From 8992cb1d0d07edc33d274f6d7924ecdf6f83d994 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Thu, 5 Sep 2013 17:57:22 +0100 Subject: making act segmenter --- ffmpeg/libavcodec/012v.c | 153 + ffmpeg/libavcodec/4xm.c | 995 ++ ffmpeg/libavcodec/8bps.c | 190 + ffmpeg/libavcodec/8svx.c | 216 + ffmpeg/libavcodec/Makefile | 862 ++ ffmpeg/libavcodec/a64colors.h | 52 + ffmpeg/libavcodec/a64multienc.c | 423 + ffmpeg/libavcodec/a64tables.h | 150 + ffmpeg/libavcodec/aac.h | 333 + ffmpeg/libavcodec/aac_ac3_parser.c | 104 + ffmpeg/libavcodec/aac_ac3_parser.h | 66 + ffmpeg/libavcodec/aac_adtstoasc_bsf.c | 118 + ffmpeg/libavcodec/aac_parser.c | 69 + ffmpeg/libavcodec/aac_tablegen.c | 37 + ffmpeg/libavcodec/aac_tablegen.h | 42 + ffmpeg/libavcodec/aac_tablegen_decl.h | 36 + ffmpeg/libavcodec/aacadtsdec.c | 70 + ffmpeg/libavcodec/aacadtsdec.h | 54 + ffmpeg/libavcodec/aaccoder.c | 1140 +++ ffmpeg/libavcodec/aacdec.c | 3060 ++++++ ffmpeg/libavcodec/aacdectab.h | 104 + ffmpeg/libavcodec/aacenc.c | 827 ++ ffmpeg/libavcodec/aacenc.h | 90 + ffmpeg/libavcodec/aacps.c | 968 ++ ffmpeg/libavcodec/aacps.h | 84 + ffmpeg/libavcodec/aacps_tablegen.c | 93 + ffmpeg/libavcodec/aacps_tablegen.h | 215 + ffmpeg/libavcodec/aacpsdata.c | 163 + ffmpeg/libavcodec/aacpsdsp.c | 216 + ffmpeg/libavcodec/aacpsdsp.h | 54 + ffmpeg/libavcodec/aacpsy.c | 940 ++ ffmpeg/libavcodec/aacpsy.h | 50 + ffmpeg/libavcodec/aacsbr.c | 1762 ++++ ffmpeg/libavcodec/aacsbr.h | 51 + ffmpeg/libavcodec/aacsbrdata.h | 616 ++ ffmpeg/libavcodec/aactab.c | 1207 +++ ffmpeg/libavcodec/aactab.h | 77 + ffmpeg/libavcodec/aandcttab.c | 47 + ffmpeg/libavcodec/aandcttab.h | 32 + ffmpeg/libavcodec/aasc.c | 164 + ffmpeg/libavcodec/ac3.c | 231 + ffmpeg/libavcodec/ac3.h | 181 + ffmpeg/libavcodec/ac3_parser.c | 194 + ffmpeg/libavcodec/ac3_parser.h | 41 + ffmpeg/libavcodec/ac3dec.c | 1488 +++ ffmpeg/libavcodec/ac3dec.h | 241 + ffmpeg/libavcodec/ac3dec_data.c | 60 + ffmpeg/libavcodec/ac3dec_data.h | 32 + ffmpeg/libavcodec/ac3dsp.c | 263 + ffmpeg/libavcodec/ac3dsp.h | 144 + ffmpeg/libavcodec/ac3enc.c | 2491 +++++ ffmpeg/libavcodec/ac3enc.h | 308 + ffmpeg/libavcodec/ac3enc_fixed.c | 169 + ffmpeg/libavcodec/ac3enc_float.c | 168 + ffmpeg/libavcodec/ac3enc_opts_template.c | 80 + ffmpeg/libavcodec/ac3enc_template.c | 447 + ffmpeg/libavcodec/ac3tab.c | 314 + ffmpeg/libavcodec/ac3tab.h | 72 + ffmpeg/libavcodec/acelp_filters.c | 155 + ffmpeg/libavcodec/acelp_filters.h | 153 + ffmpeg/libavcodec/acelp_pitch_delay.c | 189 + ffmpeg/libavcodec/acelp_pitch_delay.h | 252 + ffmpeg/libavcodec/acelp_vectors.c | 272 + ffmpeg/libavcodec/acelp_vectors.h | 288 + ffmpeg/libavcodec/adpcm.c | 1432 +++ ffmpeg/libavcodec/adpcm.h | 48 + ffmpeg/libavcodec/adpcm_data.c | 91 + ffmpeg/libavcodec/adpcm_data.h | 41 + ffmpeg/libavcodec/adpcmenc.c | 725 ++ ffmpeg/libavcodec/adx.c | 87 + ffmpeg/libavcodec/adx.h | 80 + ffmpeg/libavcodec/adx_parser.c | 96 + ffmpeg/libavcodec/adxdec.c | 187 + ffmpeg/libavcodec/adxenc.c | 169 + ffmpeg/libavcodec/alac.c | 628 ++ ffmpeg/libavcodec/alac_data.c | 56 + ffmpeg/libavcodec/alac_data.h | 46 + ffmpeg/libavcodec/alacenc.c | 656 ++ ffmpeg/libavcodec/allcodecs.c | 553 + ffmpeg/libavcodec/alpha/Makefile | 9 + ffmpeg/libavcodec/alpha/asm.h | 186 + ffmpeg/libavcodec/alpha/dsputil_alpha.c | 157 + ffmpeg/libavcodec/alpha/dsputil_alpha.h | 49 + ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S | 178 + ffmpeg/libavcodec/alpha/hpeldsp_alpha.c | 212 + ffmpeg/libavcodec/alpha/hpeldsp_alpha.h | 27 + ffmpeg/libavcodec/alpha/hpeldsp_alpha_asm.S | 135 + ffmpeg/libavcodec/alpha/motion_est_alpha.c | 345 + ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S | 179 + ffmpeg/libavcodec/alpha/mpegvideo_alpha.c | 110 + ffmpeg/libavcodec/alpha/regdef.h | 66 + ffmpeg/libavcodec/alpha/simple_idct_alpha.c | 303 + ffmpeg/libavcodec/alsdec.c | 1786 ++++ ffmpeg/libavcodec/amr.h | 70 + ffmpeg/libavcodec/amrnbdata.h | 1671 ++++ ffmpeg/libavcodec/amrnbdec.c | 1094 ++ ffmpeg/libavcodec/amrwbdata.h | 1890 ++++ ffmpeg/libavcodec/amrwbdec.c | 1279 +++ ffmpeg/libavcodec/anm.c | 200 + ffmpeg/libavcodec/ansi.c | 473 + ffmpeg/libavcodec/apedec.c | 1145 +++ ffmpeg/libavcodec/arm/Makefile | 116 + ffmpeg/libavcodec/arm/aac.h | 143 + ffmpeg/libavcodec/arm/aacpsdsp_init_arm.c | 57 + ffmpeg/libavcodec/arm/aacpsdsp_neon.S | 272 + ffmpeg/libavcodec/arm/ac3dsp_arm.S | 36 + ffmpeg/libavcodec/arm/ac3dsp_armv6.S | 84 + ffmpeg/libavcodec/arm/ac3dsp_init_arm.c | 70 + ffmpeg/libavcodec/arm/ac3dsp_neon.S | 154 + ffmpeg/libavcodec/arm/asm-offsets.h | 39 + ffmpeg/libavcodec/arm/dca.h | 105 + ffmpeg/libavcodec/arm/dcadsp_init_arm.c | 36 + ffmpeg/libavcodec/arm/dcadsp_neon.S | 61 + ffmpeg/libavcodec/arm/dsputil_arm.S | 125 + ffmpeg/libavcodec/arm/dsputil_arm.h | 32 + ffmpeg/libavcodec/arm/dsputil_armv6.S | 381 + ffmpeg/libavcodec/arm/dsputil_init_arm.c | 86 + ffmpeg/libavcodec/arm/dsputil_init_armv5te.c | 37 + ffmpeg/libavcodec/arm/dsputil_init_armv6.c | 85 + ffmpeg/libavcodec/arm/dsputil_init_neon.c | 81 + ffmpeg/libavcodec/arm/dsputil_neon.S | 209 + ffmpeg/libavcodec/arm/fft_fixed_init_arm.c | 48 + ffmpeg/libavcodec/arm/fft_fixed_neon.S | 261 + ffmpeg/libavcodec/arm/fft_init_arm.c | 77 + ffmpeg/libavcodec/arm/fft_neon.S | 375 + ffmpeg/libavcodec/arm/flacdsp_arm.S | 146 + ffmpeg/libavcodec/arm/flacdsp_init_arm.c | 32 + ffmpeg/libavcodec/arm/fmtconvert_init_arm.c | 52 + ffmpeg/libavcodec/arm/fmtconvert_neon.S | 392 + ffmpeg/libavcodec/arm/fmtconvert_vfp.S | 78 + ffmpeg/libavcodec/arm/h264chroma_init_arm.c | 51 + ffmpeg/libavcodec/arm/h264cmc_neon.S | 400 + ffmpeg/libavcodec/arm/h264dsp_init_arm.c | 111 + ffmpeg/libavcodec/arm/h264dsp_neon.S | 541 + ffmpeg/libavcodec/arm/h264idct_neon.S | 413 + ffmpeg/libavcodec/arm/h264pred_init_arm.c | 92 + ffmpeg/libavcodec/arm/h264pred_neon.S | 359 + ffmpeg/libavcodec/arm/h264qpel_init_arm.c | 171 + ffmpeg/libavcodec/arm/h264qpel_neon.S | 955 ++ ffmpeg/libavcodec/arm/hpeldsp_arm.S | 611 ++ ffmpeg/libavcodec/arm/hpeldsp_arm.h | 29 + ffmpeg/libavcodec/arm/hpeldsp_armv6.S | 259 + ffmpeg/libavcodec/arm/hpeldsp_init_arm.c | 68 + ffmpeg/libavcodec/arm/hpeldsp_init_armv6.c | 66 + ffmpeg/libavcodec/arm/hpeldsp_init_neon.c | 86 + ffmpeg/libavcodec/arm/hpeldsp_neon.S | 410 + ffmpeg/libavcodec/arm/int_neon.S | 92 + ffmpeg/libavcodec/arm/jrevdct_arm.S | 383 + ffmpeg/libavcodec/arm/mathops.h | 108 + ffmpeg/libavcodec/arm/mdct_fixed_neon.S | 193 + ffmpeg/libavcodec/arm/mdct_neon.S | 301 + ffmpeg/libavcodec/arm/mpegaudiodsp_fixed_armv6.S | 143 + ffmpeg/libavcodec/arm/mpegaudiodsp_init_arm.c | 38 + ffmpeg/libavcodec/arm/mpegvideo_arm.c | 52 + ffmpeg/libavcodec/arm/mpegvideo_arm.h | 26 + ffmpeg/libavcodec/arm/mpegvideo_armv5te.c | 102 + ffmpeg/libavcodec/arm/mpegvideo_armv5te_s.S | 114 + ffmpeg/libavcodec/arm/mpegvideo_neon.S | 107 + ffmpeg/libavcodec/arm/neon.S | 59 + ffmpeg/libavcodec/arm/rdft_neon.S | 150 + ffmpeg/libavcodec/arm/rv34dsp_init_arm.c | 46 + ffmpeg/libavcodec/arm/rv34dsp_neon.S | 156 + ffmpeg/libavcodec/arm/rv40dsp_init_arm.c | 148 + ffmpeg/libavcodec/arm/rv40dsp_neon.S | 920 ++ ffmpeg/libavcodec/arm/sbrdsp_init_arm.c | 73 + ffmpeg/libavcodec/arm/sbrdsp_neon.S | 411 + ffmpeg/libavcodec/arm/simple_idct_arm.S | 479 + ffmpeg/libavcodec/arm/simple_idct_armv5te.S | 620 ++ ffmpeg/libavcodec/arm/simple_idct_armv6.S | 425 + ffmpeg/libavcodec/arm/simple_idct_neon.S | 375 + ffmpeg/libavcodec/arm/synth_filter_neon.S | 115 + ffmpeg/libavcodec/arm/videodsp_arm.h | 29 + ffmpeg/libavcodec/arm/videodsp_armv5te.S | 31 + ffmpeg/libavcodec/arm/videodsp_init_arm.c | 30 + ffmpeg/libavcodec/arm/videodsp_init_armv5te.c | 33 + ffmpeg/libavcodec/arm/vorbisdsp_init_arm.c | 37 + ffmpeg/libavcodec/arm/vorbisdsp_neon.S | 83 + ffmpeg/libavcodec/arm/vp3dsp_init_arm.c | 45 + ffmpeg/libavcodec/arm/vp3dsp_neon.S | 395 + ffmpeg/libavcodec/arm/vp56_arith.h | 121 + ffmpeg/libavcodec/arm/vp56dsp_init_arm.c | 39 + ffmpeg/libavcodec/arm/vp56dsp_neon.S | 121 + ffmpeg/libavcodec/arm/vp8.h | 35 + ffmpeg/libavcodec/arm/vp8_armv6.S | 248 + ffmpeg/libavcodec/arm/vp8dsp.h | 78 + ffmpeg/libavcodec/arm/vp8dsp_armv6.S | 1634 +++ ffmpeg/libavcodec/arm/vp8dsp_init_arm.c | 34 + ffmpeg/libavcodec/arm/vp8dsp_init_armv6.c | 120 + ffmpeg/libavcodec/arm/vp8dsp_init_neon.c | 116 + ffmpeg/libavcodec/arm/vp8dsp_neon.S | 1867 ++++ ffmpeg/libavcodec/ass.c | 107 + ffmpeg/libavcodec/ass.h | 91 + ffmpeg/libavcodec/ass_split.c | 476 + ffmpeg/libavcodec/ass_split.h | 172 + ffmpeg/libavcodec/assdec.c | 82 + ffmpeg/libavcodec/assenc.c | 72 + ffmpeg/libavcodec/asv.c | 94 + ffmpeg/libavcodec/asv.h | 66 + ffmpeg/libavcodec/asvdec.c | 334 + ffmpeg/libavcodec/asvenc.c | 288 + ffmpeg/libavcodec/atrac.c | 119 + ffmpeg/libavcodec/atrac.h | 36 + ffmpeg/libavcodec/atrac1.c | 390 + ffmpeg/libavcodec/atrac1data.h | 64 + ffmpeg/libavcodec/atrac3.c | 1015 ++ ffmpeg/libavcodec/atrac3data.h | 141 + ffmpeg/libavcodec/audio_frame_queue.c | 112 + ffmpeg/libavcodec/audio_frame_queue.h | 83 + ffmpeg/libavcodec/audioconvert.c | 116 + ffmpeg/libavcodec/audioconvert.h | 70 + ffmpeg/libavcodec/aura.c | 108 + ffmpeg/libavcodec/avcodec.h | 4705 +++++++++ ffmpeg/libavcodec/avfft.c | 144 + ffmpeg/libavcodec/avfft.h | 116 + ffmpeg/libavcodec/avpacket.c | 400 + ffmpeg/libavcodec/avpicture.c | 78 + ffmpeg/libavcodec/avr32/mathops.h | 101 + ffmpeg/libavcodec/avrndec.c | 132 + ffmpeg/libavcodec/avs.c | 186 + ffmpeg/libavcodec/avuidec.c | 130 + ffmpeg/libavcodec/avuienc.c | 112 + ffmpeg/libavcodec/bethsoftvideo.c | 162 + ffmpeg/libavcodec/bethsoftvideo.h | 36 + ffmpeg/libavcodec/bfi.c | 186 + ffmpeg/libavcodec/bfin/Makefile | 10 + ffmpeg/libavcodec/bfin/config_bfin.h | 65 + ffmpeg/libavcodec/bfin/dsputil_bfin.c | 173 + ffmpeg/libavcodec/bfin/dsputil_bfin.h | 95 + ffmpeg/libavcodec/bfin/fdct_bfin.S | 332 + ffmpeg/libavcodec/bfin/hpel_pixels_bfin.S | 379 + ffmpeg/libavcodec/bfin/hpeldsp_bfin.c | 119 + ffmpeg/libavcodec/bfin/hpeldsp_bfin.h | 50 + ffmpeg/libavcodec/bfin/idct_bfin.S | 304 + ffmpeg/libavcodec/bfin/mathops.h | 44 + ffmpeg/libavcodec/bfin/mpegvideo_bfin.c | 152 + ffmpeg/libavcodec/bfin/pixels_bfin.S | 381 + ffmpeg/libavcodec/bfin/vp3_bfin.c | 60 + ffmpeg/libavcodec/bfin/vp3_bfin.h | 27 + ffmpeg/libavcodec/bfin/vp3_idct_bfin.S | 280 + ffmpeg/libavcodec/bgmc.c | 558 ++ ffmpeg/libavcodec/bgmc.h | 56 + ffmpeg/libavcodec/bink.c | 1344 +++ ffmpeg/libavcodec/binkaudio.c | 359 + ffmpeg/libavcodec/binkdata.h | 655 ++ ffmpeg/libavcodec/binkdsp.c | 136 + ffmpeg/libavcodec/binkdsp.h | 40 + ffmpeg/libavcodec/bintext.c | 258 + ffmpeg/libavcodec/bintext.h | 37 + ffmpeg/libavcodec/bit_depth_template.c | 92 + ffmpeg/libavcodec/bitstream.c | 339 + ffmpeg/libavcodec/bitstream_filter.c | 68 + ffmpeg/libavcodec/bmp.c | 338 + ffmpeg/libavcodec/bmp.h | 38 + ffmpeg/libavcodec/bmp_parser.c | 91 + ffmpeg/libavcodec/bmpenc.c | 183 + ffmpeg/libavcodec/bmv.c | 360 + ffmpeg/libavcodec/brender_pix.c | 219 + ffmpeg/libavcodec/bytestream.h | 345 + ffmpeg/libavcodec/c93.c | 256 + ffmpeg/libavcodec/cabac.c | 319 + ffmpeg/libavcodec/cabac.h | 56 + ffmpeg/libavcodec/cabac_functions.h | 162 + ffmpeg/libavcodec/cavs.c | 790 ++ ffmpeg/libavcodec/cavs.h | 275 + ffmpeg/libavcodec/cavs_parser.c | 106 + ffmpeg/libavcodec/cavsdata.c | 62 + ffmpeg/libavcodec/cavsdata.h | 67 + ffmpeg/libavcodec/cavsdec.c | 1226 +++ ffmpeg/libavcodec/cavsdsp.c | 566 ++ ffmpeg/libavcodec/cavsdsp.h | 42 + ffmpeg/libavcodec/cbrt_tablegen.c | 37 + ffmpeg/libavcodec/cbrt_tablegen.h | 51 + ffmpeg/libavcodec/cdgraphics.c | 379 + ffmpeg/libavcodec/cdxl.c | 303 + ffmpeg/libavcodec/celp_filters.c | 219 + ffmpeg/libavcodec/celp_filters.h | 169 + ffmpeg/libavcodec/celp_math.c | 126 + ffmpeg/libavcodec/celp_math.h | 97 + ffmpeg/libavcodec/cga_data.c | 55 + ffmpeg/libavcodec/cga_data.h | 47 + ffmpeg/libavcodec/chomp_bsf.c | 47 + ffmpeg/libavcodec/cinepak.c | 488 + ffmpeg/libavcodec/cljr.c | 190 + ffmpeg/libavcodec/cllc.c | 398 + ffmpeg/libavcodec/cngdec.c | 171 + ffmpeg/libavcodec/cngenc.c | 116 + ffmpeg/libavcodec/codec_desc.c | 2565 +++++ ffmpeg/libavcodec/cook.c | 1292 +++ ffmpeg/libavcodec/cook_parser.c | 59 + ffmpeg/libavcodec/cookdata.h | 580 ++ ffmpeg/libavcodec/copy_block.h | 94 + ffmpeg/libavcodec/cos_tablegen.c | 73 + ffmpeg/libavcodec/cpia.c | 233 + ffmpeg/libavcodec/crystalhd.c | 1223 +++ ffmpeg/libavcodec/cscd.c | 170 + ffmpeg/libavcodec/cyuv.c | 202 + ffmpeg/libavcodec/dca.c | 33 + ffmpeg/libavcodec/dca.h | 42 + ffmpeg/libavcodec/dca_parser.c | 208 + ffmpeg/libavcodec/dca_parser.h | 36 + ffmpeg/libavcodec/dcadata.h | 7664 ++++++++++++++ ffmpeg/libavcodec/dcadec.c | 2525 +++++ ffmpeg/libavcodec/dcadsp.c | 51 + ffmpeg/libavcodec/dcadsp.h | 30 + ffmpeg/libavcodec/dcaenc.c | 602 ++ ffmpeg/libavcodec/dcaenc.h | 546 + ffmpeg/libavcodec/dcahuff.h | 1076 ++ ffmpeg/libavcodec/dct-test.c | 576 ++ ffmpeg/libavcodec/dct.c | 222 + ffmpeg/libavcodec/dct.h | 70 + ffmpeg/libavcodec/dct32.c | 276 + ffmpeg/libavcodec/dct32.h | 25 + ffmpeg/libavcodec/dct32_fixed.c | 20 + ffmpeg/libavcodec/dct32_float.c | 20 + ffmpeg/libavcodec/dctref.c | 123 + ffmpeg/libavcodec/dctref.h | 29 + ffmpeg/libavcodec/dfa.c | 390 + ffmpeg/libavcodec/dirac.c | 334 + ffmpeg/libavcodec/dirac.h | 60 + ffmpeg/libavcodec/dirac_arith.c | 116 + ffmpeg/libavcodec/dirac_arith.h | 190 + ffmpeg/libavcodec/dirac_dwt.c | 585 ++ ffmpeg/libavcodec/dirac_dwt.h | 126 + ffmpeg/libavcodec/dirac_parser.c | 260 + ffmpeg/libavcodec/diracdec.c | 1938 ++++ ffmpeg/libavcodec/diracdsp.c | 201 + ffmpeg/libavcodec/diracdsp.h | 67 + ffmpeg/libavcodec/dnxhd_parser.c | 116 + ffmpeg/libavcodec/dnxhddata.c | 1082 ++ ffmpeg/libavcodec/dnxhddata.h | 57 + ffmpeg/libavcodec/dnxhddec.c | 427 + ffmpeg/libavcodec/dnxhdenc.c | 1054 ++ ffmpeg/libavcodec/dnxhdenc.h | 98 + ffmpeg/libavcodec/dpcm.c | 343 + ffmpeg/libavcodec/dpx.c | 266 + ffmpeg/libavcodec/dpxenc.c | 274 + ffmpeg/libavcodec/dsicinav.c | 409 + ffmpeg/libavcodec/dsputil.c | 2959 ++++++ ffmpeg/libavcodec/dsputil.h | 336 + ffmpeg/libavcodec/dsputil_template.c | 260 + ffmpeg/libavcodec/dump_extradata_bsf.c | 53 + ffmpeg/libavcodec/dv.c | 1003 ++ ffmpeg/libavcodec/dv_profile.c | 360 + ffmpeg/libavcodec/dv_profile.h | 78 + ffmpeg/libavcodec/dv_tablegen.c | 47 + ffmpeg/libavcodec/dv_tablegen.h | 97 + ffmpeg/libavcodec/dv_vlc_data.h | 259 + ffmpeg/libavcodec/dvbsub.c | 464 + ffmpeg/libavcodec/dvbsub_parser.c | 179 + ffmpeg/libavcodec/dvbsubdec.c | 1546 +++ ffmpeg/libavcodec/dvd_nav_parser.c | 116 + ffmpeg/libavcodec/dvdata.c | 122 + ffmpeg/libavcodec/dvdata.h | 124 + ffmpeg/libavcodec/dvdec.c | 382 + ffmpeg/libavcodec/dvdsub_parser.c | 88 + ffmpeg/libavcodec/dvdsubdec.c | 611 ++ ffmpeg/libavcodec/dvdsubenc.c | 443 + ffmpeg/libavcodec/dxa.c | 331 + ffmpeg/libavcodec/dxtory.c | 92 + ffmpeg/libavcodec/dxva2.c | 150 + ffmpeg/libavcodec/dxva2.h | 95 + ffmpeg/libavcodec/dxva2_h264.c | 452 + ffmpeg/libavcodec/dxva2_internal.h | 56 + ffmpeg/libavcodec/dxva2_mpeg2.c | 276 + ffmpeg/libavcodec/dxva2_vc1.c | 297 + ffmpeg/libavcodec/eac3_data.c | 1134 +++ ffmpeg/libavcodec/eac3_data.h | 36 + ffmpeg/libavcodec/eac3dec.c | 607 ++ ffmpeg/libavcodec/eac3enc.c | 268 + ffmpeg/libavcodec/eac3enc.h | 54 + ffmpeg/libavcodec/eacmv.c | 236 + ffmpeg/libavcodec/eaidct.c | 88 + ffmpeg/libavcodec/eaidct.h | 26 + ffmpeg/libavcodec/eamad.c | 327 + ffmpeg/libavcodec/eatgq.c | 252 + ffmpeg/libavcodec/eatgv.c | 358 + ffmpeg/libavcodec/eatqi.c | 158 + ffmpeg/libavcodec/elbg.c | 438 + ffmpeg/libavcodec/elbg.h | 55 + ffmpeg/libavcodec/error_resilience.c | 1275 +++ ffmpeg/libavcodec/error_resilience.h | 79 + ffmpeg/libavcodec/escape124.c | 379 + ffmpeg/libavcodec/escape130.c | 319 + ffmpeg/libavcodec/evrcdata.h | 1499 +++ ffmpeg/libavcodec/evrcdec.c | 917 ++ ffmpeg/libavcodec/exr.c | 813 ++ ffmpeg/libavcodec/faandct.c | 228 + ffmpeg/libavcodec/faandct.h | 37 + ffmpeg/libavcodec/faanidct.c | 169 + ffmpeg/libavcodec/faanidct.h | 31 + ffmpeg/libavcodec/faxcompr.c | 333 + ffmpeg/libavcodec/faxcompr.h | 46 + ffmpeg/libavcodec/fft-fixed-test.c | 20 + ffmpeg/libavcodec/fft-internal.h | 75 + ffmpeg/libavcodec/fft-test.c | 495 + ffmpeg/libavcodec/fft.c | 353 + ffmpeg/libavcodec/fft.h | 153 + ffmpeg/libavcodec/fft_fixed.c | 20 + ffmpeg/libavcodec/fft_float.c | 20 + ffmpeg/libavcodec/ffv1.c | 221 + ffmpeg/libavcodec/ffv1.h | 216 + ffmpeg/libavcodec/ffv1dec.c | 858 ++ ffmpeg/libavcodec/ffv1enc.c | 1169 +++ ffmpeg/libavcodec/ffwavesynth.c | 484 + ffmpeg/libavcodec/flac.c | 246 + ffmpeg/libavcodec/flac.h | 143 + ffmpeg/libavcodec/flac_parser.c | 692 ++ ffmpeg/libavcodec/flacdata.c | 33 + ffmpeg/libavcodec/flacdata.h | 31 + ffmpeg/libavcodec/flacdec.c | 592 ++ ffmpeg/libavcodec/flacdsp.c | 131 + ffmpeg/libavcodec/flacdsp.h | 37 + ffmpeg/libavcodec/flacdsp_lpc_template.c | 141 + ffmpeg/libavcodec/flacdsp_template.c | 103 + ffmpeg/libavcodec/flacenc.c | 1358 +++ ffmpeg/libavcodec/flashsv.c | 551 + ffmpeg/libavcodec/flashsv2enc.c | 931 ++ ffmpeg/libavcodec/flashsvenc.c | 288 + ffmpeg/libavcodec/flicvideo.c | 813 ++ ffmpeg/libavcodec/flv.h | 33 + ffmpeg/libavcodec/flvdec.c | 134 + ffmpeg/libavcodec/flvenc.c | 100 + ffmpeg/libavcodec/fmtconvert.c | 121 + ffmpeg/libavcodec/fmtconvert.h | 101 + ffmpeg/libavcodec/frame_thread_encoder.c | 270 + ffmpeg/libavcodec/frame_thread_encoder.h | 26 + ffmpeg/libavcodec/fraps.c | 315 + ffmpeg/libavcodec/frwu.c | 128 + ffmpeg/libavcodec/g722.c | 171 + ffmpeg/libavcodec/g722.h | 77 + ffmpeg/libavcodec/g722dec.c | 149 + ffmpeg/libavcodec/g722enc.c | 394 + ffmpeg/libavcodec/g723_1.c | 2478 +++++ ffmpeg/libavcodec/g723_1_data.h | 1329 +++ ffmpeg/libavcodec/g726.c | 468 + ffmpeg/libavcodec/g729.h | 29 + ffmpeg/libavcodec/g729data.h | 382 + ffmpeg/libavcodec/g729dec.c | 730 ++ ffmpeg/libavcodec/g729postfilter.c | 610 ++ ffmpeg/libavcodec/g729postfilter.h | 116 + ffmpeg/libavcodec/get_bits.h | 631 ++ ffmpeg/libavcodec/gif.c | 205 + ffmpeg/libavcodec/gif.h | 47 + ffmpeg/libavcodec/gifdec.c | 545 + ffmpeg/libavcodec/golomb-test.c | 99 + ffmpeg/libavcodec/golomb.c | 173 + ffmpeg/libavcodec/golomb.h | 557 ++ ffmpeg/libavcodec/gsm.h | 31 + ffmpeg/libavcodec/gsm_parser.c | 92 + ffmpeg/libavcodec/gsmdec.c | 128 + ffmpeg/libavcodec/gsmdec_data.c | 94 + ffmpeg/libavcodec/gsmdec_data.h | 43 + ffmpeg/libavcodec/gsmdec_template.c | 151 + ffmpeg/libavcodec/h261.c | 52 + ffmpeg/libavcodec/h261.h | 51 + ffmpeg/libavcodec/h261_parser.c | 93 + ffmpeg/libavcodec/h261data.c | 155 + ffmpeg/libavcodec/h261data.h | 42 + ffmpeg/libavcodec/h261dec.c | 664 ++ ffmpeg/libavcodec/h261enc.c | 337 + ffmpeg/libavcodec/h263.c | 384 + ffmpeg/libavcodec/h263.h | 212 + ffmpeg/libavcodec/h263_parser.c | 95 + ffmpeg/libavcodec/h263_parser.h | 29 + ffmpeg/libavcodec/h263data.h | 299 + ffmpeg/libavcodec/h263dec.c | 813 ++ ffmpeg/libavcodec/h264.c | 5034 ++++++++++ ffmpeg/libavcodec/h264.h | 977 ++ ffmpeg/libavcodec/h264_cabac.c | 2425 +++++ ffmpeg/libavcodec/h264_cavlc.c | 1162 +++ ffmpeg/libavcodec/h264_direct.c | 628 ++ ffmpeg/libavcodec/h264_loopfilter.c | 826 ++ ffmpeg/libavcodec/h264_mb_template.c | 367 + ffmpeg/libavcodec/h264_mc_template.c | 159 + ffmpeg/libavcodec/h264_mp4toannexb_bsf.c | 188 + ffmpeg/libavcodec/h264_mvpred.h | 829 ++ ffmpeg/libavcodec/h264_parser.c | 398 + ffmpeg/libavcodec/h264_ps.c | 688 ++ ffmpeg/libavcodec/h264_refs.c | 813 ++ ffmpeg/libavcodec/h264_sei.c | 251 + ffmpeg/libavcodec/h264addpx_template.c | 72 + ffmpeg/libavcodec/h264chroma.c | 54 + ffmpeg/libavcodec/h264chroma.h | 38 + ffmpeg/libavcodec/h264chroma_template.c | 142 + ffmpeg/libavcodec/h264data.h | 272 + ffmpeg/libavcodec/h264dsp.c | 153 + ffmpeg/libavcodec/h264dsp.h | 119 + ffmpeg/libavcodec/h264dsp_template.c | 328 + ffmpeg/libavcodec/h264idct.c | 48 + ffmpeg/libavcodec/h264idct.h | 44 + ffmpeg/libavcodec/h264idct_template.c | 323 + ffmpeg/libavcodec/h264pred.c | 593 ++ ffmpeg/libavcodec/h264pred.h | 119 + ffmpeg/libavcodec/h264pred_template.c | 1280 +++ ffmpeg/libavcodec/h264qpel.c | 104 + ffmpeg/libavcodec/h264qpel.h | 38 + ffmpeg/libavcodec/h264qpel_template.c | 549 + ffmpeg/libavcodec/hpel_template.c | 100 + ffmpeg/libavcodec/hpeldsp.c | 63 + ffmpeg/libavcodec/hpeldsp.h | 105 + ffmpeg/libavcodec/hpeldsp_template.c | 254 + ffmpeg/libavcodec/huffman.c | 176 + ffmpeg/libavcodec/huffman.h | 47 + ffmpeg/libavcodec/huffyuv.c | 97 + ffmpeg/libavcodec/huffyuv.h | 92 + ffmpeg/libavcodec/huffyuvdec.c | 797 ++ ffmpeg/libavcodec/huffyuvenc.c | 700 ++ ffmpeg/libavcodec/idcinvideo.c | 253 + ffmpeg/libavcodec/iff.c | 896 ++ ffmpeg/libavcodec/iirfilter.c | 352 + ffmpeg/libavcodec/iirfilter.h | 145 + ffmpeg/libavcodec/imc.c | 1025 ++ ffmpeg/libavcodec/imcdata.h | 169 + ffmpeg/libavcodec/imgconvert.c | 665 ++ ffmpeg/libavcodec/imgconvert.h | 29 + ffmpeg/libavcodec/imx_dump_header_bsf.c | 59 + ffmpeg/libavcodec/indeo2.c | 258 + ffmpeg/libavcodec/indeo2data.h | 141 + ffmpeg/libavcodec/indeo3.c | 1138 +++ ffmpeg/libavcodec/indeo3data.h | 362 + ffmpeg/libavcodec/indeo4.c | 659 ++ ffmpeg/libavcodec/indeo4data.h | 350 + ffmpeg/libavcodec/indeo5.c | 676 ++ ffmpeg/libavcodec/indeo5data.h | 162 + ffmpeg/libavcodec/intelh263dec.c | 138 + ffmpeg/libavcodec/internal.h | 230 + ffmpeg/libavcodec/interplayvideo.c | 1027 ++ ffmpeg/libavcodec/intrax8.c | 789 ++ ffmpeg/libavcodec/intrax8.h | 59 + ffmpeg/libavcodec/intrax8dsp.c | 432 + ffmpeg/libavcodec/intrax8dsp.h | 35 + ffmpeg/libavcodec/intrax8huf.h | 918 ++ ffmpeg/libavcodec/ituh263dec.c | 1157 +++ ffmpeg/libavcodec/ituh263enc.c | 837 ++ ffmpeg/libavcodec/ivi_common.c | 1375 +++ ffmpeg/libavcodec/ivi_common.h | 321 + ffmpeg/libavcodec/ivi_dsp.c | 623 ++ ffmpeg/libavcodec/ivi_dsp.h | 205 + ffmpeg/libavcodec/j2k.c | 391 + ffmpeg/libavcodec/j2k.h | 234 + ffmpeg/libavcodec/j2k_dwt.c | 386 + ffmpeg/libavcodec/j2k_dwt.h | 63 + ffmpeg/libavcodec/j2kdec.c | 1093 ++ ffmpeg/libavcodec/j2kenc.c | 1046 ++ ffmpeg/libavcodec/jacosub.h | 45 + ffmpeg/libavcodec/jacosubdec.c | 205 + ffmpeg/libavcodec/jfdctfst.c | 332 + ffmpeg/libavcodec/jfdctint.c | 25 + ffmpeg/libavcodec/jfdctint_template.c | 403 + ffmpeg/libavcodec/jpegls.c | 87 + ffmpeg/libavcodec/jpegls.h | 114 + ffmpeg/libavcodec/jpeglsdec.c | 385 + ffmpeg/libavcodec/jpeglsdec.h | 41 + ffmpeg/libavcodec/jpeglsenc.c | 409 + ffmpeg/libavcodec/jrevdct.c | 1155 +++ ffmpeg/libavcodec/jvdec.c | 220 + ffmpeg/libavcodec/kbdwin.c | 47 + ffmpeg/libavcodec/kbdwin.h | 35 + ffmpeg/libavcodec/kgv1dec.c | 185 + ffmpeg/libavcodec/kmvc.c | 442 + ffmpeg/libavcodec/lagarith.c | 714 ++ ffmpeg/libavcodec/lagarithrac.c | 59 + ffmpeg/libavcodec/lagarithrac.h | 119 + ffmpeg/libavcodec/latm_parser.c | 112 + ffmpeg/libavcodec/lcl.h | 49 + ffmpeg/libavcodec/lcldec.c | 665 ++ ffmpeg/libavcodec/lclenc.c | 197 + ffmpeg/libavcodec/libaacplus.c | 141 + ffmpeg/libavcodec/libavcodec.pc | 14 + ffmpeg/libavcodec/libavcodec.v | 33 + ffmpeg/libavcodec/libcelt_dec.c | 140 + ffmpeg/libavcodec/libfaac.c | 237 + ffmpeg/libavcodec/libfdk-aacenc.c | 411 + ffmpeg/libavcodec/libgsm.c | 254 + ffmpeg/libavcodec/libilbc.c | 197 + ffmpeg/libavcodec/libmp3lame.c | 305 + ffmpeg/libavcodec/libopencore-amr.c | 379 + ffmpeg/libavcodec/libopenjpegdec.c | 408 + ffmpeg/libavcodec/libopenjpegenc.c | 581 ++ ffmpeg/libavcodec/libopus.c | 48 + ffmpeg/libavcodec/libopus.h | 27 + ffmpeg/libavcodec/libopusdec.c | 198 + ffmpeg/libavcodec/libopusenc.c | 426 + ffmpeg/libavcodec/libschroedinger.c | 221 + ffmpeg/libavcodec/libschroedinger.h | 133 + ffmpeg/libavcodec/libschroedingerdec.c | 386 + ffmpeg/libavcodec/libschroedingerenc.c | 446 + ffmpeg/libavcodec/libspeexdec.c | 182 + ffmpeg/libavcodec/libspeexenc.c | 368 + ffmpeg/libavcodec/libstagefright.cpp | 597 ++ ffmpeg/libavcodec/libtheoraenc.c | 382 + ffmpeg/libavcodec/libtwolame.c | 196 + ffmpeg/libavcodec/libutvideo.h | 61 + ffmpeg/libavcodec/libutvideodec.cpp | 199 + ffmpeg/libavcodec/libutvideoenc.cpp | 239 + ffmpeg/libavcodec/libvo-aacenc.c | 200 + ffmpeg/libavcodec/libvo-amrwbenc.c | 152 + ffmpeg/libavcodec/libvorbisdec.c | 199 + ffmpeg/libavcodec/libvorbisenc.c | 378 + ffmpeg/libavcodec/libvpxdec.c | 149 + ffmpeg/libavcodec/libvpxenc.c | 729 ++ ffmpeg/libavcodec/libx264.c | 751 ++ ffmpeg/libavcodec/libxavs.c | 432 + ffmpeg/libavcodec/libxvid.c | 775 ++ ffmpeg/libavcodec/libxvid.h | 32 + ffmpeg/libavcodec/libxvid_rc.c | 141 + ffmpeg/libavcodec/ljpegenc.c | 236 + ffmpeg/libavcodec/loco.c | 312 + ffmpeg/libavcodec/log2_tab.c | 1 + ffmpeg/libavcodec/lpc.c | 287 + ffmpeg/libavcodec/lpc.h | 197 + ffmpeg/libavcodec/lsp.c | 235 + ffmpeg/libavcodec/lsp.h | 130 + ffmpeg/libavcodec/lzw.c | 234 + ffmpeg/libavcodec/lzw.h | 63 + ffmpeg/libavcodec/lzwenc.c | 269 + ffmpeg/libavcodec/mace.c | 304 + ffmpeg/libavcodec/mathops.h | 218 + ffmpeg/libavcodec/mathtables.c | 122 + ffmpeg/libavcodec/mdct.c | 203 + ffmpeg/libavcodec/mdct_fixed.c | 64 + ffmpeg/libavcodec/mdct_float.c | 20 + ffmpeg/libavcodec/mdec.c | 254 + ffmpeg/libavcodec/microdvddec.c | 377 + ffmpeg/libavcodec/mimic.c | 478 + ffmpeg/libavcodec/mips/Makefile | 21 + ffmpeg/libavcodec/mips/aaccoder_mips.c | 2498 +++++ ffmpeg/libavcodec/mips/aacdec_mips.c | 831 ++ ffmpeg/libavcodec/mips/aacdec_mips.h | 249 + ffmpeg/libavcodec/mips/aacpsdsp_mips.c | 459 + ffmpeg/libavcodec/mips/aacsbr_mips.c | 618 ++ ffmpeg/libavcodec/mips/aacsbr_mips.h | 493 + ffmpeg/libavcodec/mips/ac3dsp_mips.c | 412 + ffmpeg/libavcodec/mips/acelp_filters_mips.c | 216 + ffmpeg/libavcodec/mips/acelp_vectors_mips.c | 101 + ffmpeg/libavcodec/mips/amrwbdec_mips.c | 187 + ffmpeg/libavcodec/mips/amrwbdec_mips.h | 62 + ffmpeg/libavcodec/mips/celp_filters_mips.c | 288 + ffmpeg/libavcodec/mips/celp_math_mips.c | 89 + ffmpeg/libavcodec/mips/compute_antialias_fixed.h | 250 + ffmpeg/libavcodec/mips/compute_antialias_float.h | 185 + ffmpeg/libavcodec/mips/fft_init_table.c | 67 + ffmpeg/libavcodec/mips/fft_mips.c | 534 + ffmpeg/libavcodec/mips/fft_table.h | 63 + ffmpeg/libavcodec/mips/fmtconvert_mips.c | 342 + ffmpeg/libavcodec/mips/iirfilter_mips.c | 204 + ffmpeg/libavcodec/mips/lsp_mips.h | 109 + ffmpeg/libavcodec/mips/mathops.h | 82 + ffmpeg/libavcodec/mips/mpegaudiodsp_mips_fixed.c | 907 ++ ffmpeg/libavcodec/mips/mpegaudiodsp_mips_float.c | 1250 +++ ffmpeg/libavcodec/mips/sbrdsp_mips.c | 940 ++ ffmpeg/libavcodec/mjpeg.c | 145 + ffmpeg/libavcodec/mjpeg.h | 156 + ffmpeg/libavcodec/mjpeg2jpeg_bsf.c | 112 + ffmpeg/libavcodec/mjpeg_parser.c | 134 + ffmpeg/libavcodec/mjpega_dump_header_bsf.c | 94 + ffmpeg/libavcodec/mjpegbdec.c | 167 + ffmpeg/libavcodec/mjpegdec.c | 1935 ++++ ffmpeg/libavcodec/mjpegdec.h | 135 + ffmpeg/libavcodec/mjpegenc.c | 544 + ffmpeg/libavcodec/mjpegenc.h | 61 + ffmpeg/libavcodec/mlp.c | 115 + ffmpeg/libavcodec/mlp.h | 127 + ffmpeg/libavcodec/mlp_parser.c | 398 + ffmpeg/libavcodec/mlp_parser.h | 65 + ffmpeg/libavcodec/mlpdec.c | 1272 +++ ffmpeg/libavcodec/mlpdsp.c | 64 + ffmpeg/libavcodec/mlpdsp.h | 37 + ffmpeg/libavcodec/mmvideo.c | 238 + ffmpeg/libavcodec/motion-test.c | 151 + ffmpeg/libavcodec/motion_est.c | 1759 ++++ ffmpeg/libavcodec/motion_est_template.c | 1103 ++ ffmpeg/libavcodec/motionpixels.c | 343 + ffmpeg/libavcodec/motionpixels_tablegen.c | 41 + ffmpeg/libavcodec/motionpixels_tablegen.h | 91 + ffmpeg/libavcodec/movsub_bsf.c | 57 + ffmpeg/libavcodec/movtextdec.c | 116 + ffmpeg/libavcodec/movtextenc.c | 165 + ffmpeg/libavcodec/mp3_header_compress_bsf.c | 88 + ffmpeg/libavcodec/mp3_header_decompress_bsf.c | 98 + ffmpeg/libavcodec/mpc.c | 99 + ffmpeg/libavcodec/mpc.h | 77 + ffmpeg/libavcodec/mpc7.c | 343 + ffmpeg/libavcodec/mpc7data.h | 171 + ffmpeg/libavcodec/mpc8.c | 448 + ffmpeg/libavcodec/mpc8data.h | 121 + ffmpeg/libavcodec/mpc8huff.h | 578 ++ ffmpeg/libavcodec/mpcdata.h | 100 + ffmpeg/libavcodec/mpeg12.c | 2774 +++++ ffmpeg/libavcodec/mpeg12.h | 76 + ffmpeg/libavcodec/mpeg12data.c | 432 + ffmpeg/libavcodec/mpeg12data.h | 57 + ffmpeg/libavcodec/mpeg12decdata.h | 93 + ffmpeg/libavcodec/mpeg12enc.c | 1023 ++ ffmpeg/libavcodec/mpeg4audio.c | 190 + ffmpeg/libavcodec/mpeg4audio.h | 109 + ffmpeg/libavcodec/mpeg4data.h | 376 + ffmpeg/libavcodec/mpeg4video.c | 170 + ffmpeg/libavcodec/mpeg4video.h | 200 + ffmpeg/libavcodec/mpeg4video_parser.c | 154 + ffmpeg/libavcodec/mpeg4video_parser.h | 34 + ffmpeg/libavcodec/mpeg4videodec.c | 2389 +++++ ffmpeg/libavcodec/mpeg4videoenc.c | 1363 +++ ffmpeg/libavcodec/mpegaudio.c | 50 + ffmpeg/libavcodec/mpegaudio.h | 77 + ffmpeg/libavcodec/mpegaudio_parser.c | 114 + ffmpeg/libavcodec/mpegaudio_tablegen.c | 42 + ffmpeg/libavcodec/mpegaudio_tablegen.h | 72 + ffmpeg/libavcodec/mpegaudiodata.c | 146 + ffmpeg/libavcodec/mpegaudiodata.h | 44 + ffmpeg/libavcodec/mpegaudiodec.c | 2076 ++++ ffmpeg/libavcodec/mpegaudiodec_float.c | 104 + ffmpeg/libavcodec/mpegaudiodecheader.c | 146 + ffmpeg/libavcodec/mpegaudiodecheader.h | 76 + ffmpeg/libavcodec/mpegaudiodectab.h | 615 ++ ffmpeg/libavcodec/mpegaudiodsp.c | 48 + ffmpeg/libavcodec/mpegaudiodsp.h | 89 + ffmpeg/libavcodec/mpegaudiodsp_data.c | 56 + ffmpeg/libavcodec/mpegaudiodsp_fixed.c | 20 + ffmpeg/libavcodec/mpegaudiodsp_float.c | 20 + ffmpeg/libavcodec/mpegaudiodsp_template.c | 400 + ffmpeg/libavcodec/mpegaudioenc.c | 788 ++ ffmpeg/libavcodec/mpegaudiotab.h | 118 + ffmpeg/libavcodec/mpegvideo.c | 3365 +++++++ ffmpeg/libavcodec/mpegvideo.h | 968 ++ ffmpeg/libavcodec/mpegvideo_enc.c | 4311 ++++++++ ffmpeg/libavcodec/mpegvideo_motion.c | 894 ++ ffmpeg/libavcodec/mpegvideo_parser.c | 208 + ffmpeg/libavcodec/mpegvideo_xvmc.c | 331 + ffmpeg/libavcodec/mpl2dec.c | 96 + ffmpeg/libavcodec/mqc.c | 108 + ffmpeg/libavcodec/mqc.h | 75 + ffmpeg/libavcodec/mqcdec.c | 93 + ffmpeg/libavcodec/mqcenc.c | 119 + ffmpeg/libavcodec/msgsmdec.c | 38 + ffmpeg/libavcodec/msgsmdec.h | 30 + ffmpeg/libavcodec/msmpeg4.c | 1269 +++ ffmpeg/libavcodec/msmpeg4.h | 68 + ffmpeg/libavcodec/msmpeg4data.c | 2005 ++++ ffmpeg/libavcodec/msmpeg4data.h | 90 + ffmpeg/libavcodec/msmpeg4enc.c | 691 ++ ffmpeg/libavcodec/msrle.c | 164 + ffmpeg/libavcodec/msrledec.c | 266 + ffmpeg/libavcodec/msrledec.h | 39 + ffmpeg/libavcodec/mss1.c | 224 + ffmpeg/libavcodec/mss12.c | 679 ++ ffmpeg/libavcodec/mss12.h | 133 + ffmpeg/libavcodec/mss2.c | 852 ++ ffmpeg/libavcodec/mss2dsp.c | 156 + ffmpeg/libavcodec/mss2dsp.h | 50 + ffmpeg/libavcodec/mss3.c | 866 ++ ffmpeg/libavcodec/mss34dsp.c | 114 + ffmpeg/libavcodec/mss34dsp.h | 45 + ffmpeg/libavcodec/mss4.c | 677 ++ ffmpeg/libavcodec/msvideo1.c | 346 + ffmpeg/libavcodec/msvideo1enc.c | 311 + ffmpeg/libavcodec/mvcdec.c | 286 + ffmpeg/libavcodec/mxpegdec.c | 340 + ffmpeg/libavcodec/nellymoser.c | 224 + ffmpeg/libavcodec/nellymoser.h | 57 + ffmpeg/libavcodec/nellymoserdec.c | 209 + ffmpeg/libavcodec/nellymoserenc.c | 417 + ffmpeg/libavcodec/noise_bsf.c | 53 + ffmpeg/libavcodec/nuv.c | 341 + ffmpeg/libavcodec/old_codec_ids.h | 397 + ffmpeg/libavcodec/options.c | 294 + ffmpeg/libavcodec/options_table.h | 392 + ffmpeg/libavcodec/os2threads.h | 162 + ffmpeg/libavcodec/paf.c | 446 + ffmpeg/libavcodec/paf.h | 28 + ffmpeg/libavcodec/pamenc.c | 143 + ffmpeg/libavcodec/parser.c | 300 + ffmpeg/libavcodec/parser.h | 59 + ffmpeg/libavcodec/pcm-mpeg.c | 312 + ffmpeg/libavcodec/pcm.c | 625 ++ ffmpeg/libavcodec/pcm_tablegen.c | 39 + ffmpeg/libavcodec/pcm_tablegen.h | 119 + ffmpeg/libavcodec/pcx.c | 234 + ffmpeg/libavcodec/pcxenc.c | 230 + ffmpeg/libavcodec/pgssubdec.c | 549 + ffmpeg/libavcodec/pictordec.c | 262 + ffmpeg/libavcodec/png.c | 72 + ffmpeg/libavcodec/png.h | 69 + ffmpeg/libavcodec/png_parser.c | 120 + ffmpeg/libavcodec/pngdec.c | 902 ++ ffmpeg/libavcodec/pngdsp.c | 48 + ffmpeg/libavcodec/pngdsp.h | 40 + ffmpeg/libavcodec/pngenc.c | 480 + ffmpeg/libavcodec/pnm.c | 204 + ffmpeg/libavcodec/pnm.h | 39 + ffmpeg/libavcodec/pnm_parser.c | 92 + ffmpeg/libavcodec/pnmdec.c | 290 + ffmpeg/libavcodec/pnmenc.c | 186 + ffmpeg/libavcodec/ppc/Makefile | 24 + ffmpeg/libavcodec/ppc/asm.S | 133 + ffmpeg/libavcodec/ppc/dsputil_altivec.c | 963 ++ ffmpeg/libavcodec/ppc/dsputil_altivec.h | 43 + ffmpeg/libavcodec/ppc/dsputil_ppc.c | 184 + ffmpeg/libavcodec/ppc/fdct_altivec.c | 462 + ffmpeg/libavcodec/ppc/fft_altivec.c | 150 + ffmpeg/libavcodec/ppc/fft_altivec_s.S | 449 + ffmpeg/libavcodec/ppc/fmtconvert_altivec.c | 166 + ffmpeg/libavcodec/ppc/gmc_altivec.c | 130 + ffmpeg/libavcodec/ppc/h264_altivec.c | 748 ++ ffmpeg/libavcodec/ppc/h264_qpel.c | 317 + ffmpeg/libavcodec/ppc/h264_qpel_template.c | 507 + ffmpeg/libavcodec/ppc/h264chroma_init.c | 64 + ffmpeg/libavcodec/ppc/h264chroma_template.c | 289 + ffmpeg/libavcodec/ppc/hpeldsp_altivec.c | 464 + ffmpeg/libavcodec/ppc/idct_altivec.c | 216 + ffmpeg/libavcodec/ppc/int_altivec.c | 145 + ffmpeg/libavcodec/ppc/mathops.h | 79 + ffmpeg/libavcodec/ppc/mpegaudiodec_altivec.c | 130 + ffmpeg/libavcodec/ppc/mpegvideo_altivec.c | 124 + ffmpeg/libavcodec/ppc/vc1dsp_altivec.c | 347 + ffmpeg/libavcodec/ppc/videodsp_ppc.c | 36 + ffmpeg/libavcodec/ppc/vorbisdsp_altivec.c | 61 + ffmpeg/libavcodec/ppc/vp3dsp_altivec.c | 189 + ffmpeg/libavcodec/ppc/vp8dsp_altivec.c | 304 + ffmpeg/libavcodec/proresdata.c | 72 + ffmpeg/libavcodec/proresdata.h | 39 + ffmpeg/libavcodec/proresdec.h | 54 + ffmpeg/libavcodec/proresdec2.c | 595 ++ ffmpeg/libavcodec/proresdec_lgpl.c | 668 ++ ffmpeg/libavcodec/proresdsp.c | 91 + ffmpeg/libavcodec/proresdsp.h | 44 + ffmpeg/libavcodec/proresenc_anatoliy.c | 626 ++ ffmpeg/libavcodec/proresenc_kostya.c | 1077 ++ ffmpeg/libavcodec/psymodel.c | 147 + ffmpeg/libavcodec/psymodel.h | 189 + ffmpeg/libavcodec/pthread.c | 1136 +++ ffmpeg/libavcodec/ptx.c | 93 + ffmpeg/libavcodec/put_bits.h | 237 + ffmpeg/libavcodec/qcelpdata.h | 552 + ffmpeg/libavcodec/qcelpdec.c | 797 ++ ffmpeg/libavcodec/qdm2.c | 2014 ++++ ffmpeg/libavcodec/qdm2_tablegen.c | 44 + ffmpeg/libavcodec/qdm2_tablegen.h | 97 + ffmpeg/libavcodec/qdm2data.h | 531 + ffmpeg/libavcodec/qdrw.c | 151 + ffmpeg/libavcodec/qpeg.c | 352 + ffmpeg/libavcodec/qtrle.c | 526 + ffmpeg/libavcodec/qtrleenc.c | 402 + ffmpeg/libavcodec/r210dec.c | 122 + ffmpeg/libavcodec/r210enc.c | 123 + ffmpeg/libavcodec/ra144.c | 1728 ++++ ffmpeg/libavcodec/ra144.h | 85 + ffmpeg/libavcodec/ra144dec.c | 137 + ffmpeg/libavcodec/ra144enc.c | 558 ++ ffmpeg/libavcodec/ra288.c | 239 + ffmpeg/libavcodec/ra288.h | 148 + ffmpeg/libavcodec/ralf.c | 535 + ffmpeg/libavcodec/ralfdata.h | 9920 ++++++++++++++++++ ffmpeg/libavcodec/rangecoder.c | 157 + ffmpeg/libavcodec/rangecoder.h | 147 + ffmpeg/libavcodec/ratecontrol.c | 1062 ++ ffmpeg/libavcodec/ratecontrol.h | 103 + ffmpeg/libavcodec/raw.c | 208 + ffmpeg/libavcodec/raw.h | 44 + ffmpeg/libavcodec/rawdec.c | 348 + ffmpeg/libavcodec/rawenc.c | 80 + ffmpeg/libavcodec/rdft.c | 133 + ffmpeg/libavcodec/rdft.h | 74 + ffmpeg/libavcodec/realtextdec.c | 83 + ffmpeg/libavcodec/rectangle.h | 124 + ffmpeg/libavcodec/remove_extradata_bsf.c | 55 + ffmpeg/libavcodec/resample.c | 435 + ffmpeg/libavcodec/resample2.c | 319 + ffmpeg/libavcodec/rl.h | 86 + ffmpeg/libavcodec/rl2.c | 226 + ffmpeg/libavcodec/rle.c | 85 + ffmpeg/libavcodec/rle.h | 39 + ffmpeg/libavcodec/rnd_avg.h | 57 + ffmpeg/libavcodec/roqaudioenc.c | 206 + ffmpeg/libavcodec/roqvideo.c | 143 + ffmpeg/libavcodec/roqvideo.h | 93 + ffmpeg/libavcodec/roqvideodec.c | 247 + ffmpeg/libavcodec/roqvideoenc.c | 1087 ++ ffmpeg/libavcodec/rpza.c | 292 + ffmpeg/libavcodec/rtjpeg.c | 173 + ffmpeg/libavcodec/rtjpeg.h | 47 + ffmpeg/libavcodec/rv10.c | 789 ++ ffmpeg/libavcodec/rv10enc.c | 72 + ffmpeg/libavcodec/rv20enc.c | 73 + ffmpeg/libavcodec/rv30.c | 288 + ffmpeg/libavcodec/rv30data.h | 181 + ffmpeg/libavcodec/rv30dsp.c | 314 + ffmpeg/libavcodec/rv34.c | 1821 ++++ ffmpeg/libavcodec/rv34.h | 140 + ffmpeg/libavcodec/rv34_parser.c | 93 + ffmpeg/libavcodec/rv34data.h | 126 + ffmpeg/libavcodec/rv34dsp.c | 143 + ffmpeg/libavcodec/rv34dsp.h | 87 + ffmpeg/libavcodec/rv34vlc.h | 4055 ++++++++ ffmpeg/libavcodec/rv40.c | 579 ++ ffmpeg/libavcodec/rv40data.h | 101 + ffmpeg/libavcodec/rv40dsp.c | 626 ++ ffmpeg/libavcodec/rv40vlc2.h | 706 ++ ffmpeg/libavcodec/s302m.c | 161 + ffmpeg/libavcodec/s3tc.c | 97 + ffmpeg/libavcodec/s3tc.h | 55 + ffmpeg/libavcodec/samidec.c | 158 + ffmpeg/libavcodec/sanm.c | 1300 +++ ffmpeg/libavcodec/sanm_data.h | 248 + ffmpeg/libavcodec/sbr.h | 213 + ffmpeg/libavcodec/sbrdsp.c | 250 + ffmpeg/libavcodec/sbrdsp.h | 52 + ffmpeg/libavcodec/sgi.h | 36 + ffmpeg/libavcodec/sgidec.c | 243 + ffmpeg/libavcodec/sgienc.c | 228 + ffmpeg/libavcodec/sgirledec.c | 151 + ffmpeg/libavcodec/sh4/Makefile | 7 + ffmpeg/libavcodec/sh4/dsputil_align.c | 312 + ffmpeg/libavcodec/sh4/dsputil_sh4.c | 108 + ffmpeg/libavcodec/sh4/dsputil_sh4.h | 34 + ffmpeg/libavcodec/sh4/h264chroma_init.c | 132 + ffmpeg/libavcodec/sh4/hpeldsp.c | 347 + ffmpeg/libavcodec/sh4/idct_sh4.c | 210 + ffmpeg/libavcodec/sh4/qpel.c | 862 ++ ffmpeg/libavcodec/sh4/sh4.h | 44 + ffmpeg/libavcodec/shorten.c | 671 ++ ffmpeg/libavcodec/simple_idct.c | 233 + ffmpeg/libavcodec/simple_idct.h | 57 + ffmpeg/libavcodec/simple_idct_template.c | 324 + ffmpeg/libavcodec/sinewin.c | 20 + ffmpeg/libavcodec/sinewin.h | 60 + ffmpeg/libavcodec/sinewin_tablegen.c | 46 + ffmpeg/libavcodec/sinewin_tablegen.h | 67 + ffmpeg/libavcodec/sipr.c | 574 ++ ffmpeg/libavcodec/sipr.h | 109 + ffmpeg/libavcodec/sipr16k.c | 282 + ffmpeg/libavcodec/sipr16kdata.h | 533 + ffmpeg/libavcodec/siprdata.h | 263 + ffmpeg/libavcodec/smacker.c | 782 ++ ffmpeg/libavcodec/smc.c | 474 + ffmpeg/libavcodec/snow.c | 692 ++ ffmpeg/libavcodec/snow.h | 703 ++ ffmpeg/libavcodec/snow_dwt.c | 865 ++ ffmpeg/libavcodec/snow_dwt.h | 127 + ffmpeg/libavcodec/snowdata.h | 132 + ffmpeg/libavcodec/snowdec.c | 587 ++ ffmpeg/libavcodec/snowenc.c | 2112 ++++ ffmpeg/libavcodec/sonic.c | 999 ++ ffmpeg/libavcodec/sp5x.h | 238 + ffmpeg/libavcodec/sp5xdec.c | 121 + ffmpeg/libavcodec/sparc/Makefile | 4 + ffmpeg/libavcodec/sparc/dsputil_vis.c | 62 + ffmpeg/libavcodec/sparc/dsputil_vis.h | 28 + ffmpeg/libavcodec/sparc/hpeldsp_vis.c | 3537 +++++++ ffmpeg/libavcodec/sparc/simple_idct_vis.c | 531 + ffmpeg/libavcodec/sparc/vis.h | 331 + ffmpeg/libavcodec/srtdec.c | 282 + ffmpeg/libavcodec/srtenc.c | 324 + ffmpeg/libavcodec/subviewerdec.c | 83 + ffmpeg/libavcodec/sunrast.c | 217 + ffmpeg/libavcodec/sunrast.h | 56 + ffmpeg/libavcodec/sunrastenc.c | 224 + ffmpeg/libavcodec/svq1.c | 43 + ffmpeg/libavcodec/svq1.h | 59 + ffmpeg/libavcodec/svq13.c | 69 + ffmpeg/libavcodec/svq1_cb.h | 1525 +++ ffmpeg/libavcodec/svq1_vlc.h | 268 + ffmpeg/libavcodec/svq1dec.c | 821 ++ ffmpeg/libavcodec/svq1enc.c | 635 ++ ffmpeg/libavcodec/svq1enc_cb.h | 86 + ffmpeg/libavcodec/svq3.c | 1350 +++ ffmpeg/libavcodec/svq3.h | 27 + ffmpeg/libavcodec/synth_filter.c | 64 + ffmpeg/libavcodec/synth_filter.h | 37 + ffmpeg/libavcodec/tableprint.h | 111 + ffmpeg/libavcodec/tak.c | 175 + ffmpeg/libavcodec/tak.h | 165 + ffmpeg/libavcodec/tak_parser.c | 128 + ffmpeg/libavcodec/takdec.c | 938 ++ ffmpeg/libavcodec/targa.c | 307 + ffmpeg/libavcodec/targa.h | 48 + ffmpeg/libavcodec/targa_y216dec.c | 90 + ffmpeg/libavcodec/targaenc.c | 201 + ffmpeg/libavcodec/textdec.c | 188 + ffmpeg/libavcodec/thread.h | 128 + ffmpeg/libavcodec/tiertexseqv.c | 267 + ffmpeg/libavcodec/tiff.c | 1237 +++ ffmpeg/libavcodec/tiff.h | 193 + ffmpeg/libavcodec/tiff_data.c | 1870 ++++ ffmpeg/libavcodec/tiff_data.h | 92 + ffmpeg/libavcodec/tiffenc.c | 546 + ffmpeg/libavcodec/timecode.c | 150 + ffmpeg/libavcodec/timecode.h | 106 + ffmpeg/libavcodec/tmv.c | 97 + ffmpeg/libavcodec/truemotion1.c | 909 ++ ffmpeg/libavcodec/truemotion1data.h | 832 ++ ffmpeg/libavcodec/truemotion2.c | 1004 ++ ffmpeg/libavcodec/truespeech.c | 366 + ffmpeg/libavcodec/truespeech_data.h | 159 + ffmpeg/libavcodec/tscc.c | 190 + ffmpeg/libavcodec/tscc2.c | 377 + ffmpeg/libavcodec/tscc2data.h | 935 ++ ffmpeg/libavcodec/tta.c | 515 + ffmpeg/libavcodec/twinvq.c | 1185 +++ ffmpeg/libavcodec/twinvq_data.h | 11137 +++++++++++++++++++++ ffmpeg/libavcodec/txd.c | 142 + ffmpeg/libavcodec/ulti.c | 429 + ffmpeg/libavcodec/ulti_cb.h | 4124 ++++++++ ffmpeg/libavcodec/unary.h | 56 + ffmpeg/libavcodec/utils.c | 3095 ++++++ ffmpeg/libavcodec/utvideo.c | 39 + ffmpeg/libavcodec/utvideo.h | 91 + ffmpeg/libavcodec/utvideodec.c | 543 + ffmpeg/libavcodec/utvideoenc.c | 622 ++ ffmpeg/libavcodec/v210dec.c | 178 + ffmpeg/libavcodec/v210dec.h | 36 + ffmpeg/libavcodec/v210enc.c | 126 + ffmpeg/libavcodec/v210x.c | 131 + ffmpeg/libavcodec/v308dec.c | 91 + ffmpeg/libavcodec/v308enc.c | 94 + ffmpeg/libavcodec/v408dec.c | 111 + ffmpeg/libavcodec/v408enc.c | 113 + ffmpeg/libavcodec/v410dec.c | 98 + ffmpeg/libavcodec/v410enc.c | 98 + ffmpeg/libavcodec/vaapi.c | 219 + ffmpeg/libavcodec/vaapi.h | 173 + ffmpeg/libavcodec/vaapi_h264.c | 361 + ffmpeg/libavcodec/vaapi_internal.h | 72 + ffmpeg/libavcodec/vaapi_mpeg2.c | 143 + ffmpeg/libavcodec/vaapi_mpeg4.c | 169 + ffmpeg/libavcodec/vaapi_vc1.c | 356 + ffmpeg/libavcodec/vb.c | 277 + ffmpeg/libavcodec/vble.c | 213 + ffmpeg/libavcodec/vc1.c | 1666 +++ ffmpeg/libavcodec/vc1.h | 462 + ffmpeg/libavcodec/vc1_parser.c | 201 + ffmpeg/libavcodec/vc1acdata.h | 367 + ffmpeg/libavcodec/vc1data.c | 1135 +++ ffmpeg/libavcodec/vc1data.h | 208 + ffmpeg/libavcodec/vc1dec.c | 6266 ++++++++++++ ffmpeg/libavcodec/vc1dsp.c | 874 ++ ffmpeg/libavcodec/vc1dsp.h | 82 + ffmpeg/libavcodec/vcr1.c | 128 + ffmpeg/libavcodec/vda.h | 151 + ffmpeg/libavcodec/vda_h264.c | 237 + ffmpeg/libavcodec/vda_h264_dec.c | 258 + ffmpeg/libavcodec/vdpau.c | 414 + ffmpeg/libavcodec/vdpau.h | 151 + ffmpeg/libavcodec/vdpau_h264.c | 210 + ffmpeg/libavcodec/vdpau_internal.h | 60 + ffmpeg/libavcodec/vdpau_mpeg12.c | 116 + ffmpeg/libavcodec/vdpau_mpeg4.c | 110 + ffmpeg/libavcodec/vdpau_vc1.c | 128 + ffmpeg/libavcodec/version.h | 92 + ffmpeg/libavcodec/videodsp.c | 52 + ffmpeg/libavcodec/videodsp.h | 79 + ffmpeg/libavcodec/videodsp_template.c | 98 + ffmpeg/libavcodec/vima.c | 233 + ffmpeg/libavcodec/vmdav.c | 662 ++ ffmpeg/libavcodec/vmnc.c | 532 + ffmpeg/libavcodec/vorbis.c | 236 + ffmpeg/libavcodec/vorbis.h | 50 + ffmpeg/libavcodec/vorbis_data.c | 2193 ++++ ffmpeg/libavcodec/vorbis_enc_data.h | 504 + ffmpeg/libavcodec/vorbis_parser.c | 271 + ffmpeg/libavcodec/vorbis_parser.h | 68 + ffmpeg/libavcodec/vorbisdec.c | 1802 ++++ ffmpeg/libavcodec/vorbisdsp.c | 33 + ffmpeg/libavcodec/vorbisdsp.h | 37 + ffmpeg/libavcodec/vorbisenc.c | 1205 +++ ffmpeg/libavcodec/vp3.c | 2486 +++++ ffmpeg/libavcodec/vp3_parser.c | 42 + ffmpeg/libavcodec/vp3data.h | 3181 ++++++ ffmpeg/libavcodec/vp3dsp.c | 298 + ffmpeg/libavcodec/vp3dsp.h | 54 + ffmpeg/libavcodec/vp5.c | 291 + ffmpeg/libavcodec/vp56.c | 755 ++ ffmpeg/libavcodec/vp56.h | 376 + ffmpeg/libavcodec/vp56data.c | 68 + ffmpeg/libavcodec/vp56data.h | 252 + ffmpeg/libavcodec/vp56dsp.c | 94 + ffmpeg/libavcodec/vp56dsp.h | 42 + ffmpeg/libavcodec/vp56rac.c | 47 + ffmpeg/libavcodec/vp5data.h | 177 + ffmpeg/libavcodec/vp6.c | 694 ++ ffmpeg/libavcodec/vp6data.h | 310 + ffmpeg/libavcodec/vp6dsp.c | 61 + ffmpeg/libavcodec/vp8.c | 2110 ++++ ffmpeg/libavcodec/vp8.h | 275 + ffmpeg/libavcodec/vp8_parser.c | 38 + ffmpeg/libavcodec/vp8data.h | 691 ++ ffmpeg/libavcodec/vp8dsp.c | 530 + ffmpeg/libavcodec/vp8dsp.h | 96 + ffmpeg/libavcodec/vqavideo.c | 639 ++ ffmpeg/libavcodec/w32pthreads.h | 272 + ffmpeg/libavcodec/wavpack.c | 1265 +++ ffmpeg/libavcodec/webvttdec.c | 100 + ffmpeg/libavcodec/wma.c | 488 + ffmpeg/libavcodec/wma.h | 159 + ffmpeg/libavcodec/wma_common.c | 62 + ffmpeg/libavcodec/wma_common.h | 27 + ffmpeg/libavcodec/wmadata.h | 1403 +++ ffmpeg/libavcodec/wmadec.c | 974 ++ ffmpeg/libavcodec/wmaenc.c | 421 + ffmpeg/libavcodec/wmalosslessdec.c | 1300 +++ ffmpeg/libavcodec/wmaprodata.h | 604 ++ ffmpeg/libavcodec/wmaprodec.c | 1646 +++ ffmpeg/libavcodec/wmavoice.c | 2055 ++++ ffmpeg/libavcodec/wmavoice_data.h | 3259 ++++++ ffmpeg/libavcodec/wmv2.c | 176 + ffmpeg/libavcodec/wmv2.h | 59 + ffmpeg/libavcodec/wmv2dec.c | 478 + ffmpeg/libavcodec/wmv2dsp.c | 146 + ffmpeg/libavcodec/wmv2dsp.h | 33 + ffmpeg/libavcodec/wmv2enc.c | 223 + ffmpeg/libavcodec/wnv1.c | 160 + ffmpeg/libavcodec/ws-snd1.c | 181 + ffmpeg/libavcodec/x86/Makefile | 95 + ffmpeg/libavcodec/x86/ac3dsp.asm | 457 + ffmpeg/libavcodec/x86/ac3dsp_init.c | 232 + ffmpeg/libavcodec/x86/cabac.h | 229 + ffmpeg/libavcodec/x86/cavsdsp.c | 512 + ffmpeg/libavcodec/x86/constants.c | 39 + ffmpeg/libavcodec/x86/dct32.asm | 490 + ffmpeg/libavcodec/x86/deinterlace.asm | 82 + ffmpeg/libavcodec/x86/dirac_dwt.c | 202 + ffmpeg/libavcodec/x86/dirac_dwt.h | 30 + ffmpeg/libavcodec/x86/diracdsp_mmx.c | 104 + ffmpeg/libavcodec/x86/diracdsp_mmx.h | 47 + ffmpeg/libavcodec/x86/diracdsp_yasm.asm | 264 + ffmpeg/libavcodec/x86/dnxhdenc.c | 66 + ffmpeg/libavcodec/x86/dsputil.asm | 652 ++ ffmpeg/libavcodec/x86/dsputil_mmx.c | 1636 +++ ffmpeg/libavcodec/x86/dsputil_mmx.h | 113 + ffmpeg/libavcodec/x86/dsputil_qns_template.c | 101 + ffmpeg/libavcodec/x86/dsputil_rnd_template.c | 221 + ffmpeg/libavcodec/x86/dsputilenc.asm | 487 + ffmpeg/libavcodec/x86/dsputilenc_mmx.c | 1060 ++ ffmpeg/libavcodec/x86/dwt_yasm.asm | 306 + ffmpeg/libavcodec/x86/fdct.c | 586 ++ ffmpeg/libavcodec/x86/fft.asm | 1093 ++ ffmpeg/libavcodec/x86/fft.h | 41 + ffmpeg/libavcodec/x86/fft_init.c | 68 + ffmpeg/libavcodec/x86/fmtconvert.asm | 429 + ffmpeg/libavcodec/x86/fmtconvert_init.c | 148 + ffmpeg/libavcodec/x86/fpelbase.asm | 106 + ffmpeg/libavcodec/x86/h263_loopfilter.asm | 189 + ffmpeg/libavcodec/x86/h264_chromamc.asm | 678 ++ ffmpeg/libavcodec/x86/h264_chromamc_10bit.asm | 271 + ffmpeg/libavcodec/x86/h264_deblock.asm | 1083 ++ ffmpeg/libavcodec/x86/h264_deblock_10bit.asm | 923 ++ ffmpeg/libavcodec/x86/h264_i386.h | 204 + ffmpeg/libavcodec/x86/h264_idct.asm | 1073 ++ ffmpeg/libavcodec/x86/h264_idct_10bit.asm | 589 ++ ffmpeg/libavcodec/x86/h264_intrapred.asm | 2702 +++++ ffmpeg/libavcodec/x86/h264_intrapred_10bit.asm | 1199 +++ ffmpeg/libavcodec/x86/h264_intrapred_init.c | 402 + ffmpeg/libavcodec/x86/h264_qpel.c | 644 ++ ffmpeg/libavcodec/x86/h264_qpel_10bit.asm | 884 ++ ffmpeg/libavcodec/x86/h264_qpel_8bit.asm | 862 ++ ffmpeg/libavcodec/x86/h264_weight.asm | 317 + ffmpeg/libavcodec/x86/h264_weight_10bit.asm | 282 + ffmpeg/libavcodec/x86/h264chroma_init.c | 118 + ffmpeg/libavcodec/x86/h264dsp_init.c | 375 + ffmpeg/libavcodec/x86/hpeldsp.asm | 461 + ffmpeg/libavcodec/x86/hpeldsp_avg_template.c | 77 + ffmpeg/libavcodec/x86/hpeldsp_init.c | 415 + ffmpeg/libavcodec/x86/hpeldsp_rnd_template.c | 428 + ffmpeg/libavcodec/x86/idct_mmx_xvid.c | 558 ++ ffmpeg/libavcodec/x86/idct_sse2_xvid.c | 407 + ffmpeg/libavcodec/x86/idct_xvid.h | 43 + ffmpeg/libavcodec/x86/imdct36.asm | 724 ++ ffmpeg/libavcodec/x86/lpc.c | 154 + ffmpeg/libavcodec/x86/mathops.h | 130 + ffmpeg/libavcodec/x86/mlpdsp.c | 182 + ffmpeg/libavcodec/x86/motion_est.c | 473 + ffmpeg/libavcodec/x86/mpeg4qpel.asm | 560 ++ ffmpeg/libavcodec/x86/mpegaudiodec.c | 273 + ffmpeg/libavcodec/x86/mpegvideo.c | 600 ++ ffmpeg/libavcodec/x86/mpegvideoenc.c | 107 + ffmpeg/libavcodec/x86/mpegvideoenc_template.c | 364 + ffmpeg/libavcodec/x86/pngdsp.asm | 173 + ffmpeg/libavcodec/x86/pngdsp_init.c | 50 + ffmpeg/libavcodec/x86/proresdsp.asm | 326 + ffmpeg/libavcodec/x86/proresdsp_init.c | 57 + ffmpeg/libavcodec/x86/qpelbase.asm | 176 + ffmpeg/libavcodec/x86/rv34dsp.asm | 196 + ffmpeg/libavcodec/x86/rv34dsp_init.c | 45 + ffmpeg/libavcodec/x86/rv40dsp.asm | 505 + ffmpeg/libavcodec/x86/rv40dsp_init.c | 243 + ffmpeg/libavcodec/x86/sbrdsp.asm | 222 + ffmpeg/libavcodec/x86/sbrdsp_init.c | 48 + ffmpeg/libavcodec/x86/simple_idct.c | 1167 +++ ffmpeg/libavcodec/x86/snowdsp.c | 902 ++ ffmpeg/libavcodec/x86/v210-init.c | 48 + ffmpeg/libavcodec/x86/v210.asm | 88 + ffmpeg/libavcodec/x86/vc1dsp.asm | 317 + ffmpeg/libavcodec/x86/vc1dsp.h | 29 + ffmpeg/libavcodec/x86/vc1dsp_init.c | 132 + ffmpeg/libavcodec/x86/vc1dsp_mmx.c | 750 ++ ffmpeg/libavcodec/x86/videodsp.asm | 612 ++ ffmpeg/libavcodec/x86/videodsp_init.c | 128 + ffmpeg/libavcodec/x86/vorbisdsp.asm | 83 + ffmpeg/libavcodec/x86/vorbisdsp_init.c | 43 + ffmpeg/libavcodec/x86/vp3dsp.asm | 709 ++ ffmpeg/libavcodec/x86/vp3dsp_init.c | 128 + ffmpeg/libavcodec/x86/vp56_arith.h | 54 + ffmpeg/libavcodec/x86/vp56dsp.asm | 170 + ffmpeg/libavcodec/x86/vp56dsp_init.c | 48 + ffmpeg/libavcodec/x86/vp8dsp.asm | 2780 +++++ ffmpeg/libavcodec/x86/vp8dsp_init.c | 442 + ffmpeg/libavcodec/x86/w64xmmtest.c | 80 + ffmpeg/libavcodec/xan.c | 638 ++ ffmpeg/libavcodec/xbmdec.c | 127 + ffmpeg/libavcodec/xbmenc.c | 85 + ffmpeg/libavcodec/xface.c | 381 + ffmpeg/libavcodec/xface.h | 95 + ffmpeg/libavcodec/xfacedec.c | 188 + ffmpeg/libavcodec/xfaceenc.c | 238 + ffmpeg/libavcodec/xiph.c | 63 + ffmpeg/libavcodec/xiph.h | 43 + ffmpeg/libavcodec/xl.c | 139 + ffmpeg/libavcodec/xsubdec.c | 145 + ffmpeg/libavcodec/xsubenc.c | 219 + ffmpeg/libavcodec/xvmc.h | 168 + ffmpeg/libavcodec/xvmc_internal.h | 33 + ffmpeg/libavcodec/xwd.h | 41 + ffmpeg/libavcodec/xwddec.c | 247 + ffmpeg/libavcodec/xwdenc.c | 256 + ffmpeg/libavcodec/xxan.c | 444 + ffmpeg/libavcodec/y41pdec.c | 99 + ffmpeg/libavcodec/y41penc.c | 102 + ffmpeg/libavcodec/yop.c | 257 + ffmpeg/libavcodec/yuv4dec.c | 91 + ffmpeg/libavcodec/yuv4enc.c | 91 + ffmpeg/libavcodec/zerocodec.c | 146 + ffmpeg/libavcodec/zmbv.c | 635 ++ ffmpeg/libavcodec/zmbvenc.c | 348 + 1233 files changed, 493877 insertions(+) create mode 100644 ffmpeg/libavcodec/012v.c create mode 100644 ffmpeg/libavcodec/4xm.c create mode 100644 ffmpeg/libavcodec/8bps.c create mode 100644 ffmpeg/libavcodec/8svx.c create mode 100644 ffmpeg/libavcodec/Makefile create mode 100644 ffmpeg/libavcodec/a64colors.h create mode 100644 ffmpeg/libavcodec/a64multienc.c create mode 100644 ffmpeg/libavcodec/a64tables.h create mode 100644 ffmpeg/libavcodec/aac.h create mode 100644 ffmpeg/libavcodec/aac_ac3_parser.c create mode 100644 ffmpeg/libavcodec/aac_ac3_parser.h create mode 100644 ffmpeg/libavcodec/aac_adtstoasc_bsf.c create mode 100644 ffmpeg/libavcodec/aac_parser.c create mode 100644 ffmpeg/libavcodec/aac_tablegen.c create mode 100644 ffmpeg/libavcodec/aac_tablegen.h create mode 100644 ffmpeg/libavcodec/aac_tablegen_decl.h create mode 100644 ffmpeg/libavcodec/aacadtsdec.c create mode 100644 ffmpeg/libavcodec/aacadtsdec.h create mode 100644 ffmpeg/libavcodec/aaccoder.c create mode 100644 ffmpeg/libavcodec/aacdec.c create mode 100644 ffmpeg/libavcodec/aacdectab.h create mode 100644 ffmpeg/libavcodec/aacenc.c create mode 100644 ffmpeg/libavcodec/aacenc.h create mode 100644 ffmpeg/libavcodec/aacps.c create mode 100644 ffmpeg/libavcodec/aacps.h create mode 100644 ffmpeg/libavcodec/aacps_tablegen.c create mode 100644 ffmpeg/libavcodec/aacps_tablegen.h create mode 100644 ffmpeg/libavcodec/aacpsdata.c create mode 100644 ffmpeg/libavcodec/aacpsdsp.c create mode 100644 ffmpeg/libavcodec/aacpsdsp.h create mode 100644 ffmpeg/libavcodec/aacpsy.c create mode 100644 ffmpeg/libavcodec/aacpsy.h create mode 100644 ffmpeg/libavcodec/aacsbr.c create mode 100644 ffmpeg/libavcodec/aacsbr.h create mode 100644 ffmpeg/libavcodec/aacsbrdata.h create mode 100644 ffmpeg/libavcodec/aactab.c create mode 100644 ffmpeg/libavcodec/aactab.h create mode 100644 ffmpeg/libavcodec/aandcttab.c create mode 100644 ffmpeg/libavcodec/aandcttab.h create mode 100644 ffmpeg/libavcodec/aasc.c create mode 100644 ffmpeg/libavcodec/ac3.c create mode 100644 ffmpeg/libavcodec/ac3.h create mode 100644 ffmpeg/libavcodec/ac3_parser.c create mode 100644 ffmpeg/libavcodec/ac3_parser.h create mode 100644 ffmpeg/libavcodec/ac3dec.c create mode 100644 ffmpeg/libavcodec/ac3dec.h create mode 100644 ffmpeg/libavcodec/ac3dec_data.c create mode 100644 ffmpeg/libavcodec/ac3dec_data.h create mode 100644 ffmpeg/libavcodec/ac3dsp.c create mode 100644 ffmpeg/libavcodec/ac3dsp.h create mode 100644 ffmpeg/libavcodec/ac3enc.c create mode 100644 ffmpeg/libavcodec/ac3enc.h create mode 100644 ffmpeg/libavcodec/ac3enc_fixed.c create mode 100644 ffmpeg/libavcodec/ac3enc_float.c create mode 100644 ffmpeg/libavcodec/ac3enc_opts_template.c create mode 100644 ffmpeg/libavcodec/ac3enc_template.c create mode 100644 ffmpeg/libavcodec/ac3tab.c create mode 100644 ffmpeg/libavcodec/ac3tab.h create mode 100644 ffmpeg/libavcodec/acelp_filters.c create mode 100644 ffmpeg/libavcodec/acelp_filters.h create mode 100644 ffmpeg/libavcodec/acelp_pitch_delay.c create mode 100644 ffmpeg/libavcodec/acelp_pitch_delay.h create mode 100644 ffmpeg/libavcodec/acelp_vectors.c create mode 100644 ffmpeg/libavcodec/acelp_vectors.h create mode 100644 ffmpeg/libavcodec/adpcm.c create mode 100644 ffmpeg/libavcodec/adpcm.h create mode 100644 ffmpeg/libavcodec/adpcm_data.c create mode 100644 ffmpeg/libavcodec/adpcm_data.h create mode 100644 ffmpeg/libavcodec/adpcmenc.c create mode 100644 ffmpeg/libavcodec/adx.c create mode 100644 ffmpeg/libavcodec/adx.h create mode 100644 ffmpeg/libavcodec/adx_parser.c create mode 100644 ffmpeg/libavcodec/adxdec.c create mode 100644 ffmpeg/libavcodec/adxenc.c create mode 100644 ffmpeg/libavcodec/alac.c create mode 100644 ffmpeg/libavcodec/alac_data.c create mode 100644 ffmpeg/libavcodec/alac_data.h create mode 100644 ffmpeg/libavcodec/alacenc.c create mode 100644 ffmpeg/libavcodec/allcodecs.c create mode 100644 ffmpeg/libavcodec/alpha/Makefile create mode 100644 ffmpeg/libavcodec/alpha/asm.h create mode 100644 ffmpeg/libavcodec/alpha/dsputil_alpha.c create mode 100644 ffmpeg/libavcodec/alpha/dsputil_alpha.h create mode 100644 ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S create mode 100644 ffmpeg/libavcodec/alpha/hpeldsp_alpha.c create mode 100644 ffmpeg/libavcodec/alpha/hpeldsp_alpha.h create mode 100644 ffmpeg/libavcodec/alpha/hpeldsp_alpha_asm.S create mode 100644 ffmpeg/libavcodec/alpha/motion_est_alpha.c create mode 100644 ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S create mode 100644 ffmpeg/libavcodec/alpha/mpegvideo_alpha.c create mode 100644 ffmpeg/libavcodec/alpha/regdef.h create mode 100644 ffmpeg/libavcodec/alpha/simple_idct_alpha.c create mode 100644 ffmpeg/libavcodec/alsdec.c create mode 100644 ffmpeg/libavcodec/amr.h create mode 100644 ffmpeg/libavcodec/amrnbdata.h create mode 100644 ffmpeg/libavcodec/amrnbdec.c create mode 100644 ffmpeg/libavcodec/amrwbdata.h create mode 100644 ffmpeg/libavcodec/amrwbdec.c create mode 100644 ffmpeg/libavcodec/anm.c create mode 100644 ffmpeg/libavcodec/ansi.c create mode 100644 ffmpeg/libavcodec/apedec.c create mode 100644 ffmpeg/libavcodec/arm/Makefile create mode 100644 ffmpeg/libavcodec/arm/aac.h create mode 100644 ffmpeg/libavcodec/arm/aacpsdsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/aacpsdsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/ac3dsp_arm.S create mode 100644 ffmpeg/libavcodec/arm/ac3dsp_armv6.S create mode 100644 ffmpeg/libavcodec/arm/ac3dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/ac3dsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/asm-offsets.h create mode 100644 ffmpeg/libavcodec/arm/dca.h create mode 100644 ffmpeg/libavcodec/arm/dcadsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/dcadsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/dsputil_arm.S create mode 100644 ffmpeg/libavcodec/arm/dsputil_arm.h create mode 100644 ffmpeg/libavcodec/arm/dsputil_armv6.S create mode 100644 ffmpeg/libavcodec/arm/dsputil_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/dsputil_init_armv5te.c create mode 100644 ffmpeg/libavcodec/arm/dsputil_init_armv6.c create mode 100644 ffmpeg/libavcodec/arm/dsputil_init_neon.c create mode 100644 ffmpeg/libavcodec/arm/dsputil_neon.S create mode 100644 ffmpeg/libavcodec/arm/fft_fixed_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/fft_fixed_neon.S create mode 100644 ffmpeg/libavcodec/arm/fft_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/fft_neon.S create mode 100644 ffmpeg/libavcodec/arm/flacdsp_arm.S create mode 100644 ffmpeg/libavcodec/arm/flacdsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/fmtconvert_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/fmtconvert_neon.S create mode 100644 ffmpeg/libavcodec/arm/fmtconvert_vfp.S create mode 100644 ffmpeg/libavcodec/arm/h264chroma_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/h264cmc_neon.S create mode 100644 ffmpeg/libavcodec/arm/h264dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/h264dsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/h264idct_neon.S create mode 100644 ffmpeg/libavcodec/arm/h264pred_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/h264pred_neon.S create mode 100644 ffmpeg/libavcodec/arm/h264qpel_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/h264qpel_neon.S create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_arm.S create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_arm.h create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_armv6.S create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_init_armv6.c create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_init_neon.c create mode 100644 ffmpeg/libavcodec/arm/hpeldsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/int_neon.S create mode 100644 ffmpeg/libavcodec/arm/jrevdct_arm.S create mode 100644 ffmpeg/libavcodec/arm/mathops.h create mode 100644 ffmpeg/libavcodec/arm/mdct_fixed_neon.S create mode 100644 ffmpeg/libavcodec/arm/mdct_neon.S create mode 100644 ffmpeg/libavcodec/arm/mpegaudiodsp_fixed_armv6.S create mode 100644 ffmpeg/libavcodec/arm/mpegaudiodsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/mpegvideo_arm.c create mode 100644 ffmpeg/libavcodec/arm/mpegvideo_arm.h create mode 100644 ffmpeg/libavcodec/arm/mpegvideo_armv5te.c create mode 100644 ffmpeg/libavcodec/arm/mpegvideo_armv5te_s.S create mode 100644 ffmpeg/libavcodec/arm/mpegvideo_neon.S create mode 100644 ffmpeg/libavcodec/arm/neon.S create mode 100644 ffmpeg/libavcodec/arm/rdft_neon.S create mode 100644 ffmpeg/libavcodec/arm/rv34dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/rv34dsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/rv40dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/rv40dsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/sbrdsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/sbrdsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/simple_idct_arm.S create mode 100644 ffmpeg/libavcodec/arm/simple_idct_armv5te.S create mode 100644 ffmpeg/libavcodec/arm/simple_idct_armv6.S create mode 100644 ffmpeg/libavcodec/arm/simple_idct_neon.S create mode 100644 ffmpeg/libavcodec/arm/synth_filter_neon.S create mode 100644 ffmpeg/libavcodec/arm/videodsp_arm.h create mode 100644 ffmpeg/libavcodec/arm/videodsp_armv5te.S create mode 100644 ffmpeg/libavcodec/arm/videodsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/videodsp_init_armv5te.c create mode 100644 ffmpeg/libavcodec/arm/vorbisdsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/vorbisdsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/vp3dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/vp3dsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/vp56_arith.h create mode 100644 ffmpeg/libavcodec/arm/vp56dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/vp56dsp_neon.S create mode 100644 ffmpeg/libavcodec/arm/vp8.h create mode 100644 ffmpeg/libavcodec/arm/vp8_armv6.S create mode 100644 ffmpeg/libavcodec/arm/vp8dsp.h create mode 100644 ffmpeg/libavcodec/arm/vp8dsp_armv6.S create mode 100644 ffmpeg/libavcodec/arm/vp8dsp_init_arm.c create mode 100644 ffmpeg/libavcodec/arm/vp8dsp_init_armv6.c create mode 100644 ffmpeg/libavcodec/arm/vp8dsp_init_neon.c create mode 100644 ffmpeg/libavcodec/arm/vp8dsp_neon.S create mode 100644 ffmpeg/libavcodec/ass.c create mode 100644 ffmpeg/libavcodec/ass.h create mode 100644 ffmpeg/libavcodec/ass_split.c create mode 100644 ffmpeg/libavcodec/ass_split.h create mode 100644 ffmpeg/libavcodec/assdec.c create mode 100644 ffmpeg/libavcodec/assenc.c create mode 100644 ffmpeg/libavcodec/asv.c create mode 100644 ffmpeg/libavcodec/asv.h create mode 100644 ffmpeg/libavcodec/asvdec.c create mode 100644 ffmpeg/libavcodec/asvenc.c create mode 100644 ffmpeg/libavcodec/atrac.c create mode 100644 ffmpeg/libavcodec/atrac.h create mode 100644 ffmpeg/libavcodec/atrac1.c create mode 100644 ffmpeg/libavcodec/atrac1data.h create mode 100644 ffmpeg/libavcodec/atrac3.c create mode 100644 ffmpeg/libavcodec/atrac3data.h create mode 100644 ffmpeg/libavcodec/audio_frame_queue.c create mode 100644 ffmpeg/libavcodec/audio_frame_queue.h create mode 100644 ffmpeg/libavcodec/audioconvert.c create mode 100644 ffmpeg/libavcodec/audioconvert.h create mode 100644 ffmpeg/libavcodec/aura.c create mode 100644 ffmpeg/libavcodec/avcodec.h create mode 100644 ffmpeg/libavcodec/avfft.c create mode 100644 ffmpeg/libavcodec/avfft.h create mode 100644 ffmpeg/libavcodec/avpacket.c create mode 100644 ffmpeg/libavcodec/avpicture.c create mode 100644 ffmpeg/libavcodec/avr32/mathops.h create mode 100644 ffmpeg/libavcodec/avrndec.c create mode 100644 ffmpeg/libavcodec/avs.c create mode 100644 ffmpeg/libavcodec/avuidec.c create mode 100644 ffmpeg/libavcodec/avuienc.c create mode 100644 ffmpeg/libavcodec/bethsoftvideo.c create mode 100644 ffmpeg/libavcodec/bethsoftvideo.h create mode 100644 ffmpeg/libavcodec/bfi.c create mode 100644 ffmpeg/libavcodec/bfin/Makefile create mode 100644 ffmpeg/libavcodec/bfin/config_bfin.h create mode 100644 ffmpeg/libavcodec/bfin/dsputil_bfin.c create mode 100644 ffmpeg/libavcodec/bfin/dsputil_bfin.h create mode 100644 ffmpeg/libavcodec/bfin/fdct_bfin.S create mode 100644 ffmpeg/libavcodec/bfin/hpel_pixels_bfin.S create mode 100644 ffmpeg/libavcodec/bfin/hpeldsp_bfin.c create mode 100644 ffmpeg/libavcodec/bfin/hpeldsp_bfin.h create mode 100644 ffmpeg/libavcodec/bfin/idct_bfin.S create mode 100644 ffmpeg/libavcodec/bfin/mathops.h create mode 100644 ffmpeg/libavcodec/bfin/mpegvideo_bfin.c create mode 100644 ffmpeg/libavcodec/bfin/pixels_bfin.S create mode 100644 ffmpeg/libavcodec/bfin/vp3_bfin.c create mode 100644 ffmpeg/libavcodec/bfin/vp3_bfin.h create mode 100644 ffmpeg/libavcodec/bfin/vp3_idct_bfin.S create mode 100644 ffmpeg/libavcodec/bgmc.c create mode 100644 ffmpeg/libavcodec/bgmc.h create mode 100644 ffmpeg/libavcodec/bink.c create mode 100644 ffmpeg/libavcodec/binkaudio.c create mode 100644 ffmpeg/libavcodec/binkdata.h create mode 100644 ffmpeg/libavcodec/binkdsp.c create mode 100644 ffmpeg/libavcodec/binkdsp.h create mode 100644 ffmpeg/libavcodec/bintext.c create mode 100644 ffmpeg/libavcodec/bintext.h create mode 100644 ffmpeg/libavcodec/bit_depth_template.c create mode 100644 ffmpeg/libavcodec/bitstream.c create mode 100644 ffmpeg/libavcodec/bitstream_filter.c create mode 100644 ffmpeg/libavcodec/bmp.c create mode 100644 ffmpeg/libavcodec/bmp.h create mode 100644 ffmpeg/libavcodec/bmp_parser.c create mode 100644 ffmpeg/libavcodec/bmpenc.c create mode 100644 ffmpeg/libavcodec/bmv.c create mode 100644 ffmpeg/libavcodec/brender_pix.c create mode 100644 ffmpeg/libavcodec/bytestream.h create mode 100644 ffmpeg/libavcodec/c93.c create mode 100644 ffmpeg/libavcodec/cabac.c create mode 100644 ffmpeg/libavcodec/cabac.h create mode 100644 ffmpeg/libavcodec/cabac_functions.h create mode 100644 ffmpeg/libavcodec/cavs.c create mode 100644 ffmpeg/libavcodec/cavs.h create mode 100644 ffmpeg/libavcodec/cavs_parser.c create mode 100644 ffmpeg/libavcodec/cavsdata.c create mode 100644 ffmpeg/libavcodec/cavsdata.h create mode 100644 ffmpeg/libavcodec/cavsdec.c create mode 100644 ffmpeg/libavcodec/cavsdsp.c create mode 100644 ffmpeg/libavcodec/cavsdsp.h create mode 100644 ffmpeg/libavcodec/cbrt_tablegen.c create mode 100644 ffmpeg/libavcodec/cbrt_tablegen.h create mode 100644 ffmpeg/libavcodec/cdgraphics.c create mode 100644 ffmpeg/libavcodec/cdxl.c create mode 100644 ffmpeg/libavcodec/celp_filters.c create mode 100644 ffmpeg/libavcodec/celp_filters.h create mode 100644 ffmpeg/libavcodec/celp_math.c create mode 100644 ffmpeg/libavcodec/celp_math.h create mode 100644 ffmpeg/libavcodec/cga_data.c create mode 100644 ffmpeg/libavcodec/cga_data.h create mode 100644 ffmpeg/libavcodec/chomp_bsf.c create mode 100644 ffmpeg/libavcodec/cinepak.c create mode 100644 ffmpeg/libavcodec/cljr.c create mode 100644 ffmpeg/libavcodec/cllc.c create mode 100644 ffmpeg/libavcodec/cngdec.c create mode 100644 ffmpeg/libavcodec/cngenc.c create mode 100644 ffmpeg/libavcodec/codec_desc.c create mode 100644 ffmpeg/libavcodec/cook.c create mode 100644 ffmpeg/libavcodec/cook_parser.c create mode 100644 ffmpeg/libavcodec/cookdata.h create mode 100644 ffmpeg/libavcodec/copy_block.h create mode 100644 ffmpeg/libavcodec/cos_tablegen.c create mode 100644 ffmpeg/libavcodec/cpia.c create mode 100644 ffmpeg/libavcodec/crystalhd.c create mode 100644 ffmpeg/libavcodec/cscd.c create mode 100644 ffmpeg/libavcodec/cyuv.c create mode 100644 ffmpeg/libavcodec/dca.c create mode 100644 ffmpeg/libavcodec/dca.h create mode 100644 ffmpeg/libavcodec/dca_parser.c create mode 100644 ffmpeg/libavcodec/dca_parser.h create mode 100644 ffmpeg/libavcodec/dcadata.h create mode 100644 ffmpeg/libavcodec/dcadec.c create mode 100644 ffmpeg/libavcodec/dcadsp.c create mode 100644 ffmpeg/libavcodec/dcadsp.h create mode 100644 ffmpeg/libavcodec/dcaenc.c create mode 100644 ffmpeg/libavcodec/dcaenc.h create mode 100644 ffmpeg/libavcodec/dcahuff.h create mode 100644 ffmpeg/libavcodec/dct-test.c create mode 100644 ffmpeg/libavcodec/dct.c create mode 100644 ffmpeg/libavcodec/dct.h create mode 100644 ffmpeg/libavcodec/dct32.c create mode 100644 ffmpeg/libavcodec/dct32.h create mode 100644 ffmpeg/libavcodec/dct32_fixed.c create mode 100644 ffmpeg/libavcodec/dct32_float.c create mode 100644 ffmpeg/libavcodec/dctref.c create mode 100644 ffmpeg/libavcodec/dctref.h create mode 100644 ffmpeg/libavcodec/dfa.c create mode 100644 ffmpeg/libavcodec/dirac.c create mode 100644 ffmpeg/libavcodec/dirac.h create mode 100644 ffmpeg/libavcodec/dirac_arith.c create mode 100644 ffmpeg/libavcodec/dirac_arith.h create mode 100644 ffmpeg/libavcodec/dirac_dwt.c create mode 100644 ffmpeg/libavcodec/dirac_dwt.h create mode 100644 ffmpeg/libavcodec/dirac_parser.c create mode 100644 ffmpeg/libavcodec/diracdec.c create mode 100644 ffmpeg/libavcodec/diracdsp.c create mode 100644 ffmpeg/libavcodec/diracdsp.h create mode 100644 ffmpeg/libavcodec/dnxhd_parser.c create mode 100644 ffmpeg/libavcodec/dnxhddata.c create mode 100644 ffmpeg/libavcodec/dnxhddata.h create mode 100644 ffmpeg/libavcodec/dnxhddec.c create mode 100644 ffmpeg/libavcodec/dnxhdenc.c create mode 100644 ffmpeg/libavcodec/dnxhdenc.h create mode 100644 ffmpeg/libavcodec/dpcm.c create mode 100644 ffmpeg/libavcodec/dpx.c create mode 100644 ffmpeg/libavcodec/dpxenc.c create mode 100644 ffmpeg/libavcodec/dsicinav.c create mode 100644 ffmpeg/libavcodec/dsputil.c create mode 100644 ffmpeg/libavcodec/dsputil.h create mode 100644 ffmpeg/libavcodec/dsputil_template.c create mode 100644 ffmpeg/libavcodec/dump_extradata_bsf.c create mode 100644 ffmpeg/libavcodec/dv.c create mode 100644 ffmpeg/libavcodec/dv_profile.c create mode 100644 ffmpeg/libavcodec/dv_profile.h create mode 100644 ffmpeg/libavcodec/dv_tablegen.c create mode 100644 ffmpeg/libavcodec/dv_tablegen.h create mode 100644 ffmpeg/libavcodec/dv_vlc_data.h create mode 100644 ffmpeg/libavcodec/dvbsub.c create mode 100644 ffmpeg/libavcodec/dvbsub_parser.c create mode 100644 ffmpeg/libavcodec/dvbsubdec.c create mode 100644 ffmpeg/libavcodec/dvd_nav_parser.c create mode 100644 ffmpeg/libavcodec/dvdata.c create mode 100644 ffmpeg/libavcodec/dvdata.h create mode 100644 ffmpeg/libavcodec/dvdec.c create mode 100644 ffmpeg/libavcodec/dvdsub_parser.c create mode 100644 ffmpeg/libavcodec/dvdsubdec.c create mode 100644 ffmpeg/libavcodec/dvdsubenc.c create mode 100644 ffmpeg/libavcodec/dxa.c create mode 100644 ffmpeg/libavcodec/dxtory.c create mode 100644 ffmpeg/libavcodec/dxva2.c create mode 100644 ffmpeg/libavcodec/dxva2.h create mode 100644 ffmpeg/libavcodec/dxva2_h264.c create mode 100644 ffmpeg/libavcodec/dxva2_internal.h create mode 100644 ffmpeg/libavcodec/dxva2_mpeg2.c create mode 100644 ffmpeg/libavcodec/dxva2_vc1.c create mode 100644 ffmpeg/libavcodec/eac3_data.c create mode 100644 ffmpeg/libavcodec/eac3_data.h create mode 100644 ffmpeg/libavcodec/eac3dec.c create mode 100644 ffmpeg/libavcodec/eac3enc.c create mode 100644 ffmpeg/libavcodec/eac3enc.h create mode 100644 ffmpeg/libavcodec/eacmv.c create mode 100644 ffmpeg/libavcodec/eaidct.c create mode 100644 ffmpeg/libavcodec/eaidct.h create mode 100644 ffmpeg/libavcodec/eamad.c create mode 100644 ffmpeg/libavcodec/eatgq.c create mode 100644 ffmpeg/libavcodec/eatgv.c create mode 100644 ffmpeg/libavcodec/eatqi.c create mode 100644 ffmpeg/libavcodec/elbg.c create mode 100644 ffmpeg/libavcodec/elbg.h create mode 100644 ffmpeg/libavcodec/error_resilience.c create mode 100644 ffmpeg/libavcodec/error_resilience.h create mode 100644 ffmpeg/libavcodec/escape124.c create mode 100644 ffmpeg/libavcodec/escape130.c create mode 100644 ffmpeg/libavcodec/evrcdata.h create mode 100644 ffmpeg/libavcodec/evrcdec.c create mode 100644 ffmpeg/libavcodec/exr.c create mode 100644 ffmpeg/libavcodec/faandct.c create mode 100644 ffmpeg/libavcodec/faandct.h create mode 100644 ffmpeg/libavcodec/faanidct.c create mode 100644 ffmpeg/libavcodec/faanidct.h create mode 100644 ffmpeg/libavcodec/faxcompr.c create mode 100644 ffmpeg/libavcodec/faxcompr.h create mode 100644 ffmpeg/libavcodec/fft-fixed-test.c create mode 100644 ffmpeg/libavcodec/fft-internal.h create mode 100644 ffmpeg/libavcodec/fft-test.c create mode 100644 ffmpeg/libavcodec/fft.c create mode 100644 ffmpeg/libavcodec/fft.h create mode 100644 ffmpeg/libavcodec/fft_fixed.c create mode 100644 ffmpeg/libavcodec/fft_float.c create mode 100644 ffmpeg/libavcodec/ffv1.c create mode 100644 ffmpeg/libavcodec/ffv1.h create mode 100644 ffmpeg/libavcodec/ffv1dec.c create mode 100644 ffmpeg/libavcodec/ffv1enc.c create mode 100644 ffmpeg/libavcodec/ffwavesynth.c create mode 100644 ffmpeg/libavcodec/flac.c create mode 100644 ffmpeg/libavcodec/flac.h create mode 100644 ffmpeg/libavcodec/flac_parser.c create mode 100644 ffmpeg/libavcodec/flacdata.c create mode 100644 ffmpeg/libavcodec/flacdata.h create mode 100644 ffmpeg/libavcodec/flacdec.c create mode 100644 ffmpeg/libavcodec/flacdsp.c create mode 100644 ffmpeg/libavcodec/flacdsp.h create mode 100644 ffmpeg/libavcodec/flacdsp_lpc_template.c create mode 100644 ffmpeg/libavcodec/flacdsp_template.c create mode 100644 ffmpeg/libavcodec/flacenc.c create mode 100644 ffmpeg/libavcodec/flashsv.c create mode 100644 ffmpeg/libavcodec/flashsv2enc.c create mode 100644 ffmpeg/libavcodec/flashsvenc.c create mode 100644 ffmpeg/libavcodec/flicvideo.c create mode 100644 ffmpeg/libavcodec/flv.h create mode 100644 ffmpeg/libavcodec/flvdec.c create mode 100644 ffmpeg/libavcodec/flvenc.c create mode 100644 ffmpeg/libavcodec/fmtconvert.c create mode 100644 ffmpeg/libavcodec/fmtconvert.h create mode 100644 ffmpeg/libavcodec/frame_thread_encoder.c create mode 100644 ffmpeg/libavcodec/frame_thread_encoder.h create mode 100644 ffmpeg/libavcodec/fraps.c create mode 100644 ffmpeg/libavcodec/frwu.c create mode 100644 ffmpeg/libavcodec/g722.c create mode 100644 ffmpeg/libavcodec/g722.h create mode 100644 ffmpeg/libavcodec/g722dec.c create mode 100644 ffmpeg/libavcodec/g722enc.c create mode 100644 ffmpeg/libavcodec/g723_1.c create mode 100644 ffmpeg/libavcodec/g723_1_data.h create mode 100644 ffmpeg/libavcodec/g726.c create mode 100644 ffmpeg/libavcodec/g729.h create mode 100644 ffmpeg/libavcodec/g729data.h create mode 100644 ffmpeg/libavcodec/g729dec.c create mode 100644 ffmpeg/libavcodec/g729postfilter.c create mode 100644 ffmpeg/libavcodec/g729postfilter.h create mode 100644 ffmpeg/libavcodec/get_bits.h create mode 100644 ffmpeg/libavcodec/gif.c create mode 100644 ffmpeg/libavcodec/gif.h create mode 100644 ffmpeg/libavcodec/gifdec.c create mode 100644 ffmpeg/libavcodec/golomb-test.c create mode 100644 ffmpeg/libavcodec/golomb.c create mode 100644 ffmpeg/libavcodec/golomb.h create mode 100644 ffmpeg/libavcodec/gsm.h create mode 100644 ffmpeg/libavcodec/gsm_parser.c create mode 100644 ffmpeg/libavcodec/gsmdec.c create mode 100644 ffmpeg/libavcodec/gsmdec_data.c create mode 100644 ffmpeg/libavcodec/gsmdec_data.h create mode 100644 ffmpeg/libavcodec/gsmdec_template.c create mode 100644 ffmpeg/libavcodec/h261.c create mode 100644 ffmpeg/libavcodec/h261.h create mode 100644 ffmpeg/libavcodec/h261_parser.c create mode 100644 ffmpeg/libavcodec/h261data.c create mode 100644 ffmpeg/libavcodec/h261data.h create mode 100644 ffmpeg/libavcodec/h261dec.c create mode 100644 ffmpeg/libavcodec/h261enc.c create mode 100644 ffmpeg/libavcodec/h263.c create mode 100644 ffmpeg/libavcodec/h263.h create mode 100644 ffmpeg/libavcodec/h263_parser.c create mode 100644 ffmpeg/libavcodec/h263_parser.h create mode 100644 ffmpeg/libavcodec/h263data.h create mode 100644 ffmpeg/libavcodec/h263dec.c create mode 100644 ffmpeg/libavcodec/h264.c create mode 100644 ffmpeg/libavcodec/h264.h create mode 100644 ffmpeg/libavcodec/h264_cabac.c create mode 100644 ffmpeg/libavcodec/h264_cavlc.c create mode 100644 ffmpeg/libavcodec/h264_direct.c create mode 100644 ffmpeg/libavcodec/h264_loopfilter.c create mode 100644 ffmpeg/libavcodec/h264_mb_template.c create mode 100644 ffmpeg/libavcodec/h264_mc_template.c create mode 100644 ffmpeg/libavcodec/h264_mp4toannexb_bsf.c create mode 100644 ffmpeg/libavcodec/h264_mvpred.h create mode 100644 ffmpeg/libavcodec/h264_parser.c create mode 100644 ffmpeg/libavcodec/h264_ps.c create mode 100644 ffmpeg/libavcodec/h264_refs.c create mode 100644 ffmpeg/libavcodec/h264_sei.c create mode 100644 ffmpeg/libavcodec/h264addpx_template.c create mode 100644 ffmpeg/libavcodec/h264chroma.c create mode 100644 ffmpeg/libavcodec/h264chroma.h create mode 100644 ffmpeg/libavcodec/h264chroma_template.c create mode 100644 ffmpeg/libavcodec/h264data.h create mode 100644 ffmpeg/libavcodec/h264dsp.c create mode 100644 ffmpeg/libavcodec/h264dsp.h create mode 100644 ffmpeg/libavcodec/h264dsp_template.c create mode 100644 ffmpeg/libavcodec/h264idct.c create mode 100644 ffmpeg/libavcodec/h264idct.h create mode 100644 ffmpeg/libavcodec/h264idct_template.c create mode 100644 ffmpeg/libavcodec/h264pred.c create mode 100644 ffmpeg/libavcodec/h264pred.h create mode 100644 ffmpeg/libavcodec/h264pred_template.c create mode 100644 ffmpeg/libavcodec/h264qpel.c create mode 100644 ffmpeg/libavcodec/h264qpel.h create mode 100644 ffmpeg/libavcodec/h264qpel_template.c create mode 100644 ffmpeg/libavcodec/hpel_template.c create mode 100644 ffmpeg/libavcodec/hpeldsp.c create mode 100644 ffmpeg/libavcodec/hpeldsp.h create mode 100644 ffmpeg/libavcodec/hpeldsp_template.c create mode 100644 ffmpeg/libavcodec/huffman.c create mode 100644 ffmpeg/libavcodec/huffman.h create mode 100644 ffmpeg/libavcodec/huffyuv.c create mode 100644 ffmpeg/libavcodec/huffyuv.h create mode 100644 ffmpeg/libavcodec/huffyuvdec.c create mode 100644 ffmpeg/libavcodec/huffyuvenc.c create mode 100644 ffmpeg/libavcodec/idcinvideo.c create mode 100644 ffmpeg/libavcodec/iff.c create mode 100644 ffmpeg/libavcodec/iirfilter.c create mode 100644 ffmpeg/libavcodec/iirfilter.h create mode 100644 ffmpeg/libavcodec/imc.c create mode 100644 ffmpeg/libavcodec/imcdata.h create mode 100644 ffmpeg/libavcodec/imgconvert.c create mode 100644 ffmpeg/libavcodec/imgconvert.h create mode 100644 ffmpeg/libavcodec/imx_dump_header_bsf.c create mode 100644 ffmpeg/libavcodec/indeo2.c create mode 100644 ffmpeg/libavcodec/indeo2data.h create mode 100644 ffmpeg/libavcodec/indeo3.c create mode 100644 ffmpeg/libavcodec/indeo3data.h create mode 100644 ffmpeg/libavcodec/indeo4.c create mode 100644 ffmpeg/libavcodec/indeo4data.h create mode 100644 ffmpeg/libavcodec/indeo5.c create mode 100644 ffmpeg/libavcodec/indeo5data.h create mode 100644 ffmpeg/libavcodec/intelh263dec.c create mode 100644 ffmpeg/libavcodec/internal.h create mode 100644 ffmpeg/libavcodec/interplayvideo.c create mode 100644 ffmpeg/libavcodec/intrax8.c create mode 100644 ffmpeg/libavcodec/intrax8.h create mode 100644 ffmpeg/libavcodec/intrax8dsp.c create mode 100644 ffmpeg/libavcodec/intrax8dsp.h create mode 100644 ffmpeg/libavcodec/intrax8huf.h create mode 100644 ffmpeg/libavcodec/ituh263dec.c create mode 100644 ffmpeg/libavcodec/ituh263enc.c create mode 100644 ffmpeg/libavcodec/ivi_common.c create mode 100644 ffmpeg/libavcodec/ivi_common.h create mode 100644 ffmpeg/libavcodec/ivi_dsp.c create mode 100644 ffmpeg/libavcodec/ivi_dsp.h create mode 100644 ffmpeg/libavcodec/j2k.c create mode 100644 ffmpeg/libavcodec/j2k.h create mode 100644 ffmpeg/libavcodec/j2k_dwt.c create mode 100644 ffmpeg/libavcodec/j2k_dwt.h create mode 100644 ffmpeg/libavcodec/j2kdec.c create mode 100644 ffmpeg/libavcodec/j2kenc.c create mode 100644 ffmpeg/libavcodec/jacosub.h create mode 100644 ffmpeg/libavcodec/jacosubdec.c create mode 100644 ffmpeg/libavcodec/jfdctfst.c create mode 100644 ffmpeg/libavcodec/jfdctint.c create mode 100644 ffmpeg/libavcodec/jfdctint_template.c create mode 100644 ffmpeg/libavcodec/jpegls.c create mode 100644 ffmpeg/libavcodec/jpegls.h create mode 100644 ffmpeg/libavcodec/jpeglsdec.c create mode 100644 ffmpeg/libavcodec/jpeglsdec.h create mode 100644 ffmpeg/libavcodec/jpeglsenc.c create mode 100644 ffmpeg/libavcodec/jrevdct.c create mode 100644 ffmpeg/libavcodec/jvdec.c create mode 100644 ffmpeg/libavcodec/kbdwin.c create mode 100644 ffmpeg/libavcodec/kbdwin.h create mode 100644 ffmpeg/libavcodec/kgv1dec.c create mode 100644 ffmpeg/libavcodec/kmvc.c create mode 100644 ffmpeg/libavcodec/lagarith.c create mode 100644 ffmpeg/libavcodec/lagarithrac.c create mode 100644 ffmpeg/libavcodec/lagarithrac.h create mode 100644 ffmpeg/libavcodec/latm_parser.c create mode 100644 ffmpeg/libavcodec/lcl.h create mode 100644 ffmpeg/libavcodec/lcldec.c create mode 100644 ffmpeg/libavcodec/lclenc.c create mode 100644 ffmpeg/libavcodec/libaacplus.c create mode 100644 ffmpeg/libavcodec/libavcodec.pc create mode 100644 ffmpeg/libavcodec/libavcodec.v create mode 100644 ffmpeg/libavcodec/libcelt_dec.c create mode 100644 ffmpeg/libavcodec/libfaac.c create mode 100644 ffmpeg/libavcodec/libfdk-aacenc.c create mode 100644 ffmpeg/libavcodec/libgsm.c create mode 100644 ffmpeg/libavcodec/libilbc.c create mode 100644 ffmpeg/libavcodec/libmp3lame.c create mode 100644 ffmpeg/libavcodec/libopencore-amr.c create mode 100644 ffmpeg/libavcodec/libopenjpegdec.c create mode 100644 ffmpeg/libavcodec/libopenjpegenc.c create mode 100644 ffmpeg/libavcodec/libopus.c create mode 100644 ffmpeg/libavcodec/libopus.h create mode 100644 ffmpeg/libavcodec/libopusdec.c create mode 100644 ffmpeg/libavcodec/libopusenc.c create mode 100644 ffmpeg/libavcodec/libschroedinger.c create mode 100644 ffmpeg/libavcodec/libschroedinger.h create mode 100644 ffmpeg/libavcodec/libschroedingerdec.c create mode 100644 ffmpeg/libavcodec/libschroedingerenc.c create mode 100644 ffmpeg/libavcodec/libspeexdec.c create mode 100644 ffmpeg/libavcodec/libspeexenc.c create mode 100644 ffmpeg/libavcodec/libstagefright.cpp create mode 100644 ffmpeg/libavcodec/libtheoraenc.c create mode 100644 ffmpeg/libavcodec/libtwolame.c create mode 100644 ffmpeg/libavcodec/libutvideo.h create mode 100644 ffmpeg/libavcodec/libutvideodec.cpp create mode 100644 ffmpeg/libavcodec/libutvideoenc.cpp create mode 100644 ffmpeg/libavcodec/libvo-aacenc.c create mode 100644 ffmpeg/libavcodec/libvo-amrwbenc.c create mode 100644 ffmpeg/libavcodec/libvorbisdec.c create mode 100644 ffmpeg/libavcodec/libvorbisenc.c create mode 100644 ffmpeg/libavcodec/libvpxdec.c create mode 100644 ffmpeg/libavcodec/libvpxenc.c create mode 100644 ffmpeg/libavcodec/libx264.c create mode 100644 ffmpeg/libavcodec/libxavs.c create mode 100644 ffmpeg/libavcodec/libxvid.c create mode 100644 ffmpeg/libavcodec/libxvid.h create mode 100644 ffmpeg/libavcodec/libxvid_rc.c create mode 100644 ffmpeg/libavcodec/ljpegenc.c create mode 100644 ffmpeg/libavcodec/loco.c create mode 100644 ffmpeg/libavcodec/log2_tab.c create mode 100644 ffmpeg/libavcodec/lpc.c create mode 100644 ffmpeg/libavcodec/lpc.h create mode 100644 ffmpeg/libavcodec/lsp.c create mode 100644 ffmpeg/libavcodec/lsp.h create mode 100644 ffmpeg/libavcodec/lzw.c create mode 100644 ffmpeg/libavcodec/lzw.h create mode 100644 ffmpeg/libavcodec/lzwenc.c create mode 100644 ffmpeg/libavcodec/mace.c create mode 100644 ffmpeg/libavcodec/mathops.h create mode 100644 ffmpeg/libavcodec/mathtables.c create mode 100644 ffmpeg/libavcodec/mdct.c create mode 100644 ffmpeg/libavcodec/mdct_fixed.c create mode 100644 ffmpeg/libavcodec/mdct_float.c create mode 100644 ffmpeg/libavcodec/mdec.c create mode 100644 ffmpeg/libavcodec/microdvddec.c create mode 100644 ffmpeg/libavcodec/mimic.c create mode 100644 ffmpeg/libavcodec/mips/Makefile create mode 100644 ffmpeg/libavcodec/mips/aaccoder_mips.c create mode 100644 ffmpeg/libavcodec/mips/aacdec_mips.c create mode 100644 ffmpeg/libavcodec/mips/aacdec_mips.h create mode 100644 ffmpeg/libavcodec/mips/aacpsdsp_mips.c create mode 100644 ffmpeg/libavcodec/mips/aacsbr_mips.c create mode 100644 ffmpeg/libavcodec/mips/aacsbr_mips.h create mode 100644 ffmpeg/libavcodec/mips/ac3dsp_mips.c create mode 100644 ffmpeg/libavcodec/mips/acelp_filters_mips.c create mode 100644 ffmpeg/libavcodec/mips/acelp_vectors_mips.c create mode 100644 ffmpeg/libavcodec/mips/amrwbdec_mips.c create mode 100644 ffmpeg/libavcodec/mips/amrwbdec_mips.h create mode 100644 ffmpeg/libavcodec/mips/celp_filters_mips.c create mode 100644 ffmpeg/libavcodec/mips/celp_math_mips.c create mode 100644 ffmpeg/libavcodec/mips/compute_antialias_fixed.h create mode 100644 ffmpeg/libavcodec/mips/compute_antialias_float.h create mode 100644 ffmpeg/libavcodec/mips/fft_init_table.c create mode 100644 ffmpeg/libavcodec/mips/fft_mips.c create mode 100644 ffmpeg/libavcodec/mips/fft_table.h create mode 100644 ffmpeg/libavcodec/mips/fmtconvert_mips.c create mode 100644 ffmpeg/libavcodec/mips/iirfilter_mips.c create mode 100644 ffmpeg/libavcodec/mips/lsp_mips.h create mode 100644 ffmpeg/libavcodec/mips/mathops.h create mode 100644 ffmpeg/libavcodec/mips/mpegaudiodsp_mips_fixed.c create mode 100644 ffmpeg/libavcodec/mips/mpegaudiodsp_mips_float.c create mode 100644 ffmpeg/libavcodec/mips/sbrdsp_mips.c create mode 100644 ffmpeg/libavcodec/mjpeg.c create mode 100644 ffmpeg/libavcodec/mjpeg.h create mode 100644 ffmpeg/libavcodec/mjpeg2jpeg_bsf.c create mode 100644 ffmpeg/libavcodec/mjpeg_parser.c create mode 100644 ffmpeg/libavcodec/mjpega_dump_header_bsf.c create mode 100644 ffmpeg/libavcodec/mjpegbdec.c create mode 100644 ffmpeg/libavcodec/mjpegdec.c create mode 100644 ffmpeg/libavcodec/mjpegdec.h create mode 100644 ffmpeg/libavcodec/mjpegenc.c create mode 100644 ffmpeg/libavcodec/mjpegenc.h create mode 100644 ffmpeg/libavcodec/mlp.c create mode 100644 ffmpeg/libavcodec/mlp.h create mode 100644 ffmpeg/libavcodec/mlp_parser.c create mode 100644 ffmpeg/libavcodec/mlp_parser.h create mode 100644 ffmpeg/libavcodec/mlpdec.c create mode 100644 ffmpeg/libavcodec/mlpdsp.c create mode 100644 ffmpeg/libavcodec/mlpdsp.h create mode 100644 ffmpeg/libavcodec/mmvideo.c create mode 100644 ffmpeg/libavcodec/motion-test.c create mode 100644 ffmpeg/libavcodec/motion_est.c create mode 100644 ffmpeg/libavcodec/motion_est_template.c create mode 100644 ffmpeg/libavcodec/motionpixels.c create mode 100644 ffmpeg/libavcodec/motionpixels_tablegen.c create mode 100644 ffmpeg/libavcodec/motionpixels_tablegen.h create mode 100644 ffmpeg/libavcodec/movsub_bsf.c create mode 100644 ffmpeg/libavcodec/movtextdec.c create mode 100644 ffmpeg/libavcodec/movtextenc.c create mode 100644 ffmpeg/libavcodec/mp3_header_compress_bsf.c create mode 100644 ffmpeg/libavcodec/mp3_header_decompress_bsf.c create mode 100644 ffmpeg/libavcodec/mpc.c create mode 100644 ffmpeg/libavcodec/mpc.h create mode 100644 ffmpeg/libavcodec/mpc7.c create mode 100644 ffmpeg/libavcodec/mpc7data.h create mode 100644 ffmpeg/libavcodec/mpc8.c create mode 100644 ffmpeg/libavcodec/mpc8data.h create mode 100644 ffmpeg/libavcodec/mpc8huff.h create mode 100644 ffmpeg/libavcodec/mpcdata.h create mode 100644 ffmpeg/libavcodec/mpeg12.c create mode 100644 ffmpeg/libavcodec/mpeg12.h create mode 100644 ffmpeg/libavcodec/mpeg12data.c create mode 100644 ffmpeg/libavcodec/mpeg12data.h create mode 100644 ffmpeg/libavcodec/mpeg12decdata.h create mode 100644 ffmpeg/libavcodec/mpeg12enc.c create mode 100644 ffmpeg/libavcodec/mpeg4audio.c create mode 100644 ffmpeg/libavcodec/mpeg4audio.h create mode 100644 ffmpeg/libavcodec/mpeg4data.h create mode 100644 ffmpeg/libavcodec/mpeg4video.c create mode 100644 ffmpeg/libavcodec/mpeg4video.h create mode 100644 ffmpeg/libavcodec/mpeg4video_parser.c create mode 100644 ffmpeg/libavcodec/mpeg4video_parser.h create mode 100644 ffmpeg/libavcodec/mpeg4videodec.c create mode 100644 ffmpeg/libavcodec/mpeg4videoenc.c create mode 100644 ffmpeg/libavcodec/mpegaudio.c create mode 100644 ffmpeg/libavcodec/mpegaudio.h create mode 100644 ffmpeg/libavcodec/mpegaudio_parser.c create mode 100644 ffmpeg/libavcodec/mpegaudio_tablegen.c create mode 100644 ffmpeg/libavcodec/mpegaudio_tablegen.h create mode 100644 ffmpeg/libavcodec/mpegaudiodata.c create mode 100644 ffmpeg/libavcodec/mpegaudiodata.h create mode 100644 ffmpeg/libavcodec/mpegaudiodec.c create mode 100644 ffmpeg/libavcodec/mpegaudiodec_float.c create mode 100644 ffmpeg/libavcodec/mpegaudiodecheader.c create mode 100644 ffmpeg/libavcodec/mpegaudiodecheader.h create mode 100644 ffmpeg/libavcodec/mpegaudiodectab.h create mode 100644 ffmpeg/libavcodec/mpegaudiodsp.c create mode 100644 ffmpeg/libavcodec/mpegaudiodsp.h create mode 100644 ffmpeg/libavcodec/mpegaudiodsp_data.c create mode 100644 ffmpeg/libavcodec/mpegaudiodsp_fixed.c create mode 100644 ffmpeg/libavcodec/mpegaudiodsp_float.c create mode 100644 ffmpeg/libavcodec/mpegaudiodsp_template.c create mode 100644 ffmpeg/libavcodec/mpegaudioenc.c create mode 100644 ffmpeg/libavcodec/mpegaudiotab.h create mode 100644 ffmpeg/libavcodec/mpegvideo.c create mode 100644 ffmpeg/libavcodec/mpegvideo.h create mode 100644 ffmpeg/libavcodec/mpegvideo_enc.c create mode 100644 ffmpeg/libavcodec/mpegvideo_motion.c create mode 100644 ffmpeg/libavcodec/mpegvideo_parser.c create mode 100644 ffmpeg/libavcodec/mpegvideo_xvmc.c create mode 100644 ffmpeg/libavcodec/mpl2dec.c create mode 100644 ffmpeg/libavcodec/mqc.c create mode 100644 ffmpeg/libavcodec/mqc.h create mode 100644 ffmpeg/libavcodec/mqcdec.c create mode 100644 ffmpeg/libavcodec/mqcenc.c create mode 100644 ffmpeg/libavcodec/msgsmdec.c create mode 100644 ffmpeg/libavcodec/msgsmdec.h create mode 100644 ffmpeg/libavcodec/msmpeg4.c create mode 100644 ffmpeg/libavcodec/msmpeg4.h create mode 100644 ffmpeg/libavcodec/msmpeg4data.c create mode 100644 ffmpeg/libavcodec/msmpeg4data.h create mode 100644 ffmpeg/libavcodec/msmpeg4enc.c create mode 100644 ffmpeg/libavcodec/msrle.c create mode 100644 ffmpeg/libavcodec/msrledec.c create mode 100644 ffmpeg/libavcodec/msrledec.h create mode 100644 ffmpeg/libavcodec/mss1.c create mode 100644 ffmpeg/libavcodec/mss12.c create mode 100644 ffmpeg/libavcodec/mss12.h create mode 100644 ffmpeg/libavcodec/mss2.c create mode 100644 ffmpeg/libavcodec/mss2dsp.c create mode 100644 ffmpeg/libavcodec/mss2dsp.h create mode 100644 ffmpeg/libavcodec/mss3.c create mode 100644 ffmpeg/libavcodec/mss34dsp.c create mode 100644 ffmpeg/libavcodec/mss34dsp.h create mode 100644 ffmpeg/libavcodec/mss4.c create mode 100644 ffmpeg/libavcodec/msvideo1.c create mode 100644 ffmpeg/libavcodec/msvideo1enc.c create mode 100644 ffmpeg/libavcodec/mvcdec.c create mode 100644 ffmpeg/libavcodec/mxpegdec.c create mode 100644 ffmpeg/libavcodec/nellymoser.c create mode 100644 ffmpeg/libavcodec/nellymoser.h create mode 100644 ffmpeg/libavcodec/nellymoserdec.c create mode 100644 ffmpeg/libavcodec/nellymoserenc.c create mode 100644 ffmpeg/libavcodec/noise_bsf.c create mode 100644 ffmpeg/libavcodec/nuv.c create mode 100644 ffmpeg/libavcodec/old_codec_ids.h create mode 100644 ffmpeg/libavcodec/options.c create mode 100644 ffmpeg/libavcodec/options_table.h create mode 100644 ffmpeg/libavcodec/os2threads.h create mode 100644 ffmpeg/libavcodec/paf.c create mode 100644 ffmpeg/libavcodec/paf.h create mode 100644 ffmpeg/libavcodec/pamenc.c create mode 100644 ffmpeg/libavcodec/parser.c create mode 100644 ffmpeg/libavcodec/parser.h create mode 100644 ffmpeg/libavcodec/pcm-mpeg.c create mode 100644 ffmpeg/libavcodec/pcm.c create mode 100644 ffmpeg/libavcodec/pcm_tablegen.c create mode 100644 ffmpeg/libavcodec/pcm_tablegen.h create mode 100644 ffmpeg/libavcodec/pcx.c create mode 100644 ffmpeg/libavcodec/pcxenc.c create mode 100644 ffmpeg/libavcodec/pgssubdec.c create mode 100644 ffmpeg/libavcodec/pictordec.c create mode 100644 ffmpeg/libavcodec/png.c create mode 100644 ffmpeg/libavcodec/png.h create mode 100644 ffmpeg/libavcodec/png_parser.c create mode 100644 ffmpeg/libavcodec/pngdec.c create mode 100644 ffmpeg/libavcodec/pngdsp.c create mode 100644 ffmpeg/libavcodec/pngdsp.h create mode 100644 ffmpeg/libavcodec/pngenc.c create mode 100644 ffmpeg/libavcodec/pnm.c create mode 100644 ffmpeg/libavcodec/pnm.h create mode 100644 ffmpeg/libavcodec/pnm_parser.c create mode 100644 ffmpeg/libavcodec/pnmdec.c create mode 100644 ffmpeg/libavcodec/pnmenc.c create mode 100644 ffmpeg/libavcodec/ppc/Makefile create mode 100644 ffmpeg/libavcodec/ppc/asm.S create mode 100644 ffmpeg/libavcodec/ppc/dsputil_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/dsputil_altivec.h create mode 100644 ffmpeg/libavcodec/ppc/dsputil_ppc.c create mode 100644 ffmpeg/libavcodec/ppc/fdct_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/fft_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/fft_altivec_s.S create mode 100644 ffmpeg/libavcodec/ppc/fmtconvert_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/gmc_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/h264_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/h264_qpel.c create mode 100644 ffmpeg/libavcodec/ppc/h264_qpel_template.c create mode 100644 ffmpeg/libavcodec/ppc/h264chroma_init.c create mode 100644 ffmpeg/libavcodec/ppc/h264chroma_template.c create mode 100644 ffmpeg/libavcodec/ppc/hpeldsp_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/idct_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/int_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/mathops.h create mode 100644 ffmpeg/libavcodec/ppc/mpegaudiodec_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/mpegvideo_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/vc1dsp_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/videodsp_ppc.c create mode 100644 ffmpeg/libavcodec/ppc/vorbisdsp_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/vp3dsp_altivec.c create mode 100644 ffmpeg/libavcodec/ppc/vp8dsp_altivec.c create mode 100644 ffmpeg/libavcodec/proresdata.c create mode 100644 ffmpeg/libavcodec/proresdata.h create mode 100644 ffmpeg/libavcodec/proresdec.h create mode 100644 ffmpeg/libavcodec/proresdec2.c create mode 100644 ffmpeg/libavcodec/proresdec_lgpl.c create mode 100644 ffmpeg/libavcodec/proresdsp.c create mode 100644 ffmpeg/libavcodec/proresdsp.h create mode 100644 ffmpeg/libavcodec/proresenc_anatoliy.c create mode 100644 ffmpeg/libavcodec/proresenc_kostya.c create mode 100644 ffmpeg/libavcodec/psymodel.c create mode 100644 ffmpeg/libavcodec/psymodel.h create mode 100644 ffmpeg/libavcodec/pthread.c create mode 100644 ffmpeg/libavcodec/ptx.c create mode 100644 ffmpeg/libavcodec/put_bits.h create mode 100644 ffmpeg/libavcodec/qcelpdata.h create mode 100644 ffmpeg/libavcodec/qcelpdec.c create mode 100644 ffmpeg/libavcodec/qdm2.c create mode 100644 ffmpeg/libavcodec/qdm2_tablegen.c create mode 100644 ffmpeg/libavcodec/qdm2_tablegen.h create mode 100644 ffmpeg/libavcodec/qdm2data.h create mode 100644 ffmpeg/libavcodec/qdrw.c create mode 100644 ffmpeg/libavcodec/qpeg.c create mode 100644 ffmpeg/libavcodec/qtrle.c create mode 100644 ffmpeg/libavcodec/qtrleenc.c create mode 100644 ffmpeg/libavcodec/r210dec.c create mode 100644 ffmpeg/libavcodec/r210enc.c create mode 100644 ffmpeg/libavcodec/ra144.c create mode 100644 ffmpeg/libavcodec/ra144.h create mode 100644 ffmpeg/libavcodec/ra144dec.c create mode 100644 ffmpeg/libavcodec/ra144enc.c create mode 100644 ffmpeg/libavcodec/ra288.c create mode 100644 ffmpeg/libavcodec/ra288.h create mode 100644 ffmpeg/libavcodec/ralf.c create mode 100644 ffmpeg/libavcodec/ralfdata.h create mode 100644 ffmpeg/libavcodec/rangecoder.c create mode 100644 ffmpeg/libavcodec/rangecoder.h create mode 100644 ffmpeg/libavcodec/ratecontrol.c create mode 100644 ffmpeg/libavcodec/ratecontrol.h create mode 100644 ffmpeg/libavcodec/raw.c create mode 100644 ffmpeg/libavcodec/raw.h create mode 100644 ffmpeg/libavcodec/rawdec.c create mode 100644 ffmpeg/libavcodec/rawenc.c create mode 100644 ffmpeg/libavcodec/rdft.c create mode 100644 ffmpeg/libavcodec/rdft.h create mode 100644 ffmpeg/libavcodec/realtextdec.c create mode 100644 ffmpeg/libavcodec/rectangle.h create mode 100644 ffmpeg/libavcodec/remove_extradata_bsf.c create mode 100644 ffmpeg/libavcodec/resample.c create mode 100644 ffmpeg/libavcodec/resample2.c create mode 100644 ffmpeg/libavcodec/rl.h create mode 100644 ffmpeg/libavcodec/rl2.c create mode 100644 ffmpeg/libavcodec/rle.c create mode 100644 ffmpeg/libavcodec/rle.h create mode 100644 ffmpeg/libavcodec/rnd_avg.h create mode 100644 ffmpeg/libavcodec/roqaudioenc.c create mode 100644 ffmpeg/libavcodec/roqvideo.c create mode 100644 ffmpeg/libavcodec/roqvideo.h create mode 100644 ffmpeg/libavcodec/roqvideodec.c create mode 100644 ffmpeg/libavcodec/roqvideoenc.c create mode 100644 ffmpeg/libavcodec/rpza.c create mode 100644 ffmpeg/libavcodec/rtjpeg.c create mode 100644 ffmpeg/libavcodec/rtjpeg.h create mode 100644 ffmpeg/libavcodec/rv10.c create mode 100644 ffmpeg/libavcodec/rv10enc.c create mode 100644 ffmpeg/libavcodec/rv20enc.c create mode 100644 ffmpeg/libavcodec/rv30.c create mode 100644 ffmpeg/libavcodec/rv30data.h create mode 100644 ffmpeg/libavcodec/rv30dsp.c create mode 100644 ffmpeg/libavcodec/rv34.c create mode 100644 ffmpeg/libavcodec/rv34.h create mode 100644 ffmpeg/libavcodec/rv34_parser.c create mode 100644 ffmpeg/libavcodec/rv34data.h create mode 100644 ffmpeg/libavcodec/rv34dsp.c create mode 100644 ffmpeg/libavcodec/rv34dsp.h create mode 100644 ffmpeg/libavcodec/rv34vlc.h create mode 100644 ffmpeg/libavcodec/rv40.c create mode 100644 ffmpeg/libavcodec/rv40data.h create mode 100644 ffmpeg/libavcodec/rv40dsp.c create mode 100644 ffmpeg/libavcodec/rv40vlc2.h create mode 100644 ffmpeg/libavcodec/s302m.c create mode 100644 ffmpeg/libavcodec/s3tc.c create mode 100644 ffmpeg/libavcodec/s3tc.h create mode 100644 ffmpeg/libavcodec/samidec.c create mode 100644 ffmpeg/libavcodec/sanm.c create mode 100644 ffmpeg/libavcodec/sanm_data.h create mode 100644 ffmpeg/libavcodec/sbr.h create mode 100644 ffmpeg/libavcodec/sbrdsp.c create mode 100644 ffmpeg/libavcodec/sbrdsp.h create mode 100644 ffmpeg/libavcodec/sgi.h create mode 100644 ffmpeg/libavcodec/sgidec.c create mode 100644 ffmpeg/libavcodec/sgienc.c create mode 100644 ffmpeg/libavcodec/sgirledec.c create mode 100644 ffmpeg/libavcodec/sh4/Makefile create mode 100644 ffmpeg/libavcodec/sh4/dsputil_align.c create mode 100644 ffmpeg/libavcodec/sh4/dsputil_sh4.c create mode 100644 ffmpeg/libavcodec/sh4/dsputil_sh4.h create mode 100644 ffmpeg/libavcodec/sh4/h264chroma_init.c create mode 100644 ffmpeg/libavcodec/sh4/hpeldsp.c create mode 100644 ffmpeg/libavcodec/sh4/idct_sh4.c create mode 100644 ffmpeg/libavcodec/sh4/qpel.c create mode 100644 ffmpeg/libavcodec/sh4/sh4.h create mode 100644 ffmpeg/libavcodec/shorten.c create mode 100644 ffmpeg/libavcodec/simple_idct.c create mode 100644 ffmpeg/libavcodec/simple_idct.h create mode 100644 ffmpeg/libavcodec/simple_idct_template.c create mode 100644 ffmpeg/libavcodec/sinewin.c create mode 100644 ffmpeg/libavcodec/sinewin.h create mode 100644 ffmpeg/libavcodec/sinewin_tablegen.c create mode 100644 ffmpeg/libavcodec/sinewin_tablegen.h create mode 100644 ffmpeg/libavcodec/sipr.c create mode 100644 ffmpeg/libavcodec/sipr.h create mode 100644 ffmpeg/libavcodec/sipr16k.c create mode 100644 ffmpeg/libavcodec/sipr16kdata.h create mode 100644 ffmpeg/libavcodec/siprdata.h create mode 100644 ffmpeg/libavcodec/smacker.c create mode 100644 ffmpeg/libavcodec/smc.c create mode 100644 ffmpeg/libavcodec/snow.c create mode 100644 ffmpeg/libavcodec/snow.h create mode 100644 ffmpeg/libavcodec/snow_dwt.c create mode 100644 ffmpeg/libavcodec/snow_dwt.h create mode 100644 ffmpeg/libavcodec/snowdata.h create mode 100644 ffmpeg/libavcodec/snowdec.c create mode 100644 ffmpeg/libavcodec/snowenc.c create mode 100644 ffmpeg/libavcodec/sonic.c create mode 100644 ffmpeg/libavcodec/sp5x.h create mode 100644 ffmpeg/libavcodec/sp5xdec.c create mode 100644 ffmpeg/libavcodec/sparc/Makefile create mode 100644 ffmpeg/libavcodec/sparc/dsputil_vis.c create mode 100644 ffmpeg/libavcodec/sparc/dsputil_vis.h create mode 100644 ffmpeg/libavcodec/sparc/hpeldsp_vis.c create mode 100644 ffmpeg/libavcodec/sparc/simple_idct_vis.c create mode 100644 ffmpeg/libavcodec/sparc/vis.h create mode 100644 ffmpeg/libavcodec/srtdec.c create mode 100644 ffmpeg/libavcodec/srtenc.c create mode 100644 ffmpeg/libavcodec/subviewerdec.c create mode 100644 ffmpeg/libavcodec/sunrast.c create mode 100644 ffmpeg/libavcodec/sunrast.h create mode 100644 ffmpeg/libavcodec/sunrastenc.c create mode 100644 ffmpeg/libavcodec/svq1.c create mode 100644 ffmpeg/libavcodec/svq1.h create mode 100644 ffmpeg/libavcodec/svq13.c create mode 100644 ffmpeg/libavcodec/svq1_cb.h create mode 100644 ffmpeg/libavcodec/svq1_vlc.h create mode 100644 ffmpeg/libavcodec/svq1dec.c create mode 100644 ffmpeg/libavcodec/svq1enc.c create mode 100644 ffmpeg/libavcodec/svq1enc_cb.h create mode 100644 ffmpeg/libavcodec/svq3.c create mode 100644 ffmpeg/libavcodec/svq3.h create mode 100644 ffmpeg/libavcodec/synth_filter.c create mode 100644 ffmpeg/libavcodec/synth_filter.h create mode 100644 ffmpeg/libavcodec/tableprint.h create mode 100644 ffmpeg/libavcodec/tak.c create mode 100644 ffmpeg/libavcodec/tak.h create mode 100644 ffmpeg/libavcodec/tak_parser.c create mode 100644 ffmpeg/libavcodec/takdec.c create mode 100644 ffmpeg/libavcodec/targa.c create mode 100644 ffmpeg/libavcodec/targa.h create mode 100644 ffmpeg/libavcodec/targa_y216dec.c create mode 100644 ffmpeg/libavcodec/targaenc.c create mode 100644 ffmpeg/libavcodec/textdec.c create mode 100644 ffmpeg/libavcodec/thread.h create mode 100644 ffmpeg/libavcodec/tiertexseqv.c create mode 100644 ffmpeg/libavcodec/tiff.c create mode 100644 ffmpeg/libavcodec/tiff.h create mode 100644 ffmpeg/libavcodec/tiff_data.c create mode 100644 ffmpeg/libavcodec/tiff_data.h create mode 100644 ffmpeg/libavcodec/tiffenc.c create mode 100644 ffmpeg/libavcodec/timecode.c create mode 100644 ffmpeg/libavcodec/timecode.h create mode 100644 ffmpeg/libavcodec/tmv.c create mode 100644 ffmpeg/libavcodec/truemotion1.c create mode 100644 ffmpeg/libavcodec/truemotion1data.h create mode 100644 ffmpeg/libavcodec/truemotion2.c create mode 100644 ffmpeg/libavcodec/truespeech.c create mode 100644 ffmpeg/libavcodec/truespeech_data.h create mode 100644 ffmpeg/libavcodec/tscc.c create mode 100644 ffmpeg/libavcodec/tscc2.c create mode 100644 ffmpeg/libavcodec/tscc2data.h create mode 100644 ffmpeg/libavcodec/tta.c create mode 100644 ffmpeg/libavcodec/twinvq.c create mode 100644 ffmpeg/libavcodec/twinvq_data.h create mode 100644 ffmpeg/libavcodec/txd.c create mode 100644 ffmpeg/libavcodec/ulti.c create mode 100644 ffmpeg/libavcodec/ulti_cb.h create mode 100644 ffmpeg/libavcodec/unary.h create mode 100644 ffmpeg/libavcodec/utils.c create mode 100644 ffmpeg/libavcodec/utvideo.c create mode 100644 ffmpeg/libavcodec/utvideo.h create mode 100644 ffmpeg/libavcodec/utvideodec.c create mode 100644 ffmpeg/libavcodec/utvideoenc.c create mode 100644 ffmpeg/libavcodec/v210dec.c create mode 100644 ffmpeg/libavcodec/v210dec.h create mode 100644 ffmpeg/libavcodec/v210enc.c create mode 100644 ffmpeg/libavcodec/v210x.c create mode 100644 ffmpeg/libavcodec/v308dec.c create mode 100644 ffmpeg/libavcodec/v308enc.c create mode 100644 ffmpeg/libavcodec/v408dec.c create mode 100644 ffmpeg/libavcodec/v408enc.c create mode 100644 ffmpeg/libavcodec/v410dec.c create mode 100644 ffmpeg/libavcodec/v410enc.c create mode 100644 ffmpeg/libavcodec/vaapi.c create mode 100644 ffmpeg/libavcodec/vaapi.h create mode 100644 ffmpeg/libavcodec/vaapi_h264.c create mode 100644 ffmpeg/libavcodec/vaapi_internal.h create mode 100644 ffmpeg/libavcodec/vaapi_mpeg2.c create mode 100644 ffmpeg/libavcodec/vaapi_mpeg4.c create mode 100644 ffmpeg/libavcodec/vaapi_vc1.c create mode 100644 ffmpeg/libavcodec/vb.c create mode 100644 ffmpeg/libavcodec/vble.c create mode 100644 ffmpeg/libavcodec/vc1.c create mode 100644 ffmpeg/libavcodec/vc1.h create mode 100644 ffmpeg/libavcodec/vc1_parser.c create mode 100644 ffmpeg/libavcodec/vc1acdata.h create mode 100644 ffmpeg/libavcodec/vc1data.c create mode 100644 ffmpeg/libavcodec/vc1data.h create mode 100644 ffmpeg/libavcodec/vc1dec.c create mode 100644 ffmpeg/libavcodec/vc1dsp.c create mode 100644 ffmpeg/libavcodec/vc1dsp.h create mode 100644 ffmpeg/libavcodec/vcr1.c create mode 100644 ffmpeg/libavcodec/vda.h create mode 100644 ffmpeg/libavcodec/vda_h264.c create mode 100644 ffmpeg/libavcodec/vda_h264_dec.c create mode 100644 ffmpeg/libavcodec/vdpau.c create mode 100644 ffmpeg/libavcodec/vdpau.h create mode 100644 ffmpeg/libavcodec/vdpau_h264.c create mode 100644 ffmpeg/libavcodec/vdpau_internal.h create mode 100644 ffmpeg/libavcodec/vdpau_mpeg12.c create mode 100644 ffmpeg/libavcodec/vdpau_mpeg4.c create mode 100644 ffmpeg/libavcodec/vdpau_vc1.c create mode 100644 ffmpeg/libavcodec/version.h create mode 100644 ffmpeg/libavcodec/videodsp.c create mode 100644 ffmpeg/libavcodec/videodsp.h create mode 100644 ffmpeg/libavcodec/videodsp_template.c create mode 100644 ffmpeg/libavcodec/vima.c create mode 100644 ffmpeg/libavcodec/vmdav.c create mode 100644 ffmpeg/libavcodec/vmnc.c create mode 100644 ffmpeg/libavcodec/vorbis.c create mode 100644 ffmpeg/libavcodec/vorbis.h create mode 100644 ffmpeg/libavcodec/vorbis_data.c create mode 100644 ffmpeg/libavcodec/vorbis_enc_data.h create mode 100644 ffmpeg/libavcodec/vorbis_parser.c create mode 100644 ffmpeg/libavcodec/vorbis_parser.h create mode 100644 ffmpeg/libavcodec/vorbisdec.c create mode 100644 ffmpeg/libavcodec/vorbisdsp.c create mode 100644 ffmpeg/libavcodec/vorbisdsp.h create mode 100644 ffmpeg/libavcodec/vorbisenc.c create mode 100644 ffmpeg/libavcodec/vp3.c create mode 100644 ffmpeg/libavcodec/vp3_parser.c create mode 100644 ffmpeg/libavcodec/vp3data.h create mode 100644 ffmpeg/libavcodec/vp3dsp.c create mode 100644 ffmpeg/libavcodec/vp3dsp.h create mode 100644 ffmpeg/libavcodec/vp5.c create mode 100644 ffmpeg/libavcodec/vp56.c create mode 100644 ffmpeg/libavcodec/vp56.h create mode 100644 ffmpeg/libavcodec/vp56data.c create mode 100644 ffmpeg/libavcodec/vp56data.h create mode 100644 ffmpeg/libavcodec/vp56dsp.c create mode 100644 ffmpeg/libavcodec/vp56dsp.h create mode 100644 ffmpeg/libavcodec/vp56rac.c create mode 100644 ffmpeg/libavcodec/vp5data.h create mode 100644 ffmpeg/libavcodec/vp6.c create mode 100644 ffmpeg/libavcodec/vp6data.h create mode 100644 ffmpeg/libavcodec/vp6dsp.c create mode 100644 ffmpeg/libavcodec/vp8.c create mode 100644 ffmpeg/libavcodec/vp8.h create mode 100644 ffmpeg/libavcodec/vp8_parser.c create mode 100644 ffmpeg/libavcodec/vp8data.h create mode 100644 ffmpeg/libavcodec/vp8dsp.c create mode 100644 ffmpeg/libavcodec/vp8dsp.h create mode 100644 ffmpeg/libavcodec/vqavideo.c create mode 100644 ffmpeg/libavcodec/w32pthreads.h create mode 100644 ffmpeg/libavcodec/wavpack.c create mode 100644 ffmpeg/libavcodec/webvttdec.c create mode 100644 ffmpeg/libavcodec/wma.c create mode 100644 ffmpeg/libavcodec/wma.h create mode 100644 ffmpeg/libavcodec/wma_common.c create mode 100644 ffmpeg/libavcodec/wma_common.h create mode 100644 ffmpeg/libavcodec/wmadata.h create mode 100644 ffmpeg/libavcodec/wmadec.c create mode 100644 ffmpeg/libavcodec/wmaenc.c create mode 100644 ffmpeg/libavcodec/wmalosslessdec.c create mode 100644 ffmpeg/libavcodec/wmaprodata.h create mode 100644 ffmpeg/libavcodec/wmaprodec.c create mode 100644 ffmpeg/libavcodec/wmavoice.c create mode 100644 ffmpeg/libavcodec/wmavoice_data.h create mode 100644 ffmpeg/libavcodec/wmv2.c create mode 100644 ffmpeg/libavcodec/wmv2.h create mode 100644 ffmpeg/libavcodec/wmv2dec.c create mode 100644 ffmpeg/libavcodec/wmv2dsp.c create mode 100644 ffmpeg/libavcodec/wmv2dsp.h create mode 100644 ffmpeg/libavcodec/wmv2enc.c create mode 100644 ffmpeg/libavcodec/wnv1.c create mode 100644 ffmpeg/libavcodec/ws-snd1.c create mode 100644 ffmpeg/libavcodec/x86/Makefile create mode 100644 ffmpeg/libavcodec/x86/ac3dsp.asm create mode 100644 ffmpeg/libavcodec/x86/ac3dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/cabac.h create mode 100644 ffmpeg/libavcodec/x86/cavsdsp.c create mode 100644 ffmpeg/libavcodec/x86/constants.c create mode 100644 ffmpeg/libavcodec/x86/dct32.asm create mode 100644 ffmpeg/libavcodec/x86/deinterlace.asm create mode 100644 ffmpeg/libavcodec/x86/dirac_dwt.c create mode 100644 ffmpeg/libavcodec/x86/dirac_dwt.h create mode 100644 ffmpeg/libavcodec/x86/diracdsp_mmx.c create mode 100644 ffmpeg/libavcodec/x86/diracdsp_mmx.h create mode 100644 ffmpeg/libavcodec/x86/diracdsp_yasm.asm create mode 100644 ffmpeg/libavcodec/x86/dnxhdenc.c create mode 100644 ffmpeg/libavcodec/x86/dsputil.asm create mode 100644 ffmpeg/libavcodec/x86/dsputil_mmx.c create mode 100644 ffmpeg/libavcodec/x86/dsputil_mmx.h create mode 100644 ffmpeg/libavcodec/x86/dsputil_qns_template.c create mode 100644 ffmpeg/libavcodec/x86/dsputil_rnd_template.c create mode 100644 ffmpeg/libavcodec/x86/dsputilenc.asm create mode 100644 ffmpeg/libavcodec/x86/dsputilenc_mmx.c create mode 100644 ffmpeg/libavcodec/x86/dwt_yasm.asm create mode 100644 ffmpeg/libavcodec/x86/fdct.c create mode 100644 ffmpeg/libavcodec/x86/fft.asm create mode 100644 ffmpeg/libavcodec/x86/fft.h create mode 100644 ffmpeg/libavcodec/x86/fft_init.c create mode 100644 ffmpeg/libavcodec/x86/fmtconvert.asm create mode 100644 ffmpeg/libavcodec/x86/fmtconvert_init.c create mode 100644 ffmpeg/libavcodec/x86/fpelbase.asm create mode 100644 ffmpeg/libavcodec/x86/h263_loopfilter.asm create mode 100644 ffmpeg/libavcodec/x86/h264_chromamc.asm create mode 100644 ffmpeg/libavcodec/x86/h264_chromamc_10bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264_deblock.asm create mode 100644 ffmpeg/libavcodec/x86/h264_deblock_10bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264_i386.h create mode 100644 ffmpeg/libavcodec/x86/h264_idct.asm create mode 100644 ffmpeg/libavcodec/x86/h264_idct_10bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264_intrapred.asm create mode 100644 ffmpeg/libavcodec/x86/h264_intrapred_10bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264_intrapred_init.c create mode 100644 ffmpeg/libavcodec/x86/h264_qpel.c create mode 100644 ffmpeg/libavcodec/x86/h264_qpel_10bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264_qpel_8bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264_weight.asm create mode 100644 ffmpeg/libavcodec/x86/h264_weight_10bit.asm create mode 100644 ffmpeg/libavcodec/x86/h264chroma_init.c create mode 100644 ffmpeg/libavcodec/x86/h264dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/hpeldsp.asm create mode 100644 ffmpeg/libavcodec/x86/hpeldsp_avg_template.c create mode 100644 ffmpeg/libavcodec/x86/hpeldsp_init.c create mode 100644 ffmpeg/libavcodec/x86/hpeldsp_rnd_template.c create mode 100644 ffmpeg/libavcodec/x86/idct_mmx_xvid.c create mode 100644 ffmpeg/libavcodec/x86/idct_sse2_xvid.c create mode 100644 ffmpeg/libavcodec/x86/idct_xvid.h create mode 100644 ffmpeg/libavcodec/x86/imdct36.asm create mode 100644 ffmpeg/libavcodec/x86/lpc.c create mode 100644 ffmpeg/libavcodec/x86/mathops.h create mode 100644 ffmpeg/libavcodec/x86/mlpdsp.c create mode 100644 ffmpeg/libavcodec/x86/motion_est.c create mode 100644 ffmpeg/libavcodec/x86/mpeg4qpel.asm create mode 100644 ffmpeg/libavcodec/x86/mpegaudiodec.c create mode 100644 ffmpeg/libavcodec/x86/mpegvideo.c create mode 100644 ffmpeg/libavcodec/x86/mpegvideoenc.c create mode 100644 ffmpeg/libavcodec/x86/mpegvideoenc_template.c create mode 100644 ffmpeg/libavcodec/x86/pngdsp.asm create mode 100644 ffmpeg/libavcodec/x86/pngdsp_init.c create mode 100644 ffmpeg/libavcodec/x86/proresdsp.asm create mode 100644 ffmpeg/libavcodec/x86/proresdsp_init.c create mode 100644 ffmpeg/libavcodec/x86/qpelbase.asm create mode 100644 ffmpeg/libavcodec/x86/rv34dsp.asm create mode 100644 ffmpeg/libavcodec/x86/rv34dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/rv40dsp.asm create mode 100644 ffmpeg/libavcodec/x86/rv40dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/sbrdsp.asm create mode 100644 ffmpeg/libavcodec/x86/sbrdsp_init.c create mode 100644 ffmpeg/libavcodec/x86/simple_idct.c create mode 100644 ffmpeg/libavcodec/x86/snowdsp.c create mode 100644 ffmpeg/libavcodec/x86/v210-init.c create mode 100644 ffmpeg/libavcodec/x86/v210.asm create mode 100644 ffmpeg/libavcodec/x86/vc1dsp.asm create mode 100644 ffmpeg/libavcodec/x86/vc1dsp.h create mode 100644 ffmpeg/libavcodec/x86/vc1dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/vc1dsp_mmx.c create mode 100644 ffmpeg/libavcodec/x86/videodsp.asm create mode 100644 ffmpeg/libavcodec/x86/videodsp_init.c create mode 100644 ffmpeg/libavcodec/x86/vorbisdsp.asm create mode 100644 ffmpeg/libavcodec/x86/vorbisdsp_init.c create mode 100644 ffmpeg/libavcodec/x86/vp3dsp.asm create mode 100644 ffmpeg/libavcodec/x86/vp3dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/vp56_arith.h create mode 100644 ffmpeg/libavcodec/x86/vp56dsp.asm create mode 100644 ffmpeg/libavcodec/x86/vp56dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/vp8dsp.asm create mode 100644 ffmpeg/libavcodec/x86/vp8dsp_init.c create mode 100644 ffmpeg/libavcodec/x86/w64xmmtest.c create mode 100644 ffmpeg/libavcodec/xan.c create mode 100644 ffmpeg/libavcodec/xbmdec.c create mode 100644 ffmpeg/libavcodec/xbmenc.c create mode 100644 ffmpeg/libavcodec/xface.c create mode 100644 ffmpeg/libavcodec/xface.h create mode 100644 ffmpeg/libavcodec/xfacedec.c create mode 100644 ffmpeg/libavcodec/xfaceenc.c create mode 100644 ffmpeg/libavcodec/xiph.c create mode 100644 ffmpeg/libavcodec/xiph.h create mode 100644 ffmpeg/libavcodec/xl.c create mode 100644 ffmpeg/libavcodec/xsubdec.c create mode 100644 ffmpeg/libavcodec/xsubenc.c create mode 100644 ffmpeg/libavcodec/xvmc.h create mode 100644 ffmpeg/libavcodec/xvmc_internal.h create mode 100644 ffmpeg/libavcodec/xwd.h create mode 100644 ffmpeg/libavcodec/xwddec.c create mode 100644 ffmpeg/libavcodec/xwdenc.c create mode 100644 ffmpeg/libavcodec/xxan.c create mode 100644 ffmpeg/libavcodec/y41pdec.c create mode 100644 ffmpeg/libavcodec/y41penc.c create mode 100644 ffmpeg/libavcodec/yop.c create mode 100644 ffmpeg/libavcodec/yuv4dec.c create mode 100644 ffmpeg/libavcodec/yuv4enc.c create mode 100644 ffmpeg/libavcodec/zerocodec.c create mode 100644 ffmpeg/libavcodec/zmbv.c create mode 100644 ffmpeg/libavcodec/zmbvenc.c (limited to 'ffmpeg/libavcodec') diff --git a/ffmpeg/libavcodec/012v.c b/ffmpeg/libavcodec/012v.c new file mode 100644 index 0000000..58e3cd6 --- /dev/null +++ b/ffmpeg/libavcodec/012v.c @@ -0,0 +1,153 @@ +/* + * 012v decoder + * + * Copyright (C) 2012 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" + +static av_cold int zero12v_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV422P16; + avctx->bits_per_raw_sample = 10; + + if (avctx->codec_tag == MKTAG('a', '1', '2', 'v')) + avpriv_request_sample(avctx, "transparency"); + + return 0; +} + +static int zero12v_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + int line = 0, ret; + const int width = avctx->width; + AVFrame *pic = data; + uint16_t *y, *u, *v; + const uint8_t *line_end, *src = avpkt->data; + int stride = avctx->width * 8 / 3; + + if (width == 1) { + av_log(avctx, AV_LOG_ERROR, "Width 1 not supported.\n"); + return AVERROR_INVALIDDATA; + } + if (avpkt->size < avctx->height * stride) { + av_log(avctx, AV_LOG_ERROR, "Packet too small: %d instead of %d\n", + avpkt->size, avctx->height * stride); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + + y = (uint16_t *)pic->data[0]; + u = (uint16_t *)pic->data[1]; + v = (uint16_t *)pic->data[2]; + line_end = avpkt->data + stride; + + while (line++ < avctx->height) { + while (1) { + uint32_t t = AV_RL32(src); + src += 4; + *u++ = t << 6 & 0xFFC0; + *y++ = t >> 4 & 0xFFC0; + *v++ = t >> 14 & 0xFFC0; + + if (src >= line_end - 1) { + *y = 0x80; + src++; + line_end += stride; + y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]); + u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]); + v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]); + break; + } + + t = AV_RL32(src); + src += 4; + *y++ = t << 6 & 0xFFC0; + *u++ = t >> 4 & 0xFFC0; + *y++ = t >> 14 & 0xFFC0; + if (src >= line_end - 2) { + if (!(width & 1)) { + *y = 0x80; + src += 2; + } + line_end += stride; + y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]); + u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]); + v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]); + break; + } + + t = AV_RL32(src); + src += 4; + *v++ = t << 6 & 0xFFC0; + *y++ = t >> 4 & 0xFFC0; + *u++ = t >> 14 & 0xFFC0; + + if (src >= line_end - 1) { + *y = 0x80; + src++; + line_end += stride; + y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]); + u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]); + v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]); + break; + } + + t = AV_RL32(src); + src += 4; + *y++ = t << 6 & 0xFFC0; + *v++ = t >> 4 & 0xFFC0; + *y++ = t >> 14 & 0xFFC0; + + if (src >= line_end - 2) { + if (width & 1) { + *y = 0x80; + src += 2; + } + line_end += stride; + y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]); + u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]); + v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]); + break; + } + } + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_zero12v_decoder = { + .name = "012v", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_012V, + .init = zero12v_decode_init, + .decode = zero12v_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), +}; diff --git a/ffmpeg/libavcodec/4xm.c b/ffmpeg/libavcodec/4xm.c new file mode 100644 index 0000000..cd22aa4 --- /dev/null +++ b/ffmpeg/libavcodec/4xm.c @@ -0,0 +1,995 @@ +/* + * 4XM codec + * Copyright (c) 2003 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 + */ + +/** + * @file + * 4XM codec. + */ + +#include "libavutil/frame.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "dsputil.h" +#include "get_bits.h" +#include "internal.h" + +#include "libavutil/avassert.h" + +#define BLOCK_TYPE_VLC_BITS 5 +#define ACDC_VLC_BITS 9 + +#define CFRAME_BUFFER_COUNT 100 + +static const uint8_t block_type_tab[2][4][8][2] = { + { + { // { 8, 4, 2 } x { 8, 4, 2} + { 0, 1 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 30, 5 }, { 31, 5 }, { 0, 0 } + }, { // { 8, 4 } x 1 + { 0, 1 }, { 0, 0 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 }, { 0, 0 } + }, { // 1 x { 8, 4 } + { 0, 1 }, { 2, 2 }, { 0, 0 }, { 6, 3 }, { 14, 4 }, { 15, 4 }, { 0, 0 } + }, { // 1 x 2, 2 x 1 + { 0, 1 }, { 0, 0 }, { 0, 0 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 } + } + }, { + { // { 8, 4, 2 } x { 8, 4, 2} + { 1, 2 }, { 4, 3 }, { 5, 3 }, { 0, 2 }, { 6, 3 }, { 7, 3 }, { 0, 0 } + }, {// { 8, 4 } x 1 + { 1, 2 }, { 0, 0 }, { 2, 2 }, { 0, 2 }, { 6, 3 }, { 7, 3 }, { 0, 0 } + }, {// 1 x { 8, 4 } + { 1, 2 }, { 2, 2 }, { 0, 0 }, { 0, 2 }, { 6, 3 }, { 7, 3 }, { 0, 0 } + }, {// 1 x 2, 2 x 1 + { 1, 2 }, { 0, 0 }, { 0, 0 }, { 0, 2 }, { 2, 2 }, { 6, 3 }, { 7, 3 } + } + } +}; + +static const uint8_t size2index[4][4] = { + { -1, 3, 1, 1 }, + { 3, 0, 0, 0 }, + { 2, 0, 0, 0 }, + { 2, 0, 0, 0 }, +}; + +static const int8_t mv[256][2] = { + { 0, 0 }, { 0, -1 }, { -1, 0 }, { 1, 0 }, { 0, 1 }, { -1, -1 }, { 1, -1 }, { -1, 1 }, + { 1, 1 }, { 0, -2 }, { -2, 0 }, { 2, 0 }, { 0, 2 }, { -1, -2 }, { 1, -2 }, { -2, -1 }, + { 2, -1 }, { -2, 1 }, { 2, 1 }, { -1, 2 }, { 1, 2 }, { -2, -2 }, { 2, -2 }, { -2, 2 }, + { 2, 2 }, { 0, -3 }, { -3, 0 }, { 3, 0 }, { 0, 3 }, { -1, -3 }, { 1, -3 }, { -3, -1 }, + { 3, -1 }, { -3, 1 }, { 3, 1 }, { -1, 3 }, { 1, 3 }, { -2, -3 }, { 2, -3 }, { -3, -2 }, + { 3, -2 }, { -3, 2 }, { 3, 2 }, { -2, 3 }, { 2, 3 }, { 0, -4 }, { -4, 0 }, { 4, 0 }, + { 0, 4 }, { -1, -4 }, { 1, -4 }, { -4, -1 }, { 4, -1 }, { 4, 1 }, { -1, 4 }, { 1, 4 }, + { -3, -3 }, { -3, 3 }, { 3, 3 }, { -2, -4 }, { -4, -2 }, { 4, -2 }, { -4, 2 }, { -2, 4 }, + { 2, 4 }, { -3, -4 }, { 3, -4 }, { 4, -3 }, { -5, 0 }, { -4, 3 }, { -3, 4 }, { 3, 4 }, + { -1, -5 }, { -5, -1 }, { -5, 1 }, { -1, 5 }, { -2, -5 }, { 2, -5 }, { 5, -2 }, { 5, 2 }, + { -4, -4 }, { -4, 4 }, { -3, -5 }, { -5, -3 }, { -5, 3 }, { 3, 5 }, { -6, 0 }, { 0, 6 }, + { -6, -1 }, { -6, 1 }, { 1, 6 }, { 2, -6 }, { -6, 2 }, { 2, 6 }, { -5, -4 }, { 5, 4 }, + { 4, 5 }, { -6, -3 }, { 6, 3 }, { -7, 0 }, { -1, -7 }, { 5, -5 }, { -7, 1 }, { -1, 7 }, + { 4, -6 }, { 6, 4 }, { -2, -7 }, { -7, 2 }, { -3, -7 }, { 7, -3 }, { 3, 7 }, { 6, -5 }, + { 0, -8 }, { -1, -8 }, { -7, -4 }, { -8, 1 }, { 4, 7 }, { 2, -8 }, { -2, 8 }, { 6, 6 }, + { -8, 3 }, { 5, -7 }, { -5, 7 }, { 8, -4 }, { 0, -9 }, { -9, -1 }, { 1, 9 }, { 7, -6 }, + { -7, 6 }, { -5, -8 }, { -5, 8 }, { -9, 3 }, { 9, -4 }, { 7, -7 }, { 8, -6 }, { 6, 8 }, + { 10, 1 }, { -10, 2 }, { 9, -5 }, { 10, -3 }, { -8, -7 }, { -10, -4 }, { 6, -9 }, { -11, 0 }, + { 11, 1 }, { -11, -2 }, { -2, 11 }, { 7, -9 }, { -7, 9 }, { 10, 6 }, { -4, 11 }, { 8, -9 }, + { 8, 9 }, { 5, 11 }, { 7, -10 }, { 12, -3 }, { 11, 6 }, { -9, -9 }, { 8, 10 }, { 5, 12 }, + { -11, 7 }, { 13, 2 }, { 6, -12 }, { 10, 9 }, { -11, 8 }, { -7, 12 }, { 0, 14 }, { 14, -2 }, + { -9, 11 }, { -6, 13 }, { -14, -4 }, { -5, -14 }, { 5, 14 }, { -15, -1 }, { -14, -6 }, { 3, -15 }, + { 11, -11 }, { -7, 14 }, { -5, 15 }, { 8, -14 }, { 15, 6 }, { 3, 16 }, { 7, -15 }, { -16, 5 }, + { 0, 17 }, { -16, -6 }, { -10, 14 }, { -16, 7 }, { 12, 13 }, { -16, 8 }, { -17, 6 }, { -18, 3 }, + { -7, 17 }, { 15, 11 }, { 16, 10 }, { 2, -19 }, { 3, -19 }, { -11, -16 }, { -18, 8 }, { -19, -6 }, + { 2, -20 }, { -17, -11 }, { -10, -18 }, { 8, 19 }, { -21, -1 }, { -20, 7 }, { -4, 21 }, { 21, 5 }, + { 15, 16 }, { 2, -22 }, { -10, -20 }, { -22, 5 }, { 20, -11 }, { -7, -22 }, { -12, 20 }, { 23, -5 }, + { 13, -20 }, { 24, -2 }, { -15, 19 }, { -11, 22 }, { 16, 19 }, { 23, -10 }, { -18, -18 }, { -9, -24 }, + { 24, -10 }, { -3, 26 }, { -23, 13 }, { -18, -20 }, { 17, 21 }, { -4, 27 }, { 27, 6 }, { 1, -28 }, + { -11, 26 }, { -17, -23 }, { 7, 28 }, { 11, -27 }, { 29, 5 }, { -23, -19 }, { -28, -11 }, { -21, 22 }, + { -30, 7 }, { -17, 26 }, { -27, 16 }, { 13, 29 }, { 19, -26 }, { 10, -31 }, { -14, -30 }, { 20, -27 }, + { -29, 18 }, { -16, -31 }, { -28, -22 }, { 21, -30 }, { -25, 28 }, { 26, -29 }, { 25, -32 }, { -32, -32 } +}; + +/* This is simply the scaled down elementwise product of the standard JPEG + * quantizer table and the AAN premul table. */ +static const uint8_t dequant_table[64] = { + 16, 15, 13, 19, 24, 31, 28, 17, + 17, 23, 25, 31, 36, 63, 45, 21, + 18, 24, 27, 37, 52, 59, 49, 20, + 16, 28, 34, 40, 60, 80, 51, 20, + 18, 31, 48, 66, 68, 86, 56, 21, + 19, 38, 56, 59, 64, 64, 48, 20, + 27, 48, 55, 55, 56, 51, 35, 15, + 20, 35, 34, 32, 31, 22, 15, 8, +}; + +static VLC block_type_vlc[2][4]; + + +typedef struct CFrameBuffer { + unsigned int allocated_size; + unsigned int size; + int id; + uint8_t *data; +} CFrameBuffer; + +typedef struct FourXContext { + AVCodecContext *avctx; + DSPContext dsp; + AVFrame *current_picture, *last_picture; + GetBitContext pre_gb; ///< ac/dc prefix + GetBitContext gb; + GetByteContext g; + GetByteContext g2; + int mv[256]; + VLC pre_vlc; + int last_dc; + DECLARE_ALIGNED(16, int16_t, block)[6][64]; + void *bitstream_buffer; + unsigned int bitstream_buffer_size; + int version; + CFrameBuffer cfrm[CFRAME_BUFFER_COUNT]; +} FourXContext; + + +#define FIX_1_082392200 70936 +#define FIX_1_414213562 92682 +#define FIX_1_847759065 121095 +#define FIX_2_613125930 171254 + +#define MULTIPLY(var, const) (((var) * (const)) >> 16) + +static void idct(int16_t block[64]) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z5, z10, z11, z12, z13; + int i; + int temp[64]; + + for (i = 0; i < 8; i++) { + tmp10 = block[8 * 0 + i] + block[8 * 4 + i]; + tmp11 = block[8 * 0 + i] - block[8 * 4 + i]; + + tmp13 = block[8 * 2 + i] + block[8 * 6 + i]; + tmp12 = MULTIPLY(block[8 * 2 + i] - block[8 * 6 + i], FIX_1_414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + z13 = block[8 * 5 + i] + block[8 * 3 + i]; + z10 = block[8 * 5 + i] - block[8 * 3 + i]; + z11 = block[8 * 1 + i] + block[8 * 7 + i]; + z12 = block[8 * 1 + i] - block[8 * 7 + i]; + + tmp7 = z11 + z13; + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; + tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + temp[8 * 0 + i] = tmp0 + tmp7; + temp[8 * 7 + i] = tmp0 - tmp7; + temp[8 * 1 + i] = tmp1 + tmp6; + temp[8 * 6 + i] = tmp1 - tmp6; + temp[8 * 2 + i] = tmp2 + tmp5; + temp[8 * 5 + i] = tmp2 - tmp5; + temp[8 * 4 + i] = tmp3 + tmp4; + temp[8 * 3 + i] = tmp3 - tmp4; + } + + for (i = 0; i < 8 * 8; i += 8) { + tmp10 = temp[0 + i] + temp[4 + i]; + tmp11 = temp[0 + i] - temp[4 + i]; + + tmp13 = temp[2 + i] + temp[6 + i]; + tmp12 = MULTIPLY(temp[2 + i] - temp[6 + i], FIX_1_414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + z13 = temp[5 + i] + temp[3 + i]; + z10 = temp[5 + i] - temp[3 + i]; + z11 = temp[1 + i] + temp[7 + i]; + z12 = temp[1 + i] - temp[7 + i]; + + tmp7 = z11 + z13; + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; + tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + block[0 + i] = (tmp0 + tmp7) >> 6; + block[7 + i] = (tmp0 - tmp7) >> 6; + block[1 + i] = (tmp1 + tmp6) >> 6; + block[6 + i] = (tmp1 - tmp6) >> 6; + block[2 + i] = (tmp2 + tmp5) >> 6; + block[5 + i] = (tmp2 - tmp5) >> 6; + block[4 + i] = (tmp3 + tmp4) >> 6; + block[3 + i] = (tmp3 - tmp4) >> 6; + } +} + +static av_cold void init_vlcs(FourXContext *f) +{ + static VLC_TYPE table[2][4][32][2]; + int i, j; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + block_type_vlc[i][j].table = table[i][j]; + block_type_vlc[i][j].table_allocated = 32; + init_vlc(&block_type_vlc[i][j], BLOCK_TYPE_VLC_BITS, 7, + &block_type_tab[i][j][0][1], 2, 1, + &block_type_tab[i][j][0][0], 2, 1, + INIT_VLC_USE_NEW_STATIC); + } + } +} + +static void init_mv(FourXContext *f, int linesize) +{ + int i; + + for (i = 0; i < 256; i++) { + if (f->version > 1) + f->mv[i] = mv[i][0] + mv[i][1] * linesize / 2; + else + f->mv[i] = (i & 15) - 8 + ((i >> 4) - 8) * linesize / 2; + } +} + +#if HAVE_BIGENDIAN +#define LE_CENTRIC_MUL(dst, src, scale, dc) \ + { \ + unsigned tmpval = AV_RN32(src); \ + tmpval = (tmpval << 16) | (tmpval >> 16); \ + tmpval = tmpval * (scale) + (dc); \ + tmpval = (tmpval << 16) | (tmpval >> 16); \ + AV_WN32A(dst, tmpval); \ + } +#else +#define LE_CENTRIC_MUL(dst, src, scale, dc) \ + { \ + unsigned tmpval = AV_RN32(src) * (scale) + (dc); \ + AV_WN32A(dst, tmpval); \ + } +#endif + +static inline void mcdc(uint16_t *dst, const uint16_t *src, int log2w, + int h, int stride, int scale, unsigned dc) +{ + int i; + dc *= 0x10001; + + switch (log2w) { + case 0: + for (i = 0; i < h; i++) { + dst[0] = scale * src[0] + dc; + if (scale) + src += stride; + dst += stride; + } + break; + case 1: + for (i = 0; i < h; i++) { + LE_CENTRIC_MUL(dst, src, scale, dc); + if (scale) + src += stride; + dst += stride; + } + break; + case 2: + for (i = 0; i < h; i++) { + LE_CENTRIC_MUL(dst, src, scale, dc); + LE_CENTRIC_MUL(dst + 2, src + 2, scale, dc); + if (scale) + src += stride; + dst += stride; + } + break; + case 3: + for (i = 0; i < h; i++) { + LE_CENTRIC_MUL(dst, src, scale, dc); + LE_CENTRIC_MUL(dst + 2, src + 2, scale, dc); + LE_CENTRIC_MUL(dst + 4, src + 4, scale, dc); + LE_CENTRIC_MUL(dst + 6, src + 6, scale, dc); + if (scale) + src += stride; + dst += stride; + } + break; + default: + av_assert2(0); + } +} + +static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, + int log2w, int log2h, int stride) +{ + const int index = size2index[log2h][log2w]; + const int h = 1 << log2h; + int code = get_vlc2(&f->gb, + block_type_vlc[1 - (f->version > 1)][index].table, + BLOCK_TYPE_VLC_BITS, 1); + uint16_t *start = (uint16_t *)f->last_picture->data[0]; + uint16_t *end = start + stride * (f->avctx->height - h + 1) - (1 << log2w); + + av_assert2(code >= 0 && code <= 6); + + if (code == 0) { + if (bytestream2_get_bytes_left(&f->g) < 1) { + av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n"); + return; + } + src += f->mv[bytestream2_get_byteu(&f->g)]; + if (start > src || src > end) { + av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); + return; + } + mcdc(dst, src, log2w, h, stride, 1, 0); + } else if (code == 1) { + log2h--; + decode_p_block(f, dst, src, log2w, log2h, stride); + decode_p_block(f, dst + (stride << log2h), + src + (stride << log2h), log2w, log2h, stride); + } else if (code == 2) { + log2w--; + decode_p_block(f, dst , src, log2w, log2h, stride); + decode_p_block(f, dst + (1 << log2w), + src + (1 << log2w), log2w, log2h, stride); + } else if (code == 3 && f->version < 2) { + mcdc(dst, src, log2w, h, stride, 1, 0); + } else if (code == 4) { + if (bytestream2_get_bytes_left(&f->g) < 1) { + av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n"); + return; + } + src += f->mv[bytestream2_get_byteu(&f->g)]; + if (start > src || src > end) { + av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); + return; + } + if (bytestream2_get_bytes_left(&f->g2) < 2){ + av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n"); + return; + } + mcdc(dst, src, log2w, h, stride, 1, bytestream2_get_le16u(&f->g2)); + } else if (code == 5) { + if (bytestream2_get_bytes_left(&f->g2) < 2) { + av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n"); + return; + } + mcdc(dst, src, log2w, h, stride, 0, bytestream2_get_le16u(&f->g2)); + } else if (code == 6) { + if (bytestream2_get_bytes_left(&f->g2) < 4) { + av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n"); + return; + } + if (log2w) { + dst[0] = bytestream2_get_le16u(&f->g2); + dst[1] = bytestream2_get_le16u(&f->g2); + } else { + dst[0] = bytestream2_get_le16u(&f->g2); + dst[stride] = bytestream2_get_le16u(&f->g2); + } + } +} + +static int decode_p_frame(FourXContext *f, AVFrame *frame, + const uint8_t *buf, int length) +{ + int x, y; + const int width = f->avctx->width; + const int height = f->avctx->height; + uint16_t *src = (uint16_t *)f->last_picture->data[0]; + uint16_t *dst = (uint16_t *)frame->data[0]; + const int stride = frame->linesize[0] >> 1; + unsigned int bitstream_size, bytestream_size, wordstream_size, extra, + bytestream_offset, wordstream_offset; + + if (f->version > 1) { + extra = 20; + if (length < extra) + return -1; + bitstream_size = AV_RL32(buf + 8); + wordstream_size = AV_RL32(buf + 12); + bytestream_size = AV_RL32(buf + 16); + } else { + extra = 0; + bitstream_size = AV_RL16(buf - 4); + wordstream_size = AV_RL16(buf - 2); + bytestream_size = FFMAX(length - bitstream_size - wordstream_size, 0); + } + + if (bitstream_size > length || bitstream_size >= INT_MAX/8 || + bytestream_size > length - bitstream_size || + wordstream_size > length - bytestream_size - bitstream_size || + extra > length - bytestream_size - bitstream_size - wordstream_size) { + av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size, + bitstream_size+ bytestream_size+ wordstream_size - length); + return AVERROR_INVALIDDATA; + } + + av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, + bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!f->bitstream_buffer) + return AVERROR(ENOMEM); + f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)(buf + extra), + bitstream_size / 4); + memset((uint8_t*)f->bitstream_buffer + bitstream_size, + 0, FF_INPUT_BUFFER_PADDING_SIZE); + init_get_bits(&f->gb, f->bitstream_buffer, 8 * bitstream_size); + + wordstream_offset = extra + bitstream_size; + bytestream_offset = extra + bitstream_size + wordstream_size; + bytestream2_init(&f->g2, buf + wordstream_offset, + length - wordstream_offset); + bytestream2_init(&f->g, buf + bytestream_offset, + length - bytestream_offset); + + init_mv(f, frame->linesize[0]); + + for (y = 0; y < height; y += 8) { + for (x = 0; x < width; x += 8) + decode_p_block(f, dst + x, src + x, 3, 3, stride); + src += 8 * stride; + dst += 8 * stride; + } + + return 0; +} + +/** + * decode block and dequantize. + * Note this is almost identical to MJPEG. + */ +static int decode_i_block(FourXContext *f, int16_t *block) +{ + int code, i, j, level, val; + + if (get_bits_left(&f->gb) < 2){ + av_log(f->avctx, AV_LOG_ERROR, "%d bits left before decode_i_block()\n", get_bits_left(&f->gb)); + return -1; + } + + /* DC coef */ + val = get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3); + if (val >> 4) + av_log(f->avctx, AV_LOG_ERROR, "error dc run != 0\n"); + + if (val) + val = get_xbits(&f->gb, val); + + val = val * dequant_table[0] + f->last_dc; + f->last_dc = block[0] = val; + /* AC coefs */ + i = 1; + for (;;) { + code = get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3); + + /* EOB */ + if (code == 0) + break; + if (code == 0xf0) { + i += 16; + } else { + level = get_xbits(&f->gb, code & 0xf); + i += code >> 4; + if (i >= 64) { + av_log(f->avctx, AV_LOG_ERROR, "run %d oveflow\n", i); + return 0; + } + + j = ff_zigzag_direct[i]; + block[j] = level * dequant_table[j]; + i++; + if (i >= 64) + break; + } + } + + return 0; +} + +static inline void idct_put(FourXContext *f, AVFrame *frame, int x, int y) +{ + int16_t (*block)[64] = f->block; + int stride = frame->linesize[0] >> 1; + int i; + uint16_t *dst = ((uint16_t*)frame->data[0]) + y * stride + x; + + for (i = 0; i < 4; i++) { + block[i][0] += 0x80 * 8 * 8; + idct(block[i]); + } + + if (!(f->avctx->flags & CODEC_FLAG_GRAY)) { + for (i = 4; i < 6; i++) + idct(block[i]); + } + + /* Note transform is: + * y = ( 1b + 4g + 2r) / 14 + * cb = ( 3b - 2g - 1r) / 14 + * cr = (-1b - 4g + 5r) / 14 */ + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + int16_t *temp = block[(x >> 2) + 2 * (y >> 2)] + + 2 * (x & 3) + 2 * 8 * (y & 3); // FIXME optimize + int cb = block[4][x + 8 * y]; + int cr = block[5][x + 8 * y]; + int cg = (cb + cr) >> 1; + int y; + + cb += cb; + + y = temp[0]; + dst[0] = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8); + y = temp[1]; + dst[1] = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8); + y = temp[8]; + dst[stride] = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8); + y = temp[9]; + dst[1 + stride] = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8); + dst += 2; + } + dst += 2 * stride - 2 * 8; + } +} + +static int decode_i_mb(FourXContext *f) +{ + int ret; + int i; + + f->dsp.clear_blocks(f->block[0]); + + for (i = 0; i < 6; i++) + if ((ret = decode_i_block(f, f->block[i])) < 0) + return ret; + + return 0; +} + +static const uint8_t *read_huffman_tables(FourXContext *f, + const uint8_t * const buf, int buf_size) +{ + int frequency[512] = { 0 }; + uint8_t flag[512]; + int up[512]; + uint8_t len_tab[257]; + int bits_tab[257]; + int start, end; + const uint8_t *ptr = buf; + const uint8_t *ptr_end = buf + buf_size; + int j; + + memset(up, -1, sizeof(up)); + + start = *ptr++; + end = *ptr++; + for (;;) { + int i; + + if (ptr_end - ptr < FFMAX(end - start + 1, 0) + 1) { + av_log(f->avctx, AV_LOG_ERROR, "invalid data in read_huffman_tables\n"); + return NULL; + } + for (i = start; i <= end; i++) + frequency[i] = *ptr++; + start = *ptr++; + if (start == 0) + break; + + end = *ptr++; + } + frequency[256] = 1; + + while ((ptr - buf) & 3) + ptr++; // 4byte align + + if (ptr > ptr_end) { + av_log(f->avctx, AV_LOG_ERROR, "ptr overflow in read_huffman_tables\n"); + return NULL; + } + + for (j = 257; j < 512; j++) { + int min_freq[2] = { 256 * 256, 256 * 256 }; + int smallest[2] = { 0, 0 }; + int i; + for (i = 0; i < j; i++) { + if (frequency[i] == 0) + continue; + if (frequency[i] < min_freq[1]) { + if (frequency[i] < min_freq[0]) { + min_freq[1] = min_freq[0]; + smallest[1] = smallest[0]; + min_freq[0] = frequency[i]; + smallest[0] = i; + } else { + min_freq[1] = frequency[i]; + smallest[1] = i; + } + } + } + if (min_freq[1] == 256 * 256) + break; + + frequency[j] = min_freq[0] + min_freq[1]; + flag[smallest[0]] = 0; + flag[smallest[1]] = 1; + up[smallest[0]] = + up[smallest[1]] = j; + frequency[smallest[0]] = frequency[smallest[1]] = 0; + } + + for (j = 0; j < 257; j++) { + int node, len = 0, bits = 0; + + for (node = j; up[node] != -1; node = up[node]) { + bits += flag[node] << len; + len++; + if (len > 31) + // can this happen at all ? + av_log(f->avctx, AV_LOG_ERROR, + "vlc length overflow\n"); + } + + bits_tab[j] = bits; + len_tab[j] = len; + } + + if (init_vlc(&f->pre_vlc, ACDC_VLC_BITS, 257, len_tab, 1, 1, + bits_tab, 4, 4, 0)) + return NULL; + + return ptr; +} + +static int mix(int c0, int c1) +{ + int blue = 2 * (c0 & 0x001F) + (c1 & 0x001F); + int green = (2 * (c0 & 0x03E0) + (c1 & 0x03E0)) >> 5; + int red = 2 * (c0 >> 10) + (c1 >> 10); + return red / 3 * 1024 + green / 3 * 32 + blue / 3; +} + +static int decode_i2_frame(FourXContext *f, AVFrame *frame, const uint8_t *buf, int length) +{ + int x, y, x2, y2; + const int width = f->avctx->width; + const int height = f->avctx->height; + const int mbs = (FFALIGN(width, 16) >> 4) * (FFALIGN(height, 16) >> 4); + uint16_t *dst = (uint16_t*)frame->data[0]; + const int stride = frame->linesize[0]>>1; + const uint8_t *buf_end = buf + length; + GetByteContext g3; + + if (length < mbs * 8) { + av_log(f->avctx, AV_LOG_ERROR, "packet size too small\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_init(&g3, buf, length); + + for (y = 0; y < height; y += 16) { + for (x = 0; x < width; x += 16) { + unsigned int color[4] = { 0 }, bits; + if (buf_end - buf < 8) + return -1; + // warning following is purely guessed ... + color[0] = bytestream2_get_le16u(&g3); + color[1] = bytestream2_get_le16u(&g3); + + if (color[0] & 0x8000) + av_log(NULL, AV_LOG_ERROR, "unk bit 1\n"); + if (color[1] & 0x8000) + av_log(NULL, AV_LOG_ERROR, "unk bit 2\n"); + + color[2] = mix(color[0], color[1]); + color[3] = mix(color[1], color[0]); + + bits = bytestream2_get_le32u(&g3); + for (y2 = 0; y2 < 16; y2++) { + for (x2 = 0; x2 < 16; x2++) { + int index = 2 * (x2 >> 2) + 8 * (y2 >> 2); + dst[y2 * stride + x2] = color[(bits >> index) & 3]; + } + } + dst += 16; + } + dst += 16 * stride - x; + } + + return 0; +} + +static int decode_i_frame(FourXContext *f, AVFrame *frame, const uint8_t *buf, int length) +{ + int x, y, ret; + const int width = f->avctx->width; + const int height = f->avctx->height; + const unsigned int bitstream_size = AV_RL32(buf); + unsigned int prestream_size; + const uint8_t *prestream; + + if (bitstream_size > (1<<26) || length < bitstream_size + 12) { + av_log(f->avctx, AV_LOG_ERROR, "packet size too small\n"); + return AVERROR_INVALIDDATA; + } + + prestream_size = 4 * AV_RL32(buf + bitstream_size + 4); + prestream = buf + bitstream_size + 12; + + if (prestream_size + bitstream_size + 12 != length + || bitstream_size > (1 << 26) + || prestream_size > (1 << 26)) { + av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n", + prestream_size, bitstream_size, length); + return AVERROR_INVALIDDATA; + } + + prestream = read_huffman_tables(f, prestream, buf + length - prestream); + if (!prestream) { + av_log(f->avctx, AV_LOG_ERROR, "Error reading Huffman tables.\n"); + return AVERROR_INVALIDDATA; + } + + av_assert0(prestream <= buf + length); + + init_get_bits(&f->gb, buf + 4, 8 * bitstream_size); + + prestream_size = length + buf - prestream; + + av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size, + prestream_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!f->bitstream_buffer) + return AVERROR(ENOMEM); + f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)prestream, + prestream_size / 4); + memset((uint8_t*)f->bitstream_buffer + prestream_size, + 0, FF_INPUT_BUFFER_PADDING_SIZE); + init_get_bits(&f->pre_gb, f->bitstream_buffer, 8 * prestream_size); + + f->last_dc = 0 * 128 * 8 * 8; + + for (y = 0; y < height; y += 16) { + for (x = 0; x < width; x += 16) { + if ((ret = decode_i_mb(f)) < 0) + return ret; + + idct_put(f, frame, x, y); + } + } + + if (get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3) != 256) + av_log(f->avctx, AV_LOG_ERROR, "end mismatch\n"); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + FourXContext *const f = avctx->priv_data; + AVFrame *picture = data; + int i, frame_4cc, frame_size, ret; + + if (buf_size < 12) + return AVERROR_INVALIDDATA; + frame_4cc = AV_RL32(buf); + if (buf_size != AV_RL32(buf + 4) + 8 || buf_size < 20) + av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n", + buf_size, AV_RL32(buf + 4)); + + if (frame_4cc == AV_RL32("cfrm")) { + int free_index = -1; + const int data_size = buf_size - 20; + const int id = AV_RL32(buf + 12); + const int whole_size = AV_RL32(buf + 16); + CFrameBuffer *cfrm; + + if (data_size < 0 || whole_size < 0) { + av_log(f->avctx, AV_LOG_ERROR, "sizes invalid\n"); + return AVERROR_INVALIDDATA; + } + + if (f->version <= 1) { + av_log(f->avctx, AV_LOG_ERROR, "cfrm in version %d\n", f->version); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < CFRAME_BUFFER_COUNT; i++) + if (f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number) + av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n", + f->cfrm[i].id); + + for (i = 0; i < CFRAME_BUFFER_COUNT; i++) { + if (f->cfrm[i].id == id) + break; + if (f->cfrm[i].size == 0) + free_index = i; + } + + if (i >= CFRAME_BUFFER_COUNT) { + i = free_index; + f->cfrm[i].id = id; + } + cfrm = &f->cfrm[i]; + + if (data_size > UINT_MAX - cfrm->size - FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR_INVALIDDATA; + + cfrm->data = av_fast_realloc(cfrm->data, &cfrm->allocated_size, + cfrm->size + data_size + FF_INPUT_BUFFER_PADDING_SIZE); + // explicit check needed as memcpy below might not catch a NULL + if (!cfrm->data) { + av_log(f->avctx, AV_LOG_ERROR, "realloc failure\n"); + return AVERROR(ENOMEM); + } + + memcpy(cfrm->data + cfrm->size, buf + 20, data_size); + cfrm->size += data_size; + + if (cfrm->size >= whole_size) { + buf = cfrm->data; + frame_size = cfrm->size; + + if (id != avctx->frame_number) + av_log(f->avctx, AV_LOG_ERROR, "cframe id mismatch %d %d\n", + id, avctx->frame_number); + + cfrm->size = cfrm->id = 0; + frame_4cc = AV_RL32("pfrm"); + } else + return buf_size; + } else { + buf = buf + 12; + frame_size = buf_size - 12; + } + + FFSWAP(AVFrame*, f->current_picture, f->last_picture); + + // alternatively we would have to use our own buffer management + avctx->flags |= CODEC_FLAG_EMU_EDGE; + + if ((ret = ff_reget_buffer(avctx, f->current_picture)) < 0) + return ret; + + if (frame_4cc == AV_RL32("ifr2")) { + f->current_picture->pict_type = AV_PICTURE_TYPE_I; + if ((ret = decode_i2_frame(f, f->current_picture, buf - 4, frame_size + 4)) < 0) { + av_log(f->avctx, AV_LOG_ERROR, "decode i2 frame failed\n"); + return ret; + } + } else if (frame_4cc == AV_RL32("ifrm")) { + f->current_picture->pict_type = AV_PICTURE_TYPE_I; + if ((ret = decode_i_frame(f, f->current_picture, buf, frame_size)) < 0) { + av_log(f->avctx, AV_LOG_ERROR, "decode i frame failed\n"); + return ret; + } + } else if (frame_4cc == AV_RL32("pfrm") || frame_4cc == AV_RL32("pfr2")) { + if (!f->last_picture->data[0]) { + if ((ret = ff_get_buffer(avctx, f->last_picture, + AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + for (i=0; iheight; i++) + memset(f->last_picture->data[0] + i*f->last_picture->linesize[0], 0, 2*avctx->width); + } + + f->current_picture->pict_type = AV_PICTURE_TYPE_P; + if ((ret = decode_p_frame(f, f->current_picture, buf, frame_size)) < 0) { + av_log(f->avctx, AV_LOG_ERROR, "decode p frame failed\n"); + return ret; + } + } else if (frame_4cc == AV_RL32("snd_")) { + av_log(avctx, AV_LOG_ERROR, "ignoring snd_ chunk length:%d\n", + buf_size); + } else { + av_log(avctx, AV_LOG_ERROR, "ignoring unknown chunk length:%d\n", + buf_size); + } + + f->current_picture->key_frame = f->current_picture->pict_type == AV_PICTURE_TYPE_I; + + if ((ret = av_frame_ref(picture, f->current_picture)) < 0) + return ret; + *got_frame = 1; + + emms_c(); + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + FourXContext * const f = avctx->priv_data; + + if (avctx->extradata_size != 4 || !avctx->extradata) { + av_log(avctx, AV_LOG_ERROR, "extradata wrong or missing\n"); + return AVERROR_INVALIDDATA; + } + if((avctx->width % 16) || (avctx->height % 16)) { + av_log(avctx, AV_LOG_ERROR, "unsupported width/height\n"); + return AVERROR_INVALIDDATA; + } + + f->version = AV_RL32(avctx->extradata) >> 16; + ff_dsputil_init(&f->dsp, avctx); + f->avctx = avctx; + init_vlcs(f); + + if (f->version > 2) + avctx->pix_fmt = AV_PIX_FMT_RGB565; + else + avctx->pix_fmt = AV_PIX_FMT_BGR555; + + f->current_picture = av_frame_alloc(); + f->last_picture = av_frame_alloc(); + if (!f->current_picture || !f->last_picture) + return AVERROR(ENOMEM); + + return 0; +} + + +static av_cold int decode_end(AVCodecContext *avctx) +{ + FourXContext * const f = avctx->priv_data; + int i; + + av_freep(&f->bitstream_buffer); + f->bitstream_buffer_size = 0; + for (i = 0; i < CFRAME_BUFFER_COUNT; i++) { + av_freep(&f->cfrm[i].data); + f->cfrm[i].allocated_size = 0; + } + ff_free_vlc(&f->pre_vlc); + av_frame_free(&f->current_picture); + av_frame_free(&f->last_picture); + + return 0; +} + +AVCodec ff_fourxm_decoder = { + .name = "4xm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_4XM, + .priv_data_size = sizeof(FourXContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("4X Movie"), +}; diff --git a/ffmpeg/libavcodec/8bps.c b/ffmpeg/libavcodec/8bps.c new file mode 100644 index 0000000..a910551 --- /dev/null +++ b/ffmpeg/libavcodec/8bps.c @@ -0,0 +1,190 @@ +/* + * Quicktime Planar RGB (8BPS) Video Decoder + * Copyright (C) 2003 Roberto Togni + * + * 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 + */ + +/** + * @file + * QT 8BPS Video Decoder by Roberto Togni + * For more information about the 8BPS format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * Supports: PAL8 (RGB 8bpp, paletted) + * : BGR24 (RGB 24bpp) (can also output it as RGB32) + * : RGB32 (RGB 32bpp, 4th plane is alpha) + * + */ + +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + + +static const enum AVPixelFormat pixfmt_rgb24[] = { + AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE }; + +typedef struct EightBpsContext { + AVCodecContext *avctx; + + unsigned char planes; + unsigned char planemap[4]; + + uint32_t pal[256]; +} EightBpsContext; + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + EightBpsContext * const c = avctx->priv_data; + const unsigned char *encoded = buf; + unsigned char *pixptr, *pixptr_end; + unsigned int height = avctx->height; // Real image height + unsigned int dlen, p, row; + const unsigned char *lp, *dp; + unsigned char count; + unsigned int planes = c->planes; + unsigned char *planemap = c->planemap; + int ret; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + /* Set data pointer after line lengths */ + dp = encoded + planes * (height << 1); + + for (p = 0; p < planes; p++) { + /* Lines length pointer for this plane */ + lp = encoded + p * (height << 1); + + /* Decode a plane */ + for (row = 0; row < height; row++) { + pixptr = frame->data[0] + row * frame->linesize[0] + planemap[p]; + pixptr_end = pixptr + frame->linesize[0]; + if(lp - encoded + row*2 + 1 >= buf_size) + return -1; + dlen = av_be2ne16(*(const unsigned short *)(lp + row * 2)); + /* Decode a row of this plane */ + while (dlen > 0) { + if (dp + 1 >= buf + buf_size) + return AVERROR_INVALIDDATA; + if ((count = *dp++) <= 127) { + count++; + dlen -= count + 1; + if (pixptr + count * planes > pixptr_end) + break; + if (dp + count > buf + buf_size) + return AVERROR_INVALIDDATA; + while (count--) { + *pixptr = *dp++; + pixptr += planes; + } + } else { + count = 257 - count; + if (pixptr + count * planes > pixptr_end) + break; + while (count--) { + *pixptr = *dp; + pixptr += planes; + } + dp++; + dlen -= 2; + } + } + } + } + + if (avctx->bits_per_coded_sample <= 8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, + AV_PKT_DATA_PALETTE, + NULL); + if (pal) { + frame->palette_has_changed = 1; + memcpy(c->pal, pal, AVPALETTE_SIZE); + } + + memcpy (frame->data[1], c->pal, AVPALETTE_SIZE); + } + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + EightBpsContext * const c = avctx->priv_data; + + c->avctx = avctx; + + switch (avctx->bits_per_coded_sample) { + case 8: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + c->planes = 1; + c->planemap[0] = 0; // 1st plane is palette indexes + break; + case 24: + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_rgb24); + c->planes = 3; + c->planemap[0] = 2; // 1st plane is red + c->planemap[1] = 1; // 2nd plane is green + c->planemap[2] = 0; // 3rd plane is blue + break; + case 32: + avctx->pix_fmt = AV_PIX_FMT_RGB32; + c->planes = 4; +#if HAVE_BIGENDIAN + c->planemap[0] = 1; // 1st plane is red + c->planemap[1] = 2; // 2nd plane is green + c->planemap[2] = 3; // 3rd plane is blue + c->planemap[3] = 0; // 4th plane is alpha +#else + c->planemap[0] = 2; // 1st plane is red + c->planemap[1] = 1; // 2nd plane is green + c->planemap[2] = 0; // 3rd plane is blue + c->planemap[3] = 3; // 4th plane is alpha +#endif + break; + default: + av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n", + avctx->bits_per_coded_sample); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +AVCodec ff_eightbps_decoder = { + .name = "8bps", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_8BPS, + .priv_data_size = sizeof(EightBpsContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"), +}; diff --git a/ffmpeg/libavcodec/8svx.c b/ffmpeg/libavcodec/8svx.c new file mode 100644 index 0000000..82fda6f --- /dev/null +++ b/ffmpeg/libavcodec/8svx.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2008 Jaikrishnan Menon + * Copyright (C) 2011 Stefano Sabatini + * + * 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 + */ + +/** + * @file + * 8svx audio decoder + * @author Jaikrishnan Menon + * + * supports: fibonacci delta encoding + * : exponential encoding + * + * For more information about the 8SVX format: + * http://netghost.narod.ru/gff/vendspec/iff/iff.txt + * http://sox.sourceforge.net/AudioFormats-11.html + * http://aminet.net/package/mus/misc/wavepak + * http://amigan.1emu.net/reg/8SVX.txt + * + * Samples can be found here: + * http://aminet.net/mods/smpl/ + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +#include "libavutil/common.h" + +/** decoder context */ +typedef struct EightSvxContext { + uint8_t fib_acc[2]; + const int8_t *table; + + /* buffer used to store the whole first packet. + data is only sent as one large packet */ + uint8_t *data[2]; + int data_size; + int data_idx; +} EightSvxContext; + +static const int8_t fibonacci[16] = { -34, -21, -13, -8, -5, -3, -2, -1, 0, 1, 2, 3, 5, 8, 13, 21 }; +static const int8_t exponential[16] = { -128, -64, -32, -16, -8, -4, -2, -1, 0, 1, 2, 4, 8, 16, 32, 64 }; + +#define MAX_FRAME_SIZE 2048 + +/** + * Delta decode the compressed values in src, and put the resulting + * decoded samples in dst. + * + * @param[in,out] state starting value. it is saved for use in the next call. + * @param table delta sequence table + */ +static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size, + uint8_t *state, const int8_t *table) +{ + uint8_t val = *state; + + while (src_size--) { + uint8_t d = *src++; + val = av_clip_uint8(val + table[d & 0xF]); + *dst++ = val; + val = av_clip_uint8(val + table[d >> 4]); + *dst++ = val; + } + + *state = val; +} + +/** decode a frame */ +static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + EightSvxContext *esc = avctx->priv_data; + AVFrame *frame = data; + int buf_size; + int ch, ret; + int hdr_size = 2; + + /* decode and interleave the first packet */ + if (!esc->data[0] && avpkt) { + int chan_size = avpkt->size / avctx->channels - hdr_size; + + if (avpkt->size % avctx->channels) { + av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n"); + } + if (avpkt->size < (hdr_size + 1) * avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); + return AVERROR(EINVAL); + } + + esc->fib_acc[0] = avpkt->data[1] + 128; + if (avctx->channels == 2) + esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128; + + esc->data_idx = 0; + esc->data_size = chan_size; + if (!(esc->data[0] = av_malloc(chan_size))) + return AVERROR(ENOMEM); + if (avctx->channels == 2) { + if (!(esc->data[1] = av_malloc(chan_size))) { + av_freep(&esc->data[0]); + return AVERROR(ENOMEM); + } + } + memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size); + if (avctx->channels == 2) + memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size); + } + if (!esc->data[0]) { + av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n"); + return AVERROR(EINVAL); + } + + /* decode next piece of data from the buffer */ + buf_size = FFMIN(MAX_FRAME_SIZE, esc->data_size - esc->data_idx); + if (buf_size <= 0) { + *got_frame_ptr = 0; + return avpkt->size; + } + + /* get output buffer */ + frame->nb_samples = buf_size * 2; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (ch = 0; ch < avctx->channels; ch++) { + delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx], + buf_size, &esc->fib_acc[ch], esc->table); + } + + esc->data_idx += buf_size; + + *got_frame_ptr = 1; + + return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels; +} + +static av_cold int eightsvx_decode_init(AVCodecContext *avctx) +{ + EightSvxContext *esc = avctx->priv_data; + + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n"); + return AVERROR_INVALIDDATA; + } + + switch (avctx->codec->id) { + case AV_CODEC_ID_8SVX_FIB: esc->table = fibonacci; break; + case AV_CODEC_ID_8SVX_EXP: esc->table = exponential; break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid codec id %d.\n", avctx->codec->id); + return AVERROR_INVALIDDATA; + } + avctx->sample_fmt = AV_SAMPLE_FMT_U8P; + + return 0; +} + +static av_cold int eightsvx_decode_close(AVCodecContext *avctx) +{ + EightSvxContext *esc = avctx->priv_data; + + av_freep(&esc->data[0]); + av_freep(&esc->data[1]); + esc->data_size = 0; + esc->data_idx = 0; + + return 0; +} + +#if CONFIG_EIGHTSVX_FIB_DECODER +AVCodec ff_eightsvx_fib_decoder = { + .name = "8svx_fib", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_8SVX_FIB, + .priv_data_size = sizeof (EightSvxContext), + .init = eightsvx_decode_init, + .decode = eightsvx_decode_frame, + .close = eightsvx_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_EIGHTSVX_EXP_DECODER +AVCodec ff_eightsvx_exp_decoder = { + .name = "8svx_exp", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_8SVX_EXP, + .priv_data_size = sizeof (EightSvxContext), + .init = eightsvx_decode_init, + .decode = eightsvx_decode_frame, + .close = eightsvx_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_NONE }, +}; +#endif diff --git a/ffmpeg/libavcodec/Makefile b/ffmpeg/libavcodec/Makefile new file mode 100644 index 0000000..0d73067 --- /dev/null +++ b/ffmpeg/libavcodec/Makefile @@ -0,0 +1,862 @@ +include $(SUBDIR)../config.mak + +NAME = avcodec +FFLIBS = avutil + +HEADERS = avcodec.h \ + avfft.h \ + dxva2.h \ + old_codec_ids.h \ + vaapi.h \ + vda.h \ + vdpau.h \ + version.h \ + xvmc.h \ + +OBJS = allcodecs.o \ + audioconvert.o \ + avpacket.o \ + avpicture.o \ + bitstream.o \ + bitstream_filter.o \ + codec_desc.o \ + fmtconvert.o \ + imgconvert.o \ + mathtables.o \ + options.o \ + parser.o \ + raw.o \ + rawdec.o \ + resample.o \ + resample2.o \ + utils.o \ + +# parts needed for many different codecs +OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o +OBJS-$(CONFIG_AC3DSP) += ac3dsp.o +OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o +OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o +OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o +OBJS-$(CONFIG_DXVA2) += dxva2.o +OBJS-$(CONFIG_DSPUTIL) += dsputil.o faanidct.o \ + simple_idct.o \ + jrevdct.o +OBJS-$(CONFIG_ENCODERS) += faandct.o jfdctfst.o jfdctint.o +OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o +FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o cos_fixed_tables.o +OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.o \ + $(FFT-OBJS-yes) +OBJS-$(CONFIG_GOLOMB) += golomb.o +OBJS-$(CONFIG_H264CHROMA) += h264chroma.o +OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o +OBJS-$(CONFIG_H264PRED) += h264pred.o +OBJS-$(CONFIG_H264QPEL) += h264qpel.o +OBJS-$(CONFIG_HPELDSP) += hpeldsp.o +OBJS-$(CONFIG_HUFFMAN) += huffman.o +OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o +OBJS-$(CONFIG_LPC) += lpc.o +OBJS-$(CONFIG_LSP) += lsp.o +OBJS-$(CONFIG_MDCT) += mdct_fixed.o mdct_float.o +OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodata.o \ + mpegaudiodecheader.o +OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ + mpegaudiodsp_data.o \ + mpegaudiodsp_fixed.o \ + mpegaudiodsp_float.o +OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideo_motion.o +OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ + motion_est.o ratecontrol.o +OBJS-$(CONFIG_RANGECODER) += rangecoder.o +RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o +OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes) +OBJS-$(CONFIG_SHARED) += log2_tab.o +OBJS-$(CONFIG_SINEWIN) += sinewin.o +OBJS-$(CONFIG_VAAPI) += vaapi.o +OBJS-$(CONFIG_VDPAU) += vdpau.o +OBJS-$(CONFIG_VIDEODSP) += videodsp.o +OBJS-$(CONFIG_VP3DSP) += vp3dsp.o + +# decoders/encoders +OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o +OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o +OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o +OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps.o \ + aacadtsdec.o mpeg4audio.o kbdwin.o \ + sbrdsp.o aacpsdsp.o +OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \ + aacpsy.o aactab.o \ + psymodel.o iirfilter.o \ + mpeg4audio.o kbdwin.o +OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o +OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o kbdwin.o +OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \ + ac3.o kbdwin.o +OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o +OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o +OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o +OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mpeg4audio.o +OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ + celp_math.o acelp_filters.o \ + acelp_vectors.o \ + acelp_pitch_delay.o +OBJS-$(CONFIG_AMRWB_DECODER) += amrwbdec.o celp_filters.o \ + celp_math.o acelp_filters.o \ + acelp_vectors.o \ + acelp_pitch_delay.o +OBJS-$(CONFIG_AMV_DECODER) += sp5xdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpeg.o \ + mpegvideo_enc.o motion_est.o \ + ratecontrol.o mpeg12data.o \ + mpegvideo.o +OBJS-$(CONFIG_ANM_DECODER) += anm.o +OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o +OBJS-$(CONFIG_APE_DECODER) += apedec.o +OBJS-$(CONFIG_ASS_DECODER) += assdec.o ass.o ass_split.o +OBJS-$(CONFIG_ASS_ENCODER) += assenc.o ass.o +OBJS-$(CONFIG_ASV1_DECODER) += asvdec.o asv.o mpeg12data.o +OBJS-$(CONFIG_ASV1_ENCODER) += asvenc.o asv.o mpeg12data.o +OBJS-$(CONFIG_ASV2_DECODER) += asvdec.o asv.o mpeg12data.o +OBJS-$(CONFIG_ASV2_ENCODER) += asvenc.o asv.o mpeg12data.o +OBJS-$(CONFIG_ATRAC1_DECODER) += atrac1.o atrac.o +OBJS-$(CONFIG_ATRAC3_DECODER) += atrac3.o atrac.o +OBJS-$(CONFIG_AURA_DECODER) += cyuv.o +OBJS-$(CONFIG_AURA2_DECODER) += aura.o +OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o +OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o +OBJS-$(CONFIG_AVS_DECODER) += avs.o +OBJS-$(CONFIG_AVUI_DECODER) += avuidec.o +OBJS-$(CONFIG_AVUI_ENCODER) += avuienc.o +OBJS-$(CONFIG_AYUV_DECODER) += v408dec.o +OBJS-$(CONFIG_AYUV_ENCODER) += v408enc.o +OBJS-$(CONFIG_BETHSOFTVID_DECODER) += bethsoftvideo.o +OBJS-$(CONFIG_BFI_DECODER) += bfi.o +OBJS-$(CONFIG_BINK_DECODER) += bink.o binkdsp.o +OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o wma.o wma_common.o +OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o wma.o wma_common.o +OBJS-$(CONFIG_BINTEXT_DECODER) += bintext.o cga_data.o +OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o +OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o +OBJS-$(CONFIG_BMV_VIDEO_DECODER) += bmv.o +OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmv.o +OBJS-$(CONFIG_BRENDER_PIX_DECODER) += brender_pix.o +OBJS-$(CONFIG_C93_DECODER) += c93.o +OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ + cavsdata.o mpeg12data.o +OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o +OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o +OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o +OBJS-$(CONFIG_CLJR_DECODER) += cljr.o +OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o +OBJS-$(CONFIG_CLLC_DECODER) += cllc.o +OBJS-$(CONFIG_COOK_DECODER) += cook.o +OBJS-$(CONFIG_COMFORTNOISE_DECODER) += cngdec.o celp_filters.o +OBJS-$(CONFIG_COMFORTNOISE_ENCODER) += cngenc.o +OBJS-$(CONFIG_CPIA_DECODER) += cpia.o +OBJS-$(CONFIG_CSCD_DECODER) += cscd.o +OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o +OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadsp.o \ + dca_parser.o synth_filter.o +OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o +OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o \ + dirac_arith.o mpeg12data.o dirac_dwt.o +OBJS-$(CONFIG_DFA_DECODER) += dfa.o +OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o +OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o +OBJS-$(CONFIG_DPX_DECODER) += dpx.o +OBJS-$(CONFIG_DPX_ENCODER) += dpxenc.o +OBJS-$(CONFIG_DSICINAUDIO_DECODER) += dsicinav.o +OBJS-$(CONFIG_DSICINVIDEO_DECODER) += dsicinav.o +OBJS-$(CONFIG_DVBSUB_DECODER) += dvbsubdec.o +OBJS-$(CONFIG_DVBSUB_ENCODER) += dvbsub.o +OBJS-$(CONFIG_DVDSUB_DECODER) += dvdsubdec.o +OBJS-$(CONFIG_DVDSUB_ENCODER) += dvdsubenc.o +OBJS-$(CONFIG_DVVIDEO_DECODER) += dvdec.o dv.o dvdata.o dv_profile.o +OBJS-$(CONFIG_DVVIDEO_ENCODER) += dv.o dvdata.o dv_profile.o +OBJS-$(CONFIG_DXA_DECODER) += dxa.o +OBJS-$(CONFIG_DXTORY_DECODER) += dxtory.o +OBJS-$(CONFIG_EAC3_DECODER) += eac3dec.o eac3_data.o +OBJS-$(CONFIG_EAC3_ENCODER) += eac3enc.o eac3_data.o +OBJS-$(CONFIG_EACMV_DECODER) += eacmv.o +OBJS-$(CONFIG_EAMAD_DECODER) += eamad.o eaidct.o mpeg12.o \ + mpeg12data.o +OBJS-$(CONFIG_EATGQ_DECODER) += eatgq.o eaidct.o +OBJS-$(CONFIG_EATGV_DECODER) += eatgv.o +OBJS-$(CONFIG_EATQI_DECODER) += eatqi.o eaidct.o mpeg12.o \ + mpeg12data.o +OBJS-$(CONFIG_EIGHTBPS_DECODER) += 8bps.o +OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER) += 8svx.o +OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER) += 8svx.o +OBJS-$(CONFIG_ESCAPE124_DECODER) += escape124.o +OBJS-$(CONFIG_ESCAPE130_DECODER) += escape130.o +OBJS-$(CONFIG_EVRC_DECODER) += evrcdec.o acelp_vectors.o lsp.o +OBJS-$(CONFIG_EXR_DECODER) += exr.o +OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o +OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o +OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o huffyuvdec.o +OBJS-$(CONFIG_FFVHUFF_ENCODER) += huffyuv.o huffyuvenc.o +OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o +OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o flacdsp.o +OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o flacdsp.o vorbis_data.o +OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o +OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o +OBJS-$(CONFIG_FLASHSV2_ENCODER) += flashsv2enc.o +OBJS-$(CONFIG_FLASHSV2_DECODER) += flashsv.o +OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o +OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o +OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o +OBJS-$(CONFIG_FRWU_DECODER) += frwu.o +OBJS-$(CONFIG_G723_1_DECODER) += g723_1.o acelp_vectors.o \ + celp_filters.o celp_math.o +OBJS-$(CONFIG_G723_1_ENCODER) += g723_1.o acelp_vectors.o celp_math.o +OBJS-$(CONFIG_G729_DECODER) += g729dec.o lsp.o celp_math.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o +OBJS-$(CONFIG_GIF_DECODER) += gifdec.o lzw.o +OBJS-$(CONFIG_GIF_ENCODER) += gif.o lzwenc.o +OBJS-$(CONFIG_GSM_DECODER) += gsmdec.o gsmdec_data.o msgsmdec.o +OBJS-$(CONFIG_GSM_MS_DECODER) += gsmdec.o gsmdec_data.o msgsmdec.o +OBJS-$(CONFIG_H261_DECODER) += h261dec.o h261.o h261data.o +OBJS-$(CONFIG_H261_ENCODER) += h261enc.o h261.o h261data.o +OBJS-$(CONFIG_H263_DECODER) += h263dec.o h263.o ituh263dec.o \ + mpeg4video.o mpeg4videodec.o flvdec.o\ + intelh263dec.o +OBJS-$(CONFIG_H263_ENCODER) += mpeg4videoenc.o mpeg4video.o \ + h263.o ituh263enc.o flvenc.o +OBJS-$(CONFIG_H264_DECODER) += h264.o \ + h264_loopfilter.o h264_direct.o \ + cabac.o h264_sei.o h264_ps.o \ + h264_refs.o h264_cavlc.o h264_cabac.o +OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.o +OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o +OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o +OBJS-$(CONFIG_IAC_DECODER) += imc.o +OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o +OBJS-$(CONFIG_IDF_DECODER) += bintext.o cga_data.o +OBJS-$(CONFIG_IFF_BYTERUN1_DECODER) += iff.o +OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o +OBJS-$(CONFIG_IMC_DECODER) += imc.o +OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o +OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o +OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi_common.o ivi_dsp.o +OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi_common.o ivi_dsp.o +OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o +OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o +OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o +OBJS-$(CONFIG_JPEG2000_DECODER) += j2kdec.o mqcdec.o mqc.o j2k.o j2k_dwt.o +OBJS-$(CONFIG_JPEG2000_ENCODER) += j2kenc.o mqcenc.o mqc.o j2k.o j2k_dwt.o +OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o \ + mjpegdec.o mjpeg.o +OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o +OBJS-$(CONFIG_JV_DECODER) += jvdec.o +OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o +OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o +OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o +OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc.o mjpeg.o +OBJS-$(CONFIG_LOCO_DECODER) += loco.o +OBJS-$(CONFIG_MACE3_DECODER) += mace.o +OBJS-$(CONFIG_MACE6_DECODER) += mace.o +OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o +OBJS-$(CONFIG_MICRODVD_DECODER) += microdvddec.o ass.o +OBJS-$(CONFIG_MIMIC_DECODER) += mimic.o +OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpeg.o +OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpeg.o +OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o +OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o +OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o +OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o ass.o +OBJS-$(CONFIG_MOVTEXT_ENCODER) += movtextenc.o ass_split.o +OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec.o +OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o +OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec.o +OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc.o mpegaudio.o \ + mpegaudiodata.o mpegaudiodsp_data.o +OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o +OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec.o +OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec.o +OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o +OBJS-$(CONFIG_MP3FLOAT_DECODER) += mpegaudiodec_float.o +OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec.o mpeg4audio.o +OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o +OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o +OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o +OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12.o mpeg12data.o \ + mpegvideo.o error_resilience.o +OBJS-$(CONFIG_MPEG_XVMC_DECODER) += mpegvideo_xvmc.o +OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12.o mpeg12data.o +OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o \ + +OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12.o mpeg12data.o +OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o \ + timecode.o +OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o +OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4.o msmpeg4data.o +OBJS-$(CONFIG_MSMPEG4V2_DECODER) += msmpeg4.o msmpeg4data.o h263dec.o \ + h263.o ituh263dec.o mpeg4videodec.o +OBJS-$(CONFIG_MSMPEG4V2_ENCODER) += msmpeg4.o msmpeg4enc.o msmpeg4data.o \ + h263dec.o h263.o ituh263dec.o \ + mpeg4videodec.o +OBJS-$(CONFIG_MSMPEG4V3_DECODER) += msmpeg4.o msmpeg4data.o h263dec.o \ + h263.o ituh263dec.o mpeg4videodec.o +OBJS-$(CONFIG_MSMPEG4V3_ENCODER) += msmpeg4.o msmpeg4enc.o msmpeg4data.o \ + h263dec.o h263.o ituh263dec.o \ + mpeg4videodec.o +OBJS-$(CONFIG_MSRLE_DECODER) += msrle.o msrledec.o +OBJS-$(CONFIG_MSA1_DECODER) += mss3.o mss34dsp.o +OBJS-$(CONFIG_MSS1_DECODER) += mss1.o mss12.o +OBJS-$(CONFIG_MSS2_DECODER) += mss2.o mss12.o mss2dsp.o +OBJS-$(CONFIG_MSVIDEO1_DECODER) += msvideo1.o +OBJS-$(CONFIG_MSVIDEO1_ENCODER) += msvideo1enc.o elbg.o +OBJS-$(CONFIG_MSZH_DECODER) += lcldec.o +OBJS-$(CONFIG_MTS2_DECODER) += mss4.o mss34dsp.o +OBJS-$(CONFIG_MVC1_DECODER) += mvcdec.o +OBJS-$(CONFIG_MVC2_DECODER) += mvcdec.o +OBJS-$(CONFIG_MXPEG_DECODER) += mxpegdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_NELLYMOSER_DECODER) += nellymoserdec.o nellymoser.o +OBJS-$(CONFIG_NELLYMOSER_ENCODER) += nellymoserenc.o nellymoser.o +OBJS-$(CONFIG_NUV_DECODER) += nuv.o rtjpeg.o +OBJS-$(CONFIG_PAF_VIDEO_DECODER) += paf.o +OBJS-$(CONFIG_PAF_AUDIO_DECODER) += paf.o +OBJS-$(CONFIG_PAM_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PAM_ENCODER) += pamenc.o pnm.o +OBJS-$(CONFIG_PBM_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PBM_ENCODER) += pnmenc.o pnm.o +OBJS-$(CONFIG_PCX_DECODER) += pcx.o +OBJS-$(CONFIG_PCX_ENCODER) += pcxenc.o +OBJS-$(CONFIG_PGM_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PGM_ENCODER) += pnmenc.o pnm.o +OBJS-$(CONFIG_PGMYUV_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PGMYUV_ENCODER) += pnmenc.o pnm.o +OBJS-$(CONFIG_PGSSUB_DECODER) += pgssubdec.o +OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o +OBJS-$(CONFIG_PJS_DECODER) += textdec.o ass.o +OBJS-$(CONFIG_PNG_DECODER) += png.o pngdec.o pngdsp.o +OBJS-$(CONFIG_PNG_ENCODER) += png.o pngenc.o +OBJS-$(CONFIG_PPM_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PPM_ENCODER) += pnmenc.o pnm.o +OBJS-$(CONFIG_PRORES_DECODER) += proresdec2.o proresdsp.o +OBJS-$(CONFIG_PRORES_LGPL_DECODER) += proresdec_lgpl.o proresdsp.o proresdata.o +OBJS-$(CONFIG_PRORES_ENCODER) += proresenc_anatoliy.o +OBJS-$(CONFIG_PRORES_ANATOLIY_ENCODER) += proresenc_anatoliy.o +OBJS-$(CONFIG_PRORES_KOSTYA_ENCODER) += proresenc_kostya.o proresdata.o proresdsp.o +OBJS-$(CONFIG_PTX_DECODER) += ptx.o +OBJS-$(CONFIG_QCELP_DECODER) += qcelpdec.o \ + celp_filters.o acelp_vectors.o \ + acelp_filters.o +OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o +OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o +OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o +OBJS-$(CONFIG_QTRLE_DECODER) += qtrle.o +OBJS-$(CONFIG_QTRLE_ENCODER) += qtrleenc.o +OBJS-$(CONFIG_R10K_DECODER) += r210dec.o +OBJS-$(CONFIG_R10K_ENCODER) += r210enc.o +OBJS-$(CONFIG_R210_DECODER) += r210dec.o +OBJS-$(CONFIG_R210_ENCODER) += r210enc.o +OBJS-$(CONFIG_RA_144_DECODER) += ra144dec.o ra144.o celp_filters.o +OBJS-$(CONFIG_RA_144_ENCODER) += ra144enc.o ra144.o celp_filters.o +OBJS-$(CONFIG_RA_288_DECODER) += ra288.o celp_filters.o +OBJS-$(CONFIG_RALF_DECODER) += ralf.o +OBJS-$(CONFIG_RAWVIDEO_DECODER) += rawdec.o +OBJS-$(CONFIG_RAWVIDEO_ENCODER) += rawenc.o +OBJS-$(CONFIG_REALTEXT_DECODER) += realtextdec.o ass.o +OBJS-$(CONFIG_RL2_DECODER) += rl2.o +OBJS-$(CONFIG_ROQ_DECODER) += roqvideodec.o roqvideo.o +OBJS-$(CONFIG_ROQ_ENCODER) += roqvideoenc.o roqvideo.o elbg.o +OBJS-$(CONFIG_ROQ_DPCM_DECODER) += dpcm.o +OBJS-$(CONFIG_ROQ_DPCM_ENCODER) += roqaudioenc.o +OBJS-$(CONFIG_RPZA_DECODER) += rpza.o +OBJS-$(CONFIG_RV10_DECODER) += rv10.o +OBJS-$(CONFIG_RV10_ENCODER) += rv10enc.o +OBJS-$(CONFIG_RV20_DECODER) += rv10.o +OBJS-$(CONFIG_RV20_ENCODER) += rv20enc.o +OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o rv34dsp.o +OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv34dsp.o rv40dsp.o +OBJS-$(CONFIG_SAMI_DECODER) += samidec.o ass.o +OBJS-$(CONFIG_S302M_DECODER) += s302m.o +OBJS-$(CONFIG_SANM_DECODER) += sanm.o +OBJS-$(CONFIG_SGI_DECODER) += sgidec.o +OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o +OBJS-$(CONFIG_SGIRLE_DECODER) += sgirledec.o +OBJS-$(CONFIG_SHORTEN_DECODER) += shorten.o +OBJS-$(CONFIG_SIPR_DECODER) += sipr.o acelp_pitch_delay.o \ + celp_math.o acelp_vectors.o \ + acelp_filters.o celp_filters.o \ + sipr16k.o +OBJS-$(CONFIG_SMACKAUD_DECODER) += smacker.o +OBJS-$(CONFIG_SMACKER_DECODER) += smacker.o +OBJS-$(CONFIG_SMC_DECODER) += smc.o +OBJS-$(CONFIG_SNOW_DECODER) += snowdec.o snow.o snow_dwt.o +OBJS-$(CONFIG_SNOW_ENCODER) += snowenc.o snow.o snow_dwt.o \ + h263.o ituh263enc.o +OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o +OBJS-$(CONFIG_SONIC_DECODER) += sonic.o +OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o +OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o +OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o mjpegdec.o mjpeg.o +OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o +OBJS-$(CONFIG_SRT_ENCODER) += srtenc.o ass_split.o +OBJS-$(CONFIG_SUBRIP_DECODER) += srtdec.o ass.o +OBJS-$(CONFIG_SUBRIP_ENCODER) += srtenc.o ass_split.o +OBJS-$(CONFIG_SUBVIEWER1_DECODER) += textdec.o ass.o +OBJS-$(CONFIG_SUBVIEWER_DECODER) += subviewerdec.o ass.o +OBJS-$(CONFIG_SUNRAST_DECODER) += sunrast.o +OBJS-$(CONFIG_SUNRAST_ENCODER) += sunrastenc.o +OBJS-$(CONFIG_SVQ1_DECODER) += svq1dec.o svq1.o svq13.o h263.o +OBJS-$(CONFIG_SVQ1_ENCODER) += svq1enc.o svq1.o \ + h263.o ituh263enc.o +OBJS-$(CONFIG_SVQ3_DECODER) += svq3.o svq13.o h263.o h264.o \ + h264_loopfilter.o h264_direct.o \ + h264_sei.o h264_ps.o h264_refs.o \ + h264_cavlc.o h264_cabac.o cabac.o +OBJS-$(CONFIG_TEXT_DECODER) += textdec.o ass.o +OBJS-$(CONFIG_TAK_DECODER) += takdec.o tak.o +OBJS-$(CONFIG_TARGA_DECODER) += targa.o +OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o +OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o +OBJS-$(CONFIG_THEORA_DECODER) += xiph.o +OBJS-$(CONFIG_THP_DECODER) += mjpegdec.o mjpeg.o +OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o +OBJS-$(CONFIG_TIFF_DECODER) += tiff.o lzw.o faxcompr.o tiff_data.o +OBJS-$(CONFIG_TIFF_ENCODER) += tiffenc.o rle.o lzwenc.o tiff_data.o +OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o +OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o +OBJS-$(CONFIG_TRUEMOTION1_DECODER) += truemotion1.o +OBJS-$(CONFIG_TRUEMOTION2_DECODER) += truemotion2.o +OBJS-$(CONFIG_TRUESPEECH_DECODER) += truespeech.o +OBJS-$(CONFIG_TSCC_DECODER) += tscc.o msrledec.o +OBJS-$(CONFIG_TSCC2_DECODER) += tscc2.o +OBJS-$(CONFIG_TTA_DECODER) += tta.o +OBJS-$(CONFIG_TWINVQ_DECODER) += twinvq.o +OBJS-$(CONFIG_TXD_DECODER) += txd.o s3tc.o +OBJS-$(CONFIG_ULTI_DECODER) += ulti.o +OBJS-$(CONFIG_UTVIDEO_DECODER) += utvideodec.o utvideo.o +OBJS-$(CONFIG_UTVIDEO_ENCODER) += utvideoenc.o utvideo.o +OBJS-$(CONFIG_V210_DECODER) += v210dec.o +OBJS-$(CONFIG_V210_ENCODER) += v210enc.o +OBJS-$(CONFIG_V308_DECODER) += v308dec.o +OBJS-$(CONFIG_V308_ENCODER) += v308enc.o +OBJS-$(CONFIG_V408_DECODER) += v408dec.o +OBJS-$(CONFIG_V408_ENCODER) += v408enc.o +OBJS-$(CONFIG_V410_DECODER) += v410dec.o +OBJS-$(CONFIG_V410_ENCODER) += v410enc.o +OBJS-$(CONFIG_V210X_DECODER) += v210x.o +OBJS-$(CONFIG_VB_DECODER) += vb.o +OBJS-$(CONFIG_VBLE_DECODER) += vble.o +OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \ + msmpeg4.o msmpeg4data.o \ + intrax8.o intrax8dsp.o +OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o +OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o +OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o +OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o +OBJS-$(CONFIG_VORBIS_DECODER) += vorbisdec.o vorbisdsp.o vorbis.o \ + vorbis_data.o xiph.o +OBJS-$(CONFIG_VORBIS_ENCODER) += vorbisenc.o vorbis.o \ + vorbis_data.o +OBJS-$(CONFIG_VP3_DECODER) += vp3.o +OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \ + vp56rac.o +OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp56dsp.o \ + vp6dsp.o vp56rac.o +OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8dsp.o vp56rac.o +OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o +OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o +OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o +OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o +OBJS-$(CONFIG_WMALOSSLESS_DECODER) += wmalosslessdec.o wma_common.o +OBJS-$(CONFIG_WMAPRO_DECODER) += wmaprodec.o wma.o wma_common.o +OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o wma.o wma_common.o aactab.o +OBJS-$(CONFIG_WMAV1_ENCODER) += wmaenc.o wma.o wma_common.o aactab.o +OBJS-$(CONFIG_WMAV2_DECODER) += wmadec.o wma.o wma_common.o aactab.o +OBJS-$(CONFIG_WMAV2_ENCODER) += wmaenc.o wma.o wma_common.o aactab.o +OBJS-$(CONFIG_WMAVOICE_DECODER) += wmavoice.o \ + celp_filters.o \ + acelp_vectors.o acelp_filters.o +OBJS-$(CONFIG_WMV1_DECODER) += msmpeg4.o msmpeg4data.o +OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2dsp.o \ + msmpeg4.o msmpeg4data.o \ + intrax8.o intrax8dsp.o +OBJS-$(CONFIG_WMV2_ENCODER) += wmv2enc.o wmv2.o wmv2dsp.o \ + msmpeg4.o msmpeg4enc.o msmpeg4data.o \ + mpeg4videodec.o ituh263dec.o h263dec.o +OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o +OBJS-$(CONFIG_WS_SND1_DECODER) += ws-snd1.o +OBJS-$(CONFIG_XAN_DPCM_DECODER) += dpcm.o +OBJS-$(CONFIG_XAN_WC3_DECODER) += xan.o +OBJS-$(CONFIG_XAN_WC4_DECODER) += xxan.o +OBJS-$(CONFIG_XBIN_DECODER) += bintext.o cga_data.o +OBJS-$(CONFIG_XBM_DECODER) += xbmdec.o +OBJS-$(CONFIG_XBM_ENCODER) += xbmenc.o +OBJS-$(CONFIG_XFACE_DECODER) += xfacedec.o xface.o +OBJS-$(CONFIG_XFACE_ENCODER) += xfaceenc.o xface.o +OBJS-$(CONFIG_XL_DECODER) += xl.o +OBJS-$(CONFIG_XSUB_DECODER) += xsubdec.o +OBJS-$(CONFIG_XSUB_ENCODER) += xsubenc.o +OBJS-$(CONFIG_XWD_DECODER) += xwddec.o +OBJS-$(CONFIG_XWD_ENCODER) += xwdenc.o +OBJS-$(CONFIG_Y41P_DECODER) += y41pdec.o +OBJS-$(CONFIG_Y41P_ENCODER) += y41penc.o +OBJS-$(CONFIG_YOP_DECODER) += yop.o +OBJS-$(CONFIG_YUV4_DECODER) += yuv4dec.o +OBJS-$(CONFIG_YUV4_ENCODER) += yuv4enc.o +OBJS-$(CONFIG_ZEROCODEC_DECODER) += zerocodec.o +OBJS-$(CONFIG_ZLIB_DECODER) += lcldec.o +OBJS-$(CONFIG_ZLIB_ENCODER) += lclenc.o +OBJS-$(CONFIG_ZMBV_DECODER) += zmbv.o +OBJS-$(CONFIG_ZMBV_ENCODER) += zmbvenc.o + +# (AD)PCM decoders/encoders +OBJS-$(CONFIG_PCM_ALAW_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_ALAW_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_BLURAY_DECODER) += pcm-mpeg.o +OBJS-$(CONFIG_PCM_DVD_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_F32BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_F32BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_F32LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_F32LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_F64BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_F64BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_F64LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_F64LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_LXF_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S8_PLANAR_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S16BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S16BE_PLANAR_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S16BE_PLANAR_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S16LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S16LE_PLANAR_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S16LE_PLANAR_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S24BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S24BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S24DAUD_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S24DAUD_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S24LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S24LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S24LE_PLANAR_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S24LE_PLANAR_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S32BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S32BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S32LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S32LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S32LE_PLANAR_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_S32LE_PLANAR_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U8_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U8_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U16BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U16BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U16LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U16LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U24BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U24BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U24LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U24LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U32BE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U32BE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_U32LE_DECODER) += pcm.o +OBJS-$(CONFIG_PCM_U32LE_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_ZORK_DECODER) += pcm.o + +OBJS-$(CONFIG_ADPCM_4XM_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_ADX_DECODER) += adxdec.o adx.o +OBJS-$(CONFIG_ADPCM_ADX_ENCODER) += adxenc.o adx.o +OBJS-$(CONFIG_ADPCM_AFC_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_CT_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_EA_MAXIS_XA_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_EA_R1_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_EA_R2_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_EA_R3_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_EA_XAS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_G722_DECODER) += g722.o g722dec.o +OBJS-$(CONFIG_ADPCM_G722_ENCODER) += g722.o g722enc.o +OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o +OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o +OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_APC_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_EA_SEAD_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_ISS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_OKI_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_QT_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_QT_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_SMJPEG_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_WAV_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_WS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_MS_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_MS_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_SBPRO_2_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_SBPRO_3_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_SBPRO_4_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_SWF_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_SWF_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_THP_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_XA_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o +OBJS-$(CONFIG_VIMA_DECODER) += vima.o adpcm_data.o + +# hardware accelerators +OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o +OBJS-$(CONFIG_H263_VDPAU_HWACCEL) += vdpau_mpeg4.o +OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o +OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o +OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o +OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o +OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o +OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o +OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o +OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o +OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o +OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o +OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o +OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o +OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o + +# libavformat dependencies +OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o +OBJS-$(CONFIG_ADX_DEMUXER) += adx.o +OBJS-$(CONFIG_CAF_DEMUXER) += mpeg4audio.o mpegaudiodata.o \ + ac3tab.o +OBJS-$(CONFIG_DV_DEMUXER) += dv_profile.o +OBJS-$(CONFIG_DV_MUXER) += dv_profile.o timecode.o +OBJS-$(CONFIG_FLAC_DEMUXER) += flac.o flacdata.o vorbis_data.o \ + vorbis_parser.o xiph.o +OBJS-$(CONFIG_FLAC_MUXER) += flac.o flacdata.o vorbis_data.o +OBJS-$(CONFIG_FLV_DEMUXER) += mpeg4audio.o +OBJS-$(CONFIG_GXF_DEMUXER) += mpeg12data.o +OBJS-$(CONFIG_IFF_DEMUXER) += iff.o +OBJS-$(CONFIG_ISMV_MUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o +OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o vorbis_data.o \ + flac.o flacdata.o +OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o mpegaudiodata.o \ + flac.o flacdata.o vorbis_data.o xiph.o +OBJS-$(CONFIG_MP2_MUXER) += mpegaudiodata.o mpegaudiodecheader.o +OBJS-$(CONFIG_MP3_MUXER) += mpegaudiodata.o mpegaudiodecheader.o +OBJS-$(CONFIG_MOV_DEMUXER) += mpeg4audio.o mpegaudiodata.o ac3tab.o timecode.o +OBJS-$(CONFIG_MOV_MUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_MPEGTS_MUXER) += mpeg4audio.o +OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpeg4audio.o mpegaudiodata.o +OBJS-$(CONFIG_MXF_MUXER) += timecode.o dnxhddata.o +OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o +OBJS-$(CONFIG_OGG_DEMUXER) += xiph.o flac.o flacdata.o \ + mpeg12data.o vorbis_parser.o \ + dirac.o vorbis_data.o +OBJS-$(CONFIG_OGG_MUXER) += xiph.o flac.o flacdata.o \ + vorbis_data.o +OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o xiph.o +OBJS-$(CONFIG_RTPDEC) += mjpeg.o +OBJS-$(CONFIG_SPDIF_DEMUXER) += aacadtsdec.o mpeg4audio.o +OBJS-$(CONFIG_SPDIF_MUXER) += dca.o +OBJS-$(CONFIG_TAK_DEMUXER) += tak.o +OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o mpegaudiodata.o \ + xiph.o flac.o flacdata.o \ + vorbis_data.o +OBJS-$(CONFIG_WTV_DEMUXER) += mpeg4audio.o mpegaudiodata.o + +# external codec libraries +OBJS-$(CONFIG_LIBAACPLUS_ENCODER) += libaacplus.o +OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o +OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o +OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o +OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o +OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o +OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o +OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsm.o +OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o +OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o +OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o +OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o +OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o +OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o +OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o +OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o +OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \ + vorbis_data.o +OBJS-$(CONFIG_LIBOPUS_ENCODER) += libopusenc.o libopus.o \ + vorbis_data.o +OBJS-$(CONFIG_LIBSCHROEDINGER_DECODER) += libschroedingerdec.o \ + libschroedinger.o +OBJS-$(CONFIG_LIBSCHROEDINGER_ENCODER) += libschroedingerenc.o \ + libschroedinger.o +OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o +OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o +OBJS-$(CONFIG_LIBSTAGEFRIGHT_H264_DECODER)+= libstagefright.o +OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o +OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o +OBJS-$(CONFIG_LIBUTVIDEO_DECODER) += libutvideodec.o +OBJS-$(CONFIG_LIBUTVIDEO_ENCODER) += libutvideoenc.o +OBJS-$(CONFIG_LIBVO_AACENC_ENCODER) += libvo-aacenc.o mpeg4audio.o +OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o +OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o +OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o \ + vorbis_data.o vorbis_parser.o xiph.o +OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o +OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o +OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o +OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o +OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o +OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o +OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o + +# parsers +OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ + aacadtsdec.o mpeg4audio.o +OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o +OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \ + aac_ac3_parser.o +OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o +OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o +OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o +OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o +OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca.o +OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o +OBJS-$(CONFIG_DNXHD_PARSER) += dnxhd_parser.o +OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o +OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o +OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o +OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o \ + vorbis_data.o +OBJS-$(CONFIG_GSM_PARSER) += gsm_parser.o +OBJS-$(CONFIG_H261_PARSER) += h261_parser.o +OBJS-$(CONFIG_H263_PARSER) += h263_parser.o +OBJS-$(CONFIG_H264_PARSER) += h264_parser.o h264.o \ + cabac.o \ + h264_refs.o h264_sei.o h264_direct.o \ + h264_loopfilter.o h264_cabac.o \ + h264_cavlc.o h264_ps.o +OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o +OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o +OBJS-$(CONFIG_MPEG4VIDEO_PARSER) += mpeg4video_parser.o h263.o \ + mpeg4videodec.o mpeg4video.o \ + ituh263dec.o h263dec.o +OBJS-$(CONFIG_PNG_PARSER) += png_parser.o +OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o \ + mpegaudiodecheader.o mpegaudiodata.o +OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ + mpeg12.o mpeg12data.o +OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o +OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o +OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o +OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o +OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ + msmpeg4.o msmpeg4data.o mpeg4video.o \ + h263.o +OBJS-$(CONFIG_VORBIS_PARSER) += vorbis_parser.o xiph.o +OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o +OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o + +# bitstream filters +OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \ + mpeg4audio.o +OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o +OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o +OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o +OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o +OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o mjpeg.o +OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o +OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o +OBJS-$(CONFIG_MP3_HEADER_COMPRESS_BSF) += mp3_header_compress_bsf.o +OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \ + mpegaudiodata.o +OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o +OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o +OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o + +# thread libraries +OBJS-$(HAVE_PTHREADS) += pthread.o +OBJS-$(HAVE_W32THREADS) += pthread.o +OBJS-$(HAVE_OS2THREADS) += pthread.o + +OBJS-$(CONFIG_FRAME_THREAD_ENCODER) += frame_thread_encoder.o + +SKIPHEADERS += %_tablegen.h \ + %_tables.h \ + aac_tablegen_decl.h \ + fft-internal.h \ + old_codec_ids.h \ + tableprint.h \ + $(ARCH)/vp56_arith.h \ + +SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h +SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h +SKIPHEADERS-$(CONFIG_LIBUTVIDEO) += libutvideo.h +SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h +SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h +SKIPHEADERS-$(CONFIG_VDA) += vda.h +SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h +SKIPHEADERS-$(HAVE_OS2THREADS) += os2threads.h +SKIPHEADERS-$(HAVE_W32THREADS) += w32pthreads.h + +TESTPROGS = cabac \ + dct \ + fft \ + fft-fixed \ + golomb \ + iirfilter \ + imgconvert \ + rangecoder \ + snowenc \ + +TESTPROGS-$(HAVE_MMX) += motion +TESTOBJS = dctref.o + +TOOLS = fourcc2pixfmt + +HOSTPROGS = aac_tablegen \ + aacps_tablegen \ + cbrt_tablegen \ + cos_tablegen \ + dv_tablegen \ + motionpixels_tablegen \ + mpegaudio_tablegen \ + pcm_tablegen \ + qdm2_tablegen \ + sinewin_tablegen \ + +CLEANFILES = *_tables.c *_tables.h *_tablegen$(HOSTEXESUF) + +$(SUBDIR)dct-test$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o + +TRIG_TABLES = cos cos_fixed sin +TRIG_TABLES := $(TRIG_TABLES:%=$(SUBDIR)%_tables.c) + +$(TRIG_TABLES): $(SUBDIR)%_tables.c: $(SUBDIR)cos_tablegen$(HOSTEXESUF) + $(M)./$< $* > $@ + +ifdef CONFIG_SMALL +$(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=1 +else +$(SUBDIR)%_tablegen$(HOSTEXESUF): HOSTCFLAGS += -DCONFIG_SMALL=0 +endif + +GEN_HEADERS = cbrt_tables.h aacps_tables.h aac_tables.h dv_tables.h \ + sinewin_tables.h mpegaudio_tables.h motionpixels_tables.h \ + pcm_tables.h qdm2_tables.h +GEN_HEADERS := $(addprefix $(SUBDIR), $(GEN_HEADERS)) + +$(GEN_HEADERS): $(SUBDIR)%_tables.h: $(SUBDIR)%_tablegen$(HOSTEXESUF) + $(M)./$< > $@ + +ifdef CONFIG_HARDCODED_TABLES +$(SUBDIR)aacdec.o: $(SUBDIR)cbrt_tables.h +$(SUBDIR)aacps.o: $(SUBDIR)aacps_tables.h +$(SUBDIR)aactab.o: $(SUBDIR)aac_tables.h +$(SUBDIR)dv.o: $(SUBDIR)dv_tables.h +$(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h +$(SUBDIR)mpegaudiodec.o: $(SUBDIR)mpegaudio_tables.h +$(SUBDIR)mpegaudiodec_float.o: $(SUBDIR)mpegaudio_tables.h +$(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h +$(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h +$(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h +endif diff --git a/ffmpeg/libavcodec/a64colors.h b/ffmpeg/libavcodec/a64colors.h new file mode 100644 index 0000000..a9cdb6f --- /dev/null +++ b/ffmpeg/libavcodec/a64colors.h @@ -0,0 +1,52 @@ +/* + * a64 video encoder - c64 colors in rgb (Pepto) + * Copyright (c) 2009 Tobias Bindhammer + * + * 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 + */ + +/** + * @file + * a64 video encoder - c64 colors in rgb + */ + +#ifndef AVCODEC_A64COLORS_H +#define AVCODEC_A64COLORS_H + +#include + +/* c64 palette in RGB */ +static const uint8_t a64_palette[16][3] = { + {0x00, 0x00, 0x00}, + {0xff, 0xff, 0xff}, + {0x68, 0x37, 0x2b}, + {0x70, 0xa4, 0xb2}, + {0x6f, 0x3d, 0x86}, + {0x58, 0x8d, 0x43}, + {0x35, 0x28, 0x79}, + {0xb8, 0xc7, 0x6f}, + {0x6f, 0x4f, 0x25}, + {0x43, 0x39, 0x00}, + {0x9a, 0x67, 0x59}, + {0x44, 0x44, 0x44}, + {0x6c, 0x6c, 0x6c}, + {0x9a, 0xd2, 0x84}, + {0x6c, 0x5e, 0xb5}, + {0x95, 0x95, 0x95}, +}; + +#endif /* AVCODEC_A64COLORS_H */ diff --git a/ffmpeg/libavcodec/a64multienc.c b/ffmpeg/libavcodec/a64multienc.c new file mode 100644 index 0000000..eaf7b46 --- /dev/null +++ b/ffmpeg/libavcodec/a64multienc.c @@ -0,0 +1,423 @@ +/* + * a64 video encoder - multicolor modes + * Copyright (c) 2009 Tobias Bindhammer + * + * 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 + */ + +/** + * @file + * a64 video encoder - multicolor modes + */ + +#include "a64colors.h" +#include "a64tables.h" +#include "elbg.h" +#include "internal.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +#define DITHERSTEPS 8 +#define CHARSET_CHARS 256 +#define INTERLACED 1 +#define CROP_SCREENS 1 + +#define C64XRES 320 +#define C64YRES 200 + +typedef struct A64Context { + /* general variables */ + AVFrame picture; + + /* variables for multicolor modes */ + AVLFG randctx; + int mc_lifetime; + int mc_use_5col; + unsigned mc_frame_counter; + int *mc_meta_charset; + int *mc_charmap; + int *mc_best_cb; + int mc_luma_vals[5]; + uint8_t *mc_charset; + uint8_t *mc_colram; + uint8_t *mc_palette; + int mc_pal_size; + + /* pts of the next packet that will be output */ + int64_t next_pts; +} A64Context; + +/* gray gradient */ +static const int mc_colors[5]={0x0,0xb,0xc,0xf,0x1}; + +/* other possible gradients - to be tested */ +//static const int mc_colors[5]={0x0,0x8,0xa,0xf,0x7}; +//static const int mc_colors[5]={0x0,0x9,0x8,0xa,0x3}; + +static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest) +{ + int blockx, blocky, x, y; + int luma = 0; + int height = FFMIN(avctx->height, C64YRES); + int width = FFMIN(avctx->width , C64XRES); + uint8_t *src = p->data[0]; + + for (blocky = 0; blocky < C64YRES; blocky += 8) { + for (blockx = 0; blockx < C64XRES; blockx += 8) { + for (y = blocky; y < blocky + 8 && y < C64YRES; y++) { + for (x = blockx; x < blockx + 8 && x < C64XRES; x += 2) { + if(x < width && y < height) { + /* build average over 2 pixels */ + luma = (src[(x + 0 + y * p->linesize[0])] + + src[(x + 1 + y * p->linesize[0])]) / 2; + /* write blocks as linear data now so they are suitable for elbg */ + dest[0] = luma; + } + dest++; + } + } + } + } +} + +static void render_charset(AVCodecContext *avctx, uint8_t *charset, + uint8_t *colrammap) +{ + A64Context *c = avctx->priv_data; + uint8_t row1, row2; + int charpos, x, y; + int a, b; + uint8_t pix; + int lowdiff, highdiff; + int *best_cb = c->mc_best_cb; + static uint8_t index1[256]; + static uint8_t index2[256]; + static uint8_t dither[256]; + int i; + int distance; + + /* generate lookup-tables for dither and index before looping */ + i = 0; + for (a=0; a < 256; a++) { + if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i + 1]) { + distance = c->mc_luma_vals[i + 1] - c->mc_luma_vals[i]; + for(b = 0; b <= distance; b++) { + dither[c->mc_luma_vals[i] + b] = b * (DITHERSTEPS - 1) / distance; + } + i++; + } + if(i >= c->mc_pal_size - 1) dither[a] = 0; + index1[a] = i; + index2[a] = FFMIN(i + 1, c->mc_pal_size - 1); + } + + /* and render charset */ + for (charpos = 0; charpos < CHARSET_CHARS; charpos++) { + lowdiff = 0; + highdiff = 0; + for (y = 0; y < 8; y++) { + row1 = 0; row2 = 0; + for (x = 0; x < 4; x++) { + pix = best_cb[y * 4 + x]; + + /* accumulate error for brightest/darkest color */ + if (index1[pix] >= 3) + highdiff += pix - c->mc_luma_vals[3]; + if (index1[pix] < 1) + lowdiff += c->mc_luma_vals[1] - pix; + + row1 <<= 2; + + if (INTERLACED) { + row2 <<= 2; + if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 0][x & 3]) + row1 |= 3-(index2[pix] & 3); + else + row1 |= 3-(index1[pix] & 3); + + if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 1][x & 3]) + row2 |= 3-(index2[pix] & 3); + else + row2 |= 3-(index1[pix] & 3); + } + else { + if (multi_dither_patterns[dither[pix]][(y & 3)][x & 3]) + row1 |= 3-(index2[pix] & 3); + else + row1 |= 3-(index1[pix] & 3); + } + } + charset[y+0x000] = row1; + if (INTERLACED) charset[y+0x800] = row2; + } + /* do we need to adjust pixels? */ + if (highdiff > 0 && lowdiff > 0 && c->mc_use_5col) { + if (lowdiff > highdiff) { + for (x = 0; x < 32; x++) + best_cb[x] = FFMIN(c->mc_luma_vals[3], best_cb[x]); + } else { + for (x = 0; x < 32; x++) + best_cb[x] = FFMAX(c->mc_luma_vals[1], best_cb[x]); + } + charpos--; /* redo now adjusted char */ + /* no adjustment needed, all fine */ + } else { + /* advance pointers */ + best_cb += 32; + charset += 8; + + /* remember colorram value */ + colrammap[charpos] = (highdiff > 0); + } + } +} + +static av_cold int a64multi_close_encoder(AVCodecContext *avctx) +{ + A64Context *c = avctx->priv_data; + av_free(c->mc_meta_charset); + av_free(c->mc_best_cb); + av_free(c->mc_charset); + av_free(c->mc_charmap); + av_free(c->mc_colram); + return 0; +} + +static av_cold int a64multi_init_encoder(AVCodecContext *avctx) +{ + A64Context *c = avctx->priv_data; + int a; + av_lfg_init(&c->randctx, 1); + + if (avctx->global_quality < 1) { + c->mc_lifetime = 4; + } else { + c->mc_lifetime = avctx->global_quality /= FF_QP2LAMBDA; + } + + av_log(avctx, AV_LOG_INFO, "charset lifetime set to %d frame(s)\n", c->mc_lifetime); + + c->mc_frame_counter = 0; + c->mc_use_5col = avctx->codec->id == AV_CODEC_ID_A64_MULTI5; + c->mc_pal_size = 4 + c->mc_use_5col; + + /* precalc luma values for later use */ + for (a = 0; a < c->mc_pal_size; a++) { + c->mc_luma_vals[a]=a64_palette[mc_colors[a]][0] * 0.30 + + a64_palette[mc_colors[a]][1] * 0.59 + + a64_palette[mc_colors[a]][2] * 0.11; + } + + if (!(c->mc_meta_charset = av_malloc(32000 * c->mc_lifetime * sizeof(int))) || + !(c->mc_best_cb = av_malloc(CHARSET_CHARS * 32 * sizeof(int))) || + !(c->mc_charmap = av_mallocz(1000 * c->mc_lifetime * sizeof(int))) || + !(c->mc_colram = av_mallocz(CHARSET_CHARS * sizeof(uint8_t))) || + !(c->mc_charset = av_malloc(0x800 * (INTERLACED+1) * sizeof(uint8_t)))) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate buffer memory.\n"); + return AVERROR(ENOMEM); + } + + /* set up extradata */ + if (!(avctx->extradata = av_mallocz(8 * 4 + FF_INPUT_BUFFER_PADDING_SIZE))) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for extradata.\n"); + return AVERROR(ENOMEM); + } + avctx->extradata_size = 8 * 4; + AV_WB32(avctx->extradata, c->mc_lifetime); + AV_WB32(avctx->extradata + 16, INTERLACED); + + avcodec_get_frame_defaults(&c->picture); + avctx->coded_frame = &c->picture; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; + if (!avctx->codec_tag) + avctx->codec_tag = AV_RL32("a64m"); + + c->next_pts = AV_NOPTS_VALUE; + + return 0; +} + +static void a64_compress_colram(unsigned char *buf, int *charmap, uint8_t *colram) +{ + int a; + uint8_t temp; + /* only needs to be done in 5col mode */ + /* XXX could be squeezed to 0x80 bytes */ + for (a = 0; a < 256; a++) { + temp = colram[charmap[a + 0x000]] << 0; + temp |= colram[charmap[a + 0x100]] << 1; + temp |= colram[charmap[a + 0x200]] << 2; + if (a < 0xe8) temp |= colram[charmap[a + 0x300]] << 3; + buf[a] = temp << 2; + } +} + +static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + A64Context *c = avctx->priv_data; + AVFrame *const p = &c->picture; + + int frame; + int x, y; + int b_height; + int b_width; + + int req_size, ret; + uint8_t *buf = NULL; + + int *charmap = c->mc_charmap; + uint8_t *colram = c->mc_colram; + uint8_t *charset = c->mc_charset; + int *meta = c->mc_meta_charset; + int *best_cb = c->mc_best_cb; + + int charset_size = 0x800 * (INTERLACED + 1); + int colram_size = 0x100 * c->mc_use_5col; + int screen_size; + + if(CROP_SCREENS) { + b_height = FFMIN(avctx->height,C64YRES) >> 3; + b_width = FFMIN(avctx->width ,C64XRES) >> 3; + screen_size = b_width * b_height; + } else { + b_height = C64YRES >> 3; + b_width = C64XRES >> 3; + screen_size = 0x400; + } + + /* no data, means end encoding asap */ + if (!pict) { + /* all done, end encoding */ + if (!c->mc_lifetime) return 0; + /* no more frames in queue, prepare to flush remaining frames */ + if (!c->mc_frame_counter) { + c->mc_lifetime = 0; + } + /* still frames in queue so limit lifetime to remaining frames */ + else c->mc_lifetime = c->mc_frame_counter; + /* still new data available */ + } else { + /* fill up mc_meta_charset with data until lifetime exceeds */ + if (c->mc_frame_counter < c->mc_lifetime) { + *p = *pict; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + to_meta_with_crop(avctx, p, meta + 32000 * c->mc_frame_counter); + c->mc_frame_counter++; + if (c->next_pts == AV_NOPTS_VALUE) + c->next_pts = pict->pts; + /* lifetime is not reached so wait for next frame first */ + return 0; + } + } + + /* lifetime reached so now convert X frames at once */ + if (c->mc_frame_counter == c->mc_lifetime) { + req_size = 0; + /* any frames to encode? */ + if (c->mc_lifetime) { + req_size = charset_size + c->mc_lifetime*(screen_size + colram_size); + if ((ret = ff_alloc_packet2(avctx, pkt, req_size)) < 0) + return ret; + buf = pkt->data; + + /* calc optimal new charset + charmaps */ + ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); + ff_do_elbg (meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); + + /* create colorram map and a c64 readable charset */ + render_charset(avctx, charset, colram); + + /* copy charset to buf */ + memcpy(buf, charset, charset_size); + + /* advance pointers */ + buf += charset_size; + charset += charset_size; + } + + /* write x frames to buf */ + for (frame = 0; frame < c->mc_lifetime; frame++) { + /* copy charmap to buf. buf is uchar*, charmap is int*, so no memcpy here, sorry */ + for (y = 0; y < b_height; y++) { + for (x = 0; x < b_width; x++) { + buf[y * b_width + x] = charmap[y * b_width + x]; + } + } + /* advance pointers */ + buf += screen_size; + req_size += screen_size; + + /* compress and copy colram to buf */ + if (c->mc_use_5col) { + a64_compress_colram(buf, charmap, colram); + /* advance pointers */ + buf += colram_size; + req_size += colram_size; + } + + /* advance to next charmap */ + charmap += 1000; + } + + AV_WB32(avctx->extradata + 4, c->mc_frame_counter); + AV_WB32(avctx->extradata + 8, charset_size); + AV_WB32(avctx->extradata + 12, screen_size + colram_size); + + /* reset counter */ + c->mc_frame_counter = 0; + + pkt->pts = pkt->dts = c->next_pts; + c->next_pts = AV_NOPTS_VALUE; + + pkt->size = req_size; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = !!req_size; + } + return 0; +} + +#if CONFIG_A64MULTI_ENCODER +AVCodec ff_a64multi_encoder = { + .name = "a64multi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_A64_MULTI, + .priv_data_size = sizeof(A64Context), + .init = a64multi_init_encoder, + .encode2 = a64multi_encode_frame, + .close = a64multi_close_encoder, + .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"), + .capabilities = CODEC_CAP_DELAY, +}; +#endif +#if CONFIG_A64MULTI5_ENCODER +AVCodec ff_a64multi5_encoder = { + .name = "a64multi5", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_A64_MULTI5, + .priv_data_size = sizeof(A64Context), + .init = a64multi_init_encoder, + .encode2 = a64multi_encode_frame, + .close = a64multi_close_encoder, + .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"), + .capabilities = CODEC_CAP_DELAY, +}; +#endif diff --git a/ffmpeg/libavcodec/a64tables.h b/ffmpeg/libavcodec/a64tables.h new file mode 100644 index 0000000..a955ef4 --- /dev/null +++ b/ffmpeg/libavcodec/a64tables.h @@ -0,0 +1,150 @@ +/* + * a64 video encoder - tables used by a64 encoders + * Copyright (c) 2009 Tobias Bindhammer + * + * 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 + */ + +/** + * @file + * a64 video encoder - tables used by a64 encoders + */ + +#ifndef AVCODEC_A64TABLES_H +#define AVCODEC_A64TABLES_H + +#include + +/** + * dither patterns used vor rendering the multicolor charset + */ + +static const uint8_t multi_dither_patterns[9][4][4] = { + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + }, + { + {1, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 0} + }, + { + {1, 0, 0, 0}, + {0, 0, 1, 0}, + {0, 1, 0, 0}, + {0, 0, 0, 1} + }, + { + {1, 0, 0, 0}, + {0, 1, 0, 1}, + {0, 0, 1, 0}, + {0, 1, 0, 1} + }, + { + {1, 0, 1, 0}, + {0, 1, 0, 1}, + {1, 0, 1, 0}, + {0, 1, 0, 1} + }, + { + {1, 1, 1, 0}, + {0, 1, 0, 1}, + {1, 0, 1, 1}, + {0, 1, 0, 1} + }, + { + {0, 1, 1, 1}, + {1, 1, 0, 1}, + {1, 0, 1, 1}, + {1, 1, 1, 0} + }, + { + {0, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 0, 1}, + {1, 1, 1, 1} + }, + { + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1}, + {1, 1, 1, 1} + }, +}; + +static const uint8_t interlaced_dither_patterns[9][8][4] = { + { + {0, 0, 0, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, + }, + { + {1, 0, 1, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, + {1, 0, 1, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, + }, + { + {1, 0, 1, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 1, 0, 1}, + {1, 0, 1, 0}, {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 1, 0, 1}, + }, + { + {1, 0, 1, 0}, {0, 1, 0, 1}, + {0, 1, 0, 1}, {0, 0, 0, 0}, + {1, 0, 1, 0}, {0, 1, 0, 1}, + {0, 1, 0, 1}, {0, 0, 0, 0}, + }, + { + {1, 0, 1, 0}, {0, 1, 0, 1}, + {0, 1, 0, 1}, {1, 0, 1, 0}, + {1, 0, 1, 0}, {0, 1, 0, 1}, + {0, 1, 0, 1}, {1, 0, 1, 0}, + }, + { + {1, 0, 1, 0}, {0, 1, 0, 1}, + {1, 1, 1, 1}, {1, 0, 1, 0}, + {1, 0, 1, 0}, {0, 1, 0, 1}, + {1, 1, 1, 1}, {1, 0, 1, 0}, + }, + { + {1, 0, 1, 0}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {0, 1, 0, 1}, + {1, 0, 1, 0}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {0, 1, 0, 1}, + }, + { + {1, 1, 1, 1}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {0, 1, 0, 1}, + {1, 1, 1, 1}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {0, 1, 0, 1}, + }, + { + {1, 1, 1, 1}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {1, 1, 1, 1}, + {1, 1, 1, 1}, {1, 1, 1, 1}, + } +}; + +#endif /* AVCODEC_A64TABLES_H */ diff --git a/ffmpeg/libavcodec/aac.h b/ffmpeg/libavcodec/aac.h new file mode 100644 index 0000000..d586e27 --- /dev/null +++ b/ffmpeg/libavcodec/aac.h @@ -0,0 +1,333 @@ +/* + * AAC definitions and structures + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * + * 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 + */ + +/** + * @file + * AAC definitions and structures + * @author Oded Shimon ( ods15 ods15 dyndns org ) + * @author Maxim Gavrilov ( maxim.gavrilov gmail com ) + */ + +#ifndef AVCODEC_AAC_H +#define AVCODEC_AAC_H + +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "fft.h" +#include "mpeg4audio.h" +#include "sbr.h" +#include "fmtconvert.h" + +#include + +#define MAX_CHANNELS 64 +#define MAX_ELEM_ID 16 + +#define TNS_MAX_ORDER 20 +#define MAX_LTP_LONG_SFB 40 + +enum RawDataBlockType { + TYPE_SCE, + TYPE_CPE, + TYPE_CCE, + TYPE_LFE, + TYPE_DSE, + TYPE_PCE, + TYPE_FIL, + TYPE_END, +}; + +enum ExtensionPayloadID { + EXT_FILL, + EXT_FILL_DATA, + EXT_DATA_ELEMENT, + EXT_DYNAMIC_RANGE = 0xb, + EXT_SBR_DATA = 0xd, + EXT_SBR_DATA_CRC = 0xe, +}; + +enum WindowSequence { + ONLY_LONG_SEQUENCE, + LONG_START_SEQUENCE, + EIGHT_SHORT_SEQUENCE, + LONG_STOP_SEQUENCE, +}; + +enum BandType { + ZERO_BT = 0, ///< Scalefactors and spectral data are all zero. + FIRST_PAIR_BT = 5, ///< This and later band types encode two values (rather than four) with one code word. + ESC_BT = 11, ///< Spectral data are coded with an escape sequence. + NOISE_BT = 13, ///< Spectral data are scaled white noise not coded in the bitstream. + INTENSITY_BT2 = 14, ///< Scalefactor data are intensity stereo positions. + INTENSITY_BT = 15, ///< Scalefactor data are intensity stereo positions. +}; + +#define IS_CODEBOOK_UNSIGNED(x) ((x - 1) & 10) + +enum ChannelPosition { + AAC_CHANNEL_OFF = 0, + AAC_CHANNEL_FRONT = 1, + AAC_CHANNEL_SIDE = 2, + AAC_CHANNEL_BACK = 3, + AAC_CHANNEL_LFE = 4, + AAC_CHANNEL_CC = 5, +}; + +/** + * The point during decoding at which channel coupling is applied. + */ +enum CouplingPoint { + BEFORE_TNS, + BETWEEN_TNS_AND_IMDCT, + AFTER_IMDCT = 3, +}; + +/** + * Output configuration status + */ +enum OCStatus { + OC_NONE, ///< Output unconfigured + OC_TRIAL_PCE, ///< Output configuration under trial specified by an inband PCE + OC_TRIAL_FRAME, ///< Output configuration under trial specified by a frame header + OC_GLOBAL_HDR, ///< Output configuration set in a global header but not yet locked + OC_LOCKED, ///< Output configuration locked in place +}; + +typedef struct OutputConfiguration { + MPEG4AudioConfig m4ac; + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + int channels; + uint64_t channel_layout; + enum OCStatus status; +} OutputConfiguration; + +/** + * Predictor State + */ +typedef struct PredictorState { + float cor0; + float cor1; + float var0; + float var1; + float r0; + float r1; +} PredictorState; + +#define MAX_PREDICTORS 672 + +#define SCALE_DIV_512 36 ///< scalefactor difference that corresponds to scale difference in 512 times +#define SCALE_ONE_POS 140 ///< scalefactor index that corresponds to scale=1.0 +#define SCALE_MAX_POS 255 ///< scalefactor index maximum value +#define SCALE_MAX_DIFF 60 ///< maximum scalefactor difference allowed by standard +#define SCALE_DIFF_ZERO 60 ///< codebook index corresponding to zero scalefactor indices difference + +/** + * Long Term Prediction + */ +typedef struct LongTermPrediction { + int8_t present; + int16_t lag; + float coef; + int8_t used[MAX_LTP_LONG_SFB]; +} LongTermPrediction; + +/** + * Individual Channel Stream + */ +typedef struct IndividualChannelStream { + uint8_t max_sfb; ///< number of scalefactor bands per group + enum WindowSequence window_sequence[2]; + uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sinus window. + int num_window_groups; + uint8_t group_len[8]; + LongTermPrediction ltp; + const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window + const uint8_t *swb_sizes; ///< table of scalefactor band sizes for a particular window + int num_swb; ///< number of scalefactor window bands + int num_windows; + int tns_max_bands; + int predictor_present; + int predictor_initialized; + int predictor_reset_group; + uint8_t prediction_used[41]; +} IndividualChannelStream; + +/** + * Temporal Noise Shaping + */ +typedef struct TemporalNoiseShaping { + int present; + int n_filt[8]; + int length[8][4]; + int direction[8][4]; + int order[8][4]; + float coef[8][4][TNS_MAX_ORDER]; +} TemporalNoiseShaping; + +/** + * Dynamic Range Control - decoded from the bitstream but not processed further. + */ +typedef struct DynamicRangeControl { + int pce_instance_tag; ///< Indicates with which program the DRC info is associated. + int dyn_rng_sgn[17]; ///< DRC sign information; 0 - positive, 1 - negative + int dyn_rng_ctl[17]; ///< DRC magnitude information + int exclude_mask[MAX_CHANNELS]; ///< Channels to be excluded from DRC processing. + int band_incr; ///< Number of DRC bands greater than 1 having DRC info. + int interpolation_scheme; ///< Indicates the interpolation scheme used in the SBR QMF domain. + int band_top[17]; ///< Indicates the top of the i-th DRC band in units of 4 spectral lines. + int prog_ref_level; /**< A reference level for the long-term program audio level for all + * channels combined. + */ +} DynamicRangeControl; + +typedef struct Pulse { + int num_pulse; + int start; + int pos[4]; + int amp[4]; +} Pulse; + +/** + * coupling parameters + */ +typedef struct ChannelCoupling { + enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied. + int num_coupled; ///< number of target elements + enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE. + int id_select[8]; ///< element id + int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel; + * [2] list of gains for left channel; [3] lists of gains for both channels + */ + float gain[16][120]; +} ChannelCoupling; + +/** + * Single Channel Element - used for both SCE and LFE elements. + */ +typedef struct SingleChannelElement { + IndividualChannelStream ics; + TemporalNoiseShaping tns; + Pulse pulse; + enum BandType band_type[128]; ///< band types + int band_type_run_end[120]; ///< band type run end points + float sf[120]; ///< scalefactors + int sf_idx[128]; ///< scalefactor indices (used by encoder) + uint8_t zeroes[128]; ///< band is not coded (used by encoder) + DECLARE_ALIGNED(32, float, coeffs)[1024]; ///< coefficients for IMDCT + DECLARE_ALIGNED(32, float, saved)[1024]; ///< overlap + DECLARE_ALIGNED(32, float, ret_buf)[2048]; ///< PCM output buffer + DECLARE_ALIGNED(16, float, ltp_state)[3072]; ///< time signal for LTP + PredictorState predictor_state[MAX_PREDICTORS]; + float *ret; ///< PCM output +} SingleChannelElement; + +/** + * channel element - generic struct for SCE/CPE/CCE/LFE + */ +typedef struct ChannelElement { + // CPE specific + int common_window; ///< Set if channels share a common 'IndividualChannelStream' in bitstream. + int ms_mode; ///< Signals mid/side stereo flags coding mode (used by encoder) + uint8_t ms_mask[128]; ///< Set if mid/side stereo is used for each scalefactor window band + // shared + SingleChannelElement ch[2]; + // CCE specific + ChannelCoupling coup; + SpectralBandReplication sbr; +} ChannelElement; + +/** + * main AAC context + */ +struct AACContext { + AVClass *class; + AVCodecContext *avctx; + AVFrame *frame; + + int is_saved; ///< Set if elements have stored overlap from previous frame. + DynamicRangeControl che_drc; + + /** + * @name Channel element related data + * @{ + */ + ChannelElement *che[4][MAX_ELEM_ID]; + ChannelElement *tag_che_map[4][MAX_ELEM_ID]; + int tags_mapped; + /** @} */ + + /** + * @name temporary aligned temporary buffers + * (We do not want to have these on the stack.) + * @{ + */ + DECLARE_ALIGNED(32, float, buf_mdct)[1024]; + /** @} */ + + /** + * @name Computed / set up during initialization + * @{ + */ + FFTContext mdct; + FFTContext mdct_small; + FFTContext mdct_ltp; + FmtConvertContext fmt_conv; + AVFloatDSPContext fdsp; + int random_state; + /** @} */ + + /** + * @name Members used for output + * @{ + */ + SingleChannelElement *output_element[MAX_CHANNELS]; ///< Points to each SingleChannelElement + /** @} */ + + + /** + * @name Japanese DTV specific extension + * @{ + */ + int force_dmono_mode;///< 0->not dmono, 1->use first channel, 2->use second channel + int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel + /** @} */ + + DECLARE_ALIGNED(32, float, temp)[128]; + + OutputConfiguration oc[2]; + int warned_num_aac_frames; + + /* aacdec functions pointers */ + void (*imdct_and_windowing)(AACContext *ac, SingleChannelElement *sce); + void (*apply_ltp)(AACContext *ac, SingleChannelElement *sce); + void (*apply_tns)(float coef[1024], TemporalNoiseShaping *tns, + IndividualChannelStream *ics, int decode); + void (*windowing_and_mdct_ltp)(AACContext *ac, float *out, + float *in, IndividualChannelStream *ics); + void (*update_ltp)(AACContext *ac, SingleChannelElement *sce); + +}; + +void ff_aacdec_init_mips(AACContext *c); + +#endif /* AVCODEC_AAC_H */ diff --git a/ffmpeg/libavcodec/aac_ac3_parser.c b/ffmpeg/libavcodec/aac_ac3_parser.c new file mode 100644 index 0000000..6f1e188 --- /dev/null +++ b/ffmpeg/libavcodec/aac_ac3_parser.c @@ -0,0 +1,104 @@ +/* + * Common AAC and AC-3 parser + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 "libavutil/common.h" +#include "parser.h" +#include "aac_ac3_parser.h" + +int ff_aac_ac3_parse(AVCodecParserContext *s1, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + AACAC3ParseContext *s = s1->priv_data; + ParseContext *pc = &s->pc; + int len, i; + int new_frame_start; + +get_next: + i=END_NOT_FOUND; + if(s->remaining_size <= buf_size){ + if(s->remaining_size && !s->need_next_header){ + i= s->remaining_size; + s->remaining_size = 0; + }else{ //we need a header first + len=0; + for(i=s->remaining_size; istate = (s->state<<8) + buf[i]; + if((len=s->sync(s->state, s, &s->need_next_header, &new_frame_start))) + break; + } + if(len<=0){ + i=END_NOT_FOUND; + }else{ + s->state=0; + i-= s->header_size -1; + s->remaining_size = len; + if(!new_frame_start || pc->index+i<=0){ + s->remaining_size += i; + goto get_next; + } + } + } + } + + if(ff_combine_frame(pc, i, &buf, &buf_size)<0){ + s->remaining_size -= FFMIN(s->remaining_size, buf_size); + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + /* update codec info */ + if(s->codec_id) + avctx->codec_id = s->codec_id; + + /* Due to backwards compatible HE-AAC the sample rate, channel count, + and total number of samples found in an AAC ADTS header are not + reliable. Bit rate is still accurate because the total frame duration in + seconds is still correct (as is the number of bits in the frame). */ + if (avctx->codec_id != AV_CODEC_ID_AAC) { + avctx->sample_rate = s->sample_rate; + + /* allow downmixing to stereo (or mono for AC-3) */ + if(avctx->request_channels > 0 && + avctx->request_channels < s->channels && + (avctx->request_channels <= 2 || + (avctx->request_channels == 1 && + (avctx->codec_id == AV_CODEC_ID_AC3 || + avctx->codec_id == AV_CODEC_ID_EAC3)))) { + avctx->channels = avctx->request_channels; + } else { + avctx->channels = s->channels; + avctx->channel_layout = s->channel_layout; + } + s1->duration = s->samples; + avctx->audio_service_type = s->service_type; + } + + avctx->bit_rate = s->bit_rate; + + return i; +} diff --git a/ffmpeg/libavcodec/aac_ac3_parser.h b/ffmpeg/libavcodec/aac_ac3_parser.h new file mode 100644 index 0000000..ca49d2f --- /dev/null +++ b/ffmpeg/libavcodec/aac_ac3_parser.h @@ -0,0 +1,66 @@ +/* + * Common AAC and AC-3 parser prototypes + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 + */ + +#ifndef AVCODEC_AAC_AC3_PARSER_H +#define AVCODEC_AAC_AC3_PARSER_H + +#include +#include "avcodec.h" +#include "parser.h" + +typedef enum { + AAC_AC3_PARSE_ERROR_SYNC = -1, + AAC_AC3_PARSE_ERROR_BSID = -2, + AAC_AC3_PARSE_ERROR_SAMPLE_RATE = -3, + AAC_AC3_PARSE_ERROR_FRAME_SIZE = -4, + AAC_AC3_PARSE_ERROR_FRAME_TYPE = -5, + AAC_AC3_PARSE_ERROR_CRC = -6, + AAC_AC3_PARSE_ERROR_CHANNEL_CFG = -7, +} AACAC3ParseError; + +typedef struct AACAC3ParseContext { + ParseContext pc; + int frame_size; + int header_size; + int (*sync)(uint64_t state, struct AACAC3ParseContext *hdr_info, + int *need_next_header, int *new_frame_start); + + int channels; + int sample_rate; + int bit_rate; + int samples; + uint64_t channel_layout; + int service_type; + + int remaining_size; + uint64_t state; + + int need_next_header; + enum AVCodecID codec_id; +} AACAC3ParseContext; + +int ff_aac_ac3_parse(AVCodecParserContext *s1, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + +#endif /* AVCODEC_AAC_AC3_PARSER_H */ diff --git a/ffmpeg/libavcodec/aac_adtstoasc_bsf.c b/ffmpeg/libavcodec/aac_adtstoasc_bsf.c new file mode 100644 index 0000000..c7d7b3a --- /dev/null +++ b/ffmpeg/libavcodec/aac_adtstoasc_bsf.c @@ -0,0 +1,118 @@ +/* + * MPEG-2/4 AAC ADTS to MPEG-4 Audio Specific Configuration bitstream filter + * Copyright (c) 2009 Alex Converse + * + * 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 "avcodec.h" +#include "aacadtsdec.h" +#include "put_bits.h" +#include "get_bits.h" +#include "mpeg4audio.h" +#include "internal.h" + +typedef struct AACBSFContext { + int first_frame_done; +} AACBSFContext; + +/** + * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 + * ADTS header and removes the ADTS header. + */ +static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int keyframe) +{ + GetBitContext gb; + PutBitContext pb; + AACADTSHeaderInfo hdr; + + AACBSFContext *ctx = bsfc->priv_data; + + init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8); + + *poutbuf = (uint8_t*) buf; + *poutbuf_size = buf_size; + + if (avctx->extradata) + if (show_bits(&gb, 12) != 0xfff) + return 0; + + if (avpriv_aac_parse_header(&gb, &hdr) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n"); + return -1; + } + + if (!hdr.crc_absent && hdr.num_aac_frames > 1) { + avpriv_report_missing_feature(avctx, + "Multiple RDBs per frame with CRC"); + return AVERROR_PATCHWELCOME; + } + + buf += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; + buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent; + + if (!ctx->first_frame_done) { + int pce_size = 0; + uint8_t pce_data[MAX_PCE_SIZE]; + if (!hdr.chan_config) { + init_get_bits(&gb, buf, buf_size * 8); + if (get_bits(&gb, 3) != 5) { + avpriv_report_missing_feature(avctx, + "PCE-based channel configuration " + "without PCE as first syntax " + "element"); + return AVERROR_PATCHWELCOME; + } + init_put_bits(&pb, pce_data, MAX_PCE_SIZE); + pce_size = avpriv_copy_pce_data(&pb, &gb)/8; + flush_put_bits(&pb); + buf_size -= get_bits_count(&gb)/8; + buf += get_bits_count(&gb)/8; + } + avctx->extradata_size = 2 + pce_size; + avctx->extradata = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + + init_put_bits(&pb, avctx->extradata, avctx->extradata_size); + put_bits(&pb, 5, hdr.object_type); + put_bits(&pb, 4, hdr.sampling_index); + put_bits(&pb, 4, hdr.chan_config); + put_bits(&pb, 1, 0); //frame length - 1024 samples + put_bits(&pb, 1, 0); //does not depend on core coder + put_bits(&pb, 1, 0); //is not extension + flush_put_bits(&pb); + if (pce_size) { + memcpy(avctx->extradata + 2, pce_data, pce_size); + } + + ctx->first_frame_done = 1; + } + + *poutbuf = (uint8_t*) buf; + *poutbuf_size = buf_size; + + return 0; +} + +AVBitStreamFilter ff_aac_adtstoasc_bsf = { + "aac_adtstoasc", + sizeof(AACBSFContext), + aac_adtstoasc_filter, +}; diff --git a/ffmpeg/libavcodec/aac_parser.c b/ffmpeg/libavcodec/aac_parser.c new file mode 100644 index 0000000..ab6ca4e --- /dev/null +++ b/ffmpeg/libavcodec/aac_parser.c @@ -0,0 +1,69 @@ +/* + * Audio and Video frame extraction + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 "parser.h" +#include "aac_ac3_parser.h" +#include "aacadtsdec.h" +#include "get_bits.h" +#include "mpeg4audio.h" + +static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info, + int *need_next_header, int *new_frame_start) +{ + GetBitContext bits; + AACADTSHeaderInfo hdr; + int size; + union { + uint64_t u64; + uint8_t u8[8]; + } tmp; + + tmp.u64 = av_be2ne64(state); + init_get_bits(&bits, tmp.u8+8-AAC_ADTS_HEADER_SIZE, AAC_ADTS_HEADER_SIZE * 8); + + if ((size = avpriv_aac_parse_header(&bits, &hdr)) < 0) + return 0; + *need_next_header = 0; + *new_frame_start = 1; + hdr_info->sample_rate = hdr.sample_rate; + hdr_info->channels = ff_mpeg4audio_channels[hdr.chan_config]; + hdr_info->samples = hdr.samples; + hdr_info->bit_rate = hdr.bit_rate; + return size; +} + +static av_cold int aac_parse_init(AVCodecParserContext *s1) +{ + AACAC3ParseContext *s = s1->priv_data; + s->header_size = AAC_ADTS_HEADER_SIZE; + s->sync = aac_sync; + return 0; +} + + +AVCodecParser ff_aac_parser = { + .codec_ids = { AV_CODEC_ID_AAC }, + .priv_data_size = sizeof(AACAC3ParseContext), + .parser_init = aac_parse_init, + .parser_parse = ff_aac_ac3_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/aac_tablegen.c b/ffmpeg/libavcodec/aac_tablegen.c new file mode 100644 index 0000000..33a179f --- /dev/null +++ b/ffmpeg/libavcodec/aac_tablegen.c @@ -0,0 +1,37 @@ +/* + * Generate a header file for hardcoded AAC tables + * + * Copyright (c) 2010 Alex Converse + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#include "aac_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + ff_aac_tableinit(); + + write_fileheader(); + + WRITE_ARRAY("const", float, ff_aac_pow2sf_tab); + + return 0; +} diff --git a/ffmpeg/libavcodec/aac_tablegen.h b/ffmpeg/libavcodec/aac_tablegen.h new file mode 100644 index 0000000..2b080ba --- /dev/null +++ b/ffmpeg/libavcodec/aac_tablegen.h @@ -0,0 +1,42 @@ +/* + * Header file for hardcoded AAC tables + * + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +#ifndef AVCODEC_AAC_TABLEGEN_H +#define AVCODEC_AAC_TABLEGEN_H + +#include "aac_tablegen_decl.h" + +#if CONFIG_HARDCODED_TABLES +#include "libavcodec/aac_tables.h" +#else +#include "libavutil/mathematics.h" +float ff_aac_pow2sf_tab[428]; + +void ff_aac_tableinit(void) +{ + int i; + for (i = 0; i < 428; i++) + ff_aac_pow2sf_tab[i] = pow(2, (i - POW_SF2_ZERO) / 4.); +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_AAC_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/aac_tablegen_decl.h b/ffmpeg/libavcodec/aac_tablegen_decl.h new file mode 100644 index 0000000..5105dae --- /dev/null +++ b/ffmpeg/libavcodec/aac_tablegen_decl.h @@ -0,0 +1,36 @@ +/* + * Header file for hardcoded AAC tables + * + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +#ifndef AVCODEC_AAC_TABLEGEN_DECL_H +#define AVCODEC_AAC_TABLEGEN_DECL_H + +#define POW_SF2_ZERO 200 ///< ff_aac_pow2sf_tab index corresponding to pow(2, 0); + +#if CONFIG_HARDCODED_TABLES +#define ff_aac_tableinit() +extern const float ff_aac_pow2sf_tab[428]; +#else +void ff_aac_tableinit(void); +extern float ff_aac_pow2sf_tab[428]; +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_AAC_TABLEGEN_DECL_H */ diff --git a/ffmpeg/libavcodec/aacadtsdec.c b/ffmpeg/libavcodec/aacadtsdec.c new file mode 100644 index 0000000..c9718c4 --- /dev/null +++ b/ffmpeg/libavcodec/aacadtsdec.c @@ -0,0 +1,70 @@ +/* + * Audio and Video frame extraction + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2009 Alex Converse + * + * 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 "aac_ac3_parser.h" +#include "aacadtsdec.h" +#include "get_bits.h" +#include "mpeg4audio.h" + +int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr) +{ + int size, rdb, ch, sr; + int aot, crc_abs; + + if(get_bits(gbc, 12) != 0xfff) + return AAC_AC3_PARSE_ERROR_SYNC; + + skip_bits1(gbc); /* id */ + skip_bits(gbc, 2); /* layer */ + crc_abs = get_bits1(gbc); /* protection_absent */ + aot = get_bits(gbc, 2); /* profile_objecttype */ + sr = get_bits(gbc, 4); /* sample_frequency_index */ + if(!avpriv_mpeg4audio_sample_rates[sr]) + return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; + skip_bits1(gbc); /* private_bit */ + ch = get_bits(gbc, 3); /* channel_configuration */ + + skip_bits1(gbc); /* original/copy */ + skip_bits1(gbc); /* home */ + + /* adts_variable_header */ + skip_bits1(gbc); /* copyright_identification_bit */ + skip_bits1(gbc); /* copyright_identification_start */ + size = get_bits(gbc, 13); /* aac_frame_length */ + if(size < AAC_ADTS_HEADER_SIZE) + return AAC_AC3_PARSE_ERROR_FRAME_SIZE; + + skip_bits(gbc, 11); /* adts_buffer_fullness */ + rdb = get_bits(gbc, 2); /* number_of_raw_data_blocks_in_frame */ + + hdr->object_type = aot + 1; + hdr->chan_config = ch; + hdr->crc_absent = crc_abs; + hdr->num_aac_frames = rdb + 1; + hdr->sampling_index = sr; + hdr->sample_rate = avpriv_mpeg4audio_sample_rates[sr]; + hdr->samples = (rdb + 1) * 1024; + hdr->bit_rate = size * 8 * hdr->sample_rate / hdr->samples; + + return size; +} diff --git a/ffmpeg/libavcodec/aacadtsdec.h b/ffmpeg/libavcodec/aacadtsdec.h new file mode 100644 index 0000000..d0584ef --- /dev/null +++ b/ffmpeg/libavcodec/aacadtsdec.h @@ -0,0 +1,54 @@ +/* + * AAC ADTS header decoding prototypes and structures + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 + */ + +#ifndef AVCODEC_AACADTSDEC_H +#define AVCODEC_AACADTSDEC_H + +#include +#include "get_bits.h" + +#define AAC_ADTS_HEADER_SIZE 7 + +typedef struct AACADTSHeaderInfo { + uint32_t sample_rate; + uint32_t samples; + uint32_t bit_rate; + uint8_t crc_absent; + uint8_t object_type; + uint8_t sampling_index; + uint8_t chan_config; + uint8_t num_aac_frames; +} AACADTSHeaderInfo; + +/** + * Parse AAC frame header. + * Parse the ADTS frame header to the end of the variable header, which is + * the first 54 bits. + * @param[in] gbc BitContext containing the first 54 bits of the frame. + * @param[out] hdr Pointer to struct where header info is written. + * @return Returns 0 on success, -1 if there is a sync word mismatch, + * -2 if the version element is invalid, -3 if the sample rate + * element is invalid, or -4 if the bit rate element is invalid. + */ +int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr); + +#endif /* AVCODEC_AACADTSDEC_H */ diff --git a/ffmpeg/libavcodec/aaccoder.c b/ffmpeg/libavcodec/aaccoder.c new file mode 100644 index 0000000..994de28 --- /dev/null +++ b/ffmpeg/libavcodec/aaccoder.c @@ -0,0 +1,1140 @@ +/* + * AAC coefficients encoder + * Copyright (C) 2008-2009 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * AAC coefficients encoder + */ + +/*********************************** + * TODOs: + * speedup quantizer selection + * add sane pulse detection + ***********************************/ + +#include "libavutil/libm.h" // brought forward to work around cygwin header breakage + +#include +#include "libavutil/mathematics.h" +#include "avcodec.h" +#include "put_bits.h" +#include "aac.h" +#include "aacenc.h" +#include "aactab.h" + +/** bits needed to code codebook run value for long windows */ +static const uint8_t run_value_bits_long[64] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 15 +}; + +/** bits needed to code codebook run value for short windows */ +static const uint8_t run_value_bits_short[16] = { + 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 9 +}; + +static const uint8_t *run_value_bits[2] = { + run_value_bits_long, run_value_bits_short +}; + + +/** + * Quantize one coefficient. + * @return absolute value of the quantized coefficient + * @see 3GPP TS26.403 5.6.2 "Scalefactor determination" + */ +static av_always_inline int quant(float coef, const float Q) +{ + float a = coef * Q; + return sqrtf(a * sqrtf(a)) + 0.4054; +} + +static void quantize_bands(int *out, const float *in, const float *scaled, + int size, float Q34, int is_signed, int maxval) +{ + int i; + double qc; + for (i = 0; i < size; i++) { + qc = scaled[i] * Q34; + out[i] = (int)FFMIN(qc + 0.4054, (double)maxval); + if (is_signed && in[i] < 0.0f) { + out[i] = -out[i]; + } + } +} + +static void abs_pow34_v(float *out, const float *in, const int size) +{ +#ifndef USE_REALLY_FULL_SEARCH + int i; + for (i = 0; i < size; i++) { + float a = fabsf(in[i]); + out[i] = sqrtf(a * sqrtf(a)); + } +#endif /* USE_REALLY_FULL_SEARCH */ +} + +static const uint8_t aac_cb_range [12] = {0, 3, 3, 3, 3, 9, 9, 8, 8, 13, 13, 17}; +static const uint8_t aac_cb_maxval[12] = {0, 1, 1, 2, 2, 4, 4, 7, 7, 12, 12, 16}; + +/** + * Calculate rate distortion cost for quantizing with given codebook + * + * @return quantization distortion + */ +static av_always_inline float quantize_and_encode_band_cost_template( + struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits, int BT_ZERO, int BT_UNSIGNED, + int BT_PAIR, int BT_ESC) +{ + const int q_idx = POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512; + const float Q = ff_aac_pow2sf_tab [q_idx]; + const float Q34 = ff_aac_pow34sf_tab[q_idx]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + const float CLIPPED_ESCAPE = 165140.0f*IQ; + int i, j; + float cost = 0; + const int dim = BT_PAIR ? 2 : 4; + int resbits = 0; + const int range = aac_cb_range[cb]; + const int maxval = aac_cb_maxval[cb]; + int off; + + if (BT_ZERO) { + for (i = 0; i < size; i++) + cost += in[i]*in[i]; + if (bits) + *bits = 0; + return cost * lambda; + } + if (!scaled) { + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + } + quantize_bands(s->qcoefs, in, scaled, size, Q34, !BT_UNSIGNED, maxval); + if (BT_UNSIGNED) { + off = 0; + } else { + off = maxval; + } + for (i = 0; i < size; i += dim) { + const float *vec; + int *quants = s->qcoefs + i; + int curidx = 0; + int curbits; + float rd = 0.0f; + for (j = 0; j < dim; j++) { + curidx *= range; + curidx += quants[j] + off; + } + curbits = ff_aac_spectral_bits[cb-1][curidx]; + vec = &ff_aac_codebook_vectors[cb-1][curidx*dim]; + if (BT_UNSIGNED) { + for (j = 0; j < dim; j++) { + float t = fabsf(in[i+j]); + float di; + if (BT_ESC && vec[j] == 64.0f) { //FIXME: slow + if (t >= CLIPPED_ESCAPE) { + di = t - CLIPPED_ESCAPE; + curbits += 21; + } else { + int c = av_clip(quant(t, Q), 0, 8191); + di = t - c*cbrtf(c)*IQ; + curbits += av_log2(c)*2 - 4 + 1; + } + } else { + di = t - vec[j]*IQ; + } + if (vec[j] != 0.0f) + curbits++; + rd += di*di; + } + } else { + for (j = 0; j < dim; j++) { + float di = in[i+j] - vec[j]*IQ; + rd += di*di; + } + } + cost += rd * lambda + curbits; + resbits += curbits; + if (cost >= uplim) + return uplim; + if (pb) { + put_bits(pb, ff_aac_spectral_bits[cb-1][curidx], ff_aac_spectral_codes[cb-1][curidx]); + if (BT_UNSIGNED) + for (j = 0; j < dim; j++) + if (ff_aac_codebook_vectors[cb-1][curidx*dim+j] != 0.0f) + put_bits(pb, 1, in[i+j] < 0.0f); + if (BT_ESC) { + for (j = 0; j < 2; j++) { + if (ff_aac_codebook_vectors[cb-1][curidx*2+j] == 64.0f) { + int coef = av_clip(quant(fabsf(in[i+j]), Q), 0, 8191); + int len = av_log2(coef); + + put_bits(pb, len - 4 + 1, (1 << (len - 4 + 1)) - 2); + put_bits(pb, len, coef & ((1 << len) - 1)); + } + } + } + } + } + + if (bits) + *bits = resbits; + return cost; +} + +#define QUANTIZE_AND_ENCODE_BAND_COST_FUNC(NAME, BT_ZERO, BT_UNSIGNED, BT_PAIR, BT_ESC) \ +static float quantize_and_encode_band_cost_ ## NAME( \ + struct AACEncContext *s, \ + PutBitContext *pb, const float *in, \ + const float *scaled, int size, int scale_idx, \ + int cb, const float lambda, const float uplim, \ + int *bits) { \ + return quantize_and_encode_band_cost_template( \ + s, pb, in, scaled, size, scale_idx, \ + BT_ESC ? ESC_BT : cb, lambda, uplim, bits, \ + BT_ZERO, BT_UNSIGNED, BT_PAIR, BT_ESC); \ +} + +QUANTIZE_AND_ENCODE_BAND_COST_FUNC(ZERO, 1, 0, 0, 0) +QUANTIZE_AND_ENCODE_BAND_COST_FUNC(SQUAD, 0, 0, 0, 0) +QUANTIZE_AND_ENCODE_BAND_COST_FUNC(UQUAD, 0, 1, 0, 0) +QUANTIZE_AND_ENCODE_BAND_COST_FUNC(SPAIR, 0, 0, 1, 0) +QUANTIZE_AND_ENCODE_BAND_COST_FUNC(UPAIR, 0, 1, 1, 0) +QUANTIZE_AND_ENCODE_BAND_COST_FUNC(ESC, 0, 1, 1, 1) + +static float (*const quantize_and_encode_band_cost_arr[])( + struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) = { + quantize_and_encode_band_cost_ZERO, + quantize_and_encode_band_cost_SQUAD, + quantize_and_encode_band_cost_SQUAD, + quantize_and_encode_band_cost_UQUAD, + quantize_and_encode_band_cost_UQUAD, + quantize_and_encode_band_cost_SPAIR, + quantize_and_encode_band_cost_SPAIR, + quantize_and_encode_band_cost_UPAIR, + quantize_and_encode_band_cost_UPAIR, + quantize_and_encode_band_cost_UPAIR, + quantize_and_encode_band_cost_UPAIR, + quantize_and_encode_band_cost_ESC, +}; + +#define quantize_and_encode_band_cost( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) \ + quantize_and_encode_band_cost_arr[cb]( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) + +static float quantize_band_cost(struct AACEncContext *s, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + return quantize_and_encode_band_cost(s, NULL, in, scaled, size, scale_idx, + cb, lambda, uplim, bits); +} + +static void quantize_and_encode_band(struct AACEncContext *s, PutBitContext *pb, + const float *in, int size, int scale_idx, + int cb, const float lambda) +{ + quantize_and_encode_band_cost(s, pb, in, NULL, size, scale_idx, cb, lambda, + INFINITY, NULL); +} + +static float find_max_val(int group_len, int swb_size, const float *scaled) { + float maxval = 0.0f; + int w2, i; + for (w2 = 0; w2 < group_len; w2++) { + for (i = 0; i < swb_size; i++) { + maxval = FFMAX(maxval, scaled[w2*128+i]); + } + } + return maxval; +} + +static int find_min_book(float maxval, int sf) { + float Q = ff_aac_pow2sf_tab[POW_SF2_ZERO - sf + SCALE_ONE_POS - SCALE_DIV_512]; + float Q34 = sqrtf(Q * sqrtf(Q)); + int qmaxval, cb; + qmaxval = maxval * Q34 + 0.4054f; + if (qmaxval == 0) cb = 0; + else if (qmaxval == 1) cb = 1; + else if (qmaxval == 2) cb = 3; + else if (qmaxval <= 4) cb = 5; + else if (qmaxval <= 7) cb = 7; + else if (qmaxval <= 12) cb = 9; + else cb = 11; + return cb; +} + +/** + * structure used in optimal codebook search + */ +typedef struct BandCodingPath { + int prev_idx; ///< pointer to the previous path point + float cost; ///< path cost + int run; +} BandCodingPath; + +/** + * Encode band info for single window group bands. + */ +static void encode_window_bands_info(AACEncContext *s, SingleChannelElement *sce, + int win, int group_len, const float lambda) +{ + BandCodingPath path[120][12]; + int w, swb, cb, start, size; + int i, j; + const int max_sfb = sce->ics.max_sfb; + const int run_bits = sce->ics.num_windows == 1 ? 5 : 3; + const int run_esc = (1 << run_bits) - 1; + int idx, ppos, count; + int stackrun[120], stackcb[120], stack_len; + float next_minrd = INFINITY; + int next_mincb = 0; + + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + start = win*128; + for (cb = 0; cb < 12; cb++) { + path[0][cb].cost = 0.0f; + path[0][cb].prev_idx = -1; + path[0][cb].run = 0; + } + for (swb = 0; swb < max_sfb; swb++) { + size = sce->ics.swb_sizes[swb]; + if (sce->zeroes[win*16 + swb]) { + for (cb = 0; cb < 12; cb++) { + path[swb+1][cb].prev_idx = cb; + path[swb+1][cb].cost = path[swb][cb].cost; + path[swb+1][cb].run = path[swb][cb].run + 1; + } + } else { + float minrd = next_minrd; + int mincb = next_mincb; + next_minrd = INFINITY; + next_mincb = 0; + for (cb = 0; cb < 12; cb++) { + float cost_stay_here, cost_get_here; + float rd = 0.0f; + for (w = 0; w < group_len; w++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(win+w)*16+swb]; + rd += quantize_band_cost(s, sce->coeffs + start + w*128, + s->scoefs + start + w*128, size, + sce->sf_idx[(win+w)*16+swb], cb, + lambda / band->threshold, INFINITY, NULL); + } + cost_stay_here = path[swb][cb].cost + rd; + cost_get_here = minrd + rd + run_bits + 4; + if ( run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run] + != run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run+1]) + cost_stay_here += run_bits; + if (cost_get_here < cost_stay_here) { + path[swb+1][cb].prev_idx = mincb; + path[swb+1][cb].cost = cost_get_here; + path[swb+1][cb].run = 1; + } else { + path[swb+1][cb].prev_idx = cb; + path[swb+1][cb].cost = cost_stay_here; + path[swb+1][cb].run = path[swb][cb].run + 1; + } + if (path[swb+1][cb].cost < next_minrd) { + next_minrd = path[swb+1][cb].cost; + next_mincb = cb; + } + } + } + start += sce->ics.swb_sizes[swb]; + } + + //convert resulting path from backward-linked list + stack_len = 0; + idx = 0; + for (cb = 1; cb < 12; cb++) + if (path[max_sfb][cb].cost < path[max_sfb][idx].cost) + idx = cb; + ppos = max_sfb; + while (ppos > 0) { + cb = idx; + stackrun[stack_len] = path[ppos][cb].run; + stackcb [stack_len] = cb; + idx = path[ppos-path[ppos][cb].run+1][cb].prev_idx; + ppos -= path[ppos][cb].run; + stack_len++; + } + //perform actual band info encoding + start = 0; + for (i = stack_len - 1; i >= 0; i--) { + put_bits(&s->pb, 4, stackcb[i]); + count = stackrun[i]; + memset(sce->zeroes + win*16 + start, !stackcb[i], count); + //XXX: memset when band_type is also uint8_t + for (j = 0; j < count; j++) { + sce->band_type[win*16 + start] = stackcb[i]; + start++; + } + while (count >= run_esc) { + put_bits(&s->pb, run_bits, run_esc); + count -= run_esc; + } + put_bits(&s->pb, run_bits, count); + } +} + +static void codebook_trellis_rate(AACEncContext *s, SingleChannelElement *sce, + int win, int group_len, const float lambda) +{ + BandCodingPath path[120][12]; + int w, swb, cb, start, size; + int i, j; + const int max_sfb = sce->ics.max_sfb; + const int run_bits = sce->ics.num_windows == 1 ? 5 : 3; + const int run_esc = (1 << run_bits) - 1; + int idx, ppos, count; + int stackrun[120], stackcb[120], stack_len; + float next_minbits = INFINITY; + int next_mincb = 0; + + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + start = win*128; + for (cb = 0; cb < 12; cb++) { + path[0][cb].cost = run_bits+4; + path[0][cb].prev_idx = -1; + path[0][cb].run = 0; + } + for (swb = 0; swb < max_sfb; swb++) { + size = sce->ics.swb_sizes[swb]; + if (sce->zeroes[win*16 + swb]) { + float cost_stay_here = path[swb][0].cost; + float cost_get_here = next_minbits + run_bits + 4; + if ( run_value_bits[sce->ics.num_windows == 8][path[swb][0].run] + != run_value_bits[sce->ics.num_windows == 8][path[swb][0].run+1]) + cost_stay_here += run_bits; + if (cost_get_here < cost_stay_here) { + path[swb+1][0].prev_idx = next_mincb; + path[swb+1][0].cost = cost_get_here; + path[swb+1][0].run = 1; + } else { + path[swb+1][0].prev_idx = 0; + path[swb+1][0].cost = cost_stay_here; + path[swb+1][0].run = path[swb][0].run + 1; + } + next_minbits = path[swb+1][0].cost; + next_mincb = 0; + for (cb = 1; cb < 12; cb++) { + path[swb+1][cb].cost = 61450; + path[swb+1][cb].prev_idx = -1; + path[swb+1][cb].run = 0; + } + } else { + float minbits = next_minbits; + int mincb = next_mincb; + int startcb = sce->band_type[win*16+swb]; + next_minbits = INFINITY; + next_mincb = 0; + for (cb = 0; cb < startcb; cb++) { + path[swb+1][cb].cost = 61450; + path[swb+1][cb].prev_idx = -1; + path[swb+1][cb].run = 0; + } + for (cb = startcb; cb < 12; cb++) { + float cost_stay_here, cost_get_here; + float bits = 0.0f; + for (w = 0; w < group_len; w++) { + bits += quantize_band_cost(s, sce->coeffs + start + w*128, + s->scoefs + start + w*128, size, + sce->sf_idx[(win+w)*16+swb], cb, + 0, INFINITY, NULL); + } + cost_stay_here = path[swb][cb].cost + bits; + cost_get_here = minbits + bits + run_bits + 4; + if ( run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run] + != run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run+1]) + cost_stay_here += run_bits; + if (cost_get_here < cost_stay_here) { + path[swb+1][cb].prev_idx = mincb; + path[swb+1][cb].cost = cost_get_here; + path[swb+1][cb].run = 1; + } else { + path[swb+1][cb].prev_idx = cb; + path[swb+1][cb].cost = cost_stay_here; + path[swb+1][cb].run = path[swb][cb].run + 1; + } + if (path[swb+1][cb].cost < next_minbits) { + next_minbits = path[swb+1][cb].cost; + next_mincb = cb; + } + } + } + start += sce->ics.swb_sizes[swb]; + } + + //convert resulting path from backward-linked list + stack_len = 0; + idx = 0; + for (cb = 1; cb < 12; cb++) + if (path[max_sfb][cb].cost < path[max_sfb][idx].cost) + idx = cb; + ppos = max_sfb; + while (ppos > 0) { + av_assert1(idx >= 0); + cb = idx; + stackrun[stack_len] = path[ppos][cb].run; + stackcb [stack_len] = cb; + idx = path[ppos-path[ppos][cb].run+1][cb].prev_idx; + ppos -= path[ppos][cb].run; + stack_len++; + } + //perform actual band info encoding + start = 0; + for (i = stack_len - 1; i >= 0; i--) { + put_bits(&s->pb, 4, stackcb[i]); + count = stackrun[i]; + memset(sce->zeroes + win*16 + start, !stackcb[i], count); + //XXX: memset when band_type is also uint8_t + for (j = 0; j < count; j++) { + sce->band_type[win*16 + start] = stackcb[i]; + start++; + } + while (count >= run_esc) { + put_bits(&s->pb, run_bits, run_esc); + count -= run_esc; + } + put_bits(&s->pb, run_bits, count); + } +} + +/** Return the minimum scalefactor where the quantized coef does not clip. */ +static av_always_inline uint8_t coef2minsf(float coef) { + return av_clip_uint8(log2f(coef)*4 - 69 + SCALE_ONE_POS - SCALE_DIV_512); +} + +/** Return the maximum scalefactor where the quantized coef is not zero. */ +static av_always_inline uint8_t coef2maxsf(float coef) { + return av_clip_uint8(log2f(coef)*4 + 6 + SCALE_ONE_POS - SCALE_DIV_512); +} + +typedef struct TrellisPath { + float cost; + int prev; +} TrellisPath; + +#define TRELLIS_STAGES 121 +#define TRELLIS_STATES (SCALE_MAX_DIFF+1) + +static void search_for_quantizers_anmr(AVCodecContext *avctx, AACEncContext *s, + SingleChannelElement *sce, + const float lambda) +{ + int q, w, w2, g, start = 0; + int i, j; + int idx; + TrellisPath paths[TRELLIS_STAGES][TRELLIS_STATES]; + int bandaddr[TRELLIS_STAGES]; + int minq; + float mincost; + float q0f = FLT_MAX, q1f = 0.0f, qnrgf = 0.0f; + int q0, q1, qcnt = 0; + + for (i = 0; i < 1024; i++) { + float t = fabsf(sce->coeffs[i]); + if (t > 0.0f) { + q0f = FFMIN(q0f, t); + q1f = FFMAX(q1f, t); + qnrgf += t*t; + qcnt++; + } + } + + if (!qcnt) { + memset(sce->sf_idx, 0, sizeof(sce->sf_idx)); + memset(sce->zeroes, 1, sizeof(sce->zeroes)); + return; + } + + //minimum scalefactor index is when minimum nonzero coefficient after quantizing is not clipped + q0 = coef2minsf(q0f); + //maximum scalefactor index is when maximum coefficient after quantizing is still not zero + q1 = coef2maxsf(q1f); + if (q1 - q0 > 60) { + int q0low = q0; + int q1high = q1; + //minimum scalefactor index is when maximum nonzero coefficient after quantizing is not clipped + int qnrg = av_clip_uint8(log2f(sqrtf(qnrgf/qcnt))*4 - 31 + SCALE_ONE_POS - SCALE_DIV_512); + q1 = qnrg + 30; + q0 = qnrg - 30; + if (q0 < q0low) { + q1 += q0low - q0; + q0 = q0low; + } else if (q1 > q1high) { + q0 -= q1 - q1high; + q1 = q1high; + } + } + + for (i = 0; i < TRELLIS_STATES; i++) { + paths[0][i].cost = 0.0f; + paths[0][i].prev = -1; + } + for (j = 1; j < TRELLIS_STAGES; j++) { + for (i = 0; i < TRELLIS_STATES; i++) { + paths[j][i].cost = INFINITY; + paths[j][i].prev = -2; + } + } + idx = 1; + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *coefs = sce->coeffs + start; + float qmin, qmax; + int nz = 0; + + bandaddr[idx] = w * 16 + g; + qmin = INT_MAX; + qmax = 0.0f; + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + if (band->energy <= band->threshold || band->threshold == 0.0f) { + sce->zeroes[(w+w2)*16+g] = 1; + continue; + } + sce->zeroes[(w+w2)*16+g] = 0; + nz = 1; + for (i = 0; i < sce->ics.swb_sizes[g]; i++) { + float t = fabsf(coefs[w2*128+i]); + if (t > 0.0f) + qmin = FFMIN(qmin, t); + qmax = FFMAX(qmax, t); + } + } + if (nz) { + int minscale, maxscale; + float minrd = INFINITY; + float maxval; + //minimum scalefactor index is when minimum nonzero coefficient after quantizing is not clipped + minscale = coef2minsf(qmin); + //maximum scalefactor index is when maximum coefficient after quantizing is still not zero + maxscale = coef2maxsf(qmax); + minscale = av_clip(minscale - q0, 0, TRELLIS_STATES - 1); + maxscale = av_clip(maxscale - q0, 0, TRELLIS_STATES); + maxval = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], s->scoefs+start); + for (q = minscale; q < maxscale; q++) { + float dist = 0; + int cb = find_min_book(maxval, sce->sf_idx[w*16+g]); + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + dist += quantize_band_cost(s, coefs + w2*128, s->scoefs + start + w2*128, sce->ics.swb_sizes[g], + q + q0, cb, lambda / band->threshold, INFINITY, NULL); + } + minrd = FFMIN(minrd, dist); + + for (i = 0; i < q1 - q0; i++) { + float cost; + cost = paths[idx - 1][i].cost + dist + + ff_aac_scalefactor_bits[q - i + SCALE_DIFF_ZERO]; + if (cost < paths[idx][q].cost) { + paths[idx][q].cost = cost; + paths[idx][q].prev = i; + } + } + } + } else { + for (q = 0; q < q1 - q0; q++) { + paths[idx][q].cost = paths[idx - 1][q].cost + 1; + paths[idx][q].prev = q; + } + } + sce->zeroes[w*16+g] = !nz; + start += sce->ics.swb_sizes[g]; + idx++; + } + } + idx--; + mincost = paths[idx][0].cost; + minq = 0; + for (i = 1; i < TRELLIS_STATES; i++) { + if (paths[idx][i].cost < mincost) { + mincost = paths[idx][i].cost; + minq = i; + } + } + while (idx) { + sce->sf_idx[bandaddr[idx]] = minq + q0; + minq = paths[idx][minq].prev; + idx--; + } + //set the same quantizers inside window groups + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) + for (g = 0; g < sce->ics.num_swb; g++) + for (w2 = 1; w2 < sce->ics.group_len[w]; w2++) + sce->sf_idx[(w+w2)*16+g] = sce->sf_idx[w*16+g]; +} + +/** + * two-loop quantizers search taken from ISO 13818-7 Appendix C + */ +static void search_for_quantizers_twoloop(AVCodecContext *avctx, + AACEncContext *s, + SingleChannelElement *sce, + const float lambda) +{ + int start = 0, i, w, w2, g; + int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels; + float dists[128] = { 0 }, uplims[128]; + float maxvals[128]; + int fflag, minscaler; + int its = 0; + int allz = 0; + float minthr = INFINITY; + + // for values above this the decoder might end up in an endless loop + // due to always having more bits than what can be encoded. + destbits = FFMIN(destbits, 5800); + //XXX: some heuristic to determine initial quantizers will reduce search time + //determine zero bands and upper limits + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + int nz = 0; + float uplim = 0.0f; + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + uplim += band->threshold; + if (band->energy <= band->threshold || band->threshold == 0.0f) { + sce->zeroes[(w+w2)*16+g] = 1; + continue; + } + nz = 1; + } + uplims[w*16+g] = uplim *512; + sce->zeroes[w*16+g] = !nz; + if (nz) + minthr = FFMIN(minthr, uplim); + allz |= nz; + } + } + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + if (sce->zeroes[w*16+g]) { + sce->sf_idx[w*16+g] = SCALE_ONE_POS; + continue; + } + sce->sf_idx[w*16+g] = SCALE_ONE_POS + FFMIN(log2f(uplims[w*16+g]/minthr)*4,59); + } + } + + if (!allz) + return; + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *scaled = s->scoefs + start; + maxvals[w*16+g] = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], scaled); + start += sce->ics.swb_sizes[g]; + } + } + + //perform two-loop search + //outer loop - improve quality + do { + int tbits, qstep; + minscaler = sce->sf_idx[0]; + //inner loop - quantize spectrum to fit into given number of bits + qstep = its ? 1 : 32; + do { + int prev = -1; + tbits = 0; + fflag = 0; + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *coefs = sce->coeffs + start; + const float *scaled = s->scoefs + start; + int bits = 0; + int cb; + float dist = 0.0f; + + if (sce->zeroes[w*16+g] || sce->sf_idx[w*16+g] >= 218) { + start += sce->ics.swb_sizes[g]; + continue; + } + minscaler = FFMIN(minscaler, sce->sf_idx[w*16+g]); + cb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + int b; + dist += quantize_band_cost(s, coefs + w2*128, + scaled + w2*128, + sce->ics.swb_sizes[g], + sce->sf_idx[w*16+g], + cb, + 1.0f, + INFINITY, + &b); + bits += b; + } + dists[w*16+g] = dist - bits; + if (prev != -1) { + bits += ff_aac_scalefactor_bits[sce->sf_idx[w*16+g] - prev + SCALE_DIFF_ZERO]; + } + tbits += bits; + start += sce->ics.swb_sizes[g]; + prev = sce->sf_idx[w*16+g]; + } + } + if (tbits > destbits) { + for (i = 0; i < 128; i++) + if (sce->sf_idx[i] < 218 - qstep) + sce->sf_idx[i] += qstep; + } else { + for (i = 0; i < 128; i++) + if (sce->sf_idx[i] > 60 - qstep) + sce->sf_idx[i] -= qstep; + } + qstep >>= 1; + if (!qstep && tbits > destbits*1.02 && sce->sf_idx[0] < 217) + qstep = 1; + } while (qstep); + + fflag = 0; + minscaler = av_clip(minscaler, 60, 255 - SCALE_MAX_DIFF); + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + int prevsc = sce->sf_idx[w*16+g]; + if (dists[w*16+g] > uplims[w*16+g] && sce->sf_idx[w*16+g] > 60) { + if (find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]-1)) + sce->sf_idx[w*16+g]--; + else //Try to make sure there is some energy in every band + sce->sf_idx[w*16+g]-=2; + } + sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler, minscaler + SCALE_MAX_DIFF); + sce->sf_idx[w*16+g] = FFMIN(sce->sf_idx[w*16+g], 219); + if (sce->sf_idx[w*16+g] != prevsc) + fflag = 1; + sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); + } + } + its++; + } while (fflag && its < 10); +} + +static void search_for_quantizers_faac(AVCodecContext *avctx, AACEncContext *s, + SingleChannelElement *sce, + const float lambda) +{ + int start = 0, i, w, w2, g; + float uplim[128], maxq[128]; + int minq, maxsf; + float distfact = ((sce->ics.num_windows > 1) ? 85.80 : 147.84) / lambda; + int last = 0, lastband = 0, curband = 0; + float avg_energy = 0.0; + if (sce->ics.num_windows == 1) { + start = 0; + for (i = 0; i < 1024; i++) { + if (i - start >= sce->ics.swb_sizes[curband]) { + start += sce->ics.swb_sizes[curband]; + curband++; + } + if (sce->coeffs[i]) { + avg_energy += sce->coeffs[i] * sce->coeffs[i]; + last = i; + lastband = curband; + } + } + } else { + for (w = 0; w < 8; w++) { + const float *coeffs = sce->coeffs + w*128; + curband = start = 0; + for (i = 0; i < 128; i++) { + if (i - start >= sce->ics.swb_sizes[curband]) { + start += sce->ics.swb_sizes[curband]; + curband++; + } + if (coeffs[i]) { + avg_energy += coeffs[i] * coeffs[i]; + last = FFMAX(last, i); + lastband = FFMAX(lastband, curband); + } + } + } + } + last++; + avg_energy /= last; + if (avg_energy == 0.0f) { + for (i = 0; i < FF_ARRAY_ELEMS(sce->sf_idx); i++) + sce->sf_idx[i] = SCALE_ONE_POS; + return; + } + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + float *coefs = sce->coeffs + start; + const int size = sce->ics.swb_sizes[g]; + int start2 = start, end2 = start + size, peakpos = start; + float maxval = -1, thr = 0.0f, t; + maxq[w*16+g] = 0.0f; + if (g > lastband) { + maxq[w*16+g] = 0.0f; + start += size; + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) + memset(coefs + w2*128, 0, sizeof(coefs[0])*size); + continue; + } + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + for (i = 0; i < size; i++) { + float t = coefs[w2*128+i]*coefs[w2*128+i]; + maxq[w*16+g] = FFMAX(maxq[w*16+g], fabsf(coefs[w2*128 + i])); + thr += t; + if (sce->ics.num_windows == 1 && maxval < t) { + maxval = t; + peakpos = start+i; + } + } + } + if (sce->ics.num_windows == 1) { + start2 = FFMAX(peakpos - 2, start2); + end2 = FFMIN(peakpos + 3, end2); + } else { + start2 -= start; + end2 -= start; + } + start += size; + thr = pow(thr / (avg_energy * (end2 - start2)), 0.3 + 0.1*(lastband - g) / lastband); + t = 1.0 - (1.0 * start2 / last); + uplim[w*16+g] = distfact / (1.4 * thr + t*t*t + 0.075); + } + } + memset(sce->sf_idx, 0, sizeof(sce->sf_idx)); + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *coefs = sce->coeffs + start; + const float *scaled = s->scoefs + start; + const int size = sce->ics.swb_sizes[g]; + int scf, prev_scf, step; + int min_scf = -1, max_scf = 256; + float curdiff; + if (maxq[w*16+g] < 21.544) { + sce->zeroes[w*16+g] = 1; + start += size; + continue; + } + sce->zeroes[w*16+g] = 0; + scf = prev_scf = av_clip(SCALE_ONE_POS - SCALE_DIV_512 - log2f(1/maxq[w*16+g])*16/3, 60, 218); + step = 16; + for (;;) { + float dist = 0.0f; + int quant_max; + + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + int b; + dist += quantize_band_cost(s, coefs + w2*128, + scaled + w2*128, + sce->ics.swb_sizes[g], + scf, + ESC_BT, + lambda, + INFINITY, + &b); + dist -= b; + } + dist *= 1.0f / 512.0f / lambda; + quant_max = quant(maxq[w*16+g], ff_aac_pow2sf_tab[POW_SF2_ZERO - scf + SCALE_ONE_POS - SCALE_DIV_512]); + if (quant_max >= 8191) { // too much, return to the previous quantizer + sce->sf_idx[w*16+g] = prev_scf; + break; + } + prev_scf = scf; + curdiff = fabsf(dist - uplim[w*16+g]); + if (curdiff <= 1.0f) + step = 0; + else + step = log2f(curdiff); + if (dist > uplim[w*16+g]) + step = -step; + scf += step; + scf = av_clip_uint8(scf); + step = scf - prev_scf; + if (FFABS(step) <= 1 || (step > 0 && scf >= max_scf) || (step < 0 && scf <= min_scf)) { + sce->sf_idx[w*16+g] = av_clip(scf, min_scf, max_scf); + break; + } + if (step > 0) + min_scf = prev_scf; + else + max_scf = prev_scf; + } + start += size; + } + } + minq = sce->sf_idx[0] ? sce->sf_idx[0] : INT_MAX; + for (i = 1; i < 128; i++) { + if (!sce->sf_idx[i]) + sce->sf_idx[i] = sce->sf_idx[i-1]; + else + minq = FFMIN(minq, sce->sf_idx[i]); + } + if (minq == INT_MAX) + minq = 0; + minq = FFMIN(minq, SCALE_MAX_POS); + maxsf = FFMIN(minq + SCALE_MAX_DIFF, SCALE_MAX_POS); + for (i = 126; i >= 0; i--) { + if (!sce->sf_idx[i]) + sce->sf_idx[i] = sce->sf_idx[i+1]; + sce->sf_idx[i] = av_clip(sce->sf_idx[i], minq, maxsf); + } +} + +static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s, + SingleChannelElement *sce, + const float lambda) +{ + int i, w, w2, g; + int minq = 255; + + memset(sce->sf_idx, 0, sizeof(sce->sf_idx)); + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + if (band->energy <= band->threshold) { + sce->sf_idx[(w+w2)*16+g] = 218; + sce->zeroes[(w+w2)*16+g] = 1; + } else { + sce->sf_idx[(w+w2)*16+g] = av_clip(SCALE_ONE_POS - SCALE_DIV_512 + log2f(band->threshold), 80, 218); + sce->zeroes[(w+w2)*16+g] = 0; + } + minq = FFMIN(minq, sce->sf_idx[(w+w2)*16+g]); + } + } + } + for (i = 0; i < 128; i++) { + sce->sf_idx[i] = 140; + //av_clip(sce->sf_idx[i], minq, minq + SCALE_MAX_DIFF - 1); + } + //set the same quantizers inside window groups + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) + for (g = 0; g < sce->ics.num_swb; g++) + for (w2 = 1; w2 < sce->ics.group_len[w]; w2++) + sce->sf_idx[(w+w2)*16+g] = sce->sf_idx[w*16+g]; +} + +static void search_for_ms(AACEncContext *s, ChannelElement *cpe, + const float lambda) +{ + int start = 0, i, w, w2, g; + float M[128], S[128]; + float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3; + SingleChannelElement *sce0 = &cpe->ch[0]; + SingleChannelElement *sce1 = &cpe->ch[1]; + if (!cpe->common_window) + return; + for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) { + for (g = 0; g < sce0->ics.num_swb; g++) { + if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) { + float dist1 = 0.0f, dist2 = 0.0f; + for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { + FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g]; + FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g]; + float minthr = FFMIN(band0->threshold, band1->threshold); + float maxthr = FFMAX(band0->threshold, band1->threshold); + for (i = 0; i < sce0->ics.swb_sizes[g]; i++) { + M[i] = (sce0->coeffs[start+w2*128+i] + + sce1->coeffs[start+w2*128+i]) * 0.5; + S[i] = M[i] + - sce1->coeffs[start+w2*128+i]; + } + abs_pow34_v(L34, sce0->coeffs+start+w2*128, sce0->ics.swb_sizes[g]); + abs_pow34_v(R34, sce1->coeffs+start+w2*128, sce0->ics.swb_sizes[g]); + abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]); + abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]); + dist1 += quantize_band_cost(s, sce0->coeffs + start + w2*128, + L34, + sce0->ics.swb_sizes[g], + sce0->sf_idx[(w+w2)*16+g], + sce0->band_type[(w+w2)*16+g], + lambda / band0->threshold, INFINITY, NULL); + dist1 += quantize_band_cost(s, sce1->coeffs + start + w2*128, + R34, + sce1->ics.swb_sizes[g], + sce1->sf_idx[(w+w2)*16+g], + sce1->band_type[(w+w2)*16+g], + lambda / band1->threshold, INFINITY, NULL); + dist2 += quantize_band_cost(s, M, + M34, + sce0->ics.swb_sizes[g], + sce0->sf_idx[(w+w2)*16+g], + sce0->band_type[(w+w2)*16+g], + lambda / maxthr, INFINITY, NULL); + dist2 += quantize_band_cost(s, S, + S34, + sce1->ics.swb_sizes[g], + sce1->sf_idx[(w+w2)*16+g], + sce1->band_type[(w+w2)*16+g], + lambda / minthr, INFINITY, NULL); + } + cpe->ms_mask[w*16+g] = dist2 < dist1; + } + start += sce0->ics.swb_sizes[g]; + } + } +} + +AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = { + { + search_for_quantizers_faac, + encode_window_bands_info, + quantize_and_encode_band, + search_for_ms, + }, + { + search_for_quantizers_anmr, + encode_window_bands_info, + quantize_and_encode_band, + search_for_ms, + }, + { + search_for_quantizers_twoloop, + codebook_trellis_rate, + quantize_and_encode_band, + search_for_ms, + }, + { + search_for_quantizers_fast, + encode_window_bands_info, + quantize_and_encode_band, + search_for_ms, + }, +}; diff --git a/ffmpeg/libavcodec/aacdec.c b/ffmpeg/libavcodec/aacdec.c new file mode 100644 index 0000000..37c7de5 --- /dev/null +++ b/ffmpeg/libavcodec/aacdec.c @@ -0,0 +1,3060 @@ +/* + * AAC decoder + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * + * AAC LATM decoder + * Copyright (c) 2008-2010 Paul Kendall + * Copyright (c) 2010 Janne Grunau + * + * 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 + */ + +/** + * @file + * AAC decoder + * @author Oded Shimon ( ods15 ods15 dyndns org ) + * @author Maxim Gavrilov ( maxim.gavrilov gmail com ) + */ + +/* + * supported tools + * + * Support? Name + * N (code in SoC repo) gain control + * Y block switching + * Y window shapes - standard + * N window shapes - Low Delay + * Y filterbank - standard + * N (code in SoC repo) filterbank - Scalable Sample Rate + * Y Temporal Noise Shaping + * Y Long Term Prediction + * Y intensity stereo + * Y channel coupling + * Y frequency domain prediction + * Y Perceptual Noise Substitution + * Y Mid/Side stereo + * N Scalable Inverse AAC Quantization + * N Frequency Selective Switch + * N upsampling filter + * Y quantization & coding - AAC + * N quantization & coding - TwinVQ + * N quantization & coding - BSAC + * N AAC Error Resilience tools + * N Error Resilience payload syntax + * N Error Protection tool + * N CELP + * N Silence Compression + * N HVXC + * N HVXC 4kbits/s VR + * N Structured Audio tools + * N Structured Audio Sample Bank Format + * N MIDI + * N Harmonic and Individual Lines plus Noise + * N Text-To-Speech Interface + * Y Spectral Band Replication + * Y (not in this code) Layer-1 + * Y (not in this code) Layer-2 + * Y (not in this code) Layer-3 + * N SinuSoidal Coding (Transient, Sinusoid, Noise) + * Y Parametric Stereo + * N Direct Stream Transfer + * + * Note: - HE AAC v1 comprises LC AAC with Spectral Band Replication. + * - HE AAC v2 comprises LC AAC with Spectral Band Replication and + Parametric Stereo. + */ + +#include "libavutil/float_dsp.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "fft.h" +#include "fmtconvert.h" +#include "lpc.h" +#include "kbdwin.h" +#include "sinewin.h" + +#include "aac.h" +#include "aactab.h" +#include "aacdectab.h" +#include "cbrt_tablegen.h" +#include "sbr.h" +#include "aacsbr.h" +#include "mpeg4audio.h" +#include "aacadtsdec.h" +#include "libavutil/intfloat.h" + +#include +#include +#include +#include + +#if ARCH_ARM +# include "arm/aac.h" +#elif ARCH_MIPS +# include "mips/aacdec_mips.h" +#endif + +static VLC vlc_scalefactors; +static VLC vlc_spectral[11]; + +static int output_configure(AACContext *ac, + uint8_t layout_map[MAX_ELEM_ID*4][3], int tags, + enum OCStatus oc_type, int get_new_frame); + +#define overread_err "Input buffer exhausted before END element found\n" + +static int count_channels(uint8_t (*layout)[3], int tags) +{ + int i, sum = 0; + for (i = 0; i < tags; i++) { + int syn_ele = layout[i][0]; + int pos = layout[i][2]; + sum += (1 + (syn_ele == TYPE_CPE)) * + (pos != AAC_CHANNEL_OFF && pos != AAC_CHANNEL_CC); + } + return sum; +} + +/** + * Check for the channel element in the current channel position configuration. + * If it exists, make sure the appropriate element is allocated and map the + * channel order to match the internal FFmpeg channel layout. + * + * @param che_pos current channel position configuration + * @param type channel element type + * @param id channel element id + * @param channels count of the number of channels in the configuration + * + * @return Returns error status. 0 - OK, !0 - error + */ +static av_cold int che_configure(AACContext *ac, + enum ChannelPosition che_pos, + int type, int id, int *channels) +{ + if (che_pos) { + if (!ac->che[type][id]) { + if (!(ac->che[type][id] = av_mallocz(sizeof(ChannelElement)))) + return AVERROR(ENOMEM); + ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr); + } + if (type != TYPE_CCE) { + if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) { + av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n"); + return AVERROR_INVALIDDATA; + } + ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0]; + if (type == TYPE_CPE || + (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) { + ac->output_element[(*channels)++] = &ac->che[type][id]->ch[1]; + } + } + } else { + if (ac->che[type][id]) + ff_aac_sbr_ctx_close(&ac->che[type][id]->sbr); + av_freep(&ac->che[type][id]); + } + return 0; +} + +static int frame_configure_elements(AVCodecContext *avctx) +{ + AACContext *ac = avctx->priv_data; + int type, id, ch, ret; + + /* set channel pointers to internal buffers by default */ + for (type = 0; type < 4; type++) { + for (id = 0; id < MAX_ELEM_ID; id++) { + ChannelElement *che = ac->che[type][id]; + if (che) { + che->ch[0].ret = che->ch[0].ret_buf; + che->ch[1].ret = che->ch[1].ret_buf; + } + } + } + + /* get output buffer */ + av_frame_unref(ac->frame); + ac->frame->nb_samples = 2048; + if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0) + return ret; + + /* map output channel pointers to AVFrame data */ + for (ch = 0; ch < avctx->channels; ch++) { + if (ac->output_element[ch]) + ac->output_element[ch]->ret = (float *)ac->frame->extended_data[ch]; + } + + return 0; +} + +struct elem_to_channel { + uint64_t av_position; + uint8_t syn_ele; + uint8_t elem_id; + uint8_t aac_position; +}; + +static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID], + uint8_t (*layout_map)[3], int offset, uint64_t left, + uint64_t right, int pos) +{ + if (layout_map[offset][0] == TYPE_CPE) { + e2c_vec[offset] = (struct elem_to_channel) { + .av_position = left | right, .syn_ele = TYPE_CPE, + .elem_id = layout_map[offset ][1], .aac_position = pos }; + return 1; + } else { + e2c_vec[offset] = (struct elem_to_channel) { + .av_position = left, .syn_ele = TYPE_SCE, + .elem_id = layout_map[offset ][1], .aac_position = pos }; + e2c_vec[offset + 1] = (struct elem_to_channel) { + .av_position = right, .syn_ele = TYPE_SCE, + .elem_id = layout_map[offset + 1][1], .aac_position = pos }; + return 2; + } +} + +static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos, int *current) { + int num_pos_channels = 0; + int first_cpe = 0; + int sce_parity = 0; + int i; + for (i = *current; i < tags; i++) { + if (layout_map[i][2] != pos) + break; + if (layout_map[i][0] == TYPE_CPE) { + if (sce_parity) { + if (pos == AAC_CHANNEL_FRONT && !first_cpe) { + sce_parity = 0; + } else { + return -1; + } + } + num_pos_channels += 2; + first_cpe = 1; + } else { + num_pos_channels++; + sce_parity ^= 1; + } + } + if (sce_parity && + ((pos == AAC_CHANNEL_FRONT && first_cpe) || pos == AAC_CHANNEL_SIDE)) + return -1; + *current = i; + return num_pos_channels; +} + +static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags) +{ + int i, n, total_non_cc_elements; + struct elem_to_channel e2c_vec[4*MAX_ELEM_ID] = {{ 0 }}; + int num_front_channels, num_side_channels, num_back_channels; + uint64_t layout; + + if (FF_ARRAY_ELEMS(e2c_vec) < tags) + return 0; + + i = 0; + num_front_channels = + count_paired_channels(layout_map, tags, AAC_CHANNEL_FRONT, &i); + if (num_front_channels < 0) + return 0; + num_side_channels = + count_paired_channels(layout_map, tags, AAC_CHANNEL_SIDE, &i); + if (num_side_channels < 0) + return 0; + num_back_channels = + count_paired_channels(layout_map, tags, AAC_CHANNEL_BACK, &i); + if (num_back_channels < 0) + return 0; + + i = 0; + if (num_front_channels & 1) { + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_FRONT_CENTER, .syn_ele = TYPE_SCE, + .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_FRONT }; + i++; + num_front_channels--; + } + if (num_front_channels >= 4) { + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_FRONT_LEFT_OF_CENTER, + AV_CH_FRONT_RIGHT_OF_CENTER, + AAC_CHANNEL_FRONT); + num_front_channels -= 2; + } + if (num_front_channels >= 2) { + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_FRONT_LEFT, + AV_CH_FRONT_RIGHT, + AAC_CHANNEL_FRONT); + num_front_channels -= 2; + } + while (num_front_channels >= 2) { + i += assign_pair(e2c_vec, layout_map, i, + UINT64_MAX, + UINT64_MAX, + AAC_CHANNEL_FRONT); + num_front_channels -= 2; + } + + if (num_side_channels >= 2) { + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_SIDE_LEFT, + AV_CH_SIDE_RIGHT, + AAC_CHANNEL_FRONT); + num_side_channels -= 2; + } + while (num_side_channels >= 2) { + i += assign_pair(e2c_vec, layout_map, i, + UINT64_MAX, + UINT64_MAX, + AAC_CHANNEL_SIDE); + num_side_channels -= 2; + } + + while (num_back_channels >= 4) { + i += assign_pair(e2c_vec, layout_map, i, + UINT64_MAX, + UINT64_MAX, + AAC_CHANNEL_BACK); + num_back_channels -= 2; + } + if (num_back_channels >= 2) { + i += assign_pair(e2c_vec, layout_map, i, + AV_CH_BACK_LEFT, + AV_CH_BACK_RIGHT, + AAC_CHANNEL_BACK); + num_back_channels -= 2; + } + if (num_back_channels) { + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_BACK_CENTER, .syn_ele = TYPE_SCE, + .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_BACK }; + i++; + num_back_channels--; + } + + if (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) { + e2c_vec[i] = (struct elem_to_channel) { + .av_position = AV_CH_LOW_FREQUENCY, .syn_ele = TYPE_LFE, + .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_LFE }; + i++; + } + while (i < tags && layout_map[i][2] == AAC_CHANNEL_LFE) { + e2c_vec[i] = (struct elem_to_channel) { + .av_position = UINT64_MAX, .syn_ele = TYPE_LFE, + .elem_id = layout_map[i][1], .aac_position = AAC_CHANNEL_LFE }; + i++; + } + + // Must choose a stable sort + total_non_cc_elements = n = i; + do { + int next_n = 0; + for (i = 1; i < n; i++) { + if (e2c_vec[i-1].av_position > e2c_vec[i].av_position) { + FFSWAP(struct elem_to_channel, e2c_vec[i-1], e2c_vec[i]); + next_n = i; + } + } + n = next_n; + } while (n > 0); + + layout = 0; + for (i = 0; i < total_non_cc_elements; i++) { + layout_map[i][0] = e2c_vec[i].syn_ele; + layout_map[i][1] = e2c_vec[i].elem_id; + layout_map[i][2] = e2c_vec[i].aac_position; + if (e2c_vec[i].av_position != UINT64_MAX) { + layout |= e2c_vec[i].av_position; + } + } + + return layout; +} + +/** + * Save current output configuration if and only if it has been locked. + */ +static void push_output_configuration(AACContext *ac) { + if (ac->oc[1].status == OC_LOCKED) { + ac->oc[0] = ac->oc[1]; + } + ac->oc[1].status = OC_NONE; +} + +/** + * Restore the previous output configuration if and only if the current + * configuration is unlocked. + */ +static void pop_output_configuration(AACContext *ac) { + if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) { + ac->oc[1] = ac->oc[0]; + ac->avctx->channels = ac->oc[1].channels; + ac->avctx->channel_layout = ac->oc[1].channel_layout; + output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, + ac->oc[1].status, 0); + } +} + +/** + * Configure output channel order based on the current program configuration element. + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int output_configure(AACContext *ac, + uint8_t layout_map[MAX_ELEM_ID*4][3], int tags, + enum OCStatus oc_type, int get_new_frame) +{ + AVCodecContext *avctx = ac->avctx; + int i, channels = 0, ret; + uint64_t layout = 0; + + if (ac->oc[1].layout_map != layout_map) { + memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0])); + ac->oc[1].layout_map_tags = tags; + } + + // Try to sniff a reasonable channel order, otherwise output the + // channels in the order the PCE declared them. + if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) + layout = sniff_channel_order(layout_map, tags); + for (i = 0; i < tags; i++) { + int type = layout_map[i][0]; + int id = layout_map[i][1]; + int position = layout_map[i][2]; + // Allocate or free elements depending on if they are in the + // current program configuration. + ret = che_configure(ac, position, type, id, &channels); + if (ret < 0) + return ret; + } + if (ac->oc[1].m4ac.ps == 1 && channels == 2) { + if (layout == AV_CH_FRONT_CENTER) { + layout = AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT; + } else { + layout = 0; + } + } + + memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); + if (layout) avctx->channel_layout = layout; + ac->oc[1].channel_layout = layout; + avctx->channels = ac->oc[1].channels = channels; + ac->oc[1].status = oc_type; + + if (get_new_frame) { + if ((ret = frame_configure_elements(ac->avctx)) < 0) + return ret; + } + + return 0; +} + +static void flush(AVCodecContext *avctx) +{ + AACContext *ac= avctx->priv_data; + int type, i, j; + + for (type = 3; type >= 0; type--) { + for (i = 0; i < MAX_ELEM_ID; i++) { + ChannelElement *che = ac->che[type][i]; + if (che) { + for (j = 0; j <= 1; j++) { + memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved)); + } + } + } + } +} + +/** + * Set up channel positions based on a default channel configuration + * as specified in table 1.17. + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int set_default_channel_config(AVCodecContext *avctx, + uint8_t (*layout_map)[3], + int *tags, + int channel_config) +{ + if (channel_config < 1 || channel_config > 7) { + av_log(avctx, AV_LOG_ERROR, "invalid default channel configuration (%d)\n", + channel_config); + return -1; + } + *tags = tags_per_config[channel_config]; + memcpy(layout_map, aac_channel_layout_map[channel_config-1], *tags * sizeof(*layout_map)); + return 0; +} + +static ChannelElement *get_che(AACContext *ac, int type, int elem_id) +{ + // For PCE based channel configurations map the channels solely based on tags. + if (!ac->oc[1].m4ac.chan_config) { + return ac->tag_che_map[type][elem_id]; + } + // Allow single CPE stereo files to be signalled with mono configuration. + if (!ac->tags_mapped && type == TYPE_CPE && ac->oc[1].m4ac.chan_config == 1) { + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + push_output_configuration(ac); + + av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n"); + + if (set_default_channel_config(ac->avctx, layout_map, &layout_map_tags, + 2) < 0) + return NULL; + if (output_configure(ac, layout_map, layout_map_tags, + OC_TRIAL_FRAME, 1) < 0) + return NULL; + + ac->oc[1].m4ac.chan_config = 2; + ac->oc[1].m4ac.ps = 0; + } + // And vice-versa + if (!ac->tags_mapped && type == TYPE_SCE && ac->oc[1].m4ac.chan_config == 2) { + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + push_output_configuration(ac); + + av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n"); + + if (set_default_channel_config(ac->avctx, layout_map, &layout_map_tags, + 1) < 0) + return NULL; + if (output_configure(ac, layout_map, layout_map_tags, + OC_TRIAL_FRAME, 1) < 0) + return NULL; + + ac->oc[1].m4ac.chan_config = 1; + if (ac->oc[1].m4ac.sbr) + ac->oc[1].m4ac.ps = -1; + } + // For indexed channel configurations map the channels solely based on position. + switch (ac->oc[1].m4ac.chan_config) { + case 7: + if (ac->tags_mapped == 3 && type == TYPE_CPE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2]; + } + case 6: + /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1] + instead of SCE[0] CPE[0] CPE[1] LFE[0]. If we seem to have + encountered such a stream, transfer the LFE[0] element to the SCE[1]'s mapping */ + if (ac->tags_mapped == tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) { + ac->tags_mapped++; + return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0]; + } + case 5: + if (ac->tags_mapped == 2 && type == TYPE_CPE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1]; + } + case 4: + if (ac->tags_mapped == 2 && ac->oc[1].m4ac.chan_config == 4 && type == TYPE_SCE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1]; + } + case 3: + case 2: + if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) && type == TYPE_CPE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0]; + } else if (ac->oc[1].m4ac.chan_config == 2) { + return NULL; + } + case 1: + if (!ac->tags_mapped && type == TYPE_SCE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0]; + } + default: + return NULL; + } +} + +/** + * Decode an array of 4 bit element IDs, optionally interleaved with a stereo/mono switching bit. + * + * @param type speaker type/position for these channels + */ +static void decode_channel_map(uint8_t layout_map[][3], + enum ChannelPosition type, + GetBitContext *gb, int n) +{ + while (n--) { + enum RawDataBlockType syn_ele; + switch (type) { + case AAC_CHANNEL_FRONT: + case AAC_CHANNEL_BACK: + case AAC_CHANNEL_SIDE: + syn_ele = get_bits1(gb); + break; + case AAC_CHANNEL_CC: + skip_bits1(gb); + syn_ele = TYPE_CCE; + break; + case AAC_CHANNEL_LFE: + syn_ele = TYPE_LFE; + break; + default: + av_assert0(0); + } + layout_map[0][0] = syn_ele; + layout_map[0][1] = get_bits(gb, 4); + layout_map[0][2] = type; + layout_map++; + } +} + +/** + * Decode program configuration element; reference: table 4.2. + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac, + uint8_t (*layout_map)[3], + GetBitContext *gb) +{ + int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc, sampling_index; + int comment_len; + int tags; + + skip_bits(gb, 2); // object_type + + sampling_index = get_bits(gb, 4); + if (m4ac->sampling_index != sampling_index) + av_log(avctx, AV_LOG_WARNING, "Sample rate index in program config element does not match the sample rate index configured by the container.\n"); + + num_front = get_bits(gb, 4); + num_side = get_bits(gb, 4); + num_back = get_bits(gb, 4); + num_lfe = get_bits(gb, 2); + num_assoc_data = get_bits(gb, 3); + num_cc = get_bits(gb, 4); + + if (get_bits1(gb)) + skip_bits(gb, 4); // mono_mixdown_tag + if (get_bits1(gb)) + skip_bits(gb, 4); // stereo_mixdown_tag + + if (get_bits1(gb)) + skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround + + if (get_bits_left(gb) < 4 * (num_front + num_side + num_back + num_lfe + num_assoc_data + num_cc)) { + av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err); + return -1; + } + decode_channel_map(layout_map , AAC_CHANNEL_FRONT, gb, num_front); + tags = num_front; + decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE, gb, num_side); + tags += num_side; + decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK, gb, num_back); + tags += num_back; + decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE, gb, num_lfe); + tags += num_lfe; + + skip_bits_long(gb, 4 * num_assoc_data); + + decode_channel_map(layout_map + tags, AAC_CHANNEL_CC, gb, num_cc); + tags += num_cc; + + align_get_bits(gb); + + /* comment field, first byte is length */ + comment_len = get_bits(gb, 8) * 8; + if (get_bits_left(gb) < comment_len) { + av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err); + return -1; + } + skip_bits_long(gb, comment_len); + return tags; +} + +/** + * Decode GA "General Audio" specific configuration; reference: table 4.1. + * + * @param ac pointer to AACContext, may be null + * @param avctx pointer to AVCCodecContext, used for logging + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx, + GetBitContext *gb, + MPEG4AudioConfig *m4ac, + int channel_config) +{ + int extension_flag, ret; + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int tags = 0; + + if (get_bits1(gb)) { // frameLengthFlag + avpriv_request_sample(avctx, "960/120 MDCT window"); + return AVERROR_PATCHWELCOME; + } + + if (get_bits1(gb)) // dependsOnCoreCoder + skip_bits(gb, 14); // coreCoderDelay + extension_flag = get_bits1(gb); + + if (m4ac->object_type == AOT_AAC_SCALABLE || + m4ac->object_type == AOT_ER_AAC_SCALABLE) + skip_bits(gb, 3); // layerNr + + if (channel_config == 0) { + skip_bits(gb, 4); // element_instance_tag + tags = decode_pce(avctx, m4ac, layout_map, gb); + if (tags < 0) + return tags; + } else { + if ((ret = set_default_channel_config(avctx, layout_map, &tags, channel_config))) + return ret; + } + + if (count_channels(layout_map, tags) > 1) { + m4ac->ps = 0; + } else if (m4ac->sbr == 1 && m4ac->ps == -1) + m4ac->ps = 1; + + if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0))) + return ret; + + if (extension_flag) { + switch (m4ac->object_type) { + case AOT_ER_BSAC: + skip_bits(gb, 5); // numOfSubFrame + skip_bits(gb, 11); // layer_length + break; + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCALABLE: + case AOT_ER_AAC_LD: + skip_bits(gb, 3); /* aacSectionDataResilienceFlag + * aacScalefactorDataResilienceFlag + * aacSpectralDataResilienceFlag + */ + break; + } + skip_bits1(gb); // extensionFlag3 (TBD in version 3) + } + return 0; +} + +/** + * Decode audio specific configuration; reference: table 1.13. + * + * @param ac pointer to AACContext, may be null + * @param avctx pointer to AVCCodecContext, used for logging + * @param m4ac pointer to MPEG4AudioConfig, used for parsing + * @param data pointer to buffer holding an audio specific config + * @param bit_size size of audio specific config or data in bits + * @param sync_extension look for an appended sync extension + * + * @return Returns error status or number of consumed bits. <0 - error + */ +static int decode_audio_specific_config(AACContext *ac, + AVCodecContext *avctx, + MPEG4AudioConfig *m4ac, + const uint8_t *data, int bit_size, + int sync_extension) +{ + GetBitContext gb; + int i; + int ret; + + av_dlog(avctx, "audio specific config size %d\n", bit_size >> 3); + for (i = 0; i < bit_size >> 3; i++) + av_dlog(avctx, "%02x ", data[i]); + av_dlog(avctx, "\n"); + + if ((ret = init_get_bits(&gb, data, bit_size)) < 0) + return ret; + + if ((i = avpriv_mpeg4audio_get_config(m4ac, data, bit_size, sync_extension)) < 0) + return -1; + if (m4ac->sampling_index > 12) { + av_log(avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", m4ac->sampling_index); + return -1; + } + + skip_bits_long(&gb, i); + + switch (m4ac->object_type) { + case AOT_AAC_MAIN: + case AOT_AAC_LC: + case AOT_AAC_LTP: + if (decode_ga_specific_config(ac, avctx, &gb, m4ac, m4ac->chan_config)) + return -1; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Audio object type %s%d is not supported.\n", + m4ac->sbr == 1? "SBR+" : "", m4ac->object_type); + return -1; + } + + av_dlog(avctx, "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n", + m4ac->object_type, m4ac->chan_config, m4ac->sampling_index, + m4ac->sample_rate, m4ac->sbr, m4ac->ps); + + return get_bits_count(&gb); +} + +/** + * linear congruential pseudorandom number generator + * + * @param previous_val pointer to the current state of the generator + * + * @return Returns a 32-bit pseudorandom integer + */ +static av_always_inline int lcg_random(unsigned previous_val) +{ + union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 }; + return v.s; +} + +static av_always_inline void reset_predict_state(PredictorState *ps) +{ + ps->r0 = 0.0f; + ps->r1 = 0.0f; + ps->cor0 = 0.0f; + ps->cor1 = 0.0f; + ps->var0 = 1.0f; + ps->var1 = 1.0f; +} + +static void reset_all_predictors(PredictorState *ps) +{ + int i; + for (i = 0; i < MAX_PREDICTORS; i++) + reset_predict_state(&ps[i]); +} + +static int sample_rate_idx (int rate) +{ + if (92017 <= rate) return 0; + else if (75132 <= rate) return 1; + else if (55426 <= rate) return 2; + else if (46009 <= rate) return 3; + else if (37566 <= rate) return 4; + else if (27713 <= rate) return 5; + else if (23004 <= rate) return 6; + else if (18783 <= rate) return 7; + else if (13856 <= rate) return 8; + else if (11502 <= rate) return 9; + else if (9391 <= rate) return 10; + else return 11; +} + +static void reset_predictor_group(PredictorState *ps, int group_num) +{ + int i; + for (i = group_num - 1; i < MAX_PREDICTORS; i += 30) + reset_predict_state(&ps[i]); +} + +#define AAC_INIT_VLC_STATIC(num, size) \ + INIT_VLC_STATIC(&vlc_spectral[num], 8, ff_aac_spectral_sizes[num], \ + ff_aac_spectral_bits[num], sizeof( ff_aac_spectral_bits[num][0]), sizeof( ff_aac_spectral_bits[num][0]), \ + ff_aac_spectral_codes[num], sizeof(ff_aac_spectral_codes[num][0]), sizeof(ff_aac_spectral_codes[num][0]), \ + size); + +static void aacdec_init(AACContext *ac); + +static av_cold int aac_decode_init(AVCodecContext *avctx) +{ + AACContext *ac = avctx->priv_data; + + ac->avctx = avctx; + ac->oc[1].m4ac.sample_rate = avctx->sample_rate; + + aacdec_init(ac); + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + if (avctx->extradata_size > 0) { + if (decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac, + avctx->extradata, + avctx->extradata_size*8, 1) < 0) + return -1; + } else { + int sr, i; + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + + sr = sample_rate_idx(avctx->sample_rate); + ac->oc[1].m4ac.sampling_index = sr; + ac->oc[1].m4ac.channels = avctx->channels; + ac->oc[1].m4ac.sbr = -1; + ac->oc[1].m4ac.ps = -1; + + for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++) + if (ff_mpeg4audio_channels[i] == avctx->channels) + break; + if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) { + i = 0; + } + ac->oc[1].m4ac.chan_config = i; + + if (ac->oc[1].m4ac.chan_config) { + int ret = set_default_channel_config(avctx, layout_map, + &layout_map_tags, ac->oc[1].m4ac.chan_config); + if (!ret) + output_configure(ac, layout_map, layout_map_tags, + OC_GLOBAL_HDR, 0); + else if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + } + + if (avctx->channels > MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "Too many channels\n"); + return AVERROR_INVALIDDATA; + } + + AAC_INIT_VLC_STATIC( 0, 304); + AAC_INIT_VLC_STATIC( 1, 270); + AAC_INIT_VLC_STATIC( 2, 550); + AAC_INIT_VLC_STATIC( 3, 300); + AAC_INIT_VLC_STATIC( 4, 328); + AAC_INIT_VLC_STATIC( 5, 294); + AAC_INIT_VLC_STATIC( 6, 306); + AAC_INIT_VLC_STATIC( 7, 268); + AAC_INIT_VLC_STATIC( 8, 510); + AAC_INIT_VLC_STATIC( 9, 366); + AAC_INIT_VLC_STATIC(10, 462); + + ff_aac_sbr_init(); + + ff_fmt_convert_init(&ac->fmt_conv, avctx); + avpriv_float_dsp_init(&ac->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + ac->random_state = 0x1f2e3d4c; + + ff_aac_tableinit(); + + INIT_VLC_STATIC(&vlc_scalefactors,7,FF_ARRAY_ELEMS(ff_aac_scalefactor_code), + ff_aac_scalefactor_bits, sizeof(ff_aac_scalefactor_bits[0]), sizeof(ff_aac_scalefactor_bits[0]), + ff_aac_scalefactor_code, sizeof(ff_aac_scalefactor_code[0]), sizeof(ff_aac_scalefactor_code[0]), + 352); + + ff_mdct_init(&ac->mdct, 11, 1, 1.0 / (32768.0 * 1024.0)); + ff_mdct_init(&ac->mdct_small, 8, 1, 1.0 / (32768.0 * 128.0)); + ff_mdct_init(&ac->mdct_ltp, 11, 0, -2.0 * 32768.0); + // window initialization + ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); + ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); + ff_init_ff_sine_windows(10); + ff_init_ff_sine_windows( 7); + + cbrt_tableinit(); + + return 0; +} + +/** + * Skip data_stream_element; reference: table 4.10. + */ +static int skip_data_stream_element(AACContext *ac, GetBitContext *gb) +{ + int byte_align = get_bits1(gb); + int count = get_bits(gb, 8); + if (count == 255) + count += get_bits(gb, 8); + if (byte_align) + align_get_bits(gb); + + if (get_bits_left(gb) < 8 * count) { + av_log(ac->avctx, AV_LOG_ERROR, "skip_data_stream_element: "overread_err); + return -1; + } + skip_bits_long(gb, 8 * count); + return 0; +} + +static int decode_prediction(AACContext *ac, IndividualChannelStream *ics, + GetBitContext *gb) +{ + int sfb; + if (get_bits1(gb)) { + ics->predictor_reset_group = get_bits(gb, 5); + if (ics->predictor_reset_group == 0 || ics->predictor_reset_group > 30) { + av_log(ac->avctx, AV_LOG_ERROR, "Invalid Predictor Reset Group.\n"); + return -1; + } + } + for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]); sfb++) { + ics->prediction_used[sfb] = get_bits1(gb); + } + return 0; +} + +/** + * Decode Long Term Prediction data; reference: table 4.xx. + */ +static void decode_ltp(LongTermPrediction *ltp, + GetBitContext *gb, uint8_t max_sfb) +{ + int sfb; + + ltp->lag = get_bits(gb, 11); + ltp->coef = ltp_coef[get_bits(gb, 3)]; + for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++) + ltp->used[sfb] = get_bits1(gb); +} + +/** + * Decode Individual Channel Stream info; reference: table 4.6. + */ +static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, + GetBitContext *gb) +{ + if (get_bits1(gb)) { + av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n"); + return AVERROR_INVALIDDATA; + } + ics->window_sequence[1] = ics->window_sequence[0]; + ics->window_sequence[0] = get_bits(gb, 2); + ics->use_kb_window[1] = ics->use_kb_window[0]; + ics->use_kb_window[0] = get_bits1(gb); + ics->num_window_groups = 1; + ics->group_len[0] = 1; + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + int i; + ics->max_sfb = get_bits(gb, 4); + for (i = 0; i < 7; i++) { + if (get_bits1(gb)) { + ics->group_len[ics->num_window_groups - 1]++; + } else { + ics->num_window_groups++; + ics->group_len[ics->num_window_groups - 1] = 1; + } + } + ics->num_windows = 8; + ics->swb_offset = ff_swb_offset_128[ac->oc[1].m4ac.sampling_index]; + ics->num_swb = ff_aac_num_swb_128[ac->oc[1].m4ac.sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_128[ac->oc[1].m4ac.sampling_index]; + ics->predictor_present = 0; + } else { + ics->max_sfb = get_bits(gb, 6); + ics->num_windows = 1; + ics->swb_offset = ff_swb_offset_1024[ac->oc[1].m4ac.sampling_index]; + ics->num_swb = ff_aac_num_swb_1024[ac->oc[1].m4ac.sampling_index]; + ics->tns_max_bands = ff_tns_max_bands_1024[ac->oc[1].m4ac.sampling_index]; + ics->predictor_present = get_bits1(gb); + ics->predictor_reset_group = 0; + if (ics->predictor_present) { + if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) { + if (decode_prediction(ac, ics, gb)) { + goto fail; + } + } else if (ac->oc[1].m4ac.object_type == AOT_AAC_LC) { + av_log(ac->avctx, AV_LOG_ERROR, "Prediction is not allowed in AAC-LC.\n"); + goto fail; + } else { + if ((ics->ltp.present = get_bits(gb, 1))) + decode_ltp(&ics->ltp, gb, ics->max_sfb); + } + } + } + + if (ics->max_sfb > ics->num_swb) { + av_log(ac->avctx, AV_LOG_ERROR, + "Number of scalefactor bands in group (%d) exceeds limit (%d).\n", + ics->max_sfb, ics->num_swb); + goto fail; + } + + return 0; +fail: + ics->max_sfb = 0; + return AVERROR_INVALIDDATA; +} + +/** + * Decode band types (section_data payload); reference: table 4.46. + * + * @param band_type array of the used band type + * @param band_type_run_end array of the last scalefactor band of a band type run + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_band_types(AACContext *ac, enum BandType band_type[120], + int band_type_run_end[120], GetBitContext *gb, + IndividualChannelStream *ics) +{ + int g, idx = 0; + const int bits = (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) ? 3 : 5; + for (g = 0; g < ics->num_window_groups; g++) { + int k = 0; + while (k < ics->max_sfb) { + uint8_t sect_end = k; + int sect_len_incr; + int sect_band_type = get_bits(gb, 4); + if (sect_band_type == 12) { + av_log(ac->avctx, AV_LOG_ERROR, "invalid band type\n"); + return -1; + } + do { + sect_len_incr = get_bits(gb, bits); + sect_end += sect_len_incr; + if (get_bits_left(gb) < 0) { + av_log(ac->avctx, AV_LOG_ERROR, "decode_band_types: "overread_err); + return -1; + } + if (sect_end > ics->max_sfb) { + av_log(ac->avctx, AV_LOG_ERROR, + "Number of bands (%d) exceeds limit (%d).\n", + sect_end, ics->max_sfb); + return -1; + } + } while (sect_len_incr == (1 << bits) - 1); + for (; k < sect_end; k++) { + band_type [idx] = sect_band_type; + band_type_run_end[idx++] = sect_end; + } + } + } + return 0; +} + +/** + * Decode scalefactors; reference: table 4.47. + * + * @param global_gain first scalefactor value as scalefactors are differentially coded + * @param band_type array of the used band type + * @param band_type_run_end array of the last scalefactor band of a band type run + * @param sf array of scalefactors or intensity stereo positions + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_scalefactors(AACContext *ac, float sf[120], GetBitContext *gb, + unsigned int global_gain, + IndividualChannelStream *ics, + enum BandType band_type[120], + int band_type_run_end[120]) +{ + int g, i, idx = 0; + int offset[3] = { global_gain, global_gain - 90, 0 }; + int clipped_offset; + int noise_flag = 1; + for (g = 0; g < ics->num_window_groups; g++) { + for (i = 0; i < ics->max_sfb;) { + int run_end = band_type_run_end[idx]; + if (band_type[idx] == ZERO_BT) { + for (; i < run_end; i++, idx++) + sf[idx] = 0.; + } else if ((band_type[idx] == INTENSITY_BT) || (band_type[idx] == INTENSITY_BT2)) { + for (; i < run_end; i++, idx++) { + offset[2] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60; + clipped_offset = av_clip(offset[2], -155, 100); + if (offset[2] != clipped_offset) { + avpriv_request_sample(ac->avctx, + "If you heard an audible artifact, there may be a bug in the decoder. " + "Clipped intensity stereo position (%d -> %d)", + offset[2], clipped_offset); + } + sf[idx] = ff_aac_pow2sf_tab[-clipped_offset + POW_SF2_ZERO]; + } + } else if (band_type[idx] == NOISE_BT) { + for (; i < run_end; i++, idx++) { + if (noise_flag-- > 0) + offset[1] += get_bits(gb, 9) - 256; + else + offset[1] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60; + clipped_offset = av_clip(offset[1], -100, 155); + if (offset[1] != clipped_offset) { + avpriv_request_sample(ac->avctx, + "If you heard an audible artifact, there may be a bug in the decoder. " + "Clipped noise gain (%d -> %d)", + offset[1], clipped_offset); + } + sf[idx] = -ff_aac_pow2sf_tab[clipped_offset + POW_SF2_ZERO]; + } + } else { + for (; i < run_end; i++, idx++) { + offset[0] += get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60; + if (offset[0] > 255U) { + av_log(ac->avctx, AV_LOG_ERROR, + "Scalefactor (%d) out of range.\n", offset[0]); + return -1; + } + sf[idx] = -ff_aac_pow2sf_tab[offset[0] - 100 + POW_SF2_ZERO]; + } + } + } + } + return 0; +} + +/** + * Decode pulse data; reference: table 4.7. + */ +static int decode_pulses(Pulse *pulse, GetBitContext *gb, + const uint16_t *swb_offset, int num_swb) +{ + int i, pulse_swb; + pulse->num_pulse = get_bits(gb, 2) + 1; + pulse_swb = get_bits(gb, 6); + if (pulse_swb >= num_swb) + return -1; + pulse->pos[0] = swb_offset[pulse_swb]; + pulse->pos[0] += get_bits(gb, 5); + if (pulse->pos[0] > 1023) + return -1; + pulse->amp[0] = get_bits(gb, 4); + for (i = 1; i < pulse->num_pulse; i++) { + pulse->pos[i] = get_bits(gb, 5) + pulse->pos[i - 1]; + if (pulse->pos[i] > 1023) + return -1; + pulse->amp[i] = get_bits(gb, 4); + } + return 0; +} + +/** + * Decode Temporal Noise Shaping data; reference: table 4.48. + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_tns(AACContext *ac, TemporalNoiseShaping *tns, + GetBitContext *gb, const IndividualChannelStream *ics) +{ + int w, filt, i, coef_len, coef_res, coef_compress; + const int is8 = ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE; + const int tns_max_order = is8 ? 7 : ac->oc[1].m4ac.object_type == AOT_AAC_MAIN ? 20 : 12; + for (w = 0; w < ics->num_windows; w++) { + if ((tns->n_filt[w] = get_bits(gb, 2 - is8))) { + coef_res = get_bits1(gb); + + for (filt = 0; filt < tns->n_filt[w]; filt++) { + int tmp2_idx; + tns->length[w][filt] = get_bits(gb, 6 - 2 * is8); + + if ((tns->order[w][filt] = get_bits(gb, 5 - 2 * is8)) > tns_max_order) { + av_log(ac->avctx, AV_LOG_ERROR, "TNS filter order %d is greater than maximum %d.\n", + tns->order[w][filt], tns_max_order); + tns->order[w][filt] = 0; + return -1; + } + if (tns->order[w][filt]) { + tns->direction[w][filt] = get_bits1(gb); + coef_compress = get_bits1(gb); + coef_len = coef_res + 3 - coef_compress; + tmp2_idx = 2 * coef_compress + coef_res; + + for (i = 0; i < tns->order[w][filt]; i++) + tns->coef[w][filt][i] = tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]; + } + } + } + } + return 0; +} + +/** + * Decode Mid/Side data; reference: table 4.54. + * + * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s; + * [1] mask is decoded from bitstream; [2] mask is all 1s; + * [3] reserved for scalable AAC + */ +static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb, + int ms_present) +{ + int idx; + if (ms_present == 1) { + for (idx = 0; idx < cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb; idx++) + cpe->ms_mask[idx] = get_bits1(gb); + } else if (ms_present == 2) { + memset(cpe->ms_mask, 1, sizeof(cpe->ms_mask[0]) * cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb); + } +} + +#ifndef VMUL2 +static inline float *VMUL2(float *dst, const float *v, unsigned idx, + const float *scale) +{ + float s = *scale; + *dst++ = v[idx & 15] * s; + *dst++ = v[idx>>4 & 15] * s; + return dst; +} +#endif + +#ifndef VMUL4 +static inline float *VMUL4(float *dst, const float *v, unsigned idx, + const float *scale) +{ + float s = *scale; + *dst++ = v[idx & 3] * s; + *dst++ = v[idx>>2 & 3] * s; + *dst++ = v[idx>>4 & 3] * s; + *dst++ = v[idx>>6 & 3] * s; + return dst; +} +#endif + +#ifndef VMUL2S +static inline float *VMUL2S(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + union av_intfloat32 s0, s1; + + s0.f = s1.f = *scale; + s0.i ^= sign >> 1 << 31; + s1.i ^= sign << 31; + + *dst++ = v[idx & 15] * s0.f; + *dst++ = v[idx>>4 & 15] * s1.f; + + return dst; +} +#endif + +#ifndef VMUL4S +static inline float *VMUL4S(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + unsigned nz = idx >> 12; + union av_intfloat32 s = { .f = *scale }; + union av_intfloat32 t; + + t.i = s.i ^ (sign & 1U<<31); + *dst++ = v[idx & 3] * t.f; + + sign <<= nz & 1; nz >>= 1; + t.i = s.i ^ (sign & 1U<<31); + *dst++ = v[idx>>2 & 3] * t.f; + + sign <<= nz & 1; nz >>= 1; + t.i = s.i ^ (sign & 1U<<31); + *dst++ = v[idx>>4 & 3] * t.f; + + sign <<= nz & 1; + t.i = s.i ^ (sign & 1U<<31); + *dst++ = v[idx>>6 & 3] * t.f; + + return dst; +} +#endif + +/** + * Decode spectral data; reference: table 4.50. + * Dequantize and scale spectral data; reference: 4.6.3.3. + * + * @param coef array of dequantized, scaled spectral data + * @param sf array of scalefactors or intensity stereo positions + * @param pulse_present set if pulses are present + * @param pulse pointer to pulse data struct + * @param band_type array of the used band type + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_spectrum_and_dequant(AACContext *ac, float coef[1024], + GetBitContext *gb, const float sf[120], + int pulse_present, const Pulse *pulse, + const IndividualChannelStream *ics, + enum BandType band_type[120]) +{ + int i, k, g, idx = 0; + const int c = 1024 / ics->num_windows; + const uint16_t *offsets = ics->swb_offset; + float *coef_base = coef; + + for (g = 0; g < ics->num_windows; g++) + memset(coef + g * 128 + offsets[ics->max_sfb], 0, sizeof(float) * (c - offsets[ics->max_sfb])); + + for (g = 0; g < ics->num_window_groups; g++) { + unsigned g_len = ics->group_len[g]; + + for (i = 0; i < ics->max_sfb; i++, idx++) { + const unsigned cbt_m1 = band_type[idx] - 1; + float *cfo = coef + offsets[i]; + int off_len = offsets[i + 1] - offsets[i]; + int group; + + if (cbt_m1 >= INTENSITY_BT2 - 1) { + for (group = 0; group < g_len; group++, cfo+=128) { + memset(cfo, 0, off_len * sizeof(float)); + } + } else if (cbt_m1 == NOISE_BT - 1) { + for (group = 0; group < g_len; group++, cfo+=128) { + float scale; + float band_energy; + + for (k = 0; k < off_len; k++) { + ac->random_state = lcg_random(ac->random_state); + cfo[k] = ac->random_state; + } + + band_energy = ac->fdsp.scalarproduct_float(cfo, cfo, off_len); + scale = sf[idx] / sqrtf(band_energy); + ac->fdsp.vector_fmul_scalar(cfo, cfo, scale, off_len); + } + } else { + const float *vq = ff_aac_codebook_vector_vals[cbt_m1]; + const uint16_t *cb_vector_idx = ff_aac_codebook_vector_idx[cbt_m1]; + VLC_TYPE (*vlc_tab)[2] = vlc_spectral[cbt_m1].table; + OPEN_READER(re, gb); + + switch (cbt_m1 >> 1) { + case 0: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned cb_idx; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + cb_idx = cb_vector_idx[code]; + cf = VMUL4(cf, vq, cb_idx, sf + idx); + } while (len -= 4); + } + break; + + case 1: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned nnz; + unsigned cb_idx; + uint32_t bits; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + cb_idx = cb_vector_idx[code]; + nnz = cb_idx >> 8 & 15; + bits = nnz ? GET_CACHE(re, gb) : 0; + LAST_SKIP_BITS(re, gb, nnz); + cf = VMUL4S(cf, vq, cb_idx, bits, sf + idx); + } while (len -= 4); + } + break; + + case 2: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned cb_idx; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + cb_idx = cb_vector_idx[code]; + cf = VMUL2(cf, vq, cb_idx, sf + idx); + } while (len -= 2); + } + break; + + case 3: + case 4: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned nnz; + unsigned cb_idx; + unsigned sign; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + cb_idx = cb_vector_idx[code]; + nnz = cb_idx >> 8 & 15; + sign = nnz ? SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12) : 0; + LAST_SKIP_BITS(re, gb, nnz); + cf = VMUL2S(cf, vq, cb_idx, sign, sf + idx); + } while (len -= 2); + } + break; + + default: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + uint32_t *icf = (uint32_t *) cf; + int len = off_len; + + do { + int code; + unsigned nzt, nnz; + unsigned cb_idx; + uint32_t bits; + int j; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + + if (!code) { + *icf++ = 0; + *icf++ = 0; + continue; + } + + cb_idx = cb_vector_idx[code]; + nnz = cb_idx >> 12; + nzt = cb_idx >> 8; + bits = SHOW_UBITS(re, gb, nnz) << (32-nnz); + LAST_SKIP_BITS(re, gb, nnz); + + for (j = 0; j < 2; j++) { + if (nzt & 1< 8) { + av_log(ac->avctx, AV_LOG_ERROR, "error in spectral data, ESC overflow\n"); + return -1; + } + + SKIP_BITS(re, gb, b + 1); + b += 4; + n = (1 << b) + SHOW_UBITS(re, gb, b); + LAST_SKIP_BITS(re, gb, b); + *icf++ = cbrt_tab[n] | (bits & 1U<<31); + bits <<= 1; + } else { + unsigned v = ((const uint32_t*)vq)[cb_idx & 15]; + *icf++ = (bits & 1U<<31) | v; + bits <<= !!v; + } + cb_idx >>= 4; + } + } while (len -= 2); + + ac->fdsp.vector_fmul_scalar(cfo, cfo, sf[idx], off_len); + } + } + + CLOSE_READER(re, gb); + } + } + coef += g_len << 7; + } + + if (pulse_present) { + idx = 0; + for (i = 0; i < pulse->num_pulse; i++) { + float co = coef_base[ pulse->pos[i] ]; + while (offsets[idx + 1] <= pulse->pos[i]) + idx++; + if (band_type[idx] != NOISE_BT && sf[idx]) { + float ico = -pulse->amp[i]; + if (co) { + co /= sf[idx]; + ico = co / sqrtf(sqrtf(fabsf(co))) + (co > 0 ? -ico : ico); + } + coef_base[ pulse->pos[i] ] = cbrtf(fabsf(ico)) * ico * sf[idx]; + } + } + } + return 0; +} + +static av_always_inline float flt16_round(float pf) +{ + union av_intfloat32 tmp; + tmp.f = pf; + tmp.i = (tmp.i + 0x00008000U) & 0xFFFF0000U; + return tmp.f; +} + +static av_always_inline float flt16_even(float pf) +{ + union av_intfloat32 tmp; + tmp.f = pf; + tmp.i = (tmp.i + 0x00007FFFU + (tmp.i & 0x00010000U >> 16)) & 0xFFFF0000U; + return tmp.f; +} + +static av_always_inline float flt16_trunc(float pf) +{ + union av_intfloat32 pun; + pun.f = pf; + pun.i &= 0xFFFF0000U; + return pun.f; +} + +static av_always_inline void predict(PredictorState *ps, float *coef, + int output_enable) +{ + const float a = 0.953125; // 61.0 / 64 + const float alpha = 0.90625; // 29.0 / 32 + float e0, e1; + float pv; + float k1, k2; + float r0 = ps->r0, r1 = ps->r1; + float cor0 = ps->cor0, cor1 = ps->cor1; + float var0 = ps->var0, var1 = ps->var1; + + k1 = var0 > 1 ? cor0 * flt16_even(a / var0) : 0; + k2 = var1 > 1 ? cor1 * flt16_even(a / var1) : 0; + + pv = flt16_round(k1 * r0 + k2 * r1); + if (output_enable) + *coef += pv; + + e0 = *coef; + e1 = e0 - k1 * r0; + + ps->cor1 = flt16_trunc(alpha * cor1 + r1 * e1); + ps->var1 = flt16_trunc(alpha * var1 + 0.5f * (r1 * r1 + e1 * e1)); + ps->cor0 = flt16_trunc(alpha * cor0 + r0 * e0); + ps->var0 = flt16_trunc(alpha * var0 + 0.5f * (r0 * r0 + e0 * e0)); + + ps->r1 = flt16_trunc(a * (r0 - k1 * e0)); + ps->r0 = flt16_trunc(a * e0); +} + +/** + * Apply AAC-Main style frequency domain prediction. + */ +static void apply_prediction(AACContext *ac, SingleChannelElement *sce) +{ + int sfb, k; + + if (!sce->ics.predictor_initialized) { + reset_all_predictors(sce->predictor_state); + sce->ics.predictor_initialized = 1; + } + + if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) { + for (sfb = 0; sfb < ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]; sfb++) { + for (k = sce->ics.swb_offset[sfb]; k < sce->ics.swb_offset[sfb + 1]; k++) { + predict(&sce->predictor_state[k], &sce->coeffs[k], + sce->ics.predictor_present && sce->ics.prediction_used[sfb]); + } + } + if (sce->ics.predictor_reset_group) + reset_predictor_group(sce->predictor_state, sce->ics.predictor_reset_group); + } else + reset_all_predictors(sce->predictor_state); +} + +/** + * Decode an individual_channel_stream payload; reference: table 4.44. + * + * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information. + * @param scale_flag scalable [1] or non-scalable [0] AAC (Unused until scalable AAC is implemented.) + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_ics(AACContext *ac, SingleChannelElement *sce, + GetBitContext *gb, int common_window, int scale_flag) +{ + Pulse pulse; + TemporalNoiseShaping *tns = &sce->tns; + IndividualChannelStream *ics = &sce->ics; + float *out = sce->coeffs; + int global_gain, pulse_present = 0; + + /* This assignment is to silence a GCC warning about the variable being used + * uninitialized when in fact it always is. + */ + pulse.num_pulse = 0; + + global_gain = get_bits(gb, 8); + + if (!common_window && !scale_flag) { + if (decode_ics_info(ac, ics, gb) < 0) + return AVERROR_INVALIDDATA; + } + + if (decode_band_types(ac, sce->band_type, sce->band_type_run_end, gb, ics) < 0) + return -1; + if (decode_scalefactors(ac, sce->sf, gb, global_gain, ics, sce->band_type, sce->band_type_run_end) < 0) + return -1; + + pulse_present = 0; + if (!scale_flag) { + if ((pulse_present = get_bits1(gb))) { + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + av_log(ac->avctx, AV_LOG_ERROR, "Pulse tool not allowed in eight short sequence.\n"); + return -1; + } + if (decode_pulses(&pulse, gb, ics->swb_offset, ics->num_swb)) { + av_log(ac->avctx, AV_LOG_ERROR, "Pulse data corrupt or invalid.\n"); + return -1; + } + } + if ((tns->present = get_bits1(gb)) && decode_tns(ac, tns, gb, ics)) + return -1; + if (get_bits1(gb)) { + avpriv_request_sample(ac->avctx, "SSR"); + return AVERROR_PATCHWELCOME; + } + } + + if (decode_spectrum_and_dequant(ac, out, gb, sce->sf, pulse_present, &pulse, ics, sce->band_type) < 0) + return -1; + + if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window) + apply_prediction(ac, sce); + + return 0; +} + +/** + * Mid/Side stereo decoding; reference: 4.6.8.1.3. + */ +static void apply_mid_side_stereo(AACContext *ac, ChannelElement *cpe) +{ + const IndividualChannelStream *ics = &cpe->ch[0].ics; + float *ch0 = cpe->ch[0].coeffs; + float *ch1 = cpe->ch[1].coeffs; + int g, i, group, idx = 0; + const uint16_t *offsets = ics->swb_offset; + for (g = 0; g < ics->num_window_groups; g++) { + for (i = 0; i < ics->max_sfb; i++, idx++) { + if (cpe->ms_mask[idx] && + cpe->ch[0].band_type[idx] < NOISE_BT && cpe->ch[1].band_type[idx] < NOISE_BT) { + for (group = 0; group < ics->group_len[g]; group++) { + ac->fdsp.butterflies_float(ch0 + group * 128 + offsets[i], + ch1 + group * 128 + offsets[i], + offsets[i+1] - offsets[i]); + } + } + } + ch0 += ics->group_len[g] * 128; + ch1 += ics->group_len[g] * 128; + } +} + +/** + * intensity stereo decoding; reference: 4.6.8.2.3 + * + * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s; + * [1] mask is decoded from bitstream; [2] mask is all 1s; + * [3] reserved for scalable AAC + */ +static void apply_intensity_stereo(AACContext *ac, ChannelElement *cpe, int ms_present) +{ + const IndividualChannelStream *ics = &cpe->ch[1].ics; + SingleChannelElement *sce1 = &cpe->ch[1]; + float *coef0 = cpe->ch[0].coeffs, *coef1 = cpe->ch[1].coeffs; + const uint16_t *offsets = ics->swb_offset; + int g, group, i, idx = 0; + int c; + float scale; + for (g = 0; g < ics->num_window_groups; g++) { + for (i = 0; i < ics->max_sfb;) { + if (sce1->band_type[idx] == INTENSITY_BT || sce1->band_type[idx] == INTENSITY_BT2) { + const int bt_run_end = sce1->band_type_run_end[idx]; + for (; i < bt_run_end; i++, idx++) { + c = -1 + 2 * (sce1->band_type[idx] - 14); + if (ms_present) + c *= 1 - 2 * cpe->ms_mask[idx]; + scale = c * sce1->sf[idx]; + for (group = 0; group < ics->group_len[g]; group++) + ac->fdsp.vector_fmul_scalar(coef1 + group * 128 + offsets[i], + coef0 + group * 128 + offsets[i], + scale, + offsets[i + 1] - offsets[i]); + } + } else { + int bt_run_end = sce1->band_type_run_end[idx]; + idx += bt_run_end - i; + i = bt_run_end; + } + } + coef0 += ics->group_len[g] * 128; + coef1 += ics->group_len[g] * 128; + } +} + +/** + * Decode a channel_pair_element; reference: table 4.4. + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_cpe(AACContext *ac, GetBitContext *gb, ChannelElement *cpe) +{ + int i, ret, common_window, ms_present = 0; + + common_window = get_bits1(gb); + if (common_window) { + if (decode_ics_info(ac, &cpe->ch[0].ics, gb)) + return AVERROR_INVALIDDATA; + i = cpe->ch[1].ics.use_kb_window[0]; + cpe->ch[1].ics = cpe->ch[0].ics; + cpe->ch[1].ics.use_kb_window[1] = i; + if (cpe->ch[1].ics.predictor_present && (ac->oc[1].m4ac.object_type != AOT_AAC_MAIN)) + if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1))) + decode_ltp(&cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb); + ms_present = get_bits(gb, 2); + if (ms_present == 3) { + av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n"); + return -1; + } else if (ms_present) + decode_mid_side_stereo(cpe, gb, ms_present); + } + if ((ret = decode_ics(ac, &cpe->ch[0], gb, common_window, 0))) + return ret; + if ((ret = decode_ics(ac, &cpe->ch[1], gb, common_window, 0))) + return ret; + + if (common_window) { + if (ms_present) + apply_mid_side_stereo(ac, cpe); + if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) { + apply_prediction(ac, &cpe->ch[0]); + apply_prediction(ac, &cpe->ch[1]); + } + } + + apply_intensity_stereo(ac, cpe, ms_present); + return 0; +} + +static const float cce_scale[] = { + 1.09050773266525765921, //2^(1/8) + 1.18920711500272106672, //2^(1/4) + M_SQRT2, + 2, +}; + +/** + * Decode coupling_channel_element; reference: table 4.8. + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int decode_cce(AACContext *ac, GetBitContext *gb, ChannelElement *che) +{ + int num_gain = 0; + int c, g, sfb, ret; + int sign; + float scale; + SingleChannelElement *sce = &che->ch[0]; + ChannelCoupling *coup = &che->coup; + + coup->coupling_point = 2 * get_bits1(gb); + coup->num_coupled = get_bits(gb, 3); + for (c = 0; c <= coup->num_coupled; c++) { + num_gain++; + coup->type[c] = get_bits1(gb) ? TYPE_CPE : TYPE_SCE; + coup->id_select[c] = get_bits(gb, 4); + if (coup->type[c] == TYPE_CPE) { + coup->ch_select[c] = get_bits(gb, 2); + if (coup->ch_select[c] == 3) + num_gain++; + } else + coup->ch_select[c] = 2; + } + coup->coupling_point += get_bits1(gb) || (coup->coupling_point >> 1); + + sign = get_bits(gb, 1); + scale = cce_scale[get_bits(gb, 2)]; + + if ((ret = decode_ics(ac, sce, gb, 0, 0))) + return ret; + + for (c = 0; c < num_gain; c++) { + int idx = 0; + int cge = 1; + int gain = 0; + float gain_cache = 1.; + if (c) { + cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb); + gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0; + gain_cache = powf(scale, -gain); + } + if (coup->coupling_point == AFTER_IMDCT) { + coup->gain[c][0] = gain_cache; + } else { + for (g = 0; g < sce->ics.num_window_groups; g++) { + for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) { + if (sce->band_type[idx] != ZERO_BT) { + if (!cge) { + int t = get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60; + if (t) { + int s = 1; + t = gain += t; + if (sign) { + s -= 2 * (t & 0x1); + t >>= 1; + } + gain_cache = powf(scale, -t) * s; + } + } + coup->gain[c][idx] = gain_cache; + } + } + } + } + } + return 0; +} + +/** + * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53. + * + * @return Returns number of bytes consumed. + */ +static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc, + GetBitContext *gb) +{ + int i; + int num_excl_chan = 0; + + do { + for (i = 0; i < 7; i++) + che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb); + } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb)); + + return num_excl_chan / 7; +} + +/** + * Decode dynamic range information; reference: table 4.52. + * + * @return Returns number of bytes consumed. + */ +static int decode_dynamic_range(DynamicRangeControl *che_drc, + GetBitContext *gb) +{ + int n = 1; + int drc_num_bands = 1; + int i; + + /* pce_tag_present? */ + if (get_bits1(gb)) { + che_drc->pce_instance_tag = get_bits(gb, 4); + skip_bits(gb, 4); // tag_reserved_bits + n++; + } + + /* excluded_chns_present? */ + if (get_bits1(gb)) { + n += decode_drc_channel_exclusions(che_drc, gb); + } + + /* drc_bands_present? */ + if (get_bits1(gb)) { + che_drc->band_incr = get_bits(gb, 4); + che_drc->interpolation_scheme = get_bits(gb, 4); + n++; + drc_num_bands += che_drc->band_incr; + for (i = 0; i < drc_num_bands; i++) { + che_drc->band_top[i] = get_bits(gb, 8); + n++; + } + } + + /* prog_ref_level_present? */ + if (get_bits1(gb)) { + che_drc->prog_ref_level = get_bits(gb, 7); + skip_bits1(gb); // prog_ref_level_reserved_bits + n++; + } + + for (i = 0; i < drc_num_bands; i++) { + che_drc->dyn_rng_sgn[i] = get_bits1(gb); + che_drc->dyn_rng_ctl[i] = get_bits(gb, 7); + n++; + } + + return n; +} + +static int decode_fill(AACContext *ac, GetBitContext *gb, int len) { + uint8_t buf[256]; + int i, major, minor; + + if (len < 13+7*8) + goto unknown; + + get_bits(gb, 13); len -= 13; + + for(i=0; i+1=8; i++, len-=8) + buf[i] = get_bits(gb, 8); + + buf[i] = 0; + if (ac->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(ac->avctx, AV_LOG_DEBUG, "FILL:%s\n", buf); + + if (sscanf(buf, "libfaac %d.%d", &major, &minor) == 2){ + ac->avctx->internal->skip_samples = 1024; + } + +unknown: + skip_bits_long(gb, len); + + return 0; +} + +/** + * Decode extension data (incomplete); reference: table 4.51. + * + * @param cnt length of TYPE_FIL syntactic element in bytes + * + * @return Returns number of bytes consumed + */ +static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt, + ChannelElement *che, enum RawDataBlockType elem_type) +{ + int crc_flag = 0; + int res = cnt; + switch (get_bits(gb, 4)) { // extension type + case EXT_SBR_DATA_CRC: + crc_flag++; + case EXT_SBR_DATA: + if (!che) { + av_log(ac->avctx, AV_LOG_ERROR, "SBR was found before the first channel element.\n"); + return res; + } else if (!ac->oc[1].m4ac.sbr) { + av_log(ac->avctx, AV_LOG_ERROR, "SBR signaled to be not-present but was found in the bitstream.\n"); + skip_bits_long(gb, 8 * cnt - 4); + return res; + } else if (ac->oc[1].m4ac.sbr == -1 && ac->oc[1].status == OC_LOCKED) { + av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n"); + skip_bits_long(gb, 8 * cnt - 4); + return res; + } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED && ac->avctx->channels == 1) { + ac->oc[1].m4ac.sbr = 1; + ac->oc[1].m4ac.ps = 1; + output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, + ac->oc[1].status, 1); + } else { + ac->oc[1].m4ac.sbr = 1; + } + res = ff_decode_sbr_extension(ac, &che->sbr, gb, crc_flag, cnt, elem_type); + break; + case EXT_DYNAMIC_RANGE: + res = decode_dynamic_range(&ac->che_drc, gb); + break; + case EXT_FILL: + decode_fill(ac, gb, 8 * cnt - 4); + break; + case EXT_FILL_DATA: + case EXT_DATA_ELEMENT: + default: + skip_bits_long(gb, 8 * cnt - 4); + break; + }; + return res; +} + +/** + * Decode Temporal Noise Shaping filter coefficients and apply all-pole filters; reference: 4.6.9.3. + * + * @param decode 1 if tool is used normally, 0 if tool is used in LTP. + * @param coef spectral coefficients + */ +static void apply_tns(float coef[1024], TemporalNoiseShaping *tns, + IndividualChannelStream *ics, int decode) +{ + const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb); + int w, filt, m, i; + int bottom, top, order, start, end, size, inc; + float lpc[TNS_MAX_ORDER]; + float tmp[TNS_MAX_ORDER+1]; + + for (w = 0; w < ics->num_windows; w++) { + bottom = ics->num_swb; + for (filt = 0; filt < tns->n_filt[w]; filt++) { + top = bottom; + bottom = FFMAX(0, top - tns->length[w][filt]); + order = tns->order[w][filt]; + if (order == 0) + continue; + + // tns_decode_coef + compute_lpc_coefs(tns->coef[w][filt], order, lpc, 0, 0, 0); + + start = ics->swb_offset[FFMIN(bottom, mmm)]; + end = ics->swb_offset[FFMIN( top, mmm)]; + if ((size = end - start) <= 0) + continue; + if (tns->direction[w][filt]) { + inc = -1; + start = end - 1; + } else { + inc = 1; + } + start += w * 128; + + if (decode) { + // ar filter + for (m = 0; m < size; m++, start += inc) + for (i = 1; i <= FFMIN(m, order); i++) + coef[start] -= coef[start - i * inc] * lpc[i - 1]; + } else { + // ma filter + for (m = 0; m < size; m++, start += inc) { + tmp[0] = coef[start]; + for (i = 1; i <= FFMIN(m, order); i++) + coef[start] += tmp[i] * lpc[i - 1]; + for (i = order; i > 0; i--) + tmp[i] = tmp[i - 1]; + } + } + } + } +} + +/** + * Apply windowing and MDCT to obtain the spectral + * coefficient from the predicted sample by LTP. + */ +static void windowing_and_mdct_ltp(AACContext *ac, float *out, + float *in, IndividualChannelStream *ics) +{ + const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128; + + if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) { + ac->fdsp.vector_fmul(in, in, lwindow_prev, 1024); + } else { + memset(in, 0, 448 * sizeof(float)); + ac->fdsp.vector_fmul(in + 448, in + 448, swindow_prev, 128); + } + if (ics->window_sequence[0] != LONG_START_SEQUENCE) { + ac->fdsp.vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024); + } else { + ac->fdsp.vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128); + memset(in + 1024 + 576, 0, 448 * sizeof(float)); + } + ac->mdct_ltp.mdct_calc(&ac->mdct_ltp, out, in); +} + +/** + * Apply the long term prediction + */ +static void apply_ltp(AACContext *ac, SingleChannelElement *sce) +{ + const LongTermPrediction *ltp = &sce->ics.ltp; + const uint16_t *offsets = sce->ics.swb_offset; + int i, sfb; + + if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) { + float *predTime = sce->ret; + float *predFreq = ac->buf_mdct; + int16_t num_samples = 2048; + + if (ltp->lag < 1024) + num_samples = ltp->lag + 1024; + for (i = 0; i < num_samples; i++) + predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef; + memset(&predTime[i], 0, (2048 - i) * sizeof(float)); + + ac->windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics); + + if (sce->tns.present) + ac->apply_tns(predFreq, &sce->tns, &sce->ics, 0); + + for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++) + if (ltp->used[sfb]) + for (i = offsets[sfb]; i < offsets[sfb + 1]; i++) + sce->coeffs[i] += predFreq[i]; + } +} + +/** + * Update the LTP buffer for next frame + */ +static void update_ltp(AACContext *ac, SingleChannelElement *sce) +{ + IndividualChannelStream *ics = &sce->ics; + float *saved = sce->saved; + float *saved_ltp = sce->coeffs; + const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + int i; + + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + memcpy(saved_ltp, saved, 512 * sizeof(float)); + memset(saved_ltp + 576, 0, 448 * sizeof(float)); + ac->fdsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64); + for (i = 0; i < 64; i++) + saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i]; + } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) { + memcpy(saved_ltp, ac->buf_mdct + 512, 448 * sizeof(float)); + memset(saved_ltp + 576, 0, 448 * sizeof(float)); + ac->fdsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64); + for (i = 0; i < 64; i++) + saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i]; + } else { // LONG_STOP or ONLY_LONG + ac->fdsp.vector_fmul_reverse(saved_ltp, ac->buf_mdct + 512, &lwindow[512], 512); + for (i = 0; i < 512; i++) + saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * lwindow[511 - i]; + } + + memcpy(sce->ltp_state, sce->ltp_state+1024, 1024 * sizeof(*sce->ltp_state)); + memcpy(sce->ltp_state+1024, sce->ret, 1024 * sizeof(*sce->ltp_state)); + memcpy(sce->ltp_state+2048, saved_ltp, 1024 * sizeof(*sce->ltp_state)); +} + +/** + * Conduct IMDCT and windowing. + */ +static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce) +{ + IndividualChannelStream *ics = &sce->ics; + float *in = sce->coeffs; + float *out = sce->ret; + float *saved = sce->saved; + const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128; + float *buf = ac->buf_mdct; + float *temp = ac->temp; + int i; + + // imdct + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + for (i = 0; i < 1024; i += 128) + ac->mdct_small.imdct_half(&ac->mdct_small, buf + i, in + i); + } else + ac->mdct.imdct_half(&ac->mdct, buf, in); + + /* window overlapping + * NOTE: To simplify the overlapping code, all 'meaningless' short to long + * and long to short transitions are considered to be short to short + * transitions. This leaves just two cases (long to long and short to short) + * with a little special sauce for EIGHT_SHORT_SEQUENCE. + */ + if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) && + (ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) { + ac->fdsp.vector_fmul_window( out, saved, buf, lwindow_prev, 512); + } else { + memcpy( out, saved, 448 * sizeof(float)); + + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + ac->fdsp.vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 64); + ac->fdsp.vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 64); + ac->fdsp.vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 64); + ac->fdsp.vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 64); + ac->fdsp.vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 64); + memcpy( out + 448 + 4*128, temp, 64 * sizeof(float)); + } else { + ac->fdsp.vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64); + memcpy( out + 576, buf + 64, 448 * sizeof(float)); + } + } + + // buffer update + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + memcpy( saved, temp + 64, 64 * sizeof(float)); + ac->fdsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64); + ac->fdsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64); + ac->fdsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64); + memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(float)); + } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) { + memcpy( saved, buf + 512, 448 * sizeof(float)); + memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(float)); + } else { // LONG_STOP or ONLY_LONG + memcpy( saved, buf + 512, 512 * sizeof(float)); + } +} + +/** + * Apply dependent channel coupling (applied before IMDCT). + * + * @param index index into coupling gain array + */ +static void apply_dependent_coupling(AACContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index) +{ + IndividualChannelStream *ics = &cce->ch[0].ics; + const uint16_t *offsets = ics->swb_offset; + float *dest = target->coeffs; + const float *src = cce->ch[0].coeffs; + int g, i, group, k, idx = 0; + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { + av_log(ac->avctx, AV_LOG_ERROR, + "Dependent coupling is not supported together with LTP\n"); + return; + } + for (g = 0; g < ics->num_window_groups; g++) { + for (i = 0; i < ics->max_sfb; i++, idx++) { + if (cce->ch[0].band_type[idx] != ZERO_BT) { + const float gain = cce->coup.gain[index][idx]; + for (group = 0; group < ics->group_len[g]; group++) { + for (k = offsets[i]; k < offsets[i + 1]; k++) { + // XXX dsputil-ize + dest[group * 128 + k] += gain * src[group * 128 + k]; + } + } + } + } + dest += ics->group_len[g] * 128; + src += ics->group_len[g] * 128; + } +} + +/** + * Apply independent channel coupling (applied after IMDCT). + * + * @param index index into coupling gain array + */ +static void apply_independent_coupling(AACContext *ac, + SingleChannelElement *target, + ChannelElement *cce, int index) +{ + int i; + const float gain = cce->coup.gain[index][0]; + const float *src = cce->ch[0].ret; + float *dest = target->ret; + const int len = 1024 << (ac->oc[1].m4ac.sbr == 1); + + for (i = 0; i < len; i++) + dest[i] += gain * src[i]; +} + +/** + * channel coupling transformation interface + * + * @param apply_coupling_method pointer to (in)dependent coupling function + */ +static void apply_channel_coupling(AACContext *ac, ChannelElement *cc, + enum RawDataBlockType type, int elem_id, + enum CouplingPoint coupling_point, + void (*apply_coupling_method)(AACContext *ac, SingleChannelElement *target, ChannelElement *cce, int index)) +{ + int i, c; + + for (i = 0; i < MAX_ELEM_ID; i++) { + ChannelElement *cce = ac->che[TYPE_CCE][i]; + int index = 0; + + if (cce && cce->coup.coupling_point == coupling_point) { + ChannelCoupling *coup = &cce->coup; + + for (c = 0; c <= coup->num_coupled; c++) { + if (coup->type[c] == type && coup->id_select[c] == elem_id) { + if (coup->ch_select[c] != 1) { + apply_coupling_method(ac, &cc->ch[0], cce, index); + if (coup->ch_select[c] != 0) + index++; + } + if (coup->ch_select[c] != 2) + apply_coupling_method(ac, &cc->ch[1], cce, index++); + } else + index += 1 + (coup->ch_select[c] == 3); + } + } + } +} + +/** + * Convert spectral data to float samples, applying all supported tools as appropriate. + */ +static void spectral_to_sample(AACContext *ac) +{ + int i, type; + for (type = 3; type >= 0; type--) { + for (i = 0; i < MAX_ELEM_ID; i++) { + ChannelElement *che = ac->che[type][i]; + if (che) { + if (type <= TYPE_CPE) + apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling); + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) { + if (che->ch[0].ics.predictor_present) { + if (che->ch[0].ics.ltp.present) + ac->apply_ltp(ac, &che->ch[0]); + if (che->ch[1].ics.ltp.present && type == TYPE_CPE) + ac->apply_ltp(ac, &che->ch[1]); + } + } + if (che->ch[0].tns.present) + ac->apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1); + if (che->ch[1].tns.present) + ac->apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1); + if (type <= TYPE_CPE) + apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling); + if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) { + ac->imdct_and_windowing(ac, &che->ch[0]); + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) + ac->update_ltp(ac, &che->ch[0]); + if (type == TYPE_CPE) { + ac->imdct_and_windowing(ac, &che->ch[1]); + if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) + ac->update_ltp(ac, &che->ch[1]); + } + if (ac->oc[1].m4ac.sbr > 0) { + ff_sbr_apply(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret); + } + } + if (type <= TYPE_CCE) + apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, apply_independent_coupling); + } + } + } +} + +static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) +{ + int size; + AACADTSHeaderInfo hdr_info; + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int layout_map_tags; + + size = avpriv_aac_parse_header(gb, &hdr_info); + if (size > 0) { + if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) { + // This is 2 for "VLB " audio in NSV files. + // See samples/nsv/vlb_audio. + avpriv_report_missing_feature(ac->avctx, + "More than one AAC RDB per ADTS frame"); + ac->warned_num_aac_frames = 1; + } + push_output_configuration(ac); + if (hdr_info.chan_config) { + ac->oc[1].m4ac.chan_config = hdr_info.chan_config; + if (set_default_channel_config(ac->avctx, layout_map, + &layout_map_tags, hdr_info.chan_config)) + return -7; + if (output_configure(ac, layout_map, layout_map_tags, + FFMAX(ac->oc[1].status, OC_TRIAL_FRAME), 0)) + return -7; + } else { + ac->oc[1].m4ac.chan_config = 0; + /** + * dual mono frames in Japanese DTV can have chan_config 0 + * WITHOUT specifying PCE. + * thus, set dual mono as default. + */ + if (ac->dmono_mode && ac->oc[0].status == OC_NONE) { + layout_map_tags = 2; + layout_map[0][0] = layout_map[1][0] = TYPE_SCE; + layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT; + layout_map[0][1] = 0; + layout_map[1][1] = 1; + if (output_configure(ac, layout_map, layout_map_tags, + OC_TRIAL_FRAME, 0)) + return -7; + } + } + ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate; + ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index; + ac->oc[1].m4ac.object_type = hdr_info.object_type; + if (ac->oc[0].status != OC_LOCKED || + ac->oc[0].m4ac.chan_config != hdr_info.chan_config || + ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) { + ac->oc[1].m4ac.sbr = -1; + ac->oc[1].m4ac.ps = -1; + } + if (!hdr_info.crc_absent) + skip_bits(gb, 16); + } + return size; +} + +static int aac_decode_frame_int(AVCodecContext *avctx, void *data, + int *got_frame_ptr, GetBitContext *gb, AVPacket *avpkt) +{ + AACContext *ac = avctx->priv_data; + ChannelElement *che = NULL, *che_prev = NULL; + enum RawDataBlockType elem_type, elem_type_prev = TYPE_END; + int err, elem_id; + int samples = 0, multiplier, audio_found = 0, pce_found = 0; + int is_dmono, sce_count = 0; + + ac->frame = data; + + if (show_bits(gb, 12) == 0xfff) { + if (parse_adts_frame_header(ac, gb) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n"); + err = -1; + goto fail; + } + if (ac->oc[1].m4ac.sampling_index > 12) { + av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->oc[1].m4ac.sampling_index); + err = -1; + goto fail; + } + } + + if (frame_configure_elements(avctx) < 0) { + err = -1; + goto fail; + } + + ac->tags_mapped = 0; + // parse + while ((elem_type = get_bits(gb, 3)) != TYPE_END) { + elem_id = get_bits(gb, 4); + + if (elem_type < TYPE_DSE) { + if (!(che=get_che(ac, elem_type, elem_id))) { + av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n", + elem_type, elem_id); + err = -1; + goto fail; + } + samples = 1024; + } + + switch (elem_type) { + + case TYPE_SCE: + err = decode_ics(ac, &che->ch[0], gb, 0, 0); + audio_found = 1; + sce_count++; + break; + + case TYPE_CPE: + err = decode_cpe(ac, gb, che); + audio_found = 1; + break; + + case TYPE_CCE: + err = decode_cce(ac, gb, che); + break; + + case TYPE_LFE: + err = decode_ics(ac, &che->ch[0], gb, 0, 0); + audio_found = 1; + break; + + case TYPE_DSE: + err = skip_data_stream_element(ac, gb); + break; + + case TYPE_PCE: { + uint8_t layout_map[MAX_ELEM_ID*4][3]; + int tags; + push_output_configuration(ac); + tags = decode_pce(avctx, &ac->oc[1].m4ac, layout_map, gb); + if (tags < 0) { + err = tags; + break; + } + if (pce_found) { + av_log(avctx, AV_LOG_ERROR, + "Not evaluating a further program_config_element as this construct is dubious at best.\n"); + } else { + err = output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1); + if (!err) + ac->oc[1].m4ac.chan_config = 0; + pce_found = 1; + } + break; + } + + case TYPE_FIL: + if (elem_id == 15) + elem_id += get_bits(gb, 8) - 1; + if (get_bits_left(gb) < 8 * elem_id) { + av_log(avctx, AV_LOG_ERROR, "TYPE_FIL: "overread_err); + err = -1; + goto fail; + } + while (elem_id > 0) + elem_id -= decode_extension_payload(ac, gb, elem_id, che_prev, elem_type_prev); + err = 0; /* FIXME */ + break; + + default: + err = -1; /* should not happen, but keeps compiler happy */ + break; + } + + che_prev = che; + elem_type_prev = elem_type; + + if (err) + goto fail; + + if (get_bits_left(gb) < 3) { + av_log(avctx, AV_LOG_ERROR, overread_err); + err = -1; + goto fail; + } + } + + spectral_to_sample(ac); + + multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0; + samples <<= multiplier; + /* for dual-mono audio (SCE + SCE) */ + is_dmono = ac->dmono_mode && sce_count == 2 && + ac->oc[1].channel_layout == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT); + + if (samples) + ac->frame->nb_samples = samples; + *got_frame_ptr = !!samples; + + if (is_dmono) { + if (ac->dmono_mode == 1) + ((AVFrame *)data)->data[1] =((AVFrame *)data)->data[0]; + else if (ac->dmono_mode == 2) + ((AVFrame *)data)->data[0] =((AVFrame *)data)->data[1]; + } + + if (ac->oc[1].status && audio_found) { + avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier; + avctx->frame_size = samples; + ac->oc[1].status = OC_LOCKED; + } + + if (multiplier) { + int side_size; + const uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size); + if (side && side_size>=4) + AV_WL32(side, 2*AV_RL32(side)); + } + return 0; +fail: + pop_output_configuration(ac); + return err; +} + +static int aac_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AACContext *ac = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + GetBitContext gb; + int buf_consumed; + int buf_offset; + int err; + int new_extradata_size; + const uint8_t *new_extradata = av_packet_get_side_data(avpkt, + AV_PKT_DATA_NEW_EXTRADATA, + &new_extradata_size); + int jp_dualmono_size; + const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt, + AV_PKT_DATA_JP_DUALMONO, + &jp_dualmono_size); + + if (new_extradata && 0) { + av_free(avctx->extradata); + avctx->extradata = av_mallocz(new_extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = new_extradata_size; + memcpy(avctx->extradata, new_extradata, new_extradata_size); + push_output_configuration(ac); + if (decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac, + avctx->extradata, + avctx->extradata_size*8, 1) < 0) { + pop_output_configuration(ac); + return AVERROR_INVALIDDATA; + } + } + + ac->dmono_mode = 0; + if (jp_dualmono && jp_dualmono_size > 0) + ac->dmono_mode = 1 + *jp_dualmono; + if (ac->force_dmono_mode >= 0) + ac->dmono_mode = ac->force_dmono_mode; + + if (INT_MAX / 8 <= buf_size) + return AVERROR_INVALIDDATA; + + init_get_bits(&gb, buf, buf_size * 8); + + if ((err = aac_decode_frame_int(avctx, data, got_frame_ptr, &gb, avpkt)) < 0) + return err; + + buf_consumed = (get_bits_count(&gb) + 7) >> 3; + for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++) + if (buf[buf_offset]) + break; + + return buf_size > buf_offset ? buf_consumed : buf_size; +} + +static av_cold int aac_decode_close(AVCodecContext *avctx) +{ + AACContext *ac = avctx->priv_data; + int i, type; + + for (i = 0; i < MAX_ELEM_ID; i++) { + for (type = 0; type < 4; type++) { + if (ac->che[type][i]) + ff_aac_sbr_ctx_close(&ac->che[type][i]->sbr); + av_freep(&ac->che[type][i]); + } + } + + ff_mdct_end(&ac->mdct); + ff_mdct_end(&ac->mdct_small); + ff_mdct_end(&ac->mdct_ltp); + return 0; +} + + +#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word + +struct LATMContext { + AACContext aac_ctx; ///< containing AACContext + int initialized; ///< initialized after a valid extradata was seen + + // parser data + int audio_mux_version_A; ///< LATM syntax version + int frame_length_type; ///< 0/1 variable/fixed frame length + int frame_length; ///< frame length for fixed frame length +}; + +static inline uint32_t latm_get_value(GetBitContext *b) +{ + int length = get_bits(b, 2); + + return get_bits_long(b, (length+1)*8); +} + +static int latm_decode_audio_specific_config(struct LATMContext *latmctx, + GetBitContext *gb, int asclen) +{ + AACContext *ac = &latmctx->aac_ctx; + AVCodecContext *avctx = ac->avctx; + MPEG4AudioConfig m4ac = { 0 }; + int config_start_bit = get_bits_count(gb); + int sync_extension = 0; + int bits_consumed, esize; + + if (asclen) { + sync_extension = 1; + asclen = FFMIN(asclen, get_bits_left(gb)); + } else + asclen = get_bits_left(gb); + + if (config_start_bit % 8) { + avpriv_request_sample(latmctx->aac_ctx.avctx, + "Non-byte-aligned audio-specific config"); + return AVERROR_PATCHWELCOME; + } + if (asclen <= 0) + return AVERROR_INVALIDDATA; + bits_consumed = decode_audio_specific_config(NULL, avctx, &m4ac, + gb->buffer + (config_start_bit / 8), + asclen, sync_extension); + + if (bits_consumed < 0) + return AVERROR_INVALIDDATA; + + if (!latmctx->initialized || + ac->oc[1].m4ac.sample_rate != m4ac.sample_rate || + ac->oc[1].m4ac.chan_config != m4ac.chan_config) { + + if(latmctx->initialized) { + av_log(avctx, AV_LOG_INFO, "audio config changed\n"); + } else { + av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n"); + } + latmctx->initialized = 0; + + esize = (bits_consumed+7) / 8; + + if (avctx->extradata_size < esize) { + av_free(avctx->extradata); + avctx->extradata = av_malloc(esize + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + } + + avctx->extradata_size = esize; + memcpy(avctx->extradata, gb->buffer + (config_start_bit/8), esize); + memset(avctx->extradata+esize, 0, FF_INPUT_BUFFER_PADDING_SIZE); + } + skip_bits_long(gb, bits_consumed); + + return bits_consumed; +} + +static int read_stream_mux_config(struct LATMContext *latmctx, + GetBitContext *gb) +{ + int ret, audio_mux_version = get_bits(gb, 1); + + latmctx->audio_mux_version_A = 0; + if (audio_mux_version) + latmctx->audio_mux_version_A = get_bits(gb, 1); + + if (!latmctx->audio_mux_version_A) { + + if (audio_mux_version) + latm_get_value(gb); // taraFullness + + skip_bits(gb, 1); // allStreamSameTimeFraming + skip_bits(gb, 6); // numSubFrames + // numPrograms + if (get_bits(gb, 4)) { // numPrograms + avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple programs"); + return AVERROR_PATCHWELCOME; + } + + // for each program (which there is only one in DVB) + + // for each layer (which there is only one in DVB) + if (get_bits(gb, 3)) { // numLayer + avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple layers"); + return AVERROR_PATCHWELCOME; + } + + // for all but first stream: use_same_config = get_bits(gb, 1); + if (!audio_mux_version) { + if ((ret = latm_decode_audio_specific_config(latmctx, gb, 0)) < 0) + return ret; + } else { + int ascLen = latm_get_value(gb); + if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0) + return ret; + ascLen -= ret; + skip_bits_long(gb, ascLen); + } + + latmctx->frame_length_type = get_bits(gb, 3); + switch (latmctx->frame_length_type) { + case 0: + skip_bits(gb, 8); // latmBufferFullness + break; + case 1: + latmctx->frame_length = get_bits(gb, 9); + break; + case 3: + case 4: + case 5: + skip_bits(gb, 6); // CELP frame length table index + break; + case 6: + case 7: + skip_bits(gb, 1); // HVXC frame length table index + break; + } + + if (get_bits(gb, 1)) { // other data + if (audio_mux_version) { + latm_get_value(gb); // other_data_bits + } else { + int esc; + do { + esc = get_bits(gb, 1); + skip_bits(gb, 8); + } while (esc); + } + } + + if (get_bits(gb, 1)) // crc present + skip_bits(gb, 8); // config_crc + } + + return 0; +} + +static int read_payload_length_info(struct LATMContext *ctx, GetBitContext *gb) +{ + uint8_t tmp; + + if (ctx->frame_length_type == 0) { + int mux_slot_length = 0; + do { + tmp = get_bits(gb, 8); + mux_slot_length += tmp; + } while (tmp == 255); + return mux_slot_length; + } else if (ctx->frame_length_type == 1) { + return ctx->frame_length; + } else if (ctx->frame_length_type == 3 || + ctx->frame_length_type == 5 || + ctx->frame_length_type == 7) { + skip_bits(gb, 2); // mux_slot_length_coded + } + return 0; +} + +static int read_audio_mux_element(struct LATMContext *latmctx, + GetBitContext *gb) +{ + int err; + uint8_t use_same_mux = get_bits(gb, 1); + if (!use_same_mux) { + if ((err = read_stream_mux_config(latmctx, gb)) < 0) + return err; + } else if (!latmctx->aac_ctx.avctx->extradata) { + av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG, + "no decoder config found\n"); + return AVERROR(EAGAIN); + } + if (latmctx->audio_mux_version_A == 0) { + int mux_slot_length_bytes = read_payload_length_info(latmctx, gb); + if (mux_slot_length_bytes * 8 > get_bits_left(gb)) { + av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, "incomplete frame\n"); + return AVERROR_INVALIDDATA; + } else if (mux_slot_length_bytes * 8 + 256 < get_bits_left(gb)) { + av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, + "frame length mismatch %d << %d\n", + mux_slot_length_bytes * 8, get_bits_left(gb)); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + + +static int latm_decode_frame(AVCodecContext *avctx, void *out, + int *got_frame_ptr, AVPacket *avpkt) +{ + struct LATMContext *latmctx = avctx->priv_data; + int muxlength, err; + GetBitContext gb; + + if ((err = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0) + return err; + + // check for LOAS sync word + if (get_bits(&gb, 11) != LOAS_SYNC_WORD) + return AVERROR_INVALIDDATA; + + muxlength = get_bits(&gb, 13) + 3; + // not enough data, the parser should have sorted this out + if (muxlength > avpkt->size) + return AVERROR_INVALIDDATA; + + if ((err = read_audio_mux_element(latmctx, &gb)) < 0) + return err; + + if (!latmctx->initialized) { + if (!avctx->extradata) { + *got_frame_ptr = 0; + return avpkt->size; + } else { + push_output_configuration(&latmctx->aac_ctx); + if ((err = decode_audio_specific_config( + &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.oc[1].m4ac, + avctx->extradata, avctx->extradata_size*8, 1)) < 0) { + pop_output_configuration(&latmctx->aac_ctx); + return err; + } + latmctx->initialized = 1; + } + } + + if (show_bits(&gb, 12) == 0xfff) { + av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, + "ADTS header detected, probably as result of configuration " + "misparsing\n"); + return AVERROR_INVALIDDATA; + } + + if ((err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb, avpkt)) < 0) + return err; + + return muxlength; +} + +static av_cold int latm_decode_init(AVCodecContext *avctx) +{ + struct LATMContext *latmctx = avctx->priv_data; + int ret = aac_decode_init(avctx); + + if (avctx->extradata_size > 0) + latmctx->initialized = !ret; + + return ret; +} + +static void aacdec_init(AACContext *c) +{ + c->imdct_and_windowing = imdct_and_windowing; + c->apply_ltp = apply_ltp; + c->apply_tns = apply_tns; + c->windowing_and_mdct_ltp = windowing_and_mdct_ltp; + c->update_ltp = update_ltp; + + if(ARCH_MIPS) + ff_aacdec_init_mips(c); +} +/** + * AVOptions for Japanese DTV specific extensions (ADTS only) + */ +#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM +static const AVOption options[] = { + {"dual_mono_mode", "Select the channel to decode for dual mono", + offsetof(AACContext, force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2, + AACDEC_FLAGS, "dual_mono_mode"}, + + {"auto", "autoselection", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, + {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, + {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, + {"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, + + {NULL}, +}; + +static const AVClass aac_decoder_class = { + .class_name = "AAC decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_aac_decoder = { + .name = "aac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(AACContext), + .init = aac_decode_init, + .close = aac_decode_close, + .decode = aac_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE + }, + .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, + .channel_layouts = aac_channel_layout, + .flush = flush, + .priv_class = &aac_decoder_class, +}; + +/* + Note: This decoder filter is intended to decode LATM streams transferred + in MPEG transport streams which only contain one program. + To do a more complex LATM demuxing a separate LATM demuxer should be used. +*/ +AVCodec ff_aac_latm_decoder = { + .name = "aac_latm", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC_LATM, + .priv_data_size = sizeof(struct LATMContext), + .init = latm_decode_init, + .close = aac_decode_close, + .decode = latm_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Coding LATM syntax)"), + .sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE + }, + .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, + .channel_layouts = aac_channel_layout, + .flush = flush, +}; diff --git a/ffmpeg/libavcodec/aacdectab.h b/ffmpeg/libavcodec/aacdectab.h new file mode 100644 index 0000000..4a12b4f --- /dev/null +++ b/ffmpeg/libavcodec/aacdectab.h @@ -0,0 +1,104 @@ +/* + * AAC decoder data + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * + * 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 + */ + +/** + * @file + * AAC decoder data + * @author Oded Shimon ( ods15 ods15 dyndns org ) + * @author Maxim Gavrilov ( maxim.gavrilov gmail com ) + */ + +#ifndef AVCODEC_AACDECTAB_H +#define AVCODEC_AACDECTAB_H + +#include "libavutil/channel_layout.h" +#include "aac.h" + +#include + +/* @name ltp_coef + * Table of the LTP coefficients + */ +static const float ltp_coef[8] = { + 0.570829, 0.696616, 0.813004, 0.911304, + 0.984900, 1.067894, 1.194601, 1.369533, +}; + +/* @name tns_tmp2_map + * Tables of the tmp2[] arrays of LPC coefficients used for TNS. + * The suffix _M_N[] indicate the values of coef_compress and coef_res + * respectively. + * @{ + */ +static const float tns_tmp2_map_1_3[4] = { + 0.00000000, -0.43388373, 0.64278758, 0.34202015, +}; + +static const float tns_tmp2_map_0_3[8] = { + 0.00000000, -0.43388373, -0.78183150, -0.97492790, + 0.98480773, 0.86602539, 0.64278758, 0.34202015, +}; + +static const float tns_tmp2_map_1_4[8] = { + 0.00000000, -0.20791170, -0.40673664, -0.58778524, + 0.67369562, 0.52643216, 0.36124167, 0.18374951, +}; + +static const float tns_tmp2_map_0_4[16] = { + 0.00000000, -0.20791170, -0.40673664, -0.58778524, + -0.74314481, -0.86602539, -0.95105654, -0.99452192, + 0.99573416, 0.96182561, 0.89516330, 0.79801720, + 0.67369562, 0.52643216, 0.36124167, 0.18374951, +}; + +static const float * const tns_tmp2_map[4] = { + tns_tmp2_map_0_3, + tns_tmp2_map_0_4, + tns_tmp2_map_1_3, + tns_tmp2_map_1_4 +}; +// @} + +static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0 }; + +static const uint8_t aac_channel_layout_map[7][5][3] = { + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, }, + { { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_SCE, 1, AAC_CHANNEL_BACK }, }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, + { { TYPE_SCE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 0, AAC_CHANNEL_FRONT }, { TYPE_CPE, 1, AAC_CHANNEL_FRONT }, { TYPE_CPE, 2, AAC_CHANNEL_BACK }, { TYPE_LFE, 0, AAC_CHANNEL_LFE }, }, +}; + +static const uint64_t aac_channel_layout[8] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_7POINT1_WIDE_BACK, + 0, +}; + +#endif /* AVCODEC_AACDECTAB_H */ diff --git a/ffmpeg/libavcodec/aacenc.c b/ffmpeg/libavcodec/aacenc.c new file mode 100644 index 0000000..80dd3d8 --- /dev/null +++ b/ffmpeg/libavcodec/aacenc.c @@ -0,0 +1,827 @@ +/* + * AAC encoder + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * AAC encoder + */ + +/*********************************** + * TODOs: + * add sane pulse detection + * add temporal noise shaping + ***********************************/ + +#include "libavutil/float_dsp.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "put_bits.h" +#include "internal.h" +#include "mpeg4audio.h" +#include "kbdwin.h" +#include "sinewin.h" + +#include "aac.h" +#include "aactab.h" +#include "aacenc.h" + +#include "psymodel.h" + +#define AAC_MAX_CHANNELS 6 + +#define ERROR_IF(cond, ...) \ + if (cond) { \ + av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \ + return AVERROR(EINVAL); \ + } + +float ff_aac_pow34sf_tab[428]; + +static const uint8_t swb_size_1024_96[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + +static const uint8_t swb_size_1024_64[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 36, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 +}; + +static const uint8_t swb_size_1024_48[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 96 +}; + +static const uint8_t swb_size_1024_32[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 +}; + +static const uint8_t swb_size_1024_24[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, + 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64 +}; + +static const uint8_t swb_size_1024_16[] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, + 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64 +}; + +static const uint8_t swb_size_1024_8[] = { + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 16, 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, 28, + 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80 +}; + +static const uint8_t *swb_size_1024[] = { + swb_size_1024_96, swb_size_1024_96, swb_size_1024_64, + swb_size_1024_48, swb_size_1024_48, swb_size_1024_32, + swb_size_1024_24, swb_size_1024_24, swb_size_1024_16, + swb_size_1024_16, swb_size_1024_16, swb_size_1024_8 +}; + +static const uint8_t swb_size_128_96[] = { + 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 +}; + +static const uint8_t swb_size_128_48[] = { + 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 +}; + +static const uint8_t swb_size_128_24[] = { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20 +}; + +static const uint8_t swb_size_128_16[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 +}; + +static const uint8_t swb_size_128_8[] = { + 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20 +}; + +static const uint8_t *swb_size_128[] = { + /* the last entry on the following row is swb_size_128_64 but is a + duplicate of swb_size_128_96 */ + swb_size_128_96, swb_size_128_96, swb_size_128_96, + swb_size_128_48, swb_size_128_48, swb_size_128_48, + swb_size_128_24, swb_size_128_24, swb_size_128_16, + swb_size_128_16, swb_size_128_16, swb_size_128_8 +}; + +/** default channel configurations */ +static const uint8_t aac_chan_configs[6][5] = { + {1, TYPE_SCE}, // 1 channel - single channel element + {1, TYPE_CPE}, // 2 channels - channel pair + {2, TYPE_SCE, TYPE_CPE}, // 3 channels - center + stereo + {3, TYPE_SCE, TYPE_CPE, TYPE_SCE}, // 4 channels - front center + stereo + back center + {3, TYPE_SCE, TYPE_CPE, TYPE_CPE}, // 5 channels - front center + stereo + back stereo + {4, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_LFE}, // 6 channels - front center + stereo + back stereo + LFE +}; + +/** + * Table to remap channels from libavcodec's default order to AAC order. + */ +static const uint8_t aac_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = { + { 0 }, + { 0, 1 }, + { 2, 0, 1 }, + { 2, 0, 1, 3 }, + { 2, 0, 1, 3, 4 }, + { 2, 0, 1, 4, 5, 3 }, +}; + +/** + * Make AAC audio config object. + * @see 1.6.2.1 "Syntax - AudioSpecificConfig" + */ +static void put_audio_specific_config(AVCodecContext *avctx) +{ + PutBitContext pb; + AACEncContext *s = avctx->priv_data; + + init_put_bits(&pb, avctx->extradata, avctx->extradata_size*8); + put_bits(&pb, 5, 2); //object type - AAC-LC + put_bits(&pb, 4, s->samplerate_index); //sample rate index + put_bits(&pb, 4, s->channels); + //GASpecificConfig + put_bits(&pb, 1, 0); //frame length - 1024 samples + put_bits(&pb, 1, 0); //does not depend on core coder + put_bits(&pb, 1, 0); //is not extension + + //Explicitly Mark SBR absent + put_bits(&pb, 11, 0x2b7); //sync extension + put_bits(&pb, 5, AOT_SBR); + put_bits(&pb, 1, 0); + flush_put_bits(&pb); +} + +#define WINDOW_FUNC(type) \ +static void apply_ ##type ##_window(AVFloatDSPContext *fdsp, \ + SingleChannelElement *sce, \ + const float *audio) + +WINDOW_FUNC(only_long) +{ + const float *lwindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *pwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024; + float *out = sce->ret_buf; + + fdsp->vector_fmul (out, audio, lwindow, 1024); + fdsp->vector_fmul_reverse(out + 1024, audio + 1024, pwindow, 1024); +} + +WINDOW_FUNC(long_start) +{ + const float *lwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + float *out = sce->ret_buf; + + fdsp->vector_fmul(out, audio, lwindow, 1024); + memcpy(out + 1024, audio + 1024, sizeof(out[0]) * 448); + fdsp->vector_fmul_reverse(out + 1024 + 448, audio + 1024 + 448, swindow, 128); + memset(out + 1024 + 576, 0, sizeof(out[0]) * 448); +} + +WINDOW_FUNC(long_stop) +{ + const float *lwindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128; + float *out = sce->ret_buf; + + memset(out, 0, sizeof(out[0]) * 448); + fdsp->vector_fmul(out + 448, audio + 448, swindow, 128); + memcpy(out + 576, audio + 576, sizeof(out[0]) * 448); + fdsp->vector_fmul_reverse(out + 1024, audio + 1024, lwindow, 1024); +} + +WINDOW_FUNC(eight_short) +{ + const float *swindow = sce->ics.use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + const float *pwindow = sce->ics.use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128; + const float *in = audio + 448; + float *out = sce->ret_buf; + int w; + + for (w = 0; w < 8; w++) { + fdsp->vector_fmul (out, in, w ? pwindow : swindow, 128); + out += 128; + in += 128; + fdsp->vector_fmul_reverse(out, in, swindow, 128); + out += 128; + } +} + +static void (*const apply_window[4])(AVFloatDSPContext *fdsp, + SingleChannelElement *sce, + const float *audio) = { + [ONLY_LONG_SEQUENCE] = apply_only_long_window, + [LONG_START_SEQUENCE] = apply_long_start_window, + [EIGHT_SHORT_SEQUENCE] = apply_eight_short_window, + [LONG_STOP_SEQUENCE] = apply_long_stop_window +}; + +static void apply_window_and_mdct(AACEncContext *s, SingleChannelElement *sce, + float *audio) +{ + int i; + float *output = sce->ret_buf; + + apply_window[sce->ics.window_sequence[0]](&s->fdsp, sce, audio); + + if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) + s->mdct1024.mdct_calc(&s->mdct1024, sce->coeffs, output); + else + for (i = 0; i < 1024; i += 128) + s->mdct128.mdct_calc(&s->mdct128, sce->coeffs + i, output + i*2); + memcpy(audio, audio + 1024, sizeof(audio[0]) * 1024); +} + +/** + * Encode ics_info element. + * @see Table 4.6 (syntax of ics_info) + */ +static void put_ics_info(AACEncContext *s, IndividualChannelStream *info) +{ + int w; + + put_bits(&s->pb, 1, 0); // ics_reserved bit + put_bits(&s->pb, 2, info->window_sequence[0]); + put_bits(&s->pb, 1, info->use_kb_window[0]); + if (info->window_sequence[0] != EIGHT_SHORT_SEQUENCE) { + put_bits(&s->pb, 6, info->max_sfb); + put_bits(&s->pb, 1, 0); // no prediction + } else { + put_bits(&s->pb, 4, info->max_sfb); + for (w = 1; w < 8; w++) + put_bits(&s->pb, 1, !info->group_len[w]); + } +} + +/** + * Encode MS data. + * @see 4.6.8.1 "Joint Coding - M/S Stereo" + */ +static void encode_ms_info(PutBitContext *pb, ChannelElement *cpe) +{ + int i, w; + + put_bits(pb, 2, cpe->ms_mode); + if (cpe->ms_mode == 1) + for (w = 0; w < cpe->ch[0].ics.num_windows; w += cpe->ch[0].ics.group_len[w]) + for (i = 0; i < cpe->ch[0].ics.max_sfb; i++) + put_bits(pb, 1, cpe->ms_mask[w*16 + i]); +} + +/** + * Produce integer coefficients from scalefactors provided by the model. + */ +static void adjust_frame_information(ChannelElement *cpe, int chans) +{ + int i, w, w2, g, ch; + int start, maxsfb, cmaxsfb; + + for (ch = 0; ch < chans; ch++) { + IndividualChannelStream *ics = &cpe->ch[ch].ics; + start = 0; + maxsfb = 0; + cpe->ch[ch].pulse.num_pulse = 0; + for (w = 0; w < ics->num_windows*16; w += 16) { + for (g = 0; g < ics->num_swb; g++) { + //apply M/S + if (cpe->common_window && !ch && cpe->ms_mask[w + g]) { + for (i = 0; i < ics->swb_sizes[g]; i++) { + cpe->ch[0].coeffs[start+i] = (cpe->ch[0].coeffs[start+i] + cpe->ch[1].coeffs[start+i]) / 2.0; + cpe->ch[1].coeffs[start+i] = cpe->ch[0].coeffs[start+i] - cpe->ch[1].coeffs[start+i]; + } + } + start += ics->swb_sizes[g]; + } + for (cmaxsfb = ics->num_swb; cmaxsfb > 0 && cpe->ch[ch].zeroes[w+cmaxsfb-1]; cmaxsfb--) + ; + maxsfb = FFMAX(maxsfb, cmaxsfb); + } + ics->max_sfb = maxsfb; + + //adjust zero bands for window groups + for (w = 0; w < ics->num_windows; w += ics->group_len[w]) { + for (g = 0; g < ics->max_sfb; g++) { + i = 1; + for (w2 = w; w2 < w + ics->group_len[w]; w2++) { + if (!cpe->ch[ch].zeroes[w2*16 + g]) { + i = 0; + break; + } + } + cpe->ch[ch].zeroes[w*16 + g] = i; + } + } + } + + if (chans > 1 && cpe->common_window) { + IndividualChannelStream *ics0 = &cpe->ch[0].ics; + IndividualChannelStream *ics1 = &cpe->ch[1].ics; + int msc = 0; + ics0->max_sfb = FFMAX(ics0->max_sfb, ics1->max_sfb); + ics1->max_sfb = ics0->max_sfb; + for (w = 0; w < ics0->num_windows*16; w += 16) + for (i = 0; i < ics0->max_sfb; i++) + if (cpe->ms_mask[w+i]) + msc++; + if (msc == 0 || ics0->max_sfb == 0) + cpe->ms_mode = 0; + else + cpe->ms_mode = msc < ics0->max_sfb * ics0->num_windows ? 1 : 2; + } +} + +/** + * Encode scalefactor band coding type. + */ +static void encode_band_info(AACEncContext *s, SingleChannelElement *sce) +{ + int w; + + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) + s->coder->encode_window_bands_info(s, sce, w, sce->ics.group_len[w], s->lambda); +} + +/** + * Encode scalefactors. + */ +static void encode_scale_factors(AVCodecContext *avctx, AACEncContext *s, + SingleChannelElement *sce) +{ + int off = sce->sf_idx[0], diff; + int i, w; + + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (i = 0; i < sce->ics.max_sfb; i++) { + if (!sce->zeroes[w*16 + i]) { + diff = sce->sf_idx[w*16 + i] - off + SCALE_DIFF_ZERO; + av_assert0(diff >= 0 && diff <= 120); + off = sce->sf_idx[w*16 + i]; + put_bits(&s->pb, ff_aac_scalefactor_bits[diff], ff_aac_scalefactor_code[diff]); + } + } + } +} + +/** + * Encode pulse data. + */ +static void encode_pulses(AACEncContext *s, Pulse *pulse) +{ + int i; + + put_bits(&s->pb, 1, !!pulse->num_pulse); + if (!pulse->num_pulse) + return; + + put_bits(&s->pb, 2, pulse->num_pulse - 1); + put_bits(&s->pb, 6, pulse->start); + for (i = 0; i < pulse->num_pulse; i++) { + put_bits(&s->pb, 5, pulse->pos[i]); + put_bits(&s->pb, 4, pulse->amp[i]); + } +} + +/** + * Encode spectral coefficients processed by psychoacoustic model. + */ +static void encode_spectral_coeffs(AACEncContext *s, SingleChannelElement *sce) +{ + int start, i, w, w2; + + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = 0; + for (i = 0; i < sce->ics.max_sfb; i++) { + if (sce->zeroes[w*16 + i]) { + start += sce->ics.swb_sizes[i]; + continue; + } + for (w2 = w; w2 < w + sce->ics.group_len[w]; w2++) + s->coder->quantize_and_encode_band(s, &s->pb, sce->coeffs + start + w2*128, + sce->ics.swb_sizes[i], + sce->sf_idx[w*16 + i], + sce->band_type[w*16 + i], + s->lambda); + start += sce->ics.swb_sizes[i]; + } + } +} + +/** + * Encode one channel of audio data. + */ +static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s, + SingleChannelElement *sce, + int common_window) +{ + put_bits(&s->pb, 8, sce->sf_idx[0]); + if (!common_window) + put_ics_info(s, &sce->ics); + encode_band_info(s, sce); + encode_scale_factors(avctx, s, sce); + encode_pulses(s, &sce->pulse); + put_bits(&s->pb, 1, 0); //tns + put_bits(&s->pb, 1, 0); //ssr + encode_spectral_coeffs(s, sce); + return 0; +} + +/** + * Write some auxiliary information about the created AAC file. + */ +static void put_bitstream_info(AACEncContext *s, const char *name) +{ + int i, namelen, padbits; + + namelen = strlen(name) + 2; + put_bits(&s->pb, 3, TYPE_FIL); + put_bits(&s->pb, 4, FFMIN(namelen, 15)); + if (namelen >= 15) + put_bits(&s->pb, 8, namelen - 14); + put_bits(&s->pb, 4, 0); //extension type - filler + padbits = -put_bits_count(&s->pb) & 7; + avpriv_align_put_bits(&s->pb); + for (i = 0; i < namelen - 2; i++) + put_bits(&s->pb, 8, name[i]); + put_bits(&s->pb, 12 - padbits, 0); +} + +/* + * Copy input samples. + * Channels are reordered from libavcodec's default order to AAC order. + */ +static void copy_input_samples(AACEncContext *s, const AVFrame *frame) +{ + int ch; + int end = 2048 + (frame ? frame->nb_samples : 0); + const uint8_t *channel_map = aac_chan_maps[s->channels - 1]; + + /* copy and remap input samples */ + for (ch = 0; ch < s->channels; ch++) { + /* copy last 1024 samples of previous frame to the start of the current frame */ + memcpy(&s->planar_samples[ch][1024], &s->planar_samples[ch][2048], 1024 * sizeof(s->planar_samples[0][0])); + + /* copy new samples and zero any remaining samples */ + if (frame) { + memcpy(&s->planar_samples[ch][2048], + frame->extended_data[channel_map[ch]], + frame->nb_samples * sizeof(s->planar_samples[0][0])); + } + memset(&s->planar_samples[ch][end], 0, + (3072 - end) * sizeof(s->planar_samples[0][0])); + } +} + +static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AACEncContext *s = avctx->priv_data; + float **samples = s->planar_samples, *samples2, *la, *overlap; + ChannelElement *cpe; + int i, ch, w, g, chans, tag, start_ch, ret; + int chan_el_counter[4]; + FFPsyWindowInfo windows[AAC_MAX_CHANNELS]; + + if (s->last_frame == 2) + return 0; + + /* add current frame to queue */ + if (frame) { + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } + + copy_input_samples(s, frame); + if (s->psypp) + ff_psy_preprocess(s->psypp, s->planar_samples, s->channels); + + if (!avctx->frame_number) + return 0; + + start_ch = 0; + for (i = 0; i < s->chan_map[0]; i++) { + FFPsyWindowInfo* wi = windows + start_ch; + tag = s->chan_map[i+1]; + chans = tag == TYPE_CPE ? 2 : 1; + cpe = &s->cpe[i]; + for (ch = 0; ch < chans; ch++) { + IndividualChannelStream *ics = &cpe->ch[ch].ics; + int cur_channel = start_ch + ch; + overlap = &samples[cur_channel][0]; + samples2 = overlap + 1024; + la = samples2 + (448+64); + if (!frame) + la = NULL; + if (tag == TYPE_LFE) { + wi[ch].window_type[0] = ONLY_LONG_SEQUENCE; + wi[ch].window_shape = 0; + wi[ch].num_windows = 1; + wi[ch].grouping[0] = 1; + + /* Only the lowest 12 coefficients are used in a LFE channel. + * The expression below results in only the bottom 8 coefficients + * being used for 11.025kHz to 16kHz sample rates. + */ + ics->num_swb = s->samplerate_index >= 8 ? 1 : 3; + } else { + wi[ch] = s->psy.model->window(&s->psy, samples2, la, cur_channel, + ics->window_sequence[0]); + } + ics->window_sequence[1] = ics->window_sequence[0]; + ics->window_sequence[0] = wi[ch].window_type[0]; + ics->use_kb_window[1] = ics->use_kb_window[0]; + ics->use_kb_window[0] = wi[ch].window_shape; + ics->num_windows = wi[ch].num_windows; + ics->swb_sizes = s->psy.bands [ics->num_windows == 8]; + ics->num_swb = tag == TYPE_LFE ? ics->num_swb : s->psy.num_bands[ics->num_windows == 8]; + for (w = 0; w < ics->num_windows; w++) + ics->group_len[w] = wi[ch].grouping[w]; + + apply_window_and_mdct(s, &cpe->ch[ch], overlap); + } + start_ch += chans; + } + if ((ret = ff_alloc_packet2(avctx, avpkt, 8192 * s->channels)) < 0) + return ret; + do { + int frame_bits; + + init_put_bits(&s->pb, avpkt->data, avpkt->size); + + if ((avctx->frame_number & 0xFF)==1 && !(avctx->flags & CODEC_FLAG_BITEXACT)) + put_bitstream_info(s, LIBAVCODEC_IDENT); + start_ch = 0; + memset(chan_el_counter, 0, sizeof(chan_el_counter)); + for (i = 0; i < s->chan_map[0]; i++) { + FFPsyWindowInfo* wi = windows + start_ch; + const float *coeffs[2]; + tag = s->chan_map[i+1]; + chans = tag == TYPE_CPE ? 2 : 1; + cpe = &s->cpe[i]; + put_bits(&s->pb, 3, tag); + put_bits(&s->pb, 4, chan_el_counter[tag]++); + for (ch = 0; ch < chans; ch++) + coeffs[ch] = cpe->ch[ch].coeffs; + s->psy.model->analyze(&s->psy, start_ch, coeffs, wi); + for (ch = 0; ch < chans; ch++) { + s->cur_channel = start_ch * 2 + ch; + s->coder->search_for_quantizers(avctx, s, &cpe->ch[ch], s->lambda); + } + cpe->common_window = 0; + if (chans > 1 + && wi[0].window_type[0] == wi[1].window_type[0] + && wi[0].window_shape == wi[1].window_shape) { + + cpe->common_window = 1; + for (w = 0; w < wi[0].num_windows; w++) { + if (wi[0].grouping[w] != wi[1].grouping[w]) { + cpe->common_window = 0; + break; + } + } + } + s->cur_channel = start_ch * 2; + if (s->options.stereo_mode && cpe->common_window) { + if (s->options.stereo_mode > 0) { + IndividualChannelStream *ics = &cpe->ch[0].ics; + for (w = 0; w < ics->num_windows; w += ics->group_len[w]) + for (g = 0; g < ics->num_swb; g++) + cpe->ms_mask[w*16+g] = 1; + } else if (s->coder->search_for_ms) { + s->coder->search_for_ms(s, cpe, s->lambda); + } + } + adjust_frame_information(cpe, chans); + if (chans == 2) { + put_bits(&s->pb, 1, cpe->common_window); + if (cpe->common_window) { + put_ics_info(s, &cpe->ch[0].ics); + encode_ms_info(&s->pb, cpe); + } + } + for (ch = 0; ch < chans; ch++) { + s->cur_channel = start_ch + ch; + encode_individual_channel(avctx, s, &cpe->ch[ch], cpe->common_window); + } + start_ch += chans; + } + + frame_bits = put_bits_count(&s->pb); + if (frame_bits <= 6144 * s->channels - 3) { + s->psy.bitres.bits = frame_bits / s->channels; + break; + } + + s->lambda *= avctx->bit_rate * 1024.0f / avctx->sample_rate / frame_bits; + + } while (1); + + put_bits(&s->pb, 3, TYPE_END); + flush_put_bits(&s->pb); + avctx->frame_bits = put_bits_count(&s->pb); + + // rate control stuff + if (!(avctx->flags & CODEC_FLAG_QSCALE)) { + float ratio = avctx->bit_rate * 1024.0f / avctx->sample_rate / avctx->frame_bits; + s->lambda *= ratio; + s->lambda = FFMIN(s->lambda, 65536.f); + } + + if (!frame) + s->last_frame++; + + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = put_bits_count(&s->pb) >> 3; + *got_packet_ptr = 1; + return 0; +} + +static av_cold int aac_encode_end(AVCodecContext *avctx) +{ + AACEncContext *s = avctx->priv_data; + + ff_mdct_end(&s->mdct1024); + ff_mdct_end(&s->mdct128); + ff_psy_end(&s->psy); + if (s->psypp) + ff_psy_preprocess_end(s->psypp); + av_freep(&s->buffer.samples); + av_freep(&s->cpe); + ff_af_queue_close(&s->afq); + return 0; +} + +static av_cold int dsp_init(AVCodecContext *avctx, AACEncContext *s) +{ + int ret = 0; + + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + // window init + ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); + ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); + ff_init_ff_sine_windows(10); + ff_init_ff_sine_windows(7); + + if (ret = ff_mdct_init(&s->mdct1024, 11, 0, 32768.0)) + return ret; + if (ret = ff_mdct_init(&s->mdct128, 8, 0, 32768.0)) + return ret; + + return 0; +} + +static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s) +{ + int ch; + FF_ALLOCZ_OR_GOTO(avctx, s->buffer.samples, 3 * 1024 * s->channels * sizeof(s->buffer.samples[0]), alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, s->cpe, sizeof(ChannelElement) * s->chan_map[0], alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + FF_INPUT_BUFFER_PADDING_SIZE, alloc_fail); + + for(ch = 0; ch < s->channels; ch++) + s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch; + + return 0; +alloc_fail: + return AVERROR(ENOMEM); +} + +static av_cold int aac_encode_init(AVCodecContext *avctx) +{ + AACEncContext *s = avctx->priv_data; + int i, ret = 0; + const uint8_t *sizes[2]; + uint8_t grouping[AAC_MAX_CHANNELS]; + int lengths[2]; + + avctx->frame_size = 1024; + + for (i = 0; i < 16; i++) + if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i]) + break; + + s->channels = avctx->channels; + + ERROR_IF(i == 16, + "Unsupported sample rate %d\n", avctx->sample_rate); + ERROR_IF(s->channels > AAC_MAX_CHANNELS, + "Unsupported number of channels: %d\n", s->channels); + ERROR_IF(avctx->profile != FF_PROFILE_UNKNOWN && avctx->profile != FF_PROFILE_AAC_LOW, + "Unsupported profile %d\n", avctx->profile); + ERROR_IF(1024.0 * avctx->bit_rate / avctx->sample_rate > 6144 * s->channels, + "Too many bits per frame requested\n"); + + s->samplerate_index = i; + + s->chan_map = aac_chan_configs[s->channels-1]; + + if (ret = dsp_init(avctx, s)) + goto fail; + + if (ret = alloc_buffers(avctx, s)) + goto fail; + + avctx->extradata_size = 5; + put_audio_specific_config(avctx); + + sizes[0] = swb_size_1024[i]; + sizes[1] = swb_size_128[i]; + lengths[0] = ff_aac_num_swb_1024[i]; + lengths[1] = ff_aac_num_swb_128[i]; + for (i = 0; i < s->chan_map[0]; i++) + grouping[i] = s->chan_map[i + 1] == TYPE_CPE; + if (ret = ff_psy_init(&s->psy, avctx, 2, sizes, lengths, s->chan_map[0], grouping)) + goto fail; + s->psypp = ff_psy_preprocess_init(avctx); + s->coder = &ff_aac_coders[s->options.aac_coder]; + + if (HAVE_MIPSDSPR1) + ff_aac_coder_init_mips(s); + + s->lambda = avctx->global_quality ? avctx->global_quality : 120; + + ff_aac_tableinit(); + + for (i = 0; i < 428; i++) + ff_aac_pow34sf_tab[i] = sqrt(ff_aac_pow2sf_tab[i] * sqrt(ff_aac_pow2sf_tab[i])); + + avctx->delay = 1024; + ff_af_queue_init(avctx, &s->afq); + + return 0; +fail: + aac_encode_end(avctx); + return ret; +} + +#define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM +static const AVOption aacenc_options[] = { + {"stereo_mode", "Stereo coding method", offsetof(AACEncContext, options.stereo_mode), AV_OPT_TYPE_INT, {.i64 = 0}, -1, 1, AACENC_FLAGS, "stereo_mode"}, + {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = -1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"}, + {"ms_off", "Disable Mid/Side coding", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"}, + {"ms_force", "Force Mid/Side for the whole frame if possible", 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"}, + {"aac_coder", "", offsetof(AACEncContext, options.aac_coder), AV_OPT_TYPE_INT, {.i64 = 2}, 0, AAC_CODER_NB-1, AACENC_FLAGS}, + {NULL} +}; + +static const AVClass aacenc_class = { + "AAC encoder", + av_default_item_name, + aacenc_options, + LIBAVUTIL_VERSION_INT, +}; + +/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build + * failures */ +static const int mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + +AVCodec ff_aac_encoder = { + .name = "aac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(AACEncContext), + .init = aac_encode_init, + .encode2 = aac_encode_frame, + .close = aac_encode_end, + .supported_samplerates = mpeg4audio_sample_rates, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | + CODEC_CAP_EXPERIMENTAL, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), + .priv_class = &aacenc_class, +}; diff --git a/ffmpeg/libavcodec/aacenc.h b/ffmpeg/libavcodec/aacenc.h new file mode 100644 index 0000000..cebdd18 --- /dev/null +++ b/ffmpeg/libavcodec/aacenc.h @@ -0,0 +1,90 @@ +/* + * AAC encoder + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_AACENC_H +#define AVCODEC_AACENC_H + +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "put_bits.h" + +#include "aac.h" +#include "audio_frame_queue.h" +#include "psymodel.h" + +#define AAC_CODER_NB 4 + +typedef struct AACEncOptions { + int stereo_mode; + int aac_coder; +} AACEncOptions; + +struct AACEncContext; + +typedef struct AACCoefficientsEncoder { + void (*search_for_quantizers)(AVCodecContext *avctx, struct AACEncContext *s, + SingleChannelElement *sce, const float lambda); + void (*encode_window_bands_info)(struct AACEncContext *s, SingleChannelElement *sce, + int win, int group_len, const float lambda); + void (*quantize_and_encode_band)(struct AACEncContext *s, PutBitContext *pb, const float *in, int size, + int scale_idx, int cb, const float lambda); + void (*search_for_ms)(struct AACEncContext *s, ChannelElement *cpe, const float lambda); +} AACCoefficientsEncoder; + +extern AACCoefficientsEncoder ff_aac_coders[]; + +/** + * AAC encoder context + */ +typedef struct AACEncContext { + AVClass *av_class; + AACEncOptions options; ///< encoding options + PutBitContext pb; + FFTContext mdct1024; ///< long (1024 samples) frame transform context + FFTContext mdct128; ///< short (128 samples) frame transform context + AVFloatDSPContext fdsp; + float *planar_samples[6]; ///< saved preprocessed input + + int samplerate_index; ///< MPEG-4 samplerate index + int channels; ///< channel count + const uint8_t *chan_map; ///< channel configuration map + + ChannelElement *cpe; ///< channel elements + FFPsyContext psy; + struct FFPsyPreprocessContext* psypp; + AACCoefficientsEncoder *coder; + int cur_channel; + int last_frame; + float lambda; + AudioFrameQueue afq; + DECLARE_ALIGNED(16, int, qcoefs)[96]; ///< quantized coefficients + DECLARE_ALIGNED(32, float, scoefs)[1024]; ///< scaled coefficients + + struct { + float *samples; + } buffer; +} AACEncContext; + +extern float ff_aac_pow34sf_tab[428]; + +void ff_aac_coder_init_mips(AACEncContext *c); + +#endif /* AVCODEC_AACENC_H */ diff --git a/ffmpeg/libavcodec/aacps.c b/ffmpeg/libavcodec/aacps.c new file mode 100644 index 0000000..b82001e --- /dev/null +++ b/ffmpeg/libavcodec/aacps.c @@ -0,0 +1,968 @@ +/* + * MPEG-4 Parametric Stereo decoding functions + * Copyright (c) 2010 Alex Converse + * + * 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 "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" +#include "avcodec.h" +#include "get_bits.h" +#include "aacps.h" +#include "aacps_tablegen.h" +#include "aacpsdata.c" + +#define PS_BASELINE 0 ///< Operate in Baseline PS mode + ///< Baseline implies 10 or 20 stereo bands, + ///< mixing mode A, and no ipd/opd + +#define numQMFSlots 32 //numTimeSlots * RATE + +static const int8_t num_env_tab[2][4] = { + { 0, 1, 2, 4, }, + { 1, 2, 3, 4, }, +}; + +static const int8_t nr_iidicc_par_tab[] = { + 10, 20, 34, 10, 20, 34, +}; + +static const int8_t nr_iidopd_par_tab[] = { + 5, 11, 17, 5, 11, 17, +}; + +enum { + huff_iid_df1, + huff_iid_dt1, + huff_iid_df0, + huff_iid_dt0, + huff_icc_df, + huff_icc_dt, + huff_ipd_df, + huff_ipd_dt, + huff_opd_df, + huff_opd_dt, +}; + +static const int huff_iid[] = { + huff_iid_df0, + huff_iid_df1, + huff_iid_dt0, + huff_iid_dt1, +}; + +static VLC vlc_ps[10]; + +#define READ_PAR_DATA(PAR, OFFSET, MASK, ERR_CONDITION) \ +/** \ + * Read Inter-channel Intensity Difference/Inter-Channel Coherence/ \ + * Inter-channel Phase Difference/Overall Phase Difference parameters from the \ + * bitstream. \ + * \ + * @param avctx contains the current codec context \ + * @param gb pointer to the input bitstream \ + * @param ps pointer to the Parametric Stereo context \ + * @param PAR pointer to the parameter to be read \ + * @param e envelope to decode \ + * @param dt 1: time delta-coded, 0: frequency delta-coded \ + */ \ +static int read_ ## PAR ## _data(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, \ + int8_t (*PAR)[PS_MAX_NR_IIDICC], int table_idx, int e, int dt) \ +{ \ + int b, num = ps->nr_ ## PAR ## _par; \ + VLC_TYPE (*vlc_table)[2] = vlc_ps[table_idx].table; \ + if (dt) { \ + int e_prev = e ? e - 1 : ps->num_env_old - 1; \ + e_prev = FFMAX(e_prev, 0); \ + for (b = 0; b < num; b++) { \ + int val = PAR[e_prev][b] + get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \ + if (MASK) val &= MASK; \ + PAR[e][b] = val; \ + if (ERR_CONDITION) \ + goto err; \ + } \ + } else { \ + int val = 0; \ + for (b = 0; b < num; b++) { \ + val += get_vlc2(gb, vlc_table, 9, 3) - OFFSET; \ + if (MASK) val &= MASK; \ + PAR[e][b] = val; \ + if (ERR_CONDITION) \ + goto err; \ + } \ + } \ + return 0; \ +err: \ + av_log(avctx, AV_LOG_ERROR, "illegal "#PAR"\n"); \ + return -1; \ +} + +READ_PAR_DATA(iid, huff_offset[table_idx], 0, FFABS(ps->iid_par[e][b]) > 7 + 8 * ps->iid_quant) +READ_PAR_DATA(icc, huff_offset[table_idx], 0, ps->icc_par[e][b] > 7U) +READ_PAR_DATA(ipdopd, 0, 0x07, 0) + +static int ps_read_extension_data(GetBitContext *gb, PSContext *ps, int ps_extension_id) +{ + int e; + int count = get_bits_count(gb); + + if (ps_extension_id) + return 0; + + ps->enable_ipdopd = get_bits1(gb); + if (ps->enable_ipdopd) { + for (e = 0; e < ps->num_env; e++) { + int dt = get_bits1(gb); + read_ipdopd_data(NULL, gb, ps, ps->ipd_par, dt ? huff_ipd_dt : huff_ipd_df, e, dt); + dt = get_bits1(gb); + read_ipdopd_data(NULL, gb, ps, ps->opd_par, dt ? huff_opd_dt : huff_opd_df, e, dt); + } + } + skip_bits1(gb); //reserved_ps + return get_bits_count(gb) - count; +} + +static void ipdopd_reset(int8_t *ipd_hist, int8_t *opd_hist) +{ + int i; + for (i = 0; i < PS_MAX_NR_IPDOPD; i++) { + opd_hist[i] = 0; + ipd_hist[i] = 0; + } +} + +int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb_host, PSContext *ps, int bits_left) +{ + int e; + int bit_count_start = get_bits_count(gb_host); + int header; + int bits_consumed; + GetBitContext gbc = *gb_host, *gb = &gbc; + + header = get_bits1(gb); + if (header) { //enable_ps_header + ps->enable_iid = get_bits1(gb); + if (ps->enable_iid) { + int iid_mode = get_bits(gb, 3); + if (iid_mode > 5) { + av_log(avctx, AV_LOG_ERROR, "iid_mode %d is reserved.\n", + iid_mode); + goto err; + } + ps->nr_iid_par = nr_iidicc_par_tab[iid_mode]; + ps->iid_quant = iid_mode > 2; + ps->nr_ipdopd_par = nr_iidopd_par_tab[iid_mode]; + } + ps->enable_icc = get_bits1(gb); + if (ps->enable_icc) { + ps->icc_mode = get_bits(gb, 3); + if (ps->icc_mode > 5) { + av_log(avctx, AV_LOG_ERROR, "icc_mode %d is reserved.\n", + ps->icc_mode); + goto err; + } + ps->nr_icc_par = nr_iidicc_par_tab[ps->icc_mode]; + } + ps->enable_ext = get_bits1(gb); + } + + ps->frame_class = get_bits1(gb); + ps->num_env_old = ps->num_env; + ps->num_env = num_env_tab[ps->frame_class][get_bits(gb, 2)]; + + ps->border_position[0] = -1; + if (ps->frame_class) { + for (e = 1; e <= ps->num_env; e++) + ps->border_position[e] = get_bits(gb, 5); + } else + for (e = 1; e <= ps->num_env; e++) + ps->border_position[e] = (e * numQMFSlots >> ff_log2_tab[ps->num_env]) - 1; + + if (ps->enable_iid) { + for (e = 0; e < ps->num_env; e++) { + int dt = get_bits1(gb); + if (read_iid_data(avctx, gb, ps, ps->iid_par, huff_iid[2*dt+ps->iid_quant], e, dt)) + goto err; + } + } else + memset(ps->iid_par, 0, sizeof(ps->iid_par)); + + if (ps->enable_icc) + for (e = 0; e < ps->num_env; e++) { + int dt = get_bits1(gb); + if (read_icc_data(avctx, gb, ps, ps->icc_par, dt ? huff_icc_dt : huff_icc_df, e, dt)) + goto err; + } + else + memset(ps->icc_par, 0, sizeof(ps->icc_par)); + + if (ps->enable_ext) { + int cnt = get_bits(gb, 4); + if (cnt == 15) { + cnt += get_bits(gb, 8); + } + cnt *= 8; + while (cnt > 7) { + int ps_extension_id = get_bits(gb, 2); + cnt -= 2 + ps_read_extension_data(gb, ps, ps_extension_id); + } + if (cnt < 0) { + av_log(avctx, AV_LOG_ERROR, "ps extension overflow %d\n", cnt); + goto err; + } + skip_bits(gb, cnt); + } + + ps->enable_ipdopd &= !PS_BASELINE; + + //Fix up envelopes + if (!ps->num_env || ps->border_position[ps->num_env] < numQMFSlots - 1) { + //Create a fake envelope + int source = ps->num_env ? ps->num_env - 1 : ps->num_env_old - 1; + int b; + if (source >= 0 && source != ps->num_env) { + if (ps->enable_iid) { + memcpy(ps->iid_par+ps->num_env, ps->iid_par+source, sizeof(ps->iid_par[0])); + } + if (ps->enable_icc) { + memcpy(ps->icc_par+ps->num_env, ps->icc_par+source, sizeof(ps->icc_par[0])); + } + if (ps->enable_ipdopd) { + memcpy(ps->ipd_par+ps->num_env, ps->ipd_par+source, sizeof(ps->ipd_par[0])); + memcpy(ps->opd_par+ps->num_env, ps->opd_par+source, sizeof(ps->opd_par[0])); + } + } + if (ps->enable_iid){ + for (b = 0; b < ps->nr_iid_par; b++) { + if (FFABS(ps->iid_par[ps->num_env][b]) > 7 + 8 * ps->iid_quant) { + av_log(avctx, AV_LOG_ERROR, "iid_par invalid\n"); + goto err; + } + } + } + if (ps->enable_icc){ + for (b = 0; b < ps->nr_iid_par; b++) { + if (ps->icc_par[ps->num_env][b] > 7U) { + av_log(avctx, AV_LOG_ERROR, "icc_par invalid\n"); + goto err; + } + } + } + ps->num_env++; + ps->border_position[ps->num_env] = numQMFSlots - 1; + } + + + ps->is34bands_old = ps->is34bands; + if (!PS_BASELINE && (ps->enable_iid || ps->enable_icc)) + ps->is34bands = (ps->enable_iid && ps->nr_iid_par == 34) || + (ps->enable_icc && ps->nr_icc_par == 34); + + //Baseline + if (!ps->enable_ipdopd) { + memset(ps->ipd_par, 0, sizeof(ps->ipd_par)); + memset(ps->opd_par, 0, sizeof(ps->opd_par)); + } + + if (header) + ps->start = 1; + + bits_consumed = get_bits_count(gb) - bit_count_start; + if (bits_consumed <= bits_left) { + skip_bits_long(gb_host, bits_consumed); + return bits_consumed; + } + av_log(avctx, AV_LOG_ERROR, "Expected to read %d PS bits actually read %d.\n", bits_left, bits_consumed); +err: + ps->start = 0; + skip_bits_long(gb_host, bits_left); + memset(ps->iid_par, 0, sizeof(ps->iid_par)); + memset(ps->icc_par, 0, sizeof(ps->icc_par)); + memset(ps->ipd_par, 0, sizeof(ps->ipd_par)); + memset(ps->opd_par, 0, sizeof(ps->opd_par)); + return bits_left; +} + +/** Split one subband into 2 subsubbands with a symmetric real filter. + * The filter must have its non-center even coefficients equal to zero. */ +static void hybrid2_re(float (*in)[2], float (*out)[32][2], const float filter[8], int len, int reverse) +{ + int i, j; + for (i = 0; i < len; i++, in++) { + float re_in = filter[6] * in[6][0]; //real inphase + float re_op = 0.0f; //real out of phase + float im_in = filter[6] * in[6][1]; //imag inphase + float im_op = 0.0f; //imag out of phase + for (j = 0; j < 6; j += 2) { + re_op += filter[j+1] * (in[j+1][0] + in[12-j-1][0]); + im_op += filter[j+1] * (in[j+1][1] + in[12-j-1][1]); + } + out[ reverse][i][0] = re_in + re_op; + out[ reverse][i][1] = im_in + im_op; + out[!reverse][i][0] = re_in - re_op; + out[!reverse][i][1] = im_in - im_op; + } +} + +/** Split one subband into 6 subsubbands with a complex filter */ +static void hybrid6_cx(PSDSPContext *dsp, float (*in)[2], float (*out)[32][2], const float (*filter)[8][2], int len) +{ + int i; + int N = 8; + LOCAL_ALIGNED_16(float, temp, [8], [2]); + + for (i = 0; i < len; i++, in++) { + dsp->hybrid_analysis(temp, in, filter, 1, N); + out[0][i][0] = temp[6][0]; + out[0][i][1] = temp[6][1]; + out[1][i][0] = temp[7][0]; + out[1][i][1] = temp[7][1]; + out[2][i][0] = temp[0][0]; + out[2][i][1] = temp[0][1]; + out[3][i][0] = temp[1][0]; + out[3][i][1] = temp[1][1]; + out[4][i][0] = temp[2][0] + temp[5][0]; + out[4][i][1] = temp[2][1] + temp[5][1]; + out[5][i][0] = temp[3][0] + temp[4][0]; + out[5][i][1] = temp[3][1] + temp[4][1]; + } +} + +static void hybrid4_8_12_cx(PSDSPContext *dsp, float (*in)[2], float (*out)[32][2], const float (*filter)[8][2], int N, int len) +{ + int i; + + for (i = 0; i < len; i++, in++) { + dsp->hybrid_analysis(out[0] + i, in, filter, 32, N); + } +} + +static void hybrid_analysis(PSDSPContext *dsp, float out[91][32][2], + float in[5][44][2], float L[2][38][64], + int is34, int len) +{ + int i, j; + for (i = 0; i < 5; i++) { + for (j = 0; j < 38; j++) { + in[i][j+6][0] = L[0][j][i]; + in[i][j+6][1] = L[1][j][i]; + } + } + if (is34) { + hybrid4_8_12_cx(dsp, in[0], out, f34_0_12, 12, len); + hybrid4_8_12_cx(dsp, in[1], out+12, f34_1_8, 8, len); + hybrid4_8_12_cx(dsp, in[2], out+20, f34_2_4, 4, len); + hybrid4_8_12_cx(dsp, in[3], out+24, f34_2_4, 4, len); + hybrid4_8_12_cx(dsp, in[4], out+28, f34_2_4, 4, len); + dsp->hybrid_analysis_ileave(out + 27, L, 5, len); + } else { + hybrid6_cx(dsp, in[0], out, f20_0_8, len); + hybrid2_re(in[1], out+6, g1_Q2, len, 1); + hybrid2_re(in[2], out+8, g1_Q2, len, 0); + dsp->hybrid_analysis_ileave(out + 7, L, 3, len); + } + //update in_buf + for (i = 0; i < 5; i++) { + memcpy(in[i], in[i]+32, 6 * sizeof(in[i][0])); + } +} + +static void hybrid_synthesis(PSDSPContext *dsp, float out[2][38][64], + float in[91][32][2], int is34, int len) +{ + int i, n; + if (is34) { + for (n = 0; n < len; n++) { + memset(out[0][n], 0, 5*sizeof(out[0][n][0])); + memset(out[1][n], 0, 5*sizeof(out[1][n][0])); + for (i = 0; i < 12; i++) { + out[0][n][0] += in[ i][n][0]; + out[1][n][0] += in[ i][n][1]; + } + for (i = 0; i < 8; i++) { + out[0][n][1] += in[12+i][n][0]; + out[1][n][1] += in[12+i][n][1]; + } + for (i = 0; i < 4; i++) { + out[0][n][2] += in[20+i][n][0]; + out[1][n][2] += in[20+i][n][1]; + out[0][n][3] += in[24+i][n][0]; + out[1][n][3] += in[24+i][n][1]; + out[0][n][4] += in[28+i][n][0]; + out[1][n][4] += in[28+i][n][1]; + } + } + dsp->hybrid_synthesis_deint(out, in + 27, 5, len); + } else { + for (n = 0; n < len; n++) { + out[0][n][0] = in[0][n][0] + in[1][n][0] + in[2][n][0] + + in[3][n][0] + in[4][n][0] + in[5][n][0]; + out[1][n][0] = in[0][n][1] + in[1][n][1] + in[2][n][1] + + in[3][n][1] + in[4][n][1] + in[5][n][1]; + out[0][n][1] = in[6][n][0] + in[7][n][0]; + out[1][n][1] = in[6][n][1] + in[7][n][1]; + out[0][n][2] = in[8][n][0] + in[9][n][0]; + out[1][n][2] = in[8][n][1] + in[9][n][1]; + } + dsp->hybrid_synthesis_deint(out, in + 7, 3, len); + } +} + +/// All-pass filter decay slope +#define DECAY_SLOPE 0.05f +/// Number of frequency bands that can be addressed by the parameter index, b(k) +static const int NR_PAR_BANDS[] = { 20, 34 }; +/// Number of frequency bands that can be addressed by the sub subband index, k +static const int NR_BANDS[] = { 71, 91 }; +/// Start frequency band for the all-pass filter decay slope +static const int DECAY_CUTOFF[] = { 10, 32 }; +/// Number of all-pass filer bands +static const int NR_ALLPASS_BANDS[] = { 30, 50 }; +/// First stereo band using the short one sample delay +static const int SHORT_DELAY_BAND[] = { 42, 62 }; + +/** Table 8.46 */ +static void map_idx_10_to_20(int8_t *par_mapped, const int8_t *par, int full) +{ + int b; + if (full) + b = 9; + else { + b = 4; + par_mapped[10] = 0; + } + for (; b >= 0; b--) { + par_mapped[2*b+1] = par_mapped[2*b] = par[b]; + } +} + +static void map_idx_34_to_20(int8_t *par_mapped, const int8_t *par, int full) +{ + par_mapped[ 0] = (2*par[ 0] + par[ 1]) / 3; + par_mapped[ 1] = ( par[ 1] + 2*par[ 2]) / 3; + par_mapped[ 2] = (2*par[ 3] + par[ 4]) / 3; + par_mapped[ 3] = ( par[ 4] + 2*par[ 5]) / 3; + par_mapped[ 4] = ( par[ 6] + par[ 7]) / 2; + par_mapped[ 5] = ( par[ 8] + par[ 9]) / 2; + par_mapped[ 6] = par[10]; + par_mapped[ 7] = par[11]; + par_mapped[ 8] = ( par[12] + par[13]) / 2; + par_mapped[ 9] = ( par[14] + par[15]) / 2; + par_mapped[10] = par[16]; + if (full) { + par_mapped[11] = par[17]; + par_mapped[12] = par[18]; + par_mapped[13] = par[19]; + par_mapped[14] = ( par[20] + par[21]) / 2; + par_mapped[15] = ( par[22] + par[23]) / 2; + par_mapped[16] = ( par[24] + par[25]) / 2; + par_mapped[17] = ( par[26] + par[27]) / 2; + par_mapped[18] = ( par[28] + par[29] + par[30] + par[31]) / 4; + par_mapped[19] = ( par[32] + par[33]) / 2; + } +} + +static void map_val_34_to_20(float par[PS_MAX_NR_IIDICC]) +{ + par[ 0] = (2*par[ 0] + par[ 1]) * 0.33333333f; + par[ 1] = ( par[ 1] + 2*par[ 2]) * 0.33333333f; + par[ 2] = (2*par[ 3] + par[ 4]) * 0.33333333f; + par[ 3] = ( par[ 4] + 2*par[ 5]) * 0.33333333f; + par[ 4] = ( par[ 6] + par[ 7]) * 0.5f; + par[ 5] = ( par[ 8] + par[ 9]) * 0.5f; + par[ 6] = par[10]; + par[ 7] = par[11]; + par[ 8] = ( par[12] + par[13]) * 0.5f; + par[ 9] = ( par[14] + par[15]) * 0.5f; + par[10] = par[16]; + par[11] = par[17]; + par[12] = par[18]; + par[13] = par[19]; + par[14] = ( par[20] + par[21]) * 0.5f; + par[15] = ( par[22] + par[23]) * 0.5f; + par[16] = ( par[24] + par[25]) * 0.5f; + par[17] = ( par[26] + par[27]) * 0.5f; + par[18] = ( par[28] + par[29] + par[30] + par[31]) * 0.25f; + par[19] = ( par[32] + par[33]) * 0.5f; +} + +static void map_idx_10_to_34(int8_t *par_mapped, const int8_t *par, int full) +{ + if (full) { + par_mapped[33] = par[9]; + par_mapped[32] = par[9]; + par_mapped[31] = par[9]; + par_mapped[30] = par[9]; + par_mapped[29] = par[9]; + par_mapped[28] = par[9]; + par_mapped[27] = par[8]; + par_mapped[26] = par[8]; + par_mapped[25] = par[8]; + par_mapped[24] = par[8]; + par_mapped[23] = par[7]; + par_mapped[22] = par[7]; + par_mapped[21] = par[7]; + par_mapped[20] = par[7]; + par_mapped[19] = par[6]; + par_mapped[18] = par[6]; + par_mapped[17] = par[5]; + par_mapped[16] = par[5]; + } else { + par_mapped[16] = 0; + } + par_mapped[15] = par[4]; + par_mapped[14] = par[4]; + par_mapped[13] = par[4]; + par_mapped[12] = par[4]; + par_mapped[11] = par[3]; + par_mapped[10] = par[3]; + par_mapped[ 9] = par[2]; + par_mapped[ 8] = par[2]; + par_mapped[ 7] = par[2]; + par_mapped[ 6] = par[2]; + par_mapped[ 5] = par[1]; + par_mapped[ 4] = par[1]; + par_mapped[ 3] = par[1]; + par_mapped[ 2] = par[0]; + par_mapped[ 1] = par[0]; + par_mapped[ 0] = par[0]; +} + +static void map_idx_20_to_34(int8_t *par_mapped, const int8_t *par, int full) +{ + if (full) { + par_mapped[33] = par[19]; + par_mapped[32] = par[19]; + par_mapped[31] = par[18]; + par_mapped[30] = par[18]; + par_mapped[29] = par[18]; + par_mapped[28] = par[18]; + par_mapped[27] = par[17]; + par_mapped[26] = par[17]; + par_mapped[25] = par[16]; + par_mapped[24] = par[16]; + par_mapped[23] = par[15]; + par_mapped[22] = par[15]; + par_mapped[21] = par[14]; + par_mapped[20] = par[14]; + par_mapped[19] = par[13]; + par_mapped[18] = par[12]; + par_mapped[17] = par[11]; + } + par_mapped[16] = par[10]; + par_mapped[15] = par[ 9]; + par_mapped[14] = par[ 9]; + par_mapped[13] = par[ 8]; + par_mapped[12] = par[ 8]; + par_mapped[11] = par[ 7]; + par_mapped[10] = par[ 6]; + par_mapped[ 9] = par[ 5]; + par_mapped[ 8] = par[ 5]; + par_mapped[ 7] = par[ 4]; + par_mapped[ 6] = par[ 4]; + par_mapped[ 5] = par[ 3]; + par_mapped[ 4] = (par[ 2] + par[ 3]) / 2; + par_mapped[ 3] = par[ 2]; + par_mapped[ 2] = par[ 1]; + par_mapped[ 1] = (par[ 0] + par[ 1]) / 2; + par_mapped[ 0] = par[ 0]; +} + +static void map_val_20_to_34(float par[PS_MAX_NR_IIDICC]) +{ + par[33] = par[19]; + par[32] = par[19]; + par[31] = par[18]; + par[30] = par[18]; + par[29] = par[18]; + par[28] = par[18]; + par[27] = par[17]; + par[26] = par[17]; + par[25] = par[16]; + par[24] = par[16]; + par[23] = par[15]; + par[22] = par[15]; + par[21] = par[14]; + par[20] = par[14]; + par[19] = par[13]; + par[18] = par[12]; + par[17] = par[11]; + par[16] = par[10]; + par[15] = par[ 9]; + par[14] = par[ 9]; + par[13] = par[ 8]; + par[12] = par[ 8]; + par[11] = par[ 7]; + par[10] = par[ 6]; + par[ 9] = par[ 5]; + par[ 8] = par[ 5]; + par[ 7] = par[ 4]; + par[ 6] = par[ 4]; + par[ 5] = par[ 3]; + par[ 4] = (par[ 2] + par[ 3]) * 0.5f; + par[ 3] = par[ 2]; + par[ 2] = par[ 1]; + par[ 1] = (par[ 0] + par[ 1]) * 0.5f; +} + +static void decorrelation(PSContext *ps, float (*out)[32][2], const float (*s)[32][2], int is34) +{ + LOCAL_ALIGNED_16(float, power, [34], [PS_QMF_TIME_SLOTS]); + LOCAL_ALIGNED_16(float, transient_gain, [34], [PS_QMF_TIME_SLOTS]); + float *peak_decay_nrg = ps->peak_decay_nrg; + float *power_smooth = ps->power_smooth; + float *peak_decay_diff_smooth = ps->peak_decay_diff_smooth; + float (*delay)[PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2] = ps->delay; + float (*ap_delay)[PS_AP_LINKS][PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2] = ps->ap_delay; + const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20; + const float peak_decay_factor = 0.76592833836465f; + const float transient_impact = 1.5f; + const float a_smooth = 0.25f; ///< Smoothing coefficient + int i, k, m, n; + int n0 = 0, nL = 32; + + memset(power, 0, 34 * sizeof(*power)); + + if (is34 != ps->is34bands_old) { + memset(ps->peak_decay_nrg, 0, sizeof(ps->peak_decay_nrg)); + memset(ps->power_smooth, 0, sizeof(ps->power_smooth)); + memset(ps->peak_decay_diff_smooth, 0, sizeof(ps->peak_decay_diff_smooth)); + memset(ps->delay, 0, sizeof(ps->delay)); + memset(ps->ap_delay, 0, sizeof(ps->ap_delay)); + } + + for (k = 0; k < NR_BANDS[is34]; k++) { + int i = k_to_i[k]; + ps->dsp.add_squares(power[i], s[k], nL - n0); + } + + //Transient detection + for (i = 0; i < NR_PAR_BANDS[is34]; i++) { + for (n = n0; n < nL; n++) { + float decayed_peak = peak_decay_factor * peak_decay_nrg[i]; + float denom; + peak_decay_nrg[i] = FFMAX(decayed_peak, power[i][n]); + power_smooth[i] += a_smooth * (power[i][n] - power_smooth[i]); + peak_decay_diff_smooth[i] += a_smooth * (peak_decay_nrg[i] - power[i][n] - peak_decay_diff_smooth[i]); + denom = transient_impact * peak_decay_diff_smooth[i]; + transient_gain[i][n] = (denom > power_smooth[i]) ? + power_smooth[i] / denom : 1.0f; + } + } + + //Decorrelation and transient reduction + // PS_AP_LINKS - 1 + // ----- + // | | Q_fract_allpass[k][m]*z^-link_delay[m] - a[m]*g_decay_slope[k] + //H[k][z] = z^-2 * phi_fract[k] * | | ---------------------------------------------------------------- + // | | 1 - a[m]*g_decay_slope[k]*Q_fract_allpass[k][m]*z^-link_delay[m] + // m = 0 + //d[k][z] (out) = transient_gain_mapped[k][z] * H[k][z] * s[k][z] + for (k = 0; k < NR_ALLPASS_BANDS[is34]; k++) { + int b = k_to_i[k]; + float g_decay_slope = 1.f - DECAY_SLOPE * (k - DECAY_CUTOFF[is34]); + g_decay_slope = av_clipf(g_decay_slope, 0.f, 1.f); + memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0])); + memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0])); + for (m = 0; m < PS_AP_LINKS; m++) { + memcpy(ap_delay[k][m], ap_delay[k][m]+numQMFSlots, 5*sizeof(ap_delay[k][m][0])); + } + ps->dsp.decorrelate(out[k], delay[k] + PS_MAX_DELAY - 2, ap_delay[k], + phi_fract[is34][k], Q_fract_allpass[is34][k], + transient_gain[b], g_decay_slope, nL - n0); + } + for (; k < SHORT_DELAY_BAND[is34]; k++) { + int i = k_to_i[k]; + memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0])); + memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0])); + //H = delay 14 + ps->dsp.mul_pair_single(out[k], delay[k] + PS_MAX_DELAY - 14, + transient_gain[i], nL - n0); + } + for (; k < NR_BANDS[is34]; k++) { + int i = k_to_i[k]; + memcpy(delay[k], delay[k]+nL, PS_MAX_DELAY*sizeof(delay[k][0])); + memcpy(delay[k]+PS_MAX_DELAY, s[k], numQMFSlots*sizeof(delay[k][0])); + //H = delay 1 + ps->dsp.mul_pair_single(out[k], delay[k] + PS_MAX_DELAY - 1, + transient_gain[i], nL - n0); + } +} + +static void remap34(int8_t (**p_par_mapped)[PS_MAX_NR_IIDICC], + int8_t (*par)[PS_MAX_NR_IIDICC], + int num_par, int num_env, int full) +{ + int8_t (*par_mapped)[PS_MAX_NR_IIDICC] = *p_par_mapped; + int e; + if (num_par == 20 || num_par == 11) { + for (e = 0; e < num_env; e++) { + map_idx_20_to_34(par_mapped[e], par[e], full); + } + } else if (num_par == 10 || num_par == 5) { + for (e = 0; e < num_env; e++) { + map_idx_10_to_34(par_mapped[e], par[e], full); + } + } else { + *p_par_mapped = par; + } +} + +static void remap20(int8_t (**p_par_mapped)[PS_MAX_NR_IIDICC], + int8_t (*par)[PS_MAX_NR_IIDICC], + int num_par, int num_env, int full) +{ + int8_t (*par_mapped)[PS_MAX_NR_IIDICC] = *p_par_mapped; + int e; + if (num_par == 34 || num_par == 17) { + for (e = 0; e < num_env; e++) { + map_idx_34_to_20(par_mapped[e], par[e], full); + } + } else if (num_par == 10 || num_par == 5) { + for (e = 0; e < num_env; e++) { + map_idx_10_to_20(par_mapped[e], par[e], full); + } + } else { + *p_par_mapped = par; + } +} + +static void stereo_processing(PSContext *ps, float (*l)[32][2], float (*r)[32][2], int is34) +{ + int e, b, k; + + float (*H11)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H11; + float (*H12)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H12; + float (*H21)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H21; + float (*H22)[PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC] = ps->H22; + int8_t *opd_hist = ps->opd_hist; + int8_t *ipd_hist = ps->ipd_hist; + int8_t iid_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; + int8_t icc_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; + int8_t ipd_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; + int8_t opd_mapped_buf[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; + int8_t (*iid_mapped)[PS_MAX_NR_IIDICC] = iid_mapped_buf; + int8_t (*icc_mapped)[PS_MAX_NR_IIDICC] = icc_mapped_buf; + int8_t (*ipd_mapped)[PS_MAX_NR_IIDICC] = ipd_mapped_buf; + int8_t (*opd_mapped)[PS_MAX_NR_IIDICC] = opd_mapped_buf; + const int8_t *k_to_i = is34 ? k_to_i_34 : k_to_i_20; + const float (*H_LUT)[8][4] = (PS_BASELINE || ps->icc_mode < 3) ? HA : HB; + + //Remapping + if (ps->num_env_old) { + memcpy(H11[0][0], H11[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[0][0][0])); + memcpy(H11[1][0], H11[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H11[1][0][0])); + memcpy(H12[0][0], H12[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[0][0][0])); + memcpy(H12[1][0], H12[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H12[1][0][0])); + memcpy(H21[0][0], H21[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[0][0][0])); + memcpy(H21[1][0], H21[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H21[1][0][0])); + memcpy(H22[0][0], H22[0][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[0][0][0])); + memcpy(H22[1][0], H22[1][ps->num_env_old], PS_MAX_NR_IIDICC*sizeof(H22[1][0][0])); + } + + if (is34) { + remap34(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1); + remap34(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1); + if (ps->enable_ipdopd) { + remap34(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0); + remap34(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0); + } + if (!ps->is34bands_old) { + map_val_20_to_34(H11[0][0]); + map_val_20_to_34(H11[1][0]); + map_val_20_to_34(H12[0][0]); + map_val_20_to_34(H12[1][0]); + map_val_20_to_34(H21[0][0]); + map_val_20_to_34(H21[1][0]); + map_val_20_to_34(H22[0][0]); + map_val_20_to_34(H22[1][0]); + ipdopd_reset(ipd_hist, opd_hist); + } + } else { + remap20(&iid_mapped, ps->iid_par, ps->nr_iid_par, ps->num_env, 1); + remap20(&icc_mapped, ps->icc_par, ps->nr_icc_par, ps->num_env, 1); + if (ps->enable_ipdopd) { + remap20(&ipd_mapped, ps->ipd_par, ps->nr_ipdopd_par, ps->num_env, 0); + remap20(&opd_mapped, ps->opd_par, ps->nr_ipdopd_par, ps->num_env, 0); + } + if (ps->is34bands_old) { + map_val_34_to_20(H11[0][0]); + map_val_34_to_20(H11[1][0]); + map_val_34_to_20(H12[0][0]); + map_val_34_to_20(H12[1][0]); + map_val_34_to_20(H21[0][0]); + map_val_34_to_20(H21[1][0]); + map_val_34_to_20(H22[0][0]); + map_val_34_to_20(H22[1][0]); + ipdopd_reset(ipd_hist, opd_hist); + } + } + + //Mixing + for (e = 0; e < ps->num_env; e++) { + for (b = 0; b < NR_PAR_BANDS[is34]; b++) { + float h11, h12, h21, h22; + h11 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][0]; + h12 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][1]; + h21 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][2]; + h22 = H_LUT[iid_mapped[e][b] + 7 + 23 * ps->iid_quant][icc_mapped[e][b]][3]; + if (!PS_BASELINE && ps->enable_ipdopd && b < ps->nr_ipdopd_par) { + //The spec say says to only run this smoother when enable_ipdopd + //is set but the reference decoder appears to run it constantly + float h11i, h12i, h21i, h22i; + float ipd_adj_re, ipd_adj_im; + int opd_idx = opd_hist[b] * 8 + opd_mapped[e][b]; + int ipd_idx = ipd_hist[b] * 8 + ipd_mapped[e][b]; + float opd_re = pd_re_smooth[opd_idx]; + float opd_im = pd_im_smooth[opd_idx]; + float ipd_re = pd_re_smooth[ipd_idx]; + float ipd_im = pd_im_smooth[ipd_idx]; + opd_hist[b] = opd_idx & 0x3F; + ipd_hist[b] = ipd_idx & 0x3F; + + ipd_adj_re = opd_re*ipd_re + opd_im*ipd_im; + ipd_adj_im = opd_im*ipd_re - opd_re*ipd_im; + h11i = h11 * opd_im; + h11 = h11 * opd_re; + h12i = h12 * ipd_adj_im; + h12 = h12 * ipd_adj_re; + h21i = h21 * opd_im; + h21 = h21 * opd_re; + h22i = h22 * ipd_adj_im; + h22 = h22 * ipd_adj_re; + H11[1][e+1][b] = h11i; + H12[1][e+1][b] = h12i; + H21[1][e+1][b] = h21i; + H22[1][e+1][b] = h22i; + } + H11[0][e+1][b] = h11; + H12[0][e+1][b] = h12; + H21[0][e+1][b] = h21; + H22[0][e+1][b] = h22; + } + for (k = 0; k < NR_BANDS[is34]; k++) { + float h[2][4]; + float h_step[2][4]; + int start = ps->border_position[e]; + int stop = ps->border_position[e+1]; + float width = 1.f / (stop - start); + b = k_to_i[k]; + h[0][0] = H11[0][e][b]; + h[0][1] = H12[0][e][b]; + h[0][2] = H21[0][e][b]; + h[0][3] = H22[0][e][b]; + if (!PS_BASELINE && ps->enable_ipdopd) { + //Is this necessary? ps_04_new seems unchanged + if ((is34 && k <= 13 && k >= 9) || (!is34 && k <= 1)) { + h[1][0] = -H11[1][e][b]; + h[1][1] = -H12[1][e][b]; + h[1][2] = -H21[1][e][b]; + h[1][3] = -H22[1][e][b]; + } else { + h[1][0] = H11[1][e][b]; + h[1][1] = H12[1][e][b]; + h[1][2] = H21[1][e][b]; + h[1][3] = H22[1][e][b]; + } + } + //Interpolation + h_step[0][0] = (H11[0][e+1][b] - h[0][0]) * width; + h_step[0][1] = (H12[0][e+1][b] - h[0][1]) * width; + h_step[0][2] = (H21[0][e+1][b] - h[0][2]) * width; + h_step[0][3] = (H22[0][e+1][b] - h[0][3]) * width; + if (!PS_BASELINE && ps->enable_ipdopd) { + h_step[1][0] = (H11[1][e+1][b] - h[1][0]) * width; + h_step[1][1] = (H12[1][e+1][b] - h[1][1]) * width; + h_step[1][2] = (H21[1][e+1][b] - h[1][2]) * width; + h_step[1][3] = (H22[1][e+1][b] - h[1][3]) * width; + } + ps->dsp.stereo_interpolate[!PS_BASELINE && ps->enable_ipdopd]( + l[k] + start + 1, r[k] + start + 1, + h, h_step, stop - start); + } + } +} + +int ff_ps_apply(AVCodecContext *avctx, PSContext *ps, float L[2][38][64], float R[2][38][64], int top) +{ + LOCAL_ALIGNED_16(float, Lbuf, [91], [32][2]); + LOCAL_ALIGNED_16(float, Rbuf, [91], [32][2]); + const int len = 32; + int is34 = ps->is34bands; + + top += NR_BANDS[is34] - 64; + memset(ps->delay+top, 0, (NR_BANDS[is34] - top)*sizeof(ps->delay[0])); + if (top < NR_ALLPASS_BANDS[is34]) + memset(ps->ap_delay + top, 0, (NR_ALLPASS_BANDS[is34] - top)*sizeof(ps->ap_delay[0])); + + hybrid_analysis(&ps->dsp, Lbuf, ps->in_buf, L, is34, len); + decorrelation(ps, Rbuf, Lbuf, is34); + stereo_processing(ps, Lbuf, Rbuf, is34); + hybrid_synthesis(&ps->dsp, L, Lbuf, is34, len); + hybrid_synthesis(&ps->dsp, R, Rbuf, is34, len); + + return 0; +} + +#define PS_INIT_VLC_STATIC(num, size) \ + INIT_VLC_STATIC(&vlc_ps[num], 9, ps_tmp[num].table_size / ps_tmp[num].elem_size, \ + ps_tmp[num].ps_bits, 1, 1, \ + ps_tmp[num].ps_codes, ps_tmp[num].elem_size, ps_tmp[num].elem_size, \ + size); + +#define PS_VLC_ROW(name) \ + { name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) } + +av_cold void ff_ps_init(void) { + // Syntax initialization + static const struct { + const void *ps_codes, *ps_bits; + const unsigned int table_size, elem_size; + } ps_tmp[] = { + PS_VLC_ROW(huff_iid_df1), + PS_VLC_ROW(huff_iid_dt1), + PS_VLC_ROW(huff_iid_df0), + PS_VLC_ROW(huff_iid_dt0), + PS_VLC_ROW(huff_icc_df), + PS_VLC_ROW(huff_icc_dt), + PS_VLC_ROW(huff_ipd_df), + PS_VLC_ROW(huff_ipd_dt), + PS_VLC_ROW(huff_opd_df), + PS_VLC_ROW(huff_opd_dt), + }; + + PS_INIT_VLC_STATIC(0, 1544); + PS_INIT_VLC_STATIC(1, 832); + PS_INIT_VLC_STATIC(2, 1024); + PS_INIT_VLC_STATIC(3, 1036); + PS_INIT_VLC_STATIC(4, 544); + PS_INIT_VLC_STATIC(5, 544); + PS_INIT_VLC_STATIC(6, 512); + PS_INIT_VLC_STATIC(7, 512); + PS_INIT_VLC_STATIC(8, 512); + PS_INIT_VLC_STATIC(9, 512); + + ps_tableinit(); +} + +av_cold void ff_ps_ctx_init(PSContext *ps) +{ + ff_psdsp_init(&ps->dsp); +} diff --git a/ffmpeg/libavcodec/aacps.h b/ffmpeg/libavcodec/aacps.h new file mode 100644 index 0000000..29323ff --- /dev/null +++ b/ffmpeg/libavcodec/aacps.h @@ -0,0 +1,84 @@ +/* + * MPEG-4 Parametric Stereo definitions and declarations + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +#ifndef AVCODEC_PS_H +#define AVCODEC_PS_H + +#include + +#include "aacpsdsp.h" +#include "avcodec.h" +#include "get_bits.h" + +#define PS_MAX_NUM_ENV 5 +#define PS_MAX_NR_IIDICC 34 +#define PS_MAX_NR_IPDOPD 17 +#define PS_MAX_SSB 91 +#define PS_MAX_AP_BANDS 50 +#define PS_QMF_TIME_SLOTS 32 +#define PS_MAX_DELAY 14 +#define PS_AP_LINKS 3 +#define PS_MAX_AP_DELAY 5 + +typedef struct PSContext { + int start; + int enable_iid; + int iid_quant; + int nr_iid_par; + int nr_ipdopd_par; + int enable_icc; + int icc_mode; + int nr_icc_par; + int enable_ext; + int frame_class; + int num_env_old; + int num_env; + int enable_ipdopd; + int border_position[PS_MAX_NUM_ENV+1]; + int8_t iid_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Inter-channel Intensity Difference Parameters + int8_t icc_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Inter-Channel Coherence Parameters + /* ipd/opd is iid/icc sized so that the same functions can handle both */ + int8_t ipd_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Inter-channel Phase Difference Parameters + int8_t opd_par[PS_MAX_NUM_ENV][PS_MAX_NR_IIDICC]; ///< Overall Phase Difference Parameters + int is34bands; + int is34bands_old; + + DECLARE_ALIGNED(16, float, in_buf)[5][44][2]; + DECLARE_ALIGNED(16, float, delay)[PS_MAX_SSB][PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2]; + DECLARE_ALIGNED(16, float, ap_delay)[PS_MAX_AP_BANDS][PS_AP_LINKS][PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2]; + DECLARE_ALIGNED(16, float, peak_decay_nrg)[34]; + DECLARE_ALIGNED(16, float, power_smooth)[34]; + DECLARE_ALIGNED(16, float, peak_decay_diff_smooth)[34]; + DECLARE_ALIGNED(16, float, H11)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC]; + DECLARE_ALIGNED(16, float, H12)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC]; + DECLARE_ALIGNED(16, float, H21)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC]; + DECLARE_ALIGNED(16, float, H22)[2][PS_MAX_NUM_ENV+1][PS_MAX_NR_IIDICC]; + int8_t opd_hist[PS_MAX_NR_IIDICC]; + int8_t ipd_hist[PS_MAX_NR_IIDICC]; + PSDSPContext dsp; +} PSContext; + +void ff_ps_init(void); +void ff_ps_ctx_init(PSContext *ps); +int ff_ps_read_data(AVCodecContext *avctx, GetBitContext *gb, PSContext *ps, int bits_left); +int ff_ps_apply(AVCodecContext *avctx, PSContext *ps, float L[2][38][64], float R[2][38][64], int top); + +#endif /* AVCODEC_PS_H */ diff --git a/ffmpeg/libavcodec/aacps_tablegen.c b/ffmpeg/libavcodec/aacps_tablegen.c new file mode 100644 index 0000000..f56930b --- /dev/null +++ b/ffmpeg/libavcodec/aacps_tablegen.c @@ -0,0 +1,93 @@ +/* + * Generate a header file for hardcoded Parametric Stereo tables + * + * Copyright (c) 2010 Alex Converse + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#include "aacps_tablegen.h" +#include "tableprint.h" + +void write_float_3d_array (const void *p, int b, int c, int d) +{ + int i; + const float *f = p; + for (i = 0; i < b; i++) { + printf("{\n"); + write_float_2d_array(f, c, d); + printf("},\n"); + f += c * d; + } +} + +void write_float_4d_array (const void *p, int a, int b, int c, int d) +{ + int i; + const float *f = p; + for (i = 0; i < a; i++) { + printf("{\n"); + write_float_3d_array(f, b, c, d); + printf("},\n"); + f += b * c * d; + } +} + +int main(void) +{ + ps_tableinit(); + + write_fileheader(); + + printf("static const float pd_re_smooth[8*8*8] = {\n"); + write_float_array(pd_re_smooth, 8*8*8); + printf("};\n"); + printf("static const float pd_im_smooth[8*8*8] = {\n"); + write_float_array(pd_im_smooth, 8*8*8); + printf("};\n"); + + printf("static const float HA[46][8][4] = {\n"); + write_float_3d_array(HA, 46, 8, 4); + printf("};\n"); + printf("static const float HB[46][8][4] = {\n"); + write_float_3d_array(HB, 46, 8, 4); + printf("};\n"); + + printf("static const DECLARE_ALIGNED(16, float, f20_0_8)[8][8][2] = {\n"); + write_float_3d_array(f20_0_8, 8, 8, 2); + printf("};\n"); + printf("static const DECLARE_ALIGNED(16, float, f34_0_12)[12][8][2] = {\n"); + write_float_3d_array(f34_0_12, 12, 8, 2); + printf("};\n"); + printf("static const DECLARE_ALIGNED(16, float, f34_1_8)[8][8][2] = {\n"); + write_float_3d_array(f34_1_8, 8, 8, 2); + printf("};\n"); + printf("static const DECLARE_ALIGNED(16, float, f34_2_4)[4][8][2] = {\n"); + write_float_3d_array(f34_2_4, 4, 8, 2); + printf("};\n"); + + printf("static const DECLARE_ALIGNED(16, float, Q_fract_allpass)[2][50][3][2] = {\n"); + write_float_4d_array(Q_fract_allpass, 2, 50, 3, 2); + printf("};\n"); + printf("static const DECLARE_ALIGNED(16, float, phi_fract)[2][50][2] = {\n"); + write_float_3d_array(phi_fract, 2, 50, 2); + printf("};\n"); + + return 0; +} diff --git a/ffmpeg/libavcodec/aacps_tablegen.h b/ffmpeg/libavcodec/aacps_tablegen.h new file mode 100644 index 0000000..1f9c326 --- /dev/null +++ b/ffmpeg/libavcodec/aacps_tablegen.h @@ -0,0 +1,215 @@ +/* + * Header file for hardcoded Parametric Stereo tables + * + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +#ifndef AACPS_TABLEGEN_H +#define AACPS_TABLEGEN_H + +#include +#include + +#if CONFIG_HARDCODED_TABLES +#define ps_tableinit() +#include "libavcodec/aacps_tables.h" +#else +#include "libavutil/common.h" +#include "libavutil/libm.h" +#include "libavutil/mathematics.h" +#include "libavutil/mem.h" +#define NR_ALLPASS_BANDS20 30 +#define NR_ALLPASS_BANDS34 50 +#define PS_AP_LINKS 3 +static float pd_re_smooth[8*8*8]; +static float pd_im_smooth[8*8*8]; +static float HA[46][8][4]; +static float HB[46][8][4]; +static DECLARE_ALIGNED(16, float, f20_0_8) [ 8][8][2]; +static DECLARE_ALIGNED(16, float, f34_0_12)[12][8][2]; +static DECLARE_ALIGNED(16, float, f34_1_8) [ 8][8][2]; +static DECLARE_ALIGNED(16, float, f34_2_4) [ 4][8][2]; +static DECLARE_ALIGNED(16, float, Q_fract_allpass)[2][50][3][2]; +static DECLARE_ALIGNED(16, float, phi_fract)[2][50][2]; + +static const float g0_Q8[] = { + 0.00746082949812f, 0.02270420949825f, 0.04546865930473f, 0.07266113929591f, + 0.09885108575264f, 0.11793710567217f, 0.125f +}; + +static const float g0_Q12[] = { + 0.04081179924692f, 0.03812810994926f, 0.05144908135699f, 0.06399831151592f, + 0.07428313801106f, 0.08100347892914f, 0.08333333333333f +}; + +static const float g1_Q8[] = { + 0.01565675600122f, 0.03752716391991f, 0.05417891378782f, 0.08417044116767f, + 0.10307344158036f, 0.12222452249753f, 0.125f +}; + +static const float g2_Q4[] = { + -0.05908211155639f, -0.04871498374946f, 0.0f, 0.07778723915851f, + 0.16486303567403f, 0.23279856662996f, 0.25f +}; + +static void make_filters_from_proto(float (*filter)[8][2], const float *proto, int bands) +{ + int q, n; + for (q = 0; q < bands; q++) { + for (n = 0; n < 7; n++) { + double theta = 2 * M_PI * (q + 0.5) * (n - 6) / bands; + filter[q][n][0] = proto[n] * cos(theta); + filter[q][n][1] = proto[n] * -sin(theta); + } + } +} + +static void ps_tableinit(void) +{ + static const float ipdopd_sin[] = { 0, M_SQRT1_2, 1, M_SQRT1_2, 0, -M_SQRT1_2, -1, -M_SQRT1_2 }; + static const float ipdopd_cos[] = { 1, M_SQRT1_2, 0, -M_SQRT1_2, -1, -M_SQRT1_2, 0, M_SQRT1_2 }; + int pd0, pd1, pd2; + + static const float iid_par_dequant[] = { + //iid_par_dequant_default + 0.05623413251903, 0.12589254117942, 0.19952623149689, 0.31622776601684, + 0.44668359215096, 0.63095734448019, 0.79432823472428, 1, + 1.25892541179417, 1.58489319246111, 2.23872113856834, 3.16227766016838, + 5.01187233627272, 7.94328234724282, 17.7827941003892, + //iid_par_dequant_fine + 0.00316227766017, 0.00562341325190, 0.01, 0.01778279410039, + 0.03162277660168, 0.05623413251903, 0.07943282347243, 0.11220184543020, + 0.15848931924611, 0.22387211385683, 0.31622776601684, 0.39810717055350, + 0.50118723362727, 0.63095734448019, 0.79432823472428, 1, + 1.25892541179417, 1.58489319246111, 1.99526231496888, 2.51188643150958, + 3.16227766016838, 4.46683592150963, 6.30957344480193, 8.91250938133745, + 12.5892541179417, 17.7827941003892, 31.6227766016838, 56.2341325190349, + 100, 177.827941003892, 316.227766016837, + }; + static const float icc_invq[] = { + 1, 0.937, 0.84118, 0.60092, 0.36764, 0, -0.589, -1 + }; + static const float acos_icc_invq[] = { + 0, 0.35685527, 0.57133466, 0.92614472, 1.1943263, M_PI/2, 2.2006171, M_PI + }; + int iid, icc; + + int k, m; + static const int8_t f_center_20[] = { + -3, -1, 1, 3, 5, 7, 10, 14, 18, 22, + }; + static const int8_t f_center_34[] = { + 2, 6, 10, 14, 18, 22, 26, 30, + 34,-10, -6, -2, 51, 57, 15, 21, + 27, 33, 39, 45, 54, 66, 78, 42, + 102, 66, 78, 90,102,114,126, 90, + }; + static const float fractional_delay_links[] = { 0.43f, 0.75f, 0.347f }; + const float fractional_delay_gain = 0.39f; + + for (pd0 = 0; pd0 < 8; pd0++) { + float pd0_re = ipdopd_cos[pd0]; + float pd0_im = ipdopd_sin[pd0]; + for (pd1 = 0; pd1 < 8; pd1++) { + float pd1_re = ipdopd_cos[pd1]; + float pd1_im = ipdopd_sin[pd1]; + for (pd2 = 0; pd2 < 8; pd2++) { + float pd2_re = ipdopd_cos[pd2]; + float pd2_im = ipdopd_sin[pd2]; + float re_smooth = 0.25f * pd0_re + 0.5f * pd1_re + pd2_re; + float im_smooth = 0.25f * pd0_im + 0.5f * pd1_im + pd2_im; + float pd_mag = 1 / sqrt(im_smooth * im_smooth + re_smooth * re_smooth); + pd_re_smooth[pd0*64+pd1*8+pd2] = re_smooth * pd_mag; + pd_im_smooth[pd0*64+pd1*8+pd2] = im_smooth * pd_mag; + } + } + } + + for (iid = 0; iid < 46; iid++) { + float c = iid_par_dequant[iid]; ///< Linear Inter-channel Intensity Difference + float c1 = (float)M_SQRT2 / sqrtf(1.0f + c*c); + float c2 = c * c1; + for (icc = 0; icc < 8; icc++) { + /*if (PS_BASELINE || ps->icc_mode < 3)*/ { + float alpha = 0.5f * acos_icc_invq[icc]; + float beta = alpha * (c1 - c2) * (float)M_SQRT1_2; + HA[iid][icc][0] = c2 * cosf(beta + alpha); + HA[iid][icc][1] = c1 * cosf(beta - alpha); + HA[iid][icc][2] = c2 * sinf(beta + alpha); + HA[iid][icc][3] = c1 * sinf(beta - alpha); + } /* else */ { + float alpha, gamma, mu, rho; + float alpha_c, alpha_s, gamma_c, gamma_s; + rho = FFMAX(icc_invq[icc], 0.05f); + alpha = 0.5f * atan2f(2.0f * c * rho, c*c - 1.0f); + mu = c + 1.0f / c; + mu = sqrtf(1 + (4 * rho * rho - 4)/(mu * mu)); + gamma = atanf(sqrtf((1.0f - mu)/(1.0f + mu))); + if (alpha < 0) alpha += M_PI/2; + alpha_c = cosf(alpha); + alpha_s = sinf(alpha); + gamma_c = cosf(gamma); + gamma_s = sinf(gamma); + HB[iid][icc][0] = M_SQRT2 * alpha_c * gamma_c; + HB[iid][icc][1] = M_SQRT2 * alpha_s * gamma_c; + HB[iid][icc][2] = -M_SQRT2 * alpha_s * gamma_s; + HB[iid][icc][3] = M_SQRT2 * alpha_c * gamma_s; + } + } + } + + for (k = 0; k < NR_ALLPASS_BANDS20; k++) { + double f_center, theta; + if (k < FF_ARRAY_ELEMS(f_center_20)) + f_center = f_center_20[k] * 0.125; + else + f_center = k - 6.5f; + for (m = 0; m < PS_AP_LINKS; m++) { + theta = -M_PI * fractional_delay_links[m] * f_center; + Q_fract_allpass[0][k][m][0] = cos(theta); + Q_fract_allpass[0][k][m][1] = sin(theta); + } + theta = -M_PI*fractional_delay_gain*f_center; + phi_fract[0][k][0] = cos(theta); + phi_fract[0][k][1] = sin(theta); + } + for (k = 0; k < NR_ALLPASS_BANDS34; k++) { + double f_center, theta; + if (k < FF_ARRAY_ELEMS(f_center_34)) + f_center = f_center_34[k] / 24.; + else + f_center = k - 26.5f; + for (m = 0; m < PS_AP_LINKS; m++) { + theta = -M_PI * fractional_delay_links[m] * f_center; + Q_fract_allpass[1][k][m][0] = cos(theta); + Q_fract_allpass[1][k][m][1] = sin(theta); + } + theta = -M_PI*fractional_delay_gain*f_center; + phi_fract[1][k][0] = cos(theta); + phi_fract[1][k][1] = sin(theta); + } + + make_filters_from_proto(f20_0_8, g0_Q8, 8); + make_filters_from_proto(f34_0_12, g0_Q12, 12); + make_filters_from_proto(f34_1_8, g1_Q8, 8); + make_filters_from_proto(f34_2_4, g2_Q4, 4); +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AACPS_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/aacpsdata.c b/ffmpeg/libavcodec/aacpsdata.c new file mode 100644 index 0000000..7431cae --- /dev/null +++ b/ffmpeg/libavcodec/aacpsdata.c @@ -0,0 +1,163 @@ +/* + * MPEG-4 Parametric Stereo data tables + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +static const uint8_t huff_iid_df1_bits[] = { + 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 18, 17, 17, 16, 16, 15, 14, 14, + 13, 12, 12, 11, 10, 10, 8, 7, 6, 5, 4, 3, 1, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 16, 16, 17, 17, 18, 17, 18, 18, + 18, 18, 18, 18, 18, 18, 18, +}; + +static const uint32_t huff_iid_df1_codes[] = { + 0x01FEB4, 0x01FEB5, 0x01FD76, 0x01FD77, 0x01FD74, 0x01FD75, 0x01FE8A, + 0x01FE8B, 0x01FE88, 0x00FE80, 0x01FEB6, 0x00FE82, 0x00FEB8, 0x007F42, + 0x007FAE, 0x003FAF, 0x001FD1, 0x001FE9, 0x000FE9, 0x0007EA, 0x0007FB, + 0x0003FB, 0x0001FB, 0x0001FF, 0x00007C, 0x00003C, 0x00001C, 0x00000C, + 0x000000, 0x000001, 0x000001, 0x000002, 0x000001, 0x00000D, 0x00001D, + 0x00003D, 0x00007D, 0x0000FC, 0x0001FC, 0x0003FC, 0x0003F4, 0x0007EB, + 0x000FEA, 0x001FEA, 0x001FD6, 0x003FD0, 0x007FAF, 0x007F43, 0x00FEB9, + 0x00FE83, 0x01FEB7, 0x00FE81, 0x01FE89, 0x01FE8E, 0x01FE8F, 0x01FE8C, + 0x01FE8D, 0x01FEB2, 0x01FEB3, 0x01FEB0, 0x01FEB1, +}; + +static const uint8_t huff_iid_dt1_bits[] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 13, + 13, 13, 12, 12, 11, 10, 9, 9, 7, 6, 5, 3, 1, 2, 5, 6, 7, 8, + 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, +}; + +static const uint16_t huff_iid_dt1_codes[] = { + 0x004ED4, 0x004ED5, 0x004ECE, 0x004ECF, 0x004ECC, 0x004ED6, 0x004ED8, + 0x004F46, 0x004F60, 0x002718, 0x002719, 0x002764, 0x002765, 0x00276D, + 0x0027B1, 0x0013B7, 0x0013D6, 0x0009C7, 0x0009E9, 0x0009ED, 0x0004EE, + 0x0004F7, 0x000278, 0x000139, 0x00009A, 0x00009F, 0x000020, 0x000011, + 0x00000A, 0x000003, 0x000001, 0x000000, 0x00000B, 0x000012, 0x000021, + 0x00004C, 0x00009B, 0x00013A, 0x000279, 0x000270, 0x0004EF, 0x0004E2, + 0x0009EA, 0x0009D8, 0x0013D7, 0x0013D0, 0x0027B2, 0x0027A2, 0x00271A, + 0x00271B, 0x004F66, 0x004F67, 0x004F61, 0x004F47, 0x004ED9, 0x004ED7, + 0x004ECD, 0x004ED2, 0x004ED3, 0x004ED0, 0x004ED1, +}; + +static const uint8_t huff_iid_df0_bits[] = { + 17, 17, 17, 17, 16, 15, 13, 10, 9, 7, 6, 5, 4, 3, 1, 3, 4, 5, + 6, 6, 8, 11, 13, 14, 14, 15, 17, 18, 18, +}; + +static const uint32_t huff_iid_df0_codes[] = { + 0x01FFFB, 0x01FFFC, 0x01FFFD, 0x01FFFA, 0x00FFFC, 0x007FFC, 0x001FFD, + 0x0003FE, 0x0001FE, 0x00007E, 0x00003C, 0x00001D, 0x00000D, 0x000005, + 0x000000, 0x000004, 0x00000C, 0x00001C, 0x00003D, 0x00003E, 0x0000FE, + 0x0007FE, 0x001FFC, 0x003FFC, 0x003FFD, 0x007FFD, 0x01FFFE, 0x03FFFE, + 0x03FFFF, +}; + +static const uint8_t huff_iid_dt0_bits[] = { + 19, 19, 19, 20, 20, 20, 17, 15, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, + 9, 11, 13, 14, 17, 19, 20, 20, 20, 20, 20, +}; + +static const uint32_t huff_iid_dt0_codes[] = { + 0x07FFF9, 0x07FFFA, 0x07FFFB, 0x0FFFF8, 0x0FFFF9, 0x0FFFFA, 0x01FFFD, + 0x007FFE, 0x000FFE, 0x0003FE, 0x0000FE, 0x00003E, 0x00000E, 0x000002, + 0x000000, 0x000006, 0x00001E, 0x00007E, 0x0001FE, 0x0007FE, 0x001FFE, + 0x003FFE, 0x01FFFC, 0x07FFF8, 0x0FFFFB, 0x0FFFFC, 0x0FFFFD, 0x0FFFFE, + 0x0FFFFF, +}; + +static const uint8_t huff_icc_df_bits[] = { + 14, 14, 12, 10, 7, 5, 3, 1, 2, 4, 6, 8, 9, 11, 13, +}; + +static const uint16_t huff_icc_df_codes[] = { + 0x3FFF, 0x3FFE, 0x0FFE, 0x03FE, 0x007E, 0x001E, 0x0006, 0x0000, + 0x0002, 0x000E, 0x003E, 0x00FE, 0x01FE, 0x07FE, 0x1FFE, +}; + +static const uint8_t huff_icc_dt_bits[] = { + 14, 13, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12, 14, +}; + +static const uint16_t huff_icc_dt_codes[] = { + 0x3FFE, 0x1FFE, 0x07FE, 0x01FE, 0x007E, 0x001E, 0x0006, 0x0000, + 0x0002, 0x000E, 0x003E, 0x00FE, 0x03FE, 0x0FFE, 0x3FFF, +}; + +static const uint8_t huff_ipd_df_bits[] = { + 1, 3, 4, 4, 4, 4, 4, 4, +}; + +static const uint8_t huff_ipd_df_codes[] = { + 0x01, 0x00, 0x06, 0x04, 0x02, 0x03, 0x05, 0x07, +}; + +static const uint8_t huff_ipd_dt_bits[] = { + 1, 3, 4, 5, 5, 4, 4, 3, +}; + +static const uint8_t huff_ipd_dt_codes[] = { + 0x01, 0x02, 0x02, 0x03, 0x02, 0x00, 0x03, 0x03, +}; + +static const uint8_t huff_opd_df_bits[] = { + 1, 3, 4, 4, 5, 5, 4, 3, +}; + +static const uint8_t huff_opd_df_codes[] = { + 0x01, 0x01, 0x06, 0x04, 0x0F, 0x0E, 0x05, 0x00, +}; + +static const uint8_t huff_opd_dt_bits[] = { + 1, 3, 4, 5, 5, 4, 4, 3, +}; + +static const uint8_t huff_opd_dt_codes[] = { + 0x01, 0x02, 0x01, 0x07, 0x06, 0x00, 0x02, 0x03, +}; + +static const int8_t huff_offset[] = { + 30, 30, + 14, 14, + 7, 7, + 0, 0, + 0, 0, +}; + +///Table 8.48 +static const int8_t k_to_i_20[] = { + 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15, + 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 +}; +///Table 8.49 +static const int8_t k_to_i_34[] = { + 0, 1, 2, 3, 4, 5, 6, 6, 7, 2, 1, 0, 10, 10, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 9, 14, 11, 12, 13, 14, 15, 16, 13, 16, 17, 18, 19, 20, 21, + 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, + 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33 +}; + +static const float g1_Q2[] = { + 0.0f, 0.01899487526049f, 0.0f, -0.07293139167538f, + 0.0f, 0.30596630545168f, 0.5f +}; diff --git a/ffmpeg/libavcodec/aacpsdsp.c b/ffmpeg/libavcodec/aacpsdsp.c new file mode 100644 index 0000000..9526d3a --- /dev/null +++ b/ffmpeg/libavcodec/aacpsdsp.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2010 Alex Converse + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "aacpsdsp.h" + +static void ps_add_squares_c(float *dst, const float (*src)[2], int n) +{ + int i; + for (i = 0; i < n; i++) + dst[i] += src[i][0] * src[i][0] + src[i][1] * src[i][1]; +} + +static void ps_mul_pair_single_c(float (*dst)[2], float (*src0)[2], float *src1, + int n) +{ + int i; + for (i = 0; i < n; i++) { + dst[i][0] = src0[i][0] * src1[i]; + dst[i][1] = src0[i][1] * src1[i]; + } +} + +static void ps_hybrid_analysis_c(float (*out)[2], float (*in)[2], + const float (*filter)[8][2], + int stride, int n) +{ + int i, j; + + for (i = 0; i < n; i++) { + float sum_re = filter[i][6][0] * in[6][0]; + float sum_im = filter[i][6][0] * in[6][1]; + + for (j = 0; j < 6; j++) { + float in0_re = in[j][0]; + float in0_im = in[j][1]; + float in1_re = in[12-j][0]; + float in1_im = in[12-j][1]; + sum_re += filter[i][j][0] * (in0_re + in1_re) - + filter[i][j][1] * (in0_im - in1_im); + sum_im += filter[i][j][0] * (in0_im + in1_im) + + filter[i][j][1] * (in0_re - in1_re); + } + out[i * stride][0] = sum_re; + out[i * stride][1] = sum_im; + } +} + +static void ps_hybrid_analysis_ileave_c(float (*out)[32][2], float L[2][38][64], + int i, int len) +{ + int j; + + for (; i < 64; i++) { + for (j = 0; j < len; j++) { + out[i][j][0] = L[0][j][i]; + out[i][j][1] = L[1][j][i]; + } + } +} + +static void ps_hybrid_synthesis_deint_c(float out[2][38][64], + float (*in)[32][2], + int i, int len) +{ + int n; + + for (; i < 64; i++) { + for (n = 0; n < len; n++) { + out[0][n][i] = in[i][n][0]; + out[1][n][i] = in[i][n][1]; + } + } +} + +static void ps_decorrelate_c(float (*out)[2], float (*delay)[2], + float (*ap_delay)[PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2], + const float phi_fract[2], float (*Q_fract)[2], + const float *transient_gain, + float g_decay_slope, + int len) +{ + static const float a[] = { 0.65143905753106f, + 0.56471812200776f, + 0.48954165955695f }; + float ag[PS_AP_LINKS]; + int m, n; + + for (m = 0; m < PS_AP_LINKS; m++) + ag[m] = a[m] * g_decay_slope; + + for (n = 0; n < len; n++) { + float in_re = delay[n][0] * phi_fract[0] - delay[n][1] * phi_fract[1]; + float in_im = delay[n][0] * phi_fract[1] + delay[n][1] * phi_fract[0]; + for (m = 0; m < PS_AP_LINKS; m++) { + float a_re = ag[m] * in_re; + float a_im = ag[m] * in_im; + float link_delay_re = ap_delay[m][n+2-m][0]; + float link_delay_im = ap_delay[m][n+2-m][1]; + float fractional_delay_re = Q_fract[m][0]; + float fractional_delay_im = Q_fract[m][1]; + float apd_re = in_re; + float apd_im = in_im; + in_re = link_delay_re * fractional_delay_re - + link_delay_im * fractional_delay_im - a_re; + in_im = link_delay_re * fractional_delay_im + + link_delay_im * fractional_delay_re - a_im; + ap_delay[m][n+5][0] = apd_re + ag[m] * in_re; + ap_delay[m][n+5][1] = apd_im + ag[m] * in_im; + } + out[n][0] = transient_gain[n] * in_re; + out[n][1] = transient_gain[n] * in_im; + } +} + +static void ps_stereo_interpolate_c(float (*l)[2], float (*r)[2], + float h[2][4], float h_step[2][4], + int len) +{ + float h0 = h[0][0]; + float h1 = h[0][1]; + float h2 = h[0][2]; + float h3 = h[0][3]; + float hs0 = h_step[0][0]; + float hs1 = h_step[0][1]; + float hs2 = h_step[0][2]; + float hs3 = h_step[0][3]; + int n; + + for (n = 0; n < len; n++) { + //l is s, r is d + float l_re = l[n][0]; + float l_im = l[n][1]; + float r_re = r[n][0]; + float r_im = r[n][1]; + h0 += hs0; + h1 += hs1; + h2 += hs2; + h3 += hs3; + l[n][0] = h0 * l_re + h2 * r_re; + l[n][1] = h0 * l_im + h2 * r_im; + r[n][0] = h1 * l_re + h3 * r_re; + r[n][1] = h1 * l_im + h3 * r_im; + } +} + +static void ps_stereo_interpolate_ipdopd_c(float (*l)[2], float (*r)[2], + float h[2][4], float h_step[2][4], + int len) +{ + float h00 = h[0][0], h10 = h[1][0]; + float h01 = h[0][1], h11 = h[1][1]; + float h02 = h[0][2], h12 = h[1][2]; + float h03 = h[0][3], h13 = h[1][3]; + float hs00 = h_step[0][0], hs10 = h_step[1][0]; + float hs01 = h_step[0][1], hs11 = h_step[1][1]; + float hs02 = h_step[0][2], hs12 = h_step[1][2]; + float hs03 = h_step[0][3], hs13 = h_step[1][3]; + int n; + + for (n = 0; n < len; n++) { + //l is s, r is d + float l_re = l[n][0]; + float l_im = l[n][1]; + float r_re = r[n][0]; + float r_im = r[n][1]; + h00 += hs00; + h01 += hs01; + h02 += hs02; + h03 += hs03; + h10 += hs10; + h11 += hs11; + h12 += hs12; + h13 += hs13; + + l[n][0] = h00 * l_re + h02 * r_re - h10 * l_im - h12 * r_im; + l[n][1] = h00 * l_im + h02 * r_im + h10 * l_re + h12 * r_re; + r[n][0] = h01 * l_re + h03 * r_re - h11 * l_im - h13 * r_im; + r[n][1] = h01 * l_im + h03 * r_im + h11 * l_re + h13 * r_re; + } +} + +av_cold void ff_psdsp_init(PSDSPContext *s) +{ + s->add_squares = ps_add_squares_c; + s->mul_pair_single = ps_mul_pair_single_c; + s->hybrid_analysis = ps_hybrid_analysis_c; + s->hybrid_analysis_ileave = ps_hybrid_analysis_ileave_c; + s->hybrid_synthesis_deint = ps_hybrid_synthesis_deint_c; + s->decorrelate = ps_decorrelate_c; + s->stereo_interpolate[0] = ps_stereo_interpolate_c; + s->stereo_interpolate[1] = ps_stereo_interpolate_ipdopd_c; + + if (ARCH_ARM) + ff_psdsp_init_arm(s); + if (ARCH_MIPS) + ff_psdsp_init_mips(s); +} diff --git a/ffmpeg/libavcodec/aacpsdsp.h b/ffmpeg/libavcodec/aacpsdsp.h new file mode 100644 index 0000000..df01e0b --- /dev/null +++ b/ffmpeg/libavcodec/aacpsdsp.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBAVCODEC_AACPSDSP_H +#define LIBAVCODEC_AACPSDSP_H + +#define PS_QMF_TIME_SLOTS 32 +#define PS_AP_LINKS 3 +#define PS_MAX_AP_DELAY 5 + +typedef struct PSDSPContext { + void (*add_squares)(float *dst, const float (*src)[2], int n); + void (*mul_pair_single)(float (*dst)[2], float (*src0)[2], float *src1, + int n); + void (*hybrid_analysis)(float (*out)[2], float (*in)[2], + const float (*filter)[8][2], + int stride, int n); + void (*hybrid_analysis_ileave)(float (*out)[32][2], float L[2][38][64], + int i, int len); + void (*hybrid_synthesis_deint)(float out[2][38][64], float (*in)[32][2], + int i, int len); + void (*decorrelate)(float (*out)[2], float (*delay)[2], + float (*ap_delay)[PS_QMF_TIME_SLOTS+PS_MAX_AP_DELAY][2], + const float phi_fract[2], float (*Q_fract)[2], + const float *transient_gain, + float g_decay_slope, + int len); + void (*stereo_interpolate[2])(float (*l)[2], float (*r)[2], + float h[2][4], float h_step[2][4], + int len); +} PSDSPContext; + +void ff_psdsp_init(PSDSPContext *s); +void ff_psdsp_init_arm(PSDSPContext *s); +void ff_psdsp_init_mips(PSDSPContext *s); + +#endif /* LIBAVCODEC_AACPSDSP_H */ diff --git a/ffmpeg/libavcodec/aacpsy.c b/ffmpeg/libavcodec/aacpsy.c new file mode 100644 index 0000000..e399be5 --- /dev/null +++ b/ffmpeg/libavcodec/aacpsy.c @@ -0,0 +1,940 @@ +/* + * AAC encoder psychoacoustic model + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * AAC encoder psychoacoustic model + */ + +#include "libavutil/libm.h" + +#include "avcodec.h" +#include "aactab.h" +#include "psymodel.h" + +/*********************************** + * TODOs: + * try other bitrate controlling mechanism (maybe use ratecontrol.c?) + * control quality for quality-based output + **********************************/ + +/** + * constants for 3GPP AAC psychoacoustic model + * @{ + */ +#define PSY_3GPP_THR_SPREAD_HI 1.5f // spreading factor for low-to-hi threshold spreading (15 dB/Bark) +#define PSY_3GPP_THR_SPREAD_LOW 3.0f // spreading factor for hi-to-low threshold spreading (30 dB/Bark) +/* spreading factor for low-to-hi energy spreading, long block, > 22kbps/channel (20dB/Bark) */ +#define PSY_3GPP_EN_SPREAD_HI_L1 2.0f +/* spreading factor for low-to-hi energy spreading, long block, <= 22kbps/channel (15dB/Bark) */ +#define PSY_3GPP_EN_SPREAD_HI_L2 1.5f +/* spreading factor for low-to-hi energy spreading, short block (15 dB/Bark) */ +#define PSY_3GPP_EN_SPREAD_HI_S 1.5f +/* spreading factor for hi-to-low energy spreading, long block (30dB/Bark) */ +#define PSY_3GPP_EN_SPREAD_LOW_L 3.0f +/* spreading factor for hi-to-low energy spreading, short block (20dB/Bark) */ +#define PSY_3GPP_EN_SPREAD_LOW_S 2.0f + +#define PSY_3GPP_RPEMIN 0.01f +#define PSY_3GPP_RPELEV 2.0f + +#define PSY_3GPP_C1 3.0f /* log2(8) */ +#define PSY_3GPP_C2 1.3219281f /* log2(2.5) */ +#define PSY_3GPP_C3 0.55935729f /* 1 - C2 / C1 */ + +#define PSY_SNR_1DB 7.9432821e-1f /* -1dB */ +#define PSY_SNR_25DB 3.1622776e-3f /* -25dB */ + +#define PSY_3GPP_SAVE_SLOPE_L -0.46666667f +#define PSY_3GPP_SAVE_SLOPE_S -0.36363637f +#define PSY_3GPP_SAVE_ADD_L -0.84285712f +#define PSY_3GPP_SAVE_ADD_S -0.75f +#define PSY_3GPP_SPEND_SLOPE_L 0.66666669f +#define PSY_3GPP_SPEND_SLOPE_S 0.81818181f +#define PSY_3GPP_SPEND_ADD_L -0.35f +#define PSY_3GPP_SPEND_ADD_S -0.26111111f +#define PSY_3GPP_CLIP_LO_L 0.2f +#define PSY_3GPP_CLIP_LO_S 0.2f +#define PSY_3GPP_CLIP_HI_L 0.95f +#define PSY_3GPP_CLIP_HI_S 0.75f + +#define PSY_3GPP_AH_THR_LONG 0.5f +#define PSY_3GPP_AH_THR_SHORT 0.63f + +enum { + PSY_3GPP_AH_NONE, + PSY_3GPP_AH_INACTIVE, + PSY_3GPP_AH_ACTIVE +}; + +#define PSY_3GPP_BITS_TO_PE(bits) ((bits) * 1.18f) + +/* LAME psy model constants */ +#define PSY_LAME_FIR_LEN 21 ///< LAME psy model FIR order +#define AAC_BLOCK_SIZE_LONG 1024 ///< long block size +#define AAC_BLOCK_SIZE_SHORT 128 ///< short block size +#define AAC_NUM_BLOCKS_SHORT 8 ///< number of blocks in a short sequence +#define PSY_LAME_NUM_SUBBLOCKS 3 ///< Number of sub-blocks in each short block + +/** + * @} + */ + +/** + * information for single band used by 3GPP TS26.403-inspired psychoacoustic model + */ +typedef struct AacPsyBand{ + float energy; ///< band energy + float thr; ///< energy threshold + float thr_quiet; ///< threshold in quiet + float nz_lines; ///< number of non-zero spectral lines + float active_lines; ///< number of active spectral lines + float pe; ///< perceptual entropy + float pe_const; ///< constant part of the PE calculation + float norm_fac; ///< normalization factor for linearization + int avoid_holes; ///< hole avoidance flag +}AacPsyBand; + +/** + * single/pair channel context for psychoacoustic model + */ +typedef struct AacPsyChannel{ + AacPsyBand band[128]; ///< bands information + AacPsyBand prev_band[128]; ///< bands information from the previous frame + + float win_energy; ///< sliding average of channel energy + float iir_state[2]; ///< hi-pass IIR filter state + uint8_t next_grouping; ///< stored grouping scheme for the next frame (in case of 8 short window sequence) + enum WindowSequence next_window_seq; ///< window sequence to be used in the next frame + /* LAME psy model specific members */ + float attack_threshold; ///< attack threshold for this channel + float prev_energy_subshort[AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS]; + int prev_attack; ///< attack value for the last short block in the previous sequence +}AacPsyChannel; + +/** + * psychoacoustic model frame type-dependent coefficients + */ +typedef struct AacPsyCoeffs{ + float ath; ///< absolute threshold of hearing per bands + float barks; ///< Bark value for each spectral band in long frame + float spread_low[2]; ///< spreading factor for low-to-high threshold spreading in long frame + float spread_hi [2]; ///< spreading factor for high-to-low threshold spreading in long frame + float min_snr; ///< minimal SNR +}AacPsyCoeffs; + +/** + * 3GPP TS26.403-inspired psychoacoustic model specific data + */ +typedef struct AacPsyContext{ + int chan_bitrate; ///< bitrate per channel + int frame_bits; ///< average bits per frame + int fill_level; ///< bit reservoir fill level + struct { + float min; ///< minimum allowed PE for bit factor calculation + float max; ///< maximum allowed PE for bit factor calculation + float previous; ///< allowed PE of the previous frame + float correction; ///< PE correction factor + } pe; + AacPsyCoeffs psy_coef[2][64]; + AacPsyChannel *ch; +}AacPsyContext; + +/** + * LAME psy model preset struct + */ +typedef struct { + int quality; ///< Quality to map the rest of the vaules to. + /* This is overloaded to be both kbps per channel in ABR mode, and + * requested quality in constant quality mode. + */ + float st_lrm; ///< short threshold for L, R, and M channels +} PsyLamePreset; + +/** + * LAME psy model preset table for ABR + */ +static const PsyLamePreset psy_abr_map[] = { +/* TODO: Tuning. These were taken from LAME. */ +/* kbps/ch st_lrm */ + { 8, 6.60}, + { 16, 6.60}, + { 24, 6.60}, + { 32, 6.60}, + { 40, 6.60}, + { 48, 6.60}, + { 56, 6.60}, + { 64, 6.40}, + { 80, 6.00}, + { 96, 5.60}, + {112, 5.20}, + {128, 5.20}, + {160, 5.20} +}; + +/** +* LAME psy model preset table for constant quality +*/ +static const PsyLamePreset psy_vbr_map[] = { +/* vbr_q st_lrm */ + { 0, 4.20}, + { 1, 4.20}, + { 2, 4.20}, + { 3, 4.20}, + { 4, 4.20}, + { 5, 4.20}, + { 6, 4.20}, + { 7, 4.20}, + { 8, 4.20}, + { 9, 4.20}, + {10, 4.20} +}; + +/** + * LAME psy model FIR coefficient table + */ +static const float psy_fir_coeffs[] = { + -8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2, + -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2, + -5.52212e-17 * 2, -0.313819 * 2 +}; + +/** + * Calculate the ABR attack threshold from the above LAME psymodel table. + */ +static float lame_calc_attack_threshold(int bitrate) +{ + /* Assume max bitrate to start with */ + int lower_range = 12, upper_range = 12; + int lower_range_kbps = psy_abr_map[12].quality; + int upper_range_kbps = psy_abr_map[12].quality; + int i; + + /* Determine which bitrates the value specified falls between. + * If the loop ends without breaking our above assumption of 320kbps was correct. + */ + for (i = 1; i < 13; i++) { + if (FFMAX(bitrate, psy_abr_map[i].quality) != bitrate) { + upper_range = i; + upper_range_kbps = psy_abr_map[i ].quality; + lower_range = i - 1; + lower_range_kbps = psy_abr_map[i - 1].quality; + break; /* Upper range found */ + } + } + + /* Determine which range the value specified is closer to */ + if ((upper_range_kbps - bitrate) > (bitrate - lower_range_kbps)) + return psy_abr_map[lower_range].st_lrm; + return psy_abr_map[upper_range].st_lrm; +} + +/** + * LAME psy model specific initialization + */ +static void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx) { + int i, j; + + for (i = 0; i < avctx->channels; i++) { + AacPsyChannel *pch = &ctx->ch[i]; + + if (avctx->flags & CODEC_FLAG_QSCALE) + pch->attack_threshold = psy_vbr_map[avctx->global_quality / FF_QP2LAMBDA].st_lrm; + else + pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->channels / 1000); + + for (j = 0; j < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; j++) + pch->prev_energy_subshort[j] = 10.0f; + } +} + +/** + * Calculate Bark value for given line. + */ +static av_cold float calc_bark(float f) +{ + return 13.3f * atanf(0.00076f * f) + 3.5f * atanf((f / 7500.0f) * (f / 7500.0f)); +} + +#define ATH_ADD 4 +/** + * Calculate ATH value for given frequency. + * Borrowed from Lame. + */ +static av_cold float ath(float f, float add) +{ + f /= 1000.0f; + return 3.64 * pow(f, -0.8) + - 6.8 * exp(-0.6 * (f - 3.4) * (f - 3.4)) + + 6.0 * exp(-0.15 * (f - 8.7) * (f - 8.7)) + + (0.6 + 0.04 * add) * 0.001 * f * f * f * f; +} + +static av_cold int psy_3gpp_init(FFPsyContext *ctx) { + AacPsyContext *pctx; + float bark; + int i, j, g, start; + float prev, minscale, minath, minsnr, pe_min; + const int chan_bitrate = ctx->avctx->bit_rate / ctx->avctx->channels; + const int bandwidth = ctx->avctx->cutoff ? ctx->avctx->cutoff : AAC_CUTOFF(ctx->avctx); + const float num_bark = calc_bark((float)bandwidth); + + ctx->model_priv_data = av_mallocz(sizeof(AacPsyContext)); + pctx = (AacPsyContext*) ctx->model_priv_data; + + pctx->chan_bitrate = chan_bitrate; + pctx->frame_bits = chan_bitrate * AAC_BLOCK_SIZE_LONG / ctx->avctx->sample_rate; + pctx->pe.min = 8.0f * AAC_BLOCK_SIZE_LONG * bandwidth / (ctx->avctx->sample_rate * 2.0f); + pctx->pe.max = 12.0f * AAC_BLOCK_SIZE_LONG * bandwidth / (ctx->avctx->sample_rate * 2.0f); + ctx->bitres.size = 6144 - pctx->frame_bits; + ctx->bitres.size -= ctx->bitres.size % 8; + pctx->fill_level = ctx->bitres.size; + minath = ath(3410, ATH_ADD); + for (j = 0; j < 2; j++) { + AacPsyCoeffs *coeffs = pctx->psy_coef[j]; + const uint8_t *band_sizes = ctx->bands[j]; + float line_to_frequency = ctx->avctx->sample_rate / (j ? 256.f : 2048.0f); + float avg_chan_bits = chan_bitrate / ctx->avctx->sample_rate * (j ? 128.0f : 1024.0f); + /* reference encoder uses 2.4% here instead of 60% like the spec says */ + float bark_pe = 0.024f * PSY_3GPP_BITS_TO_PE(avg_chan_bits) / num_bark; + float en_spread_low = j ? PSY_3GPP_EN_SPREAD_LOW_S : PSY_3GPP_EN_SPREAD_LOW_L; + /* High energy spreading for long blocks <= 22kbps/channel and short blocks are the same. */ + float en_spread_hi = (j || (chan_bitrate <= 22.0f)) ? PSY_3GPP_EN_SPREAD_HI_S : PSY_3GPP_EN_SPREAD_HI_L1; + + i = 0; + prev = 0.0; + for (g = 0; g < ctx->num_bands[j]; g++) { + i += band_sizes[g]; + bark = calc_bark((i-1) * line_to_frequency); + coeffs[g].barks = (bark + prev) / 2.0; + prev = bark; + } + for (g = 0; g < ctx->num_bands[j] - 1; g++) { + AacPsyCoeffs *coeff = &coeffs[g]; + float bark_width = coeffs[g+1].barks - coeffs->barks; + coeff->spread_low[0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_LOW); + coeff->spread_hi [0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_HI); + coeff->spread_low[1] = pow(10.0, -bark_width * en_spread_low); + coeff->spread_hi [1] = pow(10.0, -bark_width * en_spread_hi); + pe_min = bark_pe * bark_width; + minsnr = exp2(pe_min / band_sizes[g]) - 1.5f; + coeff->min_snr = av_clipf(1.0f / minsnr, PSY_SNR_25DB, PSY_SNR_1DB); + } + start = 0; + for (g = 0; g < ctx->num_bands[j]; g++) { + minscale = ath(start * line_to_frequency, ATH_ADD); + for (i = 1; i < band_sizes[g]; i++) + minscale = FFMIN(minscale, ath((start + i) * line_to_frequency, ATH_ADD)); + coeffs[g].ath = minscale - minath; + start += band_sizes[g]; + } + } + + pctx->ch = av_mallocz(sizeof(AacPsyChannel) * ctx->avctx->channels); + + lame_window_init(pctx, ctx->avctx); + + return 0; +} + +/** + * IIR filter used in block switching decision + */ +static float iir_filter(int in, float state[2]) +{ + float ret; + + ret = 0.7548f * (in - state[0]) + 0.5095f * state[1]; + state[0] = in; + state[1] = ret; + return ret; +} + +/** + * window grouping information stored as bits (0 - new group, 1 - group continues) + */ +static const uint8_t window_grouping[9] = { + 0xB6, 0x6C, 0xD8, 0xB2, 0x66, 0xC6, 0x96, 0x36, 0x36 +}; + +/** + * Tell encoder which window types to use. + * @see 3GPP TS26.403 5.4.1 "Blockswitching" + */ +static av_unused FFPsyWindowInfo psy_3gpp_window(FFPsyContext *ctx, + const int16_t *audio, + const int16_t *la, + int channel, int prev_type) +{ + int i, j; + int br = ctx->avctx->bit_rate / ctx->avctx->channels; + int attack_ratio = br <= 16000 ? 18 : 10; + AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data; + AacPsyChannel *pch = &pctx->ch[channel]; + uint8_t grouping = 0; + int next_type = pch->next_window_seq; + FFPsyWindowInfo wi = { { 0 } }; + + if (la) { + float s[8], v; + int switch_to_eight = 0; + float sum = 0.0, sum2 = 0.0; + int attack_n = 0; + int stay_short = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 128; j++) { + v = iir_filter(la[i*128+j], pch->iir_state); + sum += v*v; + } + s[i] = sum; + sum2 += sum; + } + for (i = 0; i < 8; i++) { + if (s[i] > pch->win_energy * attack_ratio) { + attack_n = i + 1; + switch_to_eight = 1; + break; + } + } + pch->win_energy = pch->win_energy*7/8 + sum2/64; + + wi.window_type[1] = prev_type; + switch (prev_type) { + case ONLY_LONG_SEQUENCE: + wi.window_type[0] = switch_to_eight ? LONG_START_SEQUENCE : ONLY_LONG_SEQUENCE; + next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : ONLY_LONG_SEQUENCE; + break; + case LONG_START_SEQUENCE: + wi.window_type[0] = EIGHT_SHORT_SEQUENCE; + grouping = pch->next_grouping; + next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE; + break; + case LONG_STOP_SEQUENCE: + wi.window_type[0] = switch_to_eight ? LONG_START_SEQUENCE : ONLY_LONG_SEQUENCE; + next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : ONLY_LONG_SEQUENCE; + break; + case EIGHT_SHORT_SEQUENCE: + stay_short = next_type == EIGHT_SHORT_SEQUENCE || switch_to_eight; + wi.window_type[0] = stay_short ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE; + grouping = next_type == EIGHT_SHORT_SEQUENCE ? pch->next_grouping : 0; + next_type = switch_to_eight ? EIGHT_SHORT_SEQUENCE : LONG_STOP_SEQUENCE; + break; + } + + pch->next_grouping = window_grouping[attack_n]; + pch->next_window_seq = next_type; + } else { + for (i = 0; i < 3; i++) + wi.window_type[i] = prev_type; + grouping = (prev_type == EIGHT_SHORT_SEQUENCE) ? window_grouping[0] : 0; + } + + wi.window_shape = 1; + if (wi.window_type[0] != EIGHT_SHORT_SEQUENCE) { + wi.num_windows = 1; + wi.grouping[0] = 1; + } else { + int lastgrp = 0; + wi.num_windows = 8; + for (i = 0; i < 8; i++) { + if (!((grouping >> i) & 1)) + lastgrp = i; + wi.grouping[lastgrp]++; + } + } + + return wi; +} + +/* 5.6.1.2 "Calculation of Bit Demand" */ +static int calc_bit_demand(AacPsyContext *ctx, float pe, int bits, int size, + int short_window) +{ + const float bitsave_slope = short_window ? PSY_3GPP_SAVE_SLOPE_S : PSY_3GPP_SAVE_SLOPE_L; + const float bitsave_add = short_window ? PSY_3GPP_SAVE_ADD_S : PSY_3GPP_SAVE_ADD_L; + const float bitspend_slope = short_window ? PSY_3GPP_SPEND_SLOPE_S : PSY_3GPP_SPEND_SLOPE_L; + const float bitspend_add = short_window ? PSY_3GPP_SPEND_ADD_S : PSY_3GPP_SPEND_ADD_L; + const float clip_low = short_window ? PSY_3GPP_CLIP_LO_S : PSY_3GPP_CLIP_LO_L; + const float clip_high = short_window ? PSY_3GPP_CLIP_HI_S : PSY_3GPP_CLIP_HI_L; + float clipped_pe, bit_save, bit_spend, bit_factor, fill_level; + + ctx->fill_level += ctx->frame_bits - bits; + ctx->fill_level = av_clip(ctx->fill_level, 0, size); + fill_level = av_clipf((float)ctx->fill_level / size, clip_low, clip_high); + clipped_pe = av_clipf(pe, ctx->pe.min, ctx->pe.max); + bit_save = (fill_level + bitsave_add) * bitsave_slope; + assert(bit_save <= 0.3f && bit_save >= -0.05000001f); + bit_spend = (fill_level + bitspend_add) * bitspend_slope; + assert(bit_spend <= 0.5f && bit_spend >= -0.1f); + /* The bit factor graph in the spec is obviously incorrect. + * bit_spend + ((bit_spend - bit_spend))... + * The reference encoder subtracts everything from 1, but also seems incorrect. + * 1 - bit_save + ((bit_spend + bit_save))... + * Hopefully below is correct. + */ + bit_factor = 1.0f - bit_save + ((bit_spend - bit_save) / (ctx->pe.max - ctx->pe.min)) * (clipped_pe - ctx->pe.min); + /* NOTE: The reference encoder attempts to center pe max/min around the current pe. */ + ctx->pe.max = FFMAX(pe, ctx->pe.max); + ctx->pe.min = FFMIN(pe, ctx->pe.min); + + return FFMIN(ctx->frame_bits * bit_factor, ctx->frame_bits + size - bits); +} + +static float calc_pe_3gpp(AacPsyBand *band) +{ + float pe, a; + + band->pe = 0.0f; + band->pe_const = 0.0f; + band->active_lines = 0.0f; + if (band->energy > band->thr) { + a = log2f(band->energy); + pe = a - log2f(band->thr); + band->active_lines = band->nz_lines; + if (pe < PSY_3GPP_C1) { + pe = pe * PSY_3GPP_C3 + PSY_3GPP_C2; + a = a * PSY_3GPP_C3 + PSY_3GPP_C2; + band->active_lines *= PSY_3GPP_C3; + } + band->pe = pe * band->nz_lines; + band->pe_const = a * band->nz_lines; + } + + return band->pe; +} + +static float calc_reduction_3gpp(float a, float desired_pe, float pe, + float active_lines) +{ + float thr_avg, reduction; + + if(active_lines == 0.0) + return 0; + + thr_avg = exp2f((a - pe) / (4.0f * active_lines)); + reduction = exp2f((a - desired_pe) / (4.0f * active_lines)) - thr_avg; + + return FFMAX(reduction, 0.0f); +} + +static float calc_reduced_thr_3gpp(AacPsyBand *band, float min_snr, + float reduction) +{ + float thr = band->thr; + + if (band->energy > thr) { + thr = sqrtf(thr); + thr = sqrtf(thr) + reduction; + thr *= thr; + thr *= thr; + + /* This deviates from the 3GPP spec to match the reference encoder. + * It performs min(thr_reduced, max(thr, energy/min_snr)) only for bands + * that have hole avoidance on (active or inactive). It always reduces the + * threshold of bands with hole avoidance off. + */ + if (thr > band->energy * min_snr && band->avoid_holes != PSY_3GPP_AH_NONE) { + thr = FFMAX(band->thr, band->energy * min_snr); + band->avoid_holes = PSY_3GPP_AH_ACTIVE; + } + } + + return thr; +} + +/** + * Calculate band thresholds as suggested in 3GPP TS26.403 + */ +static void psy_3gpp_analyze_channel(FFPsyContext *ctx, int channel, + const float *coefs, const FFPsyWindowInfo *wi) +{ + AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data; + AacPsyChannel *pch = &pctx->ch[channel]; + int start = 0; + int i, w, g; + float desired_bits, desired_pe, delta_pe, reduction= NAN, spread_en[128] = {0}; + float a = 0.0f, active_lines = 0.0f, norm_fac = 0.0f; + float pe = pctx->chan_bitrate > 32000 ? 0.0f : FFMAX(50.0f, 100.0f - pctx->chan_bitrate * 100.0f / 32000.0f); + const int num_bands = ctx->num_bands[wi->num_windows == 8]; + const uint8_t *band_sizes = ctx->bands[wi->num_windows == 8]; + AacPsyCoeffs *coeffs = pctx->psy_coef[wi->num_windows == 8]; + const float avoid_hole_thr = wi->num_windows == 8 ? PSY_3GPP_AH_THR_SHORT : PSY_3GPP_AH_THR_LONG; + + //calculate energies, initial thresholds and related values - 5.4.2 "Threshold Calculation" + for (w = 0; w < wi->num_windows*16; w += 16) { + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &pch->band[w+g]; + + float form_factor = 0.0f; + float Temp; + band->energy = 0.0f; + for (i = 0; i < band_sizes[g]; i++) { + band->energy += coefs[start+i] * coefs[start+i]; + form_factor += sqrtf(fabs(coefs[start+i])); + } + Temp = band->energy > 0 ? sqrtf((float)band_sizes[g] / band->energy) : 0; + band->thr = band->energy * 0.001258925f; + band->nz_lines = form_factor * sqrtf(Temp); + + start += band_sizes[g]; + } + } + //modify thresholds and energies - spread, threshold in quiet, pre-echo control + for (w = 0; w < wi->num_windows*16; w += 16) { + AacPsyBand *bands = &pch->band[w]; + + /* 5.4.2.3 "Spreading" & 5.4.3 "Spread Energy Calculation" */ + spread_en[0] = bands[0].energy; + for (g = 1; g < num_bands; g++) { + bands[g].thr = FFMAX(bands[g].thr, bands[g-1].thr * coeffs[g].spread_hi[0]); + spread_en[w+g] = FFMAX(bands[g].energy, spread_en[w+g-1] * coeffs[g].spread_hi[1]); + } + for (g = num_bands - 2; g >= 0; g--) { + bands[g].thr = FFMAX(bands[g].thr, bands[g+1].thr * coeffs[g].spread_low[0]); + spread_en[w+g] = FFMAX(spread_en[w+g], spread_en[w+g+1] * coeffs[g].spread_low[1]); + } + //5.4.2.4 "Threshold in quiet" + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &bands[g]; + + band->thr_quiet = band->thr = FFMAX(band->thr, coeffs[g].ath); + //5.4.2.5 "Pre-echo control" + if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (wi->window_type[1] == LONG_START_SEQUENCE && !w))) + band->thr = FFMAX(PSY_3GPP_RPEMIN*band->thr, FFMIN(band->thr, + PSY_3GPP_RPELEV*pch->prev_band[w+g].thr_quiet)); + + /* 5.6.1.3.1 "Preparatory steps of the perceptual entropy calculation" */ + pe += calc_pe_3gpp(band); + a += band->pe_const; + active_lines += band->active_lines; + + /* 5.6.1.3.3 "Selection of the bands for avoidance of holes" */ + if (spread_en[w+g] * avoid_hole_thr > band->energy || coeffs[g].min_snr > 1.0f) + band->avoid_holes = PSY_3GPP_AH_NONE; + else + band->avoid_holes = PSY_3GPP_AH_INACTIVE; + } + } + + /* 5.6.1.3.2 "Calculation of the desired perceptual entropy" */ + ctx->ch[channel].entropy = pe; + desired_bits = calc_bit_demand(pctx, pe, ctx->bitres.bits, ctx->bitres.size, wi->num_windows == 8); + desired_pe = PSY_3GPP_BITS_TO_PE(desired_bits); + /* NOTE: PE correction is kept simple. During initial testing it had very + * little effect on the final bitrate. Probably a good idea to come + * back and do more testing later. + */ + if (ctx->bitres.bits > 0) + desired_pe *= av_clipf(pctx->pe.previous / PSY_3GPP_BITS_TO_PE(ctx->bitres.bits), + 0.85f, 1.15f); + pctx->pe.previous = PSY_3GPP_BITS_TO_PE(desired_bits); + + if (desired_pe < pe) { + /* 5.6.1.3.4 "First Estimation of the reduction value" */ + for (w = 0; w < wi->num_windows*16; w += 16) { + reduction = calc_reduction_3gpp(a, desired_pe, pe, active_lines); + pe = 0.0f; + a = 0.0f; + active_lines = 0.0f; + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &pch->band[w+g]; + + band->thr = calc_reduced_thr_3gpp(band, coeffs[g].min_snr, reduction); + /* recalculate PE */ + pe += calc_pe_3gpp(band); + a += band->pe_const; + active_lines += band->active_lines; + } + } + + /* 5.6.1.3.5 "Second Estimation of the reduction value" */ + for (i = 0; i < 2; i++) { + float pe_no_ah = 0.0f, desired_pe_no_ah; + active_lines = a = 0.0f; + for (w = 0; w < wi->num_windows*16; w += 16) { + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &pch->band[w+g]; + + if (band->avoid_holes != PSY_3GPP_AH_ACTIVE) { + pe_no_ah += band->pe; + a += band->pe_const; + active_lines += band->active_lines; + } + } + } + desired_pe_no_ah = FFMAX(desired_pe - (pe - pe_no_ah), 0.0f); + if (active_lines > 0.0f) + reduction += calc_reduction_3gpp(a, desired_pe_no_ah, pe_no_ah, active_lines); + + pe = 0.0f; + for (w = 0; w < wi->num_windows*16; w += 16) { + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &pch->band[w+g]; + + if (active_lines > 0.0f) + band->thr = calc_reduced_thr_3gpp(band, coeffs[g].min_snr, reduction); + pe += calc_pe_3gpp(band); + band->norm_fac = band->active_lines / band->thr; + norm_fac += band->norm_fac; + } + } + delta_pe = desired_pe - pe; + if (fabs(delta_pe) > 0.05f * desired_pe) + break; + } + + if (pe < 1.15f * desired_pe) { + /* 6.6.1.3.6 "Final threshold modification by linearization" */ + norm_fac = 1.0f / norm_fac; + for (w = 0; w < wi->num_windows*16; w += 16) { + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &pch->band[w+g]; + + if (band->active_lines > 0.5f) { + float delta_sfb_pe = band->norm_fac * norm_fac * delta_pe; + float thr = band->thr; + + thr *= exp2f(delta_sfb_pe / band->active_lines); + if (thr > coeffs[g].min_snr * band->energy && band->avoid_holes == PSY_3GPP_AH_INACTIVE) + thr = FFMAX(band->thr, coeffs[g].min_snr * band->energy); + band->thr = thr; + } + } + } + } else { + /* 5.6.1.3.7 "Further perceptual entropy reduction" */ + g = num_bands; + while (pe > desired_pe && g--) { + for (w = 0; w < wi->num_windows*16; w+= 16) { + AacPsyBand *band = &pch->band[w+g]; + if (band->avoid_holes != PSY_3GPP_AH_NONE && coeffs[g].min_snr < PSY_SNR_1DB) { + coeffs[g].min_snr = PSY_SNR_1DB; + band->thr = band->energy * PSY_SNR_1DB; + pe += band->active_lines * 1.5f - band->pe; + } + } + } + /* TODO: allow more holes (unused without mid/side) */ + } + } + + for (w = 0; w < wi->num_windows*16; w += 16) { + for (g = 0; g < num_bands; g++) { + AacPsyBand *band = &pch->band[w+g]; + FFPsyBand *psy_band = &ctx->ch[channel].psy_bands[w+g]; + + psy_band->threshold = band->thr; + psy_band->energy = band->energy; + } + } + + memcpy(pch->prev_band, pch->band, sizeof(pch->band)); +} + +static void psy_3gpp_analyze(FFPsyContext *ctx, int channel, + const float **coeffs, const FFPsyWindowInfo *wi) +{ + int ch; + FFPsyChannelGroup *group = ff_psy_find_group(ctx, channel); + + for (ch = 0; ch < group->num_ch; ch++) + psy_3gpp_analyze_channel(ctx, channel + ch, coeffs[ch], &wi[ch]); +} + +static av_cold void psy_3gpp_end(FFPsyContext *apc) +{ + AacPsyContext *pctx = (AacPsyContext*) apc->model_priv_data; + av_freep(&pctx->ch); + av_freep(&apc->model_priv_data); +} + +static void lame_apply_block_type(AacPsyChannel *ctx, FFPsyWindowInfo *wi, int uselongblock) +{ + int blocktype = ONLY_LONG_SEQUENCE; + if (uselongblock) { + if (ctx->next_window_seq == EIGHT_SHORT_SEQUENCE) + blocktype = LONG_STOP_SEQUENCE; + } else { + blocktype = EIGHT_SHORT_SEQUENCE; + if (ctx->next_window_seq == ONLY_LONG_SEQUENCE) + ctx->next_window_seq = LONG_START_SEQUENCE; + if (ctx->next_window_seq == LONG_STOP_SEQUENCE) + ctx->next_window_seq = EIGHT_SHORT_SEQUENCE; + } + + wi->window_type[0] = ctx->next_window_seq; + ctx->next_window_seq = blocktype; +} + +static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio, + const float *la, int channel, int prev_type) +{ + AacPsyContext *pctx = (AacPsyContext*) ctx->model_priv_data; + AacPsyChannel *pch = &pctx->ch[channel]; + int grouping = 0; + int uselongblock = 1; + int attacks[AAC_NUM_BLOCKS_SHORT + 1] = { 0 }; + int i; + FFPsyWindowInfo wi = { { 0 } }; + + if (la) { + float hpfsmpl[AAC_BLOCK_SIZE_LONG]; + float const *pf = hpfsmpl; + float attack_intensity[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS]; + float energy_subshort[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS]; + float energy_short[AAC_NUM_BLOCKS_SHORT + 1] = { 0 }; + const float *firbuf = la + (AAC_BLOCK_SIZE_SHORT/4 - PSY_LAME_FIR_LEN); + int j, att_sum = 0; + + /* LAME comment: apply high pass filter of fs/4 */ + for (i = 0; i < AAC_BLOCK_SIZE_LONG; i++) { + float sum1, sum2; + sum1 = firbuf[i + (PSY_LAME_FIR_LEN - 1) / 2]; + sum2 = 0.0; + for (j = 0; j < ((PSY_LAME_FIR_LEN - 1) / 2) - 1; j += 2) { + sum1 += psy_fir_coeffs[j] * (firbuf[i + j] + firbuf[i + PSY_LAME_FIR_LEN - j]); + sum2 += psy_fir_coeffs[j + 1] * (firbuf[i + j + 1] + firbuf[i + PSY_LAME_FIR_LEN - j - 1]); + } + /* NOTE: The LAME psymodel expects it's input in the range -32768 to 32768. Tuning this for normalized floats would be difficult. */ + hpfsmpl[i] = (sum1 + sum2) * 32768.0f; + } + + /* Calculate the energies of each sub-shortblock */ + for (i = 0; i < PSY_LAME_NUM_SUBBLOCKS; i++) { + energy_subshort[i] = pch->prev_energy_subshort[i + ((AAC_NUM_BLOCKS_SHORT - 1) * PSY_LAME_NUM_SUBBLOCKS)]; + assert(pch->prev_energy_subshort[i + ((AAC_NUM_BLOCKS_SHORT - 2) * PSY_LAME_NUM_SUBBLOCKS + 1)] > 0); + attack_intensity[i] = energy_subshort[i] / pch->prev_energy_subshort[i + ((AAC_NUM_BLOCKS_SHORT - 2) * PSY_LAME_NUM_SUBBLOCKS + 1)]; + energy_short[0] += energy_subshort[i]; + } + + for (i = 0; i < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; i++) { + float const *const pfe = pf + AAC_BLOCK_SIZE_LONG / (AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS); + float p = 1.0f; + for (; pf < pfe; pf++) + p = FFMAX(p, fabsf(*pf)); + pch->prev_energy_subshort[i] = energy_subshort[i + PSY_LAME_NUM_SUBBLOCKS] = p; + energy_short[1 + i / PSY_LAME_NUM_SUBBLOCKS] += p; + /* NOTE: The indexes below are [i + 3 - 2] in the LAME source. + * Obviously the 3 and 2 have some significance, or this would be just [i + 1] + * (which is what we use here). What the 3 stands for is ambiguous, as it is both + * number of short blocks, and the number of sub-short blocks. + * It seems that LAME is comparing each sub-block to sub-block + 1 in the + * previous block. + */ + if (p > energy_subshort[i + 1]) + p = p / energy_subshort[i + 1]; + else if (energy_subshort[i + 1] > p * 10.0f) + p = energy_subshort[i + 1] / (p * 10.0f); + else + p = 0.0; + attack_intensity[i + PSY_LAME_NUM_SUBBLOCKS] = p; + } + + /* compare energy between sub-short blocks */ + for (i = 0; i < (AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS; i++) + if (!attacks[i / PSY_LAME_NUM_SUBBLOCKS]) + if (attack_intensity[i] > pch->attack_threshold) + attacks[i / PSY_LAME_NUM_SUBBLOCKS] = (i % PSY_LAME_NUM_SUBBLOCKS) + 1; + + /* should have energy change between short blocks, in order to avoid periodic signals */ + /* Good samples to show the effect are Trumpet test songs */ + /* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */ + /* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */ + for (i = 1; i < AAC_NUM_BLOCKS_SHORT + 1; i++) { + float const u = energy_short[i - 1]; + float const v = energy_short[i]; + float const m = FFMAX(u, v); + if (m < 40000) { /* (2) */ + if (u < 1.7f * v && v < 1.7f * u) { /* (1) */ + if (i == 1 && attacks[0] < attacks[i]) + attacks[0] = 0; + attacks[i] = 0; + } + } + att_sum += attacks[i]; + } + + if (attacks[0] <= pch->prev_attack) + attacks[0] = 0; + + att_sum += attacks[0]; + /* 3 below indicates the previous attack happened in the last sub-block of the previous sequence */ + if (pch->prev_attack == 3 || att_sum) { + uselongblock = 0; + + for (i = 1; i < AAC_NUM_BLOCKS_SHORT + 1; i++) + if (attacks[i] && attacks[i-1]) + attacks[i] = 0; + } + } else { + /* We have no lookahead info, so just use same type as the previous sequence. */ + uselongblock = !(prev_type == EIGHT_SHORT_SEQUENCE); + } + + lame_apply_block_type(pch, &wi, uselongblock); + + wi.window_type[1] = prev_type; + if (wi.window_type[0] != EIGHT_SHORT_SEQUENCE) { + wi.num_windows = 1; + wi.grouping[0] = 1; + if (wi.window_type[0] == LONG_START_SEQUENCE) + wi.window_shape = 0; + else + wi.window_shape = 1; + } else { + int lastgrp = 0; + + wi.num_windows = 8; + wi.window_shape = 0; + for (i = 0; i < 8; i++) { + if (!((pch->next_grouping >> i) & 1)) + lastgrp = i; + wi.grouping[lastgrp]++; + } + } + + /* Determine grouping, based on the location of the first attack, and save for + * the next frame. + * FIXME: Move this to analysis. + * TODO: Tune groupings depending on attack location + * TODO: Handle more than one attack in a group + */ + for (i = 0; i < 9; i++) { + if (attacks[i]) { + grouping = i; + break; + } + } + pch->next_grouping = window_grouping[grouping]; + + pch->prev_attack = attacks[8]; + + return wi; +} + +const FFPsyModel ff_aac_psy_model = +{ + .name = "3GPP TS 26.403-inspired model", + .init = psy_3gpp_init, + .window = psy_lame_window, + .analyze = psy_3gpp_analyze, + .end = psy_3gpp_end, +}; diff --git a/ffmpeg/libavcodec/aacpsy.h b/ffmpeg/libavcodec/aacpsy.h new file mode 100644 index 0000000..05c93cd --- /dev/null +++ b/ffmpeg/libavcodec/aacpsy.h @@ -0,0 +1,50 @@ +/* + * AAC encoder psychoacoustic model + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_AACPSY_H +#define AVCODEC_AACPSY_H + +#include "avcodec.h" +#include "aac.h" +//#include "lowpass.h" + +enum AACPsyModelType{ + AAC_PSY_TEST, ///< a sample model to exercise encoder + AAC_PSY_3GPP, ///< model following recommendations from 3GPP TS 26.403 + + AAC_NB_PSY_MODELS ///< total number of psychoacoustic models, since it's not a part of the ABI new models can be added freely +}; + +/** + * context used by psychoacoustic model + */ +typedef struct AACPsyContext { + AVCodecContext *avctx; ///< encoder context +}AACPsyContext; + +/** + * Cleanup model context at the end. + * + * @param ctx model context + */ +void ff_aac_psy_end(AACPsyContext *ctx); + +#endif /* AVCODEC_AACPSY_H */ diff --git a/ffmpeg/libavcodec/aacsbr.c b/ffmpeg/libavcodec/aacsbr.c new file mode 100644 index 0000000..0b6779c --- /dev/null +++ b/ffmpeg/libavcodec/aacsbr.c @@ -0,0 +1,1762 @@ +/* + * AAC Spectral Band Replication decoding functions + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * Copyright (c) 2009-2010 Alex Converse + * + * 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 + */ + +/** + * @file + * AAC Spectral Band Replication decoding functions + * @author Robert Swain ( rob opendot cl ) + */ + +#include "aac.h" +#include "sbr.h" +#include "aacsbr.h" +#include "aacsbrdata.h" +#include "fft.h" +#include "aacps.h" +#include "sbrdsp.h" +#include "libavutil/internal.h" +#include "libavutil/libm.h" +#include "libavutil/avassert.h" + +#include +#include +#include + +#define ENVELOPE_ADJUSTMENT_OFFSET 2 +#define NOISE_FLOOR_OFFSET 6.0f + +#if ARCH_MIPS +#include "mips/aacsbr_mips.h" +#endif /* ARCH_MIPS */ + +/** + * SBR VLC tables + */ +enum { + T_HUFFMAN_ENV_1_5DB, + F_HUFFMAN_ENV_1_5DB, + T_HUFFMAN_ENV_BAL_1_5DB, + F_HUFFMAN_ENV_BAL_1_5DB, + T_HUFFMAN_ENV_3_0DB, + F_HUFFMAN_ENV_3_0DB, + T_HUFFMAN_ENV_BAL_3_0DB, + F_HUFFMAN_ENV_BAL_3_0DB, + T_HUFFMAN_NOISE_3_0DB, + T_HUFFMAN_NOISE_BAL_3_0DB, +}; + +/** + * bs_frame_class - frame class of current SBR frame (14496-3 sp04 p98) + */ +enum { + FIXFIX, + FIXVAR, + VARFIX, + VARVAR, +}; + +enum { + EXTENSION_ID_PS = 2, +}; + +static VLC vlc_sbr[10]; +static const int8_t vlc_sbr_lav[10] = + { 60, 60, 24, 24, 31, 31, 12, 12, 31, 12 }; + +#define SBR_INIT_VLC_STATIC(num, size) \ + INIT_VLC_STATIC(&vlc_sbr[num], 9, sbr_tmp[num].table_size / sbr_tmp[num].elem_size, \ + sbr_tmp[num].sbr_bits , 1, 1, \ + sbr_tmp[num].sbr_codes, sbr_tmp[num].elem_size, sbr_tmp[num].elem_size, \ + size) + +#define SBR_VLC_ROW(name) \ + { name ## _codes, name ## _bits, sizeof(name ## _codes), sizeof(name ## _codes[0]) } + +static void aacsbr_func_ptr_init(AACSBRContext *c); + +av_cold void ff_aac_sbr_init(void) +{ + int n; + static const struct { + const void *sbr_codes, *sbr_bits; + const unsigned int table_size, elem_size; + } sbr_tmp[] = { + SBR_VLC_ROW(t_huffman_env_1_5dB), + SBR_VLC_ROW(f_huffman_env_1_5dB), + SBR_VLC_ROW(t_huffman_env_bal_1_5dB), + SBR_VLC_ROW(f_huffman_env_bal_1_5dB), + SBR_VLC_ROW(t_huffman_env_3_0dB), + SBR_VLC_ROW(f_huffman_env_3_0dB), + SBR_VLC_ROW(t_huffman_env_bal_3_0dB), + SBR_VLC_ROW(f_huffman_env_bal_3_0dB), + SBR_VLC_ROW(t_huffman_noise_3_0dB), + SBR_VLC_ROW(t_huffman_noise_bal_3_0dB), + }; + + // SBR VLC table initialization + SBR_INIT_VLC_STATIC(0, 1098); + SBR_INIT_VLC_STATIC(1, 1092); + SBR_INIT_VLC_STATIC(2, 768); + SBR_INIT_VLC_STATIC(3, 1026); + SBR_INIT_VLC_STATIC(4, 1058); + SBR_INIT_VLC_STATIC(5, 1052); + SBR_INIT_VLC_STATIC(6, 544); + SBR_INIT_VLC_STATIC(7, 544); + SBR_INIT_VLC_STATIC(8, 592); + SBR_INIT_VLC_STATIC(9, 512); + + for (n = 1; n < 320; n++) + sbr_qmf_window_us[320 + n] = sbr_qmf_window_us[320 - n]; + sbr_qmf_window_us[384] = -sbr_qmf_window_us[384]; + sbr_qmf_window_us[512] = -sbr_qmf_window_us[512]; + + for (n = 0; n < 320; n++) + sbr_qmf_window_ds[n] = sbr_qmf_window_us[2*n]; + + ff_ps_init(); +} + +/** Places SBR in pure upsampling mode. */ +static void sbr_turnoff(SpectralBandReplication *sbr) { + sbr->start = 0; + // Init defults used in pure upsampling mode + sbr->kx[1] = 32; //Typo in spec, kx' inits to 32 + sbr->m[1] = 0; + // Reset values for first SBR header + sbr->data[0].e_a[1] = sbr->data[1].e_a[1] = -1; + memset(&sbr->spectrum_params, -1, sizeof(SpectrumParameters)); +} + +av_cold void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr) +{ + if(sbr->mdct.mdct_bits) + return; + sbr->kx[0] = sbr->kx[1]; + sbr_turnoff(sbr); + sbr->data[0].synthesis_filterbank_samples_offset = SBR_SYNTHESIS_BUF_SIZE - (1280 - 128); + sbr->data[1].synthesis_filterbank_samples_offset = SBR_SYNTHESIS_BUF_SIZE - (1280 - 128); + /* SBR requires samples to be scaled to +/-32768.0 to work correctly. + * mdct scale factors are adjusted to scale up from +/-1.0 at analysis + * and scale back down at synthesis. */ + ff_mdct_init(&sbr->mdct, 7, 1, 1.0 / (64 * 32768.0)); + ff_mdct_init(&sbr->mdct_ana, 7, 1, -2.0 * 32768.0); + ff_ps_ctx_init(&sbr->ps); + ff_sbrdsp_init(&sbr->dsp); + aacsbr_func_ptr_init(&sbr->c); +} + +av_cold void ff_aac_sbr_ctx_close(SpectralBandReplication *sbr) +{ + ff_mdct_end(&sbr->mdct); + ff_mdct_end(&sbr->mdct_ana); +} + +static int qsort_comparison_function_int16(const void *a, const void *b) +{ + return *(const int16_t *)a - *(const int16_t *)b; +} + +static inline int in_table_int16(const int16_t *table, int last_el, int16_t needle) +{ + int i; + for (i = 0; i <= last_el; i++) + if (table[i] == needle) + return 1; + return 0; +} + +/// Limiter Frequency Band Table (14496-3 sp04 p198) +static void sbr_make_f_tablelim(SpectralBandReplication *sbr) +{ + int k; + if (sbr->bs_limiter_bands > 0) { + static const float bands_warped[3] = { 1.32715174233856803909f, //2^(0.49/1.2) + 1.18509277094158210129f, //2^(0.49/2) + 1.11987160404675912501f }; //2^(0.49/3) + const float lim_bands_per_octave_warped = bands_warped[sbr->bs_limiter_bands - 1]; + int16_t patch_borders[7]; + uint16_t *in = sbr->f_tablelim + 1, *out = sbr->f_tablelim; + + patch_borders[0] = sbr->kx[1]; + for (k = 1; k <= sbr->num_patches; k++) + patch_borders[k] = patch_borders[k-1] + sbr->patch_num_subbands[k-1]; + + memcpy(sbr->f_tablelim, sbr->f_tablelow, + (sbr->n[0] + 1) * sizeof(sbr->f_tablelow[0])); + if (sbr->num_patches > 1) + memcpy(sbr->f_tablelim + sbr->n[0] + 1, patch_borders + 1, + (sbr->num_patches - 1) * sizeof(patch_borders[0])); + + qsort(sbr->f_tablelim, sbr->num_patches + sbr->n[0], + sizeof(sbr->f_tablelim[0]), + qsort_comparison_function_int16); + + sbr->n_lim = sbr->n[0] + sbr->num_patches - 1; + while (out < sbr->f_tablelim + sbr->n_lim) { + if (*in >= *out * lim_bands_per_octave_warped) { + *++out = *in++; + } else if (*in == *out || + !in_table_int16(patch_borders, sbr->num_patches, *in)) { + in++; + sbr->n_lim--; + } else if (!in_table_int16(patch_borders, sbr->num_patches, *out)) { + *out = *in++; + sbr->n_lim--; + } else { + *++out = *in++; + } + } + } else { + sbr->f_tablelim[0] = sbr->f_tablelow[0]; + sbr->f_tablelim[1] = sbr->f_tablelow[sbr->n[0]]; + sbr->n_lim = 1; + } +} + +static unsigned int read_sbr_header(SpectralBandReplication *sbr, GetBitContext *gb) +{ + unsigned int cnt = get_bits_count(gb); + uint8_t bs_header_extra_1; + uint8_t bs_header_extra_2; + int old_bs_limiter_bands = sbr->bs_limiter_bands; + SpectrumParameters old_spectrum_params; + + sbr->start = 1; + + // Save last spectrum parameters variables to compare to new ones + memcpy(&old_spectrum_params, &sbr->spectrum_params, sizeof(SpectrumParameters)); + + sbr->bs_amp_res_header = get_bits1(gb); + sbr->spectrum_params.bs_start_freq = get_bits(gb, 4); + sbr->spectrum_params.bs_stop_freq = get_bits(gb, 4); + sbr->spectrum_params.bs_xover_band = get_bits(gb, 3); + skip_bits(gb, 2); // bs_reserved + + bs_header_extra_1 = get_bits1(gb); + bs_header_extra_2 = get_bits1(gb); + + if (bs_header_extra_1) { + sbr->spectrum_params.bs_freq_scale = get_bits(gb, 2); + sbr->spectrum_params.bs_alter_scale = get_bits1(gb); + sbr->spectrum_params.bs_noise_bands = get_bits(gb, 2); + } else { + sbr->spectrum_params.bs_freq_scale = 2; + sbr->spectrum_params.bs_alter_scale = 1; + sbr->spectrum_params.bs_noise_bands = 2; + } + + // Check if spectrum parameters changed + if (memcmp(&old_spectrum_params, &sbr->spectrum_params, sizeof(SpectrumParameters))) + sbr->reset = 1; + + if (bs_header_extra_2) { + sbr->bs_limiter_bands = get_bits(gb, 2); + sbr->bs_limiter_gains = get_bits(gb, 2); + sbr->bs_interpol_freq = get_bits1(gb); + sbr->bs_smoothing_mode = get_bits1(gb); + } else { + sbr->bs_limiter_bands = 2; + sbr->bs_limiter_gains = 2; + sbr->bs_interpol_freq = 1; + sbr->bs_smoothing_mode = 1; + } + + if (sbr->bs_limiter_bands != old_bs_limiter_bands && !sbr->reset) + sbr_make_f_tablelim(sbr); + + return get_bits_count(gb) - cnt; +} + +static int array_min_int16(const int16_t *array, int nel) +{ + int i, min = array[0]; + for (i = 1; i < nel; i++) + min = FFMIN(array[i], min); + return min; +} + +static void make_bands(int16_t* bands, int start, int stop, int num_bands) +{ + int k, previous, present; + float base, prod; + + base = powf((float)stop / start, 1.0f / num_bands); + prod = start; + previous = start; + + for (k = 0; k < num_bands-1; k++) { + prod *= base; + present = lrintf(prod); + bands[k] = present - previous; + previous = present; + } + bands[num_bands-1] = stop - previous; +} + +static int check_n_master(AVCodecContext *avctx, int n_master, int bs_xover_band) +{ + // Requirements (14496-3 sp04 p205) + if (n_master <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid n_master: %d\n", n_master); + return -1; + } + if (bs_xover_band >= n_master) { + av_log(avctx, AV_LOG_ERROR, + "Invalid bitstream, crossover band index beyond array bounds: %d\n", + bs_xover_band); + return -1; + } + return 0; +} + +/// Master Frequency Band Table (14496-3 sp04 p194) +static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr, + SpectrumParameters *spectrum) +{ + unsigned int temp, max_qmf_subbands; + unsigned int start_min, stop_min; + int k; + const int8_t *sbr_offset_ptr; + int16_t stop_dk[13]; + + if (sbr->sample_rate < 32000) { + temp = 3000; + } else if (sbr->sample_rate < 64000) { + temp = 4000; + } else + temp = 5000; + + switch (sbr->sample_rate) { + case 16000: + sbr_offset_ptr = sbr_offset[0]; + break; + case 22050: + sbr_offset_ptr = sbr_offset[1]; + break; + case 24000: + sbr_offset_ptr = sbr_offset[2]; + break; + case 32000: + sbr_offset_ptr = sbr_offset[3]; + break; + case 44100: case 48000: case 64000: + sbr_offset_ptr = sbr_offset[4]; + break; + case 88200: case 96000: case 128000: case 176400: case 192000: + sbr_offset_ptr = sbr_offset[5]; + break; + default: + av_log(ac->avctx, AV_LOG_ERROR, + "Unsupported sample rate for SBR: %d\n", sbr->sample_rate); + return -1; + } + + start_min = ((temp << 7) + (sbr->sample_rate >> 1)) / sbr->sample_rate; + stop_min = ((temp << 8) + (sbr->sample_rate >> 1)) / sbr->sample_rate; + + sbr->k[0] = start_min + sbr_offset_ptr[spectrum->bs_start_freq]; + + if (spectrum->bs_stop_freq < 14) { + sbr->k[2] = stop_min; + make_bands(stop_dk, stop_min, 64, 13); + qsort(stop_dk, 13, sizeof(stop_dk[0]), qsort_comparison_function_int16); + for (k = 0; k < spectrum->bs_stop_freq; k++) + sbr->k[2] += stop_dk[k]; + } else if (spectrum->bs_stop_freq == 14) { + sbr->k[2] = 2*sbr->k[0]; + } else if (spectrum->bs_stop_freq == 15) { + sbr->k[2] = 3*sbr->k[0]; + } else { + av_log(ac->avctx, AV_LOG_ERROR, + "Invalid bs_stop_freq: %d\n", spectrum->bs_stop_freq); + return -1; + } + sbr->k[2] = FFMIN(64, sbr->k[2]); + + // Requirements (14496-3 sp04 p205) + if (sbr->sample_rate <= 32000) { + max_qmf_subbands = 48; + } else if (sbr->sample_rate == 44100) { + max_qmf_subbands = 35; + } else if (sbr->sample_rate >= 48000) + max_qmf_subbands = 32; + else + av_assert0(0); + + if (sbr->k[2] - sbr->k[0] > max_qmf_subbands) { + av_log(ac->avctx, AV_LOG_ERROR, + "Invalid bitstream, too many QMF subbands: %d\n", sbr->k[2] - sbr->k[0]); + return -1; + } + + if (!spectrum->bs_freq_scale) { + int dk, k2diff; + + dk = spectrum->bs_alter_scale + 1; + sbr->n_master = ((sbr->k[2] - sbr->k[0] + (dk&2)) >> dk) << 1; + if (check_n_master(ac->avctx, sbr->n_master, sbr->spectrum_params.bs_xover_band)) + return -1; + + for (k = 1; k <= sbr->n_master; k++) + sbr->f_master[k] = dk; + + k2diff = sbr->k[2] - sbr->k[0] - sbr->n_master * dk; + if (k2diff < 0) { + sbr->f_master[1]--; + sbr->f_master[2]-= (k2diff < -1); + } else if (k2diff) { + sbr->f_master[sbr->n_master]++; + } + + sbr->f_master[0] = sbr->k[0]; + for (k = 1; k <= sbr->n_master; k++) + sbr->f_master[k] += sbr->f_master[k - 1]; + + } else { + int half_bands = 7 - spectrum->bs_freq_scale; // bs_freq_scale = {1,2,3} + int two_regions, num_bands_0; + int vdk0_max, vdk1_min; + int16_t vk0[49]; + + if (49 * sbr->k[2] > 110 * sbr->k[0]) { + two_regions = 1; + sbr->k[1] = 2 * sbr->k[0]; + } else { + two_regions = 0; + sbr->k[1] = sbr->k[2]; + } + + num_bands_0 = lrintf(half_bands * log2f(sbr->k[1] / (float)sbr->k[0])) * 2; + + if (num_bands_0 <= 0) { // Requirements (14496-3 sp04 p205) + av_log(ac->avctx, AV_LOG_ERROR, "Invalid num_bands_0: %d\n", num_bands_0); + return -1; + } + + vk0[0] = 0; + + make_bands(vk0+1, sbr->k[0], sbr->k[1], num_bands_0); + + qsort(vk0 + 1, num_bands_0, sizeof(vk0[1]), qsort_comparison_function_int16); + vdk0_max = vk0[num_bands_0]; + + vk0[0] = sbr->k[0]; + for (k = 1; k <= num_bands_0; k++) { + if (vk0[k] <= 0) { // Requirements (14496-3 sp04 p205) + av_log(ac->avctx, AV_LOG_ERROR, "Invalid vDk0[%d]: %d\n", k, vk0[k]); + return -1; + } + vk0[k] += vk0[k-1]; + } + + if (two_regions) { + int16_t vk1[49]; + float invwarp = spectrum->bs_alter_scale ? 0.76923076923076923077f + : 1.0f; // bs_alter_scale = {0,1} + int num_bands_1 = lrintf(half_bands * invwarp * + log2f(sbr->k[2] / (float)sbr->k[1])) * 2; + + make_bands(vk1+1, sbr->k[1], sbr->k[2], num_bands_1); + + vdk1_min = array_min_int16(vk1 + 1, num_bands_1); + + if (vdk1_min < vdk0_max) { + int change; + qsort(vk1 + 1, num_bands_1, sizeof(vk1[1]), qsort_comparison_function_int16); + change = FFMIN(vdk0_max - vk1[1], (vk1[num_bands_1] - vk1[1]) >> 1); + vk1[1] += change; + vk1[num_bands_1] -= change; + } + + qsort(vk1 + 1, num_bands_1, sizeof(vk1[1]), qsort_comparison_function_int16); + + vk1[0] = sbr->k[1]; + for (k = 1; k <= num_bands_1; k++) { + if (vk1[k] <= 0) { // Requirements (14496-3 sp04 p205) + av_log(ac->avctx, AV_LOG_ERROR, "Invalid vDk1[%d]: %d\n", k, vk1[k]); + return -1; + } + vk1[k] += vk1[k-1]; + } + + sbr->n_master = num_bands_0 + num_bands_1; + if (check_n_master(ac->avctx, sbr->n_master, sbr->spectrum_params.bs_xover_band)) + return -1; + memcpy(&sbr->f_master[0], vk0, + (num_bands_0 + 1) * sizeof(sbr->f_master[0])); + memcpy(&sbr->f_master[num_bands_0 + 1], vk1 + 1, + num_bands_1 * sizeof(sbr->f_master[0])); + + } else { + sbr->n_master = num_bands_0; + if (check_n_master(ac->avctx, sbr->n_master, sbr->spectrum_params.bs_xover_band)) + return -1; + memcpy(sbr->f_master, vk0, (num_bands_0 + 1) * sizeof(sbr->f_master[0])); + } + } + + return 0; +} + +/// High Frequency Generation - Patch Construction (14496-3 sp04 p216 fig. 4.46) +static int sbr_hf_calc_npatches(AACContext *ac, SpectralBandReplication *sbr) +{ + int i, k, sb = 0; + int msb = sbr->k[0]; + int usb = sbr->kx[1]; + int goal_sb = ((1000 << 11) + (sbr->sample_rate >> 1)) / sbr->sample_rate; + + sbr->num_patches = 0; + + if (goal_sb < sbr->kx[1] + sbr->m[1]) { + for (k = 0; sbr->f_master[k] < goal_sb; k++) ; + } else + k = sbr->n_master; + + do { + int odd = 0; + for (i = k; i == k || sb > (sbr->k[0] - 1 + msb - odd); i--) { + sb = sbr->f_master[i]; + odd = (sb + sbr->k[0]) & 1; + } + + // Requirements (14496-3 sp04 p205) sets the maximum number of patches to 5. + // After this check the final number of patches can still be six which is + // illegal however the Coding Technologies decoder check stream has a final + // count of 6 patches + if (sbr->num_patches > 5) { + av_log(ac->avctx, AV_LOG_ERROR, "Too many patches: %d\n", sbr->num_patches); + return -1; + } + + sbr->patch_num_subbands[sbr->num_patches] = FFMAX(sb - usb, 0); + sbr->patch_start_subband[sbr->num_patches] = sbr->k[0] - odd - sbr->patch_num_subbands[sbr->num_patches]; + + if (sbr->patch_num_subbands[sbr->num_patches] > 0) { + usb = sb; + msb = sb; + sbr->num_patches++; + } else + msb = sbr->kx[1]; + + if (sbr->f_master[k] - sb < 3) + k = sbr->n_master; + } while (sb != sbr->kx[1] + sbr->m[1]); + + if (sbr->num_patches > 1 && sbr->patch_num_subbands[sbr->num_patches-1] < 3) + sbr->num_patches--; + + return 0; +} + +/// Derived Frequency Band Tables (14496-3 sp04 p197) +static int sbr_make_f_derived(AACContext *ac, SpectralBandReplication *sbr) +{ + int k, temp; + + sbr->n[1] = sbr->n_master - sbr->spectrum_params.bs_xover_band; + sbr->n[0] = (sbr->n[1] + 1) >> 1; + + memcpy(sbr->f_tablehigh, &sbr->f_master[sbr->spectrum_params.bs_xover_band], + (sbr->n[1] + 1) * sizeof(sbr->f_master[0])); + sbr->m[1] = sbr->f_tablehigh[sbr->n[1]] - sbr->f_tablehigh[0]; + sbr->kx[1] = sbr->f_tablehigh[0]; + + // Requirements (14496-3 sp04 p205) + if (sbr->kx[1] + sbr->m[1] > 64) { + av_log(ac->avctx, AV_LOG_ERROR, + "Stop frequency border too high: %d\n", sbr->kx[1] + sbr->m[1]); + return -1; + } + if (sbr->kx[1] > 32) { + av_log(ac->avctx, AV_LOG_ERROR, "Start frequency border too high: %d\n", sbr->kx[1]); + return -1; + } + + sbr->f_tablelow[0] = sbr->f_tablehigh[0]; + temp = sbr->n[1] & 1; + for (k = 1; k <= sbr->n[0]; k++) + sbr->f_tablelow[k] = sbr->f_tablehigh[2 * k - temp]; + + sbr->n_q = FFMAX(1, lrintf(sbr->spectrum_params.bs_noise_bands * + log2f(sbr->k[2] / (float)sbr->kx[1]))); // 0 <= bs_noise_bands <= 3 + if (sbr->n_q > 5) { + av_log(ac->avctx, AV_LOG_ERROR, "Too many noise floor scale factors: %d\n", sbr->n_q); + return -1; + } + + sbr->f_tablenoise[0] = sbr->f_tablelow[0]; + temp = 0; + for (k = 1; k <= sbr->n_q; k++) { + temp += (sbr->n[0] - temp) / (sbr->n_q + 1 - k); + sbr->f_tablenoise[k] = sbr->f_tablelow[temp]; + } + + if (sbr_hf_calc_npatches(ac, sbr) < 0) + return -1; + + sbr_make_f_tablelim(sbr); + + sbr->data[0].f_indexnoise = 0; + sbr->data[1].f_indexnoise = 0; + + return 0; +} + +static av_always_inline void get_bits1_vector(GetBitContext *gb, uint8_t *vec, + int elements) +{ + int i; + for (i = 0; i < elements; i++) { + vec[i] = get_bits1(gb); + } +} + +/** ceil(log2(index+1)) */ +static const int8_t ceil_log2[] = { + 0, 1, 2, 2, 3, 3, +}; + +static int read_sbr_grid(AACContext *ac, SpectralBandReplication *sbr, + GetBitContext *gb, SBRData *ch_data) +{ + int i; + unsigned bs_pointer = 0; + // frameLengthFlag ? 15 : 16; 960 sample length frames unsupported; this value is numTimeSlots + int abs_bord_trail = 16; + int num_rel_lead, num_rel_trail; + unsigned bs_num_env_old = ch_data->bs_num_env; + + ch_data->bs_freq_res[0] = ch_data->bs_freq_res[ch_data->bs_num_env]; + ch_data->bs_amp_res = sbr->bs_amp_res_header; + ch_data->t_env_num_env_old = ch_data->t_env[bs_num_env_old]; + + switch (ch_data->bs_frame_class = get_bits(gb, 2)) { + case FIXFIX: + ch_data->bs_num_env = 1 << get_bits(gb, 2); + num_rel_lead = ch_data->bs_num_env - 1; + if (ch_data->bs_num_env == 1) + ch_data->bs_amp_res = 0; + + if (ch_data->bs_num_env > 4) { + av_log(ac->avctx, AV_LOG_ERROR, + "Invalid bitstream, too many SBR envelopes in FIXFIX type SBR frame: %d\n", + ch_data->bs_num_env); + return -1; + } + + ch_data->t_env[0] = 0; + ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail; + + abs_bord_trail = (abs_bord_trail + (ch_data->bs_num_env >> 1)) / + ch_data->bs_num_env; + for (i = 0; i < num_rel_lead; i++) + ch_data->t_env[i + 1] = ch_data->t_env[i] + abs_bord_trail; + + ch_data->bs_freq_res[1] = get_bits1(gb); + for (i = 1; i < ch_data->bs_num_env; i++) + ch_data->bs_freq_res[i + 1] = ch_data->bs_freq_res[1]; + break; + case FIXVAR: + abs_bord_trail += get_bits(gb, 2); + num_rel_trail = get_bits(gb, 2); + ch_data->bs_num_env = num_rel_trail + 1; + ch_data->t_env[0] = 0; + ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail; + + for (i = 0; i < num_rel_trail; i++) + ch_data->t_env[ch_data->bs_num_env - 1 - i] = + ch_data->t_env[ch_data->bs_num_env - i] - 2 * get_bits(gb, 2) - 2; + + bs_pointer = get_bits(gb, ceil_log2[ch_data->bs_num_env]); + + for (i = 0; i < ch_data->bs_num_env; i++) + ch_data->bs_freq_res[ch_data->bs_num_env - i] = get_bits1(gb); + break; + case VARFIX: + ch_data->t_env[0] = get_bits(gb, 2); + num_rel_lead = get_bits(gb, 2); + ch_data->bs_num_env = num_rel_lead + 1; + ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail; + + for (i = 0; i < num_rel_lead; i++) + ch_data->t_env[i + 1] = ch_data->t_env[i] + 2 * get_bits(gb, 2) + 2; + + bs_pointer = get_bits(gb, ceil_log2[ch_data->bs_num_env]); + + get_bits1_vector(gb, ch_data->bs_freq_res + 1, ch_data->bs_num_env); + break; + case VARVAR: + ch_data->t_env[0] = get_bits(gb, 2); + abs_bord_trail += get_bits(gb, 2); + num_rel_lead = get_bits(gb, 2); + num_rel_trail = get_bits(gb, 2); + ch_data->bs_num_env = num_rel_lead + num_rel_trail + 1; + + if (ch_data->bs_num_env > 5) { + av_log(ac->avctx, AV_LOG_ERROR, + "Invalid bitstream, too many SBR envelopes in VARVAR type SBR frame: %d\n", + ch_data->bs_num_env); + return -1; + } + + ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail; + + for (i = 0; i < num_rel_lead; i++) + ch_data->t_env[i + 1] = ch_data->t_env[i] + 2 * get_bits(gb, 2) + 2; + for (i = 0; i < num_rel_trail; i++) + ch_data->t_env[ch_data->bs_num_env - 1 - i] = + ch_data->t_env[ch_data->bs_num_env - i] - 2 * get_bits(gb, 2) - 2; + + bs_pointer = get_bits(gb, ceil_log2[ch_data->bs_num_env]); + + get_bits1_vector(gb, ch_data->bs_freq_res + 1, ch_data->bs_num_env); + break; + } + + if (bs_pointer > ch_data->bs_num_env + 1) { + av_log(ac->avctx, AV_LOG_ERROR, + "Invalid bitstream, bs_pointer points to a middle noise border outside the time borders table: %d\n", + bs_pointer); + return -1; + } + + for (i = 1; i <= ch_data->bs_num_env; i++) { + if (ch_data->t_env[i-1] > ch_data->t_env[i]) { + av_log(ac->avctx, AV_LOG_ERROR, "Non monotone time borders\n"); + return -1; + } + } + + ch_data->bs_num_noise = (ch_data->bs_num_env > 1) + 1; + + ch_data->t_q[0] = ch_data->t_env[0]; + ch_data->t_q[ch_data->bs_num_noise] = ch_data->t_env[ch_data->bs_num_env]; + if (ch_data->bs_num_noise > 1) { + unsigned int idx; + if (ch_data->bs_frame_class == FIXFIX) { + idx = ch_data->bs_num_env >> 1; + } else if (ch_data->bs_frame_class & 1) { // FIXVAR or VARVAR + idx = ch_data->bs_num_env - FFMAX((int)bs_pointer - 1, 1); + } else { // VARFIX + if (!bs_pointer) + idx = 1; + else if (bs_pointer == 1) + idx = ch_data->bs_num_env - 1; + else // bs_pointer > 1 + idx = bs_pointer - 1; + } + ch_data->t_q[1] = ch_data->t_env[idx]; + } + + ch_data->e_a[0] = -(ch_data->e_a[1] != bs_num_env_old); // l_APrev + ch_data->e_a[1] = -1; + if ((ch_data->bs_frame_class & 1) && bs_pointer) { // FIXVAR or VARVAR and bs_pointer != 0 + ch_data->e_a[1] = ch_data->bs_num_env + 1 - bs_pointer; + } else if ((ch_data->bs_frame_class == 2) && (bs_pointer > 1)) // VARFIX and bs_pointer > 1 + ch_data->e_a[1] = bs_pointer - 1; + + return 0; +} + +static void copy_sbr_grid(SBRData *dst, const SBRData *src) { + //These variables are saved from the previous frame rather than copied + dst->bs_freq_res[0] = dst->bs_freq_res[dst->bs_num_env]; + dst->t_env_num_env_old = dst->t_env[dst->bs_num_env]; + dst->e_a[0] = -(dst->e_a[1] != dst->bs_num_env); + + //These variables are read from the bitstream and therefore copied + memcpy(dst->bs_freq_res+1, src->bs_freq_res+1, sizeof(dst->bs_freq_res)-sizeof(*dst->bs_freq_res)); + memcpy(dst->t_env, src->t_env, sizeof(dst->t_env)); + memcpy(dst->t_q, src->t_q, sizeof(dst->t_q)); + dst->bs_num_env = src->bs_num_env; + dst->bs_amp_res = src->bs_amp_res; + dst->bs_num_noise = src->bs_num_noise; + dst->bs_frame_class = src->bs_frame_class; + dst->e_a[1] = src->e_a[1]; +} + +/// Read how the envelope and noise floor data is delta coded +static void read_sbr_dtdf(SpectralBandReplication *sbr, GetBitContext *gb, + SBRData *ch_data) +{ + get_bits1_vector(gb, ch_data->bs_df_env, ch_data->bs_num_env); + get_bits1_vector(gb, ch_data->bs_df_noise, ch_data->bs_num_noise); +} + +/// Read inverse filtering data +static void read_sbr_invf(SpectralBandReplication *sbr, GetBitContext *gb, + SBRData *ch_data) +{ + int i; + + memcpy(ch_data->bs_invf_mode[1], ch_data->bs_invf_mode[0], 5 * sizeof(uint8_t)); + for (i = 0; i < sbr->n_q; i++) + ch_data->bs_invf_mode[0][i] = get_bits(gb, 2); +} + +static void read_sbr_envelope(SpectralBandReplication *sbr, GetBitContext *gb, + SBRData *ch_data, int ch) +{ + int bits; + int i, j, k; + VLC_TYPE (*t_huff)[2], (*f_huff)[2]; + int t_lav, f_lav; + const int delta = (ch == 1 && sbr->bs_coupling == 1) + 1; + const int odd = sbr->n[1] & 1; + + if (sbr->bs_coupling && ch) { + if (ch_data->bs_amp_res) { + bits = 5; + t_huff = vlc_sbr[T_HUFFMAN_ENV_BAL_3_0DB].table; + t_lav = vlc_sbr_lav[T_HUFFMAN_ENV_BAL_3_0DB]; + f_huff = vlc_sbr[F_HUFFMAN_ENV_BAL_3_0DB].table; + f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_BAL_3_0DB]; + } else { + bits = 6; + t_huff = vlc_sbr[T_HUFFMAN_ENV_BAL_1_5DB].table; + t_lav = vlc_sbr_lav[T_HUFFMAN_ENV_BAL_1_5DB]; + f_huff = vlc_sbr[F_HUFFMAN_ENV_BAL_1_5DB].table; + f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_BAL_1_5DB]; + } + } else { + if (ch_data->bs_amp_res) { + bits = 6; + t_huff = vlc_sbr[T_HUFFMAN_ENV_3_0DB].table; + t_lav = vlc_sbr_lav[T_HUFFMAN_ENV_3_0DB]; + f_huff = vlc_sbr[F_HUFFMAN_ENV_3_0DB].table; + f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_3_0DB]; + } else { + bits = 7; + t_huff = vlc_sbr[T_HUFFMAN_ENV_1_5DB].table; + t_lav = vlc_sbr_lav[T_HUFFMAN_ENV_1_5DB]; + f_huff = vlc_sbr[F_HUFFMAN_ENV_1_5DB].table; + f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_1_5DB]; + } + } + + for (i = 0; i < ch_data->bs_num_env; i++) { + if (ch_data->bs_df_env[i]) { + // bs_freq_res[0] == bs_freq_res[bs_num_env] from prev frame + if (ch_data->bs_freq_res[i + 1] == ch_data->bs_freq_res[i]) { + for (j = 0; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) + ch_data->env_facs[i + 1][j] = ch_data->env_facs[i][j] + delta * (get_vlc2(gb, t_huff, 9, 3) - t_lav); + } else if (ch_data->bs_freq_res[i + 1]) { + for (j = 0; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) { + k = (j + odd) >> 1; // find k such that f_tablelow[k] <= f_tablehigh[j] < f_tablelow[k + 1] + ch_data->env_facs[i + 1][j] = ch_data->env_facs[i][k] + delta * (get_vlc2(gb, t_huff, 9, 3) - t_lav); + } + } else { + for (j = 0; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) { + k = j ? 2*j - odd : 0; // find k such that f_tablehigh[k] == f_tablelow[j] + ch_data->env_facs[i + 1][j] = ch_data->env_facs[i][k] + delta * (get_vlc2(gb, t_huff, 9, 3) - t_lav); + } + } + } else { + ch_data->env_facs[i + 1][0] = delta * get_bits(gb, bits); // bs_env_start_value_balance + for (j = 1; j < sbr->n[ch_data->bs_freq_res[i + 1]]; j++) + ch_data->env_facs[i + 1][j] = ch_data->env_facs[i + 1][j - 1] + delta * (get_vlc2(gb, f_huff, 9, 3) - f_lav); + } + } + + //assign 0th elements of env_facs from last elements + memcpy(ch_data->env_facs[0], ch_data->env_facs[ch_data->bs_num_env], + sizeof(ch_data->env_facs[0])); +} + +static void read_sbr_noise(SpectralBandReplication *sbr, GetBitContext *gb, + SBRData *ch_data, int ch) +{ + int i, j; + VLC_TYPE (*t_huff)[2], (*f_huff)[2]; + int t_lav, f_lav; + int delta = (ch == 1 && sbr->bs_coupling == 1) + 1; + + if (sbr->bs_coupling && ch) { + t_huff = vlc_sbr[T_HUFFMAN_NOISE_BAL_3_0DB].table; + t_lav = vlc_sbr_lav[T_HUFFMAN_NOISE_BAL_3_0DB]; + f_huff = vlc_sbr[F_HUFFMAN_ENV_BAL_3_0DB].table; + f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_BAL_3_0DB]; + } else { + t_huff = vlc_sbr[T_HUFFMAN_NOISE_3_0DB].table; + t_lav = vlc_sbr_lav[T_HUFFMAN_NOISE_3_0DB]; + f_huff = vlc_sbr[F_HUFFMAN_ENV_3_0DB].table; + f_lav = vlc_sbr_lav[F_HUFFMAN_ENV_3_0DB]; + } + + for (i = 0; i < ch_data->bs_num_noise; i++) { + if (ch_data->bs_df_noise[i]) { + for (j = 0; j < sbr->n_q; j++) + ch_data->noise_facs[i + 1][j] = ch_data->noise_facs[i][j] + delta * (get_vlc2(gb, t_huff, 9, 2) - t_lav); + } else { + ch_data->noise_facs[i + 1][0] = delta * get_bits(gb, 5); // bs_noise_start_value_balance or bs_noise_start_value_level + for (j = 1; j < sbr->n_q; j++) + ch_data->noise_facs[i + 1][j] = ch_data->noise_facs[i + 1][j - 1] + delta * (get_vlc2(gb, f_huff, 9, 3) - f_lav); + } + } + + //assign 0th elements of noise_facs from last elements + memcpy(ch_data->noise_facs[0], ch_data->noise_facs[ch_data->bs_num_noise], + sizeof(ch_data->noise_facs[0])); +} + +static void read_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, + GetBitContext *gb, + int bs_extension_id, int *num_bits_left) +{ + switch (bs_extension_id) { + case EXTENSION_ID_PS: + if (!ac->oc[1].m4ac.ps) { + av_log(ac->avctx, AV_LOG_ERROR, "Parametric Stereo signaled to be not-present but was found in the bitstream.\n"); + skip_bits_long(gb, *num_bits_left); // bs_fill_bits + *num_bits_left = 0; + } else { +#if 1 + *num_bits_left -= ff_ps_read_data(ac->avctx, gb, &sbr->ps, *num_bits_left); +#else + avpriv_report_missing_feature(ac->avctx, "Parametric Stereo"); + skip_bits_long(gb, *num_bits_left); // bs_fill_bits + *num_bits_left = 0; +#endif + } + break; + default: + // some files contain 0-padding + if (bs_extension_id || *num_bits_left > 16 || show_bits(gb, *num_bits_left)) + avpriv_request_sample(ac->avctx, "Reserved SBR extensions"); + skip_bits_long(gb, *num_bits_left); // bs_fill_bits + *num_bits_left = 0; + break; + } +} + +static int read_sbr_single_channel_element(AACContext *ac, + SpectralBandReplication *sbr, + GetBitContext *gb) +{ + if (get_bits1(gb)) // bs_data_extra + skip_bits(gb, 4); // bs_reserved + + if (read_sbr_grid(ac, sbr, gb, &sbr->data[0])) + return -1; + read_sbr_dtdf(sbr, gb, &sbr->data[0]); + read_sbr_invf(sbr, gb, &sbr->data[0]); + read_sbr_envelope(sbr, gb, &sbr->data[0], 0); + read_sbr_noise(sbr, gb, &sbr->data[0], 0); + + if ((sbr->data[0].bs_add_harmonic_flag = get_bits1(gb))) + get_bits1_vector(gb, sbr->data[0].bs_add_harmonic, sbr->n[1]); + + return 0; +} + +static int read_sbr_channel_pair_element(AACContext *ac, + SpectralBandReplication *sbr, + GetBitContext *gb) +{ + if (get_bits1(gb)) // bs_data_extra + skip_bits(gb, 8); // bs_reserved + + if ((sbr->bs_coupling = get_bits1(gb))) { + if (read_sbr_grid(ac, sbr, gb, &sbr->data[0])) + return -1; + copy_sbr_grid(&sbr->data[1], &sbr->data[0]); + read_sbr_dtdf(sbr, gb, &sbr->data[0]); + read_sbr_dtdf(sbr, gb, &sbr->data[1]); + read_sbr_invf(sbr, gb, &sbr->data[0]); + memcpy(sbr->data[1].bs_invf_mode[1], sbr->data[1].bs_invf_mode[0], sizeof(sbr->data[1].bs_invf_mode[0])); + memcpy(sbr->data[1].bs_invf_mode[0], sbr->data[0].bs_invf_mode[0], sizeof(sbr->data[1].bs_invf_mode[0])); + read_sbr_envelope(sbr, gb, &sbr->data[0], 0); + read_sbr_noise(sbr, gb, &sbr->data[0], 0); + read_sbr_envelope(sbr, gb, &sbr->data[1], 1); + read_sbr_noise(sbr, gb, &sbr->data[1], 1); + } else { + if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]) || + read_sbr_grid(ac, sbr, gb, &sbr->data[1])) + return -1; + read_sbr_dtdf(sbr, gb, &sbr->data[0]); + read_sbr_dtdf(sbr, gb, &sbr->data[1]); + read_sbr_invf(sbr, gb, &sbr->data[0]); + read_sbr_invf(sbr, gb, &sbr->data[1]); + read_sbr_envelope(sbr, gb, &sbr->data[0], 0); + read_sbr_envelope(sbr, gb, &sbr->data[1], 1); + read_sbr_noise(sbr, gb, &sbr->data[0], 0); + read_sbr_noise(sbr, gb, &sbr->data[1], 1); + } + + if ((sbr->data[0].bs_add_harmonic_flag = get_bits1(gb))) + get_bits1_vector(gb, sbr->data[0].bs_add_harmonic, sbr->n[1]); + if ((sbr->data[1].bs_add_harmonic_flag = get_bits1(gb))) + get_bits1_vector(gb, sbr->data[1].bs_add_harmonic, sbr->n[1]); + + return 0; +} + +static unsigned int read_sbr_data(AACContext *ac, SpectralBandReplication *sbr, + GetBitContext *gb, int id_aac) +{ + unsigned int cnt = get_bits_count(gb); + + if (id_aac == TYPE_SCE || id_aac == TYPE_CCE) { + if (read_sbr_single_channel_element(ac, sbr, gb)) { + sbr_turnoff(sbr); + return get_bits_count(gb) - cnt; + } + } else if (id_aac == TYPE_CPE) { + if (read_sbr_channel_pair_element(ac, sbr, gb)) { + sbr_turnoff(sbr); + return get_bits_count(gb) - cnt; + } + } else { + av_log(ac->avctx, AV_LOG_ERROR, + "Invalid bitstream - cannot apply SBR to element type %d\n", id_aac); + sbr_turnoff(sbr); + return get_bits_count(gb) - cnt; + } + if (get_bits1(gb)) { // bs_extended_data + int num_bits_left = get_bits(gb, 4); // bs_extension_size + if (num_bits_left == 15) + num_bits_left += get_bits(gb, 8); // bs_esc_count + + num_bits_left <<= 3; + while (num_bits_left > 7) { + num_bits_left -= 2; + read_sbr_extension(ac, sbr, gb, get_bits(gb, 2), &num_bits_left); // bs_extension_id + } + if (num_bits_left < 0) { + av_log(ac->avctx, AV_LOG_ERROR, "SBR Extension over read.\n"); + } + if (num_bits_left > 0) + skip_bits(gb, num_bits_left); + } + + return get_bits_count(gb) - cnt; +} + +static void sbr_reset(AACContext *ac, SpectralBandReplication *sbr) +{ + int err; + err = sbr_make_f_master(ac, sbr, &sbr->spectrum_params); + if (err >= 0) + err = sbr_make_f_derived(ac, sbr); + if (err < 0) { + av_log(ac->avctx, AV_LOG_ERROR, + "SBR reset failed. Switching SBR to pure upsampling mode.\n"); + sbr_turnoff(sbr); + } +} + +/** + * Decode Spectral Band Replication extension data; reference: table 4.55. + * + * @param crc flag indicating the presence of CRC checksum + * @param cnt length of TYPE_FIL syntactic element in bytes + * + * @return Returns number of bytes consumed from the TYPE_FIL element. + */ +int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, + GetBitContext *gb_host, int crc, int cnt, int id_aac) +{ + unsigned int num_sbr_bits = 0, num_align_bits; + unsigned bytes_read; + GetBitContext gbc = *gb_host, *gb = &gbc; + skip_bits_long(gb_host, cnt*8 - 4); + + sbr->reset = 0; + + if (!sbr->sample_rate) + sbr->sample_rate = 2 * ac->oc[1].m4ac.sample_rate; //TODO use the nominal sample rate for arbitrary sample rate support + if (!ac->oc[1].m4ac.ext_sample_rate) + ac->oc[1].m4ac.ext_sample_rate = 2 * ac->oc[1].m4ac.sample_rate; + + if (crc) { + skip_bits(gb, 10); // bs_sbr_crc_bits; TODO - implement CRC check + num_sbr_bits += 10; + } + + //Save some state from the previous frame. + sbr->kx[0] = sbr->kx[1]; + sbr->m[0] = sbr->m[1]; + sbr->kx_and_m_pushed = 1; + + num_sbr_bits++; + if (get_bits1(gb)) // bs_header_flag + num_sbr_bits += read_sbr_header(sbr, gb); + + if (sbr->reset) + sbr_reset(ac, sbr); + + if (sbr->start) + num_sbr_bits += read_sbr_data(ac, sbr, gb, id_aac); + + num_align_bits = ((cnt << 3) - 4 - num_sbr_bits) & 7; + bytes_read = ((num_sbr_bits + num_align_bits + 4) >> 3); + + if (bytes_read > cnt) { + av_log(ac->avctx, AV_LOG_ERROR, + "Expected to read %d SBR bytes actually read %d.\n", cnt, bytes_read); + } + return cnt; +} + +/// Dequantization and stereo decoding (14496-3 sp04 p203) +static void sbr_dequant(SpectralBandReplication *sbr, int id_aac) +{ + int k, e; + int ch; + + if (id_aac == TYPE_CPE && sbr->bs_coupling) { + float alpha = sbr->data[0].bs_amp_res ? 1.0f : 0.5f; + float pan_offset = sbr->data[0].bs_amp_res ? 12.0f : 24.0f; + for (e = 1; e <= sbr->data[0].bs_num_env; e++) { + for (k = 0; k < sbr->n[sbr->data[0].bs_freq_res[e]]; k++) { + float temp1 = exp2f(sbr->data[0].env_facs[e][k] * alpha + 7.0f); + float temp2 = exp2f((pan_offset - sbr->data[1].env_facs[e][k]) * alpha); + float fac; + if (temp1 > 1E20) { + av_log(NULL, AV_LOG_ERROR, "envelope scalefactor overflow in dequant\n"); + temp1 = 1; + } + fac = temp1 / (1.0f + temp2); + sbr->data[0].env_facs[e][k] = fac; + sbr->data[1].env_facs[e][k] = fac * temp2; + } + } + for (e = 1; e <= sbr->data[0].bs_num_noise; e++) { + for (k = 0; k < sbr->n_q; k++) { + float temp1 = exp2f(NOISE_FLOOR_OFFSET - sbr->data[0].noise_facs[e][k] + 1); + float temp2 = exp2f(12 - sbr->data[1].noise_facs[e][k]); + float fac; + if (temp1 > 1E20) { + av_log(NULL, AV_LOG_ERROR, "envelope scalefactor overflow in dequant\n"); + temp1 = 1; + } + fac = temp1 / (1.0f + temp2); + sbr->data[0].noise_facs[e][k] = fac; + sbr->data[1].noise_facs[e][k] = fac * temp2; + } + } + } else { // SCE or one non-coupled CPE + for (ch = 0; ch < (id_aac == TYPE_CPE) + 1; ch++) { + float alpha = sbr->data[ch].bs_amp_res ? 1.0f : 0.5f; + for (e = 1; e <= sbr->data[ch].bs_num_env; e++) + for (k = 0; k < sbr->n[sbr->data[ch].bs_freq_res[e]]; k++){ + sbr->data[ch].env_facs[e][k] = + exp2f(alpha * sbr->data[ch].env_facs[e][k] + 6.0f); + if (sbr->data[ch].env_facs[e][k] > 1E20) { + av_log(NULL, AV_LOG_ERROR, "envelope scalefactor overflow in dequant\n"); + sbr->data[ch].env_facs[e][k] = 1; + } + } + + for (e = 1; e <= sbr->data[ch].bs_num_noise; e++) + for (k = 0; k < sbr->n_q; k++) + sbr->data[ch].noise_facs[e][k] = + exp2f(NOISE_FLOOR_OFFSET - sbr->data[ch].noise_facs[e][k]); + } + } +} + +/** + * Analysis QMF Bank (14496-3 sp04 p206) + * + * @param x pointer to the beginning of the first sample window + * @param W array of complex-valued samples split into subbands + */ +#ifndef sbr_qmf_analysis +static void sbr_qmf_analysis(AVFloatDSPContext *dsp, FFTContext *mdct, + SBRDSPContext *sbrdsp, const float *in, float *x, + float z[320], float W[2][32][32][2], int buf_idx) +{ + int i; + memcpy(x , x+1024, (320-32)*sizeof(x[0])); + memcpy(x+288, in, 1024*sizeof(x[0])); + for (i = 0; i < 32; i++) { // numTimeSlots*RATE = 16*2 as 960 sample frames + // are not supported + dsp->vector_fmul_reverse(z, sbr_qmf_window_ds, x, 320); + sbrdsp->sum64x5(z); + sbrdsp->qmf_pre_shuffle(z); + mdct->imdct_half(mdct, z, z+64); + sbrdsp->qmf_post_shuffle(W[buf_idx][i], z); + x += 32; + } +} +#endif + +/** + * Synthesis QMF Bank (14496-3 sp04 p206) and Downsampled Synthesis QMF Bank + * (14496-3 sp04 p206) + */ +#ifndef sbr_qmf_synthesis +static void sbr_qmf_synthesis(FFTContext *mdct, + SBRDSPContext *sbrdsp, AVFloatDSPContext *dsp, + float *out, float X[2][38][64], + float mdct_buf[2][64], + float *v0, int *v_off, const unsigned int div) +{ + int i, n; + const float *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us; + const int step = 128 >> div; + float *v; + for (i = 0; i < 32; i++) { + if (*v_off < step) { + int saved_samples = (1280 - 128) >> div; + memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(float)); + *v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - step; + } else { + *v_off -= step; + } + v = v0 + *v_off; + if (div) { + for (n = 0; n < 32; n++) { + X[0][i][ n] = -X[0][i][n]; + X[0][i][32+n] = X[1][i][31-n]; + } + mdct->imdct_half(mdct, mdct_buf[0], X[0][i]); + sbrdsp->qmf_deint_neg(v, mdct_buf[0]); + } else { + sbrdsp->neg_odd_64(X[1][i]); + mdct->imdct_half(mdct, mdct_buf[0], X[0][i]); + mdct->imdct_half(mdct, mdct_buf[1], X[1][i]); + sbrdsp->qmf_deint_bfly(v, mdct_buf[1], mdct_buf[0]); + } + dsp->vector_fmul (out, v , sbr_qmf_window , 64 >> div); + dsp->vector_fmul_add(out, v + ( 192 >> div), sbr_qmf_window + ( 64 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + ( 256 >> div), sbr_qmf_window + (128 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + ( 448 >> div), sbr_qmf_window + (192 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + ( 512 >> div), sbr_qmf_window + (256 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + ( 704 >> div), sbr_qmf_window + (320 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + ( 768 >> div), sbr_qmf_window + (384 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + ( 960 >> div), sbr_qmf_window + (448 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + (1024 >> div), sbr_qmf_window + (512 >> div), out , 64 >> div); + dsp->vector_fmul_add(out, v + (1216 >> div), sbr_qmf_window + (576 >> div), out , 64 >> div); + out += 64 >> div; + } +} +#endif + +/** High Frequency Generation (14496-3 sp04 p214+) and Inverse Filtering + * (14496-3 sp04 p214) + * Warning: This routine does not seem numerically stable. + */ +static void sbr_hf_inverse_filter(SBRDSPContext *dsp, + float (*alpha0)[2], float (*alpha1)[2], + const float X_low[32][40][2], int k0) +{ + int k; + for (k = 0; k < k0; k++) { + LOCAL_ALIGNED_16(float, phi, [3], [2][2]); + float dk; + + dsp->autocorrelate(X_low[k], phi); + + dk = phi[2][1][0] * phi[1][0][0] - + (phi[1][1][0] * phi[1][1][0] + phi[1][1][1] * phi[1][1][1]) / 1.000001f; + + if (!dk) { + alpha1[k][0] = 0; + alpha1[k][1] = 0; + } else { + float temp_real, temp_im; + temp_real = phi[0][0][0] * phi[1][1][0] - + phi[0][0][1] * phi[1][1][1] - + phi[0][1][0] * phi[1][0][0]; + temp_im = phi[0][0][0] * phi[1][1][1] + + phi[0][0][1] * phi[1][1][0] - + phi[0][1][1] * phi[1][0][0]; + + alpha1[k][0] = temp_real / dk; + alpha1[k][1] = temp_im / dk; + } + + if (!phi[1][0][0]) { + alpha0[k][0] = 0; + alpha0[k][1] = 0; + } else { + float temp_real, temp_im; + temp_real = phi[0][0][0] + alpha1[k][0] * phi[1][1][0] + + alpha1[k][1] * phi[1][1][1]; + temp_im = phi[0][0][1] + alpha1[k][1] * phi[1][1][0] - + alpha1[k][0] * phi[1][1][1]; + + alpha0[k][0] = -temp_real / phi[1][0][0]; + alpha0[k][1] = -temp_im / phi[1][0][0]; + } + + if (alpha1[k][0] * alpha1[k][0] + alpha1[k][1] * alpha1[k][1] >= 16.0f || + alpha0[k][0] * alpha0[k][0] + alpha0[k][1] * alpha0[k][1] >= 16.0f) { + alpha1[k][0] = 0; + alpha1[k][1] = 0; + alpha0[k][0] = 0; + alpha0[k][1] = 0; + } + } +} + +/// Chirp Factors (14496-3 sp04 p214) +static void sbr_chirp(SpectralBandReplication *sbr, SBRData *ch_data) +{ + int i; + float new_bw; + static const float bw_tab[] = { 0.0f, 0.75f, 0.9f, 0.98f }; + + for (i = 0; i < sbr->n_q; i++) { + if (ch_data->bs_invf_mode[0][i] + ch_data->bs_invf_mode[1][i] == 1) { + new_bw = 0.6f; + } else + new_bw = bw_tab[ch_data->bs_invf_mode[0][i]]; + + if (new_bw < ch_data->bw_array[i]) { + new_bw = 0.75f * new_bw + 0.25f * ch_data->bw_array[i]; + } else + new_bw = 0.90625f * new_bw + 0.09375f * ch_data->bw_array[i]; + ch_data->bw_array[i] = new_bw < 0.015625f ? 0.0f : new_bw; + } +} + +/// Generate the subband filtered lowband +static int sbr_lf_gen(AACContext *ac, SpectralBandReplication *sbr, + float X_low[32][40][2], const float W[2][32][32][2], + int buf_idx) +{ + int i, k; + const int t_HFGen = 8; + const int i_f = 32; + memset(X_low, 0, 32*sizeof(*X_low)); + for (k = 0; k < sbr->kx[1]; k++) { + for (i = t_HFGen; i < i_f + t_HFGen; i++) { + X_low[k][i][0] = W[buf_idx][i - t_HFGen][k][0]; + X_low[k][i][1] = W[buf_idx][i - t_HFGen][k][1]; + } + } + buf_idx = 1-buf_idx; + for (k = 0; k < sbr->kx[0]; k++) { + for (i = 0; i < t_HFGen; i++) { + X_low[k][i][0] = W[buf_idx][i + i_f - t_HFGen][k][0]; + X_low[k][i][1] = W[buf_idx][i + i_f - t_HFGen][k][1]; + } + } + return 0; +} + +/// High Frequency Generator (14496-3 sp04 p215) +static int sbr_hf_gen(AACContext *ac, SpectralBandReplication *sbr, + float X_high[64][40][2], const float X_low[32][40][2], + const float (*alpha0)[2], const float (*alpha1)[2], + const float bw_array[5], const uint8_t *t_env, + int bs_num_env) +{ + int j, x; + int g = 0; + int k = sbr->kx[1]; + for (j = 0; j < sbr->num_patches; j++) { + for (x = 0; x < sbr->patch_num_subbands[j]; x++, k++) { + const int p = sbr->patch_start_subband[j] + x; + while (g <= sbr->n_q && k >= sbr->f_tablenoise[g]) + g++; + g--; + + if (g < 0) { + av_log(ac->avctx, AV_LOG_ERROR, + "ERROR : no subband found for frequency %d\n", k); + return -1; + } + + sbr->dsp.hf_gen(X_high[k] + ENVELOPE_ADJUSTMENT_OFFSET, + X_low[p] + ENVELOPE_ADJUSTMENT_OFFSET, + alpha0[p], alpha1[p], bw_array[g], + 2 * t_env[0], 2 * t_env[bs_num_env]); + } + } + if (k < sbr->m[1] + sbr->kx[1]) + memset(X_high + k, 0, (sbr->m[1] + sbr->kx[1] - k) * sizeof(*X_high)); + + return 0; +} + +/// Generate the subband filtered lowband +static int sbr_x_gen(SpectralBandReplication *sbr, float X[2][38][64], + const float Y0[38][64][2], const float Y1[38][64][2], + const float X_low[32][40][2], int ch) +{ + int k, i; + const int i_f = 32; + const int i_Temp = FFMAX(2*sbr->data[ch].t_env_num_env_old - i_f, 0); + memset(X, 0, 2*sizeof(*X)); + for (k = 0; k < sbr->kx[0]; k++) { + for (i = 0; i < i_Temp; i++) { + X[0][i][k] = X_low[k][i + ENVELOPE_ADJUSTMENT_OFFSET][0]; + X[1][i][k] = X_low[k][i + ENVELOPE_ADJUSTMENT_OFFSET][1]; + } + } + for (; k < sbr->kx[0] + sbr->m[0]; k++) { + for (i = 0; i < i_Temp; i++) { + X[0][i][k] = Y0[i + i_f][k][0]; + X[1][i][k] = Y0[i + i_f][k][1]; + } + } + + for (k = 0; k < sbr->kx[1]; k++) { + for (i = i_Temp; i < 38; i++) { + X[0][i][k] = X_low[k][i + ENVELOPE_ADJUSTMENT_OFFSET][0]; + X[1][i][k] = X_low[k][i + ENVELOPE_ADJUSTMENT_OFFSET][1]; + } + } + for (; k < sbr->kx[1] + sbr->m[1]; k++) { + for (i = i_Temp; i < i_f; i++) { + X[0][i][k] = Y1[i][k][0]; + X[1][i][k] = Y1[i][k][1]; + } + } + return 0; +} + +/** High Frequency Adjustment (14496-3 sp04 p217) and Mapping + * (14496-3 sp04 p217) + */ +static int sbr_mapping(AACContext *ac, SpectralBandReplication *sbr, + SBRData *ch_data, int e_a[2]) +{ + int e, i, m; + + memset(ch_data->s_indexmapped[1], 0, 7*sizeof(ch_data->s_indexmapped[1])); + for (e = 0; e < ch_data->bs_num_env; e++) { + const unsigned int ilim = sbr->n[ch_data->bs_freq_res[e + 1]]; + uint16_t *table = ch_data->bs_freq_res[e + 1] ? sbr->f_tablehigh : sbr->f_tablelow; + int k; + + if (sbr->kx[1] != table[0]) { + av_log(ac->avctx, AV_LOG_ERROR, "kx != f_table{high,low}[0]. " + "Derived frequency tables were not regenerated.\n"); + sbr_turnoff(sbr); + return AVERROR_BUG; + } + for (i = 0; i < ilim; i++) + for (m = table[i]; m < table[i + 1]; m++) + sbr->e_origmapped[e][m - sbr->kx[1]] = ch_data->env_facs[e+1][i]; + + // ch_data->bs_num_noise > 1 => 2 noise floors + k = (ch_data->bs_num_noise > 1) && (ch_data->t_env[e] >= ch_data->t_q[1]); + for (i = 0; i < sbr->n_q; i++) + for (m = sbr->f_tablenoise[i]; m < sbr->f_tablenoise[i + 1]; m++) + sbr->q_mapped[e][m - sbr->kx[1]] = ch_data->noise_facs[k+1][i]; + + for (i = 0; i < sbr->n[1]; i++) { + if (ch_data->bs_add_harmonic_flag) { + const unsigned int m_midpoint = + (sbr->f_tablehigh[i] + sbr->f_tablehigh[i + 1]) >> 1; + + ch_data->s_indexmapped[e + 1][m_midpoint - sbr->kx[1]] = ch_data->bs_add_harmonic[i] * + (e >= e_a[1] || (ch_data->s_indexmapped[0][m_midpoint - sbr->kx[1]] == 1)); + } + } + + for (i = 0; i < ilim; i++) { + int additional_sinusoid_present = 0; + for (m = table[i]; m < table[i + 1]; m++) { + if (ch_data->s_indexmapped[e + 1][m - sbr->kx[1]]) { + additional_sinusoid_present = 1; + break; + } + } + memset(&sbr->s_mapped[e][table[i] - sbr->kx[1]], additional_sinusoid_present, + (table[i + 1] - table[i]) * sizeof(sbr->s_mapped[e][0])); + } + } + + memcpy(ch_data->s_indexmapped[0], ch_data->s_indexmapped[ch_data->bs_num_env], sizeof(ch_data->s_indexmapped[0])); + return 0; +} + +/// Estimation of current envelope (14496-3 sp04 p218) +static void sbr_env_estimate(float (*e_curr)[48], float X_high[64][40][2], + SpectralBandReplication *sbr, SBRData *ch_data) +{ + int e, m; + int kx1 = sbr->kx[1]; + + if (sbr->bs_interpol_freq) { + for (e = 0; e < ch_data->bs_num_env; e++) { + const float recip_env_size = 0.5f / (ch_data->t_env[e + 1] - ch_data->t_env[e]); + int ilb = ch_data->t_env[e] * 2 + ENVELOPE_ADJUSTMENT_OFFSET; + int iub = ch_data->t_env[e + 1] * 2 + ENVELOPE_ADJUSTMENT_OFFSET; + + for (m = 0; m < sbr->m[1]; m++) { + float sum = sbr->dsp.sum_square(X_high[m+kx1] + ilb, iub - ilb); + e_curr[e][m] = sum * recip_env_size; + } + } + } else { + int k, p; + + for (e = 0; e < ch_data->bs_num_env; e++) { + const int env_size = 2 * (ch_data->t_env[e + 1] - ch_data->t_env[e]); + int ilb = ch_data->t_env[e] * 2 + ENVELOPE_ADJUSTMENT_OFFSET; + int iub = ch_data->t_env[e + 1] * 2 + ENVELOPE_ADJUSTMENT_OFFSET; + const uint16_t *table = ch_data->bs_freq_res[e + 1] ? sbr->f_tablehigh : sbr->f_tablelow; + + for (p = 0; p < sbr->n[ch_data->bs_freq_res[e + 1]]; p++) { + float sum = 0.0f; + const int den = env_size * (table[p + 1] - table[p]); + + for (k = table[p]; k < table[p + 1]; k++) { + sum += sbr->dsp.sum_square(X_high[k] + ilb, iub - ilb); + } + sum /= den; + for (k = table[p]; k < table[p + 1]; k++) { + e_curr[e][k - kx1] = sum; + } + } + } + } +} + +/** + * Calculation of levels of additional HF signal components (14496-3 sp04 p219) + * and Calculation of gain (14496-3 sp04 p219) + */ +static void sbr_gain_calc(AACContext *ac, SpectralBandReplication *sbr, + SBRData *ch_data, const int e_a[2]) +{ + int e, k, m; + // max gain limits : -3dB, 0dB, 3dB, inf dB (limiter off) + static const float limgain[4] = { 0.70795, 1.0, 1.41254, 10000000000 }; + + for (e = 0; e < ch_data->bs_num_env; e++) { + int delta = !((e == e_a[1]) || (e == e_a[0])); + for (k = 0; k < sbr->n_lim; k++) { + float gain_boost, gain_max; + float sum[2] = { 0.0f, 0.0f }; + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + const float temp = sbr->e_origmapped[e][m] / (1.0f + sbr->q_mapped[e][m]); + sbr->q_m[e][m] = sqrtf(temp * sbr->q_mapped[e][m]); + sbr->s_m[e][m] = sqrtf(temp * ch_data->s_indexmapped[e + 1][m]); + if (!sbr->s_mapped[e][m]) { + sbr->gain[e][m] = sqrtf(sbr->e_origmapped[e][m] / + ((1.0f + sbr->e_curr[e][m]) * + (1.0f + sbr->q_mapped[e][m] * delta))); + } else { + sbr->gain[e][m] = sqrtf(sbr->e_origmapped[e][m] * sbr->q_mapped[e][m] / + ((1.0f + sbr->e_curr[e][m]) * + (1.0f + sbr->q_mapped[e][m]))); + } + } + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + sum[0] += sbr->e_origmapped[e][m]; + sum[1] += sbr->e_curr[e][m]; + } + gain_max = limgain[sbr->bs_limiter_gains] * sqrtf((FLT_EPSILON + sum[0]) / (FLT_EPSILON + sum[1])); + gain_max = FFMIN(100000.f, gain_max); + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + float q_m_max = sbr->q_m[e][m] * gain_max / sbr->gain[e][m]; + sbr->q_m[e][m] = FFMIN(sbr->q_m[e][m], q_m_max); + sbr->gain[e][m] = FFMIN(sbr->gain[e][m], gain_max); + } + sum[0] = sum[1] = 0.0f; + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + sum[0] += sbr->e_origmapped[e][m]; + sum[1] += sbr->e_curr[e][m] * sbr->gain[e][m] * sbr->gain[e][m] + + sbr->s_m[e][m] * sbr->s_m[e][m] + + (delta && !sbr->s_m[e][m]) * sbr->q_m[e][m] * sbr->q_m[e][m]; + } + gain_boost = sqrtf((FLT_EPSILON + sum[0]) / (FLT_EPSILON + sum[1])); + gain_boost = FFMIN(1.584893192f, gain_boost); + for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) { + sbr->gain[e][m] *= gain_boost; + sbr->q_m[e][m] *= gain_boost; + sbr->s_m[e][m] *= gain_boost; + } + } + } +} + +/// Assembling HF Signals (14496-3 sp04 p220) +static void sbr_hf_assemble(float Y1[38][64][2], + const float X_high[64][40][2], + SpectralBandReplication *sbr, SBRData *ch_data, + const int e_a[2]) +{ + int e, i, j, m; + const int h_SL = 4 * !sbr->bs_smoothing_mode; + const int kx = sbr->kx[1]; + const int m_max = sbr->m[1]; + static const float h_smooth[5] = { + 0.33333333333333, + 0.30150283239582, + 0.21816949906249, + 0.11516383427084, + 0.03183050093751, + }; + float (*g_temp)[48] = ch_data->g_temp, (*q_temp)[48] = ch_data->q_temp; + int indexnoise = ch_data->f_indexnoise; + int indexsine = ch_data->f_indexsine; + + if (sbr->reset) { + for (i = 0; i < h_SL; i++) { + memcpy(g_temp[i + 2*ch_data->t_env[0]], sbr->gain[0], m_max * sizeof(sbr->gain[0][0])); + memcpy(q_temp[i + 2*ch_data->t_env[0]], sbr->q_m[0], m_max * sizeof(sbr->q_m[0][0])); + } + } else if (h_SL) { + memcpy(g_temp[2*ch_data->t_env[0]], g_temp[2*ch_data->t_env_num_env_old], 4*sizeof(g_temp[0])); + memcpy(q_temp[2*ch_data->t_env[0]], q_temp[2*ch_data->t_env_num_env_old], 4*sizeof(q_temp[0])); + } + + for (e = 0; e < ch_data->bs_num_env; e++) { + for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) { + memcpy(g_temp[h_SL + i], sbr->gain[e], m_max * sizeof(sbr->gain[0][0])); + memcpy(q_temp[h_SL + i], sbr->q_m[e], m_max * sizeof(sbr->q_m[0][0])); + } + } + + for (e = 0; e < ch_data->bs_num_env; e++) { + for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) { + LOCAL_ALIGNED_16(float, g_filt_tab, [48]); + LOCAL_ALIGNED_16(float, q_filt_tab, [48]); + float *g_filt, *q_filt; + + if (h_SL && e != e_a[0] && e != e_a[1]) { + g_filt = g_filt_tab; + q_filt = q_filt_tab; + for (m = 0; m < m_max; m++) { + const int idx1 = i + h_SL; + g_filt[m] = 0.0f; + q_filt[m] = 0.0f; + for (j = 0; j <= h_SL; j++) { + g_filt[m] += g_temp[idx1 - j][m] * h_smooth[j]; + q_filt[m] += q_temp[idx1 - j][m] * h_smooth[j]; + } + } + } else { + g_filt = g_temp[i + h_SL]; + q_filt = q_temp[i]; + } + + sbr->dsp.hf_g_filt(Y1[i] + kx, X_high + kx, g_filt, m_max, + i + ENVELOPE_ADJUSTMENT_OFFSET); + + if (e != e_a[0] && e != e_a[1]) { + sbr->dsp.hf_apply_noise[indexsine](Y1[i] + kx, sbr->s_m[e], + q_filt, indexnoise, + kx, m_max); + } else { + int idx = indexsine&1; + int A = (1-((indexsine+(kx & 1))&2)); + int B = (A^(-idx)) + idx; + float *out = &Y1[i][kx][idx]; + float *in = sbr->s_m[e]; + for (m = 0; m+1 < m_max; m+=2) { + out[2*m ] += in[m ] * A; + out[2*m+2] += in[m+1] * B; + } + if(m_max&1) + out[2*m ] += in[m ] * A; + } + indexnoise = (indexnoise + m_max) & 0x1ff; + indexsine = (indexsine + 1) & 3; + } + } + ch_data->f_indexnoise = indexnoise; + ch_data->f_indexsine = indexsine; +} + +void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, + float* L, float* R) +{ + int downsampled = ac->oc[1].m4ac.ext_sample_rate < sbr->sample_rate; + int ch; + int nch = (id_aac == TYPE_CPE) ? 2 : 1; + int err; + + if (!sbr->kx_and_m_pushed) { + sbr->kx[0] = sbr->kx[1]; + sbr->m[0] = sbr->m[1]; + } else { + sbr->kx_and_m_pushed = 0; + } + + if (sbr->start) { + sbr_dequant(sbr, id_aac); + } + for (ch = 0; ch < nch; ch++) { + /* decode channel */ + sbr_qmf_analysis(&ac->fdsp, &sbr->mdct_ana, &sbr->dsp, ch ? R : L, sbr->data[ch].analysis_filterbank_samples, + (float*)sbr->qmf_filter_scratch, + sbr->data[ch].W, sbr->data[ch].Ypos); + sbr->c.sbr_lf_gen(ac, sbr, sbr->X_low, sbr->data[ch].W, sbr->data[ch].Ypos); + sbr->data[ch].Ypos ^= 1; + if (sbr->start) { + sbr->c.sbr_hf_inverse_filter(&sbr->dsp, sbr->alpha0, sbr->alpha1, sbr->X_low, sbr->k[0]); + sbr_chirp(sbr, &sbr->data[ch]); + sbr_hf_gen(ac, sbr, sbr->X_high, sbr->X_low, sbr->alpha0, sbr->alpha1, + sbr->data[ch].bw_array, sbr->data[ch].t_env, + sbr->data[ch].bs_num_env); + + // hf_adj + err = sbr_mapping(ac, sbr, &sbr->data[ch], sbr->data[ch].e_a); + if (!err) { + sbr_env_estimate(sbr->e_curr, sbr->X_high, sbr, &sbr->data[ch]); + sbr_gain_calc(ac, sbr, &sbr->data[ch], sbr->data[ch].e_a); + sbr->c.sbr_hf_assemble(sbr->data[ch].Y[sbr->data[ch].Ypos], + sbr->X_high, sbr, &sbr->data[ch], + sbr->data[ch].e_a); + } + } + + /* synthesis */ + sbr->c.sbr_x_gen(sbr, sbr->X[ch], + sbr->data[ch].Y[1-sbr->data[ch].Ypos], + sbr->data[ch].Y[ sbr->data[ch].Ypos], + sbr->X_low, ch); + } + + if (ac->oc[1].m4ac.ps == 1) { + if (sbr->ps.start) { + ff_ps_apply(ac->avctx, &sbr->ps, sbr->X[0], sbr->X[1], sbr->kx[1] + sbr->m[1]); + } else { + memcpy(sbr->X[1], sbr->X[0], sizeof(sbr->X[0])); + } + nch = 2; + } + + sbr_qmf_synthesis(&sbr->mdct, &sbr->dsp, &ac->fdsp, + L, sbr->X[0], sbr->qmf_filter_scratch, + sbr->data[0].synthesis_filterbank_samples, + &sbr->data[0].synthesis_filterbank_samples_offset, + downsampled); + if (nch == 2) + sbr_qmf_synthesis(&sbr->mdct, &sbr->dsp, &ac->fdsp, + R, sbr->X[1], sbr->qmf_filter_scratch, + sbr->data[1].synthesis_filterbank_samples, + &sbr->data[1].synthesis_filterbank_samples_offset, + downsampled); +} + +static void aacsbr_func_ptr_init(AACSBRContext *c) +{ + c->sbr_lf_gen = sbr_lf_gen; + c->sbr_hf_assemble = sbr_hf_assemble; + c->sbr_x_gen = sbr_x_gen; + c->sbr_hf_inverse_filter = sbr_hf_inverse_filter; + + if(ARCH_MIPS) + ff_aacsbr_func_ptr_init_mips(c); +} diff --git a/ffmpeg/libavcodec/aacsbr.h b/ffmpeg/libavcodec/aacsbr.h new file mode 100644 index 0000000..f5e33ab --- /dev/null +++ b/ffmpeg/libavcodec/aacsbr.h @@ -0,0 +1,51 @@ +/* + * AAC Spectral Band Replication function declarations + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +/** + * @file + * AAC Spectral Band Replication function declarations + * @author Robert Swain ( rob opendot cl ) + */ + +#ifndef AVCODEC_AACSBR_H +#define AVCODEC_AACSBR_H + +#include "get_bits.h" +#include "aac.h" +#include "sbr.h" + +/** Initialize SBR. */ +void ff_aac_sbr_init(void); +/** Initialize one SBR context. */ +void ff_aac_sbr_ctx_init(AACContext *ac, SpectralBandReplication *sbr); +/** Close one SBR context. */ +void ff_aac_sbr_ctx_close(SpectralBandReplication *sbr); +/** Decode one SBR element. */ +int ff_decode_sbr_extension(AACContext *ac, SpectralBandReplication *sbr, + GetBitContext *gb, int crc, int cnt, int id_aac); +/** Apply one SBR element to one AAC element. */ +void ff_sbr_apply(AACContext *ac, SpectralBandReplication *sbr, int id_aac, + float* L, float *R); + +void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c); + +#endif /* AVCODEC_AACSBR_H */ diff --git a/ffmpeg/libavcodec/aacsbrdata.h b/ffmpeg/libavcodec/aacsbrdata.h new file mode 100644 index 0000000..dd7a827 --- /dev/null +++ b/ffmpeg/libavcodec/aacsbrdata.h @@ -0,0 +1,616 @@ +/* + * AAC Spectral Band Replication decoding data + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * + * 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 + */ + +/** + * @file + * AAC Spectral Band Replication decoding data + * @author Robert Swain ( rob opendot cl ) + */ + +#ifndef AVCODEC_AACSBRDATA_H +#define AVCODEC_AACSBRDATA_H + +#include +#include "libavutil/mem.h" + +///< Huffman tables for SBR + +static const uint8_t t_huffman_env_1_5dB_bits[121] = { + 18, 18, 18, 18, 18, 18, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 17, 18, 16, 17, 18, 17, + 16, 16, 16, 16, 15, 14, 14, 13, + 13, 12, 11, 10, 9, 8, 7, 6, + 5, 4, 3, 2, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 12, 13, 14, + 14, 15, 16, 17, 16, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, +}; + +static const uint32_t t_huffman_env_1_5dB_codes[121] = { + 0x3ffd6, 0x3ffd7, 0x3ffd8, 0x3ffd9, 0x3ffda, 0x3ffdb, 0x7ffb8, 0x7ffb9, + 0x7ffba, 0x7ffbb, 0x7ffbc, 0x7ffbd, 0x7ffbe, 0x7ffbf, 0x7ffc0, 0x7ffc1, + 0x7ffc2, 0x7ffc3, 0x7ffc4, 0x7ffc5, 0x7ffc6, 0x7ffc7, 0x7ffc8, 0x7ffc9, + 0x7ffca, 0x7ffcb, 0x7ffcc, 0x7ffcd, 0x7ffce, 0x7ffcf, 0x7ffd0, 0x7ffd1, + 0x7ffd2, 0x7ffd3, 0x1ffe6, 0x3ffd4, 0x0fff0, 0x1ffe9, 0x3ffd5, 0x1ffe7, + 0x0fff1, 0x0ffec, 0x0ffed, 0x0ffee, 0x07ff4, 0x03ff9, 0x03ff7, 0x01ffa, + 0x01ff9, 0x00ffb, 0x007fc, 0x003fc, 0x001fd, 0x000fd, 0x0007d, 0x0003d, + 0x0001d, 0x0000d, 0x00005, 0x00001, 0x00000, 0x00004, 0x0000c, 0x0001c, + 0x0003c, 0x0007c, 0x000fc, 0x001fc, 0x003fd, 0x00ffa, 0x01ff8, 0x03ff6, + 0x03ff8, 0x07ff5, 0x0ffef, 0x1ffe8, 0x0fff2, 0x7ffd4, 0x7ffd5, 0x7ffd6, + 0x7ffd7, 0x7ffd8, 0x7ffd9, 0x7ffda, 0x7ffdb, 0x7ffdc, 0x7ffdd, 0x7ffde, + 0x7ffdf, 0x7ffe0, 0x7ffe1, 0x7ffe2, 0x7ffe3, 0x7ffe4, 0x7ffe5, 0x7ffe6, + 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb, 0x7ffec, 0x7ffed, 0x7ffee, + 0x7ffef, 0x7fff0, 0x7fff1, 0x7fff2, 0x7fff3, 0x7fff4, 0x7fff5, 0x7fff6, + 0x7fff7, 0x7fff8, 0x7fff9, 0x7fffa, 0x7fffb, 0x7fffc, 0x7fffd, 0x7fffe, + 0x7ffff, +}; + +static const uint8_t f_huffman_env_1_5dB_bits[121] = { + 19, 19, 20, 20, 20, 20, 20, 20, + 20, 19, 20, 20, 20, 20, 19, 20, + 19, 19, 20, 18, 20, 20, 20, 19, + 20, 20, 20, 19, 20, 19, 18, 19, + 18, 18, 17, 18, 17, 17, 17, 16, + 16, 16, 15, 15, 14, 13, 13, 12, + 12, 11, 10, 9, 9, 8, 7, 6, + 5, 4, 3, 2, 2, 3, 4, 5, + 6, 8, 8, 9, 10, 11, 11, 11, + 12, 12, 13, 13, 14, 14, 16, 16, + 17, 17, 18, 18, 18, 18, 18, 18, + 18, 20, 19, 20, 20, 20, 20, 20, + 20, 19, 20, 20, 20, 20, 19, 20, + 18, 20, 20, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, + 20, +}; + +static const uint32_t f_huffman_env_1_5dB_codes[121] = { + 0x7ffe7, 0x7ffe8, 0xfffd2, 0xfffd3, 0xfffd4, 0xfffd5, 0xfffd6, 0xfffd7, + 0xfffd8, 0x7ffda, 0xfffd9, 0xfffda, 0xfffdb, 0xfffdc, 0x7ffdb, 0xfffdd, + 0x7ffdc, 0x7ffdd, 0xfffde, 0x3ffe4, 0xfffdf, 0xfffe0, 0xfffe1, 0x7ffde, + 0xfffe2, 0xfffe3, 0xfffe4, 0x7ffdf, 0xfffe5, 0x7ffe0, 0x3ffe8, 0x7ffe1, + 0x3ffe0, 0x3ffe9, 0x1ffef, 0x3ffe5, 0x1ffec, 0x1ffed, 0x1ffee, 0x0fff4, + 0x0fff3, 0x0fff0, 0x07ff7, 0x07ff6, 0x03ffa, 0x01ffa, 0x01ff9, 0x00ffa, + 0x00ff8, 0x007f9, 0x003fb, 0x001fc, 0x001fa, 0x000fb, 0x0007c, 0x0003c, + 0x0001c, 0x0000c, 0x00005, 0x00001, 0x00000, 0x00004, 0x0000d, 0x0001d, + 0x0003d, 0x000fa, 0x000fc, 0x001fb, 0x003fa, 0x007f8, 0x007fa, 0x007fb, + 0x00ff9, 0x00ffb, 0x01ff8, 0x01ffb, 0x03ff8, 0x03ff9, 0x0fff1, 0x0fff2, + 0x1ffea, 0x1ffeb, 0x3ffe1, 0x3ffe2, 0x3ffea, 0x3ffe3, 0x3ffe6, 0x3ffe7, + 0x3ffeb, 0xfffe6, 0x7ffe2, 0xfffe7, 0xfffe8, 0xfffe9, 0xfffea, 0xfffeb, + 0xfffec, 0x7ffe3, 0xfffed, 0xfffee, 0xfffef, 0xffff0, 0x7ffe4, 0xffff1, + 0x3ffec, 0xffff2, 0xffff3, 0x7ffe5, 0x7ffe6, 0xffff4, 0xffff5, 0xffff6, + 0xffff7, 0xffff8, 0xffff9, 0xffffa, 0xffffb, 0xffffc, 0xffffd, 0xffffe, + 0xfffff, +}; + +static const uint8_t t_huffman_env_bal_1_5dB_bits[49] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 12, 11, 9, 7, 5, 3, + 1, 2, 4, 6, 8, 11, 12, 15, + 16, 16, 16, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, +}; + +static const uint32_t t_huffman_env_bal_1_5dB_codes[49] = { + 0x0ffe4, 0x0ffe5, 0x0ffe6, 0x0ffe7, 0x0ffe8, 0x0ffe9, 0x0ffea, 0x0ffeb, + 0x0ffec, 0x0ffed, 0x0ffee, 0x0ffef, 0x0fff0, 0x0fff1, 0x0fff2, 0x0fff3, + 0x0fff4, 0x0ffe2, 0x00ffc, 0x007fc, 0x001fe, 0x0007e, 0x0001e, 0x00006, + 0x00000, 0x00002, 0x0000e, 0x0003e, 0x000fe, 0x007fd, 0x00ffd, 0x07ff0, + 0x0ffe3, 0x0fff5, 0x0fff6, 0x0fff7, 0x0fff8, 0x0fff9, 0x0fffa, 0x1fff6, + 0x1fff7, 0x1fff8, 0x1fff9, 0x1fffa, 0x1fffb, 0x1fffc, 0x1fffd, 0x1fffe, + 0x1ffff, +}; + +static const uint8_t f_huffman_env_bal_1_5dB_bits[49] = { + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 16, + 17, 14, 11, 11, 8, 7, 4, 2, + 1, 3, 5, 6, 9, 11, 12, 15, + 16, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 19, + 19, +}; + +static const uint32_t f_huffman_env_bal_1_5dB_codes[49] = { + 0x3ffe2, 0x3ffe3, 0x3ffe4, 0x3ffe5, 0x3ffe6, 0x3ffe7, 0x3ffe8, 0x3ffe9, + 0x3ffea, 0x3ffeb, 0x3ffec, 0x3ffed, 0x3ffee, 0x3ffef, 0x3fff0, 0x0fff7, + 0x1fff0, 0x03ffc, 0x007fe, 0x007fc, 0x000fe, 0x0007e, 0x0000e, 0x00002, + 0x00000, 0x00006, 0x0001e, 0x0003e, 0x001fe, 0x007fd, 0x00ffe, 0x07ffa, + 0x0fff6, 0x3fff1, 0x3fff2, 0x3fff3, 0x3fff4, 0x3fff5, 0x3fff6, 0x3fff7, + 0x3fff8, 0x3fff9, 0x3fffa, 0x3fffb, 0x3fffc, 0x3fffd, 0x3fffe, 0x7fffe, + 0x7ffff, +}; + +static const uint8_t t_huffman_env_3_0dB_bits[63] = { + 18, 18, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 17, 16, 16, 16, 14, 14, 14, + 13, 12, 11, 8, 6, 4, 2, 1, + 3, 5, 7, 9, 11, 13, 14, 14, + 15, 16, 17, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, +}; + +static const uint32_t t_huffman_env_3_0dB_codes[63] = { + 0x3ffed, 0x3ffee, 0x7ffde, 0x7ffdf, 0x7ffe0, 0x7ffe1, 0x7ffe2, 0x7ffe3, + 0x7ffe4, 0x7ffe5, 0x7ffe6, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb, + 0x7ffec, 0x1fff4, 0x0fff7, 0x0fff9, 0x0fff8, 0x03ffb, 0x03ffa, 0x03ff8, + 0x01ffa, 0x00ffc, 0x007fc, 0x000fe, 0x0003e, 0x0000e, 0x00002, 0x00000, + 0x00006, 0x0001e, 0x0007e, 0x001fe, 0x007fd, 0x01ffb, 0x03ff9, 0x03ffc, + 0x07ffa, 0x0fff6, 0x1fff5, 0x3ffec, 0x7ffed, 0x7ffee, 0x7ffef, 0x7fff0, + 0x7fff1, 0x7fff2, 0x7fff3, 0x7fff4, 0x7fff5, 0x7fff6, 0x7fff7, 0x7fff8, + 0x7fff9, 0x7fffa, 0x7fffb, 0x7fffc, 0x7fffd, 0x7fffe, 0x7ffff, +}; + +static const uint8_t f_huffman_env_3_0dB_bits[63] = { + 20, 20, 20, 20, 20, 20, 20, 18, + 19, 19, 19, 19, 18, 18, 20, 19, + 17, 18, 17, 16, 16, 15, 14, 12, + 11, 10, 9, 8, 6, 4, 2, 1, + 3, 5, 8, 9, 10, 11, 12, 13, + 14, 15, 15, 16, 16, 17, 17, 18, + 18, 18, 20, 19, 19, 19, 20, 19, + 19, 20, 20, 20, 20, 20, 20, +}; + +static const uint32_t f_huffman_env_3_0dB_codes[63] = { + 0xffff0, 0xffff1, 0xffff2, 0xffff3, 0xffff4, 0xffff5, 0xffff6, 0x3fff3, + 0x7fff5, 0x7ffee, 0x7ffef, 0x7fff6, 0x3fff4, 0x3fff2, 0xffff7, 0x7fff0, + 0x1fff5, 0x3fff0, 0x1fff4, 0x0fff7, 0x0fff6, 0x07ff8, 0x03ffb, 0x00ffd, + 0x007fd, 0x003fd, 0x001fd, 0x000fd, 0x0003e, 0x0000e, 0x00002, 0x00000, + 0x00006, 0x0001e, 0x000fc, 0x001fc, 0x003fc, 0x007fc, 0x00ffc, 0x01ffc, + 0x03ffa, 0x07ff9, 0x07ffa, 0x0fff8, 0x0fff9, 0x1fff6, 0x1fff7, 0x3fff5, + 0x3fff6, 0x3fff1, 0xffff8, 0x7fff1, 0x7fff2, 0x7fff3, 0xffff9, 0x7fff7, + 0x7fff4, 0xffffa, 0xffffb, 0xffffc, 0xffffd, 0xffffe, 0xfffff, +}; + +static const uint8_t t_huffman_env_bal_3_0dB_bits[25] = { + 13, 13, 13, 13, 13, 13, 13, 12, + 8, 7, 4, 3, 1, 2, 5, 6, + 9, 13, 13, 13, 13, 13, 13, 14, + 14, +}; + +static const uint16_t t_huffman_env_bal_3_0dB_codes[25] = { + 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x0ff8, + 0x00fe, 0x007e, 0x000e, 0x0006, 0x0000, 0x0002, 0x001e, 0x003e, + 0x01fe, 0x1ff9, 0x1ffa, 0x1ffb, 0x1ffc, 0x1ffd, 0x1ffe, 0x3ffe, + 0x3fff, +}; + +static const uint8_t f_huffman_env_bal_3_0dB_bits[25] = { + 13, 13, 13, 13, 13, 14, 14, 11, + 8, 7, 4, 2, 1, 3, 5, 6, + 9, 12, 13, 14, 14, 14, 14, 14, + 14, +}; + +static const uint16_t f_huffman_env_bal_3_0dB_codes[25] = { + 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb, 0x3ff8, 0x3ff9, 0x07fc, + 0x00fe, 0x007e, 0x000e, 0x0002, 0x0000, 0x0006, 0x001e, 0x003e, + 0x01fe, 0x0ffa, 0x1ff6, 0x3ffa, 0x3ffb, 0x3ffc, 0x3ffd, 0x3ffe, + 0x3fff, +}; + +static const uint8_t t_huffman_noise_3_0dB_bits[63] = { + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 11, 8, 6, 4, 3, 1, + 2, 5, 8, 10, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, +}; + +static const uint16_t t_huffman_noise_3_0dB_codes[63] = { + 0x1fce, 0x1fcf, 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5, + 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb, 0x1fdc, 0x1fdd, + 0x1fde, 0x1fdf, 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5, + 0x1fe6, 0x1fe7, 0x07f2, 0x00fd, 0x003e, 0x000e, 0x0006, 0x0000, + 0x0002, 0x001e, 0x00fc, 0x03f8, 0x1fcc, 0x1fe8, 0x1fe9, 0x1fea, + 0x1feb, 0x1fec, 0x1fcd, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1, + 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9, + 0x1ffa, 0x1ffb, 0x1ffc, 0x1ffd, 0x1ffe, 0x3ffe, 0x3fff, +}; + +static const uint8_t t_huffman_noise_bal_3_0dB_bits[25] = { + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 5, 2, 1, 3, 6, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, +}; + +static const uint8_t t_huffman_noise_bal_3_0dB_codes[25] = { + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0x1c, 0x02, 0x00, 0x06, 0x3a, 0xf6, + 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff, +}; + +static const int8_t sbr_offset[6][16] = { + {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}, // fs_sbr = 16000 Hz + {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13}, // fs_sbr = 22050 Hz + {-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}, // fs_sbr = 24000 Hz + {-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}, // fs_sbr = 32000 Hz + {-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20}, // 44100 Hz <= fs_sbr <= 64000 Hz + {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24}, // 64000 Hz < fs_sbr +}; + +///< window coefficients for analysis/synthesis QMF banks +static DECLARE_ALIGNED(32, float, sbr_qmf_window_ds)[320]; +static DECLARE_ALIGNED(32, float, sbr_qmf_window_us)[640] = { + 0.0000000000, -0.0005525286, -0.0005617692, -0.0004947518, + -0.0004875227, -0.0004893791, -0.0005040714, -0.0005226564, + -0.0005466565, -0.0005677802, -0.0005870930, -0.0006132747, + -0.0006312493, -0.0006540333, -0.0006777690, -0.0006941614, + -0.0007157736, -0.0007255043, -0.0007440941, -0.0007490598, + -0.0007681371, -0.0007724848, -0.0007834332, -0.0007779869, + -0.0007803664, -0.0007801449, -0.0007757977, -0.0007630793, + -0.0007530001, -0.0007319357, -0.0007215391, -0.0006917937, + -0.0006650415, -0.0006341594, -0.0005946118, -0.0005564576, + -0.0005145572, -0.0004606325, -0.0004095121, -0.0003501175, + -0.0002896981, -0.0002098337, -0.0001446380, -0.0000617334, + 0.0000134949, 0.0001094383, 0.0002043017, 0.0002949531, + 0.0004026540, 0.0005107388, 0.0006239376, 0.0007458025, + 0.0008608443, 0.0009885988, 0.0011250155, 0.0012577884, + 0.0013902494, 0.0015443219, 0.0016868083, 0.0018348265, + 0.0019841140, 0.0021461583, 0.0023017254, 0.0024625616, + 0.0026201758, 0.0027870464, 0.0029469447, 0.0031125420, + 0.0032739613, 0.0034418874, 0.0036008268, 0.0037603922, + 0.0039207432, 0.0040819753, 0.0042264269, 0.0043730719, + 0.0045209852, 0.0046606460, 0.0047932560, 0.0049137603, + 0.0050393022, 0.0051407353, 0.0052461166, 0.0053471681, + 0.0054196775, 0.0054876040, 0.0055475714, 0.0055938023, + 0.0056220643, 0.0056455196, 0.0056389199, 0.0056266114, + 0.0055917128, 0.0055404363, 0.0054753783, 0.0053838975, + 0.0052715758, 0.0051382275, 0.0049839687, 0.0048109469, + 0.0046039530, 0.0043801861, 0.0041251642, 0.0038456408, + 0.0035401246, 0.0032091885, 0.0028446757, 0.0024508540, + 0.0020274176, 0.0015784682, 0.0010902329, 0.0005832264, + 0.0000276045, -0.0005464280, -0.0011568135, -0.0018039472, + -0.0024826723, -0.0031933778, -0.0039401124, -0.0047222596, + -0.0055337211, -0.0063792293, -0.0072615816, -0.0081798233, + -0.0091325329, -0.0101150215, -0.0111315548, -0.0121849995, + 0.0132718220, 0.0143904666, 0.0155405553, 0.0167324712, + 0.0179433381, 0.0191872431, 0.0204531793, 0.0217467550, + 0.0230680169, 0.0244160992, 0.0257875847, 0.0271859429, + 0.0286072173, 0.0300502657, 0.0315017608, 0.0329754081, + 0.0344620948, 0.0359697560, 0.0374812850, 0.0390053679, + 0.0405349170, 0.0420649094, 0.0436097542, 0.0451488405, + 0.0466843027, 0.0482165720, 0.0497385755, 0.0512556155, + 0.0527630746, 0.0542452768, 0.0557173648, 0.0571616450, + 0.0585915683, 0.0599837480, 0.0613455171, 0.0626857808, + 0.0639715898, 0.0652247106, 0.0664367512, 0.0676075985, + 0.0687043828, 0.0697630244, 0.0707628710, 0.0717002673, + 0.0725682583, 0.0733620255, 0.0741003642, 0.0747452558, + 0.0753137336, 0.0758008358, 0.0761992479, 0.0764992170, + 0.0767093490, 0.0768173975, 0.0768230011, 0.0767204924, + 0.0765050718, 0.0761748321, 0.0757305756, 0.0751576255, + 0.0744664394, 0.0736406005, 0.0726774642, 0.0715826364, + 0.0703533073, 0.0689664013, 0.0674525021, 0.0657690668, + 0.0639444805, 0.0619602779, 0.0598166570, 0.0575152691, + 0.0550460034, 0.0524093821, 0.0495978676, 0.0466303305, + 0.0434768782, 0.0401458278, 0.0366418116, 0.0329583930, + 0.0290824006, 0.0250307561, 0.0207997072, 0.0163701258, + 0.0117623832, 0.0069636862, 0.0019765601, -0.0032086896, + -0.0085711749, -0.0141288827, -0.0198834129, -0.0258227288, + -0.0319531274, -0.0382776572, -0.0447806821, -0.0514804176, + -0.0583705326, -0.0654409853, -0.0726943300, -0.0801372934, + -0.0877547536, -0.0955533352, -0.1035329531, -0.1116826931, + -0.1200077984, -0.1285002850, -0.1371551761, -0.1459766491, + -0.1549607071, -0.1640958855, -0.1733808172, -0.1828172548, + -0.1923966745, -0.2021250176, -0.2119735853, -0.2219652696, + -0.2320690870, -0.2423016884, -0.2526480309, -0.2631053299, + -0.2736634040, -0.2843214189, -0.2950716717, -0.3059098575, + -0.3168278913, -0.3278113727, -0.3388722693, -0.3499914122, + 0.3611589903, 0.3723795546, 0.3836350013, 0.3949211761, + 0.4062317676, 0.4175696896, 0.4289119920, 0.4402553754, + 0.4515996535, 0.4629308085, 0.4742453214, 0.4855253091, + 0.4967708254, 0.5079817500, 0.5191234970, 0.5302240895, + 0.5412553448, 0.5522051258, 0.5630789140, 0.5738524131, + 0.5845403235, 0.5951123086, 0.6055783538, 0.6159109932, + 0.6261242695, 0.6361980107, 0.6461269695, 0.6559016302, + 0.6655139880, 0.6749663190, 0.6842353293, 0.6933282376, + 0.7022388719, 0.7109410426, 0.7194462634, 0.7277448900, + 0.7358211758, 0.7436827863, 0.7513137456, 0.7587080760, + 0.7658674865, 0.7727780881, 0.7794287519, 0.7858353120, + 0.7919735841, 0.7978466413, 0.8034485751, 0.8087695004, + 0.8138191270, 0.8185776004, 0.8230419890, 0.8272275347, + 0.8311038457, 0.8346937361, 0.8379717337, 0.8409541392, + 0.8436238281, 0.8459818469, 0.8480315777, 0.8497805198, + 0.8511971524, 0.8523047035, 0.8531020949, 0.8535720573, + 0.8537385600, +}; + +/* First two entries repeated at end to simplify SIMD implementations. */ +const DECLARE_ALIGNED(16, float, ff_sbr_noise_table)[][2] = { +{-0.99948153278296, -0.59483417516607}, { 0.97113454393991, -0.67528515225647}, +{ 0.14130051758487, -0.95090983575689}, {-0.47005496701697, -0.37340549728647}, +{ 0.80705063769351, 0.29653668284408}, {-0.38981478896926, 0.89572605717087}, +{-0.01053049862020, -0.66959058036166}, {-0.91266367957293, -0.11522938140034}, +{ 0.54840422910309, 0.75221367176302}, { 0.40009252867955, -0.98929400334421}, +{-0.99867974711855, -0.88147068645358}, {-0.95531076805040, 0.90908757154593}, +{-0.45725933317144, -0.56716323646760}, {-0.72929675029275, -0.98008272727324}, +{ 0.75622801399036, 0.20950329995549}, { 0.07069442601050, -0.78247898470706}, +{ 0.74496252926055, -0.91169004445807}, {-0.96440182703856, -0.94739918296622}, +{ 0.30424629369539, -0.49438267012479}, { 0.66565033746925, 0.64652935542491}, +{ 0.91697008020594, 0.17514097332009}, {-0.70774918760427, 0.52548653416543}, +{-0.70051415345560, -0.45340028808763}, {-0.99496513054797, -0.90071908066973}, +{ 0.98164490790123, -0.77463155528697}, {-0.54671580548181, -0.02570928536004}, +{-0.01689629065389, 0.00287506445732}, {-0.86110349531986, 0.42548583726477}, +{-0.98892980586032, -0.87881132267556}, { 0.51756627678691, 0.66926784710139}, +{-0.99635026409640, -0.58107730574765}, {-0.99969370862163, 0.98369989360250}, +{ 0.55266258627194, 0.59449057465591}, { 0.34581177741673, 0.94879421061866}, +{ 0.62664209577999, -0.74402970906471}, {-0.77149701404973, -0.33883658042801}, +{-0.91592244254432, 0.03687901376713}, {-0.76285492357887, -0.91371867919124}, +{ 0.79788337195331, -0.93180971199849}, { 0.54473080610200, -0.11919206037186}, +{-0.85639281671058, 0.42429854760451}, {-0.92882402971423, 0.27871809078609}, +{-0.11708371046774, -0.99800843444966}, { 0.21356749817493, -0.90716295627033}, +{-0.76191692573909, 0.99768118356265}, { 0.98111043100884, -0.95854459734407}, +{-0.85913269895572, 0.95766566168880}, {-0.93307242253692, 0.49431757696466}, +{ 0.30485754879632, -0.70540034357529}, { 0.85289650925190, 0.46766131791044}, +{ 0.91328082618125, -0.99839597361769}, {-0.05890199924154, 0.70741827819497}, +{ 0.28398686150148, 0.34633555702188}, { 0.95258164539612, -0.54893416026939}, +{-0.78566324168507, -0.75568541079691}, {-0.95789495447877, -0.20423194696966}, +{ 0.82411158711197, 0.96654618432562}, {-0.65185446735885, -0.88734990773289}, +{-0.93643603134666, 0.99870790442385}, { 0.91427159529618, -0.98290505544444}, +{-0.70395684036886, 0.58796798221039}, { 0.00563771969365, 0.61768196727244}, +{ 0.89065051931895, 0.52783352697585}, {-0.68683707712762, 0.80806944710339}, +{ 0.72165342518718, -0.69259857349564}, {-0.62928247730667, 0.13627037407335}, +{ 0.29938434065514, -0.46051329682246}, {-0.91781958879280, -0.74012716684186}, +{ 0.99298717043688, 0.40816610075661}, { 0.82368298622748, -0.74036047190173}, +{-0.98512833386833, -0.99972330709594}, {-0.95915368242257, -0.99237800466040}, +{-0.21411126572790, -0.93424819052545}, {-0.68821476106884, -0.26892306315457}, +{ 0.91851997982317, 0.09358228901785}, {-0.96062769559127, 0.36099095133739}, +{ 0.51646184922287, -0.71373332873917}, { 0.61130721139669, 0.46950141175917}, +{ 0.47336129371299, -0.27333178296162}, { 0.90998308703519, 0.96715662938132}, +{ 0.44844799194357, 0.99211574628306}, { 0.66614891079092, 0.96590176169121}, +{ 0.74922239129237, -0.89879858826087}, {-0.99571588506485, 0.52785521494349}, +{ 0.97401082477563, -0.16855870075190}, { 0.72683747733879, -0.48060774432251}, +{ 0.95432193457128, 0.68849603408441}, {-0.72962208425191, -0.76608443420917}, +{-0.85359479233537, 0.88738125901579}, {-0.81412430338535, -0.97480768049637}, +{-0.87930772356786, 0.74748307690436}, {-0.71573331064977, -0.98570608178923}, +{ 0.83524300028228, 0.83702537075163}, {-0.48086065601423, -0.98848504923531}, +{ 0.97139128574778, 0.80093621198236}, { 0.51992825347895, 0.80247631400510}, +{-0.00848591195325, -0.76670128000486}, {-0.70294374303036, 0.55359910445577}, +{-0.95894428168140, -0.43265504344783}, { 0.97079252950321, 0.09325857238682}, +{-0.92404293670797, 0.85507704027855}, {-0.69506469500450, 0.98633412625459}, +{ 0.26559203620024, 0.73314307966524}, { 0.28038443336943, 0.14537913654427}, +{-0.74138124825523, 0.99310339807762}, {-0.01752795995444, -0.82616635284178}, +{-0.55126773094930, -0.98898543862153}, { 0.97960898850996, -0.94021446752851}, +{-0.99196309146936, 0.67019017358456}, {-0.67684928085260, 0.12631491649378}, +{ 0.09140039465500, -0.20537731453108}, {-0.71658965751996, -0.97788200391224}, +{ 0.81014640078925, 0.53722648362443}, { 0.40616991671205, -0.26469008598449}, +{-0.67680188682972, 0.94502052337695}, { 0.86849774348749, -0.18333598647899}, +{-0.99500381284851, -0.02634122068550}, { 0.84329189340667, 0.10406957462213}, +{-0.09215968531446, 0.69540012101253}, { 0.99956173327206, -0.12358542001404}, +{-0.79732779473535, -0.91582524736159}, { 0.96349973642406, 0.96640458041000}, +{-0.79942778496547, 0.64323902822857}, {-0.11566039853896, 0.28587846253726}, +{-0.39922954514662, 0.94129601616966}, { 0.99089197565987, -0.92062625581587}, +{ 0.28631285179909, -0.91035047143603}, {-0.83302725605608, -0.67330410892084}, +{ 0.95404443402072, 0.49162765398743}, {-0.06449863579434, 0.03250560813135}, +{-0.99575054486311, 0.42389784469507}, {-0.65501142790847, 0.82546114655624}, +{-0.81254441908887, -0.51627234660629}, {-0.99646369485481, 0.84490533520752}, +{ 0.00287840603348, 0.64768261158166}, { 0.70176989408455, -0.20453028573322}, +{ 0.96361882270190, 0.40706967140989}, {-0.68883758192426, 0.91338958840772}, +{-0.34875585502238, 0.71472290693300}, { 0.91980081243087, 0.66507455644919}, +{-0.99009048343881, 0.85868021604848}, { 0.68865791458395, 0.55660316809678}, +{-0.99484402129368, -0.20052559254934}, { 0.94214511408023, -0.99696425367461}, +{-0.67414626793544, 0.49548221180078}, {-0.47339353684664, -0.85904328834047}, +{ 0.14323651387360, -0.94145598222488}, {-0.29268293575672, 0.05759224927952}, +{ 0.43793861458754, -0.78904969892724}, {-0.36345126374441, 0.64874435357162}, +{-0.08750604656825, 0.97686944362527}, {-0.96495267812511, -0.53960305946511}, +{ 0.55526940659947, 0.78891523734774}, { 0.73538215752630, 0.96452072373404}, +{-0.30889773919437, -0.80664389776860}, { 0.03574995626194, -0.97325616900959}, +{ 0.98720684660488, 0.48409133691962}, {-0.81689296271203, -0.90827703628298}, +{ 0.67866860118215, 0.81284503870856}, {-0.15808569732583, 0.85279555024382}, +{ 0.80723395114371, -0.24717418514605}, { 0.47788757329038, -0.46333147839295}, +{ 0.96367554763201, 0.38486749303242}, {-0.99143875716818, -0.24945277239809}, +{ 0.83081876925833, -0.94780851414763}, {-0.58753191905341, 0.01290772389163}, +{ 0.95538108220960, -0.85557052096538}, {-0.96490920476211, -0.64020970923102}, +{-0.97327101028521, 0.12378128133110}, { 0.91400366022124, 0.57972471346930}, +{-0.99925837363824, 0.71084847864067}, {-0.86875903507313, -0.20291699203564}, +{-0.26240034795124, -0.68264554369108}, {-0.24664412953388, -0.87642273115183}, +{ 0.02416275806869, 0.27192914288905}, { 0.82068619590515, -0.85087787994476}, +{ 0.88547373760759, -0.89636802901469}, {-0.18173078152226, -0.26152145156800}, +{ 0.09355476558534, 0.54845123045604}, {-0.54668414224090, 0.95980774020221}, +{ 0.37050990604091, -0.59910140383171}, {-0.70373594262891, 0.91227665827081}, +{-0.34600785879594, -0.99441426144200}, {-0.68774481731008, -0.30238837956299}, +{-0.26843291251234, 0.83115668004362}, { 0.49072334613242, -0.45359708737775}, +{ 0.38975993093975, 0.95515358099121}, {-0.97757125224150, 0.05305894580606}, +{-0.17325552859616, -0.92770672250494}, { 0.99948035025744, 0.58285545563426}, +{-0.64946246527458, 0.68645507104960}, {-0.12016920576437, -0.57147322153312}, +{-0.58947456517751, -0.34847132454388}, {-0.41815140454465, 0.16276422358861}, +{ 0.99885650204884, 0.11136095490444}, {-0.56649614128386, -0.90494866361587}, +{ 0.94138021032330, 0.35281916733018}, {-0.75725076534641, 0.53650549640587}, +{ 0.20541973692630, -0.94435144369918}, { 0.99980371023351, 0.79835913565599}, +{ 0.29078277605775, 0.35393777921520}, {-0.62858772103030, 0.38765693387102}, +{ 0.43440904467688, -0.98546330463232}, {-0.98298583762390, 0.21021524625209}, +{ 0.19513029146934, -0.94239832251867}, {-0.95476662400101, 0.98364554179143}, +{ 0.93379635304810, -0.70881994583682}, {-0.85235410573336, -0.08342347966410}, +{-0.86425093011245, -0.45795025029466}, { 0.38879779059045, 0.97274429344593}, +{ 0.92045124735495, -0.62433652524220}, { 0.89162532251878, 0.54950955570563}, +{-0.36834336949252, 0.96458298020975}, { 0.93891760988045, -0.89968353740388}, +{ 0.99267657565094, -0.03757034316958}, {-0.94063471614176, 0.41332338538963}, +{ 0.99740224117019, -0.16830494996370}, {-0.35899413170555, -0.46633226649613}, +{ 0.05237237274947, -0.25640361602661}, { 0.36703583957424, -0.38653265641875}, +{ 0.91653180367913, -0.30587628726597}, { 0.69000803499316, 0.90952171386132}, +{-0.38658751133527, 0.99501571208985}, {-0.29250814029851, 0.37444994344615}, +{-0.60182204677608, 0.86779651036123}, {-0.97418588163217, 0.96468523666475}, +{ 0.88461574003963, 0.57508405276414}, { 0.05198933055162, 0.21269661669964}, +{-0.53499621979720, 0.97241553731237}, {-0.49429560226497, 0.98183865291903}, +{-0.98935142339139, -0.40249159006933}, {-0.98081380091130, -0.72856895534041}, +{-0.27338148835532, 0.99950922447209}, { 0.06310802338302, -0.54539587529618}, +{-0.20461677199539, -0.14209977628489}, { 0.66223843141647, 0.72528579940326}, +{-0.84764345483665, 0.02372316801261}, {-0.89039863483811, 0.88866581484602}, +{ 0.95903308477986, 0.76744927173873}, { 0.73504123909879, -0.03747203173192}, +{-0.31744434966056, -0.36834111883652}, {-0.34110827591623, 0.40211222807691}, +{ 0.47803883714199, -0.39423219786288}, { 0.98299195879514, 0.01989791390047}, +{-0.30963073129751, -0.18076720599336}, { 0.99992588229018, -0.26281872094289}, +{-0.93149731080767, -0.98313162570490}, { 0.99923472302773, -0.80142993767554}, +{-0.26024169633417, -0.75999759855752}, {-0.35712514743563, 0.19298963768574}, +{-0.99899084509530, 0.74645156992493}, { 0.86557171579452, 0.55593866696299}, +{ 0.33408042438752, 0.86185953874709}, { 0.99010736374716, 0.04602397576623}, +{-0.66694269691195, -0.91643611810148}, { 0.64016792079480, 0.15649530836856}, +{ 0.99570534804836, 0.45844586038111}, {-0.63431466947340, 0.21079116459234}, +{-0.07706847005931, -0.89581437101329}, { 0.98590090577724, 0.88241721133981}, +{ 0.80099335254678, -0.36851896710853}, { 0.78368131392666, 0.45506999802597}, +{ 0.08707806671691, 0.80938994918745}, {-0.86811883080712, 0.39347308654705}, +{-0.39466529740375, -0.66809432114456}, { 0.97875325649683, -0.72467840967746}, +{-0.95038560288864, 0.89563219587625}, { 0.17005239424212, 0.54683053962658}, +{-0.76910792026848, -0.96226617549298}, { 0.99743281016846, 0.42697157037567}, +{ 0.95437383549973, 0.97002324109952}, { 0.99578905365569, -0.54106826257356}, +{ 0.28058259829990, -0.85361420634036}, { 0.85256524470573, -0.64567607735589}, +{-0.50608540105128, -0.65846015480300}, {-0.97210735183243, -0.23095213067791}, +{ 0.95424048234441, -0.99240147091219}, {-0.96926570524023, 0.73775654896574}, +{ 0.30872163214726, 0.41514960556126}, {-0.24523839572639, 0.63206633394807}, +{-0.33813265086024, -0.38661779441897}, {-0.05826828420146, -0.06940774188029}, +{-0.22898461455054, 0.97054853316316}, {-0.18509915019881, 0.47565762892084}, +{-0.10488238045009, -0.87769947402394}, {-0.71886586182037, 0.78030982480538}, +{ 0.99793873738654, 0.90041310491497}, { 0.57563307626120, -0.91034337352097}, +{ 0.28909646383717, 0.96307783970534}, { 0.42188998312520, 0.48148651230437}, +{ 0.93335049681047, -0.43537023883588}, {-0.97087374418267, 0.86636445711364}, +{ 0.36722871286923, 0.65291654172961}, {-0.81093025665696, 0.08778370229363}, +{-0.26240603062237, -0.92774095379098}, { 0.83996497984604, 0.55839849139647}, +{-0.99909615720225, -0.96024605713970}, { 0.74649464155061, 0.12144893606462}, +{-0.74774595569805, -0.26898062008959}, { 0.95781667469567, -0.79047927052628}, +{ 0.95472308713099, -0.08588776019550}, { 0.48708332746299, 0.99999041579432}, +{ 0.46332038247497, 0.10964126185063}, {-0.76497004940162, 0.89210929242238}, +{ 0.57397389364339, 0.35289703373760}, { 0.75374316974495, 0.96705214651335}, +{-0.59174397685714, -0.89405370422752}, { 0.75087906691890, -0.29612672982396}, +{-0.98607857336230, 0.25034911730023}, {-0.40761056640505, -0.90045573444695}, +{ 0.66929266740477, 0.98629493401748}, {-0.97463695257310, -0.00190223301301}, +{ 0.90145509409859, 0.99781390365446}, {-0.87259289048043, 0.99233587353666}, +{-0.91529461447692, -0.15698707534206}, {-0.03305738840705, -0.37205262859764}, +{ 0.07223051368337, -0.88805001733626}, { 0.99498012188353, 0.97094358113387}, +{-0.74904939500519, 0.99985483641521}, { 0.04585228574211, 0.99812337444082}, +{-0.89054954257993, -0.31791913188064}, {-0.83782144651251, 0.97637632547466}, +{ 0.33454804933804, -0.86231516800408}, {-0.99707579362824, 0.93237990079441}, +{-0.22827527843994, 0.18874759397997}, { 0.67248046289143, -0.03646211390569}, +{-0.05146538187944, -0.92599700120679}, { 0.99947295749905, 0.93625229707912}, +{ 0.66951124390363, 0.98905825623893}, {-0.99602956559179, -0.44654715757688}, +{ 0.82104905483590, 0.99540741724928}, { 0.99186510988782, 0.72023001312947}, +{-0.65284592392918, 0.52186723253637}, { 0.93885443798188, -0.74895312615259}, +{ 0.96735248738388, 0.90891816978629}, {-0.22225968841114, 0.57124029781228}, +{-0.44132783753414, -0.92688840659280}, {-0.85694974219574, 0.88844532719844}, +{ 0.91783042091762, -0.46356892383970}, { 0.72556974415690, -0.99899555770747}, +{-0.99711581834508, 0.58211560180426}, { 0.77638976371966, 0.94321834873819}, +{ 0.07717324253925, 0.58638399856595}, {-0.56049829194163, 0.82522301569036}, +{ 0.98398893639988, 0.39467440420569}, { 0.47546946844938, 0.68613044836811}, +{ 0.65675089314631, 0.18331637134880}, { 0.03273375457980, -0.74933109564108}, +{-0.38684144784738, 0.51337349030406}, {-0.97346267944545, -0.96549364384098}, +{-0.53282156061942, -0.91423265091354}, { 0.99817310731176, 0.61133572482148}, +{-0.50254500772635, -0.88829338134294}, { 0.01995873238855, 0.85223515096765}, +{ 0.99930381973804, 0.94578896296649}, { 0.82907767600783, -0.06323442598128}, +{-0.58660709669728, 0.96840773806582}, {-0.17573736667267, -0.48166920859485}, +{ 0.83434292401346, -0.13023450646997}, { 0.05946491307025, 0.20511047074866}, +{ 0.81505484574602, -0.94685947861369}, {-0.44976380954860, 0.40894572671545}, +{-0.89746474625671, 0.99846578838537}, { 0.39677256130792, -0.74854668609359}, +{-0.07588948563079, 0.74096214084170}, { 0.76343198951445, 0.41746629422634}, +{-0.74490104699626, 0.94725911744610}, { 0.64880119792759, 0.41336660830571}, +{ 0.62319537462542, -0.93098313552599}, { 0.42215817594807, -0.07712787385208}, +{ 0.02704554141885, -0.05417518053666}, { 0.80001773566818, 0.91542195141039}, +{-0.79351832348816, -0.36208897989136}, { 0.63872359151636, 0.08128252493444}, +{ 0.52890520960295, 0.60048872455592}, { 0.74238552914587, 0.04491915291044}, +{ 0.99096131449250, -0.19451182854402}, {-0.80412329643109, -0.88513818199457}, +{-0.64612616129736, 0.72198674804544}, { 0.11657770663191, -0.83662833815041}, +{-0.95053182488101, -0.96939905138082}, {-0.62228872928622, 0.82767262846661}, +{ 0.03004475787316, -0.99738896333384}, {-0.97987214341034, 0.36526129686425}, +{-0.99986980746200, -0.36021610299715}, { 0.89110648599879, -0.97894250343044}, +{ 0.10407960510582, 0.77357793811619}, { 0.95964737821728, -0.35435818285502}, +{ 0.50843233159162, 0.96107691266205}, { 0.17006334670615, -0.76854025314829}, +{ 0.25872675063360, 0.99893303933816}, {-0.01115998681937, 0.98496019742444}, +{-0.79598702973261, 0.97138411318894}, {-0.99264708948101, -0.99542822402536}, +{-0.99829663752818, 0.01877138824311}, {-0.70801016548184, 0.33680685948117}, +{-0.70467057786826, 0.93272777501857}, { 0.99846021905254, -0.98725746254433}, +{-0.63364968534650, -0.16473594423746}, {-0.16258217500792, -0.95939125400802}, +{-0.43645594360633, -0.94805030113284}, {-0.99848471702976, 0.96245166923809}, +{-0.16796458968998, -0.98987511890470}, {-0.87979225745213, -0.71725725041680}, +{ 0.44183099021786, -0.93568974498761}, { 0.93310180125532, -0.99913308068246}, +{-0.93941931782002, -0.56409379640356}, {-0.88590003188677, 0.47624600491382}, +{ 0.99971463703691, -0.83889954253462}, {-0.75376385639978, 0.00814643438625}, +{ 0.93887685615875, -0.11284528204636}, { 0.85126435782309, 0.52349251543547}, +{ 0.39701421446381, 0.81779634174316}, {-0.37024464187437, -0.87071656222959}, +{-0.36024828242896, 0.34655735648287}, {-0.93388812549209, -0.84476541096429}, +{-0.65298804552119, -0.18439575450921}, { 0.11960319006843, 0.99899346780168}, +{ 0.94292565553160, 0.83163906518293}, { 0.75081145286948, -0.35533223142265}, +{ 0.56721979748394, -0.24076836414499}, { 0.46857766746029, -0.30140233457198}, +{ 0.97312313923635, -0.99548191630031}, {-0.38299976567017, 0.98516909715427}, +{ 0.41025800019463, 0.02116736935734}, { 0.09638062008048, 0.04411984381457}, +{-0.85283249275397, 0.91475563922421}, { 0.88866808958124, -0.99735267083226}, +{-0.48202429536989, -0.96805608884164}, { 0.27572582416567, 0.58634753335832}, +{-0.65889129659168, 0.58835634138583}, { 0.98838086953732, 0.99994349600236}, +{-0.20651349620689, 0.54593044066355}, {-0.62126416356920, -0.59893681700392}, +{ 0.20320105410437, -0.86879180355289}, {-0.97790548600584, 0.96290806999242}, +{ 0.11112534735126, 0.21484763313301}, {-0.41368337314182, 0.28216837680365}, +{ 0.24133038992960, 0.51294362630238}, {-0.66393410674885, -0.08249679629081}, +{-0.53697829178752, -0.97649903936228}, {-0.97224737889348, 0.22081333579837}, +{ 0.87392477144549, -0.12796173740361}, { 0.19050361015753, 0.01602615387195}, +{-0.46353441212724, -0.95249041539006}, {-0.07064096339021, -0.94479803205886}, +{-0.92444085484466, -0.10457590187436}, {-0.83822593578728, -0.01695043208885}, +{ 0.75214681811150, -0.99955681042665}, {-0.42102998829339, 0.99720941999394}, +{-0.72094786237696, -0.35008961934255}, { 0.78843311019251, 0.52851398958271}, +{ 0.97394027897442, -0.26695944086561}, { 0.99206463477946, -0.57010120849429}, +{ 0.76789609461795, -0.76519356730966}, {-0.82002421836409, -0.73530179553767}, +{ 0.81924990025724, 0.99698425250579}, {-0.26719850873357, 0.68903369776193}, +{-0.43311260380975, 0.85321815947490}, { 0.99194979673836, 0.91876249766422}, +{-0.80692001248487, -0.32627540663214}, { 0.43080003649976, -0.21919095636638}, +{ 0.67709491937357, -0.95478075822906}, { 0.56151770568316, -0.70693811747778}, +{ 0.10831862810749, -0.08628837174592}, { 0.91229417540436, -0.65987351408410}, +{-0.48972893932274, 0.56289246362686}, {-0.89033658689697, -0.71656563987082}, +{ 0.65269447475094, 0.65916004833932}, { 0.67439478141121, -0.81684380846796}, +{-0.47770832416973, -0.16789556203025}, {-0.99715979260878, -0.93565784007648}, +{-0.90889593602546, 0.62034397054380}, {-0.06618622548177, -0.23812217221359}, +{ 0.99430266919728, 0.18812555317553}, { 0.97686402381843, -0.28664534366620}, +{ 0.94813650221268, -0.97506640027128}, {-0.95434497492853, -0.79607978501983}, +{-0.49104783137150, 0.32895214359663}, { 0.99881175120751, 0.88993983831354}, +{ 0.50449166760303, -0.85995072408434}, { 0.47162891065108, -0.18680204049569}, +{-0.62081581361840, 0.75000676218956}, {-0.43867015250812, 0.99998069244322}, +{ 0.98630563232075, -0.53578899600662}, {-0.61510362277374, -0.89515019899997}, +{-0.03841517601843, -0.69888815681179}, {-0.30102157304644, -0.07667808922205}, +{ 0.41881284182683, 0.02188098922282}, {-0.86135454941237, 0.98947480909359}, +{ 0.67226861393788, -0.13494389011014}, {-0.70737398842068, -0.76547349325992}, +{ 0.94044946687963, 0.09026201157416}, {-0.82386352534327, 0.08924768823676}, +{-0.32070666698656, 0.50143421908753}, { 0.57593163224487, -0.98966422921509}, +{-0.36326018419965, 0.07440243123228}, { 0.99979044674350, -0.14130287347405}, +{-0.92366023326932, -0.97979298068180}, {-0.44607178518598, -0.54233252016394}, +{ 0.44226800932956, 0.71326756742752}, { 0.03671907158312, 0.63606389366675}, +{ 0.52175424682195, -0.85396826735705}, {-0.94701139690956, -0.01826348194255}, +{-0.98759606946049, 0.82288714303073}, { 0.87434794743625, 0.89399495655433}, +{-0.93412041758744, 0.41374052024363}, { 0.96063943315511, 0.93116709541280}, +{ 0.97534253457837, 0.86150930812689}, { 0.99642466504163, 0.70190043427512}, +{-0.94705089665984, -0.29580042814306}, { 0.91599807087376, -0.98147830385781}, +{-0.99948153278296, -0.59483417516607}, { 0.97113454393991, -0.67528515225647}, +}; + +#endif /* AVCODEC_AACSBRDATA_H */ diff --git a/ffmpeg/libavcodec/aactab.c b/ffmpeg/libavcodec/aactab.c new file mode 100644 index 0000000..6cbb8c4 --- /dev/null +++ b/ffmpeg/libavcodec/aactab.c @@ -0,0 +1,1207 @@ +/* + * AAC data + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * + * 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 + */ + +/** + * @file + * AAC data + * @author Oded Shimon ( ods15 ods15 dyndns org ) + * @author Maxim Gavrilov ( maxim.gavrilov gmail com ) + */ + +#include "libavutil/mem.h" +#include "aac.h" +#include "aac_tablegen.h" + +#include + +DECLARE_ALIGNED(32, float, ff_aac_kbd_long_1024)[1024]; +DECLARE_ALIGNED(32, float, ff_aac_kbd_short_128)[128]; + +const uint8_t ff_aac_num_swb_1024[] = { + 41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40, 40 +}; + +const uint8_t ff_aac_num_swb_128[] = { + 12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15 +}; + +const uint8_t ff_aac_pred_sfb_max[] = { + 33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34, 34 +}; + +const uint32_t ff_aac_scalefactor_code[121] = { + 0x3ffe8, 0x3ffe6, 0x3ffe7, 0x3ffe5, 0x7fff5, 0x7fff1, 0x7ffed, 0x7fff6, + 0x7ffee, 0x7ffef, 0x7fff0, 0x7fffc, 0x7fffd, 0x7ffff, 0x7fffe, 0x7fff7, + 0x7fff8, 0x7fffb, 0x7fff9, 0x3ffe4, 0x7fffa, 0x3ffe3, 0x1ffef, 0x1fff0, + 0x0fff5, 0x1ffee, 0x0fff2, 0x0fff3, 0x0fff4, 0x0fff1, 0x07ff6, 0x07ff7, + 0x03ff9, 0x03ff5, 0x03ff7, 0x03ff3, 0x03ff6, 0x03ff2, 0x01ff7, 0x01ff5, + 0x00ff9, 0x00ff7, 0x00ff6, 0x007f9, 0x00ff4, 0x007f8, 0x003f9, 0x003f7, + 0x003f5, 0x001f8, 0x001f7, 0x000fa, 0x000f8, 0x000f6, 0x00079, 0x0003a, + 0x00038, 0x0001a, 0x0000b, 0x00004, 0x00000, 0x0000a, 0x0000c, 0x0001b, + 0x00039, 0x0003b, 0x00078, 0x0007a, 0x000f7, 0x000f9, 0x001f6, 0x001f9, + 0x003f4, 0x003f6, 0x003f8, 0x007f5, 0x007f4, 0x007f6, 0x007f7, 0x00ff5, + 0x00ff8, 0x01ff4, 0x01ff6, 0x01ff8, 0x03ff8, 0x03ff4, 0x0fff0, 0x07ff4, + 0x0fff6, 0x07ff5, 0x3ffe2, 0x7ffd9, 0x7ffda, 0x7ffdb, 0x7ffdc, 0x7ffdd, + 0x7ffde, 0x7ffd8, 0x7ffd2, 0x7ffd3, 0x7ffd4, 0x7ffd5, 0x7ffd6, 0x7fff2, + 0x7ffdf, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb, 0x7ffe6, 0x7ffe0, + 0x7ffe1, 0x7ffe2, 0x7ffe3, 0x7ffe4, 0x7ffe5, 0x7ffd7, 0x7ffec, 0x7fff4, + 0x7fff3, +}; + +const uint8_t ff_aac_scalefactor_bits[121] = { + 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 18, 19, 18, 17, 17, 16, 17, 16, 16, 16, 16, 15, 15, + 14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11, 12, 11, 10, 10, + 10, 9, 9, 8, 8, 8, 7, 6, 6, 5, 4, 3, 1, 4, 4, 5, + 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, + 12, 13, 13, 13, 14, 14, 16, 15, 16, 15, 18, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, +}; + +static const uint16_t codes1[81] = { + 0x7f8, 0x1f1, 0x7fd, 0x3f5, 0x068, 0x3f0, 0x7f7, 0x1ec, + 0x7f5, 0x3f1, 0x072, 0x3f4, 0x074, 0x011, 0x076, 0x1eb, + 0x06c, 0x3f6, 0x7fc, 0x1e1, 0x7f1, 0x1f0, 0x061, 0x1f6, + 0x7f2, 0x1ea, 0x7fb, 0x1f2, 0x069, 0x1ed, 0x077, 0x017, + 0x06f, 0x1e6, 0x064, 0x1e5, 0x067, 0x015, 0x062, 0x012, + 0x000, 0x014, 0x065, 0x016, 0x06d, 0x1e9, 0x063, 0x1e4, + 0x06b, 0x013, 0x071, 0x1e3, 0x070, 0x1f3, 0x7fe, 0x1e7, + 0x7f3, 0x1ef, 0x060, 0x1ee, 0x7f0, 0x1e2, 0x7fa, 0x3f3, + 0x06a, 0x1e8, 0x075, 0x010, 0x073, 0x1f4, 0x06e, 0x3f7, + 0x7f6, 0x1e0, 0x7f9, 0x3f2, 0x066, 0x1f5, 0x7ff, 0x1f7, + 0x7f4, +}; + +static const uint8_t bits1[81] = { + 11, 9, 11, 10, 7, 10, 11, 9, 11, 10, 7, 10, 7, 5, 7, 9, + 7, 10, 11, 9, 11, 9, 7, 9, 11, 9, 11, 9, 7, 9, 7, 5, + 7, 9, 7, 9, 7, 5, 7, 5, 1, 5, 7, 5, 7, 9, 7, 9, + 7, 5, 7, 9, 7, 9, 11, 9, 11, 9, 7, 9, 11, 9, 11, 10, + 7, 9, 7, 5, 7, 9, 7, 10, 11, 9, 11, 10, 7, 9, 11, 9, + 11, +}; + +static const uint16_t codes2[81] = { + 0x1f3, 0x06f, 0x1fd, 0x0eb, 0x023, 0x0ea, 0x1f7, 0x0e8, + 0x1fa, 0x0f2, 0x02d, 0x070, 0x020, 0x006, 0x02b, 0x06e, + 0x028, 0x0e9, 0x1f9, 0x066, 0x0f8, 0x0e7, 0x01b, 0x0f1, + 0x1f4, 0x06b, 0x1f5, 0x0ec, 0x02a, 0x06c, 0x02c, 0x00a, + 0x027, 0x067, 0x01a, 0x0f5, 0x024, 0x008, 0x01f, 0x009, + 0x000, 0x007, 0x01d, 0x00b, 0x030, 0x0ef, 0x01c, 0x064, + 0x01e, 0x00c, 0x029, 0x0f3, 0x02f, 0x0f0, 0x1fc, 0x071, + 0x1f2, 0x0f4, 0x021, 0x0e6, 0x0f7, 0x068, 0x1f8, 0x0ee, + 0x022, 0x065, 0x031, 0x002, 0x026, 0x0ed, 0x025, 0x06a, + 0x1fb, 0x072, 0x1fe, 0x069, 0x02e, 0x0f6, 0x1ff, 0x06d, + 0x1f6, +}; + +static const uint8_t bits2[81] = { + 9, 7, 9, 8, 6, 8, 9, 8, 9, 8, 6, 7, 6, 5, 6, 7, + 6, 8, 9, 7, 8, 8, 6, 8, 9, 7, 9, 8, 6, 7, 6, 5, + 6, 7, 6, 8, 6, 5, 6, 5, 3, 5, 6, 5, 6, 8, 6, 7, + 6, 5, 6, 8, 6, 8, 9, 7, 9, 8, 6, 8, 8, 7, 9, 8, + 6, 7, 6, 4, 6, 8, 6, 7, 9, 7, 9, 7, 6, 8, 9, 7, + 9, +}; + +static const uint16_t codes3[81] = { + 0x0000, 0x0009, 0x00ef, 0x000b, 0x0019, 0x00f0, 0x01eb, 0x01e6, + 0x03f2, 0x000a, 0x0035, 0x01ef, 0x0034, 0x0037, 0x01e9, 0x01ed, + 0x01e7, 0x03f3, 0x01ee, 0x03ed, 0x1ffa, 0x01ec, 0x01f2, 0x07f9, + 0x07f8, 0x03f8, 0x0ff8, 0x0008, 0x0038, 0x03f6, 0x0036, 0x0075, + 0x03f1, 0x03eb, 0x03ec, 0x0ff4, 0x0018, 0x0076, 0x07f4, 0x0039, + 0x0074, 0x03ef, 0x01f3, 0x01f4, 0x07f6, 0x01e8, 0x03ea, 0x1ffc, + 0x00f2, 0x01f1, 0x0ffb, 0x03f5, 0x07f3, 0x0ffc, 0x00ee, 0x03f7, + 0x7ffe, 0x01f0, 0x07f5, 0x7ffd, 0x1ffb, 0x3ffa, 0xffff, 0x00f1, + 0x03f0, 0x3ffc, 0x01ea, 0x03ee, 0x3ffb, 0x0ff6, 0x0ffa, 0x7ffc, + 0x07f2, 0x0ff5, 0xfffe, 0x03f4, 0x07f7, 0x7ffb, 0x0ff7, 0x0ff9, + 0x7ffa, +}; + +static const uint8_t bits3[81] = { + 1, 4, 8, 4, 5, 8, 9, 9, 10, 4, 6, 9, 6, 6, 9, 9, + 9, 10, 9, 10, 13, 9, 9, 11, 11, 10, 12, 4, 6, 10, 6, 7, + 10, 10, 10, 12, 5, 7, 11, 6, 7, 10, 9, 9, 11, 9, 10, 13, + 8, 9, 12, 10, 11, 12, 8, 10, 15, 9, 11, 15, 13, 14, 16, 8, + 10, 14, 9, 10, 14, 12, 12, 15, 11, 12, 16, 10, 11, 15, 12, 12, + 15, +}; + +static const uint16_t codes4[81] = { + 0x007, 0x016, 0x0f6, 0x018, 0x008, 0x0ef, 0x1ef, 0x0f3, + 0x7f8, 0x019, 0x017, 0x0ed, 0x015, 0x001, 0x0e2, 0x0f0, + 0x070, 0x3f0, 0x1ee, 0x0f1, 0x7fa, 0x0ee, 0x0e4, 0x3f2, + 0x7f6, 0x3ef, 0x7fd, 0x005, 0x014, 0x0f2, 0x009, 0x004, + 0x0e5, 0x0f4, 0x0e8, 0x3f4, 0x006, 0x002, 0x0e7, 0x003, + 0x000, 0x06b, 0x0e3, 0x069, 0x1f3, 0x0eb, 0x0e6, 0x3f6, + 0x06e, 0x06a, 0x1f4, 0x3ec, 0x1f0, 0x3f9, 0x0f5, 0x0ec, + 0x7fb, 0x0ea, 0x06f, 0x3f7, 0x7f9, 0x3f3, 0xfff, 0x0e9, + 0x06d, 0x3f8, 0x06c, 0x068, 0x1f5, 0x3ee, 0x1f2, 0x7f4, + 0x7f7, 0x3f1, 0xffe, 0x3ed, 0x1f1, 0x7f5, 0x7fe, 0x3f5, + 0x7fc, +}; + +static const uint8_t bits4[81] = { + 4, 5, 8, 5, 4, 8, 9, 8, 11, 5, 5, 8, 5, 4, 8, 8, + 7, 10, 9, 8, 11, 8, 8, 10, 11, 10, 11, 4, 5, 8, 4, 4, + 8, 8, 8, 10, 4, 4, 8, 4, 4, 7, 8, 7, 9, 8, 8, 10, + 7, 7, 9, 10, 9, 10, 8, 8, 11, 8, 7, 10, 11, 10, 12, 8, + 7, 10, 7, 7, 9, 10, 9, 11, 11, 10, 12, 10, 9, 11, 11, 10, + 11, +}; + +static const uint16_t codes5[81] = { + 0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8, + 0x1ffd, 0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee, + 0x07f2, 0x0ffa, 0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec, + 0x01f0, 0x03ea, 0x07f3, 0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008, + 0x0019, 0x00ee, 0x01ef, 0x07ed, 0x03f0, 0x00f2, 0x0073, 0x000b, + 0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9, 0x07ef, 0x01ee, 0x00ef, + 0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec, 0x07f6, 0x03eb, + 0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7, 0x0ff6, + 0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9, + 0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb, + 0x1ffe, +}; + +static const uint8_t bits5[81] = { + 13, 12, 11, 11, 10, 11, 11, 12, 13, 12, 11, 10, 9, 8, 9, 10, + 11, 12, 12, 10, 9, 8, 7, 8, 9, 10, 11, 11, 9, 8, 5, 4, + 5, 8, 9, 11, 10, 8, 7, 4, 1, 4, 7, 8, 11, 11, 9, 8, + 5, 4, 5, 8, 9, 11, 11, 10, 9, 8, 7, 8, 9, 10, 11, 12, + 11, 10, 9, 8, 9, 10, 11, 12, 13, 12, 12, 11, 10, 10, 11, 12, + 13, +}; + +static const uint16_t codes6[81] = { + 0x7fe, 0x3fd, 0x1f1, 0x1eb, 0x1f4, 0x1ea, 0x1f0, 0x3fc, + 0x7fd, 0x3f6, 0x1e5, 0x0ea, 0x06c, 0x071, 0x068, 0x0f0, + 0x1e6, 0x3f7, 0x1f3, 0x0ef, 0x032, 0x027, 0x028, 0x026, + 0x031, 0x0eb, 0x1f7, 0x1e8, 0x06f, 0x02e, 0x008, 0x004, + 0x006, 0x029, 0x06b, 0x1ee, 0x1ef, 0x072, 0x02d, 0x002, + 0x000, 0x003, 0x02f, 0x073, 0x1fa, 0x1e7, 0x06e, 0x02b, + 0x007, 0x001, 0x005, 0x02c, 0x06d, 0x1ec, 0x1f9, 0x0ee, + 0x030, 0x024, 0x02a, 0x025, 0x033, 0x0ec, 0x1f2, 0x3f8, + 0x1e4, 0x0ed, 0x06a, 0x070, 0x069, 0x074, 0x0f1, 0x3fa, + 0x7ff, 0x3f9, 0x1f6, 0x1ed, 0x1f8, 0x1e9, 0x1f5, 0x3fb, + 0x7fc, +}; + +static const uint8_t bits6[81] = { + 11, 10, 9, 9, 9, 9, 9, 10, 11, 10, 9, 8, 7, 7, 7, 8, + 9, 10, 9, 8, 6, 6, 6, 6, 6, 8, 9, 9, 7, 6, 4, 4, + 4, 6, 7, 9, 9, 7, 6, 4, 4, 4, 6, 7, 9, 9, 7, 6, + 4, 4, 4, 6, 7, 9, 9, 8, 6, 6, 6, 6, 6, 8, 9, 10, + 9, 8, 7, 7, 7, 7, 8, 10, 11, 10, 9, 9, 9, 9, 9, 10, + 11, +}; + +static const uint16_t codes7[64] = { + 0x000, 0x005, 0x037, 0x074, 0x0f2, 0x1eb, 0x3ed, 0x7f7, + 0x004, 0x00c, 0x035, 0x071, 0x0ec, 0x0ee, 0x1ee, 0x1f5, + 0x036, 0x034, 0x072, 0x0ea, 0x0f1, 0x1e9, 0x1f3, 0x3f5, + 0x073, 0x070, 0x0eb, 0x0f0, 0x1f1, 0x1f0, 0x3ec, 0x3fa, + 0x0f3, 0x0ed, 0x1e8, 0x1ef, 0x3ef, 0x3f1, 0x3f9, 0x7fb, + 0x1ed, 0x0ef, 0x1ea, 0x1f2, 0x3f3, 0x3f8, 0x7f9, 0x7fc, + 0x3ee, 0x1ec, 0x1f4, 0x3f4, 0x3f7, 0x7f8, 0xffd, 0xffe, + 0x7f6, 0x3f0, 0x3f2, 0x3f6, 0x7fa, 0x7fd, 0xffc, 0xfff, +}; + +static const uint8_t bits7[64] = { + 1, 3, 6, 7, 8, 9, 10, 11, 3, 4, 6, 7, 8, 8, 9, 9, + 6, 6, 7, 8, 8, 9, 9, 10, 7, 7, 8, 8, 9, 9, 10, 10, + 8, 8, 9, 9, 10, 10, 10, 11, 9, 8, 9, 9, 10, 10, 11, 11, + 10, 9, 9, 10, 10, 11, 12, 12, 11, 10, 10, 10, 11, 11, 12, 12, +}; + +static const uint16_t codes8[64] = { + 0x00e, 0x005, 0x010, 0x030, 0x06f, 0x0f1, 0x1fa, 0x3fe, + 0x003, 0x000, 0x004, 0x012, 0x02c, 0x06a, 0x075, 0x0f8, + 0x00f, 0x002, 0x006, 0x014, 0x02e, 0x069, 0x072, 0x0f5, + 0x02f, 0x011, 0x013, 0x02a, 0x032, 0x06c, 0x0ec, 0x0fa, + 0x071, 0x02b, 0x02d, 0x031, 0x06d, 0x070, 0x0f2, 0x1f9, + 0x0ef, 0x068, 0x033, 0x06b, 0x06e, 0x0ee, 0x0f9, 0x3fc, + 0x1f8, 0x074, 0x073, 0x0ed, 0x0f0, 0x0f6, 0x1f6, 0x1fd, + 0x3fd, 0x0f3, 0x0f4, 0x0f7, 0x1f7, 0x1fb, 0x1fc, 0x3ff, +}; + +static const uint8_t bits8[64] = { + 5, 4, 5, 6, 7, 8, 9, 10, 4, 3, 4, 5, 6, 7, 7, 8, + 5, 4, 4, 5, 6, 7, 7, 8, 6, 5, 5, 6, 6, 7, 8, 8, + 7, 6, 6, 6, 7, 7, 8, 9, 8, 7, 6, 7, 7, 8, 8, 10, + 9, 7, 7, 8, 8, 8, 9, 9, 10, 8, 8, 8, 9, 9, 9, 10, +}; + +static const uint16_t codes9[169] = { + 0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8, + 0x07cd, 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec, 0x0004, 0x000c, 0x0035, + 0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, 0x03e0, 0x07d8, + 0x0fcf, 0x0fd5, 0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1, + 0x03cf, 0x03dd, 0x03db, 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4, 0x00e6, + 0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca, + 0x07de, 0x0fd8, 0x0fea, 0x1fdb, 0x01df, 0x00eb, 0x01dc, 0x01e6, + 0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, 0x0fcd, 0x0fe2, 0x0fe7, + 0x1fe1, 0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db, + 0x0fd2, 0x07e0, 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9, 0x07c4, 0x01e5, + 0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, 0x0fe9, + 0x1fe6, 0x1ff3, 0x1ff7, 0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9, + 0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6, + 0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb, + 0x1fd8, 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2, 0x07e1, 0x03df, 0x07c9, + 0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, 0x1fef, 0x3ff3, + 0x3ff4, 0x3ff5, 0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1, + 0x1fe0, 0x1fe8, 0x1ff0, 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc, 0x0fe8, + 0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5, + 0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe, 0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf, + 0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, 0x3ff7, 0x3ffc, 0x3ffd, + 0x7fff, +}; + +static const uint8_t bits9[169] = { + 1, 3, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 3, 4, 6, + 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 6, 6, 7, 8, 8, 9, + 10, 10, 10, 11, 12, 12, 12, 8, 7, 8, 9, 9, 10, 10, 11, 11, + 11, 12, 12, 13, 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, + 13, 10, 9, 9, 10, 11, 11, 11, 12, 11, 12, 12, 13, 13, 11, 9, + 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 11, 10, 10, 11, 11, + 12, 12, 13, 13, 13, 13, 13, 13, 11, 10, 10, 11, 11, 11, 12, 12, + 13, 13, 14, 13, 14, 11, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14, + 14, 14, 12, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 12, + 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15, 13, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 14, 15, +}; + +static const uint16_t codes10[169] = { + 0x022, 0x008, 0x01d, 0x026, 0x05f, 0x0d3, 0x1cf, 0x3d0, + 0x3d7, 0x3ed, 0x7f0, 0x7f6, 0xffd, 0x007, 0x000, 0x001, + 0x009, 0x020, 0x054, 0x060, 0x0d5, 0x0dc, 0x1d4, 0x3cd, + 0x3de, 0x7e7, 0x01c, 0x002, 0x006, 0x00c, 0x01e, 0x028, + 0x05b, 0x0cd, 0x0d9, 0x1ce, 0x1dc, 0x3d9, 0x3f1, 0x025, + 0x00b, 0x00a, 0x00d, 0x024, 0x057, 0x061, 0x0cc, 0x0dd, + 0x1cc, 0x1de, 0x3d3, 0x3e7, 0x05d, 0x021, 0x01f, 0x023, + 0x027, 0x059, 0x064, 0x0d8, 0x0df, 0x1d2, 0x1e2, 0x3dd, + 0x3ee, 0x0d1, 0x055, 0x029, 0x056, 0x058, 0x062, 0x0ce, + 0x0e0, 0x0e2, 0x1da, 0x3d4, 0x3e3, 0x7eb, 0x1c9, 0x05e, + 0x05a, 0x05c, 0x063, 0x0ca, 0x0da, 0x1c7, 0x1ca, 0x1e0, + 0x3db, 0x3e8, 0x7ec, 0x1e3, 0x0d2, 0x0cb, 0x0d0, 0x0d7, + 0x0db, 0x1c6, 0x1d5, 0x1d8, 0x3ca, 0x3da, 0x7ea, 0x7f1, + 0x1e1, 0x0d4, 0x0cf, 0x0d6, 0x0de, 0x0e1, 0x1d0, 0x1d6, + 0x3d1, 0x3d5, 0x3f2, 0x7ee, 0x7fb, 0x3e9, 0x1cd, 0x1c8, + 0x1cb, 0x1d1, 0x1d7, 0x1df, 0x3cf, 0x3e0, 0x3ef, 0x7e6, + 0x7f8, 0xffa, 0x3eb, 0x1dd, 0x1d3, 0x1d9, 0x1db, 0x3d2, + 0x3cc, 0x3dc, 0x3ea, 0x7ed, 0x7f3, 0x7f9, 0xff9, 0x7f2, + 0x3ce, 0x1e4, 0x3cb, 0x3d8, 0x3d6, 0x3e2, 0x3e5, 0x7e8, + 0x7f4, 0x7f5, 0x7f7, 0xffb, 0x7fa, 0x3ec, 0x3df, 0x3e1, + 0x3e4, 0x3e6, 0x3f0, 0x7e9, 0x7ef, 0xff8, 0xffe, 0xffc, + 0xfff, +}; + +static const uint8_t bits10[169] = { + 6, 5, 6, 6, 7, 8, 9, 10, 10, 10, 11, 11, 12, 5, 4, 4, + 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 6, 4, 5, 5, 6, 6, + 7, 8, 8, 9, 9, 10, 10, 6, 5, 5, 5, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 7, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, + 10, 8, 7, 6, 7, 7, 7, 8, 8, 8, 9, 10, 10, 11, 9, 7, + 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 9, 8, 8, 8, 8, + 8, 9, 9, 9, 10, 10, 11, 11, 9, 8, 8, 8, 8, 8, 9, 9, + 10, 10, 10, 11, 11, 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11, + 11, 12, 10, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 11, + 10, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 11, 10, 10, 10, + 10, 10, 10, 11, 11, 12, 12, 12, 12, +}; + +static const uint16_t codes11[289] = { + 0x000, 0x006, 0x019, 0x03d, 0x09c, 0x0c6, 0x1a7, 0x390, + 0x3c2, 0x3df, 0x7e6, 0x7f3, 0xffb, 0x7ec, 0xffa, 0xffe, + 0x38e, 0x005, 0x001, 0x008, 0x014, 0x037, 0x042, 0x092, + 0x0af, 0x191, 0x1a5, 0x1b5, 0x39e, 0x3c0, 0x3a2, 0x3cd, + 0x7d6, 0x0ae, 0x017, 0x007, 0x009, 0x018, 0x039, 0x040, + 0x08e, 0x0a3, 0x0b8, 0x199, 0x1ac, 0x1c1, 0x3b1, 0x396, + 0x3be, 0x3ca, 0x09d, 0x03c, 0x015, 0x016, 0x01a, 0x03b, + 0x044, 0x091, 0x0a5, 0x0be, 0x196, 0x1ae, 0x1b9, 0x3a1, + 0x391, 0x3a5, 0x3d5, 0x094, 0x09a, 0x036, 0x038, 0x03a, + 0x041, 0x08c, 0x09b, 0x0b0, 0x0c3, 0x19e, 0x1ab, 0x1bc, + 0x39f, 0x38f, 0x3a9, 0x3cf, 0x093, 0x0bf, 0x03e, 0x03f, + 0x043, 0x045, 0x09e, 0x0a7, 0x0b9, 0x194, 0x1a2, 0x1ba, + 0x1c3, 0x3a6, 0x3a7, 0x3bb, 0x3d4, 0x09f, 0x1a0, 0x08f, + 0x08d, 0x090, 0x098, 0x0a6, 0x0b6, 0x0c4, 0x19f, 0x1af, + 0x1bf, 0x399, 0x3bf, 0x3b4, 0x3c9, 0x3e7, 0x0a8, 0x1b6, + 0x0ab, 0x0a4, 0x0aa, 0x0b2, 0x0c2, 0x0c5, 0x198, 0x1a4, + 0x1b8, 0x38c, 0x3a4, 0x3c4, 0x3c6, 0x3dd, 0x3e8, 0x0ad, + 0x3af, 0x192, 0x0bd, 0x0bc, 0x18e, 0x197, 0x19a, 0x1a3, + 0x1b1, 0x38d, 0x398, 0x3b7, 0x3d3, 0x3d1, 0x3db, 0x7dd, + 0x0b4, 0x3de, 0x1a9, 0x19b, 0x19c, 0x1a1, 0x1aa, 0x1ad, + 0x1b3, 0x38b, 0x3b2, 0x3b8, 0x3ce, 0x3e1, 0x3e0, 0x7d2, + 0x7e5, 0x0b7, 0x7e3, 0x1bb, 0x1a8, 0x1a6, 0x1b0, 0x1b2, + 0x1b7, 0x39b, 0x39a, 0x3ba, 0x3b5, 0x3d6, 0x7d7, 0x3e4, + 0x7d8, 0x7ea, 0x0ba, 0x7e8, 0x3a0, 0x1bd, 0x1b4, 0x38a, + 0x1c4, 0x392, 0x3aa, 0x3b0, 0x3bc, 0x3d7, 0x7d4, 0x7dc, + 0x7db, 0x7d5, 0x7f0, 0x0c1, 0x7fb, 0x3c8, 0x3a3, 0x395, + 0x39d, 0x3ac, 0x3ae, 0x3c5, 0x3d8, 0x3e2, 0x3e6, 0x7e4, + 0x7e7, 0x7e0, 0x7e9, 0x7f7, 0x190, 0x7f2, 0x393, 0x1be, + 0x1c0, 0x394, 0x397, 0x3ad, 0x3c3, 0x3c1, 0x3d2, 0x7da, + 0x7d9, 0x7df, 0x7eb, 0x7f4, 0x7fa, 0x195, 0x7f8, 0x3bd, + 0x39c, 0x3ab, 0x3a8, 0x3b3, 0x3b9, 0x3d0, 0x3e3, 0x3e5, + 0x7e2, 0x7de, 0x7ed, 0x7f1, 0x7f9, 0x7fc, 0x193, 0xffd, + 0x3dc, 0x3b6, 0x3c7, 0x3cc, 0x3cb, 0x3d9, 0x3da, 0x7d3, + 0x7e1, 0x7ee, 0x7ef, 0x7f5, 0x7f6, 0xffc, 0xfff, 0x19d, + 0x1c2, 0x0b5, 0x0a1, 0x096, 0x097, 0x095, 0x099, 0x0a0, + 0x0a2, 0x0ac, 0x0a9, 0x0b1, 0x0b3, 0x0bb, 0x0c0, 0x18f, + 0x004, +}; + +static const uint8_t bits11[289] = { + 4, 5, 6, 7, 8, 8, 9, 10, 10, 10, 11, 11, 12, 11, 12, 12, + 10, 5, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, + 11, 8, 6, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, + 10, 10, 8, 7, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, + 10, 10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9, + 9, 10, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 9, 9, + 9, 10, 10, 10, 10, 10, 10, 8, 10, 9, 8, 8, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 10, 11, 8, 10, 9, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 10, 11, 11, 8, 11, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 11, 10, 11, 11, 8, 11, 10, 9, 9, 10, + 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8, 11, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 9, 11, 10, 9, + 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 11, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 12, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 9, + 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, + 5, +}; + +const uint16_t * const ff_aac_spectral_codes[11] = { + codes1, codes2, codes3, codes4, codes5, codes6, codes7, codes8, + codes9, codes10, codes11, +}; + +const uint8_t * const ff_aac_spectral_bits[11] = { + bits1, bits2, bits3, bits4, bits5, bits6, bits7, bits8, + bits9, bits10, bits11, +}; + +const uint16_t ff_aac_spectral_sizes[11] = { + 81, 81, 81, 81, 81, 81, 64, 64, 169, 169, 289, +}; + +/* NOTE: + * 64.0f is a special value indicating the existence of an escape code in the + * bitstream. + */ +static const DECLARE_ALIGNED(16, float, codebook_vector0)[324] = { + -1.0000000, -1.0000000, -1.0000000, -1.0000000, + -1.0000000, -1.0000000, -1.0000000, 0.0000000, + -1.0000000, -1.0000000, -1.0000000, 1.0000000, + -1.0000000, -1.0000000, 0.0000000, -1.0000000, + -1.0000000, -1.0000000, 0.0000000, 0.0000000, + -1.0000000, -1.0000000, 0.0000000, 1.0000000, + -1.0000000, -1.0000000, 1.0000000, -1.0000000, + -1.0000000, -1.0000000, 1.0000000, 0.0000000, + -1.0000000, -1.0000000, 1.0000000, 1.0000000, + -1.0000000, 0.0000000, -1.0000000, -1.0000000, + -1.0000000, 0.0000000, -1.0000000, 0.0000000, + -1.0000000, 0.0000000, -1.0000000, 1.0000000, + -1.0000000, 0.0000000, 0.0000000, -1.0000000, + -1.0000000, 0.0000000, 0.0000000, 0.0000000, + -1.0000000, 0.0000000, 0.0000000, 1.0000000, + -1.0000000, 0.0000000, 1.0000000, -1.0000000, + -1.0000000, 0.0000000, 1.0000000, 0.0000000, + -1.0000000, 0.0000000, 1.0000000, 1.0000000, + -1.0000000, 1.0000000, -1.0000000, -1.0000000, + -1.0000000, 1.0000000, -1.0000000, 0.0000000, + -1.0000000, 1.0000000, -1.0000000, 1.0000000, + -1.0000000, 1.0000000, 0.0000000, -1.0000000, + -1.0000000, 1.0000000, 0.0000000, 0.0000000, + -1.0000000, 1.0000000, 0.0000000, 1.0000000, + -1.0000000, 1.0000000, 1.0000000, -1.0000000, + -1.0000000, 1.0000000, 1.0000000, 0.0000000, + -1.0000000, 1.0000000, 1.0000000, 1.0000000, + 0.0000000, -1.0000000, -1.0000000, -1.0000000, + 0.0000000, -1.0000000, -1.0000000, 0.0000000, + 0.0000000, -1.0000000, -1.0000000, 1.0000000, + 0.0000000, -1.0000000, 0.0000000, -1.0000000, + 0.0000000, -1.0000000, 0.0000000, 0.0000000, + 0.0000000, -1.0000000, 0.0000000, 1.0000000, + 0.0000000, -1.0000000, 1.0000000, -1.0000000, + 0.0000000, -1.0000000, 1.0000000, 0.0000000, + 0.0000000, -1.0000000, 1.0000000, 1.0000000, + 0.0000000, 0.0000000, -1.0000000, -1.0000000, + 0.0000000, 0.0000000, -1.0000000, 0.0000000, + 0.0000000, 0.0000000, -1.0000000, 1.0000000, + 0.0000000, 0.0000000, 0.0000000, -1.0000000, + 0.0000000, 0.0000000, 0.0000000, 0.0000000, + 0.0000000, 0.0000000, 0.0000000, 1.0000000, + 0.0000000, 0.0000000, 1.0000000, -1.0000000, + 0.0000000, 0.0000000, 1.0000000, 0.0000000, + 0.0000000, 0.0000000, 1.0000000, 1.0000000, + 0.0000000, 1.0000000, -1.0000000, -1.0000000, + 0.0000000, 1.0000000, -1.0000000, 0.0000000, + 0.0000000, 1.0000000, -1.0000000, 1.0000000, + 0.0000000, 1.0000000, 0.0000000, -1.0000000, + 0.0000000, 1.0000000, 0.0000000, 0.0000000, + 0.0000000, 1.0000000, 0.0000000, 1.0000000, + 0.0000000, 1.0000000, 1.0000000, -1.0000000, + 0.0000000, 1.0000000, 1.0000000, 0.0000000, + 0.0000000, 1.0000000, 1.0000000, 1.0000000, + 1.0000000, -1.0000000, -1.0000000, -1.0000000, + 1.0000000, -1.0000000, -1.0000000, 0.0000000, + 1.0000000, -1.0000000, -1.0000000, 1.0000000, + 1.0000000, -1.0000000, 0.0000000, -1.0000000, + 1.0000000, -1.0000000, 0.0000000, 0.0000000, + 1.0000000, -1.0000000, 0.0000000, 1.0000000, + 1.0000000, -1.0000000, 1.0000000, -1.0000000, + 1.0000000, -1.0000000, 1.0000000, 0.0000000, + 1.0000000, -1.0000000, 1.0000000, 1.0000000, + 1.0000000, 0.0000000, -1.0000000, -1.0000000, + 1.0000000, 0.0000000, -1.0000000, 0.0000000, + 1.0000000, 0.0000000, -1.0000000, 1.0000000, + 1.0000000, 0.0000000, 0.0000000, -1.0000000, + 1.0000000, 0.0000000, 0.0000000, 0.0000000, + 1.0000000, 0.0000000, 0.0000000, 1.0000000, + 1.0000000, 0.0000000, 1.0000000, -1.0000000, + 1.0000000, 0.0000000, 1.0000000, 0.0000000, + 1.0000000, 0.0000000, 1.0000000, 1.0000000, + 1.0000000, 1.0000000, -1.0000000, -1.0000000, + 1.0000000, 1.0000000, -1.0000000, 0.0000000, + 1.0000000, 1.0000000, -1.0000000, 1.0000000, + 1.0000000, 1.0000000, 0.0000000, -1.0000000, + 1.0000000, 1.0000000, 0.0000000, 0.0000000, + 1.0000000, 1.0000000, 0.0000000, 1.0000000, + 1.0000000, 1.0000000, 1.0000000, -1.0000000, + 1.0000000, 1.0000000, 1.0000000, 0.0000000, + 1.0000000, 1.0000000, 1.0000000, 1.0000000, +}; + +static const DECLARE_ALIGNED(16, float, codebook_vector2)[324] = { + 0.0000000, 0.0000000, 0.0000000, 0.0000000, + 0.0000000, 0.0000000, 0.0000000, 1.0000000, + 0.0000000, 0.0000000, 0.0000000, 2.5198421, + 0.0000000, 0.0000000, 1.0000000, 0.0000000, + 0.0000000, 0.0000000, 1.0000000, 1.0000000, + 0.0000000, 0.0000000, 1.0000000, 2.5198421, + 0.0000000, 0.0000000, 2.5198421, 0.0000000, + 0.0000000, 0.0000000, 2.5198421, 1.0000000, + 0.0000000, 0.0000000, 2.5198421, 2.5198421, + 0.0000000, 1.0000000, 0.0000000, 0.0000000, + 0.0000000, 1.0000000, 0.0000000, 1.0000000, + 0.0000000, 1.0000000, 0.0000000, 2.5198421, + 0.0000000, 1.0000000, 1.0000000, 0.0000000, + 0.0000000, 1.0000000, 1.0000000, 1.0000000, + 0.0000000, 1.0000000, 1.0000000, 2.5198421, + 0.0000000, 1.0000000, 2.5198421, 0.0000000, + 0.0000000, 1.0000000, 2.5198421, 1.0000000, + 0.0000000, 1.0000000, 2.5198421, 2.5198421, + 0.0000000, 2.5198421, 0.0000000, 0.0000000, + 0.0000000, 2.5198421, 0.0000000, 1.0000000, + 0.0000000, 2.5198421, 0.0000000, 2.5198421, + 0.0000000, 2.5198421, 1.0000000, 0.0000000, + 0.0000000, 2.5198421, 1.0000000, 1.0000000, + 0.0000000, 2.5198421, 1.0000000, 2.5198421, + 0.0000000, 2.5198421, 2.5198421, 0.0000000, + 0.0000000, 2.5198421, 2.5198421, 1.0000000, + 0.0000000, 2.5198421, 2.5198421, 2.5198421, + 1.0000000, 0.0000000, 0.0000000, 0.0000000, + 1.0000000, 0.0000000, 0.0000000, 1.0000000, + 1.0000000, 0.0000000, 0.0000000, 2.5198421, + 1.0000000, 0.0000000, 1.0000000, 0.0000000, + 1.0000000, 0.0000000, 1.0000000, 1.0000000, + 1.0000000, 0.0000000, 1.0000000, 2.5198421, + 1.0000000, 0.0000000, 2.5198421, 0.0000000, + 1.0000000, 0.0000000, 2.5198421, 1.0000000, + 1.0000000, 0.0000000, 2.5198421, 2.5198421, + 1.0000000, 1.0000000, 0.0000000, 0.0000000, + 1.0000000, 1.0000000, 0.0000000, 1.0000000, + 1.0000000, 1.0000000, 0.0000000, 2.5198421, + 1.0000000, 1.0000000, 1.0000000, 0.0000000, + 1.0000000, 1.0000000, 1.0000000, 1.0000000, + 1.0000000, 1.0000000, 1.0000000, 2.5198421, + 1.0000000, 1.0000000, 2.5198421, 0.0000000, + 1.0000000, 1.0000000, 2.5198421, 1.0000000, + 1.0000000, 1.0000000, 2.5198421, 2.5198421, + 1.0000000, 2.5198421, 0.0000000, 0.0000000, + 1.0000000, 2.5198421, 0.0000000, 1.0000000, + 1.0000000, 2.5198421, 0.0000000, 2.5198421, + 1.0000000, 2.5198421, 1.0000000, 0.0000000, + 1.0000000, 2.5198421, 1.0000000, 1.0000000, + 1.0000000, 2.5198421, 1.0000000, 2.5198421, + 1.0000000, 2.5198421, 2.5198421, 0.0000000, + 1.0000000, 2.5198421, 2.5198421, 1.0000000, + 1.0000000, 2.5198421, 2.5198421, 2.5198421, + 2.5198421, 0.0000000, 0.0000000, 0.0000000, + 2.5198421, 0.0000000, 0.0000000, 1.0000000, + 2.5198421, 0.0000000, 0.0000000, 2.5198421, + 2.5198421, 0.0000000, 1.0000000, 0.0000000, + 2.5198421, 0.0000000, 1.0000000, 1.0000000, + 2.5198421, 0.0000000, 1.0000000, 2.5198421, + 2.5198421, 0.0000000, 2.5198421, 0.0000000, + 2.5198421, 0.0000000, 2.5198421, 1.0000000, + 2.5198421, 0.0000000, 2.5198421, 2.5198421, + 2.5198421, 1.0000000, 0.0000000, 0.0000000, + 2.5198421, 1.0000000, 0.0000000, 1.0000000, + 2.5198421, 1.0000000, 0.0000000, 2.5198421, + 2.5198421, 1.0000000, 1.0000000, 0.0000000, + 2.5198421, 1.0000000, 1.0000000, 1.0000000, + 2.5198421, 1.0000000, 1.0000000, 2.5198421, + 2.5198421, 1.0000000, 2.5198421, 0.0000000, + 2.5198421, 1.0000000, 2.5198421, 1.0000000, + 2.5198421, 1.0000000, 2.5198421, 2.5198421, + 2.5198421, 2.5198421, 0.0000000, 0.0000000, + 2.5198421, 2.5198421, 0.0000000, 1.0000000, + 2.5198421, 2.5198421, 0.0000000, 2.5198421, + 2.5198421, 2.5198421, 1.0000000, 0.0000000, + 2.5198421, 2.5198421, 1.0000000, 1.0000000, + 2.5198421, 2.5198421, 1.0000000, 2.5198421, + 2.5198421, 2.5198421, 2.5198421, 0.0000000, + 2.5198421, 2.5198421, 2.5198421, 1.0000000, + 2.5198421, 2.5198421, 2.5198421, 2.5198421, +}; + +static const DECLARE_ALIGNED(16, float, codebook_vector4)[162] = { + -6.3496042, -6.3496042, -6.3496042, -4.3267487, + -6.3496042, -2.5198421, -6.3496042, -1.0000000, + -6.3496042, 0.0000000, -6.3496042, 1.0000000, + -6.3496042, 2.5198421, -6.3496042, 4.3267487, + -6.3496042, 6.3496042, -4.3267487, -6.3496042, + -4.3267487, -4.3267487, -4.3267487, -2.5198421, + -4.3267487, -1.0000000, -4.3267487, 0.0000000, + -4.3267487, 1.0000000, -4.3267487, 2.5198421, + -4.3267487, 4.3267487, -4.3267487, 6.3496042, + -2.5198421, -6.3496042, -2.5198421, -4.3267487, + -2.5198421, -2.5198421, -2.5198421, -1.0000000, + -2.5198421, 0.0000000, -2.5198421, 1.0000000, + -2.5198421, 2.5198421, -2.5198421, 4.3267487, + -2.5198421, 6.3496042, -1.0000000, -6.3496042, + -1.0000000, -4.3267487, -1.0000000, -2.5198421, + -1.0000000, -1.0000000, -1.0000000, 0.0000000, + -1.0000000, 1.0000000, -1.0000000, 2.5198421, + -1.0000000, 4.3267487, -1.0000000, 6.3496042, + 0.0000000, -6.3496042, 0.0000000, -4.3267487, + 0.0000000, -2.5198421, 0.0000000, -1.0000000, + 0.0000000, 0.0000000, 0.0000000, 1.0000000, + 0.0000000, 2.5198421, 0.0000000, 4.3267487, + 0.0000000, 6.3496042, 1.0000000, -6.3496042, + 1.0000000, -4.3267487, 1.0000000, -2.5198421, + 1.0000000, -1.0000000, 1.0000000, 0.0000000, + 1.0000000, 1.0000000, 1.0000000, 2.5198421, + 1.0000000, 4.3267487, 1.0000000, 6.3496042, + 2.5198421, -6.3496042, 2.5198421, -4.3267487, + 2.5198421, -2.5198421, 2.5198421, -1.0000000, + 2.5198421, 0.0000000, 2.5198421, 1.0000000, + 2.5198421, 2.5198421, 2.5198421, 4.3267487, + 2.5198421, 6.3496042, 4.3267487, -6.3496042, + 4.3267487, -4.3267487, 4.3267487, -2.5198421, + 4.3267487, -1.0000000, 4.3267487, 0.0000000, + 4.3267487, 1.0000000, 4.3267487, 2.5198421, + 4.3267487, 4.3267487, 4.3267487, 6.3496042, + 6.3496042, -6.3496042, 6.3496042, -4.3267487, + 6.3496042, -2.5198421, 6.3496042, -1.0000000, + 6.3496042, 0.0000000, 6.3496042, 1.0000000, + 6.3496042, 2.5198421, 6.3496042, 4.3267487, + 6.3496042, 6.3496042, +}; + +static const DECLARE_ALIGNED(16, float, codebook_vector6)[128] = { + 0.0000000, 0.0000000, 0.0000000, 1.0000000, + 0.0000000, 2.5198421, 0.0000000, 4.3267487, + 0.0000000, 6.3496042, 0.0000000, 8.5498797, + 0.0000000, 10.9027236, 0.0000000, 13.3905183, + 1.0000000, 0.0000000, 1.0000000, 1.0000000, + 1.0000000, 2.5198421, 1.0000000, 4.3267487, + 1.0000000, 6.3496042, 1.0000000, 8.5498797, + 1.0000000, 10.9027236, 1.0000000, 13.3905183, + 2.5198421, 0.0000000, 2.5198421, 1.0000000, + 2.5198421, 2.5198421, 2.5198421, 4.3267487, + 2.5198421, 6.3496042, 2.5198421, 8.5498797, + 2.5198421, 10.9027236, 2.5198421, 13.3905183, + 4.3267487, 0.0000000, 4.3267487, 1.0000000, + 4.3267487, 2.5198421, 4.3267487, 4.3267487, + 4.3267487, 6.3496042, 4.3267487, 8.5498797, + 4.3267487, 10.9027236, 4.3267487, 13.3905183, + 6.3496042, 0.0000000, 6.3496042, 1.0000000, + 6.3496042, 2.5198421, 6.3496042, 4.3267487, + 6.3496042, 6.3496042, 6.3496042, 8.5498797, + 6.3496042, 10.9027236, 6.3496042, 13.3905183, + 8.5498797, 0.0000000, 8.5498797, 1.0000000, + 8.5498797, 2.5198421, 8.5498797, 4.3267487, + 8.5498797, 6.3496042, 8.5498797, 8.5498797, + 8.5498797, 10.9027236, 8.5498797, 13.3905183, + 10.9027236, 0.0000000, 10.9027236, 1.0000000, + 10.9027236, 2.5198421, 10.9027236, 4.3267487, + 10.9027236, 6.3496042, 10.9027236, 8.5498797, + 10.9027236, 10.9027236, 10.9027236, 13.3905183, + 13.3905183, 0.0000000, 13.3905183, 1.0000000, + 13.3905183, 2.5198421, 13.3905183, 4.3267487, + 13.3905183, 6.3496042, 13.3905183, 8.5498797, + 13.3905183, 10.9027236, 13.3905183, 13.3905183, +}; + +static const DECLARE_ALIGNED(16, float, codebook_vector8)[338] = { + 0.0000000, 0.0000000, 0.0000000, 1.0000000, + 0.0000000, 2.5198421, 0.0000000, 4.3267487, + 0.0000000, 6.3496042, 0.0000000, 8.5498797, + 0.0000000, 10.9027236, 0.0000000, 13.3905183, + 0.0000000, 16.0000000, 0.0000000, 18.7207544, + 0.0000000, 21.5443469, 0.0000000, 24.4637810, + 0.0000000, 27.4731418, 1.0000000, 0.0000000, + 1.0000000, 1.0000000, 1.0000000, 2.5198421, + 1.0000000, 4.3267487, 1.0000000, 6.3496042, + 1.0000000, 8.5498797, 1.0000000, 10.9027236, + 1.0000000, 13.3905183, 1.0000000, 16.0000000, + 1.0000000, 18.7207544, 1.0000000, 21.5443469, + 1.0000000, 24.4637810, 1.0000000, 27.4731418, + 2.5198421, 0.0000000, 2.5198421, 1.0000000, + 2.5198421, 2.5198421, 2.5198421, 4.3267487, + 2.5198421, 6.3496042, 2.5198421, 8.5498797, + 2.5198421, 10.9027236, 2.5198421, 13.3905183, + 2.5198421, 16.0000000, 2.5198421, 18.7207544, + 2.5198421, 21.5443469, 2.5198421, 24.4637810, + 2.5198421, 27.4731418, 4.3267487, 0.0000000, + 4.3267487, 1.0000000, 4.3267487, 2.5198421, + 4.3267487, 4.3267487, 4.3267487, 6.3496042, + 4.3267487, 8.5498797, 4.3267487, 10.9027236, + 4.3267487, 13.3905183, 4.3267487, 16.0000000, + 4.3267487, 18.7207544, 4.3267487, 21.5443469, + 4.3267487, 24.4637810, 4.3267487, 27.4731418, + 6.3496042, 0.0000000, 6.3496042, 1.0000000, + 6.3496042, 2.5198421, 6.3496042, 4.3267487, + 6.3496042, 6.3496042, 6.3496042, 8.5498797, + 6.3496042, 10.9027236, 6.3496042, 13.3905183, + 6.3496042, 16.0000000, 6.3496042, 18.7207544, + 6.3496042, 21.5443469, 6.3496042, 24.4637810, + 6.3496042, 27.4731418, 8.5498797, 0.0000000, + 8.5498797, 1.0000000, 8.5498797, 2.5198421, + 8.5498797, 4.3267487, 8.5498797, 6.3496042, + 8.5498797, 8.5498797, 8.5498797, 10.9027236, + 8.5498797, 13.3905183, 8.5498797, 16.0000000, + 8.5498797, 18.7207544, 8.5498797, 21.5443469, + 8.5498797, 24.4637810, 8.5498797, 27.4731418, + 10.9027236, 0.0000000, 10.9027236, 1.0000000, + 10.9027236, 2.5198421, 10.9027236, 4.3267487, + 10.9027236, 6.3496042, 10.9027236, 8.5498797, + 10.9027236, 10.9027236, 10.9027236, 13.3905183, + 10.9027236, 16.0000000, 10.9027236, 18.7207544, + 10.9027236, 21.5443469, 10.9027236, 24.4637810, + 10.9027236, 27.4731418, 13.3905183, 0.0000000, + 13.3905183, 1.0000000, 13.3905183, 2.5198421, + 13.3905183, 4.3267487, 13.3905183, 6.3496042, + 13.3905183, 8.5498797, 13.3905183, 10.9027236, + 13.3905183, 13.3905183, 13.3905183, 16.0000000, + 13.3905183, 18.7207544, 13.3905183, 21.5443469, + 13.3905183, 24.4637810, 13.3905183, 27.4731418, + 16.0000000, 0.0000000, 16.0000000, 1.0000000, + 16.0000000, 2.5198421, 16.0000000, 4.3267487, + 16.0000000, 6.3496042, 16.0000000, 8.5498797, + 16.0000000, 10.9027236, 16.0000000, 13.3905183, + 16.0000000, 16.0000000, 16.0000000, 18.7207544, + 16.0000000, 21.5443469, 16.0000000, 24.4637810, + 16.0000000, 27.4731418, 18.7207544, 0.0000000, + 18.7207544, 1.0000000, 18.7207544, 2.5198421, + 18.7207544, 4.3267487, 18.7207544, 6.3496042, + 18.7207544, 8.5498797, 18.7207544, 10.9027236, + 18.7207544, 13.3905183, 18.7207544, 16.0000000, + 18.7207544, 18.7207544, 18.7207544, 21.5443469, + 18.7207544, 24.4637810, 18.7207544, 27.4731418, + 21.5443469, 0.0000000, 21.5443469, 1.0000000, + 21.5443469, 2.5198421, 21.5443469, 4.3267487, + 21.5443469, 6.3496042, 21.5443469, 8.5498797, + 21.5443469, 10.9027236, 21.5443469, 13.3905183, + 21.5443469, 16.0000000, 21.5443469, 18.7207544, + 21.5443469, 21.5443469, 21.5443469, 24.4637810, + 21.5443469, 27.4731418, 24.4637810, 0.0000000, + 24.4637810, 1.0000000, 24.4637810, 2.5198421, + 24.4637810, 4.3267487, 24.4637810, 6.3496042, + 24.4637810, 8.5498797, 24.4637810, 10.9027236, + 24.4637810, 13.3905183, 24.4637810, 16.0000000, + 24.4637810, 18.7207544, 24.4637810, 21.5443469, + 24.4637810, 24.4637810, 24.4637810, 27.4731418, + 27.4731418, 0.0000000, 27.4731418, 1.0000000, + 27.4731418, 2.5198421, 27.4731418, 4.3267487, + 27.4731418, 6.3496042, 27.4731418, 8.5498797, + 27.4731418, 10.9027236, 27.4731418, 13.3905183, + 27.4731418, 16.0000000, 27.4731418, 18.7207544, + 27.4731418, 21.5443469, 27.4731418, 24.4637810, + 27.4731418, 27.4731418, +}; + +static const DECLARE_ALIGNED(16, float, codebook_vector10)[578] = { + 0.0000000, 0.0000000, 0.0000000, 1.0000000, + 0.0000000, 2.5198421, 0.0000000, 4.3267487, + 0.0000000, 6.3496042, 0.0000000, 8.5498797, + 0.0000000, 10.9027236, 0.0000000, 13.3905183, + 0.0000000, 16.0000000, 0.0000000, 18.7207544, + 0.0000000, 21.5443469, 0.0000000, 24.4637810, + 0.0000000, 27.4731418, 0.0000000, 30.5673509, + 0.0000000, 33.7419917, 0.0000000, 36.9931811, + 0.0000000, 64.0f, 1.0000000, 0.0000000, + 1.0000000, 1.0000000, 1.0000000, 2.5198421, + 1.0000000, 4.3267487, 1.0000000, 6.3496042, + 1.0000000, 8.5498797, 1.0000000, 10.9027236, + 1.0000000, 13.3905183, 1.0000000, 16.0000000, + 1.0000000, 18.7207544, 1.0000000, 21.5443469, + 1.0000000, 24.4637810, 1.0000000, 27.4731418, + 1.0000000, 30.5673509, 1.0000000, 33.7419917, + 1.0000000, 36.9931811, 1.0000000, 64.0f, + 2.5198421, 0.0000000, 2.5198421, 1.0000000, + 2.5198421, 2.5198421, 2.5198421, 4.3267487, + 2.5198421, 6.3496042, 2.5198421, 8.5498797, + 2.5198421, 10.9027236, 2.5198421, 13.3905183, + 2.5198421, 16.0000000, 2.5198421, 18.7207544, + 2.5198421, 21.5443469, 2.5198421, 24.4637810, + 2.5198421, 27.4731418, 2.5198421, 30.5673509, + 2.5198421, 33.7419917, 2.5198421, 36.9931811, + 2.5198421, 64.0f, 4.3267487, 0.0000000, + 4.3267487, 1.0000000, 4.3267487, 2.5198421, + 4.3267487, 4.3267487, 4.3267487, 6.3496042, + 4.3267487, 8.5498797, 4.3267487, 10.9027236, + 4.3267487, 13.3905183, 4.3267487, 16.0000000, + 4.3267487, 18.7207544, 4.3267487, 21.5443469, + 4.3267487, 24.4637810, 4.3267487, 27.4731418, + 4.3267487, 30.5673509, 4.3267487, 33.7419917, + 4.3267487, 36.9931811, 4.3267487, 64.0f, + 6.3496042, 0.0000000, 6.3496042, 1.0000000, + 6.3496042, 2.5198421, 6.3496042, 4.3267487, + 6.3496042, 6.3496042, 6.3496042, 8.5498797, + 6.3496042, 10.9027236, 6.3496042, 13.3905183, + 6.3496042, 16.0000000, 6.3496042, 18.7207544, + 6.3496042, 21.5443469, 6.3496042, 24.4637810, + 6.3496042, 27.4731418, 6.3496042, 30.5673509, + 6.3496042, 33.7419917, 6.3496042, 36.9931811, + 6.3496042, 64.0f, 8.5498797, 0.0000000, + 8.5498797, 1.0000000, 8.5498797, 2.5198421, + 8.5498797, 4.3267487, 8.5498797, 6.3496042, + 8.5498797, 8.5498797, 8.5498797, 10.9027236, + 8.5498797, 13.3905183, 8.5498797, 16.0000000, + 8.5498797, 18.7207544, 8.5498797, 21.5443469, + 8.5498797, 24.4637810, 8.5498797, 27.4731418, + 8.5498797, 30.5673509, 8.5498797, 33.7419917, + 8.5498797, 36.9931811, 8.5498797, 64.0f, + 10.9027236, 0.0000000, 10.9027236, 1.0000000, + 10.9027236, 2.5198421, 10.9027236, 4.3267487, + 10.9027236, 6.3496042, 10.9027236, 8.5498797, + 10.9027236, 10.9027236, 10.9027236, 13.3905183, + 10.9027236, 16.0000000, 10.9027236, 18.7207544, + 10.9027236, 21.5443469, 10.9027236, 24.4637810, + 10.9027236, 27.4731418, 10.9027236, 30.5673509, + 10.9027236, 33.7419917, 10.9027236, 36.9931811, + 10.9027236, 64.0f, 13.3905183, 0.0000000, + 13.3905183, 1.0000000, 13.3905183, 2.5198421, + 13.3905183, 4.3267487, 13.3905183, 6.3496042, + 13.3905183, 8.5498797, 13.3905183, 10.9027236, + 13.3905183, 13.3905183, 13.3905183, 16.0000000, + 13.3905183, 18.7207544, 13.3905183, 21.5443469, + 13.3905183, 24.4637810, 13.3905183, 27.4731418, + 13.3905183, 30.5673509, 13.3905183, 33.7419917, + 13.3905183, 36.9931811, 13.3905183, 64.0f, + 16.0000000, 0.0000000, 16.0000000, 1.0000000, + 16.0000000, 2.5198421, 16.0000000, 4.3267487, + 16.0000000, 6.3496042, 16.0000000, 8.5498797, + 16.0000000, 10.9027236, 16.0000000, 13.3905183, + 16.0000000, 16.0000000, 16.0000000, 18.7207544, + 16.0000000, 21.5443469, 16.0000000, 24.4637810, + 16.0000000, 27.4731418, 16.0000000, 30.5673509, + 16.0000000, 33.7419917, 16.0000000, 36.9931811, + 16.0000000, 64.0f, 18.7207544, 0.0000000, + 18.7207544, 1.0000000, 18.7207544, 2.5198421, + 18.7207544, 4.3267487, 18.7207544, 6.3496042, + 18.7207544, 8.5498797, 18.7207544, 10.9027236, + 18.7207544, 13.3905183, 18.7207544, 16.0000000, + 18.7207544, 18.7207544, 18.7207544, 21.5443469, + 18.7207544, 24.4637810, 18.7207544, 27.4731418, + 18.7207544, 30.5673509, 18.7207544, 33.7419917, + 18.7207544, 36.9931811, 18.7207544, 64.0f, + 21.5443469, 0.0000000, 21.5443469, 1.0000000, + 21.5443469, 2.5198421, 21.5443469, 4.3267487, + 21.5443469, 6.3496042, 21.5443469, 8.5498797, + 21.5443469, 10.9027236, 21.5443469, 13.3905183, + 21.5443469, 16.0000000, 21.5443469, 18.7207544, + 21.5443469, 21.5443469, 21.5443469, 24.4637810, + 21.5443469, 27.4731418, 21.5443469, 30.5673509, + 21.5443469, 33.7419917, 21.5443469, 36.9931811, + 21.5443469, 64.0f, 24.4637810, 0.0000000, + 24.4637810, 1.0000000, 24.4637810, 2.5198421, + 24.4637810, 4.3267487, 24.4637810, 6.3496042, + 24.4637810, 8.5498797, 24.4637810, 10.9027236, + 24.4637810, 13.3905183, 24.4637810, 16.0000000, + 24.4637810, 18.7207544, 24.4637810, 21.5443469, + 24.4637810, 24.4637810, 24.4637810, 27.4731418, + 24.4637810, 30.5673509, 24.4637810, 33.7419917, + 24.4637810, 36.9931811, 24.4637810, 64.0f, + 27.4731418, 0.0000000, 27.4731418, 1.0000000, + 27.4731418, 2.5198421, 27.4731418, 4.3267487, + 27.4731418, 6.3496042, 27.4731418, 8.5498797, + 27.4731418, 10.9027236, 27.4731418, 13.3905183, + 27.4731418, 16.0000000, 27.4731418, 18.7207544, + 27.4731418, 21.5443469, 27.4731418, 24.4637810, + 27.4731418, 27.4731418, 27.4731418, 30.5673509, + 27.4731418, 33.7419917, 27.4731418, 36.9931811, + 27.4731418, 64.0f, 30.5673509, 0.0000000, + 30.5673509, 1.0000000, 30.5673509, 2.5198421, + 30.5673509, 4.3267487, 30.5673509, 6.3496042, + 30.5673509, 8.5498797, 30.5673509, 10.9027236, + 30.5673509, 13.3905183, 30.5673509, 16.0000000, + 30.5673509, 18.7207544, 30.5673509, 21.5443469, + 30.5673509, 24.4637810, 30.5673509, 27.4731418, + 30.5673509, 30.5673509, 30.5673509, 33.7419917, + 30.5673509, 36.9931811, 30.5673509, 64.0f, + 33.7419917, 0.0000000, 33.7419917, 1.0000000, + 33.7419917, 2.5198421, 33.7419917, 4.3267487, + 33.7419917, 6.3496042, 33.7419917, 8.5498797, + 33.7419917, 10.9027236, 33.7419917, 13.3905183, + 33.7419917, 16.0000000, 33.7419917, 18.7207544, + 33.7419917, 21.5443469, 33.7419917, 24.4637810, + 33.7419917, 27.4731418, 33.7419917, 30.5673509, + 33.7419917, 33.7419917, 33.7419917, 36.9931811, + 33.7419917, 64.0f, 36.9931811, 0.0000000, + 36.9931811, 1.0000000, 36.9931811, 2.5198421, + 36.9931811, 4.3267487, 36.9931811, 6.3496042, + 36.9931811, 8.5498797, 36.9931811, 10.9027236, + 36.9931811, 13.3905183, 36.9931811, 16.0000000, + 36.9931811, 18.7207544, 36.9931811, 21.5443469, + 36.9931811, 24.4637810, 36.9931811, 27.4731418, + 36.9931811, 30.5673509, 36.9931811, 33.7419917, + 36.9931811, 36.9931811, 36.9931811, 64.0f, + 64.0f, 0.0000000, 64.0f, 1.0000000, + 64.0f, 2.5198421, 64.0f, 4.3267487, + 64.0f, 6.3496042, 64.0f, 8.5498797, + 64.0f, 10.9027236, 64.0f, 13.3905183, + 64.0f, 16.0000000, 64.0f, 18.7207544, + 64.0f, 21.5443469, 64.0f, 24.4637810, + 64.0f, 27.4731418, 64.0f, 30.5673509, + 64.0f, 33.7419917, 64.0f, 36.9931811, + 64.0f, 64.0f, +}; + +const float * const ff_aac_codebook_vectors[] = { + codebook_vector0, codebook_vector0, codebook_vector2, + codebook_vector2, codebook_vector4, codebook_vector4, + codebook_vector6, codebook_vector6, codebook_vector8, + codebook_vector8, codebook_vector10, +}; + +static const float codebook_vector0_vals[] = { + -1.0000000, 0.0000000, 1.0000000 +}; + +/* + * bits 0:1, 2:3, 4:5, 6:7 index into _vals array + * 8:11 number of non-zero values + * 12:15 bit mask of non-zero values + */ +static const uint16_t codebook_vector02_idx[] = { + 0x0000, 0x8140, 0x8180, 0x4110, 0xc250, 0xc290, 0x4120, 0xc260, 0xc2a0, + 0x2104, 0xa244, 0xa284, 0x6214, 0xe354, 0xe394, 0x6224, 0xe364, 0xe3a4, + 0x2108, 0xa248, 0xa288, 0x6218, 0xe358, 0xe398, 0x6228, 0xe368, 0xe3a8, + 0x1101, 0x9241, 0x9281, 0x5211, 0xd351, 0xd391, 0x5221, 0xd361, 0xd3a1, + 0x3205, 0xb345, 0xb385, 0x7315, 0xf455, 0xf495, 0x7325, 0xf465, 0xf4a5, + 0x3209, 0xb349, 0xb389, 0x7319, 0xf459, 0xf499, 0x7329, 0xf469, 0xf4a9, + 0x1102, 0x9242, 0x9282, 0x5212, 0xd352, 0xd392, 0x5222, 0xd362, 0xd3a2, + 0x3206, 0xb346, 0xb386, 0x7316, 0xf456, 0xf496, 0x7326, 0xf466, 0xf4a6, + 0x320a, 0xb34a, 0xb38a, 0x731a, 0xf45a, 0xf49a, 0x732a, 0xf46a, 0xf4aa, +}; + +static const float codebook_vector4_vals[] = { + -6.3496042, -4.3267487, + -2.5198421, -1.0000000, + 0.0000000, 1.0000000, + 2.5198421, 4.3267487, + 6.3496042, +}; + +/* + * bits 0:3, 4:7 index into _vals array + */ +static const uint16_t codebook_vector4_idx[] = { + 0x0000, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, + 0x0001, 0x0011, 0x0021, 0x0031, 0x0041, 0x0051, 0x0061, 0x0071, 0x0081, + 0x0002, 0x0012, 0x0022, 0x0032, 0x0042, 0x0052, 0x0062, 0x0072, 0x0082, + 0x0003, 0x0013, 0x0023, 0x0033, 0x0043, 0x0053, 0x0063, 0x0073, 0x0083, + 0x0004, 0x0014, 0x0024, 0x0034, 0x0044, 0x0054, 0x0064, 0x0074, 0x0084, + 0x0005, 0x0015, 0x0025, 0x0035, 0x0045, 0x0055, 0x0065, 0x0075, 0x0085, + 0x0006, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0066, 0x0076, 0x0086, + 0x0007, 0x0017, 0x0027, 0x0037, 0x0047, 0x0057, 0x0067, 0x0077, 0x0087, + 0x0008, 0x0018, 0x0028, 0x0038, 0x0048, 0x0058, 0x0068, 0x0078, 0x0088, +}; + +/* + * bits 0:3, 4:7 index into _vals array + * 8:11 number of non-zero values + * 12:15 1: only second value non-zero + * 0: other cases + */ +static const uint16_t codebook_vector6_idx[] = { + 0x0000, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, + 0x1101, 0x0211, 0x0221, 0x0231, 0x0241, 0x0251, 0x0261, 0x0271, + 0x1102, 0x0212, 0x0222, 0x0232, 0x0242, 0x0252, 0x0262, 0x0272, + 0x1103, 0x0213, 0x0223, 0x0233, 0x0243, 0x0253, 0x0263, 0x0273, + 0x1104, 0x0214, 0x0224, 0x0234, 0x0244, 0x0254, 0x0264, 0x0274, + 0x1105, 0x0215, 0x0225, 0x0235, 0x0245, 0x0255, 0x0265, 0x0275, + 0x1106, 0x0216, 0x0226, 0x0236, 0x0246, 0x0256, 0x0266, 0x0276, + 0x1107, 0x0217, 0x0227, 0x0237, 0x0247, 0x0257, 0x0267, 0x0277, +}; + +/* + * bits 0:3, 4:7 index into _vals array + * 8:11 number of non-zero values + * 12:15 1: only second value non-zero + * 0: other cases + */ +static const uint16_t codebook_vector8_idx[] = { + 0x0000, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, + 0x0170, 0x0180, 0x0190, 0x01a0, 0x01b0, 0x01c0, + 0x1101, 0x0211, 0x0221, 0x0231, 0x0241, 0x0251, 0x0261, + 0x0271, 0x0281, 0x0291, 0x02a1, 0x02b1, 0x02c1, + 0x1102, 0x0212, 0x0222, 0x0232, 0x0242, 0x0252, 0x0262, + 0x0272, 0x0282, 0x0292, 0x02a2, 0x02b2, 0x02c2, + 0x1103, 0x0213, 0x0223, 0x0233, 0x0243, 0x0253, 0x0263, + 0x0273, 0x0283, 0x0293, 0x02a3, 0x02b3, 0x02c3, + 0x1104, 0x0214, 0x0224, 0x0234, 0x0244, 0x0254, 0x0264, + 0x0274, 0x0284, 0x0294, 0x02a4, 0x02b4, 0x02c4, + 0x1105, 0x0215, 0x0225, 0x0235, 0x0245, 0x0255, 0x0265, + 0x0275, 0x0285, 0x0295, 0x02a5, 0x02b5, 0x02c5, + 0x1106, 0x0216, 0x0226, 0x0236, 0x0246, 0x0256, 0x0266, + 0x0276, 0x0286, 0x0296, 0x02a6, 0x02b6, 0x02c6, + 0x1107, 0x0217, 0x0227, 0x0237, 0x0247, 0x0257, 0x0267, + 0x0277, 0x0287, 0x0297, 0x02a7, 0x02b7, 0x02c7, + 0x1108, 0x0218, 0x0228, 0x0238, 0x0248, 0x0258, 0x0268, + 0x0278, 0x0288, 0x0298, 0x02a8, 0x02b8, 0x02c8, + 0x1109, 0x0219, 0x0229, 0x0239, 0x0249, 0x0259, 0x0269, + 0x0279, 0x0289, 0x0299, 0x02a9, 0x02b9, 0x02c9, + 0x110a, 0x021a, 0x022a, 0x023a, 0x024a, 0x025a, 0x026a, + 0x027a, 0x028a, 0x029a, 0x02aa, 0x02ba, 0x02ca, + 0x110b, 0x021b, 0x022b, 0x023b, 0x024b, 0x025b, 0x026b, + 0x027b, 0x028b, 0x029b, 0x02ab, 0x02bb, 0x02cb, + 0x110c, 0x021c, 0x022c, 0x023c, 0x024c, 0x025c, 0x026c, + 0x027c, 0x028c, 0x029c, 0x02ac, 0x02bc, 0x02cc, +}; + +static const float codebook_vector10_vals[] = { + 0.0000000, 1.0000000, + 2.5198421, 4.3267487, + 6.3496042, 8.5498797, + 10.9027236, 13.3905183, + 16.0000000, 18.7207544, + 21.5443469, 24.4637810, + 27.4731418, 30.5673509, + 33.7419917, 36.9931811, +}; + +/* + * bits 0:3, 4:7 index into _vals array + * 8:9 bit mask of escape-coded entries + * 12:15 number of non-zero values + */ +static const uint16_t codebook_vector10_idx[] = { + 0x0000, 0x1010, 0x1020, 0x1030, 0x1040, 0x1050, 0x1060, 0x1070, + 0x1080, 0x1090, 0x10a0, 0x10b0, 0x10c0, 0x10d0, 0x10e0, 0x10f0, 0x1200, + 0x1001, 0x2011, 0x2021, 0x2031, 0x2041, 0x2051, 0x2061, 0x2071, + 0x2081, 0x2091, 0x20a1, 0x20b1, 0x20c1, 0x20d1, 0x20e1, 0x20f1, 0x2201, + 0x1002, 0x2012, 0x2022, 0x2032, 0x2042, 0x2052, 0x2062, 0x2072, + 0x2082, 0x2092, 0x20a2, 0x20b2, 0x20c2, 0x20d2, 0x20e2, 0x20f2, 0x2202, + 0x1003, 0x2013, 0x2023, 0x2033, 0x2043, 0x2053, 0x2063, 0x2073, + 0x2083, 0x2093, 0x20a3, 0x20b3, 0x20c3, 0x20d3, 0x20e3, 0x20f3, 0x2203, + 0x1004, 0x2014, 0x2024, 0x2034, 0x2044, 0x2054, 0x2064, 0x2074, + 0x2084, 0x2094, 0x20a4, 0x20b4, 0x20c4, 0x20d4, 0x20e4, 0x20f4, 0x2204, + 0x1005, 0x2015, 0x2025, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075, + 0x2085, 0x2095, 0x20a5, 0x20b5, 0x20c5, 0x20d5, 0x20e5, 0x20f5, 0x2205, + 0x1006, 0x2016, 0x2026, 0x2036, 0x2046, 0x2056, 0x2066, 0x2076, + 0x2086, 0x2096, 0x20a6, 0x20b6, 0x20c6, 0x20d6, 0x20e6, 0x20f6, 0x2206, + 0x1007, 0x2017, 0x2027, 0x2037, 0x2047, 0x2057, 0x2067, 0x2077, + 0x2087, 0x2097, 0x20a7, 0x20b7, 0x20c7, 0x20d7, 0x20e7, 0x20f7, 0x2207, + 0x1008, 0x2018, 0x2028, 0x2038, 0x2048, 0x2058, 0x2068, 0x2078, + 0x2088, 0x2098, 0x20a8, 0x20b8, 0x20c8, 0x20d8, 0x20e8, 0x20f8, 0x2208, + 0x1009, 0x2019, 0x2029, 0x2039, 0x2049, 0x2059, 0x2069, 0x2079, + 0x2089, 0x2099, 0x20a9, 0x20b9, 0x20c9, 0x20d9, 0x20e9, 0x20f9, 0x2209, + 0x100a, 0x201a, 0x202a, 0x203a, 0x204a, 0x205a, 0x206a, 0x207a, + 0x208a, 0x209a, 0x20aa, 0x20ba, 0x20ca, 0x20da, 0x20ea, 0x20fa, 0x220a, + 0x100b, 0x201b, 0x202b, 0x203b, 0x204b, 0x205b, 0x206b, 0x207b, + 0x208b, 0x209b, 0x20ab, 0x20bb, 0x20cb, 0x20db, 0x20eb, 0x20fb, 0x220b, + 0x100c, 0x201c, 0x202c, 0x203c, 0x204c, 0x205c, 0x206c, 0x207c, + 0x208c, 0x209c, 0x20ac, 0x20bc, 0x20cc, 0x20dc, 0x20ec, 0x20fc, 0x220c, + 0x100d, 0x201d, 0x202d, 0x203d, 0x204d, 0x205d, 0x206d, 0x207d, + 0x208d, 0x209d, 0x20ad, 0x20bd, 0x20cd, 0x20dd, 0x20ed, 0x20fd, 0x220d, + 0x100e, 0x201e, 0x202e, 0x203e, 0x204e, 0x205e, 0x206e, 0x207e, + 0x208e, 0x209e, 0x20ae, 0x20be, 0x20ce, 0x20de, 0x20ee, 0x20fe, 0x220e, + 0x100f, 0x201f, 0x202f, 0x203f, 0x204f, 0x205f, 0x206f, 0x207f, + 0x208f, 0x209f, 0x20af, 0x20bf, 0x20cf, 0x20df, 0x20ef, 0x20ff, 0x220f, + 0x1100, 0x2110, 0x2120, 0x2130, 0x2140, 0x2150, 0x2160, 0x2170, + 0x2180, 0x2190, 0x21a0, 0x21b0, 0x21c0, 0x21d0, 0x21e0, 0x21f0, 0x2300, +}; + +const float *const ff_aac_codebook_vector_vals[] = { + codebook_vector0_vals, codebook_vector0_vals, + codebook_vector10_vals, codebook_vector10_vals, + codebook_vector4_vals, codebook_vector4_vals, + codebook_vector10_vals, codebook_vector10_vals, + codebook_vector10_vals, codebook_vector10_vals, + codebook_vector10_vals, +}; + +const uint16_t *const ff_aac_codebook_vector_idx[] = { + codebook_vector02_idx, codebook_vector02_idx, + codebook_vector02_idx, codebook_vector02_idx, + codebook_vector4_idx, codebook_vector4_idx, + codebook_vector6_idx, codebook_vector6_idx, + codebook_vector8_idx, codebook_vector8_idx, + codebook_vector10_idx, +}; + +/* @name swb_offsets + * Sample offset into the window indicating the beginning of a scalefactor + * window band + * + * scalefactor window band - term for scalefactor bands within a window, + * given in Table 4.110 to Table 4.128. + * + * scalefactor band - a set of spectral coefficients which are scaled by one + * scalefactor. In case of EIGHT_SHORT_SEQUENCE and grouping a scalefactor band + * may contain several scalefactor window bands of corresponding frequency. For + * all other window_sequences scalefactor bands and scalefactor window bands are + * identical. + * @{ + */ + +static const uint16_t swb_offset_1024_96[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 64, + 72, 80, 88, 96, 108, 120, 132, 144, + 156, 172, 188, 212, 240, 276, 320, 384, + 448, 512, 576, 640, 704, 768, 832, 896, + 960, 1024 +}; + +static const uint16_t swb_offset_128_96[] = { + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128 +}; + +static const uint16_t swb_offset_1024_64[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 64, + 72, 80, 88, 100, 112, 124, 140, 156, + 172, 192, 216, 240, 268, 304, 344, 384, + 424, 464, 504, 544, 584, 624, 664, 704, + 744, 784, 824, 864, 904, 944, 984, 1024 +}; + +static const uint16_t swb_offset_1024_48[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 48, 56, 64, 72, 80, + 88, 96, 108, 120, 132, 144, 160, 176, + 196, 216, 240, 264, 292, 320, 352, 384, + 416, 448, 480, 512, 544, 576, 608, 640, + 672, 704, 736, 768, 800, 832, 864, 896, + 928, 1024 +}; + +static const uint16_t swb_offset_128_48[] = { + 0, 4, 8, 12, 16, 20, 28, 36, + 44, 56, 68, 80, 96, 112, 128 +}; + +static const uint16_t swb_offset_1024_32[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 48, 56, 64, 72, 80, + 88, 96, 108, 120, 132, 144, 160, 176, + 196, 216, 240, 264, 292, 320, 352, 384, + 416, 448, 480, 512, 544, 576, 608, 640, + 672, 704, 736, 768, 800, 832, 864, 896, + 928, 960, 992, 1024 +}; + +static const uint16_t swb_offset_1024_24[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 52, 60, 68, 76, + 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, + 308, 336, 364, 396, 432, 468, 508, 552, + 600, 652, 704, 768, 832, 896, 960, 1024 +}; + +static const uint16_t swb_offset_128_24[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 108, 128 +}; + +static const uint16_t swb_offset_1024_16[] = { + 0, 8, 16, 24, 32, 40, 48, 56, + 64, 72, 80, 88, 100, 112, 124, 136, + 148, 160, 172, 184, 196, 212, 228, 244, + 260, 280, 300, 320, 344, 368, 396, 424, + 456, 492, 532, 572, 616, 664, 716, 772, + 832, 896, 960, 1024 +}; + +static const uint16_t swb_offset_128_16[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 108, 128 +}; + +static const uint16_t swb_offset_1024_8[] = { + 0, 12, 24, 36, 48, 60, 72, 84, + 96, 108, 120, 132, 144, 156, 172, 188, + 204, 220, 236, 252, 268, 288, 308, 328, + 348, 372, 396, 420, 448, 476, 508, 544, + 580, 620, 664, 712, 764, 820, 880, 944, + 1024 +}; + +static const uint16_t swb_offset_128_8[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 108, 128 +}; + +const uint16_t * const ff_swb_offset_1024[] = { + swb_offset_1024_96, swb_offset_1024_96, swb_offset_1024_64, + swb_offset_1024_48, swb_offset_1024_48, swb_offset_1024_32, + swb_offset_1024_24, swb_offset_1024_24, swb_offset_1024_16, + swb_offset_1024_16, swb_offset_1024_16, swb_offset_1024_8, + swb_offset_1024_8 +}; + +const uint16_t * const ff_swb_offset_128[] = { + /* The last entry on the following row is swb_offset_128_64 but is a + duplicate of swb_offset_128_96. */ + swb_offset_128_96, swb_offset_128_96, swb_offset_128_96, + swb_offset_128_48, swb_offset_128_48, swb_offset_128_48, + swb_offset_128_24, swb_offset_128_24, swb_offset_128_16, + swb_offset_128_16, swb_offset_128_16, swb_offset_128_8, + swb_offset_128_8 +}; + +// @} + +/* @name ff_tns_max_bands + * The maximum number of scalefactor bands on which TNS can operate for the long + * and short transforms respectively. The index to these tables is related to + * the sample rate of the audio. + * @{ + */ +const uint8_t ff_tns_max_bands_1024[] = { + 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39, 39 +}; + +const uint8_t ff_tns_max_bands_128[] = { + 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 +}; +// @} diff --git a/ffmpeg/libavcodec/aactab.h b/ffmpeg/libavcodec/aactab.h new file mode 100644 index 0000000..6ed3b4a --- /dev/null +++ b/ffmpeg/libavcodec/aactab.h @@ -0,0 +1,77 @@ +/* + * AAC data declarations + * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org ) + * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com ) + * + * 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 + */ + +/** + * @file + * AAC data declarations + * @author Oded Shimon ( ods15 ods15 dyndns org ) + * @author Maxim Gavrilov ( maxim.gavrilov gmail com ) + */ + +#ifndef AVCODEC_AACTAB_H +#define AVCODEC_AACTAB_H + +#include "libavutil/mem.h" +#include "aac.h" +#include "aac_tablegen_decl.h" + +#include + +/* NOTE: + * Tables in this file are used by the AAC decoder and will be used by the AAC + * encoder. + */ + +/* @name window coefficients + * @{ + */ +DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_1024)[1024]; +DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_128)[128]; +// @} + +/* @name number of scalefactor window bands for long and short transform windows respectively + * @{ + */ +extern const uint8_t ff_aac_num_swb_1024[]; +extern const uint8_t ff_aac_num_swb_128 []; +// @} + +extern const uint8_t ff_aac_pred_sfb_max []; + +extern const uint32_t ff_aac_scalefactor_code[121]; +extern const uint8_t ff_aac_scalefactor_bits[121]; + +extern const uint16_t * const ff_aac_spectral_codes[11]; +extern const uint8_t * const ff_aac_spectral_bits [11]; +extern const uint16_t ff_aac_spectral_sizes[11]; + +extern const float *ff_aac_codebook_vectors[]; +extern const float *ff_aac_codebook_vector_vals[]; +extern const uint16_t *ff_aac_codebook_vector_idx[]; + +extern const uint16_t * const ff_swb_offset_1024[13]; +extern const uint16_t * const ff_swb_offset_128 [13]; + +extern const uint8_t ff_tns_max_bands_1024[13]; +extern const uint8_t ff_tns_max_bands_128 [13]; + +#endif /* AVCODEC_AACTAB_H */ diff --git a/ffmpeg/libavcodec/aandcttab.c b/ffmpeg/libavcodec/aandcttab.c new file mode 100644 index 0000000..87c50b3 --- /dev/null +++ b/ffmpeg/libavcodec/aandcttab.c @@ -0,0 +1,47 @@ +/* + * 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 + */ + +/** + * @file + * AAN (Arai Agui Aakajima) (I)DCT tables + */ + +#include + +const uint16_t ff_aanscales[64] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867 , 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520 , 6270, 5906, 5315, 4520, 3552, 2446, 1247 +}; + +const uint16_t ff_inv_aanscales[64] = { + 4096, 2953, 3135, 3483, 4096, 5213, 7568, 14846, + 2953, 2129, 2260, 2511, 2953, 3759, 5457, 10703, + 3135, 2260, 2399, 2666, 3135, 3990, 5793, 11363, + 3483, 2511, 2666, 2962, 3483, 4433, 6436, 12625, + 4096, 2953, 3135, 3483, 4096, 5213, 7568, 14846, + 5213, 3759, 3990, 4433, 5213, 6635, 9633, 18895, + 7568, 5457, 5793, 6436, 7568, 9633, 13985, 27432, + 14846, 10703, 11363, 12625, 14846, 18895, 27432, 53809, +}; diff --git a/ffmpeg/libavcodec/aandcttab.h b/ffmpeg/libavcodec/aandcttab.h new file mode 100644 index 0000000..d774828 --- /dev/null +++ b/ffmpeg/libavcodec/aandcttab.h @@ -0,0 +1,32 @@ +/* + * 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 + */ + +/** + * @file + * AAN (Arai Agui Nakajima) (I)DCT tables + */ + +#ifndef AVCODEC_AANDCTTAB_H +#define AVCODEC_AANDCTTAB_H + +#include + +extern const uint16_t ff_aanscales[64]; +extern const uint16_t ff_inv_aanscales[64]; + +#endif /* AVCODEC_AANDCTTAB_H */ diff --git a/ffmpeg/libavcodec/aasc.c b/ffmpeg/libavcodec/aasc.c new file mode 100644 index 0000000..26ba30d --- /dev/null +++ b/ffmpeg/libavcodec/aasc.c @@ -0,0 +1,164 @@ +/* + * Autodesk RLE Decoder + * Copyright (C) 2005 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Autodesk RLE Video Decoder by Konstantin Shishkov + */ + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "msrledec.h" + +typedef struct AascContext { + AVCodecContext *avctx; + GetByteContext gb; + AVFrame *frame; + + uint32_t palette[AVPALETTE_COUNT]; + int palette_size; +} AascContext; + +static av_cold int aasc_decode_init(AVCodecContext *avctx) +{ + AascContext *s = avctx->priv_data; + uint8_t *ptr; + int i; + + s->avctx = avctx; + switch (avctx->bits_per_coded_sample) { + case 8: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + ptr = avctx->extradata; + s->palette_size = FFMIN(avctx->extradata_size, AVPALETTE_SIZE); + for (i = 0; i < s->palette_size / 4; i++) { + s->palette[i] = 0xFFU << 24 | AV_RL32(ptr); + ptr += 4; + } + break; + case 16: + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", avctx->bits_per_coded_sample); + return -1; + } + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + return 0; +} + +static int aasc_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AascContext *s = avctx->priv_data; + int compr, i, stride, psize, ret; + + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "frame too short\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + + compr = AV_RL32(buf); + buf += 4; + buf_size -= 4; + psize = avctx->bits_per_coded_sample / 8; + switch (avctx->codec_tag) { + case MKTAG('A', 'A', 'S', '4'): + bytestream2_init(&s->gb, buf - 4, buf_size + 4); + ff_msrle_decode(avctx, (AVPicture*)s->frame, 8, &s->gb); + break; + case MKTAG('A', 'A', 'S', 'C'): + switch (compr) { + case 0: + stride = (avctx->width * psize + psize) & ~psize; + for (i = avctx->height - 1; i >= 0; i--) { + if (avctx->width * psize > buf_size) { + av_log(avctx, AV_LOG_ERROR, "Next line is beyond buffer bounds\n"); + break; + } + memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * psize); + buf += stride; + buf_size -= stride; + } + break; + case 1: + bytestream2_init(&s->gb, buf, buf_size); + ff_msrle_decode(avctx, (AVPicture*)s->frame, 8, &s->gb); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr); + return AVERROR_INVALIDDATA; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown FourCC: %X\n", avctx->codec_tag); + return -1; + } + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) + memcpy(s->frame->data[1], s->palette, s->palette_size); + + *got_frame = 1; + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int aasc_decode_end(AVCodecContext *avctx) +{ + AascContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +AVCodec ff_aasc_decoder = { + .name = "aasc", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AASC, + .priv_data_size = sizeof(AascContext), + .init = aasc_decode_init, + .close = aasc_decode_end, + .decode = aasc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Autodesk RLE"), +}; diff --git a/ffmpeg/libavcodec/ac3.c b/ffmpeg/libavcodec/ac3.c new file mode 100644 index 0000000..29e132f --- /dev/null +++ b/ffmpeg/libavcodec/ac3.c @@ -0,0 +1,231 @@ +/* + * Common code between the AC-3 encoder and decoder + * Copyright (c) 2000 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Common code between the AC-3 encoder and decoder. + */ + +#include "avcodec.h" +#include "ac3.h" +#include "get_bits.h" + +/** + * Starting frequency coefficient bin for each critical band. + */ +const uint8_t ff_ac3_band_start_tab[AC3_CRITICAL_BANDS+1] = { + 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, 31, + 34, 37, 40, 43, 46, 49, 55, 61, 67, 73, + 79, 85, 97, 109, 121, 133, 157, 181, 205, 229, 253 +}; + +#if CONFIG_HARDCODED_TABLES + +/** + * Map each frequency coefficient bin to the critical band that contains it. + */ +const uint8_t ff_ac3_bin_to_band_tab[253] = { + 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, 28, 28, 29, 29, 29, 30, 30, 30, + 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, + 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, + 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, + 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49 +}; + +#else /* CONFIG_HARDCODED_TABLES */ +uint8_t ff_ac3_bin_to_band_tab[253]; +#endif + +static inline int calc_lowcomp1(int a, int b0, int b1, int c) +{ + if ((b0 + 256) == b1) { + a = c; + } else if (b0 > b1) { + a = FFMAX(a - 64, 0); + } + return a; +} + +static inline int calc_lowcomp(int a, int b0, int b1, int bin) +{ + if (bin < 7) { + return calc_lowcomp1(a, b0, b1, 384); + } else if (bin < 20) { + return calc_lowcomp1(a, b0, b1, 320); + } else { + return FFMAX(a - 128, 0); + } +} + +void ff_ac3_bit_alloc_calc_psd(int8_t *exp, int start, int end, int16_t *psd, + int16_t *band_psd) +{ + int bin, band; + + /* exponent mapping to PSD */ + for (bin = start; bin < end; bin++) { + psd[bin]=(3072 - (exp[bin] << 7)); + } + + /* PSD integration */ + bin = start; + band = ff_ac3_bin_to_band_tab[start]; + do { + int v = psd[bin++]; + int band_end = FFMIN(ff_ac3_band_start_tab[band+1], end); + for (; bin < band_end; bin++) { + int max = FFMAX(v, psd[bin]); + /* logadd */ + int adr = FFMIN(max - ((v + psd[bin] + 1) >> 1), 255); + v = max + ff_ac3_log_add_tab[adr]; + } + band_psd[band++] = v; + } while (end > ff_ac3_band_start_tab[band]); +} + +int ff_ac3_bit_alloc_calc_mask(AC3BitAllocParameters *s, int16_t *band_psd, + int start, int end, int fast_gain, int is_lfe, + int dba_mode, int dba_nsegs, uint8_t *dba_offsets, + uint8_t *dba_lengths, uint8_t *dba_values, + int16_t *mask) +{ + int16_t excite[AC3_CRITICAL_BANDS]; /* excitation */ + int band; + int band_start, band_end, begin, end1; + int lowcomp, fastleak, slowleak; + + /* excitation function */ + band_start = ff_ac3_bin_to_band_tab[start]; + band_end = ff_ac3_bin_to_band_tab[end-1] + 1; + + if (band_start == 0) { + lowcomp = 0; + lowcomp = calc_lowcomp1(lowcomp, band_psd[0], band_psd[1], 384); + excite[0] = band_psd[0] - fast_gain - lowcomp; + lowcomp = calc_lowcomp1(lowcomp, band_psd[1], band_psd[2], 384); + excite[1] = band_psd[1] - fast_gain - lowcomp; + begin = 7; + for (band = 2; band < 7; band++) { + if (!(is_lfe && band == 6)) + lowcomp = calc_lowcomp1(lowcomp, band_psd[band], band_psd[band+1], 384); + fastleak = band_psd[band] - fast_gain; + slowleak = band_psd[band] - s->slow_gain; + excite[band] = fastleak - lowcomp; + if (!(is_lfe && band == 6)) { + if (band_psd[band] <= band_psd[band+1]) { + begin = band + 1; + break; + } + } + } + + end1 = FFMIN(band_end, 22); + for (band = begin; band < end1; band++) { + if (!(is_lfe && band == 6)) + lowcomp = calc_lowcomp(lowcomp, band_psd[band], band_psd[band+1], band); + fastleak = FFMAX(fastleak - s->fast_decay, band_psd[band] - fast_gain); + slowleak = FFMAX(slowleak - s->slow_decay, band_psd[band] - s->slow_gain); + excite[band] = FFMAX(fastleak - lowcomp, slowleak); + } + begin = 22; + } else { + /* coupling channel */ + begin = band_start; + fastleak = (s->cpl_fast_leak << 8) + 768; + slowleak = (s->cpl_slow_leak << 8) + 768; + } + + for (band = begin; band < band_end; band++) { + fastleak = FFMAX(fastleak - s->fast_decay, band_psd[band] - fast_gain); + slowleak = FFMAX(slowleak - s->slow_decay, band_psd[band] - s->slow_gain); + excite[band] = FFMAX(fastleak, slowleak); + } + + /* compute masking curve */ + + for (band = band_start; band < band_end; band++) { + int tmp = s->db_per_bit - band_psd[band]; + if (tmp > 0) { + excite[band] += tmp >> 2; + } + mask[band] = FFMAX(ff_ac3_hearing_threshold_tab[band >> s->sr_shift][s->sr_code], excite[band]); + } + + /* delta bit allocation */ + + if (dba_mode == DBA_REUSE || dba_mode == DBA_NEW) { + int i, seg, delta; + if (dba_nsegs > 8) + return -1; + band = band_start; + for (seg = 0; seg < dba_nsegs; seg++) { + band += dba_offsets[seg]; + if (band >= AC3_CRITICAL_BANDS || dba_lengths[seg] > AC3_CRITICAL_BANDS-band) + return -1; + if (dba_values[seg] >= 4) { + delta = (dba_values[seg] - 3) << 7; + } else { + delta = (dba_values[seg] - 4) << 7; + } + for (i = 0; i < dba_lengths[seg]; i++) { + mask[band++] += delta; + } + } + } + return 0; +} + +/** + * Initialize some tables. + * note: This function must remain thread safe because it is called by the + * AVParser init code. + */ +av_cold void ff_ac3_common_init(void) +{ +#if !CONFIG_HARDCODED_TABLES + /* compute ff_ac3_bin_to_band_tab from ff_ac3_band_start_tab */ + int bin = 0, band; + for (band = 0; band < AC3_CRITICAL_BANDS; band++) { + int band_end = ff_ac3_band_start_tab[band+1]; + while (bin < band_end) + ff_ac3_bin_to_band_tab[bin++] = band; + } +#endif /* !CONFIG_HARDCODED_TABLES */ +} diff --git a/ffmpeg/libavcodec/ac3.h b/ffmpeg/libavcodec/ac3.h new file mode 100644 index 0000000..e609bb5 --- /dev/null +++ b/ffmpeg/libavcodec/ac3.h @@ -0,0 +1,181 @@ +/* + * Common code between the AC-3 encoder and decoder + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Common code between the AC-3 encoder and decoder. + */ + +#ifndef AVCODEC_AC3_H +#define AVCODEC_AC3_H + +#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */ +#define AC3_MAX_CHANNELS 7 /**< maximum number of channels, including coupling channel */ +#define CPL_CH 0 /**< coupling channel index */ + +#define AC3_MAX_COEFS 256 +#define AC3_BLOCK_SIZE 256 +#define AC3_MAX_BLOCKS 6 +#define AC3_FRAME_SIZE (AC3_MAX_BLOCKS * 256) +#define AC3_WINDOW_SIZE (AC3_BLOCK_SIZE * 2) +#define AC3_CRITICAL_BANDS 50 +#define AC3_MAX_CPL_BANDS 18 + +#include "libavutil/opt.h" +#include "avcodec.h" +#include "ac3tab.h" + +/* exponent encoding strategy */ +#define EXP_REUSE 0 +#define EXP_NEW 1 + +#define EXP_D15 1 +#define EXP_D25 2 +#define EXP_D45 3 + +/* pre-defined gain values */ +#define LEVEL_PLUS_3DB 1.4142135623730950 +#define LEVEL_PLUS_1POINT5DB 1.1892071150027209 +#define LEVEL_MINUS_1POINT5DB 0.8408964152537145 +#define LEVEL_MINUS_3DB 0.7071067811865476 +#define LEVEL_MINUS_4POINT5DB 0.5946035575013605 +#define LEVEL_MINUS_6DB 0.5000000000000000 +#define LEVEL_MINUS_9DB 0.3535533905932738 +#define LEVEL_ZERO 0.0000000000000000 +#define LEVEL_ONE 1.0000000000000000 + +/** Delta bit allocation strategy */ +typedef enum { + DBA_REUSE = 0, + DBA_NEW, + DBA_NONE, + DBA_RESERVED +} AC3DeltaStrategy; + +/** Channel mode (audio coding mode) */ +typedef enum { + AC3_CHMODE_DUALMONO = 0, + AC3_CHMODE_MONO, + AC3_CHMODE_STEREO, + AC3_CHMODE_3F, + AC3_CHMODE_2F1R, + AC3_CHMODE_3F1R, + AC3_CHMODE_2F2R, + AC3_CHMODE_3F2R +} AC3ChannelMode; + +typedef struct AC3BitAllocParameters { + int sr_code; + int sr_shift; + int slow_gain, slow_decay, fast_decay, db_per_bit, floor; + int cpl_fast_leak, cpl_slow_leak; +} AC3BitAllocParameters; + +/** + * @struct AC3HeaderInfo + * Coded AC-3 header values up to the lfeon element, plus derived values. + */ +typedef struct AC3HeaderInfo { + /** @name Coded elements + * @{ + */ + uint16_t sync_word; + uint16_t crc1; + uint8_t sr_code; + uint8_t bitstream_id; + uint8_t bitstream_mode; + uint8_t channel_mode; + uint8_t lfe_on; + uint8_t frame_type; + int substreamid; ///< substream identification + int center_mix_level; ///< Center mix level index + int surround_mix_level; ///< Surround mix level index + uint16_t channel_map; + int num_blocks; ///< number of audio blocks + /** @} */ + + /** @name Derived values + * @{ + */ + uint8_t sr_shift; + uint16_t sample_rate; + uint32_t bit_rate; + uint8_t channels; + uint16_t frame_size; + uint64_t channel_layout; + /** @} */ +} AC3HeaderInfo; + +typedef enum { + EAC3_FRAME_TYPE_INDEPENDENT = 0, + EAC3_FRAME_TYPE_DEPENDENT, + EAC3_FRAME_TYPE_AC3_CONVERT, + EAC3_FRAME_TYPE_RESERVED +} EAC3FrameType; + +void ff_ac3_common_init(void); + +/** + * Calculate the log power-spectral density of the input signal. + * This gives a rough estimate of signal power in the frequency domain by using + * the spectral envelope (exponents). The psd is also separately grouped + * into critical bands for use in the calculating the masking curve. + * 128 units in psd = -6 dB. The dbknee parameter in AC3BitAllocParameters + * determines the reference level. + * + * @param[in] exp frequency coefficient exponents + * @param[in] start starting bin location + * @param[in] end ending bin location + * @param[out] psd signal power for each frequency bin + * @param[out] band_psd signal power for each critical band + */ +void ff_ac3_bit_alloc_calc_psd(int8_t *exp, int start, int end, int16_t *psd, + int16_t *band_psd); + +/** + * Calculate the masking curve. + * First, the excitation is calculated using parameters in s and the signal + * power in each critical band. The excitation is compared with a predefined + * hearing threshold table to produce the masking curve. If delta bit + * allocation information is provided, it is used for adjusting the masking + * curve, usually to give a closer match to a better psychoacoustic model. + * + * @param[in] s adjustable bit allocation parameters + * @param[in] band_psd signal power for each critical band + * @param[in] start starting bin location + * @param[in] end ending bin location + * @param[in] fast_gain fast gain (estimated signal-to-mask ratio) + * @param[in] is_lfe whether or not the channel being processed is the LFE + * @param[in] dba_mode delta bit allocation mode (none, reuse, or new) + * @param[in] dba_nsegs number of delta segments + * @param[in] dba_offsets location offsets for each segment + * @param[in] dba_lengths length of each segment + * @param[in] dba_values delta bit allocation for each segment + * @param[out] mask calculated masking curve + * @return returns 0 for success, non-zero for error + */ +int ff_ac3_bit_alloc_calc_mask(AC3BitAllocParameters *s, int16_t *band_psd, + int start, int end, int fast_gain, int is_lfe, + int dba_mode, int dba_nsegs, uint8_t *dba_offsets, + uint8_t *dba_lengths, uint8_t *dba_values, + int16_t *mask); + +#endif /* AVCODEC_AC3_H */ diff --git a/ffmpeg/libavcodec/ac3_parser.c b/ffmpeg/libavcodec/ac3_parser.c new file mode 100644 index 0000000..8dc4c0d --- /dev/null +++ b/ffmpeg/libavcodec/ac3_parser.c @@ -0,0 +1,194 @@ +/* + * AC-3 parser + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 "libavutil/channel_layout.h" +#include "parser.h" +#include "ac3_parser.h" +#include "aac_ac3_parser.h" +#include "get_bits.h" + + +#define AC3_HEADER_SIZE 7 + + +static const uint8_t eac3_blocks[4] = { + 1, 2, 3, 6 +}; + +/** + * Table for center mix levels + * reference: Section 5.4.2.4 cmixlev + */ +static const uint8_t center_levels[4] = { 4, 5, 6, 5 }; + +/** + * Table for surround mix levels + * reference: Section 5.4.2.5 surmixlev + */ +static const uint8_t surround_levels[4] = { 4, 6, 7, 6 }; + + +int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) +{ + int frame_size_code; + + memset(hdr, 0, sizeof(*hdr)); + + hdr->sync_word = get_bits(gbc, 16); + if(hdr->sync_word != 0x0B77) + return AAC_AC3_PARSE_ERROR_SYNC; + + /* read ahead to bsid to distinguish between AC-3 and E-AC-3 */ + hdr->bitstream_id = show_bits_long(gbc, 29) & 0x1F; + if(hdr->bitstream_id > 16) + return AAC_AC3_PARSE_ERROR_BSID; + + hdr->num_blocks = 6; + + /* set default mix levels */ + hdr->center_mix_level = 5; // -4.5dB + hdr->surround_mix_level = 6; // -6.0dB + + if(hdr->bitstream_id <= 10) { + /* Normal AC-3 */ + hdr->crc1 = get_bits(gbc, 16); + hdr->sr_code = get_bits(gbc, 2); + if(hdr->sr_code == 3) + return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; + + frame_size_code = get_bits(gbc, 6); + if(frame_size_code > 37) + return AAC_AC3_PARSE_ERROR_FRAME_SIZE; + + skip_bits(gbc, 5); // skip bsid, already got it + + hdr->bitstream_mode = get_bits(gbc, 3); + hdr->channel_mode = get_bits(gbc, 3); + + if(hdr->channel_mode == AC3_CHMODE_STEREO) { + skip_bits(gbc, 2); // skip dsurmod + } else { + if((hdr->channel_mode & 1) && hdr->channel_mode != AC3_CHMODE_MONO) + hdr-> center_mix_level = center_levels[get_bits(gbc, 2)]; + if(hdr->channel_mode & 4) + hdr->surround_mix_level = surround_levels[get_bits(gbc, 2)]; + } + hdr->lfe_on = get_bits1(gbc); + + hdr->sr_shift = FFMAX(hdr->bitstream_id, 8) - 8; + hdr->sample_rate = ff_ac3_sample_rate_tab[hdr->sr_code] >> hdr->sr_shift; + hdr->bit_rate = (ff_ac3_bitrate_tab[frame_size_code>>1] * 1000) >> hdr->sr_shift; + hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; + hdr->frame_size = ff_ac3_frame_size_tab[frame_size_code][hdr->sr_code] * 2; + hdr->frame_type = EAC3_FRAME_TYPE_AC3_CONVERT; //EAC3_FRAME_TYPE_INDEPENDENT; + hdr->substreamid = 0; + } else { + /* Enhanced AC-3 */ + hdr->crc1 = 0; + hdr->frame_type = get_bits(gbc, 2); + if(hdr->frame_type == EAC3_FRAME_TYPE_RESERVED) + return AAC_AC3_PARSE_ERROR_FRAME_TYPE; + + hdr->substreamid = get_bits(gbc, 3); + + hdr->frame_size = (get_bits(gbc, 11) + 1) << 1; + if(hdr->frame_size < AC3_HEADER_SIZE) + return AAC_AC3_PARSE_ERROR_FRAME_SIZE; + + hdr->sr_code = get_bits(gbc, 2); + if (hdr->sr_code == 3) { + int sr_code2 = get_bits(gbc, 2); + if(sr_code2 == 3) + return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; + hdr->sample_rate = ff_ac3_sample_rate_tab[sr_code2] / 2; + hdr->sr_shift = 1; + } else { + hdr->num_blocks = eac3_blocks[get_bits(gbc, 2)]; + hdr->sample_rate = ff_ac3_sample_rate_tab[hdr->sr_code]; + hdr->sr_shift = 0; + } + + hdr->channel_mode = get_bits(gbc, 3); + hdr->lfe_on = get_bits1(gbc); + + hdr->bit_rate = (uint32_t)(8.0 * hdr->frame_size * hdr->sample_rate / + (hdr->num_blocks * 256.0)); + hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; + } + hdr->channel_layout = avpriv_ac3_channel_layout_tab[hdr->channel_mode]; + if (hdr->lfe_on) + hdr->channel_layout |= AV_CH_LOW_FREQUENCY; + + return 0; +} + +static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info, + int *need_next_header, int *new_frame_start) +{ + int err; + union { + uint64_t u64; + uint8_t u8[8]; + } tmp = { av_be2ne64(state) }; + AC3HeaderInfo hdr; + GetBitContext gbc; + + init_get_bits(&gbc, tmp.u8+8-AC3_HEADER_SIZE, 54); + err = avpriv_ac3_parse_header(&gbc, &hdr); + + if(err < 0) + return 0; + + hdr_info->sample_rate = hdr.sample_rate; + hdr_info->bit_rate = hdr.bit_rate; + hdr_info->channels = hdr.channels; + hdr_info->channel_layout = hdr.channel_layout; + hdr_info->samples = hdr.num_blocks * 256; + hdr_info->service_type = hdr.bitstream_mode; + if (hdr.bitstream_mode == 0x7 && hdr.channels > 1) + hdr_info->service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; + if(hdr.bitstream_id>10) + hdr_info->codec_id = AV_CODEC_ID_EAC3; + else if (hdr_info->codec_id == AV_CODEC_ID_NONE) + hdr_info->codec_id = AV_CODEC_ID_AC3; + + *need_next_header = (hdr.frame_type != EAC3_FRAME_TYPE_AC3_CONVERT); + *new_frame_start = (hdr.frame_type != EAC3_FRAME_TYPE_DEPENDENT); + return hdr.frame_size; +} + +static av_cold int ac3_parse_init(AVCodecParserContext *s1) +{ + AACAC3ParseContext *s = s1->priv_data; + s->header_size = AC3_HEADER_SIZE; + s->sync = ac3_sync; + return 0; +} + + +AVCodecParser ff_ac3_parser = { + .codec_ids = { AV_CODEC_ID_AC3, AV_CODEC_ID_EAC3 }, + .priv_data_size = sizeof(AACAC3ParseContext), + .parser_init = ac3_parse_init, + .parser_parse = ff_aac_ac3_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/ac3_parser.h b/ffmpeg/libavcodec/ac3_parser.h new file mode 100644 index 0000000..b5022de --- /dev/null +++ b/ffmpeg/libavcodec/ac3_parser.h @@ -0,0 +1,41 @@ +/* + * AC-3 parser prototypes + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 + */ + +#ifndef AVCODEC_AC3_PARSER_H +#define AVCODEC_AC3_PARSER_H + +#include "ac3.h" +#include "get_bits.h" + +/** + * Parse AC-3 frame header. + * Parse the header up to the lfeon element, which is the first 52 or 54 bits + * depending on the audio coding mode. + * @param[in] gbc BitContext containing the first 54 bits of the frame. + * @param[out] hdr Pointer to struct where header info is written. + * @return Returns 0 on success, -1 if there is a sync word mismatch, + * -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate) + * element is invalid, or -4 if the frmsizecod (bit rate) element is invalid. + */ +int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr); + +#endif /* AVCODEC_AC3_PARSER_H */ diff --git a/ffmpeg/libavcodec/ac3dec.c b/ffmpeg/libavcodec/ac3dec.c new file mode 100644 index 0000000..a70d92a --- /dev/null +++ b/ffmpeg/libavcodec/ac3dec.c @@ -0,0 +1,1488 @@ +/* + * AC-3 Audio Decoder + * This code was developed as part of Google Summer of Code 2006. + * E-AC-3 support was added as part of Google Summer of Code 2007. + * + * Copyright (c) 2006 Kartikey Mahendra BHATT (bhattkm at gmail dot com) + * Copyright (c) 2007-2008 Bartlomiej Wolowiec + * Copyright (c) 2007 Justin Ruggles + * + * 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 +#include +#include + +#include "libavutil/crc.h" +#include "libavutil/opt.h" +#include "internal.h" +#include "aac_ac3_parser.h" +#include "ac3_parser.h" +#include "ac3dec.h" +#include "ac3dec_data.h" +#include "kbdwin.h" + +/** + * table for ungrouping 3 values in 7 bits. + * used for exponents and bap=2 mantissas + */ +static uint8_t ungroup_3_in_7_bits_tab[128][3]; + +/** tables for ungrouping mantissas */ +static int b1_mantissas[32][3]; +static int b2_mantissas[128][3]; +static int b3_mantissas[8]; +static int b4_mantissas[128][2]; +static int b5_mantissas[16]; + +/** + * Quantization table: levels for symmetric. bits for asymmetric. + * reference: Table 7.18 Mapping of bap to Quantizer + */ +static const uint8_t quantization_tab[16] = { + 0, 3, 5, 7, 11, 15, + 5, 6, 7, 8, 9, 10, 11, 12, 14, 16 +}; + +/** dynamic range table. converts codes to scale factors. */ +static float dynamic_range_tab[256]; + +/** Adjustments in dB gain */ +static const float gain_levels[9] = { + LEVEL_PLUS_3DB, + LEVEL_PLUS_1POINT5DB, + LEVEL_ONE, + LEVEL_MINUS_1POINT5DB, + LEVEL_MINUS_3DB, + LEVEL_MINUS_4POINT5DB, + LEVEL_MINUS_6DB, + LEVEL_ZERO, + LEVEL_MINUS_9DB +}; + +/** + * Table for default stereo downmixing coefficients + * reference: Section 7.8.2 Downmixing Into Two Channels + */ +static const uint8_t ac3_default_coeffs[8][5][2] = { + { { 2, 7 }, { 7, 2 }, }, + { { 4, 4 }, }, + { { 2, 7 }, { 7, 2 }, }, + { { 2, 7 }, { 5, 5 }, { 7, 2 }, }, + { { 2, 7 }, { 7, 2 }, { 6, 6 }, }, + { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 8, 8 }, }, + { { 2, 7 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, }, + { { 2, 7 }, { 5, 5 }, { 7, 2 }, { 6, 7 }, { 7, 6 }, }, +}; + +/** + * Symmetrical Dequantization + * reference: Section 7.3.3 Expansion of Mantissas for Symmetrical Quantization + * Tables 7.19 to 7.23 + */ +static inline int +symmetric_dequant(int code, int levels) +{ + return ((code - (levels >> 1)) << 24) / levels; +} + +/* + * Initialize tables at runtime. + */ +static av_cold void ac3_tables_init(void) +{ + int i; + + /* generate table for ungrouping 3 values in 7 bits + reference: Section 7.1.3 Exponent Decoding */ + for (i = 0; i < 128; i++) { + ungroup_3_in_7_bits_tab[i][0] = i / 25; + ungroup_3_in_7_bits_tab[i][1] = (i % 25) / 5; + ungroup_3_in_7_bits_tab[i][2] = (i % 25) % 5; + } + + /* generate grouped mantissa tables + reference: Section 7.3.5 Ungrouping of Mantissas */ + for (i = 0; i < 32; i++) { + /* bap=1 mantissas */ + b1_mantissas[i][0] = symmetric_dequant(ff_ac3_ungroup_3_in_5_bits_tab[i][0], 3); + b1_mantissas[i][1] = symmetric_dequant(ff_ac3_ungroup_3_in_5_bits_tab[i][1], 3); + b1_mantissas[i][2] = symmetric_dequant(ff_ac3_ungroup_3_in_5_bits_tab[i][2], 3); + } + for (i = 0; i < 128; i++) { + /* bap=2 mantissas */ + b2_mantissas[i][0] = symmetric_dequant(ungroup_3_in_7_bits_tab[i][0], 5); + b2_mantissas[i][1] = symmetric_dequant(ungroup_3_in_7_bits_tab[i][1], 5); + b2_mantissas[i][2] = symmetric_dequant(ungroup_3_in_7_bits_tab[i][2], 5); + + /* bap=4 mantissas */ + b4_mantissas[i][0] = symmetric_dequant(i / 11, 11); + b4_mantissas[i][1] = symmetric_dequant(i % 11, 11); + } + /* generate ungrouped mantissa tables + reference: Tables 7.21 and 7.23 */ + for (i = 0; i < 7; i++) { + /* bap=3 mantissas */ + b3_mantissas[i] = symmetric_dequant(i, 7); + } + for (i = 0; i < 15; i++) { + /* bap=5 mantissas */ + b5_mantissas[i] = symmetric_dequant(i, 15); + } + + /* generate dynamic range table + reference: Section 7.7.1 Dynamic Range Control */ + for (i = 0; i < 256; i++) { + int v = (i >> 5) - ((i >> 7) << 3) - 5; + dynamic_range_tab[i] = powf(2.0f, v) * ((i & 0x1F) | 0x20); + } +} + +/** + * AVCodec initialization + */ +static av_cold int ac3_decode_init(AVCodecContext *avctx) +{ + AC3DecodeContext *s = avctx->priv_data; + int i; + + s->avctx = avctx; + + ff_ac3_common_init(); + ac3_tables_init(); + ff_mdct_init(&s->imdct_256, 8, 1, 1.0); + ff_mdct_init(&s->imdct_512, 9, 1, 1.0); + ff_kbd_window_init(s->window, 5.0, 256); + ff_dsputil_init(&s->dsp, avctx); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_fmt_convert_init(&s->fmt_conv, avctx); + av_lfg_init(&s->dith_state, 0); + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + /* allow downmixing to stereo or mono */ + if (avctx->channels > 0 && avctx->request_channels > 0 && + avctx->request_channels < avctx->channels && + avctx->request_channels <= 2) { + avctx->channels = avctx->request_channels; + } + s->downmixed = 1; + + for (i = 0; i < AC3_MAX_CHANNELS; i++) { + s->xcfptr[i] = s->transform_coeffs[i]; + s->dlyptr[i] = s->delay[i]; + } + + return 0; +} + +/** + * Parse the 'sync info' and 'bit stream info' from the AC-3 bitstream. + * GetBitContext within AC3DecodeContext must point to + * the start of the synchronized AC-3 bitstream. + */ +static int ac3_parse_header(AC3DecodeContext *s) +{ + GetBitContext *gbc = &s->gbc; + int i; + + /* read the rest of the bsi. read twice for dual mono mode. */ + i = !s->channel_mode; + do { + skip_bits(gbc, 5); // skip dialog normalization + if (get_bits1(gbc)) + skip_bits(gbc, 8); //skip compression + if (get_bits1(gbc)) + skip_bits(gbc, 8); //skip language code + if (get_bits1(gbc)) + skip_bits(gbc, 7); //skip audio production information + } while (i--); + + skip_bits(gbc, 2); //skip copyright bit and original bitstream bit + + /* skip the timecodes (or extra bitstream information for Alternate Syntax) + TODO: read & use the xbsi1 downmix levels */ + if (get_bits1(gbc)) + skip_bits(gbc, 14); //skip timecode1 / xbsi1 + if (get_bits1(gbc)) + skip_bits(gbc, 14); //skip timecode2 / xbsi2 + + /* skip additional bitstream info */ + if (get_bits1(gbc)) { + i = get_bits(gbc, 6); + do { + skip_bits(gbc, 8); + } while (i--); + } + + return 0; +} + +/** + * Common function to parse AC-3 or E-AC-3 frame header + */ +static int parse_frame_header(AC3DecodeContext *s) +{ + AC3HeaderInfo hdr; + int err; + + err = avpriv_ac3_parse_header(&s->gbc, &hdr); + if (err) + return err; + + /* get decoding parameters from header info */ + s->bit_alloc_params.sr_code = hdr.sr_code; + s->bitstream_mode = hdr.bitstream_mode; + s->channel_mode = hdr.channel_mode; + s->channel_layout = hdr.channel_layout; + s->lfe_on = hdr.lfe_on; + s->bit_alloc_params.sr_shift = hdr.sr_shift; + s->sample_rate = hdr.sample_rate; + s->bit_rate = hdr.bit_rate; + s->channels = hdr.channels; + s->fbw_channels = s->channels - s->lfe_on; + s->lfe_ch = s->fbw_channels + 1; + s->frame_size = hdr.frame_size; + s->center_mix_level = hdr.center_mix_level; + s->surround_mix_level = hdr.surround_mix_level; + s->num_blocks = hdr.num_blocks; + s->frame_type = hdr.frame_type; + s->substreamid = hdr.substreamid; + + if (s->lfe_on) { + s->start_freq[s->lfe_ch] = 0; + s->end_freq[s->lfe_ch] = 7; + s->num_exp_groups[s->lfe_ch] = 2; + s->channel_in_cpl[s->lfe_ch] = 0; + } + + if (hdr.bitstream_id <= 10) { + s->eac3 = 0; + s->snr_offset_strategy = 2; + s->block_switch_syntax = 1; + s->dither_flag_syntax = 1; + s->bit_allocation_syntax = 1; + s->fast_gain_syntax = 0; + s->first_cpl_leak = 0; + s->dba_syntax = 1; + s->skip_syntax = 1; + memset(s->channel_uses_aht, 0, sizeof(s->channel_uses_aht)); + return ac3_parse_header(s); + } else if (CONFIG_EAC3_DECODER) { + s->eac3 = 1; + return ff_eac3_parse_header(s); + } else { + av_log(s->avctx, AV_LOG_ERROR, "E-AC-3 support not compiled in\n"); + return -1; + } +} + +/** + * Set stereo downmixing coefficients based on frame header info. + * reference: Section 7.8.2 Downmixing Into Two Channels + */ +static void set_downmix_coeffs(AC3DecodeContext *s) +{ + int i; + float cmix = gain_levels[s-> center_mix_level]; + float smix = gain_levels[s->surround_mix_level]; + float norm0, norm1; + + for (i = 0; i < s->fbw_channels; i++) { + s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; + s->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; + } + if (s->channel_mode > 1 && s->channel_mode & 1) { + s->downmix_coeffs[1][0] = s->downmix_coeffs[1][1] = cmix; + } + if (s->channel_mode == AC3_CHMODE_2F1R || s->channel_mode == AC3_CHMODE_3F1R) { + int nf = s->channel_mode - 2; + s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB; + } + if (s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) { + int nf = s->channel_mode - 4; + s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix; + } + + /* renormalize */ + norm0 = norm1 = 0.0; + for (i = 0; i < s->fbw_channels; i++) { + norm0 += s->downmix_coeffs[i][0]; + norm1 += s->downmix_coeffs[i][1]; + } + norm0 = 1.0f / norm0; + norm1 = 1.0f / norm1; + for (i = 0; i < s->fbw_channels; i++) { + s->downmix_coeffs[i][0] *= norm0; + s->downmix_coeffs[i][1] *= norm1; + } + + if (s->output_mode == AC3_CHMODE_MONO) { + for (i = 0; i < s->fbw_channels; i++) + s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] + + s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB; + } +} + +/** + * Decode the grouped exponents according to exponent strategy. + * reference: Section 7.1.3 Exponent Decoding + */ +static int decode_exponents(GetBitContext *gbc, int exp_strategy, int ngrps, + uint8_t absexp, int8_t *dexps) +{ + int i, j, grp, group_size; + int dexp[256]; + int expacc, prevexp; + + /* unpack groups */ + group_size = exp_strategy + (exp_strategy == EXP_D45); + for (grp = 0, i = 0; grp < ngrps; grp++) { + expacc = get_bits(gbc, 7); + dexp[i++] = ungroup_3_in_7_bits_tab[expacc][0]; + dexp[i++] = ungroup_3_in_7_bits_tab[expacc][1]; + dexp[i++] = ungroup_3_in_7_bits_tab[expacc][2]; + } + + /* convert to absolute exps and expand groups */ + prevexp = absexp; + for (i = 0, j = 0; i < ngrps * 3; i++) { + prevexp += dexp[i] - 2; + if (prevexp > 24U) + return -1; + switch (group_size) { + case 4: dexps[j++] = prevexp; + dexps[j++] = prevexp; + case 2: dexps[j++] = prevexp; + case 1: dexps[j++] = prevexp; + } + } + return 0; +} + +/** + * Generate transform coefficients for each coupled channel in the coupling + * range using the coupling coefficients and coupling coordinates. + * reference: Section 7.4.3 Coupling Coordinate Format + */ +static void calc_transform_coeffs_cpl(AC3DecodeContext *s) +{ + int bin, band, ch; + + bin = s->start_freq[CPL_CH]; + for (band = 0; band < s->num_cpl_bands; band++) { + int band_start = bin; + int band_end = bin + s->cpl_band_sizes[band]; + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (s->channel_in_cpl[ch]) { + int cpl_coord = s->cpl_coords[ch][band] << 5; + for (bin = band_start; bin < band_end; bin++) { + s->fixed_coeffs[ch][bin] = + MULH(s->fixed_coeffs[CPL_CH][bin] << 4, cpl_coord); + } + if (ch == 2 && s->phase_flags[band]) { + for (bin = band_start; bin < band_end; bin++) + s->fixed_coeffs[2][bin] = -s->fixed_coeffs[2][bin]; + } + } + } + bin = band_end; + } +} + +/** + * Grouped mantissas for 3-level 5-level and 11-level quantization + */ +typedef struct { + int b1_mant[2]; + int b2_mant[2]; + int b4_mant; + int b1; + int b2; + int b4; +} mant_groups; + +/** + * Decode the transform coefficients for a particular channel + * reference: Section 7.3 Quantization and Decoding of Mantissas + */ +static void ac3_decode_transform_coeffs_ch(AC3DecodeContext *s, int ch_index, mant_groups *m) +{ + int start_freq = s->start_freq[ch_index]; + int end_freq = s->end_freq[ch_index]; + uint8_t *baps = s->bap[ch_index]; + int8_t *exps = s->dexps[ch_index]; + int *coeffs = s->fixed_coeffs[ch_index]; + int dither = (ch_index == CPL_CH) || s->dither_flag[ch_index]; + GetBitContext *gbc = &s->gbc; + int freq; + + for (freq = start_freq; freq < end_freq; freq++) { + int bap = baps[freq]; + int mantissa; + switch (bap) { + case 0: + /* random noise with approximate range of -0.707 to 0.707 */ + if (dither) + mantissa = (((av_lfg_get(&s->dith_state)>>8)*181)>>8) - 5931008; + else + mantissa = 0; + break; + case 1: + if (m->b1) { + m->b1--; + mantissa = m->b1_mant[m->b1]; + } else { + int bits = get_bits(gbc, 5); + mantissa = b1_mantissas[bits][0]; + m->b1_mant[1] = b1_mantissas[bits][1]; + m->b1_mant[0] = b1_mantissas[bits][2]; + m->b1 = 2; + } + break; + case 2: + if (m->b2) { + m->b2--; + mantissa = m->b2_mant[m->b2]; + } else { + int bits = get_bits(gbc, 7); + mantissa = b2_mantissas[bits][0]; + m->b2_mant[1] = b2_mantissas[bits][1]; + m->b2_mant[0] = b2_mantissas[bits][2]; + m->b2 = 2; + } + break; + case 3: + mantissa = b3_mantissas[get_bits(gbc, 3)]; + break; + case 4: + if (m->b4) { + m->b4 = 0; + mantissa = m->b4_mant; + } else { + int bits = get_bits(gbc, 7); + mantissa = b4_mantissas[bits][0]; + m->b4_mant = b4_mantissas[bits][1]; + m->b4 = 1; + } + break; + case 5: + mantissa = b5_mantissas[get_bits(gbc, 4)]; + break; + default: /* 6 to 15 */ + /* Shift mantissa and sign-extend it. */ + mantissa = get_sbits(gbc, quantization_tab[bap]); + mantissa <<= 24 - quantization_tab[bap]; + break; + } + coeffs[freq] = mantissa >> exps[freq]; + } +} + +/** + * Remove random dithering from coupling range coefficients with zero-bit + * mantissas for coupled channels which do not use dithering. + * reference: Section 7.3.4 Dither for Zero Bit Mantissas (bap=0) + */ +static void remove_dithering(AC3DecodeContext *s) { + int ch, i; + + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (!s->dither_flag[ch] && s->channel_in_cpl[ch]) { + for (i = s->start_freq[CPL_CH]; i < s->end_freq[CPL_CH]; i++) { + if (!s->bap[CPL_CH][i]) + s->fixed_coeffs[ch][i] = 0; + } + } + } +} + +static void decode_transform_coeffs_ch(AC3DecodeContext *s, int blk, int ch, + mant_groups *m) +{ + if (!s->channel_uses_aht[ch]) { + ac3_decode_transform_coeffs_ch(s, ch, m); + } else { + /* if AHT is used, mantissas for all blocks are encoded in the first + block of the frame. */ + int bin; + if (!blk && CONFIG_EAC3_DECODER) + ff_eac3_decode_transform_coeffs_aht_ch(s, ch); + for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) { + s->fixed_coeffs[ch][bin] = s->pre_mantissa[ch][bin][blk] >> s->dexps[ch][bin]; + } + } +} + +/** + * Decode the transform coefficients. + */ +static void decode_transform_coeffs(AC3DecodeContext *s, int blk) +{ + int ch, end; + int got_cplchan = 0; + mant_groups m; + + m.b1 = m.b2 = m.b4 = 0; + + for (ch = 1; ch <= s->channels; ch++) { + /* transform coefficients for full-bandwidth channel */ + decode_transform_coeffs_ch(s, blk, ch, &m); + /* transform coefficients for coupling channel come right after the + coefficients for the first coupled channel*/ + if (s->channel_in_cpl[ch]) { + if (!got_cplchan) { + decode_transform_coeffs_ch(s, blk, CPL_CH, &m); + calc_transform_coeffs_cpl(s); + got_cplchan = 1; + } + end = s->end_freq[CPL_CH]; + } else { + end = s->end_freq[ch]; + } + do + s->fixed_coeffs[ch][end] = 0; + while (++end < 256); + } + + /* zero the dithered coefficients for appropriate channels */ + remove_dithering(s); +} + +/** + * Stereo rematrixing. + * reference: Section 7.5.4 Rematrixing : Decoding Technique + */ +static void do_rematrixing(AC3DecodeContext *s) +{ + int bnd, i; + int end, bndend; + + end = FFMIN(s->end_freq[1], s->end_freq[2]); + + for (bnd = 0; bnd < s->num_rematrixing_bands; bnd++) { + if (s->rematrixing_flags[bnd]) { + bndend = FFMIN(end, ff_ac3_rematrix_band_tab[bnd + 1]); + for (i = ff_ac3_rematrix_band_tab[bnd]; i < bndend; i++) { + int tmp0 = s->fixed_coeffs[1][i]; + s->fixed_coeffs[1][i] += s->fixed_coeffs[2][i]; + s->fixed_coeffs[2][i] = tmp0 - s->fixed_coeffs[2][i]; + } + } + } +} + +/** + * Inverse MDCT Transform. + * Convert frequency domain coefficients to time-domain audio samples. + * reference: Section 7.9.4 Transformation Equations + */ +static inline void do_imdct(AC3DecodeContext *s, int channels) +{ + int ch; + + for (ch = 1; ch <= channels; ch++) { + if (s->block_switch[ch]) { + int i; + float *x = s->tmp_output + 128; + for (i = 0; i < 128; i++) + x[i] = s->transform_coeffs[ch][2 * i]; + s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x); + s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1], + s->tmp_output, s->window, 128); + for (i = 0; i < 128; i++) + x[i] = s->transform_coeffs[ch][2 * i + 1]; + s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x); + } else { + s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]); + s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1], + s->tmp_output, s->window, 128); + memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(float)); + } + } +} + +/** + * Upmix delay samples from stereo to original channel layout. + */ +static void ac3_upmix_delay(AC3DecodeContext *s) +{ + int channel_data_size = sizeof(s->delay[0]); + switch (s->channel_mode) { + case AC3_CHMODE_DUALMONO: + case AC3_CHMODE_STEREO: + /* upmix mono to stereo */ + memcpy(s->delay[1], s->delay[0], channel_data_size); + break; + case AC3_CHMODE_2F2R: + memset(s->delay[3], 0, channel_data_size); + case AC3_CHMODE_2F1R: + memset(s->delay[2], 0, channel_data_size); + break; + case AC3_CHMODE_3F2R: + memset(s->delay[4], 0, channel_data_size); + case AC3_CHMODE_3F1R: + memset(s->delay[3], 0, channel_data_size); + case AC3_CHMODE_3F: + memcpy(s->delay[2], s->delay[1], channel_data_size); + memset(s->delay[1], 0, channel_data_size); + break; + } +} + +/** + * Decode band structure for coupling, spectral extension, or enhanced coupling. + * The band structure defines how many subbands are in each band. For each + * subband in the range, 1 means it is combined with the previous band, and 0 + * means that it starts a new band. + * + * @param[in] gbc bit reader context + * @param[in] blk block number + * @param[in] eac3 flag to indicate E-AC-3 + * @param[in] ecpl flag to indicate enhanced coupling + * @param[in] start_subband subband number for start of range + * @param[in] end_subband subband number for end of range + * @param[in] default_band_struct default band structure table + * @param[out] num_bands number of bands (optionally NULL) + * @param[out] band_sizes array containing the number of bins in each band (optionally NULL) + */ +static void decode_band_structure(GetBitContext *gbc, int blk, int eac3, + int ecpl, int start_subband, int end_subband, + const uint8_t *default_band_struct, + int *num_bands, uint8_t *band_sizes) +{ + int subbnd, bnd, n_subbands, n_bands=0; + uint8_t bnd_sz[22]; + uint8_t coded_band_struct[22]; + const uint8_t *band_struct; + + n_subbands = end_subband - start_subband; + + /* decode band structure from bitstream or use default */ + if (!eac3 || get_bits1(gbc)) { + for (subbnd = 0; subbnd < n_subbands - 1; subbnd++) { + coded_band_struct[subbnd] = get_bits1(gbc); + } + band_struct = coded_band_struct; + } else if (!blk) { + band_struct = &default_band_struct[start_subband+1]; + } else { + /* no change in band structure */ + return; + } + + /* calculate number of bands and band sizes based on band structure. + note that the first 4 subbands in enhanced coupling span only 6 bins + instead of 12. */ + if (num_bands || band_sizes ) { + n_bands = n_subbands; + bnd_sz[0] = ecpl ? 6 : 12; + for (bnd = 0, subbnd = 1; subbnd < n_subbands; subbnd++) { + int subbnd_size = (ecpl && subbnd < 4) ? 6 : 12; + if (band_struct[subbnd - 1]) { + n_bands--; + bnd_sz[bnd] += subbnd_size; + } else { + bnd_sz[++bnd] = subbnd_size; + } + } + } + + /* set optional output params */ + if (num_bands) + *num_bands = n_bands; + if (band_sizes) + memcpy(band_sizes, bnd_sz, n_bands); +} + +/** + * Decode a single audio block from the AC-3 bitstream. + */ +static int decode_audio_block(AC3DecodeContext *s, int blk) +{ + int fbw_channels = s->fbw_channels; + int channel_mode = s->channel_mode; + int i, bnd, seg, ch; + int different_transforms; + int downmix_output; + int cpl_in_use; + GetBitContext *gbc = &s->gbc; + uint8_t bit_alloc_stages[AC3_MAX_CHANNELS] = { 0 }; + + /* block switch flags */ + different_transforms = 0; + if (s->block_switch_syntax) { + for (ch = 1; ch <= fbw_channels; ch++) { + s->block_switch[ch] = get_bits1(gbc); + if (ch > 1 && s->block_switch[ch] != s->block_switch[1]) + different_transforms = 1; + } + } + + /* dithering flags */ + if (s->dither_flag_syntax) { + for (ch = 1; ch <= fbw_channels; ch++) { + s->dither_flag[ch] = get_bits1(gbc); + } + } + + /* dynamic range */ + i = !s->channel_mode; + do { + if (get_bits1(gbc)) { + s->dynamic_range[i] = ((dynamic_range_tab[get_bits(gbc, 8)] - 1.0) * + s->drc_scale) + 1.0; + } else if (blk == 0) { + s->dynamic_range[i] = 1.0f; + } + } while (i--); + + /* spectral extension strategy */ + if (s->eac3 && (!blk || get_bits1(gbc))) { + s->spx_in_use = get_bits1(gbc); + if (s->spx_in_use) { + int dst_start_freq, dst_end_freq, src_start_freq, + start_subband, end_subband; + + /* determine which channels use spx */ + if (s->channel_mode == AC3_CHMODE_MONO) { + s->channel_uses_spx[1] = 1; + } else { + for (ch = 1; ch <= fbw_channels; ch++) + s->channel_uses_spx[ch] = get_bits1(gbc); + } + + /* get the frequency bins of the spx copy region and the spx start + and end subbands */ + dst_start_freq = get_bits(gbc, 2); + start_subband = get_bits(gbc, 3) + 2; + if (start_subband > 7) + start_subband += start_subband - 7; + end_subband = get_bits(gbc, 3) + 5; + if (end_subband > 7) + end_subband += end_subband - 7; + dst_start_freq = dst_start_freq * 12 + 25; + src_start_freq = start_subband * 12 + 25; + dst_end_freq = end_subband * 12 + 25; + + /* check validity of spx ranges */ + if (start_subband >= end_subband) { + av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension " + "range (%d >= %d)\n", start_subband, end_subband); + return -1; + } + if (dst_start_freq >= src_start_freq) { + av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension " + "copy start bin (%d >= %d)\n", dst_start_freq, src_start_freq); + return -1; + } + + s->spx_dst_start_freq = dst_start_freq; + s->spx_src_start_freq = src_start_freq; + s->spx_dst_end_freq = dst_end_freq; + + decode_band_structure(gbc, blk, s->eac3, 0, + start_subband, end_subband, + ff_eac3_default_spx_band_struct, + &s->num_spx_bands, + s->spx_band_sizes); + } else { + for (ch = 1; ch <= fbw_channels; ch++) { + s->channel_uses_spx[ch] = 0; + s->first_spx_coords[ch] = 1; + } + } + } + + /* spectral extension coordinates */ + if (s->spx_in_use) { + for (ch = 1; ch <= fbw_channels; ch++) { + if (s->channel_uses_spx[ch]) { + if (s->first_spx_coords[ch] || get_bits1(gbc)) { + float spx_blend; + int bin, master_spx_coord; + + s->first_spx_coords[ch] = 0; + spx_blend = get_bits(gbc, 5) * (1.0f/32); + master_spx_coord = get_bits(gbc, 2) * 3; + + bin = s->spx_src_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int bandsize; + int spx_coord_exp, spx_coord_mant; + float nratio, sblend, nblend, spx_coord; + + /* calculate blending factors */ + bandsize = s->spx_band_sizes[bnd]; + nratio = ((float)((bin + (bandsize >> 1))) / s->spx_dst_end_freq) - spx_blend; + nratio = av_clipf(nratio, 0.0f, 1.0f); + nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3) + // to give unity variance + sblend = sqrtf(1.0f - nratio); + bin += bandsize; + + /* decode spx coordinates */ + spx_coord_exp = get_bits(gbc, 4); + spx_coord_mant = get_bits(gbc, 2); + if (spx_coord_exp == 15) spx_coord_mant <<= 1; + else spx_coord_mant += 4; + spx_coord_mant <<= (25 - spx_coord_exp - master_spx_coord); + spx_coord = spx_coord_mant * (1.0f / (1 << 23)); + + /* multiply noise and signal blending factors by spx coordinate */ + s->spx_noise_blend [ch][bnd] = nblend * spx_coord; + s->spx_signal_blend[ch][bnd] = sblend * spx_coord; + } + } + } else { + s->first_spx_coords[ch] = 1; + } + } + } + + /* coupling strategy */ + if (s->eac3 ? s->cpl_strategy_exists[blk] : get_bits1(gbc)) { + memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS); + if (!s->eac3) + s->cpl_in_use[blk] = get_bits1(gbc); + if (s->cpl_in_use[blk]) { + /* coupling in use */ + int cpl_start_subband, cpl_end_subband; + + if (channel_mode < AC3_CHMODE_STEREO) { + av_log(s->avctx, AV_LOG_ERROR, "coupling not allowed in mono or dual-mono\n"); + return -1; + } + + /* check for enhanced coupling */ + if (s->eac3 && get_bits1(gbc)) { + /* TODO: parse enhanced coupling strategy info */ + avpriv_request_sample(s->avctx, "Enhanced coupling"); + return AVERROR_PATCHWELCOME; + } + + /* determine which channels are coupled */ + if (s->eac3 && s->channel_mode == AC3_CHMODE_STEREO) { + s->channel_in_cpl[1] = 1; + s->channel_in_cpl[2] = 1; + } else { + for (ch = 1; ch <= fbw_channels; ch++) + s->channel_in_cpl[ch] = get_bits1(gbc); + } + + /* phase flags in use */ + if (channel_mode == AC3_CHMODE_STEREO) + s->phase_flags_in_use = get_bits1(gbc); + + /* coupling frequency range */ + cpl_start_subband = get_bits(gbc, 4); + cpl_end_subband = s->spx_in_use ? (s->spx_src_start_freq - 37) / 12 : + get_bits(gbc, 4) + 3; + if (cpl_start_subband >= cpl_end_subband) { + av_log(s->avctx, AV_LOG_ERROR, "invalid coupling range (%d >= %d)\n", + cpl_start_subband, cpl_end_subband); + return -1; + } + s->start_freq[CPL_CH] = cpl_start_subband * 12 + 37; + s->end_freq[CPL_CH] = cpl_end_subband * 12 + 37; + + decode_band_structure(gbc, blk, s->eac3, 0, cpl_start_subband, + cpl_end_subband, + ff_eac3_default_cpl_band_struct, + &s->num_cpl_bands, s->cpl_band_sizes); + } else { + /* coupling not in use */ + for (ch = 1; ch <= fbw_channels; ch++) { + s->channel_in_cpl[ch] = 0; + s->first_cpl_coords[ch] = 1; + } + s->first_cpl_leak = s->eac3; + s->phase_flags_in_use = 0; + } + } else if (!s->eac3) { + if (!blk) { + av_log(s->avctx, AV_LOG_ERROR, "new coupling strategy must " + "be present in block 0\n"); + return -1; + } else { + s->cpl_in_use[blk] = s->cpl_in_use[blk-1]; + } + } + cpl_in_use = s->cpl_in_use[blk]; + + /* coupling coordinates */ + if (cpl_in_use) { + int cpl_coords_exist = 0; + + for (ch = 1; ch <= fbw_channels; ch++) { + if (s->channel_in_cpl[ch]) { + if ((s->eac3 && s->first_cpl_coords[ch]) || get_bits1(gbc)) { + int master_cpl_coord, cpl_coord_exp, cpl_coord_mant; + s->first_cpl_coords[ch] = 0; + cpl_coords_exist = 1; + master_cpl_coord = 3 * get_bits(gbc, 2); + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + cpl_coord_exp = get_bits(gbc, 4); + cpl_coord_mant = get_bits(gbc, 4); + if (cpl_coord_exp == 15) + s->cpl_coords[ch][bnd] = cpl_coord_mant << 22; + else + s->cpl_coords[ch][bnd] = (cpl_coord_mant + 16) << 21; + s->cpl_coords[ch][bnd] >>= (cpl_coord_exp + master_cpl_coord); + } + } else if (!blk) { + av_log(s->avctx, AV_LOG_ERROR, "new coupling coordinates must " + "be present in block 0\n"); + return -1; + } + } else { + /* channel not in coupling */ + s->first_cpl_coords[ch] = 1; + } + } + /* phase flags */ + if (channel_mode == AC3_CHMODE_STEREO && cpl_coords_exist) { + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + s->phase_flags[bnd] = s->phase_flags_in_use? get_bits1(gbc) : 0; + } + } + } + + /* stereo rematrixing strategy and band structure */ + if (channel_mode == AC3_CHMODE_STEREO) { + if ((s->eac3 && !blk) || get_bits1(gbc)) { + s->num_rematrixing_bands = 4; + if (cpl_in_use && s->start_freq[CPL_CH] <= 61) { + s->num_rematrixing_bands -= 1 + (s->start_freq[CPL_CH] == 37); + } else if (s->spx_in_use && s->spx_src_start_freq <= 61) { + s->num_rematrixing_bands--; + } + for (bnd = 0; bnd < s->num_rematrixing_bands; bnd++) + s->rematrixing_flags[bnd] = get_bits1(gbc); + } else if (!blk) { + av_log(s->avctx, AV_LOG_WARNING, "Warning: " + "new rematrixing strategy not present in block 0\n"); + s->num_rematrixing_bands = 0; + } + } + + /* exponent strategies for each channel */ + for (ch = !cpl_in_use; ch <= s->channels; ch++) { + if (!s->eac3) + s->exp_strategy[blk][ch] = get_bits(gbc, 2 - (ch == s->lfe_ch)); + if (s->exp_strategy[blk][ch] != EXP_REUSE) + bit_alloc_stages[ch] = 3; + } + + /* channel bandwidth */ + for (ch = 1; ch <= fbw_channels; ch++) { + s->start_freq[ch] = 0; + if (s->exp_strategy[blk][ch] != EXP_REUSE) { + int group_size; + int prev = s->end_freq[ch]; + if (s->channel_in_cpl[ch]) + s->end_freq[ch] = s->start_freq[CPL_CH]; + else if (s->channel_uses_spx[ch]) + s->end_freq[ch] = s->spx_src_start_freq; + else { + int bandwidth_code = get_bits(gbc, 6); + if (bandwidth_code > 60) { + av_log(s->avctx, AV_LOG_ERROR, "bandwidth code = %d > 60\n", bandwidth_code); + return -1; + } + s->end_freq[ch] = bandwidth_code * 3 + 73; + } + group_size = 3 << (s->exp_strategy[blk][ch] - 1); + s->num_exp_groups[ch] = (s->end_freq[ch] + group_size-4) / group_size; + if (blk > 0 && s->end_freq[ch] != prev) + memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS); + } + } + if (cpl_in_use && s->exp_strategy[blk][CPL_CH] != EXP_REUSE) { + s->num_exp_groups[CPL_CH] = (s->end_freq[CPL_CH] - s->start_freq[CPL_CH]) / + (3 << (s->exp_strategy[blk][CPL_CH] - 1)); + } + + /* decode exponents for each channel */ + for (ch = !cpl_in_use; ch <= s->channels; ch++) { + if (s->exp_strategy[blk][ch] != EXP_REUSE) { + s->dexps[ch][0] = get_bits(gbc, 4) << !ch; + if (decode_exponents(gbc, s->exp_strategy[blk][ch], + s->num_exp_groups[ch], s->dexps[ch][0], + &s->dexps[ch][s->start_freq[ch]+!!ch])) { + av_log(s->avctx, AV_LOG_ERROR, "exponent out-of-range\n"); + return -1; + } + if (ch != CPL_CH && ch != s->lfe_ch) + skip_bits(gbc, 2); /* skip gainrng */ + } + } + + /* bit allocation information */ + if (s->bit_allocation_syntax) { + if (get_bits1(gbc)) { + s->bit_alloc_params.slow_decay = ff_ac3_slow_decay_tab[get_bits(gbc, 2)] >> s->bit_alloc_params.sr_shift; + s->bit_alloc_params.fast_decay = ff_ac3_fast_decay_tab[get_bits(gbc, 2)] >> s->bit_alloc_params.sr_shift; + s->bit_alloc_params.slow_gain = ff_ac3_slow_gain_tab[get_bits(gbc, 2)]; + s->bit_alloc_params.db_per_bit = ff_ac3_db_per_bit_tab[get_bits(gbc, 2)]; + s->bit_alloc_params.floor = ff_ac3_floor_tab[get_bits(gbc, 3)]; + for (ch = !cpl_in_use; ch <= s->channels; ch++) + bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2); + } else if (!blk) { + av_log(s->avctx, AV_LOG_ERROR, "new bit allocation info must " + "be present in block 0\n"); + return -1; + } + } + + /* signal-to-noise ratio offsets and fast gains (signal-to-mask ratios) */ + if (!s->eac3 || !blk) { + if (s->snr_offset_strategy && get_bits1(gbc)) { + int snr = 0; + int csnr; + csnr = (get_bits(gbc, 6) - 15) << 4; + for (i = ch = !cpl_in_use; ch <= s->channels; ch++) { + /* snr offset */ + if (ch == i || s->snr_offset_strategy == 2) + snr = (csnr + get_bits(gbc, 4)) << 2; + /* run at least last bit allocation stage if snr offset changes */ + if (blk && s->snr_offset[ch] != snr) { + bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 1); + } + s->snr_offset[ch] = snr; + + /* fast gain (normal AC-3 only) */ + if (!s->eac3) { + int prev = s->fast_gain[ch]; + s->fast_gain[ch] = ff_ac3_fast_gain_tab[get_bits(gbc, 3)]; + /* run last 2 bit allocation stages if fast gain changes */ + if (blk && prev != s->fast_gain[ch]) + bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2); + } + } + } else if (!s->eac3 && !blk) { + av_log(s->avctx, AV_LOG_ERROR, "new snr offsets must be present in block 0\n"); + return -1; + } + } + + /* fast gain (E-AC-3 only) */ + if (s->fast_gain_syntax && get_bits1(gbc)) { + for (ch = !cpl_in_use; ch <= s->channels; ch++) { + int prev = s->fast_gain[ch]; + s->fast_gain[ch] = ff_ac3_fast_gain_tab[get_bits(gbc, 3)]; + /* run last 2 bit allocation stages if fast gain changes */ + if (blk && prev != s->fast_gain[ch]) + bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2); + } + } else if (s->eac3 && !blk) { + for (ch = !cpl_in_use; ch <= s->channels; ch++) + s->fast_gain[ch] = ff_ac3_fast_gain_tab[4]; + } + + /* E-AC-3 to AC-3 converter SNR offset */ + if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && get_bits1(gbc)) { + skip_bits(gbc, 10); // skip converter snr offset + } + + /* coupling leak information */ + if (cpl_in_use) { + if (s->first_cpl_leak || get_bits1(gbc)) { + int fl = get_bits(gbc, 3); + int sl = get_bits(gbc, 3); + /* run last 2 bit allocation stages for coupling channel if + coupling leak changes */ + if (blk && (fl != s->bit_alloc_params.cpl_fast_leak || + sl != s->bit_alloc_params.cpl_slow_leak)) { + bit_alloc_stages[CPL_CH] = FFMAX(bit_alloc_stages[CPL_CH], 2); + } + s->bit_alloc_params.cpl_fast_leak = fl; + s->bit_alloc_params.cpl_slow_leak = sl; + } else if (!s->eac3 && !blk) { + av_log(s->avctx, AV_LOG_ERROR, "new coupling leak info must " + "be present in block 0\n"); + return -1; + } + s->first_cpl_leak = 0; + } + + /* delta bit allocation information */ + if (s->dba_syntax && get_bits1(gbc)) { + /* delta bit allocation exists (strategy) */ + for (ch = !cpl_in_use; ch <= fbw_channels; ch++) { + s->dba_mode[ch] = get_bits(gbc, 2); + if (s->dba_mode[ch] == DBA_RESERVED) { + av_log(s->avctx, AV_LOG_ERROR, "delta bit allocation strategy reserved\n"); + return -1; + } + bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2); + } + /* channel delta offset, len and bit allocation */ + for (ch = !cpl_in_use; ch <= fbw_channels; ch++) { + if (s->dba_mode[ch] == DBA_NEW) { + s->dba_nsegs[ch] = get_bits(gbc, 3) + 1; + for (seg = 0; seg < s->dba_nsegs[ch]; seg++) { + s->dba_offsets[ch][seg] = get_bits(gbc, 5); + s->dba_lengths[ch][seg] = get_bits(gbc, 4); + s->dba_values[ch][seg] = get_bits(gbc, 3); + } + /* run last 2 bit allocation stages if new dba values */ + bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2); + } + } + } else if (blk == 0) { + for (ch = 0; ch <= s->channels; ch++) { + s->dba_mode[ch] = DBA_NONE; + } + } + + /* Bit allocation */ + for (ch = !cpl_in_use; ch <= s->channels; ch++) { + if (bit_alloc_stages[ch] > 2) { + /* Exponent mapping into PSD and PSD integration */ + ff_ac3_bit_alloc_calc_psd(s->dexps[ch], + s->start_freq[ch], s->end_freq[ch], + s->psd[ch], s->band_psd[ch]); + } + if (bit_alloc_stages[ch] > 1) { + /* Compute excitation function, Compute masking curve, and + Apply delta bit allocation */ + if (ff_ac3_bit_alloc_calc_mask(&s->bit_alloc_params, s->band_psd[ch], + s->start_freq[ch], s->end_freq[ch], + s->fast_gain[ch], (ch == s->lfe_ch), + s->dba_mode[ch], s->dba_nsegs[ch], + s->dba_offsets[ch], s->dba_lengths[ch], + s->dba_values[ch], s->mask[ch])) { + av_log(s->avctx, AV_LOG_ERROR, "error in bit allocation\n"); + return -1; + } + } + if (bit_alloc_stages[ch] > 0) { + /* Compute bit allocation */ + const uint8_t *bap_tab = s->channel_uses_aht[ch] ? + ff_eac3_hebap_tab : ff_ac3_bap_tab; + s->ac3dsp.bit_alloc_calc_bap(s->mask[ch], s->psd[ch], + s->start_freq[ch], s->end_freq[ch], + s->snr_offset[ch], + s->bit_alloc_params.floor, + bap_tab, s->bap[ch]); + } + } + + /* unused dummy data */ + if (s->skip_syntax && get_bits1(gbc)) { + int skipl = get_bits(gbc, 9); + while (skipl--) + skip_bits(gbc, 8); + } + + /* unpack the transform coefficients + this also uncouples channels if coupling is in use. */ + decode_transform_coeffs(s, blk); + + /* TODO: generate enhanced coupling coordinates and uncouple */ + + /* recover coefficients if rematrixing is in use */ + if (s->channel_mode == AC3_CHMODE_STEREO) + do_rematrixing(s); + + /* apply scaling to coefficients (headroom, dynrng) */ + for (ch = 1; ch <= s->channels; ch++) { + float gain = 1.0 / 4194304.0f; + if (s->channel_mode == AC3_CHMODE_DUALMONO) { + gain *= s->dynamic_range[2 - ch]; + } else { + gain *= s->dynamic_range[0]; + } + s->fmt_conv.int32_to_float_fmul_scalar(s->transform_coeffs[ch], + s->fixed_coeffs[ch], gain, 256); + } + + /* apply spectral extension to high frequency bins */ + if (s->spx_in_use && CONFIG_EAC3_DECODER) { + ff_eac3_apply_spectral_extension(s); + } + + /* downmix and MDCT. order depends on whether block switching is used for + any channel in this block. this is because coefficients for the long + and short transforms cannot be mixed. */ + downmix_output = s->channels != s->out_channels && + !((s->output_mode & AC3_OUTPUT_LFEON) && + s->fbw_channels == s->out_channels); + if (different_transforms) { + /* the delay samples have already been downmixed, so we upmix the delay + samples in order to reconstruct all channels before downmixing. */ + if (s->downmixed) { + s->downmixed = 0; + ac3_upmix_delay(s); + } + + do_imdct(s, s->channels); + + if (downmix_output) { + s->ac3dsp.downmix(s->outptr, s->downmix_coeffs, + s->out_channels, s->fbw_channels, 256); + } + } else { + if (downmix_output) { + s->ac3dsp.downmix(s->xcfptr + 1, s->downmix_coeffs, + s->out_channels, s->fbw_channels, 256); + } + + if (downmix_output && !s->downmixed) { + s->downmixed = 1; + s->ac3dsp.downmix(s->dlyptr, s->downmix_coeffs, s->out_channels, + s->fbw_channels, 128); + } + + do_imdct(s, s->out_channels); + } + + return 0; +} + +/** + * Decode a single AC-3 frame. + */ +static int ac3_decode_frame(AVCodecContext * avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AC3DecodeContext *s = avctx->priv_data; + int blk, ch, err, ret; + const uint8_t *channel_map; + const float *output[AC3_MAX_CHANNELS]; + + /* copy input buffer to decoder context to avoid reading past the end + of the buffer, which can be caused by a damaged input stream. */ + if (buf_size >= 2 && AV_RB16(buf) == 0x770B) { + // seems to be byte-swapped AC-3 + int cnt = FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE) >> 1; + s->dsp.bswap16_buf((uint16_t *)s->input_buffer, (const uint16_t *)buf, cnt); + } else + memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE)); + buf = s->input_buffer; + /* initialize the GetBitContext with the start of valid AC-3 Frame */ + init_get_bits(&s->gbc, buf, buf_size * 8); + + /* parse the syncinfo */ + err = parse_frame_header(s); + + if (err) { + switch (err) { + case AAC_AC3_PARSE_ERROR_SYNC: + av_log(avctx, AV_LOG_ERROR, "frame sync error\n"); + return -1; + case AAC_AC3_PARSE_ERROR_BSID: + av_log(avctx, AV_LOG_ERROR, "invalid bitstream id\n"); + break; + case AAC_AC3_PARSE_ERROR_SAMPLE_RATE: + av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n"); + break; + case AAC_AC3_PARSE_ERROR_FRAME_SIZE: + av_log(avctx, AV_LOG_ERROR, "invalid frame size\n"); + break; + case AAC_AC3_PARSE_ERROR_FRAME_TYPE: + /* skip frame if CRC is ok. otherwise use error concealment. */ + /* TODO: add support for substreams and dependent frames */ + if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) { + av_log(avctx, AV_LOG_ERROR, "unsupported frame type : " + "skipping frame\n"); + *got_frame_ptr = 0; + return s->frame_size; + } else { + av_log(avctx, AV_LOG_ERROR, "invalid frame type\n"); + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid header\n"); + break; + } + } else { + /* check that reported frame size fits in input buffer */ + if (s->frame_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "incomplete frame\n"); + err = AAC_AC3_PARSE_ERROR_FRAME_SIZE; + } else if (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL)) { + /* check for crc mismatch */ + if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &buf[2], + s->frame_size - 2)) { + av_log(avctx, AV_LOG_ERROR, "frame CRC mismatch\n"); + err = AAC_AC3_PARSE_ERROR_CRC; + } + } + } + + /* if frame is ok, set audio parameters */ + if (!err) { + avctx->sample_rate = s->sample_rate; + avctx->bit_rate = s->bit_rate; + } + + /* channel config */ + if (!err || (s->channels && s->out_channels != s->channels)) { + s->out_channels = s->channels; + s->output_mode = s->channel_mode; + if (s->lfe_on) + s->output_mode |= AC3_OUTPUT_LFEON; + if (avctx->request_channels > 0 && avctx->request_channels <= 2 && + avctx->request_channels < s->channels) { + s->out_channels = avctx->request_channels; + s->output_mode = avctx->request_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO; + s->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode]; + } + avctx->channels = s->out_channels; + avctx->channel_layout = s->channel_layout; + + s->loro_center_mix_level = gain_levels[s-> center_mix_level]; + s->loro_surround_mix_level = gain_levels[s->surround_mix_level]; + s->ltrt_center_mix_level = LEVEL_MINUS_3DB; + s->ltrt_surround_mix_level = LEVEL_MINUS_3DB; + /* set downmixing coefficients if needed */ + if (s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) && + s->fbw_channels == s->out_channels)) { + set_downmix_coeffs(s); + } + } else if (!s->channels) { + av_log(avctx, AV_LOG_ERROR, "unable to determine channel mode\n"); + return AVERROR_INVALIDDATA; + } + avctx->channels = s->out_channels; + + /* set audio service type based on bitstream mode for AC-3 */ + avctx->audio_service_type = s->bitstream_mode; + if (s->bitstream_mode == 0x7 && s->channels > 1) + avctx->audio_service_type = AV_AUDIO_SERVICE_TYPE_KARAOKE; + + /* get output buffer */ + frame->nb_samples = s->num_blocks * 256; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + /* decode the audio blocks */ + channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on]; + for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) { + output[ch] = s->output[ch]; + s->outptr[ch] = s->output[ch]; + } + for (ch = 0; ch < s->channels; ch++) { + if (ch < s->out_channels) + s->outptr[channel_map[ch]] = (float *)frame->data[ch]; + } + for (blk = 0; blk < s->num_blocks; blk++) { + if (!err && decode_audio_block(s, blk)) { + av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n"); + err = 1; + } + if (err) + for (ch = 0; ch < s->out_channels; ch++) + memcpy(((float*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], 1024); + for (ch = 0; ch < s->out_channels; ch++) + output[ch] = s->outptr[channel_map[ch]]; + for (ch = 0; ch < s->out_channels; ch++) { + if (!ch || channel_map[ch]) + s->outptr[channel_map[ch]] += AC3_BLOCK_SIZE; + } + } + + av_frame_set_decode_error_flags(frame, err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0); + + /* keep last block for error concealment in next frame */ + for (ch = 0; ch < s->out_channels; ch++) + memcpy(s->output[ch], output[ch], 1024); + + *got_frame_ptr = 1; + + return FFMIN(buf_size, s->frame_size); +} + +/** + * Uninitialize the AC-3 decoder. + */ +static av_cold int ac3_decode_end(AVCodecContext *avctx) +{ + AC3DecodeContext *s = avctx->priv_data; + ff_mdct_end(&s->imdct_512); + ff_mdct_end(&s->imdct_256); + + return 0; +} + +#define OFFSET(x) offsetof(AC3DecodeContext, x) +#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) +static const AVOption options[] = { + { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 1.0, PAR }, + +{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 2, 0, "dmix_mode"}, +{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, +{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, +{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, +{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, + + { NULL}, +}; + +static const AVClass ac3_decoder_class = { + .class_name = "AC3 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_ac3_decoder = { + .name = "ac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AC3, + .priv_data_size = sizeof (AC3DecodeContext), + .init = ac3_decode_init, + .close = ac3_decode_end, + .decode = ac3_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .priv_class = &ac3_decoder_class, +}; + +#if CONFIG_EAC3_DECODER +static const AVClass eac3_decoder_class = { + .class_name = "E-AC3 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_eac3_decoder = { + .name = "eac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_EAC3, + .priv_data_size = sizeof (AC3DecodeContext), + .init = ac3_decode_init, + .close = ac3_decode_end, + .decode = ac3_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .priv_class = &eac3_decoder_class, +}; +#endif diff --git a/ffmpeg/libavcodec/ac3dec.h b/ffmpeg/libavcodec/ac3dec.h new file mode 100644 index 0000000..6c99ef6 --- /dev/null +++ b/ffmpeg/libavcodec/ac3dec.h @@ -0,0 +1,241 @@ +/* + * Common code between the AC-3 and E-AC-3 decoders + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +/** + * @file + * Common code between the AC-3 and E-AC-3 decoders. + * + * Summary of MDCT Coefficient Grouping: + * The individual MDCT coefficient indices are often referred to in the + * (E-)AC-3 specification as frequency bins. These bins are grouped together + * into subbands of 12 coefficients each. The subbands are grouped together + * into bands as defined in the bitstream by the band structures, which + * determine the number of bands and the size of each band. The full spectrum + * of 256 frequency bins is divided into 1 DC bin + 21 subbands = 253 bins. + * This system of grouping coefficients is used for channel bandwidth, stereo + * rematrixing, channel coupling, enhanced coupling, and spectral extension. + * + * +-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-+ + * |1| |12| | [12|12|12|12] | | | | | | | | | | | | |3| + * +-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-+ + * ~~~ ~~~~ ~~~~~~~~~~~~~ ~~~ + * | | | | + * | | | 3 unused frequency bins--+ + * | | | + * | | +--1 band containing 4 subbands + * | | + * | +--1 subband of 12 frequency bins + * | + * +--DC frequency bin + */ + +#ifndef AVCODEC_AC3DEC_H +#define AVCODEC_AC3DEC_H + +#include "libavutil/float_dsp.h" +#include "libavutil/lfg.h" +#include "ac3.h" +#include "ac3dsp.h" +#include "get_bits.h" +#include "dsputil.h" +#include "fft.h" +#include "fmtconvert.h" + +#define AC3_OUTPUT_LFEON 8 + +#define SPX_MAX_BANDS 17 + +/** Large enough for maximum possible frame size when the specification limit is ignored */ +#define AC3_FRAME_BUFFER_SIZE 32768 + +typedef struct AC3DecodeContext { + AVClass *class; ///< class for AVOptions + AVCodecContext *avctx; ///< parent context + GetBitContext gbc; ///< bitstream reader + +///@name Bit stream information +///@{ + int frame_type; ///< frame type (strmtyp) + int substreamid; ///< substream identification + int frame_size; ///< current frame size, in bytes + int bit_rate; ///< stream bit rate, in bits-per-second + int sample_rate; ///< sample frequency, in Hz + int num_blocks; ///< number of audio blocks + int bitstream_mode; ///< bitstream mode (bsmod) + int channel_mode; ///< channel mode (acmod) + int channel_layout; ///< channel layout + int lfe_on; ///< lfe channel in use + int channel_map; ///< custom channel map + int center_mix_level; ///< Center mix level index + int surround_mix_level; ///< Surround mix level index + int eac3; ///< indicates if current frame is E-AC-3 +///@} + + int preferred_stereo_downmix; + float ltrt_center_mix_level; + float ltrt_surround_mix_level; + float loro_center_mix_level; + float loro_surround_mix_level; + +///@name Frame syntax parameters + int snr_offset_strategy; ///< SNR offset strategy (snroffststr) + int block_switch_syntax; ///< block switch syntax enabled (blkswe) + int dither_flag_syntax; ///< dither flag syntax enabled (dithflage) + int bit_allocation_syntax; ///< bit allocation model syntax enabled (bamode) + int fast_gain_syntax; ///< fast gain codes enabled (frmfgaincode) + int dba_syntax; ///< delta bit allocation syntax enabled (dbaflde) + int skip_syntax; ///< skip field syntax enabled (skipflde) + ///@} + +///@name Standard coupling + int cpl_in_use[AC3_MAX_BLOCKS]; ///< coupling in use (cplinu) + int cpl_strategy_exists[AC3_MAX_BLOCKS];///< coupling strategy exists (cplstre) + int channel_in_cpl[AC3_MAX_CHANNELS]; ///< channel in coupling (chincpl) + int phase_flags_in_use; ///< phase flags in use (phsflginu) + int phase_flags[AC3_MAX_CPL_BANDS]; ///< phase flags (phsflg) + int num_cpl_bands; ///< number of coupling bands (ncplbnd) + uint8_t cpl_band_sizes[AC3_MAX_CPL_BANDS]; ///< number of coeffs in each coupling band + int firstchincpl; ///< first channel in coupling + int first_cpl_coords[AC3_MAX_CHANNELS]; ///< first coupling coordinates states (firstcplcos) + int cpl_coords[AC3_MAX_CHANNELS][AC3_MAX_CPL_BANDS]; ///< coupling coordinates (cplco) +///@} + +///@name Spectral extension +///@{ + int spx_in_use; ///< spectral extension in use (spxinu) + uint8_t channel_uses_spx[AC3_MAX_CHANNELS]; ///< channel uses spectral extension (chinspx) + int8_t spx_atten_code[AC3_MAX_CHANNELS]; ///< spx attenuation code (spxattencod) + int spx_src_start_freq; ///< spx start frequency bin + int spx_dst_end_freq; ///< spx end frequency bin + int spx_dst_start_freq; ///< spx starting frequency bin for copying (copystartmant) + ///< the copy region ends at the start of the spx region. + int num_spx_bands; ///< number of spx bands (nspxbnds) + uint8_t spx_band_sizes[SPX_MAX_BANDS]; ///< number of bins in each spx band + uint8_t first_spx_coords[AC3_MAX_CHANNELS]; ///< first spx coordinates states (firstspxcos) + float spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact) + float spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS];///< spx signal blending factor (sblendfact) +///@} + +///@name Adaptive hybrid transform + int channel_uses_aht[AC3_MAX_CHANNELS]; ///< channel AHT in use (chahtinu) + int pre_mantissa[AC3_MAX_CHANNELS][AC3_MAX_COEFS][AC3_MAX_BLOCKS]; ///< pre-IDCT mantissas +///@} + +///@name Channel + int fbw_channels; ///< number of full-bandwidth channels + int channels; ///< number of total channels + int lfe_ch; ///< index of LFE channel + float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients + int downmixed; ///< indicates if coeffs are currently downmixed + int output_mode; ///< output channel configuration + int out_channels; ///< number of output channels +///@} + +///@name Dynamic range + float dynamic_range[2]; ///< dynamic range + float drc_scale; ///< percentage of dynamic range compression to be applied +///@} + +///@name Bandwidth + int start_freq[AC3_MAX_CHANNELS]; ///< start frequency bin (strtmant) + int end_freq[AC3_MAX_CHANNELS]; ///< end frequency bin (endmant) +///@} + +///@name Rematrixing + int num_rematrixing_bands; ///< number of rematrixing bands (nrematbnd) + int rematrixing_flags[4]; ///< rematrixing flags (rematflg) +///@} + +///@name Exponents + int num_exp_groups[AC3_MAX_CHANNELS]; ///< Number of exponent groups (nexpgrp) + int8_t dexps[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< decoded exponents + int exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS]; ///< exponent strategies (expstr) +///@} + +///@name Bit allocation + AC3BitAllocParameters bit_alloc_params; ///< bit allocation parameters + int first_cpl_leak; ///< first coupling leak state (firstcplleak) + int snr_offset[AC3_MAX_CHANNELS]; ///< signal-to-noise ratio offsets (snroffst) + int fast_gain[AC3_MAX_CHANNELS]; ///< fast gain values/SMR's (fgain) + uint8_t bap[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< bit allocation pointers + int16_t psd[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< scaled exponents + int16_t band_psd[AC3_MAX_CHANNELS][AC3_CRITICAL_BANDS]; ///< interpolated exponents + int16_t mask[AC3_MAX_CHANNELS][AC3_CRITICAL_BANDS]; ///< masking curve values + int dba_mode[AC3_MAX_CHANNELS]; ///< delta bit allocation mode + int dba_nsegs[AC3_MAX_CHANNELS]; ///< number of delta segments + uint8_t dba_offsets[AC3_MAX_CHANNELS][8]; ///< delta segment offsets + uint8_t dba_lengths[AC3_MAX_CHANNELS][8]; ///< delta segment lengths + uint8_t dba_values[AC3_MAX_CHANNELS][8]; ///< delta values for each segment +///@} + +///@name Zero-mantissa dithering + int dither_flag[AC3_MAX_CHANNELS]; ///< dither flags (dithflg) + AVLFG dith_state; ///< for dither generation +///@} + +///@name IMDCT + int block_switch[AC3_MAX_CHANNELS]; ///< block switch flags (blksw) + FFTContext imdct_512; ///< for 512 sample IMDCT + FFTContext imdct_256; ///< for 256 sample IMDCT +///@} + +///@name Optimization + DSPContext dsp; ///< for optimization + AVFloatDSPContext fdsp; + AC3DSPContext ac3dsp; + FmtConvertContext fmt_conv; ///< optimized conversion functions +///@} + + float *outptr[AC3_MAX_CHANNELS]; + float *xcfptr[AC3_MAX_CHANNELS]; + float *dlyptr[AC3_MAX_CHANNELS]; + +///@name Aligned arrays + DECLARE_ALIGNED(16, int, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients + DECLARE_ALIGNED(32, float, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients + DECLARE_ALIGNED(32, float, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block + DECLARE_ALIGNED(32, float, window)[AC3_BLOCK_SIZE]; ///< window coefficients + DECLARE_ALIGNED(32, float, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing + DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing + DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread +///@} +} AC3DecodeContext; + +/** + * Parse the E-AC-3 frame header. + * This parses both the bit stream info and audio frame header. + */ +int ff_eac3_parse_header(AC3DecodeContext *s); + +/** + * Decode mantissas in a single channel for the entire frame. + * This is used when AHT mode is enabled. + */ +void ff_eac3_decode_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch); + +/** + * Apply spectral extension to each channel by copying lower frequency + * coefficients to higher frequency bins and applying side information to + * approximate the original high frequency signal. + */ +void ff_eac3_apply_spectral_extension(AC3DecodeContext *s); + +#endif /* AVCODEC_AC3DEC_H */ diff --git a/ffmpeg/libavcodec/ac3dec_data.c b/ffmpeg/libavcodec/ac3dec_data.c new file mode 100644 index 0000000..d0a9b1e --- /dev/null +++ b/ffmpeg/libavcodec/ac3dec_data.c @@ -0,0 +1,60 @@ +/* + * AC-3 and E-AC-3 decoder tables + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +/** + * @file + * Tables taken directly from the AC-3 spec. + */ + +#include "ac3dec_data.h" +#include "ac3.h" + +/** + * Table used to ungroup 3 values stored in 5 bits. + * Used by bap=1 mantissas and GAQ. + * ff_ac3_ungroup_3_in_5_bits_tab[i] = { i/9, (i%9)/3, (i%9)%3 } + */ +const uint8_t ff_ac3_ungroup_3_in_5_bits_tab[32][3] = { + { 0, 0, 0 }, { 0, 0, 1 }, { 0, 0, 2 }, { 0, 1, 0 }, + { 0, 1, 1 }, { 0, 1, 2 }, { 0, 2, 0 }, { 0, 2, 1 }, + { 0, 2, 2 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 0, 2 }, + { 1, 1, 0 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 2, 0 }, + { 1, 2, 1 }, { 1, 2, 2 }, { 2, 0, 0 }, { 2, 0, 1 }, + { 2, 0, 2 }, { 2, 1, 0 }, { 2, 1, 1 }, { 2, 1, 2 }, + { 2, 2, 0 }, { 2, 2, 1 }, { 2, 2, 2 }, { 3, 0, 0 }, + { 3, 0, 1 }, { 3, 0, 2 }, { 3, 1, 0 }, { 3, 1, 1 } +}; + +const uint8_t ff_eac3_hebap_tab[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, + 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, + 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, + 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, + 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, + 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, + 19, 19, 19, 19, +}; + +/** + * Table E2.15 Default Spectral Extension Banding Structure + */ +const uint8_t ff_eac3_default_spx_band_struct[17] = +{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; diff --git a/ffmpeg/libavcodec/ac3dec_data.h b/ffmpeg/libavcodec/ac3dec_data.h new file mode 100644 index 0000000..975b52e --- /dev/null +++ b/ffmpeg/libavcodec/ac3dec_data.h @@ -0,0 +1,32 @@ +/* + * AC-3 and E-AC-3 decoder tables + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +#ifndef AVCODEC_AC3DEC_DATA_H +#define AVCODEC_AC3DEC_DATA_H + +#include + +extern const uint8_t ff_ac3_ungroup_3_in_5_bits_tab[32][3]; + +extern const uint8_t ff_eac3_hebap_tab[64]; +extern const uint8_t ff_eac3_default_spx_band_struct[17]; + +#endif /* AVCODEC_AC3DEC_DATA_H */ diff --git a/ffmpeg/libavcodec/ac3dsp.c b/ffmpeg/libavcodec/ac3dsp.c new file mode 100644 index 0000000..6df3a68 --- /dev/null +++ b/ffmpeg/libavcodec/ac3dsp.c @@ -0,0 +1,263 @@ +/* + * AC-3 DSP utils + * Copyright (c) 2011 Justin Ruggles + * + * 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 "libavutil/avassert.h" +#include "avcodec.h" +#include "ac3.h" +#include "ac3dsp.h" +#include "mathops.h" + +static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs) +{ + int blk, i; + + if (!num_reuse_blocks) + return; + + for (i = 0; i < nb_coefs; i++) { + uint8_t min_exp = *exp; + uint8_t *exp1 = exp + 256; + for (blk = 0; blk < num_reuse_blocks; blk++) { + uint8_t next_exp = *exp1; + if (next_exp < min_exp) + min_exp = next_exp; + exp1 += 256; + } + *exp++ = min_exp; + } +} + +static int ac3_max_msb_abs_int16_c(const int16_t *src, int len) +{ + int i, v = 0; + for (i = 0; i < len; i++) + v |= abs(src[i]); + return v; +} + +static void ac3_lshift_int16_c(int16_t *src, unsigned int len, + unsigned int shift) +{ + uint32_t *src32 = (uint32_t *)src; + const uint32_t mask = ~(((1 << shift) - 1) << 16); + int i; + len >>= 1; + for (i = 0; i < len; i += 8) { + src32[i ] = (src32[i ] << shift) & mask; + src32[i+1] = (src32[i+1] << shift) & mask; + src32[i+2] = (src32[i+2] << shift) & mask; + src32[i+3] = (src32[i+3] << shift) & mask; + src32[i+4] = (src32[i+4] << shift) & mask; + src32[i+5] = (src32[i+5] << shift) & mask; + src32[i+6] = (src32[i+6] << shift) & mask; + src32[i+7] = (src32[i+7] << shift) & mask; + } +} + +static void ac3_rshift_int32_c(int32_t *src, unsigned int len, + unsigned int shift) +{ + do { + *src++ >>= shift; + *src++ >>= shift; + *src++ >>= shift; + *src++ >>= shift; + *src++ >>= shift; + *src++ >>= shift; + *src++ >>= shift; + *src++ >>= shift; + len -= 8; + } while (len > 0); +} + +static void float_to_fixed24_c(int32_t *dst, const float *src, unsigned int len) +{ + const float scale = 1 << 24; + do { + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + *dst++ = lrintf(*src++ * scale); + len -= 8; + } while (len > 0); +} + +static void ac3_bit_alloc_calc_bap_c(int16_t *mask, int16_t *psd, + int start, int end, + int snr_offset, int floor, + const uint8_t *bap_tab, uint8_t *bap) +{ + int bin, band, band_end; + + /* special case, if snr offset is -960, set all bap's to zero */ + if (snr_offset == -960) { + memset(bap, 0, AC3_MAX_COEFS); + return; + } + + bin = start; + band = ff_ac3_bin_to_band_tab[start]; + do { + int m = (FFMAX(mask[band] - snr_offset - floor, 0) & 0x1FE0) + floor; + band_end = ff_ac3_band_start_tab[++band]; + band_end = FFMIN(band_end, end); + + for (; bin < band_end; bin++) { + int address = av_clip((psd[bin] - m) >> 5, 0, 63); + bap[bin] = bap_tab[address]; + } + } while (end > band_end); +} + +static void ac3_update_bap_counts_c(uint16_t mant_cnt[16], uint8_t *bap, + int len) +{ + while (len-- > 0) + mant_cnt[bap[len]]++; +} + +DECLARE_ALIGNED(16, const uint16_t, ff_ac3_bap_bits)[16] = { + 0, 0, 0, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16 +}; + +static int ac3_compute_mantissa_size_c(uint16_t mant_cnt[6][16]) +{ + int blk, bap; + int bits = 0; + + for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { + // bap=1 : 3 mantissas in 5 bits + bits += (mant_cnt[blk][1] / 3) * 5; + // bap=2 : 3 mantissas in 7 bits + // bap=4 : 2 mantissas in 7 bits + bits += ((mant_cnt[blk][2] / 3) + (mant_cnt[blk][4] >> 1)) * 7; + // bap=3 : 1 mantissa in 3 bits + bits += mant_cnt[blk][3] * 3; + // bap=5 to 15 : get bits per mantissa from table + for (bap = 5; bap < 16; bap++) + bits += mant_cnt[blk][bap] * ff_ac3_bap_bits[bap]; + } + return bits; +} + +static void ac3_extract_exponents_c(uint8_t *exp, int32_t *coef, int nb_coefs) +{ + int i; + + for (i = 0; i < nb_coefs; i++) { + int v = abs(coef[i]); + exp[i] = v ? 23 - av_log2(v) : 24; + } +} + +static void ac3_sum_square_butterfly_int32_c(int64_t sum[4], + const int32_t *coef0, + const int32_t *coef1, + int len) +{ + int i; + + sum[0] = sum[1] = sum[2] = sum[3] = 0; + + for (i = 0; i < len; i++) { + int lt = coef0[i]; + int rt = coef1[i]; + int md = lt + rt; + int sd = lt - rt; + MAC64(sum[0], lt, lt); + MAC64(sum[1], rt, rt); + MAC64(sum[2], md, md); + MAC64(sum[3], sd, sd); + } +} + +static void ac3_sum_square_butterfly_float_c(float sum[4], + const float *coef0, + const float *coef1, + int len) +{ + int i; + + sum[0] = sum[1] = sum[2] = sum[3] = 0; + + for (i = 0; i < len; i++) { + float lt = coef0[i]; + float rt = coef1[i]; + float md = lt + rt; + float sd = lt - rt; + sum[0] += lt * lt; + sum[1] += rt * rt; + sum[2] += md * md; + sum[3] += sd * sd; + } +} + +static void ac3_downmix_c(float **samples, float (*matrix)[2], + int out_ch, int in_ch, int len) +{ + int i, j; + float v0, v1; + if (out_ch == 2) { + for (i = 0; i < len; i++) { + v0 = v1 = 0.0f; + for (j = 0; j < in_ch; j++) { + v0 += samples[j][i] * matrix[j][0]; + v1 += samples[j][i] * matrix[j][1]; + } + samples[0][i] = v0; + samples[1][i] = v1; + } + } else if (out_ch == 1) { + for (i = 0; i < len; i++) { + v0 = 0.0f; + for (j = 0; j < in_ch; j++) + v0 += samples[j][i] * matrix[j][0]; + samples[0][i] = v0; + } + } +} + +av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) +{ + c->ac3_exponent_min = ac3_exponent_min_c; + c->ac3_max_msb_abs_int16 = ac3_max_msb_abs_int16_c; + c->ac3_lshift_int16 = ac3_lshift_int16_c; + c->ac3_rshift_int32 = ac3_rshift_int32_c; + c->float_to_fixed24 = float_to_fixed24_c; + c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_c; + c->update_bap_counts = ac3_update_bap_counts_c; + c->compute_mantissa_size = ac3_compute_mantissa_size_c; + c->extract_exponents = ac3_extract_exponents_c; + c->sum_square_butterfly_int32 = ac3_sum_square_butterfly_int32_c; + c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_c; + c->downmix = ac3_downmix_c; + + if (ARCH_ARM) + ff_ac3dsp_init_arm(c, bit_exact); + if (ARCH_X86) + ff_ac3dsp_init_x86(c, bit_exact); + if (ARCH_MIPS) + ff_ac3dsp_init_mips(c, bit_exact); +} diff --git a/ffmpeg/libavcodec/ac3dsp.h b/ffmpeg/libavcodec/ac3dsp.h new file mode 100644 index 0000000..bafbc89 --- /dev/null +++ b/ffmpeg/libavcodec/ac3dsp.h @@ -0,0 +1,144 @@ +/* + * AC-3 DSP utils + * Copyright (c) 2011 Justin Ruggles + * + * 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 + */ + +#ifndef AVCODEC_AC3DSP_H +#define AVCODEC_AC3DSP_H + +#include + +/** + * Number of mantissa bits written for each bap value. + * bap values with fractional bits are set to 0 and are calculated separately. + */ +extern const uint16_t ff_ac3_bap_bits[16]; + +typedef struct AC3DSPContext { + /** + * Set each encoded exponent in a block to the minimum of itself and the + * exponents in the same frequency bin of up to 5 following blocks. + * @param exp pointer to the start of the current block of exponents. + * constraints: align 16 + * @param num_reuse_blocks number of blocks that will reuse exponents from the current block. + * constraints: range 0 to 5 + * @param nb_coefs number of frequency coefficients. + */ + void (*ac3_exponent_min)(uint8_t *exp, int num_reuse_blocks, int nb_coefs); + + /** + * Calculate the maximum MSB of the absolute value of each element in an + * array of int16_t. + * @param src input array + * constraints: align 16. values must be in range [-32767,32767] + * @param len number of values in the array + * constraints: multiple of 16 greater than 0 + * @return a value with the same MSB as max(abs(src[])) + */ + int (*ac3_max_msb_abs_int16)(const int16_t *src, int len); + + /** + * Left-shift each value in an array of int16_t by a specified amount. + * @param src input array + * constraints: align 16 + * @param len number of values in the array + * constraints: multiple of 32 greater than 0 + * @param shift left shift amount + * constraints: range [0,15] + */ + void (*ac3_lshift_int16)(int16_t *src, unsigned int len, unsigned int shift); + + /** + * Right-shift each value in an array of int32_t by a specified amount. + * @param src input array + * constraints: align 16 + * @param len number of values in the array + * constraints: multiple of 16 greater than 0 + * @param shift right shift amount + * constraints: range [0,31] + */ + void (*ac3_rshift_int32)(int32_t *src, unsigned int len, unsigned int shift); + + /** + * Convert an array of float in range [-1.0,1.0] to int32_t with range + * [-(1<<24),(1<<24)] + * + * @param dst destination array of int32_t. + * constraints: 16-byte aligned + * @param src source array of float. + * constraints: 16-byte aligned + * @param len number of elements to convert. + * constraints: multiple of 32 greater than zero + */ + void (*float_to_fixed24)(int32_t *dst, const float *src, unsigned int len); + + /** + * Calculate bit allocation pointers. + * The SNR is the difference between the masking curve and the signal. AC-3 + * uses this value for each frequency bin to allocate bits. The snroffset + * parameter is a global adjustment to the SNR for all bins. + * + * @param[in] mask masking curve + * @param[in] psd signal power for each frequency bin + * @param[in] start starting bin location + * @param[in] end ending bin location + * @param[in] snr_offset SNR adjustment + * @param[in] floor noise floor + * @param[in] bap_tab look-up table for bit allocation pointers + * @param[out] bap bit allocation pointers + */ + void (*bit_alloc_calc_bap)(int16_t *mask, int16_t *psd, int start, int end, + int snr_offset, int floor, + const uint8_t *bap_tab, uint8_t *bap); + + /** + * Update bap counts using the supplied array of bap. + * + * @param[out] mant_cnt bap counts for 1 block + * @param[in] bap array of bap, pointing to start coef bin + * @param[in] len number of elements to process + */ + void (*update_bap_counts)(uint16_t mant_cnt[16], uint8_t *bap, int len); + + /** + * Calculate the number of bits needed to encode a set of mantissas. + * + * @param[in] mant_cnt bap counts for all blocks + * @return mantissa bit count + */ + int (*compute_mantissa_size)(uint16_t mant_cnt[6][16]); + + void (*extract_exponents)(uint8_t *exp, int32_t *coef, int nb_coefs); + + void (*sum_square_butterfly_int32)(int64_t sum[4], const int32_t *coef0, + const int32_t *coef1, int len); + + void (*sum_square_butterfly_float)(float sum[4], const float *coef0, + const float *coef1, int len); + + void (*downmix)(float **samples, float (*matrix)[2], int out_ch, + int in_ch, int len); +} AC3DSPContext; + +void ff_ac3dsp_init (AC3DSPContext *c, int bit_exact); +void ff_ac3dsp_init_arm(AC3DSPContext *c, int bit_exact); +void ff_ac3dsp_init_x86(AC3DSPContext *c, int bit_exact); +void ff_ac3dsp_init_mips(AC3DSPContext *c, int bit_exact); + +#endif /* AVCODEC_AC3DSP_H */ diff --git a/ffmpeg/libavcodec/ac3enc.c b/ffmpeg/libavcodec/ac3enc.c new file mode 100644 index 0000000..15ff343 --- /dev/null +++ b/ffmpeg/libavcodec/ac3enc.c @@ -0,0 +1,2491 @@ +/* + * The simplest AC-3 encoder + * Copyright (c) 2000 Fabrice Bellard + * Copyright (c) 2006-2010 Justin Ruggles + * Copyright (c) 2006-2010 Prakash Punnoor + * + * 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 + */ + +/** + * @file + * The simplest AC-3 encoder. + */ + +//#define ASSERT_LEVEL 2 + +#include + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" +#include "libavutil/crc.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "put_bits.h" +#include "ac3dsp.h" +#include "ac3.h" +#include "fft.h" +#include "ac3enc.h" +#include "eac3enc.h" + +typedef struct AC3Mant { + int16_t *qmant1_ptr, *qmant2_ptr, *qmant4_ptr; ///< mantissa pointers for bap=1,2,4 + int mant1_cnt, mant2_cnt, mant4_cnt; ///< mantissa counts for bap=1,2,4 +} AC3Mant; + +#define CMIXLEV_NUM_OPTIONS 3 +static const float cmixlev_options[CMIXLEV_NUM_OPTIONS] = { + LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB +}; + +#define SURMIXLEV_NUM_OPTIONS 3 +static const float surmixlev_options[SURMIXLEV_NUM_OPTIONS] = { + LEVEL_MINUS_3DB, LEVEL_MINUS_6DB, LEVEL_ZERO +}; + +#define EXTMIXLEV_NUM_OPTIONS 8 +static const float extmixlev_options[EXTMIXLEV_NUM_OPTIONS] = { + LEVEL_PLUS_3DB, LEVEL_PLUS_1POINT5DB, LEVEL_ONE, LEVEL_MINUS_4POINT5DB, + LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB, LEVEL_MINUS_6DB, LEVEL_ZERO +}; + + +/** + * LUT for number of exponent groups. + * exponent_group_tab[coupling][exponent strategy-1][number of coefficients] + */ +static uint8_t exponent_group_tab[2][3][256]; + + +/** + * List of supported channel layouts. + */ +const uint64_t ff_ac3_channel_layouts[19] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + (AV_CH_LAYOUT_MONO | AV_CH_LOW_FREQUENCY), + (AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY), + (AV_CH_LAYOUT_2_1 | AV_CH_LOW_FREQUENCY), + (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY), + (AV_CH_LAYOUT_2_2 | AV_CH_LOW_FREQUENCY), + (AV_CH_LAYOUT_QUAD | AV_CH_LOW_FREQUENCY), + (AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY), + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_5POINT1_BACK, + 0 +}; + + +/** + * LUT to select the bandwidth code based on the bit rate, sample rate, and + * number of full-bandwidth channels. + * bandwidth_tab[fbw_channels-1][sample rate code][bit rate code] + */ +static const uint8_t ac3_bandwidth_tab[5][3][19] = { +// 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 + + { { 0, 0, 0, 12, 16, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 16, 20, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 32, 40, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 20, 24, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 4, 24, 28, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 20, 44, 52, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 24, 32, 40, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 4, 20, 28, 36, 44, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 20, 40, 48, 60, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 32, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 28, 36, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 48, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 32, 40, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 36, 44, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 44, 60, 60, 60, 60, 60, 60 } } +}; + + +/** + * LUT to select the coupling start band based on the bit rate, sample rate, and + * number of full-bandwidth channels. -1 = coupling off + * ac3_coupling_start_tab[channel_mode-2][sample rate code][bit rate code] + * + * TODO: more testing for optimal parameters. + * multi-channel tests at 44.1kHz and 32kHz. + */ +static const int8_t ac3_coupling_start_tab[6][3][19] = { +// 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 + + // 2/0 + { { 0, 0, 0, 0, 0, 0, 0, 1, 1, 7, 8, 11, 12, -1, -1, -1, -1, -1, -1 }, + { 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 10, 12, 13, -1, -1, -1, -1, -1, -1 }, + { 0, 0, 0, 0, 1, 2, 2, 9, 13, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + + // 3/0 + { { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + + // 2/1 - untested + { { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 6, 9, 11, 12, 13, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + + // 3/1 + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + + // 2/2 - untested + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 10, 11, 11, 12, 12, 14, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + + // 3/2 + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 8, 11, 12, 12, -1, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 8, 11, 12, 12, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, +}; + + +/** + * Adjust the frame size to make the average bit rate match the target bit rate. + * This is only needed for 11025, 22050, and 44100 sample rates or any E-AC-3. + * + * @param s AC-3 encoder private context + */ +void ff_ac3_adjust_frame_size(AC3EncodeContext *s) +{ + while (s->bits_written >= s->bit_rate && s->samples_written >= s->sample_rate) { + s->bits_written -= s->bit_rate; + s->samples_written -= s->sample_rate; + } + s->frame_size = s->frame_size_min + + 2 * (s->bits_written * s->sample_rate < s->samples_written * s->bit_rate); + s->bits_written += s->frame_size * 8; + s->samples_written += AC3_BLOCK_SIZE * s->num_blocks; +} + + +/** + * Set the initial coupling strategy parameters prior to coupling analysis. + * + * @param s AC-3 encoder private context + */ +void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s) +{ + int blk, ch; + int got_cpl_snr; + int num_cpl_blocks; + + /* set coupling use flags for each block/channel */ + /* TODO: turn coupling on/off and adjust start band based on bit usage */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = 1; ch <= s->fbw_channels; ch++) + block->channel_in_cpl[ch] = s->cpl_on; + } + + /* enable coupling for each block if at least 2 channels have coupling + enabled for that block */ + got_cpl_snr = 0; + num_cpl_blocks = 0; + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + block->num_cpl_channels = 0; + for (ch = 1; ch <= s->fbw_channels; ch++) + block->num_cpl_channels += block->channel_in_cpl[ch]; + block->cpl_in_use = block->num_cpl_channels > 1; + num_cpl_blocks += block->cpl_in_use; + if (!block->cpl_in_use) { + block->num_cpl_channels = 0; + for (ch = 1; ch <= s->fbw_channels; ch++) + block->channel_in_cpl[ch] = 0; + } + + block->new_cpl_strategy = !blk; + if (blk) { + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (block->channel_in_cpl[ch] != s->blocks[blk-1].channel_in_cpl[ch]) { + block->new_cpl_strategy = 1; + break; + } + } + } + block->new_cpl_leak = block->new_cpl_strategy; + + if (!blk || (block->cpl_in_use && !got_cpl_snr)) { + block->new_snr_offsets = 1; + if (block->cpl_in_use) + got_cpl_snr = 1; + } else { + block->new_snr_offsets = 0; + } + } + if (!num_cpl_blocks) + s->cpl_on = 0; + + /* set bandwidth for each channel */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (block->channel_in_cpl[ch]) + block->end_freq[ch] = s->start_freq[CPL_CH]; + else + block->end_freq[ch] = s->bandwidth_code * 3 + 73; + } + } +} + + +/** + * Apply stereo rematrixing to coefficients based on rematrixing flags. + * + * @param s AC-3 encoder private context + */ +void ff_ac3_apply_rematrixing(AC3EncodeContext *s) +{ + int nb_coefs; + int blk, bnd, i; + int start, end; + uint8_t *flags = NULL; + + if (!s->rematrixing_enabled) + return; + + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + if (block->new_rematrixing_strategy) + flags = block->rematrixing_flags; + nb_coefs = FFMIN(block->end_freq[1], block->end_freq[2]); + for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) { + if (flags[bnd]) { + start = ff_ac3_rematrix_band_tab[bnd]; + end = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]); + for (i = start; i < end; i++) { + int32_t lt = block->fixed_coef[1][i]; + int32_t rt = block->fixed_coef[2][i]; + block->fixed_coef[1][i] = (lt + rt) >> 1; + block->fixed_coef[2][i] = (lt - rt) >> 1; + } + } + } + } +} + + +/* + * Initialize exponent tables. + */ +static av_cold void exponent_init(AC3EncodeContext *s) +{ + int expstr, i, grpsize; + + for (expstr = EXP_D15-1; expstr <= EXP_D45-1; expstr++) { + grpsize = 3 << expstr; + for (i = 12; i < 256; i++) { + exponent_group_tab[0][expstr][i] = (i + grpsize - 4) / grpsize; + exponent_group_tab[1][expstr][i] = (i ) / grpsize; + } + } + /* LFE */ + exponent_group_tab[0][0][7] = 2; + + if (CONFIG_EAC3_ENCODER && s->eac3) + ff_eac3_exponent_init(); +} + + +/* + * Extract exponents from the MDCT coefficients. + */ +static void extract_exponents(AC3EncodeContext *s) +{ + int ch = !s->cpl_on; + int chan_size = AC3_MAX_COEFS * s->num_blocks * (s->channels - ch + 1); + AC3Block *block = &s->blocks[0]; + + s->ac3dsp.extract_exponents(block->exp[ch], block->fixed_coef[ch], chan_size); +} + + +/** + * Exponent Difference Threshold. + * New exponents are sent if their SAD exceed this number. + */ +#define EXP_DIFF_THRESHOLD 500 + +/** + * Table used to select exponent strategy based on exponent reuse block interval. + */ +static const uint8_t exp_strategy_reuse_tab[4][6] = { + { EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15 }, + { EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15 }, + { EXP_D25, EXP_D25, EXP_D15, EXP_D15, EXP_D15, EXP_D15 }, + { EXP_D45, EXP_D25, EXP_D25, EXP_D15, EXP_D15, EXP_D15 } +}; + +/* + * Calculate exponent strategies for all channels. + * Array arrangement is reversed to simplify the per-channel calculation. + */ +static void compute_exp_strategy(AC3EncodeContext *s) +{ + int ch, blk, blk1; + + for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) { + uint8_t *exp_strategy = s->exp_strategy[ch]; + uint8_t *exp = s->blocks[0].exp[ch]; + int exp_diff; + + /* estimate if the exponent variation & decide if they should be + reused in the next frame */ + exp_strategy[0] = EXP_NEW; + exp += AC3_MAX_COEFS; + for (blk = 1; blk < s->num_blocks; blk++, exp += AC3_MAX_COEFS) { + if (ch == CPL_CH) { + if (!s->blocks[blk-1].cpl_in_use) { + exp_strategy[blk] = EXP_NEW; + continue; + } else if (!s->blocks[blk].cpl_in_use) { + exp_strategy[blk] = EXP_REUSE; + continue; + } + } else if (s->blocks[blk].channel_in_cpl[ch] != s->blocks[blk-1].channel_in_cpl[ch]) { + exp_strategy[blk] = EXP_NEW; + continue; + } + exp_diff = s->dsp.sad[0](NULL, exp, exp - AC3_MAX_COEFS, 16, 16); + exp_strategy[blk] = EXP_REUSE; + if (ch == CPL_CH && exp_diff > (EXP_DIFF_THRESHOLD * (s->blocks[blk].end_freq[ch] - s->start_freq[ch]) / AC3_MAX_COEFS)) + exp_strategy[blk] = EXP_NEW; + else if (ch > CPL_CH && exp_diff > EXP_DIFF_THRESHOLD) + exp_strategy[blk] = EXP_NEW; + } + + /* now select the encoding strategy type : if exponents are often + recoded, we use a coarse encoding */ + blk = 0; + while (blk < s->num_blocks) { + blk1 = blk + 1; + while (blk1 < s->num_blocks && exp_strategy[blk1] == EXP_REUSE) + blk1++; + exp_strategy[blk] = exp_strategy_reuse_tab[s->num_blks_code][blk1-blk-1]; + blk = blk1; + } + } + if (s->lfe_on) { + ch = s->lfe_channel; + s->exp_strategy[ch][0] = EXP_D15; + for (blk = 1; blk < s->num_blocks; blk++) + s->exp_strategy[ch][blk] = EXP_REUSE; + } + + /* for E-AC-3, determine frame exponent strategy */ + if (CONFIG_EAC3_ENCODER && s->eac3) + ff_eac3_get_frame_exp_strategy(s); +} + + +/** + * Update the exponents so that they are the ones the decoder will decode. + * + * @param[in,out] exp array of exponents for 1 block in 1 channel + * @param nb_exps number of exponents in active bandwidth + * @param exp_strategy exponent strategy for the block + * @param cpl indicates if the block is in the coupling channel + */ +static void encode_exponents_blk_ch(uint8_t *exp, int nb_exps, int exp_strategy, + int cpl) +{ + int nb_groups, i, k; + + nb_groups = exponent_group_tab[cpl][exp_strategy-1][nb_exps] * 3; + + /* for each group, compute the minimum exponent */ + switch(exp_strategy) { + case EXP_D25: + for (i = 1, k = 1-cpl; i <= nb_groups; i++) { + uint8_t exp_min = exp[k]; + if (exp[k+1] < exp_min) + exp_min = exp[k+1]; + exp[i-cpl] = exp_min; + k += 2; + } + break; + case EXP_D45: + for (i = 1, k = 1-cpl; i <= nb_groups; i++) { + uint8_t exp_min = exp[k]; + if (exp[k+1] < exp_min) + exp_min = exp[k+1]; + if (exp[k+2] < exp_min) + exp_min = exp[k+2]; + if (exp[k+3] < exp_min) + exp_min = exp[k+3]; + exp[i-cpl] = exp_min; + k += 4; + } + break; + } + + /* constraint for DC exponent */ + if (!cpl && exp[0] > 15) + exp[0] = 15; + + /* decrease the delta between each groups to within 2 so that they can be + differentially encoded */ + for (i = 1; i <= nb_groups; i++) + exp[i] = FFMIN(exp[i], exp[i-1] + 2); + i--; + while (--i >= 0) + exp[i] = FFMIN(exp[i], exp[i+1] + 2); + + if (cpl) + exp[-1] = exp[0] & ~1; + + /* now we have the exponent values the decoder will see */ + switch (exp_strategy) { + case EXP_D25: + for (i = nb_groups, k = (nb_groups * 2)-cpl; i > 0; i--) { + uint8_t exp1 = exp[i-cpl]; + exp[k--] = exp1; + exp[k--] = exp1; + } + break; + case EXP_D45: + for (i = nb_groups, k = (nb_groups * 4)-cpl; i > 0; i--) { + exp[k] = exp[k-1] = exp[k-2] = exp[k-3] = exp[i-cpl]; + k -= 4; + } + break; + } +} + + +/* + * Encode exponents from original extracted form to what the decoder will see. + * This copies and groups exponents based on exponent strategy and reduces + * deltas between adjacent exponent groups so that they can be differentially + * encoded. + */ +static void encode_exponents(AC3EncodeContext *s) +{ + int blk, blk1, ch, cpl; + uint8_t *exp, *exp_strategy; + int nb_coefs, num_reuse_blocks; + + for (ch = !s->cpl_on; ch <= s->channels; ch++) { + exp = s->blocks[0].exp[ch] + s->start_freq[ch]; + exp_strategy = s->exp_strategy[ch]; + + cpl = (ch == CPL_CH); + blk = 0; + while (blk < s->num_blocks) { + AC3Block *block = &s->blocks[blk]; + if (cpl && !block->cpl_in_use) { + exp += AC3_MAX_COEFS; + blk++; + continue; + } + nb_coefs = block->end_freq[ch] - s->start_freq[ch]; + blk1 = blk + 1; + + /* count the number of EXP_REUSE blocks after the current block + and set exponent reference block numbers */ + s->exp_ref_block[ch][blk] = blk; + while (blk1 < s->num_blocks && exp_strategy[blk1] == EXP_REUSE) { + s->exp_ref_block[ch][blk1] = blk; + blk1++; + } + num_reuse_blocks = blk1 - blk - 1; + + /* for the EXP_REUSE case we select the min of the exponents */ + s->ac3dsp.ac3_exponent_min(exp-s->start_freq[ch], num_reuse_blocks, + AC3_MAX_COEFS); + + encode_exponents_blk_ch(exp, nb_coefs, exp_strategy[blk], cpl); + + exp += AC3_MAX_COEFS * (num_reuse_blocks + 1); + blk = blk1; + } + } + + /* reference block numbers have been changed, so reset ref_bap_set */ + s->ref_bap_set = 0; +} + + +/* + * Count exponent bits based on bandwidth, coupling, and exponent strategies. + */ +static int count_exponent_bits(AC3EncodeContext *s) +{ + int blk, ch; + int nb_groups, bit_count; + + bit_count = 0; + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = !block->cpl_in_use; ch <= s->channels; ch++) { + int exp_strategy = s->exp_strategy[ch][blk]; + int cpl = (ch == CPL_CH); + int nb_coefs = block->end_freq[ch] - s->start_freq[ch]; + + if (exp_strategy == EXP_REUSE) + continue; + + nb_groups = exponent_group_tab[cpl][exp_strategy-1][nb_coefs]; + bit_count += 4 + (nb_groups * 7); + } + } + + return bit_count; +} + + +/** + * Group exponents. + * 3 delta-encoded exponents are in each 7-bit group. The number of groups + * varies depending on exponent strategy and bandwidth. + * + * @param s AC-3 encoder private context + */ +void ff_ac3_group_exponents(AC3EncodeContext *s) +{ + int blk, ch, i, cpl; + int group_size, nb_groups; + uint8_t *p; + int delta0, delta1, delta2; + int exp0, exp1; + + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = !block->cpl_in_use; ch <= s->channels; ch++) { + int exp_strategy = s->exp_strategy[ch][blk]; + if (exp_strategy == EXP_REUSE) + continue; + cpl = (ch == CPL_CH); + group_size = exp_strategy + (exp_strategy == EXP_D45); + nb_groups = exponent_group_tab[cpl][exp_strategy-1][block->end_freq[ch]-s->start_freq[ch]]; + p = block->exp[ch] + s->start_freq[ch] - cpl; + + /* DC exponent */ + exp1 = *p++; + block->grouped_exp[ch][0] = exp1; + + /* remaining exponents are delta encoded */ + for (i = 1; i <= nb_groups; i++) { + /* merge three delta in one code */ + exp0 = exp1; + exp1 = p[0]; + p += group_size; + delta0 = exp1 - exp0 + 2; + av_assert2(delta0 >= 0 && delta0 <= 4); + + exp0 = exp1; + exp1 = p[0]; + p += group_size; + delta1 = exp1 - exp0 + 2; + av_assert2(delta1 >= 0 && delta1 <= 4); + + exp0 = exp1; + exp1 = p[0]; + p += group_size; + delta2 = exp1 - exp0 + 2; + av_assert2(delta2 >= 0 && delta2 <= 4); + + block->grouped_exp[ch][i] = ((delta0 * 5 + delta1) * 5) + delta2; + } + } + } +} + + +/** + * Calculate final exponents from the supplied MDCT coefficients and exponent shift. + * Extract exponents from MDCT coefficients, calculate exponent strategies, + * and encode final exponents. + * + * @param s AC-3 encoder private context + */ +void ff_ac3_process_exponents(AC3EncodeContext *s) +{ + extract_exponents(s); + + compute_exp_strategy(s); + + encode_exponents(s); + + emms_c(); +} + + +/* + * Count frame bits that are based solely on fixed parameters. + * This only has to be run once when the encoder is initialized. + */ +static void count_frame_bits_fixed(AC3EncodeContext *s) +{ + static const int frame_bits_inc[8] = { 0, 0, 2, 2, 2, 4, 2, 4 }; + int blk; + int frame_bits; + + /* assumptions: + * no dynamic range codes + * bit allocation parameters do not change between blocks + * no delta bit allocation + * no skipped data + * no auxiliary data + * no E-AC-3 metadata + */ + + /* header */ + frame_bits = 16; /* sync info */ + if (s->eac3) { + /* bitstream info header */ + frame_bits += 35; + frame_bits += 1 + 1; + if (s->num_blocks != 0x6) + frame_bits++; + frame_bits++; + /* audio frame header */ + if (s->num_blocks == 6) + frame_bits += 2; + frame_bits += 10; + /* exponent strategy */ + if (s->use_frame_exp_strategy) + frame_bits += 5 * s->fbw_channels; + else + frame_bits += s->num_blocks * 2 * s->fbw_channels; + if (s->lfe_on) + frame_bits += s->num_blocks; + /* converter exponent strategy */ + if (s->num_blks_code != 0x3) + frame_bits++; + else + frame_bits += s->fbw_channels * 5; + /* snr offsets */ + frame_bits += 10; + /* block start info */ + if (s->num_blocks != 1) + frame_bits++; + } else { + frame_bits += 49; + frame_bits += frame_bits_inc[s->channel_mode]; + } + + /* audio blocks */ + for (blk = 0; blk < s->num_blocks; blk++) { + if (!s->eac3) { + /* block switch flags */ + frame_bits += s->fbw_channels; + + /* dither flags */ + frame_bits += s->fbw_channels; + } + + /* dynamic range */ + frame_bits++; + + /* spectral extension */ + if (s->eac3) + frame_bits++; + + if (!s->eac3) { + /* exponent strategy */ + frame_bits += 2 * s->fbw_channels; + if (s->lfe_on) + frame_bits++; + + /* bit allocation params */ + frame_bits++; + if (!blk) + frame_bits += 2 + 2 + 2 + 2 + 3; + } + + /* converter snr offset */ + if (s->eac3) + frame_bits++; + + if (!s->eac3) { + /* delta bit allocation */ + frame_bits++; + + /* skipped data */ + frame_bits++; + } + } + + /* auxiliary data */ + frame_bits++; + + /* CRC */ + frame_bits += 1 + 16; + + s->frame_bits_fixed = frame_bits; +} + + +/* + * Initialize bit allocation. + * Set default parameter codes and calculate parameter values. + */ +static void bit_alloc_init(AC3EncodeContext *s) +{ + int ch; + + /* init default parameters */ + s->slow_decay_code = 2; + s->fast_decay_code = 1; + s->slow_gain_code = 1; + s->db_per_bit_code = s->eac3 ? 2 : 3; + s->floor_code = 7; + for (ch = 0; ch <= s->channels; ch++) + s->fast_gain_code[ch] = 4; + + /* initial snr offset */ + s->coarse_snr_offset = 40; + + /* compute real values */ + /* currently none of these values change during encoding, so we can just + set them once at initialization */ + s->bit_alloc.slow_decay = ff_ac3_slow_decay_tab[s->slow_decay_code] >> s->bit_alloc.sr_shift; + s->bit_alloc.fast_decay = ff_ac3_fast_decay_tab[s->fast_decay_code] >> s->bit_alloc.sr_shift; + s->bit_alloc.slow_gain = ff_ac3_slow_gain_tab[s->slow_gain_code]; + s->bit_alloc.db_per_bit = ff_ac3_db_per_bit_tab[s->db_per_bit_code]; + s->bit_alloc.floor = ff_ac3_floor_tab[s->floor_code]; + s->bit_alloc.cpl_fast_leak = 0; + s->bit_alloc.cpl_slow_leak = 0; + + count_frame_bits_fixed(s); +} + + +/* + * Count the bits used to encode the frame, minus exponents and mantissas. + * Bits based on fixed parameters have already been counted, so now we just + * have to add the bits based on parameters that change during encoding. + */ +static void count_frame_bits(AC3EncodeContext *s) +{ + AC3EncOptions *opt = &s->options; + int blk, ch; + int frame_bits = 0; + + /* header */ + if (s->eac3) { + if (opt->eac3_mixing_metadata) { + if (s->channel_mode > AC3_CHMODE_STEREO) + frame_bits += 2; + if (s->has_center) + frame_bits += 6; + if (s->has_surround) + frame_bits += 6; + frame_bits += s->lfe_on; + frame_bits += 1 + 1 + 2; + if (s->channel_mode < AC3_CHMODE_STEREO) + frame_bits++; + frame_bits++; + } + if (opt->eac3_info_metadata) { + frame_bits += 3 + 1 + 1; + if (s->channel_mode == AC3_CHMODE_STEREO) + frame_bits += 2 + 2; + if (s->channel_mode >= AC3_CHMODE_2F2R) + frame_bits += 2; + frame_bits++; + if (opt->audio_production_info) + frame_bits += 5 + 2 + 1; + frame_bits++; + } + /* coupling */ + if (s->channel_mode > AC3_CHMODE_MONO) { + frame_bits++; + for (blk = 1; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + frame_bits++; + if (block->new_cpl_strategy) + frame_bits++; + } + } + /* coupling exponent strategy */ + if (s->cpl_on) { + if (s->use_frame_exp_strategy) { + frame_bits += 5 * s->cpl_on; + } else { + for (blk = 0; blk < s->num_blocks; blk++) + frame_bits += 2 * s->blocks[blk].cpl_in_use; + } + } + } else { + if (opt->audio_production_info) + frame_bits += 7; + if (s->bitstream_id == 6) { + if (opt->extended_bsi_1) + frame_bits += 14; + if (opt->extended_bsi_2) + frame_bits += 14; + } + } + + /* audio blocks */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + + /* coupling strategy */ + if (!s->eac3) + frame_bits++; + if (block->new_cpl_strategy) { + if (!s->eac3) + frame_bits++; + if (block->cpl_in_use) { + if (s->eac3) + frame_bits++; + if (!s->eac3 || s->channel_mode != AC3_CHMODE_STEREO) + frame_bits += s->fbw_channels; + if (s->channel_mode == AC3_CHMODE_STEREO) + frame_bits++; + frame_bits += 4 + 4; + if (s->eac3) + frame_bits++; + else + frame_bits += s->num_cpl_subbands - 1; + } + } + + /* coupling coordinates */ + if (block->cpl_in_use) { + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (block->channel_in_cpl[ch]) { + if (!s->eac3 || block->new_cpl_coords[ch] != 2) + frame_bits++; + if (block->new_cpl_coords[ch]) { + frame_bits += 2; + frame_bits += (4 + 4) * s->num_cpl_bands; + } + } + } + } + + /* stereo rematrixing */ + if (s->channel_mode == AC3_CHMODE_STEREO) { + if (!s->eac3 || blk > 0) + frame_bits++; + if (s->blocks[blk].new_rematrixing_strategy) + frame_bits += block->num_rematrixing_bands; + } + + /* bandwidth codes & gain range */ + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (s->exp_strategy[ch][blk] != EXP_REUSE) { + if (!block->channel_in_cpl[ch]) + frame_bits += 6; + frame_bits += 2; + } + } + + /* coupling exponent strategy */ + if (!s->eac3 && block->cpl_in_use) + frame_bits += 2; + + /* snr offsets and fast gain codes */ + if (!s->eac3) { + frame_bits++; + if (block->new_snr_offsets) + frame_bits += 6 + (s->channels + block->cpl_in_use) * (4 + 3); + } + + /* coupling leak info */ + if (block->cpl_in_use) { + if (!s->eac3 || block->new_cpl_leak != 2) + frame_bits++; + if (block->new_cpl_leak) + frame_bits += 3 + 3; + } + } + + s->frame_bits = s->frame_bits_fixed + frame_bits; +} + + +/* + * Calculate masking curve based on the final exponents. + * Also calculate the power spectral densities to use in future calculations. + */ +static void bit_alloc_masking(AC3EncodeContext *s) +{ + int blk, ch; + + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = !block->cpl_in_use; ch <= s->channels; ch++) { + /* We only need psd and mask for calculating bap. + Since we currently do not calculate bap when exponent + strategy is EXP_REUSE we do not need to calculate psd or mask. */ + if (s->exp_strategy[ch][blk] != EXP_REUSE) { + ff_ac3_bit_alloc_calc_psd(block->exp[ch], s->start_freq[ch], + block->end_freq[ch], block->psd[ch], + block->band_psd[ch]); + ff_ac3_bit_alloc_calc_mask(&s->bit_alloc, block->band_psd[ch], + s->start_freq[ch], block->end_freq[ch], + ff_ac3_fast_gain_tab[s->fast_gain_code[ch]], + ch == s->lfe_channel, + DBA_NONE, 0, NULL, NULL, NULL, + block->mask[ch]); + } + } + } +} + + +/* + * Ensure that bap for each block and channel point to the current bap_buffer. + * They may have been switched during the bit allocation search. + */ +static void reset_block_bap(AC3EncodeContext *s) +{ + int blk, ch; + uint8_t *ref_bap; + + if (s->ref_bap[0][0] == s->bap_buffer && s->ref_bap_set) + return; + + ref_bap = s->bap_buffer; + for (ch = 0; ch <= s->channels; ch++) { + for (blk = 0; blk < s->num_blocks; blk++) + s->ref_bap[ch][blk] = ref_bap + AC3_MAX_COEFS * s->exp_ref_block[ch][blk]; + ref_bap += AC3_MAX_COEFS * s->num_blocks; + } + s->ref_bap_set = 1; +} + + +/** + * Initialize mantissa counts. + * These are set so that they are padded to the next whole group size when bits + * are counted in compute_mantissa_size. + * + * @param[in,out] mant_cnt running counts for each bap value for each block + */ +static void count_mantissa_bits_init(uint16_t mant_cnt[AC3_MAX_BLOCKS][16]) +{ + int blk; + + for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { + memset(mant_cnt[blk], 0, sizeof(mant_cnt[blk])); + mant_cnt[blk][1] = mant_cnt[blk][2] = 2; + mant_cnt[blk][4] = 1; + } +} + + +/** + * Update mantissa bit counts for all blocks in 1 channel in a given bandwidth + * range. + * + * @param s AC-3 encoder private context + * @param ch channel index + * @param[in,out] mant_cnt running counts for each bap value for each block + * @param start starting coefficient bin + * @param end ending coefficient bin + */ +static void count_mantissa_bits_update_ch(AC3EncodeContext *s, int ch, + uint16_t mant_cnt[AC3_MAX_BLOCKS][16], + int start, int end) +{ + int blk; + + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + if (ch == CPL_CH && !block->cpl_in_use) + continue; + s->ac3dsp.update_bap_counts(mant_cnt[blk], + s->ref_bap[ch][blk] + start, + FFMIN(end, block->end_freq[ch]) - start); + } +} + + +/* + * Count the number of mantissa bits in the frame based on the bap values. + */ +static int count_mantissa_bits(AC3EncodeContext *s) +{ + int ch, max_end_freq; + LOCAL_ALIGNED_16(uint16_t, mant_cnt, [AC3_MAX_BLOCKS], [16]); + + count_mantissa_bits_init(mant_cnt); + + max_end_freq = s->bandwidth_code * 3 + 73; + for (ch = !s->cpl_enabled; ch <= s->channels; ch++) + count_mantissa_bits_update_ch(s, ch, mant_cnt, s->start_freq[ch], + max_end_freq); + + return s->ac3dsp.compute_mantissa_size(mant_cnt); +} + + +/** + * Run the bit allocation with a given SNR offset. + * This calculates the bit allocation pointers that will be used to determine + * the quantization of each mantissa. + * + * @param s AC-3 encoder private context + * @param snr_offset SNR offset, 0 to 1023 + * @return the number of bits needed for mantissas if the given SNR offset is + * is used. + */ +static int bit_alloc(AC3EncodeContext *s, int snr_offset) +{ + int blk, ch; + + snr_offset = (snr_offset - 240) << 2; + + reset_block_bap(s); + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + + for (ch = !block->cpl_in_use; ch <= s->channels; ch++) { + /* Currently the only bit allocation parameters which vary across + blocks within a frame are the exponent values. We can take + advantage of that by reusing the bit allocation pointers + whenever we reuse exponents. */ + if (s->exp_strategy[ch][blk] != EXP_REUSE) { + s->ac3dsp.bit_alloc_calc_bap(block->mask[ch], block->psd[ch], + s->start_freq[ch], block->end_freq[ch], + snr_offset, s->bit_alloc.floor, + ff_ac3_bap_tab, s->ref_bap[ch][blk]); + } + } + } + return count_mantissa_bits(s); +} + + +/* + * Constant bitrate bit allocation search. + * Find the largest SNR offset that will allow data to fit in the frame. + */ +static int cbr_bit_allocation(AC3EncodeContext *s) +{ + int ch; + int bits_left; + int snr_offset, snr_incr; + + bits_left = 8 * s->frame_size - (s->frame_bits + s->exponent_bits); + if (bits_left < 0) + return AVERROR(EINVAL); + + snr_offset = s->coarse_snr_offset << 4; + + /* if previous frame SNR offset was 1023, check if current frame can also + use SNR offset of 1023. if so, skip the search. */ + if ((snr_offset | s->fine_snr_offset[1]) == 1023) { + if (bit_alloc(s, 1023) <= bits_left) + return 0; + } + + while (snr_offset >= 0 && + bit_alloc(s, snr_offset) > bits_left) { + snr_offset -= 64; + } + if (snr_offset < 0) + return AVERROR(EINVAL); + + FFSWAP(uint8_t *, s->bap_buffer, s->bap1_buffer); + for (snr_incr = 64; snr_incr > 0; snr_incr >>= 2) { + while (snr_offset + snr_incr <= 1023 && + bit_alloc(s, snr_offset + snr_incr) <= bits_left) { + snr_offset += snr_incr; + FFSWAP(uint8_t *, s->bap_buffer, s->bap1_buffer); + } + } + FFSWAP(uint8_t *, s->bap_buffer, s->bap1_buffer); + reset_block_bap(s); + + s->coarse_snr_offset = snr_offset >> 4; + for (ch = !s->cpl_on; ch <= s->channels; ch++) + s->fine_snr_offset[ch] = snr_offset & 0xF; + + return 0; +} + + +/* + * Perform bit allocation search. + * Finds the SNR offset value that maximizes quality and fits in the specified + * frame size. Output is the SNR offset and a set of bit allocation pointers + * used to quantize the mantissas. + */ +int ff_ac3_compute_bit_allocation(AC3EncodeContext *s) +{ + count_frame_bits(s); + + s->exponent_bits = count_exponent_bits(s); + + bit_alloc_masking(s); + + return cbr_bit_allocation(s); +} + + +/** + * Symmetric quantization on 'levels' levels. + * + * @param c unquantized coefficient + * @param e exponent + * @param levels number of quantization levels + * @return quantized coefficient + */ +static inline int sym_quant(int c, int e, int levels) +{ + int v = (((levels * c) >> (24 - e)) + levels) >> 1; + av_assert2(v >= 0 && v < levels); + return v; +} + + +/** + * Asymmetric quantization on 2^qbits levels. + * + * @param c unquantized coefficient + * @param e exponent + * @param qbits number of quantization bits + * @return quantized coefficient + */ +static inline int asym_quant(int c, int e, int qbits) +{ + int m; + + c = (((c << e) >> (24 - qbits)) + 1) >> 1; + m = (1 << (qbits-1)); + if (c >= m) + c = m - 1; + av_assert2(c >= -m); + return c; +} + + +/** + * Quantize a set of mantissas for a single channel in a single block. + * + * @param s Mantissa count context + * @param fixed_coef unquantized fixed-point coefficients + * @param exp exponents + * @param bap bit allocation pointer indices + * @param[out] qmant quantized coefficients + * @param start_freq starting coefficient bin + * @param end_freq ending coefficient bin + */ +static void quantize_mantissas_blk_ch(AC3Mant *s, int32_t *fixed_coef, + uint8_t *exp, uint8_t *bap, + int16_t *qmant, int start_freq, + int end_freq) +{ + int i; + + for (i = start_freq; i < end_freq; i++) { + int c = fixed_coef[i]; + int e = exp[i]; + int v = bap[i]; + if (v) + switch (v) { + case 1: + v = sym_quant(c, e, 3); + switch (s->mant1_cnt) { + case 0: + s->qmant1_ptr = &qmant[i]; + v = 9 * v; + s->mant1_cnt = 1; + break; + case 1: + *s->qmant1_ptr += 3 * v; + s->mant1_cnt = 2; + v = 128; + break; + default: + *s->qmant1_ptr += v; + s->mant1_cnt = 0; + v = 128; + break; + } + break; + case 2: + v = sym_quant(c, e, 5); + switch (s->mant2_cnt) { + case 0: + s->qmant2_ptr = &qmant[i]; + v = 25 * v; + s->mant2_cnt = 1; + break; + case 1: + *s->qmant2_ptr += 5 * v; + s->mant2_cnt = 2; + v = 128; + break; + default: + *s->qmant2_ptr += v; + s->mant2_cnt = 0; + v = 128; + break; + } + break; + case 3: + v = sym_quant(c, e, 7); + break; + case 4: + v = sym_quant(c, e, 11); + switch (s->mant4_cnt) { + case 0: + s->qmant4_ptr = &qmant[i]; + v = 11 * v; + s->mant4_cnt = 1; + break; + default: + *s->qmant4_ptr += v; + s->mant4_cnt = 0; + v = 128; + break; + } + break; + case 5: + v = sym_quant(c, e, 15); + break; + case 14: + v = asym_quant(c, e, 14); + break; + case 15: + v = asym_quant(c, e, 16); + break; + default: + v = asym_quant(c, e, v - 1); + break; + } + qmant[i] = v; + } +} + + +/** + * Quantize mantissas using coefficients, exponents, and bit allocation pointers. + * + * @param s AC-3 encoder private context + */ +void ff_ac3_quantize_mantissas(AC3EncodeContext *s) +{ + int blk, ch, ch0=0, got_cpl; + + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + AC3Mant m = { 0 }; + + got_cpl = !block->cpl_in_use; + for (ch = 1; ch <= s->channels; ch++) { + if (!got_cpl && ch > 1 && block->channel_in_cpl[ch-1]) { + ch0 = ch - 1; + ch = CPL_CH; + got_cpl = 1; + } + quantize_mantissas_blk_ch(&m, block->fixed_coef[ch], + s->blocks[s->exp_ref_block[ch][blk]].exp[ch], + s->ref_bap[ch][blk], block->qmant[ch], + s->start_freq[ch], block->end_freq[ch]); + if (ch == CPL_CH) + ch = ch0; + } + } +} + + +/* + * Write the AC-3 frame header to the output bitstream. + */ +static void ac3_output_frame_header(AC3EncodeContext *s) +{ + AC3EncOptions *opt = &s->options; + + put_bits(&s->pb, 16, 0x0b77); /* frame header */ + put_bits(&s->pb, 16, 0); /* crc1: will be filled later */ + put_bits(&s->pb, 2, s->bit_alloc.sr_code); + put_bits(&s->pb, 6, s->frame_size_code + (s->frame_size - s->frame_size_min) / 2); + put_bits(&s->pb, 5, s->bitstream_id); + put_bits(&s->pb, 3, s->bitstream_mode); + put_bits(&s->pb, 3, s->channel_mode); + if ((s->channel_mode & 0x01) && s->channel_mode != AC3_CHMODE_MONO) + put_bits(&s->pb, 2, s->center_mix_level); + if (s->channel_mode & 0x04) + put_bits(&s->pb, 2, s->surround_mix_level); + if (s->channel_mode == AC3_CHMODE_STEREO) + put_bits(&s->pb, 2, opt->dolby_surround_mode); + put_bits(&s->pb, 1, s->lfe_on); /* LFE */ + put_bits(&s->pb, 5, -opt->dialogue_level); + put_bits(&s->pb, 1, 0); /* no compression control word */ + put_bits(&s->pb, 1, 0); /* no lang code */ + put_bits(&s->pb, 1, opt->audio_production_info); + if (opt->audio_production_info) { + put_bits(&s->pb, 5, opt->mixing_level - 80); + put_bits(&s->pb, 2, opt->room_type); + } + put_bits(&s->pb, 1, opt->copyright); + put_bits(&s->pb, 1, opt->original); + if (s->bitstream_id == 6) { + /* alternate bit stream syntax */ + put_bits(&s->pb, 1, opt->extended_bsi_1); + if (opt->extended_bsi_1) { + put_bits(&s->pb, 2, opt->preferred_stereo_downmix); + put_bits(&s->pb, 3, s->ltrt_center_mix_level); + put_bits(&s->pb, 3, s->ltrt_surround_mix_level); + put_bits(&s->pb, 3, s->loro_center_mix_level); + put_bits(&s->pb, 3, s->loro_surround_mix_level); + } + put_bits(&s->pb, 1, opt->extended_bsi_2); + if (opt->extended_bsi_2) { + put_bits(&s->pb, 2, opt->dolby_surround_ex_mode); + put_bits(&s->pb, 2, opt->dolby_headphone_mode); + put_bits(&s->pb, 1, opt->ad_converter_type); + put_bits(&s->pb, 9, 0); /* xbsi2 and encinfo : reserved */ + } + } else { + put_bits(&s->pb, 1, 0); /* no time code 1 */ + put_bits(&s->pb, 1, 0); /* no time code 2 */ + } + put_bits(&s->pb, 1, 0); /* no additional bit stream info */ +} + + +/* + * Write one audio block to the output bitstream. + */ +static void output_audio_block(AC3EncodeContext *s, int blk) +{ + int ch, i, baie, bnd, got_cpl, ch0; + AC3Block *block = &s->blocks[blk]; + + /* block switching */ + if (!s->eac3) { + for (ch = 0; ch < s->fbw_channels; ch++) + put_bits(&s->pb, 1, 0); + } + + /* dither flags */ + if (!s->eac3) { + for (ch = 0; ch < s->fbw_channels; ch++) + put_bits(&s->pb, 1, 1); + } + + /* dynamic range codes */ + put_bits(&s->pb, 1, 0); + + /* spectral extension */ + if (s->eac3) + put_bits(&s->pb, 1, 0); + + /* channel coupling */ + if (!s->eac3) + put_bits(&s->pb, 1, block->new_cpl_strategy); + if (block->new_cpl_strategy) { + if (!s->eac3) + put_bits(&s->pb, 1, block->cpl_in_use); + if (block->cpl_in_use) { + int start_sub, end_sub; + if (s->eac3) + put_bits(&s->pb, 1, 0); /* enhanced coupling */ + if (!s->eac3 || s->channel_mode != AC3_CHMODE_STEREO) { + for (ch = 1; ch <= s->fbw_channels; ch++) + put_bits(&s->pb, 1, block->channel_in_cpl[ch]); + } + if (s->channel_mode == AC3_CHMODE_STEREO) + put_bits(&s->pb, 1, 0); /* phase flags in use */ + start_sub = (s->start_freq[CPL_CH] - 37) / 12; + end_sub = (s->cpl_end_freq - 37) / 12; + put_bits(&s->pb, 4, start_sub); + put_bits(&s->pb, 4, end_sub - 3); + /* coupling band structure */ + if (s->eac3) { + put_bits(&s->pb, 1, 0); /* use default */ + } else { + for (bnd = start_sub+1; bnd < end_sub; bnd++) + put_bits(&s->pb, 1, ff_eac3_default_cpl_band_struct[bnd]); + } + } + } + + /* coupling coordinates */ + if (block->cpl_in_use) { + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (block->channel_in_cpl[ch]) { + if (!s->eac3 || block->new_cpl_coords[ch] != 2) + put_bits(&s->pb, 1, block->new_cpl_coords[ch]); + if (block->new_cpl_coords[ch]) { + put_bits(&s->pb, 2, block->cpl_master_exp[ch]); + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + put_bits(&s->pb, 4, block->cpl_coord_exp [ch][bnd]); + put_bits(&s->pb, 4, block->cpl_coord_mant[ch][bnd]); + } + } + } + } + } + + /* stereo rematrixing */ + if (s->channel_mode == AC3_CHMODE_STEREO) { + if (!s->eac3 || blk > 0) + put_bits(&s->pb, 1, block->new_rematrixing_strategy); + if (block->new_rematrixing_strategy) { + /* rematrixing flags */ + for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) + put_bits(&s->pb, 1, block->rematrixing_flags[bnd]); + } + } + + /* exponent strategy */ + if (!s->eac3) { + for (ch = !block->cpl_in_use; ch <= s->fbw_channels; ch++) + put_bits(&s->pb, 2, s->exp_strategy[ch][blk]); + if (s->lfe_on) + put_bits(&s->pb, 1, s->exp_strategy[s->lfe_channel][blk]); + } + + /* bandwidth */ + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (s->exp_strategy[ch][blk] != EXP_REUSE && !block->channel_in_cpl[ch]) + put_bits(&s->pb, 6, s->bandwidth_code); + } + + /* exponents */ + for (ch = !block->cpl_in_use; ch <= s->channels; ch++) { + int nb_groups; + int cpl = (ch == CPL_CH); + + if (s->exp_strategy[ch][blk] == EXP_REUSE) + continue; + + /* DC exponent */ + put_bits(&s->pb, 4, block->grouped_exp[ch][0] >> cpl); + + /* exponent groups */ + nb_groups = exponent_group_tab[cpl][s->exp_strategy[ch][blk]-1][block->end_freq[ch]-s->start_freq[ch]]; + for (i = 1; i <= nb_groups; i++) + put_bits(&s->pb, 7, block->grouped_exp[ch][i]); + + /* gain range info */ + if (ch != s->lfe_channel && !cpl) + put_bits(&s->pb, 2, 0); + } + + /* bit allocation info */ + if (!s->eac3) { + baie = (blk == 0); + put_bits(&s->pb, 1, baie); + if (baie) { + put_bits(&s->pb, 2, s->slow_decay_code); + put_bits(&s->pb, 2, s->fast_decay_code); + put_bits(&s->pb, 2, s->slow_gain_code); + put_bits(&s->pb, 2, s->db_per_bit_code); + put_bits(&s->pb, 3, s->floor_code); + } + } + + /* snr offset */ + if (!s->eac3) { + put_bits(&s->pb, 1, block->new_snr_offsets); + if (block->new_snr_offsets) { + put_bits(&s->pb, 6, s->coarse_snr_offset); + for (ch = !block->cpl_in_use; ch <= s->channels; ch++) { + put_bits(&s->pb, 4, s->fine_snr_offset[ch]); + put_bits(&s->pb, 3, s->fast_gain_code[ch]); + } + } + } else { + put_bits(&s->pb, 1, 0); /* no converter snr offset */ + } + + /* coupling leak */ + if (block->cpl_in_use) { + if (!s->eac3 || block->new_cpl_leak != 2) + put_bits(&s->pb, 1, block->new_cpl_leak); + if (block->new_cpl_leak) { + put_bits(&s->pb, 3, s->bit_alloc.cpl_fast_leak); + put_bits(&s->pb, 3, s->bit_alloc.cpl_slow_leak); + } + } + + if (!s->eac3) { + put_bits(&s->pb, 1, 0); /* no delta bit allocation */ + put_bits(&s->pb, 1, 0); /* no data to skip */ + } + + /* mantissas */ + got_cpl = !block->cpl_in_use; + for (ch = 1; ch <= s->channels; ch++) { + int b, q; + + if (!got_cpl && ch > 1 && block->channel_in_cpl[ch-1]) { + ch0 = ch - 1; + ch = CPL_CH; + got_cpl = 1; + } + for (i = s->start_freq[ch]; i < block->end_freq[ch]; i++) { + q = block->qmant[ch][i]; + b = s->ref_bap[ch][blk][i]; + switch (b) { + case 0: break; + case 1: if (q != 128) put_bits (&s->pb, 5, q); break; + case 2: if (q != 128) put_bits (&s->pb, 7, q); break; + case 3: put_sbits(&s->pb, 3, q); break; + case 4: if (q != 128) put_bits (&s->pb, 7, q); break; + case 14: put_sbits(&s->pb, 14, q); break; + case 15: put_sbits(&s->pb, 16, q); break; + default: put_sbits(&s->pb, b-1, q); break; + } + } + if (ch == CPL_CH) + ch = ch0; + } +} + + +/** CRC-16 Polynomial */ +#define CRC16_POLY ((1 << 0) | (1 << 2) | (1 << 15) | (1 << 16)) + + +static unsigned int mul_poly(unsigned int a, unsigned int b, unsigned int poly) +{ + unsigned int c; + + c = 0; + while (a) { + if (a & 1) + c ^= b; + a = a >> 1; + b = b << 1; + if (b & (1 << 16)) + b ^= poly; + } + return c; +} + + +static unsigned int pow_poly(unsigned int a, unsigned int n, unsigned int poly) +{ + unsigned int r; + r = 1; + while (n) { + if (n & 1) + r = mul_poly(r, a, poly); + a = mul_poly(a, a, poly); + n >>= 1; + } + return r; +} + + +/* + * Fill the end of the frame with 0's and compute the two CRCs. + */ +static void output_frame_end(AC3EncodeContext *s) +{ + const AVCRC *crc_ctx = av_crc_get_table(AV_CRC_16_ANSI); + int frame_size_58, pad_bytes, crc1, crc2_partial, crc2, crc_inv; + uint8_t *frame; + + frame_size_58 = ((s->frame_size >> 2) + (s->frame_size >> 4)) << 1; + + /* pad the remainder of the frame with zeros */ + av_assert2(s->frame_size * 8 - put_bits_count(&s->pb) >= 18); + flush_put_bits(&s->pb); + frame = s->pb.buf; + pad_bytes = s->frame_size - (put_bits_ptr(&s->pb) - frame) - 2; + av_assert2(pad_bytes >= 0); + if (pad_bytes > 0) + memset(put_bits_ptr(&s->pb), 0, pad_bytes); + + if (s->eac3) { + /* compute crc2 */ + crc2_partial = av_crc(crc_ctx, 0, frame + 2, s->frame_size - 5); + } else { + /* compute crc1 */ + /* this is not so easy because it is at the beginning of the data... */ + crc1 = av_bswap16(av_crc(crc_ctx, 0, frame + 4, frame_size_58 - 4)); + crc_inv = s->crc_inv[s->frame_size > s->frame_size_min]; + crc1 = mul_poly(crc_inv, crc1, CRC16_POLY); + AV_WB16(frame + 2, crc1); + + /* compute crc2 */ + crc2_partial = av_crc(crc_ctx, 0, frame + frame_size_58, + s->frame_size - frame_size_58 - 3); + } + crc2 = av_crc(crc_ctx, crc2_partial, frame + s->frame_size - 3, 1); + /* ensure crc2 does not match sync word by flipping crcrsv bit if needed */ + if (crc2 == 0x770B) { + frame[s->frame_size - 3] ^= 0x1; + crc2 = av_crc(crc_ctx, crc2_partial, frame + s->frame_size - 3, 1); + } + crc2 = av_bswap16(crc2); + AV_WB16(frame + s->frame_size - 2, crc2); +} + + +/** + * Write the frame to the output bitstream. + * + * @param s AC-3 encoder private context + * @param frame output data buffer + */ +void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame) +{ + int blk; + + init_put_bits(&s->pb, frame, AC3_MAX_CODED_FRAME_SIZE); + + s->output_frame_header(s); + + for (blk = 0; blk < s->num_blocks; blk++) + output_audio_block(s, blk); + + output_frame_end(s); +} + + +static void dprint_options(AC3EncodeContext *s) +{ +#ifdef DEBUG + AVCodecContext *avctx = s->avctx; + AC3EncOptions *opt = &s->options; + char strbuf[32]; + + switch (s->bitstream_id) { + case 6: av_strlcpy(strbuf, "AC-3 (alt syntax)", 32); break; + case 8: av_strlcpy(strbuf, "AC-3 (standard)", 32); break; + case 9: av_strlcpy(strbuf, "AC-3 (dnet half-rate)", 32); break; + case 10: av_strlcpy(strbuf, "AC-3 (dnet quater-rate)", 32); break; + case 16: av_strlcpy(strbuf, "E-AC-3 (enhanced)", 32); break; + default: snprintf(strbuf, 32, "ERROR"); + } + av_dlog(avctx, "bitstream_id: %s (%d)\n", strbuf, s->bitstream_id); + av_dlog(avctx, "sample_fmt: %s\n", av_get_sample_fmt_name(avctx->sample_fmt)); + av_get_channel_layout_string(strbuf, 32, s->channels, avctx->channel_layout); + av_dlog(avctx, "channel_layout: %s\n", strbuf); + av_dlog(avctx, "sample_rate: %d\n", s->sample_rate); + av_dlog(avctx, "bit_rate: %d\n", s->bit_rate); + av_dlog(avctx, "blocks/frame: %d (code=%d)\n", s->num_blocks, s->num_blks_code); + if (s->cutoff) + av_dlog(avctx, "cutoff: %d\n", s->cutoff); + + av_dlog(avctx, "per_frame_metadata: %s\n", + opt->allow_per_frame_metadata?"on":"off"); + if (s->has_center) + av_dlog(avctx, "center_mixlev: %0.3f (%d)\n", opt->center_mix_level, + s->center_mix_level); + else + av_dlog(avctx, "center_mixlev: {not written}\n"); + if (s->has_surround) + av_dlog(avctx, "surround_mixlev: %0.3f (%d)\n", opt->surround_mix_level, + s->surround_mix_level); + else + av_dlog(avctx, "surround_mixlev: {not written}\n"); + if (opt->audio_production_info) { + av_dlog(avctx, "mixing_level: %ddB\n", opt->mixing_level); + switch (opt->room_type) { + case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; + case AC3ENC_OPT_LARGE_ROOM: av_strlcpy(strbuf, "large", 32); break; + case AC3ENC_OPT_SMALL_ROOM: av_strlcpy(strbuf, "small", 32); break; + default: snprintf(strbuf, 32, "ERROR (%d)", opt->room_type); + } + av_dlog(avctx, "room_type: %s\n", strbuf); + } else { + av_dlog(avctx, "mixing_level: {not written}\n"); + av_dlog(avctx, "room_type: {not written}\n"); + } + av_dlog(avctx, "copyright: %s\n", opt->copyright?"on":"off"); + av_dlog(avctx, "dialnorm: %ddB\n", opt->dialogue_level); + if (s->channel_mode == AC3_CHMODE_STEREO) { + switch (opt->dolby_surround_mode) { + case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; + case AC3ENC_OPT_MODE_ON: av_strlcpy(strbuf, "on", 32); break; + case AC3ENC_OPT_MODE_OFF: av_strlcpy(strbuf, "off", 32); break; + default: snprintf(strbuf, 32, "ERROR (%d)", opt->dolby_surround_mode); + } + av_dlog(avctx, "dsur_mode: %s\n", strbuf); + } else { + av_dlog(avctx, "dsur_mode: {not written}\n"); + } + av_dlog(avctx, "original: %s\n", opt->original?"on":"off"); + + if (s->bitstream_id == 6) { + if (opt->extended_bsi_1) { + switch (opt->preferred_stereo_downmix) { + case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; + case AC3ENC_OPT_DOWNMIX_LTRT: av_strlcpy(strbuf, "ltrt", 32); break; + case AC3ENC_OPT_DOWNMIX_LORO: av_strlcpy(strbuf, "loro", 32); break; + default: snprintf(strbuf, 32, "ERROR (%d)", opt->preferred_stereo_downmix); + } + av_dlog(avctx, "dmix_mode: %s\n", strbuf); + av_dlog(avctx, "ltrt_cmixlev: %0.3f (%d)\n", + opt->ltrt_center_mix_level, s->ltrt_center_mix_level); + av_dlog(avctx, "ltrt_surmixlev: %0.3f (%d)\n", + opt->ltrt_surround_mix_level, s->ltrt_surround_mix_level); + av_dlog(avctx, "loro_cmixlev: %0.3f (%d)\n", + opt->loro_center_mix_level, s->loro_center_mix_level); + av_dlog(avctx, "loro_surmixlev: %0.3f (%d)\n", + opt->loro_surround_mix_level, s->loro_surround_mix_level); + } else { + av_dlog(avctx, "extended bitstream info 1: {not written}\n"); + } + if (opt->extended_bsi_2) { + switch (opt->dolby_surround_ex_mode) { + case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; + case AC3ENC_OPT_MODE_ON: av_strlcpy(strbuf, "on", 32); break; + case AC3ENC_OPT_MODE_OFF: av_strlcpy(strbuf, "off", 32); break; + default: snprintf(strbuf, 32, "ERROR (%d)", opt->dolby_surround_ex_mode); + } + av_dlog(avctx, "dsurex_mode: %s\n", strbuf); + switch (opt->dolby_headphone_mode) { + case AC3ENC_OPT_NOT_INDICATED: av_strlcpy(strbuf, "notindicated", 32); break; + case AC3ENC_OPT_MODE_ON: av_strlcpy(strbuf, "on", 32); break; + case AC3ENC_OPT_MODE_OFF: av_strlcpy(strbuf, "off", 32); break; + default: snprintf(strbuf, 32, "ERROR (%d)", opt->dolby_headphone_mode); + } + av_dlog(avctx, "dheadphone_mode: %s\n", strbuf); + + switch (opt->ad_converter_type) { + case AC3ENC_OPT_ADCONV_STANDARD: av_strlcpy(strbuf, "standard", 32); break; + case AC3ENC_OPT_ADCONV_HDCD: av_strlcpy(strbuf, "hdcd", 32); break; + default: snprintf(strbuf, 32, "ERROR (%d)", opt->ad_converter_type); + } + av_dlog(avctx, "ad_conv_type: %s\n", strbuf); + } else { + av_dlog(avctx, "extended bitstream info 2: {not written}\n"); + } + } +#endif +} + + +#define FLT_OPTION_THRESHOLD 0.01 + +static int validate_float_option(float v, const float *v_list, int v_list_size) +{ + int i; + + for (i = 0; i < v_list_size; i++) { + if (v < (v_list[i] + FLT_OPTION_THRESHOLD) && + v > (v_list[i] - FLT_OPTION_THRESHOLD)) + break; + } + if (i == v_list_size) + return -1; + + return i; +} + + +static void validate_mix_level(void *log_ctx, const char *opt_name, + float *opt_param, const float *list, + int list_size, int default_value, int min_value, + int *ctx_param) +{ + int mixlev = validate_float_option(*opt_param, list, list_size); + if (mixlev < min_value) { + mixlev = default_value; + if (*opt_param >= 0.0) { + av_log(log_ctx, AV_LOG_WARNING, "requested %s is not valid. using " + "default value: %0.3f\n", opt_name, list[mixlev]); + } + } + *opt_param = list[mixlev]; + *ctx_param = mixlev; +} + + +/** + * Validate metadata options as set by AVOption system. + * These values can optionally be changed per-frame. + * + * @param s AC-3 encoder private context + */ +int ff_ac3_validate_metadata(AC3EncodeContext *s) +{ + AVCodecContext *avctx = s->avctx; + AC3EncOptions *opt = &s->options; + + opt->audio_production_info = 0; + opt->extended_bsi_1 = 0; + opt->extended_bsi_2 = 0; + opt->eac3_mixing_metadata = 0; + opt->eac3_info_metadata = 0; + + /* determine mixing metadata / xbsi1 use */ + if (s->channel_mode > AC3_CHMODE_STEREO && opt->preferred_stereo_downmix != AC3ENC_OPT_NONE) { + opt->extended_bsi_1 = 1; + opt->eac3_mixing_metadata = 1; + } + if (s->has_center && + (opt->ltrt_center_mix_level >= 0 || opt->loro_center_mix_level >= 0)) { + opt->extended_bsi_1 = 1; + opt->eac3_mixing_metadata = 1; + } + if (s->has_surround && + (opt->ltrt_surround_mix_level >= 0 || opt->loro_surround_mix_level >= 0)) { + opt->extended_bsi_1 = 1; + opt->eac3_mixing_metadata = 1; + } + + if (s->eac3) { + /* determine info metadata use */ + if (avctx->audio_service_type != AV_AUDIO_SERVICE_TYPE_MAIN) + opt->eac3_info_metadata = 1; + if (opt->copyright != AC3ENC_OPT_NONE || opt->original != AC3ENC_OPT_NONE) + opt->eac3_info_metadata = 1; + if (s->channel_mode == AC3_CHMODE_STEREO && + (opt->dolby_headphone_mode != AC3ENC_OPT_NONE || opt->dolby_surround_mode != AC3ENC_OPT_NONE)) + opt->eac3_info_metadata = 1; + if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode != AC3ENC_OPT_NONE) + opt->eac3_info_metadata = 1; + if (opt->mixing_level != AC3ENC_OPT_NONE || opt->room_type != AC3ENC_OPT_NONE || + opt->ad_converter_type != AC3ENC_OPT_NONE) { + opt->audio_production_info = 1; + opt->eac3_info_metadata = 1; + } + } else { + /* determine audio production info use */ + if (opt->mixing_level != AC3ENC_OPT_NONE || opt->room_type != AC3ENC_OPT_NONE) + opt->audio_production_info = 1; + + /* determine xbsi2 use */ + if (s->channel_mode >= AC3_CHMODE_2F2R && opt->dolby_surround_ex_mode != AC3ENC_OPT_NONE) + opt->extended_bsi_2 = 1; + if (s->channel_mode == AC3_CHMODE_STEREO && opt->dolby_headphone_mode != AC3ENC_OPT_NONE) + opt->extended_bsi_2 = 1; + if (opt->ad_converter_type != AC3ENC_OPT_NONE) + opt->extended_bsi_2 = 1; + } + + /* validate AC-3 mixing levels */ + if (!s->eac3) { + if (s->has_center) { + validate_mix_level(avctx, "center_mix_level", &opt->center_mix_level, + cmixlev_options, CMIXLEV_NUM_OPTIONS, 1, 0, + &s->center_mix_level); + } + if (s->has_surround) { + validate_mix_level(avctx, "surround_mix_level", &opt->surround_mix_level, + surmixlev_options, SURMIXLEV_NUM_OPTIONS, 1, 0, + &s->surround_mix_level); + } + } + + /* validate extended bsi 1 / mixing metadata */ + if (opt->extended_bsi_1 || opt->eac3_mixing_metadata) { + /* default preferred stereo downmix */ + if (opt->preferred_stereo_downmix == AC3ENC_OPT_NONE) + opt->preferred_stereo_downmix = AC3ENC_OPT_NOT_INDICATED; + if (!s->eac3 || s->has_center) { + /* validate Lt/Rt center mix level */ + validate_mix_level(avctx, "ltrt_center_mix_level", + &opt->ltrt_center_mix_level, extmixlev_options, + EXTMIXLEV_NUM_OPTIONS, 5, 0, + &s->ltrt_center_mix_level); + /* validate Lo/Ro center mix level */ + validate_mix_level(avctx, "loro_center_mix_level", + &opt->loro_center_mix_level, extmixlev_options, + EXTMIXLEV_NUM_OPTIONS, 5, 0, + &s->loro_center_mix_level); + } + if (!s->eac3 || s->has_surround) { + /* validate Lt/Rt surround mix level */ + validate_mix_level(avctx, "ltrt_surround_mix_level", + &opt->ltrt_surround_mix_level, extmixlev_options, + EXTMIXLEV_NUM_OPTIONS, 6, 3, + &s->ltrt_surround_mix_level); + /* validate Lo/Ro surround mix level */ + validate_mix_level(avctx, "loro_surround_mix_level", + &opt->loro_surround_mix_level, extmixlev_options, + EXTMIXLEV_NUM_OPTIONS, 6, 3, + &s->loro_surround_mix_level); + } + } + + /* validate audio service type / channels combination */ + if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE && + avctx->channels == 1) || + ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_COMMENTARY || + avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_EMERGENCY || + avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_VOICE_OVER) + && avctx->channels > 1)) { + av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the " + "specified number of channels\n"); + return AVERROR(EINVAL); + } + + /* validate extended bsi 2 / info metadata */ + if (opt->extended_bsi_2 || opt->eac3_info_metadata) { + /* default dolby headphone mode */ + if (opt->dolby_headphone_mode == AC3ENC_OPT_NONE) + opt->dolby_headphone_mode = AC3ENC_OPT_NOT_INDICATED; + /* default dolby surround ex mode */ + if (opt->dolby_surround_ex_mode == AC3ENC_OPT_NONE) + opt->dolby_surround_ex_mode = AC3ENC_OPT_NOT_INDICATED; + /* default A/D converter type */ + if (opt->ad_converter_type == AC3ENC_OPT_NONE) + opt->ad_converter_type = AC3ENC_OPT_ADCONV_STANDARD; + } + + /* copyright & original defaults */ + if (!s->eac3 || opt->eac3_info_metadata) { + /* default copyright */ + if (opt->copyright == AC3ENC_OPT_NONE) + opt->copyright = AC3ENC_OPT_OFF; + /* default original */ + if (opt->original == AC3ENC_OPT_NONE) + opt->original = AC3ENC_OPT_ON; + } + + /* dolby surround mode default */ + if (!s->eac3 || opt->eac3_info_metadata) { + if (opt->dolby_surround_mode == AC3ENC_OPT_NONE) + opt->dolby_surround_mode = AC3ENC_OPT_NOT_INDICATED; + } + + /* validate audio production info */ + if (opt->audio_production_info) { + if (opt->mixing_level == AC3ENC_OPT_NONE) { + av_log(avctx, AV_LOG_ERROR, "mixing_level must be set if " + "room_type is set\n"); + return AVERROR(EINVAL); + } + if (opt->mixing_level < 80) { + av_log(avctx, AV_LOG_ERROR, "invalid mixing level. must be between " + "80dB and 111dB\n"); + return AVERROR(EINVAL); + } + /* default room type */ + if (opt->room_type == AC3ENC_OPT_NONE) + opt->room_type = AC3ENC_OPT_NOT_INDICATED; + } + + /* set bitstream id for alternate bitstream syntax */ + if (!s->eac3 && (opt->extended_bsi_1 || opt->extended_bsi_2)) { + if (s->bitstream_id > 8 && s->bitstream_id < 11) { + static int warn_once = 1; + if (warn_once) { + av_log(avctx, AV_LOG_WARNING, "alternate bitstream syntax is " + "not compatible with reduced samplerates. writing of " + "extended bitstream information will be disabled.\n"); + warn_once = 0; + } + } else { + s->bitstream_id = 6; + } + } + + return 0; +} + + +/** + * Finalize encoding and free any memory allocated by the encoder. + * + * @param avctx Codec context + */ +av_cold int ff_ac3_encode_close(AVCodecContext *avctx) +{ + int blk, ch; + AC3EncodeContext *s = avctx->priv_data; + + av_freep(&s->windowed_samples); + for (ch = 0; ch < s->channels; ch++) + av_freep(&s->planar_samples[ch]); + av_freep(&s->planar_samples); + av_freep(&s->bap_buffer); + av_freep(&s->bap1_buffer); + av_freep(&s->mdct_coef_buffer); + av_freep(&s->fixed_coef_buffer); + av_freep(&s->exp_buffer); + av_freep(&s->grouped_exp_buffer); + av_freep(&s->psd_buffer); + av_freep(&s->band_psd_buffer); + av_freep(&s->mask_buffer); + av_freep(&s->qmant_buffer); + av_freep(&s->cpl_coord_exp_buffer); + av_freep(&s->cpl_coord_mant_buffer); + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + av_freep(&block->mdct_coef); + av_freep(&block->fixed_coef); + av_freep(&block->exp); + av_freep(&block->grouped_exp); + av_freep(&block->psd); + av_freep(&block->band_psd); + av_freep(&block->mask); + av_freep(&block->qmant); + av_freep(&block->cpl_coord_exp); + av_freep(&block->cpl_coord_mant); + } + + s->mdct_end(s); + + return 0; +} + + +/* + * Set channel information during initialization. + */ +static av_cold int set_channel_info(AC3EncodeContext *s, int channels, + uint64_t *channel_layout) +{ + int ch_layout; + + if (channels < 1 || channels > AC3_MAX_CHANNELS) + return AVERROR(EINVAL); + if (*channel_layout > 0x7FF) + return AVERROR(EINVAL); + ch_layout = *channel_layout; + if (!ch_layout) + ch_layout = av_get_default_channel_layout(channels); + + s->lfe_on = !!(ch_layout & AV_CH_LOW_FREQUENCY); + s->channels = channels; + s->fbw_channels = channels - s->lfe_on; + s->lfe_channel = s->lfe_on ? s->fbw_channels + 1 : -1; + if (s->lfe_on) + ch_layout -= AV_CH_LOW_FREQUENCY; + + switch (ch_layout) { + case AV_CH_LAYOUT_MONO: s->channel_mode = AC3_CHMODE_MONO; break; + case AV_CH_LAYOUT_STEREO: s->channel_mode = AC3_CHMODE_STEREO; break; + case AV_CH_LAYOUT_SURROUND: s->channel_mode = AC3_CHMODE_3F; break; + case AV_CH_LAYOUT_2_1: s->channel_mode = AC3_CHMODE_2F1R; break; + case AV_CH_LAYOUT_4POINT0: s->channel_mode = AC3_CHMODE_3F1R; break; + case AV_CH_LAYOUT_QUAD: + case AV_CH_LAYOUT_2_2: s->channel_mode = AC3_CHMODE_2F2R; break; + case AV_CH_LAYOUT_5POINT0: + case AV_CH_LAYOUT_5POINT0_BACK: s->channel_mode = AC3_CHMODE_3F2R; break; + default: + return AVERROR(EINVAL); + } + s->has_center = (s->channel_mode & 0x01) && s->channel_mode != AC3_CHMODE_MONO; + s->has_surround = s->channel_mode & 0x04; + + s->channel_map = ff_ac3_enc_channel_map[s->channel_mode][s->lfe_on]; + *channel_layout = ch_layout; + if (s->lfe_on) + *channel_layout |= AV_CH_LOW_FREQUENCY; + + return 0; +} + + +static av_cold int validate_options(AC3EncodeContext *s) +{ + AVCodecContext *avctx = s->avctx; + int i, ret, max_sr; + + /* validate channel layout */ + if (!avctx->channel_layout) { + av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The " + "encoder will guess the layout, but it " + "might be incorrect.\n"); + } + ret = set_channel_info(s, avctx->channels, &avctx->channel_layout); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "invalid channel layout\n"); + return ret; + } + + /* validate sample rate */ + /* note: max_sr could be changed from 2 to 5 for E-AC-3 once we find a + decoder that supports half sample rate so we can validate that + the generated files are correct. */ + max_sr = s->eac3 ? 2 : 8; + for (i = 0; i <= max_sr; i++) { + if ((ff_ac3_sample_rate_tab[i % 3] >> (i / 3)) == avctx->sample_rate) + break; + } + if (i > max_sr) { + av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n"); + return AVERROR(EINVAL); + } + s->sample_rate = avctx->sample_rate; + s->bit_alloc.sr_shift = i / 3; + s->bit_alloc.sr_code = i % 3; + s->bitstream_id = s->eac3 ? 16 : 8 + s->bit_alloc.sr_shift; + + /* select a default bit rate if not set by the user */ + if (!avctx->bit_rate) { + switch (s->fbw_channels) { + case 1: avctx->bit_rate = 96000; break; + case 2: avctx->bit_rate = 192000; break; + case 3: avctx->bit_rate = 320000; break; + case 4: avctx->bit_rate = 384000; break; + case 5: avctx->bit_rate = 448000; break; + } + } + + /* validate bit rate */ + if (s->eac3) { + int max_br, min_br, wpf, min_br_dist, min_br_code; + int num_blks_code, num_blocks, frame_samples; + + /* calculate min/max bitrate */ + /* TODO: More testing with 3 and 2 blocks. All E-AC-3 samples I've + found use either 6 blocks or 1 block, even though 2 or 3 blocks + would work as far as the bit rate is concerned. */ + for (num_blks_code = 3; num_blks_code >= 0; num_blks_code--) { + num_blocks = ((int[]){ 1, 2, 3, 6 })[num_blks_code]; + frame_samples = AC3_BLOCK_SIZE * num_blocks; + max_br = 2048 * s->sample_rate / frame_samples * 16; + min_br = ((s->sample_rate + (frame_samples-1)) / frame_samples) * 16; + if (avctx->bit_rate <= max_br) + break; + } + if (avctx->bit_rate < min_br || avctx->bit_rate > max_br) { + av_log(avctx, AV_LOG_ERROR, "invalid bit rate. must be %d to %d " + "for this sample rate\n", min_br, max_br); + return AVERROR(EINVAL); + } + s->num_blks_code = num_blks_code; + s->num_blocks = num_blocks; + + /* calculate words-per-frame for the selected bitrate */ + wpf = (avctx->bit_rate / 16) * frame_samples / s->sample_rate; + av_assert1(wpf > 0 && wpf <= 2048); + + /* find the closest AC-3 bitrate code to the selected bitrate. + this is needed for lookup tables for bandwidth and coupling + parameter selection */ + min_br_code = -1; + min_br_dist = INT_MAX; + for (i = 0; i < 19; i++) { + int br_dist = abs(ff_ac3_bitrate_tab[i] * 1000 - avctx->bit_rate); + if (br_dist < min_br_dist) { + min_br_dist = br_dist; + min_br_code = i; + } + } + + /* make sure the minimum frame size is below the average frame size */ + s->frame_size_code = min_br_code << 1; + while (wpf > 1 && wpf * s->sample_rate / AC3_FRAME_SIZE * 16 > avctx->bit_rate) + wpf--; + s->frame_size_min = 2 * wpf; + } else { + int best_br = 0, best_code = 0, best_diff = INT_MAX; + for (i = 0; i < 19; i++) { + int br = (ff_ac3_bitrate_tab[i] >> s->bit_alloc.sr_shift) * 1000; + int diff = abs(br - avctx->bit_rate); + if (diff < best_diff) { + best_br = br; + best_code = i; + best_diff = diff; + } + if (!best_diff) + break; + } + avctx->bit_rate = best_br; + s->frame_size_code = best_code << 1; + s->frame_size_min = 2 * ff_ac3_frame_size_tab[s->frame_size_code][s->bit_alloc.sr_code]; + s->num_blks_code = 0x3; + s->num_blocks = 6; + } + s->bit_rate = avctx->bit_rate; + s->frame_size = s->frame_size_min; + + /* validate cutoff */ + if (avctx->cutoff < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid cutoff frequency\n"); + return AVERROR(EINVAL); + } + s->cutoff = avctx->cutoff; + if (s->cutoff > (s->sample_rate >> 1)) + s->cutoff = s->sample_rate >> 1; + + ret = ff_ac3_validate_metadata(s); + if (ret) + return ret; + + s->rematrixing_enabled = s->options.stereo_rematrixing && + (s->channel_mode == AC3_CHMODE_STEREO); + + s->cpl_enabled = s->options.channel_coupling && + s->channel_mode >= AC3_CHMODE_STEREO; + + return 0; +} + + +/* + * Set bandwidth for all channels. + * The user can optionally supply a cutoff frequency. Otherwise an appropriate + * default value will be used. + */ +static av_cold void set_bandwidth(AC3EncodeContext *s) +{ + int blk, ch, cpl_start; + + if (s->cutoff) { + /* calculate bandwidth based on user-specified cutoff frequency */ + int fbw_coeffs; + fbw_coeffs = s->cutoff * 2 * AC3_MAX_COEFS / s->sample_rate; + s->bandwidth_code = av_clip((fbw_coeffs - 73) / 3, 0, 60); + } else { + /* use default bandwidth setting */ + s->bandwidth_code = ac3_bandwidth_tab[s->fbw_channels-1][s->bit_alloc.sr_code][s->frame_size_code/2]; + } + + /* set number of coefficients for each channel */ + for (ch = 1; ch <= s->fbw_channels; ch++) { + s->start_freq[ch] = 0; + for (blk = 0; blk < s->num_blocks; blk++) + s->blocks[blk].end_freq[ch] = s->bandwidth_code * 3 + 73; + } + /* LFE channel always has 7 coefs */ + if (s->lfe_on) { + s->start_freq[s->lfe_channel] = 0; + for (blk = 0; blk < s->num_blocks; blk++) + s->blocks[blk].end_freq[ch] = 7; + } + + /* initialize coupling strategy */ + if (s->cpl_enabled) { + if (s->options.cpl_start != AC3ENC_OPT_AUTO) { + cpl_start = s->options.cpl_start; + } else { + cpl_start = ac3_coupling_start_tab[s->channel_mode-2][s->bit_alloc.sr_code][s->frame_size_code/2]; + if (cpl_start < 0) { + if (s->options.channel_coupling == AC3ENC_OPT_AUTO) + s->cpl_enabled = 0; + else + cpl_start = 15; + } + } + } + if (s->cpl_enabled) { + int i, cpl_start_band, cpl_end_band; + uint8_t *cpl_band_sizes = s->cpl_band_sizes; + + cpl_end_band = s->bandwidth_code / 4 + 3; + cpl_start_band = av_clip(cpl_start, 0, FFMIN(cpl_end_band-1, 15)); + + s->num_cpl_subbands = cpl_end_band - cpl_start_band; + + s->num_cpl_bands = 1; + *cpl_band_sizes = 12; + for (i = cpl_start_band + 1; i < cpl_end_band; i++) { + if (ff_eac3_default_cpl_band_struct[i]) { + *cpl_band_sizes += 12; + } else { + s->num_cpl_bands++; + cpl_band_sizes++; + *cpl_band_sizes = 12; + } + } + + s->start_freq[CPL_CH] = cpl_start_band * 12 + 37; + s->cpl_end_freq = cpl_end_band * 12 + 37; + for (blk = 0; blk < s->num_blocks; blk++) + s->blocks[blk].end_freq[CPL_CH] = s->cpl_end_freq; + } +} + + +static av_cold int allocate_buffers(AC3EncodeContext *s) +{ + AVCodecContext *avctx = s->avctx; + int blk, ch; + int channels = s->channels + 1; /* includes coupling channel */ + int channel_blocks = channels * s->num_blocks; + int total_coefs = AC3_MAX_COEFS * channel_blocks; + + if (s->allocate_sample_buffers(s)) + goto alloc_fail; + + FF_ALLOC_OR_GOTO(avctx, s->bap_buffer, total_coefs * + sizeof(*s->bap_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->bap1_buffer, total_coefs * + sizeof(*s->bap1_buffer), alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, s->mdct_coef_buffer, total_coefs * + sizeof(*s->mdct_coef_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->exp_buffer, total_coefs * + sizeof(*s->exp_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->grouped_exp_buffer, channel_blocks * 128 * + sizeof(*s->grouped_exp_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->psd_buffer, total_coefs * + sizeof(*s->psd_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->band_psd_buffer, channel_blocks * 64 * + sizeof(*s->band_psd_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->mask_buffer, channel_blocks * 64 * + sizeof(*s->mask_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->qmant_buffer, total_coefs * + sizeof(*s->qmant_buffer), alloc_fail); + if (s->cpl_enabled) { + FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_exp_buffer, channel_blocks * 16 * + sizeof(*s->cpl_coord_exp_buffer), alloc_fail); + FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_mant_buffer, channel_blocks * 16 * + sizeof(*s->cpl_coord_mant_buffer), alloc_fail); + } + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + FF_ALLOCZ_OR_GOTO(avctx, block->mdct_coef, channels * sizeof(*block->mdct_coef), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->exp, channels * sizeof(*block->exp), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->grouped_exp, channels * sizeof(*block->grouped_exp), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->psd, channels * sizeof(*block->psd), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->band_psd, channels * sizeof(*block->band_psd), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->mask, channels * sizeof(*block->mask), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->qmant, channels * sizeof(*block->qmant), + alloc_fail); + if (s->cpl_enabled) { + FF_ALLOCZ_OR_GOTO(avctx, block->cpl_coord_exp, channels * sizeof(*block->cpl_coord_exp), + alloc_fail); + FF_ALLOCZ_OR_GOTO(avctx, block->cpl_coord_mant, channels * sizeof(*block->cpl_coord_mant), + alloc_fail); + } + + for (ch = 0; ch < channels; ch++) { + /* arrangement: block, channel, coeff */ + block->grouped_exp[ch] = &s->grouped_exp_buffer[128 * (blk * channels + ch)]; + block->psd[ch] = &s->psd_buffer [AC3_MAX_COEFS * (blk * channels + ch)]; + block->band_psd[ch] = &s->band_psd_buffer [64 * (blk * channels + ch)]; + block->mask[ch] = &s->mask_buffer [64 * (blk * channels + ch)]; + block->qmant[ch] = &s->qmant_buffer [AC3_MAX_COEFS * (blk * channels + ch)]; + if (s->cpl_enabled) { + block->cpl_coord_exp[ch] = &s->cpl_coord_exp_buffer [16 * (blk * channels + ch)]; + block->cpl_coord_mant[ch] = &s->cpl_coord_mant_buffer[16 * (blk * channels + ch)]; + } + + /* arrangement: channel, block, coeff */ + block->exp[ch] = &s->exp_buffer [AC3_MAX_COEFS * (s->num_blocks * ch + blk)]; + block->mdct_coef[ch] = &s->mdct_coef_buffer [AC3_MAX_COEFS * (s->num_blocks * ch + blk)]; + } + } + + if (!s->fixed_point) { + FF_ALLOCZ_OR_GOTO(avctx, s->fixed_coef_buffer, total_coefs * + sizeof(*s->fixed_coef_buffer), alloc_fail); + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + FF_ALLOCZ_OR_GOTO(avctx, block->fixed_coef, channels * + sizeof(*block->fixed_coef), alloc_fail); + for (ch = 0; ch < channels; ch++) + block->fixed_coef[ch] = &s->fixed_coef_buffer[AC3_MAX_COEFS * (s->num_blocks * ch + blk)]; + } + } else { + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + FF_ALLOCZ_OR_GOTO(avctx, block->fixed_coef, channels * + sizeof(*block->fixed_coef), alloc_fail); + for (ch = 0; ch < channels; ch++) + block->fixed_coef[ch] = (int32_t *)block->mdct_coef[ch]; + } + } + + return 0; +alloc_fail: + return AVERROR(ENOMEM); +} + + +av_cold int ff_ac3_encode_init(AVCodecContext *avctx) +{ + AC3EncodeContext *s = avctx->priv_data; + int ret, frame_size_58; + + s->avctx = avctx; + + s->eac3 = avctx->codec_id == AV_CODEC_ID_EAC3; + + ff_ac3_common_init(); + + ret = validate_options(s); + if (ret) + return ret; + + avctx->frame_size = AC3_BLOCK_SIZE * s->num_blocks; + avctx->delay = AC3_BLOCK_SIZE; + + s->bitstream_mode = avctx->audio_service_type; + if (s->bitstream_mode == AV_AUDIO_SERVICE_TYPE_KARAOKE) + s->bitstream_mode = 0x7; + + s->bits_written = 0; + s->samples_written = 0; + + /* calculate crc_inv for both possible frame sizes */ + frame_size_58 = (( s->frame_size >> 2) + ( s->frame_size >> 4)) << 1; + s->crc_inv[0] = pow_poly((CRC16_POLY >> 1), (8 * frame_size_58) - 16, CRC16_POLY); + if (s->bit_alloc.sr_code == 1) { + frame_size_58 = (((s->frame_size+2) >> 2) + ((s->frame_size+2) >> 4)) << 1; + s->crc_inv[1] = pow_poly((CRC16_POLY >> 1), (8 * frame_size_58) - 16, CRC16_POLY); + } + + /* set function pointers */ + if (CONFIG_AC3_FIXED_ENCODER && s->fixed_point) { + s->mdct_end = ff_ac3_fixed_mdct_end; + s->mdct_init = ff_ac3_fixed_mdct_init; + s->allocate_sample_buffers = ff_ac3_fixed_allocate_sample_buffers; + } else if (CONFIG_AC3_ENCODER || CONFIG_EAC3_ENCODER) { + s->mdct_end = ff_ac3_float_mdct_end; + s->mdct_init = ff_ac3_float_mdct_init; + s->allocate_sample_buffers = ff_ac3_float_allocate_sample_buffers; + } + if (CONFIG_EAC3_ENCODER && s->eac3) + s->output_frame_header = ff_eac3_output_frame_header; + else + s->output_frame_header = ac3_output_frame_header; + + set_bandwidth(s); + + exponent_init(s); + + bit_alloc_init(s); + + ret = s->mdct_init(s); + if (ret) + goto init_fail; + + ret = allocate_buffers(s); + if (ret) + goto init_fail; + + ff_dsputil_init(&s->dsp, avctx); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT); + + dprint_options(s); + + return 0; +init_fail: + ff_ac3_encode_close(avctx); + return ret; +} diff --git a/ffmpeg/libavcodec/ac3enc.h b/ffmpeg/libavcodec/ac3enc.h new file mode 100644 index 0000000..be9dcf2 --- /dev/null +++ b/ffmpeg/libavcodec/ac3enc.h @@ -0,0 +1,308 @@ +/* + * AC-3 encoder & E-AC-3 encoder common header + * Copyright (c) 2000 Fabrice Bellard + * Copyright (c) 2006-2010 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * AC-3 encoder & E-AC-3 encoder common header + */ + +#ifndef AVCODEC_AC3ENC_H +#define AVCODEC_AC3ENC_H + +#include + +#include "libavutil/float_dsp.h" +#include "ac3.h" +#include "ac3dsp.h" +#include "avcodec.h" +#include "dsputil.h" +#include "put_bits.h" +#include "fft.h" + +#ifndef CONFIG_AC3ENC_FLOAT +#define CONFIG_AC3ENC_FLOAT 0 +#endif + +#define OFFSET(param) offsetof(AC3EncodeContext, options.param) +#define AC3ENC_PARAM (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) + +#define AC3ENC_TYPE_AC3_FIXED 0 +#define AC3ENC_TYPE_AC3 1 +#define AC3ENC_TYPE_EAC3 2 + +#if CONFIG_AC3ENC_FLOAT +#define AC3_NAME(x) ff_ac3_float_ ## x +#define MAC_COEF(d,a,b) ((d)+=(a)*(b)) +#define COEF_MIN (-16777215.0/16777216.0) +#define COEF_MAX ( 16777215.0/16777216.0) +#define NEW_CPL_COORD_THRESHOLD 0.03 +typedef float SampleType; +typedef float CoefType; +typedef float CoefSumType; +#else +#define AC3_NAME(x) ff_ac3_fixed_ ## x +#define MAC_COEF(d,a,b) MAC64(d,a,b) +#define COEF_MIN -16777215 +#define COEF_MAX 16777215 +#define NEW_CPL_COORD_THRESHOLD 503317 +typedef int16_t SampleType; +typedef int32_t CoefType; +typedef int64_t CoefSumType; +#endif + +/* common option values */ +#define AC3ENC_OPT_NONE -1 +#define AC3ENC_OPT_AUTO -1 +#define AC3ENC_OPT_OFF 0 +#define AC3ENC_OPT_ON 1 +#define AC3ENC_OPT_NOT_INDICATED 0 +#define AC3ENC_OPT_MODE_ON 2 +#define AC3ENC_OPT_MODE_OFF 1 + +/* specific option values */ +#define AC3ENC_OPT_LARGE_ROOM 1 +#define AC3ENC_OPT_SMALL_ROOM 2 +#define AC3ENC_OPT_DOWNMIX_LTRT 1 +#define AC3ENC_OPT_DOWNMIX_LORO 2 +#define AC3ENC_OPT_ADCONV_STANDARD 0 +#define AC3ENC_OPT_ADCONV_HDCD 1 + + +/** + * Encoding Options used by AVOption. + */ +typedef struct AC3EncOptions { + /* AC-3 metadata options*/ + int dialogue_level; + int bitstream_mode; + float center_mix_level; + float surround_mix_level; + int dolby_surround_mode; + int audio_production_info; + int mixing_level; + int room_type; + int copyright; + int original; + int extended_bsi_1; + int preferred_stereo_downmix; + float ltrt_center_mix_level; + float ltrt_surround_mix_level; + float loro_center_mix_level; + float loro_surround_mix_level; + int extended_bsi_2; + int dolby_surround_ex_mode; + int dolby_headphone_mode; + int ad_converter_type; + int eac3_mixing_metadata; + int eac3_info_metadata; + + /* other encoding options */ + int allow_per_frame_metadata; + int stereo_rematrixing; + int channel_coupling; + int cpl_start; +} AC3EncOptions; + +/** + * Data for a single audio block. + */ +typedef struct AC3Block { + CoefType **mdct_coef; ///< MDCT coefficients + int32_t **fixed_coef; ///< fixed-point MDCT coefficients + uint8_t **exp; ///< original exponents + uint8_t **grouped_exp; ///< grouped exponents + int16_t **psd; ///< psd per frequency bin + int16_t **band_psd; ///< psd per critical band + int16_t **mask; ///< masking curve + uint16_t **qmant; ///< quantized mantissas + uint8_t **cpl_coord_exp; ///< coupling coord exponents (cplcoexp) + uint8_t **cpl_coord_mant; ///< coupling coord mantissas (cplcomant) + uint8_t coeff_shift[AC3_MAX_CHANNELS]; ///< fixed-point coefficient shift values + uint8_t new_rematrixing_strategy; ///< send new rematrixing flags in this block + int num_rematrixing_bands; ///< number of rematrixing bands + uint8_t rematrixing_flags[4]; ///< rematrixing flags + int new_cpl_strategy; ///< send new coupling strategy + int cpl_in_use; ///< coupling in use for this block (cplinu) + uint8_t channel_in_cpl[AC3_MAX_CHANNELS]; ///< channel in coupling (chincpl) + int num_cpl_channels; ///< number of channels in coupling + uint8_t new_cpl_coords[AC3_MAX_CHANNELS]; ///< send new coupling coordinates (cplcoe) + uint8_t cpl_master_exp[AC3_MAX_CHANNELS]; ///< coupling coord master exponents (mstrcplco) + int new_snr_offsets; ///< send new SNR offsets + int new_cpl_leak; ///< send new coupling leak info + int end_freq[AC3_MAX_CHANNELS]; ///< end frequency bin (endmant) +} AC3Block; + +/** + * AC-3 encoder private context. + */ +typedef struct AC3EncodeContext { + AVClass *av_class; ///< AVClass used for AVOption + AC3EncOptions options; ///< encoding options + AVCodecContext *avctx; ///< parent AVCodecContext + PutBitContext pb; ///< bitstream writer context + DSPContext dsp; + AVFloatDSPContext fdsp; + AC3DSPContext ac3dsp; ///< AC-3 optimized functions + FFTContext mdct; ///< FFT context for MDCT calculation + const SampleType *mdct_window; ///< MDCT window function array + + AC3Block blocks[AC3_MAX_BLOCKS]; ///< per-block info + + int fixed_point; ///< indicates if fixed-point encoder is being used + int eac3; ///< indicates if this is E-AC-3 vs. AC-3 + int bitstream_id; ///< bitstream id (bsid) + int bitstream_mode; ///< bitstream mode (bsmod) + + int bit_rate; ///< target bit rate, in bits-per-second + int sample_rate; ///< sampling frequency, in Hz + + int num_blks_code; ///< number of blocks code (numblkscod) + int num_blocks; ///< number of blocks per frame + int frame_size_min; ///< minimum frame size in case rounding is necessary + int frame_size; ///< current frame size in bytes + int frame_size_code; ///< frame size code (frmsizecod) + uint16_t crc_inv[2]; + int64_t bits_written; ///< bit count (used to avg. bitrate) + int64_t samples_written; ///< sample count (used to avg. bitrate) + + int fbw_channels; ///< number of full-bandwidth channels (nfchans) + int channels; ///< total number of channels (nchans) + int lfe_on; ///< indicates if there is an LFE channel (lfeon) + int lfe_channel; ///< channel index of the LFE channel + int has_center; ///< indicates if there is a center channel + int has_surround; ///< indicates if there are one or more surround channels + int channel_mode; ///< channel mode (acmod) + const uint8_t *channel_map; ///< channel map used to reorder channels + + int center_mix_level; ///< center mix level code + int surround_mix_level; ///< surround mix level code + int ltrt_center_mix_level; ///< Lt/Rt center mix level code + int ltrt_surround_mix_level; ///< Lt/Rt surround mix level code + int loro_center_mix_level; ///< Lo/Ro center mix level code + int loro_surround_mix_level; ///< Lo/Ro surround mix level code + + int cutoff; ///< user-specified cutoff frequency, in Hz + int bandwidth_code; ///< bandwidth code (0 to 60) (chbwcod) + int start_freq[AC3_MAX_CHANNELS]; ///< start frequency bin (strtmant) + int cpl_end_freq; ///< coupling channel end frequency bin + + int cpl_on; ///< coupling turned on for this frame + int cpl_enabled; ///< coupling enabled for all frames + int num_cpl_subbands; ///< number of coupling subbands (ncplsubnd) + int num_cpl_bands; ///< number of coupling bands (ncplbnd) + uint8_t cpl_band_sizes[AC3_MAX_CPL_BANDS]; ///< number of coeffs in each coupling band + + int rematrixing_enabled; ///< stereo rematrixing enabled + + /* bitrate allocation control */ + int slow_gain_code; ///< slow gain code (sgaincod) + int slow_decay_code; ///< slow decay code (sdcycod) + int fast_decay_code; ///< fast decay code (fdcycod) + int db_per_bit_code; ///< dB/bit code (dbpbcod) + int floor_code; ///< floor code (floorcod) + AC3BitAllocParameters bit_alloc; ///< bit allocation parameters + int coarse_snr_offset; ///< coarse SNR offsets (csnroffst) + int fast_gain_code[AC3_MAX_CHANNELS]; ///< fast gain codes (signal-to-mask ratio) (fgaincod) + int fine_snr_offset[AC3_MAX_CHANNELS]; ///< fine SNR offsets (fsnroffst) + int frame_bits_fixed; ///< number of non-coefficient bits for fixed parameters + int frame_bits; ///< all frame bits except exponents and mantissas + int exponent_bits; ///< number of bits used for exponents + + SampleType *windowed_samples; + SampleType **planar_samples; + uint8_t *bap_buffer; + uint8_t *bap1_buffer; + CoefType *mdct_coef_buffer; + int32_t *fixed_coef_buffer; + uint8_t *exp_buffer; + uint8_t *grouped_exp_buffer; + int16_t *psd_buffer; + int16_t *band_psd_buffer; + int16_t *mask_buffer; + int16_t *qmant_buffer; + uint8_t *cpl_coord_exp_buffer; + uint8_t *cpl_coord_mant_buffer; + + uint8_t exp_strategy[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< exponent strategies + uint8_t frame_exp_strategy[AC3_MAX_CHANNELS]; ///< frame exp strategy index + int use_frame_exp_strategy; ///< indicates use of frame exp strategy + uint8_t exp_ref_block[AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< reference blocks for EXP_REUSE + uint8_t *ref_bap [AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< bit allocation pointers (bap) + int ref_bap_set; ///< indicates if ref_bap pointers have been set + + /* fixed vs. float function pointers */ + void (*mdct_end)(struct AC3EncodeContext *s); + int (*mdct_init)(struct AC3EncodeContext *s); + + /* fixed vs. float templated function pointers */ + int (*allocate_sample_buffers)(struct AC3EncodeContext *s); + + /* AC-3 vs. E-AC-3 function pointers */ + void (*output_frame_header)(struct AC3EncodeContext *s); +} AC3EncodeContext; + + +extern const uint64_t ff_ac3_channel_layouts[19]; + +int ff_ac3_encode_init(AVCodecContext *avctx); + +int ff_ac3_encode_close(AVCodecContext *avctx); + +int ff_ac3_validate_metadata(AC3EncodeContext *s); + +void ff_ac3_adjust_frame_size(AC3EncodeContext *s); + +void ff_ac3_compute_coupling_strategy(AC3EncodeContext *s); + +void ff_ac3_apply_rematrixing(AC3EncodeContext *s); + +void ff_ac3_process_exponents(AC3EncodeContext *s); + +int ff_ac3_compute_bit_allocation(AC3EncodeContext *s); + +void ff_ac3_group_exponents(AC3EncodeContext *s); + +void ff_ac3_quantize_mantissas(AC3EncodeContext *s); + +void ff_ac3_output_frame(AC3EncodeContext *s, unsigned char *frame); + + +/* prototypes for functions in ac3enc_fixed.c and ac3enc_float.c */ + +void ff_ac3_fixed_mdct_end(AC3EncodeContext *s); +void ff_ac3_float_mdct_end(AC3EncodeContext *s); + +int ff_ac3_fixed_mdct_init(AC3EncodeContext *s); +int ff_ac3_float_mdct_init(AC3EncodeContext *s); + + +/* prototypes for functions in ac3enc_template.c */ + +int ff_ac3_fixed_allocate_sample_buffers(AC3EncodeContext *s); +int ff_ac3_float_allocate_sample_buffers(AC3EncodeContext *s); + +int ff_ac3_fixed_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); +int ff_ac3_float_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +#endif /* AVCODEC_AC3ENC_H */ diff --git a/ffmpeg/libavcodec/ac3enc_fixed.c b/ffmpeg/libavcodec/ac3enc_fixed.c new file mode 100644 index 0000000..5d8dd5c --- /dev/null +++ b/ffmpeg/libavcodec/ac3enc_fixed.c @@ -0,0 +1,169 @@ +/* + * The simplest AC-3 encoder + * Copyright (c) 2000 Fabrice Bellard + * Copyright (c) 2006-2010 Justin Ruggles + * Copyright (c) 2006-2010 Prakash Punnoor + * + * 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 + */ + +/** + * @file + * fixed-point AC-3 encoder. + */ + +#define CONFIG_FFT_FLOAT 0 +#undef CONFIG_AC3ENC_FLOAT +#include "internal.h" +#include "ac3enc.h" +#include "eac3enc.h" + +#define AC3ENC_TYPE AC3ENC_TYPE_AC3_FIXED +#include "ac3enc_opts_template.c" + +static const AVClass ac3enc_class = { + .class_name = "Fixed-Point AC-3 Encoder", + .item_name = av_default_item_name, + .option = ac3_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +#include "ac3enc_template.c" + + +/** + * Finalize MDCT and free allocated memory. + * + * @param s AC-3 encoder private context + */ +av_cold void AC3_NAME(mdct_end)(AC3EncodeContext *s) +{ + ff_mdct_end(&s->mdct); +} + + +/** + * Initialize MDCT tables. + * + * @param s AC-3 encoder private context + * @return 0 on success, negative error code on failure + */ +av_cold int AC3_NAME(mdct_init)(AC3EncodeContext *s) +{ + int ret = ff_mdct_init(&s->mdct, 9, 0, -1.0); + s->mdct_window = ff_ac3_window; + return ret; +} + + +/* + * Apply KBD window to input samples prior to MDCT. + */ +static void apply_window(void *dsp, int16_t *output, const int16_t *input, + const int16_t *window, unsigned int len) +{ + DSPContext *dsp0 = dsp; + dsp0->apply_window_int16(output, input, window, len); +} + + +/* + * Normalize the input samples to use the maximum available precision. + * This assumes signed 16-bit input samples. + */ +static int normalize_samples(AC3EncodeContext *s) +{ + int v = s->ac3dsp.ac3_max_msb_abs_int16(s->windowed_samples, AC3_WINDOW_SIZE); + v = 14 - av_log2(v); + if (v > 0) + s->ac3dsp.ac3_lshift_int16(s->windowed_samples, AC3_WINDOW_SIZE, v); + /* +6 to right-shift from 31-bit to 25-bit */ + return v + 6; +} + + +/* + * Scale MDCT coefficients to 25-bit signed fixed-point. + */ +static void scale_coefficients(AC3EncodeContext *s) +{ + int blk, ch; + + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = 1; ch <= s->channels; ch++) { + s->ac3dsp.ac3_rshift_int32(block->mdct_coef[ch], AC3_MAX_COEFS, + block->coeff_shift[ch]); + } + } +} + +static void sum_square_butterfly(AC3EncodeContext *s, int64_t sum[4], + const int32_t *coef0, const int32_t *coef1, + int len) +{ + s->ac3dsp.sum_square_butterfly_int32(sum, coef0, coef1, len); +} + +/* + * Clip MDCT coefficients to allowable range. + */ +static void clip_coefficients(DSPContext *dsp, int32_t *coef, unsigned int len) +{ + dsp->vector_clip_int32(coef, coef, COEF_MIN, COEF_MAX, len); +} + + +/* + * Calculate a single coupling coordinate. + */ +static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl) +{ + if (energy_cpl <= COEF_MAX) { + return 1048576; + } else { + uint64_t coord = energy_ch / (energy_cpl >> 24); + uint32_t coord32 = FFMIN(coord, 1073741824); + coord32 = ff_sqrt(coord32) << 9; + return FFMIN(coord32, COEF_MAX); + } +} + + +static av_cold int ac3_fixed_encode_init(AVCodecContext *avctx) +{ + AC3EncodeContext *s = avctx->priv_data; + s->fixed_point = 1; + return ff_ac3_encode_init(avctx); +} + + +AVCodec ff_ac3_fixed_encoder = { + .name = "ac3_fixed", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AC3, + .priv_data_size = sizeof(AC3EncodeContext), + .init = ac3_fixed_encode_init, + .encode2 = ff_ac3_fixed_encode_frame, + .close = ff_ac3_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .priv_class = &ac3enc_class, + .channel_layouts = ff_ac3_channel_layouts, + .defaults = ac3_defaults, +}; diff --git a/ffmpeg/libavcodec/ac3enc_float.c b/ffmpeg/libavcodec/ac3enc_float.c new file mode 100644 index 0000000..7864f41 --- /dev/null +++ b/ffmpeg/libavcodec/ac3enc_float.c @@ -0,0 +1,168 @@ +/* + * The simplest AC-3 encoder + * Copyright (c) 2000 Fabrice Bellard + * Copyright (c) 2006-2010 Justin Ruggles + * Copyright (c) 2006-2010 Prakash Punnoor + * + * 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 + */ + +/** + * @file + * floating-point AC-3 encoder. + */ + +#define CONFIG_AC3ENC_FLOAT 1 +#include "internal.h" +#include "ac3enc.h" +#include "eac3enc.h" +#include "kbdwin.h" + + +#if CONFIG_AC3_ENCODER +#define AC3ENC_TYPE AC3ENC_TYPE_AC3 +#include "ac3enc_opts_template.c" +static const AVClass ac3enc_class = { + .class_name = "AC-3 Encoder", + .item_name = av_default_item_name, + .option = ac3_options, + .version = LIBAVUTIL_VERSION_INT, +}; +#endif + +#include "ac3enc_template.c" + + +/** + * Finalize MDCT and free allocated memory. + * + * @param s AC-3 encoder private context + */ +av_cold void ff_ac3_float_mdct_end(AC3EncodeContext *s) +{ + ff_mdct_end(&s->mdct); + av_freep(&s->mdct_window); +} + + +/** + * Initialize MDCT tables. + * + * @param s AC-3 encoder private context + * @return 0 on success, negative error code on failure + */ +av_cold int ff_ac3_float_mdct_init(AC3EncodeContext *s) +{ + float *window; + int i, n, n2; + + n = 1 << 9; + n2 = n >> 1; + + window = av_malloc(n * sizeof(*window)); + if (!window) { + av_log(s->avctx, AV_LOG_ERROR, "Cannot allocate memory.\n"); + return AVERROR(ENOMEM); + } + ff_kbd_window_init(window, 5.0, n2); + for (i = 0; i < n2; i++) + window[n-1-i] = window[i]; + s->mdct_window = window; + + return ff_mdct_init(&s->mdct, 9, 0, -2.0 / n); +} + + +/* + * Apply KBD window to input samples prior to MDCT. + */ +static void apply_window(void *dsp, float *output, + const float *input, const float *window, + unsigned int len) +{ + AVFloatDSPContext *fdsp = dsp; + fdsp->vector_fmul(output, input, window, len); +} + + +/* + * Normalize the input samples. + * Not needed for the floating-point encoder. + */ +static int normalize_samples(AC3EncodeContext *s) +{ + return 0; +} + + +/* + * Scale MDCT coefficients from float to 24-bit fixed-point. + */ +static void scale_coefficients(AC3EncodeContext *s) +{ + int chan_size = AC3_MAX_COEFS * s->num_blocks; + int cpl = s->cpl_on; + s->ac3dsp.float_to_fixed24(s->fixed_coef_buffer + (chan_size * !cpl), + s->mdct_coef_buffer + (chan_size * !cpl), + chan_size * (s->channels + cpl)); +} + +static void sum_square_butterfly(AC3EncodeContext *s, float sum[4], + const float *coef0, const float *coef1, + int len) +{ + s->ac3dsp.sum_square_butterfly_float(sum, coef0, coef1, len); +} + +/* + * Clip MDCT coefficients to allowable range. + */ +static void clip_coefficients(DSPContext *dsp, float *coef, unsigned int len) +{ + dsp->vector_clipf(coef, coef, COEF_MIN, COEF_MAX, len); +} + + +/* + * Calculate a single coupling coordinate. + */ +static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl) +{ + float coord = 0.125; + if (energy_cpl > 0) + coord *= sqrtf(energy_ch / energy_cpl); + return FFMIN(coord, COEF_MAX); +} + + +#if CONFIG_AC3_ENCODER +AVCodec ff_ac3_encoder = { + .name = "ac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AC3, + .priv_data_size = sizeof(AC3EncodeContext), + .init = ff_ac3_encode_init, + .encode2 = ff_ac3_float_encode_frame, + .close = ff_ac3_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .priv_class = &ac3enc_class, + .channel_layouts = ff_ac3_channel_layouts, + .defaults = ac3_defaults, +}; +#endif diff --git a/ffmpeg/libavcodec/ac3enc_opts_template.c b/ffmpeg/libavcodec/ac3enc_opts_template.c new file mode 100644 index 0000000..339a08f --- /dev/null +++ b/ffmpeg/libavcodec/ac3enc_opts_template.c @@ -0,0 +1,80 @@ +/* + * AC-3 encoder options + * Copyright (c) 2011 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "internal.h" +#include "ac3.h" + +static const AVOption ac3_options[] = { +/* Metadata Options */ +{"per_frame_metadata", "Allow Changing Metadata Per-Frame", OFFSET(allow_per_frame_metadata), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, AC3ENC_PARAM}, +#if AC3ENC_TYPE != AC3ENC_TYPE_EAC3 +/* AC-3 downmix levels */ +{"center_mixlev", "Center Mix Level", OFFSET(center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_4POINT5DB }, 0.0, 1.0, AC3ENC_PARAM}, +{"surround_mixlev", "Surround Mix Level", OFFSET(surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = LEVEL_MINUS_6DB }, 0.0, 1.0, AC3ENC_PARAM}, +#endif +/* audio production information */ +{"mixing_level", "Mixing Level", OFFSET(mixing_level), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 111, AC3ENC_PARAM}, +{"room_type", "Room Type", OFFSET(room_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_SMALL_ROOM, AC3ENC_PARAM, "room_type"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, + {"large", "Large Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_LARGE_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, + {"small", "Small Room", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_SMALL_ROOM }, INT_MIN, INT_MAX, AC3ENC_PARAM, "room_type"}, +/* other metadata options */ +{"copyright", "Copyright Bit", OFFSET(copyright), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, +{"dialnorm", "Dialogue Level (dB)", OFFSET(dialogue_level), AV_OPT_TYPE_INT, {.i64 = -31 }, -31, -1, AC3ENC_PARAM}, +{"dsur_mode", "Dolby Surround Mode", OFFSET(dolby_surround_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsur_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, + {"on", "Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, + {"off", "Not Dolby Surround Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsur_mode"}, +{"original", "Original Bit Stream", OFFSET(original), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, 1, AC3ENC_PARAM}, +/* extended bitstream information */ +{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_DOWNMIX_LORO, AC3ENC_PARAM, "dmix_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, + {"ltrt", "Lt/Rt Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LTRT }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, + {"loro", "Lo/Ro Downmix Preferred", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_DOWNMIX_LORO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dmix_mode"}, +{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, AC3ENC_PARAM}, +{"dsurex_mode", "Dolby Surround EX Mode", OFFSET(dolby_surround_ex_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dsurex_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, + {"on", "Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, + {"off", "Not Dolby Surround EX Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dsurex_mode"}, +{"dheadphone_mode", "Dolby Headphone Mode", OFFSET(dolby_headphone_mode), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_MODE_ON, AC3ENC_PARAM, "dheadphone_mode"}, + {"notindicated", "Not Indicated (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_NOT_INDICATED }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, + {"on", "Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_ON }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, + {"off", "Not Dolby Headphone Encoded", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_MODE_OFF }, INT_MIN, INT_MAX, AC3ENC_PARAM, "dheadphone_mode"}, +{"ad_conv_type", "A/D Converter Type", OFFSET(ad_converter_type), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_NONE }, AC3ENC_OPT_NONE, AC3ENC_OPT_ADCONV_HDCD, AC3ENC_PARAM, "ad_conv_type"}, + {"standard", "Standard (default)", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_STANDARD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, + {"hdcd", "HDCD", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_ADCONV_HDCD }, INT_MIN, INT_MAX, AC3ENC_PARAM, "ad_conv_type"}, +/* Other Encoding Options */ +{"stereo_rematrixing", "Stereo Rematrixing", OFFSET(stereo_rematrixing), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_ON }, AC3ENC_OPT_OFF, AC3ENC_OPT_ON, AC3ENC_PARAM}, +{"channel_coupling", "Channel Coupling", OFFSET(channel_coupling), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, AC3ENC_OPT_ON, AC3ENC_PARAM, "channel_coupling"}, + {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "channel_coupling"}, +{"cpl_start_band", "Coupling Start Band", OFFSET(cpl_start), AV_OPT_TYPE_INT, {.i64 = AC3ENC_OPT_AUTO }, AC3ENC_OPT_AUTO, 15, AC3ENC_PARAM, "cpl_start_band"}, + {"auto", "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = AC3ENC_OPT_AUTO }, INT_MIN, INT_MAX, AC3ENC_PARAM, "cpl_start_band"}, +{NULL} +}; + +static const AVCodecDefault ac3_defaults[] = { + { "b", "0" }, + { NULL } +}; diff --git a/ffmpeg/libavcodec/ac3enc_template.c b/ffmpeg/libavcodec/ac3enc_template.c new file mode 100644 index 0000000..0389c2e --- /dev/null +++ b/ffmpeg/libavcodec/ac3enc_template.c @@ -0,0 +1,447 @@ +/* + * AC-3 encoder float/fixed template + * Copyright (c) 2000 Fabrice Bellard + * Copyright (c) 2006-2011 Justin Ruggles + * Copyright (c) 2006-2010 Prakash Punnoor + * + * 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 + */ + +/** + * @file + * AC-3 encoder float/fixed template + */ + +#include + +#include "libavutil/internal.h" + +/* prototypes for static functions in ac3enc_fixed.c and ac3enc_float.c */ + +static void scale_coefficients(AC3EncodeContext *s); + +static void apply_window(void *dsp, SampleType *output, + const SampleType *input, const SampleType *window, + unsigned int len); + +static int normalize_samples(AC3EncodeContext *s); + +static void clip_coefficients(DSPContext *dsp, CoefType *coef, unsigned int len); + +static CoefType calc_cpl_coord(CoefSumType energy_ch, CoefSumType energy_cpl); + +static void sum_square_butterfly(AC3EncodeContext *s, CoefSumType sum[4], + const CoefType *coef0, const CoefType *coef1, + int len); + +int AC3_NAME(allocate_sample_buffers)(AC3EncodeContext *s) +{ + int ch; + + FF_ALLOC_OR_GOTO(s->avctx, s->windowed_samples, AC3_WINDOW_SIZE * + sizeof(*s->windowed_samples), alloc_fail); + FF_ALLOC_OR_GOTO(s->avctx, s->planar_samples, s->channels * sizeof(*s->planar_samples), + alloc_fail); + for (ch = 0; ch < s->channels; ch++) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->planar_samples[ch], + (AC3_FRAME_SIZE+AC3_BLOCK_SIZE) * sizeof(**s->planar_samples), + alloc_fail); + } + + return 0; +alloc_fail: + return AVERROR(ENOMEM); +} + + +/* + * Copy input samples. + * Channels are reordered from FFmpeg's default order to AC-3 order. + */ +static void copy_input_samples(AC3EncodeContext *s, SampleType **samples) +{ + int ch; + + /* copy and remap input samples */ + for (ch = 0; ch < s->channels; ch++) { + /* copy last 256 samples of previous frame to the start of the current frame */ + memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_BLOCK_SIZE * s->num_blocks], + AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0])); + + /* copy new samples for current frame */ + memcpy(&s->planar_samples[ch][AC3_BLOCK_SIZE], + samples[s->channel_map[ch]], + AC3_BLOCK_SIZE * s->num_blocks * sizeof(s->planar_samples[0][0])); + } +} + + +/* + * Apply the MDCT to input samples to generate frequency coefficients. + * This applies the KBD window and normalizes the input to reduce precision + * loss due to fixed-point calculations. + */ +static void apply_mdct(AC3EncodeContext *s) +{ + int blk, ch; + + for (ch = 0; ch < s->channels; ch++) { + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE]; + +#if CONFIG_AC3ENC_FLOAT + apply_window(&s->fdsp, s->windowed_samples, input_samples, + s->mdct_window, AC3_WINDOW_SIZE); +#else + apply_window(&s->dsp, s->windowed_samples, input_samples, + s->mdct_window, AC3_WINDOW_SIZE); +#endif + + if (s->fixed_point) + block->coeff_shift[ch+1] = normalize_samples(s); + + s->mdct.mdct_calcw(&s->mdct, block->mdct_coef[ch+1], + s->windowed_samples); + } + } +} + + +/* + * Calculate coupling channel and coupling coordinates. + */ +static void apply_channel_coupling(AC3EncodeContext *s) +{ + LOCAL_ALIGNED_16(CoefType, cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]); +#if CONFIG_AC3ENC_FLOAT + LOCAL_ALIGNED_16(int32_t, fixed_cpl_coords, [AC3_MAX_BLOCKS], [AC3_MAX_CHANNELS][16]); +#else + int32_t (*fixed_cpl_coords)[AC3_MAX_CHANNELS][16] = cpl_coords; +#endif + int av_uninit(blk), ch, bnd, i, j; + CoefSumType energy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][16] = {{{0}}}; + int cpl_start, num_cpl_coefs; + + memset(cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords)); +#if CONFIG_AC3ENC_FLOAT + memset(fixed_cpl_coords, 0, AC3_MAX_BLOCKS * sizeof(*cpl_coords)); +#endif + + /* align start to 16-byte boundary. align length to multiple of 32. + note: coupling start bin % 4 will always be 1 */ + cpl_start = s->start_freq[CPL_CH] - 1; + num_cpl_coefs = FFALIGN(s->num_cpl_subbands * 12 + 1, 32); + cpl_start = FFMIN(256, cpl_start + num_cpl_coefs) - num_cpl_coefs; + + /* calculate coupling channel from fbw channels */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + CoefType *cpl_coef = &block->mdct_coef[CPL_CH][cpl_start]; + if (!block->cpl_in_use) + continue; + memset(cpl_coef, 0, num_cpl_coefs * sizeof(*cpl_coef)); + for (ch = 1; ch <= s->fbw_channels; ch++) { + CoefType *ch_coef = &block->mdct_coef[ch][cpl_start]; + if (!block->channel_in_cpl[ch]) + continue; + for (i = 0; i < num_cpl_coefs; i++) + cpl_coef[i] += ch_coef[i]; + } + + /* coefficients must be clipped in order to be encoded */ + clip_coefficients(&s->dsp, cpl_coef, num_cpl_coefs); + } + + /* calculate energy in each band in coupling channel and each fbw channel */ + /* TODO: possibly use SIMD to speed up energy calculation */ + bnd = 0; + i = s->start_freq[CPL_CH]; + while (i < s->cpl_end_freq) { + int band_size = s->cpl_band_sizes[bnd]; + for (ch = CPL_CH; ch <= s->fbw_channels; ch++) { + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + if (!block->cpl_in_use || (ch > CPL_CH && !block->channel_in_cpl[ch])) + continue; + for (j = 0; j < band_size; j++) { + CoefType v = block->mdct_coef[ch][i+j]; + MAC_COEF(energy[blk][ch][bnd], v, v); + } + } + } + i += band_size; + bnd++; + } + + /* calculate coupling coordinates for all blocks for all channels */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + if (!block->cpl_in_use) + continue; + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (!block->channel_in_cpl[ch]) + continue; + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + cpl_coords[blk][ch][bnd] = calc_cpl_coord(energy[blk][ch][bnd], + energy[blk][CPL_CH][bnd]); + } + } + } + + /* determine which blocks to send new coupling coordinates for */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + AC3Block *block0 = blk ? &s->blocks[blk-1] : NULL; + + memset(block->new_cpl_coords, 0, sizeof(block->new_cpl_coords)); + + if (block->cpl_in_use) { + /* send new coordinates if this is the first block, if previous + * block did not use coupling but this block does, the channels + * using coupling has changed from the previous block, or the + * coordinate difference from the last block for any channel is + * greater than a threshold value. */ + if (blk == 0 || !block0->cpl_in_use) { + for (ch = 1; ch <= s->fbw_channels; ch++) + block->new_cpl_coords[ch] = 1; + } else { + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (!block->channel_in_cpl[ch]) + continue; + if (!block0->channel_in_cpl[ch]) { + block->new_cpl_coords[ch] = 1; + } else { + CoefSumType coord_diff = 0; + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + coord_diff += FFABS(cpl_coords[blk-1][ch][bnd] - + cpl_coords[blk ][ch][bnd]); + } + coord_diff /= s->num_cpl_bands; + if (coord_diff > NEW_CPL_COORD_THRESHOLD) + block->new_cpl_coords[ch] = 1; + } + } + } + } + } + + /* calculate final coupling coordinates, taking into account reusing of + coordinates in successive blocks */ + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + blk = 0; + while (blk < s->num_blocks) { + int av_uninit(blk1); + AC3Block *block = &s->blocks[blk]; + + if (!block->cpl_in_use) { + blk++; + continue; + } + + for (ch = 1; ch <= s->fbw_channels; ch++) { + CoefSumType energy_ch, energy_cpl; + if (!block->channel_in_cpl[ch]) + continue; + energy_cpl = energy[blk][CPL_CH][bnd]; + energy_ch = energy[blk][ch][bnd]; + blk1 = blk+1; + while (!s->blocks[blk1].new_cpl_coords[ch] && blk1 < s->num_blocks) { + if (s->blocks[blk1].cpl_in_use) { + energy_cpl += energy[blk1][CPL_CH][bnd]; + energy_ch += energy[blk1][ch][bnd]; + } + blk1++; + } + cpl_coords[blk][ch][bnd] = calc_cpl_coord(energy_ch, energy_cpl); + } + blk = blk1; + } + } + + /* calculate exponents/mantissas for coupling coordinates */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + if (!block->cpl_in_use) + continue; + +#if CONFIG_AC3ENC_FLOAT + s->ac3dsp.float_to_fixed24(fixed_cpl_coords[blk][1], + cpl_coords[blk][1], + s->fbw_channels * 16); +#endif + s->ac3dsp.extract_exponents(block->cpl_coord_exp[1], + fixed_cpl_coords[blk][1], + s->fbw_channels * 16); + + for (ch = 1; ch <= s->fbw_channels; ch++) { + int bnd, min_exp, max_exp, master_exp; + + if (!block->new_cpl_coords[ch]) + continue; + + /* determine master exponent */ + min_exp = max_exp = block->cpl_coord_exp[ch][0]; + for (bnd = 1; bnd < s->num_cpl_bands; bnd++) { + int exp = block->cpl_coord_exp[ch][bnd]; + min_exp = FFMIN(exp, min_exp); + max_exp = FFMAX(exp, max_exp); + } + master_exp = ((max_exp - 15) + 2) / 3; + master_exp = FFMAX(master_exp, 0); + while (min_exp < master_exp * 3) + master_exp--; + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + block->cpl_coord_exp[ch][bnd] = av_clip(block->cpl_coord_exp[ch][bnd] - + master_exp * 3, 0, 15); + } + block->cpl_master_exp[ch] = master_exp; + + /* quantize mantissas */ + for (bnd = 0; bnd < s->num_cpl_bands; bnd++) { + int cpl_exp = block->cpl_coord_exp[ch][bnd]; + int cpl_mant = (fixed_cpl_coords[blk][ch][bnd] << (5 + cpl_exp + master_exp * 3)) >> 24; + if (cpl_exp == 15) + cpl_mant >>= 1; + else + cpl_mant -= 16; + + block->cpl_coord_mant[ch][bnd] = cpl_mant; + } + } + } + + if (CONFIG_EAC3_ENCODER && s->eac3) + ff_eac3_set_cpl_states(s); +} + + +/* + * Determine rematrixing flags for each block and band. + */ +static void compute_rematrixing_strategy(AC3EncodeContext *s) +{ + int nb_coefs; + int blk, bnd; + AC3Block *block, *block0 = NULL; + + if (s->channel_mode != AC3_CHMODE_STEREO) + return; + + for (blk = 0; blk < s->num_blocks; blk++) { + block = &s->blocks[blk]; + block->new_rematrixing_strategy = !blk; + + block->num_rematrixing_bands = 4; + if (block->cpl_in_use) { + block->num_rematrixing_bands -= (s->start_freq[CPL_CH] <= 61); + block->num_rematrixing_bands -= (s->start_freq[CPL_CH] == 37); + if (blk && block->num_rematrixing_bands != block0->num_rematrixing_bands) + block->new_rematrixing_strategy = 1; + } + nb_coefs = FFMIN(block->end_freq[1], block->end_freq[2]); + + if (!s->rematrixing_enabled) { + block0 = block; + continue; + } + + for (bnd = 0; bnd < block->num_rematrixing_bands; bnd++) { + /* calculate calculate sum of squared coeffs for one band in one block */ + int start = ff_ac3_rematrix_band_tab[bnd]; + int end = FFMIN(nb_coefs, ff_ac3_rematrix_band_tab[bnd+1]); + CoefSumType sum[4]; + sum_square_butterfly(s, sum, block->mdct_coef[1] + start, + block->mdct_coef[2] + start, end - start); + + /* compare sums to determine if rematrixing will be used for this band */ + if (FFMIN(sum[2], sum[3]) < FFMIN(sum[0], sum[1])) + block->rematrixing_flags[bnd] = 1; + else + block->rematrixing_flags[bnd] = 0; + + /* determine if new rematrixing flags will be sent */ + if (blk && + block->rematrixing_flags[bnd] != block0->rematrixing_flags[bnd]) { + block->new_rematrixing_strategy = 1; + } + } + block0 = block; + } +} + + +int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AC3EncodeContext *s = avctx->priv_data; + int ret; + + if (s->options.allow_per_frame_metadata) { + ret = ff_ac3_validate_metadata(s); + if (ret) + return ret; + } + + if (s->bit_alloc.sr_code == 1 || s->eac3) + ff_ac3_adjust_frame_size(s); + + copy_input_samples(s, (SampleType **)frame->extended_data); + + apply_mdct(s); + + if (s->fixed_point) + scale_coefficients(s); + + clip_coefficients(&s->dsp, s->blocks[0].mdct_coef[1], + AC3_MAX_COEFS * s->num_blocks * s->channels); + + s->cpl_on = s->cpl_enabled; + ff_ac3_compute_coupling_strategy(s); + + if (s->cpl_on) + apply_channel_coupling(s); + + compute_rematrixing_strategy(s); + + if (!s->fixed_point) + scale_coefficients(s); + + ff_ac3_apply_rematrixing(s); + + ff_ac3_process_exponents(s); + + ret = ff_ac3_compute_bit_allocation(s); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Bit allocation failed. Try increasing the bitrate.\n"); + return ret; + } + + ff_ac3_group_exponents(s); + + ff_ac3_quantize_mantissas(s); + + if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size)) < 0) + return ret; + ff_ac3_output_frame(s, avpkt->data); + + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + + *got_packet_ptr = 1; + return 0; +} diff --git a/ffmpeg/libavcodec/ac3tab.c b/ffmpeg/libavcodec/ac3tab.c new file mode 100644 index 0000000..9d20d90 --- /dev/null +++ b/ffmpeg/libavcodec/ac3tab.c @@ -0,0 +1,314 @@ +/* + * AC-3 tables + * copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * tables taken directly from the AC-3 spec. + */ + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "ac3tab.h" + +/** + * Possible frame sizes. + * from ATSC A/52 Table 5.18 Frame Size Code Table. + */ +const uint16_t ff_ac3_frame_size_tab[38][3] = { + { 64, 69, 96 }, + { 64, 70, 96 }, + { 80, 87, 120 }, + { 80, 88, 120 }, + { 96, 104, 144 }, + { 96, 105, 144 }, + { 112, 121, 168 }, + { 112, 122, 168 }, + { 128, 139, 192 }, + { 128, 140, 192 }, + { 160, 174, 240 }, + { 160, 175, 240 }, + { 192, 208, 288 }, + { 192, 209, 288 }, + { 224, 243, 336 }, + { 224, 244, 336 }, + { 256, 278, 384 }, + { 256, 279, 384 }, + { 320, 348, 480 }, + { 320, 349, 480 }, + { 384, 417, 576 }, + { 384, 418, 576 }, + { 448, 487, 672 }, + { 448, 488, 672 }, + { 512, 557, 768 }, + { 512, 558, 768 }, + { 640, 696, 960 }, + { 640, 697, 960 }, + { 768, 835, 1152 }, + { 768, 836, 1152 }, + { 896, 975, 1344 }, + { 896, 976, 1344 }, + { 1024, 1114, 1536 }, + { 1024, 1115, 1536 }, + { 1152, 1253, 1728 }, + { 1152, 1254, 1728 }, + { 1280, 1393, 1920 }, + { 1280, 1394, 1920 }, +}; + +/** + * Map audio coding mode (acmod) to number of full-bandwidth channels. + * from ATSC A/52 Table 5.8 Audio Coding Mode + */ +const uint8_t ff_ac3_channels_tab[8] = { + 2, 1, 2, 3, 3, 4, 4, 5 +}; + +/** + * Map audio coding mode (acmod) to channel layout mask. + */ +const uint16_t avpriv_ac3_channel_layout_tab[8] = { + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_5POINT0 +}; + +#define COMMON_CHANNEL_MAP \ + { { 0, 1, }, { 0, 1, 2, } },\ + { { 0, }, { 0, 1, } },\ + { { 0, 1, }, { 0, 1, 2, } },\ + { { 0, 2, 1, }, { 0, 2, 1, 3, } },\ + { { 0, 1, 2, }, { 0, 1, 3, 2, } },\ + { { 0, 2, 1, 3, }, { 0, 2, 1, 4, 3, } }, + +/** + * Table to remap channels from SMPTE order to AC-3 order. + * [channel_mode][lfe][ch] + */ +const uint8_t ff_ac3_enc_channel_map[8][2][6] = { + COMMON_CHANNEL_MAP + { { 0, 1, 2, 3, }, { 0, 1, 3, 4, 2, } }, + { { 0, 2, 1, 3, 4, }, { 0, 2, 1, 4, 5, 3 } }, +}; + +/** + * Table to remap channels from from AC-3 order to SMPTE order. + * [channel_mode][lfe][ch] + */ +const uint8_t ff_ac3_dec_channel_map[8][2][6] = { + COMMON_CHANNEL_MAP + { { 0, 1, 2, 3, }, { 0, 1, 4, 2, 3, } }, + { { 0, 2, 1, 3, 4, }, { 0, 2, 1, 5, 3, 4 } }, +}; + +/* possible frequencies */ +const uint16_t ff_ac3_sample_rate_tab[3] = { 48000, 44100, 32000 }; + +/* possible bitrates */ +const uint16_t ff_ac3_bitrate_tab[19] = { + 32, 40, 48, 56, 64, 80, 96, 112, 128, + 160, 192, 224, 256, 320, 384, 448, 512, 576, 640 +}; + +/** + * Table of bin locations for rematrixing bands + * reference: Section 7.5.2 Rematrixing : Frequency Band Definitions + */ +const uint8_t ff_ac3_rematrix_band_tab[5] = { 13, 25, 37, 61, 253 }; + +/** + * Table E2.16 Default Coupling Banding Structure + */ +const uint8_t ff_eac3_default_cpl_band_struct[18] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1 +}; + +/* AC-3 MDCT window */ + +/* MDCT window */ +DECLARE_ALIGNED(16, const int16_t, ff_ac3_window)[AC3_WINDOW_SIZE/2] = { + 4, 7, 12, 16, 21, 28, 34, 42, + 51, 61, 72, 84, 97, 111, 127, 145, + 164, 184, 207, 231, 257, 285, 315, 347, + 382, 419, 458, 500, 544, 591, 641, 694, + 750, 810, 872, 937, 1007, 1079, 1155, 1235, + 1318, 1406, 1497, 1593, 1692, 1796, 1903, 2016, + 2132, 2253, 2379, 2509, 2644, 2783, 2927, 3076, + 3230, 3389, 3552, 3721, 3894, 4072, 4255, 4444, + 4637, 4835, 5038, 5246, 5459, 5677, 5899, 6127, + 6359, 6596, 6837, 7083, 7334, 7589, 7848, 8112, + 8380, 8652, 8927, 9207, 9491, 9778,10069,10363, +10660,10960,11264,11570,11879,12190,12504,12820, +13138,13458,13780,14103,14427,14753,15079,15407, +15735,16063,16392,16720,17049,17377,17705,18032, +18358,18683,19007,19330,19651,19970,20287,20602, +20914,21225,21532,21837,22139,22438,22733,23025, +23314,23599,23880,24157,24430,24699,24964,25225, +25481,25732,25979,26221,26459,26691,26919,27142, +27359,27572,27780,27983,28180,28373,28560,28742, +28919,29091,29258,29420,29577,29729,29876,30018, +30155,30288,30415,30538,30657,30771,30880,30985, +31086,31182,31274,31363,31447,31528,31605,31678, +31747,31814,31877,31936,31993,32046,32097,32145, +32190,32232,32272,32310,32345,32378,32409,32438, +32465,32490,32513,32535,32556,32574,32592,32608, +32623,32636,32649,32661,32671,32681,32690,32698, +32705,32712,32718,32724,32729,32733,32737,32741, +32744,32747,32750,32752,32754,32756,32757,32759, +32760,32761,32762,32763,32764,32764,32765,32765, +32766,32766,32766,32766,32767,32767,32767,32767, +32767,32767,32767,32767,32767,32767,32767,32767, +32767,32767,32767,32767,32767,32767,32767,32767, +}; + +const uint8_t ff_ac3_log_add_tab[260]= { +0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37, +0x36,0x35,0x34,0x34,0x33,0x32,0x31,0x30,0x2f,0x2f, +0x2e,0x2d,0x2c,0x2c,0x2b,0x2a,0x29,0x29,0x28,0x27, +0x26,0x26,0x25,0x24,0x24,0x23,0x23,0x22,0x21,0x21, +0x20,0x20,0x1f,0x1e,0x1e,0x1d,0x1d,0x1c,0x1c,0x1b, +0x1b,0x1a,0x1a,0x19,0x19,0x18,0x18,0x17,0x17,0x16, +0x16,0x15,0x15,0x15,0x14,0x14,0x13,0x13,0x13,0x12, +0x12,0x12,0x11,0x11,0x11,0x10,0x10,0x10,0x0f,0x0f, +0x0f,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c, +0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a, +0x0a,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08, +0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06, +0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05, +0x05,0x05,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03, +0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]= { +{ 0x04d0,0x04f0,0x0580 }, +{ 0x04d0,0x04f0,0x0580 }, +{ 0x0440,0x0460,0x04b0 }, +{ 0x0400,0x0410,0x0450 }, +{ 0x03e0,0x03e0,0x0420 }, +{ 0x03c0,0x03d0,0x03f0 }, +{ 0x03b0,0x03c0,0x03e0 }, +{ 0x03b0,0x03b0,0x03d0 }, +{ 0x03a0,0x03b0,0x03c0 }, +{ 0x03a0,0x03a0,0x03b0 }, +{ 0x03a0,0x03a0,0x03b0 }, +{ 0x03a0,0x03a0,0x03b0 }, +{ 0x03a0,0x03a0,0x03a0 }, +{ 0x0390,0x03a0,0x03a0 }, +{ 0x0390,0x0390,0x03a0 }, +{ 0x0390,0x0390,0x03a0 }, +{ 0x0380,0x0390,0x03a0 }, +{ 0x0380,0x0380,0x03a0 }, +{ 0x0370,0x0380,0x03a0 }, +{ 0x0370,0x0380,0x03a0 }, +{ 0x0360,0x0370,0x0390 }, +{ 0x0360,0x0370,0x0390 }, +{ 0x0350,0x0360,0x0390 }, +{ 0x0350,0x0360,0x0390 }, +{ 0x0340,0x0350,0x0380 }, +{ 0x0340,0x0350,0x0380 }, +{ 0x0330,0x0340,0x0380 }, +{ 0x0320,0x0340,0x0370 }, +{ 0x0310,0x0320,0x0360 }, +{ 0x0300,0x0310,0x0350 }, +{ 0x02f0,0x0300,0x0340 }, +{ 0x02f0,0x02f0,0x0330 }, +{ 0x02f0,0x02f0,0x0320 }, +{ 0x02f0,0x02f0,0x0310 }, +{ 0x0300,0x02f0,0x0300 }, +{ 0x0310,0x0300,0x02f0 }, +{ 0x0340,0x0320,0x02f0 }, +{ 0x0390,0x0350,0x02f0 }, +{ 0x03e0,0x0390,0x0300 }, +{ 0x0420,0x03e0,0x0310 }, +{ 0x0460,0x0420,0x0330 }, +{ 0x0490,0x0450,0x0350 }, +{ 0x04a0,0x04a0,0x03c0 }, +{ 0x0460,0x0490,0x0410 }, +{ 0x0440,0x0460,0x0470 }, +{ 0x0440,0x0440,0x04a0 }, +{ 0x0520,0x0480,0x0460 }, +{ 0x0800,0x0630,0x0440 }, +{ 0x0840,0x0840,0x0450 }, +{ 0x0840,0x0840,0x04e0 }, +}; + +const uint8_t ff_ac3_bap_tab[64]= { + 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, + 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, + 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, + 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, +}; + +const uint8_t ff_ac3_slow_decay_tab[4]={ + 0x0f, 0x11, 0x13, 0x15, +}; + +const uint8_t ff_ac3_fast_decay_tab[4]={ + 0x3f, 0x53, 0x67, 0x7b, +}; + +const uint16_t ff_ac3_slow_gain_tab[4]= { + 0x540, 0x4d8, 0x478, 0x410, +}; + +const uint16_t ff_ac3_db_per_bit_tab[4]= { + 0x000, 0x700, 0x900, 0xb00, +}; + +const int16_t ff_ac3_floor_tab[8]= { + 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800, +}; + +const uint16_t ff_ac3_fast_gain_tab[8]= { + 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400, +}; + +/** + * Default channel map for a dependent substream defined by acmod + */ +const uint16_t ff_eac3_default_chmap[8] = { + AC3_CHMAP_L | AC3_CHMAP_R, // FIXME Ch1+Ch2 + AC3_CHMAP_C, + AC3_CHMAP_L | AC3_CHMAP_R, + AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R, + AC3_CHMAP_L | AC3_CHMAP_R | AC3_CHMAP_C_SUR, + AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R | AC3_CHMAP_C_SUR, + AC3_CHMAP_L | AC3_CHMAP_R | AC3_CHMAP_L_SUR | AC3_CHMAP_R_SUR, + AC3_CHMAP_L | AC3_CHMAP_C | AC3_CHMAP_R | AC3_CHMAP_L_SUR | AC3_CHMAP_R_SUR +}; diff --git a/ffmpeg/libavcodec/ac3tab.h b/ffmpeg/libavcodec/ac3tab.h new file mode 100644 index 0000000..c41a93e --- /dev/null +++ b/ffmpeg/libavcodec/ac3tab.h @@ -0,0 +1,72 @@ +/* + * AC-3 tables + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_AC3TAB_H +#define AVCODEC_AC3TAB_H + +#include "libavutil/common.h" +#include "ac3.h" + +#if CONFIG_HARDCODED_TABLES +# define HCONST const +#else +# define HCONST +#endif + +extern const uint16_t ff_ac3_frame_size_tab[38][3]; +extern const uint8_t ff_ac3_channels_tab[8]; +extern av_export const uint16_t avpriv_ac3_channel_layout_tab[8]; +extern const uint8_t ff_ac3_enc_channel_map[8][2][6]; +extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; +extern const uint16_t ff_ac3_sample_rate_tab[3]; +extern const uint16_t ff_ac3_bitrate_tab[19]; +extern const uint8_t ff_ac3_rematrix_band_tab[5]; +extern const uint8_t ff_eac3_default_cpl_band_struct[18]; +extern const int16_t ff_ac3_window[AC3_WINDOW_SIZE/2]; +extern const uint8_t ff_ac3_log_add_tab[260]; +extern const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]; +extern const uint8_t ff_ac3_bap_tab[64]; +extern const uint8_t ff_ac3_slow_decay_tab[4]; +extern const uint8_t ff_ac3_fast_decay_tab[4]; +extern const uint16_t ff_ac3_slow_gain_tab[4]; +extern const uint16_t ff_ac3_db_per_bit_tab[4]; +extern const int16_t ff_ac3_floor_tab[8]; +extern const uint16_t ff_ac3_fast_gain_tab[8]; +extern const uint16_t ff_eac3_default_chmap[8]; +extern const uint8_t ff_ac3_band_start_tab[AC3_CRITICAL_BANDS+1]; +extern HCONST uint8_t ff_ac3_bin_to_band_tab[253]; + +/** Custom channel map locations bitmask + * Other channels described in documentation: + * Lc/Rc pair, Lrs/Rrs pair, Ts, Lsd/Rsd pair, + * Lw/Rw pair, Lvh/Rvh pair, Cvh, Reserved, LFE2 + */ +enum CustomChannelMapLocation{ + AC3_CHMAP_L= 1<<(15-0), + AC3_CHMAP_C= 1<<(15-1), + AC3_CHMAP_R= 1<<(15-2), + AC3_CHMAP_L_SUR= 1<<(15-3), + AC3_CHMAP_R_SUR = 1<<(15-4), + AC3_CHMAP_C_SUR= 1<<(15-7), + AC3_CHMAP_LFE = 1<<(15-15) +}; + +#endif /* AVCODEC_AC3TAB_H */ diff --git a/ffmpeg/libavcodec/acelp_filters.c b/ffmpeg/libavcodec/acelp_filters.c new file mode 100644 index 0000000..9ab758b --- /dev/null +++ b/ffmpeg/libavcodec/acelp_filters.c @@ -0,0 +1,155 @@ +/* + * various filters for ACELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 "libavutil/avassert.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "acelp_filters.h" + +const int16_t ff_acelp_interp_filter[61] = { /* (0.15) */ + 29443, 28346, 25207, 20449, 14701, 8693, + 3143, -1352, -4402, -5865, -5850, -4673, + -2783, -672, 1211, 2536, 3130, 2991, + 2259, 1170, 0, -1001, -1652, -1868, + -1666, -1147, -464, 218, 756, 1060, + 1099, 904, 550, 135, -245, -514, + -634, -602, -451, -231, 0, 191, + 308, 340, 296, 198, 78, -36, + -120, -163, -165, -132, -79, -19, + 34, 73, 91, 89, 70, 38, + 0, +}; + +void ff_acelp_interpolate(int16_t* out, const int16_t* in, + const int16_t* filter_coeffs, int precision, + int frac_pos, int filter_length, int length) +{ + int n, i; + + av_assert1(frac_pos >= 0 && frac_pos < precision); + + for (n = 0; n < length; n++) { + int idx = 0; + int v = 0x4000; + + for (i = 0; i < filter_length;) { + + /* The reference G.729 and AMR fixed point code performs clipping after + each of the two following accumulations. + Since clipping affects only the synthetic OVERFLOW test without + causing an int type overflow, it was moved outside the loop. */ + + /* R(x):=ac_v[-k+x] + v += R(n-i)*ff_acelp_interp_filter(t+6i) + v += R(n+i+1)*ff_acelp_interp_filter(6-t+6i) */ + + v += in[n + i] * filter_coeffs[idx + frac_pos]; + idx += precision; + i++; + v += in[n - i] * filter_coeffs[idx - frac_pos]; + } + if (av_clip_int16(v >> 15) != (v >> 15)) + av_log(NULL, AV_LOG_WARNING, "overflow that would need cliping in ff_acelp_interpolate()\n"); + out[n] = v >> 15; + } +} + +void ff_acelp_interpolatef(float *out, const float *in, + const float *filter_coeffs, int precision, + int frac_pos, int filter_length, int length) +{ + int n, i; + + for (n = 0; n < length; n++) { + int idx = 0; + float v = 0; + + for (i = 0; i < filter_length;) { + v += in[n + i] * filter_coeffs[idx + frac_pos]; + idx += precision; + i++; + v += in[n - i] * filter_coeffs[idx - frac_pos]; + } + out[n] = v; + } +} + + +void ff_acelp_high_pass_filter(int16_t* out, int hpf_f[2], + const int16_t* in, int length) +{ + int i; + int tmp; + + for (i = 0; i < length; i++) { + tmp = (hpf_f[0]* 15836LL) >> 13; + tmp += (hpf_f[1]* -7667LL) >> 13; + tmp += 7699 * (in[i] - 2*in[i-1] + in[i-2]); + + /* With "+0x800" rounding, clipping is needed + for ALGTHM and SPEECH tests. */ + out[i] = av_clip_int16((tmp + 0x800) >> 12); + + hpf_f[1] = hpf_f[0]; + hpf_f[0] = tmp; + } +} + +void ff_acelp_apply_order_2_transfer_function(float *out, const float *in, + const float zero_coeffs[2], + const float pole_coeffs[2], + float gain, float mem[2], int n) +{ + int i; + float tmp; + + for (i = 0; i < n; i++) { + tmp = gain * in[i] - pole_coeffs[0] * mem[0] - pole_coeffs[1] * mem[1]; + out[i] = tmp + zero_coeffs[0] * mem[0] + zero_coeffs[1] * mem[1]; + + mem[1] = mem[0]; + mem[0] = tmp; + } +} + +void ff_tilt_compensation(float *mem, float tilt, float *samples, int size) +{ + float new_tilt_mem = samples[size - 1]; + int i; + + for (i = size - 1; i > 0; i--) + samples[i] -= tilt * samples[i - 1]; + + samples[0] -= tilt * *mem; + *mem = new_tilt_mem; +} + +void ff_acelp_filter_init(ACELPFContext *c) +{ + c->acelp_interpolatef = ff_acelp_interpolatef; + c->acelp_apply_order_2_transfer_function = ff_acelp_apply_order_2_transfer_function; + + if(HAVE_MIPSFPU) + ff_acelp_filter_init_mips(c); +} diff --git a/ffmpeg/libavcodec/acelp_filters.h b/ffmpeg/libavcodec/acelp_filters.h new file mode 100644 index 0000000..7a3061b --- /dev/null +++ b/ffmpeg/libavcodec/acelp_filters.h @@ -0,0 +1,153 @@ +/* + * various filters for ACELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_ACELP_FILTERS_H +#define AVCODEC_ACELP_FILTERS_H + +#include + +typedef struct ACELPFContext { + /** + * Floating point version of ff_acelp_interpolate() + */ + void (*acelp_interpolatef)(float *out, const float *in, + const float *filter_coeffs, int precision, + int frac_pos, int filter_length, int length); + + /** + * Apply an order 2 rational transfer function in-place. + * + * @param out output buffer for filtered speech samples + * @param in input buffer containing speech data (may be the same as out) + * @param zero_coeffs z^-1 and z^-2 coefficients of the numerator + * @param pole_coeffs z^-1 and z^-2 coefficients of the denominator + * @param gain scale factor for final output + * @param mem intermediate values used by filter (should be 0 initially) + * @param n number of samples (should be a multiple of eight) + */ + void (*acelp_apply_order_2_transfer_function)(float *out, const float *in, + const float zero_coeffs[2], + const float pole_coeffs[2], + float gain, + float mem[2], int n); + +}ACELPFContext; + +/** + * Initialize ACELPFContext. + */ +void ff_acelp_filter_init(ACELPFContext *c); +void ff_acelp_filter_init_mips(ACELPFContext *c); + +/** + * low-pass Finite Impulse Response filter coefficients. + * + * Hamming windowed sinc filter with cutoff freq 3/40 of the sampling freq, + * the coefficients are scaled by 2^15. + * This array only contains the right half of the filter. + * This filter is likely identical to the one used in G.729, though this + * could not be determined from the original comments with certainty. + */ +extern const int16_t ff_acelp_interp_filter[61]; + +/** + * Generic FIR interpolation routine. + * @param[out] out buffer for interpolated data + * @param in input data + * @param filter_coeffs interpolation filter coefficients (0.15) + * @param precision sub sample factor, that is the precision of the position + * @param frac_pos fractional part of position [0..precision-1] + * @param filter_length filter length + * @param length length of output + * + * filter_coeffs contains coefficients of the right half of the symmetric + * interpolation filter. filter_coeffs[0] should the central (unpaired) coefficient. + * See ff_acelp_interp_filter for an example. + * + */ +void ff_acelp_interpolate(int16_t* out, const int16_t* in, + const int16_t* filter_coeffs, int precision, + int frac_pos, int filter_length, int length); + +/** + * Floating point version of ff_acelp_interpolate() + */ +void ff_acelp_interpolatef(float *out, const float *in, + const float *filter_coeffs, int precision, + int frac_pos, int filter_length, int length); + + +/** + * high-pass filtering and upscaling (4.2.5 of G.729). + * @param[out] out output buffer for filtered speech data + * @param[in,out] hpf_f past filtered data from previous (2 items long) + * frames (-0x20000000 <= (14.13) < 0x20000000) + * @param in speech data to process + * @param length input data size + * + * out[i] = 0.93980581 * in[i] - 1.8795834 * in[i-1] + 0.93980581 * in[i-2] + + * 1.9330735 * out[i-1] - 0.93589199 * out[i-2] + * + * The filter has a cut-off frequency of 1/80 of the sampling freq + * + * @note Two items before the top of the in buffer must contain two items from the + * tail of the previous subframe. + * + * @remark It is safe to pass the same array in in and out parameters. + * + * @remark AMR uses mostly the same filter (cut-off frequency 60Hz, same formula, + * but constants differs in 5th sign after comma). Fortunately in + * fixed-point all coefficients are the same as in G.729. Thus this + * routine can be used for the fixed-point AMR decoder, too. + */ +void ff_acelp_high_pass_filter(int16_t* out, int hpf_f[2], + const int16_t* in, int length); + +/** + * Apply an order 2 rational transfer function in-place. + * + * @param out output buffer for filtered speech samples + * @param in input buffer containing speech data (may be the same as out) + * @param zero_coeffs z^-1 and z^-2 coefficients of the numerator + * @param pole_coeffs z^-1 and z^-2 coefficients of the denominator + * @param gain scale factor for final output + * @param mem intermediate values used by filter (should be 0 initially) + * @param n number of samples + */ +void ff_acelp_apply_order_2_transfer_function(float *out, const float *in, + const float zero_coeffs[2], + const float pole_coeffs[2], + float gain, + float mem[2], int n); + +/** + * Apply tilt compensation filter, 1 - tilt * z-1. + * + * @param mem pointer to the filter's state (one single float) + * @param tilt tilt factor + * @param samples array where the filter is applied + * @param size the size of the samples array + */ +void ff_tilt_compensation(float *mem, float tilt, float *samples, int size); + + +#endif /* AVCODEC_ACELP_FILTERS_H */ diff --git a/ffmpeg/libavcodec/acelp_pitch_delay.c b/ffmpeg/libavcodec/acelp_pitch_delay.c new file mode 100644 index 0000000..c005c4b --- /dev/null +++ b/ffmpeg/libavcodec/acelp_pitch_delay.c @@ -0,0 +1,189 @@ +/* + * gain code, gain pitch and pitch delay decoding + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/libm.h" +#include "libavutil/mathematics.h" +#include "avcodec.h" +#include "acelp_pitch_delay.h" +#include "celp_math.h" + +int ff_acelp_decode_8bit_to_1st_delay3(int ac_index) +{ + ac_index += 58; + if(ac_index > 254) + ac_index = 3 * ac_index - 510; + return ac_index; +} + +int ff_acelp_decode_4bit_to_2nd_delay3( + int ac_index, + int pitch_delay_min) +{ + if(ac_index < 4) + return 3 * (ac_index + pitch_delay_min); + else if(ac_index < 12) + return 3 * pitch_delay_min + ac_index + 6; + else + return 3 * (ac_index + pitch_delay_min) - 18; +} + +int ff_acelp_decode_5_6_bit_to_2nd_delay3( + int ac_index, + int pitch_delay_min) +{ + return 3 * pitch_delay_min + ac_index - 2; +} + +int ff_acelp_decode_9bit_to_1st_delay6(int ac_index) +{ + if(ac_index < 463) + return ac_index + 105; + else + return 6 * (ac_index - 368); +} +int ff_acelp_decode_6bit_to_2nd_delay6( + int ac_index, + int pitch_delay_min) +{ + return 6 * pitch_delay_min + ac_index - 3; +} + +void ff_acelp_update_past_gain( + int16_t* quant_energy, + int gain_corr_factor, + int log2_ma_pred_order, + int erasure) +{ + int i; + int avg_gain=quant_energy[(1 << log2_ma_pred_order) - 1]; // (5.10) + + for(i=(1 << log2_ma_pred_order) - 1; i>0; i--) + { + avg_gain += quant_energy[i-1]; + quant_energy[i] = quant_energy[i-1]; + } + + if(erasure) + quant_energy[0] = FFMAX(avg_gain >> log2_ma_pred_order, -10240) - 4096; // -10 and -4 in (5.10) + else + quant_energy[0] = (6165 * ((ff_log2_q15(gain_corr_factor) >> 2) - (13 << 13))) >> 13; +} + +int16_t ff_acelp_decode_gain_code( + DSPContext *dsp, + int gain_corr_factor, + const int16_t* fc_v, + int mr_energy, + const int16_t* quant_energy, + const int16_t* ma_prediction_coeff, + int subframe_size, + int ma_pred_order) +{ + int i; + + mr_energy <<= 10; + + for(i=0; iscalarproduct_int16(fc_v, fc_v, subframe_size, 0))) >> 3) & ~0x3ff); + + mr_energy = (5439 * (mr_energy >> 15)) >> 8; // (0.15) = (0.15) * (7.23) + + return bidir_sal( + ((ff_exp2(mr_energy & 0x7fff) + 16) >> 5) * (gain_corr_factor >> 1), + (mr_energy >> 15) - 25 + ); +#else + mr_energy = gain_corr_factor * exp(M_LN10 / (20 << 23) * mr_energy) / + sqrt(dsp->scalarproduct_int16(fc_v, fc_v, subframe_size)); + return mr_energy >> 12; +#endif +} + +float ff_amr_set_fixed_gain(float fixed_gain_factor, float fixed_mean_energy, + float *prediction_error, float energy_mean, + const float *pred_table) +{ + // Equations 66-69: + // ^g_c = ^gamma_gc * 100.05 (predicted dB + mean dB - dB of fixed vector) + // Note 10^(0.05 * -10log(average x2)) = 1/sqrt((average x2)). + float val = fixed_gain_factor * + exp2f(M_LOG2_10 * 0.05 * + (avpriv_scalarproduct_float_c(pred_table, prediction_error, 4) + + energy_mean)) / + sqrtf(fixed_mean_energy); + + // update quantified prediction error energy history + memmove(&prediction_error[0], &prediction_error[1], + 3 * sizeof(prediction_error[0])); + prediction_error[3] = 20.0 * log10f(fixed_gain_factor); + + return val; +} + +void ff_decode_pitch_lag(int *lag_int, int *lag_frac, int pitch_index, + const int prev_lag_int, const int subframe, + int third_as_first, int resolution) +{ + /* Note n * 10923 >> 15 is floor(x/3) for 0 <= n <= 32767 */ + if (subframe == 0 || (subframe == 2 && third_as_first)) { + + if (pitch_index < 197) + pitch_index += 59; + else + pitch_index = 3 * pitch_index - 335; + + } else { + if (resolution == 4) { + int search_range_min = av_clip(prev_lag_int - 5, PITCH_DELAY_MIN, + PITCH_DELAY_MAX - 9); + + // decoding with 4-bit resolution + if (pitch_index < 4) { + // integer only precision for [search_range_min, search_range_min+3] + pitch_index = 3 * (pitch_index + search_range_min) + 1; + } else if (pitch_index < 12) { + // 1/3 fractional precision for [search_range_min+3 1/3, search_range_min+5 2/3] + pitch_index += 3 * search_range_min + 7; + } else { + // integer only precision for [search_range_min+6, search_range_min+9] + pitch_index = 3 * (pitch_index + search_range_min - 6) + 1; + } + } else { + // decoding with 5 or 6 bit resolution, 1/3 fractional precision + pitch_index--; + + if (resolution == 5) { + pitch_index += 3 * av_clip(prev_lag_int - 10, PITCH_DELAY_MIN, + PITCH_DELAY_MAX - 19); + } else + pitch_index += 3 * av_clip(prev_lag_int - 5, PITCH_DELAY_MIN, + PITCH_DELAY_MAX - 9); + } + } + *lag_int = pitch_index * 10923 >> 15; + *lag_frac = pitch_index - 3 * *lag_int - 1; +} diff --git a/ffmpeg/libavcodec/acelp_pitch_delay.h b/ffmpeg/libavcodec/acelp_pitch_delay.h new file mode 100644 index 0000000..72977f1 --- /dev/null +++ b/ffmpeg/libavcodec/acelp_pitch_delay.h @@ -0,0 +1,252 @@ +/* + * gain code, gain pitch and pitch delay decoding + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_ACELP_PITCH_DELAY_H +#define AVCODEC_ACELP_PITCH_DELAY_H + +#include +#include "dsputil.h" + +#define PITCH_DELAY_MIN 20 +#define PITCH_DELAY_MAX 143 + +/** + * @brief Decode pitch delay of the first subframe encoded by 8 bits with 1/3 + * resolution. + * @param ac_index adaptive codebook index (8 bits) + * + * @return pitch delay in 1/3 units + * + * Pitch delay is coded: + * with 1/3 resolution, 19 < pitch_delay < 85 + * integers only, 85 <= pitch_delay <= 143 + */ +int ff_acelp_decode_8bit_to_1st_delay3(int ac_index); + +/** + * @brief Decode pitch delay of the second subframe encoded by 5 or 6 bits + * with 1/3 precision. + * @param ac_index adaptive codebook index (5 or 6 bits) + * @param pitch_delay_min lower bound (integer) of pitch delay interval + * for second subframe + * + * @return pitch delay in 1/3 units + * + * Pitch delay is coded: + * with 1/3 resolution, -6 < pitch_delay - int(prev_pitch_delay) < 5 + * + * @remark The routine is used in G.729 @@8k, AMR @@10.2k, AMR @@7.95k, + * AMR @@7.4k for the second subframe. + */ +int ff_acelp_decode_5_6_bit_to_2nd_delay3( + int ac_index, + int pitch_delay_min); + +/** + * @brief Decode pitch delay with 1/3 precision. + * @param ac_index adaptive codebook index (4 bits) + * @param pitch_delay_min lower bound (integer) of pitch delay interval for + * second subframe + * + * @return pitch delay in 1/3 units + * + * Pitch delay is coded: + * integers only, -6 < pitch_delay - int(prev_pitch_delay) <= -2 + * with 1/3 resolution, -2 < pitch_delay - int(prev_pitch_delay) < 1 + * integers only, 1 <= pitch_delay - int(prev_pitch_delay) < 5 + * + * @remark The routine is used in G.729 @@6.4k, AMR @@6.7k, AMR @@5.9k, + * AMR @@5.15k, AMR @@4.75k for the second subframe. + */ +int ff_acelp_decode_4bit_to_2nd_delay3( + int ac_index, + int pitch_delay_min); + +/** + * @brief Decode pitch delay of the first subframe encoded by 9 bits + * with 1/6 precision. + * @param ac_index adaptive codebook index (9 bits) + * + * @return pitch delay in 1/6 units + * + * Pitch delay is coded: + * with 1/6 resolution, 17 < pitch_delay < 95 + * integers only, 95 <= pitch_delay <= 143 + * + * @remark The routine is used in AMR @@12.2k for the first and third subframes. + */ +int ff_acelp_decode_9bit_to_1st_delay6(int ac_index); + +/** + * @brief Decode pitch delay of the second subframe encoded by 6 bits + * with 1/6 precision. + * @param ac_index adaptive codebook index (6 bits) + * @param pitch_delay_min lower bound (integer) of pitch delay interval for + * second subframe + * + * @return pitch delay in 1/6 units + * + * Pitch delay is coded: + * with 1/6 resolution, -6 < pitch_delay - int(prev_pitch_delay) < 5 + * + * @remark The routine is used in AMR @@12.2k for the second and fourth subframes. + */ +int ff_acelp_decode_6bit_to_2nd_delay6( + int ac_index, + int pitch_delay_min); + +/** + * @brief Update past quantized energies + * @param[in,out] quant_energy past quantized energies (5.10) + * @param gain_corr_factor gain correction factor + * @param log2_ma_pred_order log2() of MA prediction order + * @param erasure frame erasure flag + * + * If frame erasure flag is not equal to zero, memory is updated with + * averaged energy, attenuated by 4dB: + * max(avg(quant_energy[i])-4, -14), i=0,ma_pred_order + * + * In normal mode memory is updated with + * Er - Ep = 20 * log10(gain_corr_factor) + * + * @remark The routine is used in G.729 and AMR (all modes). + */ +void ff_acelp_update_past_gain( + int16_t* quant_energy, + int gain_corr_factor, + int log2_ma_pred_order, + int erasure); + +/** + * @brief Decode the adaptive codebook gain and add + * correction (4.1.5 and 3.9.1 of G.729). + * @param dsp initialized dsputil context + * @param gain_corr_factor gain correction factor (2.13) + * @param fc_v fixed-codebook vector (2.13) + * @param mr_energy mean innovation energy and fixed-point correction (7.13) + * @param[in,out] quant_energy past quantized energies (5.10) + * @param subframe_size length of subframe + * + * @return quantized fixed-codebook gain (14.1) + * + * The routine implements equations 69, 66 and 71 of the G.729 specification (3.9.1) + * + * Em - mean innovation energy (dB, constant, depends on decoding algorithm) + * Ep - mean-removed predicted energy (dB) + * Er - mean-removed innovation energy (dB) + * Ei - mean energy of the fixed-codebook contribution (dB) + * N - subframe_size + * M - MA (Moving Average) prediction order + * gc - fixed-codebook gain + * gc_p - predicted fixed-codebook gain + * + * Fixed codebook gain is computed using predicted gain gc_p and + * correction factor gain_corr_factor as shown below: + * + * gc = gc_p * gain_corr_factor + * + * The predicted fixed codebook gain gc_p is found by predicting + * the energy of the fixed-codebook contribution from the energy + * of previous fixed-codebook contributions. + * + * mean = 1/N * sum(i,0,N){ fc_v[i] * fc_v[i] } + * + * Ei = 10log(mean) + * + * Er = 10log(1/N * gc^2 * mean) - Em = 20log(gc) + Ei - Em + * + * Replacing Er with Ep and gc with gc_p we will receive: + * + * Ep = 10log(1/N * gc_p^2 * mean) - Em = 20log(gc_p) + Ei - Em + * + * and from above: + * + * gc_p = 10^((Ep - Ei + Em) / 20) + * + * Ep is predicted using past energies and prediction coefficients: + * + * Ep = sum(i,0,M){ ma_prediction_coeff[i] * quant_energy[i] } + * + * gc_p in fixed-point arithmetic is calculated as following: + * + * mean = 1/N * sum(i,0,N){ (fc_v[i] / 2^13) * (fc_v[i] / 2^13) } = + * = 1/N * sum(i,0,N) { fc_v[i] * fc_v[i] } / 2^26 + * + * Ei = 10log(mean) = -10log(N) - 10log(2^26) + + * + 10log(sum(i,0,N) { fc_v[i] * fc_v[i] }) + * + * Ep - Ei + Em = Ep + Em + 10log(N) + 10log(2^26) - + * - 10log(sum(i,0,N) { fc_v[i] * fc_v[i] }) = + * = Ep + mr_energy - 10log(sum(i,0,N) { fc_v[i] * fc_v[i] }) + * + * gc_p = 10 ^ ((Ep - Ei + Em) / 20) = + * = 2 ^ (3.3219 * (Ep - Ei + Em) / 20) = 2 ^ (0.166 * (Ep - Ei + Em)) + * + * where + * + * mr_energy = Em + 10log(N) + 10log(2^26) + * + * @remark The routine is used in G.729 and AMR (all modes). + */ +int16_t ff_acelp_decode_gain_code( + DSPContext *dsp, + int gain_corr_factor, + const int16_t* fc_v, + int mr_energy, + const int16_t* quant_energy, + const int16_t* ma_prediction_coeff, + int subframe_size, + int max_pred_order); + +/** + * Calculate fixed gain (part of section 6.1.3 of AMR spec) + * + * @param fixed_gain_factor gain correction factor + * @param fixed_mean_energy mean decoded algebraic codebook vector energy + * @param prediction_error vector of the quantified predictor errors of + * the four previous subframes. It is updated by this function. + * @param energy_mean desired mean innovation energy + * @param pred_table table of four moving average coefficients + */ +float ff_amr_set_fixed_gain(float fixed_gain_factor, float fixed_mean_energy, + float *prediction_error, float energy_mean, + const float *pred_table); + + +/** + * Decode the adaptive codebook index to the integer and fractional parts + * of the pitch lag for one subframe at 1/3 fractional precision. + * + * The choice of pitch lag is described in 3GPP TS 26.090 section 5.6.1. + * + * @param lag_int integer part of pitch lag of the current subframe + * @param lag_frac fractional part of pitch lag of the current subframe + * @param pitch_index parsed adaptive codebook (pitch) index + * @param prev_lag_int integer part of pitch lag for the previous subframe + * @param subframe current subframe number + * @param third_as_first treat the third frame the same way as the first + */ +void ff_decode_pitch_lag(int *lag_int, int *lag_frac, int pitch_index, + const int prev_lag_int, const int subframe, + int third_as_first, int resolution); + +#endif /* AVCODEC_ACELP_PITCH_DELAY_H */ diff --git a/ffmpeg/libavcodec/acelp_vectors.c b/ffmpeg/libavcodec/acelp_vectors.c new file mode 100644 index 0000000..c9d6f87 --- /dev/null +++ b/ffmpeg/libavcodec/acelp_vectors.c @@ -0,0 +1,272 @@ +/* + * adaptive and fixed codebook vector operations for ACELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "acelp_vectors.h" + +const uint8_t ff_fc_2pulses_9bits_track1[16] = +{ + 1, 3, + 6, 8, + 11, 13, + 16, 18, + 21, 23, + 26, 28, + 31, 33, + 36, 38 +}; +const uint8_t ff_fc_2pulses_9bits_track1_gray[16] = +{ + 1, 3, + 8, 6, + 18, 16, + 11, 13, + 38, 36, + 31, 33, + 21, 23, + 28, 26, +}; + +const uint8_t ff_fc_2pulses_9bits_track2_gray[32] = +{ + 0, 2, + 5, 4, + 12, 10, + 7, 9, + 25, 24, + 20, 22, + 14, 15, + 19, 17, + 36, 31, + 21, 26, + 1, 6, + 16, 11, + 27, 29, + 32, 30, + 39, 37, + 34, 35, +}; + +const uint8_t ff_fc_4pulses_8bits_tracks_13[16] = +{ + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, +}; + +const uint8_t ff_fc_4pulses_8bits_track_4[32] = +{ + 3, 4, + 8, 9, + 13, 14, + 18, 19, + 23, 24, + 28, 29, + 33, 34, + 38, 39, + 43, 44, + 48, 49, + 53, 54, + 58, 59, + 63, 64, + 68, 69, + 73, 74, + 78, 79, +}; + +const float ff_pow_0_7[10] = { + 0.700000, 0.490000, 0.343000, 0.240100, 0.168070, + 0.117649, 0.082354, 0.057648, 0.040354, 0.028248 +}; + +const float ff_pow_0_75[10] = { + 0.750000, 0.562500, 0.421875, 0.316406, 0.237305, + 0.177979, 0.133484, 0.100113, 0.075085, 0.056314 +}; + +const float ff_pow_0_55[10] = { + 0.550000, 0.302500, 0.166375, 0.091506, 0.050328, + 0.027681, 0.015224, 0.008373, 0.004605, 0.002533 +}; + +const float ff_b60_sinc[61] = { + 0.898529 , 0.865051 , 0.769257 , 0.624054 , 0.448639 , 0.265289 , + 0.0959167 , -0.0412598 , -0.134338 , -0.178986 , -0.178528 , -0.142609 , +-0.0849304 , -0.0205078 , 0.0369568 , 0.0773926 , 0.0955200 , 0.0912781 , + 0.0689392 , 0.0357056 , 0. , -0.0305481 , -0.0504150 , -0.0570068 , +-0.0508423 , -0.0350037 , -0.0141602 , 0.00665283, 0.0230713 , 0.0323486 , + 0.0335388 , 0.0275879 , 0.0167847 , 0.00411987, -0.00747681, -0.0156860 , +-0.0193481 , -0.0183716 , -0.0137634 , -0.00704956, 0. , 0.00582886 , + 0.00939941, 0.0103760 , 0.00903320, 0.00604248, 0.00238037, -0.00109863 , +-0.00366211, -0.00497437, -0.00503540, -0.00402832, -0.00241089, -0.000579834, + 0.00103760, 0.00222778, 0.00277710, 0.00271606, 0.00213623, 0.00115967 , + 0. +}; + +void ff_acelp_fc_pulse_per_track( + int16_t* fc_v, + const uint8_t *tab1, + const uint8_t *tab2, + int pulse_indexes, + int pulse_signs, + int pulse_count, + int bits) +{ + int mask = (1 << bits) - 1; + int i; + + for(i=0; i>= bits; + pulse_signs >>= 1; + } + + fc_v[tab2[pulse_indexes]] += (pulse_signs & 1) ? 8191 : -8192; +} + +void ff_decode_10_pulses_35bits(const int16_t *fixed_index, + AMRFixed *fixed_sparse, + const uint8_t *gray_decode, + int half_pulse_count, int bits) +{ + int i; + int mask = (1 << bits) - 1; + + fixed_sparse->no_repeat_mask = 0; + fixed_sparse->n = 2 * half_pulse_count; + for (i = 0; i < half_pulse_count; i++) { + const int pos1 = gray_decode[fixed_index[2*i+1] & mask] + i; + const int pos2 = gray_decode[fixed_index[2*i ] & mask] + i; + const float sign = (fixed_index[2*i+1] & (1 << bits)) ? -1.0 : 1.0; + fixed_sparse->x[2*i+1] = pos1; + fixed_sparse->x[2*i ] = pos2; + fixed_sparse->y[2*i+1] = sign; + fixed_sparse->y[2*i ] = pos2 < pos1 ? -sign : sign; + } +} + +void ff_acelp_weighted_vector_sum( + int16_t* out, + const int16_t *in_a, + const int16_t *in_b, + int16_t weight_coeff_a, + int16_t weight_coeff_b, + int16_t rounder, + int shift, + int length) +{ + int i; + + // Clipping required here; breaks OVERFLOW test. + for(i=0; i> shift); +} + +void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b, + float weight_coeff_a, float weight_coeff_b, int length) +{ + int i; + + for(i=0; in; i++) { + int x = in->x[i], repeats = !((in->no_repeat_mask >> i) & 1); + float y = in->y[i] * scale; + + if (in->pitch_lag > 0) + do { + out[x] += y; + y *= in->pitch_fac; + x += in->pitch_lag; + } while (x < size && repeats); + } +} + +void ff_clear_fixed_vector(float *out, const AMRFixed *in, int size) +{ + int i; + + for (i=0; i < in->n; i++) { + int x = in->x[i], repeats = !((in->no_repeat_mask >> i) & 1); + + if (in->pitch_lag > 0) + do { + out[x] = 0.0; + x += in->pitch_lag; + } while (x < size && repeats); + } +} + +void ff_acelp_vectors_init(ACELPVContext *c) +{ + c->weighted_vector_sumf = ff_weighted_vector_sumf; + + if(HAVE_MIPSFPU) + ff_acelp_vectors_init_mips(c); +} diff --git a/ffmpeg/libavcodec/acelp_vectors.h b/ffmpeg/libavcodec/acelp_vectors.h new file mode 100644 index 0000000..fae834d --- /dev/null +++ b/ffmpeg/libavcodec/acelp_vectors.h @@ -0,0 +1,288 @@ +/* + * adaptive and fixed codebook vector operations for ACELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_ACELP_VECTORS_H +#define AVCODEC_ACELP_VECTORS_H + +#include + +typedef struct ACELPVContext { + /** + * float implementation of weighted sum of two vectors. + * @param[out] out result of addition + * @param in_a first vector + * @param in_b second vector + * @param weight_coeff_a first vector weight coefficient + * @param weight_coeff_a second vector weight coefficient + * @param length vectors length (should be a multiple of two) + * + * @note It is safe to pass the same buffer for out and in_a or in_b. + */ + void (*weighted_vector_sumf)(float *out, const float *in_a, const float *in_b, + float weight_coeff_a, float weight_coeff_b, + int length); + +}ACELPVContext; + +/** + * Initialize ACELPVContext. + */ +void ff_acelp_vectors_init(ACELPVContext *c); +void ff_acelp_vectors_init_mips(ACELPVContext *c); + +/** Sparse representation for the algebraic codebook (fixed) vector */ +typedef struct AMRFixed { + int n; + int x[10]; + float y[10]; + int no_repeat_mask; + int pitch_lag; + float pitch_fac; +} AMRFixed; + +/** + * Track|Pulse| Positions + * ------------------------------------------------------------------------- + * 1 | 0 | 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75 + * ------------------------------------------------------------------------- + * 2 | 1 | 1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76 + * ------------------------------------------------------------------------- + * 3 | 2 | 2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77 + * ------------------------------------------------------------------------- + * + * Table contains only first the pulse indexes. + * + * Used in G.729 @@8k, G.729 @@4.4k, AMR @@7.95k, AMR @@7.40k + */ +extern const uint8_t ff_fc_4pulses_8bits_tracks_13[16]; + +/** + * Track|Pulse| Positions + * ------------------------------------------------------------------------- + * 4 | 3 | 3, 8, 13, 18, 23, 28, 33, 38, 43, 48, 53, 58, 63, 68, 73, 78 + * | | 4, 9, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64, 69, 74, 79 + * ------------------------------------------------------------------------- + * + * @remark Track in the table should be read top-to-bottom, left-to-right. + * + * Used in G.729 @@8k, G.729 @@4.4k, AMR @@7.95k, AMR @@7.40k + */ +extern const uint8_t ff_fc_4pulses_8bits_track_4[32]; + +/** + * Track|Pulse| Positions + * ----------------------------------------- + * 1 | 0 | 1, 6, 11, 16, 21, 26, 31, 36 + * | | 3, 8, 13, 18, 23, 28, 33, 38 + * ----------------------------------------- + * + * @remark Track in the table should be read top-to-bottom, left-to-right. + * + * @note (EE) Reference G.729D code also uses gray decoding for each + * pulse index before looking up the value in the table. + * + * Used in G.729 @@6.4k (with gray coding), AMR @@5.9k (without gray coding) + */ +extern const uint8_t ff_fc_2pulses_9bits_track1[16]; +extern const uint8_t ff_fc_2pulses_9bits_track1_gray[16]; + +/** + * Track|Pulse| Positions + * ----------------------------------------- + * 2 | 1 | 0, 7, 14, 20, 27, 34, 1, 21 + * | | 2, 9, 15, 22, 29, 35, 6, 26 + * | | 4,10, 17, 24, 30, 37, 11, 31 + * | | 5,12, 19, 25, 32, 39, 16, 36 + * ----------------------------------------- + * + * @remark Track in the table should be read top-to-bottom, left-to-right. + * + * @note (EE.1) This table (from the reference code) does not comply with + * the specification. + * The specification contains the following table: + * + * Track|Pulse| Positions + * ----------------------------------------- + * 2 | 1 | 0, 5, 10, 15, 20, 25, 30, 35 + * | | 1, 6, 11, 16, 21, 26, 31, 36 + * | | 2, 7, 12, 17, 22, 27, 32, 37 + * | | 4, 9, 14, 19, 24, 29, 34, 39 + * + * ----------------------------------------- + * + * @note (EE.2) Reference G.729D code also uses gray decoding for each + * pulse index before looking up the value in the table. + * + * Used in G.729 @@6.4k (with gray coding) + */ +extern const uint8_t ff_fc_2pulses_9bits_track2_gray[32]; + +/** + * b60 hamming windowed sinc function coefficients + */ +extern const float ff_b60_sinc[61]; + +/** + * Table of pow(0.7,n) + */ +extern const float ff_pow_0_7[10]; + +/** + * Table of pow(0.75,n) + */ +extern const float ff_pow_0_75[10]; + +/** + * Table of pow(0.55,n) + */ +extern const float ff_pow_0_55[10]; + +/** + * Decode fixed-codebook vector (3.8 and D.5.8 of G.729, 5.7.1 of AMR). + * @param[out] fc_v decoded fixed codebook vector (2.13) + * @param tab1 table used for first pulse_count pulses + * @param tab2 table used for last pulse + * @param pulse_indexes fixed codebook indexes + * @param pulse_signs signs of the excitation pulses (0 bit value + * means negative sign) + * @param bits number of bits per one pulse index + * @param pulse_count number of pulses decoded using first table + * @param bits length of one pulse index in bits + * + * Used in G.729 @@8k, G.729 @@4.4k, G.729 @@6.4k, AMR @@7.95k, AMR @@7.40k + */ +void ff_acelp_fc_pulse_per_track(int16_t* fc_v, + const uint8_t *tab1, + const uint8_t *tab2, + int pulse_indexes, + int pulse_signs, + int pulse_count, + int bits); + +/** + * Decode the algebraic codebook index to pulse positions and signs and + * construct the algebraic codebook vector for MODE_12k2. + * + * @note: The positions and signs are explicitly coded in MODE_12k2. + * + * @param fixed_index positions of the ten pulses + * @param fixed_sparse pointer to the algebraic codebook vector + * @param gray_decode gray decoding table + * @param half_pulse_count number of couples of pulses + * @param bits length of one pulse index in bits + */ +void ff_decode_10_pulses_35bits(const int16_t *fixed_index, + AMRFixed *fixed_sparse, + const uint8_t *gray_decode, + int half_pulse_count, int bits); + + +/** + * weighted sum of two vectors with rounding. + * @param[out] out result of addition + * @param in_a first vector + * @param in_b second vector + * @param weight_coeff_a first vector weight coefficient + * @param weight_coeff_a second vector weight coefficient + * @param rounder this value will be added to the sum of the two vectors + * @param shift result will be shifted to right by this value + * @param length vectors length + * + * @note It is safe to pass the same buffer for out and in_a or in_b. + * + * out[i] = (in_a[i]*weight_a + in_b[i]*weight_b + rounder) >> shift + */ +void ff_acelp_weighted_vector_sum(int16_t* out, + const int16_t *in_a, + const int16_t *in_b, + int16_t weight_coeff_a, + int16_t weight_coeff_b, + int16_t rounder, + int shift, + int length); + +/** + * float implementation of weighted sum of two vectors. + * @param[out] out result of addition + * @param in_a first vector + * @param in_b second vector + * @param weight_coeff_a first vector weight coefficient + * @param weight_coeff_a second vector weight coefficient + * @param length vectors length + * + * @note It is safe to pass the same buffer for out and in_a or in_b. + */ +void ff_weighted_vector_sumf(float *out, const float *in_a, const float *in_b, + float weight_coeff_a, float weight_coeff_b, + int length); + +/** + * Adaptive gain control (as used in AMR postfiltering) + * + * @param out output buffer for filtered speech data + * @param in the input speech buffer (may be the same as out) + * @param speech_energ input energy + * @param size the input buffer size + * @param alpha exponential filter factor + * @param gain_mem a pointer to the filter memory (single float of size) + */ +void ff_adaptive_gain_control(float *out, const float *in, float speech_energ, + int size, float alpha, float *gain_mem); + +/** + * Set the sum of squares of a signal by scaling + * + * @param out output samples + * @param in input samples + * @param sum_of_squares new sum of squares + * @param n number of samples + * + * @note If the input is zero (or its energy underflows), the output is zero. + * This is the behavior of AGC in the AMR reference decoder. The QCELP + * reference decoder seems to have undefined behavior. + * + * TIA/EIA/IS-733 2.4.8.3-2/3/4/5, 2.4.8.6 + * 3GPP TS 26.090 6.1 (6) + */ +void ff_scale_vector_to_given_sum_of_squares(float *out, const float *in, + float sum_of_squares, const int n); + +/** + * Add fixed vector to an array from a sparse representation + * + * @param out fixed vector with pitch sharpening + * @param in sparse fixed vector + * @param scale number to multiply the fixed vector by + * @param size the output vector size + */ +void ff_set_fixed_vector(float *out, const AMRFixed *in, float scale, int size); + +/** + * Clear array values set by set_fixed_vector + * + * @param out fixed vector to be cleared + * @param in sparse fixed vector + * @param size the output vector size + */ +void ff_clear_fixed_vector(float *out, const AMRFixed *in, int size); + +#endif /* AVCODEC_ACELP_VECTORS_H */ diff --git a/ffmpeg/libavcodec/adpcm.c b/ffmpeg/libavcodec/adpcm.c new file mode 100644 index 0000000..3f8cfbc --- /dev/null +++ b/ffmpeg/libavcodec/adpcm.c @@ -0,0 +1,1432 @@ +/* + * Copyright (c) 2001-2003 The ffmpeg Project + * + * 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 "avcodec.h" +#include "get_bits.h" +#include "put_bits.h" +#include "bytestream.h" +#include "adpcm.h" +#include "adpcm_data.h" +#include "internal.h" + +/** + * @file + * ADPCM decoders + * First version by Francois Revol (revol@free.fr) + * Fringe ADPCM codecs (e.g., DK3, DK4, Westwood) + * by Mike Melanson (melanson@pcisys.net) + * CD-ROM XA ADPCM codec by BERO + * EA ADPCM decoder by Robin Kay (komadori@myrealbox.com) + * EA ADPCM R1/R2/R3 decoder by Peter Ross (pross@xvid.org) + * EA IMA EACS decoder by Peter Ross (pross@xvid.org) + * EA IMA SEAD decoder by Peter Ross (pross@xvid.org) + * EA ADPCM XAS decoder by Peter Ross (pross@xvid.org) + * MAXIS EA ADPCM decoder by Robert Marston (rmarston@gmail.com) + * THP ADPCM decoder by Marco Gerards (mgerards@xs4all.nl) + * + * Features and limitations: + * + * Reference documents: + * http://wiki.multimedia.cx/index.php?title=Category:ADPCM_Audio_Codecs + * http://www.pcisys.net/~melanson/codecs/simpleaudio.html [dead] + * http://www.geocities.com/SiliconValley/8682/aud3.txt [dead] + * http://openquicktime.sourceforge.net/ + * XAnim sources (xa_codec.c) http://xanim.polter.net/ + * http://www.cs.ucla.edu/~leec/mediabench/applications.html [dead] + * SoX source code http://sox.sourceforge.net/ + * + * CD-ROM XA: + * http://ku-www.ss.titech.ac.jp/~yatsushi/xaadpcm.html [dead] + * vagpack & depack http://homepages.compuserve.de/bITmASTER32/psx-index.html [dead] + * readstr http://www.geocities.co.jp/Playtown/2004/ + */ + +/* These are for CD-ROM XA ADPCM */ +static const int xa_adpcm_table[5][2] = { + { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } +}; + +static const int ea_adpcm_table[] = { + 0, 240, 460, 392, + 0, 0, -208, -220, + 0, 1, 3, 4, + 7, 8, 10, 11, + 0, -1, -3, -4 +}; + +// padded to zero where table size is less then 16 +static const int swf_index_tables[4][16] = { + /*2*/ { -1, 2 }, + /*3*/ { -1, -1, 2, 4 }, + /*4*/ { -1, -1, -1, -1, 2, 4, 6, 8 }, + /*5*/ { -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16 } +}; + +/* end of tables */ + +typedef struct ADPCMDecodeContext { + ADPCMChannelStatus status[6]; + int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */ +} ADPCMDecodeContext; + +static av_cold int adpcm_decode_init(AVCodecContext * avctx) +{ + ADPCMDecodeContext *c = avctx->priv_data; + unsigned int min_channels = 1; + unsigned int max_channels = 2; + + switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_EA: + min_channels = 2; + break; + case AV_CODEC_ID_ADPCM_AFC: + case AV_CODEC_ID_ADPCM_EA_R1: + case AV_CODEC_ID_ADPCM_EA_R2: + case AV_CODEC_ID_ADPCM_EA_R3: + case AV_CODEC_ID_ADPCM_EA_XAS: + case AV_CODEC_ID_ADPCM_THP: + max_channels = 6; + break; + } + if (avctx->channels < min_channels || avctx->channels > max_channels) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); + } + + switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_CT: + c->status[0].step = c->status[1].step = 511; + break; + case AV_CODEC_ID_ADPCM_IMA_WAV: + if (avctx->bits_per_coded_sample != 4) { + av_log(avctx, AV_LOG_ERROR, "Only 4-bit ADPCM IMA WAV files are supported\n"); + return -1; + } + break; + case AV_CODEC_ID_ADPCM_IMA_APC: + if (avctx->extradata && avctx->extradata_size >= 8) { + c->status[0].predictor = AV_RL32(avctx->extradata); + c->status[1].predictor = AV_RL32(avctx->extradata + 4); + } + break; + case AV_CODEC_ID_ADPCM_IMA_WS: + if (avctx->extradata && avctx->extradata_size >= 2) + c->vqa_version = AV_RL16(avctx->extradata); + break; + default: + break; + } + + switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_IMA_QT: + case AV_CODEC_ID_ADPCM_IMA_WAV: + case AV_CODEC_ID_ADPCM_4XM: + case AV_CODEC_ID_ADPCM_XA: + case AV_CODEC_ID_ADPCM_EA_R1: + case AV_CODEC_ID_ADPCM_EA_R2: + case AV_CODEC_ID_ADPCM_EA_R3: + case AV_CODEC_ID_ADPCM_EA_XAS: + case AV_CODEC_ID_ADPCM_THP: + case AV_CODEC_ID_ADPCM_AFC: + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + break; + case AV_CODEC_ID_ADPCM_IMA_WS: + avctx->sample_fmt = c->vqa_version == 3 ? AV_SAMPLE_FMT_S16P : + AV_SAMPLE_FMT_S16; + break; + default: + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + } + + return 0; +} + +static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble, int shift) +{ + int step_index; + int predictor; + int sign, delta, diff, step; + + step = ff_adpcm_step_table[c->step_index]; + step_index = c->step_index + ff_adpcm_index_table[(unsigned)nibble]; + step_index = av_clip(step_index, 0, 88); + + sign = nibble & 8; + delta = nibble & 7; + /* perform direct multiplication instead of series of jumps proposed by + * the reference ADPCM implementation since modern CPUs can do the mults + * quickly enough */ + diff = ((2 * delta + 1) * step) >> shift; + predictor = c->predictor; + if (sign) predictor -= diff; + else predictor += diff; + + c->predictor = av_clip_int16(predictor); + c->step_index = step_index; + + return (short)c->predictor; +} + +static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble, int shift) +{ + int step_index; + int predictor; + int diff, step; + + step = ff_adpcm_step_table[c->step_index]; + step_index = c->step_index + ff_adpcm_index_table[nibble]; + step_index = av_clip(step_index, 0, 88); + + diff = step >> 3; + if (nibble & 4) diff += step; + if (nibble & 2) diff += step >> 1; + if (nibble & 1) diff += step >> 2; + + if (nibble & 8) + predictor = c->predictor - diff; + else + predictor = c->predictor + diff; + + c->predictor = av_clip_int16(predictor); + c->step_index = step_index; + + return c->predictor; +} + +static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble) +{ + int predictor; + + predictor = (((c->sample1) * (c->coeff1)) + ((c->sample2) * (c->coeff2))) / 64; + predictor += ((nibble & 0x08)?(nibble - 0x10):(nibble)) * c->idelta; + + c->sample2 = c->sample1; + c->sample1 = av_clip_int16(predictor); + c->idelta = (ff_adpcm_AdaptationTable[(int)nibble] * c->idelta) >> 8; + if (c->idelta < 16) c->idelta = 16; + + return c->sample1; +} + +static inline short adpcm_ima_oki_expand_nibble(ADPCMChannelStatus *c, int nibble) +{ + int step_index, predictor, sign, delta, diff, step; + + step = ff_adpcm_oki_step_table[c->step_index]; + step_index = c->step_index + ff_adpcm_index_table[(unsigned)nibble]; + step_index = av_clip(step_index, 0, 48); + + sign = nibble & 8; + delta = nibble & 7; + diff = ((2 * delta + 1) * step) >> 3; + predictor = c->predictor; + if (sign) predictor -= diff; + else predictor += diff; + + c->predictor = av_clip(predictor, -2048, 2047); + c->step_index = step_index; + + return c->predictor << 4; +} + +static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble) +{ + int sign, delta, diff; + int new_step; + + sign = nibble & 8; + delta = nibble & 7; + /* perform direct multiplication instead of series of jumps proposed by + * the reference ADPCM implementation since modern CPUs can do the mults + * quickly enough */ + diff = ((2 * delta + 1) * c->step) >> 3; + /* predictor update is not so trivial: predictor is multiplied on 254/256 before updating */ + c->predictor = ((c->predictor * 254) >> 8) + (sign ? -diff : diff); + c->predictor = av_clip_int16(c->predictor); + /* calculate new step and clamp it to range 511..32767 */ + new_step = (ff_adpcm_AdaptationTable[nibble & 7] * c->step) >> 8; + c->step = av_clip(new_step, 511, 32767); + + return (short)c->predictor; +} + +static inline short adpcm_sbpro_expand_nibble(ADPCMChannelStatus *c, char nibble, int size, int shift) +{ + int sign, delta, diff; + + sign = nibble & (1<<(size-1)); + delta = nibble & ((1<<(size-1))-1); + diff = delta << (7 + c->step + shift); + + /* clamp result */ + c->predictor = av_clip(c->predictor + (sign ? -diff : diff), -16384,16256); + + /* calculate new step */ + if (delta >= (2*size - 3) && c->step < 3) + c->step++; + else if (delta == 0 && c->step > 0) + c->step--; + + return (short) c->predictor; +} + +static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned char nibble) +{ + if(!c->step) { + c->predictor = 0; + c->step = 127; + } + + c->predictor += (c->step * ff_adpcm_yamaha_difflookup[nibble]) / 8; + c->predictor = av_clip_int16(c->predictor); + c->step = (c->step * ff_adpcm_yamaha_indexscale[nibble]) >> 8; + c->step = av_clip(c->step, 127, 24567); + return c->predictor; +} + +static int xa_decode(AVCodecContext *avctx, int16_t *out0, int16_t *out1, + const uint8_t *in, ADPCMChannelStatus *left, + ADPCMChannelStatus *right, int channels, int sample_offset) +{ + int i, j; + int shift,filter,f0,f1; + int s_1,s_2; + int d,s,t; + + out0 += sample_offset; + if (channels == 1) + out1 = out0 + 28; + else + out1 += sample_offset; + + for(i=0;i<4;i++) { + shift = 12 - (in[4+i*2] & 15); + filter = in[4+i*2] >> 4; + if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) { + avpriv_request_sample(avctx, "unknown XA-ADPCM filter %d", filter); + filter=0; + } + f0 = xa_adpcm_table[filter][0]; + f1 = xa_adpcm_table[filter][1]; + + s_1 = left->sample1; + s_2 = left->sample2; + + for(j=0;j<28;j++) { + d = in[16+i+j*4]; + + t = sign_extend(d, 4); + s = ( t<>6); + s_2 = s_1; + s_1 = av_clip_int16(s); + out0[j] = s_1; + } + + if (channels == 2) { + left->sample1 = s_1; + left->sample2 = s_2; + s_1 = right->sample1; + s_2 = right->sample2; + } + + shift = 12 - (in[5+i*2] & 15); + filter = in[5+i*2] >> 4; + if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) { + avpriv_request_sample(avctx, "unknown XA-ADPCM filter %d", filter); + filter=0; + } + + f0 = xa_adpcm_table[filter][0]; + f1 = xa_adpcm_table[filter][1]; + + for(j=0;j<28;j++) { + d = in[16+i+j*4]; + + t = sign_extend(d >> 4, 4); + s = ( t<>6); + s_2 = s_1; + s_1 = av_clip_int16(s); + out1[j] = s_1; + } + + if (channels == 2) { + right->sample1 = s_1; + right->sample2 = s_2; + } else { + left->sample1 = s_1; + left->sample2 = s_2; + } + + out0 += 28 * (3 - channels); + out1 += 28 * (3 - channels); + } + + return 0; +} + +static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_size, int16_t *samples) +{ + ADPCMDecodeContext *c = avctx->priv_data; + GetBitContext gb; + const int *table; + int k0, signmask, nb_bits, count; + int size = buf_size*8; + int i; + + init_get_bits(&gb, buf, size); + + //read bits & initial values + nb_bits = get_bits(&gb, 2)+2; + table = swf_index_tables[nb_bits-2]; + k0 = 1 << (nb_bits-2); + signmask = 1 << (nb_bits-1); + + while (get_bits_count(&gb) <= size - 22*avctx->channels) { + for (i = 0; i < avctx->channels; i++) { + *samples++ = c->status[i].predictor = get_sbits(&gb, 16); + c->status[i].step_index = get_bits(&gb, 6); + } + + for (count = 0; get_bits_count(&gb) <= size - nb_bits*avctx->channels && count < 4095; count++) { + int i; + + for (i = 0; i < avctx->channels; i++) { + // similar to IMA adpcm + int delta = get_bits(&gb, nb_bits); + int step = ff_adpcm_step_table[c->status[i].step_index]; + long vpdiff = 0; // vpdiff = (delta+0.5)*step/4 + int k = k0; + + do { + if (delta & k) + vpdiff += step; + step >>= 1; + k >>= 1; + } while(k); + vpdiff += step; + + if (delta & signmask) + c->status[i].predictor -= vpdiff; + else + c->status[i].predictor += vpdiff; + + c->status[i].step_index += table[delta & (~signmask)]; + + c->status[i].step_index = av_clip(c->status[i].step_index, 0, 88); + c->status[i].predictor = av_clip_int16(c->status[i].predictor); + + *samples++ = c->status[i].predictor; + } + } + } +} + +/** + * Get the number of samples that will be decoded from the packet. + * In one case, this is actually the maximum number of samples possible to + * decode with the given buf_size. + * + * @param[out] coded_samples set to the number of samples as coded in the + * packet, or 0 if the codec does not encode the + * number of samples in each frame. + */ +static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, + int buf_size, int *coded_samples) +{ + ADPCMDecodeContext *s = avctx->priv_data; + int nb_samples = 0; + int ch = avctx->channels; + int has_coded_samples = 0; + int header_size; + + *coded_samples = 0; + + if(ch <= 0) + return 0; + + switch (avctx->codec->id) { + /* constant, only check buf_size */ + case AV_CODEC_ID_ADPCM_EA_XAS: + if (buf_size < 76 * ch) + return 0; + nb_samples = 128; + break; + case AV_CODEC_ID_ADPCM_IMA_QT: + if (buf_size < 34 * ch) + return 0; + nb_samples = 64; + break; + /* simple 4-bit adpcm */ + case AV_CODEC_ID_ADPCM_CT: + case AV_CODEC_ID_ADPCM_IMA_APC: + case AV_CODEC_ID_ADPCM_IMA_EA_SEAD: + case AV_CODEC_ID_ADPCM_IMA_OKI: + case AV_CODEC_ID_ADPCM_IMA_WS: + case AV_CODEC_ID_ADPCM_YAMAHA: + nb_samples = buf_size * 2 / ch; + break; + } + if (nb_samples) + return nb_samples; + + /* simple 4-bit adpcm, with header */ + header_size = 0; + switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_4XM: + case AV_CODEC_ID_ADPCM_IMA_ISS: header_size = 4 * ch; break; + case AV_CODEC_ID_ADPCM_IMA_AMV: header_size = 8; break; + case AV_CODEC_ID_ADPCM_IMA_SMJPEG: header_size = 4 * ch; break; + } + if (header_size > 0) + return (buf_size - header_size) * 2 / ch; + + /* more complex formats */ + switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_EA: + has_coded_samples = 1; + *coded_samples = bytestream2_get_le32(gb); + *coded_samples -= *coded_samples % 28; + nb_samples = (buf_size - 12) / 30 * 28; + break; + case AV_CODEC_ID_ADPCM_IMA_EA_EACS: + has_coded_samples = 1; + *coded_samples = bytestream2_get_le32(gb); + nb_samples = (buf_size - (4 + 8 * ch)) * 2 / ch; + break; + case AV_CODEC_ID_ADPCM_EA_MAXIS_XA: + nb_samples = (buf_size - ch) / ch * 2; + break; + case AV_CODEC_ID_ADPCM_EA_R1: + case AV_CODEC_ID_ADPCM_EA_R2: + case AV_CODEC_ID_ADPCM_EA_R3: + /* maximum number of samples */ + /* has internal offsets and a per-frame switch to signal raw 16-bit */ + has_coded_samples = 1; + switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_EA_R1: + header_size = 4 + 9 * ch; + *coded_samples = bytestream2_get_le32(gb); + break; + case AV_CODEC_ID_ADPCM_EA_R2: + header_size = 4 + 5 * ch; + *coded_samples = bytestream2_get_le32(gb); + break; + case AV_CODEC_ID_ADPCM_EA_R3: + header_size = 4 + 5 * ch; + *coded_samples = bytestream2_get_be32(gb); + break; + } + *coded_samples -= *coded_samples % 28; + nb_samples = (buf_size - header_size) * 2 / ch; + nb_samples -= nb_samples % 28; + break; + case AV_CODEC_ID_ADPCM_IMA_DK3: + if (avctx->block_align > 0) + buf_size = FFMIN(buf_size, avctx->block_align); + nb_samples = ((buf_size - 16) * 2 / 3 * 4) / ch; + break; + case AV_CODEC_ID_ADPCM_IMA_DK4: + if (avctx->block_align > 0) + buf_size = FFMIN(buf_size, avctx->block_align); + nb_samples = 1 + (buf_size - 4 * ch) * 2 / ch; + break; + case AV_CODEC_ID_ADPCM_IMA_WAV: + if (avctx->block_align > 0) + buf_size = FFMIN(buf_size, avctx->block_align); + nb_samples = 1 + (buf_size - 4 * ch) / (4 * ch) * 8; + break; + case AV_CODEC_ID_ADPCM_MS: + if (avctx->block_align > 0) + buf_size = FFMIN(buf_size, avctx->block_align); + nb_samples = 2 + (buf_size - 7 * ch) * 2 / ch; + break; + case AV_CODEC_ID_ADPCM_SBPRO_2: + case AV_CODEC_ID_ADPCM_SBPRO_3: + case AV_CODEC_ID_ADPCM_SBPRO_4: + { + int samples_per_byte; + switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_SBPRO_2: samples_per_byte = 4; break; + case AV_CODEC_ID_ADPCM_SBPRO_3: samples_per_byte = 3; break; + case AV_CODEC_ID_ADPCM_SBPRO_4: samples_per_byte = 2; break; + } + if (!s->status[0].step_index) { + nb_samples++; + buf_size -= ch; + } + nb_samples += buf_size * samples_per_byte / ch; + break; + } + case AV_CODEC_ID_ADPCM_SWF: + { + int buf_bits = buf_size * 8 - 2; + int nbits = (bytestream2_get_byte(gb) >> 6) + 2; + int block_hdr_size = 22 * ch; + int block_size = block_hdr_size + nbits * ch * 4095; + int nblocks = buf_bits / block_size; + int bits_left = buf_bits - nblocks * block_size; + nb_samples = nblocks * 4096; + if (bits_left >= block_hdr_size) + nb_samples += 1 + (bits_left - block_hdr_size) / (nbits * ch); + break; + } + case AV_CODEC_ID_ADPCM_THP: + has_coded_samples = 1; + bytestream2_skip(gb, 4); // channel size + *coded_samples = bytestream2_get_be32(gb); + *coded_samples -= *coded_samples % 14; + nb_samples = (buf_size - (8 + 36 * ch)) / (8 * ch) * 14; + break; + case AV_CODEC_ID_ADPCM_AFC: + nb_samples = buf_size / (9 * ch) * 16; + break; + case AV_CODEC_ID_ADPCM_XA: + nb_samples = (buf_size / 128) * 224 / ch; + break; + } + + /* validate coded sample count */ + if (has_coded_samples && (*coded_samples <= 0 || *coded_samples > nb_samples)) + return AVERROR_INVALIDDATA; + + return nb_samples; +} + +static int adpcm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ADPCMDecodeContext *c = avctx->priv_data; + ADPCMChannelStatus *cs; + int n, m, channel, i; + short *samples; + int16_t **samples_p; + int st; /* stereo */ + int count1, count2; + int nb_samples, coded_samples, ret; + GetByteContext gb; + + bytestream2_init(&gb, buf, buf_size); + nb_samples = get_nb_samples(avctx, &gb, buf_size, &coded_samples); + if (nb_samples <= 0) { + av_log(avctx, AV_LOG_ERROR, "invalid number of samples in packet\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = nb_samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (short *)frame->data[0]; + samples_p = (int16_t **)frame->extended_data; + + /* use coded_samples when applicable */ + /* it is always <= nb_samples, so the output buffer will be large enough */ + if (coded_samples) { + if (coded_samples != nb_samples) + av_log(avctx, AV_LOG_WARNING, "mismatch in coded sample count\n"); + frame->nb_samples = nb_samples = coded_samples; + } + + st = avctx->channels == 2 ? 1 : 0; + + switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_IMA_QT: + /* In QuickTime, IMA is encoded by chunks of 34 bytes (=64 samples). + Channel data is interleaved per-chunk. */ + for (channel = 0; channel < avctx->channels; channel++) { + int predictor; + int step_index; + cs = &(c->status[channel]); + /* (pppppp) (piiiiiii) */ + + /* Bits 15-7 are the _top_ 9 bits of the 16-bit initial predictor value */ + predictor = sign_extend(bytestream2_get_be16u(&gb), 16); + step_index = predictor & 0x7F; + predictor &= ~0x7F; + + if (cs->step_index == step_index) { + int diff = predictor - cs->predictor; + if (diff < 0) + diff = - diff; + if (diff > 0x7f) + goto update; + } else { + update: + cs->step_index = step_index; + cs->predictor = predictor; + } + + if (cs->step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + channel, cs->step_index); + return AVERROR_INVALIDDATA; + } + + samples = samples_p[channel]; + + for (m = 0; m < 64; m += 2) { + int byte = bytestream2_get_byteu(&gb); + samples[m ] = adpcm_ima_qt_expand_nibble(cs, byte & 0x0F, 3); + samples[m + 1] = adpcm_ima_qt_expand_nibble(cs, byte >> 4 , 3); + } + } + break; + case AV_CODEC_ID_ADPCM_IMA_WAV: + for(i=0; ichannels; i++){ + cs = &(c->status[i]); + cs->predictor = samples_p[i][0] = sign_extend(bytestream2_get_le16u(&gb), 16); + + cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); + if (cs->step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + i, cs->step_index); + return AVERROR_INVALIDDATA; + } + } + + for (n = 0; n < (nb_samples - 1) / 8; n++) { + for (i = 0; i < avctx->channels; i++) { + cs = &c->status[i]; + samples = &samples_p[i][1 + n * 8]; + for (m = 0; m < 8; m += 2) { + int v = bytestream2_get_byteu(&gb); + samples[m ] = adpcm_ima_expand_nibble(cs, v & 0x0F, 3); + samples[m + 1] = adpcm_ima_expand_nibble(cs, v >> 4 , 3); + } + } + } + break; + case AV_CODEC_ID_ADPCM_4XM: + for (i = 0; i < avctx->channels; i++) + c->status[i].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + + for (i = 0; i < avctx->channels; i++) { + c->status[i].step_index = sign_extend(bytestream2_get_le16u(&gb), 16); + if (c->status[i].step_index > 88u) { + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + i, c->status[i].step_index); + return AVERROR_INVALIDDATA; + } + } + + for (i = 0; i < avctx->channels; i++) { + samples = (int16_t *)frame->data[i]; + cs = &c->status[i]; + for (n = nb_samples >> 1; n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(cs, v & 0x0F, 4); + *samples++ = adpcm_ima_expand_nibble(cs, v >> 4 , 4); + } + } + break; + case AV_CODEC_ID_ADPCM_MS: + { + int block_predictor; + + block_predictor = bytestream2_get_byteu(&gb); + if (block_predictor > 6) { + av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[0] = %d\n", + block_predictor); + return AVERROR_INVALIDDATA; + } + c->status[0].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + c->status[0].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + if (st) { + block_predictor = bytestream2_get_byteu(&gb); + if (block_predictor > 6) { + av_log(avctx, AV_LOG_ERROR, "ERROR: block_predictor[1] = %d\n", + block_predictor); + return AVERROR_INVALIDDATA; + } + c->status[1].coeff1 = ff_adpcm_AdaptCoeff1[block_predictor]; + c->status[1].coeff2 = ff_adpcm_AdaptCoeff2[block_predictor]; + } + c->status[0].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st){ + c->status[1].idelta = sign_extend(bytestream2_get_le16u(&gb), 16); + } + + c->status[0].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st) c->status[1].sample1 = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[0].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + if (st) c->status[1].sample2 = sign_extend(bytestream2_get_le16u(&gb), 16); + + *samples++ = c->status[0].sample2; + if (st) *samples++ = c->status[1].sample2; + *samples++ = c->status[0].sample1; + if (st) *samples++ = c->status[1].sample1; + for(n = (nb_samples - 2) >> (1 - st); n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ms_expand_nibble(&c->status[0 ], byte >> 4 ); + *samples++ = adpcm_ms_expand_nibble(&c->status[st], byte & 0x0F); + } + break; + } + case AV_CODEC_ID_ADPCM_IMA_DK4: + for (channel = 0; channel < avctx->channels; channel++) { + cs = &c->status[channel]; + cs->predictor = *samples++ = sign_extend(bytestream2_get_le16u(&gb), 16); + cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); + if (cs->step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + channel, cs->step_index); + return AVERROR_INVALIDDATA; + } + } + for (n = (nb_samples - 1) >> (1 - st); n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[0 ], v >> 4 , 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3); + } + break; + case AV_CODEC_ID_ADPCM_IMA_DK3: + { + int last_byte = 0; + int nibble; + int decode_top_nibble_next = 0; + int diff_channel; + const int16_t *samples_end = samples + avctx->channels * nb_samples; + + bytestream2_skipu(&gb, 10); + c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[1].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[0].step_index = bytestream2_get_byteu(&gb); + c->status[1].step_index = bytestream2_get_byteu(&gb); + if (c->status[0].step_index > 88u || c->status[1].step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i/%i\n", + c->status[0].step_index, c->status[1].step_index); + return AVERROR_INVALIDDATA; + } + /* sign extend the predictors */ + diff_channel = c->status[1].predictor; + + /* DK3 ADPCM support macro */ +#define DK3_GET_NEXT_NIBBLE() \ + if (decode_top_nibble_next) { \ + nibble = last_byte >> 4; \ + decode_top_nibble_next = 0; \ + } else { \ + last_byte = bytestream2_get_byteu(&gb); \ + nibble = last_byte & 0x0F; \ + decode_top_nibble_next = 1; \ + } + + while (samples < samples_end) { + + /* for this algorithm, c->status[0] is the sum channel and + * c->status[1] is the diff channel */ + + /* process the first predictor of the sum channel */ + DK3_GET_NEXT_NIBBLE(); + adpcm_ima_expand_nibble(&c->status[0], nibble, 3); + + /* process the diff channel predictor */ + DK3_GET_NEXT_NIBBLE(); + adpcm_ima_expand_nibble(&c->status[1], nibble, 3); + + /* process the first pair of stereo PCM samples */ + diff_channel = (diff_channel + c->status[1].predictor) / 2; + *samples++ = c->status[0].predictor + c->status[1].predictor; + *samples++ = c->status[0].predictor - c->status[1].predictor; + + /* process the second predictor of the sum channel */ + DK3_GET_NEXT_NIBBLE(); + adpcm_ima_expand_nibble(&c->status[0], nibble, 3); + + /* process the second pair of stereo PCM samples */ + diff_channel = (diff_channel + c->status[1].predictor) / 2; + *samples++ = c->status[0].predictor + c->status[1].predictor; + *samples++ = c->status[0].predictor - c->status[1].predictor; + } + break; + } + case AV_CODEC_ID_ADPCM_IMA_ISS: + for (channel = 0; channel < avctx->channels; channel++) { + cs = &c->status[channel]; + cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); + if (cs->step_index > 88u){ + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + channel, cs->step_index); + return AVERROR_INVALIDDATA; + } + } + + for (n = nb_samples >> (1 - st); n > 0; n--) { + int v1, v2; + int v = bytestream2_get_byteu(&gb); + /* nibbles are swapped for mono */ + if (st) { + v1 = v >> 4; + v2 = v & 0x0F; + } else { + v2 = v >> 4; + v1 = v & 0x0F; + } + *samples++ = adpcm_ima_expand_nibble(&c->status[0 ], v1, 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3); + } + break; + case AV_CODEC_ID_ADPCM_IMA_APC: + while (bytestream2_get_bytes_left(&gb) > 0) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4 , 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3); + } + break; + case AV_CODEC_ID_ADPCM_IMA_OKI: + while (bytestream2_get_bytes_left(&gb) > 0) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_oki_expand_nibble(&c->status[0], v >> 4 ); + *samples++ = adpcm_ima_oki_expand_nibble(&c->status[st], v & 0x0F); + } + break; + case AV_CODEC_ID_ADPCM_IMA_WS: + if (c->vqa_version == 3) { + for (channel = 0; channel < avctx->channels; channel++) { + int16_t *smp = samples_p[channel]; + + for (n = nb_samples / 2; n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + *smp++ = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); + *smp++ = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); + } + } + } else { + for (n = nb_samples / 2; n > 0; n--) { + for (channel = 0; channel < avctx->channels; channel++) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); + samples[st] = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); + } + samples += avctx->channels; + } + } + bytestream2_seek(&gb, 0, SEEK_END); + break; + case AV_CODEC_ID_ADPCM_XA: + { + int16_t *out0 = samples_p[0]; + int16_t *out1 = samples_p[1]; + int samples_per_block = 28 * (3 - avctx->channels) * 4; + int sample_offset = 0; + while (bytestream2_get_bytes_left(&gb) >= 128) { + if ((ret = xa_decode(avctx, out0, out1, buf + bytestream2_tell(&gb), + &c->status[0], &c->status[1], + avctx->channels, sample_offset)) < 0) + return ret; + bytestream2_skipu(&gb, 128); + sample_offset += samples_per_block; + } + break; + } + case AV_CODEC_ID_ADPCM_IMA_EA_EACS: + for (i=0; i<=st; i++) { + c->status[i].step_index = bytestream2_get_le32u(&gb); + if (c->status[i].step_index > 88u) { + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", + i, c->status[i].step_index); + return AVERROR_INVALIDDATA; + } + } + for (i=0; i<=st; i++) + c->status[i].predictor = bytestream2_get_le32u(&gb); + + for (n = nb_samples >> (1 - st); n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[0], byte >> 4, 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[st], byte & 0x0F, 3); + } + break; + case AV_CODEC_ID_ADPCM_IMA_EA_SEAD: + for (n = nb_samples >> (1 - st); n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ima_expand_nibble(&c->status[0], byte >> 4, 6); + *samples++ = adpcm_ima_expand_nibble(&c->status[st], byte & 0x0F, 6); + } + break; + case AV_CODEC_ID_ADPCM_EA: + { + int previous_left_sample, previous_right_sample; + int current_left_sample, current_right_sample; + int next_left_sample, next_right_sample; + int coeff1l, coeff2l, coeff1r, coeff2r; + int shift_left, shift_right; + + /* Each EA ADPCM frame has a 12-byte header followed by 30-byte pieces, + each coding 28 stereo samples. */ + + if(avctx->channels != 2) + return AVERROR_INVALIDDATA; + + current_left_sample = sign_extend(bytestream2_get_le16u(&gb), 16); + previous_left_sample = sign_extend(bytestream2_get_le16u(&gb), 16); + current_right_sample = sign_extend(bytestream2_get_le16u(&gb), 16); + previous_right_sample = sign_extend(bytestream2_get_le16u(&gb), 16); + + for (count1 = 0; count1 < nb_samples / 28; count1++) { + int byte = bytestream2_get_byteu(&gb); + coeff1l = ea_adpcm_table[ byte >> 4 ]; + coeff2l = ea_adpcm_table[(byte >> 4 ) + 4]; + coeff1r = ea_adpcm_table[ byte & 0x0F]; + coeff2r = ea_adpcm_table[(byte & 0x0F) + 4]; + + byte = bytestream2_get_byteu(&gb); + shift_left = 20 - (byte >> 4); + shift_right = 20 - (byte & 0x0F); + + for (count2 = 0; count2 < 28; count2++) { + byte = bytestream2_get_byteu(&gb); + next_left_sample = sign_extend(byte >> 4, 4) << shift_left; + next_right_sample = sign_extend(byte, 4) << shift_right; + + next_left_sample = (next_left_sample + + (current_left_sample * coeff1l) + + (previous_left_sample * coeff2l) + 0x80) >> 8; + next_right_sample = (next_right_sample + + (current_right_sample * coeff1r) + + (previous_right_sample * coeff2r) + 0x80) >> 8; + + previous_left_sample = current_left_sample; + current_left_sample = av_clip_int16(next_left_sample); + previous_right_sample = current_right_sample; + current_right_sample = av_clip_int16(next_right_sample); + *samples++ = current_left_sample; + *samples++ = current_right_sample; + } + } + + bytestream2_skip(&gb, 2); // Skip terminating 0x0000 + + break; + } + case AV_CODEC_ID_ADPCM_EA_MAXIS_XA: + { + int coeff[2][2], shift[2]; + + for(channel = 0; channel < avctx->channels; channel++) { + int byte = bytestream2_get_byteu(&gb); + for (i=0; i<2; i++) + coeff[channel][i] = ea_adpcm_table[(byte >> 4) + 4*i]; + shift[channel] = 20 - (byte & 0x0F); + } + for (count1 = 0; count1 < nb_samples / 2; count1++) { + int byte[2]; + + byte[0] = bytestream2_get_byteu(&gb); + if (st) byte[1] = bytestream2_get_byteu(&gb); + for(i = 4; i >= 0; i-=4) { /* Pairwise samples LL RR (st) or LL LL (mono) */ + for(channel = 0; channel < avctx->channels; channel++) { + int sample = sign_extend(byte[channel] >> i, 4) << shift[channel]; + sample = (sample + + c->status[channel].sample1 * coeff[channel][0] + + c->status[channel].sample2 * coeff[channel][1] + 0x80) >> 8; + c->status[channel].sample2 = c->status[channel].sample1; + c->status[channel].sample1 = av_clip_int16(sample); + *samples++ = c->status[channel].sample1; + } + } + } + bytestream2_seek(&gb, 0, SEEK_END); + break; + } + case AV_CODEC_ID_ADPCM_EA_R1: + case AV_CODEC_ID_ADPCM_EA_R2: + case AV_CODEC_ID_ADPCM_EA_R3: { + /* channel numbering + 2chan: 0=fl, 1=fr + 4chan: 0=fl, 1=rl, 2=fr, 3=rr + 6chan: 0=fl, 1=c, 2=fr, 3=rl, 4=rr, 5=sub */ + const int big_endian = avctx->codec->id == AV_CODEC_ID_ADPCM_EA_R3; + int previous_sample, current_sample, next_sample; + int coeff1, coeff2; + int shift; + unsigned int channel; + uint16_t *samplesC; + int count = 0; + int offsets[6]; + + for (channel=0; channelchannels; channel++) + offsets[channel] = (big_endian ? bytestream2_get_be32(&gb) : + bytestream2_get_le32(&gb)) + + (avctx->channels + 1) * 4; + + for (channel=0; channelchannels; channel++) { + bytestream2_seek(&gb, offsets[channel], SEEK_SET); + samplesC = samples_p[channel]; + + if (avctx->codec->id == AV_CODEC_ID_ADPCM_EA_R1) { + current_sample = sign_extend(bytestream2_get_le16(&gb), 16); + previous_sample = sign_extend(bytestream2_get_le16(&gb), 16); + } else { + current_sample = c->status[channel].predictor; + previous_sample = c->status[channel].prev_sample; + } + + for (count1 = 0; count1 < nb_samples / 28; count1++) { + int byte = bytestream2_get_byte(&gb); + if (byte == 0xEE) { /* only seen in R2 and R3 */ + current_sample = sign_extend(bytestream2_get_be16(&gb), 16); + previous_sample = sign_extend(bytestream2_get_be16(&gb), 16); + + for (count2=0; count2<28; count2++) + *samplesC++ = sign_extend(bytestream2_get_be16(&gb), 16); + } else { + coeff1 = ea_adpcm_table[ byte >> 4 ]; + coeff2 = ea_adpcm_table[(byte >> 4) + 4]; + shift = 20 - (byte & 0x0F); + + for (count2=0; count2<28; count2++) { + if (count2 & 1) + next_sample = sign_extend(byte, 4) << shift; + else { + byte = bytestream2_get_byte(&gb); + next_sample = sign_extend(byte >> 4, 4) << shift; + } + + next_sample += (current_sample * coeff1) + + (previous_sample * coeff2); + next_sample = av_clip_int16(next_sample >> 8); + + previous_sample = current_sample; + current_sample = next_sample; + *samplesC++ = current_sample; + } + } + } + if (!count) { + count = count1; + } else if (count != count1) { + av_log(avctx, AV_LOG_WARNING, "per-channel sample count mismatch\n"); + count = FFMAX(count, count1); + } + + if (avctx->codec->id != AV_CODEC_ID_ADPCM_EA_R1) { + c->status[channel].predictor = current_sample; + c->status[channel].prev_sample = previous_sample; + } + } + + frame->nb_samples = count * 28; + bytestream2_seek(&gb, 0, SEEK_END); + break; + } + case AV_CODEC_ID_ADPCM_EA_XAS: + for (channel=0; channelchannels; channel++) { + int coeff[2][4], shift[4]; + int16_t *s = samples_p[channel]; + for (n = 0; n < 4; n++, s += 32) { + int val = sign_extend(bytestream2_get_le16u(&gb), 16); + for (i=0; i<2; i++) + coeff[i][n] = ea_adpcm_table[(val&0x0F)+4*i]; + s[0] = val & ~0x0F; + + val = sign_extend(bytestream2_get_le16u(&gb), 16); + shift[n] = 20 - (val & 0x0F); + s[1] = val & ~0x0F; + } + + for (m=2; m<32; m+=2) { + s = &samples_p[channel][m]; + for (n = 0; n < 4; n++, s += 32) { + int level, pred; + int byte = bytestream2_get_byteu(&gb); + + level = sign_extend(byte >> 4, 4) << shift[n]; + pred = s[-1] * coeff[0][n] + s[-2] * coeff[1][n]; + s[0] = av_clip_int16((level + pred + 0x80) >> 8); + + level = sign_extend(byte, 4) << shift[n]; + pred = s[0] * coeff[0][n] + s[-1] * coeff[1][n]; + s[1] = av_clip_int16((level + pred + 0x80) >> 8); + } + } + } + break; + case AV_CODEC_ID_ADPCM_IMA_AMV: + c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); + c->status[0].step_index = bytestream2_get_le16u(&gb); + bytestream2_skipu(&gb, 4); + if (c->status[0].step_index > 88u) { + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", + c->status[0].step_index); + return AVERROR_INVALIDDATA; + } + + for (n = nb_samples >> (1 - st); n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + + *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4, 3); + *samples++ = adpcm_ima_expand_nibble(&c->status[0], v & 0xf, 3); + } + break; + case AV_CODEC_ID_ADPCM_IMA_SMJPEG: + for (i = 0; i < avctx->channels; i++) { + c->status[i].predictor = sign_extend(bytestream2_get_be16u(&gb), 16); + c->status[i].step_index = bytestream2_get_byteu(&gb); + bytestream2_skipu(&gb, 1); + if (c->status[i].step_index > 88u) { + av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n", + c->status[i].step_index); + return AVERROR_INVALIDDATA; + } + } + + for (n = nb_samples >> (1 - st); n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[0 ], v >> 4, 3); + *samples++ = adpcm_ima_qt_expand_nibble(&c->status[st], v & 0xf, 3); + } + break; + case AV_CODEC_ID_ADPCM_CT: + for (n = nb_samples >> (1 - st); n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_ct_expand_nibble(&c->status[0 ], v >> 4 ); + *samples++ = adpcm_ct_expand_nibble(&c->status[st], v & 0x0F); + } + break; + case AV_CODEC_ID_ADPCM_SBPRO_4: + case AV_CODEC_ID_ADPCM_SBPRO_3: + case AV_CODEC_ID_ADPCM_SBPRO_2: + if (!c->status[0].step_index) { + /* the first byte is a raw sample */ + *samples++ = 128 * (bytestream2_get_byteu(&gb) - 0x80); + if (st) + *samples++ = 128 * (bytestream2_get_byteu(&gb) - 0x80); + c->status[0].step_index = 1; + nb_samples--; + } + if (avctx->codec->id == AV_CODEC_ID_ADPCM_SBPRO_4) { + for (n = nb_samples >> (1 - st); n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], + byte >> 4, 4, 0); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[st], + byte & 0x0F, 4, 0); + } + } else if (avctx->codec->id == AV_CODEC_ID_ADPCM_SBPRO_3) { + for (n = nb_samples / 3; n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], + byte >> 5 , 3, 0); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], + (byte >> 2) & 0x07, 3, 0); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], + byte & 0x03, 2, 0); + } + } else { + for (n = nb_samples >> (2 - st); n > 0; n--) { + int byte = bytestream2_get_byteu(&gb); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], + byte >> 6 , 2, 2); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[st], + (byte >> 4) & 0x03, 2, 2); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[0], + (byte >> 2) & 0x03, 2, 2); + *samples++ = adpcm_sbpro_expand_nibble(&c->status[st], + byte & 0x03, 2, 2); + } + } + break; + case AV_CODEC_ID_ADPCM_SWF: + adpcm_swf_decode(avctx, buf, buf_size, samples); + bytestream2_seek(&gb, 0, SEEK_END); + break; + case AV_CODEC_ID_ADPCM_YAMAHA: + for (n = nb_samples >> (1 - st); n > 0; n--) { + int v = bytestream2_get_byteu(&gb); + *samples++ = adpcm_yamaha_expand_nibble(&c->status[0 ], v & 0x0F); + *samples++ = adpcm_yamaha_expand_nibble(&c->status[st], v >> 4 ); + } + break; + case AV_CODEC_ID_ADPCM_AFC: + { + int samples_per_block; + int blocks; + + if (avctx->extradata && avctx->extradata_size == 1 && avctx->extradata[0]) { + samples_per_block = avctx->extradata[0] / 16; + blocks = nb_samples / avctx->extradata[0]; + } else { + samples_per_block = nb_samples / 16; + blocks = 1; + } + + for (m = 0; m < blocks; m++) { + for (channel = 0; channel < avctx->channels; channel++) { + int prev1 = c->status[channel].sample1; + int prev2 = c->status[channel].sample2; + + samples = samples_p[channel] + m * 16; + /* Read in every sample for this channel. */ + for (i = 0; i < samples_per_block; i++) { + int byte = bytestream2_get_byteu(&gb); + int scale = 1 << (byte >> 4); + int index = byte & 0xf; + int factor1 = ff_adpcm_afc_coeffs[0][index]; + int factor2 = ff_adpcm_afc_coeffs[1][index]; + + /* Decode 16 samples. */ + for (n = 0; n < 16; n++) { + int32_t sampledat; + + if (n & 1) { + sampledat = sign_extend(byte, 4); + } else { + byte = bytestream2_get_byteu(&gb); + sampledat = sign_extend(byte >> 4, 4); + } + + sampledat = ((prev1 * factor1 + prev2 * factor2) + + ((sampledat * scale) << 11)) >> 11; + *samples = av_clip_int16(sampledat); + prev2 = prev1; + prev1 = *samples++; + } + } + + c->status[channel].sample1 = prev1; + c->status[channel].sample2 = prev2; + } + } + bytestream2_seek(&gb, 0, SEEK_END); + break; + } + case AV_CODEC_ID_ADPCM_THP: + { + int table[6][16]; + int ch; + + for (i = 0; i < avctx->channels; i++) + for (n = 0; n < 16; n++) + table[i][n] = sign_extend(bytestream2_get_be16u(&gb), 16); + + /* Initialize the previous sample. */ + for (i = 0; i < avctx->channels; i++) { + c->status[i].sample1 = sign_extend(bytestream2_get_be16u(&gb), 16); + c->status[i].sample2 = sign_extend(bytestream2_get_be16u(&gb), 16); + } + + for (ch = 0; ch < avctx->channels; ch++) { + samples = samples_p[ch]; + + /* Read in every sample for this channel. */ + for (i = 0; i < nb_samples / 14; i++) { + int byte = bytestream2_get_byteu(&gb); + int index = (byte >> 4) & 7; + unsigned int exp = byte & 0x0F; + int factor1 = table[ch][index * 2]; + int factor2 = table[ch][index * 2 + 1]; + + /* Decode 14 samples. */ + for (n = 0; n < 14; n++) { + int32_t sampledat; + + if (n & 1) { + sampledat = sign_extend(byte, 4); + } else { + byte = bytestream2_get_byteu(&gb); + sampledat = sign_extend(byte >> 4, 4); + } + + sampledat = ((c->status[ch].sample1 * factor1 + + c->status[ch].sample2 * factor2) >> 11) + (sampledat << exp); + *samples = av_clip_int16(sampledat); + c->status[ch].sample2 = c->status[ch].sample1; + c->status[ch].sample1 = *samples++; + } + } + } + break; + } + + default: + return -1; + } + + if (avpkt->size && bytestream2_tell(&gb) == 0) { + av_log(avctx, AV_LOG_ERROR, "Nothing consumed\n"); + return AVERROR_INVALIDDATA; + } + + *got_frame_ptr = 1; + + return bytestream2_tell(&gb); +} + + +static const enum AVSampleFormat sample_fmts_s16[] = { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }; +static const enum AVSampleFormat sample_fmts_s16p[] = { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }; +static const enum AVSampleFormat sample_fmts_both[] = { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }; + +#define ADPCM_DECODER(id_, sample_fmts_, name_, long_name_) \ +AVCodec ff_ ## name_ ## _decoder = { \ + .name = #name_, \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = id_, \ + .priv_data_size = sizeof(ADPCMDecodeContext), \ + .init = adpcm_decode_init, \ + .decode = adpcm_decode_frame, \ + .capabilities = CODEC_CAP_DR1, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .sample_fmts = sample_fmts_, \ +} + +/* Note: Do not forget to add new entries to the Makefile as well. */ +ADPCM_DECODER(AV_CODEC_ID_ADPCM_4XM, sample_fmts_s16p, adpcm_4xm, "ADPCM 4X Movie"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_AFC, sample_fmts_s16p, adpcm_afc, "ADPCM Nintendo Gamecube AFC"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_CT, sample_fmts_s16, adpcm_ct, "ADPCM Creative Technology"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA, sample_fmts_s16, adpcm_ea, "ADPCM Electronic Arts"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_MAXIS_XA, sample_fmts_s16, adpcm_ea_maxis_xa, "ADPCM Electronic Arts Maxis CDROM XA"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R1, sample_fmts_s16p, adpcm_ea_r1, "ADPCM Electronic Arts R1"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R2, sample_fmts_s16p, adpcm_ea_r2, "ADPCM Electronic Arts R2"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R3, sample_fmts_s16p, adpcm_ea_r3, "ADPCM Electronic Arts R3"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS, sample_fmts_s16p, adpcm_ea_xas, "ADPCM Electronic Arts XAS"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_AMV, sample_fmts_s16, adpcm_ima_amv, "ADPCM IMA AMV"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APC, sample_fmts_s16, adpcm_ima_apc, "ADPCM IMA CRYO APC"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK3, sample_fmts_s16, adpcm_ima_dk3, "ADPCM IMA Duck DK3"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4, sample_fmts_s16, adpcm_ima_dk4, "ADPCM IMA Duck DK4"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_SEAD, sample_fmts_s16, adpcm_ima_ea_sead, "ADPCM IMA Electronic Arts SEAD"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_ISS, sample_fmts_s16, adpcm_ima_iss, "ADPCM IMA Funcom ISS"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_OKI, sample_fmts_s16, adpcm_ima_oki, "ADPCM IMA Dialogic OKI"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_QT, sample_fmts_s16p, adpcm_ima_qt, "ADPCM IMA QuickTime"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG, sample_fmts_s16, adpcm_ima_smjpeg, "ADPCM IMA Loki SDL MJPEG"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV, sample_fmts_s16p, adpcm_ima_wav, "ADPCM IMA WAV"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS, sample_fmts_both, adpcm_ima_ws, "ADPCM IMA Westwood"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_MS, sample_fmts_s16, adpcm_ms, "ADPCM Microsoft"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_2, sample_fmts_s16, adpcm_sbpro_2, "ADPCM Sound Blaster Pro 2-bit"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_3, sample_fmts_s16, adpcm_sbpro_3, "ADPCM Sound Blaster Pro 2.6-bit"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_4, sample_fmts_s16, adpcm_sbpro_4, "ADPCM Sound Blaster Pro 4-bit"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_SWF, sample_fmts_s16, adpcm_swf, "ADPCM Shockwave Flash"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_THP, sample_fmts_s16p, adpcm_thp, "ADPCM Nintendo Gamecube THP"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_XA, sample_fmts_s16p, adpcm_xa, "ADPCM CDROM XA"); +ADPCM_DECODER(AV_CODEC_ID_ADPCM_YAMAHA, sample_fmts_s16, adpcm_yamaha, "ADPCM Yamaha"); diff --git a/ffmpeg/libavcodec/adpcm.h b/ffmpeg/libavcodec/adpcm.h new file mode 100644 index 0000000..08fd23f --- /dev/null +++ b/ffmpeg/libavcodec/adpcm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2001-2003 The ffmpeg Project + * + * 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 + */ + +/** + * @file + * ADPCM encoder/decoder common header. + */ + +#ifndef AVCODEC_ADPCM_H +#define AVCODEC_ADPCM_H + +#include + +#define BLKSIZE 1024 + +typedef struct ADPCMChannelStatus { + int predictor; + int16_t step_index; + int step; + /* for encoding */ + int prev_sample; + + /* MS version */ + int16_t sample1; + int16_t sample2; + int coeff1; + int coeff2; + int idelta; +} ADPCMChannelStatus; + +#endif /* AVCODEC_ADPCM_H */ diff --git a/ffmpeg/libavcodec/adpcm_data.c b/ffmpeg/libavcodec/adpcm_data.c new file mode 100644 index 0000000..0625fc9 --- /dev/null +++ b/ffmpeg/libavcodec/adpcm_data.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2001-2003 The ffmpeg Project + * + * 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 + */ + +/** + * @file + * ADPCM tables + */ + +#include + +/* ff_adpcm_step_table[] and ff_adpcm_index_table[] are from the ADPCM + reference source */ +/* This is the index table: */ +const int8_t ff_adpcm_index_table[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8, +}; + +/** + * This is the step table. Note that many programs use slight deviations from + * this table, but such deviations are negligible: + */ +const int16_t ff_adpcm_step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 +}; + +const int16_t ff_adpcm_oki_step_table[49] = { + 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, + 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, + 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, + 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 +}; + +/* These are for MS-ADPCM */ +/* ff_adpcm_AdaptationTable[], ff_adpcm_AdaptCoeff1[], and + ff_adpcm_AdaptCoeff2[] are from libsndfile */ +const int16_t ff_adpcm_AdaptationTable[] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 +}; + +/** Divided by 4 to fit in 8-bit integers */ +const uint8_t ff_adpcm_AdaptCoeff1[] = { + 64, 128, 0, 48, 60, 115, 98 +}; + +/** Divided by 4 to fit in 8-bit integers */ +const int8_t ff_adpcm_AdaptCoeff2[] = { + 0, -64, 0, 16, 0, -52, -58 +}; + +const int16_t ff_adpcm_yamaha_indexscale[] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 230, 230, 230, 230, 307, 409, 512, 614 +}; + +const int8_t ff_adpcm_yamaha_difflookup[] = { + 1, 3, 5, 7, 9, 11, 13, 15, + -1, -3, -5, -7, -9, -11, -13, -15 +}; + +const int16_t ff_adpcm_afc_coeffs[2][16] = { + { 0, 2048, 0, 1024, 4096, 3584, 3072, 4608, 4200, 4800, 5120, 2048, 1024, 64512, 64512, 63488 }, + { 0, 0, 2048, 1024, 63488, 64000, 64512, 62976, 63288, 63236, 62464, 63488, 64512, 1024, 0, 0 } +}; diff --git a/ffmpeg/libavcodec/adpcm_data.h b/ffmpeg/libavcodec/adpcm_data.h new file mode 100644 index 0000000..0ebb7c3 --- /dev/null +++ b/ffmpeg/libavcodec/adpcm_data.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2001-2003 The ffmpeg Project + * + * 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 + */ + +/** + * @file + * ADPCM tables + */ + +#ifndef AVCODEC_ADPCM_DATA_H +#define AVCODEC_ADPCM_DATA_H + +#include + +extern const int8_t ff_adpcm_index_table[16]; +extern const int16_t ff_adpcm_step_table[89]; +extern const int16_t ff_adpcm_oki_step_table[49]; +extern const int16_t ff_adpcm_AdaptationTable[]; +extern const uint8_t ff_adpcm_AdaptCoeff1[]; +extern const int8_t ff_adpcm_AdaptCoeff2[]; +extern const int16_t ff_adpcm_yamaha_indexscale[]; +extern const int8_t ff_adpcm_yamaha_difflookup[]; +extern const int16_t ff_adpcm_afc_coeffs[2][16]; + +#endif /* AVCODEC_ADPCM_DATA_H */ diff --git a/ffmpeg/libavcodec/adpcmenc.c b/ffmpeg/libavcodec/adpcmenc.c new file mode 100644 index 0000000..762cf67 --- /dev/null +++ b/ffmpeg/libavcodec/adpcmenc.c @@ -0,0 +1,725 @@ +/* + * Copyright (c) 2001-2003 The ffmpeg Project + * + * 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 "avcodec.h" +#include "put_bits.h" +#include "bytestream.h" +#include "adpcm.h" +#include "adpcm_data.h" +#include "internal.h" + +/** + * @file + * ADPCM encoders + * First version by Francois Revol (revol@free.fr) + * Fringe ADPCM codecs (e.g., DK3, DK4, Westwood) + * by Mike Melanson (melanson@pcisys.net) + * + * See ADPCM decoder reference documents for codec information. + */ + +typedef struct TrellisPath { + int nibble; + int prev; +} TrellisPath; + +typedef struct TrellisNode { + uint32_t ssd; + int path; + int sample1; + int sample2; + int step; +} TrellisNode; + +typedef struct ADPCMEncodeContext { + ADPCMChannelStatus status[6]; + TrellisPath *paths; + TrellisNode *node_buf; + TrellisNode **nodep_buf; + uint8_t *trellis_hash; +} ADPCMEncodeContext; + +#define FREEZE_INTERVAL 128 + +static av_cold int adpcm_encode_close(AVCodecContext *avctx); + +static av_cold int adpcm_encode_init(AVCodecContext *avctx) +{ + ADPCMEncodeContext *s = avctx->priv_data; + uint8_t *extradata; + int i; + int ret = AVERROR(ENOMEM); + + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "only stereo or mono is supported\n"); + return AVERROR(EINVAL); + } + + if (avctx->trellis && (unsigned)avctx->trellis > 16U) { + av_log(avctx, AV_LOG_ERROR, "invalid trellis size\n"); + return AVERROR(EINVAL); + } + + if (avctx->trellis) { + int frontier = 1 << avctx->trellis; + int max_paths = frontier * FREEZE_INTERVAL; + FF_ALLOC_OR_GOTO(avctx, s->paths, + max_paths * sizeof(*s->paths), error); + FF_ALLOC_OR_GOTO(avctx, s->node_buf, + 2 * frontier * sizeof(*s->node_buf), error); + FF_ALLOC_OR_GOTO(avctx, s->nodep_buf, + 2 * frontier * sizeof(*s->nodep_buf), error); + FF_ALLOC_OR_GOTO(avctx, s->trellis_hash, + 65536 * sizeof(*s->trellis_hash), error); + } + + avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id); + + switch (avctx->codec->id) { + case AV_CODEC_ID_ADPCM_IMA_WAV: + /* each 16 bits sample gives one nibble + and we have 4 bytes per channel overhead */ + avctx->frame_size = (BLKSIZE - 4 * avctx->channels) * 8 / + (4 * avctx->channels) + 1; + /* seems frame_size isn't taken into account... + have to buffer the samples :-( */ + avctx->block_align = BLKSIZE; + avctx->bits_per_coded_sample = 4; + break; + case AV_CODEC_ID_ADPCM_IMA_QT: + avctx->frame_size = 64; + avctx->block_align = 34 * avctx->channels; + break; + case AV_CODEC_ID_ADPCM_MS: + /* each 16 bits sample gives one nibble + and we have 7 bytes per channel overhead */ + avctx->frame_size = (BLKSIZE - 7 * avctx->channels) * 2 / avctx->channels + 2; + avctx->bits_per_coded_sample = 4; + avctx->block_align = BLKSIZE; + if (!(avctx->extradata = av_malloc(32 + FF_INPUT_BUFFER_PADDING_SIZE))) + goto error; + avctx->extradata_size = 32; + extradata = avctx->extradata; + bytestream_put_le16(&extradata, avctx->frame_size); + bytestream_put_le16(&extradata, 7); /* wNumCoef */ + for (i = 0; i < 7; i++) { + bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff1[i] * 4); + bytestream_put_le16(&extradata, ff_adpcm_AdaptCoeff2[i] * 4); + } + break; + case AV_CODEC_ID_ADPCM_YAMAHA: + avctx->frame_size = BLKSIZE * 2 / avctx->channels; + avctx->block_align = BLKSIZE; + break; + case AV_CODEC_ID_ADPCM_SWF: + if (avctx->sample_rate != 11025 && + avctx->sample_rate != 22050 && + avctx->sample_rate != 44100) { + av_log(avctx, AV_LOG_ERROR, "Sample rate must be 11025, " + "22050 or 44100\n"); + ret = AVERROR(EINVAL); + goto error; + } + avctx->frame_size = 512 * (avctx->sample_rate / 11025); + break; + default: + ret = AVERROR(EINVAL); + goto error; + } + + return 0; +error: + adpcm_encode_close(avctx); + return ret; +} + +static av_cold int adpcm_encode_close(AVCodecContext *avctx) +{ + ADPCMEncodeContext *s = avctx->priv_data; + av_freep(&s->paths); + av_freep(&s->node_buf); + av_freep(&s->nodep_buf); + av_freep(&s->trellis_hash); + + return 0; +} + + +static inline uint8_t adpcm_ima_compress_sample(ADPCMChannelStatus *c, + int16_t sample) +{ + int delta = sample - c->prev_sample; + int nibble = FFMIN(7, abs(delta) * 4 / + ff_adpcm_step_table[c->step_index]) + (delta < 0) * 8; + c->prev_sample += ((ff_adpcm_step_table[c->step_index] * + ff_adpcm_yamaha_difflookup[nibble]) / 8); + c->prev_sample = av_clip_int16(c->prev_sample); + c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88); + return nibble; +} + +static inline uint8_t adpcm_ima_qt_compress_sample(ADPCMChannelStatus *c, + int16_t sample) +{ + int delta = sample - c->prev_sample; + int diff, step = ff_adpcm_step_table[c->step_index]; + int nibble = 8*(delta < 0); + + delta= abs(delta); + diff = delta + (step >> 3); + + if (delta >= step) { + nibble |= 4; + delta -= step; + } + step >>= 1; + if (delta >= step) { + nibble |= 2; + delta -= step; + } + step >>= 1; + if (delta >= step) { + nibble |= 1; + delta -= step; + } + diff -= delta; + + if (nibble & 8) + c->prev_sample -= diff; + else + c->prev_sample += diff; + + c->prev_sample = av_clip_int16(c->prev_sample); + c->step_index = av_clip(c->step_index + ff_adpcm_index_table[nibble], 0, 88); + + return nibble; +} + +static inline uint8_t adpcm_ms_compress_sample(ADPCMChannelStatus *c, + int16_t sample) +{ + int predictor, nibble, bias; + + predictor = (((c->sample1) * (c->coeff1)) + + (( c->sample2) * (c->coeff2))) / 64; + + nibble = sample - predictor; + if (nibble >= 0) + bias = c->idelta / 2; + else + bias = -c->idelta / 2; + + nibble = (nibble + bias) / c->idelta; + nibble = av_clip(nibble, -8, 7) & 0x0F; + + predictor += ((nibble & 0x08) ? (nibble - 0x10) : nibble) * c->idelta; + + c->sample2 = c->sample1; + c->sample1 = av_clip_int16(predictor); + + c->idelta = (ff_adpcm_AdaptationTable[nibble] * c->idelta) >> 8; + if (c->idelta < 16) + c->idelta = 16; + + return nibble; +} + +static inline uint8_t adpcm_yamaha_compress_sample(ADPCMChannelStatus *c, + int16_t sample) +{ + int nibble, delta; + + if (!c->step) { + c->predictor = 0; + c->step = 127; + } + + delta = sample - c->predictor; + + nibble = FFMIN(7, abs(delta) * 4 / c->step) + (delta < 0) * 8; + + c->predictor += ((c->step * ff_adpcm_yamaha_difflookup[nibble]) / 8); + c->predictor = av_clip_int16(c->predictor); + c->step = (c->step * ff_adpcm_yamaha_indexscale[nibble]) >> 8; + c->step = av_clip(c->step, 127, 24567); + + return nibble; +} + +static void adpcm_compress_trellis(AVCodecContext *avctx, + const int16_t *samples, uint8_t *dst, + ADPCMChannelStatus *c, int n, int stride) +{ + //FIXME 6% faster if frontier is a compile-time constant + ADPCMEncodeContext *s = avctx->priv_data; + const int frontier = 1 << avctx->trellis; + const int version = avctx->codec->id; + TrellisPath *paths = s->paths, *p; + TrellisNode *node_buf = s->node_buf; + TrellisNode **nodep_buf = s->nodep_buf; + TrellisNode **nodes = nodep_buf; // nodes[] is always sorted by .ssd + TrellisNode **nodes_next = nodep_buf + frontier; + int pathn = 0, froze = -1, i, j, k, generation = 0; + uint8_t *hash = s->trellis_hash; + memset(hash, 0xff, 65536 * sizeof(*hash)); + + memset(nodep_buf, 0, 2 * frontier * sizeof(*nodep_buf)); + nodes[0] = node_buf + frontier; + nodes[0]->ssd = 0; + nodes[0]->path = 0; + nodes[0]->step = c->step_index; + nodes[0]->sample1 = c->sample1; + nodes[0]->sample2 = c->sample2; + if (version == AV_CODEC_ID_ADPCM_IMA_WAV || + version == AV_CODEC_ID_ADPCM_IMA_QT || + version == AV_CODEC_ID_ADPCM_SWF) + nodes[0]->sample1 = c->prev_sample; + if (version == AV_CODEC_ID_ADPCM_MS) + nodes[0]->step = c->idelta; + if (version == AV_CODEC_ID_ADPCM_YAMAHA) { + if (c->step == 0) { + nodes[0]->step = 127; + nodes[0]->sample1 = 0; + } else { + nodes[0]->step = c->step; + nodes[0]->sample1 = c->predictor; + } + } + + for (i = 0; i < n; i++) { + TrellisNode *t = node_buf + frontier*(i&1); + TrellisNode **u; + int sample = samples[i * stride]; + int heap_pos = 0; + memset(nodes_next, 0, frontier * sizeof(TrellisNode*)); + for (j = 0; j < frontier && nodes[j]; j++) { + // higher j have higher ssd already, so they're likely + // to yield a suboptimal next sample too + const int range = (j < frontier / 2) ? 1 : 0; + const int step = nodes[j]->step; + int nidx; + if (version == AV_CODEC_ID_ADPCM_MS) { + const int predictor = ((nodes[j]->sample1 * c->coeff1) + + (nodes[j]->sample2 * c->coeff2)) / 64; + const int div = (sample - predictor) / step; + const int nmin = av_clip(div-range, -8, 6); + const int nmax = av_clip(div+range, -7, 7); + for (nidx = nmin; nidx <= nmax; nidx++) { + const int nibble = nidx & 0xf; + int dec_sample = predictor + nidx * step; +#define STORE_NODE(NAME, STEP_INDEX)\ + int d;\ + uint32_t ssd;\ + int pos;\ + TrellisNode *u;\ + uint8_t *h;\ + dec_sample = av_clip_int16(dec_sample);\ + d = sample - dec_sample;\ + ssd = nodes[j]->ssd + d*d;\ + /* Check for wraparound, skip such samples completely. \ + * Note, changing ssd to a 64 bit variable would be \ + * simpler, avoiding this check, but it's slower on \ + * x86 32 bit at the moment. */\ + if (ssd < nodes[j]->ssd)\ + goto next_##NAME;\ + /* Collapse any two states with the same previous sample value. \ + * One could also distinguish states by step and by 2nd to last + * sample, but the effects of that are negligible. + * Since nodes in the previous generation are iterated + * through a heap, they're roughly ordered from better to + * worse, but not strictly ordered. Therefore, an earlier + * node with the same sample value is better in most cases + * (and thus the current is skipped), but not strictly + * in all cases. Only skipping samples where ssd >= + * ssd of the earlier node with the same sample gives + * slightly worse quality, though, for some reason. */ \ + h = &hash[(uint16_t) dec_sample];\ + if (*h == generation)\ + goto next_##NAME;\ + if (heap_pos < frontier) {\ + pos = heap_pos++;\ + } else {\ + /* Try to replace one of the leaf nodes with the new \ + * one, but try a different slot each time. */\ + pos = (frontier >> 1) +\ + (heap_pos & ((frontier >> 1) - 1));\ + if (ssd > nodes_next[pos]->ssd)\ + goto next_##NAME;\ + heap_pos++;\ + }\ + *h = generation;\ + u = nodes_next[pos];\ + if (!u) {\ + av_assert1(pathn < FREEZE_INTERVAL << avctx->trellis);\ + u = t++;\ + nodes_next[pos] = u;\ + u->path = pathn++;\ + }\ + u->ssd = ssd;\ + u->step = STEP_INDEX;\ + u->sample2 = nodes[j]->sample1;\ + u->sample1 = dec_sample;\ + paths[u->path].nibble = nibble;\ + paths[u->path].prev = nodes[j]->path;\ + /* Sift the newly inserted node up in the heap to \ + * restore the heap property. */\ + while (pos > 0) {\ + int parent = (pos - 1) >> 1;\ + if (nodes_next[parent]->ssd <= ssd)\ + break;\ + FFSWAP(TrellisNode*, nodes_next[parent], nodes_next[pos]);\ + pos = parent;\ + }\ + next_##NAME:; + STORE_NODE(ms, FFMAX(16, + (ff_adpcm_AdaptationTable[nibble] * step) >> 8)); + } + } else if (version == AV_CODEC_ID_ADPCM_IMA_WAV || + version == AV_CODEC_ID_ADPCM_IMA_QT || + version == AV_CODEC_ID_ADPCM_SWF) { +#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\ + const int predictor = nodes[j]->sample1;\ + const int div = (sample - predictor) * 4 / STEP_TABLE;\ + int nmin = av_clip(div - range, -7, 6);\ + int nmax = av_clip(div + range, -6, 7);\ + if (nmin <= 0)\ + nmin--; /* distinguish -0 from +0 */\ + if (nmax < 0)\ + nmax--;\ + for (nidx = nmin; nidx <= nmax; nidx++) {\ + const int nibble = nidx < 0 ? 7 - nidx : nidx;\ + int dec_sample = predictor +\ + (STEP_TABLE *\ + ff_adpcm_yamaha_difflookup[nibble]) / 8;\ + STORE_NODE(NAME, STEP_INDEX);\ + } + LOOP_NODES(ima, ff_adpcm_step_table[step], + av_clip(step + ff_adpcm_index_table[nibble], 0, 88)); + } else { //AV_CODEC_ID_ADPCM_YAMAHA + LOOP_NODES(yamaha, step, + av_clip((step * ff_adpcm_yamaha_indexscale[nibble]) >> 8, + 127, 24567)); +#undef LOOP_NODES +#undef STORE_NODE + } + } + + u = nodes; + nodes = nodes_next; + nodes_next = u; + + generation++; + if (generation == 255) { + memset(hash, 0xff, 65536 * sizeof(*hash)); + generation = 0; + } + + // prevent overflow + if (nodes[0]->ssd > (1 << 28)) { + for (j = 1; j < frontier && nodes[j]; j++) + nodes[j]->ssd -= nodes[0]->ssd; + nodes[0]->ssd = 0; + } + + // merge old paths to save memory + if (i == froze + FREEZE_INTERVAL) { + p = &paths[nodes[0]->path]; + for (k = i; k > froze; k--) { + dst[k] = p->nibble; + p = &paths[p->prev]; + } + froze = i; + pathn = 0; + // other nodes might use paths that don't coincide with the frozen one. + // checking which nodes do so is too slow, so just kill them all. + // this also slightly improves quality, but I don't know why. + memset(nodes + 1, 0, (frontier - 1) * sizeof(TrellisNode*)); + } + } + + p = &paths[nodes[0]->path]; + for (i = n - 1; i > froze; i--) { + dst[i] = p->nibble; + p = &paths[p->prev]; + } + + c->predictor = nodes[0]->sample1; + c->sample1 = nodes[0]->sample1; + c->sample2 = nodes[0]->sample2; + c->step_index = nodes[0]->step; + c->step = nodes[0]->step; + c->idelta = nodes[0]->step; +} + +static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + int n, i, ch, st, pkt_size, ret; + const int16_t *samples; + int16_t **samples_p; + uint8_t *dst; + ADPCMEncodeContext *c = avctx->priv_data; + uint8_t *buf; + + samples = (const int16_t *)frame->data[0]; + samples_p = (int16_t **)frame->extended_data; + st = avctx->channels == 2; + + if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF) + pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8; + else + pkt_size = avctx->block_align; + if ((ret = ff_alloc_packet2(avctx, avpkt, pkt_size)) < 0) + return ret; + dst = avpkt->data; + + switch(avctx->codec->id) { + case AV_CODEC_ID_ADPCM_IMA_WAV: + { + int blocks, j; + + blocks = (frame->nb_samples - 1) / 8; + + for (ch = 0; ch < avctx->channels; ch++) { + ADPCMChannelStatus *status = &c->status[ch]; + status->prev_sample = samples_p[ch][0]; + /* status->step_index = 0; + XXX: not sure how to init the state machine */ + bytestream_put_le16(&dst, status->prev_sample); + *dst++ = status->step_index; + *dst++ = 0; /* unknown */ + } + + /* stereo: 4 bytes (8 samples) for left, 4 bytes for right */ + if (avctx->trellis > 0) { + FF_ALLOC_OR_GOTO(avctx, buf, avctx->channels * blocks * 8, error); + for (ch = 0; ch < avctx->channels; ch++) { + adpcm_compress_trellis(avctx, &samples_p[ch][1], + buf + ch * blocks * 8, &c->status[ch], + blocks * 8, 1); + } + for (i = 0; i < blocks; i++) { + for (ch = 0; ch < avctx->channels; ch++) { + uint8_t *buf1 = buf + ch * blocks * 8 + i * 8; + for (j = 0; j < 8; j += 2) + *dst++ = buf1[j] | (buf1[j + 1] << 4); + } + } + av_free(buf); + } else { + for (i = 0; i < blocks; i++) { + for (ch = 0; ch < avctx->channels; ch++) { + ADPCMChannelStatus *status = &c->status[ch]; + const int16_t *smp = &samples_p[ch][1 + i * 8]; + for (j = 0; j < 8; j += 2) { + uint8_t v = adpcm_ima_compress_sample(status, smp[j ]); + v |= adpcm_ima_compress_sample(status, smp[j + 1]) << 4; + *dst++ = v; + } + } + } + } + break; + } + case AV_CODEC_ID_ADPCM_IMA_QT: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size * 8); + + for (ch = 0; ch < avctx->channels; ch++) { + ADPCMChannelStatus *status = &c->status[ch]; + put_bits(&pb, 9, (status->prev_sample & 0xFFFF) >> 7); + put_bits(&pb, 7, status->step_index); + if (avctx->trellis > 0) { + uint8_t buf[64]; + adpcm_compress_trellis(avctx, &samples_p[ch][1], buf, status, + 64, 1); + for (i = 0; i < 64; i++) + put_bits(&pb, 4, buf[i ^ 1]); + } else { + for (i = 0; i < 64; i += 2) { + int t1, t2; + t1 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i ]); + t2 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i + 1]); + put_bits(&pb, 4, t2); + put_bits(&pb, 4, t1); + } + } + } + + flush_put_bits(&pb); + break; + } + case AV_CODEC_ID_ADPCM_SWF: + { + PutBitContext pb; + init_put_bits(&pb, dst, pkt_size * 8); + + n = frame->nb_samples - 1; + + // store AdpcmCodeSize + put_bits(&pb, 2, 2); // set 4-bit flash adpcm format + + // init the encoder state + for (i = 0; i < avctx->channels; i++) { + // clip step so it fits 6 bits + c->status[i].step_index = av_clip(c->status[i].step_index, 0, 63); + put_sbits(&pb, 16, samples[i]); + put_bits(&pb, 6, c->status[i].step_index); + c->status[i].prev_sample = samples[i]; + } + + if (avctx->trellis > 0) { + FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error); + adpcm_compress_trellis(avctx, samples + avctx->channels, buf, + &c->status[0], n, avctx->channels); + if (avctx->channels == 2) + adpcm_compress_trellis(avctx, samples + avctx->channels + 1, + buf + n, &c->status[1], n, + avctx->channels); + for (i = 0; i < n; i++) { + put_bits(&pb, 4, buf[i]); + if (avctx->channels == 2) + put_bits(&pb, 4, buf[n + i]); + } + av_free(buf); + } else { + for (i = 1; i < frame->nb_samples; i++) { + put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0], + samples[avctx->channels * i])); + if (avctx->channels == 2) + put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[1], + samples[2 * i + 1])); + } + } + flush_put_bits(&pb); + break; + } + case AV_CODEC_ID_ADPCM_MS: + for (i = 0; i < avctx->channels; i++) { + int predictor = 0; + *dst++ = predictor; + c->status[i].coeff1 = ff_adpcm_AdaptCoeff1[predictor]; + c->status[i].coeff2 = ff_adpcm_AdaptCoeff2[predictor]; + } + for (i = 0; i < avctx->channels; i++) { + if (c->status[i].idelta < 16) + c->status[i].idelta = 16; + bytestream_put_le16(&dst, c->status[i].idelta); + } + for (i = 0; i < avctx->channels; i++) + c->status[i].sample2= *samples++; + for (i = 0; i < avctx->channels; i++) { + c->status[i].sample1 = *samples++; + bytestream_put_le16(&dst, c->status[i].sample1); + } + for (i = 0; i < avctx->channels; i++) + bytestream_put_le16(&dst, c->status[i].sample2); + + if (avctx->trellis > 0) { + n = avctx->block_align - 7 * avctx->channels; + FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error); + if (avctx->channels == 1) { + adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n, + avctx->channels); + for (i = 0; i < n; i += 2) + *dst++ = (buf[i] << 4) | buf[i + 1]; + } else { + adpcm_compress_trellis(avctx, samples, buf, + &c->status[0], n, avctx->channels); + adpcm_compress_trellis(avctx, samples + 1, buf + n, + &c->status[1], n, avctx->channels); + for (i = 0; i < n; i++) + *dst++ = (buf[i] << 4) | buf[n + i]; + } + av_free(buf); + } else { + for (i = 7 * avctx->channels; i < avctx->block_align; i++) { + int nibble; + nibble = adpcm_ms_compress_sample(&c->status[ 0], *samples++) << 4; + nibble |= adpcm_ms_compress_sample(&c->status[st], *samples++); + *dst++ = nibble; + } + } + break; + case AV_CODEC_ID_ADPCM_YAMAHA: + n = frame->nb_samples / 2; + if (avctx->trellis > 0) { + FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error); + n *= 2; + if (avctx->channels == 1) { + adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n, + avctx->channels); + for (i = 0; i < n; i += 2) + *dst++ = buf[i] | (buf[i + 1] << 4); + } else { + adpcm_compress_trellis(avctx, samples, buf, + &c->status[0], n, avctx->channels); + adpcm_compress_trellis(avctx, samples + 1, buf + n, + &c->status[1], n, avctx->channels); + for (i = 0; i < n; i++) + *dst++ = buf[i] | (buf[n + i] << 4); + } + av_free(buf); + } else + for (n *= avctx->channels; n > 0; n--) { + int nibble; + nibble = adpcm_yamaha_compress_sample(&c->status[ 0], *samples++); + nibble |= adpcm_yamaha_compress_sample(&c->status[st], *samples++) << 4; + *dst++ = nibble; + } + break; + default: + return AVERROR(EINVAL); + } + + avpkt->size = pkt_size; + *got_packet_ptr = 1; + return 0; +error: + return AVERROR(ENOMEM); +} + +static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE +}; + +static const enum AVSampleFormat sample_fmts_p[] = { + AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE +}; + +#define ADPCM_ENCODER(id_, name_, sample_fmts_, long_name_) \ +AVCodec ff_ ## name_ ## _encoder = { \ + .name = #name_, \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = id_, \ + .priv_data_size = sizeof(ADPCMEncodeContext), \ + .init = adpcm_encode_init, \ + .encode2 = adpcm_encode_frame, \ + .close = adpcm_encode_close, \ + .sample_fmts = sample_fmts_, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ +} + +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, "ADPCM IMA QuickTime"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, "ADPCM IMA WAV"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, sample_fmts, "ADPCM Microsoft"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, sample_fmts, "ADPCM Shockwave Flash"); +ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, "ADPCM Yamaha"); diff --git a/ffmpeg/libavcodec/adx.c b/ffmpeg/libavcodec/adx.c new file mode 100644 index 0000000..4c88f81 --- /dev/null +++ b/ffmpeg/libavcodec/adx.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "adx.h" + +void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff) +{ + double a, b, c; + + a = M_SQRT2 - cos(2.0 * M_PI * cutoff / sample_rate); + b = M_SQRT2 - 1.0; + c = (a - sqrt((a + b) * (a - b))) / b; + + coeff[0] = lrintf(c * 2.0 * (1 << bits)); + coeff[1] = lrintf(-(c * c) * (1 << bits)); +} + +int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, + int bufsize, int *header_size, int *coeff) +{ + int offset, cutoff; + + if (bufsize < 24) + return AVERROR_INVALIDDATA; + + if (AV_RB16(buf) != 0x8000) + return AVERROR_INVALIDDATA; + offset = AV_RB16(buf + 2) + 4; + + if (offset < 6) { + av_log(avctx, AV_LOG_ERROR, "offset is prior data\n"); + return AVERROR_INVALIDDATA; + } + + /* if copyright string is within the provided data, validate it */ + if (bufsize >= offset && memcmp(buf + offset - 6, "(c)CRI", 6)) + return AVERROR_INVALIDDATA; + + /* check for encoding=3 block_size=18, sample_size=4 */ + if (buf[4] != 3 || buf[5] != 18 || buf[6] != 4) { + avpriv_request_sample(avctx, "Support for this ADX format"); + return AVERROR_PATCHWELCOME; + } + + /* channels */ + avctx->channels = buf[7]; + if (avctx->channels <= 0 || avctx->channels > 2) + return AVERROR_INVALIDDATA; + + /* sample rate */ + avctx->sample_rate = AV_RB32(buf + 8); + if (avctx->sample_rate < 1 || + avctx->sample_rate > INT_MAX / (avctx->channels * BLOCK_SIZE * 8)) + return AVERROR_INVALIDDATA; + + /* bit rate */ + avctx->bit_rate = avctx->sample_rate * avctx->channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES; + + /* LPC coefficients */ + if (coeff) { + cutoff = AV_RB16(buf + 16); + ff_adx_calculate_coeffs(cutoff, avctx->sample_rate, COEFF_BITS, coeff); + } + + *header_size = offset; + return 0; +} diff --git a/ffmpeg/libavcodec/adx.h b/ffmpeg/libavcodec/adx.h new file mode 100644 index 0000000..b28d09a --- /dev/null +++ b/ffmpeg/libavcodec/adx.h @@ -0,0 +1,80 @@ +/* + * ADX ADPCM codecs + * Copyright (c) 2001,2003 BERO + * + * 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 + */ + +/** + * @file + * SEGA CRI adx codecs. + * + * Reference documents: + * http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html + * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ + */ + +#ifndef AVCODEC_ADX_H +#define AVCODEC_ADX_H + +#include + +#include "avcodec.h" + +typedef struct ADXChannelState { + int s1,s2; +} ADXChannelState; + +typedef struct ADXContext { + int channels; + ADXChannelState prev[2]; + int header_parsed; + int eof; + int cutoff; + int coeff[2]; +} ADXContext; + +#define COEFF_BITS 12 + +#define BLOCK_SIZE 18 +#define BLOCK_SAMPLES 32 + +/** + * Calculate LPC coefficients based on cutoff frequency and sample rate. + * + * @param cutoff cutoff frequency + * @param sample_rate sample rate + * @param bits number of bits used to quantize coefficients + * @param[out] coeff 2 quantized LPC coefficients + */ +void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff); + +/** + * Decode ADX stream header. + * Sets avctx->channels and avctx->sample_rate. + * + * @param avctx codec context + * @param buf header data + * @param bufsize data size, should be at least 24 bytes + * @param[out] header_size size of ADX header + * @param[out] coeff 2 LPC coefficients, can be NULL + * @return data offset or negative error code if header is invalid + */ +int avpriv_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, + int bufsize, int *header_size, int *coeff); + +#endif /* AVCODEC_ADX_H */ diff --git a/ffmpeg/libavcodec/adx_parser.c b/ffmpeg/libavcodec/adx_parser.c new file mode 100644 index 0000000..706e242 --- /dev/null +++ b/ffmpeg/libavcodec/adx_parser.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * ADX audio parser + * + * Splits packets into individual blocks. + */ + +#include "libavutil/intreadwrite.h" +#include "parser.h" +#include "adx.h" + +typedef struct ADXParseContext { + ParseContext pc; + int header_size; + int block_size; + int remaining; +} ADXParseContext; + +static int adx_parse(AVCodecParserContext *s1, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ADXParseContext *s = s1->priv_data; + ParseContext *pc = &s->pc; + int next = END_NOT_FOUND; + int i; + uint64_t state = pc->state64; + + if (!s->header_size) { + for (i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + /* check for fixed fields in ADX header for possible match */ + if ((state & 0xFFFF0000FFFFFF00) == 0x8000000003120400ULL) { + int channels = state & 0xFF; + int header_size = ((state >> 32) & 0xFFFF) + 4; + if (channels > 0 && header_size >= 8) { + s->header_size = header_size; + s->block_size = BLOCK_SIZE * channels; + s->remaining = i - 7 + s->header_size + s->block_size; + break; + } + } + } + pc->state64 = state; + } + + if (s->header_size) { + if (!s->remaining) + s->remaining = s->block_size; + if (s->remaining <= buf_size) { + next = s->remaining; + s->remaining = 0; + } else + s->remaining -= buf_size; + } + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + s1->duration = BLOCK_SAMPLES; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_adx_parser = { + .codec_ids = { AV_CODEC_ID_ADPCM_ADX }, + .priv_data_size = sizeof(ADXParseContext), + .parser_parse = adx_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/adxdec.c b/ffmpeg/libavcodec/adxdec.c new file mode 100644 index 0000000..7d7fe3a --- /dev/null +++ b/ffmpeg/libavcodec/adxdec.c @@ -0,0 +1,187 @@ +/* + * ADX ADPCM codecs + * Copyright (c) 2001,2003 BERO + * + * 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 "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "adx.h" +#include "get_bits.h" +#include "internal.h" + +/** + * @file + * SEGA CRI adx codecs. + * + * Reference documents: + * http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html + * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ + */ + +static av_cold int adx_decode_init(AVCodecContext *avctx) +{ + ADXContext *c = avctx->priv_data; + int ret, header_size; + + if (avctx->extradata_size >= 24) { + if ((ret = avpriv_adx_decode_header(avctx, avctx->extradata, + avctx->extradata_size, &header_size, + c->coeff)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); + return AVERROR_INVALIDDATA; + } + c->channels = avctx->channels; + c->header_parsed = 1; + } + + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + + return 0; +} + +/** + * Decode 32 samples from 18 bytes. + * + * A 16-bit scalar value is applied to 32 residuals, which then have a + * 2nd-order LPC filter applied to it to form the output signal for a single + * channel. + */ +static int adx_decode(ADXContext *c, int16_t *out, int offset, + const uint8_t *in, int ch) +{ + ADXChannelState *prev = &c->prev[ch]; + GetBitContext gb; + int scale = AV_RB16(in); + int i; + int s0, s1, s2, d; + + /* check if this is an EOF packet */ + if (scale & 0x8000) + return -1; + + init_get_bits(&gb, in + 2, (BLOCK_SIZE - 2) * 8); + out += offset; + s1 = prev->s1; + s2 = prev->s2; + for (i = 0; i < BLOCK_SAMPLES; i++) { + d = get_sbits(&gb, 4); + s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS; + s2 = s1; + s1 = av_clip_int16(s0); + *out++ = s1; + } + prev->s1 = s1; + prev->s2 = s2; + + return 0; +} + +static int adx_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + int buf_size = avpkt->size; + ADXContext *c = avctx->priv_data; + int16_t **samples; + int samples_offset; + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = buf + avpkt->size; + int num_blocks, ch, ret; + + if (c->eof) { + *got_frame_ptr = 0; + return buf_size; + } + + if (!c->header_parsed && buf_size >= 2 && AV_RB16(buf) == 0x8000) { + int header_size; + if ((ret = avpriv_adx_decode_header(avctx, buf, buf_size, &header_size, + c->coeff)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); + return AVERROR_INVALIDDATA; + } + c->channels = avctx->channels; + c->header_parsed = 1; + if (buf_size < header_size) + return AVERROR_INVALIDDATA; + buf += header_size; + buf_size -= header_size; + } + if (!c->header_parsed) + return AVERROR_INVALIDDATA; + + /* calculate number of blocks in the packet */ + num_blocks = buf_size / (BLOCK_SIZE * c->channels); + + /* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF + packet */ + if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) { + if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) { + c->eof = 1; + *got_frame_ptr = 0; + return avpkt->size; + } + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = num_blocks * BLOCK_SAMPLES; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t **)frame->extended_data; + samples_offset = 0; + + while (num_blocks--) { + for (ch = 0; ch < c->channels; ch++) { + if (buf_end - buf < BLOCK_SIZE || adx_decode(c, samples[ch], samples_offset, buf, ch)) { + c->eof = 1; + buf = avpkt->data + avpkt->size; + break; + } + buf_size -= BLOCK_SIZE; + buf += BLOCK_SIZE; + } + samples_offset += BLOCK_SAMPLES; + } + + *got_frame_ptr = 1; + + return buf - avpkt->data; +} + +static void adx_decode_flush(AVCodecContext *avctx) +{ + ADXContext *c = avctx->priv_data; + memset(c->prev, 0, sizeof(c->prev)); + c->eof = 0; +} + +AVCodec ff_adpcm_adx_decoder = { + .name = "adpcm_adx", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_ADX, + .priv_data_size = sizeof(ADXContext), + .init = adx_decode_init, + .decode = adx_decode_frame, + .flush = adx_decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/adxenc.c b/ffmpeg/libavcodec/adxenc.c new file mode 100644 index 0000000..df07c81 --- /dev/null +++ b/ffmpeg/libavcodec/adxenc.c @@ -0,0 +1,169 @@ +/* + * ADX ADPCM codecs + * Copyright (c) 2001,2003 BERO + * + * 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 "avcodec.h" +#include "adx.h" +#include "bytestream.h" +#include "internal.h" +#include "put_bits.h" + +/** + * @file + * SEGA CRI adx codecs. + * + * Reference documents: + * http://ku-www.ss.titech.ac.jp/~yatsushi/adx.html + * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ + */ + +static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, + ADXChannelState *prev, int channels) +{ + PutBitContext pb; + int scale; + int i, j; + int s0, s1, s2, d; + int max = 0; + int min = 0; + int data[BLOCK_SAMPLES]; + + s1 = prev->s1; + s2 = prev->s2; + for (i = 0, j = 0; j < 32; i += channels, j++) { + s0 = wav[i]; + d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; + data[j] = d; + if (max < d) + max = d; + if (min > d) + min = d; + s2 = s1; + s1 = s0; + } + prev->s1 = s1; + prev->s2 = s2; + + if (max == 0 && min == 0) { + memset(adx, 0, BLOCK_SIZE); + return; + } + + if (max / 7 > -min / 8) + scale = max / 7; + else + scale = -min / 8; + + if (scale == 0) + scale = 1; + + AV_WB16(adx, scale); + + init_put_bits(&pb, adx + 2, 16); + for (i = 0; i < BLOCK_SAMPLES; i++) + put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7)); + flush_put_bits(&pb); +} + +#define HEADER_SIZE 36 + +static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) +{ + ADXContext *c = avctx->priv_data; + + bytestream_put_be16(&buf, 0x8000); /* header signature */ + bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */ + bytestream_put_byte(&buf, 3); /* encoding */ + bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */ + bytestream_put_byte(&buf, 4); /* sample size */ + bytestream_put_byte(&buf, avctx->channels); /* channels */ + bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */ + bytestream_put_be32(&buf, 0); /* total sample count */ + bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */ + bytestream_put_byte(&buf, 3); /* version */ + bytestream_put_byte(&buf, 0); /* flags */ + bytestream_put_be32(&buf, 0); /* unknown */ + bytestream_put_be32(&buf, 0); /* loop enabled */ + bytestream_put_be16(&buf, 0); /* padding */ + bytestream_put_buffer(&buf, "(c)CRI", 6); /* copyright signature */ + + return HEADER_SIZE; +} + +static av_cold int adx_encode_init(AVCodecContext *avctx) +{ + ADXContext *c = avctx->priv_data; + + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); + } + avctx->frame_size = BLOCK_SAMPLES; + + /* the cutoff can be adjusted, but this seems to work pretty well */ + c->cutoff = 500; + ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); + + return 0; +} + +static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + ADXContext *c = avctx->priv_data; + const int16_t *samples = (const int16_t *)frame->data[0]; + uint8_t *dst; + int ch, out_size, ret; + + out_size = BLOCK_SIZE * avctx->channels + !c->header_parsed * HEADER_SIZE; + if ((ret = ff_alloc_packet2(avctx, avpkt, out_size)) < 0) + return ret; + dst = avpkt->data; + + if (!c->header_parsed) { + int hdrsize; + if ((hdrsize = adx_encode_header(avctx, dst, avpkt->size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); + return AVERROR(EINVAL); + } + dst += hdrsize; + c->header_parsed = 1; + } + + for (ch = 0; ch < avctx->channels; ch++) { + adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels); + dst += BLOCK_SIZE; + } + + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_adpcm_adx_encoder = { + .name = "adpcm_adx", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_ADX, + .priv_data_size = sizeof(ADXContext), + .init = adx_encode_init, + .encode2 = adx_encode_frame, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), +}; diff --git a/ffmpeg/libavcodec/alac.c b/ffmpeg/libavcodec/alac.c new file mode 100644 index 0000000..0018b9a --- /dev/null +++ b/ffmpeg/libavcodec/alac.c @@ -0,0 +1,628 @@ +/* + * ALAC (Apple Lossless Audio Codec) decoder + * Copyright (c) 2005 David Hammerton + * + * 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 + */ + +/** + * @file + * ALAC (Apple Lossless Audio Codec) decoder + * @author 2005 David Hammerton + * @see http://crazney.net/programs/itunes/alac.html + * + * Note: This decoder expects a 36-byte QuickTime atom to be + * passed through the extradata[_size] fields. This atom is tacked onto + * the end of an 'alac' stsd atom and has the following format: + * + * 32bit atom size + * 32bit tag ("alac") + * 32bit tag version (0) + * 32bit samples per frame (used when not set explicitly in the frames) + * 8bit compatible version (0) + * 8bit sample size + * 8bit history mult (40) + * 8bit initial history (10) + * 8bit rice param limit (14) + * 8bit channels + * 16bit maxRun (255) + * 32bit max coded frame size (0 means unknown) + * 32bit average bitrate (0 means unknown) + * 32bit samplerate + */ + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "bytestream.h" +#include "internal.h" +#include "unary.h" +#include "mathops.h" +#include "alac_data.h" + +#define ALAC_EXTRADATA_SIZE 36 + +typedef struct { + AVCodecContext *avctx; + GetBitContext gb; + int channels; + + int32_t *predict_error_buffer[2]; + int32_t *output_samples_buffer[2]; + int32_t *extra_bits_buffer[2]; + + uint32_t max_samples_per_frame; + uint8_t sample_size; + uint8_t rice_history_mult; + uint8_t rice_initial_history; + uint8_t rice_limit; + + int extra_bits; /**< number of extra bits beyond 16-bit */ + int nb_samples; /**< number of samples in the current frame */ + + int direct_output; +} ALACContext; + +static inline unsigned int decode_scalar(GetBitContext *gb, int k, int bps) +{ + unsigned int x = get_unary_0_9(gb); + + if (x > 8) { /* RICE THRESHOLD */ + /* use alternative encoding */ + x = get_bits_long(gb, bps); + } else if (k != 1) { + int extrabits = show_bits(gb, k); + + /* multiply x by 2^k - 1, as part of their strange algorithm */ + x = (x << k) - x; + + if (extrabits > 1) { + x += extrabits - 1; + skip_bits(gb, k); + } else + skip_bits(gb, k - 1); + } + return x; +} + +static int rice_decompress(ALACContext *alac, int32_t *output_buffer, + int nb_samples, int bps, int rice_history_mult) +{ + int i; + unsigned int history = alac->rice_initial_history; + int sign_modifier = 0; + + for (i = 0; i < nb_samples; i++) { + int k; + unsigned int x; + + if(get_bits_left(&alac->gb) <= 0) + return -1; + + /* calculate rice param and decode next value */ + k = av_log2((history >> 9) + 3); + k = FFMIN(k, alac->rice_limit); + x = decode_scalar(&alac->gb, k, bps); + x += sign_modifier; + sign_modifier = 0; + output_buffer[i] = (x >> 1) ^ -(x & 1); + + /* update the history */ + if (x > 0xffff) + history = 0xffff; + else + history += x * rice_history_mult - + ((history * rice_history_mult) >> 9); + + /* special case: there may be compressed blocks of 0 */ + if ((history < 128) && (i + 1 < nb_samples)) { + int block_size; + + /* calculate rice param and decode block size */ + k = 7 - av_log2(history) + ((history + 16) >> 6); + k = FFMIN(k, alac->rice_limit); + block_size = decode_scalar(&alac->gb, k, 16); + + if (block_size > 0) { + if (block_size >= nb_samples - i) { + av_log(alac->avctx, AV_LOG_ERROR, + "invalid zero block size of %d %d %d\n", block_size, + nb_samples, i); + block_size = nb_samples - i - 1; + } + memset(&output_buffer[i + 1], 0, + block_size * sizeof(*output_buffer)); + i += block_size; + } + if (block_size <= 0xffff) + sign_modifier = 1; + history = 0; + } + } + return 0; +} + +static inline int sign_only(int v) +{ + return v ? FFSIGN(v) : 0; +} + +static void lpc_prediction(int32_t *error_buffer, int32_t *buffer_out, + int nb_samples, int bps, int16_t *lpc_coefs, + int lpc_order, int lpc_quant) +{ + int i; + int32_t *pred = buffer_out; + + /* first sample always copies */ + *buffer_out = *error_buffer; + + if (nb_samples <= 1) + return; + + if (!lpc_order) { + memcpy(&buffer_out[1], &error_buffer[1], + (nb_samples - 1) * sizeof(*buffer_out)); + return; + } + + if (lpc_order == 31) { + /* simple 1st-order prediction */ + for (i = 1; i < nb_samples; i++) { + buffer_out[i] = sign_extend(buffer_out[i - 1] + error_buffer[i], + bps); + } + return; + } + + /* read warm-up samples */ + for (i = 1; i <= lpc_order && i < nb_samples; i++) + buffer_out[i] = sign_extend(buffer_out[i - 1] + error_buffer[i], bps); + + /* NOTE: 4 and 8 are very common cases that could be optimized. */ + + for (; i < nb_samples; i++) { + int j; + int val = 0; + int error_val = error_buffer[i]; + int error_sign; + int d = *pred++; + + /* LPC prediction */ + for (j = 0; j < lpc_order; j++) + val += (pred[j] - d) * lpc_coefs[j]; + val = (val + (1 << (lpc_quant - 1))) >> lpc_quant; + val += d + error_val; + buffer_out[i] = sign_extend(val, bps); + + /* adapt LPC coefficients */ + error_sign = sign_only(error_val); + if (error_sign) { + for (j = 0; j < lpc_order && error_val * error_sign > 0; j++) { + int sign; + val = d - pred[j]; + sign = sign_only(val) * error_sign; + lpc_coefs[j] -= sign; + val *= sign; + error_val -= (val >> lpc_quant) * (j + 1); + } + } + } +} + +static void decorrelate_stereo(int32_t *buffer[2], int nb_samples, + int decorr_shift, int decorr_left_weight) +{ + int i; + + for (i = 0; i < nb_samples; i++) { + int32_t a, b; + + a = buffer[0][i]; + b = buffer[1][i]; + + a -= (b * decorr_left_weight) >> decorr_shift; + b += a; + + buffer[0][i] = b; + buffer[1][i] = a; + } +} + +static void append_extra_bits(int32_t *buffer[2], int32_t *extra_bits_buffer[2], + int extra_bits, int channels, int nb_samples) +{ + int i, ch; + + for (ch = 0; ch < channels; ch++) + for (i = 0; i < nb_samples; i++) + buffer[ch][i] = (buffer[ch][i] << extra_bits) | extra_bits_buffer[ch][i]; +} + +static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index, + int channels) +{ + ALACContext *alac = avctx->priv_data; + int has_size, bps, is_compressed, decorr_shift, decorr_left_weight, ret; + uint32_t output_samples; + int i, ch; + + skip_bits(&alac->gb, 4); /* element instance tag */ + skip_bits(&alac->gb, 12); /* unused header bits */ + + /* the number of output samples is stored in the frame */ + has_size = get_bits1(&alac->gb); + + alac->extra_bits = get_bits(&alac->gb, 2) << 3; + bps = alac->sample_size - alac->extra_bits + channels - 1; + if (bps > 32U) { + av_log(avctx, AV_LOG_ERROR, "bps is unsupported: %d\n", bps); + return AVERROR_PATCHWELCOME; + } + + /* whether the frame is compressed */ + is_compressed = !get_bits1(&alac->gb); + + if (has_size) + output_samples = get_bits_long(&alac->gb, 32); + else + output_samples = alac->max_samples_per_frame; + if (!output_samples || output_samples > alac->max_samples_per_frame) { + av_log(avctx, AV_LOG_ERROR, "invalid samples per frame: %d\n", + output_samples); + return AVERROR_INVALIDDATA; + } + if (!alac->nb_samples) { + /* get output buffer */ + frame->nb_samples = output_samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + } else if (output_samples != alac->nb_samples) { + av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %u != %d\n", + output_samples, alac->nb_samples); + return AVERROR_INVALIDDATA; + } + alac->nb_samples = output_samples; + if (alac->direct_output) { + for (ch = 0; ch < channels; ch++) + alac->output_samples_buffer[ch] = (int32_t *)frame->extended_data[ch_index + ch]; + } + + if (is_compressed) { + int16_t lpc_coefs[2][32]; + int lpc_order[2]; + int prediction_type[2]; + int lpc_quant[2]; + int rice_history_mult[2]; + + decorr_shift = get_bits(&alac->gb, 8); + decorr_left_weight = get_bits(&alac->gb, 8); + + for (ch = 0; ch < channels; ch++) { + prediction_type[ch] = get_bits(&alac->gb, 4); + lpc_quant[ch] = get_bits(&alac->gb, 4); + rice_history_mult[ch] = get_bits(&alac->gb, 3); + lpc_order[ch] = get_bits(&alac->gb, 5); + + /* read the predictor table */ + for (i = lpc_order[ch] - 1; i >= 0; i--) + lpc_coefs[ch][i] = get_sbits(&alac->gb, 16); + } + + if (alac->extra_bits) { + for (i = 0; i < alac->nb_samples; i++) { + if(get_bits_left(&alac->gb) <= 0) + return -1; + for (ch = 0; ch < channels; ch++) + alac->extra_bits_buffer[ch][i] = get_bits(&alac->gb, alac->extra_bits); + } + } + for (ch = 0; ch < channels; ch++) { + int ret=rice_decompress(alac, alac->predict_error_buffer[ch], + alac->nb_samples, bps, + rice_history_mult[ch] * alac->rice_history_mult / 4); + if(ret<0) + return ret; + + /* adaptive FIR filter */ + if (prediction_type[ch] == 15) { + /* Prediction type 15 runs the adaptive FIR twice. + * The first pass uses the special-case coef_num = 31, while + * the second pass uses the coefs from the bitstream. + * + * However, this prediction type is not currently used by the + * reference encoder. + */ + lpc_prediction(alac->predict_error_buffer[ch], + alac->predict_error_buffer[ch], + alac->nb_samples, bps, NULL, 31, 0); + } else if (prediction_type[ch] > 0) { + av_log(avctx, AV_LOG_WARNING, "unknown prediction type: %i\n", + prediction_type[ch]); + } + lpc_prediction(alac->predict_error_buffer[ch], + alac->output_samples_buffer[ch], alac->nb_samples, + bps, lpc_coefs[ch], lpc_order[ch], lpc_quant[ch]); + } + } else { + /* not compressed, easy case */ + for (i = 0; i < alac->nb_samples; i++) { + if(get_bits_left(&alac->gb) <= 0) + return -1; + for (ch = 0; ch < channels; ch++) { + alac->output_samples_buffer[ch][i] = + get_sbits_long(&alac->gb, alac->sample_size); + } + } + alac->extra_bits = 0; + decorr_shift = 0; + decorr_left_weight = 0; + } + + if (channels == 2 && decorr_left_weight) { + decorrelate_stereo(alac->output_samples_buffer, alac->nb_samples, + decorr_shift, decorr_left_weight); + } + + if (alac->extra_bits) { + append_extra_bits(alac->output_samples_buffer, alac->extra_bits_buffer, + alac->extra_bits, channels, alac->nb_samples); + } + + if(av_sample_fmt_is_planar(avctx->sample_fmt)) { + switch(alac->sample_size) { + case 16: { + for (ch = 0; ch < channels; ch++) { + int16_t *outbuffer = (int16_t *)frame->extended_data[ch_index + ch]; + for (i = 0; i < alac->nb_samples; i++) + *outbuffer++ = alac->output_samples_buffer[ch][i]; + }} + break; + case 24: { + for (ch = 0; ch < channels; ch++) { + for (i = 0; i < alac->nb_samples; i++) + alac->output_samples_buffer[ch][i] <<= 8; + }} + break; + } + }else{ + switch(alac->sample_size) { + case 16: { + int16_t *outbuffer = ((int16_t *)frame->extended_data[0]) + ch_index; + for (i = 0; i < alac->nb_samples; i++) { + for (ch = 0; ch < channels; ch++) + *outbuffer++ = alac->output_samples_buffer[ch][i]; + outbuffer += alac->channels - channels; + } + } + break; + case 24: { + int32_t *outbuffer = ((int32_t *)frame->extended_data[0]) + ch_index; + for (i = 0; i < alac->nb_samples; i++) { + for (ch = 0; ch < channels; ch++) + *outbuffer++ = alac->output_samples_buffer[ch][i] << 8; + outbuffer += alac->channels - channels; + } + } + break; + case 32: { + int32_t *outbuffer = ((int32_t *)frame->extended_data[0]) + ch_index; + for (i = 0; i < alac->nb_samples; i++) { + for (ch = 0; ch < channels; ch++) + *outbuffer++ = alac->output_samples_buffer[ch][i]; + outbuffer += alac->channels - channels; + } + } + break; + } + } + + return 0; +} + +static int alac_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + ALACContext *alac = avctx->priv_data; + AVFrame *frame = data; + enum AlacRawDataBlockType element; + int channels; + int ch, ret, got_end; + + init_get_bits(&alac->gb, avpkt->data, avpkt->size * 8); + + got_end = 0; + alac->nb_samples = 0; + ch = 0; + while (get_bits_left(&alac->gb) >= 3) { + element = get_bits(&alac->gb, 3); + if (element == TYPE_END) { + got_end = 1; + break; + } + if (element > TYPE_CPE && element != TYPE_LFE) { + av_log(avctx, AV_LOG_ERROR, "syntax element unsupported: %d\n", element); + return AVERROR_PATCHWELCOME; + } + + channels = (element == TYPE_CPE) ? 2 : 1; + if ( ch + channels > alac->channels + || ff_alac_channel_layout_offsets[alac->channels - 1][ch] + channels > alac->channels + ) { + av_log(avctx, AV_LOG_ERROR, "invalid element channel count\n"); + return AVERROR_INVALIDDATA; + } + + ret = decode_element(avctx, frame, + ff_alac_channel_layout_offsets[alac->channels - 1][ch], + channels); + if (ret < 0 && get_bits_left(&alac->gb)) + return ret; + + ch += channels; + } + if (!got_end) { + av_log(avctx, AV_LOG_ERROR, "no end tag found. incomplete packet.\n"); + return AVERROR_INVALIDDATA; + } + + if (avpkt->size * 8 - get_bits_count(&alac->gb) > 8) { + av_log(avctx, AV_LOG_ERROR, "Error : %d bits left\n", + avpkt->size * 8 - get_bits_count(&alac->gb)); + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +static av_cold int alac_decode_close(AVCodecContext *avctx) +{ + ALACContext *alac = avctx->priv_data; + + int ch; + for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) { + av_freep(&alac->predict_error_buffer[ch]); + if (!alac->direct_output) + av_freep(&alac->output_samples_buffer[ch]); + av_freep(&alac->extra_bits_buffer[ch]); + } + + return 0; +} + +static int allocate_buffers(ALACContext *alac) +{ + int ch; + int buf_size; + + if (alac->max_samples_per_frame > INT_MAX / sizeof(int32_t)) + goto buf_alloc_fail; + buf_size = alac->max_samples_per_frame * sizeof(int32_t); + + for (ch = 0; ch < FFMIN(alac->channels, 2); ch++) { + FF_ALLOC_OR_GOTO(alac->avctx, alac->predict_error_buffer[ch], + buf_size, buf_alloc_fail); + + alac->direct_output = alac->sample_size > 16 && av_sample_fmt_is_planar(alac->avctx->sample_fmt); + if (!alac->direct_output) { + FF_ALLOC_OR_GOTO(alac->avctx, alac->output_samples_buffer[ch], + buf_size, buf_alloc_fail); + } + + FF_ALLOC_OR_GOTO(alac->avctx, alac->extra_bits_buffer[ch], + buf_size, buf_alloc_fail); + } + return 0; +buf_alloc_fail: + alac_decode_close(alac->avctx); + return AVERROR(ENOMEM); +} + +static int alac_set_info(ALACContext *alac) +{ + GetByteContext gb; + + bytestream2_init(&gb, alac->avctx->extradata, + alac->avctx->extradata_size); + + bytestream2_skipu(&gb, 12); // size:4, alac:4, version:4 + + alac->max_samples_per_frame = bytestream2_get_be32u(&gb); + if (!alac->max_samples_per_frame || alac->max_samples_per_frame > INT_MAX) { + av_log(alac->avctx, AV_LOG_ERROR, "max samples per frame invalid: %u\n", + alac->max_samples_per_frame); + return AVERROR_INVALIDDATA; + } + bytestream2_skipu(&gb, 1); // compatible version + alac->sample_size = bytestream2_get_byteu(&gb); + alac->rice_history_mult = bytestream2_get_byteu(&gb); + alac->rice_initial_history = bytestream2_get_byteu(&gb); + alac->rice_limit = bytestream2_get_byteu(&gb); + alac->channels = bytestream2_get_byteu(&gb); + bytestream2_get_be16u(&gb); // maxRun + bytestream2_get_be32u(&gb); // max coded frame size + bytestream2_get_be32u(&gb); // average bitrate + bytestream2_get_be32u(&gb); // samplerate + + return 0; +} + +static av_cold int alac_decode_init(AVCodecContext * avctx) +{ + int ret; + int req_packed; + ALACContext *alac = avctx->priv_data; + alac->avctx = avctx; + + /* initialize from the extradata */ + if (alac->avctx->extradata_size < ALAC_EXTRADATA_SIZE) { + av_log(avctx, AV_LOG_ERROR, "extradata is too small\n"); + return AVERROR_INVALIDDATA; + } + if (alac_set_info(alac)) { + av_log(avctx, AV_LOG_ERROR, "set_info failed\n"); + return -1; + } + + req_packed = LIBAVCODEC_VERSION_MAJOR < 55 && !av_sample_fmt_is_planar(avctx->request_sample_fmt); + switch (alac->sample_size) { + case 16: avctx->sample_fmt = req_packed ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_S16P; + break; + case 24: + case 32: avctx->sample_fmt = req_packed ? AV_SAMPLE_FMT_S32 : AV_SAMPLE_FMT_S32P; + break; + default: avpriv_request_sample(avctx, "Sample depth %d", alac->sample_size); + return AVERROR_PATCHWELCOME; + } + avctx->bits_per_raw_sample = alac->sample_size; + + if (alac->channels < 1) { + av_log(avctx, AV_LOG_WARNING, "Invalid channel count\n"); + alac->channels = avctx->channels; + } else { + if (alac->channels > ALAC_MAX_CHANNELS) + alac->channels = avctx->channels; + else + avctx->channels = alac->channels; + } + if (avctx->channels > ALAC_MAX_CHANNELS || avctx->channels <= 0 ) { + av_log(avctx, AV_LOG_ERROR, "Unsupported channel count: %d\n", + avctx->channels); + return AVERROR_PATCHWELCOME; + } + avctx->channel_layout = ff_alac_channel_layouts[alac->channels - 1]; + + if ((ret = allocate_buffers(alac)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error allocating buffers\n"); + return ret; + } + + return 0; +} + +AVCodec ff_alac_decoder = { + .name = "alac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ALAC, + .priv_data_size = sizeof(ALACContext), + .init = alac_decode_init, + .close = alac_decode_close, + .decode = alac_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), +}; diff --git a/ffmpeg/libavcodec/alac_data.c b/ffmpeg/libavcodec/alac_data.c new file mode 100644 index 0000000..0bcb06c --- /dev/null +++ b/ffmpeg/libavcodec/alac_data.c @@ -0,0 +1,56 @@ +/* + * ALAC encoder and decoder common data + * + * 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 "libavutil/channel_layout.h" +#include "alac_data.h" + +const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNELS] = { + { 0 }, + { 0, 1 }, + { 2, 0, 1 }, + { 2, 0, 1, 3 }, + { 2, 0, 1, 3, 4 }, + { 2, 0, 1, 4, 5, 3 }, + { 2, 0, 1, 4, 5, 6, 3 }, + { 2, 6, 7, 0, 1, 4, 5, 3 } +}; + +const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_6POINT1_BACK, + AV_CH_LAYOUT_7POINT1_WIDE_BACK, + 0 +}; + +const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5] = { + { TYPE_SCE, }, + { TYPE_CPE, }, + { TYPE_SCE, TYPE_CPE, }, + { TYPE_SCE, TYPE_CPE, TYPE_SCE }, + { TYPE_SCE, TYPE_CPE, TYPE_CPE, }, + { TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE, }, + { TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_SCE, }, + { TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, }, +}; diff --git a/ffmpeg/libavcodec/alac_data.h b/ffmpeg/libavcodec/alac_data.h new file mode 100644 index 0000000..650d6dc --- /dev/null +++ b/ffmpeg/libavcodec/alac_data.h @@ -0,0 +1,46 @@ +/* + * ALAC encoder and decoder common data + * + * 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 + */ + +#ifndef AVCODEC_ALAC_DATA_H +#define AVCODEC_ALAC_DATA_H + +#include + +enum AlacRawDataBlockType { + /* At the moment, only SCE, CPE, LFE, and END are recognized. */ + TYPE_SCE, + TYPE_CPE, + TYPE_CCE, + TYPE_LFE, + TYPE_DSE, + TYPE_PCE, + TYPE_FIL, + TYPE_END +}; + +#define ALAC_MAX_CHANNELS 8 + +extern const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNELS]; + +extern const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1]; + +extern const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5]; + +#endif /* AVCODEC_ALAC_DATA_H */ diff --git a/ffmpeg/libavcodec/alacenc.c b/ffmpeg/libavcodec/alacenc.c new file mode 100644 index 0000000..4ee558c --- /dev/null +++ b/ffmpeg/libavcodec/alacenc.c @@ -0,0 +1,656 @@ +/* + * ALAC audio encoder + * Copyright (c) 2008 Jaikrishnan Menon + * + * 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 "avcodec.h" +#include "put_bits.h" +#include "internal.h" +#include "lpc.h" +#include "mathops.h" +#include "alac_data.h" + +#define DEFAULT_FRAME_SIZE 4096 +#define ALAC_EXTRADATA_SIZE 36 +#define ALAC_FRAME_HEADER_SIZE 55 +#define ALAC_FRAME_FOOTER_SIZE 3 + +#define ALAC_ESCAPE_CODE 0x1FF +#define ALAC_MAX_LPC_ORDER 30 +#define DEFAULT_MAX_PRED_ORDER 6 +#define DEFAULT_MIN_PRED_ORDER 4 +#define ALAC_MAX_LPC_PRECISION 9 +#define ALAC_MAX_LPC_SHIFT 9 + +#define ALAC_CHMODE_LEFT_RIGHT 0 +#define ALAC_CHMODE_LEFT_SIDE 1 +#define ALAC_CHMODE_RIGHT_SIDE 2 +#define ALAC_CHMODE_MID_SIDE 3 + +typedef struct RiceContext { + int history_mult; + int initial_history; + int k_modifier; + int rice_modifier; +} RiceContext; + +typedef struct AlacLPCContext { + int lpc_order; + int lpc_coeff[ALAC_MAX_LPC_ORDER+1]; + int lpc_quant; +} AlacLPCContext; + +typedef struct AlacEncodeContext { + int frame_size; /**< current frame size */ + int verbatim; /**< current frame verbatim mode flag */ + int compression_level; + int min_prediction_order; + int max_prediction_order; + int max_coded_frame_size; + int write_sample_size; + int extra_bits; + int32_t sample_buf[2][DEFAULT_FRAME_SIZE]; + int32_t predictor_buf[DEFAULT_FRAME_SIZE]; + int interlacing_shift; + int interlacing_leftweight; + PutBitContext pbctx; + RiceContext rc; + AlacLPCContext lpc[2]; + LPCContext lpc_ctx; + AVCodecContext *avctx; +} AlacEncodeContext; + + +static void init_sample_buffers(AlacEncodeContext *s, int channels, + uint8_t const *samples[2]) +{ + int ch, i; + int shift = av_get_bytes_per_sample(s->avctx->sample_fmt) * 8 - + s->avctx->bits_per_raw_sample; + +#define COPY_SAMPLES(type) do { \ + for (ch = 0; ch < channels; ch++) { \ + int32_t *bptr = s->sample_buf[ch]; \ + const type *sptr = (const type *)samples[ch]; \ + for (i = 0; i < s->frame_size; i++) \ + bptr[i] = sptr[i] >> shift; \ + } \ + } while (0) + + if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S32P) + COPY_SAMPLES(int32_t); + else + COPY_SAMPLES(int16_t); +} + +static void encode_scalar(AlacEncodeContext *s, int x, + int k, int write_sample_size) +{ + int divisor, q, r; + + k = FFMIN(k, s->rc.k_modifier); + divisor = (1< 8) { + // write escape code and sample value directly + put_bits(&s->pbctx, 9, ALAC_ESCAPE_CODE); + put_bits(&s->pbctx, write_sample_size, x); + } else { + if (q) + put_bits(&s->pbctx, q, (1<pbctx, 1, 0); + + if (k != 1) { + if (r > 0) + put_bits(&s->pbctx, k, r+1); + else + put_bits(&s->pbctx, k-1, 0); + } + } +} + +static void write_element_header(AlacEncodeContext *s, + enum AlacRawDataBlockType element, + int instance) +{ + int encode_fs = 0; + + if (s->frame_size < DEFAULT_FRAME_SIZE) + encode_fs = 1; + + put_bits(&s->pbctx, 3, element); // element type + put_bits(&s->pbctx, 4, instance); // element instance + put_bits(&s->pbctx, 12, 0); // unused header bits + put_bits(&s->pbctx, 1, encode_fs); // Sample count is in the header + put_bits(&s->pbctx, 2, s->extra_bits >> 3); // Extra bytes (for 24-bit) + put_bits(&s->pbctx, 1, s->verbatim); // Audio block is verbatim + if (encode_fs) + put_bits32(&s->pbctx, s->frame_size); // No. of samples in the frame +} + +static void calc_predictor_params(AlacEncodeContext *s, int ch) +{ + int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER]; + int shift[MAX_LPC_ORDER]; + int opt_order; + + if (s->compression_level == 1) { + s->lpc[ch].lpc_order = 6; + s->lpc[ch].lpc_quant = 6; + s->lpc[ch].lpc_coeff[0] = 160; + s->lpc[ch].lpc_coeff[1] = -190; + s->lpc[ch].lpc_coeff[2] = 170; + s->lpc[ch].lpc_coeff[3] = -130; + s->lpc[ch].lpc_coeff[4] = 80; + s->lpc[ch].lpc_coeff[5] = -25; + } else { + opt_order = ff_lpc_calc_coefs(&s->lpc_ctx, s->sample_buf[ch], + s->frame_size, + s->min_prediction_order, + s->max_prediction_order, + ALAC_MAX_LPC_PRECISION, coefs, shift, + FF_LPC_TYPE_LEVINSON, 0, + ORDER_METHOD_EST, ALAC_MAX_LPC_SHIFT, 1); + + s->lpc[ch].lpc_order = opt_order; + s->lpc[ch].lpc_quant = shift[opt_order-1]; + memcpy(s->lpc[ch].lpc_coeff, coefs[opt_order-1], opt_order*sizeof(int)); + } +} + +static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n) +{ + int i, best; + int32_t lt, rt; + uint64_t sum[4]; + uint64_t score[4]; + + /* calculate sum of 2nd order residual for each channel */ + sum[0] = sum[1] = sum[2] = sum[3] = 0; + for (i = 2; i < n; i++) { + lt = left_ch[i] - 2 * left_ch[i - 1] + left_ch[i - 2]; + rt = right_ch[i] - 2 * right_ch[i - 1] + right_ch[i - 2]; + sum[2] += FFABS((lt + rt) >> 1); + sum[3] += FFABS(lt - rt); + sum[0] += FFABS(lt); + sum[1] += FFABS(rt); + } + + /* calculate score for each mode */ + score[0] = sum[0] + sum[1]; + score[1] = sum[0] + sum[3]; + score[2] = sum[1] + sum[3]; + score[3] = sum[2] + sum[3]; + + /* return mode with lowest score */ + best = 0; + for (i = 1; i < 4; i++) { + if (score[i] < score[best]) + best = i; + } + return best; +} + +static void alac_stereo_decorrelation(AlacEncodeContext *s) +{ + int32_t *left = s->sample_buf[0], *right = s->sample_buf[1]; + int i, mode, n = s->frame_size; + int32_t tmp; + + mode = estimate_stereo_mode(left, right, n); + + switch (mode) { + case ALAC_CHMODE_LEFT_RIGHT: + s->interlacing_leftweight = 0; + s->interlacing_shift = 0; + break; + case ALAC_CHMODE_LEFT_SIDE: + for (i = 0; i < n; i++) + right[i] = left[i] - right[i]; + s->interlacing_leftweight = 1; + s->interlacing_shift = 0; + break; + case ALAC_CHMODE_RIGHT_SIDE: + for (i = 0; i < n; i++) { + tmp = right[i]; + right[i] = left[i] - right[i]; + left[i] = tmp + (right[i] >> 31); + } + s->interlacing_leftweight = 1; + s->interlacing_shift = 31; + break; + default: + for (i = 0; i < n; i++) { + tmp = left[i]; + left[i] = (tmp + right[i]) >> 1; + right[i] = tmp - right[i]; + } + s->interlacing_leftweight = 1; + s->interlacing_shift = 1; + break; + } +} + +static void alac_linear_predictor(AlacEncodeContext *s, int ch) +{ + int i; + AlacLPCContext lpc = s->lpc[ch]; + + if (lpc.lpc_order == 31) { + s->predictor_buf[0] = s->sample_buf[ch][0]; + + for (i = 1; i < s->frame_size; i++) { + s->predictor_buf[i] = s->sample_buf[ch][i ] - + s->sample_buf[ch][i - 1]; + } + + return; + } + + // generalised linear predictor + + if (lpc.lpc_order > 0) { + int32_t *samples = s->sample_buf[ch]; + int32_t *residual = s->predictor_buf; + + // generate warm-up samples + residual[0] = samples[0]; + for (i = 1; i <= lpc.lpc_order; i++) + residual[i] = samples[i] - samples[i-1]; + + // perform lpc on remaining samples + for (i = lpc.lpc_order + 1; i < s->frame_size; i++) { + int sum = 1 << (lpc.lpc_quant - 1), res_val, j; + + for (j = 0; j < lpc.lpc_order; j++) { + sum += (samples[lpc.lpc_order-j] - samples[0]) * + lpc.lpc_coeff[j]; + } + + sum >>= lpc.lpc_quant; + sum += samples[0]; + residual[i] = sign_extend(samples[lpc.lpc_order+1] - sum, + s->write_sample_size); + res_val = residual[i]; + + if (res_val) { + int index = lpc.lpc_order - 1; + int neg = (res_val < 0); + + while (index >= 0 && (neg ? (res_val < 0) : (res_val > 0))) { + int val = samples[0] - samples[lpc.lpc_order - index]; + int sign = (val ? FFSIGN(val) : 0); + + if (neg) + sign *= -1; + + lpc.lpc_coeff[index] -= sign; + val *= sign; + res_val -= (val >> lpc.lpc_quant) * (lpc.lpc_order - index); + index--; + } + } + samples++; + } + } +} + +static void alac_entropy_coder(AlacEncodeContext *s) +{ + unsigned int history = s->rc.initial_history; + int sign_modifier = 0, i, k; + int32_t *samples = s->predictor_buf; + + for (i = 0; i < s->frame_size;) { + int x; + + k = av_log2((history >> 9) + 3); + + x = -2 * (*samples) -1; + x ^= x >> 31; + + samples++; + i++; + + encode_scalar(s, x - sign_modifier, k, s->write_sample_size); + + history += x * s->rc.history_mult - + ((history * s->rc.history_mult) >> 9); + + sign_modifier = 0; + if (x > 0xFFFF) + history = 0xFFFF; + + if (history < 128 && i < s->frame_size) { + unsigned int block_size = 0; + + k = 7 - av_log2(history) + ((history + 16) >> 6); + + while (*samples == 0 && i < s->frame_size) { + samples++; + i++; + block_size++; + } + encode_scalar(s, block_size, k, 16); + sign_modifier = (block_size <= 0xFFFF); + history = 0; + } + + } +} + +static void write_element(AlacEncodeContext *s, + enum AlacRawDataBlockType element, int instance, + const uint8_t *samples0, const uint8_t *samples1) +{ + uint8_t const *samples[2] = { samples0, samples1 }; + int i, j, channels; + int prediction_type = 0; + PutBitContext *pb = &s->pbctx; + + channels = element == TYPE_CPE ? 2 : 1; + + if (s->verbatim) { + write_element_header(s, element, instance); + /* samples are channel-interleaved in verbatim mode */ + if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S32P) { + int shift = 32 - s->avctx->bits_per_raw_sample; + int32_t const *samples_s32[2] = { (const int32_t *)samples0, + (const int32_t *)samples1 }; + for (i = 0; i < s->frame_size; i++) + for (j = 0; j < channels; j++) + put_sbits(pb, s->avctx->bits_per_raw_sample, + samples_s32[j][i] >> shift); + } else { + int16_t const *samples_s16[2] = { (const int16_t *)samples0, + (const int16_t *)samples1 }; + for (i = 0; i < s->frame_size; i++) + for (j = 0; j < channels; j++) + put_sbits(pb, s->avctx->bits_per_raw_sample, + samples_s16[j][i]); + } + } else { + s->write_sample_size = s->avctx->bits_per_raw_sample - s->extra_bits + + channels - 1; + + init_sample_buffers(s, channels, samples); + write_element_header(s, element, instance); + + if (channels == 2) + alac_stereo_decorrelation(s); + else + s->interlacing_shift = s->interlacing_leftweight = 0; + put_bits(pb, 8, s->interlacing_shift); + put_bits(pb, 8, s->interlacing_leftweight); + + for (i = 0; i < channels; i++) { + calc_predictor_params(s, i); + + put_bits(pb, 4, prediction_type); + put_bits(pb, 4, s->lpc[i].lpc_quant); + + put_bits(pb, 3, s->rc.rice_modifier); + put_bits(pb, 5, s->lpc[i].lpc_order); + // predictor coeff. table + for (j = 0; j < s->lpc[i].lpc_order; j++) + put_sbits(pb, 16, s->lpc[i].lpc_coeff[j]); + } + + // write extra bits if needed + if (s->extra_bits) { + uint32_t mask = (1 << s->extra_bits) - 1; + for (i = 0; i < s->frame_size; i++) { + for (j = 0; j < channels; j++) { + put_bits(pb, s->extra_bits, s->sample_buf[j][i] & mask); + s->sample_buf[j][i] >>= s->extra_bits; + } + } + } + + // apply lpc and entropy coding to audio samples + for (i = 0; i < channels; i++) { + alac_linear_predictor(s, i); + + // TODO: determine when this will actually help. for now it's not used. + if (prediction_type == 15) { + // 2nd pass 1st order filter + for (j = s->frame_size - 1; j > 0; j--) + s->predictor_buf[j] -= s->predictor_buf[j - 1]; + } + alac_entropy_coder(s); + } + } +} + +static int write_frame(AlacEncodeContext *s, AVPacket *avpkt, + uint8_t * const *samples) +{ + PutBitContext *pb = &s->pbctx; + const enum AlacRawDataBlockType *ch_elements = ff_alac_channel_elements[s->avctx->channels - 1]; + const uint8_t *ch_map = ff_alac_channel_layout_offsets[s->avctx->channels - 1]; + int ch, element, sce, cpe; + + init_put_bits(pb, avpkt->data, avpkt->size); + + ch = element = sce = cpe = 0; + while (ch < s->avctx->channels) { + if (ch_elements[element] == TYPE_CPE) { + write_element(s, TYPE_CPE, cpe, samples[ch_map[ch]], + samples[ch_map[ch + 1]]); + cpe++; + ch += 2; + } else { + write_element(s, TYPE_SCE, sce, samples[ch_map[ch]], NULL); + sce++; + ch++; + } + element++; + } + + put_bits(pb, 3, TYPE_END); + flush_put_bits(pb); + + return put_bits_count(pb) >> 3; +} + +static av_always_inline int get_max_frame_size(int frame_size, int ch, int bps) +{ + int header_bits = 23 + 32 * (frame_size < DEFAULT_FRAME_SIZE); + return FFALIGN(header_bits + bps * ch * frame_size + 3, 8) / 8; +} + +static av_cold int alac_encode_close(AVCodecContext *avctx) +{ + AlacEncodeContext *s = avctx->priv_data; + ff_lpc_end(&s->lpc_ctx); + av_freep(&avctx->extradata); + avctx->extradata_size = 0; + av_freep(&avctx->coded_frame); + return 0; +} + +static av_cold int alac_encode_init(AVCodecContext *avctx) +{ + AlacEncodeContext *s = avctx->priv_data; + int ret; + uint8_t *alac_extradata; + + avctx->frame_size = s->frame_size = DEFAULT_FRAME_SIZE; + + if (avctx->sample_fmt == AV_SAMPLE_FMT_S32P) { + if (avctx->bits_per_raw_sample != 24) + av_log(avctx, AV_LOG_WARNING, "encoding as 24 bits-per-sample\n"); + avctx->bits_per_raw_sample = 24; + } else { + avctx->bits_per_raw_sample = 16; + s->extra_bits = 0; + } + + // Set default compression level + if (avctx->compression_level == FF_COMPRESSION_DEFAULT) + s->compression_level = 2; + else + s->compression_level = av_clip(avctx->compression_level, 0, 2); + + // Initialize default Rice parameters + s->rc.history_mult = 40; + s->rc.initial_history = 10; + s->rc.k_modifier = 14; + s->rc.rice_modifier = 4; + + s->max_coded_frame_size = get_max_frame_size(avctx->frame_size, + avctx->channels, + avctx->bits_per_raw_sample); + + avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + ret = AVERROR(ENOMEM); + goto error; + } + avctx->extradata_size = ALAC_EXTRADATA_SIZE; + + alac_extradata = avctx->extradata; + AV_WB32(alac_extradata, ALAC_EXTRADATA_SIZE); + AV_WB32(alac_extradata+4, MKBETAG('a','l','a','c')); + AV_WB32(alac_extradata+12, avctx->frame_size); + AV_WB8 (alac_extradata+17, avctx->bits_per_raw_sample); + AV_WB8 (alac_extradata+21, avctx->channels); + AV_WB32(alac_extradata+24, s->max_coded_frame_size); + AV_WB32(alac_extradata+28, + avctx->sample_rate * avctx->channels * avctx->bits_per_raw_sample); // average bitrate + AV_WB32(alac_extradata+32, avctx->sample_rate); + + // Set relevant extradata fields + if (s->compression_level > 0) { + AV_WB8(alac_extradata+18, s->rc.history_mult); + AV_WB8(alac_extradata+19, s->rc.initial_history); + AV_WB8(alac_extradata+20, s->rc.k_modifier); + } + + s->min_prediction_order = DEFAULT_MIN_PRED_ORDER; + if (avctx->min_prediction_order >= 0) { + if (avctx->min_prediction_order < MIN_LPC_ORDER || + avctx->min_prediction_order > ALAC_MAX_LPC_ORDER) { + av_log(avctx, AV_LOG_ERROR, "invalid min prediction order: %d\n", + avctx->min_prediction_order); + ret = AVERROR(EINVAL); + goto error; + } + + s->min_prediction_order = avctx->min_prediction_order; + } + + s->max_prediction_order = DEFAULT_MAX_PRED_ORDER; + if (avctx->max_prediction_order >= 0) { + if (avctx->max_prediction_order < MIN_LPC_ORDER || + avctx->max_prediction_order > ALAC_MAX_LPC_ORDER) { + av_log(avctx, AV_LOG_ERROR, "invalid max prediction order: %d\n", + avctx->max_prediction_order); + ret = AVERROR(EINVAL); + goto error; + } + + s->max_prediction_order = avctx->max_prediction_order; + } + + if (s->max_prediction_order < s->min_prediction_order) { + av_log(avctx, AV_LOG_ERROR, + "invalid prediction orders: min=%d max=%d\n", + s->min_prediction_order, s->max_prediction_order); + ret = AVERROR(EINVAL); + goto error; + } + + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) { + ret = AVERROR(ENOMEM); + goto error; + } + + s->avctx = avctx; + + if ((ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size, + s->max_prediction_order, + FF_LPC_TYPE_LEVINSON)) < 0) { + goto error; + } + + return 0; +error: + alac_encode_close(avctx); + return ret; +} + +static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AlacEncodeContext *s = avctx->priv_data; + int out_bytes, max_frame_size, ret; + + s->frame_size = frame->nb_samples; + + if (frame->nb_samples < DEFAULT_FRAME_SIZE) + max_frame_size = get_max_frame_size(s->frame_size, avctx->channels, + avctx->bits_per_raw_sample); + else + max_frame_size = s->max_coded_frame_size; + + if ((ret = ff_alloc_packet2(avctx, avpkt, 2 * max_frame_size)) < 0) + return ret; + + /* use verbatim mode for compression_level 0 */ + if (s->compression_level) { + s->verbatim = 0; + s->extra_bits = avctx->bits_per_raw_sample - 16; + } else { + s->verbatim = 1; + s->extra_bits = 0; + } + + out_bytes = write_frame(s, avpkt, frame->extended_data); + + if (out_bytes > max_frame_size) { + /* frame too large. use verbatim mode */ + s->verbatim = 1; + s->extra_bits = 0; + out_bytes = write_frame(s, avpkt, frame->extended_data); + } + + avpkt->size = out_bytes; + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_alac_encoder = { + .name = "alac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ALAC, + .priv_data_size = sizeof(AlacEncodeContext), + .init = alac_encode_init, + .encode2 = alac_encode_frame, + .close = alac_encode_close, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .channel_layouts = ff_alac_channel_layouts, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), +}; diff --git a/ffmpeg/libavcodec/allcodecs.c b/ffmpeg/libavcodec/allcodecs.c new file mode 100644 index 0000000..1eaf2d3 --- /dev/null +++ b/ffmpeg/libavcodec/allcodecs.c @@ -0,0 +1,553 @@ +/* + * Provide registration of all codecs, parsers and bitstream filters for libavcodec. + * Copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Provide registration of all codecs, parsers and bitstream filters for libavcodec. + */ + +#include "avcodec.h" +#include "config.h" + +#define REGISTER_HWACCEL(X, x) \ + { \ + extern AVHWAccel ff_##x##_hwaccel; \ + if (CONFIG_##X##_HWACCEL) \ + av_register_hwaccel(&ff_##x##_hwaccel); \ + } + +#define REGISTER_ENCODER(X, x) \ + { \ + extern AVCodec ff_##x##_encoder; \ + if (CONFIG_##X##_ENCODER) \ + avcodec_register(&ff_##x##_encoder); \ + } + +#define REGISTER_DECODER(X, x) \ + { \ + extern AVCodec ff_##x##_decoder; \ + if (CONFIG_##X##_DECODER) \ + avcodec_register(&ff_##x##_decoder); \ + } + +#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x) + +#define REGISTER_PARSER(X, x) \ + { \ + extern AVCodecParser ff_##x##_parser; \ + if (CONFIG_##X##_PARSER) \ + av_register_codec_parser(&ff_##x##_parser); \ + } + +#define REGISTER_BSF(X, x) \ + { \ + extern AVBitStreamFilter ff_##x##_bsf; \ + if (CONFIG_##X##_BSF) \ + av_register_bitstream_filter(&ff_##x##_bsf); \ + } + +void avcodec_register_all(void) +{ + static int initialized; + + if (initialized) + return; + initialized = 1; + + /* hardware accelerators */ + REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); + REGISTER_HWACCEL(H263_VDPAU, h263_vdpau); + REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); + REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); + REGISTER_HWACCEL(H264_VDA, h264_vda); + REGISTER_HWACCEL(H264_VDPAU, h264_vdpau); + REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau); + REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2); + REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi); + REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau); + REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); + REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); + REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); + REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); + REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau); + REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2); + REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi); + REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau); + + /* video codecs */ + REGISTER_ENCODER(A64MULTI, a64multi); + REGISTER_ENCODER(A64MULTI5, a64multi5); + REGISTER_DECODER(AASC, aasc); + REGISTER_ENCDEC (AMV, amv); + REGISTER_DECODER(ANM, anm); + REGISTER_DECODER(ANSI, ansi); + REGISTER_ENCDEC (ASV1, asv1); + REGISTER_ENCDEC (ASV2, asv2); + REGISTER_DECODER(AURA, aura); + REGISTER_DECODER(AURA2, aura2); + REGISTER_ENCDEC (AVRP, avrp); + REGISTER_DECODER(AVRN, avrn); + REGISTER_DECODER(AVS, avs); + REGISTER_ENCDEC (AVUI, avui); + REGISTER_ENCDEC (AYUV, ayuv); + REGISTER_DECODER(BETHSOFTVID, bethsoftvid); + REGISTER_DECODER(BFI, bfi); + REGISTER_DECODER(BINK, bink); + REGISTER_ENCDEC (BMP, bmp); + REGISTER_DECODER(BMV_VIDEO, bmv_video); + REGISTER_DECODER(BRENDER_PIX, brender_pix); + REGISTER_DECODER(C93, c93); + REGISTER_DECODER(CAVS, cavs); + REGISTER_DECODER(CDGRAPHICS, cdgraphics); + REGISTER_DECODER(CDXL, cdxl); + REGISTER_DECODER(CINEPAK, cinepak); + REGISTER_ENCDEC (CLJR, cljr); + REGISTER_DECODER(CLLC, cllc); + REGISTER_ENCDEC (COMFORTNOISE, comfortnoise); + REGISTER_DECODER(CPIA, cpia); + REGISTER_DECODER(CSCD, cscd); + REGISTER_DECODER(CYUV, cyuv); + REGISTER_DECODER(DFA, dfa); + REGISTER_DECODER(DIRAC, dirac); + REGISTER_ENCDEC (DNXHD, dnxhd); + REGISTER_ENCDEC (DPX, dpx); + REGISTER_DECODER(DSICINVIDEO, dsicinvideo); + REGISTER_ENCDEC (DVVIDEO, dvvideo); + REGISTER_DECODER(DXA, dxa); + REGISTER_DECODER(DXTORY, dxtory); + REGISTER_DECODER(EACMV, eacmv); + REGISTER_DECODER(EAMAD, eamad); + REGISTER_DECODER(EATGQ, eatgq); + REGISTER_DECODER(EATGV, eatgv); + REGISTER_DECODER(EATQI, eatqi); + REGISTER_DECODER(EIGHTBPS, eightbps); + REGISTER_DECODER(EIGHTSVX_EXP, eightsvx_exp); + REGISTER_DECODER(EIGHTSVX_FIB, eightsvx_fib); + REGISTER_DECODER(ESCAPE124, escape124); + REGISTER_DECODER(ESCAPE130, escape130); + REGISTER_DECODER(EXR, exr); + REGISTER_ENCDEC (FFV1, ffv1); + REGISTER_ENCDEC (FFVHUFF, ffvhuff); + REGISTER_ENCDEC (FLASHSV, flashsv); + REGISTER_ENCDEC (FLASHSV2, flashsv2); + REGISTER_DECODER(FLIC, flic); + REGISTER_ENCDEC (FLV, flv); + REGISTER_DECODER(FOURXM, fourxm); + REGISTER_DECODER(FRAPS, fraps); + REGISTER_DECODER(FRWU, frwu); + REGISTER_ENCDEC (GIF, gif); + REGISTER_ENCDEC (H261, h261); + REGISTER_ENCDEC (H263, h263); + REGISTER_DECODER(H263I, h263i); + REGISTER_ENCDEC (H263P, h263p); + REGISTER_DECODER(H264, h264); + REGISTER_DECODER(H264_CRYSTALHD, h264_crystalhd); + REGISTER_DECODER(H264_VDA, h264_vda); + REGISTER_DECODER(H264_VDPAU, h264_vdpau); + REGISTER_ENCDEC (HUFFYUV, huffyuv); + REGISTER_DECODER(IDCIN, idcin); + REGISTER_DECODER(IFF_BYTERUN1, iff_byterun1); + REGISTER_DECODER(IFF_ILBM, iff_ilbm); + REGISTER_DECODER(INDEO2, indeo2); + REGISTER_DECODER(INDEO3, indeo3); + REGISTER_DECODER(INDEO4, indeo4); + REGISTER_DECODER(INDEO5, indeo5); + REGISTER_DECODER(INTERPLAY_VIDEO, interplay_video); + REGISTER_ENCDEC (JPEG2000, jpeg2000); + REGISTER_ENCDEC (JPEGLS, jpegls); + REGISTER_DECODER(JV, jv); + REGISTER_DECODER(KGV1, kgv1); + REGISTER_DECODER(KMVC, kmvc); + REGISTER_DECODER(LAGARITH, lagarith); + REGISTER_ENCODER(LJPEG, ljpeg); + REGISTER_DECODER(LOCO, loco); + REGISTER_DECODER(MDEC, mdec); + REGISTER_DECODER(MIMIC, mimic); + REGISTER_ENCDEC (MJPEG, mjpeg); + REGISTER_DECODER(MJPEGB, mjpegb); + REGISTER_DECODER(MMVIDEO, mmvideo); + REGISTER_DECODER(MOTIONPIXELS, motionpixels); + REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc); + REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video); + REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video); + REGISTER_ENCDEC (MPEG4, mpeg4); + REGISTER_DECODER(MPEG4_CRYSTALHD, mpeg4_crystalhd); + REGISTER_DECODER(MPEG4_VDPAU, mpeg4_vdpau); + REGISTER_DECODER(MPEGVIDEO, mpegvideo); + REGISTER_DECODER(MPEG_VDPAU, mpeg_vdpau); + REGISTER_DECODER(MPEG1_VDPAU, mpeg1_vdpau); + REGISTER_DECODER(MPEG2_CRYSTALHD, mpeg2_crystalhd); + REGISTER_DECODER(MSA1, msa1); + REGISTER_DECODER(MSMPEG4_CRYSTALHD, msmpeg4_crystalhd); + REGISTER_DECODER(MSMPEG4V1, msmpeg4v1); + REGISTER_ENCDEC (MSMPEG4V2, msmpeg4v2); + REGISTER_ENCDEC (MSMPEG4V3, msmpeg4v3); + REGISTER_DECODER(MSRLE, msrle); + REGISTER_DECODER(MSS1, mss1); + REGISTER_DECODER(MSS2, mss2); + REGISTER_ENCDEC (MSVIDEO1, msvideo1); + REGISTER_DECODER(MSZH, mszh); + REGISTER_DECODER(MTS2, mts2); + REGISTER_DECODER(MVC1, mvc1); + REGISTER_DECODER(MVC2, mvc2); + REGISTER_DECODER(MXPEG, mxpeg); + REGISTER_DECODER(NUV, nuv); + REGISTER_DECODER(PAF_VIDEO, paf_video); + REGISTER_ENCDEC (PAM, pam); + REGISTER_ENCDEC (PBM, pbm); + REGISTER_ENCDEC (PCX, pcx); + REGISTER_ENCDEC (PGM, pgm); + REGISTER_ENCDEC (PGMYUV, pgmyuv); + REGISTER_DECODER(PICTOR, pictor); + REGISTER_ENCDEC (PNG, png); + REGISTER_ENCDEC (PPM, ppm); + REGISTER_ENCDEC (PRORES, prores); + REGISTER_ENCODER(PRORES_ANATOLIY, prores_anatoliy); + REGISTER_ENCODER(PRORES_KOSTYA, prores_kostya); + REGISTER_DECODER(PRORES_LGPL, prores_lgpl); + REGISTER_DECODER(PTX, ptx); + REGISTER_DECODER(QDRAW, qdraw); + REGISTER_DECODER(QPEG, qpeg); + REGISTER_ENCDEC (QTRLE, qtrle); + REGISTER_ENCDEC (R10K, r10k); + REGISTER_ENCDEC (R210, r210); + REGISTER_ENCDEC (RAWVIDEO, rawvideo); + REGISTER_DECODER(RL2, rl2); + REGISTER_ENCDEC (ROQ, roq); + REGISTER_DECODER(RPZA, rpza); + REGISTER_ENCDEC (RV10, rv10); + REGISTER_ENCDEC (RV20, rv20); + REGISTER_DECODER(RV30, rv30); + REGISTER_DECODER(RV40, rv40); + REGISTER_DECODER(S302M, s302m); + REGISTER_DECODER(SANM, sanm); + REGISTER_ENCDEC (SGI, sgi); + REGISTER_DECODER(SGIRLE, sgirle); + REGISTER_DECODER(SMACKER, smacker); + REGISTER_DECODER(SMC, smc); + REGISTER_ENCDEC (SNOW, snow); + REGISTER_DECODER(SP5X, sp5x); + REGISTER_ENCDEC (SUNRAST, sunrast); + REGISTER_ENCDEC (SVQ1, svq1); + REGISTER_DECODER(SVQ3, svq3); + REGISTER_ENCDEC (TARGA, targa); + REGISTER_DECODER(TARGA_Y216, targa_y216); + REGISTER_DECODER(THEORA, theora); + REGISTER_DECODER(THP, thp); + REGISTER_DECODER(TIERTEXSEQVIDEO, tiertexseqvideo); + REGISTER_ENCDEC (TIFF, tiff); + REGISTER_DECODER(TMV, tmv); + REGISTER_DECODER(TRUEMOTION1, truemotion1); + REGISTER_DECODER(TRUEMOTION2, truemotion2); + REGISTER_DECODER(TSCC, tscc); + REGISTER_DECODER(TSCC2, tscc2); + REGISTER_DECODER(TXD, txd); + REGISTER_DECODER(ULTI, ulti); + REGISTER_ENCDEC (UTVIDEO, utvideo); + REGISTER_ENCDEC (V210, v210); + REGISTER_DECODER(V210X, v210x); + REGISTER_ENCDEC (V308, v308); + REGISTER_ENCDEC (V408, v408); + REGISTER_ENCDEC (V410, v410); + REGISTER_DECODER(VB, vb); + REGISTER_DECODER(VBLE, vble); + REGISTER_DECODER(VC1, vc1); + REGISTER_DECODER(VC1_CRYSTALHD, vc1_crystalhd); + REGISTER_DECODER(VC1_VDPAU, vc1_vdpau); + REGISTER_DECODER(VC1IMAGE, vc1image); + REGISTER_DECODER(VCR1, vcr1); + REGISTER_DECODER(VMDVIDEO, vmdvideo); + REGISTER_DECODER(VMNC, vmnc); + REGISTER_DECODER(VP3, vp3); + REGISTER_DECODER(VP5, vp5); + REGISTER_DECODER(VP6, vp6); + REGISTER_DECODER(VP6A, vp6a); + REGISTER_DECODER(VP6F, vp6f); + REGISTER_DECODER(VP8, vp8); + REGISTER_DECODER(VQA, vqa); + REGISTER_ENCDEC (WMV1, wmv1); + REGISTER_ENCDEC (WMV2, wmv2); + REGISTER_DECODER(WMV3, wmv3); + REGISTER_DECODER(WMV3_CRYSTALHD, wmv3_crystalhd); + REGISTER_DECODER(WMV3_VDPAU, wmv3_vdpau); + REGISTER_DECODER(WMV3IMAGE, wmv3image); + REGISTER_DECODER(WNV1, wnv1); + REGISTER_DECODER(XAN_WC3, xan_wc3); + REGISTER_DECODER(XAN_WC4, xan_wc4); + REGISTER_ENCDEC (XBM, xbm); + REGISTER_ENCDEC (XFACE, xface); + REGISTER_DECODER(XL, xl); + REGISTER_ENCDEC (XWD, xwd); + REGISTER_ENCDEC (Y41P, y41p); + REGISTER_DECODER(YOP, yop); + REGISTER_ENCDEC (YUV4, yuv4); + REGISTER_DECODER(ZERO12V, zero12v); + REGISTER_DECODER(ZEROCODEC, zerocodec); + REGISTER_ENCDEC (ZLIB, zlib); + REGISTER_ENCDEC (ZMBV, zmbv); + + /* audio codecs */ + REGISTER_ENCDEC (AAC, aac); + REGISTER_DECODER(AAC_LATM, aac_latm); + REGISTER_ENCDEC (AC3, ac3); + REGISTER_ENCODER(AC3_FIXED, ac3_fixed); + REGISTER_ENCDEC (ALAC, alac); + REGISTER_DECODER(ALS, als); + REGISTER_DECODER(AMRNB, amrnb); + REGISTER_DECODER(AMRWB, amrwb); + REGISTER_DECODER(APE, ape); + REGISTER_DECODER(ATRAC1, atrac1); + REGISTER_DECODER(ATRAC3, atrac3); + REGISTER_DECODER(BINKAUDIO_DCT, binkaudio_dct); + REGISTER_DECODER(BINKAUDIO_RDFT, binkaudio_rdft); + REGISTER_DECODER(BMV_AUDIO, bmv_audio); + REGISTER_DECODER(COOK, cook); + REGISTER_ENCDEC (DCA, dca); + REGISTER_DECODER(DSICINAUDIO, dsicinaudio); + REGISTER_ENCDEC (EAC3, eac3); + REGISTER_DECODER(EVRC, evrc); + REGISTER_DECODER(FFWAVESYNTH, ffwavesynth); + REGISTER_ENCDEC (FLAC, flac); + REGISTER_ENCDEC (G723_1, g723_1); + REGISTER_DECODER(G729, g729); + REGISTER_DECODER(GSM, gsm); + REGISTER_DECODER(GSM_MS, gsm_ms); + REGISTER_DECODER(IAC, iac); + REGISTER_DECODER(IMC, imc); + REGISTER_DECODER(MACE3, mace3); + REGISTER_DECODER(MACE6, mace6); + REGISTER_DECODER(MLP, mlp); + REGISTER_DECODER(MP1, mp1); + REGISTER_DECODER(MP1FLOAT, mp1float); + REGISTER_ENCDEC (MP2, mp2); + REGISTER_DECODER(MP2FLOAT, mp2float); + REGISTER_DECODER(MP3, mp3); + REGISTER_DECODER(MP3FLOAT, mp3float); + REGISTER_DECODER(MP3ADU, mp3adu); + REGISTER_DECODER(MP3ADUFLOAT, mp3adufloat); + REGISTER_DECODER(MP3ON4, mp3on4); + REGISTER_DECODER(MP3ON4FLOAT, mp3on4float); + REGISTER_DECODER(MPC7, mpc7); + REGISTER_DECODER(MPC8, mpc8); + REGISTER_ENCDEC (NELLYMOSER, nellymoser); + REGISTER_DECODER(PAF_AUDIO, paf_audio); + REGISTER_DECODER(QCELP, qcelp); + REGISTER_DECODER(QDM2, qdm2); + REGISTER_ENCDEC (RA_144, ra_144); + REGISTER_DECODER(RA_288, ra_288); + REGISTER_DECODER(RALF, ralf); + REGISTER_DECODER(SHORTEN, shorten); + REGISTER_DECODER(SIPR, sipr); + REGISTER_DECODER(SMACKAUD, smackaud); + REGISTER_ENCDEC (SONIC, sonic); + REGISTER_ENCODER(SONIC_LS, sonic_ls); + REGISTER_DECODER(TAK, tak); + REGISTER_DECODER(TRUEHD, truehd); + REGISTER_DECODER(TRUESPEECH, truespeech); + REGISTER_DECODER(TTA, tta); + REGISTER_DECODER(TWINVQ, twinvq); + REGISTER_DECODER(VMDAUDIO, vmdaudio); + REGISTER_ENCDEC (VORBIS, vorbis); + REGISTER_DECODER(WAVPACK, wavpack); + REGISTER_DECODER(WMALOSSLESS, wmalossless); + REGISTER_DECODER(WMAPRO, wmapro); + REGISTER_ENCDEC (WMAV1, wmav1); + REGISTER_ENCDEC (WMAV2, wmav2); + REGISTER_DECODER(WMAVOICE, wmavoice); + REGISTER_DECODER(WS_SND1, ws_snd1); + + /* PCM codecs */ + REGISTER_ENCDEC (PCM_ALAW, pcm_alaw); + REGISTER_DECODER(PCM_BLURAY, pcm_bluray); + REGISTER_DECODER(PCM_DVD, pcm_dvd); + REGISTER_ENCDEC (PCM_F32BE, pcm_f32be); + REGISTER_ENCDEC (PCM_F32LE, pcm_f32le); + REGISTER_ENCDEC (PCM_F64BE, pcm_f64be); + REGISTER_ENCDEC (PCM_F64LE, pcm_f64le); + REGISTER_DECODER(PCM_LXF, pcm_lxf); + REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw); + REGISTER_ENCDEC (PCM_S8, pcm_s8); + REGISTER_ENCDEC (PCM_S8_PLANAR, pcm_s8_planar); + REGISTER_ENCDEC (PCM_S16BE, pcm_s16be); + REGISTER_ENCDEC (PCM_S16BE_PLANAR, pcm_s16be_planar); + REGISTER_ENCDEC (PCM_S16LE, pcm_s16le); + REGISTER_ENCDEC (PCM_S16LE_PLANAR, pcm_s16le_planar); + REGISTER_ENCDEC (PCM_S24BE, pcm_s24be); + REGISTER_ENCDEC (PCM_S24DAUD, pcm_s24daud); + REGISTER_ENCDEC (PCM_S24LE, pcm_s24le); + REGISTER_ENCDEC (PCM_S24LE_PLANAR, pcm_s24le_planar); + REGISTER_ENCDEC (PCM_S32BE, pcm_s32be); + REGISTER_ENCDEC (PCM_S32LE, pcm_s32le); + REGISTER_ENCDEC (PCM_S32LE_PLANAR, pcm_s32le_planar); + REGISTER_ENCDEC (PCM_U8, pcm_u8); + REGISTER_ENCDEC (PCM_U16BE, pcm_u16be); + REGISTER_ENCDEC (PCM_U16LE, pcm_u16le); + REGISTER_ENCDEC (PCM_U24BE, pcm_u24be); + REGISTER_ENCDEC (PCM_U24LE, pcm_u24le); + REGISTER_ENCDEC (PCM_U32BE, pcm_u32be); + REGISTER_ENCDEC (PCM_U32LE, pcm_u32le); + REGISTER_DECODER(PCM_ZORK, pcm_zork); + + /* DPCM codecs */ + REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm); + REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm); + REGISTER_DECODER(SOL_DPCM, sol_dpcm); + REGISTER_DECODER(XAN_DPCM, xan_dpcm); + + /* ADPCM codecs */ + REGISTER_DECODER(ADPCM_4XM, adpcm_4xm); + REGISTER_ENCDEC (ADPCM_ADX, adpcm_adx); + REGISTER_DECODER(ADPCM_AFC, adpcm_afc); + REGISTER_DECODER(ADPCM_CT, adpcm_ct); + REGISTER_DECODER(ADPCM_EA, adpcm_ea); + REGISTER_DECODER(ADPCM_EA_MAXIS_XA, adpcm_ea_maxis_xa); + REGISTER_DECODER(ADPCM_EA_R1, adpcm_ea_r1); + REGISTER_DECODER(ADPCM_EA_R2, adpcm_ea_r2); + REGISTER_DECODER(ADPCM_EA_R3, adpcm_ea_r3); + REGISTER_DECODER(ADPCM_EA_XAS, adpcm_ea_xas); + REGISTER_ENCDEC (ADPCM_G722, adpcm_g722); + REGISTER_ENCDEC (ADPCM_G726, adpcm_g726); + REGISTER_DECODER(ADPCM_IMA_AMV, adpcm_ima_amv); + REGISTER_DECODER(ADPCM_IMA_APC, adpcm_ima_apc); + REGISTER_DECODER(ADPCM_IMA_DK3, adpcm_ima_dk3); + REGISTER_DECODER(ADPCM_IMA_DK4, adpcm_ima_dk4); + REGISTER_DECODER(ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs); + REGISTER_DECODER(ADPCM_IMA_EA_SEAD, adpcm_ima_ea_sead); + REGISTER_DECODER(ADPCM_IMA_ISS, adpcm_ima_iss); + REGISTER_DECODER(ADPCM_IMA_OKI, adpcm_ima_oki); + REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt); + REGISTER_DECODER(ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg); + REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav); + REGISTER_DECODER(ADPCM_IMA_WS, adpcm_ima_ws); + REGISTER_ENCDEC (ADPCM_MS, adpcm_ms); + REGISTER_DECODER(ADPCM_SBPRO_2, adpcm_sbpro_2); + REGISTER_DECODER(ADPCM_SBPRO_3, adpcm_sbpro_3); + REGISTER_DECODER(ADPCM_SBPRO_4, adpcm_sbpro_4); + REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf); + REGISTER_DECODER(ADPCM_THP, adpcm_thp); + REGISTER_DECODER(ADPCM_XA, adpcm_xa); + REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha); + REGISTER_DECODER(VIMA, vima); + + /* subtitles */ + REGISTER_ENCDEC (ASS, ass); + REGISTER_ENCDEC (DVBSUB, dvbsub); + REGISTER_ENCDEC (DVDSUB, dvdsub); + REGISTER_DECODER(JACOSUB, jacosub); + REGISTER_DECODER(MICRODVD, microdvd); + REGISTER_ENCDEC (MOVTEXT, movtext); + REGISTER_DECODER(MPL2, mpl2); + REGISTER_DECODER(PGSSUB, pgssub); + REGISTER_DECODER(PJS, pjs); + REGISTER_DECODER(REALTEXT, realtext); + REGISTER_DECODER(SAMI, sami); + REGISTER_ENCDEC (SRT, srt); + REGISTER_ENCDEC (SUBRIP, subrip); + REGISTER_DECODER(SUBVIEWER, subviewer); + REGISTER_DECODER(SUBVIEWER1, subviewer1); + REGISTER_DECODER(TEXT, text); + REGISTER_DECODER(VPLAYER, vplayer); + REGISTER_DECODER(WEBVTT, webvtt); + REGISTER_ENCDEC (XSUB, xsub); + + /* external libraries */ + REGISTER_DECODER(LIBCELT, libcelt); + REGISTER_ENCODER(LIBFAAC, libfaac); + REGISTER_ENCODER(LIBFDK_AAC, libfdk_aac); + REGISTER_ENCDEC (LIBGSM, libgsm); + REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); + REGISTER_ENCDEC (LIBILBC, libilbc); + REGISTER_ENCODER(LIBMP3LAME, libmp3lame); + REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); + REGISTER_DECODER(LIBOPENCORE_AMRWB, libopencore_amrwb); + REGISTER_ENCDEC (LIBOPENJPEG, libopenjpeg); + REGISTER_ENCDEC (LIBOPUS, libopus); + REGISTER_ENCDEC (LIBSCHROEDINGER, libschroedinger); + REGISTER_ENCDEC (LIBSPEEX, libspeex); + REGISTER_DECODER(LIBSTAGEFRIGHT_H264, libstagefright_h264); + REGISTER_ENCODER(LIBTHEORA, libtheora); + REGISTER_ENCODER(LIBTWOLAME, libtwolame); + REGISTER_ENCDEC (LIBUTVIDEO, libutvideo); + REGISTER_ENCODER(LIBVO_AACENC, libvo_aacenc); + REGISTER_ENCODER(LIBVO_AMRWBENC, libvo_amrwbenc); + REGISTER_ENCDEC (LIBVORBIS, libvorbis); + REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8); + REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9); + REGISTER_ENCODER(LIBX264, libx264); + REGISTER_ENCODER(LIBX264RGB, libx264rgb); + REGISTER_ENCODER(LIBXAVS, libxavs); + REGISTER_ENCODER(LIBXVID, libxvid); + REGISTER_ENCODER(LIBAACPLUS, libaacplus); + + /* text */ + REGISTER_DECODER(BINTEXT, bintext); + REGISTER_DECODER(XBIN, xbin); + REGISTER_DECODER(IDF, idf); + + /* parsers */ + REGISTER_PARSER(AAC, aac); + REGISTER_PARSER(AAC_LATM, aac_latm); + REGISTER_PARSER(AC3, ac3); + REGISTER_PARSER(ADX, adx); + REGISTER_PARSER(BMP, bmp); + REGISTER_PARSER(CAVSVIDEO, cavsvideo); + REGISTER_PARSER(COOK, cook); + REGISTER_PARSER(DCA, dca); + REGISTER_PARSER(DIRAC, dirac); + REGISTER_PARSER(DNXHD, dnxhd); + REGISTER_PARSER(DVBSUB, dvbsub); + REGISTER_PARSER(DVDSUB, dvdsub); + REGISTER_PARSER(DVD_NAV, dvd_nav); + REGISTER_PARSER(FLAC, flac); + REGISTER_PARSER(GSM, gsm); + REGISTER_PARSER(H261, h261); + REGISTER_PARSER(H263, h263); + REGISTER_PARSER(H264, h264); + REGISTER_PARSER(MJPEG, mjpeg); + REGISTER_PARSER(MLP, mlp); + REGISTER_PARSER(MPEG4VIDEO, mpeg4video); + REGISTER_PARSER(MPEGAUDIO, mpegaudio); + REGISTER_PARSER(MPEGVIDEO, mpegvideo); + REGISTER_PARSER(PNG, png); + REGISTER_PARSER(PNM, pnm); + REGISTER_PARSER(RV30, rv30); + REGISTER_PARSER(RV40, rv40); + REGISTER_PARSER(TAK, tak); + REGISTER_PARSER(VC1, vc1); + REGISTER_PARSER(VORBIS, vorbis); + REGISTER_PARSER(VP3, vp3); + REGISTER_PARSER(VP8, vp8); + + /* bitstream filters */ + REGISTER_BSF(AAC_ADTSTOASC, aac_adtstoasc); + REGISTER_BSF(CHOMP, chomp); + REGISTER_BSF(DUMP_EXTRADATA, dump_extradata); + REGISTER_BSF(H264_MP4TOANNEXB, h264_mp4toannexb); + REGISTER_BSF(IMX_DUMP_HEADER, imx_dump_header); + REGISTER_BSF(MJPEG2JPEG, mjpeg2jpeg); + REGISTER_BSF(MJPEGA_DUMP_HEADER, mjpega_dump_header); + REGISTER_BSF(MP3_HEADER_COMPRESS, mp3_header_compress); + REGISTER_BSF(MP3_HEADER_DECOMPRESS, mp3_header_decompress); + REGISTER_BSF(MOV2TEXTSUB, mov2textsub); + REGISTER_BSF(NOISE, noise); + REGISTER_BSF(REMOVE_EXTRADATA, remove_extradata); + REGISTER_BSF(TEXT2MOVSUB, text2movsub); +} diff --git a/ffmpeg/libavcodec/alpha/Makefile b/ffmpeg/libavcodec/alpha/Makefile new file mode 100644 index 0000000..6f22137 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/Makefile @@ -0,0 +1,9 @@ +OBJS += alpha/dsputil_alpha.o \ + alpha/dsputil_alpha_asm.o \ + alpha/motion_est_alpha.o \ + alpha/motion_est_mvi_asm.o \ + alpha/simple_idct_alpha.o \ + +OBJS-$(CONFIG_HPELDSP) += alpha/hpeldsp_alpha.o \ + alpha/hpeldsp_alpha_asm.o +OBJS-$(CONFIG_MPEGVIDEO) += alpha/mpegvideo_alpha.o diff --git a/ffmpeg/libavcodec/alpha/asm.h b/ffmpeg/libavcodec/alpha/asm.h new file mode 100644 index 0000000..827721e --- /dev/null +++ b/ffmpeg/libavcodec/alpha/asm.h @@ -0,0 +1,186 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 + */ + +#ifndef AVCODEC_ALPHA_ASM_H +#define AVCODEC_ALPHA_ASM_H + +#include + +#include "libavutil/common.h" + +#if AV_GCC_VERSION_AT_LEAST(2,96) +# define likely(x) __builtin_expect((x) != 0, 1) +# define unlikely(x) __builtin_expect((x) != 0, 0) +#else +# define likely(x) (x) +# define unlikely(x) (x) +#endif + +#define AMASK_BWX (1 << 0) +#define AMASK_FIX (1 << 1) +#define AMASK_CIX (1 << 2) +#define AMASK_MVI (1 << 8) + +static inline uint64_t BYTE_VEC(uint64_t x) +{ + x |= x << 8; + x |= x << 16; + x |= x << 32; + return x; +} +static inline uint64_t WORD_VEC(uint64_t x) +{ + x |= x << 16; + x |= x << 32; + return x; +} + +#define sextw(x) ((int16_t) (x)) + +#ifdef __GNUC__ +#define ldq(p) \ + (((const union { \ + uint64_t __l; \ + __typeof__(*(p)) __s[sizeof (uint64_t) / sizeof *(p)]; \ + } *) (p))->__l) +#define ldl(p) \ + (((const union { \ + int32_t __l; \ + __typeof__(*(p)) __s[sizeof (int32_t) / sizeof *(p)]; \ + } *) (p))->__l) +#define stq(l, p) \ + do { \ + (((union { \ + uint64_t __l; \ + __typeof__(*(p)) __s[sizeof (uint64_t) / sizeof *(p)]; \ + } *) (p))->__l) = l; \ + } while (0) +#define stl(l, p) \ + do { \ + (((union { \ + int32_t __l; \ + __typeof__(*(p)) __s[sizeof (int32_t) / sizeof *(p)]; \ + } *) (p))->__l) = l; \ + } while (0) +struct unaligned_long { uint64_t l; } __attribute__((packed)); +#define ldq_u(p) (*(const uint64_t *) (((uint64_t) (p)) & ~7ul)) +#define uldq(a) (((const struct unaligned_long *) (a))->l) + +#if AV_GCC_VERSION_AT_LEAST(3,3) +#define prefetch(p) __builtin_prefetch((p), 0, 1) +#define prefetch_en(p) __builtin_prefetch((p), 0, 0) +#define prefetch_m(p) __builtin_prefetch((p), 1, 1) +#define prefetch_men(p) __builtin_prefetch((p), 1, 0) +#define cmpbge __builtin_alpha_cmpbge +/* Avoid warnings. */ +#define extql(a, b) __builtin_alpha_extql(a, (uint64_t) (b)) +#define extwl(a, b) __builtin_alpha_extwl(a, (uint64_t) (b)) +#define extqh(a, b) __builtin_alpha_extqh(a, (uint64_t) (b)) +#define zap __builtin_alpha_zap +#define zapnot __builtin_alpha_zapnot +#define amask __builtin_alpha_amask +#define implver __builtin_alpha_implver +#define rpcc __builtin_alpha_rpcc +#else +#define prefetch(p) __asm__ volatile("ldl $31,%0" : : "m"(*(const char *) (p)) : "memory") +#define prefetch_en(p) __asm__ volatile("ldq $31,%0" : : "m"(*(const char *) (p)) : "memory") +#define prefetch_m(p) __asm__ volatile("lds $f31,%0" : : "m"(*(const char *) (p)) : "memory") +#define prefetch_men(p) __asm__ volatile("ldt $f31,%0" : : "m"(*(const char *) (p)) : "memory") +#define cmpbge(a, b) ({ uint64_t __r; __asm__ ("cmpbge %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; }) +#define extql(a, b) ({ uint64_t __r; __asm__ ("extql %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; }) +#define extwl(a, b) ({ uint64_t __r; __asm__ ("extwl %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; }) +#define extqh(a, b) ({ uint64_t __r; __asm__ ("extqh %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; }) +#define zap(a, b) ({ uint64_t __r; __asm__ ("zap %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; }) +#define zapnot(a, b) ({ uint64_t __r; __asm__ ("zapnot %r1,%2,%0" : "=r" (__r) : "rJ" (a), "rI" (b)); __r; }) +#define amask(a) ({ uint64_t __r; __asm__ ("amask %1,%0" : "=r" (__r) : "rI" (a)); __r; }) +#define implver() ({ uint64_t __r; __asm__ ("implver %0" : "=r" (__r)); __r; }) +#define rpcc() ({ uint64_t __r; __asm__ volatile ("rpcc %0" : "=r" (__r)); __r; }) +#endif +#define wh64(p) __asm__ volatile("wh64 (%0)" : : "r"(p) : "memory") + +#if AV_GCC_VERSION_AT_LEAST(3,3) && defined(__alpha_max__) +#define minub8 __builtin_alpha_minub8 +#define minsb8 __builtin_alpha_minsb8 +#define minuw4 __builtin_alpha_minuw4 +#define minsw4 __builtin_alpha_minsw4 +#define maxub8 __builtin_alpha_maxub8 +#define maxsb8 __builtin_alpha_maxsb8 +#define maxuw4 __builtin_alpha_maxuw4 +#define maxsw4 __builtin_alpha_maxsw4 +#define perr __builtin_alpha_perr +#define pklb __builtin_alpha_pklb +#define pkwb __builtin_alpha_pkwb +#define unpkbl __builtin_alpha_unpkbl +#define unpkbw __builtin_alpha_unpkbw +#else +#define minub8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minub8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define minsb8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minsb8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define minuw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minuw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define minsw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; minsw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define maxub8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxub8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define maxsb8(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxsb8 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define maxuw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxuw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define maxsw4(a, b) ({ uint64_t __r; __asm__ (".arch ev6; maxsw4 %r1,%2,%0" : "=r" (__r) : "%rJ" (a), "rI" (b)); __r; }) +#define perr(a, b) ({ uint64_t __r; __asm__ (".arch ev6; perr %r1,%r2,%0" : "=r" (__r) : "%rJ" (a), "rJ" (b)); __r; }) +#define pklb(a) ({ uint64_t __r; __asm__ (".arch ev6; pklb %r1,%0" : "=r" (__r) : "rJ" (a)); __r; }) +#define pkwb(a) ({ uint64_t __r; __asm__ (".arch ev6; pkwb %r1,%0" : "=r" (__r) : "rJ" (a)); __r; }) +#define unpkbl(a) ({ uint64_t __r; __asm__ (".arch ev6; unpkbl %r1,%0" : "=r" (__r) : "rJ" (a)); __r; }) +#define unpkbw(a) ({ uint64_t __r; __asm__ (".arch ev6; unpkbw %r1,%0" : "=r" (__r) : "rJ" (a)); __r; }) +#endif + +#elif defined(__DECC) /* Digital/Compaq/hp "ccc" compiler */ + +#include +#define ldq(p) (*(const uint64_t *) (p)) +#define ldl(p) (*(const int32_t *) (p)) +#define stq(l, p) do { *(uint64_t *) (p) = (l); } while (0) +#define stl(l, p) do { *(int32_t *) (p) = (l); } while (0) +#define ldq_u(a) asm ("ldq_u %v0,0(%a0)", a) +#define uldq(a) (*(const __unaligned uint64_t *) (a)) +#define cmpbge(a, b) asm ("cmpbge %a0,%a1,%v0", a, b) +#define extql(a, b) asm ("extql %a0,%a1,%v0", a, b) +#define extwl(a, b) asm ("extwl %a0,%a1,%v0", a, b) +#define extqh(a, b) asm ("extqh %a0,%a1,%v0", a, b) +#define zap(a, b) asm ("zap %a0,%a1,%v0", a, b) +#define zapnot(a, b) asm ("zapnot %a0,%a1,%v0", a, b) +#define amask(a) asm ("amask %a0,%v0", a) +#define implver() asm ("implver %v0") +#define rpcc() asm ("rpcc %v0") +#define minub8(a, b) asm ("minub8 %a0,%a1,%v0", a, b) +#define minsb8(a, b) asm ("minsb8 %a0,%a1,%v0", a, b) +#define minuw4(a, b) asm ("minuw4 %a0,%a1,%v0", a, b) +#define minsw4(a, b) asm ("minsw4 %a0,%a1,%v0", a, b) +#define maxub8(a, b) asm ("maxub8 %a0,%a1,%v0", a, b) +#define maxsb8(a, b) asm ("maxsb8 %a0,%a1,%v0", a, b) +#define maxuw4(a, b) asm ("maxuw4 %a0,%a1,%v0", a, b) +#define maxsw4(a, b) asm ("maxsw4 %a0,%a1,%v0", a, b) +#define perr(a, b) asm ("perr %a0,%a1,%v0", a, b) +#define pklb(a) asm ("pklb %a0,%v0", a) +#define pkwb(a) asm ("pkwb %a0,%v0", a) +#define unpkbl(a) asm ("unpkbl %a0,%v0", a) +#define unpkbw(a) asm ("unpkbw %a0,%v0", a) +#define wh64(a) asm ("wh64 %a0", a) + +#else +#error "Unknown compiler!" +#endif + +#endif /* AVCODEC_ALPHA_ASM_H */ diff --git a/ffmpeg/libavcodec/alpha/dsputil_alpha.c b/ffmpeg/libavcodec/alpha/dsputil_alpha.c new file mode 100644 index 0000000..03ba0a8 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/dsputil_alpha.c @@ -0,0 +1,157 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 "libavutil/attributes.h" +#include "libavcodec/dsputil.h" +#include "dsputil_alpha.h" +#include "asm.h" + +void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); +void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); + +#if 0 +/* These functions were the base for the optimized assembler routines, + and remain here for documentation purposes. */ +static void put_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels, + ptrdiff_t line_size) +{ + int i = 8; + uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */ + + do { + uint64_t shorts0, shorts1; + + shorts0 = ldq(block); + shorts0 = maxsw4(shorts0, 0); + shorts0 = minsw4(shorts0, clampmask); + stl(pkwb(shorts0), pixels); + + shorts1 = ldq(block + 4); + shorts1 = maxsw4(shorts1, 0); + shorts1 = minsw4(shorts1, clampmask); + stl(pkwb(shorts1), pixels + 4); + + pixels += line_size; + block += 8; + } while (--i); +} + +void add_pixels_clamped_mvi(const int16_t *block, uint8_t *pixels, + ptrdiff_t line_size) +{ + int h = 8; + /* Keep this function a leaf function by generating the constants + manually (mainly for the hack value ;-). */ + uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */ + uint64_t signmask = zap(-1, 0x33); + signmask ^= signmask >> 1; /* 0x8000800080008000 */ + + do { + uint64_t shorts0, pix0, signs0; + uint64_t shorts1, pix1, signs1; + + shorts0 = ldq(block); + shorts1 = ldq(block + 4); + + pix0 = unpkbw(ldl(pixels)); + /* Signed subword add (MMX paddw). */ + signs0 = shorts0 & signmask; + shorts0 &= ~signmask; + shorts0 += pix0; + shorts0 ^= signs0; + /* Clamp. */ + shorts0 = maxsw4(shorts0, 0); + shorts0 = minsw4(shorts0, clampmask); + + /* Next 4. */ + pix1 = unpkbw(ldl(pixels + 4)); + signs1 = shorts1 & signmask; + shorts1 &= ~signmask; + shorts1 += pix1; + shorts1 ^= signs1; + shorts1 = maxsw4(shorts1, 0); + shorts1 = minsw4(shorts1, clampmask); + + stl(pkwb(shorts0), pixels); + stl(pkwb(shorts1), pixels + 4); + + pixels += line_size; + block += 8; + } while (--h); +} +#endif + +static void clear_blocks_axp(int16_t *blocks) { + uint64_t *p = (uint64_t *) blocks; + int n = sizeof(int16_t) * 6 * 64; + + do { + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + p += 8; + n -= 8 * 8; + } while (n); +} + +av_cold void ff_dsputil_init_alpha(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (!high_bit_depth) { + c->clear_blocks = clear_blocks_axp; + } + + /* amask clears all bits that correspond to present features. */ + if (amask(AMASK_MVI) == 0) { + c->put_pixels_clamped = put_pixels_clamped_mvi_asm; + c->add_pixels_clamped = add_pixels_clamped_mvi_asm; + + if (!high_bit_depth) + c->get_pixels = get_pixels_mvi; + c->diff_pixels = diff_pixels_mvi; + c->sad[0] = pix_abs16x16_mvi_asm; + c->sad[1] = pix_abs8x8_mvi; + c->pix_abs[0][0] = pix_abs16x16_mvi_asm; + c->pix_abs[1][0] = pix_abs8x8_mvi; + c->pix_abs[0][1] = pix_abs16x16_x2_mvi; + c->pix_abs[0][2] = pix_abs16x16_y2_mvi; + c->pix_abs[0][3] = pix_abs16x16_xy2_mvi; + } + + put_pixels_clamped_axp_p = c->put_pixels_clamped; + add_pixels_clamped_axp_p = c->add_pixels_clamped; + + if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 && + (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEALPHA)) { + c->idct_put = ff_simple_idct_put_axp; + c->idct_add = ff_simple_idct_add_axp; + c->idct = ff_simple_idct_axp; + } +} diff --git a/ffmpeg/libavcodec/alpha/dsputil_alpha.h b/ffmpeg/libavcodec/alpha/dsputil_alpha.h new file mode 100644 index 0000000..828cd16 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/dsputil_alpha.h @@ -0,0 +1,49 @@ +/* + * 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 + */ + +#ifndef AVCODEC_ALPHA_DSPUTIL_ALPHA_H +#define AVCODEC_ALPHA_DSPUTIL_ALPHA_H + +#include +#include + +void ff_simple_idct_axp(int16_t *block); +void ff_simple_idct_put_axp(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_add_axp(uint8_t *dest, int line_size, int16_t *block); + +void put_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, + int line_size); +void add_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, + int line_size); +extern void (*put_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); +extern void (*add_pixels_clamped_axp_p)(const int16_t *block, uint8_t *pixels, + int line_size); + +void get_pixels_mvi(int16_t *restrict block, + const uint8_t *restrict pixels, int line_size); +void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2, + int stride); +int pix_abs8x8_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int pix_abs16x16_mvi_asm(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int pix_abs16x16_x2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int pix_abs16x16_y2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int pix_abs16x16_xy2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); + + +#endif /* AVCODEC_ALPHA_DSPUTIL_ALPHA_H */ diff --git a/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S b/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S new file mode 100644 index 0000000..5c5f90a --- /dev/null +++ b/ffmpeg/libavcodec/alpha/dsputil_alpha_asm.S @@ -0,0 +1,178 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 + */ + +/* + * These functions are scheduled for pca56. They should work + * reasonably on ev6, though. + */ + +#include "regdef.h" + +/* Some nicer register names. */ +#define ta t10 +#define tb t11 +#define tc t12 +#define td AT +/* Danger: these overlap with the argument list and the return value */ +#define te a5 +#define tf a4 +#define tg a3 +#define th v0 + + .set noat + .set noreorder + .arch pca56 + .text + +/************************************************************************ + * void put_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, + * int line_size) + */ + .align 6 + .globl put_pixels_clamped_mvi_asm + .ent put_pixels_clamped_mvi_asm +put_pixels_clamped_mvi_asm: + .frame sp, 0, ra + .prologue 0 + + lda t8, -1 + lda t9, 8 # loop counter + zap t8, 0xaa, t8 # 00ff00ff00ff00ff + + .align 4 +1: ldq t0, 0(a0) + ldq t1, 8(a0) + ldq t2, 16(a0) + ldq t3, 24(a0) + + maxsw4 t0, zero, t0 + subq t9, 2, t9 + maxsw4 t1, zero, t1 + lda a0, 32(a0) + + maxsw4 t2, zero, t2 + addq a1, a2, ta + maxsw4 t3, zero, t3 + minsw4 t0, t8, t0 + + minsw4 t1, t8, t1 + minsw4 t2, t8, t2 + minsw4 t3, t8, t3 + pkwb t0, t0 + + pkwb t1, t1 + pkwb t2, t2 + pkwb t3, t3 + stl t0, 0(a1) + + stl t1, 4(a1) + addq ta, a2, a1 + stl t2, 0(ta) + stl t3, 4(ta) + + bne t9, 1b + ret + .end put_pixels_clamped_mvi_asm + +/************************************************************************ + * void add_pixels_clamped_mvi_asm(const int16_t *block, uint8_t *pixels, + * int line_size) + */ + .align 6 + .globl add_pixels_clamped_mvi_asm + .ent add_pixels_clamped_mvi_asm +add_pixels_clamped_mvi_asm: + .frame sp, 0, ra + .prologue 0 + + lda t1, -1 + lda th, 8 + zap t1, 0x33, tg + nop + + srl tg, 1, t0 + xor tg, t0, tg # 0x8000800080008000 + zap t1, 0xaa, tf # 0x00ff00ff00ff00ff + + .align 4 +1: ldl t1, 0(a1) # pix0 (try to hit cache line soon) + ldl t4, 4(a1) # pix1 + addq a1, a2, te # pixels += line_size + ldq t0, 0(a0) # shorts0 + + ldl t7, 0(te) # pix2 (try to hit cache line soon) + ldl ta, 4(te) # pix3 + ldq t3, 8(a0) # shorts1 + ldq t6, 16(a0) # shorts2 + + ldq t9, 24(a0) # shorts3 + unpkbw t1, t1 # 0 0 (quarter/op no.) + and t0, tg, t2 # 0 1 + unpkbw t4, t4 # 1 0 + + bic t0, tg, t0 # 0 2 + unpkbw t7, t7 # 2 0 + and t3, tg, t5 # 1 1 + addq t0, t1, t0 # 0 3 + + xor t0, t2, t0 # 0 4 + unpkbw ta, ta # 3 0 + and t6, tg, t8 # 2 1 + maxsw4 t0, zero, t0 # 0 5 + + bic t3, tg, t3 # 1 2 + bic t6, tg, t6 # 2 2 + minsw4 t0, tf, t0 # 0 6 + addq t3, t4, t3 # 1 3 + + pkwb t0, t0 # 0 7 + xor t3, t5, t3 # 1 4 + maxsw4 t3, zero, t3 # 1 5 + addq t6, t7, t6 # 2 3 + + xor t6, t8, t6 # 2 4 + and t9, tg, tb # 3 1 + minsw4 t3, tf, t3 # 1 6 + bic t9, tg, t9 # 3 2 + + maxsw4 t6, zero, t6 # 2 5 + addq t9, ta, t9 # 3 3 + stl t0, 0(a1) # 0 8 + minsw4 t6, tf, t6 # 2 6 + + xor t9, tb, t9 # 3 4 + maxsw4 t9, zero, t9 # 3 5 + lda a0, 32(a0) # block += 16; + pkwb t3, t3 # 1 7 + + minsw4 t9, tf, t9 # 3 6 + subq th, 2, th + pkwb t6, t6 # 2 7 + pkwb t9, t9 # 3 7 + + stl t3, 4(a1) # 1 8 + addq te, a2, a1 # pixels += line_size + stl t6, 0(te) # 2 8 + stl t9, 4(te) # 3 8 + + bne th, 1b + ret + .end add_pixels_clamped_mvi_asm diff --git a/ffmpeg/libavcodec/alpha/hpeldsp_alpha.c b/ffmpeg/libavcodec/alpha/hpeldsp_alpha.c new file mode 100644 index 0000000..9a092f5 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/hpeldsp_alpha.c @@ -0,0 +1,212 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 "libavcodec/hpeldsp.h" +#include "hpeldsp_alpha.h" +#include "asm.h" + +static inline uint64_t avg2_no_rnd(uint64_t a, uint64_t b) +{ + return (a & b) + (((a ^ b) & BYTE_VEC(0xfe)) >> 1); +} + +static inline uint64_t avg2(uint64_t a, uint64_t b) +{ + return (a | b) - (((a ^ b) & BYTE_VEC(0xfe)) >> 1); +} + +#if 0 +/* The XY2 routines basically utilize this scheme, but reuse parts in + each iteration. */ +static inline uint64_t avg4(uint64_t l1, uint64_t l2, uint64_t l3, uint64_t l4) +{ + uint64_t r1 = ((l1 & ~BYTE_VEC(0x03)) >> 2) + + ((l2 & ~BYTE_VEC(0x03)) >> 2) + + ((l3 & ~BYTE_VEC(0x03)) >> 2) + + ((l4 & ~BYTE_VEC(0x03)) >> 2); + uint64_t r2 = (( (l1 & BYTE_VEC(0x03)) + + (l2 & BYTE_VEC(0x03)) + + (l3 & BYTE_VEC(0x03)) + + (l4 & BYTE_VEC(0x03)) + + BYTE_VEC(0x02)) >> 2) & BYTE_VEC(0x03); + return r1 + r2; +} +#endif + +#define OP(LOAD, STORE) \ + do { \ + STORE(LOAD(pixels), block); \ + pixels += line_size; \ + block += line_size; \ + } while (--h) + +#define OP_X2(LOAD, STORE) \ + do { \ + uint64_t pix1, pix2; \ + \ + pix1 = LOAD(pixels); \ + pix2 = pix1 >> 8 | ((uint64_t) pixels[8] << 56); \ + STORE(AVG2(pix1, pix2), block); \ + pixels += line_size; \ + block += line_size; \ + } while (--h) + +#define OP_Y2(LOAD, STORE) \ + do { \ + uint64_t pix = LOAD(pixels); \ + do { \ + uint64_t next_pix; \ + \ + pixels += line_size; \ + next_pix = LOAD(pixels); \ + STORE(AVG2(pix, next_pix), block); \ + block += line_size; \ + pix = next_pix; \ + } while (--h); \ + } while (0) + +#define OP_XY2(LOAD, STORE) \ + do { \ + uint64_t pix1 = LOAD(pixels); \ + uint64_t pix2 = pix1 >> 8 | ((uint64_t) pixels[8] << 56); \ + uint64_t pix_l = (pix1 & BYTE_VEC(0x03)) \ + + (pix2 & BYTE_VEC(0x03)); \ + uint64_t pix_h = ((pix1 & ~BYTE_VEC(0x03)) >> 2) \ + + ((pix2 & ~BYTE_VEC(0x03)) >> 2); \ + \ + do { \ + uint64_t npix1, npix2; \ + uint64_t npix_l, npix_h; \ + uint64_t avg; \ + \ + pixels += line_size; \ + npix1 = LOAD(pixels); \ + npix2 = npix1 >> 8 | ((uint64_t) pixels[8] << 56); \ + npix_l = (npix1 & BYTE_VEC(0x03)) \ + + (npix2 & BYTE_VEC(0x03)); \ + npix_h = ((npix1 & ~BYTE_VEC(0x03)) >> 2) \ + + ((npix2 & ~BYTE_VEC(0x03)) >> 2); \ + avg = (((pix_l + npix_l + AVG4_ROUNDER) >> 2) & BYTE_VEC(0x03)) \ + + pix_h + npix_h; \ + STORE(avg, block); \ + \ + block += line_size; \ + pix_l = npix_l; \ + pix_h = npix_h; \ + } while (--h); \ + } while (0) + +#define MAKE_OP(OPNAME, SUFF, OPKIND, STORE) \ +static void OPNAME ## _pixels ## SUFF ## _axp \ + (uint8_t *restrict block, const uint8_t *restrict pixels, \ + ptrdiff_t line_size, int h) \ +{ \ + if ((size_t) pixels & 0x7) { \ + OPKIND(uldq, STORE); \ + } else { \ + OPKIND(ldq, STORE); \ + } \ +} \ + \ +static void OPNAME ## _pixels16 ## SUFF ## _axp \ + (uint8_t *restrict block, const uint8_t *restrict pixels, \ + ptrdiff_t line_size, int h) \ +{ \ + OPNAME ## _pixels ## SUFF ## _axp(block, pixels, line_size, h); \ + OPNAME ## _pixels ## SUFF ## _axp(block + 8, pixels + 8, line_size, h); \ +} + +#define PIXOP(OPNAME, STORE) \ + MAKE_OP(OPNAME, , OP, STORE) \ + MAKE_OP(OPNAME, _x2, OP_X2, STORE) \ + MAKE_OP(OPNAME, _y2, OP_Y2, STORE) \ + MAKE_OP(OPNAME, _xy2, OP_XY2, STORE) + +/* Rounding primitives. */ +#define AVG2 avg2 +#define AVG4 avg4 +#define AVG4_ROUNDER BYTE_VEC(0x02) +#define STORE(l, b) stq(l, b) +PIXOP(put, STORE); + +#undef STORE +#define STORE(l, b) stq(AVG2(l, ldq(b)), b); +PIXOP(avg, STORE); + +/* Not rounding primitives. */ +#undef AVG2 +#undef AVG4 +#undef AVG4_ROUNDER +#undef STORE +#define AVG2 avg2_no_rnd +#define AVG4 avg4_no_rnd +#define AVG4_ROUNDER BYTE_VEC(0x01) +#define STORE(l, b) stq(l, b) +PIXOP(put_no_rnd, STORE); + +#undef STORE +#define STORE(l, b) stq(AVG2(l, ldq(b)), b); +PIXOP(avg_no_rnd, STORE); + +static void put_pixels16_axp_asm(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels_axp_asm(block, pixels, line_size, h); + put_pixels_axp_asm(block + 8, pixels + 8, line_size, h); +} + +void ff_hpeldsp_init_alpha(HpelDSPContext* c, int flags) +{ + c->put_pixels_tab[0][0] = put_pixels16_axp_asm; + c->put_pixels_tab[0][1] = put_pixels16_x2_axp; + c->put_pixels_tab[0][2] = put_pixels16_y2_axp; + c->put_pixels_tab[0][3] = put_pixels16_xy2_axp; + + c->put_no_rnd_pixels_tab[0][0] = put_pixels16_axp_asm; + c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_axp; + c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_axp; + c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_axp; + + c->avg_pixels_tab[0][0] = avg_pixels16_axp; + c->avg_pixels_tab[0][1] = avg_pixels16_x2_axp; + c->avg_pixels_tab[0][2] = avg_pixels16_y2_axp; + c->avg_pixels_tab[0][3] = avg_pixels16_xy2_axp; + + c->avg_no_rnd_pixels_tab[0] = avg_no_rnd_pixels16_axp; + c->avg_no_rnd_pixels_tab[1] = avg_no_rnd_pixels16_x2_axp; + c->avg_no_rnd_pixels_tab[2] = avg_no_rnd_pixels16_y2_axp; + c->avg_no_rnd_pixels_tab[3] = avg_no_rnd_pixels16_xy2_axp; + + c->put_pixels_tab[1][0] = put_pixels_axp_asm; + c->put_pixels_tab[1][1] = put_pixels_x2_axp; + c->put_pixels_tab[1][2] = put_pixels_y2_axp; + c->put_pixels_tab[1][3] = put_pixels_xy2_axp; + + c->put_no_rnd_pixels_tab[1][0] = put_pixels_axp_asm; + c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels_x2_axp; + c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels_y2_axp; + c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels_xy2_axp; + + c->avg_pixels_tab[1][0] = avg_pixels_axp; + c->avg_pixels_tab[1][1] = avg_pixels_x2_axp; + c->avg_pixels_tab[1][2] = avg_pixels_y2_axp; + c->avg_pixels_tab[1][3] = avg_pixels_xy2_axp; +} diff --git a/ffmpeg/libavcodec/alpha/hpeldsp_alpha.h b/ffmpeg/libavcodec/alpha/hpeldsp_alpha.h new file mode 100644 index 0000000..53e8604 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/hpeldsp_alpha.h @@ -0,0 +1,27 @@ +/* + * 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 + */ + +#ifndef AVCODEC_ALPHA_HPELDSP_ALPHA_H +#define AVCODEC_ALPHA_HPELDSP_ALPHA_H + +#include + +void put_pixels_axp_asm(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +#endif /* AVCODEC_ALPHA_HPELDSP_ALPHA_H */ diff --git a/ffmpeg/libavcodec/alpha/hpeldsp_alpha_asm.S b/ffmpeg/libavcodec/alpha/hpeldsp_alpha_asm.S new file mode 100644 index 0000000..afc3d42 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/hpeldsp_alpha_asm.S @@ -0,0 +1,135 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 + */ + +/* + * These functions are scheduled for pca56. They should work + * reasonably on ev6, though. + */ + +#include "regdef.h" + +/* Some nicer register names. */ +#define ta t10 +#define tb t11 +#define tc t12 +#define td AT +/* Danger: these overlap with the argument list and the return value */ +#define te a5 +#define tf a4 +#define tg a3 +#define th v0 + + .set noat + .set noreorder + .arch pca56 + .text + +/************************************************************************ + * void put_pixels_axp_asm(uint8_t *block, const uint8_t *pixels, + * int line_size, int h) + */ + .align 6 + .globl put_pixels_axp_asm + .ent put_pixels_axp_asm +put_pixels_axp_asm: + .frame sp, 0, ra + .prologue 0 + + and a1, 7, t0 + beq t0, $aligned + + .align 4 +$unaligned: + ldq_u t0, 0(a1) + ldq_u t1, 8(a1) + addq a1, a2, a1 + nop + + ldq_u t2, 0(a1) + ldq_u t3, 8(a1) + addq a1, a2, a1 + nop + + ldq_u t4, 0(a1) + ldq_u t5, 8(a1) + addq a1, a2, a1 + nop + + ldq_u t6, 0(a1) + ldq_u t7, 8(a1) + extql t0, a1, t0 + addq a1, a2, a1 + + extqh t1, a1, t1 + addq a0, a2, t8 + extql t2, a1, t2 + addq t8, a2, t9 + + extqh t3, a1, t3 + addq t9, a2, ta + extql t4, a1, t4 + or t0, t1, t0 + + extqh t5, a1, t5 + or t2, t3, t2 + extql t6, a1, t6 + or t4, t5, t4 + + extqh t7, a1, t7 + or t6, t7, t6 + stq t0, 0(a0) + stq t2, 0(t8) + + stq t4, 0(t9) + subq a3, 4, a3 + stq t6, 0(ta) + addq ta, a2, a0 + + bne a3, $unaligned + ret + + .align 4 +$aligned: + ldq t0, 0(a1) + addq a1, a2, a1 + ldq t1, 0(a1) + addq a1, a2, a1 + + ldq t2, 0(a1) + addq a1, a2, a1 + ldq t3, 0(a1) + + addq a0, a2, t4 + addq a1, a2, a1 + addq t4, a2, t5 + subq a3, 4, a3 + + stq t0, 0(a0) + addq t5, a2, t6 + stq t1, 0(t4) + addq t6, a2, a0 + + stq t2, 0(t5) + stq t3, 0(t6) + + bne a3, $aligned + ret + .end put_pixels_axp_asm diff --git a/ffmpeg/libavcodec/alpha/motion_est_alpha.c b/ffmpeg/libavcodec/alpha/motion_est_alpha.c new file mode 100644 index 0000000..a7c33e4 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/motion_est_alpha.c @@ -0,0 +1,345 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 "dsputil_alpha.h" +#include "asm.h" + +void get_pixels_mvi(int16_t *restrict block, + const uint8_t *restrict pixels, int line_size) +{ + int h = 8; + + do { + uint64_t p; + + p = ldq(pixels); + stq(unpkbw(p), block); + stq(unpkbw(p >> 32), block + 4); + + pixels += line_size; + block += 8; + } while (--h); +} + +void diff_pixels_mvi(int16_t *block, const uint8_t *s1, const uint8_t *s2, + int stride) { + int h = 8; + uint64_t mask = 0x4040; + + mask |= mask << 16; + mask |= mask << 32; + do { + uint64_t x, y, c, d, a; + uint64_t signs; + + x = ldq(s1); + y = ldq(s2); + c = cmpbge(x, y); + d = x - y; + a = zap(mask, c); /* We use 0x4040404040404040 here... */ + d += 4 * a; /* ...so we can use s4addq here. */ + signs = zap(-1, c); + + stq(unpkbw(d) | (unpkbw(signs) << 8), block); + stq(unpkbw(d >> 32) | (unpkbw(signs >> 32) << 8), block + 4); + + s1 += stride; + s2 += stride; + block += 8; + } while (--h); +} + +static inline uint64_t avg2(uint64_t a, uint64_t b) +{ + return (a | b) - (((a ^ b) & BYTE_VEC(0xfe)) >> 1); +} + +static inline uint64_t avg4(uint64_t l1, uint64_t l2, uint64_t l3, uint64_t l4) +{ + uint64_t r1 = ((l1 & ~BYTE_VEC(0x03)) >> 2) + + ((l2 & ~BYTE_VEC(0x03)) >> 2) + + ((l3 & ~BYTE_VEC(0x03)) >> 2) + + ((l4 & ~BYTE_VEC(0x03)) >> 2); + uint64_t r2 = (( (l1 & BYTE_VEC(0x03)) + + (l2 & BYTE_VEC(0x03)) + + (l3 & BYTE_VEC(0x03)) + + (l4 & BYTE_VEC(0x03)) + + BYTE_VEC(0x02)) >> 2) & BYTE_VEC(0x03); + return r1 + r2; +} + +int pix_abs8x8_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int result = 0; + + if ((size_t) pix2 & 0x7) { + /* works only when pix2 is actually unaligned */ + do { /* do 8 pixel a time */ + uint64_t p1, p2; + + p1 = ldq(pix1); + p2 = uldq(pix2); + result += perr(p1, p2); + + pix1 += line_size; + pix2 += line_size; + } while (--h); + } else { + do { + uint64_t p1, p2; + + p1 = ldq(pix1); + p2 = ldq(pix2); + result += perr(p1, p2); + + pix1 += line_size; + pix2 += line_size; + } while (--h); + } + + return result; +} + +#if 0 /* now done in assembly */ +int pix_abs16x16_mvi(uint8_t *pix1, uint8_t *pix2, int line_size) +{ + int result = 0; + int h = 16; + + if ((size_t) pix2 & 0x7) { + /* works only when pix2 is actually unaligned */ + do { /* do 16 pixel a time */ + uint64_t p1_l, p1_r, p2_l, p2_r; + uint64_t t; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + t = ldq_u(pix2 + 8); + p2_l = extql(ldq_u(pix2), pix2) | extqh(t, pix2); + p2_r = extql(t, pix2) | extqh(ldq_u(pix2 + 16), pix2); + pix1 += line_size; + pix2 += line_size; + + result += perr(p1_l, p2_l) + + perr(p1_r, p2_r); + } while (--h); + } else { + do { + uint64_t p1_l, p1_r, p2_l, p2_r; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + p2_l = ldq(pix2); + p2_r = ldq(pix2 + 8); + pix1 += line_size; + pix2 += line_size; + + result += perr(p1_l, p2_l) + + perr(p1_r, p2_r); + } while (--h); + } + + return result; +} +#endif + +int pix_abs16x16_x2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int result = 0; + uint64_t disalign = (size_t) pix2 & 0x7; + + switch (disalign) { + case 0: + do { + uint64_t p1_l, p1_r, p2_l, p2_r; + uint64_t l, r; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + l = ldq(pix2); + r = ldq(pix2 + 8); + p2_l = avg2(l, (l >> 8) | ((uint64_t) r << 56)); + p2_r = avg2(r, (r >> 8) | ((uint64_t) pix2[16] << 56)); + pix1 += line_size; + pix2 += line_size; + + result += perr(p1_l, p2_l) + + perr(p1_r, p2_r); + } while (--h); + break; + case 7: + /* |.......l|lllllllr|rrrrrrr*| + This case is special because disalign1 would be 8, which + gets treated as 0 by extqh. At least it is a bit faster + that way :) */ + do { + uint64_t p1_l, p1_r, p2_l, p2_r; + uint64_t l, m, r; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + l = ldq_u(pix2); + m = ldq_u(pix2 + 8); + r = ldq_u(pix2 + 16); + p2_l = avg2(extql(l, disalign) | extqh(m, disalign), m); + p2_r = avg2(extql(m, disalign) | extqh(r, disalign), r); + pix1 += line_size; + pix2 += line_size; + + result += perr(p1_l, p2_l) + + perr(p1_r, p2_r); + } while (--h); + break; + default: + do { + uint64_t disalign1 = disalign + 1; + uint64_t p1_l, p1_r, p2_l, p2_r; + uint64_t l, m, r; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + l = ldq_u(pix2); + m = ldq_u(pix2 + 8); + r = ldq_u(pix2 + 16); + p2_l = avg2(extql(l, disalign) | extqh(m, disalign), + extql(l, disalign1) | extqh(m, disalign1)); + p2_r = avg2(extql(m, disalign) | extqh(r, disalign), + extql(m, disalign1) | extqh(r, disalign1)); + pix1 += line_size; + pix2 += line_size; + + result += perr(p1_l, p2_l) + + perr(p1_r, p2_r); + } while (--h); + break; + } + return result; +} + +int pix_abs16x16_y2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int result = 0; + + if ((size_t) pix2 & 0x7) { + uint64_t t, p2_l, p2_r; + t = ldq_u(pix2 + 8); + p2_l = extql(ldq_u(pix2), pix2) | extqh(t, pix2); + p2_r = extql(t, pix2) | extqh(ldq_u(pix2 + 16), pix2); + + do { + uint64_t p1_l, p1_r, np2_l, np2_r; + uint64_t t; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + pix2 += line_size; + t = ldq_u(pix2 + 8); + np2_l = extql(ldq_u(pix2), pix2) | extqh(t, pix2); + np2_r = extql(t, pix2) | extqh(ldq_u(pix2 + 16), pix2); + + result += perr(p1_l, avg2(p2_l, np2_l)) + + perr(p1_r, avg2(p2_r, np2_r)); + + pix1 += line_size; + p2_l = np2_l; + p2_r = np2_r; + + } while (--h); + } else { + uint64_t p2_l, p2_r; + p2_l = ldq(pix2); + p2_r = ldq(pix2 + 8); + do { + uint64_t p1_l, p1_r, np2_l, np2_r; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + pix2 += line_size; + np2_l = ldq(pix2); + np2_r = ldq(pix2 + 8); + + result += perr(p1_l, avg2(p2_l, np2_l)) + + perr(p1_r, avg2(p2_r, np2_r)); + + pix1 += line_size; + p2_l = np2_l; + p2_r = np2_r; + } while (--h); + } + return result; +} + +int pix_abs16x16_xy2_mvi(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int result = 0; + + uint64_t p1_l, p1_r; + uint64_t p2_l, p2_r, p2_x; + + p1_l = ldq(pix1); + p1_r = ldq(pix1 + 8); + + if ((size_t) pix2 & 0x7) { /* could be optimized a lot */ + p2_l = uldq(pix2); + p2_r = uldq(pix2 + 8); + p2_x = (uint64_t) pix2[16] << 56; + } else { + p2_l = ldq(pix2); + p2_r = ldq(pix2 + 8); + p2_x = ldq(pix2 + 16) << 56; + } + + do { + uint64_t np1_l, np1_r; + uint64_t np2_l, np2_r, np2_x; + + pix1 += line_size; + pix2 += line_size; + + np1_l = ldq(pix1); + np1_r = ldq(pix1 + 8); + + if ((size_t) pix2 & 0x7) { /* could be optimized a lot */ + np2_l = uldq(pix2); + np2_r = uldq(pix2 + 8); + np2_x = (uint64_t) pix2[16] << 56; + } else { + np2_l = ldq(pix2); + np2_r = ldq(pix2 + 8); + np2_x = ldq(pix2 + 16) << 56; + } + + result += perr(p1_l, + avg4( p2_l, ( p2_l >> 8) | ((uint64_t) p2_r << 56), + np2_l, (np2_l >> 8) | ((uint64_t) np2_r << 56))) + + perr(p1_r, + avg4( p2_r, ( p2_r >> 8) | ((uint64_t) p2_x), + np2_r, (np2_r >> 8) | ((uint64_t) np2_x))); + + p1_l = np1_l; + p1_r = np1_r; + p2_l = np2_l; + p2_r = np2_r; + p2_x = np2_x; + } while (--h); + + return result; +} diff --git a/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S b/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S new file mode 100644 index 0000000..2399085 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/motion_est_mvi_asm.S @@ -0,0 +1,179 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 "regdef.h" + +/* Some nicer register names. */ +#define ta t10 +#define tb t11 +#define tc t12 +#define td AT +/* Danger: these overlap with the argument list and the return value */ +#define te a5 +#define tf a4 +#define tg a3 +#define th v0 + + .set noat + .set noreorder + .arch pca56 + .text + +/***************************************************************************** + * int pix_abs16x16_mvi_asm(uint8_t *pix1, uint8_t *pix2, int line_size) + * + * This code is written with a pca56 in mind. For ev6, one should + * really take the increased latency of 3 cycles for MVI instructions + * into account. + * + * It is important to keep the loading and first use of a register as + * far apart as possible, because if a register is accessed before it + * has been fetched from memory, the CPU will stall. + */ + .align 4 + .globl pix_abs16x16_mvi_asm + .ent pix_abs16x16_mvi_asm +pix_abs16x16_mvi_asm: + .frame sp, 0, ra, 0 + .prologue 0 + + and a2, 7, t0 + clr v0 + beq t0, $aligned + .align 4 +$unaligned: + /* Registers: + line 0: + t0: left_u -> left lo -> left + t1: mid + t2: right_u -> right hi -> right + t3: ref left + t4: ref right + line 1: + t5: left_u -> left lo -> left + t6: mid + t7: right_u -> right hi -> right + t8: ref left + t9: ref right + temp: + ta: left hi + tb: right lo + tc: error left + td: error right */ + + /* load line 0 */ + ldq_u t0, 0(a2) # left_u + ldq_u t1, 8(a2) # mid + ldq_u t2, 16(a2) # right_u + ldq t3, 0(a1) # ref left + ldq t4, 8(a1) # ref right + addq a1, a3, a1 # pix1 + addq a2, a3, a2 # pix2 + /* load line 1 */ + ldq_u t5, 0(a2) # left_u + ldq_u t6, 8(a2) # mid + ldq_u t7, 16(a2) # right_u + ldq t8, 0(a1) # ref left + ldq t9, 8(a1) # ref right + addq a1, a3, a1 # pix1 + addq a2, a3, a2 # pix2 + /* calc line 0 */ + extql t0, a2, t0 # left lo + extqh t1, a2, ta # left hi + extql t1, a2, tb # right lo + or t0, ta, t0 # left + extqh t2, a2, t2 # right hi + perr t3, t0, tc # error left + or t2, tb, t2 # right + perr t4, t2, td # error right + addq v0, tc, v0 # add error left + addq v0, td, v0 # add error left + /* calc line 1 */ + extql t5, a2, t5 # left lo + extqh t6, a2, ta # left hi + extql t6, a2, tb # right lo + or t5, ta, t5 # left + extqh t7, a2, t7 # right hi + perr t8, t5, tc # error left + or t7, tb, t7 # right + perr t9, t7, td # error right + addq v0, tc, v0 # add error left + addq v0, td, v0 # add error left + /* loop */ + subq a4, 2, a4 # h -= 2 + bne a4, $unaligned + ret + + .align 4 +$aligned: + /* load line 0 */ + ldq t0, 0(a2) # left + ldq t1, 8(a2) # right + addq a2, a3, a2 # pix2 + ldq t2, 0(a1) # ref left + ldq t3, 8(a1) # ref right + addq a1, a3, a1 # pix1 + /* load line 1 */ + ldq t4, 0(a2) # left + ldq t5, 8(a2) # right + addq a2, a3, a2 # pix2 + ldq t6, 0(a1) # ref left + ldq t7, 8(a1) # ref right + addq a1, a3, a1 # pix1 + /* load line 2 */ + ldq t8, 0(a2) # left + ldq t9, 8(a2) # right + addq a2, a3, a2 # pix2 + ldq ta, 0(a1) # ref left + ldq tb, 8(a1) # ref right + addq a1, a3, a1 # pix1 + /* load line 3 */ + ldq tc, 0(a2) # left + ldq td, 8(a2) # right + addq a2, a3, a2 # pix2 + ldq te, 0(a1) # ref left + ldq a0, 8(a1) # ref right + /* calc line 0 */ + perr t0, t2, t0 # error left + addq a1, a3, a1 # pix1 + perr t1, t3, t1 # error right + addq v0, t0, v0 # add error left + /* calc line 1 */ + perr t4, t6, t0 # error left + addq v0, t1, v0 # add error right + perr t5, t7, t1 # error right + addq v0, t0, v0 # add error left + /* calc line 2 */ + perr t8, ta, t0 # error left + addq v0, t1, v0 # add error right + perr t9, tb, t1 # error right + addq v0, t0, v0 # add error left + /* calc line 3 */ + perr tc, te, t0 # error left + addq v0, t1, v0 # add error right + perr td, a0, t1 # error right + addq v0, t0, v0 # add error left + addq v0, t1, v0 # add error right + /* loop */ + subq a4, 4, a4 # h -= 4 + bne a4, $aligned + ret + .end pix_abs16x16_mvi_asm diff --git a/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c b/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c new file mode 100644 index 0000000..7ba0f2e --- /dev/null +++ b/ffmpeg/libavcodec/alpha/mpegvideo_alpha.c @@ -0,0 +1,110 @@ +/* + * Alpha optimized DSP utils + * Copyright (c) 2002 Falk Hueffner + * + * 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 "libavutil/attributes.h" +#include "libavcodec/mpegvideo.h" +#include "asm.h" + +static void dct_unquantize_h263_axp(int16_t *block, int n_coeffs, + uint64_t qscale, uint64_t qadd) +{ + uint64_t qmul = qscale << 1; + uint64_t correction = WORD_VEC(qmul * 255 >> 8); + int i; + + qadd = WORD_VEC(qadd); + + for(i = 0; i <= n_coeffs; block += 4, i += 4) { + uint64_t levels, negmask, zeros, add, sub; + + levels = ldq(block); + if (levels == 0) + continue; + +#ifdef __alpha_max__ + /* I don't think the speed difference justifies runtime + detection. */ + negmask = maxsw4(levels, -1); /* negative -> ffff (-1) */ + negmask = minsw4(negmask, 0); /* positive -> 0000 (0) */ +#else + negmask = cmpbge(WORD_VEC(0x7fff), levels); + negmask &= (negmask >> 1) | (1 << 7); + negmask = zap(-1, negmask); +#endif + + zeros = cmpbge(0, levels); + zeros &= zeros >> 1; + /* zeros |= zeros << 1 is not needed since qadd <= 255, so + zapping the lower byte suffices. */ + + levels *= qmul; + levels -= correction & (negmask << 16); + + add = qadd & ~negmask; + sub = qadd & negmask; + /* Set qadd to 0 for levels == 0. */ + add = zap(add, zeros); + levels += add; + levels -= sub; + + stq(levels, block); + } +} + +static void dct_unquantize_h263_intra_axp(MpegEncContext *s, int16_t *block, + int n, int qscale) +{ + int n_coeffs; + uint64_t qadd; + int16_t block0 = block[0]; + + if (!s->h263_aic) { + if (n < 4) + block0 *= s->y_dc_scale; + else + block0 *= s->c_dc_scale; + qadd = (qscale - 1) | 1; + } else { + qadd = 0; + } + + if(s->ac_pred) + n_coeffs = 63; + else + n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]]; + + dct_unquantize_h263_axp(block, n_coeffs, qscale, qadd); + + block[0] = block0; +} + +static void dct_unquantize_h263_inter_axp(MpegEncContext *s, int16_t *block, + int n, int qscale) +{ + int n_coeffs = s->inter_scantable.raster_end[s->block_last_index[n]]; + dct_unquantize_h263_axp(block, n_coeffs, qscale, (qscale - 1) | 1); +} + +av_cold void ff_MPV_common_init_axp(MpegEncContext *s) +{ + s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_axp; + s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_axp; +} diff --git a/ffmpeg/libavcodec/alpha/regdef.h b/ffmpeg/libavcodec/alpha/regdef.h new file mode 100644 index 0000000..aa1959f --- /dev/null +++ b/ffmpeg/libavcodec/alpha/regdef.h @@ -0,0 +1,66 @@ +/* + * Alpha optimized DSP utils + * copyright (c) 2002 Falk Hueffner + * + * 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 + */ + +/* Some BSDs don't seem to have regdef.h... sigh */ +#ifndef AVCODEC_ALPHA_REGDEF_H +#define AVCODEC_ALPHA_REGDEF_H + +#define v0 $0 /* function return value */ + +#define t0 $1 /* temporary registers (caller-saved) */ +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 + +#define s0 $9 /* saved-registers (callee-saved registers) */ +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define s6 $15 +#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ + +#define a0 $16 /* argument registers (caller-saved) */ +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 + +#define t8 $22 /* more temps (caller-saved) */ +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 /* return address register */ +#define t12 $27 + +#define pv t12 /* procedure-variable register */ +#define AT $at /* assembler temporary */ +#define gp $29 /* global pointer */ +#define sp $30 /* stack pointer */ +#define zero $31 /* reads as zero, writes are noops */ + +#endif /* AVCODEC_ALPHA_REGDEF_H */ diff --git a/ffmpeg/libavcodec/alpha/simple_idct_alpha.c b/ffmpeg/libavcodec/alpha/simple_idct_alpha.c new file mode 100644 index 0000000..3bd1b33 --- /dev/null +++ b/ffmpeg/libavcodec/alpha/simple_idct_alpha.c @@ -0,0 +1,303 @@ +/* + * Simple IDCT (Alpha optimized) + * + * Copyright (c) 2001 Michael Niedermayer + * + * based upon some outcommented C code from mpeg2dec (idct_mmx.c + * written by Aaron Holtzman ) + * + * Alpha optimizations by Måns Rullgård + * and Falk Hueffner + * + * 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 "dsputil_alpha.h" +#include "asm.h" + +// cos(i * M_PI / 16) * sqrt(2) * (1 << 14) +// W4 is actually exactly 16384, but using 16383 works around +// accumulating rounding errors for some encoders +#define W1 22725 +#define W2 21407 +#define W3 19266 +#define W4 16383 +#define W5 12873 +#define W6 8867 +#define W7 4520 +#define ROW_SHIFT 11 +#define COL_SHIFT 20 + +/* 0: all entries 0, 1: only first entry nonzero, 2: otherwise */ +static inline int idct_row(int16_t *row) +{ + int a0, a1, a2, a3, b0, b1, b2, b3, t; + uint64_t l, r, t2; + l = ldq(row); + r = ldq(row + 4); + + if (l == 0 && r == 0) + return 0; + + a0 = W4 * sextw(l) + (1 << (ROW_SHIFT - 1)); + + if (((l & ~0xffffUL) | r) == 0) { + a0 >>= ROW_SHIFT; + t2 = (uint16_t) a0; + t2 |= t2 << 16; + t2 |= t2 << 32; + + stq(t2, row); + stq(t2, row + 4); + return 1; + } + + a1 = a0; + a2 = a0; + a3 = a0; + + t = extwl(l, 4); /* row[2] */ + if (t != 0) { + t = sextw(t); + a0 += W2 * t; + a1 += W6 * t; + a2 -= W6 * t; + a3 -= W2 * t; + } + + t = extwl(r, 0); /* row[4] */ + if (t != 0) { + t = sextw(t); + a0 += W4 * t; + a1 -= W4 * t; + a2 -= W4 * t; + a3 += W4 * t; + } + + t = extwl(r, 4); /* row[6] */ + if (t != 0) { + t = sextw(t); + a0 += W6 * t; + a1 -= W2 * t; + a2 += W2 * t; + a3 -= W6 * t; + } + + t = extwl(l, 2); /* row[1] */ + if (t != 0) { + t = sextw(t); + b0 = W1 * t; + b1 = W3 * t; + b2 = W5 * t; + b3 = W7 * t; + } else { + b0 = 0; + b1 = 0; + b2 = 0; + b3 = 0; + } + + t = extwl(l, 6); /* row[3] */ + if (t) { + t = sextw(t); + b0 += W3 * t; + b1 -= W7 * t; + b2 -= W1 * t; + b3 -= W5 * t; + } + + + t = extwl(r, 2); /* row[5] */ + if (t) { + t = sextw(t); + b0 += W5 * t; + b1 -= W1 * t; + b2 += W7 * t; + b3 += W3 * t; + } + + t = extwl(r, 6); /* row[7] */ + if (t) { + t = sextw(t); + b0 += W7 * t; + b1 -= W5 * t; + b2 += W3 * t; + b3 -= W1 * t; + } + + row[0] = (a0 + b0) >> ROW_SHIFT; + row[1] = (a1 + b1) >> ROW_SHIFT; + row[2] = (a2 + b2) >> ROW_SHIFT; + row[3] = (a3 + b3) >> ROW_SHIFT; + row[4] = (a3 - b3) >> ROW_SHIFT; + row[5] = (a2 - b2) >> ROW_SHIFT; + row[6] = (a1 - b1) >> ROW_SHIFT; + row[7] = (a0 - b0) >> ROW_SHIFT; + + return 2; +} + +static inline void idct_col(int16_t *col) +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + + col[0] += (1 << (COL_SHIFT - 1)) / W4; + + a0 = W4 * col[8 * 0]; + a1 = W4 * col[8 * 0]; + a2 = W4 * col[8 * 0]; + a3 = W4 * col[8 * 0]; + + if (col[8 * 2]) { + a0 += W2 * col[8 * 2]; + a1 += W6 * col[8 * 2]; + a2 -= W6 * col[8 * 2]; + a3 -= W2 * col[8 * 2]; + } + + if (col[8 * 4]) { + a0 += W4 * col[8 * 4]; + a1 -= W4 * col[8 * 4]; + a2 -= W4 * col[8 * 4]; + a3 += W4 * col[8 * 4]; + } + + if (col[8 * 6]) { + a0 += W6 * col[8 * 6]; + a1 -= W2 * col[8 * 6]; + a2 += W2 * col[8 * 6]; + a3 -= W6 * col[8 * 6]; + } + + if (col[8 * 1]) { + b0 = W1 * col[8 * 1]; + b1 = W3 * col[8 * 1]; + b2 = W5 * col[8 * 1]; + b3 = W7 * col[8 * 1]; + } else { + b0 = 0; + b1 = 0; + b2 = 0; + b3 = 0; + } + + if (col[8 * 3]) { + b0 += W3 * col[8 * 3]; + b1 -= W7 * col[8 * 3]; + b2 -= W1 * col[8 * 3]; + b3 -= W5 * col[8 * 3]; + } + + if (col[8 * 5]) { + b0 += W5 * col[8 * 5]; + b1 -= W1 * col[8 * 5]; + b2 += W7 * col[8 * 5]; + b3 += W3 * col[8 * 5]; + } + + if (col[8 * 7]) { + b0 += W7 * col[8 * 7]; + b1 -= W5 * col[8 * 7]; + b2 += W3 * col[8 * 7]; + b3 -= W1 * col[8 * 7]; + } + + col[8 * 0] = (a0 + b0) >> COL_SHIFT; + col[8 * 7] = (a0 - b0) >> COL_SHIFT; + col[8 * 1] = (a1 + b1) >> COL_SHIFT; + col[8 * 6] = (a1 - b1) >> COL_SHIFT; + col[8 * 2] = (a2 + b2) >> COL_SHIFT; + col[8 * 5] = (a2 - b2) >> COL_SHIFT; + col[8 * 3] = (a3 + b3) >> COL_SHIFT; + col[8 * 4] = (a3 - b3) >> COL_SHIFT; +} + +/* If all rows but the first one are zero after row transformation, + all rows will be identical after column transformation. */ +static inline void idct_col2(int16_t *col) +{ + int i; + uint64_t l, r; + + for (i = 0; i < 8; ++i) { + int a0 = col[i] + (1 << (COL_SHIFT - 1)) / W4; + + a0 *= W4; + col[i] = a0 >> COL_SHIFT; + } + + l = ldq(col + 0 * 4); r = ldq(col + 1 * 4); + stq(l, col + 2 * 4); stq(r, col + 3 * 4); + stq(l, col + 4 * 4); stq(r, col + 5 * 4); + stq(l, col + 6 * 4); stq(r, col + 7 * 4); + stq(l, col + 8 * 4); stq(r, col + 9 * 4); + stq(l, col + 10 * 4); stq(r, col + 11 * 4); + stq(l, col + 12 * 4); stq(r, col + 13 * 4); + stq(l, col + 14 * 4); stq(r, col + 15 * 4); +} + +void ff_simple_idct_axp(int16_t *block) +{ + + int i; + int rowsZero = 1; /* all rows except row 0 zero */ + int rowsConstant = 1; /* all rows consist of a constant value */ + + for (i = 0; i < 8; i++) { + int sparseness = idct_row(block + 8 * i); + + if (i > 0 && sparseness > 0) + rowsZero = 0; + if (sparseness == 2) + rowsConstant = 0; + } + + if (rowsZero) { + idct_col2(block); + } else if (rowsConstant) { + idct_col(block); + for (i = 0; i < 8; i += 2) { + uint64_t v = (uint16_t) block[0]; + uint64_t w = (uint16_t) block[8]; + + v |= v << 16; + w |= w << 16; + v |= v << 32; + w |= w << 32; + stq(v, block + 0 * 4); + stq(v, block + 1 * 4); + stq(w, block + 2 * 4); + stq(w, block + 3 * 4); + block += 4 * 4; + } + } else { + for (i = 0; i < 8; i++) + idct_col(block + i); + } +} + +void ff_simple_idct_put_axp(uint8_t *dest, int line_size, int16_t *block) +{ + ff_simple_idct_axp(block); + put_pixels_clamped_axp_p(block, dest, line_size); +} + +void ff_simple_idct_add_axp(uint8_t *dest, int line_size, int16_t *block) +{ + ff_simple_idct_axp(block); + add_pixels_clamped_axp_p(block, dest, line_size); +} diff --git a/ffmpeg/libavcodec/alsdec.c b/ffmpeg/libavcodec/alsdec.c new file mode 100644 index 0000000..96d467c --- /dev/null +++ b/ffmpeg/libavcodec/alsdec.c @@ -0,0 +1,1786 @@ +/* + * MPEG-4 ALS decoder + * Copyright (c) 2009 Thilo Borgmann + * + * 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 + */ + +/** + * @file + * MPEG-4 ALS decoder + * @author Thilo Borgmann + */ + + +//#define DEBUG + + +#include "avcodec.h" +#include "get_bits.h" +#include "unary.h" +#include "mpeg4audio.h" +#include "bytestream.h" +#include "bgmc.h" +#include "dsputil.h" +#include "internal.h" +#include "libavutil/samplefmt.h" +#include "libavutil/crc.h" + +#include + +/** Rice parameters and corresponding index offsets for decoding the + * indices of scaled PARCOR values. The table chosen is set globally + * by the encoder and stored in ALSSpecificConfig. + */ +static const int8_t parcor_rice_table[3][20][2] = { + { {-52, 4}, {-29, 5}, {-31, 4}, { 19, 4}, {-16, 4}, + { 12, 3}, { -7, 3}, { 9, 3}, { -5, 3}, { 6, 3}, + { -4, 3}, { 3, 3}, { -3, 2}, { 3, 2}, { -2, 2}, + { 3, 2}, { -1, 2}, { 2, 2}, { -1, 2}, { 2, 2} }, + { {-58, 3}, {-42, 4}, {-46, 4}, { 37, 5}, {-36, 4}, + { 29, 4}, {-29, 4}, { 25, 4}, {-23, 4}, { 20, 4}, + {-17, 4}, { 16, 4}, {-12, 4}, { 12, 3}, {-10, 4}, + { 7, 3}, { -4, 4}, { 3, 3}, { -1, 3}, { 1, 3} }, + { {-59, 3}, {-45, 5}, {-50, 4}, { 38, 4}, {-39, 4}, + { 32, 4}, {-30, 4}, { 25, 3}, {-23, 3}, { 20, 3}, + {-20, 3}, { 16, 3}, {-13, 3}, { 10, 3}, { -7, 3}, + { 3, 3}, { 0, 3}, { -1, 3}, { 2, 3}, { -1, 2} } +}; + + +/** Scaled PARCOR values used for the first two PARCOR coefficients. + * To be indexed by the Rice coded indices. + * Generated by: parcor_scaled_values[i] = 32 + ((i * (i+1)) << 7) - (1 << 20) + * Actual values are divided by 32 in order to be stored in 16 bits. + */ +static const int16_t parcor_scaled_values[] = { + -1048544 / 32, -1048288 / 32, -1047776 / 32, -1047008 / 32, + -1045984 / 32, -1044704 / 32, -1043168 / 32, -1041376 / 32, + -1039328 / 32, -1037024 / 32, -1034464 / 32, -1031648 / 32, + -1028576 / 32, -1025248 / 32, -1021664 / 32, -1017824 / 32, + -1013728 / 32, -1009376 / 32, -1004768 / 32, -999904 / 32, + -994784 / 32, -989408 / 32, -983776 / 32, -977888 / 32, + -971744 / 32, -965344 / 32, -958688 / 32, -951776 / 32, + -944608 / 32, -937184 / 32, -929504 / 32, -921568 / 32, + -913376 / 32, -904928 / 32, -896224 / 32, -887264 / 32, + -878048 / 32, -868576 / 32, -858848 / 32, -848864 / 32, + -838624 / 32, -828128 / 32, -817376 / 32, -806368 / 32, + -795104 / 32, -783584 / 32, -771808 / 32, -759776 / 32, + -747488 / 32, -734944 / 32, -722144 / 32, -709088 / 32, + -695776 / 32, -682208 / 32, -668384 / 32, -654304 / 32, + -639968 / 32, -625376 / 32, -610528 / 32, -595424 / 32, + -580064 / 32, -564448 / 32, -548576 / 32, -532448 / 32, + -516064 / 32, -499424 / 32, -482528 / 32, -465376 / 32, + -447968 / 32, -430304 / 32, -412384 / 32, -394208 / 32, + -375776 / 32, -357088 / 32, -338144 / 32, -318944 / 32, + -299488 / 32, -279776 / 32, -259808 / 32, -239584 / 32, + -219104 / 32, -198368 / 32, -177376 / 32, -156128 / 32, + -134624 / 32, -112864 / 32, -90848 / 32, -68576 / 32, + -46048 / 32, -23264 / 32, -224 / 32, 23072 / 32, + 46624 / 32, 70432 / 32, 94496 / 32, 118816 / 32, + 143392 / 32, 168224 / 32, 193312 / 32, 218656 / 32, + 244256 / 32, 270112 / 32, 296224 / 32, 322592 / 32, + 349216 / 32, 376096 / 32, 403232 / 32, 430624 / 32, + 458272 / 32, 486176 / 32, 514336 / 32, 542752 / 32, + 571424 / 32, 600352 / 32, 629536 / 32, 658976 / 32, + 688672 / 32, 718624 / 32, 748832 / 32, 779296 / 32, + 810016 / 32, 840992 / 32, 872224 / 32, 903712 / 32, + 935456 / 32, 967456 / 32, 999712 / 32, 1032224 / 32 +}; + + +/** Gain values of p(0) for long-term prediction. + * To be indexed by the Rice coded indices. + */ +static const uint8_t ltp_gain_values [4][4] = { + { 0, 8, 16, 24}, + {32, 40, 48, 56}, + {64, 70, 76, 82}, + {88, 92, 96, 100} +}; + + +/** Inter-channel weighting factors for multi-channel correlation. + * To be indexed by the Rice coded indices. + */ +static const int16_t mcc_weightings[] = { + 204, 192, 179, 166, 153, 140, 128, 115, + 102, 89, 76, 64, 51, 38, 25, 12, + 0, -12, -25, -38, -51, -64, -76, -89, + -102, -115, -128, -140, -153, -166, -179, -192 +}; + + +/** Tail codes used in arithmetic coding using block Gilbert-Moore codes. + */ +static const uint8_t tail_code[16][6] = { + { 74, 44, 25, 13, 7, 3}, + { 68, 42, 24, 13, 7, 3}, + { 58, 39, 23, 13, 7, 3}, + {126, 70, 37, 19, 10, 5}, + {132, 70, 37, 20, 10, 5}, + {124, 70, 38, 20, 10, 5}, + {120, 69, 37, 20, 11, 5}, + {116, 67, 37, 20, 11, 5}, + {108, 66, 36, 20, 10, 5}, + {102, 62, 36, 20, 10, 5}, + { 88, 58, 34, 19, 10, 5}, + {162, 89, 49, 25, 13, 7}, + {156, 87, 49, 26, 14, 7}, + {150, 86, 47, 26, 14, 7}, + {142, 84, 47, 26, 14, 7}, + {131, 79, 46, 26, 14, 7} +}; + + +enum RA_Flag { + RA_FLAG_NONE, + RA_FLAG_FRAMES, + RA_FLAG_HEADER +}; + + +typedef struct { + uint32_t samples; ///< number of samples, 0xFFFFFFFF if unknown + int resolution; ///< 000 = 8-bit; 001 = 16-bit; 010 = 24-bit; 011 = 32-bit + int floating; ///< 1 = IEEE 32-bit floating-point, 0 = integer + int msb_first; ///< 1 = original CRC calculated on big-endian system, 0 = little-endian + int frame_length; ///< frame length for each frame (last frame may differ) + int ra_distance; ///< distance between RA frames (in frames, 0...255) + enum RA_Flag ra_flag; ///< indicates where the size of ra units is stored + int adapt_order; ///< adaptive order: 1 = on, 0 = off + int coef_table; ///< table index of Rice code parameters + int long_term_prediction; ///< long term prediction (LTP): 1 = on, 0 = off + int max_order; ///< maximum prediction order (0..1023) + int block_switching; ///< number of block switching levels + int bgmc; ///< "Block Gilbert-Moore Code": 1 = on, 0 = off (Rice coding only) + int sb_part; ///< sub-block partition + int joint_stereo; ///< joint stereo: 1 = on, 0 = off + int mc_coding; ///< extended inter-channel coding (multi channel coding): 1 = on, 0 = off + int chan_config; ///< indicates that a chan_config_info field is present + int chan_sort; ///< channel rearrangement: 1 = on, 0 = off + int rlslms; ///< use "Recursive Least Square-Least Mean Square" predictor: 1 = on, 0 = off + int chan_config_info; ///< mapping of channels to loudspeaker locations. Unused until setting channel configuration is implemented. + int *chan_pos; ///< original channel positions + int crc_enabled; ///< enable Cyclic Redundancy Checksum +} ALSSpecificConfig; + + +typedef struct { + int stop_flag; + int master_channel; + int time_diff_flag; + int time_diff_sign; + int time_diff_index; + int weighting[6]; +} ALSChannelData; + + +typedef struct { + AVCodecContext *avctx; + ALSSpecificConfig sconf; + GetBitContext gb; + DSPContext dsp; + const AVCRC *crc_table; + uint32_t crc_org; ///< CRC value of the original input data + uint32_t crc; ///< CRC value calculated from decoded data + unsigned int cur_frame_length; ///< length of the current frame to decode + unsigned int frame_id; ///< the frame ID / number of the current frame + unsigned int js_switch; ///< if true, joint-stereo decoding is enforced + unsigned int cs_switch; ///< if true, channel rearrangement is done + unsigned int num_blocks; ///< number of blocks used in the current frame + unsigned int s_max; ///< maximum Rice parameter allowed in entropy coding + uint8_t *bgmc_lut; ///< pointer at lookup tables used for BGMC + int *bgmc_lut_status; ///< pointer at lookup table status flags used for BGMC + int ltp_lag_length; ///< number of bits used for ltp lag value + int *const_block; ///< contains const_block flags for all channels + unsigned int *shift_lsbs; ///< contains shift_lsbs flags for all channels + unsigned int *opt_order; ///< contains opt_order flags for all channels + int *store_prev_samples; ///< contains store_prev_samples flags for all channels + int *use_ltp; ///< contains use_ltp flags for all channels + int *ltp_lag; ///< contains ltp lag values for all channels + int **ltp_gain; ///< gain values for ltp 5-tap filter for a channel + int *ltp_gain_buffer; ///< contains all gain values for ltp 5-tap filter + int32_t **quant_cof; ///< quantized parcor coefficients for a channel + int32_t *quant_cof_buffer; ///< contains all quantized parcor coefficients + int32_t **lpc_cof; ///< coefficients of the direct form prediction filter for a channel + int32_t *lpc_cof_buffer; ///< contains all coefficients of the direct form prediction filter + int32_t *lpc_cof_reversed_buffer; ///< temporary buffer to set up a reversed versio of lpc_cof_buffer + ALSChannelData **chan_data; ///< channel data for multi-channel correlation + ALSChannelData *chan_data_buffer; ///< contains channel data for all channels + int *reverted_channels; ///< stores a flag for each reverted channel + int32_t *prev_raw_samples; ///< contains unshifted raw samples from the previous block + int32_t **raw_samples; ///< decoded raw samples for each channel + int32_t *raw_buffer; ///< contains all decoded raw samples including carryover samples + uint8_t *crc_buffer; ///< buffer of byte order corrected samples used for CRC check +} ALSDecContext; + + +typedef struct { + unsigned int block_length; ///< number of samples within the block + unsigned int ra_block; ///< if true, this is a random access block + int *const_block; ///< if true, this is a constant value block + int js_blocks; ///< true if this block contains a difference signal + unsigned int *shift_lsbs; ///< shift of values for this block + unsigned int *opt_order; ///< prediction order of this block + int *store_prev_samples;///< if true, carryover samples have to be stored + int *use_ltp; ///< if true, long-term prediction is used + int *ltp_lag; ///< lag value for long-term prediction + int *ltp_gain; ///< gain values for ltp 5-tap filter + int32_t *quant_cof; ///< quantized parcor coefficients + int32_t *lpc_cof; ///< coefficients of the direct form prediction + int32_t *raw_samples; ///< decoded raw samples / residuals for this block + int32_t *prev_raw_samples; ///< contains unshifted raw samples from the previous block + int32_t *raw_other; ///< decoded raw samples of the other channel of a channel pair +} ALSBlockData; + + +static av_cold void dprint_specific_config(ALSDecContext *ctx) +{ +#ifdef DEBUG + AVCodecContext *avctx = ctx->avctx; + ALSSpecificConfig *sconf = &ctx->sconf; + + av_dlog(avctx, "resolution = %i\n", sconf->resolution); + av_dlog(avctx, "floating = %i\n", sconf->floating); + av_dlog(avctx, "frame_length = %i\n", sconf->frame_length); + av_dlog(avctx, "ra_distance = %i\n", sconf->ra_distance); + av_dlog(avctx, "ra_flag = %i\n", sconf->ra_flag); + av_dlog(avctx, "adapt_order = %i\n", sconf->adapt_order); + av_dlog(avctx, "coef_table = %i\n", sconf->coef_table); + av_dlog(avctx, "long_term_prediction = %i\n", sconf->long_term_prediction); + av_dlog(avctx, "max_order = %i\n", sconf->max_order); + av_dlog(avctx, "block_switching = %i\n", sconf->block_switching); + av_dlog(avctx, "bgmc = %i\n", sconf->bgmc); + av_dlog(avctx, "sb_part = %i\n", sconf->sb_part); + av_dlog(avctx, "joint_stereo = %i\n", sconf->joint_stereo); + av_dlog(avctx, "mc_coding = %i\n", sconf->mc_coding); + av_dlog(avctx, "chan_config = %i\n", sconf->chan_config); + av_dlog(avctx, "chan_sort = %i\n", sconf->chan_sort); + av_dlog(avctx, "RLSLMS = %i\n", sconf->rlslms); + av_dlog(avctx, "chan_config_info = %i\n", sconf->chan_config_info); +#endif +} + + +/** Read an ALSSpecificConfig from a buffer into the output struct. + */ +static av_cold int read_specific_config(ALSDecContext *ctx) +{ + GetBitContext gb; + uint64_t ht_size; + int i, config_offset; + MPEG4AudioConfig m4ac; + ALSSpecificConfig *sconf = &ctx->sconf; + AVCodecContext *avctx = ctx->avctx; + uint32_t als_id, header_size, trailer_size; + int ret; + + if ((ret = init_get_bits8(&gb, avctx->extradata, avctx->extradata_size)) < 0) + return ret; + + config_offset = avpriv_mpeg4audio_get_config(&m4ac, avctx->extradata, + avctx->extradata_size * 8, 1); + + if (config_offset < 0) + return -1; + + skip_bits_long(&gb, config_offset); + + if (get_bits_left(&gb) < (30 << 3)) + return -1; + + // read the fixed items + als_id = get_bits_long(&gb, 32); + avctx->sample_rate = m4ac.sample_rate; + skip_bits_long(&gb, 32); // sample rate already known + sconf->samples = get_bits_long(&gb, 32); + avctx->channels = m4ac.channels; + skip_bits(&gb, 16); // number of channels already known + skip_bits(&gb, 3); // skip file_type + sconf->resolution = get_bits(&gb, 3); + sconf->floating = get_bits1(&gb); + sconf->msb_first = get_bits1(&gb); + sconf->frame_length = get_bits(&gb, 16) + 1; + sconf->ra_distance = get_bits(&gb, 8); + sconf->ra_flag = get_bits(&gb, 2); + sconf->adapt_order = get_bits1(&gb); + sconf->coef_table = get_bits(&gb, 2); + sconf->long_term_prediction = get_bits1(&gb); + sconf->max_order = get_bits(&gb, 10); + sconf->block_switching = get_bits(&gb, 2); + sconf->bgmc = get_bits1(&gb); + sconf->sb_part = get_bits1(&gb); + sconf->joint_stereo = get_bits1(&gb); + sconf->mc_coding = get_bits1(&gb); + sconf->chan_config = get_bits1(&gb); + sconf->chan_sort = get_bits1(&gb); + sconf->crc_enabled = get_bits1(&gb); + sconf->rlslms = get_bits1(&gb); + skip_bits(&gb, 5); // skip 5 reserved bits + skip_bits1(&gb); // skip aux_data_enabled + + + // check for ALSSpecificConfig struct + if (als_id != MKBETAG('A','L','S','\0')) + return -1; + + ctx->cur_frame_length = sconf->frame_length; + + // read channel config + if (sconf->chan_config) + sconf->chan_config_info = get_bits(&gb, 16); + // TODO: use this to set avctx->channel_layout + + + // read channel sorting + if (sconf->chan_sort && avctx->channels > 1) { + int chan_pos_bits = av_ceil_log2(avctx->channels); + int bits_needed = avctx->channels * chan_pos_bits + 7; + if (get_bits_left(&gb) < bits_needed) + return -1; + + if (!(sconf->chan_pos = av_malloc(avctx->channels * sizeof(*sconf->chan_pos)))) + return AVERROR(ENOMEM); + + ctx->cs_switch = 1; + + for (i = 0; i < avctx->channels; i++) { + int idx; + + idx = get_bits(&gb, chan_pos_bits); + if (idx >= avctx->channels) { + av_log(avctx, AV_LOG_WARNING, "Invalid channel reordering.\n"); + ctx->cs_switch = 0; + break; + } + sconf->chan_pos[idx] = i; + } + + align_get_bits(&gb); + } + + + // read fixed header and trailer sizes, + // if size = 0xFFFFFFFF then there is no data field! + if (get_bits_left(&gb) < 64) + return -1; + + header_size = get_bits_long(&gb, 32); + trailer_size = get_bits_long(&gb, 32); + if (header_size == 0xFFFFFFFF) + header_size = 0; + if (trailer_size == 0xFFFFFFFF) + trailer_size = 0; + + ht_size = ((int64_t)(header_size) + (int64_t)(trailer_size)) << 3; + + + // skip the header and trailer data + if (get_bits_left(&gb) < ht_size) + return -1; + + if (ht_size > INT32_MAX) + return -1; + + skip_bits_long(&gb, ht_size); + + + // initialize CRC calculation + if (sconf->crc_enabled) { + if (get_bits_left(&gb) < 32) + return -1; + + if (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL)) { + ctx->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE); + ctx->crc = 0xFFFFFFFF; + ctx->crc_org = ~get_bits_long(&gb, 32); + } else + skip_bits_long(&gb, 32); + } + + + // no need to read the rest of ALSSpecificConfig (ra_unit_size & aux data) + + dprint_specific_config(ctx); + + return 0; +} + + +/** Check the ALSSpecificConfig for unsupported features. + */ +static int check_specific_config(ALSDecContext *ctx) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + int error = 0; + + // report unsupported feature and set error value + #define MISSING_ERR(cond, str, errval) \ + { \ + if (cond) { \ + avpriv_report_missing_feature(ctx->avctx, \ + str); \ + error = errval; \ + } \ + } + + MISSING_ERR(sconf->floating, "Floating point decoding", AVERROR_PATCHWELCOME); + MISSING_ERR(sconf->rlslms, "Adaptive RLS-LMS prediction", AVERROR_PATCHWELCOME); + + return error; +} + + +/** Parse the bs_info field to extract the block partitioning used in + * block switching mode, refer to ISO/IEC 14496-3, section 11.6.2. + */ +static void parse_bs_info(const uint32_t bs_info, unsigned int n, + unsigned int div, unsigned int **div_blocks, + unsigned int *num_blocks) +{ + if (n < 31 && ((bs_info << n) & 0x40000000)) { + // if the level is valid and the investigated bit n is set + // then recursively check both children at bits (2n+1) and (2n+2) + n *= 2; + div += 1; + parse_bs_info(bs_info, n + 1, div, div_blocks, num_blocks); + parse_bs_info(bs_info, n + 2, div, div_blocks, num_blocks); + } else { + // else the bit is not set or the last level has been reached + // (bit implicitly not set) + **div_blocks = div; + (*div_blocks)++; + (*num_blocks)++; + } +} + + +/** Read and decode a Rice codeword. + */ +static int32_t decode_rice(GetBitContext *gb, unsigned int k) +{ + int max = get_bits_left(gb) - k; + int q = get_unary(gb, 0, max); + int r = k ? get_bits1(gb) : !(q & 1); + + if (k > 1) { + q <<= (k - 1); + q += get_bits_long(gb, k - 1); + } else if (!k) { + q >>= 1; + } + return r ? q : ~q; +} + + +/** Convert PARCOR coefficient k to direct filter coefficient. + */ +static void parcor_to_lpc(unsigned int k, const int32_t *par, int32_t *cof) +{ + int i, j; + + for (i = 0, j = k - 1; i < j; i++, j--) { + int tmp1 = ((MUL64(par[k], cof[j]) + (1 << 19)) >> 20); + cof[j] += ((MUL64(par[k], cof[i]) + (1 << 19)) >> 20); + cof[i] += tmp1; + } + if (i == j) + cof[i] += ((MUL64(par[k], cof[j]) + (1 << 19)) >> 20); + + cof[k] = par[k]; +} + + +/** Read block switching field if necessary and set actual block sizes. + * Also assure that the block sizes of the last frame correspond to the + * actual number of samples. + */ +static void get_block_sizes(ALSDecContext *ctx, unsigned int *div_blocks, + uint32_t *bs_info) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + GetBitContext *gb = &ctx->gb; + unsigned int *ptr_div_blocks = div_blocks; + unsigned int b; + + if (sconf->block_switching) { + unsigned int bs_info_len = 1 << (sconf->block_switching + 2); + *bs_info = get_bits_long(gb, bs_info_len); + *bs_info <<= (32 - bs_info_len); + } + + ctx->num_blocks = 0; + parse_bs_info(*bs_info, 0, 0, &ptr_div_blocks, &ctx->num_blocks); + + // The last frame may have an overdetermined block structure given in + // the bitstream. In that case the defined block structure would need + // more samples than available to be consistent. + // The block structure is actually used but the block sizes are adapted + // to fit the actual number of available samples. + // Example: 5 samples, 2nd level block sizes: 2 2 2 2. + // This results in the actual block sizes: 2 2 1 0. + // This is not specified in 14496-3 but actually done by the reference + // codec RM22 revision 2. + // This appears to happen in case of an odd number of samples in the last + // frame which is actually not allowed by the block length switching part + // of 14496-3. + // The ALS conformance files feature an odd number of samples in the last + // frame. + + for (b = 0; b < ctx->num_blocks; b++) + div_blocks[b] = ctx->sconf.frame_length >> div_blocks[b]; + + if (ctx->cur_frame_length != ctx->sconf.frame_length) { + unsigned int remaining = ctx->cur_frame_length; + + for (b = 0; b < ctx->num_blocks; b++) { + if (remaining <= div_blocks[b]) { + div_blocks[b] = remaining; + ctx->num_blocks = b + 1; + break; + } + + remaining -= div_blocks[b]; + } + } +} + + +/** Read the block data for a constant block + */ +static int read_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + AVCodecContext *avctx = ctx->avctx; + GetBitContext *gb = &ctx->gb; + + if (bd->block_length <= 0) + return AVERROR_INVALIDDATA; + + *bd->raw_samples = 0; + *bd->const_block = get_bits1(gb); // 1 = constant value, 0 = zero block (silence) + bd->js_blocks = get_bits1(gb); + + // skip 5 reserved bits + skip_bits(gb, 5); + + if (*bd->const_block) { + unsigned int const_val_bits = sconf->floating ? 24 : avctx->bits_per_raw_sample; + *bd->raw_samples = get_sbits_long(gb, const_val_bits); + } + + // ensure constant block decoding by reusing this field + *bd->const_block = 1; + + return 0; +} + + +/** Decode the block data for a constant block + */ +static void decode_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) +{ + int smp = bd->block_length - 1; + int32_t val = *bd->raw_samples; + int32_t *dst = bd->raw_samples + 1; + + // write raw samples into buffer + for (; smp; smp--) + *dst++ = val; +} + + +/** Read the block data for a non-constant block + */ +static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + AVCodecContext *avctx = ctx->avctx; + GetBitContext *gb = &ctx->gb; + unsigned int k; + unsigned int s[8]; + unsigned int sx[8]; + unsigned int sub_blocks, log2_sub_blocks, sb_length; + unsigned int start = 0; + unsigned int opt_order; + int sb; + int32_t *quant_cof = bd->quant_cof; + int32_t *current_res; + + + // ensure variable block decoding by reusing this field + *bd->const_block = 0; + + *bd->opt_order = 1; + bd->js_blocks = get_bits1(gb); + + opt_order = *bd->opt_order; + + // determine the number of subblocks for entropy decoding + if (!sconf->bgmc && !sconf->sb_part) { + log2_sub_blocks = 0; + } else { + if (sconf->bgmc && sconf->sb_part) + log2_sub_blocks = get_bits(gb, 2); + else + log2_sub_blocks = 2 * get_bits1(gb); + } + + sub_blocks = 1 << log2_sub_blocks; + + // do not continue in case of a damaged stream since + // block_length must be evenly divisible by sub_blocks + if (bd->block_length & (sub_blocks - 1)) { + av_log(avctx, AV_LOG_WARNING, + "Block length is not evenly divisible by the number of subblocks.\n"); + return -1; + } + + sb_length = bd->block_length >> log2_sub_blocks; + + if (sconf->bgmc) { + s[0] = get_bits(gb, 8 + (sconf->resolution > 1)); + for (k = 1; k < sub_blocks; k++) + s[k] = s[k - 1] + decode_rice(gb, 2); + + for (k = 0; k < sub_blocks; k++) { + sx[k] = s[k] & 0x0F; + s [k] >>= 4; + } + } else { + s[0] = get_bits(gb, 4 + (sconf->resolution > 1)); + for (k = 1; k < sub_blocks; k++) + s[k] = s[k - 1] + decode_rice(gb, 0); + } + for (k = 1; k < sub_blocks; k++) + if (s[k] > 32) { + av_log(avctx, AV_LOG_ERROR, "k invalid for rice code.\n"); + return AVERROR_INVALIDDATA; + } + + if (get_bits1(gb)) + *bd->shift_lsbs = get_bits(gb, 4) + 1; + + *bd->store_prev_samples = (bd->js_blocks && bd->raw_other) || *bd->shift_lsbs; + + + if (!sconf->rlslms) { + if (sconf->adapt_order) { + int opt_order_length = av_ceil_log2(av_clip((bd->block_length >> 3) - 1, + 2, sconf->max_order + 1)); + *bd->opt_order = get_bits(gb, opt_order_length); + if (*bd->opt_order > sconf->max_order) { + *bd->opt_order = sconf->max_order; + av_log(avctx, AV_LOG_ERROR, "Predictor order too large.\n"); + return AVERROR_INVALIDDATA; + } + } else { + *bd->opt_order = sconf->max_order; + } + + opt_order = *bd->opt_order; + + if (opt_order) { + int add_base; + + if (sconf->coef_table == 3) { + add_base = 0x7F; + + // read coefficient 0 + quant_cof[0] = 32 * parcor_scaled_values[get_bits(gb, 7)]; + + // read coefficient 1 + if (opt_order > 1) + quant_cof[1] = -32 * parcor_scaled_values[get_bits(gb, 7)]; + + // read coefficients 2 to opt_order + for (k = 2; k < opt_order; k++) + quant_cof[k] = get_bits(gb, 7); + } else { + int k_max; + add_base = 1; + + // read coefficient 0 to 19 + k_max = FFMIN(opt_order, 20); + for (k = 0; k < k_max; k++) { + int rice_param = parcor_rice_table[sconf->coef_table][k][1]; + int offset = parcor_rice_table[sconf->coef_table][k][0]; + quant_cof[k] = decode_rice(gb, rice_param) + offset; + if (quant_cof[k] < -64 || quant_cof[k] > 63) { + av_log(avctx, AV_LOG_ERROR, "quant_cof %d is out of range.\n", quant_cof[k]); + return AVERROR_INVALIDDATA; + } + } + + // read coefficients 20 to 126 + k_max = FFMIN(opt_order, 127); + for (; k < k_max; k++) + quant_cof[k] = decode_rice(gb, 2) + (k & 1); + + // read coefficients 127 to opt_order + for (; k < opt_order; k++) + quant_cof[k] = decode_rice(gb, 1); + + quant_cof[0] = 32 * parcor_scaled_values[quant_cof[0] + 64]; + + if (opt_order > 1) + quant_cof[1] = -32 * parcor_scaled_values[quant_cof[1] + 64]; + } + + for (k = 2; k < opt_order; k++) + quant_cof[k] = (quant_cof[k] << 14) + (add_base << 13); + } + } + + // read LTP gain and lag values + if (sconf->long_term_prediction) { + *bd->use_ltp = get_bits1(gb); + + if (*bd->use_ltp) { + int r, c; + + bd->ltp_gain[0] = decode_rice(gb, 1) << 3; + bd->ltp_gain[1] = decode_rice(gb, 2) << 3; + + r = get_unary(gb, 0, 3); + c = get_bits(gb, 2); + bd->ltp_gain[2] = ltp_gain_values[r][c]; + + bd->ltp_gain[3] = decode_rice(gb, 2) << 3; + bd->ltp_gain[4] = decode_rice(gb, 1) << 3; + + *bd->ltp_lag = get_bits(gb, ctx->ltp_lag_length); + *bd->ltp_lag += FFMAX(4, opt_order + 1); + } + } + + // read first value and residuals in case of a random access block + if (bd->ra_block) { + if (opt_order) + bd->raw_samples[0] = decode_rice(gb, avctx->bits_per_raw_sample - 4); + if (opt_order > 1) + bd->raw_samples[1] = decode_rice(gb, FFMIN(s[0] + 3, ctx->s_max)); + if (opt_order > 2) + bd->raw_samples[2] = decode_rice(gb, FFMIN(s[0] + 1, ctx->s_max)); + + start = FFMIN(opt_order, 3); + } + + // read all residuals + if (sconf->bgmc) { + int delta[8]; + unsigned int k [8]; + unsigned int b = av_clip((av_ceil_log2(bd->block_length) - 3) >> 1, 0, 5); + + // read most significant bits + unsigned int high; + unsigned int low; + unsigned int value; + + ff_bgmc_decode_init(gb, &high, &low, &value); + + current_res = bd->raw_samples + start; + + for (sb = 0; sb < sub_blocks; sb++) { + unsigned int sb_len = sb_length - (sb ? 0 : start); + + k [sb] = s[sb] > b ? s[sb] - b : 0; + delta[sb] = 5 - s[sb] + k[sb]; + + ff_bgmc_decode(gb, sb_len, current_res, + delta[sb], sx[sb], &high, &low, &value, ctx->bgmc_lut, ctx->bgmc_lut_status); + + current_res += sb_len; + } + + ff_bgmc_decode_end(gb); + + + // read least significant bits and tails + current_res = bd->raw_samples + start; + + for (sb = 0; sb < sub_blocks; sb++, start = 0) { + unsigned int cur_tail_code = tail_code[sx[sb]][delta[sb]]; + unsigned int cur_k = k[sb]; + unsigned int cur_s = s[sb]; + + for (; start < sb_length; start++) { + int32_t res = *current_res; + + if (res == cur_tail_code) { + unsigned int max_msb = (2 + (sx[sb] > 2) + (sx[sb] > 10)) + << (5 - delta[sb]); + + res = decode_rice(gb, cur_s); + + if (res >= 0) { + res += (max_msb ) << cur_k; + } else { + res -= (max_msb - 1) << cur_k; + } + } else { + if (res > cur_tail_code) + res--; + + if (res & 1) + res = -res; + + res >>= 1; + + if (cur_k) { + res <<= cur_k; + res |= get_bits_long(gb, cur_k); + } + } + + *current_res++ = res; + } + } + } else { + current_res = bd->raw_samples + start; + + for (sb = 0; sb < sub_blocks; sb++, start = 0) + for (; start < sb_length; start++) + *current_res++ = decode_rice(gb, s[sb]); + } + + if (!sconf->mc_coding || ctx->js_switch) + align_get_bits(gb); + + return 0; +} + + +/** Decode the block data for a non-constant block + */ +static int decode_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + unsigned int block_length = bd->block_length; + unsigned int smp = 0; + unsigned int k; + int opt_order = *bd->opt_order; + int sb; + int64_t y; + int32_t *quant_cof = bd->quant_cof; + int32_t *lpc_cof = bd->lpc_cof; + int32_t *raw_samples = bd->raw_samples; + int32_t *raw_samples_end = bd->raw_samples + bd->block_length; + int32_t *lpc_cof_reversed = ctx->lpc_cof_reversed_buffer; + + // reverse long-term prediction + if (*bd->use_ltp) { + int ltp_smp; + + for (ltp_smp = FFMAX(*bd->ltp_lag - 2, 0); ltp_smp < block_length; ltp_smp++) { + int center = ltp_smp - *bd->ltp_lag; + int begin = FFMAX(0, center - 2); + int end = center + 3; + int tab = 5 - (end - begin); + int base; + + y = 1 << 6; + + for (base = begin; base < end; base++, tab++) + y += MUL64(bd->ltp_gain[tab], raw_samples[base]); + + raw_samples[ltp_smp] += y >> 7; + } + } + + // reconstruct all samples from residuals + if (bd->ra_block) { + for (smp = 0; smp < opt_order; smp++) { + y = 1 << 19; + + for (sb = 0; sb < smp; sb++) + y += MUL64(lpc_cof[sb], raw_samples[-(sb + 1)]); + + *raw_samples++ -= y >> 20; + parcor_to_lpc(smp, quant_cof, lpc_cof); + } + } else { + for (k = 0; k < opt_order; k++) + parcor_to_lpc(k, quant_cof, lpc_cof); + + // store previous samples in case that they have to be altered + if (*bd->store_prev_samples) + memcpy(bd->prev_raw_samples, raw_samples - sconf->max_order, + sizeof(*bd->prev_raw_samples) * sconf->max_order); + + // reconstruct difference signal for prediction (joint-stereo) + if (bd->js_blocks && bd->raw_other) { + int32_t *left, *right; + + if (bd->raw_other > raw_samples) { // D = R - L + left = raw_samples; + right = bd->raw_other; + } else { // D = R - L + left = bd->raw_other; + right = raw_samples; + } + + for (sb = -1; sb >= -sconf->max_order; sb--) + raw_samples[sb] = right[sb] - left[sb]; + } + + // reconstruct shifted signal + if (*bd->shift_lsbs) + for (sb = -1; sb >= -sconf->max_order; sb--) + raw_samples[sb] >>= *bd->shift_lsbs; + } + + // reverse linear prediction coefficients for efficiency + lpc_cof = lpc_cof + opt_order; + + for (sb = 0; sb < opt_order; sb++) + lpc_cof_reversed[sb] = lpc_cof[-(sb + 1)]; + + // reconstruct raw samples + raw_samples = bd->raw_samples + smp; + lpc_cof = lpc_cof_reversed + opt_order; + + for (; raw_samples < raw_samples_end; raw_samples++) { + y = 1 << 19; + + for (sb = -opt_order; sb < 0; sb++) + y += MUL64(lpc_cof[sb], raw_samples[sb]); + + *raw_samples -= y >> 20; + } + + raw_samples = bd->raw_samples; + + // restore previous samples in case that they have been altered + if (*bd->store_prev_samples) + memcpy(raw_samples - sconf->max_order, bd->prev_raw_samples, + sizeof(*raw_samples) * sconf->max_order); + + return 0; +} + + +/** Read the block data. + */ +static int read_block(ALSDecContext *ctx, ALSBlockData *bd) +{ + GetBitContext *gb = &ctx->gb; + int ret; + + *bd->shift_lsbs = 0; + // read block type flag and read the samples accordingly + if (get_bits1(gb)) { + if ((ret = read_var_block_data(ctx, bd)) < 0) + return ret; + } else { + if ((ret = read_const_block_data(ctx, bd)) < 0) + return ret; + } + + return 0; +} + + +/** Decode the block data. + */ +static int decode_block(ALSDecContext *ctx, ALSBlockData *bd) +{ + unsigned int smp; + + // read block type flag and read the samples accordingly + if (*bd->const_block) + decode_const_block_data(ctx, bd); + else if (decode_var_block_data(ctx, bd)) + return -1; + + // TODO: read RLSLMS extension data + + if (*bd->shift_lsbs) + for (smp = 0; smp < bd->block_length; smp++) + bd->raw_samples[smp] <<= *bd->shift_lsbs; + + return 0; +} + + +/** Read and decode block data successively. + */ +static int read_decode_block(ALSDecContext *ctx, ALSBlockData *bd) +{ + int ret; + + ret = read_block(ctx, bd); + + if (ret) + return ret; + + ret = decode_block(ctx, bd); + + return ret; +} + + +/** Compute the number of samples left to decode for the current frame and + * sets these samples to zero. + */ +static void zero_remaining(unsigned int b, unsigned int b_max, + const unsigned int *div_blocks, int32_t *buf) +{ + unsigned int count = 0; + + while (b < b_max) + count += div_blocks[b++]; + + if (count) + memset(buf, 0, sizeof(*buf) * count); +} + + +/** Decode blocks independently. + */ +static int decode_blocks_ind(ALSDecContext *ctx, unsigned int ra_frame, + unsigned int c, const unsigned int *div_blocks, + unsigned int *js_blocks) +{ + unsigned int b; + ALSBlockData bd = { 0 }; + + bd.ra_block = ra_frame; + bd.const_block = ctx->const_block; + bd.shift_lsbs = ctx->shift_lsbs; + bd.opt_order = ctx->opt_order; + bd.store_prev_samples = ctx->store_prev_samples; + bd.use_ltp = ctx->use_ltp; + bd.ltp_lag = ctx->ltp_lag; + bd.ltp_gain = ctx->ltp_gain[0]; + bd.quant_cof = ctx->quant_cof[0]; + bd.lpc_cof = ctx->lpc_cof[0]; + bd.prev_raw_samples = ctx->prev_raw_samples; + bd.raw_samples = ctx->raw_samples[c]; + + + for (b = 0; b < ctx->num_blocks; b++) { + bd.block_length = div_blocks[b]; + + if (read_decode_block(ctx, &bd)) { + // damaged block, write zero for the rest of the frame + zero_remaining(b, ctx->num_blocks, div_blocks, bd.raw_samples); + return -1; + } + bd.raw_samples += div_blocks[b]; + bd.ra_block = 0; + } + + return 0; +} + + +/** Decode blocks dependently. + */ +static int decode_blocks(ALSDecContext *ctx, unsigned int ra_frame, + unsigned int c, const unsigned int *div_blocks, + unsigned int *js_blocks) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + unsigned int offset = 0; + unsigned int b; + ALSBlockData bd[2] = { { 0 } }; + + bd[0].ra_block = ra_frame; + bd[0].const_block = ctx->const_block; + bd[0].shift_lsbs = ctx->shift_lsbs; + bd[0].opt_order = ctx->opt_order; + bd[0].store_prev_samples = ctx->store_prev_samples; + bd[0].use_ltp = ctx->use_ltp; + bd[0].ltp_lag = ctx->ltp_lag; + bd[0].ltp_gain = ctx->ltp_gain[0]; + bd[0].quant_cof = ctx->quant_cof[0]; + bd[0].lpc_cof = ctx->lpc_cof[0]; + bd[0].prev_raw_samples = ctx->prev_raw_samples; + bd[0].js_blocks = *js_blocks; + + bd[1].ra_block = ra_frame; + bd[1].const_block = ctx->const_block; + bd[1].shift_lsbs = ctx->shift_lsbs; + bd[1].opt_order = ctx->opt_order; + bd[1].store_prev_samples = ctx->store_prev_samples; + bd[1].use_ltp = ctx->use_ltp; + bd[1].ltp_lag = ctx->ltp_lag; + bd[1].ltp_gain = ctx->ltp_gain[0]; + bd[1].quant_cof = ctx->quant_cof[0]; + bd[1].lpc_cof = ctx->lpc_cof[0]; + bd[1].prev_raw_samples = ctx->prev_raw_samples; + bd[1].js_blocks = *(js_blocks + 1); + + // decode all blocks + for (b = 0; b < ctx->num_blocks; b++) { + unsigned int s; + + bd[0].block_length = div_blocks[b]; + bd[1].block_length = div_blocks[b]; + + bd[0].raw_samples = ctx->raw_samples[c ] + offset; + bd[1].raw_samples = ctx->raw_samples[c + 1] + offset; + + bd[0].raw_other = bd[1].raw_samples; + bd[1].raw_other = bd[0].raw_samples; + + if(read_decode_block(ctx, &bd[0]) || read_decode_block(ctx, &bd[1])) { + // damaged block, write zero for the rest of the frame + zero_remaining(b, ctx->num_blocks, div_blocks, bd[0].raw_samples); + zero_remaining(b, ctx->num_blocks, div_blocks, bd[1].raw_samples); + return -1; + } + + // reconstruct joint-stereo blocks + if (bd[0].js_blocks) { + if (bd[1].js_blocks) + av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel pair.\n"); + + for (s = 0; s < div_blocks[b]; s++) + bd[0].raw_samples[s] = bd[1].raw_samples[s] - bd[0].raw_samples[s]; + } else if (bd[1].js_blocks) { + for (s = 0; s < div_blocks[b]; s++) + bd[1].raw_samples[s] = bd[1].raw_samples[s] + bd[0].raw_samples[s]; + } + + offset += div_blocks[b]; + bd[0].ra_block = 0; + bd[1].ra_block = 0; + } + + // store carryover raw samples, + // the others channel raw samples are stored by the calling function. + memmove(ctx->raw_samples[c] - sconf->max_order, + ctx->raw_samples[c] - sconf->max_order + sconf->frame_length, + sizeof(*ctx->raw_samples[c]) * sconf->max_order); + + return 0; +} + + +/** Read the channel data. + */ +static int read_channel_data(ALSDecContext *ctx, ALSChannelData *cd, int c) +{ + GetBitContext *gb = &ctx->gb; + ALSChannelData *current = cd; + unsigned int channels = ctx->avctx->channels; + int entries = 0; + + while (entries < channels && !(current->stop_flag = get_bits1(gb))) { + current->master_channel = get_bits_long(gb, av_ceil_log2(channels)); + + if (current->master_channel >= channels) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid master channel.\n"); + return -1; + } + + if (current->master_channel != c) { + current->time_diff_flag = get_bits1(gb); + current->weighting[0] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 31)]; + current->weighting[1] = mcc_weightings[av_clip(decode_rice(gb, 2) + 14, 0, 31)]; + current->weighting[2] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 31)]; + + if (current->time_diff_flag) { + current->weighting[3] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 31)]; + current->weighting[4] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 31)]; + current->weighting[5] = mcc_weightings[av_clip(decode_rice(gb, 1) + 16, 0, 31)]; + + current->time_diff_sign = get_bits1(gb); + current->time_diff_index = get_bits(gb, ctx->ltp_lag_length - 3) + 3; + } + } + + current++; + entries++; + } + + if (entries == channels) { + av_log(ctx->avctx, AV_LOG_ERROR, "Damaged channel data.\n"); + return -1; + } + + align_get_bits(gb); + return 0; +} + + +/** Recursively reverts the inter-channel correlation for a block. + */ +static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd, + ALSChannelData **cd, int *reverted, + unsigned int offset, int c) +{ + ALSChannelData *ch = cd[c]; + unsigned int dep = 0; + unsigned int channels = ctx->avctx->channels; + + if (reverted[c]) + return 0; + + reverted[c] = 1; + + while (dep < channels && !ch[dep].stop_flag) { + revert_channel_correlation(ctx, bd, cd, reverted, offset, + ch[dep].master_channel); + + dep++; + } + + if (dep == channels) { + av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel correlation.\n"); + return -1; + } + + bd->const_block = ctx->const_block + c; + bd->shift_lsbs = ctx->shift_lsbs + c; + bd->opt_order = ctx->opt_order + c; + bd->store_prev_samples = ctx->store_prev_samples + c; + bd->use_ltp = ctx->use_ltp + c; + bd->ltp_lag = ctx->ltp_lag + c; + bd->ltp_gain = ctx->ltp_gain[c]; + bd->lpc_cof = ctx->lpc_cof[c]; + bd->quant_cof = ctx->quant_cof[c]; + bd->raw_samples = ctx->raw_samples[c] + offset; + + dep = 0; + while (!ch[dep].stop_flag) { + unsigned int smp; + unsigned int begin = 1; + unsigned int end = bd->block_length - 1; + int64_t y; + int32_t *master = ctx->raw_samples[ch[dep].master_channel] + offset; + + if (ch[dep].time_diff_flag) { + int t = ch[dep].time_diff_index; + + if (ch[dep].time_diff_sign) { + t = -t; + begin -= t; + } else { + end -= t; + } + + for (smp = begin; smp < end; smp++) { + y = (1 << 6) + + MUL64(ch[dep].weighting[0], master[smp - 1 ]) + + MUL64(ch[dep].weighting[1], master[smp ]) + + MUL64(ch[dep].weighting[2], master[smp + 1 ]) + + MUL64(ch[dep].weighting[3], master[smp - 1 + t]) + + MUL64(ch[dep].weighting[4], master[smp + t]) + + MUL64(ch[dep].weighting[5], master[smp + 1 + t]); + + bd->raw_samples[smp] += y >> 7; + } + } else { + for (smp = begin; smp < end; smp++) { + y = (1 << 6) + + MUL64(ch[dep].weighting[0], master[smp - 1]) + + MUL64(ch[dep].weighting[1], master[smp ]) + + MUL64(ch[dep].weighting[2], master[smp + 1]); + + bd->raw_samples[smp] += y >> 7; + } + } + + dep++; + } + + return 0; +} + + +/** Read the frame data. + */ +static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) +{ + ALSSpecificConfig *sconf = &ctx->sconf; + AVCodecContext *avctx = ctx->avctx; + GetBitContext *gb = &ctx->gb; + unsigned int div_blocks[32]; ///< block sizes. + unsigned int c; + unsigned int js_blocks[2]; + + uint32_t bs_info = 0; + + // skip the size of the ra unit if present in the frame + if (sconf->ra_flag == RA_FLAG_FRAMES && ra_frame) + skip_bits_long(gb, 32); + + if (sconf->mc_coding && sconf->joint_stereo) { + ctx->js_switch = get_bits1(gb); + align_get_bits(gb); + } + + if (!sconf->mc_coding || ctx->js_switch) { + int independent_bs = !sconf->joint_stereo; + + for (c = 0; c < avctx->channels; c++) { + js_blocks[0] = 0; + js_blocks[1] = 0; + + get_block_sizes(ctx, div_blocks, &bs_info); + + // if joint_stereo and block_switching is set, independent decoding + // is signaled via the first bit of bs_info + if (sconf->joint_stereo && sconf->block_switching) + if (bs_info >> 31) + independent_bs = 2; + + // if this is the last channel, it has to be decoded independently + if (c == avctx->channels - 1) + independent_bs = 1; + + if (independent_bs) { + if (decode_blocks_ind(ctx, ra_frame, c, div_blocks, js_blocks)) + return -1; + + independent_bs--; + } else { + if (decode_blocks(ctx, ra_frame, c, div_blocks, js_blocks)) + return -1; + + c++; + } + + // store carryover raw samples + memmove(ctx->raw_samples[c] - sconf->max_order, + ctx->raw_samples[c] - sconf->max_order + sconf->frame_length, + sizeof(*ctx->raw_samples[c]) * sconf->max_order); + } + } else { // multi-channel coding + ALSBlockData bd = { 0 }; + int b, ret; + int *reverted_channels = ctx->reverted_channels; + unsigned int offset = 0; + + for (c = 0; c < avctx->channels; c++) + if (ctx->chan_data[c] < ctx->chan_data_buffer) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid channel data.\n"); + return -1; + } + + memset(reverted_channels, 0, sizeof(*reverted_channels) * avctx->channels); + + bd.ra_block = ra_frame; + bd.prev_raw_samples = ctx->prev_raw_samples; + + get_block_sizes(ctx, div_blocks, &bs_info); + + for (b = 0; b < ctx->num_blocks; b++) { + bd.block_length = div_blocks[b]; + + for (c = 0; c < avctx->channels; c++) { + bd.const_block = ctx->const_block + c; + bd.shift_lsbs = ctx->shift_lsbs + c; + bd.opt_order = ctx->opt_order + c; + bd.store_prev_samples = ctx->store_prev_samples + c; + bd.use_ltp = ctx->use_ltp + c; + bd.ltp_lag = ctx->ltp_lag + c; + bd.ltp_gain = ctx->ltp_gain[c]; + bd.lpc_cof = ctx->lpc_cof[c]; + bd.quant_cof = ctx->quant_cof[c]; + bd.raw_samples = ctx->raw_samples[c] + offset; + bd.raw_other = NULL; + + if ((ret = read_block(ctx, &bd)) < 0) + return ret; + if ((ret = read_channel_data(ctx, ctx->chan_data[c], c)) < 0) + return ret; + } + + for (c = 0; c < avctx->channels; c++) + if (revert_channel_correlation(ctx, &bd, ctx->chan_data, + reverted_channels, offset, c)) + return -1; + + for (c = 0; c < avctx->channels; c++) { + bd.const_block = ctx->const_block + c; + bd.shift_lsbs = ctx->shift_lsbs + c; + bd.opt_order = ctx->opt_order + c; + bd.store_prev_samples = ctx->store_prev_samples + c; + bd.use_ltp = ctx->use_ltp + c; + bd.ltp_lag = ctx->ltp_lag + c; + bd.ltp_gain = ctx->ltp_gain[c]; + bd.lpc_cof = ctx->lpc_cof[c]; + bd.quant_cof = ctx->quant_cof[c]; + bd.raw_samples = ctx->raw_samples[c] + offset; + + if ((ret = decode_block(ctx, &bd)) < 0) + return ret; + } + + memset(reverted_channels, 0, avctx->channels * sizeof(*reverted_channels)); + offset += div_blocks[b]; + bd.ra_block = 0; + } + + // store carryover raw samples + for (c = 0; c < avctx->channels; c++) + memmove(ctx->raw_samples[c] - sconf->max_order, + ctx->raw_samples[c] - sconf->max_order + sconf->frame_length, + sizeof(*ctx->raw_samples[c]) * sconf->max_order); + } + + // TODO: read_diff_float_data + + return 0; +} + + +/** Decode an ALS frame. + */ +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, + AVPacket *avpkt) +{ + ALSDecContext *ctx = avctx->priv_data; + AVFrame *frame = data; + ALSSpecificConfig *sconf = &ctx->sconf; + const uint8_t *buffer = avpkt->data; + int buffer_size = avpkt->size; + int invalid_frame, ret; + unsigned int c, sample, ra_frame, bytes_read, shift; + + init_get_bits(&ctx->gb, buffer, buffer_size * 8); + + // In the case that the distance between random access frames is set to zero + // (sconf->ra_distance == 0) no frame is treated as a random access frame. + // For the first frame, if prediction is used, all samples used from the + // previous frame are assumed to be zero. + ra_frame = sconf->ra_distance && !(ctx->frame_id % sconf->ra_distance); + + // the last frame to decode might have a different length + if (sconf->samples != 0xFFFFFFFF) + ctx->cur_frame_length = FFMIN(sconf->samples - ctx->frame_id * (uint64_t) sconf->frame_length, + sconf->frame_length); + else + ctx->cur_frame_length = sconf->frame_length; + + // decode the frame data + if ((invalid_frame = read_frame_data(ctx, ra_frame)) < 0) + av_log(ctx->avctx, AV_LOG_WARNING, + "Reading frame data failed. Skipping RA unit.\n"); + + ctx->frame_id++; + + /* get output buffer */ + frame->nb_samples = ctx->cur_frame_length; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + // transform decoded frame into output format + #define INTERLEAVE_OUTPUT(bps) \ + { \ + int##bps##_t *dest = (int##bps##_t*)frame->data[0]; \ + shift = bps - ctx->avctx->bits_per_raw_sample; \ + if (!ctx->cs_switch) { \ + for (sample = 0; sample < ctx->cur_frame_length; sample++) \ + for (c = 0; c < avctx->channels; c++) \ + *dest++ = ctx->raw_samples[c][sample] << shift; \ + } else { \ + for (sample = 0; sample < ctx->cur_frame_length; sample++) \ + for (c = 0; c < avctx->channels; c++) \ + *dest++ = ctx->raw_samples[sconf->chan_pos[c]][sample] << shift; \ + } \ + } + + if (ctx->avctx->bits_per_raw_sample <= 16) { + INTERLEAVE_OUTPUT(16) + } else { + INTERLEAVE_OUTPUT(32) + } + + // update CRC + if (sconf->crc_enabled && (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL))) { + int swap = HAVE_BIGENDIAN != sconf->msb_first; + + if (ctx->avctx->bits_per_raw_sample == 24) { + int32_t *src = (int32_t *)frame->data[0]; + + for (sample = 0; + sample < ctx->cur_frame_length * avctx->channels; + sample++) { + int32_t v; + + if (swap) + v = av_bswap32(src[sample]); + else + v = src[sample]; + if (!HAVE_BIGENDIAN) + v >>= 8; + + ctx->crc = av_crc(ctx->crc_table, ctx->crc, (uint8_t*)(&v), 3); + } + } else { + uint8_t *crc_source; + + if (swap) { + if (ctx->avctx->bits_per_raw_sample <= 16) { + int16_t *src = (int16_t*) frame->data[0]; + int16_t *dest = (int16_t*) ctx->crc_buffer; + for (sample = 0; + sample < ctx->cur_frame_length * avctx->channels; + sample++) + *dest++ = av_bswap16(src[sample]); + } else { + ctx->dsp.bswap_buf((uint32_t*)ctx->crc_buffer, + (uint32_t *)frame->data[0], + ctx->cur_frame_length * avctx->channels); + } + crc_source = ctx->crc_buffer; + } else { + crc_source = frame->data[0]; + } + + ctx->crc = av_crc(ctx->crc_table, ctx->crc, crc_source, + ctx->cur_frame_length * avctx->channels * + av_get_bytes_per_sample(avctx->sample_fmt)); + } + + + // check CRC sums if this is the last frame + if (ctx->cur_frame_length != sconf->frame_length && + ctx->crc_org != ctx->crc) { + av_log(avctx, AV_LOG_ERROR, "CRC error.\n"); + } + } + + *got_frame_ptr = 1; + + bytes_read = invalid_frame ? buffer_size : + (get_bits_count(&ctx->gb) + 7) >> 3; + + return bytes_read; +} + + +/** Uninitialize the ALS decoder. + */ +static av_cold int decode_end(AVCodecContext *avctx) +{ + ALSDecContext *ctx = avctx->priv_data; + + av_freep(&ctx->sconf.chan_pos); + + ff_bgmc_end(&ctx->bgmc_lut, &ctx->bgmc_lut_status); + + av_freep(&ctx->const_block); + av_freep(&ctx->shift_lsbs); + av_freep(&ctx->opt_order); + av_freep(&ctx->store_prev_samples); + av_freep(&ctx->use_ltp); + av_freep(&ctx->ltp_lag); + av_freep(&ctx->ltp_gain); + av_freep(&ctx->ltp_gain_buffer); + av_freep(&ctx->quant_cof); + av_freep(&ctx->lpc_cof); + av_freep(&ctx->quant_cof_buffer); + av_freep(&ctx->lpc_cof_buffer); + av_freep(&ctx->lpc_cof_reversed_buffer); + av_freep(&ctx->prev_raw_samples); + av_freep(&ctx->raw_samples); + av_freep(&ctx->raw_buffer); + av_freep(&ctx->chan_data); + av_freep(&ctx->chan_data_buffer); + av_freep(&ctx->reverted_channels); + av_freep(&ctx->crc_buffer); + + return 0; +} + + +/** Initialize the ALS decoder. + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + unsigned int c; + unsigned int channel_size; + int num_buffers; + ALSDecContext *ctx = avctx->priv_data; + ALSSpecificConfig *sconf = &ctx->sconf; + ctx->avctx = avctx; + + if (!avctx->extradata) { + av_log(avctx, AV_LOG_ERROR, "Missing required ALS extradata.\n"); + return -1; + } + + if (read_specific_config(ctx)) { + av_log(avctx, AV_LOG_ERROR, "Reading ALSSpecificConfig failed.\n"); + decode_end(avctx); + return -1; + } + + if (check_specific_config(ctx)) { + decode_end(avctx); + return -1; + } + + if (sconf->bgmc) + ff_bgmc_init(avctx, &ctx->bgmc_lut, &ctx->bgmc_lut_status); + + if (sconf->floating) { + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + avctx->bits_per_raw_sample = 32; + } else { + avctx->sample_fmt = sconf->resolution > 1 + ? AV_SAMPLE_FMT_S32 : AV_SAMPLE_FMT_S16; + avctx->bits_per_raw_sample = (sconf->resolution + 1) * 8; + } + + // set maximum Rice parameter for progressive decoding based on resolution + // This is not specified in 14496-3 but actually done by the reference + // codec RM22 revision 2. + ctx->s_max = sconf->resolution > 1 ? 31 : 15; + + // set lag value for long-term prediction + ctx->ltp_lag_length = 8 + (avctx->sample_rate >= 96000) + + (avctx->sample_rate >= 192000); + + // allocate quantized parcor coefficient buffer + num_buffers = sconf->mc_coding ? avctx->channels : 1; + + ctx->quant_cof = av_malloc(sizeof(*ctx->quant_cof) * num_buffers); + ctx->lpc_cof = av_malloc(sizeof(*ctx->lpc_cof) * num_buffers); + ctx->quant_cof_buffer = av_malloc(sizeof(*ctx->quant_cof_buffer) * + num_buffers * sconf->max_order); + ctx->lpc_cof_buffer = av_malloc(sizeof(*ctx->lpc_cof_buffer) * + num_buffers * sconf->max_order); + ctx->lpc_cof_reversed_buffer = av_malloc(sizeof(*ctx->lpc_cof_buffer) * + sconf->max_order); + + if (!ctx->quant_cof || !ctx->lpc_cof || + !ctx->quant_cof_buffer || !ctx->lpc_cof_buffer || + !ctx->lpc_cof_reversed_buffer) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + return AVERROR(ENOMEM); + } + + // assign quantized parcor coefficient buffers + for (c = 0; c < num_buffers; c++) { + ctx->quant_cof[c] = ctx->quant_cof_buffer + c * sconf->max_order; + ctx->lpc_cof[c] = ctx->lpc_cof_buffer + c * sconf->max_order; + } + + // allocate and assign lag and gain data buffer for ltp mode + ctx->const_block = av_malloc (sizeof(*ctx->const_block) * num_buffers); + ctx->shift_lsbs = av_malloc (sizeof(*ctx->shift_lsbs) * num_buffers); + ctx->opt_order = av_malloc (sizeof(*ctx->opt_order) * num_buffers); + ctx->store_prev_samples = av_malloc(sizeof(*ctx->store_prev_samples) * num_buffers); + ctx->use_ltp = av_mallocz(sizeof(*ctx->use_ltp) * num_buffers); + ctx->ltp_lag = av_malloc (sizeof(*ctx->ltp_lag) * num_buffers); + ctx->ltp_gain = av_malloc (sizeof(*ctx->ltp_gain) * num_buffers); + ctx->ltp_gain_buffer = av_malloc (sizeof(*ctx->ltp_gain_buffer) * + num_buffers * 5); + + if (!ctx->const_block || !ctx->shift_lsbs || + !ctx->opt_order || !ctx->store_prev_samples || + !ctx->use_ltp || !ctx->ltp_lag || + !ctx->ltp_gain || !ctx->ltp_gain_buffer) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + decode_end(avctx); + return AVERROR(ENOMEM); + } + + for (c = 0; c < num_buffers; c++) + ctx->ltp_gain[c] = ctx->ltp_gain_buffer + c * 5; + + // allocate and assign channel data buffer for mcc mode + if (sconf->mc_coding) { + ctx->chan_data_buffer = av_malloc(sizeof(*ctx->chan_data_buffer) * + num_buffers * num_buffers); + ctx->chan_data = av_malloc(sizeof(*ctx->chan_data) * + num_buffers); + ctx->reverted_channels = av_malloc(sizeof(*ctx->reverted_channels) * + num_buffers); + + if (!ctx->chan_data_buffer || !ctx->chan_data || !ctx->reverted_channels) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + decode_end(avctx); + return AVERROR(ENOMEM); + } + + for (c = 0; c < num_buffers; c++) + ctx->chan_data[c] = ctx->chan_data_buffer + c * num_buffers; + } else { + ctx->chan_data = NULL; + ctx->chan_data_buffer = NULL; + ctx->reverted_channels = NULL; + } + + channel_size = sconf->frame_length + sconf->max_order; + + ctx->prev_raw_samples = av_malloc (sizeof(*ctx->prev_raw_samples) * sconf->max_order); + ctx->raw_buffer = av_mallocz(sizeof(*ctx-> raw_buffer) * avctx->channels * channel_size); + ctx->raw_samples = av_malloc (sizeof(*ctx-> raw_samples) * avctx->channels); + + // allocate previous raw sample buffer + if (!ctx->prev_raw_samples || !ctx->raw_buffer|| !ctx->raw_samples) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + decode_end(avctx); + return AVERROR(ENOMEM); + } + + // assign raw samples buffers + ctx->raw_samples[0] = ctx->raw_buffer + sconf->max_order; + for (c = 1; c < avctx->channels; c++) + ctx->raw_samples[c] = ctx->raw_samples[c - 1] + channel_size; + + // allocate crc buffer + if (HAVE_BIGENDIAN != sconf->msb_first && sconf->crc_enabled && + (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL))) { + ctx->crc_buffer = av_malloc(sizeof(*ctx->crc_buffer) * + ctx->cur_frame_length * + avctx->channels * + av_get_bytes_per_sample(avctx->sample_fmt)); + if (!ctx->crc_buffer) { + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + decode_end(avctx); + return AVERROR(ENOMEM); + } + } + + ff_dsputil_init(&ctx->dsp, avctx); + + return 0; +} + + +/** Flush (reset) the frame ID after seeking. + */ +static av_cold void flush(AVCodecContext *avctx) +{ + ALSDecContext *ctx = avctx->priv_data; + + ctx->frame_id = 0; +} + + +AVCodec ff_als_decoder = { + .name = "als", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP4ALS, + .priv_data_size = sizeof(ALSDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .flush = flush, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Audio Lossless Coding (ALS)"), +}; diff --git a/ffmpeg/libavcodec/amr.h b/ffmpeg/libavcodec/amr.h new file mode 100644 index 0000000..1ac73ab --- /dev/null +++ b/ffmpeg/libavcodec/amr.h @@ -0,0 +1,70 @@ +/* + * Shared functions between AMR codecs + * + * Copyright (c) 2010 Marcelo Galvao Povoa + * + * 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 + */ + +#ifndef AVCODEC_AMR_H +#define AVCODEC_AMR_H + +#include + +#include "avcodec.h" + +#ifdef AMR_USE_16BIT_TABLES +#define R_TABLE_TYPE uint16_t +#else +#define R_TABLE_TYPE uint8_t +#endif + +/** + * Fill the frame structure variables from bitstream by parsing the + * given reordering table that uses the following format: + * + * Each field (16 bits) in the AMR Frame is stored as: + * - one byte for the number of bits in the field + * - one byte for the field index + * - then, one byte for each bit of the field (from most-significant to least) + * of the position of that bit in the AMR frame. + * + * @param out pointer to the frame struct + * @param size the size in bytes of the frame struct + * @param data input bitstream after the frame header + * @param ord_table the reordering table as above + */ +static inline void ff_amr_bit_reorder(uint16_t *out, int size, + const uint8_t *data, + const R_TABLE_TYPE *ord_table) +{ + int field_size; + + memset(out, 0, size); + while ((field_size = *ord_table++)) { + int field = 0; + int field_offset = *ord_table++; + while (field_size--) { + int bit = *ord_table++; + field <<= 1; + field |= data[bit >> 3] >> (bit & 7) & 1; + } + out[field_offset >> 1] = field; + } +} + +#endif /* AVCODEC_AMR_H */ diff --git a/ffmpeg/libavcodec/amrnbdata.h b/ffmpeg/libavcodec/amrnbdata.h new file mode 100644 index 0000000..435fd99 --- /dev/null +++ b/ffmpeg/libavcodec/amrnbdata.h @@ -0,0 +1,1671 @@ +/* + * AMR narrowband data and definitions + * Copyright (c) 2006-2007 Robert Swain + * Copyright (c) 2009 Colin McQuillan + * + * 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 + */ + + +/** + * @file + * AMR narrowband data and definitions + */ + +#ifndef AVCODEC_AMRNBDATA_H +#define AVCODEC_AMRNBDATA_H + +#include + +#include "libavutil/common.h" /* offsetof */ + +#define AMR_SUBFRAME_SIZE 40 ///< samples per subframe + +/** Frame type (Table 1a in 3GPP TS 26.101) */ +enum Mode { + MODE_4k75 = 0, ///< 4.75 kbit/s + MODE_5k15, ///< 5.15 kbit/s + MODE_5k9, ///< 5.90 kbit/s + MODE_6k7, ///< 6.70 kbit/s + MODE_7k4, ///< 7.40 kbit/s + MODE_7k95, ///< 7.95 kbit/s + MODE_10k2, ///< 10.2 kbit/s + MODE_12k2, ///< 12.2 kbit/s + MODE_DTX, ///< silent frame + N_MODES, ///< number of modes + NO_DATA = 15 ///< no transmission +}; + +#define LP_FILTER_ORDER 10 ///< linear predictive coding filter order + +/** + * AMRNB unpacked data subframe + */ +typedef struct AMRNBSubframe { + uint16_t p_lag; ///< index to decode the pitch lag + uint16_t p_gain; ///< index to decode the pitch gain + uint16_t fixed_gain; ///< index to decode the fixed gain factor, for MODE_12k2 and MODE_7k95 + uint16_t pulses[10]; ///< pulses: 10 for MODE_12k2, 7 for MODE_10k2, and index and sign for others +} AMRNBSubframe; + +/** + * AMRNB unpacked data frame + */ +typedef struct AMRNBFrame { + uint16_t lsf[5]; ///< lsf parameters: 5 parameters for MODE_12k2, only 3 for other modes + AMRNBSubframe subframe[4]; ///< unpacked data for each subframe +} AMRNBFrame; + +/** The index of a frame parameter */ +#define AMR_BIT(field) (offsetof(AMRNBFrame, field)) +/** The index of a subframe-specific parameter */ +#define AMR_OF(frame_num, variable) AMR_BIT(subframe[frame_num].variable) + +// The following order* tables are used to convert AMR frame parameters to and +// from a bitstream. See 3GPP TS 26.101 for more information. +// Each field in AMRNBFrame is stored as: +// * one byte for the number of bits in the field +// * one byte for the field index +// * then, one byte for each bit of the field (from most-significant to least) +// of the position of that bit in the AMR frame. +static const uint8_t order_MODE_4k75[] = { + 8, AMR_BIT(lsf[0]), 7, 6, 5, 4, 3, 2, 1, 0, + 8, AMR_BIT(lsf[1]), 15, 14, 13, 12, 11, 10, 9, 8, + 7, AMR_BIT(lsf[2]), 51, 35, 34, 50, 33, 49, 32, + 8, AMR_OF(0,p_lag), 23, 22, 21, 20, 19, 18, 43, 42, + 8, AMR_OF(0,p_gain), 54, 55, 40, 41, 24, 25, 26, 27, + 7, AMR_OF(0,pulses[0]), 92, 68, 67, 84, 66, 65, 80, + 2, AMR_OF(0,pulses[1]), 53, 52, + 4, AMR_OF(1,p_lag), 17, 16, 48, 63, + 7, AMR_OF(1,pulses[0]), 91, 64, 79, 83, 78, 77, 95, + 2, AMR_OF(1,pulses[1]), 62, 61, + 4, AMR_OF(2,p_lag), 31, 30, 60, 59, + 8, AMR_OF(2,p_gain), 44, 45, 46, 47, 36, 37, 38, 39, + 7, AMR_OF(2,pulses[0]), 90, 76, 75, 82, 74, 73, 94, + 2, AMR_OF(2,pulses[1]), 58, 57, + 4, AMR_OF(3,p_lag), 29, 28, 56, 71, + 7, AMR_OF(3,pulses[0]), 89, 72, 87, 81, 86, 85, 93, + 2, AMR_OF(3,pulses[1]), 70, 69, + 0 +}; + +static const uint8_t order_MODE_5k15[] = { + 8, AMR_BIT(lsf[0]), 0, 1, 2, 3, 4, 5, 6, 7, + 8, AMR_BIT(lsf[1]), 8, 9, 10, 11, 12, 13, 14, 15, + 7, AMR_BIT(lsf[2]), 70, 51, 43, 71, 50, 60, 49, + 8, AMR_OF(0,p_lag), 23, 22, 21, 20, 19, 47, 54, 59, + 6, AMR_OF(0,p_gain), 48, 42, 35, 29, 30, 31, + 7, AMR_OF(0,pulses[0]), 92, 84, 82, 100, 79, 72, 88, + 2, AMR_OF(0,pulses[1]), 67, 68, + 4, AMR_OF(1,p_lag), 18, 46, 53, 58, + 6, AMR_OF(1,p_gain), 63, 41, 34, 26, 27, 28, + 7, AMR_OF(1,pulses[0]), 91, 83, 81, 99, 78, 87, 103, + 2, AMR_OF(1,pulses[1]), 65, 66, + 4, AMR_OF(2,p_lag), 17, 45, 52, 57, + 6, AMR_OF(2,p_gain), 62, 40, 33, 39, 24, 25, + 7, AMR_OF(2,pulses[0]), 90, 80, 95, 98, 77, 86, 102, + 2, AMR_OF(2,pulses[1]), 75, 64, + 4, AMR_OF(3,p_lag), 16, 44, 56, 69, + 6, AMR_OF(3,p_gain), 61, 55, 32, 36, 37, 38, + 7, AMR_OF(3,pulses[0]), 89, 94, 93, 97, 76, 85, 101, + 2, AMR_OF(3,pulses[1]), 73, 74, + 0 +}; + +static const uint8_t order_MODE_5k9[] = { + 8, AMR_BIT(lsf[0]), 7, 6, 0, 3, 5, 4, 2, 1, + 9, AMR_BIT(lsf[1]), 13, 12, 8, 11, 10, 15, 9, 14, 23, + 9, AMR_BIT(lsf[2]), 71, 56, 60, 70, 59, 57, 58, 69, 76, + 8, AMR_OF(0,p_lag), 16, 18, 22, 20, 30, 38, 44, 42, + 6, AMR_OF(0,p_gain), 75, 48, 52, 40, 34, 26, + 9, AMR_OF(0,pulses[0]), 101, 89, 93, 117, 105, 81, 85, 109, 97, + 2, AMR_OF(0,pulses[1]), 67, 78, + 4, AMR_OF(1,p_lag), 28, 36, 46, 87, + 6, AMR_OF(1,p_gain), 74, 63, 51, 55, 33, 25, + 9, AMR_OF(1,pulses[0]), 100, 88, 92, 116, 104, 80, 84, 108, 96, + 2, AMR_OF(1,pulses[1]), 64, 79, + 8, AMR_OF(2,p_lag), 31, 17, 21, 19, 29, 37, 43, 41, + 6, AMR_OF(2,p_gain), 73, 62, 50, 54, 32, 24, + 9, AMR_OF(2,pulses[0]), 99, 103, 91, 115, 119, 95, 83, 107, 111, + 2, AMR_OF(2,pulses[1]), 66, 77, + 4, AMR_OF(3,p_lag), 27, 35, 45, 86, + 6, AMR_OF(3,p_gain), 72, 61, 49, 53, 47, 39, + 9, AMR_OF(3,pulses[0]), 98, 102, 90, 114, 118, 94, 82, 106, 110, + 2, AMR_OF(3,pulses[1]), 65, 68, + 0 +}; + +static const uint8_t order_MODE_6k7[] = { + 8, AMR_BIT(lsf[0]), 7, 6, 15, 4, 5, 3, 2, 0, + 9, AMR_BIT(lsf[1]), 14, 13, 8, 12, 10, 1, 9, 11, 29, + 9, AMR_BIT(lsf[2]), 57, 58, 50, 56, 60, 59, 49, 71, 70, + 8, AMR_OF(0,p_lag), 17, 19, 23, 21, 31, 24, 32, 52, + 7, AMR_OF(0,p_gain), 36, 82, 69, 46, 42, 48, 77, + 11, AMR_OF(0,pulses[0]), 109, 97, 133, 121, 101, 89, 125, 113, 93, 117, + 105, + 3, AMR_OF(0,pulses[1]), 81, 73, 65, + 4, AMR_OF(1,p_lag), 28, 26, 38, 54, + 7, AMR_OF(1,p_gain), 35, 83, 68, 45, 41, 63, 76, + 11, AMR_OF(1,pulses[0]), 108, 96, 132, 120, 100, 88, 124, 112, 92, 116, + 104, + 3, AMR_OF(1,pulses[1]), 80, 72, 64, + 8, AMR_OF(2,p_lag), 16, 18, 22, 20, 30, 39, 47, 51, + 7, AMR_OF(2,p_gain), 34, 84, 67, 44, 40, 62, 75, + 11, AMR_OF(2,pulses[0]), 107, 111, 131, 135, 99, 103, 123, 127, 91, 115, + 119, + 3, AMR_OF(2,pulses[1]), 95, 87, 79, + 4, AMR_OF(3,p_lag), 27, 25, 37, 53, + 7, AMR_OF(3,p_gain), 33, 85, 66, 43, 55, 61, 74, + 11, AMR_OF(3,pulses[0]), 106, 110, 130, 134, 98, 102, 122, 126, 90, 114, + 118, + 3, AMR_OF(3,pulses[1]), 94, 86, 78, + 0 +}; + +static const uint8_t order_MODE_7k4[] = { + 8, AMR_BIT(lsf[0]), 7, 6, 5, 4, 3, 2, 1, 0, + 9, AMR_BIT(lsf[1]), 15, 14, 13, 12, 11, 10, 9, 8, 23, + 9, AMR_BIT(lsf[2]), 53, 52, 51, 58, 40, 55, 54, 57, 56, + 8, AMR_OF(0,p_lag), 22, 20, 18, 16, 30, 50, 95, 94, + 7, AMR_OF(0,p_gain), 28, 24, 73, 36, 32, 62, 67, + 13, AMR_OF(0,pulses[0]), 127, 123, 135, 131, 143, 139, 151, 103, 102, 101, + 100, 99, 98, + 4, AMR_OF(0,pulses[1]), 83, 75, 79, 71, + 5, AMR_OF(1,p_lag), 44, 42, 49, 93, 92, + 7, AMR_OF(1,p_gain), 27, 39, 72, 35, 47, 61, 66, + 13, AMR_OF(1,pulses[0]), 126, 122, 134, 130, 142, 138, 150, 97, 96, 111, + 110, 109, 108, + 4, AMR_OF(1,pulses[1]), 82, 74, 78, 70, + 8, AMR_OF(2,p_lag), 21, 19, 17, 31, 29, 48, 91, 90, + 7, AMR_OF(2,p_gain), 26, 38, 87, 34, 46, 60, 65, + 13, AMR_OF(2,pulses[0]), 125, 121, 133, 129, 141, 137, 149, 107, 106, 105, + 104, 119, 118, + 4, AMR_OF(2,pulses[1]), 81, 85, 77, 69, + 5, AMR_OF(3,p_lag), 43, 41, 63, 89, 88, + 7, AMR_OF(3,p_gain), 25, 37, 86, 33, 45, 59, 64, + 13, AMR_OF(3,pulses[0]), 124, 120, 132, 128, 140, 136, 148, 117, 116, 115, + 114, 113, 112, + 4, AMR_OF(3,pulses[1]), 80, 84, 76, 68, + 0 +}; + +static const uint8_t order_MODE_7k95[] = { + 9, AMR_BIT(lsf[0]), 67, 68, 1, 2, 3, 4, 5, 6, 7, + 9, AMR_BIT(lsf[1]), 14, 13, 9, 12, 11, 0, 10, 15, 8, + 9, AMR_BIT(lsf[2]), 18, 19, 23, 17, 22, 20, 21, 66, 65, + 8, AMR_OF(0,p_lag), 44, 42, 40, 54, 52, 56, 64, 78, + 4, AMR_OF(0,p_gain), 36, 32, 72, 80, + 5, AMR_OF(0,fixed_gain), 16, 28, 24, 60, 84, + 13, AMR_OF(0,pulses[0]), 135, 109, 144, 156, 120, 97, 148, 121, 101, 122, + 123, 89, 124, + 4, AMR_OF(0,pulses[1]), 125, 126, 127, 112, + 6, AMR_OF(1,p_lag), 50, 48, 62, 70, 76, 74, + 4, AMR_OF(1,p_gain), 35, 47, 87, 95, + 5, AMR_OF(1,fixed_gain), 31, 27, 39, 59, 83, + 13, AMR_OF(1,pulses[0]), 129, 108, 159, 155, 130, 96, 147, 131, 100, 132, + 133, 88, 134, + 4, AMR_OF(1,pulses[1]), 113, 114, 115, 116, + 8, AMR_OF(2,p_lag), 43, 41, 55, 53, 51, 71, 79, 77, + 4, AMR_OF(2,p_gain), 34, 46, 86, 94, + 5, AMR_OF(2,fixed_gain), 30, 26, 38, 58, 82, + 13, AMR_OF(2,pulses[0]), 139, 107, 158, 154, 140, 111, 146, 141, 99, 142, + 143, 103, 128, + 4, AMR_OF(2,pulses[1]), 105, 90, 91, 92, + 6, AMR_OF(3,p_lag), 49, 63, 61, 69, 75, 73, + 4, AMR_OF(3,p_gain), 33, 45, 85, 93, + 5, AMR_OF(3,fixed_gain), 29, 25, 37, 57, 81, + 13, AMR_OF(3,pulses[0]), 149, 106, 157, 153, 150, 110, 145, 151, 98, 136, + 137, 102, 138, + 4, AMR_OF(3,pulses[1]), 117, 118, 119, 104, + 0 +}; + +static const uint8_t order_MODE_10k2[] = { + 8, AMR_BIT(lsf[0]), 0, 1, 2, 3, 4, 5, 6, 7, + 9, AMR_BIT(lsf[1]), 23, 8, 9, 10, 11, 12, 13, 14, 15, + 9, AMR_BIT(lsf[2]), 57, 58, 62, 56, 60, 59, 61, 71, 70, + 8, AMR_OF(0,p_lag), 22, 21, 20, 19, 18, 17, 42, 41, + 7, AMR_OF(0,p_gain), 38, 50, 84, 37, 36, 85, 83, + 1, AMR_OF(0,pulses[0]), 66, + 1, AMR_OF(0,pulses[1]), 67, + 1, AMR_OF(0,pulses[2]), 68, + 1, AMR_OF(0,pulses[3]), 69, + 10, AMR_OF(0,pulses[4]), 145, 144, 156, 153, 154, 163, 161, 192, 206, 195, + 10, AMR_OF(0,pulses[5]), 158, 159, 157, 152, 155, 165, 160, 205, 204, 194, + 7, AMR_OF(0,pulses[6]), 167, 166, 162, 164, 196, 207, 193, + 5, AMR_OF(1,p_lag), 26, 25, 54, 53, 89, + 7, AMR_OF(1,p_gain), 35, 49, 81, 34, 33, 82, 80, + 1, AMR_OF(1,pulses[0]), 78, + 1, AMR_OF(1,pulses[1]), 79, + 1, AMR_OF(1,pulses[2]), 64, + 1, AMR_OF(1,pulses[3]), 65, + 10, AMR_OF(1,pulses[4]), 103, 102, 98, 111, 96, 105, 119, 185, 199, 188, + 10, AMR_OF(1,pulses[5]), 100, 101, 99, 110, 97, 107, 118, 198, 197, 187, + 7, AMR_OF(1,pulses[6]), 109, 108, 104, 106, 189, 184, 186, + 8, AMR_OF(2,p_lag), 16, 31, 30, 29, 28, 27, 40, 55, + 7, AMR_OF(2,p_gain), 32, 48, 94, 47, 46, 95, 93, + 1, AMR_OF(2,pulses[0]), 74, + 1, AMR_OF(2,pulses[1]), 75, + 1, AMR_OF(2,pulses[2]), 76, + 1, AMR_OF(2,pulses[3]), 77, + 10, AMR_OF(2,pulses[4]), 117, 116, 112, 125, 126, 135, 133, 178, 176, 181, + 10, AMR_OF(2,pulses[5]), 114, 115, 113, 124, 127, 121, 132, 191, 190, 180, + 7, AMR_OF(2,pulses[6]), 123, 122, 134, 120, 182, 177, 179, + 5, AMR_OF(3,p_lag), 24, 39, 52, 51, 88, + 7, AMR_OF(3,p_gain), 45, 63, 91, 44, 43, 92, 90, + 1, AMR_OF(3,pulses[0]), 86, + 1, AMR_OF(3,pulses[1]), 87, + 1, AMR_OF(3,pulses[2]), 72, + 1, AMR_OF(3,pulses[3]), 73, + 10, AMR_OF(3,pulses[4]), 131, 130, 142, 139, 140, 149, 147, 171, 169, 174, + 10, AMR_OF(3,pulses[5]), 128, 129, 143, 138, 141, 151, 146, 168, 183, 173, + 7, AMR_OF(3,pulses[6]), 137, 136, 148, 150, 175, 170, 172, + 0 +}; + +static const uint8_t order_MODE_12k2[] = { + 7, AMR_BIT(lsf[0]), 7, 6, 5, 4, 3, 2, 1, + 8, AMR_BIT(lsf[1]), 0, 15, 14, 13, 12, 11, 10, 9, + 9, AMR_BIT(lsf[2]), 23, 22, 21, 20, 19, 18, 17, 16, 8, + 8, AMR_BIT(lsf[3]), 31, 30, 29, 28, 27, 86, 85, 84, + 6, AMR_BIT(lsf[4]), 83, 82, 81, 80, 127, 126, + 9, AMR_OF(0,p_lag), 26, 24, 38, 36, 34, 32, 46, 44, 42, + 4, AMR_OF(0,p_gain), 40, 52, 48, 95, + 5, AMR_OF(0,fixed_gain), 60, 56, 68, 91, 111, + 3, AMR_OF(0,pulses[0]), 191, 176, 177, + 4, AMR_OF(0,pulses[1]), 103, 123, 124, 125, + 3, AMR_OF(0,pulses[2]), 188, 189, 190, + 4, AMR_OF(0,pulses[3]), 99, 120, 121, 122, + 3, AMR_OF(0,pulses[4]), 185, 186, 187, + 4, AMR_OF(0,pulses[5]), 107, 133, 134, 135, + 3, AMR_OF(0,pulses[6]), 198, 199, 184, + 4, AMR_OF(0,pulses[7]), 119, 130, 131, 132, + 3, AMR_OF(0,pulses[8]), 195, 196, 197, + 4, AMR_OF(0,pulses[9]), 115, 143, 128, 129, + 6, AMR_OF(1,p_lag), 64, 78, 76, 74, 72, 245, + 4, AMR_OF(1,p_gain), 55, 51, 63, 94, + 5, AMR_OF(1,fixed_gain), 59, 71, 67, 90, 110, + 3, AMR_OF(1,pulses[0]), 192, 193, 194, + 4, AMR_OF(1,pulses[1]), 102, 140, 141, 142, + 3, AMR_OF(1,pulses[2]), 205, 206, 207, + 4, AMR_OF(1,pulses[3]), 98, 137, 138, 139, + 3, AMR_OF(1,pulses[4]), 202, 203, 204, + 4, AMR_OF(1,pulses[5]), 106, 150, 151, 136, + 3, AMR_OF(1,pulses[6]), 215, 200, 201, + 4, AMR_OF(1,pulses[7]), 118, 147, 148, 149, + 3, AMR_OF(1,pulses[8]), 212, 213, 214, + 4, AMR_OF(1,pulses[9]), 114, 144, 145, 146, + 9, AMR_OF(2,p_lag), 25, 39, 37, 35, 33, 47, 45, 43, 41, + 4, AMR_OF(2,p_gain), 54, 50, 62, 93, + 5, AMR_OF(2,fixed_gain), 58, 70, 66, 89, 109, + 3, AMR_OF(2,pulses[0]), 209, 210, 211, + 4, AMR_OF(2,pulses[1]), 101, 157, 158, 159, + 3, AMR_OF(2,pulses[2]), 222, 223, 208, + 4, AMR_OF(2,pulses[3]), 97, 154, 155, 156, + 3, AMR_OF(2,pulses[4]), 219, 220, 221, + 4, AMR_OF(2,pulses[5]), 105, 167, 152, 153, + 3, AMR_OF(2,pulses[6]), 216, 217, 218, + 4, AMR_OF(2,pulses[7]), 117, 164, 165, 166, + 3, AMR_OF(2,pulses[8]), 229, 230, 231, + 4, AMR_OF(2,pulses[9]), 113, 161, 162, 163, + 6, AMR_OF(3,p_lag), 79, 77, 75, 73, 87, 244, + 4, AMR_OF(3,p_gain), 53, 49, 61, 92, + 5, AMR_OF(3,fixed_gain), 57, 69, 65, 88, 108, + 3, AMR_OF(3,pulses[0]), 226, 227, 228, + 4, AMR_OF(3,pulses[1]), 100, 174, 175, 160, + 3, AMR_OF(3,pulses[2]), 239, 224, 225, + 4, AMR_OF(3,pulses[3]), 96, 171, 172, 173, + 3, AMR_OF(3,pulses[4]), 236, 237, 238, + 4, AMR_OF(3,pulses[5]), 104, 168, 169, 170, + 3, AMR_OF(3,pulses[6]), 233, 234, 235, + 4, AMR_OF(3,pulses[7]), 116, 181, 182, 183, + 3, AMR_OF(3,pulses[8]), 246, 247, 232, + 4, AMR_OF(3,pulses[9]), 112, 178, 179, 180, + 0 +}; + +/** + * position of the bitmapping data for each packet type in + * the AMRNBFrame + */ +static const uint8_t * const amr_unpacking_bitmaps_per_mode[N_MODES] = { + order_MODE_4k75, + order_MODE_5k15, + order_MODE_5k9, + order_MODE_6k7, + order_MODE_7k4, + order_MODE_7k95, + order_MODE_10k2, + order_MODE_12k2, +}; + +/** number of bytes for each mode */ +static const uint8_t frame_sizes_nb[N_MODES] = { + 12, 13, 15, 17, 19, 20, 26, 31, 5 +}; + +/** + * Base-5 representation for values 0-124 + * + * This is useful for decoding pulse positions in 10.2 kbit/s frames. + * Safe values are provided for out of range positions 125-127. + */ +static const uint8_t base_five_table[128][3] = { + {0, 0, 0}, {0, 0, 1}, {0, 0, 2}, {0, 0, 3}, {0, 0, 4}, {0, 1, 0}, {0, 1, 1}, + {0, 1, 2}, {0, 1, 3}, {0, 1, 4}, {0, 2, 0}, {0, 2, 1}, {0, 2, 2}, {0, 2, 3}, + {0, 2, 4}, {0, 3, 0}, {0, 3, 1}, {0, 3, 2}, {0, 3, 3}, {0, 3, 4}, {0, 4, 0}, + {0, 4, 1}, {0, 4, 2}, {0, 4, 3}, {0, 4, 4}, {1, 0, 0}, {1, 0, 1}, {1, 0, 2}, + {1, 0, 3}, {1, 0, 4}, {1, 1, 0}, {1, 1, 1}, {1, 1, 2}, {1, 1, 3}, {1, 1, 4}, + {1, 2, 0}, {1, 2, 1}, {1, 2, 2}, {1, 2, 3}, {1, 2, 4}, {1, 3, 0}, {1, 3, 1}, + {1, 3, 2}, {1, 3, 3}, {1, 3, 4}, {1, 4, 0}, {1, 4, 1}, {1, 4, 2}, {1, 4, 3}, + {1, 4, 4}, {2, 0, 0}, {2, 0, 1}, {2, 0, 2}, {2, 0, 3}, {2, 0, 4}, {2, 1, 0}, + {2, 1, 1}, {2, 1, 2}, {2, 1, 3}, {2, 1, 4}, {2, 2, 0}, {2, 2, 1}, {2, 2, 2}, + {2, 2, 3}, {2, 2, 4}, {2, 3, 0}, {2, 3, 1}, {2, 3, 2}, {2, 3, 3}, {2, 3, 4}, + {2, 4, 0}, {2, 4, 1}, {2, 4, 2}, {2, 4, 3}, {2, 4, 4}, {3, 0, 0}, {3, 0, 1}, + {3, 0, 2}, {3, 0, 3}, {3, 0, 4}, {3, 1, 0}, {3, 1, 1}, {3, 1, 2}, {3, 1, 3}, + {3, 1, 4}, {3, 2, 0}, {3, 2, 1}, {3, 2, 2}, {3, 2, 3}, {3, 2, 4}, {3, 3, 0}, + {3, 3, 1}, {3, 3, 2}, {3, 3, 3}, {3, 3, 4}, {3, 4, 0}, {3, 4, 1}, {3, 4, 2}, + {3, 4, 3}, {3, 4, 4}, {4, 0, 0}, {4, 0, 1}, {4, 0, 2}, {4, 0, 3}, {4, 0, 4}, + {4, 1, 0}, {4, 1, 1}, {4, 1, 2}, {4, 1, 3}, {4, 1, 4}, {4, 2, 0}, {4, 2, 1}, + {4, 2, 2}, {4, 2, 3}, {4, 2, 4}, {4, 3, 0}, {4, 3, 1}, {4, 3, 2}, {4, 3, 3}, + {4, 3, 4}, {4, 4, 0}, {4, 4, 1}, {4, 4, 2}, {4, 4, 3}, {4, 4, 4}, {0, 0, 0}, + {0, 0, 0}, {0, 0, 0} +}; + +/** + * Values for the lsp vector from the 4th subframe of the + * previous subframe values. + * + * @note: Taken from Decoder_amr_reset in Q15 using val/1000 + */ +static const int8_t lsp_sub4_init[LP_FILTER_ORDER] = { + 30, 26, 21, 15, 8, 0, -8, -15, -21, -26 +}; + +/** + * Mean lsp values. + * + * @note: Taken from Decoder_amr_reset in Q15 + */ +static const int16_t lsp_avg_init[LP_FILTER_ORDER] = { + 1384, 2077, 3420, 5108, 6742, 8122, 9863, 11092, 12714, 13701 +}; + +// LSF tables + +// These are stored as integers to save space. The values are taken from +// q_plsf_3.tab and q_plsf_5.tab in 3GPP TS 26.090. + +static const int16_t lsf_3_3_MODE_5k15[128][4] = { +{ 419, 163, -30, -262}, { -455, -789,-1430, -721}, { 1006, 664, 269, 25}, +{ 619, 260, 183, 96}, { -968,-1358, -388, 135}, { -693, 835, 456, 154}, +{ 1105, 703, 569, 363}, { 1625, 1326, 985, 748}, { -220, 219, 76, -208}, +{-1455,-1662, 49, 149}, { -964, -172, -752, -336}, { 625, 209, -250, -66}, +{-1017, -838, -2, 317}, {-2168,-1485, -138, 123}, {-1876,-2099, -521, 85}, +{ -967, -366, -695, -881}, { -921,-1011, -763, -949}, { -124, -256, -352, -660}, +{ 178, 463, 354, 304}, {-1744, -591, -282, 79}, {-2249, 175, 867, 499}, +{ -138, -180, -181, -21}, {-2291,-1241, -460, -520}, { -771, 451, -10, -308}, +{ 271, -65, 4, 214}, { -279, -435, -43, -348}, { -670, 35, -65, -211}, +{ 806, 535, 85, 297}, { 57, 239, 722, 493}, { 225, 661, 840, 547}, +{ -540, -376, 14, 349}, { 469, 721, 331, 162}, { -544, -752, -62, -10}, +{ 398, -88, 724, 701}, { -19, -533, -94, 601}, { 136, -71, -681, -747}, +{ -166, -344, 261, -50}, { 161, -52, 485, 337}, {-1675, 50, 190, -93}, +{-2282, -231, -194, -82}, { -95, -595, -154, 128}, { 894, 501, 588, 457}, +{ -345, 206, 122, 110}, { -631, -227, -569, 3}, { 408, 239, 397, 226}, +{ -197, -2, 128, 491}, { 1281, 904, 292, 215}, { 538, 306, 259, 509}, +{ -677,-1047, 13, 321}, { -679, -588, -358, -212}, { -558, 243, 646, 479}, +{ 486, 342, 634, 532}, { 107, 802, 331, 136}, { -112, -398,-1031, -286}, +{ -326, -705, 288, 272}, { 1299, 1144, 1178, 860}, { -423, 121, -385, -148}, +{ -295, -302, -834, -819}, { 16, -24, -201, -476}, { 555, 91, -245, 294}, +{ -38, -379, -962,-1221}, {-1191,-1518, -273, -395}, { -390,-1013, -645, 573}, +{-1843,-1030, 505, 468}, { 744, 947, 609, 493}, { -689,-1172, -628, -135}, +{-1026, 195, 411, 196}, { 1582, 1147, 575, 337}, {-1239, -777, -648, -142}, +{ 595, 825, 967, 735}, {-1206, -970, -81, -342}, { -745, 13, -72, 375}, +{ 454, 19, 1407, 921}, {-1647, -172, 861, 562}, { 928, 1537, 1063, 740}, +{-2472, -952, 264, 82}, { -502, -965,-1334, 123}, { 867, 1236, 534, 171}, +{-2320, -460, 780, 363}, {-1190, -617, 252, -61}, { -174, 34, 1011, 788}, +{-2333, 247, 423, 153}, { -16, -355, 262, 449}, {-1576,-1073, -544, -371}, +{ -615, -305, 1051, 805}, { 687, 528, 6, -182}, { 935, 875, 1002, 809}, +{ 199, 257, 126, 76}, { -584,-1138, 599, 556}, {-1105,-1391,-1591, -519}, +{ -977,-1325, 108, 347}, { -722, -975, 365, 101}, { -145, 681, 249, -153}, +{ 0, -334, -570, 159}, { 412, 285, -336, -617}, { -953, -966, 887, 689}, +{-1251, 84, -185, -398}, { -592, 433, 1044, 653}, { 85, 329, -40, 361}, +{ -433, -705, 466, 574}, { -154, 654, 592, 290}, { -167, 72, 349, 175}, +{ 674, 297, 977, 720}, { 1235, 1204, 757, 488}, { -400, -269, 538, 372}, +{-1350,-1387,-1194, -91}, { 1262, 876, 775, 700}, { -599, -38, -430, -722}, +{ 1976, 1630, 991, 608}, { 111, 276, -226, -96}, { -947, -388, -11, -7}, +{ -303, -531, -839, 338}, { 1734, 1710, 1405, 1013}, { -516, -855, -645, 210}, +{ -688, -416, 513, 230}, { -822, -637,-1146, -320}, { -952, -658, -694, 183}, +{ -114, -623, 818, 674}, { -191, -204, 731, 635}, { 51, 1221, 883, 576}, +{ -954, -431, 826, 598}, { -342, -755, -900, -407}, {-1126, -354, -206, -512}, +{ -547, -810, -357, -620}, { 66, 515, -73, -410}, { -872, -945,-1444,-1227}, +{ 191, -17, -544, -231}, {-1540, -544, -901, -886} +}; + +static const int16_t lsf_3_1_MODE_7k95[512][3] = { +{ -890,-1550,-2541}, { -819, -970, 175}, { -826,-1234, -762}, +{ -599, -22, 634}, { -811, -987, -902}, { -323, 203, 26}, +{ -383, -235, -781}, { -399, 1262, 906}, { -932,-1399,-1380}, +{ -624, 93, 87}, { -414, -539, -691}, { 37, 633, 510}, +{ -387, -476,-1330}, { 399, 66, 263}, { -407, -49, -335}, +{ -417, 1041, 1865}, { -779,-1089,-1440}, { -746, -858, 832}, +{ -581, -759, -371}, { -673, -506, 2088}, { -560, -634,-1179}, +{ 271, 241, 14}, { -438, -244, -397}, { 463, 1202, 1047}, +{ -606, -797,-1438}, { -51, -323, 481}, { -224, -584, -527}, +{ 494, 881, 682}, { -433, -306,-1002}, { 554, 659, 222}, +{ 171, -160, -353}, { 681, 1798, 1565}, { -852,-1181,-1695}, +{ -336, -666, 114}, { -581, -756, -744}, { -195, 375, 497}, +{ -465, -804,-1098}, { 154, 282, -131}, { -50, -191, -719}, +{ 323, 732, 1542}, { -722, -819,-1404}, { 105, -250, 185}, +{ -178, -502, -742}, { 321, 510, 1111}, { -323, -567, -966}, +{ 127, 484, 338}, { -160, 52, -338}, { 732, 1367, 1554}, +{ -626, -802,-1696}, { -286, -586, 676}, { -695, -343, -370}, +{ -490, 295, 1893}, { -630, -574,-1014}, { -80, 645, -69}, +{ -6, -318, -364}, { 782, 1450, 1038}, { -313, -733,-1395}, +{ 120, 60, 477}, { -264, -585, -123}, { 711, 1245, 633}, +{ -91, -355,-1016}, { 771, 758, 261}, { 253, 81, -474}, +{ 930, 2215, 1720}, { -808,-1099,-1925}, { -560, -782, 169}, +{ -804,-1074, -188}, { -626, -55, 1405}, { -694, -716,-1194}, +{ -660, 354, 329}, { -514, -55, -543}, { 366, 1033, 1182}, +{ -658, -959,-1357}, { -55, -184, 93}, { -605, -286, -662}, +{ 404, 449, 827}, { -286, -350,-1263}, { 628, 306, 227}, +{ -16, 147, -623}, { 186, 923, 2146}, { -674, -890,-1606}, +{ -443, -228, 339}, { -369, -790, -409}, { 231, 86, 1469}, +{ -448, -581,-1061}, { 594, 450, -177}, { -124, -170, -447}, +{ 671, 1159, 1404}, { -476, -667,-1511}, { -77, -138, 716}, +{ -177, -372, -381}, { 451, 934, 915}, { -250, -432, -822}, +{ 272, 828, 446}, { 26, 19, -31}, { 698, 1692, 2168}, +{ -646, -977,-1924}, { -179, -473, 268}, { -379, -745, -691}, +{ 11, 127, 1033}, { -488, -917, -825}, { 61, 323, 135}, +{ 147, -145, -686}, { 685, 786, 1682}, { -506, -848,-1297}, +{ 35, 90, 222}, { -23, -346, -670}, { 455, 591, 1287}, +{ -203, -593,-1086}, { 652, 352, 437}, { 39, 63, -457}, +{ 841, 1265, 2105}, { -520, -882,-1584}, { -328, -711, 1421}, +{ -596, -342, -70}, { 209, 173, 1928}, { -423, -598, -921}, +{ 421, 605, -38}, { -2, -245, -127}, { 896, 1969, 1135}, +{ -379, -518,-1579}, { 173, 118, 753}, { -55, -381, -52}, +{ 985, 1021, 753}, { -2, -291, -891}, { 753, 992, 423}, +{ 264, 131, -196}, { 895, 2274, 2543}, { -635,-1088,-2499}, +{ -529, -982, 526}, { -764, -830, -548}, { -436, 316, 599}, +{ -675, -940, -746}, { -57, 236, -11}, { -201, -81, -798}, +{ 16, 845, 1558}, { -737, -985,-1212}, { -468, 17, 290}, +{ -279, -584, -700}, { 183, 822, 705}, { -265, -492,-1187}, +{ 421, 152, 468}, { -390, 166, -268}, { 39, 1550, 1868}, +{ -635, -966,-1571}, { -453, -492, 910}, { -284,-1027, -75}, +{ -181, -133, 1852}, { -445, -624,-1174}, { 420, 367, -49}, +{ -389, -212, -169}, { 707, 1073, 1208}, { -539, -710,-1449}, +{ 83, -163, 484}, { -236, -543, -355}, { 338, 1175, 814}, +{ -246, -309, -958}, { 606, 760, 60}, { 166, -8, -163}, +{ -306, 1849, 2563}, { -747,-1025,-1783}, { -419, -446, 209}, +{ -718, -566, -534}, { -506, 693, 857}, { -463, -697,-1082}, +{ 325, 431, -206}, { -15, -8, -763}, { 545, 919, 1518}, +{ -611, -783,-1313}, { 256, -55, 208}, { -165, -348, -662}, +{ 321, 680, 930}, { -326, -429, -951}, { 484, 446, 570}, +{ -197, 72, -73}, { 909, 1455, 1741}, { -563, -737,-1974}, +{ -124, -416, 718}, { -478, -404, -314}, { -16, 446, 1636}, +{ -551, -537, -750}, { -58, 638, 214}, { 55, -185, -271}, +{ 1148, 1301, 1212}, { -483, -671,-1264}, { 117, 285, 543}, +{ -204, -391, -111}, { 513, 1538, 854}, { -114, -190, -978}, +{ 877, 595, 464}, { 260, 260, -311}, { 748, 2283, 2216}, +{ -517, -945,-2171}, { -326, -708, 378}, { -812, -691, -232}, +{ -560, 687, 1409}, { -732, -690, -836}, { -359, 645, 386}, +{ -265, 62, -678}, { 145, 1644, 1208}, { -555, -988,-1233}, +{ -78, 14, 114}, { -327, -358, -489}, { 392, 677, 697}, +{ -201, -236,-1140}, { 693, 449, 178}, { -243, 256, -433}, +{ 611, 1385, 2456}, { -612, -901,-1464}, { -307, -17, 499}, +{ -315, -667, -254}, { 256, 428, 1463}, { -486, -422,-1056}, +{ 655, 370, 18}, { -102, -185, -276}, { 755, 1578, 1335}, +{ -488, -603,-1418}, { 182, -93, 870}, { -73, -458, -348}, +{ 835, 862, 957}, { -282, -333, -746}, { 547, 839, 428}, +{ 273, -89, 13}, { 940, 1708, 2576}, { -418,-1084,-1758}, +{ -44, -358, 259}, { -497, -643, -560}, { 99, 557, 961}, +{ -421, -766, -917}, { 295, 326, 184}, { 175, 15, -626}, +{ 532, 878, 1981}, { -443, -768,-1275}, { 221, 156, 268}, +{ 39, -363, -505}, { 695, 772, 1140}, { -162, -459, -912}, +{ 709, 444, 658}, { 25, 303, -312}, { 1268, 1410, 1715}, +{ -297, -766,-1836}, { -263, -108, 1070}, { -406, -13, -129}, +{ 57, 438, 2734}, { -374, -487, -835}, { 304, 696, 164}, +{ 104, -235, 5}, { 1611, 1900, 1399}, { -229, -582,-1325}, +{ 405, 192, 817}, { -87, -438, 111}, { 1028, 1199, 993}, +{ 68, -175, -934}, { 1033, 1117, 451}, { 478, 200, -248}, +{ 2127, 2696, 2042}, { -835,-1323,-2131}, { -799, -692, 466}, +{ -812,-1032, -469}, { -622, 288, 920}, { -701, -841,-1070}, +{ -411, 512, 8}, { -390, -91, -744}, { -30, 1043, 1161}, +{ -822,-1148,-1156}, { -294, -46, 110}, { -411, -374, -678}, +{ 214, 531, 668}, { -406, -420,-1194}, { 487, 232, 303}, +{ -318, 91, -472}, { 123, 1232, 2445}, { -722, -952,-1495}, +{ -738, -675, 1332}, { -543, -606, -211}, { -95, -98, 1508}, +{ -549, -514,-1193}, { 473, 211, 73}, { -288, -112, -389}, +{ 537, 1332, 1258}, { -567, -755,-1545}, { 71, -283, 632}, +{ -170, -481, -493}, { 681, 1002, 817}, { -356, -331, -877}, +{ 419, 706, 346}, { 241, -34, -326}, { 377, 1950, 1883}, +{ -727,-1075,-1625}, { -233, -543, 116}, { -524, -806, -585}, +{ -73, 478, 729}, { -288, -925,-1143}, { 173, 447, -52}, +{ 68, -229, -606}, { 449, 529, 1797}, { -591, -875,-1363}, +{ 183, -144, 324}, { -103, -452, -666}, { 623, 488, 1176}, +{ -238, -511,-1004}, { 326, 552, 458}, { 136, 108, -319}, +{ 626, 1343, 1883}, { -490, -646,-1730}, { -186, -449, 984}, +{ -738, -76, -170}, { -550, 755, 2560}, { -496, -510, -947}, +{ 210, 694, -52}, { 84, -322, -199}, { 1090, 1625, 1224}, +{ -376, -603,-1396}, { 343, 74, 632}, { -175, -502, -32}, +{ 972, 1332, 734}, { 52, -295,-1113}, { 1065, 918, 160}, +{ 393, 107, -397}, { 1214, 2649, 1741}, { -632,-1201,-1891}, +{ -719, -277, 353}, { -651, -880, -122}, { -211, 209, 1338}, +{ -562, -714,-1059}, { -208, 388, 159}, { -320, -61, -551}, +{ 293, 1092, 1443}, { -648, -865,-1253}, { -49, -143, 305}, +{ -401, -227, -585}, { 561, 532, 927}, { -117, -443,-1188}, +{ 507, 436, 292}, { -79, 233, -458}, { 671, 1025, 2396}, +{ -633, -842,-1525}, { -308, -286, 640}, { -373, -621, -407}, +{ 418, 253, 1305}, { -315, -581,-1137}, { 572, 685, -281}, +{ 61, -68, -371}, { 991, 1101, 1498}, { -493, -683,-1362}, +{ -47, 164, 704}, { -256, -314, -268}, { 631, 949, 1052}, +{ -118, -348, -833}, { 68, 1180, 568}, { 152, 117, 34}, +{ 1113, 1902, 2239}, { -601, -959,-1706}, { -143, -489, 480}, +{ -332, -655, -574}, { 54, 353, 1192}, { -462, -652, -796}, +{ 150, 549, 112}, { 195, -111, -515}, { 679, 1108, 1647}, +{ -558, -749,-1217}, { -9, 272, 341}, { -53, -265, -535}, +{ 489, 843, 1298}, { -120, -482,-1032}, { 632, 543, 408}, +{ 179, 306, -526}, { 1124, 1464, 2244}, { -417, -786,-1562}, +{ -224, -384, 1364}, { -377, -459, -25}, { 385, 489, 2174}, +{ -332, -651, -829}, { 544, 553, 61}, { 22, -113, -89}, +{ 1128, 1725, 1524}, { -216, -373,-1653}, { 161, 316, 908}, +{ -165, -222, -67}, { 1362, 1175, 789}, { 73, -252, -767}, +{ 738, 932, 616}, { 362, 246, -126}, { 787, 2654, 3027}, +{ -691,-1106,-2190}, { -565, -588, 524}, { -590, -979, -490}, +{ -263, 397, 982}, { -577, -837, -945}, { -22, 435, -49}, +{ -190, -118, -629}, { -88, 1240, 1513}, { -636,-1051,-1019}, +{ -291, 189, 259}, { -257, -470, -629}, { 145, 945, 894}, +{ -326, -364,-1094}, { 543, 260, 630}, { -202, 189, -209}, +{ 357, 1379, 2091}, { -569,-1075,-1449}, { -714, -239, 919}, +{ -420, -705, -84}, { -109, -114, 2407}, { -413, -529,-1177}, +{ 482, 368, 131}, { -186, -72, -131}, { 861, 1255, 1220}, +{ -611, -658,-1341}, { 227, -121, 631}, { -176, -489, -218}, +{ 745, 1175, 957}, { -321, -148, -936}, { 671, 966, 216}, +{ 340, -3, -143}, { 469, 1848, 2437}, { -729, -961,-1683}, +{ -213, -254, 321}, { -511, -438, -521}, { -126, 725, 903}, +{ -340, -685,-1032}, { 316, 480, 20}, { 23, -89, -551}, +{ 353, 1051, 1789}, { -544, -757,-1364}, { 298, -25, 436}, +{ -100, -392, -519}, { 467, 754, 1078}, { -210, -398,-1078}, +{ 620, 658, 630}, { 33, 147, -178}, { 921, 1687, 1921}, +{ -325, -528,-1978}, { 2, -285, 910}, { -371, -490, -230}, +{ 0, 597, 2010}, { -496, -395, -834}, { 37, 945, 245}, +{ 181, -160, -144}, { 1481, 1373, 1357}, { -355, -601,-1270}, +{ 298, 322, 672}, { -193, -336, 77}, { 1089, 1533, 922}, +{ 177, -39,-1125}, { 996, 781, 536}, { 456, 366, -432}, +{ 1415, 2440, 2279}, { -466, -758,-2325}, { -303, -509, 387}, +{ -727, -557, 66}, { -145, 643, 1248}, { -544, -676, -916}, +{ -225, 862, 588}, { -152, 40, -533}, { 423, 1423, 1558}, +{ -572, -843,-1145}, { -128, 85, 461}, { -238, -257, -584}, +{ 605, 748, 861}, { 24, -202,-1409}, { 797, 487, 303}, +{ -181, 364, -182}, { 616, 1378, 2942}, { -494, -852,-1441}, +{ -292, 61, 812}, { -84, -723, -182}, { 555, 532, 1506}, +{ -365, -493,-1057}, { 822, 588, 11}, { -14, -18, -230}, +{ 1001, 1401, 1451}, { -474, -569,-1292}, { 302, 62, 1062}, +{ -70, -376, -222}, { 982, 974, 1149}, { -196, -234, -795}, +{ 479, 1098, 499}, { 362, 58, 70}, { 1147, 2069, 2857}, +{ -487, -878,-1824}, { 73, -288, 348}, { -358, -500, -508}, +{ 199, 721, 1242}, { -78, -697, -795}, { 361, 536, 196}, +{ 374, 110, -735}, { 847, 1051, 1896}, { -366, -713,-1182}, +{ 315, 320, 429}, { 72, -215, -450}, { 759, 886, 1363}, +{ -30, -428, -834}, { 861, 627, 796}, { 118, 468, -279}, +{ 1355, 1883, 1893}, { -188, -642,-1612}, { 63, -175, 1198}, +{ -418, -211, 51}, { 414, 587, 2601}, { -234, -557, -858}, +{ 424, 889, 222}, { 136, -101, 83}, { 1413, 2278, 1383}, +{ -84, -445,-1389}, { 414, 313, 1045}, { 29, -343, 65}, +{ 1552, 1647, 980}, { 183, -91, -829}, { 1273, 1413, 360}, +{ 553, 272, -107}, { 1587, 3149, 2603} +}; + +static const int16_t lsf_3_1[256][3] = { +{ 6, 82, -131}, { 154, -56, -735}, { 183, -65, -265}, +{ 9, -210, -361}, { 113, 718, 1817}, { 1010, 1214, 1573}, +{ 857, 1333, 2276}, { 827, 1568, 1933}, { 717, 1989, 2206}, +{ 838, 1172, 1823}, { 721, 1000, 2154}, { 286, 476, 1509}, +{ -247, -531, 230}, { 147, -82, 569}, { 26, -177, -944}, +{ -27, -273, 692}, { -164, -264, -183}, { 224, 790, 1039}, +{ 899, 946, 601}, { 485, 771, 1150}, { 524, 677, 903}, +{ -140, 375, 778}, { 410, 676, 429}, { 301, 530, 1009}, +{ 719, 646, 38}, { 226, 367, 40}, { 145, -45, -505}, +{ 290, 121, -121}, { 302, 127, 166}, { -124, -383, -956}, +{ -358, -455, -977}, { 715, 878, 894}, { 978, 923, 211}, +{ 477, 272, 64}, { 188, -78, 17}, { -143, -65, 38}, +{ 643, 586, 621}, { -134, -426, -651}, { 347, 545, 2820}, +{ 1188, 2726, 2442}, { 142, -80, 1735}, { 283, 130, 461}, +{ -262, -399,-1145}, { -411, 155, 430}, { 329, 375, 779}, +{ 53, -226, -139}, { -129, -236, 1682}, { 285, 744, 1327}, +{ 738, 697, 1664}, { 312, 409, 266}, { 325, 720, 135}, +{ 1, 221, 453}, { 8, 203, 145}, { 299, 640, 760}, +{ 29, 468, 638}, { 103, 429, 379}, { 420, 954, 932}, +{ 1326, 1210, 1258}, { 704, 1012, 1152}, { -166, -444, -266}, +{ -316, -130, -376}, { 191, 1151, 1904}, { -240, -543,-1260}, +{ -112, 268, 1207}, { 70, 1062, 1583}, { 278, 1360, 1574}, +{ -258, -272, -768}, { 19, 563, 2240}, { -3, -265, 135}, +{ -295, -591, -388}, { 140, 354, -206}, { -260, -504, -795}, +{ -433, -718,-1319}, { 109, 331, 962}, { -429, -87, 652}, +{ -296, 426, 1019}, { -239, 775, 851}, { 489, 1334, 1073}, +{ -334, -332, 25}, { 543, 1206, 1807}, { 326, 61, 727}, +{ 578, 849, 1405}, { -208, -277, 329}, { -152, 64, 669}, +{ -434, -678, -727}, { -454, -71, 251}, { 605, 480, 254}, +{ -482, 11, 996}, { -289, 395, 486}, { 722, 1049, 1440}, +{ -30, -316, -786}, { -106, -115, -619}, { 861, 1474, 1412}, +{ 1055, 1366, 1184}, { 812, 1237, 925}, { 42, -251, -576}, +{ 342, 141, -454}, { -168, -80, 1359}, { -342, -656,-1763}, +{ 100, 821, 725}, { 990, 747, 800}, { 332, 440, 568}, +{ 663, 379, 852}, { 112, 165, -369}, { 597, 910, 282}, +{ -8, 834, 1281}, { -352, 572, 695}, { 462, 2246, 1806}, +{ 345, 190, 1374}, { 416, 915, 2166}, { 168, -82, 280}, +{ -516, -446, 840}, { 47, 533, 44}, { -362, -711,-1143}, +{ 22, 193, 1472}, { -85, 233, 1813}, { -62, 579, 1504}, +{ 550, 944, 1749}, { 723, 650, 1148}, { 972, 884, 1395}, +{ -425, 643, 0}, { 1000, 952, 1098}, { 249, 1446, 672}, +{ -334, -87, 2172}, { -554, 1882, 2672}, { 140, 1826, 1853}, +{ 920, 1749, 2590}, { 1076, 1933, 2038}, { -137, -443,-1555}, +{ 1269, 1174, 468}, { -493, -122, 1521}, { -451, 1033, 1214}, +{ 482, 1695, 1118}, { 815, 649, 384}, { -446, -692, 107}, +{ -319, -605, -118}, { -207, -505, 525}, { -468, -12, 2736}, +{ 75, 1934, 1305}, { 880, 2358, 2267}, { 1285, 1575, 2004}, +{ -48, -304,-1186}, { -435, -461, -251}, { -366, -404, -547}, +{ -289, -605, -597}, { -538, -810, -165}, { -120, 3, 356}, +{ 639, 1241, 1502}, { 96, 177, 750}, { -435, -585,-1174}, +{ -356, 109, -79}, { -485, 288, 2005}, { 9, 1116, 731}, +{ 880, 2134, 946}, { -265, 1585, 1065}, { 1157, 1210, 843}, +{ -498, -668, 431}, { 374, 321, -229}, { 1440, 2101, 1381}, +{ 449, 461, 1155}, { -105, 39, -384}, { -263, 367, 182}, +{ -371, -660, 773}, { -188, 1151, 971}, { 1333, 1632, 1435}, +{ 774, 1267, 1221}, { -482, -832,-1489}, { -237, -210, 860}, +{ 890, 1615, 1064}, { 472, 1062, 1192}, { 185, 1077, 989}, +{ -568, -992,-1704}, { -449, -902,-2043}, { -142, -377, -458}, +{ -210, -554,-1029}, { -11, 1133, 2265}, { -329, -675, -893}, +{ -250, 657, 1187}, { 519, 1510, 1779}, { 520, 539, 1403}, +{ 527, 1421, 1302}, { -563, -871,-1248}, { -147, -463, 879}, +{ -76, 2334, 2840}, { 563, 2573, 2385}, { 632, 1926, 2920}, +{ 719, 2023, 1840}, { -545, -723, 1108}, { 129, -125, 884}, +{ 1417, 1632, 925}, { -94, 1566, 1751}, { -341, 1533, 1551}, +{ 591, 395, -274}, { -76, 981, 2831}, { 153, 2985, 1844}, +{ 1032, 2565, 2749}, { 1508, 2832, 1879}, { 791, 1199, 538}, +{ -190, -453, 1489}, { -278, -548, 1158}, { -245, 1941, 2044}, +{ 1024, 1560, 1650}, { 512, 253, 466}, { -62, -323, 1151}, +{ -473, -376, 507}, { -433, 1380, 2162}, { 899, 1943, 1445}, +{ 134, 704, 440}, { 460, 525, -28}, { -450, 279, 1338}, +{ 0, 971, 252}, { -445, -627, -991}, { -348, -602,-1424}, +{ 398, 712, 1656}, { -107, 314, -178}, { 93, 2226, 2238}, +{ 518, 849, 656}, { -462, -711, -447}, { 174, -34, 1191}, +{ -119, 42, 1005}, { -372, 274, 758}, { 1036, 2352, 1838}, +{ 675, 1724, 1498}, { 430, 1286, 2133}, { -129, -439, 0}, +{ -373, 800, 2144}, { 6, 1587, 2478}, { 478, 596, 2128}, +{ -428, -736, 1505}, { 385, 178, 980}, { 139, 449, 1225}, +{ -526, -842, -982}, { 145, 1554, 1242}, { 623, 1448, 656}, +{ 349, 1016, 1482}, { 31, -280, 415}, { -316, 724, 1641}, +{ 360, 1058, 556}, { -436, -358, 1201}, { -355, 1123, 1939}, +{ 401, 1584, 2248}, { -527,-1012, 355}, { 233, 238, 2233}, +{ -550, -897, -639}, { -365, -501, 1957}, { 389, 1860, 1621}, +{ 162, 1132, 1264}, { -237, 1174, 1390}, { -640, -411, 116}, +{ -228, 1694, 2298}, { 1639, 2186, 2267}, { 562, 1273, 2658}, +{ 323, 338, 1774}, { 578, 1107, 852}, { 22, 594, 934}, +{ -143, 718, 446} +}; + + +static const int16_t lsf_3_2[512][3] = { +{ 50, 71, -9}, { -338, -698,-1407}, { 102, -138, -820}, +{ -310, -469,-1147}, { 414, 67, -267}, { 1060, 814, 1441}, +{ 1548, 1360, 1272}, { 1754, 1895, 1661}, { 2019, 2133, 1820}, +{ 1808, 2318, 1845}, { 644, -93, 454}, { 858, 329, -136}, +{ 489, -258, -128}, { -198, -745, -41}, { -52, -265, -985}, +{ 346, 137, 479}, {-1741, -748, -684}, {-1163,-1725, -367}, +{ -895,-1145, -784}, { -488, -946, -968}, { -85, -390, -725}, +{ 215, -340, -171}, { 1020, 916, 1969}, { 564, 179, 746}, +{ 662, 977, 1734}, { 887, 622, 914}, { 939, 856, 1165}, +{ 309, 688, 803}, { 917, 161, 570}, { 118, -20, -283}, +{ -816, -42, 204}, {-1228, -325, -462}, { -963, -202, -143}, +{ -988, -484, -361}, { -702, -978, -477}, { -302, -790,-1188}, +{ -100, -786,-1088}, {-1054, -947,-1684}, { -202, -843, -782}, +{-1039,-1378, -901}, { -624, -110, -85}, { 356, 213, -10}, +{ -493, 364, 774}, { 425, 822, 479}, { -83, 557, 520}, +{ -992,-1560, -572}, { -603, -741, -26}, { -502, -638, -903}, +{ 209, 306, 147}, { -316, -593, -596}, { -85, -211, -225}, +{ -918, -529, 117}, { 233, -439, -738}, { 1101, 751, 633}, +{ 1457, 1716, 1511}, { 1765, 1457, 910}, { 1122, 1156, 849}, +{ 1354, 868, 470}, { -871,-1150,-1796}, { -871, -861, -992}, +{ -118, 155, 212}, {-1051, -849, -606}, {-1117,-1849,-2750}, +{-1019,-1427,-1869}, { 370, -184, -414}, { 959, 493, 104}, +{ 958, 1039, 543}, { 154, 653, 201}, { 1249, 507, 150}, +{ 663, 503, 230}, { 623, 777, 675}, { 659, 88, -110}, +{ 843, 244, 224}, { 382, 541, 302}, { 724, 433, 666}, +{ 1166, 734, 341}, { -138, 20, -397}, {-1183, -424, -46}, +{ -321, -352, -124}, { 1333, 1021, 1080}, { 262, 366, 723}, +{ 922, 283, -551}, { 31, -636, -611}, { -689, -697, -415}, +{ -952, -779, -201}, {-1329, -598, -359}, { -953,-1285, 166}, +{ 493, 305, 221}, { 846, 703, 610}, { 840, 936, 774}, +{ -723,-1324,-1261}, { -357,-1025,-1388}, {-1096,-1376, -365}, +{-1416,-1881, -608}, {-1798,-1727, -674}, { -545,-1173, -703}, +{ 678, 786, 148}, { -123, 696, 1288}, { 644, 350, -10}, +{ 414, 614, 15}, { 137, 344, -211}, { -814,-1512, -819}, +{ -391, -930, -588}, { 47, -591, -898}, { -909,-1097, -163}, +{-1272,-1167, -157}, {-1464,-1525, -389}, {-1274,-1188, -624}, +{ 671, 213, 454}, { 124, -274, -525}, { -729, -496, -152}, +{-1344, 122, 135}, {-2905, -589, -394}, {-1728, 441, -50}, +{ 1476, 904, 787}, { 316, 236, -440}, { -347, 217, 413}, +{ -911, -917, 121}, { -455, -932, 202}, { -92, -465, -375}, +{ 488, 390, 474}, { 876, 729, 316}, {-1815,-1312, -669}, +{ 87, 962, 432}, { 563, -249,-1058}, { 250, 285, 1105}, +{ 1141, 427, 696}, {-1038,-1664,-1582}, { -948, 346, 160}, +{ -309, -272, -858}, { 670, 624, 1250}, { -944, -408, -666}, +{ -606, -320, -384}, { -492, 230, 65}, { 334, -50, -16}, +{ -16, -690,-1397}, { 1791, 1716, 1399}, { 2478, 2063, 1404}, +{ 1245, 1471, 1426}, { -382,-1037, -2}, { 173, -398, 1145}, +{ 1491, 2024, 1801}, { 772, 1274, 1506}, { 1429, 1735, 2001}, +{ 1079, 1218, 1273}, {-1154,-1851,-1329}, { -808,-1133,-1096}, +{ -451,-1033,-1722}, { 65, 578, -84}, {-1476,-2434,-1778}, +{ -765,-1366, -494}, { -218, -594, -931}, { 337, -236, 562}, +{ 2357, 2662, 1938}, { 1489, 1276, 874}, { 189, 358, 374}, +{-1519,-2281,-2346}, { -967,-1271,-2095}, { -628,-1188,-1542}, +{ 1661, 1043, 546}, { 565, 1061, 732}, { -64, -836, -434}, +{ -436, -96, 203}, { 1078, 1216, 1636}, { 907, 1534, 986}, +{ 326, 965, 845}, { 142, -84, 197}, { 470, 2379, 1570}, +{ 1133, 470, 1214}, { 395, 1376, 1200}, { 1125, 1042, 348}, +{ -543,-1234, -376}, { -215, -181, 481}, {-1947,-1621, -210}, +{ -750,-1185, 390}, { 29, -399, 27}, { 820, 1236, 755}, +{ 695, 979, 409}, { -174, 1197, 1035}, { 912, 1356, 1846}, +{ -992,-1437, 484}, {-1485,-1700, 208}, { -412, 1204, 1432}, +{ -271, 896, 1144}, { -416, 1777, 1434}, {-1696,-2644, -204}, +{-1789,-1551, 1033}, {-1656,-1559, 1303}, {-1253,-1589, 1081}, +{ -669,-1095, -66}, { -682, 320, -345}, { 659, 305, 1069}, +{-1292, -804, -19}, {-1635,-1291, 29}, {-1683, -497, 71}, +{ -287, -7, -100}, { -494, -962, -237}, { 852, 1881, 1740}, +{-1217,-1387, 227}, { -660, 302, 373}, { 96, 1087, 1257}, +{-1074,-1669, 160}, { 485, 2076, 1798}, { -934, -220, 552}, +{ -596, -612, 237}, { 336, 1720, 879}, { 643, 629, 434}, +{ 1267, 522, 1633}, { 15, 244, -441}, { 1475, 717, 184}, +{ 1819, 1590, 1709}, { 988, 261, 937}, { 2093, 2345, 1520}, +{ 2139, 1858, 1606}, { -577, -579,-1203}, { -956, 135, -488}, +{ -464, 51, -338}, { -629, -348, -723}, { 1146, 2073, 1442}, +{ 2192, 1466, 911}, {-1444,-1572,-2278}, { 1400, 710, 1297}, +{ 1335, 633, 928}, { 1434, 2194, 2594}, { 2422, 2204, 1881}, +{ 982, 2242, 1854}, { 380, 792, 1145}, { -63, -539, 414}, +{ -252, -964, -314}, {-1261, -683, -780}, { -831, -526,-1005}, +{-1666,-1135, -424}, {-1611, -452, -299}, { 1268, 1048, 642}, +{ 1147, 853, 856}, { -675, -336, 139}, { 2268, 1343, 1418}, +{ 29, 768, 797}, {-1224, 423, 564}, {-1318,-1082, 245}, +{-1302, -812, 573}, {-1298,-1617, 646}, { -968, 834, 723}, +{ 993, 1652, 2027}, { -191, -817, 432}, { 662, 60, 198}, +{ 626, 997, 1330}, { 1648, 1963, 1289}, {-1597, -93, -45}, +{-1088, 37, -84}, { 1653, 2607, 2337}, { 1065, 2040, 2377}, +{ 1139, 2326, 2118}, { 859, 357, 1510}, { 664, 1227, 1099}, +{ 479, 1360, 912}, { 1897, 1754, 2019}, { 1168, 1909, 1784}, +{ 399, 34, 256}, { -593, -304,-1053}, { 547, 1694, 1407}, +{ 647, -99, -341}, { 1492, 1647, 1190}, { 38, -644, -212}, +{ 395, 846, 222}, { -704, -765, -716}, { -724,-1964,-2804}, +{ -150, 291, -82}, { 1233, 1459, 1007}, { -140, -155, 153}, +{ 439, 297, 1568}, {-1529, -410, -636}, { 1536, 455, -237}, +{-1328, -139, -260}, { 531, 554, 868}, { 269, 1264, 606}, +{ -233, 883, 463}, { 742, 600, -120}, { -73, 421, 212}, +{ -439, -58, 804}, {-1286,-1241, 728}, { 294, -490, 50}, +{ -591, -905,-1254}, { 42, -687, 147}, { -25, 273, 596}, +{ -311, 1213, 601}, { -754, 849, 584}, { 429, 607, 587}, +{ -602, -166, 461}, { -796, -823, 777}, { 1380, 910, 1755}, +{ 119, 1417, 972}, { -219, -880,-1596}, {-1049,-1010, 438}, +{ -713,-1379, 78}, { 0, -447,-1179}, {-1136,-1319,-1573}, +{ 2248, 1767, 1309}, { 946, 1583, 1432}, { 1150, 482, 436}, +{ -469,-1108, 618}, { -447, -966, 1088}, {-1252,-1515, -114}, +{-1104,-2008, -579}, { 210, 613, 497}, {-1975,-1437, 642}, +{-1269, -856, 1011}, {-1646,-1185, 1063}, {-1555, -672, 1204}, +{-1692,-1114, 623}, { -979,-1326,-1277}, { 539, -147, 894}, +{-1354, -897, -434}, { 888, 475, 428}, { 153, -384, 338}, +{-1492, -511, 359}, { -974,-1115, -470}, { 105, -550, 677}, +{ -937,-1145, 877}, { 380, -260, 210}, { 1685, 924, 1256}, +{ 1775, 1190, 1095}, { 1419, 631, 533}, { 627, 299, -347}, +{ -411, -534, 647}, { -650, 29, -595}, { -378,-1367, 1563}, +{ 1402, 1121, 1465}, { 1089, 1410, 648}, {-2096,-1090, -6}, +{ 311, -194, -869}, { -639, -831, 416}, {-1162,-1224, 1349}, +{-1247, -941, 1813}, {-2193,-1987, 453}, { -619,-1367, -956}, +{-1606,-1972,-1507}, {-1175,-1057,-1104}, { -377, 601, 201}, +{ 1876, 825, 374}, { -430,-1323, 29}, {-1397,-1249,-1331}, +{-1007,-1504, 960}, {-1401,-2009, 197}, {-1379,-1949, -236}, +{-1077, 123, 422}, { 615, 1269, 546}, { -306, 1526, 904}, +{ 1194, 1788, 1177}, { -626, -884,-1526}, { 199, 766, 1504}, +{-1065, 862, 197}, {-1034,-1773, -887}, { -800, 145, 599}, +{-1134, -519, 626}, {-1205,-1926, 500}, { -910,-1041,-1395}, +{-1476,-1567, -969}, { -523, 842, 34}, { 1794, 646, 862}, +{-1207,-1888,-1002}, { -78, -9, -672}, { 1044, 759, 80}, +{ -600, 1139, 1019}, { 57, 2000, 1422}, { -833, 1414, 1121}, +{-1202, 1630, 1260}, { -461, 1420, 1244}, { 1537, 975, 253}, +{ -283, 324, -359}, { 599, -195, 106}, { 588, 62, -587}, +{ -757, 645, 205}, { 51, 1201, 758}, {-1209, 673, -390}, +{ -624, 1581, 941}, { -151, 1023, 735}, { 2820, 1301, 690}, +{ -302, 524, -99}, { -900,-1588,-1189}, { 1084, 251, 238}, +{ 2014, 1792, 1010}, { 1245, 1633, 1741}, {-1227,-1540,-1208}, +{ -621, 456, -109}, { 40, -65, 788}, { -805, -699,-1350}, +{ -583, 904, 832}, { -801, 532, 594}, { 1972, 1408, 1351}, +{-1177,-1880,-2114}, { -773, 568, 948}, {-1015, 1079, 1260}, +{-1111, 482, -130}, { 1778, 1044, 780}, {-1491, 245, 912}, +{ -316,-1141, -917}, { -536,-1442,-2346}, { -785,-1546,-1988}, +{-2003, 257, 909}, {-1849, -633,-1209}, {-1538,-1918,-1054}, +{ 1606, 2239, 1576}, { -567,-1500,-1544}, {-1279, 195, 1369}, +{ -817, 293, 1219}, { -525, 630, 1197}, {-1698,-2425,-1840}, +{ -303, 731, 747}, {-1169, -251, 269}, { -950, -75, 1684}, +{-1182, -453, 1005}, {-1599, 585, 378}, {-2075, -571, -427}, +{ -529,-1159,-1171}, { -283, -205, -564}, { -796, 1246, 717}, +{ 2277, 927, 539}, { -454, 559, 440}, { -717, 1460, 1615}, +{-1030, 1052, 1610}, {-1169, -138, 847}, { 226, 39, -612}, +{-1251, -106, -729}, { -651, 968, 1302}, { -714, -636, 1727}, +{ 353, 1069, 410}, { -798, -156, 1099}, { -574, 918, 446}, +{-1310, 1012, 466}, { 1408, 1591, 765}, { 1429, 1380, 1757}, +{ 1949, 1956, 2378}, { 1578, 2047, 2148}, { 916, 98, -7}, +{ 1893, 1418, 2141}, { 348, 1405, 1579}, { 152, 1134, 1801}, +{ -267, 154, 1395}, {-1166, 469, 1054}, {-1142, -405,-1073}, +{-1341,-2264,-1581}, { -364, 869, 1706}, {-1162, 549, 1550}, +{-1225,-1932,-1666}, {-1485,-1977,-2055}, {-1727, -906, -98}, +{-1897, 233, 1492}, { 892, 108, -331}, {-1728,-1170,-1700}, +{-1060, 1980, 1790}, {-1070,-1741,-1909}, { -11, 1539, 1317}, +{-1600, 94, 497}, { 421, 443, -197}, {-1578, -349, -994}, +{ -599, -539, 1140}, { -965,-1419, -129}, {-1341, 175, -447}, +{ -375, 1311, 2055}, { -371, -650, -307}, {-1073, 605, 365}, +{-2057, -113, 430}, { 652, 914, 967}, {-1012,-1586,-2323}, +{ 1505, 1248, 559}, { 262, -486, -401}, {-1727, 1342, 1546}, +{ 50, 56, 432}, { -330, 119, -604}, {-1517,-1080, -810}, +{ 946, 1127, 1055}, {-1400,-1703,-1712}, {-1270, -704,-1317}, +{ 807, 1821, 1143}, { 2760, 1606, 2171}, { 1120, 409, -150}, +{ -147, 404, 959}, { 2439, 1911, 2189}, { -906, -141, -866}, +{ -904, -142, -458}, { -557, -708,-1679}, { -830,-1431,-1583}, +{-1842,-1346,-1086}, {-1604, -272, 915}, {-1196, 772, 1056}, +{ -638,-1234,-1897}, { -500, -81, -822}, {-1289,-1613, -735}, +{ -117, 785, 168}, {-1090, 1133, 922}, {-1096, -746, 1384}, +{ 287, -547,-1063}, {-1376,-2201,-1204}, {-2176,-1570,-1757}, +{-1511,-2241, -771}, {-1737, 1099, 830}, {-1588, 724, 1243}, +{-1542, 693, 805}, {-1690, -240, 1665}, {-1700, -4, -668}, +{ 2149, 816, 1042}, { -818,-1841, 22}, { -764, -507, 449}, +{-1151, -617, 289}, { -843,-1596, -240}, { 498, -234, -657}, +{ -752, 480, 1678}, { -319, -481, 193}, { -811, 171, -119}, +{-2128, -202, -848}, { 1717, 1140, 1700} +}; + +static const int16_t lsf_3_3[512][4] = { +{ 67, -17, 66, -12}, {-1690, -581, -104, -272}, {-1076,-1186,-1845, -376}, +{-1140, -926, -420, -58}, { -259, -656,-1134, -553}, { 1788, 1227, 455, 129}, +{ 462, 441, -240, -528}, { 840, 514, 130, -75}, { 1114, 623, 153, 216}, +{ 1068, 564, -6, -276}, { 1119, 727, 190, -68}, { 704, 306, 119, -264}, +{ 329, 61, -100, 156}, { 364, 123, 183, -208}, { -171, -123, 220, -65}, +{ -306, -62, 402, 17}, { -660, -938, -266, 0}, { 385, 235, 276, 285}, +{ 320, 268, -336, -200}, { -724, 17, -84, 381}, { -544, 429, 494, 519}, +{ -117, 288, 304, 329}, { 643, 157, 701, 508}, { 1200, 625, 796, 608}, +{ 998, 421, 492, 632}, { 1204, 780, 446, 132}, { 1257, 844, 547, 449}, +{ 829, 658, 541, 470}, { 1132, 1258, 918, 639}, { 547, 51, 423, 279}, +{ 9, 392, 83, 94}, { 542, 543, 229, -147}, { -198, 129, 194, -185}, +{ -863,-1321, -302, 30}, { -597, -629, -19, 114}, { -900,-1081, 466, 353}, +{-1483,-1573, 15, -143}, {-1708,-2059, -751, 196}, {-1876,-2067, -642, -258}, +{-2335,-1470, -450, -564}, { -584, -186, -872, -414}, {-1805, -988,-1125,-1310}, +{ -726,-1129, 28, 169}, {-1039, -864, -718, -246}, { 484, 36, -233, -49}, +{ 265, 67, 289, 467}, { 178, 543, 810, 540}, { 84, 282, 672, 703}, +{ -975, -777, 129, 287}, { -938, -227, 955, 595}, {-1617, -289, 836, 649}, +{-1847, -215, 1106, 718}, {-2034,-1085, 650, 440}, {-2101, -529, 907, 575}, +{-2011, -336, 670, 204}, {-2389, -692, 360, 137}, {-2156,-2204, -9, 280}, +{ -266, 119, 39, 193}, { 78, -59, -120, 226}, { -975, -858, -781,-1095}, +{ -619, -413, -451, -842}, {-1216,-1321, -813, -883}, {-1376,-1615, -394, -428}, +{ -737,-1113, -549, -790}, { -880, -975, -967, -642}, { -985, -886,-1273,-1361}, +{ -473, -804,-1401,-1407}, { 160, -265, -919, -275}, { -248, -250, -718, -380}, +{ 97, -103, -375, -229}, { -415, -193, -135, -555}, { 628, 361, 119, 216}, +{ 579, 364, 391, 209}, { 634, 522, -154, -148}, { 526, 389, 170, 33}, +{ 105, 267, 64, 380}, {-1503,-1000, -30, -369}, {-1070, 58, 647, 223}, +{-1520, -291, 621, 307}, {-1531, 156, 762, 404}, {-2029, 141, 734, 499}, +{-1849, -650, 306, 512}, { -187, -104, -59, 438}, { 134, -230, 156, -186}, +{ -61, -260, -16, 10}, { -569, -3, -421, -297}, {-1725, -521, -346, 178}, +{-1362, -59, -44, 157}, {-2146, -461, -470, -349}, {-2170, -1, -369, -121}, +{-1579, -373, -900,-1015}, {-1117, -591, -613, -784}, { -561, 122, -75, -449}, +{ -4, -171, -123, -372}, { 192, 168, -76, -132}, { 252, -107, 340, 210}, +{ 392, 509, 272, 181}, { -109, 145, 218, 119}, { -416, -263, 485, 265}, +{ -181, -8, -286, 226}, { -244, -218, 69, -290}, { -158, 191, -1, -64}, +{ -592, -90, 213, -96}, { 255, 435, 178, -80}, { -369, -18, -33, -80}, +{ -42, 415, 140, -222}, { 1143, 651, 649, 329}, { 767, 556, 249, 235}, +{ 948, 413, 442, 279}, { 141, 339, 356, 557}, { -470, -170, 99, 237}, +{ -569, -800, 352, 565}, { 282, 473, 470, 332}, { -199, -690,-1284, -917}, +{ -193, -426, -800,-1122}, { -26, -371, -490, -193}, { 637, 595, 519, 330}, +{ 408, -115, 79, 12}, { 477, 87, -103, -376}, { -666, -347, -277, -291}, +{ -510, -481, 169, 297}, { -829, -738, -205, -171}, { -320, -540, 328, 283}, +{ -859, -958, 442, -2}, { 556, 686, 130, 56}, { 1383, 1012, 755, 427}, +{ 612, 741, 628, 553}, { -339, -796, 134, 277}, { -633,-1085, -2, -246}, +{ -880,-1035,-1607,-1064}, { -994, -474,-1138, -488}, { -414, -795, 73, -206}, +{ -8, -139, 439, 204}, { -176, -578, 23, 131}, { -269, -757, -191, 245}, +{ -109, -338, 112, 316}, { 120, -406, -118, 611}, { -180, -186, -645, 115}, +{ -173, 34, -518, -489}, { -151, 61, -583, -844}, { 220, -138, -681,-1020}, +{ 391, -17, -598, -321}, { 157, -295, 129, 155}, { -926, -875, -987, 285}, +{ 241, -83, -125, -125}, { 620, 597, 432, 92}, { 393, 78, 409, 61}, +{ -393, -739, -413, -748}, { 83, 54, 361, 27}, {-1084, 130, -337, -694}, +{-1565, 297, 318, -19}, {-1873, 36, 51, -317}, {-2323, -246, 231, -84}, +{-2306, -783, 40, -179}, {-2233, -930, -474, -462}, { -754, -86, -288, -626}, +{-2411, -455, -63, 171}, {-1099,-1094, -26, -143}, {-1193, -455, -406, -381}, +{ -605, -210, -96, -51}, { -580, -476, -276, -15}, {-1195, -634,-1203, -881}, +{ -378, -221, -669, -952}, { 594, 178, -403, -676}, { 763, 327, 601, 290}, +{ 172, 300, 203, 157}, { -56, -336, 356, 24}, { -228, -296, -259, -29}, +{ -186, 263, 416, 14}, { -353, 373, -12, -216}, { 257, 96, 174, 57}, +{-1526, -616, -954, -499}, { -497, -152, -333, 125}, { 105, 200, 179, -97}, +{ -331, -224, 765, 697}, { 760, 256, 301, 59}, { 455, -85, 204, 288}, +{ -514, 240, 251, -109}, { 256, 417, -34, -413}, { 101, 430, 384, 156}, +{ -31, -10, 206, 426}, { 589, 145, 143, 71}, { 808, 906, 333, 349}, +{ 986, 938, 589, 331}, { 1300, 824, 187, 509}, { 1062, 653, 379, 466}, +{ 1462, 937, 401, 274}, { 787, 861, 265, 2}, { 609, 553, 28, 305}, +{ 926, 340, 106, 386}, { 241, -267, -147, 225}, { -178, -534, 347, 502}, +{ -643, -381, 397, 30}, { -651, -733, -435, 398}, { -407, -726, -484, -248}, +{ -789, -914, -438, -476}, { -498, -390, 75, -295}, { -964, -590, -606, 150}, +{ -121, -49, -155, -78}, { 935, 550, 389, 38}, { -321, 127, 424, 315}, +{ -285, -113, 283, 259}, { 658, 203, 322, 486}, { 903, 505, 748, 417}, +{ 611, 423, 555, 512}, { 239, -83, -578, -19}, { -339, -731, 349, 13}, +{ -934,-1399, -114, -360}, { 107, 692, 182, 90}, {-1243,-1538,-1551, -725}, +{ -568, -903,-1363, -525}, { -517, -853, -861,-1004}, { -168, -690, -835, 63}, +{ -137, -556, -547, 144}, { -286, -817, 485, 319}, { -147, -408, 526, 246}, +{ -347, -434, 297, -28}, { -290, -471,-1110,-1285}, { -460, -359, -988, -794}, +{ 1347, 1299, 690, 523}, { 1216, 1068, 1094, 757}, { 825, 1140, 752, 494}, +{ 1252, 1365, 1195, 898}, { 521, 1053, 532, 432}, { -334, -216, -313, -263}, +{ -160, 52, -472, -155}, { 127, 136, -380, 44}, { 851, 410, -162, -489}, +{ 123, -255, -796, -667}, { 1090, 917, 789, 493}, { 1397, 1197, 558, 202}, +{ -51, -118, -342, -701}, { 83, 108, -42, -441}, { 61, 95, 287, 256}, +{ -27, 89, 524, 531}, { 351, 227, 592, 545}, { 697, 155, -164, 307}, +{ 638, 274, -489, -50}, { 754, 240, -166, -124}, { -116, -579,-1212, -63}, +{ 190, -295,-1040,-1296}, { 147, -376, -177, -113}, { 841, 1241, 1051, 668}, +{ 2, 293, 551, 304}, {-1096, -953, -248, 376}, { -750, -965, 87, 516}, +{ -275, -516, 689, 391}, { -379, -643, 876, 594}, { -390,-1013, -645, 573}, +{ -107, -568, -689, -826}, {-1025, -27, -328, -203}, { 861, 749, 548, 233}, +{-1660,-1043, 451, 108}, { -660, -620, 430, 236}, { 21, -396,-1158, -631}, +{ 1372, 1298, 967, 577}, { 1125, 1125, 589, 454}, { -323, -865, -467, 153}, +{ -468, -699, -804, -509}, { -392, -718, -204, -35}, { -603,-1093, -567, -162}, +{ -505,-1004, -102, 350}, { 219, 224, 423, 252}, { 395, 591, 608, 363}, +{ -746, -96, 373, 172}, { 171, 295, 714, 339}, { 233, 77, 107, 277}, +{ 157, 153, -499, -356}, { 1547, 1073, 576, 494}, { -292, -339, -504, -592}, +{ -903, -72, -619, -481}, {-1594,-1117, -567, -254}, { -793, -507, -564, -291}, +{ -492, -532, 502, 560}, { -382, 427, 600, 230}, { -227, 477, 251, 75}, +{ 285, 842, 813, 476}, {-1310,-1333, 186, 377}, { -587, -917, 643, 381}, +{-1186, -553, 411, 82}, {-1127, -820, -174, -540}, { -604, 119, 543, 205}, +{ -380, 657, 909, 567}, { 112, -298, -374, 114}, { -857, -251, 56, 159}, +{ 401, 345, -34, -140}, { -111, -607, 41, 614}, { 355, -114, -77, 474}, +{ 578, 56, 1450, 924}, { 1098, 1420, 741, 400}, { 246, 22, 588, 313}, +{ -121, 327, 831, 472}, {-1138, -608, 856, 552}, {-1241,-1072, 638, 600}, +{ -358, 254, -333, -303}, { -646, 739, 358, 74}, { 1226, 1671, 1221, 849}, +{ 2241, 1624, 983, 636}, { 1841, 1477, 749, 384}, { 350, 263, 87, 128}, +{-1902, -941, -144, -64}, {-1734, -255, 288, -31}, {-2644,-1238, 366, 235}, +{-1643,-1092,-1344, -304}, { -541,-1075,-1116, 123}, {-1178, -252, -816, -180}, +{-1016, 533, 565, 233}, { -487, -430, -188, 334}, { 867, 1236, 534, 171}, +{-1590,-1607, 635, 630}, {-2196, 310, 924, 412}, {-2358, -328, 956, 529}, +{-2639, -377, 630, 278}, {-2602, 317, 799, 299}, {-2406, 133, 340, 31}, +{-2156,-1468, 131, 125}, {-1184, -490, -139, 46}, { -744, 447, 891, 564}, +{ 67, -451, 646, 604}, { -553, -429, -876, 396}, { 162, -66, 1305, 915}, +{ 479, 579, 1088, 794}, { 450, 278, 566, 324}, {-1057, -154, 148, -177}, +{-2545, 168, 1070, 592}, {-2351, -42, 819, 345}, {-2344, -707, 721, 250}, +{-2175,-1497, -309, 122}, { -78, -73, 120, 173}, { -4, 262, -263, -261}, +{ -431, -64, -405, -732}, {-2609, 116, -83, -193}, {-1525, -944, -477, -725}, +{ -508, 307, 170, 172}, { 832, 417, 832, 686}, { -225, 177, 894, 818}, +{ -482, -389, 1279, 1039}, { -383, 201, -350, 40}, { 730, 635, 226, 526}, +{ 503, 462, 338, 398}, { 535, 714, 40, -282}, { 1482, 1471, 1085, 731}, +{ 1561, 1072, 909, 693}, { 1419, 1282, 889, 879}, { 1153, 728, 1186, 840}, +{ -226, 1130, 949, 689}, { -494, -986,-1556, -128}, { -568, -721, -713, -26}, +{ 317, 524, 70, 135}, { -405, -865,-1766, -652}, { -174, -801, 885, 773}, +{ -153, -91, 1099, 751}, { -506,-1149, 853, 646}, { 241, 782, 519, 539}, +{ 1853, 1700, 1101, 684}, {-1249,-1486, -464, 188}, { -893,-1409,-1312, -341}, +{ -135, 438, -175, 18}, { 1111, 976, 319, 208}, {-1430,-1768, 83, 458}, +{ -530,-1000, 307, 129}, { -840, -15, -29, -356}, { -911, -924,-1147, -242}, +{ -119, -528, 127, -133}, { -761, -765, 190, -83}, { -315, 895, 522, 231}, +{ -222, 102, -63, -428}, { 316, 699, 379, 70}, { 25, 716, 314, -108}, +{ 507, 874, 566, 238}, { 108, 941, 519, 195}, { 425, -60, -427, 257}, +{ 139, -103, -630, 446}, { 334, 370, 412, 48}, { -172, -690, -283, 557}, +{ 187, -286, 158, 483}, { 140, 270, -344, -631}, { 924, 579, -116, 132}, +{ 142, 466, -68, -64}, { 230, -145, -302, -542}, { -803, -912, 1018, 737}, +{ -773, 1015, 630, 297}, {-2596, 95, 445, 336}, {-2122, 491, 510, 191}, +{-1253, 161, -2, -324}, {-1450, -633, -712, -105}, { -842, -254, -411, 100}, +{ -640, -290, 1010, 763}, { -650, 313, 1169, 730}, { 140, 505, 1030, 766}, +{ 772, 287, 1067, 823}, { 495, 749, 305, 323}, { -164, 462, 78, 399}, +{ -342, -874, 69, 597}, { -16, 620, 621, 337}, { -138, -444, -265, 218}, +{ 84, -450, 953, 666}, { -222, -803, 541, 604}, { -921,-1376, 244, 116}, +{ -841, -723, 630, 588}, { 140, 663, 294, 368}, { 935, 1046, 881, 759}, +{ 1746, 1464, 916, 628}, { 436, 963, 281, 1}, { -119, 74, 542, 213}, +{ 1, -567, 301, 241}, { 260, 435, 222, 396}, { 936, 957, 1108, 703}, +{ 510, 506, 808, 478}, { 601, 694, 960, 620}, { 972, 741, 980, 600}, +{ 834, 717, 767, 684}, { 643, 972, 935, 638}, { 501, 661, 720, 851}, +{ -105, -632, -303, -117}, { -429, 130, 789, 442}, { -522, -188, 704, 373}, +{ -759, 42, 814, 523}, { -531,-1137, 373, 578}, { -682,-1203, -455, 285}, +{-1163,-1577,-1098, 44}, { 81, -82, 712, 363}, { 477, 246, 954, 622}, +{ 1604, 1622, 1277, 891}, { 1409, 859, 924, 892}, { 774, 1041, 947, 1142}, +{ 40, -546, -75, 288}, { -616, -106, -697, -26}, { -169, -160, -891, -739}, +{ -279, -384,-1029, -350}, { 1781, 1308, 1046, 816}, { 1580, 1533, 1472, 1178}, +{ 1505, 1076, 1216, 899}, { 890, 904, 564, 654}, { 920, 692, 1021, 856}, +{ -493, 132, 177, 505}, { 71, 195, -28, 97}, { 456, 351, -164, 88}, +{ 439, 278, -40, 350}, { 1395, 949, 234, -95}, { -805, -472, 38, -163}, +{ 367, -98, 489, 523}, { 1025, 1178, 1212, 906}, { 319, 1314, 814, 461}, +{ -123, -543, -804, 447}, { -748, -324, -897,-1127}, { -737, -501, -789, -713}, +{ 715, 777, 1239, 922}, { 1949, 1939, 1368, 865}, { 730, 880, 758, 388}, +{ -871, 454, 17, -251}, { -381, -810,-1583, 239}, { -521, -966, -792, 259}, +{ -890,-1358, -770, -73}, { 166, 349, -212, 323}, { -840, -301, 473, 435}, +{ -679, -464, 728, 351}, { -156, -199, 667, 432}, { 29, -252, 415, 480}, +{ -731, -379, 145, 559}, { -528, -631,-1158, -159}, { 445, 273, 123, 639}, +{ 373, -126, 800, 568}, { 84, -162, 720, 712}, { -830, -536, -185, 222}, +{ 408, 452, 501, 771}, { -897,-1355, -67, 442}, { -792,-1406, 566, 602}, +{ 167, -326, 509, 330}, { -95, -626, -730, -344}, { 1668, 1217, 779, 455}, +{ 1316, 828, 584, 719}, { 404, -31, 1013, 789}, { 89, 107, 891, 549}, +{ 871, 1581, 917, 671}, { 866, 1479, 1289, 854}, { 391, 1068, 1122, 812}, +{ 78, -562, 345, 563}, { 429, -103, 417, 787}, { -122, -437, 411, 788}, +{ -913, -417, 602, 754}, { -226, -16, 151, 760}, { -700, 118, -104, -14}, +{-1128, 48, 284, 393}, { -390, -419, -639, -116}, { -910, 306, 316, -13}, +{ 1207, 984, 821, 669}, {-1195, -693, 140, -213}, { -884, -416, -199, -558}, +{ -616, 245, -404, -664}, { 262, 56, -617, -724}, { -85, -491, -320, -656}, +{ -570, -831, -129, -528}, {-1506, -63, -367, -385}, { -358, -321, 4, 51}, +{ -366, -214, 319, 511}, { 146, 671, -17, -291}, { -110, 464, -139, -496}, +{ -202, 220, -312, -631}, { -660, -73, -655, -820}, { -662, -653,-1288, -857}, +{ -430, -953, -959, -264}, { -49, -468, -72, -381}, { -350, -563, -193, -407}, +{ 55, -408, -803, 11}, { -309, 649, 188, -198}, { -512, 461, -79, -458}, +{-1318, -263, -134, -523}, {-1657, -435, -495, -765}, { 57, -347, -414, 434}, +{-1141, -242, -664, -857}, { 34, -68, -707, -338} +}; + +static const int16_t lsf_5_1[128][4] = { +{ -451,-1065, -529,-1305}, { -450, -756, -497, -863}, { -384, -619, -413, -669}, +{ -317, -538, -331, -556}, { -414, -508, -424, -378}, { -274, -324, -434, -614}, +{ -226, -500, -232, -514}, { -263, -377, -298, -410}, { -151, -710, -174, -818}, +{ -149, -412, -156, -429}, { -288, -462, -186, -203}, { -170, -302, -191, -321}, +{ -131, -147, -297, -395}, { -228, -214, -245, -192}, { -67, -316, -71, -327}, +{ -104, -205, -94, -183}, { -143, -38, -193, -95}, { 16, -76, -124, -248}, +{ 23, -237, 24, -244}, { 18, -136, 44, -111}, { -33, -24, -25, 0}, +{ 149, 19, 23, -143}, { 158, -169, 174, -181}, { 133, -55, 165, -26}, +{ 111, 84, 98, 75}, { 87, 183, -115, -11}, { -8, 130, 11, 170}, +{ 254, 77, 205, 17}, { 183, 112, 262, 194}, { 202, 287, 95, 189}, +{ -42, -105, 234, 179}, { 39, 186, 163, 345}, { 332, 199, 299, 161}, +{ -54, 285, -78, 281}, { -133, 141, -182, 111}, { 249, 341, 271, 364}, +{ 93, 403, 75, 391}, { 92, 510, -138, 220}, { -185, -29, -34, 361}, +{ -115, 320, 3, 554}, { 99, 286, 218, 591}, { -245, 406, -268, 453}, +{ 0, 580, 25, 606}, { 275, 532, 148, 450}, { -73, 739, -285, 518}, +{ -288, 94, -203, 674}, { -140, -74, 205, 714}, { -114, 299, 176, 923}, +{ 182, 557, 240, 705}, { -16, 513, 485, 593}, { 293, 384, 451, 617}, +{ -38, 50, 563, 529}, { 303, 209, 459, 363}, { 433, 452, 450, 454}, +{ 367, 606, 477, 741}, { 432, 353, 368, 267}, { 361, 716, 273, 583}, +{ 453, 166, 510, 172}, { 201, 629, 274, 191}, { 568, 639, 302, 298}, +{ 634, 387, 643, 350}, { 587, 560, 612, 565}, { 600, 788, 487, 672}, +{ 512, 1015, 321, 333}, { 357, 854, -125, 413}, { 474, 712, 17, -151}, +{ 564, 285, 270, -241}, { 971, 889, 489, 220}, { 510, 896, 549, 924}, +{ 327, 825, 290, 911}, { 540, 1108, 158, 805}, { 199, 957, 511, 730}, +{ 100, 874, 13, 791}, { 435, 632, 676, 972}, { 249, 900, 467, 1218}, +{ 781, 1074, 585, 785}, { -23, 669, 267, 1043}, { 619, 1084, 615, 1145}, +{ 622, 905, 916, 1049}, { 80, 331, 584, 1075}, { 89, 639, 988, 961}, +{ 770, 720, 798, 699}, { 492, 447, 899, 627}, { 271, 1188, 725, 1333}, +{ 87, 603, 832, 1603}, { 616, 1127, 890, 1505}, { 1000, 1156, 866, 1009}, +{ 995, 827, 1149, 858}, { 817, 1450, 773, 1320}, { 500, 1389, 312, 1153}, +{ -20, 1084, 64, 1283}, { 2, 1172, 399, 1869}, { 514, 1706, 502, 1636}, +{ 886, 1522, 416, 600}, { 1131, 1350, 1275, 1390}, { 889, 1795, 914, 1766}, +{ 227, 1183, 1250, 1826}, { 505, 1854, 919, 2353}, { -199, 431, 152, 1735}, +{ -213, -28, 392, 1334}, { -153, -52, 978, 1151}, { -323, -400, 813, 1703}, +{ -136, 84, 1449, 2015}, { -331, -143, -137, 1192}, { -256, 534, -157, 1031}, +{ -307, -439, 542, 731}, { -329, -420, -97, 616}, { -362, -168, -322, 366}, +{ -247, -110, -211, 89}, { -196, -309, 20, 59}, { -364, -463, -286, 89}, +{ -336, 175, -432, 141}, { -379, -190, -434, -196}, { -79, 150, -278, -227}, +{ -280, 166, -555, -422}, { -155, 541, -366, 54}, { -29, -83, -301, -774}, +{ 186, 628, -397, -264}, { 242, 293, -197, -585}, { 124, 410, 53, -133}, +{ 10, 340, -570,-1065}, { 65, -446, 68, -493}, { 383, 937, -357, -711}, +{ -359, -250, -677,-1068}, { 292, -26, 363, 6}, { 607, 1313, -127, -10}, +{ 1513, 1886, 713, 972}, { 1469, 2181, 1443, 2016} +}; + +static const int16_t lsf_5_2[256][4] = { +{-1631,-1600,-1796,-2290}, {-1027,-1770,-1100,-2025}, {-1277,-1388,-1367,-1534}, +{ -947,-1461, -972,-1524}, { -999,-1222,-1020,-1172}, { -815, -987, -992,-1371}, +{-1216,-1006,-1289,-1094}, { -744,-1268, -755,-1293}, { -862, -923, -905, -984}, +{ -678,-1051, -685,-1050}, {-1087, -985,-1062, -679}, { -989, -641,-1127, -976}, +{ -762, -654, -890, -806}, { -833,-1091, -706, -629}, { -621, -806, -640, -812}, +{ -775, -634, -779, -543}, { -996, -565,-1075, -580}, { -546, -611, -572, -619}, +{ -760, -290, -879, -526}, { -823, -462, -795, -253}, { -553, -415, -589, -439}, +{ -533, -340, -692, -935}, { -505, -772, -702,-1131}, { -263, -306, -971, -483}, +{ -445, -74, -555, -548}, { -614, -129, -693, -234}, { -396, -246, -475, -250}, +{ -265, -404, -376, -514}, { -417, -510, -300, -313}, { -334, -664, -463, -814}, +{ -386, -704, -337, -615}, { -234, -201, -233, -239}, { -167, -567, -203, -619}, +{ -147, -415, -115, -352}, { -166, -750, -171, -761}, { -270, -879, -264, -903}, +{ -367, -744, 43, -475}, { 14, -653, 43, -670}, { 11, -448, -59, -521}, +{ -126, -119, -155, -613}, { -42, -863, -27, -931}, { 136, -483, 183, -468}, +{ 55, -298, 55, -304}, { 313, -609, 313, -720}, { 322, -167, 100, -541}, +{ -3, -119, -111, -187}, { 233, -236, 260, -234}, { 26, -165, 134, -45}, +{ -40, -549, 360, -203}, { 378, -388, 450, -383}, { 275, 20, 182, -103}, +{ 246, -111, 431, 37}, { 462, -146, 487, -157}, { -284, -59, 503, -184}, +{ 24, 53, -3, 54}, { 122, 259, 333, 66}, { 484, 104, 436, 68}, +{ 195, 116, 190, 206}, { 269, -9, 482, 352}, { 382, 285, 399, 277}, +{ 452, 256, 69, 186}, { 13, 297, -13, 259}, { -95, 30, 56, 394}, +{ 196, 425, 205, 456}, { 281, 577, 15, 191}, { 375, 290, 407, 576}, +{ -56, 227, 544, 405}, { 0, 549, -92, 528}, { -229, 351, -245, 338}, +{ -362, 435, 167, 527}, { -75, 302, 91, 824}, { 129, 599, 496, 679}, +{ 186, 749, 153, 737}, { -281, 600, -348, 615}, { -236, 769, 41, 881}, +{ 38, 890, -220, 841}, { -357, 883, -393, 903}, { -634, 474, -444, 850}, +{ -175, 678, -493, 242}, { -519, 785, -714, 582}, { -541, 366, -543, 434}, +{ -597, 500, -765, 222}, { -702, 917, -743, 962}, { -869, 501, -899, 548}, +{ -379, 200, -435, 157}, { -819, 214, -861, 157}, { -614, 40, -632, 94}, +{ -883, -54, -741, 516}, { -501, 298, -614, -171}, { -870, -161, -865, -23}, +{ -818, 93,-1015, -267}, { -662, -359, -549, 2}, { -442, -121, -377, 0}, +{ -227, 33, -414, -126}, { -129, 212, -934, 34}, {-1082, -282,-1119, -268}, +{ -710, -825, -420, -191}, {-1076, -928, -917, -93}, { -628, -358, 97, 7}, +{ -206, -393, -101, 24}, { -203, 38, -168, 83}, { -599, -423, -279, 426}, +{ -700, 118, -75, 206}, { -981, -673, -680, 417}, { -367, 37, -279, 474}, +{ -129, -318, 319, 296}, { -626, -39, 343, 602}, { -696, -39, -303, 940}, +{ 104, 233, -380, 137}, { -36, 269, -75, -214}, { 120, 43, -529, -477}, +{ 459, 164, -202, -229}, { -49, -167, 609, 792}, { 98, -220, 915, 148}, +{ 293, 283, 869, 91}, { 575, 394, 326, -78}, { 717, 67, 365, -323}, +{ 616, -36, 731, 27}, { 619, 238, 632, 273}, { 448, 99, 801, 476}, +{ 869, 273, 685, 64}, { 789, 72, 1021, 217}, { 793, 459, 734, 360}, +{ 646, 480, 360, 322}, { 429, 464, 638, 430}, { 756, 363, 1000, 404}, +{ 683, 528, 602, 615}, { 655, 413, 946, 687}, { 937, 602, 904, 604}, +{ 555, 737, 786, 662}, { 467, 654, 362, 589}, { 929, 710, 498, 478}, +{ 415, 420, 693, 883}, { 813, 683, 781, 925}, { 913, 939, 726, 732}, +{ 491, 853, 531, 948}, { 734, 963, 315, 808}, { 761, 755, 1144, 760}, +{ 655, 1076, 826, 1057}, { 1091, 838, 1003, 808}, { 1047, 1133, 659, 1101}, +{ 992, 1050, 1074, 1075}, { 971, 694, 1226, 1054}, { 571, 841, 884, 1404}, +{ 1379, 1096, 1080, 861}, { 1231, 735, 1284, 760}, { 1272, 991, 1367, 1053}, +{ 1257, 700, 1050, 534}, { 988, 453, 1264, 599}, { 1140, 679, 1621, 815}, +{ 1384, 521, 1317, 393}, { 1564, 805, 1448, 686}, { 1068, 648, 875, 307}, +{ 1083, 361, 1047, 317}, { 1417, 964, 675, 571}, { 1152, 79, 1114, -47}, +{ 1530, 311, 1721, 314}, { 1166, 689, 514, -94}, { 349, 282, 1412, 328}, +{ 1025, 487, -65, 57}, { 805, 970, 36, 62}, { 769, -263, 791, -346}, +{ 637, 699, -137, 620}, { 534, 541, -735, 194}, { 711, 300, -268, -863}, +{ 926, 769, -708, -428}, { 506, 174, -892, -630}, { 435, 547,-1435, -258}, +{ 621, 471,-1018,-1368}, { -393, 521, -920, -686}, { -25, 20, -982,-1156}, +{ 340, 9,-1558,-1135}, { -352, 48,-1579, -402}, { -887, 6,-1156, -888}, +{ -548, -352,-1643,-1168}, { -159, 610,-2024, -963}, { -225, 193,-1656,-1960}, +{ -245, -493, -964,-1680}, { -936, -635,-1299,-1744}, {-1388, -604,-1540, -835}, +{-1397, -135,-1588, -290}, {-1670, -712,-2011,-1632}, {-1663, -27,-2258, -811}, +{-1157, 184,-1265, 189}, {-1367, 586,-2011, 201}, { -790, 712,-1210, 3}, +{-1033, 808,-1251, 830}, { -111, 635,-1636, 447}, { -463, -949, -445, -928}, +{ -504,-1162, -501,-1211}, { 144, -351, -372,-1052}, { -283,-1059, -279,-1123}, +{ -575,-1438, -587,-1614}, { -935, -984, 229, 690}, { -921, -719, -403, 1362}, +{ -685, -465, 874, 397}, { -509, -46, 317, 1334}, { -485, 456, 813, 439}, +{ -411, 339, 898, 1067}, { -425, 46, 1441, 497}, { -909, -800, 1465, 1046}, +{ -254, -321, 1430, 1165}, { 68, 350, 1034, 666}, { 370, 11, 1311, 790}, +{ 143, 232, 1041, 1562}, { -114, 663, 1616, 1078}, { 454, 579, 1275, 1040}, +{ -76, 909, 752, 1067}, { 153, 512, 348, 1214}, { 614, 385, 1843, 808}, +{ 269, 1034, 203, 1086}, { 652, 1017, 1783, 1130}, { 429, 1327, 387, 1384}, +{ -49, 1183, -72, 1215}, { -416, 1001, 544, 1749}, { -352, 1223, -502, 1199}, +{ -589, 569, -227, 1630}, { -142, 1578, -230, 1715}, { -714, 1288, -838, 1398}, +{ 1131, 1357, -208, 1232}, { 437, 965, -929, 818}, { 811, 1410, 859, 1507}, +{ 164, 1212, 1387, 1793}, { 484, 1874, 456, 2063}, { 996, 1170, 1326, 1402}, +{ 1316, 1360, 1135, 1262}, { 1234, 1618, 1361, 1768}, { 1421, 1227, 1584, 1347}, +{ 854, 672, 1685, 1566}, { 1139, 1270, 2016, 1825}, { 1773, 1581, 1532, 1460}, +{ 1487, 946, 1659, 1021}, { 1744, 1212, 1392, 977}, { 1772, 1161, 1826, 1164}, +{ 1718, 1429, 1973, 1591}, { 1185, 864, 2132, 1061}, { 1799, 814, 1838, 757}, +{ 2104, 1315, 2054, 1258}, { 2113, 915, 2331, 930}, { 1467, 1147, 2590, 1439}, +{ 2245, 1744, 2090, 1620}, { 2358, 1454, 2666, 1506}, { 1876, 1837, 2070, 1975}, +{ 1739, 1577, 682, 1289}, { 1584, 2045, 1454, 2098}, { 2498, 2004, 2711, 2066}, +{ 726, 1588, 2756, 2336}, { 228, 847, 2456, 1659}, { 36, 301, 1942, 1957}, +{ -446, -96, 2154, 1396}, { 1533, 1101, 14, 608}, { -923, -732, 1383, 1982}, +{ 1345, 952, -680, 321}, { 1281, 1268,-1594, 365}, { 941, 946,-1737, -822}, +{ 2374, 2787, 1821, 2788} +}; + +static const int16_t lsf_5_3[256][4] = { +{-1812,-2275,-1879,-2537}, {-1640,-1848,-1695,-2004}, {-1220,-1912,-1221,-2106}, +{-1559,-1588,-1573,-1556}, {-1195,-1615,-1224,-1727}, {-1359,-1151,-1616,-1948}, +{-1274,-1391,-1305,-1403}, {-1607,-1179,-1676,-1311}, {-1443,-1478,-1367, -898}, +{-1256,-1059,-1331,-1134}, { -982,-1133,-1149,-1504}, {-1080,-1308,-1020,-1183}, +{ -980,-1486, -967,-1495}, { -988, -922,-1047,-1077}, { -838,-1179, -858,-1222}, +{-1131,-1041,-1064, -767}, { -872,-1157, -701, -880}, { -706, -906, -774,-1016}, +{ -578,-1080, -801,-1478}, { -591,-1111, -592,-1146}, { -713,-1388, -640,-1376}, +{ -597,-1059, -416, -903}, { -686, -832, -661, -708}, { -444, -868, -490, -921}, +{ -374, -776, -619,-1170}, { -585, -549, -769, -795}, { -435, -659, -530, -741}, +{ -498, -837, -357, -597}, { -279, -871, -243, -887}, { -282, -665, -280, -667}, +{ -165, -560, -394, -903}, { -362, -410, -448, -583}, { -409, -574, -313, -357}, +{ -637, -548, -570, -436}, { -896, -504, -382, -757}, { -58, -481, -165, -618}, +{ -191, -374, -234, -382}, { -222, -683, -25, -480}, { -418, -359, -730, -353}, +{ -324, -157, -432, -322}, { -394, -303, -284, -104}, { -601, -289, -556, -196}, +{ -588, -150, -659, -608}, { -473, -24, -68, -448}, { -474, -8, -506, -45}, +{ -748, -184, -844, -252}, { -901, -91, -584, -97}, { -652, 138, -764, -131}, +{ -678, -12, -670, 165}, { -259, -3, -840, -107}, { -909, 37, -992, 44}, +{ -854, -415, -839, 13}, {-1001, -271,-1026, -309}, { -798, -478, -832, -488}, +{ -943, 168,-1112, -387}, {-1185, -101,-1183, -40}, { -941, -316,-1030, -770}, +{-1044, -625,-1081, -538}, {-1224, -299,-1312, -436}, {-1197, -663,-1167, -161}, +{-1216, -690,-1237, -831}, {-1432, -720,-1403, -493}, { -898, -740, -922, -801}, +{-1102, -402,-1579, -964}, {-1061, -638,-1269,-1438}, {-1499, -934,-1502, -895}, +{-1598, -564,-1723, -717}, { -606, -597,-1166,-1085}, {-1369, -468,-1946,-1493}, +{-1838, -953,-1932, -931}, {-1499, -188,-1635, -421}, {-1457, -338,-1448, -22}, +{-1942, -422,-2006, -249}, { -496, -114,-1910, -755}, {-1289, 174,-1451, -109}, +{ -482, -257,-1221, -508}, {-1617, 151,-1694, 208}, { -654, 107,-1651, 29}, +{-1141, 279,-1215, 306}, {-1228, -506, -730, -175}, {-1236, -101, -969, 551}, +{ -870, 278, -823, 315}, { -563, 376,-1051, 228}, { -507, 280, -599, 281}, +{ -758, 253, -305, 379}, { -755, -134, -611, 660}, { -824, 536, -817, 646}, +{ -413, 49, -341, 177}, { -453, 526, -482, 589}, { -71, 339, -657, 264}, +{ -244, 295, -237, 315}, { -387, 569, -506, -9}, { -377, 14, -160, 661}, +{ -216, 40, -308, -46}, { 95, 214, -242, 167}, { -86, 192, -56, 27}, +{ -76, 31, 36, 309}, { -106, -182, -113, 74}, { -441, -22, 23, 139}, +{ 81, -11, 44, 15}, { -87, -137, -118, -207}, { -158, -58, 272, -92}, +{ -156, -441, 8, -136}, { 128, -221, 101, -218}, { 40, -197, -76, -456}, +{ 9, -445, 33, -423}, { 226, 60, 73, -222}, { 156, -399, 280, -318}, +{ 245, -341, 166, -499}, { 339, -190, 327, -219}, { 325, -137, -89, -596}, +{ 100, -627, 144, -677}, { 487, 28, 252, -391}, { 214, -41, 282, -28}, +{ 99, -286, 331, 49}, { 459, -388, 565, -369}, { 436, 28, 336, -9}, +{ 397, -167, 618, 34}, { 596, -17, 561, -140}, { 299, 79, 522, 125}, +{ 203, 2, 244, 288}, { 255, 211, 175, 82}, { 596, 187, 517, 108}, +{ 381, 255, 365, 297}, { 497, 352, 327, -82}, { 25, 210, 371, 245}, +{ 261, 3, 545, 449}, { 140, 294, 44, 295}, { 212, 347, 244, 494}, +{ 331, 528, 201, 307}, { 349, 411, 613, 284}, { 614, 413, 464, 322}, +{ 624, 397, 97, 200}, { -160, 384, 149, 362}, { 495, 525, 269, 585}, +{ 33, 491, -121, 433}, { 427, 611, 498, 516}, { 171, 443, 497, 666}, +{ 440, 275, 566, 575}, { 146, 639, 155, 670}, { -33, 173, 212, 696}, +{ -166, 601, -191, 695}, { -489, 503, 175, 742}, { 214, 476, 372, 1083}, +{ 578, 530, 586, 777}, { 425, 874, 315, 841}, { 374, 848, -165, 565}, +{ 35, 991, -39, 1062}, { 329, 712, 786, 840}, { 645, 795, 661, 676}, +{ 571, 918, 632, 1079}, { 673, 817, 318, 388}, { 874, 1012, 564, 848}, +{ 880, 620, 557, 479}, { 671, 453, 692, 468}, { 840, 642, 844, 645}, +{ 506, 428, 897, 567}, { 837, 387, 962, 499}, { 691, 561, 939, 926}, +{ 783, 296, 790, 268}, { 1028, 530, 874, 329}, { 548, 143, 675, 291}, +{ 503, 66, 1041, 359}, { 786, 97, 805, 33}, { 837, 470, 511, 49}, +{ 1092, 327, 1174, 323}, { 3, 242, 872, 474}, { 689, 429, 1329, 678}, +{ 1042, 620, 1109, 664}, { 321, 193, 889, 950}, { 1153, 874, 893, 635}, +{ 877, 862, 948, 913}, { 1293, 665, 1320, 639}, { 997, 793, 1402, 1030}, +{ 1176, 1012, 1110, 959}, { 1410, 925, 1403, 915}, { 543, 862, 1116, 1222}, +{ 835, 1190, 835, 1190}, { 959, 1148, 1147, 1376}, { 1300, 1193, 1415, 1231}, +{ 1335, 1341, 746, 1092}, { 1711, 1283, 1389, 1073}, { 1334, 1566, 1153, 1475}, +{ 1645, 1137, 1825, 1220}, { 1056, 1382, 1521, 1730}, { 1632, 1545, 1620, 1542}, +{ 855, 1596, 865, 1667}, { 693, 885, 1716, 1519}, { 1167, 1296, 2209, 1760}, +{ 1952, 1493, 2020, 1482}, { 1534, 1866, 1694, 2008}, { 1566, 748, 1761, 825}, +{ 294, 1392, 1084, 2058}, { 621, 1315, 365, 1287}, { 198, 1028, 488, 1408}, +{ 249, 403, 1014, 1561}, { 324, 363, 1645, 1044}, { 193, 367, 2034, 1859}, +{ -251, 579, 750, 994}, { -243, 30, 1325, 879}, { -28, -169, 624, 917}, +{ -453, 159, 186, 1370}, { -614, 6, 537, 392}, { -94, -291, 781, 229}, +{ -128, -298, 245, 491}, { -701, -648, 972, 789}, { -501, -640, 178, 255}, +{ -365, -390, -255, 317}, { -958, -294, -191, 228}, { -775, -447, 157, -237}, +{ -657, -720, -407, 92}, { -117, -611, 334, -230}, { -679,-1084, -144, -317}, +{ -901, -861, -738, -360}, { -85, -727, -90, -787}, { 100, -22, -391, -263}, +{ -56, -73, -337, -754}, { 5, -189, -706, -624}, { 89, -344, -135,-1113}, +{ -353, -237, -684,-1135}, { -275,-1102, -269,-1203}, { 152, 145, -722,-1232}, +{ 49, 80,-1248, -776}, { -248, 391, -732, -547}, { 469, 218, -255, -864}, +{ 69, 366, -166, -485}, { -688, 191,-1212,-1196}, { -170, -169,-1308,-1631}, +{ 321, 470,-1419,-1243}, { -64, 272,-1361, -248}, { 492, 565, -721, -609}, +{ 195, 485, -573, -133}, { 427, 202, -171, -118}, { 199, 575, 2, -31}, +{ 694, 755,-1366, -39}, { 552, 557, -489, 271}, { 680, 537, 13, -453}, +{ 855, 954, -133, -52}, { -81, 738,-1169, 637}, { 1055, 1059, -95, 676}, +{ 1259, 1081, 489, 305}, { -449, 954, -534, 996}, { -969, 866,-1058, 1059}, +{-1294, 618,-1416, 617}, { -458, 1366, -159, 1821}, { -774, -528, -14, 1110}, +{-1202, -901, -772, 433}, {-1256,-1255,-1011, -302}, { -602, -585, -759,-1618}, +{ -760,-1549, -840,-1921}, { -816, -539,-1769,-2235}, { -227, -36,-2034,-1831}, +{-2107,-1126,-2471,-1816}, {-1470, 252,-2701, -415}, { -571, -467, 1509, 1554}, +{ 2180, 1975, 2326, 2020} +}; + +static const int16_t lsf_5_4[256][4] = { +{-1857,-1681,-1857,-1755}, {-2056,-1150,-2134,-1654}, {-1619,-1099,-1704,-1131}, +{-1345,-1608,-1359,-1638}, {-1338,-1293,-1325,-1265}, {-1664,-1649,-1487, -851}, +{-1346,-1832,-1413,-2188}, {-1282, -681,-1785,-1649}, { -966,-1082,-1183,-1676}, +{-1054,-1073,-1142,-1158}, {-1207, -744,-1274, -997}, { -934,-1383, -927,-1416}, +{-1010,-1305, -783, -955}, {-1049, -900, -993, -817}, { -737, -823, -972,-1189}, +{ -738,-1094, -738,-1154}, { -784, -801, -810, -786}, { -892, -520,-1000, -818}, +{ -644, -965, -577, -882}, { -541, -694, -671, -917}, { -595, -642, -646, -615}, +{ -956, -621, -925, -515}, { -727, -483, -815, -485}, { -840, -578, -440, -713}, +{ -578, -325, -657, -670}, { -386, -570, -441, -666}, { -514, -787, -392, -529}, +{ -522, -453, -487, -423}, { -616, -585, -617, -157}, { -662, -268, -680, -348}, +{ -322, -323, -632, -444}, { -304, -430, -332, -458}, { -277, -468, -659, -793}, +{ -319, -636, -227, -554}, { -373, -347, -334, -210}, { -456, -192, -530, -242}, +{ -216, -198, -366, -370}, { -338, -161, -409, -748}, { -107, -380, -294, -643}, +{ -223, -665, -234, -741}, { -141, -496, -130, -510}, { -139, -327, -172, -305}, +{ -306, -580, -164, -263}, { -262, -172, -67, -402}, { 31, -366, -10, -436}, +{ -86, -527, 71, -377}, { -22, -609, -12, -678}, { -67, -319, 63, -191}, +{ 35, -181, -39, -242}, { 126, -167, -140, -544}, { 155, -297, 174, -297}, +{ 38, -8, 117, -380}, { 197, -452, 240, -522}, { 223, -103, 110, -187}, +{ 87, -155, 169, -47}, { 157, 26, -83, -100}, { 128, 80, 209, -62}, +{ 6, 7, 22, 5}, { 318, -20, 248, -45}, { -200, -63, 156, -69}, +{ 250, -183, 369, -126}, { -113, -76, -142, -122}, { -64, -254, -31, 35}, +{ -177, -71, -7, 171}, { 93, 27, 108, 212}, { -330, -209, -123, -70}, +{ -279, 95, -96, 20}, { -188, -61, -314, 87}, { -300, -78, -354, -134}, +{ 11, 122, -140, 122}, { -275, 152, -293, 140}, { -82, 138, -321, -111}, +{ -480, -156, -359, 76}, { -254, -40, -635, -96}, { -522, 79, -507, 8}, +{ -268, 303, -539, 68}, { -446, 61, -522, 306}, { 111, 189, -435, 122}, +{ -379, 166, -571, -398}, { -632, -74, -747, -95}, { -455, 194, -952, 83}, +{ -798, 192, -755, 192}, { -781, -162, -619, 234}, { -663, -297, -488, -109}, +{ -964, -132, -838, -68}, { -843, 58,-1112, -86}, { -805, -299, -944, -253}, +{ -778, -50, -965, -549}, { -352, -98, -992, -343}, {-1117, -315,-1117, -307}, +{-1155, -374, -637, -230}, {-1166, -43,-1299, -100}, { -925, -393,-1274, -600}, +{ -689, -130,-1479, -312}, {-1321, -254,-1464, -442}, {-1292, -613,-1261, -503}, +{-1501, -368,-1322, 26}, {-1432, -66,-1743, -161}, {-1644, -467,-1760, -548}, +{-1393, -568,-1556, -871}, {-1495,-1034,-1387, -571}, {-1917, -528,-1783, -123}, +{-1897, -231,-2054, -323}, {-2052, -906,-1976, -567}, {-1917, -620,-2047, -989}, +{-1077, -370,-2031, -704}, {-2355, -749,-2740,-1089}, {-1909, 159,-2012, 248}, +{ -626, -123,-2339, -962}, { -669, -408,-1379,-1174}, { -452, -364,-1044, -735}, +{ -132, 183,-1620, -752}, { -547, -307, -777,-1261}, { -98, 41, -880,-1091}, +{ -257, 97,-1602,-1833}, { 31, -26, -644, -561}, { -180, -546, -385,-1095}, +{ -410, -802, -414, -827}, { -457, -970, -490,-1109}, { -215, -916, -144, -937}, +{ -493,-1269, -517,-1507}, { 181, 101, -332, -889}, { -836, -937, -559, -429}, +{ -629, -547, -183, -337}, { -545, -82, -250, -286}, { 5, -132, -348, -252}, +{ -293, -472, -158, 100}, { -29, 197, -236, -424}, { -861, -213, -140, -7}, +{ -427, -443, 187, -97}, { -684, -736, -293, 258}, { -368, -152, -150, 392}, +{ -609, 175, -142, 299}, { -138, 152, -119, 329}, { -486, -52, 293, 198}, +{ -183, 117, 175, 331}, { -58, -274, 231, 300}, { -288, 330, -305, 372}, +{ -111, 409, -9, 423}, { 83, 256, 67, 367}, { -19, 248, 91, 113}, +{ -35, 406, -191, 154}, { 238, 296, 5, 197}, { 141, 221, 313, 198}, +{ 211, 421, 244, 334}, { 88, 426, -243, 454}, { 202, 552, -5, 403}, +{ 291, 185, 219, 301}, { 251, 138, 128, 69}, { 197, 288, -140, -61}, +{ 188, 361, 197, 598}, { 442, 273, 290, 143}, { 472, 482, 157, 370}, +{ 415, 321, 372, 385}, { 402, 552, 155, 24}, { 550, 263, -11, 21}, +{ 360, 227, 147, -254}, { 424, 97, 366, -13}, { 375, 141, 449, 232}, +{ 396, 507, 474, 272}, { 701, 324, 362, -47}, { 587, 148, 543, 69}, +{ 400, -51, 561, 59}, { 220, -10, 352, 147}, { 206, 211, 653, 185}, +{ 563, 297, 565, 284}, { 594, 121, 766, 192}, { 398, 118, 642, 434}, +{ 233, 264, 481, 467}, { 129, -165, 699, 239}, { 90, 26, 342, 474}, +{ -55, 27, 388, 94}, { -172, 0, 725, 379}, { -60, 337, 370, 465}, +{ 95, 319, 806, 595}, { 78, 260, 497, 851}, { 210, 560, 458, 574}, +{ -464, 202, 497, 625}, { -202, 152, 48, 712}, { -20, 566, 100, 715}, +{ 455, 468, 411, 605}, { 319, 646, 195, 615}, { 401, 538, 680, 739}, +{ 201, 667, 434, 954}, { 454, 425, 646, 491}, { 606, 681, 416, 508}, +{ 497, 822, 426, 815}, { 660, 647, 628, 716}, { 697, 466, 618, 457}, +{ 685, 460, 365, 309}, { 721, 567, 836, 601}, { 609, 300, 825, 459}, +{ 943, 687, 681, 533}, { 915, 598, 591, 243}, { 876, 451, 874, 420}, +{ 786, 317, 732, 220}, { 922, 317, 1108, 367}, { 531, 466, 1028, 649}, +{ 1053, 615, 1034, 553}, { 829, 602, 1021, 799}, { 927, 803, 878, 763}, +{ 799, 496, 1373, 773}, { 585, 770, 803, 930}, { 1099, 793, 1222, 862}, +{ 1209, 895, 1025, 727}, { 772, 845, 1172, 1115}, { 867, 1021, 830, 1013}, +{ 841, 910, 506, 703}, { 1239, 1077, 620, 819}, { 1196, 1083, 1155, 1081}, +{ 1142, 907, 1547, 1121}, { 1309, 648, 1343, 612}, { 1484, 988, 1479, 937}, +{ 985, 1328, 955, 1341}, { 429, 910, 841, 1338}, { 564, 1179, 412, 1156}, +{ 1427, 1320, 1434, 1330}, { 640, 760, 1726, 1410}, { 190, 555, 1073, 1005}, +{ 426, 257, 839, 980}, { 235, 231, 1520, 1167}, { 109, 293, 1014, 1569}, +{ 305, 142, 1148, 539}, { -291, -108, 1213, 972}, { 22, -216, 667, 828}, +{ -482, 438, 453, 1431}, { -581, -422, 789, 387}, { -358, -454, 174, 780}, +{ -36, -372, 390, -134}, { -629, 160, -306, 751}, {-1258, -331, 177, 522}, +{ -248, 574, -251, 639}, { -531, 407, -596, 394}, { -419, 789, -617, 801}, +{ -986, 399, -857, 727}, { -7, 518, -703, 310}, {-1143, -24,-1002, 287}, +{ -960, 363,-1299, 312}, {-1534, 245,-1557, 305}, { 28, 153, -859, -175}, +{ -33, 332,-1398, -154}, { 212, 410, -593, -197}, {-1092, -704, -904, -65}, +{ 282, 367, -918, -686}, { 345, 93, -258, -357}, { 696, 644, -693, -28}, +{ 448, 493, -273, 193}, { 527, 546, -243, -513}, { 384, -136, 273, -353}, +{ 512, -142, 537, -198}, { 941, 750, 83, 248}, { 578, 861, -56, 592}, +{ 842, 44, 892, 24}, { 33, 890, -16, 982}, { 831, 1398, 1535, 1898}, +{ 1716, 1376, 1948, 1465} +}; + +static const int16_t lsf_5_5[64][4] = { +{-1002, -929,-1096,-1203}, { -641, -931, -604, -961}, { -779, -673, -835, -788}, +{ -416, -664, -458, -766}, { -652, -521, -662, -495}, {-1023, -509,-1023, -428}, +{ -444, -552, -368, -449}, { -479, -211,-1054, -903}, { -316, -249, -569, -591}, +{ -569, -275, -541, -191}, { -716, -188, -842, -264}, { -333, -248, -318, -228}, +{ -275, 1, -567, -228}, { -115, -221, -238, -374}, { -197, -507, -222, -579}, +{ -258, -432, -61, -244}, { -345, 2, -338, 39}, { -215, -169, -58, 0}, +{ -56, -6, -203, -131}, { 1, -186, -5, -211}, { 6, -380, 11, -418}, +{ -116, 131, -134, 113}, { 89, -4, 71, -2}, { -19, -192, 262, 24}, +{ 189, 151, -133, -109}, { 186, -153, 166, -219}, { 37, 139, 193, 171}, +{ 337, 124, 158, -61}, { 141, 226, -13, 190}, { 231, 34, 354, 109}, +{ 316, 201, 244, 164}, { 330, -85, 390, -84}, { 254, 327, 257, 335}, +{ 491, 147, 476, 105}, { 54, 77, 437, 370}, { 421, 314, 449, 342}, +{ 329, 126, 673, 292}, { 571, 388, 243, 193}, { 653, 320, 621, 280}, +{ 194, 380, 517, 581}, { 45, 323, 111, 422}, { 489, 395, 734, 534}, +{ 622, 546, 486, 502}, { 318, 572, 189, 550}, { 385, 422, -157, 153}, +{ -125, 382, -197, 386}, { -263, 334, 228, 697}, { -188, 1, 51, 297}, +{ -507, 213, -376, 397}, { -24, 255, -547, 89}, { -502, -94, 387, 179}, +{ -620, 68, -684, 112}, { -642, -350, -260, 172}, { -438, -324, 264, 648}, +{ -964, -4,-1121, 7}, { -134, 134,-1133, -306}, { 143, 96, -420, -497}, +{-1221, -350,-1527, -685}, { -161, 72, 873, 691}, { 732, 283, 921, 353}, +{ 334, 475, 1095, 821}, { 864, 524, 843, 497}, { 714, 711, 788, 750}, +{ 1076, 714, 1204, 753} +}; + +static const float lsf_3_mean[LP_FILTER_ORDER] = { + 377.441, 554.688, 922.363, 1339.84, 1702.15, + 2046.390, 2452.880, 2741.460, 3116.70, 3348.14 +}; + +static const float lsf_5_mean[LP_FILTER_ORDER] = { + 337.891, 507.080, 834.961, 1247.07, 1646.00, + 1982.910, 2407.960, 2708.010, 3104.00, 3344.97 +}; + +/** Prediction factor table for modes other than 12.2kbit/s */ +static const float pred_fac[LP_FILTER_ORDER] = { + 0.291626, 0.328644, 0.383636, 0.405640, 0.438873, + 0.355560, 0.323120, 0.298065, 0.262238, 0.197876, +}; + +// fixed tables + +/** + * number of pulses per mode + */ +static const uint8_t pulses_nb_per_mode[] = {2, 2, 2, 3, 4, 4, 8, 10}; + +/** track start positions for algebraic code book routines */ +static const uint8_t track_position[16] = { + 0, 2, 0, 3, 0, 2, 0, 3, 1, 3, 2, 4, 1, 4, 1, 4 +}; + +/** 3-bit Gray code to binary lookup table */ +static const uint8_t gray_decode[8] = { 0, 5, 15, 10, 25, 30, 20, 35 }; + + +// gain tables + +/** scalar quantized pitch gain table for 7.95 and 12.2 kbps modes */ +static const uint16_t qua_gain_pit[16] = { + 0, 3277, 6556, 8192, 9830, 11469, 12288, 13107, + 13926, 14746, 15565, 16384, 17203, 18022, 18842, 19661 +}; + +/** scalar quantized fixed gain table for 7.95 and 12.2 kbps modes */ +static const uint16_t qua_gain_code[32] = { + 159, 206, 268, 349, 419, 482, 554, 637, + 733, 842, 969, 1114, 1281, 1473, 1694, 1948, + 2241, 2577, 2963, 3408, 3919, 4507, 5183, 5960, + 6855, 7883, 9065, 10425, 12510, 16263, 21142, 27485 +}; + +/** desired mean innovation energy, indexed by active mode */ +static const float energy_mean[8] = { + 33.0, 33.0, 33.0, 28.75, 30.0, 36.0, 33.0, 36.0 +}; + +/** 4-tap moving average prediction coefficients in reverse order */ +static const float energy_pred_fac[4] = { 0.19, 0.34, 0.58, 0.68 }; + +/** gain table for 4.75 kbps mode + * + * first index has even/odd indexes for subframes 0,2/1,3 + * second index is {pitch_gain, fixed_gain_factor} */ +static const uint16_t gains_MODE_4k75[512][2] = { +{ 812, 128}, { 542, 140}, { 2873, 1135}, { 2266, 3402}, { 2067, 563}, +{12677, 647}, { 4132, 1798}, { 5601, 5285}, { 7689, 374}, { 3735, 441}, +{10912, 2638}, {11807, 2494}, {20490, 797}, { 5218, 675}, { 6724, 8354}, +{ 5282, 1696}, { 1488, 428}, { 5882, 452}, { 5332, 4072}, { 3583, 1268}, +{ 2469, 901}, {15894, 1005}, {14982, 3271}, {10331, 4858}, { 3635, 2021}, +{ 2596, 835}, {12360, 4892}, {12206, 1704}, {13432, 1604}, { 9118, 2341}, +{ 3968, 1538}, { 5479, 9936}, { 3795, 417}, { 1359, 414}, { 3640, 1569}, +{ 7995, 3541}, {11405, 645}, { 8552, 635}, { 4056, 1377}, {16608, 6124}, +{11420, 700}, { 2007, 607}, {12415, 1578}, {11119, 4654}, {13680, 1708}, +{11990, 1229}, { 7996, 7297}, {13231, 5715}, { 2428, 1159}, { 2073, 1941}, +{ 6218, 6121}, { 3546, 1804}, { 8925, 1802}, { 8679, 1580}, {13935, 3576}, +{13313, 6237}, { 6142, 1130}, { 5994, 1734}, {14141, 4662}, {11271, 3321}, +{12226, 1551}, {13931, 3015}, { 5081,10464}, { 9444, 6706}, { 1689, 683}, +{ 1436, 1306}, { 7212, 3933}, { 4082, 2713}, { 7793, 704}, {15070, 802}, +{ 6299, 5212}, { 4337, 5357}, { 6676, 541}, { 6062, 626}, {13651, 3700}, +{11498, 2408}, {16156, 716}, {12177, 751}, { 8065,11489}, { 6314, 2256}, +{ 4466, 496}, { 7293, 523}, {10213, 3833}, { 8394, 3037}, { 8403, 966}, +{14228, 1880}, { 8703, 5409}, {16395, 4863}, { 7420, 1979}, { 6089, 1230}, +{ 9371, 4398}, {14558, 3363}, {13559, 2873}, {13163, 1465}, { 5534, 1678}, +{13138,14771}, { 7338, 600}, { 1318, 548}, { 4252, 3539}, {10044, 2364}, +{10587, 622}, {13088, 669}, {14126, 3526}, { 5039, 9784}, {15338, 619}, +{ 3115, 590}, {16442, 3013}, {15542, 4168}, {15537, 1611}, {15405, 1228}, +{16023, 9299}, { 7534, 4976}, { 1990, 1213}, {11447, 1157}, {12512, 5519}, +{ 9475, 2644}, { 7716, 2034}, {13280, 2239}, {16011, 5093}, { 8066, 6761}, +{10083, 1413}, { 5002, 2347}, {12523, 5975}, {15126, 2899}, {18264, 2289}, +{15827, 2527}, {16265,10254}, {14651,11319}, { 1797, 337}, { 3115, 397}, +{ 3510, 2928}, { 4592, 2670}, { 7519, 628}, {11415, 656}, { 5946, 2435}, +{ 6544, 7367}, { 8238, 829}, { 4000, 863}, {10032, 2492}, {16057, 3551}, +{18204, 1054}, { 6103, 1454}, { 5884, 7900}, {18752, 3468}, { 1864, 544}, +{ 9198, 683}, {11623, 4160}, { 4594, 1644}, { 3158, 1157}, {15953, 2560}, +{12349, 3733}, {17420, 5260}, { 6106, 2004}, { 2917, 1742}, {16467, 5257}, +{16787, 1680}, {17205, 1759}, { 4773, 3231}, { 7386, 6035}, {14342,10012}, +{ 4035, 442}, { 4194, 458}, { 9214, 2242}, { 7427, 4217}, {12860, 801}, +{11186, 825}, {12648, 2084}, {12956, 6554}, { 9505, 996}, { 6629, 985}, +{10537, 2502}, {15289, 5006}, {12602, 2055}, {15484, 1653}, {16194, 6921}, +{14231, 5790}, { 2626, 828}, { 5615, 1686}, {13663, 5778}, { 3668, 1554}, +{11313, 2633}, { 9770, 1459}, {14003, 4733}, {15897, 6291}, { 6278, 1870}, +{ 7910, 2285}, {16978, 4571}, {16576, 3849}, {15248, 2311}, {16023, 3244}, +{14459,17808}, {11847, 2763}, { 1981, 1407}, { 1400, 876}, { 4335, 3547}, +{ 4391, 4210}, { 5405, 680}, {17461, 781}, { 6501, 5118}, { 8091, 7677}, +{ 7355, 794}, { 8333, 1182}, {15041, 3160}, {14928, 3039}, {20421, 880}, +{14545, 852}, {12337,14708}, { 6904, 1920}, { 4225, 933}, { 8218, 1087}, +{10659, 4084}, {10082, 4533}, { 2735, 840}, {20657, 1081}, {16711, 5966}, +{15873, 4578}, {10871, 2574}, { 3773, 1166}, {14519, 4044}, {20699, 2627}, +{15219, 2734}, {15274, 2186}, { 6257, 3226}, {13125,19480}, { 7196, 930}, +{ 2462, 1618}, { 4515, 3092}, {13852, 4277}, {10460, 833}, {17339, 810}, +{16891, 2289}, {15546, 8217}, {13603, 1684}, { 3197, 1834}, {15948, 2820}, +{15812, 5327}, {17006, 2438}, {16788, 1326}, {15671, 8156}, {11726, 8556}, +{ 3762, 2053}, { 9563, 1317}, {13561, 6790}, {12227, 1936}, { 8180, 3550}, +{13287, 1778}, {16299, 6599}, {16291, 7758}, { 8521, 2551}, { 7225, 2645}, +{18269, 7489}, {16885, 2248}, {17882, 2884}, {17265, 3328}, { 9417,20162}, +{11042, 8320}, { 1286, 620}, { 1431, 583}, { 5993, 2289}, { 3978, 3626}, +{ 5144, 752}, {13409, 830}, { 5553, 2860}, {11764, 5908}, {10737, 560}, +{ 5446, 564}, {13321, 3008}, {11946, 3683}, {19887, 798}, { 9825, 728}, +{13663, 8748}, { 7391, 3053}, { 2515, 778}, { 6050, 833}, { 6469, 5074}, +{ 8305, 2463}, { 6141, 1865}, {15308, 1262}, {14408, 4547}, {13663, 4515}, +{ 3137, 2983}, { 2479, 1259}, {15088, 4647}, {15382, 2607}, {14492, 2392}, +{12462, 2537}, { 7539, 2949}, {12909,12060}, { 5468, 684}, { 3141, 722}, +{ 5081, 1274}, {12732, 4200}, {15302, 681}, { 7819, 592}, { 6534, 2021}, +{16478, 8737}, {13364, 882}, { 5397, 899}, {14656, 2178}, {14741, 4227}, +{14270, 1298}, {13929, 2029}, {15477, 7482}, {15815, 4572}, { 2521, 2013}, +{ 5062, 1804}, { 5159, 6582}, { 7130, 3597}, {10920, 1611}, {11729, 1708}, +{16903, 3455}, {16268, 6640}, { 9306, 1007}, { 9369, 2106}, {19182, 5037}, +{12441, 4269}, {15919, 1332}, {15357, 3512}, {11898,14141}, {16101, 6854}, +{ 2010, 737}, { 3779, 861}, {11454, 2880}, { 3564, 3540}, { 9057, 1241}, +{12391, 896}, { 8546, 4629}, {11561, 5776}, { 8129, 589}, { 8218, 588}, +{18728, 3755}, {12973, 3149}, {15729, 758}, {16634, 754}, {15222,11138}, +{15871, 2208}, { 4673, 610}, {10218, 678}, {15257, 4146}, { 5729, 3327}, +{ 8377, 1670}, {19862, 2321}, {15450, 5511}, {14054, 5481}, { 5728, 2888}, +{ 7580, 1346}, {14384, 5325}, {16236, 3950}, {15118, 3744}, {15306, 1435}, +{14597, 4070}, {12301,15696}, { 7617, 1699}, { 2170, 884}, { 4459, 4567}, +{18094, 3306}, {12742, 815}, {14926, 907}, {15016, 4281}, {15518, 8368}, +{17994, 1087}, { 2358, 865}, {16281, 3787}, {15679, 4596}, {16356, 1534}, +{16584, 2210}, {16833, 9697}, {15929, 4513}, { 3277, 1085}, { 9643, 2187}, +{11973, 6068}, { 9199, 4462}, { 8955, 1629}, {10289, 3062}, {16481, 5155}, +{15466, 7066}, {13678, 2543}, { 5273, 2277}, {16746, 6213}, {16655, 3408}, +{20304, 3363}, {18688, 1985}, {14172,12867}, {15154,15703}, { 4473, 1020}, +{ 1681, 886}, { 4311, 4301}, { 8952, 3657}, { 5893, 1147}, {11647, 1452}, +{15886, 2227}, { 4582, 6644}, { 6929, 1205}, { 6220, 799}, {12415, 3409}, +{15968, 3877}, {19859, 2109}, { 9689, 2141}, {14742, 8830}, {14480, 2599}, +{ 1817, 1238}, { 7771, 813}, {19079, 4410}, { 5554, 2064}, { 3687, 2844}, +{17435, 2256}, {16697, 4486}, {16199, 5388}, { 8028, 2763}, { 3405, 2119}, +{17426, 5477}, {13698, 2786}, {19879, 2720}, { 9098, 3880}, {18172, 4833}, +{17336,12207}, { 5116, 996}, { 4935, 988}, { 9888, 3081}, { 6014, 5371}, +{15881, 1667}, { 8405, 1183}, {15087, 2366}, {19777, 7002}, {11963, 1562}, +{ 7279, 1128}, {16859, 1532}, {15762, 5381}, {14708, 2065}, {20105, 2155}, +{17158, 8245}, {17911, 6318}, { 5467, 1504}, { 4100, 2574}, {17421, 6810}, +{ 5673, 2888}, {16636, 3382}, { 8975, 1831}, {20159, 4737}, {19550, 7294}, +{ 6658, 2781}, {11472, 3321}, {19397, 5054}, {18878, 4722}, {16439, 2373}, +{20430, 4386}, {11353,26526}, {11593, 3068}, { 2866, 1566}, { 5108, 1070}, +{ 9614, 4915}, { 4939, 3536}, { 7541, 878}, {20717, 851}, { 6938, 4395}, +{16799, 7733}, {10137, 1019}, { 9845, 964}, {15494, 3955}, {15459, 3430}, +{18863, 982}, {20120, 963}, {16876,12887}, {14334, 4200}, { 6599, 1220}, +{ 9222, 814}, {16942, 5134}, { 5661, 4898}, { 5488, 1798}, {20258, 3962}, +{17005, 6178}, {17929, 5929}, { 9365, 3420}, { 7474, 1971}, {19537, 5177}, +{19003, 3006}, {16454, 3788}, {16070, 2367}, { 8664, 2743}, { 9445,26358}, +{10856, 1287}, { 3555, 1009}, { 5606, 3622}, {19453, 5512}, {12453, 797}, +{20634, 911}, {15427, 3066}, {17037,10275}, {18883, 2633}, { 3913, 1268}, +{19519, 3371}, {18052, 5230}, {19291, 1678}, {19508, 3172}, {18072,10754}, +{16625, 6845}, { 3134, 2298}, {10869, 2437}, {15580, 6913}, {12597, 3381}, +{11116, 3297}, {16762, 2424}, {18853, 6715}, {17171, 9887}, {12743, 2605}, +{ 8937, 3140}, {19033, 7764}, {18347, 3880}, {20475, 3682}, {19602, 3380}, +{13044,19373}, {10526,23124} +}; + +/** gain table for 6.70, 7.40 and 10.2 kbps modes + * + * second index is {pitch_gain, fixed_gain_factor} */ +static const uint16_t gains_high[128][2] = { +{ 577, 662}, { 806, 1836}, { 3109, 1052}, { 4181, 1387}, { 2373, 1425}, +{ 3248, 1985}, { 1827, 2320}, { 941, 3314}, { 2351, 2977}, { 3616, 2420}, +{ 3451, 3096}, { 2955, 4301}, { 1848, 4500}, { 3884, 5416}, { 1187, 7210}, +{ 3083, 9000}, { 7384, 883}, { 5962, 1506}, { 5155, 2134}, { 7944, 2009}, +{ 6507, 2250}, { 7670, 2752}, { 5952, 3016}, { 4898, 3764}, { 6989, 3588}, +{ 8174, 3978}, { 6064, 4404}, { 7709, 5087}, { 5523, 6021}, { 7769, 7126}, +{ 6060, 7938}, { 5594,11487}, {10581, 1356}, { 9049, 1597}, { 9794, 2035}, +{ 8946, 2415}, {10296, 2584}, { 9407, 2734}, { 8700, 3218}, { 9757, 3395}, +{10177, 3892}, { 9170, 4528}, {10152, 5004}, { 9114, 5735}, {10500, 6266}, +{10110, 7631}, { 8844, 8727}, { 8956,12496}, {12924, 976}, {11435, 1755}, +{12138, 2328}, {11388, 2368}, {10700, 3064}, {12332, 2861}, {11722, 3327}, +{11270, 3700}, {10861, 4413}, {12082, 4533}, {11283, 5205}, {11960, 6305}, +{11167, 7534}, {12128, 8329}, {10969,10777}, {10300,17376}, {13899, 1681}, +{12580, 2045}, {13265, 2439}, {14033, 2989}, {13452, 3098}, {12396, 3658}, +{13510, 3780}, {12880, 4272}, {13533, 4861}, {12667, 5457}, {13854, 6106}, +{13031, 6483}, {13557, 7721}, {12957, 9311}, {13714,11551}, {12591,15206}, +{15113, 1540}, {15072, 2333}, {14527, 2511}, {14692, 3199}, {15382, 3560}, +{14133, 3960}, {15102, 4236}, {14332, 4824}, {14846, 5451}, {15306, 6083}, +{14329, 6888}, {15060, 7689}, {14406, 9426}, {15387, 9741}, {14824,14271}, +{13600,24939}, {16396, 1969}, {16817, 2832}, {15713, 2843}, {16104, 3336}, +{16384, 3963}, {16940, 4579}, {15711, 4599}, {16222, 5448}, {16832, 6382}, +{15745, 7141}, {16326, 7469}, {16611, 8624}, {17028,10418}, {15905,11817}, +{16878,14690}, {16515,20870}, {18142, 2083}, {19401, 3178}, {17508, 3426}, +{20054, 4027}, {18069, 4249}, {18952, 5066}, {17711, 5402}, {19835, 6192}, +{17950, 7014}, {21318, 7877}, {17910, 9289}, {19144, 9290}, {20517,11381}, +{18075,14485}, {19999,17882}, {18842,32764} +}; + +/** gain table for 5.15 and 5.90 kbps modes + * + * second index is {pitch_gain, fixed_gain_factor} */ +static const uint16_t gains_low[64][2] = { +{10813,28753}, {20480, 2785}, {18841, 6594}, { 6225, 7413}, {17203,10444}, +{21626, 1269}, {21135, 4423}, {11304, 1556}, {19005,12820}, {17367, 2498}, +{17858, 4833}, { 9994, 2498}, {17530, 7864}, {14254, 1884}, {15892, 3153}, +{ 6717, 1802}, {18186,20193}, {18022, 3031}, {16711, 5857}, { 8847, 4014}, +{15892, 8970}, {18022, 1392}, {16711, 4096}, { 8192, 655}, {15237,13926}, +{14254, 3112}, {14090, 4669}, { 5406, 2703}, {13434, 6553}, {12451, 901}, +{12451, 2662}, { 3768, 655}, {14745,23511}, {19169, 2457}, {20152, 5079}, +{ 6881, 4096}, {20480, 8560}, {19660, 737}, {19005, 4259}, { 7864, 2088}, +{11468,12288}, {15892, 1474}, {15728, 4628}, { 9175, 1433}, {16056, 7004}, +{14827, 737}, {15073, 2252}, { 5079, 1228}, {13271,17326}, {16547, 2334}, +{15073, 5816}, { 3932, 3686}, {14254, 8601}, {16875, 778}, {15073, 3809}, +{ 6062, 614}, { 9338, 9256}, {13271, 1761}, {13271, 3522}, { 2457, 1966}, +{11468, 5529}, {10485, 737}, {11632, 3194}, { 1474, 778} +}; + + +// pre-processing tables + +/** impulse response filter tables converted to float from Q15 int32_t + * used for anti-sparseness processing */ +static const float ir_filter_strong_MODE_7k95[AMR_SUBFRAME_SIZE] = { + 0.817169, 0.024445, 0.076447, -0.020844, -0.042175, 0.017761, 0.018433, +-0.038879, 0.107147, -0.179871, 0.138367, -0.015228, -0.059204, 0.091888, +-0.154358, 0.171326, -0.060730, -0.032379, -0.044525, 0.135559, -0.021362, +-0.162811, 0.140656, 0.013794, -0.017975, -0.102295, 0.090118, 0.038666, +-0.036987, -0.079041, 0.052826, 0.112000, -0.136566, -0.029755, 0.134003, +-0.077423, 0.028961, -0.041595, -0.029877, 0.174988, +}; + +static const float ir_filter_strong[AMR_SUBFRAME_SIZE] = { + 0.448303, 0.351501, 0.038696, -0.084259, -0.173065, 0.229309, -0.001068, +-0.085663, -0.092773, 0.147186, 0.090088, -0.257080, 0.115509, 0.044403, + 0.066498, -0.263580, 0.245697, -0.064178, -0.044373, 0.023712, 0.033813, +-0.072784, 0.068787, -0.011078, -0.020569, -0.064178, 0.184509, -0.173370, + 0.032715, 0.095306, -0.154358, 0.162109, -0.071075, -0.113770, 0.211304, +-0.118683, 0.020599, -0.054169, 0.000885, 0.309601, +}; + +static const float ir_filter_medium[AMR_SUBFRAME_SIZE] = { + 0.923889, 0.116913, -0.123169, 0.090698, -0.031982, -0.030579, 0.075592, +-0.092865, 0.085907, -0.068085, 0.053497, -0.049164, 0.052307, -0.054169, + 0.047089, -0.030762, 0.013092, -0.005157, 0.014404, -0.038574, 0.066406, +-0.082581, 0.076996, -0.049469, 0.010498, 0.025208, -0.046661, 0.052612, +-0.050568, 0.051910, -0.062958, 0.080688, -0.093384, 0.088409, -0.060364, + 0.016998, 0.023804, -0.041779, 0.025696, 0.019989, +}; + +static const float * const ir_filters_lookup[2] = { + ir_filter_strong, ir_filter_medium +}; +static const float * const ir_filters_lookup_MODE_7k95[2] = { + ir_filter_strong_MODE_7k95, ir_filter_medium +}; + +// High-pass coefficients + +static const float highpass_zeros[2] = { -2.0, 1.0 }; +static const float highpass_poles[2] = { -1.933105469, 0.935913085 }; +static const float highpass_gain = 0.939819335; + +#endif /* AVCODEC_AMRNBDATA_H */ diff --git a/ffmpeg/libavcodec/amrnbdec.c b/ffmpeg/libavcodec/amrnbdec.c new file mode 100644 index 0000000..6376db1 --- /dev/null +++ b/ffmpeg/libavcodec/amrnbdec.c @@ -0,0 +1,1094 @@ +/* + * AMR narrowband decoder + * Copyright (c) 2006-2007 Robert Swain + * Copyright (c) 2009 Colin McQuillan + * + * 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 + */ + + +/** + * @file + * AMR narrowband decoder + * + * This decoder uses floats for simplicity and so is not bit-exact. One + * difference is that differences in phase can accumulate. The test sequences + * in 3GPP TS 26.074 can still be useful. + * + * - Comparing this file's output to the output of the ref decoder gives a + * PSNR of 30 to 80. Plotting the output samples shows a difference in + * phase in some areas. + * + * - Comparing both decoders against their input, this decoder gives a similar + * PSNR. If the test sequence homing frames are removed (this decoder does + * not detect them), the PSNR is at least as good as the reference on 140 + * out of 169 tests. + */ + + +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "libavutil/common.h" +#include "libavutil/avassert.h" +#include "celp_math.h" +#include "celp_filters.h" +#include "acelp_filters.h" +#include "acelp_vectors.h" +#include "acelp_pitch_delay.h" +#include "lsp.h" +#include "amr.h" +#include "internal.h" + +#include "amrnbdata.h" + +#define AMR_BLOCK_SIZE 160 ///< samples per frame +#define AMR_SAMPLE_BOUND 32768.0 ///< threshold for synthesis overflow + +/** + * Scale from constructed speech to [-1,1] + * + * AMR is designed to produce 16-bit PCM samples (3GPP TS 26.090 4.2) but + * upscales by two (section 6.2.2). + * + * Fundamentally, this scale is determined by energy_mean through + * the fixed vector contribution to the excitation vector. + */ +#define AMR_SAMPLE_SCALE (2.0 / 32768.0) + +/** Prediction factor for 12.2kbit/s mode */ +#define PRED_FAC_MODE_12k2 0.65 + +#define LSF_R_FAC (8000.0 / 32768.0) ///< LSF residual tables to Hertz +#define MIN_LSF_SPACING (50.0488 / 8000.0) ///< Ensures stability of LPC filter +#define PITCH_LAG_MIN_MODE_12k2 18 ///< Lower bound on decoded lag search in 12.2kbit/s mode + +/** Initial energy in dB. Also used for bad frames (unimplemented). */ +#define MIN_ENERGY -14.0 + +/** Maximum sharpening factor + * + * The specification says 0.8, which should be 13107, but the reference C code + * uses 13017 instead. (Amusingly the same applies to SHARP_MAX in g729dec.c.) + */ +#define SHARP_MAX 0.79449462890625 + +/** Number of impulse response coefficients used for tilt factor */ +#define AMR_TILT_RESPONSE 22 +/** Tilt factor = 1st reflection coefficient * gamma_t */ +#define AMR_TILT_GAMMA_T 0.8 +/** Adaptive gain control factor used in post-filter */ +#define AMR_AGC_ALPHA 0.9 + +typedef struct AMRContext { + AMRNBFrame frame; ///< decoded AMR parameters (lsf coefficients, codebook indexes, etc) + uint8_t bad_frame_indicator; ///< bad frame ? 1 : 0 + enum Mode cur_frame_mode; + + int16_t prev_lsf_r[LP_FILTER_ORDER]; ///< residual LSF vector from previous subframe + double lsp[4][LP_FILTER_ORDER]; ///< lsp vectors from current frame + double prev_lsp_sub4[LP_FILTER_ORDER]; ///< lsp vector for the 4th subframe of the previous frame + + float lsf_q[4][LP_FILTER_ORDER]; ///< Interpolated LSF vector for fixed gain smoothing + float lsf_avg[LP_FILTER_ORDER]; ///< vector of averaged lsf vector + + float lpc[4][LP_FILTER_ORDER]; ///< lpc coefficient vectors for 4 subframes + + uint8_t pitch_lag_int; ///< integer part of pitch lag from current subframe + + float excitation_buf[PITCH_DELAY_MAX + LP_FILTER_ORDER + 1 + AMR_SUBFRAME_SIZE]; ///< current excitation and all necessary excitation history + float *excitation; ///< pointer to the current excitation vector in excitation_buf + + float pitch_vector[AMR_SUBFRAME_SIZE]; ///< adaptive code book (pitch) vector + float fixed_vector[AMR_SUBFRAME_SIZE]; ///< algebraic codebook (fixed) vector (must be kept zero between frames) + + float prediction_error[4]; ///< quantified prediction errors {20log10(^gamma_gc)} for previous four subframes + float pitch_gain[5]; ///< quantified pitch gains for the current and previous four subframes + float fixed_gain[5]; ///< quantified fixed gains for the current and previous four subframes + + float beta; ///< previous pitch_gain, bounded by [0.0,SHARP_MAX] + uint8_t diff_count; ///< the number of subframes for which diff has been above 0.65 + uint8_t hang_count; ///< the number of subframes since a hangover period started + + float prev_sparse_fixed_gain; ///< previous fixed gain; used by anti-sparseness processing to determine "onset" + uint8_t prev_ir_filter_nr; ///< previous impulse response filter "impNr": 0 - strong, 1 - medium, 2 - none + uint8_t ir_filter_onset; ///< flag for impulse response filter strength + + float postfilter_mem[10]; ///< previous intermediate values in the formant filter + float tilt_mem; ///< previous input to tilt compensation filter + float postfilter_agc; ///< previous factor used for adaptive gain control + float high_pass_mem[2]; ///< previous intermediate values in the high-pass filter + + float samples_in[LP_FILTER_ORDER + AMR_SUBFRAME_SIZE]; ///< floating point samples + + ACELPFContext acelpf_ctx; ///< context for filters for ACELP-based codecs + ACELPVContext acelpv_ctx; ///< context for vector operations for ACELP-based codecs + CELPFContext celpf_ctx; ///< context for filters for CELP-based codecs + CELPMContext celpm_ctx; ///< context for fixed point math operations + +} AMRContext; + +/** Double version of ff_weighted_vector_sumf() */ +static void weighted_vector_sumd(double *out, const double *in_a, + const double *in_b, double weight_coeff_a, + double weight_coeff_b, int length) +{ + int i; + + for (i = 0; i < length; i++) + out[i] = weight_coeff_a * in_a[i] + + weight_coeff_b * in_b[i]; +} + +static av_cold int amrnb_decode_init(AVCodecContext *avctx) +{ + AMRContext *p = avctx->priv_data; + int i; + + if (avctx->channels > 1) { + avpriv_report_missing_feature(avctx, "multi-channel AMR"); + return AVERROR_PATCHWELCOME; + } + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->sample_rate) + avctx->sample_rate = 8000; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + // p->excitation always points to the same position in p->excitation_buf + p->excitation = &p->excitation_buf[PITCH_DELAY_MAX + LP_FILTER_ORDER + 1]; + + for (i = 0; i < LP_FILTER_ORDER; i++) { + p->prev_lsp_sub4[i] = lsp_sub4_init[i] * 1000 / (float)(1 << 15); + p->lsf_avg[i] = p->lsf_q[3][i] = lsp_avg_init[i] / (float)(1 << 15); + } + + for (i = 0; i < 4; i++) + p->prediction_error[i] = MIN_ENERGY; + + ff_acelp_filter_init(&p->acelpf_ctx); + ff_acelp_vectors_init(&p->acelpv_ctx); + ff_celp_filter_init(&p->celpf_ctx); + ff_celp_math_init(&p->celpm_ctx); + + return 0; +} + + +/** + * Unpack an RFC4867 speech frame into the AMR frame mode and parameters. + * + * The order of speech bits is specified by 3GPP TS 26.101. + * + * @param p the context + * @param buf pointer to the input buffer + * @param buf_size size of the input buffer + * + * @return the frame mode + */ +static enum Mode unpack_bitstream(AMRContext *p, const uint8_t *buf, + int buf_size) +{ + enum Mode mode; + + // Decode the first octet. + mode = buf[0] >> 3 & 0x0F; // frame type + p->bad_frame_indicator = (buf[0] & 0x4) != 0x4; // quality bit + + if (mode >= N_MODES || buf_size < frame_sizes_nb[mode] + 1) { + return NO_DATA; + } + + if (mode < MODE_DTX) + ff_amr_bit_reorder((uint16_t *) &p->frame, sizeof(AMRNBFrame), buf + 1, + amr_unpacking_bitmaps_per_mode[mode]); + + return mode; +} + + +/// @name AMR pitch LPC coefficient decoding functions +/// @{ + +/** + * Interpolate the LSF vector (used for fixed gain smoothing). + * The interpolation is done over all four subframes even in MODE_12k2. + * + * @param[in] ctx The Context + * @param[in,out] lsf_q LSFs in [0,1] for each subframe + * @param[in] lsf_new New LSFs in [0,1] for subframe 4 + */ +static void interpolate_lsf(ACELPVContext *ctx, float lsf_q[4][LP_FILTER_ORDER], float *lsf_new) +{ + int i; + + for (i = 0; i < 4; i++) + ctx->weighted_vector_sumf(lsf_q[i], lsf_q[3], lsf_new, + 0.25 * (3 - i), 0.25 * (i + 1), + LP_FILTER_ORDER); +} + +/** + * Decode a set of 5 split-matrix quantized lsf indexes into an lsp vector. + * + * @param p the context + * @param lsp output LSP vector + * @param lsf_no_r LSF vector without the residual vector added + * @param lsf_quantizer pointers to LSF dictionary tables + * @param quantizer_offset offset in tables + * @param sign for the 3 dictionary table + * @param update store data for computing the next frame's LSFs + */ +static void lsf2lsp_for_mode12k2(AMRContext *p, double lsp[LP_FILTER_ORDER], + const float lsf_no_r[LP_FILTER_ORDER], + const int16_t *lsf_quantizer[5], + const int quantizer_offset, + const int sign, const int update) +{ + int16_t lsf_r[LP_FILTER_ORDER]; // residual LSF vector + float lsf_q[LP_FILTER_ORDER]; // quantified LSF vector + int i; + + for (i = 0; i < LP_FILTER_ORDER >> 1; i++) + memcpy(&lsf_r[i << 1], &lsf_quantizer[i][quantizer_offset], + 2 * sizeof(*lsf_r)); + + if (sign) { + lsf_r[4] *= -1; + lsf_r[5] *= -1; + } + + if (update) + memcpy(p->prev_lsf_r, lsf_r, LP_FILTER_ORDER * sizeof(*lsf_r)); + + for (i = 0; i < LP_FILTER_ORDER; i++) + lsf_q[i] = lsf_r[i] * (LSF_R_FAC / 8000.0) + lsf_no_r[i] * (1.0 / 8000.0); + + ff_set_min_dist_lsf(lsf_q, MIN_LSF_SPACING, LP_FILTER_ORDER); + + if (update) + interpolate_lsf(&p->acelpv_ctx, p->lsf_q, lsf_q); + + ff_acelp_lsf2lspd(lsp, lsf_q, LP_FILTER_ORDER); +} + +/** + * Decode a set of 5 split-matrix quantized lsf indexes into 2 lsp vectors. + * + * @param p pointer to the AMRContext + */ +static void lsf2lsp_5(AMRContext *p) +{ + const uint16_t *lsf_param = p->frame.lsf; + float lsf_no_r[LP_FILTER_ORDER]; // LSFs without the residual vector + const int16_t *lsf_quantizer[5]; + int i; + + lsf_quantizer[0] = lsf_5_1[lsf_param[0]]; + lsf_quantizer[1] = lsf_5_2[lsf_param[1]]; + lsf_quantizer[2] = lsf_5_3[lsf_param[2] >> 1]; + lsf_quantizer[3] = lsf_5_4[lsf_param[3]]; + lsf_quantizer[4] = lsf_5_5[lsf_param[4]]; + + for (i = 0; i < LP_FILTER_ORDER; i++) + lsf_no_r[i] = p->prev_lsf_r[i] * LSF_R_FAC * PRED_FAC_MODE_12k2 + lsf_5_mean[i]; + + lsf2lsp_for_mode12k2(p, p->lsp[1], lsf_no_r, lsf_quantizer, 0, lsf_param[2] & 1, 0); + lsf2lsp_for_mode12k2(p, p->lsp[3], lsf_no_r, lsf_quantizer, 2, lsf_param[2] & 1, 1); + + // interpolate LSP vectors at subframes 1 and 3 + weighted_vector_sumd(p->lsp[0], p->prev_lsp_sub4, p->lsp[1], 0.5, 0.5, LP_FILTER_ORDER); + weighted_vector_sumd(p->lsp[2], p->lsp[1] , p->lsp[3], 0.5, 0.5, LP_FILTER_ORDER); +} + +/** + * Decode a set of 3 split-matrix quantized lsf indexes into an lsp vector. + * + * @param p pointer to the AMRContext + */ +static void lsf2lsp_3(AMRContext *p) +{ + const uint16_t *lsf_param = p->frame.lsf; + int16_t lsf_r[LP_FILTER_ORDER]; // residual LSF vector + float lsf_q[LP_FILTER_ORDER]; // quantified LSF vector + const int16_t *lsf_quantizer; + int i, j; + + lsf_quantizer = (p->cur_frame_mode == MODE_7k95 ? lsf_3_1_MODE_7k95 : lsf_3_1)[lsf_param[0]]; + memcpy(lsf_r, lsf_quantizer, 3 * sizeof(*lsf_r)); + + lsf_quantizer = lsf_3_2[lsf_param[1] << (p->cur_frame_mode <= MODE_5k15)]; + memcpy(lsf_r + 3, lsf_quantizer, 3 * sizeof(*lsf_r)); + + lsf_quantizer = (p->cur_frame_mode <= MODE_5k15 ? lsf_3_3_MODE_5k15 : lsf_3_3)[lsf_param[2]]; + memcpy(lsf_r + 6, lsf_quantizer, 4 * sizeof(*lsf_r)); + + // calculate mean-removed LSF vector and add mean + for (i = 0; i < LP_FILTER_ORDER; i++) + lsf_q[i] = (lsf_r[i] + p->prev_lsf_r[i] * pred_fac[i]) * (LSF_R_FAC / 8000.0) + lsf_3_mean[i] * (1.0 / 8000.0); + + ff_set_min_dist_lsf(lsf_q, MIN_LSF_SPACING, LP_FILTER_ORDER); + + // store data for computing the next frame's LSFs + interpolate_lsf(&p->acelpv_ctx, p->lsf_q, lsf_q); + memcpy(p->prev_lsf_r, lsf_r, LP_FILTER_ORDER * sizeof(*lsf_r)); + + ff_acelp_lsf2lspd(p->lsp[3], lsf_q, LP_FILTER_ORDER); + + // interpolate LSP vectors at subframes 1, 2 and 3 + for (i = 1; i <= 3; i++) + for(j = 0; j < LP_FILTER_ORDER; j++) + p->lsp[i-1][j] = p->prev_lsp_sub4[j] + + (p->lsp[3][j] - p->prev_lsp_sub4[j]) * 0.25 * i; +} + +/// @} + + +/// @name AMR pitch vector decoding functions +/// @{ + +/** + * Like ff_decode_pitch_lag(), but with 1/6 resolution + */ +static void decode_pitch_lag_1_6(int *lag_int, int *lag_frac, int pitch_index, + const int prev_lag_int, const int subframe) +{ + if (subframe == 0 || subframe == 2) { + if (pitch_index < 463) { + *lag_int = (pitch_index + 107) * 10923 >> 16; + *lag_frac = pitch_index - *lag_int * 6 + 105; + } else { + *lag_int = pitch_index - 368; + *lag_frac = 0; + } + } else { + *lag_int = ((pitch_index + 5) * 10923 >> 16) - 1; + *lag_frac = pitch_index - *lag_int * 6 - 3; + *lag_int += av_clip(prev_lag_int - 5, PITCH_LAG_MIN_MODE_12k2, + PITCH_DELAY_MAX - 9); + } +} + +static void decode_pitch_vector(AMRContext *p, + const AMRNBSubframe *amr_subframe, + const int subframe) +{ + int pitch_lag_int, pitch_lag_frac; + enum Mode mode = p->cur_frame_mode; + + if (p->cur_frame_mode == MODE_12k2) { + decode_pitch_lag_1_6(&pitch_lag_int, &pitch_lag_frac, + amr_subframe->p_lag, p->pitch_lag_int, + subframe); + } else + ff_decode_pitch_lag(&pitch_lag_int, &pitch_lag_frac, + amr_subframe->p_lag, + p->pitch_lag_int, subframe, + mode != MODE_4k75 && mode != MODE_5k15, + mode <= MODE_6k7 ? 4 : (mode == MODE_7k95 ? 5 : 6)); + + p->pitch_lag_int = pitch_lag_int; // store previous lag in a uint8_t + + pitch_lag_frac <<= (p->cur_frame_mode != MODE_12k2); + + pitch_lag_int += pitch_lag_frac > 0; + + /* Calculate the pitch vector by interpolating the past excitation at the + pitch lag using a b60 hamming windowed sinc function. */ + p->acelpf_ctx.acelp_interpolatef(p->excitation, + p->excitation + 1 - pitch_lag_int, + ff_b60_sinc, 6, + pitch_lag_frac + 6 - 6*(pitch_lag_frac > 0), + 10, AMR_SUBFRAME_SIZE); + + memcpy(p->pitch_vector, p->excitation, AMR_SUBFRAME_SIZE * sizeof(float)); +} + +/// @} + + +/// @name AMR algebraic code book (fixed) vector decoding functions +/// @{ + +/** + * Decode a 10-bit algebraic codebook index from a 10.2 kbit/s frame. + */ +static void decode_10bit_pulse(int code, int pulse_position[8], + int i1, int i2, int i3) +{ + // coded using 7+3 bits with the 3 LSBs being, individually, the LSB of 1 of + // the 3 pulses and the upper 7 bits being coded in base 5 + const uint8_t *positions = base_five_table[code >> 3]; + pulse_position[i1] = (positions[2] << 1) + ( code & 1); + pulse_position[i2] = (positions[1] << 1) + ((code >> 1) & 1); + pulse_position[i3] = (positions[0] << 1) + ((code >> 2) & 1); +} + +/** + * Decode the algebraic codebook index to pulse positions and signs and + * construct the algebraic codebook vector for MODE_10k2. + * + * @param fixed_index positions of the eight pulses + * @param fixed_sparse pointer to the algebraic codebook vector + */ +static void decode_8_pulses_31bits(const int16_t *fixed_index, + AMRFixed *fixed_sparse) +{ + int pulse_position[8]; + int i, temp; + + decode_10bit_pulse(fixed_index[4], pulse_position, 0, 4, 1); + decode_10bit_pulse(fixed_index[5], pulse_position, 2, 6, 5); + + // coded using 5+2 bits with the 2 LSBs being, individually, the LSB of 1 of + // the 2 pulses and the upper 5 bits being coded in base 5 + temp = ((fixed_index[6] >> 2) * 25 + 12) >> 5; + pulse_position[3] = temp % 5; + pulse_position[7] = temp / 5; + if (pulse_position[7] & 1) + pulse_position[3] = 4 - pulse_position[3]; + pulse_position[3] = (pulse_position[3] << 1) + ( fixed_index[6] & 1); + pulse_position[7] = (pulse_position[7] << 1) + ((fixed_index[6] >> 1) & 1); + + fixed_sparse->n = 8; + for (i = 0; i < 4; i++) { + const int pos1 = (pulse_position[i] << 2) + i; + const int pos2 = (pulse_position[i + 4] << 2) + i; + const float sign = fixed_index[i] ? -1.0 : 1.0; + fixed_sparse->x[i ] = pos1; + fixed_sparse->x[i + 4] = pos2; + fixed_sparse->y[i ] = sign; + fixed_sparse->y[i + 4] = pos2 < pos1 ? -sign : sign; + } +} + +/** + * Decode the algebraic codebook index to pulse positions and signs, + * then construct the algebraic codebook vector. + * + * nb of pulses | bits encoding pulses + * For MODE_4k75 or MODE_5k15, 2 | 1-3, 4-6, 7 + * MODE_5k9, 2 | 1, 2-4, 5-6, 7-9 + * MODE_6k7, 3 | 1-3, 4, 5-7, 8, 9-11 + * MODE_7k4 or MODE_7k95, 4 | 1-3, 4-6, 7-9, 10, 11-13 + * + * @param fixed_sparse pointer to the algebraic codebook vector + * @param pulses algebraic codebook indexes + * @param mode mode of the current frame + * @param subframe current subframe number + */ +static void decode_fixed_sparse(AMRFixed *fixed_sparse, const uint16_t *pulses, + const enum Mode mode, const int subframe) +{ + av_assert1(MODE_4k75 <= (signed)mode && mode <= MODE_12k2); + + if (mode == MODE_12k2) { + ff_decode_10_pulses_35bits(pulses, fixed_sparse, gray_decode, 5, 3); + } else if (mode == MODE_10k2) { + decode_8_pulses_31bits(pulses, fixed_sparse); + } else { + int *pulse_position = fixed_sparse->x; + int i, pulse_subset; + const int fixed_index = pulses[0]; + + if (mode <= MODE_5k15) { + pulse_subset = ((fixed_index >> 3) & 8) + (subframe << 1); + pulse_position[0] = ( fixed_index & 7) * 5 + track_position[pulse_subset]; + pulse_position[1] = ((fixed_index >> 3) & 7) * 5 + track_position[pulse_subset + 1]; + fixed_sparse->n = 2; + } else if (mode == MODE_5k9) { + pulse_subset = ((fixed_index & 1) << 1) + 1; + pulse_position[0] = ((fixed_index >> 1) & 7) * 5 + pulse_subset; + pulse_subset = (fixed_index >> 4) & 3; + pulse_position[1] = ((fixed_index >> 6) & 7) * 5 + pulse_subset + (pulse_subset == 3 ? 1 : 0); + fixed_sparse->n = pulse_position[0] == pulse_position[1] ? 1 : 2; + } else if (mode == MODE_6k7) { + pulse_position[0] = (fixed_index & 7) * 5; + pulse_subset = (fixed_index >> 2) & 2; + pulse_position[1] = ((fixed_index >> 4) & 7) * 5 + pulse_subset + 1; + pulse_subset = (fixed_index >> 6) & 2; + pulse_position[2] = ((fixed_index >> 8) & 7) * 5 + pulse_subset + 2; + fixed_sparse->n = 3; + } else { // mode <= MODE_7k95 + pulse_position[0] = gray_decode[ fixed_index & 7]; + pulse_position[1] = gray_decode[(fixed_index >> 3) & 7] + 1; + pulse_position[2] = gray_decode[(fixed_index >> 6) & 7] + 2; + pulse_subset = (fixed_index >> 9) & 1; + pulse_position[3] = gray_decode[(fixed_index >> 10) & 7] + pulse_subset + 3; + fixed_sparse->n = 4; + } + for (i = 0; i < fixed_sparse->n; i++) + fixed_sparse->y[i] = (pulses[1] >> i) & 1 ? 1.0 : -1.0; + } +} + +/** + * Apply pitch lag to obtain the sharpened fixed vector (section 6.1.2) + * + * @param p the context + * @param subframe unpacked amr subframe + * @param mode mode of the current frame + * @param fixed_sparse sparse respresentation of the fixed vector + */ +static void pitch_sharpening(AMRContext *p, int subframe, enum Mode mode, + AMRFixed *fixed_sparse) +{ + // The spec suggests the current pitch gain is always used, but in other + // modes the pitch and codebook gains are joinly quantized (sec 5.8.2) + // so the codebook gain cannot depend on the quantized pitch gain. + if (mode == MODE_12k2) + p->beta = FFMIN(p->pitch_gain[4], 1.0); + + fixed_sparse->pitch_lag = p->pitch_lag_int; + fixed_sparse->pitch_fac = p->beta; + + // Save pitch sharpening factor for the next subframe + // MODE_4k75 only updates on the 2nd and 4th subframes - this follows from + // the fact that the gains for two subframes are jointly quantized. + if (mode != MODE_4k75 || subframe & 1) + p->beta = av_clipf(p->pitch_gain[4], 0.0, SHARP_MAX); +} +/// @} + + +/// @name AMR gain decoding functions +/// @{ + +/** + * fixed gain smoothing + * Note that where the spec specifies the "spectrum in the q domain" + * in section 6.1.4, in fact frequencies should be used. + * + * @param p the context + * @param lsf LSFs for the current subframe, in the range [0,1] + * @param lsf_avg averaged LSFs + * @param mode mode of the current frame + * + * @return fixed gain smoothed + */ +static float fixed_gain_smooth(AMRContext *p , const float *lsf, + const float *lsf_avg, const enum Mode mode) +{ + float diff = 0.0; + int i; + + for (i = 0; i < LP_FILTER_ORDER; i++) + diff += fabs(lsf_avg[i] - lsf[i]) / lsf_avg[i]; + + // If diff is large for ten subframes, disable smoothing for a 40-subframe + // hangover period. + p->diff_count++; + if (diff <= 0.65) + p->diff_count = 0; + + if (p->diff_count > 10) { + p->hang_count = 0; + p->diff_count--; // don't let diff_count overflow + } + + if (p->hang_count < 40) { + p->hang_count++; + } else if (mode < MODE_7k4 || mode == MODE_10k2) { + const float smoothing_factor = av_clipf(4.0 * diff - 1.6, 0.0, 1.0); + const float fixed_gain_mean = (p->fixed_gain[0] + p->fixed_gain[1] + + p->fixed_gain[2] + p->fixed_gain[3] + + p->fixed_gain[4]) * 0.2; + return smoothing_factor * p->fixed_gain[4] + + (1.0 - smoothing_factor) * fixed_gain_mean; + } + return p->fixed_gain[4]; +} + +/** + * Decode pitch gain and fixed gain factor (part of section 6.1.3). + * + * @param p the context + * @param amr_subframe unpacked amr subframe + * @param mode mode of the current frame + * @param subframe current subframe number + * @param fixed_gain_factor decoded gain correction factor + */ +static void decode_gains(AMRContext *p, const AMRNBSubframe *amr_subframe, + const enum Mode mode, const int subframe, + float *fixed_gain_factor) +{ + if (mode == MODE_12k2 || mode == MODE_7k95) { + p->pitch_gain[4] = qua_gain_pit [amr_subframe->p_gain ] + * (1.0 / 16384.0); + *fixed_gain_factor = qua_gain_code[amr_subframe->fixed_gain] + * (1.0 / 2048.0); + } else { + const uint16_t *gains; + + if (mode >= MODE_6k7) { + gains = gains_high[amr_subframe->p_gain]; + } else if (mode >= MODE_5k15) { + gains = gains_low [amr_subframe->p_gain]; + } else { + // gain index is only coded in subframes 0,2 for MODE_4k75 + gains = gains_MODE_4k75[(p->frame.subframe[subframe & 2].p_gain << 1) + (subframe & 1)]; + } + + p->pitch_gain[4] = gains[0] * (1.0 / 16384.0); + *fixed_gain_factor = gains[1] * (1.0 / 4096.0); + } +} + +/// @} + + +/// @name AMR preprocessing functions +/// @{ + +/** + * Circularly convolve a sparse fixed vector with a phase dispersion impulse + * response filter (D.6.2 of G.729 and 6.1.5 of AMR). + * + * @param out vector with filter applied + * @param in source vector + * @param filter phase filter coefficients + * + * out[n] = sum(i,0,len-1){ in[i] * filter[(len + n - i)%len] } + */ +static void apply_ir_filter(float *out, const AMRFixed *in, + const float *filter) +{ + float filter1[AMR_SUBFRAME_SIZE], ///< filters at pitch lag*1 and *2 + filter2[AMR_SUBFRAME_SIZE]; + int lag = in->pitch_lag; + float fac = in->pitch_fac; + int i; + + if (lag < AMR_SUBFRAME_SIZE) { + ff_celp_circ_addf(filter1, filter, filter, lag, fac, + AMR_SUBFRAME_SIZE); + + if (lag < AMR_SUBFRAME_SIZE >> 1) + ff_celp_circ_addf(filter2, filter, filter1, lag, fac, + AMR_SUBFRAME_SIZE); + } + + memset(out, 0, sizeof(float) * AMR_SUBFRAME_SIZE); + for (i = 0; i < in->n; i++) { + int x = in->x[i]; + float y = in->y[i]; + const float *filterp; + + if (x >= AMR_SUBFRAME_SIZE - lag) { + filterp = filter; + } else if (x >= AMR_SUBFRAME_SIZE - (lag << 1)) { + filterp = filter1; + } else + filterp = filter2; + + ff_celp_circ_addf(out, out, filterp, x, y, AMR_SUBFRAME_SIZE); + } +} + +/** + * Reduce fixed vector sparseness by smoothing with one of three IR filters. + * Also know as "adaptive phase dispersion". + * + * This implements 3GPP TS 26.090 section 6.1(5). + * + * @param p the context + * @param fixed_sparse algebraic codebook vector + * @param fixed_vector unfiltered fixed vector + * @param fixed_gain smoothed gain + * @param out space for modified vector if necessary + */ +static const float *anti_sparseness(AMRContext *p, AMRFixed *fixed_sparse, + const float *fixed_vector, + float fixed_gain, float *out) +{ + int ir_filter_nr; + + if (p->pitch_gain[4] < 0.6) { + ir_filter_nr = 0; // strong filtering + } else if (p->pitch_gain[4] < 0.9) { + ir_filter_nr = 1; // medium filtering + } else + ir_filter_nr = 2; // no filtering + + // detect 'onset' + if (fixed_gain > 2.0 * p->prev_sparse_fixed_gain) { + p->ir_filter_onset = 2; + } else if (p->ir_filter_onset) + p->ir_filter_onset--; + + if (!p->ir_filter_onset) { + int i, count = 0; + + for (i = 0; i < 5; i++) + if (p->pitch_gain[i] < 0.6) + count++; + if (count > 2) + ir_filter_nr = 0; + + if (ir_filter_nr > p->prev_ir_filter_nr + 1) + ir_filter_nr--; + } else if (ir_filter_nr < 2) + ir_filter_nr++; + + // Disable filtering for very low level of fixed_gain. + // Note this step is not specified in the technical description but is in + // the reference source in the function Ph_disp. + if (fixed_gain < 5.0) + ir_filter_nr = 2; + + if (p->cur_frame_mode != MODE_7k4 && p->cur_frame_mode < MODE_10k2 + && ir_filter_nr < 2) { + apply_ir_filter(out, fixed_sparse, + (p->cur_frame_mode == MODE_7k95 ? + ir_filters_lookup_MODE_7k95 : + ir_filters_lookup)[ir_filter_nr]); + fixed_vector = out; + } + + // update ir filter strength history + p->prev_ir_filter_nr = ir_filter_nr; + p->prev_sparse_fixed_gain = fixed_gain; + + return fixed_vector; +} + +/// @} + + +/// @name AMR synthesis functions +/// @{ + +/** + * Conduct 10th order linear predictive coding synthesis. + * + * @param p pointer to the AMRContext + * @param lpc pointer to the LPC coefficients + * @param fixed_gain fixed codebook gain for synthesis + * @param fixed_vector algebraic codebook vector + * @param samples pointer to the output speech samples + * @param overflow 16-bit overflow flag + */ +static int synthesis(AMRContext *p, float *lpc, + float fixed_gain, const float *fixed_vector, + float *samples, uint8_t overflow) +{ + int i; + float excitation[AMR_SUBFRAME_SIZE]; + + // if an overflow has been detected, the pitch vector is scaled down by a + // factor of 4 + if (overflow) + for (i = 0; i < AMR_SUBFRAME_SIZE; i++) + p->pitch_vector[i] *= 0.25; + + p->acelpv_ctx.weighted_vector_sumf(excitation, p->pitch_vector, fixed_vector, + p->pitch_gain[4], fixed_gain, AMR_SUBFRAME_SIZE); + + // emphasize pitch vector contribution + if (p->pitch_gain[4] > 0.5 && !overflow) { + float energy = p->celpm_ctx.dot_productf(excitation, excitation, + AMR_SUBFRAME_SIZE); + float pitch_factor = + p->pitch_gain[4] * + (p->cur_frame_mode == MODE_12k2 ? + 0.25 * FFMIN(p->pitch_gain[4], 1.0) : + 0.5 * FFMIN(p->pitch_gain[4], SHARP_MAX)); + + for (i = 0; i < AMR_SUBFRAME_SIZE; i++) + excitation[i] += pitch_factor * p->pitch_vector[i]; + + ff_scale_vector_to_given_sum_of_squares(excitation, excitation, energy, + AMR_SUBFRAME_SIZE); + } + + p->celpf_ctx.celp_lp_synthesis_filterf(samples, lpc, excitation, + AMR_SUBFRAME_SIZE, + LP_FILTER_ORDER); + + // detect overflow + for (i = 0; i < AMR_SUBFRAME_SIZE; i++) + if (fabsf(samples[i]) > AMR_SAMPLE_BOUND) { + return 1; + } + + return 0; +} + +/// @} + + +/// @name AMR update functions +/// @{ + +/** + * Update buffers and history at the end of decoding a subframe. + * + * @param p pointer to the AMRContext + */ +static void update_state(AMRContext *p) +{ + memcpy(p->prev_lsp_sub4, p->lsp[3], LP_FILTER_ORDER * sizeof(p->lsp[3][0])); + + memmove(&p->excitation_buf[0], &p->excitation_buf[AMR_SUBFRAME_SIZE], + (PITCH_DELAY_MAX + LP_FILTER_ORDER + 1) * sizeof(float)); + + memmove(&p->pitch_gain[0], &p->pitch_gain[1], 4 * sizeof(float)); + memmove(&p->fixed_gain[0], &p->fixed_gain[1], 4 * sizeof(float)); + + memmove(&p->samples_in[0], &p->samples_in[AMR_SUBFRAME_SIZE], + LP_FILTER_ORDER * sizeof(float)); +} + +/// @} + + +/// @name AMR Postprocessing functions +/// @{ + +/** + * Get the tilt factor of a formant filter from its transfer function + * + * @param p The Context + * @param lpc_n LP_FILTER_ORDER coefficients of the numerator + * @param lpc_d LP_FILTER_ORDER coefficients of the denominator + */ +static float tilt_factor(AMRContext *p, float *lpc_n, float *lpc_d) +{ + float rh0, rh1; // autocorrelation at lag 0 and 1 + + // LP_FILTER_ORDER prior zeros are needed for ff_celp_lp_synthesis_filterf + float impulse_buffer[LP_FILTER_ORDER + AMR_TILT_RESPONSE] = { 0 }; + float *hf = impulse_buffer + LP_FILTER_ORDER; // start of impulse response + + hf[0] = 1.0; + memcpy(hf + 1, lpc_n, sizeof(float) * LP_FILTER_ORDER); + p->celpf_ctx.celp_lp_synthesis_filterf(hf, lpc_d, hf, + AMR_TILT_RESPONSE, + LP_FILTER_ORDER); + + rh0 = p->celpm_ctx.dot_productf(hf, hf, AMR_TILT_RESPONSE); + rh1 = p->celpm_ctx.dot_productf(hf, hf + 1, AMR_TILT_RESPONSE - 1); + + // The spec only specifies this check for 12.2 and 10.2 kbit/s + // modes. But in the ref source the tilt is always non-negative. + return rh1 >= 0.0 ? rh1 / rh0 * AMR_TILT_GAMMA_T : 0.0; +} + +/** + * Perform adaptive post-filtering to enhance the quality of the speech. + * See section 6.2.1. + * + * @param p pointer to the AMRContext + * @param lpc interpolated LP coefficients for this subframe + * @param buf_out output of the filter + */ +static void postfilter(AMRContext *p, float *lpc, float *buf_out) +{ + int i; + float *samples = p->samples_in + LP_FILTER_ORDER; // Start of input + + float speech_gain = p->celpm_ctx.dot_productf(samples, samples, + AMR_SUBFRAME_SIZE); + + float pole_out[AMR_SUBFRAME_SIZE + LP_FILTER_ORDER]; // Output of pole filter + const float *gamma_n, *gamma_d; // Formant filter factor table + float lpc_n[LP_FILTER_ORDER], lpc_d[LP_FILTER_ORDER]; // Transfer function coefficients + + if (p->cur_frame_mode == MODE_12k2 || p->cur_frame_mode == MODE_10k2) { + gamma_n = ff_pow_0_7; + gamma_d = ff_pow_0_75; + } else { + gamma_n = ff_pow_0_55; + gamma_d = ff_pow_0_7; + } + + for (i = 0; i < LP_FILTER_ORDER; i++) { + lpc_n[i] = lpc[i] * gamma_n[i]; + lpc_d[i] = lpc[i] * gamma_d[i]; + } + + memcpy(pole_out, p->postfilter_mem, sizeof(float) * LP_FILTER_ORDER); + p->celpf_ctx.celp_lp_synthesis_filterf(pole_out + LP_FILTER_ORDER, lpc_d, samples, + AMR_SUBFRAME_SIZE, LP_FILTER_ORDER); + memcpy(p->postfilter_mem, pole_out + AMR_SUBFRAME_SIZE, + sizeof(float) * LP_FILTER_ORDER); + + p->celpf_ctx.celp_lp_zero_synthesis_filterf(buf_out, lpc_n, + pole_out + LP_FILTER_ORDER, + AMR_SUBFRAME_SIZE, LP_FILTER_ORDER); + + ff_tilt_compensation(&p->tilt_mem, tilt_factor(p, lpc_n, lpc_d), buf_out, + AMR_SUBFRAME_SIZE); + + ff_adaptive_gain_control(buf_out, buf_out, speech_gain, AMR_SUBFRAME_SIZE, + AMR_AGC_ALPHA, &p->postfilter_agc); +} + +/// @} + +static int amrnb_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + + AMRContext *p = avctx->priv_data; // pointer to private data + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + float *buf_out; // pointer to the output data buffer + int i, subframe, ret; + float fixed_gain_factor; + AMRFixed fixed_sparse = {0}; // fixed vector up to anti-sparseness processing + float spare_vector[AMR_SUBFRAME_SIZE]; // extra stack space to hold result from anti-sparseness processing + float synth_fixed_gain; // the fixed gain that synthesis should use + const float *synth_fixed_vector; // pointer to the fixed vector that synthesis should use + + /* get output buffer */ + frame->nb_samples = AMR_BLOCK_SIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + buf_out = (float *)frame->data[0]; + + p->cur_frame_mode = unpack_bitstream(p, buf, buf_size); + if (p->cur_frame_mode == NO_DATA) { + av_log(avctx, AV_LOG_ERROR, "Corrupt bitstream\n"); + return AVERROR_INVALIDDATA; + } + if (p->cur_frame_mode == MODE_DTX) { + avpriv_report_missing_feature(avctx, "dtx mode"); + av_log(avctx, AV_LOG_INFO, "Note: libopencore_amrnb supports dtx\n"); + return AVERROR_PATCHWELCOME; + } + + if (p->cur_frame_mode == MODE_12k2) { + lsf2lsp_5(p); + } else + lsf2lsp_3(p); + + for (i = 0; i < 4; i++) + ff_acelp_lspd2lpc(p->lsp[i], p->lpc[i], 5); + + for (subframe = 0; subframe < 4; subframe++) { + const AMRNBSubframe *amr_subframe = &p->frame.subframe[subframe]; + + decode_pitch_vector(p, amr_subframe, subframe); + + decode_fixed_sparse(&fixed_sparse, amr_subframe->pulses, + p->cur_frame_mode, subframe); + + // The fixed gain (section 6.1.3) depends on the fixed vector + // (section 6.1.2), but the fixed vector calculation uses + // pitch sharpening based on the on the pitch gain (section 6.1.3). + // So the correct order is: pitch gain, pitch sharpening, fixed gain. + decode_gains(p, amr_subframe, p->cur_frame_mode, subframe, + &fixed_gain_factor); + + pitch_sharpening(p, subframe, p->cur_frame_mode, &fixed_sparse); + + if (fixed_sparse.pitch_lag == 0) { + av_log(avctx, AV_LOG_ERROR, "The file is corrupted, pitch_lag = 0 is not allowed\n"); + return AVERROR_INVALIDDATA; + } + ff_set_fixed_vector(p->fixed_vector, &fixed_sparse, 1.0, + AMR_SUBFRAME_SIZE); + + p->fixed_gain[4] = + ff_amr_set_fixed_gain(fixed_gain_factor, + p->celpm_ctx.dot_productf(p->fixed_vector, + p->fixed_vector, + AMR_SUBFRAME_SIZE) / + AMR_SUBFRAME_SIZE, + p->prediction_error, + energy_mean[p->cur_frame_mode], energy_pred_fac); + + // The excitation feedback is calculated without any processing such + // as fixed gain smoothing. This isn't mentioned in the specification. + for (i = 0; i < AMR_SUBFRAME_SIZE; i++) + p->excitation[i] *= p->pitch_gain[4]; + ff_set_fixed_vector(p->excitation, &fixed_sparse, p->fixed_gain[4], + AMR_SUBFRAME_SIZE); + + // In the ref decoder, excitation is stored with no fractional bits. + // This step prevents buzz in silent periods. The ref encoder can + // emit long sequences with pitch factor greater than one. This + // creates unwanted feedback if the excitation vector is nonzero. + // (e.g. test sequence T19_795.COD in 3GPP TS 26.074) + for (i = 0; i < AMR_SUBFRAME_SIZE; i++) + p->excitation[i] = truncf(p->excitation[i]); + + // Smooth fixed gain. + // The specification is ambiguous, but in the reference source, the + // smoothed value is NOT fed back into later fixed gain smoothing. + synth_fixed_gain = fixed_gain_smooth(p, p->lsf_q[subframe], + p->lsf_avg, p->cur_frame_mode); + + synth_fixed_vector = anti_sparseness(p, &fixed_sparse, p->fixed_vector, + synth_fixed_gain, spare_vector); + + if (synthesis(p, p->lpc[subframe], synth_fixed_gain, + synth_fixed_vector, &p->samples_in[LP_FILTER_ORDER], 0)) + // overflow detected -> rerun synthesis scaling pitch vector down + // by a factor of 4, skipping pitch vector contribution emphasis + // and adaptive gain control + synthesis(p, p->lpc[subframe], synth_fixed_gain, + synth_fixed_vector, &p->samples_in[LP_FILTER_ORDER], 1); + + postfilter(p, p->lpc[subframe], buf_out + subframe * AMR_SUBFRAME_SIZE); + + // update buffers and history + ff_clear_fixed_vector(p->fixed_vector, &fixed_sparse, AMR_SUBFRAME_SIZE); + update_state(p); + } + + p->acelpf_ctx.acelp_apply_order_2_transfer_function(buf_out, + buf_out, highpass_zeros, + highpass_poles, + highpass_gain * AMR_SAMPLE_SCALE, + p->high_pass_mem, AMR_BLOCK_SIZE); + + /* Update averaged lsf vector (used for fixed gain smoothing). + * + * Note that lsf_avg should not incorporate the current frame's LSFs + * for fixed_gain_smooth. + * The specification has an incorrect formula: the reference decoder uses + * qbar(n-1) rather than qbar(n) in section 6.1(4) equation 71. */ + p->acelpv_ctx.weighted_vector_sumf(p->lsf_avg, p->lsf_avg, p->lsf_q[3], + 0.84, 0.16, LP_FILTER_ORDER); + + *got_frame_ptr = 1; + + /* return the amount of bytes consumed if everything was OK */ + return frame_sizes_nb[p->cur_frame_mode] + 1; // +7 for rounding and +8 for TOC +} + + +AVCodec ff_amrnb_decoder = { + .name = "amrnb", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AMR_NB, + .priv_data_size = sizeof(AMRContext), + .init = amrnb_decode_init, + .decode = amrnb_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("AMR-NB (Adaptive Multi-Rate NarrowBand)"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/amrwbdata.h b/ffmpeg/libavcodec/amrwbdata.h new file mode 100644 index 0000000..8390582 --- /dev/null +++ b/ffmpeg/libavcodec/amrwbdata.h @@ -0,0 +1,1890 @@ +/* + * AMR wideband data and definitions + * Copyright (c) 2010 Marcelo Galvao Povoa + * + * 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 + */ + +/** + * @file + * AMR wideband data and definitions + */ + +#ifndef AVCODEC_AMRWBDATA_H +#define AVCODEC_AMRWBDATA_H + +#include +#include + +#define LP_ORDER 16 ///< linear predictive coding filter order +#define LP_ORDER_16k 20 ///< lpc filter order at 16kHz +#define HB_FIR_SIZE 30 ///< amount of past data needed by HB filters +#define UPS_FIR_SIZE 12 ///< upsampling filter size +#define UPS_MEM_SIZE (2 * UPS_FIR_SIZE) + +#define MIN_ISF_SPACING (128.0 / 32768.0) ///< minimum isf gap +#define PRED_FACTOR (1.0 / 3.0) +#define MIN_ENERGY -14.0 ///< initial innnovation energy (dB) +#define ENERGY_MEAN 30.0 ///< mean innovation energy (dB) in all modes +#define PREEMPH_FAC 0.68 ///< factor used to de-emphasize synthesis + +#define AMRWB_SFR_SIZE 64 ///< samples per subframe at 12.8 kHz +#define AMRWB_SFR_SIZE_16k 80 ///< samples per subframe at 16 kHz +#define AMRWB_P_DELAY_MAX 231 ///< maximum pitch delay value +#define AMRWB_P_DELAY_MIN 34 + +/* Relative mode ordering is sensitive */ +enum Mode { + MODE_6k60 = 0, ///< 6.60 kbit/s + MODE_8k85, ///< 8.85 kbit/s + MODE_12k65, ///< 12.65 kbit/s + MODE_14k25, ///< 14.25 kbit/s + MODE_15k85, ///< 15.85 kbit/s + MODE_18k25, ///< 18.25 kbit/s + MODE_19k85, ///< 19.85 kbit/s + MODE_23k05, ///< 23.05 kbit/s + MODE_23k85, ///< 23.85 kbit/s + MODE_SID, ///< comfort noise frame + /* 10-13: Future use */ + SP_LOST = 14, ///< speech lost + NO_DATA ///< no transmission +}; + +/* All decoded parameters in these structs must be 2 bytes long + * because of the direct indexing at the frame parsing */ +typedef struct AMRWBSubFrame { + uint16_t adap; ///< adaptive codebook index + uint16_t ltp; ///< ltp-filtering flag + uint16_t vq_gain; ///< VQ adaptive and innovative gains + uint16_t hb_gain; ///< high-band energy index (mode 23k85 only) + uint16_t pul_ih[4]; ///< MSBs part of codebook index (high modes only) + uint16_t pul_il[4]; ///< LSBs part of codebook index +} AMRWBSubFrame; + +typedef struct AMRWBFrame { + uint16_t vad; ///< voice activity detection flag + uint16_t isp_id[7]; ///< index of ISP subvectors + AMRWBSubFrame subframe[4]; ///< data for subframes +} AMRWBFrame; + +/** The index of a frame parameter */ +#define AMR_BIT(field) (offsetof(AMRWBFrame, field)) +/** The index of a subframe-specific parameter */ +#define AMR_OF(frame_num, variable) AMR_BIT(subframe[frame_num].variable) + +//As defined in 3GPP TS 26.201 V9.0.0 +//Tables for bit parsing in Core Frame speech frames +//The reordered bits are in order of decreasing importance and +//may be contiguously separated in Class A, B and C bits. + +// Each field in AMRWBFrame is stored as: +// * one byte for the number of bits in the field +// * one byte for the field index +// * then, one byte for each bit of the field (from most-significant to least) +// of the position of that bit in the AMR frame. +static const uint16_t order_MODE_6k60[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 24, 33, 39, 12, 6, 5, 4, 13, + 8, AMR_BIT(isp_id[1]), 65, 79, 64, 78, 51, 61, 71, 70, + 7, AMR_BIT(isp_id[2]), 52, 55, 44, 54, 53, 43, 42, + 7, AMR_BIT(isp_id[3]), 60, 59, 58, 57, 56, 75, 74, + 6, AMR_BIT(isp_id[4]), 73, 72, 86, 87, 85, 84, + 8, AMR_OF(0, adap), 11, 10, 9, 8, 28, 27, 49, 69, + 6, AMR_OF(0, pul_il[0]), 83, 91, 99, 107, 115, 123, + 6, AMR_OF(0, pul_il[1]), 82, 103, 111, 119, 127, 135, + 6, AMR_OF(0, vq_gain), 38, 23, 34, 19, 3, 15, + 5, AMR_OF(1, adap), 32, 41, 63, 67, 77, + 6, AMR_OF(1, pul_il[0]), 81, 90, 98, 106, 114, 122, + 6, AMR_OF(1, pul_il[1]), 80, 102, 110, 118, 126, 134, + 6, AMR_OF(1, vq_gain), 26, 22, 36, 18, 2, 14, + 5, AMR_OF(2, adap), 45, 40, 50, 48, 68, + 6, AMR_OF(2, pul_il[0]), 95, 89, 97, 105, 113, 121, + 6, AMR_OF(2, pul_il[1]), 94, 101, 109, 117, 125, 133, + 6, AMR_OF(2, vq_gain), 37, 21, 35, 17, 1, 31, + 5, AMR_OF(3, adap), 47, 46, 62, 66, 76, + 6, AMR_OF(3, pul_il[0]), 93, 88, 96, 104, 112, 120, + 6, AMR_OF(3, pul_il[1]), 92, 100, 108, 116, 124, 132, + 6, AMR_OF(3, vq_gain), 25, 20, 29, 16, 0, 30, + 0 +}; + +static const uint16_t order_MODE_8k85[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 47, 32, 2, 6, 3, 5, 4, 60, + 8, AMR_BIT(isp_id[1]), 69, 50, 67, 41, 51, 49, 59, 53, + 6, AMR_BIT(isp_id[2]), 40, 55, 43, 54, 42, 62, + 7, AMR_BIT(isp_id[3]), 63, 48, 52, 61, 77, 78, 72, + 7, AMR_BIT(isp_id[4]), 85, 56, 86, 68, 74, 73, 81, + 5, AMR_BIT(isp_id[5]), 82, 95, 80, 94, 91, + 5, AMR_BIT(isp_id[6]), 90, 89, 88, 103, 87, + 8, AMR_OF(0, adap), 1, 0, 15, 35, 33, 58, 64, 84, + 5, AMR_OF(0, pul_il[0]), 102, 118, 134, 150, 166, + 5, AMR_OF(0, pul_il[1]), 101, 114, 130, 146, 162, + 5, AMR_OF(0, pul_il[2]), 100, 126, 142, 158, 174, + 5, AMR_OF(0, pul_il[3]), 99, 122, 138, 154, 170, + 6, AMR_OF(0, vq_gain), 11, 39, 19, 31, 27, 23, + 5, AMR_OF(1, adap), 46, 71, 66, 76, 93, + 5, AMR_OF(1, pul_il[0]), 98, 117, 133, 149, 165, + 5, AMR_OF(1, pul_il[1]), 97, 113, 129, 145, 161, + 5, AMR_OF(1, pul_il[2]), 96, 125, 141, 157, 173, + 5, AMR_OF(1, pul_il[3]), 111, 121, 137, 153, 169, + 6, AMR_OF(1, vq_gain), 10, 38, 18, 30, 26, 22, + 8, AMR_OF(2, adap), 14, 13, 12, 34, 45, 57, 79, 83, + 5, AMR_OF(2, pul_il[0]), 110, 116, 132, 148, 164, + 5, AMR_OF(2, pul_il[1]), 109, 112, 128, 144, 160, + 5, AMR_OF(2, pul_il[2]), 108, 124, 140, 156, 172, + 5, AMR_OF(2, pul_il[3]), 107, 120, 136, 152, 168, + 6, AMR_OF(2, vq_gain), 9, 37, 17, 29, 25, 21, + 5, AMR_OF(3, adap), 44, 70, 65, 75, 92, + 5, AMR_OF(3, pul_il[0]), 106, 115, 131, 147, 163, + 5, AMR_OF(3, pul_il[1]), 105, 127, 143, 159, 175, + 5, AMR_OF(3, pul_il[2]), 104, 123, 139, 155, 171, + 5, AMR_OF(3, pul_il[3]), 119, 135, 151, 167, 183, + 6, AMR_OF(3, vq_gain), 8, 36, 16, 28, 24, 20, + 0 +}; + +static const uint16_t order_MODE_12k65[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 77, 58, 75, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 85, 86, 80, + 7, AMR_BIT(isp_id[4]), 93, 64, 94, 76, 82, 81, 89, + 5, AMR_BIT(isp_id[5]), 90, 103, 88, 102, 99, + 5, AMR_BIT(isp_id[6]), 98, 97, 96, 111, 95, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 72, + 92, + 1, AMR_OF(0, ltp), 110, + 9, AMR_OF(0, pul_il[0]), 106, 122, 154, 186, 218, 134, 166, 198, + 230, + 9, AMR_OF(0, pul_il[1]), 105, 130, 162, 194, 226, 142, 174, 206, + 238, + 9, AMR_OF(0, pul_il[2]), 104, 138, 170, 202, 234, 150, 182, 214, + 246, + 9, AMR_OF(0, pul_il[3]), 119, 146, 178, 210, 242, 158, 190, 222, + 254, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 6, AMR_OF(1, adap), 35, 54, 79, 74, 84, 101, + 1, AMR_OF(1, ltp), 109, + 9, AMR_OF(1, pul_il[0]), 118, 121, 153, 185, 217, 133, 165, 197, + 229, + 9, AMR_OF(1, pul_il[1]), 117, 129, 161, 193, 225, 141, 173, 205, + 237, + 9, AMR_OF(1, pul_il[2]), 116, 137, 169, 201, 233, 149, 181, 213, + 245, + 9, AMR_OF(1, pul_il[3]), 115, 145, 177, 209, 241, 157, 189, 221, + 253, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 87, + 91, + 1, AMR_OF(2, ltp), 108, + 9, AMR_OF(2, pul_il[0]), 114, 120, 152, 184, 216, 132, 164, 196, + 228, + 9, AMR_OF(2, pul_il[1]), 113, 128, 160, 192, 224, 140, 172, 204, + 236, + 9, AMR_OF(2, pul_il[2]), 112, 136, 168, 200, 232, 148, 180, 212, + 244, + 9, AMR_OF(2, pul_il[3]), 127, 144, 176, 208, 240, 156, 188, 220, + 252, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 6, AMR_OF(3, adap), 34, 53, 78, 73, 83, 100, + 1, AMR_OF(3, ltp), 107, + 9, AMR_OF(3, pul_il[0]), 126, 135, 167, 199, 231, 131, 163, 195, + 227, + 9, AMR_OF(3, pul_il[1]), 125, 143, 175, 207, 239, 139, 171, 203, + 235, + 9, AMR_OF(3, pul_il[2]), 124, 151, 183, 215, 247, 147, 179, 211, + 243, + 9, AMR_OF(3, pul_il[3]), 123, 159, 191, 223, 255, 155, 187, 219, + 251, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 0 +}; + +static const uint16_t order_MODE_14k25[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 77, 58, 75, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 85, 86, 80, + 7, AMR_BIT(isp_id[4]), 93, 64, 94, 76, 82, 81, 89, + 5, AMR_BIT(isp_id[5]), 90, 103, 88, 102, 99, + 5, AMR_BIT(isp_id[6]), 98, 97, 96, 111, 95, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 72, + 92, + 1, AMR_OF(0, ltp), 110, + 13, AMR_OF(0, pul_il[0]), 114, 186, 210, 234, 258, 106, 126, 162, + 170, 198, 222, 246, 270, + 13, AMR_OF(0, pul_il[1]), 122, 194, 218, 242, 266, 118, 134, 174, + 182, 206, 230, 254, 278, + 9, AMR_OF(0, pul_il[2]), 130, 138, 146, 154, 178, 202, 226, 250, + 274, + 9, AMR_OF(0, pul_il[3]), 142, 150, 158, 166, 190, 214, 238, 262, + 286, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 6, AMR_OF(1, adap), 35, 54, 79, 74, 84, 101, + 1, AMR_OF(1, ltp), 109, + 13, AMR_OF(1, pul_il[0]), 113, 185, 209, 233, 257, 105, 125, 161, + 169, 197, 221, 245, 269, + 13, AMR_OF(1, pul_il[1]), 121, 193, 217, 241, 265, 117, 133, 173, + 181, 205, 229, 253, 277, + 9, AMR_OF(1, pul_il[2]), 129, 137, 145, 153, 177, 201, 225, 249, + 273, + 9, AMR_OF(1, pul_il[3]), 141, 149, 157, 165, 189, 213, 237, 261, + 285, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 87, + 91, + 1, AMR_OF(2, ltp), 108, + 13, AMR_OF(2, pul_il[0]), 112, 184, 208, 232, 256, 104, 124, 160, + 168, 196, 220, 244, 268, + 13, AMR_OF(2, pul_il[1]), 120, 192, 216, 240, 264, 116, 132, 172, + 180, 204, 228, 252, 276, + 9, AMR_OF(2, pul_il[2]), 128, 136, 144, 152, 176, 200, 224, 248, + 272, + 9, AMR_OF(2, pul_il[3]), 140, 148, 156, 164, 188, 212, 236, 260, + 284, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 6, AMR_OF(3, adap), 34, 53, 78, 73, 83, 100, + 1, AMR_OF(3, ltp), 107, + 13, AMR_OF(3, pul_il[0]), 127, 199, 223, 247, 271, 119, 123, 175, + 183, 195, 219, 243, 267, + 13, AMR_OF(3, pul_il[1]), 135, 207, 231, 255, 279, 115, 131, 171, + 179, 203, 227, 251, 275, + 9, AMR_OF(3, pul_il[2]), 143, 151, 159, 167, 191, 215, 239, 263, + 287, + 9, AMR_OF(3, pul_il[3]), 139, 147, 155, 163, 187, 211, 235, 259, + 283, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 0 +}; + +static const uint16_t order_MODE_15k85[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 77, 58, 75, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 85, 86, 80, + 7, AMR_BIT(isp_id[4]), 93, 64, 94, 76, 82, 81, 89, + 5, AMR_BIT(isp_id[5]), 90, 103, 88, 102, 99, + 5, AMR_BIT(isp_id[6]), 98, 97, 96, 111, 95, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 72, + 92, + 1, AMR_OF(0, ltp), 110, + 13, AMR_OF(0, pul_il[0]), 122, 154, 170, 218, 266, 138, 106, 182, + 230, 278, 178, 226, 274, + 13, AMR_OF(0, pul_il[1]), 134, 166, 190, 238, 286, 150, 118, 186, + 234, 282, 198, 246, 294, + 13, AMR_OF(0, pul_il[2]), 130, 162, 194, 242, 290, 146, 114, 206, + 254, 302, 202, 250, 298, + 13, AMR_OF(0, pul_il[3]), 142, 174, 214, 262, 310, 158, 126, 210, + 258, 306, 222, 270, 318, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 6, AMR_OF(1, adap), 35, 54, 79, 74, 84, 101, + 1, AMR_OF(1, ltp), 109, + 13, AMR_OF(1, pul_il[0]), 121, 153, 169, 217, 265, 137, 105, 181, + 229, 277, 177, 225, 273, + 13, AMR_OF(1, pul_il[1]), 133, 165, 189, 237, 285, 149, 117, 185, + 233, 281, 197, 245, 293, + 13, AMR_OF(1, pul_il[2]), 129, 161, 193, 241, 289, 145, 113, 205, + 253, 301, 201, 249, 297, + 13, AMR_OF(1, pul_il[3]), 141, 173, 213, 261, 309, 157, 125, 209, + 257, 305, 221, 269, 317, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 87, + 91, + 1, AMR_OF(2, ltp), 108, + 13, AMR_OF(2, pul_il[0]), 120, 152, 168, 216, 264, 136, 104, 180, + 228, 276, 176, 224, 272, + 13, AMR_OF(2, pul_il[1]), 132, 164, 188, 236, 284, 148, 116, 184, + 232, 280, 196, 244, 292, + 13, AMR_OF(2, pul_il[2]), 128, 160, 192, 240, 288, 144, 112, 204, + 252, 300, 200, 248, 296, + 13, AMR_OF(2, pul_il[3]), 140, 172, 212, 260, 308, 156, 124, 208, + 256, 304, 220, 268, 316, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 6, AMR_OF(3, adap), 34, 53, 78, 73, 83, 100, + 1, AMR_OF(3, ltp), 107, + 13, AMR_OF(3, pul_il[0]), 135, 167, 183, 231, 279, 151, 119, 179, + 227, 275, 191, 239, 287, + 13, AMR_OF(3, pul_il[1]), 131, 163, 187, 235, 283, 147, 115, 199, + 247, 295, 195, 243, 291, + 13, AMR_OF(3, pul_il[2]), 143, 175, 207, 255, 303, 159, 127, 203, + 251, 299, 215, 263, 311, + 13, AMR_OF(3, pul_il[3]), 139, 171, 211, 259, 307, 155, 123, 223, + 271, 319, 219, 267, 315, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 0 +}; + +static const uint16_t order_MODE_18k25[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 77, 58, 75, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 85, 86, 80, + 7, AMR_BIT(isp_id[4]), 93, 64, 94, 76, 82, 81, 89, + 5, AMR_BIT(isp_id[5]), 90, 103, 88, 102, 99, + 5, AMR_BIT(isp_id[6]), 98, 97, 96, 111, 95, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 72, + 92, + 1, AMR_OF(0, ltp), 110, + 2, AMR_OF(0, pul_ih[0]), 124, 115, + 2, AMR_OF(0, pul_ih[1]), 150, 117, + 2, AMR_OF(0, pul_ih[2]), 129, 114, + 2, AMR_OF(0, pul_ih[3]), 121, 131, + 14, AMR_OF(0, pul_il[0]), 161, 257, 343, 199, 177, 303, 204, 173, + 168, 260, 277, 307, 338, 128, + 14, AMR_OF(0, pul_il[1]), 194, 286, 347, 222, 214, 316, 236, 152, + 166, 242, 284, 308, 344, 142, + 14, AMR_OF(0, pul_il[2]), 169, 273, 353, 202, 189, 311, 240, 200, + 171, 261, 309, 296, 345, 130, + 14, AMR_OF(0, pul_il[3]), 198, 275, 349, 187, 163, 282, 193, 195, + 175, 234, 265, 289, 328, 119, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 6, AMR_OF(1, adap), 35, 54, 79, 74, 84, 101, + 1, AMR_OF(1, ltp), 109, + 2, AMR_OF(1, pul_ih[0]), 139, 104, + 2, AMR_OF(1, pul_ih[1]), 135, 118, + 2, AMR_OF(1, pul_ih[2]), 112, 127, + 2, AMR_OF(1, pul_ih[3]), 140, 141, + 14, AMR_OF(1, pul_il[0]), 179, 276, 340, 225, 223, 321, 235, 190, + 182, 271, 310, 315, 352, 125, + 14, AMR_OF(1, pul_il[1]), 153, 264, 329, 232, 209, 323, 231, 165, + 191, 279, 290, 312, 367, 134, + 14, AMR_OF(1, pul_il[2]), 167, 269, 341, 205, 197, 298, 224, 160, + 170, 259, 280, 317, 357, 148, + 14, AMR_OF(1, pul_il[3]), 203, 272, 342, 227, 192, 299, 233, 172, + 183, 256, 283, 326, 355, 106, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 87, + 91, + 1, AMR_OF(2, ltp), 108, + 2, AMR_OF(2, pul_ih[0]), 144, 120, + 2, AMR_OF(2, pul_ih[1]), 157, 123, + 2, AMR_OF(2, pul_ih[2]), 145, 138, + 2, AMR_OF(2, pul_ih[3]), 132, 154, + 14, AMR_OF(2, pul_il[0]), 241, 319, 365, 252, 253, 331, 254, 230, + 220, 263, 285, 314, 364, 156, + 14, AMR_OF(2, pul_il[1]), 247, 291, 339, 249, 250, 332, 267, 196, + 207, 268, 304, 324, 356, 158, + 14, AMR_OF(2, pul_il[2]), 210, 300, 348, 243, 237, 333, 246, 206, + 219, 266, 318, 335, 363, 159, + 14, AMR_OF(2, pul_il[3]), 239, 306, 366, 221, 226, 297, 251, 184, + 178, 258, 292, 305, 346, 116, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 6, AMR_OF(3, adap), 34, 53, 78, 73, 83, 100, + 1, AMR_OF(3, ltp), 107, + 2, AMR_OF(3, pul_ih[0]), 143, 126, + 2, AMR_OF(3, pul_ih[1]), 137, 122, + 2, AMR_OF(3, pul_ih[2]), 149, 105, + 2, AMR_OF(3, pul_ih[3]), 133, 136, + 14, AMR_OF(3, pul_il[0]), 162, 287, 337, 244, 229, 322, 218, 180, + 186, 262, 274, 288, 351, 146, + 14, AMR_OF(3, pul_il[1]), 212, 294, 358, 248, 228, 334, 215, 174, + 176, 270, 293, 301, 354, 147, + 14, AMR_OF(3, pul_il[2]), 185, 327, 336, 211, 213, 313, 245, 181, + 188, 255, 281, 325, 350, 151, + 14, AMR_OF(3, pul_il[3]), 201, 295, 359, 216, 208, 320, 238, 164, + 155, 217, 278, 302, 330, 113, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 0 +}; + +static const uint16_t order_MODE_19k85[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 77, 58, 75, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 85, 86, 80, + 7, AMR_BIT(isp_id[4]), 93, 64, 94, 76, 82, 81, 89, + 5, AMR_BIT(isp_id[5]), 90, 103, 88, 102, 99, + 5, AMR_BIT(isp_id[6]), 98, 97, 96, 111, 95, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 72, + 92, + 1, AMR_OF(0, ltp), 110, + 10, AMR_OF(0, pul_ih[0]), 134, 153, 263, 342, 399, 154, 106, 177, + 317, 265, + 10, AMR_OF(0, pul_ih[1]), 128, 167, 270, 351, 385, 160, 105, 213, + 329, 259, + 2, AMR_OF(0, pul_ih[2]), 123, 147, + 2, AMR_OF(0, pul_ih[3]), 131, 143, + 10, AMR_OF(0, pul_il[0]), 346, 118, 170, 201, 296, 368, 250, 284, + 341, 391, + 10, AMR_OF(0, pul_il[1]), 345, 104, 166, 196, 281, 374, 242, 269, + 327, 390, + 14, AMR_OF(0, pul_il[2]), 141, 171, 291, 364, 229, 210, 308, 228, + 206, 200, 258, 295, 313, 361, + 14, AMR_OF(0, pul_il[3]), 144, 188, 282, 366, 217, 216, 309, 218, + 193, 182, 245, 287, 300, 367, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 6, AMR_OF(1, adap), 35, 54, 79, 74, 84, 101, + 1, AMR_OF(1, ltp), 109, + 10, AMR_OF(1, pul_ih[0]), 139, 169, 267, 348, 389, 163, 116, 189, + 343, 268, + 10, AMR_OF(1, pul_ih[1]), 120, 161, 249, 339, 397, 152, 114, 230, + 334, 303, + 2, AMR_OF(1, pul_ih[2]), 125, 138, + 2, AMR_OF(1, pul_ih[3]), 112, 129, + 10, AMR_OF(1, pul_il[0]), 349, 122, 162, 203, 288, 372, 278, 274, + 312, 377, + 10, AMR_OF(1, pul_il[1]), 357, 126, 165, 214, 298, 362, 252, 260, + 321, 378, + 14, AMR_OF(1, pul_il[2]), 150, 199, 266, 355, 211, 180, 285, 241, + 195, 198, 243, 275, 323, 375, + 14, AMR_OF(1, pul_il[3]), 142, 191, 256, 353, 208, 220, 314, 237, + 190, 212, 255, 304, 318, 371, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 87, + 91, + 1, AMR_OF(2, ltp), 108, + 10, AMR_OF(2, pul_ih[0]), 159, 168, 302, 356, 395, 178, 132, 185, + 330, 286, + 10, AMR_OF(2, pul_ih[1]), 158, 181, 292, 358, 396, 176, 133, 235, + 331, 276, + 2, AMR_OF(2, pul_ih[2]), 130, 157, + 2, AMR_OF(2, pul_ih[3]), 124, 136, + 10, AMR_OF(2, pul_il[0]), 354, 121, 194, 246, 322, 379, 272, 273, + 332, 398, + 10, AMR_OF(2, pul_il[1]), 359, 140, 186, 236, 333, 376, 290, 301, + 338, 387, + 14, AMR_OF(2, pul_il[2]), 155, 227, 319, 369, 253, 254, 350, 248, + 224, 239, 240, 293, 315, 383, + 14, AMR_OF(2, pul_il[3]), 156, 209, 297, 373, 225, 215, 326, 247, + 197, 184, 232, 289, 310, 365, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 6, AMR_OF(3, adap), 34, 53, 78, 73, 83, 100, + 1, AMR_OF(3, ltp), 107, + 10, AMR_OF(3, pul_ih[0]), 148, 164, 264, 340, 388, 183, 117, 205, + 336, 261, + 10, AMR_OF(3, pul_ih[1]), 146, 174, 257, 335, 384, 173, 113, 187, + 320, 279, + 2, AMR_OF(3, pul_ih[2]), 127, 151, + 2, AMR_OF(3, pul_ih[3]), 119, 137, + 10, AMR_OF(3, pul_il[0]), 352, 135, 172, 238, 306, 381, 262, 271, + 328, 382, + 10, AMR_OF(3, pul_il[1]), 347, 115, 179, 219, 305, 380, 277, 294, + 337, 386, + 14, AMR_OF(3, pul_il[2]), 145, 192, 307, 370, 234, 223, 324, 244, + 202, 204, 251, 299, 325, 360, + 14, AMR_OF(3, pul_il[3]), 149, 221, 311, 363, 226, 222, 316, 231, + 207, 175, 233, 280, 283, 344, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 0 +}; + +static const uint16_t order_MODE_23k05[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 77, 58, 75, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 85, 86, 80, + 7, AMR_BIT(isp_id[4]), 93, 64, 94, 76, 82, 81, 89, + 5, AMR_BIT(isp_id[5]), 90, 103, 88, 102, 99, + 5, AMR_BIT(isp_id[6]), 98, 97, 96, 111, 95, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 72, + 92, + 1, AMR_OF(0, ltp), 110, + 11, AMR_OF(0, pul_ih[0]), 118, 129, 131, 153, 170, 282, 298, 210, + 191, 357, 317, + 11, AMR_OF(0, pul_ih[1]), 126, 146, 135, 165, 187, 273, 345, 295, + 172, 338, 340, + 11, AMR_OF(0, pul_ih[2]), 119, 137, 141, 167, 208, 304, 366, 256, + 177, 339, 328, + 11, AMR_OF(0, pul_ih[3]), 116, 130, 120, 166, 190, 252, 311, 239, + 173, 343, 318, + 11, AMR_OF(0, pul_il[0]), 245, 180, 342, 424, 259, 277, 266, 380, + 398, 423, 440, + 11, AMR_OF(0, pul_il[1]), 218, 207, 367, 434, 201, 240, 275, 363, + 399, 419, 452, + 11, AMR_OF(0, pul_il[2]), 274, 188, 348, 425, 242, 204, 262, 365, + 402, 431, 463, + 11, AMR_OF(0, pul_il[3]), 221, 183, 337, 439, 243, 216, 251, 354, + 390, 411, 462, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 6, AMR_OF(1, adap), 35, 54, 79, 74, 84, 101, + 1, AMR_OF(1, ltp), 109, + 11, AMR_OF(1, pul_ih[0]), 115, 140, 142, 161, 230, 291, 351, 235, + 181, 293, 310, + 11, AMR_OF(1, pul_ih[1]), 104, 138, 132, 162, 211, 315, 347, 233, + 176, 320, 329, + 11, AMR_OF(1, pul_ih[2]), 106, 134, 125, 154, 205, 267, 306, 220, + 185, 330, 297, + 11, AMR_OF(1, pul_ih[3]), 105, 148, 122, 152, 215, 302, 350, 254, + 178, 319, 313, + 11, AMR_OF(1, pul_il[0]), 269, 189, 382, 432, 272, 228, 263, 383, + 406, 422, 453, + 11, AMR_OF(1, pul_il[1]), 286, 206, 377, 446, 226, 222, 265, 368, + 404, 416, 454, + 11, AMR_OF(1, pul_il[2]), 247, 195, 358, 445, 224, 236, 309, 341, + 375, 408, 449, + 11, AMR_OF(1, pul_il[3]), 225, 192, 359, 436, 250, 258, 290, 389, + 400, 420, 448, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 87, + 91, + 1, AMR_OF(2, ltp), 108, + 11, AMR_OF(2, pul_ih[0]), 139, 144, 145, 169, 234, 327, 395, 299, + 244, 356, 379, + 11, AMR_OF(2, pul_ih[1]), 127, 156, 158, 171, 231, 308, 397, 355, + 261, 371, 335, + 11, AMR_OF(2, pul_ih[2]), 123, 155, 157, 193, 241, 362, 384, 323, + 238, 392, 361, + 11, AMR_OF(2, pul_ih[3]), 114, 147, 121, 175, 196, 333, 373, 303, + 184, 353, 322, + 11, AMR_OF(2, pul_il[0]), 271, 203, 385, 442, 307, 276, 334, 405, + 412, 427, 459, + 11, AMR_OF(2, pul_il[1]), 278, 200, 388, 447, 292, 288, 296, 403, + 415, 429, 460, + 11, AMR_OF(2, pul_il[2]), 312, 214, 393, 433, 279, 301, 314, 391, + 410, 426, 450, + 11, AMR_OF(2, pul_il[3]), 280, 186, 376, 437, 268, 260, 255, 364, + 414, 417, 441, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 6, AMR_OF(3, adap), 34, 53, 78, 73, 83, 100, + 1, AMR_OF(3, ltp), 107, + 11, AMR_OF(3, pul_ih[0]), 112, 159, 143, 164, 213, 281, 332, 284, + 168, 344, 325, + 11, AMR_OF(3, pul_ih[1]), 113, 150, 149, 179, 199, 316, 324, 285, + 237, 360, 336, + 11, AMR_OF(3, pul_ih[2]), 124, 136, 151, 174, 209, 326, 349, 248, + 198, 374, 331, + 11, AMR_OF(3, pul_ih[3]), 117, 128, 133, 163, 202, 300, 372, 305, + 194, 387, 321, + 11, AMR_OF(3, pul_il[0]), 249, 182, 352, 428, 253, 264, 289, 413, + 407, 418, 461, + 11, AMR_OF(3, pul_il[1]), 287, 212, 369, 444, 223, 246, 217, 346, + 394, 401, 451, + 11, AMR_OF(3, pul_il[2]), 219, 197, 378, 435, 229, 257, 283, 396, + 409, 430, 455, + 11, AMR_OF(3, pul_il[3]), 232, 160, 370, 438, 227, 270, 294, 381, + 386, 421, 443, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 0 +}; + +static const uint16_t order_MODE_23k85[] = { + 1, AMR_BIT(vad), 7, + 8, AMR_BIT(isp_id[0]), 55, 40, 14, 6, 15, 5, 0, 68, + 8, AMR_BIT(isp_id[1]), 93, 58, 91, 49, 59, 57, 67, 61, + 6, AMR_BIT(isp_id[2]), 48, 63, 51, 62, 50, 70, + 7, AMR_BIT(isp_id[3]), 71, 56, 60, 69, 101, 102, 96, + 7, AMR_BIT(isp_id[4]), 109, 64, 110, 92, 98, 97, 105, + 5, AMR_BIT(isp_id[5]), 106, 119, 104, 118, 115, + 5, AMR_BIT(isp_id[6]), 114, 113, 112, 127, 111, + 9, AMR_OF(0, adap), 13, 12, 11, 10, 9, 41, 66, 88, + 108, + 1, AMR_OF(0, ltp), 126, + 11, AMR_OF(0, pul_ih[0]), 134, 145, 147, 169, 186, 298, 314, 226, + 207, 373, 333, + 11, AMR_OF(0, pul_ih[1]), 142, 162, 151, 181, 203, 289, 361, 311, + 188, 354, 356, + 11, AMR_OF(0, pul_ih[2]), 135, 153, 157, 183, 224, 320, 382, 272, + 193, 355, 344, + 11, AMR_OF(0, pul_ih[3]), 132, 146, 136, 182, 206, 268, 327, 255, + 189, 359, 334, + 11, AMR_OF(0, pul_il[0]), 261, 196, 358, 440, 275, 293, 282, 396, + 414, 439, 456, + 11, AMR_OF(0, pul_il[1]), 234, 223, 383, 450, 217, 256, 291, 379, + 415, 435, 468, + 11, AMR_OF(0, pul_il[2]), 290, 204, 364, 441, 258, 220, 278, 381, + 418, 447, 479, + 11, AMR_OF(0, pul_il[3]), 237, 199, 353, 455, 259, 232, 267, 370, + 406, 427, 478, + 7, AMR_OF(0, vq_gain), 4, 19, 45, 27, 39, 33, 31, + 4, AMR_OF(0, hb_gain), 79, 78, 77, 76, + 6, AMR_OF(1, adap), 35, 54, 95, 90, 100, 117, + 1, AMR_OF(1, ltp), 125, + 11, AMR_OF(1, pul_ih[0]), 131, 156, 158, 177, 246, 307, 367, 251, + 197, 309, 326, + 11, AMR_OF(1, pul_ih[1]), 120, 154, 148, 178, 227, 331, 363, 249, + 192, 336, 345, + 11, AMR_OF(1, pul_ih[2]), 122, 150, 141, 170, 221, 283, 322, 236, + 201, 346, 313, + 11, AMR_OF(1, pul_ih[3]), 121, 164, 138, 168, 231, 318, 366, 270, + 194, 335, 329, + 11, AMR_OF(1, pul_il[0]), 285, 205, 398, 448, 288, 244, 279, 399, + 422, 438, 469, + 11, AMR_OF(1, pul_il[1]), 302, 222, 393, 462, 242, 238, 281, 384, + 420, 432, 470, + 11, AMR_OF(1, pul_il[2]), 263, 211, 374, 461, 240, 252, 325, 357, + 391, 424, 465, + 11, AMR_OF(1, pul_il[3]), 241, 208, 375, 452, 266, 274, 306, 405, + 416, 436, 464, + 7, AMR_OF(1, vq_gain), 3, 18, 44, 26, 38, 32, 30, + 4, AMR_OF(1, hb_gain), 75, 74, 73, 72, + 9, AMR_OF(2, adap), 8, 23, 22, 21, 20, 52, 65, 103, + 107, + 1, AMR_OF(2, ltp), 124, + 11, AMR_OF(2, pul_ih[0]), 155, 160, 161, 185, 250, 343, 411, 315, + 260, 372, 395, + 11, AMR_OF(2, pul_ih[1]), 143, 172, 174, 187, 247, 324, 413, 371, + 277, 387, 351, + 11, AMR_OF(2, pul_ih[2]), 139, 171, 173, 209, 257, 378, 400, 339, + 254, 408, 377, + 11, AMR_OF(2, pul_ih[3]), 130, 163, 137, 191, 212, 349, 389, 319, + 200, 369, 338, + 11, AMR_OF(2, pul_il[0]), 287, 219, 401, 458, 323, 292, 350, 421, + 428, 443, 475, + 11, AMR_OF(2, pul_il[1]), 294, 216, 404, 463, 308, 304, 312, 419, + 431, 445, 476, + 11, AMR_OF(2, pul_il[2]), 328, 230, 409, 449, 295, 317, 330, 407, + 426, 442, 466, + 11, AMR_OF(2, pul_il[3]), 296, 202, 392, 453, 284, 276, 271, 380, + 430, 433, 457, + 7, AMR_OF(2, vq_gain), 2, 17, 43, 25, 37, 47, 29, + 4, AMR_OF(2, hb_gain), 87, 86, 85, 84, + 6, AMR_OF(3, adap), 34, 53, 94, 89, 99, 116, + 1, AMR_OF(3, ltp), 123, + 11, AMR_OF(3, pul_ih[0]), 128, 175, 159, 180, 229, 297, 348, 300, + 184, 360, 341, + 11, AMR_OF(3, pul_ih[1]), 129, 166, 165, 195, 215, 332, 340, 301, + 253, 376, 352, + 11, AMR_OF(3, pul_ih[2]), 140, 152, 167, 190, 225, 342, 365, 264, + 214, 390, 347, + 11, AMR_OF(3, pul_ih[3]), 133, 144, 149, 179, 218, 316, 388, 321, + 210, 403, 337, + 11, AMR_OF(3, pul_il[0]), 265, 198, 368, 444, 269, 280, 305, 429, + 423, 434, 477, + 11, AMR_OF(3, pul_il[1]), 303, 228, 385, 460, 239, 262, 233, 362, + 410, 417, 467, + 11, AMR_OF(3, pul_il[2]), 235, 213, 394, 451, 245, 273, 299, 412, + 425, 446, 471, + 11, AMR_OF(3, pul_il[3]), 248, 176, 386, 454, 243, 286, 310, 397, + 402, 437, 459, + 7, AMR_OF(3, vq_gain), 1, 16, 42, 24, 36, 46, 28, + 4, AMR_OF(3, hb_gain), 83, 82, 81, 80, + 0 +}; + +/** Reordering array addresses for each mode */ +static const uint16_t* amr_bit_orderings_by_mode[] = { + order_MODE_6k60, + order_MODE_8k85, + order_MODE_12k65, + order_MODE_14k25, + order_MODE_15k85, + order_MODE_18k25, + order_MODE_19k85, + order_MODE_23k05, + order_MODE_23k85 +}; + +// Extracted from 3GPP TS 26.173 V9.0.0 (qpisf_2s.tab) +// The *_36b tables are used in 6k60 mode +// Stored in fixed-point to save some space +/** Indexed tables for retrieval of quantized ISF vectors in Q15 */ +static const int16_t dico1_isf[256][9] = { + { 579, 1081, 1035, 390, 3, -263, -198, -82, 38}, + { 18, -68, -12, 313, 761, 405, 249, 111, -76}, + { 740, 1263, 1292, 1006, 997, 1019, 1017, 976, 923}, + { -91, 827, 948, 648, 613, 535, 522, 490, 421}, + { 41, -44, -281, -472, 652, 534, 193, 135, -90}, + { 41, -121, -356, -60, 663, 307, 61, -48, -344}, + { 557, 946, 1049, 867, 846, 990, 1112, 1262, 1241}, + { -118, -204, 328, 512, 870, 793, 610, 402, 186}, + { 156, 293, 74, -338, -475, -897, -594, -161, -497}, + { 226, 131, -138, 307, 169, -271, -164, -387, -624}, + { 62, -32, -61, -252, -541, -828, -1027, -523, -662}, + { 102, -61, 141, 112, -270, -251, -541, 25, -150}, + { 6, -132, -356, -686, -96, -322, -522, -31, -326}, + { -36, -209, -521, -229, 307, -132, -5, -99, -384}, + { 60, -51, -237, -668, -973, -407, -708, -75, -172}, + { 26, -138, -266, 111, -302, 43, -278, -356, -359}, + { 570, 822, 496, -154, -312, -92, 137, 279, 371}, + { -146, 368, 409, 68, 6, 77, 167, 202, 162}, + { 633, 898, 996, 756, 662, 683, 783, 909, 996}, + { -103, 294, 607, 415, 483, 462, 480, 431, 408}, + { -120, -338, -612, -524, 584, 331, 92, 433, 276}, + { -178, -293, -154, -41, 269, 100, -9, 213, 160}, + { 830, 736, 278, 820, 1254, 686, 712, 1039, 473}, + { -218, -304, 463, 454, 397, 273, 202, 286, 273}, + { -232, 7, 6, -388, -472, -427, -378, -167, -100}, + { -294, -183, 134, -47, 101, -88, -84, -117, -3}, + { 57, 17, -202, -634, -989, -1119, -533, 176, -36}, + { 120, -28, 23, 111, -319, 318, -22, -77, 266}, + { -271, -464, -434, -658, -640, -385, -385, -99, -69}, + { -198, -259, -266, -44, -39, -139, -137, 171, 66}, + { 9, -145, -377, -846, -1000, -111, -325, 342, 135}, + { -81, -286, -380, 192, -57, 307, 76, -24, -140}, + { 677, 702, 247, 56, 249, 141, -105, -236, -99}, + { 36, -39, -69, 348, 198, -93, 322, 91, -72}, + { 503, 885, 1508, 1307, 1282, 1172, 1119, 1209, 1061}, + { 416, 719, 989, 1227, 1001, 1052, 954, 741, 1044}, + { -127, -376, -657, 139, 623, 223, 501, 306, 220}, + { -113, -384, -796, 504, 438, 85, 213, -83, -194}, + { 585, 1132, 1233, 1091, 1247, 1433, 1512, 1448, 1314}, + { -174, -422, 7, 1155, 1089, 1182, 1003, 945, 806}, + { 8, -126, -317, -103, -351, -695, -98, -268, -537}, + { 33, -103, -290, 167, -39, -407, 44, -208, -375}, + { 104, -23, -64, -291, -637, -851, -1084, -61, -112}, + { -75, -306, -434, 218, -148, -354, -680, -133, -216}, + { -121, -377, -718, -97, -130, -361, -156, -379, -599}, + { -56, -254, -586, 235, 157, -214, 11, -260, -149}, + { -124, -267, -397, -580, -593, -527, -805, -385, 346}, + { -193, -440, -708, -351, -141, -255, -499, -147, -185}, + { 448, 660, 494, 208, 509, 461, 338, 291, 149}, + { -223, 88, 335, 159, 212, 191, 286, 308, 205}, + { -31, 469, 803, 659, 619, 658, 843, 987, 1113}, + { -171, -242, 514, 362, 295, 524, 552, 694, 585}, + { -64, -308, -448, -21, 284, 786, 446, 289, 92}, + { -218, -390, -7, 169, 206, 330, 352, 408, 358}, + { -36, 702, 959, 859, 861, 1115, 1269, 1357, 1305}, + { -133, -341, -65, 678, 417, 440, 486, 518, 780}, + { 33, -44, -191, -344, -461, -755, -201, 217, -31}, + { -353, -547, -44, 123, -61, -68, -79, 29, 60}, + { 73, -57, -406, -766, -1243, -1203, 240, 400, 165}, + { -73, -282, -601, -213, -171, -375, 332, 35, -103}, + { -29, -207, -553, -476, -638, -908, 172, -22, -135}, + { -192, -239, -164, -103, -111, -47, 153, 125, 110}, + { -1, -203, -570, -1030, -1424, -535, 155, 1, 147}, + { -333, -653, -865, -197, -158, -21, -44, 95, 108}, + { 389, 588, 490, 33, -237, -524, -628, -136, -260}, + { 40, -177, -462, 453, 862, 380, 131, -130, -405}, + { 842, 1678, 1841, 1549, 1474, 1256, 1082, 905, 742}, + { 370, 1216, 1768, 1633, 1212, 636, 22, -330, 71}, + { -76, -281, -741, -742, 898, 619, 277, 71, -222}, + { -32, -265, -556, -25, 994, 682, 305, 126, -165}, + { 73, 738, 893, 968, 993, 1768, 2273, 1840, 1391}, + { -69, -349, -585, 234, 1158, 903, 626, 510, 251}, + { -1, -99, -272, -210, -603, -351, -540, -811, -383}, + { -16, -230, -504, 410, 149, -205, -343, -651, -639}, + { 103, -9, -227, -205, -562, -781, -1079, -1208, -156}, + { 143, 63, -135, -67, -317, -602, -784, -1154, -640}, + { -144, -391, -674, -622, -200, -254, -660, -947, -395}, + { -40, -250, -625, 27, 543, 94, -131, -386, -673}, + { -123, -371, -757, -451, -564, -614, -415, -711, -35}, + { -116, -309, -593, -268, 239, -33, -338, -650, -135}, + { 94, 251, 554, 57, -312, -423, -154, -57, 235}, + { -268, -71, 381, 114, -44, -87, 125, 173, 133}, + { 1513, 1714, 1238, 534, 276, 315, 461, 459, 508}, + { -131, -19, 1149, 670, 486, 356, 309, 369, 296}, + { -223, -501, -899, -722, -70, 6, 131, 310, 394}, + { -99, -303, -517, 249, 64, -53, 135, -11, 453}, + { -147, -399, -730, -401, 817, 738, 802, 749, 575}, + { -154, -435, -739, 800, 593, 366, 529, 318, 326}, + { -224, 45, -39, -387, -515, -518, -608, -384, -321}, + { -315, -377, 143, -101, -113, -377, -177, -144, -12}, + { 117, 40, -239, -651, -1051, -581, -737, -990, -328}, + { 26, -50, -157, -23, -453, -283, -531, -546, 192}, + { -252, -501, -743, -589, -627, -499, -328, -118, -72}, + { -324, -494, -244, -306, -144, -177, -262, -135, -78}, + { -36, -234, -519, -961, -1290, -314, -479, -371, -45}, + { -95, -292, -535, -8, -300, 112, -164, -277, 198}, + { -99, -128, 880, 836, 579, 351, 23, -95, -217}, + { -27, -258, 124, 1011, 597, 425, 144, 7, -73}, + { 421, 1293, 1640, 1623, 1742, 1617, 1499, 1284, 1006}, + { -95, 752, 1680, 1569, 1618, 1436, 1200, 980, 712}, + { -69, -300, -683, -435, 1132, 899, 504, 332, 109}, + { -74, -323, -637, 563, 1074, 608, 371, 105, -49}, + { -78, 831, 1194, 1110, 1378, 1481, 1492, 1365, 1217}, + { -259, -121, 1440, 1334, 1628, 1490, 1438, 1223, 933}, + { -82, -306, -613, -222, -378, -675, -545, -671, -845}, + { 53, -124, -347, 422, 52, -125, -270, -529, 9}, + { 79, -89, -320, -662, -999, -1199, -1243, -676, -297}, + { -68, -273, -611, 137, -146, -397, -627, -845, -220}, + { -112, -346, -797, -826, 234, -132, -188, -278, -522}, + { -159, -405, -734, -419, 293, 74, -167, -167, 184}, + { -153, -437, -833, -1080, -336, -472, -561, -340, -253}, + { -169, -423, -820, -904, -131, -19, -346, -604, 31}, + { 33, -31, 312, 62, -148, 49, -59, 564, 486}, + { -306, -333, 194, -44, 67, 72, 147, 205, 243}, + { -207, -49, 1360, 983, 969, 991, 1014, 1110, 973}, + { -211, -172, 883, 627, 711, 674, 705, 798, 746}, + { -88, -325, -763, -974, 687, 908, 514, 382, 172}, + { -292, -612, -805, 63, 131, 270, 259, 352, 348}, + { -235, -84, 955, 818, 1120, 1289, 1559, 1480, 1285}, + { -180, -461, -614, 657, 691, 745, 854, 783, 713}, + { -97, -309, -477, -614, -777, -734, -768, -526, -472}, + { -344, -476, -35, -169, 49, -77, -150, -240, -141}, + { -52, -268, -639, -919, -1278, -1113, -342, -333, -151}, + { -68, -242, -585, -73, -209, -478, -159, -429, 133}, + { -197, -499, -1005, -1268, -272, -224, -105, -67, 17}, + { -363, -618, -414, -116, -62, 20, 10, 116, 108}, + { -195, -475, -906, -1260, -891, -441, -277, -142, -28}, + { -226, -519, -950, -700, -275, -266, -116, -105, 82}, + { 404, 511, 520, 327, 17, -194, -333, -536, -586}, + { -114, -130, 276, 237, 204, 342, 135, -16, -111}, + { 670, 1208, 1168, 860, 742, 601, 528, 403, 309}, + { 397, 621, 966, 752, 579, 398, 400, 329, 252}, + { 191, 180, -137, -467, 272, 106, -95, 17, -192}, + { -80, -290, -626, 194, 598, 196, 21, -281, 77}, + { 510, 864, 1108, 807, 939, 902, 925, 717, 481}, + { 137, 367, 534, 764, 670, 382, 296, 153, 84}, + { 303, 497, 144, -85, -125, -539, -482, -464, -764}, + { 233, 347, 68, -147, 169, -210, -242, -226, -482}, + { 307, 422, 154, -175, -386, -722, -724, -904, -1015}, + { 309, 308, 160, -60, -470, -420, -598, -791, -219}, + { 68, 121, -137, -560, -146, -446, -515, -494, -729}, + { 130, 53, -227, 46, 474, 32, -161, -192, -490}, + { 213, 164, -71, -465, -876, -161, -456, -587, -48}, + { 218, 117, 39, 177, -194, -88, -226, -418, 50}, + { 210, 547, 569, 279, 121, -44, -50, 10, -84}, + { 58, 140, 182, -5, 267, 117, 106, 211, 198}, + { 539, 835, 913, 719, 617, 544, 591, 565, 642}, + { 153, 559, 872, 460, 222, 108, 188, 180, 183}, + { 158, 119, 284, -153, -271, 229, 87, 110, -57}, + { -183, 82, 118, 21, 13, 40, 118, 191, 185}, + { 162, 889, 654, 108, -34, 244, 488, 561, 532}, + { 163, 56, 609, 341, 50, 329, 68, 266, 218}, + { 100, 206, 18, -304, -107, -436, -487, -65, -306}, + { -86, 154, 134, -30, -45, -73, -104, -80, -96}, + { 245, 330, 10, -440, -849, -1082, 79, 40, -265}, + { 196, 372, 272, -181, -493, -389, 275, 80, -59}, + { 2, -12, -246, -505, -100, -436, 21, -187, -431}, + { -221, -48, 36, -271, -186, -147, -109, 26, 71}, + { 213, 140, 72, -351, -620, -84, -363, 69, 46}, + { 91, 167, -3, -95, -99, -105, -48, 114, 147}, + { 259, 249, 172, 607, 406, 52, 59, -189, -320}, + { 115, -85, -54, 574, 128, 226, -59, -253, 130}, + { -62, 1033, 1308, 1035, 1127, 1098, 1029, 961, 823}, + { 39, 364, 757, 940, 728, 660, 659, 583, 770}, + { -115, -338, -760, -471, 394, 37, 441, 178, 6}, + { -57, -305, -525, 796, 453, 188, -4, -114, 248}, + { 71, 444, 797, 731, 1096, 1157, 1222, 1029, 811}, + { 135, 359, 551, 425, 749, 815, 874, 704, 502}, + { 132, 247, 0, -206, -449, -750, -258, -514, -633}, + { 248, 249, 91, 121, -195, -499, -90, -282, -435}, + { 78, 20, -277, -623, -983, -1224, -415, -458, -639}, + { 347, 509, 208, -179, -464, -728, -76, -237, -486}, + { -103, -343, -756, -713, -265, -609, -191, -398, -636}, + { -121, -383, -749, 567, 252, -36, -354, -417, -50}, + { 204, 100, -149, -650, -1081, -47, -7, -263, 111}, + { -46, -180, -267, -324, -562, -394, -692, 398, 292}, + { 482, 670, 683, 624, 442, 165, 116, 36, -149}, + { 108, 247, 291, 247, 355, 122, 109, 224, 296}, + { -14, 945, 990, 801, 755, 815, 847, 913, 892}, + { 292, 349, 725, 482, 388, 329, 429, 620, 667}, + { -34, 197, 213, -127, 84, 494, 620, 575, 375}, + { 126, 207, 172, 167, 362, 202, 296, 395, 455}, + { -6, 250, 539, 467, 636, 801, 1149, 1287, 1118}, + { 27, 240, 369, 280, 440, 411, 634, 892, 953}, + { 159, 170, -58, -395, -797, -690, 77, -211, -334}, + { -5, -28, -13, -74, -335, -603, 300, 88, -205}, + { 82, -33, -364, -698, -1203, -1153, 110, -146, -289}, + { 113, 1, -243, -588, -994, -496, 414, 160, 42}, + { -56, -247, -440, -693, -996, -479, 11, -178, -357}, + { -151, -353, -327, -211, -340, 141, 65, 425, 453}, + { 34, -169, -455, -932, -1215, 138, 499, 256, 324}, + { 68, 139, -15, -547, -478, 17, 306, 502, 481}, + { -32, -134, 445, 129, -143, -244, -503, -507, -599}, + { 61, -140, -345, 496, 458, -2, 20, -227, -514}, + { 394, 1765, 1666, 1339, 1117, 806, 642, 479, 380}, + { 215, 519, 920, 1053, 1090, 791, 528, 290, 155}, + { -54, -233, -647, -602, 639, 294, -2, -167, -442}, + { -78, -315, -791, -113, 820, 403, 158, -116, -356}, + { 529, 1851, 2003, 1228, 622, -41, -416, 344, 819}, + { -105, -379, -236, 1224, 893, 749, 568, 356, 214}, + { -17, -199, -144, 50, -283, -247, -578, -846, -1087}, + { 69, -11, -381, -206, 209, -284, -387, -416, -716}, + { 39, -5, -145, -374, -682, -909, -1074, -1169, -1066}, + { 287, 226, 67, -221, -662, -171, -421, -642, -707}, + { -132, -348, -538, -448, -20, -4, -354, -748, -933}, + { 4, -75, -289, -598, 317, 52, -208, -297, -559}, + { -88, -264, -358, -589, -631, -248, -523, -822, -1071}, + { 70, -8, 54, -314, -515, 92, -146, -274, -493}, + { 199, 62, 391, 158, -141, 71, -219, -203, -207}, + { 152, 40, 329, 162, -29, 48, -149, 108, 127}, + { 635, 1058, 883, 492, 372, 312, 317, 274, 241}, + { 267, 722, 1256, 882, 625, 248, 8, -81, -60}, + { -58, -138, -291, -600, -12, -2, -39, 147, 117}, + { -107, -345, -513, 459, 76, 92, -272, 388, 262}, + { 362, 516, 203, -409, -716, -831, -331, 185, 209}, + { -117, -391, -298, 671, 292, 538, 257, 166, -38}, + { -102, -319, -194, -283, -573, -262, -579, -219, -444}, + { -235, 78, 11, -168, -101, -229, -263, -321, -123}, + { 70, 50, -170, -599, -996, -588, -263, -516, -455}, + { 394, 363, 229, -136, -538, 21, -183, -348, -201}, + { -124, -368, -640, -879, -847, -209, -409, -494, -515}, + { -127, -341, -541, -425, -510, -10, -252, -473, -291}, + { 84, -69, -201, -676, -868, 103, -311, -132, -320}, + { 5, -173, -188, -297, -628, 197, -57, 7, -11}, + { 49, -160, 56, 558, 111, 33, -311, -440, -463}, + { -1, -246, -307, 862, 453, 139, -170, -355, -232}, + { 279, 966, 1642, 1478, 1463, 1123, 795, 525, 339}, + { -197, -38, 1702, 1331, 1252, 950, 692, 504, 426}, + { -108, -344, -861, -1172, 444, 354, 88, -46, -220}, + { -53, -321, -494, 1113, 744, 364, 198, -34, -75}, + { 457, 955, 1177, 1214, 1427, 1457, 1345, 917, 539}, + { -69, 199, 897, 1140, 1343, 1183, 977, 742, 522}, + { 122, 44, -269, 27, -155, -562, -307, -590, -773}, + { 154, 42, -160, 252, -129, -305, -471, -733, -371}, + { 135, 185, -82, -416, -722, -913, -504, -743, -880}, + { 149, 214, -84, -329, -680, -835, -426, -661, -81}, + { -128, -380, -735, -998, -337, 17, -182, -467, -697}, + { -84, -290, -510, -592, 13, 440, 154, -38, -279}, + { 70, -61, -246, -727, -1047, -80, -381, -535, -704}, + { 178, -2, -146, -670, -938, 482, 138, 63, 65}, + { -11, 15, 772, 443, 142, -20, -209, -126, -161}, + { -32, -249, 95, 552, 124, 30, -343, 82, -86}, + { 148, 751, 1515, 1105, 867, 606, 474, 448, 399}, + { -163, -257, 899, 1097, 906, 751, 502, 390, 294}, + { -51, -258, -447, -806, -368, 763, 464, 364, 183}, + { -166, -374, -367, 87, 35, 399, 418, 856, 833}, + { -205, -310, 588, 778, 785, 1065, 1118, 1245, 1157}, + { -173, -312, 107, 345, 400, 790, 870, 1113, 1001}, + { -7, -120, -387, -410, -614, -943, -226, -384, -491}, + { -203, -288, -51, -331, -90, -178, -408, -573, -338}, + { 56, -29, -273, -627, -1041, -798, -247, -467, 148}, + { 66, -2, -205, -205, -575, -349, -57, -352, -58}, + { -45, -225, -471, -924, -497, 77, -32, 44, -135}, + { -277, -491, -497, -502, -424, -202, -137, 77, 96}, + { 26, -179, -469, -1008, -1260, 262, -35, -132, -259}, + { -66, -232, -447, -533, -789, -191, -100, -267, 364} +}; + +static const int16_t dico2_isf[256][7] = { + { 1357, 1313, 1136, 784, 438, 181, 145}, + { 636, 648, 667, 568, 442, 217, 362}, + { 427, 440, 674, 524, 332, 117, -417}, + { 121, 295, 468, 465, 230, 44, -221}, + { -147, -240, 149, 80, 390, 278, 106}, + { -418, -556, 552, 511, 235, 144, -95}, + { 43, 193, 274, 150, 67, 34, -273}, + { -43, -126, 171, 416, 282, 63, -354}, + { -372, -86, -344, -108, -94, -182, -89}, + { -600, -840, -200, 465, 258, -11, -253}, + { -48, 329, 97, -290, -543, -795, -354}, + { -570, -117, 187, 10, -133, -416, -76}, + { -618, -129, -247, -371, 45, -76, 277}, + { -1022, -1079, 126, 474, 254, 127, 52}, + { -281, 76, -167, -361, -283, -551, -283}, + { -119, -52, -1, 134, -32, -204, -415}, + { 1064, 827, 637, 684, 464, 209, 12}, + { 482, 416, 449, 371, 335, 294, 194}, + { 719, 576, 365, 135, 113, 91, -199}, + { 298, 176, 493, 366, 194, 163, 36}, + { -35, -236, -259, -36, -4, 99, 152}, + { -98, -306, -27, 228, 90, 111, -86}, + { 91, 13, -211, -258, -106, 86, -64}, + { 73, -35, -57, -31, 162, 35, -192}, + { -109, -335, -629, -66, -61, -128, 322}, + { -495, -669, -728, 193, 31, -220, 122}, + { 324, 95, -89, -91, -409, -710, -154}, + { 0, -234, 92, 33, -343, -609, -220}, + { -343, -408, -476, -655, -153, 82, 222}, + { -490, -745, -255, 49, -48, 135, -127}, + { 119, -67, -328, -390, -272, -545, -56}, + { -57, -130, -10, -7, -164, -47, -22}, + { 984, 1064, 961, 568, 210, -27, 16}, + { 811, 691, 754, 514, 224, -35, 166}, + { 662, 704, 618, 386, 57, -211, -257}, + { 510, 359, 418, 393, 91, -144, -18}, + { -193, -31, -27, 223, 89, -143, 24}, + { -112, -98, 471, 319, 185, 3, 175}, + { 252, 146, -47, 272, 48, -211, -234}, + { 146, 69, 203, 364, 68, -52, 51}, + { -259, -478, -697, -349, -758, -501, 63}, + { -501, -769, -289, 79, -311, -497, -106}, + { 251, 53, -235, -469, -895, -884, 145}, + { -416, -551, 140, -133, -523, -775, 44}, + { -326, -423, -713, -497, -86, -431, 99}, + { -757, -772, -160, -76, -46, -32, 379}, + { 85, -35, -200, -401, -663, -1040, -247}, + { -180, -330, -92, -376, 27, -183, -110}, + { 1279, 1086, 781, 502, 324, 164, 157}, + { 682, 466, 449, 277, 146, 28, 409}, + { 635, 472, 390, 107, -232, -538, -139}, + { 196, 396, 332, 213, 209, -29, -81}, + { 150, -95, -312, 76, -77, -320, -50}, + { 46, 9, 47, 175, 139, 30, 384}, + { 218, 206, -24, -250, -96, -276, -183}, + { 26, 119, 38, 14, -4, -133, -52}, + { -477, -614, -987, -715, -631, -813, 200}, + { -744, -1009, -1065, -745, -631, -171, 18}, + { -137, -251, -483, -613, -980, -1203, 12}, + { -605, -767, -562, -686, -1088, -515, 58}, + { -202, -428, -782, -1072, -96, -234, -179}, + { -480, -709, -1070, -897, -131, -92, 321}, + { -145, -193, -512, -729, -572, -765, -210}, + { -331, -585, -525, -631, -281, -208, -303}, + { 1165, 1104, 939, 828, 716, 426, 155}, + { 6, -109, 820, 778, 415, 113, -27}, + { 381, 339, 314, 265, 121, -9, -474}, + { -373, 47, 584, 442, 99, -231, -113}, + { -496, -38, -285, 262, 305, 170, 4}, + { -587, -556, 69, 66, 471, 354, 13}, + { -138, 70, -18, 106, 67, 167, -302}, + { -445, -141, 185, 191, 151, 83, -133}, + { -257, -521, -720, -198, 134, -46, -182}, + { -819, -1168, -777, 512, 359, 95, -113}, + { 137, -2, -74, -138, -401, -114, -371}, + { -242, -466, 204, 223, -31, -212, -192}, + { -532, -637, -466, -686, 256, 277, -139}, + { -1141, -1244, -381, -75, -54, 14, 88}, + { -311, 115, -143, -499, -343, 124, -416}, + { -616, -147, -135, 43, -4, 121, -369}, + { 835, 783, 641, 390, 355, 350, 64}, + { 72, 194, 443, 467, 436, 219, 372}, + { 464, 369, 192, 4, -156, -72, -226}, + { 57, 206, 303, 205, 188, 101, 265}, + { -40, -205, -488, -184, 276, 64, -26}, + { -217, -433, -297, 137, 328, 308, -289}, + { 378, 81, -308, -465, 57, -37, 227}, + { -100, 24, -36, -151, 199, 8, 143}, + { -426, -697, -1059, -133, 388, 161, 321}, + { -644, -1023, -1271, 39, 66, -123, 70}, + { 372, 177, -173, -556, -553, -304, -189}, + { -117, -369, -425, -122, -462, -152, -73}, + { -649, -850, -1189, -767, 497, 360, 222}, + { -798, -1139, -1455, -190, 430, 234, 179}, + { 42, -94, -405, -692, 38, -202, -246}, + { -169, -366, -290, -88, -64, 32, -292}, + { 1010, 923, 938, 710, 465, 230, 342}, + { 217, 300, 1054, 675, 68, -458, -179}, + { 78, 453, 316, 18, -237, -496, -243}, + { 167, 21, 424, 215, -91, -303, -170}, + { -290, -81, -70, -67, 40, 54, -59}, + { -353, -427, -90, 53, 94, 9, 54}, + { -28, 318, 283, 15, -240, -58, 79}, + { -75, -121, 229, 35, 58, 6, -133}, + { -351, -514, -744, -834, -705, -137, 164}, + { -1124, -1388, -1055, -230, -73, 40, 36}, + { -163, -233, -532, -785, -1170, -697, 96}, + { -788, -959, -246, -430, -624, -165, -8}, + { -856, -540, -630, -907, -337, -70, 76}, + { -937, -1042, -659, -733, -208, 199, -26}, + { -523, 78, -98, -501, -869, -890, -81}, + { -624, -703, -45, -348, -25, 87, -186}, + { 1005, 823, 546, 249, 90, -22, 207}, + { 298, 397, 381, 319, 200, 62, 303}, + { 473, 379, 133, -247, -632, -441, 75}, + { 284, 208, 391, 115, -25, 44, 95}, + { -72, 79, -95, -63, -129, -293, 203}, + { -164, -349, 115, 122, 69, -1, 378}, + { 348, 170, 99, 58, -179, -302, 188}, + { -190, -2, 150, 23, -51, -11, 216}, + { -615, -863, -1090, -1427, -802, -48, -6}, + { -961, -1276, -1548, -727, -58, 56, 223}, + { -124, -255, -561, -988, -1277, -148, -82}, + { -480, -660, -891, -1191, -1339, -325, 20}, + { -621, -917, -1296, -1350, 264, 289, 50}, + { -844, -1022, -1345, -1329, -293, 46, 278}, + { -260, -468, -829, -1176, -533, -560, -78}, + { -215, -484, -822, -1233, -791, 15, -138}, + { 1301, 1317, 1262, 1048, 716, 357, -64}, + { 578, 824, 925, 802, 630, 362, 102}, + { 470, 925, 767, 514, 327, 190, -112}, + { 225, 492, 495, 437, 598, 384, -45}, + { 43, 82, -42, 175, 519, 342, -64}, + { -304, -154, 159, 576, 403, 221, 327}, + { 214, 244, 122, -62, 312, 92, -160}, + { 218, 208, 310, 268, 306, 323, -199}, + { -285, -269, -79, -124, -143, -153, 236}, + { -205, -384, -426, 344, 59, -185, -184}, + { -272, 247, 126, -210, -518, -468, 78}, + { -99, -120, 502, 160, -280, -557, 304}, + { -423, -17, -283, -443, 215, 212, -140}, + { -564, -684, -228, 510, 361, 130, 323}, + { -428, 335, 98, -65, 36, -215, -246}, + { -362, 51, 364, -16, -234, 150, -165}, + { 914, 883, 751, 653, 676, 464, -153}, + { 631, 545, 535, 720, 596, 360, -81}, + { 783, 712, 512, 439, 341, 251, -391}, + { 497, 417, 249, 372, 295, 173, -193}, + { 128, -110, -385, 93, 39, 173, -231}, + { 216, -59, -253, 462, 389, 154, 69}, + { 455, 270, -4, -337, -49, 233, -322}, + { 307, 143, 53, 218, 128, 236, -156}, + { -37, -186, -240, -411, -110, 9, 399}, + { -140, -365, -628, 258, 380, 214, 277}, + { 131, 454, 177, -285, -520, 108, -214}, + { 77, -141, 201, -123, -490, -131, 60}, + { -14, -194, -521, -741, 273, 362, -33}, + { -362, -566, -287, -228, 161, 237, 317}, + { -269, 195, -75, -375, -204, 11, 77}, + { -128, -264, -156, -223, -475, 265, 27}, + { 1238, 1147, 916, 689, 432, 210, -280}, + { 800, 664, 879, 726, 411, 160, -164}, + { 454, 686, 536, 275, 147, 46, 111}, + { 303, 486, 512, 355, 241, 181, -69}, + { 79, 92, 29, 147, 233, 52, 17}, + { -171, 289, 131, 439, 271, 3, -10}, + { 413, 241, 144, 174, 155, -2, 14}, + { 58, 217, 247, 219, 149, 175, -18}, + { 228, -8, -240, -206, -513, -191, 202}, + { -96, -272, -454, 33, -300, -575, 46}, + { -10, -108, -246, -347, -770, -535, 9}, + { -326, -430, -61, -321, -704, -299, 201}, + { -1, -280, -603, -419, -185, 18, -36}, + { -516, -522, -379, -291, -181, -97, 27}, + { -159, -313, -525, -224, -510, -831, -197}, + { -292, -459, -59, -310, -562, -143, -351}, + { 1066, 912, 631, 389, 207, 86, -224}, + { 596, 512, 596, 505, 314, 122, -48}, + { 787, 861, 441, -93, -303, 33, -190}, + { 257, 469, 337, 51, 15, 298, -93}, + { 295, 73, -119, 25, 36, 23, 108}, + { -28, -3, -32, 114, 21, 185, 107}, + { 482, 305, 15, -279, -319, 52, 96}, + { 226, 46, 115, 72, -136, 133, -125}, + { 18, -207, -559, -590, -503, -482, 321}, + { -571, -789, -951, -172, -441, -538, 113}, + { 181, 14, -310, -641, -1001, -202, 159}, + { -136, -393, -433, -513, -911, -144, -22}, + { 72, -265, -706, -954, -159, 53, 332}, + { -338, -591, -852, -383, -395, 56, 44}, + { 43, -158, -464, -897, -631, -157, -294}, + { -161, -128, -328, -573, -483, -125, 11}, + { 1017, 906, 1051, 1005, 679, 341, -102}, + { 359, 334, 1567, 1314, 723, 105, 10}, + { -65, 726, 529, 301, 220, 43, -273}, + { -510, 436, 719, 566, 358, 179, 114}, + { -560, 298, 133, -120, 342, 225, 14}, + { -899, -101, 217, 617, 400, 146, -58}, + { -41, 352, 82, -196, 39, 121, -167}, + { -212, 59, 447, 284, 423, 250, -169}, + { -371, -484, -596, 30, -41, 249, 22}, + { -372, -650, -794, 477, 445, 216, -79}, + { -352, 275, 17, -443, -929, 92, 19}, + { -699, -696, 431, 264, -49, -310, 182}, + { -978, -217, -430, -400, 101, 261, 72}, + { -929, -889, -357, -13, 463, 378, 236}, + { -826, 56, 30, -299, -360, -128, -51}, + { -878, -299, -111, 75, 65, 36, 3}, + { 817, 368, -25, 354, 697, 591, -173}, + { 309, 212, 222, 751, 484, 140, -56}, + { 593, 379, 70, -8, 258, 180, 110}, + { 165, -46, 255, 297, 219, 273, 105}, + { 160, -70, -358, -181, 379, 330, 319}, + { -238, -369, -198, 740, 580, 319, -143}, + { 201, 109, -202, -456, 328, 276, -141}, + { 203, 170, 111, 42, 207, 360, 188}, + { -345, -399, -513, -233, 650, 422, 81}, + { -635, -961, -1220, 463, 539, 204, 209}, + { 202, -25, -194, -498, -787, 193, -143}, + { -449, -538, 195, -106, -331, 68, 62}, + { -228, -477, -840, -576, 317, 128, 283}, + { -671, -937, -807, -114, 391, 335, -62}, + { 246, 2, -314, -679, -303, 180, -88}, + { -107, -272, 90, -198, -28, 290, -112}, + { 885, 1149, 1021, 712, 496, 281, -83}, + { 269, 492, 787, 643, 347, 70, 124}, + { 336, 636, 499, 92, -229, -179, 191}, + { 26, 402, 564, 340, 149, -11, 135}, + { -440, 561, 470, 204, -72, -186, 140}, + { -720, 14, 355, 229, 68, -133, 465}, + { 110, 310, 103, 12, 106, 29, 158}, + { -178, 113, 161, 142, 121, 115, 27}, + { -651, -414, -645, -152, -164, -13, -429}, + { -639, -944, -681, -104, -81, 52, -189}, + { -663, -164, -316, -683, -954, -205, -83}, + { -609, -669, -172, -517, -694, 283, -80}, + { -646, -152, -383, -678, -246, -40, -143}, + { -747, -796, -745, -390, -98, 43, 275}, + { -599, -199, -398, -433, -436, -538, 31}, + { -1107, -568, -376, -265, -126, -21, 1}, + { 847, 573, 308, 392, 305, 101, 55}, + { 273, 293, 201, 267, 346, 201, 123}, + { 727, 480, 226, 2, -65, -138, 164}, + { 273, 208, 173, 292, 12, 253, 174}, + { 340, 207, 180, 88, 116, 46, 475}, + { -460, -166, -30, 13, 110, 173, 396}, + { 137, 88, 43, -137, -94, 34, 284}, + { 96, -14, 226, 40, 63, 70, 130}, + { -467, -735, -1012, -1174, -307, 305, -67}, + { -612, -920, -1146, -567, -8, 92, -25}, + { -182, -271, -492, -754, -857, 287, -75}, + { -494, -787, -689, -683, -709, 137, -326}, + { -288, -550, -903, -1105, 334, 321, -62}, + { -354, -653, -834, -445, 1, 377, -152}, + { -162, -306, -608, -937, -297, 247, -192}, + { -234, -477, -244, -488, -266, 342, -332} +}; + +static const int16_t dico21_isf[64][3] = { + { 329, 409, 249}, { -33, 505, 160}, + { -29, -14, 582}, { -262, 127, 354}, + { 145, 237, 175}, { -152, 245, 122}, + { 27, 42, 340}, { -84, -93, 311}, + { 285, 222, -156}, { 47, -43, -504}, + { 234, 121, 385}, { 104, -317, 45}, + { 176, 195, 8}, { 104, -59, -94}, + { 177, 53, 192}, { -34, -127, 152}, + { 570, 277, -34}, { -67, -329, -639}, + { -157, -272, 462}, { -177, -462, 198}, + { 322, 179, 115}, { -386, 171, 19}, + { 19, -12, 195}, { -120, -252, 201}, + { 304, 36, -336}, { -128, -221, -380}, + { 171, -185, 296}, { -242, -312, 23}, + { 198, 39, 16}, { -3, -177, -111}, + { 111, -93, 76}, { -92, -223, 4}, + { 177, 406, -44}, { -168, 380, -149}, + { -4, 273, 331}, { -420, 513, 277}, + { 21, 247, 47}, { -58, 131, -2}, + { -3, 134, 180}, { -145, 40, 175}, + { 189, 74, -145}, { -27, -45, -325}, + { 370, -114, -21}, { -83, -415, -173}, + { 77, 95, -51}, { -40, -30, -67}, + { 71, 88, 86}, { -35, -98, 14}, + { 69, 197, -334}, { -196, 79, -231}, + { -348, -137, 218}, { -352, -89, -85}, + { 47, 201, -130}, { -165, 37, -15}, + { -43, 3, 86}, { -161, -108, 79}, + { 83, 21, -237}, { -81, -149, -238}, + { 150, -186, -251}, { -186, -249, -162}, + { -19, 66, -139}, { -26, -50, -181}, + { 24, 11, 0}, { -130, -105, -98} +}; + +static const int16_t dico22_isf[128][3] = { + { -127, 310, 42}, { -242, 197, 5}, + { -151, 84, -17}, { -214, 127, -149}, + { -247, -131, 159}, { -268, -267, -95}, + { -217, 1, -79}, { -271, -80, -185}, + { -45, 436, 159}, { 165, 199, 391}, + { -33, 81, 187}, { -66, -42, 355}, + { -298, -57, 343}, { -108, -537, 226}, + { -144, -23, 193}, { 176, -402, 87}, + { 53, 296, 25}, { -84, 253, -104}, + { -58, 105, -126}, { -169, 174, -314}, + { -48, 44, -294}, { -164, -417, -242}, + { -139, 3, -194}, { -155, -207, -211}, + { 119, 322, 213}, { 333, 50, 380}, + { 237, 247, -2}, { 466, -16, 201}, + { 238, -255, -107}, { 67, -440, -149}, + { 122, -88, -139}, { 88, -247, -73}, + { -41, 231, 167}, { -62, 155, 16}, + { -65, 16, 77}, { -68, -2, -63}, + { -151, -300, 160}, { -18, -333, 54}, + { -56, -94, 5}, { 2, -190, 14}, + { 92, 148, 209}, { 108, 9, 272}, + { 108, 35, 110}, { 142, -85, 145}, + { 47, -157, 279}, { 3, -320, 246}, + { 43, -72, 68}, { 86, -217, 135}, + { 36, 140, 79}, { 56, 175, -49}, + { 26, 45, 3}, { 73, 55, -101}, + { 109, -183, -242}, { -4, -283, -242}, + { 48, -68, -48}, { -6, -153, -122}, + { 161, 196, 96}, { 232, 80, 190}, + { 165, 97, 11}, { 258, -31, 71}, + { 267, -77, -91}, { 311, -209, 87}, + { 152, -14, -22}, { 150, -149, 9}, + { -324, 557, 187}, { -384, 307, 46}, + { -251, 27, 77}, { -365, 77, -52}, + { -482, -84, 160}, { -424, -515, -64}, + { -294, -120, -4}, { -476, -116, -109}, + { -97, 318, 365}, { 106, 627, 445}, + { -190, 120, 287}, { -146, 65, 619}, + { -427, 242, 363}, { -361, -371, 432}, + { -347, 102, 168}, { -629, 195, -14}, + { -65, 476, -47}, { -297, 320, -168}, + { -55, 356, -264}, { -391, 82, -286}, + { -51, -31, -556}, { -178, -399, -586}, + { -205, -49, -360}, { -343, -238, -337}, + { 220, 457, 58}, { 561, 467, 259}, + { 340, 270, -168}, { 450, 77, -280}, + { 60, 167, -413}, { 133, -252, -492}, + { 216, 157, -290}, { 282, 0, -495}, + { -226, 293, 183}, { -157, 135, 122}, + { -158, -59, 39}, { -133, -118, -97}, + { -332, -309, 113}, { -160, -425, -6}, + { -149, -211, 24}, { -80, -277, -90}, + { -11, 125, 338}, { 130, -71, 465}, + { 5, -45, 184}, { 237, -95, 253}, + { -139, -197, 297}, { -19, -300, 511}, + { -63, -152, 139}, { 250, -289, 336}, + { 124, 339, -150}, { 34, 176, -208}, + { 171, 166, -116}, { 94, 38, -229}, + { 75, -65, -339}, { -78, -205, -385}, + { 0, -30, -163}, { -56, -110, -242}, + { 321, 244, 194}, { 505, 238, -1}, + { 317, 116, 65}, { 309, 88, -74}, + { 452, -51, -50}, { 334, -217, -290}, + { 211, 41, -152}, { 238, -55, -260} +}; + +static const int16_t dico23_isf[128][3] = { + { -10, 151, 359}, { 136, 298, 223}, + { 255, -104, 290}, { 423, 6, 183}, + { -270, -269, -98}, { -52, -82, 13}, + { -82, -274, -97}, { 90, -246, -72}, + { -299, -70, 421}, { -88, 365, 430}, + { 187, -318, 381}, { 380, 37, 488}, + { -373, -316, 79}, { -308, -101, 5}, + { -135, -451, 8}, { 72, -421, -154}, + { 180, 170, -121}, { 62, 177, -40}, + { 326, 80, -105}, { 248, 263, -5}, + { -168, -181, -221}, { -2, -23, -158}, + { -14, -149, -121}, { 119, -91, -147}, + { 119, 332, -153}, { 49, 303, 34}, + { 442, -55, -69}, { 217, 454, 58}, + { -359, -187, -375}, { -42, 50, -274}, + { -8, -267, -249}, { 85, -86, -346}, + { -77, -40, 345}, { 89, 134, 219}, + { 156, -80, 160}, { 108, 40, 116}, + { -158, -206, 29}, { 5, -32, 175}, + { -65, -158, 146}, { 55, -78, 73}, + { -114, -222, 353}, { -47, 81, 211}, + { 49, -151, 268}, { 105, 4, 302}, + { -263, -132, 183}, { -151, -28, 201}, + { -177, -307, 166}, { 101, -221, 130}, + { 74, 58, -98}, { 32, 44, 13}, + { 194, 30, -142}, { 170, 96, 8}, + { -136, -119, -91}, { -65, 8, -55}, + { 3, -188, 12}, { 45, -63, -49}, + { 149, -21, -19}, { 24, 144, 95}, + { 254, -22, 60}, { 161, 196, 96}, + { -158, -61, 48}, { -70, 33, 82}, + { -23, -321, 58}, { 155, -147, 5}, + { -364, 328, 77}, { -21, 453, 173}, + { -108, 82, 630}, { 367, 263, 208}, + { -300, -62, -176}, { -205, 143, -158}, + { -169, -410, -264}, { 257, -269, -100}, + { -636, 289, -2}, { -292, 627, 173}, + { -382, -363, 387}, { 248, 524, 447}, + { -521, -111, -107}, { -395, 118, -274}, + { -343, -680, -125}, { -172, -447, -663}, + { 75, 148, -367}, { -79, 263, -94}, + { 249, 148, -286}, { 380, 271, -162}, + { -142, -4, -186}, { -57, 111, -125}, + { -35, -108, -254}, { 100, 29, -242}, + { -80, 303, -264}, { -78, 464, -57}, + { 248, -22, -494}, { 661, 662, 44}, + { -193, -40, -330}, { -178, 145, -337}, + { -90, -199, -400}, { -40, -23, -498}, + { -192, 114, 315}, { -41, 244, 190}, + { 88, -97, 485}, { 241, 80, 212}, + { -246, 40, 87}, { -156, 147, 134}, + { -2, -334, 239}, { 308, -203, 110}, + { -459, 251, 422}, { -218, 310, 228}, + { -86, -346, 654}, { 184, 175, 425}, + { -481, -63, 169}, { -349, 117, 188}, + { -125, -560, 310}, { 158, -416, 94}, + { 46, 171, -192}, { -63, 157, 14}, + { 256, -35, -271}, { 322, 123, 53}, + { -214, 4, -76}, { -156, 86, -18}, + { 128, -197, -232}, { 265, -90, -98}, + { -308, 332, -145}, { -131, 308, 58}, + { 509, 59, -339}, { 562, 196, -14}, + { -378, 100, -47}, { -234, 202, 1}, + { 104, -270, -493}, { 319, -210, -325} +}; + +static const int16_t dico24_isf[32][3] = { + { -79, -89, -4}, { -171, 77, -211}, + { 160, -193, 98}, { 120, -103, 323}, + { 32, -22, -129}, { 72, 78, -268}, + { 182, -76, -66}, { 309, 99, -145}, + { -229, -157, -84}, { -383, 98, -71}, + { -90, -352, 12}, { -284, -178, 178}, + { -65, -125, -166}, { -87, -175, -351}, + { 42, -198, -48}, { 154, -140, -243}, + { -77, 18, 108}, { -39, 355, 91}, + { 87, 8, 155}, { -4, 158, 239}, + { 128, 95, -54}, { 7, 246, -124}, + { 258, 15, 89}, { 206, 216, 98}, + { -201, 9, 18}, { -312, 233, 204}, + { -39, -174, 155}, { -144, -9, 284}, + { -57, 70, -69}, { -157, 187, 18}, + { 54, -30, 23}, { 24, 135, 55} +}; + +static const int16_t dico25_isf[32][4] = { + { 169, 142, -119, 115}, { 206, -20, 94, 226}, + { -106, 313, -21, 16}, { -62, 161, 71, 255}, + { -89, 101, -185, 125}, { 72, -30, -201, 344}, + { -258, 33, -8, 81}, { -104, -154, 72, 296}, + { 144, -68, -268, -25}, { 81, -78, -87, 106}, + { 22, 155, -186, -119}, { -46, -28, 27, 91}, + { -114, -37, -175, -33}, { -94, -222, -189, 122}, + { -132, -119, -191, -270}, { -172, -173, 18, -43}, + { 279, 135, -42, -128}, { 187, -86, 229, -138}, + { 159, 240, 140, 46}, { 69, 25, 227, 77}, + { 21, 115, 13, 8}, { 68, -248, 126, 81}, + { -150, 137, 207, -9}, { -154, -133, 289, 67}, + { 143, -37, -86, -326}, { 180, -32, 19, -23}, + { 26, 168, 116, -233}, { -32, -26, 118, -78}, + { 3, -8, -45, -115}, { 57, -215, -54, -83}, + { -209, 112, -22, -167}, { -91, -151, 168, -262} +}; + +static const int16_t dico21_isf_36b[128][5] = { + { -52, -96, 212, 315, -73}, { 82, -204, 363, 136, -197}, + { -126, -331, 183, 218, 143}, { -49, -41, 557, 230, 72}, + { 2, -73, 163, 377, 221}, { 133, 111, 278, 215, -110}, + { -102, -20, 284, 113, 273}, { 84, 319, 290, 18, 85}, + { -25, -5, 125, 132, -204}, { -38, -5, 286, -9, -356}, + { -140, -256, 92, 117, -189}, { -144, 191, 313, 51, -98}, + { 167, -10, 44, 247, 36}, { 381, 197, 238, 74, 6}, + { 38, -408, 29, -3, -85}, { 92, 266, 157, -25, -200}, + { 161, -121, 70, 84, -140}, { -16, -86, 112, -94, -189}, + { -269, -270, 351, 107, -24}, { -68, -67, 492, -103, -155}, + { -53, -131, 62, 122, 10}, { 135, 84, 283, -55, -120}, + { -12, -219, 331, -81, 167}, { 220, -136, 147, -172, -42}, + { 140, -95, -109, -88, -194}, { 0, -2, -4, -33, -381}, + { -66, -217, 152, -186, -402}, { 244, 108, 156, -140, -395}, + { 113, -136, -196, 110, -24}, { 214, 118, 11, -64, -131}, + { -110, -286, -6, -332, 16}, { 94, 97, 79, -291, -205}, + { -5, -39, -20, 252, -96}, { 76, 174, 101, 163, 61}, + { -69, -239, -55, 399, 6}, { -115, 319, 164, 275, 196}, + { -15, 36, -47, 331, 121}, { 226, 209, 271, 325, 184}, + { 13, -80, -218, 471, 353}, { 288, 378, 16, -51, 251}, + { 174, 116, 52, 149, -279}, { 235, 276, 39, 120, -48}, + { 0, -108, -108, 241, -339}, { -93, 534, 45, 33, -87}, + { 194, 149, -71, 405, -44}, { 409, 370, 81, -186, -154}, + { 25, -102, -448, 124, -173}, { 22, 408, -110, -310, -214}, + { -26, 23, -83, 114, 14}, { -110, 164, 52, 223, -82}, + { 37, -25, -263, 306, -15}, { -466, 415, 292, 165, -18}, + { 29, -19, -171, 155, 182}, { 179, 144, -27, 231, 258}, + { -103, -247, -396, 238, 113}, { 375, -154, -109, -4, 156}, + { 98, 85, -292, -5, -124}, { 116, 139, -116, -98, -294}, + { -14, -83, -278, -117, -378}, { 106, 33, -106, -344, -484}, + { 119, 17, -412, 138, 166}, { 384, 101, -204, 88, -156}, + { -121, -284, -300, -1, -166}, { 280, 33, -152, -313, -81}, + { -37, 22, 229, 153, 37}, { -60, -83, 236, -8, -41}, + { -169, -228, 126, -20, 363}, { -235, 17, 364, -156, 156}, + { -25, -30, 72, 144, 156}, { 153, -26, 256, 97, 144}, + { -21, -37, 48, -65, 250}, { 63, 77, 273, -128, 124}, + { -129, -26, 40, 9, -115}, { -6, 82, 38, -90, -182}, + { -336, -13, 28, 158, 91}, { -30, 241, 137, -170, -17}, + { 146, 14, -11, 33, 61}, { 192, 197, 54, -84, 85}, + { 23, -200, -78, -29, 140}, { 122, 237, 106, -341, 136}, + { -57, -142, -85, -16, -74}, { -59, -90, -8, -187, -20}, + { -211, -267, 216, -179, -110}, { -50, -7, 220, -267, -70}, + { -57, -42, -17, -15, 71}, { 32, 21, 63, -137, 33}, + { -137, -175, 104, -68, 97}, { -67, -43, 133, -301, 221}, + { -116, -200, -81, -92, -272}, { -64, -41, -54, -244, -220}, + { -287, -242, -50, -87, -89}, { -245, 236, 102, -166, -295}, + { 66, 24, -162, -71, 95}, { 66, 136, -90, -220, -36}, + { -98, -161, -222, -188, 29}, { -18, 18, -19, -415, 9}, + { 49, 61, 100, 39, -56}, { -111, 82, 135, -31, 52}, + { -90, -153, -93, 189, 182}, { -214, 295, 119, -74, 284}, + { 2, 137, 37, 47, 182}, { 92, 117, 184, -53, 373}, + { -21, -14, -35, 136, 391}, { 146, 129, -164, -28, 333}, + { 92, 80, -84, 100, -134}, { -8, 217, -32, 3, -47}, + { -151, 251, -215, 142, 92}, { -224, 310, -172, -275, 98}, + { 159, 155, -177, 112, 53}, { 205, 27, 8, -240, 192}, + { 169, 120, -319, -201, 106}, { 11, 36, -86, -237, 455}, + { -109, -154, -163, 174, -55}, { -38, 32, -101, -78, -59}, + { -205, -321, -97, 69, 79}, { -310, 44, 18, -185, 34}, + { -115, -20, -148, -39, 203}, { -29, 154, -30, -158, 166}, + { -45, -131, -317, -24, 363}, { -165, -205, -112, -222, 265}, + { -32, -44, -150, 54, -193}, { -6, -38, -255, -169, -115}, + { -266, 87, -189, -36, -169}, { -60, -87, -266, -436, -170}, + { -68, -81, -278, 24, 38}, { -23, -19, -155, -256, 141}, + { -61, -226, -565, -175, 71}, { 9, -29, -237, -515, 263} +}; + +static const int16_t dico22_isf_36b[128][4] = { + { -298, -6, 95, 31}, { -213, -87, -122, 261}, + { 4, -49, 208, 14}, { -129, -110, 30, 118}, + { -214, 258, 110, -235}, { -41, -18, -126, 120}, + { 103, 65, 127, -37}, { 126, -36, -24, 25}, + { -138, -67, -278, -186}, { -164, -194, -201, 78}, + { -211, -87, -51, -221}, { -174, -79, -94, -39}, + { 23, -6, -157, -240}, { 22, -110, -153, -68}, + { 148, -5, -2, -149}, { -1, -135, -39, -179}, + { 68, 360, -117, -15}, { 137, 47, -278, 146}, + { 136, 260, 135, 65}, { 61, 116, -45, 97}, + { 231, 379, 87, -120}, { 338, 177, -272, 3}, + { 266, 156, 28, -69}, { 260, 84, -85, 86}, + { -266, 154, -256, -182}, { -17, -65, -304, -6}, + { -40, 175, -151, -180}, { -27, 27, -87, -63}, + { 121, 114, -166, -469}, { 159, -66, -323, -231}, + { 214, 152, -141, -212}, { 137, 36, -184, -51}, + { -282, -237, 40, 10}, { -48, -235, -37, 251}, + { -54, -323, 136, 29}, { -88, -174, 213, 198}, + { -390, 99, -63, -375}, { 107, -169, -164, 424}, + { 69, -111, 141, -167}, { 74, -129, 65, 144}, + { -353, -207, -205, -109}, { -160, -386, -355, 98}, + { -176, -493, -20, -143}, { -252, -432, -2, 216}, + { -90, -174, -168, -411}, { 13, -284, -229, -160}, + { -87, -279, 34, -251}, { -75, -263, -58, -42}, + { 420, 53, -211, -358}, { 384, -35, -374, 396}, + { 68, -228, 323, -2}, { 167, -307, 192, 194}, + { 459, 329, -5, -332}, { 375, 79, -7, 313}, + { 282, -124, 200, -92}, { 271, -162, -70, 180}, + { -157, -298, -514, -309}, { 58, -163, -546, 18}, + { 124, -364, 167, -238}, { 83, -411, -117, 96}, + { 140, -112, -388, -624}, { 259, -133, -317, 41}, + { 163, -130, -64, -334}, { 226, -165, -124, -110}, + { -466, -61, 6, 229}, { -153, 205, -145, 242}, + { -159, 48, 195, 148}, { -58, 28, 31, 279}, + { -303, 185, 279, -4}, { -61, 197, 59, 86}, + { -114, 123, 168, -52}, { 35, 36, 100, 126}, + { -407, 102, -77, -40}, { -338, -1, -342, 156}, + { -179, 105, -34, -97}, { -185, 84, -35, 108}, + { -133, 107, -91, -357}, { -180, 54, -229, 24}, + { -44, 47, 47, -182}, { -66, 13, 45, 4}, + { -339, 251, 64, 226}, { -42, 101, -350, 275}, + { -99, 398, 142, 121}, { 111, 12, -102, 260}, + { 0, 505, 260, -94}, { 161, 285, -96, 224}, + { -4, 206, 314, 33}, { 167, 139, 88, 204}, + { -235, 316, -60, -25}, { -8, -150, -312, 201}, + { -36, 292, 61, -104}, { -40, 174, -162, 42}, + { -21, 402, -29, -351}, { 21, 152, -360, -93}, + { 57, 191, 212, -196}, { 76, 158, -21, -69}, + { -328, -185, 331, 119}, { -53, 285, 56, 337}, + { -107, -24, 405, 29}, { -18, 137, 272, 277}, + { -255, 22, 173, -191}, { 295, 322, 325, 302}, + { 21, -27, 332, -178}, { 119, 13, 271, 129}, + { -455, -180, 116, -191}, { -227, 62, -148, 524}, + { -176, -287, 282, -157}, { -243, 13, 199, 430}, + { -59, -49, 115, -365}, { 72, -172, -137, 93}, + { -138, -126, 141, -84}, { 5, -124, 38, -20}, + { -258, 311, 601, 213}, { 94, 130, -61, 502}, + { -1, -157, 485, 313}, { 146, -74, 158, 345}, + { 276, 135, 280, -57}, { 490, 252, 99, 43}, + { 267, -74, 429, 105}, { 278, -23, 119, 94}, + { -542, 488, 257, -115}, { -84, -244, -438, 478}, + { -113, -545, 387, 101}, { -95, -306, 111, 498}, + { 95, 166, 22, -301}, { 420, -15, -58, -78}, + { 270, 29, 122, -282}, { 160, -240, 50, -38} +}; + +static const int16_t dico23_isf_36b[64][7] = { + { 81, -18, 68, -27, -122, -280, -4}, + { 45, -177, 209, -30, -136, -74, 131}, + { -44, 101, -75, -88, -48, -137, -54}, + { -245, -28, 63, -18, -112, -103, 58}, + { -79, -6, 220, -65, 114, -35, -50}, + { 109, -65, 143, -114, 129, 76, 125}, + { 166, 90, -61, -242, 186, -74, -43}, + { -46, -92, 49, -227, 24, -155, 39}, + { 67, 85, 99, -42, 53, -184, -281}, + { 142, -122, 0, 21, -142, -15, -17}, + { 223, 92, -21, -48, -82, -14, -167}, + { 51, -37, -243, -30, -90, 18, -56}, + { 54, 105, 74, 86, 69, 13, -101}, + { 196, 72, -89, 43, 65, 19, 39}, + { 121, 34, 131, -82, 25, 213, -156}, + { 101, -102, -136, -21, 57, 214, 22}, + { 36, -124, 205, 204, 58, -156, -83}, + { 83, -117, 137, 137, 85, 116, 44}, + { -92, -148, -68, 11, -102, -197, -220}, + { -76, -185, -58, 132, -26, -183, 85}, + { -7, -31, -2, 23, 205, -151, 10}, + { -27, -37, -5, -18, 292, 131, 1}, + { 117, -168, 9, -93, 80, -59, -125}, + { -182, -244, 98, -24, 135, -22, 94}, + { 221, 97, 106, 42, 43, -160, 83}, + { 25, -64, -21, 6, 14, -15, 154}, + { 126, 15, -140, 150, -10, -207, -114}, + { 79, -63, -211, -70, -28, -217, 165}, + { 46, 38, -22, 281, 132, -62, 109}, + { 112, 54, -112, -93, 208, 27, 296}, + { 115, 10, -147, 41, 216, 42, -276}, + { 50, -115, -254, 167, 117, -2, 61}, + { 17, 144, 34, -72, -186, -150, 272}, + { -29, -66, -89, -95, -149, 129, 251}, + { 122, 0, -50, -234, -91, 36, 26}, + { -105, -102, -88, -121, -236, -7, -11}, + { -204, 109, 5, -191, 105, -15, 163}, + { -80, 32, -24, -209, 41, 294, 70}, + { -106, -94, -204, -118, 120, -50, -37}, + { -82, -241, 46, -131, -29, 150, -55}, + { 33, 155, 120, -89, -8, 7, 62}, + { 213, 82, 61, 18, -161, 144, 152}, + { 30, 131, 65, -87, -255, -17, -107}, + { -8, 85, -64, 51, -162, 223, -53}, + { -134, 261, 69, -56, 218, 72, -111}, + { 2, 155, -113, -87, 49, 85, -28}, + { -163, 42, -1, -196, 7, 39, -245}, + { 14, -137, -79, 11, -160, 202, -293}, + { -94, 33, 208, 100, 56, -44, 326}, + { -78, -41, 232, 13, -142, 227, 80}, + { -16, -87, 201, 33, -133, 15, -183}, + { -58, -192, -47, 184, -128, 133, 99}, + { -205, 11, -155, 78, 52, 72, 141}, + { -246, 26, 99, 151, 59, 115, -64}, + { -79, -47, -16, -14, 6, 47, -43}, + { -72, -178, -27, 162, 112, 43, -174}, + { -175, 238, 186, 71, -54, -188, -76}, + { -225, 233, 39, -39, -158, 122, 44}, + { -26, 43, 84, 130, -93, -51, 22}, + { 3, 92, -150, 136, -182, -57, 97}, + { -131, 179, -78, 80, 91, -165, 90}, + { -2, 148, 15, 130, 65, 175, 117}, + { -138, 114, -137, 132, 3, -10, -186}, + { 140, -4, -37, 254, -62, 92, -109} +}; + +/** Means of ISF vectors in Q15 */ +static const int16_t isf_mean[LP_ORDER] = { + 738, 1326, 2336, 3578, 4596, 5662, 6711, 7730, + 8750, 9753, 10705, 11728, 12833, 13971, 15043, 4037 +}; + +/** Initialization tables for the processed ISF vector in Q15 */ +static const int16_t isf_init[LP_ORDER] = { + 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, + 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840 +}; + +/** ISF/ISP interpolation coefficients for each subframe */ +static const float isfp_inter[4] = { 0.45, 0.8, 0.96, 1.0 }; + +/** Coefficients for FIR interpolation of excitation vector + * at pitch lag resulting the adaptive codebook vector */ +static const float ac_inter[65] = { + 9.400024e-01, + 8.563843e-01, 6.322632e-01, 3.375854e-01, 5.908203e-02, + -1.310425e-01, -1.994019e-01, -1.585693e-01, -5.633545e-02, + 4.760742e-02, 1.067505e-01, 1.036987e-01, 5.206299e-02, + -1.519775e-02, -6.372070e-02, -7.366943e-02, -4.650879e-02, + -9.765625e-04, 3.820801e-02, 5.316162e-02, 4.003906e-02, + 9.338379e-03, -2.166748e-02, -3.778076e-02, -3.320312e-02, + -1.300049e-02, 1.068115e-02, 2.587891e-02, 2.630615e-02, + 1.379395e-02, -3.662109e-03, -1.678467e-02, -1.983643e-02, + -1.275635e-02, -5.493164e-04, 1.007080e-02, 1.409912e-02, + 1.068115e-02, 2.624512e-03, -5.371094e-03, -9.338379e-03, + -8.117676e-03, -3.173828e-03, 2.319336e-03, 5.615234e-03, + 5.554199e-03, 2.868652e-03, -6.103516e-04, -2.990723e-03, + -3.356934e-03, -2.014160e-03, -1.220703e-04, 1.342773e-03, + 1.708984e-03, 1.159668e-03, 2.441406e-04, -4.272461e-04, + -6.103516e-04, -4.272461e-04, -1.220703e-04, 6.103516e-05, + 1.220703e-04, 6.103516e-05, 0.000000e+00, 0.000000e+00 +}; + +/** [i][j] is the number of pulses present in track j at mode i */ +static const uint8_t pulses_nb_per_mode_tr[][4] = { + {1, 1, 0, 0}, {1, 1, 1, 1}, {2, 2, 2, 2}, + {3, 3, 2, 2}, {3, 3, 3, 3}, {4, 4, 4, 4}, + {5, 5, 4, 4}, {6, 6, 6, 6}, {6, 6, 6, 6} +}; + +/** Tables for decoding quantized gains { pitch (Q14), fixed factor (Q11) } */ +static const int16_t qua_gain_6b[64][2] = { + { 1566, 1332}, { 1577, 3557}, + { 3071, 6490}, { 4193, 10163}, + { 4496, 2534}, { 5019, 4488}, + { 5586, 15614}, { 5725, 1422}, + { 6453, 580}, { 6724, 6831}, + { 7657, 3527}, { 8072, 2099}, + { 8232, 5319}, { 8827, 8775}, + { 9740, 2868}, { 9856, 1465}, + { 10087, 12488}, { 10241, 4453}, + { 10859, 6618}, { 11321, 3587}, + { 11417, 1800}, { 11643, 2428}, + { 11718, 988}, { 12312, 5093}, + { 12523, 8413}, { 12574, 26214}, + { 12601, 3396}, { 13172, 1623}, + { 13285, 2423}, { 13418, 6087}, + { 13459, 12810}, { 13656, 3607}, + { 14111, 4521}, { 14144, 1229}, + { 14425, 1871}, { 14431, 7234}, + { 14445, 2834}, { 14628, 10036}, + { 14860, 17496}, { 15161, 3629}, + { 15209, 5819}, { 15299, 2256}, + { 15518, 4722}, { 15663, 1060}, + { 15759, 7972}, { 15939, 11964}, + { 16020, 2996}, { 16086, 1707}, + { 16521, 4254}, { 16576, 6224}, + { 16894, 2380}, { 16906, 681}, + { 17213, 8406}, { 17610, 3418}, + { 17895, 5269}, { 18168, 11748}, + { 18230, 1575}, { 18607, 32767}, + { 18728, 21684}, { 19137, 2543}, + { 19422, 6577}, { 19446, 4097}, + { 19450, 9056}, { 20371, 14885} +}; + +static const int16_t qua_gain_7b[128][2] = { + { 204, 441}, { 464, 1977}, + { 869, 1077}, { 1072, 3062}, + { 1281, 4759}, { 1647, 1539}, + { 1845, 7020}, { 1853, 634}, + { 1995, 2336}, { 2351, 15400}, + { 2661, 1165}, { 2702, 3900}, + { 2710, 10133}, { 3195, 1752}, + { 3498, 2624}, { 3663, 849}, + { 3984, 5697}, { 4214, 3399}, + { 4415, 1304}, { 4695, 2056}, + { 5376, 4558}, { 5386, 676}, + { 5518, 23554}, { 5567, 7794}, + { 5644, 3061}, { 5672, 1513}, + { 5957, 2338}, { 6533, 1060}, + { 6804, 5998}, { 6820, 1767}, + { 6937, 3837}, { 7277, 414}, + { 7305, 2665}, { 7466, 11304}, + { 7942, 794}, { 8007, 1982}, + { 8007, 1366}, { 8326, 3105}, + { 8336, 4810}, { 8708, 7954}, + { 8989, 2279}, { 9031, 1055}, + { 9247, 3568}, { 9283, 1631}, + { 9654, 6311}, { 9811, 2605}, + { 10120, 683}, { 10143, 4179}, + { 10245, 1946}, { 10335, 1218}, + { 10468, 9960}, { 10651, 3000}, + { 10951, 1530}, { 10969, 5290}, + { 11203, 2305}, { 11325, 3562}, + { 11771, 6754}, { 11839, 1849}, + { 11941, 4495}, { 11954, 1298}, + { 11975, 15223}, { 11977, 883}, + { 11986, 2842}, { 12438, 2141}, + { 12593, 3665}, { 12636, 8367}, + { 12658, 1594}, { 12886, 2628}, + { 12984, 4942}, { 13146, 1115}, + { 13224, 524}, { 13341, 3163}, + { 13399, 1923}, { 13549, 5961}, + { 13606, 1401}, { 13655, 2399}, + { 13782, 3909}, { 13868, 10923}, + { 14226, 1723}, { 14232, 2939}, + { 14278, 7528}, { 14439, 4598}, + { 14451, 984}, { 14458, 2265}, + { 14792, 1403}, { 14818, 3445}, + { 14899, 5709}, { 15017, 15362}, + { 15048, 1946}, { 15069, 2655}, + { 15405, 9591}, { 15405, 4079}, + { 15570, 7183}, { 15687, 2286}, + { 15691, 1624}, { 15699, 3068}, + { 15772, 5149}, { 15868, 1205}, + { 15970, 696}, { 16249, 3584}, + { 16338, 1917}, { 16424, 2560}, + { 16483, 4438}, { 16529, 6410}, + { 16620, 11966}, { 16839, 8780}, + { 17030, 3050}, { 17033, 18325}, + { 17092, 1568}, { 17123, 5197}, + { 17351, 2113}, { 17374, 980}, + { 17566, 26214}, { 17609, 3912}, + { 17639, 32767}, { 18151, 7871}, + { 18197, 2516}, { 18202, 5649}, + { 18679, 3283}, { 18930, 1370}, + { 19271, 13757}, { 19317, 4120}, + { 19460, 1973}, { 19654, 10018}, + { 19764, 6792}, { 19912, 5135}, + { 20040, 2841}, { 21234, 19833} +}; + +/** 4-tap moving average prediction coefficients in reverse order */ +static const float energy_pred_fac[4] = { 0.2, 0.3, 0.4, 0.5 }; + +/** impulse response filter tables converted to float from Q15 + * used for anti-sparseness processing */ +static const float ir_filter_str[64] = { + 6.159058e-01, 2.958069e-01, 9.979248e-02, -1.048889e-01, + 8.740234e-02, -1.599121e-01, 4.849243e-02, -4.141235e-02, + 1.831055e-02, 1.188049e-01, -4.568481e-02, -2.130127e-02, + 3.671265e-02, -1.601868e-01, 3.659058e-02, 1.639099e-01, + -4.541016e-02, -2.151489e-02, -8.810425e-02, 6.030273e-02, + 2.740479e-02, 2.200317e-02, -1.182861e-01, 1.289978e-01, + -1.560059e-01, 1.953125e-01, -3.149414e-02, -1.441956e-01, + 1.249084e-01, -1.328125e-01, 9.780884e-02, 6.500244e-02, + -6.091309e-02, -5.599976e-02, 8.081055e-02, -5.450439e-02, + -1.239014e-02, 1.748657e-02, 7.580566e-02, -1.101074e-01, + 9.579468e-02, -4.159546e-02, -7.830811e-02, 1.162109e-01, + -1.950073e-02, -6.259155e-02, -1.651001e-02, 7.250977e-02, + 1.199951e-01, -1.911011e-01, 4.370117e-02, -1.098938e-01, + 1.492004e-01, 1.129150e-02, 1.730347e-02, -3.549194e-02, + -8.709717e-02, 5.841064e-02, 1.190186e-03, -7.379150e-02, + 1.054077e-01, 9.078979e-02, -1.227112e-01, 1.047058e-01 +}; + +static const float ir_filter_mid[64] = { + 7.354126e-01, 3.192139e-01, -1.606140e-01, -2.328491e-02, + 6.250000e-02, -2.828979e-02, 5.349731e-02, -1.014099e-01, + 6.750488e-02, 1.989746e-02, -6.549072e-02, 7.589722e-02, + -1.080017e-01, 1.253967e-01, -6.430054e-02, -1.141357e-02, + -1.910400e-02, 1.303101e-01, -1.673889e-01, 6.820679e-02, + 5.670166e-02, -8.450317e-02, 2.270508e-02, 3.479004e-02, + -2.328491e-02, -4.928589e-02, 1.239014e-01, -1.395874e-01, + 9.100342e-02, -3.549194e-02, 2.230835e-02, -3.350830e-02, + 2.450562e-02, 5.096436e-03, -2.178955e-02, 1.849365e-02, + -1.708984e-02, 1.950073e-02, 1.312256e-03, -5.389404e-02, + 9.851074e-02, -8.489990e-02, 2.029419e-02, 2.328491e-02, + 7.110596e-03, -6.109619e-02, 3.939819e-02, 5.709839e-02, + -1.058960e-01, 3.149414e-02, 8.270264e-02, -1.232910e-01, + 1.105957e-01, -1.286011e-01, 1.614990e-01, -1.303101e-01, + 4.769897e-02, 3.295898e-03, -1.770020e-02, 5.010986e-02, + -7.501221e-02, 2.920532e-02, 1.660156e-02, 7.751465e-02 +}; + +static const float * const ir_filters_lookup[2] = { + ir_filter_str, ir_filter_mid +}; + +/** High-pass filters coefficients for 31 Hz and 400 Hz cutoff */ +static const float hpf_zeros[2] = { -2.0, 1.0 }; +static const float hpf_31_poles[2] = { -1.978881836, 0.979125977 }; +static const float hpf_31_gain = 0.989501953; + +static const float hpf_400_poles[2] = { -1.787109375, 0.864257812 }; +static const float hpf_400_gain = 0.893554687; + +/** Interpolation coefficients for 5/4 signal upsampling + * Table from the reference source was reordered for efficiency */ +static const float upsample_fir[4][24] = { + { -6.103516e-05, 7.324219e-04, -2.014160e-03, 4.150391e-03, + -7.263184e-03, 1.165771e-02, -1.776123e-02, 2.624512e-02, + -3.869629e-02, 5.877686e-02, -9.863281e-02, 2.314453e-01, + 9.348755e-01, -1.523438e-01, 7.861328e-02, -4.937744e-02, + 3.308105e-02, -2.252197e-02, 1.507568e-02, -9.765625e-03, + 5.859375e-03, -3.173828e-03, 1.403809e-03, -3.662109e-04 }, + { -2.441406e-04, 1.464844e-03, -3.784180e-03, 7.568359e-03, + -1.300049e-02, 2.062988e-02, -3.112793e-02, 4.589844e-02, + -6.781006e-02, 1.042480e-01, -1.815186e-01, 5.016479e-01, + 7.548828e-01, -2.094727e-01, 1.148071e-01, -7.348633e-02, + 4.956055e-02, -3.369141e-02, 2.246094e-02, -1.434326e-02, + 8.483887e-03, -4.455566e-03, 1.831055e-03, -4.272461e-04 }, + { -4.272461e-04, 1.831055e-03, -4.455566e-03, 8.483887e-03, + -1.434326e-02, 2.246094e-02, -3.369141e-02, 4.956055e-02, + -7.348633e-02, 1.148071e-01, -2.094727e-01, 7.548828e-01, + 5.016479e-01, -1.815186e-01, 1.042480e-01, -6.781006e-02, + 4.589844e-02, -3.112793e-02, 2.062988e-02, -1.300049e-02, + 7.568359e-03, -3.784180e-03, 1.464844e-03, -2.441406e-04 }, + { -3.662109e-04, 1.403809e-03, -3.173828e-03, 5.859375e-03, + -9.765625e-03, 1.507568e-02, -2.252197e-02, 3.308105e-02, + -4.937744e-02, 7.861328e-02, -1.523438e-01, 9.348755e-01, + 2.314453e-01, -9.863281e-02, 5.877686e-02, -3.869629e-02, + 2.624512e-02, -1.776123e-02, 1.165771e-02, -7.263184e-03, + 4.150391e-03, -2.014160e-03, 7.324219e-04, -6.103516e-05 } +}; + +/** High band quantized gains for 23k85 in Q14 */ +static const uint16_t qua_hb_gain[16] = { + 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264, + 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728 +}; + +/** High-band post-processing FIR filters coefficients from Q15 */ +static const float bpf_6_7_coef[31] = { // band pass, 6kHz and 7kHz cutoffs + -2.441406e-04, 3.585815e-04, 2.441406e-04, + -2.059937e-04, -2.815248e-03, 8.560180e-03, + -1.084137e-02, 0.000000e+00, 2.897645e-02, + -6.774902e-02, 9.421540e-02, -8.380128e-02, + 2.706910e-02, 5.924987e-02, -1.373367e-01, + 1.687469e-01, + -1.373367e-01, 5.924987e-02, 2.706910e-02, + -8.380128e-02, 9.421540e-02, -6.774902e-02, + 2.897645e-02, 0.000000e+00, -1.084137e-02, + 8.560180e-03, -2.815248e-03, -2.059937e-04, + 2.441406e-04, 3.585815e-04, -2.441406e-04 +}; + +static const float lpf_7_coef[31] = { // low pass, 7kHz cutoff + -6.408691e-04, 1.434326e-03, -2.716064e-03, + 4.455566e-03, -6.195068e-03, 6.988525e-03, + -5.401611e-03, 0.000000e+00, 1.022339e-02, + -2.560425e-02, 4.531860e-02, -6.747437e-02, + 8.944702e-02, -1.080933e-01, 1.206360e-01, + 8.753052e-01, + 1.206360e-01, -1.080933e-01, 8.944702e-02, + -6.747437e-02, 4.531860e-02, -2.560425e-02, + 1.022339e-02, 0.000000e+00, -5.401611e-03, + 6.988525e-03, -6.195068e-03, 4.455566e-03, + -2.716064e-03, 1.434326e-03, -6.408691e-04 +}; + +/** Core frame sizes in each mode */ +static const uint16_t cf_sizes_wb[] = { + 132, 177, 253, 285, 317, 365, 397, 461, 477, + 40 /// SID/comfort noise frame +}; + +#endif /* AVCODEC_AMRWBDATA_H */ diff --git a/ffmpeg/libavcodec/amrwbdec.c b/ffmpeg/libavcodec/amrwbdec.c new file mode 100644 index 0000000..8c3eb56 --- /dev/null +++ b/ffmpeg/libavcodec/amrwbdec.c @@ -0,0 +1,1279 @@ +/* + * AMR wideband decoder + * Copyright (c) 2010 Marcelo Galvao Povoa + * + * 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 + */ + +/** + * @file + * AMR wideband decoder + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/lfg.h" + +#include "avcodec.h" +#include "lsp.h" +#include "celp_filters.h" +#include "celp_math.h" +#include "acelp_filters.h" +#include "acelp_vectors.h" +#include "acelp_pitch_delay.h" +#include "internal.h" + +#define AMR_USE_16BIT_TABLES +#include "amr.h" + +#include "amrwbdata.h" +#include "mips/amrwbdec_mips.h" + +typedef struct { + AMRWBFrame frame; ///< AMRWB parameters decoded from bitstream + enum Mode fr_cur_mode; ///< mode index of current frame + uint8_t fr_quality; ///< frame quality index (FQI) + float isf_cur[LP_ORDER]; ///< working ISF vector from current frame + float isf_q_past[LP_ORDER]; ///< quantized ISF vector of the previous frame + float isf_past_final[LP_ORDER]; ///< final processed ISF vector of the previous frame + double isp[4][LP_ORDER]; ///< ISP vectors from current frame + double isp_sub4_past[LP_ORDER]; ///< ISP vector for the 4th subframe of the previous frame + + float lp_coef[4][LP_ORDER]; ///< Linear Prediction Coefficients from ISP vector + + uint8_t base_pitch_lag; ///< integer part of pitch lag for the next relative subframe + uint8_t pitch_lag_int; ///< integer part of pitch lag of the previous subframe + + float excitation_buf[AMRWB_P_DELAY_MAX + LP_ORDER + 2 + AMRWB_SFR_SIZE]; ///< current excitation and all necessary excitation history + float *excitation; ///< points to current excitation in excitation_buf[] + + float pitch_vector[AMRWB_SFR_SIZE]; ///< adaptive codebook (pitch) vector for current subframe + float fixed_vector[AMRWB_SFR_SIZE]; ///< algebraic codebook (fixed) vector for current subframe + + float prediction_error[4]; ///< quantified prediction errors {20log10(^gamma_gc)} for previous four subframes + float pitch_gain[6]; ///< quantified pitch gains for the current and previous five subframes + float fixed_gain[2]; ///< quantified fixed gains for the current and previous subframes + + float tilt_coef; ///< {beta_1} related to the voicing of the previous subframe + + float prev_sparse_fixed_gain; ///< previous fixed gain; used by anti-sparseness to determine "onset" + uint8_t prev_ir_filter_nr; ///< previous impulse response filter "impNr": 0 - strong, 1 - medium, 2 - none + float prev_tr_gain; ///< previous initial gain used by noise enhancer for threshold + + float samples_az[LP_ORDER + AMRWB_SFR_SIZE]; ///< low-band samples and memory from synthesis at 12.8kHz + float samples_up[UPS_MEM_SIZE + AMRWB_SFR_SIZE]; ///< low-band samples and memory processed for upsampling + float samples_hb[LP_ORDER_16k + AMRWB_SFR_SIZE_16k]; ///< high-band samples and memory from synthesis at 16kHz + + float hpf_31_mem[2], hpf_400_mem[2]; ///< previous values in the high pass filters + float demph_mem[1]; ///< previous value in the de-emphasis filter + float bpf_6_7_mem[HB_FIR_SIZE]; ///< previous values in the high-band band pass filter + float lpf_7_mem[HB_FIR_SIZE]; ///< previous values in the high-band low pass filter + + AVLFG prng; ///< random number generator for white noise excitation + uint8_t first_frame; ///< flag active during decoding of the first frame + ACELPFContext acelpf_ctx; ///< context for filters for ACELP-based codecs + ACELPVContext acelpv_ctx; ///< context for vector operations for ACELP-based codecs + CELPFContext celpf_ctx; ///< context for filters for CELP-based codecs + CELPMContext celpm_ctx; ///< context for fixed point math operations + +} AMRWBContext; + +static av_cold int amrwb_decode_init(AVCodecContext *avctx) +{ + AMRWBContext *ctx = avctx->priv_data; + int i; + + if (avctx->channels > 1) { + avpriv_report_missing_feature(avctx, "multi-channel AMR"); + return AVERROR_PATCHWELCOME; + } + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->sample_rate) + avctx->sample_rate = 16000; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + av_lfg_init(&ctx->prng, 1); + + ctx->excitation = &ctx->excitation_buf[AMRWB_P_DELAY_MAX + LP_ORDER + 1]; + ctx->first_frame = 1; + + for (i = 0; i < LP_ORDER; i++) + ctx->isf_past_final[i] = isf_init[i] * (1.0f / (1 << 15)); + + for (i = 0; i < 4; i++) + ctx->prediction_error[i] = MIN_ENERGY; + + ff_acelp_filter_init(&ctx->acelpf_ctx); + ff_acelp_vectors_init(&ctx->acelpv_ctx); + ff_celp_filter_init(&ctx->celpf_ctx); + ff_celp_math_init(&ctx->celpm_ctx); + + return 0; +} + +/** + * Decode the frame header in the "MIME/storage" format. This format + * is simpler and does not carry the auxiliary frame information. + * + * @param[in] ctx The Context + * @param[in] buf Pointer to the input buffer + * + * @return The decoded header length in bytes + */ +static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf) +{ + /* Decode frame header (1st octet) */ + ctx->fr_cur_mode = buf[0] >> 3 & 0x0F; + ctx->fr_quality = (buf[0] & 0x4) == 0x4; + + return 1; +} + +/** + * Decode quantized ISF vectors using 36-bit indexes (6K60 mode only). + * + * @param[in] ind Array of 5 indexes + * @param[out] isf_q Buffer for isf_q[LP_ORDER] + * + */ +static void decode_isf_indices_36b(uint16_t *ind, float *isf_q) +{ + int i; + + for (i = 0; i < 9; i++) + isf_q[i] = dico1_isf[ind[0]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 7; i++) + isf_q[i + 9] = dico2_isf[ind[1]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 5; i++) + isf_q[i] += dico21_isf_36b[ind[2]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 4; i++) + isf_q[i + 5] += dico22_isf_36b[ind[3]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 7; i++) + isf_q[i + 9] += dico23_isf_36b[ind[4]][i] * (1.0f / (1 << 15)); +} + +/** + * Decode quantized ISF vectors using 46-bit indexes (except 6K60 mode). + * + * @param[in] ind Array of 7 indexes + * @param[out] isf_q Buffer for isf_q[LP_ORDER] + * + */ +static void decode_isf_indices_46b(uint16_t *ind, float *isf_q) +{ + int i; + + for (i = 0; i < 9; i++) + isf_q[i] = dico1_isf[ind[0]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 7; i++) + isf_q[i + 9] = dico2_isf[ind[1]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 3; i++) + isf_q[i] += dico21_isf[ind[2]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 3; i++) + isf_q[i + 3] += dico22_isf[ind[3]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 3; i++) + isf_q[i + 6] += dico23_isf[ind[4]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 3; i++) + isf_q[i + 9] += dico24_isf[ind[5]][i] * (1.0f / (1 << 15)); + + for (i = 0; i < 4; i++) + isf_q[i + 12] += dico25_isf[ind[6]][i] * (1.0f / (1 << 15)); +} + +/** + * Apply mean and past ISF values using the prediction factor. + * Updates past ISF vector. + * + * @param[in,out] isf_q Current quantized ISF + * @param[in,out] isf_past Past quantized ISF + * + */ +static void isf_add_mean_and_past(float *isf_q, float *isf_past) +{ + int i; + float tmp; + + for (i = 0; i < LP_ORDER; i++) { + tmp = isf_q[i]; + isf_q[i] += isf_mean[i] * (1.0f / (1 << 15)); + isf_q[i] += PRED_FACTOR * isf_past[i]; + isf_past[i] = tmp; + } +} + +/** + * Interpolate the fourth ISP vector from current and past frames + * to obtain an ISP vector for each subframe. + * + * @param[in,out] isp_q ISPs for each subframe + * @param[in] isp4_past Past ISP for subframe 4 + */ +static void interpolate_isp(double isp_q[4][LP_ORDER], const double *isp4_past) +{ + int i, k; + + for (k = 0; k < 3; k++) { + float c = isfp_inter[k]; + for (i = 0; i < LP_ORDER; i++) + isp_q[k][i] = (1.0 - c) * isp4_past[i] + c * isp_q[3][i]; + } +} + +/** + * Decode an adaptive codebook index into pitch lag (except 6k60, 8k85 modes). + * Calculate integer lag and fractional lag always using 1/4 resolution. + * In 1st and 3rd subframes the index is relative to last subframe integer lag. + * + * @param[out] lag_int Decoded integer pitch lag + * @param[out] lag_frac Decoded fractional pitch lag + * @param[in] pitch_index Adaptive codebook pitch index + * @param[in,out] base_lag_int Base integer lag used in relative subframes + * @param[in] subframe Current subframe index (0 to 3) + */ +static void decode_pitch_lag_high(int *lag_int, int *lag_frac, int pitch_index, + uint8_t *base_lag_int, int subframe) +{ + if (subframe == 0 || subframe == 2) { + if (pitch_index < 376) { + *lag_int = (pitch_index + 137) >> 2; + *lag_frac = pitch_index - (*lag_int << 2) + 136; + } else if (pitch_index < 440) { + *lag_int = (pitch_index + 257 - 376) >> 1; + *lag_frac = (pitch_index - (*lag_int << 1) + 256 - 376) << 1; + /* the actual resolution is 1/2 but expressed as 1/4 */ + } else { + *lag_int = pitch_index - 280; + *lag_frac = 0; + } + /* minimum lag for next subframe */ + *base_lag_int = av_clip(*lag_int - 8 - (*lag_frac < 0), + AMRWB_P_DELAY_MIN, AMRWB_P_DELAY_MAX - 15); + // XXX: the spec states clearly that *base_lag_int should be + // the nearest integer to *lag_int (minus 8), but the ref code + // actually always uses its floor, I'm following the latter + } else { + *lag_int = (pitch_index + 1) >> 2; + *lag_frac = pitch_index - (*lag_int << 2); + *lag_int += *base_lag_int; + } +} + +/** + * Decode an adaptive codebook index into pitch lag for 8k85 and 6k60 modes. + * The description is analogous to decode_pitch_lag_high, but in 6k60 the + * relative index is used for all subframes except the first. + */ +static void decode_pitch_lag_low(int *lag_int, int *lag_frac, int pitch_index, + uint8_t *base_lag_int, int subframe, enum Mode mode) +{ + if (subframe == 0 || (subframe == 2 && mode != MODE_6k60)) { + if (pitch_index < 116) { + *lag_int = (pitch_index + 69) >> 1; + *lag_frac = (pitch_index - (*lag_int << 1) + 68) << 1; + } else { + *lag_int = pitch_index - 24; + *lag_frac = 0; + } + // XXX: same problem as before + *base_lag_int = av_clip(*lag_int - 8 - (*lag_frac < 0), + AMRWB_P_DELAY_MIN, AMRWB_P_DELAY_MAX - 15); + } else { + *lag_int = (pitch_index + 1) >> 1; + *lag_frac = (pitch_index - (*lag_int << 1)) << 1; + *lag_int += *base_lag_int; + } +} + +/** + * Find the pitch vector by interpolating the past excitation at the + * pitch delay, which is obtained in this function. + * + * @param[in,out] ctx The context + * @param[in] amr_subframe Current subframe data + * @param[in] subframe Current subframe index (0 to 3) + */ +static void decode_pitch_vector(AMRWBContext *ctx, + const AMRWBSubFrame *amr_subframe, + const int subframe) +{ + int pitch_lag_int, pitch_lag_frac; + int i; + float *exc = ctx->excitation; + enum Mode mode = ctx->fr_cur_mode; + + if (mode <= MODE_8k85) { + decode_pitch_lag_low(&pitch_lag_int, &pitch_lag_frac, amr_subframe->adap, + &ctx->base_pitch_lag, subframe, mode); + } else + decode_pitch_lag_high(&pitch_lag_int, &pitch_lag_frac, amr_subframe->adap, + &ctx->base_pitch_lag, subframe); + + ctx->pitch_lag_int = pitch_lag_int; + pitch_lag_int += pitch_lag_frac > 0; + + /* Calculate the pitch vector by interpolating the past excitation at the + pitch lag using a hamming windowed sinc function */ + ctx->acelpf_ctx.acelp_interpolatef(exc, + exc + 1 - pitch_lag_int, + ac_inter, 4, + pitch_lag_frac + (pitch_lag_frac > 0 ? 0 : 4), + LP_ORDER, AMRWB_SFR_SIZE + 1); + + /* Check which pitch signal path should be used + * 6k60 and 8k85 modes have the ltp flag set to 0 */ + if (amr_subframe->ltp) { + memcpy(ctx->pitch_vector, exc, AMRWB_SFR_SIZE * sizeof(float)); + } else { + for (i = 0; i < AMRWB_SFR_SIZE; i++) + ctx->pitch_vector[i] = 0.18 * exc[i - 1] + 0.64 * exc[i] + + 0.18 * exc[i + 1]; + memcpy(exc, ctx->pitch_vector, AMRWB_SFR_SIZE * sizeof(float)); + } +} + +/** Get x bits in the index interval [lsb,lsb+len-1] inclusive */ +#define BIT_STR(x,lsb,len) (((x) >> (lsb)) & ((1 << (len)) - 1)) + +/** Get the bit at specified position */ +#define BIT_POS(x, p) (((x) >> (p)) & 1) + +/** + * The next six functions decode_[i]p_track decode exactly i pulses + * positions and amplitudes (-1 or 1) in a subframe track using + * an encoded pulse indexing (TS 26.190 section 5.8.2). + * + * The results are given in out[], in which a negative number means + * amplitude -1 and vice versa (i.e., ampl(x) = x / abs(x) ). + * + * @param[out] out Output buffer (writes i elements) + * @param[in] code Pulse index (no. of bits varies, see below) + * @param[in] m (log2) Number of potential positions + * @param[in] off Offset for decoded positions + */ +static inline void decode_1p_track(int *out, int code, int m, int off) +{ + int pos = BIT_STR(code, 0, m) + off; ///code: m+1 bits + + out[0] = BIT_POS(code, m) ? -pos : pos; +} + +static inline void decode_2p_track(int *out, int code, int m, int off) ///code: 2m+1 bits +{ + int pos0 = BIT_STR(code, m, m) + off; + int pos1 = BIT_STR(code, 0, m) + off; + + out[0] = BIT_POS(code, 2*m) ? -pos0 : pos0; + out[1] = BIT_POS(code, 2*m) ? -pos1 : pos1; + out[1] = pos0 > pos1 ? -out[1] : out[1]; +} + +static void decode_3p_track(int *out, int code, int m, int off) ///code: 3m+1 bits +{ + int half_2p = BIT_POS(code, 2*m - 1) << (m - 1); + + decode_2p_track(out, BIT_STR(code, 0, 2*m - 1), + m - 1, off + half_2p); + decode_1p_track(out + 2, BIT_STR(code, 2*m, m + 1), m, off); +} + +static void decode_4p_track(int *out, int code, int m, int off) ///code: 4m bits +{ + int half_4p, subhalf_2p; + int b_offset = 1 << (m - 1); + + switch (BIT_STR(code, 4*m - 2, 2)) { /* case ID (2 bits) */ + case 0: /* 0 pulses in A, 4 pulses in B or vice versa */ + half_4p = BIT_POS(code, 4*m - 3) << (m - 1); // which has 4 pulses + subhalf_2p = BIT_POS(code, 2*m - 3) << (m - 2); + + decode_2p_track(out, BIT_STR(code, 0, 2*m - 3), + m - 2, off + half_4p + subhalf_2p); + decode_2p_track(out + 2, BIT_STR(code, 2*m - 2, 2*m - 1), + m - 1, off + half_4p); + break; + case 1: /* 1 pulse in A, 3 pulses in B */ + decode_1p_track(out, BIT_STR(code, 3*m - 2, m), + m - 1, off); + decode_3p_track(out + 1, BIT_STR(code, 0, 3*m - 2), + m - 1, off + b_offset); + break; + case 2: /* 2 pulses in each half */ + decode_2p_track(out, BIT_STR(code, 2*m - 1, 2*m - 1), + m - 1, off); + decode_2p_track(out + 2, BIT_STR(code, 0, 2*m - 1), + m - 1, off + b_offset); + break; + case 3: /* 3 pulses in A, 1 pulse in B */ + decode_3p_track(out, BIT_STR(code, m, 3*m - 2), + m - 1, off); + decode_1p_track(out + 3, BIT_STR(code, 0, m), + m - 1, off + b_offset); + break; + } +} + +static void decode_5p_track(int *out, int code, int m, int off) ///code: 5m bits +{ + int half_3p = BIT_POS(code, 5*m - 1) << (m - 1); + + decode_3p_track(out, BIT_STR(code, 2*m + 1, 3*m - 2), + m - 1, off + half_3p); + + decode_2p_track(out + 3, BIT_STR(code, 0, 2*m + 1), m, off); +} + +static void decode_6p_track(int *out, int code, int m, int off) ///code: 6m-2 bits +{ + int b_offset = 1 << (m - 1); + /* which half has more pulses in cases 0 to 2 */ + int half_more = BIT_POS(code, 6*m - 5) << (m - 1); + int half_other = b_offset - half_more; + + switch (BIT_STR(code, 6*m - 4, 2)) { /* case ID (2 bits) */ + case 0: /* 0 pulses in A, 6 pulses in B or vice versa */ + decode_1p_track(out, BIT_STR(code, 0, m), + m - 1, off + half_more); + decode_5p_track(out + 1, BIT_STR(code, m, 5*m - 5), + m - 1, off + half_more); + break; + case 1: /* 1 pulse in A, 5 pulses in B or vice versa */ + decode_1p_track(out, BIT_STR(code, 0, m), + m - 1, off + half_other); + decode_5p_track(out + 1, BIT_STR(code, m, 5*m - 5), + m - 1, off + half_more); + break; + case 2: /* 2 pulses in A, 4 pulses in B or vice versa */ + decode_2p_track(out, BIT_STR(code, 0, 2*m - 1), + m - 1, off + half_other); + decode_4p_track(out + 2, BIT_STR(code, 2*m - 1, 4*m - 4), + m - 1, off + half_more); + break; + case 3: /* 3 pulses in A, 3 pulses in B */ + decode_3p_track(out, BIT_STR(code, 3*m - 2, 3*m - 2), + m - 1, off); + decode_3p_track(out + 3, BIT_STR(code, 0, 3*m - 2), + m - 1, off + b_offset); + break; + } +} + +/** + * Decode the algebraic codebook index to pulse positions and signs, + * then construct the algebraic codebook vector. + * + * @param[out] fixed_vector Buffer for the fixed codebook excitation + * @param[in] pulse_hi MSBs part of the pulse index array (higher modes only) + * @param[in] pulse_lo LSBs part of the pulse index array + * @param[in] mode Mode of the current frame + */ +static void decode_fixed_vector(float *fixed_vector, const uint16_t *pulse_hi, + const uint16_t *pulse_lo, const enum Mode mode) +{ + /* sig_pos stores for each track the decoded pulse position indexes + * (1-based) multiplied by its corresponding amplitude (+1 or -1) */ + int sig_pos[4][6]; + int spacing = (mode == MODE_6k60) ? 2 : 4; + int i, j; + + switch (mode) { + case MODE_6k60: + for (i = 0; i < 2; i++) + decode_1p_track(sig_pos[i], pulse_lo[i], 5, 1); + break; + case MODE_8k85: + for (i = 0; i < 4; i++) + decode_1p_track(sig_pos[i], pulse_lo[i], 4, 1); + break; + case MODE_12k65: + for (i = 0; i < 4; i++) + decode_2p_track(sig_pos[i], pulse_lo[i], 4, 1); + break; + case MODE_14k25: + for (i = 0; i < 2; i++) + decode_3p_track(sig_pos[i], pulse_lo[i], 4, 1); + for (i = 2; i < 4; i++) + decode_2p_track(sig_pos[i], pulse_lo[i], 4, 1); + break; + case MODE_15k85: + for (i = 0; i < 4; i++) + decode_3p_track(sig_pos[i], pulse_lo[i], 4, 1); + break; + case MODE_18k25: + for (i = 0; i < 4; i++) + decode_4p_track(sig_pos[i], (int) pulse_lo[i] + + ((int) pulse_hi[i] << 14), 4, 1); + break; + case MODE_19k85: + for (i = 0; i < 2; i++) + decode_5p_track(sig_pos[i], (int) pulse_lo[i] + + ((int) pulse_hi[i] << 10), 4, 1); + for (i = 2; i < 4; i++) + decode_4p_track(sig_pos[i], (int) pulse_lo[i] + + ((int) pulse_hi[i] << 14), 4, 1); + break; + case MODE_23k05: + case MODE_23k85: + for (i = 0; i < 4; i++) + decode_6p_track(sig_pos[i], (int) pulse_lo[i] + + ((int) pulse_hi[i] << 11), 4, 1); + break; + } + + memset(fixed_vector, 0, sizeof(float) * AMRWB_SFR_SIZE); + + for (i = 0; i < 4; i++) + for (j = 0; j < pulses_nb_per_mode_tr[mode][i]; j++) { + int pos = (FFABS(sig_pos[i][j]) - 1) * spacing + i; + + fixed_vector[pos] += sig_pos[i][j] < 0 ? -1.0 : 1.0; + } +} + +/** + * Decode pitch gain and fixed gain correction factor. + * + * @param[in] vq_gain Vector-quantized index for gains + * @param[in] mode Mode of the current frame + * @param[out] fixed_gain_factor Decoded fixed gain correction factor + * @param[out] pitch_gain Decoded pitch gain + */ +static void decode_gains(const uint8_t vq_gain, const enum Mode mode, + float *fixed_gain_factor, float *pitch_gain) +{ + const int16_t *gains = (mode <= MODE_8k85 ? qua_gain_6b[vq_gain] : + qua_gain_7b[vq_gain]); + + *pitch_gain = gains[0] * (1.0f / (1 << 14)); + *fixed_gain_factor = gains[1] * (1.0f / (1 << 11)); +} + +/** + * Apply pitch sharpening filters to the fixed codebook vector. + * + * @param[in] ctx The context + * @param[in,out] fixed_vector Fixed codebook excitation + */ +// XXX: Spec states this procedure should be applied when the pitch +// lag is less than 64, but this checking seems absent in reference and AMR-NB +static void pitch_sharpening(AMRWBContext *ctx, float *fixed_vector) +{ + int i; + + /* Tilt part */ + for (i = AMRWB_SFR_SIZE - 1; i != 0; i--) + fixed_vector[i] -= fixed_vector[i - 1] * ctx->tilt_coef; + + /* Periodicity enhancement part */ + for (i = ctx->pitch_lag_int; i < AMRWB_SFR_SIZE; i++) + fixed_vector[i] += fixed_vector[i - ctx->pitch_lag_int] * 0.85; +} + +/** + * Calculate the voicing factor (-1.0 = unvoiced to 1.0 = voiced). + * + * @param[in] p_vector, f_vector Pitch and fixed excitation vectors + * @param[in] p_gain, f_gain Pitch and fixed gains + * @param[in] ctx The context + */ +// XXX: There is something wrong with the precision here! The magnitudes +// of the energies are not correct. Please check the reference code carefully +static float voice_factor(float *p_vector, float p_gain, + float *f_vector, float f_gain, + CELPMContext *ctx) +{ + double p_ener = (double) ctx->dot_productf(p_vector, p_vector, + AMRWB_SFR_SIZE) * + p_gain * p_gain; + double f_ener = (double) ctx->dot_productf(f_vector, f_vector, + AMRWB_SFR_SIZE) * + f_gain * f_gain; + + return (p_ener - f_ener) / (p_ener + f_ener); +} + +/** + * Reduce fixed vector sparseness by smoothing with one of three IR filters, + * also known as "adaptive phase dispersion". + * + * @param[in] ctx The context + * @param[in,out] fixed_vector Unfiltered fixed vector + * @param[out] buf Space for modified vector if necessary + * + * @return The potentially overwritten filtered fixed vector address + */ +static float *anti_sparseness(AMRWBContext *ctx, + float *fixed_vector, float *buf) +{ + int ir_filter_nr; + + if (ctx->fr_cur_mode > MODE_8k85) // no filtering in higher modes + return fixed_vector; + + if (ctx->pitch_gain[0] < 0.6) { + ir_filter_nr = 0; // strong filtering + } else if (ctx->pitch_gain[0] < 0.9) { + ir_filter_nr = 1; // medium filtering + } else + ir_filter_nr = 2; // no filtering + + /* detect 'onset' */ + if (ctx->fixed_gain[0] > 3.0 * ctx->fixed_gain[1]) { + if (ir_filter_nr < 2) + ir_filter_nr++; + } else { + int i, count = 0; + + for (i = 0; i < 6; i++) + if (ctx->pitch_gain[i] < 0.6) + count++; + + if (count > 2) + ir_filter_nr = 0; + + if (ir_filter_nr > ctx->prev_ir_filter_nr + 1) + ir_filter_nr--; + } + + /* update ir filter strength history */ + ctx->prev_ir_filter_nr = ir_filter_nr; + + ir_filter_nr += (ctx->fr_cur_mode == MODE_8k85); + + if (ir_filter_nr < 2) { + int i; + const float *coef = ir_filters_lookup[ir_filter_nr]; + + /* Circular convolution code in the reference + * decoder was modified to avoid using one + * extra array. The filtered vector is given by: + * + * c2(n) = sum(i,0,len-1){ c(i) * coef( (n - i + len) % len ) } + */ + + memset(buf, 0, sizeof(float) * AMRWB_SFR_SIZE); + for (i = 0; i < AMRWB_SFR_SIZE; i++) + if (fixed_vector[i]) + ff_celp_circ_addf(buf, buf, coef, i, fixed_vector[i], + AMRWB_SFR_SIZE); + fixed_vector = buf; + } + + return fixed_vector; +} + +/** + * Calculate a stability factor {teta} based on distance between + * current and past isf. A value of 1 shows maximum signal stability. + */ +static float stability_factor(const float *isf, const float *isf_past) +{ + int i; + float acc = 0.0; + + for (i = 0; i < LP_ORDER - 1; i++) + acc += (isf[i] - isf_past[i]) * (isf[i] - isf_past[i]); + + // XXX: This part is not so clear from the reference code + // the result is more accurate changing the "/ 256" to "* 512" + return FFMAX(0.0, 1.25 - acc * 0.8 * 512); +} + +/** + * Apply a non-linear fixed gain smoothing in order to reduce + * fluctuation in the energy of excitation. + * + * @param[in] fixed_gain Unsmoothed fixed gain + * @param[in,out] prev_tr_gain Previous threshold gain (updated) + * @param[in] voice_fac Frame voicing factor + * @param[in] stab_fac Frame stability factor + * + * @return The smoothed gain + */ +static float noise_enhancer(float fixed_gain, float *prev_tr_gain, + float voice_fac, float stab_fac) +{ + float sm_fac = 0.5 * (1 - voice_fac) * stab_fac; + float g0; + + // XXX: the following fixed-point constants used to in(de)crement + // gain by 1.5dB were taken from the reference code, maybe it could + // be simpler + if (fixed_gain < *prev_tr_gain) { + g0 = FFMIN(*prev_tr_gain, fixed_gain + fixed_gain * + (6226 * (1.0f / (1 << 15)))); // +1.5 dB + } else + g0 = FFMAX(*prev_tr_gain, fixed_gain * + (27536 * (1.0f / (1 << 15)))); // -1.5 dB + + *prev_tr_gain = g0; // update next frame threshold + + return sm_fac * g0 + (1 - sm_fac) * fixed_gain; +} + +/** + * Filter the fixed_vector to emphasize the higher frequencies. + * + * @param[in,out] fixed_vector Fixed codebook vector + * @param[in] voice_fac Frame voicing factor + */ +static void pitch_enhancer(float *fixed_vector, float voice_fac) +{ + int i; + float cpe = 0.125 * (1 + voice_fac); + float last = fixed_vector[0]; // holds c(i - 1) + + fixed_vector[0] -= cpe * fixed_vector[1]; + + for (i = 1; i < AMRWB_SFR_SIZE - 1; i++) { + float cur = fixed_vector[i]; + + fixed_vector[i] -= cpe * (last + fixed_vector[i + 1]); + last = cur; + } + + fixed_vector[AMRWB_SFR_SIZE - 1] -= cpe * last; +} + +/** + * Conduct 16th order linear predictive coding synthesis from excitation. + * + * @param[in] ctx Pointer to the AMRWBContext + * @param[in] lpc Pointer to the LPC coefficients + * @param[out] excitation Buffer for synthesis final excitation + * @param[in] fixed_gain Fixed codebook gain for synthesis + * @param[in] fixed_vector Algebraic codebook vector + * @param[in,out] samples Pointer to the output samples and memory + */ +static void synthesis(AMRWBContext *ctx, float *lpc, float *excitation, + float fixed_gain, const float *fixed_vector, + float *samples) +{ + ctx->acelpv_ctx.weighted_vector_sumf(excitation, ctx->pitch_vector, fixed_vector, + ctx->pitch_gain[0], fixed_gain, AMRWB_SFR_SIZE); + + /* emphasize pitch vector contribution in low bitrate modes */ + if (ctx->pitch_gain[0] > 0.5 && ctx->fr_cur_mode <= MODE_8k85) { + int i; + float energy = ctx->celpm_ctx.dot_productf(excitation, excitation, + AMRWB_SFR_SIZE); + + // XXX: Weird part in both ref code and spec. A unknown parameter + // {beta} seems to be identical to the current pitch gain + float pitch_factor = 0.25 * ctx->pitch_gain[0] * ctx->pitch_gain[0]; + + for (i = 0; i < AMRWB_SFR_SIZE; i++) + excitation[i] += pitch_factor * ctx->pitch_vector[i]; + + ff_scale_vector_to_given_sum_of_squares(excitation, excitation, + energy, AMRWB_SFR_SIZE); + } + + ctx->celpf_ctx.celp_lp_synthesis_filterf(samples, lpc, excitation, + AMRWB_SFR_SIZE, LP_ORDER); +} + +/** + * Apply to synthesis a de-emphasis filter of the form: + * H(z) = 1 / (1 - m * z^-1) + * + * @param[out] out Output buffer + * @param[in] in Input samples array with in[-1] + * @param[in] m Filter coefficient + * @param[in,out] mem State from last filtering + */ +static void de_emphasis(float *out, float *in, float m, float mem[1]) +{ + int i; + + out[0] = in[0] + m * mem[0]; + + for (i = 1; i < AMRWB_SFR_SIZE; i++) + out[i] = in[i] + out[i - 1] * m; + + mem[0] = out[AMRWB_SFR_SIZE - 1]; +} + +/** + * Upsample a signal by 5/4 ratio (from 12.8kHz to 16kHz) using + * a FIR interpolation filter. Uses past data from before *in address. + * + * @param[out] out Buffer for interpolated signal + * @param[in] in Current signal data (length 0.8*o_size) + * @param[in] o_size Output signal length + * @param[in] ctx The context + */ +static void upsample_5_4(float *out, const float *in, int o_size, CELPMContext *ctx) +{ + const float *in0 = in - UPS_FIR_SIZE + 1; + int i, j, k; + int int_part = 0, frac_part; + + i = 0; + for (j = 0; j < o_size / 5; j++) { + out[i] = in[int_part]; + frac_part = 4; + i++; + + for (k = 1; k < 5; k++) { + out[i] = ctx->dot_productf(in0 + int_part, + upsample_fir[4 - frac_part], + UPS_MEM_SIZE); + int_part++; + frac_part--; + i++; + } + } +} + +/** + * Calculate the high-band gain based on encoded index (23k85 mode) or + * on the low-band speech signal and the Voice Activity Detection flag. + * + * @param[in] ctx The context + * @param[in] synth LB speech synthesis at 12.8k + * @param[in] hb_idx Gain index for mode 23k85 only + * @param[in] vad VAD flag for the frame + */ +static float find_hb_gain(AMRWBContext *ctx, const float *synth, + uint16_t hb_idx, uint8_t vad) +{ + int wsp = (vad > 0); + float tilt; + + if (ctx->fr_cur_mode == MODE_23k85) + return qua_hb_gain[hb_idx] * (1.0f / (1 << 14)); + + tilt = ctx->celpm_ctx.dot_productf(synth, synth + 1, AMRWB_SFR_SIZE - 1) / + ctx->celpm_ctx.dot_productf(synth, synth, AMRWB_SFR_SIZE); + + /* return gain bounded by [0.1, 1.0] */ + return av_clipf((1.0 - FFMAX(0.0, tilt)) * (1.25 - 0.25 * wsp), 0.1, 1.0); +} + +/** + * Generate the high-band excitation with the same energy from the lower + * one and scaled by the given gain. + * + * @param[in] ctx The context + * @param[out] hb_exc Buffer for the excitation + * @param[in] synth_exc Low-band excitation used for synthesis + * @param[in] hb_gain Wanted excitation gain + */ +static void scaled_hb_excitation(AMRWBContext *ctx, float *hb_exc, + const float *synth_exc, float hb_gain) +{ + int i; + float energy = ctx->celpm_ctx.dot_productf(synth_exc, synth_exc, + AMRWB_SFR_SIZE); + + /* Generate a white-noise excitation */ + for (i = 0; i < AMRWB_SFR_SIZE_16k; i++) + hb_exc[i] = 32768.0 - (uint16_t) av_lfg_get(&ctx->prng); + + ff_scale_vector_to_given_sum_of_squares(hb_exc, hb_exc, + energy * hb_gain * hb_gain, + AMRWB_SFR_SIZE_16k); +} + +/** + * Calculate the auto-correlation for the ISF difference vector. + */ +static float auto_correlation(float *diff_isf, float mean, int lag) +{ + int i; + float sum = 0.0; + + for (i = 7; i < LP_ORDER - 2; i++) { + float prod = (diff_isf[i] - mean) * (diff_isf[i - lag] - mean); + sum += prod * prod; + } + return sum; +} + +/** + * Extrapolate a ISF vector to the 16kHz range (20th order LP) + * used at mode 6k60 LP filter for the high frequency band. + * + * @param[out] isf Buffer for extrapolated isf; contains LP_ORDER + * values on input + */ +static void extrapolate_isf(float isf[LP_ORDER_16k]) +{ + float diff_isf[LP_ORDER - 2], diff_mean; + float corr_lag[3]; + float est, scale; + int i, j, i_max_corr; + + isf[LP_ORDER_16k - 1] = isf[LP_ORDER - 1]; + + /* Calculate the difference vector */ + for (i = 0; i < LP_ORDER - 2; i++) + diff_isf[i] = isf[i + 1] - isf[i]; + + diff_mean = 0.0; + for (i = 2; i < LP_ORDER - 2; i++) + diff_mean += diff_isf[i] * (1.0f / (LP_ORDER - 4)); + + /* Find which is the maximum autocorrelation */ + i_max_corr = 0; + for (i = 0; i < 3; i++) { + corr_lag[i] = auto_correlation(diff_isf, diff_mean, i + 2); + + if (corr_lag[i] > corr_lag[i_max_corr]) + i_max_corr = i; + } + i_max_corr++; + + for (i = LP_ORDER - 1; i < LP_ORDER_16k - 1; i++) + isf[i] = isf[i - 1] + isf[i - 1 - i_max_corr] + - isf[i - 2 - i_max_corr]; + + /* Calculate an estimate for ISF(18) and scale ISF based on the error */ + est = 7965 + (isf[2] - isf[3] - isf[4]) / 6.0; + scale = 0.5 * (FFMIN(est, 7600) - isf[LP_ORDER - 2]) / + (isf[LP_ORDER_16k - 2] - isf[LP_ORDER - 2]); + + for (i = LP_ORDER - 1, j = 0; i < LP_ORDER_16k - 1; i++, j++) + diff_isf[j] = scale * (isf[i] - isf[i - 1]); + + /* Stability insurance */ + for (i = 1; i < LP_ORDER_16k - LP_ORDER; i++) + if (diff_isf[i] + diff_isf[i - 1] < 5.0) { + if (diff_isf[i] > diff_isf[i - 1]) { + diff_isf[i - 1] = 5.0 - diff_isf[i]; + } else + diff_isf[i] = 5.0 - diff_isf[i - 1]; + } + + for (i = LP_ORDER - 1, j = 0; i < LP_ORDER_16k - 1; i++, j++) + isf[i] = isf[i - 1] + diff_isf[j] * (1.0f / (1 << 15)); + + /* Scale the ISF vector for 16000 Hz */ + for (i = 0; i < LP_ORDER_16k - 1; i++) + isf[i] *= 0.8; +} + +/** + * Spectral expand the LP coefficients using the equation: + * y[i] = x[i] * (gamma ** i) + * + * @param[out] out Output buffer (may use input array) + * @param[in] lpc LP coefficients array + * @param[in] gamma Weighting factor + * @param[in] size LP array size + */ +static void lpc_weighting(float *out, const float *lpc, float gamma, int size) +{ + int i; + float fac = gamma; + + for (i = 0; i < size; i++) { + out[i] = lpc[i] * fac; + fac *= gamma; + } +} + +/** + * Conduct 20th order linear predictive coding synthesis for the high + * frequency band excitation at 16kHz. + * + * @param[in] ctx The context + * @param[in] subframe Current subframe index (0 to 3) + * @param[in,out] samples Pointer to the output speech samples + * @param[in] exc Generated white-noise scaled excitation + * @param[in] isf Current frame isf vector + * @param[in] isf_past Past frame final isf vector + */ +static void hb_synthesis(AMRWBContext *ctx, int subframe, float *samples, + const float *exc, const float *isf, const float *isf_past) +{ + float hb_lpc[LP_ORDER_16k]; + enum Mode mode = ctx->fr_cur_mode; + + if (mode == MODE_6k60) { + float e_isf[LP_ORDER_16k]; // ISF vector for extrapolation + double e_isp[LP_ORDER_16k]; + + ctx->acelpv_ctx.weighted_vector_sumf(e_isf, isf_past, isf, isfp_inter[subframe], + 1.0 - isfp_inter[subframe], LP_ORDER); + + extrapolate_isf(e_isf); + + e_isf[LP_ORDER_16k - 1] *= 2.0; + ff_acelp_lsf2lspd(e_isp, e_isf, LP_ORDER_16k); + ff_amrwb_lsp2lpc(e_isp, hb_lpc, LP_ORDER_16k); + + lpc_weighting(hb_lpc, hb_lpc, 0.9, LP_ORDER_16k); + } else { + lpc_weighting(hb_lpc, ctx->lp_coef[subframe], 0.6, LP_ORDER); + } + + ctx->celpf_ctx.celp_lp_synthesis_filterf(samples, hb_lpc, exc, AMRWB_SFR_SIZE_16k, + (mode == MODE_6k60) ? LP_ORDER_16k : LP_ORDER); +} + +/** + * Apply a 15th order filter to high-band samples. + * The filter characteristic depends on the given coefficients. + * + * @param[out] out Buffer for filtered output + * @param[in] fir_coef Filter coefficients + * @param[in,out] mem State from last filtering (updated) + * @param[in] in Input speech data (high-band) + * + * @remark It is safe to pass the same array in in and out parameters + */ + +#ifndef hb_fir_filter +static void hb_fir_filter(float *out, const float fir_coef[HB_FIR_SIZE + 1], + float mem[HB_FIR_SIZE], const float *in) +{ + int i, j; + float data[AMRWB_SFR_SIZE_16k + HB_FIR_SIZE]; // past and current samples + + memcpy(data, mem, HB_FIR_SIZE * sizeof(float)); + memcpy(data + HB_FIR_SIZE, in, AMRWB_SFR_SIZE_16k * sizeof(float)); + + for (i = 0; i < AMRWB_SFR_SIZE_16k; i++) { + out[i] = 0.0; + for (j = 0; j <= HB_FIR_SIZE; j++) + out[i] += data[i + j] * fir_coef[j]; + } + + memcpy(mem, data + AMRWB_SFR_SIZE_16k, HB_FIR_SIZE * sizeof(float)); +} +#endif /* hb_fir_filter */ + +/** + * Update context state before the next subframe. + */ +static void update_sub_state(AMRWBContext *ctx) +{ + memmove(&ctx->excitation_buf[0], &ctx->excitation_buf[AMRWB_SFR_SIZE], + (AMRWB_P_DELAY_MAX + LP_ORDER + 1) * sizeof(float)); + + memmove(&ctx->pitch_gain[1], &ctx->pitch_gain[0], 5 * sizeof(float)); + memmove(&ctx->fixed_gain[1], &ctx->fixed_gain[0], 1 * sizeof(float)); + + memmove(&ctx->samples_az[0], &ctx->samples_az[AMRWB_SFR_SIZE], + LP_ORDER * sizeof(float)); + memmove(&ctx->samples_up[0], &ctx->samples_up[AMRWB_SFR_SIZE], + UPS_MEM_SIZE * sizeof(float)); + memmove(&ctx->samples_hb[0], &ctx->samples_hb[AMRWB_SFR_SIZE_16k], + LP_ORDER_16k * sizeof(float)); +} + +static int amrwb_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AMRWBContext *ctx = avctx->priv_data; + AVFrame *frame = data; + AMRWBFrame *cf = &ctx->frame; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int expected_fr_size, header_size; + float *buf_out; + float spare_vector[AMRWB_SFR_SIZE]; // extra stack space to hold result from anti-sparseness processing + float fixed_gain_factor; // fixed gain correction factor (gamma) + float *synth_fixed_vector; // pointer to the fixed vector that synthesis should use + float synth_fixed_gain; // the fixed gain that synthesis should use + float voice_fac, stab_fac; // parameters used for gain smoothing + float synth_exc[AMRWB_SFR_SIZE]; // post-processed excitation for synthesis + float hb_exc[AMRWB_SFR_SIZE_16k]; // excitation for the high frequency band + float hb_samples[AMRWB_SFR_SIZE_16k]; // filtered high-band samples from synthesis + float hb_gain; + int sub, i, ret; + + /* get output buffer */ + frame->nb_samples = 4 * AMRWB_SFR_SIZE_16k; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + buf_out = (float *)frame->data[0]; + + header_size = decode_mime_header(ctx, buf); + if (ctx->fr_cur_mode > MODE_SID) { + av_log(avctx, AV_LOG_ERROR, + "Invalid mode %d\n", ctx->fr_cur_mode); + return AVERROR_INVALIDDATA; + } + expected_fr_size = ((cf_sizes_wb[ctx->fr_cur_mode] + 7) >> 3) + 1; + + if (buf_size < expected_fr_size) { + av_log(avctx, AV_LOG_ERROR, + "Frame too small (%d bytes). Truncated file?\n", buf_size); + *got_frame_ptr = 0; + return AVERROR_INVALIDDATA; + } + + if (!ctx->fr_quality || ctx->fr_cur_mode > MODE_SID) + av_log(avctx, AV_LOG_ERROR, "Encountered a bad or corrupted frame\n"); + + if (ctx->fr_cur_mode == MODE_SID) { /* Comfort noise frame */ + avpriv_request_sample(avctx, "SID mode"); + return AVERROR_PATCHWELCOME; + } + + ff_amr_bit_reorder((uint16_t *) &ctx->frame, sizeof(AMRWBFrame), + buf + header_size, amr_bit_orderings_by_mode[ctx->fr_cur_mode]); + + /* Decode the quantized ISF vector */ + if (ctx->fr_cur_mode == MODE_6k60) { + decode_isf_indices_36b(cf->isp_id, ctx->isf_cur); + } else { + decode_isf_indices_46b(cf->isp_id, ctx->isf_cur); + } + + isf_add_mean_and_past(ctx->isf_cur, ctx->isf_q_past); + ff_set_min_dist_lsf(ctx->isf_cur, MIN_ISF_SPACING, LP_ORDER - 1); + + stab_fac = stability_factor(ctx->isf_cur, ctx->isf_past_final); + + ctx->isf_cur[LP_ORDER - 1] *= 2.0; + ff_acelp_lsf2lspd(ctx->isp[3], ctx->isf_cur, LP_ORDER); + + /* Generate a ISP vector for each subframe */ + if (ctx->first_frame) { + ctx->first_frame = 0; + memcpy(ctx->isp_sub4_past, ctx->isp[3], LP_ORDER * sizeof(double)); + } + interpolate_isp(ctx->isp, ctx->isp_sub4_past); + + for (sub = 0; sub < 4; sub++) + ff_amrwb_lsp2lpc(ctx->isp[sub], ctx->lp_coef[sub], LP_ORDER); + + for (sub = 0; sub < 4; sub++) { + const AMRWBSubFrame *cur_subframe = &cf->subframe[sub]; + float *sub_buf = buf_out + sub * AMRWB_SFR_SIZE_16k; + + /* Decode adaptive codebook (pitch vector) */ + decode_pitch_vector(ctx, cur_subframe, sub); + /* Decode innovative codebook (fixed vector) */ + decode_fixed_vector(ctx->fixed_vector, cur_subframe->pul_ih, + cur_subframe->pul_il, ctx->fr_cur_mode); + + pitch_sharpening(ctx, ctx->fixed_vector); + + decode_gains(cur_subframe->vq_gain, ctx->fr_cur_mode, + &fixed_gain_factor, &ctx->pitch_gain[0]); + + ctx->fixed_gain[0] = + ff_amr_set_fixed_gain(fixed_gain_factor, + ctx->celpm_ctx.dot_productf(ctx->fixed_vector, + ctx->fixed_vector, + AMRWB_SFR_SIZE) / + AMRWB_SFR_SIZE, + ctx->prediction_error, + ENERGY_MEAN, energy_pred_fac); + + /* Calculate voice factor and store tilt for next subframe */ + voice_fac = voice_factor(ctx->pitch_vector, ctx->pitch_gain[0], + ctx->fixed_vector, ctx->fixed_gain[0], + &ctx->celpm_ctx); + ctx->tilt_coef = voice_fac * 0.25 + 0.25; + + /* Construct current excitation */ + for (i = 0; i < AMRWB_SFR_SIZE; i++) { + ctx->excitation[i] *= ctx->pitch_gain[0]; + ctx->excitation[i] += ctx->fixed_gain[0] * ctx->fixed_vector[i]; + ctx->excitation[i] = truncf(ctx->excitation[i]); + } + + /* Post-processing of excitation elements */ + synth_fixed_gain = noise_enhancer(ctx->fixed_gain[0], &ctx->prev_tr_gain, + voice_fac, stab_fac); + + synth_fixed_vector = anti_sparseness(ctx, ctx->fixed_vector, + spare_vector); + + pitch_enhancer(synth_fixed_vector, voice_fac); + + synthesis(ctx, ctx->lp_coef[sub], synth_exc, synth_fixed_gain, + synth_fixed_vector, &ctx->samples_az[LP_ORDER]); + + /* Synthesis speech post-processing */ + de_emphasis(&ctx->samples_up[UPS_MEM_SIZE], + &ctx->samples_az[LP_ORDER], PREEMPH_FAC, ctx->demph_mem); + + ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(&ctx->samples_up[UPS_MEM_SIZE], + &ctx->samples_up[UPS_MEM_SIZE], hpf_zeros, hpf_31_poles, + hpf_31_gain, ctx->hpf_31_mem, AMRWB_SFR_SIZE); + + upsample_5_4(sub_buf, &ctx->samples_up[UPS_FIR_SIZE], + AMRWB_SFR_SIZE_16k, &ctx->celpm_ctx); + + /* High frequency band (6.4 - 7.0 kHz) generation part */ + ctx->acelpf_ctx.acelp_apply_order_2_transfer_function(hb_samples, + &ctx->samples_up[UPS_MEM_SIZE], hpf_zeros, hpf_400_poles, + hpf_400_gain, ctx->hpf_400_mem, AMRWB_SFR_SIZE); + + hb_gain = find_hb_gain(ctx, hb_samples, + cur_subframe->hb_gain, cf->vad); + + scaled_hb_excitation(ctx, hb_exc, synth_exc, hb_gain); + + hb_synthesis(ctx, sub, &ctx->samples_hb[LP_ORDER_16k], + hb_exc, ctx->isf_cur, ctx->isf_past_final); + + /* High-band post-processing filters */ + hb_fir_filter(hb_samples, bpf_6_7_coef, ctx->bpf_6_7_mem, + &ctx->samples_hb[LP_ORDER_16k]); + + if (ctx->fr_cur_mode == MODE_23k85) + hb_fir_filter(hb_samples, lpf_7_coef, ctx->lpf_7_mem, + hb_samples); + + /* Add the low and high frequency bands */ + for (i = 0; i < AMRWB_SFR_SIZE_16k; i++) + sub_buf[i] = (sub_buf[i] + hb_samples[i]) * (1.0f / (1 << 15)); + + /* Update buffers and history */ + update_sub_state(ctx); + } + + /* update state for next frame */ + memcpy(ctx->isp_sub4_past, ctx->isp[3], LP_ORDER * sizeof(ctx->isp[3][0])); + memcpy(ctx->isf_past_final, ctx->isf_cur, LP_ORDER * sizeof(float)); + + *got_frame_ptr = 1; + + return expected_fr_size; +} + +AVCodec ff_amrwb_decoder = { + .name = "amrwb", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AMR_WB, + .priv_data_size = sizeof(AMRWBContext), + .init = amrwb_decode_init, + .decode = amrwb_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/anm.c b/ffmpeg/libavcodec/anm.c new file mode 100644 index 0000000..9aef6d3 --- /dev/null +++ b/ffmpeg/libavcodec/anm.c @@ -0,0 +1,200 @@ +/* + * Deluxe Paint Animation decoder + * Copyright (c) 2009 Peter Ross + * + * 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 + */ + +/** + * @file + * Deluxe Paint Animation decoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct AnmContext { + AVFrame *frame; + int palette[AVPALETTE_COUNT]; + GetByteContext gb; + int x; ///< x coordinate position +} AnmContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + AnmContext *s = avctx->priv_data; + int i; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size); + if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256) + return AVERROR_INVALIDDATA; + + bytestream2_skipu(&s->gb, 16 * 8); + for (i = 0; i < 256; i++) + s->palette[i] = bytestream2_get_le32u(&s->gb); + + return 0; +} + +/** + * Perform decode operation + * @param dst pointer to destination image buffer + * @param dst_end pointer to end of destination image buffer + * @param gb GetByteContext (optional, see below) + * @param pixel Fill color (optional, see below) + * @param count Pixel count + * @param x Pointer to x-axis counter + * @param width Image width + * @param linesize Destination image buffer linesize + * @return non-zero if destination buffer is exhausted + * + * a copy operation is achieved when 'gb' is set + * a fill operation is achieved when 'gb' is null and pixel is >= 0 + * a skip operation is achieved when 'gb' is null and pixel is < 0 + */ +static inline int op(uint8_t **dst, const uint8_t *dst_end, + GetByteContext *gb, + int pixel, int count, + int *x, int width, int linesize) +{ + int remaining = width - *x; + while(count > 0) { + int striplen = FFMIN(count, remaining); + if (gb) { + if (bytestream2_get_bytes_left(gb) < striplen) + goto exhausted; + bytestream2_get_bufferu(gb, *dst, striplen); + } else if (pixel >= 0) + memset(*dst, pixel, striplen); + *dst += striplen; + remaining -= striplen; + count -= striplen; + if (remaining <= 0) { + *dst += linesize - width; + remaining = width; + } + if (linesize > 0) { + if (*dst >= dst_end) goto exhausted; + } else { + if (*dst <= dst_end) goto exhausted; + } + } + *x = width - remaining; + return 0; + +exhausted: + *x = width - remaining; + return 1; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + AnmContext *s = avctx->priv_data; + const int buf_size = avpkt->size; + uint8_t *dst, *dst_end; + int count, ret; + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + dst = s->frame->data[0]; + dst_end = s->frame->data[0] + s->frame->linesize[0]*avctx->height; + + bytestream2_init(&s->gb, avpkt->data, buf_size); + + if (bytestream2_get_byte(&s->gb) != 0x42) { + avpriv_request_sample(avctx, "Unknown record type"); + return AVERROR_INVALIDDATA; + } + if (bytestream2_get_byte(&s->gb)) { + avpriv_request_sample(avctx, "Padding bytes"); + return AVERROR_PATCHWELCOME; + } + bytestream2_skip(&s->gb, 2); + + s->x = 0; + do { + /* if statements are ordered by probability */ +#define OP(gb, pixel, count) \ + op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame->linesize[0]) + + int type = bytestream2_get_byte(&s->gb); + count = type & 0x7F; + type >>= 7; + if (count) { + if (OP(type ? NULL : &s->gb, -1, count)) break; + } else if (!type) { + int pixel; + count = bytestream2_get_byte(&s->gb); /* count==0 gives nop */ + pixel = bytestream2_get_byte(&s->gb); + if (OP(NULL, pixel, count)) break; + } else { + int pixel; + type = bytestream2_get_le16(&s->gb); + count = type & 0x3FFF; + type >>= 14; + if (!count) { + if (type == 0) + break; // stop + if (type == 2) { + avpriv_request_sample(avctx, "Unknown opcode"); + return AVERROR_PATCHWELCOME; + } + continue; + } + pixel = type == 3 ? bytestream2_get_byte(&s->gb) : -1; + if (type == 1) count += 0x4000; + if (OP(type == 2 ? &s->gb : NULL, pixel, count)) break; + } + } while (bytestream2_get_bytes_left(&s->gb) > 0); + + memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); + + *got_frame = 1; + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + return buf_size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + AnmContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + return 0; +} + +AVCodec ff_anm_decoder = { + .name = "anm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ANM, + .priv_data_size = sizeof(AnmContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), +}; diff --git a/ffmpeg/libavcodec/ansi.c b/ffmpeg/libavcodec/ansi.c new file mode 100644 index 0000000..93915f8 --- /dev/null +++ b/ffmpeg/libavcodec/ansi.c @@ -0,0 +1,473 @@ +/* + * ASCII/ANSI art decoder + * Copyright (c) 2010 Peter Ross + * + * 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 + */ + +/** + * @file + * ASCII/ANSI art decoder + */ + +#include "libavutil/common.h" +#include "libavutil/frame.h" +#include "libavutil/lfg.h" +#include "libavutil/xga_font_data.h" +#include "avcodec.h" +#include "cga_data.h" +#include "internal.h" + +#define ATTR_BOLD 0x01 /**< Bold/Bright-foreground (mode 1) */ +#define ATTR_FAINT 0x02 /**< Faint (mode 2) */ +#define ATTR_UNDERLINE 0x08 /**< Underline (mode 4) */ +#define ATTR_BLINK 0x10 /**< Blink/Bright-background (mode 5) */ +#define ATTR_REVERSE 0x40 /**< Reverse (mode 7) */ +#define ATTR_CONCEALED 0x80 /**< Concealed (mode 8) */ + +#define DEFAULT_FG_COLOR 7 /**< CGA color index */ +#define DEFAULT_BG_COLOR 0 +#define DEFAULT_SCREEN_MODE 3 /**< 80x25 */ + +#define FONT_WIDTH 8 /**< Font width */ + +/** map ansi color index to cga palette index */ +static const uint8_t ansi_to_cga[16] = { + 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 +}; + +typedef struct { + AVFrame *frame; + int x; /**< x cursor position (pixels) */ + int y; /**< y cursor position (pixels) */ + int sx; /**< saved x cursor position (pixels) */ + int sy; /**< saved y cursor position (pixels) */ + const uint8_t* font; /**< font */ + int font_height; /**< font height */ + int attributes; /**< attribute flags */ + int fg; /**< foreground color */ + int bg; /**< background color */ + int first_frame; + + /* ansi parser state machine */ + enum { + STATE_NORMAL = 0, + STATE_ESCAPE, + STATE_CODE, + STATE_MUSIC_PREAMBLE + } state; +#define MAX_NB_ARGS 4 + int args[MAX_NB_ARGS]; + int nb_args; /**< number of arguments (may exceed MAX_NB_ARGS) */ +} AnsiContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + AnsiContext *s = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + /* defaults */ + s->font = avpriv_vga16_font; + s->font_height = 16; + s->fg = DEFAULT_FG_COLOR; + s->bg = DEFAULT_BG_COLOR; + + if (!avctx->width || !avctx->height) + avcodec_set_dimensions(avctx, 80<<3, 25<<4); + + return 0; +} + +static void set_palette(uint32_t *pal) +{ + int r, g, b; + memcpy(pal, ff_cga_palette, 16 * 4); + pal += 16; +#define COLOR(x) ((x) * 40 + 55) + for (r = 0; r < 6; r++) + for (g = 0; g < 6; g++) + for (b = 0; b < 6; b++) + *pal++ = 0xFF000000 | (COLOR(r) << 16) | (COLOR(g) << 8) | COLOR(b); +#define GRAY(x) ((x) * 10 + 8) + for (g = 0; g < 24; g++) + *pal++ = 0xFF000000 | (GRAY(g) << 16) | (GRAY(g) << 8) | GRAY(g); +} + +static void hscroll(AVCodecContext *avctx) +{ + AnsiContext *s = avctx->priv_data; + int i; + + if (s->y < avctx->height - s->font_height) { + s->y += s->font_height; + return; + } + + i = 0; + for (; i < avctx->height - s->font_height; i++) + memcpy(s->frame->data[0] + i * s->frame->linesize[0], + s->frame->data[0] + (i + s->font_height) * s->frame->linesize[0], + avctx->width); + for (; i < avctx->height; i++) + memset(s->frame->data[0] + i * s->frame->linesize[0], + DEFAULT_BG_COLOR, avctx->width); +} + +static void erase_line(AVCodecContext * avctx, int xoffset, int xlength) +{ + AnsiContext *s = avctx->priv_data; + int i; + for (i = 0; i < s->font_height; i++) + memset(s->frame->data[0] + (s->y + i)*s->frame->linesize[0] + xoffset, + DEFAULT_BG_COLOR, xlength); +} + +static void erase_screen(AVCodecContext *avctx) +{ + AnsiContext *s = avctx->priv_data; + int i; + for (i = 0; i < avctx->height; i++) + memset(s->frame->data[0] + i * s->frame->linesize[0], DEFAULT_BG_COLOR, avctx->width); + s->x = s->y = 0; +} + +/** + * Draw character to screen + */ +static void draw_char(AVCodecContext *avctx, int c) +{ + AnsiContext *s = avctx->priv_data; + int fg = s->fg; + int bg = s->bg; + + if ((s->attributes & ATTR_BOLD)) + fg += 8; + if ((s->attributes & ATTR_BLINK)) + bg += 8; + if ((s->attributes & ATTR_REVERSE)) + FFSWAP(int, fg, bg); + if ((s->attributes & ATTR_CONCEALED)) + fg = bg; + ff_draw_pc_font(s->frame->data[0] + s->y * s->frame->linesize[0] + s->x, + s->frame->linesize[0], s->font, s->font_height, c, fg, bg); + s->x += FONT_WIDTH; + if (s->x >= avctx->width) { + s->x = 0; + hscroll(avctx); + } +} + +/** + * Execute ANSI escape code + * @return 0 on success, negative on error + */ +static int execute_code(AVCodecContext * avctx, int c) +{ + AnsiContext *s = avctx->priv_data; + int ret, i, width, height; + switch(c) { + case 'A': //Cursor Up + s->y = FFMAX(s->y - (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), 0); + break; + case 'B': //Cursor Down + s->y = FFMIN(s->y + (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), avctx->height - s->font_height); + break; + case 'C': //Cursor Right + s->x = FFMIN(s->x + (s->nb_args > 0 ? s->args[0]*FONT_WIDTH : FONT_WIDTH), avctx->width - FONT_WIDTH); + break; + case 'D': //Cursor Left + s->x = FFMAX(s->x - (s->nb_args > 0 ? s->args[0]*FONT_WIDTH : FONT_WIDTH), 0); + break; + case 'H': //Cursor Position + case 'f': //Horizontal and Vertical Position + s->y = s->nb_args > 0 ? av_clip((s->args[0] - 1)*s->font_height, 0, avctx->height - s->font_height) : 0; + s->x = s->nb_args > 1 ? av_clip((s->args[1] - 1)*FONT_WIDTH, 0, avctx->width - FONT_WIDTH) : 0; + break; + case 'h': //set creen mode + case 'l': //reset screen mode + if (s->nb_args < 2) + s->args[0] = DEFAULT_SCREEN_MODE; + width = avctx->width; + height = avctx->height; + switch(s->args[0]) { + case 0: case 1: case 4: case 5: case 13: case 19: //320x200 (25 rows) + s->font = avpriv_cga_font; + s->font_height = 8; + width = 40<<3; + height = 25<<3; + break; + case 2: case 3: //640x400 (25 rows) + s->font = avpriv_vga16_font; + s->font_height = 16; + width = 80<<3; + height = 25<<4; + break; + case 6: case 14: //640x200 (25 rows) + s->font = avpriv_cga_font; + s->font_height = 8; + width = 80<<3; + height = 25<<3; + break; + case 7: //set line wrapping + break; + case 15: case 16: //640x350 (43 rows) + s->font = avpriv_cga_font; + s->font_height = 8; + width = 80<<3; + height = 43<<3; + break; + case 17: case 18: //640x480 (60 rows) + s->font = avpriv_cga_font; + s->font_height = 8; + width = 80<<3; + height = 60<<4; + break; + default: + avpriv_request_sample(avctx, "Unsupported screen mode"); + } + if (width != avctx->width || height != avctx->height) { + av_frame_unref(s->frame); + avcodec_set_dimensions(avctx, width, height); + if ((ret = ff_get_buffer(avctx, s->frame, + AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + s->frame->pict_type = AV_PICTURE_TYPE_I; + s->frame->palette_has_changed = 1; + set_palette((uint32_t *)s->frame->data[1]); + erase_screen(avctx); + } else if (c == 'l') { + erase_screen(avctx); + } + break; + case 'J': //Erase in Page + switch (s->args[0]) { + case 0: + erase_line(avctx, s->x, avctx->width - s->x); + if (s->y < avctx->height - s->font_height) + memset(s->frame->data[0] + (s->y + s->font_height)*s->frame->linesize[0], + DEFAULT_BG_COLOR, (avctx->height - s->y - s->font_height)*s->frame->linesize[0]); + break; + case 1: + erase_line(avctx, 0, s->x); + if (s->y > 0) + memset(s->frame->data[0], DEFAULT_BG_COLOR, s->y * s->frame->linesize[0]); + break; + case 2: + erase_screen(avctx); + } + break; + case 'K': //Erase in Line + switch(s->args[0]) { + case 0: + erase_line(avctx, s->x, avctx->width - s->x); + break; + case 1: + erase_line(avctx, 0, s->x); + break; + case 2: + erase_line(avctx, 0, avctx->width); + } + break; + case 'm': //Select Graphics Rendition + if (s->nb_args == 0) { + s->nb_args = 1; + s->args[0] = 0; + } + for (i = 0; i < FFMIN(s->nb_args, MAX_NB_ARGS); i++) { + int m = s->args[i]; + if (m == 0) { + s->attributes = 0; + s->fg = DEFAULT_FG_COLOR; + s->bg = DEFAULT_BG_COLOR; + } else if (m == 1 || m == 2 || m == 4 || m == 5 || m == 7 || m == 8) { + s->attributes |= 1 << (m - 1); + } else if (m >= 30 && m <= 37) { + s->fg = ansi_to_cga[m - 30]; + } else if (m == 38 && i + 2 < FFMIN(s->nb_args, MAX_NB_ARGS) && s->args[i + 1] == 5 && s->args[i + 2] < 256) { + int index = s->args[i + 2]; + s->fg = index < 16 ? ansi_to_cga[index] : index; + i += 2; + } else if (m == 39) { + s->fg = ansi_to_cga[DEFAULT_FG_COLOR]; + } else if (m >= 40 && m <= 47) { + s->bg = ansi_to_cga[m - 40]; + } else if (m == 48 && i + 2 < FFMIN(s->nb_args, MAX_NB_ARGS) && s->args[i + 1] == 5 && s->args[i + 2] < 256) { + int index = s->args[i + 2]; + s->bg = index < 16 ? ansi_to_cga[index] : index; + i += 2; + } else if (m == 49) { + s->fg = ansi_to_cga[DEFAULT_BG_COLOR]; + } else { + avpriv_request_sample(avctx, "Unsupported rendition parameter"); + } + } + break; + case 'n': //Device Status Report + case 'R': //report current line and column + /* ignore */ + break; + case 's': //Save Cursor Position + s->sx = s->x; + s->sy = s->y; + break; + case 'u': //Restore Cursor Position + s->x = av_clip(s->sx, 0, avctx->width - FONT_WIDTH); + s->y = av_clip(s->sy, 0, avctx->height - s->font_height); + break; + default: + avpriv_request_sample(avctx, "Unknown escape code"); + break; + } + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + AnsiContext *s = avctx->priv_data; + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end = buf+buf_size; + int ret, i, count; + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + if (!avctx->frame_number) { + for (i=0; iheight; i++) + memset(s->frame->data[0]+ i*s->frame->linesize[0], 0, avctx->width); + memset(s->frame->data[1], 0, AVPALETTE_SIZE); + } + + s->frame->pict_type = AV_PICTURE_TYPE_I; + s->frame->palette_has_changed = 1; + set_palette((uint32_t *)s->frame->data[1]); + if (!s->first_frame) { + erase_screen(avctx); + s->first_frame = 1; + } + + while(buf < buf_end) { + switch(s->state) { + case STATE_NORMAL: + switch (buf[0]) { + case 0x00: //NUL + case 0x07: //BEL + case 0x1A: //SUB + /* ignore */ + break; + case 0x08: //BS + s->x = FFMAX(s->x - 1, 0); + break; + case 0x09: //HT + i = s->x / FONT_WIDTH; + count = ((i + 8) & ~7) - i; + for (i = 0; i < count; i++) + draw_char(avctx, ' '); + break; + case 0x0A: //LF + hscroll(avctx); + case 0x0D: //CR + s->x = 0; + break; + case 0x0C: //FF + erase_screen(avctx); + break; + case 0x1B: //ESC + s->state = STATE_ESCAPE; + break; + default: + draw_char(avctx, buf[0]); + } + break; + case STATE_ESCAPE: + if (buf[0] == '[') { + s->state = STATE_CODE; + s->nb_args = 0; + s->args[0] = -1; + } else { + s->state = STATE_NORMAL; + draw_char(avctx, 0x1B); + continue; + } + break; + case STATE_CODE: + switch(buf[0]) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (s->nb_args < MAX_NB_ARGS) + s->args[s->nb_args] = FFMAX(s->args[s->nb_args], 0) * 10 + buf[0] - '0'; + break; + case ';': + s->nb_args++; + if (s->nb_args < MAX_NB_ARGS) + s->args[s->nb_args] = 0; + break; + case 'M': + s->state = STATE_MUSIC_PREAMBLE; + break; + case '=': case '?': + /* ignore */ + break; + default: + if (s->nb_args > MAX_NB_ARGS) + av_log(avctx, AV_LOG_WARNING, "args overflow (%i)\n", s->nb_args); + if (s->nb_args < MAX_NB_ARGS && s->args[s->nb_args] >= 0) + s->nb_args++; + if ((ret = execute_code(avctx, buf[0])) < 0) + return ret; + s->state = STATE_NORMAL; + } + break; + case STATE_MUSIC_PREAMBLE: + if (buf[0] == 0x0E || buf[0] == 0x1B) + s->state = STATE_NORMAL; + /* ignore music data */ + break; + } + buf++; + } + + *got_frame = 1; + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + return buf_size; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + AnsiContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + return 0; +} + +AVCodec ff_ansi_decoder = { + .name = "ansi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ANSI, + .priv_data_size = sizeof(AnsiContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), +}; diff --git a/ffmpeg/libavcodec/apedec.c b/ffmpeg/libavcodec/apedec.c new file mode 100644 index 0000000..1581d8e --- /dev/null +++ b/ffmpeg/libavcodec/apedec.c @@ -0,0 +1,1145 @@ +/* + * Monkey's Audio lossless audio decoder + * Copyright (c) 2007 Benjamin Zores + * based upon libdemac from Dave Chapman. + * + * 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 "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dsputil.h" +#include "bytestream.h" +#include "internal.h" + +/** + * @file + * Monkey's Audio lossless audio decoder + */ + +#define MAX_CHANNELS 2 +#define MAX_BYTESPERSAMPLE 3 + +#define APE_FRAMECODE_MONO_SILENCE 1 +#define APE_FRAMECODE_STEREO_SILENCE 3 +#define APE_FRAMECODE_PSEUDO_STEREO 4 + +#define HISTORY_SIZE 512 +#define PREDICTOR_ORDER 8 +/** Total size of all predictor histories */ +#define PREDICTOR_SIZE 50 + +#define YDELAYA (18 + PREDICTOR_ORDER*4) +#define YDELAYB (18 + PREDICTOR_ORDER*3) +#define XDELAYA (18 + PREDICTOR_ORDER*2) +#define XDELAYB (18 + PREDICTOR_ORDER) + +#define YADAPTCOEFFSA 18 +#define XADAPTCOEFFSA 14 +#define YADAPTCOEFFSB 10 +#define XADAPTCOEFFSB 5 + +/** + * Possible compression levels + * @{ + */ +enum APECompressionLevel { + COMPRESSION_LEVEL_FAST = 1000, + COMPRESSION_LEVEL_NORMAL = 2000, + COMPRESSION_LEVEL_HIGH = 3000, + COMPRESSION_LEVEL_EXTRA_HIGH = 4000, + COMPRESSION_LEVEL_INSANE = 5000 +}; +/** @} */ + +#define APE_FILTER_LEVELS 3 + +/** Filter orders depending on compression level */ +static const uint16_t ape_filter_orders[5][APE_FILTER_LEVELS] = { + { 0, 0, 0 }, + { 16, 0, 0 }, + { 64, 0, 0 }, + { 32, 256, 0 }, + { 16, 256, 1280 } +}; + +/** Filter fraction bits depending on compression level */ +static const uint8_t ape_filter_fracbits[5][APE_FILTER_LEVELS] = { + { 0, 0, 0 }, + { 11, 0, 0 }, + { 11, 0, 0 }, + { 10, 13, 0 }, + { 11, 13, 15 } +}; + + +/** Filters applied to the decoded data */ +typedef struct APEFilter { + int16_t *coeffs; ///< actual coefficients used in filtering + int16_t *adaptcoeffs; ///< adaptive filter coefficients used for correcting of actual filter coefficients + int16_t *historybuffer; ///< filter memory + int16_t *delay; ///< filtered values + + int avg; +} APEFilter; + +typedef struct APERice { + uint32_t k; + uint32_t ksum; +} APERice; + +typedef struct APERangecoder { + uint32_t low; ///< low end of interval + uint32_t range; ///< length of interval + uint32_t help; ///< bytes_to_follow resp. intermediate value + unsigned int buffer; ///< buffer for input/output +} APERangecoder; + +/** Filter histories */ +typedef struct APEPredictor { + int32_t *buf; + + int32_t lastA[2]; + + int32_t filterA[2]; + int32_t filterB[2]; + + int32_t coeffsA[2][4]; ///< adaption coefficients + int32_t coeffsB[2][5]; ///< adaption coefficients + int32_t historybuffer[HISTORY_SIZE + PREDICTOR_SIZE]; +} APEPredictor; + +/** Decoder context */ +typedef struct APEContext { + AVClass *class; ///< class for AVOptions + AVCodecContext *avctx; + DSPContext dsp; + int channels; + int samples; ///< samples left to decode in current frame + int bps; + + int fileversion; ///< codec version, very important in decoding process + int compression_level; ///< compression levels + int fset; ///< which filter set to use (calculated from compression level) + int flags; ///< global decoder flags + + uint32_t CRC; ///< frame CRC + int frameflags; ///< frame flags + APEPredictor predictor; ///< predictor used for final reconstruction + + int32_t *decoded_buffer; + int decoded_size; + int32_t *decoded[MAX_CHANNELS]; ///< decoded data for each channel + int blocks_per_loop; ///< maximum number of samples to decode for each call + + int16_t* filterbuf[APE_FILTER_LEVELS]; ///< filter memory + + APERangecoder rc; ///< rangecoder used to decode actual values + APERice riceX; ///< rice code parameters for the second channel + APERice riceY; ///< rice code parameters for the first channel + APEFilter filters[APE_FILTER_LEVELS][2]; ///< filters used for reconstruction + + uint8_t *data; ///< current frame data + uint8_t *data_end; ///< frame data end + int data_size; ///< frame data allocated size + const uint8_t *ptr; ///< current position in frame data + + int error; + + void (*entropy_decode_mono)(struct APEContext *ctx, int blockstodecode); + void (*entropy_decode_stereo)(struct APEContext *ctx, int blockstodecode); + void (*predictor_decode_mono)(struct APEContext *ctx, int count); + void (*predictor_decode_stereo)(struct APEContext *ctx, int count); +} APEContext; + +static void ape_apply_filters(APEContext *ctx, int32_t *decoded0, + int32_t *decoded1, int count); + +static void entropy_decode_mono_3900(APEContext *ctx, int blockstodecode); +static void entropy_decode_stereo_3900(APEContext *ctx, int blockstodecode); +static void entropy_decode_mono_3990(APEContext *ctx, int blockstodecode); +static void entropy_decode_stereo_3990(APEContext *ctx, int blockstodecode); + +static void predictor_decode_mono_3930(APEContext *ctx, int count); +static void predictor_decode_stereo_3930(APEContext *ctx, int count); +static void predictor_decode_mono_3950(APEContext *ctx, int count); +static void predictor_decode_stereo_3950(APEContext *ctx, int count); + +// TODO: dsputilize + +static av_cold int ape_decode_close(AVCodecContext *avctx) +{ + APEContext *s = avctx->priv_data; + int i; + + for (i = 0; i < APE_FILTER_LEVELS; i++) + av_freep(&s->filterbuf[i]); + + av_freep(&s->decoded_buffer); + av_freep(&s->data); + s->decoded_size = s->data_size = 0; + + return 0; +} + +static av_cold int ape_decode_init(AVCodecContext *avctx) +{ + APEContext *s = avctx->priv_data; + int i; + + if (avctx->extradata_size != 6) { + av_log(avctx, AV_LOG_ERROR, "Incorrect extradata\n"); + return AVERROR(EINVAL); + } + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Only mono and stereo is supported\n"); + return AVERROR(EINVAL); + } + s->bps = avctx->bits_per_coded_sample; + switch (s->bps) { + case 8: + avctx->sample_fmt = AV_SAMPLE_FMT_U8P; + break; + case 16: + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + break; + case 24: + avctx->sample_fmt = AV_SAMPLE_FMT_S32P; + break; + default: + avpriv_request_sample(avctx, + "%d bits per coded sample", s->bps); + return AVERROR_PATCHWELCOME; + } + s->avctx = avctx; + s->channels = avctx->channels; + s->fileversion = AV_RL16(avctx->extradata); + s->compression_level = AV_RL16(avctx->extradata + 2); + s->flags = AV_RL16(avctx->extradata + 4); + + av_log(avctx, AV_LOG_DEBUG, "Compression Level: %d - Flags: %d\n", + s->compression_level, s->flags); + if (s->compression_level % 1000 || s->compression_level > COMPRESSION_LEVEL_INSANE || !s->compression_level) { + av_log(avctx, AV_LOG_ERROR, "Incorrect compression level %d\n", + s->compression_level); + return AVERROR_INVALIDDATA; + } + s->fset = s->compression_level / 1000 - 1; + for (i = 0; i < APE_FILTER_LEVELS; i++) { + if (!ape_filter_orders[s->fset][i]) + break; + FF_ALLOC_OR_GOTO(avctx, s->filterbuf[i], + (ape_filter_orders[s->fset][i] * 3 + HISTORY_SIZE) * 4, + filter_alloc_fail); + } + + if (s->fileversion < 3990) { + s->entropy_decode_mono = entropy_decode_mono_3900; + s->entropy_decode_stereo = entropy_decode_stereo_3900; + } else { + s->entropy_decode_mono = entropy_decode_mono_3990; + s->entropy_decode_stereo = entropy_decode_stereo_3990; + } + + if (s->fileversion < 3950) { + s->predictor_decode_mono = predictor_decode_mono_3930; + s->predictor_decode_stereo = predictor_decode_stereo_3930; + } else { + s->predictor_decode_mono = predictor_decode_mono_3950; + s->predictor_decode_stereo = predictor_decode_stereo_3950; + } + + ff_dsputil_init(&s->dsp, avctx); + avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + + return 0; +filter_alloc_fail: + ape_decode_close(avctx); + return AVERROR(ENOMEM); +} + +/** + * @name APE range decoding functions + * @{ + */ + +#define CODE_BITS 32 +#define TOP_VALUE ((unsigned int)1 << (CODE_BITS-1)) +#define SHIFT_BITS (CODE_BITS - 9) +#define EXTRA_BITS ((CODE_BITS-2) % 8 + 1) +#define BOTTOM_VALUE (TOP_VALUE >> 8) + +/** Start the decoder */ +static inline void range_start_decoding(APEContext *ctx) +{ + ctx->rc.buffer = bytestream_get_byte(&ctx->ptr); + ctx->rc.low = ctx->rc.buffer >> (8 - EXTRA_BITS); + ctx->rc.range = (uint32_t) 1 << EXTRA_BITS; +} + +/** Perform normalization */ +static inline void range_dec_normalize(APEContext *ctx) +{ + while (ctx->rc.range <= BOTTOM_VALUE) { + ctx->rc.buffer <<= 8; + if(ctx->ptr < ctx->data_end) { + ctx->rc.buffer += *ctx->ptr; + ctx->ptr++; + } else { + ctx->error = 1; + } + ctx->rc.low = (ctx->rc.low << 8) | ((ctx->rc.buffer >> 1) & 0xFF); + ctx->rc.range <<= 8; + } +} + +/** + * Calculate culmulative frequency for next symbol. Does NO update! + * @param ctx decoder context + * @param tot_f is the total frequency or (code_value)1<rc.help = ctx->rc.range / tot_f; + return ctx->rc.low / ctx->rc.help; +} + +/** + * Decode value with given size in bits + * @param ctx decoder context + * @param shift number of bits to decode + */ +static inline int range_decode_culshift(APEContext *ctx, int shift) +{ + range_dec_normalize(ctx); + ctx->rc.help = ctx->rc.range >> shift; + return ctx->rc.low / ctx->rc.help; +} + + +/** + * Update decoding state + * @param ctx decoder context + * @param sy_f the interval length (frequency of the symbol) + * @param lt_f the lower end (frequency sum of < symbols) + */ +static inline void range_decode_update(APEContext *ctx, int sy_f, int lt_f) +{ + ctx->rc.low -= ctx->rc.help * lt_f; + ctx->rc.range = ctx->rc.help * sy_f; +} + +/** Decode n bits (n <= 16) without modelling */ +static inline int range_decode_bits(APEContext *ctx, int n) +{ + int sym = range_decode_culshift(ctx, n); + range_decode_update(ctx, 1, sym); + return sym; +} + + +#define MODEL_ELEMENTS 64 + +/** + * Fixed probabilities for symbols in Monkey Audio version 3.97 + */ +static const uint16_t counts_3970[22] = { + 0, 14824, 28224, 39348, 47855, 53994, 58171, 60926, + 62682, 63786, 64463, 64878, 65126, 65276, 65365, 65419, + 65450, 65469, 65480, 65487, 65491, 65493, +}; + +/** + * Probability ranges for symbols in Monkey Audio version 3.97 + */ +static const uint16_t counts_diff_3970[21] = { + 14824, 13400, 11124, 8507, 6139, 4177, 2755, 1756, + 1104, 677, 415, 248, 150, 89, 54, 31, + 19, 11, 7, 4, 2, +}; + +/** + * Fixed probabilities for symbols in Monkey Audio version 3.98 + */ +static const uint16_t counts_3980[22] = { + 0, 19578, 36160, 48417, 56323, 60899, 63265, 64435, + 64971, 65232, 65351, 65416, 65447, 65466, 65476, 65482, + 65485, 65488, 65490, 65491, 65492, 65493, +}; + +/** + * Probability ranges for symbols in Monkey Audio version 3.98 + */ +static const uint16_t counts_diff_3980[21] = { + 19578, 16582, 12257, 7906, 4576, 2366, 1170, 536, + 261, 119, 65, 31, 19, 10, 6, 3, + 3, 2, 1, 1, 1, +}; + +/** + * Decode symbol + * @param ctx decoder context + * @param counts probability range start position + * @param counts_diff probability range widths + */ +static inline int range_get_symbol(APEContext *ctx, + const uint16_t counts[], + const uint16_t counts_diff[]) +{ + int symbol, cf; + + cf = range_decode_culshift(ctx, 16); + + if(cf > 65492){ + symbol= cf - 65535 + 63; + range_decode_update(ctx, 1, cf); + if(cf > 65535) + ctx->error=1; + return symbol; + } + /* figure out the symbol inefficiently; a binary search would be much better */ + for (symbol = 0; counts[symbol + 1] <= cf; symbol++); + + range_decode_update(ctx, counts_diff[symbol], counts[symbol]); + + return symbol; +} +/** @} */ // group rangecoder + +static inline void update_rice(APERice *rice, unsigned int x) +{ + int lim = rice->k ? (1 << (rice->k + 4)) : 0; + rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5); + + if (rice->ksum < lim) + rice->k--; + else if (rice->ksum >= (1 << (rice->k + 5))) + rice->k++; +} + +static inline int ape_decode_value_3900(APEContext *ctx, APERice *rice) +{ + unsigned int x, overflow; + int tmpk; + + overflow = range_get_symbol(ctx, counts_3970, counts_diff_3970); + + if (overflow == (MODEL_ELEMENTS - 1)) { + tmpk = range_decode_bits(ctx, 5); + overflow = 0; + } else + tmpk = (rice->k < 1) ? 0 : rice->k - 1; + + if (tmpk <= 16) + x = range_decode_bits(ctx, tmpk); + else if (tmpk <= 32) { + x = range_decode_bits(ctx, 16); + x |= (range_decode_bits(ctx, tmpk - 16) << 16); + } else { + av_log(ctx->avctx, AV_LOG_ERROR, "Too many bits: %d\n", tmpk); + return AVERROR_INVALIDDATA; + } + x += overflow << tmpk; + + update_rice(rice, x); + + /* Convert to signed */ + if (x & 1) + return (x >> 1) + 1; + else + return -(x >> 1); +} + +static inline int ape_decode_value_3990(APEContext *ctx, APERice *rice) +{ + unsigned int x, overflow; + int base, pivot; + + pivot = rice->ksum >> 5; + if (pivot == 0) + pivot = 1; + + overflow = range_get_symbol(ctx, counts_3980, counts_diff_3980); + + if (overflow == (MODEL_ELEMENTS - 1)) { + overflow = range_decode_bits(ctx, 16) << 16; + overflow |= range_decode_bits(ctx, 16); + } + + if (pivot < 0x10000) { + base = range_decode_culfreq(ctx, pivot); + range_decode_update(ctx, 1, base); + } else { + int base_hi = pivot, base_lo; + int bbits = 0; + + while (base_hi & ~0xFFFF) { + base_hi >>= 1; + bbits++; + } + base_hi = range_decode_culfreq(ctx, base_hi + 1); + range_decode_update(ctx, 1, base_hi); + base_lo = range_decode_culfreq(ctx, 1 << bbits); + range_decode_update(ctx, 1, base_lo); + + base = (base_hi << bbits) + base_lo; + } + + x = base + overflow * pivot; + + update_rice(rice, x); + + /* Convert to signed */ + if (x & 1) + return (x >> 1) + 1; + else + return -(x >> 1); +} + +static void entropy_decode_mono_3900(APEContext *ctx, int blockstodecode) +{ + int32_t *decoded0 = ctx->decoded[0]; + + while (blockstodecode--) + *decoded0++ = ape_decode_value_3900(ctx, &ctx->riceY); +} + +static void entropy_decode_stereo_3900(APEContext *ctx, int blockstodecode) +{ + int32_t *decoded0 = ctx->decoded[0]; + int32_t *decoded1 = ctx->decoded[1]; + + while (blockstodecode--) { + *decoded0++ = ape_decode_value_3900(ctx, &ctx->riceY); + *decoded1++ = ape_decode_value_3900(ctx, &ctx->riceX); + } +} + +static void entropy_decode_mono_3990(APEContext *ctx, int blockstodecode) +{ + int32_t *decoded0 = ctx->decoded[0]; + + while (blockstodecode--) + *decoded0++ = ape_decode_value_3990(ctx, &ctx->riceY); +} + +static void entropy_decode_stereo_3990(APEContext *ctx, int blockstodecode) +{ + int32_t *decoded0 = ctx->decoded[0]; + int32_t *decoded1 = ctx->decoded[1]; + + while (blockstodecode--) { + *decoded0++ = ape_decode_value_3990(ctx, &ctx->riceY); + *decoded1++ = ape_decode_value_3990(ctx, &ctx->riceX); + } +} + +static int init_entropy_decoder(APEContext *ctx) +{ + /* Read the CRC */ + if (ctx->data_end - ctx->ptr < 6) + return AVERROR_INVALIDDATA; + ctx->CRC = bytestream_get_be32(&ctx->ptr); + + /* Read the frame flags if they exist */ + ctx->frameflags = 0; + if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) { + ctx->CRC &= ~0x80000000; + + if (ctx->data_end - ctx->ptr < 6) + return AVERROR_INVALIDDATA; + ctx->frameflags = bytestream_get_be32(&ctx->ptr); + } + + /* Initialize the rice structs */ + ctx->riceX.k = 10; + ctx->riceX.ksum = (1 << ctx->riceX.k) * 16; + ctx->riceY.k = 10; + ctx->riceY.ksum = (1 << ctx->riceY.k) * 16; + + /* The first 8 bits of input are ignored. */ + ctx->ptr++; + + range_start_decoding(ctx); + + return 0; +} + +static const int32_t initial_coeffs[4] = { + 360, 317, -109, 98 +}; + +static void init_predictor_decoder(APEContext *ctx) +{ + APEPredictor *p = &ctx->predictor; + + /* Zero the history buffers */ + memset(p->historybuffer, 0, PREDICTOR_SIZE * sizeof(*p->historybuffer)); + p->buf = p->historybuffer; + + /* Initialize and zero the coefficients */ + memcpy(p->coeffsA[0], initial_coeffs, sizeof(initial_coeffs)); + memcpy(p->coeffsA[1], initial_coeffs, sizeof(initial_coeffs)); + memset(p->coeffsB, 0, sizeof(p->coeffsB)); + + p->filterA[0] = p->filterA[1] = 0; + p->filterB[0] = p->filterB[1] = 0; + p->lastA[0] = p->lastA[1] = 0; +} + +/** Get inverse sign of integer (-1 for positive, 1 for negative and 0 for zero) */ +static inline int APESIGN(int32_t x) { + return (x < 0) - (x > 0); +} + +static av_always_inline int predictor_update_3930(APEPredictor *p, + const int decoded, const int filter, + const int delayA) +{ + int32_t predictionA, sign; + int32_t d0, d1, d2, d3; + + p->buf[delayA] = p->lastA[filter]; + d0 = p->buf[delayA ]; + d1 = p->buf[delayA ] - p->buf[delayA - 1]; + d2 = p->buf[delayA - 1] - p->buf[delayA - 2]; + d3 = p->buf[delayA - 2] - p->buf[delayA - 3]; + + predictionA = d0 * p->coeffsA[filter][0] + + d1 * p->coeffsA[filter][1] + + d2 * p->coeffsA[filter][2] + + d3 * p->coeffsA[filter][3]; + + p->lastA[filter] = decoded + (predictionA >> 9); + p->filterA[filter] = p->lastA[filter] + ((p->filterA[filter] * 31) >> 5); + + sign = APESIGN(decoded); + p->coeffsA[filter][0] += ((d0 < 0) * 2 - 1) * sign; + p->coeffsA[filter][1] += ((d1 < 0) * 2 - 1) * sign; + p->coeffsA[filter][2] += ((d2 < 0) * 2 - 1) * sign; + p->coeffsA[filter][3] += ((d3 < 0) * 2 - 1) * sign; + + return p->filterA[filter]; +} + +static void predictor_decode_stereo_3930(APEContext *ctx, int count) +{ + APEPredictor *p = &ctx->predictor; + int32_t *decoded0 = ctx->decoded[0]; + int32_t *decoded1 = ctx->decoded[1]; + + ape_apply_filters(ctx, ctx->decoded[0], ctx->decoded[1], count); + + while (count--) { + /* Predictor Y */ + int Y = *decoded1, X = *decoded0; + *decoded0 = predictor_update_3930(p, Y, 0, YDELAYA); + decoded0++; + *decoded1 = predictor_update_3930(p, X, 1, XDELAYA); + decoded1++; + + /* Combined */ + p->buf++; + + /* Have we filled the history buffer? */ + if (p->buf == p->historybuffer + HISTORY_SIZE) { + memmove(p->historybuffer, p->buf, + PREDICTOR_SIZE * sizeof(*p->historybuffer)); + p->buf = p->historybuffer; + } + } +} + +static void predictor_decode_mono_3930(APEContext *ctx, int count) +{ + APEPredictor *p = &ctx->predictor; + int32_t *decoded0 = ctx->decoded[0]; + + ape_apply_filters(ctx, ctx->decoded[0], NULL, count); + + while (count--) { + *decoded0 = predictor_update_3930(p, *decoded0, 0, YDELAYA); + decoded0++; + + p->buf++; + + /* Have we filled the history buffer? */ + if (p->buf == p->historybuffer + HISTORY_SIZE) { + memmove(p->historybuffer, p->buf, + PREDICTOR_SIZE * sizeof(*p->historybuffer)); + p->buf = p->historybuffer; + } + } +} + +static av_always_inline int predictor_update_filter(APEPredictor *p, + const int decoded, const int filter, + const int delayA, const int delayB, + const int adaptA, const int adaptB) +{ + int32_t predictionA, predictionB, sign; + + p->buf[delayA] = p->lastA[filter]; + p->buf[adaptA] = APESIGN(p->buf[delayA]); + p->buf[delayA - 1] = p->buf[delayA] - p->buf[delayA - 1]; + p->buf[adaptA - 1] = APESIGN(p->buf[delayA - 1]); + + predictionA = p->buf[delayA ] * p->coeffsA[filter][0] + + p->buf[delayA - 1] * p->coeffsA[filter][1] + + p->buf[delayA - 2] * p->coeffsA[filter][2] + + p->buf[delayA - 3] * p->coeffsA[filter][3]; + + /* Apply a scaled first-order filter compression */ + p->buf[delayB] = p->filterA[filter ^ 1] - ((p->filterB[filter] * 31) >> 5); + p->buf[adaptB] = APESIGN(p->buf[delayB]); + p->buf[delayB - 1] = p->buf[delayB] - p->buf[delayB - 1]; + p->buf[adaptB - 1] = APESIGN(p->buf[delayB - 1]); + p->filterB[filter] = p->filterA[filter ^ 1]; + + predictionB = p->buf[delayB ] * p->coeffsB[filter][0] + + p->buf[delayB - 1] * p->coeffsB[filter][1] + + p->buf[delayB - 2] * p->coeffsB[filter][2] + + p->buf[delayB - 3] * p->coeffsB[filter][3] + + p->buf[delayB - 4] * p->coeffsB[filter][4]; + + p->lastA[filter] = decoded + ((predictionA + (predictionB >> 1)) >> 10); + p->filterA[filter] = p->lastA[filter] + ((p->filterA[filter] * 31) >> 5); + + sign = APESIGN(decoded); + p->coeffsA[filter][0] += p->buf[adaptA ] * sign; + p->coeffsA[filter][1] += p->buf[adaptA - 1] * sign; + p->coeffsA[filter][2] += p->buf[adaptA - 2] * sign; + p->coeffsA[filter][3] += p->buf[adaptA - 3] * sign; + p->coeffsB[filter][0] += p->buf[adaptB ] * sign; + p->coeffsB[filter][1] += p->buf[adaptB - 1] * sign; + p->coeffsB[filter][2] += p->buf[adaptB - 2] * sign; + p->coeffsB[filter][3] += p->buf[adaptB - 3] * sign; + p->coeffsB[filter][4] += p->buf[adaptB - 4] * sign; + + return p->filterA[filter]; +} + +static void predictor_decode_stereo_3950(APEContext *ctx, int count) +{ + APEPredictor *p = &ctx->predictor; + int32_t *decoded0 = ctx->decoded[0]; + int32_t *decoded1 = ctx->decoded[1]; + + ape_apply_filters(ctx, ctx->decoded[0], ctx->decoded[1], count); + + while (count--) { + /* Predictor Y */ + *decoded0 = predictor_update_filter(p, *decoded0, 0, YDELAYA, YDELAYB, + YADAPTCOEFFSA, YADAPTCOEFFSB); + decoded0++; + *decoded1 = predictor_update_filter(p, *decoded1, 1, XDELAYA, XDELAYB, + XADAPTCOEFFSA, XADAPTCOEFFSB); + decoded1++; + + /* Combined */ + p->buf++; + + /* Have we filled the history buffer? */ + if (p->buf == p->historybuffer + HISTORY_SIZE) { + memmove(p->historybuffer, p->buf, + PREDICTOR_SIZE * sizeof(*p->historybuffer)); + p->buf = p->historybuffer; + } + } +} + +static void predictor_decode_mono_3950(APEContext *ctx, int count) +{ + APEPredictor *p = &ctx->predictor; + int32_t *decoded0 = ctx->decoded[0]; + int32_t predictionA, currentA, A, sign; + + ape_apply_filters(ctx, ctx->decoded[0], NULL, count); + + currentA = p->lastA[0]; + + while (count--) { + A = *decoded0; + + p->buf[YDELAYA] = currentA; + p->buf[YDELAYA - 1] = p->buf[YDELAYA] - p->buf[YDELAYA - 1]; + + predictionA = p->buf[YDELAYA ] * p->coeffsA[0][0] + + p->buf[YDELAYA - 1] * p->coeffsA[0][1] + + p->buf[YDELAYA - 2] * p->coeffsA[0][2] + + p->buf[YDELAYA - 3] * p->coeffsA[0][3]; + + currentA = A + (predictionA >> 10); + + p->buf[YADAPTCOEFFSA] = APESIGN(p->buf[YDELAYA ]); + p->buf[YADAPTCOEFFSA - 1] = APESIGN(p->buf[YDELAYA - 1]); + + sign = APESIGN(A); + p->coeffsA[0][0] += p->buf[YADAPTCOEFFSA ] * sign; + p->coeffsA[0][1] += p->buf[YADAPTCOEFFSA - 1] * sign; + p->coeffsA[0][2] += p->buf[YADAPTCOEFFSA - 2] * sign; + p->coeffsA[0][3] += p->buf[YADAPTCOEFFSA - 3] * sign; + + p->buf++; + + /* Have we filled the history buffer? */ + if (p->buf == p->historybuffer + HISTORY_SIZE) { + memmove(p->historybuffer, p->buf, + PREDICTOR_SIZE * sizeof(*p->historybuffer)); + p->buf = p->historybuffer; + } + + p->filterA[0] = currentA + ((p->filterA[0] * 31) >> 5); + *(decoded0++) = p->filterA[0]; + } + + p->lastA[0] = currentA; +} + +static void do_init_filter(APEFilter *f, int16_t *buf, int order) +{ + f->coeffs = buf; + f->historybuffer = buf + order; + f->delay = f->historybuffer + order * 2; + f->adaptcoeffs = f->historybuffer + order; + + memset(f->historybuffer, 0, (order * 2) * sizeof(*f->historybuffer)); + memset(f->coeffs, 0, order * sizeof(*f->coeffs)); + f->avg = 0; +} + +static void init_filter(APEContext *ctx, APEFilter *f, int16_t *buf, int order) +{ + do_init_filter(&f[0], buf, order); + do_init_filter(&f[1], buf + order * 3 + HISTORY_SIZE, order); +} + +static void do_apply_filter(APEContext *ctx, int version, APEFilter *f, + int32_t *data, int count, int order, int fracbits) +{ + int res; + int absres; + + while (count--) { + /* round fixedpoint scalar product */ + res = ctx->dsp.scalarproduct_and_madd_int16(f->coeffs, f->delay - order, + f->adaptcoeffs - order, + order, APESIGN(*data)); + res = (res + (1 << (fracbits - 1))) >> fracbits; + res += *data; + *data++ = res; + + /* Update the output history */ + *f->delay++ = av_clip_int16(res); + + if (version < 3980) { + /* Version ??? to < 3.98 files (untested) */ + f->adaptcoeffs[0] = (res == 0) ? 0 : ((res >> 28) & 8) - 4; + f->adaptcoeffs[-4] >>= 1; + f->adaptcoeffs[-8] >>= 1; + } else { + /* Version 3.98 and later files */ + + /* Update the adaption coefficients */ + absres = FFABS(res); + if (absres) + *f->adaptcoeffs = ((res & (-1<<31)) ^ (-1<<30)) >> + (25 + (absres <= f->avg*3) + (absres <= f->avg*4/3)); + else + *f->adaptcoeffs = 0; + + f->avg += (absres - f->avg) / 16; + + f->adaptcoeffs[-1] >>= 1; + f->adaptcoeffs[-2] >>= 1; + f->adaptcoeffs[-8] >>= 1; + } + + f->adaptcoeffs++; + + /* Have we filled the history buffer? */ + if (f->delay == f->historybuffer + HISTORY_SIZE + (order * 2)) { + memmove(f->historybuffer, f->delay - (order * 2), + (order * 2) * sizeof(*f->historybuffer)); + f->delay = f->historybuffer + order * 2; + f->adaptcoeffs = f->historybuffer + order; + } + } +} + +static void apply_filter(APEContext *ctx, APEFilter *f, + int32_t *data0, int32_t *data1, + int count, int order, int fracbits) +{ + do_apply_filter(ctx, ctx->fileversion, &f[0], data0, count, order, fracbits); + if (data1) + do_apply_filter(ctx, ctx->fileversion, &f[1], data1, count, order, fracbits); +} + +static void ape_apply_filters(APEContext *ctx, int32_t *decoded0, + int32_t *decoded1, int count) +{ + int i; + + for (i = 0; i < APE_FILTER_LEVELS; i++) { + if (!ape_filter_orders[ctx->fset][i]) + break; + apply_filter(ctx, ctx->filters[i], decoded0, decoded1, count, + ape_filter_orders[ctx->fset][i], + ape_filter_fracbits[ctx->fset][i]); + } +} + +static int init_frame_decoder(APEContext *ctx) +{ + int i, ret; + if ((ret = init_entropy_decoder(ctx)) < 0) + return ret; + init_predictor_decoder(ctx); + + for (i = 0; i < APE_FILTER_LEVELS; i++) { + if (!ape_filter_orders[ctx->fset][i]) + break; + init_filter(ctx, ctx->filters[i], ctx->filterbuf[i], + ape_filter_orders[ctx->fset][i]); + } + return 0; +} + +static void ape_unpack_mono(APEContext *ctx, int count) +{ + if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) { + /* We are pure silence, so we're done. */ + av_log(ctx->avctx, AV_LOG_DEBUG, "pure silence mono\n"); + return; + } + + ctx->entropy_decode_mono(ctx, count); + + /* Now apply the predictor decoding */ + ctx->predictor_decode_mono(ctx, count); + + /* Pseudo-stereo - just copy left channel to right channel */ + if (ctx->channels == 2) { + memcpy(ctx->decoded[1], ctx->decoded[0], count * sizeof(*ctx->decoded[1])); + } +} + +static void ape_unpack_stereo(APEContext *ctx, int count) +{ + int32_t left, right; + int32_t *decoded0 = ctx->decoded[0]; + int32_t *decoded1 = ctx->decoded[1]; + + if (ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) { + /* We are pure silence, so we're done. */ + av_log(ctx->avctx, AV_LOG_DEBUG, "pure silence stereo\n"); + return; + } + + ctx->entropy_decode_stereo(ctx, count); + + /* Now apply the predictor decoding */ + ctx->predictor_decode_stereo(ctx, count); + + /* Decorrelate and scale to output depth */ + while (count--) { + left = *decoded1 - (*decoded0 / 2); + right = left + *decoded0; + + *(decoded0++) = left; + *(decoded1++) = right; + } +} + +static int ape_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + APEContext *s = avctx->priv_data; + uint8_t *sample8; + int16_t *sample16; + int32_t *sample24; + int i, ch, ret; + int blockstodecode; + + /* this should never be negative, but bad things will happen if it is, so + check it just to make sure. */ + av_assert0(s->samples >= 0); + + if(!s->samples){ + uint32_t nblocks, offset; + int buf_size; + + if (!avpkt->size) { + *got_frame_ptr = 0; + return 0; + } + if (avpkt->size < 8) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + buf_size = avpkt->size & ~3; + if (buf_size != avpkt->size) { + av_log(avctx, AV_LOG_WARNING, "packet size is not a multiple of 4. " + "extra bytes at the end will be skipped.\n"); + } + if (s->fileversion < 3950) // previous versions overread two bytes + buf_size += 2; + av_fast_malloc(&s->data, &s->data_size, buf_size); + if (!s->data) + return AVERROR(ENOMEM); + s->dsp.bswap_buf((uint32_t*)s->data, (const uint32_t*)buf, buf_size >> 2); + memset(s->data + (buf_size & ~3), 0, buf_size & 3); + s->ptr = s->data; + s->data_end = s->data + buf_size; + + nblocks = bytestream_get_be32(&s->ptr); + offset = bytestream_get_be32(&s->ptr); + if (offset > 3) { + av_log(avctx, AV_LOG_ERROR, "Incorrect offset passed\n"); + s->data = NULL; + return AVERROR_INVALIDDATA; + } + if (s->data_end - s->ptr < offset) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + s->ptr += offset; + + if (!nblocks || nblocks > INT_MAX) { + av_log(avctx, AV_LOG_ERROR, "Invalid sample count: %u.\n", nblocks); + return AVERROR_INVALIDDATA; + } + s->samples = nblocks; + + /* Initialize the frame decoder */ + if (init_frame_decoder(s) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error reading frame header\n"); + return AVERROR_INVALIDDATA; + } + } + + if (!s->data) { + *got_frame_ptr = 0; + return avpkt->size; + } + + blockstodecode = FFMIN(s->blocks_per_loop, s->samples); + + /* reallocate decoded sample buffer if needed */ + av_fast_malloc(&s->decoded_buffer, &s->decoded_size, + 2 * FFALIGN(blockstodecode, 8) * sizeof(*s->decoded_buffer)); + if (!s->decoded_buffer) + return AVERROR(ENOMEM); + memset(s->decoded_buffer, 0, s->decoded_size); + s->decoded[0] = s->decoded_buffer; + s->decoded[1] = s->decoded_buffer + FFALIGN(blockstodecode, 8); + + /* get output buffer */ + frame->nb_samples = blockstodecode; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + s->error=0; + + if ((s->channels == 1) || (s->frameflags & APE_FRAMECODE_PSEUDO_STEREO)) + ape_unpack_mono(s, blockstodecode); + else + ape_unpack_stereo(s, blockstodecode); + emms_c(); + + if (s->error) { + s->samples=0; + av_log(avctx, AV_LOG_ERROR, "Error decoding frame\n"); + return AVERROR_INVALIDDATA; + } + + switch (s->bps) { + case 8: + for (ch = 0; ch < s->channels; ch++) { + sample8 = (uint8_t *)frame->data[ch]; + for (i = 0; i < blockstodecode; i++) + *sample8++ = (s->decoded[ch][i] + 0x80) & 0xff; + } + break; + case 16: + for (ch = 0; ch < s->channels; ch++) { + sample16 = (int16_t *)frame->data[ch]; + for (i = 0; i < blockstodecode; i++) + *sample16++ = s->decoded[ch][i]; + } + break; + case 24: + for (ch = 0; ch < s->channels; ch++) { + sample24 = (int32_t *)frame->data[ch]; + for (i = 0; i < blockstodecode; i++) + *sample24++ = s->decoded[ch][i] << 8; + } + break; + } + + s->samples -= blockstodecode; + + *got_frame_ptr = 1; + + return !s->samples ? avpkt->size : 0; +} + +static void ape_flush(AVCodecContext *avctx) +{ + APEContext *s = avctx->priv_data; + s->samples= 0; +} + +#define OFFSET(x) offsetof(APEContext, x) +#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) +static const AVOption options[] = { + { "max_samples", "maximum number of samples decoded per call", OFFSET(blocks_per_loop), AV_OPT_TYPE_INT, { .i64 = 4608 }, 1, INT_MAX, PAR, "max_samples" }, + { "all", "no maximum. decode all samples for each packet at once", 0, AV_OPT_TYPE_CONST, { .i64 = INT_MAX }, INT_MIN, INT_MAX, PAR, "max_samples" }, + { NULL}, +}; + +static const AVClass ape_decoder_class = { + .class_name = "APE decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_ape_decoder = { + .name = "ape", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_APE, + .priv_data_size = sizeof(APEContext), + .init = ape_decode_init, + .close = ape_decode_close, + .decode = ape_decode_frame, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY | CODEC_CAP_DR1, + .flush = ape_flush, + .long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, + .priv_class = &ape_decoder_class, +}; diff --git a/ffmpeg/libavcodec/arm/Makefile b/ffmpeg/libavcodec/arm/Makefile new file mode 100644 index 0000000..011404c --- /dev/null +++ b/ffmpeg/libavcodec/arm/Makefile @@ -0,0 +1,116 @@ +ARCH_HEADERS = mathops.h + +OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_init_arm.o \ + arm/ac3dsp_arm.o + +OBJS-$(CONFIG_AAC_DECODER) += arm/sbrdsp_init_arm.o \ + arm/aacpsdsp_init_arm.o + +OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_init_arm.o \ + +ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o + +OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \ + arm/flacdsp_arm.o \ + +OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_init_arm.o +ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o + +OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_arm.o +OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o +OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_init_arm.o +OBJS-$(CONFIG_VP5_DECODER) += arm/vp56dsp_init_arm.o +OBJS-$(CONFIG_VP6_DECODER) += arm/vp56dsp_init_arm.o +OBJS-$(CONFIG_VP8_DECODER) += arm/vp8dsp_init_arm.o +ARMV6-OBJS-$(CONFIG_VP8_DECODER) += arm/vp8_armv6.o \ + arm/vp8dsp_init_armv6.o \ + arm/vp8dsp_armv6.o + +OBJS-$(CONFIG_H264CHROMA) += arm/h264chroma_init_arm.o +OBJS-$(CONFIG_H264DSP) += arm/h264dsp_init_arm.o +OBJS-$(CONFIG_H264PRED) += arm/h264pred_init_arm.o +OBJS-$(CONFIG_H264QPEL) += arm/h264qpel_init_arm.o + +OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_arm.o \ + arm/hpeldsp_init_arm.o + +OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_init_arm.o +OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_init_arm.o \ + arm/rv40dsp_init_arm.o \ + +OBJS-$(CONFIG_VIDEODSP) += arm/videodsp_init_arm.o \ + +OBJS += arm/dsputil_init_arm.o \ + arm/dsputil_arm.o \ + arm/fft_init_arm.o \ + arm/fft_fixed_init_arm.o \ + arm/fmtconvert_init_arm.o \ + arm/jrevdct_arm.o \ + arm/simple_idct_arm.o \ + +ARMV5TE-OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_armv5te.o \ + arm/mpegvideo_armv5te_s.o \ + +ARMV5TE-OBJS-$(CONFIG_VIDEODSP) += arm/videodsp_init_armv5te.o \ + arm/videodsp_armv5te.o \ + +ARMV5TE-OBJS += arm/dsputil_init_armv5te.o \ + arm/simple_idct_armv5te.o \ + +ARMV6-OBJS += arm/dsputil_init_armv6.o \ + arm/dsputil_armv6.o \ + arm/simple_idct_armv6.o \ + +ARMV6-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_armv6.o \ + arm/hpeldsp_init_armv6.o + +VFP-OBJS-$(HAVE_ARMV6) += arm/fmtconvert_vfp.o + +NEON-OBJS-$(CONFIG_FFT) += arm/fft_neon.o \ + arm/fft_fixed_neon.o \ + +NEON-OBJS-$(CONFIG_MDCT) += arm/mdct_neon.o \ + arm/mdct_fixed_neon.o \ + +NEON-OBJS-$(CONFIG_RDFT) += arm/rdft_neon.o \ + +NEON-OBJS-$(CONFIG_H264CHROMA) += arm/h264cmc_neon.o +NEON-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_neon.o \ + arm/h264idct_neon.o \ + +NEON-OBJS-$(CONFIG_H264PRED) += arm/h264pred_neon.o \ + +NEON-OBJS-$(CONFIG_H264QPEL) += arm/h264qpel_neon.o \ + +NEON-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_neon.o \ + arm/hpeldsp_init_neon.o + +NEON-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_neon.o + +NEON-OBJS-$(CONFIG_AAC_DECODER) += arm/sbrdsp_neon.o \ + arm/aacpsdsp_neon.o + +NEON-OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_neon.o \ + arm/synth_filter_neon.o \ + +NEON-OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_neon.o +NEON-OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_neon.o +NEON-OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_neon.o \ + arm/rv40dsp_neon.o \ + +NEON-OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_neon.o + +NEON-OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_neon.o + +NEON-OBJS-$(CONFIG_VP5_DECODER) += arm/vp56dsp_neon.o \ + +NEON-OBJS-$(CONFIG_VP6_DECODER) += arm/vp56dsp_neon.o \ + +NEON-OBJS-$(CONFIG_VP8_DECODER) += arm/vp8dsp_init_neon.o \ + arm/vp8dsp_neon.o + +NEON-OBJS += arm/dsputil_init_neon.o \ + arm/dsputil_neon.o \ + arm/fmtconvert_neon.o \ + arm/int_neon.o \ + arm/simple_idct_neon.o \ diff --git a/ffmpeg/libavcodec/arm/aac.h b/ffmpeg/libavcodec/arm/aac.h new file mode 100644 index 0000000..cafa881 --- /dev/null +++ b/ffmpeg/libavcodec/arm/aac.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_ARM_AAC_H +#define AVCODEC_ARM_AAC_H + +#include "config.h" + +#if HAVE_NEON_INLINE + +#define VMUL2 VMUL2 +static inline float *VMUL2(float *dst, const float *v, unsigned idx, + const float *scale) +{ + unsigned v0, v1; + __asm__ ("ubfx %0, %6, #0, #4 \n\t" + "ubfx %1, %6, #4, #4 \n\t" + "ldr %0, [%5, %0, lsl #2] \n\t" + "ldr %1, [%5, %1, lsl #2] \n\t" + "vld1.32 {d1[]}, [%7,:32] \n\t" + "vmov d0, %0, %1 \n\t" + "vmul.f32 d0, d0, d1 \n\t" + "vst1.32 {d0}, [%2,:64]! \n\t" + : "=&r"(v0), "=&r"(v1), "+r"(dst), "=m"(dst[0]), "=m"(dst[1]) + : "r"(v), "r"(idx), "r"(scale) + : "d0", "d1"); + return dst; +} + +#define VMUL4 VMUL4 +static inline float *VMUL4(float *dst, const float *v, unsigned idx, + const float *scale) +{ + unsigned v0, v1, v2, v3; + __asm__ ("ubfx %0, %10, #0, #2 \n\t" + "ubfx %1, %10, #2, #2 \n\t" + "ldr %0, [%9, %0, lsl #2] \n\t" + "ubfx %2, %10, #4, #2 \n\t" + "ldr %1, [%9, %1, lsl #2] \n\t" + "ubfx %3, %10, #6, #2 \n\t" + "ldr %2, [%9, %2, lsl #2] \n\t" + "vmov d0, %0, %1 \n\t" + "ldr %3, [%9, %3, lsl #2] \n\t" + "vld1.32 {d2[],d3[]},[%11,:32] \n\t" + "vmov d1, %2, %3 \n\t" + "vmul.f32 q0, q0, q1 \n\t" + "vst1.32 {q0}, [%4,:128]! \n\t" + : "=&r"(v0), "=&r"(v1), "=&r"(v2), "=&r"(v3), "+r"(dst), + "=m"(dst[0]), "=m"(dst[1]), "=m"(dst[2]), "=m"(dst[3]) + : "r"(v), "r"(idx), "r"(scale) + : "d0", "d1", "d2", "d3"); + return dst; +} + +#define VMUL2S VMUL2S +static inline float *VMUL2S(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + unsigned v0, v1, v2, v3; + __asm__ ("ubfx %0, %8, #0, #4 \n\t" + "ubfx %1, %8, #4, #4 \n\t" + "ldr %0, [%7, %0, lsl #2] \n\t" + "lsl %2, %10, #30 \n\t" + "ldr %1, [%7, %1, lsl #2] \n\t" + "lsl %3, %10, #31 \n\t" + "vmov d0, %0, %1 \n\t" + "bic %2, %2, #1<<30 \n\t" + "vld1.32 {d1[]}, [%9,:32] \n\t" + "vmov d2, %2, %3 \n\t" + "veor d0, d0, d2 \n\t" + "vmul.f32 d0, d0, d1 \n\t" + "vst1.32 {d0}, [%4,:64]! \n\t" + : "=&r"(v0), "=&r"(v1), "=&r"(v2), "=&r"(v3), "+r"(dst), + "=m"(dst[0]), "=m"(dst[1]) + : "r"(v), "r"(idx), "r"(scale), "r"(sign) + : "d0", "d1", "d2"); + return dst; +} + +#define VMUL4S VMUL4S +static inline float *VMUL4S(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + unsigned v0, v1, v2, v3, nz; + __asm__ ("vld1.32 {d2[],d3[]},[%13,:32] \n\t" + "ubfx %0, %12, #0, #2 \n\t" + "ubfx %1, %12, #2, #2 \n\t" + "ldr %0, [%11,%0, lsl #2] \n\t" + "ubfx %2, %12, #4, #2 \n\t" + "ldr %1, [%11,%1, lsl #2] \n\t" + "ubfx %3, %12, #6, #2 \n\t" + "ldr %2, [%11,%2, lsl #2] \n\t" + "vmov d0, %0, %1 \n\t" + "ldr %3, [%11,%3, lsl #2] \n\t" + "lsr %6, %12, #12 \n\t" + "rbit %6, %6 \n\t" + "vmov d1, %2, %3 \n\t" + "lsls %6, %6, #1 \n\t" + "and %0, %5, #1<<31 \n\t" + "it cs \n\t" + "lslcs %5, %5, #1 \n\t" + "lsls %6, %6, #1 \n\t" + "and %1, %5, #1<<31 \n\t" + "it cs \n\t" + "lslcs %5, %5, #1 \n\t" + "lsls %6, %6, #1 \n\t" + "and %2, %5, #1<<31 \n\t" + "it cs \n\t" + "lslcs %5, %5, #1 \n\t" + "vmov d4, %0, %1 \n\t" + "and %3, %5, #1<<31 \n\t" + "vmov d5, %2, %3 \n\t" + "veor q0, q0, q2 \n\t" + "vmul.f32 q0, q0, q1 \n\t" + "vst1.32 {q0}, [%4,:128]! \n\t" + : "=&r"(v0), "=&r"(v1), "=&r"(v2), "=&r"(v3), "+r"(dst), + "+r"(sign), "=r"(nz), + "=m"(dst[0]), "=m"(dst[1]), "=m"(dst[2]), "=m"(dst[3]) + : "r"(v), "r"(idx), "r"(scale) + : "cc", "d0", "d1", "d2", "d3", "d4", "d5"); + return dst; +} + +#endif /* HAVE_NEON_INLINE */ + +#endif /* AVCODEC_ARM_AAC_H */ diff --git a/ffmpeg/libavcodec/arm/aacpsdsp_init_arm.c b/ffmpeg/libavcodec/arm/aacpsdsp_init_arm.c new file mode 100644 index 0000000..6326376 --- /dev/null +++ b/ffmpeg/libavcodec/arm/aacpsdsp_init_arm.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "libavutil/arm/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/aacpsdsp.h" + +void ff_ps_add_squares_neon(float *dst, const float (*src)[2], int n); +void ff_ps_mul_pair_single_neon(float (*dst)[2], float (*src0)[2], + float *src1, int n); +void ff_ps_hybrid_analysis_neon(float (*out)[2], float (*in)[2], + const float (*filter)[8][2], + int stride, int n); +void ff_ps_hybrid_analysis_ileave_neon(float (*out)[32][2], float L[2][38][64], + int i, int len); +void ff_ps_hybrid_synthesis_deint_neon(float out[2][38][64], float (*in)[32][2], + int i, int len); +void ff_ps_decorrelate_neon(float (*out)[2], float (*delay)[2], + float (*ap_delay)[PS_QMF_TIME_SLOTS+PS_MAX_AP_DELAY][2], + const float phi_fract[2], float (*Q_fract)[2], + const float *transient_gain, float g_decay_slope, + int len); +void ff_ps_stereo_interpolate_neon(float (*l)[2], float (*r)[2], + float h[2][4], float h_step[2][4], + int len); + +av_cold void ff_psdsp_init_arm(PSDSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->add_squares = ff_ps_add_squares_neon; + s->mul_pair_single = ff_ps_mul_pair_single_neon; + s->hybrid_synthesis_deint = ff_ps_hybrid_synthesis_deint_neon; + s->hybrid_analysis = ff_ps_hybrid_analysis_neon; + s->stereo_interpolate[0] = ff_ps_stereo_interpolate_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/aacpsdsp_neon.S b/ffmpeg/libavcodec/arm/aacpsdsp_neon.S new file mode 100644 index 0000000..fb00900 --- /dev/null +++ b/ffmpeg/libavcodec/arm/aacpsdsp_neon.S @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_ps_add_squares_neon, export=1 + mov r3, r0 + sub r2, r2, #4 + vld1.32 {q0}, [r1,:128]! + vmul.f32 q0, q0, q0 + vld1.32 {q2}, [r1,:128]! + vmul.f32 q2, q2, q2 + vld1.32 {q1}, [r0,:128]! +1: + vpadd.f32 d6, d0, d1 + vld1.32 {q0}, [r1,:128]! + vpadd.f32 d7, d4, d5 + vmul.f32 q0, q0, q0 + vld1.32 {q2}, [r1,:128]! + vadd.f32 q3, q1, q3 + vld1.32 {q1}, [r0,:128]! + vmul.f32 q2, q2, q2 + vst1.32 {q3}, [r3,:128]! + subs r2, r2, #4 + bgt 1b + vpadd.f32 d6, d0, d1 + vpadd.f32 d7, d4, d5 + vadd.f32 q1, q1, q3 + vst1.32 {q1}, [r3,:128]! + bx lr +endfunc + +function ff_ps_mul_pair_single_neon, export=1 + sub r3, r3, #4 + tst r1, #8 + bne 2f + vld1.32 {q0}, [r1,:128]! +1: + vld1.32 {q3}, [r2,:128]! + vmul.f32 d4, d0, d6[0] + vmul.f32 d5, d1, d6[1] + vld1.32 {q1}, [r1,:128]! + vmul.f32 d6, d2, d7[0] + vmul.f32 d7, d3, d7[1] + vld1.32 {q0}, [r1,:128]! + vst1.32 {q2,q3}, [r0,:128]! + subs r3, r3, #4 + bgt 1b + vld1.32 {q3}, [r2,:128]! + vmul.f32 d4, d0, d6[0] + vmul.f32 d5, d1, d6[1] + vld1.32 {q1}, [r1,:128]! + vmul.f32 d6, d2, d7[0] + vmul.f32 d7, d3, d7[1] + vst1.32 {q2,q3}, [r0,:128]! + bx lr +2: + vld1.32 {d0}, [r1,:64]! + vld1.32 {d1,d2}, [r1,:128]! +1: + vld1.32 {q3}, [r2,:128]! + vmul.f32 d4, d0, d6[0] + vmul.f32 d5, d1, d6[1] + vld1.32 {d0,d1}, [r1,:128]! + vmul.f32 d6, d2, d7[0] + vmul.f32 d7, d0, d7[1] + vmov d0, d1 + vld1.32 {d1,d2}, [r1,:128]! + vst1.32 {q2,q3}, [r0,:128]! + subs r3, r3, #4 + bgt 1b + vld1.32 {q3}, [r2,:128]! + vmul.f32 d4, d0, d6[0] + vmul.f32 d5, d1, d6[1] + vld1.32 {d0}, [r1,:64]! + vmul.f32 d6, d2, d7[0] + vmul.f32 d7, d0, d7[1] + vst1.32 {q2,q3}, [r0,:128]! + bx lr +endfunc + +function ff_ps_hybrid_synthesis_deint_neon, export=1 + push {r4-r8,lr} + add r0, r0, r2, lsl #2 + add r1, r1, r2, lsl #5+1+2 + rsb r2, r2, #64 + mov r5, #64*4 + mov lr, r0 + add r4, r0, #38*64*4 + mov r12, r3 +2: + vld1.32 {d0,d1}, [r1,:128]! + vst1.32 {d0[0]}, [lr,:32], r5 + vst1.32 {d0[1]}, [r4,:32], r5 + vst1.32 {d1[0]}, [lr,:32], r5 + vst1.32 {d1[1]}, [r4,:32], r5 + subs r12, r12, #2 + bgt 2b + add r0, r0, #4 + sub r2, r2, #1 + tst r2, #2 + bne 6f +1: + mov lr, r0 + add r4, r0, #38*64*4 + add r6, r1, # 32*2*4 + add r7, r1, #2*32*2*4 + add r8, r1, #3*32*2*4 + mov r12, r3 +2: + vld1.32 {d0,d1}, [r1,:128]! + vld1.32 {d2,d3}, [r6,:128]! + vld1.32 {d4,d5}, [r7,:128]! + vld1.32 {d6,d7}, [r8,:128]! + vst4.32 {d0[0],d2[0],d4[0],d6[0]}, [lr,:128], r5 + vst4.32 {d0[1],d2[1],d4[1],d6[1]}, [r4,:128], r5 + vst4.32 {d1[0],d3[0],d5[0],d7[0]}, [lr,:128], r5 + vst4.32 {d1[1],d3[1],d5[1],d7[1]}, [r4,:128], r5 + subs r12, r12, #2 + bgt 2b + add r0, r0, #16 + add r1, r1, #3*32*2*4 + subs r2, r2, #4 + bgt 1b + pop {r4-r8,pc} +6: + mov lr, r0 + add r4, r0, #38*64*4 + add r6, r1, #32*2*4 + mov r12, r3 +2: + vld1.32 {d0,d1}, [r1,:128]! + vld1.32 {d2,d3}, [r6,:128]! + vst2.32 {d0[0],d2[0]}, [lr,:64], r5 + vst2.32 {d0[1],d2[1]}, [r4,:64], r5 + vst2.32 {d1[0],d3[0]}, [lr,:64], r5 + vst2.32 {d1[1],d3[1]}, [r4,:64], r5 + subs r12, r12, #2 + bgt 2b + add r0, r0, #8 + add r1, r1, #32*2*4 + sub r2, r2, #2 + b 1b +endfunc + +function ff_ps_hybrid_analysis_neon, export=1 + vldm r1, {d19-d31} + ldr r12, [sp] + lsl r3, r3, #3 + vadd.f32 d16, d19, d31 + vadd.f32 d17, d20, d30 + vsub.f32 d18, d19, d31 + vsub.f32 d19, d20, d30 + vsub.f32 d0, d21, d29 + vsub.f32 d1, d22, d28 + vadd.f32 d2, d21, d29 + vadd.f32 d3, d22, d28 + vadd.f32 d20, d23, d27 + vadd.f32 d21, d24, d26 + vsub.f32 d22, d23, d27 + vsub.f32 d23, d24, d26 + vmov.i32 d6, #1<<31 + vmov.i32 d7, #0 + vmov.f32 q14, #0.0 + vmov.f32 q15, #0.0 + vtrn.32 d6, d7 + vrev64.32 q9, q9 + vrev64.32 q0, q0 + vrev64.32 q11, q11 + veor q9, q9, q3 + veor q0, q0, q3 + veor q11, q11, q3 + vld1.32 {q13}, [r2,:128]! + vtrn.32 q8, q9 + vtrn.32 q1, q0 + vtrn.32 q10, q11 + sub r12, r12, #1 + vmla.f32 q14, q8, q13 + vld1.32 {q2}, [r2,:128]! + vmla.f32 q15, q9, q13 +1: + vmla.f32 q14, q1, q2 + vld1.32 {q13}, [r2,:128]! + vmla.f32 q15, q0, q2 + vmla.f32 q14, q10, q13 + vld1.32 {q2}, [r2,:128]! + vmla.f32 q15, q11, q13 + vld1.32 {q13}, [r2,:128]! + vadd.f32 d6, d28, d29 + vadd.f32 d7, d30, d31 + vmov.f32 q14, #0.0 + vmov.f32 q15, #0.0 + vmla.f32 q14, q8, q13 + vpadd.f32 d6, d6, d7 + vmla.f32 q15, q9, q13 + vmla.f32 d6, d25, d4[0] + vld1.32 {q2}, [r2,:128]! + vst1.32 {d6}, [r0,:64], r3 + subs r12, r12, #1 + bgt 1b + vmla.f32 q14, q1, q2 + vld1.32 {q13}, [r2,:128]! + vmla.f32 q15, q0, q2 + vmla.f32 q14, q10, q13 + vld1.32 {q2}, [r2,:128]! + vmla.f32 q15, q11, q13 + vadd.f32 d6, d28, d29 + vadd.f32 d7, d30, d31 + vpadd.f32 d6, d6, d7 + vmla.f32 d6, d25, d4[0] + vst1.32 {d6}, [r0,:64], r3 + bx lr +endfunc + +function ff_ps_stereo_interpolate_neon, export=1 + vld1.32 {q0}, [r2] + vld1.32 {q14}, [r3] + vadd.f32 q15, q14, q14 + mov r2, r0 + mov r3, r1 + ldr r12, [sp] + vadd.f32 q1, q0, q14 + vadd.f32 q0, q0, q15 + vld1.32 {q2}, [r0,:64]! + vld1.32 {q3}, [r1,:64]! + subs r12, r12, #1 + beq 2f +1: + vmul.f32 d16, d4, d2[0] + vmul.f32 d17, d5, d0[0] + vmul.f32 d18, d4, d2[1] + vmul.f32 d19, d5, d0[1] + vmla.f32 d16, d6, d3[0] + vmla.f32 d17, d7, d1[0] + vmla.f32 d18, d6, d3[1] + vmla.f32 d19, d7, d1[1] + vadd.f32 q1, q1, q15 + vadd.f32 q0, q0, q15 + vld1.32 {q2}, [r0,:64]! + vld1.32 {q3}, [r1,:64]! + vst1.32 {q8}, [r2,:64]! + vst1.32 {q9}, [r3,:64]! + subs r12, r12, #2 + bgt 1b + it lt + bxlt lr +2: + vmul.f32 d16, d4, d2[0] + vmul.f32 d18, d4, d2[1] + vmla.f32 d16, d6, d3[0] + vmla.f32 d18, d6, d3[1] + vst1.32 {d16}, [r2,:64]! + vst1.32 {d18}, [r3,:64]! + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/ac3dsp_arm.S b/ffmpeg/libavcodec/arm/ac3dsp_arm.S new file mode 100644 index 0000000..ed8eb37 --- /dev/null +++ b/ffmpeg/libavcodec/arm/ac3dsp_arm.S @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_ac3_update_bap_counts_arm, export=1 + push {lr} + ldrb lr, [r1], #1 +1: + lsl r3, lr, #1 + ldrh r12, [r0, r3] + subs r2, r2, #1 + it gt + ldrbgt lr, [r1], #1 + add r12, r12, #1 + strh r12, [r0, r3] + bgt 1b + pop {pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/ac3dsp_armv6.S b/ffmpeg/libavcodec/arm/ac3dsp_armv6.S new file mode 100644 index 0000000..2028d0b --- /dev/null +++ b/ffmpeg/libavcodec/arm/ac3dsp_armv6.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_ac3_bit_alloc_calc_bap_armv6, export=1 + ldr r12, [sp] + cmp r12, #-960 + beq 4f + push {r4-r11,lr} + add r5, sp, #40 + movrelx r4, X(ff_ac3_bin_to_band_tab), r11 + movrelx lr, X(ff_ac3_band_start_tab) + ldm r5, {r5-r7} + ldrb r4, [r4, r2] + add r1, r1, r2, lsl #1 @ psd + start + add r0, r0, r4, lsl #1 @ mask + band + add r4, r4, lr + add r7, r7, r2 @ bap + start +1: + ldrsh r9, [r0], #2 @ mask[band] + mov r8, #0xff0 + sub r9, r9, r12 @ - snr_offset + ldrb r10, [r4, #1]! @ band_start_tab[++band] + subs r9, r9, r5 @ - floor + it lt + movlt r9, #0 + cmp r10, r3 @ - end + and r9, r9, r8, lsl #1 @ & 0x1fe0 + ite gt + subgt r8, r3, r2 + suble r8, r10, r2 + mov r2, r10 + add r9, r9, r5 @ + floor => m + tst r8, #1 + add r11, r7, r8 + bne 3f + b 5f +2: + ldrsh r8, [r1], #2 + ldrsh lr, [r1], #2 + sub r8, r8, r9 + sub lr, lr, r9 + usat r8, #6, r8, asr #5 @ address + usat lr, #6, lr, asr #5 + ldrb r8, [r6, r8] @ bap_tab[address] + ldrb lr, [r6, lr] + strb r8, [r7], #1 @ bap[bin] + strb lr, [r7], #1 +5: cmp r7, r11 + blo 2b + cmp r3, r10 + bgt 1b + pop {r4-r11,pc} +3: + ldrsh r8, [r1], #2 @ psd[bin] + sub r8, r8, r9 @ - m + usat r8, #6, r8, asr #5 @ address + ldrb r8, [r6, r8] @ bap_tab[address] + strb r8, [r7], #1 @ bap[bin] + b 5b +4: + ldr r0, [sp, #12] + mov r1, #0 + mov r2, #256 + b X(memset) +endfunc diff --git a/ffmpeg/libavcodec/arm/ac3dsp_init_arm.c b/ffmpeg/libavcodec/arm/ac3dsp_init_arm.c new file mode 100644 index 0000000..ffe0747 --- /dev/null +++ b/ffmpeg/libavcodec/arm/ac3dsp_init_arm.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * 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 "libavutil/arm/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/ac3dsp.h" +#include "config.h" + +void ff_ac3_exponent_min_neon(uint8_t *exp, int num_reuse_blocks, int nb_coefs); +int ff_ac3_max_msb_abs_int16_neon(const int16_t *src, int len); +void ff_ac3_lshift_int16_neon(int16_t *src, unsigned len, unsigned shift); +void ff_ac3_rshift_int32_neon(int32_t *src, unsigned len, unsigned shift); +void ff_float_to_fixed24_neon(int32_t *dst, const float *src, unsigned int len); +void ff_ac3_extract_exponents_neon(uint8_t *exp, int32_t *coef, int nb_coefs); +void ff_ac3_sum_square_butterfly_int32_neon(int64_t sum[4], + const int32_t *coef0, + const int32_t *coef1, + int len); +void ff_ac3_sum_square_butterfly_float_neon(float sum[4], + const float *coef0, + const float *coef1, + int len); + +void ff_ac3_bit_alloc_calc_bap_armv6(int16_t *mask, int16_t *psd, + int start, int end, + int snr_offset, int floor, + const uint8_t *bap_tab, uint8_t *bap); + +void ff_ac3_update_bap_counts_arm(uint16_t mant_cnt[16], uint8_t *bap, int len); + +av_cold void ff_ac3dsp_init_arm(AC3DSPContext *c, int bit_exact) +{ + int cpu_flags = av_get_cpu_flags(); + + c->update_bap_counts = ff_ac3_update_bap_counts_arm; + + if (have_armv6(cpu_flags)) { + c->bit_alloc_calc_bap = ff_ac3_bit_alloc_calc_bap_armv6; + } + + if (have_neon(cpu_flags)) { + c->ac3_exponent_min = ff_ac3_exponent_min_neon; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_neon; + c->ac3_lshift_int16 = ff_ac3_lshift_int16_neon; + c->ac3_rshift_int32 = ff_ac3_rshift_int32_neon; + c->float_to_fixed24 = ff_float_to_fixed24_neon; + c->extract_exponents = ff_ac3_extract_exponents_neon; + c->sum_square_butterfly_int32 = ff_ac3_sum_square_butterfly_int32_neon; + c->sum_square_butterfly_float = ff_ac3_sum_square_butterfly_float_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/ac3dsp_neon.S b/ffmpeg/libavcodec/arm/ac3dsp_neon.S new file mode 100644 index 0000000..42f35e3 --- /dev/null +++ b/ffmpeg/libavcodec/arm/ac3dsp_neon.S @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_ac3_max_msb_abs_int16_neon, export=1 + vmov.i16 q0, #0 + vmov.i16 q2, #0 +1: vld1.16 {q1}, [r0,:128]! + vabs.s16 q1, q1 + vld1.16 {q3}, [r0,:128]! + vabs.s16 q3, q3 + vorr q0, q0, q1 + vorr q2, q2, q3 + subs r1, r1, #16 + bgt 1b + vorr q0, q0, q2 + vorr d0, d0, d1 + vpmax.u16 d0, d0, d0 + vpmax.u16 d0, d0, d0 + vmov.u16 r0, d0[0] + bx lr +endfunc + +function ff_ac3_exponent_min_neon, export=1 + cmp r1, #0 + it eq + bxeq lr + push {lr} + mov r12, #256 +1: + vld1.8 {q0}, [r0,:128] + mov lr, r1 + add r3, r0, #256 +2: vld1.8 {q1}, [r3,:128], r12 + subs lr, lr, #1 + vmin.u8 q0, q0, q1 + bgt 2b + subs r2, r2, #16 + vst1.8 {q0}, [r0,:128]! + bgt 1b + pop {pc} +endfunc + +function ff_ac3_lshift_int16_neon, export=1 + vdup.16 q0, r2 +1: vld1.16 {q1}, [r0,:128] + vshl.s16 q1, q1, q0 + vst1.16 {q1}, [r0,:128]! + subs r1, r1, #8 + bgt 1b + bx lr +endfunc + +function ff_ac3_rshift_int32_neon, export=1 + rsb r2, r2, #0 + vdup.32 q0, r2 +1: vld1.32 {q1}, [r0,:128] + vshl.s32 q1, q1, q0 + vst1.32 {q1}, [r0,:128]! + subs r1, r1, #4 + bgt 1b + bx lr +endfunc + +function ff_float_to_fixed24_neon, export=1 +1: vld1.32 {q0-q1}, [r1,:128]! + vcvt.s32.f32 q0, q0, #24 + vld1.32 {q2-q3}, [r1,:128]! + vcvt.s32.f32 q1, q1, #24 + vcvt.s32.f32 q2, q2, #24 + vst1.32 {q0-q1}, [r0,:128]! + vcvt.s32.f32 q3, q3, #24 + vst1.32 {q2-q3}, [r0,:128]! + subs r2, r2, #16 + bgt 1b + bx lr +endfunc + +function ff_ac3_extract_exponents_neon, export=1 + vmov.i32 q15, #8 +1: + vld1.32 {q0}, [r1,:128]! + vabs.s32 q1, q0 + vclz.i32 q3, q1 + vsub.i32 q3, q3, q15 + vmovn.i32 d6, q3 + vmovn.i16 d6, q3 + vst1.32 {d6[0]}, [r0,:32]! + subs r2, r2, #4 + bgt 1b + bx lr +endfunc + +function ff_ac3_sum_square_butterfly_int32_neon, export=1 + vmov.i64 q0, #0 + vmov.i64 q1, #0 + vmov.i64 q2, #0 + vmov.i64 q3, #0 +1: + vld1.32 {d16}, [r1]! + vld1.32 {d17}, [r2]! + vadd.s32 d18, d16, d17 + vsub.s32 d19, d16, d17 + vmlal.s32 q0, d16, d16 + vmlal.s32 q1, d17, d17 + vmlal.s32 q2, d18, d18 + vmlal.s32 q3, d19, d19 + subs r3, r3, #2 + bgt 1b + vadd.s64 d0, d0, d1 + vadd.s64 d1, d2, d3 + vadd.s64 d2, d4, d5 + vadd.s64 d3, d6, d7 + vst1.64 {q0-q1}, [r0] + bx lr +endfunc + +function ff_ac3_sum_square_butterfly_float_neon, export=1 + vmov.f32 q0, #0.0 + vmov.f32 q1, #0.0 +1: + vld1.32 {d16}, [r1]! + vld1.32 {d17}, [r2]! + vadd.f32 d18, d16, d17 + vsub.f32 d19, d16, d17 + vmla.f32 d0, d16, d16 + vmla.f32 d1, d17, d17 + vmla.f32 d2, d18, d18 + vmla.f32 d3, d19, d19 + subs r3, r3, #2 + bgt 1b + vpadd.f32 d0, d0, d1 + vpadd.f32 d1, d2, d3 + vst1.32 {q0}, [r0] + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/asm-offsets.h b/ffmpeg/libavcodec/arm/asm-offsets.h new file mode 100644 index 0000000..5cfc5cb --- /dev/null +++ b/ffmpeg/libavcodec/arm/asm-offsets.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_ARM_ASM_OFFSETS_H +#define AVCODEC_ARM_ASM_OFFSETS_H + +#ifndef __ASSEMBLER__ +#include +#define CHK_OFFS(s, m, o) struct check_##o { \ + int x_##o[offsetof(s, m) == o? 1: -1]; \ + } +#endif + +/* MpegEncContext */ +#define Y_DC_SCALE 0xa8 +#define C_DC_SCALE 0xac +#define AC_PRED 0xb0 +#define BLOCK_LAST_INDEX 0xb4 +#define H263_AIC 0xe4 +#define INTER_SCANTAB_RASTER_END 0x12c + +#endif /* AVCODEC_ARM_ASM_OFFSETS_H */ diff --git a/ffmpeg/libavcodec/arm/dca.h b/ffmpeg/libavcodec/arm/dca.h new file mode 100644 index 0000000..2cfd18a --- /dev/null +++ b/ffmpeg/libavcodec/arm/dca.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ARM_DCA_H +#define AVCODEC_ARM_DCA_H + +#include + +#include "config.h" +#include "libavcodec/mathops.h" + +#if HAVE_ARMV6_INLINE && AV_GCC_VERSION_AT_LEAST(4,4) && !CONFIG_THUMB + +#define decode_blockcodes decode_blockcodes +static inline int decode_blockcodes(int code1, int code2, int levels, + int *values) +{ + int v0, v1, v2, v3, v4, v5; + + __asm__ ("smmul %8, %14, %18 \n" + "smmul %11, %15, %18 \n" + "smlabb %14, %8, %17, %14 \n" + "smlabb %15, %11, %17, %15 \n" + "smmul %9, %8, %18 \n" + "smmul %12, %11, %18 \n" + "sub %14, %14, %16, lsr #1 \n" + "sub %15, %15, %16, lsr #1 \n" + "smlabb %8, %9, %17, %8 \n" + "smlabb %11, %12, %17, %11 \n" + "smmul %10, %9, %18 \n" + "smmul %13, %12, %18 \n" + "str %14, %0 \n" + "str %15, %4 \n" + "sub %8, %8, %16, lsr #1 \n" + "sub %11, %11, %16, lsr #1 \n" + "smlabb %9, %10, %17, %9 \n" + "smlabb %12, %13, %17, %12 \n" + "smmul %14, %10, %18 \n" + "smmul %15, %13, %18 \n" + "str %8, %1 \n" + "str %11, %5 \n" + "sub %9, %9, %16, lsr #1 \n" + "sub %12, %12, %16, lsr #1 \n" + "smlabb %10, %14, %17, %10 \n" + "smlabb %13, %15, %17, %13 \n" + "str %9, %2 \n" + "str %12, %6 \n" + "sub %10, %10, %16, lsr #1 \n" + "sub %13, %13, %16, lsr #1 \n" + "str %10, %3 \n" + "str %13, %7 \n" + : "=m"(values[0]), "=m"(values[1]), + "=m"(values[2]), "=m"(values[3]), + "=m"(values[4]), "=m"(values[5]), + "=m"(values[6]), "=m"(values[7]), + "=&r"(v0), "=&r"(v1), "=&r"(v2), + "=&r"(v3), "=&r"(v4), "=&r"(v5), + "+&r"(code1), "+&r"(code2) + : "r"(levels - 1), "r"(-levels), "r"(ff_inverse[levels])); + + return code1 | code2; +} + +#endif + +#if HAVE_NEON_INLINE && HAVE_ASM_MOD_Y + +#define int8x8_fmul_int32 int8x8_fmul_int32 +static inline void int8x8_fmul_int32(float *dst, const int8_t *src, int scale) +{ + __asm__ ("vcvt.f32.s32 %2, %2, #4 \n" + "vld1.8 {d0}, [%1,:64] \n" + "vmovl.s8 q0, d0 \n" + "vmovl.s16 q1, d1 \n" + "vmovl.s16 q0, d0 \n" + "vcvt.f32.s32 q0, q0 \n" + "vcvt.f32.s32 q1, q1 \n" + "vmul.f32 q0, q0, %y2 \n" + "vmul.f32 q1, q1, %y2 \n" + "vst1.32 {q0-q1}, [%m0,:128] \n" + : "=Um"(*(float (*)[8])dst) + : "r"(src), "x"(scale) + : "d0", "d1", "d2", "d3"); +} + +#endif + +#endif /* AVCODEC_ARM_DCA_H */ diff --git a/ffmpeg/libavcodec/arm/dcadsp_init_arm.c b/ffmpeg/libavcodec/arm/dcadsp_init_arm.c new file mode 100644 index 0000000..56568e0 --- /dev/null +++ b/ffmpeg/libavcodec/arm/dcadsp_init_arm.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 "config.h" + +#include "libavutil/arm/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/dcadsp.h" + +void ff_dca_lfe_fir_neon(float *out, const float *in, const float *coefs, + int decifactor, float scale); + +av_cold void ff_dcadsp_init_arm(DCADSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + s->lfe_fir = ff_dca_lfe_fir_neon; +} diff --git a/ffmpeg/libavcodec/arm/dcadsp_neon.S b/ffmpeg/libavcodec/arm/dcadsp_neon.S new file mode 100644 index 0000000..6a6c77a --- /dev/null +++ b/ffmpeg/libavcodec/arm/dcadsp_neon.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function ff_dca_lfe_fir_neon, export=1 + push {r4-r6,lr} + + add r4, r0, r3, lsl #2 @ out2 + add r5, r2, #256*4-16 @ cf1 + sub r1, r1, #12 + cmp r3, #32 + ite eq + moveq r6, #256/32 + movne r6, #256/64 +NOVFP vldr s0, [sp, #16] @ scale + mov lr, #-16 +1: + vmov.f32 q2, #0.0 @ v0 + vmov.f32 q3, #0.0 @ v1 + mov r12, r6 +2: + vld1.32 {q8}, [r2,:128]! @ cf0 + vld1.32 {q9}, [r5,:128], lr @ cf1 + vld1.32 {q1}, [r1], lr @ in + subs r12, r12, #4 + vrev64.32 q10, q8 + vmla.f32 q3, q1, q9 + vmla.f32 d4, d2, d21 + vmla.f32 d5, d3, d20 + bne 2b + + add r1, r1, r6, lsl #2 + subs r3, r3, #1 + vadd.f32 d4, d4, d5 + vadd.f32 d6, d6, d7 + vpadd.f32 d4, d4, d6 + vmul.f32 d5, d4, d0[0] + vst1.32 {d5[0]}, [r0,:32]! + vst1.32 {d5[1]}, [r4,:32]! + bne 1b + + pop {r4-r6,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/dsputil_arm.S b/ffmpeg/libavcodec/arm/dsputil_arm.S new file mode 100644 index 0000000..586a833 --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_arm.S @@ -0,0 +1,125 @@ +@ +@ ARMv4 optimized DSP utils +@ Copyright (c) 2004 AGAWA Koji +@ +@ 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 "config.h" +#include "libavutil/arm/asm.S" + +#if !HAVE_ARMV5TE_EXTERNAL +#define pld @ +#endif + + .align 5 +@ void ff_add_pixels_clamped_arm(int16_t *block, uint8_t *dest, int stride) +function ff_add_pixels_clamped_arm, export=1 + push {r4-r10} + mov r10, #8 +1: + ldr r4, [r1] /* load dest */ + /* block[0] and block[1]*/ + ldrsh r5, [r0] + ldrsh r7, [r0, #2] + and r6, r4, #0xFF + and r8, r4, #0xFF00 + add r6, r6, r5 + add r8, r7, r8, lsr #8 + mvn r5, r5 + mvn r7, r7 + tst r6, #0x100 + it ne + movne r6, r5, lsr #24 + tst r8, #0x100 + it ne + movne r8, r7, lsr #24 + mov r9, r6 + ldrsh r5, [r0, #4] /* moved form [A] */ + orr r9, r9, r8, lsl #8 + /* block[2] and block[3] */ + /* [A] */ + ldrsh r7, [r0, #6] + and r6, r4, #0xFF0000 + and r8, r4, #0xFF000000 + add r6, r5, r6, lsr #16 + add r8, r7, r8, lsr #24 + mvn r5, r5 + mvn r7, r7 + tst r6, #0x100 + it ne + movne r6, r5, lsr #24 + tst r8, #0x100 + it ne + movne r8, r7, lsr #24 + orr r9, r9, r6, lsl #16 + ldr r4, [r1, #4] /* moved form [B] */ + orr r9, r9, r8, lsl #24 + /* store dest */ + ldrsh r5, [r0, #8] /* moved form [C] */ + str r9, [r1] + + /* load dest */ + /* [B] */ + /* block[4] and block[5] */ + /* [C] */ + ldrsh r7, [r0, #10] + and r6, r4, #0xFF + and r8, r4, #0xFF00 + add r6, r6, r5 + add r8, r7, r8, lsr #8 + mvn r5, r5 + mvn r7, r7 + tst r6, #0x100 + it ne + movne r6, r5, lsr #24 + tst r8, #0x100 + it ne + movne r8, r7, lsr #24 + mov r9, r6 + ldrsh r5, [r0, #12] /* moved from [D] */ + orr r9, r9, r8, lsl #8 + /* block[6] and block[7] */ + /* [D] */ + ldrsh r7, [r0, #14] + and r6, r4, #0xFF0000 + and r8, r4, #0xFF000000 + add r6, r5, r6, lsr #16 + add r8, r7, r8, lsr #24 + mvn r5, r5 + mvn r7, r7 + tst r6, #0x100 + it ne + movne r6, r5, lsr #24 + tst r8, #0x100 + it ne + movne r8, r7, lsr #24 + orr r9, r9, r6, lsl #16 + add r0, r0, #16 /* moved from [E] */ + orr r9, r9, r8, lsl #24 + subs r10, r10, #1 /* moved from [F] */ + /* store dest */ + str r9, [r1, #4] + + /* [E] */ + /* [F] */ + add r1, r1, r2 + bne 1b + + pop {r4-r10} + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/dsputil_arm.h b/ffmpeg/libavcodec/arm/dsputil_arm.h new file mode 100644 index 0000000..b7b5bdc --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_arm.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_ARM_DSPUTIL_H +#define AVCODEC_ARM_DSPUTIL_H + +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" + +void ff_dsputil_init_armv5te(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_armv6(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_vfp(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx); + +#endif /* AVCODEC_ARM_DSPUTIL_H */ diff --git a/ffmpeg/libavcodec/arm/dsputil_armv6.S b/ffmpeg/libavcodec/arm/dsputil_armv6.S new file mode 100644 index 0000000..6ec238b --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_armv6.S @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function ff_add_pixels_clamped_armv6, export=1 + push {r4-r8,lr} + mov r3, #8 +1: + ldm r0!, {r4,r5,r12,lr} + ldrd r6, r7, [r1] + pkhbt r8, r4, r5, lsl #16 + pkhtb r5, r5, r4, asr #16 + pkhbt r4, r12, lr, lsl #16 + pkhtb lr, lr, r12, asr #16 + pld [r1, r2] + uxtab16 r8, r8, r6 + uxtab16 r5, r5, r6, ror #8 + uxtab16 r4, r4, r7 + uxtab16 lr, lr, r7, ror #8 + usat16 r8, #8, r8 + usat16 r5, #8, r5 + usat16 r4, #8, r4 + usat16 lr, #8, lr + orr r6, r8, r5, lsl #8 + orr r7, r4, lr, lsl #8 + subs r3, r3, #1 + strd_post r6, r7, r1, r2 + bgt 1b + pop {r4-r8,pc} +endfunc + +function ff_get_pixels_armv6, export=1 + pld [r1, r2] + push {r4-r8, lr} + mov lr, #8 +1: + ldrd_post r4, r5, r1, r2 + subs lr, lr, #1 + uxtb16 r6, r4 + uxtb16 r4, r4, ror #8 + uxtb16 r12, r5 + uxtb16 r8, r5, ror #8 + pld [r1, r2] + pkhbt r5, r6, r4, lsl #16 + pkhtb r6, r4, r6, asr #16 + pkhbt r7, r12, r8, lsl #16 + pkhtb r12, r8, r12, asr #16 + stm r0!, {r5,r6,r7,r12} + bgt 1b + + pop {r4-r8, pc} +endfunc + +function ff_diff_pixels_armv6, export=1 + pld [r1, r3] + pld [r2, r3] + push {r4-r9, lr} + mov lr, #8 +1: + ldrd_post r4, r5, r1, r3 + ldrd_post r6, r7, r2, r3 + uxtb16 r8, r4 + uxtb16 r4, r4, ror #8 + uxtb16 r9, r6 + uxtb16 r6, r6, ror #8 + pld [r1, r3] + ssub16 r9, r8, r9 + ssub16 r6, r4, r6 + uxtb16 r8, r5 + uxtb16 r5, r5, ror #8 + pld [r2, r3] + pkhbt r4, r9, r6, lsl #16 + pkhtb r6, r6, r9, asr #16 + uxtb16 r9, r7 + uxtb16 r7, r7, ror #8 + ssub16 r9, r8, r9 + ssub16 r5, r5, r7 + subs lr, lr, #1 + pkhbt r8, r9, r5, lsl #16 + pkhtb r9, r5, r9, asr #16 + stm r0!, {r4,r6,r8,r9} + bgt 1b + + pop {r4-r9, pc} +endfunc + +function ff_pix_abs16_armv6, export=1 + ldr r0, [sp] + push {r4-r9, lr} + mov r12, #0 + mov lr, #0 + ldm r1, {r4-r7} + ldr r8, [r2] +1: + ldr r9, [r2, #4] + pld [r1, r3] + usada8 r12, r4, r8, r12 + ldr r8, [r2, #8] + pld [r2, r3] + usada8 lr, r5, r9, lr + ldr r9, [r2, #12] + usada8 r12, r6, r8, r12 + subs r0, r0, #1 + usada8 lr, r7, r9, lr + beq 2f + add r1, r1, r3 + ldm r1, {r4-r7} + add r2, r2, r3 + ldr r8, [r2] + b 1b +2: + add r0, r12, lr + pop {r4-r9, pc} +endfunc + +function ff_pix_abs16_x2_armv6, export=1 + ldr r12, [sp] + push {r4-r11, lr} + mov r0, #0 + mov lr, #1 + orr lr, lr, lr, lsl #8 + orr lr, lr, lr, lsl #16 +1: + ldr r8, [r2] + ldr r9, [r2, #4] + lsr r10, r8, #8 + ldr r4, [r1] + lsr r6, r9, #8 + orr r10, r10, r9, lsl #24 + ldr r5, [r2, #8] + eor r11, r8, r10 + uhadd8 r7, r8, r10 + orr r6, r6, r5, lsl #24 + and r11, r11, lr + uadd8 r7, r7, r11 + ldr r8, [r1, #4] + usada8 r0, r4, r7, r0 + eor r7, r9, r6 + lsr r10, r5, #8 + and r7, r7, lr + uhadd8 r4, r9, r6 + ldr r6, [r2, #12] + uadd8 r4, r4, r7 + pld [r1, r3] + orr r10, r10, r6, lsl #24 + usada8 r0, r8, r4, r0 + ldr r4, [r1, #8] + eor r11, r5, r10 + ldrb r7, [r2, #16] + and r11, r11, lr + uhadd8 r8, r5, r10 + ldr r5, [r1, #12] + uadd8 r8, r8, r11 + pld [r2, r3] + lsr r10, r6, #8 + usada8 r0, r4, r8, r0 + orr r10, r10, r7, lsl #24 + subs r12, r12, #1 + eor r11, r6, r10 + add r1, r1, r3 + uhadd8 r9, r6, r10 + and r11, r11, lr + uadd8 r9, r9, r11 + add r2, r2, r3 + usada8 r0, r5, r9, r0 + bgt 1b + + pop {r4-r11, pc} +endfunc + +.macro usad_y2 p0, p1, p2, p3, n0, n1, n2, n3 + ldr \n0, [r2] + eor \n1, \p0, \n0 + uhadd8 \p0, \p0, \n0 + and \n1, \n1, lr + ldr \n2, [r1] + uadd8 \p0, \p0, \n1 + ldr \n1, [r2, #4] + usada8 r0, \p0, \n2, r0 + pld [r1, r3] + eor \n3, \p1, \n1 + uhadd8 \p1, \p1, \n1 + and \n3, \n3, lr + ldr \p0, [r1, #4] + uadd8 \p1, \p1, \n3 + ldr \n2, [r2, #8] + usada8 r0, \p1, \p0, r0 + pld [r2, r3] + eor \p0, \p2, \n2 + uhadd8 \p2, \p2, \n2 + and \p0, \p0, lr + ldr \p1, [r1, #8] + uadd8 \p2, \p2, \p0 + ldr \n3, [r2, #12] + usada8 r0, \p2, \p1, r0 + eor \p1, \p3, \n3 + uhadd8 \p3, \p3, \n3 + and \p1, \p1, lr + ldr \p0, [r1, #12] + uadd8 \p3, \p3, \p1 + add r1, r1, r3 + usada8 r0, \p3, \p0, r0 + add r2, r2, r3 +.endm + +function ff_pix_abs16_y2_armv6, export=1 + pld [r1] + pld [r2] + ldr r12, [sp] + push {r4-r11, lr} + mov r0, #0 + mov lr, #1 + orr lr, lr, lr, lsl #8 + orr lr, lr, lr, lsl #16 + ldr r4, [r2] + ldr r5, [r2, #4] + ldr r6, [r2, #8] + ldr r7, [r2, #12] + add r2, r2, r3 +1: + usad_y2 r4, r5, r6, r7, r8, r9, r10, r11 + subs r12, r12, #2 + usad_y2 r8, r9, r10, r11, r4, r5, r6, r7 + bgt 1b + + pop {r4-r11, pc} +endfunc + +function ff_pix_abs8_armv6, export=1 + pld [r2, r3] + ldr r12, [sp] + push {r4-r9, lr} + mov r0, #0 + mov lr, #0 + ldrd_post r4, r5, r1, r3 +1: + subs r12, r12, #2 + ldr r7, [r2, #4] + ldr_post r6, r2, r3 + ldrd_post r8, r9, r1, r3 + usada8 r0, r4, r6, r0 + pld [r2, r3] + usada8 lr, r5, r7, lr + ldr r7, [r2, #4] + ldr_post r6, r2, r3 + beq 2f + ldrd_post r4, r5, r1, r3 + usada8 r0, r8, r6, r0 + pld [r2, r3] + usada8 lr, r9, r7, lr + b 1b +2: + usada8 r0, r8, r6, r0 + usada8 lr, r9, r7, lr + add r0, r0, lr + pop {r4-r9, pc} +endfunc + +function ff_sse16_armv6, export=1 + ldr r12, [sp] + push {r4-r9, lr} + mov r0, #0 +1: + ldrd r4, r5, [r1] + ldr r8, [r2] + uxtb16 lr, r4 + uxtb16 r4, r4, ror #8 + uxtb16 r9, r8 + uxtb16 r8, r8, ror #8 + ldr r7, [r2, #4] + usub16 lr, lr, r9 + usub16 r4, r4, r8 + smlad r0, lr, lr, r0 + uxtb16 r6, r5 + uxtb16 lr, r5, ror #8 + uxtb16 r8, r7 + uxtb16 r9, r7, ror #8 + smlad r0, r4, r4, r0 + ldrd r4, r5, [r1, #8] + usub16 r6, r6, r8 + usub16 r8, lr, r9 + ldr r7, [r2, #8] + smlad r0, r6, r6, r0 + uxtb16 lr, r4 + uxtb16 r4, r4, ror #8 + uxtb16 r9, r7 + uxtb16 r7, r7, ror #8 + smlad r0, r8, r8, r0 + ldr r8, [r2, #12] + usub16 lr, lr, r9 + usub16 r4, r4, r7 + smlad r0, lr, lr, r0 + uxtb16 r6, r5 + uxtb16 r5, r5, ror #8 + uxtb16 r9, r8 + uxtb16 r8, r8, ror #8 + smlad r0, r4, r4, r0 + usub16 r6, r6, r9 + usub16 r5, r5, r8 + smlad r0, r6, r6, r0 + add r1, r1, r3 + add r2, r2, r3 + subs r12, r12, #1 + smlad r0, r5, r5, r0 + bgt 1b + + pop {r4-r9, pc} +endfunc + +function ff_pix_norm1_armv6, export=1 + push {r4-r6, lr} + mov r12, #16 + mov lr, #0 +1: + ldm r0, {r2-r5} + uxtb16 r6, r2 + uxtb16 r2, r2, ror #8 + smlad lr, r6, r6, lr + uxtb16 r6, r3 + smlad lr, r2, r2, lr + uxtb16 r3, r3, ror #8 + smlad lr, r6, r6, lr + uxtb16 r6, r4 + smlad lr, r3, r3, lr + uxtb16 r4, r4, ror #8 + smlad lr, r6, r6, lr + uxtb16 r6, r5 + smlad lr, r4, r4, lr + uxtb16 r5, r5, ror #8 + smlad lr, r6, r6, lr + subs r12, r12, #1 + add r0, r0, r1 + smlad lr, r5, r5, lr + bgt 1b + + mov r0, lr + pop {r4-r6, pc} +endfunc + +function ff_pix_sum_armv6, export=1 + push {r4-r7, lr} + mov r12, #16 + mov r2, #0 + mov r3, #0 + mov lr, #0 + ldr r4, [r0] +1: + subs r12, r12, #1 + ldr r5, [r0, #4] + usada8 r2, r4, lr, r2 + ldr r6, [r0, #8] + usada8 r3, r5, lr, r3 + ldr r7, [r0, #12] + usada8 r2, r6, lr, r2 + beq 2f + ldr_pre r4, r0, r1 + usada8 r3, r7, lr, r3 + bgt 1b +2: + usada8 r3, r7, lr, r3 + add r0, r2, r3 + pop {r4-r7, pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/dsputil_init_arm.c b/ffmpeg/libavcodec/arm/dsputil_init_arm.c new file mode 100644 index 0000000..68991fa --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_init_arm.c @@ -0,0 +1,86 @@ +/* + * ARM optimized DSP utils + * Copyright (c) 2001 Lionel Ulmer + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "dsputil_arm.h" + +void ff_j_rev_dct_arm(int16_t *data); +void ff_simple_idct_arm(int16_t *data); + +/* XXX: local hack */ +static void (*ff_put_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); +static void (*ff_add_pixels_clamped)(const int16_t *block, uint8_t *pixels, int line_size); + +void ff_add_pixels_clamped_arm(const int16_t *block, uint8_t *dest, + int line_size); + +/* XXX: those functions should be suppressed ASAP when all IDCTs are + converted */ +static void j_rev_dct_arm_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct_arm (block); + ff_put_pixels_clamped(block, dest, line_size); +} +static void j_rev_dct_arm_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct_arm (block); + ff_add_pixels_clamped(block, dest, line_size); +} +static void simple_idct_arm_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_simple_idct_arm (block); + ff_put_pixels_clamped(block, dest, line_size); +} +static void simple_idct_arm_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_simple_idct_arm (block); + ff_add_pixels_clamped(block, dest, line_size); +} + +av_cold void ff_dsputil_init_arm(DSPContext *c, AVCodecContext *avctx) +{ + int cpu_flags = av_get_cpu_flags(); + + ff_put_pixels_clamped = c->put_pixels_clamped; + ff_add_pixels_clamped = c->add_pixels_clamped; + + if (!avctx->lowres && avctx->bits_per_raw_sample <= 8) { + if(avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_ARM){ + c->idct_put = j_rev_dct_arm_put; + c->idct_add = j_rev_dct_arm_add; + c->idct = ff_j_rev_dct_arm; + c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; + } else if (avctx->idct_algo == FF_IDCT_SIMPLEARM){ + c->idct_put = simple_idct_arm_put; + c->idct_add = simple_idct_arm_add; + c->idct = ff_simple_idct_arm; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } + } + + c->add_pixels_clamped = ff_add_pixels_clamped_arm; + + if (have_armv5te(cpu_flags)) ff_dsputil_init_armv5te(c, avctx); + if (have_armv6(cpu_flags)) ff_dsputil_init_armv6(c, avctx); + if (have_neon(cpu_flags)) ff_dsputil_init_neon(c, avctx); +} diff --git a/ffmpeg/libavcodec/arm/dsputil_init_armv5te.c b/ffmpeg/libavcodec/arm/dsputil_init_armv5te.c new file mode 100644 index 0000000..841fbfa --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_init_armv5te.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "dsputil_arm.h" + +void ff_simple_idct_armv5te(int16_t *data); +void ff_simple_idct_put_armv5te(uint8_t *dest, int line_size, int16_t *data); +void ff_simple_idct_add_armv5te(uint8_t *dest, int line_size, int16_t *data); + +av_cold void ff_dsputil_init_armv5te(DSPContext *c, AVCodecContext *avctx) +{ + if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 && + (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEARMV5TE)) { + c->idct_put = ff_simple_idct_put_armv5te; + c->idct_add = ff_simple_idct_add_armv5te; + c->idct = ff_simple_idct_armv5te; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } +} diff --git a/ffmpeg/libavcodec/arm/dsputil_init_armv6.c b/ffmpeg/libavcodec/arm/dsputil_init_armv6.c new file mode 100644 index 0000000..8f38302 --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_init_armv6.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavcodec/avcodec.h" +#include "dsputil_arm.h" + +void ff_simple_idct_armv6(int16_t *data); +void ff_simple_idct_put_armv6(uint8_t *dest, int line_size, int16_t *data); +void ff_simple_idct_add_armv6(uint8_t *dest, int line_size, int16_t *data); + +void ff_add_pixels_clamped_armv6(const int16_t *block, + uint8_t *restrict pixels, + int line_size); + +void ff_get_pixels_armv6(int16_t *block, const uint8_t *pixels, int stride); +void ff_diff_pixels_armv6(int16_t *block, const uint8_t *s1, + const uint8_t *s2, int stride); + +int ff_pix_abs16_armv6(void *s, uint8_t *blk1, uint8_t *blk2, + int line_size, int h); +int ff_pix_abs16_x2_armv6(void *s, uint8_t *blk1, uint8_t *blk2, + int line_size, int h); +int ff_pix_abs16_y2_armv6(void *s, uint8_t *blk1, uint8_t *blk2, + int line_size, int h); + +int ff_pix_abs8_armv6(void *s, uint8_t *blk1, uint8_t *blk2, + int line_size, int h); + +int ff_sse16_armv6(void *s, uint8_t *blk1, uint8_t *blk2, + int line_size, int h); + +int ff_pix_norm1_armv6(uint8_t *pix, int line_size); +int ff_pix_sum_armv6(uint8_t *pix, int line_size); + +av_cold void ff_dsputil_init_armv6(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 && + (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEARMV6)) { + c->idct_put = ff_simple_idct_put_armv6; + c->idct_add = ff_simple_idct_add_armv6; + c->idct = ff_simple_idct_armv6; + c->idct_permutation_type = FF_LIBMPEG2_IDCT_PERM; + } + + if (!high_bit_depth) + c->get_pixels = ff_get_pixels_armv6; + c->add_pixels_clamped = ff_add_pixels_clamped_armv6; + c->diff_pixels = ff_diff_pixels_armv6; + + c->pix_abs[0][0] = ff_pix_abs16_armv6; + c->pix_abs[0][1] = ff_pix_abs16_x2_armv6; + c->pix_abs[0][2] = ff_pix_abs16_y2_armv6; + + c->pix_abs[1][0] = ff_pix_abs8_armv6; + + c->sad[0] = ff_pix_abs16_armv6; + c->sad[1] = ff_pix_abs8_armv6; + + c->sse[0] = ff_sse16_armv6; + + c->pix_norm1 = ff_pix_norm1_armv6; + c->pix_sum = ff_pix_sum_armv6; +} diff --git a/ffmpeg/libavcodec/arm/dsputil_init_neon.c b/ffmpeg/libavcodec/arm/dsputil_init_neon.c new file mode 100644 index 0000000..6d19af7 --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_init_neon.c @@ -0,0 +1,81 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "dsputil_arm.h" + +void ff_simple_idct_neon(int16_t *data); +void ff_simple_idct_put_neon(uint8_t *dest, int line_size, int16_t *data); +void ff_simple_idct_add_neon(uint8_t *dest, int line_size, int16_t *data); + +void ff_clear_block_neon(int16_t *block); +void ff_clear_blocks_neon(int16_t *blocks); + +void ff_add_pixels_clamped_neon(const int16_t *, uint8_t *, int); +void ff_put_pixels_clamped_neon(const int16_t *, uint8_t *, int); +void ff_put_signed_pixels_clamped_neon(const int16_t *, uint8_t *, int); + +void ff_vector_clipf_neon(float *dst, const float *src, float min, float max, + int len); +void ff_vector_clip_int32_neon(int32_t *dst, const int32_t *src, int32_t min, + int32_t max, unsigned int len); + +int32_t ff_scalarproduct_int16_neon(const int16_t *v1, const int16_t *v2, int len); +int32_t ff_scalarproduct_and_madd_int16_neon(int16_t *v1, const int16_t *v2, + const int16_t *v3, int len, int mul); + +void ff_apply_window_int16_neon(int16_t *dst, const int16_t *src, + const int16_t *window, unsigned n); + +av_cold void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (!avctx->lowres && avctx->bits_per_raw_sample <= 8) { + if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLENEON) { + c->idct_put = ff_simple_idct_put_neon; + c->idct_add = ff_simple_idct_add_neon; + c->idct = ff_simple_idct_neon; + c->idct_permutation_type = FF_PARTTRANS_IDCT_PERM; + } + } + + if (!high_bit_depth) { + c->clear_block = ff_clear_block_neon; + c->clear_blocks = ff_clear_blocks_neon; + } + + c->add_pixels_clamped = ff_add_pixels_clamped_neon; + c->put_pixels_clamped = ff_put_pixels_clamped_neon; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_neon; + + c->vector_clipf = ff_vector_clipf_neon; + c->vector_clip_int32 = ff_vector_clip_int32_neon; + + c->scalarproduct_int16 = ff_scalarproduct_int16_neon; + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_neon; + + c->apply_window_int16 = ff_apply_window_int16_neon; +} diff --git a/ffmpeg/libavcodec/arm/dsputil_neon.S b/ffmpeg/libavcodec/arm/dsputil_neon.S new file mode 100644 index 0000000..307e122 --- /dev/null +++ b/ffmpeg/libavcodec/arm/dsputil_neon.S @@ -0,0 +1,209 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function ff_clear_block_neon, export=1 + vmov.i16 q0, #0 + .rept 8 + vst1.16 {q0}, [r0,:128]! + .endr + bx lr +endfunc + +function ff_clear_blocks_neon, export=1 + vmov.i16 q0, #0 + .rept 8*6 + vst1.16 {q0}, [r0,:128]! + .endr + bx lr +endfunc + +function ff_put_pixels_clamped_neon, export=1 + vld1.16 {d16-d19}, [r0,:128]! + vqmovun.s16 d0, q8 + vld1.16 {d20-d23}, [r0,:128]! + vqmovun.s16 d1, q9 + vld1.16 {d24-d27}, [r0,:128]! + vqmovun.s16 d2, q10 + vld1.16 {d28-d31}, [r0,:128]! + vqmovun.s16 d3, q11 + vst1.8 {d0}, [r1,:64], r2 + vqmovun.s16 d4, q12 + vst1.8 {d1}, [r1,:64], r2 + vqmovun.s16 d5, q13 + vst1.8 {d2}, [r1,:64], r2 + vqmovun.s16 d6, q14 + vst1.8 {d3}, [r1,:64], r2 + vqmovun.s16 d7, q15 + vst1.8 {d4}, [r1,:64], r2 + vst1.8 {d5}, [r1,:64], r2 + vst1.8 {d6}, [r1,:64], r2 + vst1.8 {d7}, [r1,:64], r2 + bx lr +endfunc + +function ff_put_signed_pixels_clamped_neon, export=1 + vmov.u8 d31, #128 + vld1.16 {d16-d17}, [r0,:128]! + vqmovn.s16 d0, q8 + vld1.16 {d18-d19}, [r0,:128]! + vqmovn.s16 d1, q9 + vld1.16 {d16-d17}, [r0,:128]! + vqmovn.s16 d2, q8 + vld1.16 {d18-d19}, [r0,:128]! + vadd.u8 d0, d0, d31 + vld1.16 {d20-d21}, [r0,:128]! + vadd.u8 d1, d1, d31 + vld1.16 {d22-d23}, [r0,:128]! + vadd.u8 d2, d2, d31 + vst1.8 {d0}, [r1,:64], r2 + vqmovn.s16 d3, q9 + vst1.8 {d1}, [r1,:64], r2 + vqmovn.s16 d4, q10 + vst1.8 {d2}, [r1,:64], r2 + vqmovn.s16 d5, q11 + vld1.16 {d24-d25}, [r0,:128]! + vadd.u8 d3, d3, d31 + vld1.16 {d26-d27}, [r0,:128]! + vadd.u8 d4, d4, d31 + vadd.u8 d5, d5, d31 + vst1.8 {d3}, [r1,:64], r2 + vqmovn.s16 d6, q12 + vst1.8 {d4}, [r1,:64], r2 + vqmovn.s16 d7, q13 + vst1.8 {d5}, [r1,:64], r2 + vadd.u8 d6, d6, d31 + vadd.u8 d7, d7, d31 + vst1.8 {d6}, [r1,:64], r2 + vst1.8 {d7}, [r1,:64], r2 + bx lr +endfunc + +function ff_add_pixels_clamped_neon, export=1 + mov r3, r1 + vld1.8 {d16}, [r1,:64], r2 + vld1.16 {d0-d1}, [r0,:128]! + vaddw.u8 q0, q0, d16 + vld1.8 {d17}, [r1,:64], r2 + vld1.16 {d2-d3}, [r0,:128]! + vqmovun.s16 d0, q0 + vld1.8 {d18}, [r1,:64], r2 + vaddw.u8 q1, q1, d17 + vld1.16 {d4-d5}, [r0,:128]! + vaddw.u8 q2, q2, d18 + vst1.8 {d0}, [r3,:64], r2 + vqmovun.s16 d2, q1 + vld1.8 {d19}, [r1,:64], r2 + vld1.16 {d6-d7}, [r0,:128]! + vaddw.u8 q3, q3, d19 + vqmovun.s16 d4, q2 + vst1.8 {d2}, [r3,:64], r2 + vld1.8 {d16}, [r1,:64], r2 + vqmovun.s16 d6, q3 + vld1.16 {d0-d1}, [r0,:128]! + vaddw.u8 q0, q0, d16 + vst1.8 {d4}, [r3,:64], r2 + vld1.8 {d17}, [r1,:64], r2 + vld1.16 {d2-d3}, [r0,:128]! + vaddw.u8 q1, q1, d17 + vst1.8 {d6}, [r3,:64], r2 + vqmovun.s16 d0, q0 + vld1.8 {d18}, [r1,:64], r2 + vld1.16 {d4-d5}, [r0,:128]! + vaddw.u8 q2, q2, d18 + vst1.8 {d0}, [r3,:64], r2 + vqmovun.s16 d2, q1 + vld1.8 {d19}, [r1,:64], r2 + vqmovun.s16 d4, q2 + vld1.16 {d6-d7}, [r0,:128]! + vaddw.u8 q3, q3, d19 + vst1.8 {d2}, [r3,:64], r2 + vqmovun.s16 d6, q3 + vst1.8 {d4}, [r3,:64], r2 + vst1.8 {d6}, [r3,:64], r2 + bx lr +endfunc + +function ff_vector_clipf_neon, export=1 +VFP vdup.32 q1, d0[1] +VFP vdup.32 q0, d0[0] +NOVFP vdup.32 q0, r2 +NOVFP vdup.32 q1, r3 +NOVFP ldr r2, [sp] + vld1.f32 {q2},[r1,:128]! + vmin.f32 q10, q2, q1 + vld1.f32 {q3},[r1,:128]! + vmin.f32 q11, q3, q1 +1: vmax.f32 q8, q10, q0 + vmax.f32 q9, q11, q0 + subs r2, r2, #8 + beq 2f + vld1.f32 {q2},[r1,:128]! + vmin.f32 q10, q2, q1 + vld1.f32 {q3},[r1,:128]! + vmin.f32 q11, q3, q1 + vst1.f32 {q8},[r0,:128]! + vst1.f32 {q9},[r0,:128]! + b 1b +2: vst1.f32 {q8},[r0,:128]! + vst1.f32 {q9},[r0,:128]! + bx lr +endfunc + +function ff_apply_window_int16_neon, export=1 + push {r4,lr} + add r4, r1, r3, lsl #1 + add lr, r0, r3, lsl #1 + sub r4, r4, #16 + sub lr, lr, #16 + mov r12, #-16 +1: + vld1.16 {q0}, [r1,:128]! + vld1.16 {q2}, [r2,:128]! + vld1.16 {q1}, [r4,:128], r12 + vrev64.16 q3, q2 + vqrdmulh.s16 q0, q0, q2 + vqrdmulh.s16 d2, d2, d7 + vqrdmulh.s16 d3, d3, d6 + vst1.16 {q0}, [r0,:128]! + vst1.16 {q1}, [lr,:128], r12 + subs r3, r3, #16 + bgt 1b + + pop {r4,pc} +endfunc + +function ff_vector_clip_int32_neon, export=1 + vdup.32 q0, r2 + vdup.32 q1, r3 + ldr r2, [sp] +1: + vld1.32 {q2-q3}, [r1,:128]! + vmin.s32 q2, q2, q1 + vmin.s32 q3, q3, q1 + vmax.s32 q2, q2, q0 + vmax.s32 q3, q3, q0 + vst1.32 {q2-q3}, [r0,:128]! + subs r2, r2, #8 + bgt 1b + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/fft_fixed_init_arm.c b/ffmpeg/libavcodec/arm/fft_fixed_init_arm.c new file mode 100644 index 0000000..ef098f4 --- /dev/null +++ b/ffmpeg/libavcodec/arm/fft_fixed_init_arm.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/cpu.h" + +#define CONFIG_FFT_FLOAT 0 +#include "libavcodec/fft.h" + +void ff_fft_fixed_calc_neon(FFTContext *s, FFTComplex *z); +void ff_mdct_fixed_calc_neon(FFTContext *s, FFTSample *o, const FFTSample *i); +void ff_mdct_fixed_calcw_neon(FFTContext *s, FFTDouble *o, const FFTSample *i); + +av_cold void ff_fft_fixed_init_arm(FFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->fft_permutation = FF_FFT_PERM_SWAP_LSBS; +#if CONFIG_FFT + s->fft_calc = ff_fft_fixed_calc_neon; +#endif + +#if CONFIG_MDCT + if (!s->inverse && s->nbits >= 3) { + s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; + s->mdct_calc = ff_mdct_fixed_calc_neon; + s->mdct_calcw = ff_mdct_fixed_calcw_neon; + } +#endif + } +} diff --git a/ffmpeg/libavcodec/arm/fft_fixed_neon.S b/ffmpeg/libavcodec/arm/fft_fixed_neon.S new file mode 100644 index 0000000..fa33eac --- /dev/null +++ b/ffmpeg/libavcodec/arm/fft_fixed_neon.S @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +.macro bflies d0, d1, r0, r1 + vrev64.32 \r0, \d1 @ t5, t6, t1, t2 + vhsub.s16 \r1, \d1, \r0 @ t1-t5, t2-t6, t5-t1, t6-t2 + vhadd.s16 \r0, \d1, \r0 @ t1+t5, t2+t6, t5+t1, t6+t2 + vext.16 \r1, \r1, \r1, #1 @ t2-t6, t5-t1, t6-t2, t1-t5 + vtrn.32 \r0, \r1 @ t1+t5, t2+t6, t2-t6, t5-t1 + @ t5, t6, t4, t3 + vhsub.s16 \d1, \d0, \r0 + vhadd.s16 \d0, \d0, \r0 +.endm + +.macro transform01 q0, q1, d3, c0, c1, r0, w0, w1 + vrev32.16 \r0, \d3 + vmull.s16 \w0, \d3, \c0 + vmlal.s16 \w0, \r0, \c1 + vshrn.s32 \d3, \w0, #15 + bflies \q0, \q1, \w0, \w1 +.endm + +.macro transform2 d0, d1, d2, d3, q0, q1, c0, c1, c2, c3, \ + r0, r1, w0, w1 + vrev32.16 \r0, \d1 + vrev32.16 \r1, \d3 + vmull.s16 \w0, \d1, \c0 + vmlal.s16 \w0, \r0, \c1 + vmull.s16 \w1, \d3, \c2 + vmlal.s16 \w1, \r1, \c3 + vshrn.s32 \d1, \w0, #15 + vshrn.s32 \d3, \w1, #15 + bflies \q0, \q1, \w0, \w1 +.endm + +.macro fft4 d0, d1, r0, r1 + vhsub.s16 \r0, \d0, \d1 @ t3, t4, t8, t7 + vhsub.s16 \r1, \d1, \d0 + vhadd.s16 \d0, \d0, \d1 @ t1, t2, t6, t5 + vmov.i64 \d1, #0xffff00000000 + vbit \r0, \r1, \d1 + vrev64.16 \r1, \r0 @ t7, t8, t4, t3 + vtrn.32 \r0, \r1 @ t3, t4, t7, t8 + vtrn.32 \d0, \r0 @ t1, t2, t3, t4, t6, t5, t8, t7 + vhsub.s16 \d1, \d0, \r0 @ r2, i2, r3, i1 + vhadd.s16 \d0, \d0, \r0 @ r0, i0, r1, i3 +.endm + +.macro fft8 d0, d1, d2, d3, q0, q1, c0, c1, r0, r1, w0, w1 + fft4 \d0, \d1, \r0, \r1 + vtrn.32 \d0, \d1 @ z0, z2, z1, z3 + vhadd.s16 \r0, \d2, \d3 @ t1, t2, t3, t4 + vhsub.s16 \d3, \d2, \d3 @ z5, z7 + vmov \d2, \r0 + transform01 \q0, \q1, \d3, \c0, \c1, \r0, \w0, \w1 +.endm + +function fft4_neon + vld1.16 {d0-d1}, [r0] + fft4 d0, d1, d2, d3 + vst1.16 {d0-d1}, [r0] + bx lr +endfunc + +function fft8_neon + vld1.16 {d0-d3}, [r0,:128] + movrel r1, coefs + vld1.16 {d30}, [r1,:64] + vdup.16 d31, d30[0] + fft8 d0, d1, d2, d3, q0, q1, d31, d30, d20, d21, q8, q9 + vtrn.32 d0, d1 + vtrn.32 d2, d3 + vst1.16 {d0-d3}, [r0,:128] + bx lr +endfunc + +function fft16_neon + vld1.16 {d0-d3}, [r0,:128]! + vld1.16 {d4-d7}, [r0,:128] + movrel r1, coefs + sub r0, r0, #32 + vld1.16 {d28-d31},[r1,:128] + vdup.16 d31, d28[0] + fft8 d0, d1, d2, d3, q0, q1, d31, d28, d20, d21, q8, q9 + vswp d5, d6 + fft4 q2, q3, q8, q9 + vswp d5, d6 + vtrn.32 q0, q1 @ z0, z4, z2, z6, z1, z5, z3, z7 + vtrn.32 q2, q3 @ z8, z12,z10,z14,z9, z13,z11,z15 + vswp d1, d2 + vdup.16 d31, d28[0] + transform01 q0, q2, d5, d31, d28, d20, q8, q9 + vdup.16 d26, d29[0] + vdup.16 d27, d30[0] + transform2 d2, d6, d3, d7, q1, q3, d26, d30, d27, d29, \ + d20, d21, q8, q9 + vtrn.32 q0, q1 + vtrn.32 q2, q3 + vst1.16 {d0-d3}, [r0,:128]! + vst1.16 {d4-d7}, [r0,:128] + bx lr +endfunc + +function fft_pass_neon + push {r4,lr} + movrel lr, coefs+24 + vld1.16 {d30}, [lr,:64] + lsl r12, r2, #3 + vmov d31, d30 + add r3, r1, r2, lsl #2 + mov lr, #-8 + sub r3, r3, #2 + mov r4, r0 + vld1.16 {d27[]}, [r3,:16] + sub r3, r3, #6 + vld1.16 {q0}, [r4,:128], r12 + vld1.16 {q1}, [r4,:128], r12 + vld1.16 {q2}, [r4,:128], r12 + vld1.16 {q3}, [r4,:128], r12 + vld1.16 {d28}, [r1,:64]! + vld1.16 {d29}, [r3,:64], lr + vswp d1, d2 + vswp d5, d6 + vtrn.32 d0, d1 + vtrn.32 d4, d5 + vdup.16 d25, d28[1] + vmul.s16 d27, d27, d31 + transform01 q0, q2, d5, d25, d27, d20, q8, q9 + b 2f +1: + mov r4, r0 + vdup.16 d26, d29[0] + vld1.16 {q0}, [r4,:128], r12 + vld1.16 {q1}, [r4,:128], r12 + vld1.16 {q2}, [r4,:128], r12 + vld1.16 {q3}, [r4,:128], r12 + vld1.16 {d28}, [r1,:64]! + vld1.16 {d29}, [r3,:64], lr + vswp d1, d2 + vswp d5, d6 + vtrn.32 d0, d1 + vtrn.32 d4, d5 + vdup.16 d24, d28[0] + vdup.16 d25, d28[1] + vdup.16 d27, d29[3] + vmul.s16 q13, q13, q15 + transform2 d0, d4, d1, d5, q0, q2, d24, d26, d25, d27, \ + d16, d17, q9, q10 +2: + vtrn.32 d2, d3 + vtrn.32 d6, d7 + vdup.16 d24, d28[2] + vdup.16 d26, d29[2] + vdup.16 d25, d28[3] + vdup.16 d27, d29[1] + vmul.s16 q13, q13, q15 + transform2 d2, d6, d3, d7, q1, q3, d24, d26, d25, d27, \ + d16, d17, q9, q10 + vtrn.32 d0, d1 + vtrn.32 d2, d3 + vtrn.32 d4, d5 + vtrn.32 d6, d7 + vswp d1, d2 + vswp d5, d6 + mov r4, r0 + vst1.16 {q0}, [r4,:128], r12 + vst1.16 {q1}, [r4,:128], r12 + vst1.16 {q2}, [r4,:128], r12 + vst1.16 {q3}, [r4,:128], r12 + add r0, r0, #16 + subs r2, r2, #2 + bgt 1b + pop {r4,pc} +endfunc + +#define F_SQRT1_2 23170 +#define F_COS_16_1 30274 +#define F_COS_16_3 12540 + +const coefs, align=4 + .short F_SQRT1_2, -F_SQRT1_2, -F_SQRT1_2, F_SQRT1_2 + .short F_COS_16_1,-F_COS_16_1,-F_COS_16_1, F_COS_16_1 + .short F_COS_16_3,-F_COS_16_3,-F_COS_16_3, F_COS_16_3 + .short 1, -1, -1, 1 +endconst + +.macro def_fft n, n2, n4 +function fft\n\()_neon + push {r4, lr} + mov r4, r0 + bl fft\n2\()_neon + add r0, r4, #\n4*2*4 + bl fft\n4\()_neon + add r0, r4, #\n4*3*4 + bl fft\n4\()_neon + mov r0, r4 + pop {r4, lr} + movrelx r1, X(ff_cos_\n\()_fixed) + mov r2, #\n4/2 + b fft_pass_neon +endfunc +.endm + + def_fft 32, 16, 8 + def_fft 64, 32, 16 + def_fft 128, 64, 32 + def_fft 256, 128, 64 + def_fft 512, 256, 128 + def_fft 1024, 512, 256 + def_fft 2048, 1024, 512 + def_fft 4096, 2048, 1024 + def_fft 8192, 4096, 2048 + def_fft 16384, 8192, 4096 + def_fft 32768, 16384, 8192 + def_fft 65536, 32768, 16384 + +function ff_fft_fixed_calc_neon, export=1 + ldr r2, [r0] + sub r2, r2, #2 + movrel r3, fft_fixed_tab_neon + ldr r3, [r3, r2, lsl #2] + mov r0, r1 + bx r3 +endfunc + +const fft_fixed_tab_neon + .word fft4_neon + .word fft8_neon + .word fft16_neon + .word fft32_neon + .word fft64_neon + .word fft128_neon + .word fft256_neon + .word fft512_neon + .word fft1024_neon + .word fft2048_neon + .word fft4096_neon + .word fft8192_neon + .word fft16384_neon + .word fft32768_neon + .word fft65536_neon +endconst diff --git a/ffmpeg/libavcodec/arm/fft_init_arm.c b/ffmpeg/libavcodec/arm/fft_init_arm.c new file mode 100644 index 0000000..8c98abc --- /dev/null +++ b/ffmpeg/libavcodec/arm/fft_init_arm.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/cpu.h" +#include "libavcodec/fft.h" +#include "libavcodec/rdft.h" +#include "libavcodec/synth_filter.h" + +void ff_fft_permute_neon(FFTContext *s, FFTComplex *z); +void ff_fft_calc_neon(FFTContext *s, FFTComplex *z); + +void ff_imdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_neon(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_mdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input); + +void ff_rdft_calc_neon(struct RDFTContext *s, FFTSample *z); + +void ff_synth_filter_float_neon(FFTContext *imdct, + float *synth_buf_ptr, int *synth_buf_offset, + float synth_buf2[32], const float window[512], + float out[32], const float in[32], + float scale); + +av_cold void ff_fft_init_arm(FFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { +#if CONFIG_FFT + s->fft_permute = ff_fft_permute_neon; + s->fft_calc = ff_fft_calc_neon; +#endif +#if CONFIG_MDCT + s->imdct_calc = ff_imdct_calc_neon; + s->imdct_half = ff_imdct_half_neon; + s->mdct_calc = ff_mdct_calc_neon; + s->mdct_permutation = FF_MDCT_PERM_INTERLEAVE; +#endif + } +} + +#if CONFIG_RDFT +av_cold void ff_rdft_init_arm(RDFTContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + s->rdft_calc = ff_rdft_calc_neon; +} +#endif + +#if CONFIG_DCA_DECODER +av_cold void ff_synth_filter_init_arm(SynthFilterContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + s->synth_filter_float = ff_synth_filter_float_neon; +} +#endif diff --git a/ffmpeg/libavcodec/arm/fft_neon.S b/ffmpeg/libavcodec/arm/fft_neon.S new file mode 100644 index 0000000..8b9ae2a --- /dev/null +++ b/ffmpeg/libavcodec/arm/fft_neon.S @@ -0,0 +1,375 @@ +/* + * ARM NEON optimised FFT + * + * Copyright (c) 2009 Mans Rullgard + * Copyright (c) 2009 Naotoshi Nojiri + * + * This algorithm (though not any of the implementation details) is + * based on libdjbfft by D. J. Bernstein. + * + * 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 "libavutil/arm/asm.S" + +#define M_SQRT1_2 0.70710678118654752440 + + +function fft4_neon + vld1.32 {d0-d3}, [r0,:128] + + vext.32 q8, q1, q1, #1 @ i2,r3 d3=i3,r2 + vsub.f32 d6, d0, d1 @ r0-r1,i0-i1 + vsub.f32 d7, d16, d17 @ r3-r2,i2-i3 + vadd.f32 d4, d0, d1 @ r0+r1,i0+i1 + vadd.f32 d5, d2, d3 @ i2+i3,r2+r3 + vadd.f32 d1, d6, d7 + vsub.f32 d3, d6, d7 + vadd.f32 d0, d4, d5 + vsub.f32 d2, d4, d5 + + vst1.32 {d0-d3}, [r0,:128] + + bx lr +endfunc + +function fft8_neon + mov r1, r0 + vld1.32 {d0-d3}, [r1,:128]! + vld1.32 {d16-d19}, [r1,:128] + + movw r2, #0x04f3 @ sqrt(1/2) + movt r2, #0x3f35 + eor r3, r2, #1<<31 + vdup.32 d31, r2 + + vext.32 q11, q1, q1, #1 @ i2,r3,i3,r2 + vadd.f32 d4, d16, d17 @ r4+r5,i4+i5 + vmov d28, r3, r2 + vadd.f32 d5, d18, d19 @ r6+r7,i6+i7 + vsub.f32 d17, d16, d17 @ r4-r5,i4-i5 + vsub.f32 d19, d18, d19 @ r6-r7,i6-i7 + vrev64.32 d29, d28 + vadd.f32 d20, d0, d1 @ r0+r1,i0+i1 + vadd.f32 d21, d2, d3 @ r2+r3,i2+i3 + vmul.f32 d26, d17, d28 @ -a2r*w,a2i*w + vext.32 q3, q2, q2, #1 + vmul.f32 d27, d19, d29 @ a3r*w,-a3i*w + vsub.f32 d23, d22, d23 @ i2-i3,r3-r2 + vsub.f32 d22, d0, d1 @ r0-r1,i0-i1 + vmul.f32 d24, d17, d31 @ a2r*w,a2i*w + vmul.f32 d25, d19, d31 @ a3r*w,a3i*w + vadd.f32 d0, d20, d21 + vsub.f32 d2, d20, d21 + vadd.f32 d1, d22, d23 + vrev64.32 q13, q13 + vsub.f32 d3, d22, d23 + vsub.f32 d6, d6, d7 + vadd.f32 d24, d24, d26 @ a2r+a2i,a2i-a2r t1,t2 + vadd.f32 d25, d25, d27 @ a3r-a3i,a3i+a3r t5,t6 + vadd.f32 d7, d4, d5 + vsub.f32 d18, d2, d6 + vext.32 q13, q12, q12, #1 + vadd.f32 d2, d2, d6 + vsub.f32 d16, d0, d7 + vadd.f32 d5, d25, d24 + vsub.f32 d4, d26, d27 + vadd.f32 d0, d0, d7 + vsub.f32 d17, d1, d5 + vsub.f32 d19, d3, d4 + vadd.f32 d3, d3, d4 + vadd.f32 d1, d1, d5 + + vst1.32 {d16-d19}, [r1,:128] + vst1.32 {d0-d3}, [r0,:128] + + bx lr +endfunc + +function fft16_neon + movrel r1, mppm + vld1.32 {d16-d19}, [r0,:128]! @ q8{r0,i0,r1,i1} q9{r2,i2,r3,i3} + pld [r0, #32] + vld1.32 {d2-d3}, [r1,:128] + vext.32 q13, q9, q9, #1 + vld1.32 {d22-d25}, [r0,:128]! @ q11{r4,i4,r5,i5} q12{r6,i5,r7,i7} + vadd.f32 d4, d16, d17 + vsub.f32 d5, d16, d17 + vadd.f32 d18, d18, d19 + vsub.f32 d19, d26, d27 + + vadd.f32 d20, d22, d23 + vsub.f32 d22, d22, d23 + vsub.f32 d23, d24, d25 + vadd.f32 q8, q2, q9 @ {r0,i0,r1,i1} + vadd.f32 d21, d24, d25 + vmul.f32 d24, d22, d2 + vsub.f32 q9, q2, q9 @ {r2,i2,r3,i3} + vmul.f32 d25, d23, d3 + vuzp.32 d16, d17 @ {r0,r1,i0,i1} + vmul.f32 q1, q11, d2[1] + vuzp.32 d18, d19 @ {r2,r3,i2,i3} + vrev64.32 q12, q12 + vadd.f32 q11, q12, q1 @ {t1a,t2a,t5,t6} + vld1.32 {d24-d27}, [r0,:128]! @ q12{r8,i8,r9,i9} q13{r10,i10,r11,i11} + vzip.32 q10, q11 + vld1.32 {d28-d31}, [r0,:128] @ q14{r12,i12,r13,i13} q15{r14,i14,r15,i15} + vadd.f32 d0, d22, d20 + vadd.f32 d1, d21, d23 + vsub.f32 d2, d21, d23 + vsub.f32 d3, d22, d20 + sub r0, r0, #96 + vext.32 q13, q13, q13, #1 + vsub.f32 q10, q8, q0 @ {r4,r5,i4,i5} + vadd.f32 q8, q8, q0 @ {r0,r1,i0,i1} + vext.32 q15, q15, q15, #1 + vsub.f32 q11, q9, q1 @ {r6,r7,i6,i7} + vswp d25, d26 @ q12{r8,i8,i10,r11} q13{r9,i9,i11,r10} + vadd.f32 q9, q9, q1 @ {r2,r3,i2,i3} + vswp d29, d30 @ q14{r12,i12,i14,r15} q15{r13,i13,i15,r14} + vadd.f32 q0, q12, q13 @ {t1,t2,t5,t6} + vadd.f32 q1, q14, q15 @ {t1a,t2a,t5a,t6a} + movrelx r2, X(ff_cos_16) + vsub.f32 q13, q12, q13 @ {t3,t4,t7,t8} + vrev64.32 d1, d1 + vsub.f32 q15, q14, q15 @ {t3a,t4a,t7a,t8a} + vrev64.32 d3, d3 + movrel r3, pmmp + vswp d1, d26 @ q0{t1,t2,t3,t4} q13{t6,t5,t7,t8} + vswp d3, d30 @ q1{t1a,t2a,t3a,t4a} q15{t6a,t5a,t7a,t8a} + vadd.f32 q12, q0, q13 @ {r8,i8,r9,i9} + vadd.f32 q14, q1, q15 @ {r12,i12,r13,i13} + vld1.32 {d4-d5}, [r2,:64] + vsub.f32 q13, q0, q13 @ {r10,i10,r11,i11} + vsub.f32 q15, q1, q15 @ {r14,i14,r15,i15} + vswp d25, d28 @ q12{r8,i8,r12,i12} q14{r9,i9,r13,i13} + vld1.32 {d6-d7}, [r3,:128] + vrev64.32 q1, q14 + vmul.f32 q14, q14, d4[1] + vmul.f32 q1, q1, q3 + vmla.f32 q14, q1, d5[1] @ {t1a,t2a,t5a,t6a} + vswp d27, d30 @ q13{r10,i10,r14,i14} q15{r11,i11,r15,i15} + vzip.32 q12, q14 + vadd.f32 d0, d28, d24 + vadd.f32 d1, d25, d29 + vsub.f32 d2, d25, d29 + vsub.f32 d3, d28, d24 + vsub.f32 q12, q8, q0 @ {r8,r9,i8,i9} + vadd.f32 q8, q8, q0 @ {r0,r1,i0,i1} + vsub.f32 q14, q10, q1 @ {r12,r13,i12,i13} + mov r1, #32 + vadd.f32 q10, q10, q1 @ {r4,r5,i4,i5} + vrev64.32 q0, q13 + vmul.f32 q13, q13, d5[0] + vrev64.32 q1, q15 + vmul.f32 q15, q15, d5[1] + vst2.32 {d16-d17},[r0,:128], r1 + vmul.f32 q0, q0, q3 + vst2.32 {d20-d21},[r0,:128], r1 + vmul.f32 q1, q1, q3 + vmla.f32 q13, q0, d5[0] @ {t1,t2,t5,t6} + vmla.f32 q15, q1, d4[1] @ {t1a,t2a,t5a,t6a} + vst2.32 {d24-d25},[r0,:128], r1 + vst2.32 {d28-d29},[r0,:128] + vzip.32 q13, q15 + sub r0, r0, #80 + vadd.f32 d0, d30, d26 + vadd.f32 d1, d27, d31 + vsub.f32 d2, d27, d31 + vsub.f32 d3, d30, d26 + vsub.f32 q13, q9, q0 @ {r10,r11,i10,i11} + vadd.f32 q9, q9, q0 @ {r2,r3,i2,i3} + vsub.f32 q15, q11, q1 @ {r14,r15,i14,i15} + vadd.f32 q11, q11, q1 @ {r6,r7,i6,i7} + vst2.32 {d18-d19},[r0,:128], r1 + vst2.32 {d22-d23},[r0,:128], r1 + vst2.32 {d26-d27},[r0,:128], r1 + vst2.32 {d30-d31},[r0,:128] + bx lr +endfunc + +function fft_pass_neon + push {r4-r6,lr} + mov r6, r2 @ n + lsl r5, r2, #3 @ 2 * n * sizeof FFTSample + lsl r4, r2, #4 @ 2 * n * sizeof FFTComplex + lsl r2, r2, #5 @ 4 * n * sizeof FFTComplex + add r3, r2, r4 + add r4, r4, r0 @ &z[o1] + add r2, r2, r0 @ &z[o2] + add r3, r3, r0 @ &z[o3] + vld1.32 {d20-d21},[r2,:128] @ {z[o2],z[o2+1]} + movrel r12, pmmp + vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]} + add r5, r5, r1 @ wim + vld1.32 {d6-d7}, [r12,:128] @ pmmp + vswp d21, d22 + vld1.32 {d4}, [r1,:64]! @ {wre[0],wre[1]} + sub r5, r5, #4 @ wim-- + vrev64.32 q1, q11 + vmul.f32 q11, q11, d4[1] + vmul.f32 q1, q1, q3 + vld1.32 {d5[0]}, [r5,:32] @ d5[0] = wim[-1] + vmla.f32 q11, q1, d5[0] @ {t1a,t2a,t5a,t6a} + vld2.32 {d16-d17},[r0,:128] @ {z[0],z[1]} + sub r6, r6, #1 @ n-- + vld2.32 {d18-d19},[r4,:128] @ {z[o1],z[o1+1]} + vzip.32 q10, q11 + vadd.f32 d0, d22, d20 + vadd.f32 d1, d21, d23 + vsub.f32 d2, d21, d23 + vsub.f32 d3, d22, d20 + vsub.f32 q10, q8, q0 + vadd.f32 q8, q8, q0 + vsub.f32 q11, q9, q1 + vadd.f32 q9, q9, q1 + vst2.32 {d20-d21},[r2,:128]! @ {z[o2],z[o2+1]} + vst2.32 {d16-d17},[r0,:128]! @ {z[0],z[1]} + vst2.32 {d22-d23},[r3,:128]! @ {z[o3],z[o3+1]} + vst2.32 {d18-d19},[r4,:128]! @ {z[o1],z[o1+1]} + sub r5, r5, #8 @ wim -= 2 +1: + vld1.32 {d20-d21},[r2,:128] @ {z[o2],z[o2+1]} + vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]} + vswp d21, d22 + vld1.32 {d4}, [r1]! @ {wre[0],wre[1]} + vrev64.32 q0, q10 + vmul.f32 q10, q10, d4[0] + vrev64.32 q1, q11 + vmul.f32 q11, q11, d4[1] + vld1.32 {d5}, [r5] @ {wim[-1],wim[0]} + vmul.f32 q0, q0, q3 + sub r5, r5, #8 @ wim -= 2 + vmul.f32 q1, q1, q3 + vmla.f32 q10, q0, d5[1] @ {t1,t2,t5,t6} + vmla.f32 q11, q1, d5[0] @ {t1a,t2a,t5a,t6a} + vld2.32 {d16-d17},[r0,:128] @ {z[0],z[1]} + subs r6, r6, #1 @ n-- + vld2.32 {d18-d19},[r4,:128] @ {z[o1],z[o1+1]} + vzip.32 q10, q11 + vadd.f32 d0, d22, d20 + vadd.f32 d1, d21, d23 + vsub.f32 d2, d21, d23 + vsub.f32 d3, d22, d20 + vsub.f32 q10, q8, q0 + vadd.f32 q8, q8, q0 + vsub.f32 q11, q9, q1 + vadd.f32 q9, q9, q1 + vst2.32 {d20-d21}, [r2,:128]! @ {z[o2],z[o2+1]} + vst2.32 {d16-d17}, [r0,:128]! @ {z[0],z[1]} + vst2.32 {d22-d23}, [r3,:128]! @ {z[o3],z[o3+1]} + vst2.32 {d18-d19}, [r4,:128]! @ {z[o1],z[o1+1]} + bne 1b + + pop {r4-r6,pc} +endfunc + +.macro def_fft n, n2, n4 + .align 6 +function fft\n\()_neon + push {r4, lr} + mov r4, r0 + bl fft\n2\()_neon + add r0, r4, #\n4*2*8 + bl fft\n4\()_neon + add r0, r4, #\n4*3*8 + bl fft\n4\()_neon + mov r0, r4 + pop {r4, lr} + movrelx r1, X(ff_cos_\n) + mov r2, #\n4/2 + b fft_pass_neon +endfunc +.endm + + def_fft 32, 16, 8 + def_fft 64, 32, 16 + def_fft 128, 64, 32 + def_fft 256, 128, 64 + def_fft 512, 256, 128 + def_fft 1024, 512, 256 + def_fft 2048, 1024, 512 + def_fft 4096, 2048, 1024 + def_fft 8192, 4096, 2048 + def_fft 16384, 8192, 4096 + def_fft 32768, 16384, 8192 + def_fft 65536, 32768, 16384 + +function ff_fft_calc_neon, export=1 + ldr r2, [r0] + sub r2, r2, #2 + movrel r3, fft_tab_neon + ldr r3, [r3, r2, lsl #2] + mov r0, r1 + bx r3 +endfunc + +function ff_fft_permute_neon, export=1 + push {r4,lr} + mov r12, #1 + ldr r2, [r0] @ nbits + ldr r3, [r0, #12] @ tmp_buf + ldr r0, [r0, #8] @ revtab + lsl r12, r12, r2 + mov r2, r12 +1: + vld1.32 {d0-d1}, [r1,:128]! + ldr r4, [r0], #4 + uxth lr, r4 + uxth r4, r4, ror #16 + add lr, r3, lr, lsl #3 + add r4, r3, r4, lsl #3 + vst1.32 {d0}, [lr,:64] + vst1.32 {d1}, [r4,:64] + subs r12, r12, #2 + bgt 1b + + sub r1, r1, r2, lsl #3 +1: + vld1.32 {d0-d3}, [r3,:128]! + vst1.32 {d0-d3}, [r1,:128]! + subs r2, r2, #4 + bgt 1b + + pop {r4,pc} +endfunc + +const fft_tab_neon + .word fft4_neon + .word fft8_neon + .word fft16_neon + .word fft32_neon + .word fft64_neon + .word fft128_neon + .word fft256_neon + .word fft512_neon + .word fft1024_neon + .word fft2048_neon + .word fft4096_neon + .word fft8192_neon + .word fft16384_neon + .word fft32768_neon + .word fft65536_neon +endconst + +const pmmp, align=4 + .float +1.0, -1.0, -1.0, +1.0 +endconst + +const mppm, align=4 + .float -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2 +endconst diff --git a/ffmpeg/libavcodec/arm/flacdsp_arm.S b/ffmpeg/libavcodec/arm/flacdsp_arm.S new file mode 100644 index 0000000..f8861c5 --- /dev/null +++ b/ffmpeg/libavcodec/arm/flacdsp_arm.S @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function flac_lpc_16_1_arm + ldr r12, [sp] + push {r4, lr} + ldr r1, [r1] + subs r12, r12, #2 + ldr lr, [r0], #4 + beq 2f + it lt + poplt {r4, pc} +1: + mul r4, lr, r1 + ldm r0, {r2, lr} + add_sh r2, r2, r4, asr r3 + mul r4, r2, r1 + subs r12, r12, #2 + add_sh lr, lr, r4, asr r3 + stm r0!, {r2, lr} + bgt 1b + it lt + poplt {r4, pc} +2: + mul r4, lr, r1 + ldr r2, [r0] + add_sh r2, r2, r4, asr r3 + str r2, [r0] + pop {r4, pc} +endfunc + +function flac_lpc_16_2_arm + ldr r12, [sp] + subs r12, r12, r2 + it le + bxle lr + + push {r4-r9, lr} + ldm r0!, {r6, r7} + ldm r1, {r8, r9} + subs r12, r12, #1 + beq 2f +1: + mul r4, r6, r8 + mul r5, r7, r8 + mla r4, r7, r9, r4 + ldm r0, {r6, r7} + add_sh r6, r6, r4, asr r3 + mla r5, r6, r9, r5 + add_sh r7, r7, r5, asr r3 + stm r0!, {r6, r7} + subs r12, r12, #2 + bgt 1b + it lt + poplt {r4-r9, pc} +2: + mul r4, r6, r8 + mla r4, r7, r9, r4 + ldr r5, [r0] + add_sh r5, r5, r4, asr r3 + str r5, [r0] + pop {r4-r9, pc} +endfunc + +function ff_flac_lpc_16_arm, export=1 + cmp r2, #2 + blt flac_lpc_16_1_arm + beq flac_lpc_16_2_arm + + ldr r12, [sp] + subs r12, r12, r2 + it le + bxle lr + + push {r4-r9, lr} + + subs r12, r12, #1 + beq 3f +1: + sub lr, r2, #2 + mov r4, #0 + mov r5, #0 + + ldr r7, [r0], #4 + ldr r9, [r1], #4 +2: + mla r4, r7, r9, r4 + ldm r0!, {r6, r7} + mla r5, r6, r9, r5 + ldm r1!, {r8, r9} + mla r4, r6, r8, r4 + subs lr, lr, #2 + mla r5, r7, r8, r5 + bgt 2b + blt 6f + + mla r4, r7, r9, r4 + ldr r7, [r0], #4 + mla r5, r7, r9, r5 + ldr r9, [r1], #4 +6: + mla r4, r7, r9, r4 + ldm r0, {r6, r7} + add_sh r6, r6, r4, asr r3 + mla r5, r6, r9, r5 + add_sh r7, r7, r5, asr r3 + stm r0!, {r6, r7} + sub r0, r0, r2, lsl #2 + sub r1, r1, r2, lsl #2 + + subs r12, r12, #2 + bgt 1b + it lt + poplt {r4-r9, pc} +3: + mov r4, #0 +4: + ldr r5, [r1], #4 + ldr r6, [r0], #4 + mla r4, r5, r6, r4 + subs r2, r2, #1 + bgt 4b + ldr r5, [r0] + add_sh r5, r5, r4, asr r3 + str r5, [r0] + pop {r4-r9, pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/flacdsp_init_arm.c b/ffmpeg/libavcodec/arm/flacdsp_init_arm.c new file mode 100644 index 0000000..9b93942 --- /dev/null +++ b/ffmpeg/libavcodec/arm/flacdsp_init_arm.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * 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 "libavcodec/flacdsp.h" +#include "config.h" + +void ff_flac_lpc_16_arm(int32_t *samples, const int coeffs[32], int order, + int qlevel, int len); + +av_cold void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, + int bps) +{ + if (bps <= 16) + c->lpc = ff_flac_lpc_16_arm; +} diff --git a/ffmpeg/libavcodec/arm/fmtconvert_init_arm.c b/ffmpeg/libavcodec/arm/fmtconvert_init_arm.c new file mode 100644 index 0000000..1d99c97 --- /dev/null +++ b/ffmpeg/libavcodec/arm/fmtconvert_init_arm.c @@ -0,0 +1,52 @@ +/* + * ARM optimized Format Conversion Utils + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/fmtconvert.h" + +void ff_int32_to_float_fmul_scalar_neon(float *dst, const int *src, + float mul, int len); + +void ff_float_to_int16_neon(int16_t *dst, const float *src, long len); +void ff_float_to_int16_interleave_neon(int16_t *, const float **, long, int); + +void ff_float_to_int16_vfp(int16_t *dst, const float *src, long len); + +av_cold void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_vfp(cpu_flags) && have_armv6(cpu_flags)) { + c->float_to_int16 = ff_float_to_int16_vfp; + } + + if (have_neon(cpu_flags)) { + c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_neon; + + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->float_to_int16 = ff_float_to_int16_neon; + c->float_to_int16_interleave = ff_float_to_int16_interleave_neon; + } + } +} diff --git a/ffmpeg/libavcodec/arm/fmtconvert_neon.S b/ffmpeg/libavcodec/arm/fmtconvert_neon.S new file mode 100644 index 0000000..55d070e --- /dev/null +++ b/ffmpeg/libavcodec/arm/fmtconvert_neon.S @@ -0,0 +1,392 @@ +/* + * ARM NEON optimised Format Conversion Utils + * Copyright (c) 2008 Mans Rullgard + * + * 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 "config.h" +#include "libavutil/arm/asm.S" + +function ff_float_to_int16_neon, export=1 + subs r2, r2, #8 + vld1.64 {d0-d1}, [r1,:128]! + vcvt.s32.f32 q8, q0, #16 + vld1.64 {d2-d3}, [r1,:128]! + vcvt.s32.f32 q9, q1, #16 + beq 3f + bics ip, r2, #15 + beq 2f +1: subs ip, ip, #16 + vshrn.s32 d4, q8, #16 + vld1.64 {d0-d1}, [r1,:128]! + vcvt.s32.f32 q0, q0, #16 + vshrn.s32 d5, q9, #16 + vld1.64 {d2-d3}, [r1,:128]! + vcvt.s32.f32 q1, q1, #16 + vshrn.s32 d6, q0, #16 + vst1.64 {d4-d5}, [r0,:128]! + vshrn.s32 d7, q1, #16 + vld1.64 {d16-d17},[r1,:128]! + vcvt.s32.f32 q8, q8, #16 + vld1.64 {d18-d19},[r1,:128]! + vcvt.s32.f32 q9, q9, #16 + vst1.64 {d6-d7}, [r0,:128]! + bne 1b + ands r2, r2, #15 + beq 3f +2: vld1.64 {d0-d1}, [r1,:128]! + vshrn.s32 d4, q8, #16 + vcvt.s32.f32 q0, q0, #16 + vld1.64 {d2-d3}, [r1,:128]! + vshrn.s32 d5, q9, #16 + vcvt.s32.f32 q1, q1, #16 + vshrn.s32 d6, q0, #16 + vst1.64 {d4-d5}, [r0,:128]! + vshrn.s32 d7, q1, #16 + vst1.64 {d6-d7}, [r0,:128]! + bx lr +3: vshrn.s32 d4, q8, #16 + vshrn.s32 d5, q9, #16 + vst1.64 {d4-d5}, [r0,:128]! + bx lr +endfunc + +function ff_float_to_int16_interleave_neon, export=1 + cmp r3, #2 + itt lt + ldrlt r1, [r1] + blt ff_float_to_int16_neon + bne 4f + + ldr r3, [r1] + ldr r1, [r1, #4] + + subs r2, r2, #8 + vld1.64 {d0-d1}, [r3,:128]! + vcvt.s32.f32 q8, q0, #16 + vld1.64 {d2-d3}, [r3,:128]! + vcvt.s32.f32 q9, q1, #16 + vld1.64 {d20-d21},[r1,:128]! + vcvt.s32.f32 q10, q10, #16 + vld1.64 {d22-d23},[r1,:128]! + vcvt.s32.f32 q11, q11, #16 + beq 3f + bics ip, r2, #15 + beq 2f +1: subs ip, ip, #16 + vld1.64 {d0-d1}, [r3,:128]! + vcvt.s32.f32 q0, q0, #16 + vsri.32 q10, q8, #16 + vld1.64 {d2-d3}, [r3,:128]! + vcvt.s32.f32 q1, q1, #16 + vld1.64 {d24-d25},[r1,:128]! + vcvt.s32.f32 q12, q12, #16 + vld1.64 {d26-d27},[r1,:128]! + vsri.32 q11, q9, #16 + vst1.64 {d20-d21},[r0,:128]! + vcvt.s32.f32 q13, q13, #16 + vst1.64 {d22-d23},[r0,:128]! + vsri.32 q12, q0, #16 + vld1.64 {d16-d17},[r3,:128]! + vsri.32 q13, q1, #16 + vst1.64 {d24-d25},[r0,:128]! + vcvt.s32.f32 q8, q8, #16 + vld1.64 {d18-d19},[r3,:128]! + vcvt.s32.f32 q9, q9, #16 + vld1.64 {d20-d21},[r1,:128]! + vcvt.s32.f32 q10, q10, #16 + vld1.64 {d22-d23},[r1,:128]! + vcvt.s32.f32 q11, q11, #16 + vst1.64 {d26-d27},[r0,:128]! + bne 1b + ands r2, r2, #15 + beq 3f +2: vsri.32 q10, q8, #16 + vld1.64 {d0-d1}, [r3,:128]! + vcvt.s32.f32 q0, q0, #16 + vld1.64 {d2-d3}, [r3,:128]! + vcvt.s32.f32 q1, q1, #16 + vld1.64 {d24-d25},[r1,:128]! + vcvt.s32.f32 q12, q12, #16 + vsri.32 q11, q9, #16 + vld1.64 {d26-d27},[r1,:128]! + vcvt.s32.f32 q13, q13, #16 + vst1.64 {d20-d21},[r0,:128]! + vsri.32 q12, q0, #16 + vst1.64 {d22-d23},[r0,:128]! + vsri.32 q13, q1, #16 + vst1.64 {d24-d27},[r0,:128]! + bx lr +3: vsri.32 q10, q8, #16 + vsri.32 q11, q9, #16 + vst1.64 {d20-d23},[r0,:128]! + bx lr + +4: push {r4-r8,lr} + cmp r3, #4 + lsl ip, r3, #1 + blt 4f + + @ 4 channels +5: ldmia r1!, {r4-r7} + mov lr, r2 + mov r8, r0 + vld1.64 {d16-d17},[r4,:128]! + vcvt.s32.f32 q8, q8, #16 + vld1.64 {d18-d19},[r5,:128]! + vcvt.s32.f32 q9, q9, #16 + vld1.64 {d20-d21},[r6,:128]! + vcvt.s32.f32 q10, q10, #16 + vld1.64 {d22-d23},[r7,:128]! + vcvt.s32.f32 q11, q11, #16 +6: subs lr, lr, #8 + vld1.64 {d0-d1}, [r4,:128]! + vcvt.s32.f32 q0, q0, #16 + vsri.32 q9, q8, #16 + vld1.64 {d2-d3}, [r5,:128]! + vcvt.s32.f32 q1, q1, #16 + vsri.32 q11, q10, #16 + vld1.64 {d4-d5}, [r6,:128]! + vcvt.s32.f32 q2, q2, #16 + vzip.32 d18, d22 + vld1.64 {d6-d7}, [r7,:128]! + vcvt.s32.f32 q3, q3, #16 + vzip.32 d19, d23 + vst1.64 {d18}, [r8], ip + vsri.32 q1, q0, #16 + vst1.64 {d22}, [r8], ip + vsri.32 q3, q2, #16 + vst1.64 {d19}, [r8], ip + vzip.32 d2, d6 + vst1.64 {d23}, [r8], ip + vzip.32 d3, d7 + beq 7f + vld1.64 {d16-d17},[r4,:128]! + vcvt.s32.f32 q8, q8, #16 + vst1.64 {d2}, [r8], ip + vld1.64 {d18-d19},[r5,:128]! + vcvt.s32.f32 q9, q9, #16 + vst1.64 {d6}, [r8], ip + vld1.64 {d20-d21},[r6,:128]! + vcvt.s32.f32 q10, q10, #16 + vst1.64 {d3}, [r8], ip + vld1.64 {d22-d23},[r7,:128]! + vcvt.s32.f32 q11, q11, #16 + vst1.64 {d7}, [r8], ip + b 6b +7: vst1.64 {d2}, [r8], ip + vst1.64 {d6}, [r8], ip + vst1.64 {d3}, [r8], ip + vst1.64 {d7}, [r8], ip + subs r3, r3, #4 + it eq + popeq {r4-r8,pc} + cmp r3, #4 + add r0, r0, #8 + bge 5b + + @ 2 channels +4: cmp r3, #2 + blt 4f + ldmia r1!, {r4-r5} + mov lr, r2 + mov r8, r0 + tst lr, #8 + vld1.64 {d16-d17},[r4,:128]! + vcvt.s32.f32 q8, q8, #16 + vld1.64 {d18-d19},[r5,:128]! + vcvt.s32.f32 q9, q9, #16 + vld1.64 {d20-d21},[r4,:128]! + vcvt.s32.f32 q10, q10, #16 + vld1.64 {d22-d23},[r5,:128]! + vcvt.s32.f32 q11, q11, #16 + beq 6f + subs lr, lr, #8 + beq 7f + vsri.32 d18, d16, #16 + vsri.32 d19, d17, #16 + vld1.64 {d16-d17},[r4,:128]! + vcvt.s32.f32 q8, q8, #16 + vst1.32 {d18[0]}, [r8], ip + vsri.32 d22, d20, #16 + vst1.32 {d18[1]}, [r8], ip + vsri.32 d23, d21, #16 + vst1.32 {d19[0]}, [r8], ip + vst1.32 {d19[1]}, [r8], ip + vld1.64 {d18-d19},[r5,:128]! + vcvt.s32.f32 q9, q9, #16 + vst1.32 {d22[0]}, [r8], ip + vst1.32 {d22[1]}, [r8], ip + vld1.64 {d20-d21},[r4,:128]! + vcvt.s32.f32 q10, q10, #16 + vst1.32 {d23[0]}, [r8], ip + vst1.32 {d23[1]}, [r8], ip + vld1.64 {d22-d23},[r5,:128]! + vcvt.s32.f32 q11, q11, #16 +6: subs lr, lr, #16 + vld1.64 {d0-d1}, [r4,:128]! + vcvt.s32.f32 q0, q0, #16 + vsri.32 d18, d16, #16 + vld1.64 {d2-d3}, [r5,:128]! + vcvt.s32.f32 q1, q1, #16 + vsri.32 d19, d17, #16 + vld1.64 {d4-d5}, [r4,:128]! + vcvt.s32.f32 q2, q2, #16 + vld1.64 {d6-d7}, [r5,:128]! + vcvt.s32.f32 q3, q3, #16 + vst1.32 {d18[0]}, [r8], ip + vsri.32 d22, d20, #16 + vst1.32 {d18[1]}, [r8], ip + vsri.32 d23, d21, #16 + vst1.32 {d19[0]}, [r8], ip + vsri.32 d2, d0, #16 + vst1.32 {d19[1]}, [r8], ip + vsri.32 d3, d1, #16 + vst1.32 {d22[0]}, [r8], ip + vsri.32 d6, d4, #16 + vst1.32 {d22[1]}, [r8], ip + vsri.32 d7, d5, #16 + vst1.32 {d23[0]}, [r8], ip + vst1.32 {d23[1]}, [r8], ip + beq 6f + vld1.64 {d16-d17},[r4,:128]! + vcvt.s32.f32 q8, q8, #16 + vst1.32 {d2[0]}, [r8], ip + vst1.32 {d2[1]}, [r8], ip + vld1.64 {d18-d19},[r5,:128]! + vcvt.s32.f32 q9, q9, #16 + vst1.32 {d3[0]}, [r8], ip + vst1.32 {d3[1]}, [r8], ip + vld1.64 {d20-d21},[r4,:128]! + vcvt.s32.f32 q10, q10, #16 + vst1.32 {d6[0]}, [r8], ip + vst1.32 {d6[1]}, [r8], ip + vld1.64 {d22-d23},[r5,:128]! + vcvt.s32.f32 q11, q11, #16 + vst1.32 {d7[0]}, [r8], ip + vst1.32 {d7[1]}, [r8], ip + bgt 6b +6: vst1.32 {d2[0]}, [r8], ip + vst1.32 {d2[1]}, [r8], ip + vst1.32 {d3[0]}, [r8], ip + vst1.32 {d3[1]}, [r8], ip + vst1.32 {d6[0]}, [r8], ip + vst1.32 {d6[1]}, [r8], ip + vst1.32 {d7[0]}, [r8], ip + vst1.32 {d7[1]}, [r8], ip + b 8f +7: vsri.32 d18, d16, #16 + vsri.32 d19, d17, #16 + vst1.32 {d18[0]}, [r8], ip + vsri.32 d22, d20, #16 + vst1.32 {d18[1]}, [r8], ip + vsri.32 d23, d21, #16 + vst1.32 {d19[0]}, [r8], ip + vst1.32 {d19[1]}, [r8], ip + vst1.32 {d22[0]}, [r8], ip + vst1.32 {d22[1]}, [r8], ip + vst1.32 {d23[0]}, [r8], ip + vst1.32 {d23[1]}, [r8], ip +8: subs r3, r3, #2 + add r0, r0, #4 + it eq + popeq {r4-r8,pc} + + @ 1 channel +4: ldr r4, [r1],#4 + tst r2, #8 + mov lr, r2 + mov r5, r0 + vld1.64 {d0-d1}, [r4,:128]! + vcvt.s32.f32 q0, q0, #16 + vld1.64 {d2-d3}, [r4,:128]! + vcvt.s32.f32 q1, q1, #16 + bne 8f +6: subs lr, lr, #16 + vld1.64 {d4-d5}, [r4,:128]! + vcvt.s32.f32 q2, q2, #16 + vld1.64 {d6-d7}, [r4,:128]! + vcvt.s32.f32 q3, q3, #16 + vst1.16 {d0[1]}, [r5,:16], ip + vst1.16 {d0[3]}, [r5,:16], ip + vst1.16 {d1[1]}, [r5,:16], ip + vst1.16 {d1[3]}, [r5,:16], ip + vst1.16 {d2[1]}, [r5,:16], ip + vst1.16 {d2[3]}, [r5,:16], ip + vst1.16 {d3[1]}, [r5,:16], ip + vst1.16 {d3[3]}, [r5,:16], ip + beq 7f + vld1.64 {d0-d1}, [r4,:128]! + vcvt.s32.f32 q0, q0, #16 + vld1.64 {d2-d3}, [r4,:128]! + vcvt.s32.f32 q1, q1, #16 +7: vst1.16 {d4[1]}, [r5,:16], ip + vst1.16 {d4[3]}, [r5,:16], ip + vst1.16 {d5[1]}, [r5,:16], ip + vst1.16 {d5[3]}, [r5,:16], ip + vst1.16 {d6[1]}, [r5,:16], ip + vst1.16 {d6[3]}, [r5,:16], ip + vst1.16 {d7[1]}, [r5,:16], ip + vst1.16 {d7[3]}, [r5,:16], ip + bgt 6b + pop {r4-r8,pc} +8: subs lr, lr, #8 + vst1.16 {d0[1]}, [r5,:16], ip + vst1.16 {d0[3]}, [r5,:16], ip + vst1.16 {d1[1]}, [r5,:16], ip + vst1.16 {d1[3]}, [r5,:16], ip + vst1.16 {d2[1]}, [r5,:16], ip + vst1.16 {d2[3]}, [r5,:16], ip + vst1.16 {d3[1]}, [r5,:16], ip + vst1.16 {d3[3]}, [r5,:16], ip + it eq + popeq {r4-r8,pc} + vld1.64 {d0-d1}, [r4,:128]! + vcvt.s32.f32 q0, q0, #16 + vld1.64 {d2-d3}, [r4,:128]! + vcvt.s32.f32 q1, q1, #16 + b 6b +endfunc + +function ff_int32_to_float_fmul_scalar_neon, export=1 +VFP vdup.32 q0, d0[0] +VFP len .req r2 +NOVFP vdup.32 q0, r2 +NOVFP len .req r3 + + vld1.32 {q1},[r1,:128]! + vcvt.f32.s32 q3, q1 + vld1.32 {q2},[r1,:128]! + vcvt.f32.s32 q8, q2 +1: subs len, len, #8 + pld [r1, #16] + vmul.f32 q9, q3, q0 + vmul.f32 q10, q8, q0 + beq 2f + vld1.32 {q1},[r1,:128]! + vcvt.f32.s32 q3, q1 + vld1.32 {q2},[r1,:128]! + vcvt.f32.s32 q8, q2 + vst1.32 {q9}, [r0,:128]! + vst1.32 {q10},[r0,:128]! + b 1b +2: vst1.32 {q9}, [r0,:128]! + vst1.32 {q10},[r0,:128]! + bx lr + .unreq len +endfunc diff --git a/ffmpeg/libavcodec/arm/fmtconvert_vfp.S b/ffmpeg/libavcodec/arm/fmtconvert_vfp.S new file mode 100644 index 0000000..7b012bc --- /dev/null +++ b/ffmpeg/libavcodec/arm/fmtconvert_vfp.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2008 Siarhei Siamashka + * + * 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 "config.h" +#include "libavutil/arm/asm.S" + +/** + * ARM VFP optimized float to int16 conversion. + * Assume that len is a positive number and is multiple of 8, destination + * buffer is at least 4 bytes aligned (8 bytes alignment is better for + * performance), little-endian byte sex. + */ +@ void ff_float_to_int16_vfp(int16_t *dst, const float *src, int len) +function ff_float_to_int16_vfp, export=1 + push {r4-r8,lr} + vpush {d8-d11} + vldmia r1!, {s16-s23} + vcvt.s32.f32 s0, s16 + vcvt.s32.f32 s1, s17 + vcvt.s32.f32 s2, s18 + vcvt.s32.f32 s3, s19 + vcvt.s32.f32 s4, s20 + vcvt.s32.f32 s5, s21 + vcvt.s32.f32 s6, s22 + vcvt.s32.f32 s7, s23 +1: + subs r2, r2, #8 + vmov r3, r4, s0, s1 + vmov r5, r6, s2, s3 + vmov r7, r8, s4, s5 + vmov ip, lr, s6, s7 + it gt + vldmiagt r1!, {s16-s23} + ssat r4, #16, r4 + ssat r3, #16, r3 + ssat r6, #16, r6 + ssat r5, #16, r5 + pkhbt r3, r3, r4, lsl #16 + pkhbt r4, r5, r6, lsl #16 + itttt gt + vcvtgt.s32.f32 s0, s16 + vcvtgt.s32.f32 s1, s17 + vcvtgt.s32.f32 s2, s18 + vcvtgt.s32.f32 s3, s19 + itttt gt + vcvtgt.s32.f32 s4, s20 + vcvtgt.s32.f32 s5, s21 + vcvtgt.s32.f32 s6, s22 + vcvtgt.s32.f32 s7, s23 + ssat r8, #16, r8 + ssat r7, #16, r7 + ssat lr, #16, lr + ssat ip, #16, ip + pkhbt r5, r7, r8, lsl #16 + pkhbt r6, ip, lr, lsl #16 + stmia r0!, {r3-r6} + bgt 1b + + vpop {d8-d11} + pop {r4-r8,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/h264chroma_init_arm.c b/ffmpeg/libavcodec/arm/h264chroma_init_arm.c new file mode 100644 index 0000000..13f7e0d --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264chroma_init_arm.c @@ -0,0 +1,51 @@ +/* + * ARM NEON optimised H.264 chroma functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/h264chroma.h" + +void ff_put_h264_chroma_mc8_neon(uint8_t *, uint8_t *, int, int, int, int); +void ff_put_h264_chroma_mc4_neon(uint8_t *, uint8_t *, int, int, int, int); +void ff_put_h264_chroma_mc2_neon(uint8_t *, uint8_t *, int, int, int, int); + +void ff_avg_h264_chroma_mc8_neon(uint8_t *, uint8_t *, int, int, int, int); +void ff_avg_h264_chroma_mc4_neon(uint8_t *, uint8_t *, int, int, int, int); +void ff_avg_h264_chroma_mc2_neon(uint8_t *, uint8_t *, int, int, int, int); + +av_cold void ff_h264chroma_init_arm(H264ChromaContext *c, int bit_depth) +{ + const int high_bit_depth = bit_depth > 8; + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags) && !high_bit_depth) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_neon; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_neon; + c->put_h264_chroma_pixels_tab[2] = ff_put_h264_chroma_mc2_neon; + + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_neon; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_neon; + c->avg_h264_chroma_pixels_tab[2] = ff_avg_h264_chroma_mc2_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/h264cmc_neon.S b/ffmpeg/libavcodec/arm/h264cmc_neon.S new file mode 100644 index 0000000..3427e36 --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264cmc_neon.S @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +/* chroma_mc8(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y) */ +.macro h264_chroma_mc8 type, codec=h264 +function ff_\type\()_\codec\()_chroma_mc8_neon, export=1 + push {r4-r7, lr} + ldrd r4, r5, [sp, #20] + .ifc \type,avg + mov lr, r0 + .endif + pld [r1] + pld [r1, r2] + + .ifc \codec,rv40 + movrel r6, rv40bias + lsr r7, r5, #1 + add r6, r6, r7, lsl #3 + lsr r7, r4, #1 + add r6, r6, r7, lsl #1 + vld1.16 {d22[],d23[]}, [r6,:16] + .endif + +A muls r7, r4, r5 +T mul r7, r4, r5 +T cmp r7, #0 + rsb r6, r7, r5, lsl #3 + rsb r12, r7, r4, lsl #3 + sub r4, r7, r4, lsl #3 + sub r4, r4, r5, lsl #3 + add r4, r4, #64 + + beq 2f + + vdup.8 d0, r4 + vdup.8 d1, r12 + vld1.8 {d4, d5}, [r1], r2 + vdup.8 d2, r6 + vdup.8 d3, r7 + vext.8 d5, d4, d5, #1 + +1: vld1.8 {d6, d7}, [r1], r2 + vmull.u8 q8, d4, d0 + vmlal.u8 q8, d5, d1 + vext.8 d7, d6, d7, #1 + vld1.8 {d4, d5}, [r1], r2 + vmlal.u8 q8, d6, d2 + pld [r1] + vext.8 d5, d4, d5, #1 + vmlal.u8 q8, d7, d3 + vmull.u8 q9, d6, d0 + subs r3, r3, #2 + vmlal.u8 q9, d7, d1 + vmlal.u8 q9, d4, d2 + vmlal.u8 q9, d5, d3 + pld [r1, r2] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + vrshrn.u16 d17, q9, #6 + .else + vadd.u16 q8, q8, q11 + vadd.u16 q9, q9, q11 + vshrn.u16 d16, q8, #6 + vshrn.u16 d17, q9, #6 + .endif + .ifc \type,avg + vld1.8 {d20}, [lr,:64], r2 + vld1.8 {d21}, [lr,:64], r2 + vrhadd.u8 q8, q8, q10 + .endif + vst1.8 {d16}, [r0,:64], r2 + vst1.8 {d17}, [r0,:64], r2 + bgt 1b + + pop {r4-r7, pc} + +2: tst r6, r6 + add r12, r12, r6 + vdup.8 d0, r4 + vdup.8 d1, r12 + + beq 4f + + vld1.8 {d4}, [r1], r2 + +3: vld1.8 {d6}, [r1], r2 + vmull.u8 q8, d4, d0 + vmlal.u8 q8, d6, d1 + vld1.8 {d4}, [r1], r2 + vmull.u8 q9, d6, d0 + vmlal.u8 q9, d4, d1 + pld [r1] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + vrshrn.u16 d17, q9, #6 + .else + vadd.u16 q8, q8, q11 + vadd.u16 q9, q9, q11 + vshrn.u16 d16, q8, #6 + vshrn.u16 d17, q9, #6 + .endif + pld [r1, r2] + .ifc \type,avg + vld1.8 {d20}, [lr,:64], r2 + vld1.8 {d21}, [lr,:64], r2 + vrhadd.u8 q8, q8, q10 + .endif + subs r3, r3, #2 + vst1.8 {d16}, [r0,:64], r2 + vst1.8 {d17}, [r0,:64], r2 + bgt 3b + + pop {r4-r7, pc} + +4: vld1.8 {d4, d5}, [r1], r2 + vld1.8 {d6, d7}, [r1], r2 + vext.8 d5, d4, d5, #1 + vext.8 d7, d6, d7, #1 + pld [r1] + subs r3, r3, #2 + vmull.u8 q8, d4, d0 + vmlal.u8 q8, d5, d1 + vmull.u8 q9, d6, d0 + vmlal.u8 q9, d7, d1 + pld [r1, r2] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + vrshrn.u16 d17, q9, #6 + .else + vadd.u16 q8, q8, q11 + vadd.u16 q9, q9, q11 + vshrn.u16 d16, q8, #6 + vshrn.u16 d17, q9, #6 + .endif + .ifc \type,avg + vld1.8 {d20}, [lr,:64], r2 + vld1.8 {d21}, [lr,:64], r2 + vrhadd.u8 q8, q8, q10 + .endif + vst1.8 {d16}, [r0,:64], r2 + vst1.8 {d17}, [r0,:64], r2 + bgt 4b + + pop {r4-r7, pc} +endfunc +.endm + +/* chroma_mc4(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y) */ +.macro h264_chroma_mc4 type, codec=h264 +function ff_\type\()_\codec\()_chroma_mc4_neon, export=1 + push {r4-r7, lr} + ldrd r4, r5, [sp, #20] + .ifc \type,avg + mov lr, r0 + .endif + pld [r1] + pld [r1, r2] + + .ifc \codec,rv40 + movrel r6, rv40bias + lsr r7, r5, #1 + add r6, r6, r7, lsl #3 + lsr r7, r4, #1 + add r6, r6, r7, lsl #1 + vld1.16 {d22[],d23[]}, [r6,:16] + .endif + +A muls r7, r4, r5 +T mul r7, r4, r5 +T cmp r7, #0 + rsb r6, r7, r5, lsl #3 + rsb r12, r7, r4, lsl #3 + sub r4, r7, r4, lsl #3 + sub r4, r4, r5, lsl #3 + add r4, r4, #64 + + beq 2f + + vdup.8 d0, r4 + vdup.8 d1, r12 + vld1.8 {d4}, [r1], r2 + vdup.8 d2, r6 + vdup.8 d3, r7 + + vext.8 d5, d4, d5, #1 + vtrn.32 d4, d5 + + vtrn.32 d0, d1 + vtrn.32 d2, d3 + +1: vld1.8 {d6}, [r1], r2 + vext.8 d7, d6, d7, #1 + vtrn.32 d6, d7 + vmull.u8 q8, d4, d0 + vmlal.u8 q8, d6, d2 + vld1.8 {d4}, [r1], r2 + vext.8 d5, d4, d5, #1 + vtrn.32 d4, d5 + pld [r1] + vmull.u8 q9, d6, d0 + vmlal.u8 q9, d4, d2 + vadd.i16 d16, d16, d17 + vadd.i16 d17, d18, d19 + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + .else + vadd.u16 q8, q8, q11 + vshrn.u16 d16, q8, #6 + .endif + subs r3, r3, #2 + pld [r1, r2] + .ifc \type,avg + vld1.32 {d20[0]}, [lr,:32], r2 + vld1.32 {d20[1]}, [lr,:32], r2 + vrhadd.u8 d16, d16, d20 + .endif + vst1.32 {d16[0]}, [r0,:32], r2 + vst1.32 {d16[1]}, [r0,:32], r2 + bgt 1b + + pop {r4-r7, pc} + +2: tst r6, r6 + add r12, r12, r6 + vdup.8 d0, r4 + vdup.8 d1, r12 + vtrn.32 d0, d1 + + beq 4f + + vext.32 d1, d0, d1, #1 + vld1.32 {d4[0]}, [r1], r2 + +3: vld1.32 {d4[1]}, [r1], r2 + vmull.u8 q8, d4, d0 + vld1.32 {d4[0]}, [r1], r2 + vmull.u8 q9, d4, d1 + vadd.i16 d16, d16, d17 + vadd.i16 d17, d18, d19 + pld [r1] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + .else + vadd.u16 q8, q8, q11 + vshrn.u16 d16, q8, #6 + .endif + .ifc \type,avg + vld1.32 {d20[0]}, [lr,:32], r2 + vld1.32 {d20[1]}, [lr,:32], r2 + vrhadd.u8 d16, d16, d20 + .endif + subs r3, r3, #2 + pld [r1, r2] + vst1.32 {d16[0]}, [r0,:32], r2 + vst1.32 {d16[1]}, [r0,:32], r2 + bgt 3b + + pop {r4-r7, pc} + +4: vld1.8 {d4}, [r1], r2 + vld1.8 {d6}, [r1], r2 + vext.8 d5, d4, d5, #1 + vext.8 d7, d6, d7, #1 + vtrn.32 d4, d5 + vtrn.32 d6, d7 + vmull.u8 q8, d4, d0 + vmull.u8 q9, d6, d0 + subs r3, r3, #2 + vadd.i16 d16, d16, d17 + vadd.i16 d17, d18, d19 + pld [r1] + .ifc \codec,h264 + vrshrn.u16 d16, q8, #6 + .else + vadd.u16 q8, q8, q11 + vshrn.u16 d16, q8, #6 + .endif + .ifc \type,avg + vld1.32 {d20[0]}, [lr,:32], r2 + vld1.32 {d20[1]}, [lr,:32], r2 + vrhadd.u8 d16, d16, d20 + .endif + pld [r1] + vst1.32 {d16[0]}, [r0,:32], r2 + vst1.32 {d16[1]}, [r0,:32], r2 + bgt 4b + + pop {r4-r7, pc} +endfunc +.endm + +.macro h264_chroma_mc2 type +function ff_\type\()_h264_chroma_mc2_neon, export=1 + push {r4-r6, lr} + ldr r4, [sp, #16] + ldr lr, [sp, #20] + pld [r1] + pld [r1, r2] + orrs r5, r4, lr + beq 2f + + mul r5, r4, lr + rsb r6, r5, lr, lsl #3 + rsb r12, r5, r4, lsl #3 + sub r4, r5, r4, lsl #3 + sub r4, r4, lr, lsl #3 + add r4, r4, #64 + vdup.8 d0, r4 + vdup.8 d2, r12 + vdup.8 d1, r6 + vdup.8 d3, r5 + vtrn.16 q0, q1 +1: + vld1.32 {d4[0]}, [r1], r2 + vld1.32 {d4[1]}, [r1], r2 + vrev64.32 d5, d4 + vld1.32 {d5[1]}, [r1] + vext.8 q3, q2, q2, #1 + vtrn.16 q2, q3 + vmull.u8 q8, d4, d0 + vmlal.u8 q8, d5, d1 + .ifc \type,avg + vld1.16 {d18[0]}, [r0,:16], r2 + vld1.16 {d18[1]}, [r0,:16] + sub r0, r0, r2 + .endif + vtrn.32 d16, d17 + vadd.i16 d16, d16, d17 + vrshrn.u16 d16, q8, #6 + .ifc \type,avg + vrhadd.u8 d16, d16, d18 + .endif + vst1.16 {d16[0]}, [r0,:16], r2 + vst1.16 {d16[1]}, [r0,:16], r2 + subs r3, r3, #2 + bgt 1b + pop {r4-r6, pc} +2: + .ifc \type,put + ldrh_post r5, r1, r2 + strh_post r5, r0, r2 + ldrh_post r6, r1, r2 + strh_post r6, r0, r2 + .else + vld1.16 {d16[0]}, [r1], r2 + vld1.16 {d16[1]}, [r1], r2 + vld1.16 {d18[0]}, [r0,:16], r2 + vld1.16 {d18[1]}, [r0,:16] + sub r0, r0, r2 + vrhadd.u8 d16, d16, d18 + vst1.16 {d16[0]}, [r0,:16], r2 + vst1.16 {d16[1]}, [r0,:16], r2 + .endif + subs r3, r3, #2 + bgt 2b + pop {r4-r6, pc} +endfunc +.endm + +#if CONFIG_H264_DECODER + h264_chroma_mc8 put + h264_chroma_mc8 avg + h264_chroma_mc4 put + h264_chroma_mc4 avg + h264_chroma_mc2 put + h264_chroma_mc2 avg +#endif + +#if CONFIG_RV40_DECODER +const rv40bias + .short 0, 16, 32, 16 + .short 32, 28, 32, 28 + .short 0, 32, 16, 32 + .short 32, 28, 32, 28 +endconst + + h264_chroma_mc8 put, rv40 + h264_chroma_mc8 avg, rv40 + h264_chroma_mc4 put, rv40 + h264_chroma_mc4 avg, rv40 +#endif diff --git a/ffmpeg/libavcodec/arm/h264dsp_init_arm.c b/ffmpeg/libavcodec/arm/h264dsp_init_arm.c new file mode 100644 index 0000000..785b604 --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264dsp_init_arm.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/h264dsp.h" + +void ff_h264_v_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha, + int beta, int8_t *tc0); +void ff_h264_h_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha, + int beta, int8_t *tc0); +void ff_h264_v_loop_filter_chroma_neon(uint8_t *pix, int stride, int alpha, + int beta, int8_t *tc0); +void ff_h264_h_loop_filter_chroma_neon(uint8_t *pix, int stride, int alpha, + int beta, int8_t *tc0); + +void ff_weight_h264_pixels_16_neon(uint8_t *dst, int stride, int height, + int log2_den, int weight, int offset); +void ff_weight_h264_pixels_8_neon(uint8_t *dst, int stride, int height, + int log2_den, int weight, int offset); +void ff_weight_h264_pixels_4_neon(uint8_t *dst, int stride, int height, + int log2_den, int weight, int offset); + +void ff_biweight_h264_pixels_16_neon(uint8_t *dst, uint8_t *src, int stride, + int height, int log2_den, int weightd, + int weights, int offset); +void ff_biweight_h264_pixels_8_neon(uint8_t *dst, uint8_t *src, int stride, + int height, int log2_den, int weightd, + int weights, int offset); +void ff_biweight_h264_pixels_4_neon(uint8_t *dst, uint8_t *src, int stride, + int height, int log2_den, int weightd, + int weights, int offset); + +void ff_h264_idct_add_neon(uint8_t *dst, int16_t *block, int stride); +void ff_h264_idct_dc_add_neon(uint8_t *dst, int16_t *block, int stride); +void ff_h264_idct_add16_neon(uint8_t *dst, const int *block_offset, + int16_t *block, int stride, + const uint8_t nnzc[6*8]); +void ff_h264_idct_add16intra_neon(uint8_t *dst, const int *block_offset, + int16_t *block, int stride, + const uint8_t nnzc[6*8]); +void ff_h264_idct_add8_neon(uint8_t **dest, const int *block_offset, + int16_t *block, int stride, + const uint8_t nnzc[6*8]); + +void ff_h264_idct8_add_neon(uint8_t *dst, int16_t *block, int stride); +void ff_h264_idct8_dc_add_neon(uint8_t *dst, int16_t *block, int stride); +void ff_h264_idct8_add4_neon(uint8_t *dst, const int *block_offset, + int16_t *block, int stride, + const uint8_t nnzc[6*8]); + +static av_cold void ff_h264dsp_init_neon(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) +{ +#if HAVE_NEON + if (bit_depth == 8) { + c->h264_v_loop_filter_luma = ff_h264_v_loop_filter_luma_neon; + c->h264_h_loop_filter_luma = ff_h264_h_loop_filter_luma_neon; + if(chroma_format_idc == 1){ + c->h264_v_loop_filter_chroma = ff_h264_v_loop_filter_chroma_neon; + c->h264_h_loop_filter_chroma = ff_h264_h_loop_filter_chroma_neon; + } + + c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels_16_neon; + c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels_8_neon; + c->weight_h264_pixels_tab[2] = ff_weight_h264_pixels_4_neon; + + c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels_16_neon; + c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels_8_neon; + c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels_4_neon; + + c->h264_idct_add = ff_h264_idct_add_neon; + c->h264_idct_dc_add = ff_h264_idct_dc_add_neon; + c->h264_idct_add16 = ff_h264_idct_add16_neon; + c->h264_idct_add16intra = ff_h264_idct_add16intra_neon; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_neon; + c->h264_idct8_add = ff_h264_idct8_add_neon; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_neon; + c->h264_idct8_add4 = ff_h264_idct8_add4_neon; + } +#endif // HAVE_NEON +} + +av_cold void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + ff_h264dsp_init_neon(c, bit_depth, chroma_format_idc); +} diff --git a/ffmpeg/libavcodec/arm/h264dsp_neon.S b/ffmpeg/libavcodec/arm/h264dsp_neon.S new file mode 100644 index 0000000..274a547 --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264dsp_neon.S @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" +#include "neon.S" + + /* H.264 loop filter */ + +.macro h264_loop_filter_start + ldr r12, [sp] + tst r2, r2 + ldr r12, [r12] + it ne + tstne r3, r3 + vmov.32 d24[0], r12 + and r12, r12, r12, lsl #16 + it eq + bxeq lr + ands r12, r12, r12, lsl #8 + it lt + bxlt lr +.endm + +.macro h264_loop_filter_luma + vdup.8 q11, r2 @ alpha + vmovl.u8 q12, d24 + vabd.u8 q6, q8, q0 @ abs(p0 - q0) + vmovl.u16 q12, d24 + vabd.u8 q14, q9, q8 @ abs(p1 - p0) + vsli.16 q12, q12, #8 + vabd.u8 q15, q1, q0 @ abs(q1 - q0) + vsli.32 q12, q12, #16 + vclt.u8 q6, q6, q11 @ < alpha + vdup.8 q11, r3 @ beta + vclt.s8 q7, q12, #0 + vclt.u8 q14, q14, q11 @ < beta + vclt.u8 q15, q15, q11 @ < beta + vbic q6, q6, q7 + vabd.u8 q4, q10, q8 @ abs(p2 - p0) + vand q6, q6, q14 + vabd.u8 q5, q2, q0 @ abs(q2 - q0) + vclt.u8 q4, q4, q11 @ < beta + vand q6, q6, q15 + vclt.u8 q5, q5, q11 @ < beta + vand q4, q4, q6 + vand q5, q5, q6 + vand q12, q12, q6 + vrhadd.u8 q14, q8, q0 + vsub.i8 q6, q12, q4 + vqadd.u8 q7, q9, q12 + vhadd.u8 q10, q10, q14 + vsub.i8 q6, q6, q5 + vhadd.u8 q14, q2, q14 + vmin.u8 q7, q7, q10 + vqsub.u8 q11, q9, q12 + vqadd.u8 q2, q1, q12 + vmax.u8 q7, q7, q11 + vqsub.u8 q11, q1, q12 + vmin.u8 q14, q2, q14 + vmovl.u8 q2, d0 + vmax.u8 q14, q14, q11 + vmovl.u8 q10, d1 + vsubw.u8 q2, q2, d16 + vsubw.u8 q10, q10, d17 + vshl.i16 q2, q2, #2 + vshl.i16 q10, q10, #2 + vaddw.u8 q2, q2, d18 + vaddw.u8 q10, q10, d19 + vsubw.u8 q2, q2, d2 + vsubw.u8 q10, q10, d3 + vrshrn.i16 d4, q2, #3 + vrshrn.i16 d5, q10, #3 + vbsl q4, q7, q9 + vbsl q5, q14, q1 + vneg.s8 q7, q6 + vmovl.u8 q14, d16 + vmin.s8 q2, q2, q6 + vmovl.u8 q6, d17 + vmax.s8 q2, q2, q7 + vmovl.u8 q11, d0 + vmovl.u8 q12, d1 + vaddw.s8 q14, q14, d4 + vaddw.s8 q6, q6, d5 + vsubw.s8 q11, q11, d4 + vsubw.s8 q12, q12, d5 + vqmovun.s16 d16, q14 + vqmovun.s16 d17, q6 + vqmovun.s16 d0, q11 + vqmovun.s16 d1, q12 +.endm + +function ff_h264_v_loop_filter_luma_neon, export=1 + h264_loop_filter_start + + vld1.8 {d0, d1}, [r0,:128], r1 + vld1.8 {d2, d3}, [r0,:128], r1 + vld1.8 {d4, d5}, [r0,:128], r1 + sub r0, r0, r1, lsl #2 + sub r0, r0, r1, lsl #1 + vld1.8 {d20,d21}, [r0,:128], r1 + vld1.8 {d18,d19}, [r0,:128], r1 + vld1.8 {d16,d17}, [r0,:128], r1 + + vpush {d8-d15} + + h264_loop_filter_luma + + sub r0, r0, r1, lsl #1 + vst1.8 {d8, d9}, [r0,:128], r1 + vst1.8 {d16,d17}, [r0,:128], r1 + vst1.8 {d0, d1}, [r0,:128], r1 + vst1.8 {d10,d11}, [r0,:128] + + vpop {d8-d15} + bx lr +endfunc + +function ff_h264_h_loop_filter_luma_neon, export=1 + h264_loop_filter_start + + sub r0, r0, #4 + vld1.8 {d6}, [r0], r1 + vld1.8 {d20}, [r0], r1 + vld1.8 {d18}, [r0], r1 + vld1.8 {d16}, [r0], r1 + vld1.8 {d0}, [r0], r1 + vld1.8 {d2}, [r0], r1 + vld1.8 {d4}, [r0], r1 + vld1.8 {d26}, [r0], r1 + vld1.8 {d7}, [r0], r1 + vld1.8 {d21}, [r0], r1 + vld1.8 {d19}, [r0], r1 + vld1.8 {d17}, [r0], r1 + vld1.8 {d1}, [r0], r1 + vld1.8 {d3}, [r0], r1 + vld1.8 {d5}, [r0], r1 + vld1.8 {d27}, [r0], r1 + + transpose_8x8 q3, q10, q9, q8, q0, q1, q2, q13 + + vpush {d8-d15} + + h264_loop_filter_luma + + transpose_4x4 q4, q8, q0, q5 + + sub r0, r0, r1, lsl #4 + add r0, r0, #2 + vst1.32 {d8[0]}, [r0], r1 + vst1.32 {d16[0]}, [r0], r1 + vst1.32 {d0[0]}, [r0], r1 + vst1.32 {d10[0]}, [r0], r1 + vst1.32 {d8[1]}, [r0], r1 + vst1.32 {d16[1]}, [r0], r1 + vst1.32 {d0[1]}, [r0], r1 + vst1.32 {d10[1]}, [r0], r1 + vst1.32 {d9[0]}, [r0], r1 + vst1.32 {d17[0]}, [r0], r1 + vst1.32 {d1[0]}, [r0], r1 + vst1.32 {d11[0]}, [r0], r1 + vst1.32 {d9[1]}, [r0], r1 + vst1.32 {d17[1]}, [r0], r1 + vst1.32 {d1[1]}, [r0], r1 + vst1.32 {d11[1]}, [r0], r1 + + vpop {d8-d15} + bx lr +endfunc + +.macro h264_loop_filter_chroma + vdup.8 d22, r2 @ alpha + vmovl.u8 q12, d24 + vabd.u8 d26, d16, d0 @ abs(p0 - q0) + vmovl.u8 q2, d0 + vabd.u8 d28, d18, d16 @ abs(p1 - p0) + vsubw.u8 q2, q2, d16 + vsli.16 d24, d24, #8 + vshl.i16 q2, q2, #2 + vabd.u8 d30, d2, d0 @ abs(q1 - q0) + vaddw.u8 q2, q2, d18 + vclt.u8 d26, d26, d22 @ < alpha + vsubw.u8 q2, q2, d2 + vdup.8 d22, r3 @ beta + vrshrn.i16 d4, q2, #3 + vclt.u8 d28, d28, d22 @ < beta + vclt.u8 d30, d30, d22 @ < beta + vmin.s8 d4, d4, d24 + vneg.s8 d25, d24 + vand d26, d26, d28 + vmax.s8 d4, d4, d25 + vand d26, d26, d30 + vmovl.u8 q11, d0 + vand d4, d4, d26 + vmovl.u8 q14, d16 + vaddw.s8 q14, q14, d4 + vsubw.s8 q11, q11, d4 + vqmovun.s16 d16, q14 + vqmovun.s16 d0, q11 +.endm + +function ff_h264_v_loop_filter_chroma_neon, export=1 + h264_loop_filter_start + + sub r0, r0, r1, lsl #1 + vld1.8 {d18}, [r0,:64], r1 + vld1.8 {d16}, [r0,:64], r1 + vld1.8 {d0}, [r0,:64], r1 + vld1.8 {d2}, [r0,:64] + + h264_loop_filter_chroma + + sub r0, r0, r1, lsl #1 + vst1.8 {d16}, [r0,:64], r1 + vst1.8 {d0}, [r0,:64], r1 + + bx lr +endfunc + +function ff_h264_h_loop_filter_chroma_neon, export=1 + h264_loop_filter_start + + sub r0, r0, #2 + vld1.32 {d18[0]}, [r0], r1 + vld1.32 {d16[0]}, [r0], r1 + vld1.32 {d0[0]}, [r0], r1 + vld1.32 {d2[0]}, [r0], r1 + vld1.32 {d18[1]}, [r0], r1 + vld1.32 {d16[1]}, [r0], r1 + vld1.32 {d0[1]}, [r0], r1 + vld1.32 {d2[1]}, [r0], r1 + + vtrn.16 d18, d0 + vtrn.16 d16, d2 + vtrn.8 d18, d16 + vtrn.8 d0, d2 + + h264_loop_filter_chroma + + vtrn.16 d18, d0 + vtrn.16 d16, d2 + vtrn.8 d18, d16 + vtrn.8 d0, d2 + + sub r0, r0, r1, lsl #3 + vst1.32 {d18[0]}, [r0], r1 + vst1.32 {d16[0]}, [r0], r1 + vst1.32 {d0[0]}, [r0], r1 + vst1.32 {d2[0]}, [r0], r1 + vst1.32 {d18[1]}, [r0], r1 + vst1.32 {d16[1]}, [r0], r1 + vst1.32 {d0[1]}, [r0], r1 + vst1.32 {d2[1]}, [r0], r1 + + bx lr +endfunc + +@ Biweighted prediction + +.macro biweight_16 macs, macd + vdup.8 d0, r4 + vdup.8 d1, r5 + vmov q2, q8 + vmov q3, q8 +1: subs r3, r3, #2 + vld1.8 {d20-d21},[r0,:128], r2 + \macd q2, d0, d20 + pld [r0] + \macd q3, d0, d21 + vld1.8 {d22-d23},[r1,:128], r2 + \macs q2, d1, d22 + pld [r1] + \macs q3, d1, d23 + vmov q12, q8 + vld1.8 {d28-d29},[r0,:128], r2 + vmov q13, q8 + \macd q12, d0, d28 + pld [r0] + \macd q13, d0, d29 + vld1.8 {d30-d31},[r1,:128], r2 + \macs q12, d1, d30 + pld [r1] + \macs q13, d1, d31 + vshl.s16 q2, q2, q9 + vshl.s16 q3, q3, q9 + vqmovun.s16 d4, q2 + vqmovun.s16 d5, q3 + vshl.s16 q12, q12, q9 + vshl.s16 q13, q13, q9 + vqmovun.s16 d24, q12 + vqmovun.s16 d25, q13 + vmov q3, q8 + vst1.8 {d4- d5}, [r6,:128], r2 + vmov q2, q8 + vst1.8 {d24-d25},[r6,:128], r2 + bne 1b + pop {r4-r6, pc} +.endm + +.macro biweight_8 macs, macd + vdup.8 d0, r4 + vdup.8 d1, r5 + vmov q1, q8 + vmov q10, q8 +1: subs r3, r3, #2 + vld1.8 {d4},[r0,:64], r2 + \macd q1, d0, d4 + pld [r0] + vld1.8 {d5},[r1,:64], r2 + \macs q1, d1, d5 + pld [r1] + vld1.8 {d6},[r0,:64], r2 + \macd q10, d0, d6 + pld [r0] + vld1.8 {d7},[r1,:64], r2 + \macs q10, d1, d7 + pld [r1] + vshl.s16 q1, q1, q9 + vqmovun.s16 d2, q1 + vshl.s16 q10, q10, q9 + vqmovun.s16 d4, q10 + vmov q10, q8 + vst1.8 {d2},[r6,:64], r2 + vmov q1, q8 + vst1.8 {d4},[r6,:64], r2 + bne 1b + pop {r4-r6, pc} +.endm + +.macro biweight_4 macs, macd + vdup.8 d0, r4 + vdup.8 d1, r5 + vmov q1, q8 + vmov q10, q8 +1: subs r3, r3, #4 + vld1.32 {d4[0]},[r0,:32], r2 + vld1.32 {d4[1]},[r0,:32], r2 + \macd q1, d0, d4 + pld [r0] + vld1.32 {d5[0]},[r1,:32], r2 + vld1.32 {d5[1]},[r1,:32], r2 + \macs q1, d1, d5 + pld [r1] + blt 2f + vld1.32 {d6[0]},[r0,:32], r2 + vld1.32 {d6[1]},[r0,:32], r2 + \macd q10, d0, d6 + pld [r0] + vld1.32 {d7[0]},[r1,:32], r2 + vld1.32 {d7[1]},[r1,:32], r2 + \macs q10, d1, d7 + pld [r1] + vshl.s16 q1, q1, q9 + vqmovun.s16 d2, q1 + vshl.s16 q10, q10, q9 + vqmovun.s16 d4, q10 + vmov q10, q8 + vst1.32 {d2[0]},[r6,:32], r2 + vst1.32 {d2[1]},[r6,:32], r2 + vmov q1, q8 + vst1.32 {d4[0]},[r6,:32], r2 + vst1.32 {d4[1]},[r6,:32], r2 + bne 1b + pop {r4-r6, pc} +2: vshl.s16 q1, q1, q9 + vqmovun.s16 d2, q1 + vst1.32 {d2[0]},[r6,:32], r2 + vst1.32 {d2[1]},[r6,:32], r2 + pop {r4-r6, pc} +.endm + +.macro biweight_func w +function ff_biweight_h264_pixels_\w\()_neon, export=1 + push {r4-r6, lr} + ldr r12, [sp, #16] + add r4, sp, #20 + ldm r4, {r4-r6} + lsr lr, r4, #31 + add r6, r6, #1 + eors lr, lr, r5, lsr #30 + orr r6, r6, #1 + vdup.16 q9, r12 + lsl r6, r6, r12 + vmvn q9, q9 + vdup.16 q8, r6 + mov r6, r0 + beq 10f + subs lr, lr, #1 + beq 20f + subs lr, lr, #1 + beq 30f + b 40f +10: biweight_\w vmlal.u8, vmlal.u8 +20: rsb r4, r4, #0 + biweight_\w vmlal.u8, vmlsl.u8 +30: rsb r4, r4, #0 + rsb r5, r5, #0 + biweight_\w vmlsl.u8, vmlsl.u8 +40: rsb r5, r5, #0 + biweight_\w vmlsl.u8, vmlal.u8 +endfunc +.endm + + biweight_func 16 + biweight_func 8 + biweight_func 4 + +@ Weighted prediction + +.macro weight_16 add + vdup.8 d0, r12 +1: subs r2, r2, #2 + vld1.8 {d20-d21},[r0,:128], r1 + vmull.u8 q2, d0, d20 + pld [r0] + vmull.u8 q3, d0, d21 + vld1.8 {d28-d29},[r0,:128], r1 + vmull.u8 q12, d0, d28 + pld [r0] + vmull.u8 q13, d0, d29 + \add q2, q8, q2 + vrshl.s16 q2, q2, q9 + \add q3, q8, q3 + vrshl.s16 q3, q3, q9 + vqmovun.s16 d4, q2 + vqmovun.s16 d5, q3 + \add q12, q8, q12 + vrshl.s16 q12, q12, q9 + \add q13, q8, q13 + vrshl.s16 q13, q13, q9 + vqmovun.s16 d24, q12 + vqmovun.s16 d25, q13 + vst1.8 {d4- d5}, [r4,:128], r1 + vst1.8 {d24-d25},[r4,:128], r1 + bne 1b + pop {r4, pc} +.endm + +.macro weight_8 add + vdup.8 d0, r12 +1: subs r2, r2, #2 + vld1.8 {d4},[r0,:64], r1 + vmull.u8 q1, d0, d4 + pld [r0] + vld1.8 {d6},[r0,:64], r1 + vmull.u8 q10, d0, d6 + \add q1, q8, q1 + pld [r0] + vrshl.s16 q1, q1, q9 + vqmovun.s16 d2, q1 + \add q10, q8, q10 + vrshl.s16 q10, q10, q9 + vqmovun.s16 d4, q10 + vst1.8 {d2},[r4,:64], r1 + vst1.8 {d4},[r4,:64], r1 + bne 1b + pop {r4, pc} +.endm + +.macro weight_4 add + vdup.8 d0, r12 + vmov q1, q8 + vmov q10, q8 +1: subs r2, r2, #4 + vld1.32 {d4[0]},[r0,:32], r1 + vld1.32 {d4[1]},[r0,:32], r1 + vmull.u8 q1, d0, d4 + pld [r0] + blt 2f + vld1.32 {d6[0]},[r0,:32], r1 + vld1.32 {d6[1]},[r0,:32], r1 + vmull.u8 q10, d0, d6 + pld [r0] + \add q1, q8, q1 + vrshl.s16 q1, q1, q9 + vqmovun.s16 d2, q1 + \add q10, q8, q10 + vrshl.s16 q10, q10, q9 + vqmovun.s16 d4, q10 + vmov q10, q8 + vst1.32 {d2[0]},[r4,:32], r1 + vst1.32 {d2[1]},[r4,:32], r1 + vmov q1, q8 + vst1.32 {d4[0]},[r4,:32], r1 + vst1.32 {d4[1]},[r4,:32], r1 + bne 1b + pop {r4, pc} +2: \add q1, q8, q1 + vrshl.s16 q1, q1, q9 + vqmovun.s16 d2, q1 + vst1.32 {d2[0]},[r4,:32], r1 + vst1.32 {d2[1]},[r4,:32], r1 + pop {r4, pc} +.endm + +.macro weight_func w +function ff_weight_h264_pixels_\w\()_neon, export=1 + push {r4, lr} + ldr r12, [sp, #8] + ldr r4, [sp, #12] + cmp r3, #1 + lsl r4, r4, r3 + vdup.16 q8, r4 + mov r4, r0 + ble 20f + rsb lr, r3, #1 + vdup.16 q9, lr + cmp r12, #0 + blt 10f + weight_\w vhadd.s16 +10: rsb r12, r12, #0 + weight_\w vhsub.s16 +20: rsb lr, r3, #0 + vdup.16 q9, lr + cmp r12, #0 + blt 10f + weight_\w vadd.s16 +10: rsb r12, r12, #0 + weight_\w vsub.s16 +endfunc +.endm + + weight_func 16 + weight_func 8 + weight_func 4 diff --git a/ffmpeg/libavcodec/arm/h264idct_neon.S b/ffmpeg/libavcodec/arm/h264idct_neon.S new file mode 100644 index 0000000..fa5b90c --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264idct_neon.S @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function ff_h264_idct_add_neon, export=1 + vld1.64 {d0-d3}, [r1,:128] + vmov.i16 q15, #0 + + vswp d1, d2 + vst1.16 {q15}, [r1,:128]! + vadd.i16 d4, d0, d1 + vst1.16 {q15}, [r1,:128]! + vshr.s16 q8, q1, #1 + vsub.i16 d5, d0, d1 + vadd.i16 d6, d2, d17 + vsub.i16 d7, d16, d3 + vadd.i16 q0, q2, q3 + vsub.i16 q1, q2, q3 + + vtrn.16 d0, d1 + vtrn.16 d3, d2 + vtrn.32 d0, d3 + vtrn.32 d1, d2 + + vadd.i16 d4, d0, d3 + vld1.32 {d18[0]}, [r0,:32], r2 + vswp d1, d3 + vshr.s16 q8, q1, #1 + vld1.32 {d19[1]}, [r0,:32], r2 + vsub.i16 d5, d0, d1 + vld1.32 {d18[1]}, [r0,:32], r2 + vadd.i16 d6, d16, d3 + vld1.32 {d19[0]}, [r0,:32], r2 + vsub.i16 d7, d2, d17 + sub r0, r0, r2, lsl #2 + vadd.i16 q0, q2, q3 + vsub.i16 q1, q2, q3 + + vrshr.s16 q0, q0, #6 + vrshr.s16 q1, q1, #6 + + vaddw.u8 q0, q0, d18 + vaddw.u8 q1, q1, d19 + + vqmovun.s16 d0, q0 + vqmovun.s16 d1, q1 + + vst1.32 {d0[0]}, [r0,:32], r2 + vst1.32 {d1[1]}, [r0,:32], r2 + vst1.32 {d0[1]}, [r0,:32], r2 + vst1.32 {d1[0]}, [r0,:32], r2 + + sub r1, r1, #32 + bx lr +endfunc + +function ff_h264_idct_dc_add_neon, export=1 + mov r3, #0 + vld1.16 {d2[],d3[]}, [r1,:16] + strh r3, [r1] + vrshr.s16 q1, q1, #6 + vld1.32 {d0[0]}, [r0,:32], r2 + vld1.32 {d0[1]}, [r0,:32], r2 + vaddw.u8 q2, q1, d0 + vld1.32 {d1[0]}, [r0,:32], r2 + vld1.32 {d1[1]}, [r0,:32], r2 + vaddw.u8 q1, q1, d1 + vqmovun.s16 d0, q2 + vqmovun.s16 d1, q1 + sub r0, r0, r2, lsl #2 + vst1.32 {d0[0]}, [r0,:32], r2 + vst1.32 {d0[1]}, [r0,:32], r2 + vst1.32 {d1[0]}, [r0,:32], r2 + vst1.32 {d1[1]}, [r0,:32], r2 + bx lr +endfunc + +function ff_h264_idct_add16_neon, export=1 + push {r4-r8,lr} + mov r4, r0 + mov r5, r1 + mov r1, r2 + mov r2, r3 + ldr r6, [sp, #24] + movrel r7, scan8 + mov ip, #16 +1: ldrb r8, [r7], #1 + ldr r0, [r5], #4 + ldrb r8, [r6, r8] + subs r8, r8, #1 + blt 2f + ldrsh lr, [r1] + add r0, r0, r4 + it ne + movne lr, #0 + cmp lr, #0 + ite ne + adrne lr, ff_h264_idct_dc_add_neon + CONFIG_THUMB + adreq lr, ff_h264_idct_add_neon + CONFIG_THUMB + blx lr +2: subs ip, ip, #1 + add r1, r1, #32 + bne 1b + pop {r4-r8,pc} +endfunc + +function ff_h264_idct_add16intra_neon, export=1 + push {r4-r8,lr} + mov r4, r0 + mov r5, r1 + mov r1, r2 + mov r2, r3 + ldr r6, [sp, #24] + movrel r7, scan8 + mov ip, #16 +1: ldrb r8, [r7], #1 + ldr r0, [r5], #4 + ldrb r8, [r6, r8] + add r0, r0, r4 + cmp r8, #0 + ldrsh r8, [r1] + iteet ne + adrne lr, ff_h264_idct_add_neon + CONFIG_THUMB + adreq lr, ff_h264_idct_dc_add_neon + CONFIG_THUMB + cmpeq r8, #0 + blxne lr + subs ip, ip, #1 + add r1, r1, #32 + bne 1b + pop {r4-r8,pc} +endfunc + +function ff_h264_idct_add8_neon, export=1 + push {r4-r10,lr} + ldm r0, {r4,r9} + add r5, r1, #16*4 + add r1, r2, #16*32 + mov r2, r3 + mov r10, r1 + ldr r6, [sp, #32] + movrel r7, scan8+16 + mov r12, #0 +1: ldrb r8, [r7, r12] + ldr r0, [r5, r12, lsl #2] + ldrb r8, [r6, r8] + add r0, r0, r4 + add r1, r10, r12, lsl #5 + cmp r8, #0 + ldrsh r8, [r1] + iteet ne + adrne lr, ff_h264_idct_add_neon + CONFIG_THUMB + adreq lr, ff_h264_idct_dc_add_neon + CONFIG_THUMB + cmpeq r8, #0 + blxne lr + add r12, r12, #1 + cmp r12, #4 + itt eq + moveq r12, #16 + moveq r4, r9 + cmp r12, #20 + blt 1b + pop {r4-r10,pc} +endfunc + +.macro idct8x8_cols pass + .if \pass == 0 + qa .req q2 + qb .req q14 + vshr.s16 q2, q10, #1 + vadd.i16 q0, q8, q12 + vld1.16 {q14-q15},[r1,:128] + vst1.16 {q7}, [r1,:128]! + vst1.16 {q7}, [r1,:128]! + vsub.i16 q1, q8, q12 + vshr.s16 q3, q14, #1 + vsub.i16 q2, q2, q14 + vadd.i16 q3, q3, q10 + .else + qa .req q14 + qb .req q2 + vtrn.32 q8, q10 + vtrn.16 q12, q13 + vtrn.32 q9, q11 + vtrn.32 q12, q2 + vtrn.32 q13, q15 + vswp d21, d4 + vshr.s16 q14, q10, #1 + vswp d17, d24 + vshr.s16 q3, q2, #1 + vswp d19, d26 + vadd.i16 q0, q8, q12 + vswp d23, d30 + vsub.i16 q1, q8, q12 + vsub.i16 q14, q14, q2 + vadd.i16 q3, q3, q10 + .endif + vadd.i16 q10, q1, qa + vsub.i16 q12, q1, qa + vadd.i16 q8, q0, q3 + vsub.i16 qb, q0, q3 + vsub.i16 q0, q13, q11 + vadd.i16 q1, q15, q9 + vsub.i16 qa, q15, q9 + vadd.i16 q3, q13, q11 + vsub.i16 q0, q0, q15 + vsub.i16 q1, q1, q11 + vadd.i16 qa, qa, q13 + vadd.i16 q3, q3, q9 + vshr.s16 q9, q9, #1 + vshr.s16 q11, q11, #1 + vshr.s16 q13, q13, #1 + vshr.s16 q15, q15, #1 + vsub.i16 q0, q0, q15 + vsub.i16 q1, q1, q11 + vadd.i16 qa, qa, q13 + vadd.i16 q3, q3, q9 + vshr.s16 q9, q0, #2 + vshr.s16 q11, q1, #2 + vshr.s16 q13, qa, #2 + vshr.s16 q15, q3, #2 + vsub.i16 q3, q3, q9 + vsub.i16 qa, q11, qa + vadd.i16 q1, q1, q13 + vadd.i16 q0, q0, q15 + .if \pass == 0 + vsub.i16 q15, q8, q3 + vadd.i16 q8, q8, q3 + vadd.i16 q9, q10, q2 + vsub.i16 q2, q10, q2 + vtrn.16 q8, q9 + vadd.i16 q10, q12, q1 + vtrn.16 q2, q15 + vadd.i16 q11, q14, q0 + vsub.i16 q13, q12, q1 + vtrn.16 q10, q11 + vsub.i16 q12, q14, q0 + .else + vsub.i16 q15, q8, q3 + vadd.i16 q8, q8, q3 + vadd.i16 q9, q10, q14 + vsub.i16 q14, q10, q14 + vadd.i16 q10, q12, q1 + vsub.i16 q13, q12, q1 + vadd.i16 q11, q2, q0 + vsub.i16 q12, q2, q0 + .endif + .unreq qa + .unreq qb +.endm + +function ff_h264_idct8_add_neon, export=1 + vmov.i16 q7, #0 + vld1.16 {q8-q9}, [r1,:128] + vst1.16 {q7}, [r1,:128]! + vst1.16 {q7}, [r1,:128]! + vld1.16 {q10-q11},[r1,:128] + vst1.16 {q7}, [r1,:128]! + vst1.16 {q7}, [r1,:128]! + vld1.16 {q12-q13},[r1,:128] + vst1.16 {q7}, [r1,:128]! + vst1.16 {q7}, [r1,:128]! + + idct8x8_cols 0 + idct8x8_cols 1 + + mov r3, r0 + vrshr.s16 q8, q8, #6 + vld1.8 {d0}, [r0,:64], r2 + vrshr.s16 q9, q9, #6 + vld1.8 {d1}, [r0,:64], r2 + vrshr.s16 q10, q10, #6 + vld1.8 {d2}, [r0,:64], r2 + vrshr.s16 q11, q11, #6 + vld1.8 {d3}, [r0,:64], r2 + vrshr.s16 q12, q12, #6 + vld1.8 {d4}, [r0,:64], r2 + vrshr.s16 q13, q13, #6 + vld1.8 {d5}, [r0,:64], r2 + vrshr.s16 q14, q14, #6 + vld1.8 {d6}, [r0,:64], r2 + vrshr.s16 q15, q15, #6 + vld1.8 {d7}, [r0,:64], r2 + vaddw.u8 q8, q8, d0 + vaddw.u8 q9, q9, d1 + vaddw.u8 q10, q10, d2 + vqmovun.s16 d0, q8 + vaddw.u8 q11, q11, d3 + vqmovun.s16 d1, q9 + vaddw.u8 q12, q12, d4 + vqmovun.s16 d2, q10 + vst1.8 {d0}, [r3,:64], r2 + vaddw.u8 q13, q13, d5 + vqmovun.s16 d3, q11 + vst1.8 {d1}, [r3,:64], r2 + vaddw.u8 q14, q14, d6 + vqmovun.s16 d4, q12 + vst1.8 {d2}, [r3,:64], r2 + vaddw.u8 q15, q15, d7 + vqmovun.s16 d5, q13 + vst1.8 {d3}, [r3,:64], r2 + vqmovun.s16 d6, q14 + vqmovun.s16 d7, q15 + vst1.8 {d4}, [r3,:64], r2 + vst1.8 {d5}, [r3,:64], r2 + vst1.8 {d6}, [r3,:64], r2 + vst1.8 {d7}, [r3,:64], r2 + + sub r1, r1, #128 + bx lr +endfunc + +function ff_h264_idct8_dc_add_neon, export=1 + mov r3, #0 + vld1.16 {d30[],d31[]},[r1,:16] + strh r3, [r1] + vld1.32 {d0}, [r0,:64], r2 + vrshr.s16 q15, q15, #6 + vld1.32 {d1}, [r0,:64], r2 + vld1.32 {d2}, [r0,:64], r2 + vaddw.u8 q8, q15, d0 + vld1.32 {d3}, [r0,:64], r2 + vaddw.u8 q9, q15, d1 + vld1.32 {d4}, [r0,:64], r2 + vaddw.u8 q10, q15, d2 + vld1.32 {d5}, [r0,:64], r2 + vaddw.u8 q11, q15, d3 + vld1.32 {d6}, [r0,:64], r2 + vaddw.u8 q12, q15, d4 + vld1.32 {d7}, [r0,:64], r2 + vaddw.u8 q13, q15, d5 + vaddw.u8 q14, q15, d6 + vaddw.u8 q15, q15, d7 + vqmovun.s16 d0, q8 + vqmovun.s16 d1, q9 + vqmovun.s16 d2, q10 + vqmovun.s16 d3, q11 + sub r0, r0, r2, lsl #3 + vst1.32 {d0}, [r0,:64], r2 + vqmovun.s16 d4, q12 + vst1.32 {d1}, [r0,:64], r2 + vqmovun.s16 d5, q13 + vst1.32 {d2}, [r0,:64], r2 + vqmovun.s16 d6, q14 + vst1.32 {d3}, [r0,:64], r2 + vqmovun.s16 d7, q15 + vst1.32 {d4}, [r0,:64], r2 + vst1.32 {d5}, [r0,:64], r2 + vst1.32 {d6}, [r0,:64], r2 + vst1.32 {d7}, [r0,:64], r2 + bx lr +endfunc + +function ff_h264_idct8_add4_neon, export=1 + push {r4-r8,lr} + mov r4, r0 + mov r5, r1 + mov r1, r2 + mov r2, r3 + ldr r6, [sp, #24] + movrel r7, scan8 + mov r12, #16 +1: ldrb r8, [r7], #4 + ldr r0, [r5], #16 + ldrb r8, [r6, r8] + subs r8, r8, #1 + blt 2f + ldrsh lr, [r1] + add r0, r0, r4 + it ne + movne lr, #0 + cmp lr, #0 + ite ne + adrne lr, ff_h264_idct8_dc_add_neon + CONFIG_THUMB + adreq lr, ff_h264_idct8_add_neon + CONFIG_THUMB + blx lr +2: subs r12, r12, #4 + add r1, r1, #128 + bne 1b + pop {r4-r8,pc} +endfunc + +const scan8 + .byte 4+ 1*8, 5+ 1*8, 4+ 2*8, 5+ 2*8 + .byte 6+ 1*8, 7+ 1*8, 6+ 2*8, 7+ 2*8 + .byte 4+ 3*8, 5+ 3*8, 4+ 4*8, 5+ 4*8 + .byte 6+ 3*8, 7+ 3*8, 6+ 4*8, 7+ 4*8 + .byte 4+ 6*8, 5+ 6*8, 4+ 7*8, 5+ 7*8 + .byte 6+ 6*8, 7+ 6*8, 6+ 7*8, 7+ 7*8 + .byte 4+ 8*8, 5+ 8*8, 4+ 9*8, 5+ 9*8 + .byte 6+ 8*8, 7+ 8*8, 6+ 9*8, 7+ 9*8 + .byte 4+11*8, 5+11*8, 4+12*8, 5+12*8 + .byte 6+11*8, 7+11*8, 6+12*8, 7+12*8 + .byte 4+13*8, 5+13*8, 4+14*8, 5+14*8 + .byte 6+13*8, 7+13*8, 6+14*8, 7+14*8 +endconst diff --git a/ffmpeg/libavcodec/arm/h264pred_init_arm.c b/ffmpeg/libavcodec/arm/h264pred_init_arm.c new file mode 100644 index 0000000..5ec39ce --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264pred_init_arm.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/h264pred.h" + +void ff_pred16x16_vert_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_hor_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_plane_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_128_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_left_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred16x16_top_dc_neon(uint8_t *src, ptrdiff_t stride); + +void ff_pred8x8_vert_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_hor_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_plane_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_128_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_left_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_top_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_l0t_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_0lt_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_l00_dc_neon(uint8_t *src, ptrdiff_t stride); +void ff_pred8x8_0l0_dc_neon(uint8_t *src, ptrdiff_t stride); + +static av_cold void ff_h264_pred_init_neon(H264PredContext *h, int codec_id, + const int bit_depth, + const int chroma_format_idc) +{ +#if HAVE_NEON + const int high_depth = bit_depth > 8; + + if (high_depth) + return; + if(chroma_format_idc == 1){ + h->pred8x8[VERT_PRED8x8 ] = ff_pred8x8_vert_neon; + h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_hor_neon; + if (codec_id != AV_CODEC_ID_VP8) + h->pred8x8[PLANE_PRED8x8] = ff_pred8x8_plane_neon; + h->pred8x8[DC_128_PRED8x8 ] = ff_pred8x8_128_dc_neon; + if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP8) { + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_neon; + h->pred8x8[LEFT_DC_PRED8x8] = ff_pred8x8_left_dc_neon; + h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_neon; + h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8] = ff_pred8x8_l0t_dc_neon; + h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8] = ff_pred8x8_0lt_dc_neon; + h->pred8x8[ALZHEIMER_DC_L00_PRED8x8] = ff_pred8x8_l00_dc_neon; + h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8] = ff_pred8x8_0l0_dc_neon; + } + } + + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_neon; + h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vert_neon; + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_hor_neon; + h->pred16x16[LEFT_DC_PRED8x8] = ff_pred16x16_left_dc_neon; + h->pred16x16[TOP_DC_PRED8x8 ] = ff_pred16x16_top_dc_neon; + h->pred16x16[DC_128_PRED8x8 ] = ff_pred16x16_128_dc_neon; + if (codec_id != AV_CODEC_ID_SVQ3 && codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP8) + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_neon; +#endif // HAVE_NEON +} + +av_cold void ff_h264_pred_init_arm(H264PredContext *h, int codec_id, + int bit_depth, const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + ff_h264_pred_init_neon(h, codec_id, bit_depth, chroma_format_idc); +} diff --git a/ffmpeg/libavcodec/arm/h264pred_neon.S b/ffmpeg/libavcodec/arm/h264pred_neon.S new file mode 100644 index 0000000..4dc47ba --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264pred_neon.S @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + + .macro ldcol.8 rd, rs, rt, n=8, hi=0 +.if \n == 8 || \hi == 0 + vld1.8 {\rd[0]}, [\rs], \rt + vld1.8 {\rd[1]}, [\rs], \rt + vld1.8 {\rd[2]}, [\rs], \rt + vld1.8 {\rd[3]}, [\rs], \rt +.endif +.if \n == 8 || \hi == 1 + vld1.8 {\rd[4]}, [\rs], \rt + vld1.8 {\rd[5]}, [\rs], \rt + vld1.8 {\rd[6]}, [\rs], \rt + vld1.8 {\rd[7]}, [\rs], \rt +.endif + .endm + + .macro add16x8 dq, dl, dh, rl, rh + vaddl.u8 \dq, \rl, \rh + vadd.u16 \dl, \dl, \dh + vpadd.u16 \dl, \dl, \dl + vpadd.u16 \dl, \dl, \dl + .endm + +function ff_pred16x16_128_dc_neon, export=1 + vmov.i8 q0, #128 + b .L_pred16x16_dc_end +endfunc + +function ff_pred16x16_top_dc_neon, export=1 + sub r2, r0, r1 + vld1.8 {q0}, [r2,:128] + add16x8 q0, d0, d1, d0, d1 + vrshrn.u16 d0, q0, #4 + vdup.8 q0, d0[0] + b .L_pred16x16_dc_end +endfunc + +function ff_pred16x16_left_dc_neon, export=1 + sub r2, r0, #1 + ldcol.8 d0, r2, r1 + ldcol.8 d1, r2, r1 + add16x8 q0, d0, d1, d0, d1 + vrshrn.u16 d0, q0, #4 + vdup.8 q0, d0[0] + b .L_pred16x16_dc_end +endfunc + +function ff_pred16x16_dc_neon, export=1 + sub r2, r0, r1 + vld1.8 {q0}, [r2,:128] + sub r2, r0, #1 + ldcol.8 d2, r2, r1 + ldcol.8 d3, r2, r1 + vaddl.u8 q0, d0, d1 + vaddl.u8 q1, d2, d3 + vadd.u16 q0, q0, q1 + vadd.u16 d0, d0, d1 + vpadd.u16 d0, d0, d0 + vpadd.u16 d0, d0, d0 + vrshrn.u16 d0, q0, #5 + vdup.8 q0, d0[0] +.L_pred16x16_dc_end: + mov r3, #8 +6: vst1.8 {q0}, [r0,:128], r1 + vst1.8 {q0}, [r0,:128], r1 + subs r3, r3, #1 + bne 6b + bx lr +endfunc + +function ff_pred16x16_hor_neon, export=1 + sub r2, r0, #1 + mov r3, #16 +1: vld1.8 {d0[],d1[]},[r2], r1 + vst1.8 {q0}, [r0,:128], r1 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +function ff_pred16x16_vert_neon, export=1 + sub r0, r0, r1 + vld1.8 {q0}, [r0,:128], r1 + mov r3, #8 +1: vst1.8 {q0}, [r0,:128], r1 + vst1.8 {q0}, [r0,:128], r1 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +function ff_pred16x16_plane_neon, export=1 + sub r3, r0, r1 + add r2, r3, #8 + sub r3, r3, #1 + vld1.8 {d0}, [r3] + vld1.8 {d2}, [r2,:64], r1 + ldcol.8 d1, r3, r1 + add r3, r3, r1 + ldcol.8 d3, r3, r1 + vrev64.8 q0, q0 + vaddl.u8 q8, d2, d3 + vsubl.u8 q2, d2, d0 + vsubl.u8 q3, d3, d1 + movrel r3, p16weight + vld1.8 {q0}, [r3,:128] + vmul.s16 q2, q2, q0 + vmul.s16 q3, q3, q0 + vadd.i16 d4, d4, d5 + vadd.i16 d5, d6, d7 + vpadd.i16 d4, d4, d5 + vpadd.i16 d4, d4, d4 + vshll.s16 q3, d4, #2 + vaddw.s16 q2, q3, d4 + vrshrn.s32 d4, q2, #6 + mov r3, #0 + vtrn.16 d4, d5 + vadd.i16 d2, d4, d5 + vshl.i16 d3, d2, #3 + vrev64.16 d16, d17 + vsub.i16 d3, d3, d2 + vadd.i16 d16, d16, d0 + vshl.i16 d2, d16, #4 + vsub.i16 d2, d2, d3 + vshl.i16 d3, d4, #4 + vext.16 q0, q0, q0, #7 + vsub.i16 d6, d5, d3 + vmov.16 d0[0], r3 + vmul.i16 q0, q0, d4[0] + vdup.16 q1, d2[0] + vdup.16 q2, d4[0] + vdup.16 q3, d6[0] + vshl.i16 q2, q2, #3 + vadd.i16 q1, q1, q0 + vadd.i16 q3, q3, q2 + mov r3, #16 +1: + vqshrun.s16 d0, q1, #5 + vadd.i16 q1, q1, q2 + vqshrun.s16 d1, q1, #5 + vadd.i16 q1, q1, q3 + vst1.8 {q0}, [r0,:128], r1 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +const p16weight, align=4 + .short 1,2,3,4,5,6,7,8 +endconst + +function ff_pred8x8_hor_neon, export=1 + sub r2, r0, #1 + mov r3, #8 +1: vld1.8 {d0[]}, [r2], r1 + vst1.8 {d0}, [r0,:64], r1 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +function ff_pred8x8_vert_neon, export=1 + sub r0, r0, r1 + vld1.8 {d0}, [r0,:64], r1 + mov r3, #4 +1: vst1.8 {d0}, [r0,:64], r1 + vst1.8 {d0}, [r0,:64], r1 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +function ff_pred8x8_plane_neon, export=1 + sub r3, r0, r1 + add r2, r3, #4 + sub r3, r3, #1 + vld1.32 {d0[0]}, [r3] + vld1.32 {d2[0]}, [r2,:32], r1 + ldcol.8 d0, r3, r1, 4, hi=1 + add r3, r3, r1 + ldcol.8 d3, r3, r1, 4 + vaddl.u8 q8, d2, d3 + vrev32.8 d0, d0 + vtrn.32 d2, d3 + vsubl.u8 q2, d2, d0 + movrel r3, p16weight + vld1.16 {q0}, [r3,:128] + vmul.s16 d4, d4, d0 + vmul.s16 d5, d5, d0 + vpadd.i16 d4, d4, d5 + vpaddl.s16 d4, d4 + vshl.i32 d5, d4, #4 + vadd.s32 d4, d4, d5 + vrshrn.s32 d4, q2, #5 + mov r3, #0 + vtrn.16 d4, d5 + vadd.i16 d2, d4, d5 + vshl.i16 d3, d2, #2 + vrev64.16 d16, d16 + vsub.i16 d3, d3, d2 + vadd.i16 d16, d16, d0 + vshl.i16 d2, d16, #4 + vsub.i16 d2, d2, d3 + vshl.i16 d3, d4, #3 + vext.16 q0, q0, q0, #7 + vsub.i16 d6, d5, d3 + vmov.16 d0[0], r3 + vmul.i16 q0, q0, d4[0] + vdup.16 q1, d2[0] + vdup.16 q2, d4[0] + vdup.16 q3, d6[0] + vshl.i16 q2, q2, #3 + vadd.i16 q1, q1, q0 + vadd.i16 q3, q3, q2 + mov r3, #8 +1: + vqshrun.s16 d0, q1, #5 + vadd.i16 q1, q1, q3 + vst1.8 {d0}, [r0,:64], r1 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +function ff_pred8x8_128_dc_neon, export=1 + vmov.i8 q0, #128 + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_top_dc_neon, export=1 + sub r2, r0, r1 + vld1.8 {d0}, [r2,:64] + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0, d0 + vrshrn.u16 d0, q0, #2 + vdup.8 d1, d0[1] + vdup.8 d0, d0[0] + vtrn.32 d0, d1 + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_left_dc_neon, export=1 + sub r2, r0, #1 + ldcol.8 d0, r2, r1 + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0, d0 + vrshrn.u16 d0, q0, #2 + vdup.8 d1, d0[1] + vdup.8 d0, d0[0] + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_dc_neon, export=1 + sub r2, r0, r1 + vld1.8 {d0}, [r2,:64] + sub r2, r0, #1 + ldcol.8 d1, r2, r1 + vtrn.32 d0, d1 + vpaddl.u8 q0, q0 + vpadd.u16 d0, d0, d1 + vpadd.u16 d1, d0, d0 + vrshrn.u16 d2, q0, #3 + vrshrn.u16 d3, q0, #2 + vdup.8 d0, d2[4] + vdup.8 d1, d3[3] + vdup.8 d4, d3[2] + vdup.8 d5, d2[5] + vtrn.32 q0, q2 +.L_pred8x8_dc_end: + mov r3, #4 + add r2, r0, r1, lsl #2 +6: vst1.8 {d0}, [r0,:64], r1 + vst1.8 {d1}, [r2,:64], r1 + subs r3, r3, #1 + bne 6b + bx lr +endfunc + +function ff_pred8x8_l0t_dc_neon, export=1 + sub r2, r0, r1 + vld1.8 {d0}, [r2,:64] + sub r2, r0, #1 + ldcol.8 d1, r2, r1, 4 + vtrn.32 d0, d1 + vpaddl.u8 q0, q0 + vpadd.u16 d0, d0, d1 + vpadd.u16 d1, d0, d0 + vrshrn.u16 d2, q0, #3 + vrshrn.u16 d3, q0, #2 + vdup.8 d0, d2[4] + vdup.8 d1, d3[0] + vdup.8 q2, d3[2] + vtrn.32 q0, q2 + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_l00_dc_neon, export=1 + sub r2, r0, #1 + ldcol.8 d0, r2, r1, 4 + vpaddl.u8 d0, d0 + vpadd.u16 d0, d0, d0 + vrshrn.u16 d0, q0, #2 + vmov.i8 d1, #128 + vdup.8 d0, d0[0] + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_0lt_dc_neon, export=1 + sub r2, r0, r1 + vld1.8 {d0}, [r2,:64] + add r2, r0, r1, lsl #2 + sub r2, r2, #1 + ldcol.8 d1, r2, r1, 4, hi=1 + vtrn.32 d0, d1 + vpaddl.u8 q0, q0 + vpadd.u16 d0, d0, d1 + vpadd.u16 d1, d0, d0 + vrshrn.u16 d3, q0, #2 + vrshrn.u16 d2, q0, #3 + vdup.8 d0, d3[0] + vdup.8 d1, d3[3] + vdup.8 d4, d3[2] + vdup.8 d5, d2[5] + vtrn.32 q0, q2 + b .L_pred8x8_dc_end +endfunc + +function ff_pred8x8_0l0_dc_neon, export=1 + add r2, r0, r1, lsl #2 + sub r2, r2, #1 + ldcol.8 d1, r2, r1, 4 + vpaddl.u8 d2, d1 + vpadd.u16 d2, d2, d2 + vrshrn.u16 d1, q1, #2 + vmov.i8 d0, #128 + vdup.8 d1, d1[0] + b .L_pred8x8_dc_end +endfunc diff --git a/ffmpeg/libavcodec/arm/h264qpel_init_arm.c b/ffmpeg/libavcodec/arm/h264qpel_init_arm.c new file mode 100644 index 0000000..eaa1324 --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264qpel_init_arm.c @@ -0,0 +1,171 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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/arm/cpu.h" +#include "libavcodec/h264qpel.h" + +void ff_put_h264_qpel16_mc00_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc10_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc20_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc30_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc01_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc11_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc21_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc31_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc02_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc12_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc22_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc32_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc03_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc13_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc23_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel16_mc33_neon(uint8_t *, uint8_t *, ptrdiff_t); + +void ff_put_h264_qpel8_mc00_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc10_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc20_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc30_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc01_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc11_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc21_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc31_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc02_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc12_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc22_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc32_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc03_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc13_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc23_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_put_h264_qpel8_mc33_neon(uint8_t *, uint8_t *, ptrdiff_t); + +void ff_avg_h264_qpel16_mc00_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc10_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc20_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc30_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc01_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc11_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc21_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc31_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc02_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc12_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc22_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc32_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc03_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc13_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc23_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel16_mc33_neon(uint8_t *, uint8_t *, ptrdiff_t); + +void ff_avg_h264_qpel8_mc00_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc10_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc20_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc30_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc01_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc11_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc21_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc31_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc02_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc12_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc22_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc32_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc03_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc13_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc23_neon(uint8_t *, uint8_t *, ptrdiff_t); +void ff_avg_h264_qpel8_mc33_neon(uint8_t *, uint8_t *, ptrdiff_t); + +av_cold void ff_h264qpel_init_arm(H264QpelContext *c, int bit_depth) +{ + const int high_bit_depth = bit_depth > 8; + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags) && !high_bit_depth) { + c->put_h264_qpel_pixels_tab[0][ 0] = ff_put_h264_qpel16_mc00_neon; + c->put_h264_qpel_pixels_tab[0][ 1] = ff_put_h264_qpel16_mc10_neon; + c->put_h264_qpel_pixels_tab[0][ 2] = ff_put_h264_qpel16_mc20_neon; + c->put_h264_qpel_pixels_tab[0][ 3] = ff_put_h264_qpel16_mc30_neon; + c->put_h264_qpel_pixels_tab[0][ 4] = ff_put_h264_qpel16_mc01_neon; + c->put_h264_qpel_pixels_tab[0][ 5] = ff_put_h264_qpel16_mc11_neon; + c->put_h264_qpel_pixels_tab[0][ 6] = ff_put_h264_qpel16_mc21_neon; + c->put_h264_qpel_pixels_tab[0][ 7] = ff_put_h264_qpel16_mc31_neon; + c->put_h264_qpel_pixels_tab[0][ 8] = ff_put_h264_qpel16_mc02_neon; + c->put_h264_qpel_pixels_tab[0][ 9] = ff_put_h264_qpel16_mc12_neon; + c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_neon; + c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_neon; + c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_neon; + c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_neon; + c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_neon; + c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_neon; + + c->put_h264_qpel_pixels_tab[1][ 0] = ff_put_h264_qpel8_mc00_neon; + c->put_h264_qpel_pixels_tab[1][ 1] = ff_put_h264_qpel8_mc10_neon; + c->put_h264_qpel_pixels_tab[1][ 2] = ff_put_h264_qpel8_mc20_neon; + c->put_h264_qpel_pixels_tab[1][ 3] = ff_put_h264_qpel8_mc30_neon; + c->put_h264_qpel_pixels_tab[1][ 4] = ff_put_h264_qpel8_mc01_neon; + c->put_h264_qpel_pixels_tab[1][ 5] = ff_put_h264_qpel8_mc11_neon; + c->put_h264_qpel_pixels_tab[1][ 6] = ff_put_h264_qpel8_mc21_neon; + c->put_h264_qpel_pixels_tab[1][ 7] = ff_put_h264_qpel8_mc31_neon; + c->put_h264_qpel_pixels_tab[1][ 8] = ff_put_h264_qpel8_mc02_neon; + c->put_h264_qpel_pixels_tab[1][ 9] = ff_put_h264_qpel8_mc12_neon; + c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_neon; + c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_neon; + c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_neon; + c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_neon; + c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_neon; + c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_neon; + + c->avg_h264_qpel_pixels_tab[0][ 0] = ff_avg_h264_qpel16_mc00_neon; + c->avg_h264_qpel_pixels_tab[0][ 1] = ff_avg_h264_qpel16_mc10_neon; + c->avg_h264_qpel_pixels_tab[0][ 2] = ff_avg_h264_qpel16_mc20_neon; + c->avg_h264_qpel_pixels_tab[0][ 3] = ff_avg_h264_qpel16_mc30_neon; + c->avg_h264_qpel_pixels_tab[0][ 4] = ff_avg_h264_qpel16_mc01_neon; + c->avg_h264_qpel_pixels_tab[0][ 5] = ff_avg_h264_qpel16_mc11_neon; + c->avg_h264_qpel_pixels_tab[0][ 6] = ff_avg_h264_qpel16_mc21_neon; + c->avg_h264_qpel_pixels_tab[0][ 7] = ff_avg_h264_qpel16_mc31_neon; + c->avg_h264_qpel_pixels_tab[0][ 8] = ff_avg_h264_qpel16_mc02_neon; + c->avg_h264_qpel_pixels_tab[0][ 9] = ff_avg_h264_qpel16_mc12_neon; + c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_neon; + c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_neon; + c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_neon; + c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_neon; + c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_neon; + c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_neon; + + c->avg_h264_qpel_pixels_tab[1][ 0] = ff_avg_h264_qpel8_mc00_neon; + c->avg_h264_qpel_pixels_tab[1][ 1] = ff_avg_h264_qpel8_mc10_neon; + c->avg_h264_qpel_pixels_tab[1][ 2] = ff_avg_h264_qpel8_mc20_neon; + c->avg_h264_qpel_pixels_tab[1][ 3] = ff_avg_h264_qpel8_mc30_neon; + c->avg_h264_qpel_pixels_tab[1][ 4] = ff_avg_h264_qpel8_mc01_neon; + c->avg_h264_qpel_pixels_tab[1][ 5] = ff_avg_h264_qpel8_mc11_neon; + c->avg_h264_qpel_pixels_tab[1][ 6] = ff_avg_h264_qpel8_mc21_neon; + c->avg_h264_qpel_pixels_tab[1][ 7] = ff_avg_h264_qpel8_mc31_neon; + c->avg_h264_qpel_pixels_tab[1][ 8] = ff_avg_h264_qpel8_mc02_neon; + c->avg_h264_qpel_pixels_tab[1][ 9] = ff_avg_h264_qpel8_mc12_neon; + c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_neon; + c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_neon; + c->avg_h264_qpel_pixels_tab[1][12] = ff_avg_h264_qpel8_mc03_neon; + c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_neon; + c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_neon; + c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/h264qpel_neon.S b/ffmpeg/libavcodec/arm/h264qpel_neon.S new file mode 100644 index 0000000..21336c6 --- /dev/null +++ b/ffmpeg/libavcodec/arm/h264qpel_neon.S @@ -0,0 +1,955 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" +#include "neon.S" + + /* H.264 qpel MC */ + +.macro lowpass_const r + movw \r, #5 + movt \r, #20 + vmov.32 d6[0], \r +.endm + +.macro lowpass_8 r0, r1, r2, r3, d0, d1, narrow=1 + .if \narrow + t0 .req q0 + t1 .req q8 + .else + t0 .req \d0 + t1 .req \d1 + .endif + vext.8 d2, \r0, \r1, #2 + vext.8 d3, \r0, \r1, #3 + vaddl.u8 q1, d2, d3 + vext.8 d4, \r0, \r1, #1 + vext.8 d5, \r0, \r1, #4 + vaddl.u8 q2, d4, d5 + vext.8 d30, \r0, \r1, #5 + vaddl.u8 t0, \r0, d30 + vext.8 d18, \r2, \r3, #2 + vmla.i16 t0, q1, d6[1] + vext.8 d19, \r2, \r3, #3 + vaddl.u8 q9, d18, d19 + vext.8 d20, \r2, \r3, #1 + vmls.i16 t0, q2, d6[0] + vext.8 d21, \r2, \r3, #4 + vaddl.u8 q10, d20, d21 + vext.8 d31, \r2, \r3, #5 + vaddl.u8 t1, \r2, d31 + vmla.i16 t1, q9, d6[1] + vmls.i16 t1, q10, d6[0] + .if \narrow + vqrshrun.s16 \d0, t0, #5 + vqrshrun.s16 \d1, t1, #5 + .endif + .unreq t0 + .unreq t1 +.endm + +.macro lowpass_8_1 r0, r1, d0, narrow=1 + .if \narrow + t0 .req q0 + .else + t0 .req \d0 + .endif + vext.8 d2, \r0, \r1, #2 + vext.8 d3, \r0, \r1, #3 + vaddl.u8 q1, d2, d3 + vext.8 d4, \r0, \r1, #1 + vext.8 d5, \r0, \r1, #4 + vaddl.u8 q2, d4, d5 + vext.8 d30, \r0, \r1, #5 + vaddl.u8 t0, \r0, d30 + vmla.i16 t0, q1, d6[1] + vmls.i16 t0, q2, d6[0] + .if \narrow + vqrshrun.s16 \d0, t0, #5 + .endif + .unreq t0 +.endm + +.macro lowpass_8.16 r0, r1, l0, h0, l1, h1, d + vext.16 q1, \r0, \r1, #2 + vext.16 q0, \r0, \r1, #3 + vaddl.s16 q9, d2, d0 + vext.16 q2, \r0, \r1, #1 + vaddl.s16 q1, d3, d1 + vext.16 q3, \r0, \r1, #4 + vaddl.s16 q10, d4, d6 + vext.16 \r1, \r0, \r1, #5 + vaddl.s16 q2, d5, d7 + vaddl.s16 q0, \h0, \h1 + vaddl.s16 q8, \l0, \l1 + + vshl.i32 q3, q9, #4 + vshl.i32 q9, q9, #2 + vshl.i32 q15, q10, #2 + vadd.i32 q9, q9, q3 + vadd.i32 q10, q10, q15 + + vshl.i32 q3, q1, #4 + vshl.i32 q1, q1, #2 + vshl.i32 q15, q2, #2 + vadd.i32 q1, q1, q3 + vadd.i32 q2, q2, q15 + + vadd.i32 q9, q9, q8 + vsub.i32 q9, q9, q10 + + vadd.i32 q1, q1, q0 + vsub.i32 q1, q1, q2 + + vrshrn.s32 d18, q9, #10 + vrshrn.s32 d19, q1, #10 + + vqmovun.s16 \d, q9 +.endm + +function put_h264_qpel16_h_lowpass_neon_packed + mov r4, lr + mov r12, #16 + mov r3, #8 + bl put_h264_qpel8_h_lowpass_neon + sub r1, r1, r2, lsl #4 + add r1, r1, #8 + mov r12, #16 + mov lr, r4 + b put_h264_qpel8_h_lowpass_neon +endfunc + +.macro h264_qpel_h_lowpass type +function \type\()_h264_qpel16_h_lowpass_neon + push {lr} + mov r12, #16 + bl \type\()_h264_qpel8_h_lowpass_neon + sub r0, r0, r3, lsl #4 + sub r1, r1, r2, lsl #4 + add r0, r0, #8 + add r1, r1, #8 + mov r12, #16 + pop {lr} +endfunc + +function \type\()_h264_qpel8_h_lowpass_neon +1: vld1.8 {d0, d1}, [r1], r2 + vld1.8 {d16,d17}, [r1], r2 + subs r12, r12, #2 + lowpass_8 d0, d1, d16, d17, d0, d16 + .ifc \type,avg + vld1.8 {d2}, [r0,:64], r3 + vrhadd.u8 d0, d0, d2 + vld1.8 {d3}, [r0,:64] + vrhadd.u8 d16, d16, d3 + sub r0, r0, r3 + .endif + vst1.8 {d0}, [r0,:64], r3 + vst1.8 {d16}, [r0,:64], r3 + bne 1b + bx lr +endfunc +.endm + + h264_qpel_h_lowpass put + h264_qpel_h_lowpass avg + +.macro h264_qpel_h_lowpass_l2 type +function \type\()_h264_qpel16_h_lowpass_l2_neon + push {lr} + mov r12, #16 + bl \type\()_h264_qpel8_h_lowpass_l2_neon + sub r0, r0, r2, lsl #4 + sub r1, r1, r2, lsl #4 + sub r3, r3, r2, lsl #4 + add r0, r0, #8 + add r1, r1, #8 + add r3, r3, #8 + mov r12, #16 + pop {lr} +endfunc + +function \type\()_h264_qpel8_h_lowpass_l2_neon +1: vld1.8 {d0, d1}, [r1], r2 + vld1.8 {d16,d17}, [r1], r2 + vld1.8 {d28}, [r3], r2 + vld1.8 {d29}, [r3], r2 + subs r12, r12, #2 + lowpass_8 d0, d1, d16, d17, d0, d1 + vrhadd.u8 q0, q0, q14 + .ifc \type,avg + vld1.8 {d2}, [r0,:64], r2 + vrhadd.u8 d0, d0, d2 + vld1.8 {d3}, [r0,:64] + vrhadd.u8 d1, d1, d3 + sub r0, r0, r2 + .endif + vst1.8 {d0}, [r0,:64], r2 + vst1.8 {d1}, [r0,:64], r2 + bne 1b + bx lr +endfunc +.endm + + h264_qpel_h_lowpass_l2 put + h264_qpel_h_lowpass_l2 avg + +function put_h264_qpel16_v_lowpass_neon_packed + mov r4, lr + mov r2, #8 + bl put_h264_qpel8_v_lowpass_neon + sub r1, r1, r3, lsl #2 + bl put_h264_qpel8_v_lowpass_neon + sub r1, r1, r3, lsl #4 + sub r1, r1, r3, lsl #2 + add r1, r1, #8 + bl put_h264_qpel8_v_lowpass_neon + sub r1, r1, r3, lsl #2 + mov lr, r4 + b put_h264_qpel8_v_lowpass_neon +endfunc + +.macro h264_qpel_v_lowpass type +function \type\()_h264_qpel16_v_lowpass_neon + mov r4, lr + bl \type\()_h264_qpel8_v_lowpass_neon + sub r1, r1, r3, lsl #2 + bl \type\()_h264_qpel8_v_lowpass_neon + sub r0, r0, r2, lsl #4 + add r0, r0, #8 + sub r1, r1, r3, lsl #4 + sub r1, r1, r3, lsl #2 + add r1, r1, #8 + bl \type\()_h264_qpel8_v_lowpass_neon + sub r1, r1, r3, lsl #2 + mov lr, r4 +endfunc + +function \type\()_h264_qpel8_v_lowpass_neon + vld1.8 {d8}, [r1], r3 + vld1.8 {d10}, [r1], r3 + vld1.8 {d12}, [r1], r3 + vld1.8 {d14}, [r1], r3 + vld1.8 {d22}, [r1], r3 + vld1.8 {d24}, [r1], r3 + vld1.8 {d26}, [r1], r3 + vld1.8 {d28}, [r1], r3 + vld1.8 {d9}, [r1], r3 + vld1.8 {d11}, [r1], r3 + vld1.8 {d13}, [r1], r3 + vld1.8 {d15}, [r1], r3 + vld1.8 {d23}, [r1] + + transpose_8x8 q4, q5, q6, q7, q11, q12, q13, q14 + lowpass_8 d8, d9, d10, d11, d8, d10 + lowpass_8 d12, d13, d14, d15, d12, d14 + lowpass_8 d22, d23, d24, d25, d22, d24 + lowpass_8 d26, d27, d28, d29, d26, d28 + transpose_8x8 d8, d10, d12, d14, d22, d24, d26, d28 + + .ifc \type,avg + vld1.8 {d9}, [r0,:64], r2 + vrhadd.u8 d8, d8, d9 + vld1.8 {d11}, [r0,:64], r2 + vrhadd.u8 d10, d10, d11 + vld1.8 {d13}, [r0,:64], r2 + vrhadd.u8 d12, d12, d13 + vld1.8 {d15}, [r0,:64], r2 + vrhadd.u8 d14, d14, d15 + vld1.8 {d23}, [r0,:64], r2 + vrhadd.u8 d22, d22, d23 + vld1.8 {d25}, [r0,:64], r2 + vrhadd.u8 d24, d24, d25 + vld1.8 {d27}, [r0,:64], r2 + vrhadd.u8 d26, d26, d27 + vld1.8 {d29}, [r0,:64], r2 + vrhadd.u8 d28, d28, d29 + sub r0, r0, r2, lsl #3 + .endif + + vst1.8 {d8}, [r0,:64], r2 + vst1.8 {d10}, [r0,:64], r2 + vst1.8 {d12}, [r0,:64], r2 + vst1.8 {d14}, [r0,:64], r2 + vst1.8 {d22}, [r0,:64], r2 + vst1.8 {d24}, [r0,:64], r2 + vst1.8 {d26}, [r0,:64], r2 + vst1.8 {d28}, [r0,:64], r2 + + bx lr +endfunc +.endm + + h264_qpel_v_lowpass put + h264_qpel_v_lowpass avg + +.macro h264_qpel_v_lowpass_l2 type +function \type\()_h264_qpel16_v_lowpass_l2_neon + mov r4, lr + bl \type\()_h264_qpel8_v_lowpass_l2_neon + sub r1, r1, r3, lsl #2 + bl \type\()_h264_qpel8_v_lowpass_l2_neon + sub r0, r0, r3, lsl #4 + sub r12, r12, r2, lsl #4 + add r0, r0, #8 + add r12, r12, #8 + sub r1, r1, r3, lsl #4 + sub r1, r1, r3, lsl #2 + add r1, r1, #8 + bl \type\()_h264_qpel8_v_lowpass_l2_neon + sub r1, r1, r3, lsl #2 + mov lr, r4 +endfunc + +function \type\()_h264_qpel8_v_lowpass_l2_neon + vld1.8 {d8}, [r1], r3 + vld1.8 {d10}, [r1], r3 + vld1.8 {d12}, [r1], r3 + vld1.8 {d14}, [r1], r3 + vld1.8 {d22}, [r1], r3 + vld1.8 {d24}, [r1], r3 + vld1.8 {d26}, [r1], r3 + vld1.8 {d28}, [r1], r3 + vld1.8 {d9}, [r1], r3 + vld1.8 {d11}, [r1], r3 + vld1.8 {d13}, [r1], r3 + vld1.8 {d15}, [r1], r3 + vld1.8 {d23}, [r1] + + transpose_8x8 q4, q5, q6, q7, q11, q12, q13, q14 + lowpass_8 d8, d9, d10, d11, d8, d9 + lowpass_8 d12, d13, d14, d15, d12, d13 + lowpass_8 d22, d23, d24, d25, d22, d23 + lowpass_8 d26, d27, d28, d29, d26, d27 + transpose_8x8 d8, d9, d12, d13, d22, d23, d26, d27 + + vld1.8 {d0}, [r12], r2 + vld1.8 {d1}, [r12], r2 + vld1.8 {d2}, [r12], r2 + vld1.8 {d3}, [r12], r2 + vld1.8 {d4}, [r12], r2 + vrhadd.u8 q0, q0, q4 + vld1.8 {d5}, [r12], r2 + vrhadd.u8 q1, q1, q6 + vld1.8 {d10}, [r12], r2 + vrhadd.u8 q2, q2, q11 + vld1.8 {d11}, [r12], r2 + vrhadd.u8 q5, q5, q13 + + .ifc \type,avg + vld1.8 {d16}, [r0,:64], r3 + vrhadd.u8 d0, d0, d16 + vld1.8 {d17}, [r0,:64], r3 + vrhadd.u8 d1, d1, d17 + vld1.8 {d16}, [r0,:64], r3 + vrhadd.u8 d2, d2, d16 + vld1.8 {d17}, [r0,:64], r3 + vrhadd.u8 d3, d3, d17 + vld1.8 {d16}, [r0,:64], r3 + vrhadd.u8 d4, d4, d16 + vld1.8 {d17}, [r0,:64], r3 + vrhadd.u8 d5, d5, d17 + vld1.8 {d16}, [r0,:64], r3 + vrhadd.u8 d10, d10, d16 + vld1.8 {d17}, [r0,:64], r3 + vrhadd.u8 d11, d11, d17 + sub r0, r0, r3, lsl #3 + .endif + + vst1.8 {d0}, [r0,:64], r3 + vst1.8 {d1}, [r0,:64], r3 + vst1.8 {d2}, [r0,:64], r3 + vst1.8 {d3}, [r0,:64], r3 + vst1.8 {d4}, [r0,:64], r3 + vst1.8 {d5}, [r0,:64], r3 + vst1.8 {d10}, [r0,:64], r3 + vst1.8 {d11}, [r0,:64], r3 + + bx lr +endfunc +.endm + + h264_qpel_v_lowpass_l2 put + h264_qpel_v_lowpass_l2 avg + +function put_h264_qpel8_hv_lowpass_neon_top + lowpass_const r12 + mov r12, #12 +1: vld1.8 {d0, d1}, [r1], r3 + vld1.8 {d16,d17}, [r1], r3 + subs r12, r12, #2 + lowpass_8 d0, d1, d16, d17, q11, q12, narrow=0 + vst1.8 {d22-d25}, [r4,:128]! + bne 1b + + vld1.8 {d0, d1}, [r1] + lowpass_8_1 d0, d1, q12, narrow=0 + + mov r12, #-16 + add r4, r4, r12 + vld1.8 {d30,d31}, [r4,:128], r12 + vld1.8 {d20,d21}, [r4,:128], r12 + vld1.8 {d18,d19}, [r4,:128], r12 + vld1.8 {d16,d17}, [r4,:128], r12 + vld1.8 {d14,d15}, [r4,:128], r12 + vld1.8 {d12,d13}, [r4,:128], r12 + vld1.8 {d10,d11}, [r4,:128], r12 + vld1.8 {d8, d9}, [r4,:128], r12 + vld1.8 {d6, d7}, [r4,:128], r12 + vld1.8 {d4, d5}, [r4,:128], r12 + vld1.8 {d2, d3}, [r4,:128], r12 + vld1.8 {d0, d1}, [r4,:128] + + swap4 d1, d3, d5, d7, d8, d10, d12, d14 + transpose16_4x4 q0, q1, q2, q3, q4, q5, q6, q7 + + swap4 d17, d19, d21, d31, d24, d26, d28, d22 + transpose16_4x4 q8, q9, q10, q15, q12, q13, q14, q11 + + vst1.8 {d30,d31}, [r4,:128]! + vst1.8 {d6, d7}, [r4,:128]! + vst1.8 {d20,d21}, [r4,:128]! + vst1.8 {d4, d5}, [r4,:128]! + vst1.8 {d18,d19}, [r4,:128]! + vst1.8 {d2, d3}, [r4,:128]! + vst1.8 {d16,d17}, [r4,:128]! + vst1.8 {d0, d1}, [r4,:128] + + lowpass_8.16 q4, q12, d8, d9, d24, d25, d8 + lowpass_8.16 q5, q13, d10, d11, d26, d27, d9 + lowpass_8.16 q6, q14, d12, d13, d28, d29, d10 + lowpass_8.16 q7, q11, d14, d15, d22, d23, d11 + + vld1.8 {d16,d17}, [r4,:128], r12 + vld1.8 {d30,d31}, [r4,:128], r12 + lowpass_8.16 q8, q15, d16, d17, d30, d31, d12 + vld1.8 {d16,d17}, [r4,:128], r12 + vld1.8 {d30,d31}, [r4,:128], r12 + lowpass_8.16 q8, q15, d16, d17, d30, d31, d13 + vld1.8 {d16,d17}, [r4,:128], r12 + vld1.8 {d30,d31}, [r4,:128], r12 + lowpass_8.16 q8, q15, d16, d17, d30, d31, d14 + vld1.8 {d16,d17}, [r4,:128], r12 + vld1.8 {d30,d31}, [r4,:128] + lowpass_8.16 q8, q15, d16, d17, d30, d31, d15 + + transpose_8x8 d12, d13, d14, d15, d8, d9, d10, d11 + + bx lr +endfunc + +.macro h264_qpel8_hv_lowpass type +function \type\()_h264_qpel8_hv_lowpass_neon + mov r10, lr + bl put_h264_qpel8_hv_lowpass_neon_top + .ifc \type,avg + vld1.8 {d0}, [r0,:64], r2 + vrhadd.u8 d12, d12, d0 + vld1.8 {d1}, [r0,:64], r2 + vrhadd.u8 d13, d13, d1 + vld1.8 {d2}, [r0,:64], r2 + vrhadd.u8 d14, d14, d2 + vld1.8 {d3}, [r0,:64], r2 + vrhadd.u8 d15, d15, d3 + vld1.8 {d4}, [r0,:64], r2 + vrhadd.u8 d8, d8, d4 + vld1.8 {d5}, [r0,:64], r2 + vrhadd.u8 d9, d9, d5 + vld1.8 {d6}, [r0,:64], r2 + vrhadd.u8 d10, d10, d6 + vld1.8 {d7}, [r0,:64], r2 + vrhadd.u8 d11, d11, d7 + sub r0, r0, r2, lsl #3 + .endif + + vst1.8 {d12}, [r0,:64], r2 + vst1.8 {d13}, [r0,:64], r2 + vst1.8 {d14}, [r0,:64], r2 + vst1.8 {d15}, [r0,:64], r2 + vst1.8 {d8}, [r0,:64], r2 + vst1.8 {d9}, [r0,:64], r2 + vst1.8 {d10}, [r0,:64], r2 + vst1.8 {d11}, [r0,:64], r2 + + mov lr, r10 + bx lr +endfunc +.endm + + h264_qpel8_hv_lowpass put + h264_qpel8_hv_lowpass avg + +.macro h264_qpel8_hv_lowpass_l2 type +function \type\()_h264_qpel8_hv_lowpass_l2_neon + mov r10, lr + bl put_h264_qpel8_hv_lowpass_neon_top + + vld1.8 {d0, d1}, [r2,:128]! + vld1.8 {d2, d3}, [r2,:128]! + vrhadd.u8 q0, q0, q6 + vld1.8 {d4, d5}, [r2,:128]! + vrhadd.u8 q1, q1, q7 + vld1.8 {d6, d7}, [r2,:128]! + vrhadd.u8 q2, q2, q4 + vrhadd.u8 q3, q3, q5 + .ifc \type,avg + vld1.8 {d16}, [r0,:64], r3 + vrhadd.u8 d0, d0, d16 + vld1.8 {d17}, [r0,:64], r3 + vrhadd.u8 d1, d1, d17 + vld1.8 {d18}, [r0,:64], r3 + vrhadd.u8 d2, d2, d18 + vld1.8 {d19}, [r0,:64], r3 + vrhadd.u8 d3, d3, d19 + vld1.8 {d20}, [r0,:64], r3 + vrhadd.u8 d4, d4, d20 + vld1.8 {d21}, [r0,:64], r3 + vrhadd.u8 d5, d5, d21 + vld1.8 {d22}, [r0,:64], r3 + vrhadd.u8 d6, d6, d22 + vld1.8 {d23}, [r0,:64], r3 + vrhadd.u8 d7, d7, d23 + sub r0, r0, r3, lsl #3 + .endif + vst1.8 {d0}, [r0,:64], r3 + vst1.8 {d1}, [r0,:64], r3 + vst1.8 {d2}, [r0,:64], r3 + vst1.8 {d3}, [r0,:64], r3 + vst1.8 {d4}, [r0,:64], r3 + vst1.8 {d5}, [r0,:64], r3 + vst1.8 {d6}, [r0,:64], r3 + vst1.8 {d7}, [r0,:64], r3 + + mov lr, r10 + bx lr +endfunc +.endm + + h264_qpel8_hv_lowpass_l2 put + h264_qpel8_hv_lowpass_l2 avg + +.macro h264_qpel16_hv type +function \type\()_h264_qpel16_hv_lowpass_neon + mov r9, lr + bl \type\()_h264_qpel8_hv_lowpass_neon + sub r1, r1, r3, lsl #2 + bl \type\()_h264_qpel8_hv_lowpass_neon + sub r1, r1, r3, lsl #4 + sub r1, r1, r3, lsl #2 + add r1, r1, #8 + sub r0, r0, r2, lsl #4 + add r0, r0, #8 + bl \type\()_h264_qpel8_hv_lowpass_neon + sub r1, r1, r3, lsl #2 + mov lr, r9 + b \type\()_h264_qpel8_hv_lowpass_neon +endfunc + +function \type\()_h264_qpel16_hv_lowpass_l2_neon + mov r9, lr + sub r2, r4, #256 + bl \type\()_h264_qpel8_hv_lowpass_l2_neon + sub r1, r1, r3, lsl #2 + bl \type\()_h264_qpel8_hv_lowpass_l2_neon + sub r1, r1, r3, lsl #4 + sub r1, r1, r3, lsl #2 + add r1, r1, #8 + sub r0, r0, r3, lsl #4 + add r0, r0, #8 + bl \type\()_h264_qpel8_hv_lowpass_l2_neon + sub r1, r1, r3, lsl #2 + mov lr, r9 + b \type\()_h264_qpel8_hv_lowpass_l2_neon +endfunc +.endm + + h264_qpel16_hv put + h264_qpel16_hv avg + +.macro h264_qpel8 type +function ff_\type\()_h264_qpel8_mc10_neon, export=1 + lowpass_const r3 + mov r3, r1 + sub r1, r1, #2 + mov r12, #8 + b \type\()_h264_qpel8_h_lowpass_l2_neon +endfunc + +function ff_\type\()_h264_qpel8_mc20_neon, export=1 + lowpass_const r3 + sub r1, r1, #2 + mov r3, r2 + mov r12, #8 + b \type\()_h264_qpel8_h_lowpass_neon +endfunc + +function ff_\type\()_h264_qpel8_mc30_neon, export=1 + lowpass_const r3 + add r3, r1, #1 + sub r1, r1, #2 + mov r12, #8 + b \type\()_h264_qpel8_h_lowpass_l2_neon +endfunc + +function ff_\type\()_h264_qpel8_mc01_neon, export=1 + push {lr} + mov r12, r1 +\type\()_h264_qpel8_mc01: + lowpass_const r3 + mov r3, r2 + sub r1, r1, r2, lsl #1 + vpush {d8-d15} + bl \type\()_h264_qpel8_v_lowpass_l2_neon + vpop {d8-d15} + pop {pc} +endfunc + +function ff_\type\()_h264_qpel8_mc11_neon, export=1 + push {r0, r1, r11, lr} +\type\()_h264_qpel8_mc11: + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r0, r11, #15 +T mov sp, r0 + sub sp, sp, #64 + mov r0, sp + sub r1, r1, #2 + mov r3, #8 + mov r12, #8 + vpush {d8-d15} + bl put_h264_qpel8_h_lowpass_neon + ldrd r0, r1, [r11], #8 + mov r3, r2 + add r12, sp, #64 + sub r1, r1, r2, lsl #1 + mov r2, #8 + bl \type\()_h264_qpel8_v_lowpass_l2_neon + vpop {d8-d15} + mov sp, r11 + pop {r11, pc} +endfunc + +function ff_\type\()_h264_qpel8_mc21_neon, export=1 + push {r0, r1, r4, r10, r11, lr} +\type\()_h264_qpel8_mc21: + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r0, r11, #15 +T mov sp, r0 + sub sp, sp, #(8*8+16*12) + sub r1, r1, #2 + mov r3, #8 + mov r0, sp + mov r12, #8 + vpush {d8-d15} + bl put_h264_qpel8_h_lowpass_neon + mov r4, r0 + ldrd r0, r1, [r11], #8 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, r2 + sub r2, r4, #64 + bl \type\()_h264_qpel8_hv_lowpass_l2_neon + vpop {d8-d15} + mov sp, r11 + pop {r4, r10, r11, pc} +endfunc + +function ff_\type\()_h264_qpel8_mc31_neon, export=1 + add r1, r1, #1 + push {r0, r1, r11, lr} + sub r1, r1, #1 + b \type\()_h264_qpel8_mc11 +endfunc + +function ff_\type\()_h264_qpel8_mc02_neon, export=1 + push {lr} + lowpass_const r3 + sub r1, r1, r2, lsl #1 + mov r3, r2 + vpush {d8-d15} + bl \type\()_h264_qpel8_v_lowpass_neon + vpop {d8-d15} + pop {pc} +endfunc + +function ff_\type\()_h264_qpel8_mc12_neon, export=1 + push {r0, r1, r4, r10, r11, lr} +\type\()_h264_qpel8_mc12: + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r0, r11, #15 +T mov sp, r0 + sub sp, sp, #(8*8+16*12) + sub r1, r1, r2, lsl #1 + mov r3, r2 + mov r2, #8 + mov r0, sp + vpush {d8-d15} + bl put_h264_qpel8_v_lowpass_neon + mov r4, r0 + ldrd r0, r1, [r11], #8 + sub r1, r1, r3, lsl #1 + sub r1, r1, #2 + sub r2, r4, #64 + bl \type\()_h264_qpel8_hv_lowpass_l2_neon + vpop {d8-d15} + mov sp, r11 + pop {r4, r10, r11, pc} +endfunc + +function ff_\type\()_h264_qpel8_mc22_neon, export=1 + push {r4, r10, r11, lr} + mov r11, sp +A bic sp, sp, #15 +T bic r4, r11, #15 +T mov sp, r4 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, r2 + sub sp, sp, #(16*12) + mov r4, sp + vpush {d8-d15} + bl \type\()_h264_qpel8_hv_lowpass_neon + vpop {d8-d15} + mov sp, r11 + pop {r4, r10, r11, pc} +endfunc + +function ff_\type\()_h264_qpel8_mc32_neon, export=1 + push {r0, r1, r4, r10, r11, lr} + add r1, r1, #1 + b \type\()_h264_qpel8_mc12 +endfunc + +function ff_\type\()_h264_qpel8_mc03_neon, export=1 + push {lr} + add r12, r1, r2 + b \type\()_h264_qpel8_mc01 +endfunc + +function ff_\type\()_h264_qpel8_mc13_neon, export=1 + push {r0, r1, r11, lr} + add r1, r1, r2 + b \type\()_h264_qpel8_mc11 +endfunc + +function ff_\type\()_h264_qpel8_mc23_neon, export=1 + push {r0, r1, r4, r10, r11, lr} + add r1, r1, r2 + b \type\()_h264_qpel8_mc21 +endfunc + +function ff_\type\()_h264_qpel8_mc33_neon, export=1 + add r1, r1, #1 + push {r0, r1, r11, lr} + add r1, r1, r2 + sub r1, r1, #1 + b \type\()_h264_qpel8_mc11 +endfunc +.endm + + h264_qpel8 put + h264_qpel8 avg + +.macro h264_qpel16 type +function ff_\type\()_h264_qpel16_mc10_neon, export=1 + lowpass_const r3 + mov r3, r1 + sub r1, r1, #2 + b \type\()_h264_qpel16_h_lowpass_l2_neon +endfunc + +function ff_\type\()_h264_qpel16_mc20_neon, export=1 + lowpass_const r3 + sub r1, r1, #2 + mov r3, r2 + b \type\()_h264_qpel16_h_lowpass_neon +endfunc + +function ff_\type\()_h264_qpel16_mc30_neon, export=1 + lowpass_const r3 + add r3, r1, #1 + sub r1, r1, #2 + b \type\()_h264_qpel16_h_lowpass_l2_neon +endfunc + +function ff_\type\()_h264_qpel16_mc01_neon, export=1 + push {r4, lr} + mov r12, r1 +\type\()_h264_qpel16_mc01: + lowpass_const r3 + mov r3, r2 + sub r1, r1, r2, lsl #1 + vpush {d8-d15} + bl \type\()_h264_qpel16_v_lowpass_l2_neon + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_h264_qpel16_mc11_neon, export=1 + push {r0, r1, r4, r11, lr} +\type\()_h264_qpel16_mc11: + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r0, r11, #15 +T mov sp, r0 + sub sp, sp, #256 + mov r0, sp + sub r1, r1, #2 + mov r3, #16 + vpush {d8-d15} + bl put_h264_qpel16_h_lowpass_neon + ldrd r0, r1, [r11], #8 + mov r3, r2 + add r12, sp, #64 + sub r1, r1, r2, lsl #1 + mov r2, #16 + bl \type\()_h264_qpel16_v_lowpass_l2_neon + vpop {d8-d15} + mov sp, r11 + pop {r4, r11, pc} +endfunc + +function ff_\type\()_h264_qpel16_mc21_neon, export=1 + push {r0, r1, r4-r5, r9-r11, lr} +\type\()_h264_qpel16_mc21: + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r0, r11, #15 +T mov sp, r0 + sub sp, sp, #(16*16+16*12) + sub r1, r1, #2 + mov r0, sp + vpush {d8-d15} + bl put_h264_qpel16_h_lowpass_neon_packed + mov r4, r0 + ldrd r0, r1, [r11], #8 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, r2 + bl \type\()_h264_qpel16_hv_lowpass_l2_neon + vpop {d8-d15} + mov sp, r11 + pop {r4-r5, r9-r11, pc} +endfunc + +function ff_\type\()_h264_qpel16_mc31_neon, export=1 + add r1, r1, #1 + push {r0, r1, r4, r11, lr} + sub r1, r1, #1 + b \type\()_h264_qpel16_mc11 +endfunc + +function ff_\type\()_h264_qpel16_mc02_neon, export=1 + push {r4, lr} + lowpass_const r3 + sub r1, r1, r2, lsl #1 + mov r3, r2 + vpush {d8-d15} + bl \type\()_h264_qpel16_v_lowpass_neon + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_h264_qpel16_mc12_neon, export=1 + push {r0, r1, r4-r5, r9-r11, lr} +\type\()_h264_qpel16_mc12: + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r0, r11, #15 +T mov sp, r0 + sub sp, sp, #(16*16+16*12) + sub r1, r1, r2, lsl #1 + mov r0, sp + mov r3, r2 + vpush {d8-d15} + bl put_h264_qpel16_v_lowpass_neon_packed + mov r4, r0 + ldrd r0, r1, [r11], #8 + sub r1, r1, r3, lsl #1 + sub r1, r1, #2 + mov r2, r3 + bl \type\()_h264_qpel16_hv_lowpass_l2_neon + vpop {d8-d15} + mov sp, r11 + pop {r4-r5, r9-r11, pc} +endfunc + +function ff_\type\()_h264_qpel16_mc22_neon, export=1 + push {r4, r9-r11, lr} + lowpass_const r3 + mov r11, sp +A bic sp, sp, #15 +T bic r4, r11, #15 +T mov sp, r4 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, r2 + sub sp, sp, #(16*12) + mov r4, sp + vpush {d8-d15} + bl \type\()_h264_qpel16_hv_lowpass_neon + vpop {d8-d15} + mov sp, r11 + pop {r4, r9-r11, pc} +endfunc + +function ff_\type\()_h264_qpel16_mc32_neon, export=1 + push {r0, r1, r4-r5, r9-r11, lr} + add r1, r1, #1 + b \type\()_h264_qpel16_mc12 +endfunc + +function ff_\type\()_h264_qpel16_mc03_neon, export=1 + push {r4, lr} + add r12, r1, r2 + b \type\()_h264_qpel16_mc01 +endfunc + +function ff_\type\()_h264_qpel16_mc13_neon, export=1 + push {r0, r1, r4, r11, lr} + add r1, r1, r2 + b \type\()_h264_qpel16_mc11 +endfunc + +function ff_\type\()_h264_qpel16_mc23_neon, export=1 + push {r0, r1, r4-r5, r9-r11, lr} + add r1, r1, r2 + b \type\()_h264_qpel16_mc21 +endfunc + +function ff_\type\()_h264_qpel16_mc33_neon, export=1 + add r1, r1, #1 + push {r0, r1, r4, r11, lr} + add r1, r1, r2 + sub r1, r1, #1 + b \type\()_h264_qpel16_mc11 +endfunc +.endm + + h264_qpel16 put + h264_qpel16 avg diff --git a/ffmpeg/libavcodec/arm/hpeldsp_arm.S b/ffmpeg/libavcodec/arm/hpeldsp_arm.S new file mode 100644 index 0000000..2f3d311 --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_arm.S @@ -0,0 +1,611 @@ +@ +@ ARMv4 optimized DSP utils +@ Copyright (c) 2004 AGAWA Koji +@ +@ 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 "config.h" +#include "libavutil/arm/asm.S" + +#if !HAVE_ARMV5TE_EXTERNAL +#define pld @ +#endif + +.macro ALIGN_QWORD_D shift, Rd0, Rd1, Rd2, Rd3, Rn0, Rn1, Rn2, Rn3, Rn4 + mov \Rd0, \Rn0, lsr #(\shift * 8) + mov \Rd1, \Rn1, lsr #(\shift * 8) + mov \Rd2, \Rn2, lsr #(\shift * 8) + mov \Rd3, \Rn3, lsr #(\shift * 8) + orr \Rd0, \Rd0, \Rn1, lsl #(32 - \shift * 8) + orr \Rd1, \Rd1, \Rn2, lsl #(32 - \shift * 8) + orr \Rd2, \Rd2, \Rn3, lsl #(32 - \shift * 8) + orr \Rd3, \Rd3, \Rn4, lsl #(32 - \shift * 8) +.endm +.macro ALIGN_DWORD shift, R0, R1, R2 + mov \R0, \R0, lsr #(\shift * 8) + orr \R0, \R0, \R1, lsl #(32 - \shift * 8) + mov \R1, \R1, lsr #(\shift * 8) + orr \R1, \R1, \R2, lsl #(32 - \shift * 8) +.endm +.macro ALIGN_DWORD_D shift, Rdst0, Rdst1, Rsrc0, Rsrc1, Rsrc2 + mov \Rdst0, \Rsrc0, lsr #(\shift * 8) + mov \Rdst1, \Rsrc1, lsr #(\shift * 8) + orr \Rdst0, \Rdst0, \Rsrc1, lsl #(32 - (\shift * 8)) + orr \Rdst1, \Rdst1, \Rsrc2, lsl #(32 - (\shift * 8)) +.endm + +.macro RND_AVG32 Rd0, Rd1, Rn0, Rn1, Rm0, Rm1, Rmask + @ Rd = (Rn | Rm) - (((Rn ^ Rm) & ~0x01010101) >> 1) + @ Rmask = 0xFEFEFEFE + @ Rn = destroy + eor \Rd0, \Rn0, \Rm0 + eor \Rd1, \Rn1, \Rm1 + orr \Rn0, \Rn0, \Rm0 + orr \Rn1, \Rn1, \Rm1 + and \Rd0, \Rd0, \Rmask + and \Rd1, \Rd1, \Rmask + sub \Rd0, \Rn0, \Rd0, lsr #1 + sub \Rd1, \Rn1, \Rd1, lsr #1 +.endm + +.macro NO_RND_AVG32 Rd0, Rd1, Rn0, Rn1, Rm0, Rm1, Rmask + @ Rd = (Rn & Rm) - (((Rn ^ Rm) & ~0x01010101) >> 1) + @ Rmask = 0xFEFEFEFE + @ Rn = destroy + eor \Rd0, \Rn0, \Rm0 + eor \Rd1, \Rn1, \Rm1 + and \Rn0, \Rn0, \Rm0 + and \Rn1, \Rn1, \Rm1 + and \Rd0, \Rd0, \Rmask + and \Rd1, \Rd1, \Rmask + add \Rd0, \Rn0, \Rd0, lsr #1 + add \Rd1, \Rn1, \Rd1, lsr #1 +.endm + +.macro JMP_ALIGN tmp, reg + ands \tmp, \reg, #3 + bic \reg, \reg, #3 + beq 1f + subs \tmp, \tmp, #1 + beq 2f + subs \tmp, \tmp, #1 + beq 3f + b 4f +.endm + +@ ---------------------------------------------------------------- + .align 5 +function ff_put_pixels16_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r11, lr} + JMP_ALIGN r5, r1 +1: + ldm r1, {r4-r7} + add r1, r1, r2 + stm r0, {r4-r7} + pld [r1] + subs r3, r3, #1 + add r0, r0, r2 + bne 1b + pop {r4-r11, pc} + .align 5 +2: + ldm r1, {r4-r8} + add r1, r1, r2 + ALIGN_QWORD_D 1, r9, r10, r11, r12, r4, r5, r6, r7, r8 + pld [r1] + subs r3, r3, #1 + stm r0, {r9-r12} + add r0, r0, r2 + bne 2b + pop {r4-r11, pc} + .align 5 +3: + ldm r1, {r4-r8} + add r1, r1, r2 + ALIGN_QWORD_D 2, r9, r10, r11, r12, r4, r5, r6, r7, r8 + pld [r1] + subs r3, r3, #1 + stm r0, {r9-r12} + add r0, r0, r2 + bne 3b + pop {r4-r11, pc} + .align 5 +4: + ldm r1, {r4-r8} + add r1, r1, r2 + ALIGN_QWORD_D 3, r9, r10, r11, r12, r4, r5, r6, r7, r8 + pld [r1] + subs r3, r3, #1 + stm r0, {r9-r12} + add r0, r0, r2 + bne 4b + pop {r4-r11,pc} +endfunc + +@ ---------------------------------------------------------------- + .align 5 +function ff_put_pixels8_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r5,lr} + JMP_ALIGN r5, r1 +1: + ldm r1, {r4-r5} + add r1, r1, r2 + subs r3, r3, #1 + pld [r1] + stm r0, {r4-r5} + add r0, r0, r2 + bne 1b + pop {r4-r5,pc} + .align 5 +2: + ldm r1, {r4-r5, r12} + add r1, r1, r2 + ALIGN_DWORD 1, r4, r5, r12 + pld [r1] + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 2b + pop {r4-r5,pc} + .align 5 +3: + ldm r1, {r4-r5, r12} + add r1, r1, r2 + ALIGN_DWORD 2, r4, r5, r12 + pld [r1] + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 3b + pop {r4-r5,pc} + .align 5 +4: + ldm r1, {r4-r5, r12} + add r1, r1, r2 + ALIGN_DWORD 3, r4, r5, r12 + pld [r1] + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 4b + pop {r4-r5,pc} +endfunc + +@ ---------------------------------------------------------------- + .align 5 +function ff_put_pixels8_x2_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r10,lr} + ldr r12, =0xfefefefe + JMP_ALIGN r5, r1 +1: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 1, r6, r7, r4, r5, r10 + pld [r1] + RND_AVG32 r8, r9, r4, r5, r6, r7, r12 + subs r3, r3, #1 + stm r0, {r8-r9} + add r0, r0, r2 + bne 1b + pop {r4-r10,pc} + .align 5 +2: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 1, r6, r7, r4, r5, r10 + ALIGN_DWORD_D 2, r8, r9, r4, r5, r10 + pld [r1] + RND_AVG32 r4, r5, r6, r7, r8, r9, r12 + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 2b + pop {r4-r10,pc} + .align 5 +3: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 2, r6, r7, r4, r5, r10 + ALIGN_DWORD_D 3, r8, r9, r4, r5, r10 + pld [r1] + RND_AVG32 r4, r5, r6, r7, r8, r9, r12 + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 3b + pop {r4-r10,pc} + .align 5 +4: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 3, r6, r7, r4, r5, r10 + pld [r1] + RND_AVG32 r8, r9, r6, r7, r5, r10, r12 + subs r3, r3, #1 + stm r0, {r8-r9} + add r0, r0, r2 + bne 4b + pop {r4-r10,pc} +endfunc + + .align 5 +function ff_put_no_rnd_pixels8_x2_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r10,lr} + ldr r12, =0xfefefefe + JMP_ALIGN r5, r1 +1: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 1, r6, r7, r4, r5, r10 + pld [r1] + NO_RND_AVG32 r8, r9, r4, r5, r6, r7, r12 + subs r3, r3, #1 + stm r0, {r8-r9} + add r0, r0, r2 + bne 1b + pop {r4-r10,pc} + .align 5 +2: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 1, r6, r7, r4, r5, r10 + ALIGN_DWORD_D 2, r8, r9, r4, r5, r10 + pld [r1] + NO_RND_AVG32 r4, r5, r6, r7, r8, r9, r12 + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 2b + pop {r4-r10,pc} + .align 5 +3: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 2, r6, r7, r4, r5, r10 + ALIGN_DWORD_D 3, r8, r9, r4, r5, r10 + pld [r1] + NO_RND_AVG32 r4, r5, r6, r7, r8, r9, r12 + subs r3, r3, #1 + stm r0, {r4-r5} + add r0, r0, r2 + bne 3b + pop {r4-r10,pc} + .align 5 +4: + ldm r1, {r4-r5, r10} + add r1, r1, r2 + ALIGN_DWORD_D 3, r6, r7, r4, r5, r10 + pld [r1] + NO_RND_AVG32 r8, r9, r6, r7, r5, r10, r12 + subs r3, r3, #1 + stm r0, {r8-r9} + add r0, r0, r2 + bne 4b + pop {r4-r10,pc} +endfunc + + +@ ---------------------------------------------------------------- + .align 5 +function ff_put_pixels8_y2_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r11,lr} + mov r3, r3, lsr #1 + ldr r12, =0xfefefefe + JMP_ALIGN r5, r1 +1: + ldm r1, {r4-r5} + add r1, r1, r2 +6: ldm r1, {r6-r7} + add r1, r1, r2 + pld [r1] + RND_AVG32 r8, r9, r4, r5, r6, r7, r12 + ldm r1, {r4-r5} + add r1, r1, r2 + stm r0, {r8-r9} + add r0, r0, r2 + pld [r1] + RND_AVG32 r8, r9, r6, r7, r4, r5, r12 + subs r3, r3, #1 + stm r0, {r8-r9} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} + .align 5 +2: + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 1, r4, r5, r6 +6: ldm r1, {r7-r9} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 1, r7, r8, r9 + RND_AVG32 r10, r11, r4, r5, r7, r8, r12 + stm r0, {r10-r11} + add r0, r0, r2 + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 1, r4, r5, r6 + subs r3, r3, #1 + RND_AVG32 r10, r11, r7, r8, r4, r5, r12 + stm r0, {r10-r11} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} + .align 5 +3: + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 2, r4, r5, r6 +6: ldm r1, {r7-r9} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 2, r7, r8, r9 + RND_AVG32 r10, r11, r4, r5, r7, r8, r12 + stm r0, {r10-r11} + add r0, r0, r2 + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 2, r4, r5, r6 + subs r3, r3, #1 + RND_AVG32 r10, r11, r7, r8, r4, r5, r12 + stm r0, {r10-r11} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} + .align 5 +4: + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 3, r4, r5, r6 +6: ldm r1, {r7-r9} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 3, r7, r8, r9 + RND_AVG32 r10, r11, r4, r5, r7, r8, r12 + stm r0, {r10-r11} + add r0, r0, r2 + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 3, r4, r5, r6 + subs r3, r3, #1 + RND_AVG32 r10, r11, r7, r8, r4, r5, r12 + stm r0, {r10-r11} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} +endfunc + + .align 5 +function ff_put_no_rnd_pixels8_y2_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r11,lr} + mov r3, r3, lsr #1 + ldr r12, =0xfefefefe + JMP_ALIGN r5, r1 +1: + ldm r1, {r4-r5} + add r1, r1, r2 +6: ldm r1, {r6-r7} + add r1, r1, r2 + pld [r1] + NO_RND_AVG32 r8, r9, r4, r5, r6, r7, r12 + ldm r1, {r4-r5} + add r1, r1, r2 + stm r0, {r8-r9} + add r0, r0, r2 + pld [r1] + NO_RND_AVG32 r8, r9, r6, r7, r4, r5, r12 + subs r3, r3, #1 + stm r0, {r8-r9} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} + .align 5 +2: + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 1, r4, r5, r6 +6: ldm r1, {r7-r9} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 1, r7, r8, r9 + NO_RND_AVG32 r10, r11, r4, r5, r7, r8, r12 + stm r0, {r10-r11} + add r0, r0, r2 + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 1, r4, r5, r6 + subs r3, r3, #1 + NO_RND_AVG32 r10, r11, r7, r8, r4, r5, r12 + stm r0, {r10-r11} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} + .align 5 +3: + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 2, r4, r5, r6 +6: ldm r1, {r7-r9} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 2, r7, r8, r9 + NO_RND_AVG32 r10, r11, r4, r5, r7, r8, r12 + stm r0, {r10-r11} + add r0, r0, r2 + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 2, r4, r5, r6 + subs r3, r3, #1 + NO_RND_AVG32 r10, r11, r7, r8, r4, r5, r12 + stm r0, {r10-r11} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} + .align 5 +4: + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 3, r4, r5, r6 +6: ldm r1, {r7-r9} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 3, r7, r8, r9 + NO_RND_AVG32 r10, r11, r4, r5, r7, r8, r12 + stm r0, {r10-r11} + add r0, r0, r2 + ldm r1, {r4-r6} + add r1, r1, r2 + pld [r1] + ALIGN_DWORD 3, r4, r5, r6 + subs r3, r3, #1 + NO_RND_AVG32 r10, r11, r7, r8, r4, r5, r12 + stm r0, {r10-r11} + add r0, r0, r2 + bne 6b + pop {r4-r11,pc} +endfunc + + .ltorg + +@ ---------------------------------------------------------------- +.macro RND_XY2_IT align, rnd + @ l1= (a & 0x03030303) + (b & 0x03030303) ?(+ 0x02020202) + @ h1= ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2) +.if \align == 0 + ldm r1, {r6-r8} +.elseif \align == 3 + ldm r1, {r5-r7} +.else + ldm r1, {r8-r10} +.endif + add r1, r1, r2 + pld [r1] +.if \align == 0 + ALIGN_DWORD_D 1, r4, r5, r6, r7, r8 +.elseif \align == 1 + ALIGN_DWORD_D 1, r4, r5, r8, r9, r10 + ALIGN_DWORD_D 2, r6, r7, r8, r9, r10 +.elseif \align == 2 + ALIGN_DWORD_D 2, r4, r5, r8, r9, r10 + ALIGN_DWORD_D 3, r6, r7, r8, r9, r10 +.elseif \align == 3 + ALIGN_DWORD_D 3, r4, r5, r5, r6, r7 +.endif + ldr r14, =0x03030303 + tst r3, #1 + and r8, r4, r14 + and r9, r5, r14 + and r10, r6, r14 + and r11, r7, r14 + it eq + andeq r14, r14, r14, \rnd #1 + add r8, r8, r10 + add r9, r9, r11 + ldr r12, =0xfcfcfcfc >> 2 + itt eq + addeq r8, r8, r14 + addeq r9, r9, r14 + and r4, r12, r4, lsr #2 + and r5, r12, r5, lsr #2 + and r6, r12, r6, lsr #2 + and r7, r12, r7, lsr #2 + add r10, r4, r6 + add r11, r5, r7 + subs r3, r3, #1 +.endm + +.macro RND_XY2_EXPAND align, rnd + RND_XY2_IT \align, \rnd +6: push {r8-r11} + RND_XY2_IT \align, \rnd + pop {r4-r7} + add r4, r4, r8 + add r5, r5, r9 + ldr r14, =0x0f0f0f0f + add r6, r6, r10 + add r7, r7, r11 + and r4, r14, r4, lsr #2 + and r5, r14, r5, lsr #2 + add r4, r4, r6 + add r5, r5, r7 + stm r0, {r4-r5} + add r0, r0, r2 + bge 6b + pop {r4-r11,pc} +.endm + + .align 5 +function ff_put_pixels8_xy2_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r11,lr} @ R14 is also called LR + JMP_ALIGN r5, r1 +1: RND_XY2_EXPAND 0, lsl + .align 5 +2: RND_XY2_EXPAND 1, lsl + .align 5 +3: RND_XY2_EXPAND 2, lsl + .align 5 +4: RND_XY2_EXPAND 3, lsl +endfunc + + .align 5 +function ff_put_no_rnd_pixels8_xy2_arm, export=1 + @ void func(uint8_t *block, const uint8_t *pixels, int line_size, int h) + @ block = word aligned, pixles = unaligned + pld [r1] + push {r4-r11,lr} + JMP_ALIGN r5, r1 +1: RND_XY2_EXPAND 0, lsr + .align 5 +2: RND_XY2_EXPAND 1, lsr + .align 5 +3: RND_XY2_EXPAND 2, lsr + .align 5 +4: RND_XY2_EXPAND 3, lsr +endfunc diff --git a/ffmpeg/libavcodec/arm/hpeldsp_arm.h b/ffmpeg/libavcodec/arm/hpeldsp_arm.h new file mode 100644 index 0000000..e79bc6f --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_arm.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_ARM_HPELDSP_H +#define AVCODEC_ARM_HPELDSP_H + +#include "libavcodec/hpeldsp.h" + +void ff_hpeldsp_init_armv6(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_neon(HpelDSPContext *c, int flags); + +#endif /* AVCODEC_ARM_HPELDSP_H */ diff --git a/ffmpeg/libavcodec/arm/hpeldsp_armv6.S b/ffmpeg/libavcodec/arm/hpeldsp_armv6.S new file mode 100644 index 0000000..cd50150 --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_armv6.S @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +.macro call_2x_pixels type, subp +function ff_\type\()_pixels16\subp\()_armv6, export=1 + push {r0-r3, lr} + bl ff_\type\()_pixels8\subp\()_armv6 + pop {r0-r3, lr} + add r0, r0, #8 + add r1, r1, #8 + b ff_\type\()_pixels8\subp\()_armv6 +endfunc +.endm + +call_2x_pixels avg +call_2x_pixels put, _x2 +call_2x_pixels put, _y2 +call_2x_pixels put, _x2_no_rnd +call_2x_pixels put, _y2_no_rnd + +function ff_put_pixels16_armv6, export=1 + push {r4-r11} +1: + ldr r5, [r1, #4] + ldr r6, [r1, #8] + ldr r7, [r1, #12] + ldr_post r4, r1, r2 + strd r6, r7, [r0, #8] + ldr r9, [r1, #4] + strd_post r4, r5, r0, r2 + ldr r10, [r1, #8] + ldr r11, [r1, #12] + ldr_post r8, r1, r2 + strd r10, r11, [r0, #8] + subs r3, r3, #2 + strd_post r8, r9, r0, r2 + bne 1b + + pop {r4-r11} + bx lr +endfunc + +function ff_put_pixels8_armv6, export=1 + push {r4-r7} +1: + ldr r5, [r1, #4] + ldr_post r4, r1, r2 + ldr r7, [r1, #4] + strd_post r4, r5, r0, r2 + ldr_post r6, r1, r2 + subs r3, r3, #2 + strd_post r6, r7, r0, r2 + bne 1b + + pop {r4-r7} + bx lr +endfunc + +function ff_put_pixels8_x2_armv6, export=1 + push {r4-r11, lr} + mov r12, #1 + orr r12, r12, r12, lsl #8 + orr r12, r12, r12, lsl #16 +1: + ldr r4, [r1] + subs r3, r3, #2 + ldr r5, [r1, #4] + ldr r7, [r1, #5] + lsr r6, r4, #8 + ldr_pre r8, r1, r2 + orr r6, r6, r5, lsl #24 + ldr r9, [r1, #4] + ldr r11, [r1, #5] + lsr r10, r8, #8 + add r1, r1, r2 + orr r10, r10, r9, lsl #24 + eor r14, r4, r6 + uhadd8 r4, r4, r6 + eor r6, r5, r7 + uhadd8 r5, r5, r7 + and r14, r14, r12 + and r6, r6, r12 + uadd8 r4, r4, r14 + eor r14, r8, r10 + uadd8 r5, r5, r6 + eor r6, r9, r11 + uhadd8 r8, r8, r10 + and r14, r14, r12 + uhadd8 r9, r9, r11 + and r6, r6, r12 + uadd8 r8, r8, r14 + strd_post r4, r5, r0, r2 + uadd8 r9, r9, r6 + strd_post r8, r9, r0, r2 + bne 1b + + pop {r4-r11, pc} +endfunc + +function ff_put_pixels8_y2_armv6, export=1 + push {r4-r11} + mov r12, #1 + orr r12, r12, r12, lsl #8 + orr r12, r12, r12, lsl #16 + ldr r4, [r1] + ldr r5, [r1, #4] + ldr_pre r6, r1, r2 + ldr r7, [r1, #4] +1: + subs r3, r3, #2 + uhadd8 r8, r4, r6 + eor r10, r4, r6 + uhadd8 r9, r5, r7 + eor r11, r5, r7 + and r10, r10, r12 + ldr_pre r4, r1, r2 + uadd8 r8, r8, r10 + and r11, r11, r12 + uadd8 r9, r9, r11 + ldr r5, [r1, #4] + uhadd8 r10, r4, r6 + eor r6, r4, r6 + uhadd8 r11, r5, r7 + and r6, r6, r12 + eor r7, r5, r7 + uadd8 r10, r10, r6 + and r7, r7, r12 + ldr_pre r6, r1, r2 + uadd8 r11, r11, r7 + strd_post r8, r9, r0, r2 + ldr r7, [r1, #4] + strd_post r10, r11, r0, r2 + bne 1b + + pop {r4-r11} + bx lr +endfunc + +function ff_put_pixels8_x2_no_rnd_armv6, export=1 + push {r4-r9, lr} +1: + subs r3, r3, #2 + ldr r4, [r1] + ldr r5, [r1, #4] + ldr r7, [r1, #5] + ldr_pre r8, r1, r2 + ldr r9, [r1, #4] + ldr r14, [r1, #5] + add r1, r1, r2 + lsr r6, r4, #8 + orr r6, r6, r5, lsl #24 + lsr r12, r8, #8 + orr r12, r12, r9, lsl #24 + uhadd8 r4, r4, r6 + uhadd8 r5, r5, r7 + uhadd8 r8, r8, r12 + uhadd8 r9, r9, r14 + stm r0, {r4,r5} + add r0, r0, r2 + stm r0, {r8,r9} + add r0, r0, r2 + bne 1b + + pop {r4-r9, pc} +endfunc + +function ff_put_pixels8_y2_no_rnd_armv6, export=1 + push {r4-r9, lr} + ldr r4, [r1] + ldr r5, [r1, #4] + ldr_pre r6, r1, r2 + ldr r7, [r1, #4] +1: + subs r3, r3, #2 + uhadd8 r8, r4, r6 + ldr_pre r4, r1, r2 + uhadd8 r9, r5, r7 + ldr r5, [r1, #4] + uhadd8 r12, r4, r6 + ldr_pre r6, r1, r2 + uhadd8 r14, r5, r7 + ldr r7, [r1, #4] + stm r0, {r8,r9} + add r0, r0, r2 + stm r0, {r12,r14} + add r0, r0, r2 + bne 1b + + pop {r4-r9, pc} +endfunc + +function ff_avg_pixels8_armv6, export=1 + pld [r1, r2] + push {r4-r10, lr} + mov lr, #1 + orr lr, lr, lr, lsl #8 + orr lr, lr, lr, lsl #16 + ldrd r4, r5, [r0] + ldr r10, [r1, #4] + ldr_post r9, r1, r2 + subs r3, r3, #2 +1: + pld [r1, r2] + eor r8, r4, r9 + uhadd8 r4, r4, r9 + eor r12, r5, r10 + ldrd_reg r6, r7, r0, r2 + uhadd8 r5, r5, r10 + and r8, r8, lr + ldr r10, [r1, #4] + and r12, r12, lr + uadd8 r4, r4, r8 + ldr_post r9, r1, r2 + eor r8, r6, r9 + uadd8 r5, r5, r12 + pld [r1, r2, lsl #1] + eor r12, r7, r10 + uhadd8 r6, r6, r9 + strd_post r4, r5, r0, r2 + uhadd8 r7, r7, r10 + beq 2f + and r8, r8, lr + ldrd_reg r4, r5, r0, r2 + uadd8 r6, r6, r8 + ldr r10, [r1, #4] + and r12, r12, lr + subs r3, r3, #2 + uadd8 r7, r7, r12 + ldr_post r9, r1, r2 + strd_post r6, r7, r0, r2 + b 1b +2: + and r8, r8, lr + and r12, r12, lr + uadd8 r6, r6, r8 + uadd8 r7, r7, r12 + strd_post r6, r7, r0, r2 + + pop {r4-r10, pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/hpeldsp_init_arm.c b/ffmpeg/libavcodec/arm/hpeldsp_init_arm.c new file mode 100644 index 0000000..bae93eb --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_init_arm.c @@ -0,0 +1,68 @@ +/* + * ARM optimized DSP utils + * Copyright (c) 2001 Lionel Ulmer + * + * 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 "libavutil/arm/cpu.h" +#include "libavcodec/bit_depth_template.c" // for CALL_2X_PIXELS +#include "hpeldsp_arm.h" + +void ff_put_pixels8_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_put_pixels8_x2_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_put_pixels8_y2_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_put_pixels8_xy2_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); + +void ff_put_no_rnd_pixels8_x2_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_xy2_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); + +void ff_put_pixels16_arm(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); + +CALL_2X_PIXELS(ff_put_pixels16_x2_arm, ff_put_pixels8_x2_arm, 8) +CALL_2X_PIXELS(ff_put_pixels16_y2_arm, ff_put_pixels8_y2_arm, 8) +CALL_2X_PIXELS(ff_put_pixels16_xy2_arm, ff_put_pixels8_xy2_arm, 8) +CALL_2X_PIXELS(ff_put_no_rnd_pixels16_x2_arm, ff_put_no_rnd_pixels8_x2_arm, 8) +CALL_2X_PIXELS(ff_put_no_rnd_pixels16_y2_arm, ff_put_no_rnd_pixels8_y2_arm, 8) +CALL_2X_PIXELS(ff_put_no_rnd_pixels16_xy2_arm, ff_put_no_rnd_pixels8_xy2_arm,8) + +void ff_hpeldsp_init_arm(HpelDSPContext* c, int flags) +{ + int cpu_flags = av_get_cpu_flags(); + + c->put_pixels_tab[0][0] = ff_put_pixels16_arm; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_arm; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_arm; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_arm; + c->put_pixels_tab[1][0] = ff_put_pixels8_arm; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_arm; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_arm; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_arm; + + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_arm; + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_arm; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_arm; + c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_arm; + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_arm; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_arm; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_arm; + c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_arm; + + if (have_armv6(cpu_flags)) ff_hpeldsp_init_armv6(c, flags); + if (have_neon(cpu_flags)) ff_hpeldsp_init_neon(c, flags); +} diff --git a/ffmpeg/libavcodec/arm/hpeldsp_init_armv6.c b/ffmpeg/libavcodec/arm/hpeldsp_init_armv6.c new file mode 100644 index 0000000..da4caf8 --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_init_armv6.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "hpeldsp_arm.h" + +void ff_put_pixels16_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_x2_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_y2_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_put_pixels16_x2_no_rnd_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_y2_no_rnd_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_avg_pixels16_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_put_pixels8_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_x2_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_y2_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_put_pixels8_x2_no_rnd_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_y2_no_rnd_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_avg_pixels8_armv6(uint8_t *, const uint8_t *, ptrdiff_t, int); + +av_cold void ff_hpeldsp_init_armv6(HpelDSPContext *c, int flags) +{ + c->put_pixels_tab[0][0] = ff_put_pixels16_armv6; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_armv6; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_armv6; +/* c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_armv6; */ + c->put_pixels_tab[1][0] = ff_put_pixels8_armv6; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_armv6; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_armv6; +/* c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_armv6; */ + + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_armv6; + c->put_no_rnd_pixels_tab[0][1] = ff_put_pixels16_x2_no_rnd_armv6; + c->put_no_rnd_pixels_tab[0][2] = ff_put_pixels16_y2_no_rnd_armv6; +/* c->put_no_rnd_pixels_tab[0][3] = ff_put_pixels16_xy2_no_rnd_armv6; */ + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_armv6; + c->put_no_rnd_pixels_tab[1][1] = ff_put_pixels8_x2_no_rnd_armv6; + c->put_no_rnd_pixels_tab[1][2] = ff_put_pixels8_y2_no_rnd_armv6; +/* c->put_no_rnd_pixels_tab[1][3] = ff_put_pixels8_xy2_no_rnd_armv6; */ + + c->avg_pixels_tab[0][0] = ff_avg_pixels16_armv6; + c->avg_pixels_tab[1][0] = ff_avg_pixels8_armv6; +} diff --git a/ffmpeg/libavcodec/arm/hpeldsp_init_neon.c b/ffmpeg/libavcodec/arm/hpeldsp_init_neon.c new file mode 100644 index 0000000..d577735 --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_init_neon.c @@ -0,0 +1,86 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "hpeldsp_arm.h" + +void ff_put_pixels16_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_x2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_y2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_xy2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_x2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_y2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_xy2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_x2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_y2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels16_xy2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_x2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_y2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_put_pixels8_xy2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_avg_pixels16_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels16_x2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels16_y2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels16_xy2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels8_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels8_x2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels8_y2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels8_xy2_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels16_x2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels16_y2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); +void ff_avg_pixels16_xy2_no_rnd_neon(uint8_t *, const uint8_t *, ptrdiff_t, int); + +void ff_hpeldsp_init_neon(HpelDSPContext *c, int flags) +{ + c->put_pixels_tab[0][0] = ff_put_pixels16_neon; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_neon; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_neon; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_neon; + c->put_pixels_tab[1][0] = ff_put_pixels8_neon; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_neon; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_neon; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_neon; + + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_neon; + c->put_no_rnd_pixels_tab[0][1] = ff_put_pixels16_x2_no_rnd_neon; + c->put_no_rnd_pixels_tab[0][2] = ff_put_pixels16_y2_no_rnd_neon; + c->put_no_rnd_pixels_tab[0][3] = ff_put_pixels16_xy2_no_rnd_neon; + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_neon; + c->put_no_rnd_pixels_tab[1][1] = ff_put_pixels8_x2_no_rnd_neon; + c->put_no_rnd_pixels_tab[1][2] = ff_put_pixels8_y2_no_rnd_neon; + c->put_no_rnd_pixels_tab[1][3] = ff_put_pixels8_xy2_no_rnd_neon; + + c->avg_pixels_tab[0][0] = ff_avg_pixels16_neon; + c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_neon; + c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_neon; + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_neon; + c->avg_pixels_tab[1][0] = ff_avg_pixels8_neon; + c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_neon; + c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_neon; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_neon; + + c->avg_no_rnd_pixels_tab[0] = ff_avg_pixels16_neon; + c->avg_no_rnd_pixels_tab[1] = ff_avg_pixels16_x2_no_rnd_neon; + c->avg_no_rnd_pixels_tab[2] = ff_avg_pixels16_y2_no_rnd_neon; + c->avg_no_rnd_pixels_tab[3] = ff_avg_pixels16_xy2_no_rnd_neon; +} diff --git a/ffmpeg/libavcodec/arm/hpeldsp_neon.S b/ffmpeg/libavcodec/arm/hpeldsp_neon.S new file mode 100644 index 0000000..cf4a6cf --- /dev/null +++ b/ffmpeg/libavcodec/arm/hpeldsp_neon.S @@ -0,0 +1,410 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +.macro pixels16 rnd=1, avg=0 + .if \avg + mov r12, r0 + .endif +1: vld1.8 {q0}, [r1], r2 + vld1.8 {q1}, [r1], r2 + vld1.8 {q2}, [r1], r2 + pld [r1, r2, lsl #2] + vld1.8 {q3}, [r1], r2 + pld [r1] + pld [r1, r2] + pld [r1, r2, lsl #1] + .if \avg + vld1.8 {q8}, [r12,:128], r2 + vrhadd.u8 q0, q0, q8 + vld1.8 {q9}, [r12,:128], r2 + vrhadd.u8 q1, q1, q9 + vld1.8 {q10}, [r12,:128], r2 + vrhadd.u8 q2, q2, q10 + vld1.8 {q11}, [r12,:128], r2 + vrhadd.u8 q3, q3, q11 + .endif + subs r3, r3, #4 + vst1.64 {q0}, [r0,:128], r2 + vst1.64 {q1}, [r0,:128], r2 + vst1.64 {q2}, [r0,:128], r2 + vst1.64 {q3}, [r0,:128], r2 + bne 1b + bx lr +.endm + +.macro pixels16_x2 rnd=1, avg=0 +1: vld1.8 {d0-d2}, [r1], r2 + vld1.8 {d4-d6}, [r1], r2 + pld [r1] + pld [r1, r2] + subs r3, r3, #2 + vext.8 q1, q0, q1, #1 + avg q0, q0, q1 + vext.8 q3, q2, q3, #1 + avg q2, q2, q3 + .if \avg + vld1.8 {q1}, [r0,:128], r2 + vld1.8 {q3}, [r0,:128] + vrhadd.u8 q0, q0, q1 + vrhadd.u8 q2, q2, q3 + sub r0, r0, r2 + .endif + vst1.8 {q0}, [r0,:128], r2 + vst1.8 {q2}, [r0,:128], r2 + bne 1b + bx lr +.endm + +.macro pixels16_y2 rnd=1, avg=0 + sub r3, r3, #2 + vld1.8 {q0}, [r1], r2 + vld1.8 {q1}, [r1], r2 +1: subs r3, r3, #2 + avg q2, q0, q1 + vld1.8 {q0}, [r1], r2 + avg q3, q0, q1 + vld1.8 {q1}, [r1], r2 + pld [r1] + pld [r1, r2] + .if \avg + vld1.8 {q8}, [r0,:128], r2 + vld1.8 {q9}, [r0,:128] + vrhadd.u8 q2, q2, q8 + vrhadd.u8 q3, q3, q9 + sub r0, r0, r2 + .endif + vst1.8 {q2}, [r0,:128], r2 + vst1.8 {q3}, [r0,:128], r2 + bne 1b + + avg q2, q0, q1 + vld1.8 {q0}, [r1], r2 + avg q3, q0, q1 + .if \avg + vld1.8 {q8}, [r0,:128], r2 + vld1.8 {q9}, [r0,:128] + vrhadd.u8 q2, q2, q8 + vrhadd.u8 q3, q3, q9 + sub r0, r0, r2 + .endif + vst1.8 {q2}, [r0,:128], r2 + vst1.8 {q3}, [r0,:128], r2 + + bx lr +.endm + +.macro pixels16_xy2 rnd=1, avg=0 + sub r3, r3, #2 + vld1.8 {d0-d2}, [r1], r2 + vld1.8 {d4-d6}, [r1], r2 +NRND vmov.i16 q13, #1 + pld [r1] + pld [r1, r2] + vext.8 q1, q0, q1, #1 + vext.8 q3, q2, q3, #1 + vaddl.u8 q8, d0, d2 + vaddl.u8 q10, d1, d3 + vaddl.u8 q9, d4, d6 + vaddl.u8 q11, d5, d7 +1: subs r3, r3, #2 + vld1.8 {d0-d2}, [r1], r2 + vadd.u16 q12, q8, q9 + pld [r1] +NRND vadd.u16 q12, q12, q13 + vext.8 q15, q0, q1, #1 + vadd.u16 q1 , q10, q11 + shrn d28, q12, #2 +NRND vadd.u16 q1, q1, q13 + shrn d29, q1, #2 + .if \avg + vld1.8 {q8}, [r0,:128] + vrhadd.u8 q14, q14, q8 + .endif + vaddl.u8 q8, d0, d30 + vld1.8 {d2-d4}, [r1], r2 + vaddl.u8 q10, d1, d31 + vst1.8 {q14}, [r0,:128], r2 + vadd.u16 q12, q8, q9 + pld [r1, r2] +NRND vadd.u16 q12, q12, q13 + vext.8 q2, q1, q2, #1 + vadd.u16 q0, q10, q11 + shrn d30, q12, #2 +NRND vadd.u16 q0, q0, q13 + shrn d31, q0, #2 + .if \avg + vld1.8 {q9}, [r0,:128] + vrhadd.u8 q15, q15, q9 + .endif + vaddl.u8 q9, d2, d4 + vaddl.u8 q11, d3, d5 + vst1.8 {q15}, [r0,:128], r2 + bgt 1b + + vld1.8 {d0-d2}, [r1], r2 + vadd.u16 q12, q8, q9 +NRND vadd.u16 q12, q12, q13 + vext.8 q15, q0, q1, #1 + vadd.u16 q1 , q10, q11 + shrn d28, q12, #2 +NRND vadd.u16 q1, q1, q13 + shrn d29, q1, #2 + .if \avg + vld1.8 {q8}, [r0,:128] + vrhadd.u8 q14, q14, q8 + .endif + vaddl.u8 q8, d0, d30 + vaddl.u8 q10, d1, d31 + vst1.8 {q14}, [r0,:128], r2 + vadd.u16 q12, q8, q9 +NRND vadd.u16 q12, q12, q13 + vadd.u16 q0, q10, q11 + shrn d30, q12, #2 +NRND vadd.u16 q0, q0, q13 + shrn d31, q0, #2 + .if \avg + vld1.8 {q9}, [r0,:128] + vrhadd.u8 q15, q15, q9 + .endif + vst1.8 {q15}, [r0,:128], r2 + + bx lr +.endm + +.macro pixels8 rnd=1, avg=0 +1: vld1.8 {d0}, [r1], r2 + vld1.8 {d1}, [r1], r2 + vld1.8 {d2}, [r1], r2 + pld [r1, r2, lsl #2] + vld1.8 {d3}, [r1], r2 + pld [r1] + pld [r1, r2] + pld [r1, r2, lsl #1] + .if \avg + vld1.8 {d4}, [r0,:64], r2 + vrhadd.u8 d0, d0, d4 + vld1.8 {d5}, [r0,:64], r2 + vrhadd.u8 d1, d1, d5 + vld1.8 {d6}, [r0,:64], r2 + vrhadd.u8 d2, d2, d6 + vld1.8 {d7}, [r0,:64], r2 + vrhadd.u8 d3, d3, d7 + sub r0, r0, r2, lsl #2 + .endif + subs r3, r3, #4 + vst1.8 {d0}, [r0,:64], r2 + vst1.8 {d1}, [r0,:64], r2 + vst1.8 {d2}, [r0,:64], r2 + vst1.8 {d3}, [r0,:64], r2 + bne 1b + bx lr +.endm + +.macro pixels8_x2 rnd=1, avg=0 +1: vld1.8 {q0}, [r1], r2 + vext.8 d1, d0, d1, #1 + vld1.8 {q1}, [r1], r2 + vext.8 d3, d2, d3, #1 + pld [r1] + pld [r1, r2] + subs r3, r3, #2 + vswp d1, d2 + avg q0, q0, q1 + .if \avg + vld1.8 {d4}, [r0,:64], r2 + vld1.8 {d5}, [r0,:64] + vrhadd.u8 q0, q0, q2 + sub r0, r0, r2 + .endif + vst1.8 {d0}, [r0,:64], r2 + vst1.8 {d1}, [r0,:64], r2 + bne 1b + bx lr +.endm + +.macro pixels8_y2 rnd=1, avg=0 + sub r3, r3, #2 + vld1.8 {d0}, [r1], r2 + vld1.8 {d1}, [r1], r2 +1: subs r3, r3, #2 + avg d4, d0, d1 + vld1.8 {d0}, [r1], r2 + avg d5, d0, d1 + vld1.8 {d1}, [r1], r2 + pld [r1] + pld [r1, r2] + .if \avg + vld1.8 {d2}, [r0,:64], r2 + vld1.8 {d3}, [r0,:64] + vrhadd.u8 q2, q2, q1 + sub r0, r0, r2 + .endif + vst1.8 {d4}, [r0,:64], r2 + vst1.8 {d5}, [r0,:64], r2 + bne 1b + + avg d4, d0, d1 + vld1.8 {d0}, [r1], r2 + avg d5, d0, d1 + .if \avg + vld1.8 {d2}, [r0,:64], r2 + vld1.8 {d3}, [r0,:64] + vrhadd.u8 q2, q2, q1 + sub r0, r0, r2 + .endif + vst1.8 {d4}, [r0,:64], r2 + vst1.8 {d5}, [r0,:64], r2 + + bx lr +.endm + +.macro pixels8_xy2 rnd=1, avg=0 + sub r3, r3, #2 + vld1.8 {q0}, [r1], r2 + vld1.8 {q1}, [r1], r2 +NRND vmov.i16 q11, #1 + pld [r1] + pld [r1, r2] + vext.8 d4, d0, d1, #1 + vext.8 d6, d2, d3, #1 + vaddl.u8 q8, d0, d4 + vaddl.u8 q9, d2, d6 +1: subs r3, r3, #2 + vld1.8 {q0}, [r1], r2 + pld [r1] + vadd.u16 q10, q8, q9 + vext.8 d4, d0, d1, #1 +NRND vadd.u16 q10, q10, q11 + vaddl.u8 q8, d0, d4 + shrn d5, q10, #2 + vld1.8 {q1}, [r1], r2 + vadd.u16 q10, q8, q9 + pld [r1, r2] + .if \avg + vld1.8 {d7}, [r0,:64] + vrhadd.u8 d5, d5, d7 + .endif +NRND vadd.u16 q10, q10, q11 + vst1.8 {d5}, [r0,:64], r2 + shrn d7, q10, #2 + .if \avg + vld1.8 {d5}, [r0,:64] + vrhadd.u8 d7, d7, d5 + .endif + vext.8 d6, d2, d3, #1 + vaddl.u8 q9, d2, d6 + vst1.8 {d7}, [r0,:64], r2 + bgt 1b + + vld1.8 {q0}, [r1], r2 + vadd.u16 q10, q8, q9 + vext.8 d4, d0, d1, #1 +NRND vadd.u16 q10, q10, q11 + vaddl.u8 q8, d0, d4 + shrn d5, q10, #2 + vadd.u16 q10, q8, q9 + .if \avg + vld1.8 {d7}, [r0,:64] + vrhadd.u8 d5, d5, d7 + .endif +NRND vadd.u16 q10, q10, q11 + vst1.8 {d5}, [r0,:64], r2 + shrn d7, q10, #2 + .if \avg + vld1.8 {d5}, [r0,:64] + vrhadd.u8 d7, d7, d5 + .endif + vst1.8 {d7}, [r0,:64], r2 + + bx lr +.endm + +.macro pixfunc pfx, name, suf, rnd=1, avg=0 + .if \rnd + .macro avg rd, rn, rm + vrhadd.u8 \rd, \rn, \rm + .endm + .macro shrn rd, rn, rm + vrshrn.u16 \rd, \rn, \rm + .endm + .macro NRND insn:vararg + .endm + .else + .macro avg rd, rn, rm + vhadd.u8 \rd, \rn, \rm + .endm + .macro shrn rd, rn, rm + vshrn.u16 \rd, \rn, \rm + .endm + .macro NRND insn:vararg + \insn + .endm + .endif +function ff_\pfx\name\suf\()_neon, export=1 + \name \rnd, \avg +endfunc + .purgem avg + .purgem shrn + .purgem NRND +.endm + +.macro pixfunc2 pfx, name, avg=0 + pixfunc \pfx, \name, rnd=1, avg=\avg + pixfunc \pfx, \name, _no_rnd, rnd=0, avg=\avg +.endm + +function ff_put_h264_qpel16_mc00_neon, export=1 + mov r3, #16 +endfunc + + pixfunc put_, pixels16, avg=0 + pixfunc2 put_, pixels16_x2, avg=0 + pixfunc2 put_, pixels16_y2, avg=0 + pixfunc2 put_, pixels16_xy2, avg=0 + +function ff_avg_h264_qpel16_mc00_neon, export=1 + mov r3, #16 +endfunc + + pixfunc avg_, pixels16, avg=1 + pixfunc2 avg_, pixels16_x2, avg=1 + pixfunc2 avg_, pixels16_y2, avg=1 + pixfunc2 avg_, pixels16_xy2, avg=1 + +function ff_put_h264_qpel8_mc00_neon, export=1 + mov r3, #8 +endfunc + + pixfunc put_, pixels8, avg=0 + pixfunc2 put_, pixels8_x2, avg=0 + pixfunc2 put_, pixels8_y2, avg=0 + pixfunc2 put_, pixels8_xy2, avg=0 + +function ff_avg_h264_qpel8_mc00_neon, export=1 + mov r3, #8 +endfunc + + pixfunc avg_, pixels8, avg=1 + pixfunc avg_, pixels8_x2, avg=1 + pixfunc avg_, pixels8_y2, avg=1 + pixfunc avg_, pixels8_xy2, avg=1 diff --git a/ffmpeg/libavcodec/arm/int_neon.S b/ffmpeg/libavcodec/arm/int_neon.S new file mode 100644 index 0000000..6b28a97 --- /dev/null +++ b/ffmpeg/libavcodec/arm/int_neon.S @@ -0,0 +1,92 @@ +/* + * ARM NEON optimised integer operations + * Copyright (c) 2009 Kostya Shishkov + * + * 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 "libavutil/arm/asm.S" + + .fpu neon + +function ff_scalarproduct_int16_neon, export=1 + vmov.i16 q0, #0 + vmov.i16 q1, #0 + vmov.i16 q2, #0 + vmov.i16 q3, #0 +1: vld1.16 {d16-d17}, [r0]! + vld1.16 {d20-d21}, [r1,:128]! + vmlal.s16 q0, d16, d20 + vld1.16 {d18-d19}, [r0]! + vmlal.s16 q1, d17, d21 + vld1.16 {d22-d23}, [r1,:128]! + vmlal.s16 q2, d18, d22 + vmlal.s16 q3, d19, d23 + subs r2, r2, #16 + bne 1b + + vpadd.s32 d16, d0, d1 + vpadd.s32 d17, d2, d3 + vpadd.s32 d10, d4, d5 + vpadd.s32 d11, d6, d7 + vpadd.s32 d0, d16, d17 + vpadd.s32 d1, d10, d11 + vpadd.s32 d2, d0, d1 + vpaddl.s32 d3, d2 + vmov.32 r0, d3[0] + bx lr +endfunc + +@ scalarproduct_and_madd_int16(/*aligned*/v0,v1,v2,order,mul) +function ff_scalarproduct_and_madd_int16_neon, export=1 + vld1.16 {d28[],d29[]}, [sp] + vmov.i16 q0, #0 + vmov.i16 q1, #0 + vmov.i16 q2, #0 + vmov.i16 q3, #0 + mov r12, r0 + +1: vld1.16 {d16-d17}, [r0,:128]! + vld1.16 {d18-d19}, [r1]! + vld1.16 {d20-d21}, [r2]! + vld1.16 {d22-d23}, [r0,:128]! + vld1.16 {d24-d25}, [r1]! + vld1.16 {d26-d27}, [r2]! + vmul.s16 q10, q10, q14 + vmul.s16 q13, q13, q14 + vmlal.s16 q0, d16, d18 + vmlal.s16 q1, d17, d19 + vadd.s16 q10, q8, q10 + vadd.s16 q13, q11, q13 + vmlal.s16 q2, d22, d24 + vmlal.s16 q3, d23, d25 + vst1.16 {q10}, [r12,:128]! + subs r3, r3, #16 + vst1.16 {q13}, [r12,:128]! + bne 1b + + vpadd.s32 d16, d0, d1 + vpadd.s32 d17, d2, d3 + vpadd.s32 d10, d4, d5 + vpadd.s32 d11, d6, d7 + vpadd.s32 d0, d16, d17 + vpadd.s32 d1, d10, d11 + vpadd.s32 d2, d0, d1 + vpaddl.s32 d3, d2 + vmov.32 r0, d3[0] + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/jrevdct_arm.S b/ffmpeg/libavcodec/arm/jrevdct_arm.S new file mode 100644 index 0000000..f951e2a --- /dev/null +++ b/ffmpeg/libavcodec/arm/jrevdct_arm.S @@ -0,0 +1,383 @@ +/* + C-like prototype : + void j_rev_dct_arm(DCTBLOCK data) + + With DCTBLOCK being a pointer to an array of 64 'signed shorts' + + Copyright (c) 2001 Lionel Ulmer (lionel.ulmer@free.fr / bbrox@bbrox.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include "libavutil/arm/asm.S" + +#define FIX_0_298631336 2446 +#define FIX_0_541196100 4433 +#define FIX_0_765366865 6270 +#define FIX_1_175875602 9633 +#define FIX_1_501321110 12299 +#define FIX_2_053119869 16819 +#define FIX_3_072711026 25172 +#define FIX_M_0_390180644 -3196 +#define FIX_M_0_899976223 -7373 +#define FIX_M_1_847759065 -15137 +#define FIX_M_1_961570560 -16069 +#define FIX_M_2_562915447 -20995 +#define FIX_0xFFFF 0xFFFF + +#define FIX_0_298631336_ID 0 +#define FIX_0_541196100_ID 4 +#define FIX_0_765366865_ID 8 +#define FIX_1_175875602_ID 12 +#define FIX_1_501321110_ID 16 +#define FIX_2_053119869_ID 20 +#define FIX_3_072711026_ID 24 +#define FIX_M_0_390180644_ID 28 +#define FIX_M_0_899976223_ID 32 +#define FIX_M_1_847759065_ID 36 +#define FIX_M_1_961570560_ID 40 +#define FIX_M_2_562915447_ID 44 +#define FIX_0xFFFF_ID 48 + +function ff_j_rev_dct_arm, export=1 + push {r0, r4 - r11, lr} + + mov lr, r0 @ lr = pointer to the current row + mov r12, #8 @ r12 = row-counter + movrel r11, const_array @ r11 = base pointer to the constants array +row_loop: + ldrsh r0, [lr, # 0] @ r0 = 'd0' + ldrsh r2, [lr, # 2] @ r2 = 'd2' + + @ Optimization for row that have all items except the first set to 0 + @ (this works as the int16_t are always 4-byte aligned) + ldr r5, [lr, # 0] + ldr r6, [lr, # 4] + ldr r3, [lr, # 8] + ldr r4, [lr, #12] + orr r3, r3, r4 + orr r3, r3, r6 + orrs r5, r3, r5 + beq end_of_row_loop @ nothing to be done as ALL of them are '0' + orrs r3, r3, r2 + beq empty_row + + ldrsh r1, [lr, # 8] @ r1 = 'd1' + ldrsh r4, [lr, # 4] @ r4 = 'd4' + ldrsh r6, [lr, # 6] @ r6 = 'd6' + + ldr r3, [r11, #FIX_0_541196100_ID] + add r7, r2, r6 + ldr r5, [r11, #FIX_M_1_847759065_ID] + mul r7, r3, r7 @ r7 = z1 + ldr r3, [r11, #FIX_0_765366865_ID] + mla r6, r5, r6, r7 @ r6 = tmp2 + add r5, r0, r4 @ r5 = tmp0 + mla r2, r3, r2, r7 @ r2 = tmp3 + sub r3, r0, r4 @ r3 = tmp1 + + add r0, r2, r5, lsl #13 @ r0 = tmp10 + rsb r2, r2, r5, lsl #13 @ r2 = tmp13 + add r4, r6, r3, lsl #13 @ r4 = tmp11 + rsb r3, r6, r3, lsl #13 @ r3 = tmp12 + + push {r0, r2, r3, r4} @ save on the stack tmp10, tmp13, tmp12, tmp11 + + ldrsh r3, [lr, #10] @ r3 = 'd3' + ldrsh r5, [lr, #12] @ r5 = 'd5' + ldrsh r7, [lr, #14] @ r7 = 'd7' + + add r0, r3, r5 @ r0 = 'z2' + add r2, r1, r7 @ r2 = 'z1' + add r4, r3, r7 @ r4 = 'z3' + add r6, r1, r5 @ r6 = 'z4' + ldr r9, [r11, #FIX_1_175875602_ID] + add r8, r4, r6 @ r8 = z3 + z4 + ldr r10, [r11, #FIX_M_0_899976223_ID] + mul r8, r9, r8 @ r8 = 'z5' + ldr r9, [r11, #FIX_M_2_562915447_ID] + mul r2, r10, r2 @ r2 = 'z1' + ldr r10, [r11, #FIX_M_1_961570560_ID] + mul r0, r9, r0 @ r0 = 'z2' + ldr r9, [r11, #FIX_M_0_390180644_ID] + mla r4, r10, r4, r8 @ r4 = 'z3' + ldr r10, [r11, #FIX_0_298631336_ID] + mla r6, r9, r6, r8 @ r6 = 'z4' + ldr r9, [r11, #FIX_2_053119869_ID] + mla r7, r10, r7, r2 @ r7 = tmp0 + z1 + ldr r10, [r11, #FIX_3_072711026_ID] + mla r5, r9, r5, r0 @ r5 = tmp1 + z2 + ldr r9, [r11, #FIX_1_501321110_ID] + mla r3, r10, r3, r0 @ r3 = tmp2 + z2 + add r7, r7, r4 @ r7 = tmp0 + mla r1, r9, r1, r2 @ r1 = tmp3 + z1 + add r5, r5, r6 @ r5 = tmp1 + add r3, r3, r4 @ r3 = tmp2 + add r1, r1, r6 @ r1 = tmp3 + + pop {r0, r2, r4, r6} @ r0 = tmp10 / r2 = tmp13 / r4 = tmp12 / r6 = tmp11 + @ r1 = tmp3 / r3 = tmp2 / r5 = tmp1 / r7 = tmp0 + + @ Compute DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS) + add r8, r0, r1 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, # 0] + + @ Compute DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS) + sub r8, r0, r1 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, #14] + + @ Compute DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS) + add r8, r6, r3 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, # 2] + + @ Compute DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS) + sub r8, r6, r3 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, #12] + + @ Compute DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS) + add r8, r4, r5 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, # 4] + + @ Compute DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS) + sub r8, r4, r5 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, #10] + + @ Compute DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS) + add r8, r2, r7 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, # 6] + + @ Compute DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS) + sub r8, r2, r7 + add r8, r8, #(1<<10) + mov r8, r8, asr #11 + strh r8, [lr, # 8] + + @ End of row loop + add lr, lr, #16 + subs r12, r12, #1 + bne row_loop + beq start_column_loop + +empty_row: + ldr r1, [r11, #FIX_0xFFFF_ID] + mov r0, r0, lsl #2 + and r0, r0, r1 + add r0, r0, r0, lsl #16 + str r0, [lr, # 0] + str r0, [lr, # 4] + str r0, [lr, # 8] + str r0, [lr, #12] + +end_of_row_loop: + @ End of loop + add lr, lr, #16 + subs r12, r12, #1 + bne row_loop + +start_column_loop: + @ Start of column loop + pop {lr} + mov r12, #8 +column_loop: + ldrsh r0, [lr, #( 0*8)] @ r0 = 'd0' + ldrsh r2, [lr, #( 4*8)] @ r2 = 'd2' + ldrsh r4, [lr, #( 8*8)] @ r4 = 'd4' + ldrsh r6, [lr, #(12*8)] @ r6 = 'd6' + + ldr r3, [r11, #FIX_0_541196100_ID] + add r1, r2, r6 + ldr r5, [r11, #FIX_M_1_847759065_ID] + mul r1, r3, r1 @ r1 = z1 + ldr r3, [r11, #FIX_0_765366865_ID] + mla r6, r5, r6, r1 @ r6 = tmp2 + add r5, r0, r4 @ r5 = tmp0 + mla r2, r3, r2, r1 @ r2 = tmp3 + sub r3, r0, r4 @ r3 = tmp1 + + add r0, r2, r5, lsl #13 @ r0 = tmp10 + rsb r2, r2, r5, lsl #13 @ r2 = tmp13 + add r4, r6, r3, lsl #13 @ r4 = tmp11 + rsb r6, r6, r3, lsl #13 @ r6 = tmp12 + + ldrsh r1, [lr, #( 2*8)] @ r1 = 'd1' + ldrsh r3, [lr, #( 6*8)] @ r3 = 'd3' + ldrsh r5, [lr, #(10*8)] @ r5 = 'd5' + ldrsh r7, [lr, #(14*8)] @ r7 = 'd7' + + @ Check for empty odd column (happens about 20 to 25 % of the time according to my stats) + orr r9, r1, r3 + orr r10, r5, r7 + orrs r10, r9, r10 + beq empty_odd_column + + push {r0, r2, r4, r6} @ save on the stack tmp10, tmp13, tmp12, tmp11 + + add r0, r3, r5 @ r0 = 'z2' + add r2, r1, r7 @ r2 = 'z1' + add r4, r3, r7 @ r4 = 'z3' + add r6, r1, r5 @ r6 = 'z4' + ldr r9, [r11, #FIX_1_175875602_ID] + add r8, r4, r6 + ldr r10, [r11, #FIX_M_0_899976223_ID] + mul r8, r9, r8 @ r8 = 'z5' + ldr r9, [r11, #FIX_M_2_562915447_ID] + mul r2, r10, r2 @ r2 = 'z1' + ldr r10, [r11, #FIX_M_1_961570560_ID] + mul r0, r9, r0 @ r0 = 'z2' + ldr r9, [r11, #FIX_M_0_390180644_ID] + mla r4, r10, r4, r8 @ r4 = 'z3' + ldr r10, [r11, #FIX_0_298631336_ID] + mla r6, r9, r6, r8 @ r6 = 'z4' + ldr r9, [r11, #FIX_2_053119869_ID] + mla r7, r10, r7, r2 @ r7 = tmp0 + z1 + ldr r10, [r11, #FIX_3_072711026_ID] + mla r5, r9, r5, r0 @ r5 = tmp1 + z2 + ldr r9, [r11, #FIX_1_501321110_ID] + mla r3, r10, r3, r0 @ r3 = tmp2 + z2 + add r7, r7, r4 @ r7 = tmp0 + mla r1, r9, r1, r2 @ r1 = tmp3 + z1 + add r5, r5, r6 @ r5 = tmp1 + add r3, r3, r4 @ r3 = tmp2 + add r1, r1, r6 @ r1 = tmp3 + + pop {r0, r2, r4, r6} @ r0 = tmp10 / r2 = tmp13 / r4 = tmp11 / r6 = tmp12 + @ r1 = tmp3 / r3 = tmp2 / r5 = tmp1 / r7 = tmp0 + + @ Compute DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) + add r8, r0, r1 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #( 0*8)] + + @ Compute DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) + sub r8, r0, r1 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #(14*8)] + + @ Compute DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) + add r8, r4, r3 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #( 2*8)] + + @ Compute DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) + sub r8, r4, r3 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #(12*8)] + + @ Compute DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) + add r8, r6, r5 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #( 4*8)] + + @ Compute DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) + sub r8, r6, r5 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #(10*8)] + + @ Compute DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) + add r8, r2, r7 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #( 6*8)] + + @ Compute DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) + sub r8, r2, r7 + add r8, r8, #(1<<17) + mov r8, r8, asr #18 + strh r8, [lr, #( 8*8)] + + @ End of row loop + add lr, lr, #2 + subs r12, r12, #1 + bne column_loop + beq the_end + +empty_odd_column: + @ Compute DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) + @ Compute DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) + add r0, r0, #(1<<17) + mov r0, r0, asr #18 + strh r0, [lr, #( 0*8)] + strh r0, [lr, #(14*8)] + + @ Compute DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) + @ Compute DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) + add r4, r4, #(1<<17) + mov r4, r4, asr #18 + strh r4, [lr, #( 2*8)] + strh r4, [lr, #(12*8)] + + @ Compute DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) + @ Compute DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) + add r6, r6, #(1<<17) + mov r6, r6, asr #18 + strh r6, [lr, #( 4*8)] + strh r6, [lr, #(10*8)] + + @ Compute DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) + @ Compute DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) + add r2, r2, #(1<<17) + mov r2, r2, asr #18 + strh r2, [lr, #( 6*8)] + strh r2, [lr, #( 8*8)] + + @ End of row loop + add lr, lr, #2 + subs r12, r12, #1 + bne column_loop + +the_end: + @ The end.... + pop {r4 - r11, pc} +endfunc + +const const_array + .word FIX_0_298631336 + .word FIX_0_541196100 + .word FIX_0_765366865 + .word FIX_1_175875602 + .word FIX_1_501321110 + .word FIX_2_053119869 + .word FIX_3_072711026 + .word FIX_M_0_390180644 + .word FIX_M_0_899976223 + .word FIX_M_1_847759065 + .word FIX_M_1_961570560 + .word FIX_M_2_562915447 + .word FIX_0xFFFF +endconst diff --git a/ffmpeg/libavcodec/arm/mathops.h b/ffmpeg/libavcodec/arm/mathops.h new file mode 100644 index 0000000..dc57c55 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mathops.h @@ -0,0 +1,108 @@ +/* + * simple math operations + * Copyright (c) 2006 Michael Niedermayer et al + * + * 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 + */ + +#ifndef AVCODEC_ARM_MATHOPS_H +#define AVCODEC_ARM_MATHOPS_H + +#include +#include "config.h" +#include "libavutil/common.h" + +#if HAVE_INLINE_ASM + +#if HAVE_ARMV6_INLINE +#define MULH MULH +static inline av_const int MULH(int a, int b) +{ + int r; + __asm__ ("smmul %0, %1, %2" : "=r"(r) : "r"(a), "r"(b)); + return r; +} + +#define FASTDIV FASTDIV +static av_always_inline av_const int FASTDIV(int a, int b) +{ + int r; + __asm__ ("cmp %2, #2 \n\t" + "ldr %0, [%3, %2, lsl #2] \n\t" + "ite le \n\t" + "lsrle %0, %1, #1 \n\t" + "smmulgt %0, %0, %1 \n\t" + : "=&r"(r) : "r"(a), "r"(b), "r"(ff_inverse) : "cc"); + return r; +} + +#else /* HAVE_ARMV6_INLINE */ + +#define FASTDIV FASTDIV +static av_always_inline av_const int FASTDIV(int a, int b) +{ + int r, t; + __asm__ ("umull %1, %0, %2, %3" + : "=&r"(r), "=&r"(t) : "r"(a), "r"(ff_inverse[b])); + return r; +} +#endif + +#define MLS64(d, a, b) MAC64(d, -(a), b) + +#if HAVE_ARMV5TE_INLINE + +/* signed 16x16 -> 32 multiply add accumulate */ +# define MAC16(rt, ra, rb) \ + __asm__ ("smlabb %0, %1, %2, %0" : "+r"(rt) : "r"(ra), "r"(rb)); + +/* signed 16x16 -> 32 multiply */ +# define MUL16 MUL16 +static inline av_const int MUL16(int ra, int rb) +{ + int rt; + __asm__ ("smulbb %0, %1, %2" : "=r"(rt) : "r"(ra), "r"(rb)); + return rt; +} + +#endif + +#define mid_pred mid_pred +static inline av_const int mid_pred(int a, int b, int c) +{ + int m; + __asm__ ( + "mov %0, %2 \n\t" + "cmp %1, %2 \n\t" + "itt gt \n\t" + "movgt %0, %1 \n\t" + "movgt %1, %2 \n\t" + "cmp %1, %3 \n\t" + "it le \n\t" + "movle %1, %3 \n\t" + "cmp %0, %1 \n\t" + "it gt \n\t" + "movgt %0, %1 \n\t" + : "=&r"(m), "+r"(a) + : "r"(b), "r"(c) + : "cc"); + return m; +} + +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_ARM_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/arm/mdct_fixed_neon.S b/ffmpeg/libavcodec/arm/mdct_fixed_neon.S new file mode 100644 index 0000000..c77be59 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mdct_fixed_neon.S @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +.macro prerot dst, rt + lsr r3, r6, #2 @ n4 + add \rt, r4, r6, lsr #1 @ revtab + n4 + add r9, r3, r3, lsl #1 @ n3 + add r8, r7, r6 @ tcos + n4 + add r3, r2, r6, lsr #1 @ in + n4 + add r9, r2, r9, lsl #1 @ in + n3 + sub r8, r8, #16 + sub r10, r3, #16 + sub r11, r9, #16 + mov r12, #-16 +1: + vld2.16 {d0,d1}, [r9, :128]! + vld2.16 {d2,d3}, [r11,:128], r12 + vld2.16 {d4,d5}, [r3, :128]! + vld2.16 {d6,d7}, [r10,:128], r12 + vld2.16 {d16,d17},[r7, :128]! @ cos, sin + vld2.16 {d18,d19},[r8, :128], r12 + vrev64.16 q1, q1 + vrev64.16 q3, q3 + vrev64.16 q9, q9 + vneg.s16 d0, d0 + vneg.s16 d2, d2 + vneg.s16 d16, d16 + vneg.s16 d18, d18 + vhsub.s16 d0, d0, d3 @ re + vhsub.s16 d4, d7, d4 @ im + vhsub.s16 d6, d6, d5 + vhsub.s16 d2, d2, d1 + vmull.s16 q10, d0, d16 + vmlsl.s16 q10, d4, d17 + vmull.s16 q11, d0, d17 + vmlal.s16 q11, d4, d16 + vmull.s16 q12, d6, d18 + vmlsl.s16 q12, d2, d19 + vmull.s16 q13, d6, d19 + vmlal.s16 q13, d2, d18 + vshrn.s32 d0, q10, #15 + vshrn.s32 d1, q11, #15 + vshrn.s32 d2, q12, #15 + vshrn.s32 d3, q13, #15 + vzip.16 d0, d1 + vzip.16 d2, d3 + ldrh lr, [r4], #2 + ldrh r2, [\rt, #-2]! + add lr, \dst, lr, lsl #2 + add r2, \dst, r2, lsl #2 + vst1.32 {d0[0]}, [lr,:32] + vst1.32 {d2[0]}, [r2,:32] + ldrh lr, [r4], #2 + ldrh r2, [\rt, #-2]! + add lr, \dst, lr, lsl #2 + add r2, \dst, r2, lsl #2 + vst1.32 {d0[1]}, [lr,:32] + vst1.32 {d2[1]}, [r2,:32] + ldrh lr, [r4], #2 + ldrh r2, [\rt, #-2]! + add lr, \dst, lr, lsl #2 + add r2, \dst, r2, lsl #2 + vst1.32 {d1[0]}, [lr,:32] + vst1.32 {d3[0]}, [r2,:32] + ldrh lr, [r4], #2 + ldrh r2, [\rt, #-2]! + add lr, \dst, lr, lsl #2 + add r2, \dst, r2, lsl #2 + vst1.32 {d1[1]}, [lr,:32] + vst1.32 {d3[1]}, [r2,:32] + subs r6, r6, #32 + bgt 1b +.endm + +function ff_mdct_fixed_calc_neon, export=1 + push {r1,r4-r11,lr} + + ldr r4, [r0, #8] @ revtab + ldr r6, [r0, #16] @ mdct_size; n + ldr r7, [r0, #24] @ tcos + + prerot r1, r5 + + mov r4, r0 + bl X(ff_fft_fixed_calc_neon) + + pop {r5} + mov r12, #-16 + ldr r6, [r4, #16] @ mdct_size; n + ldr r7, [r4, #24] @ tcos + add r5, r5, r6, lsr #1 + add r7, r7, r6, lsr #1 + sub r1, r5, #16 + sub r2, r7, #16 +1: + vld2.16 {d4,d5}, [r7,:128]! + vld2.16 {d6,d7}, [r2,:128], r12 + vld2.16 {d0,d1}, [r5,:128] + vld2.16 {d2,d3}, [r1,:128] + vrev64.16 q3, q3 + vrev64.16 q1, q1 + vneg.s16 q3, q3 + vneg.s16 q2, q2 + vmull.s16 q11, d2, d6 + vmlal.s16 q11, d3, d7 + vmull.s16 q8, d0, d5 + vmlsl.s16 q8, d1, d4 + vmull.s16 q9, d0, d4 + vmlal.s16 q9, d1, d5 + vmull.s16 q10, d2, d7 + vmlsl.s16 q10, d3, d6 + vshrn.s32 d0, q11, #15 + vshrn.s32 d1, q8, #15 + vshrn.s32 d2, q9, #15 + vshrn.s32 d3, q10, #15 + vrev64.16 q0, q0 + vst2.16 {d2,d3}, [r5,:128]! + vst2.16 {d0,d1}, [r1,:128], r12 + subs r6, r6, #32 + bgt 1b + + pop {r4-r11,pc} +endfunc + +function ff_mdct_fixed_calcw_neon, export=1 + push {r1,r4-r11,lr} + + ldrd r4, r5, [r0, #8] @ revtab, tmp_buf + ldr r6, [r0, #16] @ mdct_size; n + ldr r7, [r0, #24] @ tcos + + prerot r5, r1 + + mov r4, r0 + mov r1, r5 + bl X(ff_fft_fixed_calc_neon) + + pop {r7} + mov r12, #-16 + ldr r6, [r4, #16] @ mdct_size; n + ldr r9, [r4, #24] @ tcos + add r5, r5, r6, lsr #1 + add r7, r7, r6 + add r9, r9, r6, lsr #1 + sub r3, r5, #16 + sub r1, r7, #16 + sub r2, r9, #16 +1: + vld2.16 {d4,d5}, [r9,:128]! + vld2.16 {d6,d7}, [r2,:128], r12 + vld2.16 {d0,d1}, [r5,:128]! + vld2.16 {d2,d3}, [r3,:128], r12 + vrev64.16 q3, q3 + vrev64.16 q1, q1 + vneg.s16 q3, q3 + vneg.s16 q2, q2 + vmull.s16 q8, d2, d6 + vmlal.s16 q8, d3, d7 + vmull.s16 q9, d0, d5 + vmlsl.s16 q9, d1, d4 + vmull.s16 q10, d0, d4 + vmlal.s16 q10, d1, d5 + vmull.s16 q11, d2, d7 + vmlsl.s16 q11, d3, d6 + vrev64.32 q8, q8 + vrev64.32 q9, q9 + vst2.32 {q10,q11},[r7,:128]! + vst2.32 {d16,d18},[r1,:128], r12 + vst2.32 {d17,d19},[r1,:128], r12 + subs r6, r6, #32 + bgt 1b + + pop {r4-r11,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/mdct_neon.S b/ffmpeg/libavcodec/arm/mdct_neon.S new file mode 100644 index 0000000..e481cd1 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mdct_neon.S @@ -0,0 +1,301 @@ +/* + * ARM NEON optimised MDCT + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +#define ff_fft_calc_neon X(ff_fft_calc_neon) + +function ff_imdct_half_neon, export=1 + push {r4-r8,lr} + + mov r12, #1 + ldr lr, [r0, #20] @ mdct_bits + ldr r4, [r0, #24] @ tcos + ldr r3, [r0, #8] @ revtab + lsl r12, r12, lr @ n = 1 << nbits + lsr lr, r12, #2 @ n4 = n >> 2 + add r7, r2, r12, lsl #1 + mov r12, #-16 + sub r7, r7, #16 + + vld2.32 {d16-d17},[r7,:128],r12 @ d16=x,n1 d17=x,n0 + vld2.32 {d0-d1}, [r2,:128]! @ d0 =m0,x d1 =m1,x + vrev64.32 d17, d17 + vld2.32 {d2,d3}, [r4,:128]! @ d2=c0,c1 d3=s0,s2 + vmul.f32 d6, d17, d2 + vmul.f32 d7, d0, d2 +1: + subs lr, lr, #2 + ldr r6, [r3], #4 + vmul.f32 d4, d0, d3 + vmul.f32 d5, d17, d3 + vsub.f32 d4, d6, d4 + vadd.f32 d5, d5, d7 + uxth r8, r6, ror #16 + uxth r6, r6 + add r8, r1, r8, lsl #3 + add r6, r1, r6, lsl #3 + beq 1f + vld2.32 {d16-d17},[r7,:128],r12 + vld2.32 {d0-d1}, [r2,:128]! + vrev64.32 d17, d17 + vld2.32 {d2,d3}, [r4,:128]! @ d2=c0,c1 d3=s0,s2 + vmul.f32 d6, d17, d2 + vmul.f32 d7, d0, d2 + vst2.32 {d4[0],d5[0]}, [r6,:64] + vst2.32 {d4[1],d5[1]}, [r8,:64] + b 1b +1: + vst2.32 {d4[0],d5[0]}, [r6,:64] + vst2.32 {d4[1],d5[1]}, [r8,:64] + + mov r4, r0 + mov r6, r1 + bl ff_fft_calc_neon + + mov r12, #1 + ldr lr, [r4, #20] @ mdct_bits + ldr r4, [r4, #24] @ tcos + lsl r12, r12, lr @ n = 1 << nbits + lsr lr, r12, #3 @ n8 = n >> 3 + + add r4, r4, lr, lsl #3 + add r6, r6, lr, lsl #3 + sub r1, r4, #16 + sub r3, r6, #16 + + mov r7, #-16 + mov r8, r6 + mov r0, r3 + + vld2.32 {d0-d1}, [r3,:128], r7 @ d0 =i1,r1 d1 =i0,r0 + vld2.32 {d20-d21},[r6,:128]! @ d20=i2,r2 d21=i3,r3 + vld2.32 {d16,d18},[r1,:128], r7 @ d16=c1,c0 d18=s1,s0 +1: + subs lr, lr, #2 + vmul.f32 d7, d0, d18 + vld2.32 {d17,d19},[r4,:128]! @ d17=c2,c3 d19=s2,s3 + vmul.f32 d4, d1, d18 + vmul.f32 d5, d21, d19 + vmul.f32 d6, d20, d19 + vmul.f32 d22, d1, d16 + vmul.f32 d23, d21, d17 + vmul.f32 d24, d0, d16 + vmul.f32 d25, d20, d17 + vadd.f32 d7, d7, d22 + vadd.f32 d6, d6, d23 + vsub.f32 d4, d4, d24 + vsub.f32 d5, d5, d25 + beq 1f + vld2.32 {d0-d1}, [r3,:128], r7 + vld2.32 {d20-d21},[r6,:128]! + vld2.32 {d16,d18},[r1,:128], r7 @ d16=c1,c0 d18=s1,s0 + vrev64.32 q3, q3 + vst2.32 {d4,d6}, [r0,:128], r7 + vst2.32 {d5,d7}, [r8,:128]! + b 1b +1: + vrev64.32 q3, q3 + vst2.32 {d4,d6}, [r0,:128] + vst2.32 {d5,d7}, [r8,:128] + + pop {r4-r8,pc} +endfunc + +function ff_imdct_calc_neon, export=1 + push {r4-r6,lr} + + ldr r3, [r0, #20] + mov r4, #1 + mov r5, r1 + lsl r4, r4, r3 + add r1, r1, r4 + + bl ff_imdct_half_neon + + add r0, r5, r4, lsl #2 + add r1, r5, r4, lsl #1 + sub r0, r0, #8 + sub r2, r1, #16 + mov r3, #-16 + mov r6, #-8 + vmov.i32 d30, #1<<31 +1: + vld1.32 {d0-d1}, [r2,:128], r3 + pld [r0, #-16] + vrev64.32 q0, q0 + vld1.32 {d2-d3}, [r1,:128]! + veor d4, d1, d30 + pld [r2, #-16] + vrev64.32 q1, q1 + veor d5, d0, d30 + vst1.32 {d2}, [r0,:64], r6 + vst1.32 {d3}, [r0,:64], r6 + vst1.32 {d4-d5}, [r5,:128]! + subs r4, r4, #16 + bgt 1b + + pop {r4-r6,pc} +endfunc + +function ff_mdct_calc_neon, export=1 + push {r4-r10,lr} + + mov r12, #1 + ldr lr, [r0, #20] @ mdct_bits + ldr r4, [r0, #24] @ tcos + ldr r3, [r0, #8] @ revtab + lsl lr, r12, lr @ n = 1 << nbits + add r7, r2, lr @ in4u + sub r9, r7, #16 @ in4d + add r2, r7, lr, lsl #1 @ in3u + add r8, r9, lr, lsl #1 @ in3d + add r5, r4, lr, lsl #1 + sub r5, r5, #16 + sub r3, r3, #4 + mov r12, #-16 + + vld2.32 {d16,d18},[r9,:128],r12 @ in0u0,in0u1 in4d1,in4d0 + vld2.32 {d17,d19},[r8,:128],r12 @ in2u0,in2u1 in3d1,in3d0 + vld2.32 {d0, d2}, [r7,:128]! @ in4u0,in4u1 in2d1,in2d0 + vrev64.32 q9, q9 @ in4d0,in4d1 in3d0,in3d1 + vld2.32 {d1, d3}, [r2,:128]! @ in3u0,in3u1 in1d1,in1d0 + vsub.f32 d0, d18, d0 @ in4d-in4u I + vld2.32 {d20,d21},[r4,:128]! @ c0,c1 s0,s1 + vrev64.32 q1, q1 @ in2d0,in2d1 in1d0,in1d1 + vld2.32 {d30,d31},[r5,:128],r12 @ c2,c3 s2,s3 + vadd.f32 d1, d1, d19 @ in3u+in3d -R + vsub.f32 d16, d16, d2 @ in0u-in2d R + vadd.f32 d17, d17, d3 @ in2u+in1d -I +1: + vmul.f32 d7, d0, d21 @ I*s +A ldr r10, [r3, lr, lsr #1] +T lsr r10, lr, #1 +T ldr r10, [r3, r10] + vmul.f32 d6, d1, d20 @ -R*c + ldr r6, [r3, #4]! + vmul.f32 d4, d1, d21 @ -R*s + vmul.f32 d5, d0, d20 @ I*c + vmul.f32 d24, d16, d30 @ R*c + vmul.f32 d25, d17, d31 @ -I*s + vmul.f32 d22, d16, d31 @ R*s + vmul.f32 d23, d17, d30 @ I*c + subs lr, lr, #16 + vsub.f32 d6, d6, d7 @ -R*c-I*s + vadd.f32 d7, d4, d5 @ -R*s+I*c + vsub.f32 d24, d25, d24 @ I*s-R*c + vadd.f32 d25, d22, d23 @ R*s-I*c + beq 1f + mov r12, #-16 + vld2.32 {d16,d18},[r9,:128],r12 @ in0u0,in0u1 in4d1,in4d0 + vld2.32 {d17,d19},[r8,:128],r12 @ in2u0,in2u1 in3d1,in3d0 + vneg.f32 d7, d7 @ R*s-I*c + vld2.32 {d0, d2}, [r7,:128]! @ in4u0,in4u1 in2d1,in2d0 + vrev64.32 q9, q9 @ in4d0,in4d1 in3d0,in3d1 + vld2.32 {d1, d3}, [r2,:128]! @ in3u0,in3u1 in1d1,in1d0 + vsub.f32 d0, d18, d0 @ in4d-in4u I + vld2.32 {d20,d21},[r4,:128]! @ c0,c1 s0,s1 + vrev64.32 q1, q1 @ in2d0,in2d1 in1d0,in1d1 + vld2.32 {d30,d31},[r5,:128],r12 @ c2,c3 s2,s3 + vadd.f32 d1, d1, d19 @ in3u+in3d -R + vsub.f32 d16, d16, d2 @ in0u-in2d R + vadd.f32 d17, d17, d3 @ in2u+in1d -I + uxth r12, r6, ror #16 + uxth r6, r6 + add r12, r1, r12, lsl #3 + add r6, r1, r6, lsl #3 + vst2.32 {d6[0],d7[0]}, [r6,:64] + vst2.32 {d6[1],d7[1]}, [r12,:64] + uxth r6, r10, ror #16 + uxth r10, r10 + add r6 , r1, r6, lsl #3 + add r10, r1, r10, lsl #3 + vst2.32 {d24[0],d25[0]},[r10,:64] + vst2.32 {d24[1],d25[1]},[r6,:64] + b 1b +1: + vneg.f32 d7, d7 @ R*s-I*c + uxth r12, r6, ror #16 + uxth r6, r6 + add r12, r1, r12, lsl #3 + add r6, r1, r6, lsl #3 + vst2.32 {d6[0],d7[0]}, [r6,:64] + vst2.32 {d6[1],d7[1]}, [r12,:64] + uxth r6, r10, ror #16 + uxth r10, r10 + add r6 , r1, r6, lsl #3 + add r10, r1, r10, lsl #3 + vst2.32 {d24[0],d25[0]},[r10,:64] + vst2.32 {d24[1],d25[1]},[r6,:64] + + mov r4, r0 + mov r6, r1 + bl ff_fft_calc_neon + + mov r12, #1 + ldr lr, [r4, #20] @ mdct_bits + ldr r4, [r4, #24] @ tcos + lsl r12, r12, lr @ n = 1 << nbits + lsr lr, r12, #3 @ n8 = n >> 3 + + add r4, r4, lr, lsl #3 + add r6, r6, lr, lsl #3 + sub r1, r4, #16 + sub r3, r6, #16 + + mov r7, #-16 + mov r8, r6 + mov r0, r3 + + vld2.32 {d0-d1}, [r3,:128], r7 @ d0 =r1,i1 d1 =r0,i0 + vld2.32 {d20-d21},[r6,:128]! @ d20=r2,i2 d21=r3,i3 + vld2.32 {d16,d18},[r1,:128], r7 @ c1,c0 s1,s0 +1: + subs lr, lr, #2 + vmul.f32 d7, d0, d18 @ r1*s1,r0*s0 + vld2.32 {d17,d19},[r4,:128]! @ c2,c3 s2,s3 + vmul.f32 d4, d1, d18 @ i1*s1,i0*s0 + vmul.f32 d5, d21, d19 @ i2*s2,i3*s3 + vmul.f32 d6, d20, d19 @ r2*s2,r3*s3 + vmul.f32 d24, d0, d16 @ r1*c1,r0*c0 + vmul.f32 d25, d20, d17 @ r2*c2,r3*c3 + vmul.f32 d22, d21, d17 @ i2*c2,i3*c3 + vmul.f32 d23, d1, d16 @ i1*c1,i0*c0 + vadd.f32 d4, d4, d24 @ i1*s1+r1*c1,i0*s0+r0*c0 + vadd.f32 d5, d5, d25 @ i2*s2+r2*c2,i3*s3+r3*c3 + vsub.f32 d6, d22, d6 @ i2*c2-r2*s2,i3*c3-r3*s3 + vsub.f32 d7, d23, d7 @ i1*c1-r1*s1,i0*c0-r0*s0 + vneg.f32 q2, q2 + beq 1f + vld2.32 {d0-d1}, [r3,:128], r7 + vld2.32 {d20-d21},[r6,:128]! + vld2.32 {d16,d18},[r1,:128], r7 @ c1,c0 s1,s0 + vrev64.32 q3, q3 + vst2.32 {d4,d6}, [r0,:128], r7 + vst2.32 {d5,d7}, [r8,:128]! + b 1b +1: + vrev64.32 q3, q3 + vst2.32 {d4,d6}, [r0,:128] + vst2.32 {d5,d7}, [r8,:128] + + pop {r4-r10,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/mpegaudiodsp_fixed_armv6.S b/ffmpeg/libavcodec/arm/mpegaudiodsp_fixed_armv6.S new file mode 100644 index 0000000..49bd0bc --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegaudiodsp_fixed_armv6.S @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +.macro skip args:vararg +.endm + +.macro sum8 lo, hi, w, p, t1, t2, t3, t4, rsb=skip, offs=0 + ldr \t1, [\w, #4*\offs] + ldr \t2, [\p, #4]! + \rsb \t1, \t1, #0 + .irpc i, 135 + ldr \t3, [\w, #4*64*\i+4*\offs] + ldr \t4, [\p, #4*64*\i] + smlal \lo, \hi, \t1, \t2 + \rsb \t3, \t3, #0 + ldr \t1, [\w, #4*64*(\i+1)+4*\offs] + ldr \t2, [\p, #4*64*(\i+1)] + smlal \lo, \hi, \t3, \t4 + \rsb \t1, \t1, #0 + .endr + ldr \t3, [\w, #4*64*7+4*\offs] + ldr \t4, [\p, #4*64*7] + smlal \lo, \hi, \t1, \t2 + \rsb \t3, \t3, #0 + smlal \lo, \hi, \t3, \t4 +.endm + +.macro round rd, lo, hi + lsr \rd, \lo, #24 + bic \lo, \lo, #0xff000000 + orr \rd, \rd, \hi, lsl #8 + mov \hi, #0 + ssat \rd, #16, \rd +.endm + +function ff_mpadsp_apply_window_fixed_armv6, export=1 + push {r2,r4-r11,lr} + + add r4, r0, #4*512 @ synth_buf + 512 + .rept 4 + ldm r0!, {r5-r12} + stm r4!, {r5-r12} + .endr + + ldr r4, [sp, #40] @ incr + sub r0, r0, #4*17 @ synth_buf + 16 + ldr r8, [r2] @ sum:low + add r2, r0, #4*32 @ synth_buf + 48 + rsb r5, r4, r4, lsl #5 @ 31 * incr + lsl r4, r4, #1 + asr r9, r8, #31 @ sum:high + add r5, r3, r5, lsl #1 @ samples2 + add r6, r1, #4*32 @ w2 + str r4, [sp, #40] + + sum8 r8, r9, r1, r0, r10, r11, r12, lr + sum8 r8, r9, r1, r2, r10, r11, r12, lr, rsb, 32 + round r10, r8, r9 + strh_post r10, r3, r4 + + mov lr, #15 +1: + ldr r12, [r0, #4]! + ldr r11, [r6, #-4]! + ldr r10, [r1, #4]! + .irpc i, 0246 + .if \i + ldr r11, [r6, #4*64*\i] + ldr r10, [r1, #4*64*\i] + .endif + rsb r11, r11, #0 + smlal r8, r9, r10, r12 + ldr r10, [r0, #4*64*(\i+1)] + .ifeq \i + smull r4, r7, r11, r12 + .else + smlal r4, r7, r11, r12 + .endif + ldr r11, [r6, #4*64*(\i+1)] + ldr r12, [r1, #4*64*(\i+1)] + rsb r11, r11, #0 + smlal r8, r9, r12, r10 + .iflt \i-6 + ldr r12, [r0, #4*64*(\i+2)] + .else + ldr r12, [r2, #-4]! + .endif + smlal r4, r7, r11, r10 + .endr + .irpc i, 0246 + ldr r10, [r1, #4*64*\i+4*32] + rsb r12, r12, #0 + ldr r11, [r6, #4*64*\i+4*32] + smlal r8, r9, r10, r12 + ldr r10, [r2, #4*64*(\i+1)] + smlal r4, r7, r11, r12 + ldr r12, [r1, #4*64*(\i+1)+4*32] + rsb r10, r10, #0 + ldr r11, [r6, #4*64*(\i+1)+4*32] + smlal r8, r9, r12, r10 + .iflt \i-6 + ldr r12, [r2, #4*64*(\i+2)] + .else + ldr r12, [sp, #40] + .endif + smlal r4, r7, r11, r10 + .endr + round r10, r8, r9 + adds r8, r8, r4 + adc r9, r9, r7 + strh_post r10, r3, r12 + round r11, r8, r9 + subs lr, lr, #1 + strh_dpost r11, r5, r12 + bgt 1b + + sum8 r8, r9, r1, r0, r10, r11, r12, lr, rsb, 33 + pop {r4} + round r10, r8, r9 + str r8, [r4] + strh r10, [r3] + + pop {r4-r11,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/mpegaudiodsp_init_arm.c b/ffmpeg/libavcodec/arm/mpegaudiodsp_init_arm.c new file mode 100644 index 0000000..e73aee6 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegaudiodsp_init_arm.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/mpegaudiodsp.h" +#include "config.h" + +void ff_mpadsp_apply_window_fixed_armv6(int32_t *synth_buf, int32_t *window, + int *dither, int16_t *out, int incr); + +av_cold void ff_mpadsp_init_arm(MPADSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv6(cpu_flags)) { + s->apply_window_fixed = ff_mpadsp_apply_window_fixed_armv6; + } +} diff --git a/ffmpeg/libavcodec/arm/mpegvideo_arm.c b/ffmpeg/libavcodec/arm/mpegvideo_arm.c new file mode 100644 index 0000000..6566798 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegvideo_arm.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002 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 "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpegvideo.h" +#include "mpegvideo_arm.h" +#include "asm-offsets.h" + +#if HAVE_NEON +CHK_OFFS(MpegEncContext, y_dc_scale, Y_DC_SCALE); +CHK_OFFS(MpegEncContext, c_dc_scale, C_DC_SCALE); +CHK_OFFS(MpegEncContext, ac_pred, AC_PRED); +CHK_OFFS(MpegEncContext, block_last_index, BLOCK_LAST_INDEX); +CHK_OFFS(MpegEncContext, inter_scantable.raster_end, INTER_SCANTAB_RASTER_END); +CHK_OFFS(MpegEncContext, h263_aic, H263_AIC); +#endif + +void ff_dct_unquantize_h263_inter_neon(MpegEncContext *s, int16_t *block, + int n, int qscale); +void ff_dct_unquantize_h263_intra_neon(MpegEncContext *s, int16_t *block, + int n, int qscale); + +av_cold void ff_MPV_common_init_arm(MpegEncContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv5te(cpu_flags)) + ff_MPV_common_init_armv5te(s); + + if (have_neon(cpu_flags)) { + s->dct_unquantize_h263_intra = ff_dct_unquantize_h263_intra_neon; + s->dct_unquantize_h263_inter = ff_dct_unquantize_h263_inter_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/mpegvideo_arm.h b/ffmpeg/libavcodec/arm/mpegvideo_arm.h new file mode 100644 index 0000000..4ff93b7 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegvideo_arm.h @@ -0,0 +1,26 @@ +/* + * 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 + */ + +#ifndef AVCODEC_ARM_MPEGVIDEO_H +#define AVCODEC_ARM_MPEGVIDEO_H + +#include "libavcodec/mpegvideo.h" + +void ff_MPV_common_init_armv5te(MpegEncContext *s); + +#endif /* AVCODEC_ARM_MPEGVIDEO_H */ diff --git a/ffmpeg/libavcodec/arm/mpegvideo_armv5te.c b/ffmpeg/libavcodec/arm/mpegvideo_armv5te.c new file mode 100644 index 0000000..a572290 --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegvideo_armv5te.c @@ -0,0 +1,102 @@ +/* + * Optimization of some functions from mpegvideo.c for armv5te + * Copyright (c) 2007 Siarhei Siamashka + * + * 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 "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpegvideo.h" +#include "mpegvideo_arm.h" + +void ff_dct_unquantize_h263_armv5te(int16_t *block, int qmul, int qadd, int count); + +#ifdef ENABLE_ARM_TESTS +/** + * h263 dequantizer supplementary function, it is performance critical and needs to + * have optimized implementations for each architecture. Is also used as a reference + * implementation in regression tests + */ +static inline void dct_unquantize_h263_helper_c(int16_t *block, int qmul, int qadd, int count) +{ + int i, level; + for (i = 0; i < count; i++) { + level = block[i]; + if (level) { + if (level < 0) { + level = level * qmul - qadd; + } else { + level = level * qmul + qadd; + } + block[i] = level; + } + } +} +#endif + +static void dct_unquantize_h263_intra_armv5te(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + int level, qmul, qadd; + int nCoeffs; + + av_assert2(s->block_last_index[n]>=0); + + qmul = qscale << 1; + + if (!s->h263_aic) { + if (n < 4) + level = block[0] * s->y_dc_scale; + else + level = block[0] * s->c_dc_scale; + qadd = (qscale - 1) | 1; + }else{ + qadd = 0; + level = block[0]; + } + if(s->ac_pred) + nCoeffs=63; + else + nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ]; + + ff_dct_unquantize_h263_armv5te(block, qmul, qadd, nCoeffs + 1); + block[0] = level; +} + +static void dct_unquantize_h263_inter_armv5te(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + int 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] ]; + + ff_dct_unquantize_h263_armv5te(block, qmul, qadd, nCoeffs + 1); +} + +av_cold void ff_MPV_common_init_armv5te(MpegEncContext *s) +{ + s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_armv5te; + s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_armv5te; +} diff --git a/ffmpeg/libavcodec/arm/mpegvideo_armv5te_s.S b/ffmpeg/libavcodec/arm/mpegvideo_armv5te_s.S new file mode 100644 index 0000000..8687d6b --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegvideo_armv5te_s.S @@ -0,0 +1,114 @@ +/* + * Optimization of some functions from mpegvideo.c for armv5te + * Copyright (c) 2007 Siarhei Siamashka + * + * 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 "config.h" +#include "libavutil/arm/asm.S" + +/* + * Special optimized version of dct_unquantize_h263_helper_c, it + * requires the block to be at least 8 bytes aligned, and may process + * more elements than requested. But it is guaranteed to never + * process more than 64 elements provided that count argument is <= 64, + * so it is safe. This function is optimized for a common distribution + * of values for nCoeffs (they are mostly multiple of 8 plus one or + * two extra elements). So this function processes data as 8 elements + * per loop iteration and contains optional 2 elements processing in + * the end. + * + * Inner loop should take 6 cycles per element on arm926ej-s (Nokia 770) + */ + +.macro dequant_t dst, src, mul, add, tmp + rsbs \tmp, ip, \src, asr #16 + it gt + addgt \tmp, \add, #0 + it lt + rsblt \tmp, \add, #0 + it ne + smlatbne \dst, \src, \mul, \tmp +.endm + +.macro dequant_b dst, src, mul, add, tmp + rsbs \tmp, ip, \src, lsl #16 + it gt + addgt \tmp, \add, #0 + it lt + rsblt \tmp, \add, #0 + it ne + smlabbne \dst, \src, \mul, \tmp +.endm + +function ff_dct_unquantize_h263_armv5te, export=1 + push {r4-r9,lr} + mov ip, #0 + subs r3, r3, #2 + ble 2f + ldrd r4, r5, [r0, #0] +1: + ldrd r6, r7, [r0, #8] + + dequant_t r9, r4, r1, r2, r9 + dequant_t lr, r5, r1, r2, lr + dequant_b r4, r4, r1, r2, r8 + dequant_b r5, r5, r1, r2, r8 + + strh r4, [r0], #2 + strh r9, [r0], #2 + strh r5, [r0], #2 + strh lr, [r0], #2 + + dequant_t r9, r6, r1, r2, r9 + dequant_t lr, r7, r1, r2, lr + dequant_b r6, r6, r1, r2, r8 + dequant_b r7, r7, r1, r2, r8 + + strh r6, [r0], #2 + strh r9, [r0], #2 + strh r7, [r0], #2 + strh lr, [r0], #2 + + subs r3, r3, #8 + it gt + ldrdgt r4, r5, [r0, #0] /* load data early to avoid load/use pipeline stall */ + bgt 1b + + adds r3, r3, #2 + it le + pople {r4-r9,pc} +2: + ldrsh r9, [r0, #0] + ldrsh lr, [r0, #2] + mov r8, r2 + cmp r9, #0 + it lt + rsblt r8, r2, #0 + it ne + smlabbne r9, r9, r1, r8 + mov r8, r2 + cmp lr, #0 + it lt + rsblt r8, r2, #0 + it ne + smlabbne lr, lr, r1, r8 + strh r9, [r0], #2 + strh lr, [r0], #2 + pop {r4-r9,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/mpegvideo_neon.S b/ffmpeg/libavcodec/arm/mpegvideo_neon.S new file mode 100644 index 0000000..e05df8e --- /dev/null +++ b/ffmpeg/libavcodec/arm/mpegvideo_neon.S @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" +#include "asm-offsets.h" + +function ff_dct_unquantize_h263_inter_neon, export=1 + add r12, r0, #BLOCK_LAST_INDEX + ldr r12, [r12, r2, lsl #2] + add r0, r0, #INTER_SCANTAB_RASTER_END + ldrb r12, [r0, r12] + sub r2, r3, #1 + lsl r0, r3, #1 + orr r2, r2, #1 + add r3, r12, #1 +endfunc + +function ff_dct_unquantize_h263_neon, export=1 + vdup.16 q15, r0 @ qmul + vdup.16 q14, r2 @ qadd + vneg.s16 q13, q14 + cmp r3, #4 + mov r0, r1 + ble 2f +1: + vld1.16 {q0}, [r0,:128]! + vclt.s16 q3, q0, #0 + vld1.16 {q8}, [r0,:128]! + vceq.s16 q1, q0, #0 + vmul.s16 q2, q0, q15 + vclt.s16 q11, q8, #0 + vmul.s16 q10, q8, q15 + vbsl q3, q13, q14 + vbsl q11, q13, q14 + vadd.s16 q2, q2, q3 + vceq.s16 q9, q8, #0 + vadd.s16 q10, q10, q11 + vbif q0, q2, q1 + vbif q8, q10, q9 + subs r3, r3, #16 + vst1.16 {q0}, [r1,:128]! + vst1.16 {q8}, [r1,:128]! + it le + bxle lr + cmp r3, #8 + bgt 1b +2: + vld1.16 {d0}, [r0,:64] + vclt.s16 d3, d0, #0 + vceq.s16 d1, d0, #0 + vmul.s16 d2, d0, d30 + vbsl d3, d26, d28 + vadd.s16 d2, d2, d3 + vbif d0, d2, d1 + vst1.16 {d0}, [r1,:64] + bx lr +endfunc + +function ff_dct_unquantize_h263_intra_neon, export=1 + push {r4-r6,lr} + add r12, r0, #BLOCK_LAST_INDEX + ldr r6, [r0, #AC_PRED] + add lr, r0, #INTER_SCANTAB_RASTER_END + cmp r6, #0 + it ne + movne r12, #63 + bne 1f + ldr r12, [r12, r2, lsl #2] + ldrb r12, [lr, r12] +1: ldr r5, [r0, #H263_AIC] + ldrsh r4, [r1] + cmp r5, #0 + mov r5, r1 + it ne + movne r2, #0 + bne 2f + cmp r2, #4 + it ge + addge r0, r0, #4 + sub r2, r3, #1 + ldr r6, [r0, #Y_DC_SCALE] + orr r2, r2, #1 + smulbb r4, r4, r6 +2: lsl r0, r3, #1 + add r3, r12, #1 + bl ff_dct_unquantize_h263_neon + vmov.16 d0[0], r4 + vst1.16 {d0[0]}, [r5] + pop {r4-r6,pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/neon.S b/ffmpeg/libavcodec/arm/neon.S new file mode 100644 index 0000000..716a607 --- /dev/null +++ b/ffmpeg/libavcodec/arm/neon.S @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +.macro transpose_8x8 r0, r1, r2, r3, r4, r5, r6, r7 + vtrn.32 \r0, \r4 + vtrn.32 \r1, \r5 + vtrn.32 \r2, \r6 + vtrn.32 \r3, \r7 + vtrn.16 \r0, \r2 + vtrn.16 \r1, \r3 + vtrn.16 \r4, \r6 + vtrn.16 \r5, \r7 + vtrn.8 \r0, \r1 + vtrn.8 \r2, \r3 + vtrn.8 \r4, \r5 + vtrn.8 \r6, \r7 +.endm + +.macro transpose_4x4 r0, r1, r2, r3 + vtrn.16 \r0, \r2 + vtrn.16 \r1, \r3 + vtrn.8 \r0, \r1 + vtrn.8 \r2, \r3 +.endm + +.macro swap4 r0, r1, r2, r3, r4, r5, r6, r7 + vswp \r0, \r4 + vswp \r1, \r5 + vswp \r2, \r6 + vswp \r3, \r7 +.endm + +.macro transpose16_4x4 r0, r1, r2, r3, r4, r5, r6, r7 + vtrn.32 \r0, \r2 + vtrn.32 \r1, \r3 + vtrn.32 \r4, \r6 + vtrn.32 \r5, \r7 + vtrn.16 \r0, \r1 + vtrn.16 \r2, \r3 + vtrn.16 \r4, \r5 + vtrn.16 \r6, \r7 +.endm diff --git a/ffmpeg/libavcodec/arm/rdft_neon.S b/ffmpeg/libavcodec/arm/rdft_neon.S new file mode 100644 index 0000000..781d976 --- /dev/null +++ b/ffmpeg/libavcodec/arm/rdft_neon.S @@ -0,0 +1,150 @@ +/* + * ARM NEON optimised RDFT + * Copyright (c) 2009 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function ff_rdft_calc_neon, export=1 + push {r4-r8,lr} + + ldr r6, [r0, #4] @ inverse + mov r4, r0 + mov r5, r1 + + lsls r6, r6, #31 + bne 1f + add r0, r4, #20 + bl X(ff_fft_permute_neon) + add r0, r4, #20 + mov r1, r5 + bl X(ff_fft_calc_neon) +1: + ldr r12, [r4, #0] @ nbits + mov r2, #1 + lsl r12, r2, r12 + add r0, r5, #8 + add r1, r5, r12, lsl #2 + lsr r12, r12, #2 + ldr r2, [r4, #12] @ tcos + sub r12, r12, #2 + ldr r3, [r4, #16] @ tsin + mov r7, r0 + sub r1, r1, #8 + mov lr, r1 + mov r8, #-8 + vld1.32 {d0}, [r0,:64]! @ d1[0,1] + vld1.32 {d1}, [r1,:64], r8 @ d2[0,1] + vld1.32 {d4}, [r2,:64]! @ tcos[i] + vld1.32 {d5}, [r3,:64]! @ tsin[i] + vmov.f32 d18, #0.5 @ k1 + vdup.32 d19, r6 + pld [r0, #32] + veor d19, d18, d19 @ k2 + vmov.i32 d16, #0 + vmov.i32 d17, #1<<31 + pld [r1, #-32] + vtrn.32 d16, d17 + pld [r2, #32] + vrev64.32 d16, d16 @ d16=1,0 d17=0,1 + pld [r3, #32] +2: + veor q1, q0, q8 @ -d1[0],d1[1], d2[0],-d2[1] + vld1.32 {d24}, [r0,:64]! @ d1[0,1] + vadd.f32 d0, d0, d3 @ d1[0]+d2[0], d1[1]-d2[1] + vld1.32 {d25}, [r1,:64], r8 @ d2[0,1] + vadd.f32 d1, d2, d1 @ -d1[0]+d2[0], d1[1]+d2[1] + veor q3, q12, q8 @ -d1[0],d1[1], d2[0],-d2[1] + pld [r0, #32] + vmul.f32 q10, q0, q9 @ ev.re, ev.im, od.im, od.re + pld [r1, #-32] + vadd.f32 d0, d24, d7 @ d1[0]+d2[0], d1[1]-d2[1] + vadd.f32 d1, d6, d25 @ -d1[0]+d2[0], d1[1]+d2[1] + vmul.f32 q11, q0, q9 @ ev.re, ev.im, od.im, od.re + veor d7, d21, d16 @ -od.im, od.re + vrev64.32 d3, d21 @ od.re, od.im + veor d6, d20, d17 @ ev.re,-ev.im + veor d2, d3, d16 @ -od.re, od.im + vmla.f32 d20, d3, d4[1] + vmla.f32 d20, d7, d5[1] + vmla.f32 d6, d2, d4[1] + vmla.f32 d6, d21, d5[1] + vld1.32 {d4}, [r2,:64]! @ tcos[i] + veor d7, d23, d16 @ -od.im, od.re + vld1.32 {d5}, [r3,:64]! @ tsin[i] + veor d24, d22, d17 @ ev.re,-ev.im + vrev64.32 d3, d23 @ od.re, od.im + pld [r2, #32] + veor d2, d3, d16 @ -od.re, od.im + pld [r3, #32] + vmla.f32 d22, d3, d4[0] + vmla.f32 d22, d7, d5[0] + vmla.f32 d24, d2, d4[0] + vmla.f32 d24, d23, d5[0] + vld1.32 {d0}, [r0,:64]! @ d1[0,1] + vld1.32 {d1}, [r1,:64], r8 @ d2[0,1] + vst1.32 {d20}, [r7,:64]! + vst1.32 {d6}, [lr,:64], r8 + vst1.32 {d22}, [r7,:64]! + vst1.32 {d24}, [lr,:64], r8 + subs r12, r12, #2 + bgt 2b + + veor q1, q0, q8 @ -d1[0],d1[1], d2[0],-d2[1] + vadd.f32 d0, d0, d3 @ d1[0]+d2[0], d1[1]-d2[1] + vadd.f32 d1, d2, d1 @ -d1[0]+d2[0], d1[1]+d2[1] + ldr r2, [r4, #8] @ sign_convention + vmul.f32 q10, q0, q9 @ ev.re, ev.im, od.im, od.re + add r0, r0, #4 + bfc r2, #0, #31 + vld1.32 {d0[0]}, [r0,:32] + veor d7, d21, d16 @ -od.im, od.re + vrev64.32 d3, d21 @ od.re, od.im + veor d6, d20, d17 @ ev.re,-ev.im + vld1.32 {d22}, [r5,:64] + vdup.32 d1, r2 + vmov d23, d22 + veor d2, d3, d16 @ -od.re, od.im + vtrn.32 d22, d23 + veor d0, d0, d1 + veor d23, d23, d17 + vmla.f32 d20, d3, d4[1] + vmla.f32 d20, d7, d5[1] + vmla.f32 d6, d2, d4[1] + vmla.f32 d6, d21, d5[1] + vadd.f32 d22, d22, d23 + vst1.32 {d20}, [r7,:64] + vst1.32 {d6}, [lr,:64] + vst1.32 {d0[0]}, [r0,:32] + vst1.32 {d22}, [r5,:64] + + cmp r6, #0 + it eq + popeq {r4-r8,pc} + + vmul.f32 d22, d22, d18 + vst1.32 {d22}, [r5,:64] + add r0, r4, #20 + mov r1, r5 + bl X(ff_fft_permute_neon) + add r0, r4, #20 + mov r1, r5 + pop {r4-r8,lr} + b X(ff_fft_calc_neon) +endfunc diff --git a/ffmpeg/libavcodec/arm/rv34dsp_init_arm.c b/ffmpeg/libavcodec/arm/rv34dsp_init_arm.c new file mode 100644 index 0000000..8bfe90b --- /dev/null +++ b/ffmpeg/libavcodec/arm/rv34dsp_init_arm.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Janne Grunau + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/rv34dsp.h" +#include "libavutil/arm/cpu.h" + +void ff_rv34_inv_transform_noround_neon(int16_t *block); + +void ff_rv34_inv_transform_noround_dc_neon(int16_t *block); + +void ff_rv34_idct_add_neon(uint8_t *dst, ptrdiff_t stride, int16_t *block); +void ff_rv34_idct_dc_add_neon(uint8_t *dst, ptrdiff_t stride, int dc); + +av_cold void ff_rv34dsp_init_arm(RV34DSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->rv34_inv_transform = ff_rv34_inv_transform_noround_neon; + c->rv34_inv_transform_dc = ff_rv34_inv_transform_noround_dc_neon; + + c->rv34_idct_add = ff_rv34_idct_add_neon; + c->rv34_idct_dc_add = ff_rv34_idct_dc_add_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/rv34dsp_neon.S b/ffmpeg/libavcodec/arm/rv34dsp_neon.S new file mode 100644 index 0000000..a29123f --- /dev/null +++ b/ffmpeg/libavcodec/arm/rv34dsp_neon.S @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2011 Janne Grunau + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" +#include "neon.S" + +.macro rv34_inv_transform r0 + vld1.16 {q14-q15}, [\r0,:128] + vmov.s16 d0, #13 + vshll.s16 q12, d29, #3 + vshll.s16 q13, d29, #4 + vshll.s16 q9, d31, #3 + vshll.s16 q1, d31, #4 + vmull.s16 q10, d28, d0 + vmlal.s16 q10, d30, d0 + vmull.s16 q11, d28, d0 + vmlsl.s16 q11, d30, d0 + vsubw.s16 q12, q12, d29 @ z2 = block[i+4*1]*7 + vaddw.s16 q13, q13, d29 @ z3 = block[i+4*1]*17 + vsubw.s16 q9, q9, d31 + vaddw.s16 q1, q1, d31 + vadd.s32 q13, q13, q9 @ z3 = 17*block[i+4*1] + 7*block[i+4*3] + vsub.s32 q12, q12, q1 @ z2 = 7*block[i+4*1] - 17*block[i+4*3] + vadd.s32 q1, q10, q13 @ z0 + z3 + vadd.s32 q2, q11, q12 @ z1 + z2 + vsub.s32 q8, q10, q13 @ z0 - z3 + vsub.s32 q3, q11, q12 @ z1 - z2 + vtrn.32 q1, q2 + vtrn.32 q3, q8 + vswp d3, d6 + vswp d5, d16 + vmov.s32 d0, #13 + vadd.s32 q10, q1, q3 + vsub.s32 q11, q1, q3 + vshl.s32 q12, q2, #3 + vshl.s32 q9, q2, #4 + vmul.s32 q13, q11, d0[0] + vshl.s32 q11, q8, #4 + vadd.s32 q9, q9, q2 + vshl.s32 q15, q8, #3 + vsub.s32 q12, q12, q2 + vadd.s32 q11, q11, q8 + vmul.s32 q14, q10, d0[0] + vsub.s32 q8, q15, q8 + vsub.s32 q12, q12, q11 + vadd.s32 q9, q9, q8 + vadd.s32 q2, q13, q12 @ z1 + z2 + vadd.s32 q1, q14, q9 @ z0 + z3 + vsub.s32 q3, q13, q12 @ z1 - z2 + vsub.s32 q15, q14, q9 @ z0 - z3 +.endm + +/* void rv34_idct_add_c(uint8_t *dst, int stride, int16_t *block) */ +function ff_rv34_idct_add_neon, export=1 + mov r3, r0 + rv34_inv_transform r2 + vmov.i16 q12, #0 + vrshrn.s32 d16, q1, #10 @ (z0 + z3) >> 10 + vrshrn.s32 d17, q2, #10 @ (z1 + z2) >> 10 + vrshrn.s32 d18, q3, #10 @ (z1 - z2) >> 10 + vrshrn.s32 d19, q15, #10 @ (z0 - z3) >> 10 + vld1.32 {d28[]}, [r0,:32], r1 + vld1.32 {d29[]}, [r0,:32], r1 + vtrn.32 q8, q9 + vld1.32 {d28[1]}, [r0,:32], r1 + vld1.32 {d29[1]}, [r0,:32], r1 + vst1.16 {q12}, [r2,:128]! @ memset(block, 0, 16) + vst1.16 {q12}, [r2,:128] @ memset(block+16, 0, 16) + vtrn.16 d16, d17 + vtrn.32 d28, d29 + vtrn.16 d18, d19 + vaddw.u8 q0, q8, d28 + vaddw.u8 q1, q9, d29 + vqmovun.s16 d28, q0 + vqmovun.s16 d29, q1 + vst1.32 {d28[0]}, [r3,:32], r1 + vst1.32 {d28[1]}, [r3,:32], r1 + vst1.32 {d29[0]}, [r3,:32], r1 + vst1.32 {d29[1]}, [r3,:32], r1 + bx lr +endfunc + +/* void rv34_inv_transform_noround_neon(int16_t *block); */ +function ff_rv34_inv_transform_noround_neon, export=1 + rv34_inv_transform r0 + vshl.s32 q11, q2, #1 + vshl.s32 q10, q1, #1 + vshl.s32 q12, q3, #1 + vshl.s32 q13, q15, #1 + vadd.s32 q11, q11, q2 + vadd.s32 q10, q10, q1 + vadd.s32 q12, q12, q3 + vadd.s32 q13, q13, q15 + vshrn.s32 d0, q10, #11 @ (z0 + z3)*3 >> 11 + vshrn.s32 d1, q11, #11 @ (z1 + z2)*3 >> 11 + vshrn.s32 d2, q12, #11 @ (z1 - z2)*3 >> 11 + vshrn.s32 d3, q13, #11 @ (z0 - z3)*3 >> 11 + vst4.16 {d0[0], d1[0], d2[0], d3[0]}, [r0,:64]! + vst4.16 {d0[1], d1[1], d2[1], d3[1]}, [r0,:64]! + vst4.16 {d0[2], d1[2], d2[2], d3[2]}, [r0,:64]! + vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r0,:64]! + bx lr +endfunc + +/* void ff_rv34_idct_dc_add_neon(uint8_t *dst, int stride, int dc) */ +function ff_rv34_idct_dc_add_neon, export=1 + mov r3, r0 + vld1.32 {d28[]}, [r0,:32], r1 + vld1.32 {d29[]}, [r0,:32], r1 + vdup.16 d0, r2 + vmov.s16 d1, #169 + vld1.32 {d28[1]}, [r0,:32], r1 + vmull.s16 q1, d0, d1 @ dc * 13 * 13 + vld1.32 {d29[1]}, [r0,:32], r1 + vrshrn.s32 d0, q1, #10 @ (dc * 13 * 13 + 0x200) >> 10 + vmov d1, d0 + vaddw.u8 q2, q0, d28 + vaddw.u8 q3, q0, d29 + vqmovun.s16 d28, q2 + vqmovun.s16 d29, q3 + vst1.32 {d28[0]}, [r3,:32], r1 + vst1.32 {d29[0]}, [r3,:32], r1 + vst1.32 {d28[1]}, [r3,:32], r1 + vst1.32 {d29[1]}, [r3,:32], r1 + bx lr +endfunc + +/* void rv34_inv_transform_dc_noround_c(int16_t *block) */ +function ff_rv34_inv_transform_noround_dc_neon, export=1 + vld1.16 {d28[]}, [r0,:16] @ block[0] + vmov.i16 d4, #251 + vorr.s16 d4, #256 @ 13^2 * 3 + vmull.s16 q3, d28, d4 + vshrn.s32 d0, q3, #11 + vmov.i16 d1, d0 + vst1.64 {q0}, [r0,:128]! + vst1.64 {q0}, [r0,:128]! + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/rv40dsp_init_arm.c b/ffmpeg/libavcodec/arm/rv40dsp_init_arm.c new file mode 100644 index 0000000..fec3702 --- /dev/null +++ b/ffmpeg/libavcodec/arm/rv40dsp_init_arm.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2011 Janne Grunau + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/rv34dsp.h" +#include "libavutil/arm/cpu.h" + +#define DECL_QPEL3(type, w, pos) \ + void ff_##type##_rv40_qpel##w##_mc##pos##_neon(uint8_t *dst, uint8_t *src,\ + ptrdiff_t stride) +#define DECL_QPEL2(w, pos) \ + DECL_QPEL3(put, w, pos); \ + DECL_QPEL3(avg, w, pos) + +#define DECL_QPEL_XY(x, y) \ + DECL_QPEL2(16, x ## y); \ + DECL_QPEL2(8, x ## y) + +#define DECL_QPEL_Y(y) \ + DECL_QPEL_XY(0, y); \ + DECL_QPEL_XY(1, y); \ + DECL_QPEL_XY(2, y); \ + DECL_QPEL_XY(3, y); \ + +DECL_QPEL_Y(0); +DECL_QPEL_Y(1); +DECL_QPEL_Y(2); +DECL_QPEL_Y(3); + +void ff_put_rv40_chroma_mc8_neon(uint8_t *, uint8_t *, int, int, int, int); +void ff_put_rv40_chroma_mc4_neon(uint8_t *, uint8_t *, int, int, int, int); + +void ff_avg_rv40_chroma_mc8_neon(uint8_t *, uint8_t *, int, int, int, int); +void ff_avg_rv40_chroma_mc4_neon(uint8_t *, uint8_t *, int, int, int, int); + +void ff_rv40_weight_func_16_neon(uint8_t *, uint8_t *, uint8_t *, int, int, ptrdiff_t); +void ff_rv40_weight_func_8_neon(uint8_t *, uint8_t *, uint8_t *, int, int, ptrdiff_t); + +int ff_rv40_h_loop_filter_strength_neon(uint8_t *src, ptrdiff_t stride, + int beta, int beta2, int edge, + int *p1, int *q1); +int ff_rv40_v_loop_filter_strength_neon(uint8_t *src, ptrdiff_t stride, + int beta, int beta2, int edge, + int *p1, int *q1); + +void ff_rv40_h_weak_loop_filter_neon(uint8_t *src, ptrdiff_t stride, int filter_p1, + int filter_q1, int alpha, int beta, + int lim_p0q0, int lim_q1, int lim_p1); +void ff_rv40_v_weak_loop_filter_neon(uint8_t *src, ptrdiff_t stride, int filter_p1, + int filter_q1, int alpha, int beta, + int lim_p0q0, int lim_q1, int lim_p1); + +static av_cold void ff_rv40dsp_init_neon(RV34DSPContext *c) +{ + c->put_pixels_tab[0][ 1] = ff_put_rv40_qpel16_mc10_neon; + c->put_pixels_tab[0][ 3] = ff_put_rv40_qpel16_mc30_neon; + c->put_pixels_tab[0][ 4] = ff_put_rv40_qpel16_mc01_neon; + c->put_pixels_tab[0][ 5] = ff_put_rv40_qpel16_mc11_neon; + c->put_pixels_tab[0][ 6] = ff_put_rv40_qpel16_mc21_neon; + c->put_pixels_tab[0][ 7] = ff_put_rv40_qpel16_mc31_neon; + c->put_pixels_tab[0][ 9] = ff_put_rv40_qpel16_mc12_neon; + c->put_pixels_tab[0][10] = ff_put_rv40_qpel16_mc22_neon; + c->put_pixels_tab[0][11] = ff_put_rv40_qpel16_mc32_neon; + c->put_pixels_tab[0][12] = ff_put_rv40_qpel16_mc03_neon; + c->put_pixels_tab[0][13] = ff_put_rv40_qpel16_mc13_neon; + c->put_pixels_tab[0][14] = ff_put_rv40_qpel16_mc23_neon; + c->put_pixels_tab[0][15] = ff_put_rv40_qpel16_mc33_neon; + c->avg_pixels_tab[0][ 1] = ff_avg_rv40_qpel16_mc10_neon; + c->avg_pixels_tab[0][ 3] = ff_avg_rv40_qpel16_mc30_neon; + c->avg_pixels_tab[0][ 4] = ff_avg_rv40_qpel16_mc01_neon; + c->avg_pixels_tab[0][ 5] = ff_avg_rv40_qpel16_mc11_neon; + c->avg_pixels_tab[0][ 6] = ff_avg_rv40_qpel16_mc21_neon; + c->avg_pixels_tab[0][ 7] = ff_avg_rv40_qpel16_mc31_neon; + c->avg_pixels_tab[0][ 9] = ff_avg_rv40_qpel16_mc12_neon; + c->avg_pixels_tab[0][10] = ff_avg_rv40_qpel16_mc22_neon; + c->avg_pixels_tab[0][11] = ff_avg_rv40_qpel16_mc32_neon; + c->avg_pixels_tab[0][12] = ff_avg_rv40_qpel16_mc03_neon; + c->avg_pixels_tab[0][13] = ff_avg_rv40_qpel16_mc13_neon; + c->avg_pixels_tab[0][14] = ff_avg_rv40_qpel16_mc23_neon; + c->avg_pixels_tab[0][15] = ff_avg_rv40_qpel16_mc33_neon; + c->put_pixels_tab[1][ 1] = ff_put_rv40_qpel8_mc10_neon; + c->put_pixels_tab[1][ 3] = ff_put_rv40_qpel8_mc30_neon; + c->put_pixels_tab[1][ 4] = ff_put_rv40_qpel8_mc01_neon; + c->put_pixels_tab[1][ 5] = ff_put_rv40_qpel8_mc11_neon; + c->put_pixels_tab[1][ 6] = ff_put_rv40_qpel8_mc21_neon; + c->put_pixels_tab[1][ 7] = ff_put_rv40_qpel8_mc31_neon; + c->put_pixels_tab[1][ 9] = ff_put_rv40_qpel8_mc12_neon; + c->put_pixels_tab[1][10] = ff_put_rv40_qpel8_mc22_neon; + c->put_pixels_tab[1][11] = ff_put_rv40_qpel8_mc32_neon; + c->put_pixels_tab[1][12] = ff_put_rv40_qpel8_mc03_neon; + c->put_pixels_tab[1][13] = ff_put_rv40_qpel8_mc13_neon; + c->put_pixels_tab[1][14] = ff_put_rv40_qpel8_mc23_neon; + c->put_pixels_tab[1][15] = ff_put_rv40_qpel8_mc33_neon; + c->avg_pixels_tab[1][ 1] = ff_avg_rv40_qpel8_mc10_neon; + c->avg_pixels_tab[1][ 3] = ff_avg_rv40_qpel8_mc30_neon; + c->avg_pixels_tab[1][ 4] = ff_avg_rv40_qpel8_mc01_neon; + c->avg_pixels_tab[1][ 5] = ff_avg_rv40_qpel8_mc11_neon; + c->avg_pixels_tab[1][ 6] = ff_avg_rv40_qpel8_mc21_neon; + c->avg_pixels_tab[1][ 7] = ff_avg_rv40_qpel8_mc31_neon; + c->avg_pixels_tab[1][ 9] = ff_avg_rv40_qpel8_mc12_neon; + c->avg_pixels_tab[1][10] = ff_avg_rv40_qpel8_mc22_neon; + c->avg_pixels_tab[1][11] = ff_avg_rv40_qpel8_mc32_neon; + c->avg_pixels_tab[1][12] = ff_avg_rv40_qpel8_mc03_neon; + c->avg_pixels_tab[1][13] = ff_avg_rv40_qpel8_mc13_neon; + c->avg_pixels_tab[1][14] = ff_avg_rv40_qpel8_mc23_neon; + c->avg_pixels_tab[1][15] = ff_avg_rv40_qpel8_mc33_neon; + + c->put_chroma_pixels_tab[0] = ff_put_rv40_chroma_mc8_neon; + c->put_chroma_pixels_tab[1] = ff_put_rv40_chroma_mc4_neon; + c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_neon; + c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_neon; + + c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_16_neon; + c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_8_neon; + + c->rv40_loop_filter_strength[0] = ff_rv40_h_loop_filter_strength_neon; + c->rv40_loop_filter_strength[1] = ff_rv40_v_loop_filter_strength_neon; + c->rv40_weak_loop_filter[0] = ff_rv40_h_weak_loop_filter_neon; + c->rv40_weak_loop_filter[1] = ff_rv40_v_weak_loop_filter_neon; +} + +av_cold void ff_rv40dsp_init_arm(RV34DSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) + ff_rv40dsp_init_neon(c); +} diff --git a/ffmpeg/libavcodec/arm/rv40dsp_neon.S b/ffmpeg/libavcodec/arm/rv40dsp_neon.S new file mode 100644 index 0000000..6bd45eb --- /dev/null +++ b/ffmpeg/libavcodec/arm/rv40dsp_neon.S @@ -0,0 +1,920 @@ +/* + * Copyright (c) 2011 Janne Grunau + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" +#include "neon.S" + +.macro qpel_lowpass r0, r1, rc1, rc2, shift + vext.8 d25, \r0, \r1, #1 @ src[-1] + vext.8 d26, \r0, \r1, #4 @ src[ 2] + vext.8 d24, \r0, \r1, #5 @ src[ 3] + vaddl.u8 q9, d25, d26 + vaddl.u8 q8, \r0, d24 + vext.8 d27, \r0, \r1, #2 @ src[ 0] + vshl.s16 q12, q9, #2 + vsub.s16 q8, q8, q9 + vext.8 d28, \r0, \r1, #3 @ src[ 1] + vsub.s16 q8, q8, q12 + vmlal.u8 q8, d27, \rc1 + vmlal.u8 q8, d28, \rc2 + vqrshrun.s16 \r0, q8, #\shift +.endm + +.macro qpel_lowpass_x2 r0, r1, r2, r3, rc1, rc2, shift + vext.8 d25, \r0, \r1, #1 @ src[-1] + vext.8 d26, \r0, \r1, #4 @ src[ 2] + vext.8 d24, \r0, \r1, #5 @ src[ 3] + vaddl.u8 q9, d25, d26 + vaddl.u8 q8, \r0, d24 + vext.8 d29, \r0, \r1, #2 @ src[ 0] + vext.8 d28, \r0, \r1, #3 @ src[ 1] + vshl.s16 q10, q9, #2 + vext.8 \r1, \r2, \r3, #1 @ src[-1] + vsub.s16 q8, q8, q9 + vext.8 d22, \r2, \r3, #4 @ src[ 2] + vext.8 \r0, \r2, \r3, #5 @ src[ 3] + vaddl.u8 q13, \r1, d22 + vaddl.u8 q12, \r2, \r0 + vsub.s16 q8, q8, q10 + vshl.s16 q9, q13, #2 + vsub.s16 q12, q12, q13 + vmlal.u8 q8, d29, \rc1 + vmlal.u8 q8, d28, \rc2 + vsub.s16 q12, q12, q9 + vext.8 d26, \r2, \r3, #2 @ src[ 0] + vext.8 d27, \r2, \r3, #3 @ src[ 1] + vmlal.u8 q12, d26, \rc1 + vmlal.u8 q12, d27, \rc2 + vqrshrun.s16 \r0, q8, #\shift + vqrshrun.s16 \r2, q12, #\shift +.endm + +.macro rv40_qpel8_h shift +function put_rv40_qpel8_h_lp_packed_s\shift\()_neon +1: + vld1.8 {q2}, [r1], r2 + vld1.8 {q3}, [r1], r2 + qpel_lowpass_x2 d4, d5, d6, d7, d0, d1, \shift + vst1.8 {d4}, [r12,:64]! + vst1.8 {d6}, [r12,:64]! + subs r3, r3, #2 + bgt 1b + vld1.8 {q2}, [r1] + qpel_lowpass d4, d5, d0, d1, \shift + vst1.8 {d4}, [r12,:64]! + bx lr +endfunc +.endm + +.macro rv40_qpel8_v shift, type +function \type\()_rv40_qpel8_v_lp_packed_s\shift\()_neon + vld1.64 {d2}, [r1,:64]! + vld1.64 {d3}, [r1,:64]! + vld1.64 {d4}, [r1,:64]! + vld1.64 {d5}, [r1,:64]! + vld1.64 {d6}, [r1,:64]! + vld1.64 {d7}, [r1,:64]! + vld1.64 {d8}, [r1,:64]! + vld1.64 {d9}, [r1,:64]! + vld1.64 {d10}, [r1,:64]! + vld1.64 {d11}, [r1,:64]! + vld1.64 {d12}, [r1,:64]! + vld1.64 {d13}, [r1,:64]! + vld1.64 {d14}, [r1,:64]! + transpose_8x8 d2, d3, d4, d5, d6, d7, d8, d9 + transpose_8x8 d10, d11, d12, d13, d14, d15, d30, d31 + qpel_lowpass_x2 d2, d10, d3, d11, d0, d1, \shift + qpel_lowpass_x2 d4, d12, d5, d13, d0, d1, \shift + qpel_lowpass_x2 d6, d14, d7, d15, d0, d1, \shift + qpel_lowpass_x2 d8, d30, d9, d31, d0, d1, \shift + transpose_8x8 d2, d3, d4, d5, d6, d7, d8, d9 + .ifc \type,avg + vld1.64 d12, [r0,:64], r2 + vld1.64 d13, [r0,:64], r2 + vld1.64 d14, [r0,:64], r2 + vld1.64 d15, [r0,:64], r2 + vld1.64 d16, [r0,:64], r2 + vld1.64 d17, [r0,:64], r2 + vld1.64 d18, [r0,:64], r2 + vld1.64 d19, [r0,:64], r2 + sub r0, r0, r2, lsl #3 + vrhadd.u8 q1, q1, q6 + vrhadd.u8 q2, q2, q7 + vrhadd.u8 q3, q3, q8 + vrhadd.u8 q4, q4, q9 + .endif + vst1.64 d2, [r0,:64], r2 + vst1.64 d3, [r0,:64], r2 + vst1.64 d4, [r0,:64], r2 + vst1.64 d5, [r0,:64], r2 + vst1.64 d6, [r0,:64], r2 + vst1.64 d7, [r0,:64], r2 + vst1.64 d8, [r0,:64], r2 + vst1.64 d9, [r0,:64], r2 + bx lr +endfunc +.endm + + rv40_qpel8_h 5 + rv40_qpel8_h 6 + +.macro rv40_qpel type +function \type\()_rv40_qpel8_h_lowpass_neon + .ifc \type,avg + mov r12, r0 + .endif +1: + vld1.8 {q2}, [r1], r2 + vld1.8 {q3}, [r1], r2 + qpel_lowpass_x2 d4, d5, d6, d7, d0, d1, 6 + .ifc \type,avg + vld1.8 {d3}, [r12,:64], r2 + vld1.8 {d16}, [r12,:64], r2 + vrhadd.u8 d4, d4, d3 + vrhadd.u8 d6, d6, d16 + .endif + vst1.8 {d4}, [r0,:64], r2 + vst1.8 {d6}, [r0,:64], r2 + subs r3, r3, #2 + bgt 1b + bx lr +endfunc + +function \type\()_rv40_qpel8_v_lowpass_neon + vld1.64 {d2}, [r1], r2 + vld1.64 {d3}, [r1], r2 + vld1.64 {d4}, [r1], r2 + vld1.64 {d5}, [r1], r2 + vld1.64 {d6}, [r1], r2 + vld1.64 {d7}, [r1], r2 + vld1.64 {d8}, [r1], r2 + vld1.64 {d9}, [r1], r2 + vld1.64 {d10}, [r1], r2 + vld1.64 {d11}, [r1], r2 + vld1.64 {d12}, [r1], r2 + vld1.64 {d13}, [r1], r2 + vld1.64 {d14}, [r1] + transpose_8x8 d2, d3, d4, d5, d6, d7, d8, d9 + transpose_8x8 d10, d11, d12, d13, d14, d15, d30, d31 + qpel_lowpass_x2 d2, d10, d3, d11, d0, d1, 6 + qpel_lowpass_x2 d4, d12, d5, d13, d0, d1, 6 + qpel_lowpass_x2 d6, d14, d7, d15, d0, d1, 6 + qpel_lowpass_x2 d8, d30, d9, d31, d0, d1, 6 + transpose_8x8 d2, d3, d4, d5, d6, d7, d8, d9 + .ifc \type,avg + vld1.64 d12, [r0,:64], r2 + vld1.64 d13, [r0,:64], r2 + vld1.64 d14, [r0,:64], r2 + vld1.64 d15, [r0,:64], r2 + vld1.64 d16, [r0,:64], r2 + vld1.64 d17, [r0,:64], r2 + vld1.64 d18, [r0,:64], r2 + vld1.64 d19, [r0,:64], r2 + sub r0, r0, r2, lsl #3 + vrhadd.u8 q1, q1, q6 + vrhadd.u8 q2, q2, q7 + vrhadd.u8 q3, q3, q8 + vrhadd.u8 q4, q4, q9 + .endif + vst1.64 d2, [r0,:64], r2 + vst1.64 d3, [r0,:64], r2 + vst1.64 d4, [r0,:64], r2 + vst1.64 d5, [r0,:64], r2 + vst1.64 d6, [r0,:64], r2 + vst1.64 d7, [r0,:64], r2 + vst1.64 d8, [r0,:64], r2 + vst1.64 d9, [r0,:64], r2 + bx lr +endfunc + + rv40_qpel8_v 5, \type + rv40_qpel8_v 6, \type + +function ff_\type\()_rv40_qpel8_mc10_neon, export=1 + sub r1, r1, #2 + mov r3, #8 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + b \type\()_rv40_qpel8_h_lowpass_neon +endfunc + +function ff_\type\()_rv40_qpel8_mc30_neon, export=1 + sub r1, r1, #2 + mov r3, #8 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + b \type\()_rv40_qpel8_h_lowpass_neon +endfunc + +function ff_\type\()_rv40_qpel8_mc01_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub r1, r1, r2, lsl #1 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl \type\()_rv40_qpel8_v_lowpass_neon + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc11_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + add r1, sp, #7 + bic r1, r1, #7 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc21_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #20 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + add r1, sp, #7 + bic r1, r1, #7 + vmov.i8 d0, #52 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc31_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + bl put_rv40_qpel8_h_lp_packed_s6_neon + add r1, sp, #7 + bic r1, r1, #7 + vswp d0, d1 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc12_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + add r1, sp, #7 + bic r1, r1, #7 + vmov.i8 d0, #20 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc22_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #20 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + add r1, sp, #7 + bic r1, r1, #7 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc32_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + bl put_rv40_qpel8_h_lp_packed_s6_neon + add r1, sp, #7 + bic r1, r1, #7 + vmov.i8 d1, #20 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc03_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub r1, r1, r2, lsl #1 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + bl \type\()_rv40_qpel8_v_lowpass_neon + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc33_neon, export=1 + mov r3, #8 + b X(ff_\type\()_pixels8_xy2_neon) +endfunc + +function ff_\type\()_rv40_qpel8_mc13_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + add r1, sp, #7 + bic r1, r1, #7 + vswp d0, d1 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel8_mc23_neon, export=1 + push {r4, lr} + vpush {d8-d15} + sub sp, sp, #14*8 + add r12, sp, #7 + bic r12, r12, #7 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + mov r3, #12 + vmov.i8 d0, #20 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + add r1, sp, #7 + bic r1, r1, #7 + vmov.i8 d1, #52 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + add sp, sp, #14*8 + vpop {d8-d15} + pop {r4, pc} +endfunc + +function ff_\type\()_rv40_qpel16_mc10_neon, export=1 + vmov.i8 d0, #52 + vmov.i8 d1, #20 +.L\type\()_rv40_qpel16_h: + push {r1, lr} + sub r1, r1, #2 + mov r3, #16 + bl \type\()_rv40_qpel8_h_lowpass_neon + pop {r1, lr} + sub r0, r0, r2, lsl #4 + add r0, r0, #8 + add r1, r1, #6 + mov r3, #16 + b \type\()_rv40_qpel8_h_lowpass_neon +endfunc + +function ff_\type\()_rv40_qpel16_mc30_neon, export=1 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + b .L\type\()_rv40_qpel16_h +endfunc + +function ff_\type\()_rv40_qpel16_mc01_neon, export=1 + vmov.i8 d0, #52 + vmov.i8 d1, #20 +.L\type\()_rv40_qpel16_v: + sub r1, r1, r2, lsl #1 + push {r1, lr} + vpush {d8-d15} + bl \type\()_rv40_qpel8_v_lowpass_neon + sub r1, r1, r2, lsl #2 + bl \type\()_rv40_qpel8_v_lowpass_neon + ldr r1, [sp, #64] + sub r0, r0, r2, lsl #4 + add r0, r0, #8 + add r1, r1, #8 + bl \type\()_rv40_qpel8_v_lowpass_neon + sub r1, r1, r2, lsl #2 + bl \type\()_rv40_qpel8_v_lowpass_neon + vpop {d8-d15} + pop {r1, pc} +endfunc + +function ff_\type\()_rv40_qpel16_mc11_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon +.L\type\()_rv40_qpel16_v_s6: + add r1, sp, #7 + bic r1, r1, #7 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + sub r1, r1, #40 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + sub r0, r0, r2, lsl #4 + add r0, r0, #8 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + sub r1, r1, #40 + bl \type\()_rv40_qpel8_v_lp_packed_s6_neon + add sp, sp, #44*8 + vpop {d8-d15} + pop {r1, pc} +endfunc + +function ff_\type\()_rv40_qpel16_mc21_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #20 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + vmov.i8 d0, #52 + b .L\type\()_rv40_qpel16_v_s6 +endfunc + +function ff_\type\()_rv40_qpel16_mc31_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + bl put_rv40_qpel8_h_lp_packed_s6_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + vswp d0, d1 + b .L\type\()_rv40_qpel16_v_s6 +endfunc + +function ff_\type\()_rv40_qpel16_mc12_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + vmov.i8 d0, #20 +.L\type\()_rv40_qpel16_v_s5: + add r1, sp, #7 + bic r1, r1, #7 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + sub r1, r1, #40 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + sub r0, r0, r2, lsl #4 + add r0, r0, #8 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + sub r1, r1, #40 + bl \type\()_rv40_qpel8_v_lp_packed_s5_neon + add sp, sp, #44*8 + vpop {d8-d15} + pop {r1, pc} +endfunc + +function ff_\type\()_rv40_qpel16_mc22_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #20 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + b .L\type\()_rv40_qpel16_v_s5 +endfunc + +function ff_\type\()_rv40_qpel16_mc32_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + bl put_rv40_qpel8_h_lp_packed_s6_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + vmov.i8 d1, #20 + b .L\type\()_rv40_qpel16_v_s5 +endfunc + +function ff_\type\()_rv40_qpel16_mc03_neon, export=1 + vmov.i8 d0, #20 + vmov.i8 d1, #52 + b .L\type\()_rv40_qpel16_v +endfunc + +function ff_\type\()_rv40_qpel16_mc13_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #52 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s6_neon + vswp d0, d1 + b .L\type\()_rv40_qpel16_v_s6 +endfunc + +function ff_\type\()_rv40_qpel16_mc23_neon, export=1 + sub r1, r1, r2, lsl #1 + sub r1, r1, #2 + push {r1, lr} + vpush {d8-d15} + sub sp, sp, #44*8 + add r12, sp, #7 + bic r12, r12, #7 + mov r3, #20 + vmov.i8 d0, #20 + vmov.i8 d1, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + ldr r1, [sp, #416] + add r1, r1, #8 + mov r3, #20 + bl put_rv40_qpel8_h_lp_packed_s5_neon + vmov.i8 d1, #52 + b .L\type\()_rv40_qpel16_v_s6 +endfunc + +function ff_\type\()_rv40_qpel16_mc33_neon, export=1 + mov r3, #16 + b X(ff_\type\()_pixels16_xy2_neon) +endfunc +.endm + + rv40_qpel put + rv40_qpel avg + +.macro rv40_weight + vmovl.u8 q8, d2 + vmovl.u8 q9, d3 + vmovl.u8 q10, d4 + vmovl.u8 q11, d5 + vmull.u16 q2, d16, d0[2] + vmull.u16 q3, d17, d0[2] + vmull.u16 q8, d18, d0[2] + vmull.u16 q9, d19, d0[2] + vmull.u16 q12, d20, d0[0] + vmull.u16 q13, d21, d0[0] + vmull.u16 q14, d22, d0[0] + vmull.u16 q15, d23, d0[0] + vshrn.i32 d4, q2, #9 + vshrn.i32 d5, q3, #9 + vshrn.i32 d6, q8, #9 + vshrn.i32 d7, q9, #9 + vshrn.i32 d16, q12, #9 + vshrn.i32 d17, q13, #9 + vshrn.i32 d18, q14, #9 + vshrn.i32 d19, q15, #9 + vadd.u16 q2, q2, q8 + vadd.u16 q3, q3, q9 + vrshrn.i16 d2, q2, #5 + vrshrn.i16 d3, q3, #5 +.endm + +/* void ff_rv40_weight_func_16_neon(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int w1, int w2, int stride) */ +function ff_rv40_weight_func_16_neon, export=1 + ldr r12, [sp] + vmov d0, r3, r12 + ldr r12, [sp, #4] + mov r3, #16 +1: + vld1.8 {q1}, [r1,:128], r12 + vld1.8 {q2}, [r2,:128], r12 + rv40_weight + vst1.8 {q1}, [r0,:128], r12 + subs r3, r3, #1 + bne 1b + bx lr +endfunc + +/* void ff_rv40_weight_func_8_neon(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int w1, int w2, int stride) */ +function ff_rv40_weight_func_8_neon, export=1 + ldr r12, [sp] + vmov d0, r3, r12 + ldr r12, [sp, #4] + mov r3, #8 +1: + vld1.8 {d2}, [r1,:64], r12 + vld1.8 {d3}, [r1,:64], r12 + vld1.8 {d4}, [r2,:64], r12 + vld1.8 {d5}, [r2,:64], r12 + rv40_weight + vst1.8 {d2}, [r0,:64], r12 + vst1.8 {d3}, [r0,:64], r12 + subs r3, r3, #2 + bne 1b + bx lr +endfunc + +function ff_rv40_h_loop_filter_strength_neon, export=1 + pkhbt r2, r3, r2, lsl #18 + + ldr r3, [r0] + ldr_dpre r12, r0, r1 + teq r3, r12 + beq 1f + + sub r0, r0, r1, lsl #1 + + vld1.32 {d4[]}, [r0,:32], r1 @ -3 + vld1.32 {d0[]}, [r0,:32], r1 @ -2 + vld1.32 {d4[1]}, [r0,:32], r1 @ -1 + vld1.32 {d5[]}, [r0,:32], r1 @ 0 + vld1.32 {d1[]}, [r0,:32], r1 @ 1 + vld1.32 {d5[0]}, [r0,:32], r1 @ 2 + + vpaddl.u8 q8, q0 @ -2, -2, -2, -2, 1, 1, 1, 1 + vpaddl.u8 q9, q2 @ -3, -3, -1, -1, 2, 2, 0, 0 + vdup.32 d30, r2 @ beta2, beta << 2 + vpadd.u16 d16, d16, d17 @ -2, -2, 1, 1 + vpadd.u16 d18, d18, d19 @ -3, -1, 2, 0 + vabd.u16 d16, d18, d16 + vclt.u16 d16, d16, d30 + + ldrd r2, r3, [sp, #4] + vmovl.u16 q12, d16 + vtrn.16 d16, d17 + vshr.u32 q12, q12, #15 + ldr r0, [sp] + vst1.32 {d24[1]}, [r2,:32] + vst1.32 {d25[1]}, [r3,:32] + + cmp r0, #0 + it eq + bxeq lr + + vand d18, d16, d17 + vtrn.32 d18, d19 + vand d18, d18, d19 + vmov.u16 r0, d18[0] + bx lr +1: + ldrd r2, r3, [sp, #4] + mov r0, #0 + str r0, [r2] + str r0, [r3] + bx lr +endfunc + +function ff_rv40_v_loop_filter_strength_neon, export=1 + sub r0, r0, #3 + pkhbt r2, r3, r2, lsl #18 + + vld1.8 {d0}, [r0], r1 + vld1.8 {d1}, [r0], r1 + vld1.8 {d2}, [r0], r1 + vld1.8 {d3}, [r0], r1 + + vaddl.u8 q0, d0, d1 + vaddl.u8 q1, d2, d3 + vdup.32 q15, r2 + vadd.u16 q0, q0, q1 @ -3, -2, -1, 0, 1, 2 + vext.16 q1, q0, q0, #1 @ -2, -1, 0, 1, 2 + vabd.u16 q0, q1, q0 + vclt.u16 q0, q0, q15 + + ldrd r2, r3, [sp, #4] + vmovl.u16 q1, d0 + vext.16 d1, d0, d1, #3 + vshr.u32 q1, q1, #15 + ldr r0, [sp] + vst1.32 {d2[1]}, [r2,:32] + vst1.32 {d3[1]}, [r3,:32] + + cmp r0, #0 + it eq + bxeq lr + + vand d0, d0, d1 + vtrn.16 d0, d1 + vand d0, d0, d1 + vmov.u16 r0, d0[0] + bx lr +endfunc + +.macro rv40_weak_loop_filter + vdup.16 d30, r2 @ filter_p1 + vdup.16 d31, r3 @ filter_q1 + ldrd r2, r3, [sp] + vdup.16 d28, r2 @ alpha + vdup.16 d29, r3 @ beta + ldr r12, [sp, #8] + vdup.16 d25, r12 @ lim_p0q0 + ldrd r2, r3, [sp, #12] + vsubl.u8 q9, d5, d4 @ x, t + vabdl.u8 q8, d5, d4 @ x, abs(t) + vneg.s16 q15, q15 + vceq.i16 d16, d19, #0 @ !t + vshl.s16 d19, d19, #2 @ t << 2 + vmul.u16 d18, d17, d28 @ alpha * abs(t) + vand d24, d30, d31 @ filter_p1 & filter_q1 + vsubl.u8 q1, d0, d4 @ p1p2, p1p0 + vsubl.u8 q3, d1, d5 @ q1q2, q1q0 + vmov.i16 d22, #3 + vshr.u16 d18, d18, #7 + vadd.i16 d22, d22, d24 @ 3 - (filter_p1 & filter_q1) + vsubl.u8 q10, d0, d1 @ src[-2] - src[1] + vcle.u16 d18, d18, d22 + vand d20, d20, d24 + vneg.s16 d23, d25 @ -lim_p0q0 + vadd.s16 d19, d19, d20 + vbic d16, d18, d16 @ t && u <= 3 - (fp1 & fq1) + vtrn.32 d4, d5 @ -3, 2, -1, 0 + vrshr.s16 d19, d19, #3 + vmov d28, d29 @ beta + vswp d3, d6 @ q1q2, p1p0 + vmin.s16 d19, d19, d25 + vand d30, d30, d16 + vand d31, d31, d16 + vadd.s16 q10, q1, q3 @ p1p2 + p1p0, q1q2 + q1q0 + vmax.s16 d19, d19, d23 @ diff + vabs.s16 q1, q1 @ abs(p1p2), abs(q1q2) + vand d18, d19, d16 @ diff + vcle.u16 q1, q1, q14 + vneg.s16 d19, d18 @ -diff + vdup.16 d26, r3 @ lim_p1 + vaddw.u8 q2, q9, d5 @ src[-1]+diff, src[0]-diff + vhsub.s16 q11, q10, q9 + vand q1, q1, q15 + vqmovun.s16 d4, q2 @ -1, 0 + vand q9, q11, q1 + vdup.16 d27, r2 @ lim_q1 + vneg.s16 q9, q9 + vneg.s16 q14, q13 + vmin.s16 q9, q9, q13 + vtrn.32 d0, d1 @ -2, 1, -2, 1 + vmax.s16 q9, q9, q14 + vaddw.u8 q3, q9, d0 + vqmovun.s16 d5, q3 @ -2, 1 +.endm + +function ff_rv40_h_weak_loop_filter_neon, export=1 + sub r0, r0, r1, lsl #1 + sub r0, r0, r1 + + vld1.32 {d4[]}, [r0,:32], r1 + vld1.32 {d0[]}, [r0,:32], r1 + vld1.32 {d4[1]}, [r0,:32], r1 + vld1.32 {d5[]}, [r0,:32], r1 + vld1.32 {d1[]}, [r0,:32], r1 + vld1.32 {d5[0]}, [r0,:32] + + sub r0, r0, r1, lsl #2 + + rv40_weak_loop_filter + + vst1.32 {d5[0]}, [r0,:32], r1 + vst1.32 {d4[0]}, [r0,:32], r1 + vst1.32 {d4[1]}, [r0,:32], r1 + vst1.32 {d5[1]}, [r0,:32], r1 + + bx lr +endfunc + +function ff_rv40_v_weak_loop_filter_neon, export=1 + sub r12, r0, #3 + sub r0, r0, #2 + + vld1.8 {d4}, [r12], r1 + vld1.8 {d5}, [r12], r1 + vld1.8 {d2}, [r12], r1 + vld1.8 {d3}, [r12], r1 + + vtrn.16 q2, q1 + vtrn.8 d4, d5 + vtrn.8 d2, d3 + + vrev64.32 d5, d5 + vtrn.32 q2, q1 + vdup.32 d0, d3[0] + vdup.32 d1, d2[0] + + rv40_weak_loop_filter + + vtrn.32 q2, q3 + vswp d4, d5 + + vst4.8 {d4[0],d5[0],d6[0],d7[0]}, [r0], r1 + vst4.8 {d4[1],d5[1],d6[1],d7[1]}, [r0], r1 + vst4.8 {d4[2],d5[2],d6[2],d7[2]}, [r0], r1 + vst4.8 {d4[3],d5[3],d6[3],d7[3]}, [r0], r1 + + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/sbrdsp_init_arm.c b/ffmpeg/libavcodec/arm/sbrdsp_init_arm.c new file mode 100644 index 0000000..4da7967 --- /dev/null +++ b/ffmpeg/libavcodec/arm/sbrdsp_init_arm.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/arm/cpu.h" +#include "libavutil/attributes.h" +#include "libavcodec/sbrdsp.h" + +void ff_sbr_sum64x5_neon(float *z); +float ff_sbr_sum_square_neon(float (*x)[2], int n); +void ff_sbr_neg_odd_64_neon(float *x); +void ff_sbr_qmf_pre_shuffle_neon(float *z); +void ff_sbr_qmf_post_shuffle_neon(float W[32][2], const float *z); +void ff_sbr_qmf_deint_neg_neon(float *v, const float *src); +void ff_sbr_qmf_deint_bfly_neon(float *v, const float *src0, const float *src1); +void ff_sbr_hf_g_filt_neon(float (*Y)[2], const float (*X_high)[40][2], + const float *g_filt, int m_max, intptr_t ixh); +void ff_sbr_hf_gen_neon(float (*X_high)[2], const float (*X_low)[2], + const float alpha0[2], const float alpha1[2], + float bw, int start, int end); +void ff_sbr_autocorrelate_neon(const float x[40][2], float phi[3][2][2]); + +void ff_sbr_hf_apply_noise_0_neon(float Y[64][2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max); +void ff_sbr_hf_apply_noise_1_neon(float Y[64][2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max); +void ff_sbr_hf_apply_noise_2_neon(float Y[64][2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max); +void ff_sbr_hf_apply_noise_3_neon(float Y[64][2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max); + +av_cold void ff_sbrdsp_init_arm(SBRDSPContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + s->sum64x5 = ff_sbr_sum64x5_neon; + s->sum_square = ff_sbr_sum_square_neon; + s->neg_odd_64 = ff_sbr_neg_odd_64_neon; + s->qmf_pre_shuffle = ff_sbr_qmf_pre_shuffle_neon; + s->qmf_post_shuffle = ff_sbr_qmf_post_shuffle_neon; + s->qmf_deint_neg = ff_sbr_qmf_deint_neg_neon; + s->qmf_deint_bfly = ff_sbr_qmf_deint_bfly_neon; + s->hf_g_filt = ff_sbr_hf_g_filt_neon; + s->hf_gen = ff_sbr_hf_gen_neon; + s->autocorrelate = ff_sbr_autocorrelate_neon; + s->hf_apply_noise[0] = ff_sbr_hf_apply_noise_0_neon; + s->hf_apply_noise[1] = ff_sbr_hf_apply_noise_1_neon; + s->hf_apply_noise[2] = ff_sbr_hf_apply_noise_2_neon; + s->hf_apply_noise[3] = ff_sbr_hf_apply_noise_3_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/sbrdsp_neon.S b/ffmpeg/libavcodec/arm/sbrdsp_neon.S new file mode 100644 index 0000000..610397f --- /dev/null +++ b/ffmpeg/libavcodec/arm/sbrdsp_neon.S @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/arm/asm.S" + +function ff_sbr_sum64x5_neon, export=1 + push {lr} + add r1, r0, # 64*4 + add r2, r0, #128*4 + add r3, r0, #192*4 + add lr, r0, #256*4 + mov r12, #64 +1: + vld1.32 {q0}, [r0,:128] + vld1.32 {q1}, [r1,:128]! + vadd.f32 q0, q0, q1 + vld1.32 {q2}, [r2,:128]! + vadd.f32 q0, q0, q2 + vld1.32 {q3}, [r3,:128]! + vadd.f32 q0, q0, q3 + vld1.32 {q8}, [lr,:128]! + vadd.f32 q0, q0, q8 + vst1.32 {q0}, [r0,:128]! + subs r12, #4 + bgt 1b + pop {pc} +endfunc + +function ff_sbr_sum_square_neon, export=1 + vmov.f32 q0, #0.0 +1: + vld1.32 {q1}, [r0,:128]! + vmla.f32 q0, q1, q1 + subs r1, r1, #2 + bgt 1b + vadd.f32 d0, d0, d1 + vpadd.f32 d0, d0, d0 +NOVFP vmov.32 r0, d0[0] + bx lr +endfunc + +function ff_sbr_neg_odd_64_neon, export=1 + mov r1, r0 + vmov.i32 q8, #1<<31 + vld2.32 {q0,q1}, [r0,:128]! + veor q1, q1, q8 + vld2.32 {q2,q3}, [r0,:128]! + .rept 3 + vst2.32 {q0,q1}, [r1,:128]! + veor q3, q3, q8 + vld2.32 {q0,q1}, [r0,:128]! + vst2.32 {q2,q3}, [r1,:128]! + veor q1, q1, q8 + vld2.32 {q2,q3}, [r0,:128]! + .endr + veor q3, q3, q8 + vst2.32 {q0,q1}, [r1,:128]! + vst2.32 {q2,q3}, [r1,:128]! + bx lr +endfunc + +function ff_sbr_qmf_pre_shuffle_neon, export=1 + add r1, r0, #60*4 + add r2, r0, #64*4 + vld1.32 {d0}, [r0,:64]! + vst1.32 {d0}, [r2,:64]! + mov r3, #-16 + mov r12, #24 + vmov.i32 q8, #1<<31 + vld1.32 {q0}, [r1,:128], r3 + vld1.32 {d2}, [r0,:64]! +1: + vld1.32 {d3,d4}, [r0,:128]! + vrev64.32 q0, q0 + vld1.32 {q9}, [r1,:128], r3 + veor q0, q0, q8 + vld1.32 {d5,d6}, [r0,:128]! + vswp d0, d1 + vrev64.32 q9, q9 + vst2.32 {q0,q1}, [r2,:64]! + vmov q10, q2 + veor q9, q9, q8 + vmov d2, d6 + vswp d18, d19 + vld1.32 {q0}, [r1,:128], r3 + vst2.32 {q9,q10}, [r2,:64]! + subs r12, r12, #8 + bgt 1b + vld1.32 {d3,d4}, [r0,:128]! + vrev64.32 q0, q0 + vld1.32 {q9}, [r1,:128], r3 + veor q0, q0, q8 + vld1.32 {d5}, [r0,:64]! + vswp d0, d1 + vrev64.32 q9, q9 + vst2.32 {q0,q1}, [r2,:64]! + vswp d4, d5 + veor q1, q9, q8 + vst2.32 {d3,d5}, [r2,:64]! + vst2.32 {d2[0],d4[0]}, [r2,:64]! + bx lr +endfunc + +function ff_sbr_qmf_post_shuffle_neon, export=1 + add r2, r1, #60*4 + mov r3, #-16 + mov r12, #32 + vmov.i32 q8, #1<<31 + vld1.32 {q0}, [r2,:128], r3 + vld1.32 {q1}, [r1,:128]! +1: + pld [r2, #-32] + vrev64.32 q0, q0 + vswp d2, d3 + veor q0, q0, q8 + vld1.32 {q2}, [r2,:128], r3 + vld1.32 {q3}, [r1,:128]! + vst2.32 {d1,d3}, [r0,:128]! + vst2.32 {d0,d2}, [r0,:128]! + pld [r2, #-32] + vrev64.32 q2, q2 + vswp d6, d7 + veor q2, q2, q8 + vld1.32 {q0}, [r2,:128], r3 + vld1.32 {q1}, [r1,:128]! + vst2.32 {d5,d7}, [r0,:128]! + vst2.32 {d4,d6}, [r0,:128]! + subs r12, r12, #8 + bgt 1b + bx lr +endfunc + +function ff_sbr_qmf_deint_neg_neon, export=1 + add r1, r1, #60*4 + add r2, r0, #62*4 + mov r3, #-16 + mov r12, #32 + vmov.i32 d2, #1<<31 +1: + vld2.32 {d0,d1}, [r1,:128], r3 + veor d0, d0, d2 + vrev64.32 d1, d1 + vst1.32 {d0}, [r2,:64] + vst1.32 {d1}, [r0,:64]! + sub r2, r2, #8 + subs r12, r12, #2 + bgt 1b + bx lr +endfunc + +function ff_sbr_qmf_deint_bfly_neon, export=1 + push {lr} + add r2, r2, #60*4 + add r3, r0, #124*4 + mov r12, #64 + mov lr, #-16 +1: + vld1.32 {q0}, [r1,:128]! + vld1.32 {q1}, [r2,:128], lr + vrev64.32 q2, q0 + vrev64.32 q3, q1 + vadd.f32 d3, d4, d3 + vadd.f32 d2, d5, d2 + vsub.f32 d0, d0, d7 + vsub.f32 d1, d1, d6 + vst1.32 {q1}, [r3,:128], lr + vst1.32 {q0}, [r0,:128]! + subs r12, r12, #4 + bgt 1b + pop {pc} +endfunc + +function ff_sbr_hf_g_filt_neon, export=1 + ldr r12, [sp] + add r1, r1, r12, lsl #3 + mov r12, #40*2*4 + sub r3, r3, #1 + vld2.32 {d2[],d3[]},[r2,:64]! + vld1.32 {d0}, [r1,:64], r12 +1: + vld1.32 {d1}, [r1,:64], r12 + vmul.f32 q3, q0, q1 + vld2.32 {d2[],d3[]},[r2,:64]! + vld1.32 {d0}, [r1,:64], r12 + vst1.32 {q3}, [r0,:64]! + subs r3, r3, #2 + bgt 1b + it lt + bxlt lr + vmul.f32 d0, d0, d2 + vst1.32 {d0}, [r0,:64]! + bx lr +endfunc + +function ff_sbr_hf_gen_neon, export=1 +NOVFP vld1.32 {d1[]}, [sp,:32] +VFP vdup.32 d1, d0[0] + vmul.f32 d0, d1, d1 + vld1.32 {d3}, [r2,:64] + vld1.32 {d2}, [r3,:64] + vmul.f32 q0, q0, q1 + ldrd r2, r3, [sp, #4*!HAVE_VFP_ARGS] + vtrn.32 d0, d1 + vneg.f32 d18, d1 + vtrn.32 d18, d1 + add r0, r0, r2, lsl #3 + add r1, r1, r2, lsl #3 + sub r1, r1, #2*8 + sub r3, r3, r2 + vld1.32 {q1}, [r1,:128]! +1: + vld1.32 {q3}, [r1,:128]! + vrev64.32 q2, q1 + vmov q8, q3 + vrev64.32 d20, d3 + vrev64.32 d21, d6 + vmla.f32 q3, q1, d0[0] + vmla.f32 d6, d4, d18 + vmla.f32 d7, d20, d18 + vmla.f32 d6, d3, d0[1] + vmla.f32 d7, d16, d0[1] + vmla.f32 d6, d5, d1 + vmla.f32 d7, d21, d1 + vmov q1, q8 + vst1.32 {q3}, [r0,:128]! + subs r3, r3, #2 + bgt 1b + bx lr +endfunc + +function ff_sbr_autocorrelate_neon, export=1 + vld1.32 {q0}, [r0,:128]! + vmov.f32 q1, #0.0 + vmov.f32 q3, #0.0 + vmov.f32 d20, #0.0 + vmul.f32 d21, d1, d1 + vmov q8, q0 + vmov q11, q0 + mov r12, #36 +1: + vld1.32 {q2}, [r0,:128]! + vrev64.32 q12, q2 + vmla.f32 q10, q2, q2 + vmla.f32 d2, d1, d4 + vmla.f32 d3, d1, d24 + vmla.f32 d6, d0, d4 + vmla.f32 d7, d0, d24 + vmla.f32 d2, d4, d5 + vmla.f32 d3, d4, d25 + vmla.f32 d6, d1, d5 + vmla.f32 d7, d1, d25 + vmov q0, q2 + subs r12, r12, #2 + bgt 1b + vld1.32 {q2}, [r0,:128]! + vrev64.32 q12, q2 + vmla.f32 d2, d1, d4 + vmla.f32 d3, d1, d24 + vmla.f32 d6, d0, d4 + vmla.f32 d7, d0, d24 + vadd.f32 d20, d20, d21 + vrev64.32 d18, d17 + vmla.f32 d6, d1, d5 + vmla.f32 d7, d1, d25 + vmov q0, q1 + vmla.f32 d0, d16, d17 + vmla.f32 d1, d16, d18 + vmla.f32 d2, d4, d5 + vmla.f32 d3, d4, d25 + vneg.f32 s15, s15 + vmov d21, d20 + vpadd.f32 d0, d0, d2 + vpadd.f32 d7, d6, d7 + vtrn.32 d1, d3 + vsub.f32 d6, d1, d3 + vmla.f32 d20, d22, d22 + vmla.f32 d21, d4, d4 + vtrn.32 d0, d6 + vpadd.f32 d20, d20, d21 + vst1.32 {q3}, [r1,:128]! + vst1.32 {d20[1]}, [r1,:32] + add r1, r1, #2*4 + vst1.32 {d0}, [r1,:64] + add r1, r1, #4*4 + vst1.32 {d20[0]}, [r1,:32] + bx lr +endfunc + +function ff_sbr_hf_apply_noise_0_neon, export=1 + vmov.i32 d3, #0 +.Lhf_apply_noise_0: + push {r4,lr} + movrelx r4, X(ff_sbr_noise_table) + ldr r12, [sp, #12] + add r3, r3, #1 + bfc r3, #9, #23 + sub r12, r12, #1 +1: + add lr, r4, r3, lsl #3 + vld2.32 {q0}, [r0,:64] + vld2.32 {q3}, [lr,:64] + vld1.32 {d2}, [r1,:64]! + vld1.32 {d18}, [r2,:64]! + vceq.f32 d16, d2, #0 + veor d2, d2, d3 + vmov q2, q0 + vmla.f32 d0, d6, d18 + vmla.f32 d1, d7, d18 + vadd.f32 d4, d4, d2 + add r3, r3, #2 + bfc r3, #9, #23 + vbif d0, d4, d16 + vbif d1, d5, d16 + vst2.32 {q0}, [r0,:64]! + subs r12, r12, #2 + bgt 1b + blt 2f + add lr, r4, r3, lsl #3 + vld1.32 {d0}, [r0,:64] + vld1.32 {d6}, [lr,:64] + vld1.32 {d2[]}, [r1,:32]! + vld1.32 {d3[]}, [r2,:32]! + vceq.f32 d4, d2, #0 + veor d2, d2, d3 + vmov d1, d0 + vmla.f32 d0, d6, d3 + vadd.f32 s2, s2, s4 + vbif d0, d1, d4 + vst1.32 {d0}, [r0,:64]! +2: + pop {r4,pc} +endfunc + +function ff_sbr_hf_apply_noise_1_neon, export=1 + ldr r12, [sp] + push {r4,lr} + lsl r12, r12, #31 + eor lr, r12, #1<<31 + vmov d3, r12, lr +.Lhf_apply_noise_1: + movrelx r4, X(ff_sbr_noise_table) + ldr r12, [sp, #12] + add r3, r3, #1 + bfc r3, #9, #23 + sub r12, r12, #1 +1: + add lr, r4, r3, lsl #3 + vld2.32 {q0}, [r0,:64] + vld2.32 {q3}, [lr,:64] + vld1.32 {d2}, [r1,:64]! + vld1.32 {d18}, [r2,:64]! + vceq.f32 d16, d2, #0 + veor d2, d2, d3 + vmov q2, q0 + vmla.f32 d0, d6, d18 + vmla.f32 d1, d7, d18 + vadd.f32 d5, d5, d2 + add r3, r3, #2 + bfc r3, #9, #23 + vbif d0, d4, d16 + vbif d1, d5, d16 + vst2.32 {q0}, [r0,:64]! + subs r12, r12, #2 + bgt 1b + blt 2f + add lr, r4, r3, lsl #3 + vld1.32 {d0}, [r0,:64] + vld1.32 {d6}, [lr,:64] + vld1.32 {d2[]}, [r1,:32]! + vld1.32 {d18[]}, [r2,:32]! + vceq.f32 d4, d2, #0 + veor d2, d2, d3 + vmov d1, d0 + vmla.f32 d0, d6, d18 + vadd.f32 s3, s3, s5 + vbif d0, d1, d4 + vst1.32 {d0}, [r0,:64]! +2: + pop {r4,pc} +endfunc + +function ff_sbr_hf_apply_noise_2_neon, export=1 + vmov.i32 d3, #1<<31 + b .Lhf_apply_noise_0 +endfunc + +function ff_sbr_hf_apply_noise_3_neon, export=1 + ldr r12, [sp] + push {r4,lr} + lsl r12, r12, #31 + eor lr, r12, #1<<31 + vmov d3, lr, r12 + b .Lhf_apply_noise_1 +endfunc diff --git a/ffmpeg/libavcodec/arm/simple_idct_arm.S b/ffmpeg/libavcodec/arm/simple_idct_arm.S new file mode 100644 index 0000000..dd1c815 --- /dev/null +++ b/ffmpeg/libavcodec/arm/simple_idct_arm.S @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2002 Frederic 'dilb' Boulay + * + * Author: Frederic Boulay + * + * The function defined in this file is derived from the simple_idct function + * from the libavcodec library part of the FFmpeg project. + * + * 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 "libavutil/arm/asm.S" + +/* useful constants for the algorithm */ +#define W1 22725 +#define W2 21407 +#define W3 19266 +#define W4 16383 +#define W5 12873 +#define W6 8867 +#define W7 4520 +#define MASK_MSHW 0xFFFF0000 + +#define ROW_SHIFT 11 +#define ROW_SHIFT2MSHW (16-11) +#define COL_SHIFT 20 +#define ROW_SHIFTED_1 1024 /* 1<< (ROW_SHIFT-1) */ +#define COL_SHIFTED_1 524288 /* 1<< (COL_SHIFT-1) */ + + +function ff_simple_idct_arm, export=1 + @@ void simple_idct_arm(int16_t *block) + @@ save stack for reg needed (take all of them), + @@ R0-R3 are scratch regs, so no need to save them, but R0 contains the pointer to block + @@ so it must not be overwritten, if it is not saved!! + @@ R12 is another scratch register, so it should not be saved too + @@ save all registers + stmfd sp!, {r4-r11, r14} @ R14 is also called LR + @@ at this point, R0=block, other registers are free. + add r14, r0, #112 @ R14=&block[8*7], better start from the last row, and decrease the value until row=0, i.e. R12=block. + @@ add 2 temporary variables in the stack: R0 and R14 + sub sp, sp, #8 @ allow 2 local variables + str r0, [sp, #0] @ save block in sp[0] + @@ stack status + @@ sp+4 free + @@ sp+0 R0 (block) + + + @@ at this point, R0=block, R14=&block[56], R12=__const_ptr_, R1-R11 free + + +__row_loop: + @@ read the row and check if it is null, almost null, or not, according to strongarm specs, it is not necessary to optimize ldr accesses (i.e. split 32bits in 2 16bits words), at least it gives more usable registers :) + ldr r1, [r14, #0] @ R1=(int32)(R12)[0]=ROWr32[0] (relative row cast to a 32b pointer) + ldr r2, [r14, #4] @ R2=(int32)(R12)[1]=ROWr32[1] + ldr r3, [r14, #8] @ R3=ROWr32[2] + ldr r4, [r14, #12] @ R4=ROWr32[3] + @@ check if the words are null, if all of them are null, then proceed with next row (branch __end_row_loop), + @@ if ROWr16[0] is the only one not null, then proceed with this special case (branch __almost_empty_row) + @@ else follow the complete algorithm. + @@ at this point, R0=block, R14=&block[n], R12=__const_ptr_, R1=ROWr32[0], R2=ROWr32[1], + @@ R3=ROWr32[2], R4=ROWr32[3], R5-R11 free + orr r5, r4, r3 @ R5=R4 | R3 + orr r5, r5, r2 @ R5=R4 | R3 | R2 + orrs r6, r5, r1 @ Test R5 | R1 (the aim is to check if everything is null) + beq __end_row_loop + mov r7, r1, asr #16 @ R7=R1>>16=ROWr16[1] (evaluate it now, as it could be useful later) + ldrsh r6, [r14, #0] @ R6=ROWr16[0] + orrs r5, r5, r7 @ R5=R4 | R3 | R2 | R7 + beq __almost_empty_row + +__b_evaluation: + @@ at this point, R0=block (temp), R1(free), R2=ROWr32[1], R3=ROWr32[2], R4=ROWr32[3], + @@ R5=(temp), R6=ROWr16[0], R7=ROWr16[1], R8-R11 free, + @@ R12=__const_ptr_, R14=&block[n] + @@ to save some registers/calls, proceed with b0-b3 first, followed by a0-a3 + + @@ MUL16(b0, W1, row[1]); + @@ MUL16(b1, W3, row[1]); + @@ MUL16(b2, W5, row[1]); + @@ MUL16(b3, W7, row[1]); + @@ MAC16(b0, W3, row[3]); + @@ MAC16(b1, -W7, row[3]); + @@ MAC16(b2, -W1, row[3]); + @@ MAC16(b3, -W5, row[3]); + ldr r8, =W1 @ R8=W1 + mov r2, r2, asr #16 @ R2=ROWr16[3] + mul r0, r8, r7 @ R0=W1*ROWr16[1]=b0 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + ldr r9, =W3 @ R9=W3 + ldr r10, =W5 @ R10=W5 + mul r1, r9, r7 @ R1=W3*ROWr16[1]=b1 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + ldr r11, =W7 @ R11=W7 + mul r5, r10, r7 @ R5=W5*ROWr16[1]=b2 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + mul r7, r11, r7 @ R7=W7*ROWr16[1]=b3 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + teq r2, #0 @ if null avoid muls + itttt ne + mlane r0, r9, r2, r0 @ R0+=W3*ROWr16[3]=b0 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + rsbne r2, r2, #0 @ R2=-ROWr16[3] + mlane r1, r11, r2, r1 @ R1-=W7*ROWr16[3]=b1 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + mlane r5, r8, r2, r5 @ R5-=W1*ROWr16[3]=b2 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + it ne + mlane r7, r10, r2, r7 @ R7-=W5*ROWr16[3]=b3 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + + @@ at this point, R0=b0, R1=b1, R2 (free), R3=ROWr32[2], R4=ROWr32[3], + @@ R5=b2, R6=ROWr16[0], R7=b3, R8=W1, R9=W3, R10=W5, R11=W7, + @@ R12=__const_ptr_, R14=&block[n] + @@ temp = ((uint32_t*)row)[2] | ((uint32_t*)row)[3]; + @@ if (temp != 0) {} + orrs r2, r3, r4 @ R2=ROWr32[2] | ROWr32[3] + beq __end_b_evaluation + + @@ at this point, R0=b0, R1=b1, R2 (free), R3=ROWr32[2], R4=ROWr32[3], + @@ R5=b2, R6=ROWr16[0], R7=b3, R8=W1, R9=W3, R10=W5, R11=W7, + @@ R12=__const_ptr_, R14=&block[n] + @@ MAC16(b0, W5, row[5]); + @@ MAC16(b2, W7, row[5]); + @@ MAC16(b3, W3, row[5]); + @@ MAC16(b1, -W1, row[5]); + @@ MAC16(b0, W7, row[7]); + @@ MAC16(b2, W3, row[7]); + @@ MAC16(b3, -W1, row[7]); + @@ MAC16(b1, -W5, row[7]); + mov r3, r3, asr #16 @ R3=ROWr16[5] + teq r3, #0 @ if null avoid muls + it ne + mlane r0, r10, r3, r0 @ R0+=W5*ROWr16[5]=b0 + mov r4, r4, asr #16 @ R4=ROWr16[7] + itttt ne + mlane r5, r11, r3, r5 @ R5+=W7*ROWr16[5]=b2 + mlane r7, r9, r3, r7 @ R7+=W3*ROWr16[5]=b3 + rsbne r3, r3, #0 @ R3=-ROWr16[5] + mlane r1, r8, r3, r1 @ R7-=W1*ROWr16[5]=b1 + @@ R3 is free now + teq r4, #0 @ if null avoid muls + itttt ne + mlane r0, r11, r4, r0 @ R0+=W7*ROWr16[7]=b0 + mlane r5, r9, r4, r5 @ R5+=W3*ROWr16[7]=b2 + rsbne r4, r4, #0 @ R4=-ROWr16[7] + mlane r7, r8, r4, r7 @ R7-=W1*ROWr16[7]=b3 + it ne + mlane r1, r10, r4, r1 @ R1-=W5*ROWr16[7]=b1 + @@ R4 is free now +__end_b_evaluation: + @@ at this point, R0=b0, R1=b1, R2=ROWr32[2] | ROWr32[3] (tmp), R3 (free), R4 (free), + @@ R5=b2, R6=ROWr16[0], R7=b3, R8 (free), R9 (free), R10 (free), R11 (free), + @@ R12=__const_ptr_, R14=&block[n] + +__a_evaluation: + @@ a0 = (W4 * row[0]) + (1 << (ROW_SHIFT - 1)); + @@ a1 = a0 + W6 * row[2]; + @@ a2 = a0 - W6 * row[2]; + @@ a3 = a0 - W2 * row[2]; + @@ a0 = a0 + W2 * row[2]; + ldr r9, =W4 @ R9=W4 + mul r6, r9, r6 @ R6=W4*ROWr16[0] + ldr r10, =W6 @ R10=W6 + ldrsh r4, [r14, #4] @ R4=ROWr16[2] (a3 not defined yet) + add r6, r6, #ROW_SHIFTED_1 @ R6=W4*ROWr16[0] + 1<<(ROW_SHIFT-1) (a0) + + mul r11, r10, r4 @ R11=W6*ROWr16[2] + ldr r8, =W2 @ R8=W2 + sub r3, r6, r11 @ R3=a0-W6*ROWr16[2] (a2) + @@ temp = ((uint32_t*)row)[2] | ((uint32_t*)row)[3]; + @@ if (temp != 0) {} + teq r2, #0 + beq __end_bef_a_evaluation + + add r2, r6, r11 @ R2=a0+W6*ROWr16[2] (a1) + mul r11, r8, r4 @ R11=W2*ROWr16[2] + sub r4, r6, r11 @ R4=a0-W2*ROWr16[2] (a3) + add r6, r6, r11 @ R6=a0+W2*ROWr16[2] (a0) + + + @@ at this point, R0=b0, R1=b1, R2=a1, R3=a2, R4=a3, + @@ R5=b2, R6=a0, R7=b3, R8=W2, R9=W4, R10=W6, R11 (free), + @@ R12=__const_ptr_, R14=&block[n] + + + @@ a0 += W4*row[4] + @@ a1 -= W4*row[4] + @@ a2 -= W4*row[4] + @@ a3 += W4*row[4] + ldrsh r11, [r14, #8] @ R11=ROWr16[4] + teq r11, #0 @ if null avoid muls + it ne + mulne r11, r9, r11 @ R11=W4*ROWr16[4] + @@ R9 is free now + ldrsh r9, [r14, #12] @ R9=ROWr16[6] + itttt ne + addne r6, r6, r11 @ R6+=W4*ROWr16[4] (a0) + subne r2, r2, r11 @ R2-=W4*ROWr16[4] (a1) + subne r3, r3, r11 @ R3-=W4*ROWr16[4] (a2) + addne r4, r4, r11 @ R4+=W4*ROWr16[4] (a3) + @@ W6 alone is no more useful, save W2*ROWr16[6] in it instead + teq r9, #0 @ if null avoid muls + itttt ne + mulne r11, r10, r9 @ R11=W6*ROWr16[6] + addne r6, r6, r11 @ R6+=W6*ROWr16[6] (a0) + mulne r10, r8, r9 @ R10=W2*ROWr16[6] + @@ a0 += W6*row[6]; + @@ a3 -= W6*row[6]; + @@ a1 -= W2*row[6]; + @@ a2 += W2*row[6]; + subne r4, r4, r11 @ R4-=W6*ROWr16[6] (a3) + itt ne + subne r2, r2, r10 @ R2-=W2*ROWr16[6] (a1) + addne r3, r3, r10 @ R3+=W2*ROWr16[6] (a2) + +__end_a_evaluation: + @@ at this point, R0=b0, R1=b1, R2=a1, R3=a2, R4=a3, + @@ R5=b2, R6=a0, R7=b3, R8 (free), R9 (free), R10 (free), R11 (free), + @@ R12=__const_ptr_, R14=&block[n] + @@ row[0] = (a0 + b0) >> ROW_SHIFT; + @@ row[1] = (a1 + b1) >> ROW_SHIFT; + @@ row[2] = (a2 + b2) >> ROW_SHIFT; + @@ row[3] = (a3 + b3) >> ROW_SHIFT; + @@ row[4] = (a3 - b3) >> ROW_SHIFT; + @@ row[5] = (a2 - b2) >> ROW_SHIFT; + @@ row[6] = (a1 - b1) >> ROW_SHIFT; + @@ row[7] = (a0 - b0) >> ROW_SHIFT; + add r8, r6, r0 @ R8=a0+b0 + add r9, r2, r1 @ R9=a1+b1 + @@ put 2 16 bits half-words in a 32bits word + @@ ROWr32[0]=ROWr16[0] | (ROWr16[1]<<16) (only Little Endian compliant then!!!) + ldr r10, =MASK_MSHW @ R10=0xFFFF0000 + and r9, r10, r9, lsl #ROW_SHIFT2MSHW @ R9=0xFFFF0000 & ((a1+b1)<<5) + mvn r11, r10 @ R11= NOT R10= 0x0000FFFF + and r8, r11, r8, asr #ROW_SHIFT @ R8=0x0000FFFF & ((a0+b0)>>11) + orr r8, r8, r9 + str r8, [r14, #0] + + add r8, r3, r5 @ R8=a2+b2 + add r9, r4, r7 @ R9=a3+b3 + and r9, r10, r9, lsl #ROW_SHIFT2MSHW @ R9=0xFFFF0000 & ((a3+b3)<<5) + and r8, r11, r8, asr #ROW_SHIFT @ R8=0x0000FFFF & ((a2+b2)>>11) + orr r8, r8, r9 + str r8, [r14, #4] + + sub r8, r4, r7 @ R8=a3-b3 + sub r9, r3, r5 @ R9=a2-b2 + and r9, r10, r9, lsl #ROW_SHIFT2MSHW @ R9=0xFFFF0000 & ((a2-b2)<<5) + and r8, r11, r8, asr #ROW_SHIFT @ R8=0x0000FFFF & ((a3-b3)>>11) + orr r8, r8, r9 + str r8, [r14, #8] + + sub r8, r2, r1 @ R8=a1-b1 + sub r9, r6, r0 @ R9=a0-b0 + and r9, r10, r9, lsl #ROW_SHIFT2MSHW @ R9=0xFFFF0000 & ((a0-b0)<<5) + and r8, r11, r8, asr #ROW_SHIFT @ R8=0x0000FFFF & ((a1-b1)>>11) + orr r8, r8, r9 + str r8, [r14, #12] + + bal __end_row_loop + +__almost_empty_row: + @@ the row was empty, except ROWr16[0], now, management of this special case + @@ at this point, R0=block, R14=&block[n], R12=__const_ptr_, R1=ROWr32[0], R2=ROWr32[1], + @@ R3=ROWr32[2], R4=ROWr32[3], R5=(temp), R6=ROWr16[0], R7=ROWr16[1], + @@ R8=0xFFFF (temp), R9-R11 free + mov r8, #0x10000 @ R8=0xFFFF (2 steps needed!) it saves a ldr call (because of delay run). + sub r8, r8, #1 @ R8 is now ready. + and r5, r8, r6, lsl #3 @ R5=R8 & (R6<<3)= (ROWr16[0]<<3) & 0xFFFF + orr r5, r5, r5, lsl #16 @ R5=R5 | (R5<<16) + str r5, [r14, #0] @ R14[0]=ROWr32[0]=R5 + str r5, [r14, #4] @ R14[4]=ROWr32[1]=R5 + str r5, [r14, #8] @ R14[8]=ROWr32[2]=R5 + str r5, [r14, #12] @ R14[12]=ROWr32[3]=R5 + +__end_row_loop: + @@ at this point, R0-R11 (free) + @@ R12=__const_ptr_, R14=&block[n] + ldr r0, [sp, #0] @ R0=block + teq r0, r14 @ compare current &block[8*n] to block, when block is reached, the loop is finished. + sub r14, r14, #16 + bne __row_loop + + + + @@ at this point, R0=block, R1-R11 (free) + @@ R12=__const_ptr_, R14=&block[n] + add r14, r0, #14 @ R14=&block[7], better start from the last col, and decrease the value until col=0, i.e. R14=block. +__col_loop: + +__b_evaluation2: + @@ at this point, R0=block (temp), R1-R11 (free) + @@ R12=__const_ptr_, R14=&block[n] + @@ proceed with b0-b3 first, followed by a0-a3 + @@ MUL16(b0, W1, col[8x1]); + @@ MUL16(b1, W3, col[8x1]); + @@ MUL16(b2, W5, col[8x1]); + @@ MUL16(b3, W7, col[8x1]); + @@ MAC16(b0, W3, col[8x3]); + @@ MAC16(b1, -W7, col[8x3]); + @@ MAC16(b2, -W1, col[8x3]); + @@ MAC16(b3, -W5, col[8x3]); + ldr r8, =W1 @ R8=W1 + ldrsh r7, [r14, #16] + mul r0, r8, r7 @ R0=W1*ROWr16[1]=b0 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + ldr r9, =W3 @ R9=W3 + ldr r10, =W5 @ R10=W5 + mul r1, r9, r7 @ R1=W3*ROWr16[1]=b1 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + ldr r11, =W7 @ R11=W7 + mul r5, r10, r7 @ R5=W5*ROWr16[1]=b2 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + ldrsh r2, [r14, #48] + mul r7, r11, r7 @ R7=W7*ROWr16[1]=b3 (ROWr16[1] must be the second arg, to have the possibility to save 1 cycle) + teq r2, #0 @ if 0, then avoid muls + itttt ne + mlane r0, r9, r2, r0 @ R0+=W3*ROWr16[3]=b0 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + rsbne r2, r2, #0 @ R2=-ROWr16[3] + mlane r1, r11, r2, r1 @ R1-=W7*ROWr16[3]=b1 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + mlane r5, r8, r2, r5 @ R5-=W1*ROWr16[3]=b2 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + it ne + mlane r7, r10, r2, r7 @ R7-=W5*ROWr16[3]=b3 (ROWr16[3] must be the second arg, to have the possibility to save 1 cycle) + + @@ at this point, R0=b0, R1=b1, R2 (free), R3 (free), R4 (free), + @@ R5=b2, R6 (free), R7=b3, R8=W1, R9=W3, R10=W5, R11=W7, + @@ R12=__const_ptr_, R14=&block[n] + @@ MAC16(b0, W5, col[5x8]); + @@ MAC16(b2, W7, col[5x8]); + @@ MAC16(b3, W3, col[5x8]); + @@ MAC16(b1, -W1, col[5x8]); + @@ MAC16(b0, W7, col[7x8]); + @@ MAC16(b2, W3, col[7x8]); + @@ MAC16(b3, -W1, col[7x8]); + @@ MAC16(b1, -W5, col[7x8]); + ldrsh r3, [r14, #80] @ R3=COLr16[5x8] + teq r3, #0 @ if 0 then avoid muls + itttt ne + mlane r0, r10, r3, r0 @ R0+=W5*ROWr16[5x8]=b0 + mlane r5, r11, r3, r5 @ R5+=W7*ROWr16[5x8]=b2 + mlane r7, r9, r3, r7 @ R7+=W3*ROWr16[5x8]=b3 + rsbne r3, r3, #0 @ R3=-ROWr16[5x8] + ldrsh r4, [r14, #112] @ R4=COLr16[7x8] + it ne + mlane r1, r8, r3, r1 @ R7-=W1*ROWr16[5x8]=b1 + @@ R3 is free now + teq r4, #0 @ if 0 then avoid muls + itttt ne + mlane r0, r11, r4, r0 @ R0+=W7*ROWr16[7x8]=b0 + mlane r5, r9, r4, r5 @ R5+=W3*ROWr16[7x8]=b2 + rsbne r4, r4, #0 @ R4=-ROWr16[7x8] + mlane r7, r8, r4, r7 @ R7-=W1*ROWr16[7x8]=b3 + it ne + mlane r1, r10, r4, r1 @ R1-=W5*ROWr16[7x8]=b1 + @@ R4 is free now +__end_b_evaluation2: + @@ at this point, R0=b0, R1=b1, R2 (free), R3 (free), R4 (free), + @@ R5=b2, R6 (free), R7=b3, R8 (free), R9 (free), R10 (free), R11 (free), + @@ R12=__const_ptr_, R14=&block[n] + +__a_evaluation2: + @@ a0 = (W4 * col[8x0]) + (1 << (COL_SHIFT - 1)); + @@ a1 = a0 + W6 * row[2]; + @@ a2 = a0 - W6 * row[2]; + @@ a3 = a0 - W2 * row[2]; + @@ a0 = a0 + W2 * row[2]; + ldrsh r6, [r14, #0] + ldr r9, =W4 @ R9=W4 + mul r6, r9, r6 @ R6=W4*ROWr16[0] + ldr r10, =W6 @ R10=W6 + ldrsh r4, [r14, #32] @ R4=ROWr16[2] (a3 not defined yet) + add r6, r6, #COL_SHIFTED_1 @ R6=W4*ROWr16[0] + 1<<(COL_SHIFT-1) (a0) + mul r11, r10, r4 @ R11=W6*ROWr16[2] + ldr r8, =W2 @ R8=W2 + add r2, r6, r11 @ R2=a0+W6*ROWr16[2] (a1) + sub r3, r6, r11 @ R3=a0-W6*ROWr16[2] (a2) + mul r11, r8, r4 @ R11=W2*ROWr16[2] + sub r4, r6, r11 @ R4=a0-W2*ROWr16[2] (a3) + add r6, r6, r11 @ R6=a0+W2*ROWr16[2] (a0) + + @@ at this point, R0=b0, R1=b1, R2=a1, R3=a2, R4=a3, + @@ R5=b2, R6=a0, R7=b3, R8=W2, R9=W4, R10=W6, R11 (free), + @@ R12=__const_ptr_, R14=&block[n] + @@ a0 += W4*row[4] + @@ a1 -= W4*row[4] + @@ a2 -= W4*row[4] + @@ a3 += W4*row[4] + ldrsh r11, [r14, #64] @ R11=ROWr16[4] + teq r11, #0 @ if null avoid muls + itttt ne + mulne r11, r9, r11 @ R11=W4*ROWr16[4] + @@ R9 is free now + addne r6, r6, r11 @ R6+=W4*ROWr16[4] (a0) + subne r2, r2, r11 @ R2-=W4*ROWr16[4] (a1) + subne r3, r3, r11 @ R3-=W4*ROWr16[4] (a2) + ldrsh r9, [r14, #96] @ R9=ROWr16[6] + it ne + addne r4, r4, r11 @ R4+=W4*ROWr16[4] (a3) + @@ W6 alone is no more useful, save W2*ROWr16[6] in it instead + teq r9, #0 @ if null avoid muls + itttt ne + mulne r11, r10, r9 @ R11=W6*ROWr16[6] + addne r6, r6, r11 @ R6+=W6*ROWr16[6] (a0) + mulne r10, r8, r9 @ R10=W2*ROWr16[6] + @@ a0 += W6*row[6]; + @@ a3 -= W6*row[6]; + @@ a1 -= W2*row[6]; + @@ a2 += W2*row[6]; + subne r4, r4, r11 @ R4-=W6*ROWr16[6] (a3) + itt ne + subne r2, r2, r10 @ R2-=W2*ROWr16[6] (a1) + addne r3, r3, r10 @ R3+=W2*ROWr16[6] (a2) +__end_a_evaluation2: + @@ at this point, R0=b0, R1=b1, R2=a1, R3=a2, R4=a3, + @@ R5=b2, R6=a0, R7=b3, R8 (free), R9 (free), R10 (free), R11 (free), + @@ R12=__const_ptr_, R14=&block[n] + @@ col[0 ] = ((a0 + b0) >> COL_SHIFT); + @@ col[8 ] = ((a1 + b1) >> COL_SHIFT); + @@ col[16] = ((a2 + b2) >> COL_SHIFT); + @@ col[24] = ((a3 + b3) >> COL_SHIFT); + @@ col[32] = ((a3 - b3) >> COL_SHIFT); + @@ col[40] = ((a2 - b2) >> COL_SHIFT); + @@ col[48] = ((a1 - b1) >> COL_SHIFT); + @@ col[56] = ((a0 - b0) >> COL_SHIFT); + @@@@@ no optimization here @@@@@ + add r8, r6, r0 @ R8=a0+b0 + add r9, r2, r1 @ R9=a1+b1 + mov r8, r8, asr #COL_SHIFT + mov r9, r9, asr #COL_SHIFT + strh r8, [r14, #0] + strh r9, [r14, #16] + add r8, r3, r5 @ R8=a2+b2 + add r9, r4, r7 @ R9=a3+b3 + mov r8, r8, asr #COL_SHIFT + mov r9, r9, asr #COL_SHIFT + strh r8, [r14, #32] + strh r9, [r14, #48] + sub r8, r4, r7 @ R8=a3-b3 + sub r9, r3, r5 @ R9=a2-b2 + mov r8, r8, asr #COL_SHIFT + mov r9, r9, asr #COL_SHIFT + strh r8, [r14, #64] + strh r9, [r14, #80] + sub r8, r2, r1 @ R8=a1-b1 + sub r9, r6, r0 @ R9=a0-b0 + mov r8, r8, asr #COL_SHIFT + mov r9, r9, asr #COL_SHIFT + strh r8, [r14, #96] + strh r9, [r14, #112] + +__end_col_loop: + @@ at this point, R0-R11 (free) + @@ R12=__const_ptr_, R14=&block[n] + ldr r0, [sp, #0] @ R0=block + teq r0, r14 @ compare current &block[n] to block, when block is reached, the loop is finished. + sub r14, r14, #2 + bne __col_loop + + + + +__end_simple_idct_arm: + @@ restore registers to previous status! + add sp, sp, #8 @@ the local variables! + ldmfd sp!, {r4-r11, r15} @@ update PC with LR content. + + + +@@ kind of sub-function, here not to overload the common case. +__end_bef_a_evaluation: + add r2, r6, r11 @ R2=a0+W6*ROWr16[2] (a1) + mul r11, r8, r4 @ R11=W2*ROWr16[2] + sub r4, r6, r11 @ R4=a0-W2*ROWr16[2] (a3) + add r6, r6, r11 @ R6=a0+W2*ROWr16[2] (a0) + bal __end_a_evaluation diff --git a/ffmpeg/libavcodec/arm/simple_idct_armv5te.S b/ffmpeg/libavcodec/arm/simple_idct_armv5te.S new file mode 100644 index 0000000..d1f10b7 --- /dev/null +++ b/ffmpeg/libavcodec/arm/simple_idct_armv5te.S @@ -0,0 +1,620 @@ +/* + * Simple IDCT + * + * Copyright (c) 2001 Michael Niedermayer + * Copyright (c) 2006 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +#define W1 22725 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W2 21407 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W3 19266 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W4 16383 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W5 12873 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W6 8867 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W7 4520 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define ROW_SHIFT 11 +#define COL_SHIFT 20 + +#define W13 (W1 | (W3 << 16)) +#define W26 (W2 | (W6 << 16)) +#define W57 (W5 | (W7 << 16)) + +function idct_row_armv5te + str lr, [sp, #-4]! + + ldrd v1, v2, [a1, #8] + ldrd a3, a4, [a1] /* a3 = row[1:0], a4 = row[3:2] */ + orrs v1, v1, v2 + itt eq + cmpeq v1, a4 + cmpeq v1, a3, lsr #16 + beq row_dc_only + + mov v1, #(1<<(ROW_SHIFT-1)) + mov ip, #16384 + sub ip, ip, #1 /* ip = W4 */ + smlabb v1, ip, a3, v1 /* v1 = W4*row[0]+(1<<(RS-1)) */ + ldr ip, =W26 /* ip = W2 | (W6 << 16) */ + smultb a2, ip, a4 + smulbb lr, ip, a4 + add v2, v1, a2 + sub v3, v1, a2 + sub v4, v1, lr + add v1, v1, lr + + ldr ip, =W13 /* ip = W1 | (W3 << 16) */ + ldr lr, =W57 /* lr = W5 | (W7 << 16) */ + smulbt v5, ip, a3 + smultt v6, lr, a4 + smlatt v5, ip, a4, v5 + smultt a2, ip, a3 + smulbt v7, lr, a3 + sub v6, v6, a2 + smulbt a2, ip, a4 + smultt fp, lr, a3 + sub v7, v7, a2 + smulbt a2, lr, a4 + ldrd a3, a4, [a1, #8] /* a3=row[5:4] a4=row[7:6] */ + sub fp, fp, a2 + + orrs a2, a3, a4 + beq 1f + + smlabt v5, lr, a3, v5 + smlabt v6, ip, a3, v6 + smlatt v5, lr, a4, v5 + smlabt v6, lr, a4, v6 + smlatt v7, lr, a3, v7 + smlatt fp, ip, a3, fp + smulbt a2, ip, a4 + smlatt v7, ip, a4, v7 + sub fp, fp, a2 + + ldr ip, =W26 /* ip = W2 | (W6 << 16) */ + mov a2, #16384 + sub a2, a2, #1 /* a2 = W4 */ + smulbb a2, a2, a3 /* a2 = W4*row[4] */ + smultb lr, ip, a4 /* lr = W6*row[6] */ + add v1, v1, a2 /* v1 += W4*row[4] */ + add v1, v1, lr /* v1 += W6*row[6] */ + add v4, v4, a2 /* v4 += W4*row[4] */ + sub v4, v4, lr /* v4 -= W6*row[6] */ + smulbb lr, ip, a4 /* lr = W2*row[6] */ + sub v2, v2, a2 /* v2 -= W4*row[4] */ + sub v2, v2, lr /* v2 -= W2*row[6] */ + sub v3, v3, a2 /* v3 -= W4*row[4] */ + add v3, v3, lr /* v3 += W2*row[6] */ + +1: add a2, v1, v5 + mov a3, a2, lsr #11 + bic a3, a3, #0x1f0000 + sub a2, v2, v6 + mov a2, a2, lsr #11 + add a3, a3, a2, lsl #16 + add a2, v3, v7 + mov a4, a2, lsr #11 + bic a4, a4, #0x1f0000 + add a2, v4, fp + mov a2, a2, lsr #11 + add a4, a4, a2, lsl #16 + strd a3, a4, [a1] + + sub a2, v4, fp + mov a3, a2, lsr #11 + bic a3, a3, #0x1f0000 + sub a2, v3, v7 + mov a2, a2, lsr #11 + add a3, a3, a2, lsl #16 + add a2, v2, v6 + mov a4, a2, lsr #11 + bic a4, a4, #0x1f0000 + sub a2, v1, v5 + mov a2, a2, lsr #11 + add a4, a4, a2, lsl #16 + strd a3, a4, [a1, #8] + + ldr pc, [sp], #4 + +row_dc_only: + orr a3, a3, a3, lsl #16 + bic a3, a3, #0xe000 + mov a3, a3, lsl #3 + mov a4, a3 + strd a3, a4, [a1] + strd a3, a4, [a1, #8] + + ldr pc, [sp], #4 +endfunc + + .macro idct_col + ldr a4, [a1] /* a4 = col[1:0] */ + mov ip, #16384 + sub ip, ip, #1 /* ip = W4 */ +#if 0 + mov v1, #(1<<(COL_SHIFT-1)) + smlabt v2, ip, a4, v1 /* v2 = W4*col[1] + (1<<(COL_SHIFT-1)) */ + smlabb v1, ip, a4, v1 /* v1 = W4*col[0] + (1<<(COL_SHIFT-1)) */ + ldr a4, [a1, #(16*4)] +#else + mov v1, #((1<<(COL_SHIFT-1))/W4) /* this matches the C version */ + add v2, v1, a4, asr #16 + rsb v2, v2, v2, lsl #14 + mov a4, a4, lsl #16 + add v1, v1, a4, asr #16 + ldr a4, [a1, #(16*4)] + rsb v1, v1, v1, lsl #14 +#endif + + smulbb lr, ip, a4 + smulbt a3, ip, a4 + sub v3, v1, lr + sub v5, v1, lr + add v7, v1, lr + add v1, v1, lr + sub v4, v2, a3 + sub v6, v2, a3 + add fp, v2, a3 + ldr ip, =W26 + ldr a4, [a1, #(16*2)] + add v2, v2, a3 + + smulbb lr, ip, a4 + smultb a3, ip, a4 + add v1, v1, lr + sub v7, v7, lr + add v3, v3, a3 + sub v5, v5, a3 + smulbt lr, ip, a4 + smultt a3, ip, a4 + add v2, v2, lr + sub fp, fp, lr + add v4, v4, a3 + ldr a4, [a1, #(16*6)] + sub v6, v6, a3 + + smultb lr, ip, a4 + smulbb a3, ip, a4 + add v1, v1, lr + sub v7, v7, lr + sub v3, v3, a3 + add v5, v5, a3 + smultt lr, ip, a4 + smulbt a3, ip, a4 + add v2, v2, lr + sub fp, fp, lr + sub v4, v4, a3 + add v6, v6, a3 + + stmfd sp!, {v1, v2, v3, v4, v5, v6, v7, fp} + + ldr ip, =W13 + ldr a4, [a1, #(16*1)] + ldr lr, =W57 + smulbb v1, ip, a4 + smultb v3, ip, a4 + smulbb v5, lr, a4 + smultb v7, lr, a4 + smulbt v2, ip, a4 + smultt v4, ip, a4 + smulbt v6, lr, a4 + smultt fp, lr, a4 + rsb v4, v4, #0 + ldr a4, [a1, #(16*3)] + rsb v3, v3, #0 + + smlatb v1, ip, a4, v1 + smlatb v3, lr, a4, v3 + smulbb a3, ip, a4 + smulbb a2, lr, a4 + sub v5, v5, a3 + sub v7, v7, a2 + smlatt v2, ip, a4, v2 + smlatt v4, lr, a4, v4 + smulbt a3, ip, a4 + smulbt a2, lr, a4 + sub v6, v6, a3 + ldr a4, [a1, #(16*5)] + sub fp, fp, a2 + + smlabb v1, lr, a4, v1 + smlabb v3, ip, a4, v3 + smlatb v5, lr, a4, v5 + smlatb v7, ip, a4, v7 + smlabt v2, lr, a4, v2 + smlabt v4, ip, a4, v4 + smlatt v6, lr, a4, v6 + ldr a3, [a1, #(16*7)] + smlatt fp, ip, a4, fp + + smlatb v1, lr, a3, v1 + smlabb v3, lr, a3, v3 + smlatb v5, ip, a3, v5 + smulbb a4, ip, a3 + smlatt v2, lr, a3, v2 + sub v7, v7, a4 + smlabt v4, lr, a3, v4 + smulbt a4, ip, a3 + smlatt v6, ip, a3, v6 + sub fp, fp, a4 + .endm + +function idct_col_armv5te + str lr, [sp, #-4]! + + idct_col + + ldmfd sp!, {a3, a4} + adds a2, a3, v1 + mov a2, a2, lsr #20 + it mi + orrmi a2, a2, #0xf000 + add ip, a4, v2 + mov ip, ip, asr #20 + orr a2, a2, ip, lsl #16 + str a2, [a1] + subs a3, a3, v1 + mov a2, a3, lsr #20 + it mi + orrmi a2, a2, #0xf000 + sub a4, a4, v2 + mov a4, a4, asr #20 + orr a2, a2, a4, lsl #16 + ldmfd sp!, {a3, a4} + str a2, [a1, #(16*7)] + + subs a2, a3, v3 + mov a2, a2, lsr #20 + it mi + orrmi a2, a2, #0xf000 + sub ip, a4, v4 + mov ip, ip, asr #20 + orr a2, a2, ip, lsl #16 + str a2, [a1, #(16*1)] + adds a3, a3, v3 + mov a2, a3, lsr #20 + it mi + orrmi a2, a2, #0xf000 + add a4, a4, v4 + mov a4, a4, asr #20 + orr a2, a2, a4, lsl #16 + ldmfd sp!, {a3, a4} + str a2, [a1, #(16*6)] + + adds a2, a3, v5 + mov a2, a2, lsr #20 + it mi + orrmi a2, a2, #0xf000 + add ip, a4, v6 + mov ip, ip, asr #20 + orr a2, a2, ip, lsl #16 + str a2, [a1, #(16*2)] + subs a3, a3, v5 + mov a2, a3, lsr #20 + it mi + orrmi a2, a2, #0xf000 + sub a4, a4, v6 + mov a4, a4, asr #20 + orr a2, a2, a4, lsl #16 + ldmfd sp!, {a3, a4} + str a2, [a1, #(16*5)] + + adds a2, a3, v7 + mov a2, a2, lsr #20 + it mi + orrmi a2, a2, #0xf000 + add ip, a4, fp + mov ip, ip, asr #20 + orr a2, a2, ip, lsl #16 + str a2, [a1, #(16*3)] + subs a3, a3, v7 + mov a2, a3, lsr #20 + it mi + orrmi a2, a2, #0xf000 + sub a4, a4, fp + mov a4, a4, asr #20 + orr a2, a2, a4, lsl #16 + str a2, [a1, #(16*4)] + + ldr pc, [sp], #4 +endfunc + +.macro clip dst, src:vararg + movs \dst, \src + it mi + movmi \dst, #0 + cmp \dst, #255 + it gt + movgt \dst, #255 +.endm + +.macro aclip dst, src:vararg + adds \dst, \src + it mi + movmi \dst, #0 + cmp \dst, #255 + it gt + movgt \dst, #255 +.endm + +function idct_col_put_armv5te + str lr, [sp, #-4]! + + idct_col + + ldmfd sp!, {a3, a4} + ldr lr, [sp, #32] + add a2, a3, v1 + clip a2, a2, asr #20 + add ip, a4, v2 + clip ip, ip, asr #20 + orr a2, a2, ip, lsl #8 + sub a3, a3, v1 + clip a3, a3, asr #20 + sub a4, a4, v2 + clip a4, a4, asr #20 + ldr v1, [sp, #28] + strh a2, [v1] + add a2, v1, #2 + str a2, [sp, #28] + orr a2, a3, a4, lsl #8 + rsb v2, lr, lr, lsl #3 + ldmfd sp!, {a3, a4} + strh_pre a2, v2, v1 + + sub a2, a3, v3 + clip a2, a2, asr #20 + sub ip, a4, v4 + clip ip, ip, asr #20 + orr a2, a2, ip, lsl #8 + strh_pre a2, v1, lr + add a3, a3, v3 + clip a2, a3, asr #20 + add a4, a4, v4 + clip a4, a4, asr #20 + orr a2, a2, a4, lsl #8 + ldmfd sp!, {a3, a4} + strh_dpre a2, v2, lr + + add a2, a3, v5 + clip a2, a2, asr #20 + add ip, a4, v6 + clip ip, ip, asr #20 + orr a2, a2, ip, lsl #8 + strh_pre a2, v1, lr + sub a3, a3, v5 + clip a2, a3, asr #20 + sub a4, a4, v6 + clip a4, a4, asr #20 + orr a2, a2, a4, lsl #8 + ldmfd sp!, {a3, a4} + strh_dpre a2, v2, lr + + add a2, a3, v7 + clip a2, a2, asr #20 + add ip, a4, fp + clip ip, ip, asr #20 + orr a2, a2, ip, lsl #8 + strh a2, [v1, lr] + sub a3, a3, v7 + clip a2, a3, asr #20 + sub a4, a4, fp + clip a4, a4, asr #20 + orr a2, a2, a4, lsl #8 + strh_dpre a2, v2, lr + + ldr pc, [sp], #4 +endfunc + +function idct_col_add_armv5te + str lr, [sp, #-4]! + + idct_col + + ldr lr, [sp, #36] + + ldmfd sp!, {a3, a4} + ldrh ip, [lr] + add a2, a3, v1 + sub a3, a3, v1 + and v1, ip, #255 + aclip a2, v1, a2, asr #20 + add v1, a4, v2 + mov v1, v1, asr #20 + aclip v1, v1, ip, lsr #8 + orr a2, a2, v1, lsl #8 + ldr v1, [sp, #32] + sub a4, a4, v2 + rsb v2, v1, v1, lsl #3 + ldrh_pre ip, v2, lr + strh a2, [lr] + and a2, ip, #255 + aclip a3, a2, a3, asr #20 + mov a4, a4, asr #20 + aclip a4, a4, ip, lsr #8 + add a2, lr, #2 + str a2, [sp, #28] + orr a2, a3, a4, lsl #8 + strh a2, [v2] + + ldmfd sp!, {a3, a4} + ldrh_pre ip, lr, v1 + sub a2, a3, v3 + add a3, a3, v3 + and v3, ip, #255 + aclip a2, v3, a2, asr #20 + sub v3, a4, v4 + mov v3, v3, asr #20 + aclip v3, v3, ip, lsr #8 + orr a2, a2, v3, lsl #8 + add a4, a4, v4 + ldrh_dpre ip, v2, v1 + strh a2, [lr] + and a2, ip, #255 + aclip a3, a2, a3, asr #20 + mov a4, a4, asr #20 + aclip a4, a4, ip, lsr #8 + orr a2, a3, a4, lsl #8 + strh a2, [v2] + + ldmfd sp!, {a3, a4} + ldrh_pre ip, lr, v1 + add a2, a3, v5 + sub a3, a3, v5 + and v3, ip, #255 + aclip a2, v3, a2, asr #20 + add v3, a4, v6 + mov v3, v3, asr #20 + aclip v3, v3, ip, lsr #8 + orr a2, a2, v3, lsl #8 + sub a4, a4, v6 + ldrh_dpre ip, v2, v1 + strh a2, [lr] + and a2, ip, #255 + aclip a3, a2, a3, asr #20 + mov a4, a4, asr #20 + aclip a4, a4, ip, lsr #8 + orr a2, a3, a4, lsl #8 + strh a2, [v2] + + ldmfd sp!, {a3, a4} + ldrh_pre ip, lr, v1 + add a2, a3, v7 + sub a3, a3, v7 + and v3, ip, #255 + aclip a2, v3, a2, asr #20 + add v3, a4, fp + mov v3, v3, asr #20 + aclip v3, v3, ip, lsr #8 + orr a2, a2, v3, lsl #8 + sub a4, a4, fp + ldrh_dpre ip, v2, v1 + strh a2, [lr] + and a2, ip, #255 + aclip a3, a2, a3, asr #20 + mov a4, a4, asr #20 + aclip a4, a4, ip, lsr #8 + orr a2, a3, a4, lsl #8 + strh a2, [v2] + + ldr pc, [sp], #4 +endfunc + +function ff_simple_idct_armv5te, export=1 + stmfd sp!, {v1, v2, v3, v4, v5, v6, v7, fp, lr} + + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + + sub a1, a1, #(16*7) + + bl idct_col_armv5te + add a1, a1, #4 + bl idct_col_armv5te + add a1, a1, #4 + bl idct_col_armv5te + add a1, a1, #4 + bl idct_col_armv5te + + ldmfd sp!, {v1, v2, v3, v4, v5, v6, v7, fp, pc} +endfunc + +function ff_simple_idct_add_armv5te, export=1 + stmfd sp!, {a1, a2, v1, v2, v3, v4, v5, v6, v7, fp, lr} + + mov a1, a3 + + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + + sub a1, a1, #(16*7) + + bl idct_col_add_armv5te + add a1, a1, #4 + bl idct_col_add_armv5te + add a1, a1, #4 + bl idct_col_add_armv5te + add a1, a1, #4 + bl idct_col_add_armv5te + + add sp, sp, #8 + ldmfd sp!, {v1, v2, v3, v4, v5, v6, v7, fp, pc} +endfunc + +function ff_simple_idct_put_armv5te, export=1 + stmfd sp!, {a1, a2, v1, v2, v3, v4, v5, v6, v7, fp, lr} + + mov a1, a3 + + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + add a1, a1, #16 + bl idct_row_armv5te + + sub a1, a1, #(16*7) + + bl idct_col_put_armv5te + add a1, a1, #4 + bl idct_col_put_armv5te + add a1, a1, #4 + bl idct_col_put_armv5te + add a1, a1, #4 + bl idct_col_put_armv5te + + add sp, sp, #8 + ldmfd sp!, {v1, v2, v3, v4, v5, v6, v7, fp, pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/simple_idct_armv6.S b/ffmpeg/libavcodec/arm/simple_idct_armv6.S new file mode 100644 index 0000000..79cf5d4 --- /dev/null +++ b/ffmpeg/libavcodec/arm/simple_idct_armv6.S @@ -0,0 +1,425 @@ +/* + * Simple IDCT + * + * Copyright (c) 2001 Michael Niedermayer + * Copyright (c) 2007 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +#define W1 22725 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W2 21407 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W3 19266 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W4 16383 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W5 12873 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W6 8867 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define W7 4520 /* cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 */ +#define ROW_SHIFT 11 +#define COL_SHIFT 20 + +#define W13 (W1 | (W3 << 16)) +#define W26 (W2 | (W6 << 16)) +#define W42 (W4 | (W2 << 16)) +#define W42n (-W4&0xffff | (-W2 << 16)) +#define W46 (W4 | (W6 << 16)) +#define W57 (W5 | (W7 << 16)) + +/* + Compute partial IDCT of single row. + shift = left-shift amount + r0 = source address + r2 = row[2,0] <= 2 cycles + r3 = row[3,1] + ip = w42 <= 2 cycles + + Output in registers r4--r11 +*/ + .macro idct_row shift + ldr lr, =W46 /* lr = W4 | (W6 << 16) */ + mov r1, #(1<<(\shift-1)) + smlad r4, r2, ip, r1 + smlsd r7, r2, ip, r1 + ldr ip, =W13 /* ip = W1 | (W3 << 16) */ + ldr r10,=W57 /* r10 = W5 | (W7 << 16) */ + smlad r5, r2, lr, r1 + smlsd r6, r2, lr, r1 + + smuad r8, r3, ip /* r8 = B0 = W1*row[1] + W3*row[3] */ + smusdx r11,r3, r10 /* r11 = B3 = W7*row[1] - W5*row[3] */ + ldr lr, [r0, #12] /* lr = row[7,5] */ + pkhtb r2, ip, r10,asr #16 /* r3 = W7 | (W3 << 16) */ + pkhbt r1, ip, r10,lsl #16 /* r1 = W1 | (W5 << 16) */ + smusdx r9, r2, r3 /* r9 = -B1 = W7*row[3] - W3*row[1] */ + smlad r8, lr, r10,r8 /* B0 += W5*row[5] + W7*row[7] */ + smusdx r10,r3, r1 /* r10 = B2 = W5*row[1] - W1*row[3] */ + + ldr r3, =W42n /* r3 = -W4 | (-W2 << 16) */ + smlad r10,lr, r2, r10 /* B2 += W7*row[5] + W3*row[7] */ + ldr r2, [r0, #4] /* r2 = row[6,4] */ + smlsdx r11,lr, ip, r11 /* B3 += W3*row[5] - W1*row[7] */ + ldr ip, =W46 /* ip = W4 | (W6 << 16) */ + smlad r9, lr, r1, r9 /* B1 -= W1*row[5] + W5*row[7] */ + + smlad r5, r2, r3, r5 /* A1 += -W4*row[4] - W2*row[6] */ + smlsd r6, r2, r3, r6 /* A2 += -W4*row[4] + W2*row[6] */ + smlad r4, r2, ip, r4 /* A0 += W4*row[4] + W6*row[6] */ + smlsd r7, r2, ip, r7 /* A3 += W4*row[4] - W6*row[6] */ + .endm + +/* + Compute partial IDCT of half row. + shift = left-shift amount + r2 = row[2,0] + r3 = row[3,1] + ip = w42 + + Output in registers r4--r11 +*/ + .macro idct_row4 shift + ldr lr, =W46 /* lr = W4 | (W6 << 16) */ + ldr r10,=W57 /* r10 = W5 | (W7 << 16) */ + mov r1, #(1<<(\shift-1)) + smlad r4, r2, ip, r1 + smlsd r7, r2, ip, r1 + ldr ip, =W13 /* ip = W1 | (W3 << 16) */ + smlad r5, r2, lr, r1 + smlsd r6, r2, lr, r1 + smusdx r11,r3, r10 /* r11 = B3 = W7*row[1] - W5*row[3] */ + smuad r8, r3, ip /* r8 = B0 = W1*row[1] + W3*row[3] */ + pkhtb r2, ip, r10,asr #16 /* r3 = W7 | (W3 << 16) */ + pkhbt r1, ip, r10,lsl #16 /* r1 = W1 | (W5 << 16) */ + smusdx r9, r2, r3 /* r9 = -B1 = W7*row[3] - W3*row[1] */ + smusdx r10,r3, r1 /* r10 = B2 = W5*row[1] - W1*row[3] */ + .endm + +/* + Compute final part of IDCT single row without shift. + Input in registers r4--r11 + Output in registers ip, r4--r6, lr, r8--r10 +*/ + .macro idct_finish + add ip, r4, r8 /* r1 = A0 + B0 */ + sub lr, r4, r8 /* r2 = A0 - B0 */ + sub r4, r5, r9 /* r2 = A1 + B1 */ + add r8, r5, r9 /* r2 = A1 - B1 */ + add r5, r6, r10 /* r1 = A2 + B2 */ + sub r9, r6, r10 /* r1 = A2 - B2 */ + add r6, r7, r11 /* r2 = A3 + B3 */ + sub r10,r7, r11 /* r2 = A3 - B3 */ + .endm + +/* + Compute final part of IDCT single row. + shift = right-shift amount + Input/output in registers r4--r11 +*/ + .macro idct_finish_shift shift + add r3, r4, r8 /* r3 = A0 + B0 */ + sub r2, r4, r8 /* r2 = A0 - B0 */ + mov r4, r3, asr #\shift + mov r8, r2, asr #\shift + + sub r3, r5, r9 /* r3 = A1 + B1 */ + add r2, r5, r9 /* r2 = A1 - B1 */ + mov r5, r3, asr #\shift + mov r9, r2, asr #\shift + + add r3, r6, r10 /* r3 = A2 + B2 */ + sub r2, r6, r10 /* r2 = A2 - B2 */ + mov r6, r3, asr #\shift + mov r10,r2, asr #\shift + + add r3, r7, r11 /* r3 = A3 + B3 */ + sub r2, r7, r11 /* r2 = A3 - B3 */ + mov r7, r3, asr #\shift + mov r11,r2, asr #\shift + .endm + +/* + Compute final part of IDCT single row, saturating results at 8 bits. + shift = right-shift amount + Input/output in registers r4--r11 +*/ + .macro idct_finish_shift_sat shift + add r3, r4, r8 /* r3 = A0 + B0 */ + sub ip, r4, r8 /* ip = A0 - B0 */ + usat r4, #8, r3, asr #\shift + usat r8, #8, ip, asr #\shift + + sub r3, r5, r9 /* r3 = A1 + B1 */ + add ip, r5, r9 /* ip = A1 - B1 */ + usat r5, #8, r3, asr #\shift + usat r9, #8, ip, asr #\shift + + add r3, r6, r10 /* r3 = A2 + B2 */ + sub ip, r6, r10 /* ip = A2 - B2 */ + usat r6, #8, r3, asr #\shift + usat r10,#8, ip, asr #\shift + + add r3, r7, r11 /* r3 = A3 + B3 */ + sub ip, r7, r11 /* ip = A3 - B3 */ + usat r7, #8, r3, asr #\shift + usat r11,#8, ip, asr #\shift + .endm + +/* + Compute IDCT of single row, storing as column. + r0 = source + r1 = dest +*/ +function idct_row_armv6 + push {lr} + + ldr lr, [r0, #12] /* lr = row[7,5] */ + ldr ip, [r0, #4] /* ip = row[6,4] */ + ldr r3, [r0, #8] /* r3 = row[3,1] */ + ldr r2, [r0] /* r2 = row[2,0] */ + orrs lr, lr, ip + itt eq + cmpeq lr, r3 + cmpeq lr, r2, lsr #16 + beq 1f + push {r1} + ldr ip, =W42 /* ip = W4 | (W2 << 16) */ + cmp lr, #0 + beq 2f + + idct_row ROW_SHIFT + b 3f + +2: idct_row4 ROW_SHIFT + +3: pop {r1} + idct_finish_shift ROW_SHIFT + + strh r4, [r1] + strh r5, [r1, #(16*2)] + strh r6, [r1, #(16*4)] + strh r7, [r1, #(16*6)] + strh r11,[r1, #(16*1)] + strh r10,[r1, #(16*3)] + strh r9, [r1, #(16*5)] + strh r8, [r1, #(16*7)] + + pop {pc} + +1: mov r2, r2, lsl #3 + strh r2, [r1] + strh r2, [r1, #(16*2)] + strh r2, [r1, #(16*4)] + strh r2, [r1, #(16*6)] + strh r2, [r1, #(16*1)] + strh r2, [r1, #(16*3)] + strh r2, [r1, #(16*5)] + strh r2, [r1, #(16*7)] + pop {pc} +endfunc + +/* + Compute IDCT of single column, read as row. + r0 = source + r1 = dest +*/ +function idct_col_armv6 + push {r1, lr} + + ldr r2, [r0] /* r2 = row[2,0] */ + ldr ip, =W42 /* ip = W4 | (W2 << 16) */ + ldr r3, [r0, #8] /* r3 = row[3,1] */ + idct_row COL_SHIFT + pop {r1} + idct_finish_shift COL_SHIFT + + strh r4, [r1] + strh r5, [r1, #(16*1)] + strh r6, [r1, #(16*2)] + strh r7, [r1, #(16*3)] + strh r11,[r1, #(16*4)] + strh r10,[r1, #(16*5)] + strh r9, [r1, #(16*6)] + strh r8, [r1, #(16*7)] + + pop {pc} +endfunc + +/* + Compute IDCT of single column, read as row, store saturated 8-bit. + r0 = source + r1 = dest + r2 = line size +*/ +function idct_col_put_armv6 + push {r1, r2, lr} + + ldr r2, [r0] /* r2 = row[2,0] */ + ldr ip, =W42 /* ip = W4 | (W2 << 16) */ + ldr r3, [r0, #8] /* r3 = row[3,1] */ + idct_row COL_SHIFT + pop {r1, r2} + idct_finish_shift_sat COL_SHIFT + + strb_post r4, r1, r2 + strb_post r5, r1, r2 + strb_post r6, r1, r2 + strb_post r7, r1, r2 + strb_post r11,r1, r2 + strb_post r10,r1, r2 + strb_post r9, r1, r2 + strb_post r8, r1, r2 + + sub r1, r1, r2, lsl #3 + + pop {pc} +endfunc + +/* + Compute IDCT of single column, read as row, add/store saturated 8-bit. + r0 = source + r1 = dest + r2 = line size +*/ +function idct_col_add_armv6 + push {r1, r2, lr} + + ldr r2, [r0] /* r2 = row[2,0] */ + ldr ip, =W42 /* ip = W4 | (W2 << 16) */ + ldr r3, [r0, #8] /* r3 = row[3,1] */ + idct_row COL_SHIFT + pop {r1, r2} + idct_finish + + ldrb r3, [r1] + ldrb r7, [r1, r2] + ldrb r11,[r1, r2, lsl #2] + add ip, r3, ip, asr #COL_SHIFT + usat ip, #8, ip + add r4, r7, r4, asr #COL_SHIFT + strb_post ip, r1, r2 + ldrb ip, [r1, r2] + usat r4, #8, r4 + ldrb r11,[r1, r2, lsl #2] + add r5, ip, r5, asr #COL_SHIFT + usat r5, #8, r5 + strb_post r4, r1, r2 + ldrb r3, [r1, r2] + ldrb ip, [r1, r2, lsl #2] + strb_post r5, r1, r2 + ldrb r7, [r1, r2] + ldrb r4, [r1, r2, lsl #2] + add r6, r3, r6, asr #COL_SHIFT + usat r6, #8, r6 + add r10,r7, r10,asr #COL_SHIFT + usat r10,#8, r10 + add r9, r11,r9, asr #COL_SHIFT + usat r9, #8, r9 + add r8, ip, r8, asr #COL_SHIFT + usat r8, #8, r8 + add lr, r4, lr, asr #COL_SHIFT + usat lr, #8, lr + strb_post r6, r1, r2 + strb_post r10,r1, r2 + strb_post r9, r1, r2 + strb_post r8, r1, r2 + strb_post lr, r1, r2 + + sub r1, r1, r2, lsl #3 + + pop {pc} +endfunc + +/* + Compute 8 IDCT row transforms. + func = IDCT row->col function + width = width of columns in bytes +*/ + .macro idct_rows func width + bl \func + add r0, r0, #(16*2) + add r1, r1, #\width + bl \func + add r0, r0, #(16*2) + add r1, r1, #\width + bl \func + add r0, r0, #(16*2) + add r1, r1, #\width + bl \func + sub r0, r0, #(16*5) + add r1, r1, #\width + bl \func + add r0, r0, #(16*2) + add r1, r1, #\width + bl \func + add r0, r0, #(16*2) + add r1, r1, #\width + bl \func + add r0, r0, #(16*2) + add r1, r1, #\width + bl \func + + sub r0, r0, #(16*7) + .endm + +/* void ff_simple_idct_armv6(int16_t *data); */ +function ff_simple_idct_armv6, export=1 + push {r4-r11, lr} + sub sp, sp, #128 + + mov r1, sp + idct_rows idct_row_armv6, 2 + mov r1, r0 + mov r0, sp + idct_rows idct_col_armv6, 2 + + add sp, sp, #128 + pop {r4-r11, pc} +endfunc + +/* ff_simple_idct_add_armv6(uint8_t *dest, int line_size, int16_t *data); */ +function ff_simple_idct_add_armv6, export=1 + push {r0, r1, r4-r11, lr} + sub sp, sp, #128 + + mov r0, r2 + mov r1, sp + idct_rows idct_row_armv6, 2 + mov r0, sp + ldr r1, [sp, #128] + ldr r2, [sp, #(128+4)] + idct_rows idct_col_add_armv6, 1 + + add sp, sp, #(128+8) + pop {r4-r11, pc} +endfunc + +/* ff_simple_idct_put_armv6(uint8_t *dest, int line_size, int16_t *data); */ +function ff_simple_idct_put_armv6, export=1 + push {r0, r1, r4-r11, lr} + sub sp, sp, #128 + + mov r0, r2 + mov r1, sp + idct_rows idct_row_armv6, 2 + mov r0, sp + ldr r1, [sp, #128] + ldr r2, [sp, #(128+4)] + idct_rows idct_col_put_armv6, 1 + + add sp, sp, #(128+8) + pop {r4-r11, pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/simple_idct_neon.S b/ffmpeg/libavcodec/arm/simple_idct_neon.S new file mode 100644 index 0000000..c3e573c --- /dev/null +++ b/ffmpeg/libavcodec/arm/simple_idct_neon.S @@ -0,0 +1,375 @@ +/* + * ARM NEON IDCT + * + * Copyright (c) 2008 Mans Rullgard + * + * Based on Simple IDCT + * Copyright (c) 2001 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 "libavutil/arm/asm.S" + +#define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W4c ((1<<(COL_SHIFT-1))/W4) +#define ROW_SHIFT 11 +#define COL_SHIFT 20 + +#define w1 d0[0] +#define w2 d0[1] +#define w3 d0[2] +#define w4 d0[3] +#define w5 d1[0] +#define w6 d1[1] +#define w7 d1[2] +#define w4c d1[3] + + .macro idct_col4_top + vmull.s16 q7, d6, w2 /* q9 = W2 * col[2] */ + vmull.s16 q8, d6, w6 /* q10 = W6 * col[2] */ + vmull.s16 q9, d4, w1 /* q9 = W1 * col[1] */ + vadd.i32 q11, q15, q7 + vmull.s16 q10, d4, w3 /* q10 = W3 * col[1] */ + vadd.i32 q12, q15, q8 + vmull.s16 q5, d4, w5 /* q5 = W5 * col[1] */ + vsub.i32 q13, q15, q8 + vmull.s16 q6, d4, w7 /* q6 = W7 * col[1] */ + vsub.i32 q14, q15, q7 + + vmlal.s16 q9, d8, w3 /* q9 += W3 * col[3] */ + vmlsl.s16 q10, d8, w7 /* q10 -= W7 * col[3] */ + vmlsl.s16 q5, d8, w1 /* q5 -= W1 * col[3] */ + vmlsl.s16 q6, d8, w5 /* q6 -= W5 * col[3] */ + .endm + + .text + .align 6 + +function idct_row4_pld_neon + pld [r0] + add r3, r0, r1, lsl #2 + pld [r0, r1] + pld [r0, r1, lsl #1] +A pld [r3, -r1] + pld [r3] + pld [r3, r1] + add r3, r3, r1, lsl #1 + pld [r3] + pld [r3, r1] +endfunc + +function idct_row4_neon + vmov.i32 q15, #(1<<(ROW_SHIFT-1)) + vld1.64 {d2-d5}, [r2,:128]! + vmlal.s16 q15, d2, w4 /* q15 += W4 * col[0] */ + vld1.64 {d6,d7}, [r2,:128]! + vorr d10, d3, d5 + vld1.64 {d8,d9}, [r2,:128]! + add r2, r2, #-64 + + vorr d11, d7, d9 + vorr d10, d10, d11 + vmov r3, r4, d10 + + idct_col4_top + + orrs r3, r3, r4 + beq 1f + + vmull.s16 q7, d3, w4 /* q7 = W4 * col[4] */ + vmlal.s16 q9, d5, w5 /* q9 += W5 * col[5] */ + vmlsl.s16 q10, d5, w1 /* q10 -= W1 * col[5] */ + vmull.s16 q8, d7, w2 /* q8 = W2 * col[6] */ + vmlal.s16 q5, d5, w7 /* q5 += W7 * col[5] */ + vadd.i32 q11, q11, q7 + vsub.i32 q12, q12, q7 + vsub.i32 q13, q13, q7 + vadd.i32 q14, q14, q7 + vmlal.s16 q6, d5, w3 /* q6 += W3 * col[5] */ + vmull.s16 q7, d7, w6 /* q7 = W6 * col[6] */ + vmlal.s16 q9, d9, w7 + vmlsl.s16 q10, d9, w5 + vmlal.s16 q5, d9, w3 + vmlsl.s16 q6, d9, w1 + vadd.i32 q11, q11, q7 + vsub.i32 q12, q12, q8 + vadd.i32 q13, q13, q8 + vsub.i32 q14, q14, q7 + +1: vadd.i32 q3, q11, q9 + vadd.i32 q4, q12, q10 + vshrn.i32 d2, q3, #ROW_SHIFT + vshrn.i32 d4, q4, #ROW_SHIFT + vadd.i32 q7, q13, q5 + vadd.i32 q8, q14, q6 + vtrn.16 d2, d4 + vshrn.i32 d6, q7, #ROW_SHIFT + vshrn.i32 d8, q8, #ROW_SHIFT + vsub.i32 q14, q14, q6 + vsub.i32 q11, q11, q9 + vtrn.16 d6, d8 + vsub.i32 q13, q13, q5 + vshrn.i32 d3, q14, #ROW_SHIFT + vtrn.32 d2, d6 + vsub.i32 q12, q12, q10 + vtrn.32 d4, d8 + vshrn.i32 d5, q13, #ROW_SHIFT + vshrn.i32 d7, q12, #ROW_SHIFT + vshrn.i32 d9, q11, #ROW_SHIFT + + vtrn.16 d3, d5 + vtrn.16 d7, d9 + vtrn.32 d3, d7 + vtrn.32 d5, d9 + + vst1.64 {d2-d5}, [r2,:128]! + vst1.64 {d6-d9}, [r2,:128]! + + bx lr +endfunc + +function idct_col4_neon + mov ip, #16 + vld1.64 {d2}, [r2,:64], ip /* d2 = col[0] */ + vdup.16 d30, w4c + vld1.64 {d4}, [r2,:64], ip /* d3 = col[1] */ + vadd.i16 d30, d30, d2 + vld1.64 {d6}, [r2,:64], ip /* d4 = col[2] */ + vmull.s16 q15, d30, w4 /* q15 = W4*(col[0]+(1< + * + * 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 "libavutil/arm/asm.S" + +function ff_synth_filter_float_neon, export=1 + push {r3-r11,lr} + + ldr r4, [r2] @ synth_buf_offset + add r1, r1, r4, lsl #2 @ synth_buf + sub r12, r4, #32 + bfc r12, #9, #23 + bic r4, r4, #63 + str r12, [r2] + + ldr r2, [sp, #12*4] @ in + mov r9, r1 @ synth_buf + +VFP vpush {d0} + bl X(ff_imdct_half_neon) +VFP vpop {d0} + pop {r3} + + ldr r5, [sp, #9*4] @ window + ldr r2, [sp, #10*4] @ out +NOVFP vldr s0, [sp, #12*4] @ scale + add r8, r9, #12*4 + + mov lr, #64*4 + mov r1, #4 +1: + add r10, r9, #16*4 @ synth_buf + add r11, r8, #16*4 + add r0, r5, #16*4 @ window + add r6, r5, #32*4 + add r7, r5, #48*4 + + vld1.32 {q10}, [r3,:128] @ a + add r3, r3, #16*4 + vld1.32 {q1}, [r3,:128] @ b + vmov.f32 q2, #0.0 @ c + vmov.f32 q3, #0.0 @ d + + mov r12, #512 +2: + vld1.32 {q9}, [r8, :128], lr + vrev64.32 q9, q9 + vld1.32 {q8}, [r5, :128], lr + vmls.f32 d20, d16, d19 + vld1.32 {q11}, [r0, :128], lr + vmls.f32 d21, d17, d18 + vld1.32 {q12}, [r9, :128], lr + vmla.f32 d2, d22, d24 + vld1.32 {q8}, [r6, :128], lr + vmla.f32 d3, d23, d25 + vld1.32 {q9}, [r10,:128], lr + vmla.f32 d4, d16, d18 + vld1.32 {q12}, [r11,:128], lr + vmla.f32 d5, d17, d19 + vrev64.32 q12, q12 + vld1.32 {q11}, [r7, :128], lr + vmla.f32 d6, d22, d25 + vmla.f32 d7, d23, d24 + subs r12, r12, #64 + beq 3f + cmp r12, r4 + bne 2b + sub r8, r8, #512*4 + sub r9, r9, #512*4 + sub r10, r10, #512*4 + sub r11, r11, #512*4 + b 2b +3: + vmul.f32 q8, q10, d0[0] + vmul.f32 q9, q1, d0[0] + vst1.32 {q3}, [r3,:128] + sub r3, r3, #16*4 + vst1.32 {q2}, [r3,:128] + vst1.32 {q8}, [r2,:128] + add r2, r2, #16*4 + vst1.32 {q9}, [r2,:128] + + subs r1, r1, #1 + it eq + popeq {r4-r11,pc} + + cmp r4, #0 + itt eq + subeq r8, r8, #512*4 + subeq r9, r9, #512*4 + sub r5, r5, #512*4 + sub r2, r2, #12*4 @ out + add r3, r3, #4*4 @ synth_buf2 + add r5, r5, #4*4 @ window + add r9, r9, #4*4 @ synth_buf + sub r8, r8, #4*4 @ synth_buf + b 1b +endfunc diff --git a/ffmpeg/libavcodec/arm/videodsp_arm.h b/ffmpeg/libavcodec/arm/videodsp_arm.h new file mode 100644 index 0000000..112cbb8 --- /dev/null +++ b/ffmpeg/libavcodec/arm/videodsp_arm.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_ARM_VIDEODSP_ARM_H +#define AVCODEC_ARM_VIDEODSP_ARM_H + +#include "libavcodec/avcodec.h" +#include "libavcodec/videodsp.h" + +void ff_videodsp_init_armv5te(VideoDSPContext* ctx, int bpc); + +#endif /* AVCODEC_ARM_VIDEODSP_ARM_H */ diff --git a/ffmpeg/libavcodec/arm/videodsp_armv5te.S b/ffmpeg/libavcodec/arm/videodsp_armv5te.S new file mode 100644 index 0000000..48a6c3b --- /dev/null +++ b/ffmpeg/libavcodec/arm/videodsp_armv5te.S @@ -0,0 +1,31 @@ +@ +@ ARMv5te optimized DSP utils +@ Copyright (c) 2004 AGAWA Koji +@ +@ 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 "config.h" +#include "libavutil/arm/asm.S" + +function ff_prefetch_arm, export=1 + subs r2, r2, #1 + pld [r0] + add r0, r0, r1 + bne ff_prefetch_arm + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/videodsp_init_arm.c b/ffmpeg/libavcodec/arm/videodsp_init_arm.c new file mode 100644 index 0000000..a89abb2 --- /dev/null +++ b/ffmpeg/libavcodec/arm/videodsp_init_arm.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Ronald S. Bultje + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/videodsp.h" +#include "videodsp_arm.h" + +av_cold void ff_videodsp_init_arm(VideoDSPContext *ctx, int bpc) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_armv5te(cpu_flags)) ff_videodsp_init_armv5te(ctx, bpc); +} diff --git a/ffmpeg/libavcodec/arm/videodsp_init_armv5te.c b/ffmpeg/libavcodec/arm/videodsp_init_armv5te.c new file mode 100644 index 0000000..1ea1f34 --- /dev/null +++ b/ffmpeg/libavcodec/arm/videodsp_init_armv5te.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Ronald S. Bultje + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/videodsp.h" +#include "videodsp_arm.h" + +void ff_prefetch_arm(uint8_t *mem, ptrdiff_t stride, int h); + +av_cold void ff_videodsp_init_armv5te(VideoDSPContext *ctx, int bpc) +{ +#if HAVE_ARMV5TE_EXTERNAL + ctx->prefetch = ff_prefetch_arm; +#endif +} diff --git a/ffmpeg/libavcodec/arm/vorbisdsp_init_arm.c b/ffmpeg/libavcodec/arm/vorbisdsp_init_arm.c new file mode 100644 index 0000000..f4b3d80 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vorbisdsp_init_arm.c @@ -0,0 +1,37 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/vorbisdsp.h" + +void ff_vorbis_inverse_coupling_neon(float *mag, float *ang, + intptr_t blocksize); + +av_cold void ff_vorbisdsp_init_arm(VorbisDSPContext *c) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/vorbisdsp_neon.S b/ffmpeg/libavcodec/arm/vorbisdsp_neon.S new file mode 100644 index 0000000..79ce54f --- /dev/null +++ b/ffmpeg/libavcodec/arm/vorbisdsp_neon.S @@ -0,0 +1,83 @@ +/* + * ARM NEON optimised DSP functions + * Copyright (c) 2008 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +function ff_vorbis_inverse_coupling_neon, export=1 + vmov.i32 q10, #1<<31 + subs r2, r2, #4 + mov r3, r0 + mov r12, r1 + beq 3f + + vld1.32 {d24-d25},[r1,:128]! + vld1.32 {d22-d23},[r0,:128]! + vcle.s32 q8, q12, #0 + vand q9, q11, q10 + veor q12, q12, q9 + vand q2, q12, q8 + vbic q3, q12, q8 + vadd.f32 q12, q11, q2 + vsub.f32 q11, q11, q3 +1: vld1.32 {d2-d3}, [r1,:128]! + vld1.32 {d0-d1}, [r0,:128]! + vcle.s32 q8, q1, #0 + vand q9, q0, q10 + veor q1, q1, q9 + vst1.32 {d24-d25},[r3, :128]! + vst1.32 {d22-d23},[r12,:128]! + vand q2, q1, q8 + vbic q3, q1, q8 + vadd.f32 q1, q0, q2 + vsub.f32 q0, q0, q3 + subs r2, r2, #8 + ble 2f + vld1.32 {d24-d25},[r1,:128]! + vld1.32 {d22-d23},[r0,:128]! + vcle.s32 q8, q12, #0 + vand q9, q11, q10 + veor q12, q12, q9 + vst1.32 {d2-d3}, [r3, :128]! + vst1.32 {d0-d1}, [r12,:128]! + vand q2, q12, q8 + vbic q3, q12, q8 + vadd.f32 q12, q11, q2 + vsub.f32 q11, q11, q3 + b 1b + +2: vst1.32 {d2-d3}, [r3, :128]! + vst1.32 {d0-d1}, [r12,:128]! + it lt + bxlt lr + +3: vld1.32 {d2-d3}, [r1,:128] + vld1.32 {d0-d1}, [r0,:128] + vcle.s32 q8, q1, #0 + vand q9, q0, q10 + veor q1, q1, q9 + vand q2, q1, q8 + vbic q3, q1, q8 + vadd.f32 q1, q0, q2 + vsub.f32 q0, q0, q3 + vst1.32 {d2-d3}, [r0,:128]! + vst1.32 {d0-d1}, [r1,:128]! + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/vp3dsp_init_arm.c b/ffmpeg/libavcodec/arm/vp3dsp_init_arm.c new file mode 100644 index 0000000..5af795b --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp3dsp_init_arm.c @@ -0,0 +1,45 @@ +/* + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/vp3dsp.h" + +void ff_vp3_idct_put_neon(uint8_t *dest, int line_size, int16_t *data); +void ff_vp3_idct_add_neon(uint8_t *dest, int line_size, int16_t *data); +void ff_vp3_idct_dc_add_neon(uint8_t *dest, int line_size, const int16_t *data); + +void ff_vp3_v_loop_filter_neon(uint8_t *, int, int *); +void ff_vp3_h_loop_filter_neon(uint8_t *, int, int *); + +av_cold void ff_vp3dsp_init_arm(VP3DSPContext *c, int flags) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->idct_put = ff_vp3_idct_put_neon; + c->idct_add = ff_vp3_idct_add_neon; + c->idct_dc_add = ff_vp3_idct_dc_add_neon; + c->v_loop_filter = ff_vp3_v_loop_filter_neon; + c->h_loop_filter = ff_vp3_h_loop_filter_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/vp3dsp_neon.S b/ffmpeg/libavcodec/arm/vp3dsp_neon.S new file mode 100644 index 0000000..f133905 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp3dsp_neon.S @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2009 David Conrad + * + * 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 "libavutil/arm/asm.S" + +const vp3_idct_constants, align=4 +.short 64277, 60547, 54491, 46341, 36410, 25080, 12785 +endconst + +#define xC1S7 d0[0] +#define xC2S6 d0[1] +#define xC3S5 d0[2] +#define xC4S4 d0[3] +#define xC5S3 d1[0] +#define xC6S2 d1[1] +#define xC7S1 d1[2] + +.macro vp3_loop_filter + vsubl.u8 q3, d18, d17 + vsubl.u8 q2, d16, d19 + vadd.i16 q1, q3, q3 + vadd.i16 q2, q2, q3 + vadd.i16 q0, q1, q2 + vrshr.s16 q0, q0, #3 + vmovl.u8 q9, d18 + vdup.u16 q15, r2 + + vabs.s16 q1, q0 + vshr.s16 q0, q0, #15 + vqsub.u16 q2, q15, q1 + vqsub.u16 q3, q2, q1 + vsub.i16 q1, q2, q3 + veor q1, q1, q0 + vsub.i16 q0, q1, q0 + + vaddw.u8 q2, q0, d17 + vsub.i16 q3, q9, q0 + vqmovun.s16 d0, q2 + vqmovun.s16 d1, q3 +.endm + +function ff_vp3_v_loop_filter_neon, export=1 + sub ip, r0, r1 + sub r0, r0, r1, lsl #1 + vld1.64 {d16}, [r0,:64], r1 + vld1.64 {d17}, [r0,:64], r1 + vld1.64 {d18}, [r0,:64], r1 + vld1.64 {d19}, [r0,:64], r1 + ldrb r2, [r2, #129*4] + + vp3_loop_filter + + vst1.64 {d0}, [ip,:64], r1 + vst1.64 {d1}, [ip,:64], r1 + bx lr +endfunc + +function ff_vp3_h_loop_filter_neon, export=1 + sub ip, r0, #1 + sub r0, r0, #2 + vld1.32 {d16[]}, [r0], r1 + vld1.32 {d17[]}, [r0], r1 + vld1.32 {d18[]}, [r0], r1 + vld1.32 {d19[]}, [r0], r1 + vld1.32 {d16[1]}, [r0], r1 + vld1.32 {d17[1]}, [r0], r1 + vld1.32 {d18[1]}, [r0], r1 + vld1.32 {d19[1]}, [r0], r1 + ldrb r2, [r2, #129*4] + + vtrn.8 d16, d17 + vtrn.8 d18, d19 + vtrn.16 d16, d18 + vtrn.16 d17, d19 + + vp3_loop_filter + + vtrn.8 d0, d1 + + vst1.16 {d0[0]}, [ip], r1 + vst1.16 {d1[0]}, [ip], r1 + vst1.16 {d0[1]}, [ip], r1 + vst1.16 {d1[1]}, [ip], r1 + vst1.16 {d0[2]}, [ip], r1 + vst1.16 {d1[2]}, [ip], r1 + vst1.16 {d0[3]}, [ip], r1 + vst1.16 {d1[3]}, [ip], r1 + bx lr +endfunc + + +function vp3_idct_start_neon + vpush {d8-d15} + vmov.i16 q4, #0 + vmov.i16 q5, #0 + movrel r3, vp3_idct_constants + vld1.64 {d0-d1}, [r3,:128] + vld1.64 {d16-d19}, [r2,:128] + vst1.64 {q4-q5}, [r2,:128]! + vld1.64 {d20-d23}, [r2,:128] + vst1.64 {q4-q5}, [r2,:128]! + vld1.64 {d24-d27}, [r2,:128] + vst1.64 {q4-q5}, [r2,:128]! + vadd.s16 q1, q8, q12 + vsub.s16 q8, q8, q12 + vld1.64 {d28-d31}, [r2,:128] + vst1.64 {q4-q5}, [r2,:128]! + +vp3_idct_core_neon: + vmull.s16 q2, d18, xC1S7 // (ip[1] * C1) << 16 + vmull.s16 q3, d19, xC1S7 + vmull.s16 q4, d2, xC4S4 // ((ip[0] + ip[4]) * C4) << 16 + vmull.s16 q5, d3, xC4S4 + vmull.s16 q6, d16, xC4S4 // ((ip[0] - ip[4]) * C4) << 16 + vmull.s16 q7, d17, xC4S4 + vshrn.s32 d4, q2, #16 + vshrn.s32 d5, q3, #16 + vshrn.s32 d6, q4, #16 + vshrn.s32 d7, q5, #16 + vshrn.s32 d8, q6, #16 + vshrn.s32 d9, q7, #16 + vadd.s16 q12, q1, q3 // E = (ip[0] + ip[4]) * C4 + vadd.s16 q8, q8, q4 // F = (ip[0] - ip[4]) * C4 + vadd.s16 q1, q2, q9 // ip[1] * C1 + + vmull.s16 q2, d30, xC1S7 // (ip[7] * C1) << 16 + vmull.s16 q3, d31, xC1S7 + vmull.s16 q4, d30, xC7S1 // (ip[7] * C7) << 16 + vmull.s16 q5, d31, xC7S1 + vmull.s16 q6, d18, xC7S1 // (ip[1] * C7) << 16 + vmull.s16 q7, d19, xC7S1 + vshrn.s32 d4, q2, #16 + vshrn.s32 d5, q3, #16 + vshrn.s32 d6, q4, #16 // ip[7] * C7 + vshrn.s32 d7, q5, #16 + vshrn.s32 d8, q6, #16 // ip[1] * C7 + vshrn.s32 d9, q7, #16 + vadd.s16 q2, q2, q15 // ip[7] * C1 + vadd.s16 q9, q1, q3 // A = ip[1] * C1 + ip[7] * C7 + vsub.s16 q15, q4, q2 // B = ip[1] * C7 - ip[7] * C1 + + vmull.s16 q2, d22, xC5S3 // (ip[3] * C5) << 16 + vmull.s16 q3, d23, xC5S3 + vmull.s16 q4, d22, xC3S5 // (ip[3] * C3) << 16 + vmull.s16 q5, d23, xC3S5 + vmull.s16 q6, d26, xC5S3 // (ip[5] * C5) << 16 + vmull.s16 q7, d27, xC5S3 + vshrn.s32 d4, q2, #16 + vshrn.s32 d5, q3, #16 + vshrn.s32 d6, q4, #16 + vshrn.s32 d7, q5, #16 + vshrn.s32 d8, q6, #16 + vshrn.s32 d9, q7, #16 + vadd.s16 q3, q3, q11 // ip[3] * C3 + vadd.s16 q4, q4, q13 // ip[5] * C5 + vadd.s16 q1, q2, q11 // ip[3] * C5 + vadd.s16 q11, q3, q4 // C = ip[3] * C3 + ip[5] * C5 + + vmull.s16 q2, d26, xC3S5 // (ip[5] * C3) << 16 + vmull.s16 q3, d27, xC3S5 + vmull.s16 q4, d20, xC2S6 // (ip[2] * C2) << 16 + vmull.s16 q5, d21, xC2S6 + vmull.s16 q6, d28, xC6S2 // (ip[6] * C6) << 16 + vmull.s16 q7, d29, xC6S2 + vshrn.s32 d4, q2, #16 + vshrn.s32 d5, q3, #16 + vshrn.s32 d6, q4, #16 + vshrn.s32 d7, q5, #16 + vshrn.s32 d8, q6, #16 // ip[6] * C6 + vshrn.s32 d9, q7, #16 + vadd.s16 q2, q2, q13 // ip[5] * C3 + vadd.s16 q3, q3, q10 // ip[2] * C2 + vsub.s16 q13, q2, q1 // D = ip[5] * C3 - ip[3] * C5 + vsub.s16 q1, q9, q11 // (A - C) + vadd.s16 q11, q9, q11 // Cd = A + C + vsub.s16 q9, q15, q13 // (B - D) + vadd.s16 q13, q15, q13 // Dd = B + D + vadd.s16 q15, q3, q4 // G = ip[2] * C2 + ip[6] * C6 + + vmull.s16 q2, d2, xC4S4 // ((A - C) * C4) << 16 + vmull.s16 q3, d3, xC4S4 + vmull.s16 q4, d28, xC2S6 // (ip[6] * C2) << 16 + vmull.s16 q5, d29, xC2S6 + vmull.s16 q6, d20, xC6S2 // (ip[2] * C6) << 16 + vmull.s16 q7, d21, xC6S2 + vshrn.s32 d4, q2, #16 + vshrn.s32 d5, q3, #16 + vshrn.s32 d6, q4, #16 + vshrn.s32 d7, q5, #16 + vshrn.s32 d8, q6, #16 // ip[2] * C6 + vmull.s16 q5, d18, xC4S4 // ((B - D) * C4) << 16 + vmull.s16 q6, d19, xC4S4 + vshrn.s32 d9, q7, #16 + vadd.s16 q3, q3, q14 // ip[6] * C2 + vadd.s16 q10, q1, q2 // Ad = (A - C) * C4 + vsub.s16 q14, q4, q3 // H = ip[2] * C6 - ip[6] * C2 + bx lr +endfunc + +.macro VP3_IDCT_END type +function vp3_idct_end_\type\()_neon +.ifc \type, col + vdup.16 q0, r3 + vadd.s16 q12, q12, q0 + vadd.s16 q8, q8, q0 +.endif + + vshrn.s32 d2, q5, #16 + vshrn.s32 d3, q6, #16 + vadd.s16 q2, q12, q15 // Gd = E + G + vadd.s16 q9, q1, q9 // (B - D) * C4 + vsub.s16 q12, q12, q15 // Ed = E - G + vsub.s16 q3, q8, q10 // Fd = F - Ad + vadd.s16 q10, q8, q10 // Add = F + Ad + vadd.s16 q4, q9, q14 // Hd = Bd + H + vsub.s16 q14, q9, q14 // Bdd = Bd - H + vadd.s16 q8, q2, q11 // [0] = Gd + Cd + vsub.s16 q15, q2, q11 // [7] = Gd - Cd + vadd.s16 q9, q10, q4 // [1] = Add + Hd + vsub.s16 q10, q10, q4 // [2] = Add - Hd + vadd.s16 q11, q12, q13 // [3] = Ed + Dd + vsub.s16 q12, q12, q13 // [4] = Ed - Dd +.ifc \type, row + vtrn.16 q8, q9 +.endif + vadd.s16 q13, q3, q14 // [5] = Fd + Bdd + vsub.s16 q14, q3, q14 // [6] = Fd - Bdd + +.ifc \type, row + // 8x8 transpose + vtrn.16 q10, q11 + vtrn.16 q12, q13 + vtrn.16 q14, q15 + vtrn.32 q8, q10 + vtrn.32 q9, q11 + vtrn.32 q12, q14 + vtrn.32 q13, q15 + vswp d17, d24 + vswp d19, d26 + vadd.s16 q1, q8, q12 + vswp d21, d28 + vsub.s16 q8, q8, q12 + vswp d23, d30 +.endif + bx lr +endfunc +.endm + +VP3_IDCT_END row +VP3_IDCT_END col + +function ff_vp3_idct_put_neon, export=1 + mov ip, lr + bl vp3_idct_start_neon + bl vp3_idct_end_row_neon + mov r3, #8 + add r3, r3, #2048 // convert signed pixel to unsigned + bl vp3_idct_core_neon + bl vp3_idct_end_col_neon + mov lr, ip + vpop {d8-d15} + + vqshrun.s16 d0, q8, #4 + vqshrun.s16 d1, q9, #4 + vqshrun.s16 d2, q10, #4 + vqshrun.s16 d3, q11, #4 + vst1.64 {d0}, [r0,:64], r1 + vqshrun.s16 d4, q12, #4 + vst1.64 {d1}, [r0,:64], r1 + vqshrun.s16 d5, q13, #4 + vst1.64 {d2}, [r0,:64], r1 + vqshrun.s16 d6, q14, #4 + vst1.64 {d3}, [r0,:64], r1 + vqshrun.s16 d7, q15, #4 + vst1.64 {d4}, [r0,:64], r1 + vst1.64 {d5}, [r0,:64], r1 + vst1.64 {d6}, [r0,:64], r1 + vst1.64 {d7}, [r0,:64], r1 + bx lr +endfunc + +function ff_vp3_idct_add_neon, export=1 + mov ip, lr + bl vp3_idct_start_neon + bl vp3_idct_end_row_neon + mov r3, #8 + bl vp3_idct_core_neon + bl vp3_idct_end_col_neon + mov lr, ip + vpop {d8-d15} + mov r2, r0 + + vld1.64 {d0}, [r0,:64], r1 + vshr.s16 q8, q8, #4 + vld1.64 {d1}, [r0,:64], r1 + vshr.s16 q9, q9, #4 + vld1.64 {d2}, [r0,:64], r1 + vaddw.u8 q8, q8, d0 + vld1.64 {d3}, [r0,:64], r1 + vaddw.u8 q9, q9, d1 + vld1.64 {d4}, [r0,:64], r1 + vshr.s16 q10, q10, #4 + vld1.64 {d5}, [r0,:64], r1 + vshr.s16 q11, q11, #4 + vld1.64 {d6}, [r0,:64], r1 + vqmovun.s16 d0, q8 + vld1.64 {d7}, [r0,:64], r1 + vqmovun.s16 d1, q9 + vaddw.u8 q10, q10, d2 + vaddw.u8 q11, q11, d3 + vshr.s16 q12, q12, #4 + vshr.s16 q13, q13, #4 + vqmovun.s16 d2, q10 + vqmovun.s16 d3, q11 + vaddw.u8 q12, q12, d4 + vaddw.u8 q13, q13, d5 + vshr.s16 q14, q14, #4 + vshr.s16 q15, q15, #4 + vst1.64 {d0}, [r2,:64], r1 + vqmovun.s16 d4, q12 + vst1.64 {d1}, [r2,:64], r1 + vqmovun.s16 d5, q13 + vst1.64 {d2}, [r2,:64], r1 + vaddw.u8 q14, q14, d6 + vst1.64 {d3}, [r2,:64], r1 + vaddw.u8 q15, q15, d7 + vst1.64 {d4}, [r2,:64], r1 + vqmovun.s16 d6, q14 + vst1.64 {d5}, [r2,:64], r1 + vqmovun.s16 d7, q15 + vst1.64 {d6}, [r2,:64], r1 + vst1.64 {d7}, [r2,:64], r1 + bx lr +endfunc + +function ff_vp3_idct_dc_add_neon, export=1 + ldrsh r12, [r2] + mov r3, r0 + add r12, r12, #15 + vdup.16 q15, r12 + mov r12, 0 + strh r12, [r2] + vshr.s16 q15, q15, #5 + + vld1.8 {d0}, [r0,:64], r1 + vld1.8 {d1}, [r0,:64], r1 + vld1.8 {d2}, [r0,:64], r1 + vaddw.u8 q8, q15, d0 + vld1.8 {d3}, [r0,:64], r1 + vaddw.u8 q9, q15, d1 + vld1.8 {d4}, [r0,:64], r1 + vaddw.u8 q10, q15, d2 + vld1.8 {d5}, [r0,:64], r1 + vaddw.u8 q11, q15, d3 + vld1.8 {d6}, [r0,:64], r1 + vaddw.u8 q12, q15, d4 + vld1.8 {d7}, [r0,:64], r1 + vaddw.u8 q13, q15, d5 + vqmovun.s16 d0, q8 + vaddw.u8 q14, q15, d6 + vqmovun.s16 d1, q9 + vaddw.u8 q15, q15, d7 + vqmovun.s16 d2, q10 + vst1.8 {d0}, [r3,:64], r1 + vqmovun.s16 d3, q11 + vst1.8 {d1}, [r3,:64], r1 + vqmovun.s16 d4, q12 + vst1.8 {d2}, [r3,:64], r1 + vqmovun.s16 d5, q13 + vst1.8 {d3}, [r3,:64], r1 + vqmovun.s16 d6, q14 + vst1.8 {d4}, [r3,:64], r1 + vqmovun.s16 d7, q15 + vst1.8 {d5}, [r3,:64], r1 + vst1.8 {d6}, [r3,:64], r1 + vst1.8 {d7}, [r3,:64], r1 + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/vp56_arith.h b/ffmpeg/libavcodec/arm/vp56_arith.h new file mode 100644 index 0000000..feb1247 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp56_arith.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2010 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_ARM_VP56_ARITH_H +#define AVCODEC_ARM_VP56_ARITH_H + +#if CONFIG_THUMB +# define A(x) +# define T(x) x +#else +# define A(x) x +# define T(x) +#endif + +#if CONFIG_THUMB || defined __clang__ +# define L(x) +# define U(x) x +#else +# define L(x) x +# define U(x) +#endif + +#if HAVE_ARMV6_INLINE + +#define vp56_rac_get_prob vp56_rac_get_prob_armv6 +static inline int vp56_rac_get_prob_armv6(VP56RangeCoder *c, int pr) +{ + unsigned shift = ff_vp56_norm_shift[c->high]; + unsigned code_word = c->code_word << shift; + unsigned high = c->high << shift; + unsigned bit; + + __asm__ ("adds %3, %3, %0 \n" + "itt cs \n" + "cmpcs %7, %4 \n" + L("ldrcsh %2, [%4], #2 \n") + U("ldrhcs %2, [%4], #2 \n") + "rsb %0, %6, #256 \n" + "smlabb %0, %5, %6, %0 \n" + T("itttt cs \n") + "rev16cs %2, %2 \n" + T("lslcs %2, %2, %3 \n") + T("orrcs %1, %1, %2 \n") + A("orrcs %1, %1, %2, lsl %3 \n") + "subcs %3, %3, #16 \n" + "lsr %0, %0, #8 \n" + "cmp %1, %0, lsl #16 \n" + "ittte ge \n" + "subge %1, %1, %0, lsl #16 \n" + "subge %0, %5, %0 \n" + "movge %2, #1 \n" + "movlt %2, #0 \n" + : "=&r"(c->high), "=&r"(c->code_word), "=&r"(bit), + "+&r"(c->bits), "+&r"(c->buffer) + : "r"(high), "r"(pr), "r"(c->end - 1), + "0"(shift), "1"(code_word) + : "cc"); + + return bit; +} + +#define vp56_rac_get_prob_branchy vp56_rac_get_prob_branchy_armv6 +static inline int vp56_rac_get_prob_branchy_armv6(VP56RangeCoder *c, int pr) +{ + unsigned shift = ff_vp56_norm_shift[c->high]; + unsigned code_word = c->code_word << shift; + unsigned high = c->high << shift; + unsigned low; + unsigned tmp; + + __asm__ ("adds %3, %3, %0 \n" + "itt cs \n" + "cmpcs %7, %4 \n" + L("ldrcsh %2, [%4], #2 \n") + U("ldrhcs %2, [%4], #2 \n") + "rsb %0, %6, #256 \n" + "smlabb %0, %5, %6, %0 \n" + T("itttt cs \n") + "rev16cs %2, %2 \n" + T("lslcs %2, %2, %3 \n") + T("orrcs %1, %1, %2 \n") + A("orrcs %1, %1, %2, lsl %3 \n") + "subcs %3, %3, #16 \n" + "lsr %0, %0, #8 \n" + "lsl %2, %0, #16 \n" + : "=&r"(low), "+&r"(code_word), "=&r"(tmp), + "+&r"(c->bits), "+&r"(c->buffer) + : "r"(high), "r"(pr), "r"(c->end - 1), "0"(shift) + : "cc"); + + if (code_word >= tmp) { + c->high = high - low; + c->code_word = code_word - tmp; + return 1; + } + + c->high = low; + c->code_word = code_word; + return 0; +} + +#endif + +#endif /* AVCODEC_ARM_VP56_ARITH_H */ diff --git a/ffmpeg/libavcodec/arm/vp56dsp_init_arm.c b/ffmpeg/libavcodec/arm/vp56dsp_init_arm.c new file mode 100644 index 0000000..f53cbae --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp56dsp_init_arm.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/vp56dsp.h" + +void ff_vp6_edge_filter_hor_neon(uint8_t *yuv, int stride, int t); +void ff_vp6_edge_filter_ver_neon(uint8_t *yuv, int stride, int t); + +av_cold void ff_vp56dsp_init_arm(VP56DSPContext *s, enum AVCodecID codec) +{ + int cpu_flags = av_get_cpu_flags(); + + if (codec != AV_CODEC_ID_VP5 && have_neon(cpu_flags)) { + s->edge_filter_hor = ff_vp6_edge_filter_hor_neon; + s->edge_filter_ver = ff_vp6_edge_filter_ver_neon; + } +} diff --git a/ffmpeg/libavcodec/arm/vp56dsp_neon.S b/ffmpeg/libavcodec/arm/vp56dsp_neon.S new file mode 100644 index 0000000..03dd28d --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp56dsp_neon.S @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +.macro vp6_edge_filter + vdup.16 q3, r2 @ t + vmov.i16 q13, #1 + vsubl.u8 q0, d20, d18 @ p[ 0] - p[-s] + vsubl.u8 q1, d16, d22 @ p[-2*s] - p[ s] + vsubl.u8 q14, d21, d19 + vsubl.u8 q15, d17, d23 + vadd.i16 q2, q0, q0 @ 2*(p[0]-p[-s]) + vadd.i16 d29, d28, d28 + vadd.i16 q0, q0, q1 @ p[0]-p[-s] + p[-2*s]-p[s] + vadd.i16 d28, d28, d30 + vadd.i16 q0, q0, q2 @ 3*(p[0]-p[-s]) + p[-2*s]-p[s] + vadd.i16 d28, d28, d29 + vrshr.s16 q0, q0, #3 @ v + vrshr.s16 d28, d28, #3 + vsub.i16 q8, q3, q13 @ t-1 + vabs.s16 q1, q0 @ V + vshr.s16 q2, q0, #15 @ s + vabs.s16 d30, d28 + vshr.s16 d29, d28, #15 + vsub.i16 q12, q1, q3 @ V-t + vsub.i16 d31, d30, d6 + vsub.i16 q12, q12, q13 @ V-t-1 + vsub.i16 d31, d31, d26 + vcge.u16 q12, q12, q8 @ V-t-1 >= t-1 + vcge.u16 d31, d31, d16 + vadd.i16 q13, q3, q3 @ 2*t + vadd.i16 d16, d6, d6 + vsub.i16 q13, q13, q1 @ 2*t - V + vsub.i16 d16, d16, d30 + vadd.i16 q13, q13, q2 @ += s + vadd.i16 d16, d16, d29 + veor q13, q13, q2 @ ^= s + veor d16, d16, d29 + vbif q0, q13, q12 + vbif d28, d16, d31 + vmovl.u8 q1, d20 + vmovl.u8 q15, d21 + vaddw.u8 q2, q0, d18 + vaddw.u8 q3, q14, d19 + vsub.i16 q1, q1, q0 + vsub.i16 d30, d30, d28 + vqmovun.s16 d18, q2 + vqmovun.s16 d19, q3 + vqmovun.s16 d20, q1 + vqmovun.s16 d21, q15 +.endm + +function ff_vp6_edge_filter_ver_neon, export=1 + sub r0, r0, r1, lsl #1 + vld1.8 {q8}, [r0], r1 @ p[-2*s] + vld1.8 {q9}, [r0], r1 @ p[-s] + vld1.8 {q10}, [r0], r1 @ p[0] + vld1.8 {q11}, [r0] @ p[s] + vp6_edge_filter + sub r0, r0, r1, lsl #1 + sub r1, r1, #8 + vst1.8 {d18}, [r0]! + vst1.32 {d19[0]}, [r0], r1 + vst1.8 {d20}, [r0]! + vst1.32 {d21[0]}, [r0] + bx lr +endfunc + +function ff_vp6_edge_filter_hor_neon, export=1 + sub r3, r0, #1 + sub r0, r0, #2 + vld1.32 {d16[0]}, [r0], r1 + vld1.32 {d18[0]}, [r0], r1 + vld1.32 {d20[0]}, [r0], r1 + vld1.32 {d22[0]}, [r0], r1 + vld1.32 {d16[1]}, [r0], r1 + vld1.32 {d18[1]}, [r0], r1 + vld1.32 {d20[1]}, [r0], r1 + vld1.32 {d22[1]}, [r0], r1 + vld1.32 {d17[0]}, [r0], r1 + vld1.32 {d19[0]}, [r0], r1 + vld1.32 {d21[0]}, [r0], r1 + vld1.32 {d23[0]}, [r0], r1 + vtrn.8 q8, q9 + vtrn.8 q10, q11 + vtrn.16 q8, q10 + vtrn.16 q9, q11 + vp6_edge_filter + vtrn.8 q9, q10 + vst1.16 {d18[0]}, [r3], r1 + vst1.16 {d20[0]}, [r3], r1 + vst1.16 {d18[1]}, [r3], r1 + vst1.16 {d20[1]}, [r3], r1 + vst1.16 {d18[2]}, [r3], r1 + vst1.16 {d20[2]}, [r3], r1 + vst1.16 {d18[3]}, [r3], r1 + vst1.16 {d20[3]}, [r3], r1 + vst1.16 {d19[0]}, [r3], r1 + vst1.16 {d21[0]}, [r3], r1 + vst1.16 {d19[1]}, [r3], r1 + vst1.16 {d21[1]}, [r3], r1 + bx lr +endfunc diff --git a/ffmpeg/libavcodec/arm/vp8.h b/ffmpeg/libavcodec/arm/vp8.h new file mode 100644 index 0000000..ddaa120 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef AVCODEC_ARM_VP8_H +#define AVCODEC_ARM_VP8_H + +#include + +#include "config.h" +#include "libavcodec/vp56.h" +#include "libavcodec/vp8.h" + +#if HAVE_ARMV6_EXTERNAL +#define decode_block_coeffs_internal ff_decode_block_coeffs_armv6 +int ff_decode_block_coeffs_armv6(VP56RangeCoder *rc, int16_t block[16], + uint8_t probs[8][3][NUM_DCT_TOKENS-1], + int i, uint8_t *token_prob, int16_t qmul[2]); +#endif + +#endif /* AVCODEC_ARM_VP8_H */ diff --git a/ffmpeg/libavcodec/arm/vp8_armv6.S b/ffmpeg/libavcodec/arm/vp8_armv6.S new file mode 100644 index 0000000..e7d25a4 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8_armv6.S @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2010 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" + +.macro rac_get_prob h, bs, buf, cw, pr, t0, t1 + adds \bs, \bs, \t0 + lsl \cw, \cw, \t0 + lsl \t0, \h, \t0 + rsb \h, \pr, #256 + it cs + ldrhcs \t1, [\buf], #2 + smlabb \h, \t0, \pr, \h +T itttt cs + rev16cs \t1, \t1 +A orrcs \cw, \cw, \t1, lsl \bs +T lslcs \t1, \t1, \bs +T orrcs \cw, \cw, \t1 + subcs \bs, \bs, #16 + lsr \h, \h, #8 + cmp \cw, \h, lsl #16 + itt ge + subge \cw, \cw, \h, lsl #16 + subge \h, \t0, \h +.endm + +.macro rac_get_128 h, bs, buf, cw, t0, t1 + adds \bs, \bs, \t0 + lsl \cw, \cw, \t0 + lsl \t0, \h, \t0 + it cs + ldrhcs \t1, [\buf], #2 + mov \h, #128 + it cs + rev16cs \t1, \t1 + add \h, \h, \t0, lsl #7 +A orrcs \cw, \cw, \t1, lsl \bs +T ittt cs +T lslcs \t1, \t1, \bs +T orrcs \cw, \cw, \t1 + subcs \bs, \bs, #16 + lsr \h, \h, #8 + cmp \cw, \h, lsl #16 + itt ge + subge \cw, \cw, \h, lsl #16 + subge \h, \t0, \h +.endm + +function ff_decode_block_coeffs_armv6, export=1 + push {r0,r1,r4-r11,lr} + movrelx lr, X(ff_vp56_norm_shift) + ldrd r4, r5, [sp, #44] @ token_prob, qmul + cmp r3, #0 + ldr r11, [r5] + ldm r0, {r5-r7} @ high, bits, buf + it ne + pkhtbne r11, r11, r11, asr #16 + ldr r8, [r0, #16] @ code_word +0: + ldrb r9, [lr, r5] + add r3, r3, #1 + ldrb r0, [r4, #1] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + blt 2f + + ldrb r9, [lr, r5] + ldrb r0, [r4, #2] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + ldrb r9, [lr, r5] + bge 3f + + add r4, r3, r3, lsl #5 + sxth r12, r11 + add r4, r4, r2 + adds r6, r6, r9 + add r4, r4, #11 + lsl r8, r8, r9 + it cs + ldrhcs r10, [r7], #2 + lsl r9, r5, r9 + mov r5, #128 + it cs + rev16cs r10, r10 + add r5, r5, r9, lsl #7 +T ittt cs +T lslcs r10, r10, r6 +T orrcs r8, r8, r10 +A orrcs r8, r8, r10, lsl r6 + subcs r6, r6, #16 + lsr r5, r5, #8 + cmp r8, r5, lsl #16 + movrel r10, zigzag_scan-1 + itt ge + subge r8, r8, r5, lsl #16 + subge r5, r9, r5 + ldrb r10, [r10, r3] + it ge + rsbge r12, r12, #0 + cmp r3, #16 + strh r12, [r1, r10] + bge 6f +5: + ldrb r9, [lr, r5] + ldrb r0, [r4] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + pkhtb r11, r11, r11, asr #16 + bge 0b + +6: + ldr r0, [sp] + ldr r9, [r0, #12] + cmp r7, r9 + it hi + movhi r7, r9 + stm r0, {r5-r7} @ high, bits, buf + str r8, [r0, #16] @ code_word + + add sp, sp, #8 + mov r0, r3 + pop {r4-r11,pc} +2: + add r4, r3, r3, lsl #5 + cmp r3, #16 + add r4, r4, r2 + pkhtb r11, r11, r11, asr #16 + bne 0b + b 6b +3: + ldrb r0, [r4, #3] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + ldrb r9, [lr, r5] + bge 1f + + mov r12, #2 + ldrb r0, [r4, #4] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + it ge + addge r12, #1 + ldrb r9, [lr, r5] + blt 4f + ldrb r0, [r4, #5] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + it ge + addge r12, #1 + ldrb r9, [lr, r5] + b 4f +1: + ldrb r0, [r4, #6] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + ldrb r9, [lr, r5] + bge 3f + + ldrb r0, [r4, #7] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + ldrb r9, [lr, r5] + bge 2f + + mov r12, #5 + mov r0, #159 + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + it ge + addge r12, r12, #1 + ldrb r9, [lr, r5] + b 4f +2: + mov r12, #7 + mov r0, #165 + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + it ge + addge r12, r12, #2 + ldrb r9, [lr, r5] + mov r0, #145 + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + it ge + addge r12, r12, #1 + ldrb r9, [lr, r5] + b 4f +3: + ldrb r0, [r4, #8] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + it ge + addge r4, r4, #1 + ldrb r9, [lr, r5] + ite ge + movge r12, #2 + movlt r12, #0 + ldrb r0, [r4, #9] + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + mov r9, #8 + it ge + addge r12, r12, #1 + movrelx r4, X(ff_vp8_dct_cat_prob), r1 + lsl r9, r9, r12 + ldr r4, [r4, r12, lsl #2] + add r12, r9, #3 + mov r1, #0 + ldrb r0, [r4], #1 +1: + ldrb r9, [lr, r5] + lsl r1, r1, #1 + rac_get_prob r5, r6, r7, r8, r0, r9, r10 + ldrb r0, [r4], #1 + it ge + addge r1, r1, #1 + cmp r0, #0 + bne 1b + ldrb r9, [lr, r5] + add r12, r12, r1 + ldr r1, [sp, #4] +4: + add r4, r3, r3, lsl #5 + add r4, r4, r2 + add r4, r4, #22 + rac_get_128 r5, r6, r7, r8, r9, r10 + it ge + rsbge r12, r12, #0 + smulbb r12, r12, r11 + movrel r9, zigzag_scan-1 + ldrb r9, [r9, r3] + cmp r3, #16 + strh r12, [r1, r9] + bge 6b + b 5b +endfunc + +const zigzag_scan + .byte 0, 2, 8, 16 + .byte 10, 4, 6, 12 + .byte 18, 24, 26, 20 + .byte 14, 22, 28, 30 +endconst diff --git a/ffmpeg/libavcodec/arm/vp8dsp.h b/ffmpeg/libavcodec/arm/vp8dsp.h new file mode 100644 index 0000000..ce00e4a --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8dsp.h @@ -0,0 +1,78 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_ARM_VP8DSP_H +#define AVCODEC_ARM_VP8DSP_H + +#include "libavcodec/vp8dsp.h" + +void ff_vp8dsp_init_armv6(VP8DSPContext *dsp); +void ff_vp8dsp_init_neon(VP8DSPContext *dsp); + +#define VP8_LF_Y(hv, inner, opt) \ + void ff_vp8_##hv##_loop_filter16##inner##_##opt(uint8_t *dst, \ + ptrdiff_t stride, \ + int flim_E, int flim_I, \ + int hev_thresh) + +#define VP8_LF_UV(hv, inner, opt) \ + void ff_vp8_##hv##_loop_filter8uv##inner##_##opt(uint8_t *dstU, \ + uint8_t *dstV, \ + ptrdiff_t stride, \ + int flim_E, int flim_I, \ + int hev_thresh) + +#define VP8_LF_SIMPLE(hv, opt) \ + void ff_vp8_##hv##_loop_filter16_simple_##opt(uint8_t *dst, \ + ptrdiff_t stride, \ + int flim) + +#define VP8_LF_HV(inner, opt) \ + VP8_LF_Y(h, inner, opt); \ + VP8_LF_Y(v, inner, opt); \ + VP8_LF_UV(h, inner, opt); \ + VP8_LF_UV(v, inner, opt) + +#define VP8_LF(opt) \ + VP8_LF_HV(, opt); \ + VP8_LF_HV(_inner, opt); \ + VP8_LF_SIMPLE(h, opt); \ + VP8_LF_SIMPLE(v, opt) + +#define VP8_MC(n, opt) \ + void ff_put_vp8_##n##_##opt(uint8_t *dst, ptrdiff_t dststride, \ + uint8_t *src, ptrdiff_t srcstride, \ + int h, int x, int y) + +#define VP8_EPEL(w, opt) \ + VP8_MC(pixels ## w, opt); \ + VP8_MC(epel ## w ## _h4, opt); \ + VP8_MC(epel ## w ## _h6, opt); \ + VP8_MC(epel ## w ## _v4, opt); \ + VP8_MC(epel ## w ## _h4v4, opt); \ + VP8_MC(epel ## w ## _h6v4, opt); \ + VP8_MC(epel ## w ## _v6, opt); \ + VP8_MC(epel ## w ## _h4v6, opt); \ + VP8_MC(epel ## w ## _h6v6, opt) + +#define VP8_BILIN(w, opt) \ + VP8_MC(bilin ## w ## _h, opt); \ + VP8_MC(bilin ## w ## _v, opt); \ + VP8_MC(bilin ## w ## _hv, opt) + +#endif /* AVCODEC_ARM_VP8DSP_H */ diff --git a/ffmpeg/libavcodec/arm/vp8dsp_armv6.S b/ffmpeg/libavcodec/arm/vp8dsp_armv6.S new file mode 100644 index 0000000..5207758 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8dsp_armv6.S @@ -0,0 +1,1634 @@ +/* + * VP8 ARMv6 optimisations + * + * Copyright (c) 2010 Google Inc. + * Copyright (c) 2010 Rob Clark + * Copyright (c) 2011 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * This code was partially ported from libvpx, which uses this license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "libavutil/arm/asm.S" + +@ idct + +@ void vp8_luma_dc_wht(int16_t block[4][4][16], int16_t dc[16]) +function ff_vp8_luma_dc_wht_armv6, export=1 + push {r4-r10, lr} + + ldm r1, {r2-r9} + mov r10, #0 + mov lr, #0 + uadd16 r12, r2, r8 @ t0[0,1] + usub16 r2, r2, r8 @ t3[0,1] + stm r1!, {r10, lr} + uadd16 r8, r4, r6 @ t1[0,1] + usub16 r4, r4, r6 @ t2[0,1] + stm r1!, {r10, lr} + uadd16 r6, r12, r8 @ dc0[0,1] + usub16 r12, r12, r8 @ dc2[0,1] + stm r1!, {r10, lr} + uadd16 r8, r2, r4 @ dc1[0,1] + usub16 r2, r2, r4 @ dc3[0,1] + stm r1!, {r10, lr} + + uadd16 lr, r3, r9 @ t0[2,3] + usub16 r3, r3, r9 @ t3[2,3] + uadd16 r9, r5, r7 @ t1[2,3] + usub16 r5, r5, r7 @ t2[2,3] + + uadd16 r7, lr, r9 @ dc0[2,3] + usub16 lr, lr, r9 @ dc2[2,3] + uadd16 r9, r3, r5 @ dc1[2,3] + usub16 r3, r3, r5 @ dc3[2,3] + + mov r1, #3 + orr r1, r1, #0x30000 @ 3 | 3 (round) + + pkhbt r4, r6, r8, lsl #16 @ dc{0,1}[0] + pkhtb r6, r8, r6, asr #16 @ dc{0,1}[1] + pkhbt r5, r12, r2, lsl #16 @ dc{2,3}[0] + pkhtb r12, r2, r12, asr #16 @ dc{2,3}[1] + pkhbt r8, r7, r9, lsl #16 @ dc{0,1}[2] + uadd16 r4, r4, r1 + uadd16 r5, r5, r1 + pkhtb r7, r9, r7, asr #16 @ dc{0,1}[3] + pkhbt r2, lr, r3, lsl #16 @ dc{2,3}[2] + pkhtb lr, r3, lr, asr #16 @ dc{2,3}[3] + + uadd16 r9, r4, r7 @ t0[0,1] + uadd16 r3, r5, lr @ t0[2,3] + usub16 r4, r4, r7 @ t3[0,1] + usub16 r5, r5, lr @ t3[2,3] + uadd16 r7, r6, r8 @ t1[0,1] + uadd16 lr, r12, r2 @ t1[2,3] + usub16 r6, r6, r8 @ t2[0,1] + usub16 r12, r12, r2 @ t2[2,3] + + uadd16 r8, r9, r7 @ block[0,1][0] + uadd16 r2, r3, lr @ block[2,3][0] + usub16 r9, r9, r7 @ block[0,1][2] + usub16 r3, r3, lr @ block[2,3][2] + uadd16 r7, r4, r6 @ block[0,1][1] + uadd16 lr, r5, r12 @ block[2,3][1] + usub16 r4, r4, r6 @ block[0,1][3] + usub16 r5, r5, r12 @ block[2,3][3] + +#if HAVE_ARMV6T2_EXTERNAL + sbfx r6, r8, #3, #13 + sbfx r12, r7, #3, #13 + sbfx r1, r9, #3, #13 + sbfx r10, r4, #3, #13 +#else + sxth r6, r8 + sxth r12, r7 + sxth r1, r9 + sxth r10, r4 + asr r6, #3 @ block[0][0] + asr r12, #3 @ block[0][1] + asr r1, #3 @ block[0][2] + asr r10, #3 @ block[0][3] +#endif + + strh r6, [r0], #32 + asr r8, r8, #19 @ block[1][0] + strh r12, [r0], #32 + asr r7, r7, #19 @ block[1][1] + strh r1, [r0], #32 + asr r9, r9, #19 @ block[1][2] + strh r10, [r0], #32 + asr r4, r4, #19 @ block[1][3] + strh r8, [r0], #32 + asr r6, r2, #19 @ block[3][0] + strh r7, [r0], #32 + asr r12, lr, #19 @ block[3][1] + strh r9, [r0], #32 + asr r1, r3, #19 @ block[3][2] + strh r4, [r0], #32 + asr r10, r5, #19 @ block[3][3] + +#if HAVE_ARMV6T2_EXTERNAL + sbfx r2, r2, #3, #13 + sbfx lr, lr, #3, #13 + sbfx r3, r3, #3, #13 + sbfx r5, r5, #3, #13 +#else + sxth r2, r2 + sxth lr, lr + sxth r3, r3 + sxth r5, r5 + asr r2, #3 @ block[2][0] + asr lr, #3 @ block[2][1] + asr r3, #3 @ block[2][2] + asr r5, #3 @ block[2][3] +#endif + + strh r2, [r0], #32 + strh lr, [r0], #32 + strh r3, [r0], #32 + strh r5, [r0], #32 + strh r6, [r0], #32 + strh r12, [r0], #32 + strh r1, [r0], #32 + strh r10, [r0], #32 + + pop {r4-r10, pc} +endfunc + +@ void vp8_luma_dc_wht_dc(int16_t block[4][4][16], int16_t dc[16]) +function ff_vp8_luma_dc_wht_dc_armv6, export=1 + ldrsh r2, [r1] + mov r3, #0 + add r2, r2, #3 + strh r3, [r1] + asr r2, r2, #3 + .rept 16 + strh r2, [r0], #32 + .endr + bx lr +endfunc + +@ void vp8_idct_add(uint8_t *dst, int16_t block[16], int stride) +function ff_vp8_idct_add_armv6, export=1 + push {r4-r12, lr} + sub sp, sp, #32 + + movw r3, #20091 @ cospi8sqrt2minus1 + movw r4, #35468 @ sinpi8sqrt2 + mov r5, sp +1: + ldr r6, [r1, #8] @ i5 | i4 = block1[1] | block1[0] + ldr lr, [r1, #16] @ i9 | i8 = block2[1] | block2[0] + ldr r12, [r1, #24] @ i13 | i12 = block3[1] | block3[0] + + smulwt r9, r3, r6 @ ip[5] * cospi8sqrt2minus1 + smulwb r7, r3, r6 @ ip[4] * cospi8sqrt2minus1 + smulwt r10, r4, r6 @ ip[5] * sinpi8sqrt2 + smulwb r8, r4, r6 @ ip[4] * sinpi8sqrt2 + pkhbt r7, r7, r9, lsl #16 @ 5c | 4c + smulwt r11, r3, r12 @ ip[13] * cospi8sqrt2minus1 + pkhbt r8, r8, r10, lsl #16 @ 5s | 4s = t2 first half + uadd16 r6, r6, r7 @ 5c+5 | 4c+4 = t3 first half + smulwb r9, r3, r12 @ ip[12] * cospi8sqrt2minus1 + smulwt r7, r4, r12 @ ip[13] * sinpi8sqrt2 + smulwb r10, r4, r12 @ ip[12] * sinpi8sqrt2 + + pkhbt r9, r9, r11, lsl #16 @ 13c | 12c + ldr r11, [r1] @ i1 | i0 + pkhbt r10, r10, r7, lsl #16 @ 13s | 12s = t3 second half + uadd16 r7, r12, r9 @ 13c+13 | 12c+12 = t2 2nd half + uadd16 r6, r6, r10 @ d = t3 + uadd16 r10, r11, lr @ a = t0 + usub16 r7, r8, r7 @ c = t2 + usub16 r8, r11, lr @ b = t1 + uadd16 r9, r10, r6 @ a+d = tmp{0,1}[0] + usub16 r10, r10, r6 @ a-d = tmp{0,1}[3] + uadd16 r6, r8, r7 @ b+c = tmp{0,1}[1] + usub16 r7, r8, r7 @ b-c = tmp{0,1}[2] + mov r8, #0 + cmp sp, r5 + str r6, [r5, #8] @ o5 | o4 + str r7, [r5, #16] @ o9 | o8 + str r10, [r5, #24] @ o13 | o12 + str r9, [r5], #4 @ o1 | o0 + str r8, [r1, #8] + str r8, [r1, #16] + str r8, [r1, #24] + str r8, [r1], #4 + beq 1b + + mov r5, #2 +2: + pop {r1, r6, r12, lr} + smulwt r9, r3, r12 @ ip[5] * cospi8sqrt2minus1 + smulwt r7, r3, r1 @ ip[1] * cospi8sqrt2minus1 + smulwt r10, r4, r12 @ ip[5] * sinpi8sqrt2 + smulwt r8, r4, r1 @ ip[1] * sinpi8sqrt2 + pkhbt r11, r1, r12, lsl #16 @ i4 | i0 = t0/t1 first half + pkhtb r1, r12, r1, asr #16 @ i5 | i1 + pkhbt r7, r7, r9, lsl #16 @ 5c | 1c + pkhbt r8, r8, r10, lsl #16 @ 5s | 1s = t2 first half + pkhbt r9, r6, lr, lsl #16 @ i6 | i2 = t0/t1 second half + pkhtb r12, lr, r6, asr #16 @ i7 | i3 + uadd16 r1, r7, r1 @ 5c+5 | 1c+1 = t3 first half + uadd16 r10, r11, r9 @ a = t0 + usub16 r9, r11, r9 @ b = t1 + smulwt r7, r3, r12 @ ip[7] * cospi8sqrt2minus1 + smulwb lr, r3, r12 @ ip[3] * cospi8sqrt2minus1 + smulwt r11, r4, r12 @ ip[7] * sinpi8sqrt2 + smulwb r6, r4, r12 @ ip[3] * sinpi8sqrt2 + subs r5, r5, #1 + pkhbt r7, lr, r7, lsl #16 @ 7c | 3c + pkhbt r11, r6, r11, lsl #16 @ 7s | 3s = t3 second half + mov r6, #0x4 + orr r6, r6, #0x40000 + uadd16 r12, r7, r12 @ 7c+7 | 3c+3 = t2 second half + uadd16 r10, r10, r6 @ t0 + 4 + uadd16 r9, r9, r6 @ t1 + 4 + usub16 lr, r8, r12 @ c (o5 | o1) = t2 + uadd16 r12, r11, r1 @ d (o7 | o3) = t3 + usub16 r1, r9, lr @ b-c = dst{0,1}[2] + uadd16 r7, r10, r12 @ a+d = dst{0,1}[0] + usub16 r12, r10, r12 @ a-d = dst{0,1}[3] + uadd16 r10, r9, lr @ b+c = dst{0,1}[1] + + asr lr, r1, #3 @ o[1][2] + asr r9, r12, #3 @ o[1][3] + pkhtb r8, lr, r7, asr #19 @ o[1][0,2] + pkhtb r11, r9, r10, asr #19 @ o[1][1,3] + ldr lr, [r0] + sxth r12, r12 + ldr r9, [r0, r2] + sxth r1, r1 +#if HAVE_ARMV6T2_EXTERNAL + sbfx r7, r7, #3, #13 + sbfx r10, r10, #3, #13 +#else + sxth r7, r7 + sxth r10, r10 + asr r7, #3 @ o[0][0] + asr r10, #3 @ o[0][1] +#endif + pkhbt r7, r7, r1, lsl #13 @ o[0][0,2] + pkhbt r10, r10, r12, lsl #13 @ o[0][1,3] + + uxtab16 r7, r7, lr + uxtab16 r10, r10, lr, ror #8 + uxtab16 r8, r8, r9 + uxtab16 r11, r11, r9, ror #8 + usat16 r7, #8, r7 + usat16 r10, #8, r10 + usat16 r8, #8, r8 + usat16 r11, #8, r11 + orr r7, r7, r10, lsl #8 + orr r8, r8, r11, lsl #8 + str r8, [r0, r2] + str_post r7, r0, r2, lsl #1 + + bne 2b + + pop {r4-r12, pc} +endfunc + +@ void vp8_idct_dc_add(uint8_t *dst, int16_t block[16], int stride) +function ff_vp8_idct_dc_add_armv6, export=1 + push {r4-r6, lr} + add r6, r0, r2, lsl #1 + ldrsh r3, [r1] + mov r4, #0 + add r3, r3, #4 + strh r4, [r1], #32 + asr r3, #3 + ldr r5, [r0] + ldr r4, [r0, r2] + pkhbt r3, r3, r3, lsl #16 + uxtab16 lr, r3, r5 @ a1+2 | a1+0 + uxtab16 r5, r3, r5, ror #8 @ a1+3 | a1+1 + uxtab16 r12, r3, r4 + uxtab16 r4, r3, r4, ror #8 + usat16 lr, #8, lr + usat16 r5, #8, r5 + usat16 r12, #8, r12 + usat16 r4, #8, r4 + orr lr, lr, r5, lsl #8 + ldr r5, [r6] + orr r12, r12, r4, lsl #8 + ldr r4, [r6, r2] + str lr, [r0] + uxtab16 lr, r3, r5 + str r12, [r0, r2] + uxtab16 r5, r3, r5, ror #8 + uxtab16 r12, r3, r4 + uxtab16 r4, r3, r4, ror #8 + usat16 lr, #8, lr + usat16 r5, #8, r5 + usat16 r12, #8, r12 + usat16 r4, #8, r4 + orr lr, lr, r5, lsl #8 + orr r12, r12, r4, lsl #8 + str lr, [r6] + str r12, [r6, r2] + pop {r4-r6, pc} +endfunc + +@ void vp8_idct_dc_add4uv(uint8_t *dst, int16_t block[4][16], int stride) +function ff_vp8_idct_dc_add4uv_armv6, export=1 + push {r4, lr} + + bl ff_vp8_idct_dc_add_armv6 + add r0, r0, #4 + bl ff_vp8_idct_dc_add_armv6 + add r0, r0, r2, lsl #2 + sub r0, r0, #4 + bl ff_vp8_idct_dc_add_armv6 + add r0, r0, #4 + bl ff_vp8_idct_dc_add_armv6 + + pop {r4, pc} +endfunc + +@ void vp8_idct_dc_add4y(uint8_t *dst, int16_t block[4][16], int stride) +function ff_vp8_idct_dc_add4y_armv6, export=1 + push {r4, lr} + + bl ff_vp8_idct_dc_add_armv6 + add r0, r0, #4 + bl ff_vp8_idct_dc_add_armv6 + add r0, r0, #4 + bl ff_vp8_idct_dc_add_armv6 + add r0, r0, #4 + bl ff_vp8_idct_dc_add_armv6 + + pop {r4, pc} +endfunc + +@ loopfilter + +.macro transpose o3, o2, o1, o0, i0, i1, i2, i3 + uxtb16 \o1, \i1 @ xx 12 xx 10 + uxtb16 \o0, \i0 @ xx 02 xx 00 + uxtb16 \o3, \i3 @ xx 32 xx 30 + uxtb16 \o2, \i2 @ xx 22 xx 20 + orr \o1, \o0, \o1, lsl #8 @ 12 02 10 00 + orr \o3, \o2, \o3, lsl #8 @ 32 22 30 20 + + uxtb16 \i1, \i1, ror #8 @ xx 13 xx 11 + uxtb16 \i3, \i3, ror #8 @ xx 33 xx 31 + uxtb16 \i0, \i0, ror #8 @ xx 03 xx 01 + uxtb16 \i2, \i2, ror #8 @ xx 23 xx 21 + orr \i0, \i0, \i1, lsl #8 @ 13 03 11 01 + orr \i2, \i2, \i3, lsl #8 @ 33 23 31 21 + + pkhtb \o2, \o3, \o1, asr #16 @ 32 22 12 02 + pkhbt \o0, \o1, \o3, lsl #16 @ 30 20 10 00 + pkhtb \o3, \i2, \i0, asr #16 @ 33 23 13 03 + pkhbt \o1, \i0, \i2, lsl #16 @ 31 21 11 01 +.endm + +.macro simple_filter + uqsub8 r7, r3, r6 @ p1 - q1 + uqsub8 r8, r6, r3 @ q1 - p1 + uqsub8 r10, r4, r5 @ p0 - q0 + uqsub8 r9, r5, r4 @ q0 - p0 + orr r7, r7, r8 @ abs(p1 - q1) + orr r9, r9, r10 @ abs(p0 - q0) + uhadd8 r7, r7, lr @ abs(p1 - q2) >> 1 + uqadd8 r9, r9, r9 @ abs(p0 - q0) * 2 + uqadd8 r7, r7, r9 @ abs(p0 - q0)*2 + abs(p1-q1)/2 + mvn r8, #0 + usub8 r10, r12, r7 @ compare to flimit + sel r10, r8, lr @ filter mask: F or 0 + cmp r10, #0 + beq 2f + + eor r3, r3, r2 @ ps1 + eor r6, r6, r2 @ qs1 + eor r4, r4, r2 @ ps0 + eor r5, r5, r2 @ qs0 + + qsub8 r3, r3, r6 @ vp8_filter = p1 - q1 + qsub8 r6, r5, r4 @ q0 - p0 + qadd8 r3, r3, r6 @ += q0 - p0 + lsr r7, r2, #5 @ 0x04040404 + qadd8 r3, r3, r6 @ += q0 - p0 + sub r9, r7, r2, lsr #7 @ 0x03030303 + qadd8 r3, r3, r6 @ vp8_filter = p1-q1 + 3*(q0-p0) + and r3, r3, r10 @ vp8_filter &= mask + + qadd8 r9, r3, r9 @ Filter2 = vp8_filter + 3 + qadd8 r3, r3, r7 @ Filter1 = vp8_filter + 4 + + shadd8 r9, r9, lr + shadd8 r3, r3, lr + shadd8 r9, r9, lr + shadd8 r3, r3, lr + shadd8 r9, r9, lr @ Filter2 >>= 3 + shadd8 r3, r3, lr @ Filter1 >>= 3 + + qadd8 r4, r4, r9 @ u = p0 + Filter2 + qsub8 r5, r5, r3 @ u = q0 - Filter1 + eor r4, r4, r2 @ *op0 = u ^ 0x80 + eor r5, r5, r2 @ *oq0 = u ^ 0x80 +.endm + +@ void vp8_v_loop_filter16_simple(uint8_t *dst, int stride, int flim) +function ff_vp8_v_loop_filter16_simple_armv6, export=1 + push {r4-r11, lr} + + orr r2, r2, r2, lsl #16 + mov r11, #4 + mov lr, #0 + orr r12, r2, r2, lsl #8 + mov32 r2, 0x80808080 +1: + ldr_nreg r3, r0, r1, lsl #1 @ p1 + ldr_nreg r4, r0, r1 @ p0 + ldr r5, [r0] @ q0 + ldr r6, [r0, r1] @ q1 + simple_filter +T sub r7, r0, r1 + str r5, [r0] @ oq0 +A str r4, [r0, -r1] @ op0 +T str r4, [r7] +2: + subs r11, r11, #1 + add r0, r0, #4 + bne 1b + + pop {r4-r11, pc} +endfunc + +.macro filter_mask_p + uqsub8 r6, r9, r10 @ p3 - p2 + uqsub8 r7, r10, r9 @ p2 - p3 + uqsub8 r8, r10, r11 @ p2 - p1 + uqsub8 r10, r11, r10 @ p1 - p2 + orr r6, r6, r7 @ abs(p3-p2) + orr r8, r8, r10 @ abs(p2-p1) + uqsub8 lr, r6, r2 @ compare to limit + uqsub8 r8, r8, r2 @ compare to limit + uqsub8 r6, r11, r12 @ p1 - p0 + orr lr, lr, r8 + uqsub8 r7, r12, r11 @ p0 - p1 + orr r6, r6, r7 @ abs(p1-p0) + uqsub8 r7, r6, r2 @ compare to limit + uqsub8 r8, r6, r3 @ compare to thresh + orr lr, lr, r7 +.endm + +.macro filter_mask_pq + uqsub8 r6, r11, r10 @ p1 - q1 + uqsub8 r7, r10, r11 @ q1 - p1 + uqsub8 r11, r12, r9 @ p0 - q0 + uqsub8 r12, r9, r12 @ q0 - p0 + orr r6, r6, r7 @ abs(p1-q1) + orr r12, r11, r12 @ abs(p0-q0) + mov32 r7, 0x7f7f7f7f + uqadd8 r12, r12, r12 @ abs(p0-q0) * 2 + and r6, r7, r6, lsr #1 @ abs(p1-q1) / 2 + uqadd8 r12, r12, r6 @ abs(p0-q0) * 2 + abs(p1-q1)/2 +.endm + +.macro filter_mask_v + filter_mask_p + + ldr r10, [r0, r1] @ q1 + ldr_post r9, r0, r1, lsl #1 @ q0 + + filter_mask_pq + + ldr r11, [r0] @ q2 + + uqsub8 r7, r9, r10 @ q0 - q1 + uqsub8 r6, r10, r9 @ q1 - q0 + uqsub8 r12, r12, r4 @ compare to flimit + uqsub8 r9, r11, r10 @ q2 - q1 + uqsub8 r10, r10, r11 @ q1 - q2 + orr lr, lr, r12 + ldr r12, [r0, r1] @ q3 + orr r6, r7, r6 @ abs(q1-q0) + orr r10, r9, r10 @ abs(q2-q1) + uqsub8 r9, r12, r11 @ q3 - q2 + uqsub8 r11, r11, r12 @ q2 - q3 + uqsub8 r7, r6, r2 @ compare to limit + uqsub8 r10, r10, r2 @ compare to limit + uqsub8 r6, r6, r3 @ compare to thresh + orr r9, r9, r11 @ abs(q3-q2) + orr lr, lr, r7 + orr lr, lr, r10 + uqsub8 r9, r9, r2 @ compare to limit + orr lr, lr, r9 + + mov r12, #0 + usub8 lr, r12, lr + mvn r11, #0 + sel lr, r11, r12 @ filter mask + sub r0, r0, r1, lsl #1 +.endm + +.macro filter_mask_h + transpose r12, r11, r10, r9, r6, r7, r8, lr + + filter_mask_p + + stm sp, {r8, r11, r12, lr} + sub r0, r0, r1, lsl #2 + add r0, r0, #4 + + ldr r7, [r0, r1] + ldr_post r6, r0, r1, lsl #1 + ldr lr, [r0, r1] + ldr r8, [r0] + + transpose r12, r11, r10, r9, r6, r7, r8, lr + + uqsub8 r8, r12, r11 @ q3 - q2 + uqsub8 lr, r11, r12 @ q2 - q3 + uqsub8 r7, r9, r10 @ q0 - q1 + uqsub8 r6, r10, r9 @ q1 - q0 + uqsub8 r12, r11, r10 @ q2 - q1 + uqsub8 r11, r10, r11 @ q1 - q2 + orr r8, r8, lr @ abs(q3-q2) + orr r6, r7, r6 @ abs(q1-q0) + orr r11, r12, r11 @ abs(q2-q1) + ldr lr, [sp, #12] @ load back (f)limit accumulator + uqsub8 r8, r8, r2 @ compare to limit + uqsub8 r7, r6, r2 @ compare to limit + uqsub8 r11, r11, r2 @ compare to limit + orr lr, lr, r8 + uqsub8 r8, r6, r3 @ compare to thresh + orr lr, lr, r7 + ldr r12, [sp, #8] @ p1 + orr lr, lr, r11 + + ldr r11, [sp, #4] @ p0 + + filter_mask_pq + + mov r10, #0 + uqsub8 r12, r12, r4 @ compare to flimit + mvn r11, #0 + orr lr, lr, r12 + usub8 lr, r10, lr + sel lr, r11, r10 @ filter mask +.endm + +.macro filter inner + mov32 r12, 0x80808080 + eor r11, r7, r12 @ ps1 + eor r8, r8, r12 @ ps0 + eor r9, r9, r12 @ qs0 + eor r10, r10, r12 @ qs1 + + stm sp, {r8-r11} + + qsub8 r7, r11, r10 @ vp8_signed_char_clamp(ps1-qs1) + qsub8 r8, r9, r8 @ vp8_signed_char_clamp(vp8_filter + 3 * ( qs0 - ps0)) + .if \inner + and r7, r7, r6 @ vp8_filter &= hev + .endif + qadd8 r7, r7, r8 + lsr r10, r12, #5 @ 0x04040404 + qadd8 r7, r7, r8 + sub r9, r10, r12, lsr #7 @ 0x03030303 + qadd8 r7, r7, r8 + + and r7, r7, lr @ vp8_filter &= mask + .if !\inner + mov r12, r7 @ Filter2 + and r7, r7, r6 @ Filter2 &= hev + .endif + qadd8 lr, r7, r9 @ Filter2 = vp8_signed_char_clamp(vp8_filter+3) + qadd8 r7, r7, r10 @ Filter1 = vp8_signed_char_clamp(vp8_filter+4) + + mov r9, #0 + shadd8 lr, lr, r9 @ Filter2 >>= 3 + shadd8 r7, r7, r9 @ Filter1 >>= 3 + shadd8 lr, lr, r9 + shadd8 r7, r7, r9 + shadd8 lr, lr, r9 @ Filter2 + shadd8 r7, r7, r9 @ Filter1 +.endm + +.macro filter_v inner + orr r10, r6, r8 @ calculate vp8_hevmask + ldr_nreg r7, r0, r1, lsl #1 @ p1 + usub8 r10, r12, r10 + ldr_nreg r8, r0, r1 @ p0 + sel r6, r12, r11 @ obtain vp8_hevmask + ldr r9, [r0] @ q0 + ldr r10, [r0, r1] @ q1 + filter \inner +.endm + +.macro filter_h inner + orr r9, r6, r8 + usub8 r9, r12, r9 + sel r6, r12, r11 @ hev mask + + stm sp, {r6, lr} + + ldr_nreg r12, r0, r1, lsl #1 + ldr_nreg r11, r0, r1 + ldr r6, [r0] + ldr lr, [r0, r1] + + transpose r10, r9, r8, r7, r12, r11, r6, lr + + ldm sp, {r6, lr} + filter \inner +.endm + +.macro filter_inner + ldm sp, {r8, r9} + lsr r10, r10, #2 @ 0x01010101 + qadd8 r8, r8, lr @ u = vp8_signed_char_clamp(ps0 + Filter2) + mov lr, #0 + qsub8 r9, r9, r7 @ u = vp8_signed_char_clamp(qs0 - Filter1) + sadd8 r7, r7, r10 @ vp8_filter += 1 + ldr r10, [sp, #8] @ qs1 + shadd8 r7, r7, lr @ vp8_filter >>= 1 + eor r8, r8, r12 @ *op0 = u ^ 0x80 + bic r7, r7, r6 @ vp8_filter &= ~hev + qadd8 r11, r11, r7 @ u = vp8_signed_char_clamp(ps1 + vp8_filter) + eor r9, r9, r12 @ *oq0 = u ^ 0x80 + qsub8 r10, r10, r7 @ u = vp8_signed_char_clamp(qs1 - vp8_filter) + eor r11, r11, r12 @ *op1 = u ^ 0x80 + eor r10, r10, r12 @ *oq1 = u ^ 0x80 +.endm + +.macro filter_x c0 + mov lr, \c0 + mov r7, #63 + + sxtb16 r6, r12 + sxtb16 r10, r12, ror #8 + smlabb r8, r6, lr, r7 + smlatb r6, r6, lr, r7 + smlabb r7, r10, lr, r7 + smultb r10, r10, lr + ssat r8, #8, r8, asr #7 + ssat r6, #8, r6, asr #7 + add r10, r10, #63 + ssat r7, #8, r7, asr #7 + ssat r10, #8, r10, asr #7 + + pkhbt r6, r8, r6, lsl #16 + pkhbt r10, r7, r10, lsl #16 + uxtb16 r6, r6 + uxtb16 r10, r10 + + mov32 lr, 0x80808080 + + orr r10, r6, r10, lsl #8 @ u = vp8_signed_char_clamp((63 + Filter2 * 27)>>7) + qsub8 r8, r9, r10 @ s = vp8_signed_char_clamp(qs0 - u) + qadd8 r10, r11, r10 @ s = vp8_signed_char_clamp(ps0 + u) + eor r8, r8, lr @ *oq0 = s ^ 0x80 + eor r10, r10, lr @ *op0 = s ^ 0x80 +.endm + +.macro filter_1 + ldm sp, {r8, r9} + qadd8 r11, r8, lr + qsub8 r9, r9, r7 + bic r12, r12, r6 @ vp8_filter &= ~hev + filter_x #27 +.endm + +.macro filter_2 + ldr r9, [sp, #8] @ qs1 + ldr r11, [sp, #12] @ ps1 + filter_x #18 +.endm + +.macro filter_3 + eor r9, r9, lr + eor r11, r11, lr + filter_x #9 +.endm + +function vp8_v_loop_filter_inner_armv6 + mov r5, #4 + sub sp, sp, #16 + + orr r2, r2, r2, lsl #16 + orr r3, r3, r3, lsl #16 + orr r6, r6, r6, lsl #16 + orr r4, r2, r2, lsl #8 @ flimE + orr r2, r3, r3, lsl #8 @ flimI + orr r3, r6, r6, lsl #8 @ thresh +1: + sub r0, r0, r1, lsl #2 + ldr r10, [r0, r1] @ p2 + ldr_post r9, r0, r1, lsl #1 @ p3 + ldr r12, [r0, r1] @ p0 + ldr_post r11, r0, r1, lsl #1 @ p1 + + filter_mask_v + cmp lr, #0 + beq 2f + filter_v inner=1 + filter_inner + +A str r11, [r0, -r1, lsl #1] @ op1 +A str r8, [r0, -r1] @ op0 +T sub r0, r0, r1, lsl #1 +T str r8, [r0, r1] +T str_post r11, r0, r1, lsl #1 + str r9, [r0] @ oq0 + str r10, [r0, r1] @ oq1 +2: + add r0, r0, #4 + cmp r5, #3 + it eq + ldreq r0, [sp, #16] + subs r5, r5, #1 + bne 1b + + add sp, sp, #16 + pop {r0, r4-r11, pc} +endfunc + +function ff_vp8_v_loop_filter16_inner_armv6, export=1 + push {r4-r11, lr} + add r12, r0, #8 + push {r12} + ldr r6, [sp, #40] + orr r2, r2, r2, lsl #16 + b vp8_v_loop_filter_inner_armv6 +endfunc + +function ff_vp8_v_loop_filter8uv_inner_armv6, export=1 + push {r1, r4-r11, lr} + mov r1, r2 + orr r2, r3, r3, lsl #16 + ldr r3, [sp, #40] + ldr r6, [sp, #44] + b vp8_v_loop_filter_inner_armv6 +endfunc + +function vp8_v_loop_filter_armv6 + mov r5, #4 + sub sp, sp, #16 + + orr r3, r3, r3, lsl #16 + orr r6, r6, r6, lsl #16 + orr r4, r2, r2, lsl #8 @ flimE + orr r2, r3, r3, lsl #8 @ flimI + orr r3, r6, r6, lsl #8 @ thresh +1: + sub r0, r0, r1, lsl #2 + ldr r10, [r0, r1] @ p2 + ldr_post r9, r0, r1, lsl #1 @ p3 + ldr r12, [r0, r1] @ p0 + ldr_post r11, r0, r1, lsl #1 @ p1 + + filter_mask_v + cmp lr, #0 + beq 2f + + filter_v inner=0 + filter_1 + + str r8, [r0] @ *oq0 +A str r10, [r0, -r1] @ *op0 +T sub r0, r0, r1, lsl #1 +T str r10, [r0, r1] + + filter_2 + +A str r10, [r0, -r1, lsl #1] @ *op1 +T str_post r10, r0, r1, lsl #1 + str r8, [r0, r1] @ *oq1 + + ldr r9, [r0, r1, lsl #1] @ q2 + add r0, r0, r1 +A ldr r11, [r0, -r1, lsl #2] @ p2 +T ldr_dpre r11, r0, r1, lsl #2 + + filter_3 + +A str r10, [r0, -r1, lsl #2] @ *op2 +T str_post r10, r0, r1, lsl #2 + str r8, [r0, r1] @ *oq2 + sub r0, r0, r1 +2: + add r0, r0, #4 + cmp r5, #3 + it eq + ldreq r0, [sp, #16] + subs r5, r5, #1 + bne 1b + + add sp, sp, #16 + pop {r0, r4-r11, pc} +endfunc + +function ff_vp8_v_loop_filter16_armv6, export=1 + push {r4-r11, lr} + add r12, r0, #8 + push {r12} + ldr r6, [sp, #40] + orr r2, r2, r2, lsl #16 + b vp8_v_loop_filter_armv6 +endfunc + +function ff_vp8_v_loop_filter8uv_armv6, export=1 + push {r1, r4-r11, lr} + mov r1, r2 + orr r2, r3, r3, lsl #16 + ldr r3, [sp, #40] + ldr r6, [sp, #44] + b vp8_v_loop_filter_armv6 +endfunc + +@ void vp8_h_loop_filter16_simple(uint8_t *dst, int stride, int flim) +function ff_vp8_h_loop_filter16_simple_armv6, export=1 + push {r4-r11, lr} + orr r12, r2, r2, lsl #16 + mov32 r2, 0x80808080 + orr r12, r12, r12, lsl #8 + + mov lr, #0 + mov r11, #4 +1: + sub r0, r0, #2 + ldr r8, [r0, r1] + ldr_post r7, r0, r1, lsl #1 + ldr r10, [r0, r1] + ldr_post r9, r0, r1, lsl #1 + add r0, r0, #2 + transpose r6, r5, r4, r3, r7, r8, r9, r10 + simple_filter + sub r0, r0, r1, lsl #2 + sub r0, r0, #1 + + uxtb16 r6, r4 + uxtb16 r8, r5 + uxtb16 r7, r4, ror #8 + uxtb16 r9, r5, ror #8 + orr r6, r6, r8, lsl #8 + orr r7, r7, r9, lsl #8 + lsr r4, r6, #16 + lsr r5, r7, #16 + + strh_post r6, r0, r1 + strh_post r7, r0, r1 + strh_post r4, r0, r1 + strh_post r5, r0, r1 + add r0, r0, #1 +2: + subs r11, r11, #1 + bne 1b + + pop {r4-r11, pc} +endfunc + +function vp8_h_loop_filter_inner_armv6 + mov r5, #4 + sub sp, sp, #16 + + orr r3, r3, r3, lsl #16 + orr r9, r9, r9, lsl #16 + orr r4, r2, r2, lsl #8 @ flimE + orr r2, r3, r3, lsl #8 @ flimI + orr r3, r9, r9, lsl #8 @ thresh + sub r0, r0, #4 +1: + ldr r7, [r0, r1] + ldr_post r6, r0, r1, lsl #1 + ldr lr, [r0, r1] + ldr_post r8, r0, r1, lsl #1 + + filter_mask_h + + cmp lr, #0 + sub r0, r0, #2 + beq 2f + + ldr r6, [sp] + + filter_h inner=1 + filter_inner + + transpose lr, r12, r7, r6, r11, r8, r9, r10 + +A str r6, [r0, -r1, lsl #1] +A str r7, [r0, -r1] +T sub r0, r0, r1, lsl #1 +T str r7, [r0, r1] +T str_post r6, r0, r1, lsl #1 + str r12, [r0] + str lr, [r0, r1] +2: + sub r0, r0, #2 + add r0, r0, r1, lsl #1 + cmp r5, #3 + it eq + ldreq r0, [sp, #16] + subs r5, r5, #1 + bne 1b + + add sp, sp, #16 + pop {r0, r4-r11, pc} +endfunc + +function ff_vp8_h_loop_filter16_inner_armv6, export=1 + push {r4-r11, lr} + add r12, r0, r1, lsl #3 + sub r12, r12, #4 + push {r12} + ldr r9, [sp, #40] + orr r2, r2, r2, lsl #16 + b vp8_h_loop_filter_inner_armv6 +endfunc + +function ff_vp8_h_loop_filter8uv_inner_armv6, export=1 + sub r1, r1, #4 + push {r1, r4-r11, lr} + mov r1, r2 + orr r2, r3, r3, lsl #16 + ldr r3, [sp, #40] + ldr r9, [sp, #44] + b vp8_h_loop_filter_inner_armv6 +endfunc + +function vp8_h_loop_filter_armv6 + mov r5, #4 + sub sp, sp, #16 + + orr r3, r3, r3, lsl #16 + orr r9, r9, r9, lsl #16 + orr r4, r2, r2, lsl #8 @ flimE + orr r2, r3, r3, lsl #8 @ flimI + orr r3, r9, r9, lsl #8 @ thresh +1: + sub r0, r0, #4 + ldr r7, [r0, r1] + ldr_post r6, r0, r1, lsl #1 + ldr lr, [r0, r1] + ldr_post r8, r0, r1, lsl #1 + + filter_mask_h + cmp lr, #0 + it eq + addeq r0, r0, r1, lsl #1 + beq 2f + + ldr r6, [sp] + sub r0, r0, #2 + + filter_h inner=0 + filter_1 + + sub r0, r0, r1, lsl #1 + uxtb16 r6, r10 + uxtb16 r7, r8 + uxtb16 r10, r10, ror #8 + uxtb16 r8, r8, ror #8 + orr r6, r6, r7, lsl #8 + orr r10, r10, r8, lsl #8 + lsr r7, r6, #16 + lsr r8, r10, #16 + + add r0, r0, #1 + strh_post r6, r0, r1 + strh_post r10, r0, r1 + strh_post r7, r0, r1 + strh_post r8, r0, r1 + + filter_2 + + sub r0, r0, r1, lsl #2 + add r0, r0, #3 + + ldrb r11, [r0, #-5] @ p2 for 1/7th difference + strb r10, [r0, #-4] @ op1 + strb r8, [r0, #-1] @ oq1 + ldrb_post r9, r0, r1 @ q2 for 1/7th difference + + lsr r10, r10, #8 + lsr r8, r8, #8 + + ldrb r6, [r0, #-5] + strb r10, [r0, #-4] + strb r8, [r0, #-1] + ldrb_post r7, r0, r1 + + lsr r10, r10, #8 + lsr r8, r8, #8 + orr r11, r11, r6, lsl #8 + orr r9, r9, r7, lsl #8 + + ldrb r6, [r0, #-5] + strb r10, [r0, #-4] + strb r8, [r0, #-1] + ldrb_post r7, r0, r1 + + lsr r10, r10, #8 + lsr r8, r8, #8 + orr r11, r11, r6, lsl #16 + orr r9, r9, r7, lsl #16 + + ldrb r6, [r0, #-5] + strb r10, [r0, #-4] + strb r8, [r0, #-1] + ldrb_post r7, r0, r1 + orr r11, r11, r6, lsl #24 + orr r9, r9, r7, lsl #24 + + filter_3 + + sub r0, r0, r1, lsl #2 + strb r10, [r0, #-5] + strb_post r8, r0, r1 + lsr r10, r10, #8 + lsr r8, r8, #8 + strb r10, [r0, #-5] + strb_post r8, r0, r1 + lsr r10, r10, #8 + lsr r8, r8, #8 + strb r10, [r0, #-5] + strb_post r8, r0, r1 + lsr r10, r10, #8 + lsr r8, r8, #8 + strb r10, [r0, #-5] + strb_post r8, r0, r1 + + sub r0, r0, #2 +2: + cmp r5, #3 + it eq + ldreq r0, [sp, #16] + subs r5, r5, #1 + bne 1b + + add sp, sp, #16 + pop {r0, r4-r11, pc} +endfunc + +function ff_vp8_h_loop_filter16_armv6, export=1 + push {r4-r11, lr} + add r12, r0, r1, lsl #3 + push {r12} + ldr r9, [sp, #40] + orr r2, r2, r2, lsl #16 + b vp8_h_loop_filter_armv6 +endfunc + +function ff_vp8_h_loop_filter8uv_armv6, export=1 + push {r1, r4-r11, lr} + mov r1, r2 + orr r2, r3, r3, lsl #16 + ldr r3, [sp, #40] + ldr r9, [sp, #44] + b vp8_h_loop_filter_armv6 +endfunc + +.ltorg + +@ MC + +@ void put_vp8_pixels16(uint8_t *dst, int dststride, uint8_t *src, +@ int srcstride, int h, int mx, int my) +function ff_put_vp8_pixels16_armv6, export=1 + push {r4-r11} + ldr r12, [sp, #32] @ h +1: + subs r12, r12, #2 + ldr r5, [r2, #4] + ldr r6, [r2, #8] + ldr r7, [r2, #12] + ldr_post r4, r2, r3 + ldr r9, [r2, #4] + ldr r10, [r2, #8] + ldr r11, [r2, #12] + ldr_post r8, r2, r3 + strd r6, r7, [r0, #8] + strd_post r4, r5, r0, r1 + strd r10, r11, [r0, #8] + strd_post r8, r9, r0, r1 + bgt 1b + pop {r4-r11} + bx lr +endfunc + +@ void put_vp8_pixels8(uint8_t *dst, int dststride, uint8_t *src, +@ int srcstride, int h, int mx, int my) +function ff_put_vp8_pixels8_armv6, export=1 + push {r4-r11} + ldr r12, [sp, #32] @ h +1: + subs r12, r12, #4 + ldr r5, [r2, #4] + ldr_post r4, r2, r3 + ldr r7, [r2, #4] + ldr_post r6, r2, r3 + ldr r9, [r2, #4] + ldr_post r8, r2, r3 + ldr r11, [r2, #4] + ldr_post r10, r2, r3 + strd_post r4, r5, r0, r1 + strd_post r6, r7, r0, r1 + strd_post r8, r9, r0, r1 + strd_post r10, r11, r0, r1 + bgt 1b + pop {r4-r11} + bx lr +endfunc + +@ void put_vp8_pixels4(uint8_t *dst, int dststride, uint8_t *src, +@ int srcstride, int h, int mx, int my) +function ff_put_vp8_pixels4_armv6, export=1 + ldr r12, [sp, #0] @ h + push {r4-r6,lr} +1: + subs r12, r12, #4 + ldr_post r4, r2, r3 + ldr_post r5, r2, r3 + ldr_post r6, r2, r3 + ldr_post lr, r2, r3 + str_post r4, r0, r1 + str_post r5, r0, r1 + str_post r6, r0, r1 + str_post lr, r0, r1 + bgt 1b + pop {r4-r6,pc} +endfunc + +@ note: worst case sum of all 6-tap filter values * 255 is 0x7f80 so 16 bit +@ arithmatic can be used to apply filters +const sixtap_filters_13245600, align=4 + .short 2, 108, -11, 36, -8, 1, 0, 0 + .short 3, 77, -16, 77, -16, 3, 0, 0 + .short 1, 36, -8, 108, -11, 2, 0, 0 +endconst + +const fourtap_filters_1324, align=4 + .short -6, 12, 123, -1 + .short -9, 50, 93, -6 + .short -6, 93, 50, -9 + .short -1, 123, 12, -6 +endconst + +.macro vp8_mc_1 name, size, hv +function ff_put_vp8_\name\size\()_\hv\()_armv6, export=1 + sub r1, r1, #\size + mov r12, sp + push {r1, r4-r11, lr} + ldm r12, {r5-r7} + mov r4, #\size + stm r12, {r4, r5} + orr r12, r6, r7 + b vp8_put_\name\()_\hv\()_armv6 + 4 +endfunc +.endm + +vp8_mc_1 epel, 16, h6 +vp8_mc_1 epel, 16, v6 +vp8_mc_1 epel, 8, h6 +vp8_mc_1 epel, 8, v6 +vp8_mc_1 epel, 8, h4 +vp8_mc_1 epel, 8, v4 +vp8_mc_1 epel, 4, h6 +vp8_mc_1 epel, 4, v6 +vp8_mc_1 epel, 4, h4 +vp8_mc_1 epel, 4, v4 + +vp8_mc_1 bilin, 16, h +vp8_mc_1 bilin, 16, v +vp8_mc_1 bilin, 8, h +vp8_mc_1 bilin, 8, v +vp8_mc_1 bilin, 4, h +vp8_mc_1 bilin, 4, v + +/* True relational expressions have the value -1 in the GNU assembler, + +1 in Apple's. */ +#ifdef __APPLE__ +# define TMPSIZE \size * (8 + 8*(\size > 4) + \ytaps - 1) +#else +# define TMPSIZE \size * (8 - 8*(\size > 4) + \ytaps - 1) +#endif + +.macro vp8_mc_hv name, size, h, v, ytaps +function ff_put_vp8_\name\size\()_\h\v\()_armv6, export=1 + push {r0, r1, r4, lr} + add r0, sp, #16 + sub sp, sp, #TMPSIZE+16 + ldm r0, {r0, r12} + mov r4, #\size + add lr, r0, #\ytaps-1 + .if \ytaps > 2 + sub r2, r2, r3, lsl #\ytaps >> 1 & 1 + .endif + stm sp, {r4, lr} + add r0, sp, #16 + mov r1, #0 + bl vp8_put_\name\()_\h\()_armv6 + add r0, sp, #TMPSIZE+16 + ldr lr, [sp, #TMPSIZE+16+16] + ldm r0, {r0, r1} + mov r3, #\size + ldr r12, [sp, #TMPSIZE+16+16+8] + str lr, [sp, #4] + add r2, sp, #16 + \size * (\ytaps / 2 - 1) + sub r1, r1, #\size + bl vp8_put_\name\()_\v\()_armv6 + add sp, sp, #TMPSIZE+16+8 + pop {r4, pc} +endfunc +.endm + +vp8_mc_hv epel, 16, h6, v6, 6 +vp8_mc_hv epel, 8, h6, v6, 6 +vp8_mc_hv epel, 8, h4, v6, 6 +vp8_mc_hv epel, 8, h6, v4, 4 +vp8_mc_hv epel, 8, h4, v4, 4 +vp8_mc_hv epel, 4, h6, v6, 6 +vp8_mc_hv epel, 4, h4, v6, 6 +vp8_mc_hv epel, 4, h6, v4, 4 +vp8_mc_hv epel, 4, h4, v4, 4 + +vp8_mc_hv bilin, 16, h, v, 2 +vp8_mc_hv bilin, 8, h, v, 2 +vp8_mc_hv bilin, 4, h, v, 2 + +.macro sat4 r0, r1, r2, r3 + asr \r0, \r0, #7 + asr \r1, \r1, #7 + pkhbt \r0, \r0, \r2, lsl #9 + pkhbt \r1, \r1, \r3, lsl #9 + usat16 \r0, #8, \r0 + usat16 \r1, #8, \r1 + orr \r0, \r0, \r1, lsl #8 +.endm + +@ Calling convention for the inner MC functions: +@ r0 dst +@ r1 dst_stride - block_width +@ r2 src +@ r3 src_stride +@ r4 block_width +@ r12 filter_index +@ [sp] block_width +@ [sp+4] height +@ [sp+8] scratch + +function vp8_put_epel_h6_armv6 + push {r1, r4-r11, lr} + sub r2, r2, #2 + movrel lr, sixtap_filters_13245600 - 16 + add lr, lr, r12, lsl #3 + sub r3, r3, r4 + str r3, [sp, #48] + ldm lr, {r1, r3, lr} +1: + ldr r7, [r2, #5] @ src[5-8] + ldr r6, [r2, #2] @ src[2-5] + ldr r5, [r2], #4 @ src[0-3] + + pkhtb r7, r7, r7, asr #8 @ src[8,7,7,6] + uxtb16 r9, r6, ror #8 @ src[5] | src[3] + uxtb16 r6, r6 @ src[4] | src[2] + uxtb16 r8, r5, ror #8 @ src[3] | src[1] + uxtb16 r11, r7, ror #8 @ src[8] | src[7] + uxtb16 r7, r7 @ src[7] | src[6] + uxtb16 r5, r5 @ src[2] | src[0] + + mov r10, #0x40 + smlad r5, r5, r1, r10 @ filter[0][0] + smlad r11, r11, lr, r10 @ filter[3][2] + smlad r12, r7, lr, r10 @ filter[2][2] + smlad r10, r8, r1, r10 @ filter[1][0] + smlad r5, r8, r3, r5 @ filter[0][1] + smlad r11, r9, r1, r11 @ filter[3][0] + smlad r12, r9, r3, r12 @ filter[2][1] + pkhtb r9, r9, r6, asr #16 @ src[5] | src[4] + smlad r10, r6, r3, r10 @ filter[1][1] + pkhbt r7, r9, r7, lsl #16 @ src[6] | src[4] + smlad r5, r9, lr, r5 @ filter[0][2] + pkhtb r8, r7, r9, asr #16 @ src[6] | src[5] + smlad r11, r7, r3, r11 @ filter[3][1] + smlad r9, r8, lr, r10 @ filter[1][2] + smlad r7, r6, r1, r12 @ filter[2][0] + + subs r4, r4, #4 + + sat4 r5, r9, r7, r11 + str r5, [r0], #4 + + bne 1b + + add r4, sp, #40 + ldm r4, {r4, r5, r12} + ldr r6, [sp] + subs r5, r5, #1 + add r2, r2, r12 + str r5, [sp, #44] + add r0, r0, r6 + + bne 1b + + pop {r1, r4-r11, pc} +endfunc + +function vp8_put_epel_v6_armv6 + push {r1, r4-r11, lr} + movrel lr, sixtap_filters_13245600 - 16 + add lr, lr, r12, lsl #3 + str r3, [sp, #48] +1: + add r1, r3, r3, lsl #1 @ stride * 3 + ldr_nreg r5, r2, r3 @ src[0,1,2,3 + stride * 1] + ldr r6, [r2, r3] @ src[0,1,2,3 + stride * 3] + ldr r7, [r2, r3, lsl #1] @ src[0,1,2,3 + stride * 4] + ldr r8, [r2, r1] @ src[0,1,2,3 + stride * 5] + + uxtb16 r9, r5, ror #8 @ src[3 + s*1] | src[1 + s*1] + uxtb16 r10, r6, ror #8 @ src[3 + s*3] | src[1 + s*3] + uxtb16 r11, r7, ror #8 @ src[3 + s*4] | src[1 + s*4] + uxtb16 r12, r8, ror #8 @ src[3 + s*5] | src[1 + s*5] + uxtb16 r5, r5 @ src[2 + s*1] | src[0 + s*1] + uxtb16 r6, r6 @ src[2 + s*3] | src[0 + s*3] + uxtb16 r7, r7 @ src[2 + s*4] | src[0 + s*4] + uxtb16 r8, r8 @ src[2 + s*5] | src[0 + s*5] + pkhbt r1, r9, r10, lsl #16 @ src[1 + s*3] | src[1 + s*1] + pkhtb r9, r10, r9, asr #16 @ src[3 + s*3] | src[3 + s*1] + pkhbt r10, r11, r12, lsl #16 @ src[1 + s*5] | src[1 + s*4] + pkhtb r11, r12, r11, asr #16 @ src[3 + s*5] | src[3 + s*4] + pkhbt r12, r5, r6, lsl #16 @ src[0 + s*3] | src[0 + s*1] + pkhtb r5, r6, r5, asr #16 @ src[2 + s*3] | src[2 + s*1] + pkhbt r6, r7, r8, lsl #16 @ src[0 + s*5] | src[0 + s*4] + pkhtb r7, r8, r7, asr #16 @ src[2 + s*5] | src[2 + s*4] + + ldr r8, [lr, #4] + mov r3, #0x40 + smlad r12, r12, r8, r3 @ filter[0][1] + smlad r1, r1, r8, r3 @ filter[1][1] + smlad r5, r5, r8, r3 @ filter[2][1] + smlad r9, r9, r8, r3 @ filter[3][1] + ldr r8, [lr, #8] + ldr r3, [sp, #48] + smlad r12, r6, r8, r12 @ filter[0][2] + smlad r1, r10, r8, r1 @ filter[1][2] + ldr_nreg r6, r2, r3, lsl #1 @ src[0,1,2,3 + stride * 0] + ldr r10, [r2], #4 @ src[0,1,2,3 + stride * 2] + smlad r5, r7, r8, r5 @ filter[2][2] + smlad r9, r11, r8, r9 @ filter[3][2] + + uxtb16 r7, r6, ror #8 @ src[3 + s*0] | src[1 + s*0] + uxtb16 r11, r10, ror #8 @ src[3 + s*2] | src[1 + s*2] + uxtb16 r6, r6 @ src[2 + s*0] | src[0 + s*0] + uxtb16 r10, r10 @ src[2 + s*2] | src[0 + s*2] + + pkhbt r8, r7, r11, lsl #16 @ src[1 + s*2] | src[1 + s*0] + pkhtb r7, r11, r7, asr #16 @ src[3 + s*2] | src[3 + s*0] + pkhbt r11, r6, r10, lsl #16 @ src[0 + s*2] | src[0 + s*0] + pkhtb r6, r10, r6, asr #16 @ src[2 + s*2] | src[2 + s*0] + + ldr r10, [lr] + subs r4, r4, #4 + smlad r12, r11, r10, r12 @ filter[0][0] + smlad r1, r8, r10, r1 @ filter[1][0] + smlad r5, r6, r10, r5 @ filter[2][0] + smlad r9, r7, r10, r9 @ filter[3][0] + + sat4 r12, r1, r5, r9 + str r12, [r0], #4 + + bne 1b + + ldrd r4, r5, [sp, #40] + ldr r6, [sp] + subs r5, r5, #1 + sub r2, r2, r4 + str r5, [sp, #44] + add r0, r0, r6 + add r2, r2, r3 + + bne 1b + + pop {r1, r4-r11, pc} +endfunc + +function vp8_put_epel_h4_armv6 + push {r1, r4-r11, lr} + subs r2, r2, #1 + movrel lr, fourtap_filters_1324 - 4 + add lr, lr, r12, lsl #2 + sub r3, r3, r4 + ldm lr, {r5, r6} + ldr lr, [sp, #44] +1: + ldr r9, [r2, #3] + ldr r8, [r2, #2] + ldr r7, [r2], #4 + + uxtb16 r9, r9, ror #8 @ src[6] | src[4] + uxtb16 r10, r8, ror #8 @ src[5] | src[3] + uxtb16 r8, r8 @ src[4] | src[2] + uxtb16 r11, r7, ror #8 @ src[3] | src[1] + uxtb16 r7, r7 @ src[2] | src[0] + + mov r12, #0x40 + smlad r9, r9, r6, r12 @ filter[3][1] + smlad r7, r7, r5, r12 @ filter[0][0] + smlad r9, r10, r5, r9 @ filter[3][0] + smlad r10, r10, r6, r12 @ filter[2][1] + smlad r12, r11, r5, r12 @ filter[1][0] + smlad r7, r11, r6, r7 @ filter[0][1] + smlad r10, r8, r5, r10 @ filter[2][0] + smlad r12, r8, r6, r12 @ filter[1][1] + + subs r4, r4, #4 + + sat4 r7, r12, r10, r9 + str r7, [r0], #4 + + bne 1b + + subs lr, lr, #1 + ldr r4, [sp, #40] + add r2, r2, r3 + add r0, r0, r1 + + bne 1b + + pop {r1, r4-r11, pc} +endfunc + +function vp8_put_epel_v4_armv6 + push {r1, r4-r11, lr} + movrel lr, fourtap_filters_1324 - 4 + add lr, lr, r12, lsl #2 + ldm lr, {r5, r6} + str r3, [sp, #48] +1: + ldr lr, [r2, r3, lsl #1] + ldr r12, [r2, r3] + ldr_nreg r7, r2, r3 + ldr r11, [r2], #4 + + uxtb16 r8, lr, ror #8 @ src[3 + s*3] | src[1 + s*3] + uxtb16 r9, r12, ror #8 @ src[3 + s*2] | src[1 + s*2] + uxtb16 r3, r7, ror #8 @ src[3 + s*0] | src[1 + s*0] + uxtb16 r1, r11, ror #8 @ src[3 + s*1] | src[1 + s*1] + uxtb16 lr, lr @ src[2 + s*3] | src[0 + s*3] + uxtb16 r12, r12 @ src[2 + s*2] | src[0 + s*2] + uxtb16 r7, r7 @ src[2 + s*0] | src[0 + s*0] + uxtb16 r11, r11 @ src[2 + s*1] | src[0 + s*1] + pkhbt r10, r1, r8, lsl #16 @ src[1 + s*3] | src[1 + s*1] + pkhtb r1, r8, r1, asr #16 @ src[3 + s*3] | src[3 + s*1] + pkhbt r8, r3, r9, lsl #16 @ src[1 + s*2] | src[1 + s*0] + pkhtb r3, r9, r3, asr #16 @ src[3 + s*2] | src[3 + s*0] + pkhbt r9, r11, lr, lsl #16 @ src[0 + s*3] | src[0 + s*1] + pkhtb r11, lr, r11, asr #16 @ src[2 + s*3] | src[2 + s*1] + pkhbt lr, r7, r12, lsl #16 @ src[0 + s*2] | src[0 + s*0] + pkhtb r7, r12, r7, asr #16 @ src[2 + s*2] | src[2 + s*0] + + mov r12, #0x40 + smlad r9, r9, r6, r12 @ filter[0][1] + smlad r10, r10, r6, r12 @ filter[1][1] + smlad r11, r11, r6, r12 @ filter[2][1] + smlad r1, r1, r6, r12 @ filter[3][1] + smlad r9, lr, r5, r9 @ filter[0][0] + smlad r10, r8, r5, r10 @ filter[1][0] + smlad r11, r7, r5, r11 @ filter[2][0] + smlad r1, r3, r5, r1 @ filter[3][0] + + subs r4, r4, #4 + ldr r3, [sp, #48] + + sat4 r9, r10, r11, r1 + str r9, [r0], #4 + + bne 1b + + ldr r4, [sp, #40] + ldr r12, [sp, #44] + add r2, r2, r3 + ldr r9, [sp, #0] + subs r12, r12, #1 + sub r2, r2, r4 + str r12, [sp, #44] + add r0, r0, r9 + + bne 1b + + pop {r1, r4-r11, pc} +endfunc + +function vp8_put_bilin_h_armv6 + push {r1, r4-r11, lr} + rsb r5, r12, r12, lsl #16 + ldr r12, [sp, #44] + sub r3, r3, r4 + add r5, r5, #8 +1: + ldrb r6, [r2], #1 + ldrb r7, [r2], #1 + ldrb r8, [r2], #1 + ldrb r9, [r2], #1 + ldrb lr, [r2] + + pkhbt r6, r6, r7, lsl #16 @ src[1] | src[0] + pkhbt r7, r7, r8, lsl #16 @ src[2] | src[1] + pkhbt r8, r8, r9, lsl #16 @ src[3] | src[2] + pkhbt r9, r9, lr, lsl #16 @ src[4] | src[3] + + mov r10, #4 + smlad r6, r6, r5, r10 + smlad r7, r7, r5, r10 + smlad r8, r8, r5, r10 + smlad r9, r9, r5, r10 + + subs r4, r4, #4 + + asr r6, #3 + asr r7, #3 + pkhbt r6, r6, r8, lsl #13 + pkhbt r7, r7, r9, lsl #13 + orr r6, r6, r7, lsl #8 + str r6, [r0], #4 + + bne 1b + + ldr r4, [sp, #40] + subs r12, r12, #1 + add r2, r2, r3 + add r0, r0, r1 + + bne 1b + + pop {r1, r4-r11, pc} +endfunc + +function vp8_put_bilin_v_armv6 + push {r1, r4-r11, lr} + rsb r5, r12, r12, lsl #16 + ldr r12, [sp, #44] + add r5, r5, #8 +1: + ldrb r10, [r2, r3] + ldrb r6, [r2], #1 + ldrb r11, [r2, r3] + ldrb r7, [r2], #1 + ldrb lr, [r2, r3] + ldrb r8, [r2], #1 + ldrb r9, [r2, r3] + pkhbt r6, r6, r10, lsl #16 + ldrb r10, [r2], #1 + pkhbt r7, r7, r11, lsl #16 + pkhbt r8, r8, lr, lsl #16 + pkhbt r9, r10, r9, lsl #16 + + mov r10, #4 + smlad r6, r6, r5, r10 + smlad r7, r7, r5, r10 + smlad r8, r8, r5, r10 + smlad r9, r9, r5, r10 + + subs r4, r4, #4 + + asr r6, #3 + asr r7, #3 + pkhbt r6, r6, r8, lsl #13 + pkhbt r7, r7, r9, lsl #13 + orr r6, r6, r7, lsl #8 + str r6, [r0], #4 + + bne 1b + + ldr r4, [sp, #40] + subs r12, r12, #1 + add r2, r2, r3 + add r0, r0, r1 + sub r2, r2, r4 + + bne 1b + pop {r1, r4-r11, pc} +endfunc diff --git a/ffmpeg/libavcodec/arm/vp8dsp_init_arm.c b/ffmpeg/libavcodec/arm/vp8dsp_init_arm.c new file mode 100644 index 0000000..d360ae3 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8dsp_init_arm.c @@ -0,0 +1,34 @@ +/* + * 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 "libavutil/attributes.h" +#include "libavutil/arm/cpu.h" +#include "libavcodec/vp8dsp.h" +#include "vp8dsp.h" + +av_cold void ff_vp8dsp_init_arm(VP8DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_armv6(cpu_flags)) + ff_vp8dsp_init_armv6(dsp); + if (have_neon(cpu_flags)) + ff_vp8dsp_init_neon(dsp); +} diff --git a/ffmpeg/libavcodec/arm/vp8dsp_init_armv6.c b/ffmpeg/libavcodec/arm/vp8dsp_init_armv6.c new file mode 100644 index 0000000..e15e191 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8dsp_init_armv6.c @@ -0,0 +1,120 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/vp8dsp.h" +#include "vp8dsp.h" + +void ff_vp8_luma_dc_wht_armv6(int16_t block[4][4][16], int16_t dc[16]); +void ff_vp8_luma_dc_wht_dc_armv6(int16_t block[4][4][16], int16_t dc[16]); + +void ff_vp8_idct_add_armv6(uint8_t *dst, int16_t block[16], ptrdiff_t stride); +void ff_vp8_idct_dc_add_armv6(uint8_t *dst, int16_t block[16], ptrdiff_t stride); +void ff_vp8_idct_dc_add4y_armv6(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); +void ff_vp8_idct_dc_add4uv_armv6(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); + +VP8_LF(armv6); + +VP8_EPEL(16, armv6); +VP8_EPEL(8, armv6); +VP8_EPEL(4, armv6); + +VP8_BILIN(16, armv6); +VP8_BILIN(8, armv6); +VP8_BILIN(4, armv6); + +av_cold void ff_vp8dsp_init_armv6(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_armv6; + dsp->vp8_luma_dc_wht_dc = ff_vp8_luma_dc_wht_dc_armv6; + + dsp->vp8_idct_add = ff_vp8_idct_add_armv6; + dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_armv6; + dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_armv6; + dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_armv6; + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_armv6; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_armv6; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_armv6; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_armv6; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_armv6; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_armv6; + dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_armv6; + dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_armv6; + + dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter16_simple_armv6; + dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter16_simple_armv6; + + dsp->put_vp8_epel_pixels_tab[0][0][0] = ff_put_vp8_pixels16_armv6; + dsp->put_vp8_epel_pixels_tab[0][0][2] = ff_put_vp8_epel16_h6_armv6; + dsp->put_vp8_epel_pixels_tab[0][2][0] = ff_put_vp8_epel16_v6_armv6; + dsp->put_vp8_epel_pixels_tab[0][2][2] = ff_put_vp8_epel16_h6v6_armv6; + + dsp->put_vp8_epel_pixels_tab[1][0][0] = ff_put_vp8_pixels8_armv6; + dsp->put_vp8_epel_pixels_tab[1][0][1] = ff_put_vp8_epel8_h4_armv6; + dsp->put_vp8_epel_pixels_tab[1][0][2] = ff_put_vp8_epel8_h6_armv6; + dsp->put_vp8_epel_pixels_tab[1][1][0] = ff_put_vp8_epel8_v4_armv6; + dsp->put_vp8_epel_pixels_tab[1][1][1] = ff_put_vp8_epel8_h4v4_armv6; + dsp->put_vp8_epel_pixels_tab[1][1][2] = ff_put_vp8_epel8_h6v4_armv6; + dsp->put_vp8_epel_pixels_tab[1][2][0] = ff_put_vp8_epel8_v6_armv6; + dsp->put_vp8_epel_pixels_tab[1][2][1] = ff_put_vp8_epel8_h4v6_armv6; + dsp->put_vp8_epel_pixels_tab[1][2][2] = ff_put_vp8_epel8_h6v6_armv6; + + dsp->put_vp8_epel_pixels_tab[2][0][0] = ff_put_vp8_pixels4_armv6; + dsp->put_vp8_epel_pixels_tab[2][0][1] = ff_put_vp8_epel4_h4_armv6; + dsp->put_vp8_epel_pixels_tab[2][0][2] = ff_put_vp8_epel4_h6_armv6; + dsp->put_vp8_epel_pixels_tab[2][1][0] = ff_put_vp8_epel4_v4_armv6; + dsp->put_vp8_epel_pixels_tab[2][1][1] = ff_put_vp8_epel4_h4v4_armv6; + dsp->put_vp8_epel_pixels_tab[2][1][2] = ff_put_vp8_epel4_h6v4_armv6; + dsp->put_vp8_epel_pixels_tab[2][2][0] = ff_put_vp8_epel4_v6_armv6; + dsp->put_vp8_epel_pixels_tab[2][2][1] = ff_put_vp8_epel4_h4v6_armv6; + dsp->put_vp8_epel_pixels_tab[2][2][2] = ff_put_vp8_epel4_h6v6_armv6; + + dsp->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][0][1] = ff_put_vp8_bilin16_h_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][0][2] = ff_put_vp8_bilin16_h_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][1][0] = ff_put_vp8_bilin16_v_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][1][1] = ff_put_vp8_bilin16_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][1][2] = ff_put_vp8_bilin16_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][2][0] = ff_put_vp8_bilin16_v_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][2][1] = ff_put_vp8_bilin16_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[0][2][2] = ff_put_vp8_bilin16_hv_armv6; + + dsp->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][0][1] = ff_put_vp8_bilin8_h_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][0][2] = ff_put_vp8_bilin8_h_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][1][0] = ff_put_vp8_bilin8_v_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][1][1] = ff_put_vp8_bilin8_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][1][2] = ff_put_vp8_bilin8_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][2][0] = ff_put_vp8_bilin8_v_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][2][1] = ff_put_vp8_bilin8_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[1][2][2] = ff_put_vp8_bilin8_hv_armv6; + + dsp->put_vp8_bilinear_pixels_tab[2][0][0] = ff_put_vp8_pixels4_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][0][1] = ff_put_vp8_bilin4_h_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][0][2] = ff_put_vp8_bilin4_h_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][1][0] = ff_put_vp8_bilin4_v_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][1][1] = ff_put_vp8_bilin4_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][1][2] = ff_put_vp8_bilin4_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][2][0] = ff_put_vp8_bilin4_v_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][2][1] = ff_put_vp8_bilin4_hv_armv6; + dsp->put_vp8_bilinear_pixels_tab[2][2][2] = ff_put_vp8_bilin4_hv_armv6; +} diff --git a/ffmpeg/libavcodec/arm/vp8dsp_init_neon.c b/ffmpeg/libavcodec/arm/vp8dsp_init_neon.c new file mode 100644 index 0000000..0468181 --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8dsp_init_neon.c @@ -0,0 +1,116 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/vp8dsp.h" +#include "vp8dsp.h" + +void ff_vp8_luma_dc_wht_neon(int16_t block[4][4][16], int16_t dc[16]); + +void ff_vp8_idct_add_neon(uint8_t *dst, int16_t block[16], ptrdiff_t stride); +void ff_vp8_idct_dc_add_neon(uint8_t *dst, int16_t block[16], ptrdiff_t stride); +void ff_vp8_idct_dc_add4y_neon(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); +void ff_vp8_idct_dc_add4uv_neon(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); + +VP8_LF(neon); + +VP8_EPEL(16, neon); +VP8_EPEL(8, neon); +VP8_EPEL(4, neon); + +VP8_BILIN(16, neon); +VP8_BILIN(8, neon); +VP8_BILIN(4, neon); + +av_cold void ff_vp8dsp_init_neon(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_neon; + + dsp->vp8_idct_add = ff_vp8_idct_add_neon; + dsp->vp8_idct_dc_add = ff_vp8_idct_dc_add_neon; + dsp->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_neon; + dsp->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_neon; + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_neon; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_neon; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_neon; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_neon; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_neon; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_neon; + dsp->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_neon; + dsp->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_neon; + + dsp->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter16_simple_neon; + dsp->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter16_simple_neon; + + dsp->put_vp8_epel_pixels_tab[0][0][0] = ff_put_vp8_pixels16_neon; + dsp->put_vp8_epel_pixels_tab[0][0][2] = ff_put_vp8_epel16_h6_neon; + dsp->put_vp8_epel_pixels_tab[0][2][0] = ff_put_vp8_epel16_v6_neon; + dsp->put_vp8_epel_pixels_tab[0][2][2] = ff_put_vp8_epel16_h6v6_neon; + + dsp->put_vp8_epel_pixels_tab[1][0][0] = ff_put_vp8_pixels8_neon; + dsp->put_vp8_epel_pixels_tab[1][0][1] = ff_put_vp8_epel8_h4_neon; + dsp->put_vp8_epel_pixels_tab[1][0][2] = ff_put_vp8_epel8_h6_neon; + dsp->put_vp8_epel_pixels_tab[1][1][0] = ff_put_vp8_epel8_v4_neon; + dsp->put_vp8_epel_pixels_tab[1][1][1] = ff_put_vp8_epel8_h4v4_neon; + dsp->put_vp8_epel_pixels_tab[1][1][2] = ff_put_vp8_epel8_h6v4_neon; + dsp->put_vp8_epel_pixels_tab[1][2][0] = ff_put_vp8_epel8_v6_neon; + dsp->put_vp8_epel_pixels_tab[1][2][1] = ff_put_vp8_epel8_h4v6_neon; + dsp->put_vp8_epel_pixels_tab[1][2][2] = ff_put_vp8_epel8_h6v6_neon; + + dsp->put_vp8_epel_pixels_tab[2][0][1] = ff_put_vp8_epel4_h4_neon; + dsp->put_vp8_epel_pixels_tab[2][0][2] = ff_put_vp8_epel4_h6_neon; + dsp->put_vp8_epel_pixels_tab[2][1][0] = ff_put_vp8_epel4_v4_neon; + dsp->put_vp8_epel_pixels_tab[2][1][1] = ff_put_vp8_epel4_h4v4_neon; + dsp->put_vp8_epel_pixels_tab[2][1][2] = ff_put_vp8_epel4_h6v4_neon; + dsp->put_vp8_epel_pixels_tab[2][2][0] = ff_put_vp8_epel4_v6_neon; + dsp->put_vp8_epel_pixels_tab[2][2][1] = ff_put_vp8_epel4_h4v6_neon; + dsp->put_vp8_epel_pixels_tab[2][2][2] = ff_put_vp8_epel4_h6v6_neon; + + dsp->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_neon; + dsp->put_vp8_bilinear_pixels_tab[0][0][1] = ff_put_vp8_bilin16_h_neon; + dsp->put_vp8_bilinear_pixels_tab[0][0][2] = ff_put_vp8_bilin16_h_neon; + dsp->put_vp8_bilinear_pixels_tab[0][1][0] = ff_put_vp8_bilin16_v_neon; + dsp->put_vp8_bilinear_pixels_tab[0][1][1] = ff_put_vp8_bilin16_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[0][1][2] = ff_put_vp8_bilin16_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[0][2][0] = ff_put_vp8_bilin16_v_neon; + dsp->put_vp8_bilinear_pixels_tab[0][2][1] = ff_put_vp8_bilin16_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[0][2][2] = ff_put_vp8_bilin16_hv_neon; + + dsp->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_neon; + dsp->put_vp8_bilinear_pixels_tab[1][0][1] = ff_put_vp8_bilin8_h_neon; + dsp->put_vp8_bilinear_pixels_tab[1][0][2] = ff_put_vp8_bilin8_h_neon; + dsp->put_vp8_bilinear_pixels_tab[1][1][0] = ff_put_vp8_bilin8_v_neon; + dsp->put_vp8_bilinear_pixels_tab[1][1][1] = ff_put_vp8_bilin8_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[1][1][2] = ff_put_vp8_bilin8_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[1][2][0] = ff_put_vp8_bilin8_v_neon; + dsp->put_vp8_bilinear_pixels_tab[1][2][1] = ff_put_vp8_bilin8_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[1][2][2] = ff_put_vp8_bilin8_hv_neon; + + dsp->put_vp8_bilinear_pixels_tab[2][0][1] = ff_put_vp8_bilin4_h_neon; + dsp->put_vp8_bilinear_pixels_tab[2][0][2] = ff_put_vp8_bilin4_h_neon; + dsp->put_vp8_bilinear_pixels_tab[2][1][0] = ff_put_vp8_bilin4_v_neon; + dsp->put_vp8_bilinear_pixels_tab[2][1][1] = ff_put_vp8_bilin4_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[2][1][2] = ff_put_vp8_bilin4_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[2][2][0] = ff_put_vp8_bilin4_v_neon; + dsp->put_vp8_bilinear_pixels_tab[2][2][1] = ff_put_vp8_bilin4_hv_neon; + dsp->put_vp8_bilinear_pixels_tab[2][2][2] = ff_put_vp8_bilin4_hv_neon; +} diff --git a/ffmpeg/libavcodec/arm/vp8dsp_neon.S b/ffmpeg/libavcodec/arm/vp8dsp_neon.S new file mode 100644 index 0000000..04e7c5c --- /dev/null +++ b/ffmpeg/libavcodec/arm/vp8dsp_neon.S @@ -0,0 +1,1867 @@ +/* + * VP8 NEON optimisations + * + * Copyright (c) 2010 Rob Clark + * Copyright (c) 2011 Mans Rullgard + * + * 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 "libavutil/arm/asm.S" +#include "neon.S" + +function ff_vp8_luma_dc_wht_neon, export=1 + vld1.16 {q0-q1}, [r1,:128] + vmov.i16 q15, #0 + + vadd.i16 d4, d0, d3 + vadd.i16 d6, d1, d2 + vst1.16 {q15}, [r1,:128]! + vsub.i16 d7, d1, d2 + vsub.i16 d5, d0, d3 + vst1.16 {q15}, [r1,:128] + vadd.i16 q0, q2, q3 + vsub.i16 q1, q2, q3 + + vmov.i16 q8, #3 + + vtrn.32 d0, d2 + vtrn.32 d1, d3 + vtrn.16 d0, d1 + vtrn.16 d2, d3 + + vadd.i16 d0, d0, d16 + + vadd.i16 d4, d0, d3 + vadd.i16 d6, d1, d2 + vsub.i16 d7, d1, d2 + vsub.i16 d5, d0, d3 + vadd.i16 q0, q2, q3 + vsub.i16 q1, q2, q3 + + vshr.s16 q0, q0, #3 + vshr.s16 q1, q1, #3 + + mov r3, #32 + vst1.16 {d0[0]}, [r0,:16], r3 + vst1.16 {d1[0]}, [r0,:16], r3 + vst1.16 {d2[0]}, [r0,:16], r3 + vst1.16 {d3[0]}, [r0,:16], r3 + vst1.16 {d0[1]}, [r0,:16], r3 + vst1.16 {d1[1]}, [r0,:16], r3 + vst1.16 {d2[1]}, [r0,:16], r3 + vst1.16 {d3[1]}, [r0,:16], r3 + vst1.16 {d0[2]}, [r0,:16], r3 + vst1.16 {d1[2]}, [r0,:16], r3 + vst1.16 {d2[2]}, [r0,:16], r3 + vst1.16 {d3[2]}, [r0,:16], r3 + vst1.16 {d0[3]}, [r0,:16], r3 + vst1.16 {d1[3]}, [r0,:16], r3 + vst1.16 {d2[3]}, [r0,:16], r3 + vst1.16 {d3[3]}, [r0,:16], r3 + + bx lr +endfunc + +function ff_vp8_idct_add_neon, export=1 + vld1.16 {q0-q1}, [r1,:128] + movw r3, #20091 + movt r3, #35468/2 + vdup.32 d4, r3 + + vmull.s16 q12, d1, d4[0] + vmull.s16 q13, d3, d4[0] + vqdmulh.s16 d20, d1, d4[1] + vqdmulh.s16 d23, d3, d4[1] + vshrn.s32 d21, q12, #16 + vshrn.s32 d22, q13, #16 + vadd.s16 d21, d21, d1 + vadd.s16 d22, d22, d3 + + vadd.s16 d16, d0, d2 + vsub.s16 d17, d0, d2 + vadd.s16 d18, d21, d23 + vsub.s16 d19, d20, d22 + vadd.s16 q0, q8, q9 + vsub.s16 q1, q8, q9 + + vtrn.32 d0, d3 + vtrn.32 d1, d2 + vtrn.16 d0, d1 + vtrn.16 d3, d2 + + vmov.i16 q15, #0 + vmull.s16 q12, d1, d4[0] + vst1.16 {q15}, [r1,:128]! + vmull.s16 q13, d2, d4[0] + vst1.16 {q15}, [r1,:128] + vqdmulh.s16 d21, d1, d4[1] + vqdmulh.s16 d23, d2, d4[1] + vshrn.s32 d20, q12, #16 + vshrn.s32 d22, q13, #16 + vadd.i16 d20, d20, d1 + vadd.i16 d22, d22, d2 + + vadd.i16 d16, d0, d3 + vsub.i16 d17, d0, d3 + vadd.i16 d18, d20, d23 + vld1.32 {d20[]}, [r0,:32], r2 + vsub.i16 d19, d21, d22 + vld1.32 {d22[]}, [r0,:32], r2 + vadd.s16 q0, q8, q9 + vld1.32 {d23[]}, [r0,:32], r2 + vsub.s16 q1, q8, q9 + vld1.32 {d21[]}, [r0,:32], r2 + vrshr.s16 q0, q0, #3 + vtrn.32 q10, q11 + vrshr.s16 q1, q1, #3 + + sub r0, r0, r2, lsl #2 + + vtrn.32 d0, d3 + vtrn.32 d1, d2 + vtrn.16 d0, d1 + vtrn.16 d3, d2 + + vaddw.u8 q0, q0, d20 + vaddw.u8 q1, q1, d21 + vqmovun.s16 d0, q0 + vqmovun.s16 d1, q1 + + vst1.32 {d0[0]}, [r0,:32], r2 + vst1.32 {d0[1]}, [r0,:32], r2 + vst1.32 {d1[1]}, [r0,:32], r2 + vst1.32 {d1[0]}, [r0,:32], r2 + + bx lr +endfunc + +function ff_vp8_idct_dc_add_neon, export=1 + mov r3, #0 + ldrsh r12, [r1] + strh r3, [r1] + vdup.16 q1, r12 + vrshr.s16 q1, q1, #3 + vld1.32 {d0[]}, [r0,:32], r2 + vld1.32 {d1[]}, [r0,:32], r2 + vld1.32 {d0[1]}, [r0,:32], r2 + vld1.32 {d1[1]}, [r0,:32], r2 + vaddw.u8 q2, q1, d0 + vaddw.u8 q3, q1, d1 + sub r0, r0, r2, lsl #2 + vqmovun.s16 d0, q2 + vqmovun.s16 d1, q3 + vst1.32 {d0[0]}, [r0,:32], r2 + vst1.32 {d1[0]}, [r0,:32], r2 + vst1.32 {d0[1]}, [r0,:32], r2 + vst1.32 {d1[1]}, [r0,:32], r2 + bx lr +endfunc + +function ff_vp8_idct_dc_add4uv_neon, export=1 + vmov.i16 d0, #0 + mov r3, #32 + vld1.16 {d16[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vld1.16 {d17[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vld1.16 {d18[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vld1.16 {d19[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + mov r3, r0 + vrshr.s16 q8, q8, #3 @ dc >>= 3 + vld1.8 {d0}, [r0,:64], r2 + vrshr.s16 q9, q9, #3 + vld1.8 {d1}, [r0,:64], r2 + vaddw.u8 q10, q8, d0 + vld1.8 {d2}, [r0,:64], r2 + vaddw.u8 q0, q8, d1 + vld1.8 {d3}, [r0,:64], r2 + vaddw.u8 q11, q8, d2 + vld1.8 {d4}, [r0,:64], r2 + vaddw.u8 q1, q8, d3 + vld1.8 {d5}, [r0,:64], r2 + vaddw.u8 q12, q9, d4 + vld1.8 {d6}, [r0,:64], r2 + vaddw.u8 q2, q9, d5 + vld1.8 {d7}, [r0,:64], r2 + vaddw.u8 q13, q9, d6 + vqmovun.s16 d20, q10 + vaddw.u8 q3, q9, d7 + vqmovun.s16 d21, q0 + vqmovun.s16 d22, q11 + vst1.8 {d20}, [r3,:64], r2 + vqmovun.s16 d23, q1 + vst1.8 {d21}, [r3,:64], r2 + vqmovun.s16 d24, q12 + vst1.8 {d22}, [r3,:64], r2 + vqmovun.s16 d25, q2 + vst1.8 {d23}, [r3,:64], r2 + vqmovun.s16 d26, q13 + vst1.8 {d24}, [r3,:64], r2 + vqmovun.s16 d27, q3 + vst1.8 {d25}, [r3,:64], r2 + vst1.8 {d26}, [r3,:64], r2 + vst1.8 {d27}, [r3,:64], r2 + + bx lr +endfunc + +function ff_vp8_idct_dc_add4y_neon, export=1 + vmov.i16 d0, #0 + mov r3, #32 + vld1.16 {d16[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vld1.16 {d17[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vld1.16 {d18[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vld1.16 {d19[]}, [r1,:16] + vst1.16 {d0[0]}, [r1,:16], r3 + vrshr.s16 q8, q8, #3 @ dc >>= 3 + vld1.8 {q0}, [r0,:128], r2 + vrshr.s16 q9, q9, #3 + vld1.8 {q1}, [r0,:128], r2 + vaddw.u8 q10, q8, d0 + vld1.8 {q2}, [r0,:128], r2 + vaddw.u8 q0, q9, d1 + vld1.8 {q3}, [r0,:128], r2 + vaddw.u8 q11, q8, d2 + vaddw.u8 q1, q9, d3 + vaddw.u8 q12, q8, d4 + vaddw.u8 q2, q9, d5 + vaddw.u8 q13, q8, d6 + vaddw.u8 q3, q9, d7 + sub r0, r0, r2, lsl #2 + vqmovun.s16 d20, q10 + vqmovun.s16 d21, q0 + vqmovun.s16 d22, q11 + vqmovun.s16 d23, q1 + vqmovun.s16 d24, q12 + vst1.8 {q10}, [r0,:128], r2 + vqmovun.s16 d25, q2 + vst1.8 {q11}, [r0,:128], r2 + vqmovun.s16 d26, q13 + vst1.8 {q12}, [r0,:128], r2 + vqmovun.s16 d27, q3 + vst1.8 {q13}, [r0,:128], r2 + + bx lr +endfunc + +@ Register layout: +@ P3..Q3 -> q0..q7 +@ flim_E -> q14 +@ flim_I -> q15 +@ hev_thresh -> r12 +@ +.macro vp8_loop_filter, inner=0, simple=0 + .if \simple + vabd.u8 q9, q3, q4 @ abs(P0-Q0) + vabd.u8 q15, q2, q5 @ abs(P1-Q1) + vqadd.u8 q9, q9, q9 @ abs(P0-Q0) * 2 + vshr.u8 q10, q15, #1 @ abs(P1-Q1) / 2 + vqadd.u8 q11, q9, q10 @ (abs(P0-Q0)*2) + (abs(P1-Q1)/2) + vmov.i8 q13, #0x80 + vcle.u8 q8, q11, q14 @ (abs(P0-Q0)*2) + (abs(P1-Q1)/2) <= flim + .else + @ calculate hev and normal_limit: + vabd.u8 q12, q2, q3 @ abs(P1-P0) + vabd.u8 q13, q5, q4 @ abs(Q1-Q0) + vabd.u8 q10, q0, q1 @ abs(P3-P2) + vabd.u8 q11, q1, q2 @ abs(P2-P1) + vcle.u8 q8, q12, q15 @ abs(P1-P0) <= flim_I + vcle.u8 q9, q13, q15 @ abs(Q1-Q0) <= flim_I + vcle.u8 q10, q10, q15 @ abs(P3-P2) <= flim_I + vcle.u8 q11, q11, q15 @ abs(P2-P1) <= flim_I + vand q8, q8, q9 + vabd.u8 q9, q7, q6 @ abs(Q3-Q2) + vand q8, q8, q11 + vabd.u8 q11, q6, q5 @ abs(Q2-Q1) + vand q8, q8, q10 + vcle.u8 q10, q9, q15 @ abs(Q3-Q2) <= flim_I + vcle.u8 q11, q11, q15 @ abs(Q2-Q1) <= flim_I + vabd.u8 q9, q3, q4 @ abs(P0-Q0) + vabd.u8 q15, q2, q5 @ abs(P1-Q1) + vand q8, q8, q10 + vqadd.u8 q9, q9, q9 @ abs(P0-Q0) * 2 + vand q8, q8, q11 + vshr.u8 q10, q15, #1 @ abs(P1-Q1) / 2 + vdup.8 q15, r12 @ hev_thresh + vqadd.u8 q11, q9, q10 @ (abs(P0-Q0)*2) + (abs(P1-Q1)/2) + vcgt.u8 q12, q12, q15 @ abs(P1-P0) > hev_thresh + vcle.u8 q11, q11, q14 @ (abs(P0-Q0)*2) + (abs(P1-Q1)/2) <= flim_E + vcgt.u8 q14, q13, q15 @ abs(Q1-Q0) > hev_thresh + vand q8, q8, q11 + vmov.i8 q13, #0x80 + vorr q9, q12, q14 + .endif + + @ at this point: + @ q8: normal_limit + @ q9: hev + + @ convert to signed value: + veor q3, q3, q13 @ PS0 = P0 ^ 0x80 + veor q4, q4, q13 @ QS0 = Q0 ^ 0x80 + + vmov.i16 q12, #3 + vsubl.s8 q10, d8, d6 @ QS0 - PS0 + vsubl.s8 q11, d9, d7 @ (widened to 16bit) + veor q2, q2, q13 @ PS1 = P1 ^ 0x80 + veor q5, q5, q13 @ QS1 = Q1 ^ 0x80 + vmul.i16 q10, q10, q12 @ w = 3 * (QS0 - PS0) + vmul.i16 q11, q11, q12 + + vqsub.s8 q12, q2, q5 @ clamp(PS1-QS1) + vmov.i8 q14, #4 + vmov.i8 q15, #3 + .if \inner + vand q12, q12, q9 @ if(hev) w += clamp(PS1-QS1) + .endif + vaddw.s8 q10, q10, d24 @ w += clamp(PS1-QS1) + vaddw.s8 q11, q11, d25 + vqmovn.s16 d20, q10 @ narrow result back into q10 + vqmovn.s16 d21, q11 + .if !\inner && !\simple + veor q1, q1, q13 @ PS2 = P2 ^ 0x80 + veor q6, q6, q13 @ QS2 = Q2 ^ 0x80 + .endif + vand q10, q10, q8 @ w &= normal_limit + + @ registers used at this point.. + @ q0 -> P3 (don't corrupt) + @ q1-q6 -> PS2-QS2 + @ q7 -> Q3 (don't corrupt) + @ q9 -> hev + @ q10 -> w + @ q13 -> #0x80 + @ q14 -> #4 + @ q15 -> #3 + @ q8, q11, q12 -> unused + + @ filter_common: is4tap==1 + @ c1 = clamp(w + 4) >> 3; + @ c2 = clamp(w + 3) >> 3; + @ Q0 = s2u(QS0 - c1); + @ P0 = s2u(PS0 + c2); + + .if \simple + vqadd.s8 q11, q10, q14 @ c1 = clamp((w&hev)+4) + vqadd.s8 q12, q10, q15 @ c2 = clamp((w&hev)+3) + vshr.s8 q11, q11, #3 @ c1 >>= 3 + vshr.s8 q12, q12, #3 @ c2 >>= 3 + vqsub.s8 q4, q4, q11 @ QS0 = clamp(QS0-c1) + vqadd.s8 q3, q3, q12 @ PS0 = clamp(PS0+c2) + veor q4, q4, q13 @ Q0 = QS0 ^ 0x80 + veor q3, q3, q13 @ P0 = PS0 ^ 0x80 + veor q5, q5, q13 @ Q1 = QS1 ^ 0x80 + veor q2, q2, q13 @ P1 = PS1 ^ 0x80 + .elseif \inner + @ the !is4tap case of filter_common, only used for inner blocks + @ c3 = ((c1&~hev) + 1) >> 1; + @ Q1 = s2u(QS1 - c3); + @ P1 = s2u(PS1 + c3); + vqadd.s8 q11, q10, q14 @ c1 = clamp((w&hev)+4) + vqadd.s8 q12, q10, q15 @ c2 = clamp((w&hev)+3) + vshr.s8 q11, q11, #3 @ c1 >>= 3 + vshr.s8 q12, q12, #3 @ c2 >>= 3 + vqsub.s8 q4, q4, q11 @ QS0 = clamp(QS0-c1) + vqadd.s8 q3, q3, q12 @ PS0 = clamp(PS0+c2) + vbic q11, q11, q9 @ c1 & ~hev + veor q4, q4, q13 @ Q0 = QS0 ^ 0x80 + vrshr.s8 q11, q11, #1 @ c3 >>= 1 + veor q3, q3, q13 @ P0 = PS0 ^ 0x80 + vqsub.s8 q5, q5, q11 @ QS1 = clamp(QS1-c3) + vqadd.s8 q2, q2, q11 @ PS1 = clamp(PS1+c3) + veor q5, q5, q13 @ Q1 = QS1 ^ 0x80 + veor q2, q2, q13 @ P1 = PS1 ^ 0x80 + .else + vand q12, q10, q9 @ w & hev + vqadd.s8 q11, q12, q14 @ c1 = clamp((w&hev)+4) + vqadd.s8 q12, q12, q15 @ c2 = clamp((w&hev)+3) + vshr.s8 q11, q11, #3 @ c1 >>= 3 + vshr.s8 q12, q12, #3 @ c2 >>= 3 + vbic q10, q10, q9 @ w &= ~hev + vqsub.s8 q4, q4, q11 @ QS0 = clamp(QS0-c1) + vqadd.s8 q3, q3, q12 @ PS0 = clamp(PS0+c2) + + @ filter_mbedge: + @ a = clamp((27*w + 63) >> 7); + @ Q0 = s2u(QS0 - a); + @ P0 = s2u(PS0 + a); + @ a = clamp((18*w + 63) >> 7); + @ Q1 = s2u(QS1 - a); + @ P1 = s2u(PS1 + a); + @ a = clamp((9*w + 63) >> 7); + @ Q2 = s2u(QS2 - a); + @ P2 = s2u(PS2 + a); + vmov.i16 q9, #63 + vshll.s8 q14, d20, #3 + vshll.s8 q15, d21, #3 + vaddw.s8 q14, q14, d20 + vaddw.s8 q15, q15, d21 + vadd.s16 q8, q9, q14 + vadd.s16 q9, q9, q15 @ 9*w + 63 + vadd.s16 q11, q8, q14 + vadd.s16 q12, q9, q15 @ 18*w + 63 + vadd.s16 q14, q11, q14 + vadd.s16 q15, q12, q15 @ 27*w + 63 + vqshrn.s16 d16, q8, #7 + vqshrn.s16 d17, q9, #7 @ clamp(( 9*w + 63)>>7) + vqshrn.s16 d22, q11, #7 + vqshrn.s16 d23, q12, #7 @ clamp((18*w + 63)>>7) + vqshrn.s16 d28, q14, #7 + vqshrn.s16 d29, q15, #7 @ clamp((27*w + 63)>>7) + vqadd.s8 q1, q1, q8 @ PS2 = clamp(PS2+a) + vqsub.s8 q6, q6, q8 @ QS2 = clamp(QS2-a) + vqadd.s8 q2, q2, q11 @ PS1 = clamp(PS1+a) + vqsub.s8 q5, q5, q11 @ QS1 = clamp(QS1-a) + vqadd.s8 q3, q3, q14 @ PS0 = clamp(PS0+a) + vqsub.s8 q4, q4, q14 @ QS0 = clamp(QS0-a) + veor q3, q3, q13 @ P0 = PS0 ^ 0x80 + veor q4, q4, q13 @ Q0 = QS0 ^ 0x80 + veor q2, q2, q13 @ P1 = PS1 ^ 0x80 + veor q5, q5, q13 @ Q1 = QS1 ^ 0x80 + veor q1, q1, q13 @ P2 = PS2 ^ 0x80 + veor q6, q6, q13 @ Q2 = QS2 ^ 0x80 + .endif +.endm + +.macro vp8_v_loop_filter16 name, inner=0, simple=0 +function ff_vp8_v_loop_filter16\name\()_neon, export=1 + vpush {q4-q7} + sub r0, r0, r1, lsl #1+!\simple + + @ Load pixels: + .if !\simple + ldr r12, [sp, #64] @ hev_thresh + vld1.8 {q0}, [r0,:128], r1 @ P3 + vld1.8 {q1}, [r0,:128], r1 @ P2 + .endif + vld1.8 {q2}, [r0,:128], r1 @ P1 + vld1.8 {q3}, [r0,:128], r1 @ P0 + vld1.8 {q4}, [r0,:128], r1 @ Q0 + vld1.8 {q5}, [r0,:128], r1 @ Q1 + .if !\simple + vld1.8 {q6}, [r0,:128], r1 @ Q2 + vld1.8 {q7}, [r0,:128] @ Q3 + vdup.8 q15, r3 @ flim_I + .endif + vdup.8 q14, r2 @ flim_E + + vp8_loop_filter inner=\inner, simple=\simple + + @ back up to P2: dst -= stride * 6 + sub r0, r0, r1, lsl #2 + .if !\simple + sub r0, r0, r1, lsl #1 + + @ Store pixels: + vst1.8 {q1}, [r0,:128], r1 @ P2 + .endif + vst1.8 {q2}, [r0,:128], r1 @ P1 + vst1.8 {q3}, [r0,:128], r1 @ P0 + vst1.8 {q4}, [r0,:128], r1 @ Q0 + vst1.8 {q5}, [r0,:128], r1 @ Q1 + .if !\simple + vst1.8 {q6}, [r0,:128] @ Q2 + .endif + + vpop {q4-q7} + bx lr +endfunc +.endm + +vp8_v_loop_filter16 +vp8_v_loop_filter16 _inner, inner=1 +vp8_v_loop_filter16 _simple, simple=1 + +.macro vp8_v_loop_filter8uv name, inner=0 +function ff_vp8_v_loop_filter8uv\name\()_neon, export=1 + vpush {q4-q7} + sub r0, r0, r2, lsl #2 + sub r1, r1, r2, lsl #2 + ldr r12, [sp, #64] @ flim_I + + @ Load pixels: + vld1.8 {d0}, [r0,:64], r2 @ P3 + vld1.8 {d1}, [r1,:64], r2 @ P3 + vld1.8 {d2}, [r0,:64], r2 @ P2 + vld1.8 {d3}, [r1,:64], r2 @ P2 + vld1.8 {d4}, [r0,:64], r2 @ P1 + vld1.8 {d5}, [r1,:64], r2 @ P1 + vld1.8 {d6}, [r0,:64], r2 @ P0 + vld1.8 {d7}, [r1,:64], r2 @ P0 + vld1.8 {d8}, [r0,:64], r2 @ Q0 + vld1.8 {d9}, [r1,:64], r2 @ Q0 + vld1.8 {d10}, [r0,:64], r2 @ Q1 + vld1.8 {d11}, [r1,:64], r2 @ Q1 + vld1.8 {d12}, [r0,:64], r2 @ Q2 + vld1.8 {d13}, [r1,:64], r2 @ Q2 + vld1.8 {d14}, [r0,:64] @ Q3 + vld1.8 {d15}, [r1,:64] @ Q3 + + vdup.8 q14, r3 @ flim_E + vdup.8 q15, r12 @ flim_I + ldr r12, [sp, #68] @ hev_thresh + + vp8_loop_filter inner=\inner + + @ back up to P2: u,v -= stride * 6 + sub r0, r0, r2, lsl #2 + sub r1, r1, r2, lsl #2 + sub r0, r0, r2, lsl #1 + sub r1, r1, r2, lsl #1 + + @ Store pixels: + vst1.8 {d2}, [r0,:64], r2 @ P2 + vst1.8 {d3}, [r1,:64], r2 @ P2 + vst1.8 {d4}, [r0,:64], r2 @ P1 + vst1.8 {d5}, [r1,:64], r2 @ P1 + vst1.8 {d6}, [r0,:64], r2 @ P0 + vst1.8 {d7}, [r1,:64], r2 @ P0 + vst1.8 {d8}, [r0,:64], r2 @ Q0 + vst1.8 {d9}, [r1,:64], r2 @ Q0 + vst1.8 {d10}, [r0,:64], r2 @ Q1 + vst1.8 {d11}, [r1,:64], r2 @ Q1 + vst1.8 {d12}, [r0,:64] @ Q2 + vst1.8 {d13}, [r1,:64] @ Q2 + + vpop {q4-q7} + bx lr +endfunc +.endm + +vp8_v_loop_filter8uv +vp8_v_loop_filter8uv _inner, inner=1 + +.macro vp8_h_loop_filter16 name, inner=0, simple=0 +function ff_vp8_h_loop_filter16\name\()_neon, export=1 + vpush {q4-q7} + sub r0, r0, #4 + .if !\simple + ldr r12, [sp, #64] @ hev_thresh + .endif + + @ Load pixels: + vld1.8 {d0}, [r0], r1 @ load first 8-line src data + vld1.8 {d2}, [r0], r1 + vld1.8 {d4}, [r0], r1 + vld1.8 {d6}, [r0], r1 + vld1.8 {d8}, [r0], r1 + vld1.8 {d10}, [r0], r1 + vld1.8 {d12}, [r0], r1 + vld1.8 {d14}, [r0], r1 + vld1.8 {d1}, [r0], r1 @ load second 8-line src data + vld1.8 {d3}, [r0], r1 + vld1.8 {d5}, [r0], r1 + vld1.8 {d7}, [r0], r1 + vld1.8 {d9}, [r0], r1 + vld1.8 {d11}, [r0], r1 + vld1.8 {d13}, [r0], r1 + vld1.8 {d15}, [r0], r1 + + transpose_8x8 q0, q1, q2, q3, q4, q5, q6, q7 + + vdup.8 q14, r2 @ flim_E + .if !\simple + vdup.8 q15, r3 @ flim_I + .endif + + vp8_loop_filter inner=\inner, simple=\simple + + sub r0, r0, r1, lsl #4 @ backup 16 rows + + transpose_8x8 q0, q1, q2, q3, q4, q5, q6, q7 + + @ Store pixels: + vst1.8 {d0}, [r0], r1 + vst1.8 {d2}, [r0], r1 + vst1.8 {d4}, [r0], r1 + vst1.8 {d6}, [r0], r1 + vst1.8 {d8}, [r0], r1 + vst1.8 {d10}, [r0], r1 + vst1.8 {d12}, [r0], r1 + vst1.8 {d14}, [r0], r1 + vst1.8 {d1}, [r0], r1 + vst1.8 {d3}, [r0], r1 + vst1.8 {d5}, [r0], r1 + vst1.8 {d7}, [r0], r1 + vst1.8 {d9}, [r0], r1 + vst1.8 {d11}, [r0], r1 + vst1.8 {d13}, [r0], r1 + vst1.8 {d15}, [r0] + + vpop {q4-q7} + bx lr +endfunc +.endm + +vp8_h_loop_filter16 +vp8_h_loop_filter16 _inner, inner=1 +vp8_h_loop_filter16 _simple, simple=1 + +.macro vp8_h_loop_filter8uv name, inner=0 +function ff_vp8_h_loop_filter8uv\name\()_neon, export=1 + vpush {q4-q7} + sub r0, r0, #4 + sub r1, r1, #4 + ldr r12, [sp, #64] @ flim_I + + @ Load pixels: + vld1.8 {d0}, [r0], r2 @ load u + vld1.8 {d1}, [r1], r2 @ load v + vld1.8 {d2}, [r0], r2 + vld1.8 {d3}, [r1], r2 + vld1.8 {d4}, [r0], r2 + vld1.8 {d5}, [r1], r2 + vld1.8 {d6}, [r0], r2 + vld1.8 {d7}, [r1], r2 + vld1.8 {d8}, [r0], r2 + vld1.8 {d9}, [r1], r2 + vld1.8 {d10}, [r0], r2 + vld1.8 {d11}, [r1], r2 + vld1.8 {d12}, [r0], r2 + vld1.8 {d13}, [r1], r2 + vld1.8 {d14}, [r0], r2 + vld1.8 {d15}, [r1], r2 + + transpose_8x8 q0, q1, q2, q3, q4, q5, q6, q7 + + vdup.8 q14, r3 @ flim_E + vdup.8 q15, r12 @ flim_I + ldr r12, [sp, #68] @ hev_thresh + + vp8_loop_filter inner=\inner + + sub r0, r0, r2, lsl #3 @ backup u 8 rows + sub r1, r1, r2, lsl #3 @ backup v 8 rows + + transpose_8x8 q0, q1, q2, q3, q4, q5, q6, q7 + + @ Store pixels: + vst1.8 {d0}, [r0], r2 + vst1.8 {d1}, [r1], r2 + vst1.8 {d2}, [r0], r2 + vst1.8 {d3}, [r1], r2 + vst1.8 {d4}, [r0], r2 + vst1.8 {d5}, [r1], r2 + vst1.8 {d6}, [r0], r2 + vst1.8 {d7}, [r1], r2 + vst1.8 {d8}, [r0], r2 + vst1.8 {d9}, [r1], r2 + vst1.8 {d10}, [r0], r2 + vst1.8 {d11}, [r1], r2 + vst1.8 {d12}, [r0], r2 + vst1.8 {d13}, [r1], r2 + vst1.8 {d14}, [r0] + vst1.8 {d15}, [r1] + + vpop {q4-q7} + bx lr +endfunc +.endm + +vp8_h_loop_filter8uv +vp8_h_loop_filter8uv _inner, inner=1 + +function ff_put_vp8_pixels16_neon, export=1 + ldr r12, [sp, #0] @ h +1: + subs r12, r12, #4 + vld1.8 {q0}, [r2], r3 + vld1.8 {q1}, [r2], r3 + vld1.8 {q2}, [r2], r3 + vld1.8 {q3}, [r2], r3 + vst1.8 {q0}, [r0,:128], r1 + vst1.8 {q1}, [r0,:128], r1 + vst1.8 {q2}, [r0,:128], r1 + vst1.8 {q3}, [r0,:128], r1 + bgt 1b + bx lr +endfunc + +function ff_put_vp8_pixels8_neon, export=1 + ldr r12, [sp, #0] @ h +1: + subs r12, r12, #4 + vld1.8 {d0}, [r2], r3 + vld1.8 {d1}, [r2], r3 + vld1.8 {d2}, [r2], r3 + vld1.8 {d3}, [r2], r3 + vst1.8 {d0}, [r0,:64], r1 + vst1.8 {d1}, [r0,:64], r1 + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + bgt 1b + bx lr +endfunc + +/* 4/6-tap 8th-pel MC */ + +.macro vp8_epel8_h6 d, a, b + vext.8 d27, \a, \b, #1 + vmovl.u8 q8, \a + vext.8 d28, \a, \b, #2 + vmovl.u8 q9, d27 + vext.8 d29, \a, \b, #3 + vmovl.u8 q10, d28 + vext.8 d30, \a, \b, #4 + vmovl.u8 q11, d29 + vext.8 d31, \a, \b, #5 + vmovl.u8 q12, d30 + vmul.u16 q10, q10, d0[2] + vmovl.u8 q13, d31 + vmul.u16 q11, q11, d0[3] + vmls.u16 q10, q9, d0[1] + vmls.u16 q11, q12, d1[0] + vmla.u16 q10, q8, d0[0] + vmla.u16 q11, q13, d1[1] + vqadd.s16 q11, q10, q11 + vqrshrun.s16 \d, q11, #7 +.endm + +.macro vp8_epel16_h6 d0, d1, s0, s1, s2, q0, q1 + vext.8 q14, \q0, \q1, #3 + vext.8 q15, \q0, \q1, #4 + vmovl.u8 q11, d28 + vmovl.u8 q14, d29 + vext.8 q3, \q0, \q1, #2 + vmovl.u8 q12, d30 + vmovl.u8 q15, d31 + vext.8 q8, \q0, \q1, #1 + vmovl.u8 q10, d6 + vmovl.u8 q3, d7 + vext.8 q2, \q0, \q1, #5 + vmovl.u8 q13, d4 + vmovl.u8 q2, d5 + vmovl.u8 q9, d16 + vmovl.u8 q8, d17 + vmul.u16 q11, q11, d0[3] + vmul.u16 q10, q10, d0[2] + vmul.u16 q3, q3, d0[2] + vmul.u16 q14, q14, d0[3] + vmls.u16 q11, q12, d1[0] + vmovl.u8 q12, \s0 + vmovl.u8 q1, \s1 + vmls.u16 q10, q9, d0[1] + vmls.u16 q3, q8, d0[1] + vmls.u16 q14, q15, d1[0] + vmla.u16 q10, q12, d0[0] + vmla.u16 q11, q13, d1[1] + vmla.u16 q3, q1, d0[0] + vmla.u16 q14, q2, d1[1] + vqadd.s16 q11, q10, q11 + vqadd.s16 q14, q3, q14 + vqrshrun.s16 \d0, q11, #7 + vqrshrun.s16 \d1, q14, #7 +.endm + +.macro vp8_epel8_v6 d0, s0, s1, s2, s3, s4, s5 + vmovl.u8 q10, \s2 + vmovl.u8 q11, \s3 + vmovl.u8 q9, \s1 + vmovl.u8 q12, \s4 + vmovl.u8 q8, \s0 + vmovl.u8 q13, \s5 + vmul.u16 q10, q10, d0[2] + vmul.u16 q11, q11, d0[3] + vmls.u16 q10, q9, d0[1] + vmls.u16 q11, q12, d1[0] + vmla.u16 q10, q8, d0[0] + vmla.u16 q11, q13, d1[1] + vqadd.s16 q11, q10, q11 + vqrshrun.s16 \d0, q11, #7 +.endm + +.macro vp8_epel8_v6_y2 d0, d1, s0, s1, s2, s3, s4, s5, s6 + vmovl.u8 q10, \s0 + vmovl.u8 q11, \s3 + vmovl.u8 q14, \s6 + vmovl.u8 q9, \s1 + vmovl.u8 q12, \s4 + vmovl.u8 q8, \s2 + vmovl.u8 q13, \s5 + vmul.u16 q10, q10, d0[0] + vmul.u16 q15, q11, d0[3] + vmul.u16 q11, q11, d0[2] + vmul.u16 q14, q14, d1[1] + vmls.u16 q10, q9, d0[1] + vmls.u16 q15, q12, d1[0] + vmls.u16 q11, q8, d0[1] + vmls.u16 q14, q13, d1[0] + vmla.u16 q10, q8, d0[2] + vmla.u16 q15, q13, d1[1] + vmla.u16 q11, q9, d0[0] + vmla.u16 q14, q12, d0[3] + vqadd.s16 q15, q10, q15 + vqadd.s16 q14, q11, q14 + vqrshrun.s16 \d0, q15, #7 + vqrshrun.s16 \d1, q14, #7 +.endm + +.macro vp8_epel8_h4 d, a, b + vext.8 d28, \a, \b, #1 + vmovl.u8 q9, \a + vext.8 d29, \a, \b, #2 + vmovl.u8 q10, d28 + vext.8 d30, \a, \b, #3 + vmovl.u8 q11, d29 + vmovl.u8 q12, d30 + vmul.u16 q10, q10, d0[2] + vmul.u16 q11, q11, d0[3] + vmls.u16 q10, q9, d0[1] + vmls.u16 q11, q12, d1[0] + vqadd.s16 q11, q10, q11 + vqrshrun.s16 \d, q11, #7 +.endm + +.macro vp8_epel8_v4_y2 d0, d1, s0, s1, s2, s3, s4 + vmovl.u8 q9, \s0 + vmovl.u8 q10, \s1 + vmovl.u8 q11, \s2 + vmovl.u8 q12, \s3 + vmovl.u8 q13, \s4 + vmul.u16 q8, q10, d0[2] + vmul.u16 q14, q11, d0[3] + vmul.u16 q11, q11, d0[2] + vmul.u16 q15, q12, d0[3] + vmls.u16 q8, q9, d0[1] + vmls.u16 q14, q12, d1[0] + vmls.u16 q11, q10, d0[1] + vmls.u16 q15, q13, d1[0] + vqadd.s16 q8, q8, q14 + vqadd.s16 q11, q11, q15 + vqrshrun.s16 \d0, q8, #7 + vqrshrun.s16 \d1, q11, #7 +.endm + +function ff_put_vp8_epel16_v6_neon, export=1 + sub r2, r2, r3, lsl #1 + push {r4,lr} + vpush {d8-d15} + + ldr r4, [sp, #80] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #72] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2-d3}, [r2], r3 + vld1.8 {d4-d5}, [r2], r3 + vld1.8 {d6-d7}, [r2], r3 + vld1.8 {d8-d9}, [r2], r3 + vld1.8 {d10-d11},[r2], r3 + vld1.8 {d12-d13},[r2], r3 + vld1.8 {d14-d15},[r2] + sub r2, r2, r3, lsl #2 + + vp8_epel8_v6_y2 d2, d4, d2, d4, d6, d8, d10, d12, d14 + vp8_epel8_v6_y2 d3, d5, d3, d5, d7, d9, d11, d13, d15 + + vst1.8 {d2-d3}, [r0,:128], r1 + vst1.8 {d4-d5}, [r0,:128], r1 + subs r12, r12, #2 + bne 1b + + vpop {d8-d15} + pop {r4,pc} +endfunc + +function ff_put_vp8_epel16_h6_neon, export=1 + sub r2, r2, #2 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2-d4}, [r2], r3 + + vp8_epel16_h6 d2, d3, d2, d3, d4, q1, q2 + + vst1.8 {d2-d3}, [r0,:128], r1 + subs r12, r12, #1 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel16_h6v6_neon, export=1 + sub r2, r2, r3, lsl #1 + sub r2, r2, #2 + push {r4,lr} + vpush {d8-d9} + + @ first pass (horizontal): + ldr r4, [sp, #28] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #24] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #336+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #5 + bic lr, lr, #15 +1: + vld1.8 {d2,d3,d4}, [r2], r3 + + vp8_epel16_h6 d2, d3, d2, d3, d4, q1, q2 + + vst1.8 {d2-d3}, [lr,:128]! + subs r12, r12, #1 + bne 1b + + @ second pass (vertical): + ldr r4, [sp, #336+16+32] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #336+16+24] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d5}, [lr,:128]! + vld1.8 {d6-d9}, [lr,:128]! + vld1.8 {d28-d31},[lr,:128] + sub lr, lr, #48 + + vp8_epel8_v6 d2, d2, d4, d6, d8, d28, d30 + vp8_epel8_v6 d3, d3, d5, d7, d9, d29, d31 + + vst1.8 {d2-d3}, [r0,:128], r1 + subs r12, r12, #1 + bne 2b + + add sp, sp, #336+16 + vpop {d8-d9} + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_v6_neon, export=1 + sub r2, r2, r3, lsl #1 + push {r4,lr} + + ldr r4, [sp, #16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2}, [r2], r3 + vld1.8 {d3}, [r2], r3 + vld1.8 {d4}, [r2], r3 + vld1.8 {d5}, [r2], r3 + vld1.8 {d6}, [r2], r3 + vld1.8 {d7}, [r2], r3 + vld1.8 {d28}, [r2] + + sub r2, r2, r3, lsl #2 + + vp8_epel8_v6_y2 d2, d3, d2, d3, d4, d5, d6, d7, d28 + + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + subs r12, r12, #2 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_h6_neon, export=1 + sub r2, r2, #2 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2,d3}, [r2], r3 + + vp8_epel8_h6 d2, d2, d3 + + vst1.8 {d2}, [r0,:64], r1 + subs r12, r12, #1 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_h6v6_neon, export=1 + sub r2, r2, r3, lsl #1 + sub r2, r2, #2 + push {r4,lr} + + @ first pass (horizontal): + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #168+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #5 + bic lr, lr, #15 +1: + vld1.8 {d2,d3}, [r2], r3 + + vp8_epel8_h6 d2, d2, d3 + + vst1.8 {d2}, [lr,:64]! + subs r12, r12, #1 + bne 1b + + @ second pass (vertical): + ldr r4, [sp, #168+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #168+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d5}, [lr,:128]! + vld1.8 {d6-d7}, [lr,:128]! + vld1.8 {d30}, [lr,:64] + sub lr, lr, #32 + + vp8_epel8_v6_y2 d2, d3, d2, d3, d4, d5, d6, d7, d30 + + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + subs r12, r12, #2 + bne 2b + + add sp, sp, #168+16 + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_v4_neon, export=1 + sub r2, r2, r3 + push {r4,lr} + + ldr r4, [sp, #16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2}, [r2], r3 + vld1.8 {d3}, [r2], r3 + vld1.8 {d4}, [r2], r3 + vld1.8 {d5}, [r2], r3 + vld1.8 {d6}, [r2] + sub r2, r2, r3, lsl #1 + + vp8_epel8_v4_y2 d2, d3, d2, d3, d4, d5, d6 + + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + subs r12, r12, #2 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_h4_neon, export=1 + sub r2, r2, #1 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2,d3}, [r2], r3 + + vp8_epel8_h4 d2, d2, d3 + + vst1.8 {d2}, [r0,:64], r1 + subs r12, r12, #1 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_h4v4_neon, export=1 + sub r2, r2, r3 + sub r2, r2, #1 + push {r4,lr} + + @ first pass (horizontal): + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #168+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #3 + bic lr, lr, #15 +1: + vld1.8 {d2,d3}, [r2], r3 + + vp8_epel8_h4 d2, d2, d3 + + vst1.8 {d2}, [lr,:64]! + subs r12, r12, #1 + bne 1b + + @ second pass (vertical): + ldr r4, [sp, #168+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #168+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d5}, [lr,:128]! + vld1.8 {d6}, [lr,:64] + sub lr, lr, #16 + + vp8_epel8_v4_y2 d2, d3, d2, d3, d4, d5, d6 + + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + subs r12, r12, #2 + bne 2b + + add sp, sp, #168+16 + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_h6v4_neon, export=1 + sub r2, r2, r3 + sub r2, r2, #2 + push {r4,lr} + + @ first pass (horizontal): + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #168+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #3 + bic lr, lr, #15 +1: + vld1.8 {d2,d3}, [r2], r3 + + vp8_epel8_h6 d2, d2, d3 + + vst1.8 {d2}, [lr,:64]! + subs r12, r12, #1 + bne 1b + + @ second pass (vertical): + ldr r4, [sp, #168+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #168+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d5}, [lr,:128]! + vld1.8 {d6}, [lr,:64] + sub lr, lr, #16 + + vp8_epel8_v4_y2 d2, d3, d2, d3, d4, d5, d6 + + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + subs r12, r12, #2 + bne 2b + + add sp, sp, #168+16 + pop {r4,pc} +endfunc + +function ff_put_vp8_epel8_h4v6_neon, export=1 + sub r2, r2, r3, lsl #1 + sub r2, r2, #1 + push {r4,lr} + + @ first pass (horizontal): + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #168+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #5 + bic lr, lr, #15 +1: + vld1.8 {d2,d3}, [r2], r3 + + vp8_epel8_h4 d2, d2, d3 + + vst1.8 {d2}, [lr,:64]! + subs r12, r12, #1 + bne 1b + + @ second pass (vertical): + ldr r4, [sp, #168+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #168+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d5}, [lr,:128]! + vld1.8 {d6-d7}, [lr,:128]! + vld1.8 {d30}, [lr,:64] + sub lr, lr, #32 + + vp8_epel8_v6_y2 d2, d3, d2, d3, d4, d5, d6, d7, d30 + + vst1.8 {d2}, [r0,:64], r1 + vst1.8 {d3}, [r0,:64], r1 + subs r12, r12, #2 + bne 2b + + add sp, sp, #168+16 + pop {r4,pc} +endfunc + +.ltorg + +function ff_put_vp8_epel4_v6_neon, export=1 + sub r2, r2, r3, lsl #1 + push {r4,lr} + + ldr r4, [sp, #16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.32 {d2[]}, [r2], r3 + vld1.32 {d3[]}, [r2], r3 + vld1.32 {d4[]}, [r2], r3 + vld1.32 {d5[]}, [r2], r3 + vld1.32 {d6[]}, [r2], r3 + vld1.32 {d7[]}, [r2], r3 + vld1.32 {d28[]}, [r2] + sub r2, r2, r3, lsl #2 + vld1.32 {d2[1]}, [r2], r3 + vld1.32 {d3[1]}, [r2], r3 + vld1.32 {d4[1]}, [r2], r3 + vld1.32 {d5[1]}, [r2], r3 + vld1.32 {d6[1]}, [r2], r3 + vld1.32 {d7[1]}, [r2], r3 + vld1.32 {d28[1]}, [r2] + sub r2, r2, r3, lsl #2 + + vp8_epel8_v6_y2 d2, d3, d2, d3, d4, d5, d6, d7, d28 + + vst1.32 {d2[0]}, [r0,:32], r1 + vst1.32 {d3[0]}, [r0,:32], r1 + vst1.32 {d2[1]}, [r0,:32], r1 + vst1.32 {d3[1]}, [r0,:32], r1 + subs r12, r12, #4 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_h6_neon, export=1 + sub r2, r2, #2 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {q1}, [r2], r3 + vp8_epel8_h6 d2, d2, d3 + vst1.32 {d2[0]}, [r0,:32], r1 + subs r12, r12, #1 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_h6v6_neon, export=1 + sub r2, r2, r3, lsl #1 + sub r2, r2, #2 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #52+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #5 + bic lr, lr, #15 +1: + vld1.8 {q1}, [r2], r3 + vp8_epel8_h6 d2, d2, d3 + vst1.32 {d2[0]}, [lr,:32]! + subs r12, r12, #1 + bne 1b + + ldr r4, [sp, #52+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #52+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d3}, [lr,:128]! + vld1.8 {d6}, [lr,:64]! + vld1.32 {d28[]}, [lr,:32] + sub lr, lr, #16 + vld1.8 {d4-d5}, [lr]! + vld1.8 {d7}, [lr,:64]! + vld1.32 {d28[1]}, [lr,:32] + sub lr, lr, #16 + vtrn.32 q1, q2 + vtrn.32 d6, d7 + vp8_epel8_v6_y2 d2, d3, d2, d4, d3, d5, d6, d7, d28 + vst1.32 {d2[0]}, [r0,:32], r1 + vst1.32 {d3[0]}, [r0,:32], r1 + vst1.32 {d2[1]}, [r0,:32], r1 + vst1.32 {d3[1]}, [r0,:32], r1 + subs r12, r12, #4 + bne 2b + + add sp, sp, #52+16 + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_h4v6_neon, export=1 + sub r2, r2, r3, lsl #1 + sub r2, r2, #1 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #52+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #5 + bic lr, lr, #15 +1: + vld1.8 {d2}, [r2], r3 + vp8_epel8_h4 d2, d2, d2 + vst1.32 {d2[0]}, [lr,:32]! + subs r12, r12, #1 + bne 1b + + ldr r4, [sp, #52+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #52+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d3}, [lr,:128]! + vld1.8 {d6}, [lr,:64]! + vld1.32 {d28[]}, [lr,:32] + sub lr, lr, #16 + vld1.8 {d4-d5}, [lr]! + vld1.8 {d7}, [lr,:64]! + vld1.32 {d28[1]}, [lr,:32] + sub lr, lr, #16 + vtrn.32 q1, q2 + vtrn.32 d6, d7 + vp8_epel8_v6_y2 d2, d3, d2, d4, d3, d5, d6, d7, d28 + vst1.32 {d2[0]}, [r0,:32], r1 + vst1.32 {d3[0]}, [r0,:32], r1 + vst1.32 {d2[1]}, [r0,:32], r1 + vst1.32 {d3[1]}, [r0,:32], r1 + subs r12, r12, #4 + bne 2b + + add sp, sp, #52+16 + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_h6v4_neon, export=1 + sub r2, r2, r3 + sub r2, r2, #2 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #44+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #3 + bic lr, lr, #15 +1: + vld1.8 {q1}, [r2], r3 + vp8_epel8_h6 d2, d2, d3 + vst1.32 {d2[0]}, [lr,:32]! + subs r12, r12, #1 + bne 1b + + ldr r4, [sp, #44+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #44+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d3}, [lr,:128]! + vld1.32 {d6[]}, [lr,:32] + sub lr, lr, #8 + vld1.8 {d4-d5}, [lr]! + vld1.32 {d6[1]}, [lr,:32] + sub lr, lr, #8 + vtrn.32 q1, q2 + vp8_epel8_v4_y2 d2, d3, d2, d4, d3, d5, d6 + vst1.32 {d2[0]}, [r0,:32], r1 + vst1.32 {d3[0]}, [r0,:32], r1 + vst1.32 {d2[1]}, [r0,:32], r1 + vst1.32 {d3[1]}, [r0,:32], r1 + subs r12, r12, #4 + bne 2b + + add sp, sp, #44+16 + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_h4_neon, export=1 + sub r2, r2, #1 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.8 {d2}, [r2], r3 + vp8_epel8_h4 d2, d2, d2 + vst1.32 {d2[0]}, [r0,:32], r1 + subs r12, r12, #1 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_v4_neon, export=1 + sub r2, r2, r3 + push {r4,lr} + + ldr r4, [sp, #16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + vld1.16 {q0}, [r4,:128] +1: + vld1.32 {d2[]}, [r2], r3 + vld1.32 {d3[]}, [r2], r3 + vld1.32 {d4[]}, [r2], r3 + vld1.32 {d5[]}, [r2], r3 + vld1.32 {d6[]}, [r2] + sub r2, r2, r3, lsl #1 + vld1.32 {d2[1]}, [r2], r3 + vld1.32 {d3[1]}, [r2], r3 + vld1.32 {d4[1]}, [r2], r3 + vld1.32 {d5[1]}, [r2], r3 + vld1.32 {d6[1]}, [r2] + sub r2, r2, r3, lsl #1 + + vp8_epel8_v4_y2 d2, d3, d2, d3, d4, d5, d6 + + vst1.32 {d2[0]}, [r0,:32], r1 + vst1.32 {d3[0]}, [r0,:32], r1 + vst1.32 {d2[1]}, [r0,:32], r1 + vst1.32 {d3[1]}, [r0,:32], r1 + subs r12, r12, #4 + bne 1b + + pop {r4,pc} +endfunc + +function ff_put_vp8_epel4_h4v4_neon, export=1 + sub r2, r2, r3 + sub r2, r2, #1 + push {r4,lr} + + ldr r4, [sp, #12] @ mx + movrel lr, subpel_filters-16 + ldr r12, [sp, #8] @ h + add r4, lr, r4, lsl #4 + sub sp, sp, #44+16 + vld1.16 {q0}, [r4,:128] + add lr, sp, #15 + add r12, r12, #3 + bic lr, lr, #15 +1: + vld1.8 {d2}, [r2], r3 + vp8_epel8_h4 d2, d2, d3 + vst1.32 {d2[0]}, [lr,:32]! + subs r12, r12, #1 + bne 1b + + ldr r4, [sp, #44+16+16] @ my + movrel lr, subpel_filters-16 + ldr r12, [sp, #44+16+8] @ h + add r4, lr, r4, lsl #4 + add lr, sp, #15 + vld1.16 {q0}, [r4,:128] + bic lr, lr, #15 +2: + vld1.8 {d2-d3}, [lr,:128]! + vld1.32 {d6[]}, [lr,:32] + sub lr, lr, #8 + vld1.8 {d4-d5}, [lr]! + vld1.32 {d6[1]}, [lr,:32] + sub lr, lr, #8 + vtrn.32 q1, q2 + vp8_epel8_v4_y2 d2, d3, d2, d4, d3, d5, d6 + vst1.32 {d2[0]}, [r0,:32], r1 + vst1.32 {d3[0]}, [r0,:32], r1 + vst1.32 {d2[1]}, [r0,:32], r1 + vst1.32 {d3[1]}, [r0,:32], r1 + subs r12, r12, #4 + bne 2b + + add sp, sp, #44+16 + pop {r4,pc} +endfunc + +@ note: worst case sum of all 6-tap filter values * 255 is 0x7f80 so 16 bit +@ arithmatic can be used to apply filters +const subpel_filters, align=4 + .short 0, 6, 123, 12, 1, 0, 0, 0 + .short 2, 11, 108, 36, 8, 1, 0, 0 + .short 0, 9, 93, 50, 6, 0, 0, 0 + .short 3, 16, 77, 77, 16, 3, 0, 0 + .short 0, 6, 50, 93, 9, 0, 0, 0 + .short 1, 8, 36, 108, 11, 2, 0, 0 + .short 0, 1, 12, 123, 6, 0, 0, 0 +endconst + +/* Bilinear MC */ + +function ff_put_vp8_bilin16_h_neon, export=1 + ldr r3, [sp, #4] @ mx + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r12, [sp] @ h +1: + subs r12, r12, #2 + vld1.8 {d2-d4}, [r2], r1 + vext.8 q2, q1, q2, #1 + vmull.u8 q8, d2, d1 + vmlal.u8 q8, d4, d0 + vld1.8 {d18-d20},[r2], r1 + vmull.u8 q3, d3, d1 + vmlal.u8 q3, d5, d0 + vext.8 q10, q9, q10, #1 + vmull.u8 q11, d18, d1 + vmlal.u8 q11, d20, d0 + vmull.u8 q12, d19, d1 + vmlal.u8 q12, d21, d0 + vrshrn.u16 d4, q8, #3 + vrshrn.u16 d5, q3, #3 + vrshrn.u16 d6, q11, #3 + vrshrn.u16 d7, q12, #3 + vst1.8 {q2}, [r0,:128], r1 + vst1.8 {q3}, [r0,:128], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin16_v_neon, export=1 + ldr r3, [sp, #8] @ my + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r12, [sp] @ h + vld1.8 {q1}, [r2], r1 +1: + subs r12, r12, #2 + vld1.8 {q2}, [r2], r1 + vmull.u8 q3, d2, d1 + vmlal.u8 q3, d4, d0 + vmull.u8 q8, d3, d1 + vmlal.u8 q8, d5, d0 + vld1.8 {q1}, [r2], r1 + vmull.u8 q9, d4, d1 + vmlal.u8 q9, d2, d0 + vmull.u8 q10, d5, d1 + vmlal.u8 q10, d3, d0 + vrshrn.u16 d4, q3, #3 + vrshrn.u16 d5, q8, #3 + vrshrn.u16 d6, q9, #3 + vrshrn.u16 d7, q10, #3 + vst1.8 {q2}, [r0,:128], r1 + vst1.8 {q3}, [r0,:128], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin16_hv_neon, export=1 + ldr r3, [sp, #4] @ mx + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r3, [sp, #8] @ my + rsb r12, r3, #8 + vdup.8 d2, r3 + vdup.8 d3, r12 + ldr r12, [sp] @ h + + vld1.8 {d4-d6}, [r2], r1 + vext.8 q3, q2, q3, #1 + vmull.u8 q8, d4, d1 + vmlal.u8 q8, d6, d0 + vmull.u8 q9, d5, d1 + vmlal.u8 q9, d7, d0 + vrshrn.u16 d4, q8, #3 + vrshrn.u16 d5, q9, #3 +1: + subs r12, r12, #2 + vld1.8 {d18-d20},[r2], r1 + vext.8 q10, q9, q10, #1 + vmull.u8 q11, d18, d1 + vmlal.u8 q11, d20, d0 + vld1.8 {d26-d28},[r2], r1 + vmull.u8 q12, d19, d1 + vmlal.u8 q12, d21, d0 + vext.8 q14, q13, q14, #1 + vmull.u8 q8, d26, d1 + vmlal.u8 q8, d28, d0 + vmull.u8 q9, d27, d1 + vmlal.u8 q9, d29, d0 + vrshrn.u16 d6, q11, #3 + vrshrn.u16 d7, q12, #3 + vmull.u8 q12, d4, d3 + vmlal.u8 q12, d6, d2 + vmull.u8 q15, d5, d3 + vmlal.u8 q15, d7, d2 + vrshrn.u16 d4, q8, #3 + vrshrn.u16 d5, q9, #3 + vmull.u8 q10, d6, d3 + vmlal.u8 q10, d4, d2 + vmull.u8 q11, d7, d3 + vmlal.u8 q11, d5, d2 + vrshrn.u16 d24, q12, #3 + vrshrn.u16 d25, q15, #3 + vst1.8 {q12}, [r0,:128], r1 + vrshrn.u16 d20, q10, #3 + vrshrn.u16 d21, q11, #3 + vst1.8 {q10}, [r0,:128], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin8_h_neon, export=1 + ldr r3, [sp, #4] @ mx + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r12, [sp] @ h +1: + subs r12, r12, #2 + vld1.8 {q1}, [r2], r1 + vext.8 d3, d2, d3, #1 + vmull.u8 q2, d2, d1 + vmlal.u8 q2, d3, d0 + vld1.8 {q3}, [r2], r1 + vext.8 d7, d6, d7, #1 + vmull.u8 q8, d6, d1 + vmlal.u8 q8, d7, d0 + vrshrn.u16 d4, q2, #3 + vrshrn.u16 d16, q8, #3 + vst1.8 {d4}, [r0,:64], r1 + vst1.8 {d16}, [r0,:64], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin8_v_neon, export=1 + ldr r3, [sp, #8] @ my + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r12, [sp] @ h + vld1.8 {d2}, [r2], r1 +1: + subs r12, r12, #2 + vld1.8 {d3}, [r2], r1 + vmull.u8 q2, d2, d1 + vmlal.u8 q2, d3, d0 + vld1.8 {d2}, [r2], r1 + vmull.u8 q3, d3, d1 + vmlal.u8 q3, d2, d0 + vrshrn.u16 d4, q2, #3 + vrshrn.u16 d6, q3, #3 + vst1.8 {d4}, [r0,:64], r1 + vst1.8 {d6}, [r0,:64], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin8_hv_neon, export=1 + ldr r3, [sp, #4] @ mx + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r3, [sp, #8] @ my + rsb r12, r3, #8 + vdup.8 d2, r3 + vdup.8 d3, r12 + ldr r12, [sp] @ h + + vld1.8 {q2}, [r2], r1 + vext.8 d5, d4, d5, #1 + vmull.u8 q9, d4, d1 + vmlal.u8 q9, d5, d0 + vrshrn.u16 d22, q9, #3 +1: + subs r12, r12, #2 + vld1.8 {q3}, [r2], r1 + vext.8 d7, d6, d7, #1 + vmull.u8 q8, d6, d1 + vmlal.u8 q8, d7, d0 + vld1.8 {q2}, [r2], r1 + vext.8 d5, d4, d5, #1 + vmull.u8 q9, d4, d1 + vmlal.u8 q9, d5, d0 + vrshrn.u16 d16, q8, #3 + vmull.u8 q10, d22, d3 + vmlal.u8 q10, d16, d2 + vrshrn.u16 d22, q9, #3 + vmull.u8 q12, d16, d3 + vmlal.u8 q12, d22, d2 + vrshrn.u16 d20, q10, #3 + vst1.8 {d20}, [r0,:64], r1 + vrshrn.u16 d23, q12, #3 + vst1.8 {d23}, [r0,:64], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin4_h_neon, export=1 + ldr r3, [sp, #4] @ mx + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r12, [sp] @ h +1: + subs r12, r12, #2 + vld1.8 {d2}, [r2], r1 + vext.8 d3, d2, d3, #1 + vld1.8 {d6}, [r2], r1 + vext.8 d7, d6, d7, #1 + vtrn.32 q1, q3 + vmull.u8 q2, d2, d1 + vmlal.u8 q2, d3, d0 + vrshrn.u16 d4, q2, #3 + vst1.32 {d4[0]}, [r0,:32], r1 + vst1.32 {d4[1]}, [r0,:32], r1 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin4_v_neon, export=1 + ldr r3, [sp, #8] @ my + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r12, [sp] @ h + vld1.32 {d2[]}, [r2], r1 +1: + vld1.32 {d3[]}, [r2] + vld1.32 {d2[1]}, [r2], r1 + vld1.32 {d3[1]}, [r2], r1 + vmull.u8 q2, d2, d1 + vmlal.u8 q2, d3, d0 + vtrn.32 d3, d2 + vrshrn.u16 d4, q2, #3 + vst1.32 {d4[0]}, [r0,:32], r1 + vst1.32 {d4[1]}, [r0,:32], r1 + subs r12, r12, #2 + bgt 1b + + bx lr +endfunc + +function ff_put_vp8_bilin4_hv_neon, export=1 + ldr r3, [sp, #4] @ mx + rsb r12, r3, #8 + vdup.8 d0, r3 + vdup.8 d1, r12 + ldr r3, [sp, #8] @ my + rsb r12, r3, #8 + vdup.8 d2, r3 + vdup.8 d3, r12 + ldr r12, [sp] @ h + + vld1.8 {d4}, [r2], r1 + vext.8 d5, d4, d4, #1 + vmull.u8 q9, d4, d1 + vmlal.u8 q9, d5, d0 + vrshrn.u16 d22, q9, #3 +1: + subs r12, r12, #2 + vld1.8 {d6}, [r2], r1 + vext.8 d7, d6, d6, #1 + vld1.8 {d4}, [r2], r1 + vext.8 d5, d4, d4, #1 + vtrn.32 q3, q2 + vmull.u8 q8, d6, d1 + vmlal.u8 q8, d7, d0 + vrshrn.u16 d16, q8, #3 + vmull.u8 q10, d16, d2 + vtrn.32 d22, d16 + vmlal.u8 q10, d22, d3 + vrev64.32 d22, d16 + vrshrn.u16 d20, q10, #3 + vst1.32 {d20[0]}, [r0,:32], r1 + vst1.32 {d20[1]}, [r0,:32], r1 + bgt 1b + + bx lr +endfunc diff --git a/ffmpeg/libavcodec/ass.c b/ffmpeg/libavcodec/ass.c new file mode 100644 index 0000000..db0fdd8 --- /dev/null +++ b/ffmpeg/libavcodec/ass.c @@ -0,0 +1,107 @@ +/* + * SSA/ASS common functions + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 "avcodec.h" +#include "ass.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/common.h" + +int ff_ass_subtitle_header(AVCodecContext *avctx, + const char *font, int font_size, + int color, int back_color, + int bold, int italic, int underline, + int alignment) +{ + avctx->subtitle_header = av_asprintf( + "[Script Info]\r\n" + "ScriptType: v4.00+\r\n" + "\r\n" + "[V4+ Styles]\r\n" + "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\r\n" + "Style: Default,%s,%d,&H%x,&H%x,&H%x,&H%x,%d,%d,%d,1,1,0,%d,10,10,10,0,0\r\n" + "\r\n" + "[Events]\r\n" + "Format: Layer, Start, End, Style, Text\r\n", + font, font_size, color, color, back_color, back_color, + -bold, -italic, -underline, alignment); + + if (!avctx->subtitle_header) + return AVERROR(ENOMEM); + avctx->subtitle_header_size = strlen(avctx->subtitle_header); + return 0; +} + +int ff_ass_subtitle_header_default(AVCodecContext *avctx) +{ + return ff_ass_subtitle_header(avctx, ASS_DEFAULT_FONT, + ASS_DEFAULT_FONT_SIZE, + ASS_DEFAULT_COLOR, + ASS_DEFAULT_BACK_COLOR, + ASS_DEFAULT_BOLD, + ASS_DEFAULT_ITALIC, + ASS_DEFAULT_UNDERLINE, + ASS_DEFAULT_ALIGNMENT); +} + +static int ts_to_string(char *str, int strlen, int ts) +{ + int h, m, s; + h = ts/360000; ts -= 360000*h; + m = ts/ 6000; ts -= 6000*m; + s = ts/ 100; ts -= 100*s; + return snprintf(str, strlen, "%d:%02d:%02d.%02d", h, m, s, ts); +} + +int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, + int ts_start, int duration, int raw) +{ + int len = 0, dlen; + char s_start[16], s_end[16], header[48] = {0}; + AVSubtitleRect **rects; + + if (!raw) { + ts_to_string(s_start, sizeof(s_start), ts_start); + if (duration == -1) + snprintf(s_end, sizeof(s_end), "9:59:59.99"); + else + ts_to_string(s_end, sizeof(s_end), ts_start + duration); + len = snprintf(header, sizeof(header), "Dialogue: 0,%s,%s,Default,", + s_start, s_end); + av_assert0(len < sizeof(header)); + } + + dlen = strcspn(dialog, "\n"); + dlen += dialog[dlen] == '\n'; + + rects = av_realloc(sub->rects, (sub->num_rects+1) * sizeof(*sub->rects)); + if (!rects) + return AVERROR(ENOMEM); + sub->rects = rects; + sub->end_display_time = FFMAX(sub->end_display_time, 10 * duration); + rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); + rects[sub->num_rects]->type = SUBTITLE_ASS; + rects[sub->num_rects]->ass = av_malloc(len + dlen + 1); + strcpy (rects[sub->num_rects]->ass , header); + av_strlcpy(rects[sub->num_rects]->ass + len, dialog, dlen + 1); + sub->num_rects++; + return dlen; +} diff --git a/ffmpeg/libavcodec/ass.h b/ffmpeg/libavcodec/ass.h new file mode 100644 index 0000000..e9339e4 --- /dev/null +++ b/ffmpeg/libavcodec/ass.h @@ -0,0 +1,91 @@ +/* + * SSA/ASS common functions + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVCODEC_ASS_H +#define AVCODEC_ASS_H + +#include "avcodec.h" + +/** + * @name Default values for ASS style + * @{ + */ +#define ASS_DEFAULT_FONT "Arial" +#define ASS_DEFAULT_FONT_SIZE 16 +#define ASS_DEFAULT_COLOR 0xffffff +#define ASS_DEFAULT_BACK_COLOR 0 +#define ASS_DEFAULT_BOLD 0 +#define ASS_DEFAULT_ITALIC 0 +#define ASS_DEFAULT_UNDERLINE 0 +#define ASS_DEFAULT_ALIGNMENT 2 +/** @} */ + +/** + * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS. + * + * @param avctx pointer to the AVCodecContext + * @param font name of the default font face to use + * @param font_size default font size to use + * @param color default text color to use (ABGR) + * @param back_color default background color to use (ABGR) + * @param bold 1 for bold text, 0 for normal text + * @param italic 1 for italic text, 0 for normal text + * @param underline 1 for underline text, 0 for normal text + * @param alignment position of the text (left, center, top...), defined after + * the layout of the numpad (1-3 sub, 4-6 mid, 7-9 top) + * @return >= 0 on success otherwise an error code <0 + */ +int ff_ass_subtitle_header(AVCodecContext *avctx, + const char *font, int font_size, + int color, int back_color, + int bold, int italic, int underline, + int alignment); + +/** + * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS + * with default style. + * + * @param avctx pointer to the AVCodecContext + * @return >= 0 on success otherwise an error code <0 + */ +int ff_ass_subtitle_header_default(AVCodecContext *avctx); + +/** + * Add an ASS dialog line to an AVSubtitle as a new AVSubtitleRect. + * + * @param sub pointer to the AVSubtitle + * @param dialog ASS dialog to add to sub + * @param ts_start start timestamp for this dialog (in 1/100 second unit) + * @param duration duration for this dialog (in 1/100 second unit), can be -1 + * to last until the end of the presentation + * @param raw when set to 1, it indicates that dialog contains a whole ASS + * dialog line which should be copied as is. + * when set to 0, it indicates that dialog contains only the Text + * part of the ASS dialog line, the rest of the line + * will be generated. + * @return number of characters read from dialog. It can be less than the whole + * length of dialog, if dialog contains several lines of text. + * A negative value indicates an error. + */ +int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, + int ts_start, int duration, int raw); + +#endif /* AVCODEC_ASS_H */ diff --git a/ffmpeg/libavcodec/ass_split.c b/ffmpeg/libavcodec/ass_split.c new file mode 100644 index 0000000..413e9c8 --- /dev/null +++ b/ffmpeg/libavcodec/ass_split.c @@ -0,0 +1,476 @@ +/* + * SSA/ASS spliting functions + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 "avcodec.h" +#include "ass_split.h" + +typedef enum { + ASS_STR, + ASS_INT, + ASS_FLT, + ASS_COLOR, + ASS_TIMESTAMP, + ASS_ALGN, +} ASSFieldType; + +typedef struct { + const char *name; + int type; + int offset; +} ASSFields; + +typedef struct { + const char *section; + const char *format_header; + const char *fields_header; + int size; + int offset; + int offset_count; + ASSFields fields[10]; +} ASSSection; + +static const ASSSection ass_sections[] = { + { .section = "Script Info", + .offset = offsetof(ASS, script_info), + .fields = {{"ScriptType", ASS_STR, offsetof(ASSScriptInfo, script_type)}, + {"Collisions", ASS_STR, offsetof(ASSScriptInfo, collisions) }, + {"PlayResX", ASS_INT, offsetof(ASSScriptInfo, play_res_x) }, + {"PlayResY", ASS_INT, offsetof(ASSScriptInfo, play_res_y) }, + {"Timer", ASS_FLT, offsetof(ASSScriptInfo, timer) }, + {0}, + } + }, + { .section = "V4+ Styles", + .format_header = "Format", + .fields_header = "Style", + .size = sizeof(ASSStyle), + .offset = offsetof(ASS, styles), + .offset_count = offsetof(ASS, styles_count), + .fields = {{"Name", ASS_STR, offsetof(ASSStyle, name) }, + {"Fontname", ASS_STR, offsetof(ASSStyle, font_name) }, + {"Fontsize", ASS_INT, offsetof(ASSStyle, font_size) }, + {"PrimaryColour",ASS_COLOR,offsetof(ASSStyle, primary_color)}, + {"BackColour", ASS_COLOR,offsetof(ASSStyle, back_color) }, + {"Bold", ASS_INT, offsetof(ASSStyle, bold) }, + {"Italic", ASS_INT, offsetof(ASSStyle, italic) }, + {"Underline", ASS_INT, offsetof(ASSStyle, underline) }, + {"Alignment", ASS_INT, offsetof(ASSStyle, alignment) }, + {0}, + } + }, + { .section = "V4 Styles", + .format_header = "Format", + .fields_header = "Style", + .size = sizeof(ASSStyle), + .offset = offsetof(ASS, styles), + .offset_count = offsetof(ASS, styles_count), + .fields = {{"Name", ASS_STR, offsetof(ASSStyle, name) }, + {"Fontname", ASS_STR, offsetof(ASSStyle, font_name) }, + {"Fontsize", ASS_INT, offsetof(ASSStyle, font_size) }, + {"PrimaryColour",ASS_COLOR,offsetof(ASSStyle, primary_color)}, + {"BackColour", ASS_COLOR,offsetof(ASSStyle, back_color) }, + {"Bold", ASS_INT, offsetof(ASSStyle, bold) }, + {"Italic", ASS_INT, offsetof(ASSStyle, italic) }, + {"Alignment", ASS_ALGN, offsetof(ASSStyle, alignment) }, + {0}, + } + }, + { .section = "Events", + .format_header = "Format", + .fields_header = "Dialogue", + .size = sizeof(ASSDialog), + .offset = offsetof(ASS, dialogs), + .offset_count = offsetof(ASS, dialogs_count), + .fields = {{"Layer", ASS_INT, offsetof(ASSDialog, layer) }, + {"Start", ASS_TIMESTAMP, offsetof(ASSDialog, start) }, + {"End", ASS_TIMESTAMP, offsetof(ASSDialog, end) }, + {"Style", ASS_STR, offsetof(ASSDialog, style) }, + {"Text", ASS_STR, offsetof(ASSDialog, text) }, + {0}, + } + }, +}; + + +typedef int (*ASSConvertFunc)(void *dest, const char *buf, int len); + +static int convert_str(void *dest, const char *buf, int len) +{ + char *str = av_malloc(len + 1); + if (str) { + memcpy(str, buf, len); + str[len] = 0; + if (*(void **)dest) + av_free(*(void **)dest); + *(char **)dest = str; + } + return !str; +} +static int convert_int(void *dest, const char *buf, int len) +{ + return sscanf(buf, "%d", (int *)dest) == 1; +} +static int convert_flt(void *dest, const char *buf, int len) +{ + return sscanf(buf, "%f", (float *)dest) == 1; +} +static int convert_color(void *dest, const char *buf, int len) +{ + return sscanf(buf, "&H%8x", (int *)dest) == 1 || + sscanf(buf, "%d", (int *)dest) == 1; +} +static int convert_timestamp(void *dest, const char *buf, int len) +{ + int c, h, m, s, cs; + if ((c = sscanf(buf, "%d:%02d:%02d.%02d", &h, &m, &s, &cs)) == 4) + *(int *)dest = 360000*h + 6000*m + 100*s + cs; + return c == 4; +} +static int convert_alignment(void *dest, const char *buf, int len) +{ + int a; + if (sscanf(buf, "%d", &a) == 1) { + /* convert V4 Style alignment to V4+ Style */ + *(int *)dest = a + ((a&4) >> 1) - 5*!!(a&8); + return 1; + } + return 0; +} + +static const ASSConvertFunc convert_func[] = { + [ASS_STR] = convert_str, + [ASS_INT] = convert_int, + [ASS_FLT] = convert_flt, + [ASS_COLOR] = convert_color, + [ASS_TIMESTAMP] = convert_timestamp, + [ASS_ALGN] = convert_alignment, +}; + + +struct ASSSplitContext { + ASS ass; + int current_section; + int field_number[FF_ARRAY_ELEMS(ass_sections)]; + int *field_order[FF_ARRAY_ELEMS(ass_sections)]; +}; + + +static uint8_t *realloc_section_array(ASSSplitContext *ctx) +{ + const ASSSection *section = &ass_sections[ctx->current_section]; + int *count = (int *)((uint8_t *)&ctx->ass + section->offset_count); + void **section_ptr = (void **)((uint8_t *)&ctx->ass + section->offset); + uint8_t *tmp = av_realloc(*section_ptr, (*count+1)*section->size); + if (!tmp) + return NULL; + *section_ptr = tmp; + tmp += *count * section->size; + memset(tmp, 0, section->size); + (*count)++; + return tmp; +} + +static inline int is_eol(char buf) +{ + return buf == '\r' || buf == '\n' || buf == 0; +} + +static inline const char *skip_space(const char *buf) +{ + while (*buf == ' ') + buf++; + return buf; +} + +static const char *ass_split_section(ASSSplitContext *ctx, const char *buf) +{ + const ASSSection *section = &ass_sections[ctx->current_section]; + int *number = &ctx->field_number[ctx->current_section]; + int *order = ctx->field_order[ctx->current_section]; + int *tmp, i, len; + + while (buf && *buf) { + if (buf[0] == '[') { + ctx->current_section = -1; + break; + } + if (buf[0] == ';' || (buf[0] == '!' && buf[1] == ':')) { + /* skip comments */ + } else if (section->format_header && !order) { + len = strlen(section->format_header); + if (strncmp(buf, section->format_header, len) || buf[len] != ':') + return NULL; + buf += len + 1; + while (!is_eol(*buf)) { + buf = skip_space(buf); + len = strcspn(buf, ", \r\n"); + if (!(tmp = av_realloc(order, (*number + 1) * sizeof(*order)))) + return NULL; + order = tmp; + order[*number] = -1; + for (i=0; section->fields[i].name; i++) + if (!strncmp(buf, section->fields[i].name, len)) { + order[*number] = i; + break; + } + (*number)++; + buf = skip_space(buf + len + (buf[len] == ',')); + } + ctx->field_order[ctx->current_section] = order; + } else if (section->fields_header) { + len = strlen(section->fields_header); + if (!strncmp(buf, section->fields_header, len) && buf[len] == ':') { + uint8_t *ptr, *struct_ptr = realloc_section_array(ctx); + if (!struct_ptr) return NULL; + buf += len + 1; + for (i=0; !is_eol(*buf) && i < *number; i++) { + int last = i == *number - 1; + buf = skip_space(buf); + len = strcspn(buf, last ? "\r\n" : ",\r\n"); + if (order[i] >= 0) { + ASSFieldType type = section->fields[order[i]].type; + ptr = struct_ptr + section->fields[order[i]].offset; + convert_func[type](ptr, buf, len); + } + buf += len; + if (!last && *buf) buf++; + buf = skip_space(buf); + } + } + } else { + len = strcspn(buf, ":\r\n"); + if (buf[len] == ':') { + for (i=0; section->fields[i].name; i++) + if (!strncmp(buf, section->fields[i].name, len)) { + ASSFieldType type = section->fields[i].type; + uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset; + ptr += section->fields[i].offset; + buf = skip_space(buf + len + 1); + convert_func[type](ptr, buf, strcspn(buf, "\r\n")); + break; + } + } + } + buf += strcspn(buf, "\n"); + buf += !!*buf; + } + return buf; +} + +static int ass_split(ASSSplitContext *ctx, const char *buf) +{ + char c, section[16]; + int i; + + if (ctx->current_section >= 0) + buf = ass_split_section(ctx, buf); + + while (buf && *buf) { + if (sscanf(buf, "[%15[0-9A-Za-z+ ]]%c", section, &c) == 2) { + buf += strcspn(buf, "\n"); + buf += !!*buf; + for (i=0; icurrent_section = i; + buf = ass_split_section(ctx, buf); + } + } else { + buf += strcspn(buf, "\n"); + buf += !!*buf; + } + } + return buf ? 0 : AVERROR_INVALIDDATA; +} + +ASSSplitContext *ff_ass_split(const char *buf) +{ + ASSSplitContext *ctx = av_mallocz(sizeof(*ctx)); + ctx->current_section = -1; + if (ass_split(ctx, buf) < 0) { + ff_ass_split_free(ctx); + return NULL; + } + return ctx; +} + +static void free_section(ASSSplitContext *ctx, const ASSSection *section) +{ + uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset; + int i, j, *count, c = 1; + + if (section->format_header) { + ptr = *(void **)ptr; + count = (int *)((uint8_t *)&ctx->ass + section->offset_count); + } else + count = &c; + + if (ptr) + for (i=0; i<*count; i++, ptr += section->size) + for (j=0; section->fields[j].name; j++) { + const ASSFields *field = §ion->fields[j]; + if (field->type == ASS_STR) + av_freep(ptr + field->offset); + } + *count = 0; + + if (section->format_header) + av_freep((uint8_t *)&ctx->ass + section->offset); +} + +ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf, + int cache, int *number) +{ + ASSDialog *dialog = NULL; + int i, count; + if (!cache) + for (i=0; iass.dialogs_count; + if (ass_split(ctx, buf) == 0) + dialog = ctx->ass.dialogs + count; + if (number) + *number = ctx->ass.dialogs_count - count; + return dialog; +} + +void ff_ass_split_free(ASSSplitContext *ctx) +{ + if (ctx) { + int i; + for (i=0; ifield_order[i])); + } + av_free(ctx); + } +} + + +int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, + const char *buf) +{ + const char *text = NULL; + char new_line[2]; + int text_len = 0; + + while (buf && *buf) { + if (text && callbacks->text && + (sscanf(buf, "\\%1[nN]", new_line) == 1 || + !strncmp(buf, "{\\", 2))) { + callbacks->text(priv, text, text_len); + text = NULL; + } + if (sscanf(buf, "\\%1[nN]", new_line) == 1) { + if (callbacks->new_line) + callbacks->new_line(priv, new_line[0] == 'N'); + buf += 2; + } else if (!strncmp(buf, "{\\", 2)) { + buf++; + while (*buf == '\\') { + char style[2], c[2], sep[2], c_num[2] = "0", tmp[128] = {0}; + unsigned int color = 0xFFFFFFFF; + int len, size = -1, an = -1, alpha = -1; + int x1, y1, x2, y2, t1 = -1, t2 = -1; + if (sscanf(buf, "\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) { + int close = c[0] == '0' ? 1 : c[0] == '1' ? 0 : -1; + len += close != -1; + if (callbacks->style) + callbacks->style(priv, style[0], close); + } else if (sscanf(buf, "\\c%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 || + sscanf(buf, "\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 || + sscanf(buf, "\\%1[1234]c&H%X&%1[\\}]%n", c_num, &color, sep, &len) > 2) { + if (callbacks->color) + callbacks->color(priv, color, c_num[0] - '0'); + } else if (sscanf(buf, "\\alpha%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\alpha&H%2X&%1[\\}]%n", &alpha, sep, &len) > 1 || + sscanf(buf, "\\%1[1234]a%1[\\}]%n", c_num, sep, &len) > 1 || + sscanf(buf, "\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &alpha, sep, &len) > 2) { + if (callbacks->alpha) + callbacks->alpha(priv, alpha, c_num[0] - '0'); + } else if (sscanf(buf, "\\fn%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fn%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) { + if (callbacks->font_name) + callbacks->font_name(priv, tmp[0] ? tmp : NULL); + } else if (sscanf(buf, "\\fs%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\fs%u%1[\\}]%n", &size, sep, &len) > 1) { + if (callbacks->font_size) + callbacks->font_size(priv, size); + } else if (sscanf(buf, "\\a%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\a%2u%1[\\}]%n", &an, sep, &len) > 1 || + sscanf(buf, "\\an%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\an%1u%1[\\}]%n", &an, sep, &len) > 1) { + if (an != -1 && buf[2] != 'n') + an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0); + if (callbacks->alignment) + callbacks->alignment(priv, an); + } else if (sscanf(buf, "\\r%1[\\}]%n", sep, &len) > 0 || + sscanf(buf, "\\r%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) { + if (callbacks->cancel_overrides) + callbacks->cancel_overrides(priv, tmp); + } else if (sscanf(buf, "\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4 || + sscanf(buf, "\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &t2, sep, &len) > 6) { + if (callbacks->move) + callbacks->move(priv, x1, y1, x2, y2, t1, t2); + } else if (sscanf(buf, "\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) { + if (callbacks->move) + callbacks->move(priv, x1, y1, x1, y1, -1, -1); + } else if (sscanf(buf, "\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) { + if (callbacks->origin) + callbacks->origin(priv, x1, y1); + } else { + len = strcspn(buf+1, "\\}") + 2; /* skip unknown code */ + } + buf += len - 1; + } + if (*buf++ != '}') + return AVERROR_INVALIDDATA; + } else { + if (!text) { + text = buf; + text_len = 1; + } else + text_len++; + buf++; + } + } + if (text && callbacks->text) + callbacks->text(priv, text, text_len); + if (callbacks->end) + callbacks->end(priv); + return 0; +} + +ASSStyle *ff_ass_style_get(ASSSplitContext *ctx, const char *style) +{ + ASS *ass = &ctx->ass; + int i; + + if (!style || !*style) + style = "Default"; + for (i=0; istyles_count; i++) + if (!strcmp(ass->styles[i].name, style)) + return ass->styles + i; + return NULL; +} diff --git a/ffmpeg/libavcodec/ass_split.h b/ffmpeg/libavcodec/ass_split.h new file mode 100644 index 0000000..7a6a75e --- /dev/null +++ b/ffmpeg/libavcodec/ass_split.h @@ -0,0 +1,172 @@ +/* + * SSA/ASS spliting functions + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVCODEC_ASS_SPLIT_H +#define AVCODEC_ASS_SPLIT_H + +/** + * fields extracted from the [Script Info] section + */ +typedef struct { + char *script_type; /**< SSA script format version (eg. v4.00) */ + char *collisions; /**< how subtitles are moved to prevent collisions */ + int play_res_x; /**< video width that ASS coords are referring to */ + int play_res_y; /**< video height that ASS coords are referring to */ + float timer; /**< time multiplier to apply to SSA clock (in %) */ +} ASSScriptInfo; + +/** + * fields extracted from the [V4(+) Styles] section + */ +typedef struct { + char *name; /**< name of the tyle (case sensitive) */ + char *font_name; /**< font face (case sensitive) */ + int font_size; /**< font height */ + int primary_color; /**< color that a subtitle will normally appear in */ + int back_color; /**< color of the subtitle outline or shadow */ + int bold; /**< whether text is bold (1) or not (0) */ + int italic; /**< whether text is italic (1) or not (0) */ + int underline; /**< whether text is underlined (1) or not (0) */ + int alignment; /**< position of the text (left, center, top...), + defined after the layout of the numpad + (1-3 sub, 4-6 mid, 7-9 top) */ +} ASSStyle; + +/** + * fields extracted from the [Events] section + */ +typedef struct { + int layer; /**< higher numbered layers are drawn over lower numbered */ + int start; /**< start time of the dialog in centiseconds */ + int end; /**< end time of the dialog in centiseconds */ + char *style; /**< name of the ASSStyle to use with this dialog */ + char *text; /**< actual text which will be displayed as a subtitle, + can include style override control codes (see + ff_ass_split_override_codes()) */ +} ASSDialog; + +/** + * structure containing the whole split ASS data + */ +typedef struct { + ASSScriptInfo script_info; /**< general information about the SSA script*/ + ASSStyle *styles; /**< array of split out styles */ + int styles_count; /**< number of ASSStyle in the styles array */ + ASSDialog *dialogs; /**< array of split out dialogs */ + int dialogs_count; /**< number of ASSDialog in the dialogs array*/ +} ASS; + +/** + * This struct can be casted to ASS to access to the split data. + */ +typedef struct ASSSplitContext ASSSplitContext; + +/** + * Split a full ASS file or a ASS header from a string buffer and store + * the split structure in a newly allocated context. + * + * @param buf String containing the ASS formated data. + * @return Newly allocated struct containing split data. + */ +ASSSplitContext *ff_ass_split(const char *buf); + +/** + * Split one or several ASS "Dialogue" lines from a string buffer and store + * them in a already initialized context. + * + * @param ctx Context previously initialized by ff_ass_split(). + * @param buf String containing the ASS "Dialogue" lines. + * @param cache Set to 1 to keep all the previously split ASSDialog in + * the context, or set to 0 to free all the previously split + * ASSDialog. + * @param number If not NULL, the pointed integer will be set to the number + * of split ASSDialog. + * @return Pointer to the first split ASSDialog. + */ +ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf, + int cache, int *number); + +/** + * Free all the memory allocated for an ASSSplitContext. + * + * @param ctx Context previously initialized by ff_ass_split(). + */ +void ff_ass_split_free(ASSSplitContext *ctx); + + +/** + * Set of callback functions corresponding to each override codes that can + * be encountered in a "Dialogue" Text field. + */ +typedef struct { + /** + * @defgroup ass_styles ASS styles + * @{ + */ + void (*text)(void *priv, const char *text, int len); + void (*new_line)(void *priv, int forced); + void (*style)(void *priv, char style, int close); + void (*color)(void *priv, unsigned int color, unsigned int color_id); + void (*alpha)(void *priv, int alpha, int alpha_id); + void (*font_name)(void *priv, const char *name); + void (*font_size)(void *priv, int size); + void (*alignment)(void *priv, int alignment); + void (*cancel_overrides)(void *priv, const char *style); + /** @} */ + + /** + * @defgroup ass_functions ASS functions + * @{ + */ + void (*move)(void *priv, int x1, int y1, int x2, int y2, int t1, int t2); + void (*origin)(void *priv, int x, int y); + /** @} */ + + /** + * @defgroup ass_end end of Dialogue Event + * @{ + */ + void (*end)(void *priv); + /** @} */ +} ASSCodesCallbacks; + +/** + * Split override codes out of a ASS "Dialogue" Text field. + * + * @param callbacks Set of callback functions called for each override code + * encountered. + * @param priv Opaque pointer passed to the callback functions. + * @param buf The ASS "Dialogue" Text field to split. + * @return >= 0 on success otherwise an error code <0 + */ +int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, + const char *buf); + +/** + * Find an ASSStyle structure by its name. + * + * @param ctx Context previously initialized by ff_ass_split(). + * @param style name of the style to search for. + * @return the ASSStyle corresponding to style, or NULL if style can't be found + */ +ASSStyle *ff_ass_style_get(ASSSplitContext *ctx, const char *style); + +#endif /* AVCODEC_ASS_SPLIT_H */ diff --git a/ffmpeg/libavcodec/assdec.c b/ffmpeg/libavcodec/assdec.c new file mode 100644 index 0000000..d790656 --- /dev/null +++ b/ffmpeg/libavcodec/assdec.c @@ -0,0 +1,82 @@ +/* + * SSA/ASS decoder + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 "avcodec.h" +#include "ass.h" +#include "ass_split.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +static av_cold int ass_decode_init(AVCodecContext *avctx) +{ + avctx->subtitle_header = av_malloc(avctx->extradata_size + 1); + if (!avctx->subtitle_header) + return AVERROR(ENOMEM); + memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size); + avctx->subtitle_header[avctx->extradata_size] = 0; + avctx->subtitle_header_size = avctx->extradata_size; + avctx->priv_data = ff_ass_split(avctx->extradata); + if(!avctx->priv_data) + return -1; + return 0; +} + +static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, + AVPacket *avpkt) +{ + const char *ptr = avpkt->data; + int len, size = avpkt->size; + + while (size > 0) { + int duration; + ASSDialog *dialog = ff_ass_split_dialog(avctx->priv_data, ptr, 0, NULL); + if (!dialog) + return AVERROR_INVALIDDATA; + duration = dialog->end - dialog->start; + len = ff_ass_add_rect(data, ptr, 0, duration, 1); + if (len < 0) + return len; + ptr += len; + size -= len; + } + + *got_sub_ptr = avpkt->size > 0; + return avpkt->size; +} + +static int ass_decode_close(AVCodecContext *avctx) +{ + ff_ass_split_free(avctx->priv_data); + avctx->priv_data = NULL; + return 0; +} + +AVCodec ff_ass_decoder = { + .name = "ass", + .long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SSA, + .init = ass_decode_init, + .decode = ass_decode_frame, + .close = ass_decode_close, +}; diff --git a/ffmpeg/libavcodec/assenc.c b/ffmpeg/libavcodec/assenc.c new file mode 100644 index 0000000..50b89c0 --- /dev/null +++ b/ffmpeg/libavcodec/assenc.c @@ -0,0 +1,72 @@ +/* + * SSA/ASS encoder + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 "avcodec.h" +#include "libavutil/avstring.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +static av_cold int ass_encode_init(AVCodecContext *avctx) +{ + avctx->extradata = av_malloc(avctx->subtitle_header_size + 1); + if (!avctx->extradata) + return AVERROR(ENOMEM); + memcpy(avctx->extradata, avctx->subtitle_header, avctx->subtitle_header_size); + avctx->extradata_size = avctx->subtitle_header_size; + avctx->extradata[avctx->extradata_size] = 0; + return 0; +} + +static int ass_encode_frame(AVCodecContext *avctx, + unsigned char *buf, int bufsize, + const AVSubtitle *sub) +{ + int i, len, total_len = 0; + + for (i=0; inum_rects; i++) { + if (sub->rects[i]->type != SUBTITLE_ASS) { + av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); + return -1; + } + + len = av_strlcpy(buf+total_len, sub->rects[i]->ass, bufsize-total_len); + + if (len > bufsize-total_len-1) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); + return -1; + } + + total_len += len; + } + + return total_len; +} + +AVCodec ff_ass_encoder = { + .name = "ass", + .long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SSA, + .init = ass_encode_init, + .encode_sub = ass_encode_frame, +}; diff --git a/ffmpeg/libavcodec/asv.c b/ffmpeg/libavcodec/asv.c new file mode 100644 index 0000000..21f179b --- /dev/null +++ b/ffmpeg/libavcodec/asv.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2003 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 + */ + +/** + * @file + * ASUS V1/V2 encoder/decoder common data + */ + +#include + +#include "asv.h" +#include "avcodec.h" + +const uint8_t ff_asv_scantab[64] = { + 0x00,0x08,0x01,0x09,0x10,0x18,0x11,0x19, + 0x02,0x0A,0x03,0x0B,0x12,0x1A,0x13,0x1B, + 0x04,0x0C,0x05,0x0D,0x20,0x28,0x21,0x29, + 0x06,0x0E,0x07,0x0F,0x14,0x1C,0x15,0x1D, + 0x22,0x2A,0x23,0x2B,0x30,0x38,0x31,0x39, + 0x16,0x1E,0x17,0x1F,0x24,0x2C,0x25,0x2D, + 0x32,0x3A,0x33,0x3B,0x26,0x2E,0x27,0x2F, + 0x34,0x3C,0x35,0x3D,0x36,0x3E,0x37,0x3F, +}; + +const uint8_t ff_asv_ccp_tab[17][2] = { + {0x2,2}, {0x7,5}, {0xB,5}, {0x3,5}, + {0xD,5}, {0x5,5}, {0x9,5}, {0x1,5}, + {0xE,5}, {0x6,5}, {0xA,5}, {0x2,5}, + {0xC,5}, {0x4,5}, {0x8,5}, {0x3,2}, + {0xF,5}, //EOB +}; + +const uint8_t ff_asv_level_tab[7][2] = { + {3,4}, {3,3}, {3,2}, {0,3}, {2,2}, {2,3}, {2,4} +}; + +const uint8_t ff_asv_dc_ccp_tab[8][2] = { + {0x1,2}, {0xD,4}, {0xF,4}, {0xC,4}, + {0x5,3}, {0xE,4}, {0x4,3}, {0x0,2}, +}; + +const uint8_t ff_asv_ac_ccp_tab[16][2] = { + {0x00,2}, {0x3B,6}, {0x0A,4}, {0x3A,6}, + {0x02,3}, {0x39,6}, {0x3C,6}, {0x38,6}, + {0x03,3}, {0x3D,6}, {0x08,4}, {0x1F,5}, + {0x09,4}, {0x0B,4}, {0x0D,4}, {0x0C,4}, +}; + +const uint8_t ff_asv2_level_tab[63][2] = { + {0x3F,10},{0x2F,10},{0x37,10},{0x27,10},{0x3B,10},{0x2B,10},{0x33,10},{0x23,10}, + {0x3D,10},{0x2D,10},{0x35,10},{0x25,10},{0x39,10},{0x29,10},{0x31,10},{0x21,10}, + {0x1F, 8},{0x17, 8},{0x1B, 8},{0x13, 8},{0x1D, 8},{0x15, 8},{0x19, 8},{0x11, 8}, + {0x0F, 6},{0x0B, 6},{0x0D, 6},{0x09, 6}, + {0x07, 4},{0x05, 4}, + {0x03, 2}, + {0x00, 5}, + {0x02, 2}, + {0x04, 4},{0x06, 4}, + {0x08, 6},{0x0C, 6},{0x0A, 6},{0x0E, 6}, + {0x10, 8},{0x18, 8},{0x14, 8},{0x1C, 8},{0x12, 8},{0x1A, 8},{0x16, 8},{0x1E, 8}, + {0x20,10},{0x30,10},{0x28,10},{0x38,10},{0x24,10},{0x34,10},{0x2C,10},{0x3C,10}, + {0x22,10},{0x32,10},{0x2A,10},{0x3A,10},{0x26,10},{0x36,10},{0x2E,10},{0x3E,10}, +}; + +av_cold void ff_asv_common_init(AVCodecContext *avctx) { + ASV1Context * const a = avctx->priv_data; + + ff_dsputil_init(&a->dsp, avctx); + + a->mb_width = (avctx->width + 15) / 16; + a->mb_height = (avctx->height + 15) / 16; + a->mb_width2 = (avctx->width + 0) / 16; + a->mb_height2 = (avctx->height + 0) / 16; + + avctx->coded_frame= &a->picture; + a->avctx= avctx; +} diff --git a/ffmpeg/libavcodec/asv.h b/ffmpeg/libavcodec/asv.h new file mode 100644 index 0000000..ca67c67 --- /dev/null +++ b/ffmpeg/libavcodec/asv.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003 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 + */ + +/** + * @file + * ASUS V1/V2 encoder/decoder common data. + */ + +#ifndef AVCODEC_ASV_H +#define AVCODEC_ASV_H + +#include + +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "put_bits.h" + +typedef struct ASV1Context{ + AVCodecContext *avctx; + DSPContext dsp; + AVFrame picture; + PutBitContext pb; + GetBitContext gb; + ScanTable scantable; + int inv_qscale; + int mb_width; + int mb_height; + int mb_width2; + int mb_height2; + DECLARE_ALIGNED(16, int16_t, block)[6][64]; + uint16_t intra_matrix[64]; + int q_intra_matrix[64]; + uint8_t *bitstream_buffer; + unsigned int bitstream_buffer_size; +} ASV1Context; + +extern const uint8_t ff_asv_scantab[64]; +extern const uint8_t ff_asv_ccp_tab[17][2]; +extern const uint8_t ff_asv_level_tab[7][2]; +extern const uint8_t ff_asv_dc_ccp_tab[8][2]; +extern const uint8_t ff_asv_ac_ccp_tab[16][2]; +extern const uint8_t ff_asv2_level_tab[63][2]; + +void ff_asv_common_init(AVCodecContext *avctx); + +#endif /* AVCODEC_ASV_H */ diff --git a/ffmpeg/libavcodec/asvdec.c b/ffmpeg/libavcodec/asvdec.c new file mode 100644 index 0000000..7dca22b --- /dev/null +++ b/ffmpeg/libavcodec/asvdec.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2003 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 + */ + +/** + * @file + * ASUS V1/V2 decoder. + */ + +#include "libavutil/attributes.h" +#include "libavutil/mem.h" + +#include "asv.h" +#include "avcodec.h" +#include "put_bits.h" +#include "internal.h" +#include "mathops.h" +#include "mpeg12data.h" + +#define VLC_BITS 6 +#define ASV2_LEVEL_VLC_BITS 10 + +static VLC ccp_vlc; +static VLC level_vlc; +static VLC dc_ccp_vlc; +static VLC ac_ccp_vlc; +static VLC asv2_level_vlc; + +static av_cold void init_vlcs(ASV1Context *a) +{ + static int done = 0; + + if (!done) { + done = 1; + + INIT_VLC_STATIC(&ccp_vlc, VLC_BITS, 17, + &ff_asv_ccp_tab[0][1], 2, 1, + &ff_asv_ccp_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&dc_ccp_vlc, VLC_BITS, 8, + &ff_asv_dc_ccp_tab[0][1], 2, 1, + &ff_asv_dc_ccp_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&ac_ccp_vlc, VLC_BITS, 16, + &ff_asv_ac_ccp_tab[0][1], 2, 1, + &ff_asv_ac_ccp_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&level_vlc, VLC_BITS, 7, + &ff_asv_level_tab[0][1], 2, 1, + &ff_asv_level_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63, + &ff_asv2_level_tab[0][1], 2, 1, + &ff_asv2_level_tab[0][0], 2, 1, 1024); + } +} + +//FIXME write a reversed bitstream reader to avoid the double reverse +static inline int asv2_get_bits(GetBitContext *gb, int n) +{ + return ff_reverse[get_bits(gb, n) << (8-n)]; +} + +static inline int asv1_get_level(GetBitContext *gb) +{ + int code = get_vlc2(gb, level_vlc.table, VLC_BITS, 1); + + if (code == 3) + return get_sbits(gb, 8); + else + return code - 3; +} + +static inline int asv2_get_level(GetBitContext *gb) +{ + int code = get_vlc2(gb, asv2_level_vlc.table, ASV2_LEVEL_VLC_BITS, 1); + + if (code == 31) + return (int8_t)asv2_get_bits(gb, 8); + else + return code - 31; +} + +static inline int asv1_decode_block(ASV1Context *a, int16_t block[64]) +{ + int i; + + block[0] = 8 * get_bits(&a->gb, 8); + + for (i = 0; i < 11; i++) { + const int ccp = get_vlc2(&a->gb, ccp_vlc.table, VLC_BITS, 1); + + if (ccp) { + if (ccp == 16) + break; + if (ccp < 0 || i >= 10) { + av_log(a->avctx, AV_LOG_ERROR, "coded coeff pattern damaged\n"); + return AVERROR_INVALIDDATA; + } + + if (ccp & 8) + block[a->scantable.permutated[4 * i + 0]] = (asv1_get_level(&a->gb) * a->intra_matrix[4 * i + 0]) >> 4; + if (ccp & 4) + block[a->scantable.permutated[4 * i + 1]] = (asv1_get_level(&a->gb) * a->intra_matrix[4 * i + 1]) >> 4; + if (ccp & 2) + block[a->scantable.permutated[4 * i + 2]] = (asv1_get_level(&a->gb) * a->intra_matrix[4 * i + 2]) >> 4; + if (ccp & 1) + block[a->scantable.permutated[4 * i + 3]] = (asv1_get_level(&a->gb) * a->intra_matrix[4 * i + 3]) >> 4; + } + } + + return 0; +} + +static inline int asv2_decode_block(ASV1Context *a, int16_t block[64]) +{ + int i, count, ccp; + + count = asv2_get_bits(&a->gb, 4); + + block[0] = 8 * asv2_get_bits(&a->gb, 8); + + ccp = get_vlc2(&a->gb, dc_ccp_vlc.table, VLC_BITS, 1); + if (ccp) { + if (ccp & 4) + block[a->scantable.permutated[1]] = (asv2_get_level(&a->gb) * a->intra_matrix[1]) >> 4; + if (ccp & 2) + block[a->scantable.permutated[2]] = (asv2_get_level(&a->gb) * a->intra_matrix[2]) >> 4; + if (ccp & 1) + block[a->scantable.permutated[3]] = (asv2_get_level(&a->gb) * a->intra_matrix[3]) >> 4; + } + + for (i = 1; i < count + 1; i++) { + const int ccp = get_vlc2(&a->gb, ac_ccp_vlc.table, VLC_BITS, 1); + + if (ccp) { + if (ccp & 8) + block[a->scantable.permutated[4*i + 0]] = (asv2_get_level(&a->gb) * a->intra_matrix[4*i + 0]) >> 4; + if (ccp & 4) + block[a->scantable.permutated[4*i + 1]] = (asv2_get_level(&a->gb) * a->intra_matrix[4*i + 1]) >> 4; + if (ccp & 2) + block[a->scantable.permutated[4*i + 2]] = (asv2_get_level(&a->gb) * a->intra_matrix[4*i + 2]) >> 4; + if (ccp & 1) + block[a->scantable.permutated[4*i + 3]] = (asv2_get_level(&a->gb) * a->intra_matrix[4*i + 3]) >> 4; + } + } + + return 0; +} + +static inline int decode_mb(ASV1Context *a, int16_t block[6][64]) +{ + int i; + + a->dsp.clear_blocks(block[0]); + + if (a->avctx->codec_id == AV_CODEC_ID_ASV1) { + for (i = 0; i < 6; i++) { + if (asv1_decode_block(a, block[i]) < 0) + return -1; + } + } else { + for (i = 0; i < 6; i++) { + if (asv2_decode_block(a, block[i]) < 0) + return -1; + } + } + return 0; +} + +static inline void idct_put(ASV1Context *a, AVFrame *frame, int mb_x, int mb_y) +{ + int16_t (*block)[64] = a->block; + int linesize = frame->linesize[0]; + + uint8_t *dest_y = frame->data[0] + (mb_y * 16* linesize ) + mb_x * 16; + uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; + uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; + + a->dsp.idct_put(dest_y , linesize, block[0]); + a->dsp.idct_put(dest_y + 8, linesize, block[1]); + a->dsp.idct_put(dest_y + 8*linesize , linesize, block[2]); + a->dsp.idct_put(dest_y + 8*linesize + 8, linesize, block[3]); + + if (!(a->avctx->flags&CODEC_FLAG_GRAY)) { + a->dsp.idct_put(dest_cb, frame->linesize[1], block[4]); + a->dsp.idct_put(dest_cr, frame->linesize[2], block[5]); + } +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + ASV1Context * const a = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame * const p = data; + int mb_x, mb_y, ret; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, + buf_size); + if (!a->bitstream_buffer) + return AVERROR(ENOMEM); + + if (avctx->codec_id == AV_CODEC_ID_ASV1) + a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (const uint32_t*)buf, buf_size/4); + else { + int i; + for (i = 0; i < buf_size; i++) + a->bitstream_buffer[i] = ff_reverse[buf[i]]; + } + + init_get_bits(&a->gb, a->bitstream_buffer, buf_size*8); + + for (mb_y = 0; mb_y < a->mb_height2; mb_y++) { + for (mb_x = 0; mb_x < a->mb_width2; mb_x++) { + if ((ret = decode_mb(a, a->block)) < 0) + return ret; + + idct_put(a, p, mb_x, mb_y); + } + } + + if (a->mb_width2 != a->mb_width) { + mb_x = a->mb_width2; + for (mb_y = 0; mb_y < a->mb_height2; mb_y++) { + if ((ret = decode_mb(a, a->block)) < 0) + return ret; + + idct_put(a, p, mb_x, mb_y); + } + } + + if (a->mb_height2 != a->mb_height) { + mb_y = a->mb_height2; + for (mb_x = 0; mb_x < a->mb_width; mb_x++) { + if ((ret = decode_mb(a, a->block)) < 0) + return ret; + + idct_put(a, p, mb_x, mb_y); + } + } + + *got_frame = 1; + + emms_c(); + + return (get_bits_count(&a->gb) + 31) / 32 * 4; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + ASV1Context * const a = avctx->priv_data; + const int scale = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; + int i; + + ff_asv_common_init(avctx); + init_vlcs(a); + ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_asv_scantab); + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + if (avctx->extradata_size < 1 || (a->inv_qscale = avctx->extradata[0]) == 0) { + av_log(avctx, AV_LOG_ERROR, "illegal qscale 0\n"); + if (avctx->codec_id == AV_CODEC_ID_ASV1) + a->inv_qscale = 6; + else + a->inv_qscale = 10; + } + + for (i = 0; i < 64; i++) { + int index = ff_asv_scantab[i]; + + a->intra_matrix[i] = 64 * scale * ff_mpeg1_default_intra_matrix[index] / a->inv_qscale; + } + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + ASV1Context * const a = avctx->priv_data; + + av_freep(&a->bitstream_buffer); + a->bitstream_buffer_size = 0; + + return 0; +} + +#if CONFIG_ASV1_DECODER +AVCodec ff_asv1_decoder = { + .name = "asv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ASV1, + .priv_data_size = sizeof(ASV1Context), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), +}; +#endif + +#if CONFIG_ASV2_DECODER +AVCodec ff_asv2_decoder = { + .name = "asv2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ASV2, + .priv_data_size = sizeof(ASV1Context), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), +}; +#endif + diff --git a/ffmpeg/libavcodec/asvenc.c b/ffmpeg/libavcodec/asvenc.c new file mode 100644 index 0000000..a09aa73 --- /dev/null +++ b/ffmpeg/libavcodec/asvenc.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2003 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 + */ + +/** + * @file + * ASUS V1/V2 encoder. + */ + +#include "libavutil/attributes.h" +#include "libavutil/mem.h" + +#include "asv.h" +#include "avcodec.h" +#include "internal.h" +#include "mathops.h" +#include "mpeg12data.h" + +static inline void asv2_put_bits(PutBitContext *pb, int n, int v){ + put_bits(pb, n, ff_reverse[ v << (8-n) ]); +} + +static inline void asv1_put_level(PutBitContext *pb, int level){ + unsigned int index= level + 3; + + if(index <= 6) put_bits(pb, ff_asv_level_tab[index][1], ff_asv_level_tab[index][0]); + else{ + put_bits(pb, ff_asv_level_tab[3][1], ff_asv_level_tab[3][0]); + put_sbits(pb, 8, level); + } +} + +static inline void asv2_put_level(PutBitContext *pb, int level){ + unsigned int index= level + 31; + + if(index <= 62) put_bits(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]); + else{ + put_bits(pb, ff_asv2_level_tab[31][1], ff_asv2_level_tab[31][0]); + asv2_put_bits(pb, 8, level&0xFF); + } +} + +static inline void asv1_encode_block(ASV1Context *a, int16_t block[64]){ + int i; + int nc_count=0; + + put_bits(&a->pb, 8, (block[0] + 32)>>6); + block[0]= 0; + + for(i=0; i<10; i++){ + const int index = ff_asv_scantab[4*i]; + int ccp=0; + + if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8; + if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4; + if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2; + if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1; + + if(ccp){ + for(;nc_count; nc_count--) + put_bits(&a->pb, ff_asv_ccp_tab[0][1], ff_asv_ccp_tab[0][0]); + + put_bits(&a->pb, ff_asv_ccp_tab[ccp][1], ff_asv_ccp_tab[ccp][0]); + + if(ccp&8) asv1_put_level(&a->pb, block[index + 0]); + if(ccp&4) asv1_put_level(&a->pb, block[index + 8]); + if(ccp&2) asv1_put_level(&a->pb, block[index + 1]); + if(ccp&1) asv1_put_level(&a->pb, block[index + 9]); + }else{ + nc_count++; + } + } + put_bits(&a->pb, ff_asv_ccp_tab[16][1], ff_asv_ccp_tab[16][0]); +} + +static inline void asv2_encode_block(ASV1Context *a, int16_t block[64]){ + int i; + int count=0; + + for(count=63; count>3; count--){ + const int index = ff_asv_scantab[count]; + + if( (block[index]*a->q_intra_matrix[index] + (1<<15))>>16 ) + break; + } + + count >>= 2; + + asv2_put_bits(&a->pb, 4, count); + asv2_put_bits(&a->pb, 8, (block[0] + 32)>>6); + block[0]= 0; + + for(i=0; i<=count; i++){ + const int index = ff_asv_scantab[4*i]; + int ccp=0; + + if( (block[index + 0] = (block[index + 0]*a->q_intra_matrix[index + 0] + (1<<15))>>16) ) ccp |= 8; + if( (block[index + 8] = (block[index + 8]*a->q_intra_matrix[index + 8] + (1<<15))>>16) ) ccp |= 4; + if( (block[index + 1] = (block[index + 1]*a->q_intra_matrix[index + 1] + (1<<15))>>16) ) ccp |= 2; + if( (block[index + 9] = (block[index + 9]*a->q_intra_matrix[index + 9] + (1<<15))>>16) ) ccp |= 1; + + av_assert2(i || ccp<8); + if(i) put_bits(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]); + else put_bits(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]); + + if(ccp){ + if(ccp&8) asv2_put_level(&a->pb, block[index + 0]); + if(ccp&4) asv2_put_level(&a->pb, block[index + 8]); + if(ccp&2) asv2_put_level(&a->pb, block[index + 1]); + if(ccp&1) asv2_put_level(&a->pb, block[index + 9]); + } + } +} + +#define MAX_MB_SIZE (30*16*16*3/2/8) + +static inline int encode_mb(ASV1Context *a, int16_t block[6][64]){ + int i; + + if (a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < MAX_MB_SIZE) { + av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + + if(a->avctx->codec_id == AV_CODEC_ID_ASV1){ + for(i=0; i<6; i++) + asv1_encode_block(a, block[i]); + }else{ + for(i=0; i<6; i++) + asv2_encode_block(a, block[i]); + } + return 0; +} + +static inline void dct_get(ASV1Context *a, int mb_x, int mb_y){ + int16_t (*block)[64]= a->block; + int linesize= a->picture.linesize[0]; + int i; + + uint8_t *ptr_y = a->picture.data[0] + (mb_y * 16* linesize ) + mb_x * 16; + uint8_t *ptr_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8; + uint8_t *ptr_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8; + + a->dsp.get_pixels(block[0], ptr_y , linesize); + a->dsp.get_pixels(block[1], ptr_y + 8, linesize); + a->dsp.get_pixels(block[2], ptr_y + 8*linesize , linesize); + a->dsp.get_pixels(block[3], ptr_y + 8*linesize + 8, linesize); + for(i=0; i<4; i++) + a->dsp.fdct(block[i]); + + if(!(a->avctx->flags&CODEC_FLAG_GRAY)){ + a->dsp.get_pixels(block[4], ptr_cb, a->picture.linesize[1]); + a->dsp.get_pixels(block[5], ptr_cr, a->picture.linesize[2]); + for(i=4; i<6; i++) + a->dsp.fdct(block[i]); + } +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + ASV1Context * const a = avctx->priv_data; + AVFrame * const p= &a->picture; + int size, ret; + int mb_x, mb_y; + + if ((ret = ff_alloc_packet2(avctx, pkt, a->mb_height*a->mb_width*MAX_MB_SIZE + + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + init_put_bits(&a->pb, pkt->data, pkt->size); + + *p = *pict; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + for(mb_y=0; mb_ymb_height2; mb_y++){ + for(mb_x=0; mb_xmb_width2; mb_x++){ + dct_get(a, mb_x, mb_y); + encode_mb(a, a->block); + } + } + + if(a->mb_width2 != a->mb_width){ + mb_x= a->mb_width2; + for(mb_y=0; mb_ymb_height2; mb_y++){ + dct_get(a, mb_x, mb_y); + encode_mb(a, a->block); + } + } + + if(a->mb_height2 != a->mb_height){ + mb_y= a->mb_height2; + for(mb_x=0; mb_xmb_width; mb_x++){ + dct_get(a, mb_x, mb_y); + encode_mb(a, a->block); + } + } + emms_c(); + + avpriv_align_put_bits(&a->pb); + while(put_bits_count(&a->pb)&31) + put_bits(&a->pb, 8, 0); + + size= put_bits_count(&a->pb)/32; + + if(avctx->codec_id == AV_CODEC_ID_ASV1) + a->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); + else{ + int i; + for(i=0; i<4*size; i++) + pkt->data[i] = ff_reverse[pkt->data[i]]; + } + + pkt->size = size*4; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int encode_init(AVCodecContext *avctx){ + ASV1Context * const a = avctx->priv_data; + int i; + const int scale= avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2; + + ff_asv_common_init(avctx); + + if(avctx->global_quality == 0) avctx->global_quality= 4*FF_QUALITY_SCALE; + + a->inv_qscale= (32*scale*FF_QUALITY_SCALE + avctx->global_quality/2) / avctx->global_quality; + + avctx->extradata= av_mallocz(8); + avctx->extradata_size=8; + ((uint32_t*)avctx->extradata)[0]= av_le2ne32(a->inv_qscale); + ((uint32_t*)avctx->extradata)[1]= av_le2ne32(AV_RL32("ASUS")); + + for(i=0; i<64; i++){ + int q= 32*scale*ff_mpeg1_default_intra_matrix[i]; + a->q_intra_matrix[i]= ((a->inv_qscale<<16) + q/2) / q; + } + + return 0; +} + +#if CONFIG_ASV1_ENCODER +AVCodec ff_asv1_encoder = { + .name = "asv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ASV1, + .priv_data_size = sizeof(ASV1Context), + .init = encode_init, + .encode2 = encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), +}; +#endif + +#if CONFIG_ASV2_ENCODER +AVCodec ff_asv2_encoder = { + .name = "asv2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ASV2, + .priv_data_size = sizeof(ASV1Context), + .init = encode_init, + .encode2 = encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), +}; +#endif diff --git a/ffmpeg/libavcodec/atrac.c b/ffmpeg/libavcodec/atrac.c new file mode 100644 index 0000000..ea342a0 --- /dev/null +++ b/ffmpeg/libavcodec/atrac.c @@ -0,0 +1,119 @@ +/* + * Atrac common functions + * Copyright (c) 2006-2008 Maxim Poliakovski + * Copyright (c) 2006-2008 Benjamin Larsson + * + * 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 + */ + +/** + * @file + */ + +#include +#include +#include +#include + +#include "avcodec.h" +#include "atrac.h" + +float ff_atrac_sf_table[64]; +static float qmf_window[48]; + +static const float qmf_48tap_half[24] = { + -0.00001461907, -0.00009205479,-0.000056157569,0.00030117269, + 0.0002422519, -0.00085293897,-0.0005205574, 0.0020340169, + 0.00078333891, -0.0042153862, -0.00075614988, 0.0078402944, + -0.000061169922,-0.01344162, 0.0024626821, 0.021736089, + -0.007801671, -0.034090221, 0.01880949, 0.054326009, + -0.043596379, -0.099384367, 0.13207909, 0.46424159 +}; + +/** + * Generate common tables + */ + +void ff_atrac_generate_tables(void) +{ + int i; + float s; + + /* Generate scale factors */ + if (!ff_atrac_sf_table[63]) + for (i=0 ; i<64 ; i++) + ff_atrac_sf_table[i] = pow(2.0, (i - 15) / 3.0); + + /* Generate the QMF window. */ + if (!qmf_window[47]) + for (i=0 ; i<24; i++) { + s = qmf_48tap_half[i] * 2.0; + qmf_window[i] = qmf_window[47 - i] = s; + } +} + + +/** + * Quadrature mirror synthesis filter. + * + * @param inlo lower part of spectrum + * @param inhi higher part of spectrum + * @param nIn size of spectrum buffer + * @param pOut out buffer + * @param delayBuf delayBuf buffer + * @param temp temp buffer + */ + + +void ff_atrac_iqmf (float *inlo, float *inhi, unsigned int nIn, float *pOut, float *delayBuf, float *temp) +{ + int i, j; + float *p1, *p3; + + memcpy(temp, delayBuf, 46*sizeof(float)); + + p3 = temp + 46; + + /* loop1 */ + for(i=0; i +#include +#include + +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "get_bits.h" +#include "fft.h" +#include "internal.h" +#include "sinewin.h" + +#include "atrac.h" +#include "atrac1data.h" + +#define AT1_MAX_BFU 52 ///< max number of block floating units in a sound unit +#define AT1_SU_SIZE 212 ///< number of bytes in a sound unit +#define AT1_SU_SAMPLES 512 ///< number of samples in a sound unit +#define AT1_FRAME_SIZE AT1_SU_SIZE * 2 +#define AT1_SU_MAX_BITS AT1_SU_SIZE * 8 +#define AT1_MAX_CHANNELS 2 + +#define AT1_QMF_BANDS 3 +#define IDX_LOW_BAND 0 +#define IDX_MID_BAND 1 +#define IDX_HIGH_BAND 2 + +/** + * Sound unit struct, one unit is used per channel + */ +typedef struct { + int log2_block_count[AT1_QMF_BANDS]; ///< log2 number of blocks in a band + int num_bfus; ///< number of Block Floating Units + float* spectrum[2]; + DECLARE_ALIGNED(32, float, spec1)[AT1_SU_SAMPLES]; ///< mdct buffer + DECLARE_ALIGNED(32, float, spec2)[AT1_SU_SAMPLES]; ///< mdct buffer + DECLARE_ALIGNED(32, float, fst_qmf_delay)[46]; ///< delay line for the 1st stacked QMF filter + DECLARE_ALIGNED(32, float, snd_qmf_delay)[46]; ///< delay line for the 2nd stacked QMF filter + DECLARE_ALIGNED(32, float, last_qmf_delay)[256+23]; ///< delay line for the last stacked QMF filter +} AT1SUCtx; + +/** + * The atrac1 context, holds all needed parameters for decoding + */ +typedef struct { + AT1SUCtx SUs[AT1_MAX_CHANNELS]; ///< channel sound unit + DECLARE_ALIGNED(32, float, spec)[AT1_SU_SAMPLES]; ///< the mdct spectrum buffer + + DECLARE_ALIGNED(32, float, low)[256]; + DECLARE_ALIGNED(32, float, mid)[256]; + DECLARE_ALIGNED(32, float, high)[512]; + float* bands[3]; + FFTContext mdct_ctx[3]; + AVFloatDSPContext fdsp; +} AT1Ctx; + +/** size of the transform in samples in the long mode for each QMF band */ +static const uint16_t samples_per_band[3] = {128, 128, 256}; +static const uint8_t mdct_long_nbits[3] = {7, 7, 8}; + + +static void at1_imdct(AT1Ctx *q, float *spec, float *out, int nbits, + int rev_spec) +{ + FFTContext* mdct_context = &q->mdct_ctx[nbits - 5 - (nbits > 6)]; + int transf_size = 1 << nbits; + + if (rev_spec) { + int i; + for (i = 0; i < transf_size / 2; i++) + FFSWAP(float, spec[i], spec[transf_size - 1 - i]); + } + mdct_context->imdct_half(mdct_context, out, spec); +} + + +static int at1_imdct_block(AT1SUCtx* su, AT1Ctx *q) +{ + int band_num, band_samples, log2_block_count, nbits, num_blocks, block_size; + unsigned int start_pos, ref_pos = 0, pos = 0; + + for (band_num = 0; band_num < AT1_QMF_BANDS; band_num++) { + float *prev_buf; + int j; + + band_samples = samples_per_band[band_num]; + log2_block_count = su->log2_block_count[band_num]; + + /* number of mdct blocks in the current QMF band: 1 - for long mode */ + /* 4 for short mode(low/middle bands) and 8 for short mode(high band)*/ + num_blocks = 1 << log2_block_count; + + if (num_blocks == 1) { + /* mdct block size in samples: 128 (long mode, low & mid bands), */ + /* 256 (long mode, high band) and 32 (short mode, all bands) */ + block_size = band_samples >> log2_block_count; + + /* calc transform size in bits according to the block_size_mode */ + nbits = mdct_long_nbits[band_num] - log2_block_count; + + if (nbits != 5 && nbits != 7 && nbits != 8) + return AVERROR_INVALIDDATA; + } else { + block_size = 32; + nbits = 5; + } + + start_pos = 0; + prev_buf = &su->spectrum[1][ref_pos + band_samples - 16]; + for (j=0; j < num_blocks; j++) { + at1_imdct(q, &q->spec[pos], &su->spectrum[0][ref_pos + start_pos], nbits, band_num); + + /* overlap and window */ + q->fdsp.vector_fmul_window(&q->bands[band_num][start_pos], prev_buf, + &su->spectrum[0][ref_pos + start_pos], ff_sine_32, 16); + + prev_buf = &su->spectrum[0][ref_pos+start_pos + 16]; + start_pos += block_size; + pos += block_size; + } + + if (num_blocks == 1) + memcpy(q->bands[band_num] + 32, &su->spectrum[0][ref_pos + 16], 240 * sizeof(float)); + + ref_pos += band_samples; + } + + /* Swap buffers so the mdct overlap works */ + FFSWAP(float*, su->spectrum[0], su->spectrum[1]); + + return 0; +} + +/** + * Parse the block size mode byte + */ + +static int at1_parse_bsm(GetBitContext* gb, int log2_block_cnt[AT1_QMF_BANDS]) +{ + int log2_block_count_tmp, i; + + for (i = 0; i < 2; i++) { + /* low and mid band */ + log2_block_count_tmp = get_bits(gb, 2); + if (log2_block_count_tmp & 1) + return AVERROR_INVALIDDATA; + log2_block_cnt[i] = 2 - log2_block_count_tmp; + } + + /* high band */ + log2_block_count_tmp = get_bits(gb, 2); + if (log2_block_count_tmp != 0 && log2_block_count_tmp != 3) + return AVERROR_INVALIDDATA; + log2_block_cnt[IDX_HIGH_BAND] = 3 - log2_block_count_tmp; + + skip_bits(gb, 2); + return 0; +} + + +static int at1_unpack_dequant(GetBitContext* gb, AT1SUCtx* su, + float spec[AT1_SU_SAMPLES]) +{ + int bits_used, band_num, bfu_num, i; + uint8_t idwls[AT1_MAX_BFU]; ///< the word length indexes for each BFU + uint8_t idsfs[AT1_MAX_BFU]; ///< the scalefactor indexes for each BFU + + /* parse the info byte (2nd byte) telling how much BFUs were coded */ + su->num_bfus = bfu_amount_tab1[get_bits(gb, 3)]; + + /* calc number of consumed bits: + num_BFUs * (idwl(4bits) + idsf(6bits)) + log2_block_count(8bits) + info_byte(8bits) + + info_byte_copy(8bits) + log2_block_count_copy(8bits) */ + bits_used = su->num_bfus * 10 + 32 + + bfu_amount_tab2[get_bits(gb, 2)] + + (bfu_amount_tab3[get_bits(gb, 3)] << 1); + + /* get word length index (idwl) for each BFU */ + for (i = 0; i < su->num_bfus; i++) + idwls[i] = get_bits(gb, 4); + + /* get scalefactor index (idsf) for each BFU */ + for (i = 0; i < su->num_bfus; i++) + idsfs[i] = get_bits(gb, 6); + + /* zero idwl/idsf for empty BFUs */ + for (i = su->num_bfus; i < AT1_MAX_BFU; i++) + idwls[i] = idsfs[i] = 0; + + /* read in the spectral data and reconstruct MDCT spectrum of this channel */ + for (band_num = 0; band_num < AT1_QMF_BANDS; band_num++) { + for (bfu_num = bfu_bands_t[band_num]; bfu_num < bfu_bands_t[band_num+1]; bfu_num++) { + int pos; + + int num_specs = specs_per_bfu[bfu_num]; + int word_len = !!idwls[bfu_num] + idwls[bfu_num]; + float scale_factor = ff_atrac_sf_table[idsfs[bfu_num]]; + bits_used += word_len * num_specs; /* add number of bits consumed by current BFU */ + + /* check for bitstream overflow */ + if (bits_used > AT1_SU_MAX_BITS) + return AVERROR_INVALIDDATA; + + /* get the position of the 1st spec according to the block size mode */ + pos = su->log2_block_count[band_num] ? bfu_start_short[bfu_num] : bfu_start_long[bfu_num]; + + if (word_len) { + float max_quant = 1.0 / (float)((1 << (word_len - 1)) - 1); + + for (i = 0; i < num_specs; i++) { + /* read in a quantized spec and convert it to + * signed int and then inverse quantization + */ + spec[pos+i] = get_sbits(gb, word_len) * scale_factor * max_quant; + } + } else { /* word_len = 0 -> empty BFU, zero all specs in the empty BFU */ + memset(&spec[pos], 0, num_specs * sizeof(float)); + } + } + } + + return 0; +} + + +static void at1_subband_synthesis(AT1Ctx *q, AT1SUCtx* su, float *pOut) +{ + float temp[256]; + float iqmf_temp[512 + 46]; + + /* combine low and middle bands */ + ff_atrac_iqmf(q->bands[0], q->bands[1], 128, temp, su->fst_qmf_delay, iqmf_temp); + + /* delay the signal of the high band by 23 samples */ + memcpy( su->last_qmf_delay, &su->last_qmf_delay[256], sizeof(float) * 23); + memcpy(&su->last_qmf_delay[23], q->bands[2], sizeof(float) * 256); + + /* combine (low + middle) and high bands */ + ff_atrac_iqmf(temp, su->last_qmf_delay, 256, pOut, su->snd_qmf_delay, iqmf_temp); +} + + +static int atrac1_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AT1Ctx *q = avctx->priv_data; + int ch, ret; + GetBitContext gb; + + + if (buf_size < 212 * avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Not enough data to decode!\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = AT1_SU_SAMPLES; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (ch = 0; ch < avctx->channels; ch++) { + AT1SUCtx* su = &q->SUs[ch]; + + init_get_bits(&gb, &buf[212 * ch], 212 * 8); + + /* parse block_size_mode, 1st byte */ + ret = at1_parse_bsm(&gb, su->log2_block_count); + if (ret < 0) + return ret; + + ret = at1_unpack_dequant(&gb, su, q->spec); + if (ret < 0) + return ret; + + ret = at1_imdct_block(su, q); + if (ret < 0) + return ret; + at1_subband_synthesis(q, su, (float *)frame->extended_data[ch]); + } + + *got_frame_ptr = 1; + + return avctx->block_align; +} + + +static av_cold int atrac1_decode_end(AVCodecContext * avctx) +{ + AT1Ctx *q = avctx->priv_data; + + ff_mdct_end(&q->mdct_ctx[0]); + ff_mdct_end(&q->mdct_ctx[1]); + ff_mdct_end(&q->mdct_ctx[2]); + + return 0; +} + + +static av_cold int atrac1_decode_init(AVCodecContext *avctx) +{ + AT1Ctx *q = avctx->priv_data; + int ret; + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + if (avctx->channels < 1 || avctx->channels > AT1_MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %d\n", + avctx->channels); + return AVERROR(EINVAL); + } + + if (avctx->block_align <= 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported block align."); + return AVERROR_PATCHWELCOME; + } + + /* Init the mdct transforms */ + if ((ret = ff_mdct_init(&q->mdct_ctx[0], 6, 1, -1.0/ (1 << 15))) || + (ret = ff_mdct_init(&q->mdct_ctx[1], 8, 1, -1.0/ (1 << 15))) || + (ret = ff_mdct_init(&q->mdct_ctx[2], 9, 1, -1.0/ (1 << 15)))) { + av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); + atrac1_decode_end(avctx); + return ret; + } + + ff_init_ff_sine_windows(5); + + ff_atrac_generate_tables(); + + avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + q->bands[0] = q->low; + q->bands[1] = q->mid; + q->bands[2] = q->high; + + /* Prepare the mdct overlap buffers */ + q->SUs[0].spectrum[0] = q->SUs[0].spec1; + q->SUs[0].spectrum[1] = q->SUs[0].spec2; + q->SUs[1].spectrum[0] = q->SUs[1].spec1; + q->SUs[1].spectrum[1] = q->SUs[1].spec2; + + return 0; +} + + +AVCodec ff_atrac1_decoder = { + .name = "atrac1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ATRAC1, + .priv_data_size = sizeof(AT1Ctx), + .init = atrac1_decode_init, + .close = atrac1_decode_end, + .decode = atrac1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Atrac 1 (Adaptive TRansform Acoustic Coding)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/atrac1data.h b/ffmpeg/libavcodec/atrac1data.h new file mode 100644 index 0000000..ebebe4b --- /dev/null +++ b/ffmpeg/libavcodec/atrac1data.h @@ -0,0 +1,64 @@ +/* + * Atrac 1 compatible decoder data + * Copyright (c) 2009 Maxim Poliakovski + * Copyright (c) 2009 Benjamin Larsson + * + * 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 + */ + +/** + * @file + * Atrac 1 compatible decoder data + */ + +#ifndef AVCODEC_ATRAC1DATA_H +#define AVCODEC_ATRAC1DATA_H + +#include + +static const uint8_t bfu_amount_tab1[8] = {20, 28, 32, 36, 40, 44, 48, 52}; +static const uint8_t bfu_amount_tab2[4] = { 0, 112, 176, 208}; +static const uint8_t bfu_amount_tab3[8] = { 0, 24, 36, 48, 72, 108, 132, 156}; + +/** number of BFUs in each QMF band */ +static const uint8_t bfu_bands_t[4] = {0, 20, 36, 52}; + +/** number of spectral lines in each BFU + * block floating unit = group of spectral frequencies having the + * same quantization parameters like word length and scale factor + */ +static const uint8_t specs_per_bfu[52] = { + 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 6, 6, 6, 6, 6, 6, 6, 6, // low band + 6, 6, 6, 6, 7, 7, 7, 7, 9, 9, 9, 9, 10, 10, 10, 10, // midle band + 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20, 20, 20, 20 // high band +}; + +/** start position of each BFU in the MDCT spectrum for the long mode */ +static const uint16_t bfu_start_long[52] = { + 0, 8, 16, 24, 32, 36, 40, 44, 48, 56, 64, 72, 80, 86, 92, 98, 104, 110, 116, 122, + 128, 134, 140, 146, 152, 159, 166, 173, 180, 189, 198, 207, 216, 226, 236, 246, + 256, 268, 280, 292, 304, 316, 328, 340, 352, 372, 392, 412, 432, 452, 472, 492, +}; + +/** start position of each BFU in the MDCT spectrum for the short mode */ +static const uint16_t bfu_start_short[52] = { + 0, 32, 64, 96, 8, 40, 72, 104, 12, 44, 76, 108, 20, 52, 84, 116, 26, 58, 90, 122, + 128, 160, 192, 224, 134, 166, 198, 230, 141, 173, 205, 237, 150, 182, 214, 246, + 256, 288, 320, 352, 384, 416, 448, 480, 268, 300, 332, 364, 396, 428, 460, 492 +}; + +#endif /* AVCODEC_ATRAC1DATA_H */ diff --git a/ffmpeg/libavcodec/atrac3.c b/ffmpeg/libavcodec/atrac3.c new file mode 100644 index 0000000..a9e98f8 --- /dev/null +++ b/ffmpeg/libavcodec/atrac3.c @@ -0,0 +1,1015 @@ +/* + * Atrac 3 compatible decoder + * Copyright (c) 2006-2008 Maxim Poliakovski + * Copyright (c) 2006-2008 Benjamin Larsson + * + * 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 + */ + +/** + * @file + * Atrac 3 compatible decoder. + * This decoder handles Sony's ATRAC3 data. + * + * Container formats used to store atrac 3 data: + * RealMedia (.rm), RIFF WAV (.wav, .at3), Sony OpenMG (.oma, .aa3). + * + * To use this decoder, a calling application must supply the extradata + * bytes provided in the containers above. + */ + +#include +#include +#include + +#include "libavutil/float_dsp.h" +#include "libavutil/libm.h" +#include "avcodec.h" +#include "bytestream.h" +#include "fft.h" +#include "fmtconvert.h" +#include "get_bits.h" +#include "internal.h" + +#include "atrac.h" +#include "atrac3data.h" + +#define JOINT_STEREO 0x12 +#define STEREO 0x2 + +#define SAMPLES_PER_FRAME 1024 +#define MDCT_SIZE 512 + +typedef struct GainInfo { + int num_gain_data; + int lev_code[8]; + int loc_code[8]; +} GainInfo; + +typedef struct GainBlock { + GainInfo g_block[4]; +} GainBlock; + +typedef struct TonalComponent { + int pos; + int num_coefs; + float coef[8]; +} TonalComponent; + +typedef struct ChannelUnit { + int bands_coded; + int num_components; + float prev_frame[SAMPLES_PER_FRAME]; + int gc_blk_switch; + TonalComponent components[64]; + GainBlock gain_block[2]; + + DECLARE_ALIGNED(32, float, spectrum)[SAMPLES_PER_FRAME]; + DECLARE_ALIGNED(32, float, imdct_buf)[SAMPLES_PER_FRAME]; + + float delay_buf1[46]; ///mdct_ctx.imdct_calc(&q->mdct_ctx, output, input); + + /* Perform windowing on the output. */ + q->fdsp.vector_fmul(output, output, mdct_window, MDCT_SIZE); +} + +/* + * indata descrambling, only used for data coming from the rm container + */ +static int decode_bytes(const uint8_t *input, uint8_t *out, int bytes) +{ + int i, off; + uint32_t c; + const uint32_t *buf; + uint32_t *output = (uint32_t *)out; + + off = (intptr_t)input & 3; + buf = (const uint32_t *)(input - off); + if (off) + c = av_be2ne32((0x537F6103U >> (off * 8)) | (0x537F6103U << (32 - (off * 8)))); + else + c = av_be2ne32(0x537F6103U); + bytes += 3 + off; + for (i = 0; i < bytes / 4; i++) + output[i] = c ^ buf[i]; + + if (off) + avpriv_request_sample(NULL, "Offset of %d", off); + + return off; +} + +static av_cold void init_atrac3_window(void) +{ + int i, j; + + /* generate the mdct window, for details see + * http://wiki.multimedia.cx/index.php?title=RealAudio_atrc#Windows */ + for (i = 0, j = 255; i < 128; i++, j--) { + float wi = sin(((i + 0.5) / 256.0 - 0.5) * M_PI) + 1.0; + float wj = sin(((j + 0.5) / 256.0 - 0.5) * M_PI) + 1.0; + float w = 0.5 * (wi * wi + wj * wj); + mdct_window[i] = mdct_window[511 - i] = wi / w; + mdct_window[j] = mdct_window[511 - j] = wj / w; + } +} + +static av_cold int atrac3_decode_close(AVCodecContext *avctx) +{ + ATRAC3Context *q = avctx->priv_data; + + av_free(q->units); + av_free(q->decoded_bytes_buffer); + + ff_mdct_end(&q->mdct_ctx); + + return 0; +} + +/** + * Mantissa decoding + * + * @param selector which table the output values are coded with + * @param coding_flag constant length coding or variable length coding + * @param mantissas mantissa output table + * @param num_codes number of values to get + */ +static void read_quant_spectral_coeffs(GetBitContext *gb, int selector, + int coding_flag, int *mantissas, + int num_codes) +{ + int i, code, huff_symb; + + if (selector == 1) + num_codes /= 2; + + if (coding_flag != 0) { + /* constant length coding (CLC) */ + int num_bits = clc_length_tab[selector]; + + if (selector > 1) { + for (i = 0; i < num_codes; i++) { + if (num_bits) + code = get_sbits(gb, num_bits); + else + code = 0; + mantissas[i] = code; + } + } else { + for (i = 0; i < num_codes; i++) { + if (num_bits) + code = get_bits(gb, num_bits); // num_bits is always 4 in this case + else + code = 0; + mantissas[i * 2 ] = mantissa_clc_tab[code >> 2]; + mantissas[i * 2 + 1] = mantissa_clc_tab[code & 3]; + } + } + } else { + /* variable length coding (VLC) */ + if (selector != 1) { + for (i = 0; i < num_codes; i++) { + huff_symb = get_vlc2(gb, spectral_coeff_tab[selector-1].table, + spectral_coeff_tab[selector-1].bits, 3); + huff_symb += 1; + code = huff_symb >> 1; + if (huff_symb & 1) + code = -code; + mantissas[i] = code; + } + } else { + for (i = 0; i < num_codes; i++) { + huff_symb = get_vlc2(gb, spectral_coeff_tab[selector - 1].table, + spectral_coeff_tab[selector - 1].bits, 3); + mantissas[i * 2 ] = mantissa_vlc_tab[huff_symb * 2 ]; + mantissas[i * 2 + 1] = mantissa_vlc_tab[huff_symb * 2 + 1]; + } + } + } +} + +/** + * Restore the quantized band spectrum coefficients + * + * @return subband count, fix for broken specification/files + */ +static int decode_spectrum(GetBitContext *gb, float *output) +{ + int num_subbands, coding_mode, i, j, first, last, subband_size; + int subband_vlc_index[32], sf_index[32]; + int mantissas[128]; + float scale_factor; + + num_subbands = get_bits(gb, 5); // number of coded subbands + coding_mode = get_bits1(gb); // coding Mode: 0 - VLC/ 1-CLC + + /* get the VLC selector table for the subbands, 0 means not coded */ + for (i = 0; i <= num_subbands; i++) + subband_vlc_index[i] = get_bits(gb, 3); + + /* read the scale factor indexes from the stream */ + for (i = 0; i <= num_subbands; i++) { + if (subband_vlc_index[i] != 0) + sf_index[i] = get_bits(gb, 6); + } + + for (i = 0; i <= num_subbands; i++) { + first = subband_tab[i ]; + last = subband_tab[i + 1]; + + subband_size = last - first; + + if (subband_vlc_index[i] != 0) { + /* decode spectral coefficients for this subband */ + /* TODO: This can be done faster is several blocks share the + * same VLC selector (subband_vlc_index) */ + read_quant_spectral_coeffs(gb, subband_vlc_index[i], coding_mode, + mantissas, subband_size); + + /* decode the scale factor for this subband */ + scale_factor = ff_atrac_sf_table[sf_index[i]] * + inv_max_quant[subband_vlc_index[i]]; + + /* inverse quantize the coefficients */ + for (j = 0; first < last; first++, j++) + output[first] = mantissas[j] * scale_factor; + } else { + /* this subband was not coded, so zero the entire subband */ + memset(output + first, 0, subband_size * sizeof(*output)); + } + } + + /* clear the subbands that were not coded */ + first = subband_tab[i]; + memset(output + first, 0, (SAMPLES_PER_FRAME - first) * sizeof(*output)); + return num_subbands; +} + +/** + * Restore the quantized tonal components + * + * @param components tonal components + * @param num_bands number of coded bands + */ +static int decode_tonal_components(GetBitContext *gb, + TonalComponent *components, int num_bands) +{ + int i, b, c, m; + int nb_components, coding_mode_selector, coding_mode; + int band_flags[4], mantissa[8]; + int component_count = 0; + + nb_components = get_bits(gb, 5); + + /* no tonal components */ + if (nb_components == 0) + return 0; + + coding_mode_selector = get_bits(gb, 2); + if (coding_mode_selector == 2) + return AVERROR_INVALIDDATA; + + coding_mode = coding_mode_selector & 1; + + for (i = 0; i < nb_components; i++) { + int coded_values_per_component, quant_step_index; + + for (b = 0; b <= num_bands; b++) + band_flags[b] = get_bits1(gb); + + coded_values_per_component = get_bits(gb, 3); + + quant_step_index = get_bits(gb, 3); + if (quant_step_index <= 1) + return AVERROR_INVALIDDATA; + + if (coding_mode_selector == 3) + coding_mode = get_bits1(gb); + + for (b = 0; b < (num_bands + 1) * 4; b++) { + int coded_components; + + if (band_flags[b >> 2] == 0) + continue; + + coded_components = get_bits(gb, 3); + + for (c = 0; c < coded_components; c++) { + TonalComponent *cmp = &components[component_count]; + int sf_index, coded_values, max_coded_values; + float scale_factor; + + sf_index = get_bits(gb, 6); + if (component_count >= 64) + return AVERROR_INVALIDDATA; + + cmp->pos = b * 64 + get_bits(gb, 6); + + max_coded_values = SAMPLES_PER_FRAME - cmp->pos; + coded_values = coded_values_per_component + 1; + coded_values = FFMIN(max_coded_values, coded_values); + + scale_factor = ff_atrac_sf_table[sf_index] * + inv_max_quant[quant_step_index]; + + read_quant_spectral_coeffs(gb, quant_step_index, coding_mode, + mantissa, coded_values); + + cmp->num_coefs = coded_values; + + /* inverse quant */ + for (m = 0; m < coded_values; m++) + cmp->coef[m] = mantissa[m] * scale_factor; + + component_count++; + } + } + } + + return component_count; +} + +/** + * Decode gain parameters for the coded bands + * + * @param block the gainblock for the current band + * @param num_bands amount of coded bands + */ +static int decode_gain_control(GetBitContext *gb, GainBlock *block, + int num_bands) +{ + int i, cf, num_data; + int *level, *loc; + + GainInfo *gain = block->g_block; + + for (i = 0; i <= num_bands; i++) { + num_data = get_bits(gb, 3); + gain[i].num_gain_data = num_data; + level = gain[i].lev_code; + loc = gain[i].loc_code; + + for (cf = 0; cf < gain[i].num_gain_data; cf++) { + level[cf] = get_bits(gb, 4); + loc [cf] = get_bits(gb, 5); + if (cf && loc[cf] <= loc[cf - 1]) + return AVERROR_INVALIDDATA; + } + } + + /* Clear the unused blocks. */ + for (; i < 4 ; i++) + gain[i].num_gain_data = 0; + + return 0; +} + +/** + * Apply gain parameters and perform the MDCT overlapping part + * + * @param input input buffer + * @param prev previous buffer to perform overlap against + * @param output output buffer + * @param gain1 current band gain info + * @param gain2 next band gain info + */ +static void gain_compensate_and_overlap(float *input, float *prev, + float *output, GainInfo *gain1, + GainInfo *gain2) +{ + float g1, g2, gain_inc; + int i, j, num_data, start_loc, end_loc; + + + if (gain2->num_gain_data == 0) + g1 = 1.0; + else + g1 = gain_tab1[gain2->lev_code[0]]; + + if (gain1->num_gain_data == 0) { + for (i = 0; i < 256; i++) + output[i] = input[i] * g1 + prev[i]; + } else { + num_data = gain1->num_gain_data; + gain1->loc_code[num_data] = 32; + gain1->lev_code[num_data] = 4; + + for (i = 0, j = 0; i < num_data; i++) { + start_loc = gain1->loc_code[i] * 8; + end_loc = start_loc + 8; + + g2 = gain_tab1[gain1->lev_code[i]]; + gain_inc = gain_tab2[gain1->lev_code[i + 1] - + gain1->lev_code[i ] + 15]; + + /* interpolate */ + for (; j < start_loc; j++) + output[j] = (input[j] * g1 + prev[j]) * g2; + + /* interpolation is done over eight samples */ + for (; j < end_loc; j++) { + output[j] = (input[j] * g1 + prev[j]) * g2; + g2 *= gain_inc; + } + } + + for (; j < 256; j++) + output[j] = input[j] * g1 + prev[j]; + } + + /* Delay for the overlapping part. */ + memcpy(prev, &input[256], 256 * sizeof(*prev)); +} + +/** + * Combine the tonal band spectrum and regular band spectrum + * + * @param spectrum output spectrum buffer + * @param num_components number of tonal components + * @param components tonal components for this band + * @return position of the last tonal coefficient + */ +static int add_tonal_components(float *spectrum, int num_components, + TonalComponent *components) +{ + int i, j, last_pos = -1; + float *input, *output; + + for (i = 0; i < num_components; i++) { + last_pos = FFMAX(components[i].pos + components[i].num_coefs, last_pos); + input = components[i].coef; + output = &spectrum[components[i].pos]; + + for (j = 0; j < components[i].num_coefs; j++) + output[j] += input[j]; + } + + return last_pos; +} + +#define INTERPOLATE(old, new, nsample) \ + ((old) + (nsample) * 0.125 * ((new) - (old))) + +static void reverse_matrixing(float *su1, float *su2, int *prev_code, + int *curr_code) +{ + int i, nsample, band; + float mc1_l, mc1_r, mc2_l, mc2_r; + + for (i = 0, band = 0; band < 4 * 256; band += 256, i++) { + int s1 = prev_code[i]; + int s2 = curr_code[i]; + nsample = band; + + if (s1 != s2) { + /* Selector value changed, interpolation needed. */ + mc1_l = matrix_coeffs[s1 * 2 ]; + mc1_r = matrix_coeffs[s1 * 2 + 1]; + mc2_l = matrix_coeffs[s2 * 2 ]; + mc2_r = matrix_coeffs[s2 * 2 + 1]; + + /* Interpolation is done over the first eight samples. */ + for (; nsample < band + 8; nsample++) { + float c1 = su1[nsample]; + float c2 = su2[nsample]; + c2 = c1 * INTERPOLATE(mc1_l, mc2_l, nsample - band) + + c2 * INTERPOLATE(mc1_r, mc2_r, nsample - band); + su1[nsample] = c2; + su2[nsample] = c1 * 2.0 - c2; + } + } + + /* Apply the matrix without interpolation. */ + switch (s2) { + case 0: /* M/S decoding */ + for (; nsample < band + 256; nsample++) { + float c1 = su1[nsample]; + float c2 = su2[nsample]; + su1[nsample] = c2 * 2.0; + su2[nsample] = (c1 - c2) * 2.0; + } + break; + case 1: + for (; nsample < band + 256; nsample++) { + float c1 = su1[nsample]; + float c2 = su2[nsample]; + su1[nsample] = (c1 + c2) * 2.0; + su2[nsample] = c2 * -2.0; + } + break; + case 2: + case 3: + for (; nsample < band + 256; nsample++) { + float c1 = su1[nsample]; + float c2 = su2[nsample]; + su1[nsample] = c1 + c2; + su2[nsample] = c1 - c2; + } + break; + default: + av_assert1(0); + } + } +} + +static void get_channel_weights(int index, int flag, float ch[2]) +{ + if (index == 7) { + ch[0] = 1.0; + ch[1] = 1.0; + } else { + ch[0] = (index & 7) / 7.0; + ch[1] = sqrt(2 - ch[0] * ch[0]); + if (flag) + FFSWAP(float, ch[0], ch[1]); + } +} + +static void channel_weighting(float *su1, float *su2, int *p3) +{ + int band, nsample; + /* w[x][y] y=0 is left y=1 is right */ + float w[2][2]; + + if (p3[1] != 7 || p3[3] != 7) { + get_channel_weights(p3[1], p3[0], w[0]); + get_channel_weights(p3[3], p3[2], w[1]); + + for (band = 256; band < 4 * 256; band += 256) { + for (nsample = band; nsample < band + 8; nsample++) { + su1[nsample] *= INTERPOLATE(w[0][0], w[0][1], nsample - band); + su2[nsample] *= INTERPOLATE(w[1][0], w[1][1], nsample - band); + } + for(; nsample < band + 256; nsample++) { + su1[nsample] *= w[1][0]; + su2[nsample] *= w[1][1]; + } + } + } +} + +/** + * Decode a Sound Unit + * + * @param snd the channel unit to be used + * @param output the decoded samples before IQMF in float representation + * @param channel_num channel number + * @param coding_mode the coding mode (JOINT_STEREO or regular stereo/mono) + */ +static int decode_channel_sound_unit(ATRAC3Context *q, GetBitContext *gb, + ChannelUnit *snd, float *output, + int channel_num, int coding_mode) +{ + int band, ret, num_subbands, last_tonal, num_bands; + GainBlock *gain1 = &snd->gain_block[ snd->gc_blk_switch]; + GainBlock *gain2 = &snd->gain_block[1 - snd->gc_blk_switch]; + + if (coding_mode == JOINT_STEREO && channel_num == 1) { + if (get_bits(gb, 2) != 3) { + av_log(NULL,AV_LOG_ERROR,"JS mono Sound Unit id != 3.\n"); + return AVERROR_INVALIDDATA; + } + } else { + if (get_bits(gb, 6) != 0x28) { + av_log(NULL,AV_LOG_ERROR,"Sound Unit id != 0x28.\n"); + return AVERROR_INVALIDDATA; + } + } + + /* number of coded QMF bands */ + snd->bands_coded = get_bits(gb, 2); + + ret = decode_gain_control(gb, gain2, snd->bands_coded); + if (ret) + return ret; + + snd->num_components = decode_tonal_components(gb, snd->components, + snd->bands_coded); + if (snd->num_components == -1) + return -1; + + num_subbands = decode_spectrum(gb, snd->spectrum); + + /* Merge the decoded spectrum and tonal components. */ + last_tonal = add_tonal_components(snd->spectrum, snd->num_components, + snd->components); + + + /* calculate number of used MLT/QMF bands according to the amount of coded + spectral lines */ + num_bands = (subband_tab[num_subbands] - 1) >> 8; + if (last_tonal >= 0) + num_bands = FFMAX((last_tonal + 256) >> 8, num_bands); + + + /* Reconstruct time domain samples. */ + for (band = 0; band < 4; band++) { + /* Perform the IMDCT step without overlapping. */ + if (band <= num_bands) + imlt(q, &snd->spectrum[band * 256], snd->imdct_buf, band & 1); + else + memset(snd->imdct_buf, 0, 512 * sizeof(*snd->imdct_buf)); + + /* gain compensation and overlapping */ + gain_compensate_and_overlap(snd->imdct_buf, + &snd->prev_frame[band * 256], + &output[band * 256], + &gain1->g_block[band], + &gain2->g_block[band]); + } + + /* Swap the gain control buffers for the next frame. */ + snd->gc_blk_switch ^= 1; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf, + float **out_samples) +{ + ATRAC3Context *q = avctx->priv_data; + int ret, i; + uint8_t *ptr1; + + if (q->coding_mode == JOINT_STEREO) { + /* channel coupling mode */ + /* decode Sound Unit 1 */ + init_get_bits(&q->gb, databuf, avctx->block_align * 8); + + ret = decode_channel_sound_unit(q, &q->gb, q->units, out_samples[0], 0, + JOINT_STEREO); + if (ret != 0) + return ret; + + /* Framedata of the su2 in the joint-stereo mode is encoded in + * reverse byte order so we need to swap it first. */ + if (databuf == q->decoded_bytes_buffer) { + uint8_t *ptr2 = q->decoded_bytes_buffer + avctx->block_align - 1; + ptr1 = q->decoded_bytes_buffer; + for (i = 0; i < avctx->block_align / 2; i++, ptr1++, ptr2--) + FFSWAP(uint8_t, *ptr1, *ptr2); + } else { + const uint8_t *ptr2 = databuf + avctx->block_align - 1; + for (i = 0; i < avctx->block_align; i++) + q->decoded_bytes_buffer[i] = *ptr2--; + } + + /* Skip the sync codes (0xF8). */ + ptr1 = q->decoded_bytes_buffer; + for (i = 4; *ptr1 == 0xF8; i++, ptr1++) { + if (i >= avctx->block_align) + return AVERROR_INVALIDDATA; + } + + + /* set the bitstream reader at the start of the second Sound Unit*/ + init_get_bits8(&q->gb, ptr1, q->decoded_bytes_buffer + avctx->block_align - ptr1); + + /* Fill the Weighting coeffs delay buffer */ + memmove(q->weighting_delay, &q->weighting_delay[2], + 4 * sizeof(*q->weighting_delay)); + q->weighting_delay[4] = get_bits1(&q->gb); + q->weighting_delay[5] = get_bits(&q->gb, 3); + + for (i = 0; i < 4; i++) { + q->matrix_coeff_index_prev[i] = q->matrix_coeff_index_now[i]; + q->matrix_coeff_index_now[i] = q->matrix_coeff_index_next[i]; + q->matrix_coeff_index_next[i] = get_bits(&q->gb, 2); + } + + /* Decode Sound Unit 2. */ + ret = decode_channel_sound_unit(q, &q->gb, &q->units[1], + out_samples[1], 1, JOINT_STEREO); + if (ret != 0) + return ret; + + /* Reconstruct the channel coefficients. */ + reverse_matrixing(out_samples[0], out_samples[1], + q->matrix_coeff_index_prev, + q->matrix_coeff_index_now); + + channel_weighting(out_samples[0], out_samples[1], q->weighting_delay); + } else { + /* normal stereo mode or mono */ + /* Decode the channel sound units. */ + for (i = 0; i < avctx->channels; i++) { + /* Set the bitstream reader at the start of a channel sound unit. */ + init_get_bits(&q->gb, + databuf + i * avctx->block_align / avctx->channels, + avctx->block_align * 8 / avctx->channels); + + ret = decode_channel_sound_unit(q, &q->gb, &q->units[i], + out_samples[i], i, q->coding_mode); + if (ret != 0) + return ret; + } + } + + /* Apply the iQMF synthesis filter. */ + for (i = 0; i < avctx->channels; i++) { + float *p1 = out_samples[i]; + float *p2 = p1 + 256; + float *p3 = p2 + 256; + float *p4 = p3 + 256; + ff_atrac_iqmf(p1, p2, 256, p1, q->units[i].delay_buf1, q->temp_buf); + ff_atrac_iqmf(p4, p3, 256, p3, q->units[i].delay_buf2, q->temp_buf); + ff_atrac_iqmf(p1, p3, 512, p1, q->units[i].delay_buf3, q->temp_buf); + } + + return 0; +} + +static int atrac3_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ATRAC3Context *q = avctx->priv_data; + int ret; + const uint8_t *databuf; + + if (buf_size < avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, + "Frame too small (%d bytes). Truncated file?\n", buf_size); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = SAMPLES_PER_FRAME; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + /* Check if we need to descramble and what buffer to pass on. */ + if (q->scrambled_stream) { + decode_bytes(buf, q->decoded_bytes_buffer, avctx->block_align); + databuf = q->decoded_bytes_buffer; + } else { + databuf = buf; + } + + ret = decode_frame(avctx, databuf, (float **)frame->extended_data); + if (ret) { + av_log(NULL, AV_LOG_ERROR, "Frame decoding error!\n"); + return ret; + } + + *got_frame_ptr = 1; + + return avctx->block_align; +} + +static void atrac3_init_static_data(void) +{ + int i; + + init_atrac3_window(); + ff_atrac_generate_tables(); + + /* Initialize the VLC tables. */ + for (i = 0; i < 7; i++) { + spectral_coeff_tab[i].table = &atrac3_vlc_table[atrac3_vlc_offs[i]]; + spectral_coeff_tab[i].table_allocated = atrac3_vlc_offs[i + 1] - + atrac3_vlc_offs[i ]; + init_vlc(&spectral_coeff_tab[i], 9, huff_tab_sizes[i], + huff_bits[i], 1, 1, + huff_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + + /* Generate gain tables */ + for (i = 0; i < 16; i++) + gain_tab1[i] = exp2f (4 - i); + + for (i = -15; i < 16; i++) + gain_tab2[i + 15] = exp2f (i * -0.125); +} + +static av_cold int atrac3_decode_init(AVCodecContext *avctx) +{ + static int static_init_done; + int i, ret; + int version, delay, samples_per_frame, frame_factor; + const uint8_t *edata_ptr = avctx->extradata; + ATRAC3Context *q = avctx->priv_data; + + if (avctx->channels <= 0 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Channel configuration error!\n"); + return AVERROR(EINVAL); + } + + if (!static_init_done) + atrac3_init_static_data(); + static_init_done = 1; + + /* Take care of the codec-specific extradata. */ + if (avctx->extradata_size == 14) { + /* Parse the extradata, WAV format */ + av_log(avctx, AV_LOG_DEBUG, "[0-1] %d\n", + bytestream_get_le16(&edata_ptr)); // Unknown value always 1 + edata_ptr += 4; // samples per channel + q->coding_mode = bytestream_get_le16(&edata_ptr); + av_log(avctx, AV_LOG_DEBUG,"[8-9] %d\n", + bytestream_get_le16(&edata_ptr)); //Dupe of coding mode + frame_factor = bytestream_get_le16(&edata_ptr); // Unknown always 1 + av_log(avctx, AV_LOG_DEBUG,"[12-13] %d\n", + bytestream_get_le16(&edata_ptr)); // Unknown always 0 + + /* setup */ + samples_per_frame = SAMPLES_PER_FRAME * avctx->channels; + version = 4; + delay = 0x88E; + q->coding_mode = q->coding_mode ? JOINT_STEREO : STEREO; + q->scrambled_stream = 0; + + if (avctx->block_align != 96 * avctx->channels * frame_factor && + avctx->block_align != 152 * avctx->channels * frame_factor && + avctx->block_align != 192 * avctx->channels * frame_factor) { + av_log(avctx, AV_LOG_ERROR, "Unknown frame/channel/frame_factor " + "configuration %d/%d/%d\n", avctx->block_align, + avctx->channels, frame_factor); + return AVERROR_INVALIDDATA; + } + } else if (avctx->extradata_size == 12 || avctx->extradata_size == 10) { + /* Parse the extradata, RM format. */ + version = bytestream_get_be32(&edata_ptr); + samples_per_frame = bytestream_get_be16(&edata_ptr); + delay = bytestream_get_be16(&edata_ptr); + q->coding_mode = bytestream_get_be16(&edata_ptr); + q->scrambled_stream = 1; + + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown extradata size %d.\n", + avctx->extradata_size); + return AVERROR(EINVAL); + } + + if (q->coding_mode == JOINT_STEREO && avctx->channels < 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid coding mode\n"); + return AVERROR_INVALIDDATA; + } + + /* Check the extradata */ + + if (version != 4) { + av_log(avctx, AV_LOG_ERROR, "Version %d != 4.\n", version); + return AVERROR_INVALIDDATA; + } + + if (samples_per_frame != SAMPLES_PER_FRAME && + samples_per_frame != SAMPLES_PER_FRAME * 2) { + av_log(avctx, AV_LOG_ERROR, "Unknown amount of samples per frame %d.\n", + samples_per_frame); + return AVERROR_INVALIDDATA; + } + + if (delay != 0x88E) { + av_log(avctx, AV_LOG_ERROR, "Unknown amount of delay %x != 0x88E.\n", + delay); + return AVERROR_INVALIDDATA; + } + + if (q->coding_mode == STEREO) + av_log(avctx, AV_LOG_DEBUG, "Normal stereo detected.\n"); + else if (q->coding_mode == JOINT_STEREO) + av_log(avctx, AV_LOG_DEBUG, "Joint stereo detected.\n"); + else { + av_log(avctx, AV_LOG_ERROR, "Unknown channel coding mode %x!\n", + q->coding_mode); + return AVERROR_INVALIDDATA; + } + + if (avctx->block_align >= UINT_MAX / 2) + return AVERROR(EINVAL); + + q->decoded_bytes_buffer = av_mallocz(FFALIGN(avctx->block_align, 4) + + FF_INPUT_BUFFER_PADDING_SIZE); + if (q->decoded_bytes_buffer == NULL) + return AVERROR(ENOMEM); + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + /* initialize the MDCT transform */ + if ((ret = ff_mdct_init(&q->mdct_ctx, 9, 1, 1.0 / 32768)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); + av_freep(&q->decoded_bytes_buffer); + return ret; + } + + /* init the joint-stereo decoding data */ + q->weighting_delay[0] = 0; + q->weighting_delay[1] = 7; + q->weighting_delay[2] = 0; + q->weighting_delay[3] = 7; + q->weighting_delay[4] = 0; + q->weighting_delay[5] = 7; + + for (i = 0; i < 4; i++) { + q->matrix_coeff_index_prev[i] = 3; + q->matrix_coeff_index_now[i] = 3; + q->matrix_coeff_index_next[i] = 3; + } + + avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_fmt_convert_init(&q->fmt_conv, avctx); + + q->units = av_mallocz(sizeof(*q->units) * avctx->channels); + if (!q->units) { + atrac3_decode_close(avctx); + return AVERROR(ENOMEM); + } + + return 0; +} + +AVCodec ff_atrac3_decoder = { + .name = "atrac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ATRAC3, + .priv_data_size = sizeof(ATRAC3Context), + .init = atrac3_decode_init, + .close = atrac3_decode_close, + .decode = atrac3_decode_frame, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Atrac 3 (Adaptive TRansform Acoustic Coding 3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/atrac3data.h b/ffmpeg/libavcodec/atrac3data.h new file mode 100644 index 0000000..9963d4e --- /dev/null +++ b/ffmpeg/libavcodec/atrac3data.h @@ -0,0 +1,141 @@ +/* + * Atrac 3 compatible decoder data + * Copyright (c) 2006-2007 Maxim Poliakovski + * Copyright (c) 2006-2007 Benjamin Larsson + * + * 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 + */ + +/** + * @file + * Atrac 3 AKA RealAudio 8 compatible decoder data + */ + +#ifndef AVCODEC_ATRAC3DATA_H +#define AVCODEC_ATRAC3DATA_H + +#include + +/* VLC tables */ + +static const uint8_t huffcode1[9] = { + 0x0, 0x4, 0x5, 0xC, 0xD, 0x1C, 0x1D, 0x1E, 0x1F +}; + +static const uint8_t huffbits1[9] = { 1, 3, 3, 4, 4, 5, 5, 5, 5 }; + +static const uint8_t huffcode2[5] = { 0x0, 0x4, 0x5, 0x6, 0x7 }; + +static const uint8_t huffbits2[5] = { 1, 3, 3, 3, 3 }; + +static const uint8_t huffcode3[7] = { 0x0, 0x4, 0x5, 0xC, 0xD, 0xE, 0xF }; + +static const uint8_t huffbits3[7] = { 1, 3, 3, 4, 4, 4, 4 }; + +static const uint8_t huffcode4[9] = { + 0x0, 0x4, 0x5, 0xC, 0xD, 0x1C, 0x1D, 0x1E, 0x1F +}; + +static const uint8_t huffbits4[9] = { 1, 3, 3, 4, 4, 5, 5, 5, 5 }; + +static const uint8_t huffcode5[15] = { + 0x00, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x1C, + 0x1D, 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x0D +}; + +static const uint8_t huffbits5[15] = { + 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 4, 4 +}; + +static const uint8_t huffcode6[31] = { + 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x78, 0x79, 0x7A, + 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x08, 0x09 +}; + +static const uint8_t huffbits6[31] = { + 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4 +}; + +static const uint8_t huffcode7[63] = { + 0x00, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x68, 0x69, 0x6A, 0x6B, 0x6C, + 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, + 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, + 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x02, 0x03 +}; + +static const uint8_t huffbits7[63] = { + 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4 +}; + +static const uint8_t huff_tab_sizes[7] = { + 9, 5, 7, 9, 15, 31, 63, +}; + +static const uint8_t* const huff_codes[7] = { + huffcode1, huffcode2, huffcode3, huffcode4, huffcode5, huffcode6, huffcode7 +}; + +static const uint8_t* const huff_bits[7] = { + huffbits1, huffbits2, huffbits3, huffbits4, huffbits5, huffbits6, huffbits7, +}; + +static const uint16_t atrac3_vlc_offs[9] = { + 0, 512, 1024, 1536, 2048, 2560, 3072, 3584, 4096 +}; + +/* selector tables */ + +static const uint8_t clc_length_tab[8] = { 0, 4, 3, 3, 4, 4, 5, 6 }; + +static const int8_t mantissa_clc_tab[4] = { 0, 1, -2, -1 }; + +static const int8_t mantissa_vlc_tab[18] = { + 0, 0, 0, 1, 0, -1, 1, 0, -1, 0, 1, 1, 1, -1, -1, 1, -1, -1 +}; + + +/* tables for the scalefactor decoding */ + +static const float inv_max_quant[8] = { + 0.0, 1.0 / 1.5, 1.0 / 2.5, 1.0 / 3.5, + 1.0 / 4.5, 1.0 / 7.5, 1.0 / 15.5, 1.0 / 31.5 +}; + +static const uint16_t subband_tab[33] = { + 0, 8, 16, 24, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 144, 160, 176, + 192, 224, 256, 288, 320, 352, 384, 416, + 448, 480, 512, 576, 640, 704, 768, 896, + 1024 +}; + +/* joint stereo related tables */ +static const float matrix_coeffs[8] = { + 0.0, 2.0, 2.0, 2.0, 0.0, 0.0, 1.0, 1.0 +}; + +#endif /* AVCODEC_ATRAC3DATA_H */ diff --git a/ffmpeg/libavcodec/audio_frame_queue.c b/ffmpeg/libavcodec/audio_frame_queue.c new file mode 100644 index 0000000..ba6e225 --- /dev/null +++ b/ffmpeg/libavcodec/audio_frame_queue.c @@ -0,0 +1,112 @@ +/* + * Audio Frame Queue + * Copyright (c) 2012 Justin Ruggles + * + * 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 "libavutil/common.h" +#include "audio_frame_queue.h" +#include "internal.h" +#include "libavutil/avassert.h" + +void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq) +{ + afq->avctx = avctx; + afq->remaining_delay = avctx->delay; + afq->remaining_samples = avctx->delay; + afq->frame_count = 0; +} + +void ff_af_queue_close(AudioFrameQueue *afq) +{ + if(afq->frame_count) + av_log(afq->avctx, AV_LOG_WARNING, "%d frames left in the queue on closing\n", afq->frame_count); + av_freep(&afq->frames); + memset(afq, 0, sizeof(*afq)); +} + +int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f) +{ + AudioFrame *new = av_fast_realloc(afq->frames, &afq->frame_alloc, sizeof(*afq->frames)*(afq->frame_count+1)); + if(!new) + return AVERROR(ENOMEM); + afq->frames = new; + new += afq->frame_count; + + /* get frame parameters */ + new->duration = f->nb_samples; + new->duration += afq->remaining_delay; + if (f->pts != AV_NOPTS_VALUE) { + new->pts = av_rescale_q(f->pts, + afq->avctx->time_base, + (AVRational){ 1, afq->avctx->sample_rate }); + new->pts -= afq->remaining_delay; + if(afq->frame_count && new[-1].pts >= new->pts) + av_log(afq->avctx, AV_LOG_WARNING, "Queue input is backward in time\n"); + } else { + new->pts = AV_NOPTS_VALUE; + } + afq->remaining_delay = 0; + + /* add frame sample count */ + afq->remaining_samples += f->nb_samples; + + afq->frame_count++; + + return 0; +} + +void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, + int *duration) +{ + int64_t out_pts = AV_NOPTS_VALUE; + int removed_samples = 0; + int i; + + if (afq->frame_count || afq->frame_alloc) { + if (afq->frames->pts != AV_NOPTS_VALUE) + out_pts = afq->frames->pts; + } + if(!afq->frame_count) + av_log(afq->avctx, AV_LOG_WARNING, "Trying to remove %d samples, but the queue is empty\n", nb_samples); + if (pts) + *pts = ff_samples_to_time_base(afq->avctx, out_pts); + + for(i=0; nb_samples && iframe_count; i++){ + int n= FFMIN(afq->frames[i].duration, nb_samples); + afq->frames[i].duration -= n; + nb_samples -= n; + removed_samples += n; + if(afq->frames[i].pts != AV_NOPTS_VALUE) + afq->frames[i].pts += n; + } + afq->remaining_samples -= removed_samples; + i -= i && afq->frames[i-1].duration; + memmove(afq->frames, afq->frames + i, sizeof(*afq->frames) * (afq->frame_count - i)); + afq->frame_count -= i; + + if(nb_samples){ + av_assert0(!afq->frame_count); + av_assert0(afq->remaining_samples == afq->remaining_delay); + if(afq->frames && afq->frames[0].pts != AV_NOPTS_VALUE) + afq->frames[0].pts += nb_samples; + av_log(afq->avctx, AV_LOG_DEBUG, "Trying to remove %d more samples than there are in the queue\n", nb_samples); + } + if (duration) + *duration = ff_samples_to_time_base(afq->avctx, removed_samples); +} diff --git a/ffmpeg/libavcodec/audio_frame_queue.h b/ffmpeg/libavcodec/audio_frame_queue.h new file mode 100644 index 0000000..7e98afe --- /dev/null +++ b/ffmpeg/libavcodec/audio_frame_queue.h @@ -0,0 +1,83 @@ +/* + * Audio Frame Queue + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_AUDIO_FRAME_QUEUE_H +#define AVCODEC_AUDIO_FRAME_QUEUE_H + +#include "avcodec.h" + +typedef struct AudioFrame { + int64_t pts; + int duration; +} AudioFrame; + +typedef struct AudioFrameQueue { + AVCodecContext *avctx; + int remaining_delay; + int remaining_samples; + AudioFrame *frames; + unsigned frame_count; + unsigned frame_alloc; +} AudioFrameQueue; + +/** + * Initialize AudioFrameQueue. + * + * @param avctx context to use for time_base and av_log + * @param afq queue context + */ +void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq); + +/** + * Close AudioFrameQueue. + * + * Frees memory if needed. + * + * @param afq queue context + */ +void ff_af_queue_close(AudioFrameQueue *afq); + +/** + * Add a frame to the queue. + * + * @param afq queue context + * @param f frame to add to the queue + */ +int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f); + +/** + * Remove frame(s) from the queue. + * + * Retrieves the pts of the next available frame, or a generated pts based on + * the last frame duration if there are no frames left in the queue. The number + * of requested samples should be the full number of samples represented by the + * packet that will be output by the encoder. If fewer samples are available + * in the queue, a smaller value will be used for the output duration. + * + * @param afq queue context + * @param nb_samples number of samples to remove from the queue + * @param[out] pts output packet pts + * @param[out] duration output packet duration + */ +void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts, + int *duration); + +#endif /* AVCODEC_AUDIO_FRAME_QUEUE_H */ diff --git a/ffmpeg/libavcodec/audioconvert.c b/ffmpeg/libavcodec/audioconvert.c new file mode 100644 index 0000000..5d8a348 --- /dev/null +++ b/ffmpeg/libavcodec/audioconvert.c @@ -0,0 +1,116 @@ +/* + * audio conversion + * Copyright (c) 2006 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 + */ + +/** + * @file + * audio conversion + * @author Michael Niedermayer + */ + +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/libm.h" +#include "libavutil/samplefmt.h" +#include "avcodec.h" +#include "audioconvert.h" + +struct AVAudioConvert { + int in_channels, out_channels; + int fmt_pair; +}; + +AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels, + enum AVSampleFormat in_fmt, int in_channels, + const float *matrix, int flags) +{ + AVAudioConvert *ctx; + if (in_channels!=out_channels) + return NULL; /* FIXME: not supported */ + ctx = av_malloc(sizeof(AVAudioConvert)); + if (!ctx) + return NULL; + ctx->in_channels = in_channels; + ctx->out_channels = out_channels; + ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt; + return ctx; +} + +void av_audio_convert_free(AVAudioConvert *ctx) +{ + av_free(ctx); +} + +int av_audio_convert(AVAudioConvert *ctx, + void * const out[6], const int out_stride[6], + const void * const in[6], const int in_stride[6], int len) +{ + int ch; + + //FIXME optimize common cases + + for(ch=0; chout_channels; ch++){ + const int is= in_stride[ch]; + const int os= out_stride[ch]; + const uint8_t *pi= in[ch]; + uint8_t *po= out[ch]; + uint8_t *end= po + os*len; + if(!out[ch]) + continue; + +#define CONV(ofmt, otype, ifmt, expr)\ +if(ctx->fmt_pair == ofmt + AV_SAMPLE_FMT_NB*ifmt){\ + do{\ + *(otype*)po = expr; pi += is; po += os;\ + }while(po < end);\ +} + +//FIXME put things below under ifdefs so we do not waste space for cases no codec will need +//FIXME rounding ? + + CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_U8 , *(const uint8_t*)pi) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7))) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi<<16) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15))) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi>>16) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31))) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31))) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80)) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15)))) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31)))) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_FLT, *(const float*)pi) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi) + else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80)) + else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15)))) + else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31)))) + else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi) + else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi) + else return -1; + } + return 0; +} diff --git a/ffmpeg/libavcodec/audioconvert.h b/ffmpeg/libavcodec/audioconvert.h new file mode 100644 index 0000000..61124b3 --- /dev/null +++ b/ffmpeg/libavcodec/audioconvert.h @@ -0,0 +1,70 @@ +/* + * audio conversion + * Copyright (c) 2006 Michael Niedermayer + * Copyright (c) 2008 Peter Ross + * + * 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 + */ + +#ifndef AVCODEC_AUDIOCONVERT_H +#define AVCODEC_AUDIOCONVERT_H + +/** + * @file + * Audio format conversion routines + */ + + +#include "libavutil/cpu.h" +#include "avcodec.h" +#include "libavutil/channel_layout.h" + +struct AVAudioConvert; +typedef struct AVAudioConvert AVAudioConvert; + +/** + * Create an audio sample format converter context + * @param out_fmt Output sample format + * @param out_channels Number of output channels + * @param in_fmt Input sample format + * @param in_channels Number of input channels + * @param[in] matrix Channel mixing matrix (of dimension in_channel*out_channels). Set to NULL to ignore. + * @param flags See AV_CPU_FLAG_xx + * @return NULL on error + */ +AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels, + enum AVSampleFormat in_fmt, int in_channels, + const float *matrix, int flags); + +/** + * Free audio sample format converter context + */ +void av_audio_convert_free(AVAudioConvert *ctx); + +/** + * Convert between audio sample formats + * @param[in] out array of output buffers for each channel. set to NULL to ignore processing of the given channel. + * @param[in] out_stride distance between consecutive output samples (measured in bytes) + * @param[in] in array of input buffers for each channel + * @param[in] in_stride distance between consecutive input samples (measured in bytes) + * @param len length of audio frame size (measured in samples) + */ +int av_audio_convert(AVAudioConvert *ctx, + void * const out[6], const int out_stride[6], + const void * const in[6], const int in_stride[6], int len); + +#endif /* AVCODEC_AUDIOCONVERT_H */ diff --git a/ffmpeg/libavcodec/aura.c b/ffmpeg/libavcodec/aura.c new file mode 100644 index 0000000..34d46ae --- /dev/null +++ b/ffmpeg/libavcodec/aura.c @@ -0,0 +1,108 @@ +/* + * Aura 2 decoder + * + * 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 + */ + +/** + * @file + * Aura 2 decoder + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/internal.h" + +static av_cold int aura_decode_init(AVCodecContext *avctx) +{ + /* width needs to be divisible by 4 for this codec to work */ + if (avctx->width & 0x3) + return AVERROR(EINVAL); + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + + return 0; +} + +static int aura_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *pkt) +{ + AVFrame *frame = data; + uint8_t *Y, *U, *V; + uint8_t val; + int x, y, ret; + const uint8_t *buf = pkt->data; + + /* prediction error tables (make it clear that they are signed values) */ + const int8_t *delta_table = (const int8_t*)buf + 16; + + if (pkt->size != 48 + avctx->height * avctx->width) { + av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n", + pkt->size, 48 + avctx->height * avctx->width); + return AVERROR_INVALIDDATA; + } + + /* pixel data starts 48 bytes in, after 3x16-byte tables */ + buf += 48; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + Y = frame->data[0]; + U = frame->data[1]; + V = frame->data[2]; + + /* iterate through each line in the height */ + for (y = 0; y < avctx->height; y++) { + /* reset predictors */ + val = *buf++; + U[0] = val & 0xF0; + Y[0] = val << 4; + val = *buf++; + V[0] = val & 0xF0; + Y[1] = Y[0] + delta_table[val & 0xF]; + Y += 2; U++; V++; + + /* iterate through the remaining pixel groups (4 pixels/group) */ + for (x = 1; x < (avctx->width >> 1); x++) { + val = *buf++; + U[0] = U[-1] + delta_table[val >> 4]; + Y[0] = Y[-1] + delta_table[val & 0xF]; + val = *buf++; + V[0] = V[-1] + delta_table[val >> 4]; + Y[1] = Y[ 0] + delta_table[val & 0xF]; + Y += 2; U++; V++; + } + Y += frame->linesize[0] - avctx->width; + U += frame->linesize[1] - (avctx->width >> 1); + V += frame->linesize[2] - (avctx->width >> 1); + } + + *got_frame = 1; + + return pkt->size; +} + +AVCodec ff_aura2_decoder = { + .name = "aura2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AURA2, + .init = aura_decode_init, + .decode = aura_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Auravision Aura 2"), +}; diff --git a/ffmpeg/libavcodec/avcodec.h b/ffmpeg/libavcodec/avcodec.h new file mode 100644 index 0000000..c3bd534 --- /dev/null +++ b/ffmpeg/libavcodec/avcodec.h @@ -0,0 +1,4705 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_AVCODEC_H +#define AVCODEC_AVCODEC_H + +/** + * @file + * external API header + */ + +#include +#include "libavutil/samplefmt.h" +#include "libavutil/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/cpu.h" +#include "libavutil/channel_layout.h" +#include "libavutil/dict.h" +#include "libavutil/frame.h" +#include "libavutil/log.h" +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" + +#include "libavcodec/version.h" +/** + * @defgroup libavc Encoding/Decoding Library + * @{ + * + * @defgroup lavc_decoding Decoding + * @{ + * @} + * + * @defgroup lavc_encoding Encoding + * @{ + * @} + * + * @defgroup lavc_codec Codecs + * @{ + * @defgroup lavc_codec_native Native Codecs + * @{ + * @} + * @defgroup lavc_codec_wrappers External library wrappers + * @{ + * @} + * @defgroup lavc_codec_hwaccel Hardware Accelerators bridge + * @{ + * @} + * @} + * @defgroup lavc_internal Internal + * @{ + * @} + * @} + * + */ + +/** + * @defgroup lavc_core Core functions/structures. + * @ingroup libavc + * + * Basic definitions, functions for querying libavcodec capabilities, + * allocating core structures, etc. + * @{ + */ + + +/** + * Identify the syntax and semantics of the bitstream. + * The principle is roughly: + * Two decoders with the same ID can decode the same streams. + * Two encoders with the same ID can encode compatible streams. + * There may be slight deviations from the principle due to implementation + * details. + * + * If you add a codec ID to this list, add it so that + * 1. no value of a existing codec ID changes (that would break ABI), + * 2. Give it a value which when taken as ASCII is recognized uniquely by a human as this specific codec. + * This ensures that 2 forks can independently add AVCodecIDs without producing conflicts. + * + * After adding new codec IDs, do not forget to add an entry to the codec + * descriptor list and bump libavcodec minor version. + */ +enum AVCodecID { + AV_CODEC_ID_NONE, + + /* video codecs */ + AV_CODEC_ID_MPEG1VIDEO, + AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + AV_CODEC_ID_MPEG2VIDEO_XVMC, + AV_CODEC_ID_H261, + AV_CODEC_ID_H263, + AV_CODEC_ID_RV10, + AV_CODEC_ID_RV20, + AV_CODEC_ID_MJPEG, + AV_CODEC_ID_MJPEGB, + AV_CODEC_ID_LJPEG, + AV_CODEC_ID_SP5X, + AV_CODEC_ID_JPEGLS, + AV_CODEC_ID_MPEG4, + AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_MSMPEG4V1, + AV_CODEC_ID_MSMPEG4V2, + AV_CODEC_ID_MSMPEG4V3, + AV_CODEC_ID_WMV1, + AV_CODEC_ID_WMV2, + AV_CODEC_ID_H263P, + AV_CODEC_ID_H263I, + AV_CODEC_ID_FLV1, + AV_CODEC_ID_SVQ1, + AV_CODEC_ID_SVQ3, + AV_CODEC_ID_DVVIDEO, + AV_CODEC_ID_HUFFYUV, + AV_CODEC_ID_CYUV, + AV_CODEC_ID_H264, + AV_CODEC_ID_INDEO3, + AV_CODEC_ID_VP3, + AV_CODEC_ID_THEORA, + AV_CODEC_ID_ASV1, + AV_CODEC_ID_ASV2, + AV_CODEC_ID_FFV1, + AV_CODEC_ID_4XM, + AV_CODEC_ID_VCR1, + AV_CODEC_ID_CLJR, + AV_CODEC_ID_MDEC, + AV_CODEC_ID_ROQ, + AV_CODEC_ID_INTERPLAY_VIDEO, + AV_CODEC_ID_XAN_WC3, + AV_CODEC_ID_XAN_WC4, + AV_CODEC_ID_RPZA, + AV_CODEC_ID_CINEPAK, + AV_CODEC_ID_WS_VQA, + AV_CODEC_ID_MSRLE, + AV_CODEC_ID_MSVIDEO1, + AV_CODEC_ID_IDCIN, + AV_CODEC_ID_8BPS, + AV_CODEC_ID_SMC, + AV_CODEC_ID_FLIC, + AV_CODEC_ID_TRUEMOTION1, + AV_CODEC_ID_VMDVIDEO, + AV_CODEC_ID_MSZH, + AV_CODEC_ID_ZLIB, + AV_CODEC_ID_QTRLE, + AV_CODEC_ID_TSCC, + AV_CODEC_ID_ULTI, + AV_CODEC_ID_QDRAW, + AV_CODEC_ID_VIXL, + AV_CODEC_ID_QPEG, + AV_CODEC_ID_PNG, + AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, + AV_CODEC_ID_PGM, + AV_CODEC_ID_PGMYUV, + AV_CODEC_ID_PAM, + AV_CODEC_ID_FFVHUFF, + AV_CODEC_ID_RV30, + AV_CODEC_ID_RV40, + AV_CODEC_ID_VC1, + AV_CODEC_ID_WMV3, + AV_CODEC_ID_LOCO, + AV_CODEC_ID_WNV1, + AV_CODEC_ID_AASC, + AV_CODEC_ID_INDEO2, + AV_CODEC_ID_FRAPS, + AV_CODEC_ID_TRUEMOTION2, + AV_CODEC_ID_BMP, + AV_CODEC_ID_CSCD, + AV_CODEC_ID_MMVIDEO, + AV_CODEC_ID_ZMBV, + AV_CODEC_ID_AVS, + AV_CODEC_ID_SMACKVIDEO, + AV_CODEC_ID_NUV, + AV_CODEC_ID_KMVC, + AV_CODEC_ID_FLASHSV, + AV_CODEC_ID_CAVS, + AV_CODEC_ID_JPEG2000, + AV_CODEC_ID_VMNC, + AV_CODEC_ID_VP5, + AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, + AV_CODEC_ID_TARGA, + AV_CODEC_ID_DSICINVIDEO, + AV_CODEC_ID_TIERTEXSEQVIDEO, + AV_CODEC_ID_TIFF, + AV_CODEC_ID_GIF, + AV_CODEC_ID_DXA, + AV_CODEC_ID_DNXHD, + AV_CODEC_ID_THP, + AV_CODEC_ID_SGI, + AV_CODEC_ID_C93, + AV_CODEC_ID_BETHSOFTVID, + AV_CODEC_ID_PTX, + AV_CODEC_ID_TXD, + AV_CODEC_ID_VP6A, + AV_CODEC_ID_AMV, + AV_CODEC_ID_VB, + AV_CODEC_ID_PCX, + AV_CODEC_ID_SUNRAST, + AV_CODEC_ID_INDEO4, + AV_CODEC_ID_INDEO5, + AV_CODEC_ID_MIMIC, + AV_CODEC_ID_RL2, + AV_CODEC_ID_ESCAPE124, + AV_CODEC_ID_DIRAC, + AV_CODEC_ID_BFI, + AV_CODEC_ID_CMV, + AV_CODEC_ID_MOTIONPIXELS, + AV_CODEC_ID_TGV, + AV_CODEC_ID_TGQ, + AV_CODEC_ID_TQI, + AV_CODEC_ID_AURA, + AV_CODEC_ID_AURA2, + AV_CODEC_ID_V210X, + AV_CODEC_ID_TMV, + AV_CODEC_ID_V210, + AV_CODEC_ID_DPX, + AV_CODEC_ID_MAD, + AV_CODEC_ID_FRWU, + AV_CODEC_ID_FLASHSV2, + AV_CODEC_ID_CDGRAPHICS, + AV_CODEC_ID_R210, + AV_CODEC_ID_ANM, + AV_CODEC_ID_BINKVIDEO, + AV_CODEC_ID_IFF_ILBM, + AV_CODEC_ID_IFF_BYTERUN1, + AV_CODEC_ID_KGV1, + AV_CODEC_ID_YOP, + AV_CODEC_ID_VP8, + AV_CODEC_ID_PICTOR, + AV_CODEC_ID_ANSI, + AV_CODEC_ID_A64_MULTI, + AV_CODEC_ID_A64_MULTI5, + AV_CODEC_ID_R10K, + AV_CODEC_ID_MXPEG, + AV_CODEC_ID_LAGARITH, + AV_CODEC_ID_PRORES, + AV_CODEC_ID_JV, + AV_CODEC_ID_DFA, + AV_CODEC_ID_WMV3IMAGE, + AV_CODEC_ID_VC1IMAGE, + AV_CODEC_ID_UTVIDEO, + AV_CODEC_ID_BMV_VIDEO, + AV_CODEC_ID_VBLE, + AV_CODEC_ID_DXTORY, + AV_CODEC_ID_V410, + AV_CODEC_ID_XWD, + AV_CODEC_ID_CDXL, + AV_CODEC_ID_XBM, + AV_CODEC_ID_ZEROCODEC, + AV_CODEC_ID_MSS1, + AV_CODEC_ID_MSA1, + AV_CODEC_ID_TSCC2, + AV_CODEC_ID_MTS2, + AV_CODEC_ID_CLLC, + AV_CODEC_ID_MSS2, + AV_CODEC_ID_VP9, + AV_CODEC_ID_BRENDER_PIX= MKBETAG('B','P','I','X'), + AV_CODEC_ID_Y41P = MKBETAG('Y','4','1','P'), + AV_CODEC_ID_ESCAPE130 = MKBETAG('E','1','3','0'), + AV_CODEC_ID_EXR = MKBETAG('0','E','X','R'), + AV_CODEC_ID_AVRP = MKBETAG('A','V','R','P'), + + AV_CODEC_ID_012V = MKBETAG('0','1','2','V'), + AV_CODEC_ID_G2M = MKBETAG( 0 ,'G','2','M'), + AV_CODEC_ID_AVUI = MKBETAG('A','V','U','I'), + AV_CODEC_ID_AYUV = MKBETAG('A','Y','U','V'), + AV_CODEC_ID_TARGA_Y216 = MKBETAG('T','2','1','6'), + AV_CODEC_ID_V308 = MKBETAG('V','3','0','8'), + AV_CODEC_ID_V408 = MKBETAG('V','4','0','8'), + AV_CODEC_ID_YUV4 = MKBETAG('Y','U','V','4'), + AV_CODEC_ID_SANM = MKBETAG('S','A','N','M'), + AV_CODEC_ID_PAF_VIDEO = MKBETAG('P','A','F','V'), + AV_CODEC_ID_AVRN = MKBETAG('A','V','R','n'), + AV_CODEC_ID_CPIA = MKBETAG('C','P','I','A'), + AV_CODEC_ID_XFACE = MKBETAG('X','F','A','C'), + AV_CODEC_ID_SGIRLE = MKBETAG('S','G','I','R'), + AV_CODEC_ID_MVC1 = MKBETAG('M','V','C','1'), + AV_CODEC_ID_MVC2 = MKBETAG('M','V','C','2'), + AV_CODEC_ID_SNOW = MKBETAG('S','N','O','W'), + + /* various PCM "codecs" */ + AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + AV_CODEC_ID_PCM_S16LE = 0x10000, + AV_CODEC_ID_PCM_S16BE, + AV_CODEC_ID_PCM_U16LE, + AV_CODEC_ID_PCM_U16BE, + AV_CODEC_ID_PCM_S8, + AV_CODEC_ID_PCM_U8, + AV_CODEC_ID_PCM_MULAW, + AV_CODEC_ID_PCM_ALAW, + AV_CODEC_ID_PCM_S32LE, + AV_CODEC_ID_PCM_S32BE, + AV_CODEC_ID_PCM_U32LE, + AV_CODEC_ID_PCM_U32BE, + AV_CODEC_ID_PCM_S24LE, + AV_CODEC_ID_PCM_S24BE, + AV_CODEC_ID_PCM_U24LE, + AV_CODEC_ID_PCM_U24BE, + AV_CODEC_ID_PCM_S24DAUD, + AV_CODEC_ID_PCM_ZORK, + AV_CODEC_ID_PCM_S16LE_PLANAR, + AV_CODEC_ID_PCM_DVD, + AV_CODEC_ID_PCM_F32BE, + AV_CODEC_ID_PCM_F32LE, + AV_CODEC_ID_PCM_F64BE, + AV_CODEC_ID_PCM_F64LE, + AV_CODEC_ID_PCM_BLURAY, + AV_CODEC_ID_PCM_LXF, + AV_CODEC_ID_S302M, + AV_CODEC_ID_PCM_S8_PLANAR, + AV_CODEC_ID_PCM_S24LE_PLANAR = MKBETAG(24,'P','S','P'), + AV_CODEC_ID_PCM_S32LE_PLANAR = MKBETAG(32,'P','S','P'), + AV_CODEC_ID_PCM_S16BE_PLANAR = MKBETAG('P','S','P',16), + + /* various ADPCM codecs */ + AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, + AV_CODEC_ID_ADPCM_IMA_WAV, + AV_CODEC_ID_ADPCM_IMA_DK3, + AV_CODEC_ID_ADPCM_IMA_DK4, + AV_CODEC_ID_ADPCM_IMA_WS, + AV_CODEC_ID_ADPCM_IMA_SMJPEG, + AV_CODEC_ID_ADPCM_MS, + AV_CODEC_ID_ADPCM_4XM, + AV_CODEC_ID_ADPCM_XA, + AV_CODEC_ID_ADPCM_ADX, + AV_CODEC_ID_ADPCM_EA, + AV_CODEC_ID_ADPCM_G726, + AV_CODEC_ID_ADPCM_CT, + AV_CODEC_ID_ADPCM_SWF, + AV_CODEC_ID_ADPCM_YAMAHA, + AV_CODEC_ID_ADPCM_SBPRO_4, + AV_CODEC_ID_ADPCM_SBPRO_3, + AV_CODEC_ID_ADPCM_SBPRO_2, + AV_CODEC_ID_ADPCM_THP, + AV_CODEC_ID_ADPCM_IMA_AMV, + AV_CODEC_ID_ADPCM_EA_R1, + AV_CODEC_ID_ADPCM_EA_R3, + AV_CODEC_ID_ADPCM_EA_R2, + AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + AV_CODEC_ID_ADPCM_IMA_EA_EACS, + AV_CODEC_ID_ADPCM_EA_XAS, + AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + AV_CODEC_ID_ADPCM_IMA_ISS, + AV_CODEC_ID_ADPCM_G722, + AV_CODEC_ID_ADPCM_IMA_APC, + AV_CODEC_ID_VIMA = MKBETAG('V','I','M','A'), + AV_CODEC_ID_ADPCM_AFC = MKBETAG('A','F','C',' '), + AV_CODEC_ID_ADPCM_IMA_OKI = MKBETAG('O','K','I',' '), + + /* AMR */ + AV_CODEC_ID_AMR_NB = 0x12000, + AV_CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + AV_CODEC_ID_RA_144 = 0x13000, + AV_CODEC_ID_RA_288, + + /* various DPCM codecs */ + AV_CODEC_ID_ROQ_DPCM = 0x14000, + AV_CODEC_ID_INTERPLAY_DPCM, + AV_CODEC_ID_XAN_DPCM, + AV_CODEC_ID_SOL_DPCM, + + /* audio codecs */ + AV_CODEC_ID_MP2 = 0x15000, + AV_CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + AV_CODEC_ID_AAC, + AV_CODEC_ID_AC3, + AV_CODEC_ID_DTS, + AV_CODEC_ID_VORBIS, + AV_CODEC_ID_DVAUDIO, + AV_CODEC_ID_WMAV1, + AV_CODEC_ID_WMAV2, + AV_CODEC_ID_MACE3, + AV_CODEC_ID_MACE6, + AV_CODEC_ID_VMDAUDIO, + AV_CODEC_ID_FLAC, + AV_CODEC_ID_MP3ADU, + AV_CODEC_ID_MP3ON4, + AV_CODEC_ID_SHORTEN, + AV_CODEC_ID_ALAC, + AV_CODEC_ID_WESTWOOD_SND1, + AV_CODEC_ID_GSM, ///< as in Berlin toast format + AV_CODEC_ID_QDM2, + AV_CODEC_ID_COOK, + AV_CODEC_ID_TRUESPEECH, + AV_CODEC_ID_TTA, + AV_CODEC_ID_SMACKAUDIO, + AV_CODEC_ID_QCELP, + AV_CODEC_ID_WAVPACK, + AV_CODEC_ID_DSICINAUDIO, + AV_CODEC_ID_IMC, + AV_CODEC_ID_MUSEPACK7, + AV_CODEC_ID_MLP, + AV_CODEC_ID_GSM_MS, /* as found in WAV */ + AV_CODEC_ID_ATRAC3, + AV_CODEC_ID_VOXWARE, + AV_CODEC_ID_APE, + AV_CODEC_ID_NELLYMOSER, + AV_CODEC_ID_MUSEPACK8, + AV_CODEC_ID_SPEEX, + AV_CODEC_ID_WMAVOICE, + AV_CODEC_ID_WMAPRO, + AV_CODEC_ID_WMALOSSLESS, + AV_CODEC_ID_ATRAC3P, + AV_CODEC_ID_EAC3, + AV_CODEC_ID_SIPR, + AV_CODEC_ID_MP1, + AV_CODEC_ID_TWINVQ, + AV_CODEC_ID_TRUEHD, + AV_CODEC_ID_MP4ALS, + AV_CODEC_ID_ATRAC1, + AV_CODEC_ID_BINKAUDIO_RDFT, + AV_CODEC_ID_BINKAUDIO_DCT, + AV_CODEC_ID_AAC_LATM, + AV_CODEC_ID_QDMC, + AV_CODEC_ID_CELT, + AV_CODEC_ID_G723_1, + AV_CODEC_ID_G729, + AV_CODEC_ID_8SVX_EXP, + AV_CODEC_ID_8SVX_FIB, + AV_CODEC_ID_BMV_AUDIO, + AV_CODEC_ID_RALF, + AV_CODEC_ID_IAC, + AV_CODEC_ID_ILBC, + AV_CODEC_ID_OPUS_DEPRECATED, + AV_CODEC_ID_COMFORT_NOISE, + AV_CODEC_ID_TAK_DEPRECATED, + AV_CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), + AV_CODEC_ID_SONIC = MKBETAG('S','O','N','C'), + AV_CODEC_ID_SONIC_LS = MKBETAG('S','O','N','L'), + AV_CODEC_ID_PAF_AUDIO = MKBETAG('P','A','F','A'), + AV_CODEC_ID_OPUS = MKBETAG('O','P','U','S'), + AV_CODEC_ID_TAK = MKBETAG('t','B','a','K'), + AV_CODEC_ID_EVRC = MKBETAG('s','e','v','c'), + AV_CODEC_ID_SMV = MKBETAG('s','s','m','v'), + + /* subtitle codecs */ + AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + AV_CODEC_ID_DVD_SUBTITLE = 0x17000, + AV_CODEC_ID_DVB_SUBTITLE, + AV_CODEC_ID_TEXT, ///< raw UTF-8 text + AV_CODEC_ID_XSUB, + AV_CODEC_ID_SSA, + AV_CODEC_ID_MOV_TEXT, + AV_CODEC_ID_HDMV_PGS_SUBTITLE, + AV_CODEC_ID_DVB_TELETEXT, + AV_CODEC_ID_SRT, + AV_CODEC_ID_MICRODVD = MKBETAG('m','D','V','D'), + AV_CODEC_ID_EIA_608 = MKBETAG('c','6','0','8'), + AV_CODEC_ID_JACOSUB = MKBETAG('J','S','U','B'), + AV_CODEC_ID_SAMI = MKBETAG('S','A','M','I'), + AV_CODEC_ID_REALTEXT = MKBETAG('R','T','X','T'), + AV_CODEC_ID_SUBVIEWER1 = MKBETAG('S','b','V','1'), + AV_CODEC_ID_SUBVIEWER = MKBETAG('S','u','b','V'), + AV_CODEC_ID_SUBRIP = MKBETAG('S','R','i','p'), + AV_CODEC_ID_WEBVTT = MKBETAG('W','V','T','T'), + AV_CODEC_ID_MPL2 = MKBETAG('M','P','L','2'), + AV_CODEC_ID_VPLAYER = MKBETAG('V','P','l','r'), + AV_CODEC_ID_PJS = MKBETAG('P','h','J','S'), + + /* other specific kind of codecs (generally used for attachments) */ + AV_CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + AV_CODEC_ID_TTF = 0x18000, + AV_CODEC_ID_BINTEXT = MKBETAG('B','T','X','T'), + AV_CODEC_ID_XBIN = MKBETAG('X','B','I','N'), + AV_CODEC_ID_IDF = MKBETAG( 0 ,'I','D','F'), + AV_CODEC_ID_OTF = MKBETAG( 0 ,'O','T','F'), + AV_CODEC_ID_SMPTE_KLV = MKBETAG('K','L','V','A'), + AV_CODEC_ID_DVD_NAV = MKBETAG('D','N','A','V'), + + + AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like AV_CODEC_ID_NONE) but lavf should attempt to identify it + + AV_CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + AV_CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + AV_CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + +#if FF_API_CODEC_ID +#include "old_codec_ids.h" +#endif +}; + +/** + * This struct describes the properties of a single codec described by an + * AVCodecID. + * @see avcodec_get_descriptor() + */ +typedef struct AVCodecDescriptor { + enum AVCodecID id; + enum AVMediaType type; + /** + * Name of the codec described by this descriptor. It is non-empty and + * unique for each codec descriptor. It should contain alphanumeric + * characters and '_' only. + */ + const char *name; + /** + * A more descriptive name for this codec. May be NULL. + */ + const char *long_name; + /** + * Codec properties, a combination of AV_CODEC_PROP_* flags. + */ + int props; +} AVCodecDescriptor; + +/** + * Codec uses only intra compression. + * Video codecs only. + */ +#define AV_CODEC_PROP_INTRA_ONLY (1 << 0) +/** + * Codec supports lossy compression. Audio and video codecs only. + * @note a codec may support both lossy and lossless + * compression modes + */ +#define AV_CODEC_PROP_LOSSY (1 << 1) +/** + * Codec supports lossless compression. Audio and video codecs only. + */ +#define AV_CODEC_PROP_LOSSLESS (1 << 2) +/** + * Subtitle codec is bitmap based + */ +#define AV_CODEC_PROP_BITMAP_SUB (1 << 16) + +/** + * @ingroup lavc_decoding + * Required number of additionally allocated bytes at the end of the input bitstream for decoding. + * This is mainly needed because some optimized bitstream readers read + * 32 or 64 bit at once and could read over the end.
+ * Note: If the first 23 bits of the additional bytes are not 0, then damaged + * MPEG bitstreams could cause overread and segfault. + */ +#define FF_INPUT_BUFFER_PADDING_SIZE 16 + +/** + * @ingroup lavc_encoding + * minimum encoding buffer size + * Used to avoid some checks during header writing. + */ +#define FF_MIN_BUFFER_SIZE 16384 + + +/** + * @ingroup lavc_encoding + * motion estimation type. + */ +enum Motion_Est_ID { + ME_ZERO = 1, ///< no search, that is use 0,0 vector whenever one is needed + ME_FULL, + ME_LOG, + ME_PHODS, + ME_EPZS, ///< enhanced predictive zonal search + ME_X1, ///< reserved for experiments + ME_HEX, ///< hexagon based search + ME_UMH, ///< uneven multi-hexagon search + ME_TESA, ///< transformed exhaustive search algorithm + ME_ITER=50, ///< iterative search +}; + +/** + * @ingroup lavc_decoding + */ +enum AVDiscard{ + /* We leave some space between them for extensions (drop some + * keyframes for intra-only or drop just some bidir frames). */ + AVDISCARD_NONE =-16, ///< discard nothing + AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi + AVDISCARD_NONREF = 8, ///< discard all non reference + AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames + AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes + AVDISCARD_ALL = 48, ///< discard all +}; + +enum AVColorPrimaries{ + AVCOL_PRI_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + AVCOL_PRI_UNSPECIFIED = 2, + AVCOL_PRI_BT470M = 4, + AVCOL_PRI_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + AVCOL_PRI_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above + AVCOL_PRI_FILM = 8, + AVCOL_PRI_NB , ///< Not part of ABI +}; + +enum AVColorTransferCharacteristic{ + AVCOL_TRC_BT709 = 1, ///< also ITU-R BT1361 + AVCOL_TRC_UNSPECIFIED = 2, + AVCOL_TRC_GAMMA22 = 4, ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + AVCOL_TRC_GAMMA28 = 5, ///< also ITU-R BT470BG + AVCOL_TRC_SMPTE240M = 7, + AVCOL_TRC_NB , ///< Not part of ABI +}; + +enum AVColorSpace{ + AVCOL_SPC_RGB = 0, + AVCOL_SPC_BT709 = 1, ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + AVCOL_SPC_UNSPECIFIED = 2, + AVCOL_SPC_FCC = 4, + AVCOL_SPC_BT470BG = 5, ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601 + AVCOL_SPC_SMPTE170M = 6, ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above + AVCOL_SPC_SMPTE240M = 7, + AVCOL_SPC_YCOCG = 8, ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + AVCOL_SPC_NB , ///< Not part of ABI +}; +#define AVCOL_SPC_YCGCO AVCOL_SPC_YCOCG + +enum AVColorRange{ + AVCOL_RANGE_UNSPECIFIED = 0, + AVCOL_RANGE_MPEG = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges + AVCOL_RANGE_JPEG = 2, ///< the normal 2^n-1 "JPEG" YUV ranges + AVCOL_RANGE_NB , ///< Not part of ABI +}; + +/** + * X X 3 4 X X are luma samples, + * 1 2 1-6 are possible chroma positions + * X X 5 6 X 0 is undefined/unknown position + */ +enum AVChromaLocation{ + AVCHROMA_LOC_UNSPECIFIED = 0, + AVCHROMA_LOC_LEFT = 1, ///< mpeg2/4, h264 default + AVCHROMA_LOC_CENTER = 2, ///< mpeg1, jpeg, h263 + AVCHROMA_LOC_TOPLEFT = 3, ///< DV + AVCHROMA_LOC_TOP = 4, + AVCHROMA_LOC_BOTTOMLEFT = 5, + AVCHROMA_LOC_BOTTOM = 6, + AVCHROMA_LOC_NB , ///< Not part of ABI +}; + +enum AVAudioServiceType { + AV_AUDIO_SERVICE_TYPE_MAIN = 0, + AV_AUDIO_SERVICE_TYPE_EFFECTS = 1, + AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED = 2, + AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED = 3, + AV_AUDIO_SERVICE_TYPE_DIALOGUE = 4, + AV_AUDIO_SERVICE_TYPE_COMMENTARY = 5, + AV_AUDIO_SERVICE_TYPE_EMERGENCY = 6, + AV_AUDIO_SERVICE_TYPE_VOICE_OVER = 7, + AV_AUDIO_SERVICE_TYPE_KARAOKE = 8, + AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI +}; + +/** + * @ingroup lavc_encoding + */ +typedef struct RcOverride{ + int start_frame; + int end_frame; + int qscale; // If this is 0 then quality_factor will be used instead. + float quality_factor; +} RcOverride; + +#define FF_MAX_B_FRAMES 16 + +/* encoding support + These flags can be passed in AVCodecContext.flags before initialization. + Note: Not everything is supported yet. +*/ + +#define CODEC_FLAG_QSCALE 0x0002 ///< Use fixed qscale. +#define CODEC_FLAG_4MV 0x0004 ///< 4 MV per MB allowed / advanced prediction for H.263. +#define CODEC_FLAG_QPEL 0x0010 ///< Use qpel MC. +#define CODEC_FLAG_GMC 0x0020 ///< Use GMC. +#define CODEC_FLAG_MV0 0x0040 ///< Always try a MB with MV=<0,0>. +/** + * The parent program guarantees that the input for B-frames containing + * streams is not written to for at least s->max_b_frames+1 frames, if + * this is not set the input will be copied. + */ +#define CODEC_FLAG_INPUT_PRESERVED 0x0100 +#define CODEC_FLAG_PASS1 0x0200 ///< Use internal 2pass ratecontrol in first pass mode. +#define CODEC_FLAG_PASS2 0x0400 ///< Use internal 2pass ratecontrol in second pass mode. +#define CODEC_FLAG_GRAY 0x2000 ///< Only decode/encode grayscale. +#define CODEC_FLAG_EMU_EDGE 0x4000 ///< Don't draw edges. +#define CODEC_FLAG_PSNR 0x8000 ///< error[?] variables will be set during encoding. +#define CODEC_FLAG_TRUNCATED 0x00010000 /** Input bitstream might be truncated at a random + location instead of only at frame boundaries. */ +#define CODEC_FLAG_NORMALIZE_AQP 0x00020000 ///< Normalize adaptive quantization. +#define CODEC_FLAG_INTERLACED_DCT 0x00040000 ///< Use interlaced DCT. +#define CODEC_FLAG_LOW_DELAY 0x00080000 ///< Force low delay. +#define CODEC_FLAG_GLOBAL_HEADER 0x00400000 ///< Place global headers in extradata instead of every keyframe. +#define CODEC_FLAG_BITEXACT 0x00800000 ///< Use only bitexact stuff (except (I)DCT). +/* Fx : Flag for h263+ extra options */ +#define CODEC_FLAG_AC_PRED 0x01000000 ///< H.263 advanced intra coding / MPEG-4 AC prediction +#define CODEC_FLAG_LOOP_FILTER 0x00000800 ///< loop filter +#define CODEC_FLAG_INTERLACED_ME 0x20000000 ///< interlaced motion estimation +#define CODEC_FLAG_CLOSED_GOP 0x80000000 +#define CODEC_FLAG2_FAST 0x00000001 ///< Allow non spec compliant speedup tricks. +#define CODEC_FLAG2_NO_OUTPUT 0x00000004 ///< Skip bitstream encoding. +#define CODEC_FLAG2_LOCAL_HEADER 0x00000008 ///< Place global headers at every keyframe instead of in extradata. +#define CODEC_FLAG2_DROP_FRAME_TIMECODE 0x00002000 ///< timecode is in drop frame format. DEPRECATED!!!! +#define CODEC_FLAG2_IGNORE_CROP 0x00010000 ///< Discard cropping information from SPS. + +#define CODEC_FLAG2_CHUNKS 0x00008000 ///< Input bitstream might be truncated at a packet boundaries instead of only at frame boundaries. +#define CODEC_FLAG2_SHOW_ALL 0x00400000 ///< Show all frames before the first keyframe + +/* Unsupported options : + * Syntax Arithmetic coding (SAC) + * Reference Picture Selection + * Independent Segment Decoding */ +/* /Fx */ +/* codec capabilities */ + +#define CODEC_CAP_DRAW_HORIZ_BAND 0x0001 ///< Decoder can use draw_horiz_band callback. +/** + * Codec uses get_buffer() for allocating buffers and supports custom allocators. + * If not set, it might not use get_buffer() at all or use operations that + * assume the buffer was allocated by avcodec_default_get_buffer. + */ +#define CODEC_CAP_DR1 0x0002 +#define CODEC_CAP_TRUNCATED 0x0008 +/* Codec can export data for HW decoding (XvMC). */ +#define CODEC_CAP_HWACCEL 0x0010 +/** + * Encoder or decoder requires flushing with NULL input at the end in order to + * give the complete and correct output. + * + * NOTE: If this flag is not set, the codec is guaranteed to never be fed with + * with NULL data. The user can still send NULL data to the public encode + * or decode function, but libavcodec will not pass it along to the codec + * unless this flag is set. + * + * Decoders: + * The decoder has a non-zero delay and needs to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to get the delayed data until the decoder no longer + * returns frames. + * + * Encoders: + * The encoder needs to be fed with NULL data at the end of encoding until the + * encoder no longer returns data. + * + * NOTE: For encoders implementing the AVCodec.encode2() function, setting this + * flag also means that the encoder must set the pts and duration for + * each output packet. If this flag is not set, the pts and duration will + * be determined by libavcodec from the input frame. + */ +#define CODEC_CAP_DELAY 0x0020 +/** + * Codec can be fed a final frame with a smaller size. + * This can be used to prevent truncation of the last audio samples. + */ +#define CODEC_CAP_SMALL_LAST_FRAME 0x0040 +/** + * Codec can export data for HW decoding (VDPAU). + */ +#define CODEC_CAP_HWACCEL_VDPAU 0x0080 +/** + * Codec can output multiple frames per AVPacket + * Normally demuxers return one frame at a time, demuxers which do not do + * are connected to a parser to split what they return into proper frames. + * This flag is reserved to the very rare category of codecs which have a + * bitstream that cannot be split into frames without timeconsuming + * operations like full decoding. Demuxers carring such bitstreams thus + * may return multiple frames in a packet. This has many disadvantages like + * prohibiting stream copy in many cases thus it should only be considered + * as a last resort. + */ +#define CODEC_CAP_SUBFRAMES 0x0100 +/** + * Codec is experimental and is thus avoided in favor of non experimental + * encoders + */ +#define CODEC_CAP_EXPERIMENTAL 0x0200 +/** + * Codec should fill in channel configuration and samplerate instead of container + */ +#define CODEC_CAP_CHANNEL_CONF 0x0400 + +/** + * Codec is able to deal with negative linesizes + */ +#define CODEC_CAP_NEG_LINESIZES 0x0800 + +/** + * Codec supports frame-level multithreading. + */ +#define CODEC_CAP_FRAME_THREADS 0x1000 +/** + * Codec supports slice-based (or partition-based) multithreading. + */ +#define CODEC_CAP_SLICE_THREADS 0x2000 +/** + * Codec supports changed parameters at any point. + */ +#define CODEC_CAP_PARAM_CHANGE 0x4000 +/** + * Codec supports avctx->thread_count == 0 (auto). + */ +#define CODEC_CAP_AUTO_THREADS 0x8000 +/** + * Audio encoder supports receiving a different number of samples in each call. + */ +#define CODEC_CAP_VARIABLE_FRAME_SIZE 0x10000 +/** + * Codec is intra only. + */ +#define CODEC_CAP_INTRA_ONLY 0x40000000 +/** + * Codec is lossless. + */ +#define CODEC_CAP_LOSSLESS 0x80000000 + +//The following defines may change, don't expect compatibility if you use them. +#define MB_TYPE_INTRA4x4 0x0001 +#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific +#define MB_TYPE_INTRA_PCM 0x0004 //FIXME H.264-specific +#define MB_TYPE_16x16 0x0008 +#define MB_TYPE_16x8 0x0010 +#define MB_TYPE_8x16 0x0020 +#define MB_TYPE_8x8 0x0040 +#define MB_TYPE_INTERLACED 0x0080 +#define MB_TYPE_DIRECT2 0x0100 //FIXME +#define MB_TYPE_ACPRED 0x0200 +#define MB_TYPE_GMC 0x0400 +#define MB_TYPE_SKIP 0x0800 +#define MB_TYPE_P0L0 0x1000 +#define MB_TYPE_P1L0 0x2000 +#define MB_TYPE_P0L1 0x4000 +#define MB_TYPE_P1L1 0x8000 +#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0) +#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1) +#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1) +#define MB_TYPE_QUANT 0x00010000 +#define MB_TYPE_CBP 0x00020000 +//Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...) + +/** + * Pan Scan area. + * This specifies the area which should be displayed. + * Note there may be multiple such areas for one frame. + */ +typedef struct AVPanScan{ + /** + * id + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int id; + + /** + * width and height in 1/16 pel + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int width; + int height; + + /** + * position of the top left corner in 1/16 pel for up to 3 fields/frames + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int16_t position[3][2]; +}AVPanScan; + +#define FF_QSCALE_TYPE_MPEG1 0 +#define FF_QSCALE_TYPE_MPEG2 1 +#define FF_QSCALE_TYPE_H264 2 +#define FF_QSCALE_TYPE_VP56 3 + +#if FF_API_GET_BUFFER +#define FF_BUFFER_TYPE_INTERNAL 1 +#define FF_BUFFER_TYPE_USER 2 ///< direct rendering buffers (image is (de)allocated by user) +#define FF_BUFFER_TYPE_SHARED 4 ///< Buffer from somewhere else; don't deallocate image (data/base), all other tables are not shared. +#define FF_BUFFER_TYPE_COPY 8 ///< Just a (modified) copy of some other buffer, don't deallocate anything. + +#define FF_BUFFER_HINTS_VALID 0x01 // Buffer hints value is meaningful (if 0 ignore). +#define FF_BUFFER_HINTS_READABLE 0x02 // Codec will read from buffer. +#define FF_BUFFER_HINTS_PRESERVE 0x04 // User must not alter buffer content. +#define FF_BUFFER_HINTS_REUSABLE 0x08 // Codec will reuse the buffer (update). +#endif + +/** + * The decoder will keep a reference to the frame and may reuse it later. + */ +#define AV_GET_BUFFER_FLAG_REF (1 << 0) + +/** + * @defgroup lavc_packet AVPacket + * + * Types and functions for working with AVPacket. + * @{ + */ +enum AVPacketSideDataType { + AV_PKT_DATA_PALETTE, + AV_PKT_DATA_NEW_EXTRADATA, + + /** + * An AV_PKT_DATA_PARAM_CHANGE side data packet is laid out as follows: + * @code + * u32le param_flags + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) + * s32le channel_count + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) + * u64le channel_layout + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) + * s32le sample_rate + * if (param_flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) + * s32le width + * s32le height + * @endcode + */ + AV_PKT_DATA_PARAM_CHANGE, + + /** + * An AV_PKT_DATA_H263_MB_INFO side data packet contains a number of + * structures with info about macroblocks relevant to splitting the + * packet into smaller packets on macroblock edges (e.g. as for RFC 2190). + * That is, it does not necessarily contain info about all macroblocks, + * as long as the distance between macroblocks in the info is smaller + * than the target payload size. + * Each MB info structure is 12 bytes, and is laid out as follows: + * @code + * u32le bit offset from the start of the packet + * u8 current quantizer at the start of the macroblock + * u8 GOB number + * u16le macroblock address within the GOB + * u8 horizontal MV predictor + * u8 vertical MV predictor + * u8 horizontal MV predictor for block number 3 + * u8 vertical MV predictor for block number 3 + * @endcode + */ + AV_PKT_DATA_H263_MB_INFO, + + /** + * Recommmends skipping the specified number of samples + * @code + * u32le number of samples to skip from start of this packet + * u32le number of samples to skip from end of this packet + * u8 reason for start skip + * u8 reason for end skip (0=padding silence, 1=convergence) + * @endcode + */ + AV_PKT_DATA_SKIP_SAMPLES=70, + + /** + * An AV_PKT_DATA_JP_DUALMONO side data packet indicates that + * the packet may contain "dual mono" audio specific to Japanese DTV + * and if it is true, recommends only the selected channel to be used. + * @code + * u8 selected channels (0=mail/left, 1=sub/right, 2=both) + * @endcode + */ + AV_PKT_DATA_JP_DUALMONO, + + /** + * A list of zero terminated key/value strings. There is no end marker for + * the list, so it is required to rely on the side data size to stop. + */ + AV_PKT_DATA_STRINGS_METADATA, + + /** + * Subtitle event position + * @code + * u32le x1 + * u32le y1 + * u32le x2 + * u32le y2 + * @endcode + */ + AV_PKT_DATA_SUBTITLE_POSITION, + + /** + * Data found in BlockAdditional element of matroska container. There is + * no end marker for the data, so it is required to rely on the side data + * size to recognize the end. 8 byte id (as found in BlockAddId) followed + * by data. + */ + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, +}; + +/** + * This structure stores compressed data. It is typically exported by demuxers + * and then passed as input to decoders, or received as output from encoders and + * then passed to muxers. + * + * For video, it should typically contain one compressed frame. For audio it may + * contain several compressed frames. + * + * AVPacket is one of the few structs in FFmpeg, whose size is a part of public + * ABI. Thus it may be allocated on stack and no new fields can be added to it + * without libavcodec and libavformat major bump. + * + * The semantics of data ownership depends on the buf or destruct (deprecated) + * fields. If either is set, the packet data is dynamically allocated and is + * valid indefinitely until av_free_packet() is called (which in turn calls + * av_buffer_unref()/the destruct callback to free the data). If neither is set, + * the packet data is typically backed by some static buffer somewhere and is + * only valid for a limited time (e.g. until the next read call when demuxing). + * + * The side data is always allocated with av_malloc() and is freed in + * av_free_packet(). + */ +typedef struct AVPacket { + /** + * A reference to the reference-counted buffer where the packet data is + * stored. + * May be NULL, then the packet data is not reference-counted. + */ + AVBufferRef *buf; + /** + * Presentation timestamp in AVStream->time_base units; the time at which + * the decompressed packet will be presented to the user. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + * pts MUST be larger or equal to dts as presentation cannot happen before + * decompression, unless one wants to view hex dumps. Some formats misuse + * the terms dts and pts/cts to mean something different. Such timestamps + * must be converted to true pts/dts before they are stored in AVPacket. + */ + int64_t pts; + /** + * Decompression timestamp in AVStream->time_base units; the time at which + * the packet is decompressed. + * Can be AV_NOPTS_VALUE if it is not stored in the file. + */ + int64_t dts; + uint8_t *data; + int size; + int stream_index; + /** + * A combination of AV_PKT_FLAG values + */ + int flags; + /** + * Additional packet data that can be provided by the container. + * Packet can contain several types of side information. + */ + struct { + uint8_t *data; + int size; + enum AVPacketSideDataType type; + } *side_data; + int side_data_elems; + + /** + * Duration of this packet in AVStream->time_base units, 0 if unknown. + * Equals next_pts - this_pts in presentation order. + */ + int duration; +#if FF_API_DESTRUCT_PACKET + attribute_deprecated + void (*destruct)(struct AVPacket *); + attribute_deprecated + void *priv; +#endif + int64_t pos; ///< byte position in stream, -1 if unknown + + /** + * Time difference in AVStream->time_base units from the pts of this + * packet to the point at which the output from the decoder has converged + * independent from the availability of previous frames. That is, the + * frames are virtually identical no matter if decoding started from + * the very first frame or from this keyframe. + * Is AV_NOPTS_VALUE if unknown. + * This field is not the display duration of the current packet. + * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY + * set. + * + * The purpose of this field is to allow seeking in streams that have no + * keyframes in the conventional sense. It corresponds to the + * recovery point SEI in H.264 and match_time_delta in NUT. It is also + * essential for some types of subtitle streams to ensure that all + * subtitles are correctly displayed after seeking. + */ + int64_t convergence_duration; +} AVPacket; +#define AV_PKT_FLAG_KEY 0x0001 ///< The packet contains a keyframe +#define AV_PKT_FLAG_CORRUPT 0x0002 ///< The packet content is corrupted + +enum AVSideDataParamChangeFlags { + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, + AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, +}; +/** + * @} + */ + +struct AVCodecInternal; + +enum AVFieldOrder { + AV_FIELD_UNKNOWN, + AV_FIELD_PROGRESSIVE, + AV_FIELD_TT, //< Top coded_first, top displayed first + AV_FIELD_BB, //< Bottom coded first, bottom displayed first + AV_FIELD_TB, //< Top coded first, bottom displayed first + AV_FIELD_BT, //< Bottom coded first, top displayed first +}; + +/** + * main external API structure. + * New fields can be added to the end with minor version bumps. + * Removal, reordering and changes to existing fields require a major + * version bump. + * Please use AVOptions (av_opt* / av_set/get*()) to access these fields from user + * applications. + * sizeof(AVCodecContext) must not be used outside libav*. + */ +typedef struct AVCodecContext { + /** + * information on struct for av_log + * - set by avcodec_alloc_context3 + */ + const AVClass *av_class; + int log_level_offset; + + enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ + const struct AVCodec *codec; + char codec_name[32]; + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + + /** + * fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * A demuxer should set this to what is stored in the field used to identify the codec. + * If there are multiple such fields in a container then the demuxer should choose the one + * which maximizes the information about the used codec. + * If the codec tag field in a container is larger than 32 bits then the demuxer should + * remap the longer ID to 32 bits with a table or other structure. Alternatively a new + * extra_codec_tag + size could be added but for this a clear advantage must be demonstrated + * first. + * - encoding: Set by user, if not then the default based on codec_id will be used. + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int codec_tag; + + /** + * fourcc from the AVI stream header (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A'). + * This is used to work around some encoder bugs. + * - encoding: unused + * - decoding: Set by user, will be converted to uppercase by libavcodec during init. + */ + unsigned int stream_codec_tag; + + void *priv_data; + + /** + * Private context used for internal data. + * + * Unlike priv_data, this is not codec-specific. It is used in general + * libavcodec functions. + */ + struct AVCodecInternal *internal; + + /** + * Private data of the user, can be used to carry app specific stuff. + * - encoding: Set by user. + * - decoding: Set by user. + */ + void *opaque; + + /** + * the average bitrate + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: Set by libavcodec. 0 or some bitrate if this info is available in the stream. + */ + int bit_rate; + + /** + * number of bits the bitstream is allowed to diverge from the reference. + * the reference can be CBR (for CBR pass1) or VBR (for pass2) + * - encoding: Set by user; unused for constant quantizer encoding. + * - decoding: unused + */ + int bit_rate_tolerance; + + /** + * Global quality for codecs which cannot change it per frame. + * This should be proportional to MPEG-1/2/4 qscale. + * - encoding: Set by user. + * - decoding: unused + */ + int global_quality; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int compression_level; +#define FF_COMPRESSION_DEFAULT -1 + + /** + * CODEC_FLAG_*. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags; + + /** + * CODEC_FLAG2_* + * - encoding: Set by user. + * - decoding: Set by user. + */ + int flags2; + + /** + * some codecs need / can use extradata like Huffman tables. + * mjpeg: Huffman tables + * rv10: additional flags + * mpeg4: global headers (they can be in the bitstream or here) + * The allocated memory should be FF_INPUT_BUFFER_PADDING_SIZE bytes larger + * than extradata_size to avoid prolems if it is read with the bitstream reader. + * The bytewise contents of extradata must not depend on the architecture or CPU endianness. + * - encoding: Set/allocated/freed by libavcodec. + * - decoding: Set/allocated/freed by user. + */ + uint8_t *extradata; + int extradata_size; + + /** + * This is the fundamental unit of time (in seconds) in terms + * of which frame timestamps are represented. For fixed-fps content, + * timebase should be 1/framerate and timestamp increments should be + * identically 1. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. + */ + AVRational time_base; + + /** + * For some codecs, the time base is closer to the field rate than the frame rate. + * Most notably, H.264 and MPEG-2 specify time_base as half of frame duration + * if no telecine is used ... + * + * Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. + */ + int ticks_per_frame; + + /** + * Codec delay. + * + * Encoding: Number of frames delay there will be from the encoder input to + * the decoder output. (we assume the decoder matches the spec) + * Decoding: Number of frames delay in addition to what a standard decoder + * as specified in the spec would produce. + * + * Video: + * Number of frames the decoded output will be delayed relative to the + * encoded input. + * + * Audio: + * For encoding, this is the number of "priming" samples added to the + * beginning of the stream. The decoded output will be delayed by this + * many samples relative to the input to the encoder. Note that this + * field is purely informational and does not directly affect the pts + * output by the encoder, which should always be based on the actual + * presentation time, including any delay. + * For decoding, this is the number of samples the decoder needs to + * output before the decoder's output is valid. When seeking, you should + * start decoding this many samples prior to your desired seek point. + * + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int delay; + + + /* video only */ + /** + * picture width / height. + * - encoding: MUST be set by user. + * - decoding: Set by libavcodec. + * Note: For compatibility it is possible to set this instead of + * coded_width/height before decoding. + */ + int width, height; + + /** + * Bitstream width / height, may be different from width/height if lowres enabled. + * - encoding: unused + * - decoding: Set by user before init if known. Codec should override / dynamically change if needed. + */ + int coded_width, coded_height; + +#define FF_ASPECT_EXTENDED 15 + + /** + * the number of pictures in a group of pictures, or 0 for intra_only + * - encoding: Set by user. + * - decoding: unused + */ + int gop_size; + + /** + * Pixel format, see AV_PIX_FMT_xxx. + * May be set by the demuxer if known from headers. + * May be overridden by the decoder if it knows better. + * - encoding: Set by user. + * - decoding: Set by user if known, overridden by libavcodec if known + */ + enum AVPixelFormat pix_fmt; + + /** + * Motion estimation algorithm used for video coding. + * 1 (zero), 2 (full), 3 (log), 4 (phods), 5 (epzs), 6 (x1), 7 (hex), + * 8 (umh), 9 (iter), 10 (tesa) [7, 8, 10 are x264 specific, 9 is snow specific] + * - encoding: MUST be set by user. + * - decoding: unused + */ + int me_method; + + /** + * If non NULL, 'draw_horiz_band' is called by the libavcodec + * decoder to draw a horizontal band. It improves cache usage. Not + * all codecs can do that. You must check the codec capabilities + * beforehand. + * When multithreading is used, it may be called from multiple threads + * at the same time; threads might draw different parts of the same AVFrame, + * or multiple AVFrames, and there is no guarantee that slices will be drawn + * in order. + * The function is also used by hardware acceleration APIs. + * It is called at least once during frame decoding to pass + * the data needed for hardware render. + * In that mode instead of pixel data, AVFrame points to + * a structure specific to the acceleration API. The application + * reads the structure and can change some fields to indicate progress + * or mark state. + * - encoding: unused + * - decoding: Set by user. + * @param height the height of the slice + * @param y the y position of the slice + * @param type 1->top field, 2->bottom field, 3->frame + * @param offset offset into the AVFrame.data from which the slice should be read + */ + void (*draw_horiz_band)(struct AVCodecContext *s, + const AVFrame *src, int offset[AV_NUM_DATA_POINTERS], + int y, int type, int height); + + /** + * callback to negotiate the pixelFormat + * @param fmt is the list of formats which are supported by the codec, + * it is terminated by -1 as 0 is a valid format, the formats are ordered by quality. + * The first is always the native one. + * @return the chosen format + * - encoding: unused + * - decoding: Set by user, if not set the native format will be chosen. + */ + enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + + /** + * maximum number of B-frames between non-B-frames + * Note: The output will be delayed by max_b_frames+1 relative to the input. + * - encoding: Set by user. + * - decoding: unused + */ + int max_b_frames; + + /** + * qscale factor between IP and B-frames + * If > 0 then the last P-frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_factor; + + /** obsolete FIXME remove */ + int rc_strategy; +#define FF_RC_STRATEGY_XVID 1 + + int b_frame_strategy; + + /** + * qscale offset between IP and B-frames + * - encoding: Set by user. + * - decoding: unused + */ + float b_quant_offset; + + /** + * Size of the frame reordering buffer in the decoder. + * For MPEG-2 it is 1 IPB or 0 low delay IP. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int has_b_frames; + + /** + * 0-> h263 quant 1-> mpeg quant + * - encoding: Set by user. + * - decoding: unused + */ + int mpeg_quant; + + /** + * qscale factor between P and I-frames + * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset). + * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset). + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_factor; + + /** + * qscale offset between P and I-frames + * - encoding: Set by user. + * - decoding: unused + */ + float i_quant_offset; + + /** + * luminance masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float lumi_masking; + + /** + * temporary complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float temporal_cplx_masking; + + /** + * spatial complexity masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float spatial_cplx_masking; + + /** + * p block masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float p_masking; + + /** + * darkness masking (0-> disabled) + * - encoding: Set by user. + * - decoding: unused + */ + float dark_masking; + + /** + * slice count + * - encoding: Set by libavcodec. + * - decoding: Set by user (or 0). + */ + int slice_count; + /** + * prediction method (needed for huffyuv) + * - encoding: Set by user. + * - decoding: unused + */ + int prediction_method; +#define FF_PRED_LEFT 0 +#define FF_PRED_PLANE 1 +#define FF_PRED_MEDIAN 2 + + /** + * slice offsets in the frame in bytes + * - encoding: Set/allocated by libavcodec. + * - decoding: Set/allocated by user (or NULL). + */ + int *slice_offset; + + /** + * sample aspect ratio (0 if unknown) + * That is the width of a pixel divided by the height of the pixel. + * Numerator and denominator must be relatively prime and smaller than 256 for some video standards. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + AVRational sample_aspect_ratio; + + /** + * motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_cmp; + /** + * subpixel motion estimation comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_sub_cmp; + /** + * macroblock comparison function (not supported yet) + * - encoding: Set by user. + * - decoding: unused + */ + int mb_cmp; + /** + * interlaced DCT comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int ildct_cmp; +#define FF_CMP_SAD 0 +#define FF_CMP_SSE 1 +#define FF_CMP_SATD 2 +#define FF_CMP_DCT 3 +#define FF_CMP_PSNR 4 +#define FF_CMP_BIT 5 +#define FF_CMP_RD 6 +#define FF_CMP_ZERO 7 +#define FF_CMP_VSAD 8 +#define FF_CMP_VSSE 9 +#define FF_CMP_NSSE 10 +#define FF_CMP_W53 11 +#define FF_CMP_W97 12 +#define FF_CMP_DCTMAX 13 +#define FF_CMP_DCT264 14 +#define FF_CMP_CHROMA 256 + + /** + * ME diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int dia_size; + + /** + * amount of previous MV predictors (2a+1 x 2a+1 square) + * - encoding: Set by user. + * - decoding: unused + */ + int last_predictor_count; + + /** + * prepass for motion estimation + * - encoding: Set by user. + * - decoding: unused + */ + int pre_me; + + /** + * motion estimation prepass comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int me_pre_cmp; + + /** + * ME prepass diamond size & shape + * - encoding: Set by user. + * - decoding: unused + */ + int pre_dia_size; + + /** + * subpel ME quality + * - encoding: Set by user. + * - decoding: unused + */ + int me_subpel_quality; + + /** + * DTG active format information (additional aspect ratio + * information only used in DVB MPEG-2 transport streams) + * 0 if not set. + * + * - encoding: unused + * - decoding: Set by decoder. + */ + int dtg_active_format; +#define FF_DTG_AFD_SAME 8 +#define FF_DTG_AFD_4_3 9 +#define FF_DTG_AFD_16_9 10 +#define FF_DTG_AFD_14_9 11 +#define FF_DTG_AFD_4_3_SP_14_9 13 +#define FF_DTG_AFD_16_9_SP_14_9 14 +#define FF_DTG_AFD_SP_4_3 15 + + /** + * maximum motion estimation search range in subpel units + * If 0 then no limit. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_range; + + /** + * intra quantizer bias + * - encoding: Set by user. + * - decoding: unused + */ + int intra_quant_bias; +#define FF_DEFAULT_QUANT_BIAS 999999 + + /** + * inter quantizer bias + * - encoding: Set by user. + * - decoding: unused + */ + int inter_quant_bias; + + /** + * slice flags + * - encoding: unused + * - decoding: Set by user. + */ + int slice_flags; +#define SLICE_FLAG_CODED_ORDER 0x0001 ///< draw_horiz_band() is called in coded order instead of display +#define SLICE_FLAG_ALLOW_FIELD 0x0002 ///< allow draw_horiz_band() with field slices (MPEG2 field pics) +#define SLICE_FLAG_ALLOW_PLANE 0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1) + + /** + * XVideo Motion Acceleration + * - encoding: forbidden + * - decoding: set by decoder + */ + int xvmc_acceleration; + + /** + * macroblock decision mode + * - encoding: Set by user. + * - decoding: unused + */ + int mb_decision; +#define FF_MB_DECISION_SIMPLE 0 ///< uses mb_cmp +#define FF_MB_DECISION_BITS 1 ///< chooses the one which needs the fewest bits +#define FF_MB_DECISION_RD 2 ///< rate distortion + + /** + * custom intra quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: Set by libavcodec. + */ + uint16_t *intra_matrix; + + /** + * custom inter quantization matrix + * - encoding: Set by user, can be NULL. + * - decoding: Set by libavcodec. + */ + uint16_t *inter_matrix; + + /** + * scene change detection threshold + * 0 is default, larger means fewer detected scene changes. + * - encoding: Set by user. + * - decoding: unused + */ + int scenechange_threshold; + + /** + * noise reduction strength + * - encoding: Set by user. + * - decoding: unused + */ + int noise_reduction; + + /** + * Motion estimation threshold below which no motion estimation is + * performed, but instead the user specified motion vectors are used. + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_threshold; + + /** + * Macroblock threshold below which the user specified macroblock types will be used. + * - encoding: Set by user. + * - decoding: unused + */ + int mb_threshold; + + /** + * precision of the intra DC coefficient - 8 + * - encoding: Set by user. + * - decoding: unused + */ + int intra_dc_precision; + + /** + * Number of macroblock rows at the top which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_top; + + /** + * Number of macroblock rows at the bottom which are skipped. + * - encoding: unused + * - decoding: Set by user. + */ + int skip_bottom; + + /** + * Border processing masking, raises the quantizer for mbs on the borders + * of the picture. + * - encoding: Set by user. + * - decoding: unused + */ + float border_masking; + + /** + * minimum MB lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmin; + + /** + * maximum MB lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int mb_lmax; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int me_penalty_compensation; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int bidir_refine; + + /** + * + * - encoding: Set by user. + * - decoding: unused + */ + int brd_scale; + + /** + * minimum GOP size + * - encoding: Set by user. + * - decoding: unused + */ + int keyint_min; + + /** + * number of reference frames + * - encoding: Set by user. + * - decoding: Set by lavc. + */ + int refs; + + /** + * chroma qp offset from luma + * - encoding: Set by user. + * - decoding: unused + */ + int chromaoffset; + + /** + * Multiplied by qscale for each frame and added to scene_change_score. + * - encoding: Set by user. + * - decoding: unused + */ + int scenechange_factor; + + /** + * + * Note: Value depends upon the compare function used for fullpel ME. + * - encoding: Set by user. + * - decoding: unused + */ + int mv0_threshold; + + /** + * Adjust sensitivity of b_frame_strategy 1. + * - encoding: Set by user. + * - decoding: unused + */ + int b_sensitivity; + + /** + * Chromaticity coordinates of the source primaries. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorPrimaries color_primaries; + + /** + * Color Transfer Characteristic. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorTransferCharacteristic color_trc; + + /** + * YUV colorspace type. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorSpace colorspace; + + /** + * MPEG vs JPEG YUV range. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVColorRange color_range; + + /** + * This defines the location of chroma samples. + * - encoding: Set by user + * - decoding: Set by libavcodec + */ + enum AVChromaLocation chroma_sample_location; + + /** + * Number of slices. + * Indicates number of picture subdivisions. Used for parallelized + * decoding. + * - encoding: Set by user + * - decoding: unused + */ + int slices; + + /** Field order + * - encoding: set by libavcodec + * - decoding: Set by user. + */ + enum AVFieldOrder field_order; + + /* audio only */ + int sample_rate; ///< samples per second + int channels; ///< number of audio channels + + /** + * audio sample format + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVSampleFormat sample_fmt; ///< sample format + + /* The following data should not be initialized. */ + /** + * Number of samples per channel in an audio frame. + * + * - encoding: set by libavcodec in avcodec_open2(). Each submitted frame + * except the last must contain exactly frame_size samples per channel. + * May be 0 when the codec has CODEC_CAP_VARIABLE_FRAME_SIZE set, then the + * frame size is not restricted. + * - decoding: may be set by some decoders to indicate constant frame size + */ + int frame_size; + + /** + * Frame counter, set by libavcodec. + * + * - decoding: total number of frames returned from the decoder so far. + * - encoding: total number of frames passed to the encoder so far. + * + * @note the counter is not incremented if encoding/decoding resulted in + * an error. + */ + int frame_number; + + /** + * number of bytes per packet if constant and known or 0 + * Used by some WAV based audio codecs. + */ + int block_align; + + /** + * Audio cutoff bandwidth (0 means "automatic") + * - encoding: Set by user. + * - decoding: unused + */ + int cutoff; + +#if FF_API_REQUEST_CHANNELS + /** + * Decoder should decode to this many channels if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + * @deprecated Deprecated in favor of request_channel_layout. + */ + int request_channels; +#endif + + /** + * Audio channel layout. + * - encoding: set by user. + * - decoding: set by user, may be overwritten by libavcodec. + */ + uint64_t channel_layout; + + /** + * Request decoder to use this channel layout if it can (0 for default) + * - encoding: unused + * - decoding: Set by user. + */ + uint64_t request_channel_layout; + + /** + * Type of service that the audio stream conveys. + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + enum AVAudioServiceType audio_service_type; + + /** + * desired sample format + * - encoding: Not used. + * - decoding: Set by user. + * Decoder will decode to this format if it can. + */ + enum AVSampleFormat request_sample_fmt; + +#if FF_API_GET_BUFFER + /** + * Called at the beginning of each frame to get a buffer for it. + * + * The function will set AVFrame.data[], AVFrame.linesize[]. + * AVFrame.extended_data[] must also be set, but it should be the same as + * AVFrame.data[] except for planar audio with more channels than can fit + * in AVFrame.data[]. In that case, AVFrame.data[] shall still contain as + * many data pointers as it can hold. + * + * if CODEC_CAP_DR1 is not set then get_buffer() must call + * avcodec_default_get_buffer() instead of providing buffers allocated by + * some other means. + * + * AVFrame.data[] should be 32- or 16-byte-aligned unless the CPU doesn't + * need it. avcodec_default_get_buffer() aligns the output buffer properly, + * but if get_buffer() is overridden then alignment considerations should + * be taken into account. + * + * @see avcodec_default_get_buffer() + * + * Video: + * + * If pic.reference is set then the frame will be read later by libavcodec. + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * If frame multithreading is used and thread_safe_callbacks is set, + * it may be called from a different thread, but not from more than one at + * once. Does not need to be reentrant. + * + * @see release_buffer(), reget_buffer() + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * Decoders cannot use the buffer after returning from + * avcodec_decode_audio4(), so they will not call release_buffer(), as it + * is assumed to be released immediately upon return. In some rare cases, + * a decoder may need to call get_buffer() more than once in a single + * call to avcodec_decode_audio4(). In that case, when get_buffer() is + * called again after it has already been called once, the previously + * acquired buffer is assumed to be released at that time and may not be + * reused by the decoder. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + * + * @deprecated use get_buffer2() + */ + attribute_deprecated + int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * Called to release buffers which were allocated with get_buffer. + * A released buffer can be reused in get_buffer(). + * pic.data[*] must be set to NULL. + * May be called from a different thread if frame multithreading is used, + * but not by more than one thread at once, so does not need to be reentrant. + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + * + * @deprecated custom freeing callbacks should be set from get_buffer2() + */ + attribute_deprecated + void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); + + /** + * Called at the beginning of a frame to get cr buffer for it. + * Buffer type (size, hints) must be the same. libavcodec won't check it. + * libavcodec will pass previous buffer in pic, function should return + * same buffer or new buffer with old frame "painted" into it. + * If pic.data[0] == NULL must behave like get_buffer(). + * if CODEC_CAP_DR1 is not set then reget_buffer() must call + * avcodec_default_reget_buffer() instead of providing buffers allocated by + * some other means. + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + attribute_deprecated + int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); +#endif + + /** + * This callback is called at the beginning of each frame to get data + * buffer(s) for it. There may be one contiguous buffer for all the data or + * there may be a buffer per each data plane or anything in between. Each + * buffer must be reference-counted using the AVBuffer API. + * + * The following fields will be set in the frame before this callback is + * called: + * - format + * - width, height (video only) + * - sample_rate, channel_layout, nb_samples (audio only) + * Their values may differ from the corresponding values in + * AVCodecContext. This callback must use the frame values, not the codec + * context values, to calculate the required buffer size. + * + * This callback must fill the following fields in the frame: + * - data[] + * - linesize[] + * - extended_data: + * * if the data is planar audio with more than 8 channels, then this + * callback must allocate and fill extended_data to contain all pointers + * to all data planes. data[] must hold as many pointers as it can. + * extended_data must be allocated with av_malloc() and will be freed in + * av_frame_unref(). + * * otherwise exended_data must point to data + * - buf[] must contain references to the buffers that contain the frame + * data. + * - extended_buf and nb_extended_buf must be allocated with av_malloc() by + * this callback and filled with the extra buffers if there are more + * buffers than buf[] can hold. extended_buf will be freed in + * av_frame_unref(). + * + * If CODEC_CAP_DR1 is not set then get_buffer2() must call + * avcodec_default_get_buffer2() instead of providing buffers allocated by + * some other means. + * + * Each data plane must be aligned to the maximum required by the target + * CPU. + * + * @see avcodec_default_get_buffer2() + * + * Video: + * + * If AV_GET_BUFFER_FLAG_REF is set in flags then the frame may be reused + * (read and/or written to if it is writable) later by libavcodec. + * + * If CODEC_FLAG_EMU_EDGE is not set in s->flags, the buffer must contain an + * edge of the size returned by avcodec_get_edge_width() on all sides. + * + * avcodec_align_dimensions2() should be used to find the required width and + * height, as they normally need to be rounded up to the next multiple of 16. + * + * If frame multithreading is used and thread_safe_callbacks is set, + * this callback may be called from a different thread, but not from more + * than one at once. Does not need to be reentrant. + * + * @see avcodec_align_dimensions2() + * + * Audio: + * + * Decoders request a buffer of a particular size by setting + * AVFrame.nb_samples prior to calling get_buffer2(). The decoder may, + * however, utilize only part of the buffer by setting AVFrame.nb_samples + * to a smaller value in the output frame. + * + * As a convenience, av_samples_get_buffer_size() and + * av_samples_fill_arrays() in libavutil may be used by custom get_buffer2() + * functions to find the required data size and to fill data pointers and + * linesize. In AVFrame.linesize, only linesize[0] may be set for audio + * since all planes must be the same size. + * + * @see av_samples_get_buffer_size(), av_samples_fill_arrays() + * + * - encoding: unused + * - decoding: Set by libavcodec, user can override. + */ + int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + + /** + * If non-zero, the decoded audio and video frames returned from + * avcodec_decode_video2() and avcodec_decode_audio4() are reference-counted + * and are valid indefinitely. The caller must free them with + * av_frame_unref() when they are not needed anymore. + * Otherwise, the decoded frames must not be freed by the caller and are + * only valid until the next decode call. + * + * - encoding: unused + * - decoding: set by the caller before avcodec_open2(). + */ + int refcounted_frames; + + /* - encoding parameters */ + float qcompress; ///< amount of qscale change between easy & hard scenes (0.0-1.0) + float qblur; ///< amount of qscale smoothing over time (0.0-1.0) + + /** + * minimum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmin; + + /** + * maximum quantizer + * - encoding: Set by user. + * - decoding: unused + */ + int qmax; + + /** + * maximum quantizer difference between frames + * - encoding: Set by user. + * - decoding: unused + */ + int max_qdiff; + + /** + * ratecontrol qmin qmax limiting method + * 0-> clipping, 1-> use a nice continuous function to limit qscale wthin qmin/qmax. + * - encoding: Set by user. + * - decoding: unused + */ + float rc_qsquish; + + float rc_qmod_amp; + int rc_qmod_freq; + + /** + * decoder bitstream buffer size + * - encoding: Set by user. + * - decoding: unused + */ + int rc_buffer_size; + + /** + * ratecontrol override, see RcOverride + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + int rc_override_count; + RcOverride *rc_override; + + /** + * rate control equation + * - encoding: Set by user + * - decoding: unused + */ + const char *rc_eq; + + /** + * maximum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int rc_max_rate; + + /** + * minimum bitrate + * - encoding: Set by user. + * - decoding: unused + */ + int rc_min_rate; + + float rc_buffer_aggressivity; + + /** + * initial complexity for pass1 ratecontrol + * - encoding: Set by user. + * - decoding: unused + */ + float rc_initial_cplx; + + /** + * Ratecontrol attempt to use, at maximum, of what can be used without an underflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_max_available_vbv_use; + + /** + * Ratecontrol attempt to use, at least, times the amount needed to prevent a vbv overflow. + * - encoding: Set by user. + * - decoding: unused. + */ + float rc_min_vbv_overflow_use; + + /** + * Number of bits which should be loaded into the rc buffer before decoding starts. + * - encoding: Set by user. + * - decoding: unused + */ + int rc_initial_buffer_occupancy; + +#define FF_CODER_TYPE_VLC 0 +#define FF_CODER_TYPE_AC 1 +#define FF_CODER_TYPE_RAW 2 +#define FF_CODER_TYPE_RLE 3 +#define FF_CODER_TYPE_DEFLATE 4 + /** + * coder type + * - encoding: Set by user. + * - decoding: unused + */ + int coder_type; + + /** + * context model + * - encoding: Set by user. + * - decoding: unused + */ + int context_model; + + /** + * minimum Lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int lmin; + + /** + * maximum Lagrange multipler + * - encoding: Set by user. + * - decoding: unused + */ + int lmax; + + /** + * frame skip threshold + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_threshold; + + /** + * frame skip factor + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_factor; + + /** + * frame skip exponent + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_exp; + + /** + * frame skip comparison function + * - encoding: Set by user. + * - decoding: unused + */ + int frame_skip_cmp; + + /** + * trellis RD quantization + * - encoding: Set by user. + * - decoding: unused + */ + int trellis; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int min_prediction_order; + + /** + * - encoding: Set by user. + * - decoding: unused + */ + int max_prediction_order; + + /** + * GOP timecode frame start number + * - encoding: Set by user, in non drop frame format + * - decoding: Set by libavcodec (timecode in the 25 bits format, -1 if unset) + */ + int64_t timecode_frame_start; + + /* The RTP callback: This function is called */ + /* every time the encoder has a packet to send. */ + /* It depends on the encoder if the data starts */ + /* with a Start Code (it should). H.263 does. */ + /* mb_nb contains the number of macroblocks */ + /* encoded in the RTP payload. */ + void (*rtp_callback)(struct AVCodecContext *avctx, void *data, int size, int mb_nb); + + int rtp_payload_size; /* The size of the RTP payload: the coder will */ + /* do its best to deliver a chunk with size */ + /* below rtp_payload_size, the chunk will start */ + /* with a start code on some codecs like H.263. */ + /* This doesn't take account of any particular */ + /* headers inside the transmitted RTP payload. */ + + /* statistics, used for 2-pass encoding */ + int mv_bits; + int header_bits; + int i_tex_bits; + int p_tex_bits; + int i_count; + int p_count; + int skip_count; + int misc_bits; + + /** + * number of bits used for the previously encoded frame + * - encoding: Set by libavcodec. + * - decoding: unused + */ + int frame_bits; + + /** + * pass1 encoding statistics output buffer + * - encoding: Set by libavcodec. + * - decoding: unused + */ + char *stats_out; + + /** + * pass2 encoding statistics input buffer + * Concatenated stuff from stats_out of pass1 should be placed here. + * - encoding: Allocated/set/freed by user. + * - decoding: unused + */ + char *stats_in; + + /** + * Work around bugs in encoders which sometimes cannot be detected automatically. + * - encoding: Set by user + * - decoding: Set by user + */ + int workaround_bugs; +#define FF_BUG_AUTODETECT 1 ///< autodetection +#define FF_BUG_OLD_MSMPEG4 2 +#define FF_BUG_XVID_ILACE 4 +#define FF_BUG_UMP4 8 +#define FF_BUG_NO_PADDING 16 +#define FF_BUG_AMV 32 +#define FF_BUG_AC_VLC 0 ///< Will be removed, libavcodec can now handle these non-compliant files by default. +#define FF_BUG_QPEL_CHROMA 64 +#define FF_BUG_STD_QPEL 128 +#define FF_BUG_QPEL_CHROMA2 256 +#define FF_BUG_DIRECT_BLOCKSIZE 512 +#define FF_BUG_EDGE 1024 +#define FF_BUG_HPEL_CHROMA 2048 +#define FF_BUG_DC_CLIP 4096 +#define FF_BUG_MS 8192 ///< Work around various bugs in Microsoft's broken decoders. +#define FF_BUG_TRUNCATED 16384 + + /** + * strictly follow the standard (MPEG4, ...). + * - encoding: Set by user. + * - decoding: Set by user. + * Setting this to STRICT or higher means the encoder and decoder will + * generally do stupid things, whereas setting it to unofficial or lower + * will mean the encoder might produce output that is not supported by all + * spec-compliant decoders. Decoders don't differentiate between normal, + * unofficial and experimental (that is, they always try to decode things + * when they can) unless they are explicitly asked to behave stupidly + * (=strictly conform to the specs) + */ + int strict_std_compliance; +#define FF_COMPLIANCE_VERY_STRICT 2 ///< Strictly conform to an older more strict version of the spec or reference software. +#define FF_COMPLIANCE_STRICT 1 ///< Strictly conform to all the things in the spec no matter what consequences. +#define FF_COMPLIANCE_NORMAL 0 +#define FF_COMPLIANCE_UNOFFICIAL -1 ///< Allow unofficial extensions +#define FF_COMPLIANCE_EXPERIMENTAL -2 ///< Allow nonstandardized experimental things. + + /** + * error concealment flags + * - encoding: unused + * - decoding: Set by user. + */ + int error_concealment; +#define FF_EC_GUESS_MVS 1 +#define FF_EC_DEBLOCK 2 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug; +#define FF_DEBUG_PICT_INFO 1 +#define FF_DEBUG_RC 2 +#define FF_DEBUG_BITSTREAM 4 +#define FF_DEBUG_MB_TYPE 8 +#define FF_DEBUG_QP 16 +#define FF_DEBUG_MV 32 +#define FF_DEBUG_DCT_COEFF 0x00000040 +#define FF_DEBUG_SKIP 0x00000080 +#define FF_DEBUG_STARTCODE 0x00000100 +#define FF_DEBUG_PTS 0x00000200 +#define FF_DEBUG_ER 0x00000400 +#define FF_DEBUG_MMCO 0x00000800 +#define FF_DEBUG_BUGS 0x00001000 +#define FF_DEBUG_VIS_QP 0x00002000 +#define FF_DEBUG_VIS_MB_TYPE 0x00004000 +#define FF_DEBUG_BUFFERS 0x00008000 +#define FF_DEBUG_THREADS 0x00010000 + + /** + * debug + * - encoding: Set by user. + * - decoding: Set by user. + */ + int debug_mv; +#define FF_DEBUG_VIS_MV_P_FOR 0x00000001 //visualize forward predicted MVs of P frames +#define FF_DEBUG_VIS_MV_B_FOR 0x00000002 //visualize forward predicted MVs of B frames +#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames + + /** + * Error recognition; may misdetect some more or less valid parts as errors. + * - encoding: unused + * - decoding: Set by user. + */ + int err_recognition; +#define AV_EF_CRCCHECK (1<<0) +#define AV_EF_BITSTREAM (1<<1) +#define AV_EF_BUFFER (1<<2) +#define AV_EF_EXPLODE (1<<3) + +#define AV_EF_CAREFUL (1<<16) +#define AV_EF_COMPLIANT (1<<17) +#define AV_EF_AGGRESSIVE (1<<18) + + + /** + * opaque 64bit number (generally a PTS) that will be reordered and + * output in AVFrame.reordered_opaque + * @deprecated in favor of pkt_pts + * - encoding: unused + * - decoding: Set by user. + */ + int64_t reordered_opaque; + + /** + * Hardware accelerator in use + * - encoding: unused. + * - decoding: Set by libavcodec + */ + struct AVHWAccel *hwaccel; + + /** + * Hardware accelerator context. + * For some hardware accelerators, a global context needs to be + * provided by the user. In that case, this holds display-dependent + * data FFmpeg cannot instantiate itself. Please refer to the + * FFmpeg HW accelerator documentation to know how to fill this + * is. e.g. for VA API, this is a struct vaapi_context. + * - encoding: unused + * - decoding: Set by user + */ + void *hwaccel_context; + + /** + * error + * - encoding: Set by libavcodec if flags&CODEC_FLAG_PSNR. + * - decoding: unused + */ + uint64_t error[AV_NUM_DATA_POINTERS]; + + /** + * DCT algorithm, see FF_DCT_* below + * - encoding: Set by user. + * - decoding: unused + */ + int dct_algo; +#define FF_DCT_AUTO 0 +#define FF_DCT_FASTINT 1 +#define FF_DCT_INT 2 +#define FF_DCT_MMX 3 +#define FF_DCT_ALTIVEC 5 +#define FF_DCT_FAAN 6 + + /** + * IDCT algorithm, see FF_IDCT_* below. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int idct_algo; +#define FF_IDCT_AUTO 0 +#define FF_IDCT_INT 1 +#define FF_IDCT_SIMPLE 2 +#define FF_IDCT_SIMPLEMMX 3 +#define FF_IDCT_ARM 7 +#define FF_IDCT_ALTIVEC 8 +#define FF_IDCT_SH4 9 +#define FF_IDCT_SIMPLEARM 10 +#define FF_IDCT_IPP 13 +#define FF_IDCT_XVIDMMX 14 +#define FF_IDCT_SIMPLEARMV5TE 16 +#define FF_IDCT_SIMPLEARMV6 17 +#define FF_IDCT_SIMPLEVIS 18 +#define FF_IDCT_FAAN 20 +#define FF_IDCT_SIMPLENEON 22 +#define FF_IDCT_SIMPLEALPHA 23 + + /** + * bits per sample/pixel from the demuxer (needed for huffyuv). + * - encoding: Set by libavcodec. + * - decoding: Set by user. + */ + int bits_per_coded_sample; + + /** + * Bits per sample/pixel of internal libavcodec pixel/sample format. + * - encoding: set by user. + * - decoding: set by libavcodec. + */ + int bits_per_raw_sample; + + /** + * low resolution decoding, 1-> 1/2 size, 2->1/4 size + * - encoding: unused + * - decoding: Set by user. + */ + int lowres; + + /** + * the picture in the bitstream + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + AVFrame *coded_frame; + + /** + * thread count + * is used to decide how many independent tasks should be passed to execute() + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_count; + + /** + * Which multithreading methods to use. + * Use of FF_THREAD_FRAME will increase decoding delay by one frame per thread, + * so clients which cannot provide future frames should not use it. + * + * - encoding: Set by user, otherwise the default is used. + * - decoding: Set by user, otherwise the default is used. + */ + int thread_type; +#define FF_THREAD_FRAME 1 ///< Decode more than one frame at once +#define FF_THREAD_SLICE 2 ///< Decode more than one part of a single frame at once + + /** + * Which multithreading methods are in use by the codec. + * - encoding: Set by libavcodec. + * - decoding: Set by libavcodec. + */ + int active_thread_type; + + /** + * Set by the client if its custom get_buffer() callback can be called + * synchronously from another thread, which allows faster multithreaded decoding. + * draw_horiz_band() will be called from other threads regardless of this setting. + * Ignored if the default get_buffer() is used. + * - encoding: Set by user. + * - decoding: Set by user. + */ + int thread_safe_callbacks; + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * @param count the number of things to execute + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg), void *arg2, int *ret, int count, int size); + + /** + * The codec may call this to execute several independent things. + * It will return only after finishing all tasks. + * The user may replace this with some multithreaded implementation, + * the default implementation will execute the parts serially. + * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. + * @param c context passed also to func + * @param count the number of things to execute + * @param arg2 argument passed unchanged to func + * @param ret return values of executed functions, must have space for "count" values. May be NULL. + * @param func function that will be called count times, with jobnr from 0 to count-1. + * threadnr will be in the range 0 to c->thread_count-1 < MAX_THREADS and so that no + * two instances of func executing at the same time will have the same threadnr. + * @return always 0 currently, but code should handle a future improvement where when any call to func + * returns < 0 no further calls to func may be done and < 0 is returned. + * - encoding: Set by libavcodec, user can override. + * - decoding: Set by libavcodec, user can override. + */ + int (*execute2)(struct AVCodecContext *c, int (*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count); + + /** + * thread opaque + * Can be used by execute() to store some per AVCodecContext stuff. + * - encoding: set by execute() + * - decoding: set by execute() + */ + void *thread_opaque; + + /** + * noise vs. sse weight for the nsse comparsion function + * - encoding: Set by user. + * - decoding: unused + */ + int nsse_weight; + + /** + * profile + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int profile; +#define FF_PROFILE_UNKNOWN -99 +#define FF_PROFILE_RESERVED -100 + +#define FF_PROFILE_AAC_MAIN 0 +#define FF_PROFILE_AAC_LOW 1 +#define FF_PROFILE_AAC_SSR 2 +#define FF_PROFILE_AAC_LTP 3 +#define FF_PROFILE_AAC_HE 4 +#define FF_PROFILE_AAC_HE_V2 28 +#define FF_PROFILE_AAC_LD 22 +#define FF_PROFILE_AAC_ELD 38 + +#define FF_PROFILE_DTS 20 +#define FF_PROFILE_DTS_ES 30 +#define FF_PROFILE_DTS_96_24 40 +#define FF_PROFILE_DTS_HD_HRA 50 +#define FF_PROFILE_DTS_HD_MA 60 + +#define FF_PROFILE_MPEG2_422 0 +#define FF_PROFILE_MPEG2_HIGH 1 +#define FF_PROFILE_MPEG2_SS 2 +#define FF_PROFILE_MPEG2_SNR_SCALABLE 3 +#define FF_PROFILE_MPEG2_MAIN 4 +#define FF_PROFILE_MPEG2_SIMPLE 5 + +#define FF_PROFILE_H264_CONSTRAINED (1<<9) // 8+1; constraint_set1_flag +#define FF_PROFILE_H264_INTRA (1<<11) // 8+3; constraint_set3_flag + +#define FF_PROFILE_H264_BASELINE 66 +#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED) +#define FF_PROFILE_H264_MAIN 77 +#define FF_PROFILE_H264_EXTENDED 88 +#define FF_PROFILE_H264_HIGH 100 +#define FF_PROFILE_H264_HIGH_10 110 +#define FF_PROFILE_H264_HIGH_10_INTRA (110|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_HIGH_422 122 +#define FF_PROFILE_H264_HIGH_422_INTRA (122|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_HIGH_444 144 +#define FF_PROFILE_H264_HIGH_444_PREDICTIVE 244 +#define FF_PROFILE_H264_HIGH_444_INTRA (244|FF_PROFILE_H264_INTRA) +#define FF_PROFILE_H264_CAVLC_444 44 + +#define FF_PROFILE_VC1_SIMPLE 0 +#define FF_PROFILE_VC1_MAIN 1 +#define FF_PROFILE_VC1_COMPLEX 2 +#define FF_PROFILE_VC1_ADVANCED 3 + +#define FF_PROFILE_MPEG4_SIMPLE 0 +#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE 1 +#define FF_PROFILE_MPEG4_CORE 2 +#define FF_PROFILE_MPEG4_MAIN 3 +#define FF_PROFILE_MPEG4_N_BIT 4 +#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE 5 +#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION 6 +#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE 7 +#define FF_PROFILE_MPEG4_HYBRID 8 +#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME 9 +#define FF_PROFILE_MPEG4_CORE_SCALABLE 10 +#define FF_PROFILE_MPEG4_ADVANCED_CODING 11 +#define FF_PROFILE_MPEG4_ADVANCED_CORE 12 +#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13 +#define FF_PROFILE_MPEG4_SIMPLE_STUDIO 14 +#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE 15 + + /** + * level + * - encoding: Set by user. + * - decoding: Set by libavcodec. + */ + int level; +#define FF_LEVEL_UNKNOWN -99 + + /** + * Skip loop filtering for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_loop_filter; + + /** + * Skip IDCT/dequantization for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_idct; + + /** + * Skip decoding for selected frames. + * - encoding: unused + * - decoding: Set by user. + */ + enum AVDiscard skip_frame; + + /** + * Header containing style information for text subtitles. + * For SUBTITLE_ASS subtitle type, it should contain the whole ASS + * [Script Info] and [V4+ Styles] section, plus the [Events] line and + * the Format line following. It shouldn't include any Dialogue line. + * - encoding: Set/allocated/freed by user (before avcodec_open2()) + * - decoding: Set/allocated/freed by libavcodec (by avcodec_open2()) + */ + uint8_t *subtitle_header; + int subtitle_header_size; + + /** + * Simulates errors in the bitstream to test error concealment. + * - encoding: Set by user. + * - decoding: unused + */ + int error_rate; + + /** + * Current packet as passed into the decoder, to avoid having + * to pass the packet into every function. Currently only valid + * inside lavc and get/release_buffer callbacks. + * - decoding: set by avcodec_decode_*, read by get_buffer() for setting pkt_pts + * - encoding: unused + */ + AVPacket *pkt; + + /** + * VBV delay coded in the last frame (in periods of a 27 MHz clock). + * Used for compliant TS muxing. + * - encoding: Set by libavcodec. + * - decoding: unused. + */ + uint64_t vbv_delay; + + /** + * Timebase in which pkt_dts/pts and AVPacket.dts/pts are. + * Code outside libavcodec should access this field using: + * av_codec_{get,set}_pkt_timebase(avctx) + * - encoding unused. + * - decodimg set by user + */ + AVRational pkt_timebase; + + /** + * AVCodecDescriptor + * Code outside libavcodec should access this field using: + * av_codec_{get,set}_codec_descriptor(avctx) + * - encoding: unused. + * - decoding: set by libavcodec. + */ + const AVCodecDescriptor *codec_descriptor; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec, not intended to be used by user apps + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + + /** + * Character encoding of the input subtitles file. + * - decoding: set by user + * - encoding: unused + */ + char *sub_charenc; + + /** + * Subtitles character encoding mode. Formats or codecs might be adjusting + * this setting (if they are doing the conversion themselves for instance). + * - decoding: set by libavcodec + * - encoding: unused + */ + int sub_charenc_mode; +#define FF_SUB_CHARENC_MODE_DO_NOTHING -1 ///< do nothing (demuxer outputs a stream supposed to be already in UTF-8, or the codec is bitmap for instance) +#define FF_SUB_CHARENC_MODE_AUTOMATIC 0 ///< libavcodec will select the mode itself +#define FF_SUB_CHARENC_MODE_PRE_DECODER 1 ///< the AVPacket data needs to be recoded to UTF-8 before being fed to the decoder, requires iconv +} AVCodecContext; + +AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); +void av_codec_set_pkt_timebase (AVCodecContext *avctx, AVRational val); + +const AVCodecDescriptor *av_codec_get_codec_descriptor(const AVCodecContext *avctx); +void av_codec_set_codec_descriptor(AVCodecContext *avctx, const AVCodecDescriptor *desc); + +/** + * AVProfile. + */ +typedef struct AVProfile { + int profile; + const char *name; ///< short name for the profile +} AVProfile; + +typedef struct AVCodecDefault AVCodecDefault; + +struct AVSubtitle; + +/** + * AVCodec. + */ +typedef struct AVCodec { + /** + * Name of the codec implementation. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + * This is the primary way to find a codec from the user perspective. + */ + const char *name; + /** + * Descriptive name for the codec, meant to be more human readable than name. + * You should use the NULL_IF_CONFIG_SMALL() macro to define it. + */ + const char *long_name; + enum AVMediaType type; + enum AVCodecID id; + /** + * Codec capabilities. + * see CODEC_CAP_* + */ + int capabilities; + const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0} + const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 + const int *supported_samplerates; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0 + const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1 + const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 + uint8_t max_lowres; ///< maximum value for lowres supported by the decoder + const AVClass *priv_class; ///< AVClass for the private context + const AVProfile *profiles; ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN} + + /***************************************************************** + * No fields below this line are part of the public API. They + * may not be used outside of libavcodec and can be changed and + * removed at will. + * New public fields should be added right above. + ***************************************************************** + */ + int priv_data_size; + struct AVCodec *next; + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * If defined, called on thread contexts when they are created. + * If the codec allocates writable tables in init(), re-allocate them here. + * priv_data will be set to a copy of the original. + */ + int (*init_thread_copy)(AVCodecContext *); + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(AVCodecContext *dst, const AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const AVCodecDefault *defaults; + + /** + * Initialize codec static data, called from avcodec_register(). + */ + void (*init_static_data)(struct AVCodec *codec); + + int (*init)(AVCodecContext *); + int (*encode_sub)(AVCodecContext *, uint8_t *buf, int buf_size, + const struct AVSubtitle *sub); + /** + * Encode data to an AVPacket. + * + * @param avctx codec context + * @param avpkt output AVPacket (may contain a user-provided buffer) + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, + int *got_packet_ptr); + int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); + int (*close)(AVCodecContext *); + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(AVCodecContext *); +} AVCodec; + +/** + * AVHWAccel. + */ +typedef struct AVHWAccel { + /** + * Name of the hardware accelerated codec. + * The name is globally unique among encoders and among decoders (but an + * encoder and a decoder can share the same name). + */ + const char *name; + + /** + * Type of codec implemented by the hardware accelerator. + * + * See AVMEDIA_TYPE_xxx + */ + enum AVMediaType type; + + /** + * Codec implemented by the hardware accelerator. + * + * See AV_CODEC_ID_xxx + */ + enum AVCodecID id; + + /** + * Supported pixel format. + * + * Only hardware accelerated formats are supported here. + */ + enum AVPixelFormat pix_fmt; + + /** + * Hardware accelerated codec capabilities. + * see FF_HWACCEL_CODEC_CAP_* + */ + int capabilities; + + struct AVHWAccel *next; + + /** + * Called at the beginning of each frame or field picture. + * + * Meaningful frame information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * Note that buf can be NULL along with buf_size set to 0. + * Otherwise, this means the whole frame is available at this point. + * + * @param avctx the codec context + * @param buf the frame data buffer base + * @param buf_size the size of the frame in bytes + * @return zero if successful, a negative value otherwise + */ + int (*start_frame)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Callback for each slice. + * + * Meaningful slice information (codec specific) is guaranteed to + * be parsed at this point. This function is mandatory. + * + * @param avctx the codec context + * @param buf the slice data buffer base + * @param buf_size the size of the slice in bytes + * @return zero if successful, a negative value otherwise + */ + int (*decode_slice)(AVCodecContext *avctx, const uint8_t *buf, uint32_t buf_size); + + /** + * Called at the end of each frame or field picture. + * + * The whole picture is parsed at this point and can now be sent + * to the hardware accelerator. This function is mandatory. + * + * @param avctx the codec context + * @return zero if successful, a negative value otherwise + */ + int (*end_frame)(AVCodecContext *avctx); + + /** + * Size of HW accelerator private data. + * + * Private data is allocated with av_mallocz() before + * AVCodecContext.get_buffer() and deallocated after + * AVCodecContext.release_buffer(). + */ + int priv_data_size; +} AVHWAccel; + +/** + * @defgroup lavc_picture AVPicture + * + * Functions for working with AVPicture + * @{ + */ + +/** + * four components are given, that's all. + * the last component is alpha + */ +typedef struct AVPicture { + uint8_t *data[AV_NUM_DATA_POINTERS]; + int linesize[AV_NUM_DATA_POINTERS]; ///< number of bytes per line +} AVPicture; + +/** + * @} + */ + +enum AVSubtitleType { + SUBTITLE_NONE, + + SUBTITLE_BITMAP, ///< A bitmap, pict will be set + + /** + * Plain text, the text field must be set by the decoder and is + * authoritative. ass and pict fields may contain approximations. + */ + SUBTITLE_TEXT, + + /** + * Formatted text, the ass field must be set by the decoder and is + * authoritative. pict and text fields may contain approximations. + */ + SUBTITLE_ASS, +}; + +#define AV_SUBTITLE_FLAG_FORCED 0x00000001 + +typedef struct AVSubtitleRect { + int x; ///< top left corner of pict, undefined when pict is not set + int y; ///< top left corner of pict, undefined when pict is not set + int w; ///< width of pict, undefined when pict is not set + int h; ///< height of pict, undefined when pict is not set + int nb_colors; ///< number of colors in pict, undefined when pict is not set + + /** + * data+linesize for the bitmap of this subtitle. + * can be set for text/ass as well once they where rendered + */ + AVPicture pict; + enum AVSubtitleType type; + + char *text; ///< 0 terminated plain UTF-8 text + + /** + * 0 terminated ASS/SSA compatible event line. + * The presentation of this is unaffected by the other values in this + * struct. + */ + char *ass; + + int flags; +} AVSubtitleRect; + +typedef struct AVSubtitle { + uint16_t format; /* 0 = graphics */ + uint32_t start_display_time; /* relative to packet pts, in ms */ + uint32_t end_display_time; /* relative to packet pts, in ms */ + unsigned num_rects; + AVSubtitleRect **rects; + int64_t pts; ///< Same as packet pts, in AV_TIME_BASE +} AVSubtitle; + +/** + * If c is NULL, returns the first registered codec, + * if c is non-NULL, returns the next registered codec after c, + * or NULL if c is the last one. + */ +AVCodec *av_codec_next(const AVCodec *c); + +/** + * Return the LIBAVCODEC_VERSION_INT constant. + */ +unsigned avcodec_version(void); + +/** + * Return the libavcodec build-time configuration. + */ +const char *avcodec_configuration(void); + +/** + * Return the libavcodec license. + */ +const char *avcodec_license(void); + +/** + * Register the codec codec and initialize libavcodec. + * + * @warning either this function or avcodec_register_all() must be called + * before any other libavcodec functions. + * + * @see avcodec_register_all() + */ +void avcodec_register(AVCodec *codec); + +/** + * Register all the codecs, parsers and bitstream filters which were enabled at + * configuration time. If you do not call this function you can select exactly + * which formats you want to support, by using the individual registration + * functions. + * + * @see avcodec_register + * @see av_register_codec_parser + * @see av_register_bitstream_filter + */ +void avcodec_register_all(void); + + +#if FF_API_ALLOC_CONTEXT +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct can be deallocated by simply calling av_free(). + * + * @return An AVCodecContext filled with default values or NULL on failure. + * @see avcodec_get_context_defaults + * + * @deprecated use avcodec_alloc_context3() + */ +attribute_deprecated +AVCodecContext *avcodec_alloc_context(void); + +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +attribute_deprecated +AVCodecContext *avcodec_alloc_context2(enum AVMediaType); + +/** + * Set the fields of the given AVCodecContext to default values. + * + * @param s The AVCodecContext of which the fields should be set to default values. + * @deprecated use avcodec_get_context_defaults3 + */ +attribute_deprecated +void avcodec_get_context_defaults(AVCodecContext *s); + +/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API! + * we WILL change its arguments and name a few times! */ +attribute_deprecated +void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType); +#endif + +/** + * Allocate an AVCodecContext and set its fields to default values. The + * resulting struct can be deallocated by calling avcodec_close() on it followed + * by av_free(). + * + * @param codec if non-NULL, allocate private data and initialize defaults + * for the given codec. It is illegal to then call avcodec_open2() + * with a different codec. + * If NULL, then the codec-specific defaults won't be initialized, + * which may result in suboptimal default settings (this is + * important mainly for encoders, e.g. libx264). + * + * @return An AVCodecContext filled with default values or NULL on failure. + * @see avcodec_get_context_defaults + */ +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); + +/** + * Set the fields of the given AVCodecContext to default values corresponding + * to the given codec (defaults may be codec-dependent). + * + * Do not call this function if a non-NULL codec has been passed + * to avcodec_alloc_context3() that allocated this AVCodecContext. + * If codec is non-NULL, it is illegal to call avcodec_open2() with a + * different codec on this AVCodecContext. + */ +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); + +/** + * Get the AVClass for AVCodecContext. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_class(void); + +/** + * Get the AVClass for AVFrame. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_frame_class(void); + +/** + * Get the AVClass for AVSubtitleRect. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *avcodec_get_subtitle_rect_class(void); + +/** + * Copy the settings of the source AVCodecContext into the destination + * AVCodecContext. The resulting destination codec context will be + * unopened, i.e. you are required to call avcodec_open2() before you + * can use this AVCodecContext to decode/encode video/audio data. + * + * @param dest target codec context, should be initialized with + * avcodec_alloc_context3(), but otherwise uninitialized + * @param src source codec context + * @return AVERROR() on error (e.g. memory allocation error), 0 on success + */ +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src); + +/** + * Allocate an AVFrame and set its fields to default values. The resulting + * struct must be freed using avcodec_free_frame(). + * + * @return An AVFrame filled with default values or NULL on failure. + * @see avcodec_get_frame_defaults + */ +AVFrame *avcodec_alloc_frame(void); + +/** + * Set the fields of the given AVFrame to default values. + * + * @param frame The AVFrame of which the fields should be set to default values. + */ +void avcodec_get_frame_defaults(AVFrame *frame); + +/** + * Free the frame and any dynamically allocated objects in it, + * e.g. extended_data. + * + * @param frame frame to be freed. The pointer will be set to NULL. + * + * @warning this function does NOT free the data buffers themselves + * (it does not know how, since they might have been allocated with + * a custom get_buffer()). + */ +void avcodec_free_frame(AVFrame **frame); + +#if FF_API_AVCODEC_OPEN +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated. + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @code + * avcodec_register_all(); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open(context, codec) < 0) + * exit(1); + * @endcode + * + * @param avctx The context which will be set up to use the given codec. + * @param codec The codec to use within the context. + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3, avcodec_find_decoder, avcodec_find_encoder, avcodec_close + * + * @deprecated use avcodec_open2 + */ +attribute_deprecated +int avcodec_open(AVCodecContext *avctx, AVCodec *codec); +#endif + +/** + * Initialize the AVCodecContext to use the given AVCodec. Prior to using this + * function the context has to be allocated with avcodec_alloc_context3(). + * + * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(), + * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for + * retrieving a codec. + * + * @warning This function is not thread safe! + * + * @code + * avcodec_register_all(); + * av_dict_set(&opts, "b", "2.5M", 0); + * codec = avcodec_find_decoder(AV_CODEC_ID_H264); + * if (!codec) + * exit(1); + * + * context = avcodec_alloc_context3(codec); + * + * if (avcodec_open2(context, codec, opts) < 0) + * exit(1); + * @endcode + * + * @param avctx The context to initialize. + * @param codec The codec to open this context for. If a non-NULL codec has been + * previously passed to avcodec_alloc_context3() or + * avcodec_get_context_defaults3() for this context, then this + * parameter MUST be either NULL or equal to the previously passed + * codec. + * @param options A dictionary filled with AVCodecContext and codec-private options. + * On return this object will be filled with options that were not found. + * + * @return zero on success, a negative value on error + * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), + * av_dict_set(), av_opt_find(). + */ +int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Close a given AVCodecContext and free all the data associated with it + * (but not the AVCodecContext itself). + * + * Calling this function on an AVCodecContext that hasn't been opened will free + * the codec-specific data allocated in avcodec_alloc_context3() / + * avcodec_get_context_defaults3() with a non-NULL codec. Subsequent calls will + * do nothing. + */ +int avcodec_close(AVCodecContext *avctx); + +/** + * Free all allocated data in the given subtitle struct. + * + * @param sub AVSubtitle to free. + */ +void avsubtitle_free(AVSubtitle *sub); + +/** + * @} + */ + +/** + * @addtogroup lavc_packet + * @{ + */ + +#if FF_API_DESTRUCT_PACKET +/** + * Default packet destructor. + * @deprecated use the AVBuffer API instead + */ +attribute_deprecated +void av_destruct_packet(AVPacket *pkt); +#endif + +/** + * Initialize optional fields of a packet with default values. + * + * Note, this does not touch the data and size members, which have to be + * initialized separately. + * + * @param pkt packet + */ +void av_init_packet(AVPacket *pkt); + +/** + * Allocate the payload of a packet and initialize its fields with + * default values. + * + * @param pkt packet + * @param size wanted payload size + * @return 0 if OK, AVERROR_xxx otherwise + */ +int av_new_packet(AVPacket *pkt, int size); + +/** + * Reduce packet size, correctly zeroing padding + * + * @param pkt packet + * @param size new size + */ +void av_shrink_packet(AVPacket *pkt, int size); + +/** + * Increase packet size, correctly zeroing padding + * + * @param pkt packet + * @param grow_by number of bytes by which to increase the size of the packet + */ +int av_grow_packet(AVPacket *pkt, int grow_by); + +/** + * Initialize a reference-counted packet from av_malloc()ed data. + * + * @param pkt packet to be initialized. This function will set the data, size, + * buf and destruct fields, all others are left untouched. + * @param data Data allocated by av_malloc() to be used as packet data. If this + * function returns successfully, the data is owned by the underlying AVBuffer. + * The caller may not access the data through other means. + * @param size size of data in bytes, without the padding. I.e. the full buffer + * size is assumed to be size + FF_INPUT_BUFFER_PADDING_SIZE. + * + * @return 0 on success, a negative AVERROR on error + */ +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size); + +/** + * @warning This is a hack - the packet memory allocation stuff is broken. The + * packet is allocated if it was not really allocated. + */ +int av_dup_packet(AVPacket *pkt); + +/** + * Copy packet, including contents + * + * @return 0 on success, negative AVERROR on fail + */ +int av_copy_packet(AVPacket *dst, AVPacket *src); + +/** + * Free a packet. + * + * @param pkt packet to free + */ +void av_free_packet(AVPacket *pkt); + +/** + * Allocate new information of a packet. + * + * @param pkt packet + * @param type side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); + +/** + * Shrink the already allocated side data buffer + * + * @param pkt packet + * @param type side information type + * @param size new side information size + * @return 0 on success, < 0 on failure + */ +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size); + +/** + * Get side information from packet. + * + * @param pkt packet + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t* av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int *size); + +int av_packet_merge_side_data(AVPacket *pkt); + +int av_packet_split_side_data(AVPacket *pkt); + + +/** + * @} + */ + +/** + * @addtogroup lavc_decoding + * @{ + */ + +/** + * Find a registered decoder with a matching codec ID. + * + * @param id AVCodecID of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder(enum AVCodecID id); + +/** + * Find a registered decoder with the specified name. + * + * @param name name of the requested decoder + * @return A decoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_decoder_by_name(const char *name); + +#if FF_API_GET_BUFFER +attribute_deprecated int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); +attribute_deprecated void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); +attribute_deprecated int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); +#endif + +/** + * The default callback for AVCodecContext.get_buffer2(). It is made public so + * it can be called by custom get_buffer2() implementations for decoders without + * CODEC_CAP_DR1 set. + */ +int avcodec_default_get_buffer2(AVCodecContext *s, AVFrame *frame, int flags); + +/** + * Return the amount of padding in pixels which the get_buffer callback must + * provide around the edge of the image for codecs which do not have the + * CODEC_FLAG_EMU_EDGE flag. + * + * @return Required padding in pixels. + */ +unsigned avcodec_get_edge_width(void); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you do not use any horizontal + * padding. + * + * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased + * according to avcodec_get_edge_width() before. + */ +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); + +/** + * Modify width and height values so that they will result in a memory + * buffer that is acceptable for the codec if you also ensure that all + * line sizes are a multiple of the respective linesize_align[i]. + * + * May only be used if a codec with CODEC_CAP_DR1 has been opened. + * If CODEC_FLAG_EMU_EDGE is not set, the dimensions must have been increased + * according to avcodec_get_edge_width() before. + */ +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]); + +#if FF_API_OLD_DECODE_AUDIO +/** + * Wrapper function which calls avcodec_decode_audio4. + * + * @deprecated Use avcodec_decode_audio4 instead. + * + * Decode the audio frame of size avpkt->size from avpkt->data into samples. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. In this case, + * avcodec_decode_audio3 has to be called again with an AVPacket that contains + * the remaining data in order to decode the second frame etc. + * If no frame + * could be outputted, frame_size_ptr is zero. Otherwise, it is the + * decompressed frame size in bytes. + * + * @warning You must set frame_size_ptr to the allocated size of the + * output buffer before calling avcodec_decode_audio3(). + * + * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer avpkt->data should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @warning You must not provide a custom get_buffer() when using + * avcodec_decode_audio3(). Doing so will override it with + * avcodec_default_get_buffer. Use avcodec_decode_audio4() instead, + * which does allow the application to provide a custom get_buffer(). + * + * @note You might have to align the input buffer avpkt->data and output buffer + * samples. The alignment requirements depend on the CPU: On some CPUs it isn't + * necessary at all, on others it won't work at all if not aligned and on others + * it will work but it will have an impact on performance. + * + * In practice, avpkt->data should have 4 byte alignment at minimum and + * samples should be 16 byte aligned unless the CPU doesn't need it + * (AltiVec and SSE do). + * + * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @param avctx the codec context + * @param[out] samples the output buffer, sample type in avctx->sample_fmt + * If the sample format is planar, each channel plane will + * be the same size, with no padding between channels. + * @param[in,out] frame_size_ptr the output buffer size in bytes + * @param[in] avpkt The input AVPacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields. + * All decoders are designed to use the least fields possible though. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame data was decompressed (used) from the input AVPacket. + */ +attribute_deprecated int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, + int *frame_size_ptr, + AVPacket *avpkt); +#endif + +/** + * Decode the audio frame of size avpkt->size from avpkt->data into frame. + * + * Some decoders may support multiple frames in a single AVPacket. Such + * decoders would then just decode the first frame. In this case, + * avcodec_decode_audio4 has to be called again with an AVPacket containing + * the remaining data in order to decode the second frame, etc... + * Even if no frames are returned, the packet needs to be fed to the decoder + * with remaining data until it is completely consumed or an error occurs. + * + * @warning The input buffer, avpkt->data must be FF_INPUT_BUFFER_PADDING_SIZE + * larger than the actual read bytes because some optimized bitstream + * readers read 32 or 64 bits at once and could read over the end. + * + * @note You might have to align the input buffer. The alignment requirements + * depend on the CPU and the decoder. + * + * @param avctx the codec context + * @param[out] frame The AVFrame in which to store decoded audio samples. + * The decoder will allocate a buffer for the decoded frame by + * calling the AVCodecContext.get_buffer2() callback. + * When AVCodecContext.refcounted_frames is set to 1, the frame is + * reference counted and the returned reference belongs to the + * caller. The caller must release the frame using av_frame_unref() + * when the frame is no longer needed. The caller may safely write + * to the frame if av_frame_is_writable() returns 1. + * When AVCodecContext.refcounted_frames is set to 0, the returned + * reference belongs to the decoder and is valid only until the + * next call to this function or until closing the decoder. + * The caller may not write to it. + * @param[out] got_frame_ptr Zero if no frame could be decoded, otherwise it is + * non-zero. + * @param[in] avpkt The input AVPacket containing the input buffer. + * At least avpkt->data and avpkt->size should be set. Some + * decoders might also require additional fields to be set. + * @return A negative error code is returned if an error occurred during + * decoding, otherwise the number of bytes consumed from the input + * AVPacket is returned. + */ +int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, const AVPacket *avpkt); + +/** + * Decode the video frame of size avpkt->size from avpkt->data into picture. + * Some decoders may support multiple frames in a single AVPacket, such + * decoders would then just decode the first frame. + * + * @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than + * the actual read bytes because some optimized bitstream readers read 32 or 64 + * bits at once and could read over the end. + * + * @warning The end of the input buffer buf should be set to 0 to ensure that + * no overreading happens for damaged MPEG streams. + * + * @note You might have to align the input buffer avpkt->data. + * The alignment requirements depend on the CPU: on some CPUs it isn't + * necessary at all, on others it won't work at all if not aligned and on others + * it will work but it will have an impact on performance. + * + * In practice, avpkt->data should have 4 byte alignment at minimum. + * + * @note Codecs which have the CODEC_CAP_DELAY capability set have a delay + * between input and output, these need to be fed with avpkt->data=NULL, + * avpkt->size=0 at the end to return the remaining frames. + * + * @param avctx the codec context + * @param[out] picture The AVFrame in which the decoded video frame will be stored. + * Use av_frame_alloc() to get an AVFrame. The codec will + * allocate memory for the actual bitmap by calling the + * AVCodecContext.get_buffer2() callback. + * When AVCodecContext.refcounted_frames is set to 1, the frame is + * reference counted and the returned reference belongs to the + * caller. The caller must release the frame using av_frame_unref() + * when the frame is no longer needed. The caller may safely write + * to the frame if av_frame_is_writable() returns 1. + * When AVCodecContext.refcounted_frames is set to 0, the returned + * reference belongs to the decoder and is valid only until the + * next call to this function or until closing the decoder. The + * caller may not write to it. + * + * @param[in] avpkt The input AVpacket containing the input buffer. + * You can create such packet with av_init_packet() and by then setting + * data and size, some decoders might in addition need other fields like + * flags&AV_PKT_FLAG_KEY. All decoders are designed to use the least + * fields possible. + * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero. + * @return On error a negative value is returned, otherwise the number of bytes + * used or zero if no frame could be decompressed. + */ +int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + const AVPacket *avpkt); + +/** + * Decode a subtitle message. + * Return a negative value on error, otherwise return the number of bytes used. + * If no subtitle could be decompressed, got_sub_ptr is zero. + * Otherwise, the subtitle is stored in *sub. + * Note that CODEC_CAP_DR1 is not available for subtitle codecs. This is for + * simplicity, because the performance difference is expect to be negligible + * and reusing a get_buffer written for video codecs would probably perform badly + * due to a potentially very different allocation pattern. + * + * @param avctx the codec context + * @param[out] sub The AVSubtitle in which the decoded subtitle will be stored, must be + freed with avsubtitle_free if *got_sub_ptr is set. + * @param[in,out] got_sub_ptr Zero if no subtitle could be decompressed, otherwise, it is nonzero. + * @param[in] avpkt The input AVPacket containing the input buffer. + */ +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt); + +/** + * @defgroup lavc_parsing Frame parsing + * @{ + */ + +typedef struct AVCodecParserContext { + void *priv_data; + struct AVCodecParser *parser; + int64_t frame_offset; /* offset of the current frame */ + int64_t cur_offset; /* current offset + (incremented by each av_parser_parse()) */ + int64_t next_frame_offset; /* offset of the next frame */ + /* video info */ + int pict_type; /* XXX: Put it back in AVCodecContext. */ + /** + * This field is used for proper frame duration computation in lavf. + * It signals, how much longer the frame duration of the current frame + * is compared to normal frame duration. + * + * frame_duration = (1 + repeat_pict) * time_base + * + * It is used by codecs like H.264 to display telecined material. + */ + int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int64_t pts; /* pts of the current frame */ + int64_t dts; /* dts of the current frame */ + + /* private data */ + int64_t last_pts; + int64_t last_dts; + int fetch_timestamp; + +#define AV_PARSER_PTS_NB 4 + int cur_frame_start_index; + int64_t cur_frame_offset[AV_PARSER_PTS_NB]; + int64_t cur_frame_pts[AV_PARSER_PTS_NB]; + int64_t cur_frame_dts[AV_PARSER_PTS_NB]; + + int flags; +#define PARSER_FLAG_COMPLETE_FRAMES 0x0001 +#define PARSER_FLAG_ONCE 0x0002 +/// Set if the parser has a valid file offset +#define PARSER_FLAG_FETCHED_OFFSET 0x0004 +#define PARSER_FLAG_USE_CODEC_TS 0x1000 + + int64_t offset; ///< byte offset from starting packet start + int64_t cur_frame_end[AV_PARSER_PTS_NB]; + + /** + * Set by parser to 1 for key frames and 0 for non-key frames. + * It is initialized to -1, so if the parser doesn't set this flag, + * old-style fallback using AV_PICTURE_TYPE_I picture type as key frames + * will be used. + */ + int key_frame; + + /** + * Time difference in stream time base units from the pts of this + * packet to the point at which the output from the decoder has converged + * independent from the availability of previous frames. That is, the + * frames are virtually identical no matter if decoding started from + * the very first frame or from this keyframe. + * Is AV_NOPTS_VALUE if unknown. + * This field is not the display duration of the current frame. + * This field has no meaning if the packet does not have AV_PKT_FLAG_KEY + * set. + * + * The purpose of this field is to allow seeking in streams that have no + * keyframes in the conventional sense. It corresponds to the + * recovery point SEI in H.264 and match_time_delta in NUT. It is also + * essential for some types of subtitle streams to ensure that all + * subtitles are correctly displayed after seeking. + */ + int64_t convergence_duration; + + // Timestamp generation support: + /** + * Synchronization point for start of timestamp generation. + * + * Set to >0 for sync point, 0 for no sync point and <0 for undefined + * (default). + * + * For example, this corresponds to presence of H.264 buffering period + * SEI message. + */ + int dts_sync_point; + + /** + * Offset of the current timestamp against last timestamp sync point in + * units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain a valid timestamp offset. + * + * Note that the timestamp of sync point has usually a nonzero + * dts_ref_dts_delta, which refers to the previous sync point. Offset of + * the next frame after timestamp sync point will be usually 1. + * + * For example, this corresponds to H.264 cpb_removal_delay. + */ + int dts_ref_dts_delta; + + /** + * Presentation delay of current frame in units of AVCodecContext.time_base. + * + * Set to INT_MIN when dts_sync_point unused. Otherwise, it must + * contain valid non-negative timestamp delta (presentation time of a frame + * must not lie in the past). + * + * This delay represents the difference between decoding and presentation + * time of the frame. + * + * For example, this corresponds to H.264 dpb_output_delay. + */ + int pts_dts_delta; + + /** + * Position of the packet in file. + * + * Analogous to cur_frame_pts/dts + */ + int64_t cur_frame_pos[AV_PARSER_PTS_NB]; + + /** + * Byte position of currently parsed frame in stream. + */ + int64_t pos; + + /** + * Previous frame byte position. + */ + int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; +} AVCodecParserContext; + +typedef struct AVCodecParser { + int codec_ids[5]; /* several codec IDs are permitted */ + int priv_data_size; + int (*parser_init)(AVCodecParserContext *s); + int (*parser_parse)(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size); + void (*parser_close)(AVCodecParserContext *s); + int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size); + struct AVCodecParser *next; +} AVCodecParser; + +AVCodecParser *av_parser_next(AVCodecParser *c); + +void av_register_codec_parser(AVCodecParser *parser); +AVCodecParserContext *av_parser_init(int codec_id); + +/** + * Parse a packet. + * + * @param s parser context. + * @param avctx codec context. + * @param poutbuf set to pointer to parsed buffer or NULL if not yet finished. + * @param poutbuf_size set to size of parsed buffer or zero if not yet finished. + * @param buf input buffer. + * @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output). + * @param pts input presentation timestamp. + * @param dts input decoding timestamp. + * @param pos input byte position in stream. + * @return the number of bytes of the input bitstream used. + * + * Example: + * @code + * while(in_len){ + * len = av_parser_parse2(myparser, AVCodecContext, &data, &size, + * in_data, in_len, + * pts, dts, pos); + * in_data += len; + * in_len -= len; + * + * if(size) + * decode_frame(data, size); + * } + * @endcode + */ +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos); + +/** + * @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed + * @deprecated use AVBitstreamFilter + */ +int av_parser_change(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +void av_parser_close(AVCodecParserContext *s); + +/** + * @} + * @} + */ + +/** + * @addtogroup lavc_encoding + * @{ + */ + +/** + * Find a registered encoder with a matching codec ID. + * + * @param id AVCodecID of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder(enum AVCodecID id); + +/** + * Find a registered encoder with the specified name. + * + * @param name name of the requested encoder + * @return An encoder if one was found, NULL otherwise. + */ +AVCodec *avcodec_find_encoder_by_name(const char *name); + +#if FF_API_OLD_ENCODE_AUDIO +/** + * Encode an audio frame from samples into buf. + * + * @deprecated Use avcodec_encode_audio2 instead. + * + * @note The output buffer should be at least FF_MIN_BUFFER_SIZE bytes large. + * However, for codecs with avctx->frame_size equal to 0 (e.g. PCM) the user + * will know how much space is needed because it depends on the value passed + * in buf_size as described below. In that case a lower value can be used. + * + * @param avctx the codec context + * @param[out] buf the output buffer + * @param[in] buf_size the output buffer size + * @param[in] samples the input buffer containing the samples + * The number of samples read from this buffer is frame_size*channels, + * both of which are defined in avctx. + * For codecs which have avctx->frame_size equal to 0 (e.g. PCM) the number of + * samples read from samples is equal to: + * buf_size * 8 / (avctx->channels * av_get_bits_per_sample(avctx->codec_id)) + * This also implies that av_get_bits_per_sample() must not return 0 for these + * codecs. + * @return On error a negative value is returned, on success zero or the number + * of bytes used to encode the data read from the input buffer. + */ +int attribute_deprecated avcodec_encode_audio(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const short *samples); +#endif + +/** + * Encode a frame of audio. + * + * Takes input samples from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay, split, and combine input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. If avpkt->data and + * avpkt->size are set, avpkt->destruct must also be set. All + * other AVPacket fields will be reset by the encoder using + * av_init_packet(). If avpkt->data is NULL, the encoder will + * allocate it. The encoder will set avpkt->size to the size + * of the output packet. + * + * If this function fails or produces no output, avpkt will be + * freed using av_free_packet() (i.e. avpkt->destruct will be + * called to free the user supplied buffer). + * @param[in] frame AVFrame containing the raw audio data to be encoded. + * May be NULL when flushing an encoder that has the + * CODEC_CAP_DELAY capability set. + * If CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame + * can have any number of samples. + * If it is not set, frame->nb_samples must be equal to + * avctx->frame_size for all frames except the last. + * The final frame may be smaller than avctx->frame_size. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + */ +int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +#if FF_API_OLD_ENCODE_VIDEO +/** + * @deprecated use avcodec_encode_video2() instead. + * + * Encode a video frame from pict into buf. + * The input picture should be + * stored using a specific format, namely avctx.pix_fmt. + * + * @param avctx the codec context + * @param[out] buf the output buffer for the bitstream of encoded frame + * @param[in] buf_size the size of the output buffer in bytes + * @param[in] pict the input picture to encode + * @return On error a negative value is returned, on success zero or the number + * of bytes used from the output buffer. + */ +attribute_deprecated +int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict); +#endif + +/** + * Encode a frame of video. + * + * Takes input raw video data from frame and writes the next output packet, if + * available, to avpkt. The output packet does not necessarily contain data for + * the most recent frame, as encoders can delay and reorder input frames + * internally as needed. + * + * @param avctx codec context + * @param avpkt output AVPacket. + * The user can supply an output buffer by setting + * avpkt->data and avpkt->size prior to calling the + * function, but if the size of the user-provided data is not + * large enough, encoding will fail. All other AVPacket fields + * will be reset by the encoder using av_init_packet(). If + * avpkt->data is NULL, the encoder will allocate it. + * The encoder will set avpkt->size to the size of the + * output packet. The returned data (if any) belongs to the + * caller, he is responsible for freeing it. + * + * If this function fails or produces no output, avpkt will be + * freed using av_free_packet() (i.e. avpkt->destruct will be + * called to free the user supplied buffer). + * @param[in] frame AVFrame containing the raw video data to be encoded. + * May be NULL when flushing an encoder that has the + * CODEC_CAP_DELAY capability set. + * @param[out] got_packet_ptr This field is set to 1 by libavcodec if the + * output packet is non-empty, and to 0 if it is + * empty. If the function returns an error, the + * packet can be assumed to be invalid, and the + * value of got_packet_ptr is undefined and should + * not be used. + * @return 0 on success, negative error code on failure + */ +int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr); + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub); + + +/** + * @} + */ + +#if FF_API_AVCODEC_RESAMPLE +/** + * @defgroup lavc_resample Audio resampling + * @ingroup libavc + * @deprecated use libswresample instead + * + * @{ + */ +struct ReSampleContext; +struct AVResampleContext; + +typedef struct ReSampleContext ReSampleContext; + +/** + * Initialize audio resampling context. + * + * @param output_channels number of output channels + * @param input_channels number of input channels + * @param output_rate output sample rate + * @param input_rate input sample rate + * @param sample_fmt_out requested output sample format + * @param sample_fmt_in input sample format + * @param filter_length length of each FIR filter in the filterbank relative to the cutoff frequency + * @param log2_phase_count log2 of the number of entries in the polyphase filterbank + * @param linear if 1 then the used FIR filter will be linearly interpolated + between the 2 closest, if 0 the closest will be used + * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate + * @return allocated ReSampleContext, NULL if error occurred + */ +attribute_deprecated +ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, + int output_rate, int input_rate, + enum AVSampleFormat sample_fmt_out, + enum AVSampleFormat sample_fmt_in, + int filter_length, int log2_phase_count, + int linear, double cutoff); + +attribute_deprecated +int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples); + +/** + * Free resample context. + * + * @param s a non-NULL pointer to a resample context previously + * created with av_audio_resample_init() + */ +attribute_deprecated +void audio_resample_close(ReSampleContext *s); + + +/** + * Initialize an audio resampler. + * Note, if either rate is not an integer then simply scale both rates up so they are. + * @param filter_length length of each FIR filter in the filterbank relative to the cutoff freq + * @param log2_phase_count log2 of the number of entries in the polyphase filterbank + * @param linear If 1 then the used FIR filter will be linearly interpolated + between the 2 closest, if 0 the closest will be used + * @param cutoff cutoff frequency, 1.0 corresponds to half the output sampling rate + */ +attribute_deprecated +struct AVResampleContext *av_resample_init(int out_rate, int in_rate, int filter_length, int log2_phase_count, int linear, double cutoff); + +/** + * Resample an array of samples using a previously configured context. + * @param src an array of unconsumed samples + * @param consumed the number of samples of src which have been consumed are returned here + * @param src_size the number of unconsumed samples available + * @param dst_size the amount of space in samples available in dst + * @param update_ctx If this is 0 then the context will not be modified, that way several channels can be resampled with the same context. + * @return the number of samples written in dst or -1 if an error occurred + */ +attribute_deprecated +int av_resample(struct AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx); + + +/** + * Compensate samplerate/timestamp drift. The compensation is done by changing + * the resampler parameters, so no audible clicks or similar distortions occur + * @param compensation_distance distance in output samples over which the compensation should be performed + * @param sample_delta number of output samples which should be output less + * + * example: av_resample_compensate(c, 10, 500) + * here instead of 510 samples only 500 samples would be output + * + * note, due to rounding the actual compensation might be slightly different, + * especially if the compensation_distance is large and the in_rate used during init is small + */ +attribute_deprecated +void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int compensation_distance); +attribute_deprecated +void av_resample_close(struct AVResampleContext *c); + +/** + * @} + */ +#endif + +/** + * @addtogroup lavc_picture + * @{ + */ + +/** + * Allocate memory for a picture. Call avpicture_free() to free it. + * + * @see avpicture_fill() + * + * @param picture the picture to be filled in + * @param pix_fmt the format of the picture + * @param width the width of the picture + * @param height the height of the picture + * @return zero if successful, a negative value if not + */ +int avpicture_alloc(AVPicture *picture, enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Free a picture previously allocated by avpicture_alloc(). + * The data buffer used by the AVPicture is freed, but the AVPicture structure + * itself is not. + * + * @param picture the AVPicture to be freed + */ +void avpicture_free(AVPicture *picture); + +/** + * Fill in the AVPicture fields, always assume a linesize alignment of + * 1. + * + * @see av_image_fill_arrays() + */ +int avpicture_fill(AVPicture *picture, const uint8_t *ptr, + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Copy pixel data from an AVPicture into a buffer, always assume a + * linesize alignment of 1. + * + * @see av_image_copy_to_buffer() + */ +int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, + int width, int height, + unsigned char *dest, int dest_size); + +/** + * Calculate the size in bytes that a picture of the given width and height + * would occupy if stored in the given picture format. + * Always assume a linesize alignment of 1. + * + * @see av_image_get_buffer_size(). + */ +int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height); + +#if FF_API_DEINTERLACE +/** + * deinterlace - if not supported return -1 + * + * @deprecated - use yadif (in libavfilter) instead + */ +attribute_deprecated +int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height); +#endif +/** + * Copy image src to dst. Wraps av_image_copy(). + */ +void av_picture_copy(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height); + +/** + * Crop image top and left side. + */ +int av_picture_crop(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int top_band, int left_band); + +/** + * Pad image. + */ +int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, enum AVPixelFormat pix_fmt, + int padtop, int padbottom, int padleft, int padright, int *color); + +/** + * @} + */ + +/** + * @defgroup lavc_misc Utility functions + * @ingroup libavc + * + * Miscellaneous utility functions related to both encoding and decoding + * (or neither). + * @{ + */ + +/** + * @defgroup lavc_misc_pixfmt Pixel formats + * + * Functions for working with pixel formats. + * @{ + */ + +/** + * Utility function to access log2_chroma_w log2_chroma_h from + * the pixel format AVPixFmtDescriptor. + * + * This function asserts that pix_fmt is valid. See av_pix_fmt_get_chroma_sub_sample + * for one that returns a failure code and continues in case of invalid + * pix_fmts. + * + * @param[in] pix_fmt the pixel format + * @param[out] h_shift store log2_chroma_w + * @param[out] v_shift store log2_chroma_h + * + * @see av_pix_fmt_get_chroma_sub_sample + */ + +void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift); + +/** + * Return a value representing the fourCC code associated to the + * pixel format pix_fmt, or 0 if no associated fourCC code can be + * found. + */ +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat pix_fmt); + +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * avcodec_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format. When converting from one pixel format to another, information loss + * may occur. For example, when converting from RGB24 to GRAY, the color + * information will be lost. Similarly, other losses occur when converting from + * some formats to other formats. avcodec_find_best_pix_fmt_of_2() searches which of + * the given pixel formats should be used to suffer the least amount of loss. + * The pixel formats from which it chooses one, are determined by the + * pix_fmt_list parameter. + * + * + * @param[in] pix_fmt_list AV_PIX_FMT_NONE terminated array of pixel formats to choose from + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[out] loss_ptr Combination of flags informing you what kind of losses will occur. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); + +/** + * Find the best pixel format to convert to given a certain source pixel + * format and a selection of two destination pixel formats. When converting from + * one pixel format to another, information loss may occur. For example, when converting + * from RGB24 to GRAY, the color information will be lost. Similarly, other losses occur when + * converting from some formats to other formats. avcodec_find_best_pix_fmt_of_2() selects which of + * the given pixel formats should be used to suffer the least amount of loss. + * + * If one of the destination formats is AV_PIX_FMT_NONE the other pixel format (if valid) will be + * returned. + * + * @code + * src_pix_fmt = AV_PIX_FMT_YUV420P; + * dst_pix_fmt1= AV_PIX_FMT_RGB24; + * dst_pix_fmt2= AV_PIX_FMT_GRAY8; + * dst_pix_fmt3= AV_PIX_FMT_RGB8; + * loss= FF_LOSS_CHROMA; // don't care about chroma loss, so chroma loss will be ignored. + * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, alpha, &loss); + * dst_pix_fmt = avcodec_find_best_pix_fmt_of_2(dst_pix_fmt, dst_pix_fmt3, src_pix_fmt, alpha, &loss); + * @endcode + * + * @param[in] dst_pix_fmt1 One of the two destination pixel formats to choose from + * @param[in] dst_pix_fmt2 The other of the two destination pixel formats to choose from + * @param[in] src_pix_fmt Source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @param[in, out] loss_ptr Combination of loss flags. In: selects which of the losses to ignore, i.e. + * NULL or value of zero means we care about all losses. Out: the loss + * that occurs when converting from src to selected dst pixel format. + * @return The best pixel format to convert to or -1 if none was found. + */ +enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); + +attribute_deprecated +#if AV_HAVE_INCOMPATIBLE_FORK_ABI +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr); +#else +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); +#endif + + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + +/** + * @} + */ + +void avcodec_set_dimensions(AVCodecContext *s, int width, int height); + +/** + * Put a string representing the codec tag codec_tag in buf. + * + * @param buf_size size in bytes of buf + * @return the length of the string that would have been generated if + * enough space had been available, excluding the trailing null + */ +size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag); + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode); + +/** + * Return a name for the specified profile, if available. + * + * @param codec the codec that is searched for the given profile + * @param profile the profile value for which a name is requested + * @return A name for the profile if found, NULL otherwise. + */ +const char *av_get_profile_name(const AVCodec *codec, int profile); + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2),void *arg, int *ret, int count, int size); +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int, int),void *arg, int *ret, int count); +//FIXME func typedef + +/** + * Fill AVFrame audio data and linesize pointers. + * + * The buffer buf must be a preallocated buffer with a size big enough + * to contain the specified samples amount. The filled AVFrame data + * pointers will point to this buffer. + * + * AVFrame extended_data channel pointers are allocated if necessary for + * planar audio. + * + * @param frame the AVFrame + * frame->nb_samples must be set prior to calling the + * function. This function fills in frame->data, + * frame->extended_data, frame->linesize[0]. + * @param nb_channels channel count + * @param sample_fmt sample format + * @param buf buffer to use for frame data + * @param buf_size size of buffer + * @param align plane size sample alignment (0 = default) + * @return >=0 on success, negative error code on failure + * @todo return the size in bytes required to store the samples in + * case of success, at the next libavutil bump + */ +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align); + +/** + * Flush buffers, should be called when seeking or when switching to a different stream. + */ +void avcodec_flush_buffers(AVCodecContext *avctx); + +/** + * Return codec bits per sample. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return the PCM codec associated with a sample format. + * @param be endianness, 0 for little, 1 for big, + * -1 (or anything else) for native + * @return AV_CODEC_ID_PCM_* or AV_CODEC_ID_NONE + */ +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be); + +/** + * Return codec bits per sample. + * Only return non-zero if the bits per sample is exactly correct, not an + * approximation. + * + * @param[in] codec_id the codec + * @return Number of bits per sample or zero if unknown for the given codec. + */ +int av_get_exact_bits_per_sample(enum AVCodecID codec_id); + +/** + * Return audio frame duration. + * + * @param avctx codec context + * @param frame_bytes size of the frame, or 0 if unknown + * @return frame duration, in samples, if known. 0 if not able to + * determine. + */ +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes); + + +typedef struct AVBitStreamFilterContext { + void *priv_data; + struct AVBitStreamFilter *filter; + AVCodecParserContext *parser; + struct AVBitStreamFilterContext *next; +} AVBitStreamFilterContext; + + +typedef struct AVBitStreamFilter { + const char *name; + int priv_data_size; + int (*filter)(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); + void (*close)(AVBitStreamFilterContext *bsfc); + struct AVBitStreamFilter *next; +} AVBitStreamFilter; + +void av_register_bitstream_filter(AVBitStreamFilter *bsf); +AVBitStreamFilterContext *av_bitstream_filter_init(const char *name); +int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe); +void av_bitstream_filter_close(AVBitStreamFilterContext *bsf); + +AVBitStreamFilter *av_bitstream_filter_next(AVBitStreamFilter *f); + +/* memory */ + +/** + * Reallocate the given block if it is not large enough, otherwise do nothing. + * + * @see av_realloc + */ +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Allocate a buffer, reusing the given one if large enough. + * + * Contrary to av_fast_realloc the current buffer contents might not be + * preserved and on error the old buffer is freed, thus no special + * handling to avoid memleaks is necessary. + * + * @param ptr pointer to pointer to already allocated buffer, overwritten with pointer to new buffer + * @param size size of the buffer *ptr points to + * @param min_size minimum size of *ptr buffer after returning, *ptr will be NULL and + * *size 0 if an error occurred. + */ +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_malloc but the buffer has additional + * FF_INPUT_BUFFER_PADDING_SIZE at the end which will will always be 0. + * + * In addition the whole buffer will initially and after resizes + * be 0-initialized so that no uninitialized data will ever appear. + */ +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size); + +/** + * Same behaviour av_fast_padded_malloc except that buffer will always + * be 0-initialized after call. + */ +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size); + +/** + * Encode extradata length to a buffer. Used by xiph codecs. + * + * @param s buffer to write to; must be at least (v/255+1) bytes long + * @param v size of extradata in bytes + * @return number of bytes written to the buffer. + */ +unsigned int av_xiphlacing(unsigned char *s, unsigned int v); + +#if FF_API_MISSING_SAMPLE +/** + * Log a generic warning message about a missing feature. This function is + * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) + * only, and would normally not be used by applications. + * @param[in] avc a pointer to an arbitrary struct of which the first field is + * a pointer to an AVClass struct + * @param[in] feature string containing the name of the missing feature + * @param[in] want_sample indicates if samples are wanted which exhibit this feature. + * If want_sample is non-zero, additional verbage will be added to the log + * message which tells the user how to report samples to the development + * mailing list. + * @deprecated Use avpriv_report_missing_feature() instead. + */ +attribute_deprecated +void av_log_missing_feature(void *avc, const char *feature, int want_sample); + +/** + * Log a generic warning message asking for a sample. This function is + * intended to be used internally by FFmpeg (libavcodec, libavformat, etc.) + * only, and would normally not be used by applications. + * @param[in] avc a pointer to an arbitrary struct of which the first field is + * a pointer to an AVClass struct + * @param[in] msg string containing an optional message, or NULL if no message + * @deprecated Use avpriv_request_sample() instead. + */ +attribute_deprecated +void av_log_ask_for_sample(void *avc, const char *msg, ...) av_printf_format(2, 3); +#endif /* FF_API_MISSING_SAMPLE */ + +/** + * Register the hardware accelerator hwaccel. + */ +void av_register_hwaccel(AVHWAccel *hwaccel); + +/** + * If hwaccel is NULL, returns the first registered hardware accelerator, + * if hwaccel is non-NULL, returns the next registered hardware accelerator + * after hwaccel, or NULL if hwaccel is the last one. + */ +AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel); + + +/** + * Lock operation used by lockmgr + */ +enum AVLockOp { + AV_LOCK_CREATE, ///< Create a mutex + AV_LOCK_OBTAIN, ///< Lock the mutex + AV_LOCK_RELEASE, ///< Unlock the mutex + AV_LOCK_DESTROY, ///< Free mutex resources +}; + +/** + * Register a user provided lock manager supporting the operations + * specified by AVLockOp. mutex points to a (void *) where the + * lockmgr should store/get a pointer to a user allocated mutex. It's + * NULL upon AV_LOCK_CREATE and != NULL for all other ops. + * + * @param cb User defined callback. Note: FFmpeg may invoke calls to this + * callback during the call to av_lockmgr_register(). + * Thus, the application must be prepared to handle that. + * If cb is set to NULL the lockmgr will be unregistered. + * Also note that during unregistration the previously registered + * lockmgr callback may also be invoked. + */ +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)); + +/** + * Get the type of the given codec. + */ +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id); + +/** + * Get the name of a codec. + * @return a static string identifying the codec; never NULL + */ +const char *avcodec_get_name(enum AVCodecID id); + +/** + * @return a positive value if s is open (i.e. avcodec_open2() was called on it + * with no corresponding avcodec_close()), 0 otherwise. + */ +int avcodec_is_open(AVCodecContext *s); + +/** + * @return a non-zero number if codec is an encoder, zero otherwise + */ +int av_codec_is_encoder(const AVCodec *codec); + +/** + * @return a non-zero number if codec is a decoder, zero otherwise + */ +int av_codec_is_decoder(const AVCodec *codec); + +/** + * @return descriptor for given codec ID or NULL if no descriptor exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); + +/** + * Iterate over all codec descriptors known to libavcodec. + * + * @param prev previous descriptor. NULL to get the first descriptor. + * + * @return next descriptor or NULL after the last descriptor + */ +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); + +/** + * @return codec descriptor with the given name or NULL if no such descriptor + * exists. + */ +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); + +/** + * @} + */ + +#endif /* AVCODEC_AVCODEC_H */ diff --git a/ffmpeg/libavcodec/avfft.c b/ffmpeg/libavcodec/avfft.c new file mode 100644 index 0000000..9e0ddaa --- /dev/null +++ b/ffmpeg/libavcodec/avfft.c @@ -0,0 +1,144 @@ +/* + * 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 "libavutil/mem.h" +#include "avfft.h" +#include "fft.h" +#include "rdft.h" +#include "dct.h" + +/* FFT */ + +FFTContext *av_fft_init(int nbits, int inverse) +{ + FFTContext *s = av_malloc(sizeof(*s)); + + if (s && ff_fft_init(s, nbits, inverse)) + av_freep(&s); + + return s; +} + +void av_fft_permute(FFTContext *s, FFTComplex *z) +{ + s->fft_permute(s, z); +} + +void av_fft_calc(FFTContext *s, FFTComplex *z) +{ + s->fft_calc(s, z); +} + +void av_fft_end(FFTContext *s) +{ + if (s) { + ff_fft_end(s); + av_free(s); + } +} + +#if CONFIG_MDCT + +FFTContext *av_mdct_init(int nbits, int inverse, double scale) +{ + FFTContext *s = av_malloc(sizeof(*s)); + + if (s && ff_mdct_init(s, nbits, inverse, scale)) + av_freep(&s); + + return s; +} + +void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + s->imdct_calc(s, output, input); +} + +void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + s->imdct_half(s, output, input); +} + +void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + s->mdct_calc(s, output, input); +} + +void av_mdct_end(FFTContext *s) +{ + if (s) { + ff_mdct_end(s); + av_free(s); + } +} + +#endif /* CONFIG_MDCT */ + +#if CONFIG_RDFT + +RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans) +{ + RDFTContext *s = av_malloc(sizeof(*s)); + + if (s && ff_rdft_init(s, nbits, trans)) + av_freep(&s); + + return s; +} + +void av_rdft_calc(RDFTContext *s, FFTSample *data) +{ + s->rdft_calc(s, data); +} + +void av_rdft_end(RDFTContext *s) +{ + if (s) { + ff_rdft_end(s); + av_free(s); + } +} + +#endif /* CONFIG_RDFT */ + +#if CONFIG_DCT + +DCTContext *av_dct_init(int nbits, enum DCTTransformType inverse) +{ + DCTContext *s = av_malloc(sizeof(*s)); + + if (s && ff_dct_init(s, nbits, inverse)) + av_freep(&s); + + return s; +} + +void av_dct_calc(DCTContext *s, FFTSample *data) +{ + s->dct_calc(s, data); +} + +void av_dct_end(DCTContext *s) +{ + if (s) { + ff_dct_end(s); + av_free(s); + } +} + +#endif /* CONFIG_DCT */ diff --git a/ffmpeg/libavcodec/avfft.h b/ffmpeg/libavcodec/avfft.h new file mode 100644 index 0000000..2d20a45 --- /dev/null +++ b/ffmpeg/libavcodec/avfft.h @@ -0,0 +1,116 @@ +/* + * 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 + */ + +#ifndef AVCODEC_AVFFT_H +#define AVCODEC_AVFFT_H + +/** + * @file + * @ingroup lavc_fft + * FFT functions + */ + +/** + * @defgroup lavc_fft FFT functions + * @ingroup lavc_misc + * + * @{ + */ + +typedef float FFTSample; + +typedef struct FFTComplex { + FFTSample re, im; +} FFTComplex; + +typedef struct FFTContext FFTContext; + +/** + * Set up a complex FFT. + * @param nbits log2 of the length of the input array + * @param inverse if 0 perform the forward transform, if 1 perform the inverse + */ +FFTContext *av_fft_init(int nbits, int inverse); + +/** + * Do the permutation needed BEFORE calling ff_fft_calc(). + */ +void av_fft_permute(FFTContext *s, FFTComplex *z); + +/** + * Do a complex FFT with the parameters defined in av_fft_init(). The + * input data must be permuted before. No 1.0/sqrt(n) normalization is done. + */ +void av_fft_calc(FFTContext *s, FFTComplex *z); + +void av_fft_end(FFTContext *s); + +FFTContext *av_mdct_init(int nbits, int inverse, double scale); +void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input); +void av_mdct_end(FFTContext *s); + +/* Real Discrete Fourier Transform */ + +enum RDFTransformType { + DFT_R2C, + IDFT_C2R, + IDFT_R2C, + DFT_C2R, +}; + +typedef struct RDFTContext RDFTContext; + +/** + * Set up a real FFT. + * @param nbits log2 of the length of the input array + * @param trans the type of transform + */ +RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans); +void av_rdft_calc(RDFTContext *s, FFTSample *data); +void av_rdft_end(RDFTContext *s); + +/* Discrete Cosine Transform */ + +typedef struct DCTContext DCTContext; + +enum DCTTransformType { + DCT_II = 0, + DCT_III, + DCT_I, + DST_I, +}; + +/** + * Set up DCT. + * @param nbits size of the input array: + * (1 << nbits) for DCT-II, DCT-III and DST-I + * (1 << nbits) + 1 for DCT-I + * + * @note the first element of the input of DST-I is ignored + */ +DCTContext *av_dct_init(int nbits, enum DCTTransformType type); +void av_dct_calc(DCTContext *s, FFTSample *data); +void av_dct_end (DCTContext *s); + +/** + * @} + */ + +#endif /* AVCODEC_AVFFT_H */ diff --git a/ffmpeg/libavcodec/avpacket.c b/ffmpeg/libavcodec/avpacket.c new file mode 100644 index 0000000..651036e --- /dev/null +++ b/ffmpeg/libavcodec/avpacket.c @@ -0,0 +1,400 @@ +/* + * AVPacket functions for libavcodec + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * 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 "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/mem.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +void ff_packet_free_side_data(AVPacket *pkt) +{ + int i; + for (i = 0; i < pkt->side_data_elems; i++) + av_free(pkt->side_data[i].data); + av_freep(&pkt->side_data); + pkt->side_data_elems = 0; +} + +#if FF_API_DESTRUCT_PACKET +void av_destruct_packet(AVPacket *pkt) +{ + av_free(pkt->data); + pkt->data = NULL; + pkt->size = 0; +} + +/* a dummy destruct callback for the callers that assume AVPacket.destruct == + * NULL => static data */ +static void dummy_destruct_packet(AVPacket *pkt) +{ + av_assert0(0); +} +#endif + +void av_init_packet(AVPacket *pkt) +{ + pkt->pts = AV_NOPTS_VALUE; + pkt->dts = AV_NOPTS_VALUE; + pkt->pos = -1; + pkt->duration = 0; + pkt->convergence_duration = 0; + pkt->flags = 0; + pkt->stream_index = 0; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = NULL; +#endif + pkt->buf = NULL; + pkt->side_data = NULL; + pkt->side_data_elems = 0; +} + +int av_new_packet(AVPacket *pkt, int size) +{ + AVBufferRef *buf = NULL; + + if ((unsigned)size >= (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + av_buffer_realloc(&buf, size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!buf) + return AVERROR(ENOMEM); + + memset(buf->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + av_init_packet(pkt); + pkt->buf = buf; + pkt->data = buf->data; + pkt->size = size; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif + + return 0; +} + +void av_shrink_packet(AVPacket *pkt, int size) +{ + if (pkt->size <= size) + return; + pkt->size = size; + memset(pkt->data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); +} + +int av_grow_packet(AVPacket *pkt, int grow_by) +{ + int new_size; + av_assert0((unsigned)pkt->size <= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE); + if (!pkt->size) + return av_new_packet(pkt, grow_by); + if ((unsigned)grow_by > + INT_MAX - (pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) + return -1; + + new_size = pkt->size + grow_by + FF_INPUT_BUFFER_PADDING_SIZE; + if (pkt->buf) { + int ret = av_buffer_realloc(&pkt->buf, new_size); + if (ret < 0) + return ret; + } else { + pkt->buf = av_buffer_alloc(new_size); + if (!pkt->buf) + return AVERROR(ENOMEM); + memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by)); +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif + } + pkt->data = pkt->buf->data; + pkt->size += grow_by; + memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + return 0; +} + +int av_packet_from_data(AVPacket *pkt, uint8_t *data, int size) +{ + if (size >= INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR(EINVAL); + + pkt->buf = av_buffer_create(data, size + FF_INPUT_BUFFER_PADDING_SIZE, + av_buffer_default_free, NULL, 0); + if (!pkt->buf) + return AVERROR(ENOMEM); + + pkt->data = data; + pkt->size = size; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif + + return 0; +} + +#define ALLOC_MALLOC(data, size) data = av_malloc(size) +#define ALLOC_BUF(data, size) \ +do { \ + av_buffer_realloc(&pkt->buf, size); \ + data = pkt->buf ? pkt->buf->data : NULL; \ +} while (0) + +#define DUP_DATA(dst, src, size, padding, ALLOC) \ + do { \ + void *data; \ + if (padding) { \ + if ((unsigned)(size) > \ + (unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \ + goto failed_alloc; \ + ALLOC(data, size + FF_INPUT_BUFFER_PADDING_SIZE); \ + } else { \ + ALLOC(data, size); \ + } \ + if (!data) \ + goto failed_alloc; \ + memcpy(data, src, size); \ + if (padding) \ + memset((uint8_t *)data + size, 0, \ + FF_INPUT_BUFFER_PADDING_SIZE); \ + dst = data; \ + } while (0) + +/* Makes duplicates of data, side_data, but does not copy any other fields */ +static int copy_packet_data(AVPacket *pkt, AVPacket *src) +{ + pkt->data = NULL; + pkt->side_data = NULL; + if (pkt->buf) { + AVBufferRef *ref = av_buffer_ref(src->buf); + if (!ref) + return AVERROR(ENOMEM); + pkt->buf = ref; + pkt->data = ref->data; + } else { + DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); + } +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif + + if (pkt->side_data_elems) { + int i; + + DUP_DATA(pkt->side_data, src->side_data, + pkt->side_data_elems * sizeof(*pkt->side_data), 0, ALLOC_MALLOC); + memset(pkt->side_data, 0, + pkt->side_data_elems * sizeof(*pkt->side_data)); + for (i = 0; i < pkt->side_data_elems; i++) { + DUP_DATA(pkt->side_data[i].data, src->side_data[i].data, + src->side_data[i].size, 1, ALLOC_MALLOC); + pkt->side_data[i].size = src->side_data[i].size; + pkt->side_data[i].type = src->side_data[i].type; + } + } + return 0; + +failed_alloc: + av_destruct_packet(pkt); + return AVERROR(ENOMEM); +} + +int av_dup_packet(AVPacket *pkt) +{ + AVPacket tmp_pkt; + + if (!pkt->buf && pkt->data +#if FF_API_DESTRUCT_PACKET + && !pkt->destruct +#endif + ) { + tmp_pkt = *pkt; + return copy_packet_data(pkt, &tmp_pkt); + } + return 0; +} + +int av_copy_packet(AVPacket *dst, AVPacket *src) +{ + *dst = *src; + return copy_packet_data(dst, src); +} + +void av_free_packet(AVPacket *pkt) +{ + if (pkt) { + int i; + + if (pkt->buf) + av_buffer_unref(&pkt->buf); +#if FF_API_DESTRUCT_PACKET + else if (pkt->destruct) + pkt->destruct(pkt); + pkt->destruct = NULL; +#endif + pkt->data = NULL; + pkt->size = 0; + + for (i = 0; i < pkt->side_data_elems; i++) + av_free(pkt->side_data[i].data); + av_freep(&pkt->side_data); + pkt->side_data_elems = 0; + } +} + +uint8_t *av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size) +{ + int elems = pkt->side_data_elems; + + if ((unsigned)elems + 1 > INT_MAX / sizeof(*pkt->side_data)) + return NULL; + if ((unsigned)size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + return NULL; + + pkt->side_data = av_realloc(pkt->side_data, + (elems + 1) * sizeof(*pkt->side_data)); + if (!pkt->side_data) + return NULL; + + pkt->side_data[elems].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!pkt->side_data[elems].data) + return NULL; + pkt->side_data[elems].size = size; + pkt->side_data[elems].type = type; + pkt->side_data_elems++; + + return pkt->side_data[elems].data; +} + +uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int *size) +{ + int i; + + for (i = 0; i < pkt->side_data_elems; i++) { + if (pkt->side_data[i].type == type) { + if (size) + *size = pkt->side_data[i].size; + return pkt->side_data[i].data; + } + } + return NULL; +} + +#define FF_MERGE_MARKER 0x8c4d9d108e25e9feULL + +int av_packet_merge_side_data(AVPacket *pkt){ + if(pkt->side_data_elems){ + AVBufferRef *buf; + int i; + uint8_t *p; + uint64_t size= pkt->size + 8LL + FF_INPUT_BUFFER_PADDING_SIZE; + AVPacket old= *pkt; + for (i=0; i INT_MAX) + return AVERROR(EINVAL); + buf = av_buffer_alloc(size); + if (!buf) + return AVERROR(ENOMEM); + pkt->buf = buf; + pkt->data = p = buf->data; +#if FF_API_DESTRUCT_PACKET + pkt->destruct = dummy_destruct_packet; +#endif + pkt->size = size - FF_INPUT_BUFFER_PADDING_SIZE; + bytestream_put_buffer(&p, old.data, old.size); + for (i=old.side_data_elems-1; i>=0; i--) { + bytestream_put_buffer(&p, old.side_data[i].data, old.side_data[i].size); + bytestream_put_be32(&p, old.side_data[i].size); + *p++ = old.side_data[i].type | ((i==old.side_data_elems-1)*128); + } + bytestream_put_be64(&p, FF_MERGE_MARKER); + av_assert0(p-pkt->data == pkt->size); + memset(p, 0, FF_INPUT_BUFFER_PADDING_SIZE); + av_free_packet(&old); + pkt->side_data_elems = 0; + pkt->side_data = NULL; + return 1; + } + return 0; +} + +int av_packet_split_side_data(AVPacket *pkt){ + if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){ + int i; + unsigned int size; + uint8_t *p; + + p = pkt->data + pkt->size - 8 - 5; + for (i=1; ; i++){ + size = AV_RB32(p); + if (size>INT_MAX || p - pkt->data < size) + return 0; + if (p[4]&128) + break; + p-= size+5; + } + + pkt->side_data = av_malloc(i * sizeof(*pkt->side_data)); + if (!pkt->side_data) + return AVERROR(ENOMEM); + + p= pkt->data + pkt->size - 8 - 5; + for (i=0; ; i++){ + size= AV_RB32(p); + av_assert0(size<=INT_MAX && p - pkt->data >= size); + pkt->side_data[i].data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + pkt->side_data[i].size = size; + pkt->side_data[i].type = p[4]&127; + if (!pkt->side_data[i].data) + return AVERROR(ENOMEM); + memcpy(pkt->side_data[i].data, p-size, size); + pkt->size -= size + 5; + if(p[4]&128) + break; + p-= size+5; + } + pkt->size -= 8; + pkt->side_data_elems = i+1; + return 1; + } + return 0; +} + +int av_packet_shrink_side_data(AVPacket *pkt, enum AVPacketSideDataType type, + int size) +{ + int i; + + for (i = 0; i < pkt->side_data_elems; i++) { + if (pkt->side_data[i].type == type) { + if (size > pkt->side_data[i].size) + return AVERROR(ENOMEM); + pkt->side_data[i].size = size; + return 0; + } + } + return AVERROR(ENOENT); +} diff --git a/ffmpeg/libavcodec/avpicture.c b/ffmpeg/libavcodec/avpicture.c new file mode 100644 index 0000000..a6f89ef --- /dev/null +++ b/ffmpeg/libavcodec/avpicture.c @@ -0,0 +1,78 @@ +/* + * AVPicture management routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * AVPicture management routines + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/common.h" +#include "libavutil/pixdesc.h" +#include "libavutil/imgutils.h" +#include "libavutil/colorspace.h" + +int avpicture_fill(AVPicture *picture, const uint8_t *ptr, + enum AVPixelFormat pix_fmt, int width, int height) +{ + return av_image_fill_arrays(picture->data, picture->linesize, + ptr, pix_fmt, width, height, 1); +} + +int avpicture_layout(const AVPicture* src, enum AVPixelFormat pix_fmt, int width, int height, + unsigned char *dest, int dest_size) +{ + return av_image_copy_to_buffer(dest, dest_size, + (const uint8_t * const*)src->data, src->linesize, + pix_fmt, width, height, 1); +} + +int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height) +{ + return av_image_get_buffer_size(pix_fmt, width, height, 1); +} + +int avpicture_alloc(AVPicture *picture, + enum AVPixelFormat pix_fmt, int width, int height) +{ + int ret = av_image_alloc(picture->data, picture->linesize, + width, height, pix_fmt, 1); + if (ret < 0) { + memset(picture, 0, sizeof(AVPicture)); + return ret; + } + + return 0; +} + +void avpicture_free(AVPicture *picture) +{ + av_free(picture->data[0]); +} + +void av_picture_copy(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height) +{ + av_image_copy(dst->data, dst->linesize, (const uint8_t **)src->data, + src->linesize, pix_fmt, width, height); +} + diff --git a/ffmpeg/libavcodec/avr32/mathops.h b/ffmpeg/libavcodec/avr32/mathops.h new file mode 100644 index 0000000..85f42b5 --- /dev/null +++ b/ffmpeg/libavcodec/avr32/mathops.h @@ -0,0 +1,101 @@ +/* + * Simple math operations + * Copyright (c) 2009 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_AVR32_MATHOPS_H +#define AVCODEC_AVR32_MATHOPS_H + +#include +#include "config.h" +#include "libavutil/common.h" + +#if HAVE_INLINE_ASM + +#define MULL MULL +static inline av_const int MULL(int a, int b, unsigned shift) +{ + union { int64_t x; int hl[2]; } x; + __asm__ ("muls.d %0, %1, %2 \n\t" + "lsr %0, %3 \n\t" + "or %0, %0, %m0<<%4 \n\t" + : "=r"(x) : "r"(b), "r"(a), "i"(shift), "i"(32-shift)); + return x.hl[1]; +} + +#define MULH MULH +static inline av_const int MULH(int a, int b) +{ + union { int64_t x; int hl[2]; } x; + __asm__ ("muls.d %0, %1, %2" : "=r"(x.x) : "r"(a), "r"(b)); + return x.hl[0]; +} + +#define MUL64 MUL64 +static inline av_const int64_t MUL64(int a, int b) +{ + int64_t x; + __asm__ ("muls.d %0, %1, %2" : "=r"(x) : "r"(a), "r"(b)); + return x; +} + +static inline av_const int64_t MAC64(int64_t d, int a, int b) +{ + __asm__ ("macs.d %0, %1, %2" : "+r"(d) : "r"(a), "r"(b)); + return d; +} +#define MAC64(d, a, b) ((d) = MAC64(d, a, b)) +#define MLS64(d, a, b) MAC64(d, -(a), b) + +static inline av_const int MAC16(int d, int a, int b) +{ + __asm__ ("machh.w %0, %1:b, %2:b" : "+r"(d) : "r"(a), "r"(b)); + return d; +} +#define MAC16(d, a, b) ((d) = MAC16(d, a, b)) +#define MLS16(d, a, b) MAC16(d, -(a), b) + +#define MUL16 MUL16 +static inline av_const int MUL16(int a, int b) +{ + int d; + __asm__ ("mulhh.w %0, %1:b, %2:b" : "=r"(d) : "r"(a), "r"(b)); + return d; +} + +#define mid_pred mid_pred +static inline av_const int mid_pred(int a, int b, int c) +{ + int m; + __asm__ ("mov %0, %2 \n\t" + "cp.w %1, %2 \n\t" + "movgt %0, %1 \n\t" + "movgt %1, %2 \n\t" + "cp.w %1, %3 \n\t" + "movle %1, %3 \n\t" + "cp.w %0, %1 \n\t" + "movgt %0, %1 \n\t" + : "=&r"(m), "+r"(a) + : "r"(b), "r"(c)); + return m; +} + +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_AVR32_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/avrndec.c b/ffmpeg/libavcodec/avrndec.c new file mode 100644 index 0000000..40aca17 --- /dev/null +++ b/ffmpeg/libavcodec/avrndec.c @@ -0,0 +1,132 @@ +/* + * AVRn decoder + * Copyright (c) 2012 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 "avcodec.h" +#include "internal.h" +#include "mjpeg.h" +#include "mjpegdec.h" +#include "libavutil/imgutils.h" + +typedef struct { + MJpegDecodeContext mjpeg_ctx; + int is_mjpeg; + int interlace; //FIXME use frame.interlaced_frame + int tff; +} AVRnContext; + +static av_cold int init(AVCodecContext *avctx) +{ + AVRnContext *a = avctx->priv_data; + int ret; + + // Support "Resolution 1:1" for Avid AVI Codec + a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3); + + if(!a->is_mjpeg && avctx->lowres) { + av_log(avctx, AV_LOG_ERROR, "lowres is not possible with rawvideo\n"); + return AVERROR(EINVAL); + } + + if(a->is_mjpeg) + return ff_mjpeg_decode_init(avctx); + + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) + return ret; + + avctx->pix_fmt = AV_PIX_FMT_UYVY422; + + if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size) { + int ndx = avctx->extradata[4] + 4; + a->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4); + if(a->interlace) { + a->tff = avctx->extradata[ndx + 24] == 1; + } + } + + return 0; +} + +static av_cold int end(AVCodecContext *avctx) +{ + AVRnContext *a = avctx->priv_data; + + if(a->is_mjpeg) + ff_mjpeg_decode_end(avctx); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVRnContext *a = avctx->priv_data; + AVFrame *p = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int y, ret, true_height; + + if(a->is_mjpeg) + return ff_mjpeg_decode_frame(avctx, data, got_frame, avpkt); + + true_height = buf_size / (2*avctx->width); + + if(buf_size < 2*avctx->width * avctx->height) { + av_log(avctx, AV_LOG_ERROR, "packet too small\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + if(a->interlace) { + buf += (true_height - avctx->height)*avctx->width; + for(y = 0; y < avctx->height-1; y+=2) { + memcpy(p->data[0] + (y+ a->tff)*p->linesize[0], buf , 2*avctx->width); + memcpy(p->data[0] + (y+!a->tff)*p->linesize[0], buf + avctx->width*true_height+4, 2*avctx->width); + buf += 2*avctx->width; + } + } else { + buf += (true_height - avctx->height)*avctx->width*2; + for(y = 0; y < avctx->height; y++) { + memcpy(p->data[0] + y*p->linesize[0], buf, 2*avctx->width); + buf += 2*avctx->width; + } + } + + *got_frame = 1; + return buf_size; +} + +AVCodec ff_avrn_decoder = { + .name = "avrn", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVRN, + .priv_data_size = sizeof(AVRnContext), + .init = init, + .close = end, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"), + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, +}; + diff --git a/ffmpeg/libavcodec/avs.c b/ffmpeg/libavcodec/avs.c new file mode 100644 index 0000000..e3733d7 --- /dev/null +++ b/ffmpeg/libavcodec/avs.c @@ -0,0 +1,186 @@ +/* + * AVS video decoder. + * Copyright (c) 2006 Aurelien Jacobs + * + * 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 "avcodec.h" +#include "get_bits.h" +#include "internal.h" + + +typedef struct { + AVFrame picture; +} AvsContext; + +typedef enum { + AVS_VIDEO = 0x01, + AVS_AUDIO = 0x02, + AVS_PALETTE = 0x03, + AVS_GAME_DATA = 0x04, +} AvsBlockType; + +typedef enum { + AVS_I_FRAME = 0x00, + AVS_P_FRAME_3X3 = 0x01, + AVS_P_FRAME_2X2 = 0x02, + AVS_P_FRAME_2X3 = 0x03, +} AvsVideoSubType; + + +static int +avs_decode_frame(AVCodecContext * avctx, + void *data, int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = avpkt->data + avpkt->size; + int buf_size = avpkt->size; + AvsContext *const avs = avctx->priv_data; + AVFrame *picture = data; + AVFrame *const p = &avs->picture; + const uint8_t *table, *vect; + uint8_t *out; + int i, j, x, y, stride, ret, vect_w = 3, vect_h = 3; + AvsVideoSubType sub_type; + AvsBlockType type; + GetBitContext change_map = {0}; //init to silence warning + + if ((ret = ff_reget_buffer(avctx, p)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_P; + p->key_frame = 0; + + out = avs->picture.data[0]; + stride = avs->picture.linesize[0]; + + if (buf_end - buf < 4) + return AVERROR_INVALIDDATA; + sub_type = buf[0]; + type = buf[1]; + buf += 4; + + if (type == AVS_PALETTE) { + int first, last; + uint32_t *pal = (uint32_t *) avs->picture.data[1]; + + first = AV_RL16(buf); + last = first + AV_RL16(buf + 2); + if (first >= 256 || last > 256 || buf_end - buf < 4 + 4 + 3 * (last - first)) + return AVERROR_INVALIDDATA; + buf += 4; + for (i=first; i> 6) & 0x30303; + } + + sub_type = buf[0]; + type = buf[1]; + buf += 4; + } + + if (type != AVS_VIDEO) + return AVERROR_INVALIDDATA; + + switch (sub_type) { + case AVS_I_FRAME: + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + case AVS_P_FRAME_3X3: + vect_w = 3; + vect_h = 3; + break; + + case AVS_P_FRAME_2X2: + vect_w = 2; + vect_h = 2; + break; + + case AVS_P_FRAME_2X3: + vect_w = 2; + vect_h = 3; + break; + + default: + return AVERROR_INVALIDDATA; + } + + if (buf_end - buf < 256 * vect_w * vect_h) + return AVERROR_INVALIDDATA; + table = buf + (256 * vect_w * vect_h); + if (sub_type != AVS_I_FRAME) { + int map_size = ((318 / vect_w + 7) / 8) * (198 / vect_h); + if (buf_end - table < map_size) + return AVERROR_INVALIDDATA; + init_get_bits(&change_map, table, map_size * 8); + table += map_size; + } + + for (y=0; y<198; y+=vect_h) { + for (x=0; x<318; x+=vect_w) { + if (sub_type == AVS_I_FRAME || get_bits1(&change_map)) { + if (buf_end - table < 1) + return AVERROR_INVALIDDATA; + vect = &buf[*table++ * (vect_w * vect_h)]; + for (j=0; jpicture)) < 0) + return ret; + *got_frame = 1; + + return buf_size; +} + +static av_cold int avs_decode_init(AVCodecContext * avctx) +{ + AvsContext *s = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + avcodec_set_dimensions(avctx, 318, 198); + avcodec_get_frame_defaults(&s->picture); + return 0; +} + +static av_cold int avs_decode_end(AVCodecContext *avctx) +{ + AvsContext *s = avctx->priv_data; + av_frame_unref(&s->picture); + return 0; +} + + +AVCodec ff_avs_decoder = { + .name = "avs", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVS, + .priv_data_size = sizeof(AvsContext), + .init = avs_decode_init, + .decode = avs_decode_frame, + .close = avs_decode_end, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("AVS (Audio Video Standard) video"), +}; diff --git a/ffmpeg/libavcodec/avuidec.c b/ffmpeg/libavcodec/avuidec.c new file mode 100644 index 0000000..a574f5b --- /dev/null +++ b/ffmpeg/libavcodec/avuidec.c @@ -0,0 +1,130 @@ +/* + * AVID Meridien decoder + * + * Copyright (c) 2012 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" + +static av_cold int avui_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUVA422P; + return 0; +} + +static int avui_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + int ret; + AVFrame *pic = data; + const uint8_t *src = avpkt->data, *extradata = avctx->extradata; + const uint8_t *srca; + uint8_t *y, *u, *v, *a; + int transparent, interlaced = 1, skip, opaque_length, i, j, k; + uint32_t extradata_size = avctx->extradata_size; + + while (extradata_size >= 24) { + uint32_t atom_size = AV_RB32(extradata); + if (!memcmp(&extradata[4], "APRGAPRG0001", 12)) { + interlaced = extradata[19] != 1; + break; + } + if (atom_size && atom_size <= extradata_size) { + extradata += atom_size; + extradata_size -= atom_size; + } else { + break; + } + } + if (avctx->height == 486) { + skip = 10; + } else { + skip = 16; + } + opaque_length = 2 * avctx->width * (avctx->height + skip) + 4 * interlaced; + if (avpkt->size < opaque_length) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + transparent = avctx->bits_per_coded_sample == 32 && + avpkt->size >= opaque_length * 2 + 4; + srca = src + opaque_length + 5; + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + if (!interlaced) { + src += avctx->width * skip; + srca += avctx->width * skip; + } + + for (i = 0; i < interlaced + 1; i++) { + src += avctx->width * skip; + srca += avctx->width * skip; + if (interlaced && avctx->height == 486) { + y = pic->data[0] + (1 - i) * pic->linesize[0]; + u = pic->data[1] + (1 - i) * pic->linesize[1]; + v = pic->data[2] + (1 - i) * pic->linesize[2]; + a = pic->data[3] + (1 - i) * pic->linesize[3]; + } else { + y = pic->data[0] + i * pic->linesize[0]; + u = pic->data[1] + i * pic->linesize[1]; + v = pic->data[2] + i * pic->linesize[2]; + a = pic->data[3] + i * pic->linesize[3]; + } + + for (j = 0; j < avctx->height >> interlaced; j++) { + for (k = 0; k < avctx->width >> 1; k++) { + u[ k ] = *src++; + y[2 * k ] = *src++; + a[2 * k ] = 0xFF - (transparent ? *srca++ : 0); + srca++; + v[ k ] = *src++; + y[2 * k + 1] = *src++; + a[2 * k + 1] = 0xFF - (transparent ? *srca++ : 0); + srca++; + } + + y += (interlaced + 1) * pic->linesize[0]; + u += (interlaced + 1) * pic->linesize[1]; + v += (interlaced + 1) * pic->linesize[2]; + a += (interlaced + 1) * pic->linesize[3]; + } + src += 4; + srca += 4; + } + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_avui_decoder = { + .name = "avui", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVUI, + .init = avui_decode_init, + .decode = avui_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), +}; diff --git a/ffmpeg/libavcodec/avuienc.c b/ffmpeg/libavcodec/avuienc.c new file mode 100644 index 0000000..a4970a0 --- /dev/null +++ b/ffmpeg/libavcodec/avuienc.c @@ -0,0 +1,112 @@ +/* + * AVID Meridien encoder + * + * Copyright (c) 2012 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int avui_encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + + if (avctx->width != 720 || avctx->height != 486 && avctx->height != 576) { + av_log(avctx, AV_LOG_ERROR, "Only 720x486 and 720x576 are supported.\n"); + return AVERROR(EINVAL); + } + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + return AVERROR(ENOMEM); + } + if (!(avctx->extradata = av_mallocz(24 + FF_INPUT_BUFFER_PADDING_SIZE))) + return AVERROR(ENOMEM); + avctx->extradata_size = 24; + memcpy(avctx->extradata, "\0\0\0\x18""APRGAPRG0001", 16); + if (avctx->field_order > AV_FIELD_PROGRESSIVE) { + avctx->extradata[19] = 2; + } else { + avctx->extradata[19] = 1; + } + + + return 0; +} + +static int avui_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + uint8_t *dst, *src = pic->data[0]; + int i, j, skip, ret, size, interlaced; + + interlaced = avctx->field_order > AV_FIELD_PROGRESSIVE; + + if (avctx->height == 486) { + skip = 10; + } else { + skip = 16; + } + size = 2 * avctx->width * (avctx->height + skip) + 8 * interlaced; + if ((ret = ff_alloc_packet2(avctx, pkt, size)) < 0) + return ret; + dst = pkt->data; + if (!interlaced) { + dst += avctx->width * skip; + } + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + for (i = 0; i <= interlaced; i++) { + if (interlaced && avctx->height == 486) { + src = pic->data[0] + (1 - i) * pic->linesize[0]; + } else { + src = pic->data[0] + i * pic->linesize[0]; + } + dst += avctx->width * skip + 4 * i; + for (j = 0; j < avctx->height; j += interlaced + 1) { + memcpy(dst, src, avctx->width * 2); + src += (interlaced + 1) * pic->linesize[0]; + dst += avctx->width * 2; + } + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int avui_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_avui_encoder = { + .name = "avui", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVUI, + .init = avui_encode_init, + .encode2 = avui_encode_frame, + .close = avui_encode_close, + .capabilities = CODEC_CAP_EXPERIMENTAL, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), +}; diff --git a/ffmpeg/libavcodec/bethsoftvideo.c b/ffmpeg/libavcodec/bethsoftvideo.c new file mode 100644 index 0000000..474265f --- /dev/null +++ b/ffmpeg/libavcodec/bethsoftvideo.c @@ -0,0 +1,162 @@ +/* + * Bethesda VID video decoder + * Copyright (C) 2007 Nicholas Tung + * + * 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 + */ + +/** + * @file + * @brief Bethesda Softworks VID Video Decoder + * @author Nicholas Tung [ntung (at. ntung com] (2007-03) + * @see http://wiki.multimedia.cx/index.php?title=Bethsoft_VID + * @see http://www.svatopluk.com/andux/docs/dfvid.html + */ + +#include "libavutil/common.h" +#include "avcodec.h" +#include "bethsoftvideo.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct BethsoftvidContext { + AVFrame frame; + GetByteContext g; +} BethsoftvidContext; + +static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx) +{ + BethsoftvidContext *vid = avctx->priv_data; + avcodec_get_frame_defaults(&vid->frame); + avctx->pix_fmt = AV_PIX_FMT_PAL8; + return 0; +} + +static int set_palette(BethsoftvidContext *ctx) +{ + uint32_t *palette = (uint32_t *)ctx->frame.data[1]; + int a; + + if (bytestream2_get_bytes_left(&ctx->g) < 256*3) + return AVERROR_INVALIDDATA; + + for(a = 0; a < 256; a++){ + palette[a] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->g) * 4; + palette[a] |= palette[a] >> 6 & 0x30303; + } + ctx->frame.palette_has_changed = 1; + return 0; +} + +static int bethsoftvid_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + BethsoftvidContext * vid = avctx->priv_data; + char block_type; + uint8_t * dst; + uint8_t * frame_end; + int remaining = avctx->width; // number of bytes remaining on a line + int wrap_to_next_line; + int code, ret; + int yoffset; + + if ((ret = ff_reget_buffer(avctx, &vid->frame)) < 0) + return ret; + wrap_to_next_line = vid->frame.linesize[0] - avctx->width; + + if (avpkt->side_data_elems > 0 && + avpkt->side_data[0].type == AV_PKT_DATA_PALETTE) { + bytestream2_init(&vid->g, avpkt->side_data[0].data, + avpkt->side_data[0].size); + if ((ret = set_palette(vid)) < 0) + return ret; + } + + bytestream2_init(&vid->g, avpkt->data, avpkt->size); + dst = vid->frame.data[0]; + frame_end = vid->frame.data[0] + vid->frame.linesize[0] * avctx->height; + + switch(block_type = bytestream2_get_byte(&vid->g)){ + case PALETTE_BLOCK: { + *got_frame = 0; + if ((ret = set_palette(vid)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error reading palette\n"); + return ret; + } + return bytestream2_tell(&vid->g); + } + case VIDEO_YOFF_P_FRAME: + yoffset = bytestream2_get_le16(&vid->g); + if(yoffset >= avctx->height) + return AVERROR_INVALIDDATA; + dst += vid->frame.linesize[0] * yoffset; + } + + // main code + while((code = bytestream2_get_byte(&vid->g))){ + int length = code & 0x7f; + + // copy any bytes starting at the current position, and ending at the frame width + while(length > remaining){ + if(code < 0x80) + bytestream2_get_buffer(&vid->g, dst, remaining); + else if(block_type == VIDEO_I_FRAME) + memset(dst, bytestream2_peek_byte(&vid->g), remaining); + length -= remaining; // decrement the number of bytes to be copied + dst += remaining + wrap_to_next_line; // skip over extra bytes at end of frame + remaining = avctx->width; + if(dst == frame_end) + goto end; + } + + // copy any remaining bytes after / if line overflows + if(code < 0x80) + bytestream2_get_buffer(&vid->g, dst, length); + else if(block_type == VIDEO_I_FRAME) + memset(dst, bytestream2_get_byte(&vid->g), length); + remaining -= length; + dst += length; + } + end: + + if ((ret = av_frame_ref(data, &vid->frame)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int bethsoftvid_decode_end(AVCodecContext *avctx) +{ + BethsoftvidContext * vid = avctx->priv_data; + av_frame_unref(&vid->frame); + return 0; +} + +AVCodec ff_bethsoftvid_decoder = { + .name = "bethsoftvid", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BETHSOFTVID, + .priv_data_size = sizeof(BethsoftvidContext), + .init = bethsoftvid_decode_init, + .close = bethsoftvid_decode_end, + .decode = bethsoftvid_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"), +}; diff --git a/ffmpeg/libavcodec/bethsoftvideo.h b/ffmpeg/libavcodec/bethsoftvideo.h new file mode 100644 index 0000000..d5b5d0a --- /dev/null +++ b/ffmpeg/libavcodec/bethsoftvideo.h @@ -0,0 +1,36 @@ +/* + * Bethesda VID video decoder + * Copyright (C) 2007 Nicholas Tung + * + * 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 + */ + +#ifndef AVCODEC_BETHSOFTVIDEO_H +#define AVCODEC_BETHSOFTVIDEO_H + +enum BethsoftVidBlockType +{ + PALETTE_BLOCK = 0x02, + FIRST_AUDIO_BLOCK = 0x7c, + AUDIO_BLOCK = 0x7d, + VIDEO_I_FRAME = 0x03, + VIDEO_P_FRAME = 0x01, + VIDEO_YOFF_P_FRAME = 0x04, + EOF_BLOCK = 0x14, +}; + +#endif /* AVCODEC_BETHSOFTVIDEO_H */ diff --git a/ffmpeg/libavcodec/bfi.c b/ffmpeg/libavcodec/bfi.c new file mode 100644 index 0000000..9cfcd14 --- /dev/null +++ b/ffmpeg/libavcodec/bfi.c @@ -0,0 +1,186 @@ +/* + * Brute Force & Ignorance (BFI) video decoder + * Copyright (c) 2008 Sisir Koppaka + * + * 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 + */ + +/** + * @file + * @brief Brute Force & Ignorance (.bfi) video decoder + * @author Sisir Koppaka ( sisir.koppaka at gmail dot com ) + * @see http://wiki.multimedia.cx/index.php?title=BFI + */ + +#include "libavutil/common.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct BFIContext { + AVCodecContext *avctx; + uint8_t *dst; + uint32_t pal[256]; +} BFIContext; + +static av_cold int bfi_decode_init(AVCodecContext *avctx) +{ + BFIContext *bfi = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + bfi->dst = av_mallocz(avctx->width * avctx->height); + return 0; +} + +static int bfi_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *frame = data; + GetByteContext g; + int buf_size = avpkt->size; + BFIContext *bfi = avctx->priv_data; + uint8_t *dst = bfi->dst; + uint8_t *src, *dst_offset, colour1, colour2; + uint8_t *frame_end = bfi->dst + avctx->width * avctx->height; + uint32_t *pal; + int i, j, ret, height = avctx->height; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + bytestream2_init(&g, avpkt->data, buf_size); + + /* Set frame parameters and palette, if necessary */ + if (!avctx->frame_number) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + /* Setting the palette */ + if (avctx->extradata_size > 768) { + av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n"); + return AVERROR_INVALIDDATA; + } + pal = (uint32_t *)frame->data[1]; + for (i = 0; i < avctx->extradata_size / 3; i++) { + int shift = 16; + *pal = 0xFFU << 24; + for (j = 0; j < 3; j++, shift -= 8) + *pal += ((avctx->extradata[i * 3 + j] << 2) | + (avctx->extradata[i * 3 + j] >> 4)) << shift; + pal++; + } + memcpy(bfi->pal, frame->data[1], sizeof(bfi->pal)); + frame->palette_has_changed = 1; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + frame->key_frame = 0; + frame->palette_has_changed = 0; + memcpy(frame->data[1], bfi->pal, sizeof(bfi->pal)); + } + + bytestream2_skip(&g, 4); // Unpacked size, not required. + + while (dst != frame_end) { + static const uint8_t lentab[4] = { 0, 2, 0, 1 }; + unsigned int byte = bytestream2_get_byte(&g), av_uninit(offset); + unsigned int code = byte >> 6; + unsigned int length = byte & ~0xC0; + + if (!bytestream2_get_bytes_left(&g)) { + av_log(avctx, AV_LOG_ERROR, + "Input resolution larger than actual frame.\n"); + return AVERROR_INVALIDDATA; + } + + /* Get length and offset (if required) */ + if (length == 0) { + if (code == 1) { + length = bytestream2_get_byte(&g); + offset = bytestream2_get_le16(&g); + } else { + length = bytestream2_get_le16(&g); + if (code == 2 && length == 0) + break; + } + } else { + if (code == 1) + offset = bytestream2_get_byte(&g); + } + + /* Do boundary check */ + if (dst + (length << lentab[code]) > frame_end) + break; + + switch (code) { + case 0: // normal chain + if (length >= bytestream2_get_bytes_left(&g)) { + av_log(avctx, AV_LOG_ERROR, "Frame larger than buffer.\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_get_buffer(&g, dst, length); + dst += length; + break; + case 1: // back chain + dst_offset = dst - offset; + length *= 4; // Convert dwords to bytes. + if (dst_offset < bfi->dst) + break; + while (length--) + *dst++ = *dst_offset++; + break; + case 2: // skip chain + dst += length; + break; + case 3: // fill chain + colour1 = bytestream2_get_byte(&g); + colour2 = bytestream2_get_byte(&g); + while (length--) { + *dst++ = colour1; + *dst++ = colour2; + } + break; + } + } + + src = bfi->dst; + dst = frame->data[0]; + while (height--) { + memcpy(dst, src, avctx->width); + src += avctx->width; + dst += frame->linesize[0]; + } + *got_frame = 1; + + return buf_size; +} + +static av_cold int bfi_decode_close(AVCodecContext *avctx) +{ + BFIContext *bfi = avctx->priv_data; + av_free(bfi->dst); + return 0; +} + +AVCodec ff_bfi_decoder = { + .name = "bfi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BFI, + .priv_data_size = sizeof(BFIContext), + .init = bfi_decode_init, + .close = bfi_decode_close, + .decode = bfi_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"), +}; diff --git a/ffmpeg/libavcodec/bfin/Makefile b/ffmpeg/libavcodec/bfin/Makefile new file mode 100644 index 0000000..f7a5f42 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/Makefile @@ -0,0 +1,10 @@ +OBJS += bfin/dsputil_bfin.o \ + bfin/fdct_bfin.o \ + bfin/idct_bfin.o \ + bfin/pixels_bfin.o \ + +OBJS-$(CONFIG_HPELDS) += bfin/hpeldsp_bfin.o \ + bfin/hpel_pixels_bfin.o +OBJS-$(CONFIG_MPEGVIDEOENC) += bfin/mpegvideo_bfin.o +OBJS-$(CONFIG_VP3DSP) += bfin/vp3_bfin.o \ + bfin/vp3_idct_bfin.o diff --git a/ffmpeg/libavcodec/bfin/config_bfin.h b/ffmpeg/libavcodec/bfin/config_bfin.h new file mode 100644 index 0000000..3643953 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/config_bfin.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ +/* + low level assembler interface wrapper + +DEFUN(put_pixels_clamped,mL1, + (int16_t *block, uint8_t *dest, int line_size)): + + body + + rts; +*/ + +#ifndef AVCODEC_BFIN_CONFIG_BFIN_H +#define AVCODEC_BFIN_CONFIG_BFIN_H + +#include "config.h" + +#ifndef DEFUN + +#define mL3 .text +#ifndef mL1 +#if defined(__FDPIC__) && CONFIG_SRAM +#define mL1 .l1.text +#else +#define mL1 mL3 +#endif +#endif + +#define DEFUN(fname,where,interface) \ + .section where; \ + .global _ff_bfin_ ## fname ; \ + .type _ff_bfin_ ## fname, STT_FUNC; \ + .align 8; \ + _ff_bfin_ ## fname + +#define DEFUN_END(fname) \ + .size _ff_bfin_ ## fname, . - _ff_bfin_ ## fname + +#ifdef __FDPIC__ +#define RELOC(reg,got,obj) reg = [got + obj@GOT17M4] +#else +#define RELOC(reg,got,obj) reg.L = obj; reg.H = obj +#endif + +#endif + +#endif /* AVCODEC_BFIN_CONFIG_BFIN_H */ diff --git a/ffmpeg/libavcodec/bfin/dsputil_bfin.c b/ffmpeg/libavcodec/bfin/dsputil_bfin.c new file mode 100644 index 0000000..c9a0f15 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/dsputil_bfin.c @@ -0,0 +1,173 @@ +/* + * BlackFin DSPUTILS + * + * Copyright (C) 2007 Marc Hoffman + * Copyright (c) 2006 Michael Benjamin + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "dsputil_bfin.h" + +int off; + +static void bfin_idct_add (uint8_t *dest, int line_size, int16_t *block) +{ + ff_bfin_idct (block); + ff_bfin_add_pixels_clamped (block, dest, line_size); +} + +static void bfin_idct_put (uint8_t *dest, int line_size, int16_t *block) +{ + ff_bfin_idct (block); + ff_bfin_put_pixels_clamped (block, dest, line_size); +} + + +static void bfin_clear_blocks (int16_t *blocks) +{ + // This is just a simple memset. + // + __asm__("P0=192; " + "I0=%0; " + "R0=0; " + "LSETUP(clear_blocks_blkfn_lab,clear_blocks_blkfn_lab)LC0=P0;" + "clear_blocks_blkfn_lab:" + "[I0++]=R0;" + ::"a" (blocks):"P0","I0","R0"); +} + +static int bfin_pix_abs16 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + return ff_bfin_z_sad16x16 (blk1,blk2,line_size,line_size,h); +} + +static int bfin_vsad_intra16 (void *c, uint8_t *blk1, uint8_t *dummy, int stride, int h) { + return ff_bfin_z_sad16x16 (blk1,blk1+stride,stride<<1,stride<<1,h); +} + +static int bfin_vsad (void *c, uint8_t *blk1, uint8_t *blk2, int stride, int h) { + return ff_bfin_z_sad16x16 (blk1,blk1+stride,stride<<1,stride<<1,h) + + ff_bfin_z_sad16x16 (blk2,blk2+stride,stride<<1,stride<<1,h); +} + +static uint8_t vtmp_blk[256] attribute_l1_data_b; + +static int bfin_pix_abs16_x2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + ff_bfin_put_pixels16uc (vtmp_blk, blk2, blk2+1, 16, line_size, h); + return ff_bfin_z_sad16x16 (blk1, vtmp_blk, line_size, 16, h); +} + +static int bfin_pix_abs16_y2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + ff_bfin_put_pixels16uc (vtmp_blk, blk2, blk2+line_size, 16, line_size, h); + return ff_bfin_z_sad16x16 (blk1, vtmp_blk, line_size, 16, h); +} + +static int bfin_pix_abs16_xy2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + ff_bfin_z_put_pixels16_xy2 (vtmp_blk, blk2, 16, line_size, h); + return ff_bfin_z_sad16x16 (blk1, vtmp_blk, line_size, 16, h); +} + +static int bfin_pix_abs8 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + return ff_bfin_z_sad8x8 (blk1,blk2,line_size,line_size, h); +} + +static int bfin_pix_abs8_x2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + ff_bfin_put_pixels8uc (vtmp_blk, blk2, blk2+1, 8, line_size, h); + return ff_bfin_z_sad8x8 (blk1, vtmp_blk, line_size, 8, h); +} + +static int bfin_pix_abs8_y2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + ff_bfin_put_pixels8uc (vtmp_blk, blk2, blk2+line_size, 8, line_size, h); + return ff_bfin_z_sad8x8 (blk1, vtmp_blk, line_size, 8, h); +} + +static int bfin_pix_abs8_xy2 (void *c, uint8_t *blk1, uint8_t *blk2, int line_size, int h) +{ + ff_bfin_z_put_pixels8_xy2 (vtmp_blk, blk2, 8, line_size, h); + return ff_bfin_z_sad8x8 (blk1, vtmp_blk, line_size, 8, h); +} + + +/* + decoder optimization + start on 2/11 100 frames of 352x240@25 compiled with no optimization -g debugging + 9.824s ~ 2.44x off + 6.360s ~ 1.58x off with -O2 + 5.740s ~ 1.43x off with idcts + + 2.64s 2/20 same sman.mp4 decode only + +*/ + +av_cold void ff_dsputil_init_bfin(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + + c->diff_pixels = ff_bfin_diff_pixels; + c->put_pixels_clamped = ff_bfin_put_pixels_clamped; + c->add_pixels_clamped = ff_bfin_add_pixels_clamped; + + if (!high_bit_depth) + c->get_pixels = ff_bfin_get_pixels; + c->clear_blocks = bfin_clear_blocks; + c->pix_sum = ff_bfin_pix_sum; + c->pix_norm1 = ff_bfin_pix_norm1; + + c->sad[0] = bfin_pix_abs16; + c->sad[1] = bfin_pix_abs8; + +/* c->vsad[0] = bfin_vsad; */ +/* c->vsad[4] = bfin_vsad_intra16; */ + + /* TODO [0] 16 [1] 8 */ + c->pix_abs[0][0] = bfin_pix_abs16; + c->pix_abs[0][1] = bfin_pix_abs16_x2; + c->pix_abs[0][2] = bfin_pix_abs16_y2; + c->pix_abs[0][3] = bfin_pix_abs16_xy2; + + c->pix_abs[1][0] = bfin_pix_abs8; + c->pix_abs[1][1] = bfin_pix_abs8_x2; + c->pix_abs[1][2] = bfin_pix_abs8_y2; + c->pix_abs[1][3] = bfin_pix_abs8_xy2; + + + c->sse[0] = ff_bfin_sse16; + c->sse[1] = ff_bfin_sse8; + c->sse[2] = ff_bfin_sse4; + + if (avctx->bits_per_raw_sample <= 8) { + if (avctx->dct_algo == FF_DCT_AUTO) + c->fdct = ff_bfin_fdct; + + if (avctx->idct_algo == FF_IDCT_AUTO) { + c->idct_permutation_type = FF_NO_IDCT_PERM; + c->idct = ff_bfin_idct; + c->idct_add = bfin_idct_add; + c->idct_put = bfin_idct_put; + } + } +} diff --git a/ffmpeg/libavcodec/bfin/dsputil_bfin.h b/ffmpeg/libavcodec/bfin/dsputil_bfin.h new file mode 100644 index 0000000..079ebdd --- /dev/null +++ b/ffmpeg/libavcodec/bfin/dsputil_bfin.h @@ -0,0 +1,95 @@ +/* + * BlackFin DSPUTILS COMMON OPTIMIZATIONS HEADER + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ + + +#ifndef AVCODEC_BFIN_DSPUTIL_BFIN_H +#define AVCODEC_BFIN_DSPUTIL_BFIN_H + +#include + +#include "config.h" + +#if defined(__FDPIC__) && CONFIG_SRAM +#define attribute_l1_text __attribute__ ((l1_text)) +#define attribute_l1_data_b __attribute__((l1_data_B)) +#else +#define attribute_l1_text +#define attribute_l1_data_b +#endif + +void ff_bfin_idct (int16_t *block) attribute_l1_text; +void ff_bfin_fdct (int16_t *block) attribute_l1_text; +void ff_bfin_add_pixels_clamped (const int16_t *block, uint8_t *dest, int line_size) attribute_l1_text; +void ff_bfin_put_pixels_clamped (const int16_t *block, uint8_t *dest, int line_size) attribute_l1_text; +void ff_bfin_diff_pixels (int16_t *block, const uint8_t *s1, const uint8_t *s2, int stride) attribute_l1_text; +void ff_bfin_get_pixels (int16_t *restrict block, const uint8_t *pixels, int line_size) attribute_l1_text; +int ff_bfin_pix_norm1 (uint8_t * pix, int line_size) attribute_l1_text; +int ff_bfin_z_sad8x8 (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h) attribute_l1_text; +int ff_bfin_z_sad16x16 (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h) attribute_l1_text; + +int ff_bfin_pix_sum (uint8_t *p, int stride) attribute_l1_text; + +int ff_bfin_sse4 (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) attribute_l1_text; +int ff_bfin_sse8 (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) attribute_l1_text; +int ff_bfin_sse16 (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) attribute_l1_text; + + +#ifdef BFIN_PROFILE + +static double Telem[16]; +static char *TelemNames[16]; +static int TelemCnt; + +#define PROF(lab,e) { int xx_e = e; char*xx_lab = lab; uint64_t xx_t0 = read_time(); +#define EPROF() xx_t0 = read_time()-xx_t0; Telem[xx_e] = Telem[xx_e] + xx_t0; TelemNames[xx_e] = xx_lab; } + +static void prof_report (void) +{ + int i; + double s = 0; + for (i=0;i<16;i++) { + double v; + if (TelemNames[i]) { + v = Telem[i]/TelemCnt; + av_log (NULL,AV_LOG_DEBUG,"%-20s: %12.4f\t%12.4f\n", TelemNames[i],v,v/64); + s = s + Telem[i]; + } + } + av_log (NULL,AV_LOG_DEBUG,"%-20s: %12.4f\t%12.4f\n%20.4f\t%d\n", + "total",s/TelemCnt,s/TelemCnt/64,s,TelemCnt); +} + +static void bfprof (void) +{ + static int init; + if (!init) atexit (prof_report); + init=1; + TelemCnt++; +} + +#else +#define PROF(a,b) +#define EPROF() +#define bfprof() +#endif + +#endif /* AVCODEC_BFIN_DSPUTIL_BFIN_H */ diff --git a/ffmpeg/libavcodec/bfin/fdct_bfin.S b/ffmpeg/libavcodec/bfin/fdct_bfin.S new file mode 100644 index 0000000..9169574 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/fdct_bfin.S @@ -0,0 +1,332 @@ +/* + * fdct BlackFin + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ +/* + void ff_bfin_fdct (int16_t *buf); + + This implementation works only for 8x8 input. The range of input + must be -256 to 255 i.e. 8bit input represented in a 16bit data + word. The original data must be sign extended into the 16bit data + words. + + + Chen factorization of + + 8 + X(m) = sum (x(n) * cos ((2n+1)*m*pi/16)) + n=0 + + C4 + 0 --*-------------*0+7---*-----*0+3-------*-*-------------------> 0 + \ / \ / X S4,S4 + 1 --*-\---------/-*1+6---*-\-/-*1+2-------*-*-------------------> 4 + \ / \ -C4 C3 + 2 --*---\-----/---*2+5---*-/-\-*1-2---------------*-*-----------> 2 + \ / / \ X S3,-S3 + 3 --*-----\-/-----*3+4---*-----*0-3---------------*-*-----------> 6 + / C7 C3 + 4 --*-----/-\-----*3-4------------*-*4+5--*-----*---------------> 1 + / \ -C4 X \ /S7 C3 + 5 --*---/-----\---*2-5---*-*------*=*4-5----\-/------*-*--------> 5 + / \ X S4,S4 / X S3,-S3 + 6 --*-/---------\-*1-6---*-*------*=*7-6----/-\------*-*--------> 3 + / \ C4 X / \-S7 C3 + --*-------------*0-7------------*-*7+6--*-----*---------------> 7 + C7 + +Notation + Cn = cos(n*pi/8) used throughout the code. + + + Registers used: + R0, R1, R2, R3, R4, R5, R6,R7, P0, P1, P2, P3, P4, P5, A0, A1. + Other registers used: + I0, I1, I2, I3, B0, B2, B3, M0, M1, L3 registers and LC0. + + Input - r0 - pointer to start of int16_t *block + + Output - The DCT output coefficients in the int16_t *block + + Register constraint: + This code is called from jpeg_encode. + R6, R5, R4 if modified should be stored and restored. + + + Performance: (Timer version 0.6.33) + Code Size : 240 Bytes. + Memory Required : + Input Matrix : 8 * 8 * 2 Bytes. + Coefficients : 16 Bytes + Temporary matrix: 8 * 8 * 2 Bytes. + Cycle Count :26+{18+8*(14+2S)}*2 where S -> Stalls + (7.45 c/pel) + ----------------------------------------- + | Size | Forward DCT | Inverse DCT | + ----------------------------------------- + | 8x8 | 284 Cycles | 311 Cycles | + ----------------------------------------- + +Ck = int16(cos(k/16*pi)*32767+.5)/2 +#define C4 23170 +#define C3 13623 +#define C6 6270 +#define C7 3196 + +Sk = int16(sin(k/16*pi)*32767+.5)/2 +#define S4 11585 +#define S3 9102 +#define S6 15137 +#define S7 16069 + +the coefficients are ordered as follows: +short dct_coef[] + C4,S4, + C6,S6, + C7,S7, + S3,C3, + +----------------------------------------------------------- +FFMPEG conformance testing results +----------------------------------------------------------- +dct-test: modified with the following + dct_error("BFINfdct", 0, ff_bfin_fdct, fdct, test); +produces the following output: + +root:/u/ffmpeg/bhead/libavcodec> ./dct-test +ffmpeg DCT/IDCT test + + 2 -131 -6 -48 -36 33 -83 24 + 34 52 -24 -15 5 92 57 143 + -67 -43 -1 74 -16 5 -71 32 + -78 106 92 -34 -38 81 20 -18 + 7 -62 40 2 -15 90 -62 -83 + -83 1 -104 -13 43 -19 7 11 + -63 31 12 -29 83 72 21 10 + -17 -63 -15 73 50 -91 159 -14 +DCT BFINfdct: err_inf=2 err2=0.16425938 syserr=0.00795000 maxout=2098 blockSumErr=27 +DCT BFINfdct: 92.1 kdct/s +root:/u/ffmpeg/bhead/libavcodec> + +*/ + +#include "config.h" +#include "config_bfin.h" + +#if defined(__FDPIC__) && CONFIG_SRAM +.section .l1.data.B,"aw",@progbits +#else +.data +#endif +.align 4; +dct_coeff: +.short 0x5a82, 0x2d41, 0x187e, 0x3b21, 0x0c7c, 0x3ec5, 0x238e, 0x3537; + +#if defined(__FDPIC__) && CONFIG_SRAM +.section .l1.data.A,"aw",@progbits +#endif +.align 4 +vtmp: .space 128 + +.text +DEFUN(fdct,mL1, + (int16_t *block)): + [--SP] = (R7:4, P5:3); // Push the registers onto the stack. + + b0 = r0; + RELOC(r0, P3, dct_coeff); + b3 = r0; + RELOC(r0, P3, vtmp); + b2 = r0; + + L3 = 16; // L3 is set to 16 to make the coefficient + // array Circular. + + +//---------------------------------------------------------------------------- + +/* + * I0, I1, and I2 registers are used to read the input data. I3 register is used + * to read the coefficients. P0 and P1 registers are used for writing the output + * data. + */ + M0 = 12 (X); // All these initializations are used in the + M1 = 16 (X); // modification of address offsets. + + M2 = 128 (X); + + P2 = 16; + P3 = 32 (X); + P4 = -110 (X); + P5 = -62 (X); + P0 = 2(X); + + + // Prescale the input to get the correct precision. + i0=b0; + i1=b0; + + lsetup (.0, .1) LC0 = P3; + r0=[i0++]; +.0: r1=r0<<3 (v) || r0=[i0++] ; +.1: [i1++]=r1; + + /* + * B0 points to the "in" buffer. + * B2 points to "temp" buffer in the first iteration. + */ + + lsetup (.2, .3) LC0 = P0; +.2: + I0 = B0; // I0 points to Input Element (0, 0). + I1 = B0; // Element 1 and 0 is read in R0. + I1 += M0 || R0 = [I0++]; // I1 points to Input Element (0, 6). + I2 = I1; // Element 6 is read into R3.H. + I2 -= 4 || R3.H = W[I1++]; // I2 points to Input Element (0, 4). + + I3 = B3; // I3 points to Coefficients. + P0 = B2; // P0 points to temporary array Element + // (0, 0). + P1 = B2; // P1 points to temporary array. + R7 = [P1++P2] || R2 = [I2++]; // P1 points to temporary array + // Element (1, 0). + // R7 is a dummy read. X4,X5 + // are read into R2. + R3.L = W[I1--]; // X7 is read into R3.L. + R1.H = W[I0++]; // X2 is read into R1.H. + + + /* + * X0 = (X0 + X7) / 2. + * X1 = (X1 + X6) / 2. + * X6 = (X1 - X6) / 2. + * X7 = (X0 - X7) / 2. + * It reads the data 3 in R1.L. + */ + + R0 = R0 +|+ R3, R3 = R0 -|- R3 || R1.L = W[I0++] || NOP; + + /* + * X2 = (X2 + X5) / 2. + * X3 = (X3 + X4) / 2. + * X4 = (X3 - X4) / 2. + * X5 = (X2 - X5) / 2. + * R7 = C4 = cos(4*pi/16) + */ + + R1 = R1 +|+ R2, R2 = R1 -|- R2 (CO) || NOP || R7 = [I3++]; + + /* + * At the end of stage 1 R0 has (1,0), R1 has (2,3), R2 has (4, 5) and + * R3 has (6,7). + * Where the notation (x, y) represents uper/lower half pairs. + */ + + /* + * X0 = X0 + X3. + * X1 = X1 + X2. + * X2 = X1 - X2. + * X3 = X0 - X3. + */ + R0 = R0 +|+ R1, R1 = R0 -|- R1; + + lsetup (.row0, .row1) LC1 = P2 >> 1; // 1d dct, loops 8x +.row0: + + /* + * This is part 2 computation continued..... + * A1 = X6 * cos(pi/4) + * A0 = X6 * cos(pi/4) + * A1 = A1 - X5 * cos(pi/4) + * A0 = A0 + X5 * cos(pi/4). + * The instruction W[I0] = R3.L is used for packing it to R2.L. + */ + + A1=R3.H*R7.l, A0=R3.H*R7.l || I1+=M1 || W[I0] = R3.L; + R4.H=(A1-=R2.L*R7.l), R4.L=(A0+=R2.L*R7.l) || I2+=M0 || NOP; + + /* R0 = (X1,X0) R1 = (X2,X3) R4 = (X5, X6). */ + + /* + * A1 = X0 * cos(pi/4) + * A0 = X0 * cos(pi/4) + * A1 = A1 - X1 * cos(pi/4) + * A0 = A0 + X1 * cos(pi/4) + * R7 = (C2,C6) + */ + A1=R0.L*R7.h, A0=R0.L*R7.h || NOP || R3.H=W[I1++]; + R5.H=(A1-=R0.H*R7.h),R5.L=(A0+=R0.H*R7.h) || R7=[I3++] || NOP; + + /* + * A1 = X2 * cos(3pi/8) + * A0 = X3 * cos(3pi/8) + * A1 = A1 + X3 * cos(pi/8) + * A0 = A0 - X2 * cos(pi/8) + * R3 = cos(pi/4) + * R7 = (cos(7pi/8),cos(pi/8)) + * X4 = X4 + X5. + * X5 = X4 - X5. + * X6 = X7 - X6. + * X7 = X7 + X6. + */ + A1=R1.H*R7.L, A0=R1.L*R7.L || W[P0++P3]=R5.L || R2.L=W[I0]; + R2=R2+|+R4, R4=R2-|-R4 || I0+=4 || R3.L=W[I1--]; + R6.H=(A1+=R1.L*R7.H),R6.L=(A0 -= R1.H * R7.H) || I0+=4 || R7=[I3++]; + + /* R2 = (X4, X7) R4 = (X5,X6) R5 = (X1, X0) R6 = (X2,X3). */ + + /* + * A1 = X4 * cos(7pi/16) + * A0 = X7 * cos(7pi/16) + * A1 = A1 + X7 * cos(pi/16) + * A0 = A0 - X4 * cos(pi/16) + */ + + A1=R2.H*R7.L, A0=R2.L*R7.L || W[P0++P3]=R6.H || R0=[I0++]; + R2.H=(A1+=R2.L*R7.H),R2.L=(A0-=R2.H*R7.H) || W[P0++P3]=R5.H || R7=[I3++]; + + /* + * A1 = X5 * cos(3pi/16) + * A0 = X6 * cos(3pi/16) + * A1 = A1 + X6 * cos(5pi/16) + * A0 = A0 - X5 * cos(5pi/16) + * The output values are written. + */ + + A1=R4.H*R7.H, A0=R4.L*R7.H || W[P0++P2]=R6.L || R1.H=W[I0++]; + R4.H=(A1+=R4.L*R7.L),R4.L=(A0-=R4.H*R7.L) || W[P0++P4]=R2.L || R1.L=W[I0++]; + + + /* Beginning of next stage, **pipelined** + drain and store the + rest of the column store. */ + + R0=R0+|+R3,R3=R0-|-R3 || W[P1++P3]=R2.H || R2=[I2++]; + R1=R1+|+R2,R2=R1-|-R2 (CO) || W[P1++P3]=R4.L || R7=[I3++]; +.row1: R0=R0+|+R1,R1=R0-|-R1 || W[P1++P5]=R4.H || NOP; + + // Exchange input with output. + B1 = B0; + B0 = B2; +.3: B2 = B1; + + L3=0; + (r7:4,p5:3) = [sp++]; + RTS; +DEFUN_END(fdct) diff --git a/ffmpeg/libavcodec/bfin/hpel_pixels_bfin.S b/ffmpeg/libavcodec/bfin/hpel_pixels_bfin.S new file mode 100644 index 0000000..b22bc29 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/hpel_pixels_bfin.S @@ -0,0 +1,379 @@ +/* + * Blackfin Pixel Operations + * Copyright (C) 2007 Marc Hoffman + * + * 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 "config_bfin.h" + +/** + motion compensation + primitives + + * Halfpel motion compensation with rounding (a+b+1)>>1. + * This is an array[4][4] of motion compensation funcions for 4 + * horizontal blocksizes (8,16) and the 4 halfpel positions
+ * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + +*/ + +DEFUN(put_pixels8uc,mL1, + (uint8_t *block, const uint8_t *s0, const uint8_t *s1, + int dest_size, int line_size, int h)): + i3=r0; // dest + i0=r1; // src0 + i1=r2; // src1 + r0=[sp+12]; // dest_size + r2=[sp+16]; // line_size + p0=[sp+20]; // h + [--sp] = (r7:6); + r0+=-4; + m3=r0; + r2+=-8; + m0=r2; + LSETUP(pp8$0,pp8$1) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +pp8$0: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R6 = BYTEOP1P(R1:0,R3:2) || R0 = [I0++M0]|| R2 =[I1++M0]; + R7 = BYTEOP1P(R1:0,R3:2)(R) || R0 = [I0++] || [I3++] = R6 ; +pp8$1: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; + + (r7:6) = [sp++]; + RTS; +DEFUN_END(put_pixels8uc) + +DEFUN(put_pixels16uc,mL1, + (uint8_t *block, const uint8_t *s0, const uint8_t *s1, + int dest_size, int line_size, int h)): + link 0; + [--sp] = (r7:6); + i3=r0; // dest + i0=r1; // src0 + i1=r2; // src1 + r0=[fp+20]; // dest_size + r2=[fp+24]; // line_size + p0=[fp+28]; // h + + + r0+=-12; + m3=r0; // line_size + r2+=-16; + m0=r2; + + LSETUP(pp16$0,pp16$1) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +pp16$0: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R6 = BYTEOP1P(R1:0,R3:2) || R0 = [I0++] || R2 =[I1++]; + R7 = BYTEOP1P(R1:0,R3:2)(R) || R1 = [I0++] || R3 =[I1++]; + [I3++] = R6; + R6 = BYTEOP1P(R1:0,R3:2) || R0 = [I0++M0] || R2 =[I1++M0]; + R7 = BYTEOP1P(R1:0,R3:2)(R) || R0 = [I0++] || [I3++] = R7 ; + [I3++] = R6; +pp16$1: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; + + (r7:6) = [sp++]; + unlink; + RTS; +DEFUN_END(put_pixels16uc) + + + + + + +DEFUN(put_pixels8uc_nornd,mL1, + (uint8_t *block, const uint8_t *s0, const uint8_t *s1, + int line_size, int h)): + i3=r0; // dest + i0=r1; // src0 + i1=r2; // src1 + r2=[sp+12]; // line_size + p0=[sp+16]; // h + [--sp] = (r7:6); + r2+=-4; + m3=r2; + r2+=-4; + m0=r2; + LSETUP(pp8$2,pp8$3) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +pp8$2: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R6 = BYTEOP1P(R1:0,R3:2)(T) || R0 = [I0++M0]|| R2 =[I1++M0]; + R7 = BYTEOP1P(R1:0,R3:2)(T,R) || R0 = [I0++] || [I3++] = R6 ; +pp8$3: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; + + (r7:6) = [sp++]; + RTS; +DEFUN_END(put_pixels8uc_nornd) + +DEFUN(put_pixels16uc_nornd,mL1, + (uint8_t *block, const uint8_t *s0, const uint8_t *s1, + int line_size, int h)): + i3=r0; // dest + i0=r1; // src0 + i1=r2; // src1 + r2=[sp+12]; // line_size + p0=[sp+16]; // h + + [--sp] = (r7:6); + r2+=-12; + m3=r2; // line_size + r2+=-4; + m0=r2; + + LSETUP(pp16$2,pp16$3) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +pp16$2: + DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R6 = BYTEOP1P(R1:0,R3:2)(T) || R0 = [I0++] || R2 =[I1++]; + R7 = BYTEOP1P(R1:0,R3:2)(T,R) || R1 = [I0++] || R3 =[I1++]; + [I3++] = R6; + + R6 = BYTEOP1P(R1:0,R3:2)(T) || R0 = [I0++M0] || R2 =[I1++M0]; + R7 = BYTEOP1P(R1:0,R3:2)(T,R) || R0 = [I0++] || [I3++] = R7 ; + [I3++] = R6; +pp16$3: DISALGNEXCPT || R2 = [I1++] || [I3++M3] = R7; + + (r7:6) = [sp++]; + + RTS; +DEFUN_END(put_pixels16uc_nornd) + +DEFUN(z_put_pixels16_xy2,mL1, + (uint8_t *block, const uint8_t *s0, + int dest_size, int line_size, int h)): + link 0; + [--sp] = (r7:4); + i3=r0; // dest + i0=r1; // src0--> pixels + i1=r1; // src1--> pixels + line_size + r2+=-12; + m2=r2; // m2=dest_width-4 + r2=[fp+20]; + m3=r2; // line_size + p0=[fp+24]; // h + r2+=-16; + i1+=m3; /* src1 + line_size */ + m0=r2; /* line-size - 20 */ + + B0 = I0; + B1 = I1; + B3 = I3; + + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + + LSETUP(LS$16E,LE$16E) LC0=P0; +LS$16E: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (RNDL) || R0 = [I0++] || R2 =[I1++]; + R5 = BYTEOP2P (R3:2,R1:0) (RNDL,R) || R1 = [I0++] || [I3++] = R4 ; + DISALGNEXCPT || R3 = [I1++] || [I3++] = R5; + R4 = BYTEOP2P (R3:2,R1:0) (RNDL) || R0 = [I0++M0]|| R2 = [I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (RNDL,R) || R0 = [I0++] || [I3++] = R4 ; +LE$16E: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; + + M1 = 1; + I3 = B3; + I1 = B1; + I0 = B0; + + I0 += M1; + I1 += M1; + + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + LSETUP(LS$16O,LE$16O) LC0=P0; +LS$16O: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (RNDH) || R0 = [I0++] || R2 =[I1++]; + R5 = BYTEOP2P (R3:2,R1:0) (RNDH,R) || R1 = [I0++] || R6 =[I3++]; + R4 = R4 +|+ R6 || R7 = [I3--]; + R5 = R5 +|+ R7 || [I3++] = R4; + DISALGNEXCPT || R3 =[I1++] || [I3++] = R5; + R4 = BYTEOP2P (R3:2,R1:0) (RNDH) || R0 = [I0++M0]|| R2 = [I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (RNDH,R) || R0 = [I0++] || R6 = [I3++]; + R4 = R4 +|+ R6 || R7 = [I3--]; + R5 = R5 +|+ R7 || [I3++] = R4; +LE$16O: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; + + (r7:4) = [sp++]; + unlink; + rts; +DEFUN_END(z_put_pixels16_xy2) + +DEFUN(put_pixels16_xy2_nornd,mL1, + (uint8_t *block, const uint8_t *s0, + int line_size, int h)): + link 0; + [--sp] = (r7:4); + i3=r0; // dest + i0=r1; // src0--> pixels + i1=r1; // src1--> pixels + line_size + m3=r2; + r2+=-12; + m2=r2; + r2+=-4; + i1+=m3; /* src1 + line_size */ + m0=r2; /* line-size - 20 */ + p0=[fp+20]; // h + + B0=I0; + B1=I1; + B3=I3; + + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + + LSETUP(LS$16ET,LE$16ET) LC0=P0; +LS$16ET:DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (TL) || R0 = [I0++] || R2 =[I1++]; + R5 = BYTEOP2P (R3:2,R1:0) (TL,R) || R1 = [I0++] || [I3++] = R4 ; + DISALGNEXCPT || R3 = [I1++] || [I3++] = R5; + R4 = BYTEOP2P (R3:2,R1:0) (TL) || R0 = [I0++M0]|| R2 = [I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (TL,R) || R0 = [I0++] || [I3++] = R4 ; +LE$16ET:DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; + + M1 = 1; + I3=B3; + I1=B1; + I0=B0; + + I0 += M1; + I1 += M1; + + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + LSETUP(LS$16OT,LE$16OT) LC0=P0; +LS$16OT:DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (TH) || R0 = [I0++] || R2 =[I1++]; + R5 = BYTEOP2P (R3:2,R1:0) (TH,R) || R1 = [I0++] || R6 =[I3++]; + R4 = R4 +|+ R6 || R7 = [I3--]; + R5 = R5 +|+ R7 || [I3++] = R4; + DISALGNEXCPT || R3 =[I1++] || [I3++] = R5; + R4 = BYTEOP2P (R3:2,R1:0) (TH) || R0 = [I0++M0]|| R2 = [I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (TH,R) || R0 = [I0++] || R6 = [I3++]; + R4 = R4 +|+ R6 || R7 = [I3--]; + R5 = R5 +|+ R7 || [I3++] = R4; +LE$16OT:DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; + + (r7:4) = [sp++]; + unlink; + rts; +DEFUN_END(put_pixels16_xy2_nornd) + +DEFUN(z_put_pixels8_xy2,mL1, + (uint8_t *block, const uint8_t *s0, + int dest_size, int line_size, int h)): + link 0; + [--sp] = (r7:4); + i3=r0; // dest + i0=r1; // src0--> pixels + i1=r1; // src1--> pixels + line_size + r2+=-4; + m2=r2; // m2=dest_width-4 + r2=[fp+20]; + m3=r2; // line_size + p0=[fp+24]; // h + r2+=-8; + i1+=m3; /* src1 + line_size */ + m0=r2; /* line-size - 20 */ + + b0 = I0; + b1 = I1; + b3 = I3; + + LSETUP(LS$8E,LE$8E) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; +LS$8E: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (RNDL) || R0 = [I0++M0] || R2 =[I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (RNDL,R) || R0 = [I0++] || [I3++] = R4 ; +LE$8E: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; + + M1 = 1; + I3 = b3; + I1 = b1; + I0 = b0; + + I0 += M1; + I1 += M1; + + LSETUP(LS$8O,LE$8O) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; +LS$8O: DISALGNEXCPT || R1 = [I0++] || R3 =[I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (RNDH) || R0 = [I0++M0] || R2 =[I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (RNDH,R) || R0 = [I0++] || R6 =[I3++]; + R4 = R4 +|+ R6 || R7 = [I3--]; + R5 = R5 +|+ R7 || [I3++] = R4; +LE$8O: DISALGNEXCPT || R2 =[I1++] || [I3++M2] = R5; + + (r7:4) = [sp++]; + unlink; + rts; +DEFUN_END(z_put_pixels8_xy2) + +DEFUN(put_pixels8_xy2_nornd,mL1, + (uint8_t *block, const uint8_t *s0, int line_size, int h)): + link 0; + [--sp] = (r7:4); + i3=r0; // dest + i0=r1; // src0--> pixels + i1=r1; // src1--> pixels + line_size + m3=r2; + r2+=-4; + m2=r2; + r2+=-4; + i1+=m3; /* src1 + line_size */ + m0=r2; /* line-size - 20 */ + p0=[fp+20]; // h + + + b0 = I0; + b1 = I1; + b3 = I3; + + LSETUP(LS$8ET,LE$8ET) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +LS$8ET: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (TL) || R0 = [I0++M0] || R2 = [I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (TL,R) || R0 = [I0++] || [I3++] = R4 ; +LE$8ET: DISALGNEXCPT || R2 = [I1++] || [I3++M2] = R5; + + M1 = 1; + I3 = b3; + I1 = b1; + I0 = b0; + + I0 += M1; + I1 += M1; + + LSETUP(LS$8OT,LE$8OT) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 = [I1++]; + +LS$8OT: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + R4 = BYTEOP2P (R3:2,R1:0) (TH) || R0 = [I0++M0] || R2 = [I1++M0]; + R5 = BYTEOP2P (R3:2,R1:0) (TH,R) || R0 = [I0++] || R6 = [I3++]; + R4 = R4 +|+ R6 || R7 = [I3--]; + R5 = R5 +|+ R7 || [I3++] = R4; +LE$8OT: DISALGNEXCPT || R2 =[I1++] || [I3++M2] = R5; + + (r7:4) = [sp++]; + unlink; + rts; +DEFUN_END(put_pixels8_xy2_nornd) diff --git a/ffmpeg/libavcodec/bfin/hpeldsp_bfin.c b/ffmpeg/libavcodec/bfin/hpeldsp_bfin.c new file mode 100644 index 0000000..8b4af49 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/hpeldsp_bfin.c @@ -0,0 +1,119 @@ +/* + * BlackFin DSPUTILS + * + * Copyright (C) 2007 Marc Hoffman + * Copyright (c) 2006 Michael Benjamin + * + * 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 "libavcodec/hpeldsp.h" +#include "hpeldsp_bfin.h" + +static void bfin_put_pixels8 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels8uc (block, pixels, pixels, line_size, line_size, h); +} + +static void bfin_put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels8uc (block, pixels, pixels+1, line_size, line_size, h); +} + +static void bfin_put_pixels8_y2 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels8uc (block, pixels, pixels+line_size, line_size, line_size, h); +} + +static void bfin_put_pixels8_xy2 (uint8_t *block, const uint8_t *s0, ptrdiff_t line_size, int h) +{ + ff_bfin_z_put_pixels8_xy2 (block,s0,line_size, line_size, h); +} + +static void bfin_put_pixels16 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels16uc (block, pixels, pixels, line_size, line_size, h); +} + +static void bfin_put_pixels16_x2 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels16uc (block, pixels, pixels+1, line_size, line_size, h); +} + +static void bfin_put_pixels16_y2 (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels16uc (block, pixels, pixels+line_size, line_size, line_size, h); +} + +static void bfin_put_pixels16_xy2 (uint8_t *block, const uint8_t *s0, ptrdiff_t line_size, int h) +{ + ff_bfin_z_put_pixels16_xy2 (block,s0,line_size, line_size, h); +} + +static void bfin_put_pixels8_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels8uc_nornd (block, pixels, pixels, line_size, h); +} + +static void bfin_put_pixels8_x2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels8uc_nornd (block, pixels, pixels+1, line_size, h); +} + +static void bfin_put_pixels8_y2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels8uc_nornd (block, pixels, pixels+line_size, line_size, h); +} + + +static void bfin_put_pixels16_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels16uc_nornd (block, pixels, pixels, line_size, h); +} + +static void bfin_put_pixels16_x2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels16uc_nornd (block, pixels, pixels+1, line_size, h); +} + +static void bfin_put_pixels16_y2_nornd (uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + ff_bfin_put_pixels16uc_nornd (block, pixels, pixels+line_size, line_size, h); +} + +void ff_hpeldsp_init_bfin(HpelDSPContext* c, int flags) +{ + c->put_pixels_tab[0][0] = bfin_put_pixels16; + c->put_pixels_tab[0][1] = bfin_put_pixels16_x2; + c->put_pixels_tab[0][2] = bfin_put_pixels16_y2; + c->put_pixels_tab[0][3] = bfin_put_pixels16_xy2; + + c->put_pixels_tab[1][0] = bfin_put_pixels8; + c->put_pixels_tab[1][1] = bfin_put_pixels8_x2; + c->put_pixels_tab[1][2] = bfin_put_pixels8_y2; + c->put_pixels_tab[1][3] = bfin_put_pixels8_xy2; + + c->put_no_rnd_pixels_tab[1][0] = bfin_put_pixels8_nornd; + c->put_no_rnd_pixels_tab[1][1] = bfin_put_pixels8_x2_nornd; + c->put_no_rnd_pixels_tab[1][2] = bfin_put_pixels8_y2_nornd; +/* c->put_no_rnd_pixels_tab[1][3] = ff_bfin_put_pixels8_xy2_nornd; */ + + c->put_no_rnd_pixels_tab[0][0] = bfin_put_pixels16_nornd; + c->put_no_rnd_pixels_tab[0][1] = bfin_put_pixels16_x2_nornd; + c->put_no_rnd_pixels_tab[0][2] = bfin_put_pixels16_y2_nornd; +/* c->put_no_rnd_pixels_tab[0][3] = ff_bfin_put_pixels16_xy2_nornd; */ +} diff --git a/ffmpeg/libavcodec/bfin/hpeldsp_bfin.h b/ffmpeg/libavcodec/bfin/hpeldsp_bfin.h new file mode 100644 index 0000000..36f3872 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/hpeldsp_bfin.h @@ -0,0 +1,50 @@ +/* + * BlackFin DSPUTILS COMMON OPTIMIZATIONS HEADER + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ + + +#ifndef AVCODEC_BFIN_HPELDSP_BFIN_H +#define AVCODEC_BFIN_HPELDSP_BFIN_H + +#include + +#include "config.h" + +#if defined(__FDPIC__) && CONFIG_SRAM +#define attribute_l1_text __attribute__ ((l1_text)) +#define attribute_l1_data_b __attribute__((l1_data_B)) +#else +#define attribute_l1_text +#define attribute_l1_data_b +#endif + +void ff_bfin_z_put_pixels16_xy2 (uint8_t *block, const uint8_t *s0, int dest_size, int line_size, int h) attribute_l1_text; +void ff_bfin_z_put_pixels8_xy2 (uint8_t *block, const uint8_t *s0, int dest_size, int line_size, int h) attribute_l1_text; +void ff_bfin_put_pixels16_xy2_nornd (uint8_t *block, const uint8_t *s0, int line_size, int h) attribute_l1_text; +void ff_bfin_put_pixels8_xy2_nornd (uint8_t *block, const uint8_t *s0, int line_size, int h) attribute_l1_text; + + +void ff_bfin_put_pixels8uc (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int dest_size, int line_size, int h) attribute_l1_text; +void ff_bfin_put_pixels16uc (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int dest_size, int line_size, int h) attribute_l1_text; +void ff_bfin_put_pixels8uc_nornd (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int line_size, int h) attribute_l1_text; +void ff_bfin_put_pixels16uc_nornd (uint8_t *block, const uint8_t *s0, const uint8_t *s1, int line_size, int h) attribute_l1_text; + +#endif /* AVCODEC_BFIN_HPELDSP_BFIN_H */ diff --git a/ffmpeg/libavcodec/bfin/idct_bfin.S b/ffmpeg/libavcodec/bfin/idct_bfin.S new file mode 100644 index 0000000..bd80447 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/idct_bfin.S @@ -0,0 +1,304 @@ +/* + * idct BlackFin + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ +/* + This blackfin DSP code implements an 8x8 inverse type II DCT. + +Prototype : void ff_bfin_idct(int16_t *in) + +Registers Used : A0, A1, R0-R7, I0-I3, B0, B2, B3, M0-M2, L0-L3, P0-P5, LC0. + +Performance : + Code Size : 498 Bytes. + Cycle Count : 417 Cycles + + +----------------------------------------------------------- +FFMPEG conformance testing results +----------------------------------------------------------- + +dct-test: modified with the following + dct_error("BFINidct", 1, ff_bfin_idct, idct, test); +produces the following output + +root:/u/ffmpeg/bhead/libavcodec> ./dct-test -i +ffmpeg DCT/IDCT test + + 8 15 -2 21 24 17 0 10 + 2 -10 -5 -5 -3 7 -14 -3 + 2 -13 -10 -19 18 -6 6 -2 + 9 4 16 -3 9 12 10 15 + 15 -9 -2 10 1 16 0 -15 + -15 5 7 3 13 0 13 20 + -6 -15 24 9 -18 1 9 -22 + -8 25 23 2 -7 0 30 13 +IDCT BFINidct: err_inf=1 err2=0.01002344 syserr=0.00150000 maxout=266 blockSumErr=64 +IDCT BFINidct: 88.3 kdct/s + +*/ + +#include "config.h" +#include "config_bfin.h" + +#if defined(__FDPIC__) && CONFIG_SRAM +.section .l1.data.B,"aw",@progbits +#else +.data +#endif + +.align 4; +coefs: +.short 0x5a82; // C4 +.short 0x5a82; // C4 +.short 0x30FC; //cos(3pi/8) C6 +.short 0x7642; //cos(pi/8) C2 +.short 0x18F9; //cos(7pi/16) +.short 0x7D8A; //cos(pi/16) +.short 0x471D; //cos(5pi/16) +.short 0x6A6E; //cos(3pi/16) +.short 0x18F9; //cos(7pi/16) +.short 0x7D8A; //cos(pi/16) + +#if defined(__FDPIC__) && CONFIG_SRAM +.section .l1.data.A,"aw",@progbits +#endif + +vtmp: .space 256 + +#define TMP0 FP-8 +#define TMP1 FP-12 +#define TMP2 FP-16 + + +.text +DEFUN(idct,mL1, + (int16_t *block)): + +/********************** Function Prologue *********************************/ + link 16; + [--SP] = (R7:4, P5:3); // Push the registers onto the stack. + B0 = R0; // Pointer to Input matrix + RELOC(R1, P3, coefs); // Pointer to Coefficients + RELOC(R2, P3, vtmp); // Pointer to Temporary matrix + B3 = R1; + B2 = R2; + L3 = 20; // L3 is used for making the coefficient array + // circular. + // MUST BE RESTORED TO ZERO at function exit. + M1 = 16 (X); // All these registers are initialized for + M3 = 8(X); // modifying address offsets. + + I0 = B0; // I0 points to Input Element (0, 0). + I2 = B0; // I2 points to Input Element (0, 0). + I2 += M3 || R0.H = W[I0]; + // Element 0 is read into R0.H + I1 = I2; // I1 points to input Element (0, 6). + I1 += 4 || R0.L = W[I2++]; + // I2 points to input Element (0, 4). + // Element 4 is read into R0.L. + P2 = 8 (X); + P3 = 32 (X); + P4 = -32 (X); + P5 = 98 (X); + R7 = 0x8000(Z); + I3 = B3; // I3 points to Coefficients + P0 = B2; // P0 points to array Element (0, 0) of temp + P1 = B2; + R7 = [I3++] || [TMP2]=R7; // Coefficient C4 is read into R7.H and R7.L. + MNOP; + NOP; + + /* + * A1 = Y0 * cos(pi/4) + * A0 = Y0 * cos(pi/4) + * A1 = A1 + Y4 * cos(pi/4) + * A0 = A0 - Y4 * cos(pi/4) + * load: + * R1=(Y2,Y6) + * R7=(C2,C6) + * res: + * R3=Y0, R2=Y4 + */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+= 4 || R1.L=W[I1++]; + R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; + + LSETUP (.0, .1) LC0 = P2; // perform 8 1d idcts + + P2 = 112 (X); + P1 = P1 + P2; // P1 points to element (7, 0) of temp buffer. + P2 = -94(X); + +.0: + /* + * A1 = Y2 * cos(3pi/8) + * A0 = Y2 * cos(pi/8) + * A1 = A1 - Y6 * cos(pi/8) + * A0 = A0 + Y6 * cos(3pi/8) + * R5 = (Y1,Y7) + * R7 = (C1,C7) + * res: + * R1=Y2, R0=Y6 + */ + A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; + R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; + /* + * Y0 = Y0 + Y6. + * Y4 = Y4 + Y2. + * Y2 = Y4 - Y2. + * Y6 = Y0 - Y6. + * R3 is saved + * R6.l=Y3 + * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 + */ + R3=R3+R0, R0=R3-R0; + R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; + /* + * Compute the odd portion (1,3,5,7) even is done. + * + * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. + * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. + * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. + * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. + */ + // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; + A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; + A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) + R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; + A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) + A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); + R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; + // R3=Y1, R2=Y7, R7=Y5, R6=Y3 + + /* Transpose write column. */ + R5.H=R4+R2 (RND12); // Y0=Y0+Y7 + R5.L=R4-R2 (RND12) || R4 = [TMP1]; // Y7=Y7-Y0 + R2.H=R1+R7 (RND12) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 + R2.L=R1-R7 (RND12) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 + R5.H=R0-R3 (RND12) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 + R5.L=R0+R3 (RND12) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 + R3.H=R4-R6 (RND12) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 + R3.L=R4+R6 (RND12) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 + + /* pipeline loop start, + drain Y3, Y4 */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; +.1: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; + + + + I0 = B2; // I0 points to Input Element (0, 0) + I2 = B2; // I2 points to Input Element (0, 0) + I2 += M3 || R0.H = W[I0]; + // Y0 is read in R0.H + I1 = I2; // I1 points to input Element (0, 6) + I1 += 4 || R0.L = W[I2++]; + // I2 points to input Element (0, 4) + // Y4 is read in R0.L + P2 = 8 (X); + I3 = B3; // I3 points to Coefficients + P0 = B0; // P0 points to array Element (0, 0) for writing + // output + P1 = B0; + R7 = [I3++]; // R7.H = C4 and R7.L = C4 + NOP; + + /* + * A1 = Y0 * cos(pi/4) + * A0 = Y0 * cos(pi/4) + * A1 = A1 + Y4 * cos(pi/4) + * A0 = A0 - Y4 * cos(pi/4) + * load: + * R1=(Y2,Y6) + * R7=(C2,C6) + * res: + * R3=Y0, R2=Y4 + */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+=4 || R1.L=W[I1++]; + R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; + + LSETUP (.2, .3) LC0 = P2; // peform 8 1d idcts + P2 = 112 (X); + P1 = P1 + P2; + P2 = -94(X); + +.2: + /* + * A1 = Y2 * cos(3pi/8) + * A0 = Y2 * cos(pi/8) + * A1 = A1 - Y6 * cos(pi/8) + * A0 = A0 + Y6 * cos(3pi/8) + * R5 = (Y1,Y7) + * R7 = (C1,C7) + * res: + * R1=Y2, R0=Y6 + */ + A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; + R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; + /* + * Y0 = Y0 + Y6. + * Y4 = Y4 + Y2. + * Y2 = Y4 - Y2. + * Y6 = Y0 - Y6. + * R3 is saved + * R6.l=Y3 + * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 + */ + R3=R3+R0, R0=R3-R0; + R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; + /* + * Compute the odd portion (1,3,5,7) even is done. + * + * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. + * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. + * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. + * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. + */ + // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; + A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; + A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) + R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; + A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) + A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); + R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; + // R3=Y1, R2=Y7, R7=Y5, R6=Y3 + + /* Transpose write column. */ + R5.H=R4+R2 (RND20); // Y0=Y0+Y7 + R5.L=R4-R2 (RND20) || R4 = [TMP1]; // Y7=Y7-Y0 + R2.H=R1+R7 (RND20) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 + R2.L=R1-R7 (RND20) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 + R5.H=R0-R3 (RND20) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 + R5.L=R0+R3 (RND20) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 + R3.H=R4-R6 (RND20) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 + R3.L=R4+R6 (RND20) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 + + /* pipeline loop start, + drain Y3, Y4 */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; +.3: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; + + L3 = 0; + (R7:4,P5:3)=[SP++]; + unlink; + RTS; +DEFUN_END(idct) diff --git a/ffmpeg/libavcodec/bfin/mathops.h b/ffmpeg/libavcodec/bfin/mathops.h new file mode 100644 index 0000000..50c0316 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/mathops.h @@ -0,0 +1,44 @@ +/* + * simple math operations + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ +#ifndef AVCODEC_BFIN_MATHOPS_H +#define AVCODEC_BFIN_MATHOPS_H + +#include "config.h" + +#define MULH(X,Y) ({ int xxo; \ + __asm__ ( \ + "a1 = %2.L * %1.L (FU);\n\t" \ + "a1 = a1 >> 16;\n\t" \ + "a1 += %2.H * %1.L (IS,M);\n\t" \ + "a0 = %1.H * %2.H, a1+= %1.H * %2.L (IS,M);\n\t"\ + "a1 = a1 >>> 16;\n\t" \ + "%0 = (a0 += a1);\n\t" \ + : "=d" (xxo) : "d" (X), "d" (Y) : "A0","A1"); xxo; }) + +/* signed 16x16 -> 32 multiply */ +#define MUL16(a, b) ({ int xxo; \ + __asm__ ( \ + "%0 = %1.l*%2.l (is);\n\t" \ + : "=W" (xxo) : "d" (a), "d" (b) : "A1"); \ + xxo; }) + +#endif /* AVCODEC_BFIN_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/bfin/mpegvideo_bfin.c b/ffmpeg/libavcodec/bfin/mpegvideo_bfin.c new file mode 100644 index 0000000..458e7dc --- /dev/null +++ b/ffmpeg/libavcodec/bfin/mpegvideo_bfin.c @@ -0,0 +1,152 @@ +/* + * BlackFin MPEGVIDEO OPTIMIZATIONS + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpegvideo.h" +#include "dsputil_bfin.h" + +static int dct_quantize_bfin (MpegEncContext *s, + int16_t *block, int n, + int qscale, int *overflow) +{ + int last_non_zero, q, start_i; + const short *qmat; + short *bias; + const uint8_t *scantable= s->intra_scantable.scantable; + short dc; + int max=0; + + PROF("fdct",0); + s->dsp.fdct(block); + EPROF(); + + PROF("denoise",1); + if(s->dct_error_sum) + s->denoise_dct(s, block); + EPROF(); + + PROF("quant-init",2); + if (s->mb_intra) { + if (!s->h263_aic) { + if (n < 4) + q = s->y_dc_scale; + else + q = s->c_dc_scale; + q = q << 3; + } else + /* For AIC we skip quant/dequant of INTRADC */ + q = 1 << 3; + + /* note: block[0] is assumed to be positive */ + dc = block[0] = (block[0] + (q >> 1)) / q; + start_i = 1; + last_non_zero = 0; + if(n<4){ + bias = s->q_intra_matrix16[qscale][1]; + qmat = s->q_intra_matrix16[qscale][0]; + }else{ + bias = s->q_chroma_intra_matrix16[qscale][1]; + qmat = s->q_chroma_intra_matrix16[qscale][0]; + } + + } else { + start_i = 0; + last_non_zero = -1; + bias = s->q_inter_matrix16[qscale][1]; + qmat = s->q_inter_matrix16[qscale][0]; + + } + EPROF(); + + PROF("quantize",4); + + /* for(i=start_i; i<64; i++) { */ + /* sign = (block[i]>>15)|1; */ + /* level = ((abs(block[i])+bias[0])*qmat[i])>>16; */ + /* if (level < 0) level = 0; */ + /* max |= level; */ + /* level = level * sign; */ + /* block[i] = level; */ + /* } */ + + __asm__ volatile + ("i2=%1;\n\t" + "r1=[%1++]; \n\t" + "r0=r1>>>15 (v); \n\t" + "lsetup (0f,1f) lc0=%3; \n\t" + "0: r0=r0|%4; \n\t" + " r1=abs r1 (v) || r2=[%2++];\n\t" + " r1=r1+|+%5; \n\t" + " r1=max(r1,%6) (v); \n\t" + " r1.h=(a1 =r1.h*r2.h), r1.l=(a0 =r1.l*r2.l) (tfu); \n\t" + " %0=%0|r1; \n\t" + " r0.h=(a1 =r1.h*r0.h), r0.l=(a0 =r1.l*r0.l) (is) || r1=[%1++];\n\t" + "1: r0=r1>>>15 (v) || [i2++]=r0;\n\t" + "r1=%0>>16; \n\t" + "%0=%0|r1; \n\t" + "%0.h=0; \n\t" + : "=&d" (max) + : "b" (block), "b" (qmat), "a" (32), "d" (0x00010001), "d" (bias[0]*0x10001), "d" (0) + : "R0","R1","R2", "I2"); + if (start_i == 1) block[0] = dc; + + EPROF(); + + + PROF("zzscan",5); + + __asm__ volatile + ("r0=b[%1--] (x); \n\t" + "lsetup (0f,1f) lc0=%3; \n\t" /* for(i=63; i>=start_i; i--) { */ + "0: p0=r0; \n\t" /* j = scantable[i]; */ + " p0=%2+(p0<<1); \n\t" /* if (block[j]) { */ + " r0=w[p0]; \n\t" /* last_non_zero = i; */ + " cc=r0==0; \n\t" /* break; */ + " if !cc jump 2f; \n\t" /* } */ + "1: r0=b[%1--] (x); \n\t" /* } */ + " %0=%4; \n\t" + " jump 3f; \n\t" + "2: %0=lc0; \n\t" + "3:\n\t" + + : "=d" (last_non_zero) + : "a" (scantable+63), "a" (block), "a" (63), "d" (last_non_zero) + : "P0","R0"); + + EPROF(); + + *overflow= s->max_qcoeff < max; //overflow might have happened + + bfprof(); + + /* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */ + if (s->dsp.idct_permutation_type != FF_NO_IDCT_PERM) + ff_block_permute(block, s->dsp.idct_permutation, scantable, last_non_zero); + + return last_non_zero; +} + +av_cold void ff_MPV_common_init_bfin (MpegEncContext *s) +{ +/* s->dct_quantize= dct_quantize_bfin; */ +} diff --git a/ffmpeg/libavcodec/bfin/pixels_bfin.S b/ffmpeg/libavcodec/bfin/pixels_bfin.S new file mode 100644 index 0000000..2c84deb --- /dev/null +++ b/ffmpeg/libavcodec/bfin/pixels_bfin.S @@ -0,0 +1,381 @@ +/* + * Blackfin Pixel Operations + * Copyright (C) 2007 Marc Hoffman + * + * 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 "config_bfin.h" + +DEFUN(put_pixels_clamped,mL1, + (int16_t *block, uint8_t *dest, int line_size)): + [--SP] = (R7:4); + R4 = 0; + R5.l = 0x00ff; + R5.h = 0x00ff; + I0 = R0; // block + I1 = R1; // dest + R2 += -4; // line_size + M1 = R2; + P0 = 8; + R0 = [I0++]; + R1 = [I0++]; + R2 = MAX(R0, R4) (V); + LSETUP (ppc$0,ppc$1) LC0=P0; +ppc$0: R2 = MIN(R2, R5) (V); + R3 = MAX(R1, R4) (V); + R3 = MIN(R3, R5) (V) || R0 = [I0++]; + R6 = BYTEPACK (R2,R3) || R1 = [I0++]; + R2 = MAX(R0, R4) (V) || [I1++] = R6; + R2 = MIN(R2, R5) (V); + R3 = MAX(R1, R4) (V); + R3 = MIN(R3, R5) (V) || R0 = [I0++]; + R6 = BYTEPACK (R2,R3) || R1 = [I0++]; +ppc$1: R2 = Max(R0, R4) (V) || [I1++M1] = R6; + + (R7:4) = [SP++]; + RTS; +DEFUN_END(put_pixels_clamped) + +DEFUN(add_pixels_clamped,mL1, + (int16_t *block, uint8_t *dest, int line_size)): + [-- SP] = (R7:4); + R4 = 0; + I0 = 0; + R2 += -4; // line_size + M0 = R2; + I1 = R1; // dest + I3 = R0; // block + I2 = R1; // dest + P0 = 8; + M3 = 2; + R0 = [I3++] || R2 = [I1]; + R2 = R2 << 8 || R0.H = W[I3--] || R3 = [I1++]; + R3 = R3 >> 8 || R1.L = W[I3] || I3 += 4; + R6 = BYTEOP3P(R1:0, R3:2) (LO) || R1.H = W[I3++] || R2 = [I1]; + + LSETUP(apc$2,apc$3) LC1 = P0; +apc$2: R7 = BYTEOP3P(R1:0, R3:2) (HI, R) || R0 = [I3++] || R3 = [I1++M0]; + R2 = R2 << 8 || R0.H = W[I3--]; + R3 = R3 >> 8 || R1.L = W[I3] || I3 += 4; + R6 = R6 + R7 (S) || R1.H = W[I3]; + R6 = BYTEOP3P(R1:0, R3:2) (LO) || I3+=M3 || [I2++]=R6; + R7 = BYTEOP3P(R1:0, R3:2) (HI, R) || R0 = [I3++] || R2 = [I1]; + R2 = R2 << 8 || R0.H = W[I3--] || R3 = [I1++]; + R3 = R3 >> 8 || R1.L = W[I3] || I3 += 4; + R6 = R6 + R7 (S) || R1.H = W[I3++]; +apc$3: R6 = BYTEOP3P(R1:0, R3:2) (LO) || [I2++M0] = R6 || R2 = [I1]; + + (R7:4) = [SP++]; + RTS; +DEFUN_END(add_pixels_clamped) + +DEFUN(diff_pixels,mL1, + (int16_t *block, uint8_t *s1, uint8_t *s2, int stride)): + link 0; + [--sp] = (r7:4); + p0=8; + i3=r0; // block + i0=r1; // s1 + i1=r2; // s2 + r2=[fp+20]; // stride + r2+=-8; + m0=r2; + + + LSETUP(.LS0,.LE0) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +.LS0: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + (R5,R4) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M0]; + (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R0 = [I0++] || [I3++] = R4; + DISALGNEXCPT || R2 = [I1++] || [I3++] = R5; + [i3++]=r6; +.LE0: [i3++]=r7; + + (r7:4) = [sp++]; + unlink; + rts; +DEFUN_END(diff_pixels) + +/* + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + sum += pix[j]; + } + pix += line_size; + } +*/ +DEFUN(pix_sum,mL1, + (uint8_t *p, int stride)): + link 0; + [--sp] = (r7:4); + p0=8; + i0=r0; // s1 + i1=r0; + m1=r1; + r1=r1+r1; + r1+=-16; // stride + m0=r1; + i1+=m1; + + r6=0; + + LSETUP(LS$PS,LE$PS) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +LS$PS: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + (R5,R4) = BYTEOP16P (R3:2,R1:0) || R0 = [I0++] || R2 = [I1++]; + r6=r6+|+r5; + r6=r6+|+r4; + (R5,R4) = BYTEOP16P (R3:2,R1:0) (R)|| R1 = [I0++] || R3 = [I1++]; + r6=r6+|+r5; + r6=r6+|+r4; + (R5,R4) = BYTEOP16P (R3:2,R1:0) || R0 = [I0++m0] || R2 = [I1++m0]; + r6=r6+|+r5; + r6=r6+|+r4; + (R5,R4) = BYTEOP16P (R3:2,R1:0) (R)|| R0 = [I0++] || R2 = [I1++]; + r6=r6+|+r5; +LE$PS: r6=r6+|+r4; + r0.l=r6.l+r6.h; + r0.h=0; + + (r7:4) = [sp++]; + unlink; + rts; +DEFUN_END(pix_sum) + + +DEFUN(get_pixels,mL1, + (int16_t *av_restrict block, const uint8_t *pixels, int line_size)): + [--sp] = (r7:4); + i3=r0; // dest + i0=r1; // src0 + p0=8; + r2+=-8; + m0=r2; + LSETUP(gp8$0,gp8$1) LC0=P0; + + DISALGNEXCPT || R0 = [I0++]; + DISALGNEXCPT || R1 = [I0++]; + +gp8$0: (R7,R6) = byteunpack R1:0 || R0 = [I0++M0]; + (R5,R4) = byteunpack R1:0 (R) || R0 = [I0++] || [I3++]=R6; + DISALGNEXCPT || R1 = [I0++] || [I3++]=R7; + [I3++]=R4; +gp8$1: [I3++]=R5 + + + (r7:4) = [sp++]; + RTS; +DEFUN_END(get_pixels) + + +/* sad = sad16x16 (ubyte *mb, ubyte *refwin, srcwidth, refwinwidth, h) */ +/* 91 cycles */ +DEFUN(z_sad16x16,mL1, + (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h)): + link 0; + I0 = R0; + I1 = R1; + + A1 = A0 = 0; + R0 = [sp+20]; // rwidth + P2 = [sp+24]; // height + R3 = 16; + R0 = R0 - R3; + R3 = R2 - R3; + M1 = R0; + M0 = R3; + + DISALGNEXCPT || R0 = [I0++] || R2 = [I1++]; + LSETUP (s$16, e$16) LC0=P2; +s$16: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + SAA (R1:0,R3:2) || R0 = [I0++] || R2 = [I1++]; + SAA (R1:0,R3:2) (R) || R1 = [I0++] || R3 = [I1++]; + SAA (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M1]; +e$16: SAA (R1:0,R3:2) (R) || R0 = [I0++] || R2 = [I1++]; + + R3=A1.L+A1.H, R2=A0.L+A0.H ; + R0 = R2 + R3 ; + unlink; + RTS; +DEFUN_END(z_sad16x16) + +/* sad = sad8x8 (ubyte *mb, ubyte *refwin, int srcwidth, int refwinwidth, int h) */ +/* 36 cycles */ +DEFUN(z_sad8x8,mL1, + (uint8_t *blk1, uint8_t *blk2, int dsz, int line_size, int h)): + I0 = R0; + I1 = R1; + + A1 = A0 = 0; + r0 = [sp+12]; // rwidth + P2 = [sp+16]; //height + R3 = 8; + R0 = R0 - R3; + R3 = R2 - R3; + M0 = R3; + M1 = R0; + + LSETUP (s$8, e$8) LC0=P2; + DISALGNEXCPT || R0 = [I0++] || R2 = [I1++]; + DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; +s$8: SAA (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M1]; + SAA (R1:0,R3:2) (R) || R0 = [I0++] || R2 = [I1++]; +e$8: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + + R3=A1.L+A1.H, R2=A0.L+A0.H ; + R0 = R2 + R3 ; + RTS; +DEFUN_END(z_sad8x8) + +DEFUN(pix_norm1,mL1, + (uint8_t * pix, int line_size)): + [--SP]=(R7:4,P5:3); + + // Fetch the input arguments. + P1 = R0; // pix + P0 = R1; // line_size + P5 = 16; // loop ctr. + P0 -= P5; + M0 = P0; // M0 = line_size-16; + // Now for the real work. + A1 = A0 = 0; + lsetup(_pix_norm1_blkfn_loopStart, _pix_norm1_blkfn_loopEnd) LC1 = P5; + I0 = P1; + DISALGNEXCPT || r0 = [i0++]; + +_pix_norm1_blkfn_loopStart: + // following unpacks pix1[0..15] pix1+line_size[0..15] + DISALGNEXCPT || r1 = [i0++]; + + (r5, r4) = byteunpack r1:0 || r0 = [i0++]; + a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); + a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); + (r5, r4) = byteunpack r1:0(r) || r1 = [i0++]; + a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); + a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); + (r5, r4) = byteunpack r1:0 || r0 = [i0++M0]; + a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); + a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); + (r5, r4) = byteunpack r1:0(r) || r0 = [i0++]; + a1 += r5.h * r5.h, a0 += r5.l * r5.l (is); +_pix_norm1_blkfn_loopEnd: + a1 += r4.h * r4.h, a0 += r4.l * r4.l (is); + + +// Clean up at the end: + R2 = A0, R3 = A1; + R0 = R2 + R3 (S); + + (R7:4,P5:3)=[SP++]; + + RTS; +DEFUN_END(pix_norm1) + +DEFUN(sse4,mL1, + (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)): + link 0; + [--sp] = (r7:6); + p0=[fp+24]; // h + i0=r1; // pix1 + i1=r2; // pix2 + r2=[fp+20]; // line_size + r2+=-4; + m0=r2; + + a0=a1=0; + LSETUP(.S40,.E40) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +.S40: DISALGNEXCPT || R1 = [I0++M0] || R3 = [I1++M0]; + (R7,R6) = BYTEOP16M (R1:0,R3:2); + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); +.E40: a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + a0 += a1; + r0 = a0; + + (r7:6) = [sp++]; + unlink; + rts; +DEFUN_END(sse4) + +DEFUN(sse8,mL1, + (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)): + link 0; + [--sp] = (r7:6); + p0=[fp+24]; // h + i0=r1; // pix1 + i1=r2; // pix2 + r2=[fp+20]; // line_size + r2+=-8; + m0=r2; + + a0=a1=0; + LSETUP(.S80,.E80) LC0=P0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + +.S80: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + (R7,R6) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M0]; + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); + a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R0 = [I0++] || R2 = [I1++]; + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); +.E80: a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + a0 += a1; + r0 = a0; + + (r7:6) = [sp++]; + unlink; + rts; +DEFUN_END(sse8) + +DEFUN(sse16,mL1, + (void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)): + link 0; + [--sp] = (r7:6); + p0=[fp+24]; // h + i0=r1; // pix1 + i1=r2; // pix2 + r2=[fp+20]; // line_size + r2+=-16; + m0=r2; + + a0=a1=0; + DISALGNEXCPT || R0 = [I0++] || R2 =[I1++]; + LSETUP(.S160,.E160) LC0=P0; + +.S160: DISALGNEXCPT || R1 = [I0++] || R3 = [I1++]; + (R7,R6) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++] || R2 = [I1++]; + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); + a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R1 = [I0++] || R3 = [I1++]; + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); + a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + (R7,R6) = BYTEOP16M (R1:0,R3:2) || R0 = [I0++M0] || R2 = [I1++M0]; + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); + a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + (R7,R6) = BYTEOP16M (R1:0,R3:2) (R)|| R0 = [I0++] || R2 = [I1++]; + a0 += r7.l * r7.l, a1 += r7.h * r7.h (is); +.E160: a0 += r6.l * r6.l, a1 += r6.h * r6.h (is); + a0 += a1; + r0 = a0; + + (r7:6) = [sp++]; + unlink; + rts; +DEFUN_END(sse16) diff --git a/ffmpeg/libavcodec/bfin/vp3_bfin.c b/ffmpeg/libavcodec/bfin/vp3_bfin.c new file mode 100644 index 0000000..366955b --- /dev/null +++ b/ffmpeg/libavcodec/bfin/vp3_bfin.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007 Marc Hoffman + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/vp3dsp.h" +#include "libavcodec/dsputil.h" +#include "dsputil_bfin.h" +#include "vp3_bfin.h" + +/* Intra iDCT offset 128 */ +static void ff_bfin_vp3_idct_put (uint8_t *dest, int line_size, int16_t *block) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP + 128; + int i,j; + + ff_bfin_vp3_idct (block); + + for (i=0;i<8;i++) + for (j=0;j<8;j++) + dest[line_size*i+j]=cm[block[i*8+j]]; + + memset(block, 0, 128); +} + +/* Inter iDCT */ +static void ff_bfin_vp3_idct_add (uint8_t *dest, int line_size, int16_t *block) +{ + ff_bfin_vp3_idct (block); + ff_bfin_add_pixels_clamped (block, dest, line_size); + + memset(block, 0, 128); +} + +av_cold void ff_vp3dsp_init_bfin(VP3DSPContext *c, int flags) +{ + // FIXME: these functions are disabled because they expect unpermutated + // IDCT coefficients as input, but the coefficients are transposed + //c->idct_add = ff_bfin_vp3_idct_add; + //c->idct_put = ff_bfin_vp3_idct_put; +} diff --git a/ffmpeg/libavcodec/bfin/vp3_bfin.h b/ffmpeg/libavcodec/bfin/vp3_bfin.h new file mode 100644 index 0000000..e832de7 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/vp3_bfin.h @@ -0,0 +1,27 @@ +/* + * 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 + */ + + +#ifndef AVCODEC_BFIN_VP3_BFIN_H +#define AVCODEC_BFIN_VP3_BFIN_H + +#include + +void ff_bfin_vp3_idct(int16_t *block); + +#endif /* AVCODEC_BFIN_VP3_BFIN_H */ diff --git a/ffmpeg/libavcodec/bfin/vp3_idct_bfin.S b/ffmpeg/libavcodec/bfin/vp3_idct_bfin.S new file mode 100644 index 0000000..4e20045 --- /dev/null +++ b/ffmpeg/libavcodec/bfin/vp3_idct_bfin.S @@ -0,0 +1,280 @@ +/* + * vp3_idct BlackFin + * + * Copyright (C) 2007 Marc Hoffman + * + * 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 + */ +/* + This blackfin DSP code implements an 8x8 inverse type II DCT. + +Prototype : void ff_bfin_vp3_idct(int16_t *in) + +Registers Used : A0, A1, R0-R7, I0-I3, B0, B2, B3, M0-M2, L0-L3, P0-P5, LC0. + +*/ + +#include "config.h" +#include "config_bfin.h" + +#if defined(__FDPIC__) && CONFIG_SRAM +.section .l1.data.B,"aw",@progbits +#else +.data +#endif + +.align 4; +coefs: +.short 0x5a82; // C4 +.short 0x5a82; // C4 +.short 0x30FC; //cos(3pi/8) C6 +.short 0x7642; //cos(pi/8) C2 +.short 0x18F9; //cos(7pi/16) +.short 0x7D8A; //cos(pi/16) +.short 0x471D; //cos(5pi/16) +.short 0x6A6E; //cos(3pi/16) +.short 0x18F9; //cos(7pi/16) +.short 0x7D8A; //cos(pi/16) + +#if defined(__FDPIC__) && CONFIG_SRAM +.section .l1.data.A +#endif + +vtmp: .space 256 + +#define TMP0 FP-8 +#define TMP1 FP-12 +#define TMP2 FP-16 + + +.text +DEFUN(vp3_idct,mL1, + (int16_t *block)): + +/********************** Function Prologue *********************************/ + link 16; + [--SP] = (R7:4, P5:3); // Push the registers onto the stack. + B0 = R0; // Pointer to Input matrix + RELOC(R1, P3, coefs); // Pointer to Coefficients + RELOC(R2, P3, vtmp); // Pointer to Temporary matrix + B3 = R1; + B2 = R2; + L3 = 20; // L3 is used for making the coefficient array + // circular. + // MUST BE RESTORED TO ZERO at function exit. + M1 = 16 (X); // All these registers are initialized for + M3 = 8(X); // modifying address offsets. + + I0 = B0; // I0 points to Input Element (0, 0). + I2 = B0; // I2 points to Input Element (0, 0). + I2 += M3 || R0.H = W[I0]; + // Element 0 is read into R0.H + I1 = I2; // I1 points to input Element (0, 6). + I1 += 4 || R0.L = W[I2++]; + // I2 points to input Element (0, 4). + // Element 4 is read into R0.L. + P2 = 8 (X); + P3 = 32 (X); + P4 = -32 (X); + P5 = 98 (X); + R7 = 0x8000(Z); + I3 = B3; // I3 points to Coefficients + P0 = B2; // P0 points to array Element (0, 0) of temp + P1 = B2; + R7 = [I3++] || [TMP2]=R7; // Coefficient C4 is read into R7.H and R7.L. + MNOP; + NOP; + + /* + * A1 = Y0 * cos(pi/4) + * A0 = Y0 * cos(pi/4) + * A1 = A1 + Y4 * cos(pi/4) + * A0 = A0 - Y4 * cos(pi/4) + * load: + * R1=(Y2,Y6) + * R7=(C2,C6) + * res: + * R3=Y0, R2=Y4 + */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+= 4 || R1.L=W[I1++]; + R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; + + LSETUP (.0, .1) LC0 = P2; // perform 8 1d idcts + + P2 = 112 (X); + P1 = P1 + P2; // P1 points to element (7, 0) of temp buffer. + P2 = -94(X); + +.0: + /* + * A1 = Y2 * cos(3pi/8) + * A0 = Y2 * cos(pi/8) + * A1 = A1 - Y6 * cos(pi/8) + * A0 = A0 + Y6 * cos(3pi/8) + * R5 = (Y1,Y7) + * R7 = (C1,C7) + * res: + * R1=Y2, R0=Y6 + */ + A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; + R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; + /* + * Y0 = Y0 + Y6. + * Y4 = Y4 + Y2. + * Y2 = Y4 - Y2. + * Y6 = Y0 - Y6. + * R3 is saved + * R6.l=Y3 + * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 + */ + R3=R3+R0, R0=R3-R0; + R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; + /* + * Compute the odd portion (1,3,5,7) even is done. + * + * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. + * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. + * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. + * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. + */ + // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; + A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; + A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) + R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; + A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) + A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); + R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; + // R3=Y1, R2=Y7, R7=Y5, R6=Y3 + + /* Transpose write column. */ + R5.H=R4+R2 (RND12); // Y0=Y0+Y7 + R5.L=R4-R2 (RND12) || R4 = [TMP1]; // Y7=Y7-Y0 + R2.H=R1+R7 (RND12) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 + R2.L=R1-R7 (RND12) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 + R5.H=R0-R3 (RND12) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 + R5.L=R0+R3 (RND12) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 + R3.H=R4-R6 (RND12) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 + R3.L=R4+R6 (RND12) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 + + /* pipeline loop start, + drain Y3, Y4 */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; +.1: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; + + + + I0 = B2; // I0 points to Input Element (0, 0) + I2 = B2; // I2 points to Input Element (0, 0) + I2 += M3 || R0.H = W[I0]; + // Y0 is read in R0.H + I1 = I2; // I1 points to input Element (0, 6) + I1 += 4 || R0.L = W[I2++]; + // I2 points to input Element (0, 4) + // Y4 is read in R0.L + P2 = 8 (X); + I3 = B3; // I3 points to Coefficients + P0 = B0; // P0 points to array Element (0, 0) for writing + // output + P1 = B0; + R7 = [I3++]; // R7.H = C4 and R7.L = C4 + NOP; + + /* + * A1 = Y0 * cos(pi/4) + * A0 = Y0 * cos(pi/4) + * A1 = A1 + Y4 * cos(pi/4) + * A0 = A0 - Y4 * cos(pi/4) + * load: + * R1=(Y2,Y6) + * R7=(C2,C6) + * res: + * R3=Y0, R2=Y4 + */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || I0+=4 || R1.L=W[I1++]; + R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || R1.H=W[I0--] || R7=[I3++]; + + LSETUP (.2, .3) LC0 = P2; // peform 8 1d idcts + P2 = 112 (X); + P1 = P1 + P2; + P2 = -94(X); + +.2: + /* + * A1 = Y2 * cos(3pi/8) + * A0 = Y2 * cos(pi/8) + * A1 = A1 - Y6 * cos(pi/8) + * A0 = A0 + Y6 * cos(3pi/8) + * R5 = (Y1,Y7) + * R7 = (C1,C7) + * res: + * R1=Y2, R0=Y6 + */ + A1=R7.L*R1.H, A0=R7.H*R1.H (IS) || I0+=4 || R5.H=W[I0]; + R1=(A1-=R7.H*R1.L), R0=(A0+=R7.L*R1.L) (IS) || R5.L=W[I1--] || R7=[I3++]; + /* + * Y0 = Y0 + Y6. + * Y4 = Y4 + Y2. + * Y2 = Y4 - Y2. + * Y6 = Y0 - Y6. + * R3 is saved + * R6.l=Y3 + * note: R3: Y0, R2: Y4, R1: Y2, R0: Y6 + */ + R3=R3+R0, R0=R3-R0; + R2=R2+R1, R1=R2-R1 || [TMP0]=R3 || R6.L=W[I0--]; + /* + * Compute the odd portion (1,3,5,7) even is done. + * + * Y1 = C7 * Y1 - C1 * Y7 + C3 * Y5 - C5 * Y3. + * Y7 = C1 * Y1 + C7 * Y7 + C5 * Y5 + C3 * Y3. + * Y5 = C5 * Y1 + C3 * Y7 + C7 * Y5 - C1 * Y3. + * Y3 = C3 * Y1 - C5 * Y7 - C1 * Y5 - C7 * Y3. + */ + // R5=(Y1,Y7) R6=(Y5,Y3) // R7=(C1,C7) + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || [TMP1]=R2 || R6.H=W[I2--]; + A1-=R7.H*R5.L, A0+=R7.L*R5.L (IS) || I0-=4 || R7=[I3++]; + A1+=R7.H*R6.H, A0+=R7.L*R6.H (IS) || I0+=M1; // R7=(C3,C5) + R3 =(A1-=R7.L*R6.L), R2 =(A0+=R7.H*R6.L) (IS); + A1 =R7.L*R5.H, A0 =R7.H*R5.H (IS) || R4=[TMP0]; + A1+=R7.H*R5.L, A0-=R7.L*R5.L (IS) || I1+=M1 || R7=[I3++]; // R7=(C1,C7) + A1+=R7.L*R6.H, A0-=R7.H*R6.H (IS); + R7 =(A1-=R7.H*R6.L), R6 =(A0-=R7.L*R6.L) (IS) || I2+=M1; + // R3=Y1, R2=Y7, R7=Y5, R6=Y3 + + /* Transpose write column. */ + R5.H=R4+R2 (RND20); // Y0=Y0+Y7 + R5.L=R4-R2 (RND20) || R4 = [TMP1]; // Y7=Y7-Y0 + R5=R5>>>2(v); + R2.H=R1+R7 (RND20) || W[P0++P3]=R5.H; // Y2=Y2+Y5 st Y0 + R2.L=R1-R7 (RND20) || W[P1++P4]=R5.L || R7=[I3++]; // Y5=Y2-Y5 st Y7 + R2=R2>>>2(v); + R5.H=R0-R3 (RND20) || W[P0++P3]=R2.H || R1.L=W[I1++]; // Y1=Y6-Y1 st Y2 + R5.L=R0+R3 (RND20) || W[P1++P4]=R2.L || R0.H=W[I0++]; // Y6=Y6+Y1 st Y5 + R5=R5>>>2(v); + R3.H=R4-R6 (RND20) || W[P0++P3]=R5.H || R0.L=W[I2++]; // Y3=Y3-Y4 st Y1 + R3.L=R4+R6 (RND20) || W[P1++P4]=R5.L || R1.H=W[I0++]; // Y4=Y3+Y4 st Y6 + R3=R3>>>2(v); + /* pipeline loop start, + drain Y3, Y4 */ + A1=R7.H*R0.H, A0=R7.H*R0.H (IS) || W[P0++P2]= R3.H || R1.H = W[I0--]; +.3: R3=(A1+=R7.H*R0.L), R2=(A0-=R7.H*R0.L) (IS) || W[P1++P5]= R3.L || R7 = [I3++]; + + L3 = 0; + (R7:4,P5:3)=[SP++]; + unlink; + RTS; +DEFUN_END(vp3_idct) diff --git a/ffmpeg/libavcodec/bgmc.c b/ffmpeg/libavcodec/bgmc.c new file mode 100644 index 0000000..f48ac2e --- /dev/null +++ b/ffmpeg/libavcodec/bgmc.c @@ -0,0 +1,558 @@ +/* + * Block Gilbert-Moore decoder + * Copyright (c) 2010 Thilo Borgmann + * + * 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 + */ + +/** + * @file + * Block Gilbert-Moore decoder as used by MPEG-4 ALS + * @author Thilo Borgmann + */ + +#include "bgmc.h" + +#define FREQ_BITS 14 // bits used by frequency counters +#define VALUE_BITS 18 // bits used to represent the values +#define TOP_VALUE ((1 << VALUE_BITS) - 1) // maximum value +#define FIRST_QTR (TOP_VALUE / 4 + 1) // first quarter of values maximum value +#define HALF (2 * FIRST_QTR) // first half of values maximum value +#define THIRD_QTR (3 * FIRST_QTR) // third quarter of values maximum value + +#define LUT_BITS (FREQ_BITS - 8) // number of bits used to index lookup tables +#define LUT_SIZE (1 << LUT_BITS) // size of the lookup tables +#define LUT_BUFF 4 // number of buffered lookup tables + + +/** Cumulative frequency tables for block Gilbert-Moore coding. */ +static const uint16_t cf_tables_1[3][129] = { + { + 16384, 16066, 15748, 15431, 15114, 14799, 14485, 14173, 13861, 13552, + 13243, 12939, 12635, 12336, 12038, 11745, 11452, 11161, 10870, 10586, + 10303, 10027, 9751, 9483, 9215, 8953, 8692, 8440, 8189, 7946, + 7704, 7472, 7240, 7008, 6776, 6554, 6333, 6122, 5912, 5711, + 5512, 5320, 5128, 4947, 4766, 4595, 4425, 4264, 4104, 3946, + 3788, 3640, 3493, 3355, 3218, 3090, 2963, 2842, 2721, 2609, + 2498, 2395, 2292, 2196, 2100, 2004, 1908, 1820, 1732, 1651, + 1570, 1497, 1424, 1355, 1287, 1223, 1161, 1100, 1044, 988, + 938, 888, 839, 790, 746, 702, 662, 623, 588, 553, + 520, 488, 459, 431, 405, 380, 357, 334, 311, 288, + 268, 248, 230, 213, 197, 182, 168, 154, 142, 130, + 119, 108, 99, 90, 81, 72, 64, 56, 49, 42, + 36, 30, 25, 20, 15, 11, 7, 3, 0 + }, + { + 16384, 16080, 15776, 15473, 15170, 14868, 14567, 14268, 13970, 13674, + 13378, 13086, 12794, 12505, 12218, 11936, 11654, 11373, 11092, 10818, + 10544, 10276, 10008, 9749, 9490, 9236, 8982, 8737, 8492, 8256, + 8020, 7792, 7564, 7336, 7108, 6888, 6669, 6459, 6249, 6050, + 5852, 5660, 5468, 5286, 5104, 4931, 4760, 4598, 4436, 4275, + 4115, 3965, 3816, 3674, 3534, 3403, 3272, 3147, 3023, 2907, + 2792, 2684, 2577, 2476, 2375, 2274, 2173, 2079, 1986, 1897, + 1810, 1724, 1645, 1567, 1493, 1419, 1351, 1284, 1222, 1161, + 1105, 1050, 995, 941, 891, 842, 797, 753, 713, 673, + 636, 599, 566, 533, 503, 473, 446, 419, 392, 365, + 340, 316, 294, 272, 253, 234, 216, 199, 184, 169, + 155, 142, 130, 118, 106, 95, 85, 75, 66, 57, + 49, 41, 34, 27, 21, 15, 10, 5, 0 + }, + { + 16384, 16092, 15801, 15510, 15219, 14930, 14641, 14355, 14069, 13785, + 13501, 13219, 12938, 12661, 12384, 12112, 11841, 11571, 11301, 11037, + 10773, 10514, 10256, 10005, 9754, 9508, 9263, 9025, 8787, 8557, + 8327, 8103, 7879, 7655, 7431, 7215, 7000, 6792, 6585, 6387, + 6190, 5998, 5807, 5625, 5445, 5272, 5100, 4937, 4774, 4613, + 4452, 4301, 4150, 4007, 3865, 3731, 3597, 3469, 3341, 3218, + 3099, 2981, 2869, 2758, 2652, 2546, 2440, 2334, 2234, 2134, + 2041, 1949, 1864, 1779, 1699, 1620, 1547, 1474, 1407, 1340, + 1278, 1217, 1157, 1097, 1043, 989, 940, 891, 846, 801, + 759, 718, 680, 643, 609, 575, 543, 511, 479, 447, + 418, 389, 363, 337, 314, 291, 270, 249, 230, 212, + 195, 179, 164, 149, 135, 121, 108, 96, 85, 74, + 64, 54, 45, 36, 28, 20, 13, 6, 0 + } +}; + + +static const uint16_t cf_tables_2[8][193] = { + { + 16384, 16104, 15825, 15546, 15268, 14991, 14714, 14439, 14164, 13891, + 13620, 13350, 13081, 12815, 12549, 12287, 12025, 11765, 11505, 11250, + 10996, 10746, 10497, 10254, 10011, 9772, 9534, 9303, 9072, 8848, + 8624, 8406, 8188, 7970, 7752, 7539, 7327, 7123, 6919, 6724, + 6529, 6339, 6150, 5970, 5790, 5618, 5446, 5282, 5119, 4957, + 4795, 4642, 4490, 4345, 4201, 4065, 3929, 3798, 3669, 3547, + 3425, 3310, 3196, 3086, 2976, 2866, 2756, 2650, 2545, 2447, + 2350, 2260, 2170, 2085, 2000, 1921, 1843, 1770, 1698, 1632, + 1566, 1501, 1436, 1376, 1316, 1261, 1207, 1157, 1108, 1061, + 1015, 973, 931, 893, 855, 819, 783, 747, 711, 677, + 644, 614, 584, 557, 530, 505, 480, 458, 436, 416, + 396, 378, 360, 343, 326, 310, 295, 281, 267, 255, + 243, 232, 221, 211, 201, 192, 183, 174, 166, 158, + 150, 142, 134, 126, 119, 112, 106, 100, 95, 90, + 85, 80, 76, 72, 69, 66, 63, 60, 57, 54, + 51, 48, 46, 44, 42, 40, 38, 36, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, + 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 2, 1, 0 + }, + { + 16384, 16116, 15849, 15582, 15316, 15050, 14785, 14521, 14257, 13995, + 13734, 13476, 13218, 12963, 12708, 12457, 12206, 11956, 11706, 11460, + 11215, 10975, 10735, 10500, 10265, 10034, 9803, 9579, 9355, 9136, + 8917, 8703, 8489, 8275, 8061, 7853, 7645, 7444, 7244, 7051, + 6858, 6671, 6484, 6305, 6127, 5956, 5785, 5622, 5459, 5298, + 5137, 4983, 4830, 4684, 4539, 4401, 4263, 4131, 3999, 3874, + 3750, 3632, 3515, 3401, 3287, 3173, 3059, 2949, 2840, 2737, + 2635, 2539, 2444, 2354, 2264, 2181, 2098, 2020, 1943, 1872, + 1801, 1731, 1661, 1596, 1532, 1472, 1412, 1357, 1303, 1251, + 1200, 1153, 1106, 1063, 1020, 979, 938, 897, 856, 818, + 780, 746, 712, 681, 650, 621, 592, 566, 540, 517, + 494, 473, 452, 431, 410, 391, 373, 356, 340, 325, + 310, 296, 282, 270, 258, 247, 236, 225, 214, 203, + 192, 182, 172, 162, 153, 144, 136, 128, 121, 114, + 108, 102, 97, 92, 87, 82, 77, 73, 69, 65, + 62, 59, 56, 53, 50, 47, 45, 43, 41, 39, + 37, 35, 33, 31, 29, 27, 26, 25, 24, 23, + 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 2, 1, 0 + }, + { + 16384, 16128, 15872, 15617, 15362, 15107, 14853, 14600, 14347, 14096, + 13846, 13597, 13350, 13105, 12860, 12618, 12376, 12135, 11894, 11657, + 11421, 11189, 10957, 10730, 10503, 10279, 10056, 9838, 9620, 9407, + 9195, 8987, 8779, 8571, 8363, 8159, 7955, 7758, 7561, 7371, + 7182, 6997, 6812, 6635, 6459, 6289, 6120, 5957, 5795, 5634, + 5473, 5319, 5165, 5018, 4871, 4732, 4593, 4458, 4324, 4197, + 4071, 3951, 3831, 3714, 3597, 3480, 3363, 3250, 3138, 3032, + 2927, 2828, 2729, 2635, 2541, 2453, 2366, 2284, 2202, 2126, + 2050, 1975, 1900, 1830, 1761, 1697, 1633, 1574, 1515, 1459, + 1403, 1351, 1300, 1252, 1205, 1160, 1115, 1070, 1025, 982, + 939, 899, 860, 824, 789, 756, 723, 693, 663, 636, + 609, 584, 559, 535, 511, 489, 467, 447, 427, 409, + 391, 374, 358, 343, 328, 313, 300, 287, 274, 261, + 248, 235, 223, 211, 200, 189, 179, 169, 160, 151, + 143, 135, 128, 121, 115, 109, 103, 97, 92, 87, + 82, 77, 73, 69, 65, 61, 58, 55, 52, 49, + 46, 43, 40, 37, 35, 33, 31, 29, 27, 25, + 23, 21, 20, 19, 18, 17, 16, 15, 14, 13, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 2, 1, 0 + }, + { + 16384, 16139, 15894, 15649, 15405, 15162, 14919, 14677, 14435, 14195, + 13955, 13717, 13479, 13243, 13008, 12775, 12542, 12310, 12079, 11851, + 11623, 11399, 11176, 10956, 10737, 10521, 10305, 10094, 9883, 9677, + 9471, 9268, 9065, 8862, 8659, 8459, 8260, 8067, 7874, 7688, + 7502, 7321, 7140, 6965, 6790, 6621, 6452, 6290, 6128, 5968, + 5808, 5655, 5503, 5356, 5209, 5069, 4929, 4794, 4660, 4532, + 4404, 4282, 4160, 4041, 3922, 3803, 3684, 3568, 3452, 3343, + 3234, 3131, 3029, 2931, 2833, 2741, 2649, 2563, 2477, 2396, + 2316, 2236, 2157, 2083, 2009, 1940, 1871, 1807, 1743, 1683, + 1623, 1567, 1511, 1459, 1407, 1357, 1307, 1257, 1207, 1159, + 1111, 1067, 1023, 983, 943, 905, 868, 834, 800, 769, + 738, 709, 681, 653, 625, 600, 575, 552, 529, 508, + 487, 466, 447, 428, 410, 392, 376, 360, 344, 328, + 313, 298, 283, 268, 255, 242, 230, 218, 207, 196, + 186, 176, 167, 158, 150, 142, 135, 128, 121, 114, + 108, 102, 97, 92, 87, 82, 78, 74, 70, 66, + 62, 58, 54, 50, 47, 44, 41, 38, 35, 32, + 30, 28, 26, 24, 22, 20, 18, 16, 14, 13, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 2, 1, 0 + }, + { + 16384, 16149, 15915, 15681, 15447, 15214, 14981, 14749, 14517, 14286, + 14055, 13827, 13599, 13373, 13147, 12923, 12699, 12476, 12253, 12034, + 11815, 11599, 11383, 11171, 10959, 10750, 10541, 10337, 10133, 9933, + 9733, 9536, 9339, 9142, 8945, 8751, 8557, 8369, 8181, 7998, + 7816, 7638, 7460, 7288, 7116, 6950, 6785, 6625, 6465, 6306, + 6147, 5995, 5843, 5697, 5551, 5411, 5271, 5135, 5000, 4871, + 4742, 4618, 4495, 4374, 4253, 4132, 4011, 3893, 3775, 3663, + 3552, 3446, 3340, 3239, 3138, 3043, 2948, 2858, 2768, 2684, + 2600, 2516, 2433, 2355, 2278, 2205, 2133, 2065, 1997, 1932, + 1867, 1807, 1747, 1690, 1634, 1580, 1526, 1472, 1418, 1366, + 1314, 1266, 1218, 1174, 1130, 1088, 1047, 1009, 971, 936, + 901, 868, 836, 804, 772, 743, 714, 685, 658, 631, + 606, 582, 559, 536, 515, 494, 475, 456, 437, 418, + 399, 380, 362, 344, 328, 312, 297, 283, 270, 257, + 245, 233, 222, 211, 201, 191, 181, 172, 163, 155, + 147, 139, 132, 125, 119, 113, 107, 101, 96, 91, + 86, 81, 76, 71, 66, 62, 58, 54, 50, 46, + 43, 40, 37, 34, 31, 28, 26, 24, 22, 20, + 18, 16, 14, 12, 10, 8, 6, 5, 4, 3, + 2, 1, 0 + }, + { + 16384, 16159, 15934, 15709, 15485, 15261, 15038, 14816, 14594, 14373, + 14152, 13933, 13714, 13497, 13280, 13065, 12850, 12636, 12422, 12211, + 12000, 11791, 11583, 11378, 11173, 10971, 10769, 10571, 10373, 10179, + 9985, 9793, 9601, 9409, 9217, 9029, 8842, 8658, 8475, 8297, + 8120, 7946, 7773, 7604, 7435, 7271, 7108, 6950, 6792, 6634, + 6477, 6326, 6175, 6029, 5883, 5742, 5602, 5466, 5330, 5199, + 5068, 4943, 4818, 4696, 4574, 4452, 4330, 4211, 4093, 3979, + 3866, 3759, 3652, 3549, 3446, 3348, 3250, 3157, 3065, 2977, + 2889, 2802, 2716, 2634, 2553, 2476, 2399, 2326, 2254, 2185, + 2117, 2052, 1987, 1926, 1866, 1808, 1750, 1692, 1634, 1578, + 1522, 1470, 1418, 1369, 1321, 1275, 1229, 1187, 1145, 1105, + 1066, 1027, 991, 955, 919, 883, 850, 817, 786, 756, + 728, 700, 674, 648, 624, 600, 578, 556, 534, 512, + 490, 468, 447, 426, 407, 388, 371, 354, 338, 322, + 307, 293, 280, 267, 255, 243, 231, 219, 209, 199, + 189, 179, 170, 161, 153, 145, 138, 131, 124, 117, + 111, 105, 99, 93, 87, 81, 76, 71, 66, 61, + 57, 53, 49, 45, 42, 39, 36, 33, 30, 27, + 24, 21, 19, 17, 15, 13, 11, 9, 7, 5, + 3, 1, 0 + }, + { + 16384, 16169, 15954, 15739, 15524, 15310, 15096, 14883, 14670, 14458, + 14246, 14035, 13824, 13614, 13405, 13198, 12991, 12785, 12579, 12376, + 12173, 11972, 11772, 11574, 11377, 11182, 10987, 10795, 10603, 10414, + 10226, 10040, 9854, 9668, 9482, 9299, 9116, 8937, 8759, 8585, + 8411, 8241, 8071, 7906, 7741, 7580, 7419, 7263, 7107, 6952, + 6797, 6647, 6497, 6353, 6209, 6070, 5931, 5796, 5661, 5531, + 5401, 5275, 5150, 5027, 4904, 4781, 4658, 4538, 4419, 4304, + 4190, 4081, 3972, 3867, 3762, 3662, 3562, 3467, 3372, 3281, + 3191, 3101, 3012, 2928, 2844, 2764, 2684, 2608, 2533, 2460, + 2387, 2318, 2250, 2185, 2121, 2059, 1997, 1935, 1873, 1813, + 1754, 1698, 1642, 1588, 1535, 1483, 1433, 1384, 1338, 1292, + 1249, 1206, 1165, 1125, 1085, 1045, 1008, 971, 937, 903, + 871, 840, 810, 780, 752, 724, 698, 672, 647, 622, + 597, 572, 548, 524, 502, 480, 460, 440, 421, 403, + 386, 369, 353, 337, 323, 309, 295, 281, 268, 255, + 243, 231, 220, 209, 199, 189, 180, 171, 163, 155, + 147, 139, 131, 123, 116, 109, 102, 95, 89, 83, + 77, 72, 67, 62, 57, 52, 48, 44, 40, 36, + 32, 28, 25, 22, 19, 16, 13, 10, 8, 6, + 4, 2, 0 + }, + { + 16384, 16177, 15970, 15764, 15558, 15353, 15148, 14944, 14740, 14537, + 14334, 14132, 13930, 13729, 13529, 13330, 13131, 12933, 12735, 12539, + 12343, 12150, 11957, 11766, 11576, 11388, 11200, 11015, 10830, 10647, + 10465, 10285, 10105, 9925, 9745, 9568, 9391, 9218, 9045, 8876, + 8707, 8541, 8375, 8213, 8051, 7894, 7737, 7583, 7429, 7277, + 7125, 6977, 6830, 6687, 6544, 6406, 6268, 6133, 5998, 5868, + 5738, 5612, 5487, 5364, 5241, 5118, 4995, 4875, 4755, 4640, + 4525, 4414, 4304, 4198, 4092, 3990, 3888, 3790, 3693, 3600, + 3507, 3415, 3323, 3235, 3147, 3064, 2981, 2902, 2823, 2746, + 2670, 2594, 2522, 2450, 2382, 2314, 2248, 2182, 2116, 2050, + 1987, 1924, 1864, 1804, 1748, 1692, 1638, 1585, 1534, 1484, + 1437, 1390, 1346, 1302, 1258, 1215, 1174, 1133, 1095, 1057, + 1021, 986, 952, 918, 887, 856, 827, 798, 770, 742, + 714, 686, 659, 632, 607, 582, 559, 536, 514, 492, + 472, 452, 433, 415, 398, 381, 364, 348, 333, 318, + 304, 290, 277, 264, 252, 240, 229, 218, 208, 198, + 188, 178, 168, 158, 149, 140, 132, 124, 116, 108, + 101, 94, 87, 81, 75, 69, 64, 59, 54, 49, + 44, 39, 35, 31, 27, 23, 19, 15, 12, 9, + 6, 3, 0 + } +}; + + +static const uint16_t cf_tables_3[5][257] = { + { + 16384, 16187, 15990, 15793, 15597, 15401, 15205, 15009, 14813, 14618, + 14423, 14230, 14037, 13845, 13653, 13463, 13273, 13083, 12894, 12706, + 12518, 12332, 12146, 11962, 11778, 11597, 11416, 11237, 11059, 10882, + 10706, 10532, 10358, 10184, 10010, 9838, 9666, 9497, 9328, 9163, + 8999, 8837, 8675, 8517, 8359, 8205, 8051, 7901, 7751, 7602, + 7453, 7308, 7163, 7022, 6882, 6745, 6609, 6476, 6343, 6214, + 6085, 5960, 5835, 5712, 5589, 5466, 5343, 5223, 5103, 4987, + 4872, 4761, 4650, 4542, 4435, 4332, 4229, 4130, 4031, 3936, + 3841, 3747, 3653, 3563, 3473, 3387, 3302, 3220, 3138, 3059, + 2980, 2905, 2830, 2759, 2688, 2619, 2550, 2481, 2412, 2345, + 2278, 2215, 2152, 2092, 2032, 1974, 1917, 1863, 1809, 1758, + 1707, 1659, 1611, 1564, 1517, 1473, 1429, 1387, 1346, 1307, + 1268, 1230, 1193, 1158, 1123, 1090, 1058, 1026, 994, 962, + 930, 899, 869, 841, 813, 786, 760, 735, 710, 687, + 664, 643, 622, 602, 582, 562, 543, 525, 507, 490, + 473, 457, 442, 427, 412, 398, 385, 373, 361, 349, + 337, 325, 313, 301, 290, 279, 269, 259, 249, 240, + 231, 222, 214, 206, 199, 192, 185, 178, 171, 165, + 159, 153, 148, 143, 138, 133, 128, 123, 119, 115, + 111, 107, 103, 99, 95, 91, 87, 83, 80, 77, + 74, 71, 68, 65, 63, 61, 59, 57, 55, 53, + 51, 49, 47, 45, 43, 41, 40, 39, 38, 37, + 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, + 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0 + }, + { + 16384, 16195, 16006, 15817, 15629, 15441, 15253, 15065, 14878, 14692, + 14506, 14321, 14136, 13952, 13768, 13585, 13402, 13219, 13037, 12857, + 12677, 12499, 12321, 12144, 11967, 11792, 11617, 11444, 11271, 11100, + 10930, 10762, 10594, 10426, 10258, 10091, 9925, 9761, 9598, 9438, + 9278, 9120, 8963, 8809, 8655, 8504, 8354, 8207, 8060, 7914, + 7769, 7627, 7485, 7347, 7209, 7074, 6939, 6807, 6676, 6548, + 6420, 6296, 6172, 6050, 5928, 5806, 5684, 5564, 5444, 5328, + 5212, 5100, 4988, 4879, 4771, 4667, 4563, 4462, 4362, 4265, + 4169, 4073, 3978, 3886, 3795, 3707, 3619, 3535, 3451, 3369, + 3288, 3210, 3133, 3059, 2985, 2913, 2841, 2769, 2697, 2627, + 2557, 2490, 2424, 2360, 2297, 2237, 2177, 2119, 2062, 2007, + 1953, 1901, 1849, 1798, 1748, 1700, 1652, 1607, 1562, 1519, + 1476, 1435, 1394, 1355, 1317, 1281, 1245, 1210, 1175, 1140, + 1105, 1071, 1037, 1005, 973, 943, 913, 885, 857, 830, + 804, 779, 754, 731, 708, 685, 663, 642, 621, 601, + 581, 563, 545, 528, 511, 495, 479, 463, 448, 433, + 419, 405, 391, 377, 364, 351, 338, 326, 314, 302, + 291, 280, 270, 260, 251, 242, 234, 226, 218, 210, + 202, 195, 188, 181, 174, 168, 162, 156, 150, 144, + 139, 134, 129, 124, 119, 114, 109, 104, 100, 96, + 92, 88, 84, 80, 77, 74, 71, 68, 65, 62, + 59, 56, 54, 52, 50, 48, 46, 44, 42, 40, + 38, 36, 34, 33, 32, 31, 30, 29, 28, 27, + 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0 + }, + { + 16384, 16203, 16022, 15842, 15662, 15482, 15302, 15122, 14942, 14763, + 14584, 14406, 14228, 14051, 13874, 13698, 13522, 13347, 13172, 12998, + 12824, 12652, 12480, 12310, 12140, 11971, 11803, 11637, 11471, 11307, + 11143, 10980, 10817, 10654, 10491, 10330, 10169, 10011, 9853, 9697, + 9542, 9389, 9236, 9086, 8936, 8789, 8642, 8498, 8355, 8212, + 8070, 7931, 7792, 7656, 7520, 7388, 7256, 7126, 6996, 6870, + 6744, 6621, 6498, 6377, 6256, 6135, 6014, 5895, 5776, 5660, + 5545, 5433, 5321, 5212, 5104, 4999, 4895, 4793, 4692, 4594, + 4496, 4400, 4304, 4211, 4118, 4028, 3939, 3853, 3767, 3684, + 3601, 3521, 3441, 3364, 3287, 3212, 3137, 3062, 2987, 2915, + 2843, 2773, 2704, 2638, 2572, 2508, 2445, 2384, 2324, 2266, + 2208, 2153, 2098, 2044, 1990, 1939, 1888, 1839, 1791, 1745, + 1699, 1655, 1611, 1569, 1527, 1487, 1448, 1409, 1370, 1331, + 1292, 1255, 1218, 1183, 1148, 1115, 1082, 1051, 1020, 990, + 960, 932, 904, 878, 852, 826, 801, 777, 753, 731, + 709, 687, 666, 645, 625, 605, 586, 567, 550, 533, + 516, 499, 482, 465, 449, 433, 418, 403, 389, 375, + 362, 349, 337, 325, 314, 303, 293, 283, 273, 263, + 254, 245, 236, 227, 219, 211, 204, 197, 190, 183, + 177, 171, 165, 159, 153, 147, 141, 135, 130, 125, + 120, 115, 110, 105, 101, 97, 93, 89, 85, 81, + 77, 74, 71, 68, 65, 62, 59, 56, 53, 51, + 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, + 29, 27, 25, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0 + }, + { + 16384, 16210, 16036, 15863, 15690, 15517, 15344, 15172, 15000, 14828, + 14656, 14485, 14314, 14145, 13976, 13808, 13640, 13472, 13304, 13137, + 12970, 12804, 12639, 12475, 12312, 12149, 11987, 11827, 11667, 11508, + 11349, 11192, 11035, 10878, 10721, 10565, 10410, 10257, 10104, 9953, + 9802, 9654, 9506, 9359, 9213, 9070, 8927, 8787, 8647, 8508, + 8369, 8233, 8097, 7964, 7831, 7700, 7570, 7442, 7315, 7190, + 7065, 6943, 6821, 6701, 6581, 6461, 6341, 6223, 6105, 5990, + 5876, 5764, 5653, 5545, 5437, 5331, 5226, 5124, 5022, 4924, + 4826, 4729, 4632, 4538, 4444, 4353, 4262, 4174, 4087, 4002, + 3917, 3835, 3753, 3674, 3595, 3518, 3441, 3364, 3287, 3212, + 3138, 3066, 2995, 2926, 2858, 2792, 2726, 2662, 2599, 2538, + 2478, 2420, 2362, 2305, 2249, 2195, 2141, 2089, 2037, 1988, + 1939, 1891, 1844, 1799, 1754, 1711, 1668, 1626, 1584, 1542, + 1500, 1459, 1418, 1380, 1342, 1305, 1269, 1234, 1199, 1166, + 1133, 1102, 1071, 1041, 1012, 983, 954, 926, 899, 872, + 847, 822, 798, 774, 751, 728, 707, 686, 666, 646, + 627, 608, 589, 570, 552, 534, 517, 500, 484, 468, + 453, 438, 424, 410, 397, 384, 372, 360, 348, 336, + 325, 314, 303, 293, 283, 273, 264, 255, 246, 237, + 229, 221, 213, 205, 197, 189, 181, 174, 167, 160, + 154, 148, 142, 136, 131, 126, 121, 116, 111, 106, + 101, 97, 93, 89, 85, 81, 77, 73, 70, 67, + 64, 61, 58, 55, 52, 49, 46, 43, 40, 37, + 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 6, 5, 4, 3, 2, 1, 0 + }, + { + 16384, 16218, 16052, 15886, 15720, 15554, 15389, 15224, 15059, 14895, + 14731, 14567, 14403, 14240, 14077, 13915, 13753, 13591, 13429, 13269, + 13109, 12950, 12791, 12633, 12476, 12320, 12164, 12009, 11854, 11701, + 11548, 11396, 11244, 11092, 10940, 10790, 10640, 10492, 10344, 10198, + 10052, 9908, 9764, 9622, 9481, 9342, 9203, 9066, 8929, 8793, + 8657, 8524, 8391, 8261, 8131, 8003, 7875, 7749, 7624, 7502, + 7380, 7260, 7140, 7022, 6904, 6786, 6668, 6551, 6435, 6322, + 6209, 6099, 5989, 5881, 5773, 5668, 5563, 5461, 5359, 5260, + 5161, 5063, 4965, 4871, 4777, 4686, 4595, 4506, 4417, 4331, + 4245, 4162, 4079, 3999, 3919, 3841, 3763, 3685, 3607, 3530, + 3454, 3380, 3307, 3236, 3166, 3097, 3029, 2963, 2897, 2834, + 2771, 2710, 2650, 2591, 2532, 2475, 2418, 2363, 2309, 2257, + 2205, 2155, 2105, 2057, 2009, 1963, 1918, 1873, 1828, 1783, + 1738, 1694, 1650, 1607, 1565, 1524, 1484, 1445, 1407, 1369, + 1333, 1297, 1263, 1229, 1197, 1165, 1134, 1103, 1073, 1043, + 1015, 987, 960, 933, 907, 882, 858, 834, 811, 788, + 766, 744, 722, 700, 679, 658, 638, 618, 599, 581, + 563, 545, 528, 511, 495, 480, 465, 451, 437, 423, + 410, 397, 384, 372, 360, 348, 337, 326, 315, 305, + 295, 285, 275, 265, 255, 245, 236, 227, 219, 211, + 203, 195, 188, 181, 174, 167, 161, 155, 149, 143, + 137, 131, 126, 121, 116, 111, 106, 101, 97, 93, + 89, 85, 81, 77, 73, 69, 65, 61, 58, 55, + 52, 49, 46, 43, 40, 37, 34, 32, 30, 28, + 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, + 6, 5, 4, 3, 2, 1, 0 + } +}; + + +static const uint16_t *const cf_table[16] = { + cf_tables_1[0], cf_tables_1[1], cf_tables_1[2], cf_tables_2[0], + cf_tables_2[1], cf_tables_2[2], cf_tables_2[3], cf_tables_2[4], + cf_tables_2[5], cf_tables_2[6], cf_tables_2[7], cf_tables_3[0], + cf_tables_3[1], cf_tables_3[2], cf_tables_3[3], cf_tables_3[4] +}; + + +/** Initialize a given lookup table using a given delta */ +static void bgmc_lut_fillp(uint8_t *lut, int *lut_status, int delta) +{ + unsigned int sx, i; + + for (sx = 0; sx < 16; sx++) + for (i = 0; i < LUT_SIZE; i++) { + unsigned int target = (i + 1) << (FREQ_BITS - LUT_BITS); + unsigned int symbol = 1 << delta; + + while (cf_table[sx][symbol] > target) + symbol += 1 << delta; + + *lut++ = symbol >> delta; + } + + *lut_status = delta; +} + + +/** Retune the index of a suitable lookup table for a given delta */ +static uint8_t *bgmc_lut_getp(uint8_t *lut, int *lut_status, int delta) +{ + unsigned int i = av_clip(delta, 0, LUT_BUFF - 1); + + lut += (i * LUT_SIZE) << 4; + + if (lut_status[i] != delta) + bgmc_lut_fillp(lut, &lut_status[i], delta); + + return lut; +} + + +/** Initialize the lookup table arrays */ +int ff_bgmc_init(AVCodecContext *avctx, uint8_t **cf_lut, int **cf_lut_status) +{ + *cf_lut = av_malloc(sizeof(**cf_lut) * LUT_BUFF * 16 * LUT_SIZE); + *cf_lut_status = av_malloc(sizeof(**cf_lut_status) * LUT_BUFF); + + if (!*cf_lut || !*cf_lut_status) { + ff_bgmc_end(cf_lut, cf_lut_status); + av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); + return AVERROR(ENOMEM); + } else { + // initialize lut_status buffer to a value never used to compare against + memset(*cf_lut_status, -1, sizeof(**cf_lut_status) * LUT_BUFF); + } + + return 0; +} + + +/** Release the lookup table arrays */ +void ff_bgmc_end(uint8_t **cf_lut, int **cf_lut_status) +{ + av_freep(cf_lut); + av_freep(cf_lut_status); +} + + +/** Initialize decoding and reads the first value */ +void ff_bgmc_decode_init(GetBitContext *gb, unsigned int *h, unsigned int *l, + unsigned int *v) +{ + *h = TOP_VALUE; + *l = 0; + *v = get_bits_long(gb, VALUE_BITS); +} + + +/** Finish decoding */ +void ff_bgmc_decode_end(GetBitContext *gb) +{ + skip_bits_long(gb, -(VALUE_BITS - 2)); +} + + +/** Read and decode a block Gilbert-Moore coded symbol */ +void ff_bgmc_decode(GetBitContext *gb, unsigned int num, int32_t *dst, + int delta, unsigned int sx, + unsigned int *h, unsigned int *l, unsigned int *v, + uint8_t *cf_lut, int *cf_lut_status) +{ + unsigned int i; + uint8_t *lut = bgmc_lut_getp(cf_lut, cf_lut_status, delta); + + // read current state + unsigned int high = *h; + unsigned int low = *l; + unsigned int value = *v; + + lut += sx * LUT_SIZE; + + // decode num samples + for (i = 0; i < num; i++) { + unsigned int range = high - low + 1; + unsigned int target = (((value - low + 1) << FREQ_BITS) - 1) / range; + unsigned int symbol = lut[target >> (FREQ_BITS - LUT_BITS)] << delta; + + while (cf_table[sx][symbol] > target) + symbol += 1 << delta; + + symbol = (symbol >> delta) - 1; + + high = low + ((range * cf_table[sx][(symbol) << delta] - (1 << FREQ_BITS)) >> FREQ_BITS); + low = low + ((range * cf_table[sx][(symbol + 1) << delta]) >> FREQ_BITS); + + while (1) { + if (high >= HALF) { + if (low >= HALF) { + value -= HALF; + low -= HALF; + high -= HALF; + } else if (low >= FIRST_QTR && high < THIRD_QTR) { + value -= FIRST_QTR; + low -= FIRST_QTR; + high -= FIRST_QTR; + } else + break; + } + + low *= 2; + high = 2 * high + 1; + value = 2 * value + get_bits1(gb); + } + + *dst++ = symbol; + } + + // save current state + *h = high; + *l = low; + *v = value; +} diff --git a/ffmpeg/libavcodec/bgmc.h b/ffmpeg/libavcodec/bgmc.h new file mode 100644 index 0000000..9e386fd --- /dev/null +++ b/ffmpeg/libavcodec/bgmc.h @@ -0,0 +1,56 @@ +/* + * Block Gilbert-Moore decoder + * Copyright (c) 2010 Thilo Borgmann + * + * 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 + */ + +/** + * @file + * Block Gilbert-Moore decoder header + * @author Thilo Borgmann + */ + + +#ifndef AVCODEC_BGMC_H +#define AVCODEC_BGMC_H + + +#include "avcodec.h" +#include "get_bits.h" + + +int ff_bgmc_init(AVCodecContext *avctx, uint8_t **cf_lut, int **cf_lut_status); + + +void ff_bgmc_end(uint8_t **cf_lut, int **cf_lut_status); + + +void ff_bgmc_decode_init(GetBitContext *gb, + unsigned int *h, unsigned int *l, unsigned int *v); + + +void ff_bgmc_decode_end(GetBitContext *gb); + + +void ff_bgmc_decode(GetBitContext *gb, unsigned int num, int32_t *dst, + int delta, unsigned int sx, + unsigned int *h, unsigned int *l, unsigned int *v, + uint8_t *cf_lut, int *cf_lut_status); + + +#endif /* AVCODEC_BGMC_H */ diff --git a/ffmpeg/libavcodec/bink.c b/ffmpeg/libavcodec/bink.c new file mode 100644 index 0000000..9bab4b9 --- /dev/null +++ b/ffmpeg/libavcodec/bink.c @@ -0,0 +1,1344 @@ +/* + * Bink video decoder + * Copyright (c) 2009 Konstantin Shishkov + * Copyright (C) 2011 Peter Ross + * + * 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 "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "avcodec.h" +#include "dsputil.h" +#include "binkdata.h" +#include "binkdsp.h" +#include "hpeldsp.h" +#include "internal.h" +#include "mathops.h" + +#define BITSTREAM_READER_LE +#include "get_bits.h" + +#define BINK_FLAG_ALPHA 0x00100000 +#define BINK_FLAG_GRAY 0x00020000 + +static VLC bink_trees[16]; + +/** + * IDs for different data types used in old version of Bink video codec + */ +enum OldSources { + BINKB_SRC_BLOCK_TYPES = 0, ///< 8x8 block types + BINKB_SRC_COLORS, ///< pixel values used for different block types + BINKB_SRC_PATTERN, ///< 8-bit values for 2-colour pattern fill + BINKB_SRC_X_OFF, ///< X components of motion value + BINKB_SRC_Y_OFF, ///< Y components of motion value + BINKB_SRC_INTRA_DC, ///< DC values for intrablocks with DCT + BINKB_SRC_INTER_DC, ///< DC values for interblocks with DCT + BINKB_SRC_INTRA_Q, ///< quantizer values for intrablocks with DCT + BINKB_SRC_INTER_Q, ///< quantizer values for interblocks with DCT + BINKB_SRC_INTER_COEFS, ///< number of coefficients for residue blocks + + BINKB_NB_SRC +}; + +static const int binkb_bundle_sizes[BINKB_NB_SRC] = { + 4, 8, 8, 5, 5, 11, 11, 4, 4, 7 +}; + +static const int binkb_bundle_signed[BINKB_NB_SRC] = { + 0, 0, 0, 1, 1, 0, 1, 0, 0, 0 +}; + +static int32_t binkb_intra_quant[16][64]; +static int32_t binkb_inter_quant[16][64]; + +/** + * IDs for different data types used in Bink video codec + */ +enum Sources { + BINK_SRC_BLOCK_TYPES = 0, ///< 8x8 block types + BINK_SRC_SUB_BLOCK_TYPES, ///< 16x16 block types (a subset of 8x8 block types) + BINK_SRC_COLORS, ///< pixel values used for different block types + BINK_SRC_PATTERN, ///< 8-bit values for 2-colour pattern fill + BINK_SRC_X_OFF, ///< X components of motion value + BINK_SRC_Y_OFF, ///< Y components of motion value + BINK_SRC_INTRA_DC, ///< DC values for intrablocks with DCT + BINK_SRC_INTER_DC, ///< DC values for interblocks with DCT + BINK_SRC_RUN, ///< run lengths for special fill block + + BINK_NB_SRC +}; + +/** + * data needed to decode 4-bit Huffman-coded value + */ +typedef struct Tree { + int vlc_num; ///< tree number (in bink_trees[]) + uint8_t syms[16]; ///< leaf value to symbol mapping +} Tree; + +#define GET_HUFF(gb, tree) (tree).syms[get_vlc2(gb, bink_trees[(tree).vlc_num].table,\ + bink_trees[(tree).vlc_num].bits, 1)] + +/** + * data structure used for decoding single Bink data type + */ +typedef struct Bundle { + int len; ///< length of number of entries to decode (in bits) + Tree tree; ///< Huffman tree-related data + uint8_t *data; ///< buffer for decoded symbols + uint8_t *data_end; ///< buffer end + uint8_t *cur_dec; ///< pointer to the not yet decoded part of the buffer + uint8_t *cur_ptr; ///< pointer to the data that is not read from buffer yet +} Bundle; + +/* + * Decoder context + */ +typedef struct BinkContext { + AVCodecContext *avctx; + DSPContext dsp; + HpelDSPContext hdsp; + BinkDSPContext bdsp; + AVFrame *last; + int version; ///< internal Bink file version + int has_alpha; + int swap_planes; + + Bundle bundle[BINKB_NB_SRC]; ///< bundles for decoding all data types + Tree col_high[16]; ///< trees for decoding high nibble in "colours" data type + int col_lastval; ///< value of last decoded high nibble in "colours" data type +} BinkContext; + +/** + * Bink video block types + */ +enum BlockTypes { + SKIP_BLOCK = 0, ///< skipped block + SCALED_BLOCK, ///< block has size 16x16 + MOTION_BLOCK, ///< block is copied from previous frame with some offset + RUN_BLOCK, ///< block is composed from runs of colours with custom scan order + RESIDUE_BLOCK, ///< motion block with some difference added + INTRA_BLOCK, ///< intra DCT block + FILL_BLOCK, ///< block is filled with single colour + INTER_BLOCK, ///< motion block with DCT applied to the difference + PATTERN_BLOCK, ///< block is filled with two colours following custom pattern + RAW_BLOCK, ///< uncoded 8x8 block +}; + +/** + * Initialize length length in all bundles. + * + * @param c decoder context + * @param width plane width + * @param bw plane width in 8x8 blocks + */ +static void init_lengths(BinkContext *c, int width, int bw) +{ + width = FFALIGN(width, 8); + + c->bundle[BINK_SRC_BLOCK_TYPES].len = av_log2((width >> 3) + 511) + 1; + + c->bundle[BINK_SRC_SUB_BLOCK_TYPES].len = av_log2((width >> 4) + 511) + 1; + + c->bundle[BINK_SRC_COLORS].len = av_log2(bw*64 + 511) + 1; + + c->bundle[BINK_SRC_INTRA_DC].len = + c->bundle[BINK_SRC_INTER_DC].len = + c->bundle[BINK_SRC_X_OFF].len = + c->bundle[BINK_SRC_Y_OFF].len = av_log2((width >> 3) + 511) + 1; + + c->bundle[BINK_SRC_PATTERN].len = av_log2((bw << 3) + 511) + 1; + + c->bundle[BINK_SRC_RUN].len = av_log2(bw*48 + 511) + 1; +} + +/** + * Allocate memory for bundles. + * + * @param c decoder context + */ +static av_cold int init_bundles(BinkContext *c) +{ + int bw, bh, blocks; + int i; + + bw = (c->avctx->width + 7) >> 3; + bh = (c->avctx->height + 7) >> 3; + blocks = bw * bh; + + for (i = 0; i < BINKB_NB_SRC; i++) { + c->bundle[i].data = av_malloc(blocks * 64); + if (!c->bundle[i].data) + return AVERROR(ENOMEM); + c->bundle[i].data_end = c->bundle[i].data + blocks * 64; + } + + return 0; +} + +/** + * Free memory used by bundles. + * + * @param c decoder context + */ +static av_cold void free_bundles(BinkContext *c) +{ + int i; + for (i = 0; i < BINKB_NB_SRC; i++) + av_freep(&c->bundle[i].data); +} + +/** + * Merge two consequent lists of equal size depending on bits read. + * + * @param gb context for reading bits + * @param dst buffer where merged list will be written to + * @param src pointer to the head of the first list (the second lists starts at src+size) + * @param size input lists size + */ +static void merge(GetBitContext *gb, uint8_t *dst, uint8_t *src, int size) +{ + uint8_t *src2 = src + size; + int size2 = size; + + do { + if (!get_bits1(gb)) { + *dst++ = *src++; + size--; + } else { + *dst++ = *src2++; + size2--; + } + } while (size && size2); + + while (size--) + *dst++ = *src++; + while (size2--) + *dst++ = *src2++; +} + +/** + * Read information about Huffman tree used to decode data. + * + * @param gb context for reading bits + * @param tree pointer for storing tree data + */ +static void read_tree(GetBitContext *gb, Tree *tree) +{ + uint8_t tmp1[16] = { 0 }, tmp2[16], *in = tmp1, *out = tmp2; + int i, t, len; + + tree->vlc_num = get_bits(gb, 4); + if (!tree->vlc_num) { + for (i = 0; i < 16; i++) + tree->syms[i] = i; + return; + } + if (get_bits1(gb)) { + len = get_bits(gb, 3); + for (i = 0; i <= len; i++) { + tree->syms[i] = get_bits(gb, 4); + tmp1[tree->syms[i]] = 1; + } + for (i = 0; i < 16 && len < 16 - 1; i++) + if (!tmp1[i]) + tree->syms[++len] = i; + } else { + len = get_bits(gb, 2); + for (i = 0; i < 16; i++) + in[i] = i; + for (i = 0; i <= len; i++) { + int size = 1 << i; + for (t = 0; t < 16; t += size << 1) + merge(gb, out + t, in + t, size); + FFSWAP(uint8_t*, in, out); + } + memcpy(tree->syms, in, 16); + } +} + +/** + * Prepare bundle for decoding data. + * + * @param gb context for reading bits + * @param c decoder context + * @param bundle_num number of the bundle to initialize + */ +static void read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num) +{ + int i; + + if (bundle_num == BINK_SRC_COLORS) { + for (i = 0; i < 16; i++) + read_tree(gb, &c->col_high[i]); + c->col_lastval = 0; + } + if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC) + read_tree(gb, &c->bundle[bundle_num].tree); + c->bundle[bundle_num].cur_dec = + c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data; +} + +/** + * common check before starting decoding bundle data + * + * @param gb context for reading bits + * @param b bundle + * @param t variable where number of elements to decode will be stored + */ +#define CHECK_READ_VAL(gb, b, t) \ + if (!b->cur_dec || (b->cur_dec > b->cur_ptr)) \ + return 0; \ + t = get_bits(gb, b->len); \ + if (!t) { \ + b->cur_dec = NULL; \ + return 0; \ + } \ + +static int read_runs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) +{ + int t, v; + const uint8_t *dec_end; + + CHECK_READ_VAL(gb, b, t); + dec_end = b->cur_dec + t; + if (dec_end > b->data_end) { + av_log(avctx, AV_LOG_ERROR, "Run value went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + v = get_bits(gb, 4); + memset(b->cur_dec, v, t); + b->cur_dec += t; + } else { + while (b->cur_dec < dec_end) + *b->cur_dec++ = GET_HUFF(gb, b->tree); + } + return 0; +} + +static int read_motion_values(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) +{ + int t, sign, v; + const uint8_t *dec_end; + + CHECK_READ_VAL(gb, b, t); + dec_end = b->cur_dec + t; + if (dec_end > b->data_end) { + av_log(avctx, AV_LOG_ERROR, "Too many motion values\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + v = get_bits(gb, 4); + if (v) { + sign = -get_bits1(gb); + v = (v ^ sign) - sign; + } + memset(b->cur_dec, v, t); + b->cur_dec += t; + } else { + while (b->cur_dec < dec_end) { + v = GET_HUFF(gb, b->tree); + if (v) { + sign = -get_bits1(gb); + v = (v ^ sign) - sign; + } + *b->cur_dec++ = v; + } + } + return 0; +} + +static const uint8_t bink_rlelens[4] = { 4, 8, 12, 32 }; + +static int read_block_types(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) +{ + int t, v; + int last = 0; + const uint8_t *dec_end; + + CHECK_READ_VAL(gb, b, t); + dec_end = b->cur_dec + t; + if (dec_end > b->data_end) { + av_log(avctx, AV_LOG_ERROR, "Too many block type values\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + v = get_bits(gb, 4); + memset(b->cur_dec, v, t); + b->cur_dec += t; + } else { + while (b->cur_dec < dec_end) { + v = GET_HUFF(gb, b->tree); + if (v < 12) { + last = v; + *b->cur_dec++ = v; + } else { + int run = bink_rlelens[v - 12]; + + if (dec_end - b->cur_dec < run) + return AVERROR_INVALIDDATA; + memset(b->cur_dec, last, run); + b->cur_dec += run; + } + } + } + return 0; +} + +static int read_patterns(AVCodecContext *avctx, GetBitContext *gb, Bundle *b) +{ + int t, v; + const uint8_t *dec_end; + + CHECK_READ_VAL(gb, b, t); + dec_end = b->cur_dec + t; + if (dec_end > b->data_end) { + av_log(avctx, AV_LOG_ERROR, "Too many pattern values\n"); + return AVERROR_INVALIDDATA; + } + while (b->cur_dec < dec_end) { + v = GET_HUFF(gb, b->tree); + v |= GET_HUFF(gb, b->tree) << 4; + *b->cur_dec++ = v; + } + + return 0; +} + +static int read_colors(GetBitContext *gb, Bundle *b, BinkContext *c) +{ + int t, sign, v; + const uint8_t *dec_end; + + CHECK_READ_VAL(gb, b, t); + dec_end = b->cur_dec + t; + if (dec_end > b->data_end) { + av_log(c->avctx, AV_LOG_ERROR, "Too many color values\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]); + v = GET_HUFF(gb, b->tree); + v = (c->col_lastval << 4) | v; + if (c->version < 'i') { + sign = ((int8_t) v) >> 7; + v = ((v & 0x7F) ^ sign) - sign; + v += 0x80; + } + memset(b->cur_dec, v, t); + b->cur_dec += t; + } else { + while (b->cur_dec < dec_end) { + c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]); + v = GET_HUFF(gb, b->tree); + v = (c->col_lastval << 4) | v; + if (c->version < 'i') { + sign = ((int8_t) v) >> 7; + v = ((v & 0x7F) ^ sign) - sign; + v += 0x80; + } + *b->cur_dec++ = v; + } + } + return 0; +} + +/** number of bits used to store first DC value in bundle */ +#define DC_START_BITS 11 + +static int read_dcs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b, + int start_bits, int has_sign) +{ + int i, j, len, len2, bsize, sign, v, v2; + int16_t *dst = (int16_t*)b->cur_dec; + int16_t *dst_end = (int16_t*)b->data_end; + + CHECK_READ_VAL(gb, b, len); + v = get_bits(gb, start_bits - has_sign); + if (v && has_sign) { + sign = -get_bits1(gb); + v = (v ^ sign) - sign; + } + if (dst_end - dst < 1) + return AVERROR_INVALIDDATA; + *dst++ = v; + len--; + for (i = 0; i < len; i += 8) { + len2 = FFMIN(len - i, 8); + if (dst_end - dst < len2) + return AVERROR_INVALIDDATA; + bsize = get_bits(gb, 4); + if (bsize) { + for (j = 0; j < len2; j++) { + v2 = get_bits(gb, bsize); + if (v2) { + sign = -get_bits1(gb); + v2 = (v2 ^ sign) - sign; + } + v += v2; + *dst++ = v; + if (v < -32768 || v > 32767) { + av_log(avctx, AV_LOG_ERROR, "DC value went out of bounds: %d\n", v); + return AVERROR_INVALIDDATA; + } + } + } else { + for (j = 0; j < len2; j++) + *dst++ = v; + } + } + + b->cur_dec = (uint8_t*)dst; + return 0; +} + +/** + * Retrieve next value from bundle. + * + * @param c decoder context + * @param bundle bundle number + */ +static inline int get_value(BinkContext *c, int bundle) +{ + int ret; + + if (bundle < BINK_SRC_X_OFF || bundle == BINK_SRC_RUN) + return *c->bundle[bundle].cur_ptr++; + if (bundle == BINK_SRC_X_OFF || bundle == BINK_SRC_Y_OFF) + return (int8_t)*c->bundle[bundle].cur_ptr++; + ret = *(int16_t*)c->bundle[bundle].cur_ptr; + c->bundle[bundle].cur_ptr += 2; + return ret; +} + +static void binkb_init_bundle(BinkContext *c, int bundle_num) +{ + c->bundle[bundle_num].cur_dec = + c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data; + c->bundle[bundle_num].len = 13; +} + +static void binkb_init_bundles(BinkContext *c) +{ + int i; + for (i = 0; i < BINKB_NB_SRC; i++) + binkb_init_bundle(c, i); +} + +static int binkb_read_bundle(BinkContext *c, GetBitContext *gb, int bundle_num) +{ + const int bits = binkb_bundle_sizes[bundle_num]; + const int mask = 1 << (bits - 1); + const int issigned = binkb_bundle_signed[bundle_num]; + Bundle *b = &c->bundle[bundle_num]; + int i, len; + + CHECK_READ_VAL(gb, b, len); + if (b->data_end - b->cur_dec < len * (1 + (bits > 8))) + return AVERROR_INVALIDDATA; + if (bits <= 8) { + if (!issigned) { + for (i = 0; i < len; i++) + *b->cur_dec++ = get_bits(gb, bits); + } else { + for (i = 0; i < len; i++) + *b->cur_dec++ = get_bits(gb, bits) - mask; + } + } else { + int16_t *dst = (int16_t*)b->cur_dec; + + if (!issigned) { + for (i = 0; i < len; i++) + *dst++ = get_bits(gb, bits); + } else { + for (i = 0; i < len; i++) + *dst++ = get_bits(gb, bits) - mask; + } + b->cur_dec = (uint8_t*)dst; + } + return 0; +} + +static inline int binkb_get_value(BinkContext *c, int bundle_num) +{ + int16_t ret; + const int bits = binkb_bundle_sizes[bundle_num]; + + if (bits <= 8) { + int val = *c->bundle[bundle_num].cur_ptr++; + return binkb_bundle_signed[bundle_num] ? (int8_t)val : val; + } + ret = *(int16_t*)c->bundle[bundle_num].cur_ptr; + c->bundle[bundle_num].cur_ptr += 2; + return ret; +} + +/** + * Read 8x8 block of DCT coefficients. + * + * @param gb context for reading bits + * @param block place for storing coefficients + * @param scan scan order table + * @param quant_matrices quantization matrices + * @return 0 for success, negative value in other cases + */ +static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t *scan, + const int32_t quant_matrices[16][64], int q) +{ + int coef_list[128]; + int mode_list[128]; + int i, t, bits, ccoef, mode, sign; + int list_start = 64, list_end = 64, list_pos; + int coef_count = 0; + int coef_idx[64]; + int quant_idx; + const int32_t *quant; + + coef_list[list_end] = 4; mode_list[list_end++] = 0; + coef_list[list_end] = 24; mode_list[list_end++] = 0; + coef_list[list_end] = 44; mode_list[list_end++] = 0; + coef_list[list_end] = 1; mode_list[list_end++] = 3; + coef_list[list_end] = 2; mode_list[list_end++] = 3; + coef_list[list_end] = 3; mode_list[list_end++] = 3; + + for (bits = get_bits(gb, 4) - 1; bits >= 0; bits--) { + list_pos = list_start; + while (list_pos < list_end) { + if (!(mode_list[list_pos] | coef_list[list_pos]) || !get_bits1(gb)) { + list_pos++; + continue; + } + ccoef = coef_list[list_pos]; + mode = mode_list[list_pos]; + switch (mode) { + case 0: + coef_list[list_pos] = ccoef + 4; + mode_list[list_pos] = 1; + case 2: + if (mode == 2) { + coef_list[list_pos] = 0; + mode_list[list_pos++] = 0; + } + for (i = 0; i < 4; i++, ccoef++) { + if (get_bits1(gb)) { + coef_list[--list_start] = ccoef; + mode_list[ list_start] = 3; + } else { + if (!bits) { + t = 1 - (get_bits1(gb) << 1); + } else { + t = get_bits(gb, bits) | 1 << bits; + sign = -get_bits1(gb); + t = (t ^ sign) - sign; + } + block[scan[ccoef]] = t; + coef_idx[coef_count++] = ccoef; + } + } + break; + case 1: + mode_list[list_pos] = 2; + for (i = 0; i < 3; i++) { + ccoef += 4; + coef_list[list_end] = ccoef; + mode_list[list_end++] = 2; + } + break; + case 3: + if (!bits) { + t = 1 - (get_bits1(gb) << 1); + } else { + t = get_bits(gb, bits) | 1 << bits; + sign = -get_bits1(gb); + t = (t ^ sign) - sign; + } + block[scan[ccoef]] = t; + coef_idx[coef_count++] = ccoef; + coef_list[list_pos] = 0; + mode_list[list_pos++] = 0; + break; + } + } + } + + if (q == -1) { + quant_idx = get_bits(gb, 4); + } else { + quant_idx = q; + if (quant_idx > 15U) { + av_log(NULL, AV_LOG_ERROR, "quant_index %d out of range\n", quant_idx); + return AVERROR_INVALIDDATA; + } + } + + quant = quant_matrices[quant_idx]; + + block[0] = (block[0] * quant[0]) >> 11; + for (i = 0; i < coef_count; i++) { + int idx = coef_idx[i]; + block[scan[idx]] = (block[scan[idx]] * quant[idx]) >> 11; + } + + return 0; +} + +/** + * Read 8x8 block with residue after motion compensation. + * + * @param gb context for reading bits + * @param block place to store read data + * @param masks_count number of masks to decode + * @return 0 on success, negative value in other cases + */ +static int read_residue(GetBitContext *gb, int16_t block[64], int masks_count) +{ + int coef_list[128]; + int mode_list[128]; + int i, sign, mask, ccoef, mode; + int list_start = 64, list_end = 64, list_pos; + int nz_coeff[64]; + int nz_coeff_count = 0; + + coef_list[list_end] = 4; mode_list[list_end++] = 0; + coef_list[list_end] = 24; mode_list[list_end++] = 0; + coef_list[list_end] = 44; mode_list[list_end++] = 0; + coef_list[list_end] = 0; mode_list[list_end++] = 2; + + for (mask = 1 << get_bits(gb, 3); mask; mask >>= 1) { + for (i = 0; i < nz_coeff_count; i++) { + if (!get_bits1(gb)) + continue; + if (block[nz_coeff[i]] < 0) + block[nz_coeff[i]] -= mask; + else + block[nz_coeff[i]] += mask; + masks_count--; + if (masks_count < 0) + return 0; + } + list_pos = list_start; + while (list_pos < list_end) { + if (!(coef_list[list_pos] | mode_list[list_pos]) || !get_bits1(gb)) { + list_pos++; + continue; + } + ccoef = coef_list[list_pos]; + mode = mode_list[list_pos]; + switch (mode) { + case 0: + coef_list[list_pos] = ccoef + 4; + mode_list[list_pos] = 1; + case 2: + if (mode == 2) { + coef_list[list_pos] = 0; + mode_list[list_pos++] = 0; + } + for (i = 0; i < 4; i++, ccoef++) { + if (get_bits1(gb)) { + coef_list[--list_start] = ccoef; + mode_list[ list_start] = 3; + } else { + nz_coeff[nz_coeff_count++] = bink_scan[ccoef]; + sign = -get_bits1(gb); + block[bink_scan[ccoef]] = (mask ^ sign) - sign; + masks_count--; + if (masks_count < 0) + return 0; + } + } + break; + case 1: + mode_list[list_pos] = 2; + for (i = 0; i < 3; i++) { + ccoef += 4; + coef_list[list_end] = ccoef; + mode_list[list_end++] = 2; + } + break; + case 3: + nz_coeff[nz_coeff_count++] = bink_scan[ccoef]; + sign = -get_bits1(gb); + block[bink_scan[ccoef]] = (mask ^ sign) - sign; + coef_list[list_pos] = 0; + mode_list[list_pos++] = 0; + masks_count--; + if (masks_count < 0) + return 0; + break; + } + } + } + + return 0; +} + +/** + * Copy 8x8 block from source to destination, where src and dst may be overlapped + */ +static inline void put_pixels8x8_overlapped(uint8_t *dst, uint8_t *src, int stride) +{ + uint8_t tmp[64]; + int i; + for (i = 0; i < 8; i++) + memcpy(tmp + i*8, src + i*stride, 8); + for (i = 0; i < 8; i++) + memcpy(dst + i*stride, tmp + i*8, 8); +} + +static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, + int plane_idx, int is_key, int is_chroma) +{ + int blk, ret; + int i, j, bx, by; + uint8_t *dst, *ref, *ref_start, *ref_end; + int v, col[2]; + const uint8_t *scan; + int xoff, yoff; + LOCAL_ALIGNED_16(int16_t, block, [64]); + LOCAL_ALIGNED_16(int32_t, dctblock, [64]); + int coordmap[64]; + int ybias = is_key ? -15 : 0; + int qp; + + const int stride = frame->linesize[plane_idx]; + int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; + int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3; + + binkb_init_bundles(c); + ref_start = frame->data[plane_idx]; + ref_end = frame->data[plane_idx] + (bh * frame->linesize[plane_idx] + bw) * 8; + + for (i = 0; i < 64; i++) + coordmap[i] = (i & 7) + (i >> 3) * stride; + + for (by = 0; by < bh; by++) { + for (i = 0; i < BINKB_NB_SRC; i++) { + if ((ret = binkb_read_bundle(c, gb, i)) < 0) + return ret; + } + + dst = frame->data[plane_idx] + 8*by*stride; + for (bx = 0; bx < bw; bx++, dst += 8) { + blk = binkb_get_value(c, BINKB_SRC_BLOCK_TYPES); + switch (blk) { + case 0: + break; + case 1: + scan = bink_patterns[get_bits(gb, 4)]; + i = 0; + do { + int mode, run; + + mode = get_bits1(gb); + run = get_bits(gb, binkb_runbits[i]) + 1; + + i += run; + if (i > 64) { + av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + if (mode) { + v = binkb_get_value(c, BINKB_SRC_COLORS); + for (j = 0; j < run; j++) + dst[coordmap[*scan++]] = v; + } else { + for (j = 0; j < run; j++) + dst[coordmap[*scan++]] = binkb_get_value(c, BINKB_SRC_COLORS); + } + } while (i < 63); + if (i == 63) + dst[coordmap[*scan++]] = binkb_get_value(c, BINKB_SRC_COLORS); + break; + case 2: + memset(dctblock, 0, sizeof(*dctblock) * 64); + dctblock[0] = binkb_get_value(c, BINKB_SRC_INTRA_DC); + qp = binkb_get_value(c, BINKB_SRC_INTRA_Q); + read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_intra_quant, qp); + c->bdsp.idct_put(dst, stride, dctblock); + break; + case 3: + xoff = binkb_get_value(c, BINKB_SRC_X_OFF); + yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias; + ref = dst + xoff + yoff * stride; + if (ref < ref_start || ref + 8*stride > ref_end) { + av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); + } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + } else { + put_pixels8x8_overlapped(dst, ref, stride); + } + c->dsp.clear_block(block); + v = binkb_get_value(c, BINKB_SRC_INTER_COEFS); + read_residue(gb, block, v); + c->dsp.add_pixels8(dst, block, stride); + break; + case 4: + xoff = binkb_get_value(c, BINKB_SRC_X_OFF); + yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias; + ref = dst + xoff + yoff * stride; + if (ref < ref_start || ref + 8 * stride > ref_end) { + av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); + } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + } else { + put_pixels8x8_overlapped(dst, ref, stride); + } + memset(dctblock, 0, sizeof(*dctblock) * 64); + dctblock[0] = binkb_get_value(c, BINKB_SRC_INTER_DC); + qp = binkb_get_value(c, BINKB_SRC_INTER_Q); + read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_inter_quant, qp); + c->bdsp.idct_add(dst, stride, dctblock); + break; + case 5: + v = binkb_get_value(c, BINKB_SRC_COLORS); + c->dsp.fill_block_tab[1](dst, v, stride, 8); + break; + case 6: + for (i = 0; i < 2; i++) + col[i] = binkb_get_value(c, BINKB_SRC_COLORS); + for (i = 0; i < 8; i++) { + v = binkb_get_value(c, BINKB_SRC_PATTERN); + for (j = 0; j < 8; j++, v >>= 1) + dst[i*stride + j] = col[v & 1]; + } + break; + case 7: + xoff = binkb_get_value(c, BINKB_SRC_X_OFF); + yoff = binkb_get_value(c, BINKB_SRC_Y_OFF) + ybias; + ref = dst + xoff + yoff * stride; + if (ref < ref_start || ref + 8 * stride > ref_end) { + av_log(c->avctx, AV_LOG_WARNING, "Reference block is out of bounds\n"); + } else if (ref + 8*stride < dst || ref >= dst + 8*stride) { + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + } else { + put_pixels8x8_overlapped(dst, ref, stride); + } + break; + case 8: + for (i = 0; i < 8; i++) + memcpy(dst + i*stride, c->bundle[BINKB_SRC_COLORS].cur_ptr + i*8, 8); + c->bundle[BINKB_SRC_COLORS].cur_ptr += 64; + break; + default: + av_log(c->avctx, AV_LOG_ERROR, "Unknown block type %d\n", blk); + return AVERROR_INVALIDDATA; + } + } + } + if (get_bits_count(gb) & 0x1F) //next plane data starts at 32-bit boundary + skip_bits_long(gb, 32 - (get_bits_count(gb) & 0x1F)); + + return 0; +} + +static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb, + int plane_idx, int is_chroma) +{ + int blk, ret; + int i, j, bx, by; + uint8_t *dst, *prev, *ref, *ref_start, *ref_end; + int v, col[2]; + const uint8_t *scan; + int xoff, yoff; + LOCAL_ALIGNED_16(int16_t, block, [64]); + LOCAL_ALIGNED_16(uint8_t, ublock, [64]); + LOCAL_ALIGNED_16(int32_t, dctblock, [64]); + int coordmap[64]; + + const int stride = frame->linesize[plane_idx]; + int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3; + int bh = is_chroma ? (c->avctx->height + 15) >> 4 : (c->avctx->height + 7) >> 3; + int width = c->avctx->width >> is_chroma; + + init_lengths(c, FFMAX(width, 8), bw); + for (i = 0; i < BINK_NB_SRC; i++) + read_bundle(gb, c, i); + + ref_start = c->last->data[plane_idx] ? c->last->data[plane_idx] + : frame->data[plane_idx]; + ref_end = ref_start + + (bw - 1 + c->last->linesize[plane_idx] * (bh - 1)) * 8; + + for (i = 0; i < 64; i++) + coordmap[i] = (i & 7) + (i >> 3) * stride; + + for (by = 0; by < bh; by++) { + if ((ret = read_block_types(c->avctx, gb, &c->bundle[BINK_SRC_BLOCK_TYPES])) < 0) + return ret; + if ((ret = read_block_types(c->avctx, gb, &c->bundle[BINK_SRC_SUB_BLOCK_TYPES])) < 0) + return ret; + if ((ret = read_colors(gb, &c->bundle[BINK_SRC_COLORS], c)) < 0) + return ret; + if ((ret = read_patterns(c->avctx, gb, &c->bundle[BINK_SRC_PATTERN])) < 0) + return ret; + if ((ret = read_motion_values(c->avctx, gb, &c->bundle[BINK_SRC_X_OFF])) < 0) + return ret; + if ((ret = read_motion_values(c->avctx, gb, &c->bundle[BINK_SRC_Y_OFF])) < 0) + return ret; + if ((ret = read_dcs(c->avctx, gb, &c->bundle[BINK_SRC_INTRA_DC], DC_START_BITS, 0)) < 0) + return ret; + if ((ret = read_dcs(c->avctx, gb, &c->bundle[BINK_SRC_INTER_DC], DC_START_BITS, 1)) < 0) + return ret; + if ((ret = read_runs(c->avctx, gb, &c->bundle[BINK_SRC_RUN])) < 0) + return ret; + + if (by == bh) + break; + dst = frame->data[plane_idx] + 8*by*stride; + prev = (c->last->data[plane_idx] ? c->last->data[plane_idx] + : frame->data[plane_idx]) + 8*by*stride; + for (bx = 0; bx < bw; bx++, dst += 8, prev += 8) { + blk = get_value(c, BINK_SRC_BLOCK_TYPES); + // 16x16 block type on odd line means part of the already decoded block, so skip it + if ((by & 1) && blk == SCALED_BLOCK) { + bx++; + dst += 8; + prev += 8; + continue; + } + switch (blk) { + case SKIP_BLOCK: + c->hdsp.put_pixels_tab[1][0](dst, prev, stride, 8); + break; + case SCALED_BLOCK: + blk = get_value(c, BINK_SRC_SUB_BLOCK_TYPES); + switch (blk) { + case RUN_BLOCK: + scan = bink_patterns[get_bits(gb, 4)]; + i = 0; + do { + int run = get_value(c, BINK_SRC_RUN) + 1; + + i += run; + if (i > 64) { + av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + v = get_value(c, BINK_SRC_COLORS); + for (j = 0; j < run; j++) + ublock[*scan++] = v; + } else { + for (j = 0; j < run; j++) + ublock[*scan++] = get_value(c, BINK_SRC_COLORS); + } + } while (i < 63); + if (i == 63) + ublock[*scan++] = get_value(c, BINK_SRC_COLORS); + break; + case INTRA_BLOCK: + memset(dctblock, 0, sizeof(*dctblock) * 64); + dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); + read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1); + c->bdsp.idct_put(ublock, 8, dctblock); + break; + case FILL_BLOCK: + v = get_value(c, BINK_SRC_COLORS); + c->dsp.fill_block_tab[0](dst, v, stride, 16); + break; + case PATTERN_BLOCK: + for (i = 0; i < 2; i++) + col[i] = get_value(c, BINK_SRC_COLORS); + for (j = 0; j < 8; j++) { + v = get_value(c, BINK_SRC_PATTERN); + for (i = 0; i < 8; i++, v >>= 1) + ublock[i + j*8] = col[v & 1]; + } + break; + case RAW_BLOCK: + for (j = 0; j < 8; j++) + for (i = 0; i < 8; i++) + ublock[i + j*8] = get_value(c, BINK_SRC_COLORS); + break; + default: + av_log(c->avctx, AV_LOG_ERROR, "Incorrect 16x16 block type %d\n", blk); + return AVERROR_INVALIDDATA; + } + if (blk != FILL_BLOCK) + c->bdsp.scale_block(ublock, dst, stride); + bx++; + dst += 8; + prev += 8; + break; + case MOTION_BLOCK: + xoff = get_value(c, BINK_SRC_X_OFF); + yoff = get_value(c, BINK_SRC_Y_OFF); + ref = prev + xoff + yoff * stride; + if (ref < ref_start || ref > ref_end) { + av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", + bx*8 + xoff, by*8 + yoff); + return AVERROR_INVALIDDATA; + } + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + break; + case RUN_BLOCK: + scan = bink_patterns[get_bits(gb, 4)]; + i = 0; + do { + int run = get_value(c, BINK_SRC_RUN) + 1; + + i += run; + if (i > 64) { + av_log(c->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + v = get_value(c, BINK_SRC_COLORS); + for (j = 0; j < run; j++) + dst[coordmap[*scan++]] = v; + } else { + for (j = 0; j < run; j++) + dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS); + } + } while (i < 63); + if (i == 63) + dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS); + break; + case RESIDUE_BLOCK: + xoff = get_value(c, BINK_SRC_X_OFF); + yoff = get_value(c, BINK_SRC_Y_OFF); + ref = prev + xoff + yoff * stride; + if (ref < ref_start || ref > ref_end) { + av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", + bx*8 + xoff, by*8 + yoff); + return AVERROR_INVALIDDATA; + } + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + c->dsp.clear_block(block); + v = get_bits(gb, 7); + read_residue(gb, block, v); + c->dsp.add_pixels8(dst, block, stride); + break; + case INTRA_BLOCK: + memset(dctblock, 0, sizeof(*dctblock) * 64); + dctblock[0] = get_value(c, BINK_SRC_INTRA_DC); + read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1); + c->bdsp.idct_put(dst, stride, dctblock); + break; + case FILL_BLOCK: + v = get_value(c, BINK_SRC_COLORS); + c->dsp.fill_block_tab[1](dst, v, stride, 8); + break; + case INTER_BLOCK: + xoff = get_value(c, BINK_SRC_X_OFF); + yoff = get_value(c, BINK_SRC_Y_OFF); + ref = prev + xoff + yoff * stride; + if (ref < ref_start || ref > ref_end) { + av_log(c->avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n", + bx*8 + xoff, by*8 + yoff); + return -1; + } + c->hdsp.put_pixels_tab[1][0](dst, ref, stride, 8); + memset(dctblock, 0, sizeof(*dctblock) * 64); + dctblock[0] = get_value(c, BINK_SRC_INTER_DC); + read_dct_coeffs(gb, dctblock, bink_scan, bink_inter_quant, -1); + c->bdsp.idct_add(dst, stride, dctblock); + break; + case PATTERN_BLOCK: + for (i = 0; i < 2; i++) + col[i] = get_value(c, BINK_SRC_COLORS); + for (i = 0; i < 8; i++) { + v = get_value(c, BINK_SRC_PATTERN); + for (j = 0; j < 8; j++, v >>= 1) + dst[i*stride + j] = col[v & 1]; + } + break; + case RAW_BLOCK: + for (i = 0; i < 8; i++) + memcpy(dst + i*stride, c->bundle[BINK_SRC_COLORS].cur_ptr + i*8, 8); + c->bundle[BINK_SRC_COLORS].cur_ptr += 64; + break; + default: + av_log(c->avctx, AV_LOG_ERROR, "Unknown block type %d\n", blk); + return AVERROR_INVALIDDATA; + } + } + } + if (get_bits_count(gb) & 0x1F) //next plane data starts at 32-bit boundary + skip_bits_long(gb, 32 - (get_bits_count(gb) & 0x1F)); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) +{ + BinkContext * const c = avctx->priv_data; + AVFrame *frame = data; + GetBitContext gb; + int plane, plane_idx, ret; + int bits_count = pkt->size << 3; + + if (c->version > 'b') { + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + } else { + if ((ret = ff_reget_buffer(avctx, c->last)) < 0) + return ret; + if ((ret = av_frame_ref(frame, c->last)) < 0) + return ret; + } + + init_get_bits(&gb, pkt->data, bits_count); + if (c->has_alpha) { + if (c->version >= 'i') + skip_bits_long(&gb, 32); + if ((ret = bink_decode_plane(c, frame, &gb, 3, 0)) < 0) + return ret; + } + if (c->version >= 'i') + skip_bits_long(&gb, 32); + + for (plane = 0; plane < 3; plane++) { + plane_idx = (!plane || !c->swap_planes) ? plane : (plane ^ 3); + + if (c->version > 'b') { + if ((ret = bink_decode_plane(c, frame, &gb, plane_idx, !!plane)) < 0) + return ret; + } else { + if ((ret = binkb_decode_plane(c, frame, &gb, plane_idx, + !avctx->frame_number, !!plane)) < 0) + return ret; + } + if (get_bits_count(&gb) >= bits_count) + break; + } + emms_c(); + + if (c->version > 'b') { + av_frame_unref(c->last); + if ((ret = av_frame_ref(c->last, frame)) < 0) + return ret; + } + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return pkt->size; +} + +/** + * Caclulate quantization tables for version b + */ +static av_cold void binkb_calc_quant(void) +{ + uint8_t inv_bink_scan[64]; + static const int s[64]={ + 1073741824,1489322693,1402911301,1262586814,1073741824, 843633538, 581104888, 296244703, + 1489322693,2065749918,1945893874,1751258219,1489322693,1170153332, 806015634, 410903207, + 1402911301,1945893874,1832991949,1649649171,1402911301,1102260336, 759250125, 387062357, + 1262586814,1751258219,1649649171,1484645031,1262586814, 992008094, 683307060, 348346918, + 1073741824,1489322693,1402911301,1262586814,1073741824, 843633538, 581104888, 296244703, + 843633538,1170153332,1102260336, 992008094, 843633538, 662838617, 456571181, 232757969, + 581104888, 806015634, 759250125, 683307060, 581104888, 456571181, 314491699, 160326478, + 296244703, 410903207, 387062357, 348346918, 296244703, 232757969, 160326478, 81733730, + }; + int i, j; +#define C (1LL<<30) + for (i = 0; i < 64; i++) + inv_bink_scan[bink_scan[i]] = i; + + for (j = 0; j < 16; j++) { + for (i = 0; i < 64; i++) { + int k = inv_bink_scan[i]; + binkb_intra_quant[j][k] = binkb_intra_seed[i] * (int64_t)s[i] * + binkb_num[j]/(binkb_den[j] * (C>>12)); + binkb_inter_quant[j][k] = binkb_inter_seed[i] * (int64_t)s[i] * + binkb_num[j]/(binkb_den[j] * (C>>12)); + } + } +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + BinkContext * const c = avctx->priv_data; + static VLC_TYPE table[16 * 128][2]; + static int binkb_initialised = 0; + int i, ret; + int flags; + + c->version = avctx->codec_tag >> 24; + if (avctx->extradata_size < 4) { + av_log(avctx, AV_LOG_ERROR, "Extradata missing or too short\n"); + return AVERROR_INVALIDDATA; + } + flags = AV_RL32(avctx->extradata); + c->has_alpha = flags & BINK_FLAG_ALPHA; + c->swap_planes = c->version >= 'h'; + if (!bink_trees[15].table) { + for (i = 0; i < 16; i++) { + const int maxbits = bink_tree_lens[i][15]; + bink_trees[i].table = table + i*128; + bink_trees[i].table_allocated = 1 << maxbits; + init_vlc(&bink_trees[i], maxbits, 16, + bink_tree_lens[i], 1, 1, + bink_tree_bits[i], 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + } + } + c->avctx = avctx; + + c->last = av_frame_alloc(); + if (!c->last) + return AVERROR(ENOMEM); + + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) + return ret; + + avctx->pix_fmt = c->has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; + + ff_dsputil_init(&c->dsp, avctx); + ff_hpeldsp_init(&c->hdsp, avctx->flags); + ff_binkdsp_init(&c->bdsp); + + if ((ret = init_bundles(c)) < 0) { + free_bundles(c); + return ret; + } + + if (c->version == 'b') { + if (!binkb_initialised) { + binkb_calc_quant(); + binkb_initialised = 1; + } + } + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + BinkContext * const c = avctx->priv_data; + + av_frame_free(&c->last); + + free_bundles(c); + return 0; +} + +AVCodec ff_bink_decoder = { + .name = "binkvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BINKVIDEO, + .priv_data_size = sizeof(BinkContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Bink video"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/binkaudio.c b/ffmpeg/libavcodec/binkaudio.c new file mode 100644 index 0000000..ef5569a --- /dev/null +++ b/ffmpeg/libavcodec/binkaudio.c @@ -0,0 +1,359 @@ +/* + * Bink Audio decoder + * Copyright (c) 2007-2011 Peter Ross (pross@xvid.org) + * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) + * + * 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 + */ + +/** + * @file + * Bink Audio decoder + * + * Technical details here: + * http://wiki.multimedia.cx/index.php?title=Bink_Audio + */ + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "dct.h" +#include "rdft.h" +#include "fmtconvert.h" +#include "internal.h" +#include "libavutil/intfloat.h" + +extern const uint16_t ff_wma_critical_freqs[25]; + +static float quant_table[96]; + +#define MAX_CHANNELS 2 +#define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11) + +typedef struct { + GetBitContext gb; + int version_b; ///< Bink version 'b' + int first; + int channels; + int frame_len; ///< transform size (samples) + int overlap_len; ///< overlap size (samples) + int block_size; + int num_bands; + unsigned int *bands; + float root; + DECLARE_ALIGNED(32, FFTSample, coeffs)[BINK_BLOCK_MAX_SIZE]; + float previous[MAX_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block + uint8_t *packet_buffer; + union { + RDFTContext rdft; + DCTContext dct; + } trans; +} BinkAudioContext; + + +static av_cold int decode_init(AVCodecContext *avctx) +{ + BinkAudioContext *s = avctx->priv_data; + int sample_rate = avctx->sample_rate; + int sample_rate_half; + int i; + int frame_len_bits; + + /* determine frame length */ + if (avctx->sample_rate < 22050) { + frame_len_bits = 9; + } else if (avctx->sample_rate < 44100) { + frame_len_bits = 10; + } else { + frame_len_bits = 11; + } + + if (avctx->channels < 1 || avctx->channels > MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", avctx->channels); + return AVERROR_INVALIDDATA; + } + avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + + s->version_b = avctx->extradata_size >= 4 && avctx->extradata[3] == 'b'; + + if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) { + // audio is already interleaved for the RDFT format variant + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + sample_rate *= avctx->channels; + s->channels = 1; + if (!s->version_b) + frame_len_bits += av_log2(avctx->channels); + } else { + s->channels = avctx->channels; + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + } + + s->frame_len = 1 << frame_len_bits; + s->overlap_len = s->frame_len / 16; + s->block_size = (s->frame_len - s->overlap_len) * s->channels; + sample_rate_half = (sample_rate + 1) / 2; + if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) + s->root = 2.0 / (sqrt(s->frame_len) * 32768.0); + else + s->root = s->frame_len / (sqrt(s->frame_len) * 32768.0); + for (i = 0; i < 96; i++) { + /* constant is result of 0.066399999/log10(M_E) */ + quant_table[i] = expf(i * 0.15289164787221953823f) * s->root; + } + + /* calculate number of bands */ + for (s->num_bands = 1; s->num_bands < 25; s->num_bands++) + if (sample_rate_half <= ff_wma_critical_freqs[s->num_bands - 1]) + break; + + s->bands = av_malloc((s->num_bands + 1) * sizeof(*s->bands)); + if (!s->bands) + return AVERROR(ENOMEM); + + /* populate bands data */ + s->bands[0] = 2; + for (i = 1; i < s->num_bands; i++) + s->bands[i] = (ff_wma_critical_freqs[i - 1] * s->frame_len / sample_rate_half) & ~1; + s->bands[s->num_bands] = s->frame_len; + + s->first = 1; + + if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) + ff_rdft_init(&s->trans.rdft, frame_len_bits, DFT_C2R); + else if (CONFIG_BINKAUDIO_DCT_DECODER) + ff_dct_init(&s->trans.dct, frame_len_bits, DCT_III); + else + return -1; + + return 0; +} + +static float get_float(GetBitContext *gb) +{ + int power = get_bits(gb, 5); + float f = ldexpf(get_bits_long(gb, 23), power - 23); + if (get_bits1(gb)) + f = -f; + return f; +} + +static const uint8_t rle_length_tab[16] = { + 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 +}; + +/** + * Decode Bink Audio block + * @param[out] out Output buffer (must contain s->block_size elements) + * @return 0 on success, negative error code on failure + */ +static int decode_block(BinkAudioContext *s, float **out, int use_dct) +{ + int ch, i, j, k; + float q, quant[25]; + int width, coeff; + GetBitContext *gb = &s->gb; + + if (use_dct) + skip_bits(gb, 2); + + for (ch = 0; ch < s->channels; ch++) { + FFTSample *coeffs = out[ch]; + + if (s->version_b) { + if (get_bits_left(gb) < 64) + return AVERROR_INVALIDDATA; + coeffs[0] = av_int2float(get_bits_long(gb, 32)) * s->root; + coeffs[1] = av_int2float(get_bits_long(gb, 32)) * s->root; + } else { + if (get_bits_left(gb) < 58) + return AVERROR_INVALIDDATA; + coeffs[0] = get_float(gb) * s->root; + coeffs[1] = get_float(gb) * s->root; + } + + if (get_bits_left(gb) < s->num_bands * 8) + return AVERROR_INVALIDDATA; + for (i = 0; i < s->num_bands; i++) { + int value = get_bits(gb, 8); + quant[i] = quant_table[FFMIN(value, 95)]; + } + + k = 0; + q = quant[0]; + + // parse coefficients + i = 2; + while (i < s->frame_len) { + if (s->version_b) { + j = i + 16; + } else { + int v = get_bits1(gb); + if (v) { + v = get_bits(gb, 4); + j = i + rle_length_tab[v] * 8; + } else { + j = i + 8; + } + } + + j = FFMIN(j, s->frame_len); + + width = get_bits(gb, 4); + if (width == 0) { + memset(coeffs + i, 0, (j - i) * sizeof(*coeffs)); + i = j; + while (s->bands[k] < i) + q = quant[k++]; + } else { + while (i < j) { + if (s->bands[k] == i) + q = quant[k++]; + coeff = get_bits(gb, width); + if (coeff) { + int v; + v = get_bits1(gb); + if (v) + coeffs[i] = -q * coeff; + else + coeffs[i] = q * coeff; + } else { + coeffs[i] = 0.0f; + } + i++; + } + } + } + + if (CONFIG_BINKAUDIO_DCT_DECODER && use_dct) { + coeffs[0] /= 0.5; + s->trans.dct.dct_calc(&s->trans.dct, coeffs); + } + else if (CONFIG_BINKAUDIO_RDFT_DECODER) + s->trans.rdft.rdft_calc(&s->trans.rdft, coeffs); + } + + for (ch = 0; ch < s->channels; ch++) { + int j; + int count = s->overlap_len * s->channels; + if (!s->first) { + j = ch; + for (i = 0; i < s->overlap_len; i++, j += s->channels) + out[ch][i] = (s->previous[ch][i] * (count - j) + + out[ch][i] * j) / count; + } + memcpy(s->previous[ch], &out[ch][s->frame_len - s->overlap_len], + s->overlap_len * sizeof(*s->previous[ch])); + } + + s->first = 0; + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + BinkAudioContext * s = avctx->priv_data; + av_freep(&s->bands); + av_freep(&s->packet_buffer); + if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) + ff_rdft_end(&s->trans.rdft); + else if (CONFIG_BINKAUDIO_DCT_DECODER) + ff_dct_end(&s->trans.dct); + + return 0; +} + +static void get_bits_align32(GetBitContext *s) +{ + int n = (-get_bits_count(s)) & 31; + if (n) skip_bits(s, n); +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + BinkAudioContext *s = avctx->priv_data; + AVFrame *frame = data; + GetBitContext *gb = &s->gb; + int ret, consumed = 0; + + if (!get_bits_left(gb)) { + uint8_t *buf; + /* handle end-of-stream */ + if (!avpkt->size) { + *got_frame_ptr = 0; + return 0; + } + if (avpkt->size < 4) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + buf = av_realloc(s->packet_buffer, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!buf) + return AVERROR(ENOMEM); + s->packet_buffer = buf; + memcpy(s->packet_buffer, avpkt->data, avpkt->size); + init_get_bits(gb, s->packet_buffer, avpkt->size * 8); + consumed = avpkt->size; + + /* skip reported size */ + skip_bits_long(gb, 32); + } + + /* get output buffer */ + frame->nb_samples = s->frame_len; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (decode_block(s, (float **)frame->extended_data, + avctx->codec->id == AV_CODEC_ID_BINKAUDIO_DCT)) { + av_log(avctx, AV_LOG_ERROR, "Incomplete packet\n"); + return AVERROR_INVALIDDATA; + } + get_bits_align32(gb); + + frame->nb_samples = s->block_size / avctx->channels; + *got_frame_ptr = 1; + + return consumed; +} + +AVCodec ff_binkaudio_rdft_decoder = { + .name = "binkaudio_rdft", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_BINKAUDIO_RDFT, + .priv_data_size = sizeof(BinkAudioContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)") +}; + +AVCodec ff_binkaudio_dct_decoder = { + .name = "binkaudio_dct", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_BINKAUDIO_DCT, + .priv_data_size = sizeof(BinkAudioContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)") +}; diff --git a/ffmpeg/libavcodec/binkdata.h b/ffmpeg/libavcodec/binkdata.h new file mode 100644 index 0000000..b9dc1f2 --- /dev/null +++ b/ffmpeg/libavcodec/binkdata.h @@ -0,0 +1,655 @@ +/* + * Bink video decoder + * Copyright (C) 2009 Kostya Shishkov + * + * 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 + */ + +#ifndef AVCODEC_BINKDATA_H +#define AVCODEC_BINKDATA_H + +#include + +/** Bink DCT and residue 8x8 block scan order */ +static const uint8_t bink_scan[64] = { + 0, 1, 8, 9, 2, 3, 10, 11, + 4, 5, 12, 13, 6, 7, 14, 15, + 20, 21, 28, 29, 22, 23, 30, 31, + 16, 17, 24, 25, 32, 33, 40, 41, + 34, 35, 42, 43, 48, 49, 56, 57, + 50, 51, 58, 59, 18, 19, 26, 27, + 36, 37, 44, 45, 38, 39, 46, 47, + 52, 53, 60, 61, 54, 55, 62, 63 +}; + +static const uint8_t bink_tree_bits[16][16] = { + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + }, + { + 0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, + 0x0F, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, + }, + { + 0x00, 0x02, 0x01, 0x09, 0x05, 0x15, 0x0D, 0x1D, + 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F, + }, + { + 0x00, 0x02, 0x06, 0x01, 0x09, 0x05, 0x0D, 0x1D, + 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F, + }, + { + 0x00, 0x04, 0x02, 0x06, 0x01, 0x09, 0x05, 0x0D, + 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F, + }, + { + 0x00, 0x04, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, + 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x17, 0x0F, 0x1F, + }, + { + 0x00, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, + 0x0D, 0x03, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F, + }, + { + 0x00, 0x01, 0x05, 0x03, 0x13, 0x0B, 0x1B, 0x3B, + 0x07, 0x27, 0x17, 0x37, 0x0F, 0x2F, 0x1F, 0x3F, + }, + { + 0x00, 0x01, 0x03, 0x13, 0x0B, 0x2B, 0x1B, 0x3B, + 0x07, 0x27, 0x17, 0x37, 0x0F, 0x2F, 0x1F, 0x3F, + }, + { + 0x00, 0x01, 0x05, 0x0D, 0x03, 0x13, 0x0B, 0x1B, + 0x07, 0x27, 0x17, 0x37, 0x0F, 0x2F, 0x1F, 0x3F, + }, + { + 0x00, 0x02, 0x01, 0x05, 0x0D, 0x03, 0x13, 0x0B, + 0x1B, 0x07, 0x17, 0x37, 0x0F, 0x2F, 0x1F, 0x3F, + }, + { + 0x00, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x13, 0x0B, + 0x1B, 0x07, 0x17, 0x37, 0x0F, 0x2F, 0x1F, 0x3F, + }, + { + 0x00, 0x02, 0x01, 0x03, 0x13, 0x0B, 0x1B, 0x3B, + 0x07, 0x27, 0x17, 0x37, 0x0F, 0x2F, 0x1F, 0x3F, + }, + { + 0x00, 0x01, 0x05, 0x03, 0x07, 0x27, 0x17, 0x37, + 0x0F, 0x4F, 0x2F, 0x6F, 0x1F, 0x5F, 0x3F, 0x7F, + }, + { + 0x00, 0x01, 0x05, 0x03, 0x07, 0x17, 0x37, 0x77, + 0x0F, 0x4F, 0x2F, 0x6F, 0x1F, 0x5F, 0x3F, 0x7F, + }, + { + 0x00, 0x02, 0x01, 0x05, 0x03, 0x07, 0x27, 0x17, + 0x37, 0x0F, 0x2F, 0x6F, 0x1F, 0x5F, 0x3F, 0x7F, + }, +}; + +static const uint8_t bink_tree_lens[16][16] = { + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, + { 1, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, + { 2, 2, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, + { 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, + { 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5 }, + { 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 }, + { 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5 }, + { 1, 3, 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 1, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 1, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 2, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 }, + { 1, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 }, + { 2, 2, 2, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 1, 3, 3, 3, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 }, + { 1, 3, 3, 3, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }, + { 2, 2, 3, 3, 3, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7 }, +}; + +static const uint8_t bink_patterns[16][64] = { + { + 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, + 0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, + 0x02, 0x0A, 0x12, 0x1A, 0x22, 0x2A, 0x32, 0x3A, + 0x3B, 0x33, 0x2B, 0x23, 0x1B, 0x13, 0x0B, 0x03, + 0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x34, 0x3C, + 0x3D, 0x35, 0x2D, 0x25, 0x1D, 0x15, 0x0D, 0x05, + 0x06, 0x0E, 0x16, 0x1E, 0x26, 0x2E, 0x36, 0x3E, + 0x3F, 0x37, 0x2F, 0x27, 0x1F, 0x17, 0x0F, 0x07, + }, + { + 0x3B, 0x3A, 0x39, 0x38, 0x30, 0x31, 0x32, 0x33, + 0x2B, 0x2A, 0x29, 0x28, 0x20, 0x21, 0x22, 0x23, + 0x1B, 0x1A, 0x19, 0x18, 0x10, 0x11, 0x12, 0x13, + 0x0B, 0x0A, 0x09, 0x08, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x0F, 0x0E, 0x0D, 0x0C, + 0x14, 0x15, 0x16, 0x17, 0x1F, 0x1E, 0x1D, 0x1C, + 0x24, 0x25, 0x26, 0x27, 0x2F, 0x2E, 0x2D, 0x2C, + 0x34, 0x35, 0x36, 0x37, 0x3F, 0x3E, 0x3D, 0x3C, + }, + { + 0x19, 0x11, 0x12, 0x1A, 0x1B, 0x13, 0x0B, 0x03, + 0x02, 0x0A, 0x09, 0x01, 0x00, 0x08, 0x10, 0x18, + 0x20, 0x28, 0x30, 0x38, 0x39, 0x31, 0x29, 0x2A, + 0x32, 0x3A, 0x3B, 0x33, 0x2B, 0x23, 0x22, 0x21, + 0x1D, 0x15, 0x16, 0x1E, 0x1F, 0x17, 0x0F, 0x07, + 0x06, 0x0E, 0x0D, 0x05, 0x04, 0x0C, 0x14, 0x1C, + 0x24, 0x2C, 0x34, 0x3C, 0x3D, 0x35, 0x2D, 0x2E, + 0x36, 0x3E, 0x3F, 0x37, 0x2F, 0x27, 0x26, 0x25, + }, + { + 0x03, 0x0B, 0x02, 0x0A, 0x01, 0x09, 0x00, 0x08, + 0x10, 0x18, 0x11, 0x19, 0x12, 0x1A, 0x13, 0x1B, + 0x23, 0x2B, 0x22, 0x2A, 0x21, 0x29, 0x20, 0x28, + 0x30, 0x38, 0x31, 0x39, 0x32, 0x3A, 0x33, 0x3B, + 0x3C, 0x34, 0x3D, 0x35, 0x3E, 0x36, 0x3F, 0x37, + 0x2F, 0x27, 0x2E, 0x26, 0x2D, 0x25, 0x2C, 0x24, + 0x1C, 0x14, 0x1D, 0x15, 0x1E, 0x16, 0x1F, 0x17, + 0x0F, 0x07, 0x0E, 0x06, 0x0D, 0x05, 0x0C, 0x04, + }, + { + 0x18, 0x19, 0x10, 0x11, 0x08, 0x09, 0x00, 0x01, + 0x02, 0x03, 0x0A, 0x0B, 0x12, 0x13, 0x1A, 0x1B, + 0x1C, 0x1D, 0x14, 0x15, 0x0C, 0x0D, 0x04, 0x05, + 0x06, 0x07, 0x0E, 0x0F, 0x16, 0x17, 0x1E, 0x1F, + 0x27, 0x26, 0x2F, 0x2E, 0x37, 0x36, 0x3F, 0x3E, + 0x3D, 0x3C, 0x35, 0x34, 0x2D, 0x2C, 0x25, 0x24, + 0x23, 0x22, 0x2B, 0x2A, 0x33, 0x32, 0x3B, 0x3A, + 0x39, 0x38, 0x31, 0x30, 0x29, 0x28, 0x21, 0x20, + }, + { + 0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, + 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A, 0x1B, + 0x20, 0x21, 0x22, 0x23, 0x28, 0x29, 0x2A, 0x2B, + 0x30, 0x31, 0x32, 0x33, 0x38, 0x39, 0x3A, 0x3B, + 0x04, 0x05, 0x06, 0x07, 0x0C, 0x0D, 0x0E, 0x0F, + 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F, + 0x24, 0x25, 0x26, 0x27, 0x2C, 0x2D, 0x2E, 0x2F, + 0x34, 0x35, 0x36, 0x37, 0x3C, 0x3D, 0x3E, 0x3F, + }, + { + 0x06, 0x07, 0x0F, 0x0E, 0x0D, 0x05, 0x0C, 0x04, + 0x03, 0x0B, 0x02, 0x0A, 0x09, 0x01, 0x00, 0x08, + 0x10, 0x18, 0x11, 0x19, 0x12, 0x1A, 0x13, 0x1B, + 0x14, 0x1C, 0x15, 0x1D, 0x16, 0x1E, 0x17, 0x1F, + 0x27, 0x2F, 0x26, 0x2E, 0x25, 0x2D, 0x24, 0x2C, + 0x23, 0x2B, 0x22, 0x2A, 0x21, 0x29, 0x20, 0x28, + 0x31, 0x30, 0x38, 0x39, 0x3A, 0x32, 0x3B, 0x33, + 0x3C, 0x34, 0x3D, 0x35, 0x36, 0x37, 0x3F, 0x3E, + }, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, + }, + { + 0x00, 0x08, 0x09, 0x01, 0x02, 0x03, 0x0B, 0x0A, + 0x12, 0x13, 0x1B, 0x1A, 0x19, 0x11, 0x10, 0x18, + 0x20, 0x28, 0x29, 0x21, 0x22, 0x23, 0x2B, 0x2A, + 0x32, 0x31, 0x30, 0x38, 0x39, 0x3A, 0x3B, 0x33, + 0x34, 0x3C, 0x3D, 0x3E, 0x3F, 0x37, 0x36, 0x35, + 0x2D, 0x2C, 0x24, 0x25, 0x26, 0x2E, 0x2F, 0x27, + 0x1F, 0x17, 0x16, 0x1E, 0x1D, 0x1C, 0x14, 0x15, + 0x0D, 0x0C, 0x04, 0x05, 0x06, 0x0E, 0x0F, 0x07, + }, + { + 0x18, 0x19, 0x10, 0x11, 0x08, 0x09, 0x00, 0x01, + 0x02, 0x03, 0x0A, 0x0B, 0x12, 0x13, 0x1A, 0x1B, + 0x1C, 0x1D, 0x14, 0x15, 0x0C, 0x0D, 0x04, 0x05, + 0x06, 0x07, 0x0E, 0x0F, 0x16, 0x17, 0x1E, 0x1F, + 0x26, 0x27, 0x2E, 0x2F, 0x36, 0x37, 0x3E, 0x3F, + 0x3C, 0x3D, 0x34, 0x35, 0x2C, 0x2D, 0x24, 0x25, + 0x22, 0x23, 0x2A, 0x2B, 0x32, 0x33, 0x3A, 0x3B, + 0x38, 0x39, 0x30, 0x31, 0x28, 0x29, 0x20, 0x21, + }, + { + 0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B, + 0x13, 0x1B, 0x12, 0x1A, 0x11, 0x19, 0x10, 0x18, + 0x20, 0x28, 0x21, 0x29, 0x22, 0x2A, 0x23, 0x2B, + 0x33, 0x3B, 0x32, 0x3A, 0x31, 0x39, 0x30, 0x38, + 0x3C, 0x34, 0x3D, 0x35, 0x3E, 0x36, 0x3F, 0x37, + 0x2F, 0x27, 0x2E, 0x26, 0x2D, 0x25, 0x2C, 0x24, + 0x1F, 0x17, 0x1E, 0x16, 0x1D, 0x15, 0x1C, 0x14, + 0x0C, 0x04, 0x0D, 0x05, 0x0E, 0x06, 0x0F, 0x07, + }, + { + 0x00, 0x08, 0x10, 0x18, 0x19, 0x1A, 0x1B, 0x13, + 0x0B, 0x03, 0x02, 0x01, 0x09, 0x11, 0x12, 0x0A, + 0x04, 0x0C, 0x14, 0x1C, 0x1D, 0x1E, 0x1F, 0x17, + 0x0F, 0x07, 0x06, 0x05, 0x0D, 0x15, 0x16, 0x0E, + 0x24, 0x2C, 0x34, 0x3C, 0x3D, 0x3E, 0x3F, 0x37, + 0x2F, 0x27, 0x26, 0x25, 0x2D, 0x35, 0x36, 0x2E, + 0x20, 0x28, 0x30, 0x38, 0x39, 0x3A, 0x3B, 0x33, + 0x2B, 0x23, 0x22, 0x21, 0x29, 0x31, 0x32, 0x2A, + }, + { + 0x00, 0x08, 0x09, 0x01, 0x02, 0x03, 0x0B, 0x0A, + 0x13, 0x1B, 0x1A, 0x12, 0x11, 0x10, 0x18, 0x19, + 0x21, 0x20, 0x28, 0x29, 0x2A, 0x22, 0x23, 0x2B, + 0x33, 0x3B, 0x3A, 0x32, 0x31, 0x39, 0x38, 0x30, + 0x34, 0x3C, 0x3D, 0x35, 0x36, 0x3E, 0x3F, 0x37, + 0x2F, 0x27, 0x26, 0x2E, 0x2D, 0x2C, 0x24, 0x25, + 0x1D, 0x1C, 0x14, 0x15, 0x16, 0x1E, 0x1F, 0x17, + 0x0E, 0x0F, 0x07, 0x06, 0x05, 0x0D, 0x0C, 0x04, + }, + { + 0x18, 0x10, 0x08, 0x00, 0x01, 0x02, 0x03, 0x0B, + 0x13, 0x1B, 0x1A, 0x19, 0x11, 0x0A, 0x09, 0x12, + 0x1C, 0x14, 0x0C, 0x04, 0x05, 0x06, 0x07, 0x0F, + 0x17, 0x1F, 0x1E, 0x1D, 0x15, 0x0E, 0x0D, 0x16, + 0x3C, 0x34, 0x2C, 0x24, 0x25, 0x26, 0x27, 0x2F, + 0x37, 0x3F, 0x3E, 0x3D, 0x35, 0x2E, 0x2D, 0x36, + 0x38, 0x30, 0x28, 0x20, 0x21, 0x22, 0x23, 0x2B, + 0x33, 0x3B, 0x3A, 0x39, 0x31, 0x2A, 0x29, 0x32, + }, + { + 0x00, 0x08, 0x09, 0x01, 0x02, 0x0A, 0x12, 0x11, + 0x10, 0x18, 0x19, 0x1A, 0x1B, 0x13, 0x0B, 0x03, + 0x07, 0x06, 0x0E, 0x0F, 0x17, 0x16, 0x15, 0x0D, + 0x05, 0x04, 0x0C, 0x14, 0x1C, 0x1D, 0x1E, 0x1F, + 0x3F, 0x3E, 0x36, 0x37, 0x2F, 0x2E, 0x2D, 0x35, + 0x3D, 0x3C, 0x34, 0x2C, 0x24, 0x25, 0x26, 0x27, + 0x38, 0x30, 0x31, 0x39, 0x3A, 0x32, 0x2A, 0x29, + 0x28, 0x20, 0x21, 0x22, 0x23, 0x2B, 0x33, 0x3B, + }, + { + 0x00, 0x01, 0x08, 0x09, 0x10, 0x11, 0x18, 0x19, + 0x20, 0x21, 0x28, 0x29, 0x30, 0x31, 0x38, 0x39, + 0x3A, 0x3B, 0x32, 0x33, 0x2A, 0x2B, 0x22, 0x23, + 0x1A, 0x1B, 0x12, 0x13, 0x0A, 0x0B, 0x02, 0x03, + 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D, + 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x3C, 0x3D, + 0x3E, 0x3F, 0x36, 0x37, 0x2E, 0x2F, 0x26, 0x27, + 0x1E, 0x1F, 0x16, 0x17, 0x0E, 0x0F, 0x06, 0x07, + } +}; + +static const int32_t bink_intra_quant[16][64] = { +{ + 0x010000, 0x016315, 0x01E83D, 0x02A535, 0x014E7B, 0x016577, 0x02F1E6, 0x02724C, + 0x010000, 0x00EEDA, 0x024102, 0x017F9B, 0x00BE80, 0x00611E, 0x01083C, 0x00A552, + 0x021F88, 0x01DC53, 0x027FAD, 0x01F697, 0x014819, 0x00A743, 0x015A31, 0x009688, + 0x02346F, 0x030EE5, 0x01FBFA, 0x02C096, 0x01D000, 0x028396, 0x019247, 0x01F9AA, + 0x02346F, 0x01FBFA, 0x01DC53, 0x0231B8, 0x012F12, 0x01E06C, 0x00CB10, 0x0119A8, + 0x01C48C, 0x019748, 0x014E86, 0x0122AF, 0x02C628, 0x027F20, 0x0297B5, 0x023F32, + 0x025000, 0x01AB6B, 0x01D122, 0x0159B3, 0x012669, 0x008D43, 0x00EE1F, 0x0075ED, + 0x01490C, 0x010288, 0x00F735, 0x00EF51, 0x00E0F1, 0x0072AD, 0x00A4D8, 0x006517, +}, +{ + 0x015555, 0x01D971, 0x028AFC, 0x0386F1, 0x01BDF9, 0x01DC9F, 0x03ED33, 0x034311, + 0x015555, 0x013E78, 0x030158, 0x01FF7A, 0x00FE00, 0x00817D, 0x01604F, 0x00DC6D, + 0x02D4B5, 0x027B19, 0x0354E7, 0x029E1F, 0x01B577, 0x00DF04, 0x01CD96, 0x00C8B6, + 0x02F095, 0x0413DC, 0x02A54E, 0x03AB73, 0x026AAB, 0x035A1E, 0x02185E, 0x02A238, + 0x02F095, 0x02A54E, 0x027B19, 0x02ECF5, 0x019418, 0x028090, 0x010EC0, 0x01778A, + 0x025B66, 0x021F0B, 0x01BE09, 0x018394, 0x03B2E0, 0x03542A, 0x0374F1, 0x02FEEE, + 0x031555, 0x0239E4, 0x026C2D, 0x01CCEE, 0x01888C, 0x00BC59, 0x013D7E, 0x009D3C, + 0x01B6BB, 0x0158B5, 0x01499C, 0x013F17, 0x012BEC, 0x0098E6, 0x00DBCB, 0x0086C9, +}, +{ + 0x01AAAB, 0x024FCE, 0x032DBB, 0x0468AD, 0x022D78, 0x0253C7, 0x04E87F, 0x0413D5, + 0x01AAAB, 0x018E16, 0x03C1AE, 0x027F58, 0x013D80, 0x00A1DC, 0x01B863, 0x011388, + 0x0389E2, 0x0319DF, 0x042A21, 0x0345A7, 0x0222D4, 0x0116C5, 0x0240FC, 0x00FAE3, + 0x03ACBA, 0x0518D3, 0x034EA1, 0x04964F, 0x030555, 0x0430A5, 0x029E76, 0x034AC5, + 0x03ACBA, 0x034EA1, 0x0319DF, 0x03A833, 0x01F91E, 0x0320B4, 0x015270, 0x01D56D, + 0x02F23F, 0x02A6CE, 0x022D8B, 0x01E479, 0x049F98, 0x042935, 0x04522D, 0x03BEA9, + 0x03DAAB, 0x02C85D, 0x030738, 0x02402A, 0x01EAAF, 0x00EB6F, 0x018CDE, 0x00C48A, + 0x022469, 0x01AEE2, 0x019C02, 0x018EDD, 0x0176E7, 0x00BF20, 0x0112BE, 0x00A87B, +}, +{ + 0x020000, 0x02C62A, 0x03D07A, 0x054A69, 0x029CF6, 0x02CAEF, 0x05E3CC, 0x04E499, + 0x020000, 0x01DDB4, 0x048204, 0x02FF36, 0x017D01, 0x00C23C, 0x021077, 0x014AA3, + 0x043F0F, 0x03B8A6, 0x04FF5A, 0x03ED2E, 0x029032, 0x014E86, 0x02B461, 0x012D11, + 0x0468DF, 0x061DCA, 0x03F7F5, 0x05812C, 0x03A000, 0x05072C, 0x03248D, 0x03F353, + 0x0468DF, 0x03F7F5, 0x03B8A6, 0x046370, 0x025E24, 0x03C0D8, 0x019620, 0x02334F, + 0x038919, 0x032E91, 0x029D0D, 0x02455E, 0x058C50, 0x04FE3F, 0x052F69, 0x047E65, + 0x04A000, 0x0356D6, 0x03A243, 0x02B365, 0x024CD2, 0x011A85, 0x01DC3E, 0x00EBD9, + 0x029218, 0x020510, 0x01EE69, 0x01DEA2, 0x01C1E2, 0x00E559, 0x0149B0, 0x00CA2D, +}, +{ + 0x02AAAB, 0x03B2E3, 0x0515F8, 0x070DE2, 0x037BF2, 0x03B93E, 0x07DA65, 0x068621, + 0x02AAAB, 0x027CF0, 0x0602B1, 0x03FEF3, 0x01FC01, 0x0102FA, 0x02C09F, 0x01B8DA, + 0x05A96A, 0x04F632, 0x06A9CE, 0x053C3E, 0x036AED, 0x01BE09, 0x039B2D, 0x01916B, + 0x05E129, 0x0827B8, 0x054A9C, 0x0756E5, 0x04D555, 0x06B43B, 0x0430BC, 0x05446F, + 0x05E129, 0x054A9C, 0x04F632, 0x05D9EB, 0x032830, 0x050121, 0x021D80, 0x02EF14, + 0x04B6CC, 0x043E16, 0x037C11, 0x030728, 0x0765C0, 0x06A855, 0x06E9E2, 0x05FDDB, + 0x062AAB, 0x0473C8, 0x04D85A, 0x0399DC, 0x031118, 0x0178B2, 0x027AFD, 0x013A77, + 0x036D76, 0x02B16A, 0x029337, 0x027E2E, 0x0257D8, 0x0131CC, 0x01B796, 0x010D91, +}, +{ + 0x038000, 0x04DACA, 0x06ACD5, 0x094238, 0x0492AE, 0x04E322, 0x0A4EA5, 0x08900C, + 0x038000, 0x0343FB, 0x07E388, 0x053E9F, 0x029AC1, 0x0153E8, 0x039CD0, 0x02429E, + 0x076E5B, 0x068322, 0x08BEDE, 0x06DF11, 0x047C57, 0x02496B, 0x04BBAB, 0x020EDD, + 0x07B786, 0x0AB421, 0x06F1ED, 0x09A20D, 0x065800, 0x08CC8E, 0x057FF7, 0x06E9D2, + 0x07B786, 0x06F1ED, 0x068322, 0x07AE04, 0x0424BF, 0x06917B, 0x02C6B8, 0x03D9CB, + 0x062FEB, 0x05917D, 0x0492D7, 0x03F964, 0x09B58C, 0x08BCEF, 0x0912F8, 0x07DD30, + 0x081800, 0x05D7F7, 0x065BF6, 0x04B9F1, 0x040670, 0x01EE69, 0x03416C, 0x019CBC, + 0x047FAA, 0x0388DC, 0x036138, 0x03459C, 0x03134C, 0x01915C, 0x0240F5, 0x0161CF, +}, +{ + 0x040000, 0x058C54, 0x07A0F4, 0x0A94D3, 0x0539EC, 0x0595DD, 0x0BC798, 0x09C932, + 0x040000, 0x03BB68, 0x090409, 0x05FE6D, 0x02FA01, 0x018477, 0x0420EE, 0x029547, + 0x087E1F, 0x07714C, 0x09FEB5, 0x07DA5D, 0x052064, 0x029D0D, 0x0568C3, 0x025A21, + 0x08D1BE, 0x0C3B94, 0x07EFEA, 0x0B0258, 0x074000, 0x0A0E59, 0x06491A, 0x07E6A7, + 0x08D1BE, 0x07EFEA, 0x07714C, 0x08C6E0, 0x04BC48, 0x0781B1, 0x032C3F, 0x04669F, + 0x071232, 0x065D22, 0x053A1A, 0x048ABC, 0x0B18A0, 0x09FC7F, 0x0A5ED3, 0x08FCC9, + 0x094000, 0x06ADAC, 0x074487, 0x0566CA, 0x0499A5, 0x02350B, 0x03B87B, 0x01D7B3, + 0x052430, 0x040A20, 0x03DCD3, 0x03BD45, 0x0383C5, 0x01CAB3, 0x029361, 0x01945A, +}, +{ + 0x050000, 0x06EF69, 0x098931, 0x0D3A07, 0x068867, 0x06FB55, 0x0EB97E, 0x0C3B7E, + 0x050000, 0x04AA42, 0x0B450B, 0x077E08, 0x03B881, 0x01E595, 0x05292A, 0x033A99, + 0x0A9DA7, 0x094D9F, 0x0C7E62, 0x09D0F4, 0x06687D, 0x034450, 0x06C2F4, 0x02F0AA, + 0x0B062D, 0x0F4A78, 0x09EBE4, 0x0DC2EE, 0x091000, 0x0C91EF, 0x07DB61, 0x09E050, + 0x0B062D, 0x09EBE4, 0x094D9F, 0x0AF898, 0x05EB59, 0x09621D, 0x03F74F, 0x058046, + 0x08D6BE, 0x07F46A, 0x0688A0, 0x05AD6B, 0x0DDEC8, 0x0C7B9F, 0x0CF687, 0x0B3BFB, + 0x0B9000, 0x085917, 0x0915A8, 0x06C07D, 0x05C00E, 0x02C24D, 0x04A69A, 0x024D9F, + 0x066D3C, 0x050CA7, 0x04D407, 0x04AC96, 0x0464B6, 0x023D5F, 0x033839, 0x01F971, +}, +{ + 0x060000, 0x08527E, 0x0B716E, 0x0FDF3C, 0x07D6E1, 0x0860CC, 0x11AB63, 0x0EADCB, + 0x060000, 0x05991C, 0x0D860D, 0x08FDA3, 0x047702, 0x0246B3, 0x063165, 0x03DFEA, + 0x0CBD2E, 0x0B29F1, 0x0EFE0F, 0x0BC78B, 0x07B096, 0x03EB93, 0x081D24, 0x038732, + 0x0D3A9C, 0x12595D, 0x0BE7DF, 0x108384, 0x0AE000, 0x0F1585, 0x096DA8, 0x0BD9FA, + 0x0D3A9C, 0x0BE7DF, 0x0B29F1, 0x0D2A50, 0x071A6B, 0x0B4289, 0x04C25F, 0x0699EE, + 0x0A9B4A, 0x098BB2, 0x07D727, 0x06D01A, 0x10A4F0, 0x0EFABE, 0x0F8E3C, 0x0D7B2E, + 0x0DE000, 0x0A0482, 0x0AE6CA, 0x081A2F, 0x06E677, 0x034F90, 0x0594B9, 0x02C38C, + 0x07B649, 0x060F2F, 0x05CB3C, 0x059BE7, 0x0545A7, 0x02B00C, 0x03DD11, 0x025E87, +}, +{ + 0x080000, 0x0B18A8, 0x0F41E8, 0x1529A5, 0x0A73D7, 0x0B2BBB, 0x178F2F, 0x139264, + 0x080000, 0x0776CF, 0x120812, 0x0BFCD9, 0x05F402, 0x0308EF, 0x0841DC, 0x052A8E, + 0x10FC3E, 0x0EE297, 0x13FD69, 0x0FB4B9, 0x0A40C8, 0x053A1A, 0x0AD186, 0x04B442, + 0x11A37B, 0x187727, 0x0FDFD4, 0x1604B0, 0x0E8000, 0x141CB1, 0x0C9235, 0x0FCD4D, + 0x11A37B, 0x0FDFD4, 0x0EE297, 0x118DC0, 0x09788F, 0x0F0362, 0x06587F, 0x08CD3D, + 0x0E2463, 0x0CBA43, 0x0A7434, 0x091577, 0x163140, 0x13F8FE, 0x14BDA5, 0x11F992, + 0x128000, 0x0D5B58, 0x0E890D, 0x0ACD94, 0x093349, 0x046A15, 0x0770F7, 0x03AF65, + 0x0A4861, 0x08143F, 0x07B9A6, 0x077A89, 0x070789, 0x039565, 0x0526C2, 0x0328B4, +}, +{ + 0x0C0000, 0x10A4FD, 0x16E2DB, 0x1FBE78, 0x0FADC3, 0x10C198, 0x2356C7, 0x1D5B96, + 0x0C0000, 0x0B3237, 0x1B0C1A, 0x11FB46, 0x08EE03, 0x048D66, 0x0C62CA, 0x07BFD5, + 0x197A5D, 0x1653E3, 0x1DFC1E, 0x178F16, 0x0F612C, 0x07D727, 0x103A49, 0x070E64, + 0x1A7539, 0x24B2BB, 0x17CFBD, 0x210709, 0x15C000, 0x1E2B0A, 0x12DB4F, 0x17B3F4, + 0x1A7539, 0x17CFBD, 0x1653E3, 0x1A54A0, 0x0E34D7, 0x168513, 0x0984BE, 0x0D33DC, + 0x153695, 0x131765, 0x0FAE4E, 0x0DA033, 0x2149E1, 0x1DF57D, 0x1F1C78, 0x1AF65B, + 0x1BC000, 0x140904, 0x15CD94, 0x10345E, 0x0DCCEE, 0x069F20, 0x0B2972, 0x058718, + 0x0F6C91, 0x0C1E5E, 0x0B9678, 0x0B37CE, 0x0A8B4E, 0x056018, 0x07BA22, 0x04BD0E, +}, +{ + 0x110000, 0x179466, 0x206C0C, 0x2CF87F, 0x16362A, 0x17BCED, 0x321044, 0x299714, + 0x110000, 0x0FDC79, 0x265125, 0x19794E, 0x0CA685, 0x0672FB, 0x118BF4, 0x0AFA6D, + 0x241804, 0x1FA181, 0x2A7A80, 0x21600A, 0x15C9A9, 0x0B1B77, 0x16FD3C, 0x09FF0D, + 0x257B66, 0x33FD33, 0x21BBA2, 0x2EC9F7, 0x1ED000, 0x2ABCF9, 0x1AB6B0, 0x219444, + 0x257B66, 0x21BBA2, 0x1FA181, 0x254D38, 0x142030, 0x1FE730, 0x0D7C0E, 0x12B423, + 0x1E0D52, 0x1B0BCF, 0x1636EE, 0x134D9E, 0x2F28A9, 0x2A711B, 0x2C12FF, 0x263256, + 0x275000, 0x1C621B, 0x1EE33C, 0x16F4DB, 0x138CFB, 0x09616E, 0x0FD00C, 0x07D4B7, + 0x15D9CE, 0x112B06, 0x106A80, 0x0FE464, 0x0EF004, 0x079D77, 0x0AF25B, 0x06B67F, +}, +{ + 0x160000, 0x1E83CF, 0x29F53D, 0x3A3286, 0x1CBE90, 0x1EB842, 0x40C9C2, 0x35D293, + 0x160000, 0x1486BA, 0x319630, 0x20F756, 0x105F06, 0x085891, 0x16B51E, 0x0E3506, + 0x2EB5AA, 0x28EF20, 0x36F8E1, 0x2B30FE, 0x1C3225, 0x0E5FC7, 0x1DC030, 0x0CEFB7, + 0x308193, 0x4347AC, 0x2BA786, 0x3C8CE5, 0x27E000, 0x374EE7, 0x229212, 0x2B7494, + 0x308193, 0x2BA786, 0x28EF20, 0x3045D0, 0x1A0B89, 0x29494D, 0x11735D, 0x183469, + 0x26E410, 0x230039, 0x1CBF8F, 0x18FB09, 0x3D0771, 0x36ECBA, 0x390986, 0x316E52, + 0x32E000, 0x24BB33, 0x27F8E4, 0x1DB557, 0x194D09, 0x0C23BB, 0x1476A6, 0x0A2256, + 0x1C470A, 0x1637AD, 0x153E87, 0x1490FA, 0x1354B9, 0x09DAD6, 0x0E2A94, 0x08AFF0, +}, +{ + 0x1C0000, 0x26D64D, 0x3566AA, 0x4A11C2, 0x249572, 0x27190E, 0x527525, 0x44805E, + 0x1C0000, 0x1A1FD6, 0x3F1C3E, 0x29F4F9, 0x14D607, 0x0A9F44, 0x1CE683, 0x1214F0, + 0x3B72D9, 0x341911, 0x45F6F0, 0x36F889, 0x23E2BB, 0x124B5B, 0x25DD54, 0x1076E9, + 0x3DBC30, 0x55A109, 0x378F64, 0x4D1069, 0x32C000, 0x46646C, 0x2BFFB9, 0x374E8E, + 0x3DBC30, 0x378F64, 0x341911, 0x3D7020, 0x2125F5, 0x348BD6, 0x1635BC, 0x1ECE57, + 0x317F5B, 0x2C8BEB, 0x2496B6, 0x1FCB22, 0x4DAC61, 0x45E778, 0x4897C2, 0x3EE97F, + 0x40C000, 0x2EBFB5, 0x32DFAE, 0x25CF86, 0x203380, 0x0F734B, 0x1A0B5F, 0x0CE5E2, + 0x23FD53, 0x1C46DC, 0x1B09C4, 0x1A2CE1, 0x189A60, 0x0C8AE2, 0x1207A5, 0x0B0E77, +}, +{ + 0x220000, 0x2F28CC, 0x40D818, 0x59F0FE, 0x2C6C53, 0x2F79DA, 0x642089, 0x532E29, + 0x220000, 0x1FB8F1, 0x4CA24B, 0x32F29C, 0x194D09, 0x0CE5F7, 0x2317E8, 0x15F4DB, + 0x483007, 0x3F4303, 0x54F4FF, 0x42C014, 0x2B9351, 0x1636EE, 0x2DFA79, 0x13FE1A, + 0x4AF6CC, 0x67FA67, 0x437743, 0x5D93EE, 0x3DA000, 0x5579F1, 0x356D61, 0x432888, + 0x4AF6CC, 0x437743, 0x3F4303, 0x4A9A70, 0x284060, 0x3FCE60, 0x1AF81B, 0x256845, + 0x3C1AA5, 0x36179D, 0x2C6DDD, 0x269B3C, 0x5E5152, 0x54E237, 0x5825FE, 0x4C64AD, + 0x4EA000, 0x38C437, 0x3DC678, 0x2DE9B5, 0x2719F7, 0x12C2DB, 0x1FA018, 0x0FA96E, + 0x2BB39B, 0x22560C, 0x20D500, 0x1FC8C8, 0x1DE007, 0x0F3AEE, 0x15E4B7, 0x0D6CFE, +}, +{ + 0x2C0000, 0x3D079E, 0x53EA79, 0x74650C, 0x397D20, 0x3D7083, 0x819383, 0x6BA525, + 0x2C0000, 0x290D75, 0x632C61, 0x41EEAC, 0x20BE0C, 0x10B121, 0x2D6A3B, 0x1C6A0C, + 0x5D6B54, 0x51DE40, 0x6DF1C2, 0x5661FB, 0x38644B, 0x1CBF8F, 0x3B8060, 0x19DF6D, + 0x610326, 0x868F57, 0x574F0B, 0x7919CA, 0x4FC000, 0x6E9DCE, 0x452423, 0x56E928, + 0x610326, 0x574F0B, 0x51DE40, 0x608BA0, 0x341713, 0x52929A, 0x22E6BA, 0x3068D2, + 0x4DC821, 0x460071, 0x397F1E, 0x31F611, 0x7A0EE2, 0x6DD974, 0x72130C, 0x62DCA3, + 0x65C000, 0x497665, 0x4FF1C9, 0x3B6AAE, 0x329A12, 0x184776, 0x28ED4D, 0x1444AC, + 0x388E14, 0x2C6F5A, 0x2A7D0F, 0x2921F4, 0x26A973, 0x13B5AD, 0x1C5528, 0x115FDF, +}, +}; + +static const int32_t bink_inter_quant[16][64] = { +{ + 0x010000, 0x017946, 0x01A5A9, 0x0248DC, 0x016363, 0x0152A7, 0x0243EC, 0x0209EA, + 0x012000, 0x00E248, 0x01BBDA, 0x015CBC, 0x00A486, 0x0053E0, 0x00F036, 0x008095, + 0x01B701, 0x016959, 0x01B0B9, 0x0153FD, 0x00F8E7, 0x007EE4, 0x00EA30, 0x007763, + 0x01B701, 0x0260EB, 0x019DE9, 0x023E1B, 0x017000, 0x01FE6E, 0x012DB5, 0x01A27B, + 0x01E0D1, 0x01B0B9, 0x018A33, 0x01718D, 0x00D87A, 0x014449, 0x007B9A, 0x00AB71, + 0x013178, 0x0112EA, 0x00AD08, 0x009BB9, 0x023D97, 0x020437, 0x021CCC, 0x01E6B4, + 0x018000, 0x012DB5, 0x0146D9, 0x0100CE, 0x00CFD2, 0x006E5C, 0x00B0E4, 0x005A2D, + 0x00E9CC, 0x00B7B1, 0x00846F, 0x006B85, 0x008337, 0x0042E5, 0x004A10, 0x002831, +}, +{ + 0x015555, 0x01F708, 0x023237, 0x030BD0, 0x01D9D9, 0x01C389, 0x03053B, 0x02B7E3, + 0x018000, 0x012DB5, 0x024FCE, 0x01D0FA, 0x00DB5D, 0x006FD5, 0x014048, 0x00AB71, + 0x024957, 0x01E1CC, 0x0240F7, 0x01C551, 0x014BDE, 0x00A92F, 0x013840, 0x009F2F, + 0x024957, 0x032BE4, 0x0227E1, 0x02FD7A, 0x01EAAB, 0x02A893, 0x019247, 0x022DF9, + 0x028116, 0x0240F7, 0x020D99, 0x01ECBC, 0x0120A3, 0x01B061, 0x00A4CE, 0x00E497, + 0x01974B, 0x016E8E, 0x00E6B5, 0x00CFA2, 0x02FCC9, 0x02B04A, 0x02D110, 0x0288F1, + 0x020000, 0x019247, 0x01B3CC, 0x015668, 0x011518, 0x009325, 0x00EBDA, 0x00783D, + 0x0137BB, 0x00F4ED, 0x00B093, 0x008F5C, 0x00AEF4, 0x005931, 0x0062BF, 0x003597, +}, +{ + 0x01AAAB, 0x0274CB, 0x02BEC4, 0x03CEC4, 0x02504F, 0x02346C, 0x03C689, 0x0365DC, + 0x01E000, 0x017922, 0x02E3C1, 0x024539, 0x011235, 0x008BCA, 0x01905A, 0x00D64D, + 0x02DBAD, 0x025A40, 0x02D134, 0x0236A5, 0x019ED6, 0x00D37B, 0x018650, 0x00C6FB, + 0x02DBAD, 0x03F6DD, 0x02B1D9, 0x03BCD8, 0x026555, 0x0352B8, 0x01F6D8, 0x02B977, + 0x03215C, 0x02D134, 0x029100, 0x0267EB, 0x0168CC, 0x021C7A, 0x00CE01, 0x011DBD, + 0x01FD1E, 0x01CA31, 0x012062, 0x01038A, 0x03BBFB, 0x035C5C, 0x038554, 0x032B2D, + 0x028000, 0x01F6D8, 0x0220C0, 0x01AC02, 0x015A5E, 0x00B7EF, 0x0126D1, 0x00964C, + 0x0185A9, 0x013228, 0x00DCB8, 0x00B333, 0x00DAB2, 0x006F7D, 0x007B6F, 0x0042FC, +}, +{ + 0x020000, 0x02F28D, 0x034B52, 0x0491B8, 0x02C6C5, 0x02A54E, 0x0487D8, 0x0413D5, + 0x024000, 0x01C48F, 0x0377B5, 0x02B977, 0x01490C, 0x00A7BF, 0x01E06C, 0x01012A, + 0x036E03, 0x02D2B3, 0x036172, 0x02A7FA, 0x01F1CE, 0x00FDC7, 0x01D460, 0x00EEC7, + 0x036E03, 0x04C1D6, 0x033BD1, 0x047C37, 0x02E000, 0x03FCDD, 0x025B6A, 0x0344F5, + 0x03C1A1, 0x036172, 0x031466, 0x02E31B, 0x01B0F5, 0x028892, 0x00F735, 0x0156E2, + 0x0262F1, 0x0225D5, 0x015A10, 0x013772, 0x047B2D, 0x04086E, 0x043998, 0x03CD69, + 0x030000, 0x025B6A, 0x028DB3, 0x02019B, 0x019FA3, 0x00DCB8, 0x0161C7, 0x00B45B, + 0x01D398, 0x016F63, 0x0108DD, 0x00D70A, 0x01066F, 0x0085C9, 0x00941F, 0x005062, +}, +{ + 0x02AAAB, 0x03EE11, 0x04646D, 0x0617A0, 0x03B3B2, 0x038713, 0x060A75, 0x056FC6, + 0x030000, 0x025B6A, 0x049F9B, 0x03A1F4, 0x01B6BB, 0x00DFAA, 0x028090, 0x0156E2, + 0x0492AE, 0x03C399, 0x0481ED, 0x038AA2, 0x0297BD, 0x01525F, 0x027080, 0x013E5E, + 0x0492AE, 0x0657C8, 0x044FC1, 0x05FAF4, 0x03D555, 0x055126, 0x03248D, 0x045BF2, + 0x05022D, 0x0481ED, 0x041B33, 0x03D979, 0x024147, 0x0360C3, 0x01499C, 0x01C92E, + 0x032E96, 0x02DD1C, 0x01CD6A, 0x019F43, 0x05F991, 0x056093, 0x05A220, 0x0511E1, + 0x040000, 0x03248D, 0x036799, 0x02ACCF, 0x022A2F, 0x01264B, 0x01D7B5, 0x00F079, + 0x026F75, 0x01E9D9, 0x016127, 0x011EB8, 0x015DE9, 0x00B262, 0x00C57F, 0x006B2D, +}, +{ + 0x038000, 0x052876, 0x05C3CF, 0x07FF02, 0x04DBD9, 0x04A148, 0x07EDBA, 0x0722B4, + 0x03F000, 0x0317FB, 0x06117C, 0x04C491, 0x023FD5, 0x01258F, 0x0348BD, 0x01C209, + 0x060085, 0x04F0B9, 0x05EA87, 0x04A5F5, 0x036728, 0x01BC1C, 0x0333A8, 0x01A1DB, + 0x060085, 0x085336, 0x05A8AE, 0x07D960, 0x050800, 0x06FA82, 0x041FF9, 0x05B8AE, + 0x0692DA, 0x05EA87, 0x0563B2, 0x050D6E, 0x02F5AD, 0x046F00, 0x01B09C, 0x02580C, + 0x042D25, 0x03C235, 0x025D9B, 0x022108, 0x07D78F, 0x070EC1, 0x0764CA, 0x06A777, + 0x054000, 0x041FF9, 0x0477F9, 0x0382D0, 0x02D75E, 0x018242, 0x026B1D, 0x013B9F, + 0x03324A, 0x0282ED, 0x01CF83, 0x017851, 0x01CB42, 0x00EA21, 0x010336, 0x008CAC, +}, +{ + 0x040000, 0x05E519, 0x0696A4, 0x092370, 0x058D8A, 0x054A9C, 0x090FB0, 0x0827AA, + 0x048000, 0x03891F, 0x06EF69, 0x0572EE, 0x029218, 0x014F7E, 0x03C0D8, 0x020254, + 0x06DC05, 0x05A565, 0x06C2E4, 0x054FF3, 0x03E39B, 0x01FB8E, 0x03A8C0, 0x01DD8D, + 0x06DC05, 0x0983AC, 0x0677A2, 0x08F86E, 0x05C000, 0x07F9B9, 0x04B6D4, 0x0689EB, + 0x078343, 0x06C2E4, 0x0628CC, 0x05C635, 0x0361EA, 0x051124, 0x01EE69, 0x02ADC5, + 0x04C5E1, 0x044BAA, 0x02B41F, 0x026EE5, 0x08F65A, 0x0810DD, 0x087330, 0x079AD1, + 0x060000, 0x04B6D4, 0x051B65, 0x040337, 0x033F47, 0x01B970, 0x02C38F, 0x0168B6, + 0x03A730, 0x02DEC6, 0x0211BA, 0x01AE14, 0x020CDD, 0x010B93, 0x01283E, 0x00A0C4, +}, +{ + 0x050000, 0x075E60, 0x083C4D, 0x0B6C4C, 0x06F0ED, 0x069D43, 0x0B539C, 0x0A3194, + 0x05A000, 0x046B67, 0x08AB44, 0x06CFAA, 0x03369E, 0x01A35E, 0x04B10F, 0x0282E8, + 0x089307, 0x070EBF, 0x08739C, 0x06A3F0, 0x04DC82, 0x027A72, 0x0492F0, 0x0254F0, + 0x089307, 0x0BE497, 0x08158B, 0x0B3689, 0x073000, 0x09F827, 0x05E489, 0x082C66, + 0x096413, 0x08739C, 0x07B2FF, 0x0737C2, 0x043A64, 0x06556D, 0x026A04, 0x035936, + 0x05F75A, 0x055E94, 0x036127, 0x030A9E, 0x0B33F1, 0x0A1514, 0x0A8FFC, 0x098186, + 0x078000, 0x05E489, 0x06623F, 0x050405, 0x040F19, 0x0227CC, 0x037473, 0x01C2E3, + 0x0490FC, 0x039677, 0x029629, 0x021999, 0x029015, 0x014E78, 0x01724E, 0x00C8F5, +}, +{ + 0x060000, 0x08D7A6, 0x09E1F6, 0x0DB528, 0x085450, 0x07EFEA, 0x0D9788, 0x0C3B7E, + 0x06C000, 0x054DAE, 0x0A671E, 0x082C66, 0x03DB24, 0x01F73E, 0x05A145, 0x03037D, + 0x0A4A08, 0x087818, 0x0A2455, 0x07F7ED, 0x05D569, 0x02F955, 0x057D20, 0x02CC54, + 0x0A4A08, 0x0E4582, 0x09B373, 0x0D74A5, 0x08A000, 0x0BF696, 0x07123E, 0x09CEE0, + 0x0B44E4, 0x0A2455, 0x093D32, 0x08A950, 0x0512DF, 0x0799B6, 0x02E59E, 0x0404A7, + 0x0728D2, 0x06717F, 0x040E2F, 0x03A657, 0x0D7187, 0x0C194B, 0x0CACC8, 0x0B683A, + 0x090000, 0x07123E, 0x07A918, 0x0604D2, 0x04DEEA, 0x029629, 0x042556, 0x021D11, + 0x057AC8, 0x044E28, 0x031A97, 0x02851E, 0x03134C, 0x01915C, 0x01BC5D, 0x00F126, +}, +{ + 0x080000, 0x0BCA33, 0x0D2D48, 0x1246E0, 0x0B1B15, 0x0A9538, 0x121F5F, 0x104F53, + 0x090000, 0x07123E, 0x0DDED2, 0x0AE5DD, 0x052430, 0x029EFD, 0x0781B1, 0x0404A7, + 0x0DB80B, 0x0B4ACB, 0x0D85C7, 0x0A9FE7, 0x07C736, 0x03F71D, 0x075180, 0x03BB1A, + 0x0DB80B, 0x130757, 0x0CEF44, 0x11F0DC, 0x0B8000, 0x0FF372, 0x096DA8, 0x0D13D6, + 0x0F0686, 0x0D85C7, 0x0C5198, 0x0B8C6A, 0x06C3D4, 0x0A2248, 0x03DCD3, 0x055B8A, + 0x098BC3, 0x089754, 0x05683E, 0x04DDC9, 0x11ECB4, 0x1021B9, 0x10E661, 0x0F35A3, + 0x0C0000, 0x096DA8, 0x0A36CB, 0x08066E, 0x067E8E, 0x0372E1, 0x05871E, 0x02D16B, + 0x074E60, 0x05BD8B, 0x042374, 0x035C28, 0x0419BB, 0x021726, 0x02507C, 0x014188, +}, +{ + 0x0C0000, 0x11AF4C, 0x13C3EC, 0x1B6A50, 0x10A89F, 0x0FDFD4, 0x1B2F0F, 0x1876FD, + 0x0D8000, 0x0A9B5D, 0x14CE3C, 0x1058CB, 0x07B649, 0x03EE7B, 0x0B4289, 0x0606FB, + 0x149410, 0x10F030, 0x1448AB, 0x0FEFDA, 0x0BAAD2, 0x05F2AB, 0x0AFA40, 0x0598A7, + 0x149410, 0x1C8B03, 0x1366E6, 0x1AE949, 0x114000, 0x17ED2B, 0x0E247C, 0x139DC1, + 0x1689C8, 0x1448AB, 0x127A63, 0x11529F, 0x0A25BE, 0x0F336D, 0x05CB3C, 0x08094E, + 0x0E51A4, 0x0CE2FE, 0x081C5D, 0x074CAE, 0x1AE30E, 0x183296, 0x195991, 0x16D074, + 0x120000, 0x0E247C, 0x0F5230, 0x0C09A5, 0x09BDD5, 0x052C51, 0x084AAC, 0x043A21, + 0x0AF590, 0x089C51, 0x06352E, 0x050A3B, 0x062698, 0x0322B9, 0x0378BA, 0x01E24D, +}, +{ + 0x110000, 0x190DAC, 0x1C0039, 0x26D69C, 0x17998C, 0x167D16, 0x2682AB, 0x22A891, + 0x132000, 0x0F06C3, 0x1D797F, 0x172876, 0x0AECE7, 0x0591D9, 0x0FF398, 0x0889E3, + 0x1D2717, 0x17FEEF, 0x1CBC47, 0x1693CA, 0x108754, 0x086D1D, 0x0F8D30, 0x07ED98, + 0x1D2717, 0x286F9A, 0x1B7C71, 0x261FD3, 0x187000, 0x21E552, 0x140904, 0x1BCA27, + 0x1FEDDC, 0x1CBC47, 0x1A2D62, 0x188A62, 0x0E6022, 0x1588DA, 0x083540, 0x0B6284, + 0x1448FE, 0x124192, 0x0B7D84, 0x0A574B, 0x2616FF, 0x2247AA, 0x23E98D, 0x2051FA, + 0x198000, 0x140904, 0x15B46F, 0x110DAA, 0x0DCCEE, 0x07541E, 0x0BBF1F, 0x05FD04, + 0x0F868B, 0x0C32C8, 0x08CB57, 0x0723D4, 0x08B6AD, 0x047130, 0x04EB08, 0x02AB42, +}, +{ + 0x160000, 0x206C0C, 0x243C86, 0x3242E8, 0x1E8A79, 0x1D1A59, 0x31D646, 0x2CDA25, + 0x18C000, 0x13722A, 0x2624C3, 0x1DF820, 0x0E2385, 0x073537, 0x14A4A7, 0x0B0CCC, + 0x25BA1D, 0x1F0DAE, 0x252FE4, 0x1D37BB, 0x1563D6, 0x0AE78E, 0x142021, 0x0A4288, + 0x25BA1D, 0x345430, 0x2391FB, 0x31565C, 0x1FA000, 0x2BDD7A, 0x19ED8D, 0x23F68C, + 0x2951EF, 0x252FE4, 0x21E061, 0x1FC224, 0x129A87, 0x1BDE47, 0x0A9F44, 0x0EBBBA, + 0x1A4058, 0x17A026, 0x0EDEAB, 0x0D61E9, 0x314AEF, 0x2C5CBE, 0x2E798A, 0x29D380, + 0x210000, 0x19ED8D, 0x1C16AE, 0x1611AE, 0x11DC06, 0x097BEA, 0x0F3391, 0x07BFE7, + 0x141787, 0x0FC93E, 0x0B617F, 0x093D6D, 0x0B46C1, 0x05BFA8, 0x065D55, 0x037437, +}, +{ + 0x1C0000, 0x2943B2, 0x2E1E7C, 0x3FF810, 0x26DEC9, 0x250A43, 0x3F6DCE, 0x3915A3, + 0x1F8000, 0x18BFD8, 0x308BE1, 0x262485, 0x11FEA9, 0x092C75, 0x1A45EB, 0x0E1049, + 0x300425, 0x2785C6, 0x2F5439, 0x252FA8, 0x1B393F, 0x0DE0E4, 0x199D41, 0x0D0EDC, + 0x300425, 0x4299B2, 0x2D456E, 0x3ECB00, 0x284000, 0x37D40F, 0x20FFCB, 0x2DC56D, + 0x3496D3, 0x2F5439, 0x2B1D93, 0x286B74, 0x17AD66, 0x2377FE, 0x0D84E2, 0x12C062, + 0x21692A, 0x1E11A5, 0x12ECDA, 0x110840, 0x3EBC76, 0x387608, 0x3B2652, 0x353BBA, + 0x2A0000, 0x20FFCB, 0x23BFC6, 0x1C1681, 0x16BAF1, 0x0C1213, 0x1358E8, 0x09DCF8, + 0x19924F, 0x141767, 0x0E7C16, 0x0BC28A, 0x0E5A0D, 0x075104, 0x0819B2, 0x04655D, +}, +{ + 0x220000, 0x321B58, 0x380072, 0x4DAD38, 0x2F3318, 0x2CFA2D, 0x4D0556, 0x455122, + 0x264000, 0x1E0D86, 0x3AF2FE, 0x2E50EB, 0x15D9CE, 0x0B23B2, 0x1FE730, 0x1113C7, + 0x3A4E2D, 0x2FFDDF, 0x39788E, 0x2D2795, 0x210EA8, 0x10DA39, 0x1F1A61, 0x0FDB2F, + 0x3A4E2D, 0x50DF33, 0x36F8E1, 0x4C3FA5, 0x30E000, 0x43CAA5, 0x281209, 0x37944D, + 0x3FDBB7, 0x39788E, 0x345AC4, 0x3114C3, 0x1CC044, 0x2B11B4, 0x106A80, 0x16C509, + 0x2891FC, 0x248324, 0x16FB08, 0x14AE97, 0x4C2DFD, 0x448F54, 0x47D31B, 0x40A3F5, + 0x330000, 0x281209, 0x2B68DF, 0x221B53, 0x1B99DB, 0x0EA83B, 0x177E3E, 0x0BFA09, + 0x1F0D17, 0x18658F, 0x1196AE, 0x0E47A8, 0x116D5A, 0x08E260, 0x09D60F, 0x055684, +}, +{ + 0x2C0000, 0x40D818, 0x48790C, 0x6485D0, 0x3D14F2, 0x3A34B2, 0x63AC8D, 0x59B44A, + 0x318000, 0x26E454, 0x4C4986, 0x3BF03F, 0x1C470A, 0x0E6A6E, 0x29494D, 0x161998, + 0x4B743A, 0x3E1B5C, 0x4A5FC7, 0x3A6F75, 0x2AC7AC, 0x15CF1D, 0x284041, 0x148510, + 0x4B743A, 0x68A861, 0x4723F6, 0x62ACB8, 0x3F4000, 0x57BAF3, 0x33DB1A, 0x47ED19, + 0x52A3DE, 0x4A5FC7, 0x43C0C2, 0x3F8448, 0x25350D, 0x37BC8E, 0x153E87, 0x1D7775, + 0x3480B0, 0x2F404C, 0x1DBD56, 0x1AC3D2, 0x6295DE, 0x58B97B, 0x5CF313, 0x53A701, + 0x420000, 0x33DB1A, 0x382D5C, 0x2C235D, 0x23B80D, 0x12F7D4, 0x1E6723, 0x0F7FCF, + 0x282F0E, 0x1F927D, 0x16C2FF, 0x127AD9, 0x168D83, 0x0B7F50, 0x0CBAAA, 0x06E86E, +}, +}; + +static const uint8_t binkb_runbits[64] = { + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 2, 2, 1, 0, +}; + +static const uint8_t binkb_intra_seed[64] = { + 16, 16, 16, 19, 16, 19, 22, 22, + 22, 22, 26, 24, 26, 22, 22, 27, + 27, 27, 26, 26, 26, 29, 29, 29, + 27, 27, 27, 26, 34, 34, 34, 29, + 29, 29, 27, 27, 37, 34, 34, 32, + 32, 29, 29, 38, 37, 35, 35, 34, + 35, 40, 40, 40, 38, 38, 48, 48, + 46, 46, 58, 56, 56, 69, 69, 83, +}; + +static const uint8_t binkb_inter_seed[64] = { + 16, 17, 17, 18, 18, 18, 19, 19, + 19, 19, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 22, 22, 22, + 22, 22, 22, 22, 23, 23, 23, 23, + 23, 23, 23, 23, 24, 24, 24, 25, + 24, 24, 24, 25, 26, 26, 26, 26, + 25, 27, 27, 27, 27, 27, 28, 28, + 28, 28, 30, 30, 30, 31, 31, 33, +}; + +static const uint8_t binkb_num[16] = { + 1, 4, 5, 2, 7, 8, 3, 7, 4, 9, 5, 6, 7, 8, 9, 10 +}; + +static const uint8_t binkb_den[16] = { + 1, 3, 3, 1, 3, 3, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1 +}; + +#endif /* AVCODEC_BINKDATA_H */ diff --git a/ffmpeg/libavcodec/binkdsp.c b/ffmpeg/libavcodec/binkdsp.c new file mode 100644 index 0000000..c751743 --- /dev/null +++ b/ffmpeg/libavcodec/binkdsp.c @@ -0,0 +1,136 @@ +/* + * Bink DSP routines + * Copyright (c) 2009 Kostya Shishkov + * + * 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 + */ + +/** + * @file + * Bink DSP routines + */ + +#include "dsputil.h" +#include "binkdsp.h" + +#define A1 2896 /* (1/sqrt(2))<<12 */ +#define A2 2217 +#define A3 3784 +#define A4 -5352 + +#define IDCT_TRANSFORM(dest,s0,s1,s2,s3,s4,s5,s6,s7,d0,d1,d2,d3,d4,d5,d6,d7,munge,src) {\ + const int a0 = (src)[s0] + (src)[s4]; \ + const int a1 = (src)[s0] - (src)[s4]; \ + const int a2 = (src)[s2] + (src)[s6]; \ + const int a3 = (A1*((src)[s2] - (src)[s6])) >> 11; \ + const int a4 = (src)[s5] + (src)[s3]; \ + const int a5 = (src)[s5] - (src)[s3]; \ + const int a6 = (src)[s1] + (src)[s7]; \ + const int a7 = (src)[s1] - (src)[s7]; \ + const int b0 = a4 + a6; \ + const int b1 = (A3*(a5 + a7)) >> 11; \ + const int b2 = ((A4*a5) >> 11) - b0 + b1; \ + const int b3 = (A1*(a6 - a4) >> 11) - b2; \ + const int b4 = ((A2*a7) >> 11) + b3 - b1; \ + (dest)[d0] = munge(a0+a2 +b0); \ + (dest)[d1] = munge(a1+a3-a2+b2); \ + (dest)[d2] = munge(a1-a3+a2+b3); \ + (dest)[d3] = munge(a0-a2 -b4); \ + (dest)[d4] = munge(a0-a2 +b4); \ + (dest)[d5] = munge(a1-a3+a2-b3); \ + (dest)[d6] = munge(a1+a3-a2-b2); \ + (dest)[d7] = munge(a0+a2 -b0); \ +} +/* end IDCT_TRANSFORM macro */ + +#define MUNGE_NONE(x) (x) +#define IDCT_COL(dest,src) IDCT_TRANSFORM(dest,0,8,16,24,32,40,48,56,0,8,16,24,32,40,48,56,MUNGE_NONE,src) + +#define MUNGE_ROW(x) (((x) + 0x7F)>>8) +#define IDCT_ROW(dest,src) IDCT_TRANSFORM(dest,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,MUNGE_ROW,src) + +static inline void bink_idct_col(int *dest, const int32_t *src) +{ + if ((src[8]|src[16]|src[24]|src[32]|src[40]|src[48]|src[56])==0) { + dest[0] = + dest[8] = + dest[16] = + dest[24] = + dest[32] = + dest[40] = + dest[48] = + dest[56] = src[0]; + } else { + IDCT_COL(dest, src); + } +} + +static void bink_idct_c(int32_t *block) +{ + int i; + int temp[64]; + + for (i = 0; i < 8; i++) + bink_idct_col(&temp[i], &block[i]); + for (i = 0; i < 8; i++) { + IDCT_ROW( (&block[8*i]), (&temp[8*i]) ); + } +} + +static void bink_idct_add_c(uint8_t *dest, int linesize, int32_t *block) +{ + int i, j; + + bink_idct_c(block); + for (i = 0; i < 8; i++, dest += linesize, block += 8) + for (j = 0; j < 8; j++) + dest[j] += block[j]; +} + +static void bink_idct_put_c(uint8_t *dest, int linesize, int32_t *block) +{ + int i; + int temp[64]; + for (i = 0; i < 8; i++) + bink_idct_col(&temp[i], &block[i]); + for (i = 0; i < 8; i++) { + IDCT_ROW( (&dest[i*linesize]), (&temp[8*i]) ); + } +} + +static void scale_block_c(const uint8_t src[64]/*align 8*/, uint8_t *dst/*align 8*/, int linesize) +{ + int i, j; + uint16_t *dst1 = (uint16_t *) dst; + uint16_t *dst2 = (uint16_t *)(dst + linesize); + + for (j = 0; j < 8; j++) { + for (i = 0; i < 8; i++) { + dst1[i] = dst2[i] = src[i] * 0x0101; + } + src += 8; + dst1 += linesize; + dst2 += linesize; + } +} + +void ff_binkdsp_init(BinkDSPContext *c) +{ + c->idct_add = bink_idct_add_c; + c->idct_put = bink_idct_put_c; + c->scale_block = scale_block_c; +} diff --git a/ffmpeg/libavcodec/binkdsp.h b/ffmpeg/libavcodec/binkdsp.h new file mode 100644 index 0000000..4968413 --- /dev/null +++ b/ffmpeg/libavcodec/binkdsp.h @@ -0,0 +1,40 @@ +/* + * Bink DSP routines + * Copyright (c) 2009 Kostya Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Bink DSP routines + */ + +#ifndef AVCODEC_BINKDSP_H +#define AVCODEC_BINKDSP_H + +#include + +typedef struct BinkDSPContext { + void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, int32_t *block/*align 16*/); + void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, int32_t *block/*align 16*/); + void (*scale_block)(const uint8_t src[64]/*align 8*/, uint8_t *dst/*align 8*/, int linesize); +} BinkDSPContext; + +void ff_binkdsp_init(BinkDSPContext *c); + +#endif /* AVCODEC_BINKDSP_H */ diff --git a/ffmpeg/libavcodec/bintext.c b/ffmpeg/libavcodec/bintext.c new file mode 100644 index 0000000..f8059aa --- /dev/null +++ b/ffmpeg/libavcodec/bintext.c @@ -0,0 +1,258 @@ +/* + * Binary text decoder + * eXtended BINary text (XBIN) decoder + * iCEDraw File decoder + * Copyright (c) 2010 Peter Ross (pross@xvid.org) + * + * 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 + */ + +/** + * @file + * Binary text decoder + * eXtended BINary text (XBIN) decoder + * iCEDraw File decoder + */ + +#include "libavutil/intreadwrite.h" +#include "libavutil/xga_font_data.h" +#include "avcodec.h" +#include "cga_data.h" +#include "bintext.h" +#include "internal.h" + +typedef struct XbinContext { + AVFrame *frame; + int palette[16]; + int flags; + int font_height; + const uint8_t *font; + int x, y; +} XbinContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + XbinContext *s = avctx->priv_data; + uint8_t *p; + int i; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + p = avctx->extradata; + if (p) { + s->font_height = p[0]; + s->flags = p[1]; + p += 2; + if(avctx->extradata_size < 2 + (!!(s->flags & BINTEXT_PALETTE))*3*16 + + (!!(s->flags & BINTEXT_FONT))*s->font_height*256) { + av_log(avctx, AV_LOG_ERROR, "not enough extradata\n"); + return AVERROR_INVALIDDATA; + } + } else { + s->font_height = 8; + s->flags = 0; + } + + if ((s->flags & BINTEXT_PALETTE)) { + for (i = 0; i < 16; i++) { + s->palette[i] = 0xFF000000 | (AV_RB24(p) << 2) | ((AV_RB24(p) >> 4) & 0x30303); + p += 3; + } + } else { + for (i = 0; i < 16; i++) + s->palette[i] = 0xFF000000 | ff_cga_palette[i]; + } + + if ((s->flags & BINTEXT_FONT)) { + s->font = p; + } else { + switch(s->font_height) { + default: + av_log(avctx, AV_LOG_WARNING, "font height %i not supported\n", s->font_height); + s->font_height = 8; + case 8: + s->font = avpriv_cga_font; + break; + case 16: + s->font = avpriv_vga16_font; + break; + } + } + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + return 0; +} + +#define DEFAULT_BG_COLOR 0 +av_unused static void hscroll(AVCodecContext *avctx) +{ + XbinContext *s = avctx->priv_data; + if (s->y < avctx->height - s->font_height) { + s->y += s->font_height; + } else { + memmove(s->frame->data[0], s->frame->data[0] + s->font_height*s->frame->linesize[0], + (avctx->height - s->font_height)*s->frame->linesize[0]); + memset(s->frame->data[0] + (avctx->height - s->font_height)*s->frame->linesize[0], + DEFAULT_BG_COLOR, s->font_height * s->frame->linesize[0]); + } +} + +#define FONT_WIDTH 8 + +/** + * Draw character to screen + */ +static void draw_char(AVCodecContext *avctx, int c, int a) +{ + XbinContext *s = avctx->priv_data; + if (s->y > avctx->height - s->font_height) + return; + ff_draw_pc_font(s->frame->data[0] + s->y * s->frame->linesize[0] + s->x, + s->frame->linesize[0], s->font, s->font_height, c, + a & 0x0F, a >> 4); + s->x += FONT_WIDTH; + if (s->x > avctx->width - FONT_WIDTH) { + s->x = 0; + s->y += s->font_height; + } +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + XbinContext *s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end = buf+buf_size; + int ret; + + s->x = s->y = 0; + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + s->frame->pict_type = AV_PICTURE_TYPE_I; + s->frame->palette_has_changed = 1; + memcpy(s->frame->data[1], s->palette, 16 * 4); + + if (avctx->codec_id == AV_CODEC_ID_XBIN) { + while (buf + 2 < buf_end) { + int i,c,a; + int type = *buf >> 6; + int count = (*buf & 0x3F) + 1; + buf++; + switch (type) { + case 0: //no compression + for (i = 0; i < count && buf + 1 < buf_end; i++) { + draw_char(avctx, buf[0], buf[1]); + buf += 2; + } + break; + case 1: //character compression + c = *buf++; + for (i = 0; i < count && buf < buf_end; i++) + draw_char(avctx, c, *buf++); + break; + case 2: //attribute compression + a = *buf++; + for (i = 0; i < count && buf < buf_end; i++) + draw_char(avctx, *buf++, a); + break; + case 3: //character/attribute compression + c = *buf++; + a = *buf++; + for (i = 0; i < count && buf < buf_end; i++) + draw_char(avctx, c, a); + break; + } + } + } else if (avctx->codec_id == AV_CODEC_ID_IDF) { + while (buf + 2 < buf_end) { + if (AV_RL16(buf) == 1) { + int i; + if (buf + 6 > buf_end) + break; + for (i = 0; i < buf[2]; i++) + draw_char(avctx, buf[4], buf[5]); + buf += 6; + } else { + draw_char(avctx, buf[0], buf[1]); + buf += 2; + } + } + } else { + while (buf + 1 < buf_end) { + draw_char(avctx, buf[0], buf[1]); + buf += 2; + } + } + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + *got_frame = 1; + return buf_size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + XbinContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +#if CONFIG_BINTEXT_DECODER +AVCodec ff_bintext_decoder = { + .name = "bintext", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BINTEXT, + .priv_data_size = sizeof(XbinContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Binary text"), +}; +#endif +#if CONFIG_XBIN_DECODER +AVCodec ff_xbin_decoder = { + .name = "xbin", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XBIN, + .priv_data_size = sizeof(XbinContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("eXtended BINary text"), +}; +#endif +#if CONFIG_IDF_DECODER +AVCodec ff_idf_decoder = { + .name = "idf", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_IDF, + .priv_data_size = sizeof(XbinContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("iCEDraw text"), +}; +#endif diff --git a/ffmpeg/libavcodec/bintext.h b/ffmpeg/libavcodec/bintext.h new file mode 100644 index 0000000..ea834a0 --- /dev/null +++ b/ffmpeg/libavcodec/bintext.h @@ -0,0 +1,37 @@ +/* + * Binary text decoder + * Copyright (c) 2010 Peter Ross (pross@xvid.org) + * + * 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 + */ + +/** + * @file + * Binary text decoder + */ + +#ifndef AVCODEC_BINTEXT_H +#define AVCODEC_BINTEXT_H + +/* flag values passed between avformat and avcodec; + * while these are identical to the XBIN flags, they are are also used + * for the BINTEXT and IDF decoders. + */ +#define BINTEXT_PALETTE 0x1 +#define BINTEXT_FONT 0x2 + +#endif /* AVCODEC_BINTEXT_H */ diff --git a/ffmpeg/libavcodec/bit_depth_template.c b/ffmpeg/libavcodec/bit_depth_template.c new file mode 100644 index 0000000..1a6d007 --- /dev/null +++ b/ffmpeg/libavcodec/bit_depth_template.c @@ -0,0 +1,92 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "rnd_avg.h" +#include "libavutil/intreadwrite.h" + +#ifndef BIT_DEPTH +#define BIT_DEPTH 8 +#endif + +#ifdef AVCODEC_H264_HIGH_DEPTH_H +# undef pixel +# undef pixel2 +# undef pixel4 +# undef dctcoef +# undef INIT_CLIP +# undef no_rnd_avg_pixel4 +# undef rnd_avg_pixel4 +# undef AV_RN2P +# undef AV_RN4P +# undef AV_RN4PA +# undef AV_WN2P +# undef AV_WN4P +# undef AV_WN4PA +# undef CLIP +# undef FUNC +# undef FUNCC +# undef av_clip_pixel +# undef PIXEL_SPLAT_X4 +#else +# define AVCODEC_H264_HIGH_DEPTH_H +#endif + +#if BIT_DEPTH > 8 +# define pixel uint16_t +# define pixel2 uint32_t +# define pixel4 uint64_t +# define dctcoef int32_t + +# define INIT_CLIP +# define no_rnd_avg_pixel4 no_rnd_avg64 +# define rnd_avg_pixel4 rnd_avg64 +# define AV_RN2P AV_RN32 +# define AV_RN4P AV_RN64 +# define AV_RN4PA AV_RN64A +# define AV_WN2P AV_WN32 +# define AV_WN4P AV_WN64 +# define AV_WN4PA AV_WN64A +# define PIXEL_SPLAT_X4(x) ((x)*0x0001000100010001ULL) + +# define av_clip_pixel(a) av_clip_uintp2(a, BIT_DEPTH) +# define CLIP(a) av_clip_uintp2(a, BIT_DEPTH) +#else +# define pixel uint8_t +# define pixel2 uint16_t +# define pixel4 uint32_t +# define dctcoef int16_t + +# define INIT_CLIP +# define no_rnd_avg_pixel4 no_rnd_avg32 +# define rnd_avg_pixel4 rnd_avg32 +# define AV_RN2P AV_RN16 +# define AV_RN4P AV_RN32 +# define AV_RN4PA AV_RN32A +# define AV_WN2P AV_WN16 +# define AV_WN4P AV_WN32 +# define AV_WN4PA AV_WN32A +# define PIXEL_SPLAT_X4(x) ((x)*0x01010101U) + +# define av_clip_pixel(a) av_clip_uint8(a) +# define CLIP(a) av_clip_uint8(a) +#endif + +#define FUNC3(a, b, c) a ## _ ## b ## c +#define FUNC2(a, b, c) FUNC3(a, b, c) +#define FUNC(a) FUNC2(a, BIT_DEPTH,) +#define FUNCC(a) FUNC2(a, BIT_DEPTH, _c) diff --git a/ffmpeg/libavcodec/bitstream.c b/ffmpeg/libavcodec/bitstream.c new file mode 100644 index 0000000..6bcdadb --- /dev/null +++ b/ffmpeg/libavcodec/bitstream.c @@ -0,0 +1,339 @@ +/* + * Common bit i/o utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2010 Loren Merritt + * + * alternative bitstream reader & writer 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 + */ + +/** + * @file + * bitstream api. + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "mathops.h" +#include "get_bits.h" +#include "put_bits.h" + +const uint8_t ff_log2_run[41]={ + 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, + 8, 9,10,11,12,13,14,15, +16,17,18,19,20,21,22,23, +24, +}; + +void avpriv_align_put_bits(PutBitContext *s) +{ + put_bits(s,s->bit_left & 7,0); +} + +void avpriv_put_string(PutBitContext *pb, const char *string, int terminate_string) +{ + while(*string){ + put_bits(pb, 8, *string); + string++; + } + if(terminate_string) + put_bits(pb, 8, 0); +} + +void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) +{ + int words= length>>4; + int bits= length&15; + int i; + + if(length==0) return; + + if(CONFIG_SMALL || words < 16 || put_bits_count(pb)&7){ + for(i=0; i>(16-bits)); +} + +/* VLC decoding */ + +#define GET_DATA(v, table, i, wrap, size) \ +{\ + const uint8_t *ptr = (const uint8_t *)table + i * wrap;\ + switch(size) {\ + case 1:\ + v = *(const uint8_t *)ptr;\ + break;\ + case 2:\ + v = *(const uint16_t *)ptr;\ + break;\ + default:\ + v = *(const uint32_t *)ptr;\ + break;\ + }\ +} + + +static int alloc_table(VLC *vlc, int size, int use_static) +{ + int index; + index = vlc->table_size; + vlc->table_size += size; + if (vlc->table_size > vlc->table_allocated) { + if(use_static) + abort(); // cannot do anything, init_vlc() is used with too little memory + vlc->table_allocated += (1 << vlc->bits); + vlc->table = av_realloc_f(vlc->table, + vlc->table_allocated, sizeof(VLC_TYPE) * 2); + if (!vlc->table) + return -1; + } + return index; +} + +static av_always_inline uint32_t bitswap_32(uint32_t x) { + return (uint32_t)ff_reverse[x&0xFF]<<24 + | (uint32_t)ff_reverse[(x>>8)&0xFF]<<16 + | (uint32_t)ff_reverse[(x>>16)&0xFF]<<8 + | (uint32_t)ff_reverse[x>>24]; +} + +typedef struct { + uint8_t bits; + uint16_t symbol; + /** codeword, with the first bit-to-be-read in the msb + * (even if intended for a little-endian bitstream reader) */ + uint32_t code; +} VLCcode; + +static int compare_vlcspec(const void *a, const void *b) +{ + const VLCcode *sa=a, *sb=b; + return (sa->code >> 1) - (sb->code >> 1); +} + +/** + * Build VLC decoding tables suitable for use with get_vlc(). + * + * @param vlc the context to be initted + * + * @param table_nb_bits max length of vlc codes to store directly in this table + * (Longer codes are delegated to subtables.) + * + * @param nb_codes number of elements in codes[] + * + * @param codes descriptions of the vlc codes + * These must be ordered such that codes going into the same subtable are contiguous. + * Sorting by VLCcode.code is sufficient, though not necessary. + */ +static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, + VLCcode *codes, int flags) +{ + int table_size, table_index, index, code_prefix, symbol, subtable_bits; + int i, j, k, n, nb, inc; + uint32_t code; + VLC_TYPE (*table)[2]; + + table_size = 1 << table_nb_bits; + if (table_nb_bits > 30) + return -1; + table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC); + av_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); + if (table_index < 0) + return -1; + table = &vlc->table[table_index]; + + for (i = 0; i < table_size; i++) { + table[i][1] = 0; //bits + table[i][0] = -1; //codes + } + + /* first pass: map codes and compute auxiliary table sizes */ + for (i = 0; i < nb_codes; i++) { + n = codes[i].bits; + code = codes[i].code; + symbol = codes[i].symbol; + av_dlog(NULL, "i=%d n=%d code=0x%x\n", i, n, code); + if (n <= table_nb_bits) { + /* no need to add another table */ + j = code >> (32 - table_nb_bits); + nb = 1 << (table_nb_bits - n); + inc = 1; + if (flags & INIT_VLC_LE) { + j = bitswap_32(code); + inc = 1 << n; + } + for (k = 0; k < nb; k++) { + av_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); + if (table[j][1] /*bits*/ != 0) { + av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); + return -1; + } + table[j][1] = n; //bits + table[j][0] = symbol; + j += inc; + } + } else { + /* fill auxiliary table recursively */ + n -= table_nb_bits; + code_prefix = code >> (32 - table_nb_bits); + subtable_bits = n; + codes[i].bits = n; + codes[i].code = code << table_nb_bits; + for (k = i+1; k < nb_codes; k++) { + n = codes[k].bits - table_nb_bits; + if (n <= 0) + break; + code = codes[k].code; + if (code >> (32 - table_nb_bits) != code_prefix) + break; + codes[k].bits = n; + codes[k].code = code << table_nb_bits; + subtable_bits = FFMAX(subtable_bits, n); + } + subtable_bits = FFMIN(subtable_bits, table_nb_bits); + j = (flags & INIT_VLC_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix; + table[j][1] = -subtable_bits; + av_dlog(NULL, "%4x: n=%d (subtable)\n", + j, codes[i].bits + table_nb_bits); + index = build_table(vlc, subtable_bits, k-i, codes+i, flags); + if (index < 0) + return -1; + /* note: realloc has been done, so reload tables */ + table = &vlc->table[table_index]; + table[j][0] = index; //code + i = k-1; + } + } + return table_index; +} + + +/* Build VLC decoding tables suitable for use with get_vlc(). + + 'nb_bits' set thee decoding table size (2^nb_bits) entries. The + bigger it is, the faster is the decoding. But it should not be too + big to save memory and L1 cache. '9' is a good compromise. + + 'nb_codes' : number of vlcs codes + + 'bits' : table which gives the size (in bits) of each vlc code. + + 'codes' : table which gives the bit pattern of of each vlc code. + + 'symbols' : table which gives the values to be returned from get_vlc(). + + 'xxx_wrap' : give the number of bytes between each entry of the + 'bits' or 'codes' tables. + + 'xxx_size' : gives the number of bytes of each entry of the 'bits' + or 'codes' tables. + + 'wrap' and 'size' allows to use any memory configuration and types + (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables. + + 'use_static' should be set to 1 for tables, which should be freed + with av_free_static(), 0 if ff_free_vlc() will be used. +*/ +int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + const void *symbols, int symbols_wrap, int symbols_size, + int flags) +{ + VLCcode *buf; + int i, j, ret; + + vlc->bits = nb_bits; + if(flags & INIT_VLC_USE_NEW_STATIC){ + VLC dyn_vlc = *vlc; + + if (vlc->table_size) + return 0; + + ret = ff_init_vlc_sparse(&dyn_vlc, nb_bits, nb_codes, + bits, bits_wrap, bits_size, + codes, codes_wrap, codes_size, + symbols, symbols_wrap, symbols_size, + flags & ~INIT_VLC_USE_NEW_STATIC); + av_assert0(ret >= 0); + av_assert0(dyn_vlc.table_size <= vlc->table_allocated); + if(dyn_vlc.table_size < vlc->table_allocated) + av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", dyn_vlc.table_size, vlc->table_allocated); + memcpy(vlc->table, dyn_vlc.table, dyn_vlc.table_size * sizeof(*vlc->table)); + vlc->table_size = dyn_vlc.table_size; + ff_free_vlc(&dyn_vlc); + return 0; + }else { + vlc->table = NULL; + vlc->table_allocated = 0; + vlc->table_size = 0; + } + + av_dlog(NULL, "build table nb_codes=%d\n", nb_codes); + + buf = av_malloc((nb_codes+1)*sizeof(VLCcode)); + + av_assert0(symbols_size <= 2 || !symbols); + j = 0; +#define COPY(condition)\ + for (i = 0; i < nb_codes; i++) {\ + GET_DATA(buf[j].bits, bits, i, bits_wrap, bits_size);\ + if (!(condition))\ + continue;\ + GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size);\ + if (flags & INIT_VLC_LE)\ + buf[j].code = bitswap_32(buf[j].code);\ + else\ + buf[j].code <<= 32 - buf[j].bits;\ + if (symbols)\ + GET_DATA(buf[j].symbol, symbols, i, symbols_wrap, symbols_size)\ + else\ + buf[j].symbol = i;\ + j++;\ + } + COPY(buf[j].bits > nb_bits); + // qsort is the slowest part of init_vlc, and could probably be improved or avoided + qsort(buf, j, sizeof(VLCcode), compare_vlcspec); + COPY(buf[j].bits && buf[j].bits <= nb_bits); + nb_codes = j; + + ret = build_table(vlc, nb_bits, nb_codes, buf, flags); + + av_free(buf); + if (ret < 0) { + av_freep(&vlc->table); + return -1; + } + return 0; +} + + +void ff_free_vlc(VLC *vlc) +{ + av_freep(&vlc->table); +} diff --git a/ffmpeg/libavcodec/bitstream_filter.c b/ffmpeg/libavcodec/bitstream_filter.c new file mode 100644 index 0000000..328a9f6 --- /dev/null +++ b/ffmpeg/libavcodec/bitstream_filter.c @@ -0,0 +1,68 @@ +/* + * copyright (c) 2006 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 "avcodec.h" +#include "libavutil/mem.h" + +static AVBitStreamFilter *first_bitstream_filter= NULL; + +AVBitStreamFilter *av_bitstream_filter_next(AVBitStreamFilter *f){ + if(f) return f->next; + else return first_bitstream_filter; +} + +void av_register_bitstream_filter(AVBitStreamFilter *bsf){ + bsf->next = first_bitstream_filter; + first_bitstream_filter= bsf; +} + +AVBitStreamFilterContext *av_bitstream_filter_init(const char *name){ + AVBitStreamFilter *bsf= first_bitstream_filter; + + while(bsf){ + if(!strcmp(name, bsf->name)){ + AVBitStreamFilterContext *bsfc= av_mallocz(sizeof(AVBitStreamFilterContext)); + bsfc->filter= bsf; + bsfc->priv_data = bsf->priv_data_size ? av_mallocz(bsf->priv_data_size) : NULL; + return bsfc; + } + bsf= bsf->next; + } + return NULL; +} + +void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc){ + if(bsfc->filter->close) + bsfc->filter->close(bsfc); + av_freep(&bsfc->priv_data); + av_parser_close(bsfc->parser); + av_free(bsfc); +} + +int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + *poutbuf= (uint8_t *) buf; + *poutbuf_size= buf_size; + return bsfc->filter->filter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, buf_size, keyframe); +} diff --git a/ffmpeg/libavcodec/bmp.c b/ffmpeg/libavcodec/bmp.c new file mode 100644 index 0000000..a3bb1a7 --- /dev/null +++ b/ffmpeg/libavcodec/bmp.c @@ -0,0 +1,338 @@ +/* + * BMP image format decoder + * Copyright (c) 2005 Mans Rullgard + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "bmp.h" +#include "internal.h" +#include "msrledec.h" + +static int bmp_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *p = data; + unsigned int fsize, hsize; + int width, height; + unsigned int depth; + BiCompression comp; + unsigned int ihsize; + int i, j, n, linesize, ret; + uint32_t rgb[3] = {0}; + uint32_t alpha = 0; + uint8_t *ptr; + int dsize; + const uint8_t *buf0 = buf; + GetByteContext gb; + + if (buf_size < 14) { + av_log(avctx, AV_LOG_ERROR, "buf size too small (%d)\n", buf_size); + return AVERROR_INVALIDDATA; + } + + if (bytestream_get_byte(&buf) != 'B' || + bytestream_get_byte(&buf) != 'M') { + av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); + return AVERROR_INVALIDDATA; + } + + fsize = bytestream_get_le32(&buf); + if (buf_size < fsize) { + av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d), trying to decode anyway\n", + buf_size, fsize); + fsize = buf_size; + } + + buf += 2; /* reserved1 */ + buf += 2; /* reserved2 */ + + hsize = bytestream_get_le32(&buf); /* header size */ + ihsize = bytestream_get_le32(&buf); /* more header size */ + if (ihsize + 14 > hsize) { + av_log(avctx, AV_LOG_ERROR, "invalid header size %d\n", hsize); + return AVERROR_INVALIDDATA; + } + + /* sometimes file size is set to some headers size, set a real size in that case */ + if (fsize == 14 || fsize == ihsize + 14) + fsize = buf_size - 2; + + if (fsize <= hsize) { + av_log(avctx, AV_LOG_ERROR, "declared file size is less than header size (%d < %d)\n", + fsize, hsize); + return AVERROR_INVALIDDATA; + } + + switch (ihsize) { + case 40: // windib + case 56: // windib v3 + case 64: // OS/2 v2 + case 108: // windib v4 + case 124: // windib v5 + width = bytestream_get_le32(&buf); + height = bytestream_get_le32(&buf); + break; + case 12: // OS/2 v1 + width = bytestream_get_le16(&buf); + height = bytestream_get_le16(&buf); + break; + default: + av_log(avctx, AV_LOG_ERROR, "unsupported BMP file, patch welcome\n"); + return AVERROR_PATCHWELCOME; + } + + /* planes */ + if (bytestream_get_le16(&buf) != 1) { + av_log(avctx, AV_LOG_ERROR, "invalid BMP header\n"); + return AVERROR_INVALIDDATA; + } + + depth = bytestream_get_le16(&buf); + + if (ihsize >= 40) + comp = bytestream_get_le32(&buf); + else + comp = BMP_RGB; + + if (comp != BMP_RGB && comp != BMP_BITFIELDS && comp != BMP_RLE4 && + comp != BMP_RLE8) { + av_log(avctx, AV_LOG_ERROR, "BMP coding %d not supported\n", comp); + return AVERROR_INVALIDDATA; + } + + if (comp == BMP_BITFIELDS) { + buf += 20; + rgb[0] = bytestream_get_le32(&buf); + rgb[1] = bytestream_get_le32(&buf); + rgb[2] = bytestream_get_le32(&buf); + alpha = bytestream_get_le32(&buf); + } + + avctx->width = width; + avctx->height = height > 0 ? height : -height; + + avctx->pix_fmt = AV_PIX_FMT_NONE; + + switch (depth) { + case 32: + if (comp == BMP_BITFIELDS) { + if (rgb[0] == 0xFF000000 && rgb[1] == 0x00FF0000 && rgb[2] == 0x0000FF00) + avctx->pix_fmt = alpha ? AV_PIX_FMT_ABGR : AV_PIX_FMT_0BGR; + else if (rgb[0] == 0x00FF0000 && rgb[1] == 0x0000FF00 && rgb[2] == 0x000000FF) + avctx->pix_fmt = alpha ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGR0; + else if (rgb[0] == 0x0000FF00 && rgb[1] == 0x00FF0000 && rgb[2] == 0xFF000000) + avctx->pix_fmt = alpha ? AV_PIX_FMT_ARGB : AV_PIX_FMT_0RGB; + else if (rgb[0] == 0x000000FF && rgb[1] == 0x0000FF00 && rgb[2] == 0x00FF0000) + avctx->pix_fmt = alpha ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB0; + else { + av_log(avctx, AV_LOG_ERROR, "Unknown bitfields %0X %0X %0X\n", rgb[0], rgb[1], rgb[2]); + return AVERROR(EINVAL); + } + } else { + avctx->pix_fmt = AV_PIX_FMT_BGRA; + } + break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case 16: + if (comp == BMP_RGB) + avctx->pix_fmt = AV_PIX_FMT_RGB555; + else if (comp == BMP_BITFIELDS) { + if (rgb[0] == 0xF800 && rgb[1] == 0x07E0 && rgb[2] == 0x001F) + avctx->pix_fmt = AV_PIX_FMT_RGB565; + else if (rgb[0] == 0x7C00 && rgb[1] == 0x03E0 && rgb[2] == 0x001F) + avctx->pix_fmt = AV_PIX_FMT_RGB555; + else if (rgb[0] == 0x0F00 && rgb[1] == 0x00F0 && rgb[2] == 0x000F) + avctx->pix_fmt = AV_PIX_FMT_RGB444; + else { + av_log(avctx, AV_LOG_ERROR, "Unknown bitfields %0X %0X %0X\n", rgb[0], rgb[1], rgb[2]); + return AVERROR(EINVAL); + } + } + break; + case 8: + if (hsize - ihsize - 14 > 0) + avctx->pix_fmt = AV_PIX_FMT_PAL8; + else + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + break; + case 1: + case 4: + if (hsize - ihsize - 14 > 0) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else { + av_log(avctx, AV_LOG_ERROR, "Unknown palette for %d-colour BMP\n", 1<pix_fmt == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + buf = buf0 + hsize; + dsize = buf_size - hsize; + + /* Line size in file multiple of 4 */ + n = ((avctx->width * depth + 31) / 8) & ~3; + + if (n * avctx->height > dsize && comp != BMP_RLE4 && comp != BMP_RLE8) { + av_log(avctx, AV_LOG_ERROR, "not enough data (%d < %d)\n", + dsize, n * avctx->height); + return AVERROR_INVALIDDATA; + } + + // RLE may skip decoding some picture areas, so blank picture before decoding + if (comp == BMP_RLE4 || comp == BMP_RLE8) + memset(p->data[0], 0, avctx->height * p->linesize[0]); + + if (height > 0) { + ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; + linesize = -p->linesize[0]; + } else { + ptr = p->data[0]; + linesize = p->linesize[0]; + } + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + int colors = 1 << depth; + + memset(p->data[1], 0, 1024); + + if (ihsize >= 36) { + int t; + buf = buf0 + 46; + t = bytestream_get_le32(&buf); + if (t < 0 || t > (1 << depth)) { + av_log(avctx, AV_LOG_ERROR, "Incorrect number of colors - %X for bitdepth %d\n", t, depth); + } else if (t) { + colors = t; + } + } + buf = buf0 + 14 + ihsize; //palette location + // OS/2 bitmap, 3 bytes per palette entry + if ((hsize-ihsize-14) < (colors << 2)) { + if ((hsize-ihsize-14) < colors * 3) { + av_log(avctx, AV_LOG_ERROR, "palette doesnt fit in packet\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < colors; i++) + ((uint32_t*)p->data[1])[i] = (0xFFU<<24) | bytestream_get_le24(&buf); + } else { + for (i = 0; i < colors; i++) + ((uint32_t*)p->data[1])[i] = 0xFFU << 24 | bytestream_get_le32(&buf); + } + buf = buf0 + hsize; + } + if (comp == BMP_RLE4 || comp == BMP_RLE8) { + if (height < 0) { + p->data[0] += p->linesize[0] * (avctx->height - 1); + p->linesize[0] = -p->linesize[0]; + } + bytestream2_init(&gb, buf, dsize); + ff_msrle_decode(avctx, (AVPicture*)p, depth, &gb); + if (height < 0) { + p->data[0] += p->linesize[0] * (avctx->height - 1); + p->linesize[0] = -p->linesize[0]; + } + } else { + switch (depth) { + case 1: + for (i = 0; i < avctx->height; i++) { + int j; + for (j = 0; j < n; j++) { + ptr[j*8+0] = buf[j] >> 7; + ptr[j*8+1] = (buf[j] >> 6) & 1; + ptr[j*8+2] = (buf[j] >> 5) & 1; + ptr[j*8+3] = (buf[j] >> 4) & 1; + ptr[j*8+4] = (buf[j] >> 3) & 1; + ptr[j*8+5] = (buf[j] >> 2) & 1; + ptr[j*8+6] = (buf[j] >> 1) & 1; + ptr[j*8+7] = buf[j] & 1; + } + buf += n; + ptr += linesize; + } + break; + case 8: + case 24: + case 32: + for (i = 0; i < avctx->height; i++) { + memcpy(ptr, buf, n); + buf += n; + ptr += linesize; + } + break; + case 4: + for (i = 0; i < avctx->height; i++) { + int j; + for (j = 0; j < n; j++) { + ptr[j*2+0] = (buf[j] >> 4) & 0xF; + ptr[j*2+1] = buf[j] & 0xF; + } + buf += n; + ptr += linesize; + } + break; + case 16: + for (i = 0; i < avctx->height; i++) { + const uint16_t *src = (const uint16_t *) buf; + uint16_t *dst = (uint16_t *) ptr; + + for (j = 0; j < avctx->width; j++) + *dst++ = av_le2ne16(*src++); + + buf += n; + ptr += linesize; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "BMP decoder is broken\n"); + return AVERROR_INVALIDDATA; + } + } + + *got_frame = 1; + + return buf_size; +} + +AVCodec ff_bmp_decoder = { + .name = "bmp", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BMP, + .decode = bmp_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), +}; diff --git a/ffmpeg/libavcodec/bmp.h b/ffmpeg/libavcodec/bmp.h new file mode 100644 index 0000000..b24a1fa --- /dev/null +++ b/ffmpeg/libavcodec/bmp.h @@ -0,0 +1,38 @@ +/* + * internals for BMP codecs + * Copyright (c) 2005 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_BMP_H +#define AVCODEC_BMP_H + +#include "avcodec.h" + +typedef struct BMPContext { + AVFrame picture; +} BMPContext; + +typedef enum { + BMP_RGB =0, + BMP_RLE8 =1, + BMP_RLE4 =2, + BMP_BITFIELDS =3, +} BiCompression; + +#endif /* AVCODEC_BMP_H */ diff --git a/ffmpeg/libavcodec/bmp_parser.c b/ffmpeg/libavcodec/bmp_parser.c new file mode 100644 index 0000000..06ed367 --- /dev/null +++ b/ffmpeg/libavcodec/bmp_parser.c @@ -0,0 +1,91 @@ +/* + * BMP parser + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +/** + * @file + * BMP parser + */ + +#include "libavutil/bswap.h" +#include "parser.h" + +typedef struct BMPParseContext { + ParseContext pc; + uint32_t fsize; + uint32_t remaining_size; +} BMPParseContext; + +static int bmp_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + BMPParseContext *bpc = s->priv_data; + uint64_t state = bpc->pc.state64; + int next = END_NOT_FOUND; + int i = 0; + + s->pict_type = AV_PICTURE_TYPE_NONE; + + *poutbuf_size = 0; + if (buf_size == 0) + return 0; + + if (!bpc->pc.frame_start_found) { + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if ((state >> 48) == (('B' << 8) | 'M')) { + bpc->fsize = av_bswap32(state >> 16); + bpc->pc.frame_start_found = 1; + if (bpc->fsize > buf_size - i + 7) + bpc->remaining_size = bpc->fsize - buf_size + i - 7; + else + next = bpc->fsize + i - 7; + break; + } + } + bpc->pc.state64 = state; + } else { + if (bpc->remaining_size) { + i = FFMIN(bpc->remaining_size, buf_size); + bpc->remaining_size -= i; + if (bpc->remaining_size) + goto flush; + next = i; + } + } + +flush: + if (ff_combine_frame(&bpc->pc, next, &buf, &buf_size) < 0) + return buf_size; + + bpc->pc.frame_start_found = 0; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_bmp_parser = { + .codec_ids = { AV_CODEC_ID_BMP }, + .priv_data_size = sizeof(BMPParseContext), + .parser_parse = bmp_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/bmpenc.c b/ffmpeg/libavcodec/bmpenc.c new file mode 100644 index 0000000..bda6799 --- /dev/null +++ b/ffmpeg/libavcodec/bmpenc.c @@ -0,0 +1,183 @@ +/* + * BMP image format encoder + * Copyright (c) 2006, 2007 Michel Bardiaux + * Copyright (c) 2009 Daniel Verkamp + * + * 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 "libavutil/imgutils.h" +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "bytestream.h" +#include "bmp.h" +#include "internal.h" + +static const uint32_t monoblack_pal[] = { 0x000000, 0xFFFFFF }; +static const uint32_t rgb565_masks[] = { 0xF800, 0x07E0, 0x001F }; +static const uint32_t rgb444_masks[] = { 0x0F00, 0x00F0, 0x000F }; + +static av_cold int bmp_encode_init(AVCodecContext *avctx){ + BMPContext *s = avctx->priv_data; + + avcodec_get_frame_defaults(&s->picture); + avctx->coded_frame = &s->picture; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_BGRA: + avctx->bits_per_coded_sample = 32; + break; + case AV_PIX_FMT_BGR24: + avctx->bits_per_coded_sample = 24; + break; + case AV_PIX_FMT_RGB555: + case AV_PIX_FMT_RGB565: + case AV_PIX_FMT_RGB444: + avctx->bits_per_coded_sample = 16; + break; + case AV_PIX_FMT_RGB8: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_PAL8: + avctx->bits_per_coded_sample = 8; + break; + case AV_PIX_FMT_MONOBLACK: + avctx->bits_per_coded_sample = 1; + break; + default: + av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); + return -1; + } + + return 0; +} + +static int bmp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + BMPContext *s = avctx->priv_data; + AVFrame * const p = &s->picture; + int n_bytes_image, n_bytes_per_row, n_bytes, i, n, hsize, ret; + const uint32_t *pal = NULL; + uint32_t palette256[256]; + int pad_bytes_per_row, pal_entries = 0, compression = BMP_RGB; + int bit_count = avctx->bits_per_coded_sample; + uint8_t *ptr, *buf; + *p = *pict; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGB444: + compression = BMP_BITFIELDS; + pal = rgb444_masks; // abuse pal to hold color masks + pal_entries = 3; + break; + case AV_PIX_FMT_RGB565: + compression = BMP_BITFIELDS; + pal = rgb565_masks; // abuse pal to hold color masks + pal_entries = 3; + break; + case AV_PIX_FMT_RGB8: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_GRAY8: + av_assert1(bit_count == 8); + avpriv_set_systematic_pal2(palette256, avctx->pix_fmt); + pal = palette256; + break; + case AV_PIX_FMT_PAL8: + pal = (uint32_t *)p->data[1]; + break; + case AV_PIX_FMT_MONOBLACK: + pal = monoblack_pal; + break; + } + if (pal && !pal_entries) pal_entries = 1 << bit_count; + n_bytes_per_row = ((int64_t)avctx->width * (int64_t)bit_count + 7LL) >> 3LL; + pad_bytes_per_row = (4 - n_bytes_per_row) & 3; + n_bytes_image = avctx->height * (n_bytes_per_row + pad_bytes_per_row); + + // STRUCTURE.field refer to the MSVC documentation for BITMAPFILEHEADER + // and related pages. +#define SIZE_BITMAPFILEHEADER 14 +#define SIZE_BITMAPINFOHEADER 40 + hsize = SIZE_BITMAPFILEHEADER + SIZE_BITMAPINFOHEADER + (pal_entries << 2); + n_bytes = n_bytes_image + hsize; + if ((ret = ff_alloc_packet2(avctx, pkt, n_bytes)) < 0) + return ret; + buf = pkt->data; + bytestream_put_byte(&buf, 'B'); // BITMAPFILEHEADER.bfType + bytestream_put_byte(&buf, 'M'); // do. + bytestream_put_le32(&buf, n_bytes); // BITMAPFILEHEADER.bfSize + bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved1 + bytestream_put_le16(&buf, 0); // BITMAPFILEHEADER.bfReserved2 + bytestream_put_le32(&buf, hsize); // BITMAPFILEHEADER.bfOffBits + bytestream_put_le32(&buf, SIZE_BITMAPINFOHEADER); // BITMAPINFOHEADER.biSize + bytestream_put_le32(&buf, avctx->width); // BITMAPINFOHEADER.biWidth + bytestream_put_le32(&buf, avctx->height); // BITMAPINFOHEADER.biHeight + bytestream_put_le16(&buf, 1); // BITMAPINFOHEADER.biPlanes + bytestream_put_le16(&buf, bit_count); // BITMAPINFOHEADER.biBitCount + bytestream_put_le32(&buf, compression); // BITMAPINFOHEADER.biCompression + bytestream_put_le32(&buf, n_bytes_image); // BITMAPINFOHEADER.biSizeImage + bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biXPelsPerMeter + bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biYPelsPerMeter + bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrUsed + bytestream_put_le32(&buf, 0); // BITMAPINFOHEADER.biClrImportant + for (i = 0; i < pal_entries; i++) + bytestream_put_le32(&buf, pal[i] & 0xFFFFFF); + // BMP files are bottom-to-top so we start from the end... + ptr = p->data[0] + (avctx->height - 1) * p->linesize[0]; + buf = pkt->data + hsize; + for(i = 0; i < avctx->height; i++) { + if (bit_count == 16) { + const uint16_t *src = (const uint16_t *) ptr; + uint16_t *dst = (uint16_t *) buf; + for(n = 0; n < avctx->width; n++) + AV_WL16(dst + n, src[n]); + } else { + memcpy(buf, ptr, n_bytes_per_row); + } + buf += n_bytes_per_row; + memset(buf, 0, pad_bytes_per_row); + buf += pad_bytes_per_row; + ptr -= p->linesize[0]; // ... and go back + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +AVCodec ff_bmp_encoder = { + .name = "bmp", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BMP, + .priv_data_size = sizeof(BMPContext), + .init = bmp_encode_init, + .encode2 = bmp_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_BGRA, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB565, AV_PIX_FMT_RGB555, AV_PIX_FMT_RGB444, + AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, + AV_PIX_FMT_MONOBLACK, + AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), +}; diff --git a/ffmpeg/libavcodec/bmv.c b/ffmpeg/libavcodec/bmv.c new file mode 100644 index 0000000..2628e4a --- /dev/null +++ b/ffmpeg/libavcodec/bmv.c @@ -0,0 +1,360 @@ +/* + * Discworld II BMV video and audio decoder + * Copyright (c) 2011 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +enum BMVFlags{ + BMV_NOP = 0, + BMV_END, + BMV_DELTA, + BMV_INTRA, + + BMV_SCROLL = 0x04, + BMV_PALETTE = 0x08, + BMV_COMMAND = 0x10, + BMV_AUDIO = 0x20, + BMV_EXT = 0x40, + BMV_PRINT = 0x80 +}; + +#define SCREEN_WIDE 640 +#define SCREEN_HIGH 429 + +typedef struct BMVDecContext { + AVCodecContext *avctx; + + uint8_t *frame, frame_base[SCREEN_WIDE * (SCREEN_HIGH + 1)]; + uint32_t pal[256]; + const uint8_t *stream; +} BMVDecContext; + +#define NEXT_BYTE(v) v = forward ? v + 1 : v - 1; + +static int decode_bmv_frame(const uint8_t *source, int src_len, uint8_t *frame, int frame_off) +{ + unsigned val, saved_val = 0; + int tmplen = src_len; + const uint8_t *src, *source_end = source + src_len; + uint8_t *frame_end = frame + SCREEN_WIDE * SCREEN_HIGH; + uint8_t *dst, *dst_end; + int len, mask; + int forward = (frame_off <= -SCREEN_WIDE) || (frame_off >= 0); + int read_two_nibbles, flag; + int advance_mode; + int mode = 0; + int i; + + if (src_len <= 0) + return AVERROR_INVALIDDATA; + + if (forward) { + src = source; + dst = frame; + dst_end = frame_end; + } else { + src = source + src_len - 1; + dst = frame_end - 1; + dst_end = frame - 1; + } + for (;;) { + int shift = 0; + flag = 0; + + /* The mode/len decoding is a bit strange: + * values are coded as variable-length codes with nibble units, + * code end is signalled by two top bits in the nibble being nonzero. + * And since data is bytepacked and we read two nibbles at a time, + * we may get a nibble belonging to the next code. + * Hence this convoluted loop. + */ + if (!mode || (tmplen == 4)) { + if (src < source || src >= source_end) + return AVERROR_INVALIDDATA; + val = *src; + read_two_nibbles = 1; + } else { + val = saved_val; + read_two_nibbles = 0; + } + if (!(val & 0xC)) { + for (;;) { + if(shift>22) + return -1; + if (!read_two_nibbles) { + if (src < source || src >= source_end) + return AVERROR_INVALIDDATA; + shift += 2; + val |= *src << shift; + if (*src & 0xC) + break; + } + // two upper bits of the nibble is zero, + // so shift top nibble value down into their place + read_two_nibbles = 0; + shift += 2; + mask = (1 << shift) - 1; + val = ((val >> 2) & ~mask) | (val & mask); + NEXT_BYTE(src); + if ((val & (0xC << shift))) { + flag = 1; + break; + } + } + } else if (mode) { + flag = tmplen != 4; + } + if (flag) { + tmplen = 4; + } else { + saved_val = val >> (4 + shift); + tmplen = 0; + val &= (1 << (shift + 4)) - 1; + NEXT_BYTE(src); + } + advance_mode = val & 1; + len = (val >> 1) - 1; + av_assert0(len>0); + mode += 1 + advance_mode; + if (mode >= 4) + mode -= 3; + if (FFABS(dst_end - dst) < len) + return AVERROR_INVALIDDATA; + switch (mode) { + case 1: + if (forward) { + if (dst - frame + SCREEN_WIDE < frame_off || + dst - frame + SCREEN_WIDE + frame_off < 0 || + frame_end - dst < frame_off + len || + frame_end - dst < len) + return AVERROR_INVALIDDATA; + for (i = 0; i < len; i++) + dst[i] = dst[frame_off + i]; + dst += len; + } else { + dst -= len; + if (dst - frame + SCREEN_WIDE < frame_off || + dst - frame + SCREEN_WIDE + frame_off < 0 || + frame_end - dst < frame_off + len || + frame_end - dst < len) + return AVERROR_INVALIDDATA; + for (i = len - 1; i >= 0; i--) + dst[i] = dst[frame_off + i]; + } + break; + case 2: + if (forward) { + if (source + src_len - src < len) + return AVERROR_INVALIDDATA; + memcpy(dst, src, len); + dst += len; + src += len; + } else { + if (src - source < len) + return AVERROR_INVALIDDATA; + dst -= len; + src -= len; + memcpy(dst, src, len); + } + break; + case 3: + val = forward ? dst[-1] : dst[1]; + if (forward) { + memset(dst, val, len); + dst += len; + } else { + dst -= len; + memset(dst, val, len); + } + break; + } + if (dst == dst_end) + return 0; + } + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *pkt) +{ + BMVDecContext * const c = avctx->priv_data; + AVFrame *frame = data; + int type, scr_off; + int i, ret; + uint8_t *srcptr, *outptr; + + c->stream = pkt->data; + type = bytestream_get_byte(&c->stream); + if (type & BMV_AUDIO) { + int blobs = bytestream_get_byte(&c->stream); + if (pkt->size < blobs * 65 + 2) { + av_log(avctx, AV_LOG_ERROR, "Audio data doesn't fit in frame\n"); + return AVERROR_INVALIDDATA; + } + c->stream += blobs * 65; + } + if (type & BMV_COMMAND) { + int command_size = (type & BMV_PRINT) ? 8 : 10; + if (c->stream - pkt->data + command_size > pkt->size) { + av_log(avctx, AV_LOG_ERROR, "Command data doesn't fit in frame\n"); + return AVERROR_INVALIDDATA; + } + c->stream += command_size; + } + if (type & BMV_PALETTE) { + if (c->stream - pkt->data > pkt->size - 768) { + av_log(avctx, AV_LOG_ERROR, "Palette data doesn't fit in frame\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < 256; i++) + c->pal[i] = 0xFFU << 24 | bytestream_get_be24(&c->stream); + } + if (type & BMV_SCROLL) { + if (c->stream - pkt->data > pkt->size - 2) { + av_log(avctx, AV_LOG_ERROR, "Screen offset data doesn't fit in frame\n"); + return AVERROR_INVALIDDATA; + } + scr_off = (int16_t)bytestream_get_le16(&c->stream); + } else if ((type & BMV_INTRA) == BMV_INTRA) { + scr_off = -640; + } else { + scr_off = 0; + } + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (decode_bmv_frame(c->stream, pkt->size - (c->stream - pkt->data), c->frame, scr_off)) { + av_log(avctx, AV_LOG_ERROR, "Error decoding frame data\n"); + return AVERROR_INVALIDDATA; + } + + memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); + frame->palette_has_changed = type & BMV_PALETTE; + + outptr = frame->data[0]; + srcptr = c->frame; + + for (i = 0; i < avctx->height; i++) { + memcpy(outptr, srcptr, avctx->width); + srcptr += avctx->width; + outptr += frame->linesize[0]; + } + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return pkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + BMVDecContext * const c = avctx->priv_data; + + c->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + if (avctx->width != SCREEN_WIDE || avctx->height != SCREEN_HIGH) { + av_log(avctx, AV_LOG_ERROR, "Invalid dimension %dx%d\n", avctx->width, avctx->height); + return AVERROR_INVALIDDATA; + } + + c->frame = c->frame_base + 640; + + return 0; +} + +static const int bmv_aud_mults[16] = { + 16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 36, 32 +}; + +static av_cold int bmv_aud_decode_init(AVCodecContext *avctx) +{ + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int blocks = 0, total_blocks, i; + int ret; + int16_t *output_samples; + int scale[2]; + + total_blocks = *buf++; + if (buf_size < total_blocks * 65 + 1) { + av_log(avctx, AV_LOG_ERROR, "expected %d bytes, got %d\n", + total_blocks * 65 + 1, buf_size); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = total_blocks * 32; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + output_samples = (int16_t *)frame->data[0]; + + for (blocks = 0; blocks < total_blocks; blocks++) { + uint8_t code = *buf++; + code = (code >> 1) | (code << 7); + scale[0] = bmv_aud_mults[code & 0xF]; + scale[1] = bmv_aud_mults[code >> 4]; + for (i = 0; i < 32; i++) { + *output_samples++ = av_clip_int16((scale[0] * (int8_t)*buf++) >> 5); + *output_samples++ = av_clip_int16((scale[1] * (int8_t)*buf++) >> 5); + } + } + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_bmv_video_decoder = { + .name = "bmv_video", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BMV_VIDEO, + .priv_data_size = sizeof(BMVDecContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"), +}; + +AVCodec ff_bmv_audio_decoder = { + .name = "bmv_audio", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_BMV_AUDIO, + .init = bmv_aud_decode_init, + .decode = bmv_aud_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), +}; diff --git a/ffmpeg/libavcodec/brender_pix.c b/ffmpeg/libavcodec/brender_pix.c new file mode 100644 index 0000000..b30b882 --- /dev/null +++ b/ffmpeg/libavcodec/brender_pix.c @@ -0,0 +1,219 @@ +/* + * BRender PIX (.pix) image decoder + * Copyright (c) 2012 Aleksi Nurmi + * + * 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 + */ + +/* + * Tested against samples from I-War / Independence War and Defiance. + * If the PIX file does not contain a palette, the + * palette_has_changed property of the AVFrame is set to 0. + */ + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct BRPixHeader { + int format; + unsigned int width, height; +} BRPixHeader; + +static int brpix_decode_header(BRPixHeader *out, GetByteContext *pgb) +{ + unsigned int header_len = bytestream2_get_be32(pgb); + + out->format = bytestream2_get_byte(pgb); + bytestream2_skip(pgb, 2); + out->width = bytestream2_get_be16(pgb); + out->height = bytestream2_get_be16(pgb); + + // the header is at least 11 bytes long; we read the first 7 + if (header_len < 11) { + return 0; + } + + // skip the rest of the header + bytestream2_skip(pgb, header_len-7); + + return 1; +} + +static int brpix_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *frame = data; + + int ret; + GetByteContext gb; + + unsigned int bytes_pp; + + unsigned int magic[4]; + unsigned int chunk_type; + unsigned int data_len; + BRPixHeader hdr; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + magic[0] = bytestream2_get_be32(&gb); + magic[1] = bytestream2_get_be32(&gb); + magic[2] = bytestream2_get_be32(&gb); + magic[3] = bytestream2_get_be32(&gb); + + if (magic[0] != 0x12 || + magic[1] != 0x8 || + magic[2] != 0x2 || + magic[3] != 0x2) { + av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file\n"); + return AVERROR_INVALIDDATA; + } + + chunk_type = bytestream2_get_be32(&gb); + if (chunk_type != 0x3 && chunk_type != 0x3d) { + av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d\n", chunk_type); + return AVERROR_INVALIDDATA; + } + + ret = brpix_decode_header(&hdr, &gb); + if (!ret) { + av_log(avctx, AV_LOG_ERROR, "Invalid header length\n"); + return AVERROR_INVALIDDATA; + } + switch (hdr.format) { + case 3: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + bytes_pp = 1; + break; + case 4: + avctx->pix_fmt = AV_PIX_FMT_RGB555BE; + bytes_pp = 2; + break; + case 5: + avctx->pix_fmt = AV_PIX_FMT_RGB565BE; + bytes_pp = 2; + break; + case 6: + avctx->pix_fmt = AV_PIX_FMT_RGB24; + bytes_pp = 3; + break; + case 7: + avctx->pix_fmt = AV_PIX_FMT_0RGB; + bytes_pp = 4; + break; + case 18: + avctx->pix_fmt = AV_PIX_FMT_GRAY8A; + bytes_pp = 2; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Format %d is not supported\n", + hdr.format); + return AVERROR_PATCHWELCOME; + } + + if (av_image_check_size(hdr.width, hdr.height, 0, avctx) < 0) + return AVERROR_INVALIDDATA; + + if (hdr.width != avctx->width || hdr.height != avctx->height) + avcodec_set_dimensions(avctx, hdr.width, hdr.height); + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + chunk_type = bytestream2_get_be32(&gb); + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && + (chunk_type == 0x3 || chunk_type == 0x3d)) { + BRPixHeader palhdr; + uint32_t *pal_out = (uint32_t *)frame->data[1]; + int i; + + ret = brpix_decode_header(&palhdr, &gb); + if (!ret) { + av_log(avctx, AV_LOG_ERROR, "Invalid palette header length\n"); + return AVERROR_INVALIDDATA; + } + if (palhdr.format != 7) { + av_log(avctx, AV_LOG_ERROR, "Palette is not in 0RGB format\n"); + return AVERROR_INVALIDDATA; + } + + chunk_type = bytestream2_get_be32(&gb); + data_len = bytestream2_get_be32(&gb); + bytestream2_skip(&gb, 8); + if (chunk_type != 0x21 || data_len != 1032 || + bytestream2_get_bytes_left(&gb) < 1032) { + av_log(avctx, AV_LOG_ERROR, "Invalid palette data\n"); + return AVERROR_INVALIDDATA; + } + // convert 0RGB to machine endian format (ARGB32) + for (i = 0; i < 256; ++i) { + bytestream2_skipu(&gb, 1); + *pal_out++ = (0xFFU << 24) | bytestream2_get_be24u(&gb); + } + bytestream2_skip(&gb, 8); + + frame->palette_has_changed = 1; + + chunk_type = bytestream2_get_be32(&gb); + } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + uint32_t *pal_out = (uint32_t *)frame->data[1]; + int i; + + for (i = 0; i < 256; ++i) { + *pal_out++ = (0xFFU << 24) | (i * 0x010101); + } + frame->palette_has_changed = 1; + } + + data_len = bytestream2_get_be32(&gb); + bytestream2_skip(&gb, 8); + + // read the image data to the buffer + { + unsigned int bytes_per_scanline = bytes_pp * hdr.width; + unsigned int bytes_left = bytestream2_get_bytes_left(&gb); + + if (chunk_type != 0x21 || data_len != bytes_left || + bytes_left / bytes_per_scanline < hdr.height) + { + av_log(avctx, AV_LOG_ERROR, "Invalid image data\n"); + return AVERROR_INVALIDDATA; + } + + av_image_copy_plane(frame->data[0], frame->linesize[0], + avpkt->data + bytestream2_tell(&gb), + bytes_per_scanline, + bytes_per_scanline, hdr.height); + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_brender_pix_decoder = { + .name = "brender_pix", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_BRENDER_PIX, + .decode = brpix_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), +}; diff --git a/ffmpeg/libavcodec/bytestream.h b/ffmpeg/libavcodec/bytestream.h new file mode 100644 index 0000000..af7f75b --- /dev/null +++ b/ffmpeg/libavcodec/bytestream.h @@ -0,0 +1,345 @@ +/* + * Bytestream functions + * copyright (c) 2006 Baptiste Coudurier + * Copyright (c) 2012 Aneesh Dogra (lionaneesh) + * + * 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 + */ + +#ifndef AVCODEC_BYTESTREAM_H +#define AVCODEC_BYTESTREAM_H + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +typedef struct GetByteContext { + const uint8_t *buffer, *buffer_end, *buffer_start; +} GetByteContext; + +typedef struct PutByteContext { + uint8_t *buffer, *buffer_end, *buffer_start; + int eof; +} PutByteContext; + +#define DEF(type, name, bytes, read, write) \ +static av_always_inline type bytestream_get_ ## name(const uint8_t **b) \ +{ \ + (*b) += bytes; \ + return read(*b - bytes); \ +} \ +static av_always_inline void bytestream_put_ ## name(uint8_t **b, \ + const type value) \ +{ \ + write(*b, value); \ + (*b) += bytes; \ +} \ +static av_always_inline void bytestream2_put_ ## name ## u(PutByteContext *p, \ + const type value) \ +{ \ + bytestream_put_ ## name(&p->buffer, value); \ +} \ +static av_always_inline void bytestream2_put_ ## name(PutByteContext *p, \ + const type value) \ +{ \ + if (!p->eof && (p->buffer_end - p->buffer >= bytes)) { \ + write(p->buffer, value); \ + p->buffer += bytes; \ + } else \ + p->eof = 1; \ +} \ +static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g) \ +{ \ + return bytestream_get_ ## name(&g->buffer); \ +} \ +static av_always_inline type bytestream2_get_ ## name(GetByteContext *g) \ +{ \ + if (g->buffer_end - g->buffer < bytes) \ + return 0; \ + return bytestream2_get_ ## name ## u(g); \ +} \ +static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g) \ +{ \ + if (g->buffer_end - g->buffer < bytes) \ + return 0; \ + return read(g->buffer); \ +} + +DEF(uint64_t, le64, 8, AV_RL64, AV_WL64) +DEF(unsigned int, le32, 4, AV_RL32, AV_WL32) +DEF(unsigned int, le24, 3, AV_RL24, AV_WL24) +DEF(unsigned int, le16, 2, AV_RL16, AV_WL16) +DEF(uint64_t, be64, 8, AV_RB64, AV_WB64) +DEF(unsigned int, be32, 4, AV_RB32, AV_WB32) +DEF(unsigned int, be24, 3, AV_RB24, AV_WB24) +DEF(unsigned int, be16, 2, AV_RB16, AV_WB16) +DEF(unsigned int, byte, 1, AV_RB8 , AV_WB8) + +#if HAVE_BIGENDIAN +# define bytestream2_get_ne16 bytestream2_get_be16 +# define bytestream2_get_ne24 bytestream2_get_be24 +# define bytestream2_get_ne32 bytestream2_get_be32 +# define bytestream2_get_ne64 bytestream2_get_be64 +# define bytestream2_get_ne16u bytestream2_get_be16u +# define bytestream2_get_ne24u bytestream2_get_be24u +# define bytestream2_get_ne32u bytestream2_get_be32u +# define bytestream2_get_ne64u bytestream2_get_be64u +# define bytestream2_put_ne16 bytestream2_put_be16 +# define bytestream2_put_ne24 bytestream2_put_be24 +# define bytestream2_put_ne32 bytestream2_put_be32 +# define bytestream2_put_ne64 bytestream2_put_be64 +# define bytestream2_peek_ne16 bytestream2_peek_be16 +# define bytestream2_peek_ne24 bytestream2_peek_be24 +# define bytestream2_peek_ne32 bytestream2_peek_be32 +# define bytestream2_peek_ne64 bytestream2_peek_be64 +#else +# define bytestream2_get_ne16 bytestream2_get_le16 +# define bytestream2_get_ne24 bytestream2_get_le24 +# define bytestream2_get_ne32 bytestream2_get_le32 +# define bytestream2_get_ne64 bytestream2_get_le64 +# define bytestream2_get_ne16u bytestream2_get_le16u +# define bytestream2_get_ne24u bytestream2_get_le24u +# define bytestream2_get_ne32u bytestream2_get_le32u +# define bytestream2_get_ne64u bytestream2_get_le64u +# define bytestream2_put_ne16 bytestream2_put_le16 +# define bytestream2_put_ne24 bytestream2_put_le24 +# define bytestream2_put_ne32 bytestream2_put_le32 +# define bytestream2_put_ne64 bytestream2_put_le64 +# define bytestream2_peek_ne16 bytestream2_peek_le16 +# define bytestream2_peek_ne24 bytestream2_peek_le24 +# define bytestream2_peek_ne32 bytestream2_peek_le32 +# define bytestream2_peek_ne64 bytestream2_peek_le64 +#endif + +static av_always_inline void bytestream2_init(GetByteContext *g, + const uint8_t *buf, + int buf_size) +{ + g->buffer = buf; + g->buffer_start = buf; + g->buffer_end = buf + buf_size; +} + +static av_always_inline void bytestream2_init_writer(PutByteContext *p, + uint8_t *buf, + int buf_size) +{ + p->buffer = buf; + p->buffer_start = buf; + p->buffer_end = buf + buf_size; + p->eof = 0; +} + +static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g) +{ + return g->buffer_end - g->buffer; +} + +static av_always_inline unsigned int bytestream2_get_bytes_left_p(PutByteContext *p) +{ + return p->buffer_end - p->buffer; +} + +static av_always_inline void bytestream2_skip(GetByteContext *g, + unsigned int size) +{ + g->buffer += FFMIN(g->buffer_end - g->buffer, size); +} + +static av_always_inline void bytestream2_skipu(GetByteContext *g, + unsigned int size) +{ + g->buffer += size; +} + +static av_always_inline void bytestream2_skip_p(PutByteContext *p, + unsigned int size) +{ + int size2; + if (p->eof) + return; + size2 = FFMIN(p->buffer_end - p->buffer, size); + if (size2 != size) + p->eof = 1; + p->buffer += size2; +} + +static av_always_inline int bytestream2_tell(GetByteContext *g) +{ + return (int)(g->buffer - g->buffer_start); +} + +static av_always_inline int bytestream2_tell_p(PutByteContext *p) +{ + return (int)(p->buffer - p->buffer_start); +} + +static av_always_inline int bytestream2_size(GetByteContext *g) +{ + return (int)(g->buffer_end - g->buffer_start); +} + +static av_always_inline int bytestream2_size_p(PutByteContext *p) +{ + return (int)(p->buffer_end - p->buffer_start); +} + +static av_always_inline int bytestream2_seek(GetByteContext *g, + int offset, + int whence) +{ + switch (whence) { + case SEEK_CUR: + offset = av_clip(offset, -(g->buffer - g->buffer_start), + g->buffer_end - g->buffer); + g->buffer += offset; + break; + case SEEK_END: + offset = av_clip(offset, -(g->buffer_end - g->buffer_start), 0); + g->buffer = g->buffer_end + offset; + break; + case SEEK_SET: + offset = av_clip(offset, 0, g->buffer_end - g->buffer_start); + g->buffer = g->buffer_start + offset; + break; + default: + return AVERROR(EINVAL); + } + return bytestream2_tell(g); +} + +static av_always_inline int bytestream2_seek_p(PutByteContext *p, + int offset, + int whence) +{ + p->eof = 0; + switch (whence) { + case SEEK_CUR: + if (p->buffer_end - p->buffer < offset) + p->eof = 1; + offset = av_clip(offset, -(p->buffer - p->buffer_start), + p->buffer_end - p->buffer); + p->buffer += offset; + break; + case SEEK_END: + if (offset > 0) + p->eof = 1; + offset = av_clip(offset, -(p->buffer_end - p->buffer_start), 0); + p->buffer = p->buffer_end + offset; + break; + case SEEK_SET: + if (p->buffer_end - p->buffer_start < offset) + p->eof = 1; + offset = av_clip(offset, 0, p->buffer_end - p->buffer_start); + p->buffer = p->buffer_start + offset; + break; + default: + return AVERROR(EINVAL); + } + return bytestream2_tell_p(p); +} + +static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, + uint8_t *dst, + unsigned int size) +{ + int size2 = FFMIN(g->buffer_end - g->buffer, size); + memcpy(dst, g->buffer, size2); + g->buffer += size2; + return size2; +} + +static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, + uint8_t *dst, + unsigned int size) +{ + memcpy(dst, g->buffer, size); + g->buffer += size; + return size; +} + +static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, + const uint8_t *src, + unsigned int size) +{ + int size2; + if (p->eof) + return 0; + size2 = FFMIN(p->buffer_end - p->buffer, size); + if (size2 != size) + p->eof = 1; + memcpy(p->buffer, src, size2); + p->buffer += size2; + return size2; +} + +static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p, + const uint8_t *src, + unsigned int size) +{ + memcpy(p->buffer, src, size); + p->buffer += size; + return size; +} + +static av_always_inline void bytestream2_set_buffer(PutByteContext *p, + const uint8_t c, + unsigned int size) +{ + int size2; + if (p->eof) + return; + size2 = FFMIN(p->buffer_end - p->buffer, size); + if (size2 != size) + p->eof = 1; + memset(p->buffer, c, size2); + p->buffer += size2; +} + +static av_always_inline void bytestream2_set_bufferu(PutByteContext *p, + const uint8_t c, + unsigned int size) +{ + memset(p->buffer, c, size); + p->buffer += size; +} + +static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) +{ + return p->eof; +} + +static av_always_inline unsigned int bytestream_get_buffer(const uint8_t **b, + uint8_t *dst, + unsigned int size) +{ + memcpy(dst, *b, size); + (*b) += size; + return size; +} + +static av_always_inline void bytestream_put_buffer(uint8_t **b, + const uint8_t *src, + unsigned int size) +{ + memcpy(*b, src, size); + (*b) += size; +} + +#endif /* AVCODEC_BYTESTREAM_H */ diff --git a/ffmpeg/libavcodec/c93.c b/ffmpeg/libavcodec/c93.c new file mode 100644 index 0000000..9aaa3ee --- /dev/null +++ b/ffmpeg/libavcodec/c93.c @@ -0,0 +1,256 @@ +/* + * Interplay C93 video decoder + * Copyright (c) 2007 Anssi Hannula + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct { + AVFrame pictures[2]; + int currentpic; +} C93DecoderContext; + +typedef enum { + C93_8X8_FROM_PREV = 0x02, + C93_4X4_FROM_PREV = 0x06, + C93_4X4_FROM_CURR = 0x07, + C93_8X8_2COLOR = 0x08, + C93_4X4_2COLOR = 0x0A, + C93_4X4_4COLOR_GRP = 0x0B, + C93_4X4_4COLOR = 0x0D, + C93_NOOP = 0x0E, + C93_8X8_INTRA = 0x0F, +} C93BlockType; + +#define WIDTH 320 +#define HEIGHT 192 + +#define C93_HAS_PALETTE 0x01 +#define C93_FIRST_FRAME 0x02 + +static av_cold int decode_init(AVCodecContext *avctx) +{ + C93DecoderContext *s = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + avcodec_get_frame_defaults(&s->pictures[0]); + avcodec_get_frame_defaults(&s->pictures[1]); + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + C93DecoderContext * const c93 = avctx->priv_data; + + av_frame_unref(&c93->pictures[0]); + av_frame_unref(&c93->pictures[1]); + + return 0; +} + +static inline int copy_block(AVCodecContext *avctx, uint8_t *to, + uint8_t *from, int offset, int height, int stride) +{ + int i; + int width = height; + int from_x = offset % WIDTH; + int from_y = offset / WIDTH; + int overflow = from_x + width - WIDTH; + + if (!from) { + /* silently ignoring predictive blocks in first frame */ + return 0; + } + + if (from_y + height > HEIGHT) { + av_log(avctx, AV_LOG_ERROR, "invalid offset %d during C93 decoding\n", + offset); + return AVERROR_INVALIDDATA; + } + + if (overflow > 0) { + width -= overflow; + for (i = 0; i < height; i++) { + memcpy(&to[i*stride+width], &from[(from_y+i)*stride], overflow); + } + } + + for (i = 0; i < height; i++) { + memcpy(&to[i*stride], &from[(from_y+i)*stride+from_x], width); + } + + return 0; +} + +static inline void draw_n_color(uint8_t *out, int stride, int width, + int height, int bpp, uint8_t cols[4], uint8_t grps[4], uint32_t col) +{ + int x, y; + for (y = 0; y < height; y++) { + if (grps) + cols[0] = grps[3 * (y >> 1)]; + for (x = 0; x < width; x++) { + if (grps) + cols[1]= grps[(x >> 1) + 1]; + out[x + y*stride] = cols[col & ((1 << bpp) - 1)]; + col >>= bpp; + } + } +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + C93DecoderContext * const c93 = avctx->priv_data; + AVFrame * const newpic = &c93->pictures[c93->currentpic]; + AVFrame * const oldpic = &c93->pictures[c93->currentpic^1]; + GetByteContext gb; + uint8_t *out; + int stride, ret, i, x, y, b, bt = 0; + + c93->currentpic ^= 1; + + if ((ret = ff_reget_buffer(avctx, newpic)) < 0) + return ret; + + stride = newpic->linesize[0]; + + bytestream2_init(&gb, buf, buf_size); + b = bytestream2_get_byte(&gb); + if (b & C93_FIRST_FRAME) { + newpic->pict_type = AV_PICTURE_TYPE_I; + newpic->key_frame = 1; + } else { + newpic->pict_type = AV_PICTURE_TYPE_P; + newpic->key_frame = 0; + } + + for (y = 0; y < HEIGHT; y += 8) { + out = newpic->data[0] + y * stride; + for (x = 0; x < WIDTH; x += 8) { + uint8_t *copy_from = oldpic->data[0]; + unsigned int offset, j; + uint8_t cols[4], grps[4]; + C93BlockType block_type; + + if (!bt) + bt = bytestream2_get_byte(&gb); + + block_type= bt & 0x0F; + switch (block_type) { + case C93_8X8_FROM_PREV: + offset = bytestream2_get_le16(&gb); + if ((ret = copy_block(avctx, out, copy_from, offset, 8, stride)) < 0) + return ret; + break; + + case C93_4X4_FROM_CURR: + copy_from = newpic->data[0]; + case C93_4X4_FROM_PREV: + for (j = 0; j < 8; j += 4) { + for (i = 0; i < 8; i += 4) { + offset = bytestream2_get_le16(&gb); + if ((ret = copy_block(avctx, &out[j*stride+i], + copy_from, offset, 4, stride)) < 0) + return ret; + } + } + break; + + case C93_8X8_2COLOR: + bytestream2_get_buffer(&gb, cols, 2); + for (i = 0; i < 8; i++) { + draw_n_color(out + i*stride, stride, 8, 1, 1, cols, + NULL, bytestream2_get_byte(&gb)); + } + + break; + + case C93_4X4_2COLOR: + case C93_4X4_4COLOR: + case C93_4X4_4COLOR_GRP: + for (j = 0; j < 8; j += 4) { + for (i = 0; i < 8; i += 4) { + if (block_type == C93_4X4_2COLOR) { + bytestream2_get_buffer(&gb, cols, 2); + draw_n_color(out + i + j*stride, stride, 4, 4, + 1, cols, NULL, bytestream2_get_le16(&gb)); + } else if (block_type == C93_4X4_4COLOR) { + bytestream2_get_buffer(&gb, cols, 4); + draw_n_color(out + i + j*stride, stride, 4, 4, + 2, cols, NULL, bytestream2_get_le32(&gb)); + } else { + bytestream2_get_buffer(&gb, grps, 4); + draw_n_color(out + i + j*stride, stride, 4, 4, + 1, cols, grps, bytestream2_get_le16(&gb)); + } + } + } + break; + + case C93_NOOP: + break; + + case C93_8X8_INTRA: + for (j = 0; j < 8; j++) + bytestream2_get_buffer(&gb, out + j*stride, 8); + break; + + default: + av_log(avctx, AV_LOG_ERROR, "unexpected type %x at %dx%d\n", + block_type, x, y); + return AVERROR_INVALIDDATA; + } + bt >>= 4; + out += 8; + } + } + + if (b & C93_HAS_PALETTE) { + uint32_t *palette = (uint32_t *) newpic->data[1]; + for (i = 0; i < 256; i++) { + palette[i] = 0xFFU << 24 | bytestream2_get_be24(&gb); + } + newpic->palette_has_changed = 1; + } else { + if (oldpic->data[1]) + memcpy(newpic->data[1], oldpic->data[1], 256 * 4); + } + + if ((ret = av_frame_ref(data, newpic)) < 0) + return ret; + *got_frame = 1; + + return buf_size; +} + +AVCodec ff_c93_decoder = { + .name = "c93", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_C93, + .priv_data_size = sizeof(C93DecoderContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), +}; diff --git a/ffmpeg/libavcodec/cabac.c b/ffmpeg/libavcodec/cabac.c new file mode 100644 index 0000000..187b7dc --- /dev/null +++ b/ffmpeg/libavcodec/cabac.c @@ -0,0 +1,319 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * Context Adaptive Binary Arithmetic Coder. + */ + +#include + +#include "libavutil/common.h" +#include "get_bits.h" +#include "cabac.h" +#include "cabac_functions.h" + +uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63] = { + 9,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +static const uint8_t lps_range[64][4]= { +{128,176,208,240}, {128,167,197,227}, {128,158,187,216}, {123,150,178,205}, +{116,142,169,195}, {111,135,160,185}, {105,128,152,175}, {100,122,144,166}, +{ 95,116,137,158}, { 90,110,130,150}, { 85,104,123,142}, { 81, 99,117,135}, +{ 77, 94,111,128}, { 73, 89,105,122}, { 69, 85,100,116}, { 66, 80, 95,110}, +{ 62, 76, 90,104}, { 59, 72, 86, 99}, { 56, 69, 81, 94}, { 53, 65, 77, 89}, +{ 51, 62, 73, 85}, { 48, 59, 69, 80}, { 46, 56, 66, 76}, { 43, 53, 63, 72}, +{ 41, 50, 59, 69}, { 39, 48, 56, 65}, { 37, 45, 54, 62}, { 35, 43, 51, 59}, +{ 33, 41, 48, 56}, { 32, 39, 46, 53}, { 30, 37, 43, 50}, { 29, 35, 41, 48}, +{ 27, 33, 39, 45}, { 26, 31, 37, 43}, { 24, 30, 35, 41}, { 23, 28, 33, 39}, +{ 22, 27, 32, 37}, { 21, 26, 30, 35}, { 20, 24, 29, 33}, { 19, 23, 27, 31}, +{ 18, 22, 26, 30}, { 17, 21, 25, 28}, { 16, 20, 23, 27}, { 15, 19, 22, 25}, +{ 14, 18, 21, 24}, { 14, 17, 20, 23}, { 13, 16, 19, 22}, { 12, 15, 18, 21}, +{ 12, 14, 17, 20}, { 11, 14, 16, 19}, { 11, 13, 15, 18}, { 10, 12, 15, 17}, +{ 10, 12, 14, 16}, { 9, 11, 13, 15}, { 9, 11, 12, 14}, { 8, 10, 12, 14}, +{ 8, 9, 11, 13}, { 7, 9, 11, 12}, { 7, 9, 10, 12}, { 7, 8, 10, 11}, +{ 6, 8, 9, 11}, { 6, 7, 9, 10}, { 6, 7, 8, 9}, { 2, 2, 2, 2}, +}; + +static uint8_t h264_lps_state[2*64]; +static uint8_t h264_mps_state[2*64]; + +static const uint8_t mps_state[64]= { + 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,32, + 33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48, + 49,50,51,52,53,54,55,56, + 57,58,59,60,61,62,62,63, +}; + +static const uint8_t lps_state[64]= { + 0, 0, 1, 2, 2, 4, 4, 5, + 6, 7, 8, 9, 9,11,11,12, + 13,13,15,15,16,16,18,18, + 19,19,21,21,22,22,23,24, + 24,25,26,26,27,27,28,29, + 29,30,30,30,31,32,32,33, + 33,33,34,34,35,35,35,36, + 36,36,37,37,37,38,38,63, +}; + +static const uint8_t last_coeff_flag_offset_8x8[63] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8 +}; + +/** + * + * @param buf_size size of buf in bits + */ +void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ + init_put_bits(&c->pb, buf, buf_size); + + c->low= 0; + c->range= 0x1FE; + c->outstanding_count= 0; + c->pb.bit_left++; //avoids firstBitFlag +} + +/** + * + * @param buf_size size of buf in bits + */ +void ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){ + c->bytestream_start= + c->bytestream= buf; + c->bytestream_end= buf + buf_size; + +#if CABAC_BITS == 16 + c->low = (*c->bytestream++)<<18; + c->low+= (*c->bytestream++)<<10; +#else + c->low = (*c->bytestream++)<<10; +#endif + c->low+= ((*c->bytestream++)<<2) + 2; + c->range= 0x1FE; +} + +void ff_init_cabac_states(void) +{ + int i, j; + + for(i=0; i<64; i++){ + for(j=0; j<4; j++){ //FIXME check if this is worth the 1 shift we save + ff_h264_lps_range[j*2*64+2*i+0]= + ff_h264_lps_range[j*2*64+2*i+1]= lps_range[i][j]; + } + + ff_h264_mlps_state[128+2*i+0]= + h264_mps_state[2 * i + 0] = 2 * mps_state[i] + 0; + ff_h264_mlps_state[128+2*i+1]= + h264_mps_state[2 * i + 1] = 2 * mps_state[i] + 1; + + if( i ){ + h264_lps_state[2*i+0]= + ff_h264_mlps_state[128-2*i-1]= 2*lps_state[i]+0; + h264_lps_state[2*i+1]= + ff_h264_mlps_state[128-2*i-2]= 2*lps_state[i]+1; + }else{ + h264_lps_state[2*i+0]= + ff_h264_mlps_state[128-2*i-1]= 1; + h264_lps_state[2*i+1]= + ff_h264_mlps_state[128-2*i-2]= 0; + } + } + for(i=0; i< 63; i++){ + ff_h264_last_coeff_flag_offset_8x8[i] = last_coeff_flag_offset_8x8[i]; + } +} + +#ifdef TEST +#define SIZE 10240 + +#include "libavutil/lfg.h" +#include "avcodec.h" +#include "cabac.h" + +static inline void put_cabac_bit(CABACContext *c, int b){ + put_bits(&c->pb, 1, b); + for(;c->outstanding_count; c->outstanding_count--){ + put_bits(&c->pb, 1, 1-b); + } +} + +static inline void renorm_cabac_encoder(CABACContext *c){ + while(c->range < 0x100){ + //FIXME optimize + if(c->low<0x100){ + put_cabac_bit(c, 0); + }else if(c->low<0x200){ + c->outstanding_count++; + c->low -= 0x100; + }else{ + put_cabac_bit(c, 1); + c->low -= 0x200; + } + + c->range+= c->range; + c->low += c->low; + } +} + +static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ + int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state]; + + if(bit == ((*state)&1)){ + c->range -= RangeLPS; + *state = h264_mps_state[*state]; + }else{ + c->low += c->range - RangeLPS; + c->range = RangeLPS; + *state= h264_lps_state[*state]; + } + + renorm_cabac_encoder(c); +} + +/** + * @param bit 0 -> write zero bit, !=0 write one bit + */ +static void put_cabac_bypass(CABACContext *c, int bit){ + c->low += c->low; + + if(bit){ + c->low += c->range; + } +//FIXME optimize + if(c->low<0x200){ + put_cabac_bit(c, 0); + }else if(c->low<0x400){ + c->outstanding_count++; + c->low -= 0x200; + }else{ + put_cabac_bit(c, 1); + c->low -= 0x400; + } +} + +/** + * + * @return the number of bytes written + */ +static int put_cabac_terminate(CABACContext *c, int bit){ + c->range -= 2; + + if(!bit){ + renorm_cabac_encoder(c); + }else{ + c->low += c->range; + c->range= 2; + + renorm_cabac_encoder(c); + + av_assert0(c->low <= 0x1FF); + put_cabac_bit(c, c->low>>9); + put_bits(&c->pb, 2, ((c->low>>7)&3)|1); + + flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong + } + + return (put_bits_count(&c->pb)+7)>>3; +} + +int main(void){ + CABACContext c; + uint8_t b[9*SIZE]; + uint8_t r[9*SIZE]; + int i; + uint8_t state[10]= {0}; + AVLFG prng; + + av_lfg_init(&prng, 1); + ff_init_cabac_encoder(&c, b, SIZE); + ff_init_cabac_states(); + + for(i=0; i>8)&1; + } + + for(i=0; i + * + * 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 + */ + +/** + * @file + * Context Adaptive Binary Arithmetic Coder. + */ + +#ifndef AVCODEC_CABAC_H +#define AVCODEC_CABAC_H + +#include + +#include "put_bits.h" + +#define H264_NORM_SHIFT_OFFSET 0 +#define H264_LPS_RANGE_OFFSET 512 +#define H264_MLPS_STATE_OFFSET 1024 +#define H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET 1280 + +#define CABAC_BITS 16 +#define CABAC_MASK ((1< + * + * 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 + */ + +/** + * @file + * Context Adaptive Binary Arithmetic Coder inline functions + */ + +#ifndef AVCODEC_CABAC_FUNCTIONS_H +#define AVCODEC_CABAC_FUNCTIONS_H + +#include + +#include "cabac.h" +#include "config.h" + +#if ARCH_X86 +# include "x86/cabac.h" +#endif + +extern uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63]; +static uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET; +static uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET; +static uint8_t * const ff_h264_mlps_state = ff_h264_cabac_tables + H264_MLPS_STATE_OFFSET; +static uint8_t * const ff_h264_last_coeff_flag_offset_8x8 = ff_h264_cabac_tables + H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET; + +static void refill(CABACContext *c){ +#if CABAC_BITS == 16 + c->low+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); +#else + c->low+= c->bytestream[0]<<1; +#endif + c->low -= CABAC_MASK; + c->bytestream += CABAC_BITS / 8; +} + +static inline void renorm_cabac_decoder_once(CABACContext *c){ + int shift= (uint32_t)(c->range - 0x100)>>31; + c->range<<= shift; + c->low <<= shift; + if(!(c->low & CABAC_MASK)) + refill(c); +} + +#ifndef get_cabac_inline +static void refill2(CABACContext *c){ + int i, x; + + x= c->low ^ (c->low-1); + i= 7 - ff_h264_norm_shift[x>>(CABAC_BITS-1)]; + + x= -CABAC_MASK; + +#if CABAC_BITS == 16 + x+= (c->bytestream[0]<<9) + (c->bytestream[1]<<1); +#else + x+= c->bytestream[0]<<1; +#endif + + c->low += x<bytestream += CABAC_BITS/8; +} + +static av_always_inline int get_cabac_inline(CABACContext *c, uint8_t * const state){ + int s = *state; + int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + s]; + int bit, lps_mask; + + c->range -= RangeLPS; + lps_mask= ((c->range<<(CABAC_BITS+1)) - c->low)>>31; + + c->low -= (c->range<<(CABAC_BITS+1)) & lps_mask; + c->range += (RangeLPS - c->range) & lps_mask; + + s^=lps_mask; + *state= (ff_h264_mlps_state+128)[s]; + bit= s&1; + + lps_mask= ff_h264_norm_shift[c->range]; + c->range<<= lps_mask; + c->low <<= lps_mask; + if(!(c->low & CABAC_MASK)) + refill2(c); + return bit; +} +#endif + +static int av_noinline av_unused get_cabac_noinline(CABACContext *c, uint8_t * const state){ + return get_cabac_inline(c,state); +} + +static int av_unused get_cabac(CABACContext *c, uint8_t * const state){ + return get_cabac_inline(c,state); +} + +static int av_unused get_cabac_bypass(CABACContext *c){ + int range; + c->low += c->low; + + if(!(c->low & CABAC_MASK)) + refill(c); + + range= c->range<<(CABAC_BITS+1); + if(c->low < range){ + return 0; + }else{ + c->low -= range; + return 1; + } +} + + +#ifndef get_cabac_bypass_sign +static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){ + int range, mask; + c->low += c->low; + + if(!(c->low & CABAC_MASK)) + refill(c); + + range= c->range<<(CABAC_BITS+1); + c->low -= range; + mask= c->low >> 31; + range &= mask; + c->low += range; + return (val^mask)-mask; +} +#endif + +/** + * + * @return the number of bytes read or 0 if no end + */ +static int av_unused get_cabac_terminate(CABACContext *c){ + c->range -= 2; + if(c->low < c->range<<(CABAC_BITS+1)){ + renorm_cabac_decoder_once(c); + return 0; + }else{ + return c->bytestream - c->bytestream_start; + } +} + +#endif /* AVCODEC_CABAC_FUNCTIONS_H */ diff --git a/ffmpeg/libavcodec/cavs.c b/ffmpeg/libavcodec/cavs.c new file mode 100644 index 0000000..dffd6cc --- /dev/null +++ b/ffmpeg/libavcodec/cavs.c @@ -0,0 +1,790 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 + */ + +/** + * @file + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder + * @author Stefan Gehrer + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "golomb.h" +#include "h264chroma.h" +#include "mathops.h" +#include "cavs.h" + +static const uint8_t alpha_tab[64] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 20, + 22, 24, 26, 28, 30, 33, 33, 35, 35, 36, 37, 37, 39, 39, 42, 44, + 46, 48, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 +}; + +static const uint8_t beta_tab[64] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 24, 25, 25, 26, 27 +}; + +static const uint8_t tc_tab[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9 +}; + +/** mark block as unavailable, i.e. out of picture + or not yet decoded */ +static const cavs_vector un_mv = { 0, 0, 1, NOT_AVAIL }; + +static const int8_t left_modifier_l[8] = { 0, -1, 6, -1, -1, 7, 6, 7 }; +static const int8_t top_modifier_l[8] = { -1, 1, 5, -1, -1, 5, 7, 7 }; +static const int8_t left_modifier_c[7] = { 5, -1, 2, -1, 6, 5, 6 }; +static const int8_t top_modifier_c[7] = { 4, 1, -1, -1, 4, 6, 6 }; + +/***************************************************************************** + * + * in-loop deblocking filter + * + ****************************************************************************/ + +static inline int get_bs(cavs_vector *mvP, cavs_vector *mvQ, int b) +{ + if ((mvP->ref == REF_INTRA) || (mvQ->ref == REF_INTRA)) + return 2; + if ((abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4)) + return 1; + if (b) { + mvP += MV_BWD_OFFS; + mvQ += MV_BWD_OFFS; + if ((abs(mvP->x - mvQ->x) >= 4) || (abs(mvP->y - mvQ->y) >= 4)) + return 1; + } else { + if (mvP->ref != mvQ->ref) + return 1; + } + return 0; +} + +#define SET_PARAMS \ + alpha = alpha_tab[av_clip(qp_avg + h->alpha_offset, 0, 63)]; \ + beta = beta_tab[av_clip(qp_avg + h->beta_offset, 0, 63)]; \ + tc = tc_tab[av_clip(qp_avg + h->alpha_offset, 0, 63)]; + +/** + * in-loop deblocking filter for a single macroblock + * + * boundary strength (bs) mapping: + * + * --4---5-- + * 0 2 | + * | 6 | 7 | + * 1 3 | + * --------- + * + */ +void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type) +{ + uint8_t bs[8]; + int qp_avg, alpha, beta, tc; + int i; + + /* save un-deblocked lines */ + h->topleft_border_y = h->top_border_y[h->mbx * 16 + 15]; + h->topleft_border_u = h->top_border_u[h->mbx * 10 + 8]; + h->topleft_border_v = h->top_border_v[h->mbx * 10 + 8]; + memcpy(&h->top_border_y[h->mbx * 16], h->cy + 15 * h->l_stride, 16); + memcpy(&h->top_border_u[h->mbx * 10 + 1], h->cu + 7 * h->c_stride, 8); + memcpy(&h->top_border_v[h->mbx * 10 + 1], h->cv + 7 * h->c_stride, 8); + for (i = 0; i < 8; i++) { + h->left_border_y[i * 2 + 1] = *(h->cy + 15 + (i * 2 + 0) * h->l_stride); + h->left_border_y[i * 2 + 2] = *(h->cy + 15 + (i * 2 + 1) * h->l_stride); + h->left_border_u[i + 1] = *(h->cu + 7 + i * h->c_stride); + h->left_border_v[i + 1] = *(h->cv + 7 + i * h->c_stride); + } + if (!h->loop_filter_disable) { + /* determine bs */ + if (mb_type == I_8X8) + memset(bs, 2, 8); + else{ + memset(bs, 0, 8); + if (ff_cavs_partition_flags[mb_type] & SPLITV) { + bs[2] = get_bs(&h->mv[MV_FWD_X0], &h->mv[MV_FWD_X1], mb_type > P_8X8); + bs[3] = get_bs(&h->mv[MV_FWD_X2], &h->mv[MV_FWD_X3], mb_type > P_8X8); + } + if (ff_cavs_partition_flags[mb_type] & SPLITH) { + bs[6] = get_bs(&h->mv[MV_FWD_X0], &h->mv[MV_FWD_X2], mb_type > P_8X8); + bs[7] = get_bs(&h->mv[MV_FWD_X1], &h->mv[MV_FWD_X3], mb_type > P_8X8); + } + bs[0] = get_bs(&h->mv[MV_FWD_A1], &h->mv[MV_FWD_X0], mb_type > P_8X8); + bs[1] = get_bs(&h->mv[MV_FWD_A3], &h->mv[MV_FWD_X2], mb_type > P_8X8); + bs[4] = get_bs(&h->mv[MV_FWD_B2], &h->mv[MV_FWD_X0], mb_type > P_8X8); + bs[5] = get_bs(&h->mv[MV_FWD_B3], &h->mv[MV_FWD_X1], mb_type > P_8X8); + } + if (AV_RN64(bs)) { + if (h->flags & A_AVAIL) { + qp_avg = (h->qp + h->left_qp + 1) >> 1; + SET_PARAMS; + h->cdsp.cavs_filter_lv(h->cy, h->l_stride, alpha, beta, tc, bs[0], bs[1]); + h->cdsp.cavs_filter_cv(h->cu, h->c_stride, alpha, beta, tc, bs[0], bs[1]); + h->cdsp.cavs_filter_cv(h->cv, h->c_stride, alpha, beta, tc, bs[0], bs[1]); + } + qp_avg = h->qp; + SET_PARAMS; + h->cdsp.cavs_filter_lv(h->cy + 8, h->l_stride, alpha, beta, tc, bs[2], bs[3]); + h->cdsp.cavs_filter_lh(h->cy + 8 * h->l_stride, h->l_stride, alpha, beta, tc, bs[6], bs[7]); + + if (h->flags & B_AVAIL) { + qp_avg = (h->qp + h->top_qp[h->mbx] + 1) >> 1; + SET_PARAMS; + h->cdsp.cavs_filter_lh(h->cy, h->l_stride, alpha, beta, tc, bs[4], bs[5]); + h->cdsp.cavs_filter_ch(h->cu, h->c_stride, alpha, beta, tc, bs[4], bs[5]); + h->cdsp.cavs_filter_ch(h->cv, h->c_stride, alpha, beta, tc, bs[4], bs[5]); + } + } + } + h->left_qp = h->qp; + h->top_qp[h->mbx] = h->qp; +} + +#undef SET_PARAMS + +/***************************************************************************** + * + * spatial intra prediction + * + ****************************************************************************/ + +void ff_cavs_load_intra_pred_luma(AVSContext *h, uint8_t *top, + uint8_t **left, int block) +{ + int i; + + switch (block) { + case 0: + *left = h->left_border_y; + h->left_border_y[0] = h->left_border_y[1]; + memset(&h->left_border_y[17], h->left_border_y[16], 9); + memcpy(&top[1], &h->top_border_y[h->mbx * 16], 16); + top[17] = top[16]; + top[0] = top[1]; + if ((h->flags & A_AVAIL) && (h->flags & B_AVAIL)) + h->left_border_y[0] = top[0] = h->topleft_border_y; + break; + case 1: + *left = h->intern_border_y; + for (i = 0; i < 8; i++) + h->intern_border_y[i + 1] = *(h->cy + 7 + i * h->l_stride); + memset(&h->intern_border_y[9], h->intern_border_y[8], 9); + h->intern_border_y[0] = h->intern_border_y[1]; + memcpy(&top[1], &h->top_border_y[h->mbx * 16 + 8], 8); + if (h->flags & C_AVAIL) + memcpy(&top[9], &h->top_border_y[(h->mbx + 1) * 16], 8); + else + memset(&top[9], top[8], 9); + top[17] = top[16]; + top[0] = top[1]; + if (h->flags & B_AVAIL) + h->intern_border_y[0] = top[0] = h->top_border_y[h->mbx * 16 + 7]; + break; + case 2: + *left = &h->left_border_y[8]; + memcpy(&top[1], h->cy + 7 * h->l_stride, 16); + top[17] = top[16]; + top[0] = top[1]; + if (h->flags & A_AVAIL) + top[0] = h->left_border_y[8]; + break; + case 3: + *left = &h->intern_border_y[8]; + for (i = 0; i < 8; i++) + h->intern_border_y[i + 9] = *(h->cy + 7 + (i + 8) * h->l_stride); + memset(&h->intern_border_y[17], h->intern_border_y[16], 9); + memcpy(&top[0], h->cy + 7 + 7 * h->l_stride, 9); + memset(&top[9], top[8], 9); + break; + } +} + +void ff_cavs_load_intra_pred_chroma(AVSContext *h) +{ + /* extend borders by one pixel */ + h->left_border_u[9] = h->left_border_u[8]; + h->left_border_v[9] = h->left_border_v[8]; + h->top_border_u[h->mbx * 10 + 9] = h->top_border_u[h->mbx * 10 + 8]; + h->top_border_v[h->mbx * 10 + 9] = h->top_border_v[h->mbx * 10 + 8]; + if (h->mbx && h->mby) { + h->top_border_u[h->mbx * 10] = h->left_border_u[0] = h->topleft_border_u; + h->top_border_v[h->mbx * 10] = h->left_border_v[0] = h->topleft_border_v; + } else { + h->left_border_u[0] = h->left_border_u[1]; + h->left_border_v[0] = h->left_border_v[1]; + h->top_border_u[h->mbx * 10] = h->top_border_u[h->mbx * 10 + 1]; + h->top_border_v[h->mbx * 10] = h->top_border_v[h->mbx * 10 + 1]; + } +} + +static void intra_pred_vert(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int y; + uint64_t a = AV_RN64(&top[1]); + for (y = 0; y < 8; y++) { + *((uint64_t *)(d + y * stride)) = a; + } +} + +static void intra_pred_horiz(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int y; + uint64_t a; + for (y = 0; y < 8; y++) { + a = left[y + 1] * 0x0101010101010101ULL; + *((uint64_t *)(d + y * stride)) = a; + } +} + +static void intra_pred_dc_128(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int y; + uint64_t a = 0x8080808080808080ULL; + for (y = 0; y < 8; y++) + *((uint64_t *)(d + y * stride)) = a; +} + +static void intra_pred_plane(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int x, y, ia; + int ih = 0; + int iv = 0; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + for (x = 0; x < 4; x++) { + ih += (x + 1) * (top [5 + x] - top [3 - x]); + iv += (x + 1) * (left[5 + x] - left[3 - x]); + } + ia = (top[8] + left[8]) << 4; + ih = (17 * ih + 16) >> 5; + iv = (17 * iv + 16) >> 5; + for (y = 0; y < 8; y++) + for (x = 0; x < 8; x++) + d[y * stride + x] = cm[(ia + (x - 3) * ih + (y - 3) * iv + 16) >> 5]; +} + +#define LOWPASS(ARRAY,INDEX) \ + ((ARRAY[(INDEX) - 1] + 2 * ARRAY[(INDEX)] + ARRAY[(INDEX) + 1] + 2) >> 2) + +static void intra_pred_lp(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int x, y; + for (y = 0; y < 8; y++) + for (x = 0; x < 8; x++) + d[y * stride + x] = (LOWPASS(top, x + 1) + LOWPASS(left, y + 1)) >> 1; +} + +static void intra_pred_down_left(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int x, y; + for (y = 0; y < 8; y++) + for (x = 0; x < 8; x++) + d[y * stride + x] = (LOWPASS(top, x + y + 2) + LOWPASS(left, x + y + 2)) >> 1; +} + +static void intra_pred_down_right(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int x, y; + for (y = 0; y < 8; y++) + for (x = 0; x < 8; x++) + if (x == y) + d[y * stride + x] = (left[1] + 2 * top[0] + top[1] + 2) >> 2; + else if (x > y) + d[y * stride + x] = LOWPASS(top, x - y); + else + d[y * stride + x] = LOWPASS(left, y - x); +} + +static void intra_pred_lp_left(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int x, y; + for (y = 0; y < 8; y++) + for (x = 0; x < 8; x++) + d[y * stride + x] = LOWPASS(left, y + 1); +} + +static void intra_pred_lp_top(uint8_t *d,uint8_t *top,uint8_t *left,int stride) +{ + int x, y; + for (y = 0; y < 8; y++) + for (x = 0; x < 8; x++) + d[y * stride + x] = LOWPASS(top, x + 1); +} + +#undef LOWPASS + +static inline void modify_pred(const int8_t *mod_table, int *mode) +{ + *mode = mod_table[*mode]; + if (*mode < 0) { + av_log(NULL, AV_LOG_ERROR, "Illegal intra prediction mode\n"); + *mode = 0; + } +} + +void ff_cavs_modify_mb_i(AVSContext *h, int *pred_mode_uv) +{ + /* save pred modes before they get modified */ + h->pred_mode_Y[3] = h->pred_mode_Y[5]; + h->pred_mode_Y[6] = h->pred_mode_Y[8]; + h->top_pred_Y[h->mbx * 2 + 0] = h->pred_mode_Y[7]; + h->top_pred_Y[h->mbx * 2 + 1] = h->pred_mode_Y[8]; + + /* modify pred modes according to availability of neighbour samples */ + if (!(h->flags & A_AVAIL)) { + modify_pred(left_modifier_l, &h->pred_mode_Y[4]); + modify_pred(left_modifier_l, &h->pred_mode_Y[7]); + modify_pred(left_modifier_c, pred_mode_uv); + } + if (!(h->flags & B_AVAIL)) { + modify_pred(top_modifier_l, &h->pred_mode_Y[4]); + modify_pred(top_modifier_l, &h->pred_mode_Y[5]); + modify_pred(top_modifier_c, pred_mode_uv); + } +} + +/***************************************************************************** + * + * motion compensation + * + ****************************************************************************/ + +static inline void mc_dir_part(AVSContext *h, AVFrame *pic, + int chroma_height,int delta,int list,uint8_t *dest_y, + uint8_t *dest_cb,uint8_t *dest_cr,int src_x_offset, + int src_y_offset,qpel_mc_func *qpix_op, + h264_chroma_mc_func chroma_op,cavs_vector *mv) +{ + const int mx= mv->x + src_x_offset*8; + const int my= mv->y + src_y_offset*8; + const int luma_xy= (mx&3) + ((my&3)<<2); + uint8_t * src_y = pic->data[0] + (mx >> 2) + (my >> 2) * h->l_stride; + uint8_t * src_cb = pic->data[1] + (mx >> 3) + (my >> 3) * h->c_stride; + uint8_t * src_cr = pic->data[2] + (mx >> 3) + (my >> 3) * h->c_stride; + int extra_width = 0; + int extra_height= extra_width; + int emu=0; + const int full_mx= mx>>2; + const int full_my= my>>2; + const int pic_width = 16*h->mb_width; + const int pic_height = 16*h->mb_height; + + if (!pic->data[0]) + return; + if(mx&7) extra_width -= 3; + if(my&7) extra_height -= 3; + + if( full_mx < 0-extra_width + || full_my < 0-extra_height + || full_mx + 16/*FIXME*/ > pic_width + extra_width + || full_my + 16/*FIXME*/ > pic_height + extra_height){ + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_y - 2 - 2*h->l_stride, h->l_stride, + 16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height); + src_y= h->edge_emu_buffer + 2 + 2*h->l_stride; + emu=1; + } + + qpix_op[luma_xy](dest_y, src_y, h->l_stride); //FIXME try variable height perhaps? + + if(emu){ + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cb, h->c_stride, + 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1); + src_cb= h->edge_emu_buffer; + } + chroma_op(dest_cb, src_cb, h->c_stride, chroma_height, mx&7, my&7); + + if(emu){ + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cr, h->c_stride, + 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1); + src_cr= h->edge_emu_buffer; + } + chroma_op(dest_cr, src_cr, h->c_stride, chroma_height, mx&7, my&7); +} + +static inline void mc_part_std(AVSContext *h,int chroma_height,int delta, + uint8_t *dest_y,uint8_t *dest_cb,uint8_t *dest_cr, + int x_offset, int y_offset,qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put,qpel_mc_func *qpix_avg, + h264_chroma_mc_func chroma_avg, cavs_vector *mv) +{ + qpel_mc_func *qpix_op= qpix_put; + h264_chroma_mc_func chroma_op= chroma_put; + + dest_y += 2*x_offset + 2*y_offset*h->l_stride; + dest_cb += x_offset + y_offset*h->c_stride; + dest_cr += x_offset + y_offset*h->c_stride; + x_offset += 8*h->mbx; + y_offset += 8*h->mby; + + if(mv->ref >= 0){ + AVFrame *ref = h->DPB[mv->ref].f; + mc_dir_part(h, ref, chroma_height, delta, 0, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, mv); + + qpix_op= qpix_avg; + chroma_op= chroma_avg; + } + + if((mv+MV_BWD_OFFS)->ref >= 0){ + AVFrame *ref = h->DPB[0].f; + mc_dir_part(h, ref, chroma_height, delta, 1, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, mv+MV_BWD_OFFS); + } +} + +void ff_cavs_inter(AVSContext *h, enum cavs_mb mb_type) { + if(ff_cavs_partition_flags[mb_type] == 0){ // 16x16 + mc_part_std(h, 8, 0, h->cy, h->cu, h->cv, 0, 0, + h->cdsp.put_cavs_qpel_pixels_tab[0], + h->h264chroma.put_h264_chroma_pixels_tab[0], + h->cdsp.avg_cavs_qpel_pixels_tab[0], + h->h264chroma.avg_h264_chroma_pixels_tab[0], + &h->mv[MV_FWD_X0]); + }else{ + mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 0, 0, + h->cdsp.put_cavs_qpel_pixels_tab[1], + h->h264chroma.put_h264_chroma_pixels_tab[1], + h->cdsp.avg_cavs_qpel_pixels_tab[1], + h->h264chroma.avg_h264_chroma_pixels_tab[1], + &h->mv[MV_FWD_X0]); + mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 4, 0, + h->cdsp.put_cavs_qpel_pixels_tab[1], + h->h264chroma.put_h264_chroma_pixels_tab[1], + h->cdsp.avg_cavs_qpel_pixels_tab[1], + h->h264chroma.avg_h264_chroma_pixels_tab[1], + &h->mv[MV_FWD_X1]); + mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 0, 4, + h->cdsp.put_cavs_qpel_pixels_tab[1], + h->h264chroma.put_h264_chroma_pixels_tab[1], + h->cdsp.avg_cavs_qpel_pixels_tab[1], + h->h264chroma.avg_h264_chroma_pixels_tab[1], + &h->mv[MV_FWD_X2]); + mc_part_std(h, 4, 0, h->cy, h->cu, h->cv, 4, 4, + h->cdsp.put_cavs_qpel_pixels_tab[1], + h->h264chroma.put_h264_chroma_pixels_tab[1], + h->cdsp.avg_cavs_qpel_pixels_tab[1], + h->h264chroma.avg_h264_chroma_pixels_tab[1], + &h->mv[MV_FWD_X3]); + } +} + +/***************************************************************************** + * + * motion vector prediction + * + ****************************************************************************/ + +static inline void scale_mv(AVSContext *h, int *d_x, int *d_y, cavs_vector *src, int distp) { + int den = h->scale_den[src->ref]; + + *d_x = (src->x*distp*den + 256 + (src->x>>31)) >> 9; + *d_y = (src->y*distp*den + 256 + (src->y>>31)) >> 9; +} + +static inline void mv_pred_median(AVSContext *h, cavs_vector *mvP, + cavs_vector *mvA, cavs_vector *mvB, cavs_vector *mvC) { + int ax, ay, bx, by, cx, cy; + int len_ab, len_bc, len_ca, len_mid; + + /* scale candidates according to their temporal span */ + scale_mv(h, &ax, &ay, mvA, mvP->dist); + scale_mv(h, &bx, &by, mvB, mvP->dist); + scale_mv(h, &cx, &cy, mvC, mvP->dist); + /* find the geometrical median of the three candidates */ + len_ab = abs(ax - bx) + abs(ay - by); + len_bc = abs(bx - cx) + abs(by - cy); + len_ca = abs(cx - ax) + abs(cy - ay); + len_mid = mid_pred(len_ab, len_bc, len_ca); + if(len_mid == len_ab) { + mvP->x = cx; + mvP->y = cy; + } else if(len_mid == len_bc) { + mvP->x = ax; + mvP->y = ay; + } else { + mvP->x = bx; + mvP->y = by; + } +} + +void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, + enum cavs_mv_pred mode, enum cavs_block size, int ref) { + cavs_vector *mvP = &h->mv[nP]; + cavs_vector *mvA = &h->mv[nP-1]; + cavs_vector *mvB = &h->mv[nP-4]; + cavs_vector *mvC = &h->mv[nC]; + const cavs_vector *mvP2 = NULL; + + mvP->ref = ref; + mvP->dist = h->dist[mvP->ref]; + if(mvC->ref == NOT_AVAIL) + mvC = &h->mv[nP-5]; // set to top-left (mvD) + if((mode == MV_PRED_PSKIP) && + ((mvA->ref == NOT_AVAIL) || (mvB->ref == NOT_AVAIL) || + ((mvA->x | mvA->y | mvA->ref) == 0) || + ((mvB->x | mvB->y | mvB->ref) == 0) )) { + mvP2 = &un_mv; + /* if there is only one suitable candidate, take it */ + } else if((mvA->ref >= 0) && (mvB->ref < 0) && (mvC->ref < 0)) { + mvP2= mvA; + } else if((mvA->ref < 0) && (mvB->ref >= 0) && (mvC->ref < 0)) { + mvP2= mvB; + } else if((mvA->ref < 0) && (mvB->ref < 0) && (mvC->ref >= 0)) { + mvP2= mvC; + } else if(mode == MV_PRED_LEFT && mvA->ref == ref){ + mvP2= mvA; + } else if(mode == MV_PRED_TOP && mvB->ref == ref){ + mvP2= mvB; + } else if(mode == MV_PRED_TOPRIGHT && mvC->ref == ref){ + mvP2= mvC; + } + if(mvP2){ + mvP->x = mvP2->x; + mvP->y = mvP2->y; + }else + mv_pred_median(h, mvP, mvA, mvB, mvC); + + if(mode < MV_PRED_PSKIP) { + mvP->x += get_se_golomb(&h->gb); + mvP->y += get_se_golomb(&h->gb); + } + set_mvs(mvP,size); +} + +/***************************************************************************** + * + * macroblock level + * + ****************************************************************************/ + +/** + * initialise predictors for motion vectors and intra prediction + */ +void ff_cavs_init_mb(AVSContext *h) { + int i; + + /* copy predictors from top line (MB B and C) into cache */ + for(i=0;i<3;i++) { + h->mv[MV_FWD_B2+i] = h->top_mv[0][h->mbx*2+i]; + h->mv[MV_BWD_B2+i] = h->top_mv[1][h->mbx*2+i]; + } + h->pred_mode_Y[1] = h->top_pred_Y[h->mbx*2+0]; + h->pred_mode_Y[2] = h->top_pred_Y[h->mbx*2+1]; + /* clear top predictors if MB B is not available */ + if(!(h->flags & B_AVAIL)) { + h->mv[MV_FWD_B2] = un_mv; + h->mv[MV_FWD_B3] = un_mv; + h->mv[MV_BWD_B2] = un_mv; + h->mv[MV_BWD_B3] = un_mv; + h->pred_mode_Y[1] = h->pred_mode_Y[2] = NOT_AVAIL; + h->flags &= ~(C_AVAIL|D_AVAIL); + } else if(h->mbx) { + h->flags |= D_AVAIL; + } + if(h->mbx == h->mb_width-1) //MB C not available + h->flags &= ~C_AVAIL; + /* clear top-right predictors if MB C is not available */ + if(!(h->flags & C_AVAIL)) { + h->mv[MV_FWD_C2] = un_mv; + h->mv[MV_BWD_C2] = un_mv; + } + /* clear top-left predictors if MB D is not available */ + if(!(h->flags & D_AVAIL)) { + h->mv[MV_FWD_D3] = un_mv; + h->mv[MV_BWD_D3] = un_mv; + } +} + +/** + * save predictors for later macroblocks and increase + * macroblock address + * @return 0 if end of frame is reached, 1 otherwise + */ +int ff_cavs_next_mb(AVSContext *h) { + int i; + + h->flags |= A_AVAIL; + h->cy += 16; + h->cu += 8; + h->cv += 8; + /* copy mvs as predictors to the left */ + for(i=0;i<=20;i+=4) + h->mv[i] = h->mv[i+2]; + /* copy bottom mvs from cache to top line */ + h->top_mv[0][h->mbx*2+0] = h->mv[MV_FWD_X2]; + h->top_mv[0][h->mbx*2+1] = h->mv[MV_FWD_X3]; + h->top_mv[1][h->mbx*2+0] = h->mv[MV_BWD_X2]; + h->top_mv[1][h->mbx*2+1] = h->mv[MV_BWD_X3]; + /* next MB address */ + h->mbidx++; + h->mbx++; + if(h->mbx == h->mb_width) { //new mb line + h->flags = B_AVAIL|C_AVAIL; + /* clear left pred_modes */ + h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL; + /* clear left mv predictors */ + for(i=0;i<=20;i+=4) + h->mv[i] = un_mv; + h->mbx = 0; + h->mby++; + /* re-calculate sample pointers */ + h->cy = h->cur.f->data[0] + h->mby * 16 * h->l_stride; + h->cu = h->cur.f->data[1] + h->mby * 8 * h->c_stride; + h->cv = h->cur.f->data[2] + h->mby * 8 * h->c_stride; + if(h->mby == h->mb_height) { //frame end + return 0; + } + } + return 1; +} + +/***************************************************************************** + * + * frame level + * + ****************************************************************************/ + +int ff_cavs_init_pic(AVSContext *h) { + int i; + + /* clear some predictors */ + for(i=0;i<=20;i+=4) + h->mv[i] = un_mv; + h->mv[MV_BWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); + h->mv[MV_FWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_FWD_X0], BLK_16X16); + h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL; + h->cy = h->cur.f->data[0]; + h->cu = h->cur.f->data[1]; + h->cv = h->cur.f->data[2]; + h->l_stride = h->cur.f->linesize[0]; + h->c_stride = h->cur.f->linesize[1]; + h->luma_scan[2] = 8*h->l_stride; + h->luma_scan[3] = 8*h->l_stride+8; + h->mbx = h->mby = h->mbidx = 0; + h->flags = 0; + + return 0; +} + +/***************************************************************************** + * + * headers and interface + * + ****************************************************************************/ + +/** + * some predictions require data from the top-neighbouring macroblock. + * this data has to be stored for one complete row of macroblocks + * and this storage space is allocated here + */ +void ff_cavs_init_top_lines(AVSContext *h) { + /* alloc top line of predictors */ + h->top_qp = av_mallocz( h->mb_width); + h->top_mv[0] = av_mallocz((h->mb_width*2+1)*sizeof(cavs_vector)); + h->top_mv[1] = av_mallocz((h->mb_width*2+1)*sizeof(cavs_vector)); + h->top_pred_Y = av_mallocz( h->mb_width*2*sizeof(*h->top_pred_Y)); + h->top_border_y = av_mallocz((h->mb_width+1)*16); + h->top_border_u = av_mallocz( h->mb_width * 10); + h->top_border_v = av_mallocz( h->mb_width * 10); + + /* alloc space for co-located MVs and types */ + h->col_mv = av_mallocz( h->mb_width*h->mb_height*4*sizeof(cavs_vector)); + h->col_type_base = av_mallocz(h->mb_width*h->mb_height); + h->block = av_mallocz(64*sizeof(int16_t)); +} + +av_cold int ff_cavs_init(AVCodecContext *avctx) { + AVSContext *h = avctx->priv_data; + + ff_dsputil_init(&h->dsp, avctx); + ff_h264chroma_init(&h->h264chroma, 8); + ff_videodsp_init(&h->vdsp, 8); + ff_cavsdsp_init(&h->cdsp, avctx); + ff_init_scantable_permutation(h->dsp.idct_permutation, + h->cdsp.idct_perm); + ff_init_scantable(h->dsp.idct_permutation, &h->scantable, ff_zigzag_direct); + + h->avctx = avctx; + avctx->pix_fmt= AV_PIX_FMT_YUV420P; + + h->cur.f = av_frame_alloc(); + h->DPB[0].f = av_frame_alloc(); + h->DPB[1].f = av_frame_alloc(); + if (!h->cur.f || !h->DPB[0].f || !h->DPB[1].f) { + ff_cavs_end(avctx); + return AVERROR(ENOMEM); + } + + h->luma_scan[0] = 0; + h->luma_scan[1] = 8; + h->intra_pred_l[ INTRA_L_VERT] = intra_pred_vert; + h->intra_pred_l[ INTRA_L_HORIZ] = intra_pred_horiz; + h->intra_pred_l[ INTRA_L_LP] = intra_pred_lp; + h->intra_pred_l[ INTRA_L_DOWN_LEFT] = intra_pred_down_left; + h->intra_pred_l[INTRA_L_DOWN_RIGHT] = intra_pred_down_right; + h->intra_pred_l[ INTRA_L_LP_LEFT] = intra_pred_lp_left; + h->intra_pred_l[ INTRA_L_LP_TOP] = intra_pred_lp_top; + h->intra_pred_l[ INTRA_L_DC_128] = intra_pred_dc_128; + h->intra_pred_c[ INTRA_C_LP] = intra_pred_lp; + h->intra_pred_c[ INTRA_C_HORIZ] = intra_pred_horiz; + h->intra_pred_c[ INTRA_C_VERT] = intra_pred_vert; + h->intra_pred_c[ INTRA_C_PLANE] = intra_pred_plane; + h->intra_pred_c[ INTRA_C_LP_LEFT] = intra_pred_lp_left; + h->intra_pred_c[ INTRA_C_LP_TOP] = intra_pred_lp_top; + h->intra_pred_c[ INTRA_C_DC_128] = intra_pred_dc_128; + h->mv[ 7] = un_mv; + h->mv[19] = un_mv; + return 0; +} + +av_cold int ff_cavs_end(AVCodecContext *avctx) { + AVSContext *h = avctx->priv_data; + + av_frame_free(&h->cur.f); + av_frame_free(&h->DPB[0].f); + av_frame_free(&h->DPB[1].f); + + av_free(h->top_qp); + av_free(h->top_mv[0]); + av_free(h->top_mv[1]); + av_free(h->top_pred_Y); + av_free(h->top_border_y); + av_free(h->top_border_u); + av_free(h->top_border_v); + av_free(h->col_mv); + av_free(h->col_type_base); + av_free(h->block); + av_freep(&h->edge_emu_buffer); + return 0; +} diff --git a/ffmpeg/libavcodec/cavs.h b/ffmpeg/libavcodec/cavs.h new file mode 100644 index 0000000..b0cdb8f --- /dev/null +++ b/ffmpeg/libavcodec/cavs.h @@ -0,0 +1,275 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 + */ + +#ifndef AVCODEC_CAVS_H +#define AVCODEC_CAVS_H + +#include "cavsdsp.h" +#include "dsputil.h" +#include "h264chroma.h" +#include "get_bits.h" +#include "videodsp.h" + +#define SLICE_MAX_START_CODE 0x000001af +#define EXT_START_CODE 0x000001b5 +#define USER_START_CODE 0x000001b2 +#define CAVS_START_CODE 0x000001b0 +#define PIC_I_START_CODE 0x000001b3 +#define PIC_PB_START_CODE 0x000001b6 + +#define A_AVAIL 1 +#define B_AVAIL 2 +#define C_AVAIL 4 +#define D_AVAIL 8 +#define NOT_AVAIL -1 +#define REF_INTRA -2 +#define REF_DIR -3 + +#define ESCAPE_CODE 59 + +#define FWD0 0x01 +#define FWD1 0x02 +#define BWD0 0x04 +#define BWD1 0x08 +#define SYM0 0x10 +#define SYM1 0x20 +#define SPLITH 0x40 +#define SPLITV 0x80 + +#define MV_BWD_OFFS 12 +#define MV_STRIDE 4 + +enum cavs_mb { + I_8X8 = 0, + P_SKIP, + P_16X16, + P_16X8, + P_8X16, + P_8X8, + B_SKIP, + B_DIRECT, + B_FWD_16X16, + B_BWD_16X16, + B_SYM_16X16, + B_8X8 = 29 +}; + +enum cavs_sub_mb { + B_SUB_DIRECT, + B_SUB_FWD, + B_SUB_BWD, + B_SUB_SYM +}; + +enum cavs_intra_luma { + INTRA_L_VERT, + INTRA_L_HORIZ, + INTRA_L_LP, + INTRA_L_DOWN_LEFT, + INTRA_L_DOWN_RIGHT, + INTRA_L_LP_LEFT, + INTRA_L_LP_TOP, + INTRA_L_DC_128 +}; + +enum cavs_intra_chroma { + INTRA_C_LP, + INTRA_C_HORIZ, + INTRA_C_VERT, + INTRA_C_PLANE, + INTRA_C_LP_LEFT, + INTRA_C_LP_TOP, + INTRA_C_DC_128, +}; + +enum cavs_mv_pred { + MV_PRED_MEDIAN, + MV_PRED_LEFT, + MV_PRED_TOP, + MV_PRED_TOPRIGHT, + MV_PRED_PSKIP, + MV_PRED_BSKIP +}; + +enum cavs_block { + BLK_16X16, + BLK_16X8, + BLK_8X16, + BLK_8X8 +}; + +enum cavs_mv_loc { + MV_FWD_D3 = 0, + MV_FWD_B2, + MV_FWD_B3, + MV_FWD_C2, + MV_FWD_A1, + MV_FWD_X0, + MV_FWD_X1, + MV_FWD_A3 = 8, + MV_FWD_X2, + MV_FWD_X3, + MV_BWD_D3 = MV_BWD_OFFS, + MV_BWD_B2, + MV_BWD_B3, + MV_BWD_C2, + MV_BWD_A1, + MV_BWD_X0, + MV_BWD_X1, + MV_BWD_A3 = MV_BWD_OFFS+8, + MV_BWD_X2, + MV_BWD_X3 +}; + +DECLARE_ALIGNED(8, typedef, struct) { + int16_t x; + int16_t y; + int16_t dist; + int16_t ref; +} cavs_vector; + +struct dec_2dvlc { + int8_t rltab[59][3]; + int8_t level_add[27]; + int8_t golomb_order; + int inc_limit; + int8_t max_run; +}; + +typedef struct AVSFrame { + AVFrame *f; + int poc; +} AVSFrame; + +typedef struct AVSContext { + AVCodecContext *avctx; + DSPContext dsp; + H264ChromaContext h264chroma; + VideoDSPContext vdsp; + CAVSDSPContext cdsp; + GetBitContext gb; + AVSFrame cur; ///< currently decoded frame + AVSFrame DPB[2]; ///< reference frames + int dist[2]; ///< temporal distances from current frame to ref frames + int low_delay; + int profile, level; + int aspect_ratio; + int mb_width, mb_height; + int width, height; + int stream_revision; ///<0 for samples from 2006, 1 for rm52j encoder + int progressive; + int pic_structure; + int skip_mode_flag; ///< select between skip_count or one skip_flag per MB + int loop_filter_disable; + int alpha_offset, beta_offset; + int ref_flag; + int mbx, mby, mbidx; ///< macroblock coordinates + int flags; ///< availability flags of neighbouring macroblocks + int stc; ///< last start code + uint8_t *cy, *cu, *cv; ///< current MB sample pointers + int left_qp; + uint8_t *top_qp; + + /** mv motion vector cache + 0: D3 B2 B3 C2 + 4: A1 X0 X1 - + 8: A3 X2 X3 - + + X are the vectors in the current macroblock (5,6,9,10) + A is the macroblock to the left (4,8) + B is the macroblock to the top (1,2) + C is the macroblock to the top-right (3) + D is the macroblock to the top-left (0) + + the same is repeated for backward motion vectors */ + cavs_vector mv[2*4*3]; + cavs_vector *top_mv[2]; + cavs_vector *col_mv; + + /** luma pred mode cache + 0: -- B2 B3 + 3: A1 X0 X1 + 6: A3 X2 X3 */ + int pred_mode_Y[3*3]; + int *top_pred_Y; + int l_stride, c_stride; + int luma_scan[4]; + int qp; + int qp_fixed; + int cbp; + ScanTable scantable; + + /** intra prediction is done with un-deblocked samples + they are saved here before deblocking the MB */ + uint8_t *top_border_y, *top_border_u, *top_border_v; + uint8_t left_border_y[26], left_border_u[10], left_border_v[10]; + uint8_t intern_border_y[26]; + uint8_t topleft_border_y, topleft_border_u, topleft_border_v; + + void (*intra_pred_l[8])(uint8_t *d,uint8_t *top,uint8_t *left,int stride); + void (*intra_pred_c[7])(uint8_t *d,uint8_t *top,uint8_t *left,int stride); + uint8_t *col_type_base; + + /* scaling factors for MV prediction */ + int sym_factor; ///< for scaling in symmetrical B block + int direct_den[2]; ///< for scaling in direct B block + int scale_den[2]; ///< for scaling neighbouring MVs + + uint8_t *edge_emu_buffer; + + int got_keyframe; + int16_t *block; +} AVSContext; + +extern const uint8_t ff_cavs_partition_flags[30]; +extern const cavs_vector ff_cavs_intra_mv; +extern const cavs_vector ff_cavs_dir_mv; + +static inline void set_mvs(cavs_vector *mv, enum cavs_block size) { + switch(size) { + case BLK_16X16: + mv[MV_STRIDE ] = mv[0]; + mv[MV_STRIDE+1] = mv[0]; + case BLK_16X8: + mv[1] = mv[0]; + break; + case BLK_8X16: + mv[MV_STRIDE] = mv[0]; + break; + } +} + +void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type); +void ff_cavs_load_intra_pred_luma(AVSContext *h, uint8_t *top, uint8_t **left, + int block); +void ff_cavs_load_intra_pred_chroma(AVSContext *h); +void ff_cavs_modify_mb_i(AVSContext *h, int *pred_mode_uv); +void ff_cavs_inter(AVSContext *h, enum cavs_mb mb_type); +void ff_cavs_mv(AVSContext *h, enum cavs_mv_loc nP, enum cavs_mv_loc nC, + enum cavs_mv_pred mode, enum cavs_block size, int ref); +void ff_cavs_init_mb(AVSContext *h); +int ff_cavs_next_mb(AVSContext *h); +int ff_cavs_init_pic(AVSContext *h); +void ff_cavs_init_top_lines(AVSContext *h); +int ff_cavs_init(AVCodecContext *avctx); +int ff_cavs_end (AVCodecContext *avctx); + +#endif /* AVCODEC_CAVS_H */ diff --git a/ffmpeg/libavcodec/cavs_parser.c b/ffmpeg/libavcodec/cavs_parser.c new file mode 100644 index 0000000..6067a39 --- /dev/null +++ b/ffmpeg/libavcodec/cavs_parser.c @@ -0,0 +1,106 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) parser. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 + */ + +/** + * @file + * Chinese AVS video (AVS1-P2, JiZhun profile) parser + * @author Stefan Gehrer + */ + +#include "parser.h" +#include "cavs.h" + + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int cavs_find_frame_end(ParseContext *pc, const uint8_t *buf, + int buf_size) { + int pic_found, i; + uint32_t state; + + pic_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!pic_found){ + for(i=0; i SLICE_MAX_START_CODE){ + pc->frame_start_found=0; + pc->state=-1; + return i-3; + } + } + } + } + pc->frame_start_found= pic_found; + pc->state= state; + return END_NOT_FOUND; +} + +static int cavsvideo_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= cavs_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_cavsvideo_parser = { + .codec_ids = { AV_CODEC_ID_CAVS }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = cavsvideo_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/ffmpeg/libavcodec/cavsdata.c b/ffmpeg/libavcodec/cavsdata.c new file mode 100644 index 0000000..905a306 --- /dev/null +++ b/ffmpeg/libavcodec/cavsdata.c @@ -0,0 +1,62 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 "cavs.h" + +const uint8_t ff_cavs_partition_flags[30] = { + 0, //I_8X8 + 0, //P_SKIP + 0, //P_16X16 + SPLITH, //P_16X8 + SPLITV, //P_8X16 + SPLITH|SPLITV, //P_8X8 + SPLITH|SPLITV, //B_SKIP + SPLITH|SPLITV, //B_DIRECT + 0, //B_FWD_16X16 + 0, //B_BWD_16X16 + 0, //B_SYM_16X16 + FWD0|FWD1 |SPLITH, + FWD0|FWD1 |SPLITV, + BWD0|BWD1 |SPLITH, + BWD0|BWD1 |SPLITV, + FWD0|BWD1 |SPLITH, + FWD0|BWD1 |SPLITV, + BWD0|FWD1 |SPLITH, + BWD0|FWD1 |SPLITV, + FWD0|FWD1 |SYM1|SPLITH, + FWD0|FWD1 |SYM1 |SPLITV, + BWD0|FWD1 |SYM1|SPLITH, + BWD0|FWD1 |SYM1 |SPLITV, + FWD0|FWD1|SYM0 |SPLITH, + FWD0|FWD1|SYM0 |SPLITV, + FWD0|BWD1|SYM0 |SPLITH, + FWD0|BWD1|SYM0 |SPLITV, + FWD0|FWD1|SYM0|SYM1|SPLITH, + FWD0|FWD1|SYM0|SYM1 |SPLITV, + SPLITH|SPLITV, //B_8X8 = 29 +}; + +/** mark block as "no prediction from this direction" + e.g. forward motion vector in BWD partition */ +const cavs_vector ff_cavs_dir_mv = {0,0,1,REF_DIR}; + +/** mark block as using intra prediction */ +const cavs_vector ff_cavs_intra_mv = {0,0,1,REF_INTRA}; diff --git a/ffmpeg/libavcodec/cavsdata.h b/ffmpeg/libavcodec/cavsdata.h new file mode 100644 index 0000000..67fae3c --- /dev/null +++ b/ffmpeg/libavcodec/cavsdata.h @@ -0,0 +1,67 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 + */ + +#ifndef AVCODEC_CAVSDATA_H +#define AVCODEC_CAVSDATA_H + +#include "cavs.h" + +const uint8_t ff_cavs_partition_flags[30] = { + 0, //I_8X8 + 0, //P_SKIP + 0, //P_16X16 + SPLITH, //P_16X8 + SPLITV, //P_8X16 + SPLITH|SPLITV, //P_8X8 + SPLITH|SPLITV, //B_SKIP + SPLITH|SPLITV, //B_DIRECT + 0, //B_FWD_16X16 + 0, //B_BWD_16X16 + 0, //B_SYM_16X16 + FWD0|FWD1 |SPLITH, + FWD0|FWD1 |SPLITV, + BWD0|BWD1 |SPLITH, + BWD0|BWD1 |SPLITV, + FWD0|BWD1 |SPLITH, + FWD0|BWD1 |SPLITV, + BWD0|FWD1 |SPLITH, + BWD0|FWD1 |SPLITV, + FWD0|FWD1 |SYM1|SPLITH, + FWD0|FWD1 |SYM1 |SPLITV, + BWD0|FWD1 |SYM1|SPLITH, + BWD0|FWD1 |SYM1 |SPLITV, + FWD0|FWD1|SYM0 |SPLITH, + FWD0|FWD1|SYM0 |SPLITV, + FWD0|BWD1|SYM0 |SPLITH, + FWD0|BWD1|SYM0 |SPLITV, + FWD0|FWD1|SYM0|SYM1|SPLITH, + FWD0|FWD1|SYM0|SYM1 |SPLITV, + SPLITH|SPLITV, //B_8X8 = 29 +}; + +/** mark block as "no prediction from this direction" + e.g. forward motion vector in BWD partition */ +const cavs_vector ff_cavs_dir_mv = {0,0,1,REF_DIR}; + +/** mark block as using intra prediction */ +const cavs_vector ff_cavs_intra_mv = {0,0,1,REF_INTRA}; + +#endif /* AVCODEC_CAVSDATA_H */ diff --git a/ffmpeg/libavcodec/cavsdec.c b/ffmpeg/libavcodec/cavsdec.c new file mode 100644 index 0000000..2ef3eb3 --- /dev/null +++ b/ffmpeg/libavcodec/cavsdec.c @@ -0,0 +1,1226 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 + */ + +/** + * @file + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder + * @author Stefan Gehrer + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "get_bits.h" +#include "golomb.h" +#include "cavs.h" +#include "internal.h" +#include "mpeg12data.h" +#include "mpegvideo.h" + +static const uint8_t mv_scan[4] = { + MV_FWD_X0, MV_FWD_X1, + MV_FWD_X2, MV_FWD_X3 +}; + +static const uint8_t cbp_tab[64][2] = { + { 63, 0 }, { 15, 15 }, { 31, 63 }, { 47, 31 }, { 0, 16 }, { 14, 32 }, { 13, 47 }, { 11, 13 }, + { 7, 14 }, { 5, 11 }, { 10, 12 }, { 8, 5 }, { 12, 10 }, { 61, 7 }, { 4, 48 }, { 55, 3 }, + { 1, 2 }, { 2, 8 }, { 59, 4 }, { 3, 1 }, { 62, 61 }, { 9, 55 }, { 6, 59 }, { 29, 62 }, + { 45, 29 }, { 51, 27 }, { 23, 23 }, { 39, 19 }, { 27, 30 }, { 46, 28 }, { 53, 9 }, { 30, 6 }, + { 43, 60 }, { 37, 21 }, { 60, 44 }, { 16, 26 }, { 21, 51 }, { 28, 35 }, { 19, 18 }, { 35, 20 }, + { 42, 24 }, { 26, 53 }, { 44, 17 }, { 32, 37 }, { 58, 39 }, { 24, 45 }, { 20, 58 }, { 17, 43 }, + { 18, 42 }, { 48, 46 }, { 22, 36 }, { 33, 33 }, { 25, 34 }, { 49, 40 }, { 40, 52 }, { 36, 49 }, + { 34, 50 }, { 50, 56 }, { 52, 25 }, { 54, 22 }, { 41, 54 }, { 56, 57 }, { 38, 41 }, { 57, 38 } +}; + +static const uint8_t scan3x3[4] = { 4, 5, 7, 8 }; + +static const uint8_t cavs_chroma_qp[64] = { + 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, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 43, 44, 44, + 45, 45, 46, 46, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51 +}; + +static const uint8_t dequant_shift[64] = { + 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 12, 12, 12, 12, 12, 12, 12, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, + 10, 9, 9, 9, 9, 9, 9, 9, + 9, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7 +}; + +static const uint16_t dequant_mul[64] = { + 32768, 36061, 38968, 42495, 46341, 50535, 55437, 60424, + 32932, 35734, 38968, 42495, 46177, 50535, 55109, 59933, + 65535, 35734, 38968, 42577, 46341, 50617, 55027, 60097, + 32809, 35734, 38968, 42454, 46382, 50576, 55109, 60056, + 65535, 35734, 38968, 42495, 46320, 50515, 55109, 60076, + 65535, 35744, 38968, 42495, 46341, 50535, 55099, 60087, + 65535, 35734, 38973, 42500, 46341, 50535, 55109, 60097, + 32771, 35734, 38965, 42497, 46341, 50535, 55109, 60099 +}; + +#define EOB 0, 0, 0 + +static const struct dec_2dvlc intra_dec[7] = { + { + { //level / run / table_inc + { 1, 1, 1 }, { -1, 1, 1 }, { 1, 2, 1 }, { -1, 2, 1 }, { 1, 3, 1 }, { -1, 3, 1 }, + { 1, 4, 1 }, { -1, 4, 1 }, { 1, 5, 1 }, { -1, 5, 1 }, { 1, 6, 1 }, { -1, 6, 1 }, + { 1, 7, 1 }, { -1, 7, 1 }, { 1, 8, 1 }, { -1, 8, 1 }, { 1, 9, 1 }, { -1, 9, 1 }, + { 1, 10, 1 }, { -1, 10, 1 }, { 1, 11, 1 }, { -1, 11, 1 }, { 2, 1, 2 }, { -2, 1, 2 }, + { 1, 12, 1 }, { -1, 12, 1 }, { 1, 13, 1 }, { -1, 13, 1 }, { 1, 14, 1 }, { -1, 14, 1 }, + { 1, 15, 1 }, { -1, 15, 1 }, { 2, 2, 2 }, { -2, 2, 2 }, { 1, 16, 1 }, { -1, 16, 1 }, + { 1, 17, 1 }, { -1, 17, 1 }, { 3, 1, 3 }, { -3, 1, 3 }, { 1, 18, 1 }, { -1, 18, 1 }, + { 1, 19, 1 }, { -1, 19, 1 }, { 2, 3, 2 }, { -2, 3, 2 }, { 1, 20, 1 }, { -1, 20, 1 }, + { 1, 21, 1 }, { -1, 21, 1 }, { 2, 4, 2 }, { -2, 4, 2 }, { 1, 22, 1 }, { -1, 22, 1 }, + { 2, 5, 2 }, { -2, 5, 2 }, { 1, 23, 1 }, { -1, 23, 1 }, { EOB } + }, + //level_add + { 0, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1 }, + 2, //golomb_order + 0, //inc_limit + 23, //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 2, 1, 1 }, { -2, 1, 1 }, + { 1, 3, 0 }, { -1, 3, 0 }, { EOB }, { 1, 4, 0 }, { -1, 4, 0 }, { 1, 5, 0 }, + { -1, 5, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 3, 1, 2 }, { -3, 1, 2 }, { 2, 2, 1 }, + { -2, 2, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, { 1, 9, 0 }, + { -1, 9, 0 }, { 2, 3, 1 }, { -2, 3, 1 }, { 4, 1, 2 }, { -4, 1, 2 }, { 1, 10, 0 }, + { -1, 10, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 2, 4, 1 }, { -2, 4, 1 }, { 3, 2, 2 }, + { -3, 2, 2 }, { 1, 12, 0 }, { -1, 12, 0 }, { 2, 5, 1 }, { -2, 5, 1 }, { 5, 1, 3 }, + { -5, 1, 3 }, { 1, 13, 0 }, { -1, 13, 0 }, { 2, 6, 1 }, { -2, 6, 1 }, { 1, 14, 0 }, + { -1, 14, 0 }, { 2, 7, 1 }, { -2, 7, 1 }, { 2, 8, 1 }, { -2, 8, 1 }, { 3, 3, 2 }, + { -3, 3, 2 }, { 6, 1, 3 }, { -6, 1, 3 }, { 1, 15, 0 }, { -1, 15, 0 } + }, + //level_add + { 0, 7, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 1, //inc_limit + 15, //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, + { 3, 1, 1 }, { -3, 1, 1 }, { EOB }, { 1, 3, 0 }, { -1, 3, 0 }, { 2, 2, 0 }, + { -2, 2, 0 }, { 4, 1, 1 }, { -4, 1, 1 }, { 1, 4, 0 }, { -1, 4, 0 }, { 5, 1, 2 }, + { -5, 1, 2 }, { 1, 5, 0 }, { -1, 5, 0 }, { 3, 2, 1 }, { -3, 2, 1 }, { 2, 3, 0 }, + { -2, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 6, 1, 2 }, { -6, 1, 2 }, { 2, 4, 0 }, + { -2, 4, 0 }, { 1, 7, 0 }, { -1, 7, 0 }, { 4, 2, 1 }, { -4, 2, 1 }, { 7, 1, 2 }, + { -7, 1, 2 }, { 3, 3, 1 }, { -3, 3, 1 }, { 2, 5, 0 }, { -2, 5, 0 }, { 1, 8, 0 }, + { -1, 8, 0 }, { 2, 6, 0 }, { -2, 6, 0 }, { 8, 1, 3 }, { -8, 1, 3 }, { 1, 9, 0 }, + { -1, 9, 0 }, { 5, 2, 2 }, { -5, 2, 2 }, { 3, 4, 1 }, { -3, 4, 1 }, { 2, 7, 0 }, + { -2, 7, 0 }, { 9, 1, 3 }, { -9, 1, 3 }, { 1, 10, 0 }, { -1, 10, 0 } + }, + //level_add + { 0, 10, 6, 4, 4, 3, 3, 3, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 2, //inc_limit + 10, //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, { -3, 1, 0 }, + { 1, 2, 0 }, { -1, 2, 0 }, { EOB }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 1 }, + { -5, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 6, 1, 1 }, + { -6, 1, 1 }, { 3, 2, 0 }, { -3, 2, 0 }, { 7, 1, 1 }, { -7, 1, 1 }, { 1, 4, 0 }, + { -1, 4, 0 }, { 8, 1, 2 }, { -8, 1, 2 }, { 2, 3, 0 }, { -2, 3, 0 }, { 4, 2, 0 }, + { -4, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 9, 1, 2 }, { -9, 1, 2 }, { 5, 2, 1 }, + { -5, 2, 1 }, { 2, 4, 0 }, { -2, 4, 0 }, { 10, 1, 2 }, {-10, 1, 2 }, { 3, 3, 0 }, + { -3, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 11, 1, 3 }, {-11, 1, 3 }, { 6, 2, 1 }, + { -6, 2, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 2, 5, 0 }, { -2, 5, 0 }, { 3, 4, 0 }, + { -3, 4, 0 }, { 12, 1, 3 }, {-12, 1, 3 }, { 4, 3, 0 }, { -4, 3, 0 } + }, + //level_add + { 0, 13, 7, 5, 4, 3, 2, 2, -1, -1, -1 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 4, //inc_limit + 7, //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, { -3, 1, 0 }, + { EOB }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 }, + { -6, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 1 }, + { -8, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 9, 1, 1 }, { -9, 1, 1 }, { 10, 1, 1 }, + {-10, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 11, 1, 2 }, + {-11, 1, 2 }, { 4, 2, 0 }, { -4, 2, 0 }, { 12, 1, 2 }, {-12, 1, 2 }, { 13, 1, 2 }, + {-13, 1, 2 }, { 5, 2, 0 }, { -5, 2, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 2, 3, 0 }, + { -2, 3, 0 }, { 14, 1, 2 }, {-14, 1, 2 }, { 6, 2, 0 }, { -6, 2, 0 }, { 15, 1, 2 }, + {-15, 1, 2 }, { 16, 1, 2 }, {-16, 1, 2 }, { 3, 3, 0 }, { -3, 3, 0 }, { 1, 5, 0 }, + { -1, 5, 0 }, { 7, 2, 0 }, { -7, 2, 0 }, { 17, 1, 2 }, {-17, 1, 2 } + }, + //level_add + { 0,18, 8, 4, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 7, //inc_limit + 5, //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 }, + { -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, { -8, 1, 0 }, { 9, 1, 0 }, + { -9, 1, 0 }, { 10, 1, 0 }, {-10, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 11, 1, 1 }, + {-11, 1, 1 }, { 12, 1, 1 }, {-12, 1, 1 }, { 13, 1, 1 }, {-13, 1, 1 }, { 2, 2, 0 }, + { -2, 2, 0 }, { 14, 1, 1 }, {-14, 1, 1 }, { 15, 1, 1 }, {-15, 1, 1 }, { 3, 2, 0 }, + { -3, 2, 0 }, { 16, 1, 1 }, {-16, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 17, 1, 1 }, + {-17, 1, 1 }, { 4, 2, 0 }, { -4, 2, 0 }, { 18, 1, 1 }, {-18, 1, 1 }, { 5, 2, 0 }, + { -5, 2, 0 }, { 19, 1, 1 }, {-19, 1, 1 }, { 20, 1, 1 }, {-20, 1, 1 }, { 6, 2, 0 }, + { -6, 2, 0 }, { 21, 1, 1 }, {-21, 1, 1 }, { 2, 3, 0 }, { -2, 3, 0 } + }, + //level_add + { 0, 22, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 10, //inc_limit + 3, //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 }, + { -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, { -8, 1, 0 }, { 9, 1, 0 }, + { -9, 1, 0 }, { 10, 1, 0 }, {-10, 1, 0 }, { 11, 1, 0 }, {-11, 1, 0 }, { 12, 1, 0 }, + {-12, 1, 0 }, { 13, 1, 0 }, {-13, 1, 0 }, { 14, 1, 0 }, {-14, 1, 0 }, { 15, 1, 0 }, + {-15, 1, 0 }, { 16, 1, 0 }, {-16, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 17, 1, 0 }, + {-17, 1, 0 }, { 18, 1, 0 }, {-18, 1, 0 }, { 19, 1, 0 }, {-19, 1, 0 }, { 20, 1, 0 }, + {-20, 1, 0 }, { 21, 1, 0 }, {-21, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 22, 1, 0 }, + {-22, 1, 0 }, { 23, 1, 0 }, {-23, 1, 0 }, { 24, 1, 0 }, {-24, 1, 0 }, { 25, 1, 0 }, + {-25, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 26, 1, 0 }, {-26, 1, 0 } + }, + //level_add + { 0, 27, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + INT_MAX, //inc_limit + 2, //max_run + } +}; + +static const struct dec_2dvlc inter_dec[7] = { + { + { //level / run + { 1, 1, 1 }, { -1, 1, 1 }, { 1, 2, 1 }, { -1, 2, 1 }, { 1, 3, 1 }, { -1, 3, 1 }, + { 1, 4, 1 }, { -1, 4, 1 }, { 1, 5, 1 }, { -1, 5, 1 }, { 1, 6, 1 }, { -1, 6, 1 }, + { 1, 7, 1 }, { -1, 7, 1 }, { 1, 8, 1 }, { -1, 8, 1 }, { 1, 9, 1 }, { -1, 9, 1 }, + { 1, 10, 1 }, { -1, 10, 1 }, { 1, 11, 1 }, { -1, 11, 1 }, { 1, 12, 1 }, { -1, 12, 1 }, + { 1, 13, 1 }, { -1, 13, 1 }, { 2, 1, 2 }, { -2, 1, 2 }, { 1, 14, 1 }, { -1, 14, 1 }, + { 1, 15, 1 }, { -1, 15, 1 }, { 1, 16, 1 }, { -1, 16, 1 }, { 1, 17, 1 }, { -1, 17, 1 }, + { 1, 18, 1 }, { -1, 18, 1 }, { 1, 19, 1 }, { -1, 19, 1 }, { 3, 1, 3 }, { -3, 1, 3 }, + { 1, 20, 1 }, { -1, 20, 1 }, { 1, 21, 1 }, { -1, 21, 1 }, { 2, 2, 2 }, { -2, 2, 2 }, + { 1, 22, 1 }, { -1, 22, 1 }, { 1, 23, 1 }, { -1, 23, 1 }, { 1, 24, 1 }, { -1, 24, 1 }, + { 1, 25, 1 }, { -1, 25, 1 }, { 1, 26, 1 }, { -1, 26, 1 }, { EOB } + }, + //level_add + { 0, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, + 3, //golomb_order + 0, //inc_limit + 26 //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 1, 2, 0 }, { -1, 2, 0 }, { 1, 3, 0 }, + { -1, 3, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 1, 6, 0 }, + { -1, 6, 0 }, { 2, 1, 1 }, { -2, 1, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 1, 8, 0 }, + { -1, 8, 0 }, { 1, 9, 0 }, { -1, 9, 0 }, { 1, 10, 0 }, { -1, 10, 0 }, { 2, 2, 1 }, + { -2, 2, 1 }, { 1, 11, 0 }, { -1, 11, 0 }, { 1, 12, 0 }, { -1, 12, 0 }, { 3, 1, 2 }, + { -3, 1, 2 }, { 1, 13, 0 }, { -1, 13, 0 }, { 1, 14, 0 }, { -1, 14, 0 }, { 2, 3, 1 }, + { -2, 3, 1 }, { 1, 15, 0 }, { -1, 15, 0 }, { 2, 4, 1 }, { -2, 4, 1 }, { 1, 16, 0 }, + { -1, 16, 0 }, { 2, 5, 1 }, { -2, 5, 1 }, { 1, 17, 0 }, { -1, 17, 0 }, { 4, 1, 3 }, + { -4, 1, 3 }, { 2, 6, 1 }, { -2, 6, 1 }, { 1, 18, 0 }, { -1, 18, 0 }, { 1, 19, 0 }, + { -1, 19, 0 }, { 2, 7, 1 }, { -2, 7, 1 }, { 3, 2, 2 }, { -3, 2, 2 } + }, + //level_add + { 0, 5, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 1, //inc_limit + 19 //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 1, 2, 0 }, { -1, 2, 0 }, { 2, 1, 0 }, + { -2, 1, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 3, 1, 1 }, + { -3, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 1, 6, 0 }, + { -1, 6, 0 }, { 1, 7, 0 }, { -1, 7, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 4, 1, 2 }, + { -4, 1, 2 }, { 1, 8, 0 }, { -1, 8, 0 }, { 3, 2, 1 }, { -3, 2, 1 }, { 2, 4, 0 }, + { -2, 4, 0 }, { 1, 9, 0 }, { -1, 9, 0 }, { 1, 10, 0 }, { -1, 10, 0 }, { 5, 1, 2 }, + { -5, 1, 2 }, { 2, 5, 0 }, { -2, 5, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 2, 6, 0 }, + { -2, 6, 0 }, { 1, 12, 0 }, { -1, 12, 0 }, { 3, 3, 1 }, { -3, 3, 1 }, { 6, 1, 2 }, + { -6, 1, 2 }, { 4, 2, 2 }, { -4, 2, 2 }, { 1, 13, 0 }, { -1, 13, 0 }, { 2, 7, 0 }, + { -2, 7, 0 }, { 3, 4, 1 }, { -3, 4, 1 }, { 1, 14, 0 }, { -1, 14, 0 } + }, + //level_add + { 0, 7, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 2, //inc_limit + 14 //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 2, 1, 0 }, { -2, 1, 0 }, { 1, 2, 0 }, + { -1, 2, 0 }, { 3, 1, 0 }, { -3, 1, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 2, 2, 0 }, + { -2, 2, 0 }, { 4, 1, 1 }, { -4, 1, 1 }, { 1, 4, 0 }, { -1, 4, 0 }, { 5, 1, 1 }, + { -5, 1, 1 }, { 1, 5, 0 }, { -1, 5, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 2, 3, 0 }, + { -2, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 6, 1, 1 }, { -6, 1, 1 }, { 2, 4, 0 }, + { -2, 4, 0 }, { 1, 7, 0 }, { -1, 7, 0 }, { 4, 2, 1 }, { -4, 2, 1 }, { 7, 1, 2 }, + { -7, 1, 2 }, { 3, 3, 0 }, { -3, 3, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, { 2, 5, 0 }, + { -2, 5, 0 }, { 8, 1, 2 }, { -8, 1, 2 }, { 1, 9, 0 }, { -1, 9, 0 }, { 3, 4, 0 }, + { -3, 4, 0 }, { 2, 6, 0 }, { -2, 6, 0 }, { 5, 2, 1 }, { -5, 2, 1 }, { 1, 10, 0 }, + { -1, 10, 0 }, { 9, 1, 2 }, { -9, 1, 2 }, { 4, 3, 1 }, { -4, 3, 1 } + }, + //level_add + { 0,10, 6, 5, 4, 3, 3, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 3, //inc_limit + 10 //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, + { -5, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 6, 1, 0 }, + { -6, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 7, 1, 1 }, { -7, 1, 1 }, { 1, 4, 0 }, + { -1, 4, 0 }, { 8, 1, 1 }, { -8, 1, 1 }, { 2, 3, 0 }, { -2, 3, 0 }, { 4, 2, 0 }, + { -4, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 9, 1, 1 }, { -9, 1, 1 }, { 5, 2, 0 }, + { -5, 2, 0 }, { 2, 4, 0 }, { -2, 4, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 10, 1, 2 }, + {-10, 1, 2 }, { 3, 3, 0 }, { -3, 3, 0 }, { 11, 1, 2 }, {-11, 1, 2 }, { 1, 7, 0 }, + { -1, 7, 0 }, { 6, 2, 0 }, { -6, 2, 0 }, { 3, 4, 0 }, { -3, 4, 0 }, { 2, 5, 0 }, + { -2, 5, 0 }, { 12, 1, 2 }, {-12, 1, 2 }, { 4, 3, 0 }, { -4, 3, 0 } + }, + //level_add + { 0, 13, 7, 5, 4, 3, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 6, //inc_limit + 7 //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 1, 2, 0 }, + { -1, 2, 0 }, { 6, 1, 0 }, { -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, + { -8, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 9, 1, 0 }, { -9, 1, 0 }, { 1, 3, 0 }, + { -1, 3, 0 }, { 10, 1, 1 }, { -10, 1, 1 }, { 3, 2, 0 }, { -3, 2, 0 }, { 11, 1, 1 }, + { -11, 1, 1 }, { 4, 2, 0 }, { -4, 2, 0 }, { 12, 1, 1 }, { -12, 1, 1 }, { 1, 4, 0 }, + { -1, 4, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 13, 1, 1 }, { -13, 1, 1 }, { 5, 2, 0 }, + { -5, 2, 0 }, { 14, 1, 1 }, { -14, 1, 1 }, { 6, 2, 0 }, { -6, 2, 0 }, { 1, 5, 0 }, + { -1, 5, 0 }, { 15, 1, 1 }, { -15, 1, 1 }, { 3, 3, 0 }, { -3, 3, 0 }, { 16, 1, 1 }, + { -16, 1, 1 }, { 2, 4, 0 }, { -2, 4, 0 }, { 7, 2, 0 }, { -7, 2, 0 } + }, + //level_add + { 0, 17, 8, 4, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + 9, //inc_limit + 5 //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 }, + { -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 8, 1, 0 }, + { -8, 1, 0 }, { 9, 1, 0 }, { -9, 1, 0 }, { 10, 1, 0 }, { -10, 1, 0 }, { 11, 1, 0 }, + { -11, 1, 0 }, { 12, 1, 0 }, { -12, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 13, 1, 0 }, + { -13, 1, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 14, 1, 0 }, { -14, 1, 0 }, { 15, 1, 0 }, + { -15, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 16, 1, 0 }, { -16, 1, 0 }, { 17, 1, 0 }, + { -17, 1, 0 }, { 18, 1, 0 }, { -18, 1, 0 }, { 4, 2, 0 }, { -4, 2, 0 }, { 19, 1, 0 }, + { -19, 1, 0 }, { 20, 1, 0 }, { -20, 1, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 1, 4, 0 }, + { -1, 4, 0 }, { 5, 2, 0 }, { -5, 2, 0 }, { 21, 1, 0 }, { -21, 1, 0 } + }, + //level_add + { 0, 22, 6, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 2, //golomb_order + INT_MAX, //inc_limit + 4 //max_run + } +}; + +static const struct dec_2dvlc chroma_dec[5] = { + { + { //level / run + { 1, 1, 1 }, { -1, 1, 1 }, { 1, 2, 1 }, { -1, 2, 1 }, { 1, 3, 1 }, { -1, 3, 1 }, + { 1, 4, 1 }, { -1, 4, 1 }, { 1, 5, 1 }, { -1, 5, 1 }, { 1, 6, 1 }, { -1, 6, 1 }, + { 1, 7, 1 }, { -1, 7, 1 }, { 2, 1, 2 }, { -2, 1, 2 }, { 1, 8, 1 }, { -1, 8, 1 }, + { 1, 9, 1 }, { -1, 9, 1 }, { 1, 10, 1 }, { -1, 10, 1 }, { 1, 11, 1 }, { -1, 11, 1 }, + { 1, 12, 1 }, { -1, 12, 1 }, { 1, 13, 1 }, { -1, 13, 1 }, { 1, 14, 1 }, { -1, 14, 1 }, + { 1, 15, 1 }, { -1, 15, 1 }, { 3, 1, 3 }, { -3, 1, 3 }, { 1, 16, 1 }, { -1, 16, 1 }, + { 1, 17, 1 }, { -1, 17, 1 }, { 1, 18, 1 }, { -1, 18, 1 }, { 1, 19, 1 }, { -1, 19, 1 }, + { 1, 20, 1 }, { -1, 20, 1 }, { 1, 21, 1 }, { -1, 21, 1 }, { 1, 22, 1 }, { -1, 22, 1 }, + { 2, 2, 2 }, { -2, 2, 2 }, { 1, 23, 1 }, { -1, 23, 1 }, { 1, 24, 1 }, { -1, 24, 1 }, + { 1, 25, 1 }, { -1, 25, 1 }, { 4, 1, 3 }, { -4, 1, 3 }, { EOB } + }, + //level_add + { 0, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 }, + 2, //golomb_order + 0, //inc_limit + 25 //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 2, 1, 1 }, + { -2, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 1, 5, 0 }, + { -1, 5, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 3, 1, 2 }, { -3, 1, 2 }, { 1, 7, 0 }, + { -1, 7, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, { 2, 2, 1 }, { -2, 2, 1 }, { 1, 9, 0 }, + { -1, 9, 0 }, { 1, 10, 0 }, { -1, 10, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 4, 1, 2 }, + { -4, 1, 2 }, { 1, 12, 0 }, { -1, 12, 0 }, { 1, 13, 0 }, { -1, 13, 0 }, { 1, 14, 0 }, + { -1, 14, 0 }, { 2, 3, 1 }, { -2, 3, 1 }, { 1, 15, 0 }, { -1, 15, 0 }, { 2, 4, 1 }, + { -2, 4, 1 }, { 5, 1, 3 }, { -5, 1, 3 }, { 3, 2, 2 }, { -3, 2, 2 }, { 1, 16, 0 }, + { -1, 16, 0 }, { 1, 17, 0 }, { -1, 17, 0 }, { 1, 18, 0 }, { -1, 18, 0 }, { 2, 5, 1 }, + { -2, 5, 1 }, { 1, 19, 0 }, { -1, 19, 0 }, { 1, 20, 0 }, { -1, 20, 0 } + }, + //level_add + { 0, 6, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1 }, + 0, //golomb_order + 1, //inc_limit + 20 //max_run + }, + { + { //level / run + { 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 2, 1, 0 }, { -2, 1, 0 }, { 1, 2, 0 }, + { -1, 2, 0 }, { 3, 1, 1 }, { -3, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 4, 1, 1 }, + { -4, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 5, 1, 2 }, + { -5, 1, 2 }, { 1, 5, 0 }, { -1, 5, 0 }, { 3, 2, 1 }, { -3, 2, 1 }, { 2, 3, 0 }, + { -2, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 6, 1, 2 }, { -6, 1, 2 }, { 1, 7, 0 }, + { -1, 7, 0 }, { 2, 4, 0 }, { -2, 4, 0 }, { 7, 1, 2 }, { -7, 1, 2 }, { 1, 8, 0 }, + { -1, 8, 0 }, { 4, 2, 1 }, { -4, 2, 1 }, { 1, 9, 0 }, { -1, 9, 0 }, { 3, 3, 1 }, + { -3, 3, 1 }, { 2, 5, 0 }, { -2, 5, 0 }, { 2, 6, 0 }, { -2, 6, 0 }, { 8, 1, 2 }, + { -8, 1, 2 }, { 1, 10, 0 }, { -1, 10, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 9, 1, 2 }, + { -9, 1, 2 }, { 5, 2, 2 }, { -5, 2, 2 }, { 3, 4, 1 }, { -3, 4, 1 }, + }, + //level_add + { 0,10, 6, 4, 4, 3, 3, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 1, //golomb_order + 2, //inc_limit + 11 //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 5, 1, 1 }, + { -5, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 6, 1, 1 }, { -6, 1, 1 }, { 1, 3, 0 }, + { -1, 3, 0 }, { 7, 1, 1 }, { -7, 1, 1 }, { 3, 2, 0 }, { -3, 2, 0 }, { 8, 1, 1 }, + { -8, 1, 1 }, { 1, 4, 0 }, { -1, 4, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 9, 1, 1 }, + { -9, 1, 1 }, { 4, 2, 0 }, { -4, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 10, 1, 1 }, + {-10, 1, 1 }, { 3, 3, 0 }, { -3, 3, 0 }, { 5, 2, 1 }, { -5, 2, 1 }, { 2, 4, 0 }, + { -2, 4, 0 }, { 11, 1, 1 }, {-11, 1, 1 }, { 1, 6, 0 }, { -1, 6, 0 }, { 12, 1, 1 }, + {-12, 1, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 6, 2, 1 }, { -6, 2, 1 }, { 13, 1, 1 }, + {-13, 1, 1 }, { 2, 5, 0 }, { -2, 5, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, + }, + //level_add + { 0, 14, 7, 4, 3, 3, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 1, //golomb_order + 4, //inc_limit + 8 //max_run + }, + { + { //level / run + { EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, + { -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 }, + { -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, { -8, 1, 0 }, { 1, 2, 0 }, + { -1, 2, 0 }, { 9, 1, 0 }, { -9, 1, 0 }, { 10, 1, 0 }, { -10, 1, 0 }, { 11, 1, 0 }, + { -11, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 12, 1, 0 }, { -12, 1, 0 }, { 13, 1, 0 }, + { -13, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 14, 1, 0 }, { -14, 1, 0 }, { 1, 3, 0 }, + { -1, 3, 0 }, { 15, 1, 0 }, { -15, 1, 0 }, { 4, 2, 0 }, { -4, 2, 0 }, { 16, 1, 0 }, + { -16, 1, 0 }, { 17, 1, 0 }, { -17, 1, 0 }, { 5, 2, 0 }, { -5, 2, 0 }, { 1, 4, 0 }, + { -1, 4, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 18, 1, 0 }, { -18, 1, 0 }, { 6, 2, 0 }, + { -6, 2, 0 }, { 19, 1, 0 }, { -19, 1, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, + }, + //level_add + { 0, 20, 7, 3, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + 0, //golomb_order + INT_MAX, //inc_limit + 5, //max_run + } +}; + +#undef EOB + +/***************************************************************************** + * + * motion vector prediction + * + ****************************************************************************/ + +static inline void store_mvs(AVSContext *h) +{ + h->col_mv[h->mbidx * 4 + 0] = h->mv[MV_FWD_X0]; + h->col_mv[h->mbidx * 4 + 1] = h->mv[MV_FWD_X1]; + h->col_mv[h->mbidx * 4 + 2] = h->mv[MV_FWD_X2]; + h->col_mv[h->mbidx * 4 + 3] = h->mv[MV_FWD_X3]; +} + +static inline void mv_pred_direct(AVSContext *h, cavs_vector *pmv_fw, + cavs_vector *col_mv) +{ + cavs_vector *pmv_bw = pmv_fw + MV_BWD_OFFS; + int den = h->direct_den[col_mv->ref]; + int m = col_mv->x >> 31; + + pmv_fw->dist = h->dist[1]; + pmv_bw->dist = h->dist[0]; + pmv_fw->ref = 1; + pmv_bw->ref = 0; + /* scale the co-located motion vector according to its temporal span */ + pmv_fw->x = (((den + (den * col_mv->x * pmv_fw->dist ^ m) - m - 1) >> 14) ^ m) - m; + pmv_bw->x = m - (((den + (den * col_mv->x * pmv_bw->dist ^ m) - m - 1) >> 14) ^ m); + m = col_mv->y >> 31; + pmv_fw->y = (((den + (den * col_mv->y * pmv_fw->dist ^ m) - m - 1) >> 14) ^ m) - m; + pmv_bw->y = m - (((den + (den * col_mv->y * pmv_bw->dist ^ m) - m - 1) >> 14) ^ m); +} + +static inline void mv_pred_sym(AVSContext *h, cavs_vector *src, + enum cavs_block size) +{ + cavs_vector *dst = src + MV_BWD_OFFS; + + /* backward mv is the scaled and negated forward mv */ + dst->x = -((src->x * h->sym_factor + 256) >> 9); + dst->y = -((src->y * h->sym_factor + 256) >> 9); + dst->ref = 0; + dst->dist = h->dist[0]; + set_mvs(dst, size); +} + +/***************************************************************************** + * + * residual data decoding + * + ****************************************************************************/ + +/** kth-order exponential golomb code */ +static inline int get_ue_code(GetBitContext *gb, int order) +{ + unsigned ret = get_ue_golomb(gb); + if (ret >= ((1U<<31)>>order)) { + av_log(NULL, AV_LOG_ERROR, "get_ue_code: value too larger\n"); + return AVERROR_INVALIDDATA; + } + if (order) { + return (ret<scantable.permutated; + + /* inverse scan and dequantization */ + while (--coeff_num >= 0) { + pos += run_buf[coeff_num]; + if (pos > 63) { + av_log(h->avctx, AV_LOG_ERROR, + "position out of block bounds at pic %d MB(%d,%d)\n", + h->cur.poc, h->mbx, h->mby); + return -1; + } + dst[scantab[pos]] = (level_buf[coeff_num] * mul + round) >> shift; + } + return 0; +} + +/** + * decode coefficients from one 8x8 block, dequantize, inverse transform + * and add them to sample block + * @param r pointer to 2D VLC table + * @param esc_golomb_order escape codes are k-golomb with this order k + * @param qp quantizer + * @param dst location of sample block + * @param stride line stride in frame buffer + */ +static int decode_residual_block(AVSContext *h, GetBitContext *gb, + const struct dec_2dvlc *r, int esc_golomb_order, + int qp, uint8_t *dst, int stride) +{ + int i, esc_code, level, mask; + unsigned int level_code, run; + int16_t level_buf[65]; + uint8_t run_buf[65]; + int16_t *block = h->block; + + for (i = 0; i < 65; i++) { + level_code = get_ue_code(gb, r->golomb_order); + if (level_code >= ESCAPE_CODE) { + run = ((level_code - ESCAPE_CODE) >> 1) + 1; + if(run > 64) + return -1; + esc_code = get_ue_code(gb, esc_golomb_order); + level = esc_code + (run > r->max_run ? 1 : r->level_add[run]); + while (level > r->inc_limit) + r++; + mask = -(level_code & 1); + level = (level ^ mask) - mask; + } else { + level = r->rltab[level_code][0]; + if (!level) //end of block signal + break; + run = r->rltab[level_code][1]; + r += r->rltab[level_code][2]; + } + level_buf[i] = level; + run_buf[i] = run; + } + if (dequant(h, level_buf, run_buf, block, dequant_mul[qp], + dequant_shift[qp], i)) + return -1; + h->cdsp.cavs_idct8_add(dst, block, stride); + h->dsp.clear_block(block); + return 0; +} + + +static inline void decode_residual_chroma(AVSContext *h) +{ + if (h->cbp & (1 << 4)) + decode_residual_block(h, &h->gb, chroma_dec, 0, + cavs_chroma_qp[h->qp], h->cu, h->c_stride); + if (h->cbp & (1 << 5)) + decode_residual_block(h, &h->gb, chroma_dec, 0, + cavs_chroma_qp[h->qp], h->cv, h->c_stride); +} + +static inline int decode_residual_inter(AVSContext *h) +{ + int block; + + /* get coded block pattern */ + int cbp = get_ue_golomb(&h->gb); + if (cbp > 63U) { + av_log(h->avctx, AV_LOG_ERROR, "illegal inter cbp\n"); + return -1; + } + h->cbp = cbp_tab[cbp][1]; + + /* get quantizer */ + if (h->cbp && !h->qp_fixed) + h->qp = (h->qp + get_se_golomb(&h->gb)) & 63; + for (block = 0; block < 4; block++) + if (h->cbp & (1 << block)) + decode_residual_block(h, &h->gb, inter_dec, 0, h->qp, + h->cy + h->luma_scan[block], h->l_stride); + decode_residual_chroma(h); + + return 0; +} + +/***************************************************************************** + * + * macroblock level + * + ****************************************************************************/ + +static inline void set_mv_intra(AVSContext *h) +{ + h->mv[MV_FWD_X0] = ff_cavs_intra_mv; + set_mvs(&h->mv[MV_FWD_X0], BLK_16X16); + h->mv[MV_BWD_X0] = ff_cavs_intra_mv; + set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); + if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) + h->col_type_base[h->mbidx] = I_8X8; +} + +static int decode_mb_i(AVSContext *h, int cbp_code) +{ + GetBitContext *gb = &h->gb; + unsigned pred_mode_uv; + int block; + uint8_t top[18]; + uint8_t *left = NULL; + uint8_t *d; + + ff_cavs_init_mb(h); + + /* get intra prediction modes from stream */ + for (block = 0; block < 4; block++) { + int nA, nB, predpred; + int pos = scan3x3[block]; + + nA = h->pred_mode_Y[pos - 1]; + nB = h->pred_mode_Y[pos - 3]; + predpred = FFMIN(nA, nB); + if (predpred == NOT_AVAIL) // if either is not available + predpred = INTRA_L_LP; + if (!get_bits1(gb)) { + int rem_mode = get_bits(gb, 2); + predpred = rem_mode + (rem_mode >= predpred); + } + h->pred_mode_Y[pos] = predpred; + } + pred_mode_uv = get_ue_golomb(gb); + if (pred_mode_uv > 6) { + av_log(h->avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n"); + return -1; + } + ff_cavs_modify_mb_i(h, &pred_mode_uv); + + /* get coded block pattern */ + if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) + cbp_code = get_ue_golomb(gb); + if (cbp_code > 63U) { + av_log(h->avctx, AV_LOG_ERROR, "illegal intra cbp\n"); + return -1; + } + h->cbp = cbp_tab[cbp_code][0]; + if (h->cbp && !h->qp_fixed) + h->qp = (h->qp + get_se_golomb(gb)) & 63; //qp_delta + + /* luma intra prediction interleaved with residual decode/transform/add */ + for (block = 0; block < 4; block++) { + d = h->cy + h->luma_scan[block]; + ff_cavs_load_intra_pred_luma(h, top, &left, block); + h->intra_pred_l[h->pred_mode_Y[scan3x3[block]]] + (d, top, left, h->l_stride); + if (h->cbp & (1<qp, d, h->l_stride); + } + + /* chroma intra prediction */ + ff_cavs_load_intra_pred_chroma(h); + h->intra_pred_c[pred_mode_uv](h->cu, &h->top_border_u[h->mbx * 10], + h->left_border_u, h->c_stride); + h->intra_pred_c[pred_mode_uv](h->cv, &h->top_border_v[h->mbx * 10], + h->left_border_v, h->c_stride); + + decode_residual_chroma(h); + ff_cavs_filter(h, I_8X8); + set_mv_intra(h); + return 0; +} + +static inline void set_intra_mode_default(AVSContext *h) +{ + if (h->stream_revision > 0) { + h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL; + h->top_pred_Y[h->mbx * 2 + 0] = h->top_pred_Y[h->mbx * 2 + 1] = NOT_AVAIL; + } else { + h->pred_mode_Y[3] = h->pred_mode_Y[6] = INTRA_L_LP; + h->top_pred_Y[h->mbx * 2 + 0] = h->top_pred_Y[h->mbx * 2 + 1] = INTRA_L_LP; + } +} + +static void decode_mb_p(AVSContext *h, enum cavs_mb mb_type) +{ + GetBitContext *gb = &h->gb; + int ref[4]; + + ff_cavs_init_mb(h); + switch (mb_type) { + case P_SKIP: + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_PSKIP, BLK_16X16, 0); + break; + case P_16X16: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, ref[0]); + break; + case P_16X8: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ref[2] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, ref[0]); + ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, ref[2]); + break; + case P_8X16: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ref[1] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, ref[0]); + ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, ref[1]); + break; + case P_8X8: + ref[0] = h->ref_flag ? 0 : get_bits1(gb); + ref[1] = h->ref_flag ? 0 : get_bits1(gb); + ref[2] = h->ref_flag ? 0 : get_bits1(gb); + ref[3] = h->ref_flag ? 0 : get_bits1(gb); + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_MEDIAN, BLK_8X8, ref[0]); + ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_MEDIAN, BLK_8X8, ref[1]); + ff_cavs_mv(h, MV_FWD_X2, MV_FWD_X1, MV_PRED_MEDIAN, BLK_8X8, ref[2]); + ff_cavs_mv(h, MV_FWD_X3, MV_FWD_X0, MV_PRED_MEDIAN, BLK_8X8, ref[3]); + } + ff_cavs_inter(h, mb_type); + set_intra_mode_default(h); + store_mvs(h); + if (mb_type != P_SKIP) + decode_residual_inter(h); + ff_cavs_filter(h, mb_type); + h->col_type_base[h->mbidx] = mb_type; +} + +static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) +{ + int block; + enum cavs_sub_mb sub_type[4]; + int flags; + + ff_cavs_init_mb(h); + + /* reset all MVs */ + h->mv[MV_FWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_FWD_X0], BLK_16X16); + h->mv[MV_BWD_X0] = ff_cavs_dir_mv; + set_mvs(&h->mv[MV_BWD_X0], BLK_16X16); + switch (mb_type) { + case B_SKIP: + case B_DIRECT: + if (!h->col_type_base[h->mbidx]) { + /* intra MB at co-location, do in-plane prediction */ + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_BSKIP, BLK_16X16, 1); + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_BSKIP, BLK_16X16, 0); + } else + /* direct prediction from co-located P MB, block-wise */ + for (block = 0; block < 4; block++) + mv_pred_direct(h, &h->mv[mv_scan[block]], + &h->col_mv[h->mbidx * 4 + block]); + break; + case B_FWD_16X16: + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); + break; + case B_SYM_16X16: + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1); + mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X16); + break; + case B_BWD_16X16: + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0); + break; + case B_8X8: + for (block = 0; block < 4; block++) + sub_type[block] = get_bits(&h->gb, 2); + for (block = 0; block < 4; block++) { + switch (sub_type[block]) { + case B_SUB_DIRECT: + if (!h->col_type_base[h->mbidx]) { + /* intra MB at co-location, do in-plane prediction */ + ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3, + MV_PRED_BSKIP, BLK_8X8, 1); + ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS, + mv_scan[block] - 3 + MV_BWD_OFFS, + MV_PRED_BSKIP, BLK_8X8, 0); + } else + mv_pred_direct(h, &h->mv[mv_scan[block]], + &h->col_mv[h->mbidx * 4 + block]); + break; + case B_SUB_FWD: + ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3, + MV_PRED_MEDIAN, BLK_8X8, 1); + break; + case B_SUB_SYM: + ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3, + MV_PRED_MEDIAN, BLK_8X8, 1); + mv_pred_sym(h, &h->mv[mv_scan[block]], BLK_8X8); + break; + } + } + for (block = 0; block < 4; block++) { + if (sub_type[block] == B_SUB_BWD) + ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS, + mv_scan[block] + MV_BWD_OFFS - 3, + MV_PRED_MEDIAN, BLK_8X8, 0); + } + break; + default: + if (mb_type <= B_SYM_16X16) { + av_log(h->avctx, AV_LOG_ERROR, "Invalid mb_type %d in B frame\n", mb_type); + return AVERROR_INVALIDDATA; + } + av_assert2(mb_type < B_8X8); + flags = ff_cavs_partition_flags[mb_type]; + if (mb_type & 1) { /* 16x8 macroblock types */ + if (flags & FWD0) + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, 1); + if (flags & SYM0) + mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X8); + if (flags & FWD1) + ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, 1); + if (flags & SYM1) + mv_pred_sym(h, &h->mv[MV_FWD_X2], BLK_16X8); + if (flags & BWD0) + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_TOP, BLK_16X8, 0); + if (flags & BWD1) + ff_cavs_mv(h, MV_BWD_X2, MV_BWD_A1, MV_PRED_LEFT, BLK_16X8, 0); + } else { /* 8x16 macroblock types */ + if (flags & FWD0) + ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, 1); + if (flags & SYM0) + mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_8X16); + if (flags & FWD1) + ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 1); + if (flags & SYM1) + mv_pred_sym(h, &h->mv[MV_FWD_X1], BLK_8X16); + if (flags & BWD0) + ff_cavs_mv(h, MV_BWD_X0, MV_BWD_B3, MV_PRED_LEFT, BLK_8X16, 0); + if (flags & BWD1) + ff_cavs_mv(h, MV_BWD_X1, MV_BWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 0); + } + } + ff_cavs_inter(h, mb_type); + set_intra_mode_default(h); + if (mb_type != B_SKIP) + decode_residual_inter(h); + ff_cavs_filter(h, mb_type); + + return 0; +} + +/***************************************************************************** + * + * slice level + * + ****************************************************************************/ + +static inline int decode_slice_header(AVSContext *h, GetBitContext *gb) +{ + if (h->stc > 0xAF) + av_log(h->avctx, AV_LOG_ERROR, "unexpected start code 0x%02x\n", h->stc); + + if (h->stc >= h->mb_height) + return -1; + + h->mby = h->stc; + h->mbidx = h->mby * h->mb_width; + + /* mark top macroblocks as unavailable */ + h->flags &= ~(B_AVAIL | C_AVAIL); + if ((h->mby == 0) && (!h->qp_fixed)) { + h->qp_fixed = get_bits1(gb); + h->qp = get_bits(gb, 6); + } + /* inter frame or second slice can have weighting params */ + if ((h->cur.f->pict_type != AV_PICTURE_TYPE_I) || + (!h->pic_structure && h->mby >= h->mb_width / 2)) + if (get_bits1(gb)) { //slice_weighting_flag + av_log(h->avctx, AV_LOG_ERROR, + "weighted prediction not yet supported\n"); + } + return 0; +} + +static inline int check_for_slice(AVSContext *h) +{ + GetBitContext *gb = &h->gb; + int align; + + if (h->mbx) + return 0; + align = (-get_bits_count(gb)) & 7; + /* check for stuffing byte */ + if (!align && (show_bits(gb, 8) == 0x80)) + align = 8; + if ((show_bits_long(gb, 24 + align) & 0xFFFFFF) == 0x000001) { + skip_bits_long(gb, 24 + align); + h->stc = get_bits(gb, 8); + if (h->stc >= h->mb_height) + return 0; + decode_slice_header(h, gb); + return 1; + } + return 0; +} + +/***************************************************************************** + * + * frame level + * + ****************************************************************************/ + +static int decode_pic(AVSContext *h) +{ + int skip_count = -1; + int ret; + enum cavs_mb mb_type; + + av_frame_unref(h->cur.f); + + skip_bits(&h->gb, 16);//bbv_dwlay + if (h->stc == PIC_PB_START_CODE) { + h->cur.f->pict_type = get_bits(&h->gb, 2) + AV_PICTURE_TYPE_I; + if (h->cur.f->pict_type > AV_PICTURE_TYPE_B) { + av_log(h->avctx, AV_LOG_ERROR, "illegal picture type\n"); + return -1; + } + /* make sure we have the reference frames we need */ + if (!h->DPB[0].f->data[0] || + (!h->DPB[1].f->data[0] && h->cur.f->pict_type == AV_PICTURE_TYPE_B)) + return -1; + } else { + h->cur.f->pict_type = AV_PICTURE_TYPE_I; + if (get_bits1(&h->gb)) + skip_bits(&h->gb, 24);//time_code + /* old sample clips were all progressive and no low_delay, + bump stream revision if detected otherwise */ + if (h->low_delay || !(show_bits(&h->gb, 9) & 1)) + h->stream_revision = 1; + /* similarly test top_field_first and repeat_first_field */ + else if (show_bits(&h->gb, 11) & 3) + h->stream_revision = 1; + if (h->stream_revision > 0) + skip_bits(&h->gb, 1); //marker_bit + } + + if ((ret = ff_get_buffer(h->avctx, h->cur.f, + h->cur.f->pict_type == AV_PICTURE_TYPE_B ? + 0 : AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if (!h->edge_emu_buffer) { + int alloc_size = FFALIGN(FFABS(h->cur.f->linesize[0]) + 32, 32); + h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 24); + if (!h->edge_emu_buffer) + return AVERROR(ENOMEM); + } + + if ((ret = ff_cavs_init_pic(h)) < 0) + return ret; + h->cur.poc = get_bits(&h->gb, 8) * 2; + + /* get temporal distances and MV scaling factors */ + if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) { + h->dist[0] = (h->cur.poc - h->DPB[0].poc + 512) % 512; + } else { + h->dist[0] = (h->DPB[0].poc - h->cur.poc + 512) % 512; + } + h->dist[1] = (h->cur.poc - h->DPB[1].poc + 512) % 512; + h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0; + h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0; + if (h->cur.f->pict_type == AV_PICTURE_TYPE_B) { + h->sym_factor = h->dist[0] * h->scale_den[1]; + } else { + h->direct_den[0] = h->dist[0] ? 16384 / h->dist[0] : 0; + h->direct_den[1] = h->dist[1] ? 16384 / h->dist[1] : 0; + } + + if (h->low_delay) + get_ue_golomb(&h->gb); //bbv_check_times + h->progressive = get_bits1(&h->gb); + h->pic_structure = 1; + if (!h->progressive) + h->pic_structure = get_bits1(&h->gb); + if (!h->pic_structure && h->stc == PIC_PB_START_CODE) + skip_bits1(&h->gb); //advanced_pred_mode_disable + skip_bits1(&h->gb); //top_field_first + skip_bits1(&h->gb); //repeat_first_field + h->qp_fixed = get_bits1(&h->gb); + h->qp = get_bits(&h->gb, 6); + if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) { + if (!h->progressive && !h->pic_structure) + skip_bits1(&h->gb);//what is this? + skip_bits(&h->gb, 4); //reserved bits + } else { + if (!(h->cur.f->pict_type == AV_PICTURE_TYPE_B && h->pic_structure == 1)) + h->ref_flag = get_bits1(&h->gb); + skip_bits(&h->gb, 4); //reserved bits + h->skip_mode_flag = get_bits1(&h->gb); + } + h->loop_filter_disable = get_bits1(&h->gb); + if (!h->loop_filter_disable && get_bits1(&h->gb)) { + h->alpha_offset = get_se_golomb(&h->gb); + h->beta_offset = get_se_golomb(&h->gb); + } else { + h->alpha_offset = h->beta_offset = 0; + } + if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) { + do { + check_for_slice(h); + decode_mb_i(h, 0); + } while (ff_cavs_next_mb(h)); + } else if (h->cur.f->pict_type == AV_PICTURE_TYPE_P) { + do { + if (check_for_slice(h)) + skip_count = -1; + if (h->skip_mode_flag && (skip_count < 0)) + skip_count = get_ue_golomb(&h->gb); + if (h->skip_mode_flag && skip_count--) { + decode_mb_p(h, P_SKIP); + } else { + mb_type = get_ue_golomb(&h->gb) + P_SKIP + h->skip_mode_flag; + if (mb_type > P_8X8) + decode_mb_i(h, mb_type - P_8X8 - 1); + else + decode_mb_p(h, mb_type); + } + } while (ff_cavs_next_mb(h)); + } else { /* AV_PICTURE_TYPE_B */ + do { + if (check_for_slice(h)) + skip_count = -1; + if (h->skip_mode_flag && (skip_count < 0)) + skip_count = get_ue_golomb(&h->gb); + if (h->skip_mode_flag && skip_count--) { + decode_mb_b(h, B_SKIP); + } else { + mb_type = get_ue_golomb(&h->gb) + B_SKIP + h->skip_mode_flag; + if (mb_type > B_8X8) + decode_mb_i(h, mb_type - B_8X8 - 1); + else + decode_mb_b(h, mb_type); + } + } while (ff_cavs_next_mb(h)); + } + if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) { + av_frame_unref(h->DPB[1].f); + FFSWAP(AVSFrame, h->cur, h->DPB[1]); + FFSWAP(AVSFrame, h->DPB[0], h->DPB[1]); + } + return 0; +} + +/***************************************************************************** + * + * headers and interface + * + ****************************************************************************/ + +static int decode_seq_header(AVSContext *h) +{ + int frame_rate_code; + int width, height; + + h->profile = get_bits(&h->gb, 8); + h->level = get_bits(&h->gb, 8); + skip_bits1(&h->gb); //progressive sequence + + width = get_bits(&h->gb, 14); + height = get_bits(&h->gb, 14); + if ((h->width || h->height) && (h->width != width || h->height != height)) { + avpriv_report_missing_feature(h->avctx, + "Width/height changing in CAVS"); + return AVERROR_PATCHWELCOME; + } + if (width <= 0 || height <= 0) { + av_log(h->avctx, AV_LOG_ERROR, "Dimensions invalid\n"); + return AVERROR_INVALIDDATA; + } + h->width = width; + h->height = height; + + skip_bits(&h->gb, 2); //chroma format + skip_bits(&h->gb, 3); //sample_precision + h->aspect_ratio = get_bits(&h->gb, 4); + frame_rate_code = get_bits(&h->gb, 4); + skip_bits(&h->gb, 18); //bit_rate_lower + skip_bits1(&h->gb); //marker_bit + skip_bits(&h->gb, 12); //bit_rate_upper + h->low_delay = get_bits1(&h->gb); + h->mb_width = (h->width + 15) >> 4; + h->mb_height = (h->height + 15) >> 4; + h->avctx->time_base.den = ff_mpeg12_frame_rate_tab[frame_rate_code].num; + h->avctx->time_base.num = ff_mpeg12_frame_rate_tab[frame_rate_code].den; + h->avctx->width = h->width; + h->avctx->height = h->height; + if (!h->top_qp) + ff_cavs_init_top_lines(h); + return 0; +} + +static void cavs_flush(AVCodecContext * avctx) +{ + AVSContext *h = avctx->priv_data; + h->got_keyframe = 0; +} + +static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + AVSContext *h = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + uint32_t stc = -1; + int input_size, ret; + const uint8_t *buf_end; + const uint8_t *buf_ptr; + + if (buf_size == 0) { + if (!h->low_delay && h->DPB[0].f->data[0]) { + *got_frame = 1; + av_frame_move_ref(data, h->DPB[0].f); + } + return 0; + } + + buf_ptr = buf; + buf_end = buf + buf_size; + for(;;) { + buf_ptr = avpriv_mpv_find_start_code(buf_ptr, buf_end, &stc); + if ((stc & 0xFFFFFE00) || buf_ptr == buf_end) + return FFMAX(0, buf_ptr - buf); + input_size = (buf_end - buf_ptr) * 8; + switch (stc) { + case CAVS_START_CODE: + init_get_bits(&h->gb, buf_ptr, input_size); + decode_seq_header(h); + break; + case PIC_I_START_CODE: + if (!h->got_keyframe) { + av_frame_unref(h->DPB[0].f); + av_frame_unref(h->DPB[1].f); + h->got_keyframe = 1; + } + case PIC_PB_START_CODE: + *got_frame = 0; + if (!h->got_keyframe) + break; + if(!h->top_qp) + break; + init_get_bits(&h->gb, buf_ptr, input_size); + h->stc = stc; + if (decode_pic(h)) + break; + *got_frame = 1; + if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) { + if (h->DPB[1].f->data[0]) { + if ((ret = av_frame_ref(data, h->DPB[1].f)) < 0) + return ret; + } else { + *got_frame = 0; + } + } else { + av_frame_move_ref(data, h->cur.f); + } + break; + case EXT_START_CODE: + //mpeg_decode_extension(avctx, buf_ptr, input_size); + break; + case USER_START_CODE: + //mpeg_decode_user_data(avctx, buf_ptr, input_size); + break; + default: + if (stc <= SLICE_MAX_START_CODE) { + init_get_bits(&h->gb, buf_ptr, input_size); + decode_slice_header(h, &h->gb); + } + break; + } + } +} + +AVCodec ff_cavs_decoder = { + .name = "cavs", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CAVS, + .priv_data_size = sizeof(AVSContext), + .init = ff_cavs_init, + .close = ff_cavs_end, + .decode = cavs_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = cavs_flush, + .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"), +}; diff --git a/ffmpeg/libavcodec/cavsdsp.c b/ffmpeg/libavcodec/cavsdsp.c new file mode 100644 index 0000000..904e2df --- /dev/null +++ b/ffmpeg/libavcodec/cavsdsp.c @@ -0,0 +1,566 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * + * DSP functions + * + * Copyright (c) 2006 Stefan Gehrer + * + * 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 "dsputil.h" +#include "cavsdsp.h" +#include "libavutil/common.h" + +/***************************************************************************** + * + * in-loop deblocking filter + * + ****************************************************************************/ + +#define P2 p0_p[-3*stride] +#define P1 p0_p[-2*stride] +#define P0 p0_p[-1*stride] +#define Q0 p0_p[ 0*stride] +#define Q1 p0_p[ 1*stride] +#define Q2 p0_p[ 2*stride] + +static inline void loop_filter_l2(uint8_t *p0_p,int stride,int alpha, int beta) { + int p0 = P0; + int q0 = Q0; + + if(abs(p0-q0)>2) + 2; + if(abs(P2-p0) < beta && abs(p0-q0) < alpha) { + P0 = (P1 + p0 + s) >> 2; + P1 = (2*P1 + s) >> 2; + } else + P0 = (2*P1 + s) >> 2; + if(abs(Q2-q0) < beta && abs(q0-p0) < alpha) { + Q0 = (Q1 + q0 + s) >> 2; + Q1 = (2*Q1 + s) >> 2; + } else + Q0 = (2*Q1 + s) >> 2; + } +} + +static inline void loop_filter_l1(uint8_t *p0_p, int stride, int alpha, int beta, int tc) { + int p0 = P0; + int q0 = Q0; + + if(abs(p0-q0)>3,-tc, tc); + P0 = av_clip_uint8(p0+delta); + Q0 = av_clip_uint8(q0-delta); + if(abs(P2-p0)>3, -tc, tc); + P1 = av_clip_uint8(P1+delta); + } + if(abs(Q2-q0)>3, -tc, tc); + Q1 = av_clip_uint8(Q1-delta); + } + } +} + +static inline void loop_filter_c2(uint8_t *p0_p,int stride,int alpha, int beta) { + int p0 = P0; + int q0 = Q0; + + if(abs(p0-q0)>2) + 2; + if(abs(P2-p0) < beta && abs(p0-q0) < alpha) { + P0 = (P1 + p0 + s) >> 2; + } else + P0 = (2*P1 + s) >> 2; + if(abs(Q2-q0) < beta && abs(q0-p0) < alpha) { + Q0 = (Q1 + q0 + s) >> 2; + } else + Q0 = (2*Q1 + s) >> 2; + } +} + +static inline void loop_filter_c1(uint8_t *p0_p,int stride,int alpha, int beta, + int tc) { + if(abs(P0-Q0)>3, -tc, tc); + P0 = av_clip_uint8(P0+delta); + Q0 = av_clip_uint8(Q0-delta); + } +} + +#undef P0 +#undef P1 +#undef P2 +#undef Q0 +#undef Q1 +#undef Q2 + +static void cavs_filter_lv_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<16;i++) + loop_filter_l2(d + i*stride,1,alpha,beta); + else { + if(bs1) + for(i=0;i<8;i++) + loop_filter_l1(d + i*stride,1,alpha,beta,tc); + if (bs2) + for(i=8;i<16;i++) + loop_filter_l1(d + i*stride,1,alpha,beta,tc); + } +} + +static void cavs_filter_lh_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<16;i++) + loop_filter_l2(d + i,stride,alpha,beta); + else { + if(bs1) + for(i=0;i<8;i++) + loop_filter_l1(d + i,stride,alpha,beta,tc); + if (bs2) + for(i=8;i<16;i++) + loop_filter_l1(d + i,stride,alpha,beta,tc); + } +} + +static void cavs_filter_cv_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<8;i++) + loop_filter_c2(d + i*stride,1,alpha,beta); + else { + if(bs1) + for(i=0;i<4;i++) + loop_filter_c1(d + i*stride,1,alpha,beta,tc); + if (bs2) + for(i=4;i<8;i++) + loop_filter_c1(d + i*stride,1,alpha,beta,tc); + } +} + +static void cavs_filter_ch_c(uint8_t *d, int stride, int alpha, int beta, int tc, + int bs1, int bs2) { + int i; + if(bs1==2) + for(i=0;i<8;i++) + loop_filter_c2(d + i,stride,alpha,beta); + else { + if(bs1) + for(i=0;i<4;i++) + loop_filter_c1(d + i,stride,alpha,beta,tc); + if (bs2) + for(i=4;i<8;i++) + loop_filter_c1(d + i,stride,alpha,beta,tc); + } +} + +/***************************************************************************** + * + * inverse transform + * + ****************************************************************************/ + +static void cavs_idct8_add_c(uint8_t *dst, int16_t *block, int stride) { + int i; + int16_t (*src)[8] = (int16_t(*)[8])block; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + src[0][0] += 8; + + for( i = 0; i < 8; i++ ) { + const int a0 = 3*src[i][1] - (src[i][7]<<1); + const int a1 = 3*src[i][3] + (src[i][5]<<1); + const int a2 = (src[i][3]<<1) - 3*src[i][5]; + const int a3 = (src[i][1]<<1) + 3*src[i][7]; + + const int b4 = ((a0 + a1 + a3)<<1) + a1; + const int b5 = ((a0 - a1 + a2)<<1) + a0; + const int b6 = ((a3 - a2 - a1)<<1) + a3; + const int b7 = ((a0 - a2 - a3)<<1) - a2; + + const int a7 = (src[i][2]<<2) - 10*src[i][6]; + const int a6 = (src[i][6]<<2) + 10*src[i][2]; + const int a5 = ((src[i][0] - src[i][4]) << 3) + 4; + const int a4 = ((src[i][0] + src[i][4]) << 3) + 4; + + const int b0 = a4 + a6; + const int b1 = a5 + a7; + const int b2 = a5 - a7; + const int b3 = a4 - a6; + + src[i][0] = (b0 + b4) >> 3; + src[i][1] = (b1 + b5) >> 3; + src[i][2] = (b2 + b6) >> 3; + src[i][3] = (b3 + b7) >> 3; + src[i][4] = (b3 - b7) >> 3; + src[i][5] = (b2 - b6) >> 3; + src[i][6] = (b1 - b5) >> 3; + src[i][7] = (b0 - b4) >> 3; + } + for( i = 0; i < 8; i++ ) { + const int a0 = 3*src[1][i] - (src[7][i]<<1); + const int a1 = 3*src[3][i] + (src[5][i]<<1); + const int a2 = (src[3][i]<<1) - 3*src[5][i]; + const int a3 = (src[1][i]<<1) + 3*src[7][i]; + + const int b4 = ((a0 + a1 + a3)<<1) + a1; + const int b5 = ((a0 - a1 + a2)<<1) + a0; + const int b6 = ((a3 - a2 - a1)<<1) + a3; + const int b7 = ((a0 - a2 - a3)<<1) - a2; + + const int a7 = (src[2][i]<<2) - 10*src[6][i]; + const int a6 = (src[6][i]<<2) + 10*src[2][i]; + const int a5 = (src[0][i] - src[4][i]) << 3; + const int a4 = (src[0][i] + src[4][i]) << 3; + + const int b0 = a4 + a6; + const int b1 = a5 + a7; + const int b2 = a5 - a7; + const int b3 = a4 - a6; + + dst[i + 0*stride] = cm[ dst[i + 0*stride] + ((b0 + b4) >> 7)]; + dst[i + 1*stride] = cm[ dst[i + 1*stride] + ((b1 + b5) >> 7)]; + dst[i + 2*stride] = cm[ dst[i + 2*stride] + ((b2 + b6) >> 7)]; + dst[i + 3*stride] = cm[ dst[i + 3*stride] + ((b3 + b7) >> 7)]; + dst[i + 4*stride] = cm[ dst[i + 4*stride] + ((b3 - b7) >> 7)]; + dst[i + 5*stride] = cm[ dst[i + 5*stride] + ((b2 - b6) >> 7)]; + dst[i + 6*stride] = cm[ dst[i + 6*stride] + ((b1 - b5) >> 7)]; + dst[i + 7*stride] = cm[ dst[i + 7*stride] + ((b0 - b4) >> 7)]; + } +} + +/***************************************************************************** + * + * motion compensation + * + ****************************************************************************/ + +#define CAVS_SUBPIX(OPNAME, OP, NAME, A, B, C, D, E, F) \ +static void OPNAME ## cavs_filt8_h_ ## NAME(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + const int h=8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i=0; i>3] +#define op_put2(a, b) a = cm[((b)+64)>>7] +#define op_put3(a, b) a = cm[((b)+32)>>6] +#define op_put4(a, b) a = cm[((b)+512)>>10] +#define op_avg1(a, b) a = ((a)+cm[((b)+4)>>3] +1)>>1 +#define op_avg2(a, b) a = ((a)+cm[((b)+64)>>7] +1)>>1 +#define op_avg3(a, b) a = ((a)+cm[((b)+32)>>6] +1)>>1 +#define op_avg4(a, b) a = ((a)+cm[((b)+512)>>10]+1)>>1 +CAVS_SUBPIX(put_ , op_put1, hpel, 0, -1, 5, 5, -1, 0) +CAVS_SUBPIX(put_ , op_put2, qpel_l, -1, -2, 96, 42, -7, 0) +CAVS_SUBPIX(put_ , op_put2, qpel_r, 0, -7, 42, 96, -2, -1) +CAVS_SUBPIX_HV(put_, op_put3, jj, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, ff, 0, -1, 5, 5, -1, 0, -1, -2, 96, 42, -7, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, ii, -1, -2, 96, 42, -7, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, kk, 0, -7, 42, 96, -2, -1, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(put_, op_put4, qq, 0, -1, 5, 5, -1, 0, 0, -7, 42, 96, -2,-1, 0) +CAVS_SUBPIX_HV(put_, op_put2, egpr, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 1) +CAVS_SUBPIX(avg_ , op_avg1, hpel, 0, -1, 5, 5, -1, 0) +CAVS_SUBPIX(avg_ , op_avg2, qpel_l, -1, -2, 96, 42, -7, 0) +CAVS_SUBPIX(avg_ , op_avg2, qpel_r, 0, -7, 42, 96, -2, -1) +CAVS_SUBPIX_HV(avg_, op_avg3, jj, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, ff, 0, -1, 5, 5, -1, 0, -1, -2, 96, 42, -7, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, ii, -1, -2, 96, 42, -7, 0, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, kk, 0, -7, 42, 96, -2, -1, 0, -1, 5, 5, -1, 0, 0) +CAVS_SUBPIX_HV(avg_, op_avg4, qq, 0, -1, 5, 5, -1, 0, 0, -7, 42, 96, -2,-1, 0) +CAVS_SUBPIX_HV(avg_, op_avg2, egpr, 0, -1, 5, 5, -1, 0, 0, -1, 5, 5, -1, 0, 1) +CAVS_MC(put_, 8) +CAVS_MC(put_, 16) +CAVS_MC(avg_, 8) +CAVS_MC(avg_, 16) + +#define ff_put_cavs_qpel8_mc00_c ff_put_pixels8x8_c +#define ff_avg_cavs_qpel8_mc00_c ff_avg_pixels8x8_c +#define ff_put_cavs_qpel16_mc00_c ff_put_pixels16x16_c +#define ff_avg_cavs_qpel16_mc00_c ff_avg_pixels16x16_c + +av_cold void ff_cavsdsp_init(CAVSDSPContext* c, AVCodecContext *avctx) { +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_c; \ + c->PFX ## _pixels_tab[IDX][ 1] = ff_ ## PFX ## NUM ## _mc10_c; \ + c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_c; \ + c->PFX ## _pixels_tab[IDX][ 3] = ff_ ## PFX ## NUM ## _mc30_c; \ + c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_c; \ + c->PFX ## _pixels_tab[IDX][ 5] = ff_ ## PFX ## NUM ## _mc11_c; \ + c->PFX ## _pixels_tab[IDX][ 6] = ff_ ## PFX ## NUM ## _mc21_c; \ + c->PFX ## _pixels_tab[IDX][ 7] = ff_ ## PFX ## NUM ## _mc31_c; \ + c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_c; \ + c->PFX ## _pixels_tab[IDX][ 9] = ff_ ## PFX ## NUM ## _mc12_c; \ + c->PFX ## _pixels_tab[IDX][10] = ff_ ## PFX ## NUM ## _mc22_c; \ + c->PFX ## _pixels_tab[IDX][11] = ff_ ## PFX ## NUM ## _mc32_c; \ + c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_c; \ + c->PFX ## _pixels_tab[IDX][13] = ff_ ## PFX ## NUM ## _mc13_c; \ + c->PFX ## _pixels_tab[IDX][14] = ff_ ## PFX ## NUM ## _mc23_c; \ + c->PFX ## _pixels_tab[IDX][15] = ff_ ## PFX ## NUM ## _mc33_c + dspfunc(put_cavs_qpel, 0, 16); + dspfunc(put_cavs_qpel, 1, 8); + dspfunc(avg_cavs_qpel, 0, 16); + dspfunc(avg_cavs_qpel, 1, 8); + c->cavs_filter_lv = cavs_filter_lv_c; + c->cavs_filter_lh = cavs_filter_lh_c; + c->cavs_filter_cv = cavs_filter_cv_c; + c->cavs_filter_ch = cavs_filter_ch_c; + c->cavs_idct8_add = cavs_idct8_add_c; + c->idct_perm = FF_NO_IDCT_PERM; + + if (ARCH_X86) + ff_cavsdsp_init_x86(c, avctx); +} diff --git a/ffmpeg/libavcodec/cavsdsp.h b/ffmpeg/libavcodec/cavsdsp.h new file mode 100644 index 0000000..4598c7d --- /dev/null +++ b/ffmpeg/libavcodec/cavsdsp.h @@ -0,0 +1,42 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * 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 + */ + +#ifndef AVCODEC_CAVSDSP_H +#define AVCODEC_CAVSDSP_H + +#include +#include "dsputil.h" + +typedef struct CAVSDSPContext { + qpel_mc_func put_cavs_qpel_pixels_tab[2][16]; + qpel_mc_func avg_cavs_qpel_pixels_tab[2][16]; + void (*cavs_filter_lv)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_filter_lh)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_filter_cv)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_filter_ch)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2); + void (*cavs_idct8_add)(uint8_t *dst, int16_t *block, int stride); + int idct_perm; +} CAVSDSPContext; + +void ff_cavsdsp_init(CAVSDSPContext* c, AVCodecContext *avctx); +void ff_cavsdsp_init_x86(CAVSDSPContext* c, AVCodecContext *avctx); + +#endif /* AVCODEC_CAVSDSP_H */ diff --git a/ffmpeg/libavcodec/cbrt_tablegen.c b/ffmpeg/libavcodec/cbrt_tablegen.c new file mode 100644 index 0000000..e0a8e63 --- /dev/null +++ b/ffmpeg/libavcodec/cbrt_tablegen.c @@ -0,0 +1,37 @@ +/* + * Generate a header file for hardcoded AAC cube-root table + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#include "cbrt_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + cbrt_tableinit(); + + write_fileheader(); + + WRITE_ARRAY("static const", uint32_t, cbrt_tab); + + return 0; +} diff --git a/ffmpeg/libavcodec/cbrt_tablegen.h b/ffmpeg/libavcodec/cbrt_tablegen.h new file mode 100644 index 0000000..a9d34dc --- /dev/null +++ b/ffmpeg/libavcodec/cbrt_tablegen.h @@ -0,0 +1,51 @@ +/* + * Header file for hardcoded AAC cube-root table + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_CBRT_TABLEGEN_H +#define AVCODEC_CBRT_TABLEGEN_H + +#include +#include + +#if CONFIG_HARDCODED_TABLES +#define cbrt_tableinit() +#include "libavcodec/cbrt_tables.h" +#else +static uint32_t cbrt_tab[1 << 13]; + +static void cbrt_tableinit(void) +{ + if (!cbrt_tab[(1<<13) - 1]) { + int i; + for (i = 0; i < 1<<13; i++) { + union { + float f; + uint32_t i; + } f; + f.f = cbrtf(i) * i; + cbrt_tab[i] = f.i; + } + } +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_CBRT_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/cdgraphics.c b/ffmpeg/libavcodec/cdgraphics.c new file mode 100644 index 0000000..d22e9f6 --- /dev/null +++ b/ffmpeg/libavcodec/cdgraphics.c @@ -0,0 +1,379 @@ +/* + * CD Graphics Video Decoder + * Copyright (c) 2009 Michael Tison + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +/** + * @file + * @brief CD Graphics Video Decoder + * @author Michael Tison + * @see http://wiki.multimedia.cx/index.php?title=CD_Graphics + * @see http://www.ccs.neu.edu/home/bchafy/cdb/info/cdg + */ + +/// default screen sizes +#define CDG_FULL_WIDTH 300 +#define CDG_FULL_HEIGHT 216 +#define CDG_DISPLAY_WIDTH 294 +#define CDG_DISPLAY_HEIGHT 204 +#define CDG_BORDER_WIDTH 6 +#define CDG_BORDER_HEIGHT 12 + +/// masks +#define CDG_COMMAND 0x09 +#define CDG_MASK 0x3F + +/// instruction codes +#define CDG_INST_MEMORY_PRESET 1 +#define CDG_INST_BORDER_PRESET 2 +#define CDG_INST_TILE_BLOCK 6 +#define CDG_INST_SCROLL_PRESET 20 +#define CDG_INST_SCROLL_COPY 24 +#define CDG_INST_LOAD_PAL_LO 30 +#define CDG_INST_LOAD_PAL_HIGH 31 +#define CDG_INST_TILE_BLOCK_XOR 38 + +/// data sizes +#define CDG_PACKET_SIZE 24 +#define CDG_DATA_SIZE 16 +#define CDG_TILE_HEIGHT 12 +#define CDG_TILE_WIDTH 6 +#define CDG_MINIMUM_PKT_SIZE 6 +#define CDG_MINIMUM_SCROLL_SIZE 3 +#define CDG_HEADER_SIZE 8 +#define CDG_PALETTE_SIZE 16 + +typedef struct CDGraphicsContext { + AVFrame *frame; + int hscroll; + int vscroll; +} CDGraphicsContext; + +static av_cold int cdg_decode_init(AVCodecContext *avctx) +{ + CDGraphicsContext *cc = avctx->priv_data; + + cc->frame = av_frame_alloc(); + if (!cc->frame) + return AVERROR(ENOMEM); + + avctx->width = CDG_FULL_WIDTH; + avctx->height = CDG_FULL_HEIGHT; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + return 0; +} + +static void cdg_border_preset(CDGraphicsContext *cc, uint8_t *data) +{ + int y; + int lsize = cc->frame->linesize[0]; + uint8_t *buf = cc->frame->data[0]; + int color = data[0] & 0x0F; + + if (!(data[1] & 0x0F)) { + /// fill the top and bottom borders + memset(buf, color, CDG_BORDER_HEIGHT * lsize); + memset(buf + (CDG_FULL_HEIGHT - CDG_BORDER_HEIGHT) * lsize, + color, CDG_BORDER_HEIGHT * lsize); + + /// fill the side borders + for (y = CDG_BORDER_HEIGHT; y < CDG_FULL_HEIGHT - CDG_BORDER_HEIGHT; y++) { + memset(buf + y * lsize, color, CDG_BORDER_WIDTH); + memset(buf + CDG_FULL_WIDTH - CDG_BORDER_WIDTH + y * lsize, + color, CDG_BORDER_WIDTH); + } + } +} + +static void cdg_load_palette(CDGraphicsContext *cc, uint8_t *data, int low) +{ + uint8_t r, g, b; + uint16_t color; + int i; + int array_offset = low ? 0 : 8; + uint32_t *palette = (uint32_t *) cc->frame->data[1]; + + for (i = 0; i < 8; i++) { + color = (data[2 * i] << 6) + (data[2 * i + 1] & 0x3F); + r = ((color >> 8) & 0x000F) * 17; + g = ((color >> 4) & 0x000F) * 17; + b = ((color ) & 0x000F) * 17; + palette[i + array_offset] = 0xFFU << 24 | r << 16 | g << 8 | b; + } + cc->frame->palette_has_changed = 1; +} + +static int cdg_tile_block(CDGraphicsContext *cc, uint8_t *data, int b) +{ + unsigned ci, ri; + int color; + int x, y; + int ai; + int stride = cc->frame->linesize[0]; + uint8_t *buf = cc->frame->data[0]; + + ri = (data[2] & 0x1F) * CDG_TILE_HEIGHT + cc->vscroll; + ci = (data[3] & 0x3F) * CDG_TILE_WIDTH + cc->hscroll; + + if (ri > (CDG_FULL_HEIGHT - CDG_TILE_HEIGHT)) + return AVERROR(EINVAL); + if (ci > (CDG_FULL_WIDTH - CDG_TILE_WIDTH)) + return AVERROR(EINVAL); + + for (y = 0; y < CDG_TILE_HEIGHT; y++) { + for (x = 0; x < CDG_TILE_WIDTH; x++) { + if (!((data[4 + y] >> (5 - x)) & 0x01)) + color = data[0] & 0x0F; + else + color = data[1] & 0x0F; + + ai = ci + x + (stride * (ri + y)); + if (b) + color ^= buf[ai]; + buf[ai] = color; + } + } + + return 0; +} + +#define UP 2 +#define DOWN 1 +#define LEFT 2 +#define RIGHT 1 + +static void cdg_copy_rect_buf(int out_tl_x, int out_tl_y, uint8_t *out, + int in_tl_x, int in_tl_y, uint8_t *in, + int w, int h, int stride) +{ + int y; + + in += in_tl_x + in_tl_y * stride; + out += out_tl_x + out_tl_y * stride; + for (y = 0; y < h; y++) + memcpy(out + y * stride, in + y * stride, w); +} + +static void cdg_fill_rect_preset(int tl_x, int tl_y, uint8_t *out, + int color, int w, int h, int stride) +{ + int y; + + for (y = tl_y; y < tl_y + h; y++) + memset(out + tl_x + y * stride, color, w); +} + +static void cdg_fill_wrapper(int out_tl_x, int out_tl_y, uint8_t *out, + int in_tl_x, int in_tl_y, uint8_t *in, + int color, int w, int h, int stride, int roll) +{ + if (roll) { + cdg_copy_rect_buf(out_tl_x, out_tl_y, out, in_tl_x, in_tl_y, + in, w, h, stride); + } else { + cdg_fill_rect_preset(out_tl_x, out_tl_y, out, color, w, h, stride); + } +} + +static void cdg_scroll(CDGraphicsContext *cc, uint8_t *data, + AVFrame *new_frame, int roll_over) +{ + int color; + int hscmd, h_off, hinc, vscmd, v_off, vinc; + int y; + int stride = cc->frame->linesize[0]; + uint8_t *in = cc->frame->data[0]; + uint8_t *out = new_frame->data[0]; + + color = data[0] & 0x0F; + hscmd = (data[1] & 0x30) >> 4; + vscmd = (data[2] & 0x30) >> 4; + + h_off = FFMIN(data[1] & 0x07, CDG_BORDER_WIDTH - 1); + v_off = FFMIN(data[2] & 0x0F, CDG_BORDER_HEIGHT - 1); + + /// find the difference and save the offset for cdg_tile_block usage + hinc = h_off - cc->hscroll; + vinc = v_off - cc->vscroll; + cc->hscroll = h_off; + cc->vscroll = v_off; + + if (vscmd == UP) + vinc -= 12; + if (vscmd == DOWN) + vinc += 12; + if (hscmd == LEFT) + hinc -= 6; + if (hscmd == RIGHT) + hinc += 6; + + if (!hinc && !vinc) + return; + + memcpy(new_frame->data[1], cc->frame->data[1], CDG_PALETTE_SIZE * 4); + + for (y = FFMAX(0, vinc); y < FFMIN(CDG_FULL_HEIGHT + vinc, CDG_FULL_HEIGHT); y++) + memcpy(out + FFMAX(0, hinc) + stride * y, + in + FFMAX(0, hinc) - hinc + (y - vinc) * stride, + FFMIN(stride + hinc, stride)); + + if (vinc > 0) + cdg_fill_wrapper(0, 0, out, + 0, CDG_FULL_HEIGHT - vinc, in, color, + stride, vinc, stride, roll_over); + else if (vinc < 0) + cdg_fill_wrapper(0, CDG_FULL_HEIGHT + vinc, out, + 0, 0, in, color, + stride, -1 * vinc, stride, roll_over); + + if (hinc > 0) + cdg_fill_wrapper(0, 0, out, + CDG_FULL_WIDTH - hinc, 0, in, color, + hinc, CDG_FULL_HEIGHT, stride, roll_over); + else if (hinc < 0) + cdg_fill_wrapper(CDG_FULL_WIDTH + hinc, 0, out, + 0, 0, in, color, + -1 * hinc, CDG_FULL_HEIGHT, stride, roll_over); + +} + +static int cdg_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int ret; + uint8_t command, inst; + uint8_t cdg_data[CDG_DATA_SIZE]; + AVFrame *frame = data; + CDGraphicsContext *cc = avctx->priv_data; + + if (buf_size < CDG_MINIMUM_PKT_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buffer too small for decoder\n"); + return AVERROR(EINVAL); + } + if (buf_size > CDG_HEADER_SIZE + CDG_DATA_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buffer too big for decoder\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_reget_buffer(avctx, cc->frame)) < 0) + return ret; + if (!avctx->frame_number) { + memset(cc->frame->data[0], 0, cc->frame->linesize[0] * avctx->height); + memset(cc->frame->data[1], 0, AVPALETTE_SIZE); + } + + command = bytestream_get_byte(&buf); + inst = bytestream_get_byte(&buf); + inst &= CDG_MASK; + buf += 2; /// skipping 2 unneeded bytes + bytestream_get_buffer(&buf, cdg_data, buf_size - CDG_HEADER_SIZE); + + if ((command & CDG_MASK) == CDG_COMMAND) { + switch (inst) { + case CDG_INST_MEMORY_PRESET: + if (!(cdg_data[1] & 0x0F)) + memset(cc->frame->data[0], cdg_data[0] & 0x0F, + cc->frame->linesize[0] * CDG_FULL_HEIGHT); + break; + case CDG_INST_LOAD_PAL_LO: + case CDG_INST_LOAD_PAL_HIGH: + if (buf_size - CDG_HEADER_SIZE < CDG_DATA_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buffer too small for loading palette\n"); + return AVERROR(EINVAL); + } + + cdg_load_palette(cc, cdg_data, inst == CDG_INST_LOAD_PAL_LO); + break; + case CDG_INST_BORDER_PRESET: + cdg_border_preset(cc, cdg_data); + break; + case CDG_INST_TILE_BLOCK_XOR: + case CDG_INST_TILE_BLOCK: + if (buf_size - CDG_HEADER_SIZE < CDG_DATA_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buffer too small for drawing tile\n"); + return AVERROR(EINVAL); + } + + ret = cdg_tile_block(cc, cdg_data, inst == CDG_INST_TILE_BLOCK_XOR); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "tile is out of range\n"); + return ret; + } + break; + case CDG_INST_SCROLL_PRESET: + case CDG_INST_SCROLL_COPY: + if (buf_size - CDG_HEADER_SIZE < CDG_MINIMUM_SCROLL_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buffer too small for scrolling\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + cdg_scroll(cc, cdg_data, frame, inst == CDG_INST_SCROLL_COPY); + av_frame_unref(cc->frame); + ret = av_frame_ref(cc->frame, frame); + if (ret < 0) + return ret; + break; + default: + break; + } + + if (!frame->data[0]) { + ret = av_frame_ref(frame, cc->frame); + if (ret < 0) + return ret; + } + *got_frame = 1; + } else { + *got_frame = 0; + buf_size = 0; + } + + return buf_size; +} + +static av_cold int cdg_decode_end(AVCodecContext *avctx) +{ + CDGraphicsContext *cc = avctx->priv_data; + + av_frame_free(&cc->frame); + + return 0; +} + +AVCodec ff_cdgraphics_decoder = { + .name = "cdgraphics", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CDGRAPHICS, + .priv_data_size = sizeof(CDGraphicsContext), + .init = cdg_decode_init, + .close = cdg_decode_end, + .decode = cdg_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("CD Graphics video"), +}; diff --git a/ffmpeg/libavcodec/cdxl.c b/ffmpeg/libavcodec/cdxl.c new file mode 100644 index 0000000..7e7b7bc --- /dev/null +++ b/ffmpeg/libavcodec/cdxl.c @@ -0,0 +1,303 @@ +/* + * CDXL video decoder + * Copyright (c) 2011-2012 Paul B Mahol + * + * 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 + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" + +#define BIT_PLANAR 0x00 +#define CHUNKY 0x20 +#define BYTE_PLANAR 0x40 +#define BIT_LINE 0x80 +#define BYTE_LINE 0xC0 + +typedef struct { + AVCodecContext *avctx; + int bpp; + int format; + int padded_bits; + const uint8_t *palette; + int palette_size; + const uint8_t *video; + int video_size; + uint8_t *new_video; + int new_video_size; +} CDXLVideoContext; + +static av_cold int cdxl_decode_init(AVCodecContext *avctx) +{ + CDXLVideoContext *c = avctx->priv_data; + + c->new_video_size = 0; + c->avctx = avctx; + + return 0; +} + +static void import_palette(CDXLVideoContext *c, uint32_t *new_palette) +{ + int i; + + for (i = 0; i < c->palette_size / 2; i++) { + unsigned rgb = AV_RB16(&c->palette[i * 2]); + unsigned r = ((rgb >> 8) & 0xF) * 0x11; + unsigned g = ((rgb >> 4) & 0xF) * 0x11; + unsigned b = (rgb & 0xF) * 0x11; + AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b); + } +} + +static void bitplanar2chunky(CDXLVideoContext *c, int linesize, uint8_t *out) +{ + GetBitContext gb; + int x, y, plane; + + init_get_bits(&gb, c->video, c->video_size * 8); + for (plane = 0; plane < c->bpp; plane++) { + for (y = 0; y < c->avctx->height; y++) { + for (x = 0; x < c->avctx->width; x++) + out[linesize * y + x] |= get_bits1(&gb) << plane; + skip_bits(&gb, c->padded_bits); + } + } +} + +static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out) +{ + GetBitContext gb; + int x, y, plane; + + init_get_bits(&gb, c->video, c->video_size * 8); + for (y = 0; y < c->avctx->height; y++) { + for (plane = 0; plane < c->bpp; plane++) { + for (x = 0; x < c->avctx->width; x++) + out[linesize * y + x] |= get_bits1(&gb) << plane; + skip_bits(&gb, c->padded_bits); + } + } +} + +static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out) +{ + memset(out, 0, linesize * c->avctx->height); + + switch (c->format) { + case BIT_PLANAR: + bitplanar2chunky(c, linesize, out); + break; + case BIT_LINE: + bitline2chunky(c, linesize, out); + break; + } +} + +static void cdxl_decode_rgb(CDXLVideoContext *c, AVFrame *frame) +{ + uint32_t *new_palette = (uint32_t *)frame->data[1]; + + memset(frame->data[1], 0, AVPALETTE_SIZE); + import_palette(c, new_palette); + import_format(c, frame->linesize[0], frame->data[0]); +} + +static void cdxl_decode_ham6(CDXLVideoContext *c, AVFrame *frame) +{ + AVCodecContext *avctx = c->avctx; + uint32_t new_palette[16], r, g, b; + uint8_t *ptr, *out, index, op; + int x, y; + + ptr = c->new_video; + out = frame->data[0]; + + import_palette(c, new_palette); + import_format(c, avctx->width, c->new_video); + + for (y = 0; y < avctx->height; y++) { + r = new_palette[0] & 0xFF0000; + g = new_palette[0] & 0xFF00; + b = new_palette[0] & 0xFF; + for (x = 0; x < avctx->width; x++) { + index = *ptr++; + op = index >> 4; + index &= 15; + switch (op) { + case 0: + r = new_palette[index] & 0xFF0000; + g = new_palette[index] & 0xFF00; + b = new_palette[index] & 0xFF; + break; + case 1: + b = index * 0x11; + break; + case 2: + r = index * 0x11 << 16; + break; + case 3: + g = index * 0x11 << 8; + break; + } + AV_WL24(out + x * 3, r | g | b); + } + out += frame->linesize[0]; + } +} + +static void cdxl_decode_ham8(CDXLVideoContext *c, AVFrame *frame) +{ + AVCodecContext *avctx = c->avctx; + uint32_t new_palette[64], r, g, b; + uint8_t *ptr, *out, index, op; + int x, y; + + ptr = c->new_video; + out = frame->data[0]; + + import_palette(c, new_palette); + import_format(c, avctx->width, c->new_video); + + for (y = 0; y < avctx->height; y++) { + r = new_palette[0] & 0xFF0000; + g = new_palette[0] & 0xFF00; + b = new_palette[0] & 0xFF; + for (x = 0; x < avctx->width; x++) { + index = *ptr++; + op = index >> 6; + index &= 63; + switch (op) { + case 0: + r = new_palette[index] & 0xFF0000; + g = new_palette[index] & 0xFF00; + b = new_palette[index] & 0xFF; + break; + case 1: + b = (index << 2) | (b & 3); + break; + case 2: + r = (index << 18) | (r & (3 << 16)); + break; + case 3: + g = (index << 10) | (g & (3 << 8)); + break; + } + AV_WL24(out + x * 3, r | g | b); + } + out += frame->linesize[0]; + } +} + +static int cdxl_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) +{ + CDXLVideoContext *c = avctx->priv_data; + AVFrame * const p = data; + int ret, w, h, encoding, aligned_width, buf_size = pkt->size; + const uint8_t *buf = pkt->data; + + if (buf_size < 32) + return AVERROR_INVALIDDATA; + encoding = buf[1] & 7; + c->format = buf[1] & 0xE0; + w = AV_RB16(&buf[14]); + h = AV_RB16(&buf[16]); + c->bpp = buf[19]; + c->palette_size = AV_RB16(&buf[20]); + c->palette = buf + 32; + c->video = c->palette + c->palette_size; + c->video_size = buf_size - c->palette_size - 32; + + if (c->palette_size > 512) + return AVERROR_INVALIDDATA; + if (buf_size < c->palette_size + 32) + return AVERROR_INVALIDDATA; + if (c->bpp < 1) + return AVERROR_INVALIDDATA; + if (c->format != BIT_PLANAR && c->format != BIT_LINE) { + avpriv_request_sample(avctx, "Pixel format 0x%0x", c->format); + return AVERROR_PATCHWELCOME; + } + + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) + return ret; + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + + aligned_width = FFALIGN(c->avctx->width, 16); + c->padded_bits = aligned_width - c->avctx->width; + if (c->video_size < aligned_width * avctx->height * c->bpp / 8) + return AVERROR_INVALIDDATA; + if (!encoding && c->palette_size && c->bpp <= 8) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) { + if (c->palette_size != (1 << (c->bpp - 1))) + return AVERROR_INVALIDDATA; + avctx->pix_fmt = AV_PIX_FMT_BGR24; + } else { + avpriv_request_sample(avctx, "Encoding %d and bpp %d", + encoding, c->bpp); + return AVERROR_PATCHWELCOME; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + + if (encoding) { + av_fast_padded_malloc(&c->new_video, &c->new_video_size, + h * w + FF_INPUT_BUFFER_PADDING_SIZE); + if (!c->new_video) + return AVERROR(ENOMEM); + if (c->bpp == 8) + cdxl_decode_ham8(c, p); + else + cdxl_decode_ham6(c, p); + } else { + cdxl_decode_rgb(c, p); + } + *got_frame = 1; + + return buf_size; +} + +static av_cold int cdxl_decode_end(AVCodecContext *avctx) +{ + CDXLVideoContext *c = avctx->priv_data; + + av_free(c->new_video); + + return 0; +} + +AVCodec ff_cdxl_decoder = { + .name = "cdxl", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CDXL, + .priv_data_size = sizeof(CDXLVideoContext), + .init = cdxl_decode_init, + .close = cdxl_decode_end, + .decode = cdxl_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), +}; diff --git a/ffmpeg/libavcodec/celp_filters.c b/ffmpeg/libavcodec/celp_filters.c new file mode 100644 index 0000000..a81fd88 --- /dev/null +++ b/ffmpeg/libavcodec/celp_filters.c @@ -0,0 +1,219 @@ +/* + * various filters for ACELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 "avcodec.h" +#include "celp_filters.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" + +void ff_celp_convolve_circ(int16_t* fc_out, const int16_t* fc_in, + const int16_t* filter, int len) +{ + int i, k; + + memset(fc_out, 0, len * sizeof(int16_t)); + + /* Since there are few pulses over an entire subframe (i.e. almost + all fc_in[i] are zero) it is faster to loop over fc_in first. */ + for (i = 0; i < len; i++) { + if (fc_in[i]) { + for (k = 0; k < i; k++) + fc_out[k] += (fc_in[i] * filter[len + k - i]) >> 15; + + for (k = i; k < len; k++) + fc_out[k] += (fc_in[i] * filter[ k - i]) >> 15; + } + } +} + +void ff_celp_circ_addf(float *out, const float *in, + const float *lagged, int lag, float fac, int n) +{ + int k; + for (k = 0; k < lag; k++) + out[k] = in[k] + fac * lagged[n + k - lag]; + for (; k < n; k++) + out[k] = in[k] + fac * lagged[ k - lag]; +} + +int ff_celp_lp_synthesis_filter(int16_t *out, const int16_t *filter_coeffs, + const int16_t *in, int buffer_length, + int filter_length, int stop_on_overflow, + int shift, int rounder) +{ + int i,n; + + for (n = 0; n < buffer_length; n++) { + int sum = -rounder, sum1; + for (i = 1; i <= filter_length; i++) + sum += filter_coeffs[i-1] * out[n-i]; + + sum1 = ((-sum >> 12) + in[n]) >> shift; + sum = av_clip_int16(sum1); + + if (stop_on_overflow && sum != sum1) + return 1; + + out[n] = sum; + } + + return 0; +} + +void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs, + const float* in, int buffer_length, + int filter_length) +{ + int i,n; + +#if 0 // Unoptimized code path for improved readability + for (n = 0; n < buffer_length; n++) { + out[n] = in[n]; + for (i = 1; i <= filter_length; i++) + out[n] -= filter_coeffs[i-1] * out[n-i]; + } +#else + float out0, out1, out2, out3; + float old_out0, old_out1, old_out2, old_out3; + float a,b,c; + + a = filter_coeffs[0]; + b = filter_coeffs[1]; + c = filter_coeffs[2]; + b -= filter_coeffs[0] * filter_coeffs[0]; + c -= filter_coeffs[1] * filter_coeffs[0]; + c -= filter_coeffs[0] * b; + + av_assert2((filter_length&1)==0 && filter_length>=4); + + old_out0 = out[-4]; + old_out1 = out[-3]; + old_out2 = out[-2]; + old_out3 = out[-1]; + for (n = 0; n <= buffer_length - 4; n+=4) { + float tmp0,tmp1,tmp2; + float val; + + out0 = in[0]; + out1 = in[1]; + out2 = in[2]; + out3 = in[3]; + + out0 -= filter_coeffs[2] * old_out1; + out1 -= filter_coeffs[2] * old_out2; + out2 -= filter_coeffs[2] * old_out3; + + out0 -= filter_coeffs[1] * old_out2; + out1 -= filter_coeffs[1] * old_out3; + + out0 -= filter_coeffs[0] * old_out3; + + val = filter_coeffs[3]; + + out0 -= val * old_out0; + out1 -= val * old_out1; + out2 -= val * old_out2; + out3 -= val * old_out3; + + for (i = 5; i < filter_length; i += 2) { + old_out3 = out[-i]; + val = filter_coeffs[i-1]; + + out0 -= val * old_out3; + out1 -= val * old_out0; + out2 -= val * old_out1; + out3 -= val * old_out2; + + old_out2 = out[-i-1]; + + val = filter_coeffs[i]; + + out0 -= val * old_out2; + out1 -= val * old_out3; + out2 -= val * old_out0; + out3 -= val * old_out1; + + FFSWAP(float, old_out0, old_out2); + old_out1 = old_out3; + } + + tmp0 = out0; + tmp1 = out1; + tmp2 = out2; + + out3 -= a * tmp2; + out2 -= a * tmp1; + out1 -= a * tmp0; + + out3 -= b * tmp1; + out2 -= b * tmp0; + + out3 -= c * tmp0; + + + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + + old_out0 = out0; + old_out1 = out1; + old_out2 = out2; + old_out3 = out3; + + out += 4; + in += 4; + } + + out -= n; + in -= n; + for (; n < buffer_length; n++) { + out[n] = in[n]; + for (i = 1; i <= filter_length; i++) + out[n] -= filter_coeffs[i-1] * out[n-i]; + } +#endif +} + +void ff_celp_lp_zero_synthesis_filterf(float *out, const float *filter_coeffs, + const float *in, int buffer_length, + int filter_length) +{ + int i,n; + + for (n = 0; n < buffer_length; n++) { + out[n] = in[n]; + for (i = 1; i <= filter_length; i++) + out[n] += filter_coeffs[i-1] * in[n-i]; + } +} + +void ff_celp_filter_init(CELPFContext *c) +{ + c->celp_lp_synthesis_filterf = ff_celp_lp_synthesis_filterf; + c->celp_lp_zero_synthesis_filterf = ff_celp_lp_zero_synthesis_filterf; + + if(HAVE_MIPSFPU) + ff_celp_filter_init_mips(c); +} diff --git a/ffmpeg/libavcodec/celp_filters.h b/ffmpeg/libavcodec/celp_filters.h new file mode 100644 index 0000000..f644ec3 --- /dev/null +++ b/ffmpeg/libavcodec/celp_filters.h @@ -0,0 +1,169 @@ +/* + * various filters for CELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_CELP_FILTERS_H +#define AVCODEC_CELP_FILTERS_H + +#include + +typedef struct CELPFContext { + /** + * LP synthesis filter. + * @param[out] out pointer to output buffer + * - the array out[-filter_length, -1] must + * contain the previous result of this filter + * @param filter_coeffs filter coefficients. + * @param in input signal + * @param buffer_length amount of data to process + * @param filter_length filter length (10 for 10th order LP filter). Must be + * greater than 4 and even. + * + * @note Output buffer must contain filter_length samples of past + * speech data before pointer. + * + * Routine applies 1/A(z) filter to given speech data. + */ + void (*celp_lp_synthesis_filterf)(float *out, const float *filter_coeffs, + const float *in, int buffer_length, + int filter_length); + + /** + * LP zero synthesis filter. + * @param[out] out pointer to output buffer + * @param filter_coeffs filter coefficients. + * @param in input signal + * - the array in[-filter_length, -1] must + * contain the previous input of this filter + * @param buffer_length amount of data to process (should be a multiple of eight) + * @param filter_length filter length (10 for 10th order LP filter; + * should be a multiple of two) + * + * @note Output buffer must contain filter_length samples of past + * speech data before pointer. + * + * Routine applies A(z) filter to given speech data. + */ + void (*celp_lp_zero_synthesis_filterf)(float *out, const float *filter_coeffs, + const float *in, int buffer_length, + int filter_length); + +}CELPFContext; + +/** + * Initialize CELPFContext. + */ +void ff_celp_filter_init(CELPFContext *c); +void ff_celp_filter_init_mips(CELPFContext *c); + +/** + * Circularly convolve fixed vector with a phase dispersion impulse + * response filter (D.6.2 of G.729 and 6.1.5 of AMR). + * @param fc_out vector with filter applied + * @param fc_in source vector + * @param filter phase filter coefficients + * + * fc_out[n] = sum(i,0,len-1){ fc_in[i] * filter[(len + n - i)%len] } + * + * @note fc_in and fc_out should not overlap! + */ +void ff_celp_convolve_circ(int16_t *fc_out, const int16_t *fc_in, + const int16_t *filter, int len); + +/** + * Add an array to a rotated array. + * + * out[k] = in[k] + fac * lagged[k-lag] with wrap-around + * + * @param out result vector + * @param in samples to be added unfiltered + * @param lagged samples to be rotated, multiplied and added + * @param lag lagged vector delay in the range [0, n] + * @param fac scalefactor for lagged samples + * @param n number of samples + */ +void ff_celp_circ_addf(float *out, const float *in, + const float *lagged, int lag, float fac, int n); + +/** + * LP synthesis filter. + * @param[out] out pointer to output buffer + * @param filter_coeffs filter coefficients (-0x8000 <= (3.12) < 0x8000) + * @param in input signal + * @param buffer_length amount of data to process + * @param filter_length filter length (10 for 10th order LP filter) + * @param stop_on_overflow 1 - return immediately if overflow occurs + * 0 - ignore overflows + * @param shift the result is shifted right by this value + * @param rounder the amount to add for rounding (usually 0x800 or 0xfff) + * + * @return 1 if overflow occurred, 0 - otherwise + * + * @note Output buffer must contain filter_length samples of past + * speech data before pointer. + * + * Routine applies 1/A(z) filter to given speech data. + */ +int ff_celp_lp_synthesis_filter(int16_t *out, const int16_t *filter_coeffs, + const int16_t *in, int buffer_length, + int filter_length, int stop_on_overflow, + int shift, int rounder); + +/** + * LP synthesis filter. + * @param[out] out pointer to output buffer + * - the array out[-filter_length, -1] must + * contain the previous result of this filter + * @param filter_coeffs filter coefficients. + * @param in input signal + * @param buffer_length amount of data to process + * @param filter_length filter length (10 for 10th order LP filter). Must be + * greater than 4 and even. + * + * @note Output buffer must contain filter_length samples of past + * speech data before pointer. + * + * Routine applies 1/A(z) filter to given speech data. + */ +void ff_celp_lp_synthesis_filterf(float *out, const float *filter_coeffs, + const float *in, int buffer_length, + int filter_length); + +/** + * LP zero synthesis filter. + * @param[out] out pointer to output buffer + * @param filter_coeffs filter coefficients. + * @param in input signal + * - the array in[-filter_length, -1] must + * contain the previous input of this filter + * @param buffer_length amount of data to process + * @param filter_length filter length (10 for 10th order LP filter) + * + * @note Output buffer must contain filter_length samples of past + * speech data before pointer. + * + * Routine applies A(z) filter to given speech data. + */ +void ff_celp_lp_zero_synthesis_filterf(float *out, const float *filter_coeffs, + const float *in, int buffer_length, + int filter_length); + +#endif /* AVCODEC_CELP_FILTERS_H */ diff --git a/ffmpeg/libavcodec/celp_math.c b/ffmpeg/libavcodec/celp_math.c new file mode 100644 index 0000000..a96b1ae --- /dev/null +++ b/ffmpeg/libavcodec/celp_math.c @@ -0,0 +1,126 @@ +/* + * Various fixed-point math operations + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "mathops.h" +#include "celp_math.h" +#include "libavutil/common.h" + +static const uint16_t exp2a[]= +{ + 0, 1435, 2901, 4400, 5931, 7496, 9096, 10730, + 12400, 14106, 15850, 17632, 19454, 21315, 23216, 25160, + 27146, 29175, 31249, 33368, 35534, 37747, 40009, 42320, + 44682, 47095, 49562, 52082, 54657, 57289, 59979, 62727, +}; + +static const uint16_t exp2b[]= +{ + 3, 712, 1424, 2134, 2845, 3557, 4270, 4982, + 5696, 6409, 7124, 7839, 8554, 9270, 9986, 10704, + 11421, 12138, 12857, 13576, 14295, 15014, 15734, 16455, + 17176, 17898, 18620, 19343, 20066, 20790, 21514, 22238, +}; + +int ff_exp2(uint16_t power) +{ + unsigned int result= exp2a[power>>10] + 0x10000; + + av_assert2(power <= 0x7fff); + + result= (result<<3) + ((result*exp2b[(power>>5)&31])>>17); + return result + ((result*(power&31)*89)>>22); +} + +/** + * Table used to compute log2(x) + * + * tab_log2[i] = (1<<15) * log2(1 + i/32), i=0..32 + */ +static const uint16_t tab_log2[33] = +{ +#ifdef G729_BITEXACT + 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, + 10549, 11716, 12855, 13967, 15054, 16117, 17156, 18172, + 19167, 20142, 21097, 22033, 22951, 23852, 24735, 25603, + 26455, 27291, 28113, 28922, 29716, 30497, 31266, 32023, 32767, +#else + 4, 1459, 2870, 4240, 5572, 6867, 8127, 9355, + 10552, 11719, 12858, 13971, 15057, 16120, 17158, 18175, + 19170, 20145, 21100, 22036, 22954, 23854, 24738, 25605, + 26457, 27294, 28116, 28924, 29719, 30500, 31269, 32025, 32769, +#endif +}; + +int ff_log2_q15(uint32_t value) +{ + uint8_t power_int; + uint8_t frac_x0; + uint16_t frac_dx; + + // Stripping zeros from beginning + power_int = av_log2(value); + value <<= (31 - power_int); + + // b31 is always non-zero now + frac_x0 = (value & 0x7c000000) >> 26; // b26-b31 and [32..63] -> [0..31] + frac_dx = (value & 0x03fff800) >> 11; + + value = tab_log2[frac_x0]; + value += (frac_dx * (tab_log2[frac_x0+1] - tab_log2[frac_x0])) >> 15; + + return (power_int << 15) + value; +} + +int64_t ff_dot_product(const int16_t *a, const int16_t *b, int length) +{ + int i; + int64_t sum = 0; + + for (i = 0; i < length; i++) + sum += MUL16(a[i], b[i]); + + return sum; +} + +float ff_dot_productf(const float* a, const float* b, int length) +{ + float sum = 0; + int i; + + for(i=0; idot_productf = ff_dot_productf; + + if(HAVE_MIPSFPU) + ff_celp_math_init_mips(c); +} diff --git a/ffmpeg/libavcodec/celp_math.h b/ffmpeg/libavcodec/celp_math.h new file mode 100644 index 0000000..18d3ad9 --- /dev/null +++ b/ffmpeg/libavcodec/celp_math.h @@ -0,0 +1,97 @@ +/* + * Various fixed-point math operations + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_CELP_MATH_H +#define AVCODEC_CELP_MATH_H + +#include + +typedef struct CELPMContext { + /** + * Return the dot product. + * @param a input data array + * @param b input data array + * @param length number of elements + * + * @return dot product = sum of elementwise products + */ + float (*dot_productf)(const float* a, const float* b, int length); + +}CELPMContext; + +/** + * Initialize CELPMContext. + */ +void ff_celp_math_init(CELPMContext *c); +void ff_celp_math_init_mips(CELPMContext *c); + +/** + * fixed-point implementation of exp2(x) in [0; 1] domain. + * @param power argument to exp2, 0 <= power <= 0x7fff + * + * @return value of (1<<20) * exp2(power / (1<<15)) + * 0x8000c <= result <= 0xfffea + */ +int ff_exp2(uint16_t power); + +/** + * Calculate log2(x). + * @param value function argument, 0 < value <= 7fff ffff + * + * @return value of (1<<15) * log2(value) + */ +int ff_log2_q15(uint32_t value); + +/** + * Shift value left or right depending on sign of offset parameter. + * @param value value to shift + * @param offset shift offset + * + * @return value << offset, if offset>=0; value >> -offset - otherwise + */ +static inline int bidir_sal(int value, int offset) +{ + if(offset < 0) return value >> -offset; + else return value << offset; +} + +/** + * returns the dot product of 2 int16_t vectors. + * @param a input data array + * @param b input data array + * @param length number of elements + * + * @return dot product = sum of elementwise products + */ +int64_t ff_dot_product(const int16_t *a, const int16_t *b, int length); + +/** + * Return the dot product. + * @param a input data array + * @param b input data array + * @param length number of elements + * + * @return dot product = sum of elementwise products + */ +float ff_dot_productf(const float* a, const float* b, int length); + +#endif /* AVCODEC_CELP_MATH_H */ diff --git a/ffmpeg/libavcodec/cga_data.c b/ffmpeg/libavcodec/cga_data.c new file mode 100644 index 0000000..023a86b --- /dev/null +++ b/ffmpeg/libavcodec/cga_data.c @@ -0,0 +1,55 @@ +/* + * CGA/EGA/VGA ROM data + * + * 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 + */ + +/** + * @file + * CGA/EGA/VGA ROM data + * @note fonts are in libavutil/xga_font_data.[ch] + */ + +#include +#include "cga_data.h" + +const uint32_t ff_cga_palette[16] = { + 0xFF000000, 0xFF0000AA, 0xFF00AA00, 0xFF00AAAA, 0xFFAA0000, 0xFFAA00AA, 0xFFAA5500, 0xFFAAAAAA, + 0xFF555555, 0xFF5555FF, 0xFF55FF55, 0xFF55FFFF, 0xFFFF5555, 0xFFFF55FF, 0xFFFFFF55, 0xFFFFFFFF, +}; + +const uint32_t ff_ega_palette[64] = { + 0xFF000000, 0xFF0000AA, 0xFF00AA00, 0xFF00AAAA, 0xFFAA0000, 0xFFAA00AA, 0xFFAAAA00, 0xFFAAAAAA, + 0xFF000055, 0xFF0000FF, 0xFF00AA55, 0xFF00AAFF, 0xFFAA0055, 0xFFAA00FF, 0xFFAAAA55, 0xFFAAAAFF, + 0xFF005500, 0xFF0055AA, 0xFF00FF00, 0xFF00FFAA, 0xFFAA5500, 0xFFAA55AA, 0xFFAAFF00, 0xFFAAFFAA, + 0xFF005555, 0xFF0055FF, 0xFF00FF55, 0xFF00FFFF, 0xFFAA5555, 0xFFAA55FF, 0xFFAAFF55, 0xFFAAFFFF, + 0xFF550000, 0xFF5500AA, 0xFF55AA00, 0xFF55AAAA, 0xFFFF0000, 0xFFFF00AA, 0xFFFFAA00, 0xFFFFAAAA, + 0xFF550055, 0xFF5500FF, 0xFF55AA55, 0xFF55AAFF, 0xFFFF0055, 0xFFFF00FF, 0xFFFFAA55, 0xFFFFAAFF, + 0xFF555500, 0xFF5555AA, 0xFF55FF00, 0xFF55FFAA, 0xFFFF5500, 0xFFFF55AA, 0xFFFFFF00, 0xFFFFFFAA, + 0xFF555555, 0xFF5555FF, 0xFF55FF55, 0xFF55FFFF, 0xFFFF5555, 0xFFFF55FF, 0xFFFFFF55, 0xFFFFFFFF +}; + +void ff_draw_pc_font(uint8_t *dst, int linesize, const uint8_t *font, int font_height, int ch, int fg, int bg) +{ + int char_y, mask; + for (char_y = 0; char_y < font_height; char_y++) { + for (mask = 0x80; mask; mask >>= 1) { + *dst++ = font[ch * font_height + char_y] & mask ? fg : bg; + } + dst += linesize - 8; + } +} diff --git a/ffmpeg/libavcodec/cga_data.h b/ffmpeg/libavcodec/cga_data.h new file mode 100644 index 0000000..3f5281a --- /dev/null +++ b/ffmpeg/libavcodec/cga_data.h @@ -0,0 +1,47 @@ +/* + * CGA/EGA/VGA ROM data + * + * 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 + */ + +/** + * @file + * CGA/EGA/VGA ROM data + * @note fonts are in libavutil/xga_font_data.[ch] + */ + +#ifndef AVCODEC_CGA_DATA_H +#define AVCODEC_CGA_DATA_H + +#include + +extern const uint32_t ff_cga_palette[16]; +extern const uint32_t ff_ega_palette[64]; + +/** + * Draw CGA/EGA/VGA font to 8-bit pixel buffer + * + * @param dst Destination pixel buffer + * @param linesize Linesize (pixels) + * @param font Font table. We assume font width is always 8 pixels wide. + * @param font_height Font height (pixels) + * @param fg,bg Foreground and background palette index + * @param ch Character to draw + */ +void ff_draw_pc_font(uint8_t *dst, int linesize, const uint8_t *font, int font_height, int ch, int fg, int bg); + +#endif /* AVCODEC_CGA_DATA_H */ diff --git a/ffmpeg/libavcodec/chomp_bsf.c b/ffmpeg/libavcodec/chomp_bsf.c new file mode 100644 index 0000000..eaefaaa --- /dev/null +++ b/ffmpeg/libavcodec/chomp_bsf.c @@ -0,0 +1,47 @@ +/* + * Chomp bitstream filter + * Copyright (c) 2010 Alex Converse + * + * 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 "avcodec.h" +#include "internal.h" + +static int chomp_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int keyframe) +{ + while (buf_size > 0 && !buf[buf_size-1]) + buf_size--; + + *poutbuf = (uint8_t*) buf; + *poutbuf_size = buf_size; + + return 0; +} + +/** + * This filter removes a string of NULL bytes from the end of a packet. + */ +AVBitStreamFilter ff_chomp_bsf = { + "chomp", + 0, + chomp_filter, +}; diff --git a/ffmpeg/libavcodec/cinepak.c b/ffmpeg/libavcodec/cinepak.c new file mode 100644 index 0000000..f5bc113 --- /dev/null +++ b/ffmpeg/libavcodec/cinepak.c @@ -0,0 +1,488 @@ +/* + * Cinepak Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Cinepak video decoder + * @author Ewald Snel + * + * @see For more information on the Cinepak algorithm, visit: + * http://www.csse.monash.edu.au/~timf/ + * @see For more information on the quirky data inside Sega FILM/CPK files, visit: + * http://wiki.multimedia.cx/index.php?title=Sega_FILM + * + * Cinepak colorspace support (c) 2013 Rl, Aetey Global Technologies AB + * @author Cinepak colorspace, Rl, Aetey Global Technologies AB + */ + +#include +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + + +typedef uint8_t cvid_codebook[12]; + +#define MAX_STRIPS 32 + +typedef struct { + uint16_t id; + uint16_t x1, y1; + uint16_t x2, y2; + cvid_codebook v4_codebook[256]; + cvid_codebook v1_codebook[256]; +} cvid_strip; + +typedef struct CinepakContext { + + AVCodecContext *avctx; + AVFrame *frame; + + const unsigned char *data; + int size; + + int width, height; + + int palette_video; + cvid_strip strips[MAX_STRIPS]; + + int sega_film_skip_bytes; + + uint32_t pal[256]; +} CinepakContext; + +static void cinepak_decode_codebook (cvid_codebook *codebook, + int chunk_id, int size, const uint8_t *data) +{ + const uint8_t *eod = (data + size); + uint32_t flag, mask; + int i, n; + uint8_t *p; + + /* check if this chunk contains 4- or 6-element vectors */ + n = (chunk_id & 0x04) ? 4 : 6; + flag = 0; + mask = 0; + + p = codebook[0]; + for (i=0; i < 256; i++) { + if ((chunk_id & 0x01) && !(mask >>= 1)) { + if ((data + 4) > eod) + break; + + flag = AV_RB32 (data); + data += 4; + mask = 0x80000000; + } + + if (!(chunk_id & 0x01) || (flag & mask)) { + int k, kk; + + if ((data + n) > eod) + break; + + for (k = 0; k < 4; ++k) { + int r = *data++; + for (kk = 0; kk < 3; ++kk) + *p++ = r; + } + if (n == 6) { + int r, g, b, u, v; + u = *(int8_t *)data++; + v = *(int8_t *)data++; + p -= 12; + for(k=0; k<4; ++k) { + r = *p++ + v*2; + g = *p++ - (u/2) - v; + b = *p + u*2; + p -= 2; + *p++ = av_clip_uint8(r); + *p++ = av_clip_uint8(g); + *p++ = av_clip_uint8(b); + } + } + } else { + p += 12; + } + } +} + +static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip, + int chunk_id, int size, const uint8_t *data) +{ + const uint8_t *eod = (data + size); + uint32_t flag, mask; + uint8_t *cb0, *cb1, *cb2, *cb3; + unsigned int x, y; + char *ip0, *ip1, *ip2, *ip3; + + flag = 0; + mask = 0; + + for (y=strip->y1; y < strip->y2; y+=4) { + +/* take care of y dimension not being multiple of 4, such streams exist */ + ip0 = ip1 = ip2 = ip3 = s->frame->data[0] + + (s->palette_video?strip->x1:strip->x1*3) + (y * s->frame->linesize[0]); + if(s->avctx->height - y > 1) { + ip1 = ip0 + s->frame->linesize[0]; + if(s->avctx->height - y > 2) { + ip2 = ip1 + s->frame->linesize[0]; + if(s->avctx->height - y > 3) { + ip3 = ip2 + s->frame->linesize[0]; + } + } + } +/* to get the correct picture for not-multiple-of-4 cases let us fill + * each block from the bottom up, thus possibly overwriting the top line + * more than once but ending with the correct data in place + * (instead of in-loop checking) */ + + for (x=strip->x1; x < strip->x2; x+=4) { + if ((chunk_id & 0x01) && !(mask >>= 1)) { + if ((data + 4) > eod) + return AVERROR_INVALIDDATA; + + flag = AV_RB32 (data); + data += 4; + mask = 0x80000000; + } + + if (!(chunk_id & 0x01) || (flag & mask)) { + if (!(chunk_id & 0x02) && !(mask >>= 1)) { + if ((data + 4) > eod) + return AVERROR_INVALIDDATA; + + flag = AV_RB32 (data); + data += 4; + mask = 0x80000000; + } + + if ((chunk_id & 0x02) || (~flag & mask)) { + uint8_t *p; + if (data >= eod) + return AVERROR_INVALIDDATA; + + p = strip->v1_codebook[*data++]; + if (s->palette_video) { + ip3[0] = ip3[1] = ip2[0] = ip2[1] = p[6]; + ip3[2] = ip3[3] = ip2[2] = ip2[3] = p[9]; + ip1[0] = ip1[1] = ip0[0] = ip0[1] = p[0]; + ip1[2] = ip1[3] = ip0[2] = ip0[3] = p[3]; + } else { + p += 6; + memcpy(ip3 + 0, p, 3); memcpy(ip3 + 3, p, 3); + memcpy(ip2 + 0, p, 3); memcpy(ip2 + 3, p, 3); + p += 3; /* ... + 9 */ + memcpy(ip3 + 6, p, 3); memcpy(ip3 + 9, p, 3); + memcpy(ip2 + 6, p, 3); memcpy(ip2 + 9, p, 3); + p -= 9; /* ... + 0 */ + memcpy(ip1 + 0, p, 3); memcpy(ip1 + 3, p, 3); + memcpy(ip0 + 0, p, 3); memcpy(ip0 + 3, p, 3); + p += 3; /* ... + 3 */ + memcpy(ip1 + 6, p, 3); memcpy(ip1 + 9, p, 3); + memcpy(ip0 + 6, p, 3); memcpy(ip0 + 9, p, 3); + } + + } else if (flag & mask) { + if ((data + 4) > eod) + return AVERROR_INVALIDDATA; + + cb0 = strip->v4_codebook[*data++]; + cb1 = strip->v4_codebook[*data++]; + cb2 = strip->v4_codebook[*data++]; + cb3 = strip->v4_codebook[*data++]; + if (s->palette_video) { + uint8_t *p; + p = ip3; + *p++ = cb2[6]; + *p++ = cb2[9]; + *p++ = cb3[6]; + *p = cb3[9]; + p = ip2; + *p++ = cb2[0]; + *p++ = cb2[3]; + *p++ = cb3[0]; + *p = cb3[3]; + p = ip1; + *p++ = cb0[6]; + *p++ = cb0[9]; + *p++ = cb1[6]; + *p = cb1[9]; + p = ip0; + *p++ = cb0[0]; + *p++ = cb0[3]; + *p++ = cb1[0]; + *p = cb1[3]; + } else { + memcpy(ip3 + 0, cb2 + 6, 6); + memcpy(ip3 + 6, cb3 + 6, 6); + memcpy(ip2 + 0, cb2 + 0, 6); + memcpy(ip2 + 6, cb3 + 0, 6); + memcpy(ip1 + 0, cb0 + 6, 6); + memcpy(ip1 + 6, cb1 + 6, 6); + memcpy(ip0 + 0, cb0 + 0, 6); + memcpy(ip0 + 6, cb1 + 0, 6); + } + + } + } + + if (s->palette_video) { + ip0 += 4; ip1 += 4; + ip2 += 4; ip3 += 4; + } else { + ip0 += 12; ip1 += 12; + ip2 += 12; ip3 += 12; + } + } + } + + return 0; +} + +static int cinepak_decode_strip (CinepakContext *s, + cvid_strip *strip, const uint8_t *data, int size) +{ + const uint8_t *eod = (data + size); + int chunk_id, chunk_size; + + /* coordinate sanity checks */ + if (strip->x2 > s->width || + strip->y2 > s->height || + strip->x1 >= strip->x2 || strip->y1 >= strip->y2) + return AVERROR_INVALIDDATA; + + while ((data + 4) <= eod) { + chunk_id = data[0]; + chunk_size = AV_RB24 (&data[1]) - 4; + if(chunk_size < 0) + return AVERROR_INVALIDDATA; + + data += 4; + chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size; + + switch (chunk_id) { + + case 0x20: + case 0x21: + case 0x24: + case 0x25: + cinepak_decode_codebook (strip->v4_codebook, chunk_id, + chunk_size, data); + break; + + case 0x22: + case 0x23: + case 0x26: + case 0x27: + cinepak_decode_codebook (strip->v1_codebook, chunk_id, + chunk_size, data); + break; + + case 0x30: + case 0x31: + case 0x32: + return cinepak_decode_vectors (s, strip, chunk_id, + chunk_size, data); + } + + data += chunk_size; + } + + return AVERROR_INVALIDDATA; +} + +static int cinepak_decode (CinepakContext *s) +{ + const uint8_t *eod = (s->data + s->size); + int i, result, strip_size, frame_flags, num_strips; + int y0 = 0; + int encoded_buf_size; + + if (s->size < 10) + return AVERROR_INVALIDDATA; + + frame_flags = s->data[0]; + num_strips = AV_RB16 (&s->data[8]); + encoded_buf_size = AV_RB24(&s->data[1]); + + /* if this is the first frame, check for deviant Sega FILM data */ + if (s->sega_film_skip_bytes == -1) { + if (!encoded_buf_size) { + avpriv_request_sample(s->avctx, "encoded_buf_size 0"); + return AVERROR_PATCHWELCOME; + } + if (encoded_buf_size != s->size && (s->size % encoded_buf_size) != 0) { + /* If the encoded frame size differs from the frame size as indicated + * by the container file, this data likely comes from a Sega FILM/CPK file. + * If the frame header is followed by the bytes FE 00 00 06 00 00 then + * this is probably one of the two known files that have 6 extra bytes + * after the frame header. Else, assume 2 extra bytes. The container + * size also cannot be a multiple of the encoded size. */ + if (s->size >= 16 && + (s->data[10] == 0xFE) && + (s->data[11] == 0x00) && + (s->data[12] == 0x00) && + (s->data[13] == 0x06) && + (s->data[14] == 0x00) && + (s->data[15] == 0x00)) + s->sega_film_skip_bytes = 6; + else + s->sega_film_skip_bytes = 2; + } else + s->sega_film_skip_bytes = 0; + } + + s->data += 10 + s->sega_film_skip_bytes; + + num_strips = FFMIN(num_strips, MAX_STRIPS); + + s->frame->key_frame = 0; + + for (i=0; i < num_strips; i++) { + if ((s->data + 12) > eod) + return AVERROR_INVALIDDATA; + + s->strips[i].id = s->data[0]; +/* zero y1 means "relative to the previous stripe" */ + if (!(s->strips[i].y1 = AV_RB16 (&s->data[4]))) + s->strips[i].y2 = (s->strips[i].y1 = y0) + AV_RB16 (&s->data[8]); + else + s->strips[i].y2 = AV_RB16 (&s->data[8]); + s->strips[i].x1 = AV_RB16 (&s->data[6]); + s->strips[i].x2 = AV_RB16 (&s->data[10]); + + if (s->strips[i].id == 0x10) + s->frame->key_frame = 1; + + strip_size = AV_RB24 (&s->data[1]) - 12; + if (strip_size < 0) + return AVERROR_INVALIDDATA; + s->data += 12; + strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size; + + if ((i > 0) && !(frame_flags & 0x01)) { + memcpy (s->strips[i].v4_codebook, s->strips[i-1].v4_codebook, + sizeof(s->strips[i].v4_codebook)); + memcpy (s->strips[i].v1_codebook, s->strips[i-1].v1_codebook, + sizeof(s->strips[i].v1_codebook)); + } + + result = cinepak_decode_strip (s, &s->strips[i], s->data, strip_size); + + if (result != 0) + return result; + + s->data += strip_size; + y0 = s->strips[i].y2; + } + return 0; +} + +static av_cold int cinepak_decode_init(AVCodecContext *avctx) +{ + CinepakContext *s = avctx->priv_data; + + s->avctx = avctx; + s->width = (avctx->width + 3) & ~3; + s->height = (avctx->height + 3) & ~3; + + s->sega_film_skip_bytes = -1; /* uninitialized state */ + + // check for paletted data + if (avctx->bits_per_coded_sample != 8) { + s->palette_video = 0; + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else { + s->palette_video = 1; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + return 0; +} + +static int cinepak_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int ret = 0, buf_size = avpkt->size; + CinepakContext *s = avctx->priv_data; + + s->data = buf; + s->size = buf_size; + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + + if (s->palette_video) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + if (pal) { + s->frame->palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + } + + if ((ret = cinepak_decode(s)) < 0) { + av_log(avctx, AV_LOG_ERROR, "cinepak_decode failed\n"); + } + + if (s->palette_video) + memcpy (s->frame->data[1], s->pal, AVPALETTE_SIZE); + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int cinepak_decode_end(AVCodecContext *avctx) +{ + CinepakContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +AVCodec ff_cinepak_decoder = { + .name = "cinepak", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CINEPAK, + .priv_data_size = sizeof(CinepakContext), + .init = cinepak_decode_init, + .close = cinepak_decode_end, + .decode = cinepak_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), +}; diff --git a/ffmpeg/libavcodec/cljr.c b/ffmpeg/libavcodec/cljr.c new file mode 100644 index 0000000..2120864 --- /dev/null +++ b/ffmpeg/libavcodec/cljr.c @@ -0,0 +1,190 @@ +/* + * Cirrus Logic AccuPak (CLJR) codec + * Copyright (c) 2003 Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * Cirrus Logic AccuPak codec. + */ + +#include "avcodec.h" +#include "libavutil/opt.h" +#include "get_bits.h" +#include "internal.h" +#include "put_bits.h" + +#if CONFIG_CLJR_DECODER +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + GetBitContext gb; + AVFrame * const p = data; + int x, y, ret; + + if (avctx->height <= 0 || avctx->width <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid width or height\n"); + return AVERROR_INVALIDDATA; + } + + if (buf_size / avctx->height < avctx->width) { + av_log(avctx, AV_LOG_ERROR, + "Resolution larger than buffer size. Invalid header?\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + init_get_bits(&gb, buf, buf_size * 8); + + for (y = 0; y < avctx->height; y++) { + uint8_t *luma = &p->data[0][y * p->linesize[0]]; + uint8_t *cb = &p->data[1][y * p->linesize[1]]; + uint8_t *cr = &p->data[2][y * p->linesize[2]]; + for (x = 0; x < avctx->width; x += 4) { + luma[3] = (get_bits(&gb, 5)*33) >> 2; + luma[2] = (get_bits(&gb, 5)*33) >> 2; + luma[1] = (get_bits(&gb, 5)*33) >> 2; + luma[0] = (get_bits(&gb, 5)*33) >> 2; + luma += 4; + *(cb++) = get_bits(&gb, 6) << 2; + *(cr++) = get_bits(&gb, 6) << 2; + } + } + + *got_frame = 1; + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV411P; + return 0; +} + +AVCodec ff_cljr_decoder = { + .name = "cljr", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CLJR, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), +}; +#endif + +#if CONFIG_CLJR_ENCODER +typedef struct CLJRContext { + AVClass *avclass; + AVFrame picture; + int dither_type; +} CLJRContext; + +static av_cold int encode_init(AVCodecContext *avctx) +{ + CLJRContext * const a = avctx->priv_data; + + avctx->coded_frame = &a->picture; + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *p, int *got_packet) +{ + CLJRContext *a = avctx->priv_data; + PutBitContext pb; + int x, y, ret; + uint32_t dither= avctx->frame_number; + static const uint32_t ordered_dither[2][2] = + { + { 0x10400000, 0x104F0000 }, + { 0xCB2A0000, 0xCB250000 }, + }; + + if ((ret = ff_alloc_packet2(avctx, pkt, 32*avctx->height*avctx->width/4)) < 0) + return ret; + + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; + + init_put_bits(&pb, pkt->data, pkt->size); + + for (y = 0; y < avctx->height; y++) { + uint8_t *luma = &p->data[0][y * p->linesize[0]]; + uint8_t *cb = &p->data[1][y * p->linesize[1]]; + uint8_t *cr = &p->data[2][y * p->linesize[2]]; + for (x = 0; x < avctx->width; x += 4) { + switch (a->dither_type) { + case 0: dither = 0x492A0000; break; + case 1: dither = dither * 1664525 + 1013904223; break; + case 2: dither = ordered_dither[ y&1 ][ (x>>2)&1 ];break; + } + put_bits(&pb, 5, (249*(luma[3] + (dither>>29) )) >> 11); + put_bits(&pb, 5, (249*(luma[2] + ((dither>>26)&7))) >> 11); + put_bits(&pb, 5, (249*(luma[1] + ((dither>>23)&7))) >> 11); + put_bits(&pb, 5, (249*(luma[0] + ((dither>>20)&7))) >> 11); + luma += 4; + put_bits(&pb, 6, (253*(*(cb++) + ((dither>>18)&3))) >> 10); + put_bits(&pb, 6, (253*(*(cr++) + ((dither>>16)&3))) >> 10); + } + } + + flush_put_bits(&pb); + + pkt->size = put_bits_count(&pb) / 8; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +#define OFFSET(x) offsetof(CLJRContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "dither_type", "Dither type", OFFSET(dither_type), AV_OPT_TYPE_INT, { .i64=1 }, 0, 2, VE}, + { NULL }, +}; + +static const AVClass class = { + .class_name = "cljr encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_cljr_encoder = { + .name = "cljr", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CLJR, + .priv_data_size = sizeof(CLJRContext), + .init = encode_init, + .encode2 = encode_frame, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), + .priv_class = &class, +}; +#endif diff --git a/ffmpeg/libavcodec/cllc.c b/ffmpeg/libavcodec/cllc.c new file mode 100644 index 0000000..6378c79 --- /dev/null +++ b/ffmpeg/libavcodec/cllc.c @@ -0,0 +1,398 @@ +/* + * Canopus Lossless Codec decoder + * + * Copyright (c) 2012 Derek Buitenhuis + * + * 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 "libavutil/intreadwrite.h" +#include "dsputil.h" +#include "get_bits.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct CLLCContext { + DSPContext dsp; + AVCodecContext *avctx; + + uint8_t *swapped_buf; + int swapped_buf_size; +} CLLCContext; + +static int read_code_table(CLLCContext *ctx, GetBitContext *gb, VLC *vlc) +{ + uint8_t symbols[256]; + uint8_t bits[256]; + uint16_t codes[256]; + int num_lens, num_codes, num_codes_sum, prefix; + int i, j, count; + + prefix = 0; + count = 0; + num_codes_sum = 0; + + num_lens = get_bits(gb, 5); + + for (i = 0; i < num_lens; i++) { + num_codes = get_bits(gb, 9); + num_codes_sum += num_codes; + + if (num_codes_sum > 256) { + vlc->table = NULL; + + av_log(ctx->avctx, AV_LOG_ERROR, + "Too many VLCs (%d) to be read.\n", num_codes_sum); + return AVERROR_INVALIDDATA; + } + + for (j = 0; j < num_codes; j++) { + symbols[count] = get_bits(gb, 8); + bits[count] = i + 1; + codes[count] = prefix++; + + count++; + } + + prefix <<= 1; + } + + return ff_init_vlc_sparse(vlc, 7, count, bits, 1, 1, + codes, 2, 2, symbols, 1, 1, 0); +} + +/* + * Unlike the RGB24 read/restore, which reads in a component at a time, + * ARGB read/restore reads in ARGB quads. + */ +static int read_argb_line(CLLCContext *ctx, GetBitContext *gb, int *top_left, + VLC *vlc, uint8_t *outbuf) +{ + uint8_t *dst; + int pred[4]; + int code; + int i; + + OPEN_READER(bits, gb); + + dst = outbuf; + pred[0] = top_left[0]; + pred[1] = top_left[1]; + pred[2] = top_left[2]; + pred[3] = top_left[3]; + + for (i = 0; i < ctx->avctx->width; i++) { + /* Always get the alpha component */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[0].table, 7, 2); + + pred[0] += code; + dst[0] = pred[0]; + + /* Skip the components if they are entirely transparent */ + if (dst[0]) { + /* Red */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[1].table, 7, 2); + + pred[1] += code; + dst[1] = pred[1]; + + /* Green */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[2].table, 7, 2); + + pred[2] += code; + dst[2] = pred[2]; + + /* Blue */ + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc[3].table, 7, 2); + + pred[3] += code; + dst[3] = pred[3]; + } else { + dst[1] = 0; + dst[2] = 0; + dst[3] = 0; + } + + dst += 4; + } + + CLOSE_READER(bits, gb); + + dst -= 4 * ctx->avctx->width; + top_left[0] = dst[0]; + + /* Only stash components if they are not transparent */ + if (top_left[0]) { + top_left[1] = dst[1]; + top_left[2] = dst[2]; + top_left[3] = dst[3]; + } + + return 0; +} + +static int read_rgb24_component_line(CLLCContext *ctx, GetBitContext *gb, + int *top_left, VLC *vlc, uint8_t *outbuf) +{ + uint8_t *dst; + int pred, code; + int i; + + OPEN_READER(bits, gb); + + dst = outbuf; + pred = *top_left; + + /* Simultaneously read and restore the line */ + for (i = 0; i < ctx->avctx->width; i++) { + UPDATE_CACHE(bits, gb); + GET_VLC(code, bits, gb, vlc->table, 7, 2); + + pred += code; + dst[0] = pred; + dst += 3; + } + + CLOSE_READER(bits, gb); + + /* Stash the first pixel */ + *top_left = dst[-3 * ctx->avctx->width]; + + return 0; +} + +static int decode_argb_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic) +{ + AVCodecContext *avctx = ctx->avctx; + uint8_t *dst; + int pred[4]; + int ret; + int i, j; + VLC vlc[4]; + + pred[0] = 0; + pred[1] = 0x80; + pred[2] = 0x80; + pred[3] = 0x80; + + dst = pic->data[0]; + + skip_bits(gb, 16); + + /* Read in code table for each plane */ + for (i = 0; i < 4; i++) { + ret = read_code_table(ctx, gb, &vlc[i]); + if (ret < 0) { + for (j = 0; j <= i; j++) + ff_free_vlc(&vlc[j]); + + av_log(ctx->avctx, AV_LOG_ERROR, + "Could not read code table %d.\n", i); + return ret; + } + } + + /* Read in and restore every line */ + for (i = 0; i < avctx->height; i++) { + read_argb_line(ctx, gb, pred, vlc, dst); + + dst += pic->linesize[0]; + } + + for (i = 0; i < 4; i++) + ff_free_vlc(&vlc[i]); + + return 0; +} + +static int decode_rgb24_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic) +{ + AVCodecContext *avctx = ctx->avctx; + uint8_t *dst; + int pred[3]; + int ret; + int i, j; + VLC vlc[3]; + + pred[0] = 0x80; + pred[1] = 0x80; + pred[2] = 0x80; + + dst = pic->data[0]; + + skip_bits(gb, 16); + + /* Read in code table for each plane */ + for (i = 0; i < 3; i++) { + ret = read_code_table(ctx, gb, &vlc[i]); + if (ret < 0) { + for (j = 0; j <= i; j++) + ff_free_vlc(&vlc[j]); + + av_log(ctx->avctx, AV_LOG_ERROR, + "Could not read code table %d.\n", i); + return ret; + } + } + + /* Read in and restore every line */ + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < 3; j++) + read_rgb24_component_line(ctx, gb, &pred[j], &vlc[j], &dst[j]); + + dst += pic->linesize[0]; + } + + for (i = 0; i < 3; i++) + ff_free_vlc(&vlc[i]); + + return 0; +} + +static int cllc_decode_frame(AVCodecContext *avctx, void *data, + int *got_picture_ptr, AVPacket *avpkt) +{ + CLLCContext *ctx = avctx->priv_data; + AVFrame *pic = data; + uint8_t *src = avpkt->data; + uint32_t info_tag, info_offset; + int data_size; + GetBitContext gb; + int coding_type, ret; + + /* Skip the INFO header if present */ + info_offset = 0; + info_tag = AV_RL32(src); + if (info_tag == MKTAG('I', 'N', 'F', 'O')) { + info_offset = AV_RL32(src + 4); + if (info_offset > UINT32_MAX - 8 || info_offset + 8 > avpkt->size) { + av_log(avctx, AV_LOG_ERROR, + "Invalid INFO header offset: 0x%08X is too large.\n", + info_offset); + return AVERROR_INVALIDDATA; + } + + info_offset += 8; + src += info_offset; + + av_log(avctx, AV_LOG_DEBUG, "Skipping INFO chunk.\n"); + } + + data_size = (avpkt->size - info_offset) & ~1; + + /* Make sure our bswap16'd buffer is big enough */ + av_fast_padded_malloc(&ctx->swapped_buf, + &ctx->swapped_buf_size, data_size); + if (!ctx->swapped_buf) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate swapped buffer.\n"); + return AVERROR(ENOMEM); + } + + /* bswap16 the buffer since CLLC's bitreader works in 16-bit words */ + ctx->dsp.bswap16_buf((uint16_t *) ctx->swapped_buf, (uint16_t *) src, + data_size / 2); + + init_get_bits(&gb, ctx->swapped_buf, data_size * 8); + + /* + * Read in coding type. The types are as follows: + * + * 0 - YUY2 + * 1 - BGR24 (Triples) + * 2 - BGR24 (Quads) + * 3 - BGRA + */ + coding_type = (AV_RL32(src) >> 8) & 0xFF; + av_log(avctx, AV_LOG_DEBUG, "Frame coding type: %d\n", coding_type); + + switch (coding_type) { + case 1: + case 2: + avctx->pix_fmt = AV_PIX_FMT_RGB24; + avctx->bits_per_raw_sample = 8; + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + ret = decode_rgb24_frame(ctx, &gb, pic); + if (ret < 0) + return ret; + + break; + case 3: + avctx->pix_fmt = AV_PIX_FMT_ARGB; + avctx->bits_per_raw_sample = 8; + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + ret = decode_argb_frame(ctx, &gb, pic); + if (ret < 0) + return ret; + + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown coding type: %d.\n", coding_type); + return AVERROR_INVALIDDATA; + } + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + *got_picture_ptr = 1; + + return avpkt->size; +} + +static av_cold int cllc_decode_close(AVCodecContext *avctx) +{ + CLLCContext *ctx = avctx->priv_data; + + av_freep(&ctx->swapped_buf); + + return 0; +} + +static av_cold int cllc_decode_init(AVCodecContext *avctx) +{ + CLLCContext *ctx = avctx->priv_data; + + /* Initialize various context values */ + ctx->avctx = avctx; + ctx->swapped_buf = NULL; + ctx->swapped_buf_size = 0; + + ff_dsputil_init(&ctx->dsp, avctx); + + return 0; +} + +AVCodec ff_cllc_decoder = { + .name = "cllc", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CLLC, + .priv_data_size = sizeof(CLLCContext), + .init = cllc_decode_init, + .decode = cllc_decode_frame, + .close = cllc_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Canopus Lossless Codec"), +}; diff --git a/ffmpeg/libavcodec/cngdec.c b/ffmpeg/libavcodec/cngdec.c new file mode 100644 index 0000000..675f77d --- /dev/null +++ b/ffmpeg/libavcodec/cngdec.c @@ -0,0 +1,171 @@ +/* + * RFC 3389 comfort noise generator + * Copyright (c) 2012 Martin Storsjo + * + * 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 "libavutil/common.h" +#include "avcodec.h" +#include "celp_filters.h" +#include "internal.h" +#include "libavutil/lfg.h" + +typedef struct CNGContext { + float *refl_coef, *target_refl_coef; + float *lpc_coef; + int order; + int energy, target_energy; + int inited; + float *filter_out; + float *excitation; + AVLFG lfg; +} CNGContext; + +static av_cold int cng_decode_close(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + av_free(p->refl_coef); + av_free(p->target_refl_coef); + av_free(p->lpc_coef); + av_free(p->filter_out); + av_free(p->excitation); + return 0; +} + +static av_cold int cng_decode_init(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + avctx->sample_rate = 8000; + + p->order = 12; + avctx->frame_size = 640; + p->refl_coef = av_mallocz(p->order * sizeof(*p->refl_coef)); + p->target_refl_coef = av_mallocz(p->order * sizeof(*p->target_refl_coef)); + p->lpc_coef = av_mallocz(p->order * sizeof(*p->lpc_coef)); + p->filter_out = av_mallocz((avctx->frame_size + p->order) * + sizeof(*p->filter_out)); + p->excitation = av_mallocz(avctx->frame_size * sizeof(*p->excitation)); + if (!p->refl_coef || !p->target_refl_coef || !p->lpc_coef || + !p->filter_out || !p->excitation) { + cng_decode_close(avctx); + return AVERROR(ENOMEM); + } + + av_lfg_init(&p->lfg, 0); + + return 0; +} + +static void make_lpc_coefs(float *lpc, const float *refl, int order) +{ + float buf[100]; + float *next, *cur; + int m, i; + next = buf; + cur = lpc; + for (m = 0; m < order; m++) { + next[m] = refl[m]; + for (i = 0; i < m; i++) + next[i] = cur[i] + refl[m] * cur[m - i - 1]; + FFSWAP(float*, next, cur); + } + if (cur != lpc) + memcpy(lpc, cur, sizeof(*lpc) * order); +} + +static void cng_decode_flush(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + p->inited = 0; +} + +static int cng_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + CNGContext *p = avctx->priv_data; + int buf_size = avpkt->size; + int ret, i; + int16_t *buf_out; + float e = 1.0; + float scaling; + + if (avpkt->size) { + int dbov = -avpkt->data[0]; + p->target_energy = 1081109975 * pow(10, dbov / 10.0) * 0.75; + memset(p->target_refl_coef, 0, p->order * sizeof(*p->target_refl_coef)); + for (i = 0; i < FFMIN(avpkt->size - 1, p->order); i++) { + p->target_refl_coef[i] = (avpkt->data[1 + i] - 127) / 128.0; + } + } + + if (p->inited) { + p->energy = p->energy / 2 + p->target_energy / 2; + for (i = 0; i < p->order; i++) + p->refl_coef[i] = 0.6 *p->refl_coef[i] + 0.4 * p->target_refl_coef[i]; + } else { + p->energy = p->target_energy; + memcpy(p->refl_coef, p->target_refl_coef, p->order * sizeof(*p->refl_coef)); + p->inited = 1; + } + make_lpc_coefs(p->lpc_coef, p->refl_coef, p->order); + + for (i = 0; i < p->order; i++) + e *= 1.0 - p->refl_coef[i]*p->refl_coef[i]; + + scaling = sqrt(e * p->energy / 1081109975); + for (i = 0; i < avctx->frame_size; i++) { + int r = (av_lfg_get(&p->lfg) & 0xffff) - 0x8000; + p->excitation[i] = scaling * r; + } + ff_celp_lp_synthesis_filterf(p->filter_out + p->order, p->lpc_coef, + p->excitation, avctx->frame_size, p->order); + + frame->nb_samples = avctx->frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + buf_out = (int16_t *)frame->data[0]; + for (i = 0; i < avctx->frame_size; i++) + buf_out[i] = p->filter_out[i + p->order]; + memcpy(p->filter_out, p->filter_out + avctx->frame_size, + p->order * sizeof(*p->filter_out)); + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_comfortnoise_decoder = { + .name = "comfortnoise", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_COMFORT_NOISE, + .priv_data_size = sizeof(CNGContext), + .init = cng_decode_init, + .decode = cng_decode_frame, + .flush = cng_decode_flush, + .close = cng_decode_close, + .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/cngenc.c b/ffmpeg/libavcodec/cngenc.c new file mode 100644 index 0000000..4ab3019 --- /dev/null +++ b/ffmpeg/libavcodec/cngenc.c @@ -0,0 +1,116 @@ +/* + * RFC 3389 comfort noise generator + * Copyright (c) 2012 Martin Storsjo + * + * 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 "libavutil/common.h" +#include "avcodec.h" +#include "internal.h" +#include "lpc.h" + +typedef struct CNGContext { + LPCContext lpc; + int order; + int32_t *samples32; + double *ref_coef; +} CNGContext; + +static av_cold int cng_encode_close(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + ff_lpc_end(&p->lpc); + av_free(p->samples32); + av_free(p->ref_coef); + return 0; +} + +static av_cold int cng_encode_init(AVCodecContext *avctx) +{ + CNGContext *p = avctx->priv_data; + int ret; + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(EINVAL); + } + + avctx->frame_size = 640; + p->order = 10; + if ((ret = ff_lpc_init(&p->lpc, avctx->frame_size, p->order, FF_LPC_TYPE_LEVINSON)) < 0) + return ret; + p->samples32 = av_malloc(avctx->frame_size * sizeof(*p->samples32)); + p->ref_coef = av_malloc(p->order * sizeof(*p->ref_coef)); + if (!p->samples32 || !p->ref_coef) { + cng_encode_close(avctx); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int cng_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + CNGContext *p = avctx->priv_data; + int ret, i; + double energy = 0; + int qdbov; + int16_t *samples = (int16_t*) frame->data[0]; + + if ((ret = ff_alloc_packet(avpkt, 1 + p->order))) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); + return ret; + } + + for (i = 0; i < frame->nb_samples; i++) { + p->samples32[i] = samples[i]; + energy += samples[i] * samples[i]; + } + energy /= frame->nb_samples; + if (energy > 0) { + double dbov = 10 * log10(energy / 1081109975); + qdbov = av_clip(-floor(dbov), 0, 127); + } else { + qdbov = 127; + } + ret = ff_lpc_calc_ref_coefs(&p->lpc, p->samples32, p->order, p->ref_coef); + avpkt->data[0] = qdbov; + for (i = 0; i < p->order; i++) + avpkt->data[1 + i] = p->ref_coef[i] * 127 + 127; + + *got_packet_ptr = 1; + avpkt->size = 1 + p->order; + + return 0; +} + +AVCodec ff_comfortnoise_encoder = { + .name = "comfortnoise", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_COMFORT_NOISE, + .priv_data_size = sizeof(CNGContext), + .init = cng_encode_init, + .encode2 = cng_encode_frame, + .close = cng_encode_close, + .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/codec_desc.c b/ffmpeg/libavcodec/codec_desc.c new file mode 100644 index 0000000..ded09c9 --- /dev/null +++ b/ffmpeg/libavcodec/codec_desc.c @@ -0,0 +1,2565 @@ +/* + * This file is part of FFmpeg. + * + * This table was generated from the long and short names of AVCodecs + * please see the respective codec sources for authorship + * + * 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 "avcodec.h" + +#include "libavutil/common.h" +#include "libavutil/internal.h" + +static const AVCodecDescriptor codec_descriptors[] = { + /* video codecs */ + { + .id = AV_CODEC_ID_MPEG1VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mpeg1video", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MPEG2VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mpeg2video", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MPEG2VIDEO_XVMC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mpegvideo_xvmc", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video XvMC (X-Video Motion Compensation)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_H261, + .type = AVMEDIA_TYPE_VIDEO, + .name = "h261", + .long_name = NULL_IF_CONFIG_SMALL("H.261"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_H263, + .type = AVMEDIA_TYPE_VIDEO, + .name = "h263", + .long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RV10, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rv10", + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RV20, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rv20", + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MJPEG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mjpeg", + .long_name = NULL_IF_CONFIG_SMALL("Motion JPEG"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MJPEGB, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mjpegb", + .long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_LJPEG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ljpeg", + .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SP5X, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sp5x", + .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_JPEGLS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "jpegls", + .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MPEG4, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mpeg4", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RAWVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rawvideo", + .long_name = NULL_IF_CONFIG_SMALL("raw video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MSMPEG4V1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msmpeg4v1", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MSMPEG4V2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msmpeg4v2", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MSMPEG4V3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msmpeg4v3", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wmv1", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMV2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wmv2", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_H263P, + .type = AVMEDIA_TYPE_VIDEO, + .name = "h263p", + .long_name = NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_H263I, + .type = AVMEDIA_TYPE_VIDEO, + .name = "h263i", + .long_name = NULL_IF_CONFIG_SMALL("Intel H.263"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FLV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "flv1", + .long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SVQ1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "svq1", + .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SVQ3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "svq3", + .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 3 / Sorenson Video 3 / SVQ3"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DVVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dvvideo", + .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_HUFFYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "huffyuv", + .long_name = NULL_IF_CONFIG_SMALL("HuffYUV"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_CYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cyuv", + .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_H264, + .type = AVMEDIA_TYPE_VIDEO, + .name = "h264", + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_INDEO3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "indeo3", + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp3", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP3"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_THEORA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "theora", + .long_name = NULL_IF_CONFIG_SMALL("Theora"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ASV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "asv1", + .long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ASV2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "asv2", + .long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FFV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ffv1", + .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_4XM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "4xm", + .long_name = NULL_IF_CONFIG_SMALL("4X Movie"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VCR1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vcr1", + .long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CLJR, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cljr", + .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MDEC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mdec", + .long_name = NULL_IF_CONFIG_SMALL("Sony PlayStation MDEC (Motion DECoder)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ROQ, + .type = AVMEDIA_TYPE_VIDEO, + .name = "roq", + .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_INTERPLAY_VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "interplayvideo", + .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_XAN_WC3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xan_wc3", + .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_XAN_WC4, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xan_wc4", + .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RPZA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rpza", + .long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CINEPAK, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cinepak", + .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WS_VQA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ws_vqa", + .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MSRLE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msrle", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft RLE"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MSVIDEO1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msvideo1", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video 1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_IDCIN, + .type = AVMEDIA_TYPE_VIDEO, + .name = "idcin", + .long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_8BPS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "8bps", + .long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SMC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "smc", + .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FLIC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "flic", + .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TRUEMOTION1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "truemotion1", + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 1.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VMDVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vmdvideo", + .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MSZH, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mszh", + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ZLIB, + .type = AVMEDIA_TYPE_VIDEO, + .name = "zlib", + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_QTRLE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "qtrle", + .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SNOW, + .type = AVMEDIA_TYPE_VIDEO, + .name = "snow", + .long_name = NULL_IF_CONFIG_SMALL("Snow"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TSCC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tscc", + .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Capture Codec"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ULTI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ulti", + .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_QDRAW, + .type = AVMEDIA_TYPE_VIDEO, + .name = "qdraw", + .long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_VIXL, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vixl", + .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_QPEG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "qpeg", + .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PNG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "png", + .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PPM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ppm", + .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pbm", + .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PGM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgm", + .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PGMYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pgmyuv", + .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PAM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pam", + .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_FFVHUFF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ffvhuff", + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_RV30, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rv30", + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 3.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RV40, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rv40", + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VC1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vc1", + .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMV3, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wmv3", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_LOCO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "loco", + .long_name = NULL_IF_CONFIG_SMALL("LOCO"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_WNV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wnv1", + .long_name = NULL_IF_CONFIG_SMALL("Winnov WNV1"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AASC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "aasc", + .long_name = NULL_IF_CONFIG_SMALL("Autodesk RLE"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_INDEO2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "indeo2", + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FRAPS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "fraps", + .long_name = NULL_IF_CONFIG_SMALL("Fraps"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TRUEMOTION2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "truemotion2", + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BMP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "bmp", + .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_CSCD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cscd", + .long_name = NULL_IF_CONFIG_SMALL("CamStudio"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MMVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mmvideo", + .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ZMBV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "zmbv", + .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_AVS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avs", + .long_name = NULL_IF_CONFIG_SMALL("AVS (Audio Video Standard) video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SMACKVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "smackvideo", + .long_name = NULL_IF_CONFIG_SMALL("Smacker video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_NUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "nuv", + .long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_KMVC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "kmvc", + .long_name = NULL_IF_CONFIG_SMALL("Karl Morton's video codec"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FLASHSV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "flashsv", + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_CAVS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cavs", + .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_JPEG2000, + .type = AVMEDIA_TYPE_VIDEO, + .name = "jpeg2000", + .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_VMNC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vmnc", + .long_name = NULL_IF_CONFIG_SMALL("VMware Screen Codec / VMware Video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_VP5, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp5", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP5"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP6, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp6", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP6"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP6F, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp6f", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TARGA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "targa", + .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DSICINVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dsicinvideo", + .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TIERTEXSEQVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tiertexseqvideo", + .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TIFF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tiff", + .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_GIF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "gif", + .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DXA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dxa", + .long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DNXHD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dnxhd", + .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_THP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "thp", + .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SGI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sgi", + .long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SGIRLE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sgirle", + .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_C93, + .type = AVMEDIA_TYPE_VIDEO, + .name = "c93", + .long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BETHSOFTVID, + .type = AVMEDIA_TYPE_VIDEO, + .name = "bethsoftvid", + .long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PTX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ptx", + .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TXD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "txd", + .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP6A, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp6a", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version, with alpha channel)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AMV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "amv", + .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VB, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vb", + .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pcx", + .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SUNRAST, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sunrast", + .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_INDEO4, + .type = AVMEDIA_TYPE_VIDEO, + .name = "indeo4", + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 4"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_INDEO5, + .type = AVMEDIA_TYPE_VIDEO, + .name = "indeo5", + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 5"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MIMIC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mimic", + .long_name = NULL_IF_CONFIG_SMALL("Mimic"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RL2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "rl2", + .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ESCAPE124, + .type = AVMEDIA_TYPE_VIDEO, + .name = "escape124", + .long_name = NULL_IF_CONFIG_SMALL("Escape 124"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DIRAC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dirac", + .long_name = NULL_IF_CONFIG_SMALL("Dirac"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_BFI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "bfi", + .long_name = NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CMV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cmv", + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts CMV video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MOTIONPIXELS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "motionpixels", + .long_name = NULL_IF_CONFIG_SMALL("Motion Pixels video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TGV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tgv", + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TGQ, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tgq", + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TQI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tqi", + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TQI video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AURA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "aura", + .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AURA2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "aura2", + .long_name = NULL_IF_CONFIG_SMALL("Auravision Aura 2"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_V210X, + .type = AVMEDIA_TYPE_VIDEO, + .name = "v210x", + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_TMV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tmv", + .long_name = NULL_IF_CONFIG_SMALL("8088flex TMV"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_V210, + .type = AVMEDIA_TYPE_VIDEO, + .name = "v210", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DPX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dpx", + .long_name = NULL_IF_CONFIG_SMALL("DPX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MAD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mad", + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Madcow Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FRWU, + .type = AVMEDIA_TYPE_VIDEO, + .name = "frwu", + .long_name = NULL_IF_CONFIG_SMALL("Forward Uncompressed"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_FLASHSV2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "flashsv2", + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CDGRAPHICS, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cdgraphics", + .long_name = NULL_IF_CONFIG_SMALL("CD Graphics video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_R210, + .type = AVMEDIA_TYPE_VIDEO, + .name = "r210", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ANM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "anm", + .long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BINKVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "binkvideo", + .long_name = NULL_IF_CONFIG_SMALL("Bink video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_IFF_ILBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "iff_ilbm", + .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_IFF_BYTERUN1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "iff_byterun1", + .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_KGV1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "kgv1", + .long_name = NULL_IF_CONFIG_SMALL("Kega Game Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_YOP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "yop", + .long_name = NULL_IF_CONFIG_SMALL("Psygnosis YOP Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP8, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp8", + .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VP9, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vp9", + .long_name = NULL_IF_CONFIG_SMALL("Google VP9"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PICTOR, + .type = AVMEDIA_TYPE_VIDEO, + .name = "pictor", + .long_name = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ANSI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ansi", + .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_A64_MULTI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "a64_multi", + .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_A64_MULTI5, + .type = AVMEDIA_TYPE_VIDEO, + .name = "a64_multi5", + .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_R10K, + .type = AVMEDIA_TYPE_VIDEO, + .name = "r10k", + .long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MVC1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mvc1", + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MVC2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mvc2", + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MXPEG, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mxpeg", + .long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_LAGARITH, + .type = AVMEDIA_TYPE_VIDEO, + .name = "lagarith", + .long_name = NULL_IF_CONFIG_SMALL("Lagarith lossless"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PRORES, + .type = AVMEDIA_TYPE_VIDEO, + .name = "prores", + .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_JV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "jv", + .long_name = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DFA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dfa", + .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMV3IMAGE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "wmv3image", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VC1IMAGE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vc1image", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_UTVIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "utvideo", + .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_BMV_VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "bmv_video", + .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_VBLE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vble", + .long_name = NULL_IF_CONFIG_SMALL("VBLE Lossless Codec"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DXTORY, + .type = AVMEDIA_TYPE_VIDEO, + .name = "dxtory", + .long_name = NULL_IF_CONFIG_SMALL("Dxtory"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_V410, + .type = AVMEDIA_TYPE_VIDEO, + .name = "v410", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_XWD, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xwd", + .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_CDXL, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cdxl", + .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_XBM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xbm", + .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ZEROCODEC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "zerocodec", + .long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MSS1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mss1", + .long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MSA1, + .type = AVMEDIA_TYPE_VIDEO, + .name = "msa1", + .long_name = NULL_IF_CONFIG_SMALL("MS ATC Screen"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TSCC2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "tscc2", + .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Codec 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MTS2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mts2", + .long_name = NULL_IF_CONFIG_SMALL("MS Expression Encoder Screen"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CLLC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cllc", + .long_name = NULL_IF_CONFIG_SMALL("Canopus Lossless Codec"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MSS2, + .type = AVMEDIA_TYPE_VIDEO, + .name = "mss2", + .long_name = NULL_IF_CONFIG_SMALL("MS Windows Media Video V9 Screen"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_Y41P, + .type = AVMEDIA_TYPE_VIDEO, + .name = "y41p", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_ESCAPE130, + .type = AVMEDIA_TYPE_VIDEO, + .name = "escape130", + .long_name = NULL_IF_CONFIG_SMALL("Escape 130"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_EXR, + .type = AVMEDIA_TYPE_VIDEO, + .name = "exr", + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_AVRP, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avrp", + .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_012V, + .type = AVMEDIA_TYPE_VIDEO, + .name = "012v", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_G2M, + .type = AVMEDIA_TYPE_VIDEO, + .name = "g2m", + .long_name = NULL_IF_CONFIG_SMALL("GoToMeeting"), + }, + { + .id = AV_CODEC_ID_AVUI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avui", + .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_AYUV, + .type = AVMEDIA_TYPE_VIDEO, + .name = "ayuv", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_TARGA_Y216, + .type = AVMEDIA_TYPE_VIDEO, + .name = "targa_y216", + .long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_V308, + .type = AVMEDIA_TYPE_VIDEO, + .name = "v308", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_V408, + .type = AVMEDIA_TYPE_VIDEO, + .name = "v408", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_YUV4, + .type = AVMEDIA_TYPE_VIDEO, + .name = "yuv4", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_SANM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "sanm", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PAF_VIDEO, + .type = AVMEDIA_TYPE_VIDEO, + .name = "paf_video", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AVRN, + .type = AVMEDIA_TYPE_VIDEO, + .name = "avrn", + .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"), + }, + { + .id = AV_CODEC_ID_CPIA, + .type = AVMEDIA_TYPE_VIDEO, + .name = "cpia", + .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"), + }, + { + .id = AV_CODEC_ID_XFACE, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xface", + .long_name = NULL_IF_CONFIG_SMALL("X-face image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BRENDER_PIX, + .type = AVMEDIA_TYPE_VIDEO, + .name = "brender_pix", + .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + + /* various PCM "codecs" */ + { + .id = AV_CODEC_ID_PCM_S16LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s16le", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S16BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s16be", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U16LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u16le", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 16-bit little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U16BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u16be", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 16-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S8, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s8", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U8, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u8", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 8-bit"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_MULAW, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_mulaw", + .long_name = NULL_IF_CONFIG_SMALL("PCM mu-law / G.711 mu-law"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCM_ALAW, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_alaw", + .long_name = NULL_IF_CONFIG_SMALL("PCM A-law / G.711 A-law"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCM_S32LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s32le", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S32BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s32be", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U32LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u32le", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 32-bit little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U32BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u32be", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 32-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S24LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s24le", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S24BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s24be", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U24LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u24le", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 24-bit little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_U24BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_u24be", + .long_name = NULL_IF_CONFIG_SMALL("PCM unsigned 24-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S24DAUD, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s24daud", + .long_name = NULL_IF_CONFIG_SMALL("PCM D-Cinema audio signed 24-bit"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_ZORK, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_zork", + .long_name = NULL_IF_CONFIG_SMALL("PCM Zork"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCM_S16BE_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s16be_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit big-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S16LE_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s16le_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16-bit little-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S24LE_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s24le_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 24-bit little-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_S32LE_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s32le_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 32-bit little-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_DVD, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_dvd", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20|24-bit big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_F32BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_f32be", + .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_F32LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_f32le", + .long_name = NULL_IF_CONFIG_SMALL("PCM 32-bit floating point little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_F64BE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_f64be", + .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point big-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_F64LE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_f64le", + .long_name = NULL_IF_CONFIG_SMALL("PCM 64-bit floating point little-endian"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_BLURAY, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_bluray", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PCM_LXF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_lxf", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 20-bit little-endian planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_S302M, + .type = AVMEDIA_TYPE_AUDIO, + .name = "s302m", + .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_PCM_S8_PLANAR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "pcm_s8_planar", + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + + /* various ADPCM codecs */ + { + .id = AV_CODEC_ID_ADPCM_IMA_QT, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_qt", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA QuickTime"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_WAV, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_wav", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA WAV"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_DK3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_dk3", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Duck DK3"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_DK4, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_dk4", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Duck DK4"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_WS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_ws", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Westwood"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_SMJPEG, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_smjpeg", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Loki SDL MJPEG"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_MS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ms", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Microsoft"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_4XM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_4xm", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM 4X Movie"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_XA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_xa", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM CDROM XA"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_ADX, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_adx", + .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_EA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ea", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_G726, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_g726", + .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_CT, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ct", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Creative Technology"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_SWF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_swf", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Shockwave Flash"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_YAMAHA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_yamaha", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Yamaha"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_SBPRO_4, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_sbpro_4", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sound Blaster Pro 4-bit"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_SBPRO_3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_sbpro_3", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sound Blaster Pro 2.6-bit"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_SBPRO_2, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_sbpro_2", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Sound Blaster Pro 2-bit"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_THP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_thp", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube THP"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_AMV, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_amv", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA AMV"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_EA_R1, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ea_r1", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts R1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_EA_R3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ea_r3", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts R3"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_EA_R2, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ea_r2", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts R2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_ea_sead", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Electronic Arts SEAD"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_EA_EACS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_ea_eacs", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Electronic Arts EACS"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_EA_XAS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ea_xas", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts XAS"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_EA_MAXIS_XA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ea_maxis_xa", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Electronic Arts Maxis CDROM XA"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_ISS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_iss", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Funcom ISS"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_G722, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_g722", + .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_APC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_apc", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA CRYO APC"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_AFC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_afc", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM Nintendo Gamecube AFC"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ADPCM_IMA_OKI, + .type = AVMEDIA_TYPE_AUDIO, + .name = "adpcm_ima_oki", + .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Dialogic OKI"), + .props = AV_CODEC_PROP_LOSSY, + }, + + /* AMR */ + { + .id = AV_CODEC_ID_AMR_NB, + .type = AVMEDIA_TYPE_AUDIO, + .name = "amr_nb", + .long_name = NULL_IF_CONFIG_SMALL("AMR-NB (Adaptive Multi-Rate NarrowBand)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AMR_WB, + .type = AVMEDIA_TYPE_AUDIO, + .name = "amr_wb", + .long_name = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"), + .props = AV_CODEC_PROP_LOSSY, + }, + + /* RealAudio codecs*/ + { + .id = AV_CODEC_ID_RA_144, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ra_144", + .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RA_288, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ra_288", + .long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"), + .props = AV_CODEC_PROP_LOSSY, + }, + + /* various DPCM codecs */ + { + .id = AV_CODEC_ID_ROQ_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "roq_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM id RoQ"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_INTERPLAY_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "interplay_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM Interplay"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_XAN_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "xan_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM Xan"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SOL_DPCM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sol_dpcm", + .long_name = NULL_IF_CONFIG_SMALL("DPCM Sol"), + .props = AV_CODEC_PROP_LOSSY, + }, + + /* audio codecs */ + { + .id = AV_CODEC_ID_MP2, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mp2", + .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MP3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mp3", + .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AAC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "aac", + .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AC3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ac3", + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DTS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dts", + .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_VORBIS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "vorbis", + .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_DVAUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dvaudio", + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMAV1, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wmav1", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMAV2, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wmav2", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MACE3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mace3", + .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MACE6, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mace6", + .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VMDAUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "vmdaudio", + .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FLAC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "flac", + .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MP3ADU, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mp3adu", + .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MP3ON4, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mp3on4", + .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SHORTEN, + .type = AVMEDIA_TYPE_AUDIO, + .name = "shorten", + .long_name = NULL_IF_CONFIG_SMALL("Shorten"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ALAC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "alac", + .long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_WESTWOOD_SND1, + .type = AVMEDIA_TYPE_AUDIO, + .name = "westwood_snd1", + .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_GSM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "gsm", + .long_name = NULL_IF_CONFIG_SMALL("GSM"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_QDM2, + .type = AVMEDIA_TYPE_AUDIO, + .name = "qdm2", + .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_COOK, + .type = AVMEDIA_TYPE_AUDIO, + .name = "cook", + .long_name = NULL_IF_CONFIG_SMALL("Cook / Cooker / Gecko (RealAudio G2)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TRUESPEECH, + .type = AVMEDIA_TYPE_AUDIO, + .name = "truespeech", + .long_name = NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TTA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "tta", + .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_SMACKAUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "smackaudio", + .long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_QCELP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "qcelp", + .long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WAVPACK, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wavpack", + .long_name = NULL_IF_CONFIG_SMALL("WavPack"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_DSICINAUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dsicinaudio", + .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_IMC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "imc", + .long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MUSEPACK7, + .type = AVMEDIA_TYPE_AUDIO, + .name = "musepack7", + .long_name = NULL_IF_CONFIG_SMALL("Musepack SV7"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MLP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mlp", + .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_GSM_MS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "gsm_ms", + .long_name = NULL_IF_CONFIG_SMALL("GSM Microsoft variant"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ATRAC3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "atrac3", + .long_name = NULL_IF_CONFIG_SMALL("Atrac 3 (Adaptive TRansform Acoustic Coding 3)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VOXWARE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "voxware", + .long_name = NULL_IF_CONFIG_SMALL("Voxware RT29 Metasound"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_APE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ape", + .long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_NELLYMOSER, + .type = AVMEDIA_TYPE_AUDIO, + .name = "nellymoser", + .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MUSEPACK8, + .type = AVMEDIA_TYPE_AUDIO, + .name = "musepack8", + .long_name = NULL_IF_CONFIG_SMALL("Musepack SV8"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SPEEX, + .type = AVMEDIA_TYPE_AUDIO, + .name = "speex", + .long_name = NULL_IF_CONFIG_SMALL("Speex"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMAVOICE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wmavoice", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Voice"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMAPRO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wmapro", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_WMALOSSLESS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wmalossless", + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Lossless"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ATRAC3P, + .type = AVMEDIA_TYPE_AUDIO, + .name = "atrac3p", + .long_name = NULL_IF_CONFIG_SMALL("Sony ATRAC3+"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_EAC3, + .type = AVMEDIA_TYPE_AUDIO, + .name = "eac3", + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SIPR, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sipr", + .long_name = NULL_IF_CONFIG_SMALL("RealAudio SIPR / ACELP.NET"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_MP1, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mp1", + .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TWINVQ, + .type = AVMEDIA_TYPE_AUDIO, + .name = "twinvq", + .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TRUEHD, + .type = AVMEDIA_TYPE_AUDIO, + .name = "truehd", + .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_MP4ALS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "mp4als", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Audio Lossless Coding (ALS)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_ATRAC1, + .type = AVMEDIA_TYPE_AUDIO, + .name = "atrac1", + .long_name = NULL_IF_CONFIG_SMALL("Atrac 1 (Adaptive TRansform Acoustic Coding)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BINKAUDIO_RDFT, + .type = AVMEDIA_TYPE_AUDIO, + .name = "binkaudio_rdft", + .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BINKAUDIO_DCT, + .type = AVMEDIA_TYPE_AUDIO, + .name = "binkaudio_dct", + .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_AAC_LATM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "aac_latm", + .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Coding LATM syntax)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_QDMC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "qdmc", + .long_name = NULL_IF_CONFIG_SMALL("QDesign Music"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_CELT, + .type = AVMEDIA_TYPE_AUDIO, + .name = "celt", + .long_name = NULL_IF_CONFIG_SMALL("Constrained Energy Lapped Transform (CELT)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_G723_1, + .type = AVMEDIA_TYPE_AUDIO, + .name = "g723_1", + .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_G729, + .type = AVMEDIA_TYPE_AUDIO, + .name = "g729", + .long_name = NULL_IF_CONFIG_SMALL("G.729"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_8SVX_EXP, + .type = AVMEDIA_TYPE_AUDIO, + .name = "8svx_exp", + .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_8SVX_FIB, + .type = AVMEDIA_TYPE_AUDIO, + .name = "8svx_fib", + .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_BMV_AUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "bmv_audio", + .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_RALF, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ralf", + .long_name = NULL_IF_CONFIG_SMALL("RealAudio Lossless"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_IAC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "iac", + .long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_ILBC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "ilbc", + .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_VIMA, + .type = AVMEDIA_TYPE_AUDIO, + .name = "vima", + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_FFWAVESYNTH, + .type = AVMEDIA_TYPE_AUDIO, + .name = "wavesynth", + .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), + }, + { + .id = AV_CODEC_ID_SONIC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sonic", + .long_name = NULL_IF_CONFIG_SMALL("Sonic"), + }, + { + .id = AV_CODEC_ID_SONIC_LS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "sonicls", + .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), + }, + { + .id = AV_CODEC_ID_PAF_AUDIO, + .type = AVMEDIA_TYPE_AUDIO, + .name = "paf_audio", + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_OPUS, + .type = AVMEDIA_TYPE_AUDIO, + .name = "opus", + .long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio Codec)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_COMFORT_NOISE, + .type = AVMEDIA_TYPE_AUDIO, + .name = "comfortnoise", + .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 Comfort Noise"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_TAK, + .type = AVMEDIA_TYPE_AUDIO, + .name = "tak", + .long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor)"), + .props = AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_EVRC, + .type = AVMEDIA_TYPE_AUDIO, + .name = "evrc", + .long_name = NULL_IF_CONFIG_SMALL("EVRC (Enhanced Variable Rate Codec)"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_SMV, + .type = AVMEDIA_TYPE_AUDIO, + .name = "smv", + .long_name = NULL_IF_CONFIG_SMALL("SMV (Selectable Mode Vocoder)"), + .props = AV_CODEC_PROP_LOSSY, + }, + + /* subtitle codecs */ + { + .id = AV_CODEC_ID_DVD_SUBTITLE, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "dvd_subtitle", + .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), + .props = AV_CODEC_PROP_BITMAP_SUB, + }, + { + .id = AV_CODEC_ID_DVB_SUBTITLE, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "dvb_subtitle", + .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), + .props = AV_CODEC_PROP_BITMAP_SUB, + }, + { + .id = AV_CODEC_ID_TEXT, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "text", + .long_name = NULL_IF_CONFIG_SMALL("raw UTF-8 text"), + }, + { + .id = AV_CODEC_ID_XSUB, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "xsub", + .long_name = NULL_IF_CONFIG_SMALL("XSUB"), + .props = AV_CODEC_PROP_BITMAP_SUB, + }, + { + .id = AV_CODEC_ID_SSA, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "ssa", + .long_name = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) / ASS (Advanced SSA) subtitle"), + }, + { + .id = AV_CODEC_ID_MOV_TEXT, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "mov_text", + .long_name = NULL_IF_CONFIG_SMALL("MOV text"), + }, + { + .id = AV_CODEC_ID_HDMV_PGS_SUBTITLE, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "hdmv_pgs_subtitle", + .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), + .props = AV_CODEC_PROP_BITMAP_SUB, + }, + { + .id = AV_CODEC_ID_DVB_TELETEXT, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "dvb_teletext", + .long_name = NULL_IF_CONFIG_SMALL("DVB teletext"), + }, + { + .id = AV_CODEC_ID_SRT, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "srt", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle with embedded timing"), + }, + { + .id = AV_CODEC_ID_SUBRIP, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "subrip", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + }, + { + .id = AV_CODEC_ID_MICRODVD, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "microdvd", + .long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle"), + }, + { + .id = AV_CODEC_ID_MPL2, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "mpl2", + .long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitle"), + }, + { + .id = AV_CODEC_ID_EIA_608, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "eia_608", + .long_name = NULL_IF_CONFIG_SMALL("EIA-608 closed captions"), + }, + { + .id = AV_CODEC_ID_JACOSUB, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "jacosub", + .long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle"), + }, + { + .id = AV_CODEC_ID_PJS, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "pjs", + .long_name = NULL_IF_CONFIG_SMALL("PJS (Phoenix Japanimation Society) subtitle"), + }, + { + .id = AV_CODEC_ID_SAMI, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "sami", + .long_name = NULL_IF_CONFIG_SMALL("SAMI subtitle"), + }, + { + .id = AV_CODEC_ID_REALTEXT, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "realtext", + .long_name = NULL_IF_CONFIG_SMALL("RealText subtitle"), + }, + { + .id = AV_CODEC_ID_SUBVIEWER1, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "subviewer1", + .long_name = NULL_IF_CONFIG_SMALL("SubViewer v1 subtitle"), + }, + { + .id = AV_CODEC_ID_SUBVIEWER, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "subviewer", + .long_name = NULL_IF_CONFIG_SMALL("SubViewer subtitle"), + }, + { + .id = AV_CODEC_ID_VPLAYER, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "vplayer", + .long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), + }, + { + .id = AV_CODEC_ID_WEBVTT, + .type = AVMEDIA_TYPE_SUBTITLE, + .name = "webvtt", + .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + }, + { + .id = AV_CODEC_ID_BINTEXT, + .type = AVMEDIA_TYPE_VIDEO, + .name = "bintext", + .long_name = NULL_IF_CONFIG_SMALL("Binary text"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_XBIN, + .type = AVMEDIA_TYPE_VIDEO, + .name = "xbin", + .long_name = NULL_IF_CONFIG_SMALL("eXtended BINary text"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_IDF, + .type = AVMEDIA_TYPE_VIDEO, + .name = "idf", + .long_name = NULL_IF_CONFIG_SMALL("iCEDraw text"), + .props = AV_CODEC_PROP_INTRA_ONLY, + }, + { + .id = AV_CODEC_ID_SMPTE_KLV, + .type = AVMEDIA_TYPE_DATA, + .name = "klv", + .long_name = NULL_IF_CONFIG_SMALL("SMPTE 336M Key-Length-Value (KLV) metadata"), + }, + { + .id = AV_CODEC_ID_DVD_NAV, + .type = AVMEDIA_TYPE_DATA, + .name = "dvd_nav_packet", + .long_name = NULL_IF_CONFIG_SMALL("DVD Nav packet"), + }, + +}; + +const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(codec_descriptors); i++) + if (codec_descriptors[i].id == id) + return &codec_descriptors[i]; + return NULL; +} + +const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev) +{ + if (!prev) + return &codec_descriptors[0]; + if (prev - codec_descriptors < FF_ARRAY_ELEMS(codec_descriptors) - 1) + return prev + 1; + return NULL; +} + +const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name) +{ + const AVCodecDescriptor *desc = NULL; + + while ((desc = avcodec_descriptor_next(desc))) { + if (!strcmp(desc->name, name)) + return desc; + } + return NULL; +} diff --git a/ffmpeg/libavcodec/cook.c b/ffmpeg/libavcodec/cook.c new file mode 100644 index 0000000..08cd401 --- /dev/null +++ b/ffmpeg/libavcodec/cook.c @@ -0,0 +1,1292 @@ +/* + * COOK compatible decoder + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * 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 + */ + +/** + * @file + * Cook compatible decoder. Bastardization of the G.722.1 standard. + * This decoder handles RealNetworks, RealAudio G2 data. + * Cook is identified by the codec name cook in RM files. + * + * To use this decoder, a calling application must supply the extradata + * bytes provided from the RM container; 8+ bytes for mono streams and + * 16+ for stereo streams (maybe more). + * + * Codec technicalities (all this assume a buffer length of 1024): + * Cook works with several different techniques to achieve its compression. + * In the timedomain the buffer is divided into 8 pieces and quantized. If + * two neighboring pieces have different quantization index a smooth + * quantization curve is used to get a smooth overlap between the different + * pieces. + * To get to the transformdomain Cook uses a modulated lapped transform. + * The transform domain has 50 subbands with 20 elements each. This + * means only a maximum of 50*20=1000 coefficients are used out of the 1024 + * available. + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/lfg.h" +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "bytestream.h" +#include "fft.h" +#include "internal.h" +#include "sinewin.h" + +#include "cookdata.h" + +/* the different Cook versions */ +#define MONO 0x1000001 +#define STEREO 0x1000002 +#define JOINT_STEREO 0x1000003 +#define MC_COOK 0x2000000 // multichannel Cook, not supported + +#define SUBBAND_SIZE 20 +#define MAX_SUBPACKETS 5 + +typedef struct { + int *now; + int *previous; +} cook_gains; + +typedef struct { + int ch_idx; + int size; + int num_channels; + int cookversion; + int subbands; + int js_subband_start; + int js_vlc_bits; + int samples_per_channel; + int log2_numvector_size; + unsigned int channel_mask; + VLC channel_coupling; + int joint_stereo; + int bits_per_subpacket; + int bits_per_subpdiv; + int total_subbands; + int numvector_size; // 1 << log2_numvector_size; + + float mono_previous_buffer1[1024]; + float mono_previous_buffer2[1024]; + + cook_gains gains1; + cook_gains gains2; + int gain_1[9]; + int gain_2[9]; + int gain_3[9]; + int gain_4[9]; +} COOKSubpacket; + +typedef struct cook { + /* + * The following 5 functions provide the lowlevel arithmetic on + * the internal audio buffers. + */ + void (*scalar_dequant)(struct cook *q, int index, int quant_index, + int *subband_coef_index, int *subband_coef_sign, + float *mlt_p); + + void (*decouple)(struct cook *q, + COOKSubpacket *p, + int subband, + float f1, float f2, + float *decode_buffer, + float *mlt_buffer1, float *mlt_buffer2); + + void (*imlt_window)(struct cook *q, float *buffer1, + cook_gains *gains_ptr, float *previous_buffer); + + void (*interpolate)(struct cook *q, float *buffer, + int gain_index, int gain_index_next); + + void (*saturate_output)(struct cook *q, float *out); + + AVCodecContext* avctx; + DSPContext dsp; + GetBitContext gb; + /* stream data */ + int num_vectors; + int samples_per_channel; + /* states */ + AVLFG random_state; + int discarded_packets; + + /* transform data */ + FFTContext mdct_ctx; + float* mlt_window; + + /* VLC data */ + VLC envelope_quant_index[13]; + VLC sqvh[7]; // scalar quantization + + /* generatable tables and related variables */ + int gain_size_factor; + float gain_table[23]; + + /* data buffers */ + + uint8_t* decoded_bytes_buffer; + DECLARE_ALIGNED(32, float, mono_mdct_output)[2048]; + float decode_buffer_1[1024]; + float decode_buffer_2[1024]; + float decode_buffer_0[1060]; /* static allocation for joint decode */ + + const float *cplscales[5]; + int num_subpackets; + COOKSubpacket subpacket[MAX_SUBPACKETS]; +} COOKContext; + +static float pow2tab[127]; +static float rootpow2tab[127]; + +/*************** init functions ***************/ + +/* table generator */ +static av_cold void init_pow2table(void) +{ + int i; + for (i = -63; i < 64; i++) { + pow2tab[63 + i] = pow(2, i); + rootpow2tab[63 + i] = sqrt(pow(2, i)); + } +} + +/* table generator */ +static av_cold void init_gain_table(COOKContext *q) +{ + int i; + q->gain_size_factor = q->samples_per_channel / 8; + for (i = 0; i < 23; i++) + q->gain_table[i] = pow(pow2tab[i + 52], + (1.0 / (double) q->gain_size_factor)); +} + + +static av_cold int init_cook_vlc_tables(COOKContext *q) +{ + int i, result; + + result = 0; + for (i = 0; i < 13; i++) { + result |= init_vlc(&q->envelope_quant_index[i], 9, 24, + envelope_quant_index_huffbits[i], 1, 1, + envelope_quant_index_huffcodes[i], 2, 2, 0); + } + av_log(q->avctx, AV_LOG_DEBUG, "sqvh VLC init\n"); + for (i = 0; i < 7; i++) { + result |= init_vlc(&q->sqvh[i], vhvlcsize_tab[i], vhsize_tab[i], + cvh_huffbits[i], 1, 1, + cvh_huffcodes[i], 2, 2, 0); + } + + for (i = 0; i < q->num_subpackets; i++) { + if (q->subpacket[i].joint_stereo == 1) { + result |= init_vlc(&q->subpacket[i].channel_coupling, 6, + (1 << q->subpacket[i].js_vlc_bits) - 1, + ccpl_huffbits[q->subpacket[i].js_vlc_bits - 2], 1, 1, + ccpl_huffcodes[q->subpacket[i].js_vlc_bits - 2], 2, 2, 0); + av_log(q->avctx, AV_LOG_DEBUG, "subpacket %i Joint-stereo VLC used.\n", i); + } + } + + av_log(q->avctx, AV_LOG_DEBUG, "VLC tables initialized.\n"); + return result; +} + +static av_cold int init_cook_mlt(COOKContext *q) +{ + int j, ret; + int mlt_size = q->samples_per_channel; + + if ((q->mlt_window = av_malloc(mlt_size * sizeof(*q->mlt_window))) == 0) + return AVERROR(ENOMEM); + + /* Initialize the MLT window: simple sine window. */ + ff_sine_window_init(q->mlt_window, mlt_size); + for (j = 0; j < mlt_size; j++) + q->mlt_window[j] *= sqrt(2.0 / q->samples_per_channel); + + /* Initialize the MDCT. */ + if ((ret = ff_mdct_init(&q->mdct_ctx, av_log2(mlt_size) + 1, 1, 1.0 / 32768.0))) { + av_free(q->mlt_window); + return ret; + } + av_log(q->avctx, AV_LOG_DEBUG, "MDCT initialized, order = %d.\n", + av_log2(mlt_size) + 1); + + return 0; +} + +static av_cold void init_cplscales_table(COOKContext *q) +{ + int i; + for (i = 0; i < 5; i++) + q->cplscales[i] = cplscales[i]; +} + +/*************** init functions end ***********/ + +#define DECODE_BYTES_PAD1(bytes) (3 - ((bytes) + 3) % 4) +#define DECODE_BYTES_PAD2(bytes) ((bytes) % 4 + DECODE_BYTES_PAD1(2 * (bytes))) + +/** + * Cook indata decoding, every 32 bits are XORed with 0x37c511f2. + * Why? No idea, some checksum/error detection method maybe. + * + * Out buffer size: extra bytes are needed to cope with + * padding/misalignment. + * Subpackets passed to the decoder can contain two, consecutive + * half-subpackets, of identical but arbitrary size. + * 1234 1234 1234 1234 extraA extraB + * Case 1: AAAA BBBB 0 0 + * Case 2: AAAA ABBB BB-- 3 3 + * Case 3: AAAA AABB BBBB 2 2 + * Case 4: AAAA AAAB BBBB BB-- 1 5 + * + * Nice way to waste CPU cycles. + * + * @param inbuffer pointer to byte array of indata + * @param out pointer to byte array of outdata + * @param bytes number of bytes + */ +static inline int decode_bytes(const uint8_t *inbuffer, uint8_t *out, int bytes) +{ + static const uint32_t tab[4] = { + AV_BE2NE32C(0x37c511f2u), AV_BE2NE32C(0xf237c511u), + AV_BE2NE32C(0x11f237c5u), AV_BE2NE32C(0xc511f237u), + }; + int i, off; + uint32_t c; + const uint32_t *buf; + uint32_t *obuf = (uint32_t *) out; + /* FIXME: 64 bit platforms would be able to do 64 bits at a time. + * I'm too lazy though, should be something like + * for (i = 0; i < bitamount / 64; i++) + * (int64_t) out[i] = 0x37c511f237c511f2 ^ av_be2ne64(int64_t) in[i]); + * Buffer alignment needs to be checked. */ + + off = (intptr_t) inbuffer & 3; + buf = (const uint32_t *) (inbuffer - off); + c = tab[off]; + bytes += 3 + off; + for (i = 0; i < bytes / 4; i++) + obuf[i] = c ^ buf[i]; + + return off; +} + +static av_cold int cook_decode_close(AVCodecContext *avctx) +{ + int i; + COOKContext *q = avctx->priv_data; + av_log(avctx, AV_LOG_DEBUG, "Deallocating memory.\n"); + + /* Free allocated memory buffers. */ + av_free(q->mlt_window); + av_free(q->decoded_bytes_buffer); + + /* Free the transform. */ + ff_mdct_end(&q->mdct_ctx); + + /* Free the VLC tables. */ + for (i = 0; i < 13; i++) + ff_free_vlc(&q->envelope_quant_index[i]); + for (i = 0; i < 7; i++) + ff_free_vlc(&q->sqvh[i]); + for (i = 0; i < q->num_subpackets; i++) + ff_free_vlc(&q->subpacket[i].channel_coupling); + + av_log(avctx, AV_LOG_DEBUG, "Memory deallocated.\n"); + + return 0; +} + +/** + * Fill the gain array for the timedomain quantization. + * + * @param gb pointer to the GetBitContext + * @param gaininfo array[9] of gain indexes + */ +static void decode_gain_info(GetBitContext *gb, int *gaininfo) +{ + int i, n; + + while (get_bits1(gb)) { + /* NOTHING */ + } + + n = get_bits_count(gb) - 1; // amount of elements*2 to update + + i = 0; + while (n--) { + int index = get_bits(gb, 3); + int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1; + + while (i <= index) + gaininfo[i++] = gain; + } + while (i <= 8) + gaininfo[i++] = 0; +} + +/** + * Create the quant index table needed for the envelope. + * + * @param q pointer to the COOKContext + * @param quant_index_table pointer to the array + */ +static int decode_envelope(COOKContext *q, COOKSubpacket *p, + int *quant_index_table) +{ + int i, j, vlc_index; + + quant_index_table[0] = get_bits(&q->gb, 6) - 6; // This is used later in categorize + + for (i = 1; i < p->total_subbands; i++) { + vlc_index = i; + if (i >= p->js_subband_start * 2) { + vlc_index -= p->js_subband_start; + } else { + vlc_index /= 2; + if (vlc_index < 1) + vlc_index = 1; + } + if (vlc_index > 13) + vlc_index = 13; // the VLC tables >13 are identical to No. 13 + + j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index - 1].table, + q->envelope_quant_index[vlc_index - 1].bits, 2); + quant_index_table[i] = quant_index_table[i - 1] + j - 12; // differential encoding + if (quant_index_table[i] > 63 || quant_index_table[i] < -63) { + av_log(q->avctx, AV_LOG_ERROR, + "Invalid quantizer %d at position %d, outside [-63, 63] range\n", + quant_index_table[i], i); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +/** + * Calculate the category and category_index vector. + * + * @param q pointer to the COOKContext + * @param quant_index_table pointer to the array + * @param category pointer to the category array + * @param category_index pointer to the category_index array + */ +static void categorize(COOKContext *q, COOKSubpacket *p, const int *quant_index_table, + int *category, int *category_index) +{ + int exp_idx, bias, tmpbias1, tmpbias2, bits_left, num_bits, index, v, i, j; + int exp_index2[102] = { 0 }; + int exp_index1[102] = { 0 }; + + int tmp_categorize_array[128 * 2] = { 0 }; + int tmp_categorize_array1_idx = p->numvector_size; + int tmp_categorize_array2_idx = p->numvector_size; + + bits_left = p->bits_per_subpacket - get_bits_count(&q->gb); + + if (bits_left > q->samples_per_channel) + bits_left = q->samples_per_channel + + ((bits_left - q->samples_per_channel) * 5) / 8; + + bias = -32; + + /* Estimate bias. */ + for (i = 32; i > 0; i = i / 2) { + num_bits = 0; + index = 0; + for (j = p->total_subbands; j > 0; j--) { + exp_idx = av_clip((i - quant_index_table[index] + bias) / 2, 0, 7); + index++; + num_bits += expbits_tab[exp_idx]; + } + if (num_bits >= bits_left - 32) + bias += i; + } + + /* Calculate total number of bits. */ + num_bits = 0; + for (i = 0; i < p->total_subbands; i++) { + exp_idx = av_clip((bias - quant_index_table[i]) / 2, 0, 7); + num_bits += expbits_tab[exp_idx]; + exp_index1[i] = exp_idx; + exp_index2[i] = exp_idx; + } + tmpbias1 = tmpbias2 = num_bits; + + for (j = 1; j < p->numvector_size; j++) { + if (tmpbias1 + tmpbias2 > 2 * bits_left) { /* ---> */ + int max = -999999; + index = -1; + for (i = 0; i < p->total_subbands; i++) { + if (exp_index1[i] < 7) { + v = (-2 * exp_index1[i]) - quant_index_table[i] + bias; + if (v >= max) { + max = v; + index = i; + } + } + } + if (index == -1) + break; + tmp_categorize_array[tmp_categorize_array1_idx++] = index; + tmpbias1 -= expbits_tab[exp_index1[index]] - + expbits_tab[exp_index1[index] + 1]; + ++exp_index1[index]; + } else { /* <--- */ + int min = 999999; + index = -1; + for (i = 0; i < p->total_subbands; i++) { + if (exp_index2[i] > 0) { + v = (-2 * exp_index2[i]) - quant_index_table[i] + bias; + if (v < min) { + min = v; + index = i; + } + } + } + if (index == -1) + break; + tmp_categorize_array[--tmp_categorize_array2_idx] = index; + tmpbias2 -= expbits_tab[exp_index2[index]] - + expbits_tab[exp_index2[index] - 1]; + --exp_index2[index]; + } + } + + for (i = 0; i < p->total_subbands; i++) + category[i] = exp_index2[i]; + + for (i = 0; i < p->numvector_size - 1; i++) + category_index[i] = tmp_categorize_array[tmp_categorize_array2_idx++]; +} + + +/** + * Expand the category vector. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param category_index pointer to the category_index array + */ +static inline void expand_category(COOKContext *q, int *category, + int *category_index) +{ + int i; + for (i = 0; i < q->num_vectors; i++) + { + int idx = category_index[i]; + if (++category[idx] >= FF_ARRAY_ELEMS(dither_tab)) + --category[idx]; + } +} + +/** + * The real requantization of the mltcoefs + * + * @param q pointer to the COOKContext + * @param index index + * @param quant_index quantisation index + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_sign signs of coefficients + * @param mlt_p pointer into the mlt buffer + */ +static void scalar_dequant_float(COOKContext *q, int index, int quant_index, + int *subband_coef_index, int *subband_coef_sign, + float *mlt_p) +{ + int i; + float f1; + + for (i = 0; i < SUBBAND_SIZE; i++) { + if (subband_coef_index[i]) { + f1 = quant_centroid_tab[index][subband_coef_index[i]]; + if (subband_coef_sign[i]) + f1 = -f1; + } else { + /* noise coding if subband_coef_index[i] == 0 */ + f1 = dither_tab[index]; + if (av_lfg_get(&q->random_state) < 0x80000000) + f1 = -f1; + } + mlt_p[i] = f1 * rootpow2tab[quant_index + 63]; + } +} +/** + * Unpack the subband_coef_index and subband_coef_sign vectors. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param subband_coef_index array of indexes to quant_centroid_tab + * @param subband_coef_sign signs of coefficients + */ +static int unpack_SQVH(COOKContext *q, COOKSubpacket *p, int category, + int *subband_coef_index, int *subband_coef_sign) +{ + int i, j; + int vlc, vd, tmp, result; + + vd = vd_tab[category]; + result = 0; + for (i = 0; i < vpr_tab[category]; i++) { + vlc = get_vlc2(&q->gb, q->sqvh[category].table, q->sqvh[category].bits, 3); + if (p->bits_per_subpacket < get_bits_count(&q->gb)) { + vlc = 0; + result = 1; + } + for (j = vd - 1; j >= 0; j--) { + tmp = (vlc * invradix_tab[category]) / 0x100000; + subband_coef_index[vd * i + j] = vlc - tmp * (kmax_tab[category] + 1); + vlc = tmp; + } + for (j = 0; j < vd; j++) { + if (subband_coef_index[i * vd + j]) { + if (get_bits_count(&q->gb) < p->bits_per_subpacket) { + subband_coef_sign[i * vd + j] = get_bits1(&q->gb); + } else { + result = 1; + subband_coef_sign[i * vd + j] = 0; + } + } else { + subband_coef_sign[i * vd + j] = 0; + } + } + } + return result; +} + + +/** + * Fill the mlt_buffer with mlt coefficients. + * + * @param q pointer to the COOKContext + * @param category pointer to the category array + * @param quant_index_table pointer to the array + * @param mlt_buffer pointer to mlt coefficients + */ +static void decode_vectors(COOKContext *q, COOKSubpacket *p, int *category, + int *quant_index_table, float *mlt_buffer) +{ + /* A zero in this table means that the subband coefficient is + random noise coded. */ + int subband_coef_index[SUBBAND_SIZE]; + /* A zero in this table means that the subband coefficient is a + positive multiplicator. */ + int subband_coef_sign[SUBBAND_SIZE]; + int band, j; + int index = 0; + + for (band = 0; band < p->total_subbands; band++) { + index = category[band]; + if (category[band] < 7) { + if (unpack_SQVH(q, p, category[band], subband_coef_index, subband_coef_sign)) { + index = 7; + for (j = 0; j < p->total_subbands; j++) + category[band + j] = 7; + } + } + if (index >= 7) { + memset(subband_coef_index, 0, sizeof(subband_coef_index)); + memset(subband_coef_sign, 0, sizeof(subband_coef_sign)); + } + q->scalar_dequant(q, index, quant_index_table[band], + subband_coef_index, subband_coef_sign, + &mlt_buffer[band * SUBBAND_SIZE]); + } + + /* FIXME: should this be removed, or moved into loop above? */ + if (p->total_subbands * SUBBAND_SIZE >= q->samples_per_channel) + return; +} + + +static int mono_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer) +{ + int category_index[128] = { 0 }; + int category[128] = { 0 }; + int quant_index_table[102]; + int res, i; + + if ((res = decode_envelope(q, p, quant_index_table)) < 0) + return res; + q->num_vectors = get_bits(&q->gb, p->log2_numvector_size); + categorize(q, p, quant_index_table, category, category_index); + expand_category(q, category, category_index); + for (i=0; itotal_subbands; i++) { + if (category[i] > 7) + return AVERROR_INVALIDDATA; + } + decode_vectors(q, p, category, quant_index_table, mlt_buffer); + + return 0; +} + + +/** + * the actual requantization of the timedomain samples + * + * @param q pointer to the COOKContext + * @param buffer pointer to the timedomain buffer + * @param gain_index index for the block multiplier + * @param gain_index_next index for the next block multiplier + */ +static void interpolate_float(COOKContext *q, float *buffer, + int gain_index, int gain_index_next) +{ + int i; + float fc1, fc2; + fc1 = pow2tab[gain_index + 63]; + + if (gain_index == gain_index_next) { // static gain + for (i = 0; i < q->gain_size_factor; i++) + buffer[i] *= fc1; + } else { // smooth gain + fc2 = q->gain_table[11 + (gain_index_next - gain_index)]; + for (i = 0; i < q->gain_size_factor; i++) { + buffer[i] *= fc1; + fc1 *= fc2; + } + } +} + +/** + * Apply transform window, overlap buffers. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the mltcoefficients + * @param gains_ptr current and previous gains + * @param previous_buffer pointer to the previous buffer to be used for overlapping + */ +static void imlt_window_float(COOKContext *q, float *inbuffer, + cook_gains *gains_ptr, float *previous_buffer) +{ + const float fc = pow2tab[gains_ptr->previous[0] + 63]; + int i; + /* The weird thing here, is that the two halves of the time domain + * buffer are swapped. Also, the newest data, that we save away for + * next frame, has the wrong sign. Hence the subtraction below. + * Almost sounds like a complex conjugate/reverse data/FFT effect. + */ + + /* Apply window and overlap */ + for (i = 0; i < q->samples_per_channel; i++) + inbuffer[i] = inbuffer[i] * fc * q->mlt_window[i] - + previous_buffer[i] * q->mlt_window[q->samples_per_channel - 1 - i]; +} + +/** + * The modulated lapped transform, this takes transform coefficients + * and transforms them into timedomain samples. + * Apply transform window, overlap buffers, apply gain profile + * and buffer management. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the mltcoefficients + * @param gains_ptr current and previous gains + * @param previous_buffer pointer to the previous buffer to be used for overlapping + */ +static void imlt_gain(COOKContext *q, float *inbuffer, + cook_gains *gains_ptr, float *previous_buffer) +{ + float *buffer0 = q->mono_mdct_output; + float *buffer1 = q->mono_mdct_output + q->samples_per_channel; + int i; + + /* Inverse modified discrete cosine transform */ + q->mdct_ctx.imdct_calc(&q->mdct_ctx, q->mono_mdct_output, inbuffer); + + q->imlt_window(q, buffer1, gains_ptr, previous_buffer); + + /* Apply gain profile */ + for (i = 0; i < 8; i++) + if (gains_ptr->now[i] || gains_ptr->now[i + 1]) + q->interpolate(q, &buffer1[q->gain_size_factor * i], + gains_ptr->now[i], gains_ptr->now[i + 1]); + + /* Save away the current to be previous block. */ + memcpy(previous_buffer, buffer0, + q->samples_per_channel * sizeof(*previous_buffer)); +} + + +/** + * function for getting the jointstereo coupling information + * + * @param q pointer to the COOKContext + * @param decouple_tab decoupling array + */ +static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) +{ + int i; + int vlc = get_bits1(&q->gb); + int start = cplband[p->js_subband_start]; + int end = cplband[p->subbands - 1]; + int length = end - start + 1; + + if (start > end) + return 0; + + if (vlc) + for (i = 0; i < length; i++) + decouple_tab[start + i] = get_vlc2(&q->gb, + p->channel_coupling.table, + p->channel_coupling.bits, 2); + else + for (i = 0; i < length; i++) { + int v = get_bits(&q->gb, p->js_vlc_bits); + if (v == (1<js_vlc_bits)-1) { + av_log(q->avctx, AV_LOG_ERROR, "decouple value too large\n"); + return AVERROR_INVALIDDATA; + } + decouple_tab[start + i] = v; + } + return 0; +} + +/** + * function decouples a pair of signals from a single signal via multiplication. + * + * @param q pointer to the COOKContext + * @param subband index of the current subband + * @param f1 multiplier for channel 1 extraction + * @param f2 multiplier for channel 2 extraction + * @param decode_buffer input buffer + * @param mlt_buffer1 pointer to left channel mlt coefficients + * @param mlt_buffer2 pointer to right channel mlt coefficients + */ +static void decouple_float(COOKContext *q, + COOKSubpacket *p, + int subband, + float f1, float f2, + float *decode_buffer, + float *mlt_buffer1, float *mlt_buffer2) +{ + int j, tmp_idx; + for (j = 0; j < SUBBAND_SIZE; j++) { + tmp_idx = ((p->js_subband_start + subband) * SUBBAND_SIZE) + j; + mlt_buffer1[SUBBAND_SIZE * subband + j] = f1 * decode_buffer[tmp_idx]; + mlt_buffer2[SUBBAND_SIZE * subband + j] = f2 * decode_buffer[tmp_idx]; + } +} + +/** + * function for decoding joint stereo data + * + * @param q pointer to the COOKContext + * @param mlt_buffer1 pointer to left channel mlt coefficients + * @param mlt_buffer2 pointer to right channel mlt coefficients + */ +static int joint_decode(COOKContext *q, COOKSubpacket *p, + float *mlt_buffer_left, float *mlt_buffer_right) +{ + int i, j, res; + int decouple_tab[SUBBAND_SIZE] = { 0 }; + float *decode_buffer = q->decode_buffer_0; + int idx, cpl_tmp; + float f1, f2; + const float *cplscale; + + memset(decode_buffer, 0, sizeof(q->decode_buffer_0)); + + /* Make sure the buffers are zeroed out. */ + memset(mlt_buffer_left, 0, 1024 * sizeof(*mlt_buffer_left)); + memset(mlt_buffer_right, 0, 1024 * sizeof(*mlt_buffer_right)); + if ((res = decouple_info(q, p, decouple_tab)) < 0) + return res; + if ((res = mono_decode(q, p, decode_buffer)) < 0) + return res; + /* The two channels are stored interleaved in decode_buffer. */ + for (i = 0; i < p->js_subband_start; i++) { + for (j = 0; j < SUBBAND_SIZE; j++) { + mlt_buffer_left[i * 20 + j] = decode_buffer[i * 40 + j]; + mlt_buffer_right[i * 20 + j] = decode_buffer[i * 40 + 20 + j]; + } + } + + /* When we reach js_subband_start (the higher frequencies) + the coefficients are stored in a coupling scheme. */ + idx = (1 << p->js_vlc_bits) - 1; + for (i = p->js_subband_start; i < p->subbands; i++) { + cpl_tmp = cplband[i]; + idx -= decouple_tab[cpl_tmp]; + cplscale = q->cplscales[p->js_vlc_bits - 2]; // choose decoupler table + f1 = cplscale[decouple_tab[cpl_tmp] + 1]; + f2 = cplscale[idx]; + q->decouple(q, p, i, f1, f2, decode_buffer, + mlt_buffer_left, mlt_buffer_right); + idx = (1 << p->js_vlc_bits) - 1; + } + + return 0; +} + +/** + * First part of subpacket decoding: + * decode raw stream bytes and read gain info. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to raw stream data + * @param gains_ptr array of current/prev gain pointers + */ +static inline void decode_bytes_and_gain(COOKContext *q, COOKSubpacket *p, + const uint8_t *inbuffer, + cook_gains *gains_ptr) +{ + int offset; + + offset = decode_bytes(inbuffer, q->decoded_bytes_buffer, + p->bits_per_subpacket / 8); + init_get_bits(&q->gb, q->decoded_bytes_buffer + offset, + p->bits_per_subpacket); + decode_gain_info(&q->gb, gains_ptr->now); + + /* Swap current and previous gains */ + FFSWAP(int *, gains_ptr->now, gains_ptr->previous); +} + +/** + * Saturate the output signal and interleave. + * + * @param q pointer to the COOKContext + * @param out pointer to the output vector + */ +static void saturate_output_float(COOKContext *q, float *out) +{ + q->dsp.vector_clipf(out, q->mono_mdct_output + q->samples_per_channel, + -1.0f, 1.0f, FFALIGN(q->samples_per_channel, 8)); +} + + +/** + * Final part of subpacket decoding: + * Apply modulated lapped transform, gain compensation, + * clip and convert to integer. + * + * @param q pointer to the COOKContext + * @param decode_buffer pointer to the mlt coefficients + * @param gains_ptr array of current/prev gain pointers + * @param previous_buffer pointer to the previous buffer to be used for overlapping + * @param out pointer to the output buffer + */ +static inline void mlt_compensate_output(COOKContext *q, float *decode_buffer, + cook_gains *gains_ptr, float *previous_buffer, + float *out) +{ + imlt_gain(q, decode_buffer, gains_ptr, previous_buffer); + if (out) + q->saturate_output(q, out); +} + + +/** + * Cook subpacket decoding. This function returns one decoded subpacket, + * usually 1024 samples per channel. + * + * @param q pointer to the COOKContext + * @param inbuffer pointer to the inbuffer + * @param outbuffer pointer to the outbuffer + */ +static int decode_subpacket(COOKContext *q, COOKSubpacket *p, + const uint8_t *inbuffer, float **outbuffer) +{ + int sub_packet_size = p->size; + int res; + + memset(q->decode_buffer_1, 0, sizeof(q->decode_buffer_1)); + decode_bytes_and_gain(q, p, inbuffer, &p->gains1); + + if (p->joint_stereo) { + if ((res = joint_decode(q, p, q->decode_buffer_1, q->decode_buffer_2)) < 0) + return res; + } else { + if ((res = mono_decode(q, p, q->decode_buffer_1)) < 0) + return res; + + if (p->num_channels == 2) { + decode_bytes_and_gain(q, p, inbuffer + sub_packet_size / 2, &p->gains2); + if ((res = mono_decode(q, p, q->decode_buffer_2)) < 0) + return res; + } + } + + mlt_compensate_output(q, q->decode_buffer_1, &p->gains1, + p->mono_previous_buffer1, + outbuffer ? outbuffer[p->ch_idx] : NULL); + + if (p->num_channels == 2) { + if (p->joint_stereo) + mlt_compensate_output(q, q->decode_buffer_2, &p->gains1, + p->mono_previous_buffer2, + outbuffer ? outbuffer[p->ch_idx + 1] : NULL); + else + mlt_compensate_output(q, q->decode_buffer_2, &p->gains2, + p->mono_previous_buffer2, + outbuffer ? outbuffer[p->ch_idx + 1] : NULL); + } + + return 0; +} + + +static int cook_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + COOKContext *q = avctx->priv_data; + float **samples = NULL; + int i, ret; + int offset = 0; + int chidx = 0; + + if (buf_size < avctx->block_align) + return buf_size; + + /* get output buffer */ + if (q->discarded_packets >= 2) { + frame->nb_samples = q->samples_per_channel; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (float **)frame->extended_data; + } + + /* estimate subpacket sizes */ + q->subpacket[0].size = avctx->block_align; + + for (i = 1; i < q->num_subpackets; i++) { + q->subpacket[i].size = 2 * buf[avctx->block_align - q->num_subpackets + i]; + q->subpacket[0].size -= q->subpacket[i].size + 1; + if (q->subpacket[0].size < 0) { + av_log(avctx, AV_LOG_DEBUG, + "frame subpacket size total > avctx->block_align!\n"); + return AVERROR_INVALIDDATA; + } + } + + /* decode supbackets */ + for (i = 0; i < q->num_subpackets; i++) { + q->subpacket[i].bits_per_subpacket = (q->subpacket[i].size * 8) >> + q->subpacket[i].bits_per_subpdiv; + q->subpacket[i].ch_idx = chidx; + av_log(avctx, AV_LOG_DEBUG, + "subpacket[%i] size %i js %i %i block_align %i\n", + i, q->subpacket[i].size, q->subpacket[i].joint_stereo, offset, + avctx->block_align); + + if ((ret = decode_subpacket(q, &q->subpacket[i], buf + offset, samples)) < 0) + return ret; + offset += q->subpacket[i].size; + chidx += q->subpacket[i].num_channels; + av_log(avctx, AV_LOG_DEBUG, "subpacket[%i] %i %i\n", + i, q->subpacket[i].size * 8, get_bits_count(&q->gb)); + } + + /* Discard the first two frames: no valid audio. */ + if (q->discarded_packets < 2) { + q->discarded_packets++; + *got_frame_ptr = 0; + return avctx->block_align; + } + + *got_frame_ptr = 1; + + return avctx->block_align; +} + +#ifdef DEBUG +static void dump_cook_context(COOKContext *q) +{ + //int i=0; +#define PRINT(a, b) av_dlog(q->avctx, " %s = %d\n", a, b); + av_dlog(q->avctx, "COOKextradata\n"); + av_dlog(q->avctx, "cookversion=%x\n", q->subpacket[0].cookversion); + if (q->subpacket[0].cookversion > STEREO) { + PRINT("js_subband_start", q->subpacket[0].js_subband_start); + PRINT("js_vlc_bits", q->subpacket[0].js_vlc_bits); + } + av_dlog(q->avctx, "COOKContext\n"); + PRINT("nb_channels", q->avctx->channels); + PRINT("bit_rate", q->avctx->bit_rate); + PRINT("sample_rate", q->avctx->sample_rate); + PRINT("samples_per_channel", q->subpacket[0].samples_per_channel); + PRINT("subbands", q->subpacket[0].subbands); + PRINT("js_subband_start", q->subpacket[0].js_subband_start); + PRINT("log2_numvector_size", q->subpacket[0].log2_numvector_size); + PRINT("numvector_size", q->subpacket[0].numvector_size); + PRINT("total_subbands", q->subpacket[0].total_subbands); +} +#endif + +/** + * Cook initialization + * + * @param avctx pointer to the AVCodecContext + */ +static av_cold int cook_decode_init(AVCodecContext *avctx) +{ + COOKContext *q = avctx->priv_data; + const uint8_t *edata_ptr = avctx->extradata; + const uint8_t *edata_ptr_end = edata_ptr + avctx->extradata_size; + int extradata_size = avctx->extradata_size; + int s = 0; + unsigned int channel_mask = 0; + int samples_per_frame = 0; + int ret; + q->avctx = avctx; + + /* Take care of the codec specific extradata. */ + if (extradata_size <= 0) { + av_log(avctx, AV_LOG_ERROR, "Necessary extradata missing!\n"); + return AVERROR_INVALIDDATA; + } + av_log(avctx, AV_LOG_DEBUG, "codecdata_length=%d\n", avctx->extradata_size); + + /* Take data from the AVCodecContext (RM container). */ + if (!avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } + + /* Initialize RNG. */ + av_lfg_init(&q->random_state, 0); + + ff_dsputil_init(&q->dsp, avctx); + + while (edata_ptr < edata_ptr_end) { + /* 8 for mono, 16 for stereo, ? for multichannel + Swap to right endianness so we don't need to care later on. */ + if (extradata_size >= 8) { + q->subpacket[s].cookversion = bytestream_get_be32(&edata_ptr); + samples_per_frame = bytestream_get_be16(&edata_ptr); + q->subpacket[s].subbands = bytestream_get_be16(&edata_ptr); + extradata_size -= 8; + } + if (extradata_size >= 8) { + bytestream_get_be32(&edata_ptr); // Unknown unused + q->subpacket[s].js_subband_start = bytestream_get_be16(&edata_ptr); + if (q->subpacket[s].js_subband_start >= 51) { + av_log(avctx, AV_LOG_ERROR, "js_subband_start %d is too large\n", q->subpacket[s].js_subband_start); + return AVERROR_INVALIDDATA; + } + + q->subpacket[s].js_vlc_bits = bytestream_get_be16(&edata_ptr); + extradata_size -= 8; + } + + /* Initialize extradata related variables. */ + q->subpacket[s].samples_per_channel = samples_per_frame / avctx->channels; + q->subpacket[s].bits_per_subpacket = avctx->block_align * 8; + + /* Initialize default data states. */ + q->subpacket[s].log2_numvector_size = 5; + q->subpacket[s].total_subbands = q->subpacket[s].subbands; + q->subpacket[s].num_channels = 1; + + /* Initialize version-dependent variables */ + + av_log(avctx, AV_LOG_DEBUG, "subpacket[%i].cookversion=%x\n", s, + q->subpacket[s].cookversion); + q->subpacket[s].joint_stereo = 0; + switch (q->subpacket[s].cookversion) { + case MONO: + if (avctx->channels != 1) { + avpriv_request_sample(avctx, "Container channels != 1"); + return AVERROR_PATCHWELCOME; + } + av_log(avctx, AV_LOG_DEBUG, "MONO\n"); + break; + case STEREO: + if (avctx->channels != 1) { + q->subpacket[s].bits_per_subpdiv = 1; + q->subpacket[s].num_channels = 2; + } + av_log(avctx, AV_LOG_DEBUG, "STEREO\n"); + break; + case JOINT_STEREO: + if (avctx->channels != 2) { + avpriv_request_sample(avctx, "Container channels != 2"); + return AVERROR_PATCHWELCOME; + } + av_log(avctx, AV_LOG_DEBUG, "JOINT_STEREO\n"); + if (avctx->extradata_size >= 16) { + q->subpacket[s].total_subbands = q->subpacket[s].subbands + + q->subpacket[s].js_subband_start; + q->subpacket[s].joint_stereo = 1; + q->subpacket[s].num_channels = 2; + } + if (q->subpacket[s].samples_per_channel > 256) { + q->subpacket[s].log2_numvector_size = 6; + } + if (q->subpacket[s].samples_per_channel > 512) { + q->subpacket[s].log2_numvector_size = 7; + } + break; + case MC_COOK: + av_log(avctx, AV_LOG_DEBUG, "MULTI_CHANNEL\n"); + if (extradata_size >= 4) + channel_mask |= q->subpacket[s].channel_mask = bytestream_get_be32(&edata_ptr); + + if (av_get_channel_layout_nb_channels(q->subpacket[s].channel_mask) > 1) { + q->subpacket[s].total_subbands = q->subpacket[s].subbands + + q->subpacket[s].js_subband_start; + q->subpacket[s].joint_stereo = 1; + q->subpacket[s].num_channels = 2; + q->subpacket[s].samples_per_channel = samples_per_frame >> 1; + + if (q->subpacket[s].samples_per_channel > 256) { + q->subpacket[s].log2_numvector_size = 6; + } + if (q->subpacket[s].samples_per_channel > 512) { + q->subpacket[s].log2_numvector_size = 7; + } + } else + q->subpacket[s].samples_per_channel = samples_per_frame; + + break; + default: + avpriv_request_sample(avctx, "Cook version %d", + q->subpacket[s].cookversion); + return AVERROR_PATCHWELCOME; + } + + if (s > 1 && q->subpacket[s].samples_per_channel != q->samples_per_channel) { + av_log(avctx, AV_LOG_ERROR, "different number of samples per channel!\n"); + return AVERROR_INVALIDDATA; + } else + q->samples_per_channel = q->subpacket[0].samples_per_channel; + + + /* Initialize variable relations */ + q->subpacket[s].numvector_size = (1 << q->subpacket[s].log2_numvector_size); + + /* Try to catch some obviously faulty streams, othervise it might be exploitable */ + if (q->subpacket[s].total_subbands > 53) { + avpriv_request_sample(avctx, "total_subbands > 53"); + return AVERROR_PATCHWELCOME; + } + + if ((q->subpacket[s].js_vlc_bits > 6) || + (q->subpacket[s].js_vlc_bits < 2 * q->subpacket[s].joint_stereo)) { + av_log(avctx, AV_LOG_ERROR, "js_vlc_bits = %d, only >= %d and <= 6 allowed!\n", + q->subpacket[s].js_vlc_bits, 2 * q->subpacket[s].joint_stereo); + return AVERROR_INVALIDDATA; + } + + if (q->subpacket[s].subbands > 50) { + avpriv_request_sample(avctx, "subbands > 50"); + return AVERROR_PATCHWELCOME; + } + if (q->subpacket[s].subbands == 0) { + avpriv_request_sample(avctx, "subbands = 0"); + return AVERROR_PATCHWELCOME; + } + q->subpacket[s].gains1.now = q->subpacket[s].gain_1; + q->subpacket[s].gains1.previous = q->subpacket[s].gain_2; + q->subpacket[s].gains2.now = q->subpacket[s].gain_3; + q->subpacket[s].gains2.previous = q->subpacket[s].gain_4; + + if (q->num_subpackets + q->subpacket[s].num_channels > q->avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Too many subpackets %d for channels %d\n", q->num_subpackets, q->avctx->channels); + return AVERROR_INVALIDDATA; + } + + q->num_subpackets++; + s++; + if (s > MAX_SUBPACKETS) { + avpriv_request_sample(avctx, "subpackets > %d", MAX_SUBPACKETS); + return AVERROR_PATCHWELCOME; + } + } + /* Generate tables */ + init_pow2table(); + init_gain_table(q); + init_cplscales_table(q); + + if ((ret = init_cook_vlc_tables(q))) + return ret; + + + if (avctx->block_align >= UINT_MAX / 2) + return AVERROR(EINVAL); + + /* Pad the databuffer with: + DECODE_BYTES_PAD1 or DECODE_BYTES_PAD2 for decode_bytes(), + FF_INPUT_BUFFER_PADDING_SIZE, for the bitstreamreader. */ + q->decoded_bytes_buffer = + av_mallocz(avctx->block_align + + DECODE_BYTES_PAD1(avctx->block_align) + + FF_INPUT_BUFFER_PADDING_SIZE); + if (q->decoded_bytes_buffer == NULL) + return AVERROR(ENOMEM); + + /* Initialize transform. */ + if ((ret = init_cook_mlt(q))) + return ret; + + /* Initialize COOK signal arithmetic handling */ + if (1) { + q->scalar_dequant = scalar_dequant_float; + q->decouple = decouple_float; + q->imlt_window = imlt_window_float; + q->interpolate = interpolate_float; + q->saturate_output = saturate_output_float; + } + + /* Try to catch some obviously faulty streams, othervise it might be exploitable */ + if (q->samples_per_channel != 256 && q->samples_per_channel != 512 && + q->samples_per_channel != 1024) { + avpriv_request_sample(avctx, "samples_per_channel = %d", + q->samples_per_channel); + return AVERROR_PATCHWELCOME; + } + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + if (channel_mask) + avctx->channel_layout = channel_mask; + else + avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + +#ifdef DEBUG + dump_cook_context(q); +#endif + return 0; +} + +AVCodec ff_cook_decoder = { + .name = "cook", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_COOK, + .priv_data_size = sizeof(COOKContext), + .init = cook_decode_init, + .close = cook_decode_close, + .decode = cook_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Cook / Cooker / Gecko (RealAudio G2)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/cook_parser.c b/ffmpeg/libavcodec/cook_parser.c new file mode 100644 index 0000000..f140e90 --- /dev/null +++ b/ffmpeg/libavcodec/cook_parser.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Cook audio parser + * + * Determines subpacket duration from extradata. + */ + +#include + +#include "libavutil/intreadwrite.h" +#include "parser.h" + +typedef struct CookParseContext { + int duration; +} CookParseContext; + +static int cook_parse(AVCodecParserContext *s1, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + CookParseContext *s = s1->priv_data; + + if (s->duration) + s1->duration = s->duration; + else if (avctx->extradata && avctx->extradata_size >= 8 && avctx->channels) + s->duration = AV_RB16(avctx->extradata + 4) / avctx->channels; + + /* always return the full packet. this parser isn't doing any splitting or + combining, only setting packet duration */ + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +AVCodecParser ff_cook_parser = { + .codec_ids = { AV_CODEC_ID_COOK }, + .priv_data_size = sizeof(CookParseContext), + .parser_parse = cook_parse, +}; diff --git a/ffmpeg/libavcodec/cookdata.h b/ffmpeg/libavcodec/cookdata.h new file mode 100644 index 0000000..7b9cba3 --- /dev/null +++ b/ffmpeg/libavcodec/cookdata.h @@ -0,0 +1,580 @@ +/* + * COOK compatible decoder data + * Copyright (c) 2003 Sascha Sommer + * Copyright (c) 2005 Benjamin Larsson + * + * 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 + */ + +/** + * @file + * Cook AKA RealAudio G2 compatible decoderdata + */ + +#ifndef AVCODEC_COOKDATA_H +#define AVCODEC_COOKDATA_H + +#include + +/* various data tables */ + +static const int expbits_tab[8] = { + 52,47,43,37,29,22,16,0, +}; + +static const float dither_tab[9] = { + 0.0, 0.0, 0.0, 0.0, 0.0, 0.176777, 0.25, 0.707107, 1.0 +}; + +static const float quant_centroid_tab[7][14] = { + { 0.000, 0.392, 0.761, 1.120, 1.477, 1.832, 2.183, 2.541, 2.893, 3.245, 3.598, 3.942, 4.288, 4.724 }, + { 0.000, 0.544, 1.060, 1.563, 2.068, 2.571, 3.072, 3.562, 4.070, 4.620, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 0.746, 1.464, 2.180, 2.882, 3.584, 4.316, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.006, 2.000, 2.993, 3.985, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.321, 2.703, 3.983, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.657, 3.491, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 }, + { 0.000, 1.964, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000 } +}; + +static const int invradix_tab[7] = { + 74899, 104858, 149797, 209716, 262144, 349526, 524288, +}; + +static const int kmax_tab[7] = { + 13, 9, 6, 4, 3, 2, 1, +}; + +static const int vd_tab[7] = { + 2, 2, 2, 4, 4, 5, 5, +}; + +static const int vpr_tab[7] = { + 10, 10, 10, 5, 5, 4, 4, +}; + + + +/* VLC data */ + +static const int vhsize_tab[7] = { + 191, 97, 48, 607, 246, 230, 32, +}; + +static const int vhvlcsize_tab[7] = { + 8, 7, 7, 10, 9, 9, 6, +}; + +static const uint8_t envelope_quant_index_huffbits[13][24] = { + { 4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12 }, + { 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16 }, + { 12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14 }, + { 13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13 }, + { 12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14 }, + { 12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14 }, + { 15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16 }, + { 14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15 }, + { 9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13 }, + { 14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14 }, + { 13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14 }, + { 16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16 }, + { 13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14 }, +}; + +static const uint16_t envelope_quant_index_huffcodes[13][24] = { + {0x0006, 0x003e, 0x001c, 0x001d, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x0000, 0x0001, + 0x0002, 0x000d, 0x001e, 0x007e, 0x00fe, 0x01fe, 0x07fc, 0x07fd, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff}, + {0x03fe, 0x00fe, 0x003e, 0x001c, 0x001d, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, + 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x0ffe, 0x1ffe, 0x7ffc, 0x7ffd, 0x7ffe, 0xfffe, 0xffff}, + {0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x0000, + 0x0001, 0x0002, 0x000c, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0x3ffe, 0x3fff}, + {0x1ffc, 0x03fe, 0x01fc, 0x01fd, 0x007c, 0x007d, 0x001c, 0x001d, 0x000a, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x000b, 0x000c, 0x000d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffd, 0x1ffe, 0x1fff}, + {0x0ffe, 0x1ffe, 0x03fe, 0x00fe, 0x003c, 0x003d, 0x001a, 0x001b, 0x000a, 0x000b, 0x0000, 0x0001, + 0x0002, 0x0003, 0x0004, 0x000c, 0x001c, 0x001d, 0x003e, 0x007e, 0x01fe, 0x07fe, 0x3ffe, 0x3fff}, + {0x0ffe, 0x07fe, 0x01fe, 0x00fc, 0x00fd, 0x007c, 0x001c, 0x000a, 0x000b, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x000c, 0x000d, 0x001d, 0x001e, 0x007d, 0x00fe, 0x03fe, 0x1ffe, 0x3ffe, 0x3fff}, + {0x7ffc, 0xfffc, 0x7ffd, 0x0ffe, 0x03fe, 0x00fe, 0x003e, 0x001c, 0x000c, 0x0002, 0x0003, 0x0004, + 0x0000, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x1ffe, 0xfffd, 0xfffe, 0xffff}, + {0x3ffc, 0x3ffd, 0x07fe, 0x03fe, 0x01fc, 0x007c, 0x007d, 0x001c, 0x001d, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x0005, 0x000d, 0x001e, 0x007e, 0x01fd, 0x01fe, 0x0ffe, 0x3ffe, 0x7ffe, 0x7fff}, + {0x01fc, 0x01fd, 0x01fe, 0x00fc, 0x007c, 0x003c, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x000d, 0x001d, 0x003d, 0x007d, 0x00fd, 0x03fe, 0x07fe, 0x0ffe, 0x1ffe, 0x1fff}, + {0x3ffc, 0x0ffe, 0x03fe, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000c, 0x0000, 0x0001, 0x0002, 0x0003, + 0x0004, 0x0005, 0x000d, 0x001d, 0x003e, 0x00fd, 0x00fe, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, + {0x1ffe, 0x03fe, 0x01fc, 0x00fc, 0x003c, 0x003d, 0x001c, 0x000a, 0x000b, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x000d, 0x001d, 0x003e, 0x00fd, 0x01fd, 0x01fe, 0x07fe, 0x0ffe, 0x3ffe, 0x3fff}, + {0xfffc, 0x1ffe, 0x0ffe, 0x07fe, 0x01fe, 0x003e, 0x001c, 0x001d, 0x000a, 0x000b, 0x000c, 0x0002, + 0x0000, 0x0003, 0x0004, 0x000d, 0x001e, 0x007e, 0x00fe, 0x03fe, 0x3ffe, 0xfffd, 0xfffe, 0xffff}, + {0x1ffc, 0x3ffa, 0x3ffb, 0x3ffc, 0x03fe, 0x00fe, 0x007c, 0x007d, 0x001c, 0x000c, 0x0002, 0x0003, + 0x0000, 0x0004, 0x0005, 0x000d, 0x001d, 0x001e, 0x007e, 0x01fe, 0x07fe, 0x3ffd, 0x3ffe, 0x3fff}, +}; + + +static const uint8_t cvh_huffbits0[191] = { + 1, 4, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, + 11, 11, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, + 9, 10, 11, 11, 5, 6, 7, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 11, 12, 6, 7, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 12, 13, 7, 7, 8, 9, + 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 8, 8, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 13, 14, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, + 13, 15, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, + 12, 13, 14, 15, 9, 9, 9, 10, 10, 10, 11, 11, + 12, 13, 12, 14, 15, 16, 9, 9, 10, 10, 10, 10, + 11, 12, 12, 14, 14, 16, 16, 0, 9, 9, 10, 10, + 11, 11, 12, 13, 13, 14, 14, 15, 0, 0, 10, 10, + 10, 11, 11, 12, 12, 13, 15, 15, 16, 0, 0, 0, + 11, 11, 11, 12, 13, 13, 13, 15, 16, 16, 0, 0, + 0, 0, 11, 11, 12, 13, 13, 14, 15, 16, 16, +}; + +static const uint16_t cvh_huffcodes0[191] = { + 0x0000,0x0008,0x002c,0x002d,0x0062,0x0063,0x00d4,0x00d5,0x00d6,0x01c6,0x01c7,0x03ca, + 0x07d6,0x07d7,0x0009,0x0014,0x002e,0x0064,0x0065,0x00d7,0x00d8,0x01c8,0x01c9,0x01ca, + 0x01cb,0x03cb,0x07d8,0x07d9,0x0015,0x002f,0x0066,0x00d9,0x00da,0x01cc,0x01cd,0x01ce, + 0x01cf,0x03cc,0x03cd,0x03ce,0x07da,0x0fe4,0x0030,0x0067,0x00db,0x01d0,0x01d1,0x01d2, + 0x01d3,0x03cf,0x03d0,0x03d1,0x03d2,0x07db,0x0fe5,0x1fea,0x0068,0x0069,0x00dc,0x01d4, + 0x01d5,0x01d6,0x03d3,0x03d4,0x03d5,0x03d6,0x07dc,0x07dd,0x0fe6,0x1feb,0x00dd,0x00de, + 0x01d7,0x01d8,0x01d9,0x03d7,0x03d8,0x03d9,0x03da,0x07de,0x07df,0x0fe7,0x1fec,0x3ff2, + 0x00df,0x00e0,0x01da,0x01db,0x03db,0x03dc,0x07e0,0x07e1,0x07e2,0x0fe8,0x0fe9,0x1fed, + 0x1fee,0x7ff4,0x00e1,0x00e2,0x01dc,0x01dd,0x03dd,0x03de,0x07e3,0x07e4,0x07e5,0x0fea, + 0x0feb,0x1fef,0x3ff3,0x7ff5,0x01de,0x01df,0x01e0,0x03df,0x03e0,0x03e1,0x07e6,0x07e7, + 0x0fec,0x1ff0,0x0fed,0x3ff4,0x7ff6,0xfff8,0x01e1,0x01e2,0x03e2,0x03e3,0x03e4,0x03e5, + 0x07e8,0x0fee,0x0fef,0x3ff5,0x3ff6,0xfff9,0xfffa,0xfffa,0x01e3,0x01e4,0x03e6,0x03e7, + 0x07e9,0x07ea,0x0ff0,0x1ff1,0x1ff2,0x3ff7,0x3ff8,0x7ff7,0x7ff7,0xfffa,0x03e8,0x03e9, + 0x03ea,0x07eb,0x07ec,0x0ff1,0x0ff2,0x1ff3,0x7ff8,0x7ff9,0xfffb,0x3ff8,0x7ff7,0x7ff7, + 0x07ed,0x07ee,0x07ef,0x0ff3,0x1ff4,0x1ff5,0x1ff6,0x7ffa,0xfffc,0xfffd,0xfffb,0xfffb, + 0x3ff8,0x7ff7,0x07f0,0x07f1,0x0ff4,0x1ff7,0x1ff8,0x3ff9,0x7ffb,0xfffe,0xffff, +}; + + +static const uint8_t cvh_huffbits1[97] = { + 1, 4, 5, 6, 7, 8, 8, 9, 10, 10, 4, 5, + 6, 7, 7, 8, 8, 9, 9, 11, 5, 5, 6, 7, + 8, 8, 9, 9, 10, 11, 6, 6, 7, 8, 8, 9, + 9, 10, 11, 12, 7, 7, 8, 8, 9, 9, 10, 11, + 11, 13, 8, 8, 8, 9, 9, 10, 10, 11, 12, 14, + 8, 8, 8, 9, 10, 11, 11, 12, 13, 15, 9, 9, + 9, 10, 11, 12, 12, 14, 14, 0, 9, 9, 9, 10, + 11, 12, 14, 16, 0, 0, 10, 10, 11, 12, 13, 14, + 16, +}; + + +static const uint16_t cvh_huffcodes1[97] = { + 0x0000,0x0008,0x0014,0x0030,0x006a,0x00e2,0x00e3,0x01e4,0x03ec,0x03ed,0x0009,0x0015, + 0x0031,0x006b,0x006c,0x00e4,0x00e5,0x01e5,0x01e6,0x07f0,0x0016,0x0017,0x0032,0x006d, + 0x00e6,0x00e7,0x01e7,0x01e8,0x03ee,0x07f1,0x0033,0x0034,0x006e,0x00e8,0x00e9,0x01e9, + 0x01ea,0x03ef,0x07f2,0x0ff6,0x006f,0x0070,0x00ea,0x00eb,0x01eb,0x01ec,0x03f0,0x07f3, + 0x07f4,0x1ffa,0x00ec,0x00ed,0x00ee,0x01ed,0x01ee,0x03f1,0x03f2,0x07f5,0x0ff7,0x3ffa, + 0x00ef,0x00f0,0x00f1,0x01ef,0x03f3,0x07f6,0x07f7,0x0ff8,0x1ffb,0x7ffe,0x01f0,0x01f1, + 0x01f2,0x03f4,0x07f8,0x0ff9,0x0ffa,0x3ffb,0x3ffc,0x0000,0x01f3,0x01f4,0x01f5,0x03f5, + 0x07f9,0x0ffb,0x3ffd,0xfffe,0x0000,0x0000,0x03f6,0x03f7,0x07fa,0x0ffc,0x1ffc,0x3ffe, + 0xffff, +}; + +static const uint8_t cvh_huffbits2[48] = { + 1, 4, 5, 7, 8, 9, 10, 3, 4, 5, 7, 8, + 9, 10, 5, 5, 6, 7, 8, 10, 10, 7, 6, 7, + 8, 9, 10, 12, 8, 8, 8, 9, 10, 12, 14, 8, + 9, 9, 10, 11, 15, 16, 9, 10, 11, 12, 13, 16, +}; + +static const uint16_t cvh_huffcodes2[48] = { + 0x0000,0x000a,0x0018,0x0074,0x00f2,0x01f4,0x03f6,0x0004,0x000b,0x0019,0x0075,0x00f3, + 0x01f5,0x03f7,0x001a,0x001b,0x0038,0x0076,0x00f4,0x03f8,0x03f9,0x0077,0x0039,0x0078, + 0x00f5,0x01f6,0x03fa,0x0ffc,0x00f6,0x00f7,0x00f8,0x01f7,0x03fb,0x0ffd,0x3ffe,0x00f9, + 0x01f8,0x01f9,0x03fc,0x07fc,0x7ffe,0xfffe,0x01fa,0x03fd,0x07fd,0x0ffe,0x1ffe,0xffff, +}; + +static const uint8_t cvh_huffbits3[607] = { + 2, 4, 6, 8, 10, 5, 5, 6, 8, 10, 7, 8, + 8, 10, 12, 9, 9, 10, 12, 15, 10, 11, 13, 16, + 16, 5, 6, 8, 10, 11, 5, 6, 8, 10, 12, 7, + 7, 8, 10, 13, 9, 9, 10, 12, 15, 12, 11, 13, + 16, 16, 7, 9, 10, 12, 15, 7, 8, 10, 12, 13, + 9, 9, 11, 13, 16, 11, 11, 12, 14, 16, 12, 12, + 14, 16, 0, 9, 11, 12, 16, 16, 9, 10, 13, 15, + 16, 10, 11, 12, 16, 16, 13, 13, 16, 16, 16, 16, + 16, 15, 16, 0, 11, 13, 16, 16, 15, 11, 13, 15, + 16, 16, 13, 13, 16, 16, 0, 14, 16, 16, 16, 0, + 16, 16, 0, 0, 0, 4, 6, 8, 10, 13, 6, 6, + 8, 10, 13, 9, 8, 10, 12, 16, 10, 10, 11, 15, + 16, 13, 12, 14, 16, 16, 5, 6, 8, 11, 13, 6, + 6, 8, 10, 13, 8, 8, 9, 11, 14, 10, 10, 12, + 12, 16, 13, 12, 13, 15, 16, 7, 8, 9, 12, 16, + 7, 8, 10, 12, 14, 9, 9, 10, 13, 16, 11, 10, + 12, 15, 16, 13, 13, 16, 16, 0, 9, 11, 13, 16, + 16, 9, 10, 12, 15, 16, 10, 11, 13, 16, 16, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 0, 11, 13, 16, + 16, 16, 11, 13, 16, 16, 16, 12, 13, 15, 16, 0, + 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 6, 8, + 11, 13, 16, 8, 8, 10, 12, 16, 11, 10, 11, 13, + 16, 12, 13, 13, 15, 16, 16, 16, 14, 16, 0, 6, + 8, 10, 13, 16, 8, 8, 10, 12, 16, 10, 10, 11, + 13, 16, 13, 12, 13, 16, 16, 14, 14, 14, 16, 0, + 8, 9, 11, 13, 16, 8, 9, 11, 16, 14, 10, 10, + 12, 15, 16, 12, 12, 13, 16, 16, 15, 16, 16, 16, + 0, 10, 12, 15, 16, 16, 10, 12, 12, 14, 16, 12, + 12, 13, 16, 16, 14, 15, 16, 16, 0, 16, 16, 16, + 0, 0, 12, 15, 15, 16, 0, 13, 13, 16, 16, 0, + 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 0, 0, + 0, 0, 0, 8, 10, 13, 15, 16, 10, 11, 13, 16, + 16, 13, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 0, 8, 10, 11, 15, 16, 9, 10, 12, + 16, 16, 12, 12, 15, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 0, 9, 11, 14, 16, 16, 10, 11, + 13, 16, 16, 14, 13, 14, 16, 16, 16, 15, 15, 16, + 0, 16, 16, 16, 0, 0, 11, 13, 16, 16, 16, 11, + 13, 15, 16, 16, 13, 16, 16, 16, 0, 16, 16, 16, + 16, 0, 16, 16, 0, 0, 0, 15, 16, 16, 16, 0, + 14, 16, 16, 16, 0, 16, 16, 16, 0, 0, 16, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 13, 16, 16, + 16, 11, 13, 16, 16, 16, 14, 15, 16, 16, 0, 15, + 16, 16, 16, 0, 16, 16, 0, 0, 0, 9, 13, 15, + 15, 16, 12, 13, 14, 16, 16, 16, 15, 16, 16, 0, + 16, 16, 16, 16, 0, 16, 16, 0, 0, 0, 11, 13, + 15, 16, 0, 12, 14, 16, 16, 0, 16, 16, 16, 16, + 0, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, + 16, 16, 16, 0, 16, 16, 16, 16, 0, 16, 16, 16, + 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 0, 0, 0, 16, 16, +}; + + +static const uint16_t cvh_huffcodes3[607] = { + 0x0000,0x0004,0x0022,0x00c6,0x03b0,0x000c,0x000d,0x0023,0x00c7,0x03b1,0x005c,0x00c8, + 0x00c9,0x03b2,0x0fa4,0x01c2,0x01c3,0x03b3,0x0fa5,0x7f72,0x03b4,0x07b2,0x1f9a,0xff24, + 0xff25,0x000e,0x0024,0x00ca,0x03b5,0x07b3,0x000f,0x0025,0x00cb,0x03b6,0x0fa6,0x005d, + 0x005e,0x00cc,0x03b7,0x1f9b,0x01c4,0x01c5,0x03b8,0x0fa7,0x7f73,0x0fa8,0x07b4,0x1f9c, + 0xff26,0xff27,0x005f,0x01c6,0x03b9,0x0fa9,0x7f74,0x0060,0x00cd,0x03ba,0x0faa,0x1f9d, + 0x01c7,0x01c8,0x07b5,0x1f9e,0xff28,0x07b6,0x07b7,0x0fab,0x3fa2,0xff29,0x0fac,0x0fad, + 0x3fa3,0xff2a,0x3fa2,0x01c9,0x07b8,0x0fae,0xff2b,0xff2c,0x01ca,0x03bb,0x1f9f,0x7f75, + 0xff2d,0x03bc,0x07b9,0x0faf,0xff2e,0xff2f,0x1fa0,0x1fa1,0xff30,0xff31,0xff32,0xff33, + 0xff34,0x7f76,0xff35,0xff31,0x07ba,0x1fa2,0xff36,0xff37,0x7f77,0x07bb,0x1fa3,0x7f78, + 0xff38,0xff39,0x1fa4,0x1fa5,0xff3a,0xff3b,0xff2e,0x3fa4,0xff3c,0xff3d,0xff3e,0xff31, + 0xff3f,0xff40,0xff30,0xff31,0xff31,0x0005,0x0026,0x00ce,0x03bd,0x1fa6,0x0027,0x0028, + 0x00cf,0x03be,0x1fa7,0x01cb,0x00d0,0x03bf,0x0fb0,0xff41,0x03c0,0x03c1,0x07bc,0x7f79, + 0xff42,0x1fa8,0x0fb1,0x3fa5,0xff43,0xff44,0x0010,0x0029,0x00d1,0x07bd,0x1fa9,0x002a, + 0x002b,0x00d2,0x03c2,0x1faa,0x00d3,0x00d4,0x01cc,0x07be,0x3fa6,0x03c3,0x03c4,0x0fb2, + 0x0fb3,0xff45,0x1fab,0x0fb4,0x1fac,0x7f7a,0xff46,0x0061,0x00d5,0x01cd,0x0fb5,0xff47, + 0x0062,0x00d6,0x03c5,0x0fb6,0x3fa7,0x01ce,0x01cf,0x03c6,0x1fad,0xff48,0x07bf,0x03c7, + 0x0fb7,0x7f7b,0xff49,0x1fae,0x1faf,0xff4a,0xff4b,0x7f7b,0x01d0,0x07c0,0x1fb0,0xff4c, + 0xff4d,0x01d1,0x03c8,0x0fb8,0x7f7c,0xff4e,0x03c9,0x07c1,0x1fb1,0xff4f,0xff50,0x1fb2, + 0x0fb9,0xff51,0xff52,0xff53,0xff54,0xff55,0xff56,0xff57,0xff52,0x07c2,0x1fb3,0xff58, + 0xff59,0xff5a,0x07c3,0x1fb4,0xff5b,0xff5c,0xff5d,0x0fba,0x1fb5,0x7f7d,0xff5e,0xff4f, + 0xff5f,0xff60,0xff61,0xff62,0xff52,0xff63,0xff64,0xff51,0xff52,0xff52,0x002c,0x00d7, + 0x07c4,0x1fb6,0xff65,0x00d8,0x00d9,0x03ca,0x0fbb,0xff66,0x07c5,0x03cb,0x07c6,0x1fb7, + 0xff67,0x0fbc,0x1fb8,0x1fb9,0x7f7e,0xff68,0xff69,0xff6a,0x3fa8,0xff6b,0x7f7e,0x002d, + 0x00da,0x03cc,0x1fba,0xff6c,0x00db,0x00dc,0x03cd,0x0fbd,0xff6d,0x03ce,0x03cf,0x07c7, + 0x1fbb,0xff6e,0x1fbc,0x0fbe,0x1fbd,0xff6f,0xff70,0x3fa9,0x3faa,0x3fab,0xff71,0xff6f, + 0x00dd,0x01d2,0x07c8,0x1fbe,0xff72,0x00de,0x01d3,0x07c9,0xff73,0x3fac,0x03d0,0x03d1, + 0x0fbf,0x7f7f,0xff74,0x0fc0,0x0fc1,0x1fbf,0xff75,0xff76,0x7f80,0xff77,0xff78,0xff79, + 0xff75,0x03d2,0x0fc2,0x7f81,0xff7a,0xff7b,0x03d3,0x0fc3,0x0fc4,0x3fad,0xff7c,0x0fc5, + 0x0fc6,0x1fc0,0xff7d,0xff7e,0x3fae,0x7f82,0xff7f,0xff80,0xff80,0xff81,0xff82,0xff83, + 0xff80,0xff80,0x0fc7,0x7f83,0x7f84,0xff84,0xff7a,0x1fc1,0x1fc2,0xff85,0xff86,0x3fad, + 0x3faf,0xff87,0xff88,0xff89,0xff7d,0xff8a,0xff8b,0xff8c,0xff80,0xff80,0x3fae,0x7f82, + 0xff7f,0xff80,0xff80,0x00df,0x03d4,0x1fc3,0x7f85,0xff8d,0x03d5,0x07ca,0x1fc4,0xff8e, + 0xff8f,0x1fc5,0x1fc6,0x3fb0,0xff90,0xff91,0xff92,0xff93,0xff94,0xff95,0xff96,0xff97, + 0xff98,0xff99,0xff9a,0xff95,0x00e0,0x03d6,0x07cb,0x7f86,0xff9b,0x01d4,0x03d7,0x0fc8, + 0xff9c,0xff9d,0x0fc9,0x0fca,0x7f87,0xff9e,0xff9f,0xffa0,0x3fb1,0xffa1,0xffa2,0xffa3, + 0xffa4,0xffa5,0xffa6,0xffa7,0xffa2,0x01d5,0x07cc,0x3fb2,0xffa8,0xffa9,0x03d8,0x07cd, + 0x1fc7,0xffaa,0xffab,0x3fb3,0x1fc8,0x3fb4,0xffac,0xffad,0xffae,0x7f88,0x7f89,0xffaf, + 0xffaf,0xffb0,0xffb1,0xffb2,0xffaf,0xffaf,0x07ce,0x1fc9,0xffb3,0xffb4,0xffb5,0x07cf, + 0x1fca,0x7f8a,0xffb6,0xffb7,0x1fcb,0xffb8,0xffb9,0xffba,0xffba,0xffbb,0xffbc,0xffbd, + 0xffbe,0xffbe,0xffbf,0xffc0,0xffbd,0xffbe,0xffbe,0x7f8b,0xffc1,0xffc2,0xffc3,0xffb4, + 0x3fb5,0xffc4,0xffc5,0xffc6,0xffb6,0xffc7,0xffc8,0xffc9,0xffba,0xffba,0xffca,0xffcb, + 0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe,0x01d6,0x1fcc,0xffcc,0xffcd, + 0xffce,0x07d0,0x1fcd,0xffcf,0xffd0,0xffd1,0x3fb6,0x7f8c,0xffd2,0xffd3,0xff90,0x7f8d, + 0xffd4,0xffd5,0xffd6,0xff95,0xffd7,0xffd8,0xff94,0xff95,0xff95,0x01d7,0x1fce,0x7f8e, + 0x7f8f,0xffd9,0x0fcb,0x1fcf,0x3fb7,0xffda,0xffdb,0xffdc,0x7f90,0xffdd,0xffde,0xff9e, + 0xffdf,0xffe0,0xffe1,0xffe2,0xffa2,0xffe3,0xffe4,0xffa1,0xffa2,0xffa2,0x07d1,0x1fd0, + 0x7f91,0xffe5,0xffa8,0x0fcc,0x3fb8,0xffe6,0xffe7,0xffaa,0xffe8,0xffe9,0xffea,0xffeb, + 0xffac,0xffec,0xffed,0xffee,0xffaf,0xffaf,0xffae,0x7f88,0x7f89,0xffaf,0xffaf,0xffef, + 0xfff0,0xfff1,0xfff2,0xffb4,0xfff3,0xfff4,0xfff5,0xfff6,0xffb6,0xfff7,0xfff8,0xfff9, + 0xffba,0xffba,0xfffa,0xfffb,0xffbd,0xffbe,0xffbe,0xffbb,0xffbc,0xffbd,0xffbe,0xffbe, + 0xfffc,0xfffd,0xffb3,0xffb4,0xffb4,0xfffe,0xffff, +}; + +static const uint8_t cvh_huffbits4[246] = { + 2, 4, 7, 10, 4, 5, 7, 10, 7, 8, 10, 14, + 11, 11, 15, 15, 4, 5, 9, 12, 5, 5, 8, 12, + 8, 7, 10, 15, 11, 11, 15, 15, 7, 9, 12, 15, + 8, 8, 12, 15, 10, 10, 13, 15, 14, 14, 15, 0, + 11, 13, 15, 15, 11, 13, 15, 15, 14, 15, 15, 0, + 15, 15, 0, 0, 4, 5, 9, 13, 5, 6, 9, 13, + 9, 9, 11, 15, 14, 13, 15, 15, 4, 6, 9, 12, + 5, 6, 9, 13, 9, 8, 11, 15, 13, 12, 15, 15, + 7, 9, 12, 15, 7, 8, 11, 15, 10, 10, 14, 15, + 14, 15, 15, 0, 10, 12, 15, 15, 11, 13, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 6, 9, 13, 14, + 8, 9, 12, 15, 12, 12, 15, 15, 15, 15, 15, 0, + 7, 9, 13, 15, 8, 9, 12, 15, 11, 12, 15, 15, + 15, 15, 15, 0, 9, 11, 15, 15, 9, 11, 15, 15, + 14, 14, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, + 14, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 9, 12, 15, 15, 12, 13, 15, 15, 15, 15, 15, 0, + 15, 15, 0, 0, 10, 12, 15, 15, 12, 14, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 0, 14, 15, 15, 0, + 15, 15, 15, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 15, 15, +}; + + +static const uint16_t cvh_huffcodes4[246] = { + 0x0000,0x0004,0x006c,0x03e6,0x0005,0x0012,0x006d,0x03e7,0x006e,0x00e8,0x03e8,0x3fc4, + 0x07e0,0x07e1,0x7fa4,0x7fa5,0x0006,0x0013,0x01e2,0x0fda,0x0014,0x0015,0x00e9,0x0fdb, + 0x00ea,0x006f,0x03e9,0x7fa6,0x07e2,0x07e3,0x7fa7,0x7fa8,0x0070,0x01e3,0x0fdc,0x7fa9, + 0x00eb,0x00ec,0x0fdd,0x7faa,0x03ea,0x03eb,0x1fd6,0x7fab,0x3fc5,0x3fc6,0x7fac,0x1fd6, + 0x07e4,0x1fd7,0x7fad,0x7fae,0x07e5,0x1fd8,0x7faf,0x7fb0,0x3fc7,0x7fb1,0x7fb2,0x1fd6, + 0x7fb3,0x7fb4,0x1fd6,0x1fd6,0x0007,0x0016,0x01e4,0x1fd9,0x0017,0x0032,0x01e5,0x1fda, + 0x01e6,0x01e7,0x07e6,0x7fb5,0x3fc8,0x1fdb,0x7fb6,0x7fb7,0x0008,0x0033,0x01e8,0x0fde, + 0x0018,0x0034,0x01e9,0x1fdc,0x01ea,0x00ed,0x07e7,0x7fb8,0x1fdd,0x0fdf,0x7fb9,0x7fba, + 0x0071,0x01eb,0x0fe0,0x7fbb,0x0072,0x00ee,0x07e8,0x7fbc,0x03ec,0x03ed,0x3fc9,0x7fbd, + 0x3fca,0x7fbe,0x7fbf,0x3fc9,0x03ee,0x0fe1,0x7fc0,0x7fc1,0x07e9,0x1fde,0x7fc2,0x7fc3, + 0x7fc4,0x7fc5,0x7fc6,0x3fc9,0x7fc7,0x7fc8,0x3fc9,0x3fc9,0x0035,0x01ec,0x1fdf,0x3fcb, + 0x00ef,0x01ed,0x0fe2,0x7fc9,0x0fe3,0x0fe4,0x7fca,0x7fcb,0x7fcc,0x7fcd,0x7fce,0x7fca, + 0x0073,0x01ee,0x1fe0,0x7fcf,0x00f0,0x01ef,0x0fe5,0x7fd0,0x07ea,0x0fe6,0x7fd1,0x7fd2, + 0x7fd3,0x7fd4,0x7fd5,0x7fd1,0x01f0,0x07eb,0x7fd6,0x7fd7,0x01f1,0x07ec,0x7fd8,0x7fd9, + 0x3fcc,0x3fcd,0x7fda,0x7fda,0x7fdb,0x7fdc,0x7fda,0x7fda,0x3fce,0x7fdd,0x7fde,0x7fd6, + 0x3fcf,0x7fdf,0x7fe0,0x7fd8,0x7fe1,0x7fe2,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, + 0x01f2,0x0fe7,0x7fe3,0x7fe4,0x0fe8,0x1fe1,0x7fe5,0x7fe6,0x7fe7,0x7fe8,0x7fe9,0x7fca, + 0x7fea,0x7feb,0x7fca,0x7fca,0x03ef,0x0fe9,0x7fec,0x7fed,0x0fea,0x3fd0,0x7fee,0x7fef, + 0x7ff0,0x7ff1,0x7ff2,0x7fd1,0x7ff3,0x7ff4,0x7fd1,0x7fd1,0x3fd1,0x7ff5,0x7ff6,0x7fd6, + 0x7ff7,0x7ff8,0x7ff9,0x7fd8,0x7ffa,0x7ffb,0x7fda,0x7fda,0x3fcc,0x3fcd,0x7fda,0x7fda, + 0x7ffc,0x7ffd,0x7fd6,0x7fd6,0x7ffe,0x7fff, +}; + + +static const uint8_t cvh_huffbits5[230] = { + 2, 4, 8, 4, 5, 9, 9, 10, 14, 4, 6, 11, + 5, 6, 12, 10, 11, 15, 9, 11, 15, 10, 13, 15, + 14, 15, 0, 4, 6, 12, 6, 7, 12, 12, 12, 15, + 5, 7, 13, 6, 7, 13, 12, 13, 15, 10, 12, 15, + 11, 13, 15, 15, 15, 0, 8, 13, 15, 11, 12, 15, + 15, 15, 0, 10, 13, 15, 12, 15, 15, 15, 15, 0, + 15, 15, 0, 15, 15, 0, 0, 0, 0, 4, 5, 11, + 5, 7, 12, 11, 12, 15, 6, 7, 13, 7, 8, 14, + 12, 14, 15, 11, 13, 15, 12, 13, 15, 15, 15, 0, + 5, 6, 13, 7, 8, 15, 12, 14, 15, 6, 8, 14, + 7, 8, 15, 14, 15, 15, 12, 12, 15, 12, 13, 15, + 15, 15, 0, 9, 13, 15, 12, 13, 15, 15, 15, 0, + 11, 13, 15, 13, 13, 15, 15, 15, 0, 14, 15, 0, + 15, 15, 0, 0, 0, 0, 8, 10, 15, 11, 12, 15, + 15, 15, 0, 10, 12, 15, 12, 13, 15, 15, 15, 0, + 14, 15, 0, 15, 15, 0, 0, 0, 0, 8, 12, 15, + 12, 13, 15, 15, 15, 0, 11, 13, 15, 13, 15, 15, + 15, 15, 0, 15, 15, 0, 15, 15, 0, 0, 0, 0, + 14, 15, 0, 15, 15, 0, 0, 0, 0, 15, 15, 0, + 15, 15, +}; + + + +static const uint16_t cvh_huffcodes5[230] = { + 0x0000,0x0004,0x00f0,0x0005,0x0012,0x01f0,0x01f1,0x03e8,0x3fce,0x0006,0x0030,0x07de, + 0x0013,0x0031,0x0fd2,0x03e9,0x07df,0x7fb0,0x01f2,0x07e0,0x7fb1,0x03ea,0x1fd2,0x7fb2, + 0x3fcf,0x7fb3,0x0031,0x0007,0x0032,0x0fd3,0x0033,0x0070,0x0fd4,0x0fd5,0x0fd6,0x7fb4, + 0x0014,0x0071,0x1fd3,0x0034,0x0072,0x1fd4,0x0fd7,0x1fd5,0x7fb5,0x03eb,0x0fd8,0x7fb6, + 0x07e1,0x1fd6,0x7fb7,0x7fb8,0x7fb9,0x0072,0x00f1,0x1fd7,0x7fba,0x07e2,0x0fd9,0x7fbb, + 0x7fbc,0x7fbd,0x0070,0x03ec,0x1fd8,0x7fbe,0x0fda,0x7fbf,0x7fc0,0x7fc1,0x7fc2,0x0072, + 0x7fc3,0x7fc4,0x0071,0x7fc5,0x7fc6,0x0072,0x0034,0x0072,0x0072,0x0008,0x0015,0x07e3, + 0x0016,0x0073,0x0fdb,0x07e4,0x0fdc,0x7fc7,0x0035,0x0074,0x1fd9,0x0075,0x00f2,0x3fd0, + 0x0fdd,0x3fd1,0x7fc8,0x07e5,0x1fda,0x7fc9,0x0fde,0x1fdb,0x7fca,0x7fcb,0x7fcc,0x00f2, + 0x0017,0x0036,0x1fdc,0x0076,0x00f3,0x7fcd,0x0fdf,0x3fd2,0x7fce,0x0037,0x00f4,0x3fd3, + 0x0077,0x00f5,0x7fcf,0x3fd4,0x7fd0,0x7fd1,0x0fe0,0x0fe1,0x7fd2,0x0fe2,0x1fdd,0x7fd3, + 0x7fd4,0x7fd5,0x00f5,0x01f3,0x1fde,0x7fd6,0x0fe3,0x1fdf,0x7fd7,0x7fd8,0x7fd9,0x00f3, + 0x07e6,0x1fe0,0x7fda,0x1fe1,0x1fe2,0x7fdb,0x7fdc,0x7fdd,0x00f5,0x3fd5,0x7fde,0x00f4, + 0x7fdf,0x7fe0,0x00f5,0x0077,0x00f5,0x00f5,0x00f6,0x03ed,0x7fe1,0x07e7,0x0fe4,0x7fe2, + 0x7fe3,0x7fe4,0x0073,0x03ee,0x0fe5,0x7fe5,0x0fe6,0x1fe3,0x7fe6,0x7fe7,0x7fe8,0x00f2, + 0x3fd6,0x7fe9,0x0074,0x7fea,0x7feb,0x00f2,0x0075,0x00f2,0x00f2,0x00f7,0x0fe7,0x7fec, + 0x0fe8,0x1fe4,0x7fed,0x7fee,0x7fef,0x00f3,0x07e8,0x1fe5,0x7ff0,0x1fe6,0x7ff1,0x7ff2, + 0x7ff3,0x7ff4,0x00f5,0x7ff5,0x7ff6,0x00f4,0x7ff7,0x7ff8,0x00f5,0x0077,0x00f5,0x00f5, + 0x3fd7,0x7ff9,0x0036,0x7ffa,0x7ffb,0x00f3,0x0076,0x00f3,0x00f3,0x7ffc,0x7ffd,0x0000, + 0x7ffe,0x7fff, +}; + + +static const uint8_t cvh_huffbits6[32] = { + 1, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8, + 6, 9, 8, 10, 4, 6, 7, 8, 6, 9, 8, 11, + 6, 9, 8, 10, 8, 10, 9, 11, +}; + +static const uint16_t cvh_huffcodes6[32] = { + 0x0000,0x0008,0x0009,0x0034,0x000a,0x0035,0x0036,0x00f6,0x000b,0x0037,0x0038,0x00f7, + 0x0039,0x01fa,0x00f8,0x03fc,0x000c,0x003a,0x007a,0x00f9,0x003b,0x01fb,0x00fa,0x07fe, + 0x003c,0x01fc,0x00fb,0x03fd,0x00fc,0x03fe,0x01fd,0x07ff, +}; + +static const uint16_t* const cvh_huffcodes[7] = { + cvh_huffcodes0, cvh_huffcodes1, cvh_huffcodes2, cvh_huffcodes3, + cvh_huffcodes4, cvh_huffcodes5, cvh_huffcodes6, +}; + +static const uint8_t* const cvh_huffbits[7] = { + cvh_huffbits0, cvh_huffbits1, cvh_huffbits2, cvh_huffbits3, + cvh_huffbits4, cvh_huffbits5, cvh_huffbits6, +}; + + +static const uint16_t ccpl_huffcodes2[3] = { + 0x02,0x00,0x03, +}; + +static const uint16_t ccpl_huffcodes3[7] = { + 0x3e,0x1e,0x02,0x00,0x06,0x0e,0x3f, +}; + +static const uint16_t ccpl_huffcodes4[15] = { + 0xfc,0xfd,0x7c,0x3c,0x1c,0x0c,0x04,0x00,0x05,0x0d,0x1d,0x3d, + 0x7d,0xfe,0xff, +}; + +static const uint16_t ccpl_huffcodes5[31] = { + 0x03f8,0x03f9,0x03fa,0x03fb,0x01f8,0x01f9,0x00f8,0x00f9,0x0078,0x0079,0x0038,0x0039, + 0x0018,0x0019,0x0004,0x0000,0x0005,0x001a,0x001b,0x003a,0x003b,0x007a,0x007b,0x00fa, + 0x00fb,0x01fa,0x01fb,0x03fc,0x03fd,0x03fe,0x03ff, +}; + +static const uint16_t ccpl_huffcodes6[63] = { + 0x0004,0x0005,0x0005,0x0006,0x0006,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008, + 0x0008,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b, + 0x000b,0x000b,0x000c,0x000d,0x000e,0x000e,0x0010,0x0000,0x000a,0x0018,0x0019,0x0036, + 0x0037,0x0074,0x0075,0x0076,0x0077,0x00f4,0x00f5,0x00f6,0x00f7,0x01f5,0x01f6,0x01f7, + 0x01f8,0x03f6,0x03f7,0x03f8,0x03f9,0x03fa,0x07fa,0x07fb,0x07fc,0x07fd,0x0ffd,0x1ffd, + 0x3ffd,0x3ffe,0xffff, +}; + +static const uint8_t ccpl_huffbits2[3] = { + 2,1,2, +}; + +static const uint8_t ccpl_huffbits3[7] = { + 6,5,2,1,3,4,6, +}; + +static const uint8_t ccpl_huffbits4[15] = { + 8,8,7,6,5,4,3,1,3,4,5,6,7,8,8, +}; + +static const uint8_t ccpl_huffbits5[31] = { + 10,10,10,10,9,9,8,8,7,7,6,6, + 5,5,3,1,3,5,5,6,6,7,7,8, + 8,9,9,10,10,10,10, +}; + +static const uint8_t ccpl_huffbits6[63] = { + 16,15,14,13,12,11,11,11,11,10,10,10, + 10,9,9,9,9,9,8,8,8,8,7,7, + 7,7,6,6,5,5,3,1,4,5,5,6, + 6,7,7,7,7,8,8,8,8,9,9,9, + 9,10,10,10,10,10,11,11,11,11,12,13, + 14,14,16, +}; + +static const uint16_t* const ccpl_huffcodes[5] = { + ccpl_huffcodes2,ccpl_huffcodes3, + ccpl_huffcodes4,ccpl_huffcodes5,ccpl_huffcodes6 +}; + +static const uint8_t* const ccpl_huffbits[5] = { + ccpl_huffbits2,ccpl_huffbits3, + ccpl_huffbits4,ccpl_huffbits5,ccpl_huffbits6 +}; + + +//Coupling tables + +static const int cplband[51] = { + 0,1,2,3,4,5,6,7,8,9, + 10,11,11,12,12,13,13,14,14,14, + 15,15,15,15,16,16,16,16,16,17, + 17,17,17,17,17,18,18,18,18,18, + 18,18,19,19,19,19,19,19,19,19, + 19, +}; + +// The 1 and 0 at the beginning/end are to prevent overflows with +// bitstream-read indexes. E.g. if n_bits=5, we can access any +// index from [1, (1< + +#include "libavutil/intreadwrite.h" + +static inline void copy_block2(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) +{ + int i; + for(i=0; i + * + * 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 +#include + +#define BITS 16 +#define FLOATFMT "%.18e" +#define FIXEDFMT "%6d" + +static int clip_f15(int v) +{ + return v < -32767 ? -32767 : + v > 32767 ? 32767 : + v; +} + +static void printval(double val, int fixed) +{ + if (fixed) + printf(" "FIXEDFMT",", clip_f15(lrint(val * (double)(1<<15)))); + else + printf(" "FLOATFMT",", val); + +} + +int main(int argc, char *argv[]) +{ + int i, j; + int do_sin = argc > 1 && !strcmp(argv[1], "sin"); + int fixed = argc > 1 && strstr(argv[1], "fixed"); + double (*func)(double) = do_sin ? sin : cos; + + printf("/* This file was automatically generated. */\n"); + printf("#define CONFIG_FFT_FLOAT %d\n", !fixed); + printf("#include \"libavcodec/%s\"\n", do_sin ? "rdft.h" : "fft.h"); + for (i = 4; i <= BITS; i++) { + int m = 1 << i; + double freq = 2*3.14159265358979323846/m; + printf("%s(%i) = {\n ", do_sin ? "SINTABLE" : "COSTABLE", m); + for (j = 0; j < m/2 - 1; j++) { + int idx = j > m/4 ? m/2 - j : j; + if (do_sin && j >= m/4) + idx = m/4 - j; + printval(func(idx*freq), fixed); + if ((j & 3) == 3) + printf("\n "); + } + printval(func(do_sin ? -(m/4 - 1)*freq : freq), fixed); + printf("\n};\n"); + } + return 0; +} diff --git a/ffmpeg/libavcodec/cpia.c b/ffmpeg/libavcodec/cpia.c new file mode 100644 index 0000000..4f83503 --- /dev/null +++ b/ffmpeg/libavcodec/cpia.c @@ -0,0 +1,233 @@ +/* + * CPiA video decoder. + * Copyright (c) 2010 Hans de Goede + * + * This decoder is based on the LGPL code available at + * https://v4l4j.googlecode.com/svn/v4l4j/trunk/libvideo/libv4lconvert/cpia1.c + * + * 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 "avcodec.h" +#include "get_bits.h" +#include "internal.h" + + +#define FRAME_HEADER_SIZE 64 +#define MAGIC_0 0x19 /**< First header byte */ +#define MAGIC_1 0x68 /**< Second header byte */ +#define SUBSAMPLE_420 0 +#define SUBSAMPLE_422 1 +#define YUVORDER_YUYV 0 +#define YUVORDER_UYVY 1 +#define NOT_COMPRESSED 0 +#define COMPRESSED 1 +#define NO_DECIMATION 0 +#define DECIMATION_ENAB 1 +#define EOL 0xfd /**< End Of Line marker */ +#define EOI 0xff /**< End Of Image marker */ + + +typedef struct { + AVFrame *frame; +} CpiaContext; + + +static int cpia_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, AVPacket* avpkt) +{ + CpiaContext* const cpia = avctx->priv_data; + int i,j,ret; + + uint8_t* const header = avpkt->data; + uint8_t* src; + int src_size; + uint16_t linelength; + uint8_t skip; + + AVFrame *frame = cpia->frame; + uint8_t *y, *u, *v, *y_end, *u_end, *v_end; + + // Check header + if ( avpkt->size < FRAME_HEADER_SIZE + || header[0] != MAGIC_0 || header[1] != MAGIC_1 + || (header[17] != SUBSAMPLE_420 && header[17] != SUBSAMPLE_422) + || (header[18] != YUVORDER_YUYV && header[18] != YUVORDER_UYVY) + || (header[28] != NOT_COMPRESSED && header[28] != COMPRESSED) + || (header[29] != NO_DECIMATION && header[29] != DECIMATION_ENAB) + ) { + av_log(avctx, AV_LOG_ERROR, "Invalid header!\n"); + return AVERROR_INVALIDDATA; + } + + // currently unsupported properties + if (header[17] == SUBSAMPLE_422) { + av_log(avctx, AV_LOG_ERROR, "Unsupported subsample!\n"); + return AVERROR_PATCHWELCOME; + } + if (header[18] == YUVORDER_UYVY) { + av_log(avctx, AV_LOG_ERROR, "Unsupported YUV byte order!\n"); + return AVERROR_PATCHWELCOME; + } + if (header[29] == DECIMATION_ENAB) { + av_log(avctx, AV_LOG_ERROR, "Decimation unsupported!\n"); + return AVERROR_PATCHWELCOME; + } + + src = header + FRAME_HEADER_SIZE; + src_size = avpkt->size - FRAME_HEADER_SIZE; + + if (header[28] == NOT_COMPRESSED) { + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + } else { + frame->pict_type = AV_PICTURE_TYPE_P; + frame->key_frame = 0; + } + + // Get buffer filled with previous frame + if ((ret = ff_reget_buffer(avctx, frame)) < 0) + return ret; + + + for ( i = 0; + i < frame->height; + i++, src += linelength, src_size -= linelength + ) { + // Read line length, two byte little endian + linelength = AV_RL16(src); + src += 2; + + if (src_size < linelength) { + av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM); + av_log(avctx, AV_LOG_WARNING, "Frame ended enexpectedly!\n"); + break; + } + if (src[linelength - 1] != EOL) { + av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM); + av_log(avctx, AV_LOG_WARNING, "Wrong line length %d or line not terminated properly (found 0x%02x)!\n", linelength, src[linelength - 1]); + break; + } + + /* Update the data pointers. Y data is on every line. + * U and V data on every second line + */ + y = &frame->data[0][i * frame->linesize[0]]; + u = &frame->data[1][(i >> 1) * frame->linesize[1]]; + v = &frame->data[2][(i >> 1) * frame->linesize[2]]; + y_end = y + frame->linesize[0] - 1; + u_end = u + frame->linesize[1] - 1; + v_end = v + frame->linesize[2] - 1; + + if ((i & 1) && header[17] == SUBSAMPLE_420) { + /* We are on a odd line and 420 subsample is used. + * On this line only Y values are specified, one per pixel. + */ + for (j = 0; j < linelength - 1; j++) { + if (y > y_end) { + av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM); + av_log(avctx, AV_LOG_WARNING, "Decoded data exceeded linesize!\n"); + break; + } + if ((src[j] & 1) && header[28] == COMPRESSED) { + /* It seems that odd lines are always uncompressed, but + * we do it according to specification anyways. + */ + skip = src[j] >> 1; + y += skip; + } else { + *(y++) = src[j]; + } + } + } else if (header[17] == SUBSAMPLE_420) { + /* We are on an even line and 420 subsample is used. + * On this line each pair of pixels is described by four bytes. + */ + for (j = 0; j < linelength - 4; ) { + if (y + 1 > y_end || u > u_end || v > v_end) { + av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM); + av_log(avctx, AV_LOG_WARNING, "Decoded data exceeded linesize!\n"); + break; + } + if ((src[j] & 1) && header[28] == COMPRESSED) { + // Skip amount of pixels and move forward one byte + skip = src[j] >> 1; + y += skip; + u += skip >> 1; + v += skip >> 1; + j++; + } else { + // Set image data as specified and move forward 4 bytes + *(y++) = src[j]; + *(u++) = src[j+1]; + *(y++) = src[j+2]; + *(v++) = src[j+3]; + j += 4; + } + } + } + } + + *got_frame = 1; + if ((ret = av_frame_ref(data, cpia->frame)) < 0) + return ret; + + return avpkt->size; +} + +static av_cold int cpia_decode_init(AVCodecContext *avctx) +{ + CpiaContext *s = avctx->priv_data; + + // output pixel format + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + /* The default timebase set by the v4l2 demuxer leads to probing which is buggy. + * Set some reasonable time_base to skip this. + */ + if (avctx->time_base.num == 1 && avctx->time_base.den == 1000000) { + avctx->time_base.num = 1; + avctx->time_base.den = 60; + } + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int cpia_decode_end(AVCodecContext *avctx) +{ + CpiaContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +AVCodec ff_cpia_decoder = { + .name = "cpia", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CPIA, + .priv_data_size = sizeof(CpiaContext), + .init = cpia_decode_init, + .close = cpia_decode_end, + .decode = cpia_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"), +}; diff --git a/ffmpeg/libavcodec/crystalhd.c b/ffmpeg/libavcodec/crystalhd.c new file mode 100644 index 0000000..5dee825 --- /dev/null +++ b/ffmpeg/libavcodec/crystalhd.c @@ -0,0 +1,1223 @@ +/* + * - CrystalHD decoder module - + * + * Copyright(C) 2010,2011 Philip Langdale + * + * 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 + */ + +/* + * - Principles of Operation - + * + * The CrystalHD decoder operates at the bitstream level - which is an even + * higher level than the decoding hardware you typically see in modern GPUs. + * This means it has a very simple interface, in principle. You feed demuxed + * packets in one end and get decoded picture (fields/frames) out the other. + * + * Of course, nothing is ever that simple. Due, at the very least, to b-frame + * dependencies in the supported formats, the hardware has a delay between + * when a packet goes in, and when a picture comes out. Furthermore, this delay + * is not just a function of time, but also one of the dependency on additional + * frames being fed into the decoder to satisfy the b-frame dependencies. + * + * As such, a pipeline will build up that is roughly equivalent to the required + * DPB for the file being played. If that was all it took, things would still + * be simple - so, of course, it isn't. + * + * The hardware has a way of indicating that a picture is ready to be copied out, + * but this is unreliable - and sometimes the attempt will still fail so, based + * on testing, the code will wait until 3 pictures are ready before starting + * to copy out - and this has the effect of extending the pipeline. + * + * Finally, while it is tempting to say that once the decoder starts outputting + * frames, the software should never fail to return a frame from a decode(), + * this is a hard assertion to make, because the stream may switch between + * differently encoded content (number of b-frames, interlacing, etc) which + * might require a longer pipeline than before. If that happened, you could + * deadlock trying to retrieve a frame that can't be decoded without feeding + * in additional packets. + * + * As such, the code will return in the event that a picture cannot be copied + * out, leading to an increase in the length of the pipeline. This in turn, + * means we have to be sensitive to the time it takes to decode a picture; + * We do not want to give up just because the hardware needed a little more + * time to prepare the picture! For this reason, there are delays included + * in the decode() path that ensure that, under normal conditions, the hardware + * will only fail to return a frame if it really needs additional packets to + * complete the decoding. + * + * Finally, to be explicit, we do not want the pipeline to grow without bound + * for two reasons: 1) The hardware can only buffer a finite number of packets, + * and 2) The client application may not be able to cope with arbitrarily long + * delays in the video path relative to the audio path. For example. MPlayer + * can only handle a 20 picture delay (although this is arbitrary, and needs + * to be extended to fully support the CrystalHD where the delay could be up + * to 32 pictures - consider PAFF H.264 content with 16 b-frames). + */ + +/***************************************************************************** + * Includes + ****************************************************************************/ + +#define _XOPEN_SOURCE 600 +#include +#include +#include +#include + +#include +#include +#include + +#include "avcodec.h" +#include "h264.h" +#include "internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +/** Timeout parameter passed to DtsProcOutput() in us */ +#define OUTPUT_PROC_TIMEOUT 50 +/** Step between fake timestamps passed to hardware in units of 100ns */ +#define TIMESTAMP_UNIT 100000 +/** Initial value in us of the wait in decode() */ +#define BASE_WAIT 10000 +/** Increment in us to adjust wait in decode() */ +#define WAIT_UNIT 1000 + + +/***************************************************************************** + * Module private data + ****************************************************************************/ + +typedef enum { + RET_ERROR = -1, + RET_OK = 0, + RET_COPY_AGAIN = 1, + RET_SKIP_NEXT_COPY = 2, + RET_COPY_NEXT_FIELD = 3, +} CopyRet; + +typedef struct OpaqueList { + struct OpaqueList *next; + uint64_t fake_timestamp; + uint64_t reordered_opaque; + uint8_t pic_type; +} OpaqueList; + +typedef struct { + AVClass *av_class; + AVCodecContext *avctx; + AVFrame *pic; + HANDLE dev; + + uint8_t *orig_extradata; + uint32_t orig_extradata_size; + + AVBitStreamFilterContext *bsfc; + AVCodecParserContext *parser; + + uint8_t is_70012; + uint8_t *sps_pps_buf; + uint32_t sps_pps_size; + uint8_t is_nal; + uint8_t output_ready; + uint8_t need_second_field; + uint8_t skip_next_output; + uint64_t decode_wait; + + uint64_t last_picture; + + OpaqueList *head; + OpaqueList *tail; + + /* Options */ + uint32_t sWidth; + uint8_t bframe_bug; +} CHDContext; + +static const AVOption options[] = { + { "crystalhd_downscale_width", + "Turn on downscaling to the specified width", + offsetof(CHDContext, sWidth), + AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT32_MAX, + AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, }, + { NULL, }, +}; + + +/***************************************************************************** + * Helper functions + ****************************************************************************/ + +static inline BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum AVCodecID id) +{ + switch (id) { + case AV_CODEC_ID_MPEG4: + return BC_MSUBTYPE_DIVX; + case AV_CODEC_ID_MSMPEG4V3: + return BC_MSUBTYPE_DIVX311; + case AV_CODEC_ID_MPEG2VIDEO: + return BC_MSUBTYPE_MPEG2VIDEO; + case AV_CODEC_ID_VC1: + return BC_MSUBTYPE_VC1; + case AV_CODEC_ID_WMV3: + return BC_MSUBTYPE_WMV3; + case AV_CODEC_ID_H264: + return priv->is_nal ? BC_MSUBTYPE_AVC1 : BC_MSUBTYPE_H264; + default: + return BC_MSUBTYPE_INVALID; + } +} + +static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output) +{ + av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffSz: %u\n", output->YbuffSz); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffDoneSz: %u\n", + output->YBuffDoneSz); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tUVBuffDoneSz: %u\n", + output->UVBuffDoneSz); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tTimestamp: %"PRIu64"\n", + output->PicInfo.timeStamp); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tPicture Number: %u\n", + output->PicInfo.picture_number); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tWidth: %u\n", + output->PicInfo.width); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tHeight: %u\n", + output->PicInfo.height); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tChroma: 0x%03x\n", + output->PicInfo.chroma_format); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tPulldown: %u\n", + output->PicInfo.pulldown); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tFlags: 0x%08x\n", + output->PicInfo.flags); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrame Rate/Res: %u\n", + output->PicInfo.frame_rate); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tAspect Ratio: %u\n", + output->PicInfo.aspect_ratio); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tColor Primaries: %u\n", + output->PicInfo.colour_primaries); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tMetaData: %u\n", + output->PicInfo.picture_meta_payload); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tSession Number: %u\n", + output->PicInfo.sess_num); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tycom: %u\n", + output->PicInfo.ycom); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tCustom Aspect: %u\n", + output->PicInfo.custom_aspect_ratio_width_height); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrames to Drop: %u\n", + output->PicInfo.n_drop); + av_log(priv->avctx, AV_LOG_VERBOSE, "\tH264 Valid Fields: 0x%08x\n", + output->PicInfo.other.h264.valid); +} + + +/***************************************************************************** + * OpaqueList functions + ****************************************************************************/ + +static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque, + uint8_t pic_type) +{ + OpaqueList *newNode = av_mallocz(sizeof (OpaqueList)); + if (!newNode) { + av_log(priv->avctx, AV_LOG_ERROR, + "Unable to allocate new node in OpaqueList.\n"); + return 0; + } + if (!priv->head) { + newNode->fake_timestamp = TIMESTAMP_UNIT; + priv->head = newNode; + } else { + newNode->fake_timestamp = priv->tail->fake_timestamp + TIMESTAMP_UNIT; + priv->tail->next = newNode; + } + priv->tail = newNode; + newNode->reordered_opaque = reordered_opaque; + newNode->pic_type = pic_type; + + return newNode->fake_timestamp; +} + +/* + * The OpaqueList is built in decode order, while elements will be removed + * in presentation order. If frames are reordered, this means we must be + * able to remove elements that are not the first element. + * + * Returned node must be freed by caller. + */ +static OpaqueList *opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp) +{ + OpaqueList *node = priv->head; + + if (!priv->head) { + av_log(priv->avctx, AV_LOG_ERROR, + "CrystalHD: Attempted to query non-existent timestamps.\n"); + return NULL; + } + + /* + * The first element is special-cased because we have to manipulate + * the head pointer rather than the previous element in the list. + */ + if (priv->head->fake_timestamp == fake_timestamp) { + priv->head = node->next; + + if (!priv->head->next) + priv->tail = priv->head; + + node->next = NULL; + return node; + } + + /* + * The list is processed at arm's length so that we have the + * previous element available to rewrite its next pointer. + */ + while (node->next) { + OpaqueList *current = node->next; + if (current->fake_timestamp == fake_timestamp) { + node->next = current->next; + + if (!node->next) + priv->tail = node; + + current->next = NULL; + return current; + } else { + node = current; + } + } + + av_log(priv->avctx, AV_LOG_VERBOSE, + "CrystalHD: Couldn't match fake_timestamp.\n"); + return NULL; +} + + +/***************************************************************************** + * Video decoder API function definitions + ****************************************************************************/ + +static void flush(AVCodecContext *avctx) +{ + CHDContext *priv = avctx->priv_data; + + avctx->has_b_frames = 0; + priv->last_picture = -1; + priv->output_ready = 0; + priv->need_second_field = 0; + priv->skip_next_output = 0; + priv->decode_wait = BASE_WAIT; + + av_frame_unref (priv->pic); + + /* Flush mode 4 flushes all software and hardware buffers. */ + DtsFlushInput(priv->dev, 4); +} + + +static av_cold int uninit(AVCodecContext *avctx) +{ + CHDContext *priv = avctx->priv_data; + HANDLE device; + + device = priv->dev; + DtsStopDecoder(device); + DtsCloseDecoder(device); + DtsDeviceClose(device); + + /* + * Restore original extradata, so that if the decoder is + * reinitialised, the bitstream detection and filtering + * will work as expected. + */ + if (priv->orig_extradata) { + av_free(avctx->extradata); + avctx->extradata = priv->orig_extradata; + avctx->extradata_size = priv->orig_extradata_size; + priv->orig_extradata = NULL; + priv->orig_extradata_size = 0; + } + + av_parser_close(priv->parser); + if (priv->bsfc) { + av_bitstream_filter_close(priv->bsfc); + } + + av_free(priv->sps_pps_buf); + + av_frame_free (&priv->pic); + + if (priv->head) { + OpaqueList *node = priv->head; + while (node) { + OpaqueList *next = node->next; + av_free(node); + node = next; + } + } + + return 0; +} + + +static av_cold int init(AVCodecContext *avctx) +{ + CHDContext* priv; + BC_STATUS ret; + BC_INFO_CRYSTAL version; + BC_INPUT_FORMAT format = { + .FGTEnable = FALSE, + .Progressive = TRUE, + .OptFlags = 0x80000000 | vdecFrameRate59_94 | 0x40, + .width = avctx->width, + .height = avctx->height, + }; + + BC_MEDIA_SUBTYPE subtype; + + uint32_t mode = DTS_PLAYBACK_MODE | + DTS_LOAD_FILE_PLAY_FW | + DTS_SKIP_TX_CHK_CPB | + DTS_PLAYBACK_DROP_RPT_MODE | + DTS_SINGLE_THREADED_MODE | + DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976); + + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n", + avctx->codec->name); + + avctx->pix_fmt = AV_PIX_FMT_YUYV422; + + /* Initialize the library */ + priv = avctx->priv_data; + priv->avctx = avctx; + priv->is_nal = avctx->extradata_size > 0 && *(avctx->extradata) == 1; + priv->last_picture = -1; + priv->decode_wait = BASE_WAIT; + priv->pic = av_frame_alloc(); + + subtype = id2subtype(priv, avctx->codec->id); + switch (subtype) { + case BC_MSUBTYPE_AVC1: + { + uint8_t *dummy_p; + int dummy_int; + + /* Back up the extradata so it can be restored at close time. */ + priv->orig_extradata = av_malloc(avctx->extradata_size); + if (!priv->orig_extradata) { + av_log(avctx, AV_LOG_ERROR, + "Failed to allocate copy of extradata\n"); + return AVERROR(ENOMEM); + } + priv->orig_extradata_size = avctx->extradata_size; + memcpy(priv->orig_extradata, avctx->extradata, avctx->extradata_size); + + priv->bsfc = av_bitstream_filter_init("h264_mp4toannexb"); + if (!priv->bsfc) { + av_log(avctx, AV_LOG_ERROR, + "Cannot open the h264_mp4toannexb BSF!\n"); + return AVERROR_BSF_NOT_FOUND; + } + av_bitstream_filter_filter(priv->bsfc, avctx, NULL, &dummy_p, + &dummy_int, NULL, 0, 0); + } + subtype = BC_MSUBTYPE_H264; + // Fall-through + case BC_MSUBTYPE_H264: + format.startCodeSz = 4; + // Fall-through + case BC_MSUBTYPE_VC1: + case BC_MSUBTYPE_WVC1: + case BC_MSUBTYPE_WMV3: + case BC_MSUBTYPE_WMVA: + case BC_MSUBTYPE_MPEG2VIDEO: + case BC_MSUBTYPE_DIVX: + case BC_MSUBTYPE_DIVX311: + format.pMetaData = avctx->extradata; + format.metaDataSz = avctx->extradata_size; + break; + default: + av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n"); + return AVERROR(EINVAL); + } + format.mSubtype = subtype; + + if (priv->sWidth) { + format.bEnableScaling = 1; + format.ScalingParams.sWidth = priv->sWidth; + } + + /* Get a decoder instance */ + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n"); + // Initialize the Link and Decoder devices + ret = DtsDeviceOpen(&priv->dev, mode); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n"); + goto fail; + } + + ret = DtsCrystalHDVersion(priv->dev, &version); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_VERBOSE, + "CrystalHD: DtsCrystalHDVersion failed\n"); + goto fail; + } + priv->is_70012 = version.device == 0; + + if (priv->is_70012 && + (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) { + av_log(avctx, AV_LOG_VERBOSE, + "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n"); + goto fail; + } + + ret = DtsSetInputFormat(priv->dev, &format); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n"); + goto fail; + } + + ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n"); + goto fail; + } + + ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n"); + goto fail; + } + ret = DtsStartDecoder(priv->dev); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n"); + goto fail; + } + ret = DtsStartCapture(priv->dev); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n"); + goto fail; + } + + if (avctx->codec->id == AV_CODEC_ID_H264) { + priv->parser = av_parser_init(avctx->codec->id); + if (!priv->parser) + av_log(avctx, AV_LOG_WARNING, + "Cannot open the h.264 parser! Interlaced h.264 content " + "will not be detected reliably.\n"); + priv->parser->flags = PARSER_FLAG_COMPLETE_FRAMES; + } + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n"); + + return 0; + + fail: + uninit(avctx); + return -1; +} + + +static inline CopyRet copy_frame(AVCodecContext *avctx, + BC_DTS_PROC_OUT *output, + void *data, int *got_frame) +{ + BC_STATUS ret; + BC_DTS_STATUS decoder_status = { 0, }; + uint8_t trust_interlaced; + uint8_t interlaced; + + CHDContext *priv = avctx->priv_data; + int64_t pkt_pts = AV_NOPTS_VALUE; + uint8_t pic_type = 0; + + uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) == + VDEC_FLAG_BOTTOMFIELD; + uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST); + + int width = output->PicInfo.width; + int height = output->PicInfo.height; + int bwidth; + uint8_t *src = output->Ybuff; + int sStride; + uint8_t *dst; + int dStride; + + if (output->PicInfo.timeStamp != 0) { + OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp); + if (node) { + pkt_pts = node->reordered_opaque; + pic_type = node->pic_type; + av_free(node); + } else { + /* + * We will encounter a situation where a timestamp cannot be + * popped if a second field is being returned. In this case, + * each field has the same timestamp and the first one will + * cause it to be popped. To keep subsequent calculations + * simple, pic_type should be set a FIELD value - doesn't + * matter which, but I chose BOTTOM. + */ + pic_type = PICT_BOTTOM_FIELD; + } + av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n", + output->PicInfo.timeStamp); + av_log(avctx, AV_LOG_VERBOSE, "output picture type %d\n", + pic_type); + } + + ret = DtsGetDriverStatus(priv->dev, &decoder_status); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, + "CrystalHD: GetDriverStatus failed: %u\n", ret); + return RET_ERROR; + } + + /* + * For most content, we can trust the interlaced flag returned + * by the hardware, but sometimes we can't. These are the + * conditions under which we can trust the flag: + * + * 1) It's not h.264 content + * 2) The UNKNOWN_SRC flag is not set + * 3) We know we're expecting a second field + * 4) The hardware reports this picture and the next picture + * have the same picture number. + * + * Note that there can still be interlaced content that will + * fail this check, if the hardware hasn't decoded the next + * picture or if there is a corruption in the stream. (In either + * case a 0 will be returned for the next picture number) + */ + trust_interlaced = avctx->codec->id != AV_CODEC_ID_H264 || + !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) || + priv->need_second_field || + (decoder_status.picNumFlags & ~0x40000000) == + output->PicInfo.picture_number; + + /* + * If we got a false negative for trust_interlaced on the first field, + * we will realise our mistake here when we see that the picture number is that + * of the previous picture. We cannot recover the frame and should discard the + * second field to keep the correct number of output frames. + */ + if (output->PicInfo.picture_number == priv->last_picture && !priv->need_second_field) { + av_log(avctx, AV_LOG_WARNING, + "Incorrectly guessed progressive frame. Discarding second field\n"); + /* Returning without providing a picture. */ + return RET_OK; + } + + interlaced = (output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) && + trust_interlaced; + + if (!trust_interlaced && (decoder_status.picNumFlags & ~0x40000000) == 0) { + av_log(avctx, AV_LOG_VERBOSE, + "Next picture number unknown. Assuming progressive frame.\n"); + } + + av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d | trust_interlaced %d\n", + interlaced, trust_interlaced); + + if (priv->pic->data[0] && !priv->need_second_field) + av_frame_unref(priv->pic); + + priv->need_second_field = interlaced && !priv->need_second_field; + + if (!priv->pic->data[0]) { + if (ff_get_buffer(avctx, priv->pic, AV_GET_BUFFER_FLAG_REF) < 0) + return RET_ERROR; + } + + bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0); + if (priv->is_70012) { + int pStride; + + if (width <= 720) + pStride = 720; + else if (width <= 1280) + pStride = 1280; + else pStride = 1920; + sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0); + } else { + sStride = bwidth; + } + + dStride = priv->pic->linesize[0]; + dst = priv->pic->data[0]; + + av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n"); + + if (interlaced) { + int dY = 0; + int sY = 0; + + height /= 2; + if (bottom_field) { + av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n"); + dY = 1; + } else { + av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n"); + dY = 0; + } + + for (sY = 0; sY < height; dY++, sY++) { + memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth); + dY++; + } + } else { + av_image_copy_plane(dst, dStride, src, sStride, bwidth, height); + } + + priv->pic->interlaced_frame = interlaced; + if (interlaced) + priv->pic->top_field_first = !bottom_first; + + priv->pic->pkt_pts = pkt_pts; + + if (!priv->need_second_field) { + *got_frame = 1; + if ((ret = av_frame_ref(data, priv->pic)) < 0) { + return ret; + } + } + + /* + * Two types of PAFF content have been observed. One form causes the + * hardware to return a field pair and the other individual fields, + * even though the input is always individual fields. We must skip + * copying on the next decode() call to maintain pipeline length in + * the first case. + */ + if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) && + (pic_type == PICT_TOP_FIELD || pic_type == PICT_BOTTOM_FIELD)) { + av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n"); + return RET_SKIP_NEXT_COPY; + } + + /* + * The logic here is purely based on empirical testing with samples. + * If we need a second field, it could come from a second input packet, + * or it could come from the same field-pair input packet at the current + * field. In the first case, we should return and wait for the next time + * round to get the second field, while in the second case, we should + * ask the decoder for it immediately. + * + * Testing has shown that we are dealing with the fieldpair -> two fields + * case if the VDEC_FLAG_UNKNOWN_SRC is not set or if the input picture + * type was PICT_FRAME (in this second case, the flag might still be set) + */ + return priv->need_second_field && + (!(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) || + pic_type == PICT_FRAME) ? + RET_COPY_NEXT_FIELD : RET_OK; +} + + +static inline CopyRet receive_frame(AVCodecContext *avctx, + void *data, int *got_frame) +{ + BC_STATUS ret; + BC_DTS_PROC_OUT output = { + .PicInfo.width = avctx->width, + .PicInfo.height = avctx->height, + }; + CHDContext *priv = avctx->priv_data; + HANDLE dev = priv->dev; + + *got_frame = 0; + + // Request decoded data from the driver + ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output); + if (ret == BC_STS_FMT_CHANGE) { + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n"); + avctx->width = output.PicInfo.width; + avctx->height = output.PicInfo.height; + switch ( output.PicInfo.aspect_ratio ) { + case vdecAspectRatioSquare: + avctx->sample_aspect_ratio = (AVRational) { 1, 1}; + break; + case vdecAspectRatio12_11: + avctx->sample_aspect_ratio = (AVRational) { 12, 11}; + break; + case vdecAspectRatio10_11: + avctx->sample_aspect_ratio = (AVRational) { 10, 11}; + break; + case vdecAspectRatio16_11: + avctx->sample_aspect_ratio = (AVRational) { 16, 11}; + break; + case vdecAspectRatio40_33: + avctx->sample_aspect_ratio = (AVRational) { 40, 33}; + break; + case vdecAspectRatio24_11: + avctx->sample_aspect_ratio = (AVRational) { 24, 11}; + break; + case vdecAspectRatio20_11: + avctx->sample_aspect_ratio = (AVRational) { 20, 11}; + break; + case vdecAspectRatio32_11: + avctx->sample_aspect_ratio = (AVRational) { 32, 11}; + break; + case vdecAspectRatio80_33: + avctx->sample_aspect_ratio = (AVRational) { 80, 33}; + break; + case vdecAspectRatio18_11: + avctx->sample_aspect_ratio = (AVRational) { 18, 11}; + break; + case vdecAspectRatio15_11: + avctx->sample_aspect_ratio = (AVRational) { 15, 11}; + break; + case vdecAspectRatio64_33: + avctx->sample_aspect_ratio = (AVRational) { 64, 33}; + break; + case vdecAspectRatio160_99: + avctx->sample_aspect_ratio = (AVRational) {160, 99}; + break; + case vdecAspectRatio4_3: + avctx->sample_aspect_ratio = (AVRational) { 4, 3}; + break; + case vdecAspectRatio16_9: + avctx->sample_aspect_ratio = (AVRational) { 16, 9}; + break; + case vdecAspectRatio221_1: + avctx->sample_aspect_ratio = (AVRational) {221, 1}; + break; + } + return RET_COPY_AGAIN; + } else if (ret == BC_STS_SUCCESS) { + int copy_ret = -1; + if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) { + if (priv->last_picture == -1) { + /* + * Init to one less, so that the incrementing code doesn't + * need to be special-cased. + */ + priv->last_picture = output.PicInfo.picture_number - 1; + } + + if (avctx->codec->id == AV_CODEC_ID_MPEG4 && + output.PicInfo.timeStamp == 0 && priv->bframe_bug) { + av_log(avctx, AV_LOG_VERBOSE, + "CrystalHD: Not returning packed frame twice.\n"); + priv->last_picture++; + DtsReleaseOutputBuffs(dev, NULL, FALSE); + return RET_COPY_AGAIN; + } + + print_frame_info(priv, &output); + + if (priv->last_picture + 1 < output.PicInfo.picture_number) { + av_log(avctx, AV_LOG_WARNING, + "CrystalHD: Picture Number discontinuity\n"); + /* + * Have we lost frames? If so, we need to shrink the + * pipeline length appropriately. + * + * XXX: I have no idea what the semantics of this situation + * are so I don't even know if we've lost frames or which + * ones. + * + * In any case, only warn the first time. + */ + priv->last_picture = output.PicInfo.picture_number - 1; + } + + copy_ret = copy_frame(avctx, &output, data, got_frame); + if (*got_frame > 0) { + avctx->has_b_frames--; + priv->last_picture++; + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n", + avctx->has_b_frames); + } + } else { + /* + * An invalid frame has been consumed. + */ + av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with " + "invalid PIB\n"); + avctx->has_b_frames--; + copy_ret = RET_OK; + } + DtsReleaseOutputBuffs(dev, NULL, FALSE); + + return copy_ret; + } else if (ret == BC_STS_BUSY) { + return RET_COPY_AGAIN; + } else { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret); + return RET_ERROR; + } +} + + +static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + BC_STATUS ret; + BC_DTS_STATUS decoder_status = { 0, }; + CopyRet rec_ret; + CHDContext *priv = avctx->priv_data; + HANDLE dev = priv->dev; + uint8_t *in_data = avpkt->data; + int len = avpkt->size; + int free_data = 0; + uint8_t pic_type = 0; + + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n"); + + if (avpkt->size == 7 && !priv->bframe_bug) { + /* + * The use of a drop frame triggers the bug + */ + av_log(avctx, AV_LOG_INFO, + "CrystalHD: Enabling work-around for packed b-frame bug\n"); + priv->bframe_bug = 1; + } else if (avpkt->size == 8 && priv->bframe_bug) { + /* + * Delay frames don't trigger the bug + */ + av_log(avctx, AV_LOG_INFO, + "CrystalHD: Disabling work-around for packed b-frame bug\n"); + priv->bframe_bug = 0; + } + + if (len) { + int32_t tx_free = (int32_t)DtsTxFreeSize(dev); + + if (priv->parser) { + int ret = 0; + + if (priv->bsfc) { + ret = av_bitstream_filter_filter(priv->bsfc, avctx, NULL, + &in_data, &len, + avpkt->data, len, 0); + } + free_data = ret > 0; + + if (ret >= 0) { + uint8_t *pout; + int psize; + int index; + H264Context *h = priv->parser->priv_data; + + index = av_parser_parse2(priv->parser, avctx, &pout, &psize, + in_data, len, avctx->pkt->pts, + avctx->pkt->dts, 0); + if (index < 0) { + av_log(avctx, AV_LOG_WARNING, + "CrystalHD: Failed to parse h.264 packet to " + "detect interlacing.\n"); + } else if (index != len) { + av_log(avctx, AV_LOG_WARNING, + "CrystalHD: Failed to parse h.264 packet " + "completely. Interlaced frames may be " + "incorrectly detected.\n"); + } else { + av_log(avctx, AV_LOG_VERBOSE, + "CrystalHD: parser picture type %d\n", + h->picture_structure); + pic_type = h->picture_structure; + } + } else { + av_log(avctx, AV_LOG_WARNING, + "CrystalHD: mp4toannexb filter failed to filter " + "packet. Interlaced frames may be incorrectly " + "detected.\n"); + } + } + + if (len < tx_free - 1024) { + /* + * Despite being notionally opaque, either libcrystalhd or + * the hardware itself will mangle pts values that are too + * small or too large. The docs claim it should be in units + * of 100ns. Given that we're nominally dealing with a black + * box on both sides, any transform we do has no guarantee of + * avoiding mangling so we need to build a mapping to values + * we know will not be mangled. + */ + uint64_t pts = opaque_list_push(priv, avctx->pkt->pts, pic_type); + if (!pts) { + if (free_data) { + av_freep(&in_data); + } + return AVERROR(ENOMEM); + } + av_log(priv->avctx, AV_LOG_VERBOSE, + "input \"pts\": %"PRIu64"\n", pts); + ret = DtsProcInput(dev, in_data, len, pts, 0); + if (free_data) { + av_freep(&in_data); + } + if (ret == BC_STS_BUSY) { + av_log(avctx, AV_LOG_WARNING, + "CrystalHD: ProcInput returned busy\n"); + usleep(BASE_WAIT); + return AVERROR(EBUSY); + } else if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, + "CrystalHD: ProcInput failed: %u\n", ret); + return -1; + } + avctx->has_b_frames++; + } else { + av_log(avctx, AV_LOG_WARNING, "CrystalHD: Input buffer full\n"); + len = 0; // We didn't consume any bytes. + } + } else { + av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n"); + } + + if (priv->skip_next_output) { + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Skipping next output.\n"); + priv->skip_next_output = 0; + avctx->has_b_frames--; + return len; + } + + ret = DtsGetDriverStatus(dev, &decoder_status); + if (ret != BC_STS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n"); + return -1; + } + + /* + * No frames ready. Don't try to extract. + * + * Empirical testing shows that ReadyListCount can be a damn lie, + * and ProcOut still fails when count > 0. The same testing showed + * that two more iterations were needed before ProcOutput would + * succeed. + */ + if (priv->output_ready < 2) { + if (decoder_status.ReadyListCount != 0) + priv->output_ready++; + usleep(BASE_WAIT); + av_log(avctx, AV_LOG_INFO, "CrystalHD: Filling pipeline.\n"); + return len; + } else if (decoder_status.ReadyListCount == 0) { + /* + * After the pipeline is established, if we encounter a lack of frames + * that probably means we're not giving the hardware enough time to + * decode them, so start increasing the wait time at the end of a + * decode call. + */ + usleep(BASE_WAIT); + priv->decode_wait += WAIT_UNIT; + av_log(avctx, AV_LOG_INFO, "CrystalHD: No frames ready. Returning\n"); + return len; + } + + do { + rec_ret = receive_frame(avctx, data, got_frame); + if (rec_ret == RET_OK && *got_frame == 0) { + /* + * This case is for when the encoded fields are stored + * separately and we get a separate avpkt for each one. To keep + * the pipeline stable, we should return nothing and wait for + * the next time round to grab the second field. + * H.264 PAFF is an example of this. + */ + av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n"); + avctx->has_b_frames--; + } else if (rec_ret == RET_COPY_NEXT_FIELD) { + /* + * This case is for when the encoded fields are stored in a + * single avpkt but the hardware returns then separately. Unless + * we grab the second field before returning, we'll slip another + * frame in the pipeline and if that happens a lot, we're sunk. + * So we have to get that second field now. + * Interlaced mpeg2 and vc1 are examples of this. + */ + av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n"); + while (1) { + usleep(priv->decode_wait); + ret = DtsGetDriverStatus(dev, &decoder_status); + if (ret == BC_STS_SUCCESS && + decoder_status.ReadyListCount > 0) { + rec_ret = receive_frame(avctx, data, got_frame); + if ((rec_ret == RET_OK && *got_frame > 0) || + rec_ret == RET_ERROR) + break; + } + } + av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n"); + } else if (rec_ret == RET_SKIP_NEXT_COPY) { + /* + * Two input packets got turned into a field pair. Gawd. + */ + av_log(avctx, AV_LOG_VERBOSE, + "Don't output on next decode call.\n"); + priv->skip_next_output = 1; + } + /* + * If rec_ret == RET_COPY_AGAIN, that means that either we just handled + * a FMT_CHANGE event and need to go around again for the actual frame, + * we got a busy status and need to try again, or we're dealing with + * packed b-frames, where the hardware strangely returns the packed + * p-frame twice. We choose to keep the second copy as it carries the + * valid pts. + */ + } while (rec_ret == RET_COPY_AGAIN); + usleep(priv->decode_wait); + return len; +} + + +#if CONFIG_H264_CRYSTALHD_DECODER +static AVClass h264_class = { + "h264_crystalhd", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h264_crystalhd_decoder = { + .name = "h264_crystalhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(CHDContext), + .init = init, + .close = uninit, + .decode = decode, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, + .priv_class = &h264_class, +}; +#endif + +#if CONFIG_MPEG2_CRYSTALHD_DECODER +static AVClass mpeg2_class = { + "mpeg2_crystalhd", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mpeg2_crystalhd_decoder = { + .name = "mpeg2_crystalhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(CHDContext), + .init = init, + .close = uninit, + .decode = decode, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 Video (CrystalHD acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, + .priv_class = &mpeg2_class, +}; +#endif + +#if CONFIG_MPEG4_CRYSTALHD_DECODER +static AVClass mpeg4_class = { + "mpeg4_crystalhd", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mpeg4_crystalhd_decoder = { + .name = "mpeg4_crystalhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .priv_data_size = sizeof(CHDContext), + .init = init, + .close = uninit, + .decode = decode, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 (CrystalHD acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, + .priv_class = &mpeg4_class, +}; +#endif + +#if CONFIG_MSMPEG4_CRYSTALHD_DECODER +static AVClass msmpeg4_class = { + "msmpeg4_crystalhd", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_msmpeg4_crystalhd_decoder = { + .name = "msmpeg4_crystalhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSMPEG4V3, + .priv_data_size = sizeof(CHDContext), + .init = init, + .close = uninit, + .decode = decode, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, + .priv_class = &msmpeg4_class, +}; +#endif + +#if CONFIG_VC1_CRYSTALHD_DECODER +static AVClass vc1_class = { + "vc1_crystalhd", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_vc1_crystalhd_decoder = { + .name = "vc1_crystalhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .priv_data_size = sizeof(CHDContext), + .init = init, + .close = uninit, + .decode = decode, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1 (CrystalHD acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, + .priv_class = &vc1_class, +}; +#endif + +#if CONFIG_WMV3_CRYSTALHD_DECODER +static AVClass wmv3_class = { + "wmv3_crystalhd", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_wmv3_crystalhd_decoder = { + .name = "wmv3_crystalhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .priv_data_size = sizeof(CHDContext), + .init = init, + .close = uninit, + .decode = decode, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 (CrystalHD acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, + .priv_class = &wmv3_class, +}; +#endif diff --git a/ffmpeg/libavcodec/cscd.c b/ffmpeg/libavcodec/cscd.c new file mode 100644 index 0000000..0a5fa69 --- /dev/null +++ b/ffmpeg/libavcodec/cscd.c @@ -0,0 +1,170 @@ +/* + * CamStudio decoder + * Copyright (c) 2006 Reimar Doeffinger + * + * 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 + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/common.h" + +#if CONFIG_ZLIB +#include +#endif +#include "libavutil/lzo.h" + +typedef struct { + AVFrame *pic; + int linelen, height, bpp; + unsigned int decomp_size; + unsigned char* decomp_buf; +} CamStudioContext; + +static void copy_frame_default(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, src_stride = FFALIGN(linelen, 4); + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + memcpy(dst, src, linelen); + src += src_stride; + dst -= f->linesize[0]; + } +} + +static void add_frame_default(AVFrame *f, const uint8_t *src, + int linelen, int height) { + int i, j, src_stride = FFALIGN(linelen, 4); + uint8_t *dst = f->data[0]; + dst += (height - 1) * f->linesize[0]; + for (i = height; i; i--) { + for (j = linelen; j; j--) + *dst++ += *src++; + src += src_stride - linelen; + dst -= f->linesize[0] + linelen; + } +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + CamStudioContext *c = avctx->priv_data; + int ret; + + if (buf_size < 2) { + av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + return ret; + + // decompress data + switch ((buf[0] >> 1) & 7) { + case 0: { // lzo compression + int outlen = c->decomp_size, inlen = buf_size - 2; + if (av_lzo1x_decode(c->decomp_buf, &outlen, &buf[2], &inlen)) + av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); + break; + } + case 1: { // zlib compression +#if CONFIG_ZLIB + unsigned long dlen = c->decomp_size; + if (uncompress(c->decomp_buf, &dlen, &buf[2], buf_size - 2) != Z_OK) + av_log(avctx, AV_LOG_ERROR, "error during zlib decompression\n"); + break; +#else + av_log(avctx, AV_LOG_ERROR, "compiled without zlib support\n"); + return AVERROR(ENOSYS); +#endif + } + default: + av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); + return AVERROR_INVALIDDATA; + } + + // flip upside down, add difference frame + if (buf[0] & 1) { // keyframe + c->pic->pict_type = AV_PICTURE_TYPE_I; + c->pic->key_frame = 1; + copy_frame_default(c->pic, c->decomp_buf, + c->linelen, c->height); + } else { + c->pic->pict_type = AV_PICTURE_TYPE_P; + c->pic->key_frame = 0; + add_frame_default(c->pic, c->decomp_buf, + c->linelen, c->height); + } + + *got_frame = 1; + if ((ret = av_frame_ref(data, c->pic)) < 0) + return ret; + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) { + CamStudioContext *c = avctx->priv_data; + int stride; + switch (avctx->bits_per_coded_sample) { + case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555LE; break; + case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break; + case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break; + default: + av_log(avctx, AV_LOG_ERROR, + "CamStudio codec error: invalid depth %i bpp\n", + avctx->bits_per_coded_sample); + return AVERROR_INVALIDDATA; + } + c->bpp = avctx->bits_per_coded_sample; + c->linelen = avctx->width * avctx->bits_per_coded_sample / 8; + c->height = avctx->height; + stride = FFALIGN(c->linelen, 4); + c->decomp_size = c->height * stride; + c->decomp_buf = av_malloc(c->decomp_size + AV_LZO_OUTPUT_PADDING); + if (!c->decomp_buf) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + c->pic = av_frame_alloc(); + if (!c->pic) + return AVERROR(ENOMEM); + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) { + CamStudioContext *c = avctx->priv_data; + av_freep(&c->decomp_buf); + av_frame_free(&c->pic); + return 0; +} + +AVCodec ff_cscd_decoder = { + .name = "camstudio", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CSCD, + .priv_data_size = sizeof(CamStudioContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("CamStudio"), +}; diff --git a/ffmpeg/libavcodec/cyuv.c b/ffmpeg/libavcodec/cyuv.c new file mode 100644 index 0000000..3a30138 --- /dev/null +++ b/ffmpeg/libavcodec/cyuv.c @@ -0,0 +1,202 @@ +/* + * Creative YUV (CYUV) Video Decoder + * by Mike Melanson (melanson@pcisys.net) + * based on "Creative YUV (CYUV) stream format for AVI": + * http://www.csse.monash.edu.au/~timf/videocodec/cyuv.txt + * + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Creative YUV (CYUV) Video Decoder. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/internal.h" + + +typedef struct CyuvDecodeContext { + AVCodecContext *avctx; + int width, height; +} CyuvDecodeContext; + +static av_cold int cyuv_decode_init(AVCodecContext *avctx) +{ + CyuvDecodeContext *s = avctx->priv_data; + + s->avctx = avctx; + s->width = avctx->width; + /* width needs to be divisible by 4 for this codec to work */ + if (s->width & 0x3) + return AVERROR_INVALIDDATA; + s->height = avctx->height; + + return 0; +} + +static int cyuv_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + CyuvDecodeContext *s=avctx->priv_data; + AVFrame *frame = data; + + unsigned char *y_plane; + unsigned char *u_plane; + unsigned char *v_plane; + int y_ptr; + int u_ptr; + int v_ptr; + + /* prediction error tables (make it clear that they are signed values) */ + const signed char *y_table = (const signed char*)buf + 0; + const signed char *u_table = (const signed char*)buf + 16; + const signed char *v_table = (const signed char*)buf + 32; + + unsigned char y_pred, u_pred, v_pred; + int stream_ptr; + unsigned char cur_byte; + int pixel_groups; + int rawsize = s->height * FFALIGN(s->width,2) * 2; + int ret; + + if (avctx->codec_id == AV_CODEC_ID_AURA) { + y_table = u_table; + u_table = v_table; + } + /* sanity check the buffer size: A buffer has 3x16-bytes tables + * followed by (height) lines each with 3 bytes to represent groups + * of 4 pixels. Thus, the total size of the buffer ought to be: + * (3 * 16) + height * (width * 3 / 4) */ + if (buf_size == 48 + s->height * (s->width * 3 / 4)) { + avctx->pix_fmt = AV_PIX_FMT_YUV411P; + } else if(buf_size == rawsize ) { + avctx->pix_fmt = AV_PIX_FMT_UYVY422; + } else { + av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n", + buf_size, 48 + s->height * (s->width * 3 / 4)); + return AVERROR_INVALIDDATA; + } + + /* pixel data starts 48 bytes in, after 3x16-byte tables */ + stream_ptr = 48; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + y_plane = frame->data[0]; + u_plane = frame->data[1]; + v_plane = frame->data[2]; + + if (buf_size == rawsize) { + int linesize = FFALIGN(s->width,2) * 2; + y_plane += frame->linesize[0] * s->height; + for (stream_ptr = 0; stream_ptr < rawsize; stream_ptr += linesize) { + y_plane -= frame->linesize[0]; + memcpy(y_plane, buf+stream_ptr, linesize); + } + } else { + + /* iterate through each line in the height */ + for (y_ptr = 0, u_ptr = 0, v_ptr = 0; + y_ptr < (s->height * frame->linesize[0]); + y_ptr += frame->linesize[0] - s->width, + u_ptr += frame->linesize[1] - s->width / 4, + v_ptr += frame->linesize[2] - s->width / 4) { + + /* reset predictors */ + cur_byte = buf[stream_ptr++]; + u_plane[u_ptr++] = u_pred = cur_byte & 0xF0; + y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4; + + cur_byte = buf[stream_ptr++]; + v_plane[v_ptr++] = v_pred = cur_byte & 0xF0; + y_pred += y_table[cur_byte & 0x0F]; + y_plane[y_ptr++] = y_pred; + + cur_byte = buf[stream_ptr++]; + y_pred += y_table[cur_byte & 0x0F]; + y_plane[y_ptr++] = y_pred; + y_pred += y_table[(cur_byte & 0xF0) >> 4]; + y_plane[y_ptr++] = y_pred; + + /* iterate through the remaining pixel groups (4 pixels/group) */ + pixel_groups = s->width / 4 - 1; + while (pixel_groups--) { + + cur_byte = buf[stream_ptr++]; + u_pred += u_table[(cur_byte & 0xF0) >> 4]; + u_plane[u_ptr++] = u_pred; + y_pred += y_table[cur_byte & 0x0F]; + y_plane[y_ptr++] = y_pred; + + cur_byte = buf[stream_ptr++]; + v_pred += v_table[(cur_byte & 0xF0) >> 4]; + v_plane[v_ptr++] = v_pred; + y_pred += y_table[cur_byte & 0x0F]; + y_plane[y_ptr++] = y_pred; + + cur_byte = buf[stream_ptr++]; + y_pred += y_table[cur_byte & 0x0F]; + y_plane[y_ptr++] = y_pred; + y_pred += y_table[(cur_byte & 0xF0) >> 4]; + y_plane[y_ptr++] = y_pred; + + } + } + } + + *got_frame = 1; + + return buf_size; +} + +#if CONFIG_AURA_DECODER +AVCodec ff_aura_decoder = { + .name = "aura", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AURA, + .priv_data_size = sizeof(CyuvDecodeContext), + .init = cyuv_decode_init, + .decode = cyuv_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"), +}; +#endif + +#if CONFIG_CYUV_DECODER +AVCodec ff_cyuv_decoder = { + .name = "cyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CYUV, + .priv_data_size = sizeof(CyuvDecodeContext), + .init = cyuv_decode_init, + .decode = cyuv_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"), +}; +#endif diff --git a/ffmpeg/libavcodec/dca.c b/ffmpeg/libavcodec/dca.c new file mode 100644 index 0000000..bbe1f10 --- /dev/null +++ b/ffmpeg/libavcodec/dca.c @@ -0,0 +1,33 @@ +/* + * DCA compatible decoder data + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 "dca.h" + +const uint32_t avpriv_dca_sample_rates[16] = +{ + 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, + 12000, 24000, 48000, 96000, 192000 +}; diff --git a/ffmpeg/libavcodec/dca.h b/ffmpeg/libavcodec/dca.h new file mode 100644 index 0000000..3da93aa --- /dev/null +++ b/ffmpeg/libavcodec/dca.h @@ -0,0 +1,42 @@ +/* + * DCA compatible decoder + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_DCA_H +#define AVCODEC_DCA_H + +#include +#include "libavutil/internal.h" + +/** DCA syncwords, also used for bitstream type detection */ +#define DCA_MARKER_RAW_BE 0x7FFE8001 +#define DCA_MARKER_RAW_LE 0xFE7F0180 +#define DCA_MARKER_14B_BE 0x1FFFE800 +#define DCA_MARKER_14B_LE 0xFF1F00E8 + +/** DCA-HD specific block starts with this marker. */ +#define DCA_HD_MARKER 0x64582025 + +extern av_export const uint32_t avpriv_dca_sample_rates[16]; + +#endif /* AVCODEC_DCA_H */ diff --git a/ffmpeg/libavcodec/dca_parser.c b/ffmpeg/libavcodec/dca_parser.c new file mode 100644 index 0000000..266520f --- /dev/null +++ b/ffmpeg/libavcodec/dca_parser.c @@ -0,0 +1,208 @@ +/* + * DCA parser + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 "parser.h" +#include "dca.h" +#include "dca_parser.h" +#include "get_bits.h" +#include "put_bits.h" + +typedef struct DCAParseContext { + ParseContext pc; + uint32_t lastmarker; + int size; + int framesize; + int hd_pos; +} DCAParseContext; + +#define IS_MARKER(state, i, buf, buf_size) \ + ((state == DCA_MARKER_14B_LE && (i < buf_size-2) && (buf[i+1] & 0xF0) == 0xF0 && buf[i+2] == 0x07) \ + || (state == DCA_MARKER_14B_BE && (i < buf_size-2) && buf[i+1] == 0x07 && (buf[i+2] & 0xF0) == 0xF0) \ + || state == DCA_MARKER_RAW_LE || state == DCA_MARKER_RAW_BE || state == DCA_HD_MARKER) + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int dca_find_frame_end(DCAParseContext * pc1, const uint8_t * buf, + int buf_size) +{ + int start_found, i; + uint32_t state; + ParseContext *pc = &pc1->pc; + + start_found = pc->frame_start_found; + state = pc->state; + + i = 0; + if (!start_found) { + for (i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (IS_MARKER(state, i, buf, buf_size)) { + if (!pc1->lastmarker || state == pc1->lastmarker || pc1->lastmarker == DCA_HD_MARKER) { + start_found = 1; + pc1->lastmarker = state; + break; + } + } + } + } + if (start_found) { + for (; i < buf_size; i++) { + pc1->size++; + state = (state << 8) | buf[i]; + if (state == DCA_HD_MARKER && !pc1->hd_pos) + pc1->hd_pos = pc1->size; + if (IS_MARKER(state, i, buf, buf_size) && (state == pc1->lastmarker || pc1->lastmarker == DCA_HD_MARKER)) { + if(pc1->framesize > pc1->size) + continue; + // We have to check that we really read a full frame here, and that it isn't a pure HD frame, because their size is not constant. + if(!pc1->framesize && state == pc1->lastmarker && state != DCA_HD_MARKER){ + pc1->framesize = pc1->hd_pos ? pc1->hd_pos : pc1->size; + } + pc->frame_start_found = 0; + pc->state = -1; + pc1->size = 0; + return i - 3; + } + } + } + pc->frame_start_found = start_found; + pc->state = state; + return END_NOT_FOUND; +} + +static av_cold int dca_parse_init(AVCodecParserContext * s) +{ + DCAParseContext *pc1 = s->priv_data; + + pc1->lastmarker = 0; + return 0; +} + +int ff_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, + int max_size) +{ + uint32_t mrk; + int i, tmp; + const uint16_t *ssrc = (const uint16_t *) src; + uint16_t *sdst = (uint16_t *) dst; + PutBitContext pb; + + if ((unsigned) src_size > (unsigned) max_size) + src_size = max_size; + + mrk = AV_RB32(src); + switch (mrk) { + case DCA_MARKER_RAW_BE: + memcpy(dst, src, src_size); + return src_size; + case DCA_MARKER_RAW_LE: + for (i = 0; i < (src_size + 1) >> 1; i++) + *sdst++ = av_bswap16(*ssrc++); + return src_size; + case DCA_MARKER_14B_BE: + case DCA_MARKER_14B_LE: + init_put_bits(&pb, dst, max_size); + for (i = 0; i < (src_size + 1) >> 1; i++, src += 2) { + tmp = ((mrk == DCA_MARKER_14B_BE) ? AV_RB16(src) : AV_RL16(src)) & 0x3FFF; + put_bits(&pb, 14, tmp); + } + flush_put_bits(&pb); + return (put_bits_count(&pb) + 7) >> 3; + default: + return AVERROR_INVALIDDATA; + } +} + +static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, + int *sample_rate) +{ + GetBitContext gb; + uint8_t hdr[12 + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 }; + int ret, sample_blocks, sr_code; + + if (buf_size < 12) + return AVERROR_INVALIDDATA; + + if ((ret = ff_dca_convert_bitstream(buf, 12, hdr, 12)) < 0) + return ret; + + init_get_bits(&gb, hdr, 96); + + skip_bits_long(&gb, 39); + sample_blocks = get_bits(&gb, 7) + 1; + if (sample_blocks < 8) + return AVERROR_INVALIDDATA; + *duration = 256 * (sample_blocks / 8); + + skip_bits(&gb, 20); + sr_code = get_bits(&gb, 4); + *sample_rate = avpriv_dca_sample_rates[sr_code]; + if (*sample_rate == 0) + return AVERROR_INVALIDDATA; + + return 0; +} + +static int dca_parse(AVCodecParserContext * s, + AVCodecContext * avctx, + const uint8_t ** poutbuf, int *poutbuf_size, + const uint8_t * buf, int buf_size) +{ + DCAParseContext *pc1 = s->priv_data; + ParseContext *pc = &pc1->pc; + int next, duration, sample_rate; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = dca_find_frame_end(pc1, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + /* read the duration and sample rate from the frame header */ + if (!dca_parse_params(buf, buf_size, &duration, &sample_rate)) { + s->duration = duration; + avctx->sample_rate = sample_rate; + } else + s->duration = 0; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_dca_parser = { + .codec_ids = { AV_CODEC_ID_DTS }, + .priv_data_size = sizeof(DCAParseContext), + .parser_init = dca_parse_init, + .parser_parse = dca_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/dca_parser.h b/ffmpeg/libavcodec/dca_parser.h new file mode 100644 index 0000000..f480eab --- /dev/null +++ b/ffmpeg/libavcodec/dca_parser.h @@ -0,0 +1,36 @@ +/* + * DCA parser + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DCA_PARSER_H +#define AVCODEC_DCA_PARSER_H + +#include + +/** + * Convert bitstream to one representation based on sync marker + */ +int ff_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, + int max_size); + +#endif /* AVCODEC_DCA_PARSER_H */ diff --git a/ffmpeg/libavcodec/dcadata.h b/ffmpeg/libavcodec/dcadata.h new file mode 100644 index 0000000..15df49e --- /dev/null +++ b/ffmpeg/libavcodec/dcadata.h @@ -0,0 +1,7664 @@ +/* + * DCA compatible decoder data + * Copyright (C) 2004 Gildas Bazin + * Copyright (c) 2006 Benjamin Larsson + * + * 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 + */ + +#ifndef AVCODEC_DCADATA_H +#define AVCODEC_DCADATA_H + +#include +#include "libavutil/mem.h" + +/* Generic tables */ + +static const uint32_t dca_bit_rates[32] = +{ + 32000, 56000, 64000, 96000, 112000, 128000, + 192000, 224000, 256000, 320000, 384000, + 448000, 512000, 576000, 640000, 768000, + 896000, 1024000, 1152000, 1280000, 1344000, + 1408000, 1411200, 1472000, 1536000, 1920000, + 2048000, 3072000, 3840000, 1/*open*/, 2/*variable*/, 3/*lossless*/ +}; + +static const uint8_t dca_channels[16] = +{ + 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8 +}; + +static const uint8_t dca_bits_per_sample[7] = +{ + 16, 16, 20, 20, 0, 24, 24 +}; + + +/* Adpcm data */ + +/* 16bits signed fractional Q13 binary codes */ +static const int16_t adpcm_vb[4096][4] = +{ + { 9928, -2618, -1093, -1263 }, + { 11077, -2876, -1747, -308 }, + { 10503, -1082, -1426, -1167 }, + { 9337, -2403, -1495, 274 }, + { 10698, -2529, -532, -1122 }, + { 10368, -3974, -1264, -750 }, + { 10070, -3667, 346, 863 }, + { 10278, -3093, 311, -576 }, + { 9894, -1330, -1428, -860 }, + { 10544, -1923, -1058, -971 }, + { 10996, -1632, -841, -1404 }, + { 11832, -3465, 1658, -1990 }, + { 10852, -688, -2658, -499 }, + { 10546, -1749, -147, -1733 }, + { 10801, -1004, -708, -1453 }, + { 10588, -441, -2113, -952 }, + { 10141, -3331, -582, -1432 }, + { 9608, -2590, 383, 258 }, + { 11422, -3265, 229, -1544 }, + { 10460, -1338, -713, -1568 }, + { 10306, -1721, -1660, -603 }, + { 9580, -1812, -1235, -1061 }, + { 11471, -2285, -1617, -607 }, + { 10081, -2225, -1408, -868 }, + { 10715, -2624, -1367, -704 }, + { 10616, -1871, -2770, -35 }, + { 9352, -2340, -1024, -1566 }, + { 11065, -1458, -1926, -735 }, + { 11334, -2056, -1041, -1144 }, + { 9825, -2048, -794, -1536 }, + { 11850, -2695, -1123, -867 }, + { 10654, -2226, -1891, -373 }, + { 10024, -1557, -808, -1069 }, + { 11142, -1266, -3238, 128 }, + { 11729, -3282, -514, -1011 }, + { 11402, -2094, -2335, -189 }, + { 10195, -3658, 181, -1875 }, + { 11431, -2626, -404, -1377 }, + { 11001, -3868, -619, -1077 }, + { 10894, -2559, 274, -1758 }, + { 9633, -1482, -2253, -773 }, + { 11245, -3321, 830, -1972 }, + { 9768, -2701, -199, -1859 }, + { 10500, -2042, 525, -2043 }, + { 11669, -4069, 293, -1468 }, + { 9192, -1991, -583, -61 }, + { 10057, -3220, -2015, -473 }, + { 9497, -2315, -2490, -467 }, + { 10455, -3069, -1194, -1007 }, + { 9994, -1936, -60, -1225 }, + { 9295, -2156, -1761, -1134 }, + { 10085, -3748, -1026, 197 }, + { 9334, -2360, 804, -351 }, + { 11561, -2553, 1352, -2313 }, + { 12837, -3998, 1195, -1958 }, + { 10114, -1100, -2414, -394 }, + { 9341, -2530, 315, 755 }, + { 10131, -3164, 1411, -674 }, + { 9535, -905, -1551, 579 }, + { 11717, -1519, -3051, 91 }, + { 9824, -2911, -2775, 192 }, + { 9662, -2934, -561, 1450 }, + { 11085, -3392, -1298, -659 }, + { 8955, -2102, -1899, 703 }, + { 8607, -1742, -4348, 814 }, + { 7640, -2063, -3617, 52 }, + { 7074, -826, -4325, 4375 }, + { 7714, 584, -4238, 1927 }, + { 6355, -952, -4912, 3127 }, + { 7069, -660, -6413, 4087 }, + { 8313, -132, -2964, -876 }, + { 6952, -1422, -3962, -24 }, + { 9299, -734, -3088, -263 }, + { 9484, -574, -4513, 466 }, + { 7246, -91, -3735, -704 }, + { 8325, -1417, -3090, -530 }, + { 6469, -1226, -4757, 829 }, + { 6652, -368, -5682, 1393 }, + { 7971, -1278, -2284, 1205 }, + { 7229, -699, -3556, 1840 }, + { 7994, 1284, -2729, 732 }, + { 9005, -698, -4522, 2189 }, + { 6963, 197, -2727, 380 }, + { 8527, 135, -3991, -213 }, + { 8840, 934, -3014, -567 }, + { 10125, 418, -3284, -371 }, + { 6367, 361, -2318, 2554 }, + { 7892, 172, -5247, 4673 }, + { 6674, 387, -5424, 4398 }, + { 6240, 684, -4047, 1219 }, + { 11170, -794, -5081, 1195 }, + { 11765, -648, -6265, 2052 }, + { 10845, -775, -3837, 366 }, + { 12496, -689, -8260, 3562 }, + { 7893, -1166, -4972, 988 }, + { 8592, 1052, -5986, 3087 }, + { 7277, 1874, -5685, 3579 }, + { 6900, 2016, -4809, 3491 }, + { 8530, -2405, -3250, 1986 }, + { 9426, 494, -7067, 5038 }, + { 10285, 564, -8210, 5370 }, + { 8749, -2207, -3980, 2852 }, + { 9653, -2686, -4300, 1400 }, + { 9770, -2286, -5663, 4233 }, + { 8490, -4, -7048, 4496 }, + { 7697, -1209, -5328, 3183 }, + { 6451, 801, -4324, -554 }, + { 7387, 1806, -5265, 545 }, + { 7450, -2302, -4445, 1418 }, + { 8817, -1370, -5827, 2168 }, + { 10324, -2406, -5629, 2579 }, + { 8863, -2578, -3537, 467 }, + { 6901, -1624, -3169, 3392 }, + { 7846, 156, -6948, 3381 }, + { 7928, -1115, -5972, 4816 }, + { 6089, -599, -4368, -320 }, + { 7833, 1246, -3960, -621 }, + { 8931, 2521, -6768, 2052 }, + { 8900, 1944, -4126, 40 }, + { 7661, -34, -2855, 2480 }, + { 5873, 474, -3262, 3712 }, + { 7535, -234, -4699, 216 }, + { 5856, 143, -5142, 73 }, + { 8944, -106, -5874, 3663 }, + { 7134, 426, -5879, 2895 }, + { 10199, 1011, -4762, 369 }, + { 8454, 264, -5971, 1291 }, + { 7822, -2449, -4333, 4540 }, + { 6200, -2758, -2632, 1497 }, + { 6070, -4315, -2699, 414 }, + { 7047, -3739, -3210, 1060 }, + { 5675, -3801, -2717, -407 }, + { 4789, -4063, -2628, -744 }, + { 4023, -3366, -3133, -726 }, + { 4296, -2407, -3381, -513 }, + { 4388, -2931, -2820, 1512 }, + { 4559, -4233, -1941, 1976 }, + { 6702, -3208, -1755, 1680 }, + { 4416, -3521, -1052, 2984 }, + { 7154, -4266, -1203, 3732 }, + { 3625, -4242, -3244, 1395 }, + { 6518, -2856, -1304, 2887 }, + { 6170, -1949, -3014, 3973 }, + { 5189, -2451, -4020, 3477 }, + { 6218, -2988, -1921, 3844 }, + { 4827, -3688, -1928, 3343 }, + { 6668, -3991, -2805, 3095 }, + { 5297, -3115, -3684, 2390 }, + { 5354, -4614, -2662, 1504 }, + { 4196, -3091, -4147, 1135 }, + { 3540, -2893, -4007, 100 }, + { 5569, -1602, -4007, 1909 }, + { 4341, -2091, -4272, 252 }, + { 5559, -2878, -3832, 498 }, + { 4548, -4479, -2898, -27 }, + { 5176, -2494, -4635, 1476 }, + { 3294, -3485, -3738, 716 }, + { 4920, -1229, -4195, -365 }, + { 3257, -3518, -3349, 2862 }, + { 5286, -1948, -3485, -778 }, + { 6502, -3051, -152, 2854 }, + { 5864, -4192, -1076, 3451 }, + { 4656, -3122, -3448, 179 }, + { 5907, -754, -1596, 3116 }, + { 7229, -3680, -1590, 2892 }, + { 5107, -3888, -3364, 806 }, + { 6764, -2635, -3450, 134 }, + { 5258, -2827, -2844, -1052 }, + { 5798, -1725, -4305, 205 }, + { 5404, -1213, -3362, 449 }, + { 6224, -2738, -3046, -581 }, + { 4223, -2438, -2725, 3745 }, + { 4751, -3411, -2123, 116 }, + { 3868, -3000, -3954, 2297 }, + { 6819, -2899, -4277, 2825 }, + { 4207, -4754, -2808, 865 }, + { 4804, -1494, -1997, 4688 }, + { 5282, -2213, -548, 3559 }, + { 5580, -1912, -566, 4370 }, + { 6168, -2857, -672, 4053 }, + { 6583, -4515, -2850, 1670 }, + { 6511, -3093, -3988, 1421 }, + { 4646, -1790, -1443, 3650 }, + { 5915, -924, -2020, 896 }, + { 7814, -4181, -3152, 2007 }, + { 6190, -2238, -4817, 2279 }, + { 4737, -4034, -3288, 1835 }, + { 8161, -3633, -3423, 3137 }, + { 7415, -2351, -2088, 4290 }, + { 4106, -2517, -62, 2905 }, + { 4909, -3145, -614, 4112 }, + { 4938, -3281, -397, 1100 }, + { -173, 919, 1589, -5363 }, + { -13, 796, -295, -6655 }, + { -1860, -829, 1141, -4555 }, + { 2298, -838, -664, -5005 }, + { -884, -1097, 2074, -4613 }, + { -101, 281, 2846, -4535 }, + { 1166, 453, 2429, -5910 }, + { 879, -664, 2370, -5452 }, + { 1415, -370, -1699, -4727 }, + { -1413, 1277, -669, -6649 }, + { 2133, 304, -968, -4624 }, + { 380, 586, -2087, -4892 }, + { 1336, 275, -82, -5789 }, + { -2459, 1057, -34, -5416 }, + { 2278, -1758, 866, -5653 }, + { 1945, -2295, -149, -5302 }, + { 1287, -3525, 996, -5255 }, + { 2297, 803, 1177, -6067 }, + { 187, -180, -619, -6202 }, + { -793, -2537, 1554, -5057 }, + { -2703, -204, -629, -5853 }, + { -1007, -146, 313, -5582 }, + { 830, 357, 869, -6363 }, + { -228, -575, -3177, -4433 }, + { -1001, -1553, -142, -5708 }, + { -1644, 1683, 1721, -4533 }, + { 893, 1924, -15, -5791 }, + { 2195, 2061, -262, -5471 }, + { 3031, 270, 311, -5096 }, + { 1912, 1638, -1523, -4677 }, + { -3142, -55, 253, -4914 }, + { 356, -1680, 343, -6123 }, + { -2241, -1734, -976, -5939 }, + { -2196, -2893, 547, -4938 }, + { -1245, 126, -1916, -5419 }, + { -249, -3755, -1422, -5594 }, + { 575, -2683, -1926, -4566 }, + { -762, 1885, 192, -5880 }, + { -811, -2562, -1068, -6013 }, + { -2264, -3086, -976, -4775 }, + { 70, -1215, 2880, -4410 }, + { 714, -3760, 2916, -4691 }, + { -244, -3404, 1740, -4493 }, + { 684, -5137, -328, -5608 }, + { -529, -3825, -1786, -4535 }, + { -713, -4743, -1118, -5546 }, + { 2718, -3788, 1798, -5708 }, + { -1639, -3679, -1564, -6095 }, + { 1693, -2642, -1389, -4539 }, + { 505, -1573, -1651, -4878 }, + { -835, -2256, -1941, -5352 }, + { 1464, -411, 1993, -6441 }, + { 493, -3184, -145, -6148 }, + { -1413, 499, -1617, -6479 }, + { -294, 1722, -1419, -5725 }, + { -2937, -1528, -175, -4624 }, + { -594, -5911, -56, -6146 }, + { -300, -4275, 1156, -5947 }, + { 552, -2643, 2669, -3959 }, + { 905, -4158, 1789, -5809 }, + { 1336, -2009, 2108, -5903 }, + { 1555, -3600, 1110, -6759 }, + { -1294, -3464, 77, -6084 }, + { -1139, -4006, -1270, -4181 }, + { -5094, -3296, 1092, -2847 }, + { -5503, -2883, 1984, -2067 }, + { -4671, -4218, -1417, -4132 }, + { -3763, -3818, 1262, -3082 }, + { -5132, -3430, 2928, -728 }, + { -5957, -2877, 1251, -2446 }, + { -4425, -2319, -212, -4276 }, + { -6201, -1993, 1774, -2182 }, + { -5500, -3836, 2201, -1396 }, + { -6934, -2334, 2366, -1293 }, + { -6124, -4140, 1337, -1977 }, + { -6553, -4186, 1756, -1325 }, + { -5126, -1258, 744, -3656 }, + { -5167, -1390, 1581, -2895 }, + { -4525, -3398, 2429, -1865 }, + { -4076, -3183, 2027, -2510 }, + { -6191, -3274, 1838, -1814 }, + { -4454, -2753, 2723, -1185 }, + { -6655, -4797, 251, -2595 }, + { -6332, -2232, 1832, 217 }, + { -5869, -1698, 134, 340 }, + { -6614, -1045, 2126, -1932 }, + { -4859, -2107, 2010, -2435 }, + { -6274, -1622, 2808, -1374 }, + { -3119, -3209, 521, -3988 }, + { -5676, -2082, -420, -2711 }, + { -7073, -3623, 696, -2343 }, + { -5986, -4224, 572, -2454 }, + { -4340, -4521, 882, -2771 }, + { -6178, -1933, 535, -1444 }, + { -4923, -4163, 1744, -2066 }, + { -6410, -1519, 1058, -2683 }, + { -5077, -1185, 856, -2216 }, + { -7091, -2444, 687, -2597 }, + { -5284, -2165, 3239, -993 }, + { -4763, -1497, 197, -3179 }, + { -4128, -4958, -396, -3578 }, + { -5054, -3878, -647, -2672 }, + { -7005, -3348, 1679, -1579 }, + { -5767, -1017, 2582, -1915 }, + { -7069, -2787, 1331, -2070 }, + { -5532, -2296, 706, -2950 }, + { -5059, -3543, -821, -3637 }, + { -6639, -1835, 1016, -696 }, + { -5611, -5220, -694, -3371 }, + { -5994, -2803, 2933, -729 }, + { -5948, -619, 1596, -2676 }, + { -5486, -4419, 153, -3265 }, + { -4329, -3440, 1646, -1439 }, + { -4083, -3978, 177, -3569 }, + { -4289, -2599, 1224, -3075 }, + { -5707, -3253, 1912, -759 }, + { -6606, -3437, 2562, -571 }, + { -5254, -2444, 769, -352 }, + { -6545, -3154, 582, -1103 }, + { -5328, -2241, 2566, -1775 }, + { -7216, -1936, 1538, -1983 }, + { -3730, -2451, 426, -3869 }, + { -5110, -1385, 2031, -1169 }, + { -6470, -2715, 269, -3123 }, + { -5806, -2480, -97, -3832 }, + { -3683, -4916, -490, -4330 }, + { -6341, -2083, -669, -115 }, + { -4913, -4079, -837, -4673 }, + { -3274, -2497, 2334, -2652 }, + { -1286, -1731, 2550, -3756 }, + { -3375, -877, 926, -3977 }, + { -2525, -2079, 2879, -2625 }, + { -5308, -504, 3111, -1607 }, + { -4904, 460, 4093, -1232 }, + { -1993, 1616, 4656, -1913 }, + { -3481, -1176, 3119, -2236 }, + { -4132, -1502, 2339, -2545 }, + { -2542, 1151, 3569, -2550 }, + { -4381, 430, 3147, -2082 }, + { -3888, 867, 3899, -1657 }, + { -2861, 1290, 4202, -1979 }, + { -3893, -253, 2363, -2764 }, + { -1705, 688, 3827, -2923 }, + { -2223, 2312, 3700, -3148 }, + { -1986, -720, 5021, -795 }, + { -3177, 242, 1952, -3352 }, + { -1854, 1509, 2528, -3815 }, + { -3173, 97, 5019, -706 }, + { -2689, -145, 1375, -3915 }, + { -4838, -385, 2488, -2427 }, + { -4557, -355, 1603, -3060 }, + { -3522, 1832, 3292, -2674 }, + { -3769, 780, 2378, -2704 }, + { -4323, -1932, 3414, -1169 }, + { -2740, 1158, 2729, -3273 }, + { -3647, 210, 1464, -2892 }, + { -2342, -2097, 1513, -3727 }, + { -4422, -1242, 3130, -1833 }, + { -1308, -1039, 4290, -1875 }, + { -1754, -2535, 3298, -2314 }, + { -4102, -186, 4037, -1094 }, + { -1008, 1570, 3290, 171 }, + { -3322, -2621, 2791, -1536 }, + { -2539, -2597, 3442, -1672 }, + { -3411, -2015, 3670, -1174 }, + { -2097, 730, 5581, -1399 }, + { -1510, -74, 4820, -2004 }, + { -4086, -868, 4425, -771 }, + { -956, -986, 3640, -2925 }, + { -2087, -1250, 3464, -2458 }, + { -3308, -2411, 1334, -3667 }, + { -2264, -389, 4004, -1854 }, + { -680, 239, 4058, -3388 }, + { -1357, 30, 2993, -3658 }, + { -3601, -552, 1177, -1136 }, + { -2641, 442, 4374, -1625 }, + { -2525, 770, 1640, -3895 }, + { -3172, -891, 3893, -1608 }, + { -2996, 13, 3277, -2414 }, + { -899, 1055, 4470, -2501 }, + { -422, -584, 3475, -3787 }, + { -1978, -593, 2566, -3415 }, + { -3150, -1280, 2362, -3047 }, + { -3592, 224, 1026, -3932 }, + { -4840, -1189, 3633, -879 }, + { -3952, -2255, 2916, -1826 }, + { -1695, 28, 1810, -349 }, + { -745, -2484, 3308, -3293 }, + { -1016, 1563, 5365, -1823 }, + { -2172, -1787, 4266, -1287 }, + { -1241, -1951, 3982, -2413 }, + { -2009, -2639, 2330, -3480 }, + { 5105, -1618, -2588, -2015 }, + { 6497, -1523, -3218, -910 }, + { 6526, -2305, -2029, -1790 }, + { 5289, -99, -3436, -400 }, + { 5781, -1623, -1577, -2617 }, + { 5259, -670, -3125, -1700 }, + { 6343, -1256, -331, -3222 }, + { 7967, -678, -2195, -1462 }, + { 6119, -695, -2988, -1538 }, + { 6108, 494, -3359, -1548 }, + { 5067, 969, -2328, -2707 }, + { 7595, -435, -1497, -2056 }, + { 6929, -719, -2420, -1665 }, + { 5190, 584, -2982, -2103 }, + { 6106, -444, -1411, -2739 }, + { 5584, 289, -1804, -2803 }, + { 5276, 227, -1180, -3361 }, + { 7544, -1525, -1834, -1725 }, + { 5986, -1470, -2606, -1701 }, + { 5096, -765, -1712, -3006 }, + { 5423, -149, -3933, -1157 }, + { 7651, 26, -2445, -1507 }, + { 4745, -464, -1735, -2362 }, + { 5352, -1011, -1094, -1999 }, + { 6300, -672, -542, -1950 }, + { 6675, -1020, -1318, -1059 }, + { 7218, -2036, -603, -2462 }, + { 7755, -1514, -2430, -1229 }, + { 5041, 449, -1056, -2405 }, + { 6710, -2277, -1344, -2284 }, + { 6824, -1347, -2254, 251 }, + { 6068, -1857, -983, -1316 }, + { 5603, -2177, -2730, -1477 }, + { 5838, -1059, -3604, -970 }, + { 5076, -789, -335, -2413 }, + { 6191, -1634, -2000, -2129 }, + { 5092, -1292, -2543, -1034 }, + { 5305, 435, -1710, -1850 }, + { 6140, 561, -2176, -2380 }, + { 6752, 348, -2496, -1890 }, + { 6405, 273, -1098, -2778 }, + { 6942, -1340, -496, -1381 }, + { 5238, -687, -2454, -2349 }, + { 6959, -882, -1833, -2061 }, + { 6292, -253, -2125, -2199 }, + { 5838, -574, -759, -3215 }, + { 6954, -1484, -640, -2771 }, + { 7498, -1706, -1210, -2154 }, + { 6772, -1003, -1235, -2532 }, + { 6014, 228, -2154, -1108 }, + { 6943, -2178, -2644, -1122 }, + { 7262, -763, -3056, -1090 }, + { 6273, -1478, -1072, 177 }, + { 4734, 425, -2912, 357 }, + { 7129, 168, -1537, -2327 }, + { 7204, -434, -746, -2660 }, + { 6879, 57, -3087, -1310 }, + { 4623, -610, -718, -3459 }, + { 6565, -543, -1998, -339 }, + { 4752, -277, -2066, -1405 }, + { 7435, -1416, -1904, -505 }, + { 4076, 150, -1222, -3556 }, + { 7082, -28, -1456, -1174 }, + { 5941, -446, -1326, -1158 }, + { 3870, -1648, -2474, -2589 }, + { 858, 37, -3387, -3721 }, + { 3557, -1503, -1664, -3383 }, + { 3336, -1972, -3079, -2216 }, + { 3186, 60, -4185, -863 }, + { 3456, -773, -3066, -2457 }, + { 4131, -913, -2060, -2601 }, + { 4431, -691, -4114, -972 }, + { 3461, -334, -3680, -1751 }, + { 2006, -459, -2214, -3827 }, + { 1322, 32, -2816, -3203 }, + { 4425, -1897, -2791, -1946 }, + { 4504, 23, -3421, -1909 }, + { 3090, -885, -2366, -3264 }, + { 3209, -2363, -3730, -834 }, + { 3312, -1471, -3641, -1579 }, + { 4184, -1669, -3323, -1248 }, + { 2190, -931, -3302, -2944 }, + { 2947, -229, -4791, -1195 }, + { 2020, -1626, -2700, -3125 }, + { 2214, -326, -4352, -1683 }, + { 3286, -2619, -2412, -2458 }, + { 1000, -2571, -4129, -2158 }, + { 2496, -2627, -3611, -1433 }, + { 2043, -2191, -2167, -3827 }, + { 2571, -2544, -1915, -3222 }, + { 2022, -1501, -3856, -2165 }, + { 2685, -1180, -1461, -4038 }, + { 1610, -2313, -4391, -1173 }, + { 2340, -2490, -4215, -516 }, + { 1742, -2615, -3632, -2146 }, + { 523, -1293, -4246, -2442 }, + { 3725, -2723, -3014, -1576 }, + { 3554, -1381, -4200, -824 }, + { 1291, -1594, -4777, -1430 }, + { 1452, 515, -2960, -3830 }, + { 4264, -894, -3305, -1826 }, + { 2606, -1452, -4522, -966 }, + { 1196, -830, -4807, -1816 }, + { 1054, -775, -2616, -4071 }, + { 4206, 415, -4344, -1132 }, + { 3044, 491, -4126, -1934 }, + { 988, -901, -3353, -3443 }, + { 1729, -3063, -2267, -3370 }, + { 3915, 912, -2989, -2387 }, + { 3781, 300, -2457, -3050 }, + { 2712, 924, -1350, -1206 }, + { 4230, 405, -2343, 665 }, + { 1878, -873, -225, -29 }, + { 3510, 56, -1334, -3420 }, + { 2850, 1447, -2651, -3150 }, + { 1510, -706, -4125, -2483 }, + { 3115, 793, -1692, -3894 }, + { 2667, 213, -2973, -2786 }, + { 1184, -2384, -3051, -3173 }, + { 2139, 796, -2079, -3697 }, + { 1464, -1483, -3726, -2754 }, + { 2407, -1148, -3915, -1569 }, + { 2612, -1779, -3217, -2271 }, + { 2406, -2870, -2937, -2496 }, + { 2140, 126, -3646, -2758 }, + { 2952, -1036, 268, -1423 }, + { 93, -1931, -3841, -3535 }, + { 389, -2953, -3383, -3343 }, + { 8652, -5511, -1662, 565 }, + { 7427, -2791, -2535, -842 }, + { 8541, -4253, -1407, -988 }, + { 8018, -3203, -2998, 105 }, + { 7231, -3926, -958, 1308 }, + { 7331, -3690, -363, 2586 }, + { 6803, -3646, -2226, -903 }, + { 8163, -2811, -477, -2235 }, + { 9356, -3818, -1685, -684 }, + { 8466, -2854, -302, -698 }, + { 8458, -3224, 517, 279 }, + { 8074, -2619, -1326, 2596 }, + { 8779, -2761, -2527, -441 }, + { 6533, -2887, -899, -696 }, + { 7394, -2305, -1642, -120 }, + { 8281, -3780, -22, 1305 }, + { 9158, -4413, -779, 901 }, + { 9031, -5240, -1109, 1678 }, + { 8717, -3650, 410, -1075 }, + { 7317, -3197, -818, -2264 }, + { 7934, -2385, -1214, -1886 }, + { 8256, -4441, -291, -587 }, + { 7358, -3395, 1090, -270 }, + { 9446, -4910, -1343, -473 }, + { 8187, -4726, -808, 1166 }, + { 7504, -3845, -47, 267 }, + { 8029, -2146, -1283, -383 }, + { 7461, -2705, -853, 783 }, + { 9367, -3636, -645, -354 }, + { 8955, -3473, -308, -1947 }, + { 8676, -2683, -2099, 1485 }, + { 7481, -3003, -871, -444 }, + { 8015, -2839, -1673, 1175 }, + { 6947, -4643, -1527, -1047 }, + { 7622, -2575, -137, -960 }, + { 9388, -4279, -707, -1322 }, + { 8382, -5259, -1283, -565 }, + { 6856, -4138, -1030, 630 }, + { 8659, -2571, -1124, -1666 }, + { 8763, -3807, -537, 2543 }, + { 8049, -3578, -2186, -604 }, + { 8272, -2351, -1985, -1214 }, + { 6855, -3796, -1527, -1631 }, + { 7178, -2896, -1600, -1756 }, + { 7040, -2888, -89, -1586 }, + { 6261, -3403, -264, 998 }, + { 7756, -4699, -1543, -834 }, + { 7682, -4622, -758, -1721 }, + { 8839, -4232, -2932, 1959 }, + { 9363, -4679, -1956, 39 }, + { 7883, -3616, -1414, -1432 }, + { 8828, -3188, -1356, -1312 }, + { 7746, -3987, -121, -2424 }, + { 9262, -3256, -693, 818 }, + { 7670, -3420, -148, 3504 }, + { 7344, -3183, 608, 1595 }, + { 8976, -4139, -1848, 1304 }, + { 6708, -4131, 33, -852 }, + { 7840, -4429, -2275, 79 }, + { 8980, -3858, -2838, 453 }, + { 7815, -4604, -2563, 944 }, + { 8372, -4422, -1783, 3071 }, + { 8623, -5128, -1754, 2888 }, + { 7462, -3281, 889, 920 }, + { 8416, -59, -1320, -1825 }, + { 7928, -1488, -414, -2499 }, + { 8110, -977, -1047, -2042 }, + { 8278, -687, -1597, -1550 }, + { 7988, -174, -977, -2106 }, + { 8609, -1547, -1628, -1527 }, + { 9000, -1798, -946, -1761 }, + { 8954, -872, -1404, -1594 }, + { 8939, 466, -748, -1212 }, + { 9549, -329, -177, -1360 }, + { 9411, -18, -1126, -1568 }, + { 8859, -782, -488, -1338 }, + { 8955, -218, -43, -1209 }, + { 9131, -69, -453, -1001 }, + { 9069, -1519, -1091, -1199 }, + { 9247, -1309, -566, -1146 }, + { 8528, -1617, -287, -1313 }, + { 7763, -745, -149, -2040 }, + { 8294, -343, 257, -2633 }, + { 10149, -893, -552, -1649 }, + { 9398, -915, 218, -2042 }, + { 9703, -1194, -675, -1592 }, + { 9586, -700, -427, -1710 }, + { 8930, 497, -1445, -1218 }, + { 9285, -1323, -163, -1552 }, + { 8431, -1289, -985, -1404 }, + { 8965, -655, 653, -1483 }, + { 9542, -1001, -951, -1128 }, + { 9205, -647, -37, -882 }, + { 8603, -56, 514, -1793 }, + { 9300, -12, -1324, -567 }, + { 8773, 238, -184, -1456 }, + { 9941, -1306, -69, -1792 }, + { 9360, 279, -376, -1919 }, + { 9180, -285, 95, -2170 }, + { 9922, -501, -970, -1570 }, + { 8341, -1493, -856, -2092 }, + { 8780, -981, -850, -1014 }, + { 9721, -548, -1504, -1094 }, + { 9973, -1493, 482, -2105 }, + { 8707, -333, -1027, -1087 }, + { 9098, -469, -315, -1723 }, + { 8879, -1050, -661, -2020 }, + { 8857, 602, -866, -1918 }, + { 8945, -1025, -2154, -1071 }, + { 8484, -1930, -468, -2179 }, + { 9177, -1903, -224, -2112 }, + { 8652, -137, -2097, -1214 }, + { 9063, -973, -1405, -772 }, + { 9328, -456, 662, -2469 }, + { 10101, -697, 127, -2113 }, + { 9685, 811, -2359, -1024 }, + { 8586, -94, -460, -1982 }, + { 7924, -141, -509, -2513 }, + { 7773, -669, -107, -2835 }, + { 8636, -1064, -46, -2409 }, + { 9748, 596, -1815, -1349 }, + { 8924, 304, 547, -2614 }, + { 9442, 746, -1153, -1679 }, + { 9454, -278, -529, -1976 }, + { 8488, 561, -32, -2160 }, + { 10083, -63, -1544, -1364 }, + { 9390, -1278, 568, -1131 }, + { 9740, -49, -2253, -910 }, + { 3636, -2391, -1115, -3614 }, + { 6014, -3204, -1902, -1808 }, + { 5787, -3497, -1116, -2590 }, + { 4365, -3046, -1632, -2668 }, + { 4733, -2192, -2029, -2468 }, + { 5412, -2753, -1633, -2464 }, + { 4455, -3375, -767, -3399 }, + { 4456, -1644, -983, -2841 }, + { 4039, -2523, 38, -3967 }, + { 3406, -2662, 72, -4757 }, + { 4279, -2005, 1055, -4399 }, + { 4321, -1377, -860, -3786 }, + { 3743, -5739, -651, -3047 }, + { 3528, -5510, 361, -4060 }, + { 6496, -4886, -136, -2689 }, + { 4513, -5254, 551, -4010 }, + { 6557, -3413, -92, -3063 }, + { 4186, -2059, 187, 47 }, + { 6210, -4117, -1256, -1985 }, + { 6038, -4343, 351, -2124 }, + { 4305, -4780, -2077, -1897 }, + { 4480, -3815, -2228, -1533 }, + { 5582, -3689, 1221, -3429 }, + { 5532, -4874, 1195, -2765 }, + { 6518, -2853, -905, -2568 }, + { 5467, -2192, 470, -4115 }, + { 4139, -1577, 240, -3493 }, + { 5281, -1926, -729, -3340 }, + { 5214, -2870, 1359, -4289 }, + { 3046, -3510, -1536, -3214 }, + { 5433, -2881, -1230, -1184 }, + { 4861, -3932, -1071, -2791 }, + { 5693, -4234, -1906, -1502 }, + { 4004, -3935, -1804, -2383 }, + { 3728, -3792, 681, -4773 }, + { 3621, -3030, -1951, -2598 }, + { 5133, -3903, 44, -3700 }, + { 3561, -3451, 1183, -5301 }, + { 5026, -2762, -2341, -1780 }, + { 5841, -2492, -467, -3210 }, + { 5591, -1791, 497, -2472 }, + { 5054, -3898, -1822, -2097 }, + { 5813, -2792, 83, -1469 }, + { 4432, -4497, 1670, -5193 }, + { 5338, -4653, -1109, -2200 }, + { 3239, -4401, -648, -3655 }, + { 2147, -3598, -1200, -4242 }, + { 4417, -2271, -1552, -3210 }, + { 6494, -4360, 852, -3565 }, + { 2393, -6358, -856, -4524 }, + { 4959, -4196, -847, -1403 }, + { 4924, -5438, -226, -3026 }, + { 4254, -5303, -1306, -2424 }, + { 4121, -3126, -2334, -1981 }, + { 3437, -4443, -1464, -2953 }, + { 3203, -3459, -529, -4339 }, + { 5896, -5945, 543, -3246 }, + { 1987, -4733, -220, -4863 }, + { 4358, -4431, -514, -3081 }, + { 4583, -2416, -492, -2287 }, + { 2943, -5035, 419, -4927 }, + { 5358, -5129, 987, -4309 }, + { 4460, -3392, 1752, -5634 }, + { 3415, -4633, 1507, -5945 }, + { 811, -4692, -445, 2333 }, + { 1009, -5613, -1857, 1360 }, + { 1338, -2712, -2720, 3036 }, + { 1002, -3754, -2582, 2344 }, + { 750, -4608, -2334, 714 }, + { 2043, -3207, -2822, 2173 }, + { -140, -4654, -2953, 357 }, + { -54, -4026, -2376, 2695 }, + { 1858, -5022, -717, 2287 }, + { 2064, -3894, -722, 3255 }, + { 2727, -4558, -332, 2603 }, + { 1810, -5378, 283, 1826 }, + { 3935, -4326, 762, 3383 }, + { -767, -4697, -2510, 1922 }, + { 2146, -4312, -3090, 1641 }, + { 54, -5881, -2114, 921 }, + { 1992, -5766, -640, 1574 }, + { 1200, -5371, -1114, 1828 }, + { 2973, -5337, 34, 2266 }, + { 1531, -5018, -2817, 1192 }, + { 3078, -4570, 117, 1990 }, + { 924, -4286, -1388, 2713 }, + { 142, -5058, -2848, 1487 }, + { -106, -6180, -881, 842 }, + { 673, -5433, -229, 1596 }, + { 783, -5710, -2784, 562 }, + { 1935, -5729, -2009, 856 }, + { -410, -3375, -3326, 2734 }, + { 234, -3000, -2628, 3260 }, + { 733, -3405, -3806, 1589 }, + { 771, -4285, -3544, 1314 }, + { 1192, -3563, -3960, 2178 }, + { 206, -5555, -1250, 1546 }, + { -130, -3815, -1210, 3041 }, + { 646, -3940, -393, 2992 }, + { -184, -4931, -1767, 1925 }, + { 2746, -5120, -2275, 1464 }, + { 2440, -3731, -3352, 2729 }, + { -490, -4942, -3779, 997 }, + { 68, -2636, -4167, 3778 }, + { 48, -3986, -4118, 2106 }, + { -978, -5486, -1336, 1390 }, + { 1126, -5297, -855, 640 }, + { -472, -3975, -3622, 1557 }, + { 2456, -5344, -1523, 1648 }, + { -774, -5652, -2417, 1147 }, + { 995, -6122, -812, 1132 }, + { 3282, -4571, -1763, 2175 }, + { 3655, -3862, -676, 3568 }, + { 3038, -3647, -1672, 3381 }, + { 2595, -2964, -2772, 3263 }, + { 4176, -3353, -1148, 4354 }, + { 1603, -3442, -1500, 3444 }, + { 828, -6226, -1783, 678 }, + { 1421, -3333, -3080, 3403 }, + { 1121, -4727, -1924, 1984 }, + { -186, -5083, -682, 1796 }, + { 819, -2778, -3488, 530 }, + { 421, -2873, -3832, 2596 }, + { 2164, -4263, -1605, 2282 }, + { 585, -4437, -682, -491 }, + { -644, -4452, -1157, 2325 }, + { 1991, -4299, 210, 2834 }, + { 2135, -3632, -2113, 665 }, + { -7482, -2724, -2662, -1380 }, + { -6983, -2166, -3756, -3509 }, + { -7085, -1439, -2397, -3112 }, + { -7760, -3049, -3319, -2822 }, + { -8413, -2760, -4406, -3298 }, + { -5995, -3943, -1260, -3750 }, + { -7879, -1554, -3464, -2606 }, + { -6314, -2034, -3878, -1681 }, + { -8849, -2084, -1399, -1231 }, + { -7153, -2602, -1384, -817 }, + { -8041, -2571, -407, -2785 }, + { -7246, -2233, -1578, 260 }, + { -7336, -3883, -4061, -1342 }, + { -7619, -3908, -2342, 382 }, + { -8684, -3724, -1662, -727 }, + { -7850, -2922, -1770, -3449 }, + { -6766, -2034, -1293, -1988 }, + { -6895, -2116, -968, -3744 }, + { -7136, -5147, -2618, -2809 }, + { -8224, -3724, -2519, -1589 }, + { -6711, -2750, -3021, -219 }, + { -8059, -1638, -1102, -3175 }, + { -8710, -4839, -3963, -3143 }, + { -9363, -4965, -3257, -1002 }, + { -6099, -1751, -3157, -395 }, + { -6453, -3216, -4597, -483 }, + { -7879, -5477, -839, -2638 }, + { -7202, -4038, -526, -2856 }, + { -8022, -1228, -1910, -1646 }, + { -9117, -1393, -1582, -2535 }, + { -9095, -2693, -636, -2605 }, + { -9076, -2580, -3481, -2519 }, + { -8327, -4859, -2422, 83 }, + { -8368, -2129, -2324, -2173 }, + { -8554, -4563, -3842, -2007 }, + { -10462, -4261, -1934, -2084 }, + { -9717, -3187, -2294, -1896 }, + { -9625, -3889, -3020, -3224 }, + { -9857, -4955, -4239, -2184 }, + { -9752, -2351, -2277, -3129 }, + { -7219, -1302, -2639, -1603 }, + { -7477, -4360, -3718, -559 }, + { -5680, -2033, -2326, -3078 }, + { -10190, -5548, -4643, -3601 }, + { -9431, -4121, -879, -2479 }, + { -8365, -5450, -2020, -1439 }, + { -6289, -5178, -1605, -3845 }, + { -8319, -3866, -687, -2792 }, + { -8131, -1031, -3608, -3947 }, + { -10510, -2560, -1199, -2082 }, + { -11015, -3640, -2748, -3041 }, + { -8762, -5022, -5231, -1162 }, + { -10153, -2715, -4648, -4859 }, + { -7930, -5205, -1900, -3600 }, + { -9561, -3548, -4812, -3722 }, + { -7663, -4709, -1180, -1475 }, + { -9073, -5707, -1815, -2980 }, + { -8602, -2363, -2675, -3770 }, + { -9967, -5614, -3575, -3838 }, + { -8324, -1005, -2131, -3254 }, + { -10331, -5737, -2550, -2940 }, + { -8234, -3354, -3361, -4479 }, + { -8140, -1951, -4526, -4545 }, + { -6679, -2662, -2284, -4182 }, + { -1122, -1514, -6427, -212 }, + { 54, -1660, -5424, -1404 }, + { 254, -2778, -5222, 846 }, + { -267, -1661, -6577, 814 }, + { -305, -2021, -5759, 1484 }, + { -1791, -2446, -6867, -86 }, + { -2929, -3158, -6603, -1799 }, + { -1391, -3189, -5557, -1053 }, + { -1602, -884, -6767, -1213 }, + { -361, -318, -6219, -44 }, + { -4078, -2635, -5523, -433 }, + { -956, 478, -4382, 1470 }, + { -3300, -2462, -6021, -2721 }, + { 708, -2434, -5085, -540 }, + { -2435, -3607, -5647, -2110 }, + { -491, -1134, -4681, -2886 }, + { 87, -3435, -4641, -1194 }, + { -586, -2927, -4784, 366 }, + { -1394, -2326, -6021, 350 }, + { 97, -2519, -4678, -2120 }, + { -1547, -1907, -5069, -2993 }, + { 268, -3724, -4719, 127 }, + { -827, -1190, -5912, 1144 }, + { -3959, -2322, -6898, -1974 }, + { -2728, -2228, -6426, -562 }, + { -456, -666, -5785, -1609 }, + { 531, -1096, -5731, -656 }, + { -3569, -688, -3915, 110 }, + { -4752, -1725, -4393, -377 }, + { -3210, -3315, -6960, -840 }, + { -688, -3416, -4971, 1221 }, + { -1833, 77, -6491, -2434 }, + { -239, -255, -6850, -886 }, + { -2112, -1490, -6291, -2689 }, + { -1544, -4579, -5198, -1261 }, + { -2771, -4014, -5520, 683 }, + { -1635, -2829, -5512, 1214 }, + { -958, -2582, -4823, 2360 }, + { -2077, -4566, -4642, 365 }, + { -3112, -4214, -5960, -823 }, + { -2467, -2510, -4858, 1467 }, + { -1561, -3399, -5822, 211 }, + { -775, -1081, -4424, 2636 }, + { -1263, 25, -6378, -1392 }, + { -3476, -366, -5417, -1393 }, + { -3176, -1476, -4149, 1466 }, + { -2479, 518, -4448, -257 }, + { -2992, 158, -4660, -1279 }, + { -1320, -3872, -4479, 1147 }, + { -1475, -312, -5318, 539 }, + { -3527, -1679, -5860, -1681 }, + { -3397, -3438, -5593, 1866 }, + { -4089, -2439, -4763, 1275 }, + { -748, -4513, -4687, -48 }, + { -2166, -4531, -4691, -2856 }, + { -2385, -853, -6035, -627 }, + { -1194, -4091, -4472, -1963 }, + { -682, -3234, -4084, -3033 }, + { -3255, -5015, -5328, -12 }, + { -2313, -3436, -4601, -155 }, + { -2792, -1038, -6947, -2019 }, + { -1244, -1526, -5771, -1882 }, + { -4679, -3731, -5506, 283 }, + { -3062, -66, -3558, -758 }, + { -4895, -1187, 4751, 3728 }, + { -7600, -2752, 3320, 4613 }, + { -5703, -2975, 3944, 2659 }, + { -4972, -1257, -246, 2952 }, + { -4221, -2487, 1702, 4295 }, + { -2900, -1529, 2458, 4935 }, + { -5061, 407, 2416, 4050 }, + { -6931, -3478, 2761, 2213 }, + { -6037, -3921, 3192, 1866 }, + { -6113, -811, 2407, 3782 }, + { -5878, -1716, 1207, 3478 }, + { -5953, -2853, 2207, 2712 }, + { -6807, -3223, 2749, 3595 }, + { -3272, -3157, 1389, 3788 }, + { -5368, -1904, 1980, 5077 }, + { -7235, -1398, 3075, 4548 }, + { -4765, -3487, 2755, 2796 }, + { -7658, -4435, 2694, 2582 }, + { -6997, -4282, 456, 3832 }, + { -5563, -3115, -63, 3713 }, + { -4244, -4220, 1450, 2767 }, + { -3801, -2194, 190, 4303 }, + { -5458, -4119, 1958, 2274 }, + { -7300, -3469, 3514, 3193 }, + { -4594, -2067, 775, 4752 }, + { -3389, -1654, 1464, 5412 }, + { -4845, -3483, 964, 3437 }, + { -6007, -2818, 1666, 4659 }, + { -8709, -5007, 1757, 3287 }, + { -5833, -4389, 1025, 3171 }, + { -5788, -1780, 3944, 3661 }, + { -4430, -920, 1938, 4753 }, + { -7066, -1857, 4591, 4538 }, + { -3549, -513, 1427, 5317 }, + { -7517, -1220, 2883, 3049 }, + { -7605, -2687, 1874, 2735 }, + { -8718, -4035, 2676, 3730 }, + { -7990, -3907, 1185, 2607 }, + { -6058, -1744, 3349, 5157 }, + { -5954, 565, 3161, 3250 }, + { -6478, -612, 1930, 2271 }, + { -6535, -1445, -2, 1618 }, + { -8963, -4151, 1192, 4044 }, + { -7227, -3570, 1600, 4234 }, + { -4674, 79, 595, 3015 }, + { -3974, 430, 2727, 5137 }, + { -5299, 9, 3714, 4779 }, + { -6779, -2699, -8, 2436 }, + { -7016, -1145, 1293, 2310 }, + { -6955, -3312, 1534, 1801 }, + { -4025, 740, 1850, 4054 }, + { -9589, -3460, 4154, 5270 }, + { -4404, -1181, 4298, 5173 }, + { -7356, -4583, -18, 2644 }, + { -6516, -1235, 4439, 6234 }, + { -3453, -301, 4344, 4464 }, + { -4643, 1530, 3315, 4340 }, + { -4575, -2557, 3754, 3682 }, + { -3643, -3501, 2051, 2997 }, + { -5412, -2475, 2301, 1579 }, + { -5846, 259, 1360, 2348 }, + { -5258, -1358, 1050, 838 }, + { -5542, -219, 6377, 5750 }, + { -5713, -2952, 922, 899 }, + { -2049, -1135, 5206, 1033 }, + { -1693, -1886, 4835, -106 }, + { -2344, -3504, 4232, -13 }, + { -2475, -2334, 5043, 1126 }, + { -787, -2549, 3880, 2138 }, + { -3159, -2341, 4830, 2887 }, + { -1780, -1009, 6240, 2061 }, + { -4327, -3363, 2818, 886 }, + { -3376, -2743, 4104, 207 }, + { -3250, -4640, 2718, 1498 }, + { -382, -1075, 4382, 3460 }, + { -2416, -4168, 3530, 816 }, + { -1756, -2708, 4861, 622 }, + { -1879, -2097, 5156, 2889 }, + { -2496, -2418, 3722, 2671 }, + { -2717, -3252, 3341, 1944 }, + { -4063, -4091, 3306, 267 }, + { -3549, -3808, 3747, 842 }, + { -2635, 546, 5794, 1894 }, + { -1857, -1121, 4383, 3964 }, + { -2226, -2166, 3489, 3678 }, + { -3492, -660, 5323, 1063 }, + { -3033, -3130, 4382, 1828 }, + { -2703, -625, 6369, 2851 }, + { -1656, -2842, 4584, -528 }, + { -4781, -2622, 4390, 2097 }, + { -413, -2045, 5081, 3035 }, + { -3810, -2662, 4532, 1095 }, + { -3144, -1858, 5215, 1880 }, + { -3562, -1795, 4928, 670 }, + { -4800, -1509, 5189, 1859 }, + { -1085, -3832, 4169, 900 }, + { -1969, -3270, 2857, 2878 }, + { -4267, -4140, 3176, 1805 }, + { -5145, -3727, 3524, 1168 }, + { -1346, -1876, 5501, 1748 }, + { -4998, -2945, 3699, 338 }, + { -3458, -3096, 3406, -635 }, + { -1751, -3209, 3508, 395 }, + { -2507, 170, 5987, 705 }, + { -3756, -1072, 5647, 3536 }, + { -2870, -1439, 5026, 3212 }, + { -3913, -3225, 3669, 2144 }, + { -3739, 226, 5747, 764 }, + { -2052, -820, 5266, 3093 }, + { -3214, -3820, 2409, 2391 }, + { -4398, -2588, 3501, -218 }, + { -4484, -1763, 4180, -198 }, + { -3368, -1525, 4362, -134 }, + { -2407, 224, 4905, 3533 }, + { -1369, -2937, 4728, 1788 }, + { -4848, -1707, 4159, 851 }, + { -3454, -1749, 4281, 3230 }, + { -1990, -3853, 3487, 1735 }, + { -3117, 92, 6155, 4075 }, + { -2676, -2472, 4078, -589 }, + { -1547, -2012, 2626, 1835 }, + { -4275, -588, 4824, 725 }, + { -601, -2249, 3736, 3548 }, + { -4060, -61, 5333, 3097 }, + { -4303, 7, 6551, 3054 }, + { -5003, -1029, 5786, 3319 }, + { -2810, -728, 5392, 199 }, + { -1232, -200, 5228, 3121 }, + { 2621, 165, -6255, 298 }, + { 3669, 537, -6844, 1564 }, + { 1598, -1190, -6235, 2523 }, + { 2164, -32, -6894, 1383 }, + { 853, -1597, -6069, 1449 }, + { 1377, -1661, -5266, 108 }, + { 2660, 48, -5172, -517 }, + { 1903, -391, -5677, 1010 }, + { 3792, 206, -5274, -11 }, + { 1239, 2776, -2929, 2721 }, + { 4071, 149, -7259, 3125 }, + { 1436, -480, -6156, -196 }, + { 1373, -1960, -5005, 3122 }, + { 3413, -1271, -5176, 3283 }, + { 3060, -68, -6495, 2238 }, + { 2700, -2075, -4681, 91 }, + { 2928, -1728, -5168, 1858 }, + { 4424, 828, -4471, 88 }, + { 2672, -2604, -4038, 2753 }, + { 5223, -123, -6749, 2295 }, + { 4237, -420, -5538, 1353 }, + { 4744, -1281, -4097, 4708 }, + { 1103, -2764, -4751, 2024 }, + { 3747, -1913, -3911, 3960 }, + { 2470, -1416, -5542, 615 }, + { 4847, -1354, -5334, 1733 }, + { 5336, 88, -7593, 4007 }, + { 2388, -2880, -4807, 1037 }, + { 4495, 1391, -5685, -139 }, + { 5253, 1637, -6450, 1533 }, + { 1199, 795, -5515, 1261 }, + { 1397, -1259, -4252, 3838 }, + { 746, 70, -6640, 604 }, + { 1584, 166, -4972, 3072 }, + { 380, -999, -5397, 2267 }, + { 2974, 1707, -3242, 5360 }, + { 5202, -403, -5453, 2832 }, + { 3718, -1731, -4760, 714 }, + { 4150, -975, -4792, 61 }, + { 2925, -818, -4841, 15 }, + { 5301, 577, -4006, 3259 }, + { 5265, 1986, -5679, 3028 }, + { 3752, 1928, -4509, 3729 }, + { 3278, 1925, -6370, 1247 }, + { 5107, 1721, -4853, 3127 }, + { 3279, 2982, -2515, 4005 }, + { 4622, 668, -6204, 759 }, + { 6034, 317, -5763, 4818 }, + { -558, 57, -3785, 2817 }, + { 4476, 1616, -3965, 4536 }, + { 5953, 2056, -8215, 2715 }, + { 4387, 2613, -7463, 868 }, + { 5834, 1088, -4736, 4924 }, + { 6473, -856, -6991, 4172 }, + { 4959, -293, -5162, 76 }, + { 2731, -843, -6119, 3847 }, + { 3245, 1202, -6833, 616 }, + { 2553, 1383, -3829, 3859 }, + { 4332, 2099, -3480, 3622 }, + { 2110, 2683, -2728, 3990 }, + { 876, 1167, -3290, 3466 }, + { 3991, 1709, -2410, 4077 }, + { 5105, 939, -2584, 3256 }, + { 4719, 688, -1566, 3040 }, + { -3632, 4335, 1266, -3303 }, + { -4956, 3207, 1312, -2806 }, + { -4669, 2627, 2663, -2435 }, + { -4282, 3708, 2303, -3038 }, + { -4536, 2297, -175, -3350 }, + { -5234, 2503, -139, -880 }, + { -3978, 1512, 1092, -3619 }, + { -4519, 4649, 1363, -2455 }, + { -5118, 3132, 1961, -1577 }, + { -5196, 3379, -182, -1378 }, + { -6420, 4486, 2397, -1993 }, + { -5030, 5046, 1292, -1118 }, + { -4559, 2573, -927, -1406 }, + { -3501, 3730, 691, -4930 }, + { -4364, 2758, 1007, -3909 }, + { -4026, 2839, -1559, -2340 }, + { -5037, 4053, 836, -1571 }, + { -4727, 5136, 1110, -3588 }, + { -5245, 2799, -999, -2164 }, + { -4954, 1501, 422, -3963 }, + { -5994, 2726, 1462, -2833 }, + { -5621, 5159, 2038, -2512 }, + { -4991, 2291, 1917, -3151 }, + { -5469, 4382, -148, -2978 }, + { -5858, 1983, 807, -2720 }, + { -4709, 3556, 952, -467 }, + { -2489, 2362, 1714, -4230 }, + { -4717, 5004, -1180, -3672 }, + { -5914, 3653, 1359, -1317 }, + { -5506, 2995, 780, -1059 }, + { -5287, 3945, 2480, -2293 }, + { -3849, 4358, 322, -1770 }, + { -3911, 3570, 252, -3185 }, + { -3660, 5128, 158, -3719 }, + { -4599, 3277, -503, -2727 }, + { -3673, 3760, -1252, -3339 }, + { -5161, 2337, 388, -1943 }, + { -3529, 2216, 2156, -3080 }, + { -4309, 4331, 1808, -1460 }, + { -4782, 3820, 480, -2504 }, + { -4166, 3544, -378, -1567 }, + { -5572, 2466, -418, -2909 }, + { -6096, 2930, 119, -1878 }, + { -5963, 3554, 1011, -2233 }, + { -6433, 4335, 935, -2930 }, + { -5004, 3314, -1352, -3430 }, + { -6042, 3463, -1008, -3940 }, + { -4671, 2214, -640, -5040 }, + { -2795, 3759, 1412, -3803 }, + { -3647, 4436, 729, -515 }, + { -3594, 1033, 56, -4148 }, + { -2908, 3027, 2889, -3485 }, + { -3338, 2234, 313, -4285 }, + { -3825, 4497, -561, -2634 }, + { -6167, 3012, -48, -3149 }, + { -4828, 3515, -969, -4475 }, + { -5789, 2757, -539, -4173 }, + { -2452, 3067, 564, -4249 }, + { -4921, 1358, 1331, -2889 }, + { -3127, 4239, -1045, -1523 }, + { -4780, 2326, -1118, -3446 }, + { -3908, 5546, 152, -2622 }, + { -6972, 2976, 337, -2809 }, + { -4839, 4613, -35, -4077 }, + { -1408, 4822, -1149, -4997 }, + { -981, 4979, -912, -6304 }, + { -2098, 5689, -888, -2878 }, + { -3343, 4814, -657, -4434 }, + { -2461, 3601, -967, -4869 }, + { -2652, 3944, 87, -5520 }, + { -1104, 6076, 174, -6407 }, + { 355, 5370, -1721, -5869 }, + { 1242, 4497, -1107, -5091 }, + { -89, 4002, -1491, -5182 }, + { 1059, 5693, -1591, -4905 }, + { 1323, 4682, -2078, -4768 }, + { 818, 3996, -549, -5468 }, + { -287, 4529, 929, -5543 }, + { -919, 5519, -2791, -2844 }, + { -1407, 5679, -3289, -3974 }, + { -189, 6530, -3547, -4002 }, + { -900, 7039, -3371, -4855 }, + { -2983, 7211, -363, -4835 }, + { -814, 6503, -104, -5106 }, + { -2386, 6896, 809, -4919 }, + { 845, 4492, 352, -6621 }, + { -1998, 7237, -1646, -4231 }, + { -3380, 6251, 471, -4577 }, + { -1908, 7059, 84, -5726 }, + { -340, 6346, -803, -6265 }, + { -2279, 5834, -47, -4633 }, + { -1532, 5286, -1748, -1901 }, + { -2757, 6188, -453, -3415 }, + { -1255, 6405, -2043, -6357 }, + { 918, 5581, -121, -5667 }, + { 1840, 5336, -821, -5034 }, + { -2475, 4992, -1825, -3104 }, + { -2413, 5606, -1789, -4298 }, + { 132, 5128, -2389, -4442 }, + { 223, 6400, -2653, -4742 }, + { -673, 5012, 680, -4582 }, + { -1657, 6624, -349, -3596 }, + { -755, 6289, -1860, -3978 }, + { -572, 6894, -1946, -5207 }, + { -1141, 4756, -2665, -5586 }, + { -1073, 4269, -431, -4030 }, + { 186, 5761, 916, -5868 }, + { -1907, 4836, 1017, -5106 }, + { -963, 3363, -1248, -6348 }, + { -3262, 4774, -1818, -5858 }, + { 847, 3812, -2538, -4302 }, + { -1223, 5903, 1360, -5479 }, + { -1094, 6923, -1244, -2381 }, + { 267, 6276, -709, -2846 }, + { -157, 5840, 1124, -4266 }, + { 889, 3206, -910, -5305 }, + { -1736, 3344, 582, -4838 }, + { -2357, 5676, -2695, -6277 }, + { -1916, 6901, -986, -5397 }, + { -3062, 6028, -695, -5687 }, + { 1836, 3566, -1357, -5226 }, + { -2176, 4938, 646, -3872 }, + { -2199, 3055, -208, -6124 }, + { -236, 3032, -821, -5325 }, + { -3989, 7277, -565, -3899 }, + { -595, 4362, 74, -5975 }, + { 684, 5874, -841, -4424 }, + { -2731, 6305, -2389, -5465 }, + { -5775, 1325, -56, -2528 }, + { -7029, -534, -1890, -3278 }, + { -5798, -15, -2734, -2210 }, + { -5504, -1198, -353, -3659 }, + { -5079, 960, -894, -4336 }, + { -6073, -36, -133, -3014 }, + { -5782, -259, -1025, -3986 }, + { -6843, 1262, -807, -1639 }, + { -5263, -918, -3290, -579 }, + { -4840, 461, -2158, -533 }, + { -6014, -50, -620, 504 }, + { -5843, 241, -1359, -282 }, + { -5898, 577, 769, -3271 }, + { -6833, -946, -466, -3347 }, + { -6026, 1459, -512, -729 }, + { -7361, 747, -388, -1110 }, + { -6391, 2142, -1160, -2513 }, + { -6995, 304, 498, -2673 }, + { -6757, 679, -386, -433 }, + { -5222, 1688, -1093, -1032 }, + { -5019, 575, 184, -3627 }, + { -4237, 628, -3507, -1243 }, + { -7479, -456, -1722, -1486 }, + { -6464, 713, -1273, -1153 }, + { -6255, 1682, -606, -3607 }, + { -7033, 1497, -71, -1955 }, + { -6694, 1556, -1721, -3214 }, + { -6114, -356, 813, -2575 }, + { -5308, 632, -1851, -1636 }, + { -5742, -911, -1733, 383 }, + { -6083, -387, -2313, -879 }, + { -6535, -530, -1505, -2083 }, + { -4896, 1223, -2750, -1816 }, + { -6392, -463, -3247, -2093 }, + { -5373, 1264, -2706, -3042 }, + { -3894, -1390, -1020, -891 }, + { -6179, 1168, -1966, -1922 }, + { -5162, 1668, -1617, -1916 }, + { -6453, 920, -1169, -2432 }, + { -6130, 2005, -536, -1519 }, + { -6552, -98, -518, -1938 }, + { -7528, 355, -1101, -1772 }, + { -5745, 610, -247, -1360 }, + { -7003, 177, -2064, -1958 }, + { -6956, -570, -2220, -4225 }, + { -7830, 791, -1394, -2774 }, + { -7634, 480, -3171, -4224 }, + { -7913, 1154, -350, -2381 }, + { -5063, 1704, -1804, -2977 }, + { -4887, -524, -2703, 188 }, + { -5551, 406, -1620, -3063 }, + { -7109, 1342, 381, -3021 }, + { -6846, 631, -458, -3398 }, + { -4606, -605, 11, -3930 }, + { -8134, -225, -1738, -2648 }, + { -7043, 402, -2734, -3059 }, + { -7417, 1825, -2545, -4389 }, + { -6971, -236, -1031, -665 }, + { -5752, 2111, -1632, -3808 }, + { -7660, -78, -624, -3135 }, + { -6358, 619, -1951, -3911 }, + { -8134, 408, -1935, -3695 }, + { -6335, 1911, -2368, -4505 }, + { -7116, 2163, -344, -2753 }, + { 2357, 4488, 2220, -5682 }, + { 1385, 3206, 2300, -5305 }, + { 1419, 2557, 5203, -3516 }, + { 262, 4315, 3920, -1847 }, + { 3316, 3187, 1612, -5609 }, + { 1729, 2350, 1673, -6068 }, + { 1603, 6126, 1467, -2839 }, + { -1339, 3316, 3691, -3530 }, + { -563, 4618, 3180, -4548 }, + { 463, 4624, 3111, -5614 }, + { 1246, 5455, 3356, -5720 }, + { 480, 2149, 5422, -2893 }, + { 1768, 4827, 913, -5579 }, + { -149, 5381, 4366, -3297 }, + { 985, 3672, 2644, -92 }, + { -258, 2911, 5817, -2213 }, + { 3428, 3289, 3351, -3541 }, + { -666, 3295, 4727, -2869 }, + { 35, 6641, 4160, -4052 }, + { 623, 6787, 3156, -4560 }, + { 2654, 4360, 4676, -4632 }, + { 1386, 5246, 4834, -4497 }, + { 3488, 4574, 3856, -5946 }, + { 383, 4481, 4168, -4110 }, + { 1753, 3652, 4288, -3326 }, + { 1344, 4905, 2508, -4660 }, + { 1580, 4106, 3104, -2224 }, + { 2027, 5038, 1683, -1554 }, + { 446, 3699, 5872, -3013 }, + { 4637, 4087, 3578, -5018 }, + { 2629, 3560, 5331, -4900 }, + { 1527, 6674, 2523, -4131 }, + { -1437, 2804, 2528, -4464 }, + { -229, 3355, 2016, -5537 }, + { 3666, 3418, 4374, -4581 }, + { 1192, 3799, 923, -6596 }, + { 2040, 2956, 448, -5322 }, + { 2468, 5768, 4029, -5869 }, + { 3438, 6516, 3529, -6667 }, + { 2737, 5495, 680, -5535 }, + { 3896, 5727, 1801, -4958 }, + { 4988, 4957, 3592, -6518 }, + { -542, 4416, 5794, -2787 }, + { 4136, 4354, 2064, -4696 }, + { 3067, 5936, 1207, -3396 }, + { 2789, 4966, 2405, -3854 }, + { 1731, 3270, 3251, -1063 }, + { 1767, 5537, 2084, -2349 }, + { 465, 3116, 4532, -837 }, + { 1499, 2627, 4610, -2212 }, + { 122, 3095, 3642, -3552 }, + { 2542, 2866, 2705, -6402 }, + { 3134, 4323, 698, -4785 }, + { 731, 1859, 3112, -5242 }, + { 2553, 2980, 3241, -4846 }, + { 1329, 5310, 1607, -6624 }, + { 2468, 1858, 3476, -1034 }, + { -172, 4996, 2000, -5562 }, + { 2621, 4220, 1574, -3386 }, + { -333, 1832, 3362, -4117 }, + { 2169, 6762, 3065, -6225 }, + { 2844, 5528, 3223, -4765 }, + { 526, 5175, 1644, -4267 }, + { 2922, 4426, 2414, -2610 }, + { 452, 1399, -4516, -2636 }, + { 2872, 1720, -4667, -1435 }, + { 1279, 702, -5424, -1984 }, + { 2187, 870, -5021, -1341 }, + { 583, -144, -4628, -2464 }, + { 3, 2237, -5284, -2827 }, + { -19, 1005, -5460, -1819 }, + { 2897, 2084, -5885, -515 }, + { -400, 3370, -5527, -2947 }, + { 1505, 2593, -5518, -1802 }, + { 1341, 4534, -5094, -1899 }, + { 3241, 3670, -5493, -1252 }, + { -1287, 921, -5994, -1675 }, + { 627, 408, -6652, -364 }, + { -260, 1127, -4849, -3247 }, + { 371, 3400, -5976, -2285 }, + { 1533, 1566, -6373, -610 }, + { 2462, 4274, -6184, -1254 }, + { 1782, 3363, -6222, -1381 }, + { 572, 4650, -5673, -2754 }, + { 2674, 3414, -4460, -2154 }, + { 3614, 3820, -6883, -398 }, + { 1136, -1, -5511, -1112 }, + { -1773, 1137, -5647, -2377 }, + { -753, 2104, -6085, -2565 }, + { -204, 3025, -4731, -1418 }, + { -1486, 1438, -4380, -216 }, + { 302, 858, -5786, -264 }, + { 3486, 1495, -5234, -783 }, + { 888, 2327, -3423, -3720 }, + { -259, 772, -6596, -1311 }, + { -1197, 2073, -5174, -1826 }, + { 1500, 3470, -4462, -2645 }, + { 3072, 1960, -3277, -2264 }, + { 1841, 952, -4324, -2340 }, + { 1994, 2200, -3940, -2923 }, + { -1782, 1699, -4667, -1075 }, + { -1464, 2906, -3468, -375 }, + { 366, 2380, -3747, 1467 }, + { -545, 1645, -4619, 376 }, + { 1724, 2350, -2374, -3512 }, + { 3184, 2628, -2996, -3275 }, + { 734, 2010, -6239, -1479 }, + { 524, 3756, -4496, -3263 }, + { 1492, 3570, -3494, -3600 }, + { -932, 618, -5389, -2894 }, + { -133, 2161, -4083, -3267 }, + { 786, 774, -3279, -3731 }, + { 1078, 803, -3843, -3007 }, + { -332, 3405, -3347, 40 }, + { -17, 6, -4005, -3690 }, + { -189, 4372, -4488, -2561 }, + { -450, 3846, -3790, -1370 }, + { 362, 2212, -5272, -15 }, + { -1529, 791, -6802, -2296 }, + { 2145, 4241, -4474, 376 }, + { 1813, 2426, -2932, -2726 }, + { -542, 4557, -3140, -1080 }, + { 1192, 3784, -4371, -20 }, + { 2784, 5188, -6399, -1394 }, + { 431, 4561, -3673, -1398 }, + { 1382, 3096, -4083, 1253 }, + { 1209, 4224, -2930, 1500 }, + { 2798, 2684, -6676, -606 }, + { -2396, 1510, -5381, -2713 }, + { -2625, 2542, -4032, -2880 }, + { -1231, 3967, -4098, -2886 }, + { -1393, 2374, -3862, -4525 }, + { -2495, 1665, -1637, -5445 }, + { -3854, 1759, -1750, -4944 }, + { -2373, 1668, -2856, -6251 }, + { -2668, 1981, -886, -4557 }, + { -2927, 4427, -3451, -6172 }, + { -1925, 2596, -4696, -2527 }, + { -3202, 2847, -3928, -5896 }, + { -3332, 1665, -5025, -3412 }, + { -3212, 3115, -4155, -4062 }, + { -1013, 3205, -5133, -3751 }, + { -2022, 4595, -3947, -5611 }, + { -3556, 1755, -3715, -2300 }, + { -1784, 4114, -2723, -1773 }, + { -3586, 4081, -2733, -4942 }, + { -1608, 3685, -4154, -4573 }, + { -3368, 4042, -4452, -6227 }, + { -1407, 3881, -5729, -3719 }, + { -2751, 3281, -5077, -4999 }, + { -3791, 2410, -4906, -5288 }, + { -730, 2303, -4217, -3755 }, + { -1812, 2311, -5492, -3709 }, + { -610, 4336, -3915, -3783 }, + { -2841, 4337, -4278, -4430 }, + { -1662, 4666, -4661, -3964 }, + { -589, 5209, -4923, -3682 }, + { -4155, 2234, -4076, -4218 }, + { -3951, 2770, -2665, -2805 }, + { -2302, 3228, -3717, -1908 }, + { -3129, 4373, -2264, -2851 }, + { -447, 1363, -3578, -4323 }, + { -2648, 4237, -3159, -3071 }, + { -4072, 3241, -3541, -4605 }, + { -4507, 3458, -2339, -3838 }, + { -1646, 997, -4926, -3970 }, + { -3025, 1614, -3940, -1242 }, + { -1337, 1756, -3163, -5529 }, + { -3203, 1865, -3282, -4354 }, + { -1646, 2118, -2203, -6018 }, + { 174, 1871, -2707, -4639 }, + { -2607, 1485, -4778, -4750 }, + { -2199, 3991, -3134, -4879 }, + { -2962, 3323, -2816, -2419 }, + { -5286, 2495, -4548, -5395 }, + { -2810, 3710, -2274, -4211 }, + { -330, 3006, -2993, -4678 }, + { -1187, 2411, -2743, -5196 }, + { -664, 4033, -3101, -5641 }, + { -1458, 3602, -2816, -5371 }, + { -4116, 4923, -3321, -5630 }, + { -4165, 2528, -2592, -4798 }, + { -2759, 3080, -2333, -5719 }, + { -5157, 3011, -5526, -6348 }, + { -3095, 2126, -5881, -4234 }, + { -4377, 3849, -3600, -6099 }, + { -1994, 4947, -5235, -4753 }, + { -1067, 600, -3258, -5133 }, + { -4992, 3302, -2208, -5051 }, + { -3377, 2981, -1655, -4815 }, + { -3325, 2446, -1787, -6116 }, + { -2341, 2737, -3240, -6347 }, + { -2258, -3732, 3710, -1235 }, + { -1558, -3849, 2694, -3012 }, + { -599, -4837, 3050, -2951 }, + { -2246, -5433, 2798, -1910 }, + { -2255, -4989, 3260, 270 }, + { -3026, -5353, 2693, -1036 }, + { -1151, -6097, 1097, -3782 }, + { -3391, -6012, 2130, -1303 }, + { -2850, -4422, 3375, -480 }, + { -1138, -3779, 1491, -4162 }, + { -551, -3892, 3787, -2082 }, + { -3221, -3676, 3144, -1202 }, + { -3023, -5196, 2650, 605 }, + { -1756, -5729, 2646, 321 }, + { -2693, -4409, 494, -4797 }, + { -1913, -4573, 3372, -1730 }, + { -1277, -3604, 4061, -993 }, + { -420, -4993, 1351, -4796 }, + { -3052, -5333, 1435, -1242 }, + { -602, -5034, 3869, -1141 }, + { -2436, -4680, 1665, -3019 }, + { -2657, -3658, 1459, -3391 }, + { -1220, -6246, 2749, -525 }, + { -3838, -4844, 2265, -1735 }, + { -1247, -5679, 3356, -1417 }, + { -917, -5448, 3342, 105 }, + { -1756, -6839, 2276, -2350 }, + { -412, -5206, 1764, -3539 }, + { -1439, -6915, 1442, -3750 }, + { -1381, -4439, 3863, -282 }, + { -3482, -4953, 2726, -336 }, + { -1376, -5931, 1714, -1987 }, + { -1716, -4405, 2608, 105 }, + { -1590, -5191, 2652, -2704 }, + { -2149, -6442, 2453, -1263 }, + { -3426, -3832, 2334, -1829 }, + { -2747, -5948, 2362, -173 }, + { -2435, -3267, 2966, -1710 }, + { -3979, -4282, 2705, -775 }, + { -356, -4238, 2544, -4343 }, + { -1363, -6471, 2817, -1836 }, + { -2878, -5117, 218, -3149 }, + { -3539, -5196, 1710, -2356 }, + { -2888, -4537, 2746, -1701 }, + { -1870, -4439, 1496, -4121 }, + { -1486, -3388, 3349, -2145 }, + { -3333, -4138, 1467, -2876 }, + { -345, -5340, 1012, -1190 }, + { -1672, -4992, 2289, -1029 }, + { -2146, -5528, 3038, -635 }, + { -316, -3656, 3426, -3152 }, + { -2695, -5812, 2336, -2050 }, + { -2067, -6052, 737, -3258 }, + { -2664, -4205, -350, -1266 }, + { -617, -5406, 80, -4853 }, + { -2418, -3825, 1853, -1326 }, + { -1961, -4339, 583, -4315 }, + { -1495, -5141, -133, -5205 }, + { -3208, -6440, 1691, -2069 }, + { -2632, -3633, 2325, -2761 }, + { -2624, -5670, 1252, -3676 }, + { -3687, -5608, 687, -2833 }, + { -3320, -5707, 16, -3877 }, + { -2738, -6112, 84, -5135 }, + { 2277, -5661, 3076, 843 }, + { 1555, -5769, 2821, -5236 }, + { 536, -6381, 603, -4910 }, + { 734, -4609, 3314, -4092 }, + { 1836, -4547, 3267, -4322 }, + { -13, -5976, 3752, -1607 }, + { 1423, -6318, 2336, 398 }, + { 365, -7779, 1498, -534 }, + { 2104, -8366, 2946, -1345 }, + { 143, -5545, 1898, -3756 }, + { 655, -6852, 1430, 148 }, + { 4, -6653, 2397, -59 }, + { 2346, -5996, 4562, -934 }, + { 1229, -7104, 2963, -598 }, + { -528, -7048, 2887, -1790 }, + { 1451, -6857, 3900, -1637 }, + { 554, -6018, 3336, 9 }, + { 3278, -5758, 4034, 129 }, + { 3541, -7145, 4905, -1575 }, + { 2339, -6907, 3464, -301 }, + { 2775, -7301, 1667, -3894 }, + { 539, -7887, 991, -4156 }, + { 2115, -7421, 3131, -3075 }, + { 2803, -8546, 2564, -5836 }, + { 2869, -5833, 1620, -4561 }, + { 2591, -7281, 3215, -4719 }, + { -1228, -8477, 706, -4782 }, + { 1967, -5243, 4813, -1940 }, + { 701, -7010, 2273, -3893 }, + { 915, -8470, 1918, -5620 }, + { -94, -6715, 156, -3873 }, + { 1074, -5607, 4389, -1017 }, + { 2739, -6551, 1227, -3521 }, + { 725, -7835, 2701, -1291 }, + { -493, -7475, 2263, -1075 }, + { -412, -6508, 2984, -744 }, + { 665, -5451, 3725, -2692 }, + { 1499, -8129, 3564, -2072 }, + { 2870, -6333, 4487, -2108 }, + { 706, -5007, 3911, -152 }, + { -482, -8660, 1483, -2900 }, + { 2481, -6596, 2518, -1715 }, + { 1403, -6414, 1398, -5387 }, + { 652, -6267, 583, -5942 }, + { 694, -7540, 646, -6272 }, + { 2275, -7614, 256, -5015 }, + { 1416, -9727, 1900, -3153 }, + { 2760, -6433, 3875, -3771 }, + { 2325, -11196, 2182, -5155 }, + { 1223, -11061, 1377, -5097 }, + { 108, -10603, 307, -4952 }, + { -118, -8268, 1650, -1572 }, + { 1839, -7943, 1755, -612 }, + { 2501, -9056, 981, -2969 }, + { 2902, -8476, 1491, -5780 }, + { 1995, -11175, 1585, -3643 }, + { 696, -8212, 828, -2474 }, + { 1526, -8649, 1380, -1210 }, + { 461, -7253, 3222, -2229 }, + { 2966, -8641, 4121, -3271 }, + { 833, -6039, 2361, -1086 }, + { 3565, -7312, 1980, -5427 }, + { 2850, -8671, 3760, -1846 }, + { 2643, -7281, 2163, -173 }, + { 3463, -3706, -3132, -923 }, + { 1315, -3825, -3443, 2 }, + { 2594, -4083, -3815, 670 }, + { 1826, -4291, -2741, -155 }, + { 868, -3749, -4175, -298 }, + { 2008, -4237, -3897, -517 }, + { 1242, -3493, -4335, -1335 }, + { -88, -4142, -3390, -1529 }, + { 2176, -3488, -3822, -975 }, + { 1706, -5188, -3415, -637 }, + { 2717, -6159, -2333, -882 }, + { 1276, -3978, -4361, 537 }, + { 2471, -5556, -2866, -208 }, + { 799, -4673, -4086, 56 }, + { 1901, -4786, -3533, 270 }, + { 3036, -3902, -3606, -333 }, + { 2249, -3317, -4319, -144 }, + { 2594, -4207, -2105, -2930 }, + { 4008, -4774, -2626, -902 }, + { 1038, -3659, -3496, -2454 }, + { 2725, -3597, -3298, -1535 }, + { 1662, -5803, -2813, 175 }, + { 705, -3757, -3441, -1484 }, + { 1860, -5987, -2821, -886 }, + { 3786, -4918, -2199, -1929 }, + { 3683, -4235, -2547, -1287 }, + { 2531, -4896, -2956, -1593 }, + { 1005, -5585, -3324, -180 }, + { 1625, -5229, -1756, -3642 }, + { 1494, -5041, -2989, -2685 }, + { 2718, -4655, -3224, -867 }, + { 2374, -6640, -1745, -2975 }, + { 2133, -6436, -2477, -1499 }, + { 1833, -4418, -3523, -1512 }, + { 1128, -4910, -2658, -1106 }, + { 689, -4777, -2831, -2085 }, + { 3593, -5280, -2627, -315 }, + { 3264, -3771, -2673, -1861 }, + { 3202, -5602, -2409, 402 }, + { 552, -4618, -2221, -3002 }, + { 3095, -5356, -2666, -1083 }, + { 3401, -4609, -3146, 45 }, + { 3051, -4662, -2192, -2232 }, + { 2798, -5552, -2462, -1941 }, + { 2354, -5815, -2223, -2619 }, + { 192, -3708, -2807, -2658 }, + { 1886, -4226, -1862, -3529 }, + { 2526, -3976, -2819, -2332 }, + { 1577, -3870, -2711, -2806 }, + { 1288, -5588, -3382, -1403 }, + { 2711, -5399, -1564, -3253 }, + { 1459, -5492, -2222, -322 }, + { 2823, -5091, -2886, 776 }, + { 3559, -5821, -2109, -1360 }, + { 1587, -6331, -2760, -1909 }, + { 2139, -5213, -2874, -2120 }, + { 1318, -4337, -3695, -2098 }, + { 821, -4471, -1849, -565 }, + { 3329, -4782, -1725, -89 }, + { 582, -4914, -4105, -1119 }, + { 417, -4144, -4072, -2529 }, + { -199, -3803, -2765, -4042 }, + { 2731, -4283, -2143, 1 }, + { 2911, -6187, -1951, -2116 }, + { 1573, -6094, -493, -2838 }, + { 2081, -6927, -864, -3211 }, + { 1058, -7826, 79, -364 }, + { 3147, -5570, -684, -978 }, + { 3572, -5856, 1060, 1824 }, + { 1143, -6702, -1478, 338 }, + { 2341, -7220, -88, 260 }, + { 3639, -6861, 668, 815 }, + { 2227, -6268, -1706, 446 }, + { 3390, -6082, -353, 1302 }, + { 1123, -7556, -1237, -430 }, + { 1729, -7742, 729, -218 }, + { 1457, -6774, 587, 579 }, + { 505, -6919, -569, 371 }, + { 1106, -7245, 78, 158 }, + { 2755, -6745, -1122, 338 }, + { 3069, -6040, -1415, 986 }, + { 2174, -7064, -1430, -283 }, + { 1390, -8626, -446, -3031 }, + { 3534, -6890, -431, 547 }, + { 2267, -9618, 475, -2994 }, + { 3672, -7673, 75, -115 }, + { 2131, -7560, -1206, -750 }, + { 2972, -7477, -685, -262 }, + { 1604, -6637, -672, 699 }, + { 1666, -7577, -577, -240 }, + { 1591, -6554, -2158, -94 }, + { 2348, -6286, -353, 1123 }, + { 2017, -8810, -412, -1805 }, + { 2892, -6713, -1765, -554 }, + { 2500, -6828, -1995, -1197 }, + { 3877, -6639, -224, -1655 }, + { 2392, -7872, -91, -333 }, + { 3562, -7370, -532, -2836 }, + { 2552, -7614, 164, -1805 }, + { 990, -6104, 218, 438 }, + { 910, -7861, 312, -1195 }, + { 1472, -6327, 372, -640 }, + { 1576, -7143, -1983, -843 }, + { 422, -7625, -457, -278 }, + { 1797, -8532, 405, -1011 }, + { 1088, -7396, -238, -2277 }, + { 3209, -6753, -1431, -2072 }, + { 2617, -6839, 100, -2573 }, + { 2575, -8573, -387, -3188 }, + { 3618, -6971, -1190, -321 }, + { 2205, -7361, -1695, -2008 }, + { 2985, -6297, 1464, 1179 }, + { 2804, -7310, 1053, 338 }, + { 1362, -6074, -1163, -840 }, + { 3336, -6325, -1794, 21 }, + { 2836, -8109, 818, -329 }, + { 2791, -5879, 560, 1546 }, + { 2392, -6064, 135, 100 }, + { 1838, -6194, 596, 1085 }, + { 1926, -7515, -414, -4901 }, + { 3225, -7298, -1202, -1189 }, + { 3960, -7558, -659, -719 }, + { 3442, -6647, -1692, -1095 }, + { 3381, -6441, 262, -886 }, + { 1431, -8150, -1186, -1406 }, + { 340, -8498, -150, -899 }, + { 3004, -8149, -260, -953 }, + { 2749, -6611, 563, 873 }, + { -6647, -1325, -4517, -4691 }, + { -6005, -1657, -4089, -3797 }, + { -3157, 588, -5213, -3068 }, + { -3311, -1425, -6329, -3726 }, + { -5866, -819, -3857, -2744 }, + { -5001, -1799, -1075, -4621 }, + { -5330, -2650, -2672, -4664 }, + { -4930, -539, -2363, -4010 }, + { -2984, 10, -3863, -5749 }, + { -1055, -2106, -3713, -4267 }, + { -5476, -502, -4279, -6504 }, + { -5231, -1543, -5018, -6425 }, + { -5134, -363, -3165, -5109 }, + { -3953, -771, -4107, -6393 }, + { -2159, -563, -3652, -5342 }, + { -3888, -2321, -919, -5057 }, + { -1236, -597, -4235, -4193 }, + { -4053, 675, -3083, -6174 }, + { -2793, -1089, -5396, -3460 }, + { -3000, -44, -2209, -6575 }, + { -3336, -1531, -4313, -5160 }, + { -2127, 128, -4851, -3692 }, + { -3321, 136, -2067, -5660 }, + { -5215, 1404, -4374, -4356 }, + { -2747, 400, -6340, -3691 }, + { -3926, -599, -5361, -5006 }, + { -2875, -2592, -5143, -4092 }, + { -4991, -1958, -5322, -4891 }, + { -4965, -1318, -6652, -5333 }, + { -4920, -1691, -3388, -5561 }, + { -3644, -3354, -2688, -5982 }, + { -5076, -919, -4563, -2984 }, + { -6114, 250, -3884, -3915 }, + { -4014, 744, -3973, -1924 }, + { -5543, -1041, -5557, -3847 }, + { -4711, -1352, -5649, -2603 }, + { -3362, 775, -5305, -4879 }, + { -5001, 107, -3554, -2888 }, + { -6258, -1651, -6356, -6566 }, + { -4529, 407, -5003, -3865 }, + { -5154, 550, -5278, -5465 }, + { -4195, -467, -1894, -3129 }, + { -5022, 1127, -3349, -3314 }, + { -6075, 1250, -4313, -5641 }, + { -2677, -2283, -2312, -5903 }, + { -4113, 193, -1195, -4833 }, + { -3940, -1048, -1389, -5079 }, + { -3703, 917, -4043, -4451 }, + { -3366, -4231, -1534, -5488 }, + { -3326, -3583, -2091, -4903 }, + { -5144, 1254, -2532, -4949 }, + { -5982, -870, -2545, -4555 }, + { -3925, -157, -5367, -2281 }, + { -6419, -746, -5668, -4371 }, + { -5787, 518, -7096, -5805 }, + { -4258, 954, -6453, -4321 }, + { -4771, -695, -4158, -1639 }, + { -7078, -760, -5195, -5877 }, + { -7348, 83, -4101, -4586 }, + { -2430, 184, -2874, -1679 }, + { -2284, -3943, -2924, -5034 }, + { -1804, -1785, -3002, -4710 }, + { -4399, -2772, -1815, -4637 }, + { -6340, -2626, -2824, -5191 }, + { -4998, -5168, -3480, 1905 }, + { -3958, -5492, -1599, 1579 }, + { -2471, -3755, -276, 3182 }, + { -3033, -5779, -1063, 1554 }, + { -2936, -4829, -1290, 2386 }, + { -1835, -5073, -3051, 1299 }, + { -1724, -3771, -3935, 2324 }, + { -5070, -2550, -3692, 768 }, + { -4326, -5333, -297, 1878 }, + { -3472, -5619, -3094, 992 }, + { -3027, -4384, -3038, 2265 }, + { -3201, -5332, 67, 2200 }, + { -1681, -4373, -1947, 2461 }, + { -3221, -3329, -4238, 2564 }, + { -1262, -2968, -2915, 3227 }, + { -3419, -1878, -3373, 2110 }, + { -2244, -5583, -2012, 1288 }, + { -1971, -5266, -990, 1812 }, + { -2975, -2778, -452, 4063 }, + { -2198, -1165, -3298, 2965 }, + { -4782, -4894, -4767, 664 }, + { -6002, -3950, -2806, 2025 }, + { -3142, -3162, -2859, 3295 }, + { -3262, -3340, -4123, 1596 }, + { -4014, -3918, -1955, 3361 }, + { -1700, -3463, -1346, 3449 }, + { -4245, -4445, -4743, 1644 }, + { -4180, -3969, -401, 3281 }, + { -2782, -5240, -4117, 1156 }, + { -5744, -4040, -1439, 3470 }, + { -5063, -4663, -323, 3172 }, + { -4531, -3319, -844, 3988 }, + { -6226, -5125, -2064, 2976 }, + { -3115, -3267, -1531, 3898 }, + { -4628, -4421, -2864, 2808 }, + { -4559, -2989, -3442, 2024 }, + { -1775, -4487, -656, 2477 }, + { -2664, -1865, -1884, 4081 }, + { -1828, -2575, -3894, 3378 }, + { -6441, -3677, -2025, 1677 }, + { -4141, -2156, -1191, 3474 }, + { -4802, -1623, -1727, 2160 }, + { -5474, -2745, -1475, 2498 }, + { -3664, -1056, -1975, 2491 }, + { -4672, -3062, -2235, 2933 }, + { -4205, -5960, -2849, 1517 }, + { -4995, -5708, -1739, 1805 }, + { -4892, -6080, -4793, 872 }, + { -4270, -4172, -4263, 2185 }, + { -4687, -1470, -2905, 1023 }, + { -6446, -5017, -3919, 1000 }, + { -6046, -5538, -3943, 2006 }, + { -6028, -3750, -3953, 771 }, + { -5959, -4582, -5024, 824 }, + { -5818, -2576, -2249, 1326 }, + { -5659, -5345, -1119, 2500 }, + { -3346, -4155, 606, 2749 }, + { -5680, -4827, -2501, 1838 }, + { -6193, -2543, -1295, 840 }, + { -6871, -4925, -3512, 1801 }, + { -5605, -1788, -1895, 779 }, + { -3922, -5712, -4644, 510 }, + { -4745, -3869, -4533, 99 }, + { -2984, -4907, -399, 1497 }, + { 1847, -478, 3061, -5812 }, + { 4450, -1116, 3609, -6570 }, + { 3139, 99, 3007, -5532 }, + { 2590, -3782, 3138, -4770 }, + { 1881, 1204, 5778, -3404 }, + { 3631, 2060, 5566, -5038 }, + { 3461, 1961, 5167, -3800 }, + { 2947, 273, 4536, -4389 }, + { 4453, -1730, 5788, -4370 }, + { 4032, 1805, 2666, -4534 }, + { 3487, -944, 2313, -6028 }, + { 1313, 34, 4210, -4067 }, + { 5632, -1502, 5825, -5855 }, + { 7736, -547, 4879, -5476 }, + { 4906, -1512, 4760, -5760 }, + { 3843, 447, 1091, -4958 }, + { 2982, -1135, 5442, -4386 }, + { 3579, 271, 3031, -6770 }, + { 3932, -211, 4688, -5507 }, + { 4411, 1720, 2387, -5584 }, + { 5379, -479, 4575, -6280 }, + { 3613, -362, 2012, -4885 }, + { 3744, -2013, 4493, -5073 }, + { 5693, 109, 4379, -3362 }, + { 5475, -621, 5317, -3985 }, + { 6411, -673, 5708, -4752 }, + { 4933, -796, 7262, -4290 }, + { 2804, 444, 6276, -3655 }, + { 4120, -517, 6078, -4531 }, + { 5119, 841, 3486, -3910 }, + { 4738, 1539, 3525, -2970 }, + { 5086, 370, 5895, -5640 }, + { 4235, 2716, 4589, -5044 }, + { 3691, 682, 6199, -4700 }, + { 6111, -570, 6271, -6528 }, + { 2611, 1277, 3756, -4802 }, + { 4395, 970, 3807, -5879 }, + { 5225, 2299, 3242, -4333 }, + { 5144, 1778, 4946, -5545 }, + { 2989, -3016, 3247, -5495 }, + { 2983, 920, 2071, -6059 }, + { 5270, -903, 4434, -2350 }, + { 6415, -585, 3970, -3554 }, + { 3866, -197, 5216, -2884 }, + { 3767, -1298, 6702, -3315 }, + { 6299, 2620, 5284, -6824 }, + { 6654, 646, 3653, -4927 }, + { 4770, 3047, 5160, -6287 }, + { 5364, 434, 2919, -5207 }, + { 2998, 1344, 4801, -2456 }, + { 3896, 1013, 3773, -1864 }, + { 2115, 655, 2999, -6344 }, + { 5170, -981, 2849, -4464 }, + { 2735, -2159, 2717, -5776 }, + { 2430, -1952, 4392, -4559 }, + { 6143, -1180, 3659, -4746 }, + { 4978, -1483, 1726, -4875 }, + { 3486, -2383, 3306, -4301 }, + { 1434, -1372, 4171, -4770 }, + { 3354, -2627, 1525, -5093 }, + { 6790, 2386, 3995, -5909 }, + { 1475, -2674, 3451, -4204 }, + { 1999, -3494, 3693, -5556 }, + { 4764, -2848, 2856, -5589 }, + { -3677, 5131, 2827, -2934 }, + { -2844, 7078, 2852, -3580 }, + { -3902, 6434, 4118, -1911 }, + { -1769, 7530, 3492, -3541 }, + { -1937, 5679, -447, -1127 }, + { -2456, 4680, 4196, -2407 }, + { -2778, 8241, 1698, -4288 }, + { -2876, 6104, 5182, -2387 }, + { -2802, 7341, 4463, -2938 }, + { -1025, 6267, 4752, -3201 }, + { -2349, 5413, 2041, -3794 }, + { -2252, 8225, 2856, -4269 }, + { -1465, 4967, 4976, -2500 }, + { -636, 7565, 3517, -4233 }, + { -1905, 5618, 3904, -2942 }, + { -302, 6816, 3343, -3316 }, + { -2210, 4156, 2817, -3511 }, + { -717, 6568, 1863, -2951 }, + { -3873, 5682, 2164, -575 }, + { -2878, 5835, 440, -2597 }, + { -3228, 7701, 2610, -2514 }, + { -3608, 8888, 3377, -2468 }, + { -2582, 9717, 2519, -3126 }, + { -5238, 6202, 2866, -2831 }, + { -3428, 7370, 3056, -335 }, + { -1681, 8836, 1210, -2010 }, + { -3276, 6724, 1156, -3930 }, + { -894, 8149, 827, -1258 }, + { -2965, 8631, 2549, -1320 }, + { -3961, 6902, 3581, 55 }, + { -1894, 7745, 1750, -841 }, + { -821, 6844, 850, -676 }, + { -608, 6948, -4, -1376 }, + { 615, 6524, 1089, -1147 }, + { -2972, 5668, 1091, -489 }, + { -157, 4649, 2904, -413 }, + { 673, 5121, 1498, -66 }, + { -390, 5902, 1611, -245 }, + { -2349, 5478, 4772, -1320 }, + { 88, 6798, 1972, -1859 }, + { -1213, 5120, 2991, 200 }, + { -2347, 6040, 2839, 376 }, + { -578, 5976, 3364, -1796 }, + { -1391, 5872, 3002, -965 }, + { -564, 4496, 3946, -1186 }, + { -2299, 6386, 3135, -2176 }, + { -2131, 5641, 2011, 1223 }, + { -772, 5807, 1124, 895 }, + { -2837, 6758, 2297, -740 }, + { -3091, 6298, 1415, -2126 }, + { -4197, 6036, 1843, -3022 }, + { -41, 6459, 92, 344 }, + { -2241, 6860, 2095, -4396 }, + { -1931, 7088, 2117, -2135 }, + { -2375, 4422, 1688, -3169 }, + { -1742, 6674, 1538, -119 }, + { -4818, 7749, 4192, -1577 }, + { -2004, 5672, 193, -430 }, + { -3825, 6042, 2128, -1898 }, + { -1108, 8033, 2119, -3013 }, + { -2370, 5453, 1721, 266 }, + { -1570, 7134, 614, -2638 }, + { -1519, 8752, 3503, -4330 }, + { -2050, 3845, 2907, -1126 }, + { 5085, 4412, -335, -1923 }, + { 3618, 1423, -613, -4012 }, + { 4481, 3729, 589, -4631 }, + { 4270, 3216, -1763, -3168 }, + { 4241, 1796, -1701, -2796 }, + { 4787, 2338, -487, -3639 }, + { 2915, 3429, -621, -4753 }, + { 5175, 1660, -1265, -3223 }, + { 4280, 4057, -684, -4079 }, + { 4980, 4419, -1455, -2719 }, + { 5436, 2464, 387, -4197 }, + { 4507, 4018, 1121, -3314 }, + { 6020, 2401, -413, -3201 }, + { 4200, 3789, -333, -2813 }, + { 5229, 2493, -1194, -1878 }, + { 5851, 2695, -492, -2292 }, + { 5743, 3288, -697, -1221 }, + { 5692, 2612, 979, -2227 }, + { 5085, 2067, 1046, -1214 }, + { 3163, 2240, -2098, -3435 }, + { 5228, 1898, 145, -2397 }, + { 5860, 3976, -418, -2872 }, + { 6008, 3399, 1027, -3506 }, + { 4126, 2035, 1865, -893 }, + { 5375, 3596, 511, -2362 }, + { 1937, 1493, -852, -122 }, + { 3473, 4849, 547, -2603 }, + { 4631, 2977, 1141, -1768 }, + { 6149, 3050, -71, -1886 }, + { 4069, 4353, -289, -1429 }, + { 2884, 1225, -1388, 365 }, + { 5485, 2518, -235, -571 }, + { 1216, 4375, 1443, 398 }, + { 4988, 3106, 107, -1435 }, + { 4511, 2801, 307, -444 }, + { 3235, 4386, 327, -676 }, + { 2055, 3708, 1657, -305 }, + { 5839, 2374, 290, -1385 }, + { 5110, 3305, 1936, -4206 }, + { 6416, 2920, 338, -2736 }, + { 3350, 2824, -1269, -3881 }, + { 4840, 1815, 464, 186 }, + { 2399, 3332, 238, 1238 }, + { 3516, 1363, 1582, 688 }, + { 3582, 1874, 154, -4770 }, + { 3261, 2878, 886, 283 }, + { 3877, 2658, -327, 884 }, + { 4151, 3436, 2173, -2923 }, + { 3592, 3674, 1281, -1295 }, + { 4561, 3730, -1114, -1747 }, + { 4595, 3625, -558, -575 }, + { 2577, 2348, 2267, 120 }, + { 5242, 3299, 32, -3412 }, + { 4264, 3637, 709, -2320 }, + { 6556, 3570, -838, -2472 }, + { 5745, 4014, -940, -1973 }, + { 5629, 4475, 477, -3328 }, + { 5269, 3199, 1682, -3085 }, + { 4432, 2416, 1145, -3299 }, + { 4465, 2505, 2162, -2186 }, + { 4643, 4941, -88, -2885 }, + { 4568, 5231, 552, -3915 }, + { 5667, 3075, -1406, -2963 }, + { 5418, 5259, -771, -2818 }, + { -256, -7875, 511, -471 }, + { -1813, -7971, -424, -396 }, + { -306, -7006, 862, 282 }, + { -2306, -6422, -1440, 508 }, + { -245, -6787, 375, -100 }, + { -1309, -6065, -20, 779 }, + { -1656, -6047, -641, 1307 }, + { -1496, -6522, 964, 726 }, + { -2291, -6588, -202, 795 }, + { -762, -7522, 1454, -558 }, + { -2270, -7004, -834, -580 }, + { -1139, -7078, 259, 362 }, + { -2535, -7568, -1040, 49 }, + { -3786, -7280, 934, -476 }, + { -3336, -6368, 606, 1056 }, + { -3602, -6924, 52, 714 }, + { -2278, -6550, 1674, 204 }, + { -2855, -5765, 930, 1530 }, + { -2889, -7325, -215, 305 }, + { -2749, -6080, -237, 1452 }, + { -985, -6667, 1577, 400 }, + { -2036, -6083, 380, 1267 }, + { -2077, -7460, 380, -30 }, + { -1775, -7175, 1540, -386 }, + { -3065, -6927, 989, 168 }, + { -2836, -7602, 117, -3392 }, + { -1058, -6396, 593, -3078 }, + { -844, -6062, 999, -236 }, + { -3261, -6951, 1491, -720 }, + { -2186, -8484, 75, -1287 }, + { -2882, -7756, 456, -510 }, + { -1800, -6879, 960, -1183 }, + { -2554, -7241, 1614, -1474 }, + { -2608, -5305, 392, 851 }, + { -2973, -6562, -859, 858 }, + { -2640, -5989, 1031, -416 }, + { -977, -8366, 705, -1434 }, + { -1213, -7409, -77, -1390 }, + { -1335, -6657, 2125, -123 }, + { -2544, -6862, 1852, -737 }, + { -3235, -6422, 1752, -103 }, + { -1300, -7557, 939, -348 }, + { -3476, -7579, 202, -109 }, + { -2482, -6572, 753, 619 }, + { -2554, -8136, -648, -429 }, + { -1012, -7870, -3, -421 }, + { -3604, -6247, 32, -3102 }, + { -1486, -7271, 2013, -1021 }, + { -578, -6799, -523, 405 }, + { -2841, -5948, 1644, 911 }, + { -2411, -7473, 1084, -484 }, + { -2238, -6033, 294, -1059 }, + { -3459, -6470, -201, -790 }, + { -2027, -6009, 1833, 805 }, + { -1433, -8047, 1531, -1754 }, + { -3258, -7884, 763, -1422 }, + { -1544, -6928, -729, 478 }, + { -2314, -8415, 74, -3757 }, + { -3201, -5684, 95, -2214 }, + { -2423, -8694, 725, -3631 }, + { -3545, -7071, 1162, -1798 }, + { -294, -9662, 403, -2274 }, + { -2290, -5460, 1196, 402 }, + { -1603, -6713, 903, -2363 }, + { 4121, 2491, -3142, -2482 }, + { 4500, 3305, -3671, -1567 }, + { 5973, 3172, -1348, -534 }, + { 4830, 3379, -1549, 643 }, + { 5214, 3938, -2641, -2302 }, + { 4639, 4826, -5532, -847 }, + { 5639, 2731, -2170, -963 }, + { 6084, 3487, -3525, -1346 }, + { 5971, 3154, -2190, -2316 }, + { 5618, 4865, -6927, 116 }, + { 5345, 3568, -7391, 709 }, + { 5429, 5078, -3811, -1524 }, + { 6960, 2037, -3515, -1096 }, + { 7092, 2531, -4557, -588 }, + { 6061, 4247, -5651, -478 }, + { 4595, 3684, -4907, -827 }, + { 7497, 3213, -3048, -424 }, + { 5996, 2137, -3098, -1745 }, + { 6198, 5199, -2223, -2274 }, + { 6888, 2851, -2768, -1675 }, + { 6114, 4210, -2316, -954 }, + { 7127, 4242, -3041, -1408 }, + { 6126, 3668, -1517, -1427 }, + { 6245, 6129, -4225, -1186 }, + { 6816, 3213, -2101, -964 }, + { 5345, 5276, -2643, -847 }, + { 6592, 4665, -4338, 484 }, + { 6746, 3751, -3443, 124 }, + { 5453, 1980, -2738, 2606 }, + { 4662, 2179, -4226, -1059 }, + { 5571, 3208, -3554, 174 }, + { 5256, 4447, -1815, -1481 }, + { 5400, 2570, -1210, 235 }, + { 7056, 2549, -2674, 318 }, + { 4574, 4340, -2892, -130 }, + { 6203, 4587, -3273, -305 }, + { 5103, 1925, -2715, -2137 }, + { 3905, 4296, -1700, 247 }, + { 4421, 4605, -3299, 811 }, + { 5671, 1273, -3870, -924 }, + { 5486, 1805, -4901, 133 }, + { 6437, 2578, -1828, -106 }, + { 5530, 5253, -5058, 1223 }, + { 4816, 2025, -1215, 1443 }, + { 3457, 3525, -2456, 3217 }, + { 3316, 2595, -1108, 2459 }, + { 3068, 3810, -2207, 1926 }, + { 6351, 5436, -6470, 600 }, + { 6324, 4240, -5365, 2416 }, + { 4851, 4774, -4075, 1878 }, + { 4900, 3679, -5198, 1078 }, + { 8347, 3633, -4565, -171 }, + { 5244, 5718, -3853, 173 }, + { 3960, 3492, -2939, 2105 }, + { 6070, 3473, -2351, 161 }, + { 8228, 3034, -3360, -901 }, + { 7006, 3985, -1940, -1926 }, + { 7123, 4681, -4301, -878 }, + { 5122, 4097, -1851, -449 }, + { 6200, 2060, -2251, 1049 }, + { 7106, 3844, -7209, 2625 }, + { 7108, 3370, -6734, 533 }, + { 6859, 2849, -3992, 1360 }, + { 5458, 2278, -3253, 1131 }, + { -1072, -2109, 4783, -1073 }, + { -319, -2604, 4257, -2418 }, + { 2466, 1300, 3476, -314 }, + { 2847, -1502, 5296, -141 }, + { 1667, -1273, 5559, -2725 }, + { 2877, -3402, 6434, 204 }, + { 53, -2637, 5275, -1181 }, + { 1091, -2215, 5803, -1549 }, + { 2397, -922, 4327, 1182 }, + { 219, -3747, 4647, -1564 }, + { -29, -2705, 4812, 1277 }, + { 1499, -2608, 5648, 1407 }, + { 2139, -2399, 4202, 2791 }, + { -426, -2064, 5528, 151 }, + { 2560, -2803, 6179, -2806 }, + { 4537, -2479, 3797, 1095 }, + { 888, -3357, 5341, -415 }, + { 4460, -1814, 5388, -1227 }, + { 3920, -3268, 6364, -703 }, + { 3343, -4698, 4410, 784 }, + { 309, -1897, 6306, 1223 }, + { 958, -3318, 4254, -3167 }, + { -99, 1596, 6018, -1983 }, + { -429, -853, 6407, 878 }, + { 1170, -1322, 6290, -417 }, + { 2288, -505, 6303, -1999 }, + { 3312, -1674, 6749, -2494 }, + { -415, -3401, 4721, -371 }, + { -189, -1210, 4844, -2002 }, + { 888, -4142, 4377, 130 }, + { 2469, -4381, 5398, -2492 }, + { 2879, -2912, 5094, -2598 }, + { -717, -617, 5650, -685 }, + { 1470, -3863, 5352, -1684 }, + { 3935, -96, 3823, -730 }, + { 3769, -430, 3168, 694 }, + { 2556, 385, 3539, 512 }, + { 77, -1415, 5111, 2655 }, + { 2724, -2158, 6715, -822 }, + { 1832, 1001, 5385, -1900 }, + { 900, 2198, 4464, -559 }, + { 441, 69, 5921, -1743 }, + { -1161, 738, 6732, -308 }, + { 257, 2035, 4091, 736 }, + { 1607, 1288, 4355, -23 }, + { -13, 1316, 4180, 1672 }, + { 1511, 1336, 3057, 1435 }, + { 2189, -3813, 4530, 939 }, + { 3632, -706, 2646, 1375 }, + { 4266, -3761, 4241, 1077 }, + { 3101, -427, 5273, -1202 }, + { 2293, 276, 4810, -313 }, + { 3430, -1851, 3101, 2045 }, + { 3453, -2979, 5142, 942 }, + { 1683, -3281, 4802, 2002 }, + { 3954, -4715, 5611, 578 }, + { 1272, -155, 5085, 454 }, + { 128, -194, 5095, 1409 }, + { 820, 880, 5797, -2658 }, + { -1095, 656, 5774, 1095 }, + { 813, -1669, 4320, -3251 }, + { -119, 518, 6372, -651 }, + { 2922, -4299, 6115, -877 }, + { 4205, -4273, 4004, 2642 }, + { -1211, -3892, 224, 3127 }, + { -34, -4371, 1321, 2318 }, + { 77, -6326, 1201, 828 }, + { 3995, -3775, 1958, 3233 }, + { 178, -3301, 1985, 3318 }, + { 2330, -3801, 1033, 3195 }, + { 1413, -5536, 826, 1709 }, + { 2468, -3499, 3653, 3631 }, + { 741, -4617, 1723, 2008 }, + { 1246, -3043, 2978, 3949 }, + { -343, -4308, 2258, 2189 }, + { -682, -4640, 454, 2272 }, + { 1236, -4829, 2491, 1642 }, + { -512, -3766, 1182, 3052 }, + { 119, -3939, 3712, 971 }, + { -1145, -4624, 1360, 2281 }, + { 101, -4746, 2866, 1255 }, + { -1500, -5455, 539, 1637 }, + { -969, -5909, 1414, 1128 }, + { -1261, -4939, -231, 2022 }, + { -226, -5345, 1207, 705 }, + { 2712, -5109, 3205, 1866 }, + { -476, -5913, 273, 1208 }, + { -2039, -4464, 624, 2545 }, + { -2351, -3930, 2019, 2673 }, + { -2675, -4849, 1522, 1990 }, + { -1524, -3461, 1446, 3204 }, + { 477, -5314, 1710, 1577 }, + { 656, -3729, 2346, 2511 }, + { 550, -5917, 1975, 1040 }, + { 1728, -4704, 3067, 1058 }, + { -9, -5247, 506, 1760 }, + { -574, -5135, 1675, 1672 }, + { 2129, -3781, 3444, 2313 }, + { 1144, -4439, 2214, 2529 }, + { 1292, -4160, 3185, 1833 }, + { 2445, -3262, 2534, 3227 }, + { 2266, -4401, 2023, 2400 }, + { -587, -3602, 3408, 2067 }, + { -885, -4951, 3228, 1174 }, + { -728, -2711, 2807, 3552 }, + { 1019, -3043, 3195, 2954 }, + { 1888, -4615, 1140, 2454 }, + { 660, -5616, 754, 800 }, + { -1975, -5371, 1649, 1585 }, + { -1544, -5436, 2422, 1081 }, + { -422, -5882, 2390, 750 }, + { 1336, -5557, 2441, 1230 }, + { 136, -4001, 267, 2854 }, + { -522, -3289, 2226, 2728 }, + { -971, -4580, 2471, 708 }, + { 704, -5306, 3300, 1001 }, + { 325, -3464, 3555, 2398 }, + { 794, -3686, 848, 3169 }, + { 660, -3017, 4584, 3242 }, + { -1486, -3978, 2170, 1644 }, + { -1615, -4650, 2688, 1844 }, + { 750, -4578, 538, 2239 }, + { 1668, -5849, 1455, 1031 }, + { 3486, -4681, 2030, 2183 }, + { 2642, -5429, 1696, 1761 }, + { 4491, -4502, 3538, 2767 }, + { 3545, -4528, 3514, 2982 }, + { 3269, -3676, 2758, 3966 }, + { 5572, 1146, 209, -3379 }, + { 7459, 1053, 593, -1896 }, + { 4480, 200, -310, -4259 }, + { 5577, -939, 242, -3992 }, + { 8142, 442, 1257, -3083 }, + { 5442, 1261, 1424, -3236 }, + { 6260, -183, 3125, -2532 }, + { 7179, 889, 1618, -2548 }, + { 6416, 932, 2379, -2487 }, + { 7094, 2560, 961, -3392 }, + { 7322, 463, 2732, -3735 }, + { 6632, 1577, 1912, -3272 }, + { 6312, 1349, 3028, -3460 }, + { 6105, 386, 1213, -977 }, + { 5478, 1158, 1114, -486 }, + { 6493, 410, 1686, -2180 }, + { 6378, 1881, 1333, -2240 }, + { 5711, 812, 1958, -1300 }, + { 6844, 877, 730, -1189 }, + { 6824, -245, 2249, -2000 }, + { 7515, 1521, 1251, -3058 }, + { 6697, 1051, 1300, -1749 }, + { 6476, 1425, 811, -2773 }, + { 7350, 465, -76, -2849 }, + { 6975, 2095, 567, -2492 }, + { 4691, 1736, 2660, -2289 }, + { 7837, 1456, 340, -2767 }, + { 7930, 507, 838, -2074 }, + { 6106, 1502, 766, -1110 }, + { 4891, -659, 835, -3954 }, + { 7250, 141, 1369, -1523 }, + { 7651, 67, 1651, -2298 }, + { 7364, -305, 601, -3132 }, + { 7179, 193, 2491, -2871 }, + { 6504, -272, 2167, -1322 }, + { 4456, 983, 2300, -421 }, + { 4817, 457, 1695, 371 }, + { 6914, 555, 850, -3159 }, + { 5904, 1030, 202, -1959 }, + { 6258, 880, 2233, -4503 }, + { 6029, 10, 2130, -3600 }, + { 6449, 985, 1129, -3963 }, + { 6616, -18, -111, -3285 }, + { 4496, 775, 817, -4276 }, + { 6134, 2338, 1470, -2973 }, + { 6911, 152, 430, -1946 }, + { 4053, 991, 3218, -1193 }, + { 5435, 1285, 3124, -2412 }, + { 5507, 1836, 1935, -1988 }, + { 5240, 689, 2189, -2670 }, + { 6638, 1719, 606, -1799 }, + { 5556, -180, 129, -2595 }, + { 5644, 1918, 1281, -4316 }, + { 6410, 1088, -282, -3117 }, + { 6503, 1841, 312, -3514 }, + { 6947, 20, 1358, -3886 }, + { 5464, 2109, 2398, -3194 }, + { 5616, -407, 2140, -498 }, + { 6121, 2707, 2379, -4096 }, + { 7303, 1846, 2266, -4095 }, + { 5444, 470, 2718, -1553 }, + { 5817, -645, 3285, -1349 }, + { 5625, 1427, 1103, -1991 }, + { 6041, -806, 1196, -2943 }, + { 3050, -5722, 4070, -5460 }, + { 3420, -4386, 4078, -5155 }, + { 6020, -3982, 7268, -2689 }, + { 7502, -4317, 7894, -3973 }, + { 4156, -3558, 5247, -4316 }, + { 4725, -4401, 7290, -1540 }, + { 6688, -5122, 8216, -3210 }, + { 9176, -6576, 9276, -4963 }, + { 8706, -5708, 7987, -4621 }, + { 7060, -3535, 6532, -3308 }, + { 5600, -2719, 5363, -1568 }, + { 4661, -2803, 6263, -4716 }, + { 3673, -3636, 6147, -3433 }, + { 5305, -2585, 6073, -2638 }, + { 7614, -1962, 6079, -5266 }, + { 6760, -3366, 7382, -4322 }, + { 6385, -3883, 4797, -1353 }, + { 8182, -5120, 4298, -4641 }, + { 9130, -6198, 4975, -3063 }, + { 7421, -5436, 5576, -3713 }, + { 3483, -4898, 5443, -2745 }, + { 4907, -5643, 6390, -4105 }, + { 8119, -7008, 7992, -6764 }, + { 6528, -6122, 6967, -5590 }, + { 5890, -4190, 6624, -5688 }, + { 6815, -7934, 7275, -5456 }, + { 5434, -4306, 5169, -5378 }, + { 4364, -6436, 5376, -2604 }, + { 8152, -3404, 5913, -5048 }, + { 7983, -4863, 4262, -2461 }, + { 8023, -6188, 6238, -5062 }, + { 6753, -3692, 3935, -3723 }, + { 6826, -4760, 3284, -4051 }, + { 7224, -7423, 4492, -3875 }, + { 6904, -2590, 6587, -6248 }, + { 6106, -1944, 7345, -5506 }, + { 4956, -2990, 7808, -3146 }, + { 6908, -6885, 5949, -1288 }, + { 7162, -6058, 3419, -3401 }, + { 7015, -7080, 6907, -3018 }, + { 6971, -6832, 5646, -3273 }, + { 8014, -5546, 5471, -1544 }, + { 6792, -2220, 5105, -2879 }, + { 8494, -3974, 4408, -3999 }, + { 9591, -4866, 6027, -4558 }, + { 5264, -5161, 6101, -738 }, + { 5803, -6141, 5197, -5231 }, + { 4657, -6822, 3232, -5189 }, + { 4791, -5135, 3809, -4665 }, + { 6108, -5103, 2379, -3873 }, + { 4680, -3909, 3234, -5093 }, + { 5802, -3853, 3795, -4984 }, + { 4360, -7483, 4802, -3877 }, + { 5429, -7517, 5911, -3717 }, + { 6866, -2280, 4880, -4634 }, + { 10131, -4628, 4414, -4092 }, + { 10811, -5189, 7746, -5337 }, + { 5663, -8941, 5287, -5680 }, + { 8023, -5991, 7403, -2796 }, + { 9669, -6919, 6525, -4932 }, + { 7275, -3796, 4962, -2547 }, + { 8848, -4806, 5677, -3080 }, + { 8128, -4308, 7749, -6569 }, + { 4032, -5196, 2282, -6239 }, + { 6593, 700, -229, 304 }, + { 8260, 539, -66, -1259 }, + { 6605, 176, -814, -109 }, + { 8057, 0, -1, -136 }, + { 7382, -38, -484, -1129 }, + { 8373, -929, 682, -454 }, + { 7674, 690, -1278, 546 }, + { 7326, -517, 406, -1283 }, + { 7612, -1715, -1167, 1175 }, + { 8590, 441, -782, -710 }, + { 8572, -1202, -291, 260 }, + { 7308, -147, -1785, 414 }, + { 6787, -353, -672, 934 }, + { 5177, -133, 179, 82 }, + { 4161, -34, 447, 1497 }, + { 5997, -902, 1533, -121 }, + { 5727, -871, -1370, 945 }, + { 8386, -252, 293, -823 }, + { 6573, -1354, 682, 616 }, + { 7650, -2096, 725, 457 }, + { 8122, 78, 636, -1400 }, + { 8421, 428, -1620, 131 }, + { 7341, -1292, -717, 186 }, + { 7998, -49, -720, 266 }, + { 5987, -351, 669, 844 }, + { 7314, -1620, 250, -603 }, + { 7219, -1562, -572, 1994 }, + { 8682, -358, -290, -388 }, + { 5810, 155, -178, 1199 }, + { 7246, -12, 1042, -786 }, + { 7357, -923, 1468, -475 }, + { 7801, 621, -212, -724 }, + { 5346, -514, 1210, 1356 }, + { 8459, 36, -127, -779 }, + { 6878, -2429, 854, 1750 }, + { 7280, -1401, -1353, 2845 }, + { 7579, -2148, -1463, 2087 }, + { 6637, 946, -872, 750 }, + { 4807, -1100, 1289, 2602 }, + { 4495, 219, 1551, 1128 }, + { 7639, 506, 446, -1107 }, + { 6359, 188, 1009, -115 }, + { 6641, -1820, 1655, 723 }, + { 5394, -2382, 1604, 2542 }, + { 6021, -2644, 2396, 1407 }, + { 4698, 882, 245, 1525 }, + { 8103, 573, -798, -349 }, + { 8045, -519, 997, -1092 }, + { 7571, -122, 227, -338 }, + { 5347, -1200, 630, 1718 }, + { 7070, 790, 218, -544 }, + { 7440, 728, -527, -20 }, + { 6402, -355, 197, -736 }, + { 4031, 771, 866, 1895 }, + { 6009, 896, 445, -31 }, + { 5160, 1098, -856, 1784 }, + { 7980, -886, -1293, 1396 }, + { 6318, -1361, 2423, 252 }, + { 7547, -699, 133, 506 }, + { 8562, -2344, 940, 264 }, + { 5890, 1187, -1425, 2194 }, + { 6558, -645, -1311, 2621 }, + { 4634, -1671, 2075, 1623 }, + { 5614, 105, -816, 2376 }, + { 6646, 1558, -1365, 630 }, + { 6998, 1150, -2117, -990 }, + { 6555, 2311, -1093, -1783 }, + { 6682, 1430, -2391, -1940 }, + { 7861, 1555, -2977, -1188 }, + { 6745, 1723, -459, -2085 }, + { 7504, 1229, -1666, -2060 }, + { 7937, 671, -2128, -1529 }, + { 7139, 991, -735, -2632 }, + { 6867, 1592, -1303, -2324 }, + { 6401, 2230, -1732, -2508 }, + { 7201, 2184, -2169, -1988 }, + { 6636, 2190, -995, -2840 }, + { 7620, 2306, -2089, -651 }, + { 7584, 1875, -1438, -631 }, + { 9214, 1561, -2464, -1139 }, + { 6154, 1318, -1237, -2917 }, + { 7917, 2847, -1797, -1599 }, + { 8309, 2029, -2555, -465 }, + { 8204, 1282, -584, -2405 }, + { 8440, 1035, -1147, -1137 }, + { 7107, 1858, -60, -1568 }, + { 6781, 2912, -873, -1463 }, + { 7603, 1316, -319, -1249 }, + { 7833, 1335, -78, -1849 }, + { 7930, 1141, -1016, -695 }, + { 7883, 1610, -1017, -1314 }, + { 8069, 1409, -1811, -196 }, + { 8319, 1031, -582, -1590 }, + { 5948, 1537, -2153, -2373 }, + { 8684, 1171, -1871, -850 }, + { 8357, 2484, -2411, -1292 }, + { 6516, 2092, -193, -1167 }, + { 6112, 1697, 22, -525 }, + { 7161, 703, -602, -1879 }, + { 6047, 2351, -807, -219 }, + { 8072, 1854, -1817, -1553 }, + { 6956, 1304, 76, -1011 }, + { 6607, 1481, -544, -162 }, + { 6958, 2541, -265, -1938 }, + { 6416, 2514, -777, -850 }, + { 7272, 2110, -899, -1171 }, + { 7741, 2153, -283, -2614 }, + { 6482, 2041, -1758, -1221 }, + { 6762, 940, -1862, -2281 }, + { 5610, 1194, -1691, -1561 }, + { 7833, 2164, -823, -1952 }, + { 5460, 1438, -848, 1189 }, + { 6011, 1377, -771, -1557 }, + { 7679, 544, -1134, -2214 }, + { 7209, 1292, -2714, -1564 }, + { 5567, 1200, -404, -169 }, + { 5853, 1461, -1465, -518 }, + { 6782, 689, -844, -860 }, + { 7330, 1337, -1152, -71 }, + { 7189, 1506, -653, -685 }, + { 6860, 2116, -1403, -240 }, + { 8804, 1516, -1391, -1760 }, + { 7210, 2689, -1498, -989 }, + { 7030, 3022, -1441, -2083 }, + { 5649, 1836, -407, 525 }, + { 7451, 3099, -717, -2464 }, + { 7384, 1656, -2007, 398 }, + { 6504, 707, -1919, -134 }, + { -1851, 3639, -2279, -695 }, + { -4037, 1644, -77, 1329 }, + { -4025, 1960, -1565, -567 }, + { -3430, 2495, -795, 368 }, + { -4771, 2480, 993, 756 }, + { -3431, 2058, -2539, -971 }, + { -3802, 3418, 380, 217 }, + { -3074, 3350, -1652, -1056 }, + { -3705, 326, -1650, 1535 }, + { -3122, 1281, -1192, 1607 }, + { -4601, 1367, -968, 53 }, + { -3808, 958, 44, 2560 }, + { -2079, 2530, -1485, 1166 }, + { -3707, 343, -2889, 180 }, + { -5249, 1431, -31, 688 }, + { -4990, 125, -704, 1270 }, + { -2771, 1334, -2446, 746 }, + { -2292, 994, -1527, 2630 }, + { -1261, 3070, -2519, 268 }, + { -2544, 3890, -1057, -552 }, + { -4421, 255, -1980, 530 }, + { -2951, 454, -13, 3643 }, + { -2262, 1815, -370, 2880 }, + { -2383, 3657, -649, 576 }, + { -3541, -161, -1389, 2550 }, + { -4241, 1575, 1325, 2561 }, + { -2767, 4037, 1221, 1578 }, + { -3748, 2697, 1148, 1801 }, + { -4686, 2385, -220, 0 }, + { -1531, 1645, -2751, 1327 }, + { -45, 4032, -799, 2298 }, + { -2915, 2280, 709, 2495 }, + { -1199, 3278, -406, 2346 }, + { -2471, 116, -2706, 2060 }, + { -2440, 2173, -2894, -344 }, + { -3375, 2287, 1781, 3226 }, + { -2153, 3568, 1827, 2918 }, + { -862, 2267, -1626, 2527 }, + { -2698, 1135, 301, 4239 }, + { -2364, 2123, 1010, 3710 }, + { -2447, 3281, -81, 1408 }, + { -2660, 4735, 472, 258 }, + { -1053, 3097, 2682, 2398 }, + { -3366, -1037, -1152, -868 }, + { -643, 4242, 2212, 1259 }, + { 971, 3991, 934, 643 }, + { -1617, 2002, 2139, 2195 }, + { -4897, 972, 784, 1719 }, + { -1275, 2992, 1039, 3821 }, + { -392, 4973, -209, 1821 }, + { -1028, 4718, -1479, -137 }, + { 50, 3914, 553, 2210 }, + { 678, 4364, 359, 1303 }, + { -582, 4911, 514, 1671 }, + { 1276, 3914, -1252, 2934 }, + { -1496, 3984, 857, 2330 }, + { 772, 4744, -655, 2332 }, + { -799, 5283, -439, 624 }, + { 1341, 2937, 650, 2027 }, + { -1739, 4892, 1275, 1702 }, + { -892, 2596, -151, 3951 }, + { -3532, 1090, 1292, 32 }, + { 321, 3146, 2647, 1475 }, + { 264, 4199, -1591, 1317 }, + { -452, -2357, 2266, 4192 }, + { 3022, -1033, -2389, 5678 }, + { -1162, -1342, 3543, 4990 }, + { -474, -1477, -1223, 5016 }, + { -699, -2857, 900, 3835 }, + { -461, -2255, -117, 4626 }, + { 1204, -2062, -1211, 4403 }, + { 2192, -3035, -337, 3966 }, + { 108, -831, 279, 5643 }, + { 1457, -620, -2908, 5276 }, + { -2527, -78, 1085, 5460 }, + { -1978, -1918, -949, 4733 }, + { 32, 367, -1904, 5166 }, + { 1890, -1665, 440, 4752 }, + { -518, -348, 2816, 4891 }, + { 3695, -2490, -1374, 4603 }, + { 246, -1965, 3549, 3969 }, + { 1100, -3111, 656, 3737 }, + { -1379, 870, -414, 4575 }, + { 628, -357, -1227, 6179 }, + { -1129, -1318, -2457, 4576 }, + { -425, -98, -73, 6336 }, + { 367, -887, 2990, 4207 }, + { 2091, -1251, 2444, 3557 }, + { -1759, -1610, 2046, 5273 }, + { 3210, 1414, -20, 2616 }, + { 3303, -2636, 1005, 4237 }, + { -327, -3107, -640, 3687 }, + { -197, 764, 572, 5486 }, + { 646, -767, 1388, 5464 }, + { 104, 2742, -228, 3907 }, + { -236, 1829, -579, 4585 }, + { -2150, -474, -1525, 4006 }, + { -23, -2632, -2400, 3892 }, + { -12, -1739, -2910, 4867 }, + { -2310, -368, -102, 4583 }, + { -1991, -2061, 533, 4531 }, + { 3884, -1446, -153, 4393 }, + { 1568, 14, -289, 5268 }, + { -1376, -253, -2797, 3417 }, + { 3193, -2577, 2475, 3566 }, + { 3418, 617, 1350, 1857 }, + { 3792, -24, -272, 3370 }, + { 153, 1159, 2906, 2877 }, + { 511, 2162, 1548, 2741 }, + { 262, 819, -2791, 3734 }, + { 4232, -2015, 1486, 3477 }, + { 2943, -1110, -1014, 5480 }, + { 2842, 369, 703, 3476 }, + { 3011, 1634, -933, 3553 }, + { 4412, -1548, -942, 5021 }, + { -1405, 593, 2372, 5267 }, + { 2093, 2129, 896, 2365 }, + { 4845, -1980, 0, 3823 }, + { -2140, 81, 3278, 5637 }, + { 1484, 2665, -324, 3653 }, + { 10, 192, 1620, 5291 }, + { 2152, 738, -2269, 5000 }, + { 2102, 2748, -1652, 4707 }, + { 2855, -2131, -387, 5188 }, + { 1173, 676, 1338, 3277 }, + { 2340, -2329, -2064, 4095 }, + { 861, -2024, 1296, 5055 }, + { 2189, 3225, -695, 2626 }, + { 6196, -7079, 1943, -822 }, + { 4547, -4813, 3261, 1856 }, + { 4243, -6904, 3443, 448 }, + { 4581, -7503, 946, 506 }, + { 6626, -7754, 3427, 470 }, + { 3407, -9088, 3269, -1496 }, + { 4079, -6464, 2304, 777 }, + { 5621, -9336, 2684, -768 }, + { 5351, -6464, 5238, -214 }, + { 5961, -8007, 1724, -3091 }, + { 4213, -8067, 603, -246 }, + { 7208, -7403, 3168, -1738 }, + { 6098, -7700, 329, -1379 }, + { 6525, -6735, 4248, -1072 }, + { 6073, -6241, 2167, -2378 }, + { 4609, -9218, 3051, -1033 }, + { 6813, -7283, 1581, -1897 }, + { 6126, -6275, 2789, 681 }, + { 4423, -6538, 1621, -1692 }, + { 6272, -8298, 3167, -1855 }, + { 6172, -8558, 4498, -1169 }, + { 4844, -8588, 1647, -366 }, + { 6209, -8807, 1581, -369 }, + { 5389, -8059, 550, -192 }, + { 6654, -9775, 2504, -1063 }, + { 7103, -7998, 806, 530 }, + { 5662, -6736, 1565, -3620 }, + { 4165, -9564, 4191, -2131 }, + { 4526, -7181, 576, -2875 }, + { 4633, -8623, 2807, -4742 }, + { 3709, -7794, 1815, 34 }, + { 3634, -8622, 2313, -826 }, + { 6991, -8447, 2063, -3198 }, + { 7757, -9486, 2255, -558 }, + { 4149, -7778, 4728, -1696 }, + { 5767, -7427, 1113, 707 }, + { 4592, -6261, 2329, 1864 }, + { 3159, -10498, 1677, -4273 }, + { 3534, -9010, 2437, -3565 }, + { 4479, -10821, 2715, -4942 }, + { 3207, -9805, 3054, -3886 }, + { 4627, -8189, 3018, -2354 }, + { 5527, -10566, 3244, -2749 }, + { 4346, -10127, 3335, -3084 }, + { 6132, -10085, 3316, -1308 }, + { 5629, -9704, 2178, -3058 }, + { 3603, -8538, 1246, -624 }, + { 3737, -8488, 395, -3167 }, + { 5465, -11414, 2810, -4640 }, + { 5306, -7745, 2721, -3988 }, + { 7000, -9111, 1695, -1409 }, + { 6663, -7741, 2466, -4079 }, + { 4083, -7175, 1836, -4831 }, + { 3613, -9926, 1342, -3455 }, + { 6588, -8033, 457, -258 }, + { 4720, -8102, 17, -1209 }, + { 7414, -8709, 1294, -344 }, + { 5437, -10030, 4043, -1704 }, + { 4862, -9281, 1558, -1431 }, + { 6800, -6403, 5113, 862 }, + { 4623, -8242, 2667, -228 }, + { 5919, -5083, 3348, 2135 }, + { 5985, -8889, 2733, -5105 }, + { 5029, -5767, 4407, 719 }, + { 354, -6158, -838, -3001 }, + { 351, -5943, -2104, -1534 }, + { -633, -7190, -25, -4798 }, + { -1595, -7235, -3812, -1400 }, + { 103, -6197, -2933, -78 }, + { -1722, -5020, -3441, -4333 }, + { -1963, -5644, -4365, -270 }, + { -846, -5743, -3477, 196 }, + { -191, -5348, -4054, -469 }, + { -2515, -7754, -3495, -818 }, + { -2090, -6710, -2701, 117 }, + { -546, -7036, -1398, 163 }, + { -278, -7091, -2662, -536 }, + { -622, -7962, -2731, -1464 }, + { -1555, -8118, -3612, -2057 }, + { -1094, -6280, -2314, 505 }, + { -2556, -8538, -4024, -2247 }, + { 109, -7134, -3107, -1823 }, + { -900, -6954, -3340, -717 }, + { -605, -7113, -3656, -2154 }, + { 837, -6263, -3211, -2177 }, + { -417, -5810, -3871, -1469 }, + { -1318, -5649, -4207, -3198 }, + { 413, -6765, -2082, -33 }, + { -3101, -6450, -4362, -766 }, + { 755, -6489, -2967, -846 }, + { 1117, -7106, -2452, -1352 }, + { -1202, -8387, -3072, -2897 }, + { -365, -4894, -3561, -2937 }, + { -2372, -8776, -265, -4441 }, + { -1224, -8678, -896, -5074 }, + { -755, -10096, -600, -6623 }, + { 300, -8206, -225, -4568 }, + { -1176, -6824, -2633, -3527 }, + { -2006, -5443, -1526, -5849 }, + { -1115, -5540, -2363, -4785 }, + { 1059, -6812, -2543, -2654 }, + { -1976, -6861, -3062, -5508 }, + { -379, -5328, -2321, -3624 }, + { -2108, -5860, -4518, -1915 }, + { -379, -7885, -1329, -594 }, + { 774, -5389, -581, -5213 }, + { -2601, -5083, -1849, -4921 }, + { -176, -5580, 74, -5075 }, + { -204, -6780, -190, -6232 }, + { 418, -7594, -1987, -820 }, + { -1873, -8529, -2926, -1609 }, + { 1340, -6362, -919, -4975 }, + { 577, -7990, -2044, -1873 }, + { -2572, -7413, -1745, -2224 }, + { -2037, -7030, -1461, -7138 }, + { -2559, -8756, -2039, -5836 }, + { -2079, -6764, -1209, -5669 }, + { -1613, -7801, -2006, -685 }, + { -1865, -6583, -722, -3529 }, + { -589, -6358, -1377, -1003 }, + { -540, -7514, -1331, -3542 }, + { 419, -6192, -1677, -4927 }, + { -2786, -8763, -2966, -5065 }, + { -2172, -8411, -1726, -4675 }, + { -3382, -9833, -3497, -5722 }, + { -2433, -10169, -2077, -5775 }, + { -424, -9451, -1096, -3658 }, + { -537, -8522, -910, -1897 }, + { -5550, 2807, 1683, -693 }, + { -6395, 635, 3573, -1246 }, + { -7544, 2280, 2140, 44 }, + { -8751, 1136, 2951, -794 }, + { -5605, 2709, 2052, 916 }, + { -7650, 654, 869, 135 }, + { -6939, 967, 1409, 870 }, + { -7834, 2123, 3310, 974 }, + { -6935, 2818, 1274, -1678 }, + { -5605, 2233, 1013, 471 }, + { -7095, 1849, 1648, 198 }, + { -6636, 1634, 712, -37 }, + { -7279, 978, 296, -315 }, + { -7664, 3504, 3292, -216 }, + { -7836, 1209, 1221, -257 }, + { -7913, 2201, 1765, -1529 }, + { -7077, 3783, 2632, -1407 }, + { -5565, 1645, 1410, -622 }, + { -6494, 2879, 1181, -759 }, + { -7073, 3137, 3010, 550 }, + { -7249, 1839, 847, -805 }, + { -6630, 2197, 282, -1096 }, + { -8836, 1573, 1988, -1090 }, + { -7809, 1274, 836, -1198 }, + { -7895, 2970, 3511, -1097 }, + { -6960, 1664, 1356, -2442 }, + { -6582, 2866, 2273, 307 }, + { -7221, 821, 2851, -1435 }, + { -6015, 1703, 2001, -2367 }, + { -8082, 1034, 2103, 239 }, + { -5952, 1912, 301, -465 }, + { -6099, 841, 379, 567 }, + { -6343, 50, 494, 658 }, + { -6586, 983, 591, -893 }, + { -5500, 869, 2187, -2479 }, + { -6482, 60, 1545, -979 }, + { -6705, 515, 1974, -53 }, + { -6460, 1755, 1325, -1275 }, + { -6093, 2617, 2465, -623 }, + { -7330, 2161, 594, -2115 }, + { -7324, 762, 1593, -2004 }, + { -6385, 679, 1510, -2514 }, + { -6159, 241, 2976, -1631 }, + { -8583, 3030, 4045, -162 }, + { -6299, 66, 2209, -2103 }, + { -5428, 1279, 3267, -1846 }, + { -6438, 1335, 2728, -1631 }, + { -8012, 1070, 2428, -1151 }, + { -6201, 2781, 2349, -1918 }, + { -5918, 1139, 3121, -148 }, + { -6314, 2481, 3137, -1808 }, + { -7180, 1722, 2435, -1602 }, + { -6750, 1829, 3763, -1145 }, + { -6713, 1777, 2221, 1212 }, + { -7479, 1835, 3627, -479 }, + { -7299, 10, 2406, -1593 }, + { -8249, 3129, 996, -2870 }, + { -8374, 1534, 1333, -1882 }, + { -7507, 3353, 1598, -2299 }, + { -7379, 2701, 2326, -1167 }, + { -8440, 2276, 2796, -542 }, + { -10348, 1527, 2649, -1165 }, + { -8184, 3614, 2574, -1738 }, + { -5539, 1574, 1733, 1138 }, + { 9404, -7652, 67, 79 }, + { 8654, -3972, 1358, -60 }, + { 8617, -4794, 117, 2318 }, + { 7886, -4505, 1784, 1200 }, + { 8636, -6125, 3879, -1003 }, + { 9654, -6836, 1816, 205 }, + { 9374, -6553, 913, 1875 }, + { 8020, -6150, 1134, 2390 }, + { 7786, -4970, 2078, -1857 }, + { 8691, -6119, 711, 708 }, + { 9039, -5568, 2944, -1902 }, + { 9955, -5048, 1433, -601 }, + { 8089, -6927, 3093, -2846 }, + { 8487, -7024, 2415, 19 }, + { 9388, -5287, 3577, -2655 }, + { 8591, -7371, 2300, -996 }, + { 9104, -4763, 1453, -2558 }, + { 7615, -5457, 596, 164 }, + { 9860, -7047, 3433, -614 }, + { 8756, -4404, 2235, -964 }, + { 9462, -4660, 299, -1822 }, + { 10119, -5550, 2689, -1273 }, + { 10915, -7471, 2705, -1007 }, + { 11433, -7090, 1410, -1198 }, + { 9882, -7431, 2965, -1895 }, + { 7628, -5219, 769, -2661 }, + { 8169, -5318, 2262, 70 }, + { 8846, -6320, 1939, -754 }, + { 7147, -5593, 1248, -971 }, + { 10652, -5485, 935, 137 }, + { 7778, -6533, 2564, -1932 }, + { 8878, -5173, 1214, -361 }, + { 9828, -4943, 282, 510 }, + { 10042, -6134, 3895, -1914 }, + { 7965, -6630, 3566, -433 }, + { 8573, -4502, 3574, -1209 }, + { 8398, -4801, 1031, -1347 }, + { 10136, -7772, 2612, 1547 }, + { 9890, -7280, 1768, -1083 }, + { 8407, -6585, -706, -58 }, + { 7976, -7582, 229, -131 }, + { 10481, -8866, 1166, -147 }, + { 10914, -4342, 3189, -2412 }, + { 10440, -5198, -104, -1109 }, + { 11227, -6530, 2381, -2449 }, + { 8487, -8064, 1086, 230 }, + { 9975, -6123, -857, -134 }, + { 8339, -6498, 1232, -2337 }, + { 11042, -4506, 1119, -2098 }, + { 12563, -5592, 1837, -2062 }, + { 11801, -5590, 632, -1296 }, + { 10152, -5617, 1511, -1917 }, + { 7800, -6473, 51, -1337 }, + { 7941, -5560, 2438, -3270 }, + { 6554, -3834, 2100, 1476 }, + { 9065, -5520, -226, -1120 }, + { 10794, -7120, -243, 122 }, + { 10429, -6968, 272, -806 }, + { 8942, -8914, 1442, -392 }, + { 9969, -5051, 2033, -2953 }, + { 7275, -4152, 3058, -64 }, + { 11127, -5488, 4589, -3227 }, + { 9626, -6666, 2739, -2958 }, + { 6943, -5362, 4470, 1008 }, + { -7456, -967, 2936, -1002 }, + { -8622, -333, 6962, 2606 }, + { -7486, -3392, 3668, 1287 }, + { -8053, -827, 5148, 1097 }, + { -6610, 454, 4952, 96 }, + { -7701, -1982, 3161, -468 }, + { -7307, -1132, 4071, -36 }, + { -8125, -271, 5199, 3862 }, + { -9182, -1950, 2813, 1878 }, + { -9855, -952, 4794, 3010 }, + { -7241, 1431, 4202, 2468 }, + { -9646, 157, 4766, 1046 }, + { -9371, 1230, 6009, 2958 }, + { -11514, -64, 8630, 5248 }, + { -6766, 565, 2766, 2140 }, + { -8426, -9, 2852, 1271 }, + { -11291, -1113, 5087, 2937 }, + { -8297, 2092, 4495, 1264 }, + { -9983, 735, 3809, -51 }, + { -9048, -1000, 3191, -308 }, + { -7331, -1987, 2655, 1391 }, + { -7144, -21, 4333, 2161 }, + { -6032, -1540, 3543, 896 }, + { -7987, -1036, 1985, 1529 }, + { -9264, 2004, 5194, 290 }, + { -11308, -840, 5754, 1654 }, + { -9130, -2398, 4292, 2973 }, + { -6248, 838, 3563, 1223 }, + { -6819, -2760, 3511, 119 }, + { -7213, -2006, 4364, 762 }, + { -5431, -1047, 4533, 166 }, + { -7098, -641, 2021, 639 }, + { -8628, -2249, 3588, 399 }, + { -6352, -1498, 3560, -648 }, + { -7033, -2190, 4870, 2562 }, + { -7405, -46, 3772, -581 }, + { -6104, 796, 5143, 1965 }, + { -5787, 943, 5784, 3030 }, + { -8367, 1465, 7192, 4097 }, + { -8259, 789, 5694, 1963 }, + { -10614, -1899, 5748, 2645 }, + { -8258, -805, 3698, 2275 }, + { -6877, -972, 6431, 3160 }, + { -6483, 363, 7018, 3129 }, + { -6283, -1358, 5191, 1524 }, + { -8853, -3157, 4119, 1741 }, + { -6086, -267, 3883, -835 }, + { -7254, 1032, 6613, 4017 }, + { -11470, -3350, 4649, 3426 }, + { -6743, 481, 6148, 1239 }, + { -5394, -166, 5309, 3165 }, + { -7958, 1068, 4268, -240 }, + { -10520, 2256, 7916, 2828 }, + { -5132, -4, 5739, 1176 }, + { -8643, 120, 3255, -629 }, + { -9631, 1974, 8870, 4362 }, + { -10663, -1221, 3733, 589 }, + { -8224, -1843, 5806, 2655 }, + { -8282, 1255, 8647, 3478 }, + { -12311, -1505, 9043, 6256 }, + { -11312, -856, 7136, 4681 }, + { -11944, -722, 7941, 3309 }, + { -7868, -463, 6846, 4196 }, + { -8679, -241, 7410, 5347 }, + { 6759, -4680, -508, 1220 }, + { 5176, -6111, 944, 121 }, + { 6843, -5667, -1368, -533 }, + { 5616, -5884, -1471, -695 }, + { 6030, -5089, -1808, -940 }, + { 7444, -5463, -52, 1881 }, + { 4207, -6079, -506, 1571 }, + { 6785, -4410, -649, 3084 }, + { 4838, -5214, 2026, 2998 }, + { 4201, -5790, 645, 1811 }, + { 6930, -5129, -1940, 1698 }, + { 6332, -4627, 692, 3027 }, + { 6285, -4314, -106, 3644 }, + { 6255, -5450, -1975, 742 }, + { 4199, -4676, -459, 1796 }, + { 5592, -5500, 1345, 1300 }, + { 4358, -5556, -2236, 114 }, + { 4620, -5875, -1563, 888 }, + { 4892, -7550, -327, -419 }, + { 4734, -7085, 7, 613 }, + { 3883, -5562, -1969, 1080 }, + { 5610, -4990, -204, 834 }, + { 4117, -6482, -1271, 341 }, + { 6585, -5107, 892, 1169 }, + { 6632, -3683, 302, 3002 }, + { 6326, -5351, -983, -1250 }, + { 4382, -7192, -730, -158 }, + { 5227, -6540, -451, 1123 }, + { 5468, -6472, -870, -1471 }, + { 5191, -6402, -1365, -127 }, + { 7407, -6317, -973, -336 }, + { 4611, -6530, -820, -1980 }, + { 4963, -5159, -2050, -966 }, + { 4414, -5691, -211, -998 }, + { 5954, -5873, 750, -1749 }, + { 4394, -4796, -1268, 254 }, + { 7161, -6214, -1010, 689 }, + { 4965, -3598, 2372, 1711 }, + { 6248, -6180, 981, 864 }, + { 6473, -5336, 525, -600 }, + { 4591, -6864, -1131, -900 }, + { 6314, -6440, -1021, -375 }, + { 5838, -6209, -1199, 944 }, + { 5308, -5283, -2100, 1267 }, + { 4342, -5860, -1637, -1356 }, + { 5680, -4388, -1227, -104 }, + { 4900, -4098, 1449, 4046 }, + { 4677, -4284, -106, 3190 }, + { 7574, -6173, -848, 1859 }, + { 6493, -7207, -131, 726 }, + { 5513, -5261, -2117, 4 }, + { 6191, -7352, -193, -505 }, + { 5885, -4333, 324, -134 }, + { 6162, -6081, -312, -2044 }, + { 4216, -6200, -1810, -572 }, + { 5652, -7035, -696, -197 }, + { 7131, -7189, -366, -60 }, + { 5032, -4803, -1514, 2832 }, + { 7386, -4610, -606, 3489 }, + { 4211, -5031, 1221, 3047 }, + { 4050, -4653, 1584, 1469 }, + { 6852, -5302, -1861, 206 }, + { 7736, -4816, -1794, 3359 }, + { 6290, -3439, 1522, 2454 }, + { 1768, 5990, -5560, -2594 }, + { 3903, 5326, -1530, -1501 }, + { 2472, 3738, -2117, -4240 }, + { 3260, 5448, -904, -4733 }, + { 1435, 7297, -3676, -4102 }, + { 4096, 5951, -656, -3312 }, + { 2178, 6009, -3146, -3724 }, + { 3787, 5493, -5473, -1633 }, + { 2998, 7286, -3334, -3571 }, + { 2894, 6576, -4708, -2804 }, + { 830, 6163, -4286, -3348 }, + { 4755, 5569, -1730, -2739 }, + { 4604, 6065, -3562, -2605 }, + { 2749, 5141, -3986, -2775 }, + { 3942, 4875, -2143, -3340 }, + { 2819, 8517, -2004, -2724 }, + { 2146, 6298, -689, -3093 }, + { 5196, 6504, -3393, -1475 }, + { 1851, 8386, -1748, -1420 }, + { 3474, 8572, -3534, -2688 }, + { 4503, 7560, -3561, -2245 }, + { 4433, 6219, -2393, -1575 }, + { 3506, 7248, -2275, -1977 }, + { 3490, 7409, -3147, -604 }, + { 4214, 6447, -3520, 516 }, + { 619, 7034, -829, -1705 }, + { 1732, 7395, -356, -2208 }, + { 1226, 5204, -3294, -3732 }, + { 2027, 5619, -1813, -4146 }, + { 3078, 5877, 47, -2651 }, + { 1654, 5458, 424, -682 }, + { 3163, 5464, -2026, -270 }, + { 2884, 5375, -685, -530 }, + { 2950, 7286, -35, -2967 }, + { 1986, 5066, -597, 482 }, + { 3459, 4308, -3845, -2333 }, + { 3155, 7037, -1346, -4345 }, + { 2193, 6696, -717, -1319 }, + { 3677, 5089, -3892, -487 }, + { 2186, 5136, -4186, -1492 }, + { 773, 5796, -917, 817 }, + { 2489, 6546, -3570, -2117 }, + { 1223, 6469, -1362, -33 }, + { 271, 6061, -1466, -1725 }, + { 2540, 5171, -1847, 1032 }, + { 2548, 5251, -2697, 1677 }, + { 771, 7600, -768, -632 }, + { 4710, 6647, -4736, -1275 }, + { 1369, 5917, -2971, -1056 }, + { 163, 5239, -3499, -2275 }, + { 2104, 4285, -3211, -3286 }, + { 1107, 7411, -1972, -1671 }, + { 2196, 7262, -2310, -1926 }, + { -244, 6439, -1745, -839 }, + { 3293, 3832, -2890, -3000 }, + { 419, 6443, -379, -407 }, + { 3077, 4930, -1156, -2869 }, + { 2131, 5874, -2330, 224 }, + { 690, 6538, -2212, -2841 }, + { 1602, 4421, -2515, 1542 }, + { 3318, 9373, -3032, -3477 }, + { 5646, 7462, -5153, -1463 }, + { 4139, 7137, -1539, -3321 }, + { 3481, 9077, -1645, -3653 }, + { -7747, 375, -106, -543 }, + { -8587, -1379, -586, -461 }, + { -10146, -892, 2094, 694 }, + { -8103, 382, 504, -325 }, + { -8548, -92, 94, -656 }, + { -7460, 38, 152, 388 }, + { -8266, -271, -459, -883 }, + { -7935, -664, -1026, -802 }, + { -8341, -109, 853, 161 }, + { -8802, -1355, 1099, 630 }, + { -8957, -6, 1108, -669 }, + { -7260, -1520, -43, -407 }, + { -7555, -174, 668, -2562 }, + { -9014, -126, 227, -1191 }, + { -8184, 769, 290, -1375 }, + { -9476, 55, 962, -1528 }, + { -8679, 541, 755, -1030 }, + { -9842, -1626, 838, -1588 }, + { -8513, -702, 788, -1998 }, + { -10101, -1558, -366, -1841 }, + { -8135, 78, 1479, -1813 }, + { -9128, -454, 313, -1786 }, + { -7554, -1084, 831, -2442 }, + { -7576, -701, 2068, -1665 }, + { -7791, -1481, 1587, -1808 }, + { -6701, -596, -97, 802 }, + { -7418, -15, 684, -963 }, + { -7127, -477, -139, -426 }, + { -8097, -110, -36, -264 }, + { -7620, -1922, -590, -101 }, + { -7647, -1201, 279, 660 }, + { -7856, -1974, 758, -2271 }, + { -8496, -167, 2232, -1143 }, + { -8506, -1359, 624, -740 }, + { -7274, -1052, 1062, -139 }, + { -7800, -217, 91, -1794 }, + { -7030, -1694, -955, 615 }, + { -9020, -1864, 101, -2182 }, + { -9400, -740, 598, -667 }, + { -8448, -1184, 2024, -1272 }, + { -8812, -570, -897, -2384 }, + { -10559, -1286, 538, -1536 }, + { -8728, -888, -1089, -1397 }, + { -7080, -1185, 636, -1252 }, + { -9880, 233, 2344, -782 }, + { -7952, -1326, -378, -1947 }, + { -7207, -378, 1408, -2237 }, + { -8467, -1545, 902, -1987 }, + { -9163, -1474, 924, -1739 }, + { -8159, -992, -77, -2744 }, + { -8343, 148, -423, -1573 }, + { -9105, -649, -254, -1214 }, + { -8939, 456, 281, -1905 }, + { -8837, 179, -394, -2634 }, + { -9145, 757, 1547, -1319 }, + { -9775, -723, 441, -1680 }, + { -8910, -686, 1529, -1525 }, + { -9492, -1134, 2064, -938 }, + { -6111, -943, 677, -31 }, + { -7411, -613, -814, 46 }, + { -9479, -922, -430, -2061 }, + { -11298, -1268, 1318, -1117 }, + { -8190, 832, 671, -2214 }, + { -10453, -550, 1672, -886 }, + { 1044, 9353, -1651, -5423 }, + { 1034, 8149, -455, -6166 }, + { 761, 8293, -3214, -4838 }, + { 938, 8077, 164, -5130 }, + { 1295, 8673, 2582, -5490 }, + { -314, 7973, -2395, -5231 }, + { -507, 9012, -2497, -5775 }, + { 2396, 8314, -1022, -4673 }, + { -1516, 8501, 1950, -4969 }, + { -308, 7401, 1549, -4866 }, + { -112, 8340, 3003, -4920 }, + { -50, 9315, 1371, -5666 }, + { -659, 9449, 2496, -5547 }, + { 2573, 9148, -2270, -4783 }, + { 830, 7104, -438, -3907 }, + { 522, 10672, -677, -6483 }, + { -1190, 10108, -510, -6518 }, + { -427, 8271, -579, -6315 }, + { 1602, 8113, -1927, -4418 }, + { -2266, 8180, 448, -5190 }, + { -1633, 8816, -226, -5771 }, + { 759, 9481, -105, -5813 }, + { 2254, 6679, -466, -5662 }, + { -88, 6946, 895, -5958 }, + { -1705, 10009, 1394, -5574 }, + { 748, 7943, 540, -6692 }, + { 1411, 7009, 232, -6145 }, + { 697, 7290, -1221, -5342 }, + { -1764, 10580, 1944, -3981 }, + { -1334, 9124, 1195, -3903 }, + { -905, 10067, 635, -5039 }, + { 664, 10680, 49, -4625 }, + { 1374, 9536, -777, -3591 }, + { 252, 9698, -597, -2931 }, + { 824, 9164, -1014, -2144 }, + { 2438, 10569, -2289, -4424 }, + { 2101, 7102, 507, -3614 }, + { 294, 8051, -432, -1518 }, + { -665, 10337, 547, -2852 }, + { 1168, 11989, -492, -5427 }, + { 1344, 6416, 302, -5061 }, + { -1727, 12264, 1507, -4543 }, + { 674, 10889, -902, -3605 }, + { -582, 9504, 300, -3618 }, + { 641, 7654, 689, -2109 }, + { 2065, 9243, 508, -4367 }, + { 1055, 8373, 688, -3144 }, + { -641, 8185, 986, -3307 }, + { 1120, 7426, 1785, -3757 }, + { 1660, 8070, -593, -3104 }, + { 2002, 9467, -1722, -3475 }, + { 2361, 8368, 100, -3709 }, + { -772, 7845, -613, -4988 }, + { 1485, 7430, 1896, -6127 }, + { -432, 7823, -947, -2882 }, + { 313, 11122, -760, -4871 }, + { 412, 8412, -283, -4231 }, + { 1585, 10402, -1884, -3267 }, + { 321, 6952, 773, -3016 }, + { -105, 9014, 121, -2249 }, + { 1585, 10313, -977, -4812 }, + { 1619, 11869, 1306, -6876 }, + { -1168, 8886, -81, -2500 }, + { -395, 10886, 733, -6490 }, + { -4949, 4274, 3992, -1054 }, + { -4241, 5299, 4262, -1584 }, + { -2710, 3862, 4552, -1673 }, + { -4608, 2472, 3672, -1715 }, + { -2843, 2816, 4003, -2326 }, + { -5229, 2964, 5636, 90 }, + { -4924, 3442, 5015, -1096 }, + { -1281, 3313, 5537, -2066 }, + { -3808, 1939, 4351, -919 }, + { -1915, 2585, 4939, -1614 }, + { -3470, 1843, 5562, -682 }, + { -3800, 870, 5827, 144 }, + { -4985, 1452, 4728, -709 }, + { -3745, 2750, 7220, 259 }, + { -1875, 1900, 6514, -826 }, + { -4329, 1574, 7192, 1304 }, + { -5408, 1444, 6208, 631 }, + { -3327, 5312, 5707, -1541 }, + { -6966, 3334, 4034, 1028 }, + { -7484, 4245, 4218, -212 }, + { -6567, 5839, 4539, -512 }, + { -5715, 5935, 3747, -1186 }, + { -6410, 4881, 3356, -1610 }, + { -5146, 2590, 2850, 2172 }, + { -5196, 4095, 2569, -373 }, + { -5043, 6025, 4318, 692 }, + { -5525, 4884, 3513, 370 }, + { -6804, 7533, 5812, -488 }, + { -5657, 2480, 4061, 1234 }, + { -3155, 1472, 6071, 1188 }, + { -3427, 5217, 3442, 858 }, + { -4698, 3013, 5517, 2586 }, + { -4449, 2226, 5418, 3580 }, + { -6395, 3547, 5487, 2028 }, + { -3500, 5019, 4787, 1 }, + { -4038, 2578, 3073, 3151 }, + { -2750, 1955, 4469, 3856 }, + { -5696, 1659, 6118, 2469 }, + { -4350, 1241, 6840, 3126 }, + { -5565, 5058, 5196, 1314 }, + { -1642, 4190, 3948, 607 }, + { -1233, 4108, 4850, -640 }, + { -997, 3428, 3239, 1378 }, + { -6488, 2741, 6926, 2792 }, + { -4188, 3763, 4235, 2018 }, + { -3210, 3224, 5646, 1427 }, + { -5526, 6909, 5070, -627 }, + { -2815, 3994, 3425, 1903 }, + { -2163, 2734, 5423, 145 }, + { -4149, 4247, 2355, 734 }, + { -410, 2521, 4138, -16 }, + { -2411, 2385, 4927, 2105 }, + { -6077, 3591, 3114, 594 }, + { -4186, 4834, 5926, -1004 }, + { -7315, 3369, 5966, 448 }, + { -7042, 5721, 5771, 238 }, + { -4466, 3907, 3535, -1751 }, + { -2116, 3970, 6163, -1392 }, + { -7239, 2143, 8407, 3630 }, + { -5431, 4486, 6486, -42 }, + { -1874, 1617, 6333, 519 }, + { -6478, 2629, 4634, -505 }, + { -7784, 2342, 7216, 1365 }, + { -1154, 1432, 4831, 1544 }, + { -4964, -5801, 1797, 506 }, + { -4436, -6905, 1059, -1237 }, + { -5400, -6886, 884, -290 }, + { -6259, -7103, 523, -227 }, + { -4819, -6450, 1412, -450 }, + { -4056, -6213, 1725, -943 }, + { -5642, -6091, 1357, 605 }, + { -4196, -5678, 2187, -173 }, + { -4726, -5126, 2470, 321 }, + { -6642, -5091, 1507, -1005 }, + { -5304, -5250, 1944, 1579 }, + { -7179, -5520, 1468, -425 }, + { -6033, -4895, 1876, -955 }, + { -6595, -5143, 2207, 1291 }, + { -4224, -4943, 1846, 1792 }, + { -7128, -6950, 539, 724 }, + { -4369, -4901, 2590, 1103 }, + { -7413, -5696, 1712, 1440 }, + { -5885, -6821, 418, 871 }, + { -6828, -5599, 710, -1563 }, + { -6123, -5817, 1358, 1631 }, + { -5291, -5622, 578, 2138 }, + { -7171, -6004, 347, 2208 }, + { -6083, -5251, 2132, 425 }, + { -4329, -5721, 407, -2993 }, + { -5326, -5056, 1119, -1837 }, + { -5485, -5856, 185, -2389 }, + { -6529, -5178, 403, -697 }, + { -6719, -4412, 2726, 871 }, + { -5126, -5629, 1835, -771 }, + { -5622, -4361, 2973, 858 }, + { -5282, -5895, 45, -335 }, + { -4357, -5656, 1696, -1558 }, + { -7139, -6659, 627, -409 }, + { -4415, -6328, 35, 1306 }, + { -7639, -6110, 1134, 197 }, + { -3626, -5592, 2019, 901 }, + { -3547, -5064, 1176, 1738 }, + { -5075, -3899, 2087, 266 }, + { -4086, -6311, 1479, 360 }, + { -6210, -5220, -199, -1477 }, + { -3910, -5063, 1356, -15 }, + { -7616, -4977, 461, 2401 }, + { -6118, -6131, 1258, -563 }, + { -6127, -4968, 1286, -27 }, + { -4121, -5852, 1113, 1476 }, + { -5157, -4881, 1162, -662 }, + { -4637, -5031, 1179, 709 }, + { -5509, -5452, -397, 1224 }, + { -4597, -6861, 646, 467 }, + { -6247, -4043, 468, 278 }, + { -5336, -6465, 874, -1472 }, + { -6998, -6346, 78, -1798 }, + { -4915, -4530, 2756, -203 }, + { -6048, -4373, 1468, 1052 }, + { -4273, -7100, 942, -323 }, + { -6552, -4287, 2351, 69 }, + { -6954, -4613, 722, 1521 }, + { -4201, -5361, 763, -1562 }, + { -6881, -5596, -748, 669 }, + { -6695, -3547, -34, 1299 }, + { -3981, -5728, 84, 111 }, + { -4663, -4809, 2173, -1031 }, + { -6599, -6077, 1303, 256 }, + { -7596, -4265, -5791, -4140 }, + { -6610, -2758, -5288, -3936 }, + { -5880, -3865, -6563, -3088 }, + { -7228, -5510, -7677, -3912 }, + { -8854, -6553, -8318, -5361 }, + { -9362, -5249, -6413, -4319 }, + { -4418, -3110, -6368, -4358 }, + { -5544, -4203, -6863, -5013 }, + { -3056, -4316, -5567, -3181 }, + { -3078, -5999, -5051, -2657 }, + { -5884, -6292, -5756, -4013 }, + { -4825, -4549, -5535, -4053 }, + { -4443, -6126, -5316, -1368 }, + { -3972, -6341, -6098, -2686 }, + { -5751, -2781, -5398, -6230 }, + { -4466, -6135, -5570, -3679 }, + { -4291, -5992, -3564, -5189 }, + { -7189, -4429, -7279, -6082 }, + { -5076, -4433, -2748, -5366 }, + { -6225, -2825, -6833, -5663 }, + { -2989, -4792, -3960, -4492 }, + { -7836, -7773, -7722, -5741 }, + { -6559, -5703, -5844, -5589 }, + { -7612, -5438, -4136, -3774 }, + { -4218, -4176, -6591, -2333 }, + { -4837, -5063, -6581, 322 }, + { -6590, -5990, -2980, -3847 }, + { -5558, -2971, -5489, -1932 }, + { -7001, -5323, -4975, -1697 }, + { -4694, -2688, -6904, -3044 }, + { -8511, -5379, -5767, -2549 }, + { -7548, -5412, -6522, -2572 }, + { -6597, -4973, -6423, -1274 }, + { -6415, -4022, -5168, -1072 }, + { -5528, -5530, -7218, -2345 }, + { -4845, -4805, -5943, -1227 }, + { -6049, -7150, -6744, -2161 }, + { -9061, -7299, -8542, -4375 }, + { -5010, -5546, -5416, -82 }, + { -4135, -4205, -5109, -3373 }, + { -3311, -5869, -4007, -5061 }, + { -5993, -6472, -3962, -4718 }, + { -2966, -5832, -2821, -6305 }, + { -4851, -5152, -2067, -3930 }, + { -3620, -4441, -3362, -5836 }, + { -4469, -5221, -4534, -5592 }, + { -4022, -6335, -4321, -6107 }, + { -4899, -4503, -3084, -3725 }, + { -4490, -8276, -4620, -6236 }, + { -6591, -4342, -7365, -4063 }, + { -6498, -5057, -5553, 485 }, + { -6060, -2714, -7093, -4144 }, + { -6199, -7774, -7094, -4057 }, + { -7536, -6424, -6415, -4265 }, + { -7439, -2454, -6348, -4827 }, + { -5333, -7565, -4417, -4639 }, + { -4353, -7103, -4197, -2689 }, + { -5229, -6549, -5129, -6804 }, + { -6129, -7701, -5236, -4836 }, + { -6797, -3983, -3884, -4406 }, + { -6624, -4467, -4745, -5052 }, + { -3324, -7596, -2720, -6553 }, + { -5473, -6284, -1704, -4511 }, + { -4131, -7263, -3180, -5196 }, + { -7116, -5565, -3469, 685 }, + { -6002, -6021, -3858, 576 }, + { -3144, -8203, -1291, -434 }, + { -6096, -7027, -4004, 1353 }, + { -3943, -7709, -2344, -36 }, + { -4510, -6767, -2642, 631 }, + { -3657, -11541, -2570, -3984 }, + { -5959, -8854, -1333, -867 }, + { -6699, -8866, -1606, -344 }, + { -3836, -7961, -2334, -2028 }, + { -3430, -8045, -3037, -672 }, + { -3868, -9184, -3635, -1819 }, + { -4258, -9060, -2621, -1008 }, + { -3595, -8693, -2022, -752 }, + { -4573, -8048, -3166, -2622 }, + { -4852, -7903, -1405, 256 }, + { -4591, -7057, -1560, 965 }, + { -6963, -7655, -980, 808 }, + { -5179, -6641, -3356, 1196 }, + { -7102, -6941, -2798, 2123 }, + { -6867, -5834, -3320, -770 }, + { -5977, -7369, -2500, -778 }, + { -6160, -6400, -934, -2543 }, + { -6741, -7608, -355, -1289 }, + { -6856, -6466, -1433, -1643 }, + { -4786, -6292, -4970, 376 }, + { -5407, -8866, -2255, -400 }, + { -3814, -6506, -1387, -3620 }, + { -4998, -6137, -1200, -4092 }, + { -5123, -9557, -2849, -1306 }, + { -4259, -6444, -4395, -338 }, + { -5221, -6810, -883, 1225 }, + { -6137, -6215, -2165, 554 }, + { -3895, -6557, -3176, -1829 }, + { -3886, -8188, -87, -954 }, + { -7243, -6707, -2216, -316 }, + { -5592, -7606, 85, -432 }, + { -3957, -7945, -504, -144 }, + { -4617, -7624, 218, -312 }, + { -4797, -8737, -844, -1051 }, + { -4478, -8516, -1401, -454 }, + { -4557, -7058, -302, -2332 }, + { -6623, -7736, -271, -50 }, + { -3157, -7532, -1111, -2207 }, + { -3590, -7300, -1271, 517 }, + { -4442, -7306, -507, 590 }, + { -6458, -7524, -2807, 666 }, + { -4991, -8466, -3363, -785 }, + { -7474, -7541, -1056, -1839 }, + { -7501, -8316, -938, -180 }, + { -5329, -7739, -579, -2341 }, + { -4549, -7063, -176, -3539 }, + { -5191, -8612, -1504, -4250 }, + { -3083, -7058, -2251, 32 }, + { -4003, -7043, -1093, -791 }, + { -5523, -8093, -678, -114 }, + { -3022, -10265, -2070, -3109 }, + { -3905, -6274, -182, -3652 }, + { -3269, -9217, -551, -2650 }, + { -3138, -9314, -1726, -1704 }, + { -4420, -10339, -1744, -3459 }, + { -4163, -8609, -2298, -4113 }, + { -5566, -6505, -1241, -463 }, + { -3130, -9746, -2352, -4884 }, + { -7825, -3439, 1451, -1468 }, + { -8451, -3318, 2360, -435 }, + { -8462, -4130, 1438, -1024 }, + { -9425, -4564, 1328, -689 }, + { -11014, -3202, 2278, 2080 }, + { -8269, -2761, -146, -440 }, + { -7497, -2618, -166, 413 }, + { -8250, -3060, 522, -2133 }, + { -8365, -5366, 1347, -451 }, + { -8589, -3979, 2943, 714 }, + { -8111, -2572, 1272, -1748 }, + { -7830, -5193, 605, -1484 }, + { -8119, -4736, 2141, 256 }, + { -7724, -4769, 1463, -812 }, + { -7363, -3911, 2540, 4 }, + { -7974, -3397, 2363, 1366 }, + { -7359, -4204, 1752, -958 }, + { -7622, -3505, 660, 916 }, + { -9934, -3665, 3165, 828 }, + { -8721, -4162, 62, 1718 }, + { -9433, -4768, 2722, 1234 }, + { -7960, -4496, 138, 1528 }, + { -8198, -3454, -443, 631 }, + { -7756, -2246, 655, 1137 }, + { -8841, -3145, 1113, 829 }, + { -7817, -3298, 1251, 230 }, + { -9413, -2733, 323, -1862 }, + { -9408, -4168, 1270, 1549 }, + { -9037, -3892, -942, 283 }, + { -8255, -3849, 1301, 1762 }, + { -9057, -3987, -41, -682 }, + { -9441, -4187, 2019, -111 }, + { -9740, -3178, 1602, -871 }, + { -8344, -2474, 1461, 1506 }, + { -9752, -2925, 1996, 1243 }, + { -9199, -3796, 180, 537 }, + { -9060, -2405, 1140, -1562 }, + { -9348, -2376, 309, -162 }, + { -10786, -3182, -5, -1500 }, + { -8142, -4540, -434, -826 }, + { -7528, -2341, 1104, -73 }, + { -9360, -2658, 3062, 56 }, + { -8267, -2335, 2000, -1193 }, + { -12169, -3154, 1287, -640 }, + { -11398, -2120, 946, -1163 }, + { -8940, -4559, 328, -1696 }, + { -11025, -4213, 2813, 840 }, + { -9224, -3581, 2224, 2039 }, + { -8943, -3337, 1248, -1298 }, + { -7900, -4042, 485, -2080 }, + { -9221, -1947, 2191, -880 }, + { -10762, -1800, 2516, -324 }, + { -10095, -2238, 981, -1335 }, + { -11908, -2808, 3255, 645 }, + { -10640, -4105, 1283, -595 }, + { -7663, -2863, 2467, -797 }, + { -10712, -3854, 3710, 1538 }, + { -10823, -2893, 1408, -801 }, + { -9874, -3832, 256, -1638 }, + { -10394, -3391, 2315, -94 }, + { -11525, -4079, 4153, 2122 }, + { -9546, -2088, 1541, 481 }, + { -8731, -2433, 1042, 2160 }, + { -7852, -3977, -1370, 1677 }, + { 7072, -3420, 1398, -1741 }, + { 6180, -1976, 1280, -3557 }, + { 7692, -1793, 2844, -1700 }, + { 8363, -1773, 3104, -2679 }, + { 9213, -3266, 3756, -3542 }, + { 9650, -2644, 1426, -1318 }, + { 7712, -2796, 3686, -1975 }, + { 7316, -3517, 2821, -622 }, + { 7434, -2594, 2305, -2264 }, + { 7237, -1797, 255, -3114 }, + { 8663, -1983, 1338, -3056 }, + { 6616, -952, 4059, -2652 }, + { 8823, -1327, 1362, -1356 }, + { 9938, -1722, 1287, -2362 }, + { 7207, -1057, 1913, -1315 }, + { 7508, -1585, 870, -1982 }, + { 8217, -3680, 1417, -3170 }, + { 8329, -2541, 1684, -585 }, + { 8062, -2335, 252, -2800 }, + { 8204, -4108, 3097, -2569 }, + { 7701, -3367, 576, -3008 }, + { 7350, -786, 2414, -2129 }, + { 6948, -2568, 1607, -225 }, + { 7684, -2387, 1308, -3449 }, + { 8306, -3458, 2394, -1454 }, + { 8438, -2781, 1043, -1362 }, + { 9175, -2076, 2144, -1987 }, + { 8347, -2709, 3489, -4301 }, + { 5696, -2377, 2870, 851 }, + { 8825, -1243, 2219, -2603 }, + { 8801, -1614, 584, -2513 }, + { 8413, -384, 1421, -2244 }, + { 9228, -3050, 3279, -2164 }, + { 6342, -2698, 3547, -107 }, + { 10053, -2476, 2837, -3168 }, + { 7439, -604, 3177, -3991 }, + { 7749, -1064, 4329, -4855 }, + { 8655, -2177, 2252, -3519 }, + { 8490, -228, 1958, -3233 }, + { 10513, -2968, 1911, -2340 }, + { 8146, -862, 1884, -1723 }, + { 7788, -666, 3004, -2891 }, + { 7785, -1620, 4133, -3417 }, + { 10262, -3731, 3455, -2971 }, + { 8570, -905, 4519, -4649 }, + { 9129, -2562, 463, -2465 }, + { 9451, -3587, 1904, -3056 }, + { 6549, -2236, 3010, -4523 }, + { 7175, -2684, 2967, -3458 }, + { 9872, -3278, 1054, -2472 }, + { 9153, -931, 1217, -2565 }, + { 8789, -3469, 753, -2568 }, + { 6683, -3791, 1797, -3968 }, + { 6801, -1977, 2311, -452 }, + { 6336, -1572, 2612, -3264 }, + { 7996, -1008, 730, -2964 }, + { 7521, -1059, 1573, -3694 }, + { 8148, -3973, 2600, -3572 }, + { 7765, -1532, 2528, -3856 }, + { 7404, -3918, 4472, -143 }, + { 8894, -1398, 3299, -3685 }, + { 5768, -2041, 1487, -637 }, + { 5131, -2865, 2463, -811 }, + { 6439, -1568, 3500, -1550 }, + { -8878, -6798, -5319, -1452 }, + { -6332, -9713, -3112, -990 }, + { -8444, -6316, -3694, -687 }, + { -6123, -10840, -3637, -4358 }, + { -4784, -9580, -4577, -2581 }, + { -6108, -10515, -4859, -2524 }, + { -7605, -7518, -2327, -2797 }, + { -9662, -8775, -2467, -2010 }, + { -6494, -7523, -4715, -118 }, + { -8290, -8982, -1672, -317 }, + { -8798, -11051, -3888, -1426 }, + { -6273, -6623, -6791, -142 }, + { -8313, -7668, -2141, -1275 }, + { -6453, -8412, -3589, -4102 }, + { -6747, -7750, -5690, -2498 }, + { -7814, -6693, -3174, -2446 }, + { -10383, -10130, -3931, -2364 }, + { -10606, -8467, -5539, -2772 }, + { -9475, -6671, -3305, -2271 }, + { -8982, -9457, -5635, -4005 }, + { -10111, -7965, -6515, -4180 }, + { -7301, -6479, -5364, 720 }, + { -9543, -8999, -7921, -912 }, + { -9534, -8562, -3469, -384 }, + { -7601, -10344, -3205, -1127 }, + { -8088, -8620, -4954, -2888 }, + { -8202, -8406, -7038, -3775 }, + { -7312, -8324, -3334, -1775 }, + { -8566, -9262, -8071, -4174 }, + { -7068, -11300, -5573, -2907 }, + { -8295, -8952, -4366, -1544 }, + { -11104, -10210, -2285, -384 }, + { -5213, -7520, -5008, -1339 }, + { -5889, -7940, -5987, -1385 }, + { -10816, -8201, -4153, -1485 }, + { -10277, -8919, -6315, -1652 }, + { -5888, -10320, -3821, -1733 }, + { -10497, -7181, -6083, -3032 }, + { -7721, -9724, -6591, -5336 }, + { -5688, -7894, -3486, -2552 }, + { -10014, -10500, -3247, -820 }, + { -6301, -8765, -4506, -2923 }, + { -8261, -7847, -6213, -1552 }, + { -10212, -7481, -8113, -3954 }, + { -6938, -10874, -6074, -4703 }, + { -7183, -10968, -4446, -1773 }, + { -7120, -9193, -1966, -2509 }, + { -6234, -9263, -2313, -4284 }, + { -8503, -9857, -2429, -608 }, + { -9372, -7844, -8391, -2120 }, + { -7951, -7157, -6535, -11 }, + { -7256, -9473, -2172, -660 }, + { -10063, -9612, -2515, -15 }, + { -6684, -9134, -6109, -4206 }, + { -8204, -11932, -5220, -2306 }, + { -9710, -6706, -4115, -3275 }, + { -6855, -7078, -2409, -4447 }, + { -7344, -7673, -4479, -4116 }, + { -8851, -6842, -4927, -2948 }, + { -8927, -10452, -5633, -2194 }, + { -8627, -9002, -7176, -1575 }, + { -8209, -9722, -7021, -3324 }, + { -3770, -10249, -3623, -4816 }, + { -8183, -7465, -4090, 646 }, + { -8163, -7149, 200, 498 }, + { -8289, -6266, 686, -206 }, + { -10030, -6241, -1032, -1864 }, + { -8793, -8327, -773, -169 }, + { -9149, -6215, 969, -15 }, + { -8303, -5859, -7, 2006 }, + { -9682, -7283, 255, 1322 }, + { -9293, -7227, 71, -231 }, + { -8525, -6215, 287, -837 }, + { -10477, -5379, 1159, 1449 }, + { -10726, -7856, -130, 102 }, + { -8694, -7461, -1210, 690 }, + { -9367, -5324, 1103, 3170 }, + { -10686, -8055, -831, 1633 }, + { -9201, -6873, -2704, 2258 }, + { -8421, -5358, -1405, 226 }, + { -9066, -5830, -307, -1571 }, + { -11150, -7381, -2746, -900 }, + { -9978, -5925, -2006, -437 }, + { -9464, -4741, -273, 1061 }, + { -10543, -6684, -1113, 1660 }, + { -10073, -5576, 1083, -269 }, + { -8826, -5763, 1600, 1486 }, + { -10445, -9071, -1253, -64 }, + { -12085, -5799, 2, 769 }, + { -12939, -6663, 1650, 1437 }, + { -10932, -6434, -1252, -649 }, + { -11650, -7826, -2053, 710 }, + { -12122, -6733, -1889, -731 }, + { -9093, -6095, -2463, -842 }, + { -10977, -4364, 469, 420 }, + { -11488, -6908, -521, 893 }, + { -9669, -5478, -842, 337 }, + { -10606, -5203, -632, -1361 }, + { -10198, -6284, 1662, 1277 }, + { -10135, -5292, 2435, 3493 }, + { -11027, -6561, 655, 56 }, + { -10977, -5030, 1127, -358 }, + { -12766, -3986, 1348, -335 }, + { -14244, -7731, 264, 317 }, + { -15124, -10309, -508, 1447 }, + { -12821, -8638, -608, 137 }, + { -13076, -8693, -2852, -431 }, + { -11156, -5546, -2252, -1600 }, + { -8692, -7366, -819, -1223 }, + { -12507, -9816, -1714, -121 }, + { -10712, -6666, 544, 3349 }, + { -12462, -5890, -2491, -2318 }, + { -12468, -7226, 437, 232 }, + { -11300, -5226, 2068, 687 }, + { -11994, -8320, -626, 2728 }, + { -12222, -5476, 1142, 18 }, + { -10277, -8122, -2418, 2003 }, + { -13418, -6115, -3563, -2802 }, + { -14759, -9834, -1243, 21 }, + { -13699, -5665, 1525, 507 }, + { -16269, -9476, -701, 163 }, + { -12677, -5437, -247, -1019 }, + { -11827, -4295, -181, -1243 }, + { -12847, -4496, 2984, 1123 }, + { -13860, -7915, -1166, -547 }, + { -12276, -8145, -2290, -1527 }, + { -11417, -4830, 2983, 1854 }, + { -11793, -6002, 1163, 1940 }, + { 11443, -4920, -3235, 3151 }, + { 11300, -6616, -1506, 1175 }, + { 9198, -4628, -2060, 2390 }, + { 10532, -4027, -643, 912 }, + { 9902, -3573, -1606, 1327 }, + { 9653, -3536, -2240, 1869 }, + { 9948, -5171, -423, 2662 }, + { 12316, -4004, -1989, 281 }, + { 12125, -4800, -1265, -163 }, + { 10650, -2617, -2337, 1462 }, + { 9909, -4968, -2376, 916 }, + { 12944, -4647, -1958, 460 }, + { 12988, -5283, -1141, 41 }, + { 12321, -2915, -3621, 1025 }, + { 11449, -2894, -2728, 351 }, + { 12087, -3041, -2002, -32 }, + { 11558, -4031, -1343, -399 }, + { 12983, -3740, -3516, 1245 }, + { 12099, -2515, -2752, 225 }, + { 12515, -3465, -2701, 550 }, + { 14683, -5022, -5272, 2996 }, + { 12260, -3383, -1215, -528 }, + { 13810, -5422, -2443, 1166 }, + { 13421, -5378, -1886, 721 }, + { 12961, -4259, -2594, 796 }, + { 12266, -2104, -4768, 1591 }, + { 13523, -4710, -3045, 1342 }, + { 12437, -2099, -5610, 2117 }, + { 11850, -2183, -3497, 661 }, + { 12275, -3936, -597, -697 }, + { 12459, -5253, -517, -544 }, + { 12835, -4094, -1322, -168 }, + { 14360, -5677, -3305, 1859 }, + { 13905, -4552, -4309, 2117 }, + { 11559, -3412, -1847, -81 }, + { 13379, -3167, -5764, 2746 }, + { 11910, -1634, -4342, 1052 }, + { 12662, -4742, 71, -974 }, + { 13057, -3254, -4424, 1705 }, + { 15046, -5706, -4851, 3019 }, + { 14162, -4142, -5514, 2843 }, + { 12764, -1845, -6684, 2888 }, + { 13714, -2374, -7838, 3857 }, + { 13295, -1663, -8293, 4073 }, + { 10032, -4152, -3403, 1421 }, + { 10942, -5386, -2222, 950 }, + { 10532, -6385, -1750, 1925 }, + { 10273, -5972, -1534, 643 }, + { 10605, -4782, -1695, 27 }, + { 10988, -5153, -1123, -341 }, + { 11629, -5884, -1060, 48 }, + { 10441, -4045, -2431, 311 }, + { 10788, -3595, -4171, 1807 }, + { 12110, -5686, -2127, 976 }, + { 11746, -4773, -2639, 891 }, + { 11541, -5299, -3031, 1732 }, + { 11416, -2559, -5359, 2198 }, + { 11583, -5376, -704, 677 }, + { 10416, -3214, -3516, 872 }, + { 9651, -5435, -1618, 3255 }, + { 9973, -5133, -996, 3923 }, + { 11707, -4643, -430, -796 }, + { 10994, -2709, -3587, 2302 }, + { 10716, -5118, -645, 270 }, + { 14100, -10314, 1095, 1531 }, + { 12944, -8049, 1105, -741 }, + { 13276, -7035, -511, 274 }, + { 14008, -7254, -283, 139 }, + { 11594, -6536, -91, 1671 }, + { 11732, -8645, 746, 15 }, + { 14613, -7085, -1578, 1183 }, + { 13083, -6224, -750, -4 }, + { 13988, -6256, -1592, 820 }, + { 14678, -8683, 441, 126 }, + { 15571, -8872, -521, 1139 }, + { 15642, -9533, 341, 697 }, + { 15960, -9586, -168, 1121 }, + { 15464, -10239, 1433, -1 }, + { 14934, -7887, -1046, 1080 }, + { 15252, -7630, -1899, 1628 }, + { 15485, -8384, -1234, 1484 }, + { 15962, -8638, -1815, 1931 }, + { 16501, -10664, 398, 1167 }, + { 16146, -10145, 411, 918 }, + { 14573, -7475, -697, 601 }, + { 14302, -7996, 28, 257 }, + { 14769, -6792, -2286, 1574 }, + { 14144, -6137, -2169, 1257 }, + { 14770, -6271, -3111, 1933 }, + { 14110, -8312, 1083, -531 }, + { 15235, -6991, -2993, 2174 }, + { 13222, -5805, 547, -891 }, + { 14796, -8762, 1254, -246 }, + { 16040, -9181, -1005, 1551 }, + { 16487, -10086, -373, 1420 }, + { 15077, -9479, 966, 51 }, + { 13026, -6468, 932, -1080 }, + { 12703, -6152, -33, -573 }, + { 15641, -6810, -4128, 2874 }, + { 13282, -7673, 1583, -1283 }, + { 12373, -7150, 1512, -917 }, + { 12992, -7751, -678, 783 }, + { 10907, -6858, -313, 2597 }, + { 13026, -8963, 125, 2152 }, + { 12770, -9946, 1957, -505 }, + { 12482, -6849, -1268, 833 }, + { 13790, -6181, -138, -279 }, + { 12709, -8382, 2044, 227 }, + { 12244, -6630, 203, -457 }, + { 14209, -6816, -1032, 632 }, + { 15134, -8267, -288, 640 }, + { 13619, -6157, -1090, 356 }, + { 14044, -7413, 725, -484 }, + { 12958, -7753, 2585, -1980 }, + { 13188, -8396, 2306, -1558 }, + { 14379, -9980, 2132, -688 }, + { 14275, -9857, 1162, 179 }, + { 13690, -8648, 1621, -889 }, + { 11770, -6829, -746, 278 }, + { 12732, -8202, 286, 90 }, + { 13630, -10146, 1867, -207 }, + { 12072, -8740, 1299, -645 }, + { 12852, -9492, 1226, 62 }, + { 11792, -7382, -54, -116 }, + { 13779, -9014, 487, 351 }, + { 11951, -7729, 121, 834 }, + { 11970, -9781, 2276, -4 }, + { 12680, -7984, 2787, -787 }, + { 13300, -14488, 6408, -1927 }, + { 13635, -15355, 9153, -3073 }, + { 12804, -13566, 5517, -1625 }, + { 16624, -10854, 1690, 28 }, + { 20387, -18532, 6162, -261 }, + { 16515, -12642, 3392, -519 }, + { 15800, -11095, 2151, -202 }, + { 16824, -11790, 1651, 599 }, + { 17604, -13213, 2563, 538 }, + { 17892, -14177, 3562, 147 }, + { 16987, -11399, 869, 1052 }, + { 17003, -12456, 2442, 265 }, + { 21657, -21806, 9198, -1250 }, + { 16825, -13341, 3980, -686 }, + { 17525, -12714, 1887, 805 }, + { 16419, -11034, 1216, 617 }, + { 20931, -19939, 7469, -684 }, + { 18452, -15390, 4573, -191 }, + { 14778, -10077, 2841, -1209 }, + { 17402, -13319, 3042, 160 }, + { 19365, -17922, 7087, -1061 }, + { 16298, -11941, 2810, -351 }, + { 19087, -16176, 4775, -84 }, + { 17666, -12289, 938, 1224 }, + { 18581, -15894, 5132, -430 }, + { 19823, -16717, 4142, 545 }, + { 19960, -19423, 8400, -1492 }, + { 18973, -16817, 5906, -594 }, + { 19079, -15431, 3528, 503 }, + { 16667, -12485, 4467, -1302 }, + { 19791, -17797, 6196, -529 }, + { 20005, -17606, 5354, -20 }, + { 20123, -18599, 6886, -728 }, + { 19068, -14805, 2394, 1105 }, + { 14443, -13723, 5631, -2029 }, + { 14730, -14231, 5631, -1450 }, + { 16089, -15959, 7271, -2029 }, + { 13473, -11200, 3236, -924 }, + { 14413, -10902, 2347, -267 }, + { 17666, -18662, 11381, -3496 }, + { 14749, -11042, 3305, -275 }, + { 15304, -10486, 1869, -240 }, + { 14809, -12126, 3369, -616 }, + { 16896, -16561, 7307, -1845 }, + { 15782, -14336, 5380, -1264 }, + { 16395, -15520, 6415, -1588 }, + { 13681, -11114, 2584, -320 }, + { 14244, -12326, 4480, -1632 }, + { 15247, -13119, 4265, -898 }, + { 13987, -12091, 3469, -597 }, + { 13941, -12770, 4240, -839 }, + { 13771, -13627, 5252, -1384 }, + { 15010, -16074, 7592, -2249 }, + { 15852, -17226, 8619, -2655 }, + { 18921, -16916, 6875, -1501 }, + { 14909, -11678, 2768, -295 }, + { 18988, -18353, 8424, -2070 }, + { 15457, -15080, 6218, -1513 }, + { 14916, -15512, 6949, -1883 }, + { 18108, -14702, 4681, -701 }, + { 17600, -15733, 5616, -775 }, + { 14070, -13683, 6472, -2626 }, + { 13832, -11914, 5201, -2232 }, + { 18846, -19009, 9192, -1961 }, + { -11981, -10994, -6324, -2264 }, + { -10976, -9047, -6546, -3828 }, + { -11288, -10532, -7014, -4191 }, + { -10139, -10189, -7799, -2688 }, + { -10555, -9988, -9181, -2040 }, + { -11596, -11339, -10022, -2707 }, + { -13400, -13395, -11306, -4206 }, + { -9774, -12281, -7466, -4133 }, + { -10842, -13125, -8777, -4956 }, + { -11964, -15082, -9779, -5095 }, + { -9382, -10188, -9053, -4927 }, + { -11562, -11296, -3651, -985 }, + { -9287, -10083, -7918, -4069 }, + { -12821, -16556, -11410, -6195 }, + { -12628, -8959, -4521, -1113 }, + { -13845, -11581, -3649, -681 }, + { -12685, -10269, -5483, -1275 }, + { -14988, -12874, -5107, -1189 }, + { -13761, -11367, -6202, -1804 }, + { -13225, -11249, -7820, -3354 }, + { -14809, -11992, -3202, -312 }, + { -15620, -15519, -10210, -3433 }, + { -12954, -10200, -3139, -611 }, + { -11536, -9981, -5284, -923 }, + { -13034, -12417, -4612, -1098 }, + { -16911, -15505, -6123, -1352 }, + { -17396, -17685, -8330, -2171 }, + { -14120, -10764, -2265, -99 }, + { -12598, -7367, -5406, -3530 }, + { -14143, -12793, -10909, -5226 }, + { -14692, -16871, -11626, -5554 }, + { -12581, -11197, -9194, -3837 }, + { -16752, -16726, -9746, -2808 }, + { -10600, -10358, -6560, -1227 }, + { -14573, -13312, -8957, -3393 }, + { -10172, -8463, -8579, -3387 }, + { -11418, -12421, -5522, -1842 }, + { -11855, -14204, -6669, -2625 }, + { -13308, -8191, -3941, -2194 }, + { -10007, -12266, -5022, -1811 }, + { -13532, -15771, -9497, -3175 }, + { -11760, -11148, -10339, -5529 }, + { -12149, -12763, -11198, -3697 }, + { -12029, -12119, -8555, -1792 }, + { -16995, -19957, -11447, -3471 }, + { -13144, -14504, -9988, -3191 }, + { -9938, -11064, -6139, -3162 }, + { -8873, -11550, -8294, -6550 }, + { -9303, -13010, -6150, -2711 }, + { -15463, -10469, -1766, -170 }, + { -15985, -11693, -3007, -650 }, + { -17142, -10671, -1434, 47 }, + { -16063, -13858, -4817, -1058 }, + { -19446, -19599, -9594, -2464 }, + { -20076, -18744, -8313, -1889 }, + { -15047, -16085, -7590, -2250 }, + { -13481, -16195, -8552, -2998 }, + { -13829, -14869, -6704, -1932 }, + { -16357, -18484, -9802, -2959 }, + { -10551, -8393, -9303, -5070 }, + { -11345, -9156, -5641, -3107 }, + { -13217, -13449, -9270, -4541 }, + { -11988, -13732, -9995, -6374 }, + { -11007, -9519, -5168, -4107 }, + { 9930, -7858, 8061, -4375 }, + { 8274, -7867, 5992, -2096 }, + { 9692, -9675, 7621, -3670 }, + { 9589, -8110, 6509, -3010 }, + { 12617, -11976, 10122, -5360 }, + { 11867, -8895, 7948, -5323 }, + { 10388, -10482, 9234, -4324 }, + { 8188, -8220, 7810, -2737 }, + { 10407, -8787, 4806, -1930 }, + { 10348, -8845, 9233, -6614 }, + { 9422, -7091, 4820, -2878 }, + { 9758, -9796, 5584, -2256 }, + { 10188, -7994, 5347, -3343 }, + { 11133, -7455, 4015, -2306 }, + { 10676, -10744, 6093, -2629 }, + { 11522, -12184, 7848, -3375 }, + { 8805, -9883, 5317, -3071 }, + { 9498, -9654, 6555, -3592 }, + { 10488, -8008, 4066, -1252 }, + { 11261, -8930, 6068, -2738 }, + { 12180, -10397, 5027, -1531 }, + { 9138, -8531, 3601, -1959 }, + { 8107, -8380, 4970, -2061 }, + { 9737, -13248, 6438, -2617 }, + { 11178, -10423, 2622, -522 }, + { 9572, -12372, 5199, -2019 }, + { 12057, -12144, 4147, -1099 }, + { 9047, -9925, 2516, -665 }, + { 10790, -8030, 5882, -4386 }, + { 7199, -8426, 6337, -2841 }, + { 7778, -8285, 3529, -3442 }, + { 7559, -10569, 3484, -1332 }, + { 9404, -8115, 7484, -5541 }, + { 7792, -11976, 5546, -2573 }, + { 9313, -10264, 7661, -5195 }, + { 6701, -10725, 4370, -1784 }, + { 4918, -11361, 4507, -4527 }, + { 5147, -12305, 3978, -5556 }, + { 6525, -9899, 4481, -3129 }, + { 7538, -12855, 6060, -4826 }, + { 8659, -12111, 7159, -4430 }, + { 8440, -11304, 4547, -1747 }, + { 9216, -10918, 3507, -1195 }, + { 6165, -9254, 4771, -4677 }, + { 9163, -11019, 5637, -4935 }, + { 13441, -11509, 6676, -2434 }, + { 7912, -9398, 6663, -4048 }, + { 11723, -13745, 8131, -4148 }, + { 6065, -10257, 5005, -6327 }, + { 11618, -12417, 5336, -1894 }, + { 8891, -13924, 8407, -6131 }, + { 9622, -12563, 7908, -5109 }, + { 11479, -10315, 8349, -3991 }, + { 11676, -14103, 6611, -2330 }, + { 11951, -8953, 3829, -1550 }, + { 10486, -8044, 10493, -5920 }, + { 11801, -10769, 9763, -5305 }, + { 6109, -8676, 5827, -1346 }, + { 7030, -9611, 5624, -5761 }, + { 12808, -12886, 8683, -4148 }, + { 13213, -10464, 6381, -3189 }, + { 11796, -13681, 10703, -6075 }, + { 9639, -7949, 9625, -3944 }, + { 8538, -6997, 5309, 453 } +}; + +/* quantization tables */ + +static const uint32_t scale_factor_quant6[64] = { + 1, 2, 2, 3, 3, 4, 6, 7, + 10, 12, 16, 20, 26, 34, 44, 56, + 72, 93, 120, 155, 200, 257, 331, 427, + 550, 708, 912, 1175, 1514, 1950, 2512, 3236, + 4169, 5370, 6918, 8913, 11482, 14791, 19055, 24547, + 31623, 40738, 52481, 67608, 87096, 112202, 144544, 186209, + 239883, 309030, 398107, 512861, 660693, 851138, 1096478, 1412538, + 1819701, 2344229, 3019952, 3890451, 5011872, 6456542, 8317638, 0 +}; + +static const uint32_t scale_factor_quant7[128] = { + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 5, 6, 7, 7, 8, + 10, 11, 12, 14, 16, 18, 20, 23, + 26, 30, 34, 38, 44, 50, 56, 64, + 72, 82, 93, 106, 120, 136, 155, 176, + 200, 226, 257, 292, 331, 376, 427, 484, + 550, 624, 708, 804, 912, 1035, 1175, 1334, + 1514, 1718, 1950, 2213, 2512, 2851, 3236, 3673, + 4169, 4732, 5370, 6095, 6918, 7852, 8913, 10116, + 11482, 13032, 14791, 16788, 19055, 21627, 24547, 27861, + 31623, 35892, 40738, 46238, 52481, 59566, 67608, 76736, + 87096, 98855, 112202, 127350, 144544, 164059, 186209, 211349, + 239883, 272270, 309030, 350752, 398107, 451856, 512861, 582103, + 660693, 749894, 851138, 966051, 1096478, 1244515, 1412538, 1603245, + 1819701, 2065380, 2344229, 2660725, 3019952, 3427678, 3890451, 4415704, + 5011872, 5688529, 6456542, 7328245, 8317638, 0, 0, 0 +}; + +/* 20bits unsigned fractional binary codes */ +static const uint32_t lossy_quant[32] = { + 0, 6710886, 4194304, 3355443, 2474639, 2097152, 1761608, 1426063, + 796918, 461373, 251658, 146801, 79692, 46137, 27263, 16777, + 10486, 5872, 3355, 1887, 1258, 713, 336, 168, + 84, 42, 21, 0, 0, 0, 0, 0 +}; + +static const float lossy_quant_d[32] = { + 0, 1.6, 1.0, 0.8, 0.59, 0.50, 0.42, 0.34, + 0.19, 0.11, 0.06, 0.035, 0.019, 0.011, 0.0065, 0.0040, + 0.0025, 0.0014, 0.0008, 0.00045, 0.00030, 0.00017, 0.00008, 0.00004, + 0.00002, 0.00001, 0.000005, 0, 0, 0, 0, 0 +}; + +/* 20bits unsigned fractional binary codes */ +static const uint32_t lossless_quant[32] = { + 0, 4194304, 2097152, 1384120, 1048576, 696254, 524288, 348127, + 262144, 131072, 65431, 33026, 16450, 8208, 4100, 2049, + 1024, 512, 256, 128, 64, 32, 16, 8, + 4, 2, 1, 0, 0, 0, 0, 0 +}; + +static const float lossless_quant_d[32] = { + 0, 1.0, 0.5, 0.33, 0.25, 0.166, 0.125, + 0.083, 0.0625, 0.03125, 0.0156, 7.874E-3, 3.922E-3, 1.957E-3, + 9.775E-4, 4.885E-4, 2.442E-4, 1.221E-4, 6.104E-5, 3.052E-5, 1.526E-5, + 7.629E-6, 3.815E-6, 1.907E-6, 9.537E-7, 4.768E-7, 2.384E-7, 0, + 0, 0, 0, 0 +}; + + +/* Vector quantization tables */ + +DECLARE_ALIGNED(8, static const int8_t, high_freq_vq)[1024][32] = +{ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -4, -2, 2, 1,-16,-10, 1, 3, 1, 0, 6, 1, -3, 7, 1,-22, + 2, -4, -3, 11, 14, 6, -1, 1,-13, 29,-28, 10, 10, -8, 0, -9 }, + { -8, 8, -7, 10, -3,-12, -5, -8, 1, -2, 9, -2, -5,-18, 1, 9, + -8, -8, 3, 41, 7, -9, -9, 22,-42,-29, 14,-18,-14,-32, 1,-15 }, + {-16, 8, 15, 16,-16, 5, 2, 7, -6,-16, -7, 1, 1, -3, -2, 0, + 8, 20,-26,-11, 2,-17, 0, -3,-34,-37, 10, 44, -2, 22, 2, -4 }, + { 7, 14, 5, 6, 15, -1, 3, -3, -9,-23, -5,-14, 8, -1,-14, -6, + -5, -8, 54, 31, -6, 18, 2,-19, -2,-11,-30, -6,-19, 2, -2,-14 }, + { 1, 2, -2, -1, -3, -3, 1, -5, 1, -3, -4, -8, 5, -4, 0, 1, + 3, 7, -5, -4, -3,-12, 3, -2, -3, 12,-53,-51, 6, -1, 6, 8 }, + { 0, -1, 5, 1, -6, -8, 7, 5,-18, -4, -1, 1, 0, -3, -3,-14, + -1, -6, 0,-14, -1, -1, 5, -3,-11, 1,-20, 10, 2, 19, -2, -2 }, + { 2, 4, 3, 0, 5, 0, 3, 1, -2, 0, -6, -3, -4, -5, -3, -3, + -7, 0,-34, 4,-43, 17, 0,-53,-13, -7, 24, 14, 5,-18, 9,-20 }, + { 1, 0, -3, 2, 3, -5, -2, 7,-21, 5,-25, 23, 11,-28, 2, 1, + -11, 9, 13, -6,-12, 5, 7, 2, 4,-11, -6, -1, 8, 0, 1, -2 }, + { 2, -4, -6, -4, 0, -5,-29, 13, -6,-22, -3,-43, 12,-41, 5, 24, + 18, -9,-36, -6, 4, -7, -4, 13, 4,-15, -1, -5, 1, 2, -5, 4 }, + { 0, -1, 13, -6, -5, 1, 0, -3, 1, -5, 19,-22, 31,-27, 4,-15, + -6, 15, 9,-13, 1, -9, 10,-17, 4, -1, -1, 4, 2, 0, -3, -5 }, + { -7, 3, -8, 13, 19,-12, 8,-19, -3, -2,-24, 31, 14, 0, 7,-13, + -18, 0, 3, 6, 13, -2, 1,-12,-21, 9, -2, 30, 21,-14, 2,-14 }, + { -3, -7, 8, -1, -2, -9, 6, 1, -7, 7, 13, 3, -1,-10, 30, 4, + -10, 12, 5, 6,-13, -7, -4, -2, -2, 7, -3, -6, 3, 4, 1, 2 }, + { -8, 9, 2, -3, -5, 2, 0, 9, 3, 7, -4,-16,-13, 3, 23,-27, + 18, 46,-38, 6, 4, 43, -1, 0, 8, -7, -4, -1, 11, -7, 6, -3 }, + { 1, 1, 18, -8, -6, 0, 3, 4, 22, -3, -4, -2, -4,-11, 40, -7, + -3,-13,-14, -7,-10, 14, 7, 5,-14, 11, -5, 7, 21, -2, 9, -3 }, + { 0, 0, -2, 4, -2, 0, 2, 0, -1, 2, -1, 0, 0, 2, 2, 2, + -1, 1, -3, -1,-15, -2,-63,-27,-21,-47,-14, 1,-14, 10, 0, 2 }, + { 1, 0, -4, 0, -3, -9, 4, 2, 6, -6, 0, -5, 11, -7,-15, 6, + -7, -6, 3, 7,-15, -5, 23,-13, -6, 12, -8, 9, 2, -3, 3, 4 }, + { 6, 0, 3, 0, -2, -4, 2, 1, 1, -1, 1, -2, -1, -4,-22,-15, + -46,-66, 10, 20, 2,-17, 12, -6, 1, -2, -2, 0, 1, -5, 1, 2 }, + { -1, 0, 0, 1, 0, -4, 0, 1,-10, -3, -8, 5, 7,-11, 2,-11, + 29,-25, 11, 10, 0, -1, 5, -7, -2, -5, -2, 4, 4, -3, 5, -2 }, + { 1, -1, -1, -3, -2, 1, -8, -3, 2, -2, 4, -5, -1, -7, -2, 1, + -14, -7, 3,-30,-15,-14, 3, -4, -1, 3,-13, -1, -3, 1, 2, 3 }, + { -1, -2, -3, 2, 2, -3, 3, 1, -3, 2, 0, -4, 6, 5, -5, 10, + -57, 3, 22,-50, 1, -2, -5, -6, -1, 5, 1, 2, 2, 1, -2, 2 }, + { 2, 0, -1, -7, 2, 1, 3, 2, 0, 4, 3, -2, 3, -3, 4, -4, + 24,-35, -3, 38, -6, -5, 15, 20, 3, 16, -7, -5, 0, -4, -5, 0 }, + { 0, 1, 0, 0, 0, -1, -1, 1, 1, -1, 1, -2, 0, 0, 0, 0, + 0, -1, -2, -1, -5, -2,-43, -3, 46,-52,-10, 7, -8, 11, -2, -1 }, + { 0, 0, -1, 0, -1, 2,-41, 33,-44,-48,-15,-26, -9, 6, 3, 3, + -3, 2, 2, 2, 2, -1, -1, -2, 1, 3, 0, 0, 5, 2, 3, 1 }, + { -4, 1, 6, 1, -6, -1, -2, 1,-14, -4, 0, -5, -2, 2, -2, 0, + -6, 1, 0, 8,-21, 32, -3,-36, -6, -2, -1, -7, 3, 0, 1, -6 }, + { -3, -2, 3, 0, 2, 2, 8, -4, -4, 6, 2, 1, 3, -6, 4, 3, + 13, 0,-12, -1, 25,-20, -2,-23,-15, 7, -3,-11, -3, 6, -1, 0 }, + { 0, 0, -3, -1, 0, 0, -2, -1, -2, -2, 1, -1, 0, 0, 10, 3, + -2, 3, 3, -7, -6, -5, 0, -4,-60,-16, -6, 38, 5, 6, -5, 0 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 1, 0, 0, 1, + 0, 0, -1, 0, -8, 2, -9, 10, 40, 31,-56,-21, 4, 20, -4, 7 }, + { -2, -2, 0, 4, -3, -1, 7, 3, 1, 3, -8, 0, 3, 1, 2, 5, + 1, -2, 14, 5, 4, 5, 5, 5, -5, 9,-66, 0,-20, -2, -8, 4 }, + { -2, -1, 4, -1, -8, -2, -4, -1, -3, -3, 2, -7, -3, 5, 7, -2, + 45, 31,-17,-16, -2, -2, -1,-22, 1, -1, -3, 3, 5, -3, 5, -1 }, + { -4, 0, 7, 5, 8, 7, 2, 9, -9, -9, -7,-11, -3, -8, 17, -4, + 34, 32, 18, 22, 1, 2, 1, -7, -5, 6, -1, 6, 4, 10, -2, -7 }, + { 6, 0, 14, 9, 6, -1, -2, -3, 4, -6, -8, 4, 7, -1, 28, 38, + 15, -1, 16,-11, 5, 8, 4,-10, 3,-10,-17, 5, 3, 3, 3, 1 }, + { 1, 1, 2, -1, 2, 1, 0, 0, -1, 0, 0, -2, 1, -3, 0, 1, + 2, -2, -4, -2, 0, -1, 1, -3, 1, 1, 1, -1, 8, 8, 66, 33 }, + { -5, 2, -3, -7, 2, -8, -4, 10, 17,-18, -7, 4, -4, -7, -6, -6, + -5, 5,-12, 2, 0, 6, 8, -2, 1, 4,-11, 2, 1, 8, 31, 19 }, + { 6, 9, 16, -6, -6, -1, -2, -3,-11, -2, 7, 7, 17, 3, 4, 10, + 2, 5,-13, 8, 7, 1, 4, 5, 7, 6, 7, -8, 9, -8, 33, 6 }, + { 3, -1, 1, 0, -7, -5, 0, 14, -7, 1, -7, 1, 2, -4, 7, 10, + -16, 12, 1, -6, 3, 8, -1, 10,-13, -6,-12,-23, 12, -3, 30, 14 }, + { -2,-15, 0, 8, 3,-19, 5, -3, 2, 3, 13, 7, 14, -3,-10, 0, + 8, 5, -6,-16, -8, -8, 14, 2, -1, 1, -9,-11, 11, -5, 27, 9 }, + { -8, 6, -4, 4, -4, -1, 5, 4, 1, -7, -5, -4,-15, 1, 9, 0, + 8, 4, 1,-17, 11, -2,-19, -1, -6, -8, 3,-12, 3,-17, 33,-10 }, + { -3, -1, 2, 7, 7, -2, 9, 8,-18, -1,-13,-10, -3, -3, 11, 8, + -2,-12, -8, 1, 4, 9, 14, 10, -3, 0, 2, 1, -2, 3, 31, 10 }, + { -3,-10, 8, -1, -5,-11, 7, -5, 3, 6, 1, 4,-16, 10, 5, -4, + -2,-10, -1, 13, 6, -5, -7, 12, 7, -3,-17, 1, 12, -4, 29, 8 }, + { 1, 2, 5, 2, -6, -7, 0, -1, 6, -1, 10, 6, -4, 5, 2, 2, + -2, -8, -6,-11, 14,-13, 27, 3, -2,-12, 5,-16, 2,-26, 20, 15 }, + { -1, -3, -5, -3, -3, 6, -1, 3, -5, 1, 7, 2, 1, 0, -1, -1, + 0, -1, 9, 7, -6, -3, 4, -5, -4, 8, -8,-25, -8, -4, 34, 23 }, + { -1, -2, 1, 1, -1, -2, -1, 1, -1, 0, 0, 0, 0, -2, -1, 1, + 0, 2, 1, -1, 4, 0, 0, 1, -1, 0, 5, 3, 12, -9, 68,-16 }, + { 10, 0, -8, 14, -6, 1,-12, 0, 0, -3, -5,-11, -6, 12, 9,-10, + -3, 5, 0, 7, 11, 2, 4, -3, -8, -3, 7, 4, 3, -3, 34, 4 }, + {-12, 13, -5, 7,-11, -2, -1, 1, -4,-14,-21, 3, -3, -3, -4, -7, + -9, -4, 3,-17, -2,-13, 10, -2, 12, -4, 0, -9, 1, -5, 31, 10 }, + {-10, 6, 5, 6, 4, -7, 10, 0,-28, -3, 0,-11, -1, -5, 16,-10, + -16, 7, 20, 2, -4, 2, -5, 0, 15, 6, 5,-10, 7, -9, 20, 4 }, + { 1, -7, -2, -7, 4, -3, -2, -7, -1,-14, 6,-16, 4, -5, -4, -6, + -5, 0, -2, 2, -6, 9, -5, 4,-18, 8,-10, 8, 15, 0, 32, 1 }, + { -5, 7, -3, 7, 15, -4, 0,-16, 9, 5, -5, 5, 4, -3,-12, -9, + -18, 10, 2, 2, -3, 7, 3, -1, 6, -9,-10, 3, 15, -4, 35, -7 }, + { -1,-10, 2, 2, -4, -2, 10, 2, -1, 2, -2, 1, -1,-14,-11, 3, + -8, 5, -8, -2, 6, -1, -7, 1, 7, 5, 7, 8, 30, -4, 30, 14 }, + { 2, -2, 1, 2, 3, -8, 3, 0, -2, 0, -9, 2, 1, 4, -6, -1, + -2, 5, 0, 1, -2, 12, 6, -3, 9, -3, 4,-12, 21,-39, 24, -2 }, + { 3, 5, 1, -2, -2, -2, -3, 6, -8, -2,-11, -8, -1, 4, 2, 2, + -4,-10, 12, -5,-11, 1,-15,-34,-11, -7,-11, -1, 7,-14, 38, -1 }, + { -4, 4, 8, 9, 8, 1, -5, -9, 4, -2, 15, -4, 11,-15, 20, -1, + -1, -3, 4, -9, -2, -2, -2, 8, 6, 12, -5, 0, 11,-12, 27, -4 }, + { 0, 8, -4, 3,-11, 6,-11, 2, 3, 0, 5, -8, -7, -6, -9,-21, + 4,-11, -1,-16, -7, 16, -3, 7, -7, 4, -5, 0, 11, -7, 31, 3 }, + { 1, 3, 4, 11,-11, -2, -3, -6, 6, 5, 0, 3, -9, -6, 4, -4, + 0, 4, -8, 13, -6,-13, -1, -5, -1, 4, 0, 0, 9,-22, 24, 18 }, + { -7, 3, 10,-13, -6, 6, -6, 6, 22, 1, 0,-14, 2, 3, 7, -1, + 8, 20, -1, 5, -4, 13, 9, -9, -9, 6, 0, -4, 0, -8, 31, -4 }, + { -3, -4, 0, 1, 7, 3, -7, 0, 5, -2, 1, 3, 3, 1, -5, -2, + 5, 2,-11, 4, 0, -1, 12, 0, -3,-13, 15, 8, -6,-27, 34, 0 }, + { -3, -3, 10, -4, 2, -1, -3, 0, -1, -1, -4, 2, 6, -2, 12, 1, + 3, -6, -7, -6, -5, 4,-19, -6, -8,-34, -4, -8, 10, -7, 23, 10 }, + { -7, 0, -1, -6, 8, 4, -4, 2, -5, -8, -7, -9, -8, 5, 9, 7, + -6, 1,-12,-12, -1,-16, 5, 0, 16, 3, -7, -8, 27, -4, 23, 15 }, + { -8, 4, 8, 5, 6, 11, -3, 5, 3, -1,-11, 6, -5, 0, 2, -6, + -3, -6, 4, -1, 5, -5,-12, -6, 7, -5, 9, 3, 6, -7, 29, 1 }, + { 1, 3, -2, -2, -6, -2, 1, 6, -6, -3, 1, 2, 3, 4, 1, 5, + -1, 0, 4, 2, 11, 6, 2, -3, 13, -9,-19, 18,-15,-10, 36, 21 }, + { -3, -3, 2, -1, -7, 6, -4, 1, -3, -1, -2, 2, 3, -7, -3, 0, + -2, 0, -2, 6,-19, 3, -8, 2, -6, 7, -1, 0, 29, -6, 28,-10 }, + { -5, 1, -3, -7,-12, -4, 1, 1, -1, 13,-10, -1, -9, -5,-13, 6, + 13, 3, -4, 2, 3, 11, 2, 6,-25,-16, -6, 0, 14, -1, 27, 16 }, + { -6, -1, -7, -5, -2, -5, -5, -1, 9, 1, 0, 3, -8,-12, -6, 5, + -6, 5, 3, -9, 1, 4, -7,-10, -9, -7,-17, -5,-15,-23, 25, 3 }, + { -8, -2, 9, -3, -4, 3, -1, 8, -7, -7, -5, -4, -2, 9, 4, -1, + -7, -4, -5,-16, 3, -6, 18,-13, -9, 16,-15, 8, 15,-10, 24, 5 }, + { 1,-38, 2, 34, 9, 10, 11, 2, 2, -6, 3, 2, -2, 5, 4, -7, + -1, 1, 4, 0, 3, 1, -8, -1, -6, 5, 4, 2, -4, 5, 2, -1 }, + { 1,-22, 15, 18, -2, 10,-16, -9, -8,-11, 8, 4, 0, 7,-14, -5, + -1, -7, 12, 17, 9, 5, -7, -4,-12, -6, 7, 0, 7, 2, -2, 1 }, + {-11,-29, 7, 10, 19, -1, -8, -9, 7, 1, 9, 6, 8, -7,-14, 8, + -3,-11,-13, 0, -7,-23, -2, -8, 12, 9, 2, 14, 19, 1, -1, 5 }, + {-24,-27,-11, 36, 2, 6, -3, 4, -6, 8, 0, 12, -1, -4, -6, 3, + 4, -1, 2, -3, -2, 3, 2, -1, -2, -4, 0, -1, -2, 7, 2, 3 }, + { -9,-24, 11, 13,-10,-12, 12, -2, 7, 4, 8, 13, -3, -3, 2, 9, + -3, -4, 4, 13, 5, 13, -6, -3, 1, 15, 7, -3, 0, 19, -2, -9 }, + { -8,-15, 7, 14, -4, -5, 2,-18,-19, -2, 2, 17, 16, 6,-10, 10, + -9, 14, -1, -5, -1, -6, -7, 2, 9, 11, 13, 6, -5,-12, 3, 2 }, + {-10,-37, 13, 1, 3,-14, 0,-20, 4, -3, 8, 2, -2, -3, -9, -5, + -3,-17, -1, 13,-11, 2, -6, 4, 4, 0, 3, 1, -9, -4, -5, -4 }, + { -2,-22, -5, 46, -8, 5, 9,-11, 8, 7, 7, -1, -1, -2, -7, 2, + -3, 3, -1, -2, 7, 0, 2, -1, 1, -2, -2, -3, 6, 0, -4, -6 }, + {-16,-27, 15, 16, -4, 14, -7,-26, 2, -2, 6, 5, -3, 11, 0, 2, + 3, 9, -7, -1, 2, -4, -4, -1, 6, 10, 1, 1, -3, -2, 3, 0 }, + { -3,-22, 10, 26, 1, 2, -3, 3, 17, -3, -7, 9, 1,-21, -4, 5, + 3, 0, -7, -6, 3, 3, -8, -7, -9, 3, 7, 1, -8, 12, 6, -7 }, + { -9,-25, 3, 18, 9, -6,-11, 0, -5,-12, 9, -8, -7, -6, -6, 22, + 2, -6, -3, 15, 3, 2, -2, 9, 14,-10, -7, 15, 13, 6, -2, 11 }, + { 5,-20, -5, 28, 11, 10, -4, -4, 0, -7, 3, 5, 2, -5, -8, 2, + 6, 10, 9, -9,-18, 3, 14, 1, 3, -3, -1, -6, 7, 7, 2, -1 }, + { -8,-30, 7, 12, 10, 8, 7,-13,-16, 0, 1, -1, -6,-11,-15, 4, + 1, -2, 10,-15, 1, 11, -2, 8, 9, -7, -7, 9, -5, 2, 7,-18 }, + {-10,-32, 10, 11, 3, -1, 3, -5, 5, 2, 14, -6, 3, 1, 5,-15, + -11, 6, 20, 4, 0,-12, -7, 3, 1, -1, 10, 6, -1, -9, -4, -1 }, + { 1,-25,-14, 12,-11, 9, 9,-16,-24,-17, 22, -9, 11,-30, -3, -4, + 6, -7, 9, 2, -1, -5, -6, 2, -1, -1, 10, 1, -3, 3, 4, 8 }, + {-14,-26, -6, 9, 8, 17,-11,-24, -7, -4, -8, -2, 10, 2, 2, -1, + 2, 13, 12, -7, 4, -6,-10, 6, 6,-13,-11, -7,-16, 0, -2, 5 }, + { -4,-30,-13, 12, 16, -6, 12,-16,-13, 5, 15, -2, -2,-10, -7, 7, + 11, -1, -4, -2, -4, 7, 4, -8, 1, 3, 0, 11, 3, -2, -5, 4 }, + { -4,-21, 20, 22, 2, 20, -8, 1,-12, -5, -9, 4,-10,-17, -3, -8, + -3, 3,-12, 1, -3, 0, 7, 4, 7, 7, -3, 7, 5, 3, 1, -5 }, + {-12,-20, 2, 29, 11, -6, 9, -7, -6, -4, 0, 6, 17,-13, -2,-10, + -17, -1,-18, 2, 0, 14, -6, 1, 0, 3, 2,-10, 1, -5, -2, 5 }, + { 16,-37, -1, 26, -2,-14, 1, -5,-14, 2, 2, 3, 6, 1, 1, 4, + 0, -1, 0, -2, -2, 4, 9, -6, 0, -2, 10, -7, -2, 4, 1, 0 }, + { -9,-24,-12, 5, 5, 3,-17,-14, 4, 3, 2, -4, 10,-22, -8, -3, + 6, 1, 12, -8, 4, 1, 9, -1, 18, -3, 6, 5, 3, -5, 9, -5 }, + {-14,-33, -2, 20,-13,-10, 2, -7, -1, 11, -9, -8, 18, -3, 1, 8, + 0, -2, 10, 7, -2,-13, 9, -3, -4, 5, -2, -2, -1, -5, 1, -7 }, + {-10,-23, 8, 14, 1, 7, 1, -3, -7, 4, 1, 1, 8, -7, 15,-14, + 13, 14, 2, 5,-13, -5, -8, -1, 6, 3, 6, 9, 6, 15, 14, 5 }, + {-13,-25,-10, 13,-17,-24, -7,-13, -6,-10, -8, 2, 0,-13,-10, -4, + -8, 4, -9, 9, -4, 4, -3, -3, 3, 3, -5, -9, 1, -2, 11, 2 }, + {-12,-23, 1, 18,-11, -2, 5, 9, -5, 5, 14, -9, -3, -2, -6, 2, + -2, 11,-13, 1, -3, 11, -9, -4, -2, -6, 8, 10, 1, 4, 2, 1 }, + { -5,-18, 16, 22, 2, 0, 8, -6, -9, -7, 10,-16, 23, 10,-11, -1, + 7, 2, 7, 2, 1, -5, 6, 1, 0, -4, 9, 2, -3, 1, 0, -4 }, + { -3,-26, 14, 11, 2, -9, 17, -2, -1, -5,-16, -9, -5, 10,-13, 1, + 6, 12, 10, 11, 0, 0, -3,-14, 6, -2, 0, 4, -5, -1, -7, -1 }, + {-10,-33, 1, 8, 11, -5, 1, -6, 7, 4, 5, 6, 1, -2,-10, -5, + -6, 12,-11, 5,-10, 4, 12, -1, -1, -3, 4, -1, 9, 0, 16,-17 }, + {-14,-37, 7, 7, -2, 5, -8,-11, 2,-13, 4,-19, 1, 8, 8, 4, + -9, 2, -4, 3, 12, 2, 4, -4, -8, 8, 1, 4, 8, -1, 6, -2 }, + { -6,-30, 18, 17, 1,-22, -3, 4, -7,-10, 7, 0, -8, 8, -1, 4, + 2, 8, 6, -2, 2, 7, 4, 4, 3, -6, 2, 1, -3, 1, -1, -5 }, + {-17,-18, -3, 22, -8, 1, 9, -2,-17, 20, -5, -5,-12, -5, 4, -5, + -9, 8, -2, 16, -3, 0, 19, -8, 8, 1, 2, -4, 0, 11, 0, -3 }, + { -9,-23, 3, 10, 4, 4, -3, -2, -2, -2, 1,-22, 11, 0, -2, 5, + -2, 14, -9,-11, -4, 7, 5, 32, 1, -3, -7, 0, 21, -9, 7, -6 }, + { 0, 0, 0, 2, -1, 1, 0, 1, 3, 0, 0, 1, 0, 1, 0, 1, + -3, 0, -1, -2, 0, -1, -1, -3, -1, 1, -4, 1, -1, -5,-69,-19 }, + { -3, -5, -8,-12, 4, -3,-19,-11, -5, 0,-14, 7, 18, -6, 7, 22, + 8, 14, 15, 10, 3, -1, -3, 5, -1, 7, -7, 1, -6, 3,-26,-11 }, + { -1, -6, 4, -4, -5,-16, 0, -6, -3, 11, 1, 0, 9, 5, 16, 3, + -4,-33, -4, 4, -7, 0, 1, 6,-11, -2,-13, -2,-18, 20,-25,-16 }, + { 4, 0, -1, 0, -5, 1, 0, 2, 0, 11,-10, 4,-10, 7, 16, 2, + 16, 15, 2, -1, 2, 9, 2, 8, -3, -5, -2, 0, -3, 0,-33, -2 }, + { -3,-15, 10, 10, -9, -1, 7, 3, 5, -5, -8, -8, -3, 15, -9, 4, + 12, 13,-13,-14, 10, -6, 9, 22,-27, 23, -1, 5,-24, 2,-30, 5 }, + { 0, -2, 7, -5, -5, 3, 5, 3, -3, -5, 2, 1, -4, 3, -3, -1, + 1, -2, 10, 22, -3, -4, -2, -2, -7, 3, 8, 1, 14, 4,-37, 9 }, + { -3, -4, -1, 1, -4, 0, 6, 2, 6, -7,-10,-10, -1, -4, 11, -3, + 7, -6, 4,-12, -1, 5, 1, -7, 10, -6, 17, -4, 8, 3,-40, 13 }, + { 2, 12, 4, -7, 14, -3, 16, -2, 18, 2, 13, 5, 5, 1, 11, -1, + 0, 9, 2, -6, -1, 2, -6, 2, -5, 3, 5, 1, -1, 1,-32, -7 }, + {-16, 11, 7, -4, 2, -5, -9, 9, 11, 11, 15,-13,-11, 11, 9, 4, + 3, -8,-10, 12, 12, 0, 0,-16, -9, 13, 2, 9, 4,-13,-33, 3 }, + { 6, 4, 5, 4, 3, -1, 5, 6, 4, 2,-11, -1,-15,-11, -1, 1, + 11, -3, -2, 24, -4, -6,-25,-10,-15, -8, 0, 0, -5, 4,-30, 2 }, + { 10, -3, -6, 1, -9, -5, 6, 9,-10, -3, 8, -1, 4, -1, 11,-11, + 3, 9, 11, -3, 6,-17, 5, -8,-33, 9,-13, 19, -2, 9,-25, 2 }, + { 0, 0, -1, -3, 0, -2, 1, 0, 0, 2, 1, 0, -2, 0, -1, 2, + 0, -1, 4, -1, 2, -3, 4, -2, 3, 3, 1, 0,-15, 12,-63, 27 }, + { -2, 14, 9, -1, 3, 0, 1, 1,-19, 15, 3, 4, 0,-10, 1, -5, + 3, 0, -5,-10, 2,-16, -4, 8,-12, -6, 7, -5,-10, -1,-33, -4 }, + { 0, 3, 1, 3, 1, 2, 4, 4, 9, -6, -8, -5, 1,-12, 3, 8, + -10, 6, -1, 1, 13, -5, -5, 2, -4, 13,-18,-10, -7, -9,-33, 10 }, + { -6, -3,-12, 5, -1, 11, -6, 0, -2, 1, 2, -7, 3, 1, 3, -2, + 1, 8,-10, 7, -1, -3, 3, 0, 13, 1, 6, 7,-16, -7,-39, 8 }, + { -6, -1, 11, 6, -3, 8, 3, -5, 3, 0, -5, -2, -6, -3, -4, 2, + -3, 13,-11, 1, 7, 5, 19, -5, -3,-15, -1, 7, -1, 6,-33, 8 }, + { -7, 3, -4, -3, -4, 1, 6, -5, -5, 6, -8, -1, -7, 4, -1, -6, + -2, 1, 7, 0, 1, 1, -5, 2, -2, 0,-13, -2,-31,-14,-39,-12 }, + {-10, 9, 0, -3, 1, -1, -1, 0, 1, -5, -1, -4, -2, 5, 2, -7, + 18, -8, -2,-19, -7, -7,-12,-14,-11, -1, -9,-13, -7,-12,-31, -9 }, + { -3,-16, 10, 9, 1,-10,-12, 2, -2, 2, 7, -3, -3, 1, -4, -5, + -9, 5, 7, 3, -1, 4,-11, -8, 4, 13,-10, 13, 10, -4,-36, 1 }, + { -7,-12, 4,-20, -7, -7, 2, 11, -1, -2, 3,-12, 1, 0, -6, -7, + 6, 4, 13, 3, -3, 4, 3, -6,-12, 5, -5,-22,-13, -8,-37, -6 }, + { -7, 5, 3, 5, 7, 9,-14, -3, 10, 17, -1, 1,-12, 5, -6, 0, + -4, -9, 0,-11,-14, 3, 13, 6,-25, -8,-12, 4,-10, 18,-30, -1 }, + {-10, 6,-10, 6, 6, 1,-10, 0, -7, 5, -2, 17,-18, -4, 0, -3, + -16, -6, -3, -8, 5, 1, -4, 6, -7, 16, 6, 10, -1, 0,-32,-11 }, + { -1, 9, 9, -5, 4, 9, 6, 9, -4, -2, 7, 11, 4, 2, -5, -4, + -6, 0, 2, -3, -1, 5, 10, 0, 12,-10,-18, -3, -1, 14,-33, 2 }, + { 4, -8,-18, -4, -5,-11, 4,-10, -4, 9, 13,-12, 1, -6, 1, 2, + 4, -9, 8, 3, -6, 21, 13, -1, -2, 1, -2, 6, -7, 0,-30, 1 }, + { 6, -1, 2, -3, -1, -4, 6, -4, 0, 4, 2, 2, -9, 2, 6, 3, + -2, 4, -1, 9, -6, 0, 7, -8, 5, 19, -2, 9, -5, 2,-33, -8 }, + { 2, 1, 12, -5, -8, 8, 3, -2, -4, 1, -2, 5, -4, -9, -8, -8, + 7,-11, -4, 6,-10, 7, -1, -1, -2, -1, 16, 32, -7, 20,-33, -6 }, + {-18, 2, 6, 13, 9, 9, -1, 3,-17, 24, -2, -6, 28, 8, -2, 6, + 3,-10,-34,-16,-13, -4,-15,-11,-12, -3,-10, 4, -8, 4,-31, -4 }, + {-11, 0, 18, 2,-16, -9,-13, -2, -2,-12, -3,-22, 30, 0, 8, 3, + 9, -4,-16, 1, 0,-11, 15, -2, -4, 6, -5, 6, 1, 2,-25,-12 }, + { 14, -1, 5, 7, 3,-15, -8, 1, 5, -2, 12, 13, 11,-25, 3, 1, + 0, -2, -4,-16,-23, 0, -5,-17, 7, 5, -9, 6, -5, 2,-32, -7 }, + { 3, -1, 6, 14, 2,-12, -9, -9, 4, 7, 4, 6, 5, -8, 4, 2, + 4, 5, -2, 8, 8, -6, 0, 10,-20, -1, 3, -1, 8, 23,-33, -5 }, + { -3, 11, -6, 3, -4, 5, 7, 3, 4, 5, -2, 3, -1, 30, 6, 1, + 8, -6, 0, 0, -9, 6, -9, 4, 2, 9, -6, 1,-12, 0,-34, 18 }, + {-17, 13, 0, 1, 9, -4,-11, 0, 7, 0,-10, -4, -1, 6, -6, 4, + 1, 6, -9, 3, -5, -6,-11, 2, -4, 14, 23, -3, 2, 5,-30, 12 }, + {-14, 5,-27, 2, 0, 7, 1, 4, 30, 8, 7, 5, 1, -1, 0, 5, + 8,-10, 48,-11, 12, 33, 6, 8,-15, 20, -2, -5, 32, 5,-19, 10 }, + {-16, -4,-12, -7, -2, 0, 8, -6,-20,-18, 16, -3, 0, 31, -2, 11, + 2, -9, 49,-19,-12,-23, 10, 26, 16, -2, 4,-21,-14, 13,-11, -9 }, + { -5, -9, -1, 3, -5,-21, 2, 10, 0, 0, 10,-21, -7, 7,-26, -9, + 22, 32, 58, 11, -3, 11, -5, -8,-13, 6, -5, -9, 1, 10, 14, -8 }, + { 7, 7, 10, 3, -2, -1,-11,-11, -6,-43, -3, 14,-19,-18, 19, 18, + -32, 10, 45, -6, 6, 21,-20,-12, 2, 4, 6, 6, -4, 3, 3, 1 }, + { 21, 22, -3, -2,-11, -6, -1, -2, 8, 8, 32,-21, 7, 28, -4, -6, + -3, -2, 50, 2, 2, 27, -5, -8, 12, 7, -5, -1, -4,-17, 27, 6 }, + { 13, 7, 2, -6,-12, 2,-10, -5,-17, 11, 4, 17,-12, -2, 5,-17, + 37,-16, 48,-14,-18, 29, 8, 24, 11, -5, -9, 11, -1, 1,-13, -3 }, + { 1, 1, -1, 2, 0, 0, 0, -1, 1, -1, 7, 2, -3, 3, 0, 6, + 2, 10, 54,-25, 7, 54, -5, -6, -1,-15, 9, 13,-24,-15,-12, 3 }, + { 21, 5, 8, 3, -3, -4, -2, -4, 3,-11, -5, -8, 9, 16, 8, -9, + -10, -3, 46,-46, 2, 1,-10, 10, 17, 11,-20,-36, 10, 14, 0, -5 }, + { 7,-13, -6, -9,-24, 45, 2, 8, 8, 0, 17, 20, 12,-24, 1, -7, + -15, -3, 46,-13, -2, 20, 1,-13,-11,-13, 2, 15, 1, 10, -1, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, -1, + -16, -9, 31,-69,-34, 26, 7, 17, -1, -6, -1, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, + -5,-20, 18,-82, 22, 3, -7, 9, 4, 6, 2, -4, -1, 0, -2, 2 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, -1, + 15, -5, 62,-36, 4, 52, -7, 5, 0, 6, 1, 2, 1, 1, -1, 0 }, + { 3,-19, 19,-20, 13, -4,-11, 8, 8,-16, 10, 1,-14, 30, 1,-33, + 10,-11, 45,-30, 3, -4, -3,-13, 7, 12, 3,-22, 3, -2, -4, -2 }, + { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, + 11, 8, 70, 48,-10, 21, 4, 9, -9, -9, -4, -6, 0, -1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 2, -1, 80, 2,-15,-36,-10, -5, -2, 8, -2, 2, 0, 0, 0, 0 }, + { 10, 8, -8, -8,-24, 12, -1, 0, 20, 9, -1, -2, 2, -2, 12,-10, + -2,-13, 35,-43, 44, 15,-10,-25, 4, 10, -3, -5, -5, 7, -1, 3 }, + { 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -1, + -18, 9, 49,-72, 7, -8, 7, -5, 2, 3, 2, -2, 1, -2, -3, 1 }, + { -1, 4, -3, 10, 19, 4, 3, 20, 6,-24, 6, 9, 8, 15, 18, 18, + -36, 19, 57,-11, 4, -3, 8, 7, 2, -3, -2, -9,-15, -2, 12, -4 }, + { 20, 3, 11, -9, -4, 22, 42,-25, 1, 5,-10,-19, 0, 9,-16, 5, + 2, 10, 44,-29, 17, -3, -9, -2, -1, 8, 14, -7, -1, 16, -5, 1 }, + { -7, 16,-11, 12, 6, 33,-15, 14,-23, 2,-26, 8, 2, 10, 0, -5, + 8, -8, 38,-38, -4, 5, 5, 5, 1, 22,-15, 7, 6, 0, 4, 28 }, + { -1,-12, 2, 10, -2, 0, 7, 17, 12, 22, -4, 10, 25, 29, 5, 18, + 4, 1, 27,-39, 31, 17, 2, 2, 22,-23, 13, 16, 1, -7, -4, -5 }, + { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 0,-14, 0, + -7,-11, 49,-22, -4, 19, 17,-39, 4,-29, 10, 2, 36, -4, 23, -1 }, + { -2, -2, -2, -2, 1, 15, -5, -7,-16, -8,-19, 16, -3,-20, 36, -9, + -3, 20, 39,-20, 0, 2, 27,-16, 10, 10,-14,-22,-16, -3, 13, -8 }, + { 5, -9, 6,-25, 7, 37, 13,-10, -5, 3, -5, 7, 18,-22, -7, 9, + -5, -4, 50,-11, -4, -5, -5, 8, -4, -2, -4,-27, 14, 20, 7, -9 }, + { 0,-14,-10,-27,-14,-17, -6, 26, 10, 2, 14,-12, -5, 0, 8, 9, + 0,-28, 55, -7,-12, -7, 4,-10, 10, 7,-12, 11, 3, 5, 9, -8 }, + { 2, 23, 4, -2, -1,-20, -2, 14, 10, -9, -9,-24, 10, 0, 11,-12, + 12, 11, 49,-25, -2, 29, 7,-13, 21,-10, 11,-17, 3, 1, -8, 5 }, + { 3, 0,-14, -6, 18, -2, 17, -9,-19, 9, -5, 9, 14, 6, 19, -3, + 27, 1, 41,-21, 20,-15, 33, 0, 26, 14, 7, 10, 3, 20, -3,-12 }, + { -1, 16, 15, -8, 3, -8, -8, 21, -5,-16,-29, 4, 1, -6, -4,-28, + 2, 31, 37,-26, -2, 13, 24, 8, -9, -6,-29, 10, 7, 2, 7, 8 }, + {-10,-10, 11, 13,-32, 2, 16, 9, 14, 23,-15,-13, 24, 13, 4,-27, + 14, 12, 31,-18, 17, 23, -2, -7,-14, 9,-17, -6,-10, 20, 9, 6 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + 5, 1, 89, 8, 10, -6, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, + 4, -7, 64,-50, 7, 37, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -2, 5, 3, -4, -4, -3, 2, -3, 3, -3, 5, 4, 1, -6, -1, 1, + 6, -2, 50,-35, -7, 43, 7, -7, -5,-26, 24, 21, 3,-15, 5, 6 }, + { -8, 21,-19, 33, -8, 22,-11, 17, 3, 0, 0, -2, 1, -3, 6, -1, + 10, -8, 4,-11, -4, -5, 0, 8, -4, 3, 1, -4, 4, 2, 8, 4 }, + { -7, 5,-20, 9,-22, 3,-14, 1, 6, 13, 23, -2, -4, -7, 2, 0, + 11, 4, 6, 3, -7,-11, -7, 4, 5, 5,-12, 8, 2, 4, 7, -3 }, + { -7, 6, -4, 20,-20, 16, -2, 7, 6, 16, 11, 12, -7, -7, 5, 3, + -9, -4, 1, 2, 5, 2, 1, -9, -2,-17, -4, 6,-10, 7, -7, -6 }, + { -9, 18,-17, 12,-24, 1, -1, 4, 14, 9, 4, 3, 2, 8,-12,-14, + 4, -8, -4, 7, 7, 6, -1, 13, -9, -4, -1, 1, 0, -4, 15, 8 }, + {-25, 2,-11, 6, -5, 24,-28, -5, 8, 12, -2, 6, 8, -3, 8, -9, + -1, -5, -1, -5, 6, -1, -1, -1, -4, 8,-12, -2,-13, 7, 2, 1 }, + {-14, 14,-18, 20,-10, 12, -2, 9, 1, 0, 12, -2, 15,-10, 26,-17, + 16,-11, 10,-10, 9, -2, 4, -8, 2, -3, 4, 4, 2, -3, -5, 1 }, + {-18, 12,-18, 21, -6, 12, -6, 13,-25, 18, 1, 11, -9, -5, 0, 10, + -5, 3, -3, 8, -9, 7, 4, 2, -9, 0, 5, 0, 2, -3, 9, -8 }, + { -4, 16, 1, 18,-30, 9, 1, 6, -8, 13, 13,-12, -6, -1, 13, 7, + 6, 2,-15, -3, 5, 5, 1, -6, 1, -5, 0, 2,-16, 0, 3, -4 }, + {-21, 1, -2, 6,-43, 18, -1, 5, -1, 4, 6, -2, -1, -3, -1, -3, + 0, 1, 2, -9, 0, -1, 0, -2, 0, -1, -1, -2, 6, 0, 1, -2 }, + {-23, 10, 4, 7,-32,-11,-18, 2, -2, -7, -6, -3, -3,-12, 19, 3, + -5, -6, 16, -6, 16, 2, 16, 16, 8, -2, 13, 8,-15,-11, 2, 10 }, + { -8, 2,-13, 2,-29, 24,-20, 19, 1, 10, -4, 10, 1, 2, -9, 11, + -1, -2, 9, -5, 19, -7, 16, -9, -2,-18, 11, 1, 1, 0, 7, -3 }, + { -6, 3, 4, 13,-26, 10,-10, 28, -7, 28, 1, 7, 0,-14, 5, 7, + 4, -4, 3, -2, 3, 3,-11, 7, 6, 4, 0, -1, 2, -1, -3, 2 }, + { -6, 16,-31, 13,-10, 17, -6, 4,-14, 4, 4, -1,-10, 12, -5, 1, + -14, 15, 0, -8, 1, -5, 3, 3, 9, -5, 7,-20, 7, 4, 11, -5 }, + {-19, 3,-17, 14,-12, 16,-22, 18, 14, 8, -2, 4, 10, 12,-14, 4, + -3, 2, 3, 7, -7, 7, -6, 2, -2, -4, -5, 0, -5, -2, 2, 1 }, + { -9, -7,-11, 24,-36, -9,-11, 5, 7,-12,-13, 18, -2, 20, 1, -4, + -1,-10, 15, -6, 14, 1, 0, 2, 1, 2, -9,-16,-11, 7, 13, 0 }, + {-24, 24,-18, 18,-22, 14,-11, 13,-12, 11,-10, 11, -7, 11, -5, -4, + -1, 1, 5, 2, 3, -1, 1, -5, 7, -4, 5, -6, 8, -7, 8, -6 }, + { -6, 18,-22, 22, 5, 11, -1, 6, 19, 22, 8, 4, -8, 20, -2, 15, + -6,-18, 0,-33, -9,-12, -1, 6, 5, 2, 5, 5, -5,-17, -3, -3 }, + { 1, 11,-16, 9,-18, 11, -4, 18, 20, 26,-10, 8, 1,-11, 8, -4, + 0, 7, 3, 5, 2, 2, 10, -2, -4, 4, -4, -2, 1, -4, -5, -1 }, + {-10, 6, -1, 18,-17, 27, -3, 10, -2, 12, -7, -9, 1, 1, -1, 7, + -12, -1, -7, -6, -1, 8, 3,-15, 8, 9, 3, -7, 4, -1, 1, -1 }, + {-14, 6,-16, 22, 2, 5, 0, 5,-18, 11, 6, -3, 22,-20, -9, -3, + 6, -6, -7,-15, 1, 15, -8, 11, 8, -3, -8, 1, -8, 2, 6, -2 }, + {-21, 5,-19, 19, -7, 4, -7, 0, -8, 6, 12, 5, -3,-22,-13, -6, + -1, -3, -2,-14, 6, -3, 1, -8, -7, -5, -6, 11, -3,-10, -5, 2 }, + { -1, 9,-12, 15, -6, 6,-19, 14, -9, 11, 3, 12,-17, -3, 8, -4, + -3, -4, 1, -5, 4, 5, -7,-15, -7, 15, -6, -5, 1, -5, -3, 1 }, + {-12, 20,-15, 20,-14, 3,-14, 9, -6, 33,-13, 6, -2, 8, -6, 7, + -5, -6, -3, -3, 0, 8, -3, -3, 1, -2, 2, 2, 6, -5, -5, -2 }, + { -7, 12,-18, 12,-18, 10, -4, 8, 2, 4, 8, 9, 0, 3, -8, 3, + 6,-12, -4, 1, 25, -5, -9, 6, -7, 0, -9, -7, 3, -5, -4, -4 }, + {-18, 12,-10, 11,-22, 0,-15, 5, -2, 2, -3, 6, -4, -4, -3,-15, + -2, -3, 21, 6,-12,-11, 19, 3, 3,-14, 7, 0,-11,-22,-10, 0 }, + {-15, 2,-30, 15,-17, 13,-16, 8, -7, 10, -8, 2, 11, 3, 10, -7, + 7,-22, 12,-10, 3,-12, 6,-10, 12,-10, 7, -8, 5, 2, 9, 1 }, + { -9, 11,-14, 6,-10, 21, 5, 12, -5, 5, 7, 21, 6, 2, -2, -1, + -1, 4, 2,-20,-18, -1,-14, 3, -1, 4, -7, 10, 1, 11, 4, -4 }, + {-22, 8,-30, 13,-21, -4, 4, -1, 12, 9, -2, -3, 2, -6, 4,-13, + -2, 8, 8, 1, -7, 3, -4, -5, -1, -7, -2, 8, 8, 7, 8, 0 }, + { -6, -4,-35, 16,-13, 15,-11, 14, -7, 9, -1, 11, 7, 0, 13, 10, + -1, 8, 1, 1, -2, 8, -1, 2, 2, 3,-10, -1, 7,-13, -3, -7 }, + {-15, 7,-16, 14,-18, 17, -6, 14, 3, 4, 7, -3, 10,-22, 5,-15, + 4, -4,-11, 15,-15, 11,-11, 20, 1, 0, 2, 1, 11, -3, 11, -7 }, + {-12, 3, 5, 16,-37, -1, 15, 15,-15, 10, 3,-10, 1, 15, 7,-15, + -13, 8, 9, -3, 2, 12, -8, 2, -5, 0, -3, 4, 5, -9, -4, 5 }, + {-16, 26, -4, 14,-22, 26, 6, -3, -8, 4, 21, 6, 16, -4,-11, 7, + -10, 3, 3, 7, -4, 2, -9, 8, -2, 2, 5, -2, -4, -2, 7, -1 }, + { -7,-10, 4, 3, 2, -4,-12,-10, -4, -5, 16, 19,-16, 1, 2, -9, + -10, 0, 9, 7, -8, 3, 12, 8, -6,-11,-13, -1, -3,-20, 6, -5 }, + {-14,-17, 3, -5, 14,-12,-12, 8, -6,-25, 21, 21, 10, -8,-12, 4, + 10, -4, 3, -9, 11, 9, 0, 4, 2,-15, 1,-14, 4, 1, 0, -4 }, + { -4, -9, -3, -1, 6, 3, -6, 6,-10, -4, 14, 8, 2, -3,-12,-19, + 0, 11,-20, 1, 6, -2,-27, -6, 10,-17,-14,-17, -9, 8, -8, 3 }, + {-12,-13, 16, -4, -2, 12, -7,-11, 2,-13, 3, 7,-16,-18, -1,-12, + -2, 1,-12, -9, -2, -6, 2, 9,-22, -3, -4,-14, -7, 7, -1, 2 }, + { -7, -8, -8, 15, 15, 18, 15, 16, -4,-37, 11, 15,-12, -1, -3, 3, + 6, 6, 0, -5, -3, -5, 9, 1, 1,-11, -1, -8, -6, 2, 3, 0 }, + { -6, 7, -5,-12, 13, 10,-18, -4, -3,-21, 6, 16,-15, -7,-12, -9, + 1,-12, -1, 10, -2, -1, -3, 4, -4, 1,-16, -1, 12, -9, 5, 9 }, + {-14, -5, 9, 3, 4, 26,-28, 3, -6,-24, 4, 5, 3, 13, 5, -1, + 3, -1, 3, 1, 1, -5, 3, 0, -7, -8, -7, -3, 3, -5, 4, 0 }, + { -4, 2,-10, -6, 25, 26, -6, 10, -6, -8, 15, 11, -6, -3, 2, -7, + 5, 14, 9, -1, 0,-12, 4, -4,-10, 1, -3, 3, -2, -2, -6, -1 }, + {-10, 8,-15,-10, 19, 17, -8, 0, -3, -7, 7, 5,-13, -1, 7, -7, + 1, 13,-12,-13, 17,-12, 1, 26,-18, -3, -5, -6, 4, 5, 8, 1 }, + { 2, -5, 3, 0, 0, 0, 2, -3, -2, -5, 7, 13, -4, 9, 0, -5, + 4, -1,-11, -8, -4, 0,-13, 2,-47,-23, -8,-11, -4, 4, -2, -3 }, + {-18, -4, 4, 5, -1, 17,-12, -8, 1,-12, 7, 20,-12, 3, -2,-11, + 16, 12, -6, 1,-13,-16, -6, -3, -3, -5, 4,-12, -5, -9, 10, 1 }, + {-11, 0, 4, 7, 7, 8, 3, -1, 3,-19, 32, 8,-19, -8, 2, 4, + -12, 15,-16, 3, 1, 9, -2, 1, -2, 8, 5, 6, -4, -1, 11, -8 }, + { 3, -1, 4, -2, 14, 32, -9,-23,-10,-12, 22, 15, -1, -2, 10, 0, + 4, 6, -8, 4,-15, -2, -1, -4, 0, -8, 4, 1, -8, 3, 4, 1 }, + {-17,-12, 6, -8, 16, 13,-20, -8, -1,-16, 10, 21,-19, 11, -9, -5, + 7, 18, -6, 7, -7,-18, 13, 2, -2, 8,-12, -9, 2, 4, -5, 16 }, + { 4, 0, 17,-11, 12, 7,-12, 5, -1,-25, 30, -8, -7, -6, -4, -7, + 9, 8, 7, 3, 3,-16, 8, 0, -2, -2,-18, -3, -4, -5, 1, 4 }, + { -3, -6, 6,-16, 17, 6, -3, 2, -9,-17, 12, 11, 11, 2,-20, 8, + 1, 1, 0, 2, -2, -6,-21,-13, -9,-15, -1, -8, -6, -8, 0, -2 }, + {-11, -7, 6, -9, 3, 6, 8, 16, 4, -5, 23, 26,-10, -3, 4, 0, + 2, 2, -4, 4, -2,-12, 12, 10,-11, 0,-10,-16, 3, 0, 0,-10 }, + { -5,-16, 10, -6, 27, 13, -3, 4, -2,-13, 15, 5, 2, 5, 3, -4, + 13, 12,-11, -7, 0, 1, 11, 12, 2, 13,-15, -8, 9, -2, 3, 8 }, + { -5, -8, 4, 3, 9, 3,-11, 10, 14,-25, 14, 8, -2, 5,-12,-21, + 2, 10, -7, 2, -3, 2, 0, 2, -1, -3, -5, -6, -1,-16, 2, 8 }, + { -1, 5, 1,-11, 5, 9, -7, 8,-13,-12, 4, 12, -4, 1, -1, -1, + 27, 29, 10, 15, 2, -6, -3, 4,-21, 10, -9,-11, -6, -1, -9, -3 }, + { -6, -3, -1, -6, 11, -5, 0, -2, -5,-31, 11, 3, -1, 5, -3, 4, + 5, 7,-10, 5,-10,-13, 4, 12,-15, -2, 2, -7, 1, -9, -3,-10 }, + { -3, -7, 17, -8, -5, 36, 8, -7, -8,-20, 12, 8, 1, -1, 3, 0, + 1, 4,-10, 3, 1, 4, -2, -3, -2, -3,-10, 4, -1, -7, 3, 2 }, + {-13, -3, -5, 9, 22, 6,-23, 3,-10, -7, 17, 17, 18,-14, -8, -8, + 2, 4, -8, 2, -3, -8, 6, 4, -1, 7, 0, 0, -3, 0,-12, -3 }, + { -3,-10,-15, -3, 9, 3,-23, -9,-13,-18, 12, 13, -2, 0, 1, 8, + -1, 2, -7,-12, -5, 14, 2, 1,-22, 6,-10, -8, -9, 28, -7,-14 }, + { -3, 1, 2, -1, 13, 7, -2, -7, 1, -3, 6, 9, -3, -2, 4, -2, + 2, 1,-10, -2, -2,-22, -2, -7,-10, -5,-11,-27,-12,-16, 4, -7 }, + { 2, -6, -3, 1, 8, 0, -2, 12, -3, -4, 58, 15,-10, -4, -2, 2, + -2, 0, -2, -6, 2, 4, -1, 1, -4, 1, -1, -5, -4, -3, 3, 1 }, + { 10, -1, 0, 5, 21, 7,-14, 6, -3,-16, 15, 17,-16, 13, 3, -6, + -4, 6,-12, -5, 1, -4, -7, -8, 2, 3, -6, 6, -1, -8, 5, 4 }, + { -6, -2, -8,-11, 15, 10, 0, 8, -6,-15, 33, 8, -2, 18,-15,-11, + 5, -1, 0, 15,-15, -4, -4, -1, 10, 7,-13, 4, -4, 0, 8, 3 }, + { -7, -2, 0, -2, 0, -2, -4, -5,-14,-16, 12, 38, 7, 12, 6, -4, + 0, -1, 0, 3, -2, -6, 0, 2, -9, 1, 0, -1, 0, -2, 4, 1 }, + { -8, -4, 18, 1, 14, 5,-12, -3, 20,-17, 5, 19,-11, -8, 11, -3, + 3, 9, -7, -8, 9,-17, 2, 15,-10,-11, 5, -5, 7, 15, -6, -2 }, + { -7, 2, 38, 5, 19, 16, -5, 4,-13,-20, 0, 4, -4, 6, 4, 2, + -7, 6, -8, -2, -5, -7, 6, 3, -4, -3, -2, -3, 7, -6, -4, 0 }, + {-11,-12, 8,-15, -3, 14, -7,-22,-11, 2, 22, 14,-19, 2,-19, -6, + 1, 3,-18, 14, 2, -6, -2, -8, -3, -6, 5, -7, -8, -4, 1, 1 }, + { 8, 7, 25,-21, 12, -6, -5, -4,-10, 6, 0, 10, 1,-12, 18, -5, + -15, 4, 1, 14, -1, 5, 8, -7, 1, -7, -3, 9, 10, 1, -1, 0 }, + { 9, 10, 32,-15, 8, 2, 11, -7,-18, -8, 2, -6, -9,-16, -3, 3, + -1, 3, 1, -5, 4, -2, 1, -8, 0, -6, -3,-11, 1, 5, 0, 0 }, + { 14, 0, 23,-25, 22, 3, 7, 10, 0, -2, 7, 8, 0, 10, 0, 0, + 3, 2, 3,-10, 0, 10, 0, -7, 0, 10, -1, -5, -7, 1, -1, 2 }, + { 12, 0, 25,-18, -5, -4, 13,-10, 3, -6, 7, 21, 0,-16, 3,-10, + -6, 5, -7, -3, 2, 5, 3, -6, 4, 9, -8, 12, -2, 3, 2, 4 }, + { 31, 15, 27,-20, 10, -7, 15,-10, 9, -8, 4, -5, 3, -3, 5, 6, + 11, -2,-12, -2, 6, -2, 1, 2, -1, -1, 1, 1, 3, 1, 1, 2 }, + { 12, -4, 13,-23, 12, -6, 2, 4, -3, 13, 6, -7, 5,-19, -7, 18, + 1, -7, 7, 1, 16, -7, 3, 0, 3, 0,-12, 8,-11, 9, 4, 7 }, + { 29, 1, 3,-22, -5, 6, 0, 12,-14, 11, 1, 6, -3, 4, 6, -2, + 4,-13, 12, 1, 1, 3,-11, 9,-10, -1, -7, 16,-11, -1, 3, 9 }, + { 4, 4, 36,-23, -5, -8,-15, 1, -6, 3, 13, -1, -5, -7, 4, 9, + 2,-11, -3, 5, 1, 3, -6, -1, -4, -4, -2, 2, 3, -1, -5, -2 }, + { 19, 10, 6,-17, 2, -4, -2, -4, -3, 13, 2, 2,-13, -7, -3,-11, + 9, -6, 1, -9, -5, 4, -5, -9,-18, -7,-11, 9, 4,-11, 8, 4 }, + { 16, -3, 9,-16, 18, -2,-12,-16,-11, 11,-18, 16,-13, 6, 2, 8, + 3, 8, -4,-16, 10,-11, -1, -3, -8, 5, -9, -4, 9, -4, 0, -3 }, + { 14, 15, 3,-23, -5, 7, -8, -6, 2, 17, 2, 12, -8,-12, 13, -1, + -9, 3, 1, 1, 19, 15, 4, -1, 1, 2, -3, 2, -3, 1, 5, 3 }, + { 32, 5,-10,-47, -5, -1, 4, 11, -7, 0, 2, -2, 1, -7, 6, -4, + 6, 2, -4, -2, 2, -2, 0, -4, 1, -6, -5, 2, -2, -1, -3, -4 }, + { 20, 8, 10,-21, -7, -9,-16, 12, 1, 4, 6, -5, 9,-11, -7, 4, + -11, 28, -3, 2, 4, -6, 10, -8, -5, -5, -9, 9, -2, -1, 6, -5 }, + { 38, 3, 23,-25, -6,-18, 3,-10, -8, 6,-10, 1,-10, 2, 2, 0, + -7, 2, -4, 5, -1, 8, -3, 0, 3, 3, -1, 1, 0, -4, -4, 0 }, + { 20, 5, 16,-22, 24,-18, 2,-12,-14, -7, -3, 10, 2, 7,-10, 2, + -8, 1, 8, -1, 4, 1, 4, -2, 5, -9,-18, -8,-13, 5,-11, 10 }, + { 14, 8,-12,-16, 9,-11, -3, -6,-25, -7, 6, 5, -7,-16, 10, 2, + -7, -1, -9, -3, 16, 4, 3, 3, -3, -3,-15, 13, -3, 4, 13, -7 }, + { 16, -9, 19,-23, 7,-19, -3, -5,-15, 11,-21, 21,-16, 18, -1, 6, + 10,-10, 18,-14, 16,-15, 6, -5, -9, 5,-17, 13,-10, 13, 0, 10 }, + { 8, -4, 4,-24, 8,-21,-18, 9,-11, 4, -6, 17, 5, -9, -2, -2, + 2, 15, -2, -3, -2, 1, 7,-13, 15,-10, -8,-11, 3, 3, -1, -1 }, + { 14, 17, 6,-32, 5,-17, -2, 0, 15, -1, -5, 16, 1, -5, -2, 9, + -3, 8, 4, -2, -2, -4, -3, 1, 0, 7, -3, 4, -5, 0, -7, 2 }, + { 24, 6, 22,-12, 8, 3,-14, 4, -7, 8, 6, 5, 6, 1, 6,-12, + 15, 10, 4, 11, 9, 6, -7, -4, 10, -9, 2, -1, -5, 11, 15, 3 }, + { 17, 12, 3,-23, 5, -1, -2, 1, -9, -1, -3, 1, 8, 1, -5, 17, + 11, 0, -2,-11, 7, 4, 0,-27, -7, 1, 2, -8, 9, 7, 5, 3 }, + { 12, 10, 12,-10, -4, 5, -1, 2,-24, 5, -8, 2, 6,-17, 19, 5, + 12, -2, 16, -7, -6,-14, 4, 1, -3, 13,-16, 5, -1, 4, 1, 1 }, + { 31, 9, 11,-17, 10, -3, -7, 7, 1, 2, 2, 4, -3, -1, 11, 4, + -5, -8, 1, 4, 15, -6,-28, 1, 8, 3, -6, 5, 17, -2, 2, -4 }, + { 11, 19, 16,-26, 0, -7, -7, 2,-13,-15,-12, 9, -3, 27, 8, 4, + -6, 1, 4, -6, 11, -1, -6, -7, -3, 0, -6, 4, -6, -7, -3, -1 }, + { 10, 18, 16,-32, 19, -9, -4, -3, -7, 8, 8, -3,-11, -2, -6,-16, + 13, 13, -6, -1, 10, -2, -2, -9, 0, -3, 9, 4, 11, -2, -6, 6 }, + { 9, 4, 19,-33, 4, 7,-12, 36, -3, -1, 8, -2, 2, -8, -9, -4, + -8, 0, 1, -1, 0, -4, -4, 3, 0, 3, 6, 0, -6, 2, 0, -2 }, + { 25, 7, 15,-12, 2,-24, -1, 24, -4, 4, 9, 0, -2, -9, 4, 6, + 3, 13, -3, 1, 5, -1, -3, -5, -1, 7, -2, 3, 4, 4, 1, 0 }, + { 19, 6, 8,-20, 9, -9, 5, -4,-13, 7, 11, -3, 5,-13, -9, 6, + -11, -1, 0, 4, 11, 26, 3, 6, -7, 12, 6, -3, 1, -9, 7, 1 }, + { 15, 6, 19,-23, -3, -9, 3, 16, -6, -4, 6, -5,-10, 1, 16,-14, + 2, 0, 2,-13, -3, 8, -6, 3, 1, 1, 2, -5, 12, -4, -8, -3 }, + { 14, 4, 16,-20, 1, 12, 0, 6, -3, 9, 4, 16, 10,-16, 5, 7, + 5, -4, -4,-18, -3,-11, -4, 4, -7, 3, 13, 7, 3, 3, 2, -7 }, + { 22, 3, -1,-30, 18, -3, -9, 9, -2, 11,-16, -2,-14, 12, 0, 4, + -5, 4, -1, 3,-20, 12, 4,-10, -2, -2,-12,-12, 10, 6, 11, -3 }, + { 15, 7, 2,-21, 5, 4, 9, -9,-33, 7, 7, 3, -6,-14, -8, 10, + 12, 0, 2, -1, 5, 4, -2, 0, -7, 0, 2, 4, 0, 1, -3, 8 }, + { -7, 0, 12, 3, 0, -6, 8, -4, 0, 2, 14,-15, 2, -7,-31, -3, + 14, 0, 14,-15, -1, -4,-15, 10, 1, -3, 1, 2, 5, 2, -8, 1 }, + { -2, 5, 1, 0, -3, 3, 3, -6, -1, 2, -4, 1,-19, 0,-11, 18, + 11, 10, 21, 5, 6, 2, 10, 3, -6, 0, -2, 13, 5, -1, -2, 9 }, + { -9, 1, -5, 0, 0,-15, 8, 4, 8, 3, 8, 12,-13, -2,-39, -2, + 4, -4, 5, -3, -4, 3, -3, 3, 10, 5, 3, 2, -3, 5, -2, 8 }, + { -9, 6, 6, -8, 12,-12, 23,-18, 4,-15, -5, 2,-20, 13, -7, 7, + 7,-12, 14,-12, 6, 1, 1, -3, -8, 9, 0, 1, -7, 3, 7, -6 }, + {-18, 13, 4, 3,-10,-30,-10, -6,-14, 1, -7, -4,-35, 5,-25, 11, + 9, 8, 19, -4, -7, -3,-18, -8, 1, 5, 10, -4,-14, -9, 3, -4 }, + { -6, -1, 4, -9, -9, 4, 20, 0, 0, 3, 11, 7,-16,-17,-20, 11, + -6,-14, 1, 4, 19, 2, -8, 6,-15, 3, 6, -5,-14, 3, 7, 2 }, + { 1, 6, -2, -8, -5, -3, 3, -8, 21, 1, 3, 16,-14, -2, -9, -4, + 13, -2, 18, 14, 14, 19,-13, 5,-10, 2, -3, 3, 5, 5, 1, -1 }, + { -1, -5, -6, -2,-11, -7, 5, -4, 5, -1, 0, 3, -3, 2,-19, 18, + 16, 4, 14,-22, -2,-11,-22, 1, -1, 11, 1, 2, 11,-10, 7,-12 }, + { 1, 4, 5, -1, -9, -5, 1, 12, 5, 6, 12, 9,-24, 23, 1, 20, + 14,-11, 13, 5, -2, -2, 5, 6, 2, 1, -9, 6, 10, 5, -4, 11 }, + { -1, -1, 1, 7, -3, -4, 8,-16, 15, -1, -7, 9,-22,-11,-11, 10, + 16, 9, -2, 4, 13, 10, 6, 16, 4, 7, 1, -8, -7,-14, -7, 4 }, + { 1, 3, -6, 0, 15, -9, -4, 0, 4, 6, 12, 9, -6, -5,-22, 17, + 7,-11, 15, -5, 1, 3,-19, 0,-15, -3, 16, 5, 5, -7,-11, 12 }, + { -2, -1, 13, 2, 4,-24, 37, -5, -2, -6, 12, 7, -2,-23, -4, 9, + 2, -3, 3, 2, 3, 3,-14, 11, 0, -4, -2, -2, 3, 10,-10, 4 }, + { 2, 9, 8, -6,-28, 14, 28,-11, 18,-11, 0, 2, -2, 4,-12, 3, + 6, 0, 7, -7, -6, 2, 5, -1, -1, -1, 5, 2, 3, 0, -3, 9 }, + { -7, 14, 5,-10, -3, 7, 4, -5, 7, -8, -7, 4,-12, 14,-16, 25, + 3, 0, 1, -5, 12,-10, 0,-10, 0, 12, 12, 17, 12, 10, -1, 0 }, + { -4, -2, 5, -2,-17, -3, 5, -5, 7,-17, 1, 5, -4, 4,-20, 0, + 11,-15, 13, -8, 10, 1, 1, 5,-12, 9, -8, 0, 6, -1,-11, 4 }, + { -3, 12, 13,-15, -7, -7, 0, 5, 33, 3, 3, -6,-13, -7,-15, 10, + 3, 3, 3, -5, 2, 7, -1, 0,-12, 2, 11, -6, -9, 0, 5, 11 }, + { -8, 5, 10, -7,-14, -4, 13, 0, 18, -3, -6, 7, 1, -6, 0, 21, + 8, -7, 10, -8, -3, 17, -9, 0, -5, 1, 4, 8, -3, 11, -5, 0 }, + { -8, 8, -3, -8, 8,-11, 16,-16, 17, 0, 8, 16,-17, 10,-16, 10, + -8, 6, 11, 0, 10, 7, 4, 5, 7, -5, -5, -6, -7, -5, -1, 16 }, + { -6, 0, 6, 1, -8, -8, 8, -7, -5,-10,-11, 8,-19, 6, -7, 13, + 5, -3, 4, -8, 7, -1,-18, 9, 0, -5, 6, 26, 3, 8, 2, 4 }, + { -2, -2, 23, -2,-20, 2, 7, -7, -6,-15, 3, 9,-19, -2,-10, 7, + -2, 7, 9, 11, 0, 4, -4, 6, 9, -2, 4, -3, 4, 3, 2, 8 }, + { -6, 12, 10,-10, -7, 4, 17, 11, -6, 1, 12, 11,-18, 8,-12, 4, + 1, 13, 6,-13, 23, 9, -5, 8, -2, -5, 1, 3, 0, -2, -4, 4 }, + { 7, 1, 7,-17, -8, 8, -1, -7, 5, -6, 4, -3,-16, 9,-24, 18, + -3, 10, 13,-11, -6,-11, -4, 10, 0, 11, 8, 2, 6, -5,-11, 4 }, + { -4, 1, -5,-10, 0, -3, 9, -2, 4, -1, 1, 5,-41,-10, -7, 4, + -3, 3, 1, 0,-12, 4, -3, 0, 2, -1, -2, -5, 3, 2, -7, 5 }, + { -2, 1, 4, 4, -3, -6, 1, 0, 12, -5, 11, 0,-17, -3, -1, 11, + 4, 1, 27,-12, 0,-14, 2,-15, -3, -9, 0, -7, -3, 15, -8, 6 }, + { -6, 4, 9, 2, 4, 3, 7,-10, 28, 1, -2, 48, 7, 0,-10, 10, + 1, -9, 2, -1, 0, 3, -5, 5, -4, -2, 7, 7, 1, 3, 2, 5 }, + { -3, 3, -1, 3, -9, 0, -1, 3, 2, -6, 39,-14,-12, 5,-19, 21, + 7, -6, 4, -1, -4, 0, -4, 1, 0, -9, 1, 10, 0, -2, 0, 7 }, + { 4, 2,-29, 12, 5, -3, 16, -6, 15,-13, -4, -1,-13, 22,-16, 17, + 16, 4, 9, -4, 4, -6, -4, 11, -8, 7, 8, 4, 3, -3, -7,-13 }, + { 0, 3, 3, -6, -4, 0, 9, 0, 5, 0, 10, 10, 4,-13,-12, 16, + 23, -4,-12, -6, -4, 20, 2, 0, -4, 23, 1, 8, 11, -4, -5, 15 }, + { -6, 4,-15, -9, -1,-19, 12,-30,-17, -4, 1,-13,-13, 4, -3, 26, + 5,-25, 11,-14, -6,-13, 0, -7, 9, 2, 8, -1, -8, 1, -8, 13 }, + { 1, 6, 1, -4, -4, 1, 2, 0, -3, 2, 10, 6, -6, -2,-11, 4, + 32, 15, 15,-47, -8, 3,-12, 4, -5, 4, -1, 0, -5, 5, 1, -7 }, + { 2, -1, 0, 0, -1, -6, 0, -6, 4, -4, 5, 9, -5, 1, -3, 51, + 4, -5, 4,-14, -1, -4, -3, 1, -4, -1, 0, 2, -8, 0, 1, 2 }, + { 0, 4, -2, -7, -2, -9, 6, -8, 11, -3, -6, 3,-11, -8,-12, 8, + 11, 5, 19, 3,-24, 19,-14, 11, -5,-18, -8,-12, -5, -4, -1, 4 }, + { 16, 9, 10, 14,-18, -2,-18,-27, 10, -5, 12, 14, 4, 0, -2, -6, + -12, -7, -1, 3, 4, 7, 11, 10, 5, -5, -7,-16, -3, -6, 6, 9 }, + { 7, 15, -9, 10,-19, 4, -5,-37, -2, -4, 8, 2, 4, -1, 1, 9, + -5, -5,-12, 1, -1, -8, 3, -3, 4, 6, 9, 3, 3, -1, 2, 4 }, + { 13, 17, 3, 9, -7, -7,-15,-17, -8,-13, -4, -8, 19, 2, 16, 25, + 7, 15, 2, 16, -5, -6,-10, -9, -7, -6, -2, -7, 7, 2, 4, 5 }, + { 24, 7, 9, 8,-13, -2, 0, -4, 1,-13, 3, 6, 7, 10, -4, 15, + 5, 7, -4, 5, -5, 3, 13, -7, 5, 15,-11, -2, 7, 5, 8, 6 }, + { 17, 6,-15, 23, -2, -1, -6, -2, 0, -4, 11, -3, 12, 15, 6, -8, + -15, 10, -9, 7, -1,-11, 2, -8, -4, 3, 4,-10, 4, 4, 11, 1 }, + { 21, 12, -3, 6, -8, 8,-11, -8, -5, -5, 3, 7, -1, -5, 12, 15, + -10,-11, 3, 15, 8, 4, 2,-15, 0, 14, 1, -8, -1, 3, 10, -7 }, + { 16, 12, 5, 13, -6, 15,-23, 0,-17, -9, 0, 4, -9, 13, 6, 18, + 0, 0, -4, -1, 0, 14, 5, -1, 8, -4, -8, -6, 5, -2, -2, 0 }, + { 14, 16, -1, 12,-15, -9, -6,-20, 4, 6, 8, 9, 3, 1, -9, -4, + -1,-11, 9, 11,-12, 1,-14, -7, 2, -8, 11, 9, -4, 10, 4,-16 }, + { 13, 10, 3, 7, 0, -8,-33, -6, 4, -4, 19, -2, 14, 6, 5, 7, + 6, -3, -1,-10,-10, -9, 4, -3, 5, 9, 2, 2, 10, 9, -2, -3 }, + { 11, 10, 25, 18, -1, -6,-21,-21,-11,-16, 6, 5, 14, 4, 8, 7, + 0,-10, -7, -9, -5, -4, 3, -1, 1, 6, -1, 6, -2, 2, -3, -9 }, + { 15, 9, 5, 22,-17, 15, -9, 7, 7, -9, 13, 9, 10, -1, 8, -3, + -2, 6, 1, 17, 8,-14, 7, -3, 12, 9, 1, 0, 1, -5, 17,-18 }, + { 25, 19,-17, 12, -4,-10, 1,-13,-19, -7, -3, 9, 6, -2, 3, 1, + 4, -2,-11,-14, -1, -7, -5, -9, 7, -1, -3, 4, -5, 1, 0, -1 }, + { 20, 8, -3,-10,-24, 3, -6, -2, 0,-12, 14, 6, 7, 11, 4, 7, + -12, -5, -8,-10, 5, -1, -4, 4, 16, 7,-14, 6, -1, -2, -7,-11 }, + { 16, 18, 17, 1,-15, -6, -5, -3, -1,-19, 8, -2, 2, 8, 12,-19, + -12, 8, 0, -3, -1, -1, 4,-14, 9, -1,-12, -1, -7, 10, -3, 5 }, + { 18, 12, -7, 7, 0, -3,-13, 0, -1, -4, 9, -2, 6, -1, 0, 1, + 15,-21, 1, -8, 25,-19, 13, -9, 2, 12, 5, -7, -3, -1, -3, 1 }, + { 13, 16, -4, 9, -2, 2, -1,-19, -7, -4, 18, -6, 14, 18, -5, 4, + -6, -3,-19,-14, -1,-12, 10, 6, 7, 17,-12,-13,-10, -4, 5, 4 }, + { 27, 17, 4, 14, -9, -2, -4, -8, 0, -6, 14,-11, -7, 2, -3, -3, + -2, -3,-13, 12, 16, 1, -5, -9,-10,-11, -2, 3, -7, 5, 11, -7 }, + { 7, 17,-16, -2,-14,-28, -7, -8, 15,-10, 7, 15, 8, 17, 13, -1, + 4, -7,-12,-11, 0, 0, 2, 3, -3, 7, -6, 6, 1,-16, 1, -2 }, + { 23, 11, -9, 15,-23, -4, -6, -4, 2, -9, -7, 9, -8, 3,-13, -4, + 8, 18, -6, -2, 1, -5, 6,-14, -5, -2, -6, -5, -3, -2, 4, -5 }, + { 12, 13, 18, 18,-35, 2, 7,-17, 3,-11, 6, 9, -3, -2, 10, -4, + 3, 3, -2, -7, 0, 2, -4, 0, -4, 0, -6, 5, 10, 4, -3, -1 }, + { 19, 11, 1, 20,-14, 4, -9,-13, -2, 11, 0, 17, -1, -1, -1, -1, + -5, -8, 0, 5, -1, -8, 5, -1, 3, 2,-12, 21, -2,-24, 5, 7 }, + { 15, 15,-15, 17,-14,-22, 3, -4,-11, -3, -7, 1, 18, 10, 1, 10, + -6, -3, 8, 2, -7, 0, -2, 1, 1, 2, -9, -2, 1, 2, -3, 4 }, + { 45, 13, 8, 17, -5, 2,-16, 2, 8, -2, 8,-15, 4, 5, -1, 7, + -6, -2, -6, 2, -3, 0, 0, -9, -1, 7, 2, 3, -3, -3, -1, 5 }, + { 1, 18, -8, 18,-12,-10, 3, 4,-22,-12, 20, 8, -3, 9, 2, 10, + -10, -3, 9, 3, 6, -3, 10, -1, -3, 2, -2, 4, 2, 3, -3,-18 }, + { 9, 10, -5, 9,-35,-21,-18,-16, -1,-12, -6, -7,-15,-19, 12, 4, + 4, 9, -7, 2, 14, 1, 4, 0, -1, 6, -7, 2, 1, 1, -4, 4 }, + { 31, 8,-17, 35, -8, 1, -5, -6, -7, -6, 10, -2, -3, 6, 9, 3, + -6, -2, 3, 3, 5, -3, 0, 6, 0, 1, -5, -3, -2, -4, -1, 0 }, + { 18, 4, -8, 7, -8,-15, -1,-16, 12, 18, 3, 19, 2, 4, 8, 8, + 0, -5, -8,-12, 10, -5, 0, 1, 0, 4, -3, 16, 11, 11, -2, -6 }, + { 27, 15,-17,-10,-23,-22, -1,-14, -4, -7, 20, -2, -7, 6, 15, -5, + 32, 4, 9,-11, -3, -8, 11, -4, -1, -4, -8, -6, -4, -5, -2, -7 }, + { 22, 4, -7, 2,-15,-11,-17,-10, 2, 0, 15, 11, 7, 12, -8, 6, + -10,-18, -6,-12, 7, 3, 22, 3, -7, 14, -5, -2,-13, -7, -1, -7 }, + { 18, 13, 9, 24, -4,-19, -9,-11, 13, 8, 2, 4, -1, 8, 14, 10, + -12, 0, 0, 5, 10, 5, 4, -1, 5, 1, -1, 11, 2, -4, 0, -9 }, + { 15, 19, -5, 1, -4,-10, -8,-27, 6, 8, 5, 10, 4, 11, 5, -5, + -11, 0,-11,-14, -4, -9, -8, -8, 6, -9, 4, -5, -1, 1, 5, -4 }, + { 18, 1,-13, 14,-14, 9,-15, -7, 12, 1, 13, -4,-20, 12, 10, 12, + -12, 7, 1,-13, 10, -6, 5, -3, 4, 8, 10,-13, -3, -6, 9, -3 }, + { 19,-14, 5, -8, -6, 2, -5, 5, -3, -1,-28, 11, 18, -6, -4, -2, + 11, 14,-43,-42, 9, 2, 20,-23, 6, 32, 0, 5, 0, 6, 9, 5 }, + { 8, 11,-14, -1, 7, 12, -7, 2,-16, 2, 10, -3, -1, -7, -7, -1, + 1,-10,-60,-23,-18, 42,-13, 9, 18,-11, 0, 1, 0, 2, -5, 1 }, + { -5, -1, 2, 0, 3, -3, 3, -2, -6, 0, -3, -3, 7, 2, 0, -2, + -2, 3,-34,-15, 37, 47, 10, 20, 9, 1, 3,-21,-25,-33,-14, 8 }, + { 5, 6, 2, -2, -2, -2, 6, 5, -5, 7, -3, 1, -5,-13, 9, 3, + -17,-19, -2,-79,-12, -7, -8, -6, -2, -2, -1, -1, -7,-13, 6, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, + 0, 3, 4,-87, 6,-11, 16, -9, -1, 8, 0, 5, 0, 1, 2, 1 }, + { -5, 6, 2,-24, 5, -9, -7, 0, 7, 3, -3, 16,-14,-16, 0, 18, + 15, -9,-14,-28,-17, 53, 14, -6,-28, -1, -3,-10, -7,-14, 19,-15 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, + -13, 0,-53, 3,-22, 63, 19, 16, 1,-11, 0, -3, 0, -3, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -1, -6,-43,-43, -2, 65,-13, -4, 9, 1, 1, 2, 1, 0, 0, 1 }, + { 0, 1, 0, 0, -1, 0, 1, 1, 0, 0, 1, 2, -1, -1, -3, -1, + -23, 1,-61,-55, 3,-28, -6, -4, -4, 8, 2, 1, 1, -1, 0, 0 }, + { 0, 1, -1, 1, -1, 0, -1, 0, 1, -1, 0, 1, -1, 0, -9, -4, + -48,-19,-52,-46, 11,-12, 5,-14, 0,-10, 0, 0, -1, -2, -1, 0 }, + { 0, -3, -1, -4, 2, -1, -7, 3, 1, 3, -1, 1, -3, 0, -7, 0, + 3, -7,-61,-51, -4,-21,-16,-21,-11, 14, -7, 8, 3, -5, 1, 2 }, + { 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 9, -3, + 56,-11, -6,-67, -1, 13, 0, 7, 1, -9, -1, -1, 0, 0, 1, 0 }, + { 14, 9, -2, 14,-10,-10, 9, -5, 1, -8,-23, 30, 8, -7, 23, 8, + 2, 10, -1,-27,-17, 57, 22, 4, -5, 2,-12, -6, 2, -7, -4, -9 }, + { 1, 5, 12, -2, -2, -3, 2, -3, 6, 0, 4, -2, -8, -6, 0, 16, + -15, 29,-55,-29,-24, 29, 3, 10, 6, 13, 10, -5, 21, 11,-14, 5 }, + { 4, 2, 26, -6, 10, 11,-23,-10,-27,-20, 3,-24,-11,-10,-13, 25, + -10, 5, -9,-36, -7, 43, 3,-13, 6, 13, -2, 0, 1, 3, -3, -4 }, + { -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, -1, 0, 0, 0, -1, 1, + -12, 12,-26,-64,-15, 29, 37, -7, -3,-12, -5, 14, 8, -8,-10, -2 }, + { 19, -4,-11,-16, 8, 14, 5, 19, 3, 22,-11,-21, -1, -6,-11, 11, + 10,-24,-23,-40, -8, 20, 17, 5, 13, -6, 3, 14,-20, -8, 3, 28 }, + { 2,-12, 10,-14,-18, 26,-22, 4, -2, 5,-21, 8, 3, 1, 19, 0, + -12, 24,-14,-40, 15, 29,-15, 6, 15, 1,-19, 2, 4, 7,-12, -3 }, + { 0, 17, 13, 7, -5,-11, 2,-19, 3, 38,-21, -3, -6, -4, 7, 1, + 1, -5,-40,-10, -2, 35, 8, 8,-10, -8, -9, 33, 4, 4, 0, -2 }, + { -2,-12, 7, 29,-24, 2, 16, -1, -7, 16, 10, -2, -2, -2, 13, -2, + -37, 15,-22,-40,-11, 33, 10, -1, 8, 10, 6, 8, 9, 0,-12, 2 }, + { 15, -8, -9, -2, 7,-17, 7, 19, 14, 4, 12, 27, 11, 10, 4, 11, + -15, 14,-13,-48, 5, 18, 0, -9,-36,-11, 2, 4, 5, 5,-15,-12 }, + {-12, 0, 3, 4, 7, -5, 5,-14,-24,-18, -6,-15, -8,-20, 1, -7, + -33,-28,-40,-38,-18,-10, -5, 17,-12, 4, 3, -5, 5,-13, 4, -7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, + 3, -2, 9,-29,-11, 55, 8, 32,-36,-13, -7, 37, 4, 11, 0, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, -1,-39, -4,-30, 63, 28,-17, -6, 10, 7,-14, -9, 11, 9, 7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + 13, -2,-50,-32, 22, 51, 4, 7, 6, 11,-20,-13, 9, -5, 21, -4 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + -3, -9,-49,-60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, + 3, -2, 9,-29,-11, 55, 8, 32,-36,-13, -7, 37, 4, 11, 0, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, -1,-39, -4,-30, 63, 28,-17, -6, 10, 7,-14, -9, 11, 9, 7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + 13, -2,-50,-32, 22, 51, 4, 7, 6, 11,-20,-13, 9, -5, 21, -4 }, + { -8, 2, 1, 22,-31, -6,-25, -3, -3, 1,-15,-11, -2, -3, 4,-13, + -9, 15,-18, 37, -7,-37, 12,-13,-11,-25,-10,-11,-22, 7, 16, 7 }, + { 14, 10, 4,-10, -1, -5, -7, -3, 16, 13, -5,-15, 5, 11, -1, 8, + -27, 7,-12, 49, 17,-22, 9, -2, -9, -1, 2,-15, -1, 41,-18,-17 }, + { -4, -9,-15, -3, 3, 4, 4, 2, 7, -3, -7, -8, -5, 17,-19, -7, + 36, -9,-38, 17, 1,-48, 11,-18,-13, -2, -8, 4,-10, -5, 21, 11 }, + { 15,-13, 4, 2, 1, -5, -2, 1,-10, 7, -1, 3, -6, 0, 11,-11, + 8, 20,-17, 51,-17,-41, 2, 15, 4, 8, -2, 16,-32, -1, 17, 6 }, + { -8, 8,-18, -5, 4, 6, -3, 8, 0, -4, 2, 0, -1, -4, 5, 8, + 30, 30, -8, 70, 2, 8, 2, 0, 7, 1, 13, -1, -6, -7,-11, 2 }, + { -8, -7, 9,-10,-13, 6,-11,-14, 13, 25,-26, 5, 2, -5, -5, 5, + -8, 4, 0, 33, 12,-38, -4, 6, 13, 6, 25, 34, -1, 25,-19, -5 }, + { 18, 3,-17, 4, -8, 7, 20, 1, -1, 5, -5, -2, -8, 8,-35, 15, + 24, 43, -5, 51, 5,-12, -3, 1, -2, 3, -3, -3, -9, 8, -9, 2 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 10, 24, 76, -2,-22, 11, -1, 4, 33, 4, 1, -1, 1, 2, 0 }, + { 0, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 2, 0, + 24, 13, 32, 70, 26, 5,-21, -9, -6,-15, 2, -2, 2, 4, 1, 1 }, + { 5, -4,-11, 4, -4, 22, 10, -2, 13,-11, -4,-21,-17, 0, -7, 4, + 10,-34, 11, 52, 2,-46, -5, 0, 0, -1, 2, 4, -9, 1, 1, -7 }, + { 0, 1, 1, 0, -1, 0, 1, 0, 1, 1, 0, 1, 0, 0, -3, 1, + -8, 9, -1, 64,-13,-61, -3, 3, -5, 10, 1, 3, -1, -1, -1, -1 }, + { 0, 1, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, + 10, -2,-31, 79,-10, 27, 0, -1, 3, 8, 1, 1, 0, -1, 0, -1 }, + { 3, 12, 10, 26,-19, 10, -9, 6, -4,-15, 10, 3,-16, 6, 11,-19, + 3, 10, 18, 44, 5,-30, 5, -9, 21, 4, 20, 10, 14,-25, 8,-17 }, + { 0, 0, 0, 1, -1, 0, -1, 0, 1, 0, 1, 1, 0, 0, -6, -2, + 8, -8, 13, 69, 26,-19,-25,-17, 16, 6,-12, 22, 2, -6, 9, 5 }, + { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, + -34,-15,-33, 56, 9,-42, 9, 10, 6, 9, -8,-11, 0, -6, 15, 5 }, + { 10, 2,-14, -3,-15,-35, -1, 7,-18, 14, 8, -1,-15,-26, 6,-15, + -18, 22, 9, 33, 0,-32, -9, 3,-11, 7, 4, -1, 5, 30, 9, 1 }, + { 4, 15, 0, 6, -5,-11, 9, 6, 6, 6, 14, 2, -1, 10,-24,-25, + -2, -4, -1, 37, 2,-29, 14, -9, 22, 17, -2, 33, 10,-25, 11,-11 }, + { 0, 5, 2, 18,-12, 21, 22, 33, -7, 21, -9, -7, 7,-15, -7, 16, + 7, 0,-14, 44, 10,-25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, + { 3, 13, 12, 12, 8, 25,-23, 8,-22, -3,-18, -8, 15, 12, 9, 19, + 0, 0, -9, 49,-27,-15, -9,-15, 12, -8,-16, -7, 13, 5, 13, 2 }, + { 12, -6, 7, -2, 20, -9,-14, 12, 13, -5,-17, 22, -8, -4, 2, 7, + -13, -2,-15, 43, -5,-30, 27, 4, 10,-27, 5, 27,-10,-10,-18, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 15,-13,-20, 16, 2, 13, 5,-11, -8, -5, -3, 2, 24,-23, 30, -7, + 11, 30,-15, 43, 5,-15, 15, -3,-14, 1,-23, 8, 3, 9, 4,-11 }, + { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, + -34,-15,-33, 56, 9,-42, 9, 10, 6, 9, -8,-11, 0, -6, 15, 5 }, + { 10, 2,-14, -3,-15,-35, -1, 7,-18, 14, 8, -1,-15,-26, 6,-15, + -18, 22, 9, 33, 0,-32, -9, 3,-11, 7, 4, -1, 5, 30, 9, 1 }, + { 4, 15, 0, 6, -5,-11, 9, 6, 6, 6, 14, 2, -1, 10,-24,-25, + -2, -4, -1, 37, 2,-29, 14, -9, 22, 17, -2, 33, 10,-25, 11,-11 }, + { 0, 5, 2, 18,-12, 21, 22, 33, -7, 21, -9, -7, 7,-15, -7, 16, + 7, 0,-14, 44, 10,-25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, + { 3, 13, 12, 12, 8, 25,-23, 8,-22, -3,-18, -8, 15, 12, 9, 19, + 0, 0, -9, 49,-27,-15, -9,-15, 12, -8,-16, -7, 13, 5, 13, 2 }, + { 12, -6, 7, -2, 20, -9,-14, 12, 13, -5,-17, 22, -8, -4, 2, 7, + -13, -2,-15, 43, -5,-30, 27, 4, 10,-27, 5, 27,-10,-10,-18, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, 10,-18, 70, -2,-52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 15,-13,-20, 16, 2, 13, 5,-11, -8, -5, -3, 2, 24,-23, 30, -7, + 11, 30,-15, 43, 5,-15, 15, -3,-14, 1,-23, 8, 3, 9, 4,-11 }, + { 16,-18, 7, -4, 31,-15, -9,-13, 20,-12, -6, 0, 12, -6, -2, 4, + 3, -3, -1, 0, 1, 3, 3, -2, 1, 6, 4, 0, -3, 2, -5, 1 }, + { 38, -5,-13, -4, 8,-15, 11, 1, 2, -4, -1, 9, 13, 4,-12, -7, + 0, -2, 7, 2, -6, -2, -3, -2, 3, -4, 6, 15, 1, 1,-11, -2 }, + { 47,-22, 9,-26, 3, -5, 2, -7, 4, -2, 2, -2, 3, 0, 3, -4, + 3, -3, 2, -3, 7, -3, -1, 1, 1, -5, 5, 0, 2, -5, -3, -2 }, + { 14,-16, 2, -6, 7, -2, -7, -4, -4, -7, 14, -3, 7,-19,-14,-17, + -29, 6, 26, 16, -5, 13, -4, -1, 21, 14, 1, 3, -6, 0, -7, -1 }, + { 29,-11, 5, -3, 4, 11, 4,-10, 1,-22, -3,-10, 5, 4, 2, 8, + -2, -7,-12,-12, -8, -3,-18, -2, -9, -5, -1, -3, 2,-14,-14, 7 }, + { 28,-12, 5, 3, 9, -7, 0, -2, 2, 1, 4, 0, -7, -3, -2, 4, + 4, 14, 8, -1, -4, 14, -7, 17, -2, -2, -9, 2, 19, -7, 9, -8 }, + { 31,-18,-22, 8, 15, -5,-10,-15, 1, 10, 6, 7, 6, -8, 2, -1, + 12, -3, 3, -1, 1, 5, -6, -4, 0, 1, 7,-10, -2, 4, -3, -4 }, + { 53,-30, -4, 12, 2, 3, -3, -3, 0, 1, 6, 5, -5, -4, -7, 1, + 0, 2, 1, 3, 1, 5, 0, 2, 2, -1, 0, 4, 2, 0, -2, 0 }, + { 27,-18, -3, -2, 4, -8, 3, -2,-11, 2, 10, -8, -8, -4, 0, -2, + 8, 0, 9, 0,-16, 11, 1, -6, 13, -3,-10,-13,-15, 25, 1, 0 }, + { 35, -5, -1, -8, 23, 11,-14, -3, 2, -2, 8, -6, 17, -2, 7, 0, + -2, 10,-17, 13, -2, -2, 11, 11,-14, 2, -2, -3, -8, -1,-12, -5 }, + { 29, -9, 7, 3, 2,-10, 0, 3, 9, 0, -3, 5, 1,-10, 10, -5, + 3, 6,-20, -9, -6, -4, 1, 0, 12, 17, -8, 9, 3, -1, -9, 0 }, + { 15,-16, 18,-19, 16,-15, 17,-18, 13,-16, 17,-14, 15, -9, 13,-17, + 9, -7, 4, -5, 3, -4, -3, 0, -6, 7, -9, 7, -2, 7, -9, 9 }, + { 21,-10, 7, -2, 12, -7, 13,-17, 11, -2, 20, 3, 5,-11, -6, -6, + -15, 0, -9, 5,-11, 7, -1, 7, 8,-10, -9, 3, -5, 9, -8, -2 }, + { 23,-22, 15, -5, 16, -4, -3,-12, 9, 3, -1, -2, -8, 2, -2,-16, + 3, 4, -2, -6, -7, 12, -8, 2,-14, 2, -7, 11, -2, 6, -4, -1 }, + { 34,-17, -4, 8, 4, -6, 1, 8, 4, 16, 3, 6, 12, -1, -1,-15, + 6, 4, -7, -6, 6, 0, 2, 1, -2, 2, 3, 3, -3, -2, 8, -6 }, + { 18,-18, 2, -2, 10, 1, 18,-23, -3,-10, 0, 4, 20,-19, -3, -4, + 2, 8, 6, 1, -3, 1, 1, 3, 5, -1,-11, 3, -7, 5, -1, 1 }, + { 15,-14, 2, 3, 10, -8, 12,-13, 13,-15, 6, -8, -4,-10, 14, -9, + 24, 2, -7,-18, 13,-11, 8, 14, -6, -2, 3, -1, -4, 7, -7, -4 }, + { 20,-12, 13, 5, -1,-10, 15, -6, 8, -1, -3,-10, 17, 0, -6,-19, + 2, -1, 8, -3,-16, 0, -3, 2, -2, 0, 8, -9, 0, 1,-10, -9 }, + { 32, 0, -9, -5, -1, 5, 13,-11, 8, 3, 11,-11, 0, -8, -2,-14, + 7, 10, 6, -5, 1, 10, 2, 12,-10, 4, 4, 6, 4, 0, -7,-10 }, + { 16,-14, 10, -7, 11,-11, 11,-11, 18,-13, 8,-15, 16,-11, 13, -9, + 8, -7, 12,-11, 7, -6, 3, -5, 9, -5, 4, -1, 7, -4, 8, -3 }, + { 24,-27, -1, 5, 8, -5, 12, 7, 4, -3, 3, -1, -9,-11,-13, -5, + 10, 0,-13, 7, 1, -5, 4, -9, 7, -3, 13, 2, -5, -3,-17, -2 }, + { 23,-19, 15, 1,-10,-18,-12, -6, 8, -3, 12, 0,-12,-10, -4, -4, + 8,-10, 4, 2, -2, -8, 13, -3, -2, -6, 2, -3, 5, -2, 2, 11 }, + { 25,-12, 4, 2, 24, -3, 3, -6, 14, 11, 0,-21, -3, -3, 1, -8, + 7, 0, 0, 3, 3, -6, -7, 6, 2, 1, -4, 5, -1, 10, -2, 9 }, + { 24, -8, -6, 7, 16,-12, 13, -1, 11,-21, 2, -6, 3,-12, 0, 9, + 4, 11, -7, 1, 4, 1, -8, 3, 3, -6, 3, 3, 0, -8, 8, 4 }, + { 25,-21, 13, 14, 13,-18, 4, -3, 0, -5, -4, 5, -3, 0, 4, 12, + 7, 3, 5, -5, 2, -2, 3,-10, 2, -9,-15, 6, 1, 7, -5, 1 }, + { 23,-16, -2, 10, 4, -1, 3, 1, 32, 3, -5, -2, 9, 10, -1, -4, + -6, 2, 9, -1, 14, 12, -6, -1,-17, -2, -4, -9, -7, -6, -8, 3 }, + { 50, -8, 5, 2,-11, 10, 0, 0, 6, -3, 7, 0, -3, -2, -3, 0, + 6, -4, 2, -5, -9, 0, 3, 10, 1, -7, -2, -3, -6, -9, 1, -2 }, + { 28,-17, 0, -2, 2, -9, 1, 5, -4, -1, 0, 0, 19,-27, 5,-12, + 7,-14, -3, -6, 10, -2, -4, -2, 4, -5, -2, -7, 1, 7, -9, 4 }, + { 22,-19, -6, -6, 3,-22, 3, 5, 20, -8,-14, -5, 1, 1, 20, 2, + 16, 6, 3, 14, 4, 3, 5, 1, 5, -7,-10, -6, 3, -6, 1,-14 }, + { 29,-14, -8, 13, 8,-10, -6, 4, 4, -6, 5, -7, 1, 12, 14, 11, + -7, 1, 2, -9,-11, -9, 0, 4, -1, 7, 10, 4, 4, 20, -1,-11 }, + { 18, -9, 4, 1, 7,-29, 12, 1, -1, -9, -2, -1, -2, 2, 9, -8, + -13, 5, 4,-13, -4, 2, -5, -7, -6, 14,-10,-34, -3, 1, -3,-13 }, + { 38, -9, 24, 8, 11, 4, -6,-11, -2,-12, 1, 1,-11, -8, -5, -2, + -15, -8, 8, 0, 1, -7, 5, 4, -1, 8, -2, 11, -3, -1, -5, -5 }, + {-20, 11, -4, 24,-11, 1, 15, 4, 0,-28,-10, -1, 10, 10, -6, 5, + -6, 2, 7, -2, 1, -2, -6, -3, -7, 1, 2, 12, -1, 7, 0, -2 }, + { -9, 10,-23, 27, -4,-17, 20, -6, 14,-17, 5, -1, 5, -9, -7, 5, + -6, 4, -2, 9, 0, 8, 0, 1, -3, -3, -5, -8, 5, -2, -2, 12 }, + {-10, 19, 4, 9, 1,-16, 17, -2, 9,-29,-16,-11, -4, 7, -5, 4, + -1, -3, 3, 2, 3, -4, 5,-12, -2, 6, 5, -4, 4, 1, 4, 10 }, + {-20, 10,-24, 14, -5, 11, 9, 0, 16,-20, 10, -5, -6, -6, -1, 2, + -4, 5,-16, 8, -2, 5, 5,-11, 9,-11, 4,-11, -1, -1, 4, 3 }, + { -9, 11, 3, 19, 24, 4, 5,-14, 30,-17, -4, -2,-17, 7, 2, 3, + 1, 3, -7, -4, 2, -3, 1, 4, -1, -1, 3,-12, -2, 3, -3, 10 }, + {-19, 18, 11, 19, 19, 19, 10, 4, 13, 6, 5, 4, 8, 3, -2, 12, + -6, -2, 7, -6, 15, 12, 16, 16, 18, -3, -4,-20, 0, 10, -9, -3 }, + {-21, 9, 20, 12, 0, -3, 5, -9, 15,-13, 5, -5, -6, 24, 2, 9, + -5, 2, -7, 2, 5, 7, -5, 2, 15, 3, 1, -1, -4, -2, 7, 0 }, + {-18, 16, 13, 15, 2,-10, 14,-11, 4,-11, 5, 12, 12, 20, 8, 30, + 2, 11, -9, 7, 0, -3,-16, -5, -6, 5, -4,-21, 0, 5, 6, 1 }, + {-26, 8,-13, 9, 6,-10, 2,-11, 7, -4, 6,-19,-11, -6,-12, 16, + 0, 5, -7, 8, 5, 6, 17, -9, 10,-10, 5, -3,-11, 2, 4, 10 }, + {-11, 17, -3, 22, -5, 18, 3, 1, 4, -5, 14,-27, 5, -7, -4, -5, + -10, 11, 1, 15, 1, 1, -6, -5, 10,-22, -7, -7,-15, 13, -4, 5 }, + {-17, 14, -7, 13, 3, 0, 13, -6, 9,-14,-22, -1, 1, 19, 14, -3, + 4,-13,-13, 2, -4, 8, -2, -2, 13,-12, 13,-12, -7, -5, -3, 6 }, + {-17, 17, -1, 33, 6, 3, 9,-16, 3,-14, -8, 6,-17, 8, 3, 13, + 8, -6, 3, 1, -2, 0, -2, 8, 4, 9, 13,-10, 4,-17, 0, -6 }, + {-20, 7, 7, 21, 1, -3, 7, -3, -2,-12, 9, -7, 2, -3, 14, 1, + -1, -7, 12,-10, 5,-20, 11, -2, 0,-24,-17, 6, 6, -4, 3, -1 }, + { -8, 10, 6, 7, -1, -6, 28, -6, 10,-33, 1,-20, 0,-12, 10, 1, + -6, 8, -3, -1,-10, 8, 5, 0, 10, -2, 8, 16, -5, -3, -7, 4 }, + {-17, 13, 3, 15, 1, -5, 27, -5, 6, -6, 12, 2, -4, 8, -1, -3, + -2, 12,-15, 3, 4, 1, 2, -9, 0,-16,-21, 2, -4, 16, -7, 4 }, + {-15, 20, 8, 17, 5,-14, 15,-11, 21,-11, 13,-13, 2,-15,-13, 1, + -5, 5, 2, 10, -9, 4, -1, 3, 2, -4, 13, -5, 1, -4, 5, -3 }, + {-21, 8, 2, 16, -1, 2, 15,-16, 13,-12,-12, -7, -8, 2, -7, 11, + -8, 5, 2, -7, 16, -4, 1, -7, 3,-15, 6, -5, -8, 2, -8, 5 }, + {-15, 17, -6, 3, -3, 3, 9, -7, 14,-23, 11, 1, -1, 4, 7, 6, + -1,-14, 7, 6, -8, 5, 1,-15, 10, -9, 2, -3, -1, 4,-10, -4 }, + {-10, 18, 3, 11, 1, 4, 14,-14, 7, -4, 15,-10, 10,-11, 10, -4, + 5,-14, 10, 4, 15,-12, 15,-13, 20,-15, 14,-15, 8,-11, 4, -6 }, + { -7, 23, 2, 20, 7, 8, 19, -5, 9,-16, -8,-17, -5, 1, 5, -6, + -8, 1, -6, -4, 10, 6, 6, 2,-11, -4, 0, 2, 4, 7, 9, -4 }, + {-15, 20, -5, 22, 11, -8, 9, -5, 10,-13, -8, 8, 2, -2, -3, 7, + 6, 10, 1, 2, -5, -9, 1, 10, 16,-22, -7, 0, 7, 7, 6, 1 }, + {-26, 19, -5, 3, 5, 25, 18, -5, 9,-14, -8, -6, -2, -6, 2, 3, + -8, -2, -7, 7, -3, 7, 3, 4, -8, 0, 1, -8, -4, -2, -2, 1 }, + {-20, 14,-10, 6, -3, 7, 8,-32, -2, -7, -2,-10, 16,-12, -9, 15, + -2, -5, -6, 2, -7, 5, 9, 1, 6, -7, -1, 0, -2, -4, -7, 3 }, + {-14, 16, 4, 11, -8, 1, 23, -4, 17,-13,-10, 1, 12, 9, 12, -4, + 7, -1, -1, 5, -8, -6, 3, 3, -6, -3,-18, 0, 18, 20, 4, -2 }, + {-33, 19,-10, 30, 15, 2, -3, -1, -4,-14, 7, -7, -1, 7, -8, 9, + -1, -3, -5, 2, 2, 4, 0, 5, 0, 0, 2, 3, 3, -3, -3, 4 }, + { -6, 20, 0, 5, 17,-10, 18,-17, 9,-16, 4,-13, -6, 2,-14, 14, + -28, 9,-12, 25, -4, 7, 7, -8, 6, -6, -2,-10, 2,-11, -1, 2 }, + {-12, 14, 12, 52, -3, 5, -5, 4, 8,-13, 2, -5, -4, 2, -2, -1, + -2, 3, 3, 5, 2, 3, 0, 1, -5, 2, -4, -3, 1, -5, -2, 0 }, + {-13, 6, 9, 24, 0, 8, 14,-15, 18, -9,-11, -8, 3, 15, -2, -4, + -9, 4, -3, 12, 14,-13, 11, -4, 2, -4, 0, -6, -6, -6,-14, -1 }, + {-10, 28, 3, 12, 9, 3, 11,-28, 6,-11, -7, 4, 0, 7, 8, -9, + 0, -6, 0,-16, 4, 7, 4, 4, 7, 3, 4, -7, 0, -3,-10, 6 }, + {-11, 14, -2, 19, -1, -1, 7, 9, -2,-27, 10,-14, 15, -4, 12, -4, + 2, -2, -6, 12, -6, 0, -5, -4, -5, 1, 3,-11, 5, -9, 3, -8 }, + {-18, 7, 13, 16, -4, 3, 9,-10, 10,-10, -3,-22, -4,-12, 3,-16, + 0, -3,-16, 8,-11, 1, 10, -7, 15, 3, 0, -1,-13, 8, 1, 6 }, + {-20, 10,-10, 10, 8, -1, 6, 0, 16,-12, 9,-10, -1, -5, -4,-13, + 13, 16, -8, 12, -2, 14, 18, 13, 0,-16, 2, -5, -5, -5, -4, 3 }, + {-14, 5, -7,-17, 5,-13, 23, 20, -4, -1, 1, -6, 13, 5, -1, 4, + -14, -2, -7, 8, 3, 2, 2, -7, 2, -1, 4, 7, 3, -9, -1, -5 }, + {-19, 3,-24,-28, -9, -7, 19, 3, 2, 19, 7, 5,-13, 8,-15,-17, + 3,-11, 4, 13, 3, 2, -1, -3, -4, -4, 2, 0, -5, -6, 6, 2 }, + {-17, 18,-30,-20, -2, -3, 1, 15, -1,-11, 6, -4, 11, 11, -4, -5, + -10, 0, 0, 1, 3, -7, 8, 2, 5, 1, 5, -5, 1, 6, 4, 1 }, + { -6, 1,-30,-25, -1, -8, -2, -9,-17, 16, 3, -1, -2, -9, -6, -7, + -3, 12, 6, -4,-10, 0, 10, -8, -6, -5, -3,-11, -4, 0, -1, -3 }, + { -1, -1,-34,-28, 1,-10, 2, 9, 4, 16, 2, 6, 14, 17, 0, 7, + -4, 4, 4, 4, 0, 1, -1, -5, 8, 1, -4, 1, -9, -2, 5, 6 }, + {-11, 14, 1,-31, -7,-24, 9, 7, 6, 5,-13, 1, -1, 3, 4, -1, + -2, -8, -6, 3, 5, -4, -6, 7, -2, 5, 3, 3, 0, 0, -5, 2 }, + {-25, 8,-11,-18, 1, -4, 8, -3, -4, 15, 6, -5, 8, 2, 3, 4, + -4, 5, 6, 8, -7, 6, 1,-11,-15,-13, 9, -4,-14, 10, 12, 7 }, + {-20, 11,-15,-25, 3, 4, 18, 13, -4, -5, -9, -1, -5, -2, -2, -7, + 16, 5, -4, -5, -7, -2, -3, -9, 11, -2, 0, -7,-17, -6,-11, 6 }, + {-11, 18, -5,-20,-15, -3, 9, 11,-20, 12, 5, 5, 11, -3, 7, 1, + 10, -6, -3, -3, 3, 3, 14, -7, 10,-17, 9,-11, -2, -6, 7,-12 }, + {-20, 8,-14,-17, -9,-13, -3, 0,-27,-14, -3,-14, 4, 3, 6, -6, + 7, 4, 23, 9, 11, 9, 3, -4, 9, 2, 4, -1, -6, 1, -8,-11 }, + { -9, 14, 2,-37, -7, 13, 6,-11, -6, 9, 18,-11, -6, 2, 12, 4, + -1, 3, 1, -2, -2, 1, -9, -4, -2, -3, 3, 5, -6, 0, -2, -8 }, + {-29, 8, -1,-13, -2, 8, 23, 2,-10, 7, 13, -6, -5, 11, 13, 0, + -10,-13, 11,-12,-10, 6, 4, 6, 4, 3, 6, -5, -9, -2, -1, 3 }, + {-18, 6,-10,-55, -4,-11, -2, 0, 1, -3, -9, -6, 3, -2, -1, 6, + 3, -1, 3, 1, -4, -7, -2, 6, 3, -2, -1, -3, -2, 0, 4, 1 }, + {-14, 5, 3,-21, -8,-16, -4, -2,-11, 27, 15,-20, 3, 0, 1, 1, + 2, -5, -5, 4, 1, -9, 5, -3, 3, 0, -4, -2,-11, -4, -3, 7 }, + {-17, -1, -9,-17, -8,-18, 12,-13, -9, 13, -3, 3, 3, -3, 1, -2, + 0, 16, -9, 6, 12, 9, 5, 11, 2,-15, 1, -4,-16, 7, -4,-12 }, + {-18, 8, -6,-11, -8, -7, 13, 7, 1, 6, 8, -1, 21, -4, 14, 15, + 18, -4, -3, 15, 0, 9, 4, 7, 3, -1, 9, -2, 0, 7, -8, 2 }, + {-10, 7,-18,-29, 3, 12, 12, 9, 11, 4, -1,-15, 1, -1, 8, -2, + -2, 10,-15, -1, 0, 6, 12, -6, -1, 10, -6, -3,-11, -4, 9, -6 }, + {-14, 14, -9,-21,-12, -2, -1, -7, -5,-10, 5, -8, 0, 6, 9,-11, + 11, -3, -5, 3, 8, 15, -2, -4,-22, 4, -6, 12, 2, 13, 6, -7 }, + {-12, 11, -5,-29,-25, 4, 12,-13,-11, -7, 4, 2, 2, -5, 5, 8, + 7, -5, -5, 6, 3,-10, 1, -6, 6, -6, -5, -1, -2, -4, 7, 6 }, + {-15, 11, -5,-16, 0,-13, 26,-23, -6, -3, 5, -2, -2, 21, -6, -3, + -5, -1, 6, -1, 0,-13, 2, -3, -9, -1, -4, -3, 5, -4, 12,-16 }, + { -9, 9, -1,-17, -3, -6, 12, 6,-18, -2, 11,-14, -6, 3, 14,-12, + -11, -5, 14, 2, 5, -8, -4,-11, 2, -5, 16, 6, -7, -4, 8, 13 }, + {-13, 5, 3,-28,-14, 0, 6, 23, 5, 4, -1,-17, 1, -3, 0, 0, + 5, 4, 0,-18, 14, 10, 4, 2, 5, -2, 4, -3, 2, 0, 2, 0 }, + {-15, 4,-13,-16, -3,-12, -2, 2, 7, 10, 9, 3, 11, 4, 23, 14, + 9, 16, 4, 1,-12, -3, 4, -7,-15, -7,-10,-14, -6, -8, -1, -6 }, + { -7, 10, -5,-10, -3,-13, 16, -1,-12, 7, -3,-12, 2, 13, 13, 2, + 17, 15,-13, 1, -5, -2, 3, -1, 1, -3, 6, -3,-12,-16, 7, -7 }, + {-11, -5,-12,-30, -6,-22, 1, 4, -6, -3, 12, 6, 7, 0, 16, 6, + -2, 0,-22, -2, -9, 2,-13, 8, 6, -8, 4, -7, -1, -6, 4, 6 }, + {-14, 5, 1,-27, -4, 2, 1, 14,-11, -7, -8, -4, 1, 8, 0, -6, + -13, 11,-12, -7, -5, 1, 10, 7, 3, -2, 0, 6, -8, 2, 10, -1 }, + {-10, 10,-25,-13,-20, -4, 19, 3, 13, 5, 5, 7, -8, 2, 4, 2, + 3, -1, -1, -9, 14, 10, 9, 14, 3, 3, -6, 0, -5, 4, 1, -1 }, + { -9, 15,-18,-17, 4,-11, 6, 7,-12, 8, -1,-11, 2, 3, 7, 16, + -3, -9, 7,-12, 23, 0, 6, 7,-14, -9, 8, 1, -2, 6, -2, -1 }, + { -6, 9,-16,-26,-14,-11, 9, -6, 5, -2, 13, 17, 21, 7, 18,-19, + 6,-23, -2,-15, -2, 2,-10, -8, 2, 1, -2, 4, -3, -4, -5, -4 }, + { 0, 6, -5,-28,-17,-32, 2,-10, 11, 3, -5, 9, 10, 3, 11, 11, + -3, 12, -2, 2, 4, -6, 9, -4, -4, -4, -4, -9, 2, 0, 2, 4 }, + { 0, -8,-18,-34, -9, -7, -4,-11, 10, 15, 11, -1, -8, 15, 6,-13, + 9, 2, -4,-12, 0, -1, 19, 12, 6, 5, 0, -3,-10,-12, 3, -5 }, + {-10, 6, -9,-17,-12,-11, 9, -6, 11, 11, 18, -7, 0, 16, 4, 2, + -6, 3,-12, -1, 0, 1, -5,-22, -2,-12, 0, 6, 17, 5, 5, 6 }, + { 12, -5, 7, 1, -5, -2, -1, 2, 2, -4, -3, -3, -3, -2,-29, 11, + 5,-13,-73, 24, 12, 4,-14,-10, 5, 1, 0,-11, -7, -7, 7, 3 }, + { 10, -3, -1, -3, 4,-11, -5, -2, -8, 7, 9, 2, -8, -6, 6, 7, + 21, 17,-54, 47,-14,-10, 14, 19, 13, 21, -4, 3, 1, 2, -4, 2 }, + {-12, 4,-16,-12, 5, -9, -4, 19, -7,-22,-22,-17, 3, 0, -6, 8, + 23, -4,-55,-28, 2,-26, 2, 1, 4, 0,-13, 6, 0, 10, -7,-11 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, + 35, -1,-67,-35,-24,-24, -6, 2, 2, -2, 1, 3, 2, 0, -1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, + 41, -4,-73,-15, 18, 4, 17, 8, -1,-16, -1, -2, 1, 0, 0, 0 }, + { -4, -4, 4, 6, -1, 2,-16,-10,-15,-10, 21, -2, -6, -2, 14, -7, + 10, -5,-55, 34,-12, 11,-13, -2, 2, 28,-26, 0, 7, 4, 21, -7 }, + { 2, 1, 15,-22, 10, -3, 14, -6, -2, 15, -2, -7, 20, 6,-15, -7, + 23, 10,-60, 8, -4, 29,-22, 2,-13, 9,-10, 12, -1, -3, 4, 7 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -2, 11, -5, + -21,-11,-60,-27,-17,-39, 6, 36, 0, -8, 2, 2, 0, 0, -2, 3 }, + { 2, -5, 9,-17, -1, 2, -3, -6, 8, 12, 7, -6,-33,-11,-14,-40, + 10, 36,-46, 0,-19, 5, 0,-10, 3, 12, -6, -8, 6,-12, -7, 1 }, + { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, -2, 0, + 4, -2,-87, -3, -2, 2, -2, 20, 2, 6, -1, 6, 0, 0, 2, -1 }, + { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 7,-76, 41, -7,-24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, + { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, + -32,-11,-64,-29, -9,-43, 2,-11, -1, -7, 0, -4, -2, -2, -2, 2 }, + { 10,-20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2,-20,-20, + -19, 3,-47,-18,-16, -6,-15,-42,-17, 14, -6, 8, 12,-10, 11,-12 }, + { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, + 10, 13,-68, -9, 26, 3, 5, 3,-21, 10,-15, 21,-22, 19, 11,-14 }, + { 1, 5, 18,-19,-29,-13, -2, 18,-10, 20, 2, 10,-10, 11, 1, 8, + -16,-17,-41, 10,-14,-25, 0,-14,-19, 17, 7,-12, 14,-11, 14, 5 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1,-43, 5, + 6,-12,-48, 19, 8,-38, -8, -3, 22,-21,-10, 15, 20, -9, -5, 8 }, + { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, + 22,-14,-71,-24, -2,-33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, + { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10,-11, + -17,-32,-58, 14,-14,-11, -2, 15, 2, -8, 12, 10, -9, 13,-33,-14 }, + { 15,-17,-19, 7, -8,-15,-32,-22, 7, 12, 18, 0, 0,-15, -4, 16, + 37, -2,-46, 11, 2, -8,-10, -8, 14, 9, -4, 5, 7,-17, 4, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, + 1, 7,-76, 41, -7,-24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, + { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, + -32,-11,-64,-29, -9,-43, 2,-11, -1, -7, 0, -4, -2, -2, -2, 2 }, + { 10,-20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2,-20,-20, + -19, 3,-47,-18,-16, -6,-15,-42,-17, 14, -6, 8, 12,-10, 11,-12 }, + { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, + 10, 13,-68, -9, 26, 3, 5, 3,-21, 10,-15, 21,-22, 19, 11,-14 }, + { 1, 5, 18,-19,-29,-13, -2, 18,-10, 20, 2, 10,-10, 11, 1, 8, + -16,-17,-41, 10,-14,-25, 0,-14,-19, 17, 7,-12, 14,-11, 14, 5 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1,-43, 5, + 6,-12,-48, 19, 8,-38, -8, -3, 22,-21,-10, 15, 20, -9, -5, 8 }, + { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, + 22,-14,-71,-24, -2,-33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, + { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10,-11, + -17,-32,-58, 14,-14,-11, -2, 15, 2, -8, 12, 10, -9, 13,-33,-14 }, + { 15,-17,-19, 7, -8,-15,-32,-22, 7, 12, 18, 0, 0,-15, -4, 16, + 37, -2,-46, 11, 2, -8,-10, -8, 14, 9, -4, 5, 7,-17, 4, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + -5, 3,-85, 23, -9,-17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 16, 65, -2, -2, 4, 3, 0, -7, 3, 1, 3, 1, 0, 5, 1, -5, + 0, 2, -1, 3, 0, 0, -1, -2, 6, 0, -2, 0, 0, -1, 1, 1 }, + { 5, 37, -4, 8, -4, -1, 9, 17, 6, -7, 5, -1, 11, 6, -4, 7, + -2, 4, 1, -3, 11, 3, 3, -9, 6, 0, -2, -4, -5, 4,-12,-11 }, + { 15, 24,-14, 2, 6, 17, 26, 5, 8, 11, -9, -7, -6, -8, 3, -5, + 9, 10, -3, 10, 0, 1, 4, -9, 4, 9, 3, 0, 4, 0, -5, 3 }, + { 9, 36, -9, -8, 7, 7, 4, 3, -1,-16, -2, 7, -5, -6, 6, 12, + -11,-12, 9, -1, -3, -9, 12, 6, -6, 2, 2, 5, 0, 5, 6, -6 }, + { 25, 39, -5, 24, 3, 10, 3, -6, 13, -8, 3, -7, 2,-10, -5, 2, + -2, 3, 5, -2, 1, 5, -2, 3, -4, 1, -5, -4, 0, 1, -2, 0 }, + { 16, 27, -1, 0,-14, 6, 4, -5, 7, -2, -6, 0, -3, -5, 2, -1, + -1,-19, 5, -8, 0, 11, 12, 5, 0, 3, 10, 6,-14, 14,-13,-15 }, + { 12, 23,-14, 2, 1, 4, -3, 16, 7, -8, 2, -8, 8, 6, -8, -7, + -3, 0, 2, 8,-13, 7, 13, -6, -4, 6,-13,-16, 14, 11, -7, 5 }, + { 16, 28, -7, -1, 6, -3, 9, 0, -7, 3, 0, 3,-12, 20, 8, 9, + 8, 23, 8,-13, -2, 4, 9, 3, -5, 13, 5, -2, 12, 14, 5, -1 }, + { 19, 37, 19, 5, 7, 5, 10, 5, 19, 10, 14, 0, 2, 5, 1, -4, + -4, 2, 2, -5, -2, -1, 2, -6, -4, -4, -5, -3, 2, -2, -2, -2 }, + { 24, 21, 1,-11,-10, 17,-14, 14, 6, -1, -6, -1, 0,-13, -1,-12, + -2, -5, 6, -4,-12, 14, 5, -2, -8, -8, 15, -7,-30,-12, 4, 0 }, + { 11, 26, -3, 3, 5, -1, -2, 3, -2, 10, 15, -4, 10,-28, 10,-17, + -8, 1, 2, -7, -1, -6,-15, -1, 4, 5, -7, 9, 0, -5, -4, 4 }, + { 18, 32, 1, 2, -7, 4, 15, 2, -9, -2, 12,-11, 7, 11, 13, 2, + 0, 5, 9,-10, 16, 3, -3, 5, -9,-23, 2, -2, -1, 5, 2, 11 }, + { 35, 24,-20, 2, 4, -1, 5, 14,-10, -9, 8, -7, 0, 5, -7, -7, + 11, 1, 5, 3, 2, 0, -2, 3, 0, 1, 4, 0, -2, -8, 0, -4 }, + { 9, 35, -1, 2, -1,-19, -3, 12, -1, 8, 8,-13, -1, -2, 2, 5, + -8, -1, 13, -2, 11, 1, 0,-10, 0, -3, -7, 2, 1,-12, 3, 12 }, + { 20, 27,-12,-12, 7, 4, -1,-13, -1, -9, 2, 13,-11, 5, 7, -9, + 9, 1, 1, 8, -9, 0, -6, 7, 4, 2, -2, 7, 3, -2, 1, -9 }, + { 8, 37,-20, -5, 0,-21, 10, -8, 3, 19, -9, 7, -3, -8, 10, -2, + 0, 5, 6, -4, -2, -1, 0, -7, 6, 1, 0, 4, -5, 6, -8, 2 }, + { 8, 27, 1, -3, -5, 1, 6, 0, 15, 2, 17, -1, 3,-17, 10, 5, + 5, -6, -6, 6,-10, 18, -5, 0, 0, 13, 7, 10, -5, -6, -2, -4 }, + { 14, 29,-20, -4, -3, 1, -5, -1, 2, 12,-10, -3, 4,-18, 4, 14, + -4, -1, -9, 15, -2, 2, -5, -3, 2, 9, -2,-14, -3, 4, -4, -7 }, + { 23, 23,-23,-11, 27, 4, 4, -1, 7, 0, -5, 9, 2,-11, 3, 7, + -2, -5, 2, -7, -7, 13, -3, -6, 2, 3, 3, -4, -1, -8, 5, -2 }, + { 16, 26, -6, 8, -9, -1, -2, -1, -8, 4, -2, 0,-12, 9, -1, 0, + -17, -9, 30, -5,-15,-16,-13, 0, 10,-11, -7, -3, -1, 0,-11, -2 }, + { 12, 32, -4, -5, 10, 19,-10, 4,-12, 5, -6, 9,-12, -6, -6, -8, + 4, 1, 3, 0, 8, 0, -3, -4, -7, -4, 10, 8, 6, 5, -1, 4 }, + { 46, 42, -3,-14, -2, -6, 6, -2, -5, -1, -3, -3, 1, -1, 3, 1, + 1, 4, -1, 2, 3, 1, -2, 6, 0, -1, -2, 4, -2, -1, 2, 2 }, + { 9, 33,-13, 4,-11, 3, -8, 22, 12, -2, 4, 0,-16, 5, 4, -1, + 7, -6, -9, 1, 7, 5, 0, -5, 5, -1, 10, 3, -2, -1, 3, -2 }, + { 9, 30, 6, -3, 6, 1, -7, 5, 11, 14, 7, 1, 0, 2, 2, -1, + 8, 7, -6,-13,-10, -2, 1, -6, 10, 7, 6, 5, -2, -5, -1,-16 }, + { 9, 28,-11,-10, 9,-10, 15, 8, 4, 9, -4, -7, 0, -5, 9, 8, + -7, 2,-15,-23, 4, -4, 4, 16, -8, -3, 0, -8, 14, 5, -3, 15 }, + { 17, 26, -5, -5, -1, -8, 20, 18, -7, -2, 4, -7, -8, -5, -4, 16, + 0, 0, -7, -2,-13, -5, -2, 3, 12, 1, 3, -5, 2, 2, 0, -1 }, + { 11, 37, 7,-23, 6, -1, 15, 13, 4, -9, 7, 5, 3, -3, -5, -8, + -2, 3, -5, -1, -8, 7, 2, 13, 1, 3, 0, -3, -1, 2, 0, -2 }, + { 21, 33, 7, 20, 21,-10, 6, -5, -5, -6, -9, 2, 10, 0, 8, -4, + 10, 2, -2, -2, 0,-10, -6, -2, 0, -5, 3,-11, 3, -9, -3, 1 }, + { 6, 30,-15, -8, 16, 1, 4, 6, 4, 5, 8, -3, 8, -9, -1, -6, + 8, 2, -2, 4, -2, 5, 11,-21, 3,-10, 16,-11, 24, 10, 14, -6 }, + { 15, 36, -3, -9,-20, 12, 0, -7,-18, -4, -8, -9, 9, -7, -3, -1, + 2, 7, -5, -8, 6, 2, 2, -1, 7, 1, 1, -3, 3, -4, -8, 1 }, + { 16, 34, 21, 3, -9, 10, 7, 9, -7, 1, -4, -9, -4, -5, -5, 3, + 3,-19, 1, 5, 4, -2, -6, -5,-10,-11, -8, -2, 2, -5, -8, -7 }, + { 28, 29, -3, 18, -2, 0, -6, 12, -2, 10,-11, -4,-13,-12, -6, -4, + 0, 4, -1, -8, 6, 4, 12, 11, 10, 10, -3, -6, 1, 2, 1, 7 }, + { 3, 8, 22, -8, 3, 36, -8, -1, 9, 6,-13,-14, 8, -1, 1, 2, + -2, -8, 0, 3, 1, 2, -1, 5, -1, -8, 0, -2, 2, 2, -1, 1 }, + { 0, 6, 0, 0, 4, 13, -7,-16, -6, 15,-14,-21, -9,-10,-10, -6, + -21, 5, 4, 2, 12, 4, 12, 11, -4, -6, -6,-10, -7,-18, 1, 4 }, + { -1, 3, 10, 1, -1, 15, 4, -7,-16, 3, 0,-22, 10, 2, -3, -2, + 13, 5, -8, 16, -5, 4, 0,-11,-10,-22, 0, -4,-17, 5, 2, 1 }, + { 12, 8, -4, -9, 14, 40,-21, 0, 1,-15,-10,-12, 12, 6,-10, 2, + 8, 6,-12,-10,-11, 1, 0,-11, 2, 1, 13, 0, 6, 3, 8, 4 }, + {-10, 3, 5, -4, -3, 3, 0, -9, 2, 8,-22,-23, 17, 8,-17, -3, + 14, -8, -4, 1, -8, 3, 0, 5, -1, -3, -2, -4, 1,-10, 0, -2 }, + { 0, -1, 5, -7, 4, 12, -2, 0, -7, 2,-16,-15, 12, 21, -7, -4, + 7, -7,-11,-15, -7, -9, -5, -8, 0, -6, 8, -3, -8, 22, -7, -9 }, + { 7, 19, 4, -9, 24, 22, 2, -6, 8, 13,-14,-20, -4, 11, 8, -4, + -1, 2, 0, -7, 5,-17, -3, 3, -6, 5, 3, 4, -5, -7, -3, 14 }, + { -2, 6, 2, 8, -2, 5, -4, -2,-10, 3,-45,-30, -3, -3,-12, -4, + -3, -3, -1, 9, -6, -6, 5, -4, 0, 5, -1, -2, -1, 0, -6, -1 }, + { -3, 14,-16,-10, 10, 0, -2,-40, -9, 12, 2,-19, 15, -4, 4, 3, + 3, -4, 7, 1, -4, -5, 0, 4, -1, 0, -9, -2, -4, -1, -2, 0 }, + { 7, 16, 2, -7, 8, 2, 0, 1, 5, 21,-10,-26, 7, 2, -9, -7, + -3,-16, 8, 5, 5, -6, 10, 4,-14, -6, 5, 3, -2, -2, -4, 1 }, + { -9, 14, -1, 3, 3, 11, 1, -5, -3, 13,-16,-18, 20, 6, -5, 0, + -3, 2, 8, 4,-19, -9, 12, 0, -8, 2, 2, 1, 6, 13, -7,-11 }, + { 2, 5, 16, -4, 19, 15, 4, 0,-11, 7,-10,-10,-16, 18,-11,-12, + -9, -4, 7, -4, -4,-17, 1, 1, -8, -3, -3, 5, -2, -6,-11, -5 }, + { 2, 12, 0, -9,-10, 14, 6, 2, -3, 2,-12,-28, 12, 1, -1, 2, + 0, -3, -4, 7, 16, 5, -7, 8, -4, -3, -1, 3,-12, 4,-17, -5 }, + { -4, 7, 11, 6, 1, 14, -4, -6, 5, 5, -6,-24, 23, -9,-15, 13, + -7, -9,-15, 10, -1, 8, -5, 1, 12, 6, 2, 0, 4, -2, 9,-10 }, + { 1, 5, 11, 3, 6, 12, -3, 8,-21, 5, -7,-20, 12, -2, -9, -3, + 17, -7, -8, -9,-14, 3,-13, 18, -8, 9, 2, -8, 4, -8, -5, -2 }, + { -3, -3, -1, 5, -2, 15, 3, 2, 1, -8, 1,-39, -6, 13,-13, 0, + -2, -5, -6, -3, 0, -5, -2, 15, -9, 5, -3, -6, -2, 7, 0,-13 }, + { 2, 8, 5,-12,-13, 22, 8,-16, 11, 5, -2,-32, -2, -4, 11, 5, + 5, -6, 1, 3, 1, 5, 3, 6, -5, 4, 4, -8, 8, 4, 1, 3 }, + { 13, 9, 5, -4, 9, 18,-11, 2, -1, 15,-10,-19, -2, 14, 0,-10, + 1, 1,-18, 3, 2, -6, -8, 20, 7, -8, 16, 9, 9,-13, -3, -2 }, + {-13, 11, 11, -9,-10, 13, -3,-18, 2, 10, 5,-21, 6, 15,-11,-21, + 3, 14, 0,-12, 9, -1, -2, -4, 3, -3, -9, -8, -5, -2, -8, 2 }, + { 3, 3, 11, 4, 0, 13, 1, -8, 10, 13, -6,-26, 2, 12, -3, -5, + 12, -2, 1, 8, -7,-17,-19, 5, 10, 7, -3, 2, -3, 0, 5, 0 }, + { 5, 0, 3, -3, -9, 5,-15, -5, -5, 17, -5,-31, 0, 13, 13, 5, + -1, -6,-14, 7, -8, 9,-14, -2,-16, -4, -4, -6, 6, -6,-10, 6 }, + { 13, 3, 1, 7, -3, 4, -1, -2, -1, 4, -8,-32, -1, -4, 0, 3, + -10, 7, 10,-10, 4, -1, 6, 2,-16, -9, 4, 3, 13,-23, -3, -4 }, + { 4, 11, -4, -9, 4, 11,-12,-12,-12, 6, 1,-28, -3, 14, 18, -2, + -12, 7, 15, -3, -5, -7, -3, 2, -6, 4, 4, -2, -5, -3, 2,-13 }, + { 8, 7, -7, 0, 13, 7, -8, -7, 8, 36,-10,-22, 3, 23, -3,-10, + -3, 11, 1, -7, 3, 3, -1, -7, -4, 2, 3, 2, 5, 3, -4, -1 }, + { -1, 1, 13, 1, -6, -1, -6, -9,-18, 17, -5,-37, -1, -1, -6, -4, + 1, -6,-15, 2, 17, -9, 0, -3, 0, 4, 0, -5, 0, 4, 1, -5 }, + { 0, 14, 5, 0, -7, 2, -6, 17, -6, -9, 7,-16, -5, 23,-14,-13, + 8,-15, 11, 10,-11,-13,-33, -5, -2, 1, 6, 8, 0,-13, -9, 5 }, + { 11, 7, -2, -8, 9, 11, 25,-14, 7, 3, -1,-33, 14, 8, -6,-19, + 3, 3, 2, -1, -3, -1, -2,-10, -3, 1, 2, 1, 4, 2, -3, 4 }, + { -2, 8, 4, -2, 9, 13, -4, -2,-15, -3, 19,-37, 9, 25, -9, 2, + -5, -2, -2, -4, 4, 2, 2, 0, 3, 3, 3, 5, -2, -3, -4, -3 }, + { 10, 13, -1,-15, 4, 6,-18, -4, 25, 1,-23,-17, 15, 13, -8, -8, + 7, 4, -5, 3, 6, 9, -7, 6, 0, -5, 8, 0, -6, -1, -2, -2 }, + { 1, 3, 9, -5, 27, 15, -9,-31, -1, 23, -2, -9, 1, 8, -1, -7, + -2, -8, -4, -4, -2, -1, 3, 5, 0, 0, -1, 1, -7, 7, -3, -3 }, + { -8, 7, 3, -6, 8, 3,-11, -2, 36, 14, 1,-30, 6, 10,-12, -6, + -6, -2, -4, -3, -5, 0, 9, 4, -5, -5, -8, 12, 4, -3, 1, -8 }, + { -2, 9, 33, 0, 12, -3, -7, -4, -4, -1, 6,-25, 11, -6, -9,-11, + -2, -4, -2, 6, -1, -3, -6, 15, -6, 3, 10, -4, 1, 0, 5, 8 }, + {-22,-21, -9,-19, -5, -7,-12,-15, -8, 9,-19, 14, -7, -4, 5, -8, + -2, 7, 1, -3, 4, -4, 6, 11, 2, 6, -3, -5, 2, -2, 0, -3 }, + {-32,-13, 3,-24, 3, -8, 4, 1,-10, 14,-15, 0, 4, 6, -1, 6, + 7, -1, 6, 4, -3,-17, 1, 4, -6, -1, 1, 0, 3, 3, -7, -4 }, + {-32,-11, 7, -8,-12, 13, -5,-22, -4, 12,-16, 2, 0, 4, 0, 1, + 0, 6, -5, -8, 2, 6, 5, 0, -3, -6, 5, 6, 5, 5, 13, -4 }, + {-44,-33, 6, -4, 2, 0, -9, 10, 3, 4, 7, 0, -1, 7, 5, 1, + 1, -3, 1, 6, -1, 0, 2, 3, -4, 0, 0, 1, 0, -1, -2, -1 }, + {-30,-18,-24, -8, 5, 0, -2, 14, 7, 0, 1, 12, 6, 4, -9, 7, + 5, 7,-11, -5, 1, -8, -1, 2, 2, -9, 7, -1, 7, 5, 6, 6 }, + {-22,-20,-13, -9, 20, -3, 10, -8, 6, -4, 2, -7, 10, 8, 0, -1, + 2, -3, 6,-19, 2, 4, 3, 3, -7, 2, -1, -6, 1, 1, 6, -2 }, + {-27, -8, -1, 3, -1,-11, 24, 4, -1, 1, -8, 8, 5,-11, 15, -3, + -15, -1, -1,-13, -1, 1, -5, 5, 2, 3, -9, 0, 4, 3, -7, 6 }, + {-33,-16, -1, -8, 10,-23, 6, 13, -1, -3, -9, 0, 5, -7, -5,-12, + -2, 3, 3, 6, -2, -3, 2, -3, 9, -6, -3, -2, 0, 5, -3, -4 }, + {-22,-17, 11, -3, 3, 1, -1, -5, 17, 2,-15, -2, 10, -9, 6, 14, + -16,-12, 20, -1, -7, 6, -3,-12, 1, 10,-10, -1, 7, -3, -1, 10 }, + {-28,-13, 1, -3, -1, -1, 0, 3, 3, 5, 1, 10,-10, -3, 7, 2, + 4, 19, -1, -1, 10, 5, -8, 1, 11,-15, -4, -3, -5, 4,-13, 3 }, + {-22,-13, 42,-20, 5,-13, 7,-11, 1, 1, -1, 1, 6, 3, 6,-11, + 3, 3, -2, 0, -4, 4, -3, -1, -5, 2, 0, 0, -9, -1, 4, 4 }, + {-26,-15, -2, -6, -4, -2, 16, 8, 21, 8, 1, -3,-10, 7, -8,-12, + -5, 12, -9, 3, -2, -3, 18, 1,-12,-15, -4, 5, -3, 0, 12, 7 }, + {-26,-16, 5, 6, 14, -3, 15, 6, 1, -7,-13, 16,-15, 5, 11, -2, + 9, -7, -4, -2, 0, 0, -2, 7, -8, -6, -5, 2, 7, -3, 2, 12 }, + {-31,-17, -8,-30, 4, 14, 6, -6, 6,-11, 0, 3, -4, 0, 0, -4, + 0, -4, 1, 4, 3, 4, 0, -5, 3, 2, 2, 0, 2, 1, 3, 5 }, + {-61,-10, 4, 10, 4, 7, 0, -3, 0, 1, 0, -3, 0, 1, 0, -2, + -1, 1, 2, -2, 4, -3, 1, 1, -1, 1, -2, -4, -4, 4, 0, 0 }, + {-28,-13, -8, -4, 3, -3, 2, 1, 11, 14, 3, 9, 1, 13, 3, 5, + -3, -2, -2,-12,-14, -9,-11,-15,-12, -5, -4,-12, 3, -3, 0, -5 }, + {-41, 0, 12,-24, 13, 4, 5, 16, -5, -4, 0, 0, 13, -4, 1, -9, + 9, -6, -1, 6, -2, 5, 2, 9, 6, -9, -8, 8, -2, -3, -6, -4 }, + {-26,-19, -2,-15, 4,-14, 6, 0, 26, 20, 8, 9, 9, 3, -4, -5, + -8, 1, 0, -1, 5, 9, 3, 4, 4, 7, 1, 3, -2, -2,-10, 0 }, + {-29,-18, 9, -4, 1, -5,-14,-12, 5,-10, -5, 4, -5, 0, -1, -1, + 4, -5, 7,-16,-11, 2, 7,-15, 2, -4, 6, -4, -6, 7, -3, 7 }, + {-27,-16, 9,-14, 3, -8, 9, 0, 7, -4, -3, -7, 0,-10, -1, 2, + 1, -2, 15,-10, 14, 7, 6, 17, 3, -4, 3,-10, 8, -8, 3, 11 }, + {-21,-20, -8, -8, 4, 5, -3, -2, 0, -5, 14,-10, 11, -4, 13, 0, + 5,-11, 19,-18, 18, 3, -5, -3, -4, -8, 11,-10, 10, 3, 4, -9 }, + {-35,-15, 13,-12, 4, 0, -2, -4,-12, -3, -8,-24, -7, 1, 7, 8, + -3, 0, -2, -1, 3, -2, -2, -6, 8, 1, 0, 1, -6, -1, 2, -6 }, + {-19,-14, 13,-10, 9, -1, 1, 3,-12, 5,-16, 7, 13, 9, 4, -4, + 6, -5, 4, 9, -3, 17, -4, 12,-11, -6, -5, -6, 13, 2, 7, -9 }, + {-34, -8, -4, 1, 2, -1, 3, 6,-20,-11, 8, -1, 4, 2, -9, 4, + -4, -5, 16, 10, -4, 14,-13, 1, -6, 0, 2,-10, 0, -3, -3, 7 }, + {-36,-10, -8, -3, 2, -2, 14, -4, -1, -7, -4, 10, -1, -3, 15,-11, + 0, 2, 3, -1, 4, 0, 8, -1, 0, 18,-11, -5, 15, -5, 13,-12 }, + {-22,-13, 14,-20, 15, 25, 16, 10, 8, -2,-10, -5, -1, -8, 11, 8, + -1, -2, -4, 1, 2, -1, -7, 0, 0, 0, -3, 0, 2, -1, 0, 2 }, + {-31,-22, 7, 6, -2, 5,-20, 14, -6, 7, 0, 14, 3, -7, 3, -6, + -2, 1, -3, -5, 1,-10, 1,-24, 6, -2, 3, -7, 1, -7, 8, 7 }, + {-25,-20, -3, -9, 10, 6, 12, 7, 5, 4, -3, 6, -1, -5, -6, -8, + 3, 5, 6, 5,-10, 10, -4,-15,-15, -2, -9, 2, 18, 1, 8, 12 }, + {-24,-19, -2, -4, -7, 11, 6, 9, 16, 2, -7, 18, 6, -7, 6, 6, + -2, -9, 3, 12, -2, 3, -1, 6, 7, 8, 0, 8,-11, 8, 4, 2 }, + {-26,-20,-12,-12, -2, -3, 1, -5, -1, -2, 0, 3, 7, 9, -2, 2, + 9, 22, 13, 4, -4, -1, -2,-14, 5, 15, -8, -5, -7,-11,-14, -6 }, + {-21,-18, -1, -4, 0, 3, 7, -2, 10, 8, -8, -1, 15, 1, -9, 3, + 1, 3, -5, -2, 2, 4, 0, -1, 10, 2,-19, -8, 8, 30, -7, 8 }, + {-25, -6, 26, 4, -8, 4, -2, 21, 5, -4,-16, 5, 13, 4,-10, -1, + -6, -2, 2,-10,-13, 1, 3, -3, -6, -8, 2, 11, 1, -7, 0, 5 }, + { 0, -1, -2, 19,-12,-48, -6, 11, 8, -2, -4, -2, -7, 5, -3, 2, + -2, -1, -1, -7, 0, -3, -3, -4, -4, 4, 1, 3, -3, -1, -2, -5 }, + {-11, -8,-28, 18, 16,-24, -8, 19, 4, 8,-12, 9, -4, -2, 4, -7, + 6, 2, 3, 3, -4, 0, 1, -6, -4, -2, 2, 6, 0, -3, 1,-16 }, + { -9, -5,-26, 7, -3,-37,-16, -2, 2, -7, 4,-13, 0, -4, -6, -5, + -6, -4, 0, 3, 4, -3, -4, -4, 4, -3, 9, -4, -2, 2, 7, -4 }, + { 2, 9,-18, 7, 29,-24, -1, 7, 14, 10, 3, -3, -2, -5, 6,-10, + -6, -3, -8, 0, 5, 1, 4, 3,-12, 2, 6, 1, 3, 4, 1, -3 }, + {-20, 2, 8, 20, -9,-24, -4, 18, 3, 11, -1,-11, 6, 9, -1, -3, + 1, -1,-15, 3, 15, 9, 3, 2,-13, 2, -8, 8, 1, -1, 1, -8 }, + {-12, 5,-11, 6, 19,-26,-17, -6, 4, 14, 6, -8, 9, 5, -6, -5, + 2, -1, 20, 1,-11,-10,-18, 20, -7, 0, -3, 4, 2, 0, 10, 4 }, + {-15, 1, -2, 13, -8,-21,-22, 4, 4, 3, 3, -7,-31, 4,-10,-14, + 0, 8, 4, 5, 8, 11, 2, -8, 6, 7, 0, -2, 6, 8, 8, 7 }, + {-13,-10, -9, 12, 19,-16, -3, -2, 9, 2, 11,-29, -1, 9, 4, -3, + 1,-10,-10, 16, 1, 7, -7, -6, -4, -1, -5, 3, 6, 0, 3, 1 }, + {-17, -1, -5, 19, 12, -9,-21, -5, 2, 12, -7, -7, -3, 8, 7, -2, + 6, -9, -9, 1, -4, 1, 1, 3,-14, 2, -8, 0, 10, 1,-12, -6 }, + {-13, -5, 8, 15, 0,-20, -2, 20, 8, -8, 8,-19, 12, 10, 2,-11, + 0, 12, 1,-11, 0,-11,-15, 5,-11, 2, 4, -4,-11, 5, -4, -5 }, + { 3,-11, -7, 8, 0,-17,-26, 15, 19, -7, 10, -9, -5, -5, 14,-25, + 0, -8, 2, -9, -3, 9, 1, -6, 4, -4, 3, -9, -1, 6, 2, 2 }, + {-12, 5, 5, 9, 14,-18,-19, 4, 2, 16, 14,-21,-15, -9, -1, 16, + 12,-11,-10, -5, -7, 4, 15, -8, -5, -1, 1, 14, 13, -7, -1, -4 }, + {-10, -5, -1, 8, 7,-23,-10, 14, 6, 11, 10,-16, -3, 16, 6, 0, + 0, 9, 6, -2, -7, 1, 22, 5, 3, -8, 0, 3, -2,-10, 3, 0 }, + { -2,-14, 2, 16, 15,-17,-17, 6, 19, 4,-10,-15, -1, 15, 11,-14, + -8, 5, 8, 8, -2, -8,-11, 10, 10, -8,-14, 2, 13, 4, -2,-12 }, + {-10, 3, 6, 4, 19,-23,-19, 1, 4, -9,-30, 3, -6, 18, 0, 2, + 0,-11, 0, 3, 7, -2, 8, 5, 2, -3, 6, -9, 1, -4, 7, -6 }, + { 9, 5, -2, 21, 20,-33,-13, 7,-10, 8, 8,-15, -6, -4, 1, 5, + 3, 7, -2, -9, -1, 4, -6, 1, 0, 9, -1, -5, 2, 1, -3, 3 }, + { -9, -3, 3, 15, -3,-30, -7, -7,-25, 6, 2, -6, 1, 19, 1,-12, + 1, -8,-13, 9, 13, 1, 8, 2, 5, 15, -2, 3, -9, 0, -4, 4 }, + { -6,-12,-17, 25, 22,-13,-10, 9, 2, 11, -7,-16, 4, 6, 1, 0, + 0, 18, -4, -5, 4, -2, -1, -5, 0, -4, 6, 1, 6, -1, 7, 0 }, + { -1, 0,-10, 8, 8,-27, 0, -2, 29, 16, -2, -4, 9, -1, 2, 0, + 6, 10, 6, 4, 2, -7, 9,-18, 3, 3, 3,-10, 17, 10, 9, -6 }, + { -3,-12, -6, 11, 20,-32, 5, 21, 3, -4, -9, 2,-10, 1, 7, -4, + 5, 0, 0, -1, -8, -9, -7, 4,-10, 5, 0, 2, -5, 4, 9, 1 }, + { -5, -1, -5, 1, 2,-19,-13, 1, 6, 12, 2,-16,-17, 11, 10, 13, + 16,-12,-11, 3, -6, 0, 6, 4, -3, 1, 8, 2, 5,-11, 3,-14 }, + {-19, 5, 10, 11, 2,-23, -9, 16, -2, 7, 0,-11, -7, 10, 6, -7, + 26,-15, -4, 8, 6, -4, 7, -9,-15, 1, 8, -4, 4, 2,-12, 16 }, + {-11, 1, 11, -4, 1,-31,-13, -1, 8, 5, 4, -2, 0, 13, 7,-17, + 7,-10, -6, 1, 4, -1, 2, -9, -4, 9, 3, 3, -4, -5, 3, 4 }, + { -3, 1, 10, -1, 0,-15,-22, 4, 40,-11, -4, -3,-14, 9, 11, -1, + 9, -1, -6, 6, 3, -6, 0, 0,-12, 7, -2, 0, 9, 3, 1, 3 }, + { -1, -1, -1, 14, 8,-24,-14, -8, 5, 8, 5,-12,-17, 8, 2, 7, + 10, -8, 0, 4, -6, -6,-10, 8, 4,-12, 3, -9,-12, 5, 4, -3 }, + { -5, 1,-11, 8, 9,-24, 0, 2, 2, 14,-12,-13, 1, 6, 7, 0, + 7, -6, 9, 26, 11,-14, 8, 10, 1, 9, 0, 11, -2, 6, 2,-10 }, + {-13, 1, 4, 34, 19,-17,-15, 0, 3, -2, -7, -1, 0, -3, -3, -1, + 1, -1,-10, 8, 5, 0, -8, 4,-17, 9, -2, 0, 0, 6, 2, -3 }, + { -6, -4, 1, 2, 2,-14,-29, 0, 9, 34, -3, -5,-14, 6,-10, -9, + -5, -1, 0, 3, 3, 0, 1, -1, -2, -1, -1, -3, -3, -4, 3, -3 }, + { -4, 6, 3, 14, 14, -8,-29, 31, 11, 14, -4, -5, -6, 10, 6, -9, + -1,-11, -7, 1, 7, 4, 1, -6, 4, 0, 10, -7, -5, -1, 2, 4 }, + { -4, -4, -2, 14, 6,-32, -6,-14, 14, -5,-11, 10,-18, -4, 6, -8, + 9, 5, -4, 1, -4, 5, -2, -9, 3, 5, 2,-10, -6,-17, 3, 17 }, + {-16, 9, 21, 19, 4,-20,-17, 14, 9, 15, -6,-17, -1, 1, 6, -3, + 1, 1, 8, -3, -6, 6, 9, 4, 9, -9, -5, 1, -1, 0, -1, 2 }, + { -7, -5, 3, 19, 1,-20, -9, 14, 21, -7,-18, -9, 26, -7,-17, -7, + 12, 6, 0, -9, -6, 14, 9, -9, -8, 4, 15, -7, -9, -1, 9, 1 }, + {-20, 30, -6, 11, 24, -4, 0, -6, -2, 8, -4, 12, -8,-17, 0, 5, + -4, 1, -1, 3, -3, 5, 3, 3, 7, -2, -3, -2, 4, 0, 0, -1 }, + {-35, 17, 6, 1, -9, -1,-16, 3,-20,-13, 8, 7, -4, -7, -4,-20, + 7, 12, -5, 5, -5,-11, 12, -1, 15, -9, -6, 16, -4, -9,-13, 4 }, + {-21, 36,-19, 9, 0, -7, -8, 9, -4, -3, 3, 0, 7, -8, -2, -2, + -11, 13, -1, 5, -3, 7, 2, 3, -1, -2, -5, 1, -1, -2, -5, -3 }, + {-12, 33, -4, 1,-12, -9, 0,-13, -1, 2, -8, 4,-10, 6,-16, -7, + -1, -4,-10, 15, -1, 0, -5, -8, 5, 5, -3, 0, 2, -7, 1, -7 }, + {-14, 32, 5, -7,-15, 3, -5, 8, 14, 5, 9, 13, 3, 18, -3, 7, + 4,-10,-10, 10, -1, 2, 0, -2,-11, 5, -3, -4, 2, 2, 7, 4 }, + {-14, 34, 1, 20, -1,-12, 0, -3, -7, -4, 7, 18, 9, -3, 14, -7, + -9,-20, -7, -4,-13, 12, 1, 12, 5, -6, 2, -4, 0,-15, 1, 3 }, + {-21, 23, 7, -8, 3,-13, -3, 0, -6, -2, -7, 6,-12, 9, -6, -2, + -2, -4, -1, 6, 9, 5, -9, 15, 0, 8, -8, 7, 6,-15, 3, -5 }, + {-27, 32, -1, -4, -2, 4,-10, 12, -3, 8, 13, 7, 0,-15, 4, -2, + 3, 5, 7, -4, 9,-12, -1, -2, -1, -4, 0, -4, 2, -5, 6, -6 }, + {-17, 29, 15, 0, -1, -4,-10, 13, 12, -1, -8,-10,-10, 4, 7, -2, + 6, -5,-13, 19, 6, 1, -7, 2, -9, -2, 12, -4, -8, -3, 2, 4 }, + {-38, 27, 16,-15, -6, 3, -7, -4, 0, -1, 6, -2, -3, -6, 6, -6, + -3, 0, 2, 0, -4, 6, 1, -1, 0, 4, -1, 3, 4, 1, -2, 5 }, + {-33, 40, -4, 2, 1, 0, 0,-10,-14, 0, -7, 4, -1, 3, -2, 5, + 7, 6, -1, 4, 1, 3, 1, -7, 1, -4, 5, 7, 0, 4, 3, -4 }, + {-20, 25, 12, -4, 16, -4, 2, 2,-14, -2, -3, 29, -1, 1, 3, 1, + 9, -5, 2, -8, -3, 1, -7, -2, -7, 1, 0, 4, 16, -2, -1, -1 }, + {-10, 30, 17, 3, -5, -2, 0, -5,-22, 4, 5, 5, -3,-18, -6, 10, + -5, -7, 2, 8, 7, -7,-11, -2, 0, -3, 3, 2, 11, -4, 4, -4 }, + {-11, 30, 11, 4, -3, -8, 1, -2, 4, 18, 3, 1, -1, 0, -8, -4, + -3, 10, 13, 14, 5, -5, 1, 1,-10, 2, 15, 4, 9, -1, -5, -3 }, + {-17, 32, 18,-18, -3, -5, 6, 10, 1,-15, -5, 9, 8,-12,-10, -6, + 11, 9, -5, -8, -7, 10, 5,-10,-14, -4, -3, 1, 9,-11, 2, 1 }, + {-13, 28,-11, -1, 2,-16, -2, 7,-24, 0, 3, 6, 3, -1, -8, -7, + -12, 2, 2,-20, 10, 4, 0,-13, -2, -2, 1, 8,-14, 0, 4, 1 }, + {-14, 23, 12, 8, 8,-26, 2, -4,-14, 13,-14, 15, 3, -9, -1,-13, + -10, -2,-10, 6,-16, 12, 8, 0, 9,-10, -7, -4, -4, 7, -8, 8 }, + {-20, 45, 10,-14, 4, 16, 8, -9, 1, -8, 10, 5, -7, -2, 2, -5, + -1, 0, -5, 4, -6, -2, 4, 1, 3, 4, -4, 2, -2, -2, 5, 1 }, + {-20, 26, -4, 1, 7, 4, -8, 1, -5,-13, 2, 13, -7, -3, 6, -6, + 22, 0, 5, 11, -4,-11, 8, -9, 2, -2, -4, -2, 2,-13, -4, -8 }, + {-28, 18, 17, 3, -8,-23,-16, -6, 5,-10, 14, 10, 5, -1, -8, 4, + -2, 13, -3, -2, 3, 4, 3, -2, -3, -4, 0, 1, 3, 4, 0, 4 }, + {-12, 32, -6,-16, 18, 12,-16, 0, 7, 13, -4, 5, -8, -1, -3, 4, + 6, -2, -1,-13, 4, -1, 3, 12, -3,-10, 1, 6, 8,-11, -2, 4 }, + {-18, 26, 2, 5, 0, -9,-17, 14, 5, 1, 7, -3, -8, -3, 11, 7, + -5,-12, -8, 7, 0, -7, 2,-12, -9, 13,-11, 9, 6,-11, -5, 11 }, + {-24, 22,-15, -9, 8, 1, -7,-12, -9, 3, 11, 15, 14,-11, 12,-15, + -5, 7, -2, 0, -8, 3, 3, -1, 2, 11,-11, 14, -6, 13, 1, -6 }, + {-20, 28, 18, -4, -6, -5, 12, 14, 2, 10,-13, -6, -8, -6,-13, -1, + -26, 22, -3,-14, 6, 0, 10,-15,-13, -9, 6, -7, 1, -5, -4, -1 }, + {-19, 26, -8, -3,-14, -6, -9, -4, -8, 15, -8, 3,-12, -4, -2, -7, + -5, 3, 13, -3, -4,-25, 4, -1, 5,-12, -1,-13, 5, 2, 0, 6 }, + {-18, 43, 14, -8, 1,-23, -2, -2, 1, 3, -7, 0, 0, 8, -1, -3, + -5, 1, 5, 2, 0, -2, -2, -2, 1, -1, -1, -7, 0, 3, -3, 9 }, + {-11, 30, 10,-14, 3, 1, 10,-11, 1, -7, -4, 14, 2, 1, -9, 1, + -11, -2, -7, 5,-11, 1, 3, 14, 1,-16, -8, 3, -5, 7, -4, 4 }, + {-18, 24, 6, 3, 8, 7,-22, -7, -7, 3, -8, 4, 23, 9, 3, -1, + 3, 6, 7, -1, -7, 6, 4, 1, -3, 1, -6, -1, 2, -7, 3, 3 }, + {-15, 38, -7, -1,-11, 2,-17,-24, 24, 8, 7, -4, -5, 2, 2, -7, + 1, 4, 0, -9, 5, 0, -1, 1, -1, -5, -6, 3, 0, 7, 8, -3 }, + {-14, 22, 1, -5, 9,-12, -9, -5, -6, 5, 7, 8, -1, -4, -9, -3, + -33,-16, -9, -1, 12,-11, 17, -7, -3, -1, -7, 3, 2, -3, 16, -4 }, + {-14, 20, 6, 4,-10, -4, -4, -4, 1, -7, 2, 6, 8,-12, 4, 1, + -1, 12, 10, 3,-14,-10, -3, 18, -2, 33, -5,-17, 17, -5, 9, 7 }, + {-12, 23, 13, 0,-11, -8,-11, 12, -5, -9,-16, 11, 6, 4, 12, -5, + 5,-13, 7,-12, -3, 1, 2, 12, 1, -4, -1, 5, 4, 11,-12, -3 }, + { 15, 2, 14, 7, 1, 2, 1, 12, 10, 23, 4, 6,-20,-10, 4, 26, + -6, 13, 4, 3, 2,-11, 5, -7,-10, 4, 9, 1, 10, -4, 11, 4 }, + { 17, 15, 31, 17, 18, 16, 11, 24, 2, 4, 2, 3, -8, -3, 7, -3, + -5, -7, -2, -6, -4, -5, -4, -1, -4, -2, -5, -6, 2, -1, 4, -2 }, + { 16, 8, 15, 14, 3, 7, 21, 9, 8, 15, 21, 6, 8, 12, 5, -5, + 7, -3, 10, 2, -3, 8, 6, 0, 5, 5, 6, -3, 2, 4, 0, -5 }, + { 5, -4, 6, 12, 6, 13, 24, 17, -5, 17, -1, -6, -7,-10, -8,-18, + 3, -2, 2, 7,-15,-11, 12, -3, -2, -2, -4, -7, 2, 0, 5, 5 }, + { 10, -6, 8, 11, 12, 20, 22,-11, -3, 15, -3, 15, -2, -2, 0, 2, + 5, -8, 4, -5, -9, -4, -1, 2, -1, -3, 1, 3, 13, -1, 9, 7 }, + { -5, 8, 5, 11, 14, -5, 14, -9, 2, 35, 8, 15, 1, -2, 2, -2, + 4, -9, -3,-14,-12, -2, -2, -4, -2, -8, -3, 1, -6, 3, 10, 0 }, + { 16, 0, -6, 15, -3, 4, 4, 3, 3, 20, 5, -4, 10, 9, -9, -3, + -10, -2, -7, 11,-11,-10, 17, -1, 3,-15, 2, 9,-15,-10, 16, 10 }, + { 14, 4, -7, 19, 3, 0, 19, 8, 16, 34, -9, 6,-13, -1, 6, 5, + -1, -2, 4, 3, 2, 1, 1, -1, 0, -7, 2, -1, 1, 0, 6, -1 }, + { 1, 6, 9, 13, 9, 10, 15, 16, 10, 18, 13, 17, 3, -1, -7, 2, + -15,-11,-10, -4,-13, -6,-17,-13, -6,-14, 1,-10, 6, 4, -1, -1 }, + { 13, 1, 7, 10, 14, 13, -7, 5, 5, 28, 14, 14, -2, 2, 3, -3, + -13, -4, 10, -9, 19, -4, -3, 4, -5, -5, 0, 5, -5, 0, 3, -4 }, + { 1, 0, 6, 22, 9, 18, 18, -3, 5, 10, 12, -2, 1, -3, -8,-12, + 9,-10, -7, 1, -1, 19, 0, 2, -8,-11,-10, 9, 6, 11, 0, 3 }, + { 10, 11, 19, 44, 0, 14, 1, -7, 6, 22, 2, -1, 9, 2, 0, -4, + 4, 0, -6, -6, 3, 0, 0, -2, 2, -5, 1, -2, 0, 1, 1, 1 }, + { 5, 7, 0, 32, 30, 26, 5, 4, -7, -3, 15, -6, 3,-10, 7, 6, + -8, -7, 2,-13, -5, -1, -3, 7, 3, -2, -8, 0, 6, 4, 5, 0 }, + { 9, 8, -2, 4, 2, 11, 4, 29, -5, 14, 8, -5,-14, 8, 0, 9, + 8,-10, 5,-15, -6, -9, 9, -1, 18,-16, 9,-21, -3,-13, -2, 8 }, + { 25, 7, -9, 23, 20, 18, 6, 16, -9, 8, 8, -5, 11, 13, -8, 7, + 4, 10, -2, -1, -7, -9, -7, -9, -4, 1, 1, -5,-10, 8, 4, -5 }, + { 9, 2, 16, 14, -5, 14, 1, 0,-21, 17, -1, 9, 12, -3, -3, 4, + -4, 14, 10, 3, 0,-10, 7, 4, 4,-11, 2, 4, -1, -3, 9, -1 }, + { 17, 8, 11, 26, 15, -3, 14, -1, 12, 9, 10, -8, 8,-18,-11, -3, + -14, -7, 7, -3, -3, -4, 1, -7, -3, 2, -3, 16, 10, 0, 9, 6 }, + { 9, 8, 3, 8, 18, 14, 11, 1, 10, 6, 1, -4,-16, -2, 14, -2, + 1, 8, 12, 14, 3, -3, 8, 8, 12,-15, 3, -3, 3, -2, 14, 10 }, + { 22, -3,-11, 13, -7, 11, 4, 11, 3, 14, 0, -6, -2, -9, 4, 2, + -2, 0, -5,-27,-10, 3, -1, 5, 8,-24, -3,-11, -3, 2, 11, -1 }, + { 19, 2, 8, 36, 5, -6, 3, 15, -3, -4, -5, 14,-10, 1,-12,-10, + -3, -4, 3, -2, 1, -8, 4, 3, 5, -3, 0, 4, 8, -2, 8, 4 }, + { 8, 14, 15, 9, -4, 10, 5, 11, 9, 10, 8, 9,-15, 15, 6, -8, + -10,-13, 5, -8,-20,-13, -6,-11, -1, -3, -6, -4, -1, 0, 13, 15 }, + { -2, -1, 9, 12, 2, 2, 13, 3,-23, 33, 15, 2, -4, -1, 3, 8, + 8, 6, 6, -7, 8, 6, 9, -1, 3, -8, 0, -4, 1, -8, 11, -1 }, + { 6, 5, -6, 16, 2, -3, 31, 21, -9, 12, 0, -1, -4, 1,-12, 3, + -13,-18, 2,-11, -9, 2, -8, -6, 11, -3, -1, 0, -1, 0, 13, 5 }, + { 5, -1, 2, 0, 25, 5, 10, 16, -5, 21, 14, 12, 13, 2, -5, 5, + 5, -3, -2,-14, 0,-12, 7, 11, -1, -7, 19, -1, -1, -1, 8, -1 }, + { 10, 7, 3, 11, 0, 8, 22, 3, 3, 19, -4, 12, 15, 9, 5, 15, + 2, 1, 2,-10,-10, 0, 2, -1, 0, 1,-12, -1, 21, 16, 9, -7 }, + { 11, -4, -5, 24, -7, 11, 20, 11,-15, 18, 5,-13,-15, 0, -5, 9, + 1, 0, -1, -9, 4, -8, 6, -8, 1, -2, -7, 20, 9, 3, 9, 3 }, + { 20, 0,-12, -6, 9, 31, 9, 12, 8, 27, 15, 7,-16, 5, -3, -7, + -1, -9, -2, -7, -3, 4, -8, -3, 3, -6, -2, -2, -3, -6, -1, 2 }, + { 6, -6, 48, 8, -3, 19, 12, 11, -7, 2, 3, 0, -1, 1, 8, -4, + 4, -6, 0, -4, -4, -3, 3, 6, 3,-13, -8, 5, -3, -7, 8, 5 }, + { 7, -2, 6, 11, 12, 2, 14, 4, -5, 12, 2, 9, 4, 2, 0, -1, + 2, 0,-15, -9,-16, -2, 8,-17, -5,-22,-19, -5, -1,-10, 1, -2 }, + { 11, -9, 3, 12, 6, 6, 1, 17, -6, 19, 14, 7, -7, -1, -1, -9, + 9,-11,-17, 0, -6, 16, 0, 1, 9,-24, 3, 3, -9, -3, 3, -2 }, + { 9, 0, 1, 8, 1, 7, 2, -5, -3, 8, -1, 7, 2, 6, -3, -6, + 5, -2, 6, -2, -4, -3, 0, -3, 13,-50, 1, -2, 2, 4, 4, 3 }, + { 7, 0, 26, 21, -4, 2, 17, 8, 7, 11, -7, 1, -1,-15, -1,-15, + -11, -4,-17, -4, 1, -7, 3, 6, 3, -9, 2, 3, 6, 10, 6, 12 }, + { 1, -2, 2, -1,-10, -4, 6, -3, -5, -2, -8, 2, 2, 2, 8, 0, + 1, 1, 6, 0, 11, 13, 3, 4, 0,-12, 11, -5, 19, 20, 2, 5 }, + { 5, 3,-13, -2, 1,-12, 11, -7,-12, 7, 10, 0, 7, 0, -2, 4, + -6, -9,-11,-12,-23, 12, 10, -3, 0, 6, 19, -1, 24, 18, 9, 12 }, + { 6, -3, 2, 5, 2, 2, -2, -5, -8,-11, -4, 3, -8, -4, 5, -3, + -16, -4, 3,-12, -4, 3, 32, 7, 2, 8, 32,-18, -1, 12, 1, 7 }, + { 0, -8, -1, 0, -8, 7, -8, -1, -1, 4,-12, -1, 3, 0, 1,-18, + 8, 8,-14,-10,-11, 19, 9, 5, -7, 6, 8, -4, 26, 12, -1, 6 }, + { 3, 5,-14, 7, 14, 8, 20,-13,-16,-10, -2, 17, -7, 4, -8, -9, + 14, -5, 3, -4,-12, 7, 14,-10,-19,-20, 35, 8, 13, 14, -2, 9 }, + { -2, -4, -1, 1, -3, 0, -1, 1, 2, 2, 6, 0, 0, 4, 5, -2, + 3, 3, 3, -2, -7, -3, -3, -1, 6, -2, 29, 22, 13, 34, 0, 14 }, + { -3, -9, 3, 1, 5, -4, 2, 0, 7, -9, 0, 2, -5, -3, 0, 6, + -1, -1, -1, 2, 2, 4, 8, 7, 20, -6, 7, 16, 33, 20, 6, -1 }, + {-11, 1, -3, -3,-11, 3, -9,-25, -1,-16, 4, -8, 15, 1, -2, 7, + 8, 23, 2, 18,-13, 16, 3, -7, 6, 3, 16, -8, 12, 16, 3, 4 }, + { 0, 5, 5, -5, 1, -1, 2, -3, -2, 1,-13, 2, 2, 10, 6, 7, + 18, 18, 7, 9, 8, 9, 21, 14, 7, 12, 15, 14, 15, 12, 11, 5 }, + { 1, -5, 11, -2, 17, 8, 3, 0, -1, 6, 11, -7, 6, 6, 7, 5, + -15, 14, 1, 11, 4, 10, 12, 1, 2, 4, 30, 1, 11, 1, 6, 13 }, + { 2, 4, 3, -7, 5, 8,-11, 7, -5, 9,-10, 6, 8,-10, -3, 10, + 1,-29, -4,-26, 5, -8, 13, 4, 3, 6, 35, 1, 3, 6, 3, 0 }, + { -2, 1, 0, 0, -1, -3, -7, -3, -9, -3, -1, -6, 3, 4, 4, 0, + 5, -1, -2, -2, -1, -4,-10, 8, 0, -6, 10, -4, 46, 12, 2, 28 }, + { 4, -1, 4, 1, 0, 4, -2, -2, -2, -1, 2, -4, 1, 5, 0, -3, + 1, 1, -2, 0, 1, -2, -1, -1, 3, -6, 35,-11, 13, 53, -3, -1 }, + { -5, -2, 0,-13,-16, 5,-12,-11, 1,-30, 3,-18,-24, -8, -5,-19, + 1, -3, -8, 7, -7, -8, 15,-19, 4, 10, 30, 24, 6, 1, -9, 10 }, + { -4, 8, -7, -4, -6, 12, -1, -9, -4, 2, -9, 3, 2, -2, 4, 2, + 22, 9, 4, -5, 0, 5, -2, -9, -3, 1, 18,-12, 18, 16, 4, 16 }, + { -5, -8, -3, -5, -3, 6, -7, -3, -2, -5, -3, 1, 2, 2, 4, -6, + 10, 3, 12, -3, 20, 0, 27, -4, 16, 5, 18, -3, 23, 4, 12, 11 }, + { 0, 1, 0, 1, -2, 1, 2, 1, -1, 0, -2, 2, -2, -4, 1, -2, + -2, -1, -5, -2, 0, 0, -2, 2, 9, 7, 63, 5, 12, -1, 1, 0 }, + { 4, -3, -7, -5,-11, -5,-12,-10,-10,-12,-15,-12,-14,-14, 1, 1, + 10,-10, 16, 6, 2, 9, 11, 9, 9, 8, 12, -1, 13, 12, 6, 3 }, + { 7, -3, -2, 4, 6, -8, 2, -3,-12, -5, -9, -8,-10, 15, -2, -4, + 8, 9, 7,-13,-18, 34, -5, 7, 12, 22, 16,-11, 13, 25,-15,-11 }, + { -3, -2, 0, -4, 1, 0, -3,-13, -7, 13, 12, -7,-10, 13, 19, 6, + 16, 15,-12,-15, -3, 34, 1, 5, 1, -9, 11, 21, 8, 17, -5, -6 }, + { 3, -5, 0, -4, 0, 4,-11, 4, -7, -3, -1, -8, 3, -2, 2, 1, + 11, 5, 6, 14, -3, 2, -4, -7, 0, 31, 15, -2, 24, 11, 5, 4 }, + { -1, -4, -9, 5, -8,-18, -4, -9,-20,-18, 7,-14,-16, 3, 8, -3, + 29, 11,-13,-13, 7, 1, 17, 6, 6, 21, 11, 1, 14, -8, 2, 5 }, + { -3, 8,-10, -6, 12, 2, 1, 3, 3, 3, 3, -6, -8,-14, 15, -5, + 16, 4, 16, 0, 7, -1, 0, 16, 2, 1, 22, 4, 19, 13,-11, 1 }, + { 2, -3, 10, 20, -4, -1, -8, 5, -8, -9, -6, -2, -4, -7, 8,-10, + 0, 8, -6, 1, -8, 14, 13, 5, 17, -6, 26, -1, 7, -1, 0, 12 }, + { -4, -7,-31, -2, -7, -1, 5, -5, -5,-12, 4, -7, -6, 3, 15, -2, + 5, -2, 7, -1, 10, 7, 8, -1, 14, 20, 14, 9, 16, 16, 8, 24 }, + { -7, 0, -3, -6, 1, 3,-13, -6, -4, -4, -5, -9, -1,-10, -4, -8, + 2, 0, -1, 1, 24, 24, 21, 31, 5, 2, 11, 12, 7, 4, 3, 6 }, + { -3, -5, 6, -4, -3, -1, 2, -1, -2, 1, 0, -8, -1, 2, 0, -4, + 6, 22, -1, -5, 8, 12, -1, -2, 28, 27, 20,-27, 14, 1, 2, -3 }, + { 1, -5, -2, -2, 6, -2, 9, 1, -2, -5, 3, 4, 11, 5, 2, 8, + -3, -1, 1, -2, -3, -5, 5, 8, 49, 12, 8, -3, 9, 20, 12, 17 }, + { -6, 0, 1, 7, 0, 9, -2, -4, 8, 0, -2,-10, 0, 7, 21, -1, + 0, 1, 17, -7, -5, 2, 4, 16, -2, 17, 14,-20, 15, 14, 4, 15 }, + { 0, 3, -4, 9, -4, 0, 6, 4, -6, -6, -5, -7, 2, -9,-10, -2, + -5, 0, -3,-21, 9, 14,-11, 13, 29, 2, 25, 4, 22, -1, 2, -3 }, + { 2, 12,-11, 2, 16, 9, -4, 7, 1,-10,-15, 11, -4, 3, -2, 4, + 4, -5,-10, 1, 4, 19,-15, 6, -4, -2, 30, -7, 11, 21,-12, 5 }, + { -2, -3, -2, 4, -1, -5, -3, -7, -5, 1, 0, -6, 1, -6, 7, 0, + 8, -7, -3, -2, 2, 14, 2, -3,-26, -1, 26, 22, 32, 1, -2, 6 }, + { 1,-38, -1,-20, -2, -3, -6, -4, 2, 2, 7, 0, 3, 5, 3, 10, + 6, 1, -3, -5, 7, 5, -5, -4, 8, 3, 1,-14, -1, -9, -5, -4 }, + { -5,-26, -7,-19,-10, -5,-11, 5,-11,-25, -8,-14, -9,-16, -8, -6, + -17,-14, -1, -1, 6, 2, 2, 2, 3, 0, 2, 8, -8, 3, 0, -3 }, + { 17,-49, -3,-23, -1, 11, 7, 3, 4, -4, 0, 0, -1, 4, 2, 4, + -2, -4, 2, -2, -1, -2, 2, 0, 0, -1, 0, 0, 1, 2, 0, 0 }, + { 4,-34, -6, -9, 1, 21, -7, 3, -2, -1, -3, 18, 2,-16, 7, -3, + 8, 7, -5, 7, 2, 4, 8, -6, -7, -2, -5, -1, 4, 1, 2, -4 }, + { 5,-29, 13, -2,-14, 3, 1, 18,-15, 4, -8, 8,-10, 8, 2, 1, + -8, 15, 3,-10, -4, -4, -2, 0, -3, -4, 2, -3, -4, -3, 12, -6 }, + { 13,-20, 3,-18,-17, 4,-14, 13, 28, 11, -8, -6, 16, 6, 0, 10, + 3, 4, -9, 13, 5, -7, 12, -5, 0, -7, 5, 1, 3, 3, 2, 1 }, + { 3,-27, -5,-11,-21,-11,-12, 0, -5, 7,-22, 1, 3, 5, 0, -5, + 8, 7, 1, -5, -7, 2, -5, 4, 1, 3, -8, -2, 0, 4, -2, 6 }, + { 31,-45, 0, -1,-12, 1, 2, -6, 4, 3, -1, 3, 3, 0, 5, 3, + -5, 12, 4, 6, 2, 1, -2, 1, 3, 2, 5, 2, 2, 2, 3, -1 }, + { 9,-45, 6, 5, -1,-17, -2, 18, -3, 2, 0, 1, 0, -1, 10, 8, + -7, -2, -5, -8, 6, -1, 0, 4, 6, -3, 12, -1, -2, 0, 5, -7 }, + { 3,-26, -2,-12,-12, 2,-10, 16, -3, 12, 4, 5, 11, 8,-16,-17, + -2, -3, -3, 2, 5, -9, 13, 1, 10, 11, 3, 5, -2, 2, 2, -7 }, + { 8,-26, 32, -7, -5, 22, 2, 14,-10, -8, -7, 3, 3, 7, 0, -5, + 0, -1, -3, 0, 8, 4, -5, -7, 6, -1, 4, 8, 1, 1, 7, -6 }, + { 4,-31, 2,-14, 2, 0, 1, 8, -6, -1, 17, -3, 13, -6, 5,-10, + -2,-10, -2,-10, -3, 7, 1, 5, -8, 8,-14, -3,-15, 7,-10, -6 }, + { 16,-27, 13, -4,-23, 7, -9, 6, -7, 5, 4, 2, -1, -3, 23,-18, + 7, 0, -3, 4, -3, 9, -6, -2, -1, 8, -6, 2, 6, -3, 2, -2 }, + { -1,-35, -2, -8, 11, -1, -7, -3, -2, 11, 7, 6, -6,-10, 9, 6, + -3, -5, -6, -3, 9, 16,-16, -9,-20, 12, 3, 5, -3, 1, -9, 4 }, + { 2,-24, 1,-12,-16, 5, -4, 3, -4, -1,-11,-11, -8,-14, 14, 10, + -8, 20, 8, -3,-11, 1, 1, -4, -4, -7, -3, 15, 2, -6, -2, 7 }, + { 9,-21, 2,-19, -7, -5, -8, 25, 3, 17, 5, -3, 9,-12, 8, 2, + -4, 3, 3, 1, 11, -9, -4, -3, 4, 3,-22, 6, 4, 6, 11, -5 }, + { 16,-23, 13,-17,-21,-12, 5, 9,-20, 7, 6, -6, 0, 2, -9, 6, + -6,-13, -7, -1, 5, -3, 5, -7,-10, 1, 0, 8, -9, 11, 0, -8 }, + { 10,-26, -9, -7,-19, -4, 6, 16, -7, 5, -4, 4, 8, 0, 4, -1, + 6, -7, 1, -8,-11, 10,-14, 0,-16, 6, -3, 5, -1, 14, 12, 1 }, + { 8,-27, 12,-14, -1, -1,-19, 10,-11, 21,-14, 9, -8, -3, 8, -1, + 12,-13, 3, -4, -2, 0, -9, 0, -7, 2, -3, 12, 1, -3, 3, 1 }, + { 18,-20,-14,-14,-16, -3,-24, 6,-17, 2, -3,-11, 2, -3, 12, 10, + 10, 1, 10, 7, 8, 5, 5, 4, -1, 7, 2, 2, 0, 4, 7, 0 }, + { 0,-30, 9,-16,-18, 15, 12, -3, 4, -4, -5,-11, -4,-12,-10, 0, + 2, -2, -4, -1, 2, 0, -1, -6, 2, -3, 4, -5, 7, 3, 5, 7 }, + { 25,-24, -1, -6, -9, 6,-13, -2, 3, 15, -3, 11, 4, -8,-11, 2, + 0, -9, -2, 7, 4, 8, 5, -8, 5, 6, -1,-11,-15, -5, 0, 11 }, + { 0,-34, -7,-11, -7, 9, -3, 19, 4, -8, 3,-11, 11, -3, -9, 12, + 9, 9, 2, 1, -7, 1, -3, 0, -6, -2, -1, 3, 0, -7, -2, -5 }, + { 6,-34, -4, -5, -3, -9, 2, 9, -1, 9, -5, -3,-26,-12, 8, -6, + -7, 11, -8, 4, 4, 1, -1, 0, 8, 9, -4, 7, -1, 1, -3, -1 }, + { 3,-30, 5, 6,-10, 3, -7, 6, 3, 3,-26,-19, -3, 1, 7, 5, + -4, -5, 6, 10, 13,-10, 4, -7, -4, 5, -3, 9, -6, 3, 9, 5 }, + { 4,-24, 9,-19, 2, -4, -5, 8, -3, 2, 0,-15, -1, 9, -4, 22, + 6, 9, 3, 7, 11, -9, 0, -3, 4, 5, -5, 10, -8, 5, -7, -3 }, + { 8,-27, 7, -3, -1, 2, -9, 13, 7, 12, -4, -6, -6, 5, 0, 7, + 5, 1, 15, -3, -4, 0, -5, -2, 7, -5, -7, 1, -2, 13, -8, 13 }, + { 17,-22,-15,-11, -8, 16,-14, 18, 2, -1, 14, -7, 14, -6, -6, -7, + -8, 17, 6, 4, 4, -7, -5, -9,-14, -6, -1, 9, -3, 1, 6, -5 }, + { 25,-30, 2,-12,-13, 18,-18, 16, 8, -3, 10, -8, -3, -1, -6, 3, + -5, -7, 4, 6, 7, 1, 1,-11, -5, 6, 2, -4, 9, -1, -5, -2 }, + { 7,-23, 7,-15, -1, -3, -1, 0,-10, 12, 2, 5, -4, 0, 4, 6, + -1, 5, -9, -1, -1, -7, 1, 17, 9,-17,-16, 8, 4,-14, 11, 14 }, + { 0,-31, 7,-13, 3,-11, -7, 6, 1,-11, 8, -7, 15, -3, 16,-11, + -1,-15, 16, -3, 5, 0, -2, -2, -6, 11, 5, 6, 5, -5, 6, 3 }, + { 13,-24, -2,-20,-10, 7, -3, -1, 15, 2, 6, -5, -7,-10,-20, 1, + -4, 14, 8, -2, 3,-13, -3, 1, -4, 1, -3, 2, 8, -7, 16, -4 }, + { 1, -2, -2, -3, -4, -7, 0, 3, 6, 7, 3, 2, 1, -2, -1, 0, + -6, 4, 2, -4, -3, -4, 5, 9, 5, 0, -3, -3, -4, -7,-31,-50 }, + { -1, -3, 7, 2, -1, 2, 4, 6, 0, 10, -2, 0,-20, -6, -3, 9, + -20,-22, -1, -1, 15, 9,-12, 10,-13,-20, 12, 3, 5, 6, -7,-26 }, + { 0, 4, -2,-14,-12, 6,-13, 11,-10, 3, 22, 6, 16, -2, -5, 1, + -3,-11, 0, -7, 5, -5, 0, 1, -1, -6, 8, 8, 10, 9, -5,-27 }, + { -5, 10, -2, 7, 9, -9, 5, -9, 5, 4,-15, 14, 1, 3,-10, 5, + 0, -2, 7, 3,-13, 6, 9, -6, 5,-14,-17, -1, 11, 14, -2,-26 }, + { 0, 6, -3, 0, -8, 6, 0, 1, 4, -8, 2, -5, 4, 7, 15, 11, + 9, 19, -2, 14, -8, 7, -1, 3, -3, -3,-10, -2, 12, -2,-12,-29 }, + {-12, -5, 0, -3, -2, 6, 3, -3, 2, -2, 1, 11, 2, -7, 5, 1, + 2, -2,-14, 0, -1, -5, 3, 8,-28,-26, 6, -6, 3, 8,-10,-27 }, + { -1, -3, 6, 2, 4, 15, 1, 0, 2, -2, -2, 13, 3, 6, 0, 6, + -1, -4, -1, -5, 8, -1, 5, -5,-15, 11, -8, -5, 14, -6,-14,-29 }, + { -5, -6, 0, 1, 0, 6, -3, 2, -5, -1, 5, -3, 2,-10, 3, 4, + 3, 0, 13, -3, -1, 4, -4, -6, 2, 9, 8, 2, -3, 28,-11,-31 }, + { 1, -4,-10, -9, -4, -3,-15, -6, 1, 5, -3, -6, 5, -6,-22, 27, + -13, 5, 3, -7, -4, 20, -7,-12, -1,-24, -4,-13, -8,-11,-15,-21 }, + { -6, -4, 19, -6, 2, 11, -6, 1, -3,-10, 9, -9, 12,-10, 2, 1, + -9, 1, 15, 7, -5, 5,-29,-35, 4,-30, 9, 9, 19, 17, 2,-17 }, + { -3, 3, -3, 1, 2, 5, -1, 5, -2, -3, 1, -3, -8, 3, -4, -2, + -4, -1, 12, 0, 2, -8, -6, -4, 16, -1,-14, -2, 25, -6,-15,-36 }, + { 0, -1, 3, -4, -4, -1, 7, -4, 8, 0, 10, 9, -4, 1, 10, -1, + -3,-13, -5, -4, -1, -4, 8, 11, 14, -7, -5, 16, 12, 13, -1,-28 }, + { 1, -2, 2, -3, -8, 10, 4, 9, 12, 3, 5, 0, 8, -3, -6, 2, + 16,-11, 11, 0, 1, 6, 1, 18,-10,-16, -1, -4, 5,-14,-15,-20 }, + { 1,-12, 5, 4, -7, 8, -1,-17, -2, -9,-14,-11, 6, -9, 5, -4, + 3, -2, 7, 18, -5, 5, 6, -1,-11, -2,-10, -3, 8, -3, -2,-32 }, + {-12, 5, 20, -5, -6,-11, -6, -6,-13, 4, -6, 19, -8, 2, 3, -9, + -4, -4, -1, 9, -1, 21, -1, 7, 15,-10, -1, -3, 9, -3, 2,-24 }, + { 0, -3, 2, -6, 4, -1, -9, -2, -1, -3, 6, -1, -5, -6, -5, -8, + 0, -2, -6, 9, -4, 3, 2,-13, 1, -7, 23,-13, 4, -3,-15,-33 }, + { -7, 2,-15, 11,-10, 14, 0,-11, 3, -1, 12, -4, -4, 9, 11,-13, + -13, -3,-14, 1, 3, 6, -5, 8, 0, 5, 5,-10, 4, 5, -6,-30 }, + { -6, 4, 0, -5, 4, 1, -1, -1, 3, 6, 5, -2, -5, 0, -2, 5, + -4, -2, -4, -2, 4, 7, -7, -1, 1, -4, -3,-19, 37, 12, 10,-40 }, + { -7, 2, -7,-12, 17, 11, -7, 2, 2, 3, 1, -1, 3, 4, -2, -5, + 9, -9, 6, 4, 9, 12, 11, -5, 2, -1, 0, 9, 5, -7, -2,-24 }, + { -7, 6, 1, 3, 1, 0, 6, 0, 4,-12, -2, -2, 1, -9, 10, -2, + 11, -1, 21,-12, 15, -5, 10, -5, 5, -5, 14, -6, 5, -7, -3,-29 }, + { -2, 0, -5, -2, -3, 1, -3, 0, 4, 2, 3, 0, 2, -2, 7, -2, + 3, -5, 2, -1, 6, -4, 0, -3, 8,-11, 19, -8, 22,-34, 13,-35 }, + { -1, -3, -1, 9, 11, -3, -3, -1, 7, 18, 11, -5, 2,-12,-11, 18, + 9, -5, 1, -6, -9, 12, 1, -3, -3, -9,-14, 9, 9, 8, -6,-26 }, + { 0, 5, -5, -1, -1, -2, 4, 6, 8, 2, -1, -2, 5, 1, -5, -4, + 1, 1, 18, 1, 7,-10, 3, -2, 12, -1,-15, 9, 12,-14, 13,-38 }, + { 3, 0, -8, -1, 0, 8, -9, -3, -8, 16, 3, 16, -5, -9, 0, -1, + -7, -1, -4, 13, 7, 0, 1, 2, -1,-16, 0, -2, 1, 8, -8,-28 }, + { 7, 9, -5, -3, -2, 2, 0, 3, 11, -6, -4, -2, -2, -5, 28,-18, + -6, 2, 15,-10,-15,-10, -2, 0, -2, -2, 4, -3, 7, 11, 5,-30 }, + { 9, 0, -7, -1, -4, -7, 2, 2, 9, -2, 2, 3, -8, -6, -6, 3, + -10, 4, 10, 5, 21, -4, 14,-18, 1, 3,-10, -2, 6, 14, -8,-26 }, + {-14, -1, 2, 3, -3, 7, 1,-22, -1, -1, 0, 1, 12,-14, 3, -5, + 0, 10, -3, 1, -5, 12, -3, 10, -8,-22,-11,-13, -7,-10,-13,-25 }, + { -2, -5, -4, -4, -9,-18, 9, -3, -5, 17, 13, 5, 6, 11, 3, 8, + 20, 4, 2, 9, 8, 5, 6, 1, 7, -7, -6, -2, -7, 0,-17,-23 }, + { -5, -5, 2, 0, 6, 2, -2, 2, -3, 4, 4, 0, -5, -2, -4, 6, + 8, 10, -1, 1, -5, 5,-14, -2,-11, 8, 6, 25, 7, -1, 0,-43 }, + { -4, 0, 4, -2, 7, 0, 3, 17, 5, 2, -5, 1, 21, 3, -2,-10, + -16, -9, 7,-12, 9, -8, 2, 5, -5,-10, -2,-11, -5, -1, -9,-30 }, + { -2, 3, 1, -4, -1, 0, 8, 1, 12, 4, -1, -1, 3,-17, 13, 9, + 0, 7, -6, -5, 9, 1, 5, 4,-10,-18, 0, 14, 11, -4,-16,-28 }, + { -1, 0, 2, -1, 4, 1, -1, 1, -1, -2, -1, -2, 3, 0, 0, -1, + -1, 1, 2, -2, 3, 3, -2, 4, -2, -1, -6, 1, -1, -1, 6,-70 }, + { 7, 3,-11, -1, 12, -4,-14, 4, 4, -4, 4, -2, 2,-12, -4, 15, + -17, -4, -3, 6, 8, -5, 22,-22, 5,-11, 15, -4, 4, -1,-21, -1 }, + { 10, -2,-13, 11, 4, 14, 4, 9, 8, 8, 19, 15, 14, 15, 5, 10, + 8, 15, -5, 4, 14, -8, 1, 1, 2, 1, -1, -3, 21, 8,-29, 13 }, + { -6, 0, -6, 6, -1, 2, 8, -4, -5, 4, -4, -5, 0, -2, -4, 0, + 9, -2, 1, -2, 26,-19, 21,-10, 4, 1, -8, 5, 22,-10,-13, 15 }, + { 11, -5, 1, 0, 6, 3, 7, -2, -2, -3, -5, -1, -2, -6, 1, 1, + -8, -5,-13, 13, -2, -3, -1, -9,-28, 4, 2,-11, 18,-20,-24, 9 }, + { 7, 4, -3, 6, 6, -6, -7, -5, -7, -4, -4, 0, -7, -5, -6, -5, + 2,-13,-12, 2, 0, 5, 18, 15,-13, -7, 13,-20, 16,-10,-19, 6 }, + { 5, -8, -1, 5, 10, 2, -1,-10,-11, 23, 8, -5, -8, 4, -5, -4, + -5, -5,-11, -8, 5, 1, 7, -9, -9, -6, 12, 14, 17,-12,-22, 3 }, + { -5, -8, -3, 3, 12, -1, 0, -4, -5, 1, 1, 6, 1, 5, -5, 7, + -2, 7, 1, 6, 6, 2, 0, -5, 17, -4, -5,-24, 13,-20,-27, 14 }, + { -1, 2, -3, 1, -3, 1, -3, 0, -2, 3, -2, 1, 2, -1, -2, -1, + -2, -5, 5, -2, 0, -7, 1, -6, 8, 8, 11, -5, 24,-43,-13, 2 }, + { -2, 4, 7, -3, -4, 4, 13, -4, 0, 0, -2, 9, 0, -3, -6, 1, + -7, 1, -1, 10, 0, 5, -1,-24, 25,-15, 7, 2, 22,-10,-21, 0 }, + { -5, 2, 6, -2, 13, 3, 5,-12,-11, 16, 6, 10, -5, 0, -3, 6, + 5, -5, -5, 10, 12, 10, 11, -7, 8,-14, 2,-15, 13,-14, -8, -3 }, + { 5, 6, -7, -5, 5, 2, 9, 5, 0, -1, -4, 2, 8, 0, 3, 5, + -12, 3, -3, -6, 2, -1, -5, 14, 11,-20,-21,-25, 24, -1,-10, 6 }, + { -5, 5, -2, 9, 4, -4, -1, -6, 11, -6, 5, 0, 2, -3, 6, -1, + -17,-18, -4,-13, 9, -1, 9, -7, -4, -8, 2, -3, 12,-31,-18, 5 }, + { -7,-11, 6, -8, 4, -3,-12, 0, -1, -6, -3, 0, 5, 9, 7, 2, + 1, -8, -6, 8, 2, -5, 7, -1, 16,-10, 16,-12, 18, -1,-25,-12 }, + { 3,-12, 1, 2, -2,-18, -8,-15,-10, -9, 2, -7, 11,-11, 2, -1, + -1, -1, -9, -6, 3,-14, -2, -1, 2,-13, -7, -9, 19, -5,-17, 2 }, + { 7, 1, -8, 7, 17,-13,-10, 5, 7, 1, -6, 4, 9, -4, 0, 3, + 8, 1,-14, -9, 4, 7, -9, 0, 6, -5,-12, -2, 25, -2,-19, 1 }, + { 7, -3, 6, -3, 1, 6, -7, 0, 10, 0, 4, -5,-17, -4, 4, -1, + 0, -3, -7, 19, 24, -1, 21, 8, 10, 9, 8, -1, 23, -2,-18, -2 }, + { 3, -3, 0, 5, 8, -2, -9, 2, 9, 6, 19, 8, 2, 6, -9, -2, + -4, -3, -8, 7, -7, -8, 5, 4, 26, -6, 7, 18, 24, 0,-13, 4 }, + { 0,-13,-11, -1, 3, -9, 5, 4, -7, 3, 0, 2, -1, 4, -5, 2, + 9, -2,-11, 15, 1,-21, 1, -1, 0, 4,-14, -4, 24,-16,-13, 1 }, + { 1, -9, -8, 0, 0, -4, 11, -1, 14, 16, 0, 17, -2, -9,-12, 0, + -1,-14, -9,-14, 0, -2, 19, 4, 6, 4, 4,-11, 8,-17,-19, -5 }, + { -3, 1, 2, 12, -4,-18, -1, -4, -7, 14, -3, 2, 0, -7, -8, 12, + -5, -9, 14, 12, -9, -2, 4, -6, 4, 18, -1,-25, 22, 2,-23, -5 }, + { -2, 0, 0, 0, 1, 3, 5, -1, 5, -2, -2, 2, -3, 0, 1, 2, + 0, -1, 2, -1, -9, -6, -7, -4, -2, 4, -7, -5, 64, -3,-25, 4 }, + { 12, -2, -3, 0, 8, -9, 13, -7, 6, -3,-12, 12, 15, -9, -4, 2, + 9, -4,-12, 3, 14, 1, 7,-15, 15, 0, -6,-12, 0, -3,-20, 6 }, + { 2, -1, -4, 5, 9, 6, -7, 2, -2, -7, -2, 0, -1,-18, -4, -6, + -15, -5, 11, 5,-10, -1, 2, 7, 12,-19, -7, 8, 21, -4,-15, 4 }, + { 4, 2, 5, 5, -5, 1, 3, 2, -8, 13, 0, -5, -2,-14,-11, 6, + 2, 17, 8,-13, 26, -2, 5,-15, -4,-14, 12, -9, 13,-21,-23, -4 }, + { 2, -3, -2, -3, 3, -2, 6, 9, -9, 13, 4, 2, 12, -3, -3, 1, + -17,-22, -3, 4, 3, -2, 1, -9, 1, -6, 11,-13, 14, 0,-15, 6 }, + {-16, -4, 17, -2,-20,-11, 11, 10, 5, -8, 16, 2,-17,-14, 11, 11, + -6,-11, -7, 12, 12,-10, -6, 5, 8, -4, -2, -5, 28, 3,-13, 4 }, + { 0, -3, 3, -7, 6, 8,-12, 20,-19, 18,-11, 10, -5, 0, -9, 11, + 3, 0, -2, 9, -7, -5, 18, 3, -2,-16, 1, 6, 12, -7,-16, 1 }, + { 4, 1, 5, -5, 15, 2, -8, 3, 5,-11, 15, -3, 8, -8, -1, 7, + 4, 7, -2, 6, -9, 5, 12, 2, 33, -2, -6,-18, 4, 0,-18, 11 }, + { 3, -1, 1, -1, 0, 1, 4, -1, -5, 0, 1, 0, 4, 2, -1, 4, + -3, 2, 0, -2, 4, 6, -1, 6, 42, 19, -4,-37, 19, 1,-15, -4 }, + { 2, 0, -5, 0, 10, 0, 0, -5, 3, 0, 0, -3, -3, 0, 2, -4, + -10, 2, -6, 4, 4, 1, 27, -7, 17,-34, 5, -9, 15,-16, -7, -5 }, + { -2, 7, 7, -2, 9, -2,-15, 11, 11, 7, 5, 1, 15, 1, -9, 31, + 2,-15, 2, 4, 3, 4, -1, -8, 2, -7, 6,-17, 11,-14,-11, 2 }, + { 1, 1,-11, 9, 9, -6,-14,-11,-10, 8, -3, 11, 16, -9, -8,-13, + -8, 9, 0, 6, 6, -2, 13, -8, -2, 3, 13, -3, 10, -6,-17, 4 }, + { 14, 5, 4, -6,-12, 10, -7, 8, 21, -8,-30, 15, -2, 1, 11, -9, + -5, 1, 0, -1, -1, -6, -2, 3, -5, 7, 9, 5, -5, 2, 0, 1 }, + { -1, 2, 20,-17,-15, 3, 3, 7, 11,-17,-13, -6, -3, 18, 17,-15, + -4, -4, -5, 22, 14,-14, -2,-10, -7, 11, 8, -7, -3, 0, -7, 11 }, + { 7,-11, -7, -8,-14, 22, 5, 2, 6, 13,-12, -2, 10, 3, 0,-21, + -4, 20, 3, 10, 21,-10,-12, 8, 11, 2, -5, 2, 1, 3, -1, 15 }, + { -1, -2, -1, -2,-13, 8, -4, 0, 7, -2,-17, 8, 18, 5, 3, 8, + -8, -2, 3, -4, 14,-18,-13, 14, 15,-13, -1, -2, 4, 11, 1, 12 }, + { 13, -6, -4,-16,-17, 16, 21, -2, 5,-11, -9, 19, 21,-17, -3,-17, + 3, 12, 8,-12, -6, 1, -7, 9, 9, -7, -5, -1, -3, 5, -6, -4 }, + { 11, 5, 12,-20, -6, 10, 4, 12, 8, -5,-10, 15, 13, 14, 10,-15, + -13, 1, 6, 14, 15,-17,-13, 4, -5, 10, 7, -6, -8, -3, -4, 12 }, + { 25, -1, 7, -5, -7, 11, 1, 17, 13,-15,-14, -4, 5, 3, 8, -3, + -2, 2, 0, 6, 16,-12, -6, -4, 4, -3, 7,-10, -3, -7,-13, 7 }, + { -8, 10, -3,-13, 5, 2, 4, 9, 9,-17,-13, 2, 11, 1, 6, -4, + 8,-10, 4, 1, 19,-15, -4, 12, 31, 7, -5,-17, -4, 9, -2, 7 }, + { 14, -6, -6, -6,-14, 13, 17, -5, 4,-14, -9, 7, 7, -9, 3,-16, + -15, 11, 11, 6, 4,-11,-19, 3, 5, 8, 13,-14,-14, 3, -4, 12 }, + { -2, -4, 10, -4, -7, -1, 27, 5, 2,-16,-18, 4, 12, -2, -3, -2, + -1, 1, -8,-12, 3, -4, 8, 15, 2, 4, 9,-13,-14, 9, -7, 5 }, + { 4, 2,-10, -5, -7, 2, 1, 4, -1, -6,-15, 6, 1, 10, 5,-10, + -9, -1, 13, -3, 5,-21,-11, 8, 8, 5, 27,-21,-18, -5, -1, 15 }, + { 11, 1,-16, -8,-11, 0, 5, -8,-12,-13,-17, 22, 4, -6, -1,-18, + -10, 0, 19, 2, -2, -8, -7, -3, 2, -2, -9,-17, -5, 4, 4, 10 }, + { 8, -6,-19, -5, -4, 12, 14, 15, 10, -9, -1, -9, 19, 12, 0, -1, + 2, 4, 7, 9, 16,-16,-14, 9, -4, 3, 1, 0, -2, 10, -1, -1 }, + { 12, -8, 12, -9, 0, 25, 7, 9, 2,-31, -9, -4, 15, 4, -5, 1, + -10, 11, 8, 10, 0, -6, 5, 11, -1, -6, 4,-10, -9, 6, 4, 5 }, + { 14, 6,-17, -2, 17, 12, -9, 2, 0,-25,-14, 5, 20, 14, 8,-20, + 5, 2, -2, -3, 9,-13, -3, -1, -6, 3, 7, -6, 0, 2, 3, 1 }, + { 8, 4,-15, -3, 10, 18, -4, 13, 8,-22,-10, 9, 19,-15, 7, -5, + -13, 12, -4, 9, 2, -9, -6, 0, 2, 1, -9, -6, 6, 1, -1, 11 }, + { 4, 1, 4, -5,-10, 18, 7, 2, -4, -9,-11, 0, 32, -7, 4,-16, + -1, 0, 6, 3, 6, -3,-14, 16, 9, -2, 7, -1, 0, -5, 5, -3 }, + { -3, 2, 3, -8, -6, 4, 6, 2, 4,-12,-15, 2, 8, 8, 9, -3, + -18, 6, 34, 11, 12,-15, -1, 2, 9, 2, -4, -4, 2, 4, 2, -3 }, + { 18, -6,-12, -8, -1, 15, 20, -4, -1,-11, -5, 6, 6,-11,-15, -7, + 3, 7, 10, 2, 8,-10, -5, 8, 15, -5, 5,-17,-13, 13, 11, 7 }, + { 8, -4, -6, -1,-14, -3, 6, -2, 1, -5, -1, 10, 10,-15, 5, 0, + -10, -4, -3, 7, -4,-19,-15, 27, 11, 18, 3,-19, -2, 6, 0, 12 }, + { 12, 0, -5, 0, 4, -5, 1, 5, 10, -7,-11, 21, 29, 1, -2, 1, + -4,-11, -1, 13, 11,-20, -1, 4, 4, 4, -5, 6,-13, -2, 11, 9 }, + { 2, -7, -7, -3,-10, -1, 20, 12, 1,-19,-19, -1, 5, 4, -7,-25, + 14, 1, -3, 2, 12, -4, -3, -3, -2, 6, 1, 0, 3, 2, 5, -1 }, + { 12, -8, 3,-12,-10, 10, 13, 0, 23,-14,-18, 10, 0, 15, 3,-12, + -3, -5, 5, -4, 2,-14,-10, 8, 2, 9, -1,-11, -3, 5, 13, 2 }, + { 9, -6, 7, -7,-30, 17, 6, 13, 1,-14, 0, -1, 6, -9, 8, 3, + -4, 0, -1, -7, -5,-13,-19, -3, -4, 4, -6, -2,-13, 1, -2, 3 }, + { 10, 1, 3,-18,-26, 17, 4,-16, 4, -3,-13, -4, -6,-11, -4,-21, + 7, 8, 2, 5, 13, -6, 1, 5, 8, 7, 9, -6, -6, 1, -1, 2 }, + { -3, -1, 0, -2, -2, 0, -1, 3, 4,-14, -8, -9, 13, 2, 50,-23, + -8, 8, 7, 11, 16, 3, -7, 0, -2, 6, 5, -1, 1, -2, 4, 3 }, + { 1, 3, 1, 1, -6, 3, 6, 6, 2, -2, -3, 10, 2, -8, -5, -5, + 5, 4, 4, -2, 10, -8,-40, -1, 21, 8, 3, -4, -1, 13, 4, 7 }, + { 2, 0, -4, -8, 5, 2, 7, -5, 5, -8, -4, -1, 12, 2, 12,-13, + -9, 0, 1,-12, 9,-43, 1, -5, 12, 1, 3, 6, 1, -1, 3, -2 }, + { 6, -2, -1, 1, 0, 4, 8, 14, 4, -7,-23, -5, 23,-17, -6,-15, + -8, 7, 10, -1, 7,-16, 4, -6, 2, 3, -3, -3, -1, 8, -1, 4 }, + { 10, 4, -4, 1, 7, -3, 2, 11, 4, -6, -3, 8, 5, 4, 1,-45, + -6, -4, 4, 2, 1,-14,-10, 1, 1, 6, 2, -8, -1, -3, 3, 3 }, + { 1, -1, 2, -3, -8, 9, 3, 3, -2, -5, -8, 8, 7, -7, -4, -6, + 5, -9, 11, -2, 46, -5, -1, 9, -2, 0, 3, -5, -3, -5, 7, 0 }, + { -4, 1, -2, -1,-11, 11, 8, -3, -2,-10, 0, 4, 9, 9,-17,-17, + -34, -4, -5, -7, -3,-12, -3, 11, 18, 3, -2, -5,-18, -5, -3, 6 }, + { 7, -5, -3, 1, -4, -3, -5, -1, 2, 5, -2, 3,-10, 12,-18, -5, + -10, 12, -9, 4, -6, 2, 0, 16,-17, 15, 14,-12,-10, -2, -9, -1 }, + { 4, -5, -3, -5, -3, -1, 7, 18, -7, 12, 3, 5, -8, -4,-20, 1, + -25, 1, -8, 13,-10, 8,-19, -1, -8, 10, 6, -9, -1, 0, 12, 4 }, + { -4, 5, 0, -1, 2, 5, -8, -2, -6, 4, -8, 9, 3, 2, -7, 4, + -25, 13,-23, 10, 14, 15,-11, 3,-18, 4, 16, -4, 1,-10,-10, 3 }, + { 5, -3, -1, -3, 4, 1, -3, -4, -5, 1,-12, 14, -7, 11,-15, 6, + -6, 24, -4, 13, -1, 15,-13, 8, 3, 7, -5, 2, 2, 0, 3, -7 }, + { -3, 1, 0, 8, 6, -1, 6, 5, -5, -2,-12, 4, 0, -2, -3, 5, + -6, 0, -8, 9,-10, 4,-28, 12,-20, 11,-13, 7,-18, 1,-11, 1 }, + { 1, -4,-15, 5, 0,-13, -5, 13,-11, 4, -4, -5, 5,-14,-16, 0, + -14, 5,-20, 12, 10, -7, -5, 6, 6, 22, 6, -4, -2, 3, 8, 11 }, + { 13,-11, -2, 16, 16, -7, 0, 20, -7, -1, 0, 5, -9, 12, -2, -5, + -22, 5,-10, 12, -6, 11, 9, 21, -8, 15, 4, 0, -8, -4, -4, 10 }, + { 18, -4,-13, 0, 1,-15, -1, -3, 2, 10, -1, 6, 1, -4,-20, -5, + -8, 6, -8, 17, -5, 5,-10, 8,-22, 6, -5, -2, 8,-17, 8, 2 }, + { 1, -2, -9, 6,-31, -8, -8, 8, 0, 5, -9, -4, 2, 3,-12, 11, + -18, 10, -5, 3,-11, 13, -6, 11, -3, 12, -7, 3, -9, -1, 2, 11 }, + { -9, -6, 21, -8,-15, 4,-11, 12,-11, 17, -1, 2, -6, 0,-15, 13, + -12, 19, 0, 2, -6, -3, -9, 10, 3, 17, -2, 5,-10, -3, 0, 1 }, + { 4, -6, 5,-10, 1, -5, 1, 0, 0, 0, 2, 7, -2, 2, -2, 0, + -4, 3, -4, 1,-12, 6,-49, 16,-10, 13, 0, -2, 8, 6, 1, 8 }, + { 5, -8, -7, 9, 13, -5, 7, 0, 10, 11, -4, -3, -1, 13,-14, 6, + -15, -6,-14, 16, 15, 1,-18, -4,-20, 20, -7, -1, -9, -2,-10, 10 }, + {-12, 4, 0, 10, 0, 3, 8, 4,-27, -1, -2, 19, -4, 2,-13, 3, + 1, 9,-12, 1,-22, 19, -5, 4, -9, 12, 2, -9, -8, 11, -3, 7 }, + { 4, -5, 11, -6, 17,-17, 5, -4, -2, -6, 1, -5, 2, 4,-14, 6, + -20, 19,-20, 12,-21, 5,-14, 13, -2, 11, 4, -3, 0,-10, -4, -2 }, + { -2, -1, -3, 8, -9, -7,-22, -3,-24, 13, -2, 10,-15, 5, -9, 4, + -7, 0, -5, 15, -8, 11,-13, 6, -4, 19, -8, 12, -4, 6, 9, 7 }, + { 2, -3, 2, -1, 0, 3, 1, 2, 1, -4, -2, -3, 1, 5,-12, 6, + -16, 14,-23, 10,-14, 17,-15, 16, -2, 9,-25, 9,-10, 16, 4, 9 }, + { -3, 7, -8, -3, 2, 2, -4, -8, -9, 10, 3,-11, 25,-10,-28, 27, + -9, 7,-13, 9, -2, 4,-12, -8,-14, 6, 7,-10, 3, 3, -3, 5 }, + { -8, -3, 1,-10, 8, -3, -9, -4, 13, 7, 2, 4,-10, 4, 3, 7, + -18, 2,-22, 15, 4, 20, -7, 5, -6, 13, -1, 4, -7, -6, 6, 13 }, + { -2, 3, 0, 2, -4, -2, 0, 0, 1, 2, -2, -5, 0, 1, -4, 0, + -2, -3, 1, 2, -1, 2, -8, -1,-24, 68, -3, 8, 3, 3, -1, -1 }, + {-15, -2, -9, -7, -1, 8,-14, 8, 3, 6, 0, -1, -8, 8,-23, 2, + -14, 17,-15, 8, -4, 7,-18, 0, -8, -3, -1, -4,-10, 4, -1, 4 }, + { 8, 0, 2, -7, 0, 5, 1, 3,-11, 4, -8, 14, 3, 20, 1, 26, + -11, 13,-13, 20, -2, 0, -8, 2, -6, 6, -1, 9, 3, -6, -3, 10 }, + { 5, 0, -1, -7, 10, 1, -3, 5, 4, 7, -5, -1, -3, -1, 12, -3, + -15, 7, -9, 22,-19, 8, -9, 4,-23, 13,-14, 6, -6,-14, -4, 7 }, + { 14, -5, -8,-10, 25, 3,-23, -7,-28, 0, -1, -9, 4, 1,-13, 20, + -8, 10,-16, 8, 12,-13,-21, 5,-13, 11, -2, 1, 12, -7, 2,-10 }, + { -5, -4, 9, 5, -6, 35, -7, 8, 15, 2, -1, -9, -6, 2,-18, 7, + -15, 6, -3, 2, 8, 12,-30, 7, -4, 20, 2, 6, 13, -6, -4, 0 }, + { 1, 8, -9, 9, -5, 12, -9, 16, -9, 16,-17, 14,-13, 15,-18, 14, + -15, 17,-12, 14,-13, 7,-16, 13, -9, 5,-11, 10, -9, 6,-12, 13 }, + {-10, -4, 5, 3, 1, 6, 8,-14, -5, 15, 7, 4, 8, 7,-22, 8, + -7, -8,-15, 26, 1, 13, -3, 17, -5, 9, -2, 4, -6, 3, -8, 9 }, + { 8, -3, 2, 3, 3, 1, -2, -1,-11, 8, -4, 0, -6, -5, -1, 13, + -37, 9, 1, -6,-10, -2,-10, 11, 8, 13, -3, -2, -6, 8, -4, 13 }, + { 3, 2, -3, -4, -4, 7, -8, 9, -8, 9,-20, 12,-19, 15,-18, 17, + -15, 7, -1, 20,-11, 6, -6, 3, 1, 9, 2,-14, -2, -2, 2, 1 }, + { -7, 1, -1, -3, -6, 4, 4, -3, 3, -1, 5, -4, 3, 2, -1, 9, + -59, 5, -4, 30, 3, 3, -2, -3, -1, 2, 2, 1, -1, -1, -2, 1 }, + { 0, -3, 2, 0, -1, -8, 0, 2, -3, 4, -4, 1, 10, 6, -6, 8, + -7, 4, 10, 11,-41, 27,-20, 3, -3, 8, 1, 11, -5, -8, 0, 4 }, + { 5, 1, 4, -2, 1, 2, -1, 6, -7, 2, 11, 4, 0, 0, -8, 7, + -10, 0, 0, 8, 2, 10, -1, 1, -2, 44, -2,-21,-12, -3, -1, 2 }, + { -4, 4, -2, -2, 6, -8, 2, 1,-10, 14, 8, 6, 5, 1, -2, 4, + -13, 4, 2, 5, 10, -2,-21, 32, -3, 18, 9, -6, -9, -9, 10, 2 }, + { 9,-16, -6, -2, 1, 4, 22, 2, -2, 1, -3, -2, -9, 3, 16, 19, + -24, -6, -6, -5, -8, -7, 8, -7, -1,-12, 5, -3, 0, 4, 2, -3 }, + { 10, 3,-16, -4, -1, 13, 4, 4, 1, -3, 1, -6,-14, 18, 3, 8, + -8,-28,-16, 4, 4, 2, 12, 7, 9, -4, -4, 5, -1, -1, 2, 2 }, + { -5,-13,-22, -3, -8, 21, -2, -9, 21, -4, -9, 5, -8, 15, 5, 1, + -5, -9, -7, -2, -5, -5, -1, -5, -5, -5, 3, 10, -4, 0, -7, -2 }, + { 5,-10,-18, 2, 20, 4, 13,-10, 8,-15,-11, -3, -1, 16, 10, 9, + -8, 6, 7, -5, 6, 11, 5, 17, -4, 7,-11, 5, -3, -6, 2, 1 }, + { 3, -5,-19, 1, 1, -3, -2,-25,-11,-17, 0,-13, -4, 10, 10, 2, + -5, 4, 0, 3, -3, -5,-10, -2, 13,-22, 0, 3,-11, -5, 7, -1 }, + { 12,-14,-29, 6, -1, 10, 7,-17,-12, 14, 3, 9, -9, 9, 7, 6, + -3,-13, 0, 5, 3, -1, -6, -1, 0, 2, 4,-12, -5, -1, 2, 11 }, + { 12,-15, -7, -2,-12, 17, 20,-16, -2,-12, -6, 15, -6, 12, 11, 9, + 7, -6, 7, -4,-19, 6, 2, 2, 3,-11,-10, -4, -5, -3, 3, 2 }, + { 11,-22, -6, 0, 8, 18, 3,-11, -4, -7,-15,-17,-12, 6, 16, 4, + -9, 4, -5, 3, 6,-16, 10, -7, -7, -3, 5, 0, 1,-15, -4, 5 }, + { 12,-22,-16, 5, -6, 8, 12, -4, -9,-17,-11, 3, 5, 8,-17, 0, + 11, -4,-13, -6, 2, -1, -1, 3, 3,-11,-12, -1, 1, 1, 12, -2 }, + { 8,-10,-33, -5, -3, -6, 1, -7, -8, -4, -6, -1, 5, -4, -6,-12, + -16, -8, 11, 8,-14, 7, 12, 11, 4,-14, -3, 6, -7, -5, -3, 3 }, + { 0, -8, -7, 2, -4, 24, 2, -9,-11, -3, -7, 11,-12, 17, 1, -1, + 3, -5, -7, 12, 4, 11, 0, 3, 2,-18, -3, 4, 7, -6, 3, 15 }, + { 10,-15,-16, -2, -4, -9, 7,-15, -6, 2,-16, 13, -8, 7, 19,-21, + -4,-12, -9, -3, -3, 6, 11, -3, -1,-19, 3, -7, -9, -4, 3, -6 }, + { -5,-10,-21, 0, -3, -7, 18,-21, 15, -5,-12, -4,-13, 2, 6, -9, + -9,-11, -4, 13, -3, 6, 4, -1, 7, -9, -4, 9, 5, 2, 6, 3 }, + { 15, -1,-27, -2, 10, 3, 7, -8, 9, -2, 7, 1, -2, -5, 18, 9, + -11,-17, -2, 7, -9, 11, 10, 0, -8, 6,-16, -3, 2, -7, 3, 11 }, + { 4, -9,-39, 19, 6,-13, 13, -5, -5,-15, -2, 9, 0, 4, 14, 6, + -10, -4, -5, 2, -4, -2, 5,-11, 3, 3, -2, -2, -7, 9, 7,-10 }, + { 5,-11, -8, 10, -2, 12, 16, 0, 12, -2, -6, 8, 14, 8, 7, 1, + 18,-30, 4, 10, -4, -6, 2,-11, 9,-10, -8, 5, 0, 0, -7, 6 }, + { -1,-16,-10, 11, 0, 13, 12, -4, -4, -5,-21, 12, 4, 13, 14, -7, + 6,-16,-13, 8, 2, 9, 15,-12, 1, -9,-22, 10, -9, 9, 9, -7 }, + { 4,-12,-27, 1, -2, 11, 15, 3, 14,-14, -9, 0, -9, 16, 22, 10, + 16,-10, 5, -5, -9, 1, 1, 6, 6, -4, 2,-17, -5, -6,-15, -1 }, + { 7,-12,-17, 1, -9, 5, 20, -7, 3, 23, -8, -8, -8, -1, 13, 17, + -7,-13, 4, -4, 7, 14, 8, 11, -3, -3, 4, 0, 4, 6, -1, -9 }, + { 7,-15,-15, -4, 10, 12, 3,-13, 6, 14, 9, -8,-15, 14, 23, -5, + -10, -5, 1, 15,-10, -7, 1, 9, 4,-13,-10, 10, 7, -3, 2, 3 }, + { 4,-10,-14, 0, 3, 4, 0, -9, -3, -4,-11, 2,-17, 8, 2, 15, + 6,-12,-12, 15, -5, 17, 18, 3, -3, -3, -4, -6, -8, 13, 4, 10 }, + { -2,-18,-26, 10, -4, 10, 13, 4, -4,-16, -7,-17, -3, 5, -4, 2, + -15,-10, -1, -8, -7, -3, 2, 2, 8,-10, -7, 2, 2, -4, 4, -1 }, + { 4,-19, -5, -1, -1, -6, 2, -8, 10,-16,-28, -6, 8, -1, 11, 28, + 2,-10, -4, 6, -6, 6, 11, 15, -4, -2, 7, 3, 7, -7, 4, 1 }, + { -3, -6,-10, -5, 13, 18, 10,-15, -5, -3,-13, 5, 1, 2, 18, -5, + -10,-10, -7, 4, 2, 1, 5, 4, 2, 5, 4, 8, -9,-17, 7, 7 }, + { 20,-12, -2, -4, 5, 14, 7,-11, -1,-16, -6, -4,-11, 17, 14, 0, + -8,-10, -8, 10, 3, 5, 10,-16, 3, -8,-14, 10, 3, 9, 0, 3 }, + { 12,-10,-36, 0, 7, 15, 2,-16, 2, -1, 0, -1, 5, 4, 5, -3, + 1,-10, 5, -1,-15, -3,-12, 12, 2, 5, -1, 5, 6, -3, -2, 2 }, + { 17,-15,-31, 23, -4, 15, -2, -3, 6, -7, -5, 1,-12, 4, 6, 8, + -10, 8, 3, 5, -4, 1, 5, 3, -1, -4, -3, 1, 10, -4, -2, -2 }, + { 6,-18, -5, 12, 10, 12, 14,-11, 15, 2, -9, -6, -5, -2, -9, 4, + -5,-28, -4, 14, 0,-16, 9, 14, -1, 3, -4, -4, 2, 1, 0, 4 }, + { -5,-14,-31, 8, 16, 7, 13,-13, 5, 6,-16, 10, -5, 2, -2, 2, + 14, -5, 8, -5, 7,-16, 6,-13, -5, 0, -5, 8, -3, -1, 4, 3 }, + { 1, -2, -1, 0, 6, 5, 2, -4, -3, -1, 0, 1, 4, 2, 43, 28, + -12,-35, -2, -2, -7, -1, 0, 2, -1, -2, -2, 1, -4, 0, -2, 3 }, + { 2, -9,-22, 12, 3, 3, -7, -4,-19,-22,-14, -4, -1, 21, 9, -3, + -15,-16,-13, 1,-11, 4, -9, 1, -7, -1, -1, 0, -2, 9,-13, -3 }, + { -1, -3,-23, 0, 2, 12, 3, -9, -4, 7, 3, 9,-10, 1, 27, 28, + 0, 9,-15, -2, -2, 1, 6, 8, -8, 7, -3, 20, 0, 0, -1, -6 }, + { -1, 11, 8, -2, 1, 5, -6, -1, 4, 2, -4, 0, -1, -5, 4, -6, + -10,-12, 19, 1, -7, 9, -8, -9,-16,-11, -2, 12, 14, 4, 4, 34 }, + { 17, 7, -6, 1, 4,-10, -5, 4,-11, 3,-18, 4, 14,-13, -3, 1, + 0, 0,-11, 0, 7,-17, -4, 4,-11, -6, -8, 18, 0, 0, 0, 26 }, + { -6, -7, -1, -1, 11, -8, 1, 3, 2, 11, -6, -6, 10, -3, 1, -3, + 7, 4,-12, -8, 0, -9, 8,-22, -5, 0, -6, 22, -2, 11,-13, 24 }, + { -3, 4, 0, 3, 9, 10, -1, 3, -9,-12, 1, -5, 18, 0, -3, 8, + 25, 15, -8, 2, 2, -2, 4, 8, 9, -1, -5, 10, -3, 1, -1, 23 }, + { -5, 2, -9, -1, -3, 0, 3, -1,-10, -4, 0,-13, 16, 9, -1,-14, + 2, 6, -2, -6, -5, -2, -7, 7, 5, 3, 11, -2,-14, 0, -9, 30 }, + { 4, 6, 6, 5, -3, -1, 4, 5, 10, 0, 5, -4, 7,-11, 14, 14, + 7, 34, -9, 0,-10, 22, -7, -1, 7, -9, 2, -8, 0, -7, -5, 29 }, + { -4, 3, -1, -4, -3, 5, 1, -4, 0, 2, 4, 2, 1, -1,-10, 1, + 6, -6, -4, 1, 4, -3, -3, -5, 0, 3, 7,-12, 0, -2,-10, 55 }, + { 5, 9, -1, 0, 4, 9,-21, -9, 4, 2, 6, -7, 11, -7, 1, -5, + 0, -4, 2, -3,-13, -8, 0, -9, -4, 2, 16, -2,-15, -7,-11, 31 }, + { 8, 2, -1, 0, 3, -5, -5, 5, 1, -1, -9, 1, 0, -6, -2, -1, + 5, 2, 0, 0, 12, 20,-19, 1, 8,-12,-11, 0, 6, -5, 2, 31 }, + { -1, -1, -2, 1, -1, 3, -9, -5, 8, -2, 5, -1, 0, -2, 4, -2, + -3,-12, 0, -2, 3, 0, 9, 4, -1, 21, -8, 3, -4, 9, -6, 30 }, + { -4, 0, -7, 17, 10,-12, -2,-10,-12, -3, 10, 0, 11, -4,-13, -3, + 5, 6, 10, 7, -8, 0, -7,-13, 1, 0, -2, 7,-12, 4, -3, 24 }, + {-13, 9, 4, -2, 2, -4,-14, -1, -3, -5,-10, 4, 13, -2, 5, 13, + 8, 3, -2, 1, 5, -6, 7,-18,-10, 1, -1, 5, 4, 1, 0, 25 }, + { -5, -1, 18, 12, 8, 8,-16, -1, 1, 1, 1, -4, -5, 3, 3, 4, + 4,-11,-12,-16, -6, 2, 12,-13, 0, 9, 7, 9, -9, 0,-10, 24 }, + { -4, 1, -3, 0, 2, -4, 4, 1, 5, 0, -3, 2, -3, -2, 2, -1, + 1, 4, -1, -2, -2, 1, -1, -1, -4, -1, -4, -2, -6, 6, 12, 69 }, + { 8, 5, 11, 0,-15, -4, 13, 6, 0, -4, 9, 1, -5, -3, 15, 0, + 1, 6, -5, 0, 1, 6, 5, 8, 0, 7, 1, -1, -4,-11, -9, 41 }, + { -4, -9, 32, -6, 0, 7, -4, 6, -6, 1, -6, -2, 4, -8, -5, -3, + -16, -1, -2, -6, 1, 15, 0, 21, 3, -3, -4, 3,-12, 16, 2, 27 }, + { -6, -5, 1, -9, -5, 3, 7, -3, 5, 5, 14, 13, 20, -7, -1, 12, + -1, 10,-11,-11, -7, -4,-14, 7,-14, 13, 22, 18, -1, 0, 14, 28 }, + { -8, 3, -2, 0, 5, 6, -1, -4, 1, 3, -7, 3, 1,-15, 4, -9, + 22,-10, -9, -4, 1, 8, -4, 9,-15, 2, -6, -4,-16, 12,-10, 23 }, + { 0, 0, 2, 0, -1, 3, -3, -1, 3, -5, 7, 1, 5, -5, -8, 1, + 13,-15, -5, -7, 12, -6, -2, 3, 10, -5, -8, 17, -5,-11,-14, 23 }, + { -7, -4, 6, -4, 5, -6, -5, 2, -4, 11, 9, -4, 2, -2, -4, 6, + 15, 3, -3, 18,-15, -2, -6, 3, 3,-20, 17, 11, -4, 2, 3, 29 }, + { 6, 1, -6, 2, 3, 0, 0, -3, 3, 3, -1, 3, -4, -6, -6, -7, + -3, -2, -7, -2, -4, 5, 3, -5,-20,-13, -4, 10,-14,-29, 14, 37 }, + { 3, 4, 3, -6, -4, 5, 0, 3, 2, 3, 0, -2, 4, 0, -3, -5, + -4, 4, -4, 4, 4, 3, 1, -4, -4, -9,-14, 20,-30, 3,-18, 33 }, + { 0, 2, 5, -2, -4, -2, -1, 2, -6, -3, -2, -2, 2, -5, -1, 4, + 3, 2, -3, 0, -1, -1,-10, -7, 2, -4,-18, 2,-37, -1, 12, 40 }, + { -7, 2, -1, 0, -2, 4, -8, 1, -4, 12, 7, 4, 15, -7, 1, -9, + 18, 0, 12,-17, -3, -1, 0, 0, 0, 2, -6, 0, -4, -3, -1, 26 }, + { -6, 4, 8, -5, -6, -2, 2, -1, 1, -1,-15, 8, 7, -1,-17, -4, + 1, 5, 6,-11, -6, 14, 17, -5,-15, 11, 8, 0, -3,-15, -6, 28 }, + { -1, 0, 0, 0, 1, 0, -1, 0, 1, 3, 2, -2, 3, -1, -1, 2, + 2, -1, -1, -7, 1, 2, -9, 0, -1, -4,-18, 7,-10, 49,-13, 32 }, + { -1, -3, 4, 1, 2, -5, 1, -7, -1, 5, -9, 4, 4, 25, 1, -1, + 2, -5, 2, -7, 17, -2, 10, -5, 0, 2,-15, 3, -9, 7, -9, 30 }, + { -5, -1, 0, 2, 1, -1, 2, 5,-33, 3, -5, 14, 11, 7, 5, -3, + 2, -8, -4, -2, -7, -6, 4, -8, -1, -8, 2, -2, -8, -1, -4, 27 }, + { -1, 0, -1, -2, 1, -1, -2, -1, 2, 0, 1, 2, 2, 4, 1, 3, + 4, 2, 1, -7, -4, 1, -3, -4,-35,-25, 17, 10, -3,-26, -7, 32 }, + { -5, 1, 6, -2, 6, 6, -9, 3, -1, -4, 5, -4, -2, -2, -9, 2, + -5, 2, 2, 4, 3, 5, -5,-16,-31,-12,-11, 2,-19, 20, -2, 21 }, + { -5, 2, 7, -7, -7, 5, -7, 2, 0, 0, -4, 3, -1, 0, -1, -2, + 0, -3, 5,-11, -8, -3, -7, -7, 28,-11, -7, 0,-16,-11, -4, 29 }, + { 2, 1, -3, -2, -1, 3, 4, 0, 1, 0, -1, -5, 4, -5,-12, 2, + -2, -5,-22, -2, -1, 11, 8, -7,-12, 0,-34, 6, -5, 11, -8, 19 }, + { -1, -3, 5, 11, 18, -2, -2, -5, -2, 4, -1, 8, 5, -6, 1, -1, + 2, 8, 4, -5, -8, -2, 5,-18, 7, 12, 7, 19,-18, 2, -6,-13 }, + { 9, 0, 0, 5, 4, 3, -6, 4, 1, -4, 5, -1, -4, 8, 8, 6, + -8, -6, 0, 6, -3, 3, 5, -3, 17, 31, 16, 10,-13, 0, -9,-19 }, + { 12,-10, 2, -2, -2, -1, -3, 6,-12, -5, -2, 14,-16, 4, 12, 12, + 17, 4, 7,-16, 7, -6, 11, 7, 7, 2,-25, 23,-24, 5, -7, -9 }, + { 10, 4, 13, 10, 10, 3, -6, 3, 3, 2, -1, -6, 8, 4, 10, 0, + 1, 2, -4, 2, -3, -8, 0, -1, 9, 9,-10, -3,-29, 1, -1,-27 }, + { 2, 2, 0, 7, 9, -2,-10, -1, -1, 1, -9, -5, 8, 4, 1, 2, + -10, 1, 13, 12, -3, 15, -9, 2, -7, 1,-10, 23,-20,-18, -9,-15 }, + { -3, -5, -1, 8, 0, -5, -1, 4, 7, -1, -7, 2, -8, -5, 11, 7, + -6, 3, -3, -9, 7, 9,-22, 1, 6, -4, 14, 27,-25,-14, 3, -5 }, + { 1, 3, 8, 4, 7, 6, 12,-17,-15, 1, -8,-10, 7,-14, -8, 6, + -2, -2,-11,-11, -7, 13, -2, -2, 4, 5, -5, 13,-23, -6,-17, -8 }, + { -5, 4,-14, -5, -4, -5, 6, 5, -8, -5, -2,-11, -7,-12, 3,-11, + 2, -6, 4,-10, -5, -7, 14, 5, 23, 11, 7, 12,-16, -6, -4,-16 }, + { 5, 6, 2, 5, -2, -5, -5, -6, -5,-19,-13, -1, -3,-13, 5, 0, + 6, -2, -2, -6, -7, -7, -1, -9, 4, 14, 17,-12,-27, 3, 0, -1 }, + { 7, -1, 9,-10, 8, 2, -7, -2, 5, 2, -3, -7, 3, 0, 6, 4, + 12, 5, 11, 14,-13, -1, 8, 1, 13, 9, 12, 12,-18,-14,-11,-16 }, + { -7, -5, -6, -5, 0, -1, -3, 2, 2, 1, 4, 9, 2, 3, 5, -2, + 2, 1, 8, 0, 3, 0, -2, 2, 1, 7, 29, 0,-36, -5, -9,-21 }, + { 14, -6, -9, 0, -1, -8, -8,-11, 2, 2, -9,-12, 12, -4, 5, 3, + -5, -9, 11, -1, -3, 12,-21, -3, 12, 5, 3, 11,-18,-15, 1, -2 }, + { -1, 3, -9, -3, 7, -7,-18, 2, 4, 12,-10, 2, 8, -3,-14, 13, + 17, -5, 5, -9, 13, -3, -7,-18, 17, -2, 5, 7,-20, -3, -6,-11 }, + { -3, 3, 3, -1, 1, -6, -5, 1, 5, -3,-14, -6, -5, -8, 14, -6, + 7, -1, 5, 1, 15, -1, -7, -4, 6,-11, 9, -2,-37, 16, -7, -3 }, + { -1, 0, 6, 1, -3, -9, 0, 11, -8, 2, -2, 0, 5, 2, 12,-10, + 10, 13, 2, 7, -6, 2,-10,-10, 21, -5, 5, 5,-12,-23, 3,-14 }, + { 6, 0, -2, 1, 0, 1, 0, -4, 1, 1, 8, -2, 2, -5, -2, 1, + 8, -4, -1, -1, 4, -1, 2, 6, 32, 1, -5,-20,-40, -4,-18,-14 }, + { 2, 2, -7, -2, 4, 4, -1, 2, 0, -2, -4, -7, 3, 5, 0, -5, + 1, 2, -6, 4, -1, -2, -1,-15, 8, 3, 9, 46, -7,-18, 6,-11 }, + { 5, 5, 16, 21, 3,-11, -4, 11,-12, 2, 4,-12, -1, 11, 8, 1, + -4, 11,-11,-21, 1, 1,-11, 3, 13, 1, 5, 12,-25, 1, -3, -2 }, + { 1, 6, -7, 4, 2, 3, 1, -5, 8, 9,-15, 3, -3,-14, 17, 4, + -8, 14, -2, -8, -4, 5, 8, -7, 8, 9, 7, 6,-29,-17, 8, 4 }, + { -7, -7, 4, 0, 13, 1, 0, 4, 4,-16,-10, -7, 5, 9,-15,-10, + -10, 8, -4, -1,-11, -1,-10,-15, 3, 3, 14, 10,-19, 2,-18,-12 }, + { -4, 0, 2, 0, 5, -2, -9, 0, 4, -4, 2, -1, -2, 2, -4, 9, + 2, -6, -4, -2, -1, -3, -3, -1, 2, 5, -1, 11,-24,-44, -9,-15 }, + { -1,-10, 6, 21, 11, 15, -7, 10,-14, -9, -8, -8, 4, 6, 19, 1, + -6, 1, -5,-17, -8,-10, 9, 5, 11, 18, -1, 10,-16, -7, -9, -8 }, + { 3, -5, 0, 0, -2, -2, -6, 4, -4, 1, -1, 0, 7, -3, 4, -4, + -7, 7, 17,-20, 6, 4, 1, -6,-12, 31, 13, 19,-14,-10, -7, -2 }, + { -2, 6,-10, 3, 9, 6,-14, 15, 2, -5, 2,-11, 9, -8, 4, 6, + 20,-15, -3, -3, -1, 32,-21, 6, 1, 9, 11, 17,-19, 6, -1, -3 }, + { 8, 10, -2, 0, -8,-16, 7, 7, 6, 10, 4,-14, 7, -6, 21, -7, + 10, 5, 5, 0, -7, 2, -6, 0, -7, 11, -9, 15,-20, -7,-11, 2 }, + { 0, -7, 5, 2, 0, -3, -6, -4, -2, -1, -4, -5,-13, -1, 27, -9, + -6,-11, -7, 1, 11, -4, -4,-14, -2, 11, 6, 10,-19, -6,-15, 2 }, + { 0, 7, -1, 2, -7,-15, -2, -3, 13, -5, -5, 12, 3, 0, 5, -5, + -22, 2, 7, 22, 13, 0, -1, 2, 3, 2, -7, 7,-27, -4, -4,-12 }, + { 11, 1,-16, 6,-15, 1, 3, 2, 0, 2, -3, 2, 5, -2, -5, 9, + 5, -3, 3, -2,-11, 3, 9, 6, 9, 3, -1, 12,-41, 8, -6, 9 }, + { 3, -7, 3, 2, 5, 5, 0, -1, 1, 3, -5, -2,-13, 7, -1, -2, + -2, -6, 4, -6, 0, 2, -2, 2, 4, 1, -4, 1,-47,-21, 7, -6 }, + { 3, 16, -7, 13, -4, -2, 10, -3, -1, 18,-13, 7,-13, -4, 8, 4, + 8, 9, -5, 13, 8, -5, 3, -6, 7, 18, -8, 10,-25, -3,-12,-12 }, + { 1, -1, -1, 0, 2, 5, -5, -3, 0, -5, -1, 0, -4, -8, -2, 3, + 2, -2,-17, -6, -4, 1, 33, -6,-20, -6, 8, 31,-26, -8, -1, -4 }, + { 3, -3, -3, 5, -3, -2, 1, 7, 0, 3, 6, 3, 6, -2, 9, 15, + -10, -3,-15, -5, -3, -4, -6,-30, 17, -8, -2, 2,-20, 0, -8, -2 }, + { -2, -1, -1, -1, 3, -5, -2, -3, 4, -2, 0, 5, 8, -3, 1, -4, + 1, 1, -3, 4, 4,-14, 3, 11, -5, 3, -3, 7, -3, 13, 23,-16 }, + { 2, -6, 1, -3, 5, 0, -6,-11, -7, -4, -1, 2, -7, -1, -1, 7, + 1, -2, 6, 12, -6, 8,-13, 17, 25,-23,-19, -7,-12, 9, 16,-17 }, + { 9, 4, 4, 4, -3, -1, 6, -2, -3, 0, 13, -4, -7, 14, 1, -7, + 0, -5, 3,-19, -3, 5, 3, 9, -1, 9,-13, 13,-17, 4, 21,-26 }, + { 0, -5, 0, 0, -4, -5, 2, -6, -4, 5, -7, 10, 0, 2, 0, -2, + -2, 0, 4, -6, 7, -2, 6, 5, -5, 2,-12, 1,-29, 29, 27, 12 }, + { 9,-10,-22, 6, -1, -1, 9,-14,-12, -2, 1, -1, 10,-11,-16, 0, + 3, 11, 13,-14, -9, -2, -1, 6, 4,-14, 0,-10, -2, 16, 17,-11 }, + { 2, 0, -1, -2, 4, 3, -6, -2, 1, -1, 1, 3, -4, 1, 3, -4, + -1, -1, 4, -1, 1, 0, 1, 6, -5, -7, 2, 1,-47, -3, 50,-17 }, + { 8, -4,-11, -7, 11, 11, 14, -7, 12, -7, 6, 2, 13, -6, -3, -2, + -14, 6, 6, 6, 0, 2, -1, 5,-20, 2, -1, 4, -5, 6, 21,-11 }, + { -2, -9, 3, 0, -6, 7, 8, -8, 1, -3, 4, 1, 5, -2, -3, -7, + 4, 7,-12, -9, -2, 10, -6, 13, 6, 5, 20, 2,-15, 9, 28, -7 }, + { 0, -5, -6, -6, -6, 1, -6, 6, -2, 4, 8, -3, 12, -1, -4, -2, + 6, 16,-14, 9,-14, -2, -8,-27, -3, 18, -1, -7, -3, 8, 23,-23 }, + { 1, 4, -9, -1, -5, 10, -2, 1,-11, 1, -9, 4, 7, 14, -9, -2, + -3, 2, -5, -1, -6,-10, -7, 11, 20, 2, 3,-19, 3, 15, 30, -9 }, + { 7, 2,-14, -4, 0, -2, 5, 2, 5, -2, 8, -3, -7, 6, 6,-11, + -14, 1, 10, -1, -7, -8, 1, 10, 3, -6,-15,-12,-17, 4, 30, -6 }, + { 4, 2, 1, -2, 3, 0, 1, 0, 2, 0, 1, 6, -7, 0, 3, 4, + 4, -4, -2, -5, -2, 2, -1, -2, 0, -2,-11, -7, -3, 42, 24,-14 }, + { 4, 1, 3, 2, 0, -2, -3, -2, 2, -1, 4, 11, -2, 2, 3, -4, + -5, 9, 2, -4, -9, 5, 8, -1, -7, 1, 24,-13,-28, 20, 15,-22 }, + { -3, 7, 6, 3, -2, -5,-10, -2, -2, -1, -6, -6, -2,-14,-16, -6, + -5, 0, 18, 0, 9, 1, 7,-13, -5, -6, -9, 11,-15, 9, 22,-11 }, + { 9, -2, 6, 5, 2, 9,-10, 1, 1, 5, -4, 12, 2, 2,-10, -7, + -4, -6, 7, 9, 6, 15, 6, 6,-10, 10, 5,-13, -5, 6, 24,-12 }, + { 1, 3, -3, -3, 8, 1, -6, 2, -5, -3, 7, 2, 14, 6, 9, -6, + -5, -4, 27, 7, -3, 8, -6, 3, -8, 8, 22, -5, -6, -2, 22,-17 }, + { -2, -2, 3, 10, 9, 9, 12,-15, -1,-11,-13, 3, -2, 1, -3,-11, + 7, 9, 16, -3,-10, -5, -5, 1, 8, -3, 9, 9, -5, 3, 31,-12 }, + { 7, -5, 10, -4, -8, 2, 16, -2, 10, 10, -3, -2, 3, -8, -3, 3, + -13, -6, 15, 20, -9, -3,-12, 1, -2,-16, 8, 8, -1, 16, 22, -5 }, + { 5, -3,-15, -2, 12, -8, 8, -5, 2, -8, 20,-18, 14, -4, 3, 3, + 7,-13,-16, 1,-10, 7, 16, 7, 4,-14, -4, -5, -9, 8, 23, -6 }, + { 5, -4, -5, -4, 1, 8, 4, -7, -5, 8, 10, 6, -6,-10, -2, 6, + 9,-17,-14, 11, 12, -3,-13, -7, 2, 18, 3,-25,-16, 18, 22, -5 }, + { 5, 6, -7,-20, -4, 2, 8, 4,-24, -4, 1, 4, -5, -2, 1,-10, + -2, 9, 3, -4, -3, -4, -4, -4, 10, 10, 3, 0, -6, 25, 21,-11 }, + { 0, 7, -1, 14, -6, -4,-10, 5, 4, 4, 4, -5, 3, 4, -1, -7, + 8,-19, 0, 6, 2, 3,-18, -3, -6, 2, 8, 14,-26, 22, 27,-13 }, + { -2, -6, 7, -5, 12, -7, 8, -1, 3, -2, 4, 1, 8, -2, 0, 14, + 6, -5, 6, -4, -7, 7,-21, 8, 1, 8, -9, -4, -3, 11, 25,-13 }, + { 4, 4, -1, -6, 4, 9, -8, 1, -3,-10, -2, 0, 15, -9,-16, 11, + 1, 1, 6, 3, -9, -5, 16, 26, 1,-14, 1, -3,-14, 7, 15, -9 }, + {-12, -2, -9,-13, 2, 6, 14, 0, 1, 0, -1,-13, 0, 10, -1, 6, + 9, -7, 8, 8, 19, 6, -1, 9, 10, -4, 1, -7,-22, -2, 29, -7 }, + { 2, 4, 13,-12, -8, -4, -5, 13, 12, -5, -3, -3, -4, 1, -1, 10, + 15, -6, -1,-11,-30, 4, 15, -1, 9, -7, 0, -2, -7, 10, 25,-16 }, + { 7,-15, -7, -7, -1, -5, -5,-11,-20, 10, 3,-10, -3, 5, 20, -4, + 0, -2, -2, 17, 2, 0, -3, 3, 6, 5, -1,-12, -3, 15, 22,-16 }, + { 4, -1, 3, 4, -5, 0, -1, -5,-24,-29, 4, -9, 1, -3, 0, 0, + 0, -4, 7, -4, -4, -4, 3, 1, -6, 5, -3, -5,-10, 3, 25,-10 }, + { -2, -1, -1, 4, 4, -1, 2, 0, -4, -4, 2, -1, -3, -1, -2, -2, + 1, -3, -5, -1, 2, -3, -4, -4, -3, 5, -9, 1,-11, 7, 46,-46 }, + { 0, -9, 3, 4, 4, 3, -5, -6, 5, -4, 4, -2, 1, 7, -4,-10, + 13, 1, 3, -6, 4, -4, 7, 2,-19,-25, -3,-16,-12, 16, 20, -1 }, + { 18, 6, 4,-12, 0,-14, 9, -6, -1, -4, -5, 2, 1, 12, 4, 2, + 7, 0, 2, 5,-11, -5, -2, 2, -4, 10, 0, -9, -7, 9, 25, -8 }, + { 5, 0, -6, 5, 6, 3, 3,-10, -5, 1, -1, 4, 3,-11, -8, 5, + 4, -5, 5, -5, -7, -5, 11, 5, 20, -8,-16, 21, -4, 27, 23, -5 } +}; + + +/* FIR filter coefficients, they can be cut on half and maybe use float instead of double*/ + +DECLARE_ALIGNED(16, static const float, fir_32bands_perfect)[] = +{ ++1.135985195E-010, ++7.018770981E-011, +-1.608403011E-008, +-5.083275667E-008, +-1.543309907E-007, +-3.961981463E-007, +-7.342250683E-007, +-3.970030775E-007, +-4.741137047E-007, +-6.022448247E-007, +-6.628192182E-007, +-6.982898526E-007, +-7.020648809E-007, +-6.767839409E-007, +-6.262345096E-007, +-5.564140224E-007, ++7.003467317E-007, ++8.419976893E-007, ++9.742954035E-007, ++1.085227950E-006, ++1.162929266E-006, ++1.194632091E-006, ++1.179182050E-006, ++1.033426656E-006, ++9.451737242E-007, ++1.975324267E-006, ++1.190443072E-006, ++5.234479659E-007, ++2.014677420E-007, ++7.834767501E-008, +-6.702406963E-010, +-1.613285505E-009, +-2.682709610E-009, +-3.399493131E-009, ++1.314406006E-008, ++7.506701927E-009, ++2.788728892E-008, ++1.444918922E-007, ++3.132386439E-007, ++1.399798180E-006, ++2.032118118E-006, ++2.715013807E-006, ++3.453840463E-006, ++4.195037945E-006, ++4.896494374E-006, ++5.516381407E-006, ++6.015239251E-006, ++6.361419310E-006, ++8.006985809E-006, ++8.087732567E-006, ++7.941360309E-006, ++7.568834008E-006, ++6.986399967E-006, ++6.225028756E-006, ++5.315936960E-006, ++4.429412002E-006, ++3.332600045E-006, ++8.427224429E-007, ++4.341498823E-007, ++9.458596395E-008, ++2.975164826E-008, ++6.402664354E-008, +-3.246264413E-008, +-3.809887872E-008, ++8.434094667E-008, ++6.437721822E-008, ++1.189317118E-006, ++2.497214155E-006, ++3.617151151E-006, ++3.157242645E-006, ++2.319611212E-006, ++7.869333785E-006, ++9.826449968E-006, ++1.177108606E-005, ++1.379448349E-005, ++1.571428584E-005, ++1.743183020E-005, ++1.884208177E-005, ++1.987093310E-005, ++2.042970118E-005, +-3.144468428E-005, +-3.334947178E-005, +-3.460439257E-005, +-3.515914432E-005, +-3.495384954E-005, +-3.397853652E-005, +-3.225446198E-005, +-2.978993689E-005, +-2.677291741E-005, +-1.806914770E-005, +-1.776598037E-005, +-1.661818715E-005, +-1.207003334E-005, +-6.993315310E-006, +-5.633860383E-007, +-9.984935332E-007, +-1.470520488E-006, +-1.853591357E-006, ++7.198007665E-007, ++3.086857760E-006, ++6.084746474E-006, ++9.561075785E-006, ++1.309637537E-005, ++2.263354872E-005, ++2.847247197E-005, ++3.415624451E-005, ++3.946387005E-005, ++4.425736552E-005, ++4.839275425E-005, ++5.176846025E-005, ++5.429694284E-005, ++5.595519906E-005, ++4.916387297E-006, ++9.299508747E-006, ++1.356193479E-005, ++1.751866148E-005, ++2.093936746E-005, ++2.362549276E-005, ++2.537086584E-005, ++2.618136386E-005, ++2.554462844E-005, ++3.018750249E-005, ++2.570833203E-005, ++1.985177369E-005, ++1.191342653E-005, ++2.525620175E-006, +-1.521241393E-005, +-1.617751332E-005, ++1.992636317E-005, ++1.774702469E-005, ++4.624524081E-005, ++5.610509834E-005, ++6.568001118E-005, ++7.513730816E-005, ++8.413690375E-005, ++8.757545584E-005, ++9.517164290E-005, ++1.020687996E-004, ++1.084438481E-004, ++1.140582463E-004, ++1.187910311E-004, ++1.224978914E-004, ++1.250260248E-004, ++1.262027217E-004, ++1.226499153E-004, ++1.213575742E-004, ++1.180980107E-004, ++1.126275165E-004, ++1.047207043E-004, ++9.417100227E-005, ++8.078388782E-005, ++6.447290798E-005, ++4.491530854E-005, ++2.470704203E-005, +-1.714242217E-006, +-3.193307566E-005, +-6.541742187E-005, +-1.024175072E-004, +-1.312203676E-004, +-1.774113771E-004, +-2.233728592E-004, +-2.682086197E-004, +-3.347633174E-004, +-3.906481725E-004, +-4.490280990E-004, +-5.099929986E-004, +-5.729619297E-004, +-6.358824321E-004, +-7.021900383E-004, +-7.698345580E-004, +-8.385353722E-004, +-9.078957955E-004, +-9.775133803E-004, +-1.046945457E-003, +-1.115717343E-003, +-1.183370827E-003, +-1.252829796E-003, +-1.316190348E-003, +-1.376571832E-003, +-1.433344092E-003, +-1.485876855E-003, +-1.533520175E-003, +-1.575609902E-003, +-1.611457788E-003, +-1.640390139E-003, +-1.661288203E-003, +-1.674512983E-003, +-1.678415807E-003, +-1.672798418E-003, +-1.656501088E-003, +-1.633993932E-003, +-1.593449386E-003, ++1.542080659E-003, ++1.479332102E-003, ++1.395521569E-003, ++1.303116791E-003, ++1.196175464E-003, ++1.073757303E-003, ++9.358961834E-004, ++7.817269652E-004, ++6.114174030E-004, ++4.244441516E-004, ++2.206075296E-004, +-2.719412748E-007, +-2.382978710E-004, +-4.935106263E-004, +-7.658848190E-004, +-1.055365428E-003, +-1.361547387E-003, +-1.684492454E-003, +-2.023874084E-003, +-2.379294252E-003, +-2.750317100E-003, +-3.136433195E-003, +-3.537061159E-003, +-3.951539751E-003, +-4.379155114E-003, +-4.819062538E-003, +-5.270531867E-003, +-5.732392892E-003, +-6.203945260E-003, +-6.683901884E-003, +-7.170005701E-003, +-7.664063945E-003, +-8.162760176E-003, +-8.665001951E-003, +-9.170533158E-003, +-9.676489048E-003, +-1.018219907E-002, +-1.068630442E-002, +-1.118756086E-002, +-1.168460958E-002, +-1.217562053E-002, +-1.265939046E-002, +-1.313448418E-002, +-1.359948888E-002, +-1.405300573E-002, +-1.449365262E-002, +-1.492007636E-002, +-1.533095632E-002, +-1.572482102E-002, +-1.610082202E-002, +-1.645756140E-002, +-1.679391414E-002, +-1.710879989E-002, +-1.740120351E-002, +-1.767017506E-002, +-1.791484281E-002, +-1.813439466E-002, +-1.832821220E-002, +-1.849545911E-002, +-1.863567345E-002, +-1.874836907E-002, +-1.883326657E-002, +-1.889026538E-002, +-1.891860925E-002, ++1.891860925E-002, ++1.889026538E-002, ++1.883326657E-002, ++1.874836907E-002, ++1.863567345E-002, ++1.849545911E-002, ++1.832821220E-002, ++1.813439466E-002, ++1.791484281E-002, ++1.767017506E-002, ++1.740120351E-002, ++1.710879989E-002, ++1.679391414E-002, ++1.645756140E-002, ++1.610082202E-002, ++1.572482102E-002, ++1.533095632E-002, ++1.492007636E-002, ++1.449365262E-002, ++1.405300573E-002, ++1.359948888E-002, ++1.313448418E-002, ++1.265939046E-002, ++1.217562053E-002, ++1.168460958E-002, ++1.118756086E-002, ++1.068630442E-002, ++1.018219907E-002, ++9.676489048E-003, ++9.170533158E-003, ++8.665001951E-003, ++8.162760176E-003, ++7.664063945E-003, ++7.170005701E-003, ++6.683901884E-003, ++6.203945260E-003, ++5.732392892E-003, ++5.270531867E-003, ++4.819062538E-003, ++4.379155114E-003, ++3.951539751E-003, ++3.537061159E-003, ++3.136433195E-003, ++2.750317100E-003, ++2.379294252E-003, ++2.023874084E-003, ++1.684492454E-003, ++1.361547387E-003, ++1.055365428E-003, ++7.658848190E-004, ++4.935106263E-004, ++2.382978710E-004, ++2.719412748E-007, +-2.206075296E-004, +-4.244441516E-004, +-6.114174030E-004, +-7.817269652E-004, +-9.358961834E-004, +-1.073757303E-003, +-1.196175464E-003, +-1.303116791E-003, +-1.395521569E-003, +-1.479332102E-003, +-1.542080659E-003, ++1.593449386E-003, ++1.633993932E-003, ++1.656501088E-003, ++1.672798418E-003, ++1.678415807E-003, ++1.674512983E-003, ++1.661288203E-003, ++1.640390139E-003, ++1.611457788E-003, ++1.575609902E-003, ++1.533520175E-003, ++1.485876855E-003, ++1.433344092E-003, ++1.376571832E-003, ++1.316190348E-003, ++1.252829796E-003, ++1.183370827E-003, ++1.115717343E-003, ++1.046945457E-003, ++9.775133803E-004, ++9.078957955E-004, ++8.385353722E-004, ++7.698345580E-004, ++7.021900383E-004, ++6.358824321E-004, ++5.729619297E-004, ++5.099929986E-004, ++4.490280990E-004, ++3.906481725E-004, ++3.347633174E-004, ++2.682086197E-004, ++2.233728592E-004, ++1.774113771E-004, ++1.312203676E-004, ++1.024175072E-004, ++6.541742187E-005, ++3.193307566E-005, ++1.714242217E-006, +-2.470704203E-005, +-4.491530854E-005, +-6.447290798E-005, +-8.078388782E-005, +-9.417100227E-005, +-1.047207043E-004, +-1.126275165E-004, +-1.180980107E-004, +-1.213575742E-004, +-1.226499153E-004, +-1.262027217E-004, +-1.250260248E-004, +-1.224978914E-004, +-1.187910311E-004, +-1.140582463E-004, +-1.084438481E-004, +-1.020687996E-004, +-9.517164290E-005, +-8.757545584E-005, +-8.413690375E-005, +-7.513730816E-005, +-6.568001118E-005, +-5.610509834E-005, +-4.624524081E-005, +-1.774702469E-005, +-1.992636317E-005, ++1.617751332E-005, ++1.521241393E-005, +-2.525620175E-006, +-1.191342653E-005, +-1.985177369E-005, +-2.570833203E-005, +-3.018750249E-005, +-2.554462844E-005, +-2.618136386E-005, +-2.537086584E-005, +-2.362549276E-005, +-2.093936746E-005, +-1.751866148E-005, +-1.356193479E-005, +-9.299508747E-006, +-4.916387297E-006, +-5.595519906E-005, +-5.429694284E-005, +-5.176846025E-005, +-4.839275425E-005, +-4.425736552E-005, +-3.946387005E-005, +-3.415624451E-005, +-2.847247197E-005, +-2.263354872E-005, +-1.309637537E-005, +-9.561075785E-006, +-6.084746474E-006, +-3.086857760E-006, +-7.198007665E-007, ++1.853591357E-006, ++1.470520488E-006, ++9.984935332E-007, ++5.633860383E-007, ++6.993315310E-006, ++1.207003334E-005, ++1.661818715E-005, ++1.776598037E-005, ++1.806914770E-005, ++2.677291741E-005, ++2.978993689E-005, ++3.225446198E-005, ++3.397853652E-005, ++3.495384954E-005, ++3.515914432E-005, ++3.460439257E-005, ++3.334947178E-005, ++3.144468428E-005, +-2.042970118E-005, +-1.987093310E-005, +-1.884208177E-005, +-1.743183020E-005, +-1.571428584E-005, +-1.379448349E-005, +-1.177108606E-005, +-9.826449968E-006, +-7.869333785E-006, +-2.319611212E-006, +-3.157242645E-006, +-3.617151151E-006, +-2.497214155E-006, +-1.189317118E-006, +-6.437721822E-008, +-8.434094667E-008, ++3.809887872E-008, ++3.246264413E-008, +-6.402664354E-008, +-2.975164826E-008, +-9.458596395E-008, +-4.341498823E-007, +-8.427224429E-007, +-3.332600045E-006, +-4.429412002E-006, +-5.315936960E-006, +-6.225028756E-006, +-6.986399967E-006, +-7.568834008E-006, +-7.941360309E-006, +-8.087732567E-006, +-8.006985809E-006, +-6.361419310E-006, +-6.015239251E-006, +-5.516381407E-006, +-4.896494374E-006, +-4.195037945E-006, +-3.453840463E-006, +-2.715013807E-006, +-2.032118118E-006, +-1.399798180E-006, +-3.132386439E-007, +-1.444918922E-007, +-2.788728892E-008, +-7.506701927E-009, +-1.314406006E-008, ++3.399493131E-009, ++2.682709610E-009, ++1.613285505E-009, ++6.702406963E-010, +-7.834767501E-008, +-2.014677420E-007, +-5.234479659E-007, +-1.190443072E-006, +-1.975324267E-006, +-9.451737242E-007, +-1.033426656E-006, +-1.179182050E-006, +-1.194632091E-006, +-1.162929266E-006, +-1.085227950E-006, +-9.742954035E-007, +-8.419976893E-007, +-7.003467317E-007, ++5.564140224E-007, ++6.262345096E-007, ++6.767839409E-007, ++7.020648809E-007, ++6.982898526E-007, ++6.628192182E-007, ++6.022448247E-007, ++4.741137047E-007, ++3.970030775E-007, ++7.342250683E-007, ++3.961981463E-007, ++1.543309907E-007, ++5.083275667E-008, ++1.608403011E-008, +-7.018770981E-011, +-1.135985195E-010 +}; + +DECLARE_ALIGNED(16, static const float, fir_32bands_nonperfect)[] = +{ +-1.390191784E-007, +-1.693738625E-007, +-2.030677564E-007, +-2.404238444E-007, +-2.818143514E-007, +-3.276689142E-007, +-3.784752209E-007, +-4.347855338E-007, +-4.972276315E-007, +-5.665120852E-007, +-6.434325428E-007, +-7.288739425E-007, +-8.238164355E-007, +-9.293416952E-007, +-1.046637067E-006, +-1.176999604E-006, +-1.321840614E-006, +-1.482681114E-006, +-1.661159786E-006, +-1.859034001E-006, +-2.078171747E-006, +-2.320550948E-006, +-2.588257530E-006, +-2.883470643E-006, +-3.208459020E-006, +-3.565570978E-006, +-3.957220997E-006, +-4.385879038E-006, +-4.854050530E-006, +-5.364252502E-006, +-5.918994248E-006, +-6.520755960E-006, +-7.171964626E-006, +-7.874960829E-006, +-8.631964192E-006, +-9.445050637E-006, +-1.031611009E-005, +-1.124680875E-005, +-1.223855270E-005, +-1.329243969E-005, +-1.440921824E-005, +-1.558924305E-005, +-1.683242772E-005, +-1.813820381E-005, +-1.950545993E-005, +-2.093250441E-005, +-2.241701623E-005, +-2.395598858E-005, +-2.554569073E-005, +-2.718161704E-005, +-2.885844333E-005, +-3.056998685E-005, +-3.230916263E-005, +-3.406793985E-005, +-3.583733633E-005, +-3.760734762E-005, +-3.936696885E-005, +-4.110412556E-005, +-4.280570283E-005, +-4.445751256E-005, +-4.604430433E-005, +-4.754976908E-005, +-4.895655002E-005, +-5.024627535E-005, ++5.139957648E-005, ++5.239612074E-005, ++5.321469871E-005, ++5.383323878E-005, ++5.422891263E-005, ++5.437819709E-005, ++5.425697600E-005, ++5.384063843E-005, ++5.310418419E-005, ++5.202236207E-005, ++5.056979353E-005, ++4.872112549E-005, ++4.645117951E-005, ++4.373511547E-005, ++4.054862075E-005, ++3.686808850E-005, ++3.267079956E-005, ++2.793515523E-005, ++2.264085742E-005, ++1.676913780E-005, ++1.030297699E-005, ++3.227306706E-006, +-4.470633485E-006, +-1.280130618E-005, +-2.177240640E-005, +-3.138873581E-005, +-4.165195787E-005, +-5.256036457E-005, +-6.410864444E-005, +-7.628766616E-005, +-8.908427117E-005, +-1.024810626E-004, +-1.164562127E-004, +-1.309833024E-004, +-1.460311323E-004, +-1.615635992E-004, +-1.775395358E-004, +-1.939126523E-004, +-2.106313768E-004, +-2.276388550E-004, +-2.448728774E-004, +-2.622658503E-004, +-2.797449124E-004, +-2.972317743E-004, +-3.146430245E-004, +-3.318900708E-004, +-3.488793736E-004, +-3.655125911E-004, +-3.816867538E-004, +-3.972945851E-004, +-4.122247046E-004, +-4.263620067E-004, +-4.395879805E-004, +-4.517810594E-004, +-4.628172028E-004, +-4.725702747E-004, +-4.809123348E-004, +-4.877146275E-004, +-4.928477574E-004, +-4.961824161E-004, +-4.975944757E-004, +-4.969481961E-004, +-4.941228544E-004, +-4.889960401E-004, ++4.814492422E-004, ++4.713678791E-004, ++4.586426076E-004, ++4.431701091E-004, ++4.248536134E-004, ++4.036037717E-004, ++3.793396754E-004, ++3.519894381E-004, ++3.214911267E-004, ++2.877934603E-004, ++2.508567995E-004, ++2.106537577E-004, ++1.671699720E-004, ++1.204049113E-004, ++7.037253090E-005, ++1.710198012E-005, +-3.936182839E-005, +-9.895755647E-005, +-1.616069785E-004, +-2.272142592E-004, +-2.956659591E-004, +-3.668301215E-004, +-4.405563814E-004, +-5.166754709E-004, +-5.949990009E-004, +-6.753197522E-004, +-7.574109477E-004, +-8.410271257E-004, +-9.259034996E-004, +-1.011756598E-003, +-1.098284614E-003, +-1.185167348E-003, +-1.272067428E-003, +-1.358630019E-003, +-1.444484224E-003, +-1.529243193E-003, +-1.612505526E-003, +-1.693855622E-003, +-1.772865304E-003, +-1.849094522E-003, +-1.922092517E-003, +-1.991399564E-003, +-2.056547208E-003, +-2.117061289E-003, +-2.172462177E-003, +-2.222266514E-003, +-2.265989315E-003, +-2.303145360E-003, +-2.333251061E-003, +-2.355825622E-003, +-2.370394068E-003, +-2.376487479E-003, +-2.373647178E-003, +-2.361423569E-003, +-2.339380793E-003, +-2.307097195E-003, +-2.264167881E-003, +-2.210205887E-003, +-2.144844970E-003, +-2.067740774E-003, +-1.978572691E-003, +-1.877046190E-003, +-1.762894331E-003, +-1.635878929E-003, ++1.495792647E-003, ++1.342460280E-003, ++1.175740734E-003, ++9.955273708E-004, ++8.017504588E-004, ++5.943773431E-004, ++3.734139318E-004, ++1.389056415E-004, +-1.090620208E-004, +-3.703625989E-004, +-6.448282511E-004, +-9.322494152E-004, +-1.232374110E-003, +-1.544908970E-003, +-1.869517611E-003, +-2.205822384E-003, +-2.553403843E-003, +-2.911801683E-003, +-3.280514618E-003, +-3.659002949E-003, +-4.046686925E-003, +-4.442950245E-003, +-4.847140983E-003, +-5.258570891E-003, +-5.676518660E-003, +-6.100233644E-003, +-6.528933067E-003, +-6.961807609E-003, +-7.398022339E-003, +-7.836719044E-003, +-8.277016692E-003, +-8.718019351E-003, +-9.158811532E-003, +-9.598465636E-003, +-1.003604382E-002, +-1.047059800E-002, +-1.090117730E-002, +-1.132682897E-002, +-1.174659748E-002, +-1.215953380E-002, +-1.256469358E-002, +-1.296114177E-002, +-1.334795821E-002, +-1.372423489E-002, +-1.408908330E-002, +-1.444163360E-002, +-1.478104480E-002, +-1.510649733E-002, +-1.541720331E-002, +-1.571240649E-002, +-1.599138230E-002, +-1.625344716E-002, +-1.649795473E-002, +-1.672429405E-002, +-1.693190821E-002, +-1.712027565E-002, +-1.728892699E-002, +-1.743743755E-002, +-1.756543480E-002, +-1.767260395E-002, +-1.775865816E-002, +-1.782339066E-002, +-1.786663756E-002, +-1.788828894E-002, ++1.788828894E-002, ++1.786663756E-002, ++1.782339066E-002, ++1.775865816E-002, ++1.767260395E-002, ++1.756543480E-002, ++1.743743755E-002, ++1.728892699E-002, ++1.712027565E-002, ++1.693190821E-002, ++1.672429405E-002, ++1.649795473E-002, ++1.625344716E-002, ++1.599138230E-002, ++1.571240649E-002, ++1.541720331E-002, ++1.510649733E-002, ++1.478104480E-002, ++1.444163360E-002, ++1.408908330E-002, ++1.372423489E-002, ++1.334795821E-002, ++1.296114177E-002, ++1.256469358E-002, ++1.215953380E-002, ++1.174659748E-002, ++1.132682897E-002, ++1.090117730E-002, ++1.047059800E-002, ++1.003604382E-002, ++9.598465636E-003, ++9.158811532E-003, ++8.718019351E-003, ++8.277016692E-003, ++7.836719044E-003, ++7.398022339E-003, ++6.961807609E-003, ++6.528933067E-003, ++6.100233644E-003, ++5.676518660E-003, ++5.258570891E-003, ++4.847140983E-003, ++4.442950245E-003, ++4.046686925E-003, ++3.659002949E-003, ++3.280514618E-003, ++2.911801683E-003, ++2.553403843E-003, ++2.205822384E-003, ++1.869517611E-003, ++1.544908970E-003, ++1.232374110E-003, ++9.322494152E-004, ++6.448282511E-004, ++3.703625989E-004, ++1.090620208E-004, +-1.389056415E-004, +-3.734139318E-004, +-5.943773431E-004, +-8.017504588E-004, +-9.955273708E-004, +-1.175740734E-003, +-1.342460280E-003, +-1.495792647E-003, ++1.635878929E-003, ++1.762894331E-003, ++1.877046190E-003, ++1.978572691E-003, ++2.067740774E-003, ++2.144844970E-003, ++2.210205887E-003, ++2.264167881E-003, ++2.307097195E-003, ++2.339380793E-003, ++2.361423569E-003, ++2.373647178E-003, ++2.376487479E-003, ++2.370394068E-003, ++2.355825622E-003, ++2.333251061E-003, ++2.303145360E-003, ++2.265989315E-003, ++2.222266514E-003, ++2.172462177E-003, ++2.117061289E-003, ++2.056547208E-003, ++1.991399564E-003, ++1.922092517E-003, ++1.849094522E-003, ++1.772865304E-003, ++1.693855622E-003, ++1.612505526E-003, ++1.529243193E-003, ++1.444484224E-003, ++1.358630019E-003, ++1.272067428E-003, ++1.185167348E-003, ++1.098284614E-003, ++1.011756598E-003, ++9.259034996E-004, ++8.410271257E-004, ++7.574109477E-004, ++6.753197522E-004, ++5.949990009E-004, ++5.166754709E-004, ++4.405563814E-004, ++3.668301215E-004, ++2.956659591E-004, ++2.272142592E-004, ++1.616069785E-004, ++9.895755647E-005, ++3.936182839E-005, +-1.710198012E-005, +-7.037253090E-005, +-1.204049113E-004, +-1.671699720E-004, +-2.106537577E-004, +-2.508567995E-004, +-2.877934603E-004, +-3.214911267E-004, +-3.519894381E-004, +-3.793396754E-004, +-4.036037717E-004, +-4.248536134E-004, +-4.431701091E-004, +-4.586426076E-004, +-4.713678791E-004, +-4.814492422E-004, ++4.889960401E-004, ++4.941228544E-004, ++4.969481961E-004, ++4.975944757E-004, ++4.961824161E-004, ++4.928477574E-004, ++4.877146275E-004, ++4.809123348E-004, ++4.725702747E-004, ++4.628172028E-004, ++4.517810594E-004, ++4.395879805E-004, ++4.263620067E-004, ++4.122247046E-004, ++3.972945851E-004, ++3.816867538E-004, ++3.655125911E-004, ++3.488793736E-004, ++3.318900708E-004, ++3.146430245E-004, ++2.972317743E-004, ++2.797449124E-004, ++2.622658503E-004, ++2.448728774E-004, ++2.276388550E-004, ++2.106313768E-004, ++1.939126523E-004, ++1.775395358E-004, ++1.615635992E-004, ++1.460311323E-004, ++1.309833024E-004, ++1.164562127E-004, ++1.024810626E-004, ++8.908427117E-005, ++7.628766616E-005, ++6.410864444E-005, ++5.256036457E-005, ++4.165195787E-005, ++3.138873581E-005, ++2.177240640E-005, ++1.280130618E-005, ++4.470633485E-006, +-3.227306706E-006, +-1.030297699E-005, +-1.676913780E-005, +-2.264085742E-005, +-2.793515523E-005, +-3.267079956E-005, +-3.686808850E-005, +-4.054862075E-005, +-4.373511547E-005, +-4.645117951E-005, +-4.872112549E-005, +-5.056979353E-005, +-5.202236207E-005, +-5.310418419E-005, +-5.384063843E-005, +-5.425697600E-005, +-5.437819709E-005, +-5.422891263E-005, +-5.383323878E-005, +-5.321469871E-005, +-5.239612074E-005, +-5.139957648E-005, ++5.024627535E-005, ++4.895655002E-005, ++4.754976908E-005, ++4.604430433E-005, ++4.445751256E-005, ++4.280570283E-005, ++4.110412556E-005, ++3.936696885E-005, ++3.760734762E-005, ++3.583733633E-005, ++3.406793985E-005, ++3.230916263E-005, ++3.056998685E-005, ++2.885844333E-005, ++2.718161704E-005, ++2.554569073E-005, ++2.395598858E-005, ++2.241701623E-005, ++2.093250441E-005, ++1.950545993E-005, ++1.813820381E-005, ++1.683242772E-005, ++1.558924305E-005, ++1.440921824E-005, ++1.329243969E-005, ++1.223855270E-005, ++1.124680875E-005, ++1.031611009E-005, ++9.445050637E-006, ++8.631964192E-006, ++7.874960829E-006, ++7.171964626E-006, ++6.520755960E-006, ++5.918994248E-006, ++5.364252502E-006, ++4.854050530E-006, ++4.385879038E-006, ++3.957220997E-006, ++3.565570978E-006, ++3.208459020E-006, ++2.883470643E-006, ++2.588257530E-006, ++2.320550948E-006, ++2.078171747E-006, ++1.859034001E-006, ++1.661159786E-006, ++1.482681114E-006, ++1.321840614E-006, ++1.176999604E-006, ++1.046637067E-006, ++9.293416952E-007, ++8.238164355E-007, ++7.288739425E-007, ++6.434325428E-007, ++5.665120852E-007, ++4.972276315E-007, ++4.347855338E-007, ++3.784752209E-007, ++3.276689142E-007, ++2.818143514E-007, ++2.404238444E-007, ++2.030677564E-007, ++1.693738625E-007, ++1.390191784E-007 +}; + +DECLARE_ALIGNED(16, static const float, lfe_fir_64)[] = +{ + 2.658434386830777e-4, 9.029330685734748e-3, + 7.939263433218002e-2, 2.425158768892288e-1, + 3.430179357528686e-1, 2.398228943347931e-1, + 7.746443897485733e-2, 8.622321300208569e-3, + 8.179365249816328e-5, 9.450953453779220e-3, + 8.134882897138596e-2, 2.451938837766648e-1, + 3.429597318172455e-1, 2.371159791946411e-1, + 7.556436210870743e-2, 8.229630999267101e-3, + 9.439323912374676e-5, 9.887560270726680e-3, + 8.333285897970200e-2, 2.478559017181396e-1, + 3.428434133529663e-1, 2.343961596488952e-1, + 7.369252294301987e-2, 7.850865833461285e-3, + 1.082170274457894e-4, 1.033949479460716e-2, + 8.534456789493561e-2, 2.505008876323700e-1, + 3.426689505577088e-1, 2.316644787788391e-1, + 7.184901088476181e-2, 7.485736627131701e-3, + 1.233371440321207e-4, 1.080708485096693e-2, + 8.738376945257187e-2, 2.531278133392334e-1, + 3.424364924430847e-1, 2.289219647645950e-1, + 7.003392279148102e-2, 7.133882027119398e-3, + 1.397485757479444e-4, 1.129068247973919e-2, + 8.945026248693466e-2, 2.557355761528015e-1, + 3.421461284160614e-1, 2.261696159839630e-1, + 6.824731826782227e-2, 6.794991903007030e-3, + 1.575958012836054e-4, 1.179065089672804e-2, + 9.154383838176728e-2, 2.583232223987580e-1, + 3.417979776859284e-1, 2.234084606170654e-1, + 6.648923456668854e-2, 6.468691397458315e-3, + 1.769922382663936e-4, 1.230732165277004e-2, + 9.366425126791000e-2, 2.608896791934967e-1, + 3.413922190666198e-1, 2.206395119428635e-1, + 6.475970894098282e-2, 6.154712289571762e-3, + 1.981738605536520e-4, 1.284105982631445e-2, + 9.581124037504196e-2, 2.634339034557342e-1, + 3.409290313720703e-1, 2.178637981414795e-1, + 6.305878609418869e-2, 5.852684378623962e-3, + 2.211847313446924e-4, 1.339218579232693e-2, + 9.798453748226166e-2, 2.659549415111542e-1, + 3.404086530208588e-1, 2.150822728872299e-1, + 6.138643622398376e-2, 5.562345497310162e-3, + 2.460231189616024e-4, 1.396108977496624e-2, + 1.001838669180870e-1, 2.684516608715058e-1, + 3.398312926292420e-1, 2.122959494590759e-1, + 5.974265560507774e-2, 5.283284001052380e-3, + 2.726115926634520e-4, 1.454808749258518e-2, + 1.024089083075523e-1, 2.709231376647949e-1, + 3.391972482204438e-1, 2.095058411359787e-1, + 5.812742188572884e-2, 5.015311297029257e-3, + 3.013863170053810e-4, 1.515355054289102e-2, + 1.046593263745308e-1, 2.733682692050934e-1, + 3.385068178176880e-1, 2.067128717899322e-1, + 5.654069408774376e-2, 4.758012015372515e-3, + 3.328395541757345e-4, 1.577781140804291e-2, + 1.069347932934761e-1, 2.757860720157624e-1, + 3.377602994441986e-1, 2.039180546998978e-1, + 5.498242005705833e-2, 4.511159844696522e-3, + 3.658991190604866e-4, 1.642123050987720e-2, + 1.092349365353584e-1, 2.781755328178406e-1, + 3.369580209255218e-1, 2.011223286390304e-1, + 5.345252528786659e-2, 4.274417180567980e-3, + 4.018281470052898e-4, 1.708412915468216e-2, + 1.115593686699867e-1, 2.805356979370117e-1, + 3.361004292964936e-1, 1.983266174793244e-1, + 5.195093154907227e-2, 4.047499038279056e-3, + 4.401875485200435e-4, 1.776690222322941e-2, + 1.139076948165894e-1, 2.828655838966370e-1, + 3.351879119873047e-1, 1.955319195985794e-1, + 5.047753453254700e-2, 3.830091329291463e-3, + 4.812776169274002e-4, 1.846982724964619e-2, + 1.162794977426529e-1, 2.851640880107880e-1, + 3.342207968235016e-1, 1.927391141653061e-1, + 4.903224110603333e-2, 3.621967276558280e-3, + 5.252459668554366e-4, 1.919330470263958e-2, + 1.186743453145027e-1, 2.874303460121155e-1, + 3.331996202468872e-1, 1.899491697549820e-1, + 4.761491715908051e-2, 3.422776935622096e-3, + 5.721592460758984e-4, 1.993762329220772e-2, + 1.210917681455612e-1, 2.896633744239807e-1, + 3.321248590946198e-1, 1.871629506349564e-1, + 4.622544348239899e-2, 3.232272574678064e-3, + 6.222130032256246e-4, 2.070316113531590e-2, + 1.235313042998314e-1, 2.918621897697448e-1, + 3.309969604015350e-1, 1.843813359737396e-1, + 4.486365616321564e-2, 3.050152910873294e-3, + 6.755515350960195e-4, 2.149021252989769e-2, + 1.259924471378326e-1, 2.940258979797364e-1, + 3.298164308071136e-1, 1.816052496433258e-1, + 4.352942481637001e-2, 2.876190468668938e-3, + 7.324148900806904e-4, 2.229913882911205e-2, + 1.284746825695038e-1, 2.961534857749939e-1, + 3.285838961601258e-1, 1.788355410099030e-1, + 4.222255200147629e-2, 2.710093278437853e-3, + 7.928516715764999e-4, 2.313023805618286e-2, + 1.309774816036224e-1, 2.982441186904907e-1, + 3.272998929023742e-1, 1.760730892419815e-1, + 4.094288870692253e-2, 2.551567042246461e-3, + 8.570110658183694e-4, 2.398385666310787e-2, + 1.335003077983856e-1, 3.002967536449432e-1, + 3.259649574756622e-1, 1.733186990022659e-1, + 3.969023004174232e-2, 2.400433411821723e-3, + 9.251192095689476e-4, 2.486028522253036e-2, + 1.360425949096680e-1, 3.023106753826142e-1, + 3.245797157287598e-1, 1.705732345581055e-1, + 3.846437484025955e-2, 2.256359672173858e-3, + 9.974770946428180e-4, 2.575986087322235e-2, + 1.386037617921829e-1, 3.042849004268646e-1, + 3.231448531150818e-1, 1.678375005722046e-1, + 3.726511076092720e-2, 2.119151875376701e-3, + 1.073930296115577e-3, 2.668286114931106e-2, + 1.411831974983215e-1, 3.062185347080230e-1, + 3.216609656810760e-1, 1.651122719049454e-1, + 3.609224036335945e-2, 1.988604199141264e-3, + 1.155023579485714e-3, 2.762960828840732e-2, + 1.437802612781525e-1, 3.081108033657074e-1, + 3.201287388801574e-1, 1.623983532190323e-1, + 3.494550660252571e-2, 1.864377525635064e-3, + 1.240676851011813e-3, 2.860039286315441e-2, + 1.463943719863892e-1, 3.099608123302460e-1, + 3.185488879680634e-1, 1.596965193748474e-1, + 3.382468968629837e-2, 1.746327499859035e-3, + 1.331258914433420e-3, 2.959549613296986e-2, + 1.490248143672943e-1, 3.117676973342896e-1, + 3.169221282005310e-1, 1.570075154304504e-1, + 3.272953629493714e-2, 1.634211512282491e-3, + 1.426893868483603e-3, 3.061520494520664e-2, + 1.516709625720978e-1, 3.135308027267456e-1, + 3.152491748332978e-1, 1.543320864439010e-1, + 3.165979683399200e-2, 1.527829794213176e-3, +}; + +DECLARE_ALIGNED(16, static const float, lfe_fir_128)[] = +{ + 0.00053168571, 0.15878495574, 0.68603444099, 0.15492856503, + 0.00016358691, 0.16269733012, 0.68591803312, 0.15112841129, + 0.00018878609, 0.16666537523, 0.68568539619, 0.14738474786, + 0.00021643363, 0.17068879306, 0.68533653021, 0.14369773865, + 0.00024667382, 0.17476719618, 0.68487155437, 0.14006754756, + 0.00027949660, 0.17890018225, 0.68429082632, 0.13649433851, + 0.00031519096, 0.18308731914, 0.68359452486, 0.13297818601, + 0.00035398375, 0.18732811511, 0.68278300762, 0.12951917946, + 0.00039634691, 0.19162209332, 0.68185669184, 0.12611730397, + 0.00044236859, 0.19596865773, 0.68081587553, 0.12277261168, + 0.00049204525, 0.20036731660, 0.67966115475, 0.11948505789, + 0.00054522208, 0.20481738448, 0.67839306593, 0.11625462025, + 0.00060277141, 0.20931822062, 0.67701220512, 0.11308115721, + 0.00066567765, 0.21386915445, 0.67551922798, 0.10996460915, + 0.00073179678, 0.21846942604, 0.67391467094, 0.10690483451, + 0.00080365466, 0.22311829031, 0.67219948769, 0.10390164703, + 0.00088037323, 0.22781492770, 0.67037439346, 0.10095486045, + 0.00096255314, 0.23255851865, 0.66844022274, 0.09806428105, + 0.00105048984, 0.23734821379, 0.66639786959, 0.09522963315, + 0.00114431616, 0.24218304455, 0.66424828768, 0.09245070815, + 0.00124442333, 0.24706205726, 0.66199249029, 0.08972713351, + 0.00135110028, 0.25198432803, 0.65963155031, 0.08705867827, + 0.00146482687, 0.25694879889, 0.65716648102, 0.08444493264, + 0.00158570008, 0.26195442677, 0.65459835529, 0.08188561350, + 0.00171401864, 0.26700007915, 0.65192854404, 0.07938029617, + 0.00185023469, 0.27208462358, 0.64915806055, 0.07692859322, + 0.00199495023, 0.27720692754, 0.64628833532, 0.07453006506, + 0.00214785640, 0.28236576915, 0.64332056046, 0.07218432426, + 0.00231004250, 0.28755992651, 0.64025616646, 0.06989086419, + 0.00248134881, 0.29278811812, 0.63709646463, 0.06764923781, + 0.00266251224, 0.29804900289, 0.63384294510, 0.06545893103, + 0.00285378192, 0.30334126949, 0.63049703836, 0.06331945211, + 0.00305565330, 0.30866351724, 0.62706029415, 0.06123027951, + 0.00326841651, 0.31401440501, 0.62353414297, 0.05919086933, + 0.00349264755, 0.31939238310, 0.61992025375, 0.05720067024, + 0.00372874714, 0.32479602098, 0.61622029543, 0.05525910854, + 0.00397720048, 0.33022382855, 0.61243581772, 0.05336561054, + 0.00423829490, 0.33567428589, 0.60856848955, 0.05151961371, + 0.00451271003, 0.34114575386, 0.60462015867, 0.04972046614, + 0.00480085658, 0.34663668275, 0.60059231520, 0.04796761274, + 0.00510312291, 0.35214546323, 0.59648692608, 0.04626038298, + 0.00542017492, 0.35767036676, 0.59230577946, 0.04459818453, + 0.00575236930, 0.36320972443, 0.58805054426, 0.04298033938, + 0.00610029325, 0.36876192689, 0.58372318745, 0.04140623659, + 0.00646453211, 0.37432509661, 0.57932555676, 0.03987516090, + 0.00684553990, 0.37989753485, 0.57485944033, 0.03838652745, + 0.00724391919, 0.38547745347, 0.57032698393, 0.03693958372, + 0.00766016589, 0.39106300473, 0.56572991610, 0.03553372994, + 0.00809498038, 0.39665243030, 0.56107026339, 0.03416819125, + 0.00854881573, 0.40224379301, 0.55634999275, 0.03284239396, + 0.00902230106, 0.40783521533, 0.55157101154, 0.03155555204, + 0.00951600447, 0.41342487931, 0.54673534632, 0.03030703776, + 0.01003060210, 0.41901078820, 0.54184508324, 0.02909611352, + 0.01056654565, 0.42459106445, 0.53690224886, 0.02792212367, + 0.01112466771, 0.43016362190, 0.53190881014, 0.02678431384, + 0.01170534454, 0.43572667241, 0.52686679363, 0.02568206564, + 0.01230939943, 0.44127810001, 0.52177828550, 0.02461459488, + 0.01293735672, 0.44681602716, 0.51664537191, 0.02358125709, + 0.01358995494, 0.45233830810, 0.51147013903, 0.02258131653, + 0.01426773332, 0.45784294605, 0.50625455379, 0.02161412500, + 0.01497144438, 0.46332800388, 0.50100076199, 0.02067894675, + 0.01570170000, 0.46879136562, 0.49571081996, 0.01977507770, + 0.01645922661, 0.47423094511, 0.49038675427, 0.01890186779, + 0.01724460535, 0.47964480519, 0.48503074050, 0.01805862412, +}; + +/* 10^-(dB/20), with dB being a list of dB values ranging from 0 to -72 */ +/* do a 20*log10(dca_downmix_coeffs) to reconvert the values */ + +static const float dca_downmix_coeffs[65] = { + 1.000000000000000, 0.988553094656939, 0.971627951577106, 0.944060876285923, 0.917275935389780, 0.891250938133746, + 0.865964323360065, 0.841395141645195, 0.817523037943650, 0.794328234724281, 0.771791515585012, 0.749894209332456, + 0.728618174513228, 0.707945784384138, 0.687859912308808, 0.668343917568615, 0.649381631576211, 0.630957344480193, + 0.613055792149821, 0.595662143529010, 0.578761988349121, 0.562341325190349, 0.546386549881854, 0.530884444230988, + 0.515822165072306, 0.501187233627272, 0.446683592150963, 0.398107170553497, 0.354813389233575, 0.316227766016838, + 0.281838293126445, 0.251188643150958, 0.223872113856834, 0.199526231496888, 0.177827941003892, 0.158489319246111, + 0.141253754462275, 0.125892541179417, 0.112201845430196, 0.100000000000000, 0.089125093813374, 0.079432823472428, + 0.070794578438414, 0.063095734448019, 0.053088444423099, 0.044668359215096, 0.037583740428844, 0.031622776601684, + 0.026607250597988, 0.022387211385683, 0.018836490894898, 0.015848931924611, 0.013335214321633, 0.011220184543020, + 0.009440608762859, 0.007943282347243, 0.005623413251903, 0.003981071705535, 0.002818382931264, 0.001995262314969, + 0.001412537544623, 0.001000000000000, 0.000501187233627, 0.000251188643151, 0.000000000000000, +}; + +static const float dca_downmix_scale_factors[241] = { + 0.001000, 0.001059, 0.001122, 0.001189, 0.001259, 0.001334, 0.001413, 0.001496, + 0.001585, 0.001679, 0.001778, 0.001884, 0.001995, 0.002113, 0.002239, 0.002371, + 0.002512, 0.002661, 0.002818, 0.002985, 0.003162, 0.003350, 0.003548, 0.003758, + 0.003981, 0.004217, 0.004467, 0.004732, 0.005012, 0.005309, 0.005623, 0.005957, + 0.006310, 0.006683, 0.007079, 0.007499, 0.007943, 0.008414, 0.008913, 0.009441, + 0.010000, 0.010593, 0.011220, 0.011885, 0.012589, 0.013335, 0.014125, 0.014962, + 0.015849, 0.016788, 0.017783, 0.018836, 0.019953, 0.021135, 0.022387, 0.023714, + 0.025119, 0.026607, 0.028184, 0.029854, 0.031623, 0.032546, 0.033497, 0.034475, + 0.035481, 0.036517, 0.037584, 0.038681, 0.039811, 0.040973, 0.042170, 0.043401, + 0.044668, 0.045973, 0.047315, 0.048697, 0.050119, 0.051582, 0.053088, 0.054639, + 0.056234, 0.057876, 0.059566, 0.061306, 0.063096, 0.064938, 0.066834, 0.068786, + 0.070795, 0.072862, 0.074989, 0.077179, 0.079433, 0.081752, 0.084140, 0.086596, + 0.089125, 0.091728, 0.094406, 0.097163, 0.100000, 0.102920, 0.105925, 0.109018, + 0.112202, 0.115478, 0.118850, 0.122321, 0.125893, 0.129569, 0.133352, 0.137246, + 0.141254, 0.145378, 0.149624, 0.153993, 0.158489, 0.163117, 0.167880, 0.172783, + 0.177828, 0.180406, 0.183021, 0.185674, 0.188365, 0.191095, 0.193865, 0.196675, + 0.199526, 0.202418, 0.205353, 0.208329, 0.211349, 0.214412, 0.217520, 0.220673, + 0.223872, 0.227117, 0.230409, 0.233749, 0.237137, 0.240575, 0.244062, 0.247600, + 0.251189, 0.254830, 0.258523, 0.262271, 0.266073, 0.269929, 0.273842, 0.277811, + 0.281838, 0.285924, 0.290068, 0.294273, 0.298538, 0.302866, 0.307256, 0.311709, + 0.316228, 0.320812, 0.325462, 0.330179, 0.334965, 0.339821, 0.344747, 0.349744, + 0.354813, 0.359956, 0.365174, 0.370467, 0.375837, 0.381285, 0.386812, 0.392419, + 0.398107, 0.403878, 0.409732, 0.415671, 0.421697, 0.427809, 0.434010, 0.440301, + 0.446684, 0.453158, 0.459727, 0.466391, 0.473151, 0.480010, 0.486968, 0.494026, + 0.501187, 0.508452, 0.515822, 0.523299, 0.530884, 0.538580, 0.546387, 0.554307, + 0.562341, 0.570493, 0.578762, 0.587151, 0.595662, 0.604296, 0.613056, 0.621942, + 0.630957, 0.640103, 0.649382, 0.658795, 0.668344, 0.678032, 0.687860, 0.697831, + 0.707107, 0.718208, 0.728618, 0.739180, 0.749894, 0.760764, 0.771792, 0.782979, + 0.794328, 0.805842, 0.817523, 0.829373, 0.841395, 0.853591, 0.865964, 0.878517, + 0.891251, 0.904170, 0.917276, 0.930572, 0.944061, 0.957745, 0.971628, 0.985712, + 1.000000 +}; + +static const uint8_t dca_default_coeffs[10][5][2] = { + { { 13, 13 }, }, + { { 0, 64 }, { 64, 0 }, }, + { { 0, 64 }, { 64, 0 }, }, + { { 0, 64 }, { 64, 0 }, }, + { { 0, 64 }, { 64, 0 }, }, + { { 6, 6 }, { 0, 25 }, { 25, 0 }, }, + { { 0, 25 }, { 25, 0 }, { 13, 13 }, }, + { { 6, 6 }, { 0, 25 }, { 25, 0 }, { 13, 13 }, }, + { { 0, 25 }, { 25, 0 }, { 0, 13 }, { 13, 0 }, }, + { { 6, 6 }, { 0, 25 }, { 25, 0 }, { 0, 13 }, { 13, 0 }, }, +}; + +/* downmix coeffs + + TABLE 9 +______________________________________ +Down-mix coefficients for 8-channel source +audio (5 + 3 format) + lt + cen- rt lt ctr rt +lt ter ctr center + rt srd srd srd +______________________________________ +1 0.71 0.74 1.0 0.71 0.71 0.58 0.58 0.58 +2 left 1.0 0.89 0.71 0.46 0.71 0.50 + rt 0.45 0.71 0.89 1.0 0.50 0.71 +3 lt 1.0 0.89 0.71 0.45 + rt 0.45 0.71 0.89 1.0 + srd 0.71 0.71 0.71 +4 lt 1.0 0.89 0.71 0.45 + rt 0.45 0.71 0.89 1.0 + lt srd 1.0 0.71 + rt srd 0.71 0.71 +4 lt 1.0 0.5 + ctr 0.87 1.0 0.87 + rt 0.5 1.0 + srd 0.71 0.71 0.71 +5 lt 1.0 0.5 + ctr 0.87 1.0 0.87 + rt 0.5 1.0 + lt srd 1.0 0.71 + rt srd 0.71 1.0 +6 lt 1.0 0.5 + lt ctr 0.87 0.71 + rt ctr 0.71 0.87 + rt 0.5 1.0 + lt srd 1.0 0.71 + rt srd 0.71 1.0 +6 lt 1.0 0.5 + ctr 0.86 1.0 0.86 + rt 0.5 1.0 + lt srd 1.0 + ctr srd 1.0 + rt srd 1.0 +7 lt 1.0 + lt ctr 1.0 + ctr 1.0 + rt ctr 1.0 + rt 1.0 + lt srd 1.0 0.71 + rt srd 0.71 1.0 +7 lt 1.0 0.5 + lt ctr 0.87 0.71 + rt ctr 0.71 0.87 + rt 0.5 1.0 + lt srd 1.0 + ctr srd 1.0 + rt srd 1.0 +8 lt 1.0 0.5 + lt ctr 0.87 0.71 + rt ctr 0.71 0.87 + rt 0.5 1.0 + lt 1 srd 0.87 0.35 + lt 2 srd 0.5 0.61 + rt 2 srd 0.61 0.50 + rt 2 srd 0.35 0.87 + + Generation of Lt Rt + +In the case when the playback system has analog or digital surround multi-channel capability, a down matrix from 5, 4, or 3 channel to Lt Rt may be desirable. In the case when the number of decoded audio channels exceeds 5, 4 or 3 respectively a first stage down mix to 5, 4 or 3 chs should be used as described above. + +The down matrixing equations for 5-channel source audio to a two-channel Lt Rt playback system are given by: + +Left left+0.7*center-0.7*(lt surround+rt surround) + +Right=right+0.7*center+0.7*(lt surround+rt surround) + +Embedded mixing to 2-channel + +One concern arising from the proliferation of multi-channel audio systems is that most home systems presently have only two channel playback capability. To accommodate this a fixed 2-channel down matrix processes is commonly used following the multi-channel decoding stage. However, for music only applications the image quality etc. of the down matrixed signal may not match that of an equivalent stereo recording found on CD. + +The concept of embedded mixing is to allow the producer to dynamically specify the matrixing coefficients within the audio frame itself. In this way the stereo down mix at the decoder may be better matched to a 2-channel playback environment. + +CHS*2, 7-bit down mix indexes (MCOEFFS) are transmitted along with the multi-channel audio once in every frame. The indexes are converted to attenuation factors using a 7 bit LUT. The 2-ch down mix equations are as follows, + +Left Ch=sum (MCOEFF[n]*Ch[n]) for n=1, CHS + +Right Ch sum (MCOEFF[n+CHS]*Ch[n]) for n=1, CHS + +where Ch(n) represents the subband samples in the (n)th audio channel. + + +*/ + +#endif /* AVCODEC_DCADATA_H */ diff --git a/ffmpeg/libavcodec/dcadec.c b/ffmpeg/libavcodec/dcadec.c new file mode 100644 index 0000000..cf4412c --- /dev/null +++ b/ffmpeg/libavcodec/dcadec.c @@ -0,0 +1,2525 @@ +/* + * DCA compatible decoder + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libavutil/samplefmt.h" +#include "avcodec.h" +#include "fft.h" +#include "get_bits.h" +#include "put_bits.h" +#include "dcadata.h" +#include "dcahuff.h" +#include "dca.h" +#include "dca_parser.h" +#include "mathops.h" +#include "synth_filter.h" +#include "dcadsp.h" +#include "fmtconvert.h" +#include "internal.h" + +#if ARCH_ARM +# include "arm/dca.h" +#endif + +//#define TRACE + +#define DCA_PRIM_CHANNELS_MAX (7) +#define DCA_SUBBANDS (64) +#define DCA_ABITS_MAX (32) /* Should be 28 */ +#define DCA_SUBSUBFRAMES_MAX (4) +#define DCA_SUBFRAMES_MAX (16) +#define DCA_BLOCKS_MAX (16) +#define DCA_LFE_MAX (3) +#define DCA_CHSETS_MAX (4) +#define DCA_CHSET_CHANS_MAX (8) + +enum DCAMode { + DCA_MONO = 0, + DCA_CHANNEL, + DCA_STEREO, + DCA_STEREO_SUMDIFF, + DCA_STEREO_TOTAL, + DCA_3F, + DCA_2F1R, + DCA_3F1R, + DCA_2F2R, + DCA_3F2R, + DCA_4F2R +}; + +/* these are unconfirmed but should be mostly correct */ +enum DCAExSSSpeakerMask { + DCA_EXSS_FRONT_CENTER = 0x0001, + DCA_EXSS_FRONT_LEFT_RIGHT = 0x0002, + DCA_EXSS_SIDE_REAR_LEFT_RIGHT = 0x0004, + DCA_EXSS_LFE = 0x0008, + DCA_EXSS_REAR_CENTER = 0x0010, + DCA_EXSS_FRONT_HIGH_LEFT_RIGHT = 0x0020, + DCA_EXSS_REAR_LEFT_RIGHT = 0x0040, + DCA_EXSS_FRONT_HIGH_CENTER = 0x0080, + DCA_EXSS_OVERHEAD = 0x0100, + DCA_EXSS_CENTER_LEFT_RIGHT = 0x0200, + DCA_EXSS_WIDE_LEFT_RIGHT = 0x0400, + DCA_EXSS_SIDE_LEFT_RIGHT = 0x0800, + DCA_EXSS_LFE2 = 0x1000, + DCA_EXSS_SIDE_HIGH_LEFT_RIGHT = 0x2000, + DCA_EXSS_REAR_HIGH_CENTER = 0x4000, + DCA_EXSS_REAR_HIGH_LEFT_RIGHT = 0x8000, +}; + +enum DCAXxchSpeakerMask { + DCA_XXCH_FRONT_CENTER = 0x0000001, + DCA_XXCH_FRONT_LEFT = 0x0000002, + DCA_XXCH_FRONT_RIGHT = 0x0000004, + DCA_XXCH_SIDE_REAR_LEFT = 0x0000008, + DCA_XXCH_SIDE_REAR_RIGHT = 0x0000010, + DCA_XXCH_LFE1 = 0x0000020, + DCA_XXCH_REAR_CENTER = 0x0000040, + DCA_XXCH_SURROUND_REAR_LEFT = 0x0000080, + DCA_XXCH_SURROUND_REAR_RIGHT = 0x0000100, + DCA_XXCH_SIDE_SURROUND_LEFT = 0x0000200, + DCA_XXCH_SIDE_SURROUND_RIGHT = 0x0000400, + DCA_XXCH_FRONT_CENTER_LEFT = 0x0000800, + DCA_XXCH_FRONT_CENTER_RIGHT = 0x0001000, + DCA_XXCH_FRONT_HIGH_LEFT = 0x0002000, + DCA_XXCH_FRONT_HIGH_CENTER = 0x0004000, + DCA_XXCH_FRONT_HIGH_RIGHT = 0x0008000, + DCA_XXCH_LFE2 = 0x0010000, + DCA_XXCH_SIDE_FRONT_LEFT = 0x0020000, + DCA_XXCH_SIDE_FRONT_RIGHT = 0x0040000, + DCA_XXCH_OVERHEAD = 0x0080000, + DCA_XXCH_SIDE_HIGH_LEFT = 0x0100000, + DCA_XXCH_SIDE_HIGH_RIGHT = 0x0200000, + DCA_XXCH_REAR_HIGH_CENTER = 0x0400000, + DCA_XXCH_REAR_HIGH_LEFT = 0x0800000, + DCA_XXCH_REAR_HIGH_RIGHT = 0x1000000, + DCA_XXCH_REAR_LOW_CENTER = 0x2000000, + DCA_XXCH_REAR_LOW_LEFT = 0x4000000, + DCA_XXCH_REAR_LOW_RIGHT = 0x8000000, +}; + +static const uint32_t map_xxch_to_native[28] = { + AV_CH_FRONT_CENTER, + AV_CH_FRONT_LEFT, + AV_CH_FRONT_RIGHT, + AV_CH_SIDE_LEFT, + AV_CH_SIDE_RIGHT, + AV_CH_LOW_FREQUENCY, + AV_CH_BACK_CENTER, + AV_CH_BACK_LEFT, + AV_CH_BACK_RIGHT, + AV_CH_SIDE_LEFT, /* side surround left -- dup sur side L */ + AV_CH_SIDE_RIGHT, /* side surround right -- dup sur side R */ + AV_CH_FRONT_LEFT_OF_CENTER, + AV_CH_FRONT_RIGHT_OF_CENTER, + AV_CH_TOP_FRONT_LEFT, + AV_CH_TOP_FRONT_CENTER, + AV_CH_TOP_FRONT_RIGHT, + AV_CH_LOW_FREQUENCY, /* lfe2 -- duplicate lfe1 position */ + AV_CH_FRONT_LEFT_OF_CENTER, /* side front left -- dup front cntr L */ + AV_CH_FRONT_RIGHT_OF_CENTER,/* side front right -- dup front cntr R */ + AV_CH_TOP_CENTER, /* overhead */ + AV_CH_TOP_FRONT_LEFT, /* side high left -- dup */ + AV_CH_TOP_FRONT_RIGHT, /* side high right -- dup */ + AV_CH_TOP_BACK_CENTER, + AV_CH_TOP_BACK_LEFT, + AV_CH_TOP_BACK_RIGHT, + AV_CH_BACK_CENTER, /* rear low center -- dup */ + AV_CH_BACK_LEFT, /* rear low left -- dup */ + AV_CH_BACK_RIGHT /* read low right -- dup */ +}; + +enum DCAExtensionMask { + DCA_EXT_CORE = 0x001, ///< core in core substream + DCA_EXT_XXCH = 0x002, ///< XXCh channels extension in core substream + DCA_EXT_X96 = 0x004, ///< 96/24 extension in core substream + DCA_EXT_XCH = 0x008, ///< XCh channel extension in core substream + DCA_EXT_EXSS_CORE = 0x010, ///< core in ExSS (extension substream) + DCA_EXT_EXSS_XBR = 0x020, ///< extended bitrate extension in ExSS + DCA_EXT_EXSS_XXCH = 0x040, ///< XXCh channels extension in ExSS + DCA_EXT_EXSS_X96 = 0x080, ///< 96/24 extension in ExSS + DCA_EXT_EXSS_LBR = 0x100, ///< low bitrate component in ExSS + DCA_EXT_EXSS_XLL = 0x200, ///< lossless extension in ExSS +}; + +/* -1 are reserved or unknown */ +static const int dca_ext_audio_descr_mask[] = { + DCA_EXT_XCH, + -1, + DCA_EXT_X96, + DCA_EXT_XCH | DCA_EXT_X96, + -1, + -1, + DCA_EXT_XXCH, + -1, +}; + +/* extensions that reside in core substream */ +#define DCA_CORE_EXTS (DCA_EXT_XCH | DCA_EXT_XXCH | DCA_EXT_X96) + +/* Tables for mapping dts channel configurations to libavcodec multichannel api. + * Some compromises have been made for special configurations. Most configurations + * are never used so complete accuracy is not needed. + * + * L = left, R = right, C = center, S = surround, F = front, R = rear, T = total, OV = overhead. + * S -> side, when both rear and back are configured move one of them to the side channel + * OV -> center back + * All 2 channel configurations -> AV_CH_LAYOUT_STEREO + */ +static const uint64_t dca_core_channel_layout[] = { + AV_CH_FRONT_CENTER, ///< 1, A + AV_CH_LAYOUT_STEREO, ///< 2, A + B (dual mono) + AV_CH_LAYOUT_STEREO, ///< 2, L + R (stereo) + AV_CH_LAYOUT_STEREO, ///< 2, (L + R) + (L - R) (sum-difference) + AV_CH_LAYOUT_STEREO, ///< 2, LT + RT (left and right total) + AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER, ///< 3, C + L + R + AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER, ///< 3, L + R + S + AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER | AV_CH_BACK_CENTER, ///< 4, C + L + R + S + AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT, ///< 4, L + R + SL + SR + + AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER | AV_CH_SIDE_LEFT | + AV_CH_SIDE_RIGHT, ///< 5, C + L + R + SL + SR + + AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT | + AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER, ///< 6, CL + CR + L + R + SL + SR + + AV_CH_LAYOUT_STEREO | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | + AV_CH_FRONT_CENTER | AV_CH_BACK_CENTER, ///< 6, C + L + R + LR + RR + OV + + AV_CH_FRONT_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER | + AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_BACK_CENTER | + AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT, ///< 6, CF + CR + LF + RF + LR + RR + + AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER | AV_CH_LAYOUT_STEREO | + AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT, ///< 7, CL + C + CR + L + R + SL + SR + + AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER | + AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT | + AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT, ///< 8, CL + CR + L + R + SL1 + SL2 + SR1 + SR2 + + AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER | AV_CH_LAYOUT_STEREO | + AV_CH_SIDE_LEFT | AV_CH_BACK_CENTER | AV_CH_SIDE_RIGHT, ///< 8, CL + C + CR + L + R + SL + S + SR +}; + +static const int8_t dca_lfe_index[] = { + 1, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3 +}; + +static const int8_t dca_channel_reorder_lfe[][9] = { + { 0, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 0, 1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 3, -1, -1, -1, -1, -1, -1}, + { 2, 0, 1, 4, -1, -1, -1, -1, -1}, + { 0, 1, 3, 4, -1, -1, -1, -1, -1}, + { 2, 0, 1, 4, 5, -1, -1, -1, -1}, + { 3, 4, 0, 1, 5, 6, -1, -1, -1}, + { 2, 0, 1, 4, 5, 6, -1, -1, -1}, + { 0, 6, 4, 5, 2, 3, -1, -1, -1}, + { 4, 2, 5, 0, 1, 6, 7, -1, -1}, + { 5, 6, 0, 1, 7, 3, 8, 4, -1}, + { 4, 2, 5, 0, 1, 6, 8, 7, -1}, +}; + +static const int8_t dca_channel_reorder_lfe_xch[][9] = { + { 0, 2, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 3, -1, -1, -1, -1, -1, -1}, + { 0, 1, 3, -1, -1, -1, -1, -1, -1}, + { 0, 1, 3, -1, -1, -1, -1, -1, -1}, + { 0, 1, 3, -1, -1, -1, -1, -1, -1}, + { 2, 0, 1, 4, -1, -1, -1, -1, -1}, + { 0, 1, 3, 4, -1, -1, -1, -1, -1}, + { 2, 0, 1, 4, 5, -1, -1, -1, -1}, + { 0, 1, 4, 5, 3, -1, -1, -1, -1}, + { 2, 0, 1, 5, 6, 4, -1, -1, -1}, + { 3, 4, 0, 1, 6, 7, 5, -1, -1}, + { 2, 0, 1, 4, 5, 6, 7, -1, -1}, + { 0, 6, 4, 5, 2, 3, 7, -1, -1}, + { 4, 2, 5, 0, 1, 7, 8, 6, -1}, + { 5, 6, 0, 1, 8, 3, 9, 4, 7}, + { 4, 2, 5, 0, 1, 6, 9, 8, 7}, +}; + +static const int8_t dca_channel_reorder_nolfe[][9] = { + { 0, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 2, 0, 1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 2, -1, -1, -1, -1, -1, -1}, + { 2, 0, 1, 3, -1, -1, -1, -1, -1}, + { 0, 1, 2, 3, -1, -1, -1, -1, -1}, + { 2, 0, 1, 3, 4, -1, -1, -1, -1}, + { 2, 3, 0, 1, 4, 5, -1, -1, -1}, + { 2, 0, 1, 3, 4, 5, -1, -1, -1}, + { 0, 5, 3, 4, 1, 2, -1, -1, -1}, + { 3, 2, 4, 0, 1, 5, 6, -1, -1}, + { 4, 5, 0, 1, 6, 2, 7, 3, -1}, + { 3, 2, 4, 0, 1, 5, 7, 6, -1}, +}; + +static const int8_t dca_channel_reorder_nolfe_xch[][9] = { + { 0, 1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 1, 2, -1, -1, -1, -1, -1, -1}, + { 0, 1, 2, -1, -1, -1, -1, -1, -1}, + { 0, 1, 2, -1, -1, -1, -1, -1, -1}, + { 0, 1, 2, -1, -1, -1, -1, -1, -1}, + { 2, 0, 1, 3, -1, -1, -1, -1, -1}, + { 0, 1, 2, 3, -1, -1, -1, -1, -1}, + { 2, 0, 1, 3, 4, -1, -1, -1, -1}, + { 0, 1, 3, 4, 2, -1, -1, -1, -1}, + { 2, 0, 1, 4, 5, 3, -1, -1, -1}, + { 2, 3, 0, 1, 5, 6, 4, -1, -1}, + { 2, 0, 1, 3, 4, 5, 6, -1, -1}, + { 0, 5, 3, 4, 1, 2, 6, -1, -1}, + { 3, 2, 4, 0, 1, 6, 7, 5, -1}, + { 4, 5, 0, 1, 7, 2, 8, 3, 6}, + { 3, 2, 4, 0, 1, 5, 8, 7, 6}, +}; + +#define DCA_DOLBY 101 /* FIXME */ + +#define DCA_CHANNEL_BITS 6 +#define DCA_CHANNEL_MASK 0x3F + +#define DCA_LFE 0x80 + +#define HEADER_SIZE 14 + +#define DCA_MAX_FRAME_SIZE 16384 +#define DCA_MAX_EXSS_HEADER_SIZE 4096 + +#define DCA_BUFFER_PADDING_SIZE 1024 + +/** Bit allocation */ +typedef struct { + int offset; ///< code values offset + int maxbits[8]; ///< max bits in VLC + int wrap; ///< wrap for get_vlc2() + VLC vlc[8]; ///< actual codes +} BitAlloc; + +static BitAlloc dca_bitalloc_index; ///< indexes for samples VLC select +static BitAlloc dca_tmode; ///< transition mode VLCs +static BitAlloc dca_scalefactor; ///< scalefactor VLCs +static BitAlloc dca_smpl_bitalloc[11]; ///< samples VLCs + +static av_always_inline int get_bitalloc(GetBitContext *gb, BitAlloc *ba, + int idx) +{ + return get_vlc2(gb, ba->vlc[idx].table, ba->vlc[idx].bits, ba->wrap) + + ba->offset; +} + +typedef struct { + AVCodecContext *avctx; + /* Frame header */ + int frame_type; ///< type of the current frame + int samples_deficit; ///< deficit sample count + int crc_present; ///< crc is present in the bitstream + int sample_blocks; ///< number of PCM sample blocks + int frame_size; ///< primary frame byte size + int amode; ///< audio channels arrangement + int sample_rate; ///< audio sampling rate + int bit_rate; ///< transmission bit rate + int bit_rate_index; ///< transmission bit rate index + + int downmix; ///< embedded downmix enabled + int dynrange; ///< embedded dynamic range flag + int timestamp; ///< embedded time stamp flag + int aux_data; ///< auxiliary data flag + int hdcd; ///< source material is mastered in HDCD + int ext_descr; ///< extension audio descriptor flag + int ext_coding; ///< extended coding flag + int aspf; ///< audio sync word insertion flag + int lfe; ///< low frequency effects flag + int predictor_history; ///< predictor history flag + int header_crc; ///< header crc check bytes + int multirate_inter; ///< multirate interpolator switch + int version; ///< encoder software revision + int copy_history; ///< copy history + int source_pcm_res; ///< source pcm resolution + int front_sum; ///< front sum/difference flag + int surround_sum; ///< surround sum/difference flag + int dialog_norm; ///< dialog normalisation parameter + + /* Primary audio coding header */ + int subframes; ///< number of subframes + int total_channels; ///< number of channels including extensions + int prim_channels; ///< number of primary audio channels + int subband_activity[DCA_PRIM_CHANNELS_MAX]; ///< subband activity count + int vq_start_subband[DCA_PRIM_CHANNELS_MAX]; ///< high frequency vq start subband + int joint_intensity[DCA_PRIM_CHANNELS_MAX]; ///< joint intensity coding index + int transient_huffman[DCA_PRIM_CHANNELS_MAX]; ///< transient mode code book + int scalefactor_huffman[DCA_PRIM_CHANNELS_MAX]; ///< scale factor code book + int bitalloc_huffman[DCA_PRIM_CHANNELS_MAX]; ///< bit allocation quantizer select + int quant_index_huffman[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< quantization index codebook select + float scalefactor_adj[DCA_PRIM_CHANNELS_MAX][DCA_ABITS_MAX]; ///< scale factor adjustment + + /* Primary audio coding side information */ + int subsubframes[DCA_SUBFRAMES_MAX]; ///< number of subsubframes + int partial_samples[DCA_SUBFRAMES_MAX]; ///< partial subsubframe samples count + int prediction_mode[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< prediction mode (ADPCM used or not) + int prediction_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< prediction VQ coefs + int bitalloc[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< bit allocation index + int transition_mode[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< transition mode (transients) + int scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][2]; ///< scale factors (2 if transient) + int joint_huff[DCA_PRIM_CHANNELS_MAX]; ///< joint subband scale factors codebook + int joint_scale_factor[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< joint subband scale factors + int downmix_coef[DCA_PRIM_CHANNELS_MAX][2]; ///< stereo downmix coefficients + int dynrange_coef; ///< dynamic range coefficient + + int high_freq_vq[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS]; ///< VQ encoded high frequency subbands + + float lfe_data[2 * DCA_LFE_MAX * (DCA_BLOCKS_MAX + 4)]; ///< Low frequency effect data + int lfe_scale_factor; + + /* Subband samples history (for ADPCM) */ + DECLARE_ALIGNED(16, float, subband_samples_hist)[DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][4]; + DECLARE_ALIGNED(32, float, subband_fir_hist)[DCA_PRIM_CHANNELS_MAX][512]; + DECLARE_ALIGNED(32, float, subband_fir_noidea)[DCA_PRIM_CHANNELS_MAX][32]; + int hist_index[DCA_PRIM_CHANNELS_MAX]; + DECLARE_ALIGNED(32, float, raXin)[32]; + + int output; ///< type of output + + DECLARE_ALIGNED(32, float, subband_samples)[DCA_BLOCKS_MAX][DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][8]; + float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1]; + float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1]; + uint8_t *extra_channels_buffer; + unsigned int extra_channels_buffer_size; + + uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE]; + int dca_buffer_size; ///< how much data is in the dca_buffer + + const int8_t *channel_order_tab; ///< channel reordering table, lfe and non lfe + GetBitContext gb; + /* Current position in DCA frame */ + int current_subframe; + int current_subsubframe; + + int core_ext_mask; ///< present extensions in the core substream + + /* XCh extension information */ + int xch_present; ///< XCh extension present and valid + int xch_base_channel; ///< index of first (only) channel containing XCH data + + /* XXCH extension information */ + int xxch_chset; + int xxch_nbits_spk_mask; + uint32_t xxch_core_spkmask; + uint32_t xxch_spk_masks[4]; /* speaker masks, last element is core mask */ + int xxch_chset_nch[4]; + float xxch_dmix_sf[DCA_CHSETS_MAX]; + + uint32_t xxch_dmix_embedded; /* lower layer has mix pre-embedded, per chset */ + float xxch_dmix_coeff[DCA_PRIM_CHANNELS_MAX][32]; /* worst case sizing */ + + int8_t xxch_order_tab[32]; + int8_t lfe_index; + + /* ExSS header parser */ + int static_fields; ///< static fields present + int mix_metadata; ///< mixing metadata present + int num_mix_configs; ///< number of mix out configurations + int mix_config_num_ch[4]; ///< number of channels in each mix out configuration + + int profile; + + int debug_flag; ///< used for suppressing repeated error messages output + AVFloatDSPContext fdsp; + FFTContext imdct; + SynthFilterContext synth; + DCADSPContext dcadsp; + FmtConvertContext fmt_conv; +} DCAContext; + +static const uint16_t dca_vlc_offs[] = { + 0, 512, 640, 768, 1282, 1794, 2436, 3080, 3770, 4454, 5364, + 5372, 5380, 5388, 5392, 5396, 5412, 5420, 5428, 5460, 5492, 5508, + 5572, 5604, 5668, 5796, 5860, 5892, 6412, 6668, 6796, 7308, 7564, + 7820, 8076, 8620, 9132, 9388, 9910, 10166, 10680, 11196, 11726, 12240, + 12752, 13298, 13810, 14326, 14840, 15500, 16022, 16540, 17158, 17678, 18264, + 18796, 19352, 19926, 20468, 21472, 22398, 23014, 23622, +}; + +static av_cold void dca_init_vlcs(void) +{ + static int vlcs_initialized = 0; + int i, j, c = 14; + static VLC_TYPE dca_table[23622][2]; + + if (vlcs_initialized) + return; + + dca_bitalloc_index.offset = 1; + dca_bitalloc_index.wrap = 2; + for (i = 0; i < 5; i++) { + dca_bitalloc_index.vlc[i].table = &dca_table[dca_vlc_offs[i]]; + dca_bitalloc_index.vlc[i].table_allocated = dca_vlc_offs[i + 1] - dca_vlc_offs[i]; + init_vlc(&dca_bitalloc_index.vlc[i], bitalloc_12_vlc_bits[i], 12, + bitalloc_12_bits[i], 1, 1, + bitalloc_12_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + dca_scalefactor.offset = -64; + dca_scalefactor.wrap = 2; + for (i = 0; i < 5; i++) { + dca_scalefactor.vlc[i].table = &dca_table[dca_vlc_offs[i + 5]]; + dca_scalefactor.vlc[i].table_allocated = dca_vlc_offs[i + 6] - dca_vlc_offs[i + 5]; + init_vlc(&dca_scalefactor.vlc[i], SCALES_VLC_BITS, 129, + scales_bits[i], 1, 1, + scales_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + dca_tmode.offset = 0; + dca_tmode.wrap = 1; + for (i = 0; i < 4; i++) { + dca_tmode.vlc[i].table = &dca_table[dca_vlc_offs[i + 10]]; + dca_tmode.vlc[i].table_allocated = dca_vlc_offs[i + 11] - dca_vlc_offs[i + 10]; + init_vlc(&dca_tmode.vlc[i], tmode_vlc_bits[i], 4, + tmode_bits[i], 1, 1, + tmode_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + + for (i = 0; i < 10; i++) + for (j = 0; j < 7; j++) { + if (!bitalloc_codes[i][j]) + break; + dca_smpl_bitalloc[i + 1].offset = bitalloc_offsets[i]; + dca_smpl_bitalloc[i + 1].wrap = 1 + (j > 4); + dca_smpl_bitalloc[i + 1].vlc[j].table = &dca_table[dca_vlc_offs[c]]; + dca_smpl_bitalloc[i + 1].vlc[j].table_allocated = dca_vlc_offs[c + 1] - dca_vlc_offs[c]; + + init_vlc(&dca_smpl_bitalloc[i + 1].vlc[j], bitalloc_maxbits[i][j], + bitalloc_sizes[i], + bitalloc_bits[i][j], 1, 1, + bitalloc_codes[i][j], 2, 2, INIT_VLC_USE_NEW_STATIC); + c++; + } + vlcs_initialized = 1; +} + +static inline void get_array(GetBitContext *gb, int *dst, int len, int bits) +{ + while (len--) + *dst++ = get_bits(gb, bits); +} + +static inline int dca_xxch2index(DCAContext *s, int xxch_ch) +{ + int i, base, mask; + + /* locate channel set containing the channel */ + for (i = -1, base = 0, mask = (s->xxch_core_spkmask & ~DCA_XXCH_LFE1); + i <= s->xxch_chset && !(mask & xxch_ch); mask = s->xxch_spk_masks[++i]) + base += av_popcount(mask); + + return base + av_popcount(mask & (xxch_ch - 1)); +} + +static int dca_parse_audio_coding_header(DCAContext *s, int base_channel, + int xxch) +{ + int i, j; + static const float adj_table[4] = { 1.0, 1.1250, 1.2500, 1.4375 }; + static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 }; + static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 }; + int hdr_pos = 0, hdr_size = 0; + float sign, mag, scale_factor; + int this_chans, acc_mask; + int embedded_downmix; + int nchans, mask[8]; + int coeff, ichan; + + /* xxch has arbitrary sized audio coding headers */ + if (xxch) { + hdr_pos = get_bits_count(&s->gb); + hdr_size = get_bits(&s->gb, 7) + 1; + } + + nchans = get_bits(&s->gb, 3) + 1; + s->total_channels = nchans + base_channel; + s->prim_channels = s->total_channels; + + /* obtain speaker layout mask & downmix coefficients for XXCH */ + if (xxch) { + acc_mask = s->xxch_core_spkmask; + + this_chans = get_bits(&s->gb, s->xxch_nbits_spk_mask - 6) << 6; + s->xxch_spk_masks[s->xxch_chset] = this_chans; + s->xxch_chset_nch[s->xxch_chset] = nchans; + + for (i = 0; i <= s->xxch_chset; i++) + acc_mask |= s->xxch_spk_masks[i]; + + /* check for downmixing information */ + if (get_bits1(&s->gb)) { + embedded_downmix = get_bits1(&s->gb); + scale_factor = + 1.0f / dca_downmix_scale_factors[(get_bits(&s->gb, 6) - 1) << 2]; + + s->xxch_dmix_sf[s->xxch_chset] = scale_factor; + + for (i = base_channel; i < s->prim_channels; i++) { + mask[i] = get_bits(&s->gb, s->xxch_nbits_spk_mask); + } + + for (j = base_channel; j < s->prim_channels; j++) { + memset(s->xxch_dmix_coeff[j], 0, sizeof(s->xxch_dmix_coeff[0])); + s->xxch_dmix_embedded |= (embedded_downmix << j); + for (i = 0; i < s->xxch_nbits_spk_mask; i++) { + if (mask[j] & (1 << i)) { + if ((1 << i) == DCA_XXCH_LFE1) { + av_log(s->avctx, AV_LOG_WARNING, + "DCA-XXCH: dmix to LFE1 not supported.\n"); + continue; + } + + coeff = get_bits(&s->gb, 7); + sign = (coeff & 64) ? 1.0 : -1.0; + mag = dca_downmix_scale_factors[((coeff & 63) - 1) << 2]; + ichan = dca_xxch2index(s, 1 << i); + s->xxch_dmix_coeff[j][ichan] = sign * mag; + } + } + } + } + } + + if (s->prim_channels > DCA_PRIM_CHANNELS_MAX) + s->prim_channels = DCA_PRIM_CHANNELS_MAX; + + + for (i = base_channel; i < s->prim_channels; i++) { + s->subband_activity[i] = get_bits(&s->gb, 5) + 2; + if (s->subband_activity[i] > DCA_SUBBANDS) + s->subband_activity[i] = DCA_SUBBANDS; + } + for (i = base_channel; i < s->prim_channels; i++) { + s->vq_start_subband[i] = get_bits(&s->gb, 5) + 1; + if (s->vq_start_subband[i] > DCA_SUBBANDS) + s->vq_start_subband[i] = DCA_SUBBANDS; + } + get_array(&s->gb, s->joint_intensity + base_channel, s->prim_channels - base_channel, 3); + get_array(&s->gb, s->transient_huffman + base_channel, s->prim_channels - base_channel, 2); + get_array(&s->gb, s->scalefactor_huffman + base_channel, s->prim_channels - base_channel, 3); + get_array(&s->gb, s->bitalloc_huffman + base_channel, s->prim_channels - base_channel, 3); + + /* Get codebooks quantization indexes */ + if (!base_channel) + memset(s->quant_index_huffman, 0, sizeof(s->quant_index_huffman)); + for (j = 1; j < 11; j++) + for (i = base_channel; i < s->prim_channels; i++) + s->quant_index_huffman[i][j] = get_bits(&s->gb, bitlen[j]); + + /* Get scale factor adjustment */ + for (j = 0; j < 11; j++) + for (i = base_channel; i < s->prim_channels; i++) + s->scalefactor_adj[i][j] = 1; + + for (j = 1; j < 11; j++) + for (i = base_channel; i < s->prim_channels; i++) + if (s->quant_index_huffman[i][j] < thr[j]) + s->scalefactor_adj[i][j] = adj_table[get_bits(&s->gb, 2)]; + + if (!xxch) { + if (s->crc_present) { + /* Audio header CRC check */ + get_bits(&s->gb, 16); + } + } else { + /* Skip to the end of the header, also ignore CRC if present */ + i = get_bits_count(&s->gb); + if (hdr_pos + 8 * hdr_size > i) + skip_bits_long(&s->gb, hdr_pos + 8 * hdr_size - i); + } + + s->current_subframe = 0; + s->current_subsubframe = 0; + +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "subframes: %i\n", s->subframes); + av_log(s->avctx, AV_LOG_DEBUG, "prim channels: %i\n", s->prim_channels); + for (i = base_channel; i < s->prim_channels; i++) { + av_log(s->avctx, AV_LOG_DEBUG, "subband activity: %i\n", + s->subband_activity[i]); + av_log(s->avctx, AV_LOG_DEBUG, "vq start subband: %i\n", + s->vq_start_subband[i]); + av_log(s->avctx, AV_LOG_DEBUG, "joint intensity: %i\n", + s->joint_intensity[i]); + av_log(s->avctx, AV_LOG_DEBUG, "transient mode codebook: %i\n", + s->transient_huffman[i]); + av_log(s->avctx, AV_LOG_DEBUG, "scale factor codebook: %i\n", + s->scalefactor_huffman[i]); + av_log(s->avctx, AV_LOG_DEBUG, "bit allocation quantizer: %i\n", + s->bitalloc_huffman[i]); + av_log(s->avctx, AV_LOG_DEBUG, "quant index huff:"); + for (j = 0; j < 11; j++) + av_log(s->avctx, AV_LOG_DEBUG, " %i", s->quant_index_huffman[i][j]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + av_log(s->avctx, AV_LOG_DEBUG, "scalefac adj:"); + for (j = 0; j < 11; j++) + av_log(s->avctx, AV_LOG_DEBUG, " %1.3f", s->scalefactor_adj[i][j]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } +#endif + + return 0; +} + +static int dca_parse_frame_header(DCAContext *s) +{ + init_get_bits(&s->gb, s->dca_buffer, s->dca_buffer_size * 8); + + /* Sync code */ + skip_bits_long(&s->gb, 32); + + /* Frame header */ + s->frame_type = get_bits(&s->gb, 1); + s->samples_deficit = get_bits(&s->gb, 5) + 1; + s->crc_present = get_bits(&s->gb, 1); + s->sample_blocks = get_bits(&s->gb, 7) + 1; + s->frame_size = get_bits(&s->gb, 14) + 1; + if (s->frame_size < 95) + return AVERROR_INVALIDDATA; + s->amode = get_bits(&s->gb, 6); + s->sample_rate = avpriv_dca_sample_rates[get_bits(&s->gb, 4)]; + if (!s->sample_rate) + return AVERROR_INVALIDDATA; + s->bit_rate_index = get_bits(&s->gb, 5); + s->bit_rate = dca_bit_rates[s->bit_rate_index]; + if (!s->bit_rate) + return AVERROR_INVALIDDATA; + + s->downmix = get_bits(&s->gb, 1); /* note: this is FixedBit == 0 */ + s->dynrange = get_bits(&s->gb, 1); + s->timestamp = get_bits(&s->gb, 1); + s->aux_data = get_bits(&s->gb, 1); + s->hdcd = get_bits(&s->gb, 1); + s->ext_descr = get_bits(&s->gb, 3); + s->ext_coding = get_bits(&s->gb, 1); + s->aspf = get_bits(&s->gb, 1); + s->lfe = get_bits(&s->gb, 2); + s->predictor_history = get_bits(&s->gb, 1); + + if (s->lfe == 3) { + s->lfe = 0; + avpriv_request_sample(s->avctx, "LFE = 3"); + return AVERROR_PATCHWELCOME; + } + + /* TODO: check CRC */ + if (s->crc_present) + s->header_crc = get_bits(&s->gb, 16); + + s->multirate_inter = get_bits(&s->gb, 1); + s->version = get_bits(&s->gb, 4); + s->copy_history = get_bits(&s->gb, 2); + s->source_pcm_res = get_bits(&s->gb, 3); + s->front_sum = get_bits(&s->gb, 1); + s->surround_sum = get_bits(&s->gb, 1); + s->dialog_norm = get_bits(&s->gb, 4); + + /* FIXME: channels mixing levels */ + s->output = s->amode; + if (s->lfe) + s->output |= DCA_LFE; + +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "frame type: %i\n", s->frame_type); + av_log(s->avctx, AV_LOG_DEBUG, "samples deficit: %i\n", s->samples_deficit); + av_log(s->avctx, AV_LOG_DEBUG, "crc present: %i\n", s->crc_present); + av_log(s->avctx, AV_LOG_DEBUG, "sample blocks: %i (%i samples)\n", + s->sample_blocks, s->sample_blocks * 32); + av_log(s->avctx, AV_LOG_DEBUG, "frame size: %i bytes\n", s->frame_size); + av_log(s->avctx, AV_LOG_DEBUG, "amode: %i (%i channels)\n", + s->amode, dca_channels[s->amode]); + av_log(s->avctx, AV_LOG_DEBUG, "sample rate: %i Hz\n", + s->sample_rate); + av_log(s->avctx, AV_LOG_DEBUG, "bit rate: %i bits/s\n", + s->bit_rate); + av_log(s->avctx, AV_LOG_DEBUG, "downmix: %i\n", s->downmix); + av_log(s->avctx, AV_LOG_DEBUG, "dynrange: %i\n", s->dynrange); + av_log(s->avctx, AV_LOG_DEBUG, "timestamp: %i\n", s->timestamp); + av_log(s->avctx, AV_LOG_DEBUG, "aux_data: %i\n", s->aux_data); + av_log(s->avctx, AV_LOG_DEBUG, "hdcd: %i\n", s->hdcd); + av_log(s->avctx, AV_LOG_DEBUG, "ext descr: %i\n", s->ext_descr); + av_log(s->avctx, AV_LOG_DEBUG, "ext coding: %i\n", s->ext_coding); + av_log(s->avctx, AV_LOG_DEBUG, "aspf: %i\n", s->aspf); + av_log(s->avctx, AV_LOG_DEBUG, "lfe: %i\n", s->lfe); + av_log(s->avctx, AV_LOG_DEBUG, "predictor history: %i\n", + s->predictor_history); + av_log(s->avctx, AV_LOG_DEBUG, "header crc: %i\n", s->header_crc); + av_log(s->avctx, AV_LOG_DEBUG, "multirate inter: %i\n", + s->multirate_inter); + av_log(s->avctx, AV_LOG_DEBUG, "version number: %i\n", s->version); + av_log(s->avctx, AV_LOG_DEBUG, "copy history: %i\n", s->copy_history); + av_log(s->avctx, AV_LOG_DEBUG, + "source pcm resolution: %i (%i bits/sample)\n", + s->source_pcm_res, dca_bits_per_sample[s->source_pcm_res]); + av_log(s->avctx, AV_LOG_DEBUG, "front sum: %i\n", s->front_sum); + av_log(s->avctx, AV_LOG_DEBUG, "surround sum: %i\n", s->surround_sum); + av_log(s->avctx, AV_LOG_DEBUG, "dialog norm: %i\n", s->dialog_norm); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); +#endif + + /* Primary audio coding header */ + s->subframes = get_bits(&s->gb, 4) + 1; + + return dca_parse_audio_coding_header(s, 0, 0); +} + + +static inline int get_scale(GetBitContext *gb, int level, int value, int log2range) +{ + if (level < 5) { + /* huffman encoded */ + value += get_bitalloc(gb, &dca_scalefactor, level); + value = av_clip(value, 0, (1 << log2range) - 1); + } else if (level < 8) { + if (level + 1 > log2range) { + skip_bits(gb, level + 1 - log2range); + value = get_bits(gb, log2range); + } else { + value = get_bits(gb, level + 1); + } + } + return value; +} + +static int dca_subframe_header(DCAContext *s, int base_channel, int block_index) +{ + /* Primary audio coding side information */ + int j, k; + + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + + if (!base_channel) { + s->subsubframes[s->current_subframe] = get_bits(&s->gb, 2) + 1; + s->partial_samples[s->current_subframe] = get_bits(&s->gb, 3); + } + + for (j = base_channel; j < s->prim_channels; j++) { + for (k = 0; k < s->subband_activity[j]; k++) + s->prediction_mode[j][k] = get_bits(&s->gb, 1); + } + + /* Get prediction codebook */ + for (j = base_channel; j < s->prim_channels; j++) { + for (k = 0; k < s->subband_activity[j]; k++) { + if (s->prediction_mode[j][k] > 0) { + /* (Prediction coefficient VQ address) */ + s->prediction_vq[j][k] = get_bits(&s->gb, 12); + } + } + } + + /* Bit allocation index */ + for (j = base_channel; j < s->prim_channels; j++) { + for (k = 0; k < s->vq_start_subband[j]; k++) { + if (s->bitalloc_huffman[j] == 6) + s->bitalloc[j][k] = get_bits(&s->gb, 5); + else if (s->bitalloc_huffman[j] == 5) + s->bitalloc[j][k] = get_bits(&s->gb, 4); + else if (s->bitalloc_huffman[j] == 7) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid bit allocation index\n"); + return AVERROR_INVALIDDATA; + } else { + s->bitalloc[j][k] = + get_bitalloc(&s->gb, &dca_bitalloc_index, s->bitalloc_huffman[j]); + } + + if (s->bitalloc[j][k] > 26) { + av_dlog(s->avctx, "bitalloc index [%i][%i] too big (%i)\n", + j, k, s->bitalloc[j][k]); + return AVERROR_INVALIDDATA; + } + } + } + + /* Transition mode */ + for (j = base_channel; j < s->prim_channels; j++) { + for (k = 0; k < s->subband_activity[j]; k++) { + s->transition_mode[j][k] = 0; + if (s->subsubframes[s->current_subframe] > 1 && + k < s->vq_start_subband[j] && s->bitalloc[j][k] > 0) { + s->transition_mode[j][k] = + get_bitalloc(&s->gb, &dca_tmode, s->transient_huffman[j]); + } + } + } + + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + + for (j = base_channel; j < s->prim_channels; j++) { + const uint32_t *scale_table; + int scale_sum, log_size; + + memset(s->scale_factor[j], 0, + s->subband_activity[j] * sizeof(s->scale_factor[0][0][0]) * 2); + + if (s->scalefactor_huffman[j] == 6) { + scale_table = scale_factor_quant7; + log_size = 7; + } else { + scale_table = scale_factor_quant6; + log_size = 6; + } + + /* When huffman coded, only the difference is encoded */ + scale_sum = 0; + + for (k = 0; k < s->subband_activity[j]; k++) { + if (k >= s->vq_start_subband[j] || s->bitalloc[j][k] > 0) { + scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum, log_size); + s->scale_factor[j][k][0] = scale_table[scale_sum]; + } + + if (k < s->vq_start_subband[j] && s->transition_mode[j][k]) { + /* Get second scale factor */ + scale_sum = get_scale(&s->gb, s->scalefactor_huffman[j], scale_sum, log_size); + s->scale_factor[j][k][1] = scale_table[scale_sum]; + } + } + } + + /* Joint subband scale factor codebook select */ + for (j = base_channel; j < s->prim_channels; j++) { + /* Transmitted only if joint subband coding enabled */ + if (s->joint_intensity[j] > 0) + s->joint_huff[j] = get_bits(&s->gb, 3); + } + + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + + /* Scale factors for joint subband coding */ + for (j = base_channel; j < s->prim_channels; j++) { + int source_channel; + + /* Transmitted only if joint subband coding enabled */ + if (s->joint_intensity[j] > 0) { + int scale = 0; + source_channel = s->joint_intensity[j] - 1; + + /* When huffman coded, only the difference is encoded + * (is this valid as well for joint scales ???) */ + + for (k = s->subband_activity[j]; k < s->subband_activity[source_channel]; k++) { + scale = get_scale(&s->gb, s->joint_huff[j], 64 /* bias */, 7); + s->joint_scale_factor[j][k] = scale; /*joint_scale_table[scale]; */ + } + + if (!(s->debug_flag & 0x02)) { + av_log(s->avctx, AV_LOG_DEBUG, + "Joint stereo coding not supported\n"); + s->debug_flag |= 0x02; + } + } + } + + /* Stereo downmix coefficients */ + if (!base_channel && s->prim_channels > 2) { + if (s->downmix) { + for (j = base_channel; j < s->prim_channels; j++) { + s->downmix_coef[j][0] = get_bits(&s->gb, 7); + s->downmix_coef[j][1] = get_bits(&s->gb, 7); + } + } else { + int am = s->amode & DCA_CHANNEL_MASK; + if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid channel mode %d\n", am); + return AVERROR_INVALIDDATA; + } + for (j = base_channel; j < FFMIN(s->prim_channels, FF_ARRAY_ELEMS(dca_default_coeffs[am])); j++) { + s->downmix_coef[j][0] = dca_default_coeffs[am][j][0]; + s->downmix_coef[j][1] = dca_default_coeffs[am][j][1]; + } + } + } + + /* Dynamic range coefficient */ + if (!base_channel && s->dynrange) + s->dynrange_coef = get_bits(&s->gb, 8); + + /* Side information CRC check word */ + if (s->crc_present) { + get_bits(&s->gb, 16); + } + + /* + * Primary audio data arrays + */ + + /* VQ encoded high frequency subbands */ + for (j = base_channel; j < s->prim_channels; j++) + for (k = s->vq_start_subband[j]; k < s->subband_activity[j]; k++) + /* 1 vector -> 32 samples */ + s->high_freq_vq[j][k] = get_bits(&s->gb, 10); + + /* Low frequency effect data */ + if (!base_channel && s->lfe) { + int quant7; + /* LFE samples */ + int lfe_samples = 2 * s->lfe * (4 + block_index); + int lfe_end_sample = 2 * s->lfe * (4 + block_index + s->subsubframes[s->current_subframe]); + float lfe_scale; + + for (j = lfe_samples; j < lfe_end_sample; j++) { + /* Signed 8 bits int */ + s->lfe_data[j] = get_sbits(&s->gb, 8); + } + + /* Scale factor index */ + quant7 = get_bits(&s->gb, 8); + if (quant7 > 127) { + avpriv_request_sample(s->avctx, "LFEScaleIndex larger than 127"); + return AVERROR_INVALIDDATA; + } + s->lfe_scale_factor = scale_factor_quant7[quant7]; + + /* Quantization step size * scale factor */ + lfe_scale = 0.035 * s->lfe_scale_factor; + + for (j = lfe_samples; j < lfe_end_sample; j++) + s->lfe_data[j] *= lfe_scale; + } + +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "subsubframes: %i\n", + s->subsubframes[s->current_subframe]); + av_log(s->avctx, AV_LOG_DEBUG, "partial samples: %i\n", + s->partial_samples[s->current_subframe]); + + for (j = base_channel; j < s->prim_channels; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "prediction mode:"); + for (k = 0; k < s->subband_activity[j]; k++) + av_log(s->avctx, AV_LOG_DEBUG, " %i", s->prediction_mode[j][k]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + for (j = base_channel; j < s->prim_channels; j++) { + for (k = 0; k < s->subband_activity[j]; k++) + av_log(s->avctx, AV_LOG_DEBUG, + "prediction coefs: %f, %f, %f, %f\n", + (float) adpcm_vb[s->prediction_vq[j][k]][0] / 8192, + (float) adpcm_vb[s->prediction_vq[j][k]][1] / 8192, + (float) adpcm_vb[s->prediction_vq[j][k]][2] / 8192, + (float) adpcm_vb[s->prediction_vq[j][k]][3] / 8192); + } + for (j = base_channel; j < s->prim_channels; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "bitalloc index: "); + for (k = 0; k < s->vq_start_subband[j]; k++) + av_log(s->avctx, AV_LOG_DEBUG, "%2.2i ", s->bitalloc[j][k]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + for (j = base_channel; j < s->prim_channels; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "Transition mode:"); + for (k = 0; k < s->subband_activity[j]; k++) + av_log(s->avctx, AV_LOG_DEBUG, " %i", s->transition_mode[j][k]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + for (j = base_channel; j < s->prim_channels; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "Scale factor:"); + for (k = 0; k < s->subband_activity[j]; k++) { + if (k >= s->vq_start_subband[j] || s->bitalloc[j][k] > 0) + av_log(s->avctx, AV_LOG_DEBUG, " %i", s->scale_factor[j][k][0]); + if (k < s->vq_start_subband[j] && s->transition_mode[j][k]) + av_log(s->avctx, AV_LOG_DEBUG, " %i(t)", s->scale_factor[j][k][1]); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + for (j = base_channel; j < s->prim_channels; j++) { + if (s->joint_intensity[j] > 0) { + int source_channel = s->joint_intensity[j] - 1; + av_log(s->avctx, AV_LOG_DEBUG, "Joint scale factor index:\n"); + for (k = s->subband_activity[j]; k < s->subband_activity[source_channel]; k++) + av_log(s->avctx, AV_LOG_DEBUG, " %i", s->joint_scale_factor[j][k]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + } + if (!base_channel && s->prim_channels > 2 && s->downmix) { + av_log(s->avctx, AV_LOG_DEBUG, "Downmix coeffs:\n"); + for (j = 0; j < s->prim_channels; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "Channel 0, %d = %f\n", j, + dca_downmix_coeffs[s->downmix_coef[j][0]]); + av_log(s->avctx, AV_LOG_DEBUG, "Channel 1, %d = %f\n", j, + dca_downmix_coeffs[s->downmix_coef[j][1]]); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + for (j = base_channel; j < s->prim_channels; j++) + for (k = s->vq_start_subband[j]; k < s->subband_activity[j]; k++) + av_log(s->avctx, AV_LOG_DEBUG, "VQ index: %i\n", s->high_freq_vq[j][k]); + if (!base_channel && s->lfe) { + int lfe_samples = 2 * s->lfe * (4 + block_index); + int lfe_end_sample = 2 * s->lfe * (4 + block_index + s->subsubframes[s->current_subframe]); + + av_log(s->avctx, AV_LOG_DEBUG, "LFE samples:\n"); + for (j = lfe_samples; j < lfe_end_sample; j++) + av_log(s->avctx, AV_LOG_DEBUG, " %f", s->lfe_data[j]); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } +#endif + + return 0; +} + +static void qmf_32_subbands(DCAContext *s, int chans, + float samples_in[32][8], float *samples_out, + float scale) +{ + const float *prCoeff; + int i; + + int sb_act = s->subband_activity[chans]; + int subindex; + + scale *= sqrt(1 / 8.0); + + /* Select filter */ + if (!s->multirate_inter) /* Non-perfect reconstruction */ + prCoeff = fir_32bands_nonperfect; + else /* Perfect reconstruction */ + prCoeff = fir_32bands_perfect; + + for (i = sb_act; i < 32; i++) + s->raXin[i] = 0.0; + + /* Reconstructed channel sample index */ + for (subindex = 0; subindex < 8; subindex++) { + /* Load in one sample from each subband and clear inactive subbands */ + for (i = 0; i < sb_act; i++) { + unsigned sign = (i - 1) & 2; + uint32_t v = AV_RN32A(&samples_in[i][subindex]) ^ sign << 30; + AV_WN32A(&s->raXin[i], v); + } + + s->synth.synth_filter_float(&s->imdct, + s->subband_fir_hist[chans], + &s->hist_index[chans], + s->subband_fir_noidea[chans], prCoeff, + samples_out, s->raXin, scale); + samples_out += 32; + } +} + +static void lfe_interpolation_fir(DCAContext *s, int decimation_select, + int num_deci_sample, float *samples_in, + float *samples_out, float scale) +{ + /* samples_in: An array holding decimated samples. + * Samples in current subframe starts from samples_in[0], + * while samples_in[-1], samples_in[-2], ..., stores samples + * from last subframe as history. + * + * samples_out: An array holding interpolated samples + */ + + int decifactor; + const float *prCoeff; + int deciindex; + + /* Select decimation filter */ + if (decimation_select == 1) { + decifactor = 64; + prCoeff = lfe_fir_128; + } else { + decifactor = 32; + prCoeff = lfe_fir_64; + } + /* Interpolation */ + for (deciindex = 0; deciindex < num_deci_sample; deciindex++) { + s->dcadsp.lfe_fir(samples_out, samples_in, prCoeff, decifactor, scale); + samples_in++; + samples_out += 2 * decifactor; + } +} + +/* downmixing routines */ +#define MIX_REAR1(samples, s1, rs, coef) \ + samples[0][i] += samples[s1][i] * coef[rs][0]; \ + samples[1][i] += samples[s1][i] * coef[rs][1]; + +#define MIX_REAR2(samples, s1, s2, rs, coef) \ + samples[0][i] += samples[s1][i] * coef[rs][0] + samples[s2][i] * coef[rs + 1][0]; \ + samples[1][i] += samples[s1][i] * coef[rs][1] + samples[s2][i] * coef[rs + 1][1]; + +#define MIX_FRONT3(samples, coef) \ + t = samples[c][i]; \ + u = samples[l][i]; \ + v = samples[r][i]; \ + samples[0][i] = t * coef[0][0] + u * coef[1][0] + v * coef[2][0]; \ + samples[1][i] = t * coef[0][1] + u * coef[1][1] + v * coef[2][1]; + +#define DOWNMIX_TO_STEREO(op1, op2) \ + for (i = 0; i < 256; i++) { \ + op1 \ + op2 \ + } + +static void dca_downmix(float **samples, int srcfmt, + int downmix_coef[DCA_PRIM_CHANNELS_MAX][2], + const int8_t *channel_mapping) +{ + int c, l, r, sl, sr, s; + int i; + float t, u, v; + float coef[DCA_PRIM_CHANNELS_MAX][2]; + + for (i = 0; i < DCA_PRIM_CHANNELS_MAX; i++) { + coef[i][0] = dca_downmix_coeffs[downmix_coef[i][0]]; + coef[i][1] = dca_downmix_coeffs[downmix_coef[i][1]]; + } + + switch (srcfmt) { + case DCA_MONO: + case DCA_CHANNEL: + case DCA_STEREO_TOTAL: + case DCA_STEREO_SUMDIFF: + case DCA_4F2R: + av_log(NULL, AV_LOG_ERROR, "Not implemented!\n"); + break; + case DCA_STEREO: + break; + case DCA_3F: + c = channel_mapping[0]; + l = channel_mapping[1]; + r = channel_mapping[2]; + DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef), ); + break; + case DCA_2F1R: + s = channel_mapping[2]; + DOWNMIX_TO_STEREO(MIX_REAR1(samples, s, 2, coef), ); + break; + case DCA_3F1R: + c = channel_mapping[0]; + l = channel_mapping[1]; + r = channel_mapping[2]; + s = channel_mapping[3]; + DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef), + MIX_REAR1(samples, s, 3, coef)); + break; + case DCA_2F2R: + sl = channel_mapping[2]; + sr = channel_mapping[3]; + DOWNMIX_TO_STEREO(MIX_REAR2(samples, sl, sr, 2, coef), ); + break; + case DCA_3F2R: + c = channel_mapping[0]; + l = channel_mapping[1]; + r = channel_mapping[2]; + sl = channel_mapping[3]; + sr = channel_mapping[4]; + DOWNMIX_TO_STEREO(MIX_FRONT3(samples, coef), + MIX_REAR2(samples, sl, sr, 3, coef)); + break; + } +} + + +#ifndef decode_blockcodes +/* Very compact version of the block code decoder that does not use table + * look-up but is slightly slower */ +static int decode_blockcode(int code, int levels, int *values) +{ + int i; + int offset = (levels - 1) >> 1; + + for (i = 0; i < 4; i++) { + int div = FASTDIV(code, levels); + values[i] = code - offset - div * levels; + code = div; + } + + return code; +} + +static int decode_blockcodes(int code1, int code2, int levels, int *values) +{ + return decode_blockcode(code1, levels, values) | + decode_blockcode(code2, levels, values + 4); +} +#endif + +static const uint8_t abits_sizes[7] = { 7, 10, 12, 13, 15, 17, 19 }; +static const uint8_t abits_levels[7] = { 3, 5, 7, 9, 13, 17, 25 }; + +#ifndef int8x8_fmul_int32 +static inline void int8x8_fmul_int32(float *dst, const int8_t *src, int scale) +{ + float fscale = scale / 16.0; + int i; + for (i = 0; i < 8; i++) + dst[i] = src[i] * fscale; +} +#endif + +static int dca_subsubframe(DCAContext *s, int base_channel, int block_index) +{ + int k, l; + int subsubframe = s->current_subsubframe; + + const float *quant_step_table; + + /* FIXME */ + float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index]; + LOCAL_ALIGNED_16(int, block, [8]); + + /* + * Audio data + */ + + /* Select quantization step size table */ + if (s->bit_rate_index == 0x1f) + quant_step_table = lossless_quant_d; + else + quant_step_table = lossy_quant_d; + + for (k = base_channel; k < s->prim_channels; k++) { + if (get_bits_left(&s->gb) < 0) + return AVERROR_INVALIDDATA; + + for (l = 0; l < s->vq_start_subband[k]; l++) { + int m; + + /* Select the mid-tread linear quantizer */ + int abits = s->bitalloc[k][l]; + + float quant_step_size = quant_step_table[abits]; + + /* + * Determine quantization index code book and its type + */ + + /* Select quantization index code book */ + int sel = s->quant_index_huffman[k][abits]; + + /* + * Extract bits from the bit stream + */ + if (!abits) { + memset(subband_samples[k][l], 0, 8 * sizeof(subband_samples[0][0][0])); + } else { + /* Deal with transients */ + int sfi = s->transition_mode[k][l] && subsubframe >= s->transition_mode[k][l]; + float rscale = quant_step_size * s->scale_factor[k][l][sfi] * + s->scalefactor_adj[k][sel]; + + if (abits >= 11 || !dca_smpl_bitalloc[abits].vlc[sel].table) { + if (abits <= 7) { + /* Block code */ + int block_code1, block_code2, size, levels, err; + + size = abits_sizes[abits - 1]; + levels = abits_levels[abits - 1]; + + block_code1 = get_bits(&s->gb, size); + block_code2 = get_bits(&s->gb, size); + err = decode_blockcodes(block_code1, block_code2, + levels, block); + if (err) { + av_log(s->avctx, AV_LOG_ERROR, + "ERROR: block code look-up failed\n"); + return AVERROR_INVALIDDATA; + } + } else { + /* no coding */ + for (m = 0; m < 8; m++) + block[m] = get_sbits(&s->gb, abits - 3); + } + } else { + /* Huffman coded */ + for (m = 0; m < 8; m++) + block[m] = get_bitalloc(&s->gb, + &dca_smpl_bitalloc[abits], sel); + } + + s->fmt_conv.int32_to_float_fmul_scalar(subband_samples[k][l], + block, rscale, 8); + } + + /* + * Inverse ADPCM if in prediction mode + */ + if (s->prediction_mode[k][l]) { + int n; + for (m = 0; m < 8; m++) { + for (n = 1; n <= 4; n++) + if (m >= n) + subband_samples[k][l][m] += + (adpcm_vb[s->prediction_vq[k][l]][n - 1] * + subband_samples[k][l][m - n] / 8192); + else if (s->predictor_history) + subband_samples[k][l][m] += + (adpcm_vb[s->prediction_vq[k][l]][n - 1] * + s->subband_samples_hist[k][l][m - n + 4] / 8192); + } + } + } + + /* + * Decode VQ encoded high frequencies + */ + for (l = s->vq_start_subband[k]; l < s->subband_activity[k]; l++) { + /* 1 vector -> 32 samples but we only need the 8 samples + * for this subsubframe. */ + int hfvq = s->high_freq_vq[k][l]; + + if (!s->debug_flag & 0x01) { + av_log(s->avctx, AV_LOG_DEBUG, + "Stream with high frequencies VQ coding\n"); + s->debug_flag |= 0x01; + } + + int8x8_fmul_int32(subband_samples[k][l], + &high_freq_vq[hfvq][subsubframe * 8], + s->scale_factor[k][l][0]); + } + } + + /* Check for DSYNC after subsubframe */ + if (s->aspf || subsubframe == s->subsubframes[s->current_subframe] - 1) { + if (0xFFFF == get_bits(&s->gb, 16)) { /* 0xFFFF */ +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "Got subframe DSYNC\n"); +#endif + } else { + av_log(s->avctx, AV_LOG_ERROR, "Didn't get subframe DSYNC\n"); + } + } + + /* Backup predictor history for adpcm */ + for (k = base_channel; k < s->prim_channels; k++) + for (l = 0; l < s->vq_start_subband[k]; l++) + memcpy(s->subband_samples_hist[k][l], + &subband_samples[k][l][4], + 4 * sizeof(subband_samples[0][0][0])); + + return 0; +} + +static int dca_filter_channels(DCAContext *s, int block_index) +{ + float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index]; + int k; + + /* 32 subbands QMF */ + for (k = 0; k < s->prim_channels; k++) { +/* static float pcm_to_double[8] = { 32768.0, 32768.0, 524288.0, 524288.0, + 0, 8388608.0, 8388608.0 };*/ + if (s->channel_order_tab[k] >= 0) + qmf_32_subbands(s, k, subband_samples[k], + s->samples_chanptr[s->channel_order_tab[k]], + M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */); + } + + /* Down mixing */ + if (s->avctx->request_channels == 2 && s->prim_channels > 2) { + dca_downmix(s->samples_chanptr, s->amode, s->downmix_coef, s->channel_order_tab); + } + + /* Generate LFE samples for this subsubframe FIXME!!! */ + if (s->output & DCA_LFE) { + lfe_interpolation_fir(s, s->lfe, 2 * s->lfe, + s->lfe_data + 2 * s->lfe * (block_index + 4), + s->samples_chanptr[s->lfe_index], + 1.0 / (256.0 * 32768.0)); + /* Outputs 20bits pcm samples */ + } + + return 0; +} + + +static int dca_subframe_footer(DCAContext *s, int base_channel) +{ + int aux_data_count = 0, i; + + /* + * Unpack optional information + */ + + /* presumably optional information only appears in the core? */ + if (!base_channel) { + if (s->timestamp) + skip_bits_long(&s->gb, 32); + + if (s->aux_data) + aux_data_count = get_bits(&s->gb, 6); + + for (i = 0; i < aux_data_count; i++) + get_bits(&s->gb, 8); + + if (s->crc_present && (s->downmix || s->dynrange)) + get_bits(&s->gb, 16); + } + + return 0; +} + +/** + * Decode a dca frame block + * + * @param s pointer to the DCAContext + */ + +static int dca_decode_block(DCAContext *s, int base_channel, int block_index) +{ + int ret; + + /* Sanity check */ + if (s->current_subframe >= s->subframes) { + av_log(s->avctx, AV_LOG_DEBUG, "check failed: %i>%i", + s->current_subframe, s->subframes); + return AVERROR_INVALIDDATA; + } + + if (!s->current_subsubframe) { +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "DSYNC dca_subframe_header\n"); +#endif + /* Read subframe header */ + if ((ret = dca_subframe_header(s, base_channel, block_index))) + return ret; + } + + /* Read subsubframe */ +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "DSYNC dca_subsubframe\n"); +#endif + if ((ret = dca_subsubframe(s, base_channel, block_index))) + return ret; + + /* Update state */ + s->current_subsubframe++; + if (s->current_subsubframe >= s->subsubframes[s->current_subframe]) { + s->current_subsubframe = 0; + s->current_subframe++; + } + if (s->current_subframe >= s->subframes) { +#ifdef TRACE + av_log(s->avctx, AV_LOG_DEBUG, "DSYNC dca_subframe_footer\n"); +#endif + /* Read subframe footer */ + if ((ret = dca_subframe_footer(s, base_channel))) + return ret; + } + + return 0; +} + +/** + * Return the number of channels in an ExSS speaker mask (HD) + */ +static int dca_exss_mask2count(int mask) +{ + /* count bits that mean speaker pairs twice */ + return av_popcount(mask) + + av_popcount(mask & (DCA_EXSS_CENTER_LEFT_RIGHT | + DCA_EXSS_FRONT_LEFT_RIGHT | + DCA_EXSS_FRONT_HIGH_LEFT_RIGHT | + DCA_EXSS_WIDE_LEFT_RIGHT | + DCA_EXSS_SIDE_LEFT_RIGHT | + DCA_EXSS_SIDE_HIGH_LEFT_RIGHT | + DCA_EXSS_SIDE_REAR_LEFT_RIGHT | + DCA_EXSS_REAR_LEFT_RIGHT | + DCA_EXSS_REAR_HIGH_LEFT_RIGHT)); +} + +/** + * Skip mixing coefficients of a single mix out configuration (HD) + */ +static void dca_exss_skip_mix_coeffs(GetBitContext *gb, int channels, int out_ch) +{ + int i; + + for (i = 0; i < channels; i++) { + int mix_map_mask = get_bits(gb, out_ch); + int num_coeffs = av_popcount(mix_map_mask); + skip_bits_long(gb, num_coeffs * 6); + } +} + +/** + * Parse extension substream asset header (HD) + */ +static int dca_exss_parse_asset_header(DCAContext *s) +{ + int header_pos = get_bits_count(&s->gb); + int header_size; + int channels = 0; + int embedded_stereo = 0; + int embedded_6ch = 0; + int drc_code_present; + int av_uninit(extensions_mask); + int i, j; + + if (get_bits_left(&s->gb) < 16) + return -1; + + /* We will parse just enough to get to the extensions bitmask with which + * we can set the profile value. */ + + header_size = get_bits(&s->gb, 9) + 1; + skip_bits(&s->gb, 3); // asset index + + if (s->static_fields) { + if (get_bits1(&s->gb)) + skip_bits(&s->gb, 4); // asset type descriptor + if (get_bits1(&s->gb)) + skip_bits_long(&s->gb, 24); // language descriptor + + if (get_bits1(&s->gb)) { + /* How can one fit 1024 bytes of text here if the maximum value + * for the asset header size field above was 512 bytes? */ + int text_length = get_bits(&s->gb, 10) + 1; + if (get_bits_left(&s->gb) < text_length * 8) + return -1; + skip_bits_long(&s->gb, text_length * 8); // info text + } + + skip_bits(&s->gb, 5); // bit resolution - 1 + skip_bits(&s->gb, 4); // max sample rate code + channels = get_bits(&s->gb, 8) + 1; + + if (get_bits1(&s->gb)) { // 1-to-1 channels to speakers + int spkr_remap_sets; + int spkr_mask_size = 16; + int num_spkrs[7]; + + if (channels > 2) + embedded_stereo = get_bits1(&s->gb); + if (channels > 6) + embedded_6ch = get_bits1(&s->gb); + + if (get_bits1(&s->gb)) { + spkr_mask_size = (get_bits(&s->gb, 2) + 1) << 2; + skip_bits(&s->gb, spkr_mask_size); // spkr activity mask + } + + spkr_remap_sets = get_bits(&s->gb, 3); + + for (i = 0; i < spkr_remap_sets; i++) { + /* std layout mask for each remap set */ + num_spkrs[i] = dca_exss_mask2count(get_bits(&s->gb, spkr_mask_size)); + } + + for (i = 0; i < spkr_remap_sets; i++) { + int num_dec_ch_remaps = get_bits(&s->gb, 5) + 1; + if (get_bits_left(&s->gb) < 0) + return -1; + + for (j = 0; j < num_spkrs[i]; j++) { + int remap_dec_ch_mask = get_bits_long(&s->gb, num_dec_ch_remaps); + int num_dec_ch = av_popcount(remap_dec_ch_mask); + skip_bits_long(&s->gb, num_dec_ch * 5); // remap codes + } + } + + } else { + skip_bits(&s->gb, 3); // representation type + } + } + + drc_code_present = get_bits1(&s->gb); + if (drc_code_present) + get_bits(&s->gb, 8); // drc code + + if (get_bits1(&s->gb)) + skip_bits(&s->gb, 5); // dialog normalization code + + if (drc_code_present && embedded_stereo) + get_bits(&s->gb, 8); // drc stereo code + + if (s->mix_metadata && get_bits1(&s->gb)) { + skip_bits(&s->gb, 1); // external mix + skip_bits(&s->gb, 6); // post mix gain code + + if (get_bits(&s->gb, 2) != 3) // mixer drc code + skip_bits(&s->gb, 3); // drc limit + else + skip_bits(&s->gb, 8); // custom drc code + + if (get_bits1(&s->gb)) // channel specific scaling + for (i = 0; i < s->num_mix_configs; i++) + skip_bits_long(&s->gb, s->mix_config_num_ch[i] * 6); // scale codes + else + skip_bits_long(&s->gb, s->num_mix_configs * 6); // scale codes + + for (i = 0; i < s->num_mix_configs; i++) { + if (get_bits_left(&s->gb) < 0) + return -1; + dca_exss_skip_mix_coeffs(&s->gb, channels, s->mix_config_num_ch[i]); + if (embedded_6ch) + dca_exss_skip_mix_coeffs(&s->gb, 6, s->mix_config_num_ch[i]); + if (embedded_stereo) + dca_exss_skip_mix_coeffs(&s->gb, 2, s->mix_config_num_ch[i]); + } + } + + switch (get_bits(&s->gb, 2)) { + case 0: extensions_mask = get_bits(&s->gb, 12); break; + case 1: extensions_mask = DCA_EXT_EXSS_XLL; break; + case 2: extensions_mask = DCA_EXT_EXSS_LBR; break; + case 3: extensions_mask = 0; /* aux coding */ break; + } + + /* not parsed further, we were only interested in the extensions mask */ + + if (get_bits_left(&s->gb) < 0) + return -1; + + if (get_bits_count(&s->gb) - header_pos > header_size * 8) { + av_log(s->avctx, AV_LOG_WARNING, "Asset header size mismatch.\n"); + return -1; + } + skip_bits_long(&s->gb, header_pos + header_size * 8 - get_bits_count(&s->gb)); + + if (extensions_mask & DCA_EXT_EXSS_XLL) + s->profile = FF_PROFILE_DTS_HD_MA; + else if (extensions_mask & (DCA_EXT_EXSS_XBR | DCA_EXT_EXSS_X96 | + DCA_EXT_EXSS_XXCH)) + s->profile = FF_PROFILE_DTS_HD_HRA; + + if (!(extensions_mask & DCA_EXT_CORE)) + av_log(s->avctx, AV_LOG_WARNING, "DTS core detection mismatch.\n"); + if ((extensions_mask & DCA_CORE_EXTS) != s->core_ext_mask) + av_log(s->avctx, AV_LOG_WARNING, + "DTS extensions detection mismatch (%d, %d)\n", + extensions_mask & DCA_CORE_EXTS, s->core_ext_mask); + + return 0; +} + +static int dca_xbr_parse_frame(DCAContext *s) +{ + int scale_table_high[DCA_CHSET_CHANS_MAX][DCA_SUBBANDS][2]; + int active_bands[DCA_CHSETS_MAX][DCA_CHSET_CHANS_MAX]; + int abits_high[DCA_CHSET_CHANS_MAX][DCA_SUBBANDS]; + int anctemp[DCA_CHSET_CHANS_MAX]; + int chset_fsize[DCA_CHSETS_MAX]; + int n_xbr_ch[DCA_CHSETS_MAX]; + int hdr_size, num_chsets, xbr_tmode, hdr_pos; + int i, j, k, l, chset, chan_base; + + av_log(s->avctx, AV_LOG_DEBUG, "DTS-XBR: decoding XBR extension\n"); + + /* get bit position of sync header */ + hdr_pos = get_bits_count(&s->gb) - 32; + + hdr_size = get_bits(&s->gb, 6) + 1; + num_chsets = get_bits(&s->gb, 2) + 1; + + for(i = 0; i < num_chsets; i++) + chset_fsize[i] = get_bits(&s->gb, 14) + 1; + + xbr_tmode = get_bits1(&s->gb); + + for(i = 0; i < num_chsets; i++) { + n_xbr_ch[i] = get_bits(&s->gb, 3) + 1; + k = get_bits(&s->gb, 2) + 5; + for(j = 0; j < n_xbr_ch[i]; j++) + active_bands[i][j] = get_bits(&s->gb, k) + 1; + } + + /* skip to the end of the header */ + i = get_bits_count(&s->gb); + if(hdr_pos + hdr_size * 8 > i) + skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i); + + /* loop over the channel data sets */ + /* only decode as many channels as we've decoded base data for */ + for(chset = 0, chan_base = 0; + chset < num_chsets && chan_base + n_xbr_ch[chset] <= s->prim_channels; + chan_base += n_xbr_ch[chset++]) { + int start_posn = get_bits_count(&s->gb); + int subsubframe = 0; + int subframe = 0; + + /* loop over subframes */ + for (k = 0; k < (s->sample_blocks / 8); k++) { + /* parse header if we're on first subsubframe of a block */ + if(subsubframe == 0) { + /* Parse subframe header */ + for(i = 0; i < n_xbr_ch[chset]; i++) { + anctemp[i] = get_bits(&s->gb, 2) + 2; + } + + for(i = 0; i < n_xbr_ch[chset]; i++) { + get_array(&s->gb, abits_high[i], active_bands[chset][i], anctemp[i]); + } + + for(i = 0; i < n_xbr_ch[chset]; i++) { + anctemp[i] = get_bits(&s->gb, 3); + if(anctemp[i] < 1) { + av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: SYNC ERROR\n"); + return AVERROR_INVALIDDATA; + } + } + + /* generate scale factors */ + for(i = 0; i < n_xbr_ch[chset]; i++) { + const uint32_t *scale_table; + int nbits; + + if (s->scalefactor_huffman[chan_base+i] == 6) { + scale_table = scale_factor_quant7; + } else { + scale_table = scale_factor_quant6; + } + + nbits = anctemp[i]; + + for(j = 0; j < active_bands[chset][i]; j++) { + if(abits_high[i][j] > 0) { + scale_table_high[i][j][0] = + scale_table[get_bits(&s->gb, nbits)]; + + if(xbr_tmode && s->transition_mode[i][j]) { + scale_table_high[i][j][1] = + scale_table[get_bits(&s->gb, nbits)]; + } + } + } + } + } + + /* decode audio array for this block */ + for(i = 0; i < n_xbr_ch[chset]; i++) { + for(j = 0; j < active_bands[chset][i]; j++) { + const int xbr_abits = abits_high[i][j]; + const float quant_step_size = lossless_quant_d[xbr_abits]; + const int sfi = xbr_tmode && s->transition_mode[i][j] && subsubframe >= s->transition_mode[i][j]; + const float rscale = quant_step_size * scale_table_high[i][j][sfi]; + float *subband_samples = s->subband_samples[k][chan_base+i][j]; + int block[8]; + + if(xbr_abits <= 0) + continue; + + if(xbr_abits > 7) { + get_array(&s->gb, block, 8, xbr_abits - 3); + } else { + int block_code1, block_code2, size, levels, err; + + size = abits_sizes[xbr_abits - 1]; + levels = abits_levels[xbr_abits - 1]; + + block_code1 = get_bits(&s->gb, size); + block_code2 = get_bits(&s->gb, size); + err = decode_blockcodes(block_code1, block_code2, + levels, block); + if (err) { + av_log(s->avctx, AV_LOG_ERROR, + "ERROR: DTS-XBR: block code look-up failed\n"); + return AVERROR_INVALIDDATA; + } + } + + /* scale & sum into subband */ + for(l = 0; l < 8; l++) + subband_samples[l] += (float)block[l] * rscale; + } + } + + /* check DSYNC marker */ + if(s->aspf || subsubframe == s->subsubframes[subframe] - 1) { + if(get_bits(&s->gb, 16) != 0xffff) { + av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: Didn't get subframe DSYNC\n"); + return AVERROR_INVALIDDATA; + } + } + + /* advance sub-sub-frame index */ + if(++subsubframe >= s->subsubframes[subframe]) { + subsubframe = 0; + subframe++; + } + } + + /* skip to next channel set */ + i = get_bits_count(&s->gb); + if(start_posn + chset_fsize[chset] * 8 != i) { + j = start_posn + chset_fsize[chset] * 8 - i; + if(j < 0 || j >= 8) + av_log(s->avctx, AV_LOG_ERROR, "DTS-XBR: end of channel set," + " skipping further than expected (%d bits)\n", j); + skip_bits_long(&s->gb, j); + } + } + + return 0; +} + +/* parse initial header for XXCH and dump details */ +static int dca_xxch_decode_frame(DCAContext *s) +{ + int hdr_size, spkmsk_bits, num_chsets, core_spk, hdr_pos; + int i, chset, base_channel, chstart, fsize[8]; + + /* assume header word has already been parsed */ + hdr_pos = get_bits_count(&s->gb) - 32; + hdr_size = get_bits(&s->gb, 6) + 1; + /*chhdr_crc =*/ skip_bits1(&s->gb); + spkmsk_bits = get_bits(&s->gb, 5) + 1; + num_chsets = get_bits(&s->gb, 2) + 1; + + for (i = 0; i < num_chsets; i++) + fsize[i] = get_bits(&s->gb, 14) + 1; + + core_spk = get_bits(&s->gb, spkmsk_bits); + s->xxch_core_spkmask = core_spk; + s->xxch_nbits_spk_mask = spkmsk_bits; + s->xxch_dmix_embedded = 0; + + /* skip to the end of the header */ + i = get_bits_count(&s->gb); + if (hdr_pos + hdr_size * 8 > i) + skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i); + + for (chset = 0; chset < num_chsets; chset++) { + chstart = get_bits_count(&s->gb); + base_channel = s->prim_channels; + s->xxch_chset = chset; + + /* XXCH and Core headers differ, see 6.4.2 "XXCH Channel Set Header" vs. + 5.3.2 "Primary Audio Coding Header", DTS Spec 1.3.1 */ + dca_parse_audio_coding_header(s, base_channel, 1); + + /* decode channel data */ + for (i = 0; i < (s->sample_blocks / 8); i++) { + if (dca_decode_block(s, base_channel, i)) { + av_log(s->avctx, AV_LOG_ERROR, + "Error decoding DTS-XXCH extension\n"); + continue; + } + } + + /* skip to end of this section */ + i = get_bits_count(&s->gb); + if (chstart + fsize[chset] * 8 > i) + skip_bits_long(&s->gb, chstart + fsize[chset] * 8 - i); + } + s->xxch_chset = num_chsets; + + return 0; +} + +/** + * Parse extension substream header (HD) + */ +static void dca_exss_parse_header(DCAContext *s) +{ + int asset_size[8]; + int ss_index; + int blownup; + int num_audiop = 1; + int num_assets = 1; + int active_ss_mask[8]; + int i, j; + int start_posn; + int hdrsize; + uint32_t mkr; + + if (get_bits_left(&s->gb) < 52) + return; + + start_posn = get_bits_count(&s->gb) - 32; + + skip_bits(&s->gb, 8); // user data + ss_index = get_bits(&s->gb, 2); + + blownup = get_bits1(&s->gb); + hdrsize = get_bits(&s->gb, 8 + 4 * blownup) + 1; // header_size + skip_bits(&s->gb, 16 + 4 * blownup); // hd_size + + s->static_fields = get_bits1(&s->gb); + if (s->static_fields) { + skip_bits(&s->gb, 2); // reference clock code + skip_bits(&s->gb, 3); // frame duration code + + if (get_bits1(&s->gb)) + skip_bits_long(&s->gb, 36); // timestamp + + /* a single stream can contain multiple audio assets that can be + * combined to form multiple audio presentations */ + + num_audiop = get_bits(&s->gb, 3) + 1; + if (num_audiop > 1) { + avpriv_request_sample(s->avctx, + "Multiple DTS-HD audio presentations"); + /* ignore such streams for now */ + return; + } + + num_assets = get_bits(&s->gb, 3) + 1; + if (num_assets > 1) { + avpriv_request_sample(s->avctx, "Multiple DTS-HD audio assets"); + /* ignore such streams for now */ + return; + } + + for (i = 0; i < num_audiop; i++) + active_ss_mask[i] = get_bits(&s->gb, ss_index + 1); + + for (i = 0; i < num_audiop; i++) + for (j = 0; j <= ss_index; j++) + if (active_ss_mask[i] & (1 << j)) + skip_bits(&s->gb, 8); // active asset mask + + s->mix_metadata = get_bits1(&s->gb); + if (s->mix_metadata) { + int mix_out_mask_size; + + skip_bits(&s->gb, 2); // adjustment level + mix_out_mask_size = (get_bits(&s->gb, 2) + 1) << 2; + s->num_mix_configs = get_bits(&s->gb, 2) + 1; + + for (i = 0; i < s->num_mix_configs; i++) { + int mix_out_mask = get_bits(&s->gb, mix_out_mask_size); + s->mix_config_num_ch[i] = dca_exss_mask2count(mix_out_mask); + } + } + } + + for (i = 0; i < num_assets; i++) + asset_size[i] = get_bits_long(&s->gb, 16 + 4 * blownup); + + for (i = 0; i < num_assets; i++) { + if (dca_exss_parse_asset_header(s)) + return; + } + + /* not parsed further, we were only interested in the extensions mask + * from the asset header */ + + if (num_assets > 0) { + j = get_bits_count(&s->gb); + if (start_posn + hdrsize * 8 > j) + skip_bits_long(&s->gb, start_posn + hdrsize * 8 - j); + + for (i = 0; i < num_assets; i++) { + start_posn = get_bits_count(&s->gb); + mkr = get_bits_long(&s->gb, 32); + + /* parse extensions that we know about */ + if (mkr == 0x655e315e) { + dca_xbr_parse_frame(s); + } else if (mkr == 0x47004a03) { + dca_xxch_decode_frame(s); + s->core_ext_mask |= DCA_EXT_XXCH; /* xxx use for chan reordering */ + } else { + av_log(s->avctx, AV_LOG_DEBUG, + "DTS-ExSS: unknown marker = 0x%08x\n", mkr); + } + + /* skip to end of block */ + j = get_bits_count(&s->gb); + if (start_posn + asset_size[i] * 8 > j) + skip_bits_long(&s->gb, start_posn + asset_size[i] * 8 - j); + } + } +} + +/** + * Main frame decoding function + * FIXME add arguments + */ +static int dca_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int channel_mask; + int channel_layout; + int lfe_samples; + int num_core_channels = 0; + int i, ret; + float **samples_flt; + float *src_chan; + float *dst_chan; + DCAContext *s = avctx->priv_data; + int core_ss_end; + int channels, full_channels; + float scale; + int achan; + int chset; + int mask; + int lavc; + int posn; + int j, k; + int endch; + + s->xch_present = 0; + + s->dca_buffer_size = ff_dca_convert_bitstream(buf, buf_size, s->dca_buffer, + DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE); + if (s->dca_buffer_size == AVERROR_INVALIDDATA) { + av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n"); + return AVERROR_INVALIDDATA; + } + + init_get_bits(&s->gb, s->dca_buffer, s->dca_buffer_size * 8); + if ((ret = dca_parse_frame_header(s)) < 0) { + //seems like the frame is corrupt, try with the next one + return ret; + } + //set AVCodec values with parsed data + avctx->sample_rate = s->sample_rate; + avctx->bit_rate = s->bit_rate; + + s->profile = FF_PROFILE_DTS; + + for (i = 0; i < (s->sample_blocks / 8); i++) { + if ((ret = dca_decode_block(s, 0, i))) { + av_log(avctx, AV_LOG_ERROR, "error decoding block\n"); + return ret; + } + } + + /* record number of core channels incase less than max channels are requested */ + num_core_channels = s->prim_channels; + + if (s->ext_coding) + s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr]; + else + s->core_ext_mask = 0; + + core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8; + + /* only scan for extensions if ext_descr was unknown or indicated a + * supported XCh extension */ + if (s->core_ext_mask < 0 || s->core_ext_mask & (DCA_EXT_XCH | DCA_EXT_XXCH)) { + + /* if ext_descr was unknown, clear s->core_ext_mask so that the + * extensions scan can fill it up */ + s->core_ext_mask = FFMAX(s->core_ext_mask, 0); + + /* extensions start at 32-bit boundaries into bitstream */ + skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31); + + while (core_ss_end - get_bits_count(&s->gb) >= 32) { + uint32_t bits = get_bits_long(&s->gb, 32); + + switch (bits) { + case 0x5a5a5a5a: { + int ext_amode, xch_fsize; + + s->xch_base_channel = s->prim_channels; + + /* validate sync word using XCHFSIZE field */ + xch_fsize = show_bits(&s->gb, 10); + if ((s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + xch_fsize) && + (s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + xch_fsize + 1)) + continue; + + /* skip length-to-end-of-frame field for the moment */ + skip_bits(&s->gb, 10); + + s->core_ext_mask |= DCA_EXT_XCH; + + /* extension amode(number of channels in extension) should be 1 */ + /* AFAIK XCh is not used for more channels */ + if ((ext_amode = get_bits(&s->gb, 4)) != 1) { + av_log(avctx, AV_LOG_ERROR, "XCh extension amode %d not" + " supported!\n", ext_amode); + continue; + } + + if (s->xch_base_channel < 2) { + avpriv_request_sample(avctx, "XCh with fewer than 2 base channels"); + continue; + } + + /* much like core primary audio coding header */ + dca_parse_audio_coding_header(s, s->xch_base_channel, 0); + + for (i = 0; i < (s->sample_blocks / 8); i++) + if ((ret = dca_decode_block(s, s->xch_base_channel, i))) { + av_log(avctx, AV_LOG_ERROR, "error decoding XCh extension\n"); + continue; + } + + s->xch_present = 1; + break; + } + case 0x47004a03: + /* XXCh: extended channels */ + /* usually found either in core or HD part in DTS-HD HRA streams, + * but not in DTS-ES which contains XCh extensions instead */ + s->core_ext_mask |= DCA_EXT_XXCH; + dca_xxch_decode_frame(s); + break; + + case 0x1d95f262: { + int fsize96 = show_bits(&s->gb, 12) + 1; + if (s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + fsize96) + continue; + + av_log(avctx, AV_LOG_DEBUG, "X96 extension found at %d bits\n", + get_bits_count(&s->gb)); + skip_bits(&s->gb, 12); + av_log(avctx, AV_LOG_DEBUG, "FSIZE96 = %d bytes\n", fsize96); + av_log(avctx, AV_LOG_DEBUG, "REVNO = %d\n", get_bits(&s->gb, 4)); + + s->core_ext_mask |= DCA_EXT_X96; + break; + } + } + + skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31); + } + } else { + /* no supported extensions, skip the rest of the core substream */ + skip_bits_long(&s->gb, core_ss_end - get_bits_count(&s->gb)); + } + + if (s->core_ext_mask & DCA_EXT_X96) + s->profile = FF_PROFILE_DTS_96_24; + else if (s->core_ext_mask & (DCA_EXT_XCH | DCA_EXT_XXCH)) + s->profile = FF_PROFILE_DTS_ES; + + /* check for ExSS (HD part) */ + if (s->dca_buffer_size - s->frame_size > 32 && + get_bits_long(&s->gb, 32) == DCA_HD_MARKER) + dca_exss_parse_header(s); + + avctx->profile = s->profile; + + full_channels = channels = s->prim_channels + !!s->lfe; + + /* If we have XXCH then the channel layout is managed differently */ + /* note that XLL will also have another way to do things */ + if (!(s->core_ext_mask & DCA_EXT_XXCH) + || (s->core_ext_mask & DCA_EXT_XXCH && avctx->request_channels > 0 + && avctx->request_channels + < num_core_channels + !!s->lfe + s->xxch_chset_nch[0])) + { /* xxx should also do MA extensions */ + if (s->amode < 16) { + avctx->channel_layout = dca_core_channel_layout[s->amode]; + + if (s->xch_present && (!avctx->request_channels || + avctx->request_channels + > num_core_channels + !!s->lfe)) { + avctx->channel_layout |= AV_CH_BACK_CENTER; + if (s->lfe) { + avctx->channel_layout |= AV_CH_LOW_FREQUENCY; + s->channel_order_tab = dca_channel_reorder_lfe_xch[s->amode]; + } else { + s->channel_order_tab = dca_channel_reorder_nolfe_xch[s->amode]; + } + if (s->channel_order_tab[s->xch_base_channel] < 0) + return AVERROR_INVALIDDATA; + } else { + channels = num_core_channels + !!s->lfe; + s->xch_present = 0; /* disable further xch processing */ + if (s->lfe) { + avctx->channel_layout |= AV_CH_LOW_FREQUENCY; + s->channel_order_tab = dca_channel_reorder_lfe[s->amode]; + } else + s->channel_order_tab = dca_channel_reorder_nolfe[s->amode]; + } + + if (channels > !!s->lfe && + s->channel_order_tab[channels - 1 - !!s->lfe] < 0) + return AVERROR_INVALIDDATA; + + if (av_get_channel_layout_nb_channels(avctx->channel_layout) != channels) { + av_log(avctx, AV_LOG_ERROR, "Number of channels %d mismatches layout %d\n", channels, av_get_channel_layout_nb_channels(avctx->channel_layout)); + return AVERROR_INVALIDDATA; + } + + if (avctx->request_channels == 2 && s->prim_channels > 2) { + channels = 2; + s->output = DCA_STEREO; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } + else if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) { + static const int8_t dca_channel_order_native[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + s->channel_order_tab = dca_channel_order_native; + } + s->lfe_index = dca_lfe_index[s->amode]; + } else { + av_log(avctx, AV_LOG_ERROR, + "Non standard configuration %d !\n", s->amode); + return AVERROR_INVALIDDATA; + } + + s->xxch_dmix_embedded = 0; + } else { + /* we only get here if an XXCH channel set can be added to the mix */ + channel_mask = s->xxch_core_spkmask; + + if (avctx->request_channels > 0 + && avctx->request_channels < s->prim_channels) { + channels = num_core_channels + !!s->lfe; + for (i = 0; i < s->xxch_chset && channels + s->xxch_chset_nch[i] + <= avctx->request_channels; i++) { + channels += s->xxch_chset_nch[i]; + channel_mask |= s->xxch_spk_masks[i]; + } + } else { + channels = s->prim_channels + !!s->lfe; + for (i = 0; i < s->xxch_chset; i++) { + channel_mask |= s->xxch_spk_masks[i]; + } + } + + /* Given the DTS spec'ed channel mask, generate an avcodec version */ + channel_layout = 0; + for (i = 0; i < s->xxch_nbits_spk_mask; ++i) { + if (channel_mask & (1 << i)) { + channel_layout |= map_xxch_to_native[i]; + } + } + + /* make sure that we have managed to get equivelant dts/avcodec channel + * masks in some sense -- unfortunately some channels could overlap */ + if (av_popcount(channel_mask) != av_popcount(channel_layout)) { + av_log(avctx, AV_LOG_DEBUG, + "DTS-XXCH: Inconsistant avcodec/dts channel layouts\n"); + return AVERROR_INVALIDDATA; + } + + avctx->channel_layout = channel_layout; + + if (!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE)) { + /* Estimate DTS --> avcodec ordering table */ + for (chset = -1, j = 0; chset < s->xxch_chset; ++chset) { + mask = chset >= 0 ? s->xxch_spk_masks[chset] + : s->xxch_core_spkmask; + for (i = 0; i < s->xxch_nbits_spk_mask; i++) { + if (mask & ~(DCA_XXCH_LFE1 | DCA_XXCH_LFE2) & (1 << i)) { + lavc = map_xxch_to_native[i]; + posn = av_popcount(channel_layout & (lavc - 1)); + s->xxch_order_tab[j++] = posn; + } + } + } + + s->lfe_index = av_popcount(channel_layout & (AV_CH_LOW_FREQUENCY-1)); + } else { /* native ordering */ + for (i = 0; i < channels; i++) + s->xxch_order_tab[i] = i; + + s->lfe_index = channels - 1; + } + + s->channel_order_tab = s->xxch_order_tab; + } + + if (avctx->channels != channels) { + if (avctx->channels) + av_log(avctx, AV_LOG_INFO, "Number of channels changed in DCA decoder (%d -> %d)\n", avctx->channels, channels); + avctx->channels = channels; + } + + /* get output buffer */ + frame->nb_samples = 256 * (s->sample_blocks / 8); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples_flt = (float **)frame->extended_data; + + /* allocate buffer for extra channels if downmixing */ + if (avctx->channels < full_channels) { + ret = av_samples_get_buffer_size(NULL, full_channels - channels, + frame->nb_samples, + avctx->sample_fmt, 0); + if (ret < 0) + return ret; + + av_fast_malloc(&s->extra_channels_buffer, + &s->extra_channels_buffer_size, ret); + if (!s->extra_channels_buffer) + return AVERROR(ENOMEM); + + ret = av_samples_fill_arrays((uint8_t **)s->extra_channels, NULL, + s->extra_channels_buffer, + full_channels - channels, + frame->nb_samples, avctx->sample_fmt, 0); + if (ret < 0) + return ret; + } + + /* filter to get final output */ + for (i = 0; i < (s->sample_blocks / 8); i++) { + int ch; + + for (ch = 0; ch < channels; ch++) + s->samples_chanptr[ch] = samples_flt[ch] + i * 256; + for (; ch < full_channels; ch++) + s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * 256; + + dca_filter_channels(s, i); + + /* If this was marked as a DTS-ES stream we need to subtract back- */ + /* channel from SL & SR to remove matrixed back-channel signal */ + if ((s->source_pcm_res & 1) && s->xch_present) { + float *back_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]]; + float *lt_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]]; + float *rt_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]]; + s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256); + s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256); + } + + /* If stream contains XXCH, we might need to undo an embedded downmix */ + if (s->xxch_dmix_embedded) { + /* Loop over channel sets in turn */ + ch = num_core_channels; + for (chset = 0; chset < s->xxch_chset; chset++) { + endch = ch + s->xxch_chset_nch[chset]; + mask = s->xxch_dmix_embedded; + + /* undo downmix */ + for (j = ch; j < endch; j++) { + if (mask & (1 << j)) { /* this channel has been mixed-out */ + src_chan = s->samples_chanptr[s->channel_order_tab[j]]; + for (k = 0; k < endch; k++) { + achan = s->channel_order_tab[k]; + scale = s->xxch_dmix_coeff[j][k]; + if (scale != 0.0) { + dst_chan = s->samples_chanptr[achan]; + s->fdsp.vector_fmac_scalar(dst_chan, src_chan, + -scale, 256); + } + } + } + } + + /* if a downmix has been embedded then undo the pre-scaling */ + if ((mask & (1 << ch)) && s->xxch_dmix_sf[chset] != 1.0f) { + scale = s->xxch_dmix_sf[chset]; + + for (j = 0; j < ch; j++) { + src_chan = s->samples_chanptr[s->channel_order_tab[j]]; + for (k = 0; k < 256; k++) + src_chan[k] *= scale; + } + + /* LFE channel is always part of core, scale if it exists */ + if (s->lfe) { + src_chan = s->samples_chanptr[s->lfe_index]; + for (k = 0; k < 256; k++) + src_chan[k] *= scale; + } + } + + ch = endch; + } + + } + } + + /* update lfe history */ + lfe_samples = 2 * s->lfe * (s->sample_blocks / 8); + for (i = 0; i < 2 * s->lfe * 4; i++) + s->lfe_data[i] = s->lfe_data[i + lfe_samples]; + + *got_frame_ptr = 1; + + return buf_size; +} + + + +/** + * DCA initialization + * + * @param avctx pointer to the AVCodecContext + */ + +static av_cold int dca_decode_init(AVCodecContext *avctx) +{ + DCAContext *s = avctx->priv_data; + + s->avctx = avctx; + dca_init_vlcs(); + + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_mdct_init(&s->imdct, 6, 1, 1.0); + ff_synth_filter_init(&s->synth); + ff_dcadsp_init(&s->dcadsp); + ff_fmt_convert_init(&s->fmt_conv, avctx); + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + /* allow downmixing to stereo */ + if (avctx->channels > 0 && avctx->request_channels < avctx->channels && + avctx->request_channels == 2) { + avctx->channels = avctx->request_channels; + } + + return 0; +} + +static av_cold int dca_decode_end(AVCodecContext *avctx) +{ + DCAContext *s = avctx->priv_data; + ff_mdct_end(&s->imdct); + av_freep(&s->extra_channels_buffer); + return 0; +} + +static const AVProfile profiles[] = { + { FF_PROFILE_DTS, "DTS" }, + { FF_PROFILE_DTS_ES, "DTS-ES" }, + { FF_PROFILE_DTS_96_24, "DTS 96/24" }, + { FF_PROFILE_DTS_HD_HRA, "DTS-HD HRA" }, + { FF_PROFILE_DTS_HD_MA, "DTS-HD MA" }, + { FF_PROFILE_UNKNOWN }, +}; + +AVCodec ff_dca_decoder = { + .name = "dca", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DTS, + .priv_data_size = sizeof(DCAContext), + .init = dca_decode_init, + .decode = dca_decode_frame, + .close = dca_decode_end, + .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), + .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .profiles = NULL_IF_CONFIG_SMALL(profiles), +}; diff --git a/ffmpeg/libavcodec/dcadsp.c b/ffmpeg/libavcodec/dcadsp.c new file mode 100644 index 0000000..dd4994d --- /dev/null +++ b/ffmpeg/libavcodec/dcadsp.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004 Gildas Bazin + * Copyright (c) 2010 Mans Rullgard + * + * 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 "config.h" +#include "dcadsp.h" + +static void dca_lfe_fir_c(float *out, const float *in, const float *coefs, + int decifactor, float scale) +{ + float *out2 = out + decifactor; + const float *cf0 = coefs; + const float *cf1 = coefs + 256; + int j, k; + + /* One decimated sample generates 2*decifactor interpolated ones */ + for (k = 0; k < decifactor; k++) { + float v0 = 0.0; + float v1 = 0.0; + for (j = 0; j < 256 / decifactor; j++) { + float s = in[-j]; + v0 += s * *cf0++; + v1 += s * *--cf1; + } + *out++ = v0 * scale; + *out2++ = v1 * scale; + } +} + +void ff_dcadsp_init(DCADSPContext *s) +{ + s->lfe_fir = dca_lfe_fir_c; + if (ARCH_ARM) ff_dcadsp_init_arm(s); +} diff --git a/ffmpeg/libavcodec/dcadsp.h b/ffmpeg/libavcodec/dcadsp.h new file mode 100644 index 0000000..bb157f7 --- /dev/null +++ b/ffmpeg/libavcodec/dcadsp.h @@ -0,0 +1,30 @@ +/* + * 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 + */ + +#ifndef AVCODEC_DCADSP_H +#define AVCODEC_DCADSP_H + +typedef struct DCADSPContext { + void (*lfe_fir)(float *out, const float *in, const float *coefs, + int decifactor, float scale); +} DCADSPContext; + +void ff_dcadsp_init(DCADSPContext *s); +void ff_dcadsp_init_arm(DCADSPContext *s); + +#endif /* AVCODEC_DCADSP_H */ diff --git a/ffmpeg/libavcodec/dcaenc.c b/ffmpeg/libavcodec/dcaenc.c new file mode 100644 index 0000000..4799ef4 --- /dev/null +++ b/ffmpeg/libavcodec/dcaenc.c @@ -0,0 +1,602 @@ +/* + * DCA encoder + * Copyright (C) 2008 Alexander E. Patrakov + * 2010 Benjamin Larsson + * 2011 Xiang Wang + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +#include "put_bits.h" +#include "dcaenc.h" +#include "dcadata.h" +#include "dca.h" + +#undef NDEBUG + +#define MAX_CHANNELS 6 +#define DCA_SUBBANDS_32 32 +#define DCA_MAX_FRAME_SIZE 16383 +#define DCA_HEADER_SIZE 13 + +#define DCA_SUBBANDS 32 ///< Subband activity count +#define QUANTIZER_BITS 16 +#define SUBFRAMES 1 +#define SUBSUBFRAMES 4 +#define PCM_SAMPLES (SUBFRAMES*SUBSUBFRAMES*8) +#define LFE_BITS 8 +#define LFE_INTERPOLATION 64 +#define LFE_PRESENT 2 +#define LFE_MISSING 0 + +static const int8_t dca_lfe_index[] = { + 1,2,2,2,2,3,2,3,2,3,2,3,1,3,2,3 +}; + +static const int8_t dca_channel_reorder_lfe[][9] = { + { 0, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 0, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, 2, -1, -1, -1, -1, -1 }, + { 1, 2, 0, -1, 3, -1, -1, -1, -1 }, + { 0, 1, -1, 2, 3, -1, -1, -1, -1 }, + { 1, 2, 0, -1, 3, 4, -1, -1, -1 }, + { 2, 3, -1, 0, 1, 4, 5, -1, -1 }, + { 1, 2, 0, -1, 3, 4, 5, -1, -1 }, + { 0, -1, 4, 5, 2, 3, 1, -1, -1 }, + { 3, 4, 1, -1, 0, 2, 5, 6, -1 }, + { 2, 3, -1, 5, 7, 0, 1, 4, 6 }, + { 3, 4, 1, -1, 0, 2, 5, 7, 6 }, +}; + +static const int8_t dca_channel_reorder_nolfe[][9] = { + { 0, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 0, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 2, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 0, 3, -1, -1, -1, -1, -1 }, + { 0, 1, 2, 3, -1, -1, -1, -1, -1 }, + { 1, 2, 0, 3, 4, -1, -1, -1, -1 }, + { 2, 3, 0, 1, 4, 5, -1, -1, -1 }, + { 1, 2, 0, 3, 4, 5, -1, -1, -1 }, + { 0, 4, 5, 2, 3, 1, -1, -1, -1 }, + { 3, 4, 1, 0, 2, 5, 6, -1, -1 }, + { 2, 3, 5, 7, 0, 1, 4, 6, -1 }, + { 3, 4, 1, 0, 2, 5, 7, 6, -1 }, +}; + +typedef struct { + PutBitContext pb; + int32_t history[MAX_CHANNELS][512]; /* This is a circular buffer */ + int start[MAX_CHANNELS]; + int frame_size; + int prim_channels; + int lfe_channel; + int sample_rate_code; + int scale_factor[MAX_CHANNELS][DCA_SUBBANDS_32]; + int lfe_scale_factor; + int lfe_data[SUBFRAMES*SUBSUBFRAMES*4]; + + int a_mode; ///< audio channels arrangement + int num_channel; + int lfe_state; + int lfe_offset; + const int8_t *channel_order_tab; ///< channel reordering table, lfe and non lfe + + int32_t pcm[FFMAX(LFE_INTERPOLATION, DCA_SUBBANDS_32)]; + int32_t subband[PCM_SAMPLES][MAX_CHANNELS][DCA_SUBBANDS_32]; /* [sample][channel][subband] */ +} DCAContext; + +static int32_t cos_table[128]; + +static inline int32_t mul32(int32_t a, int32_t b) +{ + int64_t r = (int64_t) a * b; + /* round the result before truncating - improves accuracy */ + return (r + 0x80000000) >> 32; +} + +/* Integer version of the cosine modulated Pseudo QMF */ + +static void qmf_init(void) +{ + int i; + int32_t c[17], s[17]; + s[0] = 0; /* sin(index * PI / 64) * 0x7fffffff */ + c[0] = 0x7fffffff; /* cos(index * PI / 64) * 0x7fffffff */ + + for (i = 1; i <= 16; i++) { + s[i] = 2 * (mul32(c[i - 1], 105372028) + mul32(s[i - 1], 2144896908)); + c[i] = 2 * (mul32(c[i - 1], 2144896908) - mul32(s[i - 1], 105372028)); + } + + for (i = 0; i < 16; i++) { + cos_table[i ] = c[i] >> 3; /* avoid output overflow */ + cos_table[i + 16] = s[16 - i] >> 3; + cos_table[i + 32] = -s[i] >> 3; + cos_table[i + 48] = -c[16 - i] >> 3; + cos_table[i + 64] = -c[i] >> 3; + cos_table[i + 80] = -s[16 - i] >> 3; + cos_table[i + 96] = s[i] >> 3; + cos_table[i + 112] = c[16 - i] >> 3; + } +} + +static int32_t band_delta_factor(int band, int sample_num) +{ + int index = band * (2 * sample_num + 1); + if (band == 0) + return 0x07ffffff; + else + return cos_table[index & 127]; +} + +static void add_new_samples(DCAContext *c, const int32_t *in, + int count, int channel) +{ + int i; + + /* Place new samples into the history buffer */ + for (i = 0; i < count; i++) { + c->history[channel][c->start[channel] + i] = in[i]; + av_assert0(c->start[channel] + i < 512); + } + c->start[channel] += count; + if (c->start[channel] == 512) + c->start[channel] = 0; + av_assert0(c->start[channel] < 512); +} + +static void qmf_decompose(DCAContext *c, int32_t in[32], int32_t out[32], + int channel) +{ + int band, i, j, k; + int32_t resp; + int32_t accum[DCA_SUBBANDS_32] = {0}; + + add_new_samples(c, in, DCA_SUBBANDS_32, channel); + + /* Calculate the dot product of the signal with the (possibly inverted) + reference decoder's response to this vector: + (0.0, 0.0, ..., 0.0, -1.0, 1.0, 0.0, ..., 0.0) + so that -1.0 cancels 1.0 from the previous step */ + + for (k = 48, j = 0, i = c->start[channel]; i < 512; k++, j++, i++) + accum[(k & 32) ? (31 - (k & 31)) : (k & 31)] += mul32(c->history[channel][i], UnQMF[j]); + for (i = 0; i < c->start[channel]; k++, j++, i++) + accum[(k & 32) ? (31 - (k & 31)) : (k & 31)] += mul32(c->history[channel][i], UnQMF[j]); + + resp = 0; + /* TODO: implement FFT instead of this naive calculation */ + for (band = 0; band < DCA_SUBBANDS_32; band++) { + for (j = 0; j < 32; j++) + resp += mul32(accum[j], band_delta_factor(band, j)); + + out[band] = (band & 2) ? (-resp) : resp; + } +} + +static int32_t lfe_fir_64i[512]; +static int lfe_downsample(DCAContext *c, int32_t in[LFE_INTERPOLATION]) +{ + int i, j; + int channel = c->prim_channels; + int32_t accum = 0; + + add_new_samples(c, in, LFE_INTERPOLATION, channel); + for (i = c->start[channel], j = 0; i < 512; i++, j++) + accum += mul32(c->history[channel][i], lfe_fir_64i[j]); + for (i = 0; i < c->start[channel]; i++, j++) + accum += mul32(c->history[channel][i], lfe_fir_64i[j]); + return accum; +} + +static void init_lfe_fir(void) +{ + static int initialized = 0; + int i; + if (initialized) + return; + + for (i = 0; i < 512; i++) + lfe_fir_64i[i] = lfe_fir_64[i] * (1 << 25); //float -> int32_t + initialized = 1; +} + +static void put_frame_header(DCAContext *c) +{ + /* SYNC */ + put_bits(&c->pb, 16, 0x7ffe); + put_bits(&c->pb, 16, 0x8001); + + /* Frame type: normal */ + put_bits(&c->pb, 1, 1); + + /* Deficit sample count: none */ + put_bits(&c->pb, 5, 31); + + /* CRC is not present */ + put_bits(&c->pb, 1, 0); + + /* Number of PCM sample blocks */ + put_bits(&c->pb, 7, PCM_SAMPLES-1); + + /* Primary frame byte size */ + put_bits(&c->pb, 14, c->frame_size-1); + + /* Audio channel arrangement: L + R (stereo) */ + put_bits(&c->pb, 6, c->num_channel); + + /* Core audio sampling frequency */ + put_bits(&c->pb, 4, c->sample_rate_code); + + /* Transmission bit rate: 1411.2 kbps */ + put_bits(&c->pb, 5, 0x16); /* FIXME: magic number */ + + /* Embedded down mix: disabled */ + put_bits(&c->pb, 1, 0); + + /* Embedded dynamic range flag: not present */ + put_bits(&c->pb, 1, 0); + + /* Embedded time stamp flag: not present */ + put_bits(&c->pb, 1, 0); + + /* Auxiliary data flag: not present */ + put_bits(&c->pb, 1, 0); + + /* HDCD source: no */ + put_bits(&c->pb, 1, 0); + + /* Extension audio ID: N/A */ + put_bits(&c->pb, 3, 0); + + /* Extended audio data: not present */ + put_bits(&c->pb, 1, 0); + + /* Audio sync word insertion flag: after each sub-frame */ + put_bits(&c->pb, 1, 0); + + /* Low frequency effects flag: not present or interpolation factor=64 */ + put_bits(&c->pb, 2, c->lfe_state); + + /* Predictor history switch flag: on */ + put_bits(&c->pb, 1, 1); + + /* No CRC */ + /* Multirate interpolator switch: non-perfect reconstruction */ + put_bits(&c->pb, 1, 0); + + /* Encoder software revision: 7 */ + put_bits(&c->pb, 4, 7); + + /* Copy history: 0 */ + put_bits(&c->pb, 2, 0); + + /* Source PCM resolution: 16 bits, not DTS ES */ + put_bits(&c->pb, 3, 0); + + /* Front sum/difference coding: no */ + put_bits(&c->pb, 1, 0); + + /* Surrounds sum/difference coding: no */ + put_bits(&c->pb, 1, 0); + + /* Dialog normalization: 0 dB */ + put_bits(&c->pb, 4, 0); +} + +static void put_primary_audio_header(DCAContext *c) +{ + static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 }; + static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 }; + + int ch, i; + /* Number of subframes */ + put_bits(&c->pb, 4, SUBFRAMES - 1); + + /* Number of primary audio channels */ + put_bits(&c->pb, 3, c->prim_channels - 1); + + /* Subband activity count */ + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, 5, DCA_SUBBANDS - 2); + + /* High frequency VQ start subband */ + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, 5, DCA_SUBBANDS - 1); + + /* Joint intensity coding index: 0, 0 */ + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, 3, 0); + + /* Transient mode codebook: A4, A4 (arbitrary) */ + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, 2, 0); + + /* Scale factor code book: 7 bit linear, 7-bit sqrt table (for each channel) */ + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, 3, 6); + + /* Bit allocation quantizer select: linear 5-bit */ + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, 3, 6); + + /* Quantization index codebook select: dummy data + to avoid transmission of scale factor adjustment */ + + for (i = 1; i < 11; i++) + for (ch = 0; ch < c->prim_channels; ch++) + put_bits(&c->pb, bitlen[i], thr[i]); + + /* Scale factor adjustment index: not transmitted */ +} + +/** + * 8-23 bits quantization + * @param sample + * @param bits + */ +static inline uint32_t quantize(int32_t sample, int bits) +{ + av_assert0(sample < 1 << (bits - 1)); + av_assert0(sample >= -(1 << (bits - 1))); + return sample & ((1 << bits) - 1); +} + +static inline int find_scale_factor7(int64_t max_value, int bits) +{ + int i = 0, j = 128, q; + max_value = ((max_value << 15) / lossy_quant[bits + 3]) >> (bits - 1); + while (i < j) { + q = (i + j) >> 1; + if (max_value < scale_factor_quant7[q]) + j = q; + else + i = q + 1; + } + av_assert1(i < 128); + return i; +} + +static inline void put_sample7(DCAContext *c, int64_t sample, int bits, + int scale_factor) +{ + sample = (sample << 15) / ((int64_t) lossy_quant[bits + 3] * scale_factor_quant7[scale_factor]); + put_bits(&c->pb, bits, quantize((int) sample, bits)); +} + +static void put_subframe(DCAContext *c, + int32_t subband_data[8 * SUBSUBFRAMES][MAX_CHANNELS][32], + int subframe) +{ + int i, sub, ss, ch, max_value; + int32_t *lfe_data = c->lfe_data + 4 * SUBSUBFRAMES * subframe; + + /* Subsubframes count */ + put_bits(&c->pb, 2, SUBSUBFRAMES -1); + + /* Partial subsubframe sample count: dummy */ + put_bits(&c->pb, 3, 0); + + /* Prediction mode: no ADPCM, in each channel and subband */ + for (ch = 0; ch < c->prim_channels; ch++) + for (sub = 0; sub < DCA_SUBBANDS; sub++) + put_bits(&c->pb, 1, 0); + + /* Prediction VQ addres: not transmitted */ + /* Bit allocation index */ + for (ch = 0; ch < c->prim_channels; ch++) + for (sub = 0; sub < DCA_SUBBANDS; sub++) + put_bits(&c->pb, 5, QUANTIZER_BITS+3); + + if (SUBSUBFRAMES > 1) { + /* Transition mode: none for each channel and subband */ + for (ch = 0; ch < c->prim_channels; ch++) + for (sub = 0; sub < DCA_SUBBANDS; sub++) + put_bits(&c->pb, 1, 0); /* codebook A4 */ + } + + /* Determine scale_factor */ + for (ch = 0; ch < c->prim_channels; ch++) + for (sub = 0; sub < DCA_SUBBANDS; sub++) { + max_value = 0; + for (i = 0; i < 8 * SUBSUBFRAMES; i++) + max_value = FFMAX(max_value, FFABS(subband_data[i][ch][sub])); + c->scale_factor[ch][sub] = find_scale_factor7(max_value, QUANTIZER_BITS); + } + + if (c->lfe_channel) { + max_value = 0; + for (i = 0; i < 4 * SUBSUBFRAMES; i++) + max_value = FFMAX(max_value, FFABS(lfe_data[i])); + c->lfe_scale_factor = find_scale_factor7(max_value, LFE_BITS); + } + + /* Scale factors: the same for each channel and subband, + encoded according to Table D.1.2 */ + for (ch = 0; ch < c->prim_channels; ch++) + for (sub = 0; sub < DCA_SUBBANDS; sub++) + put_bits(&c->pb, 7, c->scale_factor[ch][sub]); + + /* Joint subband scale factor codebook select: not transmitted */ + /* Scale factors for joint subband coding: not transmitted */ + /* Stereo down-mix coefficients: not transmitted */ + /* Dynamic range coefficient: not transmitted */ + /* Stde information CRC check word: not transmitted */ + /* VQ encoded high frequency subbands: not transmitted */ + + /* LFE data */ + if (c->lfe_channel) { + for (i = 0; i < 4 * SUBSUBFRAMES; i++) + put_sample7(c, lfe_data[i], LFE_BITS, c->lfe_scale_factor); + put_bits(&c->pb, 8, c->lfe_scale_factor); + } + + /* Audio data (subsubframes) */ + + for (ss = 0; ss < SUBSUBFRAMES ; ss++) + for (ch = 0; ch < c->prim_channels; ch++) + for (sub = 0; sub < DCA_SUBBANDS; sub++) + for (i = 0; i < 8; i++) + put_sample7(c, subband_data[ss * 8 + i][ch][sub], QUANTIZER_BITS, c->scale_factor[ch][sub]); + + /* DSYNC */ + put_bits(&c->pb, 16, 0xffff); +} + +static void put_frame(DCAContext *c, + int32_t subband_data[PCM_SAMPLES][MAX_CHANNELS][32], + uint8_t *frame) +{ + int i; + init_put_bits(&c->pb, frame + DCA_HEADER_SIZE, DCA_MAX_FRAME_SIZE-DCA_HEADER_SIZE); + + put_primary_audio_header(c); + for (i = 0; i < SUBFRAMES; i++) + put_subframe(c, &subband_data[SUBSUBFRAMES * 8 * i], i); + + flush_put_bits(&c->pb); + c->frame_size = (put_bits_count(&c->pb) >> 3) + DCA_HEADER_SIZE; + + init_put_bits(&c->pb, frame, DCA_HEADER_SIZE); + put_frame_header(c); + flush_put_bits(&c->pb); +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + int i, k, channel; + DCAContext *c = avctx->priv_data; + const int16_t *samples; + int ret, real_channel = 0; + + if ((ret = ff_alloc_packet2(avctx, avpkt, DCA_MAX_FRAME_SIZE + DCA_HEADER_SIZE)) < 0) + return ret; + + samples = (const int16_t *)frame->data[0]; + for (i = 0; i < PCM_SAMPLES; i ++) { /* i is the decimated sample number */ + for (channel = 0; channel < c->prim_channels + 1; channel++) { + real_channel = c->channel_order_tab[channel]; + if (real_channel >= 0) { + /* Get 32 PCM samples */ + for (k = 0; k < 32; k++) { /* k is the sample number in a 32-sample block */ + c->pcm[k] = samples[avctx->channels * (32 * i + k) + channel] << 16; + } + /* Put subband samples into the proper place */ + qmf_decompose(c, c->pcm, &c->subband[i][real_channel][0], real_channel); + } + } + } + + if (c->lfe_channel) { + for (i = 0; i < PCM_SAMPLES / 2; i++) { + for (k = 0; k < LFE_INTERPOLATION; k++) /* k is the sample number in a 32-sample block */ + c->pcm[k] = samples[avctx->channels * (LFE_INTERPOLATION*i+k) + c->lfe_offset] << 16; + c->lfe_data[i] = lfe_downsample(c, c->pcm); + } + } + + put_frame(c, c->subband, avpkt->data); + + avpkt->size = c->frame_size; + *got_packet_ptr = 1; + return 0; +} + +static int encode_init(AVCodecContext *avctx) +{ + DCAContext *c = avctx->priv_data; + int i; + uint64_t layout = avctx->channel_layout; + + c->prim_channels = avctx->channels; + c->lfe_channel = (avctx->channels == 3 || avctx->channels == 6); + + if (!layout) { + av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The " + "encoder will guess the layout, but it " + "might be incorrect.\n"); + layout = av_get_default_channel_layout(avctx->channels); + } + switch (layout) { + case AV_CH_LAYOUT_STEREO: c->a_mode = 2; c->num_channel = 2; break; + case AV_CH_LAYOUT_5POINT0: c->a_mode = 9; c->num_channel = 9; break; + case AV_CH_LAYOUT_5POINT1: c->a_mode = 9; c->num_channel = 9; break; + case AV_CH_LAYOUT_5POINT0_BACK: c->a_mode = 9; c->num_channel = 9; break; + case AV_CH_LAYOUT_5POINT1_BACK: c->a_mode = 9; c->num_channel = 9; break; + default: + av_log(avctx, AV_LOG_ERROR, + "Only stereo, 5.0, 5.1 channel layouts supported at the moment!\n"); + return AVERROR_PATCHWELCOME; + } + + if (c->lfe_channel) { + init_lfe_fir(); + c->prim_channels--; + c->channel_order_tab = dca_channel_reorder_lfe[c->a_mode]; + c->lfe_state = LFE_PRESENT; + c->lfe_offset = dca_lfe_index[c->a_mode]; + } else { + c->channel_order_tab = dca_channel_reorder_nolfe[c->a_mode]; + c->lfe_state = LFE_MISSING; + } + + for (i = 0; i < 16; i++) { + if (avpriv_dca_sample_rates[i] && (avpriv_dca_sample_rates[i] == avctx->sample_rate)) + break; + } + if (i == 16) { + av_log(avctx, AV_LOG_ERROR, "Sample rate %iHz not supported, only ", avctx->sample_rate); + for (i = 0; i < 16; i++) + av_log(avctx, AV_LOG_ERROR, "%d, ", avpriv_dca_sample_rates[i]); + av_log(avctx, AV_LOG_ERROR, "supported.\n"); + return -1; + } + c->sample_rate_code = i; + + avctx->frame_size = 32 * PCM_SAMPLES; + + if (!cos_table[127]) + qmf_init(); + return 0; +} + +AVCodec ff_dca_encoder = { + .name = "dca", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DTS, + .priv_data_size = sizeof(DCAContext), + .init = encode_init, + .encode2 = encode_frame, + .capabilities = CODEC_CAP_EXPERIMENTAL, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), +}; diff --git a/ffmpeg/libavcodec/dcaenc.h b/ffmpeg/libavcodec/dcaenc.h new file mode 100644 index 0000000..121e5da --- /dev/null +++ b/ffmpeg/libavcodec/dcaenc.h @@ -0,0 +1,546 @@ +/* + * DCA encoder tables + * Copyright (C) 2008 Alexander E. Patrakov + * + * 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 + */ + +#ifndef AVCODEC_DCAENC_H +#define AVCODEC_DCAENC_H + +#include + +/* This is a scaled version of the response of the reference decoder to + this vector of subband samples: ( 1.0 0.0 0.0 ... 0.0 ) + */ + +static const int32_t UnQMF[512] = { + 7, + 4, + -961, + -2844, + -8024, + -18978, + -32081, + -15635, + -16582, + -18359, + -17180, + -14868, + -11664, + -8051, + -4477, + -1327, + -1670, + -6019, + -11590, + -18030, + -24762, + -30965, + -35947, + -36145, + -37223, + -86311, + -57024, + -27215, + -11274, + -4684, + 42, + 108, + 188, + 250, + -1007, + -596, + -2289, + -12218, + -27191, + -124367, + -184256, + -250538, + -323499, + -397784, + -468855, + -532072, + -583000, + -618041, + -777916, + -783868, + -765968, + -724740, + -662468, + -583058, + -490548, + -401623, + -296090, + -73154, + -36711, + -7766, + -2363, + -4905, + 2388, + 2681, + 5651, + 4086, + 71110, + 139742, + 188067, + 151237, + 101355, + 309917, + 343690, + 358839, + 357555, + 334606, + 289625, + 224152, + 142063, + 48725, + 74996, + 238425, + 411666, + 584160, + 744276, + 880730, + 983272, + 1041933, + 1054396, + 789531, + 851022, + 864032, + 675431, + 418134, + 35762, + 66911, + 103502, + 136403, + -55147, + -245269, + -499595, + -808470, + -1136858, + -2010912, + -2581654, + -3151901, + -3696328, + -4196599, + -4633761, + -4993229, + -5262495, + -5436311, + -477650, + -901314, + -1308090, + -1677468, + -1985525, + -2212848, + -2341196, + -2373915, + -2269552, + -2620489, + -2173858, + -1629954, + -946595, + -193499, + 1119459, + 1138657, + 1335311, + 1126544, + 2765033, + 3139603, + 3414913, + 3599213, + 3676363, + 3448981, + 3328726, + 3111551, + 2810887, + 2428657, + 1973684, + 1457278, + 893848, + 300995, + -292521, + -867621, + -1404936, + -1871278, + -2229831, + -2440932, + -2462684, + -2255006, + -1768898, + -1079574, + 82115, + 1660302, + 3660715, + 6123610, + 8329598, + 11888744, + 15722147, + 19737089, + 25647773, + 31039399, + 36868007, + 43124253, + 49737161, + 56495958, + 63668945, + 71039511, + 78540240, + 86089058, + 93600041, + 100981151, + 108136061, + 114970055, + 121718321, + 127566038, + 132774642, + 137247294, + 140894737, + 143635018, + 145395599, + 146114032, + 145742999, + 144211606, + 141594341, + 137808404, + 132914122, + 126912246, + 120243281, + 112155281, + 103338368, + 93904953, + 83439152, + 72921548, + 62192990, + 51434918, + 40894003, + 30786726, + 21384955, + 12939112, + 5718193, + -5790, + -3959261, + -5870978, + -5475538, + -2517061, + 3247310, + 12042937, + 24076729, + 39531397, + 58562863, + 81297002, + 107826748, + 138209187, + 172464115, + 210569037, + 252468018, + 298045453, + 347168648, + 399634888, + 455137189, + 513586535, + 574537650, + 637645129, + 702597163, + 768856566, + 836022040, + 903618096, + 971159680, + 1038137214, + 1103987353, + 1168195035, + 1230223053, + 1289539180, + 1345620373, + 1397957958, + 1446063657, + 1489474689, + 1527740502, + 1560502307, + 1587383079, + 1608071145, + 1622301248, + 1629859340, + 1630584888, + 1624373875, + 1611178348, + 1591018893, + 1563948667, + 1530105004, + 1489673227, + 1442904075, + 1390107674, + 1331590427, + 1267779478, + 1199115126, + 1126053392, + 1049146257, + 968928307, + 885965976, + 800851610, + 714186243, + 626590147, + 538672486, + 451042824, + 364299927, + 279026812, + 195785029, + 115109565, + 37503924, + -36564551, + -106668063, + -172421668, + -233487283, + -289575706, + -340448569, + -385919511, + -425854915, + -460174578, + -488840702, + -511893328, + -529405118, + -541489888, + -548312207, + -550036471, + -547005316, + -539436808, + -527630488, + -512084785, + -492941605, + -470665204, + -445668379, + -418328829, + -389072810, + -358293846, + -326396227, + -293769619, + -260792276, + -227825056, + -195208961, + -163262121, + -132280748, + -102533727, + -74230062, + -47600637, + -22817785, + -25786, + 20662895, + 39167253, + 55438413, + 69453741, + 81242430, + 90795329, + 98213465, + 103540643, + 106917392, + 108861938, + 108539682, + 106780704, + 103722568, + 99043289, + 93608686, + 87266209, + 80212203, + 72590022, + 64603428, + 56362402, + 48032218, + 39749162, + 31638971, + 23814664, + 16376190, + 9409836, + 2988017, + -2822356, + -7976595, + -12454837, + -16241147, + -19331944, + -21735011, + -23468284, + -24559822, + -25042936, + -25035583, + -24429587, + -23346408, + -21860411, + -20015718, + -17025330, + -14968728, + -12487138, + -9656319, + -7846681, + -5197816, + -2621904, + -144953, + 2144746, + 3990570, + 5845884, + 7454650, + 8820394, + 9929891, + 10784445, + 11390921, + 11762056, + 11916017, + 12261189, + 12117604, + 11815303, + 11374622, + 10815301, + 10157241, + 9418799, + 8629399, + 7780776, + 7303680, + 6353499, + 5392738, + 4457895, + 3543062, + 1305978, + 1402521, + 1084092, + 965652, + -151008, + -666667, + -1032157, + -1231475, + -1319043, + -1006023, + -915720, + -773426, + -612377, + -445864, + -291068, + -161337, + -66484, + -11725, + 133453, + 388184, + 615856, + 804033, + 942377, + 1022911, + 1041247, + 995854, + 891376, + 572246, + 457992, + 316365, + 172738, + 43037, + -117662, + -98542, + -70279, + -41458, + -535790, + -959038, + -1364456, + -1502265, + -1568530, + -2378681, + -2701111, + -2976407, + -3182552, + -3314415, + -3366600, + -3337701, + -3232252, + -3054999, + 1984841, + 1925903, + 1817377, + 1669153, + 1490069, + 1292040, + 1086223, + 890983, + 699163, + 201358, + 266971, + 296990, + 198419, + 91119, + 4737, + 5936, + 2553, + 2060, + -3828, + -1664, + -4917, + -20796, + -36822, + -131247, + -154923, + -162055, + -161354, + -148762, + -125754, + -94473, + -57821, + -19096, + 15172, + 43004, + 65624, + 81354, + 89325, + 89524, + 82766, + 71075, + 55128, + 13686, + 6921, + 1449, + 420, + 785, + -215, + -179, + -113, + -49, + 6002, + 16007, + 42978, + 100662, + 171472, + 83975, + 93702, + 108813, + 111893, + 110272, + 103914, + 93973, + 81606, + 68041, + -54058, + -60695, + -65277, + -67224, + -66213, + -62082, + -55574, + -42988, + -35272, + -63735, + -33501, + -12671, + -4038, + -1232, + 5, + 7 +}; + +#endif /* AVCODEC_DCAENC_H */ diff --git a/ffmpeg/libavcodec/dcahuff.h b/ffmpeg/libavcodec/dcahuff.h new file mode 100644 index 0000000..cbc8429 --- /dev/null +++ b/ffmpeg/libavcodec/dcahuff.h @@ -0,0 +1,1076 @@ +/* + * DCA compatible decoder - huffman tables + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2007 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_DCAHUFF_H +#define AVCODEC_DCAHUFF_H + +#include +#include + +#define TMODE_COUNT 4 +static const uint8_t tmode_vlc_bits[TMODE_COUNT] = { 3, 3, 3, 2 }; +static const uint16_t tmode_codes[TMODE_COUNT][4] = { + { 0x0000, 0x0002, 0x0006, 0x0007 }, + { 0x0002, 0x0006, 0x0007, 0x0000 }, + { 0x0006, 0x0007, 0x0000, 0x0002 }, + { 0x0000, 0x0001, 0x0002, 0x0003 } +}; +static const uint8_t tmode_bits[TMODE_COUNT][4] = { + { 1, 2, 3, 3 }, + { 2, 3, 3, 1 }, + { 3, 3, 1, 2 }, + { 2, 2, 2, 2 } +}; + + +#define BITALLOC_12_COUNT 5 +#define BITALLOC_12_VLC_BITS 9 +static const uint8_t bitalloc_12_vlc_bits[BITALLOC_12_COUNT] = { + 9, 7, 7, 9, 9 +}; +static const uint16_t bitalloc_12_codes[BITALLOC_12_COUNT][12] = { + { + 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x00FF, 0x00FE, + 0x01FB, 0x01FA, 0x01F9, 0x01F8, + }, + { + 0x0001, 0x0000, 0x0002, 0x000F, 0x000C, 0x001D, 0x0039, 0x0038, + 0x0037, 0x0036, 0x0035, 0x0034, + }, + { + 0x0000, 0x0007, 0x0005, 0x0004, 0x0002, 0x000D, 0x000C, 0x0006, + 0x000F, 0x001D, 0x0039, 0x0038, + }, + { + 0x0003, 0x0002, 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, + 0x007E, 0x00FE, 0x01FF, 0x01FE, + }, + { + 0x0001, 0x0000, 0x0002, 0x0006, 0x000E, 0x003F, 0x003D, 0x007C, + 0x0079, 0x0078, 0x00FB, 0x00FA, + } +}; +static const uint8_t bitalloc_12_bits[BITALLOC_12_COUNT][12] = { + { 1, 2, 3, 4, 5, 6, 8, 8, 9, 9, 9, 9 }, + { 1, 2, 3, 5, 5, 6, 7, 7, 7, 7, 7, 7 }, + { 2, 3, 3, 3, 3, 4, 4, 4, 5, 6, 7, 7 }, + { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10 }, + { 1, 2, 3, 4, 5, 7, 7, 8, 8, 8, 9, 9 } +}; + + +#define SCALES_COUNT 5 +#define SCALES_VLC_BITS 9 +static const uint16_t scales_codes[SCALES_COUNT][129] = { + { + 0x3AB0, 0x3AB2, 0x3AB4, 0x3AB6, 0x3AB8, 0x3ABA, 0x3ABC, 0x3ABE, + 0x3AC0, 0x3AC2, 0x3AC4, 0x3AC6, 0x3AC8, 0x3ACA, 0x3ACC, 0x3ACE, + 0x3AD0, 0x3AD2, 0x3AD4, 0x3AD6, 0x3AD8, 0x3ADA, 0x3ADC, 0x3ADE, + 0x3AE0, 0x3AE2, 0x3AE4, 0x3AE6, 0x3AE8, 0x3AEA, 0x3AEC, 0x3AEE, + 0x3AF0, 0x3AF2, 0x3AF4, 0x3AF6, 0x3AF8, 0x3AFA, 0x3AFC, 0x3AFE, + 0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E, + 0x0558, 0x055E, 0x02AD, 0x0154, 0x0754, 0x03A8, 0x0056, 0x0028, + 0x00E8, 0x004A, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005, + 0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x004B, + 0x00E9, 0x0029, 0x0057, 0x03A9, 0x0755, 0x0155, 0x02AE, 0x055F, + 0x0559, 0x054F, 0x054D, 0x054B, 0x0549, 0x0547, 0x0545, 0x0543, + 0x0541, 0x3AFF, 0x3AFD, 0x3AFB, 0x3AF9, 0x3AF7, 0x3AF5, 0x3AF3, + 0x3AF1, 0x3AEF, 0x3AED, 0x3AEB, 0x3AE9, 0x3AE7, 0x3AE5, 0x3AE3, + 0x3AE1, 0x3ADF, 0x3ADD, 0x3ADB, 0x3AD9, 0x3AD7, 0x3AD5, 0x3AD3, + 0x3AD1, 0x3ACF, 0x3ACD, 0x3ACB, 0x3AC9, 0x3AC7, 0x3AC5, 0x3AC3, + 0x3AC1, 0x3ABF, 0x3ABD, 0x3ABB, 0x3AB9, 0x3AB7, 0x3AB5, 0x3AB3, + 0x3AB1, + }, + { + 0x0F60, 0x0F62, 0x0F64, 0x0F66, 0x0F68, 0x0F6A, 0x0F6C, 0x0F6E, + 0x0F70, 0x0F72, 0x0F74, 0x0F76, 0x0F78, 0x0F7A, 0x0F7C, 0x0F7E, + 0x0F80, 0x0F82, 0x0F84, 0x0F86, 0x0F88, 0x0F8A, 0x0F8C, 0x0F8E, + 0x0F90, 0x0F92, 0x0F94, 0x0F96, 0x0F98, 0x0F9A, 0x0F9C, 0x0F9E, + 0x0FA0, 0x0FA2, 0x0FA4, 0x0FA6, 0x0FA8, 0x0FAA, 0x0FAC, 0x0FAE, + 0x0FB0, 0x0FB2, 0x0FB4, 0x0FB6, 0x0FB8, 0x0FBA, 0x0FBC, 0x0FBE, + 0x07A0, 0x07A2, 0x03D2, 0x01EA, 0x00FC, 0x007F, 0x001C, 0x000C, + 0x0004, 0x0034, 0x0010, 0x001B, 0x0009, 0x000B, 0x000E, 0x0001, + 0x0003, 0x0002, 0x000F, 0x000C, 0x000A, 0x0000, 0x0011, 0x0035, + 0x0005, 0x000D, 0x001D, 0x003C, 0x00FD, 0x01EB, 0x03D3, 0x07A3, + 0x07A1, 0x0FBF, 0x0FBD, 0x0FBB, 0x0FB9, 0x0FB7, 0x0FB5, 0x0FB3, + 0x0FB1, 0x0FAF, 0x0FAD, 0x0FAB, 0x0FA9, 0x0FA7, 0x0FA5, 0x0FA3, + 0x0FA1, 0x0F9F, 0x0F9D, 0x0F9B, 0x0F99, 0x0F97, 0x0F95, 0x0F93, + 0x0F91, 0x0F8F, 0x0F8D, 0x0F8B, 0x0F89, 0x0F87, 0x0F85, 0x0F83, + 0x0F81, 0x0F7F, 0x0F7D, 0x0F7B, 0x0F79, 0x0F77, 0x0F75, 0x0F73, + 0x0F71, 0x0F6F, 0x0F6D, 0x0F6B, 0x0F69, 0x0F67, 0x0F65, 0x0F63, + 0x0F61, + }, + { + 0x51D0, 0x51D2, 0x51D4, 0x51D6, 0x51D8, 0x51DA, 0x51DC, 0x51DE, + 0x51E0, 0x51E2, 0x51E4, 0x51E6, 0x51E8, 0x51EA, 0x51EC, 0x51EE, + 0x51F0, 0x51F2, 0x51F4, 0x51F6, 0x51F8, 0x51FA, 0x51FC, 0x51FE, + 0x70C0, 0x70C2, 0x70C4, 0x70C6, 0x70C8, 0x70CA, 0x70CC, 0x70CE, + 0x70EC, 0x10EA, 0x3868, 0x3877, 0x0876, 0x1C35, 0x0434, 0x0A34, + 0x0E1B, 0x021B, 0x051B, 0x070F, 0x010F, 0x0380, 0x0080, 0x0140, + 0x01C1, 0x0041, 0x00A1, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012, + 0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000, + 0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B, + 0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A2, 0x0042, + 0x01C2, 0x0141, 0x0081, 0x0381, 0x028C, 0x010C, 0x051C, 0x021C, + 0x0E1C, 0x0A35, 0x0435, 0x1C3A, 0x0877, 0x0874, 0x3869, 0x10EB, + 0x70ED, 0x70CF, 0x70CD, 0x70CB, 0x70C9, 0x70C7, 0x70C5, 0x70C3, + 0x70C1, 0x51FF, 0x51FD, 0x51FB, 0x51F9, 0x51F7, 0x51F5, 0x51F3, + 0x51F1, 0x51EF, 0x51ED, 0x51EB, 0x51E9, 0x51E7, 0x51E5, 0x51E3, + 0x51E1, 0x51DF, 0x51DD, 0x51DB, 0x51D9, 0x51D7, 0x51D5, 0x51D3, + 0x51D1, + }, + { + 0x6F64, 0x6F66, 0x6F68, 0x6F6A, 0x6F6C, 0x6F6E, 0x6F70, 0x6F72, + 0x6F74, 0x6F76, 0x6F78, 0x6F7A, 0x6F7C, 0x6F7E, 0x6F80, 0x6F82, + 0x6F84, 0x6F86, 0x6F88, 0x6F8A, 0x6F8C, 0x6F8E, 0x6F90, 0x6F92, + 0x6F94, 0x6F96, 0x6F98, 0x6F9A, 0x6F9C, 0x6F9E, 0x6FA0, 0x6FA2, + 0x6FA4, 0x6FA6, 0x6FA8, 0x6FAA, 0x6FAC, 0x6FAE, 0x6FB0, 0x6FB2, + 0x6FB4, 0x6FB6, 0x17B4, 0x37DC, 0x0BDB, 0x1BEF, 0x05EE, 0x0DF8, + 0x02F8, 0x06FD, 0x017D, 0x037F, 0x00BF, 0x0040, 0x00C0, 0x0021, + 0x0061, 0x0011, 0x0031, 0x0009, 0x0019, 0x0006, 0x000E, 0x0004, + 0x0000, 0x0005, 0x000F, 0x0007, 0x001A, 0x000A, 0x0036, 0x0016, + 0x006E, 0x002E, 0x00C1, 0x0041, 0x01BC, 0x00BC, 0x037A, 0x017A, + 0x02F9, 0x0DF9, 0x05EF, 0x05EC, 0x1BD8, 0x37DD, 0x17B5, 0x6FB7, + 0x6FB5, 0x6FB3, 0x6FB1, 0x6FAF, 0x6FAD, 0x6FAB, 0x6FA9, 0x6FA7, + 0x6FA5, 0x6FA3, 0x6FA1, 0x6F9F, 0x6F9D, 0x6F9B, 0x6F99, 0x6F97, + 0x6F95, 0x6F93, 0x6F91, 0x6F8F, 0x6F8D, 0x6F8B, 0x6F89, 0x6F87, + 0x6F85, 0x6F83, 0x6F81, 0x6F7F, 0x6F7D, 0x6F7B, 0x6F79, 0x6F77, + 0x6F75, 0x6F73, 0x6F71, 0x6F6F, 0x6F6D, 0x6F6B, 0x6F69, 0x6F67, + 0x6F65, + }, + { + 0xDF54, 0xDF56, 0xDFC8, 0xDFCA, 0xDFCC, 0xDFCE, 0xDFD0, 0xDFD2, + 0xDFD4, 0xDFD6, 0xDFD8, 0xDFDA, 0xDFDC, 0xDFDE, 0xDFE0, 0xDFE2, + 0x0FE8, 0x2FEA, 0x6FA8, 0x6FF6, 0x07F5, 0x07F7, 0x37D2, 0x37F9, + 0x03F8, 0x0BF8, 0x0BFB, 0x1BEB, 0x01FA, 0x05FA, 0x09FA, 0x0DFA, + 0x0DFF, 0x00FF, 0x02FF, 0x06FB, 0x007C, 0x017C, 0x027C, 0x027F, + 0x003C, 0x00BC, 0x013C, 0x01BC, 0x001C, 0x005C, 0x009C, 0x00DC, + 0x000C, 0x002C, 0x004C, 0x006C, 0x0004, 0x0014, 0x0024, 0x0034, + 0x0000, 0x0008, 0x0010, 0x0018, 0x001E, 0x0002, 0x0006, 0x000A, + 0x000E, 0x000B, 0x0007, 0x0003, 0x001F, 0x0019, 0x0011, 0x0009, + 0x0001, 0x0035, 0x0025, 0x0015, 0x0005, 0x006D, 0x004D, 0x002D, + 0x000D, 0x00DD, 0x009D, 0x005D, 0x001D, 0x01BD, 0x013D, 0x00BD, + 0x003D, 0x037C, 0x027D, 0x017D, 0x007D, 0x06FC, 0x04FC, 0x02FC, + 0x00FC, 0x0DFB, 0x09FB, 0x05FB, 0x01FB, 0x1BF8, 0x1BE8, 0x0BF9, + 0x03F9, 0x37FA, 0x37D3, 0x17F4, 0x07F6, 0x6FF7, 0x6FA9, 0x2FEB, + 0x0FE9, 0xDFE3, 0xDFE1, 0xDFDF, 0xDFDD, 0xDFDB, 0xDFD9, 0xDFD7, + 0xDFD5, 0xDFD3, 0xDFD1, 0xDFCF, 0xDFCD, 0xDFCB, 0xDFC9, 0xDF57, + 0xDF55, + } +}; + +static const uint8_t scales_bits[SCALES_COUNT][129] = { + { + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 12, 11, 11, 10, 9, 8, + 8, 7, 6, 6, 5, 4, 4, 3, + 2, 3, 3, 4, 5, 5, 6, 7, + 8, 8, 9, 10, 11, 11, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, + }, + { + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 14, 14, 13, 12, 11, 10, 8, 7, + 6, 6, 5, 5, 4, 4, 4, 3, + 3, 3, 4, 4, 4, 4, 5, 6, + 6, 7, 8, 9, 11, 12, 13, 14, + 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, + }, + { + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 14, 14, 14, 13, 13, 12, 12, + 12, 11, 11, 11, 10, 10, 9, 9, + 9, 8, 8, 8, 7, 7, 7, 6, + 6, 6, 5, 5, 5, 4, 4, 3, + 3, 3, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 10, 10, 10, 11, 11, + 12, 12, 12, 13, 13, 13, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, + }, + { + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 14, 13, 13, 12, 12, + 11, 11, 10, 10, 9, 8, 8, 7, + 7, 6, 6, 5, 5, 4, 4, 3, + 2, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, + 11, 12, 12, 12, 13, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, + }, + { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 15, 15, 15, 15, 14, 14, 14, 14, + 13, 13, 13, 13, 12, 12, 12, 12, + 12, 11, 11, 11, 10, 10, 10, 10, + 9, 9, 9, 9, 8, 8, 8, 8, + 7, 7, 7, 7, 6, 6, 6, 6, + 5, 5, 5, 5, 5, 4, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 11, 11, + 11, 12, 12, 12, 12, 13, 13, 13, + 13, 14, 14, 14, 14, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, + } +}; + +static const uint16_t bitalloc_3_codes[3] = +{ + 0x0003, 0x0000, 0x0002, +}; +static const uint8_t bitalloc_3_bits[3] = +{ + 2, 1, 2, +}; + +static const uint16_t bitalloc_5_codes_a[5] = +{ + 0x000F, 0x0006, 0x0000, 0x0002, 0x000E, +}; +static const uint16_t bitalloc_5_codes_b[5] = +{ + 0x0007, 0x0001, 0x0002, 0x0000, 0x0006, +}; +static const uint16_t bitalloc_5_codes_c[5] = +{ + 0x0007, 0x0005, 0x0000, 0x0004, 0x0006, +}; +static const uint8_t bitalloc_5_bits_a[5] = +{ + 4, 3, 1, 2, 4, +}; +static const uint8_t bitalloc_5_bits_b[5] = +{ + 3, 2, 2, 2, 3, +}; +static const uint8_t bitalloc_5_bits_c[5] = +{ + 3, 3, 1, 3, 3, +}; + +static const uint16_t bitalloc_7_codes_a[7] = +{ + 0x001E, 0x000E, 0x0005, 0x0000, 0x0006, 0x0004, 0x001F, +}; +static const uint16_t bitalloc_7_codes_b[7] = +{ + 0x0014, 0x000B, 0x0000, 0x0003, 0x0001, 0x0004, 0x0015, +}; +static const uint16_t bitalloc_7_codes_c[7] = +{ + 0x0000, 0x0002, 0x0001, 0x0003, 0x0002, 0x0003, 0x0001, +}; +static const uint8_t bitalloc_7_bits_a[7] = +{ + 5, 4, 3, 1, 3, 3, 5, +}; +static const uint8_t bitalloc_7_bits_b[7] = +{ + 5, 4, 2, 2, 2, 3, 5, +}; +static const uint8_t bitalloc_7_bits_c[7] = +{ + 4, 4, 2, 2, 2, 4, 4, +}; + +static const uint16_t bitalloc_9_codes_a[9] = +{ + 0x0030, 0x0019, 0x0009, 0x0005, 0x0000, 0x0007, 0x000D, 0x0008, + 0x0031, +}; +static const uint16_t bitalloc_9_codes_b[9] = +{ + 0x0018, 0x001A, 0x0002, 0x0007, 0x0002, 0x0000, 0x0003, 0x001B, + 0x0019, +}; +static const uint16_t bitalloc_9_codes_c[9] = +{ + 0x001C, 0x000F, 0x0002, 0x0007, 0x0002, 0x0000, 0x0006, 0x0006, + 0x001D, +}; +static const uint8_t bitalloc_9_bits_a[9] = +{ + 6, 5, 4, 3, 1, 3, 4, 4, 6, +}; +static const uint8_t bitalloc_9_bits_b[9] = +{ + 5, 5, 3, 3, 2, 2, 3, 5, 5, +}; +static const uint8_t bitalloc_9_bits_c[9] = +{ + 6, 5, 3, 3, 2, 2, 3, 4, 6, +}; + +static const uint16_t bitalloc_13_codes_a[13] = +{ + 0x0070, 0x002E, 0x0039, 0x001D, 0x000C, 0x000F, 0x0000, 0x0004, + 0x000D, 0x000A, 0x0016, 0x002F, 0x0071, +}; +static const uint16_t bitalloc_13_codes_b[13] = +{ + 0x0038, 0x0010, 0x001D, 0x0007, 0x000F, 0x0005, 0x0000, 0x0006, + 0x0002, 0x0009, 0x0006, 0x0011, 0x0039, +}; +static const uint16_t bitalloc_13_codes_c[13] = +{ + 0x0004, 0x001A, 0x0003, 0x000E, 0x0000, 0x0003, 0x0005, 0x0004, + 0x0002, 0x000F, 0x000C, 0x001B, 0x0005, +}; +static const uint8_t bitalloc_13_bits_a[13] = +{ + 7, 6, 6, 5, 4, 4, 1, 3, 4, 4, 5, 6, 7, +}; +static const uint8_t bitalloc_13_bits_b[13] = +{ + 6, 5, 5, 4, 4, 3, 2, 3, 3, 4, 4, 5, 6, +}; +static const uint8_t bitalloc_13_bits_c[13] = +{ + 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, +}; + +static const uint16_t bitalloc_17_codes_a[17] = +{ + 0x0154, 0x00AB, 0x002B, 0x000B, 0x0003, 0x000A, 0x0001, 0x0006, + 0x0001, 0x0007, 0x0004, 0x000B, 0x0000, 0x0004, 0x0014, 0x0054, + 0x0155, +}; +static const uint16_t bitalloc_17_codes_b[17] = +{ + 0x007C, 0x003F, 0x0019, 0x000D, 0x001C, 0x0008, 0x000F, 0x0005, + 0x0000, 0x0006, 0x0002, 0x0009, 0x001D, 0x000E, 0x001E, 0x0018, + 0x007D, +}; +static const uint16_t bitalloc_17_codes_c[17] = +{ + 0x002C, 0x0017, 0x0005, 0x001C, 0x0003, 0x000A, 0x000F, 0x0003, + 0x0006, 0x0004, 0x0000, 0x000B, 0x0004, 0x001D, 0x000A, 0x0004, + 0x002D, +}; +static const uint16_t bitalloc_17_codes_d[17] = +{ + 0x0100, 0x0102, 0x0082, 0x0042, 0x0022, 0x0012, 0x000A, 0x0006, + 0x0000, 0x0007, 0x000B, 0x0013, 0x0023, 0x0043, 0x0083, 0x0103, + 0x0101, +}; +static const uint16_t bitalloc_17_codes_e[17] = +{ + 0x00E8, 0x00F6, 0x0075, 0x0034, 0x003B, 0x001B, 0x001F, 0x0004, + 0x0000, 0x0005, 0x000C, 0x001C, 0x003C, 0x0035, 0x007A, 0x00F7, + 0x00E9, +}; +static const uint16_t bitalloc_17_codes_f[17] = +{ + 0x0004, 0x0003, 0x001E, 0x0001, 0x0001, 0x000E, 0x0001, 0x0004, + 0x0006, 0x0005, 0x0002, 0x000F, 0x0006, 0x000E, 0x001F, 0x0000, + 0x0005, +}; +static const uint16_t bitalloc_17_codes_g[17] = +{ + 0x0060, 0x007E, 0x0031, 0x0019, 0x000D, 0x0004, 0x0000, 0x0006, + 0x0002, 0x0007, 0x0001, 0x0005, 0x000E, 0x001E, 0x003E, 0x007F, + 0x0061, +}; +static const uint8_t bitalloc_17_bits_a[17] = +{ + 12, 11, 9, 7, 5, 4, 3, 3, 2, 3, 3, 4, 4, 6, 8, 10, + 12, +}; +static const uint8_t bitalloc_17_bits_b[17] = +{ + 8, 7, 6, 5, 5, 4, 4, 3, 2, 3, 3, 4, 5, 5, 6, 6, + 8, +}; +static const uint8_t bitalloc_17_bits_c[17] = +{ + 7, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 5, 5, + 7, +}; +static const uint8_t bitalloc_17_bits_d[17] = +{ + 9, 9, 8, 7, 6, 5, 4, 3, 1, 3, 4, 5, 6, 7, 8, 9, + 9, +}; +static const uint8_t bitalloc_17_bits_e[17] = +{ + 8, 8, 7, 6, 6, 5, 5, 3, 1, 3, 4, 5, 6, 6, 7, 8, + 8, +}; +static const uint8_t bitalloc_17_bits_f[17] = +{ + 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, + 8, +}; +static const uint8_t bitalloc_17_bits_g[17] = +{ + 8, 8, 7, 6, 5, 4, 3, 3, 2, 3, 3, 4, 5, 6, 7, 8, + 8, +}; + +static const uint16_t bitalloc_25_codes_a[25] = +{ + 0x2854, 0x142B, 0x050B, 0x0143, 0x00A2, 0x0052, 0x002E, 0x0015, + 0x0004, 0x000E, 0x0000, 0x0003, 0x0006, 0x0004, 0x0001, 0x000F, + 0x0005, 0x0016, 0x002F, 0x0053, 0x00A3, 0x00A0, 0x0284, 0x0A14, + 0x2855, +}; +static const uint16_t bitalloc_25_codes_b[25] = +{ + 0x001C, 0x000F, 0x0005, 0x0000, 0x0030, 0x0036, 0x000E, 0x0019, + 0x0001, 0x0008, 0x000E, 0x0001, 0x0005, 0x0002, 0x000F, 0x0009, + 0x0006, 0x001A, 0x000F, 0x0037, 0x0031, 0x0001, 0x0006, 0x0004, + 0x001D, +}; +static const uint16_t bitalloc_25_codes_c[25] = +{ + 0x004C, 0x0027, 0x006D, 0x0028, 0x0037, 0x000E, 0x0015, 0x0000, + 0x0005, 0x0008, 0x000B, 0x000E, 0x0001, 0x000F, 0x000C, 0x0009, + 0x0006, 0x0001, 0x001A, 0x000F, 0x0008, 0x0029, 0x0012, 0x006C, + 0x004D, +}; +static const uint16_t bitalloc_25_codes_d[25] = +{ + 0x0780, 0x0782, 0x03C2, 0x01E2, 0x00FE, 0x0079, 0x003D, 0x001C, + 0x000C, 0x0004, 0x0000, 0x0006, 0x0002, 0x0007, 0x0001, 0x0005, + 0x000D, 0x001D, 0x003E, 0x007E, 0x00FF, 0x01E3, 0x03C3, 0x0783, + 0x0781, +}; +static const uint16_t bitalloc_25_codes_e[25] = +{ + 0x003C, 0x0092, 0x0018, 0x001F, 0x004E, 0x000D, 0x0025, 0x0004, + 0x0010, 0x0000, 0x000A, 0x0002, 0x0003, 0x0003, 0x000B, 0x0001, + 0x0011, 0x0005, 0x0026, 0x000E, 0x004F, 0x0048, 0x0019, 0x0093, + 0x003D, +}; +static const uint16_t bitalloc_25_codes_f[25] = +{ + 0x0324, 0x0193, 0x00CE, 0x0065, 0x0024, 0x000C, 0x0013, 0x0004, + 0x0007, 0x000A, 0x000D, 0x000F, 0x0001, 0x0000, 0x000E, 0x000B, + 0x0008, 0x0005, 0x0018, 0x000D, 0x0025, 0x0066, 0x00CF, 0x00C8, + 0x0325, +}; +static const uint16_t bitalloc_25_codes_g[25] = +{ + 0x03A8, 0x03AE, 0x01D5, 0x0094, 0x0014, 0x004B, 0x000B, 0x003B, + 0x0013, 0x0003, 0x000F, 0x0005, 0x0001, 0x0006, 0x0000, 0x0008, + 0x001C, 0x0004, 0x0024, 0x0074, 0x0015, 0x0095, 0x01D6, 0x03AF, + 0x03A9, +}; +static const uint8_t bitalloc_25_bits_a[25] = +{ + 14, 13, 11, 9, 8, 7, 6, 5, 4, 4, 3, 3, 3, 3, 3, 4, + 4, 5, 6, 7, 8, 8, 10, 12, 14, +}; +static const uint8_t bitalloc_25_bits_b[25] = +{ + 9, 8, 7, 6, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 4, 4, + 4, 5, 5, 6, 6, 6, 7, 7, 9, +}; +static const uint8_t bitalloc_25_bits_c[25] = +{ + 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 4, 4, 3, 4, 4, 4, + 4, 4, 5, 5, 5, 6, 6, 7, 8, +}; +static const uint8_t bitalloc_25_bits_d[25] = +{ + 12, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 3, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 12, +}; +static const uint8_t bitalloc_25_bits_e[25] = +{ + 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 3, 2, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 7, 8, 8, +}; +static const uint8_t bitalloc_25_bits_f[25] = +{ + 10, 9, 8, 7, 6, 5, 5, 4, 4, 4, 4, 4, 3, 3, 4, 4, + 4, 4, 5, 5, 6, 7, 8, 8, 10, +}; +static const uint8_t bitalloc_25_bits_g[25] = +{ + 10, 10, 9, 8, 7, 7, 6, 6, 5, 4, 4, 3, 2, 3, 3, 4, + 5, 5, 6, 7, 7, 8, 9, 10, 10, +}; + +static const uint16_t bitalloc_33_codes_a[33] = +{ + 0x1580, 0x1582, 0x0AC2, 0x0562, 0x02B2, 0x015E, 0x00AD, 0x0054, + 0x001C, 0x003C, 0x000F, 0x001F, 0x0008, 0x000B, 0x000D, 0x0000, + 0x0002, 0x0001, 0x000E, 0x000C, 0x0009, 0x0006, 0x0014, 0x003D, + 0x001D, 0x0055, 0x00AE, 0x015F, 0x02B3, 0x0563, 0x0AC3, 0x1583, + 0x1581, +}; +static const uint16_t bitalloc_33_codes_b[33] = +{ + 0x030C, 0x0187, 0x006D, 0x0028, 0x0037, 0x0066, 0x0015, 0x0031, + 0x0000, 0x000B, 0x0012, 0x001A, 0x0001, 0x0007, 0x000A, 0x000E, + 0x0001, 0x000F, 0x000B, 0x0008, 0x0004, 0x001B, 0x0013, 0x000C, + 0x0001, 0x0032, 0x001A, 0x0067, 0x0060, 0x0029, 0x00C2, 0x006C, + 0x030D, +}; +static const uint16_t bitalloc_33_codes_c[33] = +{ + 0x00CC, 0x0067, 0x0005, 0x0070, 0x0003, 0x001A, 0x0039, 0x003F, + 0x000A, 0x0012, 0x0018, 0x001D, 0x0001, 0x0003, 0x0007, 0x000A, + 0x000D, 0x000B, 0x0008, 0x0004, 0x0002, 0x001E, 0x0019, 0x0013, + 0x000B, 0x0000, 0x003E, 0x001B, 0x0018, 0x0071, 0x0032, 0x0004, + 0x00CD, +}; +static const uint16_t bitalloc_33_codes_d[33] = +{ + 0x3AF8, 0x3AFA, 0x1D7E, 0x0EBC, 0x075C, 0x03AC, 0x01D4, 0x0094, + 0x0014, 0x004B, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005, + 0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x0074, + 0x0015, 0x0095, 0x01D5, 0x03AD, 0x075D, 0x0EBD, 0x1D7F, 0x3AFB, + 0x3AF9, +}; +static const uint16_t bitalloc_33_codes_e[33] = +{ + 0x01C8, 0x01E6, 0x0064, 0x00E2, 0x00E5, 0x0030, 0x0033, 0x0073, + 0x007A, 0x001A, 0x003A, 0x0002, 0x001A, 0x001F, 0x0007, 0x0001, + 0x0002, 0x0002, 0x000C, 0x0000, 0x001B, 0x0003, 0x003B, 0x001B, + 0x007B, 0x0078, 0x0070, 0x0031, 0x00F2, 0x00E3, 0x0065, 0x01E7, + 0x01C9, +}; +static const uint16_t bitalloc_33_codes_f[33] = +{ + 0x0724, 0x0393, 0x01CE, 0x00E5, 0x002C, 0x0008, 0x0017, 0x003E, + 0x0005, 0x0014, 0x001D, 0x0000, 0x0003, 0x0006, 0x0008, 0x000B, + 0x000D, 0x000C, 0x0009, 0x0007, 0x0004, 0x0001, 0x001E, 0x0015, + 0x000A, 0x003F, 0x0038, 0x0009, 0x002D, 0x00E6, 0x01CF, 0x01C8, + 0x0725, +}; +static const uint16_t bitalloc_33_codes_g[33] = +{ + 0x0284, 0x0042, 0x0140, 0x0143, 0x003E, 0x00BE, 0x0011, 0x0051, + 0x0009, 0x0029, 0x0005, 0x0015, 0x0000, 0x0008, 0x000E, 0x0002, + 0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0016, 0x0006, 0x002E, + 0x000E, 0x005E, 0x001E, 0x00BF, 0x003F, 0x0020, 0x0141, 0x0043, + 0x0285, +}; +static const uint8_t bitalloc_33_bits_a[33] = +{ + 13, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 5, 4, 4, 4, 3, + 3, 3, 4, 4, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, + 13, +}; +static const uint8_t bitalloc_33_bits_b[33] = +{ + 10, 9, 8, 7, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, + 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, + 10, +}; +static const uint8_t bitalloc_33_bits_c[33] = +{ + 9, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, + 9, +}; +static const uint8_t bitalloc_33_bits_d[33] = +{ + 14, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 6, 5, 4, 4, 3, + 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, + 14, +}; +static const uint8_t bitalloc_33_bits_e[33] = +{ + 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 5, 5, 5, 4, 3, + 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, + 9, +}; +static const uint8_t bitalloc_33_bits_f[33] = +{ + 11, 10, 9, 8, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9, 9, + 11, +}; +static const uint8_t bitalloc_33_bits_g[33] = +{ + 10, 9, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, + 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, + 10, +}; + +static const uint16_t bitalloc_65_codes_a[65] = +{ + 0x9E5C, 0x9E5E, 0x4F2C, 0x2794, 0x13C4, 0x1E44, 0x09E3, 0x0F23, + 0x04F3, 0x0792, 0x027E, 0x03CE, 0x013D, 0x01E5, 0x009C, 0x00CC, + 0x0040, 0x0058, 0x0067, 0x001E, 0x0021, 0x002D, 0x003D, 0x0007, + 0x0011, 0x0014, 0x0017, 0x001A, 0x001C, 0x001F, 0x0001, 0x0004, + 0x0006, 0x0005, 0x0002, 0x0000, 0x001D, 0x001B, 0x0018, 0x0015, + 0x0012, 0x000E, 0x0006, 0x0032, 0x0026, 0x001F, 0x0078, 0x0059, + 0x0041, 0x00CD, 0x009D, 0x01E6, 0x013E, 0x03CF, 0x027F, 0x0793, + 0x0790, 0x04F0, 0x09E4, 0x1E45, 0x13C5, 0x2795, 0x4F2D, 0x9E5F, + 0x9E5D, +}; +static const uint16_t bitalloc_65_codes_b[65] = +{ + 0x0A8C, 0x0547, 0x01B5, 0x0008, 0x00DB, 0x0152, 0x0005, 0x000B, + 0x008E, 0x00AE, 0x00E4, 0x0003, 0x0037, 0x0039, 0x0055, 0x006C, + 0x0073, 0x0003, 0x0015, 0x001D, 0x0028, 0x0030, 0x0037, 0x003E, + 0x0006, 0x000B, 0x000F, 0x0012, 0x0016, 0x0019, 0x001D, 0x0001, + 0x0004, 0x0002, 0x001E, 0x001A, 0x0017, 0x0013, 0x0010, 0x000C, + 0x0007, 0x003F, 0x0038, 0x0031, 0x0029, 0x0022, 0x001A, 0x0014, + 0x0000, 0x006D, 0x0056, 0x0046, 0x0038, 0x0004, 0x00E5, 0x00AF, + 0x008F, 0x006C, 0x000A, 0x0153, 0x0150, 0x0009, 0x02A2, 0x01B4, + 0x0A8D, +}; +static const uint16_t bitalloc_65_codes_c[65] = +{ + 0x045C, 0x022F, 0x03F5, 0x01BC, 0x01FB, 0x0059, 0x00D0, 0x00DF, + 0x000A, 0x002D, 0x002F, 0x0052, 0x0069, 0x0078, 0x007F, 0x000A, + 0x0010, 0x001C, 0x0023, 0x002A, 0x0035, 0x003A, 0x003D, 0x0000, + 0x0003, 0x0006, 0x0009, 0x000C, 0x000F, 0x0012, 0x0016, 0x0018, + 0x001C, 0x0019, 0x0017, 0x0013, 0x0010, 0x000D, 0x000A, 0x0007, + 0x0004, 0x0001, 0x003E, 0x003B, 0x0036, 0x002B, 0x0028, 0x001D, + 0x0011, 0x000B, 0x0004, 0x0079, 0x006E, 0x0053, 0x0044, 0x002E, + 0x000B, 0x00FC, 0x00D1, 0x008A, 0x0058, 0x01BD, 0x0116, 0x03F4, + 0x045D, +}; +static const uint16_t bitalloc_65_codes_d[65] = +{ + 0x70B0, 0x70B2, 0x70B4, 0x2852, 0x385B, 0x142E, 0x1C2E, 0x0A15, + 0x0E14, 0x0214, 0x0704, 0x0104, 0x010B, 0x0383, 0x0083, 0x0143, + 0x01C3, 0x0043, 0x00A2, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012, + 0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000, + 0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B, + 0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A3, 0x00A0, + 0x0040, 0x01C0, 0x0084, 0x0384, 0x0284, 0x0105, 0x0705, 0x0215, + 0x0E15, 0x0A16, 0x1C2F, 0x142F, 0x1428, 0x2853, 0x70B5, 0x70B3, + 0x70B1, +}; +static const uint16_t bitalloc_65_codes_e[65] = +{ + 0x032C, 0x0332, 0x0378, 0x037E, 0x008C, 0x014A, 0x0188, 0x0197, + 0x019E, 0x01BD, 0x0044, 0x0047, 0x00AA, 0x00C5, 0x00CD, 0x00DC, + 0x001C, 0x002C, 0x0053, 0x0063, 0x0068, 0x0008, 0x000F, 0x0017, + 0x002B, 0x0035, 0x0005, 0x0009, 0x0016, 0x001C, 0x0006, 0x000F, + 0x0004, 0x0000, 0x0007, 0x001D, 0x0017, 0x000A, 0x0006, 0x0036, + 0x0030, 0x0028, 0x0010, 0x0009, 0x0069, 0x0064, 0x0054, 0x002D, + 0x001D, 0x00DD, 0x00CE, 0x00CA, 0x00AB, 0x00A4, 0x0045, 0x01BE, + 0x019F, 0x0198, 0x0189, 0x014B, 0x008D, 0x037F, 0x0379, 0x0333, + 0x032D, +}; +static const uint16_t bitalloc_65_codes_f[65] = +{ + 0x0FE0, 0x0FE2, 0x0FE8, 0x0FEA, 0x0FEC, 0x0FEE, 0x0FF0, 0x0FF2, + 0x0FF4, 0x2FF2, 0x07F2, 0x07FB, 0x03F6, 0x0BFA, 0x0BFD, 0x01FF, + 0x05FF, 0x02FC, 0x007C, 0x017C, 0x003C, 0x00BC, 0x001C, 0x005C, + 0x000C, 0x002C, 0x0004, 0x0014, 0x0000, 0x0008, 0x000E, 0x0002, + 0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0015, 0x0005, 0x002D, + 0x000D, 0x005D, 0x001D, 0x00BD, 0x003D, 0x017D, 0x007D, 0x02FD, + 0x00FC, 0x05FC, 0x01FA, 0x0BFB, 0x03F7, 0x17F8, 0x07F3, 0x2FF3, + 0x0FF5, 0x0FF3, 0x0FF1, 0x0FEF, 0x0FED, 0x0FEB, 0x0FE9, 0x0FE3, + 0x0FE1, +}; +static const uint16_t bitalloc_65_codes_g[65] = +{ + 0x010C, 0x038A, 0x0608, 0x0786, 0x0084, 0x0087, 0x0302, 0x0305, + 0x0040, 0x00E0, 0x00E3, 0x0183, 0x001E, 0x005E, 0x009E, 0x00DE, + 0x00F1, 0x0011, 0x0039, 0x0061, 0x0079, 0x0009, 0x001D, 0x0031, + 0x003D, 0x0005, 0x000F, 0x0019, 0x001F, 0x0003, 0x0006, 0x000A, + 0x000E, 0x000B, 0x0008, 0x0004, 0x0000, 0x001A, 0x0012, 0x000A, + 0x0002, 0x0036, 0x0026, 0x0016, 0x0006, 0x006E, 0x004E, 0x002E, + 0x000E, 0x00DF, 0x009F, 0x005F, 0x001F, 0x01E0, 0x0180, 0x00E1, + 0x0041, 0x03C2, 0x0303, 0x01C4, 0x0085, 0x0787, 0x0609, 0x038B, + 0x010D, +}; +static const uint8_t bitalloc_65_bits_a[65] = +{ + 16, 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, + 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 7, 7, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 13, 13, 14, 15, 16, + 16, +}; +static const uint8_t bitalloc_65_bits_b[65] = +{ + 12, 11, 10, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, + 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 4, + 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 10, 10, + 12, +}; +static const uint8_t bitalloc_65_bits_c[65] = +{ + 11, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, + 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 10, + 11, +}; +static const uint8_t bitalloc_65_bits_d[65] = +{ + 15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 10, 9, 9, + 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 3, + 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, + 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 15, 15, + 15, +}; +static const uint8_t bitalloc_65_bits_e[65] = +{ + 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, + 3, 3, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10, +}; +static const uint8_t bitalloc_65_bits_f[65] = +{ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11, + 11, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3, + 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, +}; +static const uint8_t bitalloc_65_bits_g[65] = +{ + 11, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, + 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, + 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, + 11, +}; + +static const uint16_t bitalloc_129_codes_a[129] = +{ + 0x0660, 0x0666, 0x06EC, 0x0722, 0x0760, 0x076E, 0x004C, 0x004E, + 0x00F4, 0x010A, 0x0148, 0x0156, 0x01D4, 0x01F2, 0x0331, 0x0370, + 0x0377, 0x0396, 0x03B1, 0x0024, 0x0064, 0x007B, 0x008A, 0x00A5, + 0x00D4, 0x00EB, 0x00FA, 0x019A, 0x01B9, 0x01C9, 0x01D9, 0x0010, + 0x0030, 0x0033, 0x0043, 0x0053, 0x006B, 0x007A, 0x00CA, 0x00D2, + 0x00DE, 0x00E6, 0x00F6, 0x000E, 0x001F, 0x0023, 0x002B, 0x003B, + 0x003F, 0x0067, 0x0070, 0x0077, 0x0005, 0x000D, 0x0012, 0x001B, + 0x002C, 0x0035, 0x003A, 0x0004, 0x000B, 0x0017, 0x001F, 0x0009, + 0x0008, 0x000A, 0x0000, 0x0018, 0x000C, 0x0005, 0x003C, 0x0036, + 0x002D, 0x001C, 0x0013, 0x000E, 0x0006, 0x007A, 0x0071, 0x0068, + 0x0064, 0x003C, 0x0034, 0x0028, 0x0020, 0x000F, 0x00F7, 0x00E7, + 0x00DF, 0x00D3, 0x00CB, 0x007B, 0x0074, 0x0054, 0x0044, 0x003C, + 0x0031, 0x0011, 0x01DA, 0x01CA, 0x01BA, 0x019B, 0x00FB, 0x00F8, + 0x00D5, 0x00AA, 0x008B, 0x0084, 0x0065, 0x0025, 0x03B6, 0x0397, + 0x0390, 0x0371, 0x0332, 0x01F3, 0x01D5, 0x0157, 0x0149, 0x010B, + 0x00F5, 0x004F, 0x004D, 0x076F, 0x0761, 0x0723, 0x06ED, 0x0667, + 0x0661, +}; +static const uint16_t bitalloc_129_codes_b[129] = +{ + 0x29DC, 0x14EF, 0x0455, 0x0E9C, 0x022B, 0x0489, 0x0740, 0x074F, + 0x0172, 0x0245, 0x0247, 0x030A, 0x03A1, 0x001C, 0x008B, 0x00D6, + 0x010C, 0x0148, 0x014F, 0x0186, 0x01D1, 0x0008, 0x000F, 0x0046, + 0x005D, 0x0078, 0x0087, 0x0096, 0x00A5, 0x00BC, 0x00D8, 0x00DE, + 0x00F6, 0x0005, 0x0014, 0x0024, 0x002F, 0x003A, 0x003D, 0x0049, + 0x0050, 0x0058, 0x005F, 0x0066, 0x006D, 0x0075, 0x007C, 0x0004, + 0x000B, 0x0013, 0x0018, 0x001B, 0x001F, 0x0022, 0x0026, 0x002A, + 0x002D, 0x0031, 0x0034, 0x0038, 0x003B, 0x003F, 0x0003, 0x0006, + 0x000A, 0x0007, 0x0004, 0x0000, 0x003C, 0x0039, 0x0035, 0x0032, + 0x002E, 0x002B, 0x0027, 0x0023, 0x0020, 0x001C, 0x0019, 0x0016, + 0x0010, 0x0005, 0x007D, 0x007A, 0x006E, 0x0067, 0x0060, 0x0059, + 0x0051, 0x004A, 0x0042, 0x003B, 0x0034, 0x0025, 0x0015, 0x0006, + 0x00F7, 0x00DF, 0x00D9, 0x00BD, 0x00A6, 0x0097, 0x0090, 0x0079, + 0x006A, 0x0047, 0x0044, 0x0009, 0x01D2, 0x0187, 0x0184, 0x0149, + 0x010D, 0x00D7, 0x00B8, 0x001D, 0x03A6, 0x030B, 0x029C, 0x0246, + 0x0173, 0x0114, 0x0741, 0x053A, 0x0488, 0x0E9D, 0x0A76, 0x0454, + 0x29DD, +}; +static const uint16_t bitalloc_129_codes_c[129] = +{ + 0x0E5C, 0x072F, 0x001D, 0x0724, 0x000F, 0x010D, 0x0324, 0x0393, + 0x03E9, 0x0080, 0x0087, 0x00FA, 0x0164, 0x0193, 0x01DE, 0x01F5, + 0x0010, 0x002A, 0x0041, 0x0064, 0x0073, 0x008E, 0x00A4, 0x00B3, + 0x00D6, 0x00E5, 0x00F4, 0x00FB, 0x0002, 0x0009, 0x0013, 0x001E, + 0x0026, 0x002C, 0x0033, 0x003F, 0x0041, 0x004C, 0x0053, 0x005E, + 0x0065, 0x0070, 0x0073, 0x0078, 0x007B, 0x007E, 0x0002, 0x0005, + 0x0007, 0x000B, 0x000D, 0x0011, 0x0014, 0x0017, 0x001A, 0x001D, + 0x0021, 0x0024, 0x0027, 0x002A, 0x002D, 0x0030, 0x0033, 0x0036, + 0x003A, 0x0037, 0x0034, 0x0031, 0x002E, 0x002B, 0x0028, 0x0025, + 0x0022, 0x001E, 0x001B, 0x0018, 0x0015, 0x0012, 0x000E, 0x000C, + 0x0008, 0x0006, 0x0003, 0x007F, 0x007C, 0x0079, 0x0076, 0x0071, + 0x006A, 0x005F, 0x0058, 0x004D, 0x0046, 0x0040, 0x0038, 0x002D, + 0x0027, 0x001F, 0x0014, 0x0012, 0x0003, 0x0000, 0x00F5, 0x00EE, + 0x00D7, 0x00C8, 0x00A5, 0x008F, 0x007C, 0x0065, 0x0042, 0x002B, + 0x0011, 0x0002, 0x01DF, 0x01C8, 0x0165, 0x00FB, 0x00E4, 0x0081, + 0x0006, 0x03E8, 0x0325, 0x01CA, 0x010C, 0x0725, 0x0396, 0x001C, + 0x0E5D, +}; +static const uint16_t bitalloc_129_codes_d[129] = +{ + 0xA598, 0xA59A, 0xA59C, 0xA59E, 0xC598, 0xE586, 0x3ACC, 0x52CA, + 0x62CD, 0x0D48, 0x1D67, 0x2978, 0x3167, 0x3966, 0x06A5, 0x0EBC, + 0x14BD, 0x1CB1, 0x0350, 0x0353, 0x075F, 0x0A5F, 0x0C5E, 0x0E5E, + 0x01AE, 0x03AD, 0x052D, 0x062D, 0x072D, 0x00D5, 0x01D4, 0x0294, + 0x0314, 0x0394, 0x0014, 0x0094, 0x0114, 0x0174, 0x01B4, 0x01F4, + 0x000B, 0x004B, 0x008B, 0x00BB, 0x00DB, 0x00FB, 0x001B, 0x003B, + 0x0053, 0x0063, 0x0073, 0x0003, 0x0013, 0x0023, 0x002F, 0x0037, + 0x003F, 0x0007, 0x000F, 0x0015, 0x0019, 0x001D, 0x0001, 0x0005, + 0x0009, 0x0006, 0x0002, 0x001E, 0x001A, 0x0016, 0x0010, 0x0008, + 0x0000, 0x0038, 0x0030, 0x0028, 0x001C, 0x000C, 0x007C, 0x006C, + 0x005C, 0x0044, 0x0024, 0x0004, 0x00E4, 0x00C4, 0x00A4, 0x0074, + 0x0034, 0x01F5, 0x01B5, 0x0175, 0x0115, 0x0095, 0x0015, 0x0395, + 0x0315, 0x0295, 0x01D5, 0x00D6, 0x072E, 0x062E, 0x052E, 0x03AE, + 0x01AF, 0x0E5F, 0x0C5F, 0x0C58, 0x0A58, 0x0758, 0x0351, 0x1CB2, + 0x18B2, 0x0EBD, 0x0EB2, 0x3967, 0x3960, 0x2979, 0x2964, 0x0D49, + 0x72C2, 0x52CB, 0x3ACD, 0xE587, 0xC599, 0xA59F, 0xA59D, 0xA59B, + 0xA599, +}; +static const uint16_t bitalloc_129_codes_e[129] = +{ + 0xA13C, 0xC720, 0xA13F, 0xA13E, 0xA13D, 0xE722, 0x5090, 0x6393, + 0x7392, 0x2849, 0x31CE, 0x39CE, 0x1425, 0x18E5, 0x1CE5, 0x0844, + 0x0A1C, 0x0C7C, 0x036C, 0x0423, 0x050F, 0x063F, 0x01B7, 0x0216, + 0x0285, 0x031D, 0x039D, 0x0109, 0x0140, 0x0180, 0x01C8, 0x01CF, + 0x007A, 0x008A, 0x00A2, 0x00C1, 0x00E5, 0x0014, 0x0037, 0x0043, + 0x004E, 0x0056, 0x0061, 0x006C, 0x007C, 0x000B, 0x001C, 0x001F, + 0x0023, 0x0025, 0x0029, 0x002C, 0x002E, 0x0032, 0x0034, 0x0037, + 0x003A, 0x003C, 0x003F, 0x0001, 0x0003, 0x0006, 0x0008, 0x000A, + 0x000C, 0x000B, 0x0009, 0x0007, 0x0004, 0x0002, 0x0000, 0x003D, + 0x003B, 0x0038, 0x0035, 0x0033, 0x002F, 0x002D, 0x002A, 0x0026, + 0x0024, 0x0020, 0x001D, 0x001A, 0x007D, 0x006D, 0x0062, 0x0057, + 0x004F, 0x0044, 0x003C, 0x0015, 0x00E6, 0x00C6, 0x00A3, 0x008B, + 0x007B, 0x006C, 0x01C9, 0x0181, 0x0141, 0x010A, 0x00DA, 0x031E, + 0x0286, 0x0217, 0x0210, 0x0738, 0x0638, 0x0508, 0x036D, 0x0C7D, + 0x0A1D, 0x0845, 0x1CE6, 0x18E6, 0x1426, 0x39CF, 0x31CF, 0x284E, + 0x7393, 0x7390, 0x5091, 0xE723, 0xC724, 0xC725, 0xC722, 0xC723, + 0xC721, +}; +static const uint16_t bitalloc_129_codes_f[129] = +{ + 0x762C, 0x3B17, 0x1555, 0x0608, 0x0AAB, 0x0FF2, 0x0305, 0x0307, + 0x0763, 0x0046, 0x010C, 0x01BC, 0x02AB, 0x03B6, 0x03FD, 0x0080, + 0x0087, 0x00DF, 0x0156, 0x01D9, 0x01F8, 0x01FF, 0x002A, 0x0041, + 0x0061, 0x0094, 0x00D4, 0x00EA, 0x00F2, 0x00FD, 0x0009, 0x000B, + 0x001A, 0x0026, 0x0031, 0x0040, 0x004B, 0x006B, 0x0073, 0x0077, + 0x007A, 0x007C, 0x0000, 0x0002, 0x0006, 0x0008, 0x000B, 0x000E, + 0x0011, 0x0014, 0x0016, 0x0019, 0x001C, 0x001E, 0x0021, 0x0023, + 0x0026, 0x0028, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0036, + 0x0038, 0x0037, 0x0034, 0x0032, 0x0030, 0x002E, 0x002C, 0x0029, + 0x0027, 0x0024, 0x0022, 0x001F, 0x001D, 0x001A, 0x0017, 0x0015, + 0x0012, 0x000F, 0x000C, 0x0009, 0x0007, 0x0003, 0x0001, 0x007D, + 0x007B, 0x0078, 0x0074, 0x0072, 0x0054, 0x0041, 0x0036, 0x0027, + 0x001B, 0x0014, 0x000A, 0x00FE, 0x00F3, 0x00EB, 0x00D5, 0x0095, + 0x006E, 0x0042, 0x002B, 0x0010, 0x01F9, 0x01DA, 0x0157, 0x0154, + 0x00C0, 0x0081, 0x0022, 0x03B7, 0x03B0, 0x01BD, 0x010D, 0x0047, + 0x07F8, 0x0554, 0x0306, 0x0FF3, 0x0EC4, 0x0609, 0x1D8A, 0x1554, + 0x762D, +}; +static const uint16_t bitalloc_129_codes_g[129] = +{ + 0x1E20, 0x1E5E, 0x031C, 0x051A, 0x0718, 0x0916, 0x0B14, 0x0D12, + 0x0F11, 0x0090, 0x018F, 0x028E, 0x038D, 0x048C, 0x058B, 0x068A, + 0x0789, 0x0049, 0x00C8, 0x0148, 0x01C7, 0x0247, 0x02C6, 0x0346, + 0x03C5, 0x0025, 0x0065, 0x00A5, 0x00E4, 0x0124, 0x0164, 0x01A4, + 0x01E3, 0x0013, 0x0033, 0x0053, 0x0073, 0x0093, 0x00B3, 0x00D3, + 0x00F3, 0x000A, 0x001A, 0x002A, 0x003A, 0x004A, 0x005A, 0x006A, + 0x007A, 0x0006, 0x000E, 0x0016, 0x001E, 0x0026, 0x002E, 0x0036, + 0x003E, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, + 0x0000, 0x001D, 0x0019, 0x0015, 0x0011, 0x000D, 0x0009, 0x0005, + 0x003F, 0x0037, 0x002F, 0x0027, 0x001F, 0x0017, 0x000F, 0x0007, + 0x007B, 0x006B, 0x005B, 0x004B, 0x003B, 0x002B, 0x001B, 0x000B, + 0x0008, 0x00F0, 0x00D0, 0x00B0, 0x0090, 0x0070, 0x0050, 0x0030, + 0x01E4, 0x01A5, 0x0165, 0x0125, 0x00E5, 0x00E2, 0x00A2, 0x0062, + 0x03CA, 0x0347, 0x02C7, 0x02C4, 0x0244, 0x0149, 0x00C9, 0x00C6, + 0x0796, 0x068B, 0x0688, 0x048D, 0x048A, 0x028F, 0x028C, 0x0091, + 0x0F2E, 0x0D13, 0x0B15, 0x0917, 0x0719, 0x051B, 0x031D, 0x1E5F, + 0x1E21, +}; +static const uint8_t bitalloc_129_bits_a[129] = +{ + 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 4, + 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, +}; +static const uint8_t bitalloc_129_bits_b[129] = +{ + 14, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, + 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, + 14, +}; +static const uint8_t bitalloc_129_bits_c[129] = +{ + 13, 12, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, + 13, +}; +static const uint8_t bitalloc_129_bits_d[129] = +{ + 16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10, + 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, + 7, 7, 7, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, + 16, +}; +static const uint8_t bitalloc_129_bits_e[129] = +{ + 16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, + 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, + 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, + 16, +}; +static const uint8_t bitalloc_129_bits_f[129] = +{ + 15, 14, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 10, 10, 9, + 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, + 15, +}; +static const uint8_t bitalloc_129_bits_g[129] = +{ + 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, + 9, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, + 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, + 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13, + 13, +}; + +static const uint8_t bitalloc_sizes[10] = { 3, 5, 7, 9, 13, 17, 25, 33, 65, 129 }; + +static const int8_t bitalloc_offsets[10] = + { -1, -2, -3, -4, -6, -8, -12, -16, -32, -64 }; + +static const uint8_t bitalloc_maxbits[10][7] = { + { 2 }, + { 4, 3, 3 }, + { 5, 5, 4 }, + { 6, 5, 6 }, + { 7, 6, 5 }, + { 9, 8, 7, 9, 8, 8, 8 }, + { 9, 9, 8, 9, 8, 9, 9 }, + { 9, 9, 9, 9, 9, 9, 9 }, + { 9, 9, 9, 9, 9, 9, 9 }, + { 9, 9, 9, 9, 9, 9, 9 } +}; + +static const uint16_t* const bitalloc_codes[10][8] = { + { bitalloc_3_codes, NULL }, + { bitalloc_5_codes_a, bitalloc_5_codes_b, bitalloc_5_codes_c, NULL }, + { bitalloc_7_codes_a, bitalloc_7_codes_b, bitalloc_7_codes_c, NULL }, + { bitalloc_9_codes_a, bitalloc_9_codes_b, bitalloc_9_codes_c, NULL }, + { bitalloc_13_codes_a, bitalloc_13_codes_b, bitalloc_13_codes_c, NULL }, + { bitalloc_17_codes_a, bitalloc_17_codes_b, bitalloc_17_codes_c, bitalloc_17_codes_d, + bitalloc_17_codes_e, bitalloc_17_codes_f, bitalloc_17_codes_g, NULL }, + { bitalloc_25_codes_a, bitalloc_25_codes_b, bitalloc_25_codes_c, bitalloc_25_codes_d, + bitalloc_25_codes_e, bitalloc_25_codes_f, bitalloc_25_codes_g, NULL }, + { bitalloc_33_codes_a, bitalloc_33_codes_b, bitalloc_33_codes_c, bitalloc_33_codes_d, + bitalloc_33_codes_e, bitalloc_33_codes_f, bitalloc_33_codes_g, NULL }, + { bitalloc_65_codes_a, bitalloc_65_codes_b, bitalloc_65_codes_c, bitalloc_65_codes_d, + bitalloc_65_codes_e, bitalloc_65_codes_f, bitalloc_65_codes_g, NULL }, + { bitalloc_129_codes_a, bitalloc_129_codes_b, bitalloc_129_codes_c, bitalloc_129_codes_d, + bitalloc_129_codes_e, bitalloc_129_codes_f, bitalloc_129_codes_g, NULL } +}; + +static const uint8_t* const bitalloc_bits[10][8] = { + { bitalloc_3_bits, NULL }, + { bitalloc_5_bits_a, bitalloc_5_bits_b, bitalloc_5_bits_c, NULL }, + { bitalloc_7_bits_a, bitalloc_7_bits_b, bitalloc_7_bits_c, NULL }, + { bitalloc_9_bits_a, bitalloc_9_bits_b, bitalloc_9_bits_c, NULL }, + { bitalloc_13_bits_a, bitalloc_13_bits_b, bitalloc_13_bits_c, NULL }, + { bitalloc_17_bits_a, bitalloc_17_bits_b, bitalloc_17_bits_c, bitalloc_17_bits_d, + bitalloc_17_bits_e, bitalloc_17_bits_f, bitalloc_17_bits_g, NULL }, + { bitalloc_25_bits_a, bitalloc_25_bits_b, bitalloc_25_bits_c, bitalloc_25_bits_d, + bitalloc_25_bits_e, bitalloc_25_bits_f, bitalloc_25_bits_g, NULL }, + { bitalloc_33_bits_a, bitalloc_33_bits_b, bitalloc_33_bits_c, bitalloc_33_bits_d, + bitalloc_33_bits_e, bitalloc_33_bits_f, bitalloc_33_bits_g, NULL }, + { bitalloc_65_bits_a, bitalloc_65_bits_b, bitalloc_65_bits_c, bitalloc_65_bits_d, + bitalloc_65_bits_e, bitalloc_65_bits_f, bitalloc_65_bits_g, NULL }, + { bitalloc_129_bits_a, bitalloc_129_bits_b, bitalloc_129_bits_c, bitalloc_129_bits_d, + bitalloc_129_bits_e, bitalloc_129_bits_f, bitalloc_129_bits_g, NULL } +}; + +#endif /* AVCODEC_DCAHUFF_H */ diff --git a/ffmpeg/libavcodec/dct-test.c b/ffmpeg/libavcodec/dct-test.c new file mode 100644 index 0000000..3647336 --- /dev/null +++ b/ffmpeg/libavcodec/dct-test.c @@ -0,0 +1,576 @@ +/* + * (c) 2001 Fabrice Bellard + * 2007 Marc Hoffman + * + * 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 + */ + +/** + * @file + * DCT test (c) 2001 Fabrice Bellard + * Started from sample code by Juan J. Sierralta P. + */ + +#include "config.h" +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include + +#include "libavutil/cpu.h" +#include "libavutil/common.h" +#include "libavutil/lfg.h" +#include "libavutil/time.h" + +#include "dct.h" +#include "simple_idct.h" +#include "aandcttab.h" +#include "faandct.h" +#include "faanidct.h" +#include "x86/idct_xvid.h" +#include "dctref.h" + +#undef printf + +// BFIN +void ff_bfin_idct(int16_t *block); +void ff_bfin_fdct(int16_t *block); + +// ALTIVEC +void ff_fdct_altivec(int16_t *block); + +// ARM +void ff_j_rev_dct_arm(int16_t *data); +void ff_simple_idct_arm(int16_t *data); +void ff_simple_idct_armv5te(int16_t *data); +void ff_simple_idct_armv6(int16_t *data); +void ff_simple_idct_neon(int16_t *data); + +void ff_simple_idct_axp(int16_t *data); + +struct algo { + const char *name; + void (*func)(int16_t *block); + enum formattag { NO_PERM, MMX_PERM, MMX_SIMPLE_PERM, SCALE_PERM, + SSE2_PERM, PARTTRANS_PERM, TRANSPOSE_PERM } format; + int mm_support; + int nonspec; +}; + +static int cpu_flags; + +static const struct algo fdct_tab[] = { + { "REF-DBL", ff_ref_fdct, NO_PERM }, + { "FAAN", ff_faandct, NO_PERM }, + { "IJG-AAN-INT", ff_fdct_ifast, SCALE_PERM }, + { "IJG-LLM-INT", ff_jpeg_fdct_islow_8, NO_PERM }, + +#if HAVE_MMX_INLINE + { "MMX", ff_fdct_mmx, NO_PERM, AV_CPU_FLAG_MMX }, + { "MMXEXT", ff_fdct_mmxext, NO_PERM, AV_CPU_FLAG_MMXEXT }, + { "SSE2", ff_fdct_sse2, NO_PERM, AV_CPU_FLAG_SSE2 }, +#endif + +#if HAVE_ALTIVEC + { "altivecfdct", ff_fdct_altivec, NO_PERM, AV_CPU_FLAG_ALTIVEC }, +#endif + +#if ARCH_BFIN + { "BFINfdct", ff_bfin_fdct, NO_PERM }, +#endif + + { 0 } +}; + +#if ARCH_X86_64 && HAVE_MMX && HAVE_YASM +void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize, + int16_t *block, int16_t *qmat); + +static void ff_prores_idct_put_10_sse2_wrap(int16_t *dst){ + DECLARE_ALIGNED(16, static int16_t, qmat)[64]; + DECLARE_ALIGNED(16, static int16_t, tmp)[64]; + int i; + + for(i=0; i<64; i++){ + qmat[i]=4; + tmp[i]= dst[i]; + } + ff_prores_idct_put_10_sse2(dst, 16, tmp, qmat); +} +#endif + +static const struct algo idct_tab[] = { + { "FAANI", ff_faanidct, NO_PERM }, + { "REF-DBL", ff_ref_idct, NO_PERM }, + { "INT", ff_j_rev_dct, MMX_PERM }, + { "SIMPLE-C", ff_simple_idct_8, NO_PERM }, + +#if HAVE_MMX_INLINE + { "SIMPLE-MMX", ff_simple_idct_mmx, MMX_SIMPLE_PERM, AV_CPU_FLAG_MMX }, + { "XVID-MMX", ff_idct_xvid_mmx, NO_PERM, AV_CPU_FLAG_MMX, 1 }, + { "XVID-MMXEXT", ff_idct_xvid_mmxext, NO_PERM, AV_CPU_FLAG_MMXEXT, 1 }, + { "XVID-SSE2", ff_idct_xvid_sse2, SSE2_PERM, AV_CPU_FLAG_SSE2, 1 }, +#if ARCH_X86_64 && HAVE_YASM + { "PR-SSE2", ff_prores_idct_put_10_sse2_wrap, TRANSPOSE_PERM, AV_CPU_FLAG_SSE2, 1 }, +#endif +#endif + +#if ARCH_BFIN + { "BFINidct", ff_bfin_idct, NO_PERM }, +#endif + +#if ARCH_ARM + { "SIMPLE-ARM", ff_simple_idct_arm, NO_PERM }, + { "INT-ARM", ff_j_rev_dct_arm, MMX_PERM }, +#endif +#if HAVE_ARMV5TE + { "SIMPLE-ARMV5TE", ff_simple_idct_armv5te,NO_PERM, AV_CPU_FLAG_ARMV5TE }, +#endif +#if HAVE_ARMV6 + { "SIMPLE-ARMV6", ff_simple_idct_armv6, MMX_PERM, AV_CPU_FLAG_ARMV6 }, +#endif +#if HAVE_NEON + { "SIMPLE-NEON", ff_simple_idct_neon, PARTTRANS_PERM, AV_CPU_FLAG_NEON }, +#endif + +#if ARCH_ALPHA + { "SIMPLE-ALPHA", ff_simple_idct_axp, NO_PERM }, +#endif + + { 0 } +}; + +#define AANSCALE_BITS 12 + +#define NB_ITS 20000 +#define NB_ITS_SPEED 50000 + +static short idct_mmx_perm[64]; + +static short idct_simple_mmx_perm[64] = { + 0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D, + 0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D, + 0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D, + 0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F, + 0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F, + 0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D, + 0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F, + 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, +}; + +static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 }; + +static void idct_mmx_init(void) +{ + int i; + + /* the mmx/mmxext idct uses a reordered input, so we patch scan tables */ + for (i = 0; i < 64; i++) { + idct_mmx_perm[i] = (i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2); + } +} + +DECLARE_ALIGNED(16, static int16_t, block)[64]; +DECLARE_ALIGNED(8, static int16_t, block1)[64]; + +static void init_block(int16_t block[64], int test, int is_idct, AVLFG *prng, int vals) +{ + int i, j; + + memset(block, 0, 64 * sizeof(*block)); + + switch (test) { + case 0: + for (i = 0; i < 64; i++) + block[i] = (av_lfg_get(prng) % (2*vals)) -vals; + if (is_idct) { + ff_ref_fdct(block); + for (i = 0; i < 64; i++) + block[i] >>= 3; + } + break; + case 1: + j = av_lfg_get(prng) % 10 + 1; + for (i = 0; i < j; i++) { + int idx = av_lfg_get(prng) % 64; + block[idx] = av_lfg_get(prng) % (2*vals) -vals; + } + break; + case 2: + block[ 0] = av_lfg_get(prng) % (16*vals) - (8*vals); + block[63] = (block[0] & 1) ^ 1; + break; + } +} + +static void permute(int16_t dst[64], const int16_t src[64], int perm) +{ + int i; + + if (perm == MMX_PERM) { + for (i = 0; i < 64; i++) + dst[idct_mmx_perm[i]] = src[i]; + } else if (perm == MMX_SIMPLE_PERM) { + for (i = 0; i < 64; i++) + dst[idct_simple_mmx_perm[i]] = src[i]; + } else if (perm == SSE2_PERM) { + for (i = 0; i < 64; i++) + dst[(i & 0x38) | idct_sse2_row_perm[i & 7]] = src[i]; + } else if (perm == PARTTRANS_PERM) { + for (i = 0; i < 64; i++) + dst[(i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3)] = src[i]; + } else if (perm == TRANSPOSE_PERM) { + for (i = 0; i < 64; i++) + dst[(i>>3) | ((i<<3)&0x38)] = src[i]; + } else { + for (i = 0; i < 64; i++) + dst[i] = src[i]; + } +} + +static int dct_error(const struct algo *dct, int test, int is_idct, int speed, const int bits) +{ + void (*ref)(int16_t *block) = is_idct ? ff_ref_idct : ff_ref_fdct; + int it, i, scale; + int err_inf, v; + int64_t err2, ti, ti1, it1, err_sum = 0; + int64_t sysErr[64], sysErrMax = 0; + int maxout = 0; + int blockSumErrMax = 0, blockSumErr; + AVLFG prng; + const int vals=1<format); + + dct->func(block); + emms_c(); + + if (dct->format == SCALE_PERM) { + for (i = 0; i < 64; i++) { + scale = 8 * (1 << (AANSCALE_BITS + 11)) / ff_aanscales[i]; + block[i] = (block[i] * scale) >> AANSCALE_BITS; + } + } + + ref(block1); + + blockSumErr = 0; + for (i = 0; i < 64; i++) { + int err = block[i] - block1[i]; + err_sum += err; + v = abs(err); + if (v > err_inf) + err_inf = v; + err2 += v * v; + sysErr[i] += block[i] - block1[i]; + blockSumErr += v; + if (abs(block[i]) > maxout) + maxout = abs(block[i]); + } + if (blockSumErrMax < blockSumErr) + blockSumErrMax = blockSumErr; + } + for (i = 0; i < 64; i++) + sysErrMax = FFMAX(sysErrMax, FFABS(sysErr[i])); + + for (i = 0; i < 64; i++) { + if (i % 8 == 0) + printf("\n"); + printf("%7d ", (int) sysErr[i]); + } + printf("\n"); + + omse = (double) err2 / NB_ITS / 64; + ome = (double) err_sum / NB_ITS / 64; + + spec_err = is_idct && (err_inf > 1 || omse > 0.02 || fabs(ome) > 0.0015); + + printf("%s %s: max_err=%d omse=%0.8f ome=%0.8f syserr=%0.8f maxout=%d blockSumErr=%d\n", + is_idct ? "IDCT" : "DCT", dct->name, err_inf, + omse, ome, (double) sysErrMax / NB_ITS, + maxout, blockSumErrMax); + + if (spec_err && !dct->nonspec) + return 1; + + if (!speed) + return 0; + + /* speed test */ + + init_block(block, test, is_idct, &prng, vals); + permute(block1, block, dct->format); + + ti = av_gettime(); + it1 = 0; + do { + for (it = 0; it < NB_ITS_SPEED; it++) { + memcpy(block, block1, sizeof(block)); + dct->func(block); + } + emms_c(); + it1 += NB_ITS_SPEED; + ti1 = av_gettime() - ti; + } while (ti1 < 1000000); + + printf("%s %s: %0.1f kdct/s\n", is_idct ? "IDCT" : "DCT", dct->name, + (double) it1 * 1000.0 / (double) ti1); + + return 0; +} + +DECLARE_ALIGNED(8, static uint8_t, img_dest)[64]; +DECLARE_ALIGNED(8, static uint8_t, img_dest1)[64]; + +static void idct248_ref(uint8_t *dest, int linesize, int16_t *block) +{ + static int init; + static double c8[8][8]; + static double c4[4][4]; + double block1[64], block2[64], block3[64]; + double s, sum, v; + int i, j, k; + + if (!init) { + init = 1; + + for (i = 0; i < 8; i++) { + sum = 0; + for (j = 0; j < 8; j++) { + s = (i == 0) ? sqrt(1.0 / 8.0) : sqrt(1.0 / 4.0); + c8[i][j] = s * cos(M_PI * i * (j + 0.5) / 8.0); + sum += c8[i][j] * c8[i][j]; + } + } + + for (i = 0; i < 4; i++) { + sum = 0; + for (j = 0; j < 4; j++) { + s = (i == 0) ? sqrt(1.0 / 4.0) : sqrt(1.0 / 2.0); + c4[i][j] = s * cos(M_PI * i * (j + 0.5) / 4.0); + sum += c4[i][j] * c4[i][j]; + } + } + } + + /* butterfly */ + s = 0.5 * sqrt(2.0); + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) { + block1[8 * (2 * i) + j] = + (block[8 * (2 * i) + j] + block[8 * (2 * i + 1) + j]) * s; + block1[8 * (2 * i + 1) + j] = + (block[8 * (2 * i) + j] - block[8 * (2 * i + 1) + j]) * s; + } + } + + /* idct8 on lines */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + sum = 0; + for (k = 0; k < 8; k++) + sum += c8[k][j] * block1[8 * i + k]; + block2[8 * i + j] = sum; + } + } + + /* idct4 */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 4; j++) { + /* top */ + sum = 0; + for (k = 0; k < 4; k++) + sum += c4[k][j] * block2[8 * (2 * k) + i]; + block3[8 * (2 * j) + i] = sum; + + /* bottom */ + sum = 0; + for (k = 0; k < 4; k++) + sum += c4[k][j] * block2[8 * (2 * k + 1) + i]; + block3[8 * (2 * j + 1) + i] = sum; + } + } + + /* clamp and store the result */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + v = block3[8 * i + j]; + if (v < 0) v = 0; + else if (v > 255) v = 255; + dest[i * linesize + j] = (int) rint(v); + } + } +} + +static void idct248_error(const char *name, + void (*idct248_put)(uint8_t *dest, int line_size, + int16_t *block), + int speed) +{ + int it, i, it1, ti, ti1, err_max, v; + AVLFG prng; + + av_lfg_init(&prng, 1); + + /* just one test to see if code is correct (precision is less + important here) */ + err_max = 0; + for (it = 0; it < NB_ITS; it++) { + /* XXX: use forward transform to generate values */ + for (i = 0; i < 64; i++) + block1[i] = av_lfg_get(&prng) % 256 - 128; + block1[0] += 1024; + + for (i = 0; i < 64; i++) + block[i] = block1[i]; + idct248_ref(img_dest1, 8, block); + + for (i = 0; i < 64; i++) + block[i] = block1[i]; + idct248_put(img_dest, 8, block); + + for (i = 0; i < 64; i++) { + v = abs((int) img_dest[i] - (int) img_dest1[i]); + if (v == 255) + printf("%d %d\n", img_dest[i], img_dest1[i]); + if (v > err_max) + err_max = v; + } +#if 0 + printf("ref=\n"); + for(i=0;i<8;i++) { + int j; + for(j=0;j<8;j++) { + printf(" %3d", img_dest1[i*8+j]); + } + printf("\n"); + } + + printf("out=\n"); + for(i=0;i<8;i++) { + int j; + for(j=0;j<8;j++) { + printf(" %3d", img_dest[i*8+j]); + } + printf("\n"); + } +#endif + } + printf("%s %s: err_inf=%d\n", 1 ? "IDCT248" : "DCT248", name, err_max); + + if (!speed) + return; + + ti = av_gettime(); + it1 = 0; + do { + for (it = 0; it < NB_ITS_SPEED; it++) { + for (i = 0; i < 64; i++) + block[i] = block1[i]; + idct248_put(img_dest, 8, block); + } + emms_c(); + it1 += NB_ITS_SPEED; + ti1 = av_gettime() - ti; + } while (ti1 < 1000000); + + printf("%s %s: %0.1f kdct/s\n", 1 ? "IDCT248" : "DCT248", name, + (double) it1 * 1000.0 / (double) ti1); +} + +static void help(void) +{ + printf("dct-test [-i] [] []\n" + "test-number 0 -> test with random matrixes\n" + " 1 -> test with random sparse matrixes\n" + " 2 -> do 3. test from mpeg4 std\n" + "bits Number of time domain bits to use, 8 is default\n" + "-i test IDCT implementations\n" + "-4 test IDCT248 implementations\n" + "-t speed test\n"); +} + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +int main(int argc, char **argv) +{ + int test_idct = 0, test_248_dct = 0; + int c, i; + int test = 1; + int speed = 0; + int err = 0; + int bits=8; + + cpu_flags = av_get_cpu_flags(); + + ff_ref_dct_init(); + idct_mmx_init(); + + for (;;) { + c = getopt(argc, argv, "ih4t"); + if (c == -1) + break; + switch (c) { + case 'i': + test_idct = 1; + break; + case '4': + test_248_dct = 1; + break; + case 't': + speed = 1; + break; + default: + case 'h': + help(); + return 0; + } + } + + if (optind < argc) + test = atoi(argv[optind]); + if(optind+1 < argc) bits= atoi(argv[optind+1]); + + printf("ffmpeg DCT/IDCT test\n"); + + if (test_248_dct) { + idct248_error("SIMPLE-C", ff_simple_idct248_put, speed); + } else { + const struct algo *algos = test_idct ? idct_tab : fdct_tab; + for (i = 0; algos[i].name; i++) + if (!(~cpu_flags & algos[i].mm_support)) { + err |= dct_error(&algos[i], test, test_idct, speed, bits); + } + } + + return err; +} diff --git a/ffmpeg/libavcodec/dct.c b/ffmpeg/libavcodec/dct.c new file mode 100644 index 0000000..e2ac0a8 --- /dev/null +++ b/ffmpeg/libavcodec/dct.c @@ -0,0 +1,222 @@ +/* + * (I)DCT Transforms + * Copyright (c) 2009 Peter Ross + * Copyright (c) 2010 Alex Converse + * Copyright (c) 2010 Vitor Sessak + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * (Inverse) Discrete Cosine Transforms. These are also known as the + * type II and type III DCTs respectively. + */ + +#include +#include + +#include "libavutil/mathematics.h" +#include "dct.h" +#include "dct32.h" + +/* sin((M_PI * x / (2 * n)) */ +#define SIN(s, n, x) (s->costab[(n) - (x)]) + +/* cos((M_PI * x / (2 * n)) */ +#define COS(s, n, x) (s->costab[x]) + +static void ff_dst_calc_I_c(DCTContext *ctx, FFTSample *data) +{ + int n = 1 << ctx->nbits; + int i; + + data[0] = 0; + for (i = 1; i < n / 2; i++) { + float tmp1 = data[i ]; + float tmp2 = data[n - i]; + float s = SIN(ctx, n, 2 * i); + + s *= tmp1 + tmp2; + tmp1 = (tmp1 - tmp2) * 0.5f; + data[i] = s + tmp1; + data[n - i] = s - tmp1; + } + + data[n / 2] *= 2; + ctx->rdft.rdft_calc(&ctx->rdft, data); + + data[0] *= 0.5f; + + for (i = 1; i < n - 2; i += 2) { + data[i + 1] += data[i - 1]; + data[i] = -data[i + 2]; + } + + data[n - 1] = 0; +} + +static void ff_dct_calc_I_c(DCTContext *ctx, FFTSample *data) +{ + int n = 1 << ctx->nbits; + int i; + float next = -0.5f * (data[0] - data[n]); + + for (i = 0; i < n / 2; i++) { + float tmp1 = data[i]; + float tmp2 = data[n - i]; + float s = SIN(ctx, n, 2 * i); + float c = COS(ctx, n, 2 * i); + + c *= tmp1 - tmp2; + s *= tmp1 - tmp2; + + next += c; + + tmp1 = (tmp1 + tmp2) * 0.5f; + data[i] = tmp1 - s; + data[n - i] = tmp1 + s; + } + + ctx->rdft.rdft_calc(&ctx->rdft, data); + data[n] = data[1]; + data[1] = next; + + for (i = 3; i <= n; i += 2) + data[i] = data[i - 2] - data[i]; +} + +static void ff_dct_calc_III_c(DCTContext *ctx, FFTSample *data) +{ + int n = 1 << ctx->nbits; + int i; + + float next = data[n - 1]; + float inv_n = 1.0f / n; + + for (i = n - 2; i >= 2; i -= 2) { + float val1 = data[i]; + float val2 = data[i - 1] - data[i + 1]; + float c = COS(ctx, n, i); + float s = SIN(ctx, n, i); + + data[i] = c * val1 + s * val2; + data[i + 1] = s * val1 - c * val2; + } + + data[1] = 2 * next; + + ctx->rdft.rdft_calc(&ctx->rdft, data); + + for (i = 0; i < n / 2; i++) { + float tmp1 = data[i] * inv_n; + float tmp2 = data[n - i - 1] * inv_n; + float csc = ctx->csc2[i] * (tmp1 - tmp2); + + tmp1 += tmp2; + data[i] = tmp1 + csc; + data[n - i - 1] = tmp1 - csc; + } +} + +static void ff_dct_calc_II_c(DCTContext *ctx, FFTSample *data) +{ + int n = 1 << ctx->nbits; + int i; + float next; + + for (i = 0; i < n / 2; i++) { + float tmp1 = data[i]; + float tmp2 = data[n - i - 1]; + float s = SIN(ctx, n, 2 * i + 1); + + s *= tmp1 - tmp2; + tmp1 = (tmp1 + tmp2) * 0.5f; + + data[i] = tmp1 + s; + data[n-i-1] = tmp1 - s; + } + + ctx->rdft.rdft_calc(&ctx->rdft, data); + + next = data[1] * 0.5; + data[1] *= -1; + + for (i = n - 2; i >= 0; i -= 2) { + float inr = data[i ]; + float ini = data[i + 1]; + float c = COS(ctx, n, i); + float s = SIN(ctx, n, i); + + data[i] = c * inr + s * ini; + data[i + 1] = next; + + next += s * inr - c * ini; + } +} + +static void dct32_func(DCTContext *ctx, FFTSample *data) +{ + ctx->dct32(data, data); +} + +av_cold int ff_dct_init(DCTContext *s, int nbits, enum DCTTransformType inverse) +{ + int n = 1 << nbits; + int i; + + memset(s, 0, sizeof(*s)); + + s->nbits = nbits; + s->inverse = inverse; + + if (inverse == DCT_II && nbits == 5) { + s->dct_calc = dct32_func; + } else { + ff_init_ff_cos_tabs(nbits + 2); + + s->costab = ff_cos_tabs[nbits + 2]; + s->csc2 = av_malloc(n / 2 * sizeof(FFTSample)); + + if (ff_rdft_init(&s->rdft, nbits, inverse == DCT_III) < 0) { + av_free(s->csc2); + return -1; + } + + for (i = 0; i < n / 2; i++) + s->csc2[i] = 0.5 / sin((M_PI / (2 * n) * (2 * i + 1))); + + switch (inverse) { + case DCT_I : s->dct_calc = ff_dct_calc_I_c; break; + case DCT_II : s->dct_calc = ff_dct_calc_II_c; break; + case DCT_III: s->dct_calc = ff_dct_calc_III_c; break; + case DST_I : s->dct_calc = ff_dst_calc_I_c; break; + } + } + + s->dct32 = ff_dct32_float; + if (ARCH_X86) + ff_dct_init_x86(s); + + return 0; +} + +av_cold void ff_dct_end(DCTContext *s) +{ + ff_rdft_end(&s->rdft); + av_free(s->csc2); +} diff --git a/ffmpeg/libavcodec/dct.h b/ffmpeg/libavcodec/dct.h new file mode 100644 index 0000000..a500521 --- /dev/null +++ b/ffmpeg/libavcodec/dct.h @@ -0,0 +1,70 @@ +/* + * (I)DCT Transforms + * Copyright (c) 2009 Peter Ross + * Copyright (c) 2010 Alex Converse + * Copyright (c) 2010 Vitor Sessak + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DCT_H +#define AVCODEC_DCT_H + +#include + +#include "rdft.h" + +struct DCTContext { + int nbits; + int inverse; + RDFTContext rdft; + const float *costab; + FFTSample *csc2; + void (*dct_calc)(struct DCTContext *s, FFTSample *data); + void (*dct32)(FFTSample *out, const FFTSample *in); +}; + +/** + * Set up DCT. + * @param nbits size of the input array: + * (1 << nbits) for DCT-II, DCT-III and DST-I + * (1 << nbits) + 1 for DCT-I + * + * @note the first element of the input of DST-I is ignored + */ +int ff_dct_init(DCTContext *s, int nbits, enum DCTTransformType type); +void ff_dct_end (DCTContext *s); + +void ff_dct_init_x86(DCTContext *s); + +void ff_fdct_ifast(int16_t *data); +void ff_fdct_ifast248(int16_t *data); +void ff_jpeg_fdct_islow_8(int16_t *data); +void ff_jpeg_fdct_islow_10(int16_t *data); +void ff_fdct248_islow_8(int16_t *data); +void ff_fdct248_islow_10(int16_t *data); + +void ff_j_rev_dct(int16_t *data); +void ff_j_rev_dct4(int16_t *data); +void ff_j_rev_dct2(int16_t *data); +void ff_j_rev_dct1(int16_t *data); + +void ff_fdct_mmx(int16_t *block); +void ff_fdct_mmxext(int16_t *block); +void ff_fdct_sse2(int16_t *block); + +#endif /* AVCODEC_DCT_H */ diff --git a/ffmpeg/libavcodec/dct32.c b/ffmpeg/libavcodec/dct32.c new file mode 100644 index 0000000..fb53d53 --- /dev/null +++ b/ffmpeg/libavcodec/dct32.c @@ -0,0 +1,276 @@ +/* + * Template for the Discrete Cosine Transform for 32 samples + * Copyright (c) 2001, 2002 Fabrice Bellard + * + * 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 "dct32.h" +#include "mathops.h" + +#if DCT32_FLOAT +# define dct32 ff_dct32_float +# define FIXHR(x) ((float)(x)) +# define MULH3(x, y, s) ((s)*(y)*(x)) +# define INTFLOAT float +#else +# define dct32 ff_dct32_fixed +# define FIXHR(a) ((int)((a) * (1LL<<32) + 0.5)) +# define MULH3(x, y, s) MULH((s)*(x), y) +# define INTFLOAT int +#endif + + +/* tab[i][j] = 1.0 / (2.0 * cos(pi*(2*k+1) / 2^(6 - j))) */ + +/* cos(i*pi/64) */ + +#define COS0_0 FIXHR(0.50060299823519630134/2) +#define COS0_1 FIXHR(0.50547095989754365998/2) +#define COS0_2 FIXHR(0.51544730992262454697/2) +#define COS0_3 FIXHR(0.53104259108978417447/2) +#define COS0_4 FIXHR(0.55310389603444452782/2) +#define COS0_5 FIXHR(0.58293496820613387367/2) +#define COS0_6 FIXHR(0.62250412303566481615/2) +#define COS0_7 FIXHR(0.67480834145500574602/2) +#define COS0_8 FIXHR(0.74453627100229844977/2) +#define COS0_9 FIXHR(0.83934964541552703873/2) +#define COS0_10 FIXHR(0.97256823786196069369/2) +#define COS0_11 FIXHR(1.16943993343288495515/4) +#define COS0_12 FIXHR(1.48416461631416627724/4) +#define COS0_13 FIXHR(2.05778100995341155085/8) +#define COS0_14 FIXHR(3.40760841846871878570/8) +#define COS0_15 FIXHR(10.19000812354805681150/32) + +#define COS1_0 FIXHR(0.50241928618815570551/2) +#define COS1_1 FIXHR(0.52249861493968888062/2) +#define COS1_2 FIXHR(0.56694403481635770368/2) +#define COS1_3 FIXHR(0.64682178335999012954/2) +#define COS1_4 FIXHR(0.78815462345125022473/2) +#define COS1_5 FIXHR(1.06067768599034747134/4) +#define COS1_6 FIXHR(1.72244709823833392782/4) +#define COS1_7 FIXHR(5.10114861868916385802/16) + +#define COS2_0 FIXHR(0.50979557910415916894/2) +#define COS2_1 FIXHR(0.60134488693504528054/2) +#define COS2_2 FIXHR(0.89997622313641570463/2) +#define COS2_3 FIXHR(2.56291544774150617881/8) + +#define COS3_0 FIXHR(0.54119610014619698439/2) +#define COS3_1 FIXHR(1.30656296487637652785/4) + +#define COS4_0 FIXHR(0.70710678118654752439/2) + +/* butterfly operator */ +#define BF(a, b, c, s)\ +{\ + tmp0 = val##a + val##b;\ + tmp1 = val##a - val##b;\ + val##a = tmp0;\ + val##b = MULH3(tmp1, c, 1<<(s));\ +} + +#define BF0(a, b, c, s)\ +{\ + tmp0 = tab[a] + tab[b];\ + tmp1 = tab[a] - tab[b];\ + val##a = tmp0;\ + val##b = MULH3(tmp1, c, 1<<(s));\ +} + +#define BF1(a, b, c, d)\ +{\ + BF(a, b, COS4_0, 1);\ + BF(c, d,-COS4_0, 1);\ + val##c += val##d;\ +} + +#define BF2(a, b, c, d)\ +{\ + BF(a, b, COS4_0, 1);\ + BF(c, d,-COS4_0, 1);\ + val##c += val##d;\ + val##a += val##c;\ + val##c += val##b;\ + val##b += val##d;\ +} + +#define ADD(a, b) val##a += val##b + +/* DCT32 without 1/sqrt(2) coef zero scaling. */ +void dct32(INTFLOAT *out, const INTFLOAT *tab) +{ + INTFLOAT tmp0, tmp1; + + INTFLOAT val0 , val1 , val2 , val3 , val4 , val5 , val6 , val7 , + val8 , val9 , val10, val11, val12, val13, val14, val15, + val16, val17, val18, val19, val20, val21, val22, val23, + val24, val25, val26, val27, val28, val29, val30, val31; + + /* pass 1 */ + BF0( 0, 31, COS0_0 , 1); + BF0(15, 16, COS0_15, 5); + /* pass 2 */ + BF( 0, 15, COS1_0 , 1); + BF(16, 31,-COS1_0 , 1); + /* pass 1 */ + BF0( 7, 24, COS0_7 , 1); + BF0( 8, 23, COS0_8 , 1); + /* pass 2 */ + BF( 7, 8, COS1_7 , 4); + BF(23, 24,-COS1_7 , 4); + /* pass 3 */ + BF( 0, 7, COS2_0 , 1); + BF( 8, 15,-COS2_0 , 1); + BF(16, 23, COS2_0 , 1); + BF(24, 31,-COS2_0 , 1); + /* pass 1 */ + BF0( 3, 28, COS0_3 , 1); + BF0(12, 19, COS0_12, 2); + /* pass 2 */ + BF( 3, 12, COS1_3 , 1); + BF(19, 28,-COS1_3 , 1); + /* pass 1 */ + BF0( 4, 27, COS0_4 , 1); + BF0(11, 20, COS0_11, 2); + /* pass 2 */ + BF( 4, 11, COS1_4 , 1); + BF(20, 27,-COS1_4 , 1); + /* pass 3 */ + BF( 3, 4, COS2_3 , 3); + BF(11, 12,-COS2_3 , 3); + BF(19, 20, COS2_3 , 3); + BF(27, 28,-COS2_3 , 3); + /* pass 4 */ + BF( 0, 3, COS3_0 , 1); + BF( 4, 7,-COS3_0 , 1); + BF( 8, 11, COS3_0 , 1); + BF(12, 15,-COS3_0 , 1); + BF(16, 19, COS3_0 , 1); + BF(20, 23,-COS3_0 , 1); + BF(24, 27, COS3_0 , 1); + BF(28, 31,-COS3_0 , 1); + + + + /* pass 1 */ + BF0( 1, 30, COS0_1 , 1); + BF0(14, 17, COS0_14, 3); + /* pass 2 */ + BF( 1, 14, COS1_1 , 1); + BF(17, 30,-COS1_1 , 1); + /* pass 1 */ + BF0( 6, 25, COS0_6 , 1); + BF0( 9, 22, COS0_9 , 1); + /* pass 2 */ + BF( 6, 9, COS1_6 , 2); + BF(22, 25,-COS1_6 , 2); + /* pass 3 */ + BF( 1, 6, COS2_1 , 1); + BF( 9, 14,-COS2_1 , 1); + BF(17, 22, COS2_1 , 1); + BF(25, 30,-COS2_1 , 1); + + /* pass 1 */ + BF0( 2, 29, COS0_2 , 1); + BF0(13, 18, COS0_13, 3); + /* pass 2 */ + BF( 2, 13, COS1_2 , 1); + BF(18, 29,-COS1_2 , 1); + /* pass 1 */ + BF0( 5, 26, COS0_5 , 1); + BF0(10, 21, COS0_10, 1); + /* pass 2 */ + BF( 5, 10, COS1_5 , 2); + BF(21, 26,-COS1_5 , 2); + /* pass 3 */ + BF( 2, 5, COS2_2 , 1); + BF(10, 13,-COS2_2 , 1); + BF(18, 21, COS2_2 , 1); + BF(26, 29,-COS2_2 , 1); + /* pass 4 */ + BF( 1, 2, COS3_1 , 2); + BF( 5, 6,-COS3_1 , 2); + BF( 9, 10, COS3_1 , 2); + BF(13, 14,-COS3_1 , 2); + BF(17, 18, COS3_1 , 2); + BF(21, 22,-COS3_1 , 2); + BF(25, 26, COS3_1 , 2); + BF(29, 30,-COS3_1 , 2); + + /* pass 5 */ + BF1( 0, 1, 2, 3); + BF2( 4, 5, 6, 7); + BF1( 8, 9, 10, 11); + BF2(12, 13, 14, 15); + BF1(16, 17, 18, 19); + BF2(20, 21, 22, 23); + BF1(24, 25, 26, 27); + BF2(28, 29, 30, 31); + + /* pass 6 */ + + ADD( 8, 12); + ADD(12, 10); + ADD(10, 14); + ADD(14, 9); + ADD( 9, 13); + ADD(13, 11); + ADD(11, 15); + + out[ 0] = val0; + out[16] = val1; + out[ 8] = val2; + out[24] = val3; + out[ 4] = val4; + out[20] = val5; + out[12] = val6; + out[28] = val7; + out[ 2] = val8; + out[18] = val9; + out[10] = val10; + out[26] = val11; + out[ 6] = val12; + out[22] = val13; + out[14] = val14; + out[30] = val15; + + ADD(24, 28); + ADD(28, 26); + ADD(26, 30); + ADD(30, 25); + ADD(25, 29); + ADD(29, 27); + ADD(27, 31); + + out[ 1] = val16 + val24; + out[17] = val17 + val25; + out[ 9] = val18 + val26; + out[25] = val19 + val27; + out[ 5] = val20 + val28; + out[21] = val21 + val29; + out[13] = val22 + val30; + out[29] = val23 + val31; + out[ 3] = val24 + val20; + out[19] = val25 + val21; + out[11] = val26 + val22; + out[27] = val27 + val23; + out[ 7] = val28 + val18; + out[23] = val29 + val19; + out[15] = val30 + val17; + out[31] = val31; +} diff --git a/ffmpeg/libavcodec/dct32.h b/ffmpeg/libavcodec/dct32.h new file mode 100644 index 0000000..110338d --- /dev/null +++ b/ffmpeg/libavcodec/dct32.h @@ -0,0 +1,25 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DCT32_H +#define AVCODEC_DCT32_H + +void ff_dct32_float(float *dst, const float *src); +void ff_dct32_fixed(int *dst, const int *src); + +#endif diff --git a/ffmpeg/libavcodec/dct32_fixed.c b/ffmpeg/libavcodec/dct32_fixed.c new file mode 100644 index 0000000..7eb9dc1 --- /dev/null +++ b/ffmpeg/libavcodec/dct32_fixed.c @@ -0,0 +1,20 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define DCT32_FLOAT 0 +#include "dct32.c" diff --git a/ffmpeg/libavcodec/dct32_float.c b/ffmpeg/libavcodec/dct32_float.c new file mode 100644 index 0000000..727ec3c --- /dev/null +++ b/ffmpeg/libavcodec/dct32_float.c @@ -0,0 +1,20 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define DCT32_FLOAT 1 +#include "dct32.c" diff --git a/ffmpeg/libavcodec/dctref.c b/ffmpeg/libavcodec/dctref.c new file mode 100644 index 0000000..851014b --- /dev/null +++ b/ffmpeg/libavcodec/dctref.c @@ -0,0 +1,123 @@ +/* + * reference discrete cosine transform (double precision) + * Copyright (C) 2009 Dylan Yudaken + * + * 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 + */ + +/** + * @file + * reference discrete cosine transform (double precision) + * + * @author Dylan Yudaken (dyudaken at gmail) + * + * @note This file could be optimized a lot, but is for + * reference and so readability is better. + */ + +#include "libavutil/mathematics.h" +#include "dctref.h" + +static double coefficients[8 * 8]; + +/** + * Initialize the double precision discrete cosine transform + * functions fdct & idct. + */ +av_cold void ff_ref_dct_init(void) +{ + unsigned int i, j; + + for (j = 0; j < 8; ++j) { + coefficients[j] = sqrt(0.125); + for (i = 8; i < 64; i += 8) { + coefficients[i + j] = 0.5 * cos(i * (j + 0.5) * M_PI / 64.0); + } + } +} + +/** + * Transform 8x8 block of data with a double precision forward DCT
+ * This is a reference implementation. + * + * @param block pointer to 8x8 block of data to transform + */ +void ff_ref_fdct(short *block) +{ + /* implement the equation: block = coefficients * block * coefficients' */ + + unsigned int i, j, k; + double out[8 * 8]; + + /* out = coefficients * block */ + for (i = 0; i < 64; i += 8) { + for (j = 0; j < 8; ++j) { + double tmp = 0; + for (k = 0; k < 8; ++k) { + tmp += coefficients[i + k] * block[k * 8 + j]; + } + out[i + j] = tmp * 8; + } + } + + /* block = out * (coefficients') */ + for (j = 0; j < 8; ++j) { + for (i = 0; i < 64; i += 8) { + double tmp = 0; + for (k = 0; k < 8; ++k) { + tmp += out[i + k] * coefficients[j * 8 + k]; + } + block[i + j] = floor(tmp + 0.499999999999); + } + } +} + +/** + * Transform 8x8 block of data with a double precision inverse DCT
+ * This is a reference implementation. + * + * @param block pointer to 8x8 block of data to transform + */ +void ff_ref_idct(short *block) +{ + /* implement the equation: block = (coefficients') * block * coefficients */ + + unsigned int i, j, k; + double out[8 * 8]; + + /* out = block * coefficients */ + for (i = 0; i < 64; i += 8) { + for (j = 0; j < 8; ++j) { + double tmp = 0; + for (k = 0; k < 8; ++k) { + tmp += block[i + k] * coefficients[k * 8 + j]; + } + out[i + j] = tmp; + } + } + + /* block = (coefficients') * out */ + for (i = 0; i < 8; ++i) { + for (j = 0; j < 8; ++j) { + double tmp = 0; + for (k = 0; k < 64; k += 8) { + tmp += coefficients[k + i] * out[k + j]; + } + block[i * 8 + j] = floor(tmp + 0.5); + } + } +} diff --git a/ffmpeg/libavcodec/dctref.h b/ffmpeg/libavcodec/dctref.h new file mode 100644 index 0000000..f6fde88 --- /dev/null +++ b/ffmpeg/libavcodec/dctref.h @@ -0,0 +1,29 @@ +/* + * reference discrete cosine transform (double precision) + * Copyright (C) 2009 Dylan Yudaken + * + * 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 + */ + +#ifndef AVCODEC_DCTREF_H +#define AVCODEC_DCTREF_H + +void ff_ref_fdct(short *block); +void ff_ref_idct(short *block); +void ff_ref_dct_init(void); + +#endif /* AVCODEC_DCTREF_H */ diff --git a/ffmpeg/libavcodec/dfa.c b/ffmpeg/libavcodec/dfa.c new file mode 100644 index 0000000..b20cd0e --- /dev/null +++ b/ffmpeg/libavcodec/dfa.c @@ -0,0 +1,390 @@ +/* + * Chronomaster DFA Video Decoder + * Copyright (c) 2011 Konstantin Shishkov + * based on work by Vladimir "VAG" Gneushev + * + * 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 "libavutil/avassert.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" + +typedef struct DfaContext { + uint32_t pal[256]; + uint8_t *frame_buf; +} DfaContext; + +static av_cold int dfa_decode_init(AVCodecContext *avctx) +{ + DfaContext *s = avctx->priv_data; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + if (!avctx->width || !avctx->height) + return AVERROR_INVALIDDATA; + + av_assert0(av_image_check_size(avctx->width, avctx->height, 0, avctx) >= 0); + + s->frame_buf = av_mallocz(avctx->width * avctx->height); + if (!s->frame_buf) + return AVERROR(ENOMEM); + + return 0; +} + +static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + const int size = width * height; + + if (bytestream2_get_buffer(gb, frame, size) != size) + return AVERROR_INVALIDDATA; + return 0; +} + +static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + const uint8_t *frame_start = frame; + const uint8_t *frame_end = frame + width * height; + int mask = 0x10000, bitbuf = 0; + int v, count, segments; + unsigned offset; + + segments = bytestream2_get_le32(gb); + offset = bytestream2_get_le32(gb); + if (segments == 0 && offset == frame_end - frame) + return 0; // skip frame + if (frame_end - frame <= offset) + return AVERROR_INVALIDDATA; + frame += offset; + while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + if (mask == 0x10000) { + bitbuf = bytestream2_get_le16u(gb); + mask = 1; + } + if (frame_end - frame < 2) + return AVERROR_INVALIDDATA; + if (bitbuf & mask) { + v = bytestream2_get_le16(gb); + offset = (v & 0x1FFF) << 1; + count = ((v >> 13) + 2) << 1; + if (frame - frame_start < offset || frame_end - frame < count) + return AVERROR_INVALIDDATA; + av_memcpy_backptr(frame, offset, count); + frame += count; + } else { + *frame++ = bytestream2_get_byte(gb); + *frame++ = bytestream2_get_byte(gb); + } + mask <<= 1; + } + + return 0; +} + +static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + const uint8_t *frame_start = frame; + const uint8_t *frame_end = frame + width * height; + int mask = 0x10000, bitbuf = 0; + int v, offset, count, segments; + + segments = bytestream2_get_le16(gb); + while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + if (mask == 0x10000) { + bitbuf = bytestream2_get_le16u(gb); + mask = 1; + } + if (frame_end - frame < 2) + return AVERROR_INVALIDDATA; + if (bitbuf & mask) { + v = bytestream2_get_le16(gb); + offset = (v & 0x1FFF) << 1; + count = ((v >> 13) + 2) << 1; + if (frame - frame_start < offset || frame_end - frame < count) + return AVERROR_INVALIDDATA; + av_memcpy_backptr(frame, offset, count); + frame += count; + } else if (bitbuf & (mask << 1)) { + frame += bytestream2_get_le16(gb); + } else { + *frame++ = bytestream2_get_byte(gb); + *frame++ = bytestream2_get_byte(gb); + } + mask <<= 2; + } + + return 0; +} + +static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + const uint8_t *frame_start = frame; + const uint8_t *frame_end = frame + width * height; + int mask = 0x10000, bitbuf = 0; + int i, v, offset, count, segments; + + segments = bytestream2_get_le16(gb); + while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + if (mask == 0x10000) { + bitbuf = bytestream2_get_le16u(gb); + mask = 1; + } + + if (bitbuf & mask) { + v = bytestream2_get_le16(gb); + offset = (v & 0x1FFF) << 2; + count = ((v >> 13) + 2) << 1; + if (frame - frame_start < offset || frame_end - frame < count*2 + width) + return AVERROR_INVALIDDATA; + for (i = 0; i < count; i++) { + frame[0] = frame[1] = + frame[width] = frame[width + 1] = frame[-offset]; + + frame += 2; + } + } else if (bitbuf & (mask << 1)) { + v = bytestream2_get_le16(gb)*2; + if (frame - frame_end < v) + return AVERROR_INVALIDDATA; + frame += v; + } else { + if (frame_end - frame < width + 3) + return AVERROR_INVALIDDATA; + frame[0] = frame[1] = + frame[width] = frame[width + 1] = bytestream2_get_byte(gb); + frame += 2; + frame[0] = frame[1] = + frame[width] = frame[width + 1] = bytestream2_get_byte(gb); + frame += 2; + } + mask <<= 2; + } + + return 0; +} + +static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + uint8_t *line_ptr; + int count, lines, segments; + + count = bytestream2_get_le16(gb); + if (count >= height) + return AVERROR_INVALIDDATA; + frame += width * count; + lines = bytestream2_get_le16(gb); + if (count + lines > height) + return AVERROR_INVALIDDATA; + + while (lines--) { + if (bytestream2_get_bytes_left(gb) < 1) + return AVERROR_INVALIDDATA; + line_ptr = frame; + frame += width; + segments = bytestream2_get_byteu(gb); + while (segments--) { + if (frame - line_ptr <= bytestream2_peek_byte(gb)) + return AVERROR_INVALIDDATA; + line_ptr += bytestream2_get_byte(gb); + count = (int8_t)bytestream2_get_byte(gb); + if (count >= 0) { + if (frame - line_ptr < count) + return AVERROR_INVALIDDATA; + if (bytestream2_get_buffer(gb, line_ptr, count) != count) + return AVERROR_INVALIDDATA; + } else { + count = -count; + if (frame - line_ptr < count) + return AVERROR_INVALIDDATA; + memset(line_ptr, bytestream2_get_byte(gb), count); + } + line_ptr += count; + } + } + + return 0; +} + +static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + const uint8_t *frame_end = frame + width * height; + uint8_t *line_ptr; + int count, i, v, lines, segments; + int y = 0; + + lines = bytestream2_get_le16(gb); + if (lines > height) + return AVERROR_INVALIDDATA; + + while (lines--) { + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + segments = bytestream2_get_le16u(gb); + while ((segments & 0xC000) == 0xC000) { + unsigned skip_lines = -(int16_t)segments; + unsigned delta = -((int16_t)segments * width); + if (frame_end - frame <= delta || y + lines + skip_lines > height) + return AVERROR_INVALIDDATA; + frame += delta; + y += skip_lines; + segments = bytestream2_get_le16(gb); + } + if (frame_end <= frame) + return -1; + if (segments & 0x8000) { + frame[width - 1] = segments & 0xFF; + segments = bytestream2_get_le16(gb); + } + line_ptr = frame; + frame += width; + y++; + while (segments--) { + if (frame - line_ptr <= bytestream2_peek_byte(gb)) + return AVERROR_INVALIDDATA; + line_ptr += bytestream2_get_byte(gb); + count = (int8_t)bytestream2_get_byte(gb); + if (count >= 0) { + if (frame - line_ptr < count * 2) + return AVERROR_INVALIDDATA; + if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2) + return AVERROR_INVALIDDATA; + line_ptr += count * 2; + } else { + count = -count; + if (frame - line_ptr < count * 2) + return AVERROR_INVALIDDATA; + v = bytestream2_get_le16(gb); + for (i = 0; i < count; i++) + bytestream_put_le16(&line_ptr, v); + } + } + } + + return 0; +} + +static int decode_unk6(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + return AVERROR_PATCHWELCOME; +} + +static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height) +{ + memset(frame, 0, width * height); + return 0; +} + + +typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height); + +static const chunk_decoder decoder[8] = { + decode_copy, decode_tsw1, decode_bdlt, decode_wdlt, + decode_unk6, decode_dsw1, decode_blck, decode_dds1, +}; + +static const char* chunk_name[8] = { + "COPY", "TSW1", "BDLT", "WDLT", "????", "DSW1", "BLCK", "DDS1" +}; + +static int dfa_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *frame = data; + DfaContext *s = avctx->priv_data; + GetByteContext gb; + const uint8_t *buf = avpkt->data; + uint32_t chunk_type, chunk_size; + uint8_t *dst; + int ret; + int i, pal_elems; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + while (bytestream2_get_bytes_left(&gb) > 0) { + bytestream2_skip(&gb, 4); + chunk_size = bytestream2_get_le32(&gb); + chunk_type = bytestream2_get_le32(&gb); + if (!chunk_type) + break; + if (chunk_type == 1) { + pal_elems = FFMIN(chunk_size / 3, 256); + for (i = 0; i < pal_elems; i++) { + s->pal[i] = bytestream2_get_be24(&gb) << 2; + s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303; + } + frame->palette_has_changed = 1; + } else if (chunk_type <= 9) { + if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) { + av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n", + chunk_name[chunk_type - 2]); + return AVERROR_INVALIDDATA; + } + } else { + av_log(avctx, AV_LOG_WARNING, "Ignoring unknown chunk type %d\n", + chunk_type); + } + buf += chunk_size; + } + + buf = s->frame_buf; + dst = frame->data[0]; + for (i = 0; i < avctx->height; i++) { + memcpy(dst, buf, avctx->width); + dst += frame->linesize[0]; + buf += avctx->width; + } + memcpy(frame->data[1], s->pal, sizeof(s->pal)); + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int dfa_decode_end(AVCodecContext *avctx) +{ + DfaContext *s = avctx->priv_data; + + av_freep(&s->frame_buf); + + return 0; +} + +AVCodec ff_dfa_decoder = { + .name = "dfa", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DFA, + .priv_data_size = sizeof(DfaContext), + .init = dfa_decode_init, + .close = dfa_decode_end, + .decode = dfa_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), +}; diff --git a/ffmpeg/libavcodec/dirac.c b/ffmpeg/libavcodec/dirac.c new file mode 100644 index 0000000..e132acc --- /dev/null +++ b/ffmpeg/libavcodec/dirac.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2007 Marco Gerards + * Copyright (C) 2009 David Conrad + * Copyright (C) 2011 Jordi Ortiz + * + * 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 + */ + +/** + * @file + * Dirac Decoder + * @author Marco Gerards , David Conrad, Jordi Ortiz + */ + +#include "libavutil/imgutils.h" +#include "dirac.h" +#include "avcodec.h" +#include "golomb.h" +#include "mpeg12data.h" + +/* defaults for source parameters */ +static const dirac_source_params dirac_source_parameters_defaults[] = { + { 640, 480, 2, 0, 0, 1, 1, 640, 480, 0, 0, 1, 0 }, + { 176, 120, 2, 0, 0, 9, 2, 176, 120, 0, 0, 1, 1 }, + { 176, 144, 2, 0, 1, 10, 3, 176, 144, 0, 0, 1, 2 }, + { 352, 240, 2, 0, 0, 9, 2, 352, 240, 0, 0, 1, 1 }, + { 352, 288, 2, 0, 1, 10, 3, 352, 288, 0, 0, 1, 2 }, + { 704, 480, 2, 0, 0, 9, 2, 704, 480, 0, 0, 1, 1 }, + { 704, 576, 2, 0, 1, 10, 3, 704, 576, 0, 0, 1, 2 }, + { 720, 480, 1, 1, 0, 4, 2, 704, 480, 8, 0, 3, 1 }, + { 720, 576, 1, 1, 1, 3, 3, 704, 576, 8, 0, 3, 2 }, + { 1280, 720, 1, 0, 1, 7, 1, 1280, 720, 0, 0, 3, 3 }, + { 1280, 720, 1, 0, 1, 6, 1, 1280, 720, 0, 0, 3, 3 }, + { 1920, 1080, 1, 1, 1, 4, 1, 1920, 1080, 0, 0, 3, 3 }, + { 1920, 1080, 1, 1, 1, 3, 1, 1920, 1080, 0, 0, 3, 3 }, + { 1920, 1080, 1, 0, 1, 7, 1, 1920, 1080, 0, 0, 3, 3 }, + { 1920, 1080, 1, 0, 1, 6, 1, 1920, 1080, 0, 0, 3, 3 }, + { 2048, 1080, 0, 0, 1, 2, 1, 2048, 1080, 0, 0, 4, 4 }, + { 4096, 2160, 0, 0, 1, 2, 1, 4096, 2160, 0, 0, 4, 4 }, + { 3840, 2160, 1, 0, 1, 7, 1, 3840, 2160, 0, 0, 3, 3 }, + { 3840, 2160, 1, 0, 1, 6, 1, 3840, 2160, 0, 0, 3, 3 }, + { 7680, 4320, 1, 0, 1, 7, 1, 3840, 2160, 0, 0, 3, 3 }, + { 7680, 4320, 1, 0, 1, 6, 1, 3840, 2160, 0, 0, 3, 3 }, +}; + +/* [DIRAC_STD] Table 10.4 - Available preset pixel aspect ratio values */ +static const AVRational dirac_preset_aspect_ratios[] = { + {1, 1}, + {10, 11}, + {12, 11}, + {40, 33}, + {16, 11}, + {4, 3}, +}; + +/* [DIRAC_STD] Values 9,10 of 10.3.5 Frame Rate. + * Table 10.3 Available preset frame rate values + */ +static const AVRational dirac_frame_rate[] = { + {15000, 1001}, + {25, 2}, +}; + +/* [DIRAC_STD] This should be equivalent to Table 10.5 Available signal + * range presets */ +static const struct { + uint8_t bitdepth; + enum AVColorRange color_range; +} pixel_range_presets[] = { + {8, AVCOL_RANGE_JPEG}, + {8, AVCOL_RANGE_MPEG}, + {10, AVCOL_RANGE_MPEG}, + {12, AVCOL_RANGE_MPEG}, +}; + +static const enum AVColorPrimaries dirac_primaries[] = { + AVCOL_PRI_BT709, + AVCOL_PRI_SMPTE170M, + AVCOL_PRI_BT470BG, +}; + +static const struct { + enum AVColorPrimaries color_primaries; + enum AVColorSpace colorspace; + enum AVColorTransferCharacteristic color_trc; +} dirac_color_presets[] = { + { AVCOL_PRI_BT709, AVCOL_SPC_BT709, AVCOL_TRC_BT709 }, + { AVCOL_PRI_SMPTE170M, AVCOL_SPC_BT470BG, AVCOL_TRC_BT709 }, + { AVCOL_PRI_BT470BG, AVCOL_SPC_BT470BG, AVCOL_TRC_BT709 }, + { AVCOL_PRI_BT709, AVCOL_SPC_BT709, AVCOL_TRC_BT709 }, + { AVCOL_PRI_BT709, AVCOL_SPC_BT709, AVCOL_TRC_UNSPECIFIED /* DCinema */ }, +}; + +/* [DIRAC_STD] Table 10.2 Supported chroma sampling formats + luma Offset */ +static const enum AVPixelFormat dirac_pix_fmt[2][3] = { + { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P }, + { AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P }, +}; + +/* [DIRAC_STD] 10.3 Parse Source Parameters. + * source_parameters(base_video_format) */ +static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, + dirac_source_params *source) +{ + AVRational frame_rate = {0,0}; + unsigned luma_depth = 8, luma_offset = 16; + int idx; + int chroma_x_shift, chroma_y_shift; + + /* [DIRAC_STD] 10.3.2 Frame size. frame_size(video_params) */ + /* [DIRAC_STD] custom_dimensions_flag */ + if (get_bits1(gb)) { + source->width = svq3_get_ue_golomb(gb); /* [DIRAC_STD] FRAME_WIDTH */ + source->height = svq3_get_ue_golomb(gb); /* [DIRAC_STD] FRAME_HEIGHT */ + } + + /* [DIRAC_STD] 10.3.3 Chroma Sampling Format. + * chroma_sampling_format(video_params) */ + /* [DIRAC_STD] custom_chroma_format_flag */ + if (get_bits1(gb)) + /* [DIRAC_STD] CHROMA_FORMAT_INDEX */ + source->chroma_format = svq3_get_ue_golomb(gb); + if (source->chroma_format > 2U) { + av_log(avctx, AV_LOG_ERROR, "Unknown chroma format %d\n", + source->chroma_format); + return AVERROR_INVALIDDATA; + } + + /* [DIRAC_STD] 10.3.4 Scan Format. scan_format(video_params) */ + /* [DIRAC_STD] custom_scan_format_flag */ + if (get_bits1(gb)) + /* [DIRAC_STD] SOURCE_SAMPLING */ + source->interlaced = svq3_get_ue_golomb(gb); + if (source->interlaced > 1U) + return AVERROR_INVALIDDATA; + + /* [DIRAC_STD] 10.3.5 Frame Rate. frame_rate(video_params) */ + if (get_bits1(gb)) { /* [DIRAC_STD] custom_frame_rate_flag */ + source->frame_rate_index = svq3_get_ue_golomb(gb); + + if (source->frame_rate_index > 10U) + return AVERROR_INVALIDDATA; + + if (!source->frame_rate_index) { + /* [DIRAC_STD] FRAME_RATE_NUMER */ + frame_rate.num = svq3_get_ue_golomb(gb); + /* [DIRAC_STD] FRAME_RATE_DENOM */ + frame_rate.den = svq3_get_ue_golomb(gb); + } + } + /* [DIRAC_STD] preset_frame_rate(video_params, index) */ + if (source->frame_rate_index > 0) { + if (source->frame_rate_index <= 8) + frame_rate = ff_mpeg12_frame_rate_tab[source->frame_rate_index]; + else + /* [DIRAC_STD] Table 10.3 values 9-10 */ + frame_rate = dirac_frame_rate[source->frame_rate_index-9]; + } + av_reduce(&avctx->time_base.num, &avctx->time_base.den, + frame_rate.den, frame_rate.num, 1<<30); + + /* [DIRAC_STD] 10.3.6 Pixel Aspect Ratio. + * pixel_aspect_ratio(video_params) */ + if (get_bits1(gb)) { /* [DIRAC_STD] custom_pixel_aspect_ratio_flag */ + /* [DIRAC_STD] index */ + source->aspect_ratio_index = svq3_get_ue_golomb(gb); + + if (source->aspect_ratio_index > 6U) + return AVERROR_INVALIDDATA; + + if (!source->aspect_ratio_index) { + avctx->sample_aspect_ratio.num = svq3_get_ue_golomb(gb); + avctx->sample_aspect_ratio.den = svq3_get_ue_golomb(gb); + } + } + /* [DIRAC_STD] Take value from Table 10.4 Available preset pixel + * aspect ratio values */ + if (source->aspect_ratio_index > 0) + avctx->sample_aspect_ratio = + dirac_preset_aspect_ratios[source->aspect_ratio_index-1]; + + /* [DIRAC_STD] 10.3.7 Clean area. clean_area(video_params) */ + if (get_bits1(gb)) { /* [DIRAC_STD] custom_clean_area_flag */ + /* [DIRAC_STD] CLEAN_WIDTH */ + source->clean_width = svq3_get_ue_golomb(gb); + /* [DIRAC_STD] CLEAN_HEIGHT */ + source->clean_height = svq3_get_ue_golomb(gb); + /* [DIRAC_STD] CLEAN_LEFT_OFFSET */ + source->clean_left_offset = svq3_get_ue_golomb(gb); + /* [DIRAC_STD] CLEAN_RIGHT_OFFSET */ + source->clean_right_offset = svq3_get_ue_golomb(gb); + } + + /* [DIRAC_STD] 10.3.8 Signal range. signal_range(video_params) + * WARNING: Some adaptation seems to be done using the + * AVCOL_RANGE_MPEG/JPEG values */ + if (get_bits1(gb)) { /* [DIRAC_STD] custom_signal_range_flag */ + /* [DIRAC_STD] index */ + source->pixel_range_index = svq3_get_ue_golomb(gb); + + if (source->pixel_range_index > 4U) + return AVERROR_INVALIDDATA; + + /* This assumes either fullrange or MPEG levels only */ + if (!source->pixel_range_index) { + luma_offset = svq3_get_ue_golomb(gb); + luma_depth = av_log2(svq3_get_ue_golomb(gb))+1; + svq3_get_ue_golomb(gb); /* chroma offset */ + svq3_get_ue_golomb(gb); /* chroma excursion */ + avctx->color_range = luma_offset ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + } + } + /* [DIRAC_STD] Table 10.5 + * Available signal range presets <--> pixel_range_presets */ + if (source->pixel_range_index > 0) { + idx = source->pixel_range_index-1; + luma_depth = pixel_range_presets[idx].bitdepth; + avctx->color_range = pixel_range_presets[idx].color_range; + } + + if (luma_depth > 8) + av_log(avctx, AV_LOG_WARNING, "Bitdepth greater than 8\n"); + + avctx->pix_fmt = dirac_pix_fmt[!luma_offset][source->chroma_format]; + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_x_shift, &chroma_y_shift); + if ((source->width % (1<height % (1<color_spec_index = svq3_get_ue_golomb(gb); + + if (source->color_spec_index > 4U) + return AVERROR_INVALIDDATA; + + avctx->color_primaries = dirac_color_presets[idx].color_primaries; + avctx->colorspace = dirac_color_presets[idx].colorspace; + avctx->color_trc = dirac_color_presets[idx].color_trc; + + if (!source->color_spec_index) { + /* [DIRAC_STD] 10.3.9.1 Colour primaries */ + if (get_bits1(gb)) { + idx = svq3_get_ue_golomb(gb); + if (idx < 3U) + avctx->color_primaries = dirac_primaries[idx]; + } + /* [DIRAC_STD] 10.3.9.2 Colour matrix */ + if (get_bits1(gb)) { + idx = svq3_get_ue_golomb(gb); + if (!idx) + avctx->colorspace = AVCOL_SPC_BT709; + else if (idx == 1) + avctx->colorspace = AVCOL_SPC_BT470BG; + } + /* [DIRAC_STD] 10.3.9.3 Transfer function */ + if (get_bits1(gb) && !svq3_get_ue_golomb(gb)) + avctx->color_trc = AVCOL_TRC_BT709; + } + } else { + idx = source->color_spec_index; + avctx->color_primaries = dirac_color_presets[idx].color_primaries; + avctx->colorspace = dirac_color_presets[idx].colorspace; + avctx->color_trc = dirac_color_presets[idx].color_trc; + } + + return 0; +} + +/* [DIRAC_STD] 10. Sequence Header. sequence_header() */ +int avpriv_dirac_parse_sequence_header(AVCodecContext *avctx, GetBitContext *gb, + dirac_source_params *source) +{ + unsigned version_major; + unsigned video_format, picture_coding_mode; + int ret; + + /* [DIRAC_SPEC] 10.1 Parse Parameters. parse_parameters() */ + version_major = svq3_get_ue_golomb(gb); + svq3_get_ue_golomb(gb); /* version_minor */ + avctx->profile = svq3_get_ue_golomb(gb); + avctx->level = svq3_get_ue_golomb(gb); + /* [DIRAC_SPEC] sequence_header() -> base_video_format as defined in + * 10.2 Base Video Format, table 10.1 Dirac predefined video formats */ + video_format = svq3_get_ue_golomb(gb); + + if (version_major < 2) + av_log(avctx, AV_LOG_WARNING, "Stream is old and may not work\n"); + else if (version_major > 2) + av_log(avctx, AV_LOG_WARNING, "Stream may have unhandled features\n"); + + if (video_format > 20U) + return AVERROR_INVALIDDATA; + + /* Fill in defaults for the source parameters. */ + *source = dirac_source_parameters_defaults[video_format]; + + /* [DIRAC_STD] 10.3 Source Parameters + * Override the defaults. */ + if (ret = parse_source_parameters(avctx, gb, source)) + return ret; + + if (ret = av_image_check_size(source->width, source->height, 0, avctx)) + return ret; + + avcodec_set_dimensions(avctx, source->width, source->height); + + /* [DIRAC_STD] picture_coding_mode shall be 0 for fields and 1 for frames + * currently only used to signal field coding */ + picture_coding_mode = svq3_get_ue_golomb(gb); + if (picture_coding_mode != 0) { + av_log(avctx, AV_LOG_ERROR, "Unsupported picture coding mode %d\n", + picture_coding_mode); + return AVERROR_INVALIDDATA; + } + return 0; +} diff --git a/ffmpeg/libavcodec/dirac.h b/ffmpeg/libavcodec/dirac.h new file mode 100644 index 0000000..b0f955b --- /dev/null +++ b/ffmpeg/libavcodec/dirac.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007 Marco Gerards + * Copyright (C) 2009 David Conrad + * Copyright (C) 2011 Jordi Ortiz + * + * 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 + */ + +#ifndef AVCODEC_DIRAC_H +#define AVCODEC_DIRAC_H + +/** + * @file + * Interface to Dirac Decoder/Encoder + * @author Marco Gerards + * @author David Conrad + * @author Jordi Ortiz + */ + +#include "avcodec.h" +#include "get_bits.h" + +typedef struct dirac_source_params { + unsigned width; + unsigned height; + uint8_t chroma_format; ///< 0: 444 1: 422 2: 420 + + uint8_t interlaced; + uint8_t top_field_first; + + uint8_t frame_rate_index; ///< index into dirac_frame_rate[] + uint8_t aspect_ratio_index; ///< index into dirac_aspect_ratio[] + + uint16_t clean_width; + uint16_t clean_height; + uint16_t clean_left_offset; + uint16_t clean_right_offset; + + uint8_t pixel_range_index; ///< index into dirac_pixel_range_presets[] + uint8_t color_spec_index; ///< index into dirac_color_spec_presets[] +} dirac_source_params; + +int avpriv_dirac_parse_sequence_header(AVCodecContext *avctx, GetBitContext *gb, + dirac_source_params *source); + +#endif /* AVCODEC_DIRAC_H */ diff --git a/ffmpeg/libavcodec/dirac_arith.c b/ffmpeg/libavcodec/dirac_arith.c new file mode 100644 index 0000000..bf91392 --- /dev/null +++ b/ffmpeg/libavcodec/dirac_arith.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2007 Marco Gerards + * Copyright (C) 2009 David Conrad + * + * 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 + */ + +/** + * @file + * Arithmetic decoder for Dirac + * @author Marco Gerards + */ + +#include "dirac_arith.h" + + +const uint16_t ff_dirac_prob[256] = { + 0, 2, 5, 8, 11, 15, 20, 24, + 29, 35, 41, 47, 53, 60, 67, 74, + 82, 89, 97, 106, 114, 123, 132, 141, + 150, 160, 170, 180, 190, 201, 211, 222, + 233, 244, 256, 267, 279, 291, 303, 315, + 327, 340, 353, 366, 379, 392, 405, 419, + 433, 447, 461, 475, 489, 504, 518, 533, + 548, 563, 578, 593, 609, 624, 640, 656, + 672, 688, 705, 721, 738, 754, 771, 788, + 805, 822, 840, 857, 875, 892, 910, 928, + 946, 964, 983, 1001, 1020, 1038, 1057, 1076, + 1095, 1114, 1133, 1153, 1172, 1192, 1211, 1231, + 1251, 1271, 1291, 1311, 1332, 1352, 1373, 1393, + 1414, 1435, 1456, 1477, 1498, 1520, 1541, 1562, + 1584, 1606, 1628, 1649, 1671, 1694, 1716, 1738, + 1760, 1783, 1806, 1828, 1851, 1874, 1897, 1920, + 1935, 1942, 1949, 1955, 1961, 1968, 1974, 1980, + 1985, 1991, 1996, 2001, 2006, 2011, 2016, 2021, + 2025, 2029, 2033, 2037, 2040, 2044, 2047, 2050, + 2053, 2056, 2058, 2061, 2063, 2065, 2066, 2068, + 2069, 2070, 2071, 2072, 2072, 2072, 2072, 2072, + 2072, 2071, 2070, 2069, 2068, 2066, 2065, 2063, + 2060, 2058, 2055, 2052, 2049, 2045, 2042, 2038, + 2033, 2029, 2024, 2019, 2013, 2008, 2002, 1996, + 1989, 1982, 1975, 1968, 1960, 1952, 1943, 1934, + 1925, 1916, 1906, 1896, 1885, 1874, 1863, 1851, + 1839, 1827, 1814, 1800, 1786, 1772, 1757, 1742, + 1727, 1710, 1694, 1676, 1659, 1640, 1622, 1602, + 1582, 1561, 1540, 1518, 1495, 1471, 1447, 1422, + 1396, 1369, 1341, 1312, 1282, 1251, 1219, 1186, + 1151, 1114, 1077, 1037, 995, 952, 906, 857, + 805, 750, 690, 625, 553, 471, 376, 255 +}; + +const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT] = { + [CTX_ZPZN_F1] = CTX_ZP_F2, + [CTX_ZPNN_F1] = CTX_ZP_F2, + [CTX_ZP_F2] = CTX_ZP_F3, + [CTX_ZP_F3] = CTX_ZP_F4, + [CTX_ZP_F4] = CTX_ZP_F5, + [CTX_ZP_F5] = CTX_ZP_F6, + [CTX_ZP_F6] = CTX_ZP_F6, + [CTX_NPZN_F1] = CTX_NP_F2, + [CTX_NPNN_F1] = CTX_NP_F2, + [CTX_NP_F2] = CTX_NP_F3, + [CTX_NP_F3] = CTX_NP_F4, + [CTX_NP_F4] = CTX_NP_F5, + [CTX_NP_F5] = CTX_NP_F6, + [CTX_NP_F6] = CTX_NP_F6, + [CTX_DELTA_Q_F] = CTX_DELTA_Q_F, +}; + +int16_t ff_dirac_prob_branchless[256][2]; + +void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length) +{ + int i; + align_get_bits(gb); + + length = FFMIN(length, get_bits_left(gb)/8); + + c->bytestream = gb->buffer + get_bits_count(gb)/8; + c->bytestream_end = c->bytestream + length; + skip_bits_long(gb, length*8); + + c->low = 0; + for (i = 0; i < 4; i++) { + c->low <<= 8; + if (c->bytestream < c->bytestream_end) + c->low |= *c->bytestream++; + else + c->low |= 0xff; + } + + c->counter = -16; + c->range = 0xffff; + + for (i = 0; i < 256; i++) { + ff_dirac_prob_branchless[i][0] = ff_dirac_prob[255-i]; + ff_dirac_prob_branchless[i][1] = -ff_dirac_prob[i]; + } + + for (i = 0; i < DIRAC_CTX_COUNT; i++) + c->contexts[i] = 0x8000; +} diff --git a/ffmpeg/libavcodec/dirac_arith.h b/ffmpeg/libavcodec/dirac_arith.h new file mode 100644 index 0000000..f9a8bba --- /dev/null +++ b/ffmpeg/libavcodec/dirac_arith.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2007 Marco Gerards + * Copyright (C) 2009 David Conrad + * + * 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 + */ + +/** + * @file + * Arithmetic decoder for Dirac + * @author Marco Gerards + */ + +#ifndef AVCODEC_DIRAC_ARITH_H +#define AVCODEC_DIRAC_ARITH_H + +#include "bytestream.h" +#include "get_bits.h" + +enum dirac_arith_contexts { + CTX_ZPZN_F1, + CTX_ZPNN_F1, + CTX_NPZN_F1, + CTX_NPNN_F1, + CTX_ZP_F2, + CTX_ZP_F3, + CTX_ZP_F4, + CTX_ZP_F5, + CTX_ZP_F6, + CTX_NP_F2, + CTX_NP_F3, + CTX_NP_F4, + CTX_NP_F5, + CTX_NP_F6, + CTX_COEFF_DATA, + CTX_SIGN_NEG, + CTX_SIGN_ZERO, + CTX_SIGN_POS, + CTX_ZERO_BLOCK, + CTX_DELTA_Q_F, + CTX_DELTA_Q_DATA, + CTX_DELTA_Q_SIGN, + + DIRAC_CTX_COUNT +}; + +// Dirac resets the arith decoder between decoding various types of data, +// so many contexts are never used simultaneously. Thus, we can reduce +// the number of contexts needed by reusing them. +#define CTX_SB_F1 CTX_ZP_F5 +#define CTX_SB_DATA 0 +#define CTX_PMODE_REF1 0 +#define CTX_PMODE_REF2 1 +#define CTX_GLOBAL_BLOCK 2 +#define CTX_MV_F1 CTX_ZP_F2 +#define CTX_MV_DATA 0 +#define CTX_DC_F1 CTX_ZP_F5 +#define CTX_DC_DATA 0 + +typedef struct { + unsigned low; + uint16_t range; + int16_t counter; + + const uint8_t *bytestream; + const uint8_t *bytestream_end; + + uint16_t contexts[DIRAC_CTX_COUNT]; +} DiracArith; + +extern const uint8_t ff_dirac_next_ctx[DIRAC_CTX_COUNT]; +extern const uint16_t ff_dirac_prob[256]; +extern int16_t ff_dirac_prob_branchless[256][2]; + +static inline void renorm(DiracArith *c) +{ +#if HAVE_FAST_CLZ + int shift = 14 - av_log2_16bit(c->range-1) + ((c->range-1)>>15); + + c->low <<= shift; + c->range <<= shift; + c->counter += shift; +#else + while (c->range <= 0x4000) { + c->low <<= 1; + c->range <<= 1; + c->counter++; + } +#endif +} + +static inline void refill(DiracArith *c) +{ + int counter = c->counter; + + if (counter >= 0) { + int new = bytestream_get_be16(&c->bytestream); + + // the spec defines overread bits to be 1, and streams rely on this + if (c->bytestream > c->bytestream_end) { + new |= 0xff; + if (c->bytestream > c->bytestream_end+1) + new |= 0xff00; + + c->bytestream = c->bytestream_end; + } + + c->low += new << counter; + counter -= 16; + } + c->counter = counter; +} + +static inline int dirac_get_arith_bit(DiracArith *c, int ctx) +{ + int prob_zero = c->contexts[ctx]; + int range_times_prob, bit; + unsigned low = c->low; + int range = c->range; + + range_times_prob = (c->range * prob_zero) >> 16; + +#if HAVE_FAST_CMOV && HAVE_INLINE_ASM + low -= range_times_prob << 16; + range -= range_times_prob; + bit = 0; + __asm__( + "cmpl %5, %4 \n\t" + "setae %b0 \n\t" + "cmovb %3, %2 \n\t" + "cmovb %5, %1 \n\t" + : "+q"(bit), "+r"(range), "+r"(low) + : "r"(c->low), "r"(c->low>>16), + "r"(range_times_prob) + ); +#else + bit = (low >> 16) >= range_times_prob; + if (bit) { + low -= range_times_prob << 16; + range -= range_times_prob; + } else { + range = range_times_prob; + } +#endif + + c->contexts[ctx] += ff_dirac_prob_branchless[prob_zero>>8][bit]; + c->low = low; + c->range = range; + + renorm(c); + refill(c); + return bit; +} + +static inline int dirac_get_arith_uint(DiracArith *c, int follow_ctx, int data_ctx) +{ + int ret = 1; + while (!dirac_get_arith_bit(c, follow_ctx)) { + ret <<= 1; + ret += dirac_get_arith_bit(c, data_ctx); + follow_ctx = ff_dirac_next_ctx[follow_ctx]; + } + return ret-1; +} + +static inline int dirac_get_arith_int(DiracArith *c, int follow_ctx, int data_ctx) +{ + int ret = dirac_get_arith_uint(c, follow_ctx, data_ctx); + if (ret && dirac_get_arith_bit(c, data_ctx+1)) + ret = -ret; + return ret; +} + +void ff_dirac_init_arith_decoder(DiracArith *c, GetBitContext *gb, int length); + +#endif /* AVCODEC_DIRAC_ARITH_H */ diff --git a/ffmpeg/libavcodec/dirac_dwt.c b/ffmpeg/libavcodec/dirac_dwt.c new file mode 100644 index 0000000..a2848f0 --- /dev/null +++ b/ffmpeg/libavcodec/dirac_dwt.c @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2004-2010 Michael Niedermayer + * Copyright (C) 2008 David Conrad + * + * 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 "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "dsputil.h" +#include "dirac_dwt.h" +#include "libavcodec/x86/dirac_dwt.h" + + +static inline int mirror(int v, int m) +{ + while ((unsigned)v > (unsigned)m) { + v = -v; + if (v < 0) + v += 2 * m; + } + return v; +} + +static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] -= (b0[i] + b2[i] + 2) >> 2; +} + + +static av_always_inline +void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int w2, int add, int shift) +{ + int i; + for (i = 0; i < w2; i++) { + dst[2*i ] = (src0[i] + add) >> shift; + dst[2*i+1] = (src1[i] + add) >> shift; + } +} + +static void horizontal_compose_dirac53i(IDWTELEM *b, IDWTELEM *temp, int w) +{ + const int w2 = w >> 1; + int x; + + temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]); + for (x = 1; x < w2; x++) { + temp[x ] = COMPOSE_53iL0 (b[x+w2-1], b[x ], b[x+w2]); + temp[x+w2-1] = COMPOSE_DIRAC53iH0(temp[x-1], b[x+w2-1], temp[x]); + } + temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]); + + interleave(b, temp, temp+w2, w2, 1, 1); +} + +static void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int w) +{ + const int w2 = w >> 1; + int x; + + tmp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]); + for (x = 1; x < w2; x++) + tmp[x] = COMPOSE_53iL0(b[x+w2-1], b[x], b[x+w2]); + + // extend the edges + tmp[-1] = tmp[0]; + tmp[w2+1] = tmp[w2] = tmp[w2-1]; + + for (x = 0; x < w2; x++) { + b[2*x ] = (tmp[x] + 1)>>1; + b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1; + } +} + +static void horizontal_compose_dd137i(IDWTELEM *b, IDWTELEM *tmp, int w) +{ + const int w2 = w >> 1; + int x; + + tmp[0] = COMPOSE_DD137iL0(b[w2], b[w2], b[0], b[w2 ], b[w2+1]); + tmp[1] = COMPOSE_DD137iL0(b[w2], b[w2], b[1], b[w2+1], b[w2+2]); + for (x = 2; x < w2-1; x++) + tmp[x] = COMPOSE_DD137iL0(b[x+w2-2], b[x+w2-1], b[x], b[x+w2], b[x+w2+1]); + tmp[w2-1] = COMPOSE_DD137iL0(b[w-3], b[w-2], b[w2-1], b[w-1], b[w-1]); + + // extend the edges + tmp[-1] = tmp[0]; + tmp[w2+1] = tmp[w2] = tmp[w2-1]; + + for (x = 0; x < w2; x++) { + b[2*x ] = (tmp[x] + 1)>>1; + b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1; + } +} + +static av_always_inline +void horizontal_compose_haari(IDWTELEM *b, IDWTELEM *temp, int w, int shift) +{ + const int w2 = w >> 1; + int x; + + for (x = 0; x < w2; x++) { + temp[x ] = COMPOSE_HAARiL0(b[x ], b[x+w2]); + temp[x+w2] = COMPOSE_HAARiH0(b[x+w2], temp[x]); + } + + interleave(b, temp, temp+w2, w2, shift, shift); +} + +static void horizontal_compose_haar0i(IDWTELEM *b, IDWTELEM *temp, int w) +{ + horizontal_compose_haari(b, temp, w, 0); +} + +static void horizontal_compose_haar1i(IDWTELEM *b, IDWTELEM *temp, int w) +{ + horizontal_compose_haari(b, temp, w, 1); +} + +static void horizontal_compose_fidelityi(IDWTELEM *b, IDWTELEM *tmp, int w) +{ + const int w2 = w >> 1; + int i, x; + IDWTELEM v[8]; + + for (x = 0; x < w2; x++) { + for (i = 0; i < 8; i++) + v[i] = b[av_clip(x-3+i, 0, w2-1)]; + tmp[x] = COMPOSE_FIDELITYiH0(v[0], v[1], v[2], v[3], b[x+w2], v[4], v[5], v[6], v[7]); + } + + for (x = 0; x < w2; x++) { + for (i = 0; i < 8; i++) + v[i] = tmp[av_clip(x-4+i, 0, w2-1)]; + tmp[x+w2] = COMPOSE_FIDELITYiL0(v[0], v[1], v[2], v[3], b[x], v[4], v[5], v[6], v[7]); + } + + interleave(b, tmp+w2, tmp, w2, 0, 0); +} + +static void horizontal_compose_daub97i(IDWTELEM *b, IDWTELEM *temp, int w) +{ + const int w2 = w >> 1; + int x, b0, b1, b2; + + temp[0] = COMPOSE_DAUB97iL1(b[w2], b[0], b[w2]); + for (x = 1; x < w2; x++) { + temp[x ] = COMPOSE_DAUB97iL1(b[x+w2-1], b[x ], b[x+w2]); + temp[x+w2-1] = COMPOSE_DAUB97iH1(temp[x-1], b[x+w2-1], temp[x]); + } + temp[w-1] = COMPOSE_DAUB97iH1(temp[w2-1], b[w-1], temp[w2-1]); + + // second stage combined with interleave and shift + b0 = b2 = COMPOSE_DAUB97iL0(temp[w2], temp[0], temp[w2]); + b[0] = (b0 + 1) >> 1; + for (x = 1; x < w2; x++) { + b2 = COMPOSE_DAUB97iL0(temp[x+w2-1], temp[x ], temp[x+w2]); + b1 = COMPOSE_DAUB97iH0( b0, temp[x+w2-1], b2 ); + b[2*x-1] = (b1 + 1) >> 1; + b[2*x ] = (b2 + 1) >> 1; + b0 = b2; + } + b[w-1] = (COMPOSE_DAUB97iH0(b2, temp[w-1], b2) + 1) >> 1; +} + +static void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width) +{ + int i; + + for(i=0; ivertical_compose_l0; + vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0; + DWTCompose *cs = d->cs + level; + + int i, y = cs->y; + IDWTELEM *b[8]; + for (i = 0; i < 6; i++) + b[i] = cs->b[i]; + b[6] = d->buffer + av_clip(y+5, 0, height-2)*stride; + b[7] = d->buffer + av_clip(y+6, 1, height-1)*stride; + + if(y+5<(unsigned)height) vertical_compose_l0( b[5], b[6], b[7], width); + if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width); + + if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width); + if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width); + + for (i = 0; i < 6; i++) + cs->b[i] = b[i+2]; + cs->y += 2; +} + +static void spatial_compose_dirac53i_dy(DWTContext *d, int level, int width, int height, int stride) +{ + vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0; + vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0; + DWTCompose *cs = d->cs + level; + + int y= cs->y; + IDWTELEM *b[4] = { cs->b[0], cs->b[1] }; + b[2] = d->buffer + mirror(y+1, height-1)*stride; + b[3] = d->buffer + mirror(y+2, height-1)*stride; + + if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width); + if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width); + + if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width); + if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width); + + cs->b[0] = b[2]; + cs->b[1] = b[3]; + cs->y += 2; +} + + +static void spatial_compose_dd137i_dy(DWTContext *d, int level, int width, int height, int stride) +{ + vertical_compose_5tap vertical_compose_l0 = (void*)d->vertical_compose_l0; + vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0; + DWTCompose *cs = d->cs + level; + + int i, y = cs->y; + IDWTELEM *b[10]; + for (i = 0; i < 8; i++) + b[i] = cs->b[i]; + b[8] = d->buffer + av_clip(y+7, 0, height-2)*stride; + b[9] = d->buffer + av_clip(y+8, 1, height-1)*stride; + + if(y+5<(unsigned)height) vertical_compose_l0(b[3], b[5], b[6], b[7], b[9], width); + if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width); + + if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width); + if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width); + + for (i = 0; i < 8; i++) + cs->b[i] = b[i+2]; + cs->y += 2; +} + +// haar makes the assumption that height is even (always true for dirac) +static void spatial_compose_haari_dy(DWTContext *d, int level, int width, int height, int stride) +{ + vertical_compose_2tap vertical_compose = (void*)d->vertical_compose; + int y = d->cs[level].y; + IDWTELEM *b0 = d->buffer + (y-1)*stride; + IDWTELEM *b1 = d->buffer + (y )*stride; + + vertical_compose(b0, b1, width); + d->horizontal_compose(b0, d->temp, width); + d->horizontal_compose(b1, d->temp, width); + + d->cs[level].y += 2; +} + +// Don't do sliced idwt for fidelity; the 9 tap filter makes it a bit annoying +// Fortunately, this filter isn't used in practice. +static void spatial_compose_fidelity(DWTContext *d, int level, int width, int height, int stride) +{ + vertical_compose_9tap vertical_compose_l0 = (void*)d->vertical_compose_l0; + vertical_compose_9tap vertical_compose_h0 = (void*)d->vertical_compose_h0; + int i, y; + IDWTELEM *b[8]; + + for (y = 1; y < height; y += 2) { + for (i = 0; i < 8; i++) + b[i] = d->buffer + av_clip((y-7 + 2*i), 0, height-2)*stride; + vertical_compose_h0(d->buffer + y*stride, b, width); + } + + for (y = 0; y < height; y += 2) { + for (i = 0; i < 8; i++) + b[i] = d->buffer + av_clip((y-7 + 2*i), 1, height-1)*stride; + vertical_compose_l0(d->buffer + y*stride, b, width); + } + + for (y = 0; y < height; y++) + d->horizontal_compose(d->buffer + y*stride, d->temp, width); + + d->cs[level].y = height+1; +} + +static void spatial_compose_daub97i_dy(DWTContext *d, int level, int width, int height, int stride) +{ + vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0; + vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0; + vertical_compose_3tap vertical_compose_l1 = (void*)d->vertical_compose_l1; + vertical_compose_3tap vertical_compose_h1 = (void*)d->vertical_compose_h1; + DWTCompose *cs = d->cs + level; + + int i, y = cs->y; + IDWTELEM *b[6]; + for (i = 0; i < 4; i++) + b[i] = cs->b[i]; + b[4] = d->buffer + mirror(y+3, height-1)*stride; + b[5] = d->buffer + mirror(y+4, height-1)*stride; + + if(y+3<(unsigned)height) vertical_compose_l1(b[3], b[4], b[5], width); + if(y+2<(unsigned)height) vertical_compose_h1(b[2], b[3], b[4], width); + if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width); + if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width); + + if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width); + if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width); + + for (i = 0; i < 4; i++) + cs->b[i] = b[i+2]; + cs->y += 2; +} + + +static void spatial_compose97i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride) +{ + cs->b[0] = buffer + mirror(-3-1, height-1)*stride; + cs->b[1] = buffer + mirror(-3 , height-1)*stride; + cs->b[2] = buffer + mirror(-3+1, height-1)*stride; + cs->b[3] = buffer + mirror(-3+2, height-1)*stride; + cs->y = -3; +} + +static void spatial_compose53i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride) +{ + cs->b[0] = buffer + mirror(-1-1, height-1)*stride; + cs->b[1] = buffer + mirror(-1 , height-1)*stride; + cs->y = -1; +} + +static void spatial_compose_dd97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride) +{ + cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride; + cs->b[1] = buffer + av_clip(-5 , 1, height-1)*stride; + cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride; + cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride; + cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride; + cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride; + cs->y = -5; +} + +static void spatial_compose_dd137i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride) +{ + cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride; + cs->b[1] = buffer + av_clip(-5 , 1, height-1)*stride; + cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride; + cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride; + cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride; + cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride; + cs->b[6] = buffer + av_clip(-5+5, 0, height-2)*stride; + cs->b[7] = buffer + av_clip(-5+6, 1, height-1)*stride; + cs->y = -5; +} + +int ff_spatial_idwt_init2(DWTContext *d, IDWTELEM *buffer, int width, int height, + int stride, enum dwt_type type, int decomposition_count, + IDWTELEM *temp) +{ + int level; + + d->buffer = buffer; + d->width = width; + d->height = height; + d->stride = stride; + d->decomposition_count = decomposition_count; + d->temp = temp + 8; + + for(level=decomposition_count-1; level>=0; level--){ + int hl = height >> level; + int stride_l = stride << level; + + switch(type){ + case DWT_DIRAC_DD9_7: + spatial_compose_dd97i_init(d->cs+level, buffer, hl, stride_l); + break; + case DWT_DIRAC_LEGALL5_3: + spatial_compose53i_init2(d->cs+level, buffer, hl, stride_l); + break; + case DWT_DIRAC_DD13_7: + spatial_compose_dd137i_init(d->cs+level, buffer, hl, stride_l); + break; + case DWT_DIRAC_HAAR0: + case DWT_DIRAC_HAAR1: + d->cs[level].y = 1; + break; + case DWT_DIRAC_DAUB9_7: + spatial_compose97i_init2(d->cs+level, buffer, hl, stride_l); + break; + default: + d->cs[level].y = 0; + break; + } + } + + switch (type) { + case DWT_DIRAC_DD9_7: + d->spatial_compose = spatial_compose_dd97i_dy; + d->vertical_compose_l0 = (void*)vertical_compose53iL0; + d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0; + d->horizontal_compose = horizontal_compose_dd97i; + d->support = 7; + break; + case DWT_DIRAC_LEGALL5_3: + d->spatial_compose = spatial_compose_dirac53i_dy; + d->vertical_compose_l0 = (void*)vertical_compose53iL0; + d->vertical_compose_h0 = (void*)vertical_compose_dirac53iH0; + d->horizontal_compose = horizontal_compose_dirac53i; + d->support = 3; + break; + case DWT_DIRAC_DD13_7: + d->spatial_compose = spatial_compose_dd137i_dy; + d->vertical_compose_l0 = (void*)vertical_compose_dd137iL0; + d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0; + d->horizontal_compose = horizontal_compose_dd137i; + d->support = 7; + break; + case DWT_DIRAC_HAAR0: + case DWT_DIRAC_HAAR1: + d->spatial_compose = spatial_compose_haari_dy; + d->vertical_compose = (void*)vertical_compose_haar; + if (type == DWT_DIRAC_HAAR0) + d->horizontal_compose = horizontal_compose_haar0i; + else + d->horizontal_compose = horizontal_compose_haar1i; + d->support = 1; + break; + case DWT_DIRAC_FIDELITY: + d->spatial_compose = spatial_compose_fidelity; + d->vertical_compose_l0 = (void*)vertical_compose_fidelityiL0; + d->vertical_compose_h0 = (void*)vertical_compose_fidelityiH0; + d->horizontal_compose = horizontal_compose_fidelityi; + break; + case DWT_DIRAC_DAUB9_7: + d->spatial_compose = spatial_compose_daub97i_dy; + d->vertical_compose_l0 = (void*)vertical_compose_daub97iL0; + d->vertical_compose_h0 = (void*)vertical_compose_daub97iH0; + d->vertical_compose_l1 = (void*)vertical_compose_daub97iL1; + d->vertical_compose_h1 = (void*)vertical_compose_daub97iH1; + d->horizontal_compose = horizontal_compose_daub97i; + d->support = 5; + break; + default: + av_log(NULL, AV_LOG_ERROR, "Unknown wavelet type %d\n", type); + return -1; + } + + if (HAVE_MMX) ff_spatial_idwt_init_mmx(d, type); + + return 0; +} + +void ff_spatial_idwt_slice2(DWTContext *d, int y) +{ + int level, support = d->support; + + for (level = d->decomposition_count-1; level >= 0; level--) { + int wl = d->width >> level; + int hl = d->height >> level; + int stride_l = d->stride << level; + + while (d->cs[level].y <= FFMIN((y>>level)+support, hl)) + d->spatial_compose(d, level, wl, hl, stride_l); + } +} + +int ff_spatial_idwt2(IDWTELEM *buffer, int width, int height, int stride, + enum dwt_type type, int decomposition_count, IDWTELEM *temp) +{ + DWTContext d; + int y; + + if (ff_spatial_idwt_init2(&d, buffer, width, height, stride, type, decomposition_count, temp)) + return -1; + + for (y = 0; y < d.height; y += 4) + ff_spatial_idwt_slice2(&d, y); + + return 0; +} diff --git a/ffmpeg/libavcodec/dirac_dwt.h b/ffmpeg/libavcodec/dirac_dwt.h new file mode 100644 index 0000000..9514e95 --- /dev/null +++ b/ffmpeg/libavcodec/dirac_dwt.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2004-2010 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 + */ + +#ifndef AVCODEC_DIRAC_DWT_H +#define AVCODEC_DIRAC_DWT_H + +#include + +typedef int DWTELEM; +typedef short IDWTELEM; + +#define MAX_DWT_SUPPORT 8 +#define MAX_DECOMPOSITIONS 8 + +typedef struct DWTCompose { + IDWTELEM *b[MAX_DWT_SUPPORT]; + int y; +} DWTCompose; + +struct DWTContext; + +// Possible prototypes for vertical_compose functions +typedef void (*vertical_compose_2tap)(IDWTELEM *b0, IDWTELEM *b1, int width); +typedef void (*vertical_compose_3tap)(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width); +typedef void (*vertical_compose_5tap)(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, int width); +typedef void (*vertical_compose_9tap)(IDWTELEM *dst, IDWTELEM *b[8], int width); + +typedef struct DWTContext { + IDWTELEM *buffer; + IDWTELEM *temp; + int width; + int height; + int stride; + int decomposition_count; + int support; + + void (*spatial_compose)(struct DWTContext *cs, int level, int width, int height, int stride); + void (*vertical_compose_l0)(void); + void (*vertical_compose_h0)(void); + void (*vertical_compose_l1)(void); + void (*vertical_compose_h1)(void); + void (*vertical_compose)(void); ///< one set of lowpass and highpass combined + void (*horizontal_compose)(IDWTELEM *b, IDWTELEM *tmp, int width); + + DWTCompose cs[MAX_DECOMPOSITIONS]; +} DWTContext; + +enum dwt_type { + DWT_SNOW_DAUB9_7, + DWT_SNOW_LEGALL5_3, + DWT_DIRAC_DD9_7, + DWT_DIRAC_LEGALL5_3, + DWT_DIRAC_DD13_7, + DWT_DIRAC_HAAR0, + DWT_DIRAC_HAAR1, + DWT_DIRAC_FIDELITY, + DWT_DIRAC_DAUB9_7, + DWT_NUM_TYPES +}; + +// -1 if an error occurred, e.g. the dwt_type isn't recognized +int ff_spatial_idwt_init2(DWTContext *d, IDWTELEM *buffer, int width, int height, + int stride, enum dwt_type type, int decomposition_count, + IDWTELEM *temp); + +int ff_spatial_idwt2(IDWTELEM *buffer, int width, int height, int stride, + enum dwt_type type, int decomposition_count, IDWTELEM *temp); + +void ff_spatial_idwt_slice2(DWTContext *d, int y); + +// shared stuff for simd optimiztions +#define COMPOSE_53iL0(b0, b1, b2)\ + (b1 - ((b0 + b2 + 2) >> 2)) + +#define COMPOSE_DIRAC53iH0(b0, b1, b2)\ + (b1 + ((b0 + b2 + 1) >> 1)) + +#define COMPOSE_DD97iH0(b0, b1, b2, b3, b4)\ + (b2 + ((-b0 + 9*b1 + 9*b3 - b4 + 8) >> 4)) + +#define COMPOSE_DD137iL0(b0, b1, b2, b3, b4)\ + (b2 - ((-b0 + 9*b1 + 9*b3 - b4 + 16) >> 5)) + +#define COMPOSE_HAARiL0(b0, b1)\ + (b0 - ((b1 + 1) >> 1)) + +#define COMPOSE_HAARiH0(b0, b1)\ + (b0 + b1) + +#define COMPOSE_FIDELITYiL0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\ + (b4 - ((-8*(b0+b8) + 21*(b1+b7) - 46*(b2+b6) + 161*(b3+b5) + 128) >> 8)) + +#define COMPOSE_FIDELITYiH0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\ + (b4 + ((-2*(b0+b8) + 10*(b1+b7) - 25*(b2+b6) + 81*(b3+b5) + 128) >> 8)) + +#define COMPOSE_DAUB97iL1(b0, b1, b2)\ + (b1 - ((1817*(b0 + b2) + 2048) >> 12)) + +#define COMPOSE_DAUB97iH1(b0, b1, b2)\ + (b1 - (( 113*(b0 + b2) + 64) >> 7)) + +#define COMPOSE_DAUB97iL0(b0, b1, b2)\ + (b1 + (( 217*(b0 + b2) + 2048) >> 12)) + +#define COMPOSE_DAUB97iH0(b0, b1, b2)\ + (b1 + ((6497*(b0 + b2) + 2048) >> 12)) + + +#endif /* AVCODEC_DWT_H */ diff --git a/ffmpeg/libavcodec/dirac_parser.c b/ffmpeg/libavcodec/dirac_parser.c new file mode 100644 index 0000000..a2a22ee --- /dev/null +++ b/ffmpeg/libavcodec/dirac_parser.c @@ -0,0 +1,260 @@ +/* + * Dirac parser + * + * Copyright (c) 2007-2008 Marco Gerards + * Copyright (c) 2008 BBC, Anuradha Suraparaju + * + * 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 + */ + +/** + * @file + * Dirac Parser + * @author Marco Gerards + */ + +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "parser.h" + +#define DIRAC_PARSE_INFO_PREFIX 0x42424344 + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame or -1 + */ +typedef struct DiracParseContext { + int state; + int is_synced; + int sync_offset; + int header_bytes_needed; + int overread_index; + int buffer_size; + int index; + uint8_t *buffer; + int dirac_unit_size; + uint8_t *dirac_unit; +} DiracParseContext; + +static int find_frame_end(DiracParseContext *pc, + const uint8_t *buf, int buf_size) +{ + uint32_t state = pc->state; + int i = 0; + + if (!pc->is_synced) { + for (i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (state == DIRAC_PARSE_INFO_PREFIX) { + state = -1; + pc->is_synced = 1; + pc->header_bytes_needed = 9; + pc->sync_offset = i; + break; + } + } + } + + if (pc->is_synced) { + pc->sync_offset = 0; + for (; i < buf_size; i++) { + if (state == DIRAC_PARSE_INFO_PREFIX) { + if ((buf_size-i) >= pc->header_bytes_needed) { + pc->state = -1; + return i + pc->header_bytes_needed; + } else { + pc->header_bytes_needed = 9-(buf_size-i); + break; + } + } else + state = (state << 8) | buf[i]; + } + } + pc->state = state; + return -1; +} + +typedef struct DiracParseUnit +{ + int next_pu_offset; + int prev_pu_offset; + uint8_t pu_type; +} DiracParseUnit; + +static int unpack_parse_unit(DiracParseUnit *pu, DiracParseContext *pc, + int offset) +{ + uint8_t *start = pc->buffer + offset; + uint8_t *end = pc->buffer + pc->index; + if (start < pc->buffer || (start+13 > end)) + return 0; + pu->pu_type = start[4]; + + pu->next_pu_offset = AV_RB32(start+5); + pu->prev_pu_offset = AV_RB32(start+9); + + if (pu->pu_type == 0x10 && pu->next_pu_offset == 0) + pu->next_pu_offset = 13; + + return 1; +} + +static int dirac_combine_frame(AVCodecParserContext *s, AVCodecContext *avctx, + int next, const uint8_t **buf, int *buf_size) +{ + int parse_timing_info = (s->pts == AV_NOPTS_VALUE && + s->dts == AV_NOPTS_VALUE); + DiracParseContext *pc = s->priv_data; + + if (pc->overread_index) { + memcpy(pc->buffer, pc->buffer + pc->overread_index, + pc->index - pc->overread_index); + pc->index -= pc->overread_index; + pc->overread_index = 0; + if (*buf_size == 0 && pc->buffer[4] == 0x10) { + *buf = pc->buffer; + *buf_size = pc->index; + return 0; + } + } + + if ( next == -1) { + /* Found a possible frame start but not a frame end */ + void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, + pc->index + (*buf_size - + pc->sync_offset)); + pc->buffer = new_buffer; + memcpy(pc->buffer+pc->index, (*buf + pc->sync_offset), + *buf_size - pc->sync_offset); + pc->index += *buf_size - pc->sync_offset; + return -1; + } else { + /* Found a possible frame start and a possible frame end */ + DiracParseUnit pu1, pu; + void *new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, + pc->index + next); + pc->buffer = new_buffer; + memcpy(pc->buffer + pc->index, *buf, next); + pc->index += next; + + /* Need to check if we have a valid Parse Unit. We can't go by the + * sync pattern 'BBCD' alone because arithmetic coding of the residual + * and motion data can cause the pattern triggering a false start of + * frame. So check if the previous parse offset of the next parse unit + * is equal to the next parse offset of the current parse unit then + * we can be pretty sure that we have a valid parse unit */ + if (!unpack_parse_unit(&pu1, pc, pc->index - 13) || + !unpack_parse_unit(&pu, pc, pc->index - 13 - pu1.prev_pu_offset) || + pu.next_pu_offset != pu1.prev_pu_offset || + pc->index < pc->dirac_unit_size + 13LL + pu1.prev_pu_offset + ) { + pc->index -= 9; + *buf_size = next-9; + pc->header_bytes_needed = 9; + return -1; + } + + /* All non-frame data must be accompanied by frame data. This is to + * ensure that pts is set correctly. So if the current parse unit is + * not frame data, wait for frame data to come along */ + + pc->dirac_unit = pc->buffer + pc->index - 13 - + pu1.prev_pu_offset - pc->dirac_unit_size; + + pc->dirac_unit_size += pu.next_pu_offset; + + if ((pu.pu_type&0x08) != 0x08) { + pc->header_bytes_needed = 9; + *buf_size = next; + return -1; + } + + /* Get the picture number to set the pts and dts*/ + if (parse_timing_info) { + uint8_t *cur_pu = pc->buffer + + pc->index - 13 - pu1.prev_pu_offset; + int pts = AV_RB32(cur_pu + 13); + if (s->last_pts == 0 && s->last_dts == 0) + s->dts = pts - 1; + else + s->dts = s->last_dts+1; + s->pts = pts; + if (!avctx->has_b_frames && (cur_pu[4] & 0x03)) + avctx->has_b_frames = 1; + } + if (avctx->has_b_frames && s->pts == s->dts) + s->pict_type = AV_PICTURE_TYPE_B; + + /* Finally have a complete Dirac data unit */ + *buf = pc->dirac_unit; + *buf_size = pc->dirac_unit_size; + + pc->dirac_unit_size = 0; + pc->overread_index = pc->index-13; + pc->header_bytes_needed = 9; + } + return next; +} + +static int dirac_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DiracParseContext *pc = s->priv_data; + int next; + + *poutbuf = NULL; + *poutbuf_size = 0; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + *poutbuf = buf; + *poutbuf_size = buf_size; + /* Assume that data has been packetized into an encapsulation unit. */ + } else { + next = find_frame_end(pc, buf, buf_size); + if (!pc->is_synced && next == -1) { + /* No frame start found yet. So throw away the entire buffer. */ + return buf_size; + } + + if (dirac_combine_frame(s, avctx, next, &buf, &buf_size) < 0) { + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +static void dirac_parse_close(AVCodecParserContext *s) +{ + DiracParseContext *pc = s->priv_data; + + if (pc->buffer_size > 0) + av_free(pc->buffer); +} + +AVCodecParser ff_dirac_parser = { + .codec_ids = { AV_CODEC_ID_DIRAC }, + .priv_data_size = sizeof(DiracParseContext), + .parser_parse = dirac_parse, + .parser_close = dirac_parse_close, +}; diff --git a/ffmpeg/libavcodec/diracdec.c b/ffmpeg/libavcodec/diracdec.c new file mode 100644 index 0000000..81d2b65 --- /dev/null +++ b/ffmpeg/libavcodec/diracdec.c @@ -0,0 +1,1938 @@ +/* + * Copyright (C) 2007 Marco Gerards + * Copyright (C) 2009 David Conrad + * Copyright (C) 2011 Jordi Ortiz + * + * 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 + */ + +/** + * @file + * Dirac Decoder + * @author Marco Gerards , David Conrad, Jordi Ortiz + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "bytestream.h" +#include "internal.h" +#include "golomb.h" +#include "dirac_arith.h" +#include "mpeg12data.h" +#include "dirac_dwt.h" +#include "dirac.h" +#include "diracdsp.h" +#include "videodsp.h" // for ff_emulated_edge_mc_8 + +/** + * The spec limits the number of wavelet decompositions to 4 for both + * level 1 (VC-2) and 128 (long-gop default). + * 5 decompositions is the maximum before >16-bit buffers are needed. + * Schroedinger allows this for DD 9,7 and 13,7 wavelets only, limiting + * the others to 4 decompositions (or 3 for the fidelity filter). + * + * We use this instead of MAX_DECOMPOSITIONS to save some memory. + */ +#define MAX_DWT_LEVELS 5 + +/** + * The spec limits this to 3 for frame coding, but in practice can be as high as 6 + */ +#define MAX_REFERENCE_FRAMES 8 +#define MAX_DELAY 5 /* limit for main profile for frame coding (TODO: field coding) */ +#define MAX_FRAMES (MAX_REFERENCE_FRAMES + MAX_DELAY + 1) +#define MAX_QUANT 68 /* max quant for VC-2 */ +#define MAX_BLOCKSIZE 32 /* maximum xblen/yblen we support */ + +/** + * DiracBlock->ref flags, if set then the block does MC from the given ref + */ +#define DIRAC_REF_MASK_REF1 1 +#define DIRAC_REF_MASK_REF2 2 +#define DIRAC_REF_MASK_GLOBAL 4 + +/** + * Value of Picture.reference when Picture is not a reference picture, but + * is held for delayed output. + */ +#define DELAYED_PIC_REF 4 + +#define ff_emulated_edge_mc ff_emulated_edge_mc_8 /* Fix: change the calls to this function regarding bit depth */ + +#define CALC_PADDING(size, depth) \ + (((size + (1 << depth) - 1) >> depth) << depth) + +#define DIVRNDUP(a, b) (((a) + (b) - 1) / (b)) + +typedef struct { + AVFrame avframe; + int interpolated[3]; /* 1 if hpel[] is valid */ + uint8_t *hpel[3][4]; + uint8_t *hpel_base[3][4]; +} DiracFrame; + +typedef struct { + union { + int16_t mv[2][2]; + int16_t dc[3]; + } u; /* anonymous unions aren't in C99 :( */ + uint8_t ref; +} DiracBlock; + +typedef struct SubBand { + int level; + int orientation; + int stride; + int width; + int height; + int quant; + IDWTELEM *ibuf; + struct SubBand *parent; + + /* for low delay */ + unsigned length; + const uint8_t *coeff_data; +} SubBand; + +typedef struct Plane { + int width; + int height; + int stride; + + int idwt_width; + int idwt_height; + int idwt_stride; + IDWTELEM *idwt_buf; + IDWTELEM *idwt_buf_base; + IDWTELEM *idwt_tmp; + + /* block length */ + uint8_t xblen; + uint8_t yblen; + /* block separation (block n+1 starts after this many pixels in block n) */ + uint8_t xbsep; + uint8_t ybsep; + /* amount of overspill on each edge (half of the overlap between blocks) */ + uint8_t xoffset; + uint8_t yoffset; + + SubBand band[MAX_DWT_LEVELS][4]; +} Plane; + +typedef struct DiracContext { + AVCodecContext *avctx; + DSPContext dsp; + DiracDSPContext diracdsp; + GetBitContext gb; + dirac_source_params source; + int seen_sequence_header; + int frame_number; /* number of the next frame to display */ + Plane plane[3]; + int chroma_x_shift; + int chroma_y_shift; + + int zero_res; /* zero residue flag */ + int is_arith; /* whether coeffs use arith or golomb coding */ + int low_delay; /* use the low delay syntax */ + int globalmc_flag; /* use global motion compensation */ + int num_refs; /* number of reference pictures */ + + /* wavelet decoding */ + unsigned wavelet_depth; /* depth of the IDWT */ + unsigned wavelet_idx; + + /** + * schroedinger older than 1.0.8 doesn't store + * quant delta if only one codebook exists in a band + */ + unsigned old_delta_quant; + unsigned codeblock_mode; + + struct { + unsigned width; + unsigned height; + } codeblock[MAX_DWT_LEVELS+1]; + + struct { + unsigned num_x; /* number of horizontal slices */ + unsigned num_y; /* number of vertical slices */ + AVRational bytes; /* average bytes per slice */ + uint8_t quant[MAX_DWT_LEVELS][4]; /* [DIRAC_STD] E.1 */ + } lowdelay; + + struct { + int pan_tilt[2]; /* pan/tilt vector */ + int zrs[2][2]; /* zoom/rotate/shear matrix */ + int perspective[2]; /* perspective vector */ + unsigned zrs_exp; + unsigned perspective_exp; + } globalmc[2]; + + /* motion compensation */ + uint8_t mv_precision; /* [DIRAC_STD] REFS_WT_PRECISION */ + int16_t weight[2]; /* [DIRAC_STD] REF1_WT and REF2_WT */ + unsigned weight_log2denom; /* [DIRAC_STD] REFS_WT_PRECISION */ + + int blwidth; /* number of blocks (horizontally) */ + int blheight; /* number of blocks (vertically) */ + int sbwidth; /* number of superblocks (horizontally) */ + int sbheight; /* number of superblocks (vertically) */ + + uint8_t *sbsplit; + DiracBlock *blmotion; + + uint8_t *edge_emu_buffer[4]; + uint8_t *edge_emu_buffer_base; + + uint16_t *mctmp; /* buffer holding the MC data multipled by OBMC weights */ + uint8_t *mcscratch; + + DECLARE_ALIGNED(16, uint8_t, obmc_weight)[3][MAX_BLOCKSIZE*MAX_BLOCKSIZE]; + + void (*put_pixels_tab[4])(uint8_t *dst, const uint8_t *src[5], int stride, int h); + void (*avg_pixels_tab[4])(uint8_t *dst, const uint8_t *src[5], int stride, int h); + void (*add_obmc)(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); + dirac_weight_func weight_func; + dirac_biweight_func biweight_func; + + DiracFrame *current_picture; + DiracFrame *ref_pics[2]; + + DiracFrame *ref_frames[MAX_REFERENCE_FRAMES+1]; + DiracFrame *delay_frames[MAX_DELAY+1]; + DiracFrame all_frames[MAX_FRAMES]; +} DiracContext; + +/** + * Dirac Specification -> + * Parse code values. 9.6.1 Table 9.1 + */ +enum dirac_parse_code { + pc_seq_header = 0x00, + pc_eos = 0x10, + pc_aux_data = 0x20, + pc_padding = 0x30, +}; + +enum dirac_subband { + subband_ll = 0, + subband_hl = 1, + subband_lh = 2, + subband_hh = 3 +}; + +static const uint8_t default_qmat[][4][4] = { + { { 5, 3, 3, 0}, { 0, 4, 4, 1}, { 0, 5, 5, 2}, { 0, 6, 6, 3} }, + { { 4, 2, 2, 0}, { 0, 4, 4, 2}, { 0, 5, 5, 3}, { 0, 7, 7, 5} }, + { { 5, 3, 3, 0}, { 0, 4, 4, 1}, { 0, 5, 5, 2}, { 0, 6, 6, 3} }, + { { 8, 4, 4, 0}, { 0, 4, 4, 0}, { 0, 4, 4, 0}, { 0, 4, 4, 0} }, + { { 8, 4, 4, 0}, { 0, 4, 4, 0}, { 0, 4, 4, 0}, { 0, 4, 4, 0} }, + { { 0, 4, 4, 8}, { 0, 8, 8, 12}, { 0, 13, 13, 17}, { 0, 17, 17, 21} }, + { { 3, 1, 1, 0}, { 0, 4, 4, 2}, { 0, 6, 6, 5}, { 0, 9, 9, 7} }, +}; + +static const int qscale_tab[MAX_QUANT+1] = { + 4, 5, 6, 7, 8, 10, 11, 13, + 16, 19, 23, 27, 32, 38, 45, 54, + 64, 76, 91, 108, 128, 152, 181, 215, + 256, 304, 362, 431, 512, 609, 724, 861, + 1024, 1218, 1448, 1722, 2048, 2435, 2896, 3444, + 4096, 4871, 5793, 6889, 8192, 9742, 11585, 13777, + 16384, 19484, 23170, 27554, 32768, 38968, 46341, 55109, + 65536, 77936 +}; + +static const int qoffset_intra_tab[MAX_QUANT+1] = { + 1, 2, 3, 4, 4, 5, 6, 7, + 8, 10, 12, 14, 16, 19, 23, 27, + 32, 38, 46, 54, 64, 76, 91, 108, + 128, 152, 181, 216, 256, 305, 362, 431, + 512, 609, 724, 861, 1024, 1218, 1448, 1722, + 2048, 2436, 2897, 3445, 4096, 4871, 5793, 6889, + 8192, 9742, 11585, 13777, 16384, 19484, 23171, 27555, + 32768, 38968 +}; + +static const int qoffset_inter_tab[MAX_QUANT+1] = { + 1, 2, 2, 3, 3, 4, 4, 5, + 6, 7, 9, 10, 12, 14, 17, 20, + 24, 29, 34, 41, 48, 57, 68, 81, + 96, 114, 136, 162, 192, 228, 272, 323, + 384, 457, 543, 646, 768, 913, 1086, 1292, + 1536, 1827, 2172, 2583, 3072, 3653, 4344, 5166, + 6144, 7307, 8689, 10333, 12288, 14613, 17378, 20666, + 24576, 29226 +}; + +/* magic number division by 3 from schroedinger */ +static inline int divide3(int x) +{ + return ((x+1)*21845 + 10922) >> 16; +} + +static DiracFrame *remove_frame(DiracFrame *framelist[], int picnum) +{ + DiracFrame *remove_pic = NULL; + int i, remove_idx = -1; + + for (i = 0; framelist[i]; i++) + if (framelist[i]->avframe.display_picture_number == picnum) { + remove_pic = framelist[i]; + remove_idx = i; + } + + if (remove_pic) + for (i = remove_idx; framelist[i]; i++) + framelist[i] = framelist[i+1]; + + return remove_pic; +} + +static int add_frame(DiracFrame *framelist[], int maxframes, DiracFrame *frame) +{ + int i; + for (i = 0; i < maxframes; i++) + if (!framelist[i]) { + framelist[i] = frame; + return 0; + } + return -1; +} + +static int alloc_sequence_buffers(DiracContext *s) +{ + int sbwidth = DIVRNDUP(s->source.width, 4); + int sbheight = DIVRNDUP(s->source.height, 4); + int i, w, h, top_padding; + + /* todo: think more about this / use or set Plane here */ + for (i = 0; i < 3; i++) { + int max_xblen = MAX_BLOCKSIZE >> (i ? s->chroma_x_shift : 0); + int max_yblen = MAX_BLOCKSIZE >> (i ? s->chroma_y_shift : 0); + w = s->source.width >> (i ? s->chroma_x_shift : 0); + h = s->source.height >> (i ? s->chroma_y_shift : 0); + + /* we allocate the max we support here since num decompositions can + * change from frame to frame. Stride is aligned to 16 for SIMD, and + * 1<0) in arith decoding + * MAX_BLOCKSIZE padding for MC: blocks can spill up to half of that + * on each side */ + top_padding = FFMAX(1<plane[i].idwt_buf_base = av_mallocz((w+max_xblen)*h * sizeof(IDWTELEM)); + s->plane[i].idwt_tmp = av_malloc((w+16) * sizeof(IDWTELEM)); + s->plane[i].idwt_buf = s->plane[i].idwt_buf_base + top_padding*w; + if (!s->plane[i].idwt_buf_base || !s->plane[i].idwt_tmp) + return AVERROR(ENOMEM); + } + + w = s->source.width; + h = s->source.height; + + /* fixme: allocate using real stride here */ + s->sbsplit = av_malloc(sbwidth * sbheight); + s->blmotion = av_malloc(sbwidth * sbheight * 16 * sizeof(*s->blmotion)); + s->edge_emu_buffer_base = av_malloc((w+64)*MAX_BLOCKSIZE); + + s->mctmp = av_malloc((w+64+MAX_BLOCKSIZE) * (h+MAX_BLOCKSIZE) * sizeof(*s->mctmp)); + s->mcscratch = av_malloc((w+64)*MAX_BLOCKSIZE); + + if (!s->sbsplit || !s->blmotion || !s->mctmp || !s->mcscratch) + return AVERROR(ENOMEM); + return 0; +} + +static void free_sequence_buffers(DiracContext *s) +{ + int i, j, k; + + for (i = 0; i < MAX_FRAMES; i++) { + if (s->all_frames[i].avframe.data[0]) { + av_frame_unref(&s->all_frames[i].avframe); + memset(s->all_frames[i].interpolated, 0, sizeof(s->all_frames[i].interpolated)); + } + + for (j = 0; j < 3; j++) + for (k = 1; k < 4; k++) + av_freep(&s->all_frames[i].hpel_base[j][k]); + } + + memset(s->ref_frames, 0, sizeof(s->ref_frames)); + memset(s->delay_frames, 0, sizeof(s->delay_frames)); + + for (i = 0; i < 3; i++) { + av_freep(&s->plane[i].idwt_buf_base); + av_freep(&s->plane[i].idwt_tmp); + } + + av_freep(&s->sbsplit); + av_freep(&s->blmotion); + av_freep(&s->edge_emu_buffer_base); + + av_freep(&s->mctmp); + av_freep(&s->mcscratch); +} + +static av_cold int dirac_decode_init(AVCodecContext *avctx) +{ + DiracContext *s = avctx->priv_data; + s->avctx = avctx; + s->frame_number = -1; + + if (avctx->flags&CODEC_FLAG_EMU_EDGE) { + av_log(avctx, AV_LOG_ERROR, "Edge emulation not supported!\n"); + return AVERROR_PATCHWELCOME; + } + + ff_dsputil_init(&s->dsp, avctx); + ff_diracdsp_init(&s->diracdsp); + + return 0; +} + +static void dirac_decode_flush(AVCodecContext *avctx) +{ + DiracContext *s = avctx->priv_data; + free_sequence_buffers(s); + s->seen_sequence_header = 0; + s->frame_number = -1; +} + +static av_cold int dirac_decode_end(AVCodecContext *avctx) +{ + dirac_decode_flush(avctx); + return 0; +} + +#define SIGN_CTX(x) (CTX_SIGN_ZERO + ((x) > 0) - ((x) < 0)) + +static inline void coeff_unpack_arith(DiracArith *c, int qfactor, int qoffset, + SubBand *b, IDWTELEM *buf, int x, int y) +{ + int coeff, sign; + int sign_pred = 0; + int pred_ctx = CTX_ZPZN_F1; + + /* Check if the parent subband has a 0 in the corresponding position */ + if (b->parent) + pred_ctx += !!b->parent->ibuf[b->parent->stride * (y>>1) + (x>>1)] << 1; + + if (b->orientation == subband_hl) + sign_pred = buf[-b->stride]; + + /* Determine if the pixel has only zeros in its neighbourhood */ + if (x) { + pred_ctx += !(buf[-1] | buf[-b->stride] | buf[-1-b->stride]); + if (b->orientation == subband_lh) + sign_pred = buf[-1]; + } else { + pred_ctx += !buf[-b->stride]; + } + + coeff = dirac_get_arith_uint(c, pred_ctx, CTX_COEFF_DATA); + if (coeff) { + coeff = (coeff * qfactor + qoffset + 2) >> 2; + sign = dirac_get_arith_bit(c, SIGN_CTX(sign_pred)); + coeff = (coeff ^ -sign) + sign; + } + *buf = coeff; +} + +static inline int coeff_unpack_golomb(GetBitContext *gb, int qfactor, int qoffset) +{ + int sign, coeff; + + coeff = svq3_get_ue_golomb(gb); + if (coeff) { + coeff = (coeff * qfactor + qoffset + 2) >> 2; + sign = get_bits1(gb); + coeff = (coeff ^ -sign) + sign; + } + return coeff; +} + +/** + * Decode the coeffs in the rectangle defined by left, right, top, bottom + * [DIRAC_STD] 13.4.3.2 Codeblock unpacking loop. codeblock() + */ +static inline void codeblock(DiracContext *s, SubBand *b, + GetBitContext *gb, DiracArith *c, + int left, int right, int top, int bottom, + int blockcnt_one, int is_arith) +{ + int x, y, zero_block; + int qoffset, qfactor; + IDWTELEM *buf; + + /* check for any coded coefficients in this codeblock */ + if (!blockcnt_one) { + if (is_arith) + zero_block = dirac_get_arith_bit(c, CTX_ZERO_BLOCK); + else + zero_block = get_bits1(gb); + + if (zero_block) + return; + } + + if (s->codeblock_mode && !(s->old_delta_quant && blockcnt_one)) { + int quant = b->quant; + if (is_arith) + quant += dirac_get_arith_int(c, CTX_DELTA_Q_F, CTX_DELTA_Q_DATA); + else + quant += dirac_get_se_golomb(gb); + if (quant < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid quant\n"); + return; + } + b->quant = quant; + } + + b->quant = FFMIN(b->quant, MAX_QUANT); + + qfactor = qscale_tab[b->quant]; + /* TODO: context pointer? */ + if (!s->num_refs) + qoffset = qoffset_intra_tab[b->quant]; + else + qoffset = qoffset_inter_tab[b->quant]; + + buf = b->ibuf + top * b->stride; + for (y = top; y < bottom; y++) { + for (x = left; x < right; x++) { + /* [DIRAC_STD] 13.4.4 Subband coefficients. coeff_unpack() */ + if (is_arith) + coeff_unpack_arith(c, qfactor, qoffset, b, buf+x, x, y); + else + buf[x] = coeff_unpack_golomb(gb, qfactor, qoffset); + } + buf += b->stride; + } +} + +/** + * Dirac Specification -> + * 13.3 intra_dc_prediction(band) + */ +static inline void intra_dc_prediction(SubBand *b) +{ + IDWTELEM *buf = b->ibuf; + int x, y; + + for (x = 1; x < b->width; x++) + buf[x] += buf[x-1]; + buf += b->stride; + + for (y = 1; y < b->height; y++) { + buf[0] += buf[-b->stride]; + + for (x = 1; x < b->width; x++) { + int pred = buf[x - 1] + buf[x - b->stride] + buf[x - b->stride-1]; + buf[x] += divide3(pred); + } + buf += b->stride; + } +} + +/** + * Dirac Specification -> + * 13.4.2 Non-skipped subbands. subband_coeffs() + */ +static av_always_inline void decode_subband_internal(DiracContext *s, SubBand *b, int is_arith) +{ + int cb_x, cb_y, left, right, top, bottom; + DiracArith c; + GetBitContext gb; + int cb_width = s->codeblock[b->level + (b->orientation != subband_ll)].width; + int cb_height = s->codeblock[b->level + (b->orientation != subband_ll)].height; + int blockcnt_one = (cb_width + cb_height) == 2; + + if (!b->length) + return; + + init_get_bits(&gb, b->coeff_data, b->length*8); + + if (is_arith) + ff_dirac_init_arith_decoder(&c, &gb, b->length); + + top = 0; + for (cb_y = 0; cb_y < cb_height; cb_y++) { + bottom = (b->height * (cb_y+1)) / cb_height; + left = 0; + for (cb_x = 0; cb_x < cb_width; cb_x++) { + right = (b->width * (cb_x+1)) / cb_width; + codeblock(s, b, &gb, &c, left, right, top, bottom, blockcnt_one, is_arith); + left = right; + } + top = bottom; + } + + if (b->orientation == subband_ll && s->num_refs == 0) + intra_dc_prediction(b); +} + +static int decode_subband_arith(AVCodecContext *avctx, void *b) +{ + DiracContext *s = avctx->priv_data; + decode_subband_internal(s, b, 1); + return 0; +} + +static int decode_subband_golomb(AVCodecContext *avctx, void *arg) +{ + DiracContext *s = avctx->priv_data; + SubBand **b = arg; + decode_subband_internal(s, *b, 0); + return 0; +} + +/** + * Dirac Specification -> + * [DIRAC_STD] 13.4.1 core_transform_data() + */ +static void decode_component(DiracContext *s, int comp) +{ + AVCodecContext *avctx = s->avctx; + SubBand *bands[3*MAX_DWT_LEVELS+1]; + enum dirac_subband orientation; + int level, num_bands = 0; + + /* Unpack all subbands at all levels. */ + for (level = 0; level < s->wavelet_depth; level++) { + for (orientation = !!level; orientation < 4; orientation++) { + SubBand *b = &s->plane[comp].band[level][orientation]; + bands[num_bands++] = b; + + align_get_bits(&s->gb); + /* [DIRAC_STD] 13.4.2 subband() */ + b->length = svq3_get_ue_golomb(&s->gb); + if (b->length) { + b->quant = svq3_get_ue_golomb(&s->gb); + align_get_bits(&s->gb); + b->coeff_data = s->gb.buffer + get_bits_count(&s->gb)/8; + b->length = FFMIN(b->length, FFMAX(get_bits_left(&s->gb)/8, 0)); + skip_bits_long(&s->gb, b->length*8); + } + } + /* arithmetic coding has inter-level dependencies, so we can only execute one level at a time */ + if (s->is_arith) + avctx->execute(avctx, decode_subband_arith, &s->plane[comp].band[level][!!level], + NULL, 4-!!level, sizeof(SubBand)); + } + /* golomb coding has no inter-level dependencies, so we can execute all subbands in parallel */ + if (!s->is_arith) + avctx->execute(avctx, decode_subband_golomb, bands, NULL, num_bands, sizeof(SubBand*)); +} + +/* [DIRAC_STD] 13.5.5.2 Luma slice subband data. luma_slice_band(level,orient,sx,sy) --> if b2 == NULL */ +/* [DIRAC_STD] 13.5.5.3 Chroma slice subband data. chroma_slice_band(level,orient,sx,sy) --> if b2 != NULL */ +static void lowdelay_subband(DiracContext *s, GetBitContext *gb, int quant, + int slice_x, int slice_y, int bits_end, + SubBand *b1, SubBand *b2) +{ + int left = b1->width * slice_x / s->lowdelay.num_x; + int right = b1->width *(slice_x+1) / s->lowdelay.num_x; + int top = b1->height * slice_y / s->lowdelay.num_y; + int bottom = b1->height *(slice_y+1) / s->lowdelay.num_y; + + int qfactor = qscale_tab[FFMIN(quant, MAX_QUANT)]; + int qoffset = qoffset_intra_tab[FFMIN(quant, MAX_QUANT)]; + + IDWTELEM *buf1 = b1->ibuf + top * b1->stride; + IDWTELEM *buf2 = b2 ? b2->ibuf + top * b2->stride : NULL; + int x, y; + /* we have to constantly check for overread since the spec explictly + requires this, with the meaning that all remaining coeffs are set to 0 */ + if (get_bits_count(gb) >= bits_end) + return; + + for (y = top; y < bottom; y++) { + for (x = left; x < right; x++) { + buf1[x] = coeff_unpack_golomb(gb, qfactor, qoffset); + if (get_bits_count(gb) >= bits_end) + return; + if (buf2) { + buf2[x] = coeff_unpack_golomb(gb, qfactor, qoffset); + if (get_bits_count(gb) >= bits_end) + return; + } + } + buf1 += b1->stride; + if (buf2) + buf2 += b2->stride; + } +} + +struct lowdelay_slice { + GetBitContext gb; + int slice_x; + int slice_y; + int bytes; +}; + + +/** + * Dirac Specification -> + * 13.5.2 Slices. slice(sx,sy) + */ +static int decode_lowdelay_slice(AVCodecContext *avctx, void *arg) +{ + DiracContext *s = avctx->priv_data; + struct lowdelay_slice *slice = arg; + GetBitContext *gb = &slice->gb; + enum dirac_subband orientation; + int level, quant, chroma_bits, chroma_end; + + int quant_base = get_bits(gb, 7); /*[DIRAC_STD] qindex */ + int length_bits = av_log2(8 * slice->bytes)+1; + int luma_bits = get_bits_long(gb, length_bits); + int luma_end = get_bits_count(gb) + FFMIN(luma_bits, get_bits_left(gb)); + + /* [DIRAC_STD] 13.5.5.2 luma_slice_band */ + for (level = 0; level < s->wavelet_depth; level++) + for (orientation = !!level; orientation < 4; orientation++) { + quant = FFMAX(quant_base - s->lowdelay.quant[level][orientation], 0); + lowdelay_subband(s, gb, quant, slice->slice_x, slice->slice_y, luma_end, + &s->plane[0].band[level][orientation], NULL); + } + + /* consume any unused bits from luma */ + skip_bits_long(gb, get_bits_count(gb) - luma_end); + + chroma_bits = 8*slice->bytes - 7 - length_bits - luma_bits; + chroma_end = get_bits_count(gb) + FFMIN(chroma_bits, get_bits_left(gb)); + /* [DIRAC_STD] 13.5.5.3 chroma_slice_band */ + for (level = 0; level < s->wavelet_depth; level++) + for (orientation = !!level; orientation < 4; orientation++) { + quant = FFMAX(quant_base - s->lowdelay.quant[level][orientation], 0); + lowdelay_subband(s, gb, quant, slice->slice_x, slice->slice_y, chroma_end, + &s->plane[1].band[level][orientation], + &s->plane[2].band[level][orientation]); + } + + return 0; +} + +/** + * Dirac Specification -> + * 13.5.1 low_delay_transform_data() + */ +static void decode_lowdelay(DiracContext *s) +{ + AVCodecContext *avctx = s->avctx; + int slice_x, slice_y, bytes, bufsize; + const uint8_t *buf; + struct lowdelay_slice *slices; + int slice_num = 0; + + slices = av_mallocz(s->lowdelay.num_x * s->lowdelay.num_y * sizeof(struct lowdelay_slice)); + + align_get_bits(&s->gb); + /*[DIRAC_STD] 13.5.2 Slices. slice(sx,sy) */ + buf = s->gb.buffer + get_bits_count(&s->gb)/8; + bufsize = get_bits_left(&s->gb); + + for (slice_y = 0; bufsize > 0 && slice_y < s->lowdelay.num_y; slice_y++) + for (slice_x = 0; bufsize > 0 && slice_x < s->lowdelay.num_x; slice_x++) { + bytes = (slice_num+1) * s->lowdelay.bytes.num / s->lowdelay.bytes.den + - slice_num * s->lowdelay.bytes.num / s->lowdelay.bytes.den; + + slices[slice_num].bytes = bytes; + slices[slice_num].slice_x = slice_x; + slices[slice_num].slice_y = slice_y; + init_get_bits(&slices[slice_num].gb, buf, bufsize); + slice_num++; + + buf += bytes; + bufsize -= bytes*8; + } + + avctx->execute(avctx, decode_lowdelay_slice, slices, NULL, slice_num, + sizeof(struct lowdelay_slice)); /* [DIRAC_STD] 13.5.2 Slices */ + intra_dc_prediction(&s->plane[0].band[0][0]); /* [DIRAC_STD] 13.3 intra_dc_prediction() */ + intra_dc_prediction(&s->plane[1].band[0][0]); /* [DIRAC_STD] 13.3 intra_dc_prediction() */ + intra_dc_prediction(&s->plane[2].band[0][0]); /* [DIRAC_STD] 13.3 intra_dc_prediction() */ + av_free(slices); +} + +static void init_planes(DiracContext *s) +{ + int i, w, h, level, orientation; + + for (i = 0; i < 3; i++) { + Plane *p = &s->plane[i]; + + p->width = s->source.width >> (i ? s->chroma_x_shift : 0); + p->height = s->source.height >> (i ? s->chroma_y_shift : 0); + p->idwt_width = w = CALC_PADDING(p->width , s->wavelet_depth); + p->idwt_height = h = CALC_PADDING(p->height, s->wavelet_depth); + p->idwt_stride = FFALIGN(p->idwt_width, 8); + + for (level = s->wavelet_depth-1; level >= 0; level--) { + w = w>>1; + h = h>>1; + for (orientation = !!level; orientation < 4; orientation++) { + SubBand *b = &p->band[level][orientation]; + + b->ibuf = p->idwt_buf; + b->level = level; + b->stride = p->idwt_stride << (s->wavelet_depth - level); + b->width = w; + b->height = h; + b->orientation = orientation; + + if (orientation & 1) + b->ibuf += w; + if (orientation > 1) + b->ibuf += b->stride>>1; + + if (level) + b->parent = &p->band[level-1][orientation]; + } + } + + if (i > 0) { + p->xblen = s->plane[0].xblen >> s->chroma_x_shift; + p->yblen = s->plane[0].yblen >> s->chroma_y_shift; + p->xbsep = s->plane[0].xbsep >> s->chroma_x_shift; + p->ybsep = s->plane[0].ybsep >> s->chroma_y_shift; + } + + p->xoffset = (p->xblen - p->xbsep)/2; + p->yoffset = (p->yblen - p->ybsep)/2; + } +} + +/** + * Unpack the motion compensation parameters + * Dirac Specification -> + * 11.2 Picture prediction data. picture_prediction() + */ +static int dirac_unpack_prediction_parameters(DiracContext *s) +{ + static const uint8_t default_blen[] = { 4, 12, 16, 24 }; + static const uint8_t default_bsep[] = { 4, 8, 12, 16 }; + + GetBitContext *gb = &s->gb; + unsigned idx, ref; + + align_get_bits(gb); + /* [DIRAC_STD] 11.2.2 Block parameters. block_parameters() */ + /* Luma and Chroma are equal. 11.2.3 */ + idx = svq3_get_ue_golomb(gb); /* [DIRAC_STD] index */ + + if (idx > 4) { + av_log(s->avctx, AV_LOG_ERROR, "Block prediction index too high\n"); + return -1; + } + + if (idx == 0) { + s->plane[0].xblen = svq3_get_ue_golomb(gb); + s->plane[0].yblen = svq3_get_ue_golomb(gb); + s->plane[0].xbsep = svq3_get_ue_golomb(gb); + s->plane[0].ybsep = svq3_get_ue_golomb(gb); + } else { + /*[DIRAC_STD] preset_block_params(index). Table 11.1 */ + s->plane[0].xblen = default_blen[idx-1]; + s->plane[0].yblen = default_blen[idx-1]; + s->plane[0].xbsep = default_bsep[idx-1]; + s->plane[0].ybsep = default_bsep[idx-1]; + } + /*[DIRAC_STD] 11.2.4 motion_data_dimensions() + Calculated in function dirac_unpack_block_motion_data */ + + if (!s->plane[0].xbsep || !s->plane[0].ybsep || s->plane[0].xbsep < s->plane[0].xblen/2 || s->plane[0].ybsep < s->plane[0].yblen/2) { + av_log(s->avctx, AV_LOG_ERROR, "Block separation too small\n"); + return -1; + } + if (s->plane[0].xbsep > s->plane[0].xblen || s->plane[0].ybsep > s->plane[0].yblen) { + av_log(s->avctx, AV_LOG_ERROR, "Block separation greater than size\n"); + return -1; + } + if (FFMAX(s->plane[0].xblen, s->plane[0].yblen) > MAX_BLOCKSIZE) { + av_log(s->avctx, AV_LOG_ERROR, "Unsupported large block size\n"); + return -1; + } + + /*[DIRAC_STD] 11.2.5 Motion vector precision. motion_vector_precision() + Read motion vector precision */ + s->mv_precision = svq3_get_ue_golomb(gb); + if (s->mv_precision > 3) { + av_log(s->avctx, AV_LOG_ERROR, "MV precision finer than eighth-pel\n"); + return -1; + } + + /*[DIRAC_STD] 11.2.6 Global motion. global_motion() + Read the global motion compensation parameters */ + s->globalmc_flag = get_bits1(gb); + if (s->globalmc_flag) { + memset(s->globalmc, 0, sizeof(s->globalmc)); + /* [DIRAC_STD] pan_tilt(gparams) */ + for (ref = 0; ref < s->num_refs; ref++) { + if (get_bits1(gb)) { + s->globalmc[ref].pan_tilt[0] = dirac_get_se_golomb(gb); + s->globalmc[ref].pan_tilt[1] = dirac_get_se_golomb(gb); + } + /* [DIRAC_STD] zoom_rotate_shear(gparams) + zoom/rotation/shear parameters */ + if (get_bits1(gb)) { + s->globalmc[ref].zrs_exp = svq3_get_ue_golomb(gb); + s->globalmc[ref].zrs[0][0] = dirac_get_se_golomb(gb); + s->globalmc[ref].zrs[0][1] = dirac_get_se_golomb(gb); + s->globalmc[ref].zrs[1][0] = dirac_get_se_golomb(gb); + s->globalmc[ref].zrs[1][1] = dirac_get_se_golomb(gb); + } else { + s->globalmc[ref].zrs[0][0] = 1; + s->globalmc[ref].zrs[1][1] = 1; + } + /* [DIRAC_STD] perspective(gparams) */ + if (get_bits1(gb)) { + s->globalmc[ref].perspective_exp = svq3_get_ue_golomb(gb); + s->globalmc[ref].perspective[0] = dirac_get_se_golomb(gb); + s->globalmc[ref].perspective[1] = dirac_get_se_golomb(gb); + } + } + } + + /*[DIRAC_STD] 11.2.7 Picture prediction mode. prediction_mode() + Picture prediction mode, not currently used. */ + if (svq3_get_ue_golomb(gb)) { + av_log(s->avctx, AV_LOG_ERROR, "Unknown picture prediction mode\n"); + return -1; + } + + /* [DIRAC_STD] 11.2.8 Reference picture weight. reference_picture_weights() + just data read, weight calculation will be done later on. */ + s->weight_log2denom = 1; + s->weight[0] = 1; + s->weight[1] = 1; + + if (get_bits1(gb)) { + s->weight_log2denom = svq3_get_ue_golomb(gb); + s->weight[0] = dirac_get_se_golomb(gb); + if (s->num_refs == 2) + s->weight[1] = dirac_get_se_golomb(gb); + } + return 0; +} + +/** + * Dirac Specification -> + * 11.3 Wavelet transform data. wavelet_transform() + */ +static int dirac_unpack_idwt_params(DiracContext *s) +{ + GetBitContext *gb = &s->gb; + int i, level; + unsigned tmp; + +#define CHECKEDREAD(dst, cond, errmsg) \ + tmp = svq3_get_ue_golomb(gb); \ + if (cond) { \ + av_log(s->avctx, AV_LOG_ERROR, errmsg); \ + return -1; \ + }\ + dst = tmp; + + align_get_bits(gb); + + s->zero_res = s->num_refs ? get_bits1(gb) : 0; + if (s->zero_res) + return 0; + + /*[DIRAC_STD] 11.3.1 Transform parameters. transform_parameters() */ + CHECKEDREAD(s->wavelet_idx, tmp > 6, "wavelet_idx is too big\n") + + CHECKEDREAD(s->wavelet_depth, tmp > MAX_DWT_LEVELS || tmp < 1, "invalid number of DWT decompositions\n") + + if (!s->low_delay) { + /* Codeblock parameters (core syntax only) */ + if (get_bits1(gb)) { + for (i = 0; i <= s->wavelet_depth; i++) { + CHECKEDREAD(s->codeblock[i].width , tmp < 1, "codeblock width invalid\n") + CHECKEDREAD(s->codeblock[i].height, tmp < 1, "codeblock height invalid\n") + } + + CHECKEDREAD(s->codeblock_mode, tmp > 1, "unknown codeblock mode\n") + } else + for (i = 0; i <= s->wavelet_depth; i++) + s->codeblock[i].width = s->codeblock[i].height = 1; + } else { + /* Slice parameters + quantization matrix*/ + /*[DIRAC_STD] 11.3.4 Slice coding Parameters (low delay syntax only). slice_parameters() */ + s->lowdelay.num_x = svq3_get_ue_golomb(gb); + s->lowdelay.num_y = svq3_get_ue_golomb(gb); + s->lowdelay.bytes.num = svq3_get_ue_golomb(gb); + s->lowdelay.bytes.den = svq3_get_ue_golomb(gb); + + if (s->lowdelay.bytes.den <= 0) { + av_log(s->avctx,AV_LOG_ERROR,"Invalid lowdelay.bytes.den\n"); + return AVERROR_INVALIDDATA; + } + + /* [DIRAC_STD] 11.3.5 Quantisation matrices (low-delay syntax). quant_matrix() */ + if (get_bits1(gb)) { + av_log(s->avctx,AV_LOG_DEBUG,"Low Delay: Has Custom Quantization Matrix!\n"); + /* custom quantization matrix */ + s->lowdelay.quant[0][0] = svq3_get_ue_golomb(gb); + for (level = 0; level < s->wavelet_depth; level++) { + s->lowdelay.quant[level][1] = svq3_get_ue_golomb(gb); + s->lowdelay.quant[level][2] = svq3_get_ue_golomb(gb); + s->lowdelay.quant[level][3] = svq3_get_ue_golomb(gb); + } + } else { + if (s->wavelet_depth > 4) { + av_log(s->avctx,AV_LOG_ERROR,"Mandatory custom low delay matrix missing for depth %d\n", s->wavelet_depth); + return AVERROR_INVALIDDATA; + } + /* default quantization matrix */ + for (level = 0; level < s->wavelet_depth; level++) + for (i = 0; i < 4; i++) { + s->lowdelay.quant[level][i] = default_qmat[s->wavelet_idx][level][i]; + /* haar with no shift differs for different depths */ + if (s->wavelet_idx == 3) + s->lowdelay.quant[level][i] += 4*(s->wavelet_depth-1 - level); + } + } + } + return 0; +} + +static inline int pred_sbsplit(uint8_t *sbsplit, int stride, int x, int y) +{ + static const uint8_t avgsplit[7] = { 0, 0, 1, 1, 1, 2, 2 }; + + if (!(x|y)) + return 0; + else if (!y) + return sbsplit[-1]; + else if (!x) + return sbsplit[-stride]; + + return avgsplit[sbsplit[-1] + sbsplit[-stride] + sbsplit[-stride-1]]; +} + +static inline int pred_block_mode(DiracBlock *block, int stride, int x, int y, int refmask) +{ + int pred; + + if (!(x|y)) + return 0; + else if (!y) + return block[-1].ref & refmask; + else if (!x) + return block[-stride].ref & refmask; + + /* return the majority */ + pred = (block[-1].ref & refmask) + (block[-stride].ref & refmask) + (block[-stride-1].ref & refmask); + return (pred >> 1) & refmask; +} + +static inline void pred_block_dc(DiracBlock *block, int stride, int x, int y) +{ + int i, n = 0; + + memset(block->u.dc, 0, sizeof(block->u.dc)); + + if (x && !(block[-1].ref & 3)) { + for (i = 0; i < 3; i++) + block->u.dc[i] += block[-1].u.dc[i]; + n++; + } + + if (y && !(block[-stride].ref & 3)) { + for (i = 0; i < 3; i++) + block->u.dc[i] += block[-stride].u.dc[i]; + n++; + } + + if (x && y && !(block[-1-stride].ref & 3)) { + for (i = 0; i < 3; i++) + block->u.dc[i] += block[-1-stride].u.dc[i]; + n++; + } + + if (n == 2) { + for (i = 0; i < 3; i++) + block->u.dc[i] = (block->u.dc[i]+1)>>1; + } else if (n == 3) { + for (i = 0; i < 3; i++) + block->u.dc[i] = divide3(block->u.dc[i]); + } +} + +static inline void pred_mv(DiracBlock *block, int stride, int x, int y, int ref) +{ + int16_t *pred[3]; + int refmask = ref+1; + int mask = refmask | DIRAC_REF_MASK_GLOBAL; /* exclude gmc blocks */ + int n = 0; + + if (x && (block[-1].ref & mask) == refmask) + pred[n++] = block[-1].u.mv[ref]; + + if (y && (block[-stride].ref & mask) == refmask) + pred[n++] = block[-stride].u.mv[ref]; + + if (x && y && (block[-stride-1].ref & mask) == refmask) + pred[n++] = block[-stride-1].u.mv[ref]; + + switch (n) { + case 0: + block->u.mv[ref][0] = 0; + block->u.mv[ref][1] = 0; + break; + case 1: + block->u.mv[ref][0] = pred[0][0]; + block->u.mv[ref][1] = pred[0][1]; + break; + case 2: + block->u.mv[ref][0] = (pred[0][0] + pred[1][0] + 1) >> 1; + block->u.mv[ref][1] = (pred[0][1] + pred[1][1] + 1) >> 1; + break; + case 3: + block->u.mv[ref][0] = mid_pred(pred[0][0], pred[1][0], pred[2][0]); + block->u.mv[ref][1] = mid_pred(pred[0][1], pred[1][1], pred[2][1]); + break; + } +} + +static void global_mv(DiracContext *s, DiracBlock *block, int x, int y, int ref) +{ + int ez = s->globalmc[ref].zrs_exp; + int ep = s->globalmc[ref].perspective_exp; + int (*A)[2] = s->globalmc[ref].zrs; + int *b = s->globalmc[ref].pan_tilt; + int *c = s->globalmc[ref].perspective; + + int m = (1<u.mv[ref][0] = (mx + (1<<(ez+ep))) >> (ez+ep); + block->u.mv[ref][1] = (my + (1<<(ez+ep))) >> (ez+ep); +} + +static void decode_block_params(DiracContext *s, DiracArith arith[8], DiracBlock *block, + int stride, int x, int y) +{ + int i; + + block->ref = pred_block_mode(block, stride, x, y, DIRAC_REF_MASK_REF1); + block->ref ^= dirac_get_arith_bit(arith, CTX_PMODE_REF1); + + if (s->num_refs == 2) { + block->ref |= pred_block_mode(block, stride, x, y, DIRAC_REF_MASK_REF2); + block->ref ^= dirac_get_arith_bit(arith, CTX_PMODE_REF2) << 1; + } + + if (!block->ref) { + pred_block_dc(block, stride, x, y); + for (i = 0; i < 3; i++) + block->u.dc[i] += dirac_get_arith_int(arith+1+i, CTX_DC_F1, CTX_DC_DATA); + return; + } + + if (s->globalmc_flag) { + block->ref |= pred_block_mode(block, stride, x, y, DIRAC_REF_MASK_GLOBAL); + block->ref ^= dirac_get_arith_bit(arith, CTX_GLOBAL_BLOCK) << 2; + } + + for (i = 0; i < s->num_refs; i++) + if (block->ref & (i+1)) { + if (block->ref & DIRAC_REF_MASK_GLOBAL) { + global_mv(s, block, x, y, i); + } else { + pred_mv(block, stride, x, y, i); + block->u.mv[i][0] += dirac_get_arith_int(arith + 4 + 2 * i, CTX_MV_F1, CTX_MV_DATA); + block->u.mv[i][1] += dirac_get_arith_int(arith + 5 + 2 * i, CTX_MV_F1, CTX_MV_DATA); + } + } +} + +/** + * Copies the current block to the other blocks covered by the current superblock split mode + */ +static void propagate_block_data(DiracBlock *block, int stride, int size) +{ + int x, y; + DiracBlock *dst = block; + + for (x = 1; x < size; x++) + dst[x] = *block; + + for (y = 1; y < size; y++) { + dst += stride; + for (x = 0; x < size; x++) + dst[x] = *block; + } +} + +/** + * Dirac Specification -> + * 12. Block motion data syntax + */ +static int dirac_unpack_block_motion_data(DiracContext *s) +{ + GetBitContext *gb = &s->gb; + uint8_t *sbsplit = s->sbsplit; + int i, x, y, q, p; + DiracArith arith[8]; + + align_get_bits(gb); + + /* [DIRAC_STD] 11.2.4 and 12.2.1 Number of blocks and superblocks */ + s->sbwidth = DIVRNDUP(s->source.width, 4*s->plane[0].xbsep); + s->sbheight = DIVRNDUP(s->source.height, 4*s->plane[0].ybsep); + s->blwidth = 4 * s->sbwidth; + s->blheight = 4 * s->sbheight; + + /* [DIRAC_STD] 12.3.1 Superblock splitting modes. superblock_split_modes() + decode superblock split modes */ + ff_dirac_init_arith_decoder(arith, gb, svq3_get_ue_golomb(gb)); /* svq3_get_ue_golomb(gb) is the length */ + for (y = 0; y < s->sbheight; y++) { + for (x = 0; x < s->sbwidth; x++) { + unsigned int split = dirac_get_arith_uint(arith, CTX_SB_F1, CTX_SB_DATA); + if (split > 2) + return -1; + sbsplit[x] = (split + pred_sbsplit(sbsplit+x, s->sbwidth, x, y)) % 3; + } + sbsplit += s->sbwidth; + } + + /* setup arith decoding */ + ff_dirac_init_arith_decoder(arith, gb, svq3_get_ue_golomb(gb)); + for (i = 0; i < s->num_refs; i++) { + ff_dirac_init_arith_decoder(arith + 4 + 2 * i, gb, svq3_get_ue_golomb(gb)); + ff_dirac_init_arith_decoder(arith + 5 + 2 * i, gb, svq3_get_ue_golomb(gb)); + } + for (i = 0; i < 3; i++) + ff_dirac_init_arith_decoder(arith+1+i, gb, svq3_get_ue_golomb(gb)); + + for (y = 0; y < s->sbheight; y++) + for (x = 0; x < s->sbwidth; x++) { + int blkcnt = 1 << s->sbsplit[y * s->sbwidth + x]; + int step = 4 >> s->sbsplit[y * s->sbwidth + x]; + + for (q = 0; q < blkcnt; q++) + for (p = 0; p < blkcnt; p++) { + int bx = 4 * x + p*step; + int by = 4 * y + q*step; + DiracBlock *block = &s->blmotion[by*s->blwidth + bx]; + decode_block_params(s, arith, block, s->blwidth, bx, by); + propagate_block_data(block, s->blwidth, step); + } + } + + return 0; +} + +static int weight(int i, int blen, int offset) +{ +#define ROLLOFF(i) offset == 1 ? ((i) ? 5 : 3) : \ + (1 + (6*(i) + offset - 1) / (2*offset - 1)) + + if (i < 2*offset) + return ROLLOFF(i); + else if (i > blen-1 - 2*offset) + return ROLLOFF(blen-1 - i); + return 8; +} + +static void init_obmc_weight_row(Plane *p, uint8_t *obmc_weight, int stride, + int left, int right, int wy) +{ + int x; + for (x = 0; left && x < p->xblen >> 1; x++) + obmc_weight[x] = wy*8; + for (; x < p->xblen >> right; x++) + obmc_weight[x] = wy*weight(x, p->xblen, p->xoffset); + for (; x < p->xblen; x++) + obmc_weight[x] = wy*8; + for (; x < stride; x++) + obmc_weight[x] = 0; +} + +static void init_obmc_weight(Plane *p, uint8_t *obmc_weight, int stride, + int left, int right, int top, int bottom) +{ + int y; + for (y = 0; top && y < p->yblen >> 1; y++) { + init_obmc_weight_row(p, obmc_weight, stride, left, right, 8); + obmc_weight += stride; + } + for (; y < p->yblen >> bottom; y++) { + int wy = weight(y, p->yblen, p->yoffset); + init_obmc_weight_row(p, obmc_weight, stride, left, right, wy); + obmc_weight += stride; + } + for (; y < p->yblen; y++) { + init_obmc_weight_row(p, obmc_weight, stride, left, right, 8); + obmc_weight += stride; + } +} + +static void init_obmc_weights(DiracContext *s, Plane *p, int by) +{ + int top = !by; + int bottom = by == s->blheight-1; + + /* don't bother re-initing for rows 2 to blheight-2, the weights don't change */ + if (top || bottom || by == 1) { + init_obmc_weight(p, s->obmc_weight[0], MAX_BLOCKSIZE, 1, 0, top, bottom); + init_obmc_weight(p, s->obmc_weight[1], MAX_BLOCKSIZE, 0, 0, top, bottom); + init_obmc_weight(p, s->obmc_weight[2], MAX_BLOCKSIZE, 0, 1, top, bottom); + } +} + +static const uint8_t epel_weights[4][4][4] = { + {{ 16, 0, 0, 0 }, + { 12, 4, 0, 0 }, + { 8, 8, 0, 0 }, + { 4, 12, 0, 0 }}, + {{ 12, 0, 4, 0 }, + { 9, 3, 3, 1 }, + { 6, 6, 2, 2 }, + { 3, 9, 1, 3 }}, + {{ 8, 0, 8, 0 }, + { 6, 2, 6, 2 }, + { 4, 4, 4, 4 }, + { 2, 6, 2, 6 }}, + {{ 4, 0, 12, 0 }, + { 3, 1, 9, 3 }, + { 2, 2, 6, 6 }, + { 1, 3, 3, 9 }} +}; + +/** + * For block x,y, determine which of the hpel planes to do bilinear + * interpolation from and set src[] to the location in each hpel plane + * to MC from. + * + * @return the index of the put_dirac_pixels_tab function to use + * 0 for 1 plane (fpel,hpel), 1 for 2 planes (qpel), 2 for 4 planes (qpel), and 3 for epel + */ +static int mc_subpel(DiracContext *s, DiracBlock *block, const uint8_t *src[5], + int x, int y, int ref, int plane) +{ + Plane *p = &s->plane[plane]; + uint8_t **ref_hpel = s->ref_pics[ref]->hpel[plane]; + int motion_x = block->u.mv[ref][0]; + int motion_y = block->u.mv[ref][1]; + int mx, my, i, epel, nplanes = 0; + + if (plane) { + motion_x >>= s->chroma_x_shift; + motion_y >>= s->chroma_y_shift; + } + + mx = motion_x & ~(-1 << s->mv_precision); + my = motion_y & ~(-1 << s->mv_precision); + motion_x >>= s->mv_precision; + motion_y >>= s->mv_precision; + /* normalize subpel coordinates to epel */ + /* TODO: template this function? */ + mx <<= 3 - s->mv_precision; + my <<= 3 - s->mv_precision; + + x += motion_x; + y += motion_y; + epel = (mx|my)&1; + + /* hpel position */ + if (!((mx|my)&3)) { + nplanes = 1; + src[0] = ref_hpel[(my>>1)+(mx>>2)] + y*p->stride + x; + } else { + /* qpel or epel */ + nplanes = 4; + for (i = 0; i < 4; i++) + src[i] = ref_hpel[i] + y*p->stride + x; + + /* if we're interpolating in the right/bottom halves, adjust the planes as needed + we increment x/y because the edge changes for half of the pixels */ + if (mx > 4) { + src[0] += 1; + src[2] += 1; + x++; + } + if (my > 4) { + src[0] += p->stride; + src[1] += p->stride; + y++; + } + + /* hpel planes are: + [0]: F [1]: H + [2]: V [3]: C */ + if (!epel) { + /* check if we really only need 2 planes since either mx or my is + a hpel position. (epel weights of 0 handle this there) */ + if (!(mx&3)) { + /* mx == 0: average [0] and [2] + mx == 4: average [1] and [3] */ + src[!mx] = src[2 + !!mx]; + nplanes = 2; + } else if (!(my&3)) { + src[0] = src[(my>>1) ]; + src[1] = src[(my>>1)+1]; + nplanes = 2; + } + } else { + /* adjust the ordering if needed so the weights work */ + if (mx > 4) { + FFSWAP(const uint8_t *, src[0], src[1]); + FFSWAP(const uint8_t *, src[2], src[3]); + } + if (my > 4) { + FFSWAP(const uint8_t *, src[0], src[2]); + FFSWAP(const uint8_t *, src[1], src[3]); + } + src[4] = epel_weights[my&3][mx&3]; + } + } + + /* fixme: v/h _edge_pos */ + if (x + p->xblen > p->width +EDGE_WIDTH/2 || + y + p->yblen > p->height+EDGE_WIDTH/2 || + x < 0 || y < 0) { + for (i = 0; i < nplanes; i++) { + ff_emulated_edge_mc(s->edge_emu_buffer[i], src[i], p->stride, + p->xblen, p->yblen, x, y, + p->width+EDGE_WIDTH/2, p->height+EDGE_WIDTH/2); + src[i] = s->edge_emu_buffer[i]; + } + } + return (nplanes>>1) + epel; +} + +static void add_dc(uint16_t *dst, int dc, int stride, + uint8_t *obmc_weight, int xblen, int yblen) +{ + int x, y; + dc += 128; + + for (y = 0; y < yblen; y++) { + for (x = 0; x < xblen; x += 2) { + dst[x ] += dc * obmc_weight[x ]; + dst[x+1] += dc * obmc_weight[x+1]; + } + dst += stride; + obmc_weight += MAX_BLOCKSIZE; + } +} + +static void block_mc(DiracContext *s, DiracBlock *block, + uint16_t *mctmp, uint8_t *obmc_weight, + int plane, int dstx, int dsty) +{ + Plane *p = &s->plane[plane]; + const uint8_t *src[5]; + int idx; + + switch (block->ref&3) { + case 0: /* DC */ + add_dc(mctmp, block->u.dc[plane], p->stride, obmc_weight, p->xblen, p->yblen); + return; + case 1: + case 2: + idx = mc_subpel(s, block, src, dstx, dsty, (block->ref&3)-1, plane); + s->put_pixels_tab[idx](s->mcscratch, src, p->stride, p->yblen); + if (s->weight_func) + s->weight_func(s->mcscratch, p->stride, s->weight_log2denom, + s->weight[0] + s->weight[1], p->yblen); + break; + case 3: + idx = mc_subpel(s, block, src, dstx, dsty, 0, plane); + s->put_pixels_tab[idx](s->mcscratch, src, p->stride, p->yblen); + idx = mc_subpel(s, block, src, dstx, dsty, 1, plane); + if (s->biweight_func) { + /* fixme: +32 is a quick hack */ + s->put_pixels_tab[idx](s->mcscratch + 32, src, p->stride, p->yblen); + s->biweight_func(s->mcscratch, s->mcscratch+32, p->stride, s->weight_log2denom, + s->weight[0], s->weight[1], p->yblen); + } else + s->avg_pixels_tab[idx](s->mcscratch, src, p->stride, p->yblen); + break; + } + s->add_obmc(mctmp, s->mcscratch, p->stride, obmc_weight, p->yblen); +} + +static void mc_row(DiracContext *s, DiracBlock *block, uint16_t *mctmp, int plane, int dsty) +{ + Plane *p = &s->plane[plane]; + int x, dstx = p->xbsep - p->xoffset; + + block_mc(s, block, mctmp, s->obmc_weight[0], plane, -p->xoffset, dsty); + mctmp += p->xbsep; + + for (x = 1; x < s->blwidth-1; x++) { + block_mc(s, block+x, mctmp, s->obmc_weight[1], plane, dstx, dsty); + dstx += p->xbsep; + mctmp += p->xbsep; + } + block_mc(s, block+x, mctmp, s->obmc_weight[2], plane, dstx, dsty); +} + +static void select_dsp_funcs(DiracContext *s, int width, int height, int xblen, int yblen) +{ + int idx = 0; + if (xblen > 8) + idx = 1; + if (xblen > 16) + idx = 2; + + memcpy(s->put_pixels_tab, s->diracdsp.put_dirac_pixels_tab[idx], sizeof(s->put_pixels_tab)); + memcpy(s->avg_pixels_tab, s->diracdsp.avg_dirac_pixels_tab[idx], sizeof(s->avg_pixels_tab)); + s->add_obmc = s->diracdsp.add_dirac_obmc[idx]; + if (s->weight_log2denom > 1 || s->weight[0] != 1 || s->weight[1] != 1) { + s->weight_func = s->diracdsp.weight_dirac_pixels_tab[idx]; + s->biweight_func = s->diracdsp.biweight_dirac_pixels_tab[idx]; + } else { + s->weight_func = NULL; + s->biweight_func = NULL; + } +} + +static void interpolate_refplane(DiracContext *s, DiracFrame *ref, int plane, int width, int height) +{ + /* chroma allocates an edge of 8 when subsampled + which for 4:2:2 means an h edge of 16 and v edge of 8 + just use 8 for everything for the moment */ + int i, edge = EDGE_WIDTH/2; + + ref->hpel[plane][0] = ref->avframe.data[plane]; + s->dsp.draw_edges(ref->hpel[plane][0], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); /* EDGE_TOP | EDGE_BOTTOM values just copied to make it build, this needs to be ensured */ + + /* no need for hpel if we only have fpel vectors */ + if (!s->mv_precision) + return; + + for (i = 1; i < 4; i++) { + if (!ref->hpel_base[plane][i]) + ref->hpel_base[plane][i] = av_malloc((height+2*edge) * ref->avframe.linesize[plane] + 32); + /* we need to be 16-byte aligned even for chroma */ + ref->hpel[plane][i] = ref->hpel_base[plane][i] + edge*ref->avframe.linesize[plane] + 16; + } + + if (!ref->interpolated[plane]) { + s->diracdsp.dirac_hpel_filter(ref->hpel[plane][1], ref->hpel[plane][2], + ref->hpel[plane][3], ref->hpel[plane][0], + ref->avframe.linesize[plane], width, height); + s->dsp.draw_edges(ref->hpel[plane][1], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(ref->hpel[plane][2], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(ref->hpel[plane][3], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); + } + ref->interpolated[plane] = 1; +} + +/** + * Dirac Specification -> + * 13.0 Transform data syntax. transform_data() + */ +static int dirac_decode_frame_internal(DiracContext *s) +{ + DWTContext d; + int y, i, comp, dsty; + + if (s->low_delay) { + /* [DIRAC_STD] 13.5.1 low_delay_transform_data() */ + for (comp = 0; comp < 3; comp++) { + Plane *p = &s->plane[comp]; + memset(p->idwt_buf, 0, p->idwt_stride * p->idwt_height * sizeof(IDWTELEM)); + } + if (!s->zero_res) + decode_lowdelay(s); + } + + for (comp = 0; comp < 3; comp++) { + Plane *p = &s->plane[comp]; + uint8_t *frame = s->current_picture->avframe.data[comp]; + + /* FIXME: small resolutions */ + for (i = 0; i < 4; i++) + s->edge_emu_buffer[i] = s->edge_emu_buffer_base + i*FFALIGN(p->width, 16); + + if (!s->zero_res && !s->low_delay) + { + memset(p->idwt_buf, 0, p->idwt_stride * p->idwt_height * sizeof(IDWTELEM)); + decode_component(s, comp); /* [DIRAC_STD] 13.4.1 core_transform_data() */ + } + if (ff_spatial_idwt_init2(&d, p->idwt_buf, p->idwt_width, p->idwt_height, p->idwt_stride, + s->wavelet_idx+2, s->wavelet_depth, p->idwt_tmp)) + return -1; + + if (!s->num_refs) { /* intra */ + for (y = 0; y < p->height; y += 16) { + ff_spatial_idwt_slice2(&d, y+16); /* decode */ + s->diracdsp.put_signed_rect_clamped(frame + y*p->stride, p->stride, + p->idwt_buf + y*p->idwt_stride, p->idwt_stride, p->width, 16); + } + } else { /* inter */ + int rowheight = p->ybsep*p->stride; + + select_dsp_funcs(s, p->width, p->height, p->xblen, p->yblen); + + for (i = 0; i < s->num_refs; i++) + interpolate_refplane(s, s->ref_pics[i], comp, p->width, p->height); + + memset(s->mctmp, 0, 4*p->yoffset*p->stride); + + dsty = -p->yoffset; + for (y = 0; y < s->blheight; y++) { + int h = 0, + start = FFMAX(dsty, 0); + uint16_t *mctmp = s->mctmp + y*rowheight; + DiracBlock *blocks = s->blmotion + y*s->blwidth; + + init_obmc_weights(s, p, y); + + if (y == s->blheight-1 || start+p->ybsep > p->height) + h = p->height - start; + else + h = p->ybsep - (start - dsty); + if (h < 0) + break; + + memset(mctmp+2*p->yoffset*p->stride, 0, 2*rowheight); + mc_row(s, blocks, mctmp, comp, dsty); + + mctmp += (start - dsty)*p->stride + p->xoffset; + ff_spatial_idwt_slice2(&d, start + h); /* decode */ + s->diracdsp.add_rect_clamped(frame + start*p->stride, mctmp, p->stride, + p->idwt_buf + start*p->idwt_stride, p->idwt_stride, p->width, h); + + dsty += p->ybsep; + } + } + } + + + return 0; +} + +/** + * Dirac Specification -> + * 11.1.1 Picture Header. picture_header() + */ +static int dirac_decode_picture_header(DiracContext *s) +{ + int retire, picnum; + int i, j, refnum, refdist; + GetBitContext *gb = &s->gb; + + /* [DIRAC_STD] 11.1.1 Picture Header. picture_header() PICTURE_NUM */ + picnum = s->current_picture->avframe.display_picture_number = get_bits_long(gb, 32); + + + av_log(s->avctx,AV_LOG_DEBUG,"PICTURE_NUM: %d\n",picnum); + + /* if this is the first keyframe after a sequence header, start our + reordering from here */ + if (s->frame_number < 0) + s->frame_number = picnum; + + s->ref_pics[0] = s->ref_pics[1] = NULL; + for (i = 0; i < s->num_refs; i++) { + refnum = picnum + dirac_get_se_golomb(gb); + refdist = INT_MAX; + + /* find the closest reference to the one we want */ + /* Jordi: this is needed if the referenced picture hasn't yet arrived */ + for (j = 0; j < MAX_REFERENCE_FRAMES && refdist; j++) + if (s->ref_frames[j] + && FFABS(s->ref_frames[j]->avframe.display_picture_number - refnum) < refdist) { + s->ref_pics[i] = s->ref_frames[j]; + refdist = FFABS(s->ref_frames[j]->avframe.display_picture_number - refnum); + } + + if (!s->ref_pics[i] || refdist) + av_log(s->avctx, AV_LOG_DEBUG, "Reference not found\n"); + + /* if there were no references at all, allocate one */ + if (!s->ref_pics[i]) + for (j = 0; j < MAX_FRAMES; j++) + if (!s->all_frames[j].avframe.data[0]) { + s->ref_pics[i] = &s->all_frames[j]; + ff_get_buffer(s->avctx, &s->ref_pics[i]->avframe, AV_GET_BUFFER_FLAG_REF); + break; + } + } + + /* retire the reference frames that are not used anymore */ + if (s->current_picture->avframe.reference) { + retire = picnum + dirac_get_se_golomb(gb); + if (retire != picnum) { + DiracFrame *retire_pic = remove_frame(s->ref_frames, retire); + + if (retire_pic) + retire_pic->avframe.reference &= DELAYED_PIC_REF; + else + av_log(s->avctx, AV_LOG_DEBUG, "Frame to retire not found\n"); + } + + /* if reference array is full, remove the oldest as per the spec */ + while (add_frame(s->ref_frames, MAX_REFERENCE_FRAMES, s->current_picture)) { + av_log(s->avctx, AV_LOG_ERROR, "Reference frame overflow\n"); + remove_frame(s->ref_frames, s->ref_frames[0]->avframe.display_picture_number)->avframe.reference &= DELAYED_PIC_REF; + } + } + + if (s->num_refs) { + if (dirac_unpack_prediction_parameters(s)) /* [DIRAC_STD] 11.2 Picture Prediction Data. picture_prediction() */ + return -1; + if (dirac_unpack_block_motion_data(s)) /* [DIRAC_STD] 12. Block motion data syntax */ + return -1; + } + if (dirac_unpack_idwt_params(s)) /* [DIRAC_STD] 11.3 Wavelet transform data */ + return -1; + + init_planes(s); + return 0; +} + +static int get_delayed_pic(DiracContext *s, AVFrame *picture, int *got_frame) +{ + DiracFrame *out = s->delay_frames[0]; + int i, out_idx = 0; + int ret; + + /* find frame with lowest picture number */ + for (i = 1; s->delay_frames[i]; i++) + if (s->delay_frames[i]->avframe.display_picture_number < out->avframe.display_picture_number) { + out = s->delay_frames[i]; + out_idx = i; + } + + for (i = out_idx; s->delay_frames[i]; i++) + s->delay_frames[i] = s->delay_frames[i+1]; + + if (out) { + out->avframe.reference ^= DELAYED_PIC_REF; + *got_frame = 1; + if((ret = av_frame_ref(picture, &out->avframe)) < 0) + return ret; + } + + return 0; +} + +/** + * Dirac Specification -> + * 9.6 Parse Info Header Syntax. parse_info() + * 4 byte start code + byte parse code + 4 byte size + 4 byte previous size + */ +#define DATA_UNIT_HEADER_SIZE 13 + +/* [DIRAC_STD] dirac_decode_data_unit makes reference to the while defined in 9.3 + inside the function parse_sequence() */ +static int dirac_decode_data_unit(AVCodecContext *avctx, const uint8_t *buf, int size) +{ + DiracContext *s = avctx->priv_data; + DiracFrame *pic = NULL; + int ret, i, parse_code = buf[4]; + unsigned tmp; + + if (size < DATA_UNIT_HEADER_SIZE) + return -1; + + init_get_bits(&s->gb, &buf[13], 8*(size - DATA_UNIT_HEADER_SIZE)); + + if (parse_code == pc_seq_header) { + if (s->seen_sequence_header) + return 0; + + /* [DIRAC_STD] 10. Sequence header */ + if (avpriv_dirac_parse_sequence_header(avctx, &s->gb, &s->source)) + return -1; + + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + + if (alloc_sequence_buffers(s)) + return -1; + + s->seen_sequence_header = 1; + } else if (parse_code == pc_eos) { /* [DIRAC_STD] End of Sequence */ + free_sequence_buffers(s); + s->seen_sequence_header = 0; + } else if (parse_code == pc_aux_data) { + if (buf[13] == 1) { /* encoder implementation/version */ + int ver[3]; + /* versions older than 1.0.8 don't store quant delta for + subbands with only one codeblock */ + if (sscanf(buf+14, "Schroedinger %d.%d.%d", ver, ver+1, ver+2) == 3) + if (ver[0] == 1 && ver[1] == 0 && ver[2] <= 7) + s->old_delta_quant = 1; + } + } else if (parse_code & 0x8) { /* picture data unit */ + if (!s->seen_sequence_header) { + av_log(avctx, AV_LOG_DEBUG, "Dropping frame without sequence header\n"); + return -1; + } + + /* find an unused frame */ + for (i = 0; i < MAX_FRAMES; i++) + if (s->all_frames[i].avframe.data[0] == NULL) + pic = &s->all_frames[i]; + if (!pic) { + av_log(avctx, AV_LOG_ERROR, "framelist full\n"); + return -1; + } + + avcodec_get_frame_defaults(&pic->avframe); + + /* [DIRAC_STD] Defined in 9.6.1 ... */ + tmp = parse_code & 0x03; /* [DIRAC_STD] num_refs() */ + if (tmp > 2) { + av_log(avctx, AV_LOG_ERROR, "num_refs of 3\n"); + return -1; + } + s->num_refs = tmp; + s->is_arith = (parse_code & 0x48) == 0x08; /* [DIRAC_STD] using_ac() */ + s->low_delay = (parse_code & 0x88) == 0x88; /* [DIRAC_STD] is_low_delay() */ + pic->avframe.reference = (parse_code & 0x0C) == 0x0C; /* [DIRAC_STD] is_reference() */ + pic->avframe.key_frame = s->num_refs == 0; /* [DIRAC_STD] is_intra() */ + pic->avframe.pict_type = s->num_refs + 1; /* Definition of AVPictureType in avutil.h */ + + if ((ret = ff_get_buffer(avctx, &pic->avframe, (parse_code & 0x0C) == 0x0C ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) + return ret; + s->current_picture = pic; + s->plane[0].stride = pic->avframe.linesize[0]; + s->plane[1].stride = pic->avframe.linesize[1]; + s->plane[2].stride = pic->avframe.linesize[2]; + + /* [DIRAC_STD] 11.1 Picture parse. picture_parse() */ + if (dirac_decode_picture_header(s)) + return -1; + + /* [DIRAC_STD] 13.0 Transform data syntax. transform_data() */ + if (dirac_decode_frame_internal(s)) + return -1; + } + return 0; +} + +static int dirac_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) +{ + DiracContext *s = avctx->priv_data; + DiracFrame *picture = data; + uint8_t *buf = pkt->data; + int buf_size = pkt->size; + int i, data_unit_size, buf_idx = 0; + int ret; + + /* release unused frames */ + for (i = 0; i < MAX_FRAMES; i++) + if (s->all_frames[i].avframe.data[0] && !s->all_frames[i].avframe.reference) { + av_frame_unref(&s->all_frames[i].avframe); + memset(s->all_frames[i].interpolated, 0, sizeof(s->all_frames[i].interpolated)); + } + + s->current_picture = NULL; + *got_frame = 0; + + /* end of stream, so flush delayed pics */ + if (buf_size == 0) + return get_delayed_pic(s, (AVFrame *)data, got_frame); + + for (;;) { + /*[DIRAC_STD] Here starts the code from parse_info() defined in 9.6 + [DIRAC_STD] PARSE_INFO_PREFIX = "BBCD" as defined in ISO/IEC 646 + BBCD start code search */ + for (; buf_idx + DATA_UNIT_HEADER_SIZE < buf_size; buf_idx++) { + if (buf[buf_idx ] == 'B' && buf[buf_idx+1] == 'B' && + buf[buf_idx+2] == 'C' && buf[buf_idx+3] == 'D') + break; + } + /* BBCD found or end of data */ + if (buf_idx + DATA_UNIT_HEADER_SIZE >= buf_size) + break; + + data_unit_size = AV_RB32(buf+buf_idx+5); + if (buf_idx + data_unit_size > buf_size || !data_unit_size) { + if(buf_idx + data_unit_size > buf_size) + av_log(s->avctx, AV_LOG_ERROR, + "Data unit with size %d is larger than input buffer, discarding\n", + data_unit_size); + buf_idx += 4; + continue; + } + /* [DIRAC_STD] dirac_decode_data_unit makes reference to the while defined in 9.3 inside the function parse_sequence() */ + if (dirac_decode_data_unit(avctx, buf+buf_idx, data_unit_size)) + { + av_log(s->avctx, AV_LOG_ERROR,"Error in dirac_decode_data_unit\n"); + return -1; + } + buf_idx += data_unit_size; + } + + if (!s->current_picture) + return buf_size; + + if (s->current_picture->avframe.display_picture_number > s->frame_number) { + DiracFrame *delayed_frame = remove_frame(s->delay_frames, s->frame_number); + + s->current_picture->avframe.reference |= DELAYED_PIC_REF; + + if (add_frame(s->delay_frames, MAX_DELAY, s->current_picture)) { + int min_num = s->delay_frames[0]->avframe.display_picture_number; + /* Too many delayed frames, so we display the frame with the lowest pts */ + av_log(avctx, AV_LOG_ERROR, "Delay frame overflow\n"); + delayed_frame = s->delay_frames[0]; + + for (i = 1; s->delay_frames[i]; i++) + if (s->delay_frames[i]->avframe.display_picture_number < min_num) + min_num = s->delay_frames[i]->avframe.display_picture_number; + + delayed_frame = remove_frame(s->delay_frames, min_num); + add_frame(s->delay_frames, MAX_DELAY, s->current_picture); + } + + if (delayed_frame) { + delayed_frame->avframe.reference ^= DELAYED_PIC_REF; + if((ret=av_frame_ref(data, &delayed_frame->avframe)) < 0) + return ret; + *got_frame = 1; + } + } else if (s->current_picture->avframe.display_picture_number == s->frame_number) { + /* The right frame at the right time :-) */ + if((ret=av_frame_ref(data, &s->current_picture->avframe)) < 0) + return ret; + *got_frame = 1; + } + + if (*got_frame) + s->frame_number = picture->avframe.display_picture_number + 1; + + return buf_idx; +} + +AVCodec ff_dirac_decoder = { + .name = "dirac", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DIRAC, + .priv_data_size = sizeof(DiracContext), + .init = dirac_decode_init, + .close = dirac_decode_end, + .decode = dirac_decode_frame, + .capabilities = CODEC_CAP_DELAY, + .flush = dirac_decode_flush, + .long_name = NULL_IF_CONFIG_SMALL("BBC Dirac VC-2"), +}; diff --git a/ffmpeg/libavcodec/diracdsp.c b/ffmpeg/libavcodec/diracdsp.c new file mode 100644 index 0000000..429241d --- /dev/null +++ b/ffmpeg/libavcodec/diracdsp.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2009 David Conrad + * + * 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 "dsputil.h" +#include "diracdsp.h" +#include "libavcodec/x86/diracdsp_mmx.h" + +#define FILTER(src, stride) \ + ((21*((src)[ 0*stride] + (src)[1*stride]) \ + -7*((src)[-1*stride] + (src)[2*stride]) \ + +3*((src)[-2*stride] + (src)[3*stride]) \ + -1*((src)[-3*stride] + (src)[4*stride]) + 16) >> 5) + +static void dirac_hpel_filter(uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, const uint8_t *src, + int stride, int width, int height) +{ + int x, y; + + for (y = 0; y < height; y++) { + for (x = -3; x < width+5; x++) + dstv[x] = av_clip_uint8(FILTER(src+x, stride)); + + for (x = 0; x < width; x++) + dstc[x] = av_clip_uint8(FILTER(dstv+x, 1)); + + for (x = 0; x < width; x++) + dsth[x] = av_clip_uint8(FILTER(src+x, 1)); + + src += stride; + dsth += stride; + dstv += stride; + dstc += stride; + } +} + +#define PIXOP_BILINEAR(PFX, OP, WIDTH) \ + static void ff_ ## PFX ## _dirac_pixels ## WIDTH ## _bilinear_c(uint8_t *dst, const uint8_t *src[5], int stride, int h) \ + { \ + int x; \ + const uint8_t *s0 = src[0]; \ + const uint8_t *s1 = src[1]; \ + const uint8_t *s2 = src[2]; \ + const uint8_t *s3 = src[3]; \ + const uint8_t *w = src[4]; \ + \ + while (h--) { \ + for (x = 0; x < WIDTH; x++) { \ + OP(dst[x], (s0[x]*w[0] + s1[x]*w[1] + s2[x]*w[2] + s3[x]*w[3] + 8) >> 4); \ + } \ + \ + dst += stride; \ + s0 += stride; \ + s1 += stride; \ + s2 += stride; \ + s3 += stride; \ + } \ + } + +#define OP_PUT(dst, val) (dst) = (val) +#define OP_AVG(dst, val) (dst) = (((dst) + (val) + 1)>>1) + +PIXOP_BILINEAR(put, OP_PUT, 8) +PIXOP_BILINEAR(put, OP_PUT, 16) +PIXOP_BILINEAR(put, OP_PUT, 32) +PIXOP_BILINEAR(avg, OP_AVG, 8) +PIXOP_BILINEAR(avg, OP_AVG, 16) +PIXOP_BILINEAR(avg, OP_AVG, 32) + +#define op_scale1(x) block[x] = av_clip_uint8( (block[x]*weight + (1<<(log2_denom-1))) >> log2_denom) +#define op_scale2(x) dst[x] = av_clip_uint8( (src[x]*weights + dst[x]*weightd + (1<<(log2_denom-1))) >> log2_denom) + +#define DIRAC_WEIGHT(W) \ + static void weight_dirac_pixels ## W ## _c(uint8_t *block, int stride, int log2_denom, \ + int weight, int h) { \ + int x; \ + while (h--) { \ + for (x = 0; x < W; x++) { \ + op_scale1(x); \ + op_scale1(x+1); \ + } \ + block += stride; \ + } \ + } \ + static void biweight_dirac_pixels ## W ## _c(uint8_t *dst, const uint8_t *src, int stride, int log2_denom, \ + int weightd, int weights, int h) { \ + int x; \ + while (h--) { \ + for (x = 0; x < W; x++) { \ + op_scale2(x); \ + op_scale2(x+1); \ + } \ + dst += stride; \ + src += stride; \ + } \ + } + +DIRAC_WEIGHT(8) +DIRAC_WEIGHT(16) +DIRAC_WEIGHT(32) + +#define ADD_OBMC(xblen) \ + static void add_obmc ## xblen ## _c(uint16_t *dst, const uint8_t *src, int stride, \ + const uint8_t *obmc_weight, int yblen) \ + { \ + int x; \ + while (yblen--) { \ + for (x = 0; x < xblen; x += 2) { \ + dst[x ] += src[x ] * obmc_weight[x ]; \ + dst[x+1] += src[x+1] * obmc_weight[x+1]; \ + } \ + dst += stride; \ + src += stride; \ + obmc_weight += 32; \ + } \ + } + +ADD_OBMC(8) +ADD_OBMC(16) +ADD_OBMC(32) + +static void put_signed_rect_clamped_c(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height) +{ + int x, y; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x+=4) { + dst[x ] = av_clip_uint8(src[x ] + 128); + dst[x+1] = av_clip_uint8(src[x+1] + 128); + dst[x+2] = av_clip_uint8(src[x+2] + 128); + dst[x+3] = av_clip_uint8(src[x+3] + 128); + } + dst += dst_stride; + src += src_stride; + } +} + +static void add_rect_clamped_c(uint8_t *dst, const uint16_t *src, int stride, + const int16_t *idwt, int idwt_stride, + int width, int height) +{ + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x+=2) { + dst[x ] = av_clip_uint8(((src[x ]+32)>>6) + idwt[x ]); + dst[x+1] = av_clip_uint8(((src[x+1]+32)>>6) + idwt[x+1]); + } + dst += stride; + src += stride; + idwt += idwt_stride; + } +} + +#define PIXFUNC(PFX, WIDTH) \ + c->PFX ## _dirac_pixels_tab[WIDTH>>4][0] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _c; \ + c->PFX ## _dirac_pixels_tab[WIDTH>>4][1] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _l2_c; \ + c->PFX ## _dirac_pixels_tab[WIDTH>>4][2] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _l4_c; \ + c->PFX ## _dirac_pixels_tab[WIDTH>>4][3] = ff_ ## PFX ## _dirac_pixels ## WIDTH ## _bilinear_c + +void ff_diracdsp_init(DiracDSPContext *c) +{ + c->dirac_hpel_filter = dirac_hpel_filter; + c->add_rect_clamped = add_rect_clamped_c; + c->put_signed_rect_clamped = put_signed_rect_clamped_c; + + c->add_dirac_obmc[0] = add_obmc8_c; + c->add_dirac_obmc[1] = add_obmc16_c; + c->add_dirac_obmc[2] = add_obmc32_c; + + c->weight_dirac_pixels_tab[0] = weight_dirac_pixels8_c; + c->weight_dirac_pixels_tab[1] = weight_dirac_pixels16_c; + c->weight_dirac_pixels_tab[2] = weight_dirac_pixels32_c; + c->biweight_dirac_pixels_tab[0] = biweight_dirac_pixels8_c; + c->biweight_dirac_pixels_tab[1] = biweight_dirac_pixels16_c; + c->biweight_dirac_pixels_tab[2] = biweight_dirac_pixels32_c; + + PIXFUNC(put, 8); + PIXFUNC(put, 16); + PIXFUNC(put, 32); + PIXFUNC(avg, 8); + PIXFUNC(avg, 16); + PIXFUNC(avg, 32); + + if (HAVE_MMX && HAVE_YASM) ff_diracdsp_init_mmx(c); +} diff --git a/ffmpeg/libavcodec/diracdsp.h b/ffmpeg/libavcodec/diracdsp.h new file mode 100644 index 0000000..613ca5b --- /dev/null +++ b/ffmpeg/libavcodec/diracdsp.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 David Conrad + * + * 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 + */ + +#ifndef AVCODEC_DIRACDSP_H +#define AVCODEC_DIRACDSP_H + +#include + +typedef void (*dirac_weight_func)(uint8_t *block, int stride, int log2_denom, int weight, int h); +typedef void (*dirac_biweight_func)(uint8_t *dst, const uint8_t *src, int stride, int log2_denom, int weightd, int weights, int h); + +typedef struct { + void (*dirac_hpel_filter)(uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, const uint8_t *src, int stride, int width, int height); + /** + * dirac_pixels_tab[width][subpel] + * width is 2 for 32, 1 for 16, 0 for 8 + * subpel is 0 for fpel and hpel (only need to copy from the first plane in src) + * 1 if an average of the first 2 planes is needed (TODO: worth it?) + * 2 for general qpel (avg of 4) + * 3 for general epel (biweight of 4 using the weights in src[4]) + * src[0-3] is each of the hpel planes + * src[4] is the 1/8 pel weights if needed + */ + void (*put_dirac_pixels_tab[3][4])(uint8_t *dst, const uint8_t *src[5], int stride, int h); + void (*avg_dirac_pixels_tab[3][4])(uint8_t *dst, const uint8_t *src[5], int stride, int h); + + void (*put_signed_rect_clamped)(uint8_t *dst/*align 16*/, int dst_stride, const int16_t *src/*align 16*/, int src_stride, int width, int height/*mod 2*/); + void (*put_rect_clamped)(uint8_t *dst/*align 16*/, int dst_stride, const int16_t *src/*align 16*/, int src_stride, int width, int height/*mod 2*/); + void (*add_rect_clamped)(uint8_t *dst/*align 16*/, const uint16_t *src/*align 16*/, int stride, const int16_t *idwt/*align 16*/, int idwt_stride, int width, int height/*mod 2*/); + void (*add_dirac_obmc[3])(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); + + dirac_weight_func weight_dirac_pixels_tab[3]; + dirac_biweight_func biweight_dirac_pixels_tab[3]; +} DiracDSPContext; + +#define DECL_DIRAC_PIXOP(PFX, EXT) \ + void ff_ ## PFX ## _dirac_pixels8_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h); \ + void ff_ ## PFX ## _dirac_pixels16_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h); \ + void ff_ ## PFX ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5], int stride, int h) + +DECL_DIRAC_PIXOP(put, c); +DECL_DIRAC_PIXOP(avg, c); +DECL_DIRAC_PIXOP(put, l2_c); +DECL_DIRAC_PIXOP(avg, l2_c); +DECL_DIRAC_PIXOP(put, l4_c); +DECL_DIRAC_PIXOP(avg, l4_c); + +void ff_diracdsp_init(DiracDSPContext *c); + +#endif /* AVCODEC_DIRACDSP_H */ diff --git a/ffmpeg/libavcodec/dnxhd_parser.c b/ffmpeg/libavcodec/dnxhd_parser.c new file mode 100644 index 0000000..6e030e4 --- /dev/null +++ b/ffmpeg/libavcodec/dnxhd_parser.c @@ -0,0 +1,116 @@ +/* + * DNxHD/VC-3 parser + * Copyright (c) 2008 Baptiste Coudurier + * + * 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 + */ + +/** + * @file + * DNxHD/VC-3 parser + */ + +#include "parser.h" + +#define DNXHD_HEADER_PREFIX 0x000002800100 + +typedef struct { + ParseContext pc; + int interlaced; + int cur_field; /* first field is 0, second is 1 */ +} DNXHDParserContext; + +static int dnxhd_find_frame_end(DNXHDParserContext *dctx, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = &dctx->pc; + uint64_t state = pc->state64; + int pic_found = pc->frame_start_found; + int i = 0; + int interlaced = dctx->interlaced; + int cur_field = dctx->cur_field; + + if (!pic_found) { + for (i = 0; i < buf_size; i++) { + state = (state<<8) | buf[i]; + if ((state & 0xffffffffff00LL) == DNXHD_HEADER_PREFIX) { + i++; + pic_found = 1; + interlaced = (state&2)>>1; /* byte following the 5-byte header prefix */ + cur_field = state&1; + break; + } + } + } + + if (pic_found) { + if (!buf_size) /* EOF considered as end of frame */ + return 0; + for (; i < buf_size; i++) { + state = (state<<8) | buf[i]; + if ((state & 0xffffffffff00LL) == DNXHD_HEADER_PREFIX) { + if (!interlaced || dctx->cur_field) { + pc->frame_start_found = 0; + pc->state64 = -1; + dctx->interlaced = interlaced; + dctx->cur_field = 0; + return i-5; + } else { + /* continue, to get the second field */ + dctx->interlaced = interlaced = (state&2)>>1; + dctx->cur_field = cur_field = state&1; + } + } + } + } + pc->frame_start_found = pic_found; + pc->state64 = state; + dctx->interlaced = interlaced; + dctx->cur_field = cur_field; + return END_NOT_FOUND; +} + +static int dnxhd_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DNXHDParserContext *dctx = s->priv_data; + ParseContext *pc = &dctx->pc; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = dnxhd_find_frame_end(dctx, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_dnxhd_parser = { + .codec_ids = { AV_CODEC_ID_DNXHD }, + .priv_data_size = sizeof(DNXHDParserContext), + .parser_parse = dnxhd_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/dnxhddata.c b/ffmpeg/libavcodec/dnxhddata.c new file mode 100644 index 0000000..669b806 --- /dev/null +++ b/ffmpeg/libavcodec/dnxhddata.c @@ -0,0 +1,1082 @@ +/* + * VC3/DNxHD data. + * Copyright (c) 2007 SmartJog S.A., Baptiste Coudurier + * + * 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 "avcodec.h" +#include "dnxhddata.h" +#include "libavutil/common.h" + +/* The quantization tables below are in zigzag order! */ + +static const uint8_t dnxhd_1235_luma_weight[] = { + 0, 32, 32, 32, 33, 32, 32, 32, + 32, 31, 32, 33, 33, 33, 33, 35, + 36, 36, 34, 34, 36, 37, 37, 36, + 36, 35, 36, 38, 39, 39, 37, 36, + 37, 37, 39, 41, 42, 41, 39, 39, + 40, 41, 42, 43, 42, 42, 41, 41, + 41, 44, 47, 46, 46, 48, 51, 51, + 50, 50, 53, 55, 55, 56, 60, 60, +}; + +static const uint8_t dnxhd_1235_chroma_weight[] = { + 0, 32, 33, 34, 34, 33, 34, 35, + 37, 40, 43, 42, 39, 38, 39, 41, + 43, 44, 47, 50, 55, 61, 63, 56, + 48, 46, 49, 54, 59, 58, 55, 58, + 63, 65, 67, 74, 84, 82, 75, 72, + 70, 74, 84, 87, 87, 94, 93, 81, + 75, 78, 83, 89, 91, 86, 82, 85, + 90, 90, 85, 79, 73, 73, 73, 73, +}; + +static const uint8_t dnxhd_1237_luma_weight[] = { + 0, 32, 33, 34, 34, 36, 37, 36, + 36, 37, 38, 38, 38, 39, 41, 44, + 43, 41, 40, 41, 46, 49, 47, 46, + 47, 49, 51, 54, 60, 62, 59, 55, + 54, 56, 58, 61, 65, 66, 64, 63, + 66, 73, 78, 79, 80, 79, 78, 78, + 82, 87, 89, 90, 93, 95, 96, 97, + 97, 100, 104, 102, 98, 98, 99, 99, +}; + +static const uint8_t dnxhd_1237_chroma_weight[] = { + 0, 32, 36, 39, 39, 38, 39, 41, + 45, 51, 57, 58, 53, 48, 47, 51, + 55, 58, 66, 75, 81, 83, 82, 78, + 73, 72, 74, 77, 83, 85, 83, 82, + 89, 99, 96, 90, 94, 97, 99, 105, + 109, 105, 95, 89, 92, 95, 94, 93, + 92, 88, 89, 90, 93, 95, 96, 97, + 97, 100, 104, 102, 98, 98, 99, 99, +}; + +static const uint8_t dnxhd_1238_luma_weight[] = { + 0, 32, 32, 33, 34, 33, 33, 33, + 33, 33, 33, 33, 33, 35, 37, 37, + 36, 36, 35, 36, 38, 38, 36, 35, + 36, 37, 38, 41, 42, 41, 39, 38, + 38, 38, 39, 41, 42, 41, 39, 39, + 40, 41, 43, 44, 44, 44, 44, 44, + 45, 47, 47, 47, 49, 50, 51, 51, + 51, 53, 55, 57, 58, 59, 57, 57, +}; + +static const uint8_t dnxhd_1238_chroma_weight[] = { + 0, 32, 35, 35, 35, 34, 34, 35, + 39, 43, 45, 45, 41, 39, 40, 41, + 42, 44, 48, 55, 59, 63, 65, 59, + 53, 52, 52, 55, 61, 62, 58, 58, + 63, 66, 66, 65, 70, 74, 70, 66, + 65, 68, 75, 77, 74, 74, 77, 76, + 73, 73, 73, 73, 76, 80, 89, 90, + 82, 77, 80, 86, 84, 82, 82, 82, +}; + +static const uint8_t dnxhd_1241_luma_weight[] = { + 0, 32, 33, 34, 34, 35, 36, 37, + 36, 37, 38, 38, 38, 39, 39, 40, + 40, 38, 38, 39, 38, 37, 39, 41, + 41, 42, 43, 45, 45, 46, 47, 46, + 45, 43, 39, 37, 37, 40, 44, 45, + 45, 46, 46, 46, 47, 47, 46, 44, + 42, 43, 45, 47, 48, 49, 50, 49, + 48, 46, 47, 48, 48, 49, 49, 49, +}; + +static const uint8_t dnxhd_1241_chroma_weight[] = { + 0, 32, 36, 38, 37, 37, 40, 41, + 40, 40, 42, 42, 41, 41, 41, 41, + 42, 43, 44, 44, 45, 46, 46, 45, + 44, 45, 45, 45, 45, 46, 47, 46, + 45, 44, 42, 41, 43, 45, 45, 47, + 48, 48, 48, 46, 47, 47, 46, 47, + 46, 45, 45, 47, 48, 49, 50, 49, + 48, 46, 48, 49, 48, 49, 49, 49, +}; + +static const uint8_t dnxhd_1242_luma_weight[] = { + 0, 32, 33, 33, 34, 35, 36, 35, + 33, 33, 35, 36, 37, 37, 38, 37, + 37, 37, 36, 37, 37, 37, 38, 39, + 37, 36, 37, 40, 42, 45, 46, 44, + 41, 42, 44, 45, 47, 49, 50, 48, + 46, 48, 49, 50, 52, 52, 50, 49, + 47, 48, 50, 50, 51, 51, 50, 49, + 49, 51, 52, 51, 49, 47, 47, 47, +}; + +static const uint8_t dnxhd_1242_chroma_weight[] = { + 0, 32, 37, 42, 45, 45, 45, 44, + 38, 37, 40, 42, 44, 49, 51, 47, + 41, 40, 43, 44, 46, 48, 51, 54, + 51, 47, 47, 45, 47, 50, 51, 49, + 46, 47, 49, 47, 50, 55, 55, 51, + 48, 49, 51, 51, 52, 52, 54, 54, + 49, 49, 52, 53, 54, 54, 53, 53, + 55, 59, 63, 62, 60, 60, 60, 60, +}; + +static const uint8_t dnxhd_1243_luma_weight[] = { + 0, 32, 32, 33, 33, 35, 35, 35, + 35, 35, 35, 35, 34, 35, 38, 40, + 39, 37, 37, 37, 36, 35, 36, 38, + 40, 41, 42, 44, 45, 44, 42, 41, + 40, 38, 36, 36, 37, 38, 40, 43, + 44, 45, 45, 45, 45, 45, 45, 41, + 39, 41, 45, 47, 47, 48, 48, 48, + 46, 44, 45, 47, 47, 48, 47, 47, +}; + +static const uint8_t dnxhd_1243_chroma_weight[] = { + 0, 32, 36, 37, 36, 37, 39, 39, + 41, 43, 43, 42, 41, 41, 41, 42, + 43, 43, 43, 44, 44, 44, 46, 47, + 46, 45, 45, 45, 45, 46, 44, 44, + 45, 44, 42, 41, 43, 46, 45, 44, + 45, 45, 45, 46, 46, 46, 45, 44, + 45, 44, 45, 47, 47, 48, 49, 48, + 46, 45, 46, 47, 47, 48, 47, 47, +}; + +static const uint8_t dnxhd_1250_luma_weight[] = { + 0, 32, 32, 33, 34, 35, 35, 35, + 34, 34, 35, 36, 36, 36, 36, 36, + 37, 38, 38, 38, 38, 38, 39, 39, + 38, 38, 39, 41, 43, 43, 42, 41, + 40, 40, 39, 40, 41, 41, 39, 39, + 40, 42, 47, 50, 47, 45, 46, 46, + 44, 45, 46, 47, 49, 54, 58, 54, + 48, 49, 54, 57, 60, 62, 63, 63, +}; + +static const uint8_t dnxhd_1250_chroma_weight[] = { + 0, 32, 35, 36, 36, 35, 36, 39, + 41, 43, 45, 44, 41, 39, 40, 42, + 43, 43, 45, 48, 49, 51, 52, 50, + 50, 51, 51, 51, 51, 52, 53, 54, + 51, 49, 51, 52, 52, 56, 57, 55, + 54, 54, 55, 56, 55, 58, 58, 58, + 60, 61, 62, 62, 59, 57, 58, 58, + 61, 59, 59, 59, 60, 62, 63, 63, +}; + +static const uint8_t dnxhd_1251_luma_weight[] = { + 0, 32, 32, 34, 34, 34, 34, 35, + 35, 35, 36, 37, 36, 36, 35, 36, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 39, 41, 44, 43, 41, 40, + 40, 40, 40, 39, 40, 41, 40, 39, + 40, 43, 46, 46, 44, 44, 44, 42, + 41, 43, 46, 48, 50, 55, 58, 53, + 48, 50, 55, 58, 61, 62, 62, 62, +}; + +static const uint8_t dnxhd_1251_chroma_weight[] = { + 0, 32, 35, 36, 36, 35, 36, 39, + 41, 43, 45, 44, 41, 39, 40, 42, + 43, 43, 45, 48, 48, 48, 50, 50, + 50, 51, 51, 51, 51, 52, 53, 54, + 51, 49, 51, 52, 52, 56, 57, 55, + 54, 54, 55, 56, 55, 58, 58, 58, + 60, 61, 62, 62, 59, 57, 58, 58, + 61, 59, 59, 59, 61, 62, 62, 62, +}; + +static const uint8_t dnxhd_1252_luma_weight[] = { + 0, 32, 34, 35, 36, 36, 36, 37, + 36, 37, 39, 40, 41, 40, 40, 40, + 41, 41, 42, 41, 41, 43, 44, 44, + 45, 46, 48, 55, 60, 57, 52, 50, + 49, 49, 52, 52, 53, 55, 58, 62, + 65, 73, 82, 82, 80, 78, 73, 68, + 71, 82, 90, 90, 88, 87, 90, 95, + 100, 107, 103, 97, 95, 93, 99, 99, +}; +static const uint8_t dnxhd_1252_chroma_weight[] = { + 0, 32, 35, 36, 37, 37, 38, 40, + 42, 46, 49, 50, 50, 49, 49, 53, + 56, 56, 57, 58, 60, 62, 64, 65, + 63, 64, 64, 65, 66, 65, 67, 71, + 72, 74, 74, 74, 74, 77, 81, 78, + 72, 73, 82, 85, 89, 88, 84, 80, + 90, 100, 90, 90, 88, 87, 90, 95, + 114, 128, 125, 129, 134, 125, 116, 116, +}; + +static const uint8_t dnxhd_1237_dc_codes[12] = { + 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, +}; + +static const uint8_t dnxhd_1237_dc_bits[12] = { + 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, +}; + +static const uint16_t dnxhd_1237_ac_codes[257] = { + 0, 1, 4, 5, 12, 26, 27, 56, + 57, 58, 59, 120, 121, 244, 245, 246, + 247, 248, 498, 499, 500, 501, 502, 1006, + 1007, 1008, 1009, 1010, 1011, 2024, 2025, 2026, + 2027, 2028, 2029, 2030, 2031, 4064, 4065, 4066, + 4067, 4068, 4069, 4070, 4071, 4072, 4073, 8148, + 8149, 8150, 8151, 8152, 8153, 8154, 8155, 8156, + 8157, 8158, 16318, 16319, 16320, 16321, 16322, 16323, + 16324, 16325, 16326, 16327, 16328, 16329, 16330, 16331, + 16332, 16333, 32668, 32669, 32670, 32671, 32672, 32673, + 32674, 32675, 32676, 32677, 32678, 32679, 32680, 32681, + 32682, 32683, 32684, 65370, 65371, 65372, 65373, 65374, + 65375, 65376, 65377, 65378, 65379, 65380, 65381, 65382, + 65383, 65384, 65385, 65386, 65387, 65388, 65389, 65390, + 65391, 65392, 65393, 65394, 65395, 65396, 65397, 65398, + 65399, 65400, 65401, 65402, 65403, 65404, 65405, 65406, + 65407, 65408, 65409, 65410, 65411, 65412, 65413, 65414, + 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, + 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, + 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, + 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, + 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, + 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, + 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, + 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, + 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, + 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, + 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, + 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, + 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, + 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, + 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, + 65535, +}; + +static const uint8_t dnxhd_1237_ac_bits[257] = { + 2, 2, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, +}; + +static const uint8_t dnxhd_1237_ac_level[257] = { + 3, 3, 5, 0, 7, 9, 5, 11, 13, 15, 7, 17, 19, 21, 23, 25, + 9, 11, 27, 29, 31, 33, 13, 35, 37, 39, 41, 43, 15, 45, 47, 49, + 51, 53, 55, 17, 19, 57, 59, 61, 63, 65, 67, 69, 21, 23, 25, 71, + 73, 75, 77, 79, 81, 83, 27, 29, 31, 33, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105, 35, 37, 39, 41, 43,107,109,111,113,115,117, + 119,121,123,129, 3, 45, 47, 49, 51, 53, 55,125,127, 5, 7, 9, + 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, + 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, + 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,101,103,105, + 107,109,111,113,115,117,119,121,123,125,127,129, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, +}; + +static const uint8_t dnxhd_1237_ac_flags[257] = { + 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; + +static const uint16_t dnxhd_1237_run_codes[62] = { + 0, 4, 10, 11, 24, 25, 26, 54, + 55, 56, 57, 58, 118, 119, 240, 482, + 483, 484, 485, 486, 487, 488, 489, 490, + 491, 492, 493, 494, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, +}; + +static const uint8_t dnxhd_1237_run_bits[62] = { + 1, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 8, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +}; + +static const uint8_t dnxhd_1237_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 53, 57, 58, 59, 60, 61, 62, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 54, 55, 56, +}; + +static const uint8_t dnxhd_1238_dc_codes[12] = { + 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, +}; + +static const uint8_t dnxhd_1238_dc_bits[12] = { + 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, +}; + +static const uint16_t dnxhd_1238_ac_codes[257] = { + 0, 1, 4, 10, 11, 24, 25, 26, + 54, 55, 56, 57, 116, 117, 118, 119, + 240, 241, 242, 243, 244, 245, 492, 493, + 494, 495, 496, 497, 498, 499, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 2018, + 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, + 2027, 4056, 4057, 4058, 4059, 4060, 4061, 4062, + 4063, 4064, 4065, 4066, 4067, 4068, 4069, 8140, + 8141, 8142, 8143, 8144, 8145, 8146, 8147, 8148, + 8149, 8150, 8151, 8152, 8153, 8154, 8155, 8156, + 16314, 16315, 16316, 16317, 16318, 16319, 16320, 16321, + 16322, 16323, 16324, 16325, 16326, 16327, 16328, 16329, + 16330, 16331, 16332, 16333, 16334, 16335, 16336, 16337, + 16338, 32678, 32679, 32680, 32681, 32682, 32683, 32684, + 32685, 32686, 32687, 32688, 32689, 32690, 32691, 32692, + 32693, 32694, 32695, 32696, 32697, 32698, 32699, 32700, + 32701, 32702, 32703, 32704, 32705, 65412, 65413, 65414, + 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, + 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, + 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, + 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, + 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, + 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, + 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, + 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, + 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, + 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, + 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, + 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, + 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, + 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, + 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, + 65535, +}; + +static const uint8_t dnxhd_1238_ac_bits[257] = { + 2, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, +}; + +static const uint8_t dnxhd_1238_ac_level[257] = { + 3, 3, 5, 7, 0, 9, 11, 5, 13, 15, 17, 7, 19, 21, 23, 9, + 25, 27, 29, 31, 33, 11, 35, 37, 39, 41, 43, 45, 13, 15, 47, 49, + 51, 53, 55, 57, 59, 17, 19, 61, 63, 65, 67, 69, 71, 73, 75, 21, + 23, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 25, 27, 29, 99, + 101,103,105,107,109,111,113,115,117,119,121,123, 31, 33, 35, 37, + 125,127,129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, + 29, 31, 33, 39, 41, 43, 45, 47, 49, 35, 37, 39, 41, 43, 45, 47, + 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 81, 51, + 53, 55, 57, 59, 61, 77, 79, 83, 85, 87, 89, 91, 93, 95, 97, 99, + 101,103,105,107,109,111,113,115,117,119,121,123,125,127,129, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, +}; /* 0 is EOB */ + +static const uint8_t dnxhd_1238_ac_flags[257] = { + 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; + +static const uint16_t dnxhd_1235_1238_1241_run_codes[62] = { + 0, 4, 10, 11, 24, 25, 26, 27, + 56, 57, 58, 59, 120, 242, 486, 487, + 488, 489, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, +}; + +static const uint8_t dnxhd_1235_1238_1241_run_bits[62] = { + 1, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 8, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +}; + +static const uint8_t dnxhd_1238_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 20, 21, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +}; + +static const uint8_t dnxhd_1235_1241_dc_codes[14] = { + 10, 62, 11, 12, 13, 0, 1, 2, 3, 4, 14, 30, 126, 127, +}; + +static const uint8_t dnxhd_1235_1241_dc_bits[14] = { + 4, 6, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 7, 7, +}; + +static const uint16_t dnxhd_1235_1241_ac_codes[257] = { + 0, 1, 4, 10, 11, 24, 25, 26, + 54, 55, 56, 57, 116, 117, 118, 119, + 240, 241, 242, 243, 244, 245, 492, 493, + 494, 495, 496, 497, 498, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 1007, 2016, + 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, + 2025, 2026, 4054, 4055, 4056, 4057, 4058, 4059, + 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, + 4068, 4069, 8140, 8141, 8142, 8143, 8144, 8145, + 8146, 8147, 8148, 8149, 8150, 8151, 8152, 8153, + 8154, 8155, 8156, 8157, 16316, 16317, 16318, 16319, + 16320, 16321, 16322, 16323, 16324, 16325, 16326, 16327, + 16328, 16329, 16330, 16331, 16332, 16333, 16334, 16335, + 16336, 16337, 32676, 32677, 32678, 32679, 32680, 32681, + 32682, 32683, 32684, 32685, 32686, 32687, 32688, 32689, + 32690, 32691, 32692, 32693, 32694, 32695, 32696, 32697, + 32698, 32699, 32700, 32701, 32702, 32703, 32704, 32705, + 32706, 32707, 32708, 65418, 65419, 65420, 65421, 65422, + 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, + 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, + 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, + 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, + 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, + 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, + 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, + 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, + 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, + 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, + 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, + 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, + 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, + 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, + 65535, +}; + +static const uint8_t dnxhd_1235_1241_ac_bits[257] = { + 2, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, +}; + +static const uint8_t dnxhd_1235_1241_ac_level[257] = { + 3, 3, 5, 7, 0, 9, 11, 5, 13, 15, 17, 7, 19, 21, 23, 9, + 25, 27, 29, 31, 33, 11, 35, 37, 39, 41, 43, 13, 15, 45, 47, 49, + 51, 53, 55, 57, 59, 17, 19, 61, 63, 65, 67, 69, 71, 73, 75, 77, + 21, 23, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,101, 25, 27, + 29, 31,103,105,107,109,111,113,115,117,119,121,123,125,127, 3, + 33, 35, 37, 39,129, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, + 27, 29, 31, 33, 35, 41, 43, 45, 47, 49, 37, 39, 41, 43, 45, 47, + 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, + 81, 83, 85, 51, 53, 55, 57, 59, 61, 63, 65, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, +}; + +static const uint8_t dnxhd_1235_1241_ac_flags[257] = { + 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; + +static const uint8_t dnxhd_1235_1241_run[62] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 18, 20, 17, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +}; + +static const uint8_t dnxhd_1250_dc_codes[14] = { + 10, 62, 11, 12, 13, 0, 1, 2, 3, 4, 14, 30, 126, 127 +}; +static const uint8_t dnxhd_1250_dc_bits[14] = { + 4, 6, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 7, 7 +}; +static const uint16_t dnxhd_1250_ac_codes[257] = { + 0, 1, 4, 10, 11, 24, 25, 26, + 54, 55, 56, 57, 116, 117, 118, 119, + 240, 241, 242, 243, 244, 245, 492, 493, + 494, 495, 496, 497, 498, 998, 999, 1000, + 1001, 1002, 1003, 1004, 1005, 1006, 2014, 2015, + 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, + 2024, 2025, 4052, 4053, 4054, 4055, 4056, 4057, + 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, + 4066, 4067, 8136, 8137, 8138, 8139, 8140, 8141, + 8142, 8143, 8144, 8145, 8146, 8147, 8148, 8149, + 8150, 8151, 8152, 8153, 8154, 8155, 8156, 16314, + 16315, 16316, 16317, 16318, 16319, 16320, 16321, 16322, + 16323, 16324, 16325, 16326, 16327, 16328, 16329, 16330, + 16331, 16332, 16333, 16334, 16335, 16336, 16337, 16338, + 32678, 32679, 32680, 32681, 32682, 32683, 32684, 32685, + 32686, 32687, 32688, 32689, 32690, 32691, 32692, 32693, + 32694, 32695, 32696, 32697, 32698, 32699, 32700, 32701, + 32702, 32703, 32704, 32705, 32706, 32707, 32708, 32709, + 32710, 32711, 32712, 65426, 65427, 65428, 65429, 65430, + 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, + 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, + 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, + 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, + 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, + 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, + 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, + 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, + 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, + 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, + 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, + 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, + 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, + 65535 +}; +static const uint8_t dnxhd_1250_ac_bits[257] = { + 2, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16 +}; +static const uint8_t dnxhd_1250_ac_level[257] = { + 3, 3, 5, 7, 0, 9, 11, 5, 13, 15, 17, 7, 19, 21, 23, 9, + 25, 27, 29, 31, 33, 11, 35, 37, 39, 41, 43, 45, 13, 47, 49, 51, + 53, 55, 57, 59, 15, 17, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, + 19, 21, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,101,103,105, 23, + 25, 27,107,109,111,113,115,117,119,121,123,125,127,129, 3, 5, + 7, 9, 11, 29, 31, 33, 35, 13, 15, 17, 19, 21, 23, 25, 27, 29, + 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 37, 39, 41, 43, + 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, + 87, 89, 91, 93, 95, 97, 99,101,103,105,107,111,113, 45, 47, 49, + 51, 53, 55,109,115,117,119,121,123,125,127,129, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129 +}; +static const uint8_t dnxhd_1250_ac_flags[257] = { + 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; +static const uint16_t dnxhd_1250_run_codes[62] = { + 0, 4, 5, 12, 26, 27, 28, 58, + 118, 119, 120, 242, 486, 487, 976, 977, + 978, 979, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023 +}; +static const uint8_t dnxhd_1250_run_bits[62] = { + 1, 3, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; +static const uint8_t dnxhd_1250_run[62] = { + 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, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62 +}; + +static const uint8_t dnxhd_1251_dc_codes[12] = { + 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, +}; + +static const uint8_t dnxhd_1251_dc_bits[12] = { + 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, +}; + +static const uint16_t dnxhd_1251_ac_codes[257] = { + 0, 1, 4, 10, 11, 24, 25, 26, + 54, 55, 56, 57, 116, 117, 118, 119, + 240, 241, 242, 243, 244, 245, 492, 493, + 494, 495, 496, 497, 996, 997, 998, 999, + 1000, 1001, 1002, 1003, 1004, 1005, 2012, 2013, + 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, + 2022, 2023, 2024, 2025, 4052, 4053, 4054, 4055, + 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, + 4064, 4065, 4066, 8134, 8135, 8136, 8137, 8138, + 8139, 8140, 8141, 8142, 8143, 8144, 8145, 8146, + 8147, 8148, 8149, 8150, 8151, 8152, 8153, 8154, + 8155, 8156, 16314, 16315, 16316, 16317, 16318, 16319, + 16320, 16321, 16322, 16323, 16324, 16325, 16326, 16327, + 16328, 16329, 16330, 16331, 16332, 16333, 16334, 16335, + 16336, 16337, 16338, 16339, 32680, 32681, 32682, 32683, + 32684, 32685, 32686, 32687, 32688, 32689, 32690, 32691, + 32692, 32693, 32694, 32695, 32696, 32697, 32698, 32699, + 32700, 32701, 32702, 32703, 32704, 32705, 32706, 32707, + 32708, 32709, 32710, 32711, 32712, 32713, 32714, 65430, + 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, + 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, + 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, + 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, + 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, + 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, + 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, + 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, + 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, + 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, + 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, + 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, + 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, + 65535, +}; + +static const uint8_t dnxhd_1251_ac_bits[257] = { + 2, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, +}; + +static const uint8_t dnxhd_1251_ac_level[257] = { + 3, 3, 5, 7, 0, 9, 11, 5, 13, 15, 17, 7, 19, 21, 23, 9, + 25, 27, 29, 31, 33, 11, 35, 37, 39, 41, 43, 13, 45, 47, 49, 51, + 53, 55, 57, 59, 15, 17, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, + 81, 19, 21, 23, 83, 85, 87, 89, 91, 93, 95, 97, 99,101,103,105, + 25, 27, 29,107,109,111,113,115,117,119,121,123,125,127,129, 3, + 5, 7, 9, 11, 13, 15, 17, 31, 33, 35, 19, 21, 23, 25, 27, 29, + 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 37, + 39, 41, 43, 45, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, + 85, 87, 89, 91, 93, 95, 97, 99,101,103,105,107,109,111,113,115, + 117, 47, 49, 51, 53, 55, 57,119,121,123,125,127,129, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, +}; + +static const uint8_t dnxhd_1251_ac_flags[257] = { + 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; + +static const uint16_t dnxhd_1251_run_codes[62] = { + 0, 4, 5, 12, 26, 27, 28, 58, + 118, 119, 120, 242, 486, 487, 976, 977, + 978, 979, 980, 981, 982, 983, 984, 985, + 986, 987, 988, 989, 990, 991, 992, 993, + 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, + 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, + 1018, 1019, 1020, 1021, 1022, 1023, +}; + +static const uint8_t dnxhd_1251_run_bits[62] = { + 1, 3, 3, 4, 5, 5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +}; + +static const uint8_t dnxhd_1251_run[62] = { + 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, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +}; + +static const uint8_t dnxhd_1252_dc_codes[12] = { + 0, 12, 13, 1, 2, 3, 4, 5, 14, 30, 62, 63, +}; + +static const uint8_t dnxhd_1252_dc_bits[12] = { + 3, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, +}; + +static const uint16_t dnxhd_1252_ac_codes[257] = { + 0, 1, 4, 10, 11, 12, 26, 27, + 56, 57, 58, 118, 119, 120, 242, 243, + 244, 245, 246, 247, 496, 497, 498, 499, + 500, 1002, 1003, 1004, 1005, 1006, 1007, 1008, + 1009, 2020, 2021, 2022, 2023, 2024, 2025, 2026, + 2027, 2028, 2029, 4060, 4061, 4062, 4063, 4064, + 4065, 4066, 4067, 4068, 4069, 4070, 4071, 8144, + 8145, 8146, 8147, 8148, 8149, 8150, 8151, 8152, + 8153, 8154, 8155, 8156, 8157, 8158, 16318, 16319, + 16320, 16321, 16322, 16323, 16324, 16325, 16326, 16327, + 16328, 16329, 16330, 16331, 16332, 16333, 16334, 16335, + 32672, 32673, 32674, 32675, 32676, 32677, 32678, 32679, + 32680, 32681, 32682, 32683, 32684, 32685, 32686, 32687, + 32688, 32689, 32690, 32691, 32692, 32693, 32694, 65390, + 65391, 65392, 65393, 65394, 65395, 65396, 65397, 65398, + 65399, 65400, 65401, 65402, 65403, 65404, 65405, 65406, + 65407, 65408, 65409, 65410, 65411, 65412, 65413, 65414, + 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, + 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, + 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438, + 65439, 65440, 65441, 65442, 65443, 65444, 65445, 65446, + 65447, 65448, 65449, 65450, 65451, 65452, 65453, 65454, + 65455, 65456, 65457, 65458, 65459, 65460, 65461, 65462, + 65463, 65464, 65465, 65466, 65467, 65468, 65469, 65470, + 65471, 65472, 65473, 65474, 65475, 65476, 65477, 65478, + 65479, 65480, 65481, 65482, 65483, 65484, 65485, 65486, + 65487, 65488, 65489, 65490, 65491, 65492, 65493, 65494, + 65495, 65496, 65497, 65498, 65499, 65500, 65501, 65502, + 65503, 65504, 65505, 65506, 65507, 65508, 65509, 65510, + 65511, 65512, 65513, 65514, 65515, 65516, 65517, 65518, + 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, + 65527, 65528, 65529, 65530, 65531, 65532, 65533, 65534, + 65535, +}; + +static const uint8_t dnxhd_1252_ac_bits[257] = { + 2, 2, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, +}; + +static const uint8_t dnxhd_1252_ac_level[257] = { + 3, 3, 5, 7, 5, 0, 9, 11, 13, 15, 7, 17, 19, 21, 23, 25, + 27, 29, 9, 11, 31, 33, 35, 37, 13, 39, 41, 43, 45, 47, 49, 15, + 17, 51, 53, 55, 57, 59, 61, 63, 65, 19, 21, 67, 69, 71, 73, 75, + 77, 79, 81, 83, 23, 25, 27, 85, 87, 89, 91, 93, 95, 97, 99,101, + 103,105,107, 29, 31, 33,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 35, 37, 39, 41, 9, 11, 13, 15, 17, 19, 21, 23, + 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 43, 45, 47, 49, 51, 45, + 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, + 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,101,103,105,107,109, + 111,113,115,117,119,121,123,125,127,129, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, + 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, + 97, 99,101,103,105,107,109,111,113,115,117,119,121,123,125,127, + 129, +}; + +static const uint8_t dnxhd_1252_ac_flags[257] = { + 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, +}; + +const CIDEntry ff_dnxhd_cid_table[] = { + { 1235, 1920, 1080, 0, 917504, 917504, 6, 10, 4, + dnxhd_1235_luma_weight, dnxhd_1235_chroma_weight, + dnxhd_1235_1241_dc_codes, dnxhd_1235_1241_dc_bits, + dnxhd_1235_1241_ac_codes, dnxhd_1235_1241_ac_bits, dnxhd_1235_1241_ac_level, + dnxhd_1235_1241_ac_flags, + dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1235_1241_run, + { 175, 185, 365, 440 }, + { { 24000, 1001 }, { 25, 1 }, { 50, 1 }, { 60000, 1001 } } }, + { 1237, 1920, 1080, 0, 606208, 606208, 4, 8, 3, + dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, + dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_level, + dnxhd_1237_ac_flags, + dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, + { 115, 120, 145, 240, 290 }, + { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 1238, 1920, 1080, 0, 917504, 917504, 4, 8, 4, + dnxhd_1238_luma_weight, dnxhd_1238_chroma_weight, + dnxhd_1238_dc_codes, dnxhd_1238_dc_bits, + dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_level, + dnxhd_1238_ac_flags, + dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1238_run, + { 175, 185, 220, 365, 440 }, + { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 1241, 1920, 1080, 1, 917504, 458752, 6, 10, 4, + dnxhd_1241_luma_weight, dnxhd_1241_chroma_weight, + dnxhd_1235_1241_dc_codes, dnxhd_1235_1241_dc_bits, + dnxhd_1235_1241_ac_codes, dnxhd_1235_1241_ac_bits, dnxhd_1235_1241_ac_level, + dnxhd_1235_1241_ac_flags, + dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1235_1241_run, + { 185, 220 }, + { { 25, 1 }, { 30000, 1001 } } }, + { 1242, 1920, 1080, 1, 606208, 303104, 4, 8, 3, + dnxhd_1242_luma_weight, dnxhd_1242_chroma_weight, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, + dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_level, + dnxhd_1237_ac_flags, + dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, + { 120, 145 }, + { { 25, 1 }, { 30000, 1001 } } }, + { 1243, 1920, 1080, 1, 917504, 458752, 4, 8, 4, + dnxhd_1243_luma_weight, dnxhd_1243_chroma_weight, + dnxhd_1238_dc_codes, dnxhd_1238_dc_bits, + dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_level, + dnxhd_1238_ac_flags, + dnxhd_1235_1238_1241_run_codes, dnxhd_1235_1238_1241_run_bits, dnxhd_1238_run, + { 185, 220 }, + { { 25, 1 }, { 30000, 1001 } } }, + { 1250, 1280, 720, 0, 458752, 458752, 6, 10, 4, + dnxhd_1250_luma_weight, dnxhd_1250_chroma_weight, + dnxhd_1250_dc_codes, dnxhd_1250_dc_bits, + dnxhd_1250_ac_codes, dnxhd_1250_ac_bits, dnxhd_1250_ac_level, + dnxhd_1250_ac_flags, + dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run, + { 90, 90, 180, 220 }, + { { 24000, 1001 }, { 25, 1 }, { 50, 1 }, { 60000, 1001 } } }, + { 1251, 1280, 720, 0, 458752, 458752, 4, 8, 4, + dnxhd_1251_luma_weight, dnxhd_1251_chroma_weight, + dnxhd_1251_dc_codes, dnxhd_1251_dc_bits, + dnxhd_1251_ac_codes, dnxhd_1251_ac_bits, dnxhd_1251_ac_level, + dnxhd_1251_ac_flags, + dnxhd_1251_run_codes, dnxhd_1251_run_bits, dnxhd_1251_run, + { 90, 90, 110, 180, 220 }, + { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 1252, 1280, 720, 0, 303104, 303104, 4, 8, 5, + dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight, + dnxhd_1252_dc_codes, dnxhd_1252_dc_bits, + dnxhd_1252_ac_codes, dnxhd_1252_ac_bits, dnxhd_1252_ac_level, + dnxhd_1252_ac_flags, + dnxhd_1251_run_codes, dnxhd_1251_run_bits, dnxhd_1251_run, + { 60, 60, 75, 120, 145 }, + { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, + { 1253, 1920, 1080, 0, 188416, 188416, 4, 8, 3, + dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight, + dnxhd_1237_dc_codes, dnxhd_1237_dc_bits, + dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_level, + dnxhd_1237_ac_flags, + dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run, + { 36, 36, 45, 75, 90 }, + { { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } }, +}; + +int ff_dnxhd_get_cid_table(int cid) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) + if (ff_dnxhd_cid_table[i].cid == cid) + return i; + return -1; +} + +int avpriv_dnxhd_get_frame_size(int cid) +{ + int i = ff_dnxhd_get_cid_table(cid); + if (i<0) + return i; + return ff_dnxhd_cid_table[i].frame_size; +} + +int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth) +{ + int i, j; + int mbs = avctx->bit_rate/1000000; + if (!mbs) + return 0; + for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { + const CIDEntry *cid = &ff_dnxhd_cid_table[i]; + if (cid->width == avctx->width && cid->height == avctx->height && + cid->interlaced == !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT) && + cid->bit_depth == bit_depth) { + for (j = 0; j < FF_ARRAY_ELEMS(cid->bit_rates); j++) { + if (cid->bit_rates[j] == mbs) + return cid->cid; + } + } + } + return 0; +} + +void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel) +{ + int i, j; + for (i = 0; i < FF_ARRAY_ELEMS(ff_dnxhd_cid_table); i++) { + const CIDEntry *cid = &ff_dnxhd_cid_table[i]; + for (j = 0; j < FF_ARRAY_ELEMS(cid->bit_rates); j++) { + if (!cid->bit_rates[j]) + break; + + av_log(avctx, loglevel, "Frame size: %dx%d%c; bitrate: %dMbps; pixel format: %s; framerate: %d/%d\n", + cid->width, cid->height, cid->interlaced ? 'i' : 'p', cid->bit_rates[j], + cid->bit_depth == 10 ? "yuv422p10" : "yuv422p", cid->frame_rates[j].num, cid->frame_rates[j].den); + } + } +} diff --git a/ffmpeg/libavcodec/dnxhddata.h b/ffmpeg/libavcodec/dnxhddata.h new file mode 100644 index 0000000..b8bcb21 --- /dev/null +++ b/ffmpeg/libavcodec/dnxhddata.h @@ -0,0 +1,57 @@ +/* + * VC3/DNxHD decoder. + * Copyright (c) 2007 SmartJog S.A., Baptiste Coudurier + * + * 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 + */ + +#ifndef AVCODEC_DNXHDDATA_H +#define AVCODEC_DNXHDDATA_H + +#include +#include "avcodec.h" +#include "libavutil/internal.h" + +typedef struct CIDEntry { + int cid; + unsigned int width, height; + int interlaced; + unsigned int frame_size; + unsigned int coding_unit_size; + int index_bits; + int bit_depth; + int eob_index; + const uint8_t *luma_weight, *chroma_weight; + const uint8_t *dc_codes, *dc_bits; + const uint16_t *ac_codes; + const uint8_t *ac_bits, *ac_level; + const uint8_t *ac_flags; + const uint16_t *run_codes; + const uint8_t *run_bits, *run; + int bit_rates[5]; ///< Helpher to choose variants, rounded to nearest 5Mb/s + AVRational frame_rates[5]; +} CIDEntry; + +extern av_export const CIDEntry ff_dnxhd_cid_table[]; + +int ff_dnxhd_get_cid_table(int cid); +int ff_dnxhd_find_cid(AVCodecContext *avctx, int bit_depth); +void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel); + +int avpriv_dnxhd_get_frame_size(int cid); + +#endif /* AVCODEC_DNXHDDATA_H */ diff --git a/ffmpeg/libavcodec/dnxhddec.c b/ffmpeg/libavcodec/dnxhddec.c new file mode 100644 index 0000000..11bed00 --- /dev/null +++ b/ffmpeg/libavcodec/dnxhddec.c @@ -0,0 +1,427 @@ +/* + * VC3/DNxHD decoder. + * Copyright (c) 2007 SmartJog S.A., Baptiste Coudurier + * Copyright (c) 2011 MirriAd Ltd + * + * 10 bit support added by MirriAd Ltd, Joseph Artsimovich + * + * 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 + */ + +//#define TRACE +//#define DEBUG + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "get_bits.h" +#include "dnxhddata.h" +#include "dsputil.h" +#include "internal.h" +#include "thread.h" + +typedef struct DNXHDContext { + AVCodecContext *avctx; + GetBitContext gb; + int64_t cid; ///< compression id + unsigned int width, height; + unsigned int mb_width, mb_height; + uint32_t mb_scan_index[68]; /* max for 1080p */ + int cur_field; ///< current interlaced field + VLC ac_vlc, dc_vlc, run_vlc; + int last_dc[3]; + DSPContext dsp; + DECLARE_ALIGNED(16, int16_t, blocks)[8][64]; + ScanTable scantable; + const CIDEntry *cid_table; + int bit_depth; // 8, 10 or 0 if not initialized at all. + void (*decode_dct_block)(struct DNXHDContext *ctx, int16_t *block, + int n, int qscale); + int last_qscale; + int luma_scale[64]; + int chroma_scale[64]; +} DNXHDContext; + +#define DNXHD_VLC_BITS 9 +#define DNXHD_DC_VLC_BITS 7 + +static void dnxhd_decode_dct_block_8(DNXHDContext *ctx, int16_t *block, int n, int qscale); +static void dnxhd_decode_dct_block_10(DNXHDContext *ctx, int16_t *block, int n, int qscale); + +static av_cold int dnxhd_decode_init(AVCodecContext *avctx) +{ + DNXHDContext *ctx = avctx->priv_data; + + ctx->avctx = avctx; + ctx->cid = -1; + return 0; +} + +static int dnxhd_init_vlc(DNXHDContext *ctx, uint32_t cid) +{ + if (cid != ctx->cid) { + int index; + + if ((index = ff_dnxhd_get_cid_table(cid)) < 0) { + av_log(ctx->avctx, AV_LOG_ERROR, "unsupported cid %d\n", cid); + return -1; + } + if (ff_dnxhd_cid_table[index].bit_depth != ctx->bit_depth) { + av_log(ctx->avctx, AV_LOG_ERROR, "bit depth mismatches %d %d\n", ff_dnxhd_cid_table[index].bit_depth, ctx->bit_depth); + return AVERROR_INVALIDDATA; + } + ctx->cid_table = &ff_dnxhd_cid_table[index]; + + ff_free_vlc(&ctx->ac_vlc); + ff_free_vlc(&ctx->dc_vlc); + ff_free_vlc(&ctx->run_vlc); + + init_vlc(&ctx->ac_vlc, DNXHD_VLC_BITS, 257, + ctx->cid_table->ac_bits, 1, 1, + ctx->cid_table->ac_codes, 2, 2, 0); + init_vlc(&ctx->dc_vlc, DNXHD_DC_VLC_BITS, ctx->bit_depth + 4, + ctx->cid_table->dc_bits, 1, 1, + ctx->cid_table->dc_codes, 1, 1, 0); + init_vlc(&ctx->run_vlc, DNXHD_VLC_BITS, 62, + ctx->cid_table->run_bits, 1, 1, + ctx->cid_table->run_codes, 2, 2, 0); + + ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, ff_zigzag_direct); + ctx->cid = cid; + } + return 0; +} + +static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, + const uint8_t *buf, int buf_size, int first_field) +{ + static const uint8_t header_prefix[] = { 0x00, 0x00, 0x02, 0x80, 0x01 }; + int i, cid; + + if (buf_size < 0x280) + return -1; + + if (memcmp(buf, header_prefix, 5)) { + av_log(ctx->avctx, AV_LOG_ERROR, "error in header\n"); + return -1; + } + if (buf[5] & 2) { /* interlaced */ + ctx->cur_field = buf[5] & 1; + frame->interlaced_frame = 1; + frame->top_field_first = first_field ^ ctx->cur_field; + av_log(ctx->avctx, AV_LOG_DEBUG, "interlaced %d, cur field %d\n", buf[5] & 3, ctx->cur_field); + } + + ctx->height = AV_RB16(buf + 0x18); + ctx->width = AV_RB16(buf + 0x1a); + + av_dlog(ctx->avctx, "width %d, height %d\n", ctx->width, ctx->height); + + if (buf[0x21] & 0x40) { + ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; + ctx->avctx->bits_per_raw_sample = 10; + if (ctx->bit_depth != 10) { + ff_dsputil_init(&ctx->dsp, ctx->avctx); + ctx->bit_depth = 10; + ctx->decode_dct_block = dnxhd_decode_dct_block_10; + } + } else { + ctx->avctx->pix_fmt = AV_PIX_FMT_YUV422P; + ctx->avctx->bits_per_raw_sample = 8; + if (ctx->bit_depth != 8) { + ff_dsputil_init(&ctx->dsp, ctx->avctx); + ctx->bit_depth = 8; + ctx->decode_dct_block = dnxhd_decode_dct_block_8; + } + } + + cid = AV_RB32(buf + 0x28); + av_dlog(ctx->avctx, "compression id %d\n", cid); + + if (dnxhd_init_vlc(ctx, cid) < 0) + return -1; + + if (buf_size < ctx->cid_table->coding_unit_size) { + av_log(ctx->avctx, AV_LOG_ERROR, "incorrect frame size\n"); + return -1; + } + + ctx->mb_width = ctx->width>>4; + ctx->mb_height = buf[0x16d]; + + av_dlog(ctx->avctx, "mb width %d, mb height %d\n", ctx->mb_width, ctx->mb_height); + + if ((ctx->height+15)>>4 == ctx->mb_height && frame->interlaced_frame) + ctx->height <<= 1; + + if (ctx->mb_height > 68 || + (ctx->mb_height << frame->interlaced_frame) > (ctx->height+15)>>4) { + av_log(ctx->avctx, AV_LOG_ERROR, "mb height too big: %d\n", ctx->mb_height); + return -1; + } + + for (i = 0; i < ctx->mb_height; i++) { + ctx->mb_scan_index[i] = AV_RB32(buf + 0x170 + (i<<2)); + av_dlog(ctx->avctx, "mb scan index %d\n", ctx->mb_scan_index[i]); + if (buf_size < ctx->mb_scan_index[i] + 0x280LL) { + av_log(ctx->avctx, AV_LOG_ERROR, "invalid mb scan index\n"); + return -1; + } + } + + return 0; +} + +static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx, + int16_t *block, int n, + int qscale, + int index_bits, + int level_bias, + int level_shift) +{ + 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; + } + + UPDATE_CACHE(bs, &ctx->gb); + GET_VLC(len, bs, &ctx->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1); + if (len) { + level = GET_CACHE(bs, &ctx->gb); + LAST_SKIP_BITS(bs, &ctx->gb, len); + sign = ~level >> 31; + level = (NEG_USR32(sign ^ level, len) ^ sign) - sign; + ctx->last_dc[component] += level; + } + block[0] = ctx->last_dc[component]; + + 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 (flags & 1) { + level += SHOW_UBITS(bs, &ctx->gb, index_bits) << 7; + SKIP_BITS(bs, &ctx->gb, index_bits); + } + + 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) { + av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i); + break; + } + + j = ctx->scantable.permutated[i]; + level *= scale[i]; + if (level_bias < 32 || weight_matrix[i] != level_bias) + level += level_bias; + level >>= level_shift; + + 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); +} + +static void dnxhd_decode_dct_block_8(DNXHDContext *ctx, int16_t *block, + int n, int qscale) +{ + dnxhd_decode_dct_block(ctx, block, n, qscale, 4, 32, 6); +} + +static void dnxhd_decode_dct_block_10(DNXHDContext *ctx, int16_t *block, + int n, int qscale) +{ + dnxhd_decode_dct_block(ctx, block, n, qscale, 6, 8, 4); +} + +static int dnxhd_decode_macroblock(DNXHDContext *ctx, AVFrame *frame, int x, int y) +{ + int shift1 = ctx->bit_depth == 10; + int dct_linesize_luma = frame->linesize[0]; + int dct_linesize_chroma = frame->linesize[1]; + uint8_t *dest_y, *dest_u, *dest_v; + int dct_y_offset, dct_x_offset; + int qscale, i; + + qscale = get_bits(&ctx->gb, 11); + skip_bits1(&ctx->gb); + + 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); + } + + if (frame->interlaced_frame) { + dct_linesize_luma <<= 1; + dct_linesize_chroma <<= 1; + } + + dest_y = frame->data[0] + ((y * dct_linesize_luma) << 4) + (x << (4 + shift1)); + dest_u = frame->data[1] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1)); + dest_v = frame->data[2] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1)); + + if (ctx->cur_field) { + dest_y += frame->linesize[0]; + dest_u += frame->linesize[1]; + dest_v += frame->linesize[2]; + } + + dct_y_offset = dct_linesize_luma << 3; + dct_x_offset = 8 << shift1; + ctx->dsp.idct_put(dest_y, dct_linesize_luma, ctx->blocks[0]); + ctx->dsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, ctx->blocks[1]); + ctx->dsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, ctx->blocks[4]); + ctx->dsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, ctx->blocks[5]); + + if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { + dct_y_offset = dct_linesize_chroma << 3; + ctx->dsp.idct_put(dest_u, dct_linesize_chroma, ctx->blocks[2]); + ctx->dsp.idct_put(dest_v, dct_linesize_chroma, ctx->blocks[3]); + ctx->dsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, ctx->blocks[6]); + ctx->dsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, ctx->blocks[7]); + } + + return 0; +} + +static int dnxhd_decode_macroblocks(DNXHDContext *ctx, AVFrame *frame, + const uint8_t *buf, int buf_size) +{ + int x, y; + for (y = 0; y < ctx->mb_height; y++) { + ctx->last_dc[0] = + ctx->last_dc[1] = + ctx->last_dc[2] = 1 << (ctx->bit_depth + 2); // for levels +2^(bitdepth-1) + init_get_bits(&ctx->gb, buf + ctx->mb_scan_index[y], (buf_size - ctx->mb_scan_index[y]) << 3); + for (x = 0; x < ctx->mb_width; x++) { + //START_TIMER; + dnxhd_decode_macroblock(ctx, frame, x, y); + //STOP_TIMER("decode macroblock"); + } + } + return 0; +} + +static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + DNXHDContext *ctx = avctx->priv_data; + ThreadFrame frame = { .f = data }; + AVFrame *picture = data; + int first_field = 1; + int ret; + + av_dlog(avctx, "frame size %d\n", buf_size); + + decode_coding_unit: + if (dnxhd_decode_header(ctx, picture, buf, buf_size, first_field) < 0) + return -1; + + if ((avctx->width || avctx->height) && + (ctx->width != avctx->width || ctx->height != avctx->height)) { + av_log(avctx, AV_LOG_WARNING, "frame size changed: %dx%d -> %dx%d\n", + avctx->width, avctx->height, ctx->width, ctx->height); + first_field = 1; + } + + if (av_image_check_size(ctx->width, ctx->height, 0, avctx)) + return -1; + avcodec_set_dimensions(avctx, ctx->width, ctx->height); + + if (first_field) { + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + picture->pict_type = AV_PICTURE_TYPE_I; + picture->key_frame = 1; + } + + dnxhd_decode_macroblocks(ctx, picture, buf + 0x280, buf_size - 0x280); + + if (first_field && picture->interlaced_frame) { + buf += ctx->cid_table->coding_unit_size; + buf_size -= ctx->cid_table->coding_unit_size; + first_field = 0; + goto decode_coding_unit; + } + + *got_frame = 1; + return avpkt->size; +} + +static av_cold int dnxhd_decode_close(AVCodecContext *avctx) +{ + DNXHDContext *ctx = avctx->priv_data; + + ff_free_vlc(&ctx->ac_vlc); + ff_free_vlc(&ctx->dc_vlc); + ff_free_vlc(&ctx->run_vlc); + return 0; +} + +AVCodec ff_dnxhd_decoder = { + .name = "dnxhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DNXHD, + .priv_data_size = sizeof(DNXHDContext), + .init = dnxhd_decode_init, + .close = dnxhd_decode_close, + .decode = dnxhd_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), +}; diff --git a/ffmpeg/libavcodec/dnxhdenc.c b/ffmpeg/libavcodec/dnxhdenc.c new file mode 100644 index 0000000..4b6ce2f --- /dev/null +++ b/ffmpeg/libavcodec/dnxhdenc.c @@ -0,0 +1,1054 @@ +/* + * VC3/DNxHD encoder + * Copyright (c) 2007 Baptiste Coudurier + * Copyright (c) 2011 MirriAd Ltd + * + * VC-3 encoder funded by the British Broadcasting Corporation + * 10 bit support added by MirriAd Ltd, Joseph Artsimovich + * + * 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 + */ + +//#define DEBUG +#define RC_VARIANCE 1 // use variance or ssd for fast rc + +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dsputil.h" +#include "internal.h" +#include "mpegvideo.h" +#include "dnxhdenc.h" +#include "internal.h" + +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +#define DNX10BIT_QMAT_SHIFT 18 // The largest value that will not lead to overflow for 10bit samples. + +static const AVOption options[]={ + {"nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, VE}, +{NULL} +}; + +static const AVClass class = { + .class_name = "dnxhd", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +#define LAMBDA_FRAC_BITS 10 + +static void dnxhd_8bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size) +{ + int i; + for (i = 0; i < 4; i++) { + block[0] = pixels[0]; block[1] = pixels[1]; + block[2] = pixels[2]; block[3] = pixels[3]; + block[4] = pixels[4]; block[5] = pixels[5]; + block[6] = pixels[6]; block[7] = pixels[7]; + pixels += line_size; + block += 8; + } + memcpy(block, block - 8, sizeof(*block) * 8); + memcpy(block + 8, block - 16, sizeof(*block) * 8); + memcpy(block + 16, block - 24, sizeof(*block) * 8); + memcpy(block + 24, block - 32, sizeof(*block) * 8); +} + +static av_always_inline void dnxhd_10bit_get_pixels_8x4_sym(int16_t *av_restrict block, const uint8_t *pixels, int line_size) +{ + int i; + const uint16_t* pixels16 = (const uint16_t*)pixels; + line_size >>= 1; + + for (i = 0; i < 4; i++) { + block[0] = pixels16[0]; block[1] = pixels16[1]; + block[2] = pixels16[2]; block[3] = pixels16[3]; + block[4] = pixels16[4]; block[5] = pixels16[5]; + block[6] = pixels16[6]; block[7] = pixels16[7]; + pixels16 += line_size; + block += 8; + } + memcpy(block, block - 8, sizeof(*block) * 8); + memcpy(block + 8, block - 16, sizeof(*block) * 8); + memcpy(block + 16, block - 24, sizeof(*block) * 8); + memcpy(block + 24, block - 32, sizeof(*block) * 8); +} + +static int dnxhd_10bit_dct_quantize(MpegEncContext *ctx, int16_t *block, + int n, int qscale, int *overflow) +{ + const uint8_t *scantable= ctx->intra_scantable.scantable; + const int *qmat = n<4 ? ctx->q_intra_matrix[qscale] : ctx->q_chroma_intra_matrix[qscale]; + int last_non_zero = 0; + int i; + + ctx->dsp.fdct(block); + + // Divide by 4 with rounding, to compensate scaling of DCT coefficients + block[0] = (block[0] + 2) >> 2; + + for (i = 1; i < 64; ++i) { + int j = scantable[i]; + int sign = block[j] >> 31; + int level = (block[j] ^ sign) - sign; + level = level * qmat[j] >> DNX10BIT_QMAT_SHIFT; + block[j] = (level ^ sign) - sign; + if (level) + last_non_zero = i; + } + + return last_non_zero; +} + +static int dnxhd_init_vlc(DNXHDEncContext *ctx) +{ + int i, j, level, run; + int max_level = 1<<(ctx->cid_table->bit_depth+2); + + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_codes, max_level*4*sizeof(*ctx->vlc_codes), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->vlc_bits, max_level*4*sizeof(*ctx->vlc_bits) , fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_codes, 63*2, fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->run_bits, 63, fail); + + ctx->vlc_codes += max_level*2; + ctx->vlc_bits += max_level*2; + for (level = -max_level; level < max_level; level++) { + for (run = 0; run < 2; run++) { + int index = (level<<1)|run; + int sign, offset = 0, alevel = level; + + MASK_ABS(sign, alevel); + if (alevel > 64) { + offset = (alevel-1)>>6; + alevel -= offset<<6; + } + for (j = 0; j < 257; j++) { + if (ctx->cid_table->ac_level[j] >> 1 == alevel && + (!offset || (ctx->cid_table->ac_flags[j] & 1) && offset) && + (!run || (ctx->cid_table->ac_flags[j] & 2) && run)) { + av_assert1(!ctx->vlc_codes[index]); + if (alevel) { + ctx->vlc_codes[index] = (ctx->cid_table->ac_codes[j]<<1)|(sign&1); + ctx->vlc_bits [index] = ctx->cid_table->ac_bits[j]+1; + } else { + ctx->vlc_codes[index] = ctx->cid_table->ac_codes[j]; + ctx->vlc_bits [index] = ctx->cid_table->ac_bits [j]; + } + break; + } + } + av_assert0(!alevel || j < 257); + if (offset) { + ctx->vlc_codes[index] = (ctx->vlc_codes[index]<cid_table->index_bits)|offset; + ctx->vlc_bits [index]+= ctx->cid_table->index_bits; + } + } + } + for (i = 0; i < 62; i++) { + int run = ctx->cid_table->run[i]; + av_assert0(run < 63); + ctx->run_codes[run] = ctx->cid_table->run_codes[i]; + ctx->run_bits [run] = ctx->cid_table->run_bits[i]; + } + return 0; + fail: + return -1; +} + +static int dnxhd_init_qmat(DNXHDEncContext *ctx, int lbias, int cbias) +{ + // init first elem to 1 to avoid div by 0 in convert_matrix + uint16_t weight_matrix[64] = {1,}; // convert_matrix needs uint16_t* + int qscale, i; + const uint8_t *luma_weight_table = ctx->cid_table->luma_weight; + const uint8_t *chroma_weight_table = ctx->cid_table->chroma_weight; + + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l, (ctx->m.avctx->qmax+1) * 64 * sizeof(int), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c, (ctx->m.avctx->qmax+1) * 64 * sizeof(int), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_l16, (ctx->m.avctx->qmax+1) * 64 * 2 * sizeof(uint16_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->qmatrix_c16, (ctx->m.avctx->qmax+1) * 64 * 2 * sizeof(uint16_t), fail); + + if (ctx->cid_table->bit_depth == 8) { + for (i = 1; i < 64; i++) { + int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]]; + weight_matrix[j] = ctx->cid_table->luma_weight[i]; + } + ff_convert_matrix(&ctx->m.dsp, ctx->qmatrix_l, ctx->qmatrix_l16, weight_matrix, + ctx->m.intra_quant_bias, 1, ctx->m.avctx->qmax, 1); + for (i = 1; i < 64; i++) { + int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]]; + weight_matrix[j] = ctx->cid_table->chroma_weight[i]; + } + ff_convert_matrix(&ctx->m.dsp, ctx->qmatrix_c, ctx->qmatrix_c16, weight_matrix, + ctx->m.intra_quant_bias, 1, ctx->m.avctx->qmax, 1); + + for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) { + for (i = 0; i < 64; i++) { + ctx->qmatrix_l [qscale] [i] <<= 2; ctx->qmatrix_c [qscale] [i] <<= 2; + ctx->qmatrix_l16[qscale][0][i] <<= 2; ctx->qmatrix_l16[qscale][1][i] <<= 2; + ctx->qmatrix_c16[qscale][0][i] <<= 2; ctx->qmatrix_c16[qscale][1][i] <<= 2; + } + } + } else { + // 10-bit + for (qscale = 1; qscale <= ctx->m.avctx->qmax; qscale++) { + for (i = 1; i < 64; i++) { + int j = ctx->m.dsp.idct_permutation[ff_zigzag_direct[i]]; + + // The quantization formula from the VC-3 standard is: + // quantized = sign(block[i]) * floor(abs(block[i]/s) * p / (qscale * weight_table[i])) + // Where p is 32 for 8-bit samples and 8 for 10-bit ones. + // The s factor compensates scaling of DCT coefficients done by the DCT routines, + // and therefore is not present in standard. It's 8 for 8-bit samples and 4 for 10-bit ones. + // We want values of ctx->qtmatrix_l and ctx->qtmatrix_r to be: + // ((1 << DNX10BIT_QMAT_SHIFT) * (p / s)) / (qscale * weight_table[i]) + // For 10-bit samples, p / s == 2 + ctx->qmatrix_l[qscale][j] = (1 << (DNX10BIT_QMAT_SHIFT + 1)) / (qscale * luma_weight_table[i]); + ctx->qmatrix_c[qscale][j] = (1 << (DNX10BIT_QMAT_SHIFT + 1)) / (qscale * chroma_weight_table[i]); + } + } + } + + ctx->m.q_chroma_intra_matrix16 = ctx->qmatrix_c16; + ctx->m.q_chroma_intra_matrix = ctx->qmatrix_c; + ctx->m.q_intra_matrix16 = ctx->qmatrix_l16; + ctx->m.q_intra_matrix = ctx->qmatrix_l; + + return 0; + fail: + return -1; +} + +static int dnxhd_init_rc(DNXHDEncContext *ctx) +{ + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_rc, 8160*ctx->m.avctx->qmax*sizeof(RCEntry), fail); + if (ctx->m.avctx->mb_decision != FF_MB_DECISION_RD) + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_cmp, ctx->m.mb_num*sizeof(RCCMPEntry), fail); + + ctx->frame_bits = (ctx->cid_table->coding_unit_size - 640 - 4 - ctx->min_padding) * 8; + ctx->qscale = 1; + ctx->lambda = 2<priv_data; + int i, index, bit_depth; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV422P: + bit_depth = 8; + break; + case AV_PIX_FMT_YUV422P10: + bit_depth = 10; + break; + default: + av_log(avctx, AV_LOG_ERROR, "pixel format is incompatible with DNxHD\n"); + return -1; + } + + ctx->cid = ff_dnxhd_find_cid(avctx, bit_depth); + if (!ctx->cid) { + av_log(avctx, AV_LOG_ERROR, "video parameters incompatible with DNxHD. Valid DNxHD profiles:\n"); + ff_dnxhd_print_profiles(avctx, AV_LOG_ERROR); + return -1; + } + av_log(avctx, AV_LOG_DEBUG, "cid %d\n", ctx->cid); + + index = ff_dnxhd_get_cid_table(ctx->cid); + av_assert0(index >= 0); + ctx->cid_table = &ff_dnxhd_cid_table[index]; + + ctx->m.avctx = avctx; + ctx->m.mb_intra = 1; + ctx->m.h263_aic = 1; + + avctx->bits_per_raw_sample = ctx->cid_table->bit_depth; + + ff_dct_common_init(&ctx->m); + ff_dct_encode_init(&ctx->m); + + if (!ctx->m.dct_quantize) + ctx->m.dct_quantize = ff_dct_quantize_c; + + if (ctx->cid_table->bit_depth == 10) { + ctx->m.dct_quantize = dnxhd_10bit_dct_quantize; + ctx->get_pixels_8x4_sym = dnxhd_10bit_get_pixels_8x4_sym; + ctx->block_width_l2 = 4; + } else { + ctx->get_pixels_8x4_sym = dnxhd_8bit_get_pixels_8x4_sym; + ctx->block_width_l2 = 3; + } + + if (ARCH_X86) + ff_dnxhdenc_init_x86(ctx); + + ctx->m.mb_height = (avctx->height + 15) / 16; + ctx->m.mb_width = (avctx->width + 15) / 16; + + if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) { + ctx->interlaced = 1; + ctx->m.mb_height /= 2; + } + + ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width; + + if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) + ctx->m.intra_quant_bias = avctx->intra_quant_bias; + if (dnxhd_init_qmat(ctx, ctx->m.intra_quant_bias, 0) < 0) // XXX tune lbias/cbias + return -1; + + // Avid Nitris hardware decoder requires a minimum amount of padding in the coding unit payload + if (ctx->nitris_compat) + ctx->min_padding = 1600; + + if (dnxhd_init_vlc(ctx) < 0) + return -1; + if (dnxhd_init_rc(ctx) < 0) + return -1; + + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_size, ctx->m.mb_height*sizeof(uint32_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->slice_offs, ctx->m.mb_height*sizeof(uint32_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_bits, ctx->m.mb_num *sizeof(uint16_t), fail); + FF_ALLOCZ_OR_GOTO(ctx->m.avctx, ctx->mb_qscale, ctx->m.mb_num *sizeof(uint8_t), fail); + + ctx->frame.key_frame = 1; + ctx->frame.pict_type = AV_PICTURE_TYPE_I; + ctx->m.avctx->coded_frame = &ctx->frame; + + if (avctx->thread_count > MAX_THREADS) { + av_log(avctx, AV_LOG_ERROR, "too many threads\n"); + return -1; + } + + ctx->thread[0] = ctx; + for (i = 1; i < avctx->thread_count; i++) { + ctx->thread[i] = av_malloc(sizeof(DNXHDEncContext)); + memcpy(ctx->thread[i], ctx, sizeof(DNXHDEncContext)); + } + + return 0; + fail: //for FF_ALLOCZ_OR_GOTO + return -1; +} + +static int dnxhd_write_header(AVCodecContext *avctx, uint8_t *buf) +{ + DNXHDEncContext *ctx = avctx->priv_data; + const uint8_t header_prefix[5] = { 0x00,0x00,0x02,0x80,0x01 }; + + memset(buf, 0, 640); + + memcpy(buf, header_prefix, 5); + buf[5] = ctx->interlaced ? ctx->cur_field+2 : 0x01; + buf[6] = 0x80; // crc flag off + buf[7] = 0xa0; // reserved + AV_WB16(buf + 0x18, avctx->height>>ctx->interlaced); // ALPF + AV_WB16(buf + 0x1a, avctx->width); // SPL + AV_WB16(buf + 0x1d, avctx->height>>ctx->interlaced); // NAL + + buf[0x21] = ctx->cid_table->bit_depth == 10 ? 0x58 : 0x38; + buf[0x22] = 0x88 + (ctx->interlaced<<2); + AV_WB32(buf + 0x28, ctx->cid); // CID + buf[0x2c] = ctx->interlaced ? 0 : 0x80; + + buf[0x5f] = 0x01; // UDL + + buf[0x167] = 0x02; // reserved + AV_WB16(buf + 0x16a, ctx->m.mb_height * 4 + 4); // MSIPS + buf[0x16d] = ctx->m.mb_height; // Ns + buf[0x16f] = 0x10; // reserved + + ctx->msip = buf + 0x170; + return 0; +} + +static av_always_inline void dnxhd_encode_dc(DNXHDEncContext *ctx, int diff) +{ + int nbits; + if (diff < 0) { + nbits = av_log2_16bit(-2*diff); + diff--; + } else { + nbits = av_log2_16bit(2*diff); + } + put_bits(&ctx->m.pb, ctx->cid_table->dc_bits[nbits] + nbits, + (ctx->cid_table->dc_codes[nbits]<m.last_dc[n]); + ctx->m.last_dc[n] = block[0]; + + for (i = 1; i <= last_index; i++) { + j = ctx->m.intra_scantable.permutated[i]; + slevel = block[j]; + if (slevel) { + int run_level = i - last_non_zero - 1; + int rlevel = (slevel<<1)|!!run_level; + put_bits(&ctx->m.pb, ctx->vlc_bits[rlevel], ctx->vlc_codes[rlevel]); + if (run_level) + put_bits(&ctx->m.pb, ctx->run_bits[run_level], ctx->run_codes[run_level]); + last_non_zero = i; + } + } + put_bits(&ctx->m.pb, ctx->vlc_bits[0], ctx->vlc_codes[0]); // EOB +} + +static av_always_inline void dnxhd_unquantize_c(DNXHDEncContext *ctx, int16_t *block, int n, int qscale, int last_index) +{ + const uint8_t *weight_matrix; + int level; + int i; + + weight_matrix = (n&2) ? ctx->cid_table->chroma_weight : ctx->cid_table->luma_weight; + + for (i = 1; i <= last_index; i++) { + int j = ctx->m.intra_scantable.permutated[i]; + level = block[j]; + if (level) { + if (level < 0) { + level = (1-2*level) * qscale * weight_matrix[i]; + if (ctx->cid_table->bit_depth == 10) { + if (weight_matrix[i] != 8) + level += 8; + level >>= 4; + } else { + if (weight_matrix[i] != 32) + level += 32; + level >>= 6; + } + level = -level; + } else { + level = (2*level+1) * qscale * weight_matrix[i]; + if (ctx->cid_table->bit_depth == 10) { + if (weight_matrix[i] != 8) + level += 8; + level >>= 4; + } else { + if (weight_matrix[i] != 32) + level += 32; + level >>= 6; + } + } + block[j] = level; + } + } +} + +static av_always_inline int dnxhd_ssd_block(int16_t *qblock, int16_t *block) +{ + int score = 0; + int i; + for (i = 0; i < 64; i++) + score += (block[i] - qblock[i]) * (block[i] - qblock[i]); + return score; +} + +static av_always_inline int dnxhd_calc_ac_bits(DNXHDEncContext *ctx, int16_t *block, int last_index) +{ + int last_non_zero = 0; + int bits = 0; + int i, j, level; + for (i = 1; i <= last_index; i++) { + j = ctx->m.intra_scantable.permutated[i]; + level = block[j]; + if (level) { + int run_level = i - last_non_zero - 1; + bits += ctx->vlc_bits[(level<<1)|!!run_level]+ctx->run_bits[run_level]; + last_non_zero = i; + } + } + return bits; +} + +static av_always_inline void dnxhd_get_blocks(DNXHDEncContext *ctx, int mb_x, int mb_y) +{ + const int bs = ctx->block_width_l2; + const int bw = 1 << bs; + const uint8_t *ptr_y = ctx->thread[0]->src[0] + ((mb_y << 4) * ctx->m.linesize) + (mb_x << bs+1); + const uint8_t *ptr_u = ctx->thread[0]->src[1] + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); + const uint8_t *ptr_v = ctx->thread[0]->src[2] + ((mb_y << 4) * ctx->m.uvlinesize) + (mb_x << bs); + DSPContext *dsp = &ctx->m.dsp; + + dsp->get_pixels(ctx->blocks[0], ptr_y, ctx->m.linesize); + dsp->get_pixels(ctx->blocks[1], ptr_y + bw, ctx->m.linesize); + dsp->get_pixels(ctx->blocks[2], ptr_u, ctx->m.uvlinesize); + dsp->get_pixels(ctx->blocks[3], ptr_v, ctx->m.uvlinesize); + + if (mb_y+1 == ctx->m.mb_height && ctx->m.avctx->height == 1080) { + if (ctx->interlaced) { + ctx->get_pixels_8x4_sym(ctx->blocks[4], ptr_y + ctx->dct_y_offset, ctx->m.linesize); + ctx->get_pixels_8x4_sym(ctx->blocks[5], ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize); + ctx->get_pixels_8x4_sym(ctx->blocks[6], ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize); + ctx->get_pixels_8x4_sym(ctx->blocks[7], ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize); + } else { + dsp->clear_block(ctx->blocks[4]); + dsp->clear_block(ctx->blocks[5]); + dsp->clear_block(ctx->blocks[6]); + dsp->clear_block(ctx->blocks[7]); + } + } else { + dsp->get_pixels(ctx->blocks[4], ptr_y + ctx->dct_y_offset, ctx->m.linesize); + dsp->get_pixels(ctx->blocks[5], ptr_y + ctx->dct_y_offset + bw, ctx->m.linesize); + dsp->get_pixels(ctx->blocks[6], ptr_u + ctx->dct_uv_offset, ctx->m.uvlinesize); + dsp->get_pixels(ctx->blocks[7], ptr_v + ctx->dct_uv_offset, ctx->m.uvlinesize); + } +} + +static av_always_inline int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i) +{ + const static uint8_t component[8]={0,0,1,2,0,0,1,2}; + return component[i]; +} + +static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +{ + DNXHDEncContext *ctx = avctx->priv_data; + int mb_y = jobnr, mb_x; + int qscale = ctx->qscale; + LOCAL_ALIGNED_16(int16_t, block, [64]); + ctx = ctx->thread[threadnr]; + + ctx->m.last_dc[0] = + ctx->m.last_dc[1] = + ctx->m.last_dc[2] = 1 << (ctx->cid_table->bit_depth + 2); + + for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) { + unsigned mb = mb_y * ctx->m.mb_width + mb_x; + int ssd = 0; + int ac_bits = 0; + int dc_bits = 0; + int i; + + dnxhd_get_blocks(ctx, mb_x, mb_y); + + for (i = 0; i < 8; i++) { + int16_t *src_block = ctx->blocks[i]; + int overflow, nbits, diff, last_index; + int n = dnxhd_switch_matrix(ctx, i); + + memcpy(block, src_block, 64*sizeof(*block)); + last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow); + ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index); + + diff = block[0] - ctx->m.last_dc[n]; + if (diff < 0) nbits = av_log2_16bit(-2*diff); + else nbits = av_log2_16bit( 2*diff); + + av_assert1(nbits < ctx->cid_table->bit_depth + 4); + dc_bits += ctx->cid_table->dc_bits[nbits] + nbits; + + ctx->m.last_dc[n] = block[0]; + + if (avctx->mb_decision == FF_MB_DECISION_RD || !RC_VARIANCE) { + dnxhd_unquantize_c(ctx, block, i, qscale, last_index); + ctx->m.dsp.idct(block); + ssd += dnxhd_ssd_block(block, src_block); + } + } + ctx->mb_rc[qscale][mb].ssd = ssd; + ctx->mb_rc[qscale][mb].bits = ac_bits+dc_bits+12+8*ctx->vlc_bits[0]; + } + return 0; +} + +static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +{ + DNXHDEncContext *ctx = avctx->priv_data; + int mb_y = jobnr, mb_x; + ctx = ctx->thread[threadnr]; + init_put_bits(&ctx->m.pb, (uint8_t *)arg + 640 + ctx->slice_offs[jobnr], ctx->slice_size[jobnr]); + + ctx->m.last_dc[0] = + ctx->m.last_dc[1] = + ctx->m.last_dc[2] = 1 << (ctx->cid_table->bit_depth + 2); + for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) { + unsigned mb = mb_y * ctx->m.mb_width + mb_x; + int qscale = ctx->mb_qscale[mb]; + int i; + + put_bits(&ctx->m.pb, 12, qscale<<1); + + dnxhd_get_blocks(ctx, mb_x, mb_y); + + for (i = 0; i < 8; i++) { + int16_t *block = ctx->blocks[i]; + int overflow, n = dnxhd_switch_matrix(ctx, i); + int last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow); + //START_TIMER; + dnxhd_encode_block(ctx, block, last_index, n); + //STOP_TIMER("encode_block"); + } + } + if (put_bits_count(&ctx->m.pb)&31) + put_bits(&ctx->m.pb, 32-(put_bits_count(&ctx->m.pb)&31), 0); + flush_put_bits(&ctx->m.pb); + return 0; +} + +static void dnxhd_setup_threads_slices(DNXHDEncContext *ctx) +{ + int mb_y, mb_x; + int offset = 0; + for (mb_y = 0; mb_y < ctx->m.mb_height; mb_y++) { + int thread_size; + ctx->slice_offs[mb_y] = offset; + ctx->slice_size[mb_y] = 0; + for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) { + unsigned mb = mb_y * ctx->m.mb_width + mb_x; + ctx->slice_size[mb_y] += ctx->mb_bits[mb]; + } + ctx->slice_size[mb_y] = (ctx->slice_size[mb_y]+31)&~31; + ctx->slice_size[mb_y] >>= 3; + thread_size = ctx->slice_size[mb_y]; + offset += thread_size; + } +} + +static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +{ + DNXHDEncContext *ctx = avctx->priv_data; + int mb_y = jobnr, mb_x, x, y; + int partial_last_row = (mb_y == ctx->m.mb_height - 1) && + ((avctx->height >> ctx->interlaced) & 0xF); + + ctx = ctx->thread[threadnr]; + if (ctx->cid_table->bit_depth == 8) { + uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y<<4) * ctx->m.linesize); + for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x, pix += 16) { + unsigned mb = mb_y * ctx->m.mb_width + mb_x; + int sum; + int varc; + + if (!partial_last_row && mb_x * 16 <= avctx->width - 16) { + sum = ctx->m.dsp.pix_sum(pix, ctx->m.linesize); + varc = ctx->m.dsp.pix_norm1(pix, ctx->m.linesize); + } else { + int bw = FFMIN(avctx->width - 16 * mb_x, 16); + int bh = FFMIN((avctx->height >> ctx->interlaced) - 16 * mb_y, 16); + sum = varc = 0; + for (y = 0; y < bh; y++) { + for (x = 0; x < bw; x++) { + uint8_t val = pix[x + y * ctx->m.linesize]; + sum += val; + varc += val * val; + } + } + } + varc = (varc - (((unsigned)sum * sum) >> 8) + 128) >> 8; + + ctx->mb_cmp[mb].value = varc; + ctx->mb_cmp[mb].mb = mb; + } + } else { // 10-bit + int const linesize = ctx->m.linesize >> 1; + for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x) { + uint16_t *pix = (uint16_t*)ctx->thread[0]->src[0] + ((mb_y << 4) * linesize) + (mb_x << 4); + unsigned mb = mb_y * ctx->m.mb_width + mb_x; + int sum = 0; + int sqsum = 0; + int mean, sqmean; + int i, j; + // Macroblocks are 16x16 pixels, unlike DCT blocks which are 8x8. + for (i = 0; i < 16; ++i) { + for (j = 0; j < 16; ++j) { + // Turn 16-bit pixels into 10-bit ones. + int const sample = (unsigned)pix[j] >> 6; + sum += sample; + sqsum += sample * sample; + // 2^10 * 2^10 * 16 * 16 = 2^28, which is less than INT_MAX + } + pix += linesize; + } + mean = sum >> 8; // 16*16 == 2^8 + sqmean = sqsum >> 8; + ctx->mb_cmp[mb].value = sqmean - mean * mean; + ctx->mb_cmp[mb].mb = mb; + } + } + return 0; +} + +static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx) +{ + int lambda, up_step, down_step; + int last_lower = INT_MAX, last_higher = 0; + int x, y, q; + + for (q = 1; q < avctx->qmax; q++) { + ctx->qscale = q; + avctx->execute2(avctx, dnxhd_calc_bits_thread, NULL, NULL, ctx->m.mb_height); + } + up_step = down_step = 2<lambda; + + for (;;) { + int bits = 0; + int end = 0; + if (lambda == last_higher) { + lambda++; + end = 1; // need to set final qscales/bits + } + for (y = 0; y < ctx->m.mb_height; y++) { + for (x = 0; x < ctx->m.mb_width; x++) { + unsigned min = UINT_MAX; + int qscale = 1; + int mb = y*ctx->m.mb_width+x; + for (q = 1; q < avctx->qmax; q++) { + unsigned score = ctx->mb_rc[q][mb].bits*lambda+ + ((unsigned)ctx->mb_rc[q][mb].ssd<mb_rc[qscale][mb].bits; + ctx->mb_qscale[mb] = qscale; + ctx->mb_bits[mb] = ctx->mb_rc[qscale][mb].bits; + } + bits = (bits+31)&~31; // padding + if (bits > ctx->frame_bits) + break; + } + //av_dlog(ctx->m.avctx, "lambda %d, up %u, down %u, bits %d, frame %d\n", + // lambda, last_higher, last_lower, bits, ctx->frame_bits); + if (end) { + if (bits > ctx->frame_bits) + return -1; + break; + } + if (bits < ctx->frame_bits) { + last_lower = FFMIN(lambda, last_lower); + if (last_higher != 0) + lambda = (lambda+last_higher)>>1; + else + lambda -= down_step; + down_step = FFMIN((int64_t)down_step*5, INT_MAX); + up_step = 1<>1; + else if ((int64_t)lambda + up_step > INT_MAX) + return -1; + else + lambda += up_step; + up_step = FFMIN((int64_t)up_step*5, INT_MAX); + down_step = 1<m.avctx, "out lambda %d\n", lambda); + ctx->lambda = lambda; + return 0; +} + +static int dnxhd_find_qscale(DNXHDEncContext *ctx) +{ + int bits = 0; + int up_step = 1; + int down_step = 1; + int last_higher = 0; + int last_lower = INT_MAX; + int qscale; + int x, y; + + qscale = ctx->qscale; + for (;;) { + bits = 0; + ctx->qscale = qscale; + // XXX avoid recalculating bits + ctx->m.avctx->execute2(ctx->m.avctx, dnxhd_calc_bits_thread, NULL, NULL, ctx->m.mb_height); + for (y = 0; y < ctx->m.mb_height; y++) { + for (x = 0; x < ctx->m.mb_width; x++) + bits += ctx->mb_rc[qscale][y*ctx->m.mb_width+x].bits; + bits = (bits+31)&~31; // padding + if (bits > ctx->frame_bits) + break; + } + //av_dlog(ctx->m.avctx, "%d, qscale %d, bits %d, frame %d, higher %d, lower %d\n", + // ctx->m.avctx->frame_number, qscale, bits, ctx->frame_bits, last_higher, last_lower); + if (bits < ctx->frame_bits) { + if (qscale == 1) + return 1; + if (last_higher == qscale - 1) { + qscale = last_higher; + break; + } + last_lower = FFMIN(qscale, last_lower); + if (last_higher != 0) + qscale = (qscale+last_higher)>>1; + else + qscale -= down_step++; + if (qscale < 1) + qscale = 1; + up_step = 1; + } else { + if (last_lower == qscale + 1) + break; + last_higher = FFMAX(qscale, last_higher); + if (last_lower != INT_MAX) + qscale = (qscale+last_lower)>>1; + else + qscale += up_step++; + down_step = 1; + if (qscale >= ctx->m.avctx->qmax) + return -1; + } + } + //av_dlog(ctx->m.avctx, "out qscale %d\n", qscale); + ctx->qscale = qscale; + return 0; +} + +#define BUCKET_BITS 8 +#define RADIX_PASSES 4 +#define NBUCKETS (1 << BUCKET_BITS) + +static inline int get_bucket(int value, int shift) +{ + value >>= shift; + value &= NBUCKETS - 1; + return NBUCKETS - 1 - value; +} + +static void radix_count(const RCCMPEntry *data, int size, int buckets[RADIX_PASSES][NBUCKETS]) +{ + int i, j; + memset(buckets, 0, sizeof(buckets[0][0]) * RADIX_PASSES * NBUCKETS); + for (i = 0; i < size; i++) { + int v = data[i].value; + for (j = 0; j < RADIX_PASSES; j++) { + buckets[j][get_bucket(v, 0)]++; + v >>= BUCKET_BITS; + } + av_assert1(!v); + } + for (j = 0; j < RADIX_PASSES; j++) { + int offset = size; + for (i = NBUCKETS - 1; i >= 0; i--) + buckets[j][i] = offset -= buckets[j][i]; + av_assert1(!buckets[j][0]); + } +} + +static void radix_sort_pass(RCCMPEntry *dst, const RCCMPEntry *data, int size, int buckets[NBUCKETS], int pass) +{ + int shift = pass * BUCKET_BITS; + int i; + for (i = 0; i < size; i++) { + int v = get_bucket(data[i].value, shift); + int pos = buckets[v]++; + dst[pos] = data[i]; + } +} + +static void radix_sort(RCCMPEntry *data, int size) +{ + int buckets[RADIX_PASSES][NBUCKETS]; + RCCMPEntry *tmp = av_malloc(sizeof(*tmp) * size); + radix_count(data, size, buckets); + radix_sort_pass(tmp, data, size, buckets[0], 0); + radix_sort_pass(data, tmp, size, buckets[1], 1); + if (buckets[2][NBUCKETS - 1] || buckets[3][NBUCKETS - 1]) { + radix_sort_pass(tmp, data, size, buckets[2], 2); + radix_sort_pass(data, tmp, size, buckets[3], 3); + } + av_free(tmp); +} + +static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx) +{ + int max_bits = 0; + int ret, x, y; + if ((ret = dnxhd_find_qscale(ctx)) < 0) + return -1; + for (y = 0; y < ctx->m.mb_height; y++) { + for (x = 0; x < ctx->m.mb_width; x++) { + int mb = y*ctx->m.mb_width+x; + int delta_bits; + ctx->mb_qscale[mb] = ctx->qscale; + ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale][mb].bits; + max_bits += ctx->mb_rc[ctx->qscale][mb].bits; + if (!RC_VARIANCE) { + delta_bits = ctx->mb_rc[ctx->qscale][mb].bits-ctx->mb_rc[ctx->qscale+1][mb].bits; + ctx->mb_cmp[mb].mb = mb; + ctx->mb_cmp[mb].value = delta_bits ? + ((ctx->mb_rc[ctx->qscale][mb].ssd-ctx->mb_rc[ctx->qscale+1][mb].ssd)*100)/delta_bits + : INT_MIN; //avoid increasing qscale + } + } + max_bits += 31; //worst padding + } + if (!ret) { + if (RC_VARIANCE) + avctx->execute2(avctx, dnxhd_mb_var_thread, NULL, NULL, ctx->m.mb_height); + radix_sort(ctx->mb_cmp, ctx->m.mb_num); + for (x = 0; x < ctx->m.mb_num && max_bits > ctx->frame_bits; x++) { + int mb = ctx->mb_cmp[x].mb; + max_bits -= ctx->mb_rc[ctx->qscale][mb].bits - ctx->mb_rc[ctx->qscale+1][mb].bits; + ctx->mb_qscale[mb] = ctx->qscale+1; + ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale+1][mb].bits; + } + } + return 0; +} + +static void dnxhd_load_picture(DNXHDEncContext *ctx, const AVFrame *frame) +{ + int i; + + for (i = 0; i < 3; i++) { + ctx->frame.data[i] = frame->data[i]; + ctx->frame.linesize[i] = frame->linesize[i]; + } + + for (i = 0; i < ctx->m.avctx->thread_count; i++) { + ctx->thread[i]->m.linesize = ctx->frame.linesize[0]<interlaced; + ctx->thread[i]->m.uvlinesize = ctx->frame.linesize[1]<interlaced; + ctx->thread[i]->dct_y_offset = ctx->m.linesize *8; + ctx->thread[i]->dct_uv_offset = ctx->m.uvlinesize*8; + } + + ctx->frame.interlaced_frame = frame->interlaced_frame; + ctx->cur_field = frame->interlaced_frame && !frame->top_field_first; +} + +static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + DNXHDEncContext *ctx = avctx->priv_data; + int first_field = 1; + int offset, i, ret; + uint8_t *buf; + + if ((ret = ff_alloc_packet2(avctx, pkt, ctx->cid_table->frame_size)) < 0) + return ret; + buf = pkt->data; + + dnxhd_load_picture(ctx, frame); + + encode_coding_unit: + for (i = 0; i < 3; i++) { + ctx->src[i] = ctx->frame.data[i]; + if (ctx->interlaced && ctx->cur_field) + ctx->src[i] += ctx->frame.linesize[i]; + } + + dnxhd_write_header(avctx, buf); + + if (avctx->mb_decision == FF_MB_DECISION_RD) + ret = dnxhd_encode_rdo(avctx, ctx); + else + ret = dnxhd_encode_fast(avctx, ctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "picture could not fit ratecontrol constraints, increase qmax\n"); + return -1; + } + + dnxhd_setup_threads_slices(ctx); + + offset = 0; + for (i = 0; i < ctx->m.mb_height; i++) { + AV_WB32(ctx->msip + i * 4, offset); + offset += ctx->slice_size[i]; + av_assert1(!(ctx->slice_size[i] & 3)); + } + + avctx->execute2(avctx, dnxhd_encode_thread, buf, NULL, ctx->m.mb_height); + + av_assert1(640 + offset + 4 <= ctx->cid_table->coding_unit_size); + memset(buf + 640 + offset, 0, ctx->cid_table->coding_unit_size - 4 - offset - 640); + + AV_WB32(buf + ctx->cid_table->coding_unit_size - 4, 0x600DC0DE); // EOF + + if (ctx->interlaced && first_field) { + first_field = 0; + ctx->cur_field ^= 1; + buf += ctx->cid_table->coding_unit_size; + goto encode_coding_unit; + } + + ctx->frame.quality = ctx->qscale*FF_QP2LAMBDA; + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static int dnxhd_encode_end(AVCodecContext *avctx) +{ + DNXHDEncContext *ctx = avctx->priv_data; + int max_level = 1<<(ctx->cid_table->bit_depth+2); + int i; + + av_free(ctx->vlc_codes-max_level*2); + av_free(ctx->vlc_bits -max_level*2); + av_freep(&ctx->run_codes); + av_freep(&ctx->run_bits); + + av_freep(&ctx->mb_bits); + av_freep(&ctx->mb_qscale); + av_freep(&ctx->mb_rc); + av_freep(&ctx->mb_cmp); + av_freep(&ctx->slice_size); + av_freep(&ctx->slice_offs); + + av_freep(&ctx->qmatrix_c); + av_freep(&ctx->qmatrix_l); + av_freep(&ctx->qmatrix_c16); + av_freep(&ctx->qmatrix_l16); + + for (i = 1; i < avctx->thread_count; i++) + av_freep(&ctx->thread[i]); + + return 0; +} + +static const AVCodecDefault dnxhd_defaults[] = { + { "qmax", "1024" }, /* Maximum quantization scale factor allowed for VC-3 */ + { NULL }, +}; + +AVCodec ff_dnxhd_encoder = { + .name = "dnxhd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DNXHD, + .priv_data_size = sizeof(DNXHDEncContext), + .init = dnxhd_encode_init, + .encode2 = dnxhd_encode_picture, + .close = dnxhd_encode_end, + .capabilities = CODEC_CAP_SLICE_THREADS, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), + .priv_class = &class, + .defaults = dnxhd_defaults, +}; diff --git a/ffmpeg/libavcodec/dnxhdenc.h b/ffmpeg/libavcodec/dnxhdenc.h new file mode 100644 index 0000000..9b59b96 --- /dev/null +++ b/ffmpeg/libavcodec/dnxhdenc.h @@ -0,0 +1,98 @@ +/* + * VC3/DNxHD encoder structure definitions and prototypes + * Copyright (c) 2007 Baptiste Coudurier + * + * VC-3 encoder funded by the British Broadcasting Corporation + * + * 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 + */ + +#ifndef AVCODEC_DNXHDENC_H +#define AVCODEC_DNXHDENC_H + +#include + +#include "mpegvideo.h" +#include "dnxhddata.h" + +typedef struct RCCMPEntry { + uint16_t mb; + int value; +} RCCMPEntry; + +typedef struct RCEntry { + int ssd; + int bits; +} RCEntry; + +typedef struct DNXHDEncContext { + AVClass *class; + MpegEncContext m; ///< Used for quantization dsp functions + + AVFrame frame; + int cid; + const CIDEntry *cid_table; + uint8_t *msip; ///< Macroblock Scan Indexes Payload + uint32_t *slice_size; + uint32_t *slice_offs; + + struct DNXHDEncContext *thread[MAX_THREADS]; + + // Because our samples are either 8 or 16 bits for 8-bit and 10-bit + // encoding respectively, these refer either to bytes or to two-byte words. + unsigned dct_y_offset; + unsigned dct_uv_offset; + unsigned block_width_l2; + + int interlaced; + int cur_field; + + int nitris_compat; + unsigned min_padding; + + DECLARE_ALIGNED(16, int16_t, blocks)[8][64]; + + int (*qmatrix_c) [64]; + int (*qmatrix_l) [64]; + uint16_t (*qmatrix_l16)[2][64]; + uint16_t (*qmatrix_c16)[2][64]; + + unsigned frame_bits; + uint8_t *src[3]; + + uint32_t *vlc_codes; + uint8_t *vlc_bits; + uint16_t *run_codes; + uint8_t *run_bits; + + /** Rate control */ + unsigned slice_bits; + unsigned qscale; + unsigned lambda; + + uint16_t *mb_bits; + uint8_t *mb_qscale; + + RCCMPEntry *mb_cmp; + RCEntry (*mb_rc)[8160]; + + void (*get_pixels_8x4_sym)(int16_t * /*align 16*/, const uint8_t *, int); +} DNXHDEncContext; + +void ff_dnxhdenc_init_x86(DNXHDEncContext *ctx); + +#endif /* AVCODEC_DNXHDENC_H */ diff --git a/ffmpeg/libavcodec/dpcm.c b/ffmpeg/libavcodec/dpcm.c new file mode 100644 index 0000000..402b0f9 --- /dev/null +++ b/ffmpeg/libavcodec/dpcm.c @@ -0,0 +1,343 @@ +/* + * Assorted DPCM codecs + * Copyright (c) 2003 The ffmpeg Project + * + * 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 + */ + +/** + * @file + * Assorted DPCM (differential pulse code modulation) audio codecs + * by Mike Melanson (melanson@pcisys.net) + * Xan DPCM decoder by Mario Brito (mbrito@student.dei.uc.pt) + * for more information on the specific data formats, visit: + * http://www.pcisys.net/~melanson/codecs/simpleaudio.html + * SOL DPCMs implemented by Konstantin Shishkov + * + * Note about using the Xan DPCM decoder: Xan DPCM is used in AVI files + * found in the Wing Commander IV computer game. These AVI files contain + * WAVEFORMAT headers which report the audio format as 0x01: raw PCM. + * Clearly incorrect. To detect Xan DPCM, you will probably have to + * special-case your AVI demuxer to use Xan DPCM if the file uses 'Xxan' + * (Xan video) for its video codec. Alternately, such AVI files also contain + * the fourcc 'Axan' in the 'auds' chunk of the AVI header. + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + +typedef struct DPCMContext { + int16_t roq_square_array[256]; + int sample[2]; ///< previous sample (for SOL_DPCM) + const int8_t *sol_table; ///< delta table for SOL_DPCM +} DPCMContext; + +static const int16_t interplay_delta_table[] = { + 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, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 47, 51, 56, 61, + 66, 72, 79, 86, 94, 102, 112, 122, + 133, 145, 158, 173, 189, 206, 225, 245, + 267, 292, 318, 348, 379, 414, 452, 493, + 538, 587, 640, 699, 763, 832, 908, 991, + 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, + 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008, + 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, + 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206, + 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, + -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1, + 1, 1, 5481, 10503, 15105, 19322, 23186, 26728, + 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298, + -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, + -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772, + -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, + -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180, + -1081, -991, -908, -832, -763, -699, -640, -587, + -538, -493, -452, -414, -379, -348, -318, -292, + -267, -245, -225, -206, -189, -173, -158, -145, + -133, -122, -112, -102, -94, -86, -79, -72, + -66, -61, -56, -51, -47, -43, -42, -41, + -40, -39, -38, -37, -36, -35, -34, -33, + -32, -31, -30, -29, -28, -27, -26, -25, + -24, -23, -22, -21, -20, -19, -18, -17, + -16, -15, -14, -13, -12, -11, -10, -9, + -8, -7, -6, -5, -4, -3, -2, -1 + +}; + +static const int8_t sol_table_old[16] = { + 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15, + -0x15, -0xF, -0xA, -0x6, -0x3, -0x2, -0x1, 0x0 +}; + +static const int8_t sol_table_new[16] = { + 0x0, 0x1, 0x2, 0x3, 0x6, 0xA, 0xF, 0x15, + 0x0, -0x1, -0x2, -0x3, -0x6, -0xA, -0xF, -0x15 +}; + +static const int16_t sol_table_16[128] = { + 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, + 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120, + 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, + 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, + 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280, + 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0, + 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, + 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370, + 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0, + 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480, + 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, + 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00, + 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 +}; + + +static av_cold int dpcm_decode_init(AVCodecContext *avctx) +{ + DPCMContext *s = avctx->priv_data; + int i; + + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + + s->sample[0] = s->sample[1] = 0; + + switch(avctx->codec->id) { + + case AV_CODEC_ID_ROQ_DPCM: + /* initialize square table */ + for (i = 0; i < 128; i++) { + int16_t square = i * i; + s->roq_square_array[i ] = square; + s->roq_square_array[i + 128] = -square; + } + break; + + case AV_CODEC_ID_SOL_DPCM: + switch(avctx->codec_tag){ + case 1: + s->sol_table = sol_table_old; + s->sample[0] = s->sample[1] = 0x80; + break; + case 2: + s->sol_table = sol_table_new; + s->sample[0] = s->sample[1] = 0x80; + break; + case 3: + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown SOL subcodec\n"); + return -1; + } + break; + + default: + break; + } + + if (avctx->codec->id == AV_CODEC_ID_SOL_DPCM && avctx->codec_tag != 3) + avctx->sample_fmt = AV_SAMPLE_FMT_U8; + else + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + + +static int dpcm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + int buf_size = avpkt->size; + DPCMContext *s = avctx->priv_data; + AVFrame *frame = data; + int out = 0, ret; + int predictor[2]; + int ch = 0; + int stereo = avctx->channels - 1; + int16_t *output_samples, *samples_end; + GetByteContext gb; + + if (stereo && (buf_size & 1)) + buf_size--; + bytestream2_init(&gb, avpkt->data, buf_size); + + /* calculate output size */ + switch(avctx->codec->id) { + case AV_CODEC_ID_ROQ_DPCM: + out = buf_size - 8; + break; + case AV_CODEC_ID_INTERPLAY_DPCM: + out = buf_size - 6 - avctx->channels; + break; + case AV_CODEC_ID_XAN_DPCM: + out = buf_size - 2 * avctx->channels; + break; + case AV_CODEC_ID_SOL_DPCM: + if (avctx->codec_tag != 3) + out = buf_size * 2; + else + out = buf_size; + break; + } + if (out <= 0) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + if (out % avctx->channels) { + av_log(avctx, AV_LOG_WARNING, "channels have differing number of samples\n"); + } + + /* get output buffer */ + frame->nb_samples = (out + avctx->channels - 1) / avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + output_samples = (int16_t *)frame->data[0]; + samples_end = output_samples + out; + + switch(avctx->codec->id) { + + case AV_CODEC_ID_ROQ_DPCM: + bytestream2_skipu(&gb, 6); + + if (stereo) { + predictor[1] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16); + predictor[0] = sign_extend(bytestream2_get_byteu(&gb) << 8, 16); + } else { + predictor[0] = sign_extend(bytestream2_get_le16u(&gb), 16); + } + + /* decode the samples */ + while (output_samples < samples_end) { + predictor[ch] += s->roq_square_array[bytestream2_get_byteu(&gb)]; + predictor[ch] = av_clip_int16(predictor[ch]); + *output_samples++ = predictor[ch]; + + /* toggle channel */ + ch ^= stereo; + } + break; + + case AV_CODEC_ID_INTERPLAY_DPCM: + bytestream2_skipu(&gb, 6); /* skip over the stream mask and stream length */ + + for (ch = 0; ch < avctx->channels; ch++) { + predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); + *output_samples++ = predictor[ch]; + } + + ch = 0; + while (output_samples < samples_end) { + predictor[ch] += interplay_delta_table[bytestream2_get_byteu(&gb)]; + predictor[ch] = av_clip_int16(predictor[ch]); + *output_samples++ = predictor[ch]; + + /* toggle channel */ + ch ^= stereo; + } + break; + + case AV_CODEC_ID_XAN_DPCM: + { + int shift[2] = { 4, 4 }; + + for (ch = 0; ch < avctx->channels; ch++) + predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); + + ch = 0; + while (output_samples < samples_end) { + int diff = bytestream2_get_byteu(&gb); + int n = diff & 3; + + if (n == 3) + shift[ch]++; + else + shift[ch] -= (2 * n); + diff = sign_extend((diff &~ 3) << 8, 16); + + /* saturate the shifter to a lower limit of 0 */ + if (shift[ch] < 0) + shift[ch] = 0; + + diff >>= shift[ch]; + predictor[ch] += diff; + + predictor[ch] = av_clip_int16(predictor[ch]); + *output_samples++ = predictor[ch]; + + /* toggle channel */ + ch ^= stereo; + } + break; + } + case AV_CODEC_ID_SOL_DPCM: + if (avctx->codec_tag != 3) { + uint8_t *output_samples_u8 = frame->data[0], + *samples_end_u8 = output_samples_u8 + out; + while (output_samples_u8 < samples_end_u8) { + int n = bytestream2_get_byteu(&gb); + + s->sample[0] += s->sol_table[n >> 4]; + s->sample[0] = av_clip_uint8(s->sample[0]); + *output_samples_u8++ = s->sample[0]; + + s->sample[stereo] += s->sol_table[n & 0x0F]; + s->sample[stereo] = av_clip_uint8(s->sample[stereo]); + *output_samples_u8++ = s->sample[stereo]; + } + } else { + while (output_samples < samples_end) { + int n = bytestream2_get_byteu(&gb); + if (n & 0x80) s->sample[ch] -= sol_table_16[n & 0x7F]; + else s->sample[ch] += sol_table_16[n & 0x7F]; + s->sample[ch] = av_clip_int16(s->sample[ch]); + *output_samples++ = s->sample[ch]; + /* toggle channel */ + ch ^= stereo; + } + } + break; + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +#define DPCM_DECODER(id_, name_, long_name_) \ +AVCodec ff_ ## name_ ## _decoder = { \ + .name = #name_, \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = id_, \ + .priv_data_size = sizeof(DPCMContext), \ + .init = dpcm_decode_init, \ + .decode = dpcm_decode_frame, \ + .capabilities = CODEC_CAP_DR1, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ +} + +DPCM_DECODER(AV_CODEC_ID_INTERPLAY_DPCM, interplay_dpcm, "DPCM Interplay"); +DPCM_DECODER(AV_CODEC_ID_ROQ_DPCM, roq_dpcm, "DPCM id RoQ"); +DPCM_DECODER(AV_CODEC_ID_SOL_DPCM, sol_dpcm, "DPCM Sol"); +DPCM_DECODER(AV_CODEC_ID_XAN_DPCM, xan_dpcm, "DPCM Xan"); diff --git a/ffmpeg/libavcodec/dpx.c b/ffmpeg/libavcodec/dpx.c new file mode 100644 index 0000000..0d60a7e --- /dev/null +++ b/ffmpeg/libavcodec/dpx.c @@ -0,0 +1,266 @@ +/* + * DPX (.dpx) image decoder + * Copyright (c) 2009 Jimmy Christensen + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "bytestream.h" +#include "avcodec.h" +#include "internal.h" + +static unsigned int read32(const uint8_t **ptr, int is_big) +{ + unsigned int temp; + if (is_big) { + temp = AV_RB32(*ptr); + } else { + temp = AV_RL32(*ptr); + } + *ptr += 4; + return temp; +} + +static uint16_t read10in32(const uint8_t **ptr, uint32_t * lbuf, + int * n_datum, int is_big) +{ + if (*n_datum) + (*n_datum)--; + else { + *lbuf = read32(ptr, is_big); + *n_datum = 2; + } + + *lbuf = (*lbuf << 10) | (*lbuf >> 22); + + return *lbuf & 0x3FF; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, + int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *const p = data; + uint8_t *ptr[AV_NUM_DATA_POINTERS]; + + unsigned int offset; + int magic_num, endian; + int x, y, i, ret; + int w, h, bits_per_color, descriptor, elements, packing, total_size; + + unsigned int rgbBuffer = 0; + int n_datum = 0; + + if (avpkt->size <= 1634) { + av_log(avctx, AV_LOG_ERROR, "Packet too small for DPX header\n"); + return AVERROR_INVALIDDATA; + } + + magic_num = AV_RB32(buf); + buf += 4; + + /* Check if the files "magic number" is "SDPX" which means it uses + * big-endian or XPDS which is for little-endian files */ + if (magic_num == AV_RL32("SDPX")) { + endian = 0; + } else if (magic_num == AV_RB32("SDPX")) { + endian = 1; + } else { + av_log(avctx, AV_LOG_ERROR, "DPX marker not found\n"); + return AVERROR_INVALIDDATA; + } + + offset = read32(&buf, endian); + if (avpkt->size <= offset) { + av_log(avctx, AV_LOG_ERROR, "Invalid data start offset\n"); + return AVERROR_INVALIDDATA; + } + // Need to end in 0x304 offset from start of file + buf = avpkt->data + 0x304; + w = read32(&buf, endian); + h = read32(&buf, endian); + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) + return ret; + + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + + // Need to end in 0x320 to read the descriptor + buf += 20; + descriptor = buf[0]; + + // Need to end in 0x323 to read the bits per color + buf += 3; + avctx->bits_per_raw_sample = + bits_per_color = buf[0]; + buf++; + packing = *((uint16_t*)buf); + + buf += 824; + avctx->sample_aspect_ratio.num = read32(&buf, endian); + avctx->sample_aspect_ratio.den = read32(&buf, endian); + if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) + av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den, + avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, + 0x10000); + else + avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + + switch (descriptor) { + case 51: // RGBA + elements = 4; + break; + case 50: // RGB + elements = 3; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported descriptor %d\n", descriptor); + return AVERROR_INVALIDDATA; + } + + switch (bits_per_color) { + case 8: + if (elements == 4) { + avctx->pix_fmt = AV_PIX_FMT_RGBA; + } else { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } + total_size = avctx->width * avctx->height * elements; + break; + case 10: + if (!packing) { + av_log(avctx, AV_LOG_ERROR, "Packing to 32bit required\n"); + return -1; + } + avctx->pix_fmt = AV_PIX_FMT_GBRP10; + total_size = (avctx->width * avctx->height * elements + 2) / 3 * 4; + break; + case 12: + if (!packing) { + av_log(avctx, AV_LOG_ERROR, "Packing to 16bit required\n"); + return -1; + } + if (endian) { + avctx->pix_fmt = AV_PIX_FMT_GBRP12BE; + } else { + avctx->pix_fmt = AV_PIX_FMT_GBRP12LE; + } + total_size = 2 * avctx->width * avctx->height * elements; + break; + case 16: + if (endian) { + avctx->pix_fmt = elements == 4 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGB48BE; + } else { + avctx->pix_fmt = elements == 4 ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGB48LE; + } + total_size = 2 * avctx->width * avctx->height * elements; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported color depth : %d\n", bits_per_color); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + // Move pointer to offset from start of file + buf = avpkt->data + offset; + + for (i=0; idata[i]; + + if (total_size + (int64_t)offset > avpkt->size) { + av_log(avctx, AV_LOG_ERROR, "Overread buffer. Invalid header?\n"); + return AVERROR_INVALIDDATA; + } + switch (bits_per_color) { + case 10: + for (x = 0; x < avctx->height; x++) { + uint16_t *dst[3] = {(uint16_t*)ptr[0], + (uint16_t*)ptr[1], + (uint16_t*)ptr[2]}; + for (y = 0; y < avctx->width; y++) { + *dst[2]++ = read10in32(&buf, &rgbBuffer, + &n_datum, endian); + *dst[0]++ = read10in32(&buf, &rgbBuffer, + &n_datum, endian); + *dst[1]++ = read10in32(&buf, &rgbBuffer, + &n_datum, endian); + // For 10 bit, ignore alpha + if (elements == 4) + read10in32(&buf, &rgbBuffer, + &n_datum, endian); + } + for (i = 0; i < 3; i++) + ptr[i] += p->linesize[i]; + } + break; + case 12: + for (x = 0; x < avctx->height; x++) { + uint16_t *dst[3] = {(uint16_t*)ptr[0], + (uint16_t*)ptr[1], + (uint16_t*)ptr[2]}; + for (y = 0; y < avctx->width; y++) { + *dst[2] = *((uint16_t*)buf); + *dst[2] = (*dst[2] >> 4) | (*dst[2] << 12); + dst[2]++; + buf += 2; + *dst[0] = *((uint16_t*)buf); + *dst[0] = (*dst[0] >> 4) | (*dst[0] << 12); + dst[0]++; + buf += 2; + *dst[1] = *((uint16_t*)buf); + *dst[1] = (*dst[1] >> 4) | (*dst[1] << 12); + dst[1]++; + buf += 2; + // For 12 bit, ignore alpha + if (elements == 4) + buf += 2; + } + for (i = 0; i < 3; i++) + ptr[i] += p->linesize[i]; + } + break; + case 16: + elements *= 2; + case 8: + for (x = 0; x < avctx->height; x++) { + memcpy(ptr[0], buf, elements*avctx->width); + ptr[0] += p->linesize[0]; + buf += elements*avctx->width; + } + break; + } + + *got_frame = 1; + + return buf_size; +} + +AVCodec ff_dpx_decoder = { + .name = "dpx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DPX, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("DPX image"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/dpxenc.c b/ffmpeg/libavcodec/dpxenc.c new file mode 100644 index 0000000..f210bbc --- /dev/null +++ b/ffmpeg/libavcodec/dpxenc.c @@ -0,0 +1,274 @@ +/* + * DPX (.dpx) image encoder + * Copyright (c) 2011 Peter Ross + * + * 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct DPXContext { + AVFrame picture; + int big_endian; + int bits_per_component; + int descriptor; + int planar; +} DPXContext; + +static av_cold int encode_init(AVCodecContext *avctx) +{ + DPXContext *s = avctx->priv_data; + + avctx->coded_frame = &s->picture; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; + + s->big_endian = 1; + s->bits_per_component = 8; + s->descriptor = 50; /* RGB */ + s->planar = 0; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGB24: + break; + case AV_PIX_FMT_RGBA: + s->descriptor = 51; /* RGBA */ + break; + case AV_PIX_FMT_RGB48LE: + s->big_endian = 0; + case AV_PIX_FMT_RGB48BE: + s->bits_per_component = avctx->bits_per_raw_sample ? avctx->bits_per_raw_sample : 16; + break; + case AV_PIX_FMT_RGBA64LE: + s->big_endian = 0; + case AV_PIX_FMT_RGBA64BE: + s->descriptor = 51; + s->bits_per_component = 16; + break; + case AV_PIX_FMT_GBRP10LE: + s->big_endian = 0; + case AV_PIX_FMT_GBRP10BE: + s->bits_per_component = 10; + s->planar = 1; + break; + case AV_PIX_FMT_GBRP12LE: + s->big_endian = 0; + case AV_PIX_FMT_GBRP12BE: + s->bits_per_component = 12; + s->planar = 1; + break; + default: + av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); + return -1; + } + + return 0; +} + +#define write16(p, value) \ +do { \ + if (s->big_endian) AV_WB16(p, value); \ + else AV_WL16(p, value); \ +} while(0) + +#define write32(p, value) \ +do { \ + if (s->big_endian) AV_WB32(p, value); \ + else AV_WL32(p, value); \ +} while(0) + +static void encode_rgb48_10bit(AVCodecContext *avctx, const AVPicture *pic, uint8_t *dst) +{ + DPXContext *s = avctx->priv_data; + const uint8_t *src = pic->data[0]; + int x, y; + + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) { + int value; + if (s->big_endian) { + value = ((AV_RB16(src + 6*x + 4) & 0xFFC0U) >> 4) + | ((AV_RB16(src + 6*x + 2) & 0xFFC0U) << 6) + | ((AV_RB16(src + 6*x + 0) & 0xFFC0U) << 16); + } else { + value = ((AV_RL16(src + 6*x + 4) & 0xFFC0U) >> 4) + | ((AV_RL16(src + 6*x + 2) & 0xFFC0U) << 6) + | ((AV_RL16(src + 6*x + 0) & 0xFFC0U) << 16); + } + write32(dst, value); + dst += 4; + } + src += pic->linesize[0]; + } +} + +static void encode_gbrp10(AVCodecContext *avctx, const AVPicture *pic, uint8_t *dst) +{ + DPXContext *s = avctx->priv_data; + const uint8_t *src[3] = {pic->data[0], pic->data[1], pic->data[2]}; + int x, y, i; + + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) { + int value; + if (s->big_endian) { + value = (AV_RB16(src[0] + 2*x) << 12) + | (AV_RB16(src[1] + 2*x) << 2) + | (AV_RB16(src[2] + 2*x) << 22); + } else { + value = (AV_RL16(src[0] + 2*x) << 12) + | (AV_RL16(src[1] + 2*x) << 2) + | (AV_RL16(src[2] + 2*x) << 22); + } + write32(dst, value); + dst += 4; + } + for (i = 0; i < 3; i++) + src[i] += pic->linesize[i]; + } +} + +static void encode_gbrp12(AVCodecContext *avctx, const AVPicture *pic, uint16_t *dst) +{ + DPXContext *s = avctx->priv_data; + const uint16_t *src[3] = {(uint16_t*)pic->data[0], + (uint16_t*)pic->data[1], + (uint16_t*)pic->data[2]}; + int x, y, i; + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) { + uint16_t value[3]; + if (s->big_endian) { + value[1] = AV_RB16(src[0] + x) << 4; + value[2] = AV_RB16(src[1] + x) << 4; + value[0] = AV_RB16(src[2] + x) << 4; + } else { + value[1] = AV_RL16(src[0] + x) << 4; + value[2] = AV_RL16(src[1] + x) << 4; + value[0] = AV_RL16(src[2] + x) << 4; + } + for (i = 0; i < 3; i++) + write16(dst++, value[i]); + } + for (i = 0; i < 3; i++) + src[i] += pic->linesize[i]/2; + } +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + DPXContext *s = avctx->priv_data; + int size, ret; + uint8_t *buf; + +#define HEADER_SIZE 1664 /* DPX Generic header */ + if (s->bits_per_component == 10) + size = avctx->height * avctx->width * 4; + else + size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + if ((ret = ff_alloc_packet2(avctx, pkt, size + HEADER_SIZE)) < 0) + return ret; + buf = pkt->data; + + memset(buf, 0, HEADER_SIZE); + + /* File information header */ + write32(buf, MKBETAG('S','D','P','X')); + write32(buf + 4, HEADER_SIZE); + memcpy (buf + 8, "V1.0", 4); + write32(buf + 20, 1); /* new image */ + write32(buf + 24, HEADER_SIZE); + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) + memcpy (buf + 160, LIBAVCODEC_IDENT, FFMIN(sizeof(LIBAVCODEC_IDENT), 100)); + write32(buf + 660, 0xFFFFFFFF); /* unencrypted */ + + /* Image information header */ + write16(buf + 768, 0); /* orientation; left to right, top to bottom */ + write16(buf + 770, 1); /* number of elements */ + write32(buf + 772, avctx->width); + write32(buf + 776, avctx->height); + buf[800] = s->descriptor; + buf[801] = 2; /* linear transfer */ + buf[802] = 2; /* linear colorimetric */ + buf[803] = s->bits_per_component; + write16(buf + 804, (s->bits_per_component == 10 || s->bits_per_component == 12) ? + 1 : 0); /* packing method */ + write32(buf + 808, HEADER_SIZE); /* data offset */ + + /* Image source information header */ + write32(buf + 1628, avctx->sample_aspect_ratio.num); + write32(buf + 1632, avctx->sample_aspect_ratio.den); + + switch(s->bits_per_component) { + case 8: + case 16: + size = avpicture_layout((const AVPicture*)frame, avctx->pix_fmt, + avctx->width, avctx->height, + buf + HEADER_SIZE, pkt->size - HEADER_SIZE); + if (size < 0) + return size; + break; + case 10: + if (s->planar) + encode_gbrp10(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); + else + encode_rgb48_10bit(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); + break; + case 12: + encode_gbrp12(avctx, (const AVPicture*)frame, (uint16_t*)(buf + HEADER_SIZE)); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); + return -1; + } + + size += HEADER_SIZE; + + write32(buf + 16, size); /* file size */ + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +AVCodec ff_dpx_encoder = { + .name = "dpx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DPX, + .priv_data_size = sizeof(DPXContext), + .init = encode_init, + .encode2 = encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, + AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGB48LE, + AV_PIX_FMT_RGB48BE, + AV_PIX_FMT_RGBA64LE, + AV_PIX_FMT_RGBA64BE, + AV_PIX_FMT_GBRP10LE, + AV_PIX_FMT_GBRP10BE, + AV_PIX_FMT_GBRP12LE, + AV_PIX_FMT_GBRP12BE, + AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("DPX image"), +}; diff --git a/ffmpeg/libavcodec/dsicinav.c b/ffmpeg/libavcodec/dsicinav.c new file mode 100644 index 0000000..f0e8f02 --- /dev/null +++ b/ffmpeg/libavcodec/dsicinav.c @@ -0,0 +1,409 @@ +/* + * Delphine Software International CIN Audio/Video Decoders + * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) + * + * 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 + */ + +/** + * @file + * Delphine Software International CIN audio/video decoders + */ + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + + +typedef enum CinVideoBitmapIndex { + CIN_CUR_BMP = 0, /* current */ + CIN_PRE_BMP = 1, /* previous */ + CIN_INT_BMP = 2 /* intermediate */ +} CinVideoBitmapIndex; + +typedef struct CinVideoContext { + AVCodecContext *avctx; + AVFrame frame; + unsigned int bitmap_size; + uint32_t palette[256]; + uint8_t *bitmap_table[3]; +} CinVideoContext; + +typedef struct CinAudioContext { + int initial_decode_frame; + int delta; +} CinAudioContext; + + +/* table defining a geometric sequence with multiplier = 32767 ^ (1 / 128) */ +static const int16_t cinaudio_delta16_table[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -30210, -27853, -25680, -23677, -21829, + -20126, -18556, -17108, -15774, -14543, -13408, -12362, -11398, + -10508, -9689, -8933, -8236, -7593, -7001, -6455, -5951, + -5487, -5059, -4664, -4300, -3964, -3655, -3370, -3107, + -2865, -2641, -2435, -2245, -2070, -1908, -1759, -1622, + -1495, -1379, -1271, -1172, -1080, -996, -918, -847, + -781, -720, -663, -612, -564, -520, -479, -442, + -407, -376, -346, -319, -294, -271, -250, -230, + -212, -196, -181, -166, -153, -141, -130, -120, + -111, -102, -94, -87, -80, -74, -68, -62, + -58, -53, -49, -45, -41, -38, -35, -32, + -30, -27, -25, -23, -21, -20, -18, -17, + -15, -14, -13, -12, -11, -10, -9, -8, + -7, -6, -5, -4, -3, -2, -1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 17, 18, 20, 21, 23, 25, 27, 30, + 32, 35, 38, 41, 45, 49, 53, 58, + 62, 68, 74, 80, 87, 94, 102, 111, + 120, 130, 141, 153, 166, 181, 196, 212, + 230, 250, 271, 294, 319, 346, 376, 407, + 442, 479, 520, 564, 612, 663, 720, 781, + 847, 918, 996, 1080, 1172, 1271, 1379, 1495, + 1622, 1759, 1908, 2070, 2245, 2435, 2641, 2865, + 3107, 3370, 3655, 3964, 4300, 4664, 5059, 5487, + 5951, 6455, 7001, 7593, 8236, 8933, 9689, 10508, + 11398, 12362, 13408, 14543, 15774, 17108, 18556, 20126, + 21829, 23677, 25680, 27853, 30210, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static av_cold void destroy_buffers(CinVideoContext *cin) +{ + int i; + + for (i = 0; i < 3; ++i) + av_freep(&cin->bitmap_table[i]); +} + +static av_cold int allocate_buffers(CinVideoContext *cin) +{ + int i; + + for (i = 0; i < 3; ++i) { + cin->bitmap_table[i] = av_mallocz(cin->bitmap_size); + if (!cin->bitmap_table[i]) { + av_log(cin->avctx, AV_LOG_ERROR, "Can't allocate bitmap buffers.\n"); + destroy_buffers(cin); + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static av_cold int cinvideo_decode_init(AVCodecContext *avctx) +{ + CinVideoContext *cin = avctx->priv_data; + + cin->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + avcodec_get_frame_defaults(&cin->frame); + + cin->bitmap_size = avctx->width * avctx->height; + if (allocate_buffers(cin)) + return AVERROR(ENOMEM); + + return 0; +} + +static void cin_apply_delta_data(const unsigned char *src, unsigned char *dst, int size) +{ + while (size--) + *dst++ += *src++; +} + +static int cin_decode_huffman(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) +{ + int b, huff_code = 0; + unsigned char huff_code_table[15]; + unsigned char *dst_cur = dst; + unsigned char *dst_end = dst + dst_size; + const unsigned char *src_end = src + src_size; + + memcpy(huff_code_table, src, 15); src += 15; + + while (src < src_end) { + huff_code = *src++; + if ((huff_code >> 4) == 15) { + b = huff_code << 4; + huff_code = *src++; + *dst_cur++ = b | (huff_code >> 4); + } else + *dst_cur++ = huff_code_table[huff_code >> 4]; + if (dst_cur >= dst_end) + break; + + huff_code &= 15; + if (huff_code == 15) { + *dst_cur++ = *src++; + } else + *dst_cur++ = huff_code_table[huff_code]; + if (dst_cur >= dst_end) + break; + } + + return dst_cur - dst; +} + +static int cin_decode_lzss(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) +{ + uint16_t cmd; + int i, sz, offset, code; + unsigned char *dst_end = dst + dst_size, *dst_start = dst; + const unsigned char *src_end = src + src_size; + + while (src < src_end && dst < dst_end) { + code = *src++; + for (i = 0; i < 8 && src < src_end && dst < dst_end; ++i) { + if (code & (1 << i)) { + *dst++ = *src++; + } else { + cmd = AV_RL16(src); src += 2; + offset = cmd >> 4; + if ((int) (dst - dst_start) < offset + 1) + return AVERROR_INVALIDDATA; + sz = (cmd & 0xF) + 2; + /* don't use memcpy/memmove here as the decoding routine (ab)uses */ + /* buffer overlappings to repeat bytes in the destination */ + sz = FFMIN(sz, dst_end - dst); + while (sz--) { + *dst = *(dst - offset - 1); + ++dst; + } + } + } + } + + return 0; +} + +static int cin_decode_rle(const unsigned char *src, int src_size, unsigned char *dst, int dst_size) +{ + int len, code; + unsigned char *dst_end = dst + dst_size; + const unsigned char *src_end = src + src_size; + + while (src + 1 < src_end && dst < dst_end) { + code = *src++; + if (code & 0x80) { + len = code - 0x7F; + memset(dst, *src++, FFMIN(len, dst_end - dst)); + } else { + len = code + 1; + if (len > src_end-src) { + av_log(NULL, AV_LOG_ERROR, "RLE overread\n"); + return AVERROR_INVALIDDATA; + } + memcpy(dst, src, FFMIN(len, dst_end - dst)); + src += len; + } + dst += len; + } + return 0; +} + +static int cinvideo_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + CinVideoContext *cin = avctx->priv_data; + int i, y, palette_type, palette_colors_count, bitmap_frame_type, bitmap_frame_size, res = 0; + + palette_type = buf[0]; + palette_colors_count = AV_RL16(buf+1); + bitmap_frame_type = buf[3]; + buf += 4; + + bitmap_frame_size = buf_size - 4; + + /* handle palette */ + if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0))) + return AVERROR_INVALIDDATA; + if (palette_type == 0) { + if (palette_colors_count > 256) + return AVERROR_INVALIDDATA; + for (i = 0; i < palette_colors_count; ++i) { + cin->palette[i] = 0xFFU << 24 | bytestream_get_le24(&buf); + bitmap_frame_size -= 3; + } + } else { + for (i = 0; i < palette_colors_count; ++i) { + cin->palette[buf[0]] = 0xFFU << 24 | AV_RL24(buf+1); + buf += 4; + bitmap_frame_size -= 4; + } + } + + /* note: the decoding routines below assumes that surface.width = surface.pitch */ + switch (bitmap_frame_type) { + case 9: + cin_decode_rle(buf, bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + break; + case 34: + cin_decode_rle(buf, bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + break; + case 35: + bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size, + cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); + cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + break; + case 36: + bitmap_frame_size = cin_decode_huffman(buf, bitmap_frame_size, + cin->bitmap_table[CIN_INT_BMP], cin->bitmap_size); + cin_decode_rle(cin->bitmap_table[CIN_INT_BMP], bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + break; + case 37: + cin_decode_huffman(buf, bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + break; + case 38: + res = cin_decode_lzss(buf, bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], + cin->bitmap_size); + if (res < 0) + return res; + break; + case 39: + res = cin_decode_lzss(buf, bitmap_frame_size, + cin->bitmap_table[CIN_CUR_BMP], + cin->bitmap_size); + if (res < 0) + return res; + cin_apply_delta_data(cin->bitmap_table[CIN_PRE_BMP], + cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_size); + break; + } + + if ((res = ff_reget_buffer(avctx, &cin->frame)) < 0) + return res; + + memcpy(cin->frame.data[1], cin->palette, sizeof(cin->palette)); + cin->frame.palette_has_changed = 1; + for (y = 0; y < cin->avctx->height; ++y) + memcpy(cin->frame.data[0] + (cin->avctx->height - 1 - y) * cin->frame.linesize[0], + cin->bitmap_table[CIN_CUR_BMP] + y * cin->avctx->width, + cin->avctx->width); + + FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]); + + if ((res = av_frame_ref(data, &cin->frame)) < 0) + return res; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int cinvideo_decode_end(AVCodecContext *avctx) +{ + CinVideoContext *cin = avctx->priv_data; + + av_frame_unref(&cin->frame); + + destroy_buffers(cin); + + return 0; +} + +static av_cold int cinaudio_decode_init(AVCodecContext *avctx) +{ + CinAudioContext *cin = avctx->priv_data; + + cin->initial_decode_frame = 1; + cin->delta = 0; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + + return 0; +} + +static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + CinAudioContext *cin = avctx->priv_data; + const uint8_t *buf_end = buf + avpkt->size; + int16_t *samples; + int delta, ret; + + /* get output buffer */ + frame->nb_samples = avpkt->size - cin->initial_decode_frame; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + + delta = cin->delta; + if (cin->initial_decode_frame) { + cin->initial_decode_frame = 0; + delta = sign_extend(AV_RL16(buf), 16); + buf += 2; + *samples++ = delta; + } + while (buf < buf_end) { + delta += cinaudio_delta16_table[*buf++]; + delta = av_clip_int16(delta); + *samples++ = delta; + } + cin->delta = delta; + + *got_frame_ptr = 1; + + return avpkt->size; +} + + +AVCodec ff_dsicinvideo_decoder = { + .name = "dsicinvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DSICINVIDEO, + .priv_data_size = sizeof(CinVideoContext), + .init = cinvideo_decode_init, + .close = cinvideo_decode_end, + .decode = cinvideo_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"), +}; + +AVCodec ff_dsicinaudio_decoder = { + .name = "dsicinaudio", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_DSICINAUDIO, + .priv_data_size = sizeof(CinAudioContext), + .init = cinaudio_decode_init, + .decode = cinaudio_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), +}; diff --git a/ffmpeg/libavcodec/dsputil.c b/ffmpeg/libavcodec/dsputil.c new file mode 100644 index 0000000..b56af0e --- /dev/null +++ b/ffmpeg/libavcodec/dsputil.c @@ -0,0 +1,2959 @@ +/* + * DSP utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * gmc & q-pel & 32/64 bit based MC 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 + */ + +/** + * @file + * DSP utils + */ + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "avcodec.h" +#include "copy_block.h" +#include "dct.h" +#include "dsputil.h" +#include "simple_idct.h" +#include "faandct.h" +#include "faanidct.h" +#include "imgconvert.h" +#include "mathops.h" +#include "mpegvideo.h" +#include "config.h" +#include "diracdsp.h" + +uint32_t ff_squareTbl[512] = {0, }; + +#define BIT_DEPTH 16 +#include "dsputil_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 8 +#include "dsputil_template.c" + +// 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size +#define pb_7f (~0UL/255 * 0x7f) +#define pb_80 (~0UL/255 * 0x80) + +/* Specific zigzag scan for 248 idct. NOTE that unlike the + specification, we interleave the fields */ +const uint8_t ff_zigzag248_direct[64] = { + 0, 8, 1, 9, 16, 24, 2, 10, + 17, 25, 32, 40, 48, 56, 33, 41, + 18, 26, 3, 11, 4, 12, 19, 27, + 34, 42, 49, 57, 50, 58, 35, 43, + 20, 28, 5, 13, 6, 14, 21, 29, + 36, 44, 51, 59, 52, 60, 37, 45, + 22, 30, 7, 15, 23, 31, 38, 46, + 53, 61, 54, 62, 39, 47, 55, 63, +}; + +/* not permutated inverse zigzag_direct + 1 for MMX quantizer */ +DECLARE_ALIGNED(16, uint16_t, ff_inv_zigzag_direct16)[64]; + +const uint8_t ff_alternate_horizontal_scan[64] = { + 0, 1, 2, 3, 8, 9, 16, 17, + 10, 11, 4, 5, 6, 7, 15, 14, + 13, 12, 19, 18, 24, 25, 32, 33, + 26, 27, 20, 21, 22, 23, 28, 29, + 30, 31, 34, 35, 40, 41, 48, 49, + 42, 43, 36, 37, 38, 39, 44, 45, + 46, 47, 50, 51, 56, 57, 58, 59, + 52, 53, 54, 55, 60, 61, 62, 63, +}; + +const uint8_t ff_alternate_vertical_scan[64] = { + 0, 8, 16, 24, 1, 9, 2, 10, + 17, 25, 32, 40, 48, 56, 57, 49, + 41, 33, 26, 18, 3, 11, 4, 12, + 19, 27, 34, 42, 50, 58, 35, 43, + 51, 59, 20, 28, 5, 13, 6, 14, + 21, 29, 36, 44, 52, 60, 37, 45, + 53, 61, 22, 30, 7, 15, 23, 31, + 38, 46, 54, 62, 39, 47, 55, 63, +}; + +/* Input permutation for the simple_idct_mmx */ +static const uint8_t simple_mmx_permutation[64]={ + 0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D, + 0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D, + 0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D, + 0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F, + 0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F, + 0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D, + 0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F, + 0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F, +}; + +static const uint8_t idct_sse2_row_perm[8] = {0, 4, 1, 5, 2, 6, 3, 7}; + +void ff_init_scantable(uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable){ + int i; + int end; + + st->scantable= src_scantable; + + for(i=0; i<64; i++){ + int j; + j = src_scantable[i]; + st->permutated[i] = permutation[j]; + } + + end=-1; + for(i=0; i<64; i++){ + int j; + j = st->permutated[i]; + if(j>end) end=j; + st->raster_end[i]= end; + } +} + +void ff_init_scantable_permutation(uint8_t *idct_permutation, + int idct_permutation_type) +{ + int i; + + switch(idct_permutation_type){ + case FF_NO_IDCT_PERM: + for(i=0; i<64; i++) + idct_permutation[i]= i; + break; + case FF_LIBMPEG2_IDCT_PERM: + for(i=0; i<64; i++) + idct_permutation[i]= (i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2); + break; + case FF_SIMPLE_IDCT_PERM: + for(i=0; i<64; i++) + idct_permutation[i]= simple_mmx_permutation[i]; + break; + case FF_TRANSPOSE_IDCT_PERM: + for(i=0; i<64; i++) + idct_permutation[i]= ((i&7)<<3) | (i>>3); + break; + case FF_PARTTRANS_IDCT_PERM: + for(i=0; i<64; i++) + idct_permutation[i]= (i&0x24) | ((i&3)<<3) | ((i>>3)&3); + break; + case FF_SSE2_IDCT_PERM: + for(i=0; i<64; i++) + idct_permutation[i]= (i&0x38) | idct_sse2_row_perm[i&7]; + break; + default: + av_log(NULL, AV_LOG_ERROR, "Internal error, IDCT permutation not set\n"); + } +} + +static int pix_sum_c(uint8_t * pix, int line_size) +{ + int s, i, j; + + s = 0; + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j += 8) { + s += pix[0]; + s += pix[1]; + s += pix[2]; + s += pix[3]; + s += pix[4]; + s += pix[5]; + s += pix[6]; + s += pix[7]; + pix += 8; + } + pix += line_size - 16; + } + return s; +} + +static int pix_norm1_c(uint8_t * pix, int line_size) +{ + int s, i, j; + uint32_t *sq = ff_squareTbl + 256; + + s = 0; + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j += 8) { +#if 0 + s += sq[pix[0]]; + s += sq[pix[1]]; + s += sq[pix[2]]; + s += sq[pix[3]]; + s += sq[pix[4]]; + s += sq[pix[5]]; + s += sq[pix[6]]; + s += sq[pix[7]]; +#else +#if HAVE_FAST_64BIT + register uint64_t x=*(uint64_t*)pix; + s += sq[x&0xff]; + s += sq[(x>>8)&0xff]; + s += sq[(x>>16)&0xff]; + s += sq[(x>>24)&0xff]; + s += sq[(x>>32)&0xff]; + s += sq[(x>>40)&0xff]; + s += sq[(x>>48)&0xff]; + s += sq[(x>>56)&0xff]; +#else + register uint32_t x=*(uint32_t*)pix; + s += sq[x&0xff]; + s += sq[(x>>8)&0xff]; + s += sq[(x>>16)&0xff]; + s += sq[(x>>24)&0xff]; + x=*(uint32_t*)(pix+4); + s += sq[x&0xff]; + s += sq[(x>>8)&0xff]; + s += sq[(x>>16)&0xff]; + s += sq[(x>>24)&0xff]; +#endif +#endif + pix += 8; + } + pix += line_size - 16; + } + return s; +} + +static void bswap_buf(uint32_t *dst, const uint32_t *src, int w){ + int i; + + for(i=0; i+8<=w; i+=8){ + dst[i+0]= av_bswap32(src[i+0]); + dst[i+1]= av_bswap32(src[i+1]); + dst[i+2]= av_bswap32(src[i+2]); + dst[i+3]= av_bswap32(src[i+3]); + dst[i+4]= av_bswap32(src[i+4]); + dst[i+5]= av_bswap32(src[i+5]); + dst[i+6]= av_bswap32(src[i+6]); + dst[i+7]= av_bswap32(src[i+7]); + } + for(;i 127) + *pixels = 255; + else + *pixels = (uint8_t)(*block + 128); + block++; + pixels++; + } + pixels += (line_size - 8); + } +} + +static void add_pixels8_c(uint8_t *av_restrict pixels, + int16_t *block, + int line_size) +{ + int i; + + for(i=0;i<8;i++) { + pixels[0] += block[0]; + pixels[1] += block[1]; + pixels[2] += block[2]; + pixels[3] += block[3]; + pixels[4] += block[4]; + pixels[5] += block[5]; + pixels[6] += block[6]; + pixels[7] += block[7]; + pixels += line_size; + block += 8; + } +} + +static void add_pixels_clamped_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<8;i++) { + pixels[0] = av_clip_uint8(pixels[0] + block[0]); + pixels[1] = av_clip_uint8(pixels[1] + block[1]); + pixels[2] = av_clip_uint8(pixels[2] + block[2]); + pixels[3] = av_clip_uint8(pixels[3] + block[3]); + pixels[4] = av_clip_uint8(pixels[4] + block[4]); + pixels[5] = av_clip_uint8(pixels[5] + block[5]); + pixels[6] = av_clip_uint8(pixels[6] + block[6]); + pixels[7] = av_clip_uint8(pixels[7] + block[7]); + pixels += line_size; + block += 8; + } +} + +static void add_pixels_clamped4_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<4;i++) { + pixels[0] = av_clip_uint8(pixels[0] + block[0]); + pixels[1] = av_clip_uint8(pixels[1] + block[1]); + pixels[2] = av_clip_uint8(pixels[2] + block[2]); + pixels[3] = av_clip_uint8(pixels[3] + block[3]); + pixels += line_size; + block += 8; + } +} + +static void add_pixels_clamped2_c(const int16_t *block, uint8_t *av_restrict pixels, + int line_size) +{ + int i; + + /* read the pixels */ + for(i=0;i<2;i++) { + pixels[0] = av_clip_uint8(pixels[0] + block[0]); + pixels[1] = av_clip_uint8(pixels[1] + block[1]); + pixels += line_size; + block += 8; + } +} + +static int sum_abs_dctelem_c(int16_t *block) +{ + int sum=0, i; + for(i=0; i<64; i++) + sum+= FFABS(block[i]); + return sum; +} + +static void fill_block16_c(uint8_t *block, uint8_t value, int line_size, int h) +{ + int i; + + for (i = 0; i < h; i++) { + memset(block, value, 16); + block += line_size; + } +} + +static void fill_block8_c(uint8_t *block, uint8_t value, int line_size, int h) +{ + int i; + + for (i = 0; i < h; i++) { + memset(block, value, 8); + block += line_size; + } +} + +#define avg2(a,b) ((a+b+1)>>1) +#define avg4(a,b,c,d) ((a+b+c+d+2)>>2) + +static void gmc1_c(uint8_t *dst, uint8_t *src, int stride, int h, int x16, int y16, int rounder) +{ + const int A=(16-x16)*(16-y16); + const int B=( x16)*(16-y16); + const int C=(16-x16)*( y16); + const int D=( x16)*( y16); + int i; + + for(i=0; i>8; + dst[1]= (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + rounder)>>8; + dst[2]= (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + rounder)>>8; + dst[3]= (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + rounder)>>8; + dst[4]= (A*src[4] + B*src[5] + C*src[stride+4] + D*src[stride+5] + rounder)>>8; + dst[5]= (A*src[5] + B*src[6] + C*src[stride+5] + D*src[stride+6] + rounder)>>8; + dst[6]= (A*src[6] + B*src[7] + C*src[stride+6] + D*src[stride+7] + rounder)>>8; + dst[7]= (A*src[7] + B*src[8] + C*src[stride+7] + D*src[stride+8] + rounder)>>8; + dst+= stride; + src+= stride; + } +} + +void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height) +{ + int y, vx, vy; + const int s= 1<>16; + src_y= vy>>16; + frac_x= src_x&(s-1); + frac_y= src_y&(s-1); + src_x>>=shift; + src_y>>=shift; + + if((unsigned)src_x < width){ + if((unsigned)src_y < height){ + index= src_x + src_y*stride; + dst[y*stride + x]= ( ( src[index ]*(s-frac_x) + + src[index +1]* frac_x )*(s-frac_y) + + ( src[index+stride ]*(s-frac_x) + + src[index+stride+1]* frac_x )* frac_y + + r)>>(shift*2); + }else{ + index= src_x + av_clip(src_y, 0, height)*stride; + dst[y*stride + x]= ( ( src[index ]*(s-frac_x) + + src[index +1]* frac_x )*s + + r)>>(shift*2); + } + }else{ + if((unsigned)src_y < height){ + index= av_clip(src_x, 0, width) + src_y*stride; + dst[y*stride + x]= ( ( src[index ]*(s-frac_y) + + src[index+stride ]* frac_y )*s + + r)>>(shift*2); + }else{ + index= av_clip(src_x, 0, width) + av_clip(src_y, 0, height)*stride; + dst[y*stride + x]= src[index ]; + } + } + + vx+= dxx; + vy+= dyx; + } + ox += dxy; + oy += dyy; + } +} + +static inline void put_tpel_pixels_mc00_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + switch(width){ + case 2: put_pixels2_8_c (dst, src, stride, height); break; + case 4: put_pixels4_8_c (dst, src, stride, height); break; + case 8: put_pixels8_8_c (dst, src, stride, height); break; + case 16:put_pixels16_8_c(dst, src, stride, height); break; + } +} + +static inline void put_tpel_pixels_mc10_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (683*(2*src[j] + src[j+1] + 1)) >> 11; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc20_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (683*(src[j] + 2*src[j+1] + 1)) >> 11; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc01_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (683*(2*src[j] + src[j+stride] + 1)) >> 11; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc11_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (2731*(4*src[j] + 3*src[j+1] + 3*src[j+stride] + 2*src[j+stride+1] + 6)) >> 15; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc12_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (2731*(3*src[j] + 2*src[j+1] + 4*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc02_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (683*(src[j] + 2*src[j+stride] + 1)) >> 11; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc21_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (2731*(3*src[j] + 4*src[j+1] + 2*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15; + } + src += stride; + dst += stride; + } +} + +static inline void put_tpel_pixels_mc22_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (2731*(2*src[j] + 3*src[j+1] + 3*src[j+stride] + 4*src[j+stride+1] + 6)) >> 15; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc00_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + switch(width){ + case 2: avg_pixels2_8_c (dst, src, stride, height); break; + case 4: avg_pixels4_8_c (dst, src, stride, height); break; + case 8: avg_pixels8_8_c (dst, src, stride, height); break; + case 16:avg_pixels16_8_c(dst, src, stride, height); break; + } +} + +static inline void avg_tpel_pixels_mc10_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((683*(2*src[j] + src[j+1] + 1)) >> 11) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc20_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((683*(src[j] + 2*src[j+1] + 1)) >> 11) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc01_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((683*(2*src[j] + src[j+stride] + 1)) >> 11) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc11_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((2731*(4*src[j] + 3*src[j+1] + 3*src[j+stride] + 2*src[j+stride+1] + 6)) >> 15) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc12_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((2731*(3*src[j] + 2*src[j+1] + 4*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc02_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((683*(src[j] + 2*src[j+stride] + 1)) >> 11) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc21_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((2731*(3*src[j] + 4*src[j+1] + 2*src[j+stride] + 3*src[j+stride+1] + 6)) >> 15) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +static inline void avg_tpel_pixels_mc22_c(uint8_t *dst, const uint8_t *src, int stride, int width, int height){ + int i,j; + for (i=0; i < height; i++) { + for (j=0; j < width; j++) { + dst[j] = (dst[j] + ((2731*(2*src[j] + 3*src[j+1] + 3*src[j+stride] + 4*src[j+stride+1] + 6)) >> 15) + 1) >> 1; + } + src += stride; + dst += stride; + } +} + +#define QPEL_MC(r, OPNAME, RND, OP) \ +static void OPNAME ## mpeg4_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i=0; i>5]+1)>>1) +#define op_avg_no_rnd(a, b) a = (((a)+cm[((b) + 15)>>5])>>1) +#define op_put(a, b) a = cm[((b) + 16)>>5] +#define op_put_no_rnd(a, b) a = cm[((b) + 15)>>5] + +QPEL_MC(0, put_ , _ , op_put) +QPEL_MC(1, put_no_rnd_, _no_rnd_, op_put_no_rnd) +QPEL_MC(0, avg_ , _ , op_avg) +//QPEL_MC(1, avg_no_rnd , _ , op_avg) +#undef op_avg +#undef op_avg_no_rnd +#undef op_put +#undef op_put_no_rnd + +void ff_put_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels8_8_c(dst, src, stride, 8); +} +void ff_avg_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels8_8_c(dst, src, stride, 8); +} +void ff_put_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels16_8_c(dst, src, stride, 16); +} +void ff_avg_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels16_8_c(dst, src, stride, 16); +} + +#define put_qpel8_mc00_c ff_put_pixels8x8_c +#define avg_qpel8_mc00_c ff_avg_pixels8x8_c +#define put_qpel16_mc00_c ff_put_pixels16x16_c +#define avg_qpel16_mc00_c ff_avg_pixels16x16_c +#define put_no_rnd_qpel8_mc00_c ff_put_pixels8x8_c +#define put_no_rnd_qpel16_mc00_c ff_put_pixels16x16_c + +static void wmv2_mspel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int i; + + for(i=0; i>4]; + dst[1]= cm[(9*(src[1] + src[2]) - (src[ 0] + src[3]) + 8)>>4]; + dst[2]= cm[(9*(src[2] + src[3]) - (src[ 1] + src[4]) + 8)>>4]; + dst[3]= cm[(9*(src[3] + src[4]) - (src[ 2] + src[5]) + 8)>>4]; + dst[4]= cm[(9*(src[4] + src[5]) - (src[ 3] + src[6]) + 8)>>4]; + dst[5]= cm[(9*(src[5] + src[6]) - (src[ 4] + src[7]) + 8)>>4]; + dst[6]= cm[(9*(src[6] + src[7]) - (src[ 5] + src[8]) + 8)>>4]; + dst[7]= cm[(9*(src[7] + src[8]) - (src[ 6] + src[9]) + 8)>>4]; + dst+=dstStride; + src+=srcStride; + } +} + +#if CONFIG_RV40_DECODER +void ff_put_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels16_xy2_8_c(dst, src, stride, 16); +} +void ff_avg_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels16_xy2_8_c(dst, src, stride, 16); +} +void ff_put_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels8_xy2_8_c(dst, src, stride, 8); +} +void ff_avg_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels8_xy2_8_c(dst, src, stride, 8); +} +#endif /* CONFIG_RV40_DECODER */ + +#if CONFIG_DIRAC_DECODER +#define DIRAC_MC(OPNAME)\ +void ff_ ## OPNAME ## _dirac_pixels8_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels8_8_c(dst, src[0], stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels16_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_8_c(dst, src[0], stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels32_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_8_c(dst , src[0] , stride, h);\ + OPNAME ## _pixels16_8_c(dst+16, src[0]+16, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels8_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels8_l2_8(dst, src[0], src[1], stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels16_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l2_8(dst, src[0], src[1], stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels32_l2_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l2_8(dst , src[0] , src[1] , stride, stride, stride, h);\ + OPNAME ## _pixels16_l2_8(dst+16, src[0]+16, src[1]+16, stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels8_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels8_l4_8(dst, src[0], src[1], src[2], src[3], stride, stride, stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels16_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l4_8(dst, src[0], src[1], src[2], src[3], stride, stride, stride, stride, stride, h);\ +}\ +void ff_ ## OPNAME ## _dirac_pixels32_l4_c(uint8_t *dst, const uint8_t *src[5], int stride, int h)\ +{\ + OPNAME ## _pixels16_l4_8(dst , src[0] , src[1] , src[2] , src[3] , stride, stride, stride, stride, stride, h);\ + OPNAME ## _pixels16_l4_8(dst+16, src[0]+16, src[1]+16, src[2]+16, src[3]+16, stride, stride, stride, stride, stride, h);\ +} +DIRAC_MC(put) +DIRAC_MC(avg) +#endif + +static void wmv2_mspel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int w){ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int i; + + for(i=0; i>4]; + dst[1*dstStride]= cm[(9*(src1 + src2) - (src0 + src3) + 8)>>4]; + dst[2*dstStride]= cm[(9*(src2 + src3) - (src1 + src4) + 8)>>4]; + dst[3*dstStride]= cm[(9*(src3 + src4) - (src2 + src5) + 8)>>4]; + dst[4*dstStride]= cm[(9*(src4 + src5) - (src3 + src6) + 8)>>4]; + dst[5*dstStride]= cm[(9*(src5 + src6) - (src4 + src7) + 8)>>4]; + dst[6*dstStride]= cm[(9*(src6 + src7) - (src5 + src8) + 8)>>4]; + dst[7*dstStride]= cm[(9*(src7 + src8) - (src6 + src9) + 8)>>4]; + src++; + dst++; + } +} + +static void put_mspel8_mc10_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t half[64]; + wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); + put_pixels8_l2_8(dst, src, half, stride, stride, 8, 8); +} + +static void put_mspel8_mc20_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8); +} + +static void put_mspel8_mc30_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t half[64]; + wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); + put_pixels8_l2_8(dst, src+1, half, stride, stride, 8, 8); +} + +static void put_mspel8_mc02_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8); +} + +static void put_mspel8_mc12_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t halfH[88]; + uint8_t halfV[64]; + uint8_t halfHV[64]; + wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(halfV, src, 8, stride, 8); + wmv2_mspel8_v_lowpass(halfHV, halfH+8, 8, 8, 8); + put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); +} +static void put_mspel8_mc32_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t halfH[88]; + uint8_t halfV[64]; + uint8_t halfHV[64]; + wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(halfV, src+1, 8, stride, 8); + wmv2_mspel8_v_lowpass(halfHV, halfH+8, 8, 8, 8); + put_pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8); +} +static void put_mspel8_mc22_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + uint8_t halfH[88]; + wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(dst, halfH+8, stride, 8, 8); +} + +static void h263_v_loop_filter_c(uint8_t *src, int stride, int qscale){ + if(CONFIG_H263_DECODER || CONFIG_H263_ENCODER) { + int x; + const int strength= ff_h263_loop_filter_strength[qscale]; + + for(x=0; x<8; x++){ + int d1, d2, ad1; + int p0= src[x-2*stride]; + int p1= src[x-1*stride]; + int p2= src[x+0*stride]; + int p3= src[x+1*stride]; + int d = (p0 - p3 + 4*(p2 - p1)) / 8; + + if (d<-2*strength) d1= 0; + else if(d<- strength) d1=-2*strength - d; + else if(d< strength) d1= d; + else if(d< 2*strength) d1= 2*strength - d; + else d1= 0; + + p1 += d1; + p2 -= d1; + if(p1&256) p1= ~(p1>>31); + if(p2&256) p2= ~(p2>>31); + + src[x-1*stride] = p1; + src[x+0*stride] = p2; + + ad1= FFABS(d1)>>1; + + d2= av_clip((p0-p3)/4, -ad1, ad1); + + src[x-2*stride] = p0 - d2; + src[x+ stride] = p3 + d2; + } + } +} + +static void h263_h_loop_filter_c(uint8_t *src, int stride, int qscale){ + if(CONFIG_H263_DECODER || CONFIG_H263_ENCODER) { + int y; + const int strength= ff_h263_loop_filter_strength[qscale]; + + for(y=0; y<8; y++){ + int d1, d2, ad1; + int p0= src[y*stride-2]; + int p1= src[y*stride-1]; + int p2= src[y*stride+0]; + int p3= src[y*stride+1]; + int d = (p0 - p3 + 4*(p2 - p1)) / 8; + + if (d<-2*strength) d1= 0; + else if(d<- strength) d1=-2*strength - d; + else if(d< strength) d1= d; + else if(d< 2*strength) d1= 2*strength - d; + else d1= 0; + + p1 += d1; + p2 -= d1; + if(p1&256) p1= ~(p1>>31); + if(p2&256) p2= ~(p2>>31); + + src[y*stride-1] = p1; + src[y*stride+0] = p2; + + ad1= FFABS(d1)>>1; + + d2= av_clip((p0-p3)/4, -ad1, ad1); + + src[y*stride-2] = p0 - d2; + src[y*stride+1] = p3 + d2; + } + } +} + +static void h261_loop_filter_c(uint8_t *src, int stride){ + int x,y,xy,yz; + int temp[64]; + + for(x=0; x<8; x++){ + temp[x ] = 4*src[x ]; + temp[x + 7*8] = 4*src[x + 7*stride]; + } + for(y=1; y<7; y++){ + for(x=0; x<8; x++){ + xy = y * stride + x; + yz = y * 8 + x; + temp[yz] = src[xy - stride] + 2*src[xy] + src[xy + stride]; + } + } + + for(y=0; y<8; y++){ + src[ y*stride] = (temp[ y*8] + 2)>>2; + src[7+y*stride] = (temp[7+y*8] + 2)>>2; + for(x=1; x<7; x++){ + xy = y * stride + x; + yz = y * 8 + x; + src[xy] = (temp[yz-1] + 2*temp[yz] + temp[yz+1] + 8)>>4; + } + } +} + +static inline int pix_abs16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int s, i; + + s = 0; + for(i=0;iavctx->nsse_weight; + else return score1 + FFABS(score2)*8; +} + +static int nsse8_c(void *v, uint8_t *s1, uint8_t *s2, int stride, int h){ + MpegEncContext *c = v; + int score1=0; + int score2=0; + int x,y; + + for(y=0; yavctx->nsse_weight; + else return score1 + FFABS(score2)*8; +} + +static int try_8x8basis_c(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){ + int i; + unsigned int sum=0; + + for(i=0; i<8*8; i++){ + int b= rem[i] + ((basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT)); + int w= weight[i]; + b>>= RECON_SHIFT; + av_assert2(-512>4; + } + return sum>>2; +} + +static void add_8x8basis_c(int16_t rem[64], int16_t basis[64], int scale){ + int i; + + for(i=0; i<8*8; i++){ + rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT); + } +} + +static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){ + return 0; +} + +void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type){ + int i; + + memset(cmp, 0, sizeof(void*)*6); + + for(i=0; i<6; i++){ + switch(type&0xFF){ + case FF_CMP_SAD: + cmp[i]= c->sad[i]; + break; + case FF_CMP_SATD: + cmp[i]= c->hadamard8_diff[i]; + break; + case FF_CMP_SSE: + cmp[i]= c->sse[i]; + break; + case FF_CMP_DCT: + cmp[i]= c->dct_sad[i]; + break; + case FF_CMP_DCT264: + cmp[i]= c->dct264_sad[i]; + break; + case FF_CMP_DCTMAX: + cmp[i]= c->dct_max[i]; + break; + case FF_CMP_PSNR: + cmp[i]= c->quant_psnr[i]; + break; + case FF_CMP_BIT: + cmp[i]= c->bit[i]; + break; + case FF_CMP_RD: + cmp[i]= c->rd[i]; + break; + case FF_CMP_VSAD: + cmp[i]= c->vsad[i]; + break; + case FF_CMP_VSSE: + cmp[i]= c->vsse[i]; + break; + case FF_CMP_ZERO: + cmp[i]= zero_cmp; + break; + case FF_CMP_NSSE: + cmp[i]= c->nsse[i]; + break; +#if CONFIG_DWT + case FF_CMP_W53: + cmp[i]= c->w53[i]; + break; + case FF_CMP_W97: + cmp[i]= c->w97[i]; + break; +#endif + default: + av_log(NULL, AV_LOG_ERROR,"internal error in cmp function selection\n"); + } + } +} + +static void add_bytes_c(uint8_t *dst, uint8_t *src, int w){ + long i; + for(i=0; i<=w-sizeof(long); i+=sizeof(long)){ + long a = *(long*)(src+i); + long b = *(long*)(dst+i); + *(long*)(dst+i) = ((a&pb_7f) + (b&pb_7f)) ^ ((a^b)&pb_80); + } + for(; idsp.diff_pixels(temp, src1, src2, stride); + s->dsp.fdct(temp); + return s->dsp.sum_abs_dctelem(temp); +} + +#if CONFIG_GPL +#define DCT8_1D {\ + const int s07 = SRC(0) + SRC(7);\ + const int s16 = SRC(1) + SRC(6);\ + const int s25 = SRC(2) + SRC(5);\ + const int s34 = SRC(3) + SRC(4);\ + const int a0 = s07 + s34;\ + const int a1 = s16 + s25;\ + const int a2 = s07 - s34;\ + const int a3 = s16 - s25;\ + const int d07 = SRC(0) - SRC(7);\ + const int d16 = SRC(1) - SRC(6);\ + const int d25 = SRC(2) - SRC(5);\ + const int d34 = SRC(3) - SRC(4);\ + const int a4 = d16 + d25 + (d07 + (d07>>1));\ + const int a5 = d07 - d34 - (d25 + (d25>>1));\ + const int a6 = d07 + d34 - (d16 + (d16>>1));\ + const int a7 = d16 - d25 + (d34 + (d34>>1));\ + DST(0, a0 + a1 ) ;\ + DST(1, a4 + (a7>>2)) ;\ + DST(2, a2 + (a3>>1)) ;\ + DST(3, a5 + (a6>>2)) ;\ + DST(4, a0 - a1 ) ;\ + DST(5, a6 - (a5>>2)) ;\ + DST(6, (a2>>1) - a3 ) ;\ + DST(7, (a4>>2) - a7 ) ;\ +} + +static int dct264_sad8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ + MpegEncContext * const s= (MpegEncContext *)c; + int16_t dct[8][8]; + int i; + int sum=0; + + s->dsp.diff_pixels(dct[0], src1, src2, stride); + +#define SRC(x) dct[i][x] +#define DST(x,v) dct[i][x]= v + for( i = 0; i < 8; i++ ) + DCT8_1D +#undef SRC +#undef DST + +#define SRC(x) dct[x][i] +#define DST(x,v) sum += FFABS(v) + for( i = 0; i < 8; i++ ) + DCT8_1D +#undef SRC +#undef DST + return sum; +} +#endif + +static int dct_max8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ + MpegEncContext * const s= (MpegEncContext *)c; + LOCAL_ALIGNED_16(int16_t, temp, [64]); + int sum=0, i; + + av_assert2(h==8); + + s->dsp.diff_pixels(temp, src1, src2, stride); + s->dsp.fdct(temp); + + for(i=0; i<64; i++) + sum= FFMAX(sum, FFABS(temp[i])); + + return sum; +} + +static int quant_psnr8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ + MpegEncContext * const s= (MpegEncContext *)c; + LOCAL_ALIGNED_16(int16_t, temp, [64*2]); + int16_t * const bak = temp+64; + int sum=0, i; + + av_assert2(h==8); + s->mb_intra=0; + + s->dsp.diff_pixels(temp, src1, src2, stride); + + memcpy(bak, temp, 64*sizeof(int16_t)); + + s->block_last_index[0/*FIXME*/]= s->fast_dct_quantize(s, temp, 0/*FIXME*/, s->qscale, &i); + s->dct_unquantize_inter(s, temp, 0, s->qscale); + ff_simple_idct_8(temp); //FIXME + + for(i=0; i<64; i++) + sum+= (temp[i]-bak[i])*(temp[i]-bak[i]); + + return sum; +} + +static int rd8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ + MpegEncContext * const s= (MpegEncContext *)c; + const uint8_t *scantable= s->intra_scantable.permutated; + LOCAL_ALIGNED_16(int16_t, temp, [64]); + LOCAL_ALIGNED_16(uint8_t, lsrc1, [64]); + LOCAL_ALIGNED_16(uint8_t, lsrc2, [64]); + int i, last, run, bits, level, distortion, start_i; + const int esc_length= s->ac_esc_length; + uint8_t * length; + uint8_t * last_length; + + av_assert2(h==8); + + copy_block8(lsrc1, src1, 8, stride, 8); + copy_block8(lsrc2, src2, 8, stride, 8); + + s->dsp.diff_pixels(temp, lsrc1, lsrc2, 8); + + s->block_last_index[0/*FIXME*/]= last= s->fast_dct_quantize(s, temp, 0/*FIXME*/, s->qscale, &i); + + bits=0; + + if (s->mb_intra) { + start_i = 1; + length = s->intra_ac_vlc_length; + last_length= s->intra_ac_vlc_last_length; + bits+= s->luma_dc_vlc_length[temp[0] + 256]; //FIXME chroma + } else { + start_i = 0; + length = s->inter_ac_vlc_length; + last_length= s->inter_ac_vlc_last_length; + } + + if(last>=start_i){ + run=0; + for(i=start_i; i=0){ + if(s->mb_intra) + s->dct_unquantize_intra(s, temp, 0, s->qscale); + else + s->dct_unquantize_inter(s, temp, 0, s->qscale); + } + + s->dsp.idct_add(lsrc2, 8, temp); + + distortion= s->dsp.sse[1](NULL, lsrc2, lsrc1, 8, 8); + + return distortion + ((bits*s->qscale*s->qscale*109 + 64)>>7); +} + +static int bit8x8_c(/*MpegEncContext*/ void *c, uint8_t *src1, uint8_t *src2, int stride, int h){ + MpegEncContext * const s= (MpegEncContext *)c; + const uint8_t *scantable= s->intra_scantable.permutated; + LOCAL_ALIGNED_16(int16_t, temp, [64]); + int i, last, run, bits, level, start_i; + const int esc_length= s->ac_esc_length; + uint8_t * length; + uint8_t * last_length; + + av_assert2(h==8); + + s->dsp.diff_pixels(temp, src1, src2, stride); + + s->block_last_index[0/*FIXME*/]= last= s->fast_dct_quantize(s, temp, 0/*FIXME*/, s->qscale, &i); + + bits=0; + + if (s->mb_intra) { + start_i = 1; + length = s->intra_ac_vlc_length; + last_length= s->intra_ac_vlc_last_length; + bits+= s->luma_dc_vlc_length[temp[0] + 256]; //FIXME chroma + } else { + start_i = 0; + length = s->inter_ac_vlc_length; + last_length= s->inter_ac_vlc_last_length; + } + + if(last>=start_i){ + run=0; + for(i=start_i; i mini) return mini; + else if((a^(1U<<31)) > maxisign) return maxi; + else return a; +} + +static void vector_clipf_c_opposite_sign(float *dst, const float *src, float *min, float *max, int len){ + int i; + uint32_t mini = *(uint32_t*)min; + uint32_t maxi = *(uint32_t*)max; + uint32_t maxisign = maxi ^ (1U<<31); + uint32_t *dsti = (uint32_t*)dst; + const uint32_t *srci = (const uint32_t*)src; + for(i=0; i 0) { + vector_clipf_c_opposite_sign(dst, src, &min, &max, len); + } else { + for(i=0; i < len; i+=8) { + dst[i ] = av_clipf(src[i ], min, max); + dst[i + 1] = av_clipf(src[i + 1], min, max); + dst[i + 2] = av_clipf(src[i + 2], min, max); + dst[i + 3] = av_clipf(src[i + 3], min, max); + dst[i + 4] = av_clipf(src[i + 4], min, max); + dst[i + 5] = av_clipf(src[i + 5], min, max); + dst[i + 6] = av_clipf(src[i + 6], min, max); + dst[i + 7] = av_clipf(src[i + 7], min, max); + } + } +} + +static int32_t scalarproduct_int16_c(const int16_t * v1, const int16_t * v2, int order) +{ + int res = 0; + + while (order--) + res += *v1++ * *v2++; + + return res; +} + +static int32_t scalarproduct_and_madd_int16_c(int16_t *v1, const int16_t *v2, const int16_t *v3, int order, int mul) +{ + int res = 0; + while (order--) { + res += *v1 * *v2++; + *v1++ += mul * *v3++; + } + return res; +} + +static void apply_window_int16_c(int16_t *output, const int16_t *input, + const int16_t *window, unsigned int len) +{ + int i; + int len2 = len >> 1; + + for (i = 0; i < len2; i++) { + int16_t w = window[i]; + output[i] = (MUL16(input[i], w) + (1 << 14)) >> 15; + output[len-i-1] = (MUL16(input[len-i-1], w) + (1 << 14)) >> 15; + } +} + +static void vector_clip_int32_c(int32_t *dst, const int32_t *src, int32_t min, + int32_t max, unsigned int len) +{ + do { + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + *dst++ = av_clip(*src++, min, max); + len -= 8; + } while (len > 0); +} + +static void ff_jref_idct_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct (block); + put_pixels_clamped_c(block, dest, line_size); +} +static void ff_jref_idct_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct (block); + add_pixels_clamped_c(block, dest, line_size); +} + +static void ff_jref_idct4_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct4 (block); + put_pixels_clamped4_c(block, dest, line_size); +} +static void ff_jref_idct4_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct4 (block); + add_pixels_clamped4_c(block, dest, line_size); +} + +static void ff_jref_idct2_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct2 (block); + put_pixels_clamped2_c(block, dest, line_size); +} +static void ff_jref_idct2_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_j_rev_dct2 (block); + add_pixels_clamped2_c(block, dest, line_size); +} + +static void ff_jref_idct1_put(uint8_t *dest, int line_size, int16_t *block) +{ + dest[0] = av_clip_uint8((block[0] + 4)>>3); +} +static void ff_jref_idct1_add(uint8_t *dest, int line_size, int16_t *block) +{ + dest[0] = av_clip_uint8(dest[0] + ((block[0] + 4)>>3)); +} + +/* init static data */ +av_cold void ff_dsputil_static_init(void) +{ + int i; + + for(i=0;i<512;i++) { + ff_squareTbl[i] = (i - 256) * (i - 256); + } + + for(i=0; i<64; i++) ff_inv_zigzag_direct16[ff_zigzag_direct[i]]= i+1; +} + +int ff_check_alignment(void){ + static int did_fail=0; + LOCAL_ALIGNED_16(int, aligned, [4]); + + if((intptr_t)aligned & 15){ + if(!did_fail){ +#if HAVE_MMX || HAVE_ALTIVEC + av_log(NULL, AV_LOG_ERROR, + "Compiler did not align stack variables. Libavcodec has been miscompiled\n" + "and may be very slow or crash. This is not a bug in libavcodec,\n" + "but in the compiler. You may try recompiling using gcc >= 4.2.\n" + "Do not report crashes to FFmpeg developers.\n"); +#endif + did_fail=1; + } + return -1; + } + return 0; +} + +av_cold void ff_dsputil_init(DSPContext* c, AVCodecContext *avctx) +{ + ff_check_alignment(); + +#if CONFIG_ENCODERS + if (avctx->bits_per_raw_sample == 10) { + c->fdct = ff_jpeg_fdct_islow_10; + c->fdct248 = ff_fdct248_islow_10; + } else { + if(avctx->dct_algo==FF_DCT_FASTINT) { + c->fdct = ff_fdct_ifast; + c->fdct248 = ff_fdct_ifast248; + } + else if(avctx->dct_algo==FF_DCT_FAAN) { + c->fdct = ff_faandct; + c->fdct248 = ff_faandct248; + } + else { + c->fdct = ff_jpeg_fdct_islow_8; //slow/accurate/default + c->fdct248 = ff_fdct248_islow_8; + } + } +#endif //CONFIG_ENCODERS + + if(avctx->lowres==1){ + c->idct_put= ff_jref_idct4_put; + c->idct_add= ff_jref_idct4_add; + c->idct = ff_j_rev_dct4; + c->idct_permutation_type= FF_NO_IDCT_PERM; + }else if(avctx->lowres==2){ + c->idct_put= ff_jref_idct2_put; + c->idct_add= ff_jref_idct2_add; + c->idct = ff_j_rev_dct2; + c->idct_permutation_type= FF_NO_IDCT_PERM; + }else if(avctx->lowres==3){ + c->idct_put= ff_jref_idct1_put; + c->idct_add= ff_jref_idct1_add; + c->idct = ff_j_rev_dct1; + c->idct_permutation_type= FF_NO_IDCT_PERM; + }else{ + if (avctx->bits_per_raw_sample == 10) { + c->idct_put = ff_simple_idct_put_10; + c->idct_add = ff_simple_idct_add_10; + c->idct = ff_simple_idct_10; + c->idct_permutation_type = FF_NO_IDCT_PERM; + } else { + if(avctx->idct_algo==FF_IDCT_INT){ + c->idct_put= ff_jref_idct_put; + c->idct_add= ff_jref_idct_add; + c->idct = ff_j_rev_dct; + c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM; + }else if(avctx->idct_algo==FF_IDCT_FAAN){ + c->idct_put= ff_faanidct_put; + c->idct_add= ff_faanidct_add; + c->idct = ff_faanidct; + c->idct_permutation_type= FF_NO_IDCT_PERM; + }else{ //accurate/default + c->idct_put = ff_simple_idct_put_8; + c->idct_add = ff_simple_idct_add_8; + c->idct = ff_simple_idct_8; + c->idct_permutation_type= FF_NO_IDCT_PERM; + } + } + } + + c->diff_pixels = diff_pixels_c; + c->put_pixels_clamped = put_pixels_clamped_c; + c->put_signed_pixels_clamped = put_signed_pixels_clamped_c; + c->add_pixels_clamped = add_pixels_clamped_c; + c->sum_abs_dctelem = sum_abs_dctelem_c; + c->gmc1 = gmc1_c; + c->gmc = ff_gmc_c; + c->pix_sum = pix_sum_c; + c->pix_norm1 = pix_norm1_c; + + c->fill_block_tab[0] = fill_block16_c; + c->fill_block_tab[1] = fill_block8_c; + + /* TODO [0] 16 [1] 8 */ + c->pix_abs[0][0] = pix_abs16_c; + c->pix_abs[0][1] = pix_abs16_x2_c; + c->pix_abs[0][2] = pix_abs16_y2_c; + c->pix_abs[0][3] = pix_abs16_xy2_c; + c->pix_abs[1][0] = pix_abs8_c; + c->pix_abs[1][1] = pix_abs8_x2_c; + c->pix_abs[1][2] = pix_abs8_y2_c; + c->pix_abs[1][3] = pix_abs8_xy2_c; + + c->put_tpel_pixels_tab[ 0] = put_tpel_pixels_mc00_c; + c->put_tpel_pixels_tab[ 1] = put_tpel_pixels_mc10_c; + c->put_tpel_pixels_tab[ 2] = put_tpel_pixels_mc20_c; + c->put_tpel_pixels_tab[ 4] = put_tpel_pixels_mc01_c; + c->put_tpel_pixels_tab[ 5] = put_tpel_pixels_mc11_c; + c->put_tpel_pixels_tab[ 6] = put_tpel_pixels_mc21_c; + c->put_tpel_pixels_tab[ 8] = put_tpel_pixels_mc02_c; + c->put_tpel_pixels_tab[ 9] = put_tpel_pixels_mc12_c; + c->put_tpel_pixels_tab[10] = put_tpel_pixels_mc22_c; + + c->avg_tpel_pixels_tab[ 0] = avg_tpel_pixels_mc00_c; + c->avg_tpel_pixels_tab[ 1] = avg_tpel_pixels_mc10_c; + c->avg_tpel_pixels_tab[ 2] = avg_tpel_pixels_mc20_c; + c->avg_tpel_pixels_tab[ 4] = avg_tpel_pixels_mc01_c; + c->avg_tpel_pixels_tab[ 5] = avg_tpel_pixels_mc11_c; + c->avg_tpel_pixels_tab[ 6] = avg_tpel_pixels_mc21_c; + c->avg_tpel_pixels_tab[ 8] = avg_tpel_pixels_mc02_c; + c->avg_tpel_pixels_tab[ 9] = avg_tpel_pixels_mc12_c; + c->avg_tpel_pixels_tab[10] = avg_tpel_pixels_mc22_c; + +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_c; \ + c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_c; \ + c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_c; \ + c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_c; \ + c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_c; \ + c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_c; \ + c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_c; \ + c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_c; \ + c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_c; \ + c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_c; \ + c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_c; \ + c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_c; \ + c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_c; \ + c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_c; \ + c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_c; \ + c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_c + + dspfunc(put_qpel, 0, 16); + dspfunc(put_no_rnd_qpel, 0, 16); + + dspfunc(avg_qpel, 0, 16); + /* dspfunc(avg_no_rnd_qpel, 0, 16); */ + + dspfunc(put_qpel, 1, 8); + dspfunc(put_no_rnd_qpel, 1, 8); + + dspfunc(avg_qpel, 1, 8); + /* dspfunc(avg_no_rnd_qpel, 1, 8); */ + +#undef dspfunc + + c->put_mspel_pixels_tab[0]= ff_put_pixels8x8_c; + c->put_mspel_pixels_tab[1]= put_mspel8_mc10_c; + c->put_mspel_pixels_tab[2]= put_mspel8_mc20_c; + c->put_mspel_pixels_tab[3]= put_mspel8_mc30_c; + c->put_mspel_pixels_tab[4]= put_mspel8_mc02_c; + c->put_mspel_pixels_tab[5]= put_mspel8_mc12_c; + c->put_mspel_pixels_tab[6]= put_mspel8_mc22_c; + c->put_mspel_pixels_tab[7]= put_mspel8_mc32_c; + +#define SET_CMP_FUNC(name) \ + c->name[0]= name ## 16_c;\ + c->name[1]= name ## 8x8_c; + + SET_CMP_FUNC(hadamard8_diff) + c->hadamard8_diff[4]= hadamard8_intra16_c; + c->hadamard8_diff[5]= hadamard8_intra8x8_c; + SET_CMP_FUNC(dct_sad) + SET_CMP_FUNC(dct_max) +#if CONFIG_GPL + SET_CMP_FUNC(dct264_sad) +#endif + c->sad[0]= pix_abs16_c; + c->sad[1]= pix_abs8_c; + c->sse[0]= sse16_c; + c->sse[1]= sse8_c; + c->sse[2]= sse4_c; + SET_CMP_FUNC(quant_psnr) + SET_CMP_FUNC(rd) + SET_CMP_FUNC(bit) + c->vsad[0]= vsad16_c; + c->vsad[4]= vsad_intra16_c; + c->vsad[5]= vsad_intra8_c; + c->vsse[0]= vsse16_c; + c->vsse[4]= vsse_intra16_c; + c->vsse[5]= vsse_intra8_c; + c->nsse[0]= nsse16_c; + c->nsse[1]= nsse8_c; +#if CONFIG_SNOW_DECODER || CONFIG_SNOW_ENCODER + ff_dsputil_init_dwt(c); +#endif + + c->ssd_int8_vs_int16 = ssd_int8_vs_int16_c; + + c->add_bytes= add_bytes_c; + c->diff_bytes= diff_bytes_c; + c->add_hfyu_median_prediction= add_hfyu_median_prediction_c; + c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_c; + c->add_hfyu_left_prediction = add_hfyu_left_prediction_c; + c->add_hfyu_left_prediction_bgr32 = add_hfyu_left_prediction_bgr32_c; + c->bswap_buf= bswap_buf; + c->bswap16_buf = bswap16_buf; + + if (CONFIG_H263_DECODER || CONFIG_H263_ENCODER) { + c->h263_h_loop_filter= h263_h_loop_filter_c; + c->h263_v_loop_filter= h263_v_loop_filter_c; + } + + c->h261_loop_filter= h261_loop_filter_c; + + c->try_8x8basis= try_8x8basis_c; + c->add_8x8basis= add_8x8basis_c; + + c->vector_clipf = vector_clipf_c; + c->scalarproduct_int16 = scalarproduct_int16_c; + c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_c; + c->apply_window_int16 = apply_window_int16_c; + c->vector_clip_int32 = vector_clip_int32_c; + + c->shrink[0]= av_image_copy_plane; + c->shrink[1]= ff_shrink22; + c->shrink[2]= ff_shrink44; + c->shrink[3]= ff_shrink88; + + c->add_pixels8 = add_pixels8_c; + +#undef FUNC +#undef FUNCC +#define FUNC(f, depth) f ## _ ## depth +#define FUNCC(f, depth) f ## _ ## depth ## _c + +#define BIT_DEPTH_FUNCS(depth) \ + c->get_pixels = FUNCC(get_pixels, depth); + + c->draw_edges = FUNCC(draw_edges, 8); + c->clear_block = FUNCC(clear_block, 8); + c->clear_blocks = FUNCC(clear_blocks, 8); + + switch (avctx->bits_per_raw_sample) { + case 9: + case 10: + case 12: + case 14: + BIT_DEPTH_FUNCS(16); + break; + default: + if(avctx->bits_per_raw_sample<=8 || avctx->codec_type != AVMEDIA_TYPE_VIDEO) { + BIT_DEPTH_FUNCS(8); + } + break; + } + + + if (HAVE_MMX) ff_dsputil_init_mmx (c, avctx); + if (ARCH_ARM) ff_dsputil_init_arm (c, avctx); + if (HAVE_VIS) ff_dsputil_init_vis (c, avctx); + if (ARCH_ALPHA) ff_dsputil_init_alpha (c, avctx); + if (ARCH_PPC) ff_dsputil_init_ppc (c, avctx); + if (ARCH_SH4) ff_dsputil_init_sh4 (c, avctx); + if (ARCH_BFIN) ff_dsputil_init_bfin (c, avctx); + + ff_init_scantable_permutation(c->idct_permutation, + c->idct_permutation_type); +} + +av_cold void dsputil_init(DSPContext* c, AVCodecContext *avctx) +{ + ff_dsputil_init(c, avctx); +} diff --git a/ffmpeg/libavcodec/dsputil.h b/ffmpeg/libavcodec/dsputil.h new file mode 100644 index 0000000..75017ca --- /dev/null +++ b/ffmpeg/libavcodec/dsputil.h @@ -0,0 +1,336 @@ +/* + * DSP utils + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * DSP utils. + * note, many functions in here may use MMX which trashes the FPU state, it is + * absolutely necessary to call emms_c() between dsp & float/double code + */ + +#ifndef AVCODEC_DSPUTIL_H +#define AVCODEC_DSPUTIL_H + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "rnd_avg.h" + + +//#define DEBUG + +/* encoding scans */ +extern const uint8_t ff_alternate_horizontal_scan[64]; +extern const uint8_t ff_alternate_vertical_scan[64]; +extern const uint8_t ff_zigzag_direct[64]; +extern const uint8_t ff_zigzag248_direct[64]; + +/* pixel operations */ +#define MAX_NEG_CROP 1024 + +/* temporary */ +extern uint32_t ff_squareTbl[512]; +extern const uint8_t ff_cropTbl[256 + 2 * MAX_NEG_CROP]; + +void ff_put_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_pixels8x8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_put_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_pixels16x16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); + +/* RV40 functions */ +void ff_put_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_rv40_qpel16_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_put_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_rv40_qpel8_mc33_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride); + +void ff_gmc_c(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); + +/* minimum alignment rules ;) +If you notice errors in the align stuff, need more alignment for some ASM code +for some CPU or need to use a function with less aligned data then send a mail +to the ffmpeg-devel mailing list, ... + +!warning These alignments might not match reality, (missing attribute((align)) +stuff somewhere possible). +I (Michael) did not check them, these are just the alignments which I think +could be reached easily ... + +!future video codecs might need functions with less strict alignment +*/ + +/* add and put pixel (decoding) */ +// blocksizes for op_pixels_func are 8x4,8x8 16x8 16x16 +//h for op_pixels_func is limited to {width/2, width} but never larger than 16 and never smaller than 4 +typedef void (*tpel_mc_func)(uint8_t *block/*align width (8 or 16)*/, const uint8_t *pixels/*align 1*/, int line_size, int w, int h); +typedef void (*qpel_mc_func)(uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride); + +typedef void (*op_fill_func)(uint8_t *block/*align width (8 or 16)*/, uint8_t value, int line_size, int h); + +#define DEF_OLD_QPEL(name)\ +void ff_put_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride);\ +void ff_put_no_rnd_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride);\ +void ff_avg_ ## name (uint8_t *dst/*align width (8 or 16)*/, uint8_t *src/*align 1*/, ptrdiff_t stride); + +DEF_OLD_QPEL(qpel16_mc11_old_c) +DEF_OLD_QPEL(qpel16_mc31_old_c) +DEF_OLD_QPEL(qpel16_mc12_old_c) +DEF_OLD_QPEL(qpel16_mc32_old_c) +DEF_OLD_QPEL(qpel16_mc13_old_c) +DEF_OLD_QPEL(qpel16_mc33_old_c) +DEF_OLD_QPEL(qpel8_mc11_old_c) +DEF_OLD_QPEL(qpel8_mc31_old_c) +DEF_OLD_QPEL(qpel8_mc12_old_c) +DEF_OLD_QPEL(qpel8_mc32_old_c) +DEF_OLD_QPEL(qpel8_mc13_old_c) +DEF_OLD_QPEL(qpel8_mc33_old_c) + +/* motion estimation */ +// h is limited to {width/2, width, 2*width} but never larger than 16 and never smaller than 2 +// although currently h<4 is not used as functions with width <8 are neither used nor implemented +typedef int (*me_cmp_func)(void /*MpegEncContext*/ *s, uint8_t *blk1/*align width (8 or 16)*/, uint8_t *blk2/*align 1*/, int line_size, int h)/* __attribute__ ((const))*/; + +/** + * Scantable. + */ +typedef struct ScanTable{ + const uint8_t *scantable; + uint8_t permutated[64]; + uint8_t raster_end[64]; +} ScanTable; + +void ff_init_scantable(uint8_t *, ScanTable *st, const uint8_t *src_scantable); +void ff_init_scantable_permutation(uint8_t *idct_permutation, + int idct_permutation_type); + +/** + * DSPContext. + */ +typedef struct DSPContext { + /* pixel ops : interface with DCT */ + void (*get_pixels)(int16_t *block/*align 16*/, const uint8_t *pixels/*align 8*/, int line_size); + void (*diff_pixels)(int16_t *block/*align 16*/, const uint8_t *s1/*align 8*/, const uint8_t *s2/*align 8*/, int stride); + void (*put_pixels_clamped)(const int16_t *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*put_signed_pixels_clamped)(const int16_t *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*add_pixels_clamped)(const int16_t *block/*align 16*/, uint8_t *pixels/*align 8*/, int line_size); + void (*add_pixels8)(uint8_t *pixels, int16_t *block, int line_size); + int (*sum_abs_dctelem)(int16_t *block/*align 16*/); + /** + * translational global motion compensation. + */ + void (*gmc1)(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int srcStride, int h, int x16, int y16, int rounder); + /** + * global motion compensation. + */ + void (*gmc )(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); + void (*clear_block)(int16_t *block/*align 16*/); + void (*clear_blocks)(int16_t *blocks/*align 16*/); + int (*pix_sum)(uint8_t * pix, int line_size); + int (*pix_norm1)(uint8_t * pix, int line_size); +// 16x16 8x8 4x4 2x2 16x8 8x4 4x2 8x16 4x8 2x4 + + me_cmp_func sad[6]; /* identical to pix_absAxA except additional void * */ + me_cmp_func sse[6]; + me_cmp_func hadamard8_diff[6]; + me_cmp_func dct_sad[6]; + me_cmp_func quant_psnr[6]; + me_cmp_func bit[6]; + me_cmp_func rd[6]; + me_cmp_func vsad[6]; + me_cmp_func vsse[6]; + me_cmp_func nsse[6]; + me_cmp_func w53[6]; + me_cmp_func w97[6]; + me_cmp_func dct_max[6]; + me_cmp_func dct264_sad[6]; + + me_cmp_func me_pre_cmp[6]; + me_cmp_func me_cmp[6]; + me_cmp_func me_sub_cmp[6]; + me_cmp_func mb_cmp[6]; + me_cmp_func ildct_cmp[6]; //only width 16 used + me_cmp_func frame_skip_cmp[6]; //only width 8 used + + int (*ssd_int8_vs_int16)(const int8_t *pix1, const int16_t *pix2, + int size); + + /** + * Thirdpel motion compensation with rounding (a+b+1)>>1. + * this is an array[12] of motion compensation functions for the 9 thirdpe + * positions
+ * *pixels_tab[ xthirdpel + 4*ythirdpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + tpel_mc_func put_tpel_pixels_tab[11]; //FIXME individual func ptr per width? + tpel_mc_func avg_tpel_pixels_tab[11]; //FIXME individual func ptr per width? + + qpel_mc_func put_qpel_pixels_tab[2][16]; + qpel_mc_func avg_qpel_pixels_tab[2][16]; + qpel_mc_func put_no_rnd_qpel_pixels_tab[2][16]; + qpel_mc_func put_mspel_pixels_tab[8]; + + me_cmp_func pix_abs[2][4]; + + /* huffyuv specific */ + void (*add_bytes)(uint8_t *dst/*align 16*/, uint8_t *src/*align 16*/, int w); + void (*diff_bytes)(uint8_t *dst/*align 16*/, const uint8_t *src1/*align 16*/, const uint8_t *src2/*align 1*/,int w); + /** + * subtract huffyuv's variant of median prediction + * note, this might read from src1[-1], src2[-1] + */ + void (*sub_hfyu_median_prediction)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w, int *left, int *left_top); + void (*add_hfyu_median_prediction)(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top); + int (*add_hfyu_left_prediction)(uint8_t *dst, const uint8_t *src, int w, int left); + void (*add_hfyu_left_prediction_bgr32)(uint8_t *dst, const uint8_t *src, int w, int *red, int *green, int *blue, int *alpha); + /* this might write to dst[w] */ + void (*bswap_buf)(uint32_t *dst, const uint32_t *src, int w); + void (*bswap16_buf)(uint16_t *dst, const uint16_t *src, int len); + + void (*h263_v_loop_filter)(uint8_t *src, int stride, int qscale); + void (*h263_h_loop_filter)(uint8_t *src, int stride, int qscale); + + void (*h261_loop_filter)(uint8_t *src, int stride); + + /* assume len is a multiple of 8, and arrays are 16-byte aligned */ + void (*vector_clipf)(float *dst /* align 16 */, const float *src /* align 16 */, float min, float max, int len /* align 16 */); + + /* (I)DCT */ + void (*fdct)(int16_t *block/* align 16*/); + void (*fdct248)(int16_t *block/* align 16*/); + + /* IDCT really*/ + void (*idct)(int16_t *block/* align 16*/); + + /** + * block -> idct -> clip to unsigned 8 bit -> dest. + * (-1392, 0, 0, ...) -> idct -> (-174, -174, ...) -> put -> (0, 0, ...) + * @param line_size size in bytes of a horizontal line of dest + */ + void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, int16_t *block/*align 16*/); + + /** + * block -> idct -> add dest -> clip to unsigned 8 bit -> dest. + * @param line_size size in bytes of a horizontal line of dest + */ + void (*idct_add)(uint8_t *dest/*align 8*/, int line_size, int16_t *block/*align 16*/); + + /** + * idct input permutation. + * several optimized IDCTs need a permutated input (relative to the normal order of the reference + * IDCT) + * this permutation must be performed before the idct_put/add, note, normally this can be merged + * with the zigzag/alternate scan
+ * an example to avoid confusion: + * - (->decode coeffs -> zigzag reorder -> dequant -> reference idct ->...) + * - (x -> reference dct -> reference idct -> x) + * - (x -> reference dct -> simple_mmx_perm = idct_permutation -> simple_idct_mmx -> x) + * - (->decode coeffs -> zigzag reorder -> simple_mmx_perm -> dequant -> simple_idct_mmx ->...) + */ + uint8_t idct_permutation[64]; + int idct_permutation_type; +#define FF_NO_IDCT_PERM 1 +#define FF_LIBMPEG2_IDCT_PERM 2 +#define FF_SIMPLE_IDCT_PERM 3 +#define FF_TRANSPOSE_IDCT_PERM 4 +#define FF_PARTTRANS_IDCT_PERM 5 +#define FF_SSE2_IDCT_PERM 6 + + int (*try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale); + void (*add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale); +#define BASIS_SHIFT 16 +#define RECON_SHIFT 6 + + void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, int w, int h, int sides); +#define EDGE_WIDTH 16 +#define EDGE_TOP 1 +#define EDGE_BOTTOM 2 + + void (*shrink[4])(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); + + /** + * Calculate scalar product of two vectors. + * @param len length of vectors, should be multiple of 16 + */ + int32_t (*scalarproduct_int16)(const int16_t *v1, const int16_t *v2/*align 16*/, int len); + /* ape functions */ + /** + * Calculate scalar product of v1 and v2, + * and v1[i] += v3[i] * mul + * @param len length of vectors, should be multiple of 16 + */ + int32_t (*scalarproduct_and_madd_int16)(int16_t *v1/*align 16*/, const int16_t *v2, const int16_t *v3, int len, int mul); + + /** + * Apply symmetric window in 16-bit fixed-point. + * @param output destination array + * constraints: 16-byte aligned + * @param input source array + * constraints: 16-byte aligned + * @param window window array + * constraints: 16-byte aligned, at least len/2 elements + * @param len full window length + * constraints: multiple of ? greater than zero + */ + void (*apply_window_int16)(int16_t *output, const int16_t *input, + const int16_t *window, unsigned int len); + + /** + * Clip each element in an array of int32_t to a given minimum and maximum value. + * @param dst destination array + * constraints: 16-byte aligned + * @param src source array + * constraints: 16-byte aligned + * @param min minimum value + * constraints: must be in the range [-(1 << 24), 1 << 24] + * @param max maximum value + * constraints: must be in the range [-(1 << 24), 1 << 24] + * @param len number of elements in the array + * constraints: multiple of 32 greater than zero + */ + void (*vector_clip_int32)(int32_t *dst, const int32_t *src, int32_t min, + int32_t max, unsigned int len); + + op_fill_func fill_block_tab[2]; +} DSPContext; + +void ff_dsputil_static_init(void); +void ff_dsputil_init(DSPContext* p, AVCodecContext *avctx); +attribute_deprecated void dsputil_init(DSPContext* c, AVCodecContext *avctx); + +int ff_check_alignment(void); + +void ff_set_cmp(DSPContext* c, me_cmp_func *cmp, int type); + +void ff_dsputil_init_alpha(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_arm(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_bfin(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_sh4(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_vis(DSPContext* c, AVCodecContext *avctx); + +void ff_dsputil_init_dwt(DSPContext *c); + +#endif /* AVCODEC_DSPUTIL_H */ diff --git a/ffmpeg/libavcodec/dsputil_template.c b/ffmpeg/libavcodec/dsputil_template.c new file mode 100644 index 0000000..349da7d --- /dev/null +++ b/ffmpeg/libavcodec/dsputil_template.c @@ -0,0 +1,260 @@ +/* + * DSP utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * gmc & q-pel & 32/64 bit based MC 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 + */ + +/** + * @file + * DSP utils + */ + +#include "bit_depth_template.c" + +#if BIT_DEPTH == 8 +/* draw the edges of width 'w' of an image of size width, height */ +//FIXME check that this is ok for mpeg4 interlaced +static void FUNCC(draw_edges)(uint8_t *p_buf, int p_wrap, int width, int height, int w, int h, int sides) +{ + pixel *buf = (pixel*)p_buf; + int wrap = p_wrap / sizeof(pixel); + pixel *ptr, *last_line; + int i; + + /* left and right */ + ptr = buf; + for(i=0;i>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + l1= (c&0x03030303UL)\ + + (d&0x03030303UL);\ + h1= ((c&0xFCFCFCFCUL)>>2)\ + + ((d&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + a= AV_RN32(&src1[i*src_stride1+4]);\ + b= AV_RN32(&src2[i*src_stride2+4]);\ + c= AV_RN32(&src3[i*src_stride3+4]);\ + d= AV_RN32(&src4[i*src_stride4+4]);\ + l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + l1= (c&0x03030303UL)\ + + (d&0x03030303UL);\ + h1= ((c&0xFCFCFCFCUL)>>2)\ + + ((d&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + }\ +}\ +\ +static inline void FUNC(OPNAME ## _no_rnd_pixels8_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\ + int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + /* FIXME HIGH BIT DEPTH*/\ + int i;\ + for(i=0; i>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + l1= (c&0x03030303UL)\ + + (d&0x03030303UL);\ + h1= ((c&0xFCFCFCFCUL)>>2)\ + + ((d&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)&dst[i*dst_stride]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + a= AV_RN32(&src1[i*src_stride1+4]);\ + b= AV_RN32(&src2[i*src_stride2+4]);\ + c= AV_RN32(&src3[i*src_stride3+4]);\ + d= AV_RN32(&src4[i*src_stride4+4]);\ + l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x01010101UL;\ + h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + l1= (c&0x03030303UL)\ + + (d&0x03030303UL);\ + h1= ((c&0xFCFCFCFCUL)>>2)\ + + ((d&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)&dst[i*dst_stride+4]), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + }\ +}\ +static inline void FUNC(OPNAME ## _pixels16_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\ + int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + FUNC(OPNAME ## _pixels8_l4)(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ + FUNC(OPNAME ## _pixels8_l4)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), src3+8*sizeof(pixel), src4+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ +}\ +static inline void FUNC(OPNAME ## _no_rnd_pixels16_l4)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, const uint8_t *src3, const uint8_t *src4,\ + int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + FUNC(OPNAME ## _no_rnd_pixels8_l4)(dst , src1 , src2 , src3 , src4 , dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ + FUNC(OPNAME ## _no_rnd_pixels8_l4)(dst+8*sizeof(pixel), src1+8*sizeof(pixel), src2+8*sizeof(pixel), src3+8*sizeof(pixel), src4+8*sizeof(pixel), dst_stride, src_stride1, src_stride2, src_stride3, src_stride4, h);\ +}\ +\ +static inline void FUNCC(OPNAME ## _pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ +{\ + /* FIXME HIGH BIT DEPTH */\ + int j;\ + for(j=0; j<2; j++){\ + int i;\ + const uint32_t a= AV_RN32(pixels );\ + const uint32_t b= AV_RN32(pixels+1);\ + uint32_t l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + uint32_t l1,h1;\ +\ + pixels+=line_size;\ + for(i=0; i>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + a= AV_RN32(pixels );\ + b= AV_RN32(pixels+1);\ + l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + }\ + pixels+=4-line_size*(h+1);\ + block +=4-line_size*h;\ + }\ +}\ +\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_xy2), FUNCC(OPNAME ## _pixels8_xy2), 8*sizeof(pixel))\ + +#define op_avg(a, b) a = rnd_avg_pixel4(a, b) +#define op_put(a, b) a = b +#if BIT_DEPTH == 8 +#define put_no_rnd_pixels8_8_c put_pixels8_8_c +PIXOP2(avg, op_avg) +PIXOP2(put, op_put) +#endif +#undef op_avg +#undef op_put diff --git a/ffmpeg/libavcodec/dump_extradata_bsf.c b/ffmpeg/libavcodec/dump_extradata_bsf.c new file mode 100644 index 0000000..94b7b42 --- /dev/null +++ b/ffmpeg/libavcodec/dump_extradata_bsf.c @@ -0,0 +1,53 @@ +/* + * copyright (c) 2006 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 "avcodec.h" +#include "libavutil/mem.h" + + +static int dump_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + int cmd= args ? *args : 0; + /* cast to avoid warning about discarding qualifiers */ + if(avctx->extradata){ + if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER) && cmd=='a') + ||(keyframe && (cmd=='k' || !cmd)) + ||(cmd=='e') + /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){ + int size= buf_size + avctx->extradata_size; + *poutbuf_size= size; + *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + + memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); + memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + return 1; + } + } + return 0; +} + +AVBitStreamFilter ff_dump_extradata_bsf={ + "dump_extra", + 0, + dump_extradata, +}; diff --git a/ffmpeg/libavcodec/dv.c b/ffmpeg/libavcodec/dv.c new file mode 100644 index 0000000..39a87a9 --- /dev/null +++ b/ffmpeg/libavcodec/dv.c @@ -0,0 +1,1003 @@ +/* + * DV decoder + * Copyright (c) 2002 Fabrice Bellard + * Copyright (c) 2004 Roman Shaposhnik + * + * DV encoder + * Copyright (c) 2003 Roman Shaposhnik + * + * 50 Mbps (DVCPRO50) support + * Copyright (c) 2006 Daniel Maas + * + * 100 Mbps (DVCPRO HD) support + * Initial code by Daniel Maas (funded by BBC R&D) + * Final code by Roman Shaposhnik + * + * Many thanks to Dan Dennedy for providing wealth + * of DV technical info. + * + * 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 + */ + +/** + * @file + * DV codec. + */ + +#include "libavutil/internal.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "put_bits.h" +#include "simple_idct.h" +#include "dvdata.h" +#include "dv_tablegen.h" + +/* XXX: also include quantization */ +RL_VLC_ELEM ff_dv_rl_vlc[1184]; + +static inline void dv_calc_mb_coordinates(const DVprofile *d, int chan, int seq, int slot, + uint16_t *tbl) +{ + static const uint8_t off[] = { 2, 6, 8, 0, 4 }; + static const uint8_t shuf1[] = { 36, 18, 54, 0, 72 }; + static const uint8_t shuf2[] = { 24, 12, 36, 0, 48 }; + static const uint8_t shuf3[] = { 18, 9, 27, 0, 36 }; + + static const uint8_t l_start[] = {0, 4, 9, 13, 18, 22, 27, 31, 36, 40}; + static const uint8_t l_start_shuffled[] = { 9, 4, 13, 0, 18 }; + + static const uint8_t serpent1[] = {0, 1, 2, 2, 1, 0, + 0, 1, 2, 2, 1, 0, + 0, 1, 2, 2, 1, 0, + 0, 1, 2, 2, 1, 0, + 0, 1, 2}; + static const uint8_t serpent2[] = {0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5}; + + static const uint8_t remap[][2] = {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, /* dummy */ + { 0, 0}, { 0, 1}, { 0, 2}, { 0, 3}, {10, 0}, + {10, 1}, {10, 2}, {10, 3}, {20, 0}, {20, 1}, + {20, 2}, {20, 3}, {30, 0}, {30, 1}, {30, 2}, + {30, 3}, {40, 0}, {40, 1}, {40, 2}, {40, 3}, + {50, 0}, {50, 1}, {50, 2}, {50, 3}, {60, 0}, + {60, 1}, {60, 2}, {60, 3}, {70, 0}, {70, 1}, + {70, 2}, {70, 3}, { 0,64}, { 0,65}, { 0,66}, + {10,64}, {10,65}, {10,66}, {20,64}, {20,65}, + {20,66}, {30,64}, {30,65}, {30,66}, {40,64}, + {40,65}, {40,66}, {50,64}, {50,65}, {50,66}, + {60,64}, {60,65}, {60,66}, {70,64}, {70,65}, + {70,66}, { 0,67}, {20,67}, {40,67}, {60,67}}; + + int i, k, m; + int x, y, blk; + + for (m=0; m<5; m++) { + switch (d->width) { + case 1440: + blk = (chan*11+seq)*27+slot; + + if (chan == 0 && seq == 11) { + x = m*27+slot; + if (x<90) { + y = 0; + } else { + x = (x - 90)*2; + y = 67; + } + } else { + i = (4*chan + blk + off[m])%11; + k = (blk/11)%27; + + x = shuf1[m] + (chan&1)*9 + k%9; + y = (i*3+k/9)*2 + (chan>>1) + 1; + } + tbl[m] = (x<<1)|(y<<9); + break; + case 1280: + blk = (chan*10+seq)*27+slot; + + i = (4*chan + (seq/5) + 2*blk + off[m])%10; + k = (blk/5)%27; + + x = shuf1[m]+(chan&1)*9 + k%9; + y = (i*3+k/9)*2 + (chan>>1) + 4; + + if (x >= 80) { + x = remap[y][0]+((x-80)<<(y>59)); + y = remap[y][1]; + } + tbl[m] = (x<<1)|(y<<9); + break; + case 960: + blk = (chan*10+seq)*27+slot; + + i = (4*chan + (seq/5) + 2*blk + off[m])%10; + k = (blk/5)%27 + (i&1)*3; + + x = shuf2[m] + k%6 + 6*(chan&1); + y = l_start[i] + k/6 + 45*(chan>>1); + tbl[m] = (x<<1)|(y<<9); + break; + case 720: + switch (d->pix_fmt) { + case AV_PIX_FMT_YUV422P: + x = shuf3[m] + slot/3; + y = serpent1[slot] + + ((((seq + off[m]) % d->difseg_size)<<1) + chan)*3; + tbl[m] = (x<<1)|(y<<8); + break; + case AV_PIX_FMT_YUV420P: + x = shuf3[m] + slot/3; + y = serpent1[slot] + + ((seq + off[m]) % d->difseg_size)*3; + tbl[m] = (x<<1)|(y<<9); + break; + case AV_PIX_FMT_YUV411P: + i = (seq + off[m]) % d->difseg_size; + k = slot + ((m==1||m==2)?3:0); + + x = l_start_shuffled[m] + k/6; + y = serpent2[k] + i*6; + if (x>21) + y = y*2 - i*6; + tbl[m] = (x<<2)|(y<<8); + break; + } + default: + break; + } + } +} + +/* quantization quanta by QNO for DV100 */ +static const uint8_t dv100_qstep[16] = { + 1, /* QNO = 0 and 1 both have no quantization */ + 1, + 2, 3, 4, 5, 6, 7, 8, 16, 18, 20, 22, 24, 28, 52 +}; + +static const uint8_t dv_quant_areas[4] = { 6, 21, 43, 64 }; + +int ff_dv_init_dynamic_tables(const DVprofile *d) +{ + int j,i,c,s,p; + uint32_t *factor1, *factor2; + const int *iweight1, *iweight2; + + if (!d->work_chunks[dv_work_pool_size(d)-1].buf_offset) { + p = i = 0; + for (c=0; cn_difchan; c++) { + for (s=0; sdifseg_size; s++) { + p += 6; + for (j=0; j<27; j++) { + p += !(j%3); + if (!(DV_PROFILE_IS_1080i50(d) && c != 0 && s == 11) && + !(DV_PROFILE_IS_720p50(d) && s > 9)) { + dv_calc_mb_coordinates(d, c, s, j, &d->work_chunks[i].mb_coordinates[0]); + d->work_chunks[i++].buf_offset = p; + } + p += 5; + } + } + } + } + + if (!d->idct_factor[DV_PROFILE_IS_HD(d)?8191:5631]) { + factor1 = &d->idct_factor[0]; + factor2 = &d->idct_factor[DV_PROFILE_IS_HD(d)?4096:2816]; + if (d->height == 720) { + iweight1 = &ff_dv_iweight_720_y[0]; + iweight2 = &ff_dv_iweight_720_c[0]; + } else { + iweight1 = &ff_dv_iweight_1080_y[0]; + iweight2 = &ff_dv_iweight_1080_c[0]; + } + if (DV_PROFILE_IS_HD(d)) { + for (c = 0; c < 4; c++) { + for (s = 0; s < 16; s++) { + for (i = 0; i < 64; i++) { + *factor1++ = (dv100_qstep[s] << (c + 9)) * iweight1[i]; + *factor2++ = (dv100_qstep[s] << (c + 9)) * iweight2[i]; + } + } + } + } else { + iweight1 = &ff_dv_iweight_88[0]; + for (j = 0; j < 2; j++, iweight1 = &ff_dv_iweight_248[0]) { + for (s = 0; s < 22; s++) { + for (i = c = 0; c < 4; c++) { + for (; i < dv_quant_areas[c]; i++) { + *factor1 = iweight1[i] << (ff_dv_quant_shifts[s][c] + 1); + *factor2++ = (*factor1++) << 1; + } + } + } + } + } + } + + return 0; +} + +av_cold int ff_dvvideo_init(AVCodecContext *avctx) +{ + DVVideoContext *s = avctx->priv_data; + DSPContext dsp; + static int done = 0; + int i, j; + + if (!done) { + VLC dv_vlc; + uint16_t new_dv_vlc_bits[NB_DV_VLC*2]; + uint8_t new_dv_vlc_len[NB_DV_VLC*2]; + uint8_t new_dv_vlc_run[NB_DV_VLC*2]; + int16_t new_dv_vlc_level[NB_DV_VLC*2]; + + done = 1; + + /* it's faster to include sign bit in a generic VLC parsing scheme */ + for (i = 0, j = 0; i < NB_DV_VLC; i++, j++) { + new_dv_vlc_bits[j] = dv_vlc_bits[i]; + new_dv_vlc_len[j] = dv_vlc_len[i]; + new_dv_vlc_run[j] = dv_vlc_run[i]; + new_dv_vlc_level[j] = dv_vlc_level[i]; + + if (dv_vlc_level[i]) { + new_dv_vlc_bits[j] <<= 1; + new_dv_vlc_len[j]++; + + j++; + new_dv_vlc_bits[j] = (dv_vlc_bits[i] << 1) | 1; + new_dv_vlc_len[j] = dv_vlc_len[i] + 1; + new_dv_vlc_run[j] = dv_vlc_run[i]; + new_dv_vlc_level[j] = -dv_vlc_level[i]; + } + } + + /* NOTE: as a trick, we use the fact the no codes are unused + to accelerate the parsing of partial codes */ + init_vlc(&dv_vlc, TEX_VLC_BITS, j, + new_dv_vlc_len, 1, 1, new_dv_vlc_bits, 2, 2, 0); + av_assert1(dv_vlc.table_size == 1184); + + for (i = 0; i < dv_vlc.table_size; i++){ + int code = dv_vlc.table[i][0]; + int len = dv_vlc.table[i][1]; + int level, run; + + if (len < 0){ //more bits needed + run = 0; + level = code; + } else { + run = new_dv_vlc_run [code] + 1; + level = new_dv_vlc_level[code]; + } + ff_dv_rl_vlc[i].len = len; + ff_dv_rl_vlc[i].level = level; + ff_dv_rl_vlc[i].run = run; + } + ff_free_vlc(&dv_vlc); + } + + /* Generic DSP setup */ + memset(&dsp,0, sizeof(dsp)); + ff_dsputil_init(&dsp, avctx); + ff_set_cmp(&dsp, dsp.ildct_cmp, avctx->ildct_cmp); + s->get_pixels = dsp.get_pixels; + s->ildct_cmp = dsp.ildct_cmp[5]; + + /* 88DCT setup */ + s->fdct[0] = dsp.fdct; + s->idct_put[0] = dsp.idct_put; + for (i = 0; i < 64; i++) + s->dv_zigzag[0][i] = dsp.idct_permutation[ff_zigzag_direct[i]]; + + /* 248DCT setup */ + s->fdct[1] = dsp.fdct248; + s->idct_put[1] = ff_simple_idct248_put; // FIXME: need to add it to DSP + if (avctx->lowres){ + for (i = 0; i < 64; i++){ + int j = ff_zigzag248_direct[i]; + s->dv_zigzag[1][i] = dsp.idct_permutation[(j & 7) + (j & 8) * 4 + (j & 48) / 2]; + } + }else + memcpy(s->dv_zigzag[1], ff_zigzag248_direct, 64); + + avcodec_get_frame_defaults(&s->picture); + avctx->coded_frame = &s->picture; + s->avctx = avctx; + avctx->chroma_sample_location = AVCHROMA_LOC_TOPLEFT; + + return 0; +} + +static av_cold int dvvideo_init_encoder(AVCodecContext *avctx) +{ + if (!avpriv_dv_codec_profile(avctx)) { + av_log(avctx, AV_LOG_ERROR, "Found no DV profile for %ix%i %s video. " + "Valid DV profiles are:\n", + avctx->width, avctx->height, av_get_pix_fmt_name(avctx->pix_fmt)); + ff_dv_print_profiles(avctx, AV_LOG_ERROR); + return AVERROR(EINVAL); + } + if (avctx->height > 576) { + av_log(avctx, AV_LOG_ERROR, "DVCPRO HD encoding is not supported.\n"); + return AVERROR_PATCHWELCOME; + } + + dv_vlc_map_tableinit(); + + return ff_dvvideo_init(avctx); +} + +/* bit budget for AC only in 5 MBs */ +static const int vs_total_ac_bits = (100 * 4 + 68*2) * 5; +static const int mb_area_start[5] = { 1, 6, 21, 43, 64 }; + +static inline int put_bits_left(PutBitContext* s) +{ + return (s->buf_end - s->buf) * 8 - put_bits_count(s); +} + +#if CONFIG_SMALL +/* Converts run and level (where level != 0) pair into VLC, returning bit size */ +static av_always_inline int dv_rl2vlc(int run, int level, int sign, uint32_t* vlc) +{ + int size; + if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { + *vlc = dv_vlc_map[run][level].vlc | sign; + size = dv_vlc_map[run][level].size; + } + else { + if (level < DV_VLC_MAP_LEV_SIZE) { + *vlc = dv_vlc_map[0][level].vlc | sign; + size = dv_vlc_map[0][level].size; + } else { + *vlc = 0xfe00 | (level << 1) | sign; + size = 16; + } + if (run) { + *vlc |= ((run < 16) ? dv_vlc_map[run-1][0].vlc : + (0x1f80 | (run - 1))) << size; + size += (run < 16) ? dv_vlc_map[run-1][0].size : 13; + } + } + + return size; +} + +static av_always_inline int dv_rl2vlc_size(int run, int level) +{ + int size; + + if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) { + size = dv_vlc_map[run][level].size; + } + else { + size = (level < DV_VLC_MAP_LEV_SIZE) ? dv_vlc_map[0][level].size : 16; + if (run) { + size += (run < 16) ? dv_vlc_map[run-1][0].size : 13; + } + } + return size; +} +#else +static av_always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t* vlc) +{ + *vlc = dv_vlc_map[run][l].vlc | sign; + return dv_vlc_map[run][l].size; +} + +static av_always_inline int dv_rl2vlc_size(int run, int l) +{ + return dv_vlc_map[run][l].size; +} +#endif + +typedef struct EncBlockInfo { + int area_q[4]; + int bit_size[4]; + int prev[5]; + int cur_ac; + int cno; + int dct_mode; + int16_t mb[64]; + uint8_t next[64]; + uint8_t sign[64]; + uint8_t partial_bit_count; + uint32_t partial_bit_buffer; /* we can't use uint16_t here */ +} EncBlockInfo; + +static av_always_inline PutBitContext* dv_encode_ac(EncBlockInfo* bi, + PutBitContext* pb_pool, + PutBitContext* pb_end) +{ + int prev, bits_left; + PutBitContext* pb = pb_pool; + int size = bi->partial_bit_count; + uint32_t vlc = bi->partial_bit_buffer; + + bi->partial_bit_count = bi->partial_bit_buffer = 0; + for (;;){ + /* Find suitable storage space */ + for (; size > (bits_left = put_bits_left(pb)); pb++) { + if (bits_left) { + size -= bits_left; + put_bits(pb, bits_left, vlc >> size); + vlc = vlc & ((1 << size) - 1); + } + if (pb + 1 >= pb_end) { + bi->partial_bit_count = size; + bi->partial_bit_buffer = vlc; + return pb; + } + } + + /* Store VLC */ + put_bits(pb, size, vlc); + + if (bi->cur_ac >= 64) + break; + + /* Construct the next VLC */ + prev = bi->cur_ac; + bi->cur_ac = bi->next[prev]; + if (bi->cur_ac < 64){ + size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac], bi->sign[bi->cur_ac], &vlc); + } else { + size = 4; vlc = 6; /* End Of Block stamp */ + } + } + return pb; +} + +static av_always_inline int dv_guess_dct_mode(DVVideoContext *s, uint8_t *data, int linesize) { + if (s->avctx->flags & CODEC_FLAG_INTERLACED_DCT) { + int ps = s->ildct_cmp(NULL, data, NULL, linesize, 8) - 400; + if (ps > 0) { + int is = s->ildct_cmp(NULL, data , NULL, linesize<<1, 4) + + s->ildct_cmp(NULL, data + linesize, NULL, linesize<<1, 4); + return ps > is; + } + } + + return 0; +} + +static const int dv_weight_bits = 18; +static const int dv_weight_88[64] = { + 131072, 257107, 257107, 242189, 252167, 242189, 235923, 237536, + 237536, 235923, 229376, 231390, 223754, 231390, 229376, 222935, + 224969, 217965, 217965, 224969, 222935, 200636, 218652, 211916, + 212325, 211916, 218652, 200636, 188995, 196781, 205965, 206433, + 206433, 205965, 196781, 188995, 185364, 185364, 200636, 200704, + 200636, 185364, 185364, 174609, 180568, 195068, 195068, 180568, + 174609, 170091, 175557, 189591, 175557, 170091, 165371, 170627, + 170627, 165371, 160727, 153560, 160727, 144651, 144651, 136258, +}; +static const int dv_weight_248[64] = { + 131072, 242189, 257107, 237536, 229376, 200636, 242189, 223754, + 224969, 196781, 262144, 242189, 229376, 200636, 257107, 237536, + 211916, 185364, 235923, 217965, 229376, 211916, 206433, 180568, + 242189, 223754, 224969, 196781, 211916, 185364, 235923, 217965, + 200704, 175557, 222935, 205965, 200636, 185364, 195068, 170627, + 229376, 211916, 206433, 180568, 200704, 175557, 222935, 205965, + 175557, 153560, 188995, 174609, 165371, 144651, 200636, 185364, + 195068, 170627, 175557, 153560, 188995, 174609, 165371, 144651, +}; + +static av_always_inline int dv_init_enc_block(EncBlockInfo* bi, uint8_t *data, int linesize, DVVideoContext *s, int bias) +{ + const int *weight; + const uint8_t* zigzag_scan; + LOCAL_ALIGNED_16(int16_t, blk, [64]); + int i, area; + /* We offer two different methods for class number assignment: the + method suggested in SMPTE 314M Table 22, and an improved + method. The SMPTE method is very conservative; it assigns class + 3 (i.e. severe quantization) to any block where the largest AC + component is greater than 36. FFmpeg's DV encoder tracks AC bit + consumption precisely, so there is no need to bias most blocks + towards strongly lossy compression. Instead, we assign class 2 + to most blocks, and use class 3 only when strictly necessary + (for blocks whose largest AC component exceeds 255). */ + +#if 0 /* SMPTE spec method */ + static const int classes[] = {12, 24, 36, 0xffff}; +#else /* improved FFmpeg method */ + static const int classes[] = {-1, -1, 255, 0xffff}; +#endif + int max = classes[0]; + int prev = 0; + + av_assert2((((int)blk) & 15) == 0); + + bi->area_q[0] = bi->area_q[1] = bi->area_q[2] = bi->area_q[3] = 0; + bi->partial_bit_count = 0; + bi->partial_bit_buffer = 0; + bi->cur_ac = 0; + if (data) { + bi->dct_mode = dv_guess_dct_mode(s, data, linesize); + s->get_pixels(blk, data, linesize); + s->fdct[bi->dct_mode](blk); + } else { + /* We rely on the fact that encoding all zeros leads to an immediate EOB, + which is precisely what the spec calls for in the "dummy" blocks. */ + memset(blk, 0, 64*sizeof(*blk)); + bi->dct_mode = 0; + } + bi->mb[0] = blk[0]; + + zigzag_scan = bi->dct_mode ? ff_zigzag248_direct : ff_zigzag_direct; + weight = bi->dct_mode ? dv_weight_248 : dv_weight_88; + + for (area = 0; area < 4; area++) { + bi->prev[area] = prev; + bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) + for (i = mb_area_start[area]; i < mb_area_start[area+1]; i++) { + int level = blk[zigzag_scan[i]]; + + if (level + 15 > 30U) { + bi->sign[i] = (level >> 31) & 1; + /* weight it and and shift down into range, adding for rounding */ + /* the extra division by a factor of 2^4 reverses the 8x expansion of the DCT + AND the 2x doubling of the weights */ + level = (FFABS(level) * weight[i] + (1 << (dv_weight_bits+3))) >> (dv_weight_bits+4); + bi->mb[i] = level; + if (level > max) + max = level; + bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level); + bi->next[prev]= i; + prev = i; + } + } + } + bi->next[prev]= i; + for (bi->cno = 0; max > classes[bi->cno]; bi->cno++); + + bi->cno += bias; + + if (bi->cno >= 3) { + bi->cno = 3; + prev = 0; + i = bi->next[prev]; + for (area = 0; area < 4; area++) { + bi->prev[area] = prev; + bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :) + for (; i < mb_area_start[area+1]; i = bi->next[i]) { + bi->mb[i] >>= 1; + + if (bi->mb[i]) { + bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]); + bi->next[prev]= i; + prev = i; + } + } + } + bi->next[prev]= i; + } + + return bi->bit_size[0] + bi->bit_size[1] + bi->bit_size[2] + bi->bit_size[3]; +} + +static inline void dv_guess_qnos(EncBlockInfo* blks, int* qnos) +{ + int size[5]; + int i, j, k, a, prev, a2; + EncBlockInfo* b; + + size[0] = size[1] = size[2] = size[3] = size[4] = 1 << 24; + do { + b = blks; + for (i = 0; i < 5; i++) { + if (!qnos[i]) + continue; + + qnos[i]--; + size[i] = 0; + for (j = 0; j < 6; j++, b++) { + for (a = 0; a < 4; a++) { + if (b->area_q[a] != ff_dv_quant_shifts[qnos[i] + ff_dv_quant_offset[b->cno]][a]) { + b->bit_size[a] = 1; // 4 areas 4 bits for EOB :) + b->area_q[a]++; + prev = b->prev[a]; + av_assert2(b->next[prev] >= mb_area_start[a+1] || b->mb[prev]); + for (k = b->next[prev] ; k < mb_area_start[a+1]; k = b->next[k]) { + b->mb[k] >>= 1; + if (b->mb[k]) { + b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]); + prev = k; + } else { + if (b->next[k] >= mb_area_start[a+1] && b->next[k]<64){ + for (a2 = a + 1; b->next[k] >= mb_area_start[a2+1]; a2++) + b->prev[a2] = prev; + av_assert2(a2 < 4); + av_assert2(b->mb[b->next[k]]); + b->bit_size[a2] += dv_rl2vlc_size(b->next[k] - prev - 1, b->mb[b->next[k]]) + -dv_rl2vlc_size(b->next[k] - k - 1, b->mb[b->next[k]]); + av_assert2(b->prev[a2] == k && (a2 + 1 >= 4 || b->prev[a2+1] != k)); + b->prev[a2] = prev; + } + b->next[prev] = b->next[k]; + } + } + b->prev[a+1]= prev; + } + size[i] += b->bit_size[a]; + } + } + if (vs_total_ac_bits >= size[0] + size[1] + size[2] + size[3] + size[4]) + return; + } + } while (qnos[0]|qnos[1]|qnos[2]|qnos[3]|qnos[4]); + + + for (a = 2; a == 2 || vs_total_ac_bits < size[0]; a += a){ + b = blks; + size[0] = 5 * 6 * 4; //EOB + for (j = 0; j < 6 *5; j++, b++) { + prev = b->prev[0]; + for (k = b->next[prev]; k < 64; k = b->next[k]) { + if (b->mb[k] < a && b->mb[k] > -a){ + b->next[prev] = b->next[k]; + }else{ + size[0] += dv_rl2vlc_size(k - prev - 1, b->mb[k]); + prev = k; + } + } + } + } +} + +static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) +{ + DVVideoContext *s = avctx->priv_data; + DVwork_chunk *work_chunk = arg; + int mb_index, i, j; + int mb_x, mb_y, c_offset, linesize, y_stride; + uint8_t* y_ptr; + uint8_t* dif; + LOCAL_ALIGNED_8(uint8_t, scratch, [128]); + EncBlockInfo enc_blks[5*DV_MAX_BPM]; + PutBitContext pbs[5*DV_MAX_BPM]; + PutBitContext* pb; + EncBlockInfo* enc_blk; + int vs_bit_size = 0; + int qnos[5] = {15, 15, 15, 15, 15}; /* No quantization */ + int* qnosp = &qnos[0]; + + dif = &s->buf[work_chunk->buf_offset*80]; + enc_blk = &enc_blks[0]; + for (mb_index = 0; mb_index < 5; mb_index++) { + dv_calculate_mb_xy(s, work_chunk, mb_index, &mb_x, &mb_y); + + /* initializing luminance blocks */ + if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || + (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) || + (s->sys->height >= 720 && mb_y != 134)) { + y_stride = s->picture.linesize[0] << 3; + } else { + y_stride = 16; + } + y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x) << 3); + linesize = s->picture.linesize[0]; + + if (s->sys->video_stype == 4) { /* SD 422 */ + vs_bit_size += + dv_init_enc_block(enc_blk+0, y_ptr , linesize, s, 0) + + dv_init_enc_block(enc_blk+1, NULL , linesize, s, 0) + + dv_init_enc_block(enc_blk+2, y_ptr + 8 , linesize, s, 0) + + dv_init_enc_block(enc_blk+3, NULL , linesize, s, 0); + } else { + vs_bit_size += + dv_init_enc_block(enc_blk+0, y_ptr , linesize, s, 0) + + dv_init_enc_block(enc_blk+1, y_ptr + 8 , linesize, s, 0) + + dv_init_enc_block(enc_blk+2, y_ptr + y_stride, linesize, s, 0) + + dv_init_enc_block(enc_blk+3, y_ptr + 8 + y_stride, linesize, s, 0); + } + enc_blk += 4; + + /* initializing chrominance blocks */ + c_offset = (((mb_y >> (s->sys->pix_fmt == AV_PIX_FMT_YUV420P)) * s->picture.linesize[1] + + (mb_x >> ((s->sys->pix_fmt == AV_PIX_FMT_YUV411P) ? 2 : 1))) << 3); + for (j = 2; j; j--) { + uint8_t *c_ptr = s->picture.data[j] + c_offset; + linesize = s->picture.linesize[j]; + y_stride = (mb_y == 134) ? 8 : (s->picture.linesize[j] << 3); + if (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) { + uint8_t* d; + uint8_t* b = scratch; + for (i = 0; i < 8; i++) { + d = c_ptr + (linesize << 3); + b[0] = c_ptr[0]; b[1] = c_ptr[1]; b[2] = c_ptr[2]; b[3] = c_ptr[3]; + b[4] = d[0]; b[5] = d[1]; b[6] = d[2]; b[7] = d[3]; + c_ptr += linesize; + b += 16; + } + c_ptr = scratch; + linesize = 16; + } + + vs_bit_size += dv_init_enc_block( enc_blk++, c_ptr , linesize, s, 1); + if (s->sys->bpm == 8) { + vs_bit_size += dv_init_enc_block(enc_blk++, c_ptr + y_stride, linesize, s, 1); + } + } + } + + if (vs_total_ac_bits < vs_bit_size) + dv_guess_qnos(&enc_blks[0], qnosp); + + /* DIF encoding process */ + for (j=0; j<5*s->sys->bpm;) { + int start_mb = j; + + dif[3] = *qnosp++; + dif += 4; + + /* First pass over individual cells only */ + for (i=0; isys->bpm; i++, j++) { + int sz = s->sys->block_sizes[i]>>3; + + init_put_bits(&pbs[j], dif, sz); + put_sbits(&pbs[j], 9, ((enc_blks[j].mb[0] >> 3) - 1024 + 2) >> 2); + put_bits(&pbs[j], 1, enc_blks[j].dct_mode); + put_bits(&pbs[j], 2, enc_blks[j].cno); + + dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j+1]); + dif += sz; + } + + /* Second pass over each MB space */ + pb = &pbs[start_mb]; + for (i=0; isys->bpm; i++) { + if (enc_blks[start_mb+i].partial_bit_count) + pb = dv_encode_ac(&enc_blks[start_mb+i], pb, &pbs[start_mb+s->sys->bpm]); + } + } + + /* Third and final pass over the whole video segment space */ + pb = &pbs[0]; + for (j=0; j<5*s->sys->bpm; j++) { + if (enc_blks[j].partial_bit_count) + pb = dv_encode_ac(&enc_blks[j], pb, &pbs[s->sys->bpm*5]); + if (enc_blks[j].partial_bit_count) + av_log(avctx, AV_LOG_ERROR, "ac bitstream overflow\n"); + } + + for (j=0; j<5*s->sys->bpm; j++) { + int pos; + int size = pbs[j].size_in_bits >> 3; + flush_put_bits(&pbs[j]); + pos = put_bits_count(&pbs[j]) >> 3; + if (pos > size) { + av_log(avctx, AV_LOG_ERROR, "bitstream written beyond buffer size\n"); + return -1; + } + memset(pbs[j].buf + pos, 0xff, size - pos); + } + + return 0; +} + +static inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c, + uint8_t* buf) +{ + /* + * Here's what SMPTE314M says about these two: + * (page 6) APTn, AP1n, AP2n, AP3n: These data shall be identical + * as track application IDs (APTn = 001, AP1n = + * 001, AP2n = 001, AP3n = 001), if the source signal + * comes from a digital VCR. If the signal source is + * unknown, all bits for these data shall be set to 1. + * (page 12) STYPE: STYPE defines a signal type of video signal + * 00000b = 4:1:1 compression + * 00100b = 4:2:2 compression + * XXXXXX = Reserved + * Now, I've got two problems with these statements: + * 1. it looks like APT == 111b should be a safe bet, but it isn't. + * It seems that for PAL as defined in IEC 61834 we have to set + * APT to 000 and for SMPTE314M to 001. + * 2. It is not at all clear what STYPE is used for 4:2:0 PAL + * compression scheme (if any). + */ + int apt = (c->sys->pix_fmt == AV_PIX_FMT_YUV420P ? 0 : 1); + int fs = c->picture.top_field_first ? 0x00 : 0x40; + + uint8_t aspect = 0; + if ((int)(av_q2d(c->avctx->sample_aspect_ratio) * c->avctx->width / c->avctx->height * 10) >= 17) /* 16:9 */ + aspect = 0x02; + + buf[0] = (uint8_t)pack_id; + switch (pack_id) { + case dv_header525: /* I can't imagine why these two weren't defined as real */ + case dv_header625: /* packs in SMPTE314M -- they definitely look like ones */ + buf[1] = 0xf8 | /* reserved -- always 1 */ + (apt & 0x07); /* APT: Track application ID */ + buf[2] = (0 << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP1: Audio application ID */ + buf[3] = (0 << 7) | /* TF2: video data is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP2: Video application ID */ + buf[4] = (0 << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */ + (0x0f << 3) | /* reserved -- always 1 */ + (apt & 0x07); /* AP3: Subcode application ID */ + break; + case dv_video_source: + buf[1] = 0xff; /* reserved -- always 1 */ + buf[2] = (1 << 7) | /* B/W: 0 - b/w, 1 - color */ + (1 << 6) | /* following CLF is valid - 0, invalid - 1 */ + (3 << 4) | /* CLF: color frames ID (see ITU-R BT.470-4) */ + 0xf; /* reserved -- always 1 */ + buf[3] = (3 << 6) | /* reserved -- always 1 */ + (c->sys->dsf << 5) | /* system: 60fields/50fields */ + c->sys->video_stype; /* signal type video compression */ + buf[4] = 0xff; /* VISC: 0xff -- no information */ + break; + case dv_video_control: + buf[1] = (0 << 6) | /* Copy generation management (CGMS) 0 -- free */ + 0x3f; /* reserved -- always 1 */ + buf[2] = 0xc8 | /* reserved -- always b11001xxx */ + aspect; + buf[3] = (1 << 7) | /* frame/field flag 1 -- frame, 0 -- field */ + fs | /* first/second field flag 0 -- field 2, 1 -- field 1 */ + (1 << 5) | /* frame change flag 0 -- same picture as before, 1 -- different */ + (1 << 4) | /* 1 - interlaced, 0 - noninterlaced */ + 0xc; /* reserved -- always b1100 */ + buf[4] = 0xff; /* reserved -- always 1 */ + break; + default: + buf[1] = buf[2] = buf[3] = buf[4] = 0xff; + } + return 5; +} + +#if CONFIG_DVVIDEO_ENCODER +static inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num, + uint8_t seq_num, uint8_t dif_num, + uint8_t* buf) +{ + buf[0] = (uint8_t)t; /* Section type */ + buf[1] = (seq_num << 4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */ + (chan_num << 3) | /* FSC: for 50Mb/s 0 - first channel; 1 - second */ + 7; /* reserved -- always 1 */ + buf[2] = dif_num; /* DIF block number Video: 0-134, Audio: 0-8 */ + return 3; +} + + +static inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t* buf) +{ + if (syb_num == 0 || syb_num == 6) { + buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */ + (0 << 4) | /* AP3 (Subcode application ID) */ + 0x0f; /* reserved -- always 1 */ + } + else if (syb_num == 11) { + buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */ + 0x7f; /* reserved -- always 1 */ + } + else { + buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */ + (0 << 4) | /* APT (Track application ID) */ + 0x0f; /* reserved -- always 1 */ + } + buf[1] = 0xf0 | /* reserved -- always 1 */ + (syb_num & 0x0f); /* SSYB number 0 - 11 */ + buf[2] = 0xff; /* reserved -- always 1 */ + return 3; +} + +static void dv_format_frame(DVVideoContext* c, uint8_t* buf) +{ + int chan, i, j, k; + + for (chan = 0; chan < c->sys->n_difchan; chan++) { + for (i = 0; i < c->sys->difseg_size; i++) { + memset(buf, 0xff, 80 * 6); /* first 6 DIF blocks are for control data */ + + /* DV header: 1DIF */ + buf += dv_write_dif_id(dv_sect_header, chan, i, 0, buf); + buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525), c, buf); + buf += 72; /* unused bytes */ + + /* DV subcode: 2DIFs */ + for (j = 0; j < 2; j++) { + buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf); + for (k = 0; k < 6; k++) + buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf) + 5; + buf += 29; /* unused bytes */ + } + + /* DV VAUX: 3DIFS */ + for (j = 0; j < 3; j++) { + buf += dv_write_dif_id(dv_sect_vaux, chan, i, j, buf); + buf += dv_write_pack(dv_video_source, c, buf); + buf += dv_write_pack(dv_video_control, c, buf); + buf += 7*5; + buf += dv_write_pack(dv_video_source, c, buf); + buf += dv_write_pack(dv_video_control, c, buf); + buf += 4*5 + 2; /* unused bytes */ + } + + /* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */ + for (j = 0; j < 135; j++) { + if (j%15 == 0) { + memset(buf, 0xff, 80); + buf += dv_write_dif_id(dv_sect_audio, chan, i, j/15, buf); + buf += 77; /* audio control & shuffled PCM audio */ + } + buf += dv_write_dif_id(dv_sect_video, chan, i, j, buf); + buf += 77; /* 1 video macroblock: 1 bytes control + 4 * 14 bytes Y 8x8 data + 10 bytes Cr 8x8 data + 10 bytes Cb 8x8 data */ + } + } + } +} + + +static int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + DVVideoContext *s = c->priv_data; + int ret; + + s->sys = avpriv_dv_codec_profile(c); + if (!s->sys || ff_dv_init_dynamic_tables(s->sys)) + return -1; + if ((ret = ff_alloc_packet2(c, pkt, s->sys->frame_size)) < 0) + return ret; + + c->pix_fmt = s->sys->pix_fmt; + s->picture = *frame; + s->picture.key_frame = 1; + s->picture.pict_type = AV_PICTURE_TYPE_I; + + s->buf = pkt->data; + c->execute(c, dv_encode_video_segment, s->sys->work_chunks, NULL, + dv_work_pool_size(s->sys), sizeof(DVwork_chunk)); + + emms_c(); + + dv_format_frame(s, pkt->data); + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +AVCodec ff_dvvideo_encoder = { + .name = "dvvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DVVIDEO, + .priv_data_size = sizeof(DVVideoContext), + .init = dvvideo_init_encoder, + .encode2 = dvvideo_encode_frame, + .capabilities = CODEC_CAP_SLICE_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), +}; +#endif // CONFIG_DVVIDEO_ENCODER diff --git a/ffmpeg/libavcodec/dv_profile.c b/ffmpeg/libavcodec/dv_profile.c new file mode 100644 index 0000000..a1d9881 --- /dev/null +++ b/ffmpeg/libavcodec/dv_profile.c @@ -0,0 +1,360 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "dv_profile.h" + +static DVwork_chunk work_chunks_dv25pal [1*12*27]; +static DVwork_chunk work_chunks_dv25pal411[1*12*27]; +static DVwork_chunk work_chunks_dv25ntsc [1*10*27]; +static DVwork_chunk work_chunks_dv50pal [2*12*27]; +static DVwork_chunk work_chunks_dv50ntsc [2*10*27]; +static DVwork_chunk work_chunks_dv100palp [2*12*27]; +static DVwork_chunk work_chunks_dv100ntscp[2*10*27]; +static DVwork_chunk work_chunks_dv100pali [4*12*27]; +static DVwork_chunk work_chunks_dv100ntsci[4*10*27]; + +static uint32_t dv_idct_factor_sd [2*2*22*64]; +static uint32_t dv_idct_factor_hd1080[2*4*16*64]; +static uint32_t dv_idct_factor_hd720 [2*4*16*64]; + +static const uint8_t dv_audio_shuffle525[10][9] = { + { 0, 30, 60, 20, 50, 80, 10, 40, 70 }, /* 1st channel */ + { 6, 36, 66, 26, 56, 86, 16, 46, 76 }, + { 12, 42, 72, 2, 32, 62, 22, 52, 82 }, + { 18, 48, 78, 8, 38, 68, 28, 58, 88 }, + { 24, 54, 84, 14, 44, 74, 4, 34, 64 }, + + { 1, 31, 61, 21, 51, 81, 11, 41, 71 }, /* 2nd channel */ + { 7, 37, 67, 27, 57, 87, 17, 47, 77 }, + { 13, 43, 73, 3, 33, 63, 23, 53, 83 }, + { 19, 49, 79, 9, 39, 69, 29, 59, 89 }, + { 25, 55, 85, 15, 45, 75, 5, 35, 65 }, +}; + +static const uint8_t dv_audio_shuffle625[12][9] = { + { 0, 36, 72, 26, 62, 98, 16, 52, 88}, /* 1st channel */ + { 6, 42, 78, 32, 68, 104, 22, 58, 94}, + { 12, 48, 84, 2, 38, 74, 28, 64, 100}, + { 18, 54, 90, 8, 44, 80, 34, 70, 106}, + { 24, 60, 96, 14, 50, 86, 4, 40, 76}, + { 30, 66, 102, 20, 56, 92, 10, 46, 82}, + + { 1, 37, 73, 27, 63, 99, 17, 53, 89}, /* 2nd channel */ + { 7, 43, 79, 33, 69, 105, 23, 59, 95}, + { 13, 49, 85, 3, 39, 75, 29, 65, 101}, + { 19, 55, 91, 9, 45, 81, 35, 71, 107}, + { 25, 61, 97, 15, 51, 87, 5, 41, 77}, + { 31, 67, 103, 21, 57, 93, 11, 47, 83}, +}; + +/* macroblock bit budgets */ +static const uint8_t block_sizes_dv2550[8] = { + 112, 112, 112, 112, 80, 80, 0, 0, +}; + +static const uint8_t block_sizes_dv100[8] = { + 80, 80, 80, 80, 80, 80, 64, 64, +}; + +static const DVprofile dv_profiles[] = { + { .dsf = 0, + .video_stype = 0x0, + .frame_size = 120000, /* IEC 61834, SMPTE-314M - 525/60 (NTSC) */ + .difseg_size = 10, + .n_difchan = 1, + .time_base = { 1001, 30000 }, + .ltc_divisor = 30, + .height = 480, + .width = 720, + .sar = {{8, 9}, {32, 27}}, + .work_chunks = &work_chunks_dv25ntsc[0], + .idct_factor = &dv_idct_factor_sd[0], + .pix_fmt = AV_PIX_FMT_YUV411P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 90, + .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, + }, + { .dsf = 1, + .video_stype = 0x0, + .frame_size = 144000, /* IEC 61834 - 625/50 (PAL) */ + .difseg_size = 12, + .n_difchan = 1, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = {{16, 15}, {64, 45}}, + .work_chunks = &work_chunks_dv25pal[0], + .idct_factor = &dv_idct_factor_sd[0], + .pix_fmt = AV_PIX_FMT_YUV420P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + }, + { .dsf = 1, + .video_stype = 0x0, + .frame_size = 144000, /* SMPTE-314M - 625/50 (PAL) */ + .difseg_size = 12, + .n_difchan = 1, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = {{16, 15}, {64, 45}}, + .work_chunks = &work_chunks_dv25pal411[0], + .idct_factor = &dv_idct_factor_sd[0], + .pix_fmt = AV_PIX_FMT_YUV411P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + }, + { .dsf = 0, + .video_stype = 0x4, + .frame_size = 240000, /* SMPTE-314M - 525/60 (NTSC) 50 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO50" */ + .n_difchan = 2, + .time_base = { 1001, 30000 }, + .ltc_divisor = 30, + .height = 480, + .width = 720, + .sar = {{8, 9}, {32, 27}}, + .work_chunks = &work_chunks_dv50ntsc[0], + .idct_factor = &dv_idct_factor_sd[0], + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 90, + .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, + }, + { .dsf = 1, + .video_stype = 0x4, + .frame_size = 288000, /* SMPTE-314M - 625/50 (PAL) 50 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO50" */ + .n_difchan = 2, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = {{16, 15}, {64, 45}}, + .work_chunks = &work_chunks_dv50pal[0], + .idct_factor = &dv_idct_factor_sd[0], + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + }, + { .dsf = 0, + .video_stype = 0x14, + .frame_size = 480000, /* SMPTE-370M - 1080i60 100 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .time_base = { 1001, 30000 }, + .ltc_divisor = 30, + .height = 1080, + .width = 1280, + .sar = {{1, 1}, {3, 2}}, + .work_chunks = &work_chunks_dv100ntsci[0], + .idct_factor = &dv_idct_factor_hd1080[0], + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 90, + .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, + }, + { .dsf = 1, + .video_stype = 0x14, + .frame_size = 576000, /* SMPTE-370M - 1080i50 100 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO HD" */ + .n_difchan = 4, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 1080, + .width = 1440, + .sar = {{1, 1}, {4, 3}}, + .work_chunks = &work_chunks_dv100pali[0], + .idct_factor = &dv_idct_factor_hd1080[0], + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 108, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + }, + { .dsf = 0, + .video_stype = 0x18, + .frame_size = 240000, /* SMPTE-370M - 720p60 100 Mbps */ + .difseg_size = 10, /* also known as "DVCPRO HD" */ + .n_difchan = 2, + .time_base = { 1001, 60000 }, + .ltc_divisor = 60, + .height = 720, + .width = 960, + .sar = {{1, 1}, {4, 3}}, + .work_chunks = &work_chunks_dv100ntscp[0], + .idct_factor = &dv_idct_factor_hd720[0], + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 90, + .audio_min_samples = { 1580, 1452, 1053 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1600, 1602, 1602, 1602, 1602 }, /* per SMPTE-314M */ + .audio_shuffle = dv_audio_shuffle525, + }, + { .dsf = 1, + .video_stype = 0x18, + .frame_size = 288000, /* SMPTE-370M - 720p50 100 Mbps */ + .difseg_size = 12, /* also known as "DVCPRO HD" */ + .n_difchan = 2, + .time_base = { 1, 50 }, + .ltc_divisor = 50, + .height = 720, + .width = 960, + .sar = {{1, 1}, {4, 3}}, + .work_chunks = &work_chunks_dv100palp[0], + .idct_factor = &dv_idct_factor_hd720[0], + .pix_fmt = AV_PIX_FMT_YUV422P, + .bpm = 8, + .block_sizes = block_sizes_dv100, + .audio_stride = 90, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + }, + { .dsf = 1, + .video_stype = 0x1, + .frame_size = 144000, /* IEC 61883-5 - 625/50 (PAL) */ + .difseg_size = 12, + .n_difchan = 1, + .time_base = { 1, 25 }, + .ltc_divisor = 25, + .height = 576, + .width = 720, + .sar = {{16, 15}, {64, 45}}, + .work_chunks = &work_chunks_dv25pal[0], + .idct_factor = &dv_idct_factor_sd[0], + .pix_fmt = AV_PIX_FMT_YUV420P, + .bpm = 6, + .block_sizes = block_sizes_dv2550, + .audio_stride = 108, + .audio_min_samples = { 1896, 1742, 1264 }, /* for 48, 44.1 and 32kHz */ + .audio_samples_dist = { 1920, 1920, 1920, 1920, 1920 }, + .audio_shuffle = dv_audio_shuffle625, + } +}; + +const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile *sys, + const uint8_t* frame, unsigned buf_size) +{ + int i, dsf, stype; + + if(buf_size < DV_PROFILE_BYTES) + return NULL; + + dsf = (frame[3] & 0x80) >> 7; + stype = frame[80 * 5 + 48 + 3] & 0x1f; + + /* 576i50 25Mbps 4:1:1 is a special case */ + if ((dsf == 1 && stype == 0 && frame[4] & 0x07 /* the APT field */) || + (stype == 31 && codec && codec->codec_tag==AV_RL32("SL25") && codec->coded_width==720 && codec->coded_height==576)) { + return &dv_profiles[2]; + } + + if( stype == 0 + && codec + && (codec->codec_tag==AV_RL32("dvsd") || codec->codec_tag==AV_RL32("CDVC")) + && codec->coded_width ==720 + && codec->coded_height==576) + return &dv_profiles[1]; + + for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) + if (dsf == dv_profiles[i].dsf && stype == dv_profiles[i].video_stype) + return &dv_profiles[i]; + + /* check if old sys matches and assumes corrupted input */ + if (sys && buf_size == sys->frame_size) + return sys; + + /* hack for trac issue #217, dv files created with QuickTime 3 */ + if ((frame[3] & 0x7f) == 0x3f && frame[80 * 5 + 48 + 3] == 0xff) + return &dv_profiles[dsf]; + + return NULL; +} + +const DVprofile* avpriv_dv_frame_profile(const DVprofile *sys, + const uint8_t* frame, unsigned buf_size) +{ + return avpriv_dv_frame_profile2(NULL, sys, frame, buf_size); +} + +const DVprofile* avpriv_dv_codec_profile(AVCodecContext* codec) +{ + int i; + int w, h; + + if (codec->coded_width || codec->coded_height) { + w = codec->coded_width; + h = codec->coded_height; + } else { + w = codec->width; + h = codec->height; + } + + for (i=0; ipix_fmt == dv_profiles[i].pix_fmt && + w == dv_profiles[i].width) + return &dv_profiles[i]; + + return NULL; +} + +void ff_dv_print_profiles(void *logctx, int loglevel) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++) { + const DVprofile *p = &dv_profiles[i]; + av_log(logctx, loglevel, "Frame size: %dx%d; pixel format: %s, " + "framerate: %d/%d\n", p->width, p->height, av_get_pix_fmt_name(p->pix_fmt), + p->time_base.den, p->time_base.num); + } +} diff --git a/ffmpeg/libavcodec/dv_profile.h b/ffmpeg/libavcodec/dv_profile.h new file mode 100644 index 0000000..97edce9 --- /dev/null +++ b/ffmpeg/libavcodec/dv_profile.h @@ -0,0 +1,78 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DV_PROFILE_H +#define AVCODEC_DV_PROFILE_H + +#include + +#include "libavutil/pixfmt.h" +#include "libavutil/rational.h" +#include "avcodec.h" + +/* minimum number of bytes to read from a DV stream in order to + determine the profile */ +#define DV_PROFILE_BYTES (6*80) /* 6 DIF blocks */ + +typedef struct DVwork_chunk { + uint16_t buf_offset; + uint16_t mb_coordinates[5]; +} DVwork_chunk; + +/* + * DVprofile is used to express the differences between various + * DV flavors. For now it's primarily used for differentiating + * 525/60 and 625/50, but the plans are to use it for various + * DV specs as well (e.g. SMPTE314M vs. IEC 61834). + */ +typedef struct DVprofile { + int dsf; /* value of the dsf in the DV header */ + int video_stype; /* stype for VAUX source pack */ + int frame_size; /* total size of one frame in bytes */ + int difseg_size; /* number of DIF segments per DIF channel */ + int n_difchan; /* number of DIF channels per frame */ + AVRational time_base; /* 1/framerate */ + int ltc_divisor; /* FPS from the LTS standpoint */ + int height; /* picture height in pixels */ + int width; /* picture width in pixels */ + AVRational sar[2]; /* sample aspect ratios for 4:3 and 16:9 */ + DVwork_chunk *work_chunks; /* each thread gets its own chunk of frame to work on */ + uint32_t *idct_factor; /* set of iDCT factor tables */ + enum AVPixelFormat pix_fmt; /* picture pixel format */ + int bpm; /* blocks per macroblock */ + const uint8_t *block_sizes; /* AC block sizes, in bits */ + int audio_stride; /* size of audio_shuffle table */ + int audio_min_samples[3]; /* min amount of audio samples */ + /* for 48kHz, 44.1kHz and 32kHz */ + int audio_samples_dist[5]; /* how many samples are supposed to be */ + /* in each frame in a 5 frames window */ + const uint8_t (*audio_shuffle)[9]; /* PCM shuffling table */ +} DVprofile; + +const DVprofile* avpriv_dv_frame_profile(const DVprofile *sys, + const uint8_t* frame, unsigned buf_size); +const DVprofile* avpriv_dv_frame_profile2(AVCodecContext* codec, const DVprofile *sys, + const uint8_t* frame, unsigned buf_size); +const DVprofile* avpriv_dv_codec_profile(AVCodecContext* codec); + +/** + * Print all allowed DV profiles into logctx at specified logging level. + */ +void ff_dv_print_profiles(void *logctx, int loglevel); + +#endif /* AVCODEC_DV_PROFILE_H */ diff --git a/ffmpeg/libavcodec/dv_tablegen.c b/ffmpeg/libavcodec/dv_tablegen.c new file mode 100644 index 0000000..5d3793e --- /dev/null +++ b/ffmpeg/libavcodec/dv_tablegen.c @@ -0,0 +1,47 @@ +/* + * Generate a header file for hardcoded DV tables + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#ifndef CONFIG_SMALL +#error CONFIG_SMALL must be defined to generate tables +#endif +#include "dv_tablegen.h" +#include "tableprint.h" +#include + +WRITE_1D_FUNC_ARGV(dv_vlc_pair, 7, + "{0x%"PRIx32", %"PRId8"}", data[i].vlc, data[i].size) +WRITE_2D_FUNC(dv_vlc_pair) + +int main(void) +{ + dv_vlc_map_tableinit(); + + write_fileheader(); + + printf("static const struct dv_vlc_pair dv_vlc_map[DV_VLC_MAP_RUN_SIZE][DV_VLC_MAP_LEV_SIZE] = {\n"); + write_dv_vlc_pair_2d_array(dv_vlc_map, DV_VLC_MAP_RUN_SIZE, DV_VLC_MAP_LEV_SIZE); + printf("};\n"); + + return 0; +} diff --git a/ffmpeg/libavcodec/dv_tablegen.h b/ffmpeg/libavcodec/dv_tablegen.h new file mode 100644 index 0000000..e8cdc21 --- /dev/null +++ b/ffmpeg/libavcodec/dv_tablegen.h @@ -0,0 +1,97 @@ +/* + * Header file for hardcoded DV tables + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_DV_TABLEGEN_H +#define AVCODEC_DV_TABLEGEN_H + +#include + +#include "dv_vlc_data.h" + +#if CONFIG_SMALL +#define DV_VLC_MAP_RUN_SIZE 15 +#define DV_VLC_MAP_LEV_SIZE 23 +#else +#define DV_VLC_MAP_RUN_SIZE 64 +#define DV_VLC_MAP_LEV_SIZE 512 //FIXME sign was removed so this should be /2 but needs check +#endif + +/* VLC encoding lookup table */ +typedef struct dv_vlc_pair { + uint32_t vlc; + uint32_t size; +} dv_vlc_pair; + +#if CONFIG_HARDCODED_TABLES +#define dv_vlc_map_tableinit() +#include "libavcodec/dv_tables.h" +#else +static struct dv_vlc_pair dv_vlc_map[DV_VLC_MAP_RUN_SIZE][DV_VLC_MAP_LEV_SIZE]; + +static void dv_vlc_map_tableinit(void) +{ + int i, j; + for (i = 0; i < NB_DV_VLC - 1; i++) { + if (dv_vlc_run[i] >= DV_VLC_MAP_RUN_SIZE) + continue; +#if CONFIG_SMALL + if (dv_vlc_level[i] >= DV_VLC_MAP_LEV_SIZE) + continue; +#endif + + if (dv_vlc_map[dv_vlc_run[i]][dv_vlc_level[i]].size != 0) + continue; + + dv_vlc_map[dv_vlc_run[i]][dv_vlc_level[i]].vlc = + dv_vlc_bits[i] << (!!dv_vlc_level[i]); + dv_vlc_map[dv_vlc_run[i]][dv_vlc_level[i]].size = + dv_vlc_len[i] + (!!dv_vlc_level[i]); + } + for (i = 0; i < DV_VLC_MAP_RUN_SIZE; i++) { +#if CONFIG_SMALL + for (j = 1; j < DV_VLC_MAP_LEV_SIZE; j++) { + if (dv_vlc_map[i][j].size == 0) { + dv_vlc_map[i][j].vlc = dv_vlc_map[0][j].vlc | + (dv_vlc_map[i-1][0].vlc << (dv_vlc_map[0][j].size)); + dv_vlc_map[i][j].size = dv_vlc_map[i-1][0].size + + dv_vlc_map[0][j].size; + } + } +#else + for (j = 1; j < DV_VLC_MAP_LEV_SIZE/2; j++) { + if (dv_vlc_map[i][j].size == 0) { + dv_vlc_map[i][j].vlc = dv_vlc_map[0][j].vlc | + (dv_vlc_map[i-1][0].vlc << (dv_vlc_map[0][j].size)); + dv_vlc_map[i][j].size = dv_vlc_map[i-1][0].size + + dv_vlc_map[0][j].size; + } + dv_vlc_map[i][((uint16_t)(-j))&0x1ff].vlc = + dv_vlc_map[i][j].vlc | 1; + dv_vlc_map[i][((uint16_t)(-j))&0x1ff].size = + dv_vlc_map[i][j].size; + } +#endif + } +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_DV_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/dv_vlc_data.h b/ffmpeg/libavcodec/dv_vlc_data.h new file mode 100644 index 0000000..be768e6 --- /dev/null +++ b/ffmpeg/libavcodec/dv_vlc_data.h @@ -0,0 +1,259 @@ +/* + * VLC constants for DV codec + * Copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * VLC constants for DV codec. + */ + +#ifndef AVCODEC_DV_VLC_DATA_H +#define AVCODEC_DV_VLC_DATA_H + +#include + +#define NB_DV_VLC 409 + +/* + * There's a catch about the following three tables: the mapping they establish + * between (run, level) and vlc is not 1-1. So you have to watch out for that + * when building misc. tables. E.g. (1, 0) can be either 0x7cf or 0x1f82. + */ +static const uint16_t dv_vlc_bits[NB_DV_VLC] = { + 0x0000, 0x0002, 0x0007, 0x0008, 0x0009, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0030, 0x0031, 0x0032, 0x0033, 0x0068, 0x0069, 0x006a, + 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x00e0, 0x00e1, 0x00e2, + 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, + 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, 0x01e0, 0x01e1, 0x01e2, + 0x01e3, 0x01e4, 0x01e5, 0x01e6, 0x01e7, 0x01e8, 0x01e9, 0x01ea, + 0x01eb, 0x01ec, 0x01ed, 0x01ee, 0x01ef, 0x03e0, 0x03e1, 0x03e2, + 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x07ce, 0x07cf, 0x07d0, 0x07d1, + 0x07d2, 0x07d3, 0x07d4, 0x07d5, 0x0fac, 0x0fad, 0x0fae, 0x0faf, + 0x0fb0, 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, + 0x0fb8, 0x0fb9, 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, + 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87, + 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, + 0x1f90, 0x1f91, 0x1f92, 0x1f93, 0x1f94, 0x1f95, 0x1f96, 0x1f97, + 0x1f98, 0x1f99, 0x1f9a, 0x1f9b, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, + 0x1fa0, 0x1fa1, 0x1fa2, 0x1fa3, 0x1fa4, 0x1fa5, 0x1fa6, 0x1fa7, + 0x1fa8, 0x1fa9, 0x1faa, 0x1fab, 0x1fac, 0x1fad, 0x1fae, 0x1faf, + 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4, 0x1fb5, 0x1fb6, 0x1fb7, + 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb, 0x1fbc, 0x1fbd, 0x1fbe, 0x1fbf, + 0x7f00, 0x7f01, 0x7f02, 0x7f03, 0x7f04, 0x7f05, 0x7f06, 0x7f07, + 0x7f08, 0x7f09, 0x7f0a, 0x7f0b, 0x7f0c, 0x7f0d, 0x7f0e, 0x7f0f, + 0x7f10, 0x7f11, 0x7f12, 0x7f13, 0x7f14, 0x7f15, 0x7f16, 0x7f17, + 0x7f18, 0x7f19, 0x7f1a, 0x7f1b, 0x7f1c, 0x7f1d, 0x7f1e, 0x7f1f, + 0x7f20, 0x7f21, 0x7f22, 0x7f23, 0x7f24, 0x7f25, 0x7f26, 0x7f27, + 0x7f28, 0x7f29, 0x7f2a, 0x7f2b, 0x7f2c, 0x7f2d, 0x7f2e, 0x7f2f, + 0x7f30, 0x7f31, 0x7f32, 0x7f33, 0x7f34, 0x7f35, 0x7f36, 0x7f37, + 0x7f38, 0x7f39, 0x7f3a, 0x7f3b, 0x7f3c, 0x7f3d, 0x7f3e, 0x7f3f, + 0x7f40, 0x7f41, 0x7f42, 0x7f43, 0x7f44, 0x7f45, 0x7f46, 0x7f47, + 0x7f48, 0x7f49, 0x7f4a, 0x7f4b, 0x7f4c, 0x7f4d, 0x7f4e, 0x7f4f, + 0x7f50, 0x7f51, 0x7f52, 0x7f53, 0x7f54, 0x7f55, 0x7f56, 0x7f57, + 0x7f58, 0x7f59, 0x7f5a, 0x7f5b, 0x7f5c, 0x7f5d, 0x7f5e, 0x7f5f, + 0x7f60, 0x7f61, 0x7f62, 0x7f63, 0x7f64, 0x7f65, 0x7f66, 0x7f67, + 0x7f68, 0x7f69, 0x7f6a, 0x7f6b, 0x7f6c, 0x7f6d, 0x7f6e, 0x7f6f, + 0x7f70, 0x7f71, 0x7f72, 0x7f73, 0x7f74, 0x7f75, 0x7f76, 0x7f77, + 0x7f78, 0x7f79, 0x7f7a, 0x7f7b, 0x7f7c, 0x7f7d, 0x7f7e, 0x7f7f, + 0x7f80, 0x7f81, 0x7f82, 0x7f83, 0x7f84, 0x7f85, 0x7f86, 0x7f87, + 0x7f88, 0x7f89, 0x7f8a, 0x7f8b, 0x7f8c, 0x7f8d, 0x7f8e, 0x7f8f, + 0x7f90, 0x7f91, 0x7f92, 0x7f93, 0x7f94, 0x7f95, 0x7f96, 0x7f97, + 0x7f98, 0x7f99, 0x7f9a, 0x7f9b, 0x7f9c, 0x7f9d, 0x7f9e, 0x7f9f, + 0x7fa0, 0x7fa1, 0x7fa2, 0x7fa3, 0x7fa4, 0x7fa5, 0x7fa6, 0x7fa7, + 0x7fa8, 0x7fa9, 0x7faa, 0x7fab, 0x7fac, 0x7fad, 0x7fae, 0x7faf, + 0x7fb0, 0x7fb1, 0x7fb2, 0x7fb3, 0x7fb4, 0x7fb5, 0x7fb6, 0x7fb7, + 0x7fb8, 0x7fb9, 0x7fba, 0x7fbb, 0x7fbc, 0x7fbd, 0x7fbe, 0x7fbf, + 0x7fc0, 0x7fc1, 0x7fc2, 0x7fc3, 0x7fc4, 0x7fc5, 0x7fc6, 0x7fc7, + 0x7fc8, 0x7fc9, 0x7fca, 0x7fcb, 0x7fcc, 0x7fcd, 0x7fce, 0x7fcf, + 0x7fd0, 0x7fd1, 0x7fd2, 0x7fd3, 0x7fd4, 0x7fd5, 0x7fd6, 0x7fd7, + 0x7fd8, 0x7fd9, 0x7fda, 0x7fdb, 0x7fdc, 0x7fdd, 0x7fde, 0x7fdf, + 0x7fe0, 0x7fe1, 0x7fe2, 0x7fe3, 0x7fe4, 0x7fe5, 0x7fe6, 0x7fe7, + 0x7fe8, 0x7fe9, 0x7fea, 0x7feb, 0x7fec, 0x7fed, 0x7fee, 0x7fef, + 0x7ff0, 0x7ff1, 0x7ff2, 0x7ff3, 0x7ff4, 0x7ff5, 0x7ff6, 0x7ff7, + 0x7ff8, 0x7ff9, 0x7ffa, 0x7ffb, 0x7ffc, 0x7ffd, 0x7ffe, 0x7fff, + 0x0006, +}; + +static const uint8_t dv_vlc_len[NB_DV_VLC] = { + 2, 3, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 4, +}; + +static const uint8_t dv_vlc_run[NB_DV_VLC] = { + 0, 0, 1, 0, 0, 2, 1, 0, + 0, 3, 4, 0, 0, 5, 6, 2, + 1, 1, 0, 0, 0, 7, 8, 9, + 10, 3, 4, 2, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 11, 12, 13, + 14, 5, 6, 3, 4, 2, 2, 1, + 0, 0, 0, 0, 0, 5, 3, 3, + 2, 1, 1, 1, 0, 1, 6, 4, + 3, 1, 1, 1, 2, 3, 4, 5, + 7, 8, 9, 10, 7, 8, 4, 3, + 2, 2, 2, 2, 2, 1, 1, 1, + 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, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +127, +}; + +static const uint8_t dv_vlc_level[NB_DV_VLC] = { + 1, 2, 1, 3, 4, 1, 2, 5, + 6, 1, 1, 7, 8, 1, 1, 2, + 3, 4, 9, 10, 11, 1, 1, 1, + 1, 2, 2, 3, 5, 6, 7, 12, + 13, 14, 15, 16, 17, 1, 1, 1, + 1, 2, 2, 3, 3, 4, 5, 8, + 18, 19, 20, 21, 22, 3, 4, 5, + 6, 9, 10, 11, 0, 0, 3, 4, + 6, 12, 13, 14, 0, 0, 0, 0, + 2, 2, 2, 2, 3, 3, 5, 7, + 7, 8, 9, 10, 11, 15, 16, 17, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 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, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, + 0, +}; + +#endif /* AVCODEC_DV_VLC_DATA_H */ diff --git a/ffmpeg/libavcodec/dvbsub.c b/ffmpeg/libavcodec/dvbsub.c new file mode 100644 index 0000000..562db6a --- /dev/null +++ b/ffmpeg/libavcodec/dvbsub.c @@ -0,0 +1,464 @@ +/* + * DVB subtitle encoding + * Copyright (c) 2005 Fabrice Bellard + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "libavutil/colorspace.h" + +typedef struct DVBSubtitleContext { + int object_version; +} DVBSubtitleContext; + +#define PUTBITS2(val)\ +{\ + bitbuf |= (val) << bitcnt;\ + bitcnt -= 2;\ + if (bitcnt < 0) {\ + bitcnt = 6;\ + *q++ = bitbuf;\ + bitbuf = 0;\ + }\ +} + +static void dvb_encode_rle2(uint8_t **pq, + const uint8_t *bitmap, int linesize, + int w, int h) +{ + uint8_t *q; + unsigned int bitbuf; + int bitcnt; + int x, y, len, x1, v, color; + + q = *pq; + + for(y = 0; y < h; y++) { + *q++ = 0x10; + bitbuf = 0; + bitcnt = 6; + + x = 0; + while (x < w) { + x1 = x; + color = bitmap[x1++]; + while (x1 < w && bitmap[x1] == color) + x1++; + len = x1 - x; + if (color == 0 && len == 2) { + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(1); + } else if (len >= 3 && len <= 10) { + v = len - 3; + PUTBITS2(0); + PUTBITS2((v >> 2) | 2); + PUTBITS2(v & 3); + PUTBITS2(color); + } else if (len >= 12 && len <= 27) { + v = len - 12; + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(2); + PUTBITS2(v >> 2); + PUTBITS2(v & 3); + PUTBITS2(color); + } else if (len >= 29) { + /* length = 29 ... 284 */ + if (len > 284) + len = 284; + v = len - 29; + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(3); + PUTBITS2((v >> 6)); + PUTBITS2((v >> 4) & 3); + PUTBITS2((v >> 2) & 3); + PUTBITS2(v & 3); + PUTBITS2(color); + } else { + PUTBITS2(color); + if (color == 0) { + PUTBITS2(1); + } + len = 1; + } + x += len; + } + /* end of line */ + PUTBITS2(0); + PUTBITS2(0); + PUTBITS2(0); + if (bitcnt != 6) { + *q++ = bitbuf; + } + *q++ = 0xf0; + bitmap += linesize; + } + *pq = q; +} + +#define PUTBITS4(val)\ +{\ + bitbuf |= (val) << bitcnt;\ + bitcnt -= 4;\ + if (bitcnt < 0) {\ + bitcnt = 4;\ + *q++ = bitbuf;\ + bitbuf = 0;\ + }\ +} + +/* some DVB decoders only implement 4 bits/pixel */ +static void dvb_encode_rle4(uint8_t **pq, + const uint8_t *bitmap, int linesize, + int w, int h) +{ + uint8_t *q; + unsigned int bitbuf; + int bitcnt; + int x, y, len, x1, v, color; + + q = *pq; + + for(y = 0; y < h; y++) { + *q++ = 0x11; + bitbuf = 0; + bitcnt = 4; + + x = 0; + while (x < w) { + x1 = x; + color = bitmap[x1++]; + while (x1 < w && bitmap[x1] == color) + x1++; + len = x1 - x; + if (color == 0 && len == 2) { + PUTBITS4(0); + PUTBITS4(0xd); + } else if (color == 0 && (len >= 3 && len <= 9)) { + PUTBITS4(0); + PUTBITS4(len - 2); + } else if (len >= 4 && len <= 7) { + PUTBITS4(0); + PUTBITS4(8 + len - 4); + PUTBITS4(color); + } else if (len >= 9 && len <= 24) { + PUTBITS4(0); + PUTBITS4(0xe); + PUTBITS4(len - 9); + PUTBITS4(color); + } else if (len >= 25) { + if (len > 280) + len = 280; + v = len - 25; + PUTBITS4(0); + PUTBITS4(0xf); + PUTBITS4(v >> 4); + PUTBITS4(v & 0xf); + PUTBITS4(color); + } else { + PUTBITS4(color); + if (color == 0) { + PUTBITS4(0xc); + } + len = 1; + } + x += len; + } + /* end of line */ + PUTBITS4(0); + PUTBITS4(0); + if (bitcnt != 4) { + *q++ = bitbuf; + } + *q++ = 0xf0; + bitmap += linesize; + } + *pq = q; +} + +static void dvb_encode_rle8(uint8_t **pq, + const uint8_t *bitmap, int linesize, + int w, int h) +{ + uint8_t *q; + int x, y, len, x1, color; + + q = *pq; + + for (y = 0; y < h; y++) { + *q++ = 0x12; + + x = 0; + while (x < w) { + x1 = x; + color = bitmap[x1++]; + while (x1 < w && bitmap[x1] == color) + x1++; + len = x1 - x; + if (len == 1 && color) { + // 00000001 to 11111111 1 pixel in colour x + *q++ = color; + } else { + if (color == 0x00) { + // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0) + len = FFMIN(len, 127); + *q++ = 0x00; + *q++ = len; + } else if (len > 2) { + // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2) + len = FFMIN(len, 127); + *q++ = 0x00; + *q++ = 0x80+len; + *q++ = color; + } + else if (len == 2) { + *q++ = color; + *q++ = color; + } else { + *q++ = color; + len = 1; + } + } + x += len; + } + /* end of line */ + // 00000000 00000000 end of 8-bit/pixel_code_string + *q++ = 0x00; + *q++ = 0x00; + bitmap += linesize; + } + *pq = q; +} + +static int encode_dvb_subtitles(DVBSubtitleContext *s, + uint8_t *outbuf, const AVSubtitle *h) +{ + uint8_t *q, *pseg_len; + int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; + + + q = outbuf; + + page_id = 1; + + if (h->num_rects && h->rects == NULL) + return -1; + + *q++ = 0x00; /* subtitle_stream_id */ + + /* page composition segment */ + + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x10; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = 30; /* page_timeout (seconds) */ + page_state = 2; /* mode change */ + /* page_version = 0 + page_state */ + *q++ = (s->object_version << 4) | (page_state << 2) | 3; + + for (region_id = 0; region_id < h->num_rects; region_id++) { + *q++ = region_id; + *q++ = 0xff; /* reserved */ + bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */ + bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */ + } + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + + if (h->num_rects) { + for (clut_id = 0; clut_id < h->num_rects; clut_id++) { + + /* CLUT segment */ + + if (h->rects[clut_id]->nb_colors <= 4) { + /* 2 bpp, some decoders do not support it correctly */ + bpp_index = 0; + } else if (h->rects[clut_id]->nb_colors <= 16) { + /* 4 bpp, standard encoding */ + bpp_index = 1; + } else if (h->rects[clut_id]->nb_colors <= 256) { + /* 8 bpp, standard encoding */ + bpp_index = 2; + } else { + return -1; + } + + + /* CLUT segment */ + *q++ = 0x0f; /* sync byte */ + *q++ = 0x12; /* CLUT definition segment */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = clut_id; + *q++ = (0 << 4) | 0xf; /* version = 0 */ + + for(i = 0; i < h->rects[clut_id]->nb_colors; i++) { + *q++ = i; /* clut_entry_id */ + *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ + { + int a, r, g, b; + uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i]; + a = (x >> 24) & 0xff; + r = (x >> 16) & 0xff; + g = (x >> 8) & 0xff; + b = (x >> 0) & 0xff; + + *q++ = RGB_TO_Y_CCIR(r, g, b); + *q++ = RGB_TO_V_CCIR(r, g, b, 0); + *q++ = RGB_TO_U_CCIR(r, g, b, 0); + *q++ = 255 - a; + } + } + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + } + } + + for (region_id = 0; region_id < h->num_rects; region_id++) { + + /* region composition segment */ + + if (h->rects[region_id]->nb_colors <= 4) { + /* 2 bpp, some decoders do not support it correctly */ + bpp_index = 0; + } else if (h->rects[region_id]->nb_colors <= 16) { + /* 4 bpp, standard encoding */ + bpp_index = 1; + } else { + return -1; + } + + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x11; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + *q++ = region_id; + *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ + bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */ + bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */ + *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; + *q++ = region_id; /* clut_id == region_id */ + *q++ = 0; /* 8 bit fill colors */ + *q++ = 0x03; /* 4 bit and 2 bit fill colors */ + + bytestream_put_be16(&q, region_id); /* object_id == region_id */ + *q++ = (0 << 6) | (0 << 4); + *q++ = 0; + *q++ = 0xf0; + *q++ = 0; + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + } + + if (h->num_rects) { + + for (object_id = 0; object_id < h->num_rects; object_id++) { + void (*dvb_encode_rle)(uint8_t **pq, + const uint8_t *bitmap, int linesize, + int w, int h); + + /* bpp_index maths */ + if (h->rects[object_id]->nb_colors <= 4) { + /* 2 bpp, some decoders do not support it correctly */ + dvb_encode_rle = dvb_encode_rle2; + } else if (h->rects[object_id]->nb_colors <= 16) { + /* 4 bpp, standard encoding */ + dvb_encode_rle = dvb_encode_rle4; + } else if (h->rects[object_id]->nb_colors <= 256) { + /* 8 bpp, standard encoding */ + dvb_encode_rle = dvb_encode_rle8; + } else { + return -1; + } + + /* Object Data segment */ + *q++ = 0x0f; /* sync byte */ + *q++ = 0x13; + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + + bytestream_put_be16(&q, object_id); + *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, + onject_coding_method, + non_modifying_color_flag */ + { + uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; + + ptop_field_len = q; + q += 2; + pbottom_field_len = q; + q += 2; + + top_ptr = q; + dvb_encode_rle(&q, h->rects[object_id]->pict.data[0], h->rects[object_id]->w * 2, + h->rects[object_id]->w, h->rects[object_id]->h >> 1); + bottom_ptr = q; + dvb_encode_rle(&q, h->rects[object_id]->pict.data[0] + h->rects[object_id]->w, + h->rects[object_id]->w * 2, h->rects[object_id]->w, + h->rects[object_id]->h >> 1); + + bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); + bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); + } + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + } + } + + /* end of display set segment */ + + *q++ = 0x0f; /* sync_byte */ + *q++ = 0x80; /* segment_type */ + bytestream_put_be16(&q, page_id); + pseg_len = q; + q += 2; /* segment length */ + + bytestream_put_be16(&pseg_len, q - pseg_len - 2); + + *q++ = 0xff; /* end of PES data */ + + s->object_version = (s->object_version + 1) & 0xf; + return q - outbuf; +} + +static int dvbsub_encode(AVCodecContext *avctx, + unsigned char *buf, int buf_size, + const AVSubtitle *sub) +{ + DVBSubtitleContext *s = avctx->priv_data; + int ret; + + ret = encode_dvb_subtitles(s, buf, sub); + return ret; +} + +AVCodec ff_dvbsub_encoder = { + .name = "dvbsub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_DVB_SUBTITLE, + .priv_data_size = sizeof(DVBSubtitleContext), + .encode_sub = dvbsub_encode, + .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), +}; diff --git a/ffmpeg/libavcodec/dvbsub_parser.c b/ffmpeg/libavcodec/dvbsub_parser.c new file mode 100644 index 0000000..d15c891 --- /dev/null +++ b/ffmpeg/libavcodec/dvbsub_parser.c @@ -0,0 +1,179 @@ +/* + * DVB subtitle parser for FFmpeg + * Copyright (c) 2005 Ian Caulfield + * + * 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 "avcodec.h" +#include "get_bits.h" + +/* Parser (mostly) copied from dvdsub.c */ + +#define PARSE_BUF_SIZE (65536) + + +/* parser definition */ +typedef struct DVBSubParseContext { + uint8_t *packet_buf; + int packet_start; + int packet_index; + int in_packet; +} DVBSubParseContext; + +static av_cold int dvbsub_parse_init(AVCodecParserContext *s) +{ + DVBSubParseContext *pc = s->priv_data; + pc->packet_buf = av_malloc(PARSE_BUF_SIZE); + + return 0; +} + +static int dvbsub_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DVBSubParseContext *pc = s->priv_data; + uint8_t *p, *p_end; + int i, len, buf_pos = 0; + + av_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n", + s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]); + + for (i=0; i < buf_size; i++) + { + av_dlog(avctx, "%02x ", buf[i]); + if (i % 16 == 15) + av_dlog(avctx, "\n"); + } + + if (i % 16 != 0) + av_dlog(avctx, "\n"); + + *poutbuf = NULL; + *poutbuf_size = 0; + + s->fetch_timestamp = 1; + + if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */ + { + if (pc->packet_index != pc->packet_start) + { + av_dlog(avctx, "Discarding %d bytes\n", + pc->packet_index - pc->packet_start); + } + + pc->packet_start = 0; + pc->packet_index = 0; + + if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) { + av_dlog(avctx, "Bad packet header\n"); + return -1; + } + + buf_pos = 2; + + pc->in_packet = 1; + } else { + if (pc->packet_start != 0) + { + if (pc->packet_index != pc->packet_start) + { + memmove(pc->packet_buf, pc->packet_buf + pc->packet_start, + pc->packet_index - pc->packet_start); + + pc->packet_index -= pc->packet_start; + pc->packet_start = 0; + } else { + pc->packet_start = 0; + pc->packet_index = 0; + } + } + } + + if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE) + return -1; + +/* if not currently in a packet, discard data */ + if (pc->in_packet == 0) + return buf_size; + + memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos); + pc->packet_index += buf_size - buf_pos; + + p = pc->packet_buf; + p_end = pc->packet_buf + pc->packet_index; + + while (p < p_end) + { + if (*p == 0x0f) + { + if (p + 6 <= p_end) + { + len = AV_RB16(p + 4); + + if (p + len + 6 <= p_end) + { + *poutbuf_size += len + 6; + + p += len + 6; + } else + break; + } else + break; + } else if (*p == 0xff) { + if (p + 1 < p_end) + { + av_dlog(avctx, "Junk at end of packet\n"); + } + pc->packet_index = p - pc->packet_buf; + pc->in_packet = 0; + break; + } else { + av_log(avctx, AV_LOG_ERROR, "Junk in packet\n"); + + pc->packet_index = p - pc->packet_buf; + pc->in_packet = 0; + break; + } + } + + if (*poutbuf_size > 0) + { + *poutbuf = pc->packet_buf; + pc->packet_start = *poutbuf_size; + } + + if (s->pts == AV_NOPTS_VALUE) + s->pts = s->last_pts; + + return buf_size; +} + +static av_cold void dvbsub_parse_close(AVCodecParserContext *s) +{ + DVBSubParseContext *pc = s->priv_data; + av_freep(&pc->packet_buf); +} + +AVCodecParser ff_dvbsub_parser = { + .codec_ids = { AV_CODEC_ID_DVB_SUBTITLE }, + .priv_data_size = sizeof(DVBSubParseContext), + .parser_init = dvbsub_parse_init, + .parser_parse = dvbsub_parse, + .parser_close = dvbsub_parse_close, +}; diff --git a/ffmpeg/libavcodec/dvbsubdec.c b/ffmpeg/libavcodec/dvbsubdec.c new file mode 100644 index 0000000..955925a --- /dev/null +++ b/ffmpeg/libavcodec/dvbsubdec.c @@ -0,0 +1,1546 @@ +/* + * DVB subtitle decoding + * Copyright (c) 2005 Ian Caulfield + * + * 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 "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "bytestream.h" +#include "libavutil/colorspace.h" + +#define DVBSUB_PAGE_SEGMENT 0x10 +#define DVBSUB_REGION_SEGMENT 0x11 +#define DVBSUB_CLUT_SEGMENT 0x12 +#define DVBSUB_OBJECT_SEGMENT 0x13 +#define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14 +#define DVBSUB_DISPLAY_SEGMENT 0x80 + +#define cm (ff_cropTbl + MAX_NEG_CROP) + +#ifdef DEBUG +#undef fprintf +#undef perror +#if 0 +static void png_save(const char *filename, uint8_t *bitmap, int w, int h, + uint32_t *rgba_palette) +{ + int x, y, v; + FILE *f; + char fname[40], fname2[40]; + char command[1024]; + + snprintf(fname, 40, "%s.ppm", filename); + + f = fopen(fname, "w"); + if (!f) { + perror(fname); + return; + } + fprintf(f, "P6\n" + "%d %d\n" + "%d\n", + w, h, 255); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + v = rgba_palette[bitmap[y * w + x]]; + putc((v >> 16) & 0xff, f); + putc((v >> 8) & 0xff, f); + putc((v >> 0) & 0xff, f); + } + } + fclose(f); + + + snprintf(fname2, 40, "%s-a.pgm", filename); + + f = fopen(fname2, "w"); + if (!f) { + perror(fname2); + return; + } + fprintf(f, "P5\n" + "%d %d\n" + "%d\n", + w, h, 255); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + v = rgba_palette[bitmap[y * w + x]]; + putc((v >> 24) & 0xff, f); + } + } + fclose(f); + + snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename); + system(command); + + snprintf(command, 1024, "rm %s %s", fname, fname2); + system(command); +} +#endif + +static void png_save2(const char *filename, uint32_t *bitmap, int w, int h) +{ + int x, y, v; + FILE *f; + char fname[40], fname2[40]; + char command[1024]; + + snprintf(fname, sizeof(fname), "%s.ppm", filename); + + f = fopen(fname, "w"); + if (!f) { + perror(fname); + return; + } + fprintf(f, "P6\n" + "%d %d\n" + "%d\n", + w, h, 255); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + v = bitmap[y * w + x]; + putc((v >> 16) & 0xff, f); + putc((v >> 8) & 0xff, f); + putc((v >> 0) & 0xff, f); + } + } + fclose(f); + + + snprintf(fname2, sizeof(fname2), "%s-a.pgm", filename); + + f = fopen(fname2, "w"); + if (!f) { + perror(fname2); + return; + } + fprintf(f, "P5\n" + "%d %d\n" + "%d\n", + w, h, 255); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + v = bitmap[y * w + x]; + putc((v >> 24) & 0xff, f); + } + } + fclose(f); + + snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename); + system(command); + + snprintf(command, sizeof(command), "rm %s %s", fname, fname2); + system(command); +} +#endif + +#define RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +typedef struct DVBSubCLUT { + int id; + int version; + + uint32_t clut4[4]; + uint32_t clut16[16]; + uint32_t clut256[256]; + + struct DVBSubCLUT *next; +} DVBSubCLUT; + +static DVBSubCLUT default_clut; + +typedef struct DVBSubObjectDisplay { + int object_id; + int region_id; + + int x_pos; + int y_pos; + + int fgcolor; + int bgcolor; + + struct DVBSubObjectDisplay *region_list_next; + struct DVBSubObjectDisplay *object_list_next; +} DVBSubObjectDisplay; + +typedef struct DVBSubObject { + int id; + int version; + + int type; + + DVBSubObjectDisplay *display_list; + + struct DVBSubObject *next; +} DVBSubObject; + +typedef struct DVBSubRegionDisplay { + int region_id; + + int x_pos; + int y_pos; + + struct DVBSubRegionDisplay *next; +} DVBSubRegionDisplay; + +typedef struct DVBSubRegion { + int id; + int version; + + int width; + int height; + int depth; + + int clut; + int bgcolor; + + uint8_t *pbuf; + int buf_size; + int dirty; + + DVBSubObjectDisplay *display_list; + + struct DVBSubRegion *next; +} DVBSubRegion; + +typedef struct DVBSubDisplayDefinition { + int version; + + int x; + int y; + int width; + int height; +} DVBSubDisplayDefinition; + +typedef struct DVBSubContext { + int composition_id; + int ancillary_id; + + int version; + int time_out; + DVBSubRegion *region_list; + DVBSubCLUT *clut_list; + DVBSubObject *object_list; + + int display_list_size; + DVBSubRegionDisplay *display_list; + DVBSubDisplayDefinition *display_definition; +} DVBSubContext; + + +static DVBSubObject* get_object(DVBSubContext *ctx, int object_id) +{ + DVBSubObject *ptr = ctx->object_list; + + while (ptr && ptr->id != object_id) { + ptr = ptr->next; + } + + return ptr; +} + +static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id) +{ + DVBSubCLUT *ptr = ctx->clut_list; + + while (ptr && ptr->id != clut_id) { + ptr = ptr->next; + } + + return ptr; +} + +static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id) +{ + DVBSubRegion *ptr = ctx->region_list; + + while (ptr && ptr->id != region_id) { + ptr = ptr->next; + } + + return ptr; +} + +static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region) +{ + DVBSubObject *object, *obj2, **obj2_ptr; + DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr; + + while (region->display_list) { + display = region->display_list; + + object = get_object(ctx, display->object_id); + + if (object) { + obj_disp_ptr = &object->display_list; + obj_disp = *obj_disp_ptr; + + while (obj_disp && obj_disp != display) { + obj_disp_ptr = &obj_disp->object_list_next; + obj_disp = *obj_disp_ptr; + } + + if (obj_disp) { + *obj_disp_ptr = obj_disp->object_list_next; + + if (!object->display_list) { + obj2_ptr = &ctx->object_list; + obj2 = *obj2_ptr; + + while (obj2 != object) { + assert(obj2); + obj2_ptr = &obj2->next; + obj2 = *obj2_ptr; + } + + *obj2_ptr = obj2->next; + + av_free(obj2); + } + } + } + + region->display_list = display->region_list_next; + + av_free(display); + } + +} + +static void delete_cluts(DVBSubContext *ctx) +{ + DVBSubCLUT *clut; + + while (ctx->clut_list) { + clut = ctx->clut_list; + + ctx->clut_list = clut->next; + + av_free(clut); + } +} + +static void delete_objects(DVBSubContext *ctx) +{ + DVBSubObject *object; + + while (ctx->object_list) { + object = ctx->object_list; + + ctx->object_list = object->next; + + av_free(object); + } +} + +static void delete_regions(DVBSubContext *ctx) +{ + DVBSubRegion *region; + + while (ctx->region_list) { + region = ctx->region_list; + + ctx->region_list = region->next; + + delete_region_display_list(ctx, region); + + av_free(region->pbuf); + av_free(region); + } +} + +static av_cold int dvbsub_init_decoder(AVCodecContext *avctx) +{ + int i, r, g, b, a = 0; + DVBSubContext *ctx = avctx->priv_data; + + if (!avctx->extradata || avctx->extradata_size != 4) { + av_log(avctx, AV_LOG_WARNING, "Invalid extradata, subtitle streams may be combined!\n"); + ctx->composition_id = -1; + ctx->ancillary_id = -1; + } else { + ctx->composition_id = AV_RB16(avctx->extradata); + ctx->ancillary_id = AV_RB16(avctx->extradata + 2); + } + + ctx->version = -1; + + default_clut.id = -1; + default_clut.next = NULL; + + default_clut.clut4[0] = RGBA( 0, 0, 0, 0); + default_clut.clut4[1] = RGBA(255, 255, 255, 255); + default_clut.clut4[2] = RGBA( 0, 0, 0, 255); + default_clut.clut4[3] = RGBA(127, 127, 127, 255); + + default_clut.clut16[0] = RGBA( 0, 0, 0, 0); + for (i = 1; i < 16; i++) { + if (i < 8) { + r = (i & 1) ? 255 : 0; + g = (i & 2) ? 255 : 0; + b = (i & 4) ? 255 : 0; + } else { + r = (i & 1) ? 127 : 0; + g = (i & 2) ? 127 : 0; + b = (i & 4) ? 127 : 0; + } + default_clut.clut16[i] = RGBA(r, g, b, 255); + } + + default_clut.clut256[0] = RGBA( 0, 0, 0, 0); + for (i = 1; i < 256; i++) { + if (i < 8) { + r = (i & 1) ? 255 : 0; + g = (i & 2) ? 255 : 0; + b = (i & 4) ? 255 : 0; + a = 63; + } else { + switch (i & 0x88) { + case 0x00: + r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); + g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); + b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); + a = 255; + break; + case 0x08: + r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); + g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); + b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); + a = 127; + break; + case 0x80: + r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); + g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); + b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); + a = 255; + break; + case 0x88: + r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); + g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); + b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); + a = 255; + break; + } + } + default_clut.clut256[i] = RGBA(r, g, b, a); + } + + return 0; +} + +static av_cold int dvbsub_close_decoder(AVCodecContext *avctx) +{ + DVBSubContext *ctx = avctx->priv_data; + DVBSubRegionDisplay *display; + + delete_regions(ctx); + + delete_objects(ctx); + + delete_cluts(ctx); + + av_freep(&ctx->display_definition); + + while (ctx->display_list) { + display = ctx->display_list; + ctx->display_list = display->next; + + av_free(display); + } + + return 0; +} + +static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len, + const uint8_t **srcbuf, int buf_size, + int non_mod, uint8_t *map_table, int x_pos) +{ + GetBitContext gb; + + int bits; + int run_length; + int pixels_read = x_pos; + + init_get_bits(&gb, *srcbuf, buf_size << 3); + + destbuf += x_pos; + + while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) { + bits = get_bits(&gb, 2); + + if (bits) { + if (non_mod != 1 || bits != 1) { + if (map_table) + *destbuf++ = map_table[bits]; + else + *destbuf++ = bits; + } + pixels_read++; + } else { + bits = get_bits1(&gb); + if (bits == 1) { + run_length = get_bits(&gb, 3) + 3; + bits = get_bits(&gb, 2); + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } else { + bits = get_bits1(&gb); + if (bits == 0) { + bits = get_bits(&gb, 2); + if (bits == 2) { + run_length = get_bits(&gb, 4) + 12; + bits = get_bits(&gb, 2); + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } else if (bits == 3) { + run_length = get_bits(&gb, 8) + 29; + bits = get_bits(&gb, 2); + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } else if (bits == 1) { + if (map_table) + bits = map_table[0]; + else + bits = 0; + run_length = 2; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } else { + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + return pixels_read; + } + } else { + if (map_table) + bits = map_table[0]; + else + bits = 0; + *destbuf++ = bits; + pixels_read++; + } + } + } + } + + if (get_bits(&gb, 6)) + av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n"); + + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + + return pixels_read; +} + +static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len, + const uint8_t **srcbuf, int buf_size, + int non_mod, uint8_t *map_table, int x_pos) +{ + GetBitContext gb; + + int bits; + int run_length; + int pixels_read = x_pos; + + init_get_bits(&gb, *srcbuf, buf_size << 3); + + destbuf += x_pos; + + while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) { + bits = get_bits(&gb, 4); + + if (bits) { + if (non_mod != 1 || bits != 1) { + if (map_table) + *destbuf++ = map_table[bits]; + else + *destbuf++ = bits; + } + pixels_read++; + } else { + bits = get_bits1(&gb); + if (bits == 0) { + run_length = get_bits(&gb, 3); + + if (run_length == 0) { + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + return pixels_read; + } + + run_length += 2; + + if (map_table) + bits = map_table[0]; + else + bits = 0; + + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } else { + bits = get_bits1(&gb); + if (bits == 0) { + run_length = get_bits(&gb, 2) + 4; + bits = get_bits(&gb, 4); + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } else { + bits = get_bits(&gb, 2); + if (bits == 2) { + run_length = get_bits(&gb, 4) + 9; + bits = get_bits(&gb, 4); + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } else if (bits == 3) { + run_length = get_bits(&gb, 8) + 25; + bits = get_bits(&gb, 4); + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + else { + if (map_table) + bits = map_table[bits]; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } else if (bits == 1) { + if (map_table) + bits = map_table[0]; + else + bits = 0; + run_length = 2; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } else { + if (map_table) + bits = map_table[0]; + else + bits = 0; + *destbuf++ = bits; + pixels_read ++; + } + } + } + } + } + + if (get_bits(&gb, 8)) + av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n"); + + (*srcbuf) += (get_bits_count(&gb) + 7) >> 3; + + return pixels_read; +} + +static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len, + const uint8_t **srcbuf, int buf_size, + int non_mod, uint8_t *map_table, int x_pos) +{ + const uint8_t *sbuf_end = (*srcbuf) + buf_size; + int bits; + int run_length; + int pixels_read = x_pos; + + destbuf += x_pos; + + while (*srcbuf < sbuf_end && pixels_read < dbuf_len) { + bits = *(*srcbuf)++; + + if (bits) { + if (non_mod != 1 || bits != 1) { + if (map_table) + *destbuf++ = map_table[bits]; + else + *destbuf++ = bits; + } + pixels_read++; + } else { + bits = *(*srcbuf)++; + run_length = bits & 0x7f; + if ((bits & 0x80) == 0) { + if (run_length == 0) { + return pixels_read; + } + + if (map_table) + bits = map_table[0]; + else + bits = 0; + while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } else { + bits = *(*srcbuf)++; + + if (non_mod == 1 && bits == 1) + pixels_read += run_length; + if (map_table) + bits = map_table[bits]; + else while (run_length-- > 0 && pixels_read < dbuf_len) { + *destbuf++ = bits; + pixels_read++; + } + } + } + } + + if (*(*srcbuf)++) + av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n"); + + return pixels_read; +} + + + +static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display, + const uint8_t *buf, int buf_size, int top_bottom, int non_mod) +{ + DVBSubContext *ctx = avctx->priv_data; + + DVBSubRegion *region = get_region(ctx, display->region_id); + const uint8_t *buf_end = buf + buf_size; + uint8_t *pbuf; + int x_pos, y_pos; + int i; + + uint8_t map2to4[] = { 0x0, 0x7, 0x8, 0xf}; + uint8_t map2to8[] = {0x00, 0x77, 0x88, 0xff}; + uint8_t map4to8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; + uint8_t *map_table; + +#if 0 + av_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size, + top_bottom ? "bottom" : "top"); + + for (i = 0; i < buf_size; i++) { + if (i % 16 == 0) + av_dlog(avctx, "0x%8p: ", buf+i); + + av_dlog(avctx, "%02x ", buf[i]); + if (i % 16 == 15) + av_dlog(avctx, "\n"); + } + + if (i % 16) + av_dlog(avctx, "\n"); +#endif + + if (region == 0) + return; + + pbuf = region->pbuf; + region->dirty = 1; + + x_pos = display->x_pos; + y_pos = display->y_pos; + + y_pos += top_bottom; + + while (buf < buf_end) { + if ((*buf!=0xf0 && x_pos >= region->width) || y_pos >= region->height) { + av_log(avctx, AV_LOG_ERROR, "Invalid object location! %d-%d %d-%d %02x\n", x_pos, region->width, y_pos, region->height, *buf); + return; + } + + switch (*buf++) { + case 0x10: + if (region->depth == 8) + map_table = map2to8; + else if (region->depth == 4) + map_table = map2to4; + else + map_table = NULL; + + x_pos = dvbsub_read_2bit_string(pbuf + (y_pos * region->width), + region->width, &buf, buf_end - buf, + non_mod, map_table, x_pos); + break; + case 0x11: + if (region->depth < 4) { + av_log(avctx, AV_LOG_ERROR, "4-bit pixel string in %d-bit region!\n", region->depth); + return; + } + + if (region->depth == 8) + map_table = map4to8; + else + map_table = NULL; + + x_pos = dvbsub_read_4bit_string(pbuf + (y_pos * region->width), + region->width, &buf, buf_end - buf, + non_mod, map_table, x_pos); + break; + case 0x12: + if (region->depth < 8) { + av_log(avctx, AV_LOG_ERROR, "8-bit pixel string in %d-bit region!\n", region->depth); + return; + } + + x_pos = dvbsub_read_8bit_string(pbuf + (y_pos * region->width), + region->width, &buf, buf_end - buf, + non_mod, NULL, x_pos); + break; + + case 0x20: + map2to4[0] = (*buf) >> 4; + map2to4[1] = (*buf++) & 0xf; + map2to4[2] = (*buf) >> 4; + map2to4[3] = (*buf++) & 0xf; + break; + case 0x21: + for (i = 0; i < 4; i++) + map2to8[i] = *buf++; + break; + case 0x22: + for (i = 0; i < 16; i++) + map4to8[i] = *buf++; + break; + + case 0xf0: + x_pos = display->x_pos; + y_pos += 2; + break; + default: + av_log(avctx, AV_LOG_INFO, "Unknown/unsupported pixel block 0x%x\n", *(buf-1)); + } + } + +} + +static void dvbsub_parse_object_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + DVBSubContext *ctx = avctx->priv_data; + + const uint8_t *buf_end = buf + buf_size; + int object_id; + DVBSubObject *object; + DVBSubObjectDisplay *display; + int top_field_len, bottom_field_len; + + int coding_method, non_modifying_color; + + object_id = AV_RB16(buf); + buf += 2; + + object = get_object(ctx, object_id); + + if (!object) + return; + + coding_method = ((*buf) >> 2) & 3; + non_modifying_color = ((*buf++) >> 1) & 1; + + if (coding_method == 0) { + top_field_len = AV_RB16(buf); + buf += 2; + bottom_field_len = AV_RB16(buf); + buf += 2; + + if (buf + top_field_len + bottom_field_len > buf_end) { + av_log(avctx, AV_LOG_ERROR, "Field data size too large\n"); + return; + } + + for (display = object->display_list; display; display = display->object_list_next) { + const uint8_t *block = buf; + int bfl = bottom_field_len; + + dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0, + non_modifying_color); + + if (bottom_field_len > 0) + block = buf + top_field_len; + else + bfl = top_field_len; + + dvbsub_parse_pixel_data_block(avctx, display, block, bfl, 1, + non_modifying_color); + } + +/* } else if (coding_method == 1) {*/ + + } else { + av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method); + } + +} + +static void dvbsub_parse_clut_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + DVBSubContext *ctx = avctx->priv_data; + + const uint8_t *buf_end = buf + buf_size; + int i, clut_id; + int version; + DVBSubCLUT *clut; + int entry_id, depth , full_range; + int y, cr, cb, alpha; + int r, g, b, r_add, g_add, b_add; + + av_dlog(avctx, "DVB clut packet:\n"); + + for (i=0; i < buf_size; i++) { + av_dlog(avctx, "%02x ", buf[i]); + if (i % 16 == 15) + av_dlog(avctx, "\n"); + } + + if (i % 16) + av_dlog(avctx, "\n"); + + clut_id = *buf++; + version = ((*buf)>>4)&15; + buf += 1; + + clut = get_clut(ctx, clut_id); + + if (!clut) { + clut = av_malloc(sizeof(DVBSubCLUT)); + + memcpy(clut, &default_clut, sizeof(DVBSubCLUT)); + + clut->id = clut_id; + clut->version = -1; + + clut->next = ctx->clut_list; + ctx->clut_list = clut; + } + + if (clut->version != version) { + + clut->version = version; + + while (buf + 4 < buf_end) { + entry_id = *buf++; + + depth = (*buf) & 0xe0; + + if (depth == 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf); + return; + } + + full_range = (*buf++) & 1; + + if (full_range) { + y = *buf++; + cr = *buf++; + cb = *buf++; + alpha = *buf++; + } else { + y = buf[0] & 0xfc; + cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; + cb = (buf[1] << 2) & 0xf0; + alpha = (buf[1] << 6) & 0xc0; + + buf += 2; + } + + if (y == 0) + alpha = 0xff; + + YUV_TO_RGB1_CCIR(cb, cr); + YUV_TO_RGB2_CCIR(r, g, b, y); + + av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha); + + if (depth & 0x80) + clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha); + if (depth & 0x40) + clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha); + if (depth & 0x20) + clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha); + } + } +} + + +static void dvbsub_parse_region_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + DVBSubContext *ctx = avctx->priv_data; + + const uint8_t *buf_end = buf + buf_size; + int region_id, object_id; + int av_unused version; + DVBSubRegion *region; + DVBSubObject *object; + DVBSubObjectDisplay *display; + int fill; + + if (buf_size < 10) + return; + + region_id = *buf++; + + region = get_region(ctx, region_id); + + if (!region) { + region = av_mallocz(sizeof(DVBSubRegion)); + + region->id = region_id; + region->version = -1; + + region->next = ctx->region_list; + ctx->region_list = region; + } + + version = ((*buf)>>4) & 15; + fill = ((*buf++) >> 3) & 1; + + region->width = AV_RB16(buf); + buf += 2; + region->height = AV_RB16(buf); + buf += 2; + + if (region->width * region->height != region->buf_size) { + av_free(region->pbuf); + + region->buf_size = region->width * region->height; + + region->pbuf = av_malloc(region->buf_size); + + fill = 1; + region->dirty = 0; + } + + region->depth = 1 << (((*buf++) >> 2) & 7); + if(region->depth<2 || region->depth>8){ + av_log(avctx, AV_LOG_ERROR, "region depth %d is invalid\n", region->depth); + region->depth= 4; + } + region->clut = *buf++; + + if (region->depth == 8) { + region->bgcolor = *buf++; + buf += 1; + } else { + buf += 1; + + if (region->depth == 4) + region->bgcolor = (((*buf++) >> 4) & 15); + else + region->bgcolor = (((*buf++) >> 2) & 3); + } + + av_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height); + + if (fill) { + memset(region->pbuf, region->bgcolor, region->buf_size); + av_dlog(avctx, "Fill region (%d)\n", region->bgcolor); + } + + delete_region_display_list(ctx, region); + + while (buf + 5 < buf_end) { + object_id = AV_RB16(buf); + buf += 2; + + object = get_object(ctx, object_id); + + if (!object) { + object = av_mallocz(sizeof(DVBSubObject)); + + object->id = object_id; + object->next = ctx->object_list; + ctx->object_list = object; + } + + object->type = (*buf) >> 6; + + display = av_mallocz(sizeof(DVBSubObjectDisplay)); + + display->object_id = object_id; + display->region_id = region_id; + + display->x_pos = AV_RB16(buf) & 0xfff; + buf += 2; + display->y_pos = AV_RB16(buf) & 0xfff; + buf += 2; + + if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) { + display->fgcolor = *buf++; + display->bgcolor = *buf++; + } + + display->region_list_next = region->display_list; + region->display_list = display; + + display->object_list_next = object->display_list; + object->display_list = display; + } +} + +static void dvbsub_parse_page_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + DVBSubContext *ctx = avctx->priv_data; + DVBSubRegionDisplay *display; + DVBSubRegionDisplay *tmp_display_list, **tmp_ptr; + + const uint8_t *buf_end = buf + buf_size; + int region_id; + int page_state; + int timeout; + int version; + + if (buf_size < 1) + return; + + timeout = *buf++; + version = ((*buf)>>4) & 15; + page_state = ((*buf++) >> 2) & 3; + + if (ctx->version != version) { + + ctx->time_out = timeout; + ctx->version = version; + + av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state); + + if (page_state == 1 || page_state == 2) { + delete_regions(ctx); + delete_objects(ctx); + delete_cluts(ctx); + } + + tmp_display_list = ctx->display_list; + ctx->display_list = NULL; + ctx->display_list_size = 0; + + while (buf + 5 < buf_end) { + region_id = *buf++; + buf += 1; + + display = tmp_display_list; + tmp_ptr = &tmp_display_list; + + while (display && display->region_id != region_id) { + tmp_ptr = &display->next; + display = display->next; + } + + if (!display) + display = av_mallocz(sizeof(DVBSubRegionDisplay)); + + display->region_id = region_id; + + display->x_pos = AV_RB16(buf); + buf += 2; + display->y_pos = AV_RB16(buf); + buf += 2; + + *tmp_ptr = display->next; + + display->next = ctx->display_list; + ctx->display_list = display; + ctx->display_list_size++; + + av_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos); + } + + while (tmp_display_list) { + display = tmp_display_list; + + tmp_display_list = display->next; + + av_free(display); + } + } + +} + + +#ifdef DEBUG +static void save_display_set(DVBSubContext *ctx) +{ + DVBSubRegion *region; + DVBSubRegionDisplay *display; + DVBSubCLUT *clut; + uint32_t *clut_table; + int x_pos, y_pos, width, height; + int x, y, y_off, x_off; + uint32_t *pbuf; + char filename[32]; + static int fileno_index = 0; + + x_pos = -1; + y_pos = -1; + width = 0; + height = 0; + + for (display = ctx->display_list; display; display = display->next) { + region = get_region(ctx, display->region_id); + + if (x_pos == -1) { + x_pos = display->x_pos; + y_pos = display->y_pos; + width = region->width; + height = region->height; + } else { + if (display->x_pos < x_pos) { + width += (x_pos - display->x_pos); + x_pos = display->x_pos; + } + + if (display->y_pos < y_pos) { + height += (y_pos - display->y_pos); + y_pos = display->y_pos; + } + + if (display->x_pos + region->width > x_pos + width) { + width = display->x_pos + region->width - x_pos; + } + + if (display->y_pos + region->height > y_pos + height) { + height = display->y_pos + region->height - y_pos; + } + } + } + + if (x_pos >= 0) { + + pbuf = av_malloc(width * height * 4); + + for (display = ctx->display_list; display; display = display->next) { + region = get_region(ctx, display->region_id); + + x_off = display->x_pos - x_pos; + y_off = display->y_pos - y_pos; + + clut = get_clut(ctx, region->clut); + + if (clut == 0) + clut = &default_clut; + + switch (region->depth) { + case 2: + clut_table = clut->clut4; + break; + case 8: + clut_table = clut->clut256; + break; + case 4: + default: + clut_table = clut->clut16; + break; + } + + for (y = 0; y < region->height; y++) { + for (x = 0; x < region->width; x++) { + pbuf[((y + y_off) * width) + x_off + x] = + clut_table[region->pbuf[y * region->width + x]]; + } + } + + } + + snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index); + + png_save2(filename, pbuf, width, height); + + av_free(pbuf); + } + + fileno_index++; +} +#endif + +static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx, + const uint8_t *buf, + int buf_size) +{ + DVBSubContext *ctx = avctx->priv_data; + DVBSubDisplayDefinition *display_def = ctx->display_definition; + int dds_version, info_byte; + + if (buf_size < 5) + return; + + info_byte = bytestream_get_byte(&buf); + dds_version = info_byte >> 4; + if (display_def && display_def->version == dds_version) + return; // already have this display definition version + + if (!display_def) { + display_def = av_mallocz(sizeof(*display_def)); + ctx->display_definition = display_def; + } + if (!display_def) + return; + + display_def->version = dds_version; + display_def->x = 0; + display_def->y = 0; + display_def->width = bytestream_get_be16(&buf) + 1; + display_def->height = bytestream_get_be16(&buf) + 1; + if (!avctx->width || !avctx->height) { + avctx->width = display_def->width; + avctx->height = display_def->height; + } + + if (buf_size < 13) + return; + + if (info_byte & 1<<3) { // display_window_flag + display_def->x = bytestream_get_be16(&buf); + display_def->y = bytestream_get_be16(&buf); + display_def->width = bytestream_get_be16(&buf) - display_def->x + 1; + display_def->height = bytestream_get_be16(&buf) - display_def->y + 1; + } +} + +static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, + int buf_size, AVSubtitle *sub) +{ + DVBSubContext *ctx = avctx->priv_data; + DVBSubDisplayDefinition *display_def = ctx->display_definition; + + DVBSubRegion *region; + DVBSubRegionDisplay *display; + AVSubtitleRect *rect; + DVBSubCLUT *clut; + uint32_t *clut_table; + int i; + int offset_x=0, offset_y=0; + + sub->end_display_time = ctx->time_out * 1000; + + if (display_def) { + offset_x = display_def->x; + offset_y = display_def->y; + } + + sub->num_rects = ctx->display_list_size; + + if (sub->num_rects > 0){ + sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects); + for(i=0; inum_rects; i++) + sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); + + i = 0; + + for (display = ctx->display_list; display; display = display->next) { + region = get_region(ctx, display->region_id); + + if (!region) + continue; + + if (!region->dirty) + continue; + + rect = sub->rects[i]; + rect->x = display->x_pos + offset_x; + rect->y = display->y_pos + offset_y; + rect->w = region->width; + rect->h = region->height; + rect->nb_colors = (1 << region->depth); + rect->type = SUBTITLE_BITMAP; + rect->pict.linesize[0] = region->width; + + clut = get_clut(ctx, region->clut); + + if (!clut) + clut = &default_clut; + + switch (region->depth) { + case 2: + clut_table = clut->clut4; + break; + case 8: + clut_table = clut->clut256; + break; + case 4: + default: + clut_table = clut->clut16; + break; + } + + rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t)); + + rect->pict.data[0] = av_malloc(region->buf_size); + memcpy(rect->pict.data[0], region->pbuf, region->buf_size); + + i++; + } + + sub->num_rects = i; + } +#ifdef DEBUG + save_display_set(ctx); +#endif + + return 1; +} + +static int dvbsub_decode(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + DVBSubContext *ctx = avctx->priv_data; + AVSubtitle *sub = data; + const uint8_t *p, *p_end; + int segment_type; + int page_id; + int segment_length; + int i; + int got_segment = 0; + + av_dlog(avctx, "DVB sub packet:\n"); + + for (i=0; i < buf_size; i++) { + av_dlog(avctx, "%02x ", buf[i]); + if (i % 16 == 15) + av_dlog(avctx, "\n"); + } + + if (i % 16) + av_dlog(avctx, "\n"); + + if (buf_size <= 6 || *buf != 0x0f) { + av_dlog(avctx, "incomplete or broken packet"); + return -1; + } + + p = buf; + p_end = buf + buf_size; + + while (p_end - p >= 6 && *p == 0x0f) { + p += 1; + segment_type = *p++; + page_id = AV_RB16(p); + p += 2; + segment_length = AV_RB16(p); + p += 2; + + if (p_end - p < segment_length) { + av_dlog(avctx, "incomplete or broken packet"); + return -1; + } + + if (page_id == ctx->composition_id || page_id == ctx->ancillary_id || + ctx->composition_id == -1 || ctx->ancillary_id == -1) { + switch (segment_type) { + case DVBSUB_PAGE_SEGMENT: + dvbsub_parse_page_segment(avctx, p, segment_length); + got_segment |= 1; + break; + case DVBSUB_REGION_SEGMENT: + dvbsub_parse_region_segment(avctx, p, segment_length); + got_segment |= 2; + break; + case DVBSUB_CLUT_SEGMENT: + dvbsub_parse_clut_segment(avctx, p, segment_length); + got_segment |= 4; + break; + case DVBSUB_OBJECT_SEGMENT: + dvbsub_parse_object_segment(avctx, p, segment_length); + got_segment |= 8; + break; + case DVBSUB_DISPLAYDEFINITION_SEGMENT: + dvbsub_parse_display_definition_segment(avctx, p, segment_length); + break; + case DVBSUB_DISPLAY_SEGMENT: + *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub); + got_segment |= 16; + break; + default: + av_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n", + segment_type, page_id, segment_length); + break; + } + } + + p += segment_length; + } + // Some streams do not send a display segment but if we have all the other + // segments then we need no further data. + if (got_segment == 15 && sub) + *data_size = dvbsub_display_end_segment(avctx, p, 0, sub); + + return p - buf; +} + + +AVCodec ff_dvbsub_decoder = { + .name = "dvbsub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_DVB_SUBTITLE, + .priv_data_size = sizeof(DVBSubContext), + .init = dvbsub_init_decoder, + .close = dvbsub_close_decoder, + .decode = dvbsub_decode, + .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), +}; diff --git a/ffmpeg/libavcodec/dvd_nav_parser.c b/ffmpeg/libavcodec/dvd_nav_parser.c new file mode 100644 index 0000000..4b03e39 --- /dev/null +++ b/ffmpeg/libavcodec/dvd_nav_parser.c @@ -0,0 +1,116 @@ +/* + * DVD navigation block parser for FFmpeg + * Copyright (c) 2013 The FFmpeg Project + * + * 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 "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "parser.h" + +#define PCI_SIZE 980 +#define DSI_SIZE 1018 + +/* parser definition */ +typedef struct DVDNavParseContext { + uint32_t lba; + uint8_t buffer[PCI_SIZE+DSI_SIZE]; + int copied; +} DVDNavParseContext; + +static av_cold int dvd_nav_parse_init(AVCodecParserContext *s) +{ + DVDNavParseContext *pc = s->priv_data; + + pc->lba = 0xFFFFFFFF; + pc->copied = 0; + return 0; +} + +static int dvd_nav_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DVDNavParseContext *pc1 = s->priv_data; + int lastPacket = 0; + int valid = 0; + + s->pict_type = AV_PICTURE_TYPE_NONE; + + avctx->time_base.num = 1; + avctx->time_base.den = 90000; + + if (buf && buf_size) { + switch(buf[0]) { + case 0x00: + if (buf_size == PCI_SIZE) { + /* PCI */ + uint32_t lba = AV_RB32(&buf[0x01]); + uint32_t startpts = AV_RB32(&buf[0x0D]); + uint32_t endpts = AV_RB32(&buf[0x11]); + + if (endpts > startpts) { + pc1->lba = lba; + s->pts = (int64_t)startpts; + s->duration = endpts - startpts; + + memcpy(pc1->buffer, buf, PCI_SIZE); + pc1->copied = PCI_SIZE; + valid = 1; + } + } + break; + + case 0x01: + if ((buf_size == DSI_SIZE) && (pc1->copied == PCI_SIZE)) { + /* DSI */ + uint32_t lba = AV_RB32(&buf[0x05]); + + if (lba == pc1->lba) { + memcpy(pc1->buffer + pc1->copied, buf, DSI_SIZE); + lastPacket = 1; + valid = 1; + } + } + break; + } + } + + if (!valid || lastPacket) { + pc1->copied = 0; + pc1->lba = 0xFFFFFFFF; + } + + if (lastPacket) { + *poutbuf = pc1->buffer; + *poutbuf_size = sizeof(pc1->buffer); + } else { + *poutbuf = NULL; + *poutbuf_size = 0; + } + + return buf_size; +} + +AVCodecParser ff_dvd_nav_parser = { + .codec_ids = { AV_CODEC_ID_DVD_NAV }, + .priv_data_size = sizeof(DVDNavParseContext), + .parser_init = dvd_nav_parse_init, + .parser_parse = dvd_nav_parse, +}; diff --git a/ffmpeg/libavcodec/dvdata.c b/ffmpeg/libavcodec/dvdata.c new file mode 100644 index 0000000..a7e3d59 --- /dev/null +++ b/ffmpeg/libavcodec/dvdata.c @@ -0,0 +1,122 @@ +/* + * Constants for DV codec + * Copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Constants for DV codec. + */ + +#include "avcodec.h" +#include "dvdata.h" + +/* unquant tables (not used directly) */ +const uint8_t ff_dv_quant_shifts[22][4] = { + { 3,3,4,4 }, + { 3,3,4,4 }, + { 2,3,3,4 }, + { 2,3,3,4 }, + { 2,2,3,3 }, + { 2,2,3,3 }, + { 1,2,2,3 }, + { 1,2,2,3 }, + { 1,1,2,2 }, + { 1,1,2,2 }, + { 0,1,1,2 }, + { 0,1,1,2 }, + { 0,0,1,1 }, + { 0,0,1,1 }, + { 0,0,0,1 }, + { 0,0,0,0 }, + { 0,0,0,0 }, + { 0,0,0,0 }, + { 0,0,0,0 }, + { 0,0,0,0 }, + { 0,0,0,0 }, + { 0,0,0,0 }, +}; + +const uint8_t ff_dv_quant_offset[4] = { 6, 3, 0, 1 }; + +const int ff_dv_iweight_88[64] = { + 32768, 16710, 16710, 17735, 17015, 17735, 18197, 18079, + 18079, 18197, 18725, 18559, 19196, 18559, 18725, 19284, + 19108, 19692, 19692, 19108, 19284, 21400, 19645, 20262, + 20214, 20262, 19645, 21400, 22733, 21845, 20867, 20815, + 20815, 20867, 21845, 22733, 23173, 23173, 21400, 21400, + 21400, 23173, 23173, 24600, 23764, 22017, 22017, 23764, + 24600, 25267, 24457, 22672, 24457, 25267, 25971, 25191, + 25191, 25971, 26715, 27962, 26715, 29642, 29642, 31536, +}; +const int ff_dv_iweight_248[64] = { + 32768, 17735, 16710, 18079, 18725, 21400, 17735, 19196, + 19108, 21845, 16384, 17735, 18725, 21400, 16710, 18079, + 20262, 23173, 18197, 19692, 18725, 20262, 20815, 23764, + 17735, 19196, 19108, 21845, 20262, 23173, 18197, 19692, + 21400, 24457, 19284, 20867, 21400, 23173, 22017, 25191, + 18725, 20262, 20815, 23764, 21400, 24457, 19284, 20867, + 24457, 27962, 22733, 24600, 25971, 29642, 21400, 23173, + 22017, 25191, 24457, 27962, 22733, 24600, 25971, 29642, +}; + +/** + * The "inverse" DV100 weights are actually just the spec weights (zig-zagged). + */ +const int ff_dv_iweight_1080_y[64] = { + 128, 16, 16, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 19, 18, 18, 19, + 19, 19, 19, 19, 19, 42, 38, 40, + 40, 40, 38, 42, 44, 43, 41, 41, + 41, 41, 43, 44, 45, 45, 42, 42, + 42, 45, 45, 48, 46, 43, 43, 46, + 48, 49, 48, 44, 48, 49, 101, 98, + 98, 101, 104, 109, 104, 116, 116, 123, +}; +const int ff_dv_iweight_1080_c[64] = { + 128, 16, 16, 17, 17, 17, 25, 25, + 25, 25, 26, 25, 26, 25, 26, 26, + 26, 27, 27, 26, 26, 42, 38, 40, + 40, 40, 38, 42, 44, 43, 41, 41, + 41, 41, 43, 44, 91, 91, 84, 84, + 84, 91, 91, 96, 93, 86, 86, 93, + 96, 197, 191, 177, 191, 197, 203, 197, + 197, 203, 209, 219, 209, 232, 232, 246, +}; +const int ff_dv_iweight_720_y[64] = { + 128, 16, 16, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 19, 18, 18, 19, + 19, 19, 19, 19, 19, 42, 38, 40, + 40, 40, 38, 42, 44, 43, 41, 41, + 41, 41, 43, 44, 68, 68, 63, 63, + 63, 68, 68, 96, 92, 86, 86, 92, + 96, 98, 96, 88, 96, 98, 202, 196, + 196, 202, 208, 218, 208, 232, 232, 246, +}; +const int ff_dv_iweight_720_c[64] = { + 128, 24, 24, 26, 26, 26, 36, 36, + 36, 36, 36, 36, 38, 36, 36, 38, + 38, 38, 38, 38, 38, 84, 76, 80, + 80, 80, 76, 84, 88, 86, 82, 82, + 82, 82, 86, 88, 182, 182, 168, 168, + 168, 182, 182, 192, 186, 192, 172, 186, + 192, 394, 382, 354, 382, 394, 406, 394, + 394, 406, 418, 438, 418, 464, 464, 492, +}; + diff --git a/ffmpeg/libavcodec/dvdata.h b/ffmpeg/libavcodec/dvdata.h new file mode 100644 index 0000000..97c20e3 --- /dev/null +++ b/ffmpeg/libavcodec/dvdata.h @@ -0,0 +1,124 @@ +/* + * Constants for DV codec + * Copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Constants for DV codec. + */ + +#ifndef AVCODEC_DVDATA_H +#define AVCODEC_DVDATA_H + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "dv_profile.h" + +typedef struct DVVideoContext { + const DVprofile *sys; + AVFrame picture; + AVCodecContext *avctx; + uint8_t *buf; + + uint8_t dv_zigzag[2][64]; + + void (*get_pixels)(int16_t *block, const uint8_t *pixels, int line_size); + void (*fdct[2])(int16_t *block); + void (*idct_put[2])(uint8_t *dest, int line_size, int16_t *block); + me_cmp_func ildct_cmp; +} DVVideoContext; + +enum dv_section_type { + dv_sect_header = 0x1f, + dv_sect_subcode = 0x3f, + dv_sect_vaux = 0x56, + dv_sect_audio = 0x76, + dv_sect_video = 0x96, +}; + +enum dv_pack_type { + dv_header525 = 0x3f, /* see dv_write_pack for important details on */ + dv_header625 = 0xbf, /* these two packs */ + dv_timecode = 0x13, + dv_audio_source = 0x50, + dv_audio_control = 0x51, + dv_audio_recdate = 0x52, + dv_audio_rectime = 0x53, + dv_video_source = 0x60, + dv_video_control = 0x61, + dv_video_recdate = 0x62, + dv_video_rectime = 0x63, + dv_unknown_pack = 0xff, +}; + +extern const uint8_t ff_dv_quant_shifts[22][4]; +extern const uint8_t ff_dv_quant_offset[4]; + +extern const int ff_dv_iweight_88[64]; +extern const int ff_dv_iweight_248[64]; +extern const int ff_dv_iweight_1080_y[64]; +extern const int ff_dv_iweight_1080_c[64]; +extern const int ff_dv_iweight_720_y[64]; +extern const int ff_dv_iweight_720_c[64]; + +#define DV_PROFILE_IS_HD(p) ((p)->video_stype & 0x10) +#define DV_PROFILE_IS_1080i50(p) (((p)->video_stype == 0x14) && ((p)->dsf == 1)) +#define DV_PROFILE_IS_720p50(p) (((p)->video_stype == 0x18) && ((p)->dsf == 1)) + +/** + * largest possible DV frame, in bytes (1080i50) + */ +#define DV_MAX_FRAME_SIZE 576000 + +/** + * maximum number of blocks per macroblock in any DV format + */ +#define DV_MAX_BPM 8 + +#define TEX_VLC_BITS 9 + +extern RL_VLC_ELEM ff_dv_rl_vlc[1184]; + +int ff_dv_init_dynamic_tables(const DVprofile *d); +int ff_dvvideo_init(AVCodecContext *avctx); + +static inline int dv_work_pool_size(const DVprofile *d) +{ + int size = d->n_difchan*d->difseg_size*27; + if (DV_PROFILE_IS_1080i50(d)) + size -= 3*27; + if (DV_PROFILE_IS_720p50(d)) + size -= 4*27; + return size; +} + +static inline void dv_calculate_mb_xy(DVVideoContext *s, DVwork_chunk *work_chunk, int m, int *mb_x, int *mb_y) +{ + *mb_x = work_chunk->mb_coordinates[m] & 0xff; + *mb_y = work_chunk->mb_coordinates[m] >> 8; + + /* We work with 720p frames split in half. The odd half-frame (chan==2,3) is displaced :-( */ + if (s->sys->height == 720 && !(s->buf[1]&0x0C)) { + *mb_y -= (*mb_y>17)?18:-72; /* shifting the Y coordinate down by 72/2 macro blocks */ + } +} + +#endif /* AVCODEC_DVDATA_H */ diff --git a/ffmpeg/libavcodec/dvdec.c b/ffmpeg/libavcodec/dvdec.c new file mode 100644 index 0000000..5cc205c --- /dev/null +++ b/ffmpeg/libavcodec/dvdec.c @@ -0,0 +1,382 @@ +/* + * DV decoder + * Copyright (c) 2002 Fabrice Bellard + * Copyright (c) 2004 Roman Shaposhnik + * + * 50 Mbps (DVCPRO50) support + * Copyright (c) 2006 Daniel Maas + * + * 100 Mbps (DVCPRO HD) support + * Initial code by Daniel Maas (funded by BBC R&D) + * Final code by Roman Shaposhnik + * + * Many thanks to Dan Dennedy for providing wealth + * of DV technical info. + * + * 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 + */ + +/** + * @file + * DV decoder + */ + +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "put_bits.h" +#include "simple_idct.h" +#include "dvdata.h" + +typedef struct BlockInfo { + const uint32_t *factor_table; + const uint8_t *scan_table; + uint8_t pos; /* position in block */ + void (*idct_put)(uint8_t *dest, int line_size, int16_t *block); + uint8_t partial_bit_count; + uint32_t partial_bit_buffer; + int shift_offset; +} BlockInfo; + +static const int dv_iweight_bits = 14; + +/* decode AC coefficients */ +static void dv_decode_ac(GetBitContext *gb, BlockInfo *mb, int16_t *block) +{ + int last_index = gb->size_in_bits; + const uint8_t *scan_table = mb->scan_table; + const uint32_t *factor_table = mb->factor_table; + int pos = mb->pos; + int partial_bit_count = mb->partial_bit_count; + int level, run, vlc_len, index; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + + /* if we must parse a partial VLC, we do it here */ + if (partial_bit_count > 0) { + re_cache = re_cache >> partial_bit_count | mb->partial_bit_buffer; + re_index -= partial_bit_count; + mb->partial_bit_count = 0; + } + + /* get the AC coefficients until last_index is reached */ + for (;;) { + av_dlog(NULL, "%2d: bits=%04x index=%d\n", pos, SHOW_UBITS(re, gb, 16), + re_index); + /* our own optimized GET_RL_VLC */ + index = NEG_USR32(re_cache, TEX_VLC_BITS); + vlc_len = ff_dv_rl_vlc[index].len; + if (vlc_len < 0) { + index = NEG_USR32((unsigned)re_cache << TEX_VLC_BITS, -vlc_len) + + ff_dv_rl_vlc[index].level; + vlc_len = TEX_VLC_BITS - vlc_len; + } + level = ff_dv_rl_vlc[index].level; + run = ff_dv_rl_vlc[index].run; + + /* gotta check if we're still within gb boundaries */ + if (re_index + vlc_len > last_index) { + /* should be < 16 bits otherwise a codeword could have been parsed */ + mb->partial_bit_count = last_index - re_index; + mb->partial_bit_buffer = re_cache & ~(-1u >> mb->partial_bit_count); + re_index = last_index; + break; + } + re_index += vlc_len; + + av_dlog(NULL, "run=%d level=%d\n", run, level); + pos += run; + if (pos >= 64) + break; + + level = (level * factor_table[pos] + (1 << (dv_iweight_bits - 1))) >> dv_iweight_bits; + block[scan_table[pos]] = level; + + UPDATE_CACHE(re, gb); + } + CLOSE_READER(re, gb); + mb->pos = pos; +} + +static inline void bit_copy(PutBitContext *pb, GetBitContext *gb) +{ + int bits_left = get_bits_left(gb); + while (bits_left >= MIN_CACHE_BITS) { + put_bits(pb, MIN_CACHE_BITS, get_bits(gb, MIN_CACHE_BITS)); + bits_left -= MIN_CACHE_BITS; + } + if (bits_left > 0) { + put_bits(pb, bits_left, get_bits(gb, bits_left)); + } +} + +/* mb_x and mb_y are in units of 8 pixels */ +static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) +{ + DVVideoContext *s = avctx->priv_data; + DVwork_chunk *work_chunk = arg; + int quant, dc, dct_mode, class1, j; + int mb_index, mb_x, mb_y, last_index; + int y_stride, linesize; + int16_t *block, *block1; + int c_offset; + uint8_t *y_ptr; + const uint8_t *buf_ptr; + PutBitContext pb, vs_pb; + GetBitContext gb; + BlockInfo mb_data[5 * DV_MAX_BPM], *mb, *mb1; + LOCAL_ALIGNED_16(int16_t, sblock, [5*DV_MAX_BPM], [64]); + LOCAL_ALIGNED_16(uint8_t, mb_bit_buffer, [ 80 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */ + LOCAL_ALIGNED_16(uint8_t, vs_bit_buffer, [5*80 + FF_INPUT_BUFFER_PADDING_SIZE]); /* allow some slack */ + const int log2_blocksize = 3-s->avctx->lowres; + int is_field_mode[5]; + + av_assert1((((int)mb_bit_buffer) & 7) == 0); + av_assert1((((int)vs_bit_buffer) & 7) == 0); + + memset(sblock, 0, 5*DV_MAX_BPM*sizeof(*sblock)); + + /* pass 1: read DC and AC coefficients in blocks */ + buf_ptr = &s->buf[work_chunk->buf_offset*80]; + block1 = &sblock[0][0]; + mb1 = mb_data; + init_put_bits(&vs_pb, vs_bit_buffer, 5 * 80); + for (mb_index = 0; mb_index < 5; mb_index++, mb1 += s->sys->bpm, block1 += s->sys->bpm * 64) { + /* skip header */ + quant = buf_ptr[3] & 0x0f; + buf_ptr += 4; + init_put_bits(&pb, mb_bit_buffer, 80); + mb = mb1; + block = block1; + is_field_mode[mb_index] = 0; + for (j = 0; j < s->sys->bpm; j++) { + last_index = s->sys->block_sizes[j]; + init_get_bits(&gb, buf_ptr, last_index); + + /* get the DC */ + dc = get_sbits(&gb, 9); + dct_mode = get_bits1(&gb); + class1 = get_bits(&gb, 2); + if (DV_PROFILE_IS_HD(s->sys)) { + mb->idct_put = s->idct_put[0]; + mb->scan_table = s->dv_zigzag[0]; + mb->factor_table = &s->sys->idct_factor[(j >= 4)*4*16*64 + class1*16*64 + quant*64]; + is_field_mode[mb_index] |= !j && dct_mode; + } else { + mb->idct_put = s->idct_put[dct_mode && log2_blocksize == 3]; + mb->scan_table = s->dv_zigzag[dct_mode]; + mb->factor_table = &s->sys->idct_factor[(class1 == 3)*2*22*64 + dct_mode*22*64 + + (quant + ff_dv_quant_offset[class1])*64]; + } + dc = dc << 2; + /* convert to unsigned because 128 is not added in the + standard IDCT */ + dc += 1024; + block[0] = dc; + buf_ptr += last_index >> 3; + mb->pos = 0; + mb->partial_bit_count = 0; + + av_dlog(avctx, "MB block: %d, %d ", mb_index, j); + dv_decode_ac(&gb, mb, block); + + /* write the remaining bits in a new buffer only if the + block is finished */ + if (mb->pos >= 64) + bit_copy(&pb, &gb); + + block += 64; + mb++; + } + + /* pass 2: we can do it just after */ + av_dlog(avctx, "***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index); + block = block1; + mb = mb1; + init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb)); + put_bits32(&pb, 0); // padding must be zeroed + flush_put_bits(&pb); + for (j = 0; j < s->sys->bpm; j++, block += 64, mb++) { + if (mb->pos < 64 && get_bits_left(&gb) > 0) { + dv_decode_ac(&gb, mb, block); + /* if still not finished, no need to parse other blocks */ + if (mb->pos < 64) + break; + } + } + /* all blocks are finished, so the extra bytes can be used at + the video segment level */ + if (j >= s->sys->bpm) + bit_copy(&vs_pb, &gb); + } + + /* we need a pass over the whole video segment */ + av_dlog(avctx, "***pass 3 size=%d\n", put_bits_count(&vs_pb)); + block = &sblock[0][0]; + mb = mb_data; + init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb)); + put_bits32(&vs_pb, 0); // padding must be zeroed + flush_put_bits(&vs_pb); + for (mb_index = 0; mb_index < 5; mb_index++) { + for (j = 0; j < s->sys->bpm; j++) { + if (mb->pos < 64) { + av_dlog(avctx, "start %d:%d\n", mb_index, j); + dv_decode_ac(&gb, mb, block); + } + if (mb->pos >= 64 && mb->pos < 127) + av_log(avctx, AV_LOG_ERROR, "AC EOB marker is absent pos=%d\n", mb->pos); + block += 64; + mb++; + } + } + + /* compute idct and place blocks */ + block = &sblock[0][0]; + mb = mb_data; + for (mb_index = 0; mb_index < 5; mb_index++) { + dv_calculate_mb_xy(s, work_chunk, mb_index, &mb_x, &mb_y); + + /* idct_put'ting luminance */ + if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P) || + (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) || + (s->sys->height >= 720 && mb_y != 134)) { + y_stride = (s->picture.linesize[0] << ((!is_field_mode[mb_index]) * log2_blocksize)); + } else { + y_stride = (2 << log2_blocksize); + } + y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x) << log2_blocksize); + linesize = s->picture.linesize[0] << is_field_mode[mb_index]; + mb[0] .idct_put(y_ptr , linesize, block + 0*64); + if (s->sys->video_stype == 4) { /* SD 422 */ + mb[2].idct_put(y_ptr + (1 << log2_blocksize) , linesize, block + 2*64); + } else { + mb[1].idct_put(y_ptr + (1 << log2_blocksize) , linesize, block + 1*64); + mb[2].idct_put(y_ptr + y_stride, linesize, block + 2*64); + mb[3].idct_put(y_ptr + (1 << log2_blocksize) + y_stride, linesize, block + 3*64); + } + mb += 4; + block += 4*64; + + /* idct_put'ting chrominance */ + c_offset = (((mb_y >> (s->sys->pix_fmt == AV_PIX_FMT_YUV420P)) * s->picture.linesize[1] + + (mb_x >> ((s->sys->pix_fmt == AV_PIX_FMT_YUV411P) ? 2 : 1))) << log2_blocksize); + for (j = 2; j; j--) { + uint8_t *c_ptr = s->picture.data[j] + c_offset; + if (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) { + uint64_t aligned_pixels[64/8]; + uint8_t *pixels = (uint8_t*)aligned_pixels; + uint8_t *c_ptr1, *ptr1; + int x, y; + mb->idct_put(pixels, 8, block); + for (y = 0; y < (1 << log2_blocksize); y++, c_ptr += s->picture.linesize[j], pixels += 8) { + ptr1 = pixels + (1 << (log2_blocksize - 1)); + c_ptr1 = c_ptr + (s->picture.linesize[j] << log2_blocksize); + for (x = 0; x < (1 << (log2_blocksize - 1)); x++) { + c_ptr[x] = pixels[x]; + c_ptr1[x] = ptr1[x]; + } + } + block += 64; mb++; + } else { + y_stride = (mb_y == 134) ? (1 << log2_blocksize) : + s->picture.linesize[j] << ((!is_field_mode[mb_index]) * log2_blocksize); + linesize = s->picture.linesize[j] << is_field_mode[mb_index]; + (mb++)-> idct_put(c_ptr , linesize, block); block += 64; + if (s->sys->bpm == 8) { + (mb++)->idct_put(c_ptr + y_stride, linesize, block); block += 64; + } + } + } + } + return 0; +} + +/* NOTE: exactly one frame must be given (120000 bytes for NTSC, + 144000 bytes for PAL - or twice those for 50Mbps) */ +static int dvvideo_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + DVVideoContext *s = avctx->priv_data; + const uint8_t* vsc_pack; + int ret, apt, is16_9; + + s->sys = avpriv_dv_frame_profile2(avctx, s->sys, buf, buf_size); + if (!s->sys || buf_size < s->sys->frame_size || ff_dv_init_dynamic_tables(s->sys)) { + av_log(avctx, AV_LOG_ERROR, "could not find dv frame profile\n"); + return -1; /* NOTE: we only accept several full frames */ + } + + s->picture.key_frame = 1; + s->picture.pict_type = AV_PICTURE_TYPE_I; + avctx->pix_fmt = s->sys->pix_fmt; + avctx->time_base = s->sys->time_base; + avcodec_set_dimensions(avctx, s->sys->width, s->sys->height); + if ((ret = ff_get_buffer(avctx, &s->picture, 0)) < 0) + return ret; + s->picture.interlaced_frame = 1; + s->picture.top_field_first = 0; + + /* Determine the codec's sample_aspect ratio and field order from the packet */ + vsc_pack = buf + 80*5 + 48 + 5; + if ( *vsc_pack == dv_video_control ) { + apt = buf[4] & 0x07; + is16_9 = (vsc_pack[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07); + avctx->sample_aspect_ratio = s->sys->sar[is16_9]; + s->picture.top_field_first = !(vsc_pack[3] & 0x40); + } + + s->buf = buf; + avctx->execute(avctx, dv_decode_video_segment, s->sys->work_chunks, NULL, + dv_work_pool_size(s->sys), sizeof(DVwork_chunk)); + + emms_c(); + + /* return image */ + *got_frame = 1; + av_frame_move_ref(data, &s->picture); + + return s->sys->frame_size; +} + +static int dvvideo_close(AVCodecContext *c) +{ + DVVideoContext *s = c->priv_data; + + av_frame_unref(&s->picture); + + return 0; +} + +AVCodec ff_dvvideo_decoder = { + .name = "dvvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DVVIDEO, + .priv_data_size = sizeof(DVVideoContext), + .init = ff_dvvideo_init, + .close = dvvideo_close, + .decode = dvvideo_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), +}; diff --git a/ffmpeg/libavcodec/dvdsub_parser.c b/ffmpeg/libavcodec/dvdsub_parser.c new file mode 100644 index 0000000..e50c339 --- /dev/null +++ b/ffmpeg/libavcodec/dvdsub_parser.c @@ -0,0 +1,88 @@ +/* + * DVD subtitle decoding + * Copyright (c) 2005 Fabrice Bellard + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "avcodec.h" + +/* parser definition */ +typedef struct DVDSubParseContext { + uint8_t *packet; + int packet_len; + int packet_index; +} DVDSubParseContext; + +static av_cold int dvdsub_parse_init(AVCodecParserContext *s) +{ + return 0; +} + +static int dvdsub_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + DVDSubParseContext *pc = s->priv_data; + + if (pc->packet_index == 0) { + if (buf_size < 2) + return 0; + pc->packet_len = AV_RB16(buf); + if (pc->packet_len == 0) /* HD-DVD subpicture packet */ + pc->packet_len = AV_RB32(buf+2); + av_freep(&pc->packet); + pc->packet = av_malloc(pc->packet_len); + } + if (pc->packet) { + if (pc->packet_index + buf_size <= pc->packet_len) { + memcpy(pc->packet + pc->packet_index, buf, buf_size); + pc->packet_index += buf_size; + if (pc->packet_index >= pc->packet_len) { + *poutbuf = pc->packet; + *poutbuf_size = pc->packet_len; + pc->packet_index = 0; + return buf_size; + } + } else { + /* erroneous size */ + pc->packet_index = 0; + } + } + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; +} + +static av_cold void dvdsub_parse_close(AVCodecParserContext *s) +{ + DVDSubParseContext *pc = s->priv_data; + av_freep(&pc->packet); +} + +AVCodecParser ff_dvdsub_parser = { + .codec_ids = { AV_CODEC_ID_DVD_SUBTITLE }, + .priv_data_size = sizeof(DVDSubParseContext), + .parser_init = dvdsub_parse_init, + .parser_parse = dvdsub_parse, + .parser_close = dvdsub_parse_close, +}; diff --git a/ffmpeg/libavcodec/dvdsubdec.c b/ffmpeg/libavcodec/dvdsubdec.c new file mode 100644 index 0000000..cb268b8 --- /dev/null +++ b/ffmpeg/libavcodec/dvdsubdec.c @@ -0,0 +1,611 @@ +/* + * DVD subtitle decoding + * Copyright (c) 2005 Fabrice Bellard + * + * 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 "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "libavutil/colorspace.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/avstring.h" + +//#define DEBUG + +typedef struct DVDSubContext +{ + AVClass *class; + uint32_t palette[16]; + char *palette_str; + int has_palette; + uint8_t colormap[4]; + uint8_t alpha[256]; +} DVDSubContext; + +static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + uint8_t r, g, b; + int i, y, cb, cr; + int r_add, g_add, b_add; + + for (i = num_values; i > 0; i--) { + y = *ycbcr++; + cr = *ycbcr++; + cb = *ycbcr++; + YUV_TO_RGB1_CCIR(cb, cr); + YUV_TO_RGB2_CCIR(r, g, b, y); + *rgba++ = (*alpha++ << 24) | (r << 16) | (g << 8) | b; + } +} + +static int decode_run_2bit(GetBitContext *gb, int *color) +{ + unsigned int v, t; + + v = 0; + for (t = 1; v < t && t <= 0x40; t <<= 2) + v = (v << 4) | get_bits(gb, 4); + *color = v & 3; + if (v < 4) { /* Code for fill rest of line */ + return INT_MAX; + } + return v >> 2; +} + +static int decode_run_8bit(GetBitContext *gb, int *color) +{ + int len; + int has_run = get_bits1(gb); + if (get_bits1(gb)) + *color = get_bits(gb, 8); + else + *color = get_bits(gb, 2); + if (has_run) { + if (get_bits1(gb)) { + len = get_bits(gb, 7); + if (len == 0) + len = INT_MAX; + else + len += 9; + } else + len = get_bits(gb, 3) + 2; + } else + len = 1; + return len; +} + +static int decode_rle(uint8_t *bitmap, int linesize, int w, int h, + const uint8_t *buf, int start, int buf_size, int is_8bit) +{ + GetBitContext gb; + int bit_len; + int x, y, len, color; + uint8_t *d; + + bit_len = (buf_size - start) * 8; + init_get_bits(&gb, buf + start, bit_len); + + x = 0; + y = 0; + d = bitmap; + for(;;) { + if (get_bits_count(&gb) > bit_len) + return -1; + if (is_8bit) + len = decode_run_8bit(&gb, &color); + else + len = decode_run_2bit(&gb, &color); + len = FFMIN(len, w - x); + memset(d + x, color, len); + x += len; + if (x >= w) { + y++; + if (y >= h) + break; + d += linesize; + x = 0; + /* byte align */ + align_get_bits(&gb); + } + } + return 0; +} + +static void guess_palette(DVDSubContext* ctx, + uint32_t *rgba_palette, + uint32_t subtitle_color) +{ + static const uint8_t level_map[4][4] = { + // this configuration (full range, lowest to highest) in tests + // seemed most common, so assume this + {0xff}, + {0x00, 0xff}, + {0x00, 0x80, 0xff}, + {0x00, 0x55, 0xaa, 0xff}, + }; + uint8_t color_used[16] = { 0 }; + int nb_opaque_colors, i, level, j, r, g, b; + uint8_t *colormap = ctx->colormap, *alpha = ctx->alpha; + + if(ctx->has_palette) { + for(i = 0; i < 4; i++) + rgba_palette[i] = (ctx->palette[colormap[i]] & 0x00ffffff) + | ((alpha[i] * 17U) << 24); + return; + } + + for(i = 0; i < 4; i++) + rgba_palette[i] = 0; + + nb_opaque_colors = 0; + for(i = 0; i < 4; i++) { + if (alpha[i] != 0 && !color_used[colormap[i]]) { + color_used[colormap[i]] = 1; + nb_opaque_colors++; + } + } + + if (nb_opaque_colors == 0) + return; + + j = 0; + memset(color_used, 0, 16); + for(i = 0; i < 4; i++) { + if (alpha[i] != 0) { + if (!color_used[colormap[i]]) { + level = level_map[nb_opaque_colors][j]; + r = (((subtitle_color >> 16) & 0xff) * level) >> 8; + g = (((subtitle_color >> 8) & 0xff) * level) >> 8; + b = (((subtitle_color >> 0) & 0xff) * level) >> 8; + rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17) << 24); + color_used[colormap[i]] = (i + 1); + j++; + } else { + rgba_palette[i] = (rgba_palette[color_used[colormap[i]] - 1] & 0x00ffffff) | + ((alpha[i] * 17) << 24); + } + } + } +} + +#define READ_OFFSET(a) (big_offsets ? AV_RB32(a) : AV_RB16(a)) + +static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, + const uint8_t *buf, int buf_size) +{ + int cmd_pos, pos, cmd, x1, y1, x2, y2, offset1, offset2, next_cmd_pos; + int big_offsets, offset_size, is_8bit = 0; + const uint8_t *yuv_palette = 0; + uint8_t *colormap = ctx->colormap, *alpha = ctx->alpha; + int date; + int i; + int is_menu = 0; + + if (buf_size < 10) + return -1; + + if (AV_RB16(buf) == 0) { /* HD subpicture with 4-byte offsets */ + big_offsets = 1; + offset_size = 4; + cmd_pos = 6; + } else { + big_offsets = 0; + offset_size = 2; + cmd_pos = 2; + } + + cmd_pos = READ_OFFSET(buf + cmd_pos); + + while (cmd_pos > 0 && cmd_pos < buf_size - 2 - offset_size) { + date = AV_RB16(buf + cmd_pos); + next_cmd_pos = READ_OFFSET(buf + cmd_pos + 2); + av_dlog(NULL, "cmd_pos=0x%04x next=0x%04x date=%d\n", + cmd_pos, next_cmd_pos, date); + pos = cmd_pos + 2 + offset_size; + offset1 = -1; + offset2 = -1; + x1 = y1 = x2 = y2 = 0; + while (pos < buf_size) { + cmd = buf[pos++]; + av_dlog(NULL, "cmd=%02x\n", cmd); + switch(cmd) { + case 0x00: + /* menu subpicture */ + is_menu = 1; + break; + case 0x01: + /* set start date */ + sub_header->start_display_time = (date << 10) / 90; + break; + case 0x02: + /* set end date */ + sub_header->end_display_time = (date << 10) / 90; + break; + case 0x03: + /* set colormap */ + if ((buf_size - pos) < 2) + goto fail; + colormap[3] = buf[pos] >> 4; + colormap[2] = buf[pos] & 0x0f; + colormap[1] = buf[pos + 1] >> 4; + colormap[0] = buf[pos + 1] & 0x0f; + pos += 2; + break; + case 0x04: + /* set alpha */ + if ((buf_size - pos) < 2) + goto fail; + alpha[3] = buf[pos] >> 4; + alpha[2] = buf[pos] & 0x0f; + alpha[1] = buf[pos + 1] >> 4; + alpha[0] = buf[pos + 1] & 0x0f; + pos += 2; + av_dlog(NULL, "alpha=%x%x%x%x\n", alpha[0],alpha[1],alpha[2],alpha[3]); + break; + case 0x05: + case 0x85: + if ((buf_size - pos) < 6) + goto fail; + x1 = (buf[pos] << 4) | (buf[pos + 1] >> 4); + x2 = ((buf[pos + 1] & 0x0f) << 8) | buf[pos + 2]; + y1 = (buf[pos + 3] << 4) | (buf[pos + 4] >> 4); + y2 = ((buf[pos + 4] & 0x0f) << 8) | buf[pos + 5]; + if (cmd & 0x80) + is_8bit = 1; + av_dlog(NULL, "x1=%d x2=%d y1=%d y2=%d\n", x1, x2, y1, y2); + pos += 6; + break; + case 0x06: + if ((buf_size - pos) < 4) + goto fail; + offset1 = AV_RB16(buf + pos); + offset2 = AV_RB16(buf + pos + 2); + av_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); + pos += 4; + break; + case 0x86: + if ((buf_size - pos) < 8) + goto fail; + offset1 = AV_RB32(buf + pos); + offset2 = AV_RB32(buf + pos + 4); + av_dlog(NULL, "offset1=0x%04x offset2=0x%04x\n", offset1, offset2); + pos += 8; + break; + + case 0x83: + /* HD set palette */ + if ((buf_size - pos) < 768) + goto fail; + yuv_palette = buf + pos; + pos += 768; + break; + case 0x84: + /* HD set contrast (alpha) */ + if ((buf_size - pos) < 256) + goto fail; + for (i = 0; i < 256; i++) + alpha[i] = 0xFF - buf[pos+i]; + pos += 256; + break; + + case 0xff: + goto the_end; + default: + av_dlog(NULL, "unrecognised subpicture command 0x%x\n", cmd); + goto the_end; + } + } + the_end: + if (offset1 >= 0) { + int w, h; + uint8_t *bitmap; + + /* decode the bitmap */ + w = x2 - x1 + 1; + if (w < 0) + w = 0; + h = y2 - y1; + if (h < 0) + h = 0; + if (w > 0 && h > 0) { + if (sub_header->rects != NULL) { + for (i = 0; i < sub_header->num_rects; i++) { + av_freep(&sub_header->rects[i]->pict.data[0]); + av_freep(&sub_header->rects[i]->pict.data[1]); + av_freep(&sub_header->rects[i]); + } + av_freep(&sub_header->rects); + sub_header->num_rects = 0; + } + + bitmap = av_malloc(w * h); + sub_header->rects = av_mallocz(sizeof(*sub_header->rects)); + sub_header->rects[0] = av_mallocz(sizeof(AVSubtitleRect)); + sub_header->num_rects = 1; + sub_header->rects[0]->pict.data[0] = bitmap; + decode_rle(bitmap, w * 2, w, (h + 1) / 2, + buf, offset1, buf_size, is_8bit); + decode_rle(bitmap + w, w * 2, w, h / 2, + buf, offset2, buf_size, is_8bit); + sub_header->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + if (is_8bit) { + if (yuv_palette == 0) + goto fail; + sub_header->rects[0]->nb_colors = 256; + yuv_a_to_rgba(yuv_palette, alpha, (uint32_t*)sub_header->rects[0]->pict.data[1], 256); + } else { + sub_header->rects[0]->nb_colors = 4; + guess_palette(ctx, (uint32_t*)sub_header->rects[0]->pict.data[1], + 0xffff00); + } + sub_header->rects[0]->x = x1; + sub_header->rects[0]->y = y1; + sub_header->rects[0]->w = w; + sub_header->rects[0]->h = h; + sub_header->rects[0]->type = SUBTITLE_BITMAP; + sub_header->rects[0]->pict.linesize[0] = w; + sub_header->rects[0]->flags = is_menu ? AV_SUBTITLE_FLAG_FORCED : 0; + } + } + if (next_cmd_pos < cmd_pos) { + av_log(NULL, AV_LOG_ERROR, "Invalid command offset\n"); + break; + } + if (next_cmd_pos == cmd_pos) + break; + cmd_pos = next_cmd_pos; + } + if (sub_header->num_rects > 0) + return is_menu; + fail: + if (sub_header->rects != NULL) { + for (i = 0; i < sub_header->num_rects; i++) { + av_freep(&sub_header->rects[i]->pict.data[0]); + av_freep(&sub_header->rects[i]->pict.data[1]); + av_freep(&sub_header->rects[i]); + } + av_freep(&sub_header->rects); + sub_header->num_rects = 0; + } + return -1; +} + +static int is_transp(const uint8_t *buf, int pitch, int n, + const uint8_t *transp_color) +{ + int i; + for(i = 0; i < n; i++) { + if (!transp_color[*buf]) + return 0; + buf += pitch; + } + return 1; +} + +/* return 0 if empty rectangle, 1 if non empty */ +static int find_smallest_bounding_rectangle(AVSubtitle *s) +{ + uint8_t transp_color[256] = { 0 }; + int y1, y2, x1, x2, y, w, h, i; + uint8_t *bitmap; + + if (s->num_rects == 0 || s->rects == NULL || s->rects[0]->w <= 0 || s->rects[0]->h <= 0) + return 0; + + for(i = 0; i < s->rects[0]->nb_colors; i++) { + if ((((uint32_t*)s->rects[0]->pict.data[1])[i] >> 24) == 0) + transp_color[i] = 1; + } + y1 = 0; + while (y1 < s->rects[0]->h && is_transp(s->rects[0]->pict.data[0] + y1 * s->rects[0]->pict.linesize[0], + 1, s->rects[0]->w, transp_color)) + y1++; + if (y1 == s->rects[0]->h) { + av_freep(&s->rects[0]->pict.data[0]); + s->rects[0]->w = s->rects[0]->h = 0; + return 0; + } + + y2 = s->rects[0]->h - 1; + while (y2 > 0 && is_transp(s->rects[0]->pict.data[0] + y2 * s->rects[0]->pict.linesize[0], 1, + s->rects[0]->w, transp_color)) + y2--; + x1 = 0; + while (x1 < (s->rects[0]->w - 1) && is_transp(s->rects[0]->pict.data[0] + x1, s->rects[0]->pict.linesize[0], + s->rects[0]->h, transp_color)) + x1++; + x2 = s->rects[0]->w - 1; + while (x2 > 0 && is_transp(s->rects[0]->pict.data[0] + x2, s->rects[0]->pict.linesize[0], s->rects[0]->h, + transp_color)) + x2--; + w = x2 - x1 + 1; + h = y2 - y1 + 1; + bitmap = av_malloc(w * h); + if (!bitmap) + return 1; + for(y = 0; y < h; y++) { + memcpy(bitmap + w * y, s->rects[0]->pict.data[0] + x1 + (y1 + y) * s->rects[0]->pict.linesize[0], w); + } + av_freep(&s->rects[0]->pict.data[0]); + s->rects[0]->pict.data[0] = bitmap; + s->rects[0]->pict.linesize[0] = w; + s->rects[0]->w = w; + s->rects[0]->h = h; + s->rects[0]->x += x1; + s->rects[0]->y += y1; + return 1; +} + +#ifdef DEBUG +#undef fprintf +#undef perror +#undef exit +static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h, + uint32_t *rgba_palette) +{ + int x, y, v; + FILE *f; + + f = fopen(filename, "w"); + if (!f) { + perror(filename); + exit(1); + } + fprintf(f, "P6\n" + "%d %d\n" + "%d\n", + w, h, 255); + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + v = rgba_palette[bitmap[y * w + x]]; + putc((v >> 16) & 0xff, f); + putc((v >> 8) & 0xff, f); + putc((v >> 0) & 0xff, f); + } + } + fclose(f); +} +#endif + +static int dvdsub_decode(AVCodecContext *avctx, + void *data, int *data_size, + AVPacket *avpkt) +{ + DVDSubContext *ctx = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVSubtitle *sub = data; + int is_menu; + + is_menu = decode_dvd_subtitles(ctx, sub, buf, buf_size); + + if (is_menu < 0) { + no_subtitle: + *data_size = 0; + + return buf_size; + } + if (!is_menu && find_smallest_bounding_rectangle(sub) == 0) + goto no_subtitle; + +#if defined(DEBUG) + av_dlog(NULL, "start=%d ms end =%d ms\n", + sub->start_display_time, + sub->end_display_time); + ppm_save("/tmp/a.ppm", sub->rects[0]->pict.data[0], + sub->rects[0]->w, sub->rects[0]->h, sub->rects[0]->pict.data[1]); +#endif + + *data_size = 1; + return buf_size; +} + +static void parse_palette(DVDSubContext *ctx, char *p) +{ + int i; + + ctx->has_palette = 1; + for(i=0;i<16;i++) { + ctx->palette[i] = strtoul(p, &p, 16); + while(*p == ',' || av_isspace(*p)) + p++; + } +} + +static int dvdsub_parse_extradata(AVCodecContext *avctx) +{ + DVDSubContext *ctx = (DVDSubContext*) avctx->priv_data; + char *dataorig, *data; + + if (!avctx->extradata || !avctx->extradata_size) + return 1; + + dataorig = data = av_malloc(avctx->extradata_size+1); + if (!data) + return AVERROR(ENOMEM); + memcpy(data, avctx->extradata, avctx->extradata_size); + data[avctx->extradata_size] = '\0'; + + for(;;) { + int pos = strcspn(data, "\n\r"); + if (pos==0 && *data==0) + break; + + if (strncmp("palette:", data, 8) == 0) { + parse_palette(ctx, data + 8); + } else if (strncmp("size:", data, 5) == 0) { + int w, h; + if (sscanf(data + 5, "%dx%d", &w, &h) == 2 && + av_image_check_size(w, h, 0, avctx) >= 0) + avcodec_set_dimensions(avctx, w, h); + } + + data += pos; + data += strspn(data, "\n\r"); + } + + av_free(dataorig); + return 1; +} + +static int dvdsub_init(AVCodecContext *avctx) +{ + DVDSubContext *ctx = avctx->priv_data; + int ret; + + if ((ret = dvdsub_parse_extradata(avctx)) < 0) + return ret; + + if (ctx->palette_str) + parse_palette(ctx, ctx->palette_str); + if (ctx->has_palette) { + int i; + av_log(avctx, AV_LOG_DEBUG, "palette:"); + for(i=0;i<16;i++) + av_log(avctx, AV_LOG_DEBUG, " 0x%06x", ctx->palette[i]); + av_log(avctx, AV_LOG_DEBUG, "\n"); + } + + return 1; +} + +#define OFFSET(field) offsetof(DVDSubContext, field) +#define VD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, + { NULL } +}; +static const AVClass class = { + .class_name = "dvdsubdec", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_dvdsub_decoder = { + .name = "dvdsub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_DVD_SUBTITLE, + .priv_data_size = sizeof(DVDSubContext), + .init = dvdsub_init, + .decode = dvdsub_decode, + .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), + .priv_class = &class, +}; diff --git a/ffmpeg/libavcodec/dvdsubenc.c b/ffmpeg/libavcodec/dvdsubenc.c new file mode 100644 index 0000000..6e19623 --- /dev/null +++ b/ffmpeg/libavcodec/dvdsubenc.c @@ -0,0 +1,443 @@ +/* + * DVD subtitle encoding + * Copyright (c) 2005 Wolfram Gloger + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "libavutil/avassert.h" +#include "libavutil/bprint.h" +#include "libavutil/imgutils.h" + +typedef struct { + uint32_t global_palette[16]; +} DVDSubtitleContext; + +// ncnt is the nibble counter +#define PUTNIBBLE(val)\ +do {\ + if (ncnt++ & 1)\ + *q++ = bitbuf | ((val) & 0x0f);\ + else\ + bitbuf = (val) << 4;\ +} while(0) + +static void dvd_encode_rle(uint8_t **pq, + const uint8_t *bitmap, int linesize, + int w, int h, + const int cmap[256]) +{ + uint8_t *q; + unsigned int bitbuf = 0; + int ncnt; + int x, y, len, color; + + q = *pq; + + for (y = 0; y < h; ++y) { + ncnt = 0; + for(x = 0; x < w; x += len) { + color = bitmap[x]; + for (len=1; x+len < w; ++len) + if (bitmap[x+len] != color) + break; + color = cmap[color]; + av_assert0(color < 4); + if (len < 0x04) { + PUTNIBBLE((len << 2)|color); + } else if (len < 0x10) { + PUTNIBBLE(len >> 2); + PUTNIBBLE((len << 2)|color); + } else if (len < 0x40) { + PUTNIBBLE(0); + PUTNIBBLE(len >> 2); + PUTNIBBLE((len << 2)|color); + } else if (x+len == w) { + PUTNIBBLE(0); + PUTNIBBLE(0); + PUTNIBBLE(0); + PUTNIBBLE(color); + } else { + if (len > 0xff) + len = 0xff; + PUTNIBBLE(0); + PUTNIBBLE(len >> 6); + PUTNIBBLE(len >> 2); + PUTNIBBLE((len << 2)|color); + } + } + /* end of line */ + if (ncnt & 1) + PUTNIBBLE(0); + bitmap += linesize; + } + + *pq = q; +} + +static int color_distance(uint32_t a, uint32_t b) +{ + int r = 0, d, i; + int alpha_a = 8, alpha_b = 8; + + for (i = 24; i >= 0; i -= 8) { + d = alpha_a * (int)((a >> i) & 0xFF) - + alpha_b * (int)((b >> i) & 0xFF); + r += d * d; + alpha_a = a >> 28; + alpha_b = b >> 28; + } + return r; +} + +/** + * Count colors used in a rectangle, quantizing alpha and grouping by + * nearest global palette entry. + */ +static void count_colors(AVCodecContext *avctx, unsigned hits[33], + const AVSubtitleRect *r) +{ + DVDSubtitleContext *dvdc = avctx->priv_data; + unsigned count[256] = { 0 }; + uint32_t *palette = (uint32_t *)r->pict.data[1]; + uint32_t color; + int x, y, i, j, match, d, best_d, av_uninit(best_j); + uint8_t *p = r->pict.data[0]; + + for (y = 0; y < r->h; y++) { + for (x = 0; x < r->w; x++) + count[*(p++)]++; + p += r->pict.linesize[0] - r->w; + } + for (i = 0; i < 256; i++) { + if (!count[i]) /* avoid useless search */ + continue; + color = palette[i]; + /* 0: transparent, 1-16: semi-transparent, 17-33 opaque */ + match = color < 0x33000000 ? 0 : color < 0xCC000000 ? 1 : 17; + if (match) { + best_d = INT_MAX; + for (j = 0; j < 16; j++) { + d = color_distance(0xFF000000 | color, + 0xFF000000 | dvdc->global_palette[j]); + if (d < best_d) { + best_d = d; + best_j = j; + } + } + match += best_j; + } + hits[match] += count[i]; + } +} + +static void select_palette(AVCodecContext *avctx, int out_palette[4], + int out_alpha[4], unsigned hits[33]) +{ + DVDSubtitleContext *dvdc = avctx->priv_data; + int i, j, bright, mult; + uint32_t color; + int selected[4] = { 0 }; + uint32_t pseudopal[33] = { 0 }; + uint32_t refcolor[3] = { 0x00000000, 0xFFFFFFFF, 0xFF000000 }; + + /* Bonus for transparent: if the rectangle fits tightly the text, the + background color can be quite rare, but it would be ugly without it */ + hits[0] *= 16; + /* Bonus for bright colors */ + for (i = 0; i < 16; i++) { + if (!(hits[1 + i] + hits[17 + i])) + continue; /* skip unused colors to gain time */ + color = dvdc->global_palette[i]; + bright = 0; + for (j = 0; j < 3; j++, color >>= 8) + bright += (color & 0xFF) < 0x40 || (color & 0xFF) >= 0xC0; + mult = 2 + FFMIN(bright, 2); + hits[ 1 + i] *= mult; + hits[17 + i] *= mult; + } + + /* Select four most frequent colors */ + for (i = 0; i < 4; i++) { + for (j = 0; j < 33; j++) + if (hits[j] > hits[selected[i]]) + selected[i] = j; + hits[selected[i]] = 0; + } + + /* Order the colors like in most DVDs: + 0: background, 1: foreground, 2: outline */ + for (i = 0; i < 16; i++) { + pseudopal[ 1 + i] = 0x80000000 | dvdc->global_palette[i]; + pseudopal[17 + i] = 0xFF000000 | dvdc->global_palette[i]; + } + for (i = 0; i < 3; i++) { + int best_d = color_distance(refcolor[i], pseudopal[selected[i]]); + for (j = i + 1; j < 4; j++) { + int d = color_distance(refcolor[i], pseudopal[selected[j]]); + if (d < best_d) { + FFSWAP(int, selected[i], selected[j]); + best_d = d; + } + } + } + + /* Output */ + for (i = 0; i < 4; i++) { + out_palette[i] = selected[i] ? (selected[i] - 1) & 0xF : 0; + out_alpha [i] = !selected[i] ? 0 : selected[i] < 17 ? 0x80 : 0xFF; + } +} + +static void build_color_map(AVCodecContext *avctx, int cmap[], + const uint32_t palette[], + const int out_palette[], unsigned int const out_alpha[]) +{ + DVDSubtitleContext *dvdc = avctx->priv_data; + int i, j, d, best_d; + uint32_t pseudopal[4]; + + for (i = 0; i < 4; i++) + pseudopal[i] = (out_alpha[i] << 24) | + dvdc->global_palette[out_palette[i]]; + for (i = 0; i < 256; i++) { + best_d = INT_MAX; + for (j = 0; j < 4; j++) { + d = color_distance(pseudopal[j], palette[i]); + if (d < best_d) { + cmap[i] = j; + best_d = d; + } + } + } +} + +static void copy_rectangle(AVSubtitleRect *dst, AVSubtitleRect *src, int cmap[]) +{ + int x, y; + uint8_t *p, *q; + + p = src->pict.data[0]; + q = dst->pict.data[0] + (src->x - dst->x) + + (src->y - dst->y) * dst->pict.linesize[0]; + for (y = 0; y < src->h; y++) { + for (x = 0; x < src->w; x++) + *(q++) = cmap[*(p++)]; + p += src->pict.linesize[0] - src->w; + q += dst->pict.linesize[0] - src->w; + } +} + +static int encode_dvd_subtitles(AVCodecContext *avctx, + uint8_t *outbuf, int outbuf_size, + const AVSubtitle *h) +{ + DVDSubtitleContext *dvdc = avctx->priv_data; + uint8_t *q, *qq; + int offset1, offset2; + int i, rects = h->num_rects, ret; + unsigned global_palette_hits[33] = { 0 }; + int cmap[256]; + int out_palette[4]; + int out_alpha[4]; + AVSubtitleRect vrect; + uint8_t *vrect_data = NULL; + int x2, y2; + + if (rects == 0 || h->rects == NULL) + return AVERROR(EINVAL); + for (i = 0; i < rects; i++) + if (h->rects[i]->type != SUBTITLE_BITMAP) { + av_log(avctx, AV_LOG_ERROR, "Bitmap subtitle required\n"); + return AVERROR(EINVAL); + } + vrect = *h->rects[0]; + + if (rects > 1) { + /* DVD subtitles can have only one rectangle: build a virtual + rectangle containing all actual rectangles. + The data of the rectangles will be copied later, when the palette + is decided, because the rectangles may have different palettes. */ + int xmin = h->rects[0]->x, xmax = xmin + h->rects[0]->w; + int ymin = h->rects[0]->y, ymax = ymin + h->rects[0]->h; + for (i = 1; i < rects; i++) { + xmin = FFMIN(xmin, h->rects[i]->x); + ymin = FFMIN(ymin, h->rects[i]->y); + xmax = FFMAX(xmax, h->rects[i]->x + h->rects[i]->w); + ymax = FFMAX(ymax, h->rects[i]->y + h->rects[i]->h); + } + vrect.x = xmin; + vrect.y = ymin; + vrect.w = xmax - xmin; + vrect.h = ymax - ymin; + if ((ret = av_image_check_size(vrect.w, vrect.h, 0, avctx)) < 0) + return ret; + + /* Count pixels outside the virtual rectangle as transparent */ + global_palette_hits[0] = vrect.w * vrect.h; + for (i = 0; i < rects; i++) + global_palette_hits[0] -= h->rects[i]->w * h->rects[i]->h; + } + + for (i = 0; i < rects; i++) + count_colors(avctx, global_palette_hits, h->rects[i]); + select_palette(avctx, out_palette, out_alpha, global_palette_hits); + + if (rects > 1) { + if (!(vrect_data = av_calloc(vrect.w, vrect.h))) + return AVERROR(ENOMEM); + vrect.pict.data [0] = vrect_data; + vrect.pict.linesize[0] = vrect.w; + for (i = 0; i < rects; i++) { + build_color_map(avctx, cmap, (uint32_t *)h->rects[i]->pict.data[1], + out_palette, out_alpha); + copy_rectangle(&vrect, h->rects[i], cmap); + } + for (i = 0; i < 4; i++) + cmap[i] = i; + } else { + build_color_map(avctx, cmap, (uint32_t *)h->rects[0]->pict.data[1], + out_palette, out_alpha); + } + + av_log(avctx, AV_LOG_DEBUG, "Selected palette:"); + for (i = 0; i < 4; i++) + av_log(avctx, AV_LOG_DEBUG, " 0x%06x@@%02x (0x%x,0x%x)", + dvdc->global_palette[out_palette[i]], out_alpha[i], + out_palette[i], out_alpha[i] >> 4); + av_log(avctx, AV_LOG_DEBUG, "\n"); + + // encode data block + q = outbuf + 4; + offset1 = q - outbuf; + // worst case memory requirement: 1 nibble per pixel.. + if ((q - outbuf) + vrect.w * vrect.h / 2 + 17 + 21 > outbuf_size) { + av_log(NULL, AV_LOG_ERROR, "dvd_subtitle too big\n"); + ret = AVERROR_BUFFER_TOO_SMALL; + goto fail; + } + dvd_encode_rle(&q, vrect.pict.data[0], vrect.w * 2, + vrect.w, (vrect.h + 1) >> 1, cmap); + offset2 = q - outbuf; + dvd_encode_rle(&q, vrect.pict.data[0] + vrect.w, vrect.w * 2, + vrect.w, vrect.h >> 1, cmap); + + // set data packet size + qq = outbuf + 2; + bytestream_put_be16(&qq, q - outbuf); + + // send start display command + bytestream_put_be16(&q, (h->start_display_time*90) >> 10); + bytestream_put_be16(&q, (q - outbuf) /*- 2 */ + 8 + 12 + 2); + *q++ = 0x03; // palette - 4 nibbles + *q++ = (out_palette[3] << 4) | out_palette[2]; + *q++ = (out_palette[1] << 4) | out_palette[0]; + *q++ = 0x04; // alpha - 4 nibbles + *q++ = (out_alpha[3] & 0xF0) | (out_alpha[2] >> 4); + *q++ = (out_alpha[1] & 0xF0) | (out_alpha[0] >> 4); + + // 12 bytes per rect + x2 = vrect.x + vrect.w - 1; + y2 = vrect.y + vrect.h - 1; + + *q++ = 0x05; + // x1 x2 -> 6 nibbles + *q++ = vrect.x >> 4; + *q++ = (vrect.x << 4) | ((x2 >> 8) & 0xf); + *q++ = x2; + // y1 y2 -> 6 nibbles + *q++ = vrect.y >> 4; + *q++ = (vrect.y << 4) | ((y2 >> 8) & 0xf); + *q++ = y2; + + *q++ = 0x06; + // offset1, offset2 + bytestream_put_be16(&q, offset1); + bytestream_put_be16(&q, offset2); + + *q++ = 0x01; // start command + *q++ = 0xff; // terminating command + + // send stop display command last + bytestream_put_be16(&q, (h->end_display_time*90) >> 10); + bytestream_put_be16(&q, (q - outbuf) - 2 /*+ 4*/); + *q++ = 0x02; // set end + *q++ = 0xff; // terminating command + + qq = outbuf; + bytestream_put_be16(&qq, q - outbuf); + + av_log(NULL, AV_LOG_DEBUG, "subtitle_packet size=%td\n", q - outbuf); + ret = q - outbuf; + +fail: + av_free(vrect_data); + return ret; +} + +static int dvdsub_init(AVCodecContext *avctx) +{ + DVDSubtitleContext *dvdc = avctx->priv_data; + static const uint32_t default_palette[16] = { + 0x000000, 0x0000FF, 0x00FF00, 0xFF0000, + 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF, + 0x808000, 0x8080FF, 0x800080, 0x80FF80, + 0x008080, 0xFF8080, 0x555555, 0xAAAAAA, + }; + AVBPrint extradata; + int i, ret; + + av_assert0(sizeof(dvdc->global_palette) == sizeof(default_palette)); + memcpy(dvdc->global_palette, default_palette, sizeof(dvdc->global_palette)); + + av_bprint_init(&extradata, 0, 1); + if (avctx->width && avctx->height) + av_bprintf(&extradata, "size: %dx%d\n", avctx->width, avctx->height); + av_bprintf(&extradata, "palette:"); + for (i = 0; i < 16; i++) + av_bprintf(&extradata, " %06"PRIx32"%c", + dvdc->global_palette[i] & 0xFFFFFF, i < 15 ? ',' : '\n'); + + ret = avpriv_bprint_to_extradata(avctx, &extradata); + if (ret < 0) + return ret; + + return 0; +} + +static int dvdsub_encode(AVCodecContext *avctx, + unsigned char *buf, int buf_size, + const AVSubtitle *sub) +{ + //DVDSubtitleContext *s = avctx->priv_data; + int ret; + + ret = encode_dvd_subtitles(avctx, buf, buf_size, sub); + return ret; +} + +AVCodec ff_dvdsub_encoder = { + .name = "dvdsub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_DVD_SUBTITLE, + .init = dvdsub_init, + .encode_sub = dvdsub_encode, + .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), + .priv_data_size = sizeof(DVDSubtitleContext), +}; diff --git a/ffmpeg/libavcodec/dxa.c b/ffmpeg/libavcodec/dxa.c new file mode 100644 index 0000000..2286f33 --- /dev/null +++ b/ffmpeg/libavcodec/dxa.c @@ -0,0 +1,331 @@ +/* + * Feeble Files/ScummVM DXA decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * DXA Video decoder + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "bytestream.h" +#include "avcodec.h" +#include "internal.h" + +#include + +/* + * Decoder context + */ +typedef struct DxaDecContext { + AVFrame prev; + + int dsize; + uint8_t *decomp_buf; + uint32_t pal[256]; +} DxaDecContext; + +static const int shift1[6] = { 0, 8, 8, 8, 4, 4 }; +static const int shift2[6] = { 0, 0, 8, 4, 0, 4 }; + +static int decode_13(AVCodecContext *avctx, DxaDecContext *c, uint8_t* dst, + int stride, uint8_t *src, uint8_t *ref) +{ + uint8_t *code, *data, *mv, *msk, *tmp, *tmp2; + int i, j, k; + int type, x, y, d, d2; + uint32_t mask; + + code = src + 12; + data = code + ((avctx->width * avctx->height) >> 4); + mv = data + AV_RB32(src + 0); + msk = mv + AV_RB32(src + 4); + + for(j = 0; j < avctx->height; j += 4){ + for(i = 0; i < avctx->width; i += 4){ + tmp = dst + i; + tmp2 = ref + i; + type = *code++; + switch(type){ + case 4: // motion compensation + x = (*mv) >> 4; if(x & 8) x = 8 - x; + y = (*mv++) & 0xF; if(y & 8) y = 8 - y; + tmp2 += x + y*stride; + case 0: // skip + case 5: // skip in method 12 + for(y = 0; y < 4; y++){ + memcpy(tmp, tmp2, 4); + tmp += stride; + tmp2 += stride; + } + break; + case 1: // masked change + case 10: // masked change with only half of pixels changed + case 11: // cases 10-15 are for method 12 only + case 12: + case 13: + case 14: + case 15: + if(type == 1){ + mask = AV_RB16(msk); + msk += 2; + }else{ + type -= 10; + mask = ((msk[0] & 0xF0) << shift1[type]) | ((msk[0] & 0xF) << shift2[type]); + msk++; + } + for(y = 0; y < 4; y++){ + for(x = 0; x < 4; x++){ + tmp[x] = (mask & 0x8000) ? *data++ : tmp2[x]; + mask <<= 1; + } + tmp += stride; + tmp2 += stride; + } + break; + case 2: // fill block + for(y = 0; y < 4; y++){ + memset(tmp, data[0], 4); + tmp += stride; + } + data++; + break; + case 3: // raw block + for(y = 0; y < 4; y++){ + memcpy(tmp, data, 4); + data += 4; + tmp += stride; + } + break; + case 8: // subblocks - method 13 only + mask = *msk++; + for(k = 0; k < 4; k++){ + d = ((k & 1) << 1) + ((k & 2) * stride); + d2 = ((k & 1) << 1) + ((k & 2) * stride); + tmp2 = ref + i + d2; + switch(mask & 0xC0){ + case 0x80: // motion compensation + x = (*mv) >> 4; if(x & 8) x = 8 - x; + y = (*mv++) & 0xF; if(y & 8) y = 8 - y; + tmp2 += x + y*stride; + case 0x00: // skip + tmp[d + 0 ] = tmp2[0]; + tmp[d + 1 ] = tmp2[1]; + tmp[d + 0 + stride] = tmp2[0 + stride]; + tmp[d + 1 + stride] = tmp2[1 + stride]; + break; + case 0x40: // fill + tmp[d + 0 ] = data[0]; + tmp[d + 1 ] = data[0]; + tmp[d + 0 + stride] = data[0]; + tmp[d + 1 + stride] = data[0]; + data++; + break; + case 0xC0: // raw + tmp[d + 0 ] = *data++; + tmp[d + 1 ] = *data++; + tmp[d + 0 + stride] = *data++; + tmp[d + 1 + stride] = *data++; + break; + } + mask <<= 2; + } + break; + case 32: // vector quantization - 2 colors + mask = AV_RB16(msk); + msk += 2; + for(y = 0; y < 4; y++){ + for(x = 0; x < 4; x++){ + tmp[x] = data[mask & 1]; + mask >>= 1; + } + tmp += stride; + tmp2 += stride; + } + data += 2; + break; + case 33: // vector quantization - 3 or 4 colors + case 34: + mask = AV_RB32(msk); + msk += 4; + for(y = 0; y < 4; y++){ + for(x = 0; x < 4; x++){ + tmp[x] = data[mask & 3]; + mask >>= 2; + } + tmp += stride; + tmp2 += stride; + } + data += type - 30; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown opcode %d\n", type); + return AVERROR_INVALIDDATA; + } + } + dst += stride * 4; + ref += stride * 4; + } + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + AVFrame *frame = data; + DxaDecContext * const c = avctx->priv_data; + uint8_t *outptr, *srcptr, *tmpptr; + unsigned long dsize; + int i, j, compr, ret; + int stride; + int pc = 0; + GetByteContext gb; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + /* make the palette available on the way out */ + if (bytestream2_peek_le32(&gb) == MKTAG('C','M','A','P')) { + bytestream2_skip(&gb, 4); + for(i = 0; i < 256; i++){ + c->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&gb); + } + pc = 1; + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); + frame->palette_has_changed = pc; + + outptr = frame->data[0]; + srcptr = c->decomp_buf; + tmpptr = c->prev.data[0]; + stride = frame->linesize[0]; + + if (bytestream2_get_le32(&gb) == MKTAG('N','U','L','L')) + compr = -1; + else + compr = bytestream2_get_byte(&gb); + + dsize = c->dsize; + if (compr != 4 && compr != -1) { + bytestream2_skip(&gb, 4); + if (uncompress(c->decomp_buf, &dsize, avpkt->data + bytestream2_tell(&gb), + bytestream2_get_bytes_left(&gb)) != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n"); + return AVERROR_UNKNOWN; + } + } + switch(compr){ + case -1: + frame->key_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_P; + if(c->prev.data[0]) + memcpy(frame->data[0], c->prev.data[0], frame->linesize[0] * avctx->height); + else{ // Should happen only when first frame is 'NULL' + memset(frame->data[0], 0, frame->linesize[0] * avctx->height); + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + } + break; + case 2: + case 3: + case 4: + case 5: + frame->key_frame = !(compr & 1); + frame->pict_type = (compr & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + for(j = 0; j < avctx->height; j++){ + if((compr & 1) && tmpptr){ + for(i = 0; i < avctx->width; i++) + outptr[i] = srcptr[i] ^ tmpptr[i]; + tmpptr += stride; + }else + memcpy(outptr, srcptr, avctx->width); + outptr += stride; + srcptr += avctx->width; + } + break; + case 12: // ScummVM coding + case 13: + frame->key_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_P; + if (!c->prev.data[0]) { + av_log(avctx, AV_LOG_ERROR, "Missing reference frame\n"); + return AVERROR_INVALIDDATA; + } + decode_13(avctx, c, frame->data[0], frame->linesize[0], srcptr, c->prev.data[0]); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", compr); + return AVERROR_INVALIDDATA; + } + + av_frame_unref(&c->prev); + if ((ret = av_frame_ref(&c->prev, frame)) < 0) + return ret; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + DxaDecContext * const c = avctx->priv_data; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + avcodec_get_frame_defaults(&c->prev); + + c->dsize = avctx->width * avctx->height * 2; + c->decomp_buf = av_malloc(c->dsize); + if (!c->decomp_buf) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + DxaDecContext * const c = avctx->priv_data; + + av_freep(&c->decomp_buf); + av_frame_unref(&c->prev); + + return 0; +} + +AVCodec ff_dxa_decoder = { + .name = "dxa", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DXA, + .priv_data_size = sizeof(DxaDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"), +}; diff --git a/ffmpeg/libavcodec/dxtory.c b/ffmpeg/libavcodec/dxtory.c new file mode 100644 index 0000000..28e66ba --- /dev/null +++ b/ffmpeg/libavcodec/dxtory.c @@ -0,0 +1,92 @@ +/* + * Dxtory decoder + * + * Copyright (c) 2011 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + int h, w; + AVFrame *pic = data; + const uint8_t *src = avpkt->data; + uint8_t *Y1, *Y2, *U, *V; + int ret; + + if (avpkt->size < avctx->width * avctx->height * 3 / 2 + 16) { + av_log(avctx, AV_LOG_ERROR, "packet too small\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + + if (AV_RL32(src) != 0x01000002) { + avpriv_request_sample(avctx, "Frame header %X", AV_RL32(src)); + return AVERROR_PATCHWELCOME; + } + src += 16; + + Y1 = pic->data[0]; + Y2 = pic->data[0] + pic->linesize[0]; + U = pic->data[1]; + V = pic->data[2]; + for (h = 0; h < avctx->height; h += 2) { + for (w = 0; w < avctx->width; w += 2) { + AV_COPY16(Y1 + w, src); + AV_COPY16(Y2 + w, src + 2); + U[w >> 1] = src[4] + 0x80; + V[w >> 1] = src[5] + 0x80; + src += 6; + } + Y1 += pic->linesize[0] << 1; + Y2 += pic->linesize[0] << 1; + U += pic->linesize[1]; + V += pic->linesize[2]; + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_dxtory_decoder = { + .name = "dxtory", + .long_name = NULL_IF_CONFIG_SMALL("Dxtory"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DXTORY, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/dxva2.c b/ffmpeg/libavcodec/dxva2.c new file mode 100644 index 0000000..0997c73 --- /dev/null +++ b/ffmpeg/libavcodec/dxva2.c @@ -0,0 +1,150 @@ +/* + * DXVA2 HW acceleration. + * + * copyright (c) 2010 Laurent Aimar + * + * 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 "dxva2_internal.h" + +void *ff_dxva2_get_surface(const Picture *picture) +{ + return picture->f.data[3]; +} + +unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx, + const Picture *picture) +{ + void *surface = ff_dxva2_get_surface(picture); + unsigned i; + + for (i = 0; i < ctx->surface_count; i++) + if (ctx->surface[i] == surface) + return i; + + assert(0); + return 0; +} + +int ff_dxva2_commit_buffer(AVCodecContext *avctx, + struct dxva_context *ctx, + DXVA2_DecodeBufferDesc *dsc, + unsigned type, const void *data, unsigned size, + unsigned mb_count) +{ + void *dxva_data; + unsigned dxva_size; + int result; + + if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type, + &dxva_data, &dxva_size))) { + av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type); + return -1; + } + if (size <= dxva_size) { + memcpy(dxva_data, data, size); + + memset(dsc, 0, sizeof(*dsc)); + dsc->CompressedBufferType = type; + dsc->DataSize = size; + dsc->NumMBsInBuffer = mb_count; + + result = 0; + } else { + av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type); + result = -1; + } + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) { + av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type); + result = -1; + } + return result; +} + +int ff_dxva2_common_end_frame(AVCodecContext *avctx, Picture *pic, + const void *pp, unsigned pp_size, + const void *qm, unsigned qm_size, + int (*commit_bs_si)(AVCodecContext *, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *slice)) +{ + struct dxva_context *ctx = avctx->hwaccel_context; + unsigned buffer_count = 0; + DXVA2_DecodeBufferDesc buffer[4]; + DXVA2_DecodeExecuteParams exec = { 0 }; + int result; + + if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder, + ff_dxva2_get_surface(pic), + NULL))) { + av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n"); + return -1; + } + + result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], + DXVA2_PictureParametersBufferType, + pp, pp_size, 0); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add picture parameter buffer\n"); + goto end; + } + buffer_count++; + + if (qm_size > 0) { + result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], + DXVA2_InverseQuantizationMatrixBufferType, + qm, qm_size, 0); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add inverse quantization matrix buffer\n"); + goto end; + } + buffer_count++; + } + + result = commit_bs_si(avctx, + &buffer[buffer_count + 0], + &buffer[buffer_count + 1]); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add bitstream or slice control buffer\n"); + goto end; + } + buffer_count += 2; + + /* TODO Film Grain when possible */ + + assert(buffer_count == 1 + (qm_size > 0) + 2); + + exec.NumCompBuffers = buffer_count; + exec.pCompressedBuffers = buffer; + exec.pExtensionData = NULL; + if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) { + av_log(avctx, AV_LOG_ERROR, "Failed to execute\n"); + result = -1; + } + +end: + if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) { + av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n"); + result = -1; + } + + return result; +} diff --git a/ffmpeg/libavcodec/dxva2.h b/ffmpeg/libavcodec/dxva2.h new file mode 100644 index 0000000..ac39e06 --- /dev/null +++ b/ffmpeg/libavcodec/dxva2.h @@ -0,0 +1,95 @@ +/* + * DXVA2 HW acceleration + * + * copyright (c) 2009 Laurent Aimar + * + * 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 + */ + +#ifndef AVCODEC_DXVA_H +#define AVCODEC_DXVA_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_dxva2 + * Public libavcodec DXVA2 header. + */ + +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600 +#undef _WIN32_WINNT +#endif + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0600 +#endif + +#include +#include +#include + +/** + * @defgroup lavc_codec_hwaccel_dxva2 DXVA2 + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards + +/** + * This structure is used to provides the necessary configurations and data + * to the DXVA2 FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct dxva_context { + /** + * DXVA2 decoder object + */ + IDirectXVideoDecoder *decoder; + + /** + * DXVA2 configuration used to create the decoder + */ + const DXVA2_ConfigPictureDecode *cfg; + + /** + * The number of surface in the surface array + */ + unsigned surface_count; + + /** + * The array of Direct3D surfaces used to create the decoder + */ + LPDIRECT3DSURFACE9 *surface; + + /** + * A bit field configuring the workarounds needed for using the decoder + */ + uint64_t workaround; + + /** + * Private to the FFmpeg AVHWAccel implementation + */ + unsigned report_id; +}; + +/** + * @} + */ + +#endif /* AVCODEC_DXVA_H */ diff --git a/ffmpeg/libavcodec/dxva2_h264.c b/ffmpeg/libavcodec/dxva2_h264.c new file mode 100644 index 0000000..1090502 --- /dev/null +++ b/ffmpeg/libavcodec/dxva2_h264.c @@ -0,0 +1,452 @@ +/* + * DXVA2 H264 HW acceleration. + * + * copyright (c) 2009 Laurent Aimar + * + * 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 "dxva2_internal.h" +#include "h264.h" +#include "h264data.h" + +struct dxva2_picture_context { + DXVA_PicParams_H264 pp; + DXVA_Qmatrix_H264 qm; + unsigned slice_count; + DXVA_Slice_H264_Short slice_short[MAX_SLICES]; + DXVA_Slice_H264_Long slice_long[MAX_SLICES]; + const uint8_t *bitstream; + unsigned bitstream_size; +}; + +static void fill_picture_entry(DXVA_PicEntry_H264 *pic, + unsigned index, unsigned flag) +{ + assert((index&0x7f) == index && (flag&0x01) == flag); + pic->bPicEntry = index | (flag << 7); +} + +static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h, + DXVA_PicParams_H264 *pp) +{ + const Picture *current_picture = h->cur_pic_ptr; + int i, j; + + memset(pp, 0, sizeof(*pp)); + /* Configure current picture */ + fill_picture_entry(&pp->CurrPic, + ff_dxva2_get_surface_index(ctx, current_picture), + h->picture_structure == PICT_BOTTOM_FIELD); + /* Configure the set of references */ + pp->UsedForReferenceFlags = 0; + pp->NonExistingFrameFlags = 0; + for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { + const Picture *r; + if (j < h->short_ref_count) { + r = h->short_ref[j++]; + } else { + r = NULL; + while (!r && j < h->short_ref_count + 16) + r = h->long_ref[j++ - h->short_ref_count]; + } + if (r) { + fill_picture_entry(&pp->RefFrameList[i], + ff_dxva2_get_surface_index(ctx, r), + r->long_ref != 0); + + if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX) + pp->FieldOrderCntList[i][0] = r->field_poc[0]; + if ((r->reference & PICT_BOTTOM_FIELD) && r->field_poc[1] != INT_MAX) + pp->FieldOrderCntList[i][1] = r->field_poc[1]; + + pp->FrameNumList[i] = r->long_ref ? r->pic_id : r->frame_num; + if (r->reference & PICT_TOP_FIELD) + pp->UsedForReferenceFlags |= 1 << (2*i + 0); + if (r->reference & PICT_BOTTOM_FIELD) + pp->UsedForReferenceFlags |= 1 << (2*i + 1); + } else { + pp->RefFrameList[i].bPicEntry = 0xff; + pp->FieldOrderCntList[i][0] = 0; + pp->FieldOrderCntList[i][1] = 0; + pp->FrameNumList[i] = 0; + } + } + + pp->wFrameWidthInMbsMinus1 = h->mb_width - 1; + pp->wFrameHeightInMbsMinus1 = h->mb_height - 1; + pp->num_ref_frames = h->sps.ref_frame_count; + + pp->wBitFields = ((h->picture_structure != PICT_FRAME) << 0) | + ((h->sps.mb_aff && + (h->picture_structure == PICT_FRAME)) << 1) | + (h->sps.residual_color_transform_flag << 2) | + /* sp_for_switch_flag (not implemented by FFmpeg) */ + (0 << 3) | + (h->sps.chroma_format_idc << 4) | + ((h->nal_ref_idc != 0) << 6) | + (h->pps.constrained_intra_pred << 7) | + (h->pps.weighted_pred << 8) | + (h->pps.weighted_bipred_idc << 9) | + /* MbsConsecutiveFlag */ + (1 << 11) | + (h->sps.frame_mbs_only_flag << 12) | + (h->pps.transform_8x8_mode << 13) | + ((h->sps.level_idc >= 31) << 14) | + /* IntraPicFlag (Modified if we detect a non + * intra slice in dxva2_h264_decode_slice) */ + (1 << 15); + + pp->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; + pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; + if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) + pp->Reserved16Bits = 0; + else + pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */ + pp->StatusReportFeedbackNumber = 1 + ctx->report_id++; + pp->CurrFieldOrderCnt[0] = 0; + if ((h->picture_structure & PICT_TOP_FIELD) && + current_picture->field_poc[0] != INT_MAX) + pp->CurrFieldOrderCnt[0] = current_picture->field_poc[0]; + pp->CurrFieldOrderCnt[1] = 0; + if ((h->picture_structure & PICT_BOTTOM_FIELD) && + current_picture->field_poc[1] != INT_MAX) + pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1]; + pp->pic_init_qs_minus26 = h->pps.init_qs - 26; + pp->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; + pp->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + pp->ContinuationFlag = 1; + pp->pic_init_qp_minus26 = h->pps.init_qp - 26; + pp->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; + pp->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; + pp->Reserved8BitsA = 0; + pp->frame_num = h->frame_num; + pp->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; + pp->pic_order_cnt_type = h->sps.poc_type; + if (h->sps.poc_type == 0) + pp->log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; + else if (h->sps.poc_type == 1) + pp->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; + pp->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; + pp->entropy_coding_mode_flag = h->pps.cabac; + pp->pic_order_present_flag = h->pps.pic_order_present; + pp->num_slice_groups_minus1 = h->pps.slice_group_count - 1; + pp->slice_group_map_type = h->pps.mb_slice_group_map_type; + pp->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; + pp->redundant_pic_cnt_present_flag= h->pps.redundant_pic_cnt_present; + pp->Reserved8BitsB = 0; + pp->slice_group_change_rate_minus1= 0; /* XXX not implemented by FFmpeg */ + //pp->SliceGroupMap[810]; /* XXX not implemented by FFmpeg */ +} + +static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm) +{ + unsigned i, j; + memset(qm, 0, sizeof(*qm)); + if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) { + for (i = 0; i < 6; i++) + for (j = 0; j < 16; j++) + qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][j]; + + for (i = 0; i < 64; i++) { + qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][i]; + qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][i]; + } + } else { + for (i = 0; i < 6; i++) + for (j = 0; j < 16; j++) + qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][zigzag_scan[j]]; + + for (i = 0; i < 64; i++) { + qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][ff_zigzag_direct[i]]; + qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][ff_zigzag_direct[i]]; + } + } +} + +static int is_slice_short(struct dxva_context *ctx) +{ + assert(ctx->cfg->ConfigBitstreamRaw == 1 || + ctx->cfg->ConfigBitstreamRaw == 2); + return ctx->cfg->ConfigBitstreamRaw == 2; +} + +static void fill_slice_short(DXVA_Slice_H264_Short *slice, + unsigned position, unsigned size) +{ + memset(slice, 0, sizeof(*slice)); + slice->BSNALunitDataLocation = position; + slice->SliceBytesInBuffer = size; + slice->wBadSliceChopping = 0; +} + +static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, + unsigned position, unsigned size) +{ + const H264Context *h = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + unsigned list; + + memset(slice, 0, sizeof(*slice)); + slice->BSNALunitDataLocation = position; + slice->SliceBytesInBuffer = size; + slice->wBadSliceChopping = 0; + + slice->first_mb_in_slice = (h->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + h->mb_x; + slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices */ + slice->BitOffsetToSliceData = get_bits_count(&h->gb); + slice->slice_type = ff_h264_get_slice_type(h); + if (h->slice_type_fixed) + slice->slice_type += 5; + slice->luma_log2_weight_denom = h->luma_log2_weight_denom; + slice->chroma_log2_weight_denom = h->chroma_log2_weight_denom; + if (h->list_count > 0) + slice->num_ref_idx_l0_active_minus1 = h->ref_count[0] - 1; + if (h->list_count > 1) + slice->num_ref_idx_l1_active_minus1 = h->ref_count[1] - 1; + slice->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2 - 26; + slice->slice_beta_offset_div2 = h->slice_beta_offset / 2 - 26; + slice->Reserved8Bits = 0; + + for (list = 0; list < 2; list++) { + unsigned i; + for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) { + if (list < h->list_count && i < h->ref_count[list]) { + const Picture *r = &h->ref_list[list][i]; + unsigned plane; + fill_picture_entry(&slice->RefPicList[list][i], + ff_dxva2_get_surface_index(ctx, r), + r->reference == PICT_BOTTOM_FIELD); + for (plane = 0; plane < 3; plane++) { + int w, o; + if (plane == 0 && h->luma_weight_flag[list]) { + w = h->luma_weight[i][list][0]; + o = h->luma_weight[i][list][1]; + } else if (plane >= 1 && h->chroma_weight_flag[list]) { + w = h->chroma_weight[i][list][plane-1][0]; + o = h->chroma_weight[i][list][plane-1][1]; + } else { + w = 1 << (plane == 0 ? h->luma_log2_weight_denom : + h->chroma_log2_weight_denom); + o = 0; + } + slice->Weights[list][i][plane][0] = w; + slice->Weights[list][i][plane][1] = o; + } + } else { + unsigned plane; + slice->RefPicList[list][i].bPicEntry = 0xff; + for (plane = 0; plane < 3; plane++) { + slice->Weights[list][i][plane][0] = 0; + slice->Weights[list][i][plane][1] = 0; + } + } + } + } + slice->slice_qs_delta = 0; /* XXX not implemented by FFmpeg */ + slice->slice_qp_delta = h->qscale - h->pps.init_qp; + slice->redundant_pic_cnt = h->redundant_pic_count; + if (h->slice_type == AV_PICTURE_TYPE_B) + slice->direct_spatial_mv_pred_flag = h->direct_spatial_mv_pred; + slice->cabac_init_idc = h->pps.cabac ? h->cabac_init_idc : 0; + if (h->deblocking_filter < 2) + slice->disable_deblocking_filter_idc = 1 - h->deblocking_filter; + else + slice->disable_deblocking_filter_idc = h->deblocking_filter; + slice->slice_id = h->current_slice - 1; +} + +static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *sc) +{ + const H264Context *h = avctx->priv_data; + const unsigned mb_count = h->mb_width * h->mb_height; + struct dxva_context *ctx = avctx->hwaccel_context; + const Picture *current_picture = h->cur_pic_ptr; + struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; + DXVA_Slice_H264_Short *slice = NULL; + uint8_t *dxva_data, *current, *end; + unsigned dxva_size; + void *slice_data; + unsigned slice_size; + unsigned padding; + unsigned i; + + /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ + if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, + DXVA2_BitStreamDateBufferType, + (void **)&dxva_data, &dxva_size))) + return -1; + current = dxva_data; + end = dxva_data + dxva_size; + + for (i = 0; i < ctx_pic->slice_count; i++) { + static const uint8_t start_code[] = { 0, 0, 1 }; + static const unsigned start_code_size = sizeof(start_code); + unsigned position, size; + + assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) == + offsetof(DXVA_Slice_H264_Long, BSNALunitDataLocation)); + assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) == + offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer)); + + if (is_slice_short(ctx)) + slice = &ctx_pic->slice_short[i]; + else + slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i]; + + position = slice->BSNALunitDataLocation; + size = slice->SliceBytesInBuffer; + if (start_code_size + size > end - current) { + av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); + break; + } + + slice->BSNALunitDataLocation = current - dxva_data; + slice->SliceBytesInBuffer = start_code_size + size; + + if (!is_slice_short(ctx)) { + DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice; + if (i < ctx_pic->slice_count - 1) + slice_long->NumMbsForSlice = + slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice; + else + slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice; + } + + memcpy(current, start_code, start_code_size); + current += start_code_size; + + memcpy(current, &ctx_pic->bitstream[position], size); + current += size; + } + padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); + if (slice && padding > 0) { + memset(current, 0, padding); + current += padding; + + slice->SliceBytesInBuffer += padding; + } + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, + DXVA2_BitStreamDateBufferType))) + return -1; + if (i < ctx_pic->slice_count) + return -1; + + memset(bs, 0, sizeof(*bs)); + bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; + bs->DataSize = current - dxva_data; + bs->NumMBsInBuffer = mb_count; + + if (is_slice_short(ctx)) { + slice_data = ctx_pic->slice_short; + slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short); + } else { + slice_data = ctx_pic->slice_long; + slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long); + } + assert((bs->DataSize & 127) == 0); + return ff_dxva2_commit_buffer(avctx, ctx, sc, + DXVA2_SliceControlBufferType, + slice_data, slice_size, mb_count); +} + + +static int dxva2_h264_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const H264Context *h = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private; + + if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + return -1; + assert(ctx_pic); + + /* Fill up DXVA_PicParams_H264 */ + fill_picture_parameters(ctx, h, &ctx_pic->pp); + + /* Fill up DXVA_Qmatrix_H264 */ + fill_scaling_lists(ctx, h, &ctx_pic->qm); + + ctx_pic->slice_count = 0; + ctx_pic->bitstream_size = 0; + ctx_pic->bitstream = NULL; + return 0; +} + +static int dxva2_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const H264Context *h = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + const Picture *current_picture = h->cur_pic_ptr; + struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; + unsigned position; + + if (ctx_pic->slice_count >= MAX_SLICES) + return -1; + + if (!ctx_pic->bitstream) + ctx_pic->bitstream = buffer; + ctx_pic->bitstream_size += size; + + position = buffer - ctx_pic->bitstream; + if (is_slice_short(ctx)) + fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], + position, size); + else + fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count], + position, size); + ctx_pic->slice_count++; + + if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) + ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */ + return 0; +} + +static int dxva2_h264_end_frame(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + struct dxva2_picture_context *ctx_pic = + h->cur_pic_ptr->hwaccel_picture_private; + int ret; + + if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) + return -1; + ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr, + &ctx_pic->pp, sizeof(ctx_pic->pp), + &ctx_pic->qm, sizeof(ctx_pic->qm), + commit_bitstream_and_slice_buffer); + if (!ret) + ff_h264_draw_horiz_band(h, 0, h->avctx->height); + return ret; +} + +AVHWAccel ff_h264_dxva2_hwaccel = { + .name = "h264_dxva2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .start_frame = dxva2_h264_start_frame, + .decode_slice = dxva2_h264_decode_slice, + .end_frame = dxva2_h264_end_frame, + .priv_data_size = sizeof(struct dxva2_picture_context), +}; diff --git a/ffmpeg/libavcodec/dxva2_internal.h b/ffmpeg/libavcodec/dxva2_internal.h new file mode 100644 index 0000000..8a454c1 --- /dev/null +++ b/ffmpeg/libavcodec/dxva2_internal.h @@ -0,0 +1,56 @@ +/* + * DXVA2 HW acceleration + * + * copyright (c) 2010 Laurent Aimar + * + * 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 + */ + +#ifndef AVCODEC_DXVA_INTERNAL_H +#define AVCODEC_DXVA_INTERNAL_H + +#define COBJMACROS + +#include "config.h" + +#include "dxva2.h" +#if HAVE_DXVA_H +#include +#endif + +#include "avcodec.h" +#include "mpegvideo.h" + +void *ff_dxva2_get_surface(const Picture *picture); + +unsigned ff_dxva2_get_surface_index(const struct dxva_context *, + const Picture *picture); + +int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *, + DXVA2_DecodeBufferDesc *, + unsigned type, const void *data, unsigned size, + unsigned mb_count); + + +int ff_dxva2_common_end_frame(AVCodecContext *, Picture *, + const void *pp, unsigned pp_size, + const void *qm, unsigned qm_size, + int (*commit_bs_si)(AVCodecContext *, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *slice)); + +#endif /* AVCODEC_DXVA_INTERNAL_H */ diff --git a/ffmpeg/libavcodec/dxva2_mpeg2.c b/ffmpeg/libavcodec/dxva2_mpeg2.c new file mode 100644 index 0000000..542f17c --- /dev/null +++ b/ffmpeg/libavcodec/dxva2_mpeg2.c @@ -0,0 +1,276 @@ +/* + * MPEG-2 HW acceleration. + * + * copyright (c) 2010 Laurent Aimar + * + * 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 "dxva2_internal.h" + +#define MAX_SLICES (SLICE_MAX_START_CODE - SLICE_MIN_START_CODE + 1) +struct dxva2_picture_context { + DXVA_PictureParameters pp; + DXVA_QmatrixData qm; + unsigned slice_count; + DXVA_SliceInfo slice[MAX_SLICES]; + + const uint8_t *bitstream; + unsigned bitstream_size; +}; + +static void fill_picture_parameters(AVCodecContext *avctx, + struct dxva_context *ctx, + const struct MpegEncContext *s, + DXVA_PictureParameters *pp) +{ + const Picture *current_picture = s->current_picture_ptr; + int is_field = s->picture_structure != PICT_FRAME; + + memset(pp, 0, sizeof(*pp)); + pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture); + pp->wDeblockedPictureIndex = 0; + if (s->pict_type != AV_PICTURE_TYPE_I) + pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->last_picture); + else + pp->wForwardRefPictureIndex = 0xffff; + if (s->pict_type == AV_PICTURE_TYPE_B) + pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->next_picture); + else + pp->wBackwardRefPictureIndex = 0xffff; + pp->wPicWidthInMBminus1 = s->mb_width - 1; + pp->wPicHeightInMBminus1 = (s->mb_height >> is_field) - 1; + pp->bMacroblockWidthMinus1 = 15; + pp->bMacroblockHeightMinus1 = 15; + pp->bBlockWidthMinus1 = 7; + pp->bBlockHeightMinus1 = 7; + pp->bBPPminus1 = 7; + pp->bPicStructure = s->picture_structure; + pp->bSecondField = is_field && !s->first_field; + pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I; + pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B; + pp->bBidirectionalAveragingMode = 0; + pp->bMVprecisionAndChromaRelation= 0; /* FIXME */ + pp->bChromaFormat = s->chroma_format; + pp->bPicScanFixed = 1; + pp->bPicScanMethod = s->alternate_scan ? 1 : 0; + pp->bPicReadbackRequests = 0; + pp->bRcontrol = 0; + pp->bPicSpatialResid8 = 0; + pp->bPicOverflowBlocks = 0; + pp->bPicExtrapolation = 0; + pp->bPicDeblocked = 0; + pp->bPicDeblockConfined = 0; + pp->bPic4MVallowed = 0; + pp->bPicOBMC = 0; + pp->bPicBinPB = 0; + pp->bMV_RPS = 0; + pp->bReservedBits = 0; + pp->wBitstreamFcodes = (s->mpeg_f_code[0][0] << 12) | + (s->mpeg_f_code[0][1] << 8) | + (s->mpeg_f_code[1][0] << 4) | + (s->mpeg_f_code[1][1] ); + pp->wBitstreamPCEelements = (s->intra_dc_precision << 14) | + (s->picture_structure << 12) | + (s->top_field_first << 11) | + (s->frame_pred_frame_dct << 10) | + (s->concealment_motion_vectors << 9) | + (s->q_scale_type << 8) | + (s->intra_vlc_format << 7) | + (s->alternate_scan << 6) | + (s->repeat_first_field << 5) | + (s->chroma_420_type << 4) | + (s->progressive_frame << 3); + pp->bBitstreamConcealmentNeed = 0; + pp->bBitstreamConcealmentMethod = 0; +} + +static void fill_quantization_matrices(AVCodecContext *avctx, + struct dxva_context *ctx, + const struct MpegEncContext *s, + DXVA_QmatrixData *qm) +{ + int i; + for (i = 0; i < 4; i++) + qm->bNewQmatrix[i] = 1; + for (i = 0; i < 64; i++) { + int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + qm->Qmatrix[0][i] = s->intra_matrix[n]; + qm->Qmatrix[1][i] = s->inter_matrix[n]; + qm->Qmatrix[2][i] = s->chroma_intra_matrix[n]; + qm->Qmatrix[3][i] = s->chroma_inter_matrix[n]; + } +} + +static void fill_slice(AVCodecContext *avctx, + const struct MpegEncContext *s, + DXVA_SliceInfo *slice, + unsigned position, + const uint8_t *buffer, unsigned size) +{ + int is_field = s->picture_structure != PICT_FRAME; + GetBitContext gb; + + memset(slice, 0, sizeof(*slice)); + slice->wHorizontalPosition = s->mb_x; + slice->wVerticalPosition = s->mb_y >> is_field; + slice->dwSliceBitsInBuffer = 8 * size; + slice->dwSliceDataLocation = position; + slice->bStartCodeBitOffset = 0; + slice->bReservedBits = 0; + /* XXX We store the index of the first MB and it will be fixed later */ + slice->wNumberMBsInSlice = (s->mb_y >> is_field) * s->mb_width + s->mb_x; + slice->wBadSliceChopping = 0; + + init_get_bits(&gb, &buffer[4], 8 * (size - 4)); + + slice->wQuantizerScaleCode = get_bits(&gb, 5); + while (get_bits1(&gb)) + skip_bits(&gb, 8); + + slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb); +} +static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *sc) +{ + const struct MpegEncContext *s = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + struct dxva2_picture_context *ctx_pic = + s->current_picture_ptr->hwaccel_picture_private; + const int is_field = s->picture_structure != PICT_FRAME; + const unsigned mb_count = s->mb_width * (s->mb_height >> is_field); + uint8_t *dxva_data, *current, *end; + unsigned dxva_size; + unsigned i; + + if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, + DXVA2_BitStreamDateBufferType, + (void **)&dxva_data, &dxva_size))) + return -1; + current = dxva_data; + end = dxva_data + dxva_size; + + for (i = 0; i < ctx_pic->slice_count; i++) { + DXVA_SliceInfo *slice = &ctx_pic->slice[i]; + unsigned position = slice->dwSliceDataLocation; + unsigned size = slice->dwSliceBitsInBuffer / 8; + if (size > end - current) { + av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); + break; + } + slice->dwSliceDataLocation = current - dxva_data; + + if (i < ctx_pic->slice_count - 1) + slice->wNumberMBsInSlice = + slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice; + else + slice->wNumberMBsInSlice = + mb_count - slice[0].wNumberMBsInSlice; + + memcpy(current, &ctx_pic->bitstream[position], size); + current += size; + } + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, + DXVA2_BitStreamDateBufferType))) + return -1; + if (i < ctx_pic->slice_count) + return -1; + + memset(bs, 0, sizeof(*bs)); + bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; + bs->DataSize = current - dxva_data; + bs->NumMBsInBuffer = mb_count; + + return ff_dxva2_commit_buffer(avctx, ctx, sc, + DXVA2_SliceControlBufferType, + ctx_pic->slice, + ctx_pic->slice_count * sizeof(*ctx_pic->slice), + mb_count); +} + +static int dxva2_mpeg2_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const struct MpegEncContext *s = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + struct dxva2_picture_context *ctx_pic = + s->current_picture_ptr->hwaccel_picture_private; + + if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + return -1; + assert(ctx_pic); + + fill_picture_parameters(avctx, ctx, s, &ctx_pic->pp); + fill_quantization_matrices(avctx, ctx, s, &ctx_pic->qm); + + ctx_pic->slice_count = 0; + ctx_pic->bitstream_size = 0; + ctx_pic->bitstream = NULL; + return 0; +} + +static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + const struct MpegEncContext *s = avctx->priv_data; + struct dxva2_picture_context *ctx_pic = + s->current_picture_ptr->hwaccel_picture_private; + unsigned position; + + if (ctx_pic->slice_count >= MAX_SLICES) + return -1; + + if (!ctx_pic->bitstream) + ctx_pic->bitstream = buffer; + ctx_pic->bitstream_size += size; + + position = buffer - ctx_pic->bitstream; + fill_slice(avctx, s, &ctx_pic->slice[ctx_pic->slice_count++], position, + buffer, size); + return 0; +} + +static int dxva2_mpeg2_end_frame(AVCodecContext *avctx) +{ + struct MpegEncContext *s = avctx->priv_data; + struct dxva2_picture_context *ctx_pic = + s->current_picture_ptr->hwaccel_picture_private; + int ret; + + if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) + return -1; + ret = ff_dxva2_common_end_frame(avctx, s->current_picture_ptr, + &ctx_pic->pp, sizeof(ctx_pic->pp), + &ctx_pic->qm, sizeof(ctx_pic->qm), + commit_bitstream_and_slice_buffer); + if (!ret) + ff_mpeg_draw_horiz_band(s, 0, avctx->height); + return ret; +} + +AVHWAccel ff_mpeg2_dxva2_hwaccel = { + .name = "mpeg2_dxva2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .start_frame = dxva2_mpeg2_start_frame, + .decode_slice = dxva2_mpeg2_decode_slice, + .end_frame = dxva2_mpeg2_end_frame, + .priv_data_size = sizeof(struct dxva2_picture_context), +}; diff --git a/ffmpeg/libavcodec/dxva2_vc1.c b/ffmpeg/libavcodec/dxva2_vc1.c new file mode 100644 index 0000000..92c78fd --- /dev/null +++ b/ffmpeg/libavcodec/dxva2_vc1.c @@ -0,0 +1,297 @@ +/* + * DXVA2 WMV3/VC-1 HW acceleration. + * + * copyright (c) 2010 Laurent Aimar + * + * 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 "dxva2_internal.h" +#include "vc1.h" +#include "vc1data.h" + +struct dxva2_picture_context { + DXVA_PictureParameters pp; + DXVA_SliceInfo si; + + const uint8_t *bitstream; + unsigned bitstream_size; +}; + +static void fill_picture_parameters(AVCodecContext *avctx, + struct dxva_context *ctx, const VC1Context *v, + DXVA_PictureParameters *pp) +{ + const MpegEncContext *s = &v->s; + const Picture *current_picture = s->current_picture_ptr; + + memset(pp, 0, sizeof(*pp)); + pp->wDecodedPictureIndex = + pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture); + if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type) + pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->last_picture); + else + pp->wForwardRefPictureIndex = 0xffff; + if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type) + pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->next_picture); + else + pp->wBackwardRefPictureIndex = 0xffff; + if (v->profile == PROFILE_ADVANCED) { + /* It is the cropped width/height -1 of the frame */ + pp->wPicWidthInMBminus1 = avctx->width - 1; + pp->wPicHeightInMBminus1= avctx->height - 1; + } else { + /* It is the coded width/height in macroblock -1 of the frame */ + pp->wPicWidthInMBminus1 = s->mb_width - 1; + pp->wPicHeightInMBminus1= s->mb_height - 1; + } + pp->bMacroblockWidthMinus1 = 15; + pp->bMacroblockHeightMinus1 = 15; + pp->bBlockWidthMinus1 = 7; + pp->bBlockHeightMinus1 = 7; + pp->bBPPminus1 = 7; + if (s->picture_structure & PICT_TOP_FIELD) + pp->bPicStructure |= 0x01; + if (s->picture_structure & PICT_BOTTOM_FIELD) + pp->bPicStructure |= 0x02; + pp->bSecondField = v->interlace && v->fcm == ILACE_FIELD && v->second_field; + pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type; + pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type; + pp->bBidirectionalAveragingMode = (1 << 7) | + ((ctx->cfg->ConfigIntraResidUnsigned != 0) << 6) | + ((ctx->cfg->ConfigResidDiffAccelerator != 0) << 5) | + ((v->lumscale != 32 || v->lumshift != 0) << 4) | + ((v->profile == PROFILE_ADVANCED) << 3); + pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) | + (1 << 2) | + (0 << 1) | + (!s->quarter_sample ); + pp->bChromaFormat = v->chromaformat; + ctx->report_id++; + if (ctx->report_id >= (1 << 16)) + ctx->report_id = 1; + pp->bPicScanFixed = ctx->report_id >> 8; + pp->bPicScanMethod = ctx->report_id & 0xff; + pp->bPicReadbackRequests = 0; + pp->bRcontrol = v->rnd; + pp->bPicSpatialResid8 = (v->panscanflag << 7) | + (v->refdist_flag << 6) | + (s->loop_filter << 5) | + (v->fastuvmc << 4) | + (v->extended_mv << 3) | + (v->dquant << 1) | + (v->vstransform ); + pp->bPicOverflowBlocks = (v->quantizer_mode << 6) | + (v->multires << 5) | + (s->resync_marker << 4) | + (v->rangered << 3) | + (s->max_b_frames ); + pp->bPicExtrapolation = (!v->interlace || v->fcm == PROGRESSIVE) ? 1 : 2; + pp->bPicDeblocked = ((!pp->bPicBackwardPrediction && v->overlap) << 6) | + ((v->profile != PROFILE_ADVANCED && v->rangeredfrm) << 5) | + (s->loop_filter << 1); + pp->bPicDeblockConfined = (v->postprocflag << 7) | + (v->broadcast << 6) | + (v->interlace << 5) | + (v->tfcntrflag << 4) | + (v->finterpflag << 3) | + ((s->pict_type != AV_PICTURE_TYPE_B) << 2) | + (v->psf << 1) | + (v->extended_dmv ); + if (s->pict_type != AV_PICTURE_TYPE_I) + pp->bPic4MVallowed = v->mv_mode == MV_PMODE_MIXED_MV || + (v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->mv_mode2 == MV_PMODE_MIXED_MV); + if (v->profile == PROFILE_ADVANCED) + pp->bPicOBMC = (v->range_mapy_flag << 7) | + (v->range_mapy << 4) | + (v->range_mapuv_flag << 3) | + (v->range_mapuv ); + pp->bPicBinPB = 0; + pp->bMV_RPS = 0; + pp->bReservedBits = 0; + if (s->picture_structure == PICT_FRAME) { + pp->wBitstreamFcodes = v->lumscale; + pp->wBitstreamPCEelements = v->lumshift; + } else { + /* Syntax: (top_field_param << 8) | bottom_field_param */ + pp->wBitstreamFcodes = (v->lumscale << 8) | v->lumscale; + pp->wBitstreamPCEelements = (v->lumshift << 8) | v->lumshift; + } + pp->bBitstreamConcealmentNeed = 0; + pp->bBitstreamConcealmentMethod = 0; +} + +static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice, + unsigned position, unsigned size) +{ + const VC1Context *v = avctx->priv_data; + const MpegEncContext *s = &v->s; + + memset(slice, 0, sizeof(*slice)); + slice->wHorizontalPosition = 0; + slice->wVerticalPosition = s->mb_y; + slice->dwSliceBitsInBuffer = 8 * size; + slice->dwSliceDataLocation = position; + slice->bStartCodeBitOffset = 0; + slice->bReservedBits = 0; + slice->wMBbitOffset = get_bits_count(&s->gb); + slice->wNumberMBsInSlice = s->mb_width * s->mb_height; /* XXX We assume 1 slice */ + slice->wQuantizerScaleCode = v->pq; + slice->wBadSliceChopping = 0; +} + +static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *sc) +{ + const VC1Context *v = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + const MpegEncContext *s = &v->s; + struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private; + + DXVA_SliceInfo *slice = &ctx_pic->si; + + static const uint8_t start_code[] = { 0, 0, 1, 0x0d }; + const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ? sizeof(start_code) : 0; + const unsigned slice_size = slice->dwSliceBitsInBuffer / 8; + const unsigned padding = 128 - ((start_code_size + slice_size) & 127); + const unsigned data_size = start_code_size + slice_size + padding; + + uint8_t *dxva_data; + unsigned dxva_size; + int result; + + if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, + DXVA2_BitStreamDateBufferType, + (void **)&dxva_data, &dxva_size))) + return -1; + + result = data_size <= dxva_size ? 0 : -1; + if (!result) { + if (start_code_size > 0) { + memcpy(dxva_data, start_code, start_code_size); + if (v->second_field) + dxva_data[3] = 0x0c; + } + memcpy(dxva_data + start_code_size, + ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size); + if (padding > 0) + memset(dxva_data + start_code_size + slice_size, 0, padding); + slice->dwSliceBitsInBuffer = 8 * data_size; + } + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, + DXVA2_BitStreamDateBufferType))) + return -1; + if (result) + return result; + + memset(bs, 0, sizeof(*bs)); + bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; + bs->DataSize = data_size; + bs->NumMBsInBuffer = s->mb_width * s->mb_height; + assert((bs->DataSize & 127) == 0); + + return ff_dxva2_commit_buffer(avctx, ctx, sc, + DXVA2_SliceControlBufferType, + slice, sizeof(*slice), bs->NumMBsInBuffer); +} + +static int dxva2_vc1_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + const VC1Context *v = avctx->priv_data; + struct dxva_context *ctx = avctx->hwaccel_context; + struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; + + if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) + return -1; + assert(ctx_pic); + + fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp); + + ctx_pic->bitstream_size = 0; + ctx_pic->bitstream = NULL; + return 0; +} + +static int dxva2_vc1_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + const VC1Context *v = avctx->priv_data; + const Picture *current_picture = v->s.current_picture_ptr; + struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; + + if (ctx_pic->bitstream_size > 0) + return -1; + + if (avctx->codec_id == AV_CODEC_ID_VC1 && + size >= 4 && IS_MARKER(AV_RB32(buffer))) { + buffer += 4; + size -= 4; + } + + ctx_pic->bitstream_size = size; + ctx_pic->bitstream = buffer; + + fill_slice(avctx, &ctx_pic->si, 0, size); + return 0; +} + +static int dxva2_vc1_end_frame(AVCodecContext *avctx) +{ + VC1Context *v = avctx->priv_data; + struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private; + int ret; + + if (ctx_pic->bitstream_size <= 0) + return -1; + + ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr, + &ctx_pic->pp, sizeof(ctx_pic->pp), + NULL, 0, + commit_bitstream_and_slice_buffer); + if (!ret) + ff_mpeg_draw_horiz_band(&v->s, 0, avctx->height); + return ret; +} + +#if CONFIG_WMV3_DXVA2_HWACCEL +AVHWAccel ff_wmv3_dxva2_hwaccel = { + .name = "wmv3_dxva2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .start_frame = dxva2_vc1_start_frame, + .decode_slice = dxva2_vc1_decode_slice, + .end_frame = dxva2_vc1_end_frame, + .priv_data_size = sizeof(struct dxva2_picture_context), +}; +#endif + +AVHWAccel ff_vc1_dxva2_hwaccel = { + .name = "vc1_dxva2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_DXVA2_VLD, + .start_frame = dxva2_vc1_start_frame, + .decode_slice = dxva2_vc1_decode_slice, + .end_frame = dxva2_vc1_end_frame, + .priv_data_size = sizeof(struct dxva2_picture_context), +}; diff --git a/ffmpeg/libavcodec/eac3_data.c b/ffmpeg/libavcodec/eac3_data.c new file mode 100644 index 0000000..b159e16 --- /dev/null +++ b/ffmpeg/libavcodec/eac3_data.c @@ -0,0 +1,1134 @@ +/* + * E-AC-3 tables + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +/** + * @file + * Tables taken directly from the E-AC-3 spec. + */ + +#include "eac3_data.h" +#include "ac3.h" + +const uint8_t ff_eac3_bits_vs_hebap[20] = { + 0, 2, 3, 4, 5, 7, 8, 9, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, +}; + +/** + * Table E3.6, Gk=1 + * No gain (Gk=1) inverse quantization, remapping scale factors + * ff_eac3_gaq_remap[hebap+8] + */ +const int16_t ff_eac3_gaq_remap_1[12] = { + 4681, 2185, 1057, 520, 258, 129, 64, 32, 16, 8, 2, 0 +}; + +/** + * Table E3.6, Gk=2 & Gk=4, A + * Large mantissa inverse quantization, remapping scale factors + * ff_eac3_gaq_remap_2_4_a[hebap-8][Gk=2,4] + */ +const int16_t ff_eac3_gaq_remap_2_4_a[9][2] = { + { -10923, -4681 }, + { -14043, -6554 }, + { -15292, -7399 }, + { -15855, -7802 }, + { -16124, -7998 }, + { -16255, -8096 }, + { -16320, -8144 }, + { -16352, -8168 }, + { -16368, -8180 } +}; + +/** + * Table E3.6, Gk=2 & Gk=4, B + * Large mantissa inverse quantization, negative mantissa remapping offsets + * ff_eac3_gaq_remap_3_4_b[hebap-8][Gk=2,4] + */ +const int16_t ff_eac3_gaq_remap_2_4_b[9][2] = { + { -5461, -1170 }, + { -11703, -4915 }, + { -14199, -6606 }, + { -15327, -7412 }, + { -15864, -7805 }, + { -16126, -7999 }, + { -16255, -8096 }, + { -16320, -8144 }, + { -16352, -8168 } +}; + +static const int16_t vq_hebap1[4][6] = { +{ 7167, 4739, 1106, 4269, 10412, 4820}, +{ -5702, -3187, -14483, -1392, -2027, 849}, +{ 633, 6199, 7009, -12779, -2306, -2636}, +{ -1468, -7031, 7592, 10617, -5946, -3062}, +}; +static const int16_t vq_hebap2[8][6] = { +{ -12073, 608, -7019, 590, 4000, 869}, +{ 6692, 15689, -6178, -9239, -74, 133}, +{ 1855, -989, 20596, -2920, -4475, 225}, +{ -1194, -3901, -821, -6566, -875, -20298}, +{ -2762, -3181, -4094, -5623, -16945, 9765}, +{ 1547, 6839, 1980, 20233, -1071, -4986}, +{ 6221, -17915, -5516, 6266, 358, 1162}, +{ 3753, -1066, 4283, -3227, 15928, 10186}, +}; +static const int16_t vq_hebap3[16][6] = { +{ -10028, 20779, 10982, -4560, 798, -68}, +{ 11050, 20490, -6617, -5342, -1797, -1631}, +{ 3977, -542, 7118, -1166, 18844, 14678}, +{ -4320, -96, -7295, -492, -22050, -4277}, +{ 2692, 5856, 5530, 21862, -7212, -5325}, +{ -135, -23391, 962, 8115, -644, 382}, +{ -1563, 3400, -3299, 4693, -6892, 22398}, +{ 3535, 3030, 7296, 6214, 20476, -12099}, +{ 57, -6823, 1848, -22349, -5919, 6823}, +{ -821, -3655, -387, -6253, -1735, -22373}, +{ -6046, 1586, -18890, -14392, 9214, 705}, +{ -5716, 264, -17964, 14618, 7921, -337}, +{ -110, 108, 8, 74, -89, -50}, +{ 6612, -1517, 21687, -1658, -7949, -246}, +{ 21667, -6335, -8290, -101, -1349, -22}, +{ -22003, -6476, 7974, 648, 2054, -331}, +}; +static const int16_t vq_hebap4[32][6] = { +{ 6636, -4593, 14173, -17297, -16523, 864}, +{ 3658, 22540, 104, -1763, -84, 6}, +{ 21580, -17815, -7282, -1575, -2078, -320}, +{ -2233, 10017, -2728, 14938, -13640, -17659}, +{ -1564, -17738, -19161, 13735, 2757, 2951}, +{ 4520, 5510, 7393, 10799, 19231, -13770}, +{ 399, 2976, -1099, 5013, -1159, 22095}, +{ 3624, -2359, 4680, -2238, 22702, 3765}, +{ -4201, -8285, -6810, -12390, -18414, 15382}, +{ -5198, -6869, -10047, -8364, -16022, -20562}, +{ -142, -22671, -368, 4391, -464, -13}, +{ 814, -1118, -1089, -22019, 74, 1553}, +{ -1618, 19222, -17642, -13490, 842, -2309}, +{ 4689, 16490, 20813, -15387, -4164, -3968}, +{ -3308, 11214, -13542, 13599, -19473, 13770}, +{ 1817, 854, 21225, -966, -1643, -268}, +{ -2587, -107, -20154, 376, 1174, -304}, +{ -2919, 453, -5390, 750, -22034, -978}, +{ -19012, 16839, 10000, -3580, 2211, 1459}, +{ 1363, -2658, -33, -4067, 1165, -21985}, +{ -8592, -2760, -17520, -15985, 14897, 1323}, +{ 652, -9331, 3253, -14622, 12181, 19692}, +{ -6361, 5773, -15395, 17291, 16590, -2922}, +{ -661, -601, 1609, 22610, 992, -1045}, +{ 4961, 9107, 11225, 7829, 16320, 18627}, +{ -21872, -1433, 138, 1470, -1891, -196}, +{ -19499, -18203, 11056, -516, 2543, -2249}, +{ -1196, -17574, 20150, 11462, -401, 2619}, +{ 4638, -8154, 11891, -15759, 17615, -14955}, +{ -83, 278, 323, 55, -154, 232}, +{ 7788, 1462, 18395, 15296, -15763, -1131}, +}; +static const int16_t vq_hebap5[128][6] = { +{ -3394, -19730, 2963, 9590, 4660, 19673}, +{ -15665, -6405, 17671, 3860, -8232, -19429}, +{ 4467, 412, -17873, -8037, 691, -17307}, +{ 3580, 2363, 6886, 3763, 6379, -20522}, +{ -17230, -14133, -1396, -23939, 8373, -12537}, +{ -8073, -21469, -15638, 3214, 8105, -5965}, +{ 4343, 5169, 2683, -16822, -5146, -16558}, +{ 6348, -10668, 12995, -25500, -22090, 4091}, +{ -2880, -8366, -5968, -17158, -2638, 23132}, +{ -5095, -14281, -22371, 21741, 3689, 2961}, +{ -2443, -17739, 25155, 2707, 1594, 7}, +{ -18379, 9010, 4270, 731, -426, -640}, +{ -23695, 24732, 5642, 612, -308, -964}, +{ -767, 1268, 225, 1635, 173, 916}, +{ 5455, 6493, 4902, 10560, 23041, -17140}, +{ 17219, -21054, -18716, 4936, -3420, 3357}, +{ -1390, 15488, -21946, -14611, 1339, 542}, +{ -6866, -2254, -12070, -3075, -19981, -20622}, +{ -1803, 11775, 1343, 8917, 693, 24497}, +{ -21610, 9462, 4681, 9254, -7815, 15904}, +{ -5559, -3018, -9169, -1347, -22547, 12868}, +{ -366, 5076, -1727, 20427, -283, -2923}, +{ -1886, -6313, -939, -2081, -1399, 3513}, +{ -3161, -537, -5075, 11268, 19396, 989}, +{ 2345, 4153, 5769, -4273, 233, -399}, +{ -21894, -1138, -16474, 5902, 5488, -3211}, +{ 10007, -12530, 18829, 20932, -1158, 1790}, +{ -1165, 5014, -1199, 6415, -8418, -21038}, +{ 1892, -3534, 3815, -5846, 16427, 20288}, +{ -2664, -11627, -4147, -18311, -22710, 14848}, +{ 17256, 10419, 7764, 12040, 18956, 2525}, +{ -21419, -18685, -10897, 4368, -7051, 4539}, +{ -1574, 2050, 5760, 24756, 15983, 17678}, +{ -538, -22867, 11067, 10301, 385, 528}, +{ -8465, -3025, -16357, -23237, 16491, 3654}, +{ 5840, 575, 11890, 1947, 25157, 6653}, +{ 6625, -3516, -1964, 3850, -390, -116}, +{ 18005, 20900, 14323, -7621, -10922, 11802}, +{ -4857, -2932, -13334, -7815, 21622, 2267}, +{ -579, -9431, -748, -21321, 12367, 8265}, +{ -8317, 1375, -17847, 2921, 9062, 22046}, +{ 18398, 8635, -1503, -2418, -18295, -14734}, +{ -2987, 15129, -3331, 22300, 13878, -13639}, +{ 5874, -19026, 15587, 11350, -20738, 1971}, +{ 1581, -6955, -21440, 2455, 65, 414}, +{ 515, -4468, -665, -4672, 125, -19222}, +{ 21495, -20301, -1872, -1926, -211, -1022}, +{ 5189, -12250, -1775, -23550, -4546, 5813}, +{ 321, -6331, 14646, 6975, -1773, 867}, +{ -13814, 3180, 7927, 444, 19552, 3146}, +{ -6660, 12252, -1972, 17408, -24280, -12956}, +{ -745, 14356, -1107, 23742, -9631, -18344}, +{ 18284, -7909, -7531, 19118, 7721, -12659}, +{ 1926, 15101, -12848, 2153, 21631, 1864}, +{ -2130, 23416, 17056, -15597, -1544, 87}, +{ 8314, -11824, 14581, -20591, 7891, -2099}, +{ 19600, 22814, -17304, -2040, 285, -3863}, +{ -8214, -18322, 10724, -13744, -13469, -1666}, +{ 14351, 4880, -20034, 964, -4221, -180}, +{ -24598, -16635, 19724, 5925, 4777, 4414}, +{ -2495, 23493, -16141, 2918, -1038, -2010}, +{ 18974, -2540, 13343, 1405, -6194, -1136}, +{ 2489, 13670, 22638, -7311, -129, -2792}, +{ -13962, 16775, 23012, 728, 3397, 162}, +{ 3038, 993, 8774, -21969, -6609, 910}, +{ -12444, -22386, -2626, -5295, 19520, 9872}, +{ -1911, -18274, -18506, -14962, 4760, 7119}, +{ 8298, -2978, 25886, 7660, -7897, 1020}, +{ 6132, 15127, 18757, -24370, -6529, -6627}, +{ 7924, 12125, -9459, -23962, 5502, 937}, +{ -17056, -5373, 2522, 327, 1129, -390}, +{ 15774, 19955, -10380, 11172, -3107, 14853}, +{ -11904, -8091, -17928, -22287, -17237, -6803}, +{ -12862, -2172, -6509, 5927, 12458, -22355}, +{ -497, 322, 1038, -6643, -5404, 20311}, +{ 1083, -22984, -8494, 12130, -762, 2623}, +{ 5067, 19712, -1901, -30, -325, 85}, +{ 987, -5830, 4212, -9030, 9121, -25038}, +{ -7868, 7284, -12292, 12914, -21592, 20941}, +{ -1630, -7694, -2187, -8525, -5604, -25196}, +{ -6668, 388, -22535, 1526, 9082, 193}, +{ -7867, -22308, 5163, 362, 944, -259}, +{ 3824, -11850, 7591, -23176, 25342, 23771}, +{ -10504, 4123, -21111, 21173, 22439, -838}, +{ -4723, 21795, 6184, -122, 1642, -717}, +{ 24504, 19887, -2043, 986, 7, -55}, +{ -27313, -135, 2437, 259, 89, 307}, +{ 24446, -3873, -5391, -820, -2387, 361}, +{ 5529, 5784, 18682, 242, -21896, -4003}, +{ 22304, 4483, 722, -12242, 7570, 15448}, +{ 8673, 3009, 20437, 21108, -21100, -3080}, +{ -1132, 2705, -1825, 5420, -785, 18532}, +{ 16932, -13517, -16509, -14858, -20327, -14221}, +{ 2219, 1380, 21474, -1128, 327, 83}, +{ -2177, 21517, -3856, -14180, -204, -2191}, +{ 953, -9426, 15874, -10710, -3231, 21030}, +{ -421, -1377, 640, -8239, -20976, 2174}, +{ 4309, 18514, -9100, -18319, -15518, 3704}, +{ -5943, 449, -8387, 1075, -22210, -4992}, +{ 2953, 12788, 18285, 1430, 14937, 21731}, +{ -2913, 401, -4739, -20105, 1699, -1147}, +{ 3449, 5241, 8853, 22134, -7547, 1451}, +{ -2154, 8584, 18120, -15614, 19319, -5991}, +{ 3501, 2841, 5897, 6397, 8630, 23018}, +{ 2467, 2956, 379, 5703, -22047, -2189}, +{ -16963, -594, 18822, -5295, 1640, 774}, +{ 2896, -1424, 3586, -2292, 19910, -1822}, +{ -18575, 21219, -14001, -12573, 16466, 635}, +{ -1998, -19314, -16527, 12208, -16576, -7854}, +{ -9674, 1012, -21645, 2883, -12712, 2321}, +{ -1005, 471, -3629, 8045, -11087, 25533}, +{ 4141, -21472, -2673, 756, -663, -523}, +{ 6490, 8531, 19289, 18949, 6092, -9347}, +{ 16965, 24599, 14024, 10072, -536, -10438}, +{ -8147, 2145, -23028, -17073, 5451, -4401}, +{ -14873, 20520, -18303, -9717, -11885, -17831}, +{ -2290, -14120, 2070, 22467, 1671, 725}, +{ -8538, 14629, 3521, -20577, 6673, 8200}, +{ 20248, 4410, -1366, -585, 1229, -2449}, +{ 7467, -7148, 13667, -8246, 22392, -17320}, +{ -1932, 3875, -9064, -3812, 958, 265}, +{ -4399, 2959, -15911, 19598, 4954, -1105}, +{ 18009, -9923, -18137, -3862, 11178, 5821}, +{ -14596, -1227, 9660, 21619, 11228, -11721}, +{ -721, -1700, 109, -2142, 61, -6772}, +{ -24619, -22520, 5608, -1957, -1761, -1012}, +{ -23728, -4451, -2688, -14679, -4266, 9919}, +{ 8495, -894, 20438, -13820, -17267, 139}, +}; +static const int16_t vq_hebap6[256][6] = { +{ 10154, 7365, 16861, 18681, -22893, -3636}, +{ -2619, -3788, -5529, -5192, -9009, -20298}, +{ -5583, -22800, 21297, 7012, 745, 720}, +{ 428, -1459, 109, -3082, 361, -8403}, +{ 8161, 22401, 241, 1755, -874, -2824}, +{ 1140, 12643, 2306, 22263, -25146, -17557}, +{ -2609, 3379, 10337, -19730, -15468, -23944}, +{ -4040, -12796, -25772, 13096, 3905, 1315}, +{ 4624, -23799, 13608, 25317, -1175, 2173}, +{ -97, 13747, -5122, 23255, 4214, -22145}, +{ 6878, -322, 18264, -854, -11916, -733}, +{ 17280, -12669, -9693, 23563, -16240, -1309}, +{ 5802, -4968, 19526, -21194, -24622, -183}, +{ 5851, -16137, 15229, -9496, -1538, 377}, +{ 14096, 25057, 13419, 8290, 23320, 16818}, +{ -7261, 118, -15867, 19097, 9781, -277}, +{ -4288, 21589, -13288, -16259, 16633, -4862}, +{ 4909, -19217, 23411, 14705, -722, 125}, +{ 19462, -4732, -1928, -11527, 20770, 5425}, +{ -27562, -2881, -4331, 384, -2103, 1367}, +{ -266, -9175, 5441, 26333, -1924, 4221}, +{ -2970, -20170, -21816, 5450, -7426, 5344}, +{ -221, -6696, 603, -9140, 1308, -27506}, +{ 9621, -8380, -1967, 9403, -1651, 22817}, +{ 7566, -5250, -4165, 1385, -990, 560}, +{ -1262, 24738, -19057, 10741, 7585, -7098}, +{ 451, 20130, -9949, -6015, -2188, -1458}, +{ 22249, 9380, 9096, 10959, -2365, -3724}, +{ 18668, -650, -1234, 11092, 7678, 5969}, +{ 19207, -1485, -1076, -731, -684, 43}, +{ -4973, 13430, 20139, 60, 476, -935}, +{ -20029, 8710, 2499, 1016, -1158, 335}, +{ -26413, 18598, -2201, -669, 3409, 793}, +{ -4726, 8875, -24607, -9646, 3643, -283}, +{ 13303, -21404, -3691, -1184, -1970, 1612}, +{ 173, 60, 919, 1229, 6942, -665}, +{ 16377, 16991, 5341, -14015, -2304, -20390}, +{ 25334, -10609, 11947, -7653, -6363, 14058}, +{ 23929, -13259, -7226, -937, 234, -187}, +{ 6311, -1877, 12506, -1879, 18751, -23341}, +{ 621, 6445, 3354, -24274, 8406, 5315}, +{ -3297, -5034, -4704, -5080, -25730, 5347}, +{ -1275, -13295, -965, -23318, 1214, 26259}, +{ -6252, 10035, -20105, 15301, -16073, 5136}, +{ 9562, -3911, -19510, 4745, 22270, -4171}, +{ 7978, -19600, 14024, -5745, -20855, 8939}, +{ 7, -4039, 991, -6065, 52, -19423}, +{ 3485, 2969, 7732, 7786, 25312, 6206}, +{ -959, -12812, -1840, -22743, 7324, 10830}, +{ -4686, 1678, -10172, -5205, 4294, -1271}, +{ 3889, 1302, 7450, 638, 20374, -3133}, +{ -12496, -9123, 18463, -12343, -7238, 18552}, +{ -6185, 8649, -6903, -895, 17109, 16604}, +{ -9896, 28579, 2845, 1640, 2925, -298}, +{ 14968, -25988, 14878, -24012, 1815, -6474}, +{ 26107, 5166, 21225, 15873, 21617, 14825}, +{ -21684, 16438, 20504, -14346, -7114, -4162}, +{ 28647, 90, -1572, 789, -902, -75}, +{ -1479, 2471, -4061, 3612, -2240, 10914}, +{ 8616, 17491, 17255, -17456, 17022, -16357}, +{ -20722, -18597, 25274, 17720, -3573, 1695}, +{ -997, 6129, -6303, 11250, -11359, -19739}, +{ -74, -4001, -1584, 13384, 162, -144}, +{ -529, 21068, 7923, -11396, 422, -26}, +{ 7102, -13531, -20055, 2629, -178, -429}, +{ 9201, 1368, -22238, 2623, -20499, 24889}, +{ -432, 6675, -266, 8723, 80, 28024}, +{ 19493, -3108, -9261, 1910, -21777, 5345}, +{ 14079, -11489, 12604, 6079, 19877, 1315}, +{ 10947, 9837, -18612, 15742, 4792, 605}, +{ -1777, 3758, -4087, 21696, 6024, -576}, +{ 3567, -3578, 16379, 2680, -1752, 716}, +{ -5049, -1399, -4550, -652, -17721, -3366}, +{ -3635, -4372, -6522, -22152, 7382, 1458}, +{ 12242, 19190, 5646, -7815, -20289, 21344}, +{ -7508, 19952, 23542, -9753, 5669, -1990}, +{ -2275, 15438, 10907, -17879, 6497, 13582}, +{ -15894, -15646, -4716, 6019, 24250, -6179}, +{ -2049, -6856, -1208, 918, 17735, -69}, +{ -3721, 9099, -16065, -23621, 5981, -2344}, +{ 7862, -8918, 24033, 25508, -11033, -741}, +{ -12588, 19468, 14649, 15451, -21226, 1171}, +{ 2102, 1147, 2789, 4096, 2179, 8750}, +{ -18214, -17758, -10366, -5203, -1066, -3541}, +{ -2819, -19958, -11921, 6032, 8315, 10374}, +{ -9078, -2100, 19431, -17, 732, -689}, +{ -14512, -19224, -7095, 18727, 1870, 22906}, +{ 3912, 659, 25597, -4006, 9619, 877}, +{ 2616, 22695, -5770, 17920, 3812, 20220}, +{ 2561, 26847, -5245, -10908, 2256, -517}, +{ -4974, 198, -21983, -3608, 22174, -18924}, +{ 21308, -1211, 19144, 16691, -1588, 11390}, +{ -1790, 3959, -3488, 7003, -7107, 20877}, +{ -6108, -17955, -18722, 24763, 16508, 3211}, +{ 20462, -24987, -20361, 4484, -5111, -478}, +{ -6378, -1998, -10229, -561, -22039, -22339}, +{ 3047, -18850, 7586, 14743, -19862, 6351}, +{ -5047, 1405, -9672, 1055, -21881, 11170}, +{ 3481, -9699, 6526, -16655, 22813, 21907}, +{ -18570, 17501, 14664, 1291, 5026, 19676}, +{ 16134, -19810, -16956, -17939, -16933, 5800}, +{ -8224, 4908, 8935, 2272, -1140, -23217}, +{ 1572, 2753, -1598, 2143, -3346, -21926}, +{ -9832, -1060, -27818, 1214, 7289, 150}, +{ 98, 1538, 535, 17429, -23198, -901}, +{ 21340, -20146, 3297, -1744, -8207, -21462}, +{ -4166, -4633, -17902, 5478, 1285, 136}, +{ 18713, 21003, 24818, 11421, 1282, -4618}, +{ -3535, 7636, -265, 2141, -829, -2035}, +{ -3184, 19713, 2775, -2, 1090, 104}, +{ -6771, -20185, 2938, -2125, -36, 1268}, +{ 9560, 9430, 9586, 22100, 13827, 6296}, +{ -535, -20018, 4276, -1868, -448, -17183}, +{ -24352, 14244, -13647, -21040, 2271, 11555}, +{ -2646, 15437, -4589, 18638, -4299, -622}, +{ -20064, 4169, 18115, -1404, 13722, -1825}, +{ -16359, 9080, 744, 22021, 125, 10794}, +{ 9644, -14607, -18479, -14714, 11174, -20754}, +{ -326, -23762, 6144, 7909, 602, 1540}, +{ -6650, 6634, -12683, 21396, 20785, -6839}, +{ 4252, -21043, 5628, 18687, 23860, 8328}, +{ 17986, 5704, -5245, -18093, -555, 3219}, +{ 6091, 14232, -5117, -17456, -19452, -11649}, +{ -21586, 11302, 15434, 25590, 6777, -26683}, +{ 21355, -8244, 5877, -3540, 6079, -2567}, +{ 2603, -2455, 5421, -12286, -19100, 5574}, +{ -1721, -26393, -23664, 22904, -349, 3787}, +{ 2189, -1203, 5340, 3249, -22617, 104}, +{ -1664, -11020, -2857, -20723, -24049, 19900}, +{ 22873, -7345, -18481, -14616, -8400, -12965}, +{ 3777, 3958, 8239, 20494, -6991, -1201}, +{ -160, -1613, -793, -8681, 573, 776}, +{ 4297, -3786, 20373, 6082, -5321, -18400}, +{ 18745, 2463, 12546, -7749, -7734, -2183}, +{ 11074, -4720, 22119, 1825, -24351, 4080}, +{ 1503, -19178, -1569, 13, -313, 375}, +{ 318, -575, 2544, 178, 102, 40}, +{ -15996, -26897, 5008, 3320, 686, 1159}, +{ 25755, 26886, 574, -5930, -3916, 1407}, +{ -9148, -7665, -2875, -8384, -18663, 26400}, +{ -7445, -18040, -18396, 8802, -2252, -21886}, +{ 7851, 11773, 27485, -12847, -1410, 19590}, +{ 2240, 5947, 11247, 15980, -6499, 24280}, +{ 21673, -18515, 9771, 6550, -2730, 334}, +{ -4149, 1576, -11010, 89, -24429, -5710}, +{ 7720, 1478, 21412, -25025, -8385, 9}, +{ -2448, 10218, -12756, -16079, 1161, -21284}, +{ -8757, -14429, -22918, -14812, 2629, 13844}, +{ -7252, 2843, -9639, 2882, -14625, 24497}, +{ -674, -6530, 414, -23333, -21343, 454}, +{ 2104, -6312, 10887, 18087, -1199, 175}, +{ -493, -562, -2739, 118, -1074, 93}, +{ -10011, -4075, -28071, 22180, 15077, -636}, +{ -4637, -16408, -9003, -20418, -11608, -20932}, +{ 4815, 15892, 24238, -13634, -3074, -1059}, +{ -6724, 4610, -18772, -15283, -16685, 23988}, +{ 15349, -674, -3682, 21679, 4475, -12088}, +{ 4756, 2593, 5354, 6001, 15063, 26490}, +{ -23815, -17251, 6944, 378, 694, 670}, +{ 23392, -8839, -14713, 7544, -876, 11088}, +{ 3640, 3336, 22593, -3495, -2328, -113}, +{ 284, 6914, 3097, 10171, 6638, -18621}, +{ 2472, 5976, 11054, -11936, -603, -663}, +{ 16175, 16441, 13164, -4043, 4667, 7431}, +{ 19338, 15534, -6533, 1681, -4857, 17048}, +{ 17027, 532, -19064, -1441, -5130, 1085}, +{ -12617, -17609, 2062, -25332, 19009, -16121}, +{ 10056, -21000, -13634, -2949, 15367, 19934}, +{ -648, -1605, 10046, -1592, 13296, 19808}, +{ -1054, 10744, 538, 24938, 9630, -9052}, +{ -10099, 3042, -25076, -24052, 13971, 100}, +{ 6547, 6907, 7031, 10348, 23775, -17886}, +{ -22793, -1984, -1393, -3330, 9267, 14317}, +{ -14346, -3967, 3042, 16254, -17303, 9646}, +{ -21393, 23628, 16773, 716, 2663, 114}, +{ -19016, -3038, 1574, -245, 1463, -793}, +{ 22410, 23441, -14637, -530, 17310, 13617}, +{ -11582, 7935, -13954, 23465, -24628, 26550}, +{ -1045, 3679, -2218, 10572, 20999, -3702}, +{ -15513, 197, 16718, -24603, 4945, 5}, +{ 10781, 4335, 26790, -9059, -16152, -2840}, +{ 16075, -24100, -3933, -6833, 12645, -7029}, +{ 2096, -25572, -8370, 6814, 11, 1178}, +{ -11848, -583, -8889, -20543, -10471, -380}, +{ -2487, 24777, -21639, -19341, 1660, -732}, +{ 2313, 13679, 4085, 24549, 24691, -21179}, +{ -2366, -504, -4130, -10570, 23668, 1961}, +{ 20379, 17809, -9506, 3733, -18954, -6292}, +{ -3856, 16802, -929, -20310, -17739, 6797}, +{ 12431, 6078, -11272, -14450, 6913, 23476}, +{ 7636, -1655, 23017, 10719, -8292, 838}, +{ -8559, -1235, -18096, 3897, 16093, 1490}, +{ -3586, 8276, 15165, -3791, -21149, 1741}, +{ -4497, 21739, 2366, -278, -4792, 15549}, +{ -23122, -13708, 7668, 16232, 24120, 15025}, +{ -20043, 12821, -20160, 16691, -11655, -16081}, +{ -12601, 20239, 3496, -2549, -6745, -11850}, +{ 4441, 7812, 20783, 17080, 11523, -9643}, +{ 24766, 8494, -23298, -3262, 11101, -7120}, +{ -10107, -7623, -22152, -18303, 26645, 9550}, +{ -25549, 477, 7874, -1538, 1123, -168}, +{ 470, 9834, -347, 23945, -10381, -9467}, +{ -4096, -9702, -6856, -21544, 20845, 7174}, +{ 5370, 9748, -23765, -1190, 512, -1538}, +{ -1006, -10046, -12649, 19234, -1790, -890}, +{ 15108, 23620, -15646, -2522, -1203, -1325}, +{ -7406, -2605, 1095, -247, -473, 177}, +{ 8089, 4, 12424, -22284, 10405, -7728}, +{ 22196, 10775, -5043, 690, 534, -212}, +{ -3153, -1418, -16835, 18426, 15821, 22956}, +{ 5681, -2229, 3196, -3414, -21817, -14807}, +{ 19, 787, 1032, 170, -8295, -645}, +{ -882, -2319, -27105, 432, -4392, 1499}, +{ -1354, -11819, -76, -20380, -10293, 11328}, +{ 211, -4753, -4675, -6933, -13538, 14479}, +{ 6043, 5260, -459, -462, 143, -65}, +{ -2572, 7256, -3317, 9212, -23184, -9990}, +{ -24882, -9532, 18874, 6101, 2429, -14482}, +{ 8314, 2277, 14192, 3512, 25881, 22000}, +{ 208, 20218, -281, -24778, -63, -1183}, +{ 1095, -6034, 2706, -21935, -2655, 563}, +{ 23, -5930, 243, -8989, 5345, 20558}, +{ -15466, 12699, 4160, 11087, 20621, -10416}, +{ 20995, -85, -8468, 194, 1003, -9515}, +{ -19637, -3335, -14081, 3574, -23381, -667}, +{ -2076, 3489, -3192, -19367, 539, -1530}, +{ 7352, -15213, 22596, 19369, 1043, 16627}, +{ -1872, -413, 1235, -5276, -3550, 21903}, +{ 7931, -2008, 16968, -6799, 29393, -2475}, +{ -13589, 8389, -23636, -22091, -14178, -14297}, +{ -11575, -20090, 16056, -1848, 15721, 4500}, +{ 3849, -16581, 20161, -21155, 7778, 11864}, +{ -6547, -1273, -18837, -11218, 11636, 1044}, +{ 2528, -6691, -17917, -11362, -4894, -1008}, +{ 1241, 4260, 2319, 6111, 3485, 20209}, +{ 3014, -3048, 5316, -4539, 20831, 8702}, +{ -1790, -14683, 278, 13956, -10065, -10547}, +{ -22732, -7957, -1154, 13821, -1484, -1247}, +{ -7317, -615, 13094, 18927, 9897, 1452}, +{ 2552, -2338, 3424, -4630, 11124, -19584}, +{ -11125, -20553, -10855, -10783, -20767, 6833}, +{ 984, -15095, 5775, 25125, 5377, -19799}, +{ 517, 13272, -7458, -1711, 20612, -6013}, +{ -21417, 13251, -20795, 13449, 17281, 13104}, +{ -15811, -16248, 23093, -4037, -8195, 871}, +{ 582, 12571, -21129, -14766, -9187, 5685}, +{ 4318, -1776, 11425, -17763, -9921, 577}, +{ 6013, 16830, 17655, -25766, -4400, -3550}, +{ -13744, -16541, 3636, -3330, -21091, -15886}, +{ 6565, -11147, 8649, -13114, 23345, -13565}, +{ -2542, -9046, -7558, 29240, 3701, -383}, +{ -10612, 24995, 1893, -8210, 20920, -16210}, +{ 5276, 16726, 10659, 19940, -4799, -19324}, +{ -532, -9300, 27856, 4965, -241, 536}, +{ -765, -20706, -3412, 18870, 2765, 1420}, +{ -3059, 2708, -19022, -331, 3537, 116}, +}; +static const int16_t vq_hebap7[512][6] = { +{ -21173, 21893, 10390, 13646, 10718, -9177}, +{ -22519, -8193, 18328, -6629, 25518, -10848}, +{ 6800, -13758, -13278, 22418, 14667, -20938}, +{ 2347, 10516, 1125, -3455, 5569, 27136}, +{ -6617, 11851, -24524, 22937, 20362, -6019}, +{ -21768, 10681, -19615, -15021, -8478, -2081}, +{ -2745, 8684, -4895, 27739, 7554, -11961}, +{ -1020, 2460, -954, 4754, -627, -16368}, +{ -19702, 23097, 75, -13684, -2644, 2108}, +{ 4049, -2872, 5851, -4459, 22150, 12560}, +{ -21304, -17129, -730, 7419, -11658, -10523}, +{ 11332, 1792, 26666, 23518, -19561, -491}, +{ -17827, -16777, -13606, -14389, -22029, -2464}, +{ 1091, -5967, -7975, -16977, -20432, -21931}, +{ 18388, -1103, 1933, 13342, -17463, 18114}, +{ 22646, 17345, -9966, 17919, 18274, 698}, +{ 1484, 20297, -5754, -26515, 4941, -22263}, +{ -2603, 4587, -5842, 18464, 8767, -2568}, +{ -2797, -1602, 21713, 3099, -25683, 3224}, +{ -19027, 4693, -5007, 6060, 1972, -15095}, +{ -2189, 9516, -530, 20669, -4662, -8301}, +{ -22325, -8887, 2529, -11352, 5476, 998}, +{ 22100, -5052, 1651, -2657, 4615, 2319}, +{ 20855, -3078, -3330, 4105, 13470, 3069}, +{ 85, 17289, 10264, -14752, 214, 90}, +{ -26365, -18849, -19352, 19244, -10218, 9909}, +{ -9739, 20497, -6579, -6983, 2891, -738}, +{ 20575, -15860, -22913, 6870, 76, 327}, +{ 8744, -12877, -22945, -2372, -19424, -9771}, +{ -12886, 16183, 21084, 3821, 749, -13792}, +{ -15995, 18399, 2391, -17661, 19484, -6018}, +{ 1423, 11734, 4051, 19290, 6857, -19681}, +{ -5200, 9766, 18246, 2463, 18764, -4852}, +{ -597, 19498, 1323, -9096, -308, -1104}, +{ -3099, -25731, -15665, 25332, 4634, 2635}, +{ 19623, -2384, -7913, 11796, -9333, -14084}, +{ 2642, 26453, -21091, -10354, -1693, -1711}, +{ 22031, 21625, 11580, -22915, -4141, 129}, +{ -6122, 3542, 915, -261, -17, -383}, +{ 1696, 6704, -1425, 20838, 857, -4416}, +{ 1423, -15280, -8550, -9667, 5210, 5687}, +{ -4520, -613, -11683, 5618, 4230, 619}, +{ 937, -4963, -14102, -17104, -6906, -5952}, +{ -15068, -481, -7237, -14894, 18876, 21673}, +{ -25658, 2910, 1143, -327, -458, -995}, +{ -9656, -819, -24900, 2804, 20225, 1083}, +{ -1111, -3682, -1788, -19492, 966, 821}, +{ 7293, -21759, 10790, -7059, -23293, -1723}, +{ -282, -11093, 170, -20950, -28926, 12615}, +{ 17938, 3713, -1563, 885, 5, 564}, +{ 6116, 22696, 2242, -6951, 9975, -6132}, +{ 4338, 26808, -3705, 1976, -1079, -2570}, +{ -661, -7901, -2668, -15194, 17722, 4375}, +{ -4174, -11053, 717, -22506, 1562, 12252}, +{ -6405, 18334, 6103, 6983, 5956, 18195}, +{ 9851, 5370, 23604, -6861, -6569, -62}, +{ 21964, 13359, -683, 3785, 2168, 209}, +{ -3569, -1127, -19724, -1544, 1308, -803}, +{ -3083, 16049, -13791, -3077, 4294, 23713}, +{ -9999, 9943, -15872, 12934, -23631, 21699}, +{ 9722, 22837, 12192, 15091, 5533, 4837}, +{ 2243, 2099, 1243, 4089, 4748, 12956}, +{ 4007, -2468, 3353, -3092, 8843, 17024}, +{ 4330, 6127, 5549, 9249, 11226, 28592}, +{ -9586, -8825, 236, 1009, 455, -964}, +{ 6829, 19290, -1018, 200, 1821, 578}, +{ 5196, 957, 10372, 3330, -12800, -127}, +{ -3022, -8193, -14557, 22061, 5920, 1053}, +{ 10982, 25942, -24546, -23278, -11905, -6789}, +{ 22667, -11010, 5736, 2567, 23705, -10253}, +{ -3343, -4233, -5458, 20667, -10843, -3605}, +{ -4131, -3612, 4575, -829, -350, -847}, +{ -3303, 3451, -7398, -11604, 3023, 455}, +{ 3200, -9547, 3202, -22893, 11184, -26466}, +{ -14093, -4117, 15382, 14295, -10915, -20377}, +{ 3807, -11016, 22052, 14370, -15328, -7733}, +{ -6291, -17719, -1560, 12048, -19805, -443}, +{ -6147, -4234, -160, 8363, 22638, 11911}, +{ 19197, 1175, 7422, -9875, -4136, 4704}, +{ -72, -7652, -112, -11955, -3230, 27175}, +{ 3274, 5963, 7501, -17019, 866, -25452}, +{ 737, 1861, 1833, 2022, 2384, 4755}, +{ -5217, 7512, 3323, 2715, 3065, -1606}, +{ 4247, 565, 5629, 2497, 18019, -4920}, +{ -2833, -17920, -8062, 15738, -1018, 2136}, +{ 3050, -19483, 16930, 29835, -10222, 15153}, +{ -11346, 118, -25796, -13761, 15320, -468}, +{ -4824, 4960, -4263, 1575, -10593, 19561}, +{ -8203, -1409, -763, -1139, -607, 1408}, +{ -2203, -11415, 2021, -6388, -2600, 711}, +{ -413, -2511, -216, -3519, -28267, 1719}, +{ -14446, 17050, 13917, 13499, -25762, -16121}, +{ 19228, 7341, -12301, 682, -3791, -199}, +{ -4193, 20746, -15651, 11349, 5860, -824}, +{ -21490, -3546, -3, -1705, -3959, 9213}, +{ 15445, -1876, 2012, -19627, 16228, -4845}, +{ -2867, -3733, -7354, -175, -20119, 11174}, +{ -3571, -24587, 19700, 6654, 979, -654}, +{ 21820, -7430, -6639, -10767, -8362, 15543}, +{ 14827, 17977, -7204, -3409, 1906, -17288}, +{ 3525, -3947, -1415, -2798, 17648, 2082}, +{ -6580, -15255, -17913, 1337, 15338, 21158}, +{ 6210, 9698, 15155, -24666, -22507, -3999}, +{ -1740, -593, 1095, -7779, 25058, 5601}, +{ 21415, -432, -1658, -6898, -1438, -14454}, +{ -6943, 700, -12139, -745, -24187, 22466}, +{ 6287, 3283, 11006, 3844, 19184, 14781}, +{ -22502, 15274, 5443, -2808, -970, -3343}, +{ 3257, -3708, 4744, -8301, 22814, -10208}, +{ 24346, -20970, 19846, 987, -11958, -6277}, +{ 3906, -19701, 13060, -1609, 18641, 7466}, +{ -26409, -22549, 16305, 2014, 10975, 18032}, +{ -7039, 4655, -14818, 18739, 15789, 1296}, +{ 9310, -1681, 14667, -3326, 26535, -11853}, +{ 5728, 5917, 13400, 10020, -2236, -24704}, +{ 1741, -6727, 12695, -22009, 4080, 5450}, +{ -2621, 9393, 21143, -25938, -3162, -2529}, +{ 20672, 18894, -13939, 6990, -8260, 15811}, +{ -23818, 11183, -13639, 11868, 16045, 2630}, +{ 18361, -10220, 829, 856, -1010, 157}, +{ 14400, -4678, 5153, -13290, -27434, -11028}, +{ 21613, 11256, 17453, 7604, 13130, -484}, +{ 7, 1236, 573, 4214, 5576, -3081}, +{ 916, -9092, 1285, -8958, 1185, -28699}, +{ 21587, 23695, 19116, -2885, -14282, -8438}, +{ 23414, -6161, 12978, 3061, -9351, 2236}, +{ -3070, -7344, -20140, 5788, 582, -551}, +{ -3993, 315, -7773, 8224, -28082, -12465}, +{ 13766, -15357, 19205, -20624, 13043, -19247}, +{ 3777, -177, 8029, -1001, 17812, 5162}, +{ -7308, -4327, -18096, -620, -1350, 14932}, +{ 14756, -1221, -12819, -14922, -547, 27125}, +{ 2234, 1708, 2764, 5416, 7986, -25163}, +{ 2873, 3636, 3992, 5344, 10142, 21259}, +{ 1158, 5379, 508, -10514, 290, -1615}, +{ 1114, 24789, 16575, -25168, -298, -2832}, +{ -1107, -6144, -1918, -7791, -2971, -23276}, +{ 4016, 10793, 17317, -4342, -20982, -3383}, +{ -4494, -207, -9951, -3575, 7947, 1154}, +{ -7576, 8117, -14047, 16982, -26457, -27540}, +{ -15164, 16096, -16844, -8886, -23720, 15906}, +{ 24922, 5680, -1874, 420, 132, 117}, +{ -506, -19310, -198, 412, -311, 752}, +{ -1906, 3981, -7688, 16566, -19291, -14722}, +{ -399, -729, -3807, -4196, -12395, 7639}, +{ 3368, 2330, 9092, 23686, -10290, -1705}, +{ -3148, 2596, -7986, 14602, -4807, 16627}, +{ 8057, 1481, 49, 17205, 24869, 7474}, +{ -19304, -513, 11905, 2346, 5588, 3365}, +{ -5063, -21812, 11370, 10896, 4881, 261}, +{ 4794, 20577, 5109, -6025, -8049, -1521}, +{ 8125, -14756, 20639, -14918, 23941, -3650}, +{ 12451, 1381, 3613, 8687, -24002, 4848}, +{ 6726, 10643, 10086, 25217, -25159, -1065}, +{ 6561, 13977, 2911, 21737, 16465, -26050}, +{ -1776, 2575, -19606, -16800, 3032, 6679}, +{ 15012, -17910, -8438, -21554, -27111, 11808}, +{ 3448, -924, -15913, -1135, 5126, -20613}, +{ 7720, 2226, 17463, 5434, 28942, 17552}, +{ 1246, 15614, -11743, 24618, -17539, 3272}, +{ 3215, 17950, 2783, -722, -22672, 5979}, +{ -5678, -3184, -26087, 26034, 6583, 3302}, +{ 20310, -3555, -2715, -444, -1487, 1526}, +{ -20640, -21970, -12207, -25793, 8863, -1036}, +{ 17888, 570, -16102, 8329, -2553, 15275}, +{ -2677, 9950, -1879, 16477, -12762, -29007}, +{ -120, -2221, 219, 97, 365, 35}, +{ 1270, -718, 1480, -2689, 1930, -7527}, +{ 1896, 8750, 1906, 18235, -12692, -6174}, +{ -3733, 13713, -9882, -15960, -1376, -7146}, +{ -10600, 8496, 15967, -8792, 7532, 20439}, +{ 3041, -13457, 1032, -26952, 5787, 24984}, +{ -4590, -8220, -9322, -6112, -17243, 25745}, +{ -17808, 6970, 3752, 626, -114, 2178}, +{ 4449, -4862, 7054, -5404, 4738, -2827}, +{ 4922, -651, 18939, -9866, 848, 1886}, +{ -336, -5410, 7234, 20444, -9583, -600}, +{ 781, -19474, -12648, 6634, 1414, 450}, +{ -3399, -16770, 11107, 13200, -5498, 21663}, +{ -3265, 4859, -5961, 7530, -10837, 28086}, +{ 10350, -12901, 25699, 25640, -639, 351}, +{ 1163, 18763, -5466, -15087, -145, -1377}, +{ -14477, 27229, -31383, -32653, 21439, -2894}, +{ 15420, 18823, 22128, 19398, 22583, 13587}, +{ -10674, 10710, 5089, -4756, 909, -20760}, +{ -12948, -20660, 7410, 2722, 3427, 11585}, +{ -1105, 18374, 19731, -9650, 22442, 19634}, +{ -296, -6798, -14677, 21603, 19796, 21399}, +{ -19350, -7501, 25446, 13144, 8588, -25298}, +{ 3092, -10618, 20896, 9249, -3326, 1796}, +{ -811, 1449, 3106, 4748, 12073, -14262}, +{ -20720, 14275, -4332, -25838, -5781, -21149}, +{ -5132, 10554, -14020, -22150, 2840, -554}, +{ 25533, 17648, 14886, -21074, 2459, 25142}, +{ -9370, -1788, -12862, -5870, -25811, -11023}, +{ 6698, 819, 10313, 166, 27581, 523}, +{ 101, -19388, 3413, 9638, 64, 806}, +{ -2742, -17931, -2576, 22818, 8553, 1126}, +{ 2972, 15203, 1792, 25434, -5728, -17265}, +{ -1419, 1604, 4398, 11452, 1731, 23787}, +{ -5136, 4625, -10653, 27981, 9897, -2510}, +{ -10528, -28033, 2999, -1530, -832, -830}, +{ -11133, -12511, 22206, -7243, -23578, -21698}, +{ 16935, -21892, 1861, -9606, 9432, 19026}, +{ 10277, 9516, 26815, 2010, -4943, -9080}, +{ 5547, -2210, 14270, -15300, -19316, 1822}, +{ -4850, -783, -8959, -3076, -20056, -3197}, +{ 8232, -2794, -17752, 13308, 3229, -991}, +{ -12237, -6581, 10315, -9552, 2260, -20648}, +{ -7000, 5529, -7553, -7490, -10342, -10266}, +{ 3641, 19479, -5972, -19097, -18570, 12805}, +{ 1283, -4164, 4198, -28473, -2498, 1866}, +{ 16047, 26826, -13053, -6316, 985, -1597}, +{ -403, 13680, 6457, 25070, 27124, -20710}, +{ -18070, -1790, -24986, 5953, -954, 26600}, +{ -24224, -15383, 24788, 1953, -1136, 187}, +{ -2289, 12505, -20738, -904, 18324, 21258}, +{ 2658, -6140, 16179, 22276, -556, 2154}, +{ -6087, 13950, -25682, -27713, 4049, -4795}, +{ -21452, 26473, 19435, -9124, 895, 303}, +{ -22200, -26177, -6026, 24729, -22926, -9030}, +{ -14276, -15982, 23732, -22851, 9268, -3841}, +{ 29482, 21923, -6213, 1679, -2059, -1120}, +{ -435, 9802, -3891, 12359, -4288, -18971}, +{ 19768, -86, 2467, 1990, -1021, -5354}, +{ 20986, -8783, -5329, -23562, -4730, 2673}, +{ -5095, 5605, -4629, 19150, 26037, -12259}, +{ 972, 6858, 4551, 27949, -4025, -2272}, +{ 6075, -3260, -4989, -373, -1571, -3730}, +{ -7256, -12992, -8820, -5109, 23054, 5054}, +{ 920, 2615, 7912, -7353, -4905, 20186}, +{ -250, 5454, 3140, 6928, -18723, -2051}, +{ -10299, -4372, 19608, 4879, -661, -1885}, +{ 14816, -8603, -19815, 6135, -21210, 14108}, +{ -11945, -2223, 5018, 11892, 22741, 406}, +{ -13184, -2613, -13256, -22433, -12482, -8380}, +{ 17066, 25267, -2273, 5056, -342, 145}, +{ 8401, -17683, 19112, 10615, -19453, 17083}, +{ 20821, -5700, 12298, -25598, 10391, 7692}, +{ 4550, 15779, 17338, -19379, -4768, 1206}, +{ -7723, 10836, -27164, -11439, 6835, -1776}, +{ 2542, 3199, 4442, 17513, -3711, -914}, +{ 20960, -16774, -5814, 11087, -70, 22961}, +{ 3305, 2919, 6256, -4800, -20966, -3230}, +{ 5924, -16547, 2183, 2733, 3446, -23306}, +{ -6061, -194, -13852, -10971, 19488, 1029}, +{ 4467, -5964, -19004, 1519, -359, 855}, +{ -1581, -7607, 22070, -11580, -10032, 17102}, +{ -12412, 2553, 4324, 22500, 5751, 12170}, +{ -25127, 17996, -6384, 1180, 1182, 9622}, +{ 23462, -8471, -4392, -2669, 7638, -16835}, +{ -5511, -2887, -10757, -20883, 7246, 1053}, +{ 2703, -20602, -7554, 7516, -7740, 5868}, +{ 20670, 21901, 457, 14969, -17657, -11921}, +{ 3603, -1595, -2177, -157, -43, 605}, +{ 2513, 8954, 10527, 22559, -16100, -16041}, +{ 6002, 4951, 6795, -4862, -22400, 18849}, +{ 7590, -1693, -24688, -3404, 14169, 1214}, +{ -4398, -6663, -6870, -10083, -24596, 9253}, +{ 10468, 17751, -7748, 147, -6314, 4419}, +{ 16187, -16557, -4119, 4302, 7625, 5409}, +{ 3303, 2735, 7458, -19902, -2254, -3702}, +{ -2077, 21609, 14870, 12545, -6081, -1764}, +{ 4678, 11740, 2859, 6953, 1919, -3871}, +{ 3522, -21853, -2469, -10453, 18893, -10742}, +{ 3759, -10191, -4866, -2659, -17831, -1242}, +{ 14991, 9351, 11870, -1573, -4848, 22549}, +{ 9509, -27152, 10734, 20851, -26185, -17878}, +{ -7170, -1392, -19495, 12746, 8198, -1988}, +{ 1883, 28158, -846, -7235, 249, 233}, +{ -7200, 669, -371, -2948, 23234, -5635}, +{ 3141, 288, 3223, -1258, -98, -27607}, +{ 17373, -23235, 5110, -11199, -2574, -11487}, +{ -4928, 1518, -5456, 670, -18278, 1951}, +{ 10334, -19865, -4649, 361, -160, -923}, +{ 18732, 14264, -3155, -7485, -3328, 5959}, +{ -3614, 21077, 7276, 3536, 8121, -1528}, +{ -8422, 500, -19182, 18929, 26392, -1039}, +{ 15639, 25668, 8375, 1903, 1945, -11979}, +{ -2716, 3389, 26850, -4587, 1803, 22}, +{ 1177, -655, 1233, -2128, 7844, 1767}, +{ -761, 8209, -19290, -4593, 1923, -343}, +{ -689, -3530, -3267, -3804, -2753, 18566}, +{ -2110, 1962, -1353, 16643, 2765, -23102}, +{ -433, 4905, 302, 13016, 15933, -5905}, +{ 3203, 4126, 11181, -5496, -2529, -1160}, +{ -1091, -6469, -1415, 5682, -268, 583}, +{ -9405, -19572, 6216, 1658, 993, -75}, +{ -1695, -4504, -2289, -4088, -6556, -16577}, +{ 4760, -892, -10902, 6516, 24199, -6011}, +{ -253, 1000, 63, -81, -115, -382}, +{ -1333, 24224, -698, -4667, -2801, -19144}, +{ -876, -28866, -21873, 12677, -6344, 3235}, +{ 16847, 21145, -26172, -3183, -396, 230}, +{ 18296, -7790, -12857, -679, -1473, 5}, +{ -10488, 11429, 25805, -1122, 1401, -438}, +{ 3782, -7429, 26720, 17567, 19257, 12542}, +{ 6332, -746, 12789, 9316, -22542, -5354}, +{ 3418, -22728, 26978, 18303, 1076, 956}, +{ -27315, -2988, 920, 235, 2233, 81}, +{ 6199, 5296, 16093, 14768, -8429, -1112}, +{ -6432, 19244, 9921, -3253, 1278, -954}, +{ 24213, 2049, -22931, 2585, -2410, -4216}, +{ 9286, 14282, -19735, -3985, -2344, 1028}, +{ -20128, 17993, -9458, 23012, -16983, 8625}, +{ -6896, -20730, 3762, 17415, 22341, 19024}, +{ 842, 24181, 25062, -5839, -78, 937}, +{ -621, 19722, -24204, -1962, -14854, -56}, +{ 22766, -5119, 17365, 23868, -19480, -6558}, +{ -2158, 17490, -21435, 3340, -12819, -20295}, +{ -9621, 17325, 715, 2265, -4123, -492}, +{ 9156, 12947, 27303, -21175, -6072, -9457}, +{ -13164, -23269, -14006, -4184, 6978, 2}, +{ 938, -13381, 3520, -24297, 22902, 19589}, +{ -4911, -19774, 19764, -9310, -12650, 3819}, +{ -5462, -4249, -6987, -6260, -13943, -25150}, +{ 9341, 10369, -13862, -6704, 22556, -519}, +{ 6651, 18768, -4855, 12570, 14730, -10209}, +{ -823, 18119, 398, -1582, -116, -363}, +{ -6935, -12694, -28392, 8552, 6961, -239}, +{ -2602, -4704, -1021, 2015, 5129, 23670}, +{ -12559, -8190, -25028, 18544, 14179, 1663}, +{ 3813, 21036, -9620, -5051, -1800, -1087}, +{ -22057, 16675, 14960, 9459, 2786, 16991}, +{ -26040, -19318, -6414, 1104, 5798, -18039}, +{ -1737, 24825, 10417, -11087, 896, -5273}, +{ -1855, 11661, -2803, 24809, -21435, -19792}, +{ -23473, -16729, -5782, 5643, 2636, 4940}, +{ -1724, 4388, -26673, -13695, 10570, -25895}, +{ 15358, -19496, 26242, -18493, 1736, 8054}, +{ 5684, 20890, 4091, -19100, -14588, -10468}, +{ 17260, -16291, 14859, -17711, -19174, 12435}, +{ -27185, -12573, 6743, -562, 976, -257}, +{ 12395, -8618, -22248, -19843, 11013, 7762}, +{ 3799, 11853, -27622, -8473, 1089, -1495}, +{ 4141, -2182, -26720, -735, -774, 1469}, +{ 3125, 13762, 4606, 29257, 18771, -9958}, +{ -17465, -9445, -17562, -2530, -6435, -3726}, +{ -1742, 4351, -6841, -19773, 9627, -10654}, +{ 7251, 3525, 10835, 5601, 25198, -23348}, +{ -10300, -17830, 631, 11640, 2044, -20878}, +{ -873, -8502, -1063, -15674, -10693, 14934}, +{ -15957, 28137, 5268, 477, -1053, 1158}, +{ -1495, -8814, -5764, -24965, 25988, 7907}, +{ -1038, -114, -2308, -1319, -6480, 1472}, +{ 4895, -17897, -25850, 5301, -188, 1581}, +{ 3200, 17225, 4346, 22101, -18543, 22028}, +{ -10250, 545, -10932, 2276, -28070, 8118}, +{ 15343, 2329, 9316, 20537, 14908, 21021}, +{ 6329, 6130, -24508, 837, -8637, -5844}, +{ 7386, -501, 10503, 20131, 11435, -4755}, +{ -2745, 24174, -9274, 15273, -8389, -5835}, +{ 2992, -2864, 6048, -7473, 11687, -19996}, +{ -883, -11954, -9976, -21829, -4436, -27178}, +{ 3458, 19626, 1280, 2597, 19849, 5255}, +{ -5315, 19133, -14518, -8946, 13749, -1352}, +{ 18642, 17655, 11001, 6817, -18418, 6336}, +{ -1697, 2244, -4640, 3948, -12890, -5273}, +{ 20428, 10542, 4170, -1012, 19439, 21691}, +{ -2943, -19735, -4208, 1320, 909, -8897}, +{ 9351, -8066, -2618, -12933, 26582, 3507}, +{ 9705, -22628, 8311, 8167, -13293, 5608}, +{ 3222, 3749, -1508, 165, -52, -196}, +{ 102, -22744, -8832, 903, -11421, -14662}, +{ -120, 5998, 19765, 13401, 3628, 5197}, +{ 8528, 5827, -1066, 774, -39, -166}, +{ 9411, -9476, 9581, -13004, 24456, 24900}, +{ 17878, 2235, -21639, 20478, 4716, -7190}, +{ -2482, 9511, 1611, -21943, 14230, -1289}, +{ 9288, -2291, 23215, -3452, -10842, 11}, +{ 9496, 3041, 5130, -3890, -21219, -22589}, +{ 14262, -9838, 20195, 14019, 91, -17200}, +{ -18591, 980, 17, 821, 120, -574}, +{ 12285, -19269, 13742, 16373, -161, 6025}, +{ -3364, 1530, -4005, 2454, -10872, -23839}, +{ 105, 5085, -260, 5790, -588, 19170}, +{ 4121, 4169, 13439, 14644, 20899, 7434}, +{ -175, 13101, -3704, 23233, 3907, 10106}, +{ -6101, 23467, 5204, -1341, 1599, 13174}, +{ -3217, -3494, 15117, -8387, -11762, -4750}, +{ 1146, 4675, -19378, 14917, -5091, 249}, +{ -21506, 10136, -16473, -13305, 18382, -8601}, +{ 628, 2447, 3344, 3130, -5115, 119}, +{ 17900, -22422, -17633, 21967, -16293, -7676}, +{ 16863, 24214, 5612, -3858, -809, 3822}, +{ -2291, 10091, -2360, -25109, -1226, 312}, +{ 2957, 11256, 26745, -13266, -3455, -1128}, +{ -19762, -2708, 4604, 6355, 1638, 25501}, +{ -19593, -7753, 3159, -85, -489, -1855}, +{ 814, 12510, 19077, -4681, -2610, -1474}, +{ -23408, -19027, 8137, 19878, 7912, -282}, +{ 839, -19652, 11927, 27278, -3211, 2266}, +{ 4020, -1110, 8226, -1274, 20922, 25060}, +{ 26576, 325, -8693, -232, -2218, -699}, +{ -11293, -4200, 1805, -6673, -22940, -1339}, +{ -2005, -15886, -1047, -27687, -13235, 14370}, +{ -22073, 1949, 13175, -15656, -1846, 8055}, +{ 3039, 12025, 7132, -24632, 413, -2347}, +{ -24048, -206, 12459, -6654, -417, -10091}, +{ 18179, -23688, -20515, -16396, 7230, 763}, +{ 5659, -5085, 13878, -23729, -11077, -19587}, +{ 11340, 501, 25040, 7616, -19658, 1605}, +{ -26650, 8878, 10544, 417, 1299, 261}, +{ 14460, 11369, -3263, 9990, 8194, 18111}, +{ 1355, -20838, -9196, -16060, -8559, -730}, +{ -1918, -20937, -18293, -2461, -2651, 4316}, +{ -2810, 24521, -10996, -25721, 308, -1234}, +{ -9075, -17280, -1833, -29342, -24213, -16631}, +{ -2843, 10165, -5339, -2888, 21858, -21340}, +{ -15832, 14849, -23780, 5184, 10113, -20639}, +{ -19535, -11361, 8413, 1486, -23658, -5759}, +{ -7512, 1027, -20794, 13732, 19892, -21934}, +{ -12132, -7022, -19175, -8840, 22125, -16490}, +{ 1937, 5210, -6318, -23788, 13141, 11082}, +{ -205, 6036, -380, 8658, -233, 28020}, +{ -5523, 7477, 7635, 23595, 9763, -2590}, +{ 21658, -28313, -3086, -300, -1032, 1744}, +{ -22352, 16646, 208, 6665, -17400, -3028}, +{ 18482, 9336, -2737, -19372, 407, -4389}, +{ -4913, -17370, 18819, -17654, 13416, 15232}, +{ 7749, 6368, 23135, -18174, 7584, -4248}, +{ -1489, -6523, 586, -10157, 14964, 25568}, +{ 3844, -6156, 4897, -13045, -22526, 5647}, +{ -8491, -2105, -24774, 905, -9326, 1456}, +{ -3040, -1476, 1166, -4428, 11236, 9204}, +{ 3397, -1451, 13598, -15841, 24540, 5819}, +{ 8483, -2993, 21547, -16916, 7741, 24018}, +{ -14932, -23758, -5332, -6664, -4497, 13267}, +{ 19379, 12916, -2142, -737, 21100, -22101}, +{ 3393, -4629, 5735, -18913, -6969, 2687}, +{ 1148, -16147, -21433, -28095, -630, -14449}, +{ 7300, 672, 18530, -17452, -10149, 351}, +{ 11356, -10974, 17212, 4624, 145, 17791}, +{ -711, -3479, -2238, 15887, 2027, 0}, +{ -28048, 1794, -593, -2758, -21852, 11535}, +{ -19683, 4937, 22004, 21523, -3148, 1790}, +{ 813, 8231, 2633, 11981, -3043, 22201}, +{ 8952, -24760, -690, 14873, -2366, -5372}, +{ 8406, -5439, -274, -642, -145, 778}, +{ -6605, 7258, 20780, -23507, -18625, 22782}, +{ -22896, -25488, 10020, -1614, 1508, -1393}, +{ 7607, 407, -24678, -16385, -1804, -4699}, +{ -10592, -19139, 10462, -3747, 8721, -6919}, +{ 13010, 5292, -6230, -4884, -20904, -1797}, +{ 16891, -13770, -465, 19343, -10741, -12959}, +{ 25193, -14799, -5681, -521, -321, -1211}, +{ 6917, -3093, 20183, -26903, -12026, 1295}, +{ 305, 1992, 19457, -985, 25, -521}, +{ 6707, -3698, 8365, -8687, 21921, -27166}, +{ 4668, 5997, 7117, 11696, 24401, -10794}, +{ 744, -9416, 19893, 1963, 7922, -9824}, +{ 3430, 21282, -1736, 10844, 8821, 27015}, +{ -8813, 1521, -24038, 1651, 7838, -1208}, +{ 3911, -11221, 3273, -12541, 7168, 18402}, +{ 21642, 9117, -11536, -5256, 7077, 2382}, +{ 100, 3817, -6713, 1244, 1518, -321}, +{ 7946, -18670, 10667, -4866, 727, 776}, +{ -15883, -8150, -2087, 22739, 1567, -3482}, +{ 4380, -2735, 8469, -7025, -11424, 1317}, +{ 26970, 4393, 7665, 17561, -714, 650}, +{ -16191, -835, 8365, 1795, -14314, 16297}, +{ 4504, -10048, 7662, -26690, -17428, 2580}, +{ 48, -3984, 564, -5871, 2658, -18658}, +{ 12579, -26016, -15642, 2672, -1347, -887}, +{ -4950, 4208, -6811, 2569, -20621, -8658}, +{ -1836, -14818, -5571, -23322, -14800, 25867}, +{ 5434, -28139, -2357, -2883, -570, 2431}, +{ 13096, -2771, 24994, -12496, -24723, -1025}, +{ -5676, -4339, 1908, 18628, -21323, 17366}, +{ 27660, -27897, -15409, 1436, -7112, -2241}, +{ 8019, 3847, 24568, -469, 9674, 10683}, +{ -903, -10149, 1801, -21260, 4795, -8751}, +{ 1122, -9582, 2625, 22791, 956, 882}, +{ 7876, 19075, -9900, -24266, 7496, 9277}, +{ 980, -26764, -5386, 5396, 1086, 1648}, +{ 28838, -1270, -447, 5, -429, -20}, +{ -15283, 6132, 22812, 1252, -9963, 511}, +{ 851, 7925, -457, -12210, 4261, 7579}, +{ -4530, 8452, -1246, 14501, -24951, -5760}, +{ -17814, -10727, 9887, -23929, -13432, 1878}, +{ -15049, 10165, 16491, -14603, -11712, -21156}, +{ -3317, 840, -5683, 22413, 1994, 586}, +{ 23158, -5788, -15043, -10372, -9271, -13523}, +{ -773, -9509, -3993, -24264, 8463, 5804}, +{ -8545, -703, -12440, -3985, -25122, -28147}, +{ -16659, 16001, 2746, 1611, 5097, -1043}, +{ 41, -7181, 19903, 31555, -32237, 13927}, +{ -5658, 845, -12774, 5705, 16695, -86}, +{ 5282, 14875, 27026, 21124, 15776, -10477}, +{ 14712, 19648, -11487, -13361, -20196, -15229}, +{ 8597, -9138, -626, 10891, -6015, 6346}, +{ -1488, -1272, -1479, -1303, -3704, -5485}, +{ -3370, 17871, -6604, 24930, 25886, -3127}, +{ 8416, 27783, -1385, 5350, -4260, 19993}, +{ 5688, 362, 17246, 3809, -3246, 1088}, +{ -105, -29607, 2747, 15223, -167, 3722}, +{ 3502, -3195, 8602, 7772, -1566, -915}, +{ -491, 3257, -2423, 5522, 20606, -100}, +{ -13948, -11368, -15375, -21866, -8520, 12221}, +{ -616, 2424, -2023, 4398, -3805, 8108}, +{ -7204, 21043, 21211, -9395, -19391, 896}, +{ -5737, -15160, -21298, 17066, -1006, -366}, +{ 6261, 3240, -11937, -16213, -15820, 6581}, +{ -3155, 24796, 2733, -1257, -875, -1597}, +{ -20469, 11094, 24071, -8987, 14136, 2220}, +{ -14106, 11959, -22495, 4135, -1055, -5420}, +{ 801, -2655, 60, -5324, -790, 5937}, +{ -7372, -1764, -22433, -26060, 21707, 4178}, +{ -5715, -6648, -14908, 1325, -24044, 1493}, +{ -6024, -12488, 23930, 2950, 1601, 1173}, +{ 19067, 17630, 17929, -10654, 10928, -4958}, +{ 3231, -3284, 27336, 4174, -1683, 497}, +}; + +const int16_t (* const ff_eac3_mantissa_vq[8])[6] = { + NULL, + vq_hebap1, + vq_hebap2, + vq_hebap3, + vq_hebap4, + vq_hebap5, + vq_hebap6, + vq_hebap7, +}; + +/** + * Table E2.14 Frame Exponent Strategy Combinations + */ +const uint8_t ff_eac3_frm_expstr[32][6] = { +{ EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_REUSE}, +{ EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_D45}, +{ EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_D25, EXP_REUSE}, +{ EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_D45, EXP_D45}, +{ EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_REUSE}, +{ EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_D45}, +{ EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D45, EXP_D25, EXP_REUSE}, +{ EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D45, EXP_D45, EXP_D45}, +{ EXP_D25, EXP_REUSE, EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE}, +{ EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D45}, +{ EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE}, +{ EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_D45, EXP_D45}, +{ EXP_D25, EXP_REUSE, EXP_D45, EXP_D25, EXP_REUSE, EXP_REUSE}, +{ EXP_D25, EXP_REUSE, EXP_D45, EXP_D25, EXP_REUSE, EXP_D45}, +{ EXP_D25, EXP_REUSE, EXP_D45, EXP_D45, EXP_D25, EXP_REUSE}, +{ EXP_D25, EXP_REUSE, EXP_D45, EXP_D45, EXP_D45, EXP_D45}, +{ EXP_D45, EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_REUSE}, +{ EXP_D45, EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE, EXP_D45}, +{ EXP_D45, EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D25, EXP_REUSE}, +{ EXP_D45, EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D45, EXP_D45}, +{ EXP_D45, EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_REUSE}, +{ EXP_D45, EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE, EXP_D45}, +{ EXP_D45, EXP_D25, EXP_REUSE, EXP_D45, EXP_D25, EXP_REUSE}, +{ EXP_D45, EXP_D25, EXP_REUSE, EXP_D45, EXP_D45, EXP_D45}, +{ EXP_D45, EXP_D45, EXP_D15, EXP_REUSE, EXP_REUSE, EXP_REUSE}, +{ EXP_D45, EXP_D45, EXP_D25, EXP_REUSE, EXP_REUSE, EXP_D45}, +{ EXP_D45, EXP_D45, EXP_D25, EXP_REUSE, EXP_D25, EXP_REUSE}, +{ EXP_D45, EXP_D45, EXP_D25, EXP_REUSE, EXP_D45, EXP_D45}, +{ EXP_D45, EXP_D45, EXP_D45, EXP_D25, EXP_REUSE, EXP_REUSE}, +{ EXP_D45, EXP_D45, EXP_D45, EXP_D25, EXP_REUSE, EXP_D45}, +{ EXP_D45, EXP_D45, EXP_D45, EXP_D45, EXP_D25, EXP_REUSE}, +{ EXP_D45, EXP_D45, EXP_D45, EXP_D45, EXP_D45, EXP_D45}, +}; + +/** + * Table E.25: Spectral Extension Attenuation Table + * ff_eac3_spx_atten_tab[code][bin]=pow(2.0,(bin+1)*(code+1)/-15.0); + */ +const float ff_eac3_spx_atten_tab[32][3] = { + { 0.954841603910416503f, 0.911722488558216804f, 0.870550563296124125f }, + { 0.911722488558216804f, 0.831237896142787758f, 0.757858283255198995f }, + { 0.870550563296124125f, 0.757858283255198995f, 0.659753955386447100f }, + { 0.831237896142787758f, 0.690956439983888004f, 0.574349177498517438f }, + { 0.793700525984099792f, 0.629960524947436595f, 0.500000000000000000f }, + { 0.757858283255198995f, 0.574349177498517438f, 0.435275281648062062f }, + { 0.723634618720189082f, 0.523647061410313364f, 0.378929141627599553f }, + { 0.690956439983888004f, 0.477420801955208307f, 0.329876977693223550f }, + { 0.659753955386447100f, 0.435275281648062062f, 0.287174588749258719f }, + { 0.629960524947436595f, 0.396850262992049896f, 0.250000000000000000f }, + { 0.601512518041058319f, 0.361817309360094541f, 0.217637640824031003f }, + { 0.574349177498517438f, 0.329876977693223550f, 0.189464570813799776f }, + { 0.548412489847312945f, 0.300756259020529160f, 0.164938488846611775f }, + { 0.523647061410313364f, 0.274206244923656473f, 0.143587294374629387f }, + { 0.500000000000000000f, 0.250000000000000000f, 0.125000000000000000f }, + { 0.477420801955208307f, 0.227930622139554201f, 0.108818820412015502f }, + { 0.455861244279108402f, 0.207809474035696939f, 0.094732285406899888f }, + { 0.435275281648062062f, 0.189464570813799776f, 0.082469244423305887f }, + { 0.415618948071393879f, 0.172739109995972029f, 0.071793647187314694f }, + { 0.396850262992049896f, 0.157490131236859149f, 0.062500000000000000f }, + { 0.378929141627599553f, 0.143587294374629387f, 0.054409410206007751f }, + { 0.361817309360094541f, 0.130911765352578369f, 0.047366142703449930f }, + { 0.345478219991944002f, 0.119355200488802049f, 0.041234622211652958f }, + { 0.329876977693223550f, 0.108818820412015502f, 0.035896823593657347f }, + { 0.314980262473718298f, 0.099212565748012460f, 0.031250000000000000f }, + { 0.300756259020529160f, 0.090454327340023621f, 0.027204705103003875f }, + { 0.287174588749258719f, 0.082469244423305887f, 0.023683071351724965f }, + { 0.274206244923656473f, 0.075189064755132290f, 0.020617311105826479f }, + { 0.261823530705156682f, 0.068551561230914118f, 0.017948411796828673f }, + { 0.250000000000000000f, 0.062500000000000000f, 0.015625000000000000f }, + { 0.238710400977604098f, 0.056982655534888536f, 0.013602352551501938f }, + { 0.227930622139554201f, 0.051952368508924235f, 0.011841535675862483f } +}; diff --git a/ffmpeg/libavcodec/eac3_data.h b/ffmpeg/libavcodec/eac3_data.h new file mode 100644 index 0000000..10a67f1 --- /dev/null +++ b/ffmpeg/libavcodec/eac3_data.h @@ -0,0 +1,36 @@ +/* + * E-AC-3 tables + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +#ifndef AVCODEC_EAC3_DATA_H +#define AVCODEC_EAC3_DATA_H + +#include + +extern const uint8_t ff_eac3_bits_vs_hebap[20]; +extern const int16_t ff_eac3_gaq_remap_1[12]; +extern const int16_t ff_eac3_gaq_remap_2_4_a[9][2]; +extern const int16_t ff_eac3_gaq_remap_2_4_b[9][2]; + +extern const int16_t (* const ff_eac3_mantissa_vq[8])[6]; +extern const uint8_t ff_eac3_frm_expstr[32][6]; +extern const float ff_eac3_spx_atten_tab[32][3]; + +#endif /* AVCODEC_EAC3_DATA_H */ diff --git a/ffmpeg/libavcodec/eac3dec.c b/ffmpeg/libavcodec/eac3dec.c new file mode 100644 index 0000000..b55ee2a --- /dev/null +++ b/ffmpeg/libavcodec/eac3dec.c @@ -0,0 +1,607 @@ +/* + * E-AC-3 decoder + * Copyright (c) 2007 Bartlomiej Wolowiec + * Copyright (c) 2008 Justin Ruggles + * + * 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 + */ + +/* + * There are several features of E-AC-3 that this decoder does not yet support. + * + * Enhanced Coupling + * No known samples exist. If any ever surface, this feature should not be + * too difficult to implement. + * + * Reduced Sample Rates + * No known samples exist. The spec also does not give clear information + * on how this is to be implemented. + * + * Dependent Streams + * Only the independent stream is currently decoded. Any dependent + * streams are skipped. We have only come across two examples of this, and + * they are both just test streams, one for HD-DVD and the other for + * Blu-ray. + * + * Transient Pre-noise Processing + * This is side information which a decoder should use to reduce artifacts + * caused by transients. There are samples which are known to have this + * information, but this decoder currently ignores it. + */ + + +#include "avcodec.h" +#include "internal.h" +#include "aac_ac3_parser.h" +#include "ac3.h" +#include "ac3_parser.h" +#include "ac3dec.h" +#include "ac3dec_data.h" +#include "eac3_data.h" + +/** gain adaptive quantization mode */ +typedef enum { + EAC3_GAQ_NO =0, + EAC3_GAQ_12, + EAC3_GAQ_14, + EAC3_GAQ_124 +} EAC3GaqMode; + +#define EAC3_SR_CODE_REDUCED 3 + +void ff_eac3_apply_spectral_extension(AC3DecodeContext *s) +{ + int bin, bnd, ch, i; + uint8_t wrapflag[SPX_MAX_BANDS]={1,0,}, num_copy_sections, copy_sizes[SPX_MAX_BANDS]; + float rms_energy[SPX_MAX_BANDS]; + + /* Set copy index mapping table. Set wrap flags to apply a notch filter at + wrap points later on. */ + bin = s->spx_dst_start_freq; + num_copy_sections = 0; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int copysize; + int bandsize = s->spx_band_sizes[bnd]; + if (bin + bandsize > s->spx_src_start_freq) { + copy_sizes[num_copy_sections++] = bin - s->spx_dst_start_freq; + bin = s->spx_dst_start_freq; + wrapflag[bnd] = 1; + } + for (i = 0; i < bandsize; i += copysize) { + if (bin == s->spx_src_start_freq) { + copy_sizes[num_copy_sections++] = bin - s->spx_dst_start_freq; + bin = s->spx_dst_start_freq; + } + copysize = FFMIN(bandsize - i, s->spx_src_start_freq - bin); + bin += copysize; + } + } + copy_sizes[num_copy_sections++] = bin - s->spx_dst_start_freq; + + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (!s->channel_uses_spx[ch]) + continue; + + /* Copy coeffs from normal bands to extension bands */ + bin = s->spx_src_start_freq; + for (i = 0; i < num_copy_sections; i++) { + memcpy(&s->transform_coeffs[ch][bin], + &s->transform_coeffs[ch][s->spx_dst_start_freq], + copy_sizes[i]*sizeof(float)); + bin += copy_sizes[i]; + } + + /* Calculate RMS energy for each SPX band. */ + bin = s->spx_src_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int bandsize = s->spx_band_sizes[bnd]; + float accum = 0.0f; + for (i = 0; i < bandsize; i++) { + float coeff = s->transform_coeffs[ch][bin++]; + accum += coeff * coeff; + } + rms_energy[bnd] = sqrtf(accum / bandsize); + } + + /* Apply a notch filter at transitions between normal and extension + bands and at all wrap points. */ + if (s->spx_atten_code[ch] >= 0) { + const float *atten_tab = ff_eac3_spx_atten_tab[s->spx_atten_code[ch]]; + bin = s->spx_src_start_freq - 2; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + if (wrapflag[bnd]) { + float *coeffs = &s->transform_coeffs[ch][bin]; + coeffs[0] *= atten_tab[0]; + coeffs[1] *= atten_tab[1]; + coeffs[2] *= atten_tab[2]; + coeffs[3] *= atten_tab[1]; + coeffs[4] *= atten_tab[0]; + } + bin += s->spx_band_sizes[bnd]; + } + } + + /* Apply noise-blended coefficient scaling based on previously + calculated RMS energy, blending factors, and SPX coordinates for + each band. */ + bin = s->spx_src_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + float nscale = s->spx_noise_blend[ch][bnd] * rms_energy[bnd] * (1.0f / INT32_MIN); + float sscale = s->spx_signal_blend[ch][bnd]; + for (i = 0; i < s->spx_band_sizes[bnd]; i++) { + float noise = nscale * (int32_t)av_lfg_get(&s->dith_state); + s->transform_coeffs[ch][bin] *= sscale; + s->transform_coeffs[ch][bin++] += noise; + } + } + } +} + + +/** lrint(M_SQRT2*cos(2*M_PI/12)*(1<<23)) */ +#define COEFF_0 10273905LL + +/** lrint(M_SQRT2*cos(0*M_PI/12)*(1<<23)) = lrint(M_SQRT2*(1<<23)) */ +#define COEFF_1 11863283LL + +/** lrint(M_SQRT2*cos(5*M_PI/12)*(1<<23)) */ +#define COEFF_2 3070444LL + +/** + * Calculate 6-point IDCT of the pre-mantissas. + * All calculations are 24-bit fixed-point. + */ +static void idct6(int pre_mant[6]) +{ + int tmp; + int even0, even1, even2, odd0, odd1, odd2; + + odd1 = pre_mant[1] - pre_mant[3] - pre_mant[5]; + + even2 = ( pre_mant[2] * COEFF_0) >> 23; + tmp = ( pre_mant[4] * COEFF_1) >> 23; + odd0 = ((pre_mant[1] + pre_mant[5]) * COEFF_2) >> 23; + + even0 = pre_mant[0] + (tmp >> 1); + even1 = pre_mant[0] - tmp; + + tmp = even0; + even0 = tmp + even2; + even2 = tmp - even2; + + tmp = odd0; + odd0 = tmp + pre_mant[1] + pre_mant[3]; + odd2 = tmp + pre_mant[5] - pre_mant[3]; + + pre_mant[0] = even0 + odd0; + pre_mant[1] = even1 + odd1; + pre_mant[2] = even2 + odd2; + pre_mant[3] = even2 - odd2; + pre_mant[4] = even1 - odd1; + pre_mant[5] = even0 - odd0; +} + +void ff_eac3_decode_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch) +{ + int bin, blk, gs; + int end_bap, gaq_mode; + GetBitContext *gbc = &s->gbc; + int gaq_gain[AC3_MAX_COEFS]; + + gaq_mode = get_bits(gbc, 2); + end_bap = (gaq_mode < 2) ? 12 : 17; + + /* if GAQ gain is used, decode gain codes for bins with hebap between + 8 and end_bap */ + gs = 0; + if (gaq_mode == EAC3_GAQ_12 || gaq_mode == EAC3_GAQ_14) { + /* read 1-bit GAQ gain codes */ + for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) { + if (s->bap[ch][bin] > 7 && s->bap[ch][bin] < end_bap) + gaq_gain[gs++] = get_bits1(gbc) << (gaq_mode-1); + } + } else if (gaq_mode == EAC3_GAQ_124) { + /* read 1.67-bit GAQ gain codes (3 codes in 5 bits) */ + int gc = 2; + for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) { + if (s->bap[ch][bin] > 7 && s->bap[ch][bin] < 17) { + if (gc++ == 2) { + int group_code = get_bits(gbc, 5); + if (group_code > 26) { + av_log(s->avctx, AV_LOG_WARNING, "GAQ gain group code out-of-range\n"); + group_code = 26; + } + gaq_gain[gs++] = ff_ac3_ungroup_3_in_5_bits_tab[group_code][0]; + gaq_gain[gs++] = ff_ac3_ungroup_3_in_5_bits_tab[group_code][1]; + gaq_gain[gs++] = ff_ac3_ungroup_3_in_5_bits_tab[group_code][2]; + gc = 0; + } + } + } + } + + gs=0; + for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) { + int hebap = s->bap[ch][bin]; + int bits = ff_eac3_bits_vs_hebap[hebap]; + if (!hebap) { + /* zero-mantissa dithering */ + for (blk = 0; blk < 6; blk++) { + s->pre_mantissa[ch][bin][blk] = (av_lfg_get(&s->dith_state) & 0x7FFFFF) - 0x400000; + } + } else if (hebap < 8) { + /* Vector Quantization */ + int v = get_bits(gbc, bits); + for (blk = 0; blk < 6; blk++) { + s->pre_mantissa[ch][bin][blk] = ff_eac3_mantissa_vq[hebap][v][blk] << 8; + } + } else { + /* Gain Adaptive Quantization */ + int gbits, log_gain; + if (gaq_mode != EAC3_GAQ_NO && hebap < end_bap) { + log_gain = gaq_gain[gs++]; + } else { + log_gain = 0; + } + gbits = bits - log_gain; + + for (blk = 0; blk < 6; blk++) { + int mant = get_sbits(gbc, gbits); + if (log_gain && mant == -(1 << (gbits-1))) { + /* large mantissa */ + int b; + int mbits = bits - (2 - log_gain); + mant = get_sbits(gbc, mbits); + mant <<= (23 - (mbits - 1)); + /* remap mantissa value to correct for asymmetric quantization */ + if (mant >= 0) + b = 1 << (23 - log_gain); + else + b = ff_eac3_gaq_remap_2_4_b[hebap-8][log_gain-1] << 8; + mant += ((ff_eac3_gaq_remap_2_4_a[hebap-8][log_gain-1] * (int64_t)mant) >> 15) + b; + } else { + /* small mantissa, no GAQ, or Gk=1 */ + mant <<= 24 - bits; + if (!log_gain) { + /* remap mantissa value for no GAQ or Gk=1 */ + mant += (ff_eac3_gaq_remap_1[hebap-8] * (int64_t)mant) >> 15; + } + } + s->pre_mantissa[ch][bin][blk] = mant; + } + } + idct6(s->pre_mantissa[ch][bin]); + } +} + +int ff_eac3_parse_header(AC3DecodeContext *s) +{ + int i, blk, ch; + int ac3_exponent_strategy, parse_aht_info, parse_spx_atten_data; + int parse_transient_proc_info; + int num_cpl_blocks; + GetBitContext *gbc = &s->gbc; + + /* An E-AC-3 stream can have multiple independent streams which the + application can select from. each independent stream can also contain + dependent streams which are used to add or replace channels. */ + if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { + avpriv_request_sample(s->avctx, "Dependent substream decoding"); + return AAC_AC3_PARSE_ERROR_FRAME_TYPE; + } else if (s->frame_type == EAC3_FRAME_TYPE_RESERVED) { + av_log(s->avctx, AV_LOG_ERROR, "Reserved frame type\n"); + return AAC_AC3_PARSE_ERROR_FRAME_TYPE; + } + + /* The substream id indicates which substream this frame belongs to. each + independent stream has its own substream id, and the dependent streams + associated to an independent stream have matching substream id's. */ + if (s->substreamid) { + /* only decode substream with id=0. skip any additional substreams. */ + avpriv_request_sample(s->avctx, "Additional substreams"); + return AAC_AC3_PARSE_ERROR_FRAME_TYPE; + } + + if (s->bit_alloc_params.sr_code == EAC3_SR_CODE_REDUCED) { + /* The E-AC-3 specification does not tell how to handle reduced sample + rates in bit allocation. The best assumption would be that it is + handled like AC-3 DolbyNet, but we cannot be sure until we have a + sample which utilizes this feature. */ + avpriv_request_sample(s->avctx, "Reduced sampling rate"); + return AVERROR_PATCHWELCOME; + } + skip_bits(gbc, 5); // skip bitstream id + + /* volume control params */ + for (i = 0; i < (s->channel_mode ? 1 : 2); i++) { + skip_bits(gbc, 5); // skip dialog normalization + if (get_bits1(gbc)) { + skip_bits(gbc, 8); // skip compression gain word + } + } + + /* dependent stream channel map */ + if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { + if (get_bits1(gbc)) { + skip_bits(gbc, 16); // skip custom channel map + } + } + + /* mixing metadata */ + if (get_bits1(gbc)) { + /* center and surround mix levels */ + if (s->channel_mode > AC3_CHMODE_STEREO) { + skip_bits(gbc, 2); // skip preferred stereo downmix mode + if (s->channel_mode & 1) { + /* if three front channels exist */ + skip_bits(gbc, 3); //skip Lt/Rt center mix level + s->center_mix_level = get_bits(gbc, 3); + } + if (s->channel_mode & 4) { + /* if a surround channel exists */ + skip_bits(gbc, 3); //skip Lt/Rt surround mix level + s->surround_mix_level = get_bits(gbc, 3); + } + } + + /* lfe mix level */ + if (s->lfe_on && get_bits1(gbc)) { + // TODO: use LFE mix level + skip_bits(gbc, 5); // skip LFE mix level code + } + + /* info for mixing with other streams and substreams */ + if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT) { + for (i = 0; i < (s->channel_mode ? 1 : 2); i++) { + // TODO: apply program scale factor + if (get_bits1(gbc)) { + skip_bits(gbc, 6); // skip program scale factor + } + } + if (get_bits1(gbc)) { + skip_bits(gbc, 6); // skip external program scale factor + } + /* skip mixing parameter data */ + switch(get_bits(gbc, 2)) { + case 1: skip_bits(gbc, 5); break; + case 2: skip_bits(gbc, 12); break; + case 3: { + int mix_data_size = (get_bits(gbc, 5) + 2) << 3; + skip_bits_long(gbc, mix_data_size); + break; + } + } + /* skip pan information for mono or dual mono source */ + if (s->channel_mode < AC3_CHMODE_STEREO) { + for (i = 0; i < (s->channel_mode ? 1 : 2); i++) { + if (get_bits1(gbc)) { + /* note: this is not in the ATSC A/52B specification + reference: ETSI TS 102 366 V1.1.1 + section: E.1.3.1.25 */ + skip_bits(gbc, 8); // skip pan mean direction index + skip_bits(gbc, 6); // skip reserved paninfo bits + } + } + } + /* skip mixing configuration information */ + if (get_bits1(gbc)) { + for (blk = 0; blk < s->num_blocks; blk++) { + if (s->num_blocks == 1 || get_bits1(gbc)) { + skip_bits(gbc, 5); + } + } + } + } + } + + /* informational metadata */ + if (get_bits1(gbc)) { + s->bitstream_mode = get_bits(gbc, 3); + skip_bits(gbc, 2); // skip copyright bit and original bitstream bit + if (s->channel_mode == AC3_CHMODE_STEREO) { + skip_bits(gbc, 4); // skip Dolby surround and headphone mode + } + if (s->channel_mode >= AC3_CHMODE_2F2R) { + skip_bits(gbc, 2); // skip Dolby surround EX mode + } + for (i = 0; i < (s->channel_mode ? 1 : 2); i++) { + if (get_bits1(gbc)) { + skip_bits(gbc, 8); // skip mix level, room type, and A/D converter type + } + } + if (s->bit_alloc_params.sr_code != EAC3_SR_CODE_REDUCED) { + skip_bits1(gbc); // skip source sample rate code + } + } + + /* converter synchronization flag + If frames are less than six blocks, this bit should be turned on + once every 6 blocks to indicate the start of a frame set. + reference: RFC 4598, Section 2.1.3 Frame Sets */ + if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && s->num_blocks != 6) { + skip_bits1(gbc); // skip converter synchronization flag + } + + /* original frame size code if this stream was converted from AC-3 */ + if (s->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT && + (s->num_blocks == 6 || get_bits1(gbc))) { + skip_bits(gbc, 6); // skip frame size code + } + + /* additional bitstream info */ + if (get_bits1(gbc)) { + int addbsil = get_bits(gbc, 6); + for (i = 0; i < addbsil + 1; i++) { + skip_bits(gbc, 8); // skip additional bit stream info + } + } + + /* audio frame syntax flags, strategy data, and per-frame data */ + + if (s->num_blocks == 6) { + ac3_exponent_strategy = get_bits1(gbc); + parse_aht_info = get_bits1(gbc); + } else { + /* less than 6 blocks, so use AC-3-style exponent strategy syntax, and + do not use AHT */ + ac3_exponent_strategy = 1; + parse_aht_info = 0; + } + + s->snr_offset_strategy = get_bits(gbc, 2); + parse_transient_proc_info = get_bits1(gbc); + + s->block_switch_syntax = get_bits1(gbc); + if (!s->block_switch_syntax) + memset(s->block_switch, 0, sizeof(s->block_switch)); + + s->dither_flag_syntax = get_bits1(gbc); + if (!s->dither_flag_syntax) { + for (ch = 1; ch <= s->fbw_channels; ch++) + s->dither_flag[ch] = 1; + } + s->dither_flag[CPL_CH] = s->dither_flag[s->lfe_ch] = 0; + + s->bit_allocation_syntax = get_bits1(gbc); + if (!s->bit_allocation_syntax) { + /* set default bit allocation parameters */ + s->bit_alloc_params.slow_decay = ff_ac3_slow_decay_tab[2]; + s->bit_alloc_params.fast_decay = ff_ac3_fast_decay_tab[1]; + s->bit_alloc_params.slow_gain = ff_ac3_slow_gain_tab [1]; + s->bit_alloc_params.db_per_bit = ff_ac3_db_per_bit_tab[2]; + s->bit_alloc_params.floor = ff_ac3_floor_tab [7]; + } + + s->fast_gain_syntax = get_bits1(gbc); + s->dba_syntax = get_bits1(gbc); + s->skip_syntax = get_bits1(gbc); + parse_spx_atten_data = get_bits1(gbc); + + /* coupling strategy occurrence and coupling use per block */ + num_cpl_blocks = 0; + if (s->channel_mode > 1) { + for (blk = 0; blk < s->num_blocks; blk++) { + s->cpl_strategy_exists[blk] = (!blk || get_bits1(gbc)); + if (s->cpl_strategy_exists[blk]) { + s->cpl_in_use[blk] = get_bits1(gbc); + } else { + s->cpl_in_use[blk] = s->cpl_in_use[blk-1]; + } + num_cpl_blocks += s->cpl_in_use[blk]; + } + } else { + memset(s->cpl_in_use, 0, sizeof(s->cpl_in_use)); + } + + /* exponent strategy data */ + if (ac3_exponent_strategy) { + /* AC-3-style exponent strategy syntax */ + for (blk = 0; blk < s->num_blocks; blk++) { + for (ch = !s->cpl_in_use[blk]; ch <= s->fbw_channels; ch++) { + s->exp_strategy[blk][ch] = get_bits(gbc, 2); + } + } + } else { + /* LUT-based exponent strategy syntax */ + for (ch = !((s->channel_mode > 1) && num_cpl_blocks); ch <= s->fbw_channels; ch++) { + int frmchexpstr = get_bits(gbc, 5); + for (blk = 0; blk < 6; blk++) { + s->exp_strategy[blk][ch] = ff_eac3_frm_expstr[frmchexpstr][blk]; + } + } + } + /* LFE exponent strategy */ + if (s->lfe_on) { + for (blk = 0; blk < s->num_blocks; blk++) { + s->exp_strategy[blk][s->lfe_ch] = get_bits1(gbc); + } + } + /* original exponent strategies if this stream was converted from AC-3 */ + if (s->frame_type == EAC3_FRAME_TYPE_INDEPENDENT && + (s->num_blocks == 6 || get_bits1(gbc))) { + skip_bits(gbc, 5 * s->fbw_channels); // skip converter channel exponent strategy + } + + /* determine which channels use AHT */ + if (parse_aht_info) { + /* For AHT to be used, all non-zero blocks must reuse exponents from + the first block. Furthermore, for AHT to be used in the coupling + channel, all blocks must use coupling and use the same coupling + strategy. */ + s->channel_uses_aht[CPL_CH]=0; + for (ch = (num_cpl_blocks != 6); ch <= s->channels; ch++) { + int use_aht = 1; + for (blk = 1; blk < 6; blk++) { + if ((s->exp_strategy[blk][ch] != EXP_REUSE) || + (!ch && s->cpl_strategy_exists[blk])) { + use_aht = 0; + break; + } + } + s->channel_uses_aht[ch] = use_aht && get_bits1(gbc); + } + } else { + memset(s->channel_uses_aht, 0, sizeof(s->channel_uses_aht)); + } + + /* per-frame SNR offset */ + if (!s->snr_offset_strategy) { + int csnroffst = (get_bits(gbc, 6) - 15) << 4; + int snroffst = (csnroffst + get_bits(gbc, 4)) << 2; + for (ch = 0; ch <= s->channels; ch++) + s->snr_offset[ch] = snroffst; + } + + /* transient pre-noise processing data */ + if (parse_transient_proc_info) { + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (get_bits1(gbc)) { // channel in transient processing + skip_bits(gbc, 10); // skip transient processing location + skip_bits(gbc, 8); // skip transient processing length + } + } + } + + /* spectral extension attenuation data */ + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (parse_spx_atten_data && get_bits1(gbc)) { + s->spx_atten_code[ch] = get_bits(gbc, 5); + } else { + s->spx_atten_code[ch] = -1; + } + } + + /* block start information */ + if (s->num_blocks > 1 && get_bits1(gbc)) { + /* reference: Section E2.3.2.27 + nblkstrtbits = (numblks - 1) * (4 + ceiling(log2(words_per_frame))) + The spec does not say what this data is or what it's used for. + It is likely the offset of each block within the frame. */ + int block_start_bits = (s->num_blocks-1) * (4 + av_log2(s->frame_size-2)); + skip_bits_long(gbc, block_start_bits); + avpriv_request_sample(s->avctx, "Block start info"); + } + + /* syntax state initialization */ + for (ch = 1; ch <= s->fbw_channels; ch++) { + s->first_spx_coords[ch] = 1; + s->first_cpl_coords[ch] = 1; + } + s->first_cpl_leak = 1; + + return 0; +} diff --git a/ffmpeg/libavcodec/eac3enc.c b/ffmpeg/libavcodec/eac3enc.c new file mode 100644 index 0000000..bb9ef4f --- /dev/null +++ b/ffmpeg/libavcodec/eac3enc.c @@ -0,0 +1,268 @@ +/* + * E-AC-3 encoder + * Copyright (c) 2011 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * E-AC-3 encoder + */ + +#define CONFIG_AC3ENC_FLOAT 1 +#include "ac3enc.h" +#include "eac3enc.h" +#include "eac3_data.h" + + +#define AC3ENC_TYPE AC3ENC_TYPE_EAC3 +#include "ac3enc_opts_template.c" + +static const AVClass eac3enc_class = { + .class_name = "E-AC-3 Encoder", + .item_name = av_default_item_name, + .option = ac3_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +/** + * LUT for finding a matching frame exponent strategy index from a set of + * exponent strategies for a single channel across all 6 blocks. + */ +static int8_t eac3_frame_expstr_index_tab[3][4][4][4][4][4]; + + +void ff_eac3_exponent_init(void) +{ + int i; + + memset(eac3_frame_expstr_index_tab, -1, sizeof(eac3_frame_expstr_index_tab)); + for (i = 0; i < 32; i++) { + eac3_frame_expstr_index_tab[ff_eac3_frm_expstr[i][0]-1] + [ff_eac3_frm_expstr[i][1]] + [ff_eac3_frm_expstr[i][2]] + [ff_eac3_frm_expstr[i][3]] + [ff_eac3_frm_expstr[i][4]] + [ff_eac3_frm_expstr[i][5]] = i; + } +} + + +void ff_eac3_get_frame_exp_strategy(AC3EncodeContext *s) +{ + int ch; + + if (s->num_blocks < 6) { + s->use_frame_exp_strategy = 0; + return; + } + + s->use_frame_exp_strategy = 1; + for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) { + int expstr = eac3_frame_expstr_index_tab[s->exp_strategy[ch][0]-1] + [s->exp_strategy[ch][1]] + [s->exp_strategy[ch][2]] + [s->exp_strategy[ch][3]] + [s->exp_strategy[ch][4]] + [s->exp_strategy[ch][5]]; + if (expstr < 0) { + s->use_frame_exp_strategy = 0; + break; + } + s->frame_exp_strategy[ch] = expstr; + } +} + + + +void ff_eac3_set_cpl_states(AC3EncodeContext *s) +{ + int ch, blk; + int first_cpl_coords[AC3_MAX_CHANNELS]; + + /* set first cpl coords */ + for (ch = 1; ch <= s->fbw_channels; ch++) + first_cpl_coords[ch] = 1; + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (block->channel_in_cpl[ch]) { + if (first_cpl_coords[ch]) { + block->new_cpl_coords[ch] = 2; + first_cpl_coords[ch] = 0; + } + } else { + first_cpl_coords[ch] = 1; + } + } + } + + /* set first cpl leak */ + for (blk = 0; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + if (block->cpl_in_use) { + block->new_cpl_leak = 2; + break; + } + } +} + + +void ff_eac3_output_frame_header(AC3EncodeContext *s) +{ + int blk, ch; + AC3EncOptions *opt = &s->options; + + put_bits(&s->pb, 16, 0x0b77); /* sync word */ + + /* BSI header */ + put_bits(&s->pb, 2, 0); /* stream type = independent */ + put_bits(&s->pb, 3, 0); /* substream id = 0 */ + put_bits(&s->pb, 11, (s->frame_size / 2) - 1); /* frame size */ + if (s->bit_alloc.sr_shift) { + put_bits(&s->pb, 2, 0x3); /* fscod2 */ + put_bits(&s->pb, 2, s->bit_alloc.sr_code); /* sample rate code */ + } else { + put_bits(&s->pb, 2, s->bit_alloc.sr_code); /* sample rate code */ + put_bits(&s->pb, 2, s->num_blks_code); /* number of blocks */ + } + put_bits(&s->pb, 3, s->channel_mode); /* audio coding mode */ + put_bits(&s->pb, 1, s->lfe_on); /* LFE channel indicator */ + put_bits(&s->pb, 5, s->bitstream_id); /* bitstream id (EAC3=16) */ + put_bits(&s->pb, 5, -opt->dialogue_level); /* dialogue normalization level */ + put_bits(&s->pb, 1, 0); /* no compression gain */ + /* mixing metadata*/ + put_bits(&s->pb, 1, opt->eac3_mixing_metadata); + if (opt->eac3_mixing_metadata) { + if (s->channel_mode > AC3_CHMODE_STEREO) + put_bits(&s->pb, 2, opt->preferred_stereo_downmix); + if (s->has_center) { + put_bits(&s->pb, 3, s->ltrt_center_mix_level); + put_bits(&s->pb, 3, s->loro_center_mix_level); + } + if (s->has_surround) { + put_bits(&s->pb, 3, s->ltrt_surround_mix_level); + put_bits(&s->pb, 3, s->loro_surround_mix_level); + } + if (s->lfe_on) + put_bits(&s->pb, 1, 0); + put_bits(&s->pb, 1, 0); /* no program scale */ + put_bits(&s->pb, 1, 0); /* no ext program scale */ + put_bits(&s->pb, 2, 0); /* no mixing parameters */ + if (s->channel_mode < AC3_CHMODE_STEREO) + put_bits(&s->pb, 1, 0); /* no pan info */ + put_bits(&s->pb, 1, 0); /* no frame mix config info */ + } + /* info metadata*/ + put_bits(&s->pb, 1, opt->eac3_info_metadata); + if (opt->eac3_info_metadata) { + put_bits(&s->pb, 3, s->bitstream_mode); + put_bits(&s->pb, 1, opt->copyright); + put_bits(&s->pb, 1, opt->original); + if (s->channel_mode == AC3_CHMODE_STEREO) { + put_bits(&s->pb, 2, opt->dolby_surround_mode); + put_bits(&s->pb, 2, opt->dolby_headphone_mode); + } + if (s->channel_mode >= AC3_CHMODE_2F2R) + put_bits(&s->pb, 2, opt->dolby_surround_ex_mode); + put_bits(&s->pb, 1, opt->audio_production_info); + if (opt->audio_production_info) { + put_bits(&s->pb, 5, opt->mixing_level - 80); + put_bits(&s->pb, 2, opt->room_type); + put_bits(&s->pb, 1, opt->ad_converter_type); + } + put_bits(&s->pb, 1, 0); + } + if (s->num_blocks != 6) + put_bits(&s->pb, 1, !(s->avctx->frame_number % 6)); /* converter sync flag */ + put_bits(&s->pb, 1, 0); /* no additional bit stream info */ + + /* frame header */ + if (s->num_blocks == 6) { + put_bits(&s->pb, 1, !s->use_frame_exp_strategy);/* exponent strategy syntax */ + put_bits(&s->pb, 1, 0); /* aht enabled = no */ + } + put_bits(&s->pb, 2, 0); /* snr offset strategy = 1 */ + put_bits(&s->pb, 1, 0); /* transient pre-noise processing enabled = no */ + put_bits(&s->pb, 1, 0); /* block switch syntax enabled = no */ + put_bits(&s->pb, 1, 0); /* dither flag syntax enabled = no */ + put_bits(&s->pb, 1, 0); /* bit allocation model syntax enabled = no */ + put_bits(&s->pb, 1, 0); /* fast gain codes enabled = no */ + put_bits(&s->pb, 1, 0); /* dba syntax enabled = no */ + put_bits(&s->pb, 1, 0); /* skip field syntax enabled = no */ + put_bits(&s->pb, 1, 0); /* spx enabled = no */ + /* coupling strategy use flags */ + if (s->channel_mode > AC3_CHMODE_MONO) { + put_bits(&s->pb, 1, s->blocks[0].cpl_in_use); + for (blk = 1; blk < s->num_blocks; blk++) { + AC3Block *block = &s->blocks[blk]; + put_bits(&s->pb, 1, block->new_cpl_strategy); + if (block->new_cpl_strategy) + put_bits(&s->pb, 1, block->cpl_in_use); + } + } + /* exponent strategy */ + if (s->use_frame_exp_strategy) { + for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) + put_bits(&s->pb, 5, s->frame_exp_strategy[ch]); + } else { + for (blk = 0; blk < s->num_blocks; blk++) + for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) + put_bits(&s->pb, 2, s->exp_strategy[ch][blk]); + } + if (s->lfe_on) { + for (blk = 0; blk < s->num_blocks; blk++) + put_bits(&s->pb, 1, s->exp_strategy[s->lfe_channel][blk]); + } + /* E-AC-3 to AC-3 converter exponent strategy (not optional when num blocks == 6) */ + if (s->num_blocks != 6) { + put_bits(&s->pb, 1, 0); + } else { + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (s->use_frame_exp_strategy) + put_bits(&s->pb, 5, s->frame_exp_strategy[ch]); + else + put_bits(&s->pb, 5, 0); + } + } + /* snr offsets */ + put_bits(&s->pb, 6, s->coarse_snr_offset); + put_bits(&s->pb, 4, s->fine_snr_offset[1]); + /* block start info */ + if (s->num_blocks > 1) + put_bits(&s->pb, 1, 0); +} + + +#if CONFIG_EAC3_ENCODER +AVCodec ff_eac3_encoder = { + .name = "eac3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_EAC3, + .priv_data_size = sizeof(AC3EncodeContext), + .init = ff_ac3_encode_init, + .encode2 = ff_ac3_float_encode_frame, + .close = ff_ac3_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"), + .priv_class = &eac3enc_class, + .channel_layouts = ff_ac3_channel_layouts, + .defaults = ac3_defaults, +}; +#endif diff --git a/ffmpeg/libavcodec/eac3enc.h b/ffmpeg/libavcodec/eac3enc.h new file mode 100644 index 0000000..a92a24c --- /dev/null +++ b/ffmpeg/libavcodec/eac3enc.h @@ -0,0 +1,54 @@ +/* + * E-AC-3 encoder + * Copyright (c) 2011 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * E-AC-3 encoder + */ + +#ifndef AVCODEC_EAC3ENC_H +#define AVCODEC_EAC3ENC_H + +#include "ac3enc.h" + +/** + * Initialize E-AC-3 exponent tables. + */ +void ff_eac3_exponent_init(void); + +/** + * Determine frame exponent strategy use and indices. + */ +void ff_eac3_get_frame_exp_strategy(AC3EncodeContext *s); + +/** + * Set coupling states. + * This determines whether certain flags must be written to the bitstream or + * whether they will be implicitly already known by the decoder. + */ +void ff_eac3_set_cpl_states(AC3EncodeContext *s); + +/** + * Write the E-AC-3 frame header to the output bitstream. + */ +void ff_eac3_output_frame_header(AC3EncodeContext *s); + +#endif /* AVCODEC_EAC3ENC_H */ diff --git a/ffmpeg/libavcodec/eacmv.c b/ffmpeg/libavcodec/eacmv.c new file mode 100644 index 0000000..4e96c1a --- /dev/null +++ b/ffmpeg/libavcodec/eacmv.c @@ -0,0 +1,236 @@ +/* + * Electronic Arts CMV Video Decoder + * Copyright (c) 2007-2008 Peter Ross + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Electronic Arts CMV Video Decoder + * by Peter Ross (pross@xvid.org) + * + * Technical details here: + * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_CMV + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct CmvContext { + AVCodecContext *avctx; + AVFrame *last_frame; ///< last + AVFrame *last2_frame; ///< second-last + int width, height; + unsigned int palette[AVPALETTE_COUNT]; +} CmvContext; + +static av_cold int cmv_decode_init(AVCodecContext *avctx){ + CmvContext *s = avctx->priv_data; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + s->last_frame = av_frame_alloc(); + s->last2_frame = av_frame_alloc(); + if (!s->last_frame || !s->last2_frame) { + av_frame_free(&s->last_frame); + av_frame_free(&s->last2_frame); + return AVERROR(ENOMEM); + } + + return 0; +} + +static void cmv_decode_intra(CmvContext * s, AVFrame *frame, + const uint8_t *buf, const uint8_t *buf_end) +{ + unsigned char *dst = frame->data[0]; + int i; + + for (i=0; i < s->avctx->height && buf_end - buf >= s->avctx->width; i++) { + memcpy(dst, buf, s->avctx->width); + dst += frame->linesize[0]; + buf += s->avctx->width; + } +} + +static void cmv_motcomp(unsigned char *dst, int dst_stride, + const unsigned char *src, int src_stride, + int x, int y, + int xoffset, int yoffset, + int width, int height){ + int i,j; + + for(j=y;j=0 && i+xoffset=0 && j+yoffsetavctx->width*s->avctx->height/16); + int x,y,i; + + i = 0; + for(y=0; yavctx->height/4; y++) + for(x=0; xavctx->width/4 && buf_end - buf > i; x++) { + if (buf[i]==0xFF) { + unsigned char *dst = frame->data[0] + (y*4)*frame->linesize[0] + x*4; + if (raw+16linesize[0], raw+4, 4); + memcpy(dst + 2 * frame->linesize[0], raw+8, 4); + memcpy(dst + 3 * frame->linesize[0], raw+12, 4); + raw+=16; + }else if(raw> 4)) - 7; + if (s->last2_frame->data[0]) + cmv_motcomp(frame->data[0], frame->linesize[0], + s->last2_frame->data[0], s->last2_frame->linesize[0], + x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height); + raw++; + } + }else{ /* inter using last frame as reference */ + int xoffset = (buf[i] & 0xF) - 7; + int yoffset = ((buf[i] >> 4)) - 7; + if (s->last_frame->data[0]) + cmv_motcomp(frame->data[0], frame->linesize[0], + s->last_frame->data[0], s->last_frame->linesize[0], + x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height); + } + i++; + } +} + +static void cmv_process_header(CmvContext *s, const uint8_t *buf, const uint8_t *buf_end) +{ + int pal_start, pal_count, i; + + if(buf_end - buf < 16) { + av_log(s->avctx, AV_LOG_WARNING, "truncated header\n"); + return; + } + + s->width = AV_RL16(&buf[4]); + s->height = AV_RL16(&buf[6]); + if (s->avctx->width!=s->width || s->avctx->height!=s->height) { + avcodec_set_dimensions(s->avctx, s->width, s->height); + av_frame_unref(s->last_frame); + av_frame_unref(s->last2_frame); + } + + s->avctx->time_base.num = 1; + s->avctx->time_base.den = AV_RL16(&buf[10]); + + pal_start = AV_RL16(&buf[12]); + pal_count = AV_RL16(&buf[14]); + + buf += 16; + for (i=pal_start; i= 3; i++) { + s->palette[i] = 0xFFU << 24 | AV_RB24(buf); + buf += 3; + } +} + +#define EA_PREAMBLE_SIZE 8 +#define MVIh_TAG MKTAG('M', 'V', 'I', 'h') + +static int cmv_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + CmvContext *s = avctx->priv_data; + const uint8_t *buf_end = buf + buf_size; + AVFrame *frame = data; + int ret; + + if (buf_end - buf < EA_PREAMBLE_SIZE) + return AVERROR_INVALIDDATA; + + if (AV_RL32(buf)==MVIh_TAG||AV_RB32(buf)==MVIh_TAG) { + unsigned size = AV_RL32(buf + 4); + cmv_process_header(s, buf+EA_PREAMBLE_SIZE, buf_end); + if (size > buf_end - buf - EA_PREAMBLE_SIZE) + return -1; + buf += size; + } + + if (av_image_check_size(s->width, s->height, 0, s->avctx)) + return -1; + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + memcpy(frame->data[1], s->palette, AVPALETTE_SIZE); + + buf += EA_PREAMBLE_SIZE; + if ((buf[0]&1)) { // subtype + cmv_decode_inter(s, frame, buf+2, buf_end); + frame->key_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_P; + }else{ + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + cmv_decode_intra(s, frame, buf+2, buf_end); + } + + av_frame_unref(s->last2_frame); + av_frame_move_ref(s->last2_frame, s->last_frame); + if ((ret = av_frame_ref(s->last_frame, frame)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int cmv_decode_end(AVCodecContext *avctx){ + CmvContext *s = avctx->priv_data; + + av_frame_free(&s->last_frame); + av_frame_free(&s->last2_frame); + + return 0; +} + +AVCodec ff_eacmv_decoder = { + .name = "eacmv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CMV, + .priv_data_size = sizeof(CmvContext), + .init = cmv_decode_init, + .close = cmv_decode_end, + .decode = cmv_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts CMV video"), +}; diff --git a/ffmpeg/libavcodec/eaidct.c b/ffmpeg/libavcodec/eaidct.c new file mode 100644 index 0000000..e4840f2 --- /dev/null +++ b/ffmpeg/libavcodec/eaidct.c @@ -0,0 +1,88 @@ +/* + * Electronic Arts TGQ/TQI/MAD IDCT algorithm + * Copyright (c) 2007-2008 Peter Ross + * + * 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 + */ + +/** + * @file + * Electronic Arts TGQ/TQI/MAD IDCT algorithm + * @author Peter Ross + */ + +#include "eaidct.h" +#include "libavutil/common.h" + +#define ASQRT 181 /* (1/sqrt(2))<<8 */ +#define A4 669 /* cos(pi/8)*sqrt(2)<<9 */ +#define A2 277 /* sin(pi/8)*sqrt(2)<<9 */ +#define A5 196 /* sin(pi/8)<<9 */ + +#define IDCT_TRANSFORM(dest,s0,s1,s2,s3,s4,s5,s6,s7,d0,d1,d2,d3,d4,d5,d6,d7,munge,src) {\ + const int a1 = (src)[s1] + (src)[s7]; \ + const int a7 = (src)[s1] - (src)[s7]; \ + const int a5 = (src)[s5] + (src)[s3]; \ + const int a3 = (src)[s5] - (src)[s3]; \ + const int a2 = (src)[s2] + (src)[s6]; \ + const int a6 = (ASQRT*((src)[s2] - (src)[s6]))>>8; \ + const int a0 = (src)[s0] + (src)[s4]; \ + const int a4 = (src)[s0] - (src)[s4]; \ + const int b0 = (((A4-A5)*a7 - A5*a3)>>9) + a1+a5; \ + const int b1 = (((A4-A5)*a7 - A5*a3)>>9) + ((ASQRT*(a1-a5))>>8); \ + const int b2 = (((A2+A5)*a3 + A5*a7)>>9) + ((ASQRT*(a1-a5))>>8); \ + const int b3 = ((A2+A5)*a3 + A5*a7)>>9; \ + (dest)[d0] = munge(a0+a2+a6+b0); \ + (dest)[d1] = munge(a4+a6 +b1); \ + (dest)[d2] = munge(a4-a6 +b2); \ + (dest)[d3] = munge(a0-a2-a6+b3); \ + (dest)[d4] = munge(a0-a2-a6-b3); \ + (dest)[d5] = munge(a4-a6 -b2); \ + (dest)[d6] = munge(a4+a6 -b1); \ + (dest)[d7] = munge(a0+a2+a6-b0); \ +} +/* end IDCT_TRANSFORM macro */ + +#define MUNGE_NONE(x) (x) +#define IDCT_COL(dest,src) IDCT_TRANSFORM(dest,0,8,16,24,32,40,48,56,0,8,16,24,32,40,48,56,MUNGE_NONE,src) + +#define MUNGE_8BIT(x) av_clip_uint8((x)>>4) +#define IDCT_ROW(dest,src) IDCT_TRANSFORM(dest,0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7,MUNGE_8BIT,src) + +static inline void ea_idct_col(int16_t *dest, const int16_t *src) { + if ((src[8]|src[16]|src[24]|src[32]|src[40]|src[48]|src[56])==0) { + dest[0] = + dest[8] = + dest[16] = + dest[24] = + dest[32] = + dest[40] = + dest[48] = + dest[56] = src[0]; + }else + IDCT_COL(dest, src); +} + +void ff_ea_idct_put_c(uint8_t *dest, int linesize, int16_t *block) { + int i; + int16_t temp[64]; + block[0] += 4; + for (i=0; i<8; i++) + ea_idct_col(&temp[i], &block[i]); + for (i=0; i<8; i++) + IDCT_ROW( (&dest[i*linesize]), (&temp[8*i]) ); +} diff --git a/ffmpeg/libavcodec/eaidct.h b/ffmpeg/libavcodec/eaidct.h new file mode 100644 index 0000000..6b9ec1c --- /dev/null +++ b/ffmpeg/libavcodec/eaidct.h @@ -0,0 +1,26 @@ +/* + * 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 + */ + +#ifndef AVCODEC_EAIDCT_H +#define AVCODEC_EAIDCT_H + +#include + +void ff_ea_idct_put_c(uint8_t *dest, int linesize, int16_t *block); + +#endif /* AVCODEC_EAIDCT_H */ diff --git a/ffmpeg/libavcodec/eamad.c b/ffmpeg/libavcodec/eamad.c new file mode 100644 index 0000000..58cdea6 --- /dev/null +++ b/ffmpeg/libavcodec/eamad.c @@ -0,0 +1,327 @@ +/* + * Electronic Arts Madcow Video Decoder + * Copyright (c) 2007-2009 Peter Ross + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Electronic Arts Madcow Video Decoder + * @author Peter Ross + * + * @see technical details at + * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_MAD + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "aandcttab.h" +#include "eaidct.h" +#include "internal.h" +#include "mpeg12.h" +#include "mpeg12data.h" +#include "libavutil/imgutils.h" + +#define EA_PREAMBLE_SIZE 8 +#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD i-frame */ +#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD p-frame */ +#define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ + +typedef struct MadContext { + AVCodecContext *avctx; + DSPContext dsp; + AVFrame last_frame; + GetBitContext gb; + void *bitstream_buf; + unsigned int bitstream_buf_size; + DECLARE_ALIGNED(16, int16_t, block)[64]; + ScanTable scantable; + uint16_t quant_matrix[64]; + int mb_x; + int mb_y; +} MadContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + MadContext *s = avctx->priv_data; + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + ff_dsputil_init(&s->dsp, avctx); + ff_init_scantable_permutation(s->dsp.idct_permutation, FF_NO_IDCT_PERM); + ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); + ff_mpeg12_init_vlcs(); + return 0; +} + +static inline void comp(unsigned char *dst, int dst_stride, + unsigned char *src, int src_stride, int add) +{ + int j, i; + for (j=0; j<8; j++) + for (i=0; i<8; i++) + dst[j*dst_stride + i] = av_clip_uint8(src[j*src_stride + i] + add); +} + +static inline void comp_block(MadContext *t, AVFrame *frame, + int mb_x, int mb_y, + int j, int mv_x, int mv_y, int add) +{ + if (j < 4) { + unsigned offset = (mb_y*16 + ((j&2)<<2) + mv_y)*t->last_frame.linesize[0] + mb_x*16 + ((j&1)<<3) + mv_x; + if (offset >= (t->avctx->height - 7) * t->last_frame.linesize[0] - 7) + return; + comp(frame->data[0] + (mb_y*16 + ((j&2)<<2))*frame->linesize[0] + mb_x*16 + ((j&1)<<3), + frame->linesize[0], + t->last_frame.data[0] + offset, + t->last_frame.linesize[0], add); + } else if (!(t->avctx->flags & CODEC_FLAG_GRAY)) { + int index = j - 3; + unsigned offset = (mb_y * 8 + (mv_y/2))*t->last_frame.linesize[index] + mb_x * 8 + (mv_x/2); + if (offset >= (t->avctx->height/2 - 7) * t->last_frame.linesize[index] - 7) + return; + comp(frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x * 8, + frame->linesize[index], + t->last_frame.data[index] + offset, + t->last_frame.linesize[index], add); + } +} + +static inline void idct_put(MadContext *t, AVFrame *frame, int16_t *block, + int mb_x, int mb_y, int j) +{ + if (j < 4) { + ff_ea_idct_put_c( + frame->data[0] + (mb_y*16 + ((j&2)<<2))*frame->linesize[0] + mb_x*16 + ((j&1)<<3), + frame->linesize[0], block); + } else if (!(t->avctx->flags & CODEC_FLAG_GRAY)) { + int index = j - 3; + ff_ea_idct_put_c( + frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x*8, + frame->linesize[index], block); + } +} + +static inline int decode_block_intra(MadContext *s, int16_t * block) +{ + int level, i, j, run; + RLTable *rl = &ff_rl_mpeg1; + const uint8_t *scantable = s->scantable.permutated; + int16_t *quant_matrix = s->quant_matrix; + + block[0] = (128 + get_sbits(&s->gb, 8)) * quant_matrix[0]; + + /* The RL decoder is derived from mpeg1_decode_block_intra; + Escaped level and run values a decoded differently */ + i = 0; + { + OPEN_READER(re, &s->gb); + /* now quantify & encode AC coefficients */ + for (;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level == 127) { + break; + } else if (level != 0) { + i += run; + j = scantable[i]; + level = (level*quant_matrix[j]) >> 4; + level = (level-1)|1; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 10); SKIP_BITS(re, &s->gb, 10); + + UPDATE_CACHE(re, &s->gb); + run = SHOW_UBITS(re, &s->gb, 6)+1; LAST_SKIP_BITS(re, &s->gb, 6); + + i += run; + j = scantable[i]; + if (level < 0) { + level = -level; + level = (level*quant_matrix[j]) >> 4; + level = (level-1)|1; + level = -level; + } else { + level = (level*quant_matrix[j]) >> 4; + level = (level-1)|1; + } + } + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + block[j] = level; + } + CLOSE_READER(re, &s->gb); + } + return 0; +} + +static int decode_motion(GetBitContext *gb) +{ + int value = 0; + if (get_bits1(gb)) { + if (get_bits1(gb)) + value = -17; + value += get_bits(gb, 4) + 1; + } + return value; +} + +static int decode_mb(MadContext *s, AVFrame *frame, int inter) +{ + int mv_map = 0; + int mv_x, mv_y; + int j; + + if (inter) { + int v = decode210(&s->gb); + if (v < 2) { + mv_map = v ? get_bits(&s->gb, 6) : 63; + mv_x = decode_motion(&s->gb); + mv_y = decode_motion(&s->gb); + } + } + + for (j=0; j<6; j++) { + if (mv_map & (1<gb); + if (s->last_frame.data[0]) + comp_block(s, frame, s->mb_x, s->mb_y, j, mv_x, mv_y, add); + } else { + s->dsp.clear_block(s->block); + if(decode_block_intra(s, s->block) < 0) + return -1; + idct_put(s, frame, s->block, s->mb_x, s->mb_y, j); + } + } + return 0; +} + +static void calc_quant_matrix(MadContext *s, int qscale) +{ + int i; + + s->quant_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0]) >> 11; + for (i=1; i<64; i++) + s->quant_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32) >> 10; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end = buf+buf_size; + MadContext *s = avctx->priv_data; + AVFrame *frame = data; + int width, height; + int chunk_type; + int inter, ret; + + if (buf_size < 26) { + av_log(avctx, AV_LOG_ERROR, "Input buffer too small\n"); + *got_frame = 0; + return AVERROR_INVALIDDATA; + } + + chunk_type = AV_RL32(&buf[0]); + inter = (chunk_type == MADm_TAG || chunk_type == MADe_TAG); + buf += 8; + + av_reduce(&avctx->time_base.num, &avctx->time_base.den, + AV_RL16(&buf[6]), 1000, 1<<30); + + width = AV_RL16(&buf[8]); + height = AV_RL16(&buf[10]); + calc_quant_matrix(s, buf[13]); + buf += 16; + + if (avctx->width != width || avctx->height != height) { + if((width * height)/2048*7 > buf_end-buf) + return AVERROR_INVALIDDATA; + if ((ret = av_image_check_size(width, height, 0, avctx)) < 0) + return ret; + avcodec_set_dimensions(avctx, width, height); + av_frame_unref(&s->last_frame); + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if (inter && !s->last_frame.data[0]) { + av_log(avctx, AV_LOG_WARNING, "Missing reference frame.\n"); + ret = ff_get_buffer(avctx, &s->last_frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) + return ret; + memset(s->last_frame.data[0], 0, s->last_frame.height * + s->last_frame.linesize[0]); + memset(s->last_frame.data[1], 0x80, s->last_frame.height / 2 * + s->last_frame.linesize[1]); + memset(s->last_frame.data[2], 0x80, s->last_frame.height / 2 * + s->last_frame.linesize[2]); + } + + av_fast_padded_malloc(&s->bitstream_buf, &s->bitstream_buf_size, + buf_end - buf); + if (!s->bitstream_buf) + return AVERROR(ENOMEM); + s->dsp.bswap16_buf(s->bitstream_buf, (const uint16_t*)buf, (buf_end-buf)/2); + memset((uint8_t*)s->bitstream_buf + (buf_end-buf), 0, FF_INPUT_BUFFER_PADDING_SIZE); + init_get_bits(&s->gb, s->bitstream_buf, 8*(buf_end-buf)); + + for (s->mb_y=0; s->mb_y < (avctx->height+15)/16; s->mb_y++) + for (s->mb_x=0; s->mb_x < (avctx->width +15)/16; s->mb_x++) + if(decode_mb(s, frame, inter) < 0) + return AVERROR_INVALIDDATA; + + *got_frame = 1; + + if (chunk_type != MADe_TAG) { + av_frame_unref(&s->last_frame); + if ((ret = av_frame_ref(&s->last_frame, frame)) < 0) + return ret; + } + + return buf_size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + MadContext *t = avctx->priv_data; + av_frame_unref(&t->last_frame); + av_free(t->bitstream_buf); + return 0; +} + +AVCodec ff_eamad_decoder = { + .name = "eamad", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MAD, + .priv_data_size = sizeof(MadContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Madcow Video") +}; diff --git a/ffmpeg/libavcodec/eatgq.c b/ffmpeg/libavcodec/eatgq.c new file mode 100644 index 0000000..cf93c06 --- /dev/null +++ b/ffmpeg/libavcodec/eatgq.c @@ -0,0 +1,252 @@ +/* + * Electronic Arts TGQ Video Decoder + * Copyright (c) 2007-2008 Peter Ross + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Electronic Arts TGQ Video Decoder + * @author Peter Ross + * + * Technical details here: + * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGQ + */ + +#include "avcodec.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "bytestream.h" +#include "dsputil.h" +#include "aandcttab.h" +#include "eaidct.h" +#include "internal.h" + +typedef struct TgqContext { + AVCodecContext *avctx; + int width, height; + ScanTable scantable; + int qtable[64]; + DECLARE_ALIGNED(16, int16_t, block)[6][64]; + GetByteContext gb; +} TgqContext; + +static av_cold int tgq_decode_init(AVCodecContext *avctx) +{ + TgqContext *s = avctx->priv_data; + uint8_t idct_permutation[64]; + s->avctx = avctx; + ff_init_scantable_permutation(idct_permutation, FF_NO_IDCT_PERM); + ff_init_scantable(idct_permutation, &s->scantable, ff_zigzag_direct); + avctx->time_base = (AVRational){1, 15}; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + return 0; +} + +static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb) +{ + uint8_t *perm = s->scantable.permutated; + int i, j, value; + block[0] = get_sbits(gb, 8) * s->qtable[0]; + for (i = 1; i < 64;) { + switch (show_bits(gb, 3)) { + case 4: + block[perm[i++]] = 0; + case 0: + block[perm[i++]] = 0; + skip_bits(gb, 3); + break; + case 5: + case 1: + skip_bits(gb, 2); + value = get_bits(gb, 6); + for (j = 0; j < value; j++) + block[perm[i++]] = 0; + break; + case 6: + skip_bits(gb, 3); + block[perm[i]] = -s->qtable[perm[i]]; + i++; + break; + case 2: + skip_bits(gb, 3); + block[perm[i]] = s->qtable[perm[i]]; + i++; + break; + case 7: // 111b + case 3: // 011b + skip_bits(gb, 2); + if (show_bits(gb, 6) == 0x3F) { + skip_bits(gb, 6); + block[perm[i]] = get_sbits(gb, 8) * s->qtable[perm[i]]; + } else { + block[perm[i]] = get_sbits(gb, 6) * s->qtable[perm[i]]; + } + i++; + break; + } + } + block[0] += 128 << 4; +} + +static void tgq_idct_put_mb(TgqContext *s, int16_t (*block)[64], AVFrame *frame, + int mb_x, int mb_y) +{ + int linesize = frame->linesize[0]; + uint8_t *dest_y = frame->data[0] + (mb_y * 16 * linesize) + mb_x * 16; + uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; + uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; + + ff_ea_idct_put_c(dest_y , linesize, block[0]); + ff_ea_idct_put_c(dest_y + 8, linesize, block[1]); + ff_ea_idct_put_c(dest_y + 8 * linesize , linesize, block[2]); + ff_ea_idct_put_c(dest_y + 8 * linesize + 8, linesize, block[3]); + if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { + ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]); + ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]); + } +} + +static inline void tgq_dconly(TgqContext *s, unsigned char *dst, + int dst_stride, int dc) +{ + int level = av_clip_uint8((dc*s->qtable[0] + 2056) >> 4); + int j; + for (j = 0; j < 8; j++) + memset(dst + j * dst_stride, level, 8); +} + +static void tgq_idct_put_mb_dconly(TgqContext *s, AVFrame *frame, + int mb_x, int mb_y, const int8_t *dc) +{ + int linesize = frame->linesize[0]; + uint8_t *dest_y = frame->data[0] + (mb_y * 16 * linesize) + mb_x * 16; + uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; + uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; + tgq_dconly(s, dest_y, linesize, dc[0]); + tgq_dconly(s, dest_y + 8, linesize, dc[1]); + tgq_dconly(s, dest_y + 8 * linesize, linesize, dc[2]); + tgq_dconly(s, dest_y + 8 * linesize + 8, linesize, dc[3]); + if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { + tgq_dconly(s, dest_cb, frame->linesize[1], dc[4]); + tgq_dconly(s, dest_cr, frame->linesize[2], dc[5]); + } +} + +static int tgq_decode_mb(TgqContext *s, AVFrame *frame, int mb_y, int mb_x) +{ + int mode; + int i; + int8_t dc[6]; + + mode = bytestream2_get_byte(&s->gb); + if (mode > 12) { + GetBitContext gb; + init_get_bits(&gb, s->gb.buffer, FFMIN(bytestream2_get_bytes_left(&s->gb), mode) * 8); + for (i = 0; i < 6; i++) + tgq_decode_block(s, s->block[i], &gb); + tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y); + bytestream2_skip(&s->gb, mode); + } else { + if (mode == 3) { + memset(dc, bytestream2_get_byte(&s->gb), 4); + dc[4] = bytestream2_get_byte(&s->gb); + dc[5] = bytestream2_get_byte(&s->gb); + } else if (mode == 6) { + bytestream2_get_buffer(&s->gb, dc, 6); + } else if (mode == 12) { + for (i = 0; i < 6; i++) { + dc[i] = bytestream2_get_byte(&s->gb); + bytestream2_skip(&s->gb, 1); + } + } else { + av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode); + return -1; + } + tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc); + } + return 0; +} + +static void tgq_calculate_qtable(TgqContext *s, int quant) +{ + int i, j; + const int a = (14 * (100 - quant)) / 100 + 1; + const int b = (11 * (100 - quant)) / 100 + 4; + for (j = 0; j < 8; j++) + for (i = 0; i < 8; i++) + s->qtable[j * 8 + i] = ((a * (j + i) / (7 + 7) + b) * + ff_inv_aanscales[j * 8 + i]) >> (14 - 4); +} + +static int tgq_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + TgqContext *s = avctx->priv_data; + AVFrame *frame = data; + int x, y, ret; + int big_endian; + + if (buf_size < 16) { + av_log(avctx, AV_LOG_WARNING, "truncated header\n"); + return AVERROR_INVALIDDATA; + } + big_endian = AV_RL32(&buf[4]) > 0x000FFFFF; + bytestream2_init(&s->gb, buf + 8, buf_size - 8); + if (big_endian) { + s->width = bytestream2_get_be16u(&s->gb); + s->height = bytestream2_get_be16u(&s->gb); + } else { + s->width = bytestream2_get_le16u(&s->gb); + s->height = bytestream2_get_le16u(&s->gb); + } + + if (s->avctx->width!=s->width || s->avctx->height!=s->height) { + avcodec_set_dimensions(s->avctx, s->width, s->height); + } + tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb)); + bytestream2_skip(&s->gb, 3); + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + + for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++) + for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++) + if (tgq_decode_mb(s, frame, y, x) < 0) + return AVERROR_INVALIDDATA; + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_eatgq_decoder = { + .name = "eatgq", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TGQ, + .priv_data_size = sizeof(TgqContext), + .init = tgq_decode_init, + .decode = tgq_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"), +}; diff --git a/ffmpeg/libavcodec/eatgv.c b/ffmpeg/libavcodec/eatgv.c new file mode 100644 index 0000000..54074b3 --- /dev/null +++ b/ffmpeg/libavcodec/eatgv.c @@ -0,0 +1,358 @@ +/* + * Electronic Arts TGV Video Decoder + * Copyright (c) 2007-2008 Peter Ross + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Electronic Arts TGV Video Decoder + * by Peter Ross (pross@xvid.org) + * + * Technical details here: + * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGV + */ + +#include "avcodec.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" + +#define EA_PREAMBLE_SIZE 8 +#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') + +typedef struct TgvContext { + AVCodecContext *avctx; + AVFrame last_frame; + uint8_t *frame_buffer; + int width,height; + uint32_t palette[AVPALETTE_COUNT]; + + int (*mv_codebook)[2]; + uint8_t (*block_codebook)[16]; + int num_mvs; ///< current length of mv_codebook + int num_blocks_packed; ///< current length of block_codebook +} TgvContext; + +static av_cold int tgv_decode_init(AVCodecContext *avctx) +{ + TgvContext *s = avctx->priv_data; + s->avctx = avctx; + avctx->time_base = (AVRational){1, 15}; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + avcodec_get_frame_defaults(&s->last_frame); + return 0; +} + +/** + * Unpack buffer + * @return 0 on success, -1 on critical buffer underflow + */ +static int unpack(const uint8_t *src, const uint8_t *src_end, + uint8_t *dst, int width, int height) +{ + uint8_t *dst_end = dst + width*height; + int size, size1, size2, offset, run; + uint8_t *dst_start = dst; + + if (src[0] & 0x01) + src += 5; + else + src += 2; + + if (src_end - src < 3) + return AVERROR_INVALIDDATA; + size = AV_RB24(src); + src += 3; + + while (size > 0 && src < src_end) { + + /* determine size1 and size2 */ + size1 = (src[0] & 3); + if (src[0] & 0x80) { // 1 + if (src[0] & 0x40 ) { // 11 + if (src[0] & 0x20) { // 111 + if (src[0] < 0xFC) // !(111111) + size1 = (((src[0] & 31) + 1) << 2); + src++; + size2 = 0; + } else { // 110 + offset = ((src[0] & 0x10) << 12) + AV_RB16(&src[1]) + 1; + size2 = ((src[0] & 0xC) << 6) + src[3] + 5; + src += 4; + } + } else { // 10 + size1 = ((src[1] & 0xC0) >> 6); + offset = (AV_RB16(&src[1]) & 0x3FFF) + 1; + size2 = (src[0] & 0x3F) + 4; + src += 3; + } + } else { // 0 + offset = ((src[0] & 0x60) << 3) + src[1] + 1; + size2 = ((src[0] & 0x1C) >> 2) + 3; + src += 2; + } + + + /* fetch strip from src */ + if (size1 > src_end - src) + break; + + if (size1 > 0) { + size -= size1; + run = FFMIN(size1, dst_end - dst); + memcpy(dst, src, run); + dst += run; + src += run; + } + + if (size2 > 0) { + if (dst - dst_start < offset) + return 0; + size -= size2; + run = FFMIN(size2, dst_end - dst); + av_memcpy_backptr(dst, offset, run); + dst += run; + } + } + + return 0; +} + +/** + * Decode inter-frame + * @return 0 on success, -1 on critical buffer underflow + */ +static int tgv_decode_inter(TgvContext *s, AVFrame *frame, + const uint8_t *buf, const uint8_t *buf_end) +{ + int num_mvs; + int num_blocks_raw; + int num_blocks_packed; + int vector_bits; + int i,j,x,y; + GetBitContext gb; + int mvbits; + const uint8_t *blocks_raw; + + if(buf_end - buf < 12) + return AVERROR_INVALIDDATA; + + num_mvs = AV_RL16(&buf[0]); + num_blocks_raw = AV_RL16(&buf[2]); + num_blocks_packed = AV_RL16(&buf[4]); + vector_bits = AV_RL16(&buf[6]); + buf += 12; + + if (vector_bits > MIN_CACHE_BITS || !vector_bits) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid value for motion vector bits: %d\n", vector_bits); + return AVERROR_INVALIDDATA; + } + + /* allocate codebook buffers as necessary */ + if (num_mvs > s->num_mvs) { + s->mv_codebook = av_realloc(s->mv_codebook, num_mvs*2*sizeof(int)); + s->num_mvs = num_mvs; + } + + if (num_blocks_packed > s->num_blocks_packed) { + s->block_codebook = av_realloc(s->block_codebook, num_blocks_packed*16); + s->num_blocks_packed = num_blocks_packed; + } + + /* read motion vectors */ + mvbits = (num_mvs * 2 * 10 + 31) & ~31; + + if (buf_end - buf < (mvbits>>3) + 16*num_blocks_raw + 8*num_blocks_packed) + return AVERROR_INVALIDDATA; + + init_get_bits(&gb, buf, mvbits); + for (i = 0; i < num_mvs; i++) { + s->mv_codebook[i][0] = get_sbits(&gb, 10); + s->mv_codebook[i][1] = get_sbits(&gb, 10); + } + buf += mvbits >> 3; + + /* note ptr to uncompressed blocks */ + blocks_raw = buf; + buf += num_blocks_raw * 16; + + /* read compressed blocks */ + init_get_bits(&gb, buf, (buf_end - buf) << 3); + for (i = 0; i < num_blocks_packed; i++) { + int tmp[4]; + for (j = 0; j < 4; j++) + tmp[j] = get_bits(&gb, 8); + for (j = 0; j < 16; j++) + s->block_codebook[i][15-j] = tmp[get_bits(&gb, 2)]; + } + + if (get_bits_left(&gb) < vector_bits * + (s->avctx->height / 4) * (s->avctx->width / 4)) + return AVERROR_INVALIDDATA; + + /* read vectors and build frame */ + for (y = 0; y < s->avctx->height / 4; y++) + for (x = 0; x < s->avctx->width / 4; x++) { + unsigned int vector = get_bits(&gb, vector_bits); + const uint8_t *src; + int src_stride; + + if (vector < num_mvs) { + int mx = x * 4 + s->mv_codebook[vector][0]; + int my = y * 4 + s->mv_codebook[vector][1]; + + if (mx < 0 || mx + 4 > s->avctx->width || + my < 0 || my + 4 > s->avctx->height) { + av_log(s->avctx, AV_LOG_ERROR, "MV %d %d out of picture\n", mx, my); + continue; + } + + src = s->last_frame.data[0] + mx + my * s->last_frame.linesize[0]; + src_stride = s->last_frame.linesize[0]; + } else { + int offset = vector - num_mvs; + if (offset < num_blocks_raw) + src = blocks_raw + 16*offset; + else if (offset - num_blocks_raw < num_blocks_packed) + src = s->block_codebook[offset - num_blocks_raw]; + else + continue; + src_stride = 4; + } + + for (j = 0; j < 4; j++) + for (i = 0; i < 4; i++) + frame->data[0][(y * 4 + j) * frame->linesize[0] + (x * 4 + i)] = + src[j * src_stride + i]; + } + + return 0; +} + +static int tgv_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + TgvContext *s = avctx->priv_data; + const uint8_t *buf_end = buf + buf_size; + AVFrame *frame = data; + int chunk_type, ret; + + if (buf_end - buf < EA_PREAMBLE_SIZE) + return AVERROR_INVALIDDATA; + + chunk_type = AV_RL32(&buf[0]); + buf += EA_PREAMBLE_SIZE; + + if (chunk_type == kVGT_TAG) { + int pal_count, i; + if(buf_end - buf < 12) { + av_log(avctx, AV_LOG_WARNING, "truncated header\n"); + return AVERROR_INVALIDDATA; + } + + s->width = AV_RL16(&buf[0]); + s->height = AV_RL16(&buf[2]); + if (s->avctx->width != s->width || s->avctx->height != s->height) { + avcodec_set_dimensions(s->avctx, s->width, s->height); + av_freep(&s->frame_buffer); + av_frame_unref(&s->last_frame); + } + + pal_count = AV_RL16(&buf[6]); + buf += 12; + for(i = 0; i < pal_count && i < AVPALETTE_COUNT && buf_end - buf >= 3; i++) { + s->palette[i] = 0xFFU << 24 | AV_RB24(buf); + buf += 3; + } + } + + if ((ret = av_image_check_size(s->width, s->height, 0, avctx)) < 0) + return ret; + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + memcpy(frame->data[1], s->palette, AVPALETTE_SIZE); + + if (chunk_type == kVGT_TAG) { + int y; + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + + if (!s->frame_buffer && + !(s->frame_buffer = av_malloc(s->width * s->height))) + return AVERROR(ENOMEM); + + if (unpack(buf, buf_end, s->frame_buffer, s->avctx->width, s->avctx->height) < 0) { + av_log(avctx, AV_LOG_WARNING, "truncated intra frame\n"); + return AVERROR_INVALIDDATA; + } + for (y = 0; y < s->height; y++) + memcpy(frame->data[0] + y * frame->linesize[0], + s->frame_buffer + y * s->width, + s->width); + } else { + if (!s->last_frame.data[0]) { + av_log(avctx, AV_LOG_WARNING, "inter frame without corresponding intra frame\n"); + return buf_size; + } + frame->key_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_P; + if (tgv_decode_inter(s, frame, buf, buf_end) < 0) { + av_log(avctx, AV_LOG_WARNING, "truncated inter frame\n"); + return AVERROR_INVALIDDATA; + } + } + + av_frame_unref(&s->last_frame); + if ((ret = av_frame_ref(&s->last_frame, frame)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int tgv_decode_end(AVCodecContext *avctx) +{ + TgvContext *s = avctx->priv_data; + av_frame_unref(&s->last_frame); + av_freep(&s->frame_buffer); + av_free(s->mv_codebook); + av_free(s->block_codebook); + return 0; +} + +AVCodec ff_eatgv_decoder = { + .name = "eatgv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TGV, + .priv_data_size = sizeof(TgvContext), + .init = tgv_decode_init, + .close = tgv_decode_end, + .decode = tgv_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/eatqi.c b/ffmpeg/libavcodec/eatqi.c new file mode 100644 index 0000000..1484ddc --- /dev/null +++ b/ffmpeg/libavcodec/eatqi.c @@ -0,0 +1,158 @@ +/* + * Electronic Arts TQI Video Decoder + * Copyright (c) 2007-2009 Peter Ross + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Electronic Arts TQI Video Decoder + * @author Peter Ross + * @see http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TQI + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "aandcttab.h" +#include "eaidct.h" +#include "internal.h" +#include "mpeg12.h" +#include "mpegvideo.h" + +typedef struct TqiContext { + MpegEncContext s; + void *bitstream_buf; + unsigned int bitstream_buf_size; + DECLARE_ALIGNED(16, int16_t, block)[6][64]; +} TqiContext; + +static av_cold int tqi_decode_init(AVCodecContext *avctx) +{ + TqiContext *t = avctx->priv_data; + MpegEncContext *s = &t->s; + s->avctx = avctx; + ff_dsputil_init(&s->dsp, avctx); + ff_init_scantable_permutation(s->dsp.idct_permutation, FF_NO_IDCT_PERM); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); + s->qscale = 1; + avctx->time_base = (AVRational){1, 15}; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + ff_mpeg12_init_vlcs(); + return 0; +} + +static int tqi_decode_mb(MpegEncContext *s, int16_t (*block)[64]) +{ + int n; + s->dsp.clear_blocks(block[0]); + for (n=0; n<6; n++) + if (ff_mpeg1_decode_block_intra(s, block[n], n) < 0) + return -1; + + return 0; +} + +static inline void tqi_idct_put(TqiContext *t, AVFrame *frame, int16_t (*block)[64]) +{ + MpegEncContext *s = &t->s; + int linesize = frame->linesize[0]; + uint8_t *dest_y = frame->data[0] + (s->mb_y * 16* linesize ) + s->mb_x * 16; + uint8_t *dest_cb = frame->data[1] + (s->mb_y * 8 * frame->linesize[1]) + s->mb_x * 8; + uint8_t *dest_cr = frame->data[2] + (s->mb_y * 8 * frame->linesize[2]) + s->mb_x * 8; + + ff_ea_idct_put_c(dest_y , linesize, block[0]); + ff_ea_idct_put_c(dest_y + 8, linesize, block[1]); + ff_ea_idct_put_c(dest_y + 8*linesize , linesize, block[2]); + ff_ea_idct_put_c(dest_y + 8*linesize + 8, linesize, block[3]); + if(!(s->avctx->flags&CODEC_FLAG_GRAY)) { + ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]); + ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]); + } +} + +static void tqi_calculate_qtable(MpegEncContext *s, int quant) +{ + const int qscale = (215 - 2*quant)*5; + int i; + s->intra_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0])>>11; + for(i=1; i<64; i++) + s->intra_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32)>>14; +} + +static int tqi_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + const uint8_t *buf_end = buf+buf_size; + TqiContext *t = avctx->priv_data; + MpegEncContext *s = &t->s; + AVFrame *frame = data; + int ret; + + s->width = AV_RL16(&buf[0]); + s->height = AV_RL16(&buf[2]); + tqi_calculate_qtable(s, buf[4]); + buf += 8; + + if (s->avctx->width!=s->width || s->avctx->height!=s->height) + avcodec_set_dimensions(s->avctx, s->width, s->height); + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + av_fast_padded_malloc(&t->bitstream_buf, &t->bitstream_buf_size, + buf_end - buf); + if (!t->bitstream_buf) + return AVERROR(ENOMEM); + s->dsp.bswap_buf(t->bitstream_buf, (const uint32_t*)buf, (buf_end-buf)/4); + init_get_bits(&s->gb, t->bitstream_buf, 8*(buf_end-buf)); + + s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 0; + for (s->mb_y=0; s->mb_y<(avctx->height+15)/16; s->mb_y++) + for (s->mb_x=0; s->mb_x<(avctx->width+15)/16; s->mb_x++) + { + if (tqi_decode_mb(s, t->block) < 0) + goto end; + tqi_idct_put(t, frame, t->block); + } + end: + + *got_frame = 1; + return buf_size; +} + +static av_cold int tqi_decode_end(AVCodecContext *avctx) +{ + TqiContext *t = avctx->priv_data; + av_free(t->bitstream_buf); + return 0; +} + +AVCodec ff_eatqi_decoder = { + .name = "eatqi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TQI, + .priv_data_size = sizeof(TqiContext), + .init = tqi_decode_init, + .close = tqi_decode_end, + .decode = tqi_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TQI Video"), +}; diff --git a/ffmpeg/libavcodec/elbg.c b/ffmpeg/libavcodec/elbg.c new file mode 100644 index 0000000..2707599 --- /dev/null +++ b/ffmpeg/libavcodec/elbg.c @@ -0,0 +1,438 @@ +/* + * Copyright (C) 2007 Vitor Sessak + * + * 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 + */ + +/** + * @file + * Codebook Generator using the ELBG algorithm + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/lfg.h" +#include "elbg.h" +#include "avcodec.h" + +#define DELTA_ERR_MAX 0.1 ///< Precision of the ELBG algorithm (as percentual error) + +/** + * In the ELBG jargon, a cell is the set of points that are closest to a + * codebook entry. Not to be confused with a RoQ Video cell. */ +typedef struct cell_s { + int index; + struct cell_s *next; +} cell; + +/** + * ELBG internal data + */ +typedef struct{ + int error; + int dim; + int numCB; + int *codebook; + cell **cells; + int *utility; + int *utility_inc; + int *nearest_cb; + int *points; + AVLFG *rand_state; + int *scratchbuf; +} elbg_data; + +static inline int distance_limited(int *a, int *b, int dim, int limit) +{ + int i, dist=0; + for (i=0; i limit) + return INT_MAX; + } + + return dist; +} + +static inline void vect_division(int *res, int *vect, int div, int dim) +{ + int i; + if (div > 1) + for (i=0; inext) + error += distance_limited(centroid, elbg->points + cells->index*elbg->dim, elbg->dim, INT_MAX); + + return error; +} + +static int get_closest_codebook(elbg_data *elbg, int index) +{ + int i, pick=0, diff, diff_min = INT_MAX; + for (i=0; inumCB; i++) + if (i != index) { + diff = distance_limited(elbg->codebook + i*elbg->dim, elbg->codebook + index*elbg->dim, elbg->dim, diff_min); + if (diff < diff_min) { + pick = i; + diff_min = diff; + } + } + return pick; +} + +static int get_high_utility_cell(elbg_data *elbg) +{ + int i=0; + /* Using linear search, do binary if it ever turns to be speed critical */ + int r = av_lfg_get(elbg->rand_state)%elbg->utility_inc[elbg->numCB-1] + 1; + while (elbg->utility_inc[i] < r) + i++; + + av_assert2(elbg->cells[i]); + + return i; +} + +/** + * Implementation of the simple LBG algorithm for just two codebooks + */ +static int simple_lbg(elbg_data *elbg, + int dim, + int *centroid[3], + int newutility[3], + int *points, + cell *cells) +{ + int i, idx; + int numpoints[2] = {0,0}; + int *newcentroid[2] = { + elbg->scratchbuf + 3*dim, + elbg->scratchbuf + 4*dim + }; + cell *tempcell; + + memset(newcentroid[0], 0, 2 * dim * sizeof(*newcentroid[0])); + + newutility[0] = + newutility[1] = 0; + + for (tempcell = cells; tempcell; tempcell=tempcell->next) { + idx = distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX)>= + distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX); + numpoints[idx]++; + for (i=0; iindex*dim + i]; + } + + vect_division(centroid[0], newcentroid[0], numpoints[0], dim); + vect_division(centroid[1], newcentroid[1], numpoints[1], dim); + + for (tempcell = cells; tempcell; tempcell=tempcell->next) { + int dist[2] = {distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX), + distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX)}; + int idx = dist[0] > dist[1]; + newutility[idx] += dist[idx]; + } + + return newutility[0] + newutility[1]; +} + +static void get_new_centroids(elbg_data *elbg, int huc, int *newcentroid_i, + int *newcentroid_p) +{ + cell *tempcell; + int *min = newcentroid_i; + int *max = newcentroid_p; + int i; + + for (i=0; i< elbg->dim; i++) { + min[i]=INT_MAX; + max[i]=0; + } + + for (tempcell = elbg->cells[huc]; tempcell; tempcell = tempcell->next) + for(i=0; idim; i++) { + min[i]=FFMIN(min[i], elbg->points[tempcell->index*elbg->dim + i]); + max[i]=FFMAX(max[i], elbg->points[tempcell->index*elbg->dim + i]); + } + + for (i=0; idim; i++) { + int ni = min[i] + (max[i] - min[i])/3; + int np = min[i] + (2*(max[i] - min[i]))/3; + newcentroid_i[i] = ni; + newcentroid_p[i] = np; + } +} + +/** + * Add the points in the low utility cell to its closest cell. Split the high + * utility cell, putting the separate points in the (now empty) low utility + * cell. + * + * @param elbg Internal elbg data + * @param indexes {luc, huc, cluc} + * @param newcentroid A vector with the position of the new centroids + */ +static void shift_codebook(elbg_data *elbg, int *indexes, + int *newcentroid[3]) +{ + cell *tempdata; + cell **pp = &elbg->cells[indexes[2]]; + + while(*pp) + pp= &(*pp)->next; + + *pp = elbg->cells[indexes[0]]; + + elbg->cells[indexes[0]] = NULL; + tempdata = elbg->cells[indexes[1]]; + elbg->cells[indexes[1]] = NULL; + + while(tempdata) { + cell *tempcell2 = tempdata->next; + int idx = distance_limited(elbg->points + tempdata->index*elbg->dim, + newcentroid[0], elbg->dim, INT_MAX) > + distance_limited(elbg->points + tempdata->index*elbg->dim, + newcentroid[1], elbg->dim, INT_MAX); + + tempdata->next = elbg->cells[indexes[idx]]; + elbg->cells[indexes[idx]] = tempdata; + tempdata = tempcell2; + } +} + +static void evaluate_utility_inc(elbg_data *elbg) +{ + int i, inc=0; + + for (i=0; i < elbg->numCB; i++) { + if (elbg->numCB*elbg->utility[i] > elbg->error) + inc += elbg->utility[i]; + elbg->utility_inc[i] = inc; + } +} + + +static void update_utility_and_n_cb(elbg_data *elbg, int idx, int newutility) +{ + cell *tempcell; + + elbg->utility[idx] = newutility; + for (tempcell=elbg->cells[idx]; tempcell; tempcell=tempcell->next) + elbg->nearest_cb[tempcell->index] = idx; +} + +/** + * Evaluate if a shift lower the error. If it does, call shift_codebooks + * and update elbg->error, elbg->utility and elbg->nearest_cb. + * + * @param elbg Internal elbg data + * @param idx {luc (low utility cell, huc (high utility cell), cluc (closest cell to low utility cell)} + */ +static void try_shift_candidate(elbg_data *elbg, int idx[3]) +{ + int j, k, olderror=0, newerror, cont=0; + int newutility[3]; + int *newcentroid[3] = { + elbg->scratchbuf, + elbg->scratchbuf + elbg->dim, + elbg->scratchbuf + 2*elbg->dim + }; + cell *tempcell; + + for (j=0; j<3; j++) + olderror += elbg->utility[idx[j]]; + + memset(newcentroid[2], 0, elbg->dim*sizeof(int)); + + for (k=0; k<2; k++) + for (tempcell=elbg->cells[idx[2*k]]; tempcell; tempcell=tempcell->next) { + cont++; + for (j=0; jdim; j++) + newcentroid[2][j] += elbg->points[tempcell->index*elbg->dim + j]; + } + + vect_division(newcentroid[2], newcentroid[2], cont, elbg->dim); + + get_new_centroids(elbg, idx[1], newcentroid[0], newcentroid[1]); + + newutility[2] = eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[0]]); + newutility[2] += eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[2]]); + + newerror = newutility[2]; + + newerror += simple_lbg(elbg, elbg->dim, newcentroid, newutility, elbg->points, + elbg->cells[idx[1]]); + + if (olderror > newerror) { + shift_codebook(elbg, idx, newcentroid); + + elbg->error += newerror - olderror; + + for (j=0; j<3; j++) + update_utility_and_n_cb(elbg, idx[j], newutility[j]); + + evaluate_utility_inc(elbg); + } + } + +/** + * Implementation of the ELBG block + */ +static void do_shiftings(elbg_data *elbg) +{ + int idx[3]; + + evaluate_utility_inc(elbg); + + for (idx[0]=0; idx[0] < elbg->numCB; idx[0]++) + if (elbg->numCB*elbg->utility[idx[0]] < elbg->error) { + if (elbg->utility_inc[elbg->numCB-1] == 0) + return; + + idx[1] = get_high_utility_cell(elbg); + idx[2] = get_closest_codebook(elbg, idx[0]); + + if (idx[1] != idx[0] && idx[1] != idx[2]) + try_shift_candidate(elbg, idx); + } +} + +#define BIG_PRIME 433494437LL + +void ff_init_elbg(int *points, int dim, int numpoints, int *codebook, + int numCB, int max_steps, int *closest_cb, + AVLFG *rand_state) +{ + int i, k; + + if (numpoints > 24*numCB) { + /* ELBG is very costly for a big number of points. So if we have a lot + of them, get a good initial codebook to save on iterations */ + int *temp_points = av_malloc(dim*(numpoints/8)*sizeof(int)); + for (i=0; ierror = INT_MAX; + elbg->dim = dim; + elbg->numCB = numCB; + elbg->codebook = codebook; + elbg->cells = av_malloc(numCB*sizeof(cell *)); + elbg->utility = av_malloc(numCB*sizeof(int)); + elbg->nearest_cb = closest_cb; + elbg->points = points; + elbg->utility_inc = av_malloc(numCB*sizeof(int)); + elbg->scratchbuf = av_malloc(5*dim*sizeof(int)); + + elbg->rand_state = rand_state; + + do { + free_cells = list_buffer; + last_error = elbg->error; + steps++; + memset(elbg->utility, 0, numCB*sizeof(int)); + memset(elbg->cells, 0, numCB*sizeof(cell *)); + + elbg->error = 0; + + /* This loop evaluate the actual Voronoi partition. It is the most + costly part of the algorithm. */ + for (i=0; i < numpoints; i++) { + best_dist = distance_limited(elbg->points + i*elbg->dim, elbg->codebook + best_idx*elbg->dim, dim, INT_MAX); + for (k=0; k < elbg->numCB; k++) { + dist = distance_limited(elbg->points + i*elbg->dim, elbg->codebook + k*elbg->dim, dim, best_dist); + if (dist < best_dist) { + best_dist = dist; + best_idx = k; + } + } + elbg->nearest_cb[i] = best_idx; + dist_cb[i] = best_dist; + elbg->error += dist_cb[i]; + elbg->utility[elbg->nearest_cb[i]] += dist_cb[i]; + free_cells->index = i; + free_cells->next = elbg->cells[elbg->nearest_cb[i]]; + elbg->cells[elbg->nearest_cb[i]] = free_cells; + free_cells++; + } + + do_shiftings(elbg); + + memset(size_part, 0, numCB*sizeof(int)); + + memset(elbg->codebook, 0, elbg->numCB*dim*sizeof(int)); + + for (i=0; i < numpoints; i++) { + size_part[elbg->nearest_cb[i]]++; + for (j=0; j < elbg->dim; j++) + elbg->codebook[elbg->nearest_cb[i]*elbg->dim + j] += + elbg->points[i*elbg->dim + j]; + } + + for (i=0; i < elbg->numCB; i++) + vect_division(elbg->codebook + i*elbg->dim, + elbg->codebook + i*elbg->dim, size_part[i], elbg->dim); + + } while(((last_error - elbg->error) > DELTA_ERR_MAX*elbg->error) && + (steps < max_steps)); + + av_free(dist_cb); + av_free(size_part); + av_free(elbg->utility); + av_free(list_buffer); + av_free(elbg->cells); + av_free(elbg->utility_inc); + av_free(elbg->scratchbuf); +} diff --git a/ffmpeg/libavcodec/elbg.h b/ffmpeg/libavcodec/elbg.h new file mode 100644 index 0000000..e6f577e --- /dev/null +++ b/ffmpeg/libavcodec/elbg.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007 Vitor Sessak + * + * 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 + */ + +#ifndef AVCODEC_ELBG_H +#define AVCODEC_ELBG_H + +#include "libavutil/lfg.h" + +/** + * Implementation of the Enhanced LBG Algorithm + * Based on the paper "Neural Networks 14:1219-1237" that can be found in + * http://citeseer.ist.psu.edu/patan01enhanced.html . + * + * @param points Input points. + * @param dim Dimension of the points. + * @param numpoints Num of points in **points. + * @param codebook Pointer to the output codebook. Must be allocated. + * @param numCB Number of points in the codebook. + * @param num_steps The maximum number of steps. One step is already a good compromise between time and quality. + * @param closest_cb Return the closest codebook to each point. Must be allocated. + * @param rand_state A random number generator state. Should be already initialized by av_lfg_init(). + */ +void ff_do_elbg(int *points, int dim, int numpoints, int *codebook, + int numCB, int num_steps, int *closest_cb, + AVLFG *rand_state); + +/** + * Initialize the **codebook vector for the elbg algorithm. If you have already + * a codebook and you want to refine it, you shouldn't call this function. + * If numpoints < 8*numCB this function fills **codebook with random numbers. + * If not, it calls ff_do_elbg for a (smaller) random sample of the points in + * **points. Get the same parameters as ff_do_elbg. + */ +void ff_init_elbg(int *points, int dim, int numpoints, int *codebook, + int numCB, int num_steps, int *closest_cb, + AVLFG *rand_state); + +#endif /* AVCODEC_ELBG_H */ diff --git a/ffmpeg/libavcodec/error_resilience.c b/ffmpeg/libavcodec/error_resilience.c new file mode 100644 index 0000000..cdd28ab --- /dev/null +++ b/ffmpeg/libavcodec/error_resilience.c @@ -0,0 +1,1275 @@ +/* + * Error resilience / concealment + * + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * Error resilience / concealment. + */ + +#include + +#include "avcodec.h" +#include "error_resilience.h" +#include "mpegvideo.h" +#include "rectangle.h" +#include "thread.h" + +/** + * @param stride the number of MVs to get to the next row + * @param mv_step the number of MVs per row or column in a macroblock + */ +static void set_mv_strides(ERContext *s, int *mv_step, int *stride) +{ + if (s->avctx->codec_id == AV_CODEC_ID_H264) { + av_assert0(s->quarter_sample); + *mv_step = 4; + *stride = s->mb_width * 4; + } else { + *mv_step = 2; + *stride = s->b8_stride; + } +} + +/** + * Replace the current MB with a flat dc-only version. + */ +static void put_dc(ERContext *s, uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, int mb_x, int mb_y) +{ + int *linesize = s->cur_pic->f.linesize; + int dc, dcu, dcv, y, i; + for (i = 0; i < 4; i++) { + dc = s->dc_val[0][mb_x * 2 + (i & 1) + (mb_y * 2 + (i >> 1)) * s->b8_stride]; + if (dc < 0) + dc = 0; + else if (dc > 2040) + dc = 2040; + for (y = 0; y < 8; y++) { + int x; + for (x = 0; x < 8; x++) + dest_y[x + (i & 1) * 8 + (y + (i >> 1) * 8) * linesize[0]] = dc / 8; + } + } + dcu = s->dc_val[1][mb_x + mb_y * s->mb_stride]; + dcv = s->dc_val[2][mb_x + mb_y * s->mb_stride]; + if (dcu < 0) + dcu = 0; + else if (dcu > 2040) + dcu = 2040; + if (dcv < 0) + dcv = 0; + else if (dcv > 2040) + dcv = 2040; + for (y = 0; y < 8; y++) { + int x; + for (x = 0; x < 8; x++) { + dest_cb[x + y * linesize[1]] = dcu / 8; + dest_cr[x + y * linesize[2]] = dcv / 8; + } + } +} + +static void filter181(int16_t *data, int width, int height, int stride) +{ + int x, y; + + /* horizontal filter */ + for (y = 1; y < height - 1; y++) { + int prev_dc = data[0 + y * stride]; + + for (x = 1; x < width - 1; x++) { + int dc; + dc = -prev_dc + + data[x + y * stride] * 8 - + data[x + 1 + y * stride]; + dc = (dc * 10923 + 32768) >> 16; + prev_dc = data[x + y * stride]; + data[x + y * stride] = dc; + } + } + + /* vertical filter */ + for (x = 1; x < width - 1; x++) { + int prev_dc = data[x]; + + for (y = 1; y < height - 1; y++) { + int dc; + + dc = -prev_dc + + data[x + y * stride] * 8 - + data[x + (y + 1) * stride]; + dc = (dc * 10923 + 32768) >> 16; + prev_dc = data[x + y * stride]; + data[x + y * stride] = dc; + } + } +} + +/** + * guess the dc of blocks which do not have an undamaged dc + * @param w width in 8 pixel blocks + * @param h height in 8 pixel blocks + */ +static void guess_dc(ERContext *s, int16_t *dc, int w, + int h, int stride, int is_luma) +{ + int b_x, b_y; + int16_t (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4); + uint32_t (*dist)[4] = av_malloc(stride*h*sizeof(uint32_t)*4); + + if(!col || !dist) { + av_log(s->avctx, AV_LOG_ERROR, "guess_dc() is out of memory\n"); + goto fail; + } + + for(b_y=0; b_y>is_luma) + (b_y>>is_luma)*s->mb_stride; + int error_j= s->error_status_table[mb_index_j]; + int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + if(intra_j==0 || !(error_j&ER_DC_ERROR)){ + color= dc[b_x + b_y*stride]; + distance= b_x; + } + col [b_x + b_y*stride][1]= color; + dist[b_x + b_y*stride][1]= distance >= 0 ? b_x-distance : 9999; + } + color= 1024; + distance= -1; + for(b_x=w-1; b_x>=0; b_x--){ + int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; + int error_j= s->error_status_table[mb_index_j]; + int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + if(intra_j==0 || !(error_j&ER_DC_ERROR)){ + color= dc[b_x + b_y*stride]; + distance= b_x; + } + col [b_x + b_y*stride][0]= color; + dist[b_x + b_y*stride][0]= distance >= 0 ? distance-b_x : 9999; + } + } + for(b_x=0; b_x>is_luma) + (b_y>>is_luma)*s->mb_stride; + int error_j= s->error_status_table[mb_index_j]; + int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + if(intra_j==0 || !(error_j&ER_DC_ERROR)){ + color= dc[b_x + b_y*stride]; + distance= b_y; + } + col [b_x + b_y*stride][3]= color; + dist[b_x + b_y*stride][3]= distance >= 0 ? b_y-distance : 9999; + } + color= 1024; + distance= -1; + for(b_y=h-1; b_y>=0; b_y--){ + int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride; + int error_j= s->error_status_table[mb_index_j]; + int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]); + if(intra_j==0 || !(error_j&ER_DC_ERROR)){ + color= dc[b_x + b_y*stride]; + distance= b_y; + } + col [b_x + b_y*stride][2]= color; + dist[b_x + b_y*stride][2]= distance >= 0 ? distance-b_y : 9999; + } + } + + for (b_y = 0; b_y < h; b_y++) { + for (b_x = 0; b_x < w; b_x++) { + int mb_index, error, j; + int64_t guess, weight_sum; + mb_index = (b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride; + error = s->error_status_table[mb_index]; + + if (IS_INTER(s->cur_pic->mb_type[mb_index])) + continue; // inter + if (!(error & ER_DC_ERROR)) + continue; // dc-ok + + weight_sum = 0; + guess = 0; + for (j = 0; j < 4; j++) { + int64_t weight = 256 * 256 * 256 * 16 / FFMAX(dist[b_x + b_y*stride][j], 1); + guess += weight*(int64_t)col[b_x + b_y*stride][j]; + weight_sum += weight; + } + guess = (guess + weight_sum / 2) / weight_sum; + dc[b_x + b_y * stride] = guess; + } + } + +fail: + av_freep(&col); + av_freep(&dist); +} + +/** + * simple horizontal deblocking filter used for error resilience + * @param w width in 8 pixel blocks + * @param h height in 8 pixel blocks + */ +static void h_block_filter(ERContext *s, uint8_t *dst, int w, + int h, int stride, int is_luma) +{ + int b_x, b_y, mvx_stride, mvy_stride; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + set_mv_strides(s, &mvx_stride, &mvy_stride); + mvx_stride >>= is_luma; + mvy_stride *= mvx_stride; + + for (b_y = 0; b_y < h; b_y++) { + for (b_x = 0; b_x < w - 1; b_x++) { + int y; + int left_status = s->error_status_table[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]; + int right_status = s->error_status_table[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]; + int left_intra = IS_INTRA(s->cur_pic->mb_type[( b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]); + int right_intra = IS_INTRA(s->cur_pic->mb_type[((b_x + 1) >> is_luma) + (b_y >> is_luma) * s->mb_stride]); + int left_damage = left_status & ER_MB_ERROR; + int right_damage = right_status & ER_MB_ERROR; + int offset = b_x * 8 + b_y * stride * 8; + int16_t *left_mv = s->cur_pic->motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; + int16_t *right_mv = s->cur_pic->motion_val[0][mvy_stride * b_y + mvx_stride * (b_x + 1)]; + if (!(left_damage || right_damage)) + continue; // both undamaged + if ((!left_intra) && (!right_intra) && + FFABS(left_mv[0] - right_mv[0]) + + FFABS(left_mv[1] + right_mv[1]) < 2) + continue; + + for (y = 0; y < 8; y++) { + int a, b, c, d; + + a = dst[offset + 7 + y * stride] - dst[offset + 6 + y * stride]; + b = dst[offset + 8 + y * stride] - dst[offset + 7 + y * stride]; + c = dst[offset + 9 + y * stride] - dst[offset + 8 + y * stride]; + + d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1); + d = FFMAX(d, 0); + if (b < 0) + d = -d; + + if (d == 0) + continue; + + if (!(left_damage && right_damage)) + d = d * 16 / 9; + + if (left_damage) { + dst[offset + 7 + y * stride] = cm[dst[offset + 7 + y * stride] + ((d * 7) >> 4)]; + dst[offset + 6 + y * stride] = cm[dst[offset + 6 + y * stride] + ((d * 5) >> 4)]; + dst[offset + 5 + y * stride] = cm[dst[offset + 5 + y * stride] + ((d * 3) >> 4)]; + dst[offset + 4 + y * stride] = cm[dst[offset + 4 + y * stride] + ((d * 1) >> 4)]; + } + if (right_damage) { + dst[offset + 8 + y * stride] = cm[dst[offset + 8 + y * stride] - ((d * 7) >> 4)]; + dst[offset + 9 + y * stride] = cm[dst[offset + 9 + y * stride] - ((d * 5) >> 4)]; + dst[offset + 10+ y * stride] = cm[dst[offset + 10 + y * stride] - ((d * 3) >> 4)]; + dst[offset + 11+ y * stride] = cm[dst[offset + 11 + y * stride] - ((d * 1) >> 4)]; + } + } + } + } +} + +/** + * simple vertical deblocking filter used for error resilience + * @param w width in 8 pixel blocks + * @param h height in 8 pixel blocks + */ +static void v_block_filter(ERContext *s, uint8_t *dst, int w, int h, + int stride, int is_luma) +{ + int b_x, b_y, mvx_stride, mvy_stride; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + set_mv_strides(s, &mvx_stride, &mvy_stride); + mvx_stride >>= is_luma; + mvy_stride *= mvx_stride; + + for (b_y = 0; b_y < h - 1; b_y++) { + for (b_x = 0; b_x < w; b_x++) { + int x; + int top_status = s->error_status_table[(b_x >> is_luma) + (b_y >> is_luma) * s->mb_stride]; + int bottom_status = s->error_status_table[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]; + int top_intra = IS_INTRA(s->cur_pic->mb_type[(b_x >> is_luma) + ( b_y >> is_luma) * s->mb_stride]); + int bottom_intra = IS_INTRA(s->cur_pic->mb_type[(b_x >> is_luma) + ((b_y + 1) >> is_luma) * s->mb_stride]); + int top_damage = top_status & ER_MB_ERROR; + int bottom_damage = bottom_status & ER_MB_ERROR; + int offset = b_x * 8 + b_y * stride * 8; + + int16_t *top_mv = s->cur_pic->motion_val[0][mvy_stride * b_y + mvx_stride * b_x]; + int16_t *bottom_mv = s->cur_pic->motion_val[0][mvy_stride * (b_y + 1) + mvx_stride * b_x]; + + if (!(top_damage || bottom_damage)) + continue; // both undamaged + + if ((!top_intra) && (!bottom_intra) && + FFABS(top_mv[0] - bottom_mv[0]) + + FFABS(top_mv[1] + bottom_mv[1]) < 2) + continue; + + for (x = 0; x < 8; x++) { + int a, b, c, d; + + a = dst[offset + x + 7 * stride] - dst[offset + x + 6 * stride]; + b = dst[offset + x + 8 * stride] - dst[offset + x + 7 * stride]; + c = dst[offset + x + 9 * stride] - dst[offset + x + 8 * stride]; + + d = FFABS(b) - ((FFABS(a) + FFABS(c) + 1) >> 1); + d = FFMAX(d, 0); + if (b < 0) + d = -d; + + if (d == 0) + continue; + + if (!(top_damage && bottom_damage)) + d = d * 16 / 9; + + if (top_damage) { + dst[offset + x + 7 * stride] = cm[dst[offset + x + 7 * stride] + ((d * 7) >> 4)]; + dst[offset + x + 6 * stride] = cm[dst[offset + x + 6 * stride] + ((d * 5) >> 4)]; + dst[offset + x + 5 * stride] = cm[dst[offset + x + 5 * stride] + ((d * 3) >> 4)]; + dst[offset + x + 4 * stride] = cm[dst[offset + x + 4 * stride] + ((d * 1) >> 4)]; + } + if (bottom_damage) { + dst[offset + x + 8 * stride] = cm[dst[offset + x + 8 * stride] - ((d * 7) >> 4)]; + dst[offset + x + 9 * stride] = cm[dst[offset + x + 9 * stride] - ((d * 5) >> 4)]; + dst[offset + x + 10 * stride] = cm[dst[offset + x + 10 * stride] - ((d * 3) >> 4)]; + dst[offset + x + 11 * stride] = cm[dst[offset + x + 11 * stride] - ((d * 1) >> 4)]; + } + } + } + } +} + +static void guess_mv(ERContext *s) +{ + uint8_t *fixed = s->er_temp_buffer; +#define MV_FROZEN 3 +#define MV_CHANGED 2 +#define MV_UNCHANGED 1 + const int mb_stride = s->mb_stride; + const int mb_width = s->mb_width; + const int mb_height = s->mb_height; + int i, depth, num_avail; + int mb_x, mb_y, mot_step, mot_stride; + + set_mv_strides(s, &mot_step, &mot_stride); + + num_avail = 0; + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + int f = 0; + int error = s->error_status_table[mb_xy]; + + if (IS_INTRA(s->cur_pic->mb_type[mb_xy])) + f = MV_FROZEN; // intra // FIXME check + if (!(error & ER_MV_ERROR)) + f = MV_FROZEN; // inter with undamaged MV + + fixed[mb_xy] = f; + if (f == MV_FROZEN) + num_avail++; + else if(s->last_pic->f.data[0] && s->last_pic->motion_val[0]){ + const int mb_y= mb_xy / s->mb_stride; + const int mb_x= mb_xy % s->mb_stride; + const int mot_index= (mb_x + mb_y*mot_stride) * mot_step; + s->cur_pic->motion_val[0][mot_index][0]= s->last_pic->motion_val[0][mot_index][0]; + s->cur_pic->motion_val[0][mot_index][1]= s->last_pic->motion_val[0][mot_index][1]; + s->cur_pic->ref_index[0][4*mb_xy] = s->last_pic->ref_index[0][4*mb_xy]; + } + } + + if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || + num_avail <= mb_width / 2) { + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + const int mb_xy = mb_x + mb_y * s->mb_stride; + int mv_dir = (s->last_pic && s->last_pic->f.data[0]) ? MV_DIR_FORWARD : MV_DIR_BACKWARD; + + if (IS_INTRA(s->cur_pic->mb_type[mb_xy])) + continue; + if (!(s->error_status_table[mb_xy] & ER_MV_ERROR)) + continue; + + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->decode_mb(s->opaque, 0, mv_dir, MV_TYPE_16X16, &s->mv, + mb_x, mb_y, 0, 0); + } + } + return; + } + + for (depth = 0; ; depth++) { + int changed, pass, none_left; + + none_left = 1; + changed = 1; + for (pass = 0; (changed || pass < 2) && pass < 10; pass++) { + int mb_x, mb_y; + int score_sum = 0; + + changed = 0; + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + const int mb_xy = mb_x + mb_y * s->mb_stride; + int mv_predictor[8][2] = { { 0 } }; + int ref[8] = { 0 }; + int pred_count = 0; + int j; + int best_score = 256 * 256 * 256 * 64; + int best_pred = 0; + const int mot_index = (mb_x + mb_y * mot_stride) * mot_step; + int prev_x, prev_y, prev_ref; + + if ((mb_x ^ mb_y ^ pass) & 1) + continue; + + if (fixed[mb_xy] == MV_FROZEN) + continue; + av_assert1(!IS_INTRA(s->cur_pic->mb_type[mb_xy])); + av_assert1(s->last_pic && s->last_pic->f.data[0]); + + j = 0; + if (mb_x > 0 && fixed[mb_xy - 1] == MV_FROZEN) + j = 1; + if (mb_x + 1 < mb_width && fixed[mb_xy + 1] == MV_FROZEN) + j = 1; + if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_FROZEN) + j = 1; + if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_FROZEN) + j = 1; + if (j == 0) + continue; + + j = 0; + if (mb_x > 0 && fixed[mb_xy - 1 ] == MV_CHANGED) + j = 1; + if (mb_x + 1 < mb_width && fixed[mb_xy + 1 ] == MV_CHANGED) + j = 1; + if (mb_y > 0 && fixed[mb_xy - mb_stride] == MV_CHANGED) + j = 1; + if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride] == MV_CHANGED) + j = 1; + if (j == 0 && pass > 1) + continue; + + none_left = 0; + + if (mb_x > 0 && fixed[mb_xy - 1]) { + mv_predictor[pred_count][0] = + s->cur_pic->motion_val[0][mot_index - mot_step][0]; + mv_predictor[pred_count][1] = + s->cur_pic->motion_val[0][mot_index - mot_step][1]; + ref[pred_count] = + s->cur_pic->ref_index[0][4 * (mb_xy - 1)]; + pred_count++; + } + if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) { + mv_predictor[pred_count][0] = + s->cur_pic->motion_val[0][mot_index + mot_step][0]; + mv_predictor[pred_count][1] = + s->cur_pic->motion_val[0][mot_index + mot_step][1]; + ref[pred_count] = + s->cur_pic->ref_index[0][4 * (mb_xy + 1)]; + pred_count++; + } + if (mb_y > 0 && fixed[mb_xy - mb_stride]) { + mv_predictor[pred_count][0] = + s->cur_pic->motion_val[0][mot_index - mot_stride * mot_step][0]; + mv_predictor[pred_count][1] = + s->cur_pic->motion_val[0][mot_index - mot_stride * mot_step][1]; + ref[pred_count] = + s->cur_pic->ref_index[0][4 * (mb_xy - s->mb_stride)]; + pred_count++; + } + if (mb_y + 1cur_pic->motion_val[0][mot_index + mot_stride * mot_step][0]; + mv_predictor[pred_count][1] = + s->cur_pic->motion_val[0][mot_index + mot_stride * mot_step][1]; + ref[pred_count] = + s->cur_pic->ref_index[0][4 * (mb_xy + s->mb_stride)]; + pred_count++; + } + if (pred_count == 0) + continue; + + if (pred_count > 1) { + int sum_x = 0, sum_y = 0, sum_r = 0; + int max_x, max_y, min_x, min_y, max_r, min_r; + + for (j = 0; j < pred_count; j++) { + sum_x += mv_predictor[j][0]; + sum_y += mv_predictor[j][1]; + sum_r += ref[j]; + if (j && ref[j] != ref[j - 1]) + goto skip_mean_and_median; + } + + /* mean */ + mv_predictor[pred_count][0] = sum_x / j; + mv_predictor[pred_count][1] = sum_y / j; + ref[pred_count] = sum_r / j; + + /* median */ + if (pred_count >= 3) { + min_y = min_x = min_r = 99999; + max_y = max_x = max_r = -99999; + } else { + min_x = min_y = max_x = max_y = min_r = max_r = 0; + } + for (j = 0; j < pred_count; j++) { + max_x = FFMAX(max_x, mv_predictor[j][0]); + max_y = FFMAX(max_y, mv_predictor[j][1]); + max_r = FFMAX(max_r, ref[j]); + min_x = FFMIN(min_x, mv_predictor[j][0]); + min_y = FFMIN(min_y, mv_predictor[j][1]); + min_r = FFMIN(min_r, ref[j]); + } + mv_predictor[pred_count + 1][0] = sum_x - max_x - min_x; + mv_predictor[pred_count + 1][1] = sum_y - max_y - min_y; + ref[pred_count + 1] = sum_r - max_r - min_r; + + if (pred_count == 4) { + mv_predictor[pred_count + 1][0] /= 2; + mv_predictor[pred_count + 1][1] /= 2; + ref[pred_count + 1] /= 2; + } + pred_count += 2; + } + +skip_mean_and_median: + /* zero MV */ + pred_count++; + + if (!fixed[mb_xy] && 0) { + if (s->avctx->codec_id == AV_CODEC_ID_H264) { + // FIXME + } else { + ff_thread_await_progress(&s->last_pic->tf, + mb_y, 0); + } + if (!s->last_pic->motion_val[0] || + !s->last_pic->ref_index[0]) + goto skip_last_mv; + prev_x = s->last_pic->motion_val[0][mot_index][0]; + prev_y = s->last_pic->motion_val[0][mot_index][1]; + prev_ref = s->last_pic->ref_index[0][4 * mb_xy]; + } else { + prev_x = s->cur_pic->motion_val[0][mot_index][0]; + prev_y = s->cur_pic->motion_val[0][mot_index][1]; + prev_ref = s->cur_pic->ref_index[0][4 * mb_xy]; + } + + /* last MV */ + mv_predictor[pred_count][0] = prev_x; + mv_predictor[pred_count][1] = prev_y; + ref[pred_count] = prev_ref; + pred_count++; + +skip_last_mv: + + for (j = 0; j < pred_count; j++) { + int *linesize = s->cur_pic->f.linesize; + int score = 0; + uint8_t *src = s->cur_pic->f.data[0] + + mb_x * 16 + mb_y * 16 * linesize[0]; + + s->cur_pic->motion_val[0][mot_index][0] = + s->mv[0][0][0] = mv_predictor[j][0]; + s->cur_pic->motion_val[0][mot_index][1] = + s->mv[0][0][1] = mv_predictor[j][1]; + + // predictor intra or otherwise not available + if (ref[j] < 0) + continue; + + s->decode_mb(s->opaque, ref[j], MV_DIR_FORWARD, + MV_TYPE_16X16, &s->mv, mb_x, mb_y, 0, 0); + + if (mb_x > 0 && fixed[mb_xy - 1]) { + int k; + for (k = 0; k < 16; k++) + score += FFABS(src[k * linesize[0] - 1] - + src[k * linesize[0]]); + } + if (mb_x + 1 < mb_width && fixed[mb_xy + 1]) { + int k; + for (k = 0; k < 16; k++) + score += FFABS(src[k * linesize[0] + 15] - + src[k * linesize[0] + 16]); + } + if (mb_y > 0 && fixed[mb_xy - mb_stride]) { + int k; + for (k = 0; k < 16; k++) + score += FFABS(src[k - linesize[0]] - src[k]); + } + if (mb_y + 1 < mb_height && fixed[mb_xy + mb_stride]) { + int k; + for (k = 0; k < 16; k++) + score += FFABS(src[k + linesize[0] * 15] - + src[k + linesize[0] * 16]); + } + + if (score <= best_score) { // <= will favor the last MV + best_score = score; + best_pred = j; + } + } + score_sum += best_score; + s->mv[0][0][0] = mv_predictor[best_pred][0]; + s->mv[0][0][1] = mv_predictor[best_pred][1]; + + for (i = 0; i < mot_step; i++) + for (j = 0; j < mot_step; j++) { + s->cur_pic->motion_val[0][mot_index + i + j * mot_stride][0] = s->mv[0][0][0]; + s->cur_pic->motion_val[0][mot_index + i + j * mot_stride][1] = s->mv[0][0][1]; + } + + s->decode_mb(s->opaque, ref[best_pred], MV_DIR_FORWARD, + MV_TYPE_16X16, &s->mv, mb_x, mb_y, 0, 0); + + + if (s->mv[0][0][0] != prev_x || s->mv[0][0][1] != prev_y) { + fixed[mb_xy] = MV_CHANGED; + changed++; + } else + fixed[mb_xy] = MV_UNCHANGED; + } + } + } + + if (none_left) + return; + + for (i = 0; i < s->mb_num; i++) { + int mb_xy = s->mb_index2xy[i]; + if (fixed[mb_xy]) + fixed[mb_xy] = MV_FROZEN; + } + } +} + +static int is_intra_more_likely(ERContext *s) +{ + int is_intra_likely, i, j, undamaged_count, skip_amount, mb_x, mb_y; + + if (!s->last_pic || !s->last_pic->f.data[0]) + return 1; // no previous frame available -> use spatial prediction + + undamaged_count = 0; + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + const int error = s->error_status_table[mb_xy]; + if (!((error & ER_DC_ERROR) && (error & ER_MV_ERROR))) + undamaged_count++; + } + + if (s->avctx->codec_id == AV_CODEC_ID_H264 && s->ref_count <= 0) + return 1; + + if (undamaged_count < 5) + return 0; // almost all MBs damaged -> use temporal prediction + + // prevent dsp.sad() check, that requires access to the image + if (CONFIG_MPEG_XVMC_DECODER && + s->avctx->xvmc_acceleration && + s->cur_pic->f.pict_type == AV_PICTURE_TYPE_I) + return 1; + + skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs + is_intra_likely = 0; + + j = 0; + for (mb_y = 0; mb_y < s->mb_height - 1; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + int error; + const int mb_xy = mb_x + mb_y * s->mb_stride; + + error = s->error_status_table[mb_xy]; + if ((error & ER_DC_ERROR) && (error & ER_MV_ERROR)) + continue; // skip damaged + + j++; + // skip a few to speed things up + if ((j % skip_amount) != 0) + continue; + + if (s->cur_pic->f.pict_type == AV_PICTURE_TYPE_I) { + int *linesize = s->cur_pic->f.linesize; + uint8_t *mb_ptr = s->cur_pic->f.data[0] + + mb_x * 16 + mb_y * 16 * linesize[0]; + uint8_t *last_mb_ptr = s->last_pic->f.data[0] + + mb_x * 16 + mb_y * 16 * linesize[0]; + + if (s->avctx->codec_id == AV_CODEC_ID_H264) { + // FIXME + } else { + ff_thread_await_progress(&s->last_pic->tf, mb_y, 0); + } + is_intra_likely += s->dsp->sad[0](NULL, last_mb_ptr, mb_ptr, + linesize[0], 16); + // FIXME need await_progress() here + is_intra_likely -= s->dsp->sad[0](NULL, last_mb_ptr, + last_mb_ptr + linesize[0] * 16, + linesize[0], 16); + } else { + if (IS_INTRA(s->cur_pic->mb_type[mb_xy])) + is_intra_likely++; + else + is_intra_likely--; + } + } + } + // printf("is_intra_likely: %d type:%d\n", is_intra_likely, s->pict_type); + return is_intra_likely > 0; +} + +void ff_er_frame_start(ERContext *s) +{ + if (!s->avctx->err_recognition) + return; + + memset(s->error_status_table, ER_MB_ERROR | VP_START | ER_MB_END, + s->mb_stride * s->mb_height * sizeof(uint8_t)); + s->error_count = 3 * s->mb_num; + s->error_occurred = 0; +} + +/** + * Add a slice. + * @param endx x component of the last macroblock, can be -1 + * for the last of the previous line + * @param status the status at the end (ER_MV_END, ER_AC_ERROR, ...), it is + * assumed that no earlier end or error of the same type occurred + */ +void ff_er_add_slice(ERContext *s, int startx, int starty, + int endx, int endy, int status) +{ + const int start_i = av_clip(startx + starty * s->mb_width, 0, s->mb_num - 1); + const int end_i = av_clip(endx + endy * s->mb_width, 0, s->mb_num); + const int start_xy = s->mb_index2xy[start_i]; + const int end_xy = s->mb_index2xy[end_i]; + int mask = -1; + + if (s->avctx->hwaccel) + return; + + if (start_i > end_i || start_xy > end_xy) { + av_log(s->avctx, AV_LOG_ERROR, + "internal error, slice end before start\n"); + return; + } + + if (!s->avctx->err_recognition) + return; + + mask &= ~VP_START; + if (status & (ER_AC_ERROR | ER_AC_END)) { + mask &= ~(ER_AC_ERROR | ER_AC_END); + s->error_count -= end_i - start_i + 1; + } + if (status & (ER_DC_ERROR | ER_DC_END)) { + mask &= ~(ER_DC_ERROR | ER_DC_END); + s->error_count -= end_i - start_i + 1; + } + if (status & (ER_MV_ERROR | ER_MV_END)) { + mask &= ~(ER_MV_ERROR | ER_MV_END); + s->error_count -= end_i - start_i + 1; + } + + if (status & ER_MB_ERROR) { + s->error_occurred = 1; + s->error_count = INT_MAX; + } + + if (mask == ~0x7F) { + memset(&s->error_status_table[start_xy], 0, + (end_xy - start_xy) * sizeof(uint8_t)); + } else { + int i; + for (i = start_xy; i < end_xy; i++) + s->error_status_table[i] &= mask; + } + + if (end_i == s->mb_num) + s->error_count = INT_MAX; + else { + s->error_status_table[end_xy] &= mask; + s->error_status_table[end_xy] |= status; + } + + s->error_status_table[start_xy] |= VP_START; + + if (start_xy > 0 && !(s->avctx->active_thread_type & FF_THREAD_SLICE) && + s->avctx->skip_top * s->mb_width < start_i) { + int prev_status = s->error_status_table[s->mb_index2xy[start_i - 1]]; + + prev_status &= ~ VP_START; + if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END)) { + s->error_occurred = 1; + s->error_count = INT_MAX; + } + } +} + +void ff_er_frame_end(ERContext *s) +{ + int *linesize = s->cur_pic->f.linesize; + int i, mb_x, mb_y, error, error_type, dc_error, mv_error, ac_error; + int distance; + int threshold_part[4] = { 100, 100, 100 }; + int threshold = 50; + int is_intra_likely; + int size = s->b8_stride * 2 * s->mb_height; + + /* We do not support ER of field pictures yet, + * though it should not crash if enabled. */ + if (!s->avctx->err_recognition || s->error_count == 0 || + s->avctx->lowres || + s->avctx->hwaccel || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU || + !s->cur_pic || s->cur_pic->field_picture || + s->error_count == 3 * s->mb_width * + (s->avctx->skip_top + s->avctx->skip_bottom)) { + return; + } + if (s->last_pic) { + if (s->last_pic->f.width != s->cur_pic->f.width || + s->last_pic->f.height != s->cur_pic->f.height || + s->last_pic->f.format != s->cur_pic->f.format) { + av_log(s->avctx, AV_LOG_WARNING, "Cannot use previous picture in error concealment\n"); + s->last_pic = NULL; + } + } + if (s->next_pic) { + if (s->next_pic->f.width != s->cur_pic->f.width || + s->next_pic->f.height != s->cur_pic->f.height || + s->next_pic->f.format != s->cur_pic->f.format) { + av_log(s->avctx, AV_LOG_WARNING, "Cannot use next picture in error concealment\n"); + s->next_pic = NULL; + } + } + + if (s->cur_pic->motion_val[0] == NULL) { + av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n"); + + for (i = 0; i < 2; i++) { + s->cur_pic->ref_index_buf[i] = av_buffer_allocz(s->mb_stride * s->mb_height * 4 * sizeof(uint8_t)); + s->cur_pic->motion_val_buf[i] = av_buffer_allocz((size + 4) * 2 * sizeof(uint16_t)); + if (!s->cur_pic->ref_index_buf[i] || !s->cur_pic->motion_val_buf[i]) + break; + s->cur_pic->ref_index[i] = s->cur_pic->ref_index_buf[i]->data; + s->cur_pic->motion_val[i] = (int16_t (*)[2])s->cur_pic->motion_val_buf[i]->data + 4; + } + if (i < 2) { + for (i = 0; i < 2; i++) { + av_buffer_unref(&s->cur_pic->ref_index_buf[i]); + av_buffer_unref(&s->cur_pic->motion_val_buf[i]); + s->cur_pic->ref_index[i] = NULL; + s->cur_pic->motion_val[i] = NULL; + } + return; + } + } + + if (s->avctx->debug & FF_DEBUG_ER) { + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + int status = s->error_status_table[mb_x + mb_y * s->mb_stride]; + + av_log(s->avctx, AV_LOG_DEBUG, "%2X ", status); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + } + +#if 1 + /* handle overlapping slices */ + for (error_type = 1; error_type <= 3; error_type++) { + int end_ok = 0; + + for (i = s->mb_num - 1; i >= 0; i--) { + const int mb_xy = s->mb_index2xy[i]; + int error = s->error_status_table[mb_xy]; + + if (error & (1 << error_type)) + end_ok = 1; + if (error & (8 << error_type)) + end_ok = 1; + + if (!end_ok) + s->error_status_table[mb_xy] |= 1 << error_type; + + if (error & VP_START) + end_ok = 0; + } + } +#endif +#if 1 + /* handle slices with partitions of different length */ + if (s->partitioned_frame) { + int end_ok = 0; + + for (i = s->mb_num - 1; i >= 0; i--) { + const int mb_xy = s->mb_index2xy[i]; + int error = s->error_status_table[mb_xy]; + + if (error & ER_AC_END) + end_ok = 0; + if ((error & ER_MV_END) || + (error & ER_DC_END) || + (error & ER_AC_ERROR)) + end_ok = 1; + + if (!end_ok) + s->error_status_table[mb_xy]|= ER_AC_ERROR; + + if (error & VP_START) + end_ok = 0; + } + } +#endif + /* handle missing slices */ + if (s->avctx->err_recognition & AV_EF_EXPLODE) { + int end_ok = 1; + + // FIXME + 100 hack + for (i = s->mb_num - 2; i >= s->mb_width + 100; i--) { + const int mb_xy = s->mb_index2xy[i]; + int error1 = s->error_status_table[mb_xy]; + int error2 = s->error_status_table[s->mb_index2xy[i + 1]]; + + if (error1 & VP_START) + end_ok = 1; + + if (error2 == (VP_START | ER_MB_ERROR | ER_MB_END) && + error1 != (VP_START | ER_MB_ERROR | ER_MB_END) && + ((error1 & ER_AC_END) || (error1 & ER_DC_END) || + (error1 & ER_MV_END))) { + // end & uninit + end_ok = 0; + } + + if (!end_ok) + s->error_status_table[mb_xy] |= ER_MB_ERROR; + } + } + +#if 1 + /* backward mark errors */ + distance = 9999999; + for (error_type = 1; error_type <= 3; error_type++) { + for (i = s->mb_num - 1; i >= 0; i--) { + const int mb_xy = s->mb_index2xy[i]; + int error = s->error_status_table[mb_xy]; + + if (!s->mbskip_table[mb_xy]) // FIXME partition specific + distance++; + if (error & (1 << error_type)) + distance = 0; + + if (s->partitioned_frame) { + if (distance < threshold_part[error_type - 1]) + s->error_status_table[mb_xy] |= 1 << error_type; + } else { + if (distance < threshold) + s->error_status_table[mb_xy] |= 1 << error_type; + } + + if (error & VP_START) + distance = 9999999; + } + } +#endif + + /* forward mark errors */ + error = 0; + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + int old_error = s->error_status_table[mb_xy]; + + if (old_error & VP_START) { + error = old_error & ER_MB_ERROR; + } else { + error |= old_error & ER_MB_ERROR; + s->error_status_table[mb_xy] |= error; + } + } +#if 1 + /* handle not partitioned case */ + if (!s->partitioned_frame) { + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + error = s->error_status_table[mb_xy]; + if (error & ER_MB_ERROR) + error |= ER_MB_ERROR; + s->error_status_table[mb_xy] = error; + } + } +#endif + + dc_error = ac_error = mv_error = 0; + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + error = s->error_status_table[mb_xy]; + if (error & ER_DC_ERROR) + dc_error++; + if (error & ER_AC_ERROR) + ac_error++; + if (error & ER_MV_ERROR) + mv_error++; + } + av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors in %c frame\n", + dc_error, ac_error, mv_error, av_get_picture_type_char(s->cur_pic->f.pict_type)); + + is_intra_likely = is_intra_more_likely(s); + + /* set unknown mb-type to most likely */ + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + error = s->error_status_table[mb_xy]; + if (!((error & ER_DC_ERROR) && (error & ER_MV_ERROR))) + continue; + + if (is_intra_likely) + s->cur_pic->mb_type[mb_xy] = MB_TYPE_INTRA4x4; + else + s->cur_pic->mb_type[mb_xy] = MB_TYPE_16x16 | MB_TYPE_L0; + } + + // change inter to intra blocks if no reference frames are available + if (!(s->last_pic && s->last_pic->f.data[0]) && + !(s->next_pic && s->next_pic->f.data[0])) + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + if (!IS_INTRA(s->cur_pic->mb_type[mb_xy])) + s->cur_pic->mb_type[mb_xy] = MB_TYPE_INTRA4x4; + } + + /* handle inter blocks with damaged AC */ + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + const int mb_xy = mb_x + mb_y * s->mb_stride; + const int mb_type = s->cur_pic->mb_type[mb_xy]; + const int dir = !(s->last_pic && s->last_pic->f.data[0]); + const int mv_dir = dir ? MV_DIR_BACKWARD : MV_DIR_FORWARD; + int mv_type; + + error = s->error_status_table[mb_xy]; + + if (IS_INTRA(mb_type)) + continue; // intra + if (error & ER_MV_ERROR) + continue; // inter with damaged MV + if (!(error & ER_AC_ERROR)) + continue; // undamaged inter + + if (IS_8X8(mb_type)) { + int mb_index = mb_x * 2 + mb_y * 2 * s->b8_stride; + int j; + mv_type = MV_TYPE_8X8; + for (j = 0; j < 4; j++) { + s->mv[0][j][0] = s->cur_pic->motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][0]; + s->mv[0][j][1] = s->cur_pic->motion_val[dir][mb_index + (j & 1) + (j >> 1) * s->b8_stride][1]; + } + } else { + mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = s->cur_pic->motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][0]; + s->mv[0][0][1] = s->cur_pic->motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1]; + } + + s->decode_mb(s->opaque, 0 /* FIXME h264 partitioned slices need this set */, + mv_dir, mv_type, &s->mv, mb_x, mb_y, 0, 0); + } + } + + /* guess MVs */ + if (s->cur_pic->f.pict_type == AV_PICTURE_TYPE_B) { + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + int xy = mb_x * 2 + mb_y * 2 * s->b8_stride; + const int mb_xy = mb_x + mb_y * s->mb_stride; + const int mb_type = s->cur_pic->mb_type[mb_xy]; + int mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + + error = s->error_status_table[mb_xy]; + + if (IS_INTRA(mb_type)) + continue; + if (!(error & ER_MV_ERROR)) + continue; // inter with undamaged MV + if (!(error & ER_AC_ERROR)) + continue; // undamaged inter + + if (!(s->last_pic && s->last_pic->f.data[0])) + mv_dir &= ~MV_DIR_FORWARD; + if (!(s->next_pic && s->next_pic->f.data[0])) + mv_dir &= ~MV_DIR_BACKWARD; + + if (s->pp_time) { + int time_pp = s->pp_time; + int time_pb = s->pb_time; + + av_assert0(s->avctx->codec_id != AV_CODEC_ID_H264); + ff_thread_await_progress(&s->next_pic->tf, mb_y, 0); + + s->mv[0][0][0] = s->next_pic->motion_val[0][xy][0] * time_pb / time_pp; + s->mv[0][0][1] = s->next_pic->motion_val[0][xy][1] * time_pb / time_pp; + s->mv[1][0][0] = s->next_pic->motion_val[0][xy][0] * (time_pb - time_pp) / time_pp; + s->mv[1][0][1] = s->next_pic->motion_val[0][xy][1] * (time_pb - time_pp) / time_pp; + } else { + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mv[1][0][0] = 0; + s->mv[1][0][1] = 0; + } + + s->decode_mb(s->opaque, 0, mv_dir, MV_TYPE_16X16, &s->mv, + mb_x, mb_y, 0, 0); + } + } + } else + guess_mv(s); + + /* the filters below are not XvMC compatible, skip them */ + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + goto ec_clean; + /* fill DC for inter blocks */ + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + int dc, dcu, dcv, y, n; + int16_t *dc_ptr; + uint8_t *dest_y, *dest_cb, *dest_cr; + const int mb_xy = mb_x + mb_y * s->mb_stride; + const int mb_type = s->cur_pic->mb_type[mb_xy]; + + error = s->error_status_table[mb_xy]; + + if (IS_INTRA(mb_type) && s->partitioned_frame) + continue; + // if (error & ER_MV_ERROR) + // continue; // inter data damaged FIXME is this good? + + dest_y = s->cur_pic->f.data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; + dest_cb = s->cur_pic->f.data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; + dest_cr = s->cur_pic->f.data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; + + dc_ptr = &s->dc_val[0][mb_x * 2 + mb_y * 2 * s->b8_stride]; + for (n = 0; n < 4; n++) { + dc = 0; + for (y = 0; y < 8; y++) { + int x; + for (x = 0; x < 8; x++) + dc += dest_y[x + (n & 1) * 8 + + (y + (n >> 1) * 8) * linesize[0]]; + } + dc_ptr[(n & 1) + (n >> 1) * s->b8_stride] = (dc + 4) >> 3; + } + + dcu = dcv = 0; + for (y = 0; y < 8; y++) { + int x; + for (x = 0; x < 8; x++) { + dcu += dest_cb[x + y * linesize[1]]; + dcv += dest_cr[x + y * linesize[2]]; + } + } + s->dc_val[1][mb_x + mb_y * s->mb_stride] = (dcu + 4) >> 3; + s->dc_val[2][mb_x + mb_y * s->mb_stride] = (dcv + 4) >> 3; + } + } +#if 1 + /* guess DC for damaged blocks */ + guess_dc(s, s->dc_val[0], s->mb_width*2, s->mb_height*2, s->b8_stride, 1); + guess_dc(s, s->dc_val[1], s->mb_width , s->mb_height , s->mb_stride, 0); + guess_dc(s, s->dc_val[2], s->mb_width , s->mb_height , s->mb_stride, 0); +#endif + + /* filter luma DC */ + filter181(s->dc_val[0], s->mb_width * 2, s->mb_height * 2, s->b8_stride); + +#if 1 + /* render DC only intra */ + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + uint8_t *dest_y, *dest_cb, *dest_cr; + const int mb_xy = mb_x + mb_y * s->mb_stride; + const int mb_type = s->cur_pic->mb_type[mb_xy]; + + error = s->error_status_table[mb_xy]; + + if (IS_INTER(mb_type)) + continue; + if (!(error & ER_AC_ERROR)) + continue; // undamaged + + dest_y = s->cur_pic->f.data[0] + mb_x * 16 + mb_y * 16 * linesize[0]; + dest_cb = s->cur_pic->f.data[1] + mb_x * 8 + mb_y * 8 * linesize[1]; + dest_cr = s->cur_pic->f.data[2] + mb_x * 8 + mb_y * 8 * linesize[2]; + + put_dc(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); + } + } +#endif + + if (s->avctx->error_concealment & FF_EC_DEBLOCK) { + /* filter horizontal block boundaries */ + h_block_filter(s, s->cur_pic->f.data[0], s->mb_width * 2, + s->mb_height * 2, linesize[0], 1); + h_block_filter(s, s->cur_pic->f.data[1], s->mb_width, + s->mb_height, linesize[1], 0); + h_block_filter(s, s->cur_pic->f.data[2], s->mb_width, + s->mb_height, linesize[2], 0); + + /* filter vertical block boundaries */ + v_block_filter(s, s->cur_pic->f.data[0], s->mb_width * 2, + s->mb_height * 2, linesize[0], 1); + v_block_filter(s, s->cur_pic->f.data[1], s->mb_width, + s->mb_height, linesize[1], 0); + v_block_filter(s, s->cur_pic->f.data[2], s->mb_width, + s->mb_height, linesize[2], 0); + } + +ec_clean: + /* clean a few tables */ + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + int error = s->error_status_table[mb_xy]; + + if (s->cur_pic->f.pict_type != AV_PICTURE_TYPE_B && + (error & (ER_DC_ERROR | ER_MV_ERROR | ER_AC_ERROR))) { + s->mbskip_table[mb_xy] = 0; + } + s->mbintra_table[mb_xy] = 1; + } + s->cur_pic = NULL; + s->next_pic = NULL; + s->last_pic = NULL; +} diff --git a/ffmpeg/libavcodec/error_resilience.h b/ffmpeg/libavcodec/error_resilience.h new file mode 100644 index 0000000..970fdc2 --- /dev/null +++ b/ffmpeg/libavcodec/error_resilience.h @@ -0,0 +1,79 @@ +/* + * + * 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 + */ + +#ifndef AVCODEC_ERROR_RESILIENCE_H +#define AVCODEC_ERROR_RESILIENCE_H + +#include + +#include "avcodec.h" +#include "dsputil.h" + +///< current MB is the first after a resync marker +#define VP_START 1 +#define ER_AC_ERROR 2 +#define ER_DC_ERROR 4 +#define ER_MV_ERROR 8 +#define ER_AC_END 16 +#define ER_DC_END 32 +#define ER_MV_END 64 + +#define ER_MB_ERROR (ER_AC_ERROR|ER_DC_ERROR|ER_MV_ERROR) +#define ER_MB_END (ER_AC_END|ER_DC_END|ER_MV_END) + +typedef struct ERContext { + AVCodecContext *avctx; + DSPContext *dsp; + + int *mb_index2xy; + int mb_num; + int mb_width, mb_height; + int mb_stride; + int b8_stride; + + int error_count, error_occurred; + uint8_t *error_status_table; + uint8_t *er_temp_buffer; + int16_t *dc_val[3]; + uint8_t *mbskip_table; + uint8_t *mbintra_table; + int mv[2][4][2]; + + struct Picture *cur_pic; + struct Picture *last_pic; + struct Picture *next_pic; + + uint16_t pp_time; + uint16_t pb_time; + int quarter_sample; + int partitioned_frame; + int ref_count; + + void (*decode_mb)(void *opaque, int ref, int mv_dir, int mv_type, + int (*mv)[2][4][2], + int mb_x, int mb_y, int mb_intra, int mb_skipped); + void *opaque; +} ERContext; + +void ff_er_frame_start(ERContext *s); +void ff_er_frame_end(ERContext *s); +void ff_er_add_slice(ERContext *s, int startx, int starty, int endx, int endy, + int status); + +#endif /* AVCODEC_ERROR_RESILIENCE_H */ diff --git a/ffmpeg/libavcodec/escape124.c b/ffmpeg/libavcodec/escape124.c new file mode 100644 index 0000000..3c83e58 --- /dev/null +++ b/ffmpeg/libavcodec/escape124.c @@ -0,0 +1,379 @@ +/* + * Escape 124 Video Decoder + * Copyright (C) 2008 Eli Friedman (eli.friedman@gmail.com) + * + * 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 "avcodec.h" +#include "internal.h" + +#define BITSTREAM_READER_LE +#include "get_bits.h" + +typedef union MacroBlock { + uint16_t pixels[4]; + uint32_t pixels32[2]; +} MacroBlock; + +typedef union SuperBlock { + uint16_t pixels[64]; + uint32_t pixels32[32]; +} SuperBlock; + +typedef struct CodeBook { + unsigned depth; + unsigned size; + MacroBlock* blocks; +} CodeBook; + +typedef struct Escape124Context { + AVFrame frame; + + unsigned num_superblocks; + + CodeBook codebooks[3]; +} Escape124Context; + +static int can_safely_read(GetBitContext* gb, uint64_t bits) { + return get_bits_left(gb) >= bits; +} + +/** + * Initialize the decoder + * @param avctx decoder context + * @return 0 success, negative on error + */ +static av_cold int escape124_decode_init(AVCodecContext *avctx) +{ + Escape124Context *s = avctx->priv_data; + + avcodec_get_frame_defaults(&s->frame); + avctx->pix_fmt = AV_PIX_FMT_RGB555; + + s->num_superblocks = ((unsigned)avctx->width / 8) * + ((unsigned)avctx->height / 8); + + return 0; +} + +static av_cold int escape124_decode_close(AVCodecContext *avctx) +{ + unsigned i; + Escape124Context *s = avctx->priv_data; + + for (i = 0; i < 3; i++) + av_free(s->codebooks[i].blocks); + + av_frame_unref(&s->frame); + + return 0; +} + +static CodeBook unpack_codebook(GetBitContext* gb, unsigned depth, + unsigned size) +{ + unsigned i, j; + CodeBook cb = { 0 }; + + if (!can_safely_read(gb, (uint64_t)size * 34)) + return cb; + + if (size >= INT_MAX / sizeof(MacroBlock)) + return cb; + cb.blocks = av_malloc(size ? size * sizeof(MacroBlock) : 1); + if (!cb.blocks) + return cb; + + cb.depth = depth; + cb.size = size; + for (i = 0; i < size; i++) { + unsigned mask_bits = get_bits(gb, 4); + unsigned color0 = get_bits(gb, 15); + unsigned color1 = get_bits(gb, 15); + + for (j = 0; j < 4; j++) { + if (mask_bits & (1 << j)) + cb.blocks[i].pixels[j] = color1; + else + cb.blocks[i].pixels[j] = color0; + } + } + return cb; +} + +static unsigned decode_skip_count(GetBitContext* gb) +{ + unsigned value; + // This function reads a maximum of 23 bits, + // which is within the padding space + if (!can_safely_read(gb, 1)) + return -1; + value = get_bits1(gb); + if (!value) + return value; + + value += get_bits(gb, 3); + if (value != (1 + ((1 << 3) - 1))) + return value; + + value += get_bits(gb, 7); + if (value != (1 + ((1 << 3) - 1)) + ((1 << 7) - 1)) + return value; + + return value + get_bits(gb, 12); +} + +static MacroBlock decode_macroblock(Escape124Context* s, GetBitContext* gb, + int* codebook_index, int superblock_index) +{ + // This function reads a maximum of 22 bits; the callers + // guard this function appropriately + unsigned block_index, depth; + + if (get_bits1(gb)) { + static const char transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} }; + *codebook_index = transitions[*codebook_index][get_bits1(gb)]; + } + + depth = s->codebooks[*codebook_index].depth; + + // depth = 0 means that this shouldn't read any bits; + // in theory, this is the same as get_bits(gb, 0), but + // that doesn't actually work. + block_index = depth ? get_bits(gb, depth) : 0; + + if (*codebook_index == 1) { + block_index += superblock_index << s->codebooks[1].depth; + } + + // This condition can occur with invalid bitstreams and + // *codebook_index == 2 + if (block_index >= s->codebooks[*codebook_index].size) + return (MacroBlock) { { 0 } }; + + return s->codebooks[*codebook_index].blocks[block_index]; +} + +static void insert_mb_into_sb(SuperBlock* sb, MacroBlock mb, unsigned index) { + // Formula: ((index / 4) * 16 + (index % 4) * 2) / 2 + uint32_t *dst = sb->pixels32 + index + (index & -4); + + // This technically violates C99 aliasing rules, but it should be safe. + dst[0] = mb.pixels32[0]; + dst[4] = mb.pixels32[1]; +} + +static void copy_superblock(uint16_t* dest, unsigned dest_stride, + uint16_t* src, unsigned src_stride) +{ + unsigned y; + if (src) + for (y = 0; y < 8; y++) + memcpy(dest + y * dest_stride, src + y * src_stride, + sizeof(uint16_t) * 8); + else + for (y = 0; y < 8; y++) + memset(dest + y * dest_stride, 0, sizeof(uint16_t) * 8); +} + +static const uint16_t mask_matrix[] = {0x1, 0x2, 0x10, 0x20, + 0x4, 0x8, 0x40, 0x80, + 0x100, 0x200, 0x1000, 0x2000, + 0x400, 0x800, 0x4000, 0x8000}; + +static int escape124_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + Escape124Context *s = avctx->priv_data; + AVFrame *frame = data; + + GetBitContext gb; + unsigned frame_flags, frame_size; + unsigned i; + + unsigned superblock_index, cb_index = 1, + superblock_col_index = 0, + superblocks_per_row = avctx->width / 8, skip = -1; + + uint16_t* old_frame_data, *new_frame_data; + unsigned old_stride, new_stride; + + int ret; + + init_get_bits(&gb, buf, buf_size * 8); + + // This call also guards the potential depth reads for the + // codebook unpacking. + if (!can_safely_read(&gb, 64)) + return -1; + + frame_flags = get_bits_long(&gb, 32); + frame_size = get_bits_long(&gb, 32); + + // Leave last frame unchanged + // FIXME: Is this necessary? I haven't seen it in any real samples + if (!(frame_flags & 0x114) || !(frame_flags & 0x7800000)) { + if (!s->frame.data[0]) + return AVERROR_INVALIDDATA; + + av_log(NULL, AV_LOG_DEBUG, "Skipping frame\n"); + + *got_frame = 1; + if ((ret = av_frame_ref(frame, &s->frame)) < 0) + return ret; + + return frame_size; + } + + for (i = 0; i < 3; i++) { + if (frame_flags & (1 << (17 + i))) { + unsigned cb_depth, cb_size; + if (i == 2) { + // This codebook can be cut off at places other than + // powers of 2, leaving some of the entries undefined. + cb_size = get_bits_long(&gb, 20); + cb_depth = av_log2(cb_size - 1) + 1; + } else { + cb_depth = get_bits(&gb, 4); + if (i == 0) { + // This is the most basic codebook: pow(2,depth) entries + // for a depth-length key + cb_size = 1 << cb_depth; + } else { + // This codebook varies per superblock + // FIXME: I don't think this handles integer overflow + // properly + cb_size = s->num_superblocks << cb_depth; + } + } + av_free(s->codebooks[i].blocks); + s->codebooks[i] = unpack_codebook(&gb, cb_depth, cb_size); + if (!s->codebooks[i].blocks) + return -1; + } + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + new_frame_data = (uint16_t*)frame->data[0]; + new_stride = frame->linesize[0] / 2; + old_frame_data = (uint16_t*)s->frame.data[0]; + old_stride = s->frame.linesize[0] / 2; + + for (superblock_index = 0; superblock_index < s->num_superblocks; + superblock_index++) { + MacroBlock mb; + SuperBlock sb; + unsigned multi_mask = 0; + + if (skip == -1) { + // Note that this call will make us skip the rest of the blocks + // if the frame prematurely ends + skip = decode_skip_count(&gb); + } + + if (skip) { + copy_superblock(new_frame_data, new_stride, + old_frame_data, old_stride); + } else { + copy_superblock(sb.pixels, 8, + old_frame_data, old_stride); + + while (can_safely_read(&gb, 1) && !get_bits1(&gb)) { + unsigned mask; + mb = decode_macroblock(s, &gb, &cb_index, superblock_index); + mask = get_bits(&gb, 16); + multi_mask |= mask; + for (i = 0; i < 16; i++) { + if (mask & mask_matrix[i]) { + insert_mb_into_sb(&sb, mb, i); + } + } + } + + if (can_safely_read(&gb, 1) && !get_bits1(&gb)) { + unsigned inv_mask = get_bits(&gb, 4); + for (i = 0; i < 4; i++) { + if (inv_mask & (1 << i)) { + multi_mask ^= 0xF << i*4; + } else { + multi_mask ^= get_bits(&gb, 4) << i*4; + } + } + + for (i = 0; i < 16; i++) { + if (multi_mask & mask_matrix[i]) { + if (!can_safely_read(&gb, 1)) + break; + mb = decode_macroblock(s, &gb, &cb_index, + superblock_index); + insert_mb_into_sb(&sb, mb, i); + } + } + } else if (frame_flags & (1 << 16)) { + while (can_safely_read(&gb, 1) && !get_bits1(&gb)) { + mb = decode_macroblock(s, &gb, &cb_index, superblock_index); + insert_mb_into_sb(&sb, mb, get_bits(&gb, 4)); + } + } + + copy_superblock(new_frame_data, new_stride, sb.pixels, 8); + } + + superblock_col_index++; + new_frame_data += 8; + if (old_frame_data) + old_frame_data += 8; + if (superblock_col_index == superblocks_per_row) { + new_frame_data += new_stride * 8 - superblocks_per_row * 8; + if (old_frame_data) + old_frame_data += old_stride * 8 - superblocks_per_row * 8; + superblock_col_index = 0; + } + skip--; + } + + av_log(NULL, AV_LOG_DEBUG, + "Escape sizes: %i, %i, %i\n", + frame_size, buf_size, get_bits_count(&gb) / 8); + + av_frame_unref(&s->frame); + if ((ret = av_frame_ref(&s->frame, frame)) < 0) + return ret; + + *got_frame = 1; + + return frame_size; +} + + +AVCodec ff_escape124_decoder = { + .name = "escape124", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ESCAPE124, + .priv_data_size = sizeof(Escape124Context), + .init = escape124_decode_init, + .close = escape124_decode_close, + .decode = escape124_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Escape 124"), +}; diff --git a/ffmpeg/libavcodec/escape130.c b/ffmpeg/libavcodec/escape130.c new file mode 100644 index 0000000..d24af79 --- /dev/null +++ b/ffmpeg/libavcodec/escape130.c @@ -0,0 +1,319 @@ +/* + * Escape 130 Video Decoder + * Copyright (C) 2008 Eli Friedman (eli.friedman gmail.com) + * + * 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 "avcodec.h" + +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" + + +typedef struct Escape130Context { + AVFrame frame; + uint8_t *bases; +} Escape130Context; + +/** + * Initialize the decoder + * @param avctx decoder context + * @return 0 success, negative on error + */ +static av_cold int escape130_decode_init(AVCodecContext *avctx) +{ + Escape130Context *s = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avcodec_get_frame_defaults(&s->frame); + + if((avctx->width&1) || (avctx->height&1)){ + av_log(avctx, AV_LOG_ERROR, "Dimensions are not a multiple of the block size\n"); + return AVERROR(EINVAL); + } + + s->bases= av_malloc(avctx->width * avctx->height /4); + + return 0; +} + +static av_cold int escape130_decode_close(AVCodecContext *avctx) +{ + Escape130Context *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + av_freep(&s->bases); + + return 0; +} + +static unsigned decode_skip_count(GetBitContext* gb) { + unsigned value; + // This function reads a maximum of 27 bits, + // which is within the padding space + if (get_bits_left(gb) < 1+3) + return -1; + + value = get_bits1(gb); + if (value) + return 0; + + value = get_bits(gb, 3); + if (value) + return value; + + value = get_bits(gb, 8); + if (value) + return value + 7; + + value = get_bits(gb, 15); + if (value) + return value + 262; + + return -1; +} + +/** + * Decode a single frame + * @param avctx decoder context + * @param data decoded frame + * @param got_frame have decoded frame + * @param buf input buffer + * @param buf_size input buffer size + * @return 0 success, -1 on error + */ +static int escape130_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + Escape130Context *s = avctx->priv_data; + + GetBitContext gb; + unsigned i; + int ret; + + uint8_t *old_y, *old_cb, *old_cr, + *new_y, *new_cb, *new_cr; + unsigned old_y_stride, old_cb_stride, old_cr_stride, + new_y_stride, new_cb_stride, new_cr_stride; + unsigned total_blocks = avctx->width * avctx->height / 4, + block_index, row_index = 0; + unsigned y[4] = {0}, cb = 16, cr = 16; + unsigned skip = -1; + unsigned y_base = 0; + uint8_t *yb= s->bases; + + AVFrame *frame = data; + + init_get_bits(&gb, buf, buf_size * 8); + + if (get_bits_left(&gb) < 128) + return -1; + + // Header; no useful information in here + skip_bits_long(&gb, 128); + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + new_y = frame->data[0]; + new_cb = frame->data[1]; + new_cr = frame->data[2]; + new_y_stride = frame->linesize[0]; + new_cb_stride = frame->linesize[1]; + new_cr_stride = frame->linesize[2]; + old_y = s->frame.data[0]; + old_cb = s->frame.data[1]; + old_cr = s->frame.data[2]; + old_y_stride = s->frame.linesize[0]; + old_cb_stride = s->frame.linesize[1]; + old_cr_stride = s->frame.linesize[2]; + + av_log(avctx, AV_LOG_DEBUG, + "Strides: %i, %i\n", + new_y_stride, new_cb_stride); + + for (block_index = 0; block_index < total_blocks; block_index++) { + // Note that this call will make us skip the rest of the blocks + // if the frame prematurely ends + if (skip == -1) + skip = decode_skip_count(&gb); + + if (skip) { + if (old_y) { + y[0] = old_y[0] / 4; + y[1] = old_y[1] / 4; + y[2] = old_y[old_y_stride] / 4; + y[3] = old_y[old_y_stride+1] / 4; + y_base= yb[0]; + cb = old_cb[0] / 8; + cr = old_cr[0] / 8; + } else { + y_base=y[0] = y[1] = y[2] = y[3] = 0; + cb = cr = 16; + } + } else { + if (get_bits1(&gb)) { + static const uint8_t offset_table[] = {2, 4, 10, 20}; + static const int8_t sign_table[64][4] = + { {0, 0, 0, 0}, + {-1, 1, 0, 0}, + {1, -1, 0, 0}, + {-1, 0, 1, 0}, + {-1, 1, 1, 0}, + {0, -1, 1, 0}, + {1, -1, 1, 0}, + {-1, -1, 1, 0}, + {1, 0, -1, 0}, + {0, 1, -1, 0}, + {1, 1, -1, 0}, + {-1, 1, -1, 0}, + {1, -1, -1, 0}, + {-1, 0, 0, 1}, + {-1, 1, 0, 1}, + {0, -1, 0, 1}, + + {0, 0, 0, 0}, + {1, -1, 0, 1}, + {-1, -1, 0, 1}, + {-1, 0, 1, 1}, + {-1, 1, 1, 1}, + {0, -1, 1, 1}, + {1, -1, 1, 1}, + {-1, -1, 1, 1}, + {0, 0, -1, 1}, + {1, 0, -1, 1}, + {-1, 0, -1, 1}, + {0, 1, -1, 1}, + {1, 1, -1, 1}, + {-1, 1, -1, 1}, + {0, -1, -1, 1}, + {1, -1, -1, 1}, + + {0, 0, 0, 0}, + {-1, -1, -1, 1}, + {1, 0, 0, -1}, + {0, 1, 0, -1}, + {1, 1, 0, -1}, + {-1, 1, 0, -1}, + {1, -1, 0, -1}, + {0, 0, 1, -1}, + {1, 0, 1, -1}, + {-1, 0, 1, -1}, + {0, 1, 1, -1}, + {1, 1, 1, -1}, + {-1, 1, 1, -1}, + {0, -1, 1, -1}, + {1, -1, 1, -1}, + {-1, -1, 1, -1}, + + {0, 0, 0, 0}, + {1, 0, -1, -1}, + {0, 1, -1, -1}, + {1, 1, -1, -1}, + {-1, 1, -1, -1}, + {1, -1, -1, -1} }; + unsigned sign_selector = get_bits(&gb, 6); + unsigned difference_selector = get_bits(&gb, 2); + y_base = 2 * get_bits(&gb, 5); + for (i = 0; i < 4; i++) { + y[i] = av_clip((int)y_base + offset_table[difference_selector] * + sign_table[sign_selector][i], 0, 63); + } + } else if (get_bits1(&gb)) { + if (get_bits1(&gb)) { + y_base = get_bits(&gb, 6); + } else { + unsigned adjust_index = get_bits(&gb, 3); + static const int8_t adjust[] = {-4, -3, -2, -1, 1, 2, 3, 4}; + y_base = (y_base + adjust[adjust_index]) & 63; + } + for (i = 0; i < 4; i++) + y[i] = y_base; + } + + if (get_bits1(&gb)) { + if (get_bits1(&gb)) { + cb = get_bits(&gb, 5); + cr = get_bits(&gb, 5); + } else { + unsigned adjust_index = get_bits(&gb, 3); + static const int8_t adjust[2][8] = + { { 1, 1, 0, -1, -1, -1, 0, 1 }, + { 0, 1, 1, 1, 0, -1, -1, -1 } }; + cb = (cb + adjust[0][adjust_index]) & 31; + cr = (cr + adjust[1][adjust_index]) & 31; + } + } + } + *yb++= y_base; + + new_y[0] = y[0] * 4; + new_y[1] = y[1] * 4; + new_y[new_y_stride] = y[2] * 4; + new_y[new_y_stride + 1] = y[3] * 4; + *new_cb = cb * 8; + *new_cr = cr * 8; + + if (old_y) + old_y += 2, old_cb++, old_cr++; + new_y += 2, new_cb++, new_cr++; + row_index++; + if (avctx->width / 2 == row_index) { + row_index = 0; + if (old_y) { + old_y += old_y_stride * 2 - avctx->width; + old_cb += old_cb_stride - avctx->width / 2; + old_cr += old_cr_stride - avctx->width / 2; + } + new_y += new_y_stride * 2 - avctx->width; + new_cb += new_cb_stride - avctx->width / 2; + new_cr += new_cr_stride - avctx->width / 2; + } + + skip--; + } + + av_log(avctx, AV_LOG_DEBUG, + "Escape sizes: %i, %i\n", + buf_size, get_bits_count(&gb) / 8); + + av_frame_unref(&s->frame); + if ((ret = av_frame_ref(&s->frame, frame)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + + +AVCodec ff_escape130_decoder = { + .name = "escape130", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ESCAPE130, + .priv_data_size = sizeof(Escape130Context), + .init = escape130_decode_init, + .close = escape130_decode_close, + .decode = escape130_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Escape 130"), +}; diff --git a/ffmpeg/libavcodec/evrcdata.h b/ffmpeg/libavcodec/evrcdata.h new file mode 100644 index 0000000..cde1f57 --- /dev/null +++ b/ffmpeg/libavcodec/evrcdata.h @@ -0,0 +1,1499 @@ +/* + * Enhanced Variable Rate Codec, Service Option 3 decoder + * Copyright (c) 2013 Paul B Mahol + * + * 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 + */ + +#ifndef AVCODEC_EVRCDATA_H +#define AVCODEC_EVRCDATA_H + +/** + * @file + * Data tables for the EVRC decoder + * @author Paul B Mahol + */ + +#include "libavutil/common.h" + +/** + * Rate 1/8 frame energy quantization + * + * TIA/IS-127 table 8-18 + */ +static const float evrc_energy_quant[][3] = { +{-0.2464E-01,-0.4005E-02,-0.1107E+00 }, { 0.8734E+00, 0.1004E+01, 0.9930E+00 }, +{ 0.4222E+00, 0.3894E+00, 0.5020E+00 }, { 0.1450E+01, 0.1328E+01, 0.1278E+01 }, +{ 0.1957E+00, 0.2169E+00, 0.2735E+00 }, { 0.1142E+01, 0.1240E+01, 0.1157E+01 }, +{ 0.7881E+00, 0.6778E+00, 0.4185E+00 }, { 0.1504E+01, 0.1468E+01, 0.1534E+01 }, +{ 0.3173E+00, 0.2693E+00,-0.9526E-01 }, { 0.1141E+01, 0.1154E+01, 0.1044E+01 }, +{ 0.5147E+00, 0.5784E+00, 0.8802E+00 }, { 0.1502E+01, 0.1407E+01, 0.1409E+01 }, +{ 0.3163E+00, 0.3592E+00, 0.2830E+00 }, { 0.1217E+01, 0.1213E+01, 0.1216E+01 }, +{ 0.1023E+01, 0.1139E+01,-0.9526E-01 }, { 0.1619E+01, 0.1655E+01, 0.1642E+01 }, +{ 0.1437E+00, 0.1505E+00, 0.6838E-01 }, { 0.9794E+00, 0.1021E+01, 0.1117E+01 }, +{ 0.4701E+00, 0.6426E+00, 0.5519E+00 }, { 0.1366E+01, 0.1397E+01, 0.1406E+01 }, +{ 0.2918E+00, 0.3022E+00, 0.2420E+00 }, { 0.1309E+01, 0.1241E+01, 0.1220E+01 }, +{ 0.7989E+00, 0.7654E+00, 0.7391E+00 }, { 0.1612E+01, 0.1502E+01, 0.1447E+01 }, +{ 0.2594E+00, 0.1948E+00, 0.2555E+00 }, { 0.1091E+01, 0.1150E+01, 0.1272E+01 }, +{ 0.3423E+00, 0.4150E+00, 0.1294E+01 }, { 0.1729E+01, 0.1377E+01, 0.1065E+01 }, +{ 0.4103E+00, 0.3287E+00, 0.3228E+00 }, { 0.1144E+01, 0.1281E+01, 0.1416E+01 }, +{ 0.1047E+01, 0.1117E+01, 0.6188E+00 }, { 0.1914E+01, 0.1777E+01, 0.1516E+01 }, +{-0.2117E-01, 0.2159E+00, 0.2351E+00 }, { 0.1093E+01, 0.1088E+01, 0.1026E+01 }, +{ 0.5567E+00, 0.5092E+00, 0.4654E+00 }, { 0.1510E+01, 0.1449E+01, 0.1201E+01 }, +{ 0.2362E+00, 0.3426E+00, 0.2549E+00 }, { 0.1340E+01, 0.1225E+01, 0.1117E+01 }, +{ 0.1203E+01, 0.3819E+00, 0.2269E+00 }, { 0.1373E+01, 0.1404E+01, 0.1830E+01 }, +{ 0.2570E+00, 0.2668E+00, 0.1636E+00 }, { 0.1219E+01, 0.1098E+01, 0.1122E+01 }, +{ 0.6985E+00, 0.8456E+00, 0.1069E+01 }, { 0.1550E+01, 0.1501E+01, 0.1388E+01 }, +{ 0.2870E+00, 0.3060E+00, 0.3599E+00 }, { 0.1178E+01, 0.1345E+01, 0.1302E+01 }, +{ 0.1270E+01, 0.1215E+01, 0.1812E+00 }, { 0.1725E+01, 0.1777E+01, 0.1693E+01 }, +{ 0.2074E+00, 0.2104E+00, 0.1539E+00 }, { 0.1105E+01, 0.1034E+01, 0.1104E+01 }, +{ 0.6683E+00, 0.6646E+00, 0.6639E+00 }, { 0.1403E+01, 0.1462E+01, 0.1435E+01 }, +{ 0.3389E+00, 0.3754E+00, 0.2150E+00 }, { 0.1288E+01, 0.1325E+01, 0.1257E+01 }, +{ 0.8933E+00, 0.8253E+00, 0.8133E+00 }, { 0.1555E+01, 0.1579E+01, 0.1565E+01 }, +{ 0.3264E+00, 0.2434E+00, 0.2852E+00 }, { 0.1242E+01, 0.1180E+01, 0.1202E+01 }, +{ 0.1314E+00, 0.1698E+00, 0.1646E+01 }, { 0.1797E+01, 0.1597E+01, 0.1241E+01 }, +{ 0.4721E+00, 0.5346E+00, 0.3066E+00 }, { 0.1274E+01, 0.1401E+01, 0.1351E+01 }, +{ 0.1455E+01, 0.1386E+01, 0.6430E+00 }, { 0.1828E+01, 0.1867E+01, 0.1825E+01 }, +{-0.3265E+00,-0.2956E+00,-0.2462E+00 }, { 0.1035E+01, 0.1020E+01, 0.1003E+01 }, +{ 0.3702E+00, 0.4307E+00, 0.7072E+00 }, { 0.1424E+01, 0.1345E+01, 0.1352E+01 }, +{ 0.2267E+00, 0.2680E+00, 0.3037E+00 }, { 0.1235E+01, 0.1249E+01, 0.1146E+01 }, +{ 0.9944E+00, 0.6485E+00, 0.5248E+00 }, { 0.1539E+01, 0.1492E+01, 0.1612E+01 }, +{ 0.3815E+00, 0.3360E+00,-0.9526E-01 }, { 0.1163E+01, 0.1144E+01, 0.1117E+01 }, +{ 0.6734E+00, 0.7656E+00, 0.1014E+01 }, { 0.1568E+01, 0.1438E+01, 0.1455E+01 }, +{ 0.3409E+00, 0.3317E+00, 0.3856E+00 }, { 0.1180E+01, 0.1284E+01, 0.1284E+01 }, +{ 0.1244E+01, 0.1214E+01,-0.9526E-01 }, { 0.1753E+01, 0.1598E+01, 0.1744E+01 }, +{ 0.1548E+00, 0.1388E+00, 0.2020E+00 }, { 0.1027E+01, 0.1133E+01, 0.1093E+01 }, +{ 0.3906E+00, 0.7505E+00, 0.5705E+00 }, { 0.1420E+01, 0.1357E+01, 0.1543E+01 }, +{ 0.3252E+00, 0.3136E+00, 0.2804E+00 }, { 0.1351E+01, 0.1309E+01, 0.1224E+01 }, +{ 0.8781E+00, 0.8095E+00, 0.7109E+00 }, { 0.1614E+01, 0.1580E+01, 0.1433E+01 }, +{ 0.3222E+00, 0.2298E+00, 0.2157E+00 }, { 0.1216E+01, 0.1077E+01, 0.1247E+01 }, +{ 0.1363E+01, 0.1280E+01, 0.1317E+01 }, { 0.1751E+01, 0.1457E+01, 0.1182E+01 }, +{ 0.4428E+00, 0.4082E+00, 0.3181E+00 }, { 0.1157E+01, 0.1227E+01, 0.1604E+01 }, +{ 0.1286E+01, 0.1268E+01, 0.8167E+00 }, { 0.1994E+01, 0.2018E+01, 0.1307E+01 }, +{ 0.2671E-01, 0.2594E+00, 0.3397E+00 }, { 0.1164E+01, 0.1080E+01, 0.9321E+00 }, +{ 0.5998E+00, 0.6076E+00, 0.5081E+00 }, { 0.1442E+01, 0.1442E+01, 0.1375E+01 }, +{ 0.2390E+00, 0.3554E+00, 0.3426E+00 }, { 0.1287E+01, 0.1307E+01, 0.1144E+01 }, +{ 0.1200E+01, 0.7495E+00, 0.3967E+00 }, { 0.1561E+01, 0.1517E+01, 0.1898E+01 }, +{ 0.3598E+00, 0.3463E+00, 0.1200E+00 }, { 0.1298E+01, 0.1125E+01, 0.1062E+01 }, +{ 0.7577E+00, 0.1013E+01, 0.1194E+01 }, { 0.1537E+01, 0.1513E+01, 0.1464E+01 }, +{ 0.4041E+00, 0.4038E+00, 0.3897E+00 }, { 0.1293E+01, 0.1219E+01, 0.1378E+01 }, +{ 0.1250E+01, 0.1391E+01, 0.2451E+00 }, { 0.1558E+01, 0.1764E+01, 0.1728E+01 }, +{ 0.2700E+00, 0.1894E+00, 0.1924E+00 }, { 0.1111E+01, 0.1112E+01, 0.1173E+01 }, +{ 0.7579E+00, 0.8342E+00, 0.4781E+00 }, { 0.1464E+01, 0.1477E+01, 0.1469E+01 }, +{ 0.4001E+00, 0.3104E+00, 0.2217E+00 }, { 0.1346E+01, 0.1421E+01, 0.1312E+01 }, +{ 0.1071E+01, 0.8967E+00, 0.7511E+00 }, { 0.1616E+01, 0.1551E+01, 0.1574E+01 }, +{ 0.3329E+00, 0.2785E+00, 0.3140E+00 }, { 0.1281E+01, 0.1209E+01, 0.1239E+01 }, +{ 0.2805E+00, 0.2687E+00, 0.1646E+01 }, { 0.1814E+01, 0.1514E+01, 0.1510E+01 }, +{ 0.6231E+00, 0.4200E+00, 0.3701E+00 }, { 0.1255E+01, 0.1429E+01, 0.1454E+01 }, +{ 0.1642E+01, 0.1581E+01, 0.7112E+00 }, { 0.1844E+01, 0.1963E+01, 0.1895E+01 }, +{-0.4208E-01,-0.1491E+00,-0.7639E-01 }, { 0.1046E+01, 0.9598E+00, 0.9176E+00 }, +{ 0.4478E+00, 0.4605E+00, 0.5111E+00 }, { 0.1521E+01, 0.1292E+01, 0.1342E+01 }, +{ 0.2220E+00, 0.2549E+00, 0.2510E+00 }, { 0.1186E+01, 0.1254E+01, 0.1171E+01 }, +{ 0.8999E+00, 0.4960E+00, 0.4943E+00 }, { 0.1423E+01, 0.1484E+01, 0.1620E+01 }, +{ 0.2796E+00, 0.2778E+00,-0.2820E+00 }, { 0.1170E+01, 0.1181E+01, 0.1076E+01 }, +{ 0.4068E+00, 0.8541E+00, 0.9352E+00 }, { 0.1584E+01, 0.1416E+01, 0.1387E+01 }, +{ 0.3325E+00, 0.3655E+00, 0.3340E+00 }, { 0.1224E+01, 0.1257E+01, 0.1245E+01 }, +{ 0.1061E+01, 0.1138E+01,-0.9526E-01 }, { 0.1681E+01, 0.1704E+01, 0.1673E+01 }, +{ 0.1932E+00, 0.1489E+00, 0.1258E+00 }, { 0.1023E+01, 0.1088E+01, 0.1145E+01 }, +{ 0.5190E+00, 0.6873E+00, 0.5172E+00 }, { 0.1380E+01, 0.1405E+01, 0.1474E+01 }, +{ 0.3393E+00, 0.3100E+00, 0.2231E+00 }, { 0.1354E+01, 0.1249E+01, 0.1270E+01 }, +{ 0.7363E+00, 0.8508E+00, 0.8247E+00 }, { 0.1612E+01, 0.1537E+01, 0.1509E+01 }, +{ 0.2952E+00, 0.2053E+00, 0.2590E+00 }, { 0.1138E+01, 0.1219E+01, 0.1262E+01 }, +{ 0.1345E+01, 0.1289E+01, 0.1338E+01 }, { 0.1437E+01, 0.1360E+01, 0.1442E+01 }, +{ 0.4826E+00, 0.3298E+00, 0.3842E+00 }, { 0.1219E+01, 0.1311E+01, 0.1413E+01 }, +{ 0.1212E+01, 0.1186E+01, 0.6357E+00 }, { 0.1873E+01, 0.1939E+01, 0.1674E+01 }, +{ 0.1260E+01, 0.1306E+01, 0.1368E+01 }, { 0.1146E+01, 0.1077E+01, 0.1025E+01 }, +{ 0.6029E+00, 0.5039E+00, 0.5781E+00 }, { 0.1514E+01, 0.1420E+01, 0.1324E+01 }, +{ 0.2652E+00, 0.3192E+00, 0.3042E+00 }, { 0.1368E+01, 0.1198E+01, 0.1200E+01 }, +{ 0.1234E+01, 0.4910E+00, 0.3464E-01 }, { 0.1347E+01, 0.1560E+01, 0.1861E+01 }, +{ 0.2766E+00, 0.2887E+00, 0.2029E+00 }, { 0.1257E+01, 0.1105E+01, 0.1145E+01 }, +{ 0.1351E+01, 0.1353E+01, 0.1406E+01 }, { 0.1506E+01, 0.1580E+01, 0.1362E+01 }, +{ 0.2794E+00, 0.3868E+00, 0.4277E+00 }, { 0.1234E+01, 0.1334E+01, 0.1336E+01 }, +{ 0.1280E+01, 0.1252E+01, 0.1805E+00 }, { 0.1387E+01, 0.1396E+01, 0.1434E+01 }, +{ 0.2902E+00, 0.1170E+00, 0.1698E+00 }, { 0.1134E+01, 0.1077E+01, 0.1117E+01 }, +{ 0.6986E+00, 0.7177E+00, 0.7366E+00 }, { 0.1370E+01, 0.1491E+01, 0.1495E+01 }, +{ 0.4031E+00, 0.5144E+00, 0.1751E+00 }, { 0.1333E+01, 0.1377E+01, 0.1257E+01 }, +{ 0.9212E+00, 0.8934E+00, 0.8897E+00 }, { 0.1589E+01, 0.1614E+01, 0.1523E+01 }, +{ 0.3152E+00, 0.2164E+00, 0.3230E+00 }, { 0.1300E+01, 0.1145E+01, 0.1212E+01 }, +{ 0.1269E+01, 0.1245E+01, 0.1497E+01 }, { 0.1763E+01, 0.1716E+01, 0.1311E+01 }, +{ 0.4702E+00, 0.5422E+00, 0.4306E+00 }, { 0.1342E+01, 0.1433E+01, 0.1423E+01 }, +{ 0.1472E+01, 0.1404E+01, 0.8371E+00 }, { 0.1936E+01, 0.1883E+01, 0.1838E+01 }, +{ 0.1266E+01, 0.1295E+01, 0.1302E+01 }, { 0.1074E+01, 0.1002E+01, 0.1023E+01 }, +{ 0.5206E+00, 0.4045E+00, 0.6549E+00 }, { 0.1457E+01, 0.1378E+01, 0.1363E+01 }, +{ 0.2715E+00, 0.2629E+00, 0.2841E+00 }, { 0.1264E+01, 0.1271E+01, 0.1175E+01 }, +{ 0.1337E+01, 0.1305E+01, 0.1306E+01 }, { 0.1555E+01, 0.1571E+01, 0.1657E+01 }, +{ 0.3341E+00, 0.4147E+00,-0.3648E+00 }, { 0.1188E+01, 0.1185E+01, 0.1161E+01 }, +{ 0.6198E+00, 0.7208E+00, 0.1157E+01 }, { 0.1582E+01, 0.1465E+01, 0.1513E+01 }, +{ 0.3839E+00, 0.3651E+00, 0.3814E+00 }, { 0.1214E+01, 0.1256E+01, 0.1292E+01 }, +{ 0.1361E+01, 0.1363E+01, 0.1312E+01 }, { 0.1793E+01, 0.1693E+01, 0.1669E+01 }, +{ 0.1889E+00, 0.1275E+00, 0.2534E+00 }, { 0.1066E+01, 0.1174E+01, 0.1133E+01 }, +{ 0.4999E+00, 0.8207E+00, 0.5813E+00 }, { 0.1478E+01, 0.1416E+01, 0.1497E+01 }, +{ 0.3814E+00, 0.3138E+00, 0.2889E+00 }, { 0.1396E+01, 0.1265E+01, 0.1233E+01 }, +{ 0.9458E+00, 0.9161E+00, 0.5875E+00 }, { 0.1672E+01, 0.1632E+01, 0.1553E+01 }, +{ 0.3505E+00, 0.2525E+00, 0.2364E+00 }, { 0.1211E+01, 0.1138E+01, 0.1235E+01 }, +{ 0.1391E+01, 0.1231E+01, 0.1355E+01 }, { 0.1783E+01, 0.1510E+01, 0.1199E+01 }, +{ 0.4227E+00, 0.4548E+00, 0.3671E+00 }, { 0.1281E+01, 0.1254E+01, 0.1661E+01 }, +{ 0.1338E+01, 0.1379E+01, 0.9531E+00 }, { 0.2148E+01, 0.1965E+01, 0.1584E+01 }, +{ 0.9324E-01, 0.3575E+00, 0.3522E+00 }, { 0.1212E+01, 0.1086E+01, 0.1044E+01 }, +{ 0.6128E+00, 0.6136E+00, 0.6060E+00 }, { 0.1484E+01, 0.1507E+01, 0.1396E+01 }, +{ 0.2820E+00, 0.3848E+00, 0.3156E+00 }, { 0.1368E+01, 0.1287E+01, 0.1128E+01 }, +{ 0.1369E+01, 0.1352E+01, 0.1358E+01 }, { 0.1381E+01, 0.1765E+01, 0.2113E+01 }, +{ 0.1314E+01, 0.1345E+01, 0.1334E+01 }, { 0.1290E+01, 0.1172E+01, 0.1119E+01 }, +{ 0.1304E+01, 0.1377E+01, 0.1427E+01 }, { 0.1490E+01, 0.1540E+01, 0.1536E+01 }, +{ 0.3994E+00, 0.4402E+00, 0.4173E+00 }, { 0.1323E+01, 0.1307E+01, 0.1392E+01 }, +{ 0.1400E+01, 0.1388E+01, 0.1369E+01 }, { 0.1669E+01, 0.1818E+01, 0.1834E+01 }, +{ 0.2742E+00, 0.2235E+00, 0.1986E+00 }, { 0.1137E+01, 0.1139E+01, 0.1201E+01 }, +{ 0.1324E+01, 0.1385E+01, 0.1349E+01 }, { 0.1455E+01, 0.1574E+01, 0.1454E+01 }, +{ 0.5019E+00, 0.3255E+00, 0.2555E+00 }, { 0.1388E+01, 0.1438E+01, 0.1300E+01 }, +{ 0.1394E+01, 0.1349E+01, 0.1411E+01 }, { 0.1639E+01, 0.1580E+01, 0.1681E+01 }, +{ 0.3920E+00, 0.2498E+00, 0.3523E+00 }, { 0.1301E+01, 0.1221E+01, 0.1285E+01 }, +{ 0.1318E+01, 0.1342E+01, 0.1494E+01 }, { 0.1910E+01, 0.1680E+01, 0.1470E+01 }, +{ 0.6082E+00, 0.5270E+00, 0.4173E+00 }, { 0.1255E+01, 0.1477E+01, 0.1503E+01 }, +{ 0.1807E+01, 0.1742E+01, 0.6553E+00 }, { 0.2000E+01, 0.2072E+01, 0.2051E+01 }}; + +/** + * LSP vector quantization tables + * + * TIA/IS-127 tables 8-1 through 8-9 + */ + +static const float evrc_lspq_full_codebook1[64][2] = { +{1.42016308E-2, 1.93881616E-2}, {2.91667543E-2, 6.51749149E-2}, +{2.06693150E-2, 4.97564934E-2}, {3.94719802E-2, 9.55850929E-2}, +{2.27012448E-2, 3.96625809E-2}, {5.38789518E-2, 6.28347769E-2}, +{2.90525518E-2, 5.73435798E-2}, {4.48280610E-2, 1.15364626E-1}, +{1.94110647E-2, 3.46889682E-2}, {4.37502973E-2, 6.75228462E-2}, +{3.55497338E-2, 4.94086780E-2}, {6.99219853E-2, 8.67279768E-2}, +{2.77880151E-2, 4.65748496E-2}, {5.79111017E-2, 6.74542487E-2}, +{4.74664383E-2, 5.50271496E-2}, {7.88898915E-2, 1.22443043E-1}, +{2.21715886E-2, 3.02628800E-2}, {3.39134485E-2, 7.17703998E-2}, +{3.17989141E-2, 4.98996116E-2}, {6.11555986E-2, 8.73361230E-2}, +{2.67506503E-2, 3.96735854E-2}, {4.44100983E-2, 8.26731324E-2}, +{3.89172547E-2, 5.65788932E-2}, {6.04800619E-2, 1.04536951E-1}, +{2.69156620E-2, 3.57168876E-2}, {4.11117189E-2, 7.33322948E-2}, +{4.12660725E-2, 4.85165231E-2}, {7.18049556E-2, 1.06202349E-1}, +{3.38037871E-2, 4.24300395E-2}, {5.91818243E-2, 7.97467977E-2}, +{4.70107906E-2, 6.28563762E-2}, {9.42011923E-2, 1.30053163E-1}, +{1.94244273E-2, 2.72732340E-2}, {3.70831676E-2, 6.64898157E-2}, +{2.80136354E-2, 5.15984930E-2}, {5.34461029E-2, 9.25904214E-2}, +{2.54959203E-2, 4.32844795E-2}, {5.51860742E-2, 7.36182332E-2}, +{3.39851119E-2, 6.05329126E-2}, {6.18182123E-2, 1.34581268E-1}, +{2.35669166E-2, 3.55242006E-2}, {5.10804243E-2, 6.79562539E-2}, +{3.83464955E-2, 5.23469411E-2}, {7.44275749E-2, 9.66108292E-2}, +{3.18591148E-2, 4.62123118E-2}, {6.18909821E-2, 7.33231753E-2}, +{4.41718437E-2, 5.79240918E-2}, {7.93596208E-2, 1.41177371E-1}, +{2.47412287E-2, 3.23629379E-2}, {3.36563922E-2, 8.04650635E-2}, +{3.37943695E-2, 5.44977151E-2}, {6.53648973E-2, 9.52775925E-2}, +{2.93364152E-2, 4.28411029E-2}, {5.27870469E-2, 8.16159397E-2}, +{4.00724895E-2, 6.18144684E-2}, {6.75848573E-2, 1.17196076E-1}, +{3.03064957E-2, 3.86914052E-2}, {4.83106263E-2, 7.42383003E-2}, +{4.37548272E-2, 5.22842295E-2}, {8.32310021E-2, 1.09881967E-1}, +{3.75600643E-2, 4.53217216E-2}, {6.60113171E-2, 7.97580183E-2}, +{5.03225066E-2, 5.90176322E-2}, {8.77133310E-2, 1.63187444E-1}}; + +static const float evrc_lspq_full_codebook2[64][2] = { +{5.21959551E-2, 8.38445649E-2}, {1.05874076E-1, 1.28694162E-1}, +{5.48323877E-2, 1.33842856E-1}, {1.17768474E-1, 1.94037274E-1}, +{5.36086522E-2, 1.11398734E-1}, {1.19989693E-1, 1.47474691E-1}, +{8.00373554E-2, 1.42999724E-1}, {1.64086595E-1, 2.09821835E-1}, +{5.21059223E-2, 9.95229408E-2}, {8.67567956E-2, 1.85966507E-1}, +{7.77341127E-2, 1.31506845E-1}, {1.60545513E-1, 1.81930289E-1}, +{7.42243677E-2, 1.10437103E-1}, {1.18635088E-1, 1.75306752E-1}, +{6.61557764E-2, 1.64441928E-1}, {1.96810856E-1, 2.16682002E-1}, +{6.05317838E-2, 9.45408568E-2}, {1.06271386E-1, 1.48013934E-1}, +{5.87486550E-2, 1.47724584E-1}, {1.34816468E-1, 2.01517954E-1}, +{6.59698322E-2, 1.16447397E-1}, {1.32297173E-1, 1.53267249E-1}, +{9.26660746E-2, 1.46725491E-1}, {1.79285541E-1, 2.19705954E-1}, +{7.06458464E-2, 9.99924466E-2}, {1.06500491E-1, 1.79443434E-1}, +{8.79249722E-2, 1.25287697E-1}, {1.53640196E-1, 1.97852716E-1}, +{8.88430104E-2, 1.12465657E-1}, {1.48286715E-1, 1.67517021E-1}, +{8.16568136E-2, 1.69274017E-1}, {2.07810536E-1, 2.31033549E-1}, +{6.14927970E-2, 8.36263224E-2}, {1.14473253E-1, 1.36779979E-1}, +{6.87129870E-2, 1.38099059E-1}, {1.10511415E-1, 2.15352878E-1}, +{5.55652268E-2, 1.22242786E-1}, {1.20557591E-1, 1.61072448E-1}, +{8.32249671E-2, 1.55475482E-1}, {1.61638483E-1, 2.28268847E-1}, +{6.29152283E-2, 1.06229566E-1}, {8.29186887E-2, 2.06774518E-1}, +{8.84756893E-2, 1.35799959E-1}, {1.69772223E-1, 1.93773940E-1}, +{7.77297840E-2, 1.20287232E-1}, {1.30648017E-1, 1.84331819E-1}, +{6.91939592E-2, 1.84218004E-1}, {2.03904077E-1, 2.49715164E-1}, +{7.07671717E-2, 9.03186128E-2}, {1.08471557E-1, 1.61966518E-1}, +{7.16886371E-2, 1.51093170E-1}, {1.38779536E-1, 2.18801782E-1}, +{6.75907061E-2, 1.26740307E-1}, {1.33412346E-1, 1.68838874E-1}, +{9.61822569E-2, 1.58728704E-1}, {1.86485633E-1, 2.36560926E-1}, +{8.23447108E-2, 1.02126025E-1}, {1.00336641E-1, 1.94918498E-1}, +{9.95981991E-2, 1.36425093E-1}, {1.82448462E-1, 2.03655198E-1}, +{9.78890732E-2, 1.21145472E-1}, {1.45453140E-1, 1.83604524E-1}, +{9.58395451E-2, 1.72194853E-1}, {2.23295853E-1, 2.46418610E-1}}; + +static const float evrc_lspq_full_codebook3[512][3] = { +{1.36425778E-1, 1.68651849E-1, 2.04688221E-1}, +{1.85717627E-1, 2.28756160E-1, 2.51958042E-1}, +{1.22760192E-1, 1.85950696E-1, 2.79446691E-1}, +{1.96468458E-1, 2.64484435E-1, 2.89318889E-1}, +{1.25653744E-1, 1.50529265E-1, 2.76144296E-1}, +{1.96301565E-1, 2.41699994E-1, 2.88230687E-1}, +{1.40099391E-1, 2.22365588E-1, 2.74666578E-1}, +{2.59952307E-1, 2.75394946E-1, 3.10975939E-1}, +{1.58452198E-1, 1.88591003E-1, 2.07339197E-1}, +{1.95616230E-1, 2.21379519E-1, 2.87022918E-1}, +{1.69424579E-1, 2.01614648E-1, 2.75669187E-1}, +{2.12393746E-1, 2.64250666E-1, 3.17967504E-1}, +{1.82965085E-1, 1.99547559E-1, 2.29538843E-1}, +{2.15200707E-1, 2.62409419E-1, 2.82432705E-1}, +{1.46404549E-1, 2.36966729E-1, 2.90067106E-1}, +{2.45338634E-1, 3.03358108E-1, 3.42260152E-1}, +{1.37478963E-1, 1.58276558E-1, 2.39217222E-1}, +{2.01999024E-1, 2.20102608E-1, 2.69546896E-1}, +{1.18350029E-1, 2.30206400E-1, 2.83554822E-1}, +{2.25519255E-1, 2.72272140E-1, 3.06072980E-1}, +{1.35661438E-1, 1.91633970E-1, 2.65912026E-1}, +{1.95733085E-1, 2.31926173E-1, 3.14376086E-1}, +{1.67998984E-1, 2.27706313E-1, 2.76947826E-1}, +{2.50170559E-1, 3.01627070E-1, 3.21084231E-1}, +{1.33492306E-1, 2.01223105E-1, 2.33893991E-1}, +{2.06442133E-1, 2.38704175E-1, 2.77560145E-1}, +{1.79048792E-1, 1.95776582E-1, 2.80656606E-1}, +{2.06193641E-1, 2.64055401E-1, 3.33098441E-1}, +{1.75185278E-1, 1.91166341E-1, 2.57540315E-1}, +{2.28398636E-1, 2.45296657E-1, 3.08980793E-1}, +{1.80859819E-1, 2.43579060E-1, 2.96631068E-1}, +{2.76152968E-1, 3.08256060E-1, 3.46822590E-1}, +{1.37115732E-1, 1.80057764E-1, 2.20953465E-1}, +{1.81370094E-1, 2.26770103E-1, 2.70392686E-1}, +{1.25246510E-1, 1.79606944E-1, 3.10376436E-1}, +{1.90708354E-1, 2.87734240E-1, 3.13476235E-1}, +{1.30486086E-1, 1.60435289E-1, 3.00243706E-1}, +{1.97318628E-1, 2.56378502E-1, 2.78474301E-1}, +{1.58597067E-1, 2.37381399E-1, 2.62910336E-1}, +{2.61825919E-1, 2.77717203E-1, 3.31382245E-1}, +{1.64160743E-1, 1.85841531E-1, 2.35615849E-1}, +{2.09486142E-1, 2.21452802E-1, 2.92153865E-1}, +{1.66807845E-1, 2.13641763E-1, 2.70675927E-1}, +{2.29834273E-1, 2.88374633E-1, 3.06238323E-1}, +{1.82154253E-1, 2.00822473E-1, 2.40169376E-1}, +{2.24944726E-1, 2.69813925E-1, 2.91401237E-1}, +{1.63940564E-1, 2.50341147E-1, 2.78307766E-1}, +{2.56727993E-1, 2.95103759E-1, 3.53297085E-1}, +{1.40218839E-1, 1.76687688E-1, 2.46773273E-1}, +{2.15291306E-1, 2.29216009E-1, 2.64283627E-1}, +{1.21002659E-1, 2.18333840E-1, 3.22341293E-1}, +{2.54243195E-1, 2.73986191E-1, 2.96262473E-1}, +{1.60385415E-1, 1.83762908E-1, 2.81598717E-1}, +{1.87832162E-1, 2.37420350E-1, 3.29777509E-1}, +{1.77788362E-1, 2.26703495E-1, 3.02322537E-1}, +{2.75108218E-1, 2.93730587E-1, 3.12373787E-1}, +{1.70116410E-1, 1.85232103E-1, 2.46125028E-1}, +{2.21754774E-1, 2.39912242E-1, 2.86891907E-1}, +{1.95083722E-1, 2.08337873E-1, 2.88349718E-1}, +{2.37536535E-1, 2.75004476E-1, 3.39786023E-1}, +{1.88369319E-1, 2.04371840E-1, 2.57375032E-1}, +{2.47250155E-1, 2.60551840E-1, 3.02137524E-1}, +{1.66944191E-1, 2.46912360E-1, 3.18894416E-1}, +{2.78118610E-1, 3.13011140E-1, 3.65329295E-1}, +{1.45213529E-1, 1.63051456E-1, 2.24912614E-1}, +{2.05692515E-1, 2.20831484E-1, 2.52817810E-1}, +{1.21125661E-1, 1.96374118E-1, 3.00122708E-1}, +{2.15566799E-1, 2.65657336E-1, 2.99202889E-1}, +{1.09134212E-1, 1.78472102E-1, 2.88323194E-1}, +{2.03508541E-1, 2.40347922E-1, 2.96309739E-1}, +{1.53101787E-1, 2.25415319E-1, 2.84843713E-1}, +{2.50233442E-1, 2.77736932E-1, 3.24840695E-1}, +{1.66308925E-1, 1.94173396E-1, 2.11635381E-1}, +{2.01289460E-1, 2.26062179E-1, 2.93246478E-1}, +{1.49518773E-1, 2.14201719E-1, 2.83894747E-1}, +{2.21836135E-1, 2.85231501E-1, 3.20082635E-1}, +{1.89573213E-1, 2.06577629E-1, 2.30332345E-1}, +{2.31247649E-1, 2.46864259E-1, 2.89846569E-1}, +{1.39116928E-1, 2.59189934E-1, 2.98019558E-1}, +{2.44512573E-1, 2.82671362E-1, 3.61258298E-1}, +{1.22530967E-1, 1.68514788E-1, 2.70879298E-1}, +{2.04372838E-1, 2.30398357E-1, 2.71792918E-1}, +{1.42643943E-1, 2.22405583E-1, 2.92057186E-1}, +{2.42643669E-1, 2.77429372E-1, 2.97135502E-1}, +{1.52048603E-1, 1.96921080E-1, 2.61013240E-1}, +{2.17875019E-1, 2.45840371E-1, 3.08138579E-1}, +{1.90109268E-1, 2.31099129E-1, 2.80178159E-1}, +{2.54314184E-1, 2.94079810E-1, 3.39649171E-1}, +{1.56698599E-1, 2.08597451E-1, 2.28010774E-1}, +{2.25088730E-1, 2.50014484E-1, 2.76250154E-1}, +{1.78219035E-1, 1.98228240E-1, 3.04198891E-1}, +{2.08567217E-1, 2.92395383E-1, 3.46786886E-1}, +{1.71052113E-1, 2.03438759E-1, 2.62644321E-1}, +{2.30275467E-1, 2.58817524E-1, 3.11986536E-1}, +{1.85333565E-1, 2.45760202E-1, 3.10553998E-1}, +{2.89413869E-1, 3.11095625E-1, 3.46476167E-1}, +{1.50332406E-1, 1.67538226E-1, 2.40182847E-1}, +{1.79971650E-1, 2.37168610E-1, 2.60899693E-1}, +{1.49866179E-1, 1.97890073E-1, 3.07916552E-1}, +{2.10799649E-1, 2.88180083E-1, 3.29747230E-1}, +{1.31711140E-1, 1.65906459E-1, 3.22898000E-1}, +{2.14832023E-1, 2.52822131E-1, 2.97547072E-1}, +{1.83760419E-1, 2.37523615E-1, 2.74610013E-1}, +{2.55575180E-1, 2.75439233E-1, 3.46021861E-1}, +{1.82662204E-1, 1.99470907E-1, 2.16051653E-1}, +{2.09240332E-1, 2.22406715E-1, 3.02382857E-1}, +{1.84088245E-1, 2.11327791E-1, 2.82538086E-1}, +{2.41171077E-1, 2.97036022E-1, 3.15979272E-1}, +{1.96804658E-1, 2.11815894E-1, 2.41647676E-1}, +{2.42761984E-1, 2.58586556E-1, 2.93204397E-1}, +{1.58905461E-1, 2.65077025E-1, 2.89881319E-1}, +{2.58060575E-1, 3.18903178E-1, 3.47846836E-1}, +{1.48766384E-1, 1.66853935E-1, 2.66827434E-1}, +{2.15942249E-1, 2.29938298E-1, 2.76041597E-1}, +{1.38410494E-1, 2.39283442E-1, 3.27972382E-1}, +{2.43765280E-1, 2.88408488E-1, 3.06048721E-1}, +{1.70157120E-1, 1.89986289E-1, 2.81219155E-1}, +{2.19117031E-1, 2.58005291E-1, 3.26571971E-1}, +{1.92163572E-1, 2.23614186E-1, 2.98683077E-1}, +{2.73545444E-1, 3.12078089E-1, 3.30766588E-1}, +{1.62452087E-1, 2.04930902E-1, 2.53337711E-1}, +{2.23855302E-1, 2.37671077E-1, 3.03202003E-1}, +{1.93955287E-1, 2.12335557E-1, 3.07566851E-1}, +{2.29912683E-1, 2.97581047E-1, 3.37499231E-1}, +{1.89335391E-1, 2.04148144E-1, 2.78609782E-1}, +{2.42303565E-1, 2.73163110E-1, 3.15361649E-1}, +{1.55009672E-1, 2.88095146E-1, 3.35996419E-1}, +{2.73716152E-1, 3.31215471E-1, 3.62539083E-1}, +{1.52389362E-1, 1.72619134E-1, 1.90585673E-1}, +{1.96988270E-1, 2.26309747E-1, 2.46197492E-1}, +{1.20555148E-1, 2.06369758E-1, 2.81199783E-1}, +{1.93709418E-1, 2.71900505E-1, 3.01332921E-1}, +{1.36701152E-1, 1.54093146E-1, 2.82258362E-1}, +{1.97299168E-1, 2.53656298E-1, 2.90315062E-1}, +{1.43463776E-1, 2.43872911E-1, 2.75533706E-1}, +{2.58477271E-1, 2.73279876E-1, 3.21119100E-1}, +{1.54406175E-1, 1.93793535E-1, 2.15884149E-1}, +{2.05979452E-1, 2.24277020E-1, 2.85732359E-1}, +{1.74535319E-1, 2.08482355E-1, 2.79668540E-1}, +{2.18844578E-1, 2.72486299E-1, 3.27095598E-1}, +{1.77609727E-1, 2.12990195E-1, 2.39119649E-1}, +{2.29163751E-1, 2.59165913E-1, 2.83514649E-1}, +{1.57353148E-1, 2.39961296E-1, 3.04263145E-1}, +{2.45613828E-1, 3.16824526E-1, 3.42909366E-1}, +{1.42953232E-1, 1.61905348E-1, 2.53710240E-1}, +{2.10192814E-1, 2.22847700E-1, 2.71103770E-1}, +{1.26843944E-1, 2.16709048E-1, 2.97734648E-1}, +{2.31000140E-1, 2.80109137E-1, 2.99707443E-1}, +{1.52980462E-1, 1.93996876E-1, 2.72895664E-1}, +{2.12860718E-1, 2.41545349E-1, 3.16518754E-1}, +{1.71154693E-1, 2.22469687E-1, 2.93786496E-1}, +{2.51988232E-1, 3.04254979E-1, 3.31269950E-1}, +{1.33188918E-1, 2.07924992E-1, 2.55362093E-1}, +{2.12044910E-1, 2.42189646E-1, 2.88903743E-1}, +{1.84612468E-1, 2.01143622E-1, 2.86360770E-1}, +{2.18286708E-1, 2.76752442E-1, 3.44581515E-1}, +{1.83562174E-1, 1.99478507E-1, 2.62156576E-1}, +{2.33130530E-1, 2.49596909E-1, 3.15842837E-1}, +{1.89898983E-1, 2.46874869E-1, 2.97132462E-1}, +{2.75022447E-1, 3.22490305E-1, 3.46977681E-1}, +{1.42305329E-1, 1.92689180E-1, 2.16155857E-1}, +{1.95676163E-1, 2.22268641E-1, 2.76587397E-1}, +{1.33241490E-1, 1.97791785E-1, 3.22897941E-1}, +{1.84865132E-1, 2.97106177E-1, 3.26105148E-1}, +{1.50203660E-1, 1.76781267E-1, 2.91536182E-1}, +{2.03144446E-1, 2.59616166E-1, 2.99156040E-1}, +{1.65488973E-1, 2.38342047E-1, 2.87493914E-1}, +{2.71071255E-1, 2.89544493E-1, 3.19521040E-1}, +{1.68598369E-1, 1.98825568E-1, 2.30347604E-1}, +{2.13811651E-1, 2.34471768E-1, 2.90959626E-1}, +{1.74605444E-1, 2.17256010E-1, 2.85688072E-1}, +{2.28503481E-1, 2.96190292E-1, 3.16534668E-1}, +{1.87172607E-1, 2.20547438E-1, 2.39688724E-1}, +{2.28884771E-1, 2.63583153E-1, 3.01329464E-1}, +{1.77897051E-1, 2.58131474E-1, 2.81487674E-1}, +{2.59513617E-1, 3.07204396E-1, 3.48793596E-1}, +{1.45224437E-1, 1.78715974E-1, 2.59186983E-1}, +{2.19062313E-1, 2.38223523E-1, 2.60461539E-1}, +{1.43650874E-1, 2.09760785E-1, 3.15830201E-1}, +{2.50127465E-1, 2.79182345E-1, 3.05153579E-1}, +{1.48986444E-1, 2.01226771E-1, 2.82543689E-1}, +{2.08387777E-1, 2.35603899E-1, 3.45363885E-1}, +{1.85830340E-1, 2.21607298E-1, 3.10773641E-1}, +{2.80904710E-1, 2.95469791E-1, 3.25499445E-1}, +{1.72967300E-1, 1.97078109E-1, 2.45801106E-1}, +{2.19495699E-1, 2.44767100E-1, 2.93587774E-1}, +{1.83909580E-1, 2.15004295E-1, 3.00334543E-1}, +{2.45338634E-1, 2.68595248E-1, 3.48330349E-1}, +{1.92957386E-1, 2.06625074E-1, 2.67336398E-1}, +{2.54845560E-1, 2.68642277E-1, 3.03547889E-1}, +{1.76853105E-1, 2.59330958E-1, 3.16200763E-1}, +{2.90929139E-1, 3.15634757E-1, 3.68723541E-1}, +{1.57116994E-1, 1.73552901E-1, 2.28736520E-1}, +{2.12509260E-1, 2.30501205E-1, 2.52217978E-1}, +{1.42521843E-1, 2.01979935E-1, 2.93012232E-1}, +{2.14919671E-1, 2.78065056E-1, 3.14176053E-1}, +{1.35947272E-1, 1.81055903E-1, 2.75475413E-1}, +{1.98416695E-1, 2.41673797E-1, 3.05173427E-1}, +{1.59517333E-1, 2.31580108E-1, 2.95412451E-1}, +{2.58203626E-1, 2.87348121E-1, 3.20351988E-1}, +{1.74840674E-1, 1.92883253E-1, 2.11250007E-1}, +{2.02168509E-1, 2.27025688E-1, 3.04884046E-1}, +{1.69532105E-1, 2.11826235E-1, 2.97355384E-1}, +{2.30033740E-1, 2.91504353E-1, 3.26589435E-1}, +{1.95046112E-1, 2.11709172E-1, 2.27705747E-1}, +{2.37926885E-1, 2.52411634E-1, 2.97752172E-1}, +{1.53762922E-1, 2.46541560E-1, 3.14768940E-1}, +{2.36075714E-1, 3.03568929E-1, 3.70624453E-1}, +{1.38660327E-1, 1.67949975E-1, 2.73515254E-1}, +{2.13806167E-1, 2.27267206E-1, 2.86276251E-1}, +{1.25080630E-1, 2.44098395E-1, 3.02548796E-1}, +{2.35714868E-1, 2.81208843E-1, 3.08903724E-1}, +{1.51691392E-1, 2.10877746E-1, 2.63812989E-1}, +{2.20730439E-1, 2.52777904E-1, 3.16413730E-1}, +{1.84924737E-1, 2.39424765E-1, 2.85120815E-1}, +{2.59548545E-1, 3.09809893E-1, 3.26423734E-1}, +{1.62930742E-1, 2.19900876E-1, 2.36148626E-1}, +{2.34194234E-1, 2.49944329E-1, 2.77549058E-1}, +{1.70870200E-1, 1.98291600E-1, 3.21412593E-1}, +{2.31566861E-1, 2.75015086E-1, 3.69710356E-1}, +{1.80002406E-1, 2.06701040E-1, 2.71204919E-1}, +{2.38075271E-1, 2.54006237E-1, 3.23827595E-1}, +{1.99148253E-1, 2.54273921E-1, 3.07479709E-1}, +{2.87428617E-1, 3.25045079E-1, 3.48634571E-1}, +{1.45285025E-1, 1.91359162E-1, 2.49691397E-1}, +{1.94659308E-1, 2.40821242E-1, 2.77302653E-1}, +{1.53150991E-1, 1.94375664E-1, 3.27550441E-1}, +{2.04085842E-1, 2.98595697E-1, 3.21480066E-1}, +{1.56009689E-1, 1.81012720E-1, 3.00931662E-1}, +{2.10962430E-1, 2.55770296E-1, 3.08086127E-1}, +{1.85444072E-1, 2.49021322E-1, 2.74029821E-1}, +{2.74493456E-1, 2.89441973E-1, 3.38794917E-1}, +{1.76941887E-1, 1.94476932E-1, 2.22077265E-1}, +{2.16377512E-1, 2.30735779E-1, 3.03689271E-1}, +{1.89683452E-1, 2.14660764E-1, 2.88445383E-1}, +{2.40827337E-1, 2.98141748E-1, 3.27378422E-1}, +{2.01787844E-1, 2.19441772E-1, 2.39327446E-1}, +{2.48812512E-1, 2.65865892E-1, 2.93382376E-1}, +{1.82027832E-1, 2.68279046E-1, 2.93991417E-1}, +{2.56498635E-1, 3.19984466E-1, 3.62663239E-1}, +{1.58799276E-1, 1.75433666E-1, 2.67389864E-1}, +{2.24259302E-1, 2.36668259E-1, 2.77639121E-1}, +{1.49203405E-1, 2.26585329E-1, 3.45255584E-1}, +{2.50655770E-1, 2.92264849E-1, 3.13574284E-1}, +{1.58096299E-1, 2.02193201E-1, 2.98711687E-1}, +{2.28820905E-1, 2.48557344E-1, 3.44726473E-1}, +{1.87972054E-1, 2.34109432E-1, 3.04235607E-1}, +{2.85657108E-1, 3.14878136E-1, 3.36931497E-1}, +{1.62680015E-1, 2.17820048E-1, 2.57436782E-1}, +{2.24049792E-1, 2.46739820E-1, 3.00795883E-1}, +{2.01354548E-1, 2.18286663E-1, 3.13036293E-1}, +{2.38028511E-1, 2.98103482E-1, 3.53503793E-1}, +{1.98829994E-1, 2.12877125E-1, 2.72980839E-1}, +{2.50616491E-1, 2.67659992E-1, 3.20611864E-1}, +{1.70901820E-1, 2.69330353E-1, 3.34428221E-1}, +{3.04988861E-1, 3.36196691E-1, 3.65235358E-1}, +{1.47624031E-1, 1.81272805E-1, 2.04707921E-1}, +{1.93751350E-1, 2.20973969E-1, 2.61775166E-1}, +{1.32089809E-1, 1.94851607E-1, 2.83547610E-1}, +{2.07739428E-1, 2.70596832E-1, 2.92264789E-1}, +{1.27733424E-1, 1.66896015E-1, 2.83891350E-1}, +{2.05309406E-1, 2.47807533E-1, 2.83632785E-1}, +{1.54211894E-1, 2.25014091E-1, 2.70082027E-1}, +{2.67574131E-1, 2.84426898E-1, 3.09334785E-1}, +{1.68846920E-1, 1.87004536E-1, 2.02433169E-1}, +{2.02441111E-1, 2.16733068E-1, 2.93079227E-1}, +{1.63621262E-1, 2.15616465E-1, 2.82792896E-1}, +{2.25509301E-1, 2.66283005E-1, 3.17886561E-1}, +{1.89110294E-1, 2.05609441E-1, 2.22113580E-1}, +{2.21240178E-1, 2.60288864E-1, 2.92541057E-1}, +{1.55563369E-1, 2.46850818E-1, 2.89648801E-1}, +{2.48406157E-1, 3.05291861E-1, 3.55316669E-1}, +{1.27122149E-1, 1.58053726E-1, 2.54164368E-1}, +{2.04998836E-1, 2.19476849E-1, 2.78342038E-1}, +{1.33302316E-1, 2.29614019E-1, 2.86947161E-1}, +{2.36777052E-1, 2.67918199E-1, 3.08230907E-1}, +{1.40853569E-1, 2.03414679E-1, 2.73257107E-1}, +{2.07684264E-1, 2.34520018E-1, 3.24583262E-1}, +{1.77181646E-1, 2.29595393E-1, 2.83539146E-1}, +{2.61378348E-1, 3.01160187E-1, 3.21707100E-1}, +{1.48595735E-1, 2.07772017E-1, 2.46946126E-1}, +{2.14334831E-1, 2.48061299E-1, 2.72259146E-1}, +{1.76380262E-1, 1.96897894E-1, 2.92286903E-1}, +{1.98193476E-1, 2.75483340E-1, 3.49037558E-1}, +{1.76153168E-1, 1.93248957E-1, 2.69548506E-1}, +{2.36968622E-1, 2.50065804E-1, 3.06820840E-1}, +{1.76060721E-1, 2.54037619E-1, 3.03566784E-1}, +{2.82952905E-1, 3.01765054E-1, 3.53956312E-1}, +{1.45353720E-1, 1.83678836E-1, 2.34750062E-1}, +{1.93842635E-1, 2.30635554E-1, 2.67817765E-1}, +{1.38958976E-1, 1.86760783E-1, 3.13113242E-1}, +{1.99944481E-1, 2.77624756E-1, 3.25046331E-1}, +{1.42966077E-1, 1.71310842E-1, 3.03013414E-1}, +{2.07741663E-1, 2.58691758E-1, 2.88766950E-1}, +{1.71776935E-1, 2.40246087E-1, 2.73284525E-1}, +{2.71046638E-1, 2.85170943E-1, 3.27401131E-1}, +{1.69854626E-1, 1.87545776E-1, 2.24484712E-1}, +{2.15221986E-1, 2.27339745E-1, 2.95008808E-1}, +{1.75596640E-1, 2.17936546E-1, 2.74879605E-1}, +{2.34665439E-1, 2.89530903E-1, 3.16494375E-1}, +{1.89946994E-1, 2.04953820E-1, 2.46955171E-1}, +{2.37297818E-1, 2.68316716E-1, 2.90684313E-1}, +{1.69963166E-1, 2.53367484E-1, 2.92533010E-1}, +{2.70659864E-1, 2.97146112E-1, 3.56183976E-1}, +{1.52539685E-1, 1.70138955E-1, 2.52703935E-1}, +{2.19119206E-1, 2.35900700E-1, 2.69739121E-1}, +{1.42245665E-1, 2.18184620E-1, 3.28218073E-1}, +{2.61472821E-1, 2.78025657E-1, 3.02375883E-1}, +{1.53526023E-1, 1.90727741E-1, 2.92820841E-1}, +{2.09240988E-1, 2.49808684E-1, 3.24709088E-1}, +{1.75176397E-1, 2.38646746E-1, 3.06392699E-1}, +{2.73218870E-1, 3.03954989E-1, 3.20513874E-1}, +{1.63911596E-1, 1.89611584E-1, 2.56272525E-1}, +{2.26953760E-1, 2.40120232E-1, 2.92728513E-1}, +{1.95565715E-1, 2.11956203E-1, 2.97374696E-1}, +{2.41045550E-1, 2.88497001E-1, 3.36352319E-1}, +{1.94948331E-1, 2.09475279E-1, 2.56309658E-1}, +{2.47884631E-1, 2.63356417E-1, 3.11270863E-1}, +{1.69189706E-1, 2.35864580E-1, 3.36249381E-1}, +{2.86001563E-1, 3.25423747E-1, 3.59607369E-1}, +{1.56258598E-1, 1.76704943E-1, 2.14393437E-1}, +{2.08996847E-1, 2.23968685E-1, 2.60886759E-1}, +{1.35765389E-1, 2.03580052E-1, 3.05503219E-1}, +{2.18961373E-1, 2.79463500E-1, 2.99450845E-1}, +{1.34064749E-1, 1.78332120E-1, 2.90169626E-1}, +{2.13298395E-1, 2.40031511E-1, 3.00345927E-1}, +{1.64373413E-1, 2.26438701E-1, 2.87171155E-1}, +{2.50739604E-1, 2.80812472E-1, 3.35349351E-1}, +{1.63649514E-1, 1.97108001E-1, 2.21165180E-1}, +{2.08139613E-1, 2.30869800E-1, 2.96137065E-1}, +{1.59113124E-1, 2.18189180E-1, 2.95531958E-1}, +{2.39883497E-1, 2.81831235E-1, 3.26045603E-1}, +{1.89394727E-1, 2.08127141E-1, 2.38446414E-1}, +{2.32995704E-1, 2.59603471E-1, 2.93427974E-1}, +{1.60558835E-1, 2.55164832E-1, 3.02872926E-1}, +{2.53509283E-1, 2.96028465E-1, 3.67721587E-1}, +{1.30124375E-1, 1.74838990E-1, 2.60486037E-1}, +{2.10203990E-1, 2.33570784E-1, 2.83061892E-1}, +{1.52365491E-1, 2.25338757E-1, 3.03720981E-1}, +{2.40558609E-1, 2.77192205E-1, 3.05891901E-1}, +{1.63728818E-1, 1.94779396E-1, 2.69253582E-1}, +{2.25709423E-1, 2.40902692E-1, 3.18060607E-1}, +{1.92055091E-1, 2.29857832E-1, 2.89826721E-1}, +{2.62759686E-1, 3.04292172E-1, 3.35680574E-1}, +{1.66071162E-1, 2.06819177E-1, 2.39712462E-1}, +{2.23915562E-1, 2.50106871E-1, 2.85296232E-1}, +{1.88402340E-1, 2.03793734E-1, 3.03041130E-1}, +{2.30698988E-1, 2.87044138E-1, 3.49802762E-1}, +{1.82025358E-1, 2.14073509E-1, 2.63470024E-1}, +{2.37297758E-1, 2.65025407E-1, 3.17815512E-1}, +{1.89278707E-1, 2.58802205E-1, 3.04866165E-1}, +{2.97243059E-1, 3.17153066E-1, 3.56583923E-1}, +{1.58607468E-1, 1.78659767E-1, 2.41919369E-1}, +{1.94887385E-1, 2.41695851E-1, 2.62176663E-1}, +{1.58124432E-1, 2.11753070E-1, 3.11352164E-1}, +{2.16902718E-1, 2.98796803E-1, 3.20994049E-1}, +{1.49272785E-1, 1.74964130E-1, 3.15334409E-1}, +{2.21622273E-1, 2.56179065E-1, 3.03902954E-1}, +{1.75979599E-1, 2.43505448E-1, 2.85801739E-1}, +{2.64590383E-1, 2.85541564E-1, 3.45107764E-1}, +{1.80137083E-1, 2.05279350E-1, 2.22255990E-1}, +{2.10796222E-1, 2.26315439E-1, 3.14426929E-1}, +{1.79151163E-1, 2.09439725E-1, 2.93280870E-1}, +{2.49719024E-1, 2.91257650E-1, 3.27162296E-1}, +{1.98700234E-1, 2.15896755E-1, 2.49960214E-1}, +{2.40726396E-1, 2.64857739E-1, 2.99639553E-1}, +{1.71249732E-1, 2.68166155E-1, 3.03572744E-1}, +{2.69555569E-1, 3.16100627E-1, 3.56570691E-1}, +{1.50564745E-1, 1.84190869E-1, 2.68674821E-1}, +{2.16941193E-1, 2.40813971E-1, 2.78942198E-1}, +{1.35399476E-1, 2.60586530E-1, 3.32604855E-1}, +{2.56150961E-1, 2.87822872E-1, 3.06156367E-1}, +{1.66398838E-1, 1.88721806E-1, 2.93023735E-1}, +{2.29214087E-1, 2.61565417E-1, 3.27494055E-1}, +{1.98266640E-1, 2.32970506E-1, 2.99134284E-1}, +{2.87046254E-1, 3.07103783E-1, 3.27298075E-1}, +{1.75898686E-1, 2.11898595E-1, 2.51332909E-1}, +{2.32067421E-1, 2.44622201E-1, 2.99443692E-1}, +{1.90780059E-1, 2.12090015E-1, 3.25059265E-1}, +{2.31531218E-1, 3.14166099E-1, 3.42735857E-1}, +{1.95099846E-1, 2.09554315E-1, 2.79483467E-1}, +{2.40416065E-1, 2.69604772E-1, 3.28015476E-1}, +{1.71800867E-1, 2.82233089E-1, 3.14749271E-1}, +{2.69243777E-1, 3.38462502E-1, 3.79935652E-1}, +{1.59934625E-1, 1.77966774E-1, 2.00818628E-1}, +{2.01979712E-1, 2.30668545E-1, 2.56773323E-1}, +{1.34024277E-1, 2.10961610E-1, 2.84687728E-1}, +{2.03712896E-1, 2.83053070E-1, 3.03309411E-1}, +{1.44528881E-1, 1.64728075E-1, 2.85079390E-1}, +{2.06285611E-1, 2.48649031E-1, 2.96383053E-1}, +{1.58138171E-1, 2.34317720E-1, 2.79650003E-1}, +{2.64995635E-1, 2.79900700E-1, 3.18619400E-1}, +{1.66537479E-1, 1.84279412E-1, 2.14547485E-1}, +{2.03051880E-1, 2.35110492E-1, 2.88755983E-1}, +{1.68422714E-1, 2.03946173E-1, 2.87478894E-1}, +{2.31727019E-1, 2.74086386E-1, 3.24755162E-1}, +{1.85356215E-1, 2.14113116E-1, 2.29030401E-1}, +{2.42482558E-1, 2.60655493E-1, 2.83030301E-1}, +{1.67562261E-1, 2.42027491E-1, 2.99461991E-1}, +{2.38809898E-1, 3.19003850E-1, 3.58415872E-1}, +{1.37908265E-1, 1.54787809E-1, 2.65611202E-1}, +{2.11019263E-1, 2.24607319E-1, 2.79954702E-1}, +{1.37569889E-1, 2.25128531E-1, 3.09312850E-1}, +{2.29239866E-1, 2.76150972E-1, 3.15241843E-1}, +{1.60487458E-1, 1.95461214E-1, 2.83169478E-1}, +{2.18505666E-1, 2.38197207E-1, 3.30340117E-1}, +{1.81991324E-1, 2.33026952E-1, 2.93276042E-1}, +{2.54552305E-1, 3.14394146E-1, 3.36392254E-1}, +{1.44095764E-1, 2.26640165E-1, 2.50595063E-1}, +{2.15188012E-1, 2.51417249E-1, 2.85043985E-1}, +{1.87674388E-1, 2.04458863E-1, 2.94168979E-1}, +{2.30494842E-1, 2.68452436E-1, 3.52370054E-1}, +{1.85022101E-1, 1.99075252E-1, 2.71930546E-1}, +{2.42569372E-1, 2.55389154E-1, 3.11399311E-1}, +{1.95166096E-1, 2.49102056E-1, 2.98998445E-1}, +{2.83654153E-1, 3.14600259E-1, 3.55619401E-1}, +{1.51490018E-1, 1.97729796E-1, 2.32467473E-1}, +{2.00029895E-1, 2.30101258E-1, 2.81933933E-1}, +{1.38711318E-1, 1.91816628E-1, 3.45780402E-1}, +{1.96580395E-1, 3.04714769E-1, 3.40553433E-1}, +{1.38154253E-1, 1.88543141E-1, 2.99461216E-1}, +{2.05666468E-1, 2.68904895E-1, 3.05537194E-1}, +{1.72447845E-1, 2.33558387E-1, 2.93625206E-1}, +{2.70145416E-1, 2.98654765E-1, 3.28556389E-1}, +{1.75489411E-1, 1.91361547E-1, 2.35585332E-1}, +{2.20548794E-1, 2.34773993E-1, 2.95397669E-1}, +{1.85652360E-1, 2.22349137E-1, 2.79883891E-1}, +{2.29456946E-1, 3.04546326E-1, 3.24684292E-1}, +{1.86900780E-1, 2.15469390E-1, 2.51856804E-1}, +{2.34910533E-1, 2.71217376E-1, 2.99894661E-1}, +{1.85142443E-1, 2.56071001E-1, 2.93291301E-1}, +{2.63883710E-1, 3.07127446E-1, 3.62546653E-1}, +{1.60997644E-1, 1.78937852E-1, 2.55808324E-1}, +{2.25671068E-1, 2.43735075E-1, 2.68624991E-1}, +{1.55076161E-1, 2.30396181E-1, 3.21005553E-1}, +{2.51760483E-1, 2.79653400E-1, 3.14202160E-1}, +{1.56988814E-1, 2.07466930E-1, 2.89933950E-1}, +{2.17479482E-1, 2.59626418E-1, 3.40659052E-1}, +{1.76811531E-1, 2.31087089E-1, 3.17562491E-1}, +{2.82952607E-1, 2.99844354E-1, 3.36822897E-1}, +{1.82060316E-1, 1.98734730E-1, 2.51980305E-1}, +{2.25874200E-1, 2.52469152E-1, 2.93356389E-1}, +{2.00799957E-1, 2.17786849E-1, 3.02210063E-1}, +{2.47423753E-1, 2.86882848E-1, 3.47820610E-1}, +{2.01128140E-1, 2.14746892E-1, 2.62269646E-1}, +{2.53963351E-1, 2.69477993E-1, 3.12133819E-1}, +{1.91034868E-1, 2.55738169E-1, 3.32559615E-1}, +{2.91053712E-1, 3.31458420E-1, 3.68588477E-1}, +{1.57229915E-1, 1.85374141E-1, 2.25361317E-1}, +{2.08051339E-1, 2.38350868E-1, 2.64212936E-1}, +{1.46848336E-1, 2.13000089E-1, 3.00192565E-1}, +{2.18630567E-1, 2.90263802E-1, 3.09045762E-1}, +{1.43699184E-1, 1.87815160E-1, 2.83769876E-1}, +{2.07328036E-1, 2.45088696E-1, 3.08956414E-1}, +{1.64228097E-1, 2.27826655E-1, 3.08907896E-1}, +{2.61919737E-1, 2.91333705E-1, 3.31527978E-1}, +{1.70648888E-1, 2.02157527E-1, 2.17827827E-1}, +{2.07796112E-1, 2.34704822E-1, 3.06783766E-1}, +{1.72118798E-1, 2.14057386E-1, 3.10151786E-1}, +{2.29116157E-1, 2.80949861E-1, 3.33774298E-1}, +{1.96622208E-1, 2.16653049E-1, 2.33279720E-1}, +{2.37789229E-1, 2.58971304E-1, 3.04609209E-1}, +{1.55182019E-1, 2.63032585E-1, 3.18943053E-1}, +{2.49388829E-1, 3.16970855E-1, 3.77762467E-1}, +{1.51363596E-1, 1.75010651E-1, 2.78245836E-1}, +{2.19810233E-1, 2.32360214E-1, 2.85034925E-1}, +{1.42630622E-1, 2.40602851E-1, 3.04125100E-1}, +{2.42764875E-1, 2.83762127E-1, 3.15481216E-1}, +{1.57467470E-1, 2.07524061E-1, 2.75674909E-1}, +{2.28758618E-1, 2.49092206E-1, 3.28139395E-1}, +{1.90872714E-1, 2.38125205E-1, 2.94894546E-1}, +{2.66389251E-1, 3.14321429E-1, 3.38669509E-1}, +{1.70644209E-1, 2.25980043E-1, 2.47372389E-1}, +{2.36442789E-1, 2.53003448E-1, 2.88220435E-1}, +{1.85423777E-1, 2.04888850E-1, 3.14608842E-1}, +{2.17379019E-1, 2.94553548E-1, 3.67831022E-1}, +{1.88563988E-1, 2.15174288E-1, 2.72999734E-1}, +{2.45102122E-1, 2.59770364E-1, 3.21885556E-1}, +{1.98444173E-1, 2.61160702E-1, 3.17097872E-1}, +{2.99013853E-1, 3.28965336E-1, 3.56681198E-1}, +{1.58248767E-1, 1.92205697E-1, 2.46059090E-1}, +{2.02385351E-1, 2.47965842E-1, 2.71749645E-1}, +{1.61710784E-1, 2.13708103E-1, 3.27384740E-1}, +{2.14419708E-1, 3.05552453E-1, 3.33721548E-1}, +{1.61819980E-1, 1.89897299E-1, 3.10501546E-1}, +{2.19436333E-1, 2.65029579E-1, 3.09288830E-1}, +{1.88303933E-1, 2.49633163E-1, 2.85499543E-1}, +{2.69325376E-1, 2.99807042E-1, 3.41722459E-1}, +{1.72406003E-1, 2.10977256E-1, 2.27773219E-1}, +{2.20281526E-1, 2.34015763E-1, 3.12846094E-1}, +{1.83257267E-1, 2.22061962E-1, 2.91052371E-1}, +{2.42531225E-1, 3.09527606E-1, 3.30389649E-1}, +{2.07546696E-1, 2.24662632E-1, 2.44420141E-1}, +{2.45858207E-1, 2.70285994E-1, 3.05132121E-1}, +{1.84840545E-1, 2.72096783E-1, 3.12531084E-1}, +{2.74252594E-1, 3.21252435E-1, 3.74658197E-1}, +{1.66425839E-1, 1.84491634E-1, 2.68278092E-1}, +{2.28423670E-1, 2.43025422E-1, 2.81184882E-1}, +{1.60091296E-1, 2.52953321E-1, 3.35822314E-1}, +{2.62109995E-1, 2.95581907E-1, 3.13354105E-1}, +{1.67702749E-1, 2.01536924E-1, 3.01801592E-1}, +{2.37822965E-1, 2.59894758E-1, 3.38231117E-1}, +{1.97206214E-1, 2.45490909E-1, 3.17895442E-1}, +{2.98455298E-1, 3.19209784E-1, 3.40971738E-1}, +{1.71195343E-1, 2.24327832E-1, 2.62736112E-1}, +{2.30626896E-1, 2.53310233E-1, 3.01206797E-1}, +{2.04814211E-1, 2.21881568E-1, 3.25966567E-1}, +{2.22987518E-1, 3.06339115E-1, 3.50717157E-1}, +{2.00855389E-1, 2.15359926E-1, 2.84143478E-1}, +{2.50951648E-1, 2.66189247E-1, 3.33360583E-1}, +{1.75610259E-1, 2.93791324E-1, 3.40326935E-1}, +{2.91745067E-1, 3.40602487E-1, 3.81397158E-1}}; + +static const float evrc_lspq_full_codebook4[128][3] = { +{2.77461529E-1, 3.16972077E-1, 3.95498335E-1}, +{3.36560428E-1, 3.60156953E-1, 3.81473005E-1}, +{3.10509324E-1, 3.31732392E-1, 3.66864383E-1}, +{3.37470949E-1, 3.96795273E-1, 4.12356317E-1}, +{2.79660404E-1, 3.66520107E-1, 3.85313451E-1}, +{3.16038966E-1, 3.85609329E-1, 4.01304781E-1}, +{3.09960425E-1, 3.43410730E-1, 4.24745500E-1}, +{3.54243636E-1, 4.08699274E-1, 4.22167957E-1}, +{2.95587242E-1, 3.33741128E-1, 3.87421668E-1}, +{3.33446383E-1, 3.86974752E-1, 4.01353061E-1}, +{3.23412836E-1, 3.65269661E-1, 3.85193288E-1}, +{3.42731953E-1, 4.03192520E-1, 4.19920385E-1}, +{2.77681828E-1, 3.82494986E-1, 4.04274166E-1}, +{3.18247974E-1, 3.95985305E-1, 4.31353152E-1}, +{3.03711414E-1, 3.80319715E-1, 4.37173545E-1}, +{3.78288805E-1, 4.07077312E-1, 4.22679126E-1}, +{2.38116503E-1, 3.42454314E-1, 4.24624741E-1}, +{3.45615685E-1, 3.68681073E-1, 4.00817335E-1}, +{3.17688107E-1, 3.41902673E-1, 4.05601799E-1}, +{3.66368949E-1, 3.89039934E-1, 4.06154454E-1}, +{2.99398005E-1, 3.52021694E-1, 3.99955690E-1}, +{3.24991941E-1, 3.90028834E-1, 4.19478714E-1}, +{3.23025763E-1, 3.68114293E-1, 4.02087748E-1}, +{3.62326264E-1, 4.16927993E-1, 4.32773650E-1}, +{2.72696435E-1, 3.59205008E-1, 4.26880658E-1}, +{3.46539855E-1, 3.69616628E-1, 4.15621221E-1}, +{3.34109128E-1, 3.55736315E-1, 3.96749556E-1}, +{3.37468982E-1, 4.10392702E-1, 4.25986826E-1}, +{2.99468994E-1, 3.80648255E-1, 4.18284118E-1}, +{3.21378171E-1, 4.11198020E-1, 4.28792536E-1}, +{3.27841163E-1, 3.69345129E-1, 4.34395611E-1}, +{3.80669057E-1, 4.26086366E-1, 4.42754567E-1}, +{2.68943667E-1, 3.42942953E-1, 3.98681462E-1}, +{3.38102877E-1, 3.76338840E-1, 3.92043173E-1}, +{3.23593497E-1, 3.48742068E-1, 3.72551978E-1}, +{3.47550809E-1, 3.92885387E-1, 4.21169937E-1}, +{3.04182827E-1, 3.59816670E-1, 3.81633341E-1}, +{3.14221382E-1, 4.02108550E-1, 4.20085251E-1}, +{3.01306546E-1, 3.62662733E-1, 4.29262817E-1}, +{3.71770263E-1, 3.98696363E-1, 4.31438982E-1}, +{2.74591267E-1, 3.35595489E-1, 4.20079648E-1}, +{3.44540834E-1, 3.90451789E-1, 4.06412065E-1}, +{3.25239837E-1, 3.78344476E-1, 3.94673288E-1}, +{3.56683493E-1, 3.90574157E-1, 4.33851063E-1}, +{2.63501287E-1, 3.95260096E-1, 4.23116386E-1}, +{3.37520659E-1, 3.92563462E-1, 4.43415821E-1}, +{3.14522266E-1, 3.80968630E-1, 4.22676384E-1}, +{3.76235068E-1, 4.17298734E-1, 4.31451261E-1}, +{2.61855006E-1, 3.68646085E-1, 4.04260576E-1}, +{3.55580151E-1, 3.77994478E-1, 3.95868242E-1}, +{3.27742815E-1, 3.53872776E-1, 4.11040604E-1}, +{3.62960637E-1, 3.99466991E-1, 4.14690197E-1}, +{3.09410870E-1, 3.73796046E-1, 3.92672479E-1}, +{3.31016302E-1, 4.00801599E-1, 4.31759298E-1}, +{3.23573053E-1, 3.68619561E-1, 4.17455137E-1}, +{3.49115849E-1, 4.26840067E-1, 4.43913996E-1}, +{2.89738595E-1, 3.63759339E-1, 4.10511792E-1}, +{3.55286479E-1, 3.89331281E-1, 4.13432419E-1}, +{3.36565912E-1, 3.60222459E-1, 4.24179018E-1}, +{3.39932680E-1, 4.09228802E-1, 4.40184891E-1}, +{3.00889730E-1, 4.00081098E-1, 4.17955697E-1}, +{3.17052066E-1, 4.22288120E-1, 4.42229569E-1}, +{3.27336788E-1, 3.84311676E-1, 4.30288613E-1}, +{3.98990929E-1, 4.29498434E-1, 4.43475187E-1}, +{2.49110118E-1, 3.25696886E-1, 4.11728263E-1}, +{3.45929205E-1, 3.68577540E-1, 3.88473272E-1}, +{3.13219666E-1, 3.39229465E-1, 3.87597919E-1}, +{3.51453960E-1, 3.98730278E-1, 4.12656188E-1}, +{2.93487132E-1, 3.75763118E-1, 3.94488096E-1}, +{3.24470758E-1, 3.94202888E-1, 4.08882737E-1}, +{3.12710822E-1, 3.57720256E-1, 4.14061189E-1}, +{3.66507173E-1, 4.08171296E-1, 4.23891425E-1}, +{2.99965680E-1, 3.31993401E-1, 4.07860160E-1}, +{3.34925175E-1, 3.86143029E-1, 4.11538124E-1}, +{3.34788024E-1, 3.66196156E-1, 3.93347144E-1}, +{3.47847939E-1, 4.05926466E-1, 4.30507302E-1}, +{2.85952926E-1, 3.95283282E-1, 4.16119337E-1}, +{3.23867381E-1, 4.06476676E-1, 4.42482829E-1}, +{3.16716671E-1, 3.84451628E-1, 4.39411044E-1}, +{3.86772931E-1, 4.11824584E-1, 4.27831531E-1}, +{2.38072395E-1, 3.62342358E-1, 4.30931687E-1}, +{3.46450031E-1, 3.79082918E-1, 4.06567812E-1}, +{3.16576600E-1, 3.56468618E-1, 3.96218300E-1}, +{3.66539180E-1, 3.89590919E-1, 4.21055555E-1}, +{3.08291376E-1, 3.71324301E-1, 4.07867432E-1}, +{3.36435199E-1, 3.91514421E-1, 4.22977090E-1}, +{3.23035538E-1, 3.80447328E-1, 4.09550190E-1}, +{3.65228057E-1, 4.27910388E-1, 4.43691254E-1}, +{2.72038043E-1, 3.76596808E-1, 4.33685899E-1}, +{3.57665777E-1, 3.77761602E-1, 4.09178972E-1}, +{3.36498559E-1, 3.64215910E-1, 4.09255505E-1}, +{3.48082423E-1, 4.17631805E-1, 4.33284521E-1}, +{3.02754521E-1, 3.95974755E-1, 4.33717251E-1}, +{3.31676304E-1, 4.17587161E-1, 4.36239839E-1}, +{3.33287597E-1, 3.80799115E-1, 4.39620733E-1}, +{3.88112009E-1, 4.36933577E-1, 4.50829268E-1}, +{2.56026626E-1, 3.48015189E-1, 4.22922611E-1}, +{3.45773995E-1, 3.81725788E-1, 3.96794081E-1}, +{3.25623751E-1, 3.50391924E-1, 3.87330651E-1}, +{3.56868088E-1, 3.98574769E-1, 4.23177242E-1}, +{3.01226199E-1, 3.86906981E-1, 4.03335571E-1}, +{3.28178406E-1, 4.02090192E-1, 4.19389248E-1}, +{3.14385355E-1, 3.69043887E-1, 4.34375286E-1}, +{3.72321129E-1, 4.11672413E-1, 4.40518737E-1}, +{2.90479720E-1, 3.48121881E-1, 4.26216483E-1}, +{3.44438791E-1, 3.82666349E-1, 4.17321086E-1}, +{3.34866822E-1, 3.76235664E-1, 4.04475212E-1}, +{3.59025359E-1, 4.04721916E-1, 4.34838414E-1}, +{2.79127955E-1, 4.11106586E-1, 4.35360551E-1}, +{3.48125517E-1, 3.98732066E-1, 4.46927428E-1}, +{3.27018857E-1, 3.90107334E-1, 4.41707492E-1}, +{3.90858352E-1, 4.19813931E-1, 4.35153484E-1}, +{2.55319297E-1, 3.70405972E-1, 4.32188630E-1}, +{3.54651988E-1, 3.88332665E-1, 4.02956128E-1}, +{3.21608186E-1, 3.54489803E-1, 4.28299785E-1}, +{3.75163496E-1, 3.98833990E-1, 4.14177418E-1}, +{3.11953604E-1, 3.91430676E-1, 4.12552476E-1}, +{3.42528820E-1, 3.96365345E-1, 4.32497382E-1}, +{3.33744347E-1, 3.76422405E-1, 4.20536995E-1}, +{3.53529096E-1, 4.29231048E-1, 4.59699273E-1}, +{2.88017929E-1, 3.77999961E-1, 4.34011698E-1}, +{3.55683446E-1, 3.80780041E-1, 4.23145533E-1}, +{3.44358265E-1, 3.72184873E-1, 4.31265354E-1}, +{3.53966117E-1, 4.14166689E-1, 4.42941308E-1}, +{3.04770231E-1, 4.12517488E-1, 4.34183121E-1}, +{3.35913360E-1, 4.24590766E-1, 4.46378469E-1}, +{3.43738198E-1, 3.84766221E-1, 4.35271382E-1}, +{4.10941303E-1, 4.40662980E-1, 4.52113390E-1}}; + +static const float evrc_lspq_half_codebook1[128][3] = { +{1.35226343E-2, 1.82081293E-2, 3.93940695E-2}, +{2.29392890E-2, 3.57831158E-2, 1.05352886E-1}, +{2.09106486E-2, 3.04159056E-2, 8.93941075E-2}, +{1.88909005E-2, 3.82722206E-2, 1.37820408E-1}, +{2.05143820E-2, 2.85481159E-2, 7.39762187E-2}, +{4.69510332E-2, 6.84031919E-2, 1.09123811E-1}, +{3.15557197E-2, 5.69139980E-2, 8.57057571E-2}, +{3.81181911E-2, 7.77784660E-2, 1.92532852E-1}, +{2.16297153E-2, 2.92908940E-2, 6.25042021E-2}, +{3.11414022E-2, 5.99079318E-2, 1.02860682E-1}, +{3.02799307E-2, 5.35012372E-2, 7.80925751E-2}, +{6.50846213E-2, 9.06624720E-2, 1.42850950E-1}, +{3.27340364E-2, 5.04027791E-2, 6.26492277E-2}, +{5.27439862E-2, 6.22574277E-2, 1.22198336E-1}, +{3.48840356E-2, 6.42222390E-2, 9.16024595E-2}, +{4.88984436E-2, 1.05058022E-1, 1.68813452E-1}, +{2.35791076E-2, 3.21034677E-2, 5.60899563E-2}, +{2.77252812E-2, 4.87281792E-2, 1.01224191E-1}, +{2.74348017E-2, 4.04965915E-2, 9.34926122E-2}, +{4.38360050E-2, 6.03261292E-2, 1.52400866E-1}, +{2.68994924E-2, 4.52906378E-2, 6.49800375E-2}, +{5.16058952E-2, 6.08312152E-2, 1.08799636E-1}, +{4.20064926E-2, 6.11845106E-2, 8.54474008E-2}, +{7.13502690E-2, 1.01972111E-1, 1.74640998E-1}, +{2.88906675E-2, 4.13964354E-2, 5.25928028E-2}, +{3.16364467E-2, 6.63532093E-2, 1.24950245E-1}, +{4.30289507E-2, 5.14023267E-2, 7.96877742E-2}, +{5.70970774E-2, 1.08444504E-1, 1.44075617E-1}, +{3.38840261E-2, 5.04746847E-2, 7.29765445E-2}, +{6.54265657E-2, 7.90987685E-2, 1.15570590E-1}, +{3.85423526E-2, 7.33125433E-2, 1.02307513E-1}, +{6.57824501E-2, 1.02909811E-1, 2.11874440E-1}, +{1.54727865E-2, 2.04559695E-2, 5.46121262E-2}, +{2.27950197E-2, 3.90954204E-2, 1.19443826E-1}, +{3.06889173E-2, 4.54540215E-2, 8.20418894E-2}, +{2.25957241E-2, 4.79101725E-2, 1.71844408E-1}, +{2.71088015E-2, 4.01739590E-2, 7.01922849E-2}, +{4.95789349E-2, 7.92963281E-2, 1.04862511E-1}, +{3.06095853E-2, 5.64059429E-2, 9.49584097E-2}, +{6.34224564E-2, 9.11655501E-2, 1.84724405E-1}, +{2.43342388E-2, 3.91998328E-2, 6.31406233E-2}, +{3.38011980E-2, 6.60846457E-2, 1.11031540E-1}, +{3.51784080E-2, 5.79397269E-2, 7.20702857E-2}, +{6.49054050E-2, 8.65831897E-2, 1.54648736E-1}, +{2.91934665E-2, 5.16204573E-2, 6.94437325E-2}, +{5.94522804E-2, 7.19829276E-2, 1.27434507E-1}, +{5.31888530E-2, 6.38182089E-2, 9.88218486E-2}, +{8.68290961E-2, 1.41135350E-1, 1.91728458E-1}, +{2.49991138E-2, 3.62556018E-2, 5.03724031E-2}, +{2.82246377E-2, 5.44572286E-2, 1.12663500E-1}, +{3.62618119E-2, 4.59073223E-2, 9.43343639E-2}, +{5.70455343E-2, 7.46300444E-2, 1.59157172E-1}, +{2.72987466E-2, 4.56625856E-2, 7.52529651E-2}, +{5.12860194E-2, 8.51126984E-2, 1.23587973E-1}, +{4.91451994E-2, 5.93483113E-2, 9.22686011E-2}, +{7.06961900E-2, 1.05451979E-1, 1.92602143E-1}, +{2.80733760E-2, 4.18509208E-2, 5.87159805E-2}, +{4.64449003E-2, 7.06698820E-2, 1.26038432E-1}, +{4.18453738E-2, 6.30445331E-2, 7.66169876E-2}, +{8.42416435E-2, 1.13282882E-1, 1.43687114E-1}, +{4.17615622E-2, 5.59472926E-2, 7.09872842E-2}, +{5.55161387E-2, 9.50126722E-2, 1.27727196E-1}, +{5.90935498E-2, 7.36730024E-2, 9.65935886E-2}, +{7.84136653E-2, 1.41432360E-1, 2.17428640E-1}, +{2.10490543E-2, 2.91891042E-2, 4.60035764E-2}, +{3.64863276E-2, 4.62387018E-2, 1.07044168E-1}, +{2.68652122E-2, 3.92937548E-2, 8.41179937E-2}, +{2.72903945E-2, 5.53805046E-2, 1.41586170E-1}, +{2.48476695E-2, 3.63277681E-2, 7.62430876E-2}, +{5.25430813E-2, 7.75778666E-2, 1.14567965E-1}, +{4.07741442E-2, 5.39923795E-2, 9.07640457E-2}, +{5.73043302E-2, 7.65803084E-2, 1.79578975E-1}, +{2.46032421E-2, 3.41408364E-2, 6.78990781E-2}, +{4.08220068E-2, 6.29783794E-2, 9.95191261E-2}, +{3.83025035E-2, 5.52857481E-2, 7.90019333E-2}, +{7.24111274E-2, 1.01903863E-1, 1.46979645E-1}, +{3.73902172E-2, 4.70463894E-2, 6.54684529E-2}, +{5.27397543E-2, 6.72770366E-2, 1.39680430E-1}, +{4.05365378E-2, 7.05081299E-2, 9.25668627E-2}, +{4.43425253E-2, 1.10367171E-1, 1.99636266E-1}, +{2.54920740E-2, 3.47603969E-2, 6.05902039E-2}, +{4.35465500E-2, 5.32369502E-2, 1.08325966E-1}, +{2.79599819E-2, 4.91324775E-2, 8.84284526E-2}, +{4.98051867E-2, 8.81728902E-2, 1.52597323E-1}, +{3.19346264E-2, 4.62169312E-2, 6.85206428E-2}, +{5.80246300E-2, 6.84268698E-2, 1.15085281E-1}, +{4.33904678E-2, 6.90575615E-2, 8.44984353E-2}, +{7.39691556E-2, 1.19240515E-1, 1.77340195E-1}, +{3.18767503E-2, 4.59697433E-2, 5.72372638E-2}, +{4.50873822E-2, 5.66509366E-2, 1.32005826E-1}, +{4.59097028E-2, 5.45580424E-2, 8.61423314E-2}, +{7.44685754E-2, 1.13815404E-1, 1.61570594E-1}, +{3.97509560E-2, 4.95359488E-2, 7.22542256E-2}, +{6.76257759E-2, 8.31029043E-2, 1.27990112E-1}, +{5.76258078E-2, 6.95326403E-2, 1.05012968E-1}, +{6.85313493E-2, 1.21758826E-1, 2.20626548E-1}, +{2.18480472E-2, 2.99130920E-2, 5.16208000E-2}, +{3.64343151E-2, 4.91795056E-2, 1.23277210E-1}, +{3.89611274E-2, 4.76634987E-2, 8.61716568E-2}, +{4.14635167E-2, 6.88006952E-2, 1.69356152E-1}, +{3.35514620E-2, 4.17815186E-2, 7.37159401E-2}, +{5.80224693E-2, 8.70314166E-2, 1.12917498E-1}, +{4.80243117E-2, 5.69486506E-2, 1.00755706E-1}, +{5.98873124E-2, 8.57942328E-2, 2.01388851E-1}, +{2.99309995E-2, 3.94828431E-2, 6.46376088E-2}, +{3.88626605E-2, 8.07443634E-2, 1.15519784E-1}, +{3.49444002E-2, 6.28911033E-2, 8.04982036E-2}, +{6.88817874E-2, 9.92431119E-2, 1.60393253E-1}, +{3.64237651E-2, 5.34016453E-2, 6.70152009E-2}, +{5.83492741E-2, 7.85285756E-2, 1.41746715E-1}, +{4.86469641E-2, 7.26736858E-2, 9.48315859E-2}, +{5.85533604E-2, 1.36289746E-1, 1.98639736E-1}, +{2.60888506E-2, 3.73406820E-2, 5.57853170E-2}, +{4.58504409E-2, 5.60512505E-2, 1.17927872E-1}, +{4.28801328E-2, 5.14739119E-2, 9.75309014E-2}, +{6.37611598E-2, 8.73552933E-2, 1.68334916E-1}, +{3.76709923E-2, 4.58216034E-2, 7.86528140E-2}, +{6.75194561E-2, 8.98697898E-2, 1.19418114E-1}, +{5.46374246E-2, 6.66805878E-2, 8.93813819E-2}, +{7.73086548E-2, 1.21754415E-1, 1.99579224E-1}, +{3.15621309E-2, 4.51702215E-2, 6.25768527E-2}, +{3.78782675E-2, 8.03486481E-2, 1.38961688E-1}, +{5.08303270E-2, 6.18740581E-2, 8.31153840E-2}, +{8.96311402E-2, 1.28753766E-1, 1.64891586E-1}, +{4.73503470E-2, 5.75724356E-2, 7.65264630E-2}, +{7.16898590E-2, 9.89895687E-2, 1.30078360E-1}, +{6.29082546E-2, 7.90778771E-2, 1.05111063E-1}, +{8.80649835E-2, 1.65206164E-1, 2.13214174E-1}}; + +static const float evrc_lspq_half_codebook2[128][3] = { +{9.75915268E-2, 1.23701490E-1, 1.69437975E-1}, +{9.49536338E-2, 2.01081768E-1, 2.26855248E-1}, +{9.00496617E-2, 1.49164870E-1, 2.26532787E-1}, +{1.70302704E-1, 1.97222874E-1, 2.49974832E-1}, +{1.08773641E-1, 1.51972428E-1, 1.75123364E-1}, +{1.30278930E-1, 2.13229164E-1, 2.29646355E-1}, +{1.24917991E-1, 1.87347755E-1, 2.04712003E-1}, +{2.00670198E-1, 2.28963569E-1, 2.69420803E-1}, +{8.98375586E-2, 1.25332758E-1, 2.10539430E-1}, +{9.62376669E-2, 2.07185850E-1, 2.54174471E-1}, +{1.05694629E-1, 1.78856418E-1, 2.00121015E-1}, +{1.56048968E-1, 2.19573721E-1, 2.91079402E-1}, +{1.37392268E-1, 1.59993336E-1, 1.94698542E-1}, +{1.07262500E-1, 2.37790957E-1, 2.70740807E-1}, +{1.42976448E-1, 2.01550499E-1, 2.18468934E-1}, +{2.14270487E-1, 2.71881402E-1, 3.01200211E-1}, +{1.10729210E-1, 1.33688226E-1, 1.54877156E-1}, +{1.06667660E-1, 1.76678821E-1, 2.62798905E-1}, +{9.16352943E-2, 1.74592838E-1, 2.19329327E-1}, +{1.84038624E-1, 2.27964059E-1, 2.47762203E-1}, +{1.10572360E-1, 1.58207163E-1, 1.96013063E-1}, +{1.33543387E-1, 2.32269660E-1, 2.51828164E-1}, +{1.55922309E-1, 1.77941337E-1, 2.18096644E-1}, +{1.92260072E-1, 2.49512479E-1, 2.89911509E-1}, +{1.13708906E-1, 1.37872443E-1, 2.02929884E-1}, +{1.02557532E-1, 1.84820071E-1, 2.92164624E-1}, +{1.36595622E-1, 1.58687428E-1, 2.41399556E-1}, +{1.72813818E-1, 2.49303415E-1, 3.00458610E-1}, +{1.36871174E-1, 1.57249823E-1, 2.10913152E-1}, +{1.28974810E-1, 2.45167866E-1, 2.67653584E-1}, +{1.66812256E-1, 1.88998029E-1, 2.31345922E-1}, +{2.32248470E-1, 2.63196051E-1, 3.16754937E-1}, +{9.24560949E-2, 1.19977452E-1, 1.91262275E-1}, +{1.13085262E-1, 2.08461538E-1, 2.29368120E-1}, +{1.00716405E-1, 1.40670076E-1, 2.58062959E-1}, +{1.67010382E-1, 2.18105540E-1, 2.62592494E-1}, +{1.25487238E-1, 1.62686959E-1, 1.84409231E-1}, +{1.52406558E-1, 2.07131729E-1, 2.47582436E-1}, +{1.37441203E-1, 1.80262372E-1, 2.17698842E-1}, +{2.07853511E-1, 2.49209508E-1, 2.69830108E-1}, +{9.35257301E-2, 1.49197355E-1, 2.04652041E-1}, +{1.11997180E-1, 2.25233063E-1, 2.47003049E-1}, +{1.09315015E-1, 1.93811879E-1, 2.13802189E-1}, +{1.75118580E-1, 2.52520263E-1, 2.75082767E-1}, +{1.36918738E-1, 1.77440569E-1, 1.97931141E-1}, +{1.36811242E-1, 2.37426177E-1, 2.84737825E-1}, +{1.60759792E-1, 2.00833157E-1, 2.18084484E-1}, +{2.33710244E-1, 2.66372561E-1, 2.91802049E-1}, +{1.19171090E-1, 1.39703169E-1, 1.87723249E-1}, +{1.31049946E-1, 1.93696663E-1, 2.60426998E-1}, +{1.08267047E-1, 1.65194795E-1, 2.39523023E-1}, +{2.03195021E-1, 2.25942209E-1, 2.49403238E-1}, +{1.23842932E-1, 1.45794615E-1, 2.15635628E-1}, +{1.71226338E-1, 2.38054529E-1, 2.57975638E-1}, +{1.66923836E-1, 1.88604668E-1, 2.11124212E-1}, +{2.10620746E-1, 2.62442708E-1, 2.83127964E-1}, +{1.05748810E-1, 1.36286482E-1, 2.20050186E-1}, +{9.72945765E-2, 2.33471528E-1, 2.96113968E-1}, +{1.34298369E-1, 1.93955436E-1, 2.39148825E-1}, +{1.64229318E-1, 2.70067751E-1, 2.94142485E-1}, +{1.42760262E-1, 1.65033355E-1, 2.24100381E-1}, +{1.46414533E-1, 2.47942328E-1, 3.00708115E-1}, +{1.74778774E-1, 2.19349250E-1, 2.38162965E-1}, +{2.36311123E-1, 2.90669680E-1, 3.28010976E-1}, +{1.14076428E-1, 1.33071408E-1, 1.73181504E-1}, +{1.13575839E-1, 1.90307274E-1, 2.41681188E-1}, +{8.59165266E-2, 1.63920239E-1, 2.37934500E-1}, +{1.92916945E-1, 2.15082392E-1, 2.39128128E-1}, +{1.37291834E-1, 1.59423307E-1, 1.79722220E-1}, +{1.40435383E-1, 2.22092256E-1, 2.40960747E-1}, +{1.40387163E-1, 1.89601168E-1, 2.05635697E-1}, +{2.11695507E-1, 2.36578360E-1, 2.81248927E-1}, +{9.03010592E-2, 1.27157405E-1, 2.33567923E-1}, +{1.10118054E-1, 2.09328398E-1, 2.72836268E-1}, +{1.16710417E-1, 1.77853987E-1, 2.22808748E-1}, +{1.81691542E-1, 2.32265159E-1, 2.74991214E-1}, +{1.46553472E-1, 1.69474706E-1, 1.90245956E-1}, +{1.09213792E-1, 2.63291955E-1, 2.88490772E-1}, +{1.49815127E-1, 2.11342707E-1, 2.28899449E-1}, +{1.97645500E-1, 2.83229947E-1, 3.14882278E-1}, +{1.24495603E-1, 1.46097973E-1, 1.66125208E-1}, +{1.34878591E-1, 1.83030054E-1, 2.89288282E-1}, +{9.33032110E-2, 1.83962211E-1, 2.38543004E-1}, +{1.92844257E-1, 2.39588335E-1, 2.58421540E-1}, +{1.23796798E-1, 1.65556595E-1, 2.08408386E-1}, +{1.51144341E-1, 2.35801116E-1, 2.59280622E-1}, +{1.50657728E-1, 1.90052524E-1, 2.28362590E-1}, +{1.98180959E-1, 2.56794214E-1, 3.08975637E-1}, +{1.28490031E-1, 1.49084017E-1, 1.98376507E-1}, +{9.20595750E-2, 2.12231293E-1, 2.92948842E-1}, +{1.41698137E-1, 1.72356680E-1, 2.58454144E-1}, +{1.96733460E-1, 2.29709730E-1, 2.95780182E-1}, +{1.47062227E-1, 1.68918088E-1, 2.07363635E-1}, +{1.36309877E-1, 2.60373056E-1, 2.82607377E-1}, +{1.81041077E-1, 2.01826140E-1, 2.38867551E-1}, +{2.45326266E-1, 2.80183077E-1, 3.11954319E-1}, +{1.04131766E-1, 1.33040652E-1, 1.89834684E-1}, +{1.23298146E-1, 2.09621087E-1, 2.47813210E-1}, +{1.24040775E-1, 1.59827366E-1, 2.58856058E-1}, +{1.87048867E-1, 2.12488100E-1, 2.59629130E-1}, +{1.24255307E-1, 1.73768952E-1, 1.92850024E-1}, +{1.58917829E-1, 2.25389823E-1, 2.43284762E-1}, +{1.53421149E-1, 1.91807315E-1, 2.09249526E-1}, +{2.27154449E-1, 2.51181155E-1, 2.72600353E-1}, +{1.09922059E-1, 1.57100275E-1, 2.20024973E-1}, +{1.32782355E-1, 2.19485506E-1, 2.67028928E-1}, +{1.26857504E-1, 1.98836312E-1, 2.17928499E-1}, +{1.91415027E-1, 2.52424240E-1, 2.72652745E-1}, +{1.55277625E-1, 1.79573521E-1, 2.00773627E-1}, +{1.17547743E-1, 2.47869864E-1, 3.08279335E-1}, +{1.65706977E-1, 2.10339502E-1, 2.29199320E-1}, +{2.25694910E-1, 2.84438193E-1, 3.12106073E-1}, +{1.29503176E-1, 1.48420051E-1, 1.80180401E-1}, +{1.54752508E-1, 1.97748467E-1, 2.67275035E-1}, +{1.28590241E-1, 1.76178381E-1, 2.39905864E-1}, +{2.14926764E-1, 2.37634435E-1, 2.58794010E-1}, +{1.28322318E-1, 1.59338519E-1, 2.26626605E-1}, +{1.55747548E-1, 2.47740522E-1, 2.73726821E-1}, +{1.75741687E-1, 1.97952345E-1, 2.19115943E-1}, +{2.18626365E-1, 2.45809183E-1, 3.00479650E-1}, +{1.17709018E-1, 1.45512864E-1, 2.38044471E-1}, +{1.18006893E-1, 2.23775521E-1, 2.94175088E-1}, +{1.51349202E-1, 1.88157812E-1, 2.48743281E-1}, +{1.89312205E-1, 2.69580543E-1, 2.93785989E-1}, +{1.49895594E-1, 1.74537256E-1, 2.37430006E-1}, +{1.39775530E-1, 2.71709383E-1, 3.07839513E-1}, +{1.83945730E-1, 2.07717165E-1, 2.26722151E-1}, +{2.54552156E-1, 2.96640933E-1, 3.24801445E-1}}; + +static const float evrc_lspq_half_codebook3[256][4] = { +{2.36904725E-1, 2.56104350E-1, 3.16955745E-1, 4.07520533E-1}, +{2.97596931E-1, 3.23482454E-1, 3.47667515E-1, 3.74551237E-1}, +{2.73721159E-1, 2.98297524E-1, 3.29923928E-1, 3.83599102E-1}, +{3.07849586E-1, 3.32836270E-1, 3.89340341E-1, 4.05575991E-1}, +{2.33803615E-1, 2.60296524E-1, 3.67351949E-1, 4.04388249E-1}, +{2.97513664E-1, 3.15356553E-1, 3.85135233E-1, 4.02197123E-1}, +{2.85618782E-1, 3.10872793E-1, 3.65022361E-1, 3.84816766E-1}, +{3.35271597E-1, 3.55222225E-1, 3.81921113E-1, 3.98685753E-1}, +{2.00265601E-1, 2.50502288E-1, 3.70398223E-1, 4.32012677E-1}, +{3.07982087E-1, 3.33767712E-1, 3.58199060E-1, 3.78386796E-1}, +{2.60086119E-1, 3.25520277E-1, 3.56873333E-1, 3.84737790E-1}, +{3.01356375E-1, 3.41369390E-1, 4.00296748E-1, 4.17337179E-1}, +{2.67080963E-1, 2.97674358E-1, 3.69702041E-1, 3.89139235E-1}, +{2.72669852E-1, 3.49704087E-1, 3.91925275E-1, 4.06383276E-1}, +{2.52825916E-1, 3.49636555E-1, 3.84550989E-1, 4.05930996E-1}, +{3.42927098E-1, 3.74274015E-1, 4.05468166E-1, 4.20351923E-1}, +{2.52408743E-1, 2.80375838E-1, 3.21436584E-1, 3.88436913E-1}, +{2.96970189E-1, 3.17173600E-1, 3.65342557E-1, 4.02736843E-1}, +{2.81905174E-1, 3.01479161E-1, 3.34335625E-1, 4.07633483E-1}, +{3.26872945E-1, 3.47177684E-1, 3.75017703E-1, 4.05372381E-1}, +{2.36371145E-1, 3.16441059E-1, 3.48707020E-1, 3.82030427E-1}, +{2.87817597E-1, 3.13627005E-1, 4.05129731E-1, 4.23379660E-1}, +{2.77502477E-1, 3.01843822E-1, 3.72250855E-1, 4.19212818E-1}, +{3.28988850E-1, 3.61901104E-1, 4.02015507E-1, 4.19229805E-1}, +{2.24960461E-1, 2.74636388E-1, 3.77016127E-1, 3.94726515E-1}, +{3.01045477E-1, 3.40486169E-1, 3.74888122E-1, 4.02532160E-1}, +{2.59897947E-1, 3.30334961E-1, 3.57493818E-1, 4.08657968E-1}, +{3.00961852E-1, 3.56449068E-1, 4.04779494E-1, 4.22508955E-1}, +{2.20979586E-1, 3.16477656E-1, 4.01744068E-1, 4.20735776E-1}, +{2.79754996E-1, 3.30776095E-1, 4.11152899E-1, 4.32687044E-1}, +{2.64246881E-1, 3.16610634E-1, 3.83876741E-1, 4.36683774E-1}, +{3.44381154E-1, 3.85365665E-1, 4.24949467E-1, 4.41560209E-1}, +{2.19488308E-1, 2.36459881E-1, 3.42465997E-1, 4.24989998E-1}, +{2.91465104E-1, 3.22282016E-1, 3.72852802E-1, 3.91635895E-1}, +{2.74792433E-1, 3.16536307E-1, 3.45392585E-1, 3.74555230E-1}, +{3.10583472E-1, 3.35264921E-1, 3.87527227E-1, 4.23076212E-1}, +{2.23211512E-1, 2.98497617E-1, 3.68426204E-1, 3.90213728E-1}, +{2.89078832E-1, 3.26512754E-1, 3.76308680E-1, 4.09553707E-1}, +{2.63830125E-1, 3.08977246E-1, 3.81453037E-1, 4.04660761E-1}, +{3.47073615E-1, 3.64797831E-1, 3.86763453E-1, 4.04511690E-1}, +{2.18452707E-1, 2.75614083E-1, 3.62711072E-1, 4.18278992E-1}, +{3.15042794E-1, 3.40813220E-1, 3.78627181E-1, 3.96316767E-1}, +{2.79727697E-1, 3.31259727E-1, 3.60061288E-1, 3.81175518E-1}, +{3.18602443E-1, 3.38044286E-1, 4.09010768E-1, 4.30300415E-1}, +{2.64196932E-1, 2.90672481E-1, 3.68595004E-1, 4.31856751E-1}, +{2.72645593E-1, 3.63514841E-1, 3.96518826E-1, 4.20091212E-1}, +{2.26540968E-1, 3.50055099E-1, 3.93851519E-1, 4.12597001E-1}, +{3.53053868E-1, 3.69929552E-1, 4.09656048E-1, 4.26387310E-1}, +{2.60788381E-1, 2.85172462E-1, 3.45943332E-1, 3.97500694E-1}, +{3.01113129E-1, 3.28201890E-1, 3.56068015E-1, 4.10803795E-1}, +{2.88101614E-1, 3.09559643E-1, 3.43756795E-1, 4.24872875E-1}, +{3.10489357E-1, 3.51421893E-1, 3.93717408E-1, 4.15550530E-1}, +{2.22308263E-1, 3.26798201E-1, 3.77981663E-1, 3.98635030E-1}, +{3.02915514E-1, 3.22781920E-1, 3.98558855E-1, 4.25489604E-1}, +{2.77136803E-1, 3.19992602E-1, 3.77490878E-1, 4.29177463E-1}, +{3.38731766E-1, 3.58164370E-1, 4.08386350E-1, 4.25495386E-1}, +{2.18726233E-1, 2.84384966E-1, 3.94053698E-1, 4.16346967E-1}, +{3.01005960E-1, 3.44093680E-1, 3.69013667E-1, 4.15091276E-1}, +{2.80783713E-1, 3.33053648E-1, 3.76726151E-1, 3.97526860E-1}, +{3.14394057E-1, 3.62678826E-1, 4.23668981E-1, 4.41899240E-1}, +{2.66453624E-1, 3.08513761E-1, 3.97407174E-1, 4.17450190E-1}, +{2.94222653E-1, 3.41904402E-1, 4.12726879E-1, 4.34888899E-1}, +{2.87300706E-1, 3.32434595E-1, 3.78856659E-1, 4.38234031E-1}, +{3.57146621E-1, 3.98147047E-1, 4.29875731E-1, 4.44243908E-1}, +{2.29671344E-1, 2.51018614E-1, 3.41046572E-1, 4.04376328E-1}, +{2.94472575E-1, 3.34944606E-1, 3.60409737E-1, 3.83682847E-1}, +{2.88250983E-1, 3.11722696E-1, 3.31680059E-1, 3.65104675E-1}, +{3.24881613E-1, 3.45656693E-1, 3.88306379E-1, 4.05954897E-1}, +{2.50829220E-1, 2.77623534E-1, 3.70799541E-1, 3.90479207E-1}, +{2.93523371E-1, 3.28319192E-1, 3.92112255E-1, 4.09464061E-1}, +{2.83608794E-1, 3.03885639E-1, 3.78504395E-1, 3.97310555E-1}, +{3.34039807E-1, 3.52837384E-1, 3.97272944E-1, 4.14322019E-1}, +{2.21891895E-1, 2.51877457E-1, 3.71723533E-1, 4.31791008E-1}, +{3.13201427E-1, 3.41175437E-1, 3.65503550E-1, 3.88567209E-1}, +{2.71330535E-1, 3.39163721E-1, 3.62616420E-1, 3.95735979E-1}, +{3.07550132E-1, 3.47777665E-1, 4.01049614E-1, 4.32767451E-1}, +{2.59387434E-1, 2.87243843E-1, 3.86817336E-1, 4.06042695E-1}, +{2.85485208E-1, 3.44094992E-1, 4.02050495E-1, 4.19413745E-1}, +{2.65781403E-1, 3.40084374E-1, 3.69407654E-1, 4.27031696E-1}, +{3.53740931E-1, 3.84463251E-1, 4.11747813E-1, 4.26181793E-1}, +{2.43866488E-1, 2.68350184E-1, 3.42201948E-1, 3.98457229E-1}, +{2.93145239E-1, 3.34754169E-1, 3.61702800E-1, 3.98416638E-1}, +{2.91342974E-1, 3.13155174E-1, 3.36525917E-1, 3.87748599E-1}, +{3.05656791E-1, 3.62904549E-1, 3.88153434E-1, 4.05543149E-1}, +{2.17492327E-1, 3.11723530E-1, 3.75984788E-1, 4.28997755E-1}, +{2.91149259E-1, 3.29380929E-1, 4.03900385E-1, 4.22333181E-1}, +{2.90362060E-1, 3.09530973E-1, 3.78994226E-1, 4.13688362E-1}, +{3.29564869E-1, 3.77404690E-1, 4.06584859E-1, 4.24739718E-1}, +{2.46461585E-1, 2.71593273E-1, 3.66338253E-1, 4.30753767E-1}, +{3.14107716E-1, 3.37011874E-1, 3.80409718E-1, 4.11099434E-1}, +{2.76568413E-1, 3.27320695E-1, 3.58844280E-1, 4.28949475E-1}, +{3.17179084E-1, 3.58972430E-1, 4.04765844E-1, 4.40376341E-1}, +{2.42777750E-1, 3.34954798E-1, 3.96943450E-1, 4.13318396E-1}, +{2.88895488E-1, 3.25691164E-1, 4.22859550E-1, 4.43758667E-1}, +{2.77583301E-1, 3.25479031E-1, 3.89144659E-1, 4.41075861E-1}, +{3.59125674E-1, 3.90694141E-1, 4.21009541E-1, 4.35708523E-1}, +{2.20172390E-1, 2.47719273E-1, 3.54381859E-1, 4.25398111E-1}, +{3.06046784E-1, 3.27924728E-1, 3.66992772E-1, 3.93192589E-1}, +{2.70805597E-1, 3.16826642E-1, 3.45648706E-1, 4.11717594E-1}, +{3.23188901E-1, 3.45463097E-1, 3.89778793E-1, 4.21570778E-1}, +{2.46136114E-1, 3.12391996E-1, 3.72188628E-1, 3.95842731E-1}, +{3.03856730E-1, 3.24354768E-1, 3.85747254E-1, 4.14155006E-1}, +{2.81075418E-1, 3.18608463E-1, 3.85646880E-1, 4.02703643E-1}, +{3.53517115E-1, 3.72702539E-1, 3.96264613E-1, 4.13074911E-1}, +{2.09221140E-1, 2.95262218E-1, 3.80314291E-1, 4.31278229E-1}, +{3.25313628E-1, 3.46735477E-1, 3.70724022E-1, 3.91045630E-1}, +{2.86396503E-1, 3.43560040E-1, 3.69713604E-1, 3.89867842E-1}, +{3.27794671E-1, 3.47367823E-1, 4.05465066E-1, 4.24566150E-1}, +{2.53054976E-1, 3.02656293E-1, 3.82165134E-1, 4.29898322E-1}, +{2.94418454E-1, 3.70745420E-1, 3.95443261E-1, 4.19514775E-1}, +{2.62873113E-1, 3.45069230E-1, 4.04140890E-1, 4.21902061E-1}, +{3.65063488E-1, 3.82435143E-1, 4.13424790E-1, 4.31241691E-1}, +{2.48788506E-1, 2.82372773E-1, 3.65772307E-1, 4.10981059E-1}, +{3.07288766E-1, 3.27828944E-1, 3.77664983E-1, 4.36220944E-1}, +{2.98542321E-1, 3.20627332E-1, 3.50569665E-1, 4.27620232E-1}, +{3.16258013E-1, 3.62903833E-1, 3.88225138E-1, 4.25608873E-1}, +{2.39077866E-1, 3.31310451E-1, 3.70317876E-1, 4.15995896E-1}, +{3.03735793E-1, 3.32806051E-1, 4.10232842E-1, 4.27751064E-1}, +{2.96002507E-1, 3.19014788E-1, 3.81062448E-1, 4.26954985E-1}, +{3.32508922E-1, 3.62516999E-1, 4.23315108E-1, 4.40995157E-1}, +{2.35128701E-1, 2.74731100E-1, 4.12070572E-1, 4.35478806E-1}, +{2.98073769E-1, 3.55338752E-1, 3.79087746E-1, 4.15318787E-1}, +{2.83429801E-1, 3.45264912E-1, 3.70376289E-1, 4.09900844E-1}, +{3.23593080E-1, 3.65412831E-1, 4.12813127E-1, 4.31023479E-1}, +{2.76626348E-1, 3.00508440E-1, 4.02236879E-1, 4.26638782E-1}, +{2.94512928E-1, 3.61443222E-1, 4.19635236E-1, 4.36999202E-1}, +{2.90807247E-1, 3.41689348E-1, 3.92779291E-1, 4.43490267E-1}, +{3.59391451E-1, 4.03985143E-1, 4.40843761E-1, 4.53028619E-1}, +{2.23295465E-1, 2.39192486E-1, 3.23768020E-1, 4.21689451E-1}, +{2.94778049E-1, 3.18798721E-1, 3.53217840E-1, 3.91906381E-1}, +{2.59032130E-1, 3.10240507E-1, 3.43569040E-1, 3.95064235E-1}, +{3.16474676E-1, 3.38544369E-1, 3.93329024E-1, 4.12235558E-1}, +{2.40108207E-1, 2.84631193E-1, 3.60280991E-1, 3.79973769E-1}, +{2.96909094E-1, 3.15798342E-1, 3.94964337E-1, 4.15127575E-1}, +{2.85434067E-1, 3.04921508E-1, 3.61974716E-1, 4.05767262E-1}, +{3.37407053E-1, 3.56672168E-1, 3.85155082E-1, 4.11186695E-1}, +{2.24014923E-1, 2.60116160E-1, 3.94772530E-1, 4.19585884E-1}, +{3.00647914E-1, 3.41640651E-1, 3.70223522E-1, 3.89520049E-1}, +{2.65946031E-1, 3.25039148E-1, 3.74339938E-1, 3.92346144E-1}, +{3.16029310E-1, 3.40491295E-1, 4.02355313E-1, 4.20484245E-1}, +{2.69841492E-1, 2.94562399E-1, 3.62341762E-1, 4.06415462E-1}, +{2.78897285E-1, 3.59831035E-1, 3.82025838E-1, 4.10577476E-1}, +{2.60760844E-1, 3.31088543E-1, 3.88826251E-1, 4.05486643E-1}, +{3.43372285E-1, 3.82647038E-1, 4.14716601E-1, 4.31592941E-1}, +{2.47998103E-1, 2.73393154E-1, 3.31160426E-1, 4.18943226E-1}, +{3.03579569E-1, 3.25202465E-1, 3.70984435E-1, 4.14420485E-1}, +{2.76896894E-1, 3.00499499E-1, 3.54178190E-1, 4.28807020E-1}, +{3.23655546E-1, 3.59816968E-1, 3.89525414E-1, 4.09288704E-1}, +{2.38927796E-1, 3.09919238E-1, 3.53915572E-1, 4.16634321E-1}, +{2.81171739E-1, 3.07520270E-1, 4.16264892E-1, 4.38523829E-1}, +{2.88858652E-1, 3.09810817E-1, 3.67845178E-1, 4.36035573E-1}, +{3.38423491E-1, 3.70634377E-1, 4.15449977E-1, 4.31534529E-1}, +{2.41260394E-1, 2.73617864E-1, 3.89554620E-1, 4.12539542E-1}, +{2.98046708E-1, 3.40122104E-1, 3.86183739E-1, 4.13826346E-1}, +{2.82436430E-1, 3.31597507E-1, 3.57941389E-1, 4.12115216E-1}, +{3.03820193E-1, 3.70588601E-1, 4.05774951E-1, 4.31517065E-1}, +{2.39077732E-1, 3.11638474E-1, 4.13935781E-1, 4.35304046E-1}, +{2.67116845E-1, 3.41937900E-1, 4.17409420E-1, 4.39184844E-1}, +{2.67946839E-1, 3.33343923E-1, 3.86481404E-1, 4.37462509E-1}, +{3.40510964E-1, 3.90878022E-1, 4.35485125E-1, 4.49101925E-1}, +{2.10069850E-1, 2.32524484E-1, 3.61781418E-1, 4.31357861E-1}, +{2.94509888E-1, 3.33709776E-1, 3.82278621E-1, 3.98638904E-1}, +{2.80525148E-1, 3.25905204E-1, 3.50647032E-1, 3.92873943E-1}, +{3.19999635E-1, 3.43674660E-1, 3.91070545E-1, 4.37501073E-1}, +{2.20581010E-1, 3.03151906E-1, 3.81765544E-1, 4.04488146E-1}, +{2.86122739E-1, 3.29746544E-1, 3.88102829E-1, 4.24247742E-1}, +{2.69807100E-1, 3.25332284E-1, 3.79154503E-1, 4.15138245E-1}, +{3.34858894E-1, 3.69258404E-1, 3.94743145E-1, 4.11922157E-1}, +{2.07109794E-1, 2.72779524E-1, 3.78566444E-1, 4.34579968E-1}, +{3.06466222E-1, 3.46695721E-1, 3.87138307E-1, 4.03558314E-1}, +{2.70148575E-1, 3.46654534E-1, 3.77696693E-1, 3.96434486E-1}, +{3.18745911E-1, 3.40225697E-1, 4.14991558E-1, 4.41578746E-1}, +{2.58592844E-1, 3.14370096E-1, 3.65083754E-1, 4.21615183E-1}, +{2.82712996E-1, 3.54137123E-1, 4.06745970E-1, 4.29267883E-1}, +{2.52021760E-1, 3.59105110E-1, 3.95102918E-1, 4.18148398E-1}, +{3.54906201E-1, 3.74952912E-1, 4.18965995E-1, 4.36144412E-1}, +{2.64841139E-1, 2.92941809E-1, 3.27751458E-1, 4.08790469E-1}, +{3.07774246E-1, 3.35586190E-1, 3.62209618E-1, 4.25394237E-1}, +{2.88466334E-1, 3.16075742E-1, 3.60989630E-1, 4.19551432E-1}, +{3.17128420E-1, 3.55772197E-1, 4.05808747E-1, 4.23972964E-1}, +{2.47089684E-1, 3.38184595E-1, 3.71859610E-1, 3.95971477E-1}, +{3.07981730E-1, 3.32691789E-1, 4.00534213E-1, 4.38273668E-1}, +{2.79484808E-1, 3.16183507E-1, 3.97237718E-1, 4.34746623E-1}, +{3.44490469E-1, 3.66153181E-1, 4.10959423E-1, 4.41727102E-1}, +{2.35741779E-1, 2.94587255E-1, 3.98072541E-1, 4.16833401E-1}, +{3.14038455E-1, 3.52272034E-1, 3.79138887E-1, 4.10969079E-1}, +{2.83002496E-1, 3.38136256E-1, 3.88641894E-1, 4.06193316E-1}, +{3.23625326E-1, 3.50243390E-1, 4.28089559E-1, 4.46630359E-1}, +{2.61252105E-1, 3.24970961E-1, 4.00214493E-1, 4.25321758E-1}, +{3.05284500E-1, 3.42164159E-1, 4.24475133E-1, 4.43830967E-1}, +{2.87374794E-1, 3.32500637E-1, 3.94308269E-1, 4.42538500E-1}, +{3.74075353E-1, 4.02026355E-1, 4.30933535E-1, 4.44160044E-1}, +{2.34503999E-1, 2.56218612E-1, 3.41238797E-1, 4.23045278E-1}, +{3.05492580E-1, 3.29156995E-1, 3.52709830E-1, 3.92439067E-1}, +{2.81323552E-1, 3.03292334E-1, 3.48925412E-1, 3.93163860E-1}, +{3.21893454E-1, 3.50419939E-1, 3.97317469E-1, 4.14560318E-1}, +{2.39684582E-1, 2.92451501E-1, 3.78937423E-1, 3.96535456E-1}, +{3.07307243E-1, 3.29127908E-1, 3.98455560E-1, 4.16143298E-1}, +{2.85274565E-1, 3.08774531E-1, 3.92916501E-1, 4.14437652E-1}, +{3.44446361E-1, 3.62201869E-1, 3.97619784E-1, 4.17743623E-1}, +{2.32083067E-1, 2.67807961E-1, 3.78075659E-1, 4.34560895E-1}, +{3.04738700E-1, 3.51865292E-1, 3.75973165E-1, 3.95293653E-1}, +{2.61990905E-1, 3.46207321E-1, 3.71296942E-1, 4.12438929E-1}, +{3.11080933E-1, 3.51040900E-1, 4.16082799E-1, 4.34340119E-1}, +{2.74980426E-1, 2.96631455E-1, 3.87520492E-1, 4.09243762E-1}, +{2.90939093E-1, 3.54455590E-1, 3.93426955E-1, 4.08220291E-1}, +{2.71871865E-1, 3.45510781E-1, 3.87125313E-1, 4.22590613E-1}, +{3.63245904E-1, 3.81932199E-1, 4.04114902E-1, 4.18370664E-1}, +{2.45770738E-1, 2.72909343E-1, 3.48317921E-1, 4.25161839E-1}, +{3.14139009E-1, 3.37872326E-1, 3.65195215E-1, 4.04423416E-1}, +{2.94075787E-1, 3.16935539E-1, 3.43047202E-1, 4.06130373E-1}, +{3.14627469E-1, 3.72413397E-1, 4.00660694E-1, 4.17930841E-1}, +{2.34014243E-1, 3.14007223E-1, 3.83003533E-1, 4.34829175E-1}, +{2.93635666E-1, 3.20529997E-1, 4.10837352E-1, 4.36393142E-1}, +{2.89505839E-1, 3.11828852E-1, 3.86311471E-1, 4.38771248E-1}, +{3.26317430E-1, 3.80858183E-1, 4.19721425E-1, 4.38795507E-1}, +{2.50809520E-1, 2.83018053E-1, 3.82247388E-1, 4.34244394E-1}, +{3.18994045E-1, 3.44855130E-1, 3.72690141E-1, 4.23067033E-1}, +{2.88380086E-1, 3.36622238E-1, 3.69742334E-1, 4.25057590E-1}, +{3.06107700E-1, 3.81856918E-1, 4.18206155E-1, 4.32868361E-1}, +{2.33898312E-1, 3.44861805E-1, 4.12176549E-1, 4.29216206E-1}, +{2.85980880E-1, 3.42903793E-1, 4.25112903E-1, 4.44299698E-1}, +{2.79858828E-1, 3.38789344E-1, 3.92085373E-1, 4.40541029E-1}, +{3.64509344E-1, 3.82202744E-1, 4.29830611E-1, 4.45818365E-1}, +{2.34392300E-1, 2.57377386E-1, 3.59567046E-1, 4.30088580E-1}, +{3.05031896E-1, 3.27589393E-1, 3.78305554E-1, 4.01026130E-1}, +{2.77522624E-1, 3.18130314E-1, 3.67794275E-1, 4.01543021E-1}, +{3.33035767E-1, 3.55820954E-1, 3.87548923E-1, 4.24628675E-1}, +{2.45021001E-1, 3.12560678E-1, 3.91147614E-1, 4.08762813E-1}, +{2.97059119E-1, 3.40246916E-1, 3.92919302E-1, 4.28899705E-1}, +{2.77839303E-1, 3.25019777E-1, 3.97436380E-1, 4.15920913E-1}, +{3.49465251E-1, 3.70362461E-1, 3.95482540E-1, 4.31923389E-1}, +{2.31485590E-1, 2.91023374E-1, 3.77909541E-1, 4.32259738E-1}, +{3.19283485E-1, 3.53671074E-1, 3.80982876E-1, 3.97843361E-1}, +{2.89689243E-1, 3.50265682E-1, 3.80729675E-1, 3.97969365E-1}, +{3.28987300E-1, 3.52005422E-1, 4.12557244E-1, 4.37597930E-1}, +{2.76273251E-1, 3.02267194E-1, 3.81723404E-1, 4.34989095E-1}, +{2.79627264E-1, 3.73727322E-1, 4.12374616E-1, 4.30626333E-1}, +{2.53442764E-1, 3.65940034E-1, 4.14937019E-1, 4.32743609E-1}, +{3.76107216E-1, 3.95142019E-1, 4.16787744E-1, 4.33023572E-1}, +{2.62815833E-1, 2.88270533E-1, 3.47397208E-1, 4.24182594E-1}, +{3.01931322E-1, 3.43652546E-1, 3.77031326E-1, 4.34204459E-1}, +{2.97834277E-1, 3.23495388E-1, 3.64492416E-1, 4.33550835E-1}, +{3.31774473E-1, 3.64324927E-1, 3.98243546E-1, 4.35078323E-1}, +{2.49049723E-1, 3.27870786E-1, 3.83587003E-1, 4.35558081E-1}, +{3.04653406E-1, 3.27671230E-1, 4.18484688E-1, 4.41378772E-1}, +{2.96960890E-1, 3.23898911E-1, 3.90463710E-1, 4.39915955E-1}, +{3.43923748E-1, 3.67100477E-1, 4.29523230E-1, 4.45214987E-1}, +{2.59399652E-1, 2.91602671E-1, 4.04372454E-1, 4.31413233E-1}, +{2.97537506E-1, 3.57573807E-1, 3.88991833E-1, 4.30006981E-1}, +{2.84068942E-1, 3.49574566E-1, 3.81042838E-1, 4.29712772E-1}, +{3.25716257E-1, 3.74875903E-1, 4.31959271E-1, 4.47290838E-1}, +{2.65302956E-1, 3.14745963E-1, 4.16703463E-1, 4.37294722E-1}, +{3.00398588E-1, 3.54147255E-1, 4.28538084E-1, 4.60336387E-1}, +{2.98077166E-1, 3.49304914E-1, 4.00429249E-1, 4.48213518E-1}, +{3.75576198E-1, 4.16657329E-1, 4.42136765E-1, 4.52728629E-1}}; + +static const float evrc_lspq_quant_codebook1[16][5] = { +{0.42091064E-1, 0.69474973E-1, 0.11168948E+0, 0.14571965E+0, 0.20893581E+0}, +{0.54944664E-1, 0.98242261E-1, 0.11007882E+0, 0.15890779E+0, 0.20548241E+0}, +{0.45188572E-1, 0.75199433E-1, 0.11423391E+0, 0.15469728E+0, 0.19746706E+0}, +{0.49474996E-1, 0.79667501E-1, 0.12571351E+0, 0.16944779E+0, 0.20775315E+0}, +{0.41789379E-1, 0.63459560E-1, 0.12068028E+0, 0.15850765E+0, 0.20406815E+0}, +{0.47159236E-1, 0.79129547E-1, 0.12183110E+0, 0.15650047E+0, 0.22309226E+0}, +{0.54539919E-1, 0.80343045E-1, 0.12947764E+0, 0.15186153E+0, 0.20171718E+0}, +{0.55852082E-1, 0.94114847E-1, 0.14016025E+0, 0.17807084E+0, 0.22955489E+0}, +{0.45443531E-1, 0.73541410E-1, 0.11937657E+0, 0.15442030E+0, 0.21010752E+0}, +{0.63178010E-1, 0.95231488E-1, 0.12364983E+0, 0.17672543E+0, 0.21743731E+0}, +{0.52765369E-1, 0.84351443E-1, 0.11589085E+0, 0.15790924E+0, 0.20732352E+0}, +{0.51865745E-1, 0.81328541E-1, 0.13756232E+0, 0.18322878E+0, 0.21640070E+0}, +{0.44419531E-1, 0.68874463E-1, 0.13115251E+0, 0.16263582E+0, 0.21659100E+0}, +{0.49378436E-1, 0.81882551E-1, 0.13067168E+0, 0.16821896E+0, 0.23136081E+0}, +{0.55909779E-1, 0.90783298E-1, 0.13348848E+0, 0.16298474E+0, 0.20961523E+0}, +{0.61378211E-1, 0.98602772E-1, 0.14793332E+0, 0.19283190E+0, 0.23156509E+0}}; + +static const float evrc_lspq_quant_codebook2[16][5] = { +{0.26822963, 0.30585295, 0.31110349, 0.36823335, 0.40774474}, +{0.24418014, 0.28970167, 0.32573757, 0.39021483, 0.41345838}, +{0.23341830, 0.30078292, 0.32893899, 0.38557330, 0.41068462}, +{0.25905868, 0.29756859, 0.34196618, 0.38531172, 0.41295227}, +{0.24290450, 0.29223618, 0.32718554, 0.37788135, 0.40332928}, +{0.24674191, 0.29749370, 0.33631226, 0.39426059, 0.42258954}, +{0.21377595, 0.33140418, 0.34067687, 0.38222077, 0.40939021}, +{0.26673481, 0.30791649, 0.34419721, 0.39611506, 0.42387524}, +{0.26121426, 0.30492544, 0.32997236, 0.38486803, 0.42023736}, +{0.24954870, 0.29372856, 0.33382735, 0.37850669, 0.41714057}, +{0.24158891, 0.30173415, 0.34128246, 0.38428575, 0.41619650}, +{0.25818908, 0.31736413, 0.34904337, 0.38769925, 0.41551358}, +{0.24450587, 0.30673453, 0.33579323, 0.37844428, 0.40557048}, +{0.25164026, 0.31225079, 0.33847794, 0.39554194, 0.42396802}, +{0.22787990, 0.31779197, 0.33831909, 0.40044111, 0.41185561}, +{0.27896860, 0.32261974, 0.35658112, 0.40206763, 0.42370448}}; + +static const float const *evrc_lspq_full_codebooks[] = { + evrc_lspq_full_codebook1[0], evrc_lspq_full_codebook2[0], + evrc_lspq_full_codebook3[0], evrc_lspq_full_codebook4[0], +}; + +static const float const *evrc_lspq_half_codebooks[] = { + evrc_lspq_half_codebook1[0], evrc_lspq_half_codebook2[0], + evrc_lspq_half_codebook3[0], +}; + +static const float const *evrc_lspq_quant_codebooks[] = { + evrc_lspq_quant_codebook1[0], evrc_lspq_quant_codebook2[0], +}; + +static const float const **evrc_lspq_codebooks[] = { + 0, + evrc_lspq_quant_codebooks, + 0, + evrc_lspq_half_codebooks, + evrc_lspq_full_codebooks, +}; + +static const uint8_t evrc_lspq_nb_codebooks[] = { + 0, + FF_ARRAY_ELEMS(evrc_lspq_quant_codebooks), + 0, + FF_ARRAY_ELEMS(evrc_lspq_half_codebooks), + FF_ARRAY_ELEMS(evrc_lspq_full_codebooks), +}; + +static const uint8_t evrc_lspq_full_codebooks_row_sizes[] = { + FF_ARRAY_ELEMS(evrc_lspq_full_codebook1[0]), + FF_ARRAY_ELEMS(evrc_lspq_full_codebook2[0]), + FF_ARRAY_ELEMS(evrc_lspq_full_codebook3[0]), + FF_ARRAY_ELEMS(evrc_lspq_full_codebook4[0]), +}; + +static const uint8_t evrc_lspq_half_codebooks_row_sizes[] = { + FF_ARRAY_ELEMS(evrc_lspq_half_codebook1[0]), + FF_ARRAY_ELEMS(evrc_lspq_half_codebook2[0]), + FF_ARRAY_ELEMS(evrc_lspq_half_codebook3[0]), +}; + +static const uint8_t evrc_lspq_quant_codebooks_row_sizes[] = { + FF_ARRAY_ELEMS(evrc_lspq_quant_codebook1[0]), + FF_ARRAY_ELEMS(evrc_lspq_quant_codebook2[0]), +}; + +static const uint8_t* const evrc_lspq_codebooks_row_sizes[] = { + NULL, + evrc_lspq_quant_codebooks_row_sizes, + NULL, + evrc_lspq_half_codebooks_row_sizes, + evrc_lspq_full_codebooks_row_sizes, +}; + +static const float pitch_gain_vq[] = { 0, 0.3, 0.55, 0.7, 0.8, 0.9, 1, 1.2 }; +static const float estimation_delay[] = { 55.0, 80.0, 39.0, 71.0, 33.0 }; // 5.2.3.4 +static const uint8_t subframe_sizes[] = { 53, 53, 54 }; +#endif /* AVCODEC_EVRCDATA_H */ diff --git a/ffmpeg/libavcodec/evrcdec.c b/ffmpeg/libavcodec/evrcdec.c new file mode 100644 index 0000000..7691455 --- /dev/null +++ b/ffmpeg/libavcodec/evrcdec.c @@ -0,0 +1,917 @@ +/* + * Enhanced Variable Rate Codec, Service Option 3 decoder + * Copyright (c) 2013 Paul B Mahol + * + * 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 + */ + +/** + * @file + * Enhanced Variable Rate Codec, Service Option 3 decoder + * @author Paul B Mahol + */ + +#include "libavutil/mathematics.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "evrcdata.h" +#include "acelp_vectors.h" +#include "lsp.h" + +#define MIN_LSP_SEP (0.05 / (2.0 * M_PI)) +#define MIN_DELAY 20 +#define MAX_DELAY 120 +#define NB_SUBFRAMES 3 +#define SUBFRAME_SIZE 54 +#define FILTER_ORDER 10 +#define ACB_SIZE 128 + +typedef enum { + RATE_ERRS = -1, + SILENCE, + RATE_QUANT, + RATE_QUARTER, + RATE_HALF, + RATE_FULL, +} evrc_packet_rate; + +/** + * EVRC-A unpacked data frame + */ +typedef struct EVRCAFrame { + uint8_t lpc_flag; ///< spectral change indicator + uint16_t lsp[4]; ///< index into LSP codebook + uint8_t pitch_delay; ///< pitch delay for entire frame + uint8_t delay_diff; ///< delay difference for entire frame + uint8_t acb_gain[3]; ///< adaptive codebook gain + uint16_t fcb_shape[3][4]; ///< fixed codebook shape + uint8_t fcb_gain[3]; ///< fixed codebook gain index + uint8_t energy_gain; ///< frame energy gain index + uint8_t tty; ///< tty baud rate bit +} EVRCAFrame; + +typedef struct EVRCContext { + GetBitContext gb; + evrc_packet_rate bitrate; + evrc_packet_rate last_valid_bitrate; + EVRCAFrame frame; + + float lspf[FILTER_ORDER]; + float prev_lspf[FILTER_ORDER]; + float synthesis[FILTER_ORDER]; + float postfilter_fir[FILTER_ORDER]; + float postfilter_iir[FILTER_ORDER]; + float postfilter_residual[ACB_SIZE + SUBFRAME_SIZE]; + float pitch_delay; + float prev_pitch_delay; + float avg_acb_gain; ///< average adaptive codebook gain + float avg_fcb_gain; ///< average fixed codebook gain + float pitch[ACB_SIZE + FILTER_ORDER + SUBFRAME_SIZE]; + float pitch_back[ACB_SIZE]; + float interpolation_coeffs[136]; + float energy_vector[NB_SUBFRAMES]; + float fade_scale; + float last; + + uint8_t prev_energy_gain; + uint8_t prev_error_flag; + uint8_t warned_buf_mismatch_bitrate; +} EVRCContext; + +/** + * Frame unpacking for RATE_FULL, RATE_HALF and RATE_QUANT + * + * @param e the context + * + * TIA/IS-127 Table 4.21-1 + */ +static void unpack_frame(EVRCContext *e) +{ + EVRCAFrame *frame = &e->frame; + GetBitContext *gb = &e->gb; + + switch (e->bitrate) { + case RATE_FULL: + frame->lpc_flag = get_bits1(gb); + frame->lsp[0] = get_bits(gb, 6); + frame->lsp[1] = get_bits(gb, 6); + frame->lsp[2] = get_bits(gb, 9); + frame->lsp[3] = get_bits(gb, 7); + frame->pitch_delay = get_bits(gb, 7); + frame->delay_diff = get_bits(gb, 5); + frame->acb_gain[0] = get_bits(gb, 3); + frame->fcb_shape[0][0] = get_bits(gb, 8); + frame->fcb_shape[0][1] = get_bits(gb, 8); + frame->fcb_shape[0][2] = get_bits(gb, 8); + frame->fcb_shape[0][3] = get_bits(gb, 11); + frame->fcb_gain[0] = get_bits(gb, 5); + frame->acb_gain[1] = get_bits(gb, 3); + frame->fcb_shape[1][0] = get_bits(gb, 8); + frame->fcb_shape[1][1] = get_bits(gb, 8); + frame->fcb_shape[1][2] = get_bits(gb, 8); + frame->fcb_shape[1][3] = get_bits(gb, 11); + frame->fcb_gain [1] = get_bits(gb, 5); + frame->acb_gain [2] = get_bits(gb, 3); + frame->fcb_shape[2][0] = get_bits(gb, 8); + frame->fcb_shape[2][1] = get_bits(gb, 8); + frame->fcb_shape[2][2] = get_bits(gb, 8); + frame->fcb_shape[2][3] = get_bits(gb, 11); + frame->fcb_gain [2] = get_bits(gb, 5); + frame->tty = get_bits1(gb); + break; + case RATE_HALF: + frame->lsp [0] = get_bits(gb, 7); + frame->lsp [1] = get_bits(gb, 7); + frame->lsp [2] = get_bits(gb, 8); + frame->pitch_delay = get_bits(gb, 7); + frame->acb_gain [0] = get_bits(gb, 3); + frame->fcb_shape[0][0] = get_bits(gb, 10); + frame->fcb_gain [0] = get_bits(gb, 4); + frame->acb_gain [1] = get_bits(gb, 3); + frame->fcb_shape[1][0] = get_bits(gb, 10); + frame->fcb_gain [1] = get_bits(gb, 4); + frame->acb_gain [2] = get_bits(gb, 3); + frame->fcb_shape[2][0] = get_bits(gb, 10); + frame->fcb_gain [2] = get_bits(gb, 4); + break; + case RATE_QUANT: + frame->lsp [0] = get_bits(gb, 4); + frame->lsp [1] = get_bits(gb, 4); + frame->energy_gain = get_bits(gb, 8); + break; + } +} + +static evrc_packet_rate buf_size2bitrate(const int buf_size) +{ + switch (buf_size) { + case 23: return RATE_FULL; + case 11: return RATE_HALF; + case 6: return RATE_QUARTER; + case 3: return RATE_QUANT; + case 1: return SILENCE; + } + + return RATE_ERRS; +} + +/** + * Determine the bitrate from the frame size and/or the first byte of the frame. + * + * @param avctx the AV codec context + * @param buf_size length of the buffer + * @param buf the bufffer + * + * @return the bitrate on success, + * RATE_ERRS if the bitrate cannot be satisfactorily determined + */ +static evrc_packet_rate determine_bitrate(AVCodecContext *avctx, + int *buf_size, + const uint8_t **buf) +{ + evrc_packet_rate bitrate; + + if ((bitrate = buf_size2bitrate(*buf_size)) >= 0) { + if (bitrate > **buf) { + EVRCContext *e = avctx->priv_data; + if (!e->warned_buf_mismatch_bitrate) { + av_log(avctx, AV_LOG_WARNING, + "Claimed bitrate and buffer size mismatch.\n"); + e->warned_buf_mismatch_bitrate = 1; + } + bitrate = **buf; + } else if (bitrate < **buf) { + av_log(avctx, AV_LOG_ERROR, + "Buffer is too small for the claimed bitrate.\n"); + return RATE_ERRS; + } + (*buf)++; + *buf_size -= 1; + } else if ((bitrate = buf_size2bitrate(*buf_size + 1)) >= 0) { + av_log(avctx, AV_LOG_DEBUG, + "Bitrate byte is missing, guessing the bitrate from packet size.\n"); + } else + return RATE_ERRS; + + return bitrate; +} + +static void warn_insufficient_frame_quality(AVCodecContext *avctx, + const char *message) +{ + av_log(avctx, AV_LOG_WARNING, "Frame #%d, %s\n", + avctx->frame_number, message); +} + +/** + * Initialize the speech codec according to the specification. + * + * TIA/IS-127 5.2 + */ +static av_cold int evrc_decode_init(AVCodecContext *avctx) +{ + EVRCContext *e = avctx->priv_data; + int i, n, idx = 0; + float denom = 2.0 / (2.0 * 8.0 + 1.0); + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + for (i = 0; i < FILTER_ORDER; i++) { + e->prev_lspf[i] = (i + 1) * 0.048; + e->synthesis[i] = 0.0; + } + + for (i = 0; i < ACB_SIZE; i++) + e->pitch[i] = e->pitch_back[i] = 0.0; + + e->last_valid_bitrate = RATE_QUANT; + e->prev_pitch_delay = 40.0; + e->fade_scale = 1.0; + e->prev_error_flag = 0; + e->avg_acb_gain = e->avg_fcb_gain = 0.0; + + for (i = 0; i < 8; i++) { + float tt = ((float)i - 8.0 / 2.0) / 8.0; + + for (n = -8; n <= 8; n++, idx++) { + float arg1 = M_PI * 0.9 * (tt - n); + float arg2 = M_PI * (tt - n); + + e->interpolation_coeffs[idx] = 0.9; + if (arg1) + e->interpolation_coeffs[idx] *= (0.54 + 0.46 * cos(arg2 * denom)) * + sin(arg1) / arg1; + } + } + + return 0; +} + +/** + * Decode the 10 vector quantized line spectral pair frequencies from the LSP + * transmission codes of any bitrate and check for badly received packets. + * + * @param e the context + * + * @return 0 on success, -1 if the packet is badly received + * + * TIA/IS-127 5.2.1, 5.7.1 + */ +static int decode_lspf(EVRCContext *e) +{ + const float **codebooks = evrc_lspq_codebooks[e->bitrate]; + int i, j, k = 0; + + for (i = 0; i < evrc_lspq_nb_codebooks[e->bitrate]; i++) { + int row_size = evrc_lspq_codebooks_row_sizes[e->bitrate][i]; + const float *codebook = codebooks[i]; + + for (j = 0; j < row_size; j++) + e->lspf[k++] = codebook[e->frame.lsp[i] * row_size + j]; + } + + // check for monotonic LSPs + for (i = 1; i < FILTER_ORDER; i++) + if (e->lspf[i] <= e->lspf[i - 1]) + return -1; + + // check for minimum separation of LSPs at the splits + for (i = 0, k = 0; i < evrc_lspq_nb_codebooks[e->bitrate] - 1; i++) { + k += evrc_lspq_codebooks_row_sizes[e->bitrate][i]; + if (e->lspf[k] - e->lspf[k - 1] <= MIN_LSP_SEP) + return -1; + } + + return 0; +} + +/* + * Interpolation of LSP parameters. + * + * TIA/IS-127 5.2.3.1, 5.7.3.2 + */ +static void interpolate_lsp(float *ilsp, const float *lsp, + const float *prev, int index) +{ + static const float lsp_interpolation_factors[] = { 0.1667, 0.5, 0.8333 }; + ff_weighted_vector_sumf(ilsp, prev, lsp, + 1.0 - lsp_interpolation_factors[index], + lsp_interpolation_factors[index], FILTER_ORDER); +} + +/* + * Reconstruction of the delay contour. + * + * TIA/IS-127 5.2.2.3.2 + */ +static void interpolate_delay(float *dst, float current, float prev, int index) +{ + static const float d_interpolation_factors[] = { 0, 0.3313, 0.6625, 1, 1 }; + dst[0] = (1.0 - d_interpolation_factors[index ]) * prev + + d_interpolation_factors[index ] * current; + dst[1] = (1.0 - d_interpolation_factors[index + 1]) * prev + + d_interpolation_factors[index + 1] * current; + dst[2] = (1.0 - d_interpolation_factors[index + 2]) * prev + + d_interpolation_factors[index + 2] * current; +} + +/* + * Convert the quantized, interpolated line spectral frequencies, + * to prediction coefficients. + * + * TIA/IS-127 5.2.3.2, 4.7.2.2 + */ +static void decode_predictor_coeffs(const float *ilspf, float *ilpc) +{ + double lsp[FILTER_ORDER]; + float a[FILTER_ORDER / 2 + 1], b[FILTER_ORDER / 2 + 1]; + float a1[FILTER_ORDER / 2] = { 0 }; + float a2[FILTER_ORDER / 2] = { 0 }; + float b1[FILTER_ORDER / 2] = { 0 }; + float b2[FILTER_ORDER / 2] = { 0 }; + int i, k; + + ff_acelp_lsf2lspd(lsp, ilspf, FILTER_ORDER); + + for (k = 0; k <= FILTER_ORDER; k++) { + a[0] = k < 2 ? 0.25 : 0; + b[0] = k < 2 ? k < 1 ? 0.25 : -0.25 : 0; + + for (i = 0; i < FILTER_ORDER / 2; i++) { + a[i + 1] = a[i] - 2 * lsp[i * 2 ] * a1[i] + a2[i]; + b[i + 1] = b[i] - 2 * lsp[i * 2 + 1] * b1[i] + b2[i]; + a2[i] = a1[i]; + a1[i] = a[i]; + b2[i] = b1[i]; + b1[i] = b[i]; + } + + if (k) + ilpc[k - 1] = 2.0 * (a[FILTER_ORDER / 2] + b[FILTER_ORDER / 2]); + } +} + +static void bl_intrp(EVRCContext *e, float *ex, float delay) +{ + float *f; + int offset, i, coef_idx; + int16_t t; + + offset = lrintf(fabs(delay)); + + t = (offset - delay + 0.5) * 8.0 + 0.5; + if (t == 8) { + t = 0; + offset--; + } + + f = ex - offset - 8; + + coef_idx = t * (2 * 8 + 1); + + ex[0] = 0.0; + for (i = 0; i < 2 * 8 + 1; i++) + ex[0] += e->interpolation_coeffs[coef_idx + i] * f[i]; +} + +/* + * Adaptive codebook excitation. + * + * TIA/IS-127 5.2.2.3.3, 4.12.5.2 + */ +static void acb_excitation(EVRCContext *e, float *excitation, float gain, + const float delay[3], int length) +{ + float denom, locdelay, dpr, invl; + int i; + + invl = 1.0 / ((float) length); + dpr = length; + + /* first at-most extra samples */ + denom = (delay[1] - delay[0]) * invl; + for (i = 0; i < dpr; i++) { + locdelay = delay[0] + i * denom; + bl_intrp(e, excitation + i, locdelay); + } + + denom = (delay[2] - delay[1]) * invl; + /* interpolation */ + for (i = dpr; i < dpr + 10; i++) { + locdelay = delay[1] + (i - dpr) * denom; + bl_intrp(e, excitation + i, locdelay); + } + + for (i = 0; i < length; i++) + excitation[i] *= gain; +} + +static void decode_8_pulses_35bits(const uint16_t *fixed_index, float *cod) +{ + int i, pos1, pos2, offset; + + offset = (fixed_index[3] >> 9) & 3; + + for (i = 0; i < 3; i++) { + pos1 = ((fixed_index[i] & 0x7f) / 11) * 5 + ((i + offset) % 5); + pos2 = ((fixed_index[i] & 0x7f) % 11) * 5 + ((i + offset) % 5); + + cod[pos1] = (fixed_index[i] & 0x80) ? -1.0 : 1.0; + + if (pos2 < pos1) + cod[pos2] = -cod[pos1]; + else + cod[pos2] += cod[pos1]; + } + + pos1 = ((fixed_index[3] & 0x7f) / 11) * 5 + ((3 + offset) % 5); + pos2 = ((fixed_index[3] & 0x7f) % 11) * 5 + ((4 + offset) % 5); + + cod[pos1] = (fixed_index[3] & 0x100) ? -1.0 : 1.0; + cod[pos2] = (fixed_index[3] & 0x80 ) ? -1.0 : 1.0; +} + +static void decode_3_pulses_10bits(uint16_t fixed_index, float *cod) +{ + float sign; + int pos; + + sign = (fixed_index & 0x200) ? -1.0 : 1.0; + + pos = ((fixed_index & 0x7) * 7) + 4; + cod[pos] += sign; + pos = (((fixed_index >> 3) & 0x7) * 7) + 2; + cod[pos] -= sign; + pos = (((fixed_index >> 6) & 0x7) * 7); + cod[pos] += sign; +} + +/* + * Reconstruction of ACELP fixed codebook excitation for full and half rate. + * + * TIA/IS-127 5.2.3.7 + */ +static void fcb_excitation(EVRCContext *e, const uint16_t *codebook, + float *excitation, float pitch_gain, + int pitch_lag, int subframe_size) +{ + int i; + + if (e->bitrate == RATE_FULL) + decode_8_pulses_35bits(codebook, excitation); + else + decode_3_pulses_10bits(*codebook, excitation); + + pitch_gain = av_clipf(pitch_gain, 0.2, 0.9); + + for (i = pitch_lag; i < subframe_size; i++) + excitation[i] += pitch_gain * excitation[i - pitch_lag]; +} + +/** + * Synthesis of the decoder output signal. + * + * param[in] in input signal + * param[in] filter_coeffs LPC coefficients + * param[in/out] memory synthesis filter memory + * param buffer_length amount of data to process + * param[out] samples output samples + * + * TIA/IS-127 5.2.3.15, 5.7.3.4 + */ +static void synthesis_filter(const float *in, const float *filter_coeffs, + float *memory, int buffer_length, float *samples) +{ + int i, j; + + for (i = 0; i < buffer_length; i++) { + samples[i] = in[i]; + for (j = FILTER_ORDER - 1; j > 0; j--) { + samples[i] -= filter_coeffs[j] * memory[j]; + memory[j] = memory[j - 1]; + } + samples[i] -= filter_coeffs[0] * memory[0]; + memory[0] = samples[i]; + } +} + +static void bandwidth_expansion(float *coeff, const float *inbuf, float gamma) +{ + double fac = gamma; + int i; + + for (i = 0; i < FILTER_ORDER; i++) { + coeff[i] = inbuf[i] * fac; + fac *= gamma; + } +} + +static void residual_filter(float *output, const float *input, + const float *coef, float *memory, int length) +{ + float sum; + int i, j; + + for (i = 0; i < length; i++) { + sum = input[i]; + + for (j = FILTER_ORDER - 1; j > 0; j--) { + sum += coef[j] * memory[j]; + memory[j] = memory[j - 1]; + } + sum += coef[0] * memory[0]; + memory[0] = input[i]; + output[i] = sum; + } +} + +/* + * TIA/IS-127 Table 5.9.1-1. + */ +static const struct PfCoeff { + float tilt; + float ltgain; + float p1; + float p2; +} postfilter_coeffs[5] = { + { 0.0 , 0.0 , 0.0 , 0.0 }, + { 0.0 , 0.0 , 0.57, 0.57 }, + { 0.0 , 0.0 , 0.0 , 0.0 }, + { 0.35, 0.50, 0.50, 0.75 }, + { 0.20, 0.50, 0.57, 0.75 }, +}; + +/* + * Adaptive postfilter. + * + * TIA/IS-127 5.9 + */ +static void postfilter(EVRCContext *e, float *in, const float *coeff, + float *out, int idx, const struct PfCoeff *pfc, + int length) +{ + float wcoef1[FILTER_ORDER], wcoef2[FILTER_ORDER], + scratch[SUBFRAME_SIZE], temp[SUBFRAME_SIZE], + mem[SUBFRAME_SIZE]; + float sum1 = 0.0, sum2 = 0.0, gamma, gain; + float tilt = pfc->tilt; + int i, n, best; + + bandwidth_expansion(wcoef1, coeff, pfc->p1); + bandwidth_expansion(wcoef2, coeff, pfc->p2); + + /* Tilt compensation filter, TIA/IS-127 5.9.1 */ + for (i = 0; i < length - 1; i++) + sum2 += in[i] * in[i + 1]; + if (sum2 < 0.0) + tilt = 0.0; + + for (i = 0; i < length; i++) { + scratch[i] = in[i] - tilt * e->last; + e->last = in[i]; + } + + /* Short term residual filter, TIA/IS-127 5.9.2 */ + residual_filter(&e->postfilter_residual[ACB_SIZE], scratch, wcoef1, e->postfilter_fir, length); + + /* Long term postfilter */ + best = idx; + for (i = FFMIN(MIN_DELAY, idx - 3); i <= FFMAX(MAX_DELAY, idx + 3); i++) { + for (n = ACB_SIZE, sum2 = 0; n < ACB_SIZE + length; n++) + sum2 += e->postfilter_residual[n] * e->postfilter_residual[n - i]; + if (sum2 > sum1) { + sum1 = sum2; + best = i; + } + } + + for (i = ACB_SIZE, sum1 = 0; i < ACB_SIZE + length; i++) + sum1 += e->postfilter_residual[i - best] * e->postfilter_residual[i - best]; + for (i = ACB_SIZE, sum2 = 0; i < ACB_SIZE + length; i++) + sum2 += e->postfilter_residual[i] * e->postfilter_residual[i - best]; + + if (sum2 * sum1 == 0 || e->bitrate == RATE_QUANT) { + memcpy(temp, e->postfilter_residual + ACB_SIZE, length * sizeof(float)); + } else { + gamma = sum2 / sum1; + if (gamma < 0.5) + memcpy(temp, e->postfilter_residual + ACB_SIZE, length * sizeof(float)); + else { + gamma = FFMIN(gamma, 1.0); + + for (i = 0; i < length; i++) { + temp[i] = e->postfilter_residual[ACB_SIZE + i] + gamma * + pfc->ltgain * e->postfilter_residual[ACB_SIZE + i - best]; + } + } + } + + memcpy(scratch, temp, length * sizeof(float)); + memcpy(mem, e->postfilter_iir, FILTER_ORDER * sizeof(float)); + synthesis_filter(scratch, wcoef2, mem, length, scratch); + + /* Gain computation, TIA/IS-127 5.9.4-2 */ + for (i = 0, sum1 = 0, sum2 = 0; i < length; i++) { + sum1 += in[i] * in[i]; + sum2 += scratch[i] * scratch[i]; + } + gain = sum2 ? sqrt(sum1 / sum2) : 1.0; + + for (i = 0; i < length; i++) + temp[i] *= gain; + + /* Short term postfilter */ + synthesis_filter(temp, wcoef2, e->postfilter_iir, length, out); + + memcpy(e->postfilter_residual, + e->postfilter_residual + length, ACB_SIZE * sizeof(float)); +} + +static void frame_erasure(EVRCContext *e, float *samples) +{ + float ilspf[FILTER_ORDER], ilpc[FILTER_ORDER], idelay[NB_SUBFRAMES], + tmp[SUBFRAME_SIZE + 6], f; + int i, j; + + for (i = 0; i < FILTER_ORDER; i++) { + if (e->bitrate != RATE_QUANT) + e->lspf[i] = e->prev_lspf[i] * 0.875 + 0.125 * (i + 1) * 0.048; + else + e->lspf[i] = e->prev_lspf[i]; + } + + if (e->prev_error_flag) + e->avg_acb_gain *= 0.75; + if (e->bitrate == RATE_FULL) + memcpy(e->pitch_back, e->pitch, ACB_SIZE * sizeof(float)); + if (e->last_valid_bitrate == RATE_QUANT) + e->bitrate = RATE_QUANT; + else + e->bitrate = RATE_FULL; + + if (e->bitrate == RATE_FULL || e->bitrate == RATE_HALF) { + e->pitch_delay = e->prev_pitch_delay; + } else { + float sum = 0; + + idelay[0] = idelay[1] = idelay[2] = MIN_DELAY; + + for (i = 0; i < NB_SUBFRAMES; i++) + sum += evrc_energy_quant[e->prev_energy_gain][i]; + sum /= (float) NB_SUBFRAMES; + sum = pow(10, sum); + for (i = 0; i < NB_SUBFRAMES; i++) + e->energy_vector[i] = sum; + } + + if (fabs(e->pitch_delay - e->prev_pitch_delay) > 15) + e->prev_pitch_delay = e->pitch_delay; + + for (i = 0; i < NB_SUBFRAMES; i++) { + int subframe_size = subframe_sizes[i]; + int pitch_lag; + + interpolate_lsp(ilspf, e->lspf, e->prev_lspf, i); + + if (e->bitrate != RATE_QUANT) { + if (e->avg_acb_gain < 0.3) { + idelay[0] = estimation_delay[i]; + idelay[1] = estimation_delay[i + 1]; + idelay[2] = estimation_delay[i + 2]; + } else { + interpolate_delay(idelay, e->pitch_delay, e->prev_pitch_delay, i); + } + } + + pitch_lag = lrintf((idelay[1] + idelay[0]) / 2.0); + decode_predictor_coeffs(ilspf, ilpc); + + if (e->bitrate != RATE_QUANT) { + acb_excitation(e, e->pitch + ACB_SIZE, + e->avg_acb_gain, idelay, subframe_size); + for (j = 0; j < subframe_size; j++) + e->pitch[ACB_SIZE + j] *= e->fade_scale; + e->fade_scale = FFMAX(e->fade_scale - 0.05, 0.0); + } else { + for (j = 0; j < subframe_size; j++) + e->pitch[ACB_SIZE + j] = e->energy_vector[i]; + } + + memcpy(e->pitch, e->pitch + subframe_size, ACB_SIZE * sizeof(float)); + + if (e->bitrate != RATE_QUANT && e->avg_acb_gain < 0.4) { + f = 0.1 * e->avg_fcb_gain; + for (j = 0; j < subframe_size; j++) + e->pitch[ACB_SIZE + j] += f; + } else if (e->bitrate == RATE_QUANT) { + for (j = 0; j < subframe_size; j++) + e->pitch[ACB_SIZE + j] = e->energy_vector[i]; + } + + synthesis_filter(e->pitch + ACB_SIZE, ilpc, + e->synthesis, subframe_size, tmp); + postfilter(e, tmp, ilpc, samples, pitch_lag, + &postfilter_coeffs[e->bitrate], subframe_size); + + samples += subframe_size; + } +} + +static int evrc_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + AVFrame *frame = data; + EVRCContext *e = avctx->priv_data; + int buf_size = avpkt->size; + float ilspf[FILTER_ORDER], ilpc[FILTER_ORDER], idelay[NB_SUBFRAMES]; + float *samples; + int i, j, ret, error_flag = 0; + + frame->nb_samples = 160; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (float *)frame->data[0]; + + if ((e->bitrate = determine_bitrate(avctx, &buf_size, &buf)) == RATE_ERRS) { + warn_insufficient_frame_quality(avctx, "bitrate cannot be determined."); + goto erasure; + } + if (e->bitrate <= SILENCE || e->bitrate == RATE_QUARTER) + goto erasure; + if (e->bitrate == RATE_QUANT && e->last_valid_bitrate == RATE_FULL + && !e->prev_error_flag) + goto erasure; + + init_get_bits(&e->gb, buf, 8 * buf_size); + memset(&e->frame, 0, sizeof(EVRCAFrame)); + + unpack_frame(e); + + if (e->bitrate != RATE_QUANT) { + uint8_t *p = (uint8_t *) &e->frame; + for (i = 0; i < sizeof(EVRCAFrame); i++) { + if (p[i]) + break; + } + if (i == sizeof(EVRCAFrame)) + goto erasure; + } else if (e->frame.lsp[0] == 0xf && + e->frame.lsp[1] == 0xf && + e->frame.energy_gain == 0xff) { + goto erasure; + } + + if (decode_lspf(e) < 0) + goto erasure; + + if (e->bitrate == RATE_FULL || e->bitrate == RATE_HALF) { + /* Pitch delay parameter checking as per TIA/IS-127 5.1.5.1 */ + if (e->frame.pitch_delay > MAX_DELAY - MIN_DELAY) + goto erasure; + + e->pitch_delay = e->frame.pitch_delay + MIN_DELAY; + + /* Delay diff parameter checking as per TIA/IS-127 5.1.5.2 */ + if (e->frame.delay_diff) { + int p = e->pitch_delay - e->frame.delay_diff + 16; + if (p < MIN_DELAY || p > MAX_DELAY) + goto erasure; + } + + /* Delay contour reconstruction as per TIA/IS-127 5.2.2.2 */ + if (e->frame.delay_diff && + e->bitrate == RATE_FULL && e->prev_error_flag) { + float delay; + + memcpy(e->pitch, e->pitch_back, ACB_SIZE * sizeof(float)); + + delay = e->prev_pitch_delay; + e->prev_pitch_delay = delay - e->frame.delay_diff + 16.0; + + if (fabs(e->pitch_delay - delay) > 15) + delay = e->pitch_delay; + + for (i = 0; i < NB_SUBFRAMES; i++) { + int subframe_size = subframe_sizes[i]; + + interpolate_delay(idelay, delay, e->prev_pitch_delay, i); + acb_excitation(e, e->pitch + ACB_SIZE, e->avg_acb_gain, idelay, subframe_size); + memcpy(e->pitch, e->pitch + subframe_size, ACB_SIZE * sizeof(float)); + } + } + + /* Smoothing of the decoded delay as per TIA/IS-127 5.2.2.5 */ + if (fabs(e->pitch_delay - e->prev_pitch_delay) > 15) + e->prev_pitch_delay = e->pitch_delay; + + e->avg_acb_gain = e->avg_fcb_gain = 0.0; + } else { + idelay[0] = idelay[1] = idelay[2] = MIN_DELAY; + + /* Decode frame energy vectors as per TIA/IS-127 5.7.2 */ + for (i = 0; i < NB_SUBFRAMES; i++) + e->energy_vector[i] = pow(10, evrc_energy_quant[e->frame.energy_gain][i]); + e->prev_energy_gain = e->frame.energy_gain; + } + + for (i = 0; i < NB_SUBFRAMES; i++) { + float tmp[SUBFRAME_SIZE + 6] = { 0 }; + int subframe_size = subframe_sizes[i]; + int pitch_lag; + + interpolate_lsp(ilspf, e->lspf, e->prev_lspf, i); + + if (e->bitrate != RATE_QUANT) + interpolate_delay(idelay, e->pitch_delay, e->prev_pitch_delay, i); + + pitch_lag = lrintf((idelay[1] + idelay[0]) / 2.0); + decode_predictor_coeffs(ilspf, ilpc); + + /* Bandwidth expansion as per TIA/IS-127 5.2.3.3 */ + if (e->frame.lpc_flag && e->prev_error_flag) + bandwidth_expansion(ilpc, ilpc, 0.75); + + if (e->bitrate != RATE_QUANT) { + float acb_sum, f; + + f = exp((e->bitrate == RATE_HALF ? 0.5 : 0.25) + * (e->frame.fcb_gain[i] + 1)); + acb_sum = pitch_gain_vq[e->frame.acb_gain[i]]; + e->avg_acb_gain += acb_sum / NB_SUBFRAMES; + e->avg_fcb_gain += f / NB_SUBFRAMES; + + acb_excitation(e, e->pitch + ACB_SIZE, + acb_sum, idelay, subframe_size); + fcb_excitation(e, e->frame.fcb_shape[i], tmp, + acb_sum, pitch_lag, subframe_size); + + /* Total excitation generation as per TIA/IS-127 5.2.3.9 */ + for (j = 0; j < subframe_size; j++) + e->pitch[ACB_SIZE + j] += f * tmp[j]; + e->fade_scale = FFMIN(e->fade_scale + 0.2, 1.0); + } else { + for (j = 0; j < subframe_size; j++) + e->pitch[ACB_SIZE + j] = e->energy_vector[i]; + } + + memcpy(e->pitch, e->pitch + subframe_size, ACB_SIZE * sizeof(float)); + + synthesis_filter(e->pitch + ACB_SIZE, ilpc, + e->synthesis, subframe_size, tmp); + postfilter(e, tmp, ilpc, samples, pitch_lag, + &postfilter_coeffs[e->bitrate], subframe_size); + + samples += subframe_size; + } + + if (error_flag) { +erasure: + error_flag = 1; + av_log(avctx, AV_LOG_WARNING, "frame erasure\n"); + frame_erasure(e, samples); + } + + memcpy(e->prev_lspf, e->lspf, sizeof(e->prev_lspf)); + e->prev_error_flag = error_flag; + e->last_valid_bitrate = e->bitrate; + + if (e->bitrate != RATE_QUANT) + e->prev_pitch_delay = e->pitch_delay; + + samples = (float *)frame->data[0]; + for (i = 0; i < 160; i++) + samples[i] /= 32768; + + *got_frame_ptr = 1; + + return avpkt->size; +} + +AVCodec ff_evrc_decoder = { + .name = "evrc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_EVRC, + .init = evrc_decode_init, + .decode = evrc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .priv_data_size = sizeof(EVRCContext), + .long_name = NULL_IF_CONFIG_SMALL("EVRC (Enhanced Variable Rate Codec)"), +}; diff --git a/ffmpeg/libavcodec/exr.c b/ffmpeg/libavcodec/exr.c new file mode 100644 index 0000000..af1bee0 --- /dev/null +++ b/ffmpeg/libavcodec/exr.c @@ -0,0 +1,813 @@ +/* + * OpenEXR (.exr) image decoder + * Copyright (c) 2009 Jimmy Christensen + * + * 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 + */ + +/** + * @file + * OpenEXR decoder + * @author Jimmy Christensen + * + * For more information on the OpenEXR format, visit: + * http://openexr.com/ + * + * exr_flt2uint() and exr_halflt2uint() is credited to Reimar Döffinger + */ + +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "mathops.h" +#include "thread.h" +#include "libavutil/imgutils.h" +#include "libavutil/avassert.h" + +enum ExrCompr { + EXR_RAW = 0, + EXR_RLE = 1, + EXR_ZIP1 = 2, + EXR_ZIP16 = 3, + EXR_PIZ = 4, + EXR_PXR24 = 5, + EXR_B44 = 6, + EXR_B44A = 7, +}; + +enum ExrPixelType { + EXR_UINT, + EXR_HALF, + EXR_FLOAT +}; + +typedef struct EXRChannel { + int xsub, ysub; + enum ExrPixelType pixel_type; +} EXRChannel; + +typedef struct EXRThreadData { + uint8_t *uncompressed_data; + int uncompressed_size; + + uint8_t *tmp; + int tmp_size; +} EXRThreadData; + +typedef struct EXRContext { + AVFrame *picture; + int compr; + enum ExrPixelType pixel_type; + int channel_offsets[4]; // 0 = red, 1 = green, 2 = blue and 3 = alpha + const AVPixFmtDescriptor *desc; + + uint32_t xmax, xmin; + uint32_t ymax, ymin; + uint32_t xdelta, ydelta; + + int ysize; + + uint64_t scan_line_size; + int scan_lines_per_block; + + const uint8_t *buf, *table; + int buf_size; + + EXRChannel *channels; + int nb_channels; + + EXRThreadData *thread_data; + int thread_data_size; +} EXRContext; + +/** + * Converts from 32-bit float as uint32_t to uint16_t + * + * @param v 32-bit float + * @return normalized 16-bit unsigned int + */ +static inline uint16_t exr_flt2uint(uint32_t v) +{ + unsigned int exp = v >> 23; + // "HACK": negative values result in exp< 0, so clipping them to 0 + // is also handled by this condition, avoids explicit check for sign bit. + if (exp<= 127 + 7 - 24) // we would shift out all bits anyway + return 0; + if (exp >= 127) + return 0xffff; + v &= 0x007fffff; + return (v + (1 << 23)) >> (127 + 7 - exp); +} + +/** + * Converts from 16-bit float as uint16_t to uint16_t + * + * @param v 16-bit float + * @return normalized 16-bit unsigned int + */ +static inline uint16_t exr_halflt2uint(uint16_t v) +{ + unsigned exp = 14 - (v >> 10); + if (exp >= 14) { + if (exp == 14) return (v >> 9) & 1; + else return (v & 0x8000) ? 0 : 0xffff; + } + v <<= 6; + return (v + (1 << 16)) >> (exp + 1); +} + +/** + * Gets the size of the header variable + * + * @param **buf the current pointer location in the header where + * the variable data starts + * @param *buf_end pointer location of the end of the buffer + * @return size of variable data + */ +static unsigned int get_header_variable_length(const uint8_t **buf, + const uint8_t *buf_end) +{ + unsigned int variable_buffer_data_size = bytestream_get_le32(buf); + if (variable_buffer_data_size >= buf_end - *buf) + return 0; + return variable_buffer_data_size; +} + +/** + * Checks if the variable name corresponds with it's data type + * + * @param *avctx the AVCodecContext + * @param **buf the current pointer location in the header where + * the variable name starts + * @param *buf_end pointer location of the end of the buffer + * @param *value_name name of the varible to check + * @param *value_type type of the varible to check + * @param minimum_length minimum length of the variable data + * @param variable_buffer_data_size variable length read from the header + * after it's checked + * @return negative if variable is invalid + */ +static int check_header_variable(AVCodecContext *avctx, + const uint8_t **buf, + const uint8_t *buf_end, + const char *value_name, + const char *value_type, + unsigned int minimum_length, + unsigned int *variable_buffer_data_size) +{ + if (buf_end - *buf >= minimum_length && !strcmp(*buf, value_name)) { + *buf += strlen(value_name)+1; + if (!strcmp(*buf, value_type)) { + *buf += strlen(value_type)+1; + *variable_buffer_data_size = get_header_variable_length(buf, buf_end); + if (!*variable_buffer_data_size) + av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); + return 1; + } + *buf -= strlen(value_name)+1; + av_log(avctx, AV_LOG_WARNING, "Unknown data type for header variable %s\n", value_name); + } + return -1; +} + +static void predictor(uint8_t *src, int size) +{ + uint8_t *t = src + 1; + uint8_t *stop = src + size; + + while (t < stop) { + int d = (int)t[-1] + (int)t[0] - 128; + t[0] = d; + ++t; + } +} + +static void reorder_pixels(uint8_t *src, uint8_t *dst, int size) +{ + const int8_t *t1 = src; + const int8_t *t2 = src + (size + 1) / 2; + int8_t *s = dst; + int8_t *stop = s + size; + + while (1) { + if (s < stop) + *(s++) = *(t1++); + else + break; + + if (s < stop) + *(s++) = *(t2++); + else + break; + } +} + +static int zip_uncompress(const uint8_t *src, int compressed_size, + int uncompressed_size, EXRThreadData *td) +{ + unsigned long dest_len = uncompressed_size; + + if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK || + dest_len != uncompressed_size) + return AVERROR(EINVAL); + + predictor(td->tmp, uncompressed_size); + reorder_pixels(td->tmp, td->uncompressed_data, uncompressed_size); + + return 0; +} + +static int rle_uncompress(const uint8_t *src, int compressed_size, + int uncompressed_size, EXRThreadData *td) +{ + int8_t *d = (int8_t *)td->tmp; + const int8_t *s = (const int8_t *)src; + int ssize = compressed_size; + int dsize = uncompressed_size; + int8_t *dend = d + dsize; + int count; + + while (ssize > 0) { + count = *s++; + + if (count < 0) { + count = -count; + + if ((dsize -= count ) < 0 || + (ssize -= count + 1) < 0) + return -1; + + while (count--) + *d++ = *s++; + } else { + count++; + + if ((dsize -= count) < 0 || + (ssize -= 2 ) < 0) + return -1; + + while (count--) + *d++ = *s; + + s++; + } + } + + if (dend != d) + return AVERROR_INVALIDDATA; + + predictor(td->tmp, uncompressed_size); + reorder_pixels(td->tmp, td->uncompressed_data, uncompressed_size); + + return 0; +} + +static int pxr24_uncompress(EXRContext *s, const uint8_t *src, + int compressed_size, int uncompressed_size, + EXRThreadData *td) +{ + unsigned long dest_len = uncompressed_size; + const uint8_t *in = td->tmp; + uint8_t *out; + int c, i, j; + + if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK || + dest_len != uncompressed_size) + return AVERROR(EINVAL); + + out = td->uncompressed_data; + for (i = 0; i < s->ysize; i++) { + for (c = 0; c < s->nb_channels; c++) { + EXRChannel *channel = &s->channels[c]; + const uint8_t *ptr[4]; + uint32_t pixel = 0; + + switch (channel->pixel_type) { + case EXR_FLOAT: + ptr[0] = in; + ptr[1] = ptr[0] + s->xdelta; + ptr[2] = ptr[1] + s->xdelta; + in = ptr[2] + s->xdelta; + + for (j = 0; j < s->xdelta; ++j) { + uint32_t diff = (*(ptr[0]++) << 24) | + (*(ptr[1]++) << 16) | + (*(ptr[2]++) << 8); + pixel += diff; + bytestream_put_le32(&out, pixel); + } + break; + case EXR_HALF: + ptr[0] = in; + ptr[1] = ptr[0] + s->xdelta; + in = ptr[1] + s->xdelta; + for (j = 0; j < s->xdelta; j++) { + uint32_t diff = (*(ptr[0]++) << 8) | *(ptr[1]++); + + pixel += diff; + bytestream_put_le16(&out, pixel); + } + break; + default: + av_assert1(0); + } + } + } + + return 0; +} + +static int decode_block(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + EXRContext *s = avctx->priv_data; + AVFrame *const p = s->picture; + EXRThreadData *td = &s->thread_data[threadnr]; + const uint8_t *channel_buffer[4] = { 0 }; + const uint8_t *buf = s->buf; + uint64_t line_offset, uncompressed_size; + uint32_t xdelta = s->xdelta; + uint16_t *ptr_x; + uint8_t *ptr; + int32_t data_size, line; + const uint8_t *src; + int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; + int bxmin = s->xmin * 2 * s->desc->nb_components; + int i, x, buf_size = s->buf_size; + int av_unused ret; + + line_offset = AV_RL64(s->table + jobnr * 8); + // Check if the buffer has the required bytes needed from the offset + if (line_offset > buf_size - 8) + return AVERROR_INVALIDDATA; + + src = buf + line_offset + 8; + line = AV_RL32(src - 8); + if (line < s->ymin || line > s->ymax) + return AVERROR_INVALIDDATA; + + data_size = AV_RL32(src - 4); + if (data_size <= 0 || data_size > buf_size) + return AVERROR_INVALIDDATA; + + s->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); + uncompressed_size = s->scan_line_size * s->ysize; + if ((s->compr == EXR_RAW && (data_size != uncompressed_size || + line_offset > buf_size - uncompressed_size)) || + (s->compr != EXR_RAW && (data_size > uncompressed_size || + line_offset > buf_size - data_size))) { + return AVERROR_INVALIDDATA; + } + + if (data_size < uncompressed_size) { + av_fast_padded_malloc(&td->uncompressed_data, &td->uncompressed_size, uncompressed_size); + av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size); + if (!td->uncompressed_data || !td->tmp) + return AVERROR(ENOMEM); + + switch (s->compr) { + case EXR_ZIP1: + case EXR_ZIP16: + ret = zip_uncompress(src, data_size, uncompressed_size, td); + break; + case EXR_PXR24: + ret = pxr24_uncompress(s, src, data_size, uncompressed_size, td); + break; + case EXR_RLE: + ret = rle_uncompress(src, data_size, uncompressed_size, td); + } + + src = td->uncompressed_data; + } + + channel_buffer[0] = src + xdelta * s->channel_offsets[0]; + channel_buffer[1] = src + xdelta * s->channel_offsets[1]; + channel_buffer[2] = src + xdelta * s->channel_offsets[2]; + if (s->channel_offsets[3] >= 0) + channel_buffer[3] = src + xdelta * s->channel_offsets[3]; + + ptr = p->data[0] + line * p->linesize[0]; + for (i = 0; i < s->scan_lines_per_block && line + i <= s->ymax; i++, ptr += p->linesize[0]) { + const uint8_t *r, *g, *b, *a; + + r = channel_buffer[0]; + g = channel_buffer[1]; + b = channel_buffer[2]; + if (channel_buffer[3]) + a = channel_buffer[3]; + + ptr_x = (uint16_t *)ptr; + + // Zero out the start if xmin is not 0 + memset(ptr_x, 0, bxmin); + ptr_x += s->xmin * s->desc->nb_components; + if (s->pixel_type == EXR_FLOAT) { + // 32-bit + for (x = 0; x < xdelta; x++) { + *ptr_x++ = exr_flt2uint(bytestream_get_le32(&r)); + *ptr_x++ = exr_flt2uint(bytestream_get_le32(&g)); + *ptr_x++ = exr_flt2uint(bytestream_get_le32(&b)); + if (channel_buffer[3]) + *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a)); + } + } else { + // 16-bit + for (x = 0; x < xdelta; x++) { + *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&r)); + *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&g)); + *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&b)); + if (channel_buffer[3]) + *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a)); + } + } + + // Zero out the end if xmax+1 is not w + memset(ptr_x, 0, axmax); + + channel_buffer[0] += s->scan_line_size; + channel_buffer[1] += s->scan_line_size; + channel_buffer[2] += s->scan_line_size; + if (channel_buffer[3]) + channel_buffer[3] += s->scan_line_size; + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, + int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + unsigned int buf_size = avpkt->size; + const uint8_t *buf_end = buf + buf_size; + + EXRContext *const s = avctx->priv_data; + ThreadFrame frame = { .f = data }; + AVFrame *picture = data; + uint8_t *ptr; + + int i, y, magic_number, version, flags, ret; + int w = 0; + int h = 0; + + int out_line_size; + int scan_line_blocks; + + unsigned int current_channel_offset = 0; + + s->xmin = ~0; + s->xmax = ~0; + s->ymin = ~0; + s->ymax = ~0; + s->xdelta = ~0; + s->ydelta = ~0; + s->channel_offsets[0] = -1; + s->channel_offsets[1] = -1; + s->channel_offsets[2] = -1; + s->channel_offsets[3] = -1; + s->pixel_type = -1; + s->nb_channels = 0; + s->compr = -1; + s->buf = buf; + s->buf_size = buf_size; + + if (buf_size < 10) { + av_log(avctx, AV_LOG_ERROR, "Too short header to parse\n"); + return AVERROR_INVALIDDATA; + } + + magic_number = bytestream_get_le32(&buf); + if (magic_number != 20000630) { // As per documentation of OpenEXR it's supposed to be int 20000630 little-endian + av_log(avctx, AV_LOG_ERROR, "Wrong magic number %d\n", magic_number); + return AVERROR_INVALIDDATA; + } + + version = bytestream_get_byte(&buf); + if (version != 2) { + av_log(avctx, AV_LOG_ERROR, "Unsupported version %d\n", version); + return AVERROR_PATCHWELCOME; + } + + flags = bytestream_get_le24(&buf); + if (flags & 0x2) { + av_log(avctx, AV_LOG_ERROR, "Tile based images are not supported\n"); + return AVERROR_PATCHWELCOME; + } + + // Parse the header + while (buf < buf_end && buf[0]) { + unsigned int variable_buffer_data_size; + // Process the channel list + if (check_header_variable(avctx, &buf, buf_end, "channels", "chlist", 38, &variable_buffer_data_size) >= 0) { + const uint8_t *channel_list_end; + if (!variable_buffer_data_size) + return AVERROR_INVALIDDATA; + + channel_list_end = buf + variable_buffer_data_size; + while (channel_list_end - buf >= 19) { + EXRChannel *channel; + int current_pixel_type = -1; + int channel_index = -1; + int xsub, ysub; + + if (!strcmp(buf, "R")) + channel_index = 0; + else if (!strcmp(buf, "G")) + channel_index = 1; + else if (!strcmp(buf, "B")) + channel_index = 2; + else if (!strcmp(buf, "A")) + channel_index = 3; + else + av_log(avctx, AV_LOG_WARNING, "Unsupported channel %.256s\n", buf); + + while (bytestream_get_byte(&buf) && buf < channel_list_end) + continue; /* skip */ + + if (channel_list_end - * &buf < 4) { + av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); + return AVERROR_INVALIDDATA; + } + + current_pixel_type = bytestream_get_le32(&buf); + if (current_pixel_type > 2) { + av_log(avctx, AV_LOG_ERROR, "Unknown pixel type\n"); + return AVERROR_INVALIDDATA; + } + + buf += 4; + xsub = bytestream_get_le32(&buf); + ysub = bytestream_get_le32(&buf); + if (xsub != 1 || ysub != 1) { + av_log(avctx, AV_LOG_ERROR, "Unsupported subsampling %dx%d\n", xsub, ysub); + return AVERROR_PATCHWELCOME; + } + + if (channel_index >= 0) { + if (s->pixel_type != -1 && s->pixel_type != current_pixel_type) { + av_log(avctx, AV_LOG_ERROR, "RGB channels not of the same depth\n"); + return AVERROR_INVALIDDATA; + } + s->pixel_type = current_pixel_type; + s->channel_offsets[channel_index] = current_channel_offset; + } + + s->channels = av_realloc_f(s->channels, ++s->nb_channels, sizeof(EXRChannel)); + if (!s->channels) + return AVERROR(ENOMEM); + channel = &s->channels[s->nb_channels - 1]; + channel->pixel_type = current_pixel_type; + channel->xsub = xsub; + channel->ysub = ysub; + + current_channel_offset += 1 << current_pixel_type; + } + + /* Check if all channels are set with an offset or if the channels + * are causing an overflow */ + + if (FFMIN3(s->channel_offsets[0], + s->channel_offsets[1], + s->channel_offsets[2]) < 0) { + if (s->channel_offsets[0] < 0) + av_log(avctx, AV_LOG_ERROR, "Missing red channel\n"); + if (s->channel_offsets[1] < 0) + av_log(avctx, AV_LOG_ERROR, "Missing green channel\n"); + if (s->channel_offsets[2] < 0) + av_log(avctx, AV_LOG_ERROR, "Missing blue channel\n"); + return AVERROR_INVALIDDATA; + } + + buf = channel_list_end; + continue; + } else if (check_header_variable(avctx, &buf, buf_end, "dataWindow", "box2i", 31, &variable_buffer_data_size) >= 0) { + if (!variable_buffer_data_size) + return AVERROR_INVALIDDATA; + + s->xmin = AV_RL32(buf); + s->ymin = AV_RL32(buf + 4); + s->xmax = AV_RL32(buf + 8); + s->ymax = AV_RL32(buf + 12); + s->xdelta = (s->xmax - s->xmin) + 1; + s->ydelta = (s->ymax - s->ymin) + 1; + + buf += variable_buffer_data_size; + continue; + } else if (check_header_variable(avctx, &buf, buf_end, "displayWindow", "box2i", 34, &variable_buffer_data_size) >= 0) { + if (!variable_buffer_data_size) + return AVERROR_INVALIDDATA; + + w = AV_RL32(buf + 8) + 1; + h = AV_RL32(buf + 12) + 1; + + buf += variable_buffer_data_size; + continue; + } else if (check_header_variable(avctx, &buf, buf_end, "lineOrder", "lineOrder", 25, &variable_buffer_data_size) >= 0) { + if (!variable_buffer_data_size) + return AVERROR_INVALIDDATA; + + av_log(avctx, AV_LOG_DEBUG, "line order : %d\n", *buf); + if (*buf > 2) { + av_log(avctx, AV_LOG_ERROR, "Unknown line order\n"); + return AVERROR_INVALIDDATA; + } + + buf += variable_buffer_data_size; + continue; + } else if (check_header_variable(avctx, &buf, buf_end, "pixelAspectRatio", "float", 31, &variable_buffer_data_size) >= 0) { + if (!variable_buffer_data_size) + return AVERROR_INVALIDDATA; + + avctx->sample_aspect_ratio = av_d2q(av_int2float(AV_RL32(buf)), 255); + + buf += variable_buffer_data_size; + continue; + } else if (check_header_variable(avctx, &buf, buf_end, "compression", "compression", 29, &variable_buffer_data_size) >= 0) { + if (!variable_buffer_data_size) + return AVERROR_INVALIDDATA; + + if (s->compr == -1) + s->compr = *buf; + else + av_log(avctx, AV_LOG_WARNING, "Found more than one compression attribute\n"); + + buf += variable_buffer_data_size; + continue; + } + + // Check if there is enough bytes for a header + if (buf_end - buf <= 9) { + av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); + return AVERROR_INVALIDDATA; + } + + // Process unknown variables + for (i = 0; i < 2; i++) { + // Skip variable name/type + while (++buf < buf_end) + if (buf[0] == 0x0) + break; + } + buf++; + // Skip variable length + if (buf_end - buf >= 5) { + variable_buffer_data_size = get_header_variable_length(&buf, buf_end); + if (!variable_buffer_data_size) { + av_log(avctx, AV_LOG_ERROR, "Incomplete header\n"); + return AVERROR_INVALIDDATA; + } + buf += variable_buffer_data_size; + } + } + + if (s->compr == -1) { + av_log(avctx, AV_LOG_ERROR, "Missing compression attribute\n"); + return AVERROR_INVALIDDATA; + } + + if (buf >= buf_end) { + av_log(avctx, AV_LOG_ERROR, "Incomplete frame\n"); + return AVERROR_INVALIDDATA; + } + buf++; + + switch (s->pixel_type) { + case EXR_FLOAT: + case EXR_HALF: + if (s->channel_offsets[3] >= 0) + avctx->pix_fmt = AV_PIX_FMT_RGBA64; + else + avctx->pix_fmt = AV_PIX_FMT_RGB48; + break; + case EXR_UINT: + avpriv_request_sample(avctx, "32-bit unsigned int"); + return AVERROR_PATCHWELCOME; + default: + av_log(avctx, AV_LOG_ERROR, "Missing channel list\n"); + return AVERROR_INVALIDDATA; + } + + switch (s->compr) { + case EXR_RAW: + case EXR_RLE: + case EXR_ZIP1: + s->scan_lines_per_block = 1; + break; + case EXR_PXR24: + case EXR_ZIP16: + s->scan_lines_per_block = 16; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Compression type %d is not supported\n", s->compr); + return AVERROR_PATCHWELCOME; + } + + if (av_image_check_size(w, h, 0, avctx)) + return AVERROR_INVALIDDATA; + + // Verify the xmin, xmax, ymin, ymax and xdelta before setting the actual image size + if (s->xmin > s->xmax || + s->ymin > s->ymax || + s->xdelta != s->xmax - s->xmin + 1 || + s->xmax >= w || s->ymax >= h) { + av_log(avctx, AV_LOG_ERROR, "Wrong sizing or missing size information\n"); + return AVERROR_INVALIDDATA; + } + + if (w != avctx->width || h != avctx->height) { + avcodec_set_dimensions(avctx, w, h); + } + + s->desc = av_pix_fmt_desc_get(avctx->pix_fmt); + out_line_size = avctx->width * 2 * s->desc->nb_components; + s->scan_line_size = s->xdelta * current_channel_offset; + scan_line_blocks = (s->ydelta + s->scan_lines_per_block - 1) / s->scan_lines_per_block; + + if (s->compr != EXR_RAW) { + size_t thread_data_size, prev_size; + EXRThreadData *m; + + prev_size = s->thread_data_size; + if (av_size_mult(avctx->thread_count, sizeof(EXRThreadData), &thread_data_size)) + return AVERROR(EINVAL); + + m = av_fast_realloc(s->thread_data, &s->thread_data_size, thread_data_size); + if (!m) + return AVERROR(ENOMEM); + s->thread_data = m; + memset(s->thread_data + prev_size, 0, s->thread_data_size - prev_size); + } + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + if (buf_end - buf < scan_line_blocks * 8) + return AVERROR_INVALIDDATA; + s->table = buf; + ptr = picture->data[0]; + + // Zero out the start if ymin is not 0 + for (y = 0; y < s->ymin; y++) { + memset(ptr, 0, out_line_size); + ptr += picture->linesize[0]; + } + + s->picture = picture; + avctx->execute2(avctx, decode_block, s->thread_data, NULL, scan_line_blocks); + + // Zero out the end if ymax+1 is not h + for (y = s->ymax + 1; y < avctx->height; y++) { + memset(ptr, 0, out_line_size); + ptr += picture->linesize[0]; + } + + *got_frame = 1; + + return buf_size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + EXRContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->thread_data_size / sizeof(EXRThreadData); i++) { + EXRThreadData *td = &s->thread_data[i]; + av_free(td->uncompressed_data); + av_free(td->tmp); + } + + av_freep(&s->thread_data); + s->thread_data_size = 0; + av_freep(&s->channels); + + return 0; +} + +AVCodec ff_exr_decoder = { + .name = "exr", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_EXR, + .priv_data_size = sizeof(EXRContext), + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), +}; diff --git a/ffmpeg/libavcodec/faandct.c b/ffmpeg/libavcodec/faandct.c new file mode 100644 index 0000000..b1d7a14 --- /dev/null +++ b/ffmpeg/libavcodec/faandct.c @@ -0,0 +1,228 @@ +/* + * Floating point AAN DCT + * this implementation is based upon the IJG integer AAN DCT (see jfdctfst.c) + * + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2003 Roman Shaposhnik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * @file + * @brief + * Floating point AAN DCT + * @author Michael Niedermayer + */ + +#include "faandct.h" +#include "libavutil/internal.h" +#include "libavutil/libm.h" + +#define FLOAT float + +//numbers generated by simple c code (not as accurate as they could be) +/* +for(i=0; i<8; i++){ + printf("#define B%d %1.20llf\n", i, (long double)1.0/(cosl(i*acosl(-1.0)/(long double)16.0)*sqrtl(2))); +} +*/ +#define B0 1.00000000000000000000 +#define B1 0.72095982200694791383 // (cos(pi*1/16)sqrt(2))^-1 +#define B2 0.76536686473017954350 // (cos(pi*2/16)sqrt(2))^-1 +#define B3 0.85043009476725644878 // (cos(pi*3/16)sqrt(2))^-1 +#define B4 1.00000000000000000000 // (cos(pi*4/16)sqrt(2))^-1 +#define B5 1.27275858057283393842 // (cos(pi*5/16)sqrt(2))^-1 +#define B6 1.84775906502257351242 // (cos(pi*6/16)sqrt(2))^-1 +#define B7 3.62450978541155137218 // (cos(pi*7/16)sqrt(2))^-1 + + +#define A1 0.70710678118654752438 // cos(pi*4/16) +#define A2 0.54119610014619698435 // cos(pi*6/16)sqrt(2) +#define A5 0.38268343236508977170 // cos(pi*6/16) +#define A4 1.30656296487637652774 // cos(pi*2/16)sqrt(2) + +static const FLOAT postscale[64]={ +B0*B0, B0*B1, B0*B2, B0*B3, B0*B4, B0*B5, B0*B6, B0*B7, +B1*B0, B1*B1, B1*B2, B1*B3, B1*B4, B1*B5, B1*B6, B1*B7, +B2*B0, B2*B1, B2*B2, B2*B3, B2*B4, B2*B5, B2*B6, B2*B7, +B3*B0, B3*B1, B3*B2, B3*B3, B3*B4, B3*B5, B3*B6, B3*B7, +B4*B0, B4*B1, B4*B2, B4*B3, B4*B4, B4*B5, B4*B6, B4*B7, +B5*B0, B5*B1, B5*B2, B5*B3, B5*B4, B5*B5, B5*B6, B5*B7, +B6*B0, B6*B1, B6*B2, B6*B3, B6*B4, B6*B5, B6*B6, B6*B7, +B7*B0, B7*B1, B7*B2, B7*B3, B7*B4, B7*B5, B7*B6, B7*B7, +}; + +static av_always_inline void row_fdct(FLOAT temp[64], int16_t *data) +{ + FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FLOAT tmp10, tmp11, tmp12, tmp13; + FLOAT z2, z4, z11, z13; + FLOAT av_unused z5; + int i; + + for (i=0; i<8*8; i+=8) { + tmp0= data[0 + i] + data[7 + i]; + tmp7= data[0 + i] - data[7 + i]; + tmp1= data[1 + i] + data[6 + i]; + tmp6= data[1 + i] - data[6 + i]; + tmp2= data[2 + i] + data[5 + i]; + tmp5= data[2 + i] - data[5 + i]; + tmp3= data[3 + i] + data[4 + i]; + tmp4= data[3 + i] - data[4 + i]; + + tmp10= tmp0 + tmp3; + tmp13= tmp0 - tmp3; + tmp11= tmp1 + tmp2; + tmp12= tmp1 - tmp2; + + temp[0 + i]= tmp10 + tmp11; + temp[4 + i]= tmp10 - tmp11; + + tmp12 += tmp13; + tmp12 *= A1; + temp[2 + i]= tmp13 + tmp12; + temp[6 + i]= tmp13 - tmp12; + + tmp4 += tmp5; + tmp5 += tmp6; + tmp6 += tmp7; + +#if 0 + z5= (tmp4 - tmp6) * A5; + z2= tmp4*A2 + z5; + z4= tmp6*A4 + z5; +#else + z2= tmp4*(A2+A5) - tmp6*A5; + z4= tmp6*(A4-A5) + tmp4*A5; +#endif + tmp5*=A1; + + z11= tmp7 + tmp5; + z13= tmp7 - tmp5; + + temp[5 + i]= z13 + z2; + temp[3 + i]= z13 - z2; + temp[1 + i]= z11 + z4; + temp[7 + i]= z11 - z4; + } +} + +void ff_faandct(int16_t *data) +{ + FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FLOAT tmp10, tmp11, tmp12, tmp13; + FLOAT z2, z4, z11, z13; + FLOAT av_unused z5; + FLOAT temp[64]; + int i; + + emms_c(); + + row_fdct(temp, data); + + for (i=0; i<8; i++) { + tmp0= temp[8*0 + i] + temp[8*7 + i]; + tmp7= temp[8*0 + i] - temp[8*7 + i]; + tmp1= temp[8*1 + i] + temp[8*6 + i]; + tmp6= temp[8*1 + i] - temp[8*6 + i]; + tmp2= temp[8*2 + i] + temp[8*5 + i]; + tmp5= temp[8*2 + i] - temp[8*5 + i]; + tmp3= temp[8*3 + i] + temp[8*4 + i]; + tmp4= temp[8*3 + i] - temp[8*4 + i]; + + tmp10= tmp0 + tmp3; + tmp13= tmp0 - tmp3; + tmp11= tmp1 + tmp2; + tmp12= tmp1 - tmp2; + + data[8*0 + i]= lrintf(postscale[8*0 + i] * (tmp10 + tmp11)); + data[8*4 + i]= lrintf(postscale[8*4 + i] * (tmp10 - tmp11)); + + tmp12 += tmp13; + tmp12 *= A1; + data[8*2 + i]= lrintf(postscale[8*2 + i] * (tmp13 + tmp12)); + data[8*6 + i]= lrintf(postscale[8*6 + i] * (tmp13 - tmp12)); + + tmp4 += tmp5; + tmp5 += tmp6; + tmp6 += tmp7; + +#if 0 + z5= (tmp4 - tmp6) * A5; + z2= tmp4*A2 + z5; + z4= tmp6*A4 + z5; +#else + z2= tmp4*(A2+A5) - tmp6*A5; + z4= tmp6*(A4-A5) + tmp4*A5; +#endif + tmp5*=A1; + + z11= tmp7 + tmp5; + z13= tmp7 - tmp5; + + data[8*5 + i]= lrintf(postscale[8*5 + i] * (z13 + z2)); + data[8*3 + i]= lrintf(postscale[8*3 + i] * (z13 - z2)); + data[8*1 + i]= lrintf(postscale[8*1 + i] * (z11 + z4)); + data[8*7 + i]= lrintf(postscale[8*7 + i] * (z11 - z4)); + } +} + +void ff_faandct248(int16_t *data) +{ + FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FLOAT tmp10, tmp11, tmp12, tmp13; + FLOAT temp[64]; + int i; + + emms_c(); + + row_fdct(temp, data); + + for (i=0; i<8; i++) { + tmp0 = temp[8*0 + i] + temp[8*1 + i]; + tmp1 = temp[8*2 + i] + temp[8*3 + i]; + tmp2 = temp[8*4 + i] + temp[8*5 + i]; + tmp3 = temp[8*6 + i] + temp[8*7 + i]; + tmp4 = temp[8*0 + i] - temp[8*1 + i]; + tmp5 = temp[8*2 + i] - temp[8*3 + i]; + tmp6 = temp[8*4 + i] - temp[8*5 + i]; + tmp7 = temp[8*6 + i] - temp[8*7 + i]; + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + tmp13 = tmp0 - tmp3; + + data[8*0 + i] = lrintf(postscale[8*0 + i] * (tmp10 + tmp11)); + data[8*4 + i] = lrintf(postscale[8*4 + i] * (tmp10 - tmp11)); + + tmp12 += tmp13; + tmp12 *= A1; + data[8*2 + i] = lrintf(postscale[8*2 + i] * (tmp13 + tmp12)); + data[8*6 + i] = lrintf(postscale[8*6 + i] * (tmp13 - tmp12)); + + tmp10 = tmp4 + tmp7; + tmp11 = tmp5 + tmp6; + tmp12 = tmp5 - tmp6; + tmp13 = tmp4 - tmp7; + + data[8*1 + i] = lrintf(postscale[8*0 + i] * (tmp10 + tmp11)); + data[8*5 + i] = lrintf(postscale[8*4 + i] * (tmp10 - tmp11)); + + tmp12 += tmp13; + tmp12 *= A1; + data[8*3 + i] = lrintf(postscale[8*2 + i] * (tmp13 + tmp12)); + data[8*7 + i] = lrintf(postscale[8*6 + i] * (tmp13 - tmp12)); + } +} diff --git a/ffmpeg/libavcodec/faandct.h b/ffmpeg/libavcodec/faandct.h new file mode 100644 index 0000000..c5ef96d --- /dev/null +++ b/ffmpeg/libavcodec/faandct.h @@ -0,0 +1,37 @@ +/* + * Floating point AAN DCT + * Copyright (c) 2003 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 + */ + +/** + * @file + * @brief + * Floating point AAN DCT + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_FAANDCT_H +#define AVCODEC_FAANDCT_H + +#include + +void ff_faandct(int16_t *data); +void ff_faandct248(int16_t *data); + +#endif /* AVCODEC_FAANDCT_H */ diff --git a/ffmpeg/libavcodec/faanidct.c b/ffmpeg/libavcodec/faanidct.c new file mode 100644 index 0000000..5f34fa5 --- /dev/null +++ b/ffmpeg/libavcodec/faanidct.c @@ -0,0 +1,169 @@ +/* + * Floating point AAN IDCT + * Copyright (c) 2008 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 "faanidct.h" +#include "libavutil/common.h" + +/* To allow switching to double. */ +#define FLOAT float + +#define B0 1.0000000000000000000000 +#define B1 1.3870398453221474618216 // cos(pi*1/16)sqrt(2) +#define B2 1.3065629648763765278566 // cos(pi*2/16)sqrt(2) +#define B3 1.1758756024193587169745 // cos(pi*3/16)sqrt(2) +#define B4 1.0000000000000000000000 // cos(pi*4/16)sqrt(2) +#define B5 0.7856949583871021812779 // cos(pi*5/16)sqrt(2) +#define B6 0.5411961001461969843997 // cos(pi*6/16)sqrt(2) +#define B7 0.2758993792829430123360 // cos(pi*7/16)sqrt(2) + +#define A4 0.70710678118654752438 // cos(pi*4/16) +#define A2 0.92387953251128675613 // cos(pi*2/16) + +static const FLOAT prescale[64]={ +B0*B0/8, B0*B1/8, B0*B2/8, B0*B3/8, B0*B4/8, B0*B5/8, B0*B6/8, B0*B7/8, +B1*B0/8, B1*B1/8, B1*B2/8, B1*B3/8, B1*B4/8, B1*B5/8, B1*B6/8, B1*B7/8, +B2*B0/8, B2*B1/8, B2*B2/8, B2*B3/8, B2*B4/8, B2*B5/8, B2*B6/8, B2*B7/8, +B3*B0/8, B3*B1/8, B3*B2/8, B3*B3/8, B3*B4/8, B3*B5/8, B3*B6/8, B3*B7/8, +B4*B0/8, B4*B1/8, B4*B2/8, B4*B3/8, B4*B4/8, B4*B5/8, B4*B6/8, B4*B7/8, +B5*B0/8, B5*B1/8, B5*B2/8, B5*B3/8, B5*B4/8, B5*B5/8, B5*B6/8, B5*B7/8, +B6*B0/8, B6*B1/8, B6*B2/8, B6*B3/8, B6*B4/8, B6*B5/8, B6*B6/8, B6*B7/8, +B7*B0/8, B7*B1/8, B7*B2/8, B7*B3/8, B7*B4/8, B7*B5/8, B7*B6/8, B7*B7/8, +}; + +static inline void p8idct(int16_t data[64], FLOAT temp[64], uint8_t *dest, int stride, int x, int y, int type){ + int i; + FLOAT av_unused tmp0; + FLOAT s04, d04, s17, d17, s26, d26, s53, d53; + FLOAT os07, os16, os25, os34; + FLOAT od07, od16, od25, od34; + + for(i=0; i + * + * 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 + */ + +#ifndef AVCODEC_FAANIDCT_H +#define AVCODEC_FAANIDCT_H + +#include + +void ff_faanidct(int16_t block[64]); +void ff_faanidct_add(uint8_t *dest, int line_size, int16_t block[64]); +void ff_faanidct_put(uint8_t *dest, int line_size, int16_t block[64]); + +#endif /* AVCODEC_FAANIDCT_H */ diff --git a/ffmpeg/libavcodec/faxcompr.c b/ffmpeg/libavcodec/faxcompr.c new file mode 100644 index 0000000..86be977 --- /dev/null +++ b/ffmpeg/libavcodec/faxcompr.c @@ -0,0 +1,333 @@ +/* + * CCITT Fax Group 3 and 4 decompression + * Copyright (c) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * CCITT Fax Group 3 and 4 decompression + * @author Konstantin Shishkov + */ +#include "avcodec.h" +#include "get_bits.h" +#include "put_bits.h" +#include "faxcompr.h" + +#define CCITT_SYMS 104 + +static const uint16_t ccitt_syms[CCITT_SYMS] = { + 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, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, + 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, + 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560 +}; + +static const uint8_t ccitt_codes_bits[2][CCITT_SYMS] = +{ + { + 0x35, 0x07, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, 0x13, 0x14, 0x07, 0x08, 0x08, + 0x03, 0x34, 0x35, 0x2A, 0x2B, 0x27, 0x0C, 0x08, 0x17, 0x03, 0x04, 0x28, 0x2B, + 0x13, 0x24, 0x18, 0x02, 0x03, 0x1A, 0x1B, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x04, 0x05, 0x0A, 0x0B, 0x52, 0x53, 0x54, + 0x55, 0x24, 0x25, 0x58, 0x59, 0x5A, 0x5B, 0x4A, 0x4B, 0x32, 0x33, 0x34, 0x1B, + 0x12, 0x17, 0x37, 0x36, 0x37, 0x64, 0x65, 0x68, 0x67, 0xCC, 0xCD, 0xD2, 0xD3, + 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0x98, 0x99, 0x9A, 0x18, 0x9B, + 0x08, 0x0C, 0x0D, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F + }, + { + 0x37, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0x05, 0x04, 0x04, 0x05, 0x07, + 0x04, 0x07, 0x18, 0x17, 0x18, 0x08, 0x67, 0x68, 0x6C, 0x37, 0x28, 0x17, 0x18, + 0xCA, 0xCB, 0xCC, 0xCD, 0x68, 0x69, 0x6A, 0x6B, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0x6C, 0x6D, 0xDA, 0xDB, 0x54, 0x55, 0x56, 0x57, 0x64, 0x65, 0x52, 0x53, + 0x24, 0x37, 0x38, 0x27, 0x28, 0x58, 0x59, 0x2B, 0x2C, 0x5A, 0x66, 0x67, 0x0F, + 0xC8, 0xC9, 0x5B, 0x33, 0x34, 0x35, 0x6C, 0x6D, 0x4A, 0x4B, 0x4C, 0x4D, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x52, 0x53, 0x54, 0x55, 0x5A, 0x5B, 0x64, 0x65, + 0x08, 0x0C, 0x0D, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1C, 0x1D, 0x1E, 0x1F + } +}; + +static const uint8_t ccitt_codes_lens[2][CCITT_SYMS] = +{ + { + 8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 9, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12 + }, + { + 10, 3, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 11, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12 + } +}; + +static const uint8_t ccitt_group3_2d_bits[11] = { + 1, 1, 2, 2, 2, 1, 3, 3, 3, 1, 1 +}; + +static const uint8_t ccitt_group3_2d_lens[11] = { + 4, 3, 7, 6, 3, 1, 3, 6, 7, 7, 9 +}; + +static VLC ccitt_vlc[2], ccitt_group3_2d_vlc; + +av_cold void ff_ccitt_unpack_init(void) +{ + static VLC_TYPE code_table1[528][2]; + static VLC_TYPE code_table2[648][2]; + int i; + static int initialized = 0; + + if(initialized) + return; + ccitt_vlc[0].table = code_table1; + ccitt_vlc[0].table_allocated = 528; + ccitt_vlc[1].table = code_table2; + ccitt_vlc[1].table_allocated = 648; + for(i = 0; i < 2; i++){ + ff_init_vlc_sparse(&ccitt_vlc[i], 9, CCITT_SYMS, + ccitt_codes_lens[i], 1, 1, + ccitt_codes_bits[i], 1, 1, + ccitt_syms, 2, 2, + INIT_VLC_USE_NEW_STATIC); + } + INIT_VLC_STATIC(&ccitt_group3_2d_vlc, 9, 11, + ccitt_group3_2d_lens, 1, 1, + ccitt_group3_2d_bits, 1, 1, 512); + initialized = 1; +} + + +static int decode_group3_1d_line(AVCodecContext *avctx, GetBitContext *gb, + unsigned int pix_left, int *runs, const int *runend) +{ + int mode = 0; + unsigned int run=0; + unsigned int t; + for(;;){ + t = get_vlc2(gb, ccitt_vlc[mode].table, 9, 2); + run += t; + if(t < 64){ + *runs++ = run; + if(runs >= runend){ + av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); + return -1; + } + if(pix_left <= run){ + if(pix_left == run) + break; + av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return -1; + } + pix_left -= run; + run = 0; + mode = !mode; + }else if((int)t == -1){ + av_log(avctx, AV_LOG_ERROR, "Incorrect code\n"); + return -1; + } + } + *runs++ = 0; + return 0; +} + +static int decode_group3_2d_line(AVCodecContext *avctx, GetBitContext *gb, + unsigned int width, int *runs, const int *runend, const int *ref) +{ + int mode = 0, saved_run = 0, t; + int run_off = *ref++; + unsigned int offs=0, run= 0; + + while(offs < width){ + int cmode = get_vlc2(gb, ccitt_group3_2d_vlc.table, 9, 1); + if(cmode == -1){ + av_log(avctx, AV_LOG_ERROR, "Incorrect mode VLC\n"); + return -1; + } + if(!cmode){//pass mode + if(run_off < width) + run_off += *ref++; + run = run_off - offs; + offs= run_off; + if(run_off < width) + run_off += *ref++; + if(offs > width){ + av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return -1; + } + saved_run += run; + }else if(cmode == 1){//horizontal mode + int k; + for(k = 0; k < 2; k++){ + run = 0; + for(;;){ + t = get_vlc2(gb, ccitt_vlc[mode].table, 9, 2); + if(t == -1){ + av_log(avctx, AV_LOG_ERROR, "Incorrect code\n"); + return -1; + } + run += t; + if(t < 64) + break; + } + *runs++ = run + saved_run; + if(runs >= runend){ + av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); + return -1; + } + saved_run = 0; + offs += run; + if(offs > width || run > width){ + av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return -1; + } + mode = !mode; + } + }else if(cmode == 9 || cmode == 10){ + av_log(avctx, AV_LOG_ERROR, "Special modes are not supported (yet)\n"); + return -1; + }else{//vertical mode + run = run_off - offs + (cmode - 5); + run_off -= *--ref; + offs += run; + if(offs > width || run > width){ + av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + return -1; + } + *runs++ = run + saved_run; + if(runs >= runend){ + av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); + return -1; + } + saved_run = 0; + mode = !mode; + } + //sync line pointers + while(offs < width && run_off <= offs){ + run_off += *ref++; + run_off += *ref++; + } + } + *runs++ = saved_run; + if (saved_run) { + if(runs >= runend){ + av_log(avctx, AV_LOG_ERROR, "Run overrun\n"); + return -1; + } + *runs++ = 0; + } + return 0; +} + +static void put_line(uint8_t *dst, int size, int width, const int *runs) +{ + PutBitContext pb; + int run, mode = ~0, pix_left = width, run_idx = 0; + + init_put_bits(&pb, dst, size*8); + while(pix_left > 0){ + run = runs[run_idx++]; + mode = ~mode; + pix_left -= run; + for(; run > 16; run -= 16) + put_sbits(&pb, 16, mode); + if(run) + put_sbits(&pb, run, mode); + } + flush_put_bits(&pb); +} + +static int find_group3_syncmarker(GetBitContext *gb, int srcsize) +{ + unsigned int state = -1; + srcsize -= get_bits_count(gb); + while(srcsize-- > 0){ + state+= state + get_bits1(gb); + if((state & 0xFFF) == 1) + return 0; + } + return -1; +} + +int ff_ccitt_unpack(AVCodecContext *avctx, + const uint8_t *src, int srcsize, + uint8_t *dst, int height, int stride, + enum TiffCompr compr, int opts) +{ + int j; + GetBitContext gb; + int *runs, *ref = NULL, *runend; + int ret; + int runsize= avctx->width + 2; + int err = 0; + int has_eol; + + runs = av_malloc(runsize * sizeof(runs[0])); + ref = av_malloc(runsize * sizeof(ref[0])); + if (!runs || ! ref) { + err = AVERROR(ENOMEM); + goto fail; + } + ref[0] = avctx->width; + ref[1] = 0; + ref[2] = 0; + init_get_bits(&gb, src, srcsize*8); + has_eol = show_bits(&gb, 12) == 1 || show_bits(&gb, 16) == 1; + + for(j = 0; j < height; j++){ + runend = runs + runsize; + if(compr == TIFF_G4){ + ret = decode_group3_2d_line(avctx, &gb, avctx->width, runs, runend, ref); + if(ret < 0){ + err = -1; + goto fail; + } + }else{ + int g3d1 = (compr == TIFF_G3) && !(opts & 1); + if(compr!=TIFF_CCITT_RLE && has_eol && find_group3_syncmarker(&gb, srcsize*8) < 0) + break; + if(compr==TIFF_CCITT_RLE || g3d1 || get_bits1(&gb)) + ret = decode_group3_1d_line(avctx, &gb, avctx->width, runs, runend); + else + ret = decode_group3_2d_line(avctx, &gb, avctx->width, runs, runend, ref); + if(compr==TIFF_CCITT_RLE) + align_get_bits(&gb); + } + if(ret < 0){ + put_line(dst, stride, avctx->width, ref); + }else{ + put_line(dst, stride, avctx->width, runs); + FFSWAP(int*, runs, ref); + } + dst += stride; + } +fail: + av_free(runs); + av_free(ref); + return err; +} diff --git a/ffmpeg/libavcodec/faxcompr.h b/ffmpeg/libavcodec/faxcompr.h new file mode 100644 index 0000000..53d1168 --- /dev/null +++ b/ffmpeg/libavcodec/faxcompr.h @@ -0,0 +1,46 @@ +/* + * CCITT Fax Group 3 and 4 decompression + * Copyright (c) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * CCITT Fax Group 3 and 4 decompression + * @author Konstantin Shishkov + */ +#ifndef AVCODEC_FAXCOMPR_H +#define AVCODEC_FAXCOMPR_H + +#include "avcodec.h" +#include "tiff.h" + +/** + * initialize upacker code + */ +void ff_ccitt_unpack_init(void); + +/** + * unpack data compressed with CCITT Group 3 1/2-D or Group 4 method + */ +int ff_ccitt_unpack(AVCodecContext *avctx, + const uint8_t *src, int srcsize, + uint8_t *dst, int height, int stride, + enum TiffCompr compr, int opts); + +#endif /* AVCODEC_FAXCOMPR_H */ diff --git a/ffmpeg/libavcodec/fft-fixed-test.c b/ffmpeg/libavcodec/fft-fixed-test.c new file mode 100644 index 0000000..a1a6160 --- /dev/null +++ b/ffmpeg/libavcodec/fft-fixed-test.c @@ -0,0 +1,20 @@ +/* + * 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 + */ + +#define CONFIG_FFT_FLOAT 0 +#include "fft-test.c" diff --git a/ffmpeg/libavcodec/fft-internal.h b/ffmpeg/libavcodec/fft-internal.h new file mode 100644 index 0000000..d66731f --- /dev/null +++ b/ffmpeg/libavcodec/fft-internal.h @@ -0,0 +1,75 @@ +/* + * 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 + */ + +#ifndef AVCODEC_FFT_INTERNAL_H +#define AVCODEC_FFT_INTERNAL_H + +#if CONFIG_FFT_FLOAT + +#define FIX15(v) (v) +#define sqrthalf (float)M_SQRT1_2 + +#define BF(x, y, a, b) do { \ + x = a - b; \ + y = a + b; \ + } while (0) + +#define CMUL(dre, dim, are, aim, bre, bim) do { \ + (dre) = (are) * (bre) - (aim) * (bim); \ + (dim) = (are) * (bim) + (aim) * (bre); \ + } while (0) + +#else + +#include "fft.h" +#include "mathops.h" + +void ff_mdct_calcw_c(FFTContext *s, FFTDouble *output, const FFTSample *input); + +#define SCALE_FLOAT(a, bits) lrint((a) * (double)(1 << (bits))) +#define FIX15(a) av_clip(SCALE_FLOAT(a, 15), -32767, 32767) + +#define sqrthalf ((int16_t)((1<<15)*M_SQRT1_2)) + +#define BF(x, y, a, b) do { \ + x = (a - b) >> 1; \ + y = (a + b) >> 1; \ + } while (0) + +#define CMULS(dre, dim, are, aim, bre, bim, sh) do { \ + (dre) = (MUL16(are, bre) - MUL16(aim, bim)) >> sh; \ + (dim) = (MUL16(are, bim) + MUL16(aim, bre)) >> sh; \ + } while (0) + +#define CMUL(dre, dim, are, aim, bre, bim) \ + CMULS(dre, dim, are, aim, bre, bim, 15) + +#define CMULL(dre, dim, are, aim, bre, bim) \ + CMULS(dre, dim, are, aim, bre, bim, 0) + +#endif /* CONFIG_FFT_FLOAT */ + +#define ff_imdct_calc_c FFT_NAME(ff_imdct_calc_c) +#define ff_imdct_half_c FFT_NAME(ff_imdct_half_c) +#define ff_mdct_calc_c FFT_NAME(ff_mdct_calc_c) + +void ff_imdct_calc_c(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_mdct_calc_c(FFTContext *s, FFTSample *output, const FFTSample *input); + +#endif /* AVCODEC_FFT_INTERNAL_H */ diff --git a/ffmpeg/libavcodec/fft-test.c b/ffmpeg/libavcodec/fft-test.c new file mode 100644 index 0000000..66474ce --- /dev/null +++ b/ffmpeg/libavcodec/fft-test.c @@ -0,0 +1,495 @@ +/* + * (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * FFT and MDCT tests. + */ + +#include "libavutil/cpu.h" +#include "libavutil/mathematics.h" +#include "libavutil/lfg.h" +#include "libavutil/log.h" +#include "libavutil/time.h" +#include "fft.h" +#if CONFIG_FFT_FLOAT +#include "dct.h" +#include "rdft.h" +#endif +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +/* reference fft */ + +#define MUL16(a,b) ((a) * (b)) + +#define CMAC(pre, pim, are, aim, bre, bim) \ +{\ + pre += (MUL16(are, bre) - MUL16(aim, bim));\ + pim += (MUL16(are, bim) + MUL16(bre, aim));\ +} + +#if CONFIG_FFT_FLOAT +# define RANGE 1.0 +# define REF_SCALE(x, bits) (x) +# define FMT "%10.6f" +#else +# define RANGE 16384 +# define REF_SCALE(x, bits) ((x) / (1<<(bits))) +# define FMT "%6d" +#endif + +struct { + float re, im; +} *exptab; + +static void fft_ref_init(int nbits, int inverse) +{ + int n, i; + double c1, s1, alpha; + + n = 1 << nbits; + exptab = av_malloc((n / 2) * sizeof(*exptab)); + + for (i = 0; i < (n/2); i++) { + alpha = 2 * M_PI * (float)i / (float)n; + c1 = cos(alpha); + s1 = sin(alpha); + if (!inverse) + s1 = -s1; + exptab[i].re = c1; + exptab[i].im = s1; + } +} + +static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) +{ + int n, i, j, k, n2; + double tmp_re, tmp_im, s, c; + FFTComplex *q; + + n = 1 << nbits; + n2 = n >> 1; + for (i = 0; i < n; i++) { + tmp_re = 0; + tmp_im = 0; + q = tab; + for (j = 0; j < n; j++) { + k = (i * j) & (n - 1); + if (k >= n2) { + c = -exptab[k - n2].re; + s = -exptab[k - n2].im; + } else { + c = exptab[k].re; + s = exptab[k].im; + } + CMAC(tmp_re, tmp_im, c, s, q->re, q->im); + q++; + } + tabr[i].re = REF_SCALE(tmp_re, nbits); + tabr[i].im = REF_SCALE(tmp_im, nbits); + } +} + +static void imdct_ref(FFTSample *out, FFTSample *in, int nbits) +{ + int n = 1<= 1e-3) { + av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n", + i, tab1[i], tab2[i]); + err = 1; + } + error+= e*e; + if(e>max) max= e; + } + av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error/n)); + return err; +} + + +static void help(void) +{ + av_log(NULL, AV_LOG_INFO,"usage: fft-test [-h] [-s] [-i] [-n b]\n" + "-h print this help\n" + "-s speed test\n" + "-m (I)MDCT test\n" + "-d (I)DCT test\n" + "-r (I)RDFT test\n" + "-i inverse transform test\n" + "-n b set the transform size to 2^b\n" + "-f x set scale factor for output data of (I)MDCT to x\n" + ); +} + +enum tf_transform { + TRANSFORM_FFT, + TRANSFORM_MDCT, + TRANSFORM_RDFT, + TRANSFORM_DCT, +}; + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +int main(int argc, char **argv) +{ + FFTComplex *tab, *tab1, *tab_ref; + FFTSample *tab2; + int it, i, c; + int cpuflags; + int do_speed = 0; + int err = 1; + enum tf_transform transform = TRANSFORM_FFT; + int do_inverse = 0; + FFTContext s1, *s = &s1; + FFTContext m1, *m = &m1; +#if CONFIG_FFT_FLOAT + RDFTContext r1, *r = &r1; + DCTContext d1, *d = &d1; + int fft_size_2; +#endif + int fft_nbits, fft_size; + double scale = 1.0; + AVLFG prng; + av_lfg_init(&prng, 1); + + fft_nbits = 9; + for(;;) { + c = getopt(argc, argv, "hsimrdn:f:c:"); + if (c == -1) + break; + switch(c) { + case 'h': + help(); + return 1; + case 's': + do_speed = 1; + break; + case 'i': + do_inverse = 1; + break; + case 'm': + transform = TRANSFORM_MDCT; + break; + case 'r': + transform = TRANSFORM_RDFT; + break; + case 'd': + transform = TRANSFORM_DCT; + break; + case 'n': + fft_nbits = atoi(optarg); + break; + case 'f': + scale = atof(optarg); + break; + case 'c': + cpuflags = av_get_cpu_flags(); + + if (av_parse_cpu_caps(&cpuflags, optarg) < 0) + return 1; + + av_force_cpu_flags(cpuflags); + break; + } + } + + fft_size = 1 << fft_nbits; + tab = av_malloc(fft_size * sizeof(FFTComplex)); + tab1 = av_malloc(fft_size * sizeof(FFTComplex)); + tab_ref = av_malloc(fft_size * sizeof(FFTComplex)); + tab2 = av_malloc(fft_size * sizeof(FFTSample)); + + switch (transform) { + case TRANSFORM_MDCT: + av_log(NULL, AV_LOG_INFO,"Scale factor is set to %f\n", scale); + if (do_inverse) + av_log(NULL, AV_LOG_INFO,"IMDCT"); + else + av_log(NULL, AV_LOG_INFO,"MDCT"); + ff_mdct_init(m, fft_nbits, do_inverse, scale); + break; + case TRANSFORM_FFT: + if (do_inverse) + av_log(NULL, AV_LOG_INFO,"IFFT"); + else + av_log(NULL, AV_LOG_INFO,"FFT"); + ff_fft_init(s, fft_nbits, do_inverse); + fft_ref_init(fft_nbits, do_inverse); + break; +#if CONFIG_FFT_FLOAT + case TRANSFORM_RDFT: + if (do_inverse) + av_log(NULL, AV_LOG_INFO,"IDFT_C2R"); + else + av_log(NULL, AV_LOG_INFO,"DFT_R2C"); + ff_rdft_init(r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); + fft_ref_init(fft_nbits, do_inverse); + break; + case TRANSFORM_DCT: + if (do_inverse) + av_log(NULL, AV_LOG_INFO,"DCT_III"); + else + av_log(NULL, AV_LOG_INFO,"DCT_II"); + ff_dct_init(d, fft_nbits, do_inverse ? DCT_III : DCT_II); + break; +#endif + default: + av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); + return 1; + } + av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); + + /* generate random data */ + + for (i = 0; i < fft_size; i++) { + tab1[i].re = frandom(&prng); + tab1[i].im = frandom(&prng); + } + + /* checking result */ + av_log(NULL, AV_LOG_INFO,"Checking...\n"); + + switch (transform) { + case TRANSFORM_MDCT: + if (do_inverse) { + imdct_ref((FFTSample *)tab_ref, (FFTSample *)tab1, fft_nbits); + m->imdct_calc(m, tab2, (FFTSample *)tab1); + err = check_diff((FFTSample *)tab_ref, tab2, fft_size, scale); + } else { + mdct_ref((FFTSample *)tab_ref, (FFTSample *)tab1, fft_nbits); + + m->mdct_calc(m, tab2, (FFTSample *)tab1); + + err = check_diff((FFTSample *)tab_ref, tab2, fft_size / 2, scale); + } + break; + case TRANSFORM_FFT: + memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); + s->fft_permute(s, tab); + s->fft_calc(s, tab); + + fft_ref(tab_ref, tab1, fft_nbits); + err = check_diff((FFTSample *)tab_ref, (FFTSample *)tab, fft_size * 2, 1.0); + break; +#if CONFIG_FFT_FLOAT + case TRANSFORM_RDFT: + fft_size_2 = fft_size >> 1; + if (do_inverse) { + tab1[ 0].im = 0; + tab1[fft_size_2].im = 0; + for (i = 1; i < fft_size_2; i++) { + tab1[fft_size_2+i].re = tab1[fft_size_2-i].re; + tab1[fft_size_2+i].im = -tab1[fft_size_2-i].im; + } + + memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); + tab2[1] = tab1[fft_size_2].re; + + r->rdft_calc(r, tab2); + fft_ref(tab_ref, tab1, fft_nbits); + for (i = 0; i < fft_size; i++) { + tab[i].re = tab2[i]; + tab[i].im = 0; + } + err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 0.5); + } else { + for (i = 0; i < fft_size; i++) { + tab2[i] = tab1[i].re; + tab1[i].im = 0; + } + r->rdft_calc(r, tab2); + fft_ref(tab_ref, tab1, fft_nbits); + tab_ref[0].im = tab_ref[fft_size_2].re; + err = check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0); + } + break; + case TRANSFORM_DCT: + memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); + d->dct_calc(d, (FFTSample *)tab); + if (do_inverse) { + idct_ref((FFTSample*)tab_ref, (FFTSample *)tab1, fft_nbits); + } else { + dct_ref((FFTSample*)tab_ref, (FFTSample *)tab1, fft_nbits); + } + err = check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); + break; +#endif + } + + /* do a speed test */ + + if (do_speed) { + int64_t time_start, duration; + int nb_its; + + av_log(NULL, AV_LOG_INFO,"Speed test...\n"); + /* we measure during about 1 seconds */ + nb_its = 1; + for(;;) { + time_start = av_gettime(); + for (it = 0; it < nb_its; it++) { + switch (transform) { + case TRANSFORM_MDCT: + if (do_inverse) { + m->imdct_calc(m, (FFTSample *)tab, (FFTSample *)tab1); + } else { + m->mdct_calc(m, (FFTSample *)tab, (FFTSample *)tab1); + } + break; + case TRANSFORM_FFT: + memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); + s->fft_calc(s, tab); + break; +#if CONFIG_FFT_FLOAT + case TRANSFORM_RDFT: + memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); + r->rdft_calc(r, tab2); + break; + case TRANSFORM_DCT: + memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); + d->dct_calc(d, tab2); + break; +#endif + } + } + duration = av_gettime() - time_start; + if (duration >= 1000000) + break; + nb_its *= 2; + } + av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n", + (double)duration / nb_its, + (double)duration / 1000000.0, + nb_its); + } + + switch (transform) { + case TRANSFORM_MDCT: + ff_mdct_end(m); + break; + case TRANSFORM_FFT: + ff_fft_end(s); + break; +#if CONFIG_FFT_FLOAT + case TRANSFORM_RDFT: + ff_rdft_end(r); + break; + case TRANSFORM_DCT: + ff_dct_end(d); + break; +#endif + } + + av_free(tab); + av_free(tab1); + av_free(tab2); + av_free(tab_ref); + av_free(exptab); + + return err; +} diff --git a/ffmpeg/libavcodec/fft.c b/ffmpeg/libavcodec/fft.c new file mode 100644 index 0000000..00c434a --- /dev/null +++ b/ffmpeg/libavcodec/fft.c @@ -0,0 +1,353 @@ +/* + * FFT/IFFT transforms + * Copyright (c) 2008 Loren Merritt + * Copyright (c) 2002 Fabrice Bellard + * Partly based on libdjbfft by D. J. Bernstein + * + * 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 + */ + +/** + * @file + * FFT/IFFT transforms. + */ + +#include +#include +#include "libavutil/mathematics.h" +#include "fft.h" +#include "fft-internal.h" + +/* cos(2*pi*x/n) for 0<=x<=n/4, followed by its reverse */ +#if !CONFIG_HARDCODED_TABLES +COSTABLE(16); +COSTABLE(32); +COSTABLE(64); +COSTABLE(128); +COSTABLE(256); +COSTABLE(512); +COSTABLE(1024); +COSTABLE(2048); +COSTABLE(4096); +COSTABLE(8192); +COSTABLE(16384); +COSTABLE(32768); +COSTABLE(65536); +#endif +COSTABLE_CONST FFTSample * const FFT_NAME(ff_cos_tabs)[] = { + NULL, NULL, NULL, NULL, + FFT_NAME(ff_cos_16), + FFT_NAME(ff_cos_32), + FFT_NAME(ff_cos_64), + FFT_NAME(ff_cos_128), + FFT_NAME(ff_cos_256), + FFT_NAME(ff_cos_512), + FFT_NAME(ff_cos_1024), + FFT_NAME(ff_cos_2048), + FFT_NAME(ff_cos_4096), + FFT_NAME(ff_cos_8192), + FFT_NAME(ff_cos_16384), + FFT_NAME(ff_cos_32768), + FFT_NAME(ff_cos_65536), +}; + +static void ff_fft_permute_c(FFTContext *s, FFTComplex *z); +static void ff_fft_calc_c(FFTContext *s, FFTComplex *z); + +static int split_radix_permutation(int i, int n, int inverse) +{ + int m; + if(n <= 2) return i&1; + m = n >> 1; + if(!(i&m)) return split_radix_permutation(i, m, inverse)*2; + m >>= 1; + if(inverse == !(i&m)) return split_radix_permutation(i, m, inverse)*4 + 1; + else return split_radix_permutation(i, m, inverse)*4 - 1; +} + +av_cold void ff_init_ff_cos_tabs(int index) +{ +#if !CONFIG_HARDCODED_TABLES + int i; + int m = 1<= 16; + else if (i < n/2) + return is_second_half_of_fft32(i, n/2); + else if (i < 3*n/4) + return is_second_half_of_fft32(i - n/2, n/4); + else + return is_second_half_of_fft32(i - 3*n/4, n/4); +} + +static av_cold void fft_perm_avx(FFTContext *s) +{ + int i; + int n = 1 << s->nbits; + + for (i = 0; i < n; i += 16) { + int k; + if (is_second_half_of_fft32(i, n)) { + for (k = 0; k < 16; k++) + s->revtab[-split_radix_permutation(i + k, n, s->inverse) & (n - 1)] = + i + avx_tab[k]; + + } else { + for (k = 0; k < 16; k++) { + int j = i + k; + j = (j & ~7) | ((j >> 1) & 3) | ((j << 2) & 4); + s->revtab[-split_radix_permutation(i + k, n, s->inverse) & (n - 1)] = j; + } + } + } +} + +av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse) +{ + int i, j, n; + + if (nbits < 2 || nbits > 16) + goto fail; + s->nbits = nbits; + n = 1 << nbits; + + s->revtab = av_malloc(n * sizeof(uint16_t)); + if (!s->revtab) + goto fail; + s->tmp_buf = av_malloc(n * sizeof(FFTComplex)); + if (!s->tmp_buf) + goto fail; + s->inverse = inverse; + s->fft_permutation = FF_FFT_PERM_DEFAULT; + + s->fft_permute = ff_fft_permute_c; + s->fft_calc = ff_fft_calc_c; +#if CONFIG_MDCT + s->imdct_calc = ff_imdct_calc_c; + s->imdct_half = ff_imdct_half_c; + s->mdct_calc = ff_mdct_calc_c; +#endif + +#if CONFIG_FFT_FLOAT + if (ARCH_ARM) ff_fft_init_arm(s); + if (HAVE_ALTIVEC) ff_fft_init_altivec(s); + if (ARCH_X86) ff_fft_init_x86(s); + if (CONFIG_MDCT) s->mdct_calcw = s->mdct_calc; + if (HAVE_MIPSFPU) ff_fft_init_mips(s); +#else + if (CONFIG_MDCT) s->mdct_calcw = ff_mdct_calcw_c; + if (ARCH_ARM) ff_fft_fixed_init_arm(s); +#endif + + for(j=4; j<=nbits; j++) { + ff_init_ff_cos_tabs(j); + } + + if (s->fft_permutation == FF_FFT_PERM_AVX) { + fft_perm_avx(s); + } else { + for(i=0; ifft_permutation == FF_FFT_PERM_SWAP_LSBS) + j = (j&~3) | ((j>>1)&1) | ((j<<1)&2); + s->revtab[-split_radix_permutation(i, n, s->inverse) & (n-1)] = j; + } + } + + return 0; + fail: + av_freep(&s->revtab); + av_freep(&s->tmp_buf); + return -1; +} + +static void ff_fft_permute_c(FFTContext *s, FFTComplex *z) +{ + int j, np; + const uint16_t *revtab = s->revtab; + np = 1 << s->nbits; + /* TODO: handle split-radix permute in a more optimal way, probably in-place */ + for(j=0;jtmp_buf[revtab[j]] = z[j]; + memcpy(z, s->tmp_buf, np * sizeof(FFTComplex)); +} + +av_cold void ff_fft_end(FFTContext *s) +{ + av_freep(&s->revtab); + av_freep(&s->tmp_buf); +} + +#define BUTTERFLIES(a0,a1,a2,a3) {\ + BF(t3, t5, t5, t1);\ + BF(a2.re, a0.re, a0.re, t5);\ + BF(a3.im, a1.im, a1.im, t3);\ + BF(t4, t6, t2, t6);\ + BF(a3.re, a1.re, a1.re, t4);\ + BF(a2.im, a0.im, a0.im, t6);\ +} + +// force loading all the inputs before storing any. +// this is slightly slower for small data, but avoids store->load aliasing +// for addresses separated by large powers of 2. +#define BUTTERFLIES_BIG(a0,a1,a2,a3) {\ + FFTSample r0=a0.re, i0=a0.im, r1=a1.re, i1=a1.im;\ + BF(t3, t5, t5, t1);\ + BF(a2.re, a0.re, r0, t5);\ + BF(a3.im, a1.im, i1, t3);\ + BF(t4, t6, t2, t6);\ + BF(a3.re, a1.re, r1, t4);\ + BF(a2.im, a0.im, i0, t6);\ +} + +#define TRANSFORM(a0,a1,a2,a3,wre,wim) {\ + CMUL(t1, t2, a2.re, a2.im, wre, -wim);\ + CMUL(t5, t6, a3.re, a3.im, wre, wim);\ + BUTTERFLIES(a0,a1,a2,a3)\ +} + +#define TRANSFORM_ZERO(a0,a1,a2,a3) {\ + t1 = a2.re;\ + t2 = a2.im;\ + t5 = a3.re;\ + t6 = a3.im;\ + BUTTERFLIES(a0,a1,a2,a3)\ +} + +/* z[0...8n-1], w[1...2n-1] */ +#define PASS(name)\ +static void name(FFTComplex *z, const FFTSample *wre, unsigned int n)\ +{\ + FFTDouble t1, t2, t3, t4, t5, t6;\ + int o1 = 2*n;\ + int o2 = 4*n;\ + int o3 = 6*n;\ + const FFTSample *wim = wre+o1;\ + n--;\ +\ + TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3]);\ + TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\ + do {\ + z += 2;\ + wre += 2;\ + wim -= 2;\ + TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0]);\ + TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1]);\ + } while(--n);\ +} + +PASS(pass) +#undef BUTTERFLIES +#define BUTTERFLIES BUTTERFLIES_BIG +PASS(pass_big) + +#define DECL_FFT(n,n2,n4)\ +static void fft##n(FFTComplex *z)\ +{\ + fft##n2(z);\ + fft##n4(z+n4*2);\ + fft##n4(z+n4*3);\ + pass(z,FFT_NAME(ff_cos_##n),n4/2);\ +} + +static void fft4(FFTComplex *z) +{ + FFTDouble t1, t2, t3, t4, t5, t6, t7, t8; + + BF(t3, t1, z[0].re, z[1].re); + BF(t8, t6, z[3].re, z[2].re); + BF(z[2].re, z[0].re, t1, t6); + BF(t4, t2, z[0].im, z[1].im); + BF(t7, t5, z[2].im, z[3].im); + BF(z[3].im, z[1].im, t4, t8); + BF(z[3].re, z[1].re, t3, t7); + BF(z[2].im, z[0].im, t2, t5); +} + +static void fft8(FFTComplex *z) +{ + FFTDouble t1, t2, t3, t4, t5, t6; + + fft4(z); + + BF(t1, z[5].re, z[4].re, -z[5].re); + BF(t2, z[5].im, z[4].im, -z[5].im); + BF(t5, z[7].re, z[6].re, -z[7].re); + BF(t6, z[7].im, z[6].im, -z[7].im); + + BUTTERFLIES(z[0],z[2],z[4],z[6]); + TRANSFORM(z[1],z[3],z[5],z[7],sqrthalf,sqrthalf); +} + +#if !CONFIG_SMALL +static void fft16(FFTComplex *z) +{ + FFTDouble t1, t2, t3, t4, t5, t6; + FFTSample cos_16_1 = FFT_NAME(ff_cos_16)[1]; + FFTSample cos_16_3 = FFT_NAME(ff_cos_16)[3]; + + fft8(z); + fft4(z+8); + fft4(z+12); + + TRANSFORM_ZERO(z[0],z[4],z[8],z[12]); + TRANSFORM(z[2],z[6],z[10],z[14],sqrthalf,sqrthalf); + TRANSFORM(z[1],z[5],z[9],z[13],cos_16_1,cos_16_3); + TRANSFORM(z[3],z[7],z[11],z[15],cos_16_3,cos_16_1); +} +#else +DECL_FFT(16,8,4) +#endif +DECL_FFT(32,16,8) +DECL_FFT(64,32,16) +DECL_FFT(128,64,32) +DECL_FFT(256,128,64) +DECL_FFT(512,256,128) +#if !CONFIG_SMALL +#define pass pass_big +#endif +DECL_FFT(1024,512,256) +DECL_FFT(2048,1024,512) +DECL_FFT(4096,2048,1024) +DECL_FFT(8192,4096,2048) +DECL_FFT(16384,8192,4096) +DECL_FFT(32768,16384,8192) +DECL_FFT(65536,32768,16384) + +static void (* const fft_dispatch[])(FFTComplex*) = { + fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024, + fft2048, fft4096, fft8192, fft16384, fft32768, fft65536, +}; + +static void ff_fft_calc_c(FFTContext *s, FFTComplex *z) +{ + fft_dispatch[s->nbits-2](z); +} diff --git a/ffmpeg/libavcodec/fft.h b/ffmpeg/libavcodec/fft.h new file mode 100644 index 0000000..9d92b2c --- /dev/null +++ b/ffmpeg/libavcodec/fft.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +#ifndef AVCODEC_FFT_H +#define AVCODEC_FFT_H + +#ifndef CONFIG_FFT_FLOAT +#define CONFIG_FFT_FLOAT 1 +#endif + +#include +#include "config.h" +#include "libavutil/mem.h" + +#if CONFIG_FFT_FLOAT + +#include "avfft.h" + +#define FFT_NAME(x) x + +typedef float FFTDouble; + +#else + +#define FFT_NAME(x) x ## _fixed + +typedef int16_t FFTSample; +typedef int FFTDouble; + +typedef struct FFTComplex { + int16_t re, im; +} FFTComplex; + +typedef struct FFTContext FFTContext; + +#endif /* CONFIG_FFT_FLOAT */ + +typedef struct FFTDComplex { + FFTDouble re, im; +} FFTDComplex; + +/* FFT computation */ + +struct FFTContext { + int nbits; + int inverse; + uint16_t *revtab; + FFTComplex *tmp_buf; + int mdct_size; /* size of MDCT (i.e. number of input data * 2) */ + int mdct_bits; /* n = 2^nbits */ + /* pre/post rotation tables */ + FFTSample *tcos; + FFTSample *tsin; + /** + * Do the permutation needed BEFORE calling fft_calc(). + */ + void (*fft_permute)(struct FFTContext *s, FFTComplex *z); + /** + * Do a complex FFT with the parameters defined in ff_fft_init(). The + * input data must be permuted before. No 1.0/sqrt(n) normalization is done. + */ + void (*fft_calc)(struct FFTContext *s, FFTComplex *z); + void (*imdct_calc)(struct FFTContext *s, FFTSample *output, const FFTSample *input); + void (*imdct_half)(struct FFTContext *s, FFTSample *output, const FFTSample *input); + void (*mdct_calc)(struct FFTContext *s, FFTSample *output, const FFTSample *input); + void (*mdct_calcw)(struct FFTContext *s, FFTDouble *output, const FFTSample *input); + int fft_permutation; +#define FF_FFT_PERM_DEFAULT 0 +#define FF_FFT_PERM_SWAP_LSBS 1 +#define FF_FFT_PERM_AVX 2 + int mdct_permutation; +#define FF_MDCT_PERM_NONE 0 +#define FF_MDCT_PERM_INTERLEAVE 1 +}; + +#if CONFIG_HARDCODED_TABLES +#define COSTABLE_CONST const +#else +#define COSTABLE_CONST +#endif + +#define COSTABLE(size) \ + COSTABLE_CONST DECLARE_ALIGNED(32, FFTSample, FFT_NAME(ff_cos_##size))[size/2] + +extern COSTABLE(16); +extern COSTABLE(32); +extern COSTABLE(64); +extern COSTABLE(128); +extern COSTABLE(256); +extern COSTABLE(512); +extern COSTABLE(1024); +extern COSTABLE(2048); +extern COSTABLE(4096); +extern COSTABLE(8192); +extern COSTABLE(16384); +extern COSTABLE(32768); +extern COSTABLE(65536); +extern COSTABLE_CONST FFTSample* const FFT_NAME(ff_cos_tabs)[17]; + +#define ff_init_ff_cos_tabs FFT_NAME(ff_init_ff_cos_tabs) + +/** + * Initialize the cosine table in ff_cos_tabs[index] + * @param index index in ff_cos_tabs array of the table to initialize + */ +void ff_init_ff_cos_tabs(int index); + +#define ff_fft_init FFT_NAME(ff_fft_init) +#define ff_fft_end FFT_NAME(ff_fft_end) + +/** + * Set up a complex FFT. + * @param nbits log2 of the length of the input array + * @param inverse if 0 perform the forward transform, if 1 perform the inverse + */ +int ff_fft_init(FFTContext *s, int nbits, int inverse); + +#if CONFIG_FFT_FLOAT +void ff_fft_init_altivec(FFTContext *s); +void ff_fft_init_x86(FFTContext *s); +void ff_fft_init_arm(FFTContext *s); +void ff_fft_init_mips(FFTContext *s); +#else +void ff_fft_fixed_init_arm(FFTContext *s); +#endif + +void ff_fft_end(FFTContext *s); + +#define ff_mdct_init FFT_NAME(ff_mdct_init) +#define ff_mdct_end FFT_NAME(ff_mdct_end) + +int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale); +void ff_mdct_end(FFTContext *s); + +#endif /* AVCODEC_FFT_H */ diff --git a/ffmpeg/libavcodec/fft_fixed.c b/ffmpeg/libavcodec/fft_fixed.c new file mode 100644 index 0000000..3955efe --- /dev/null +++ b/ffmpeg/libavcodec/fft_fixed.c @@ -0,0 +1,20 @@ +/* + * 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 + */ + +#define CONFIG_FFT_FLOAT 0 +#include "fft.c" diff --git a/ffmpeg/libavcodec/fft_float.c b/ffmpeg/libavcodec/fft_float.c new file mode 100644 index 0000000..2149646 --- /dev/null +++ b/ffmpeg/libavcodec/fft_float.c @@ -0,0 +1,20 @@ +/* + * 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 + */ + +#define CONFIG_FFT_FLOAT 1 +#include "fft.c" diff --git a/ffmpeg/libavcodec/ffv1.c b/ffmpeg/libavcodec/ffv1.c new file mode 100644 index 0000000..404b0e3 --- /dev/null +++ b/ffmpeg/libavcodec/ffv1.c @@ -0,0 +1,221 @@ +/* + * FFV1 codec for libavcodec + * + * Copyright (c) 2003-2012 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 + */ + +/** + * @file + * FF Video Codec 1 (a lossless codec) + */ + +#include "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/timer.h" +#include "avcodec.h" +#include "internal.h" +#include "rangecoder.h" +#include "golomb.h" +#include "mathops.h" +#include "ffv1.h" + +av_cold int ffv1_common_init(AVCodecContext *avctx) +{ + FFV1Context *s = avctx->priv_data; + + if (!avctx->width || !avctx->height) + return AVERROR_INVALIDDATA; + + s->avctx = avctx; + s->flags = avctx->flags; + + avcodec_get_frame_defaults(&s->picture); + + ff_dsputil_init(&s->dsp, avctx); + + s->width = avctx->width; + s->height = avctx->height; + + // defaults + s->num_h_slices = 1; + s->num_v_slices = 1; + + return 0; +} + +int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) +{ + int j; + + fs->plane_count = f->plane_count; + fs->transparency = f->transparency; + for (j = 0; j < f->plane_count; j++) { + PlaneContext *const p = &fs->plane[j]; + + if (fs->ac) { + if (!p->state) + p->state = av_malloc(CONTEXT_SIZE * p->context_count * + sizeof(uint8_t)); + if (!p->state) + return AVERROR(ENOMEM); + } else { + if (!p->vlc_state) + p->vlc_state = av_malloc(p->context_count * sizeof(VlcState)); + if (!p->vlc_state) + return AVERROR(ENOMEM); + } + } + + if (fs->ac > 1) { + //FIXME only redo if state_transition changed + for (j = 1; j < 256; j++) { + fs->c. one_state[ j] = f->state_transition[j]; + fs->c.zero_state[256 - j] = 256 - fs->c.one_state[j]; + } + } + + return 0; +} + +int ffv1_init_slices_state(FFV1Context *f) +{ + int i, ret; + for (i = 0; i < f->slice_count; i++) { + FFV1Context *fs = f->slice_context[i]; + if ((ret = ffv1_init_slice_state(f, fs)) < 0) + return AVERROR(ENOMEM); + } + return 0; +} + +av_cold int ffv1_init_slice_contexts(FFV1Context *f) +{ + int i; + + f->slice_count = f->num_h_slices * f->num_v_slices; + av_assert0(f->slice_count > 0); + + for (i = 0; i < f->slice_count; i++) { + FFV1Context *fs = av_mallocz(sizeof(*fs)); + int sx = i % f->num_h_slices; + int sy = i / f->num_h_slices; + int sxs = f->avctx->width * sx / f->num_h_slices; + int sxe = f->avctx->width * (sx + 1) / f->num_h_slices; + int sys = f->avctx->height * sy / f->num_v_slices; + int sye = f->avctx->height * (sy + 1) / f->num_v_slices; + + if (!fs) + return AVERROR(ENOMEM); + + f->slice_context[i] = fs; + memcpy(fs, f, sizeof(*fs)); + memset(fs->rc_stat2, 0, sizeof(fs->rc_stat2)); + + fs->slice_width = sxe - sxs; + fs->slice_height = sye - sys; + fs->slice_x = sxs; + fs->slice_y = sys; + + fs->sample_buffer = av_malloc(3 * MAX_PLANES * (fs->width + 6) * + sizeof(*fs->sample_buffer)); + if (!fs->sample_buffer) + return AVERROR(ENOMEM); + } + return 0; +} + +int ffv1_allocate_initial_states(FFV1Context *f) +{ + int i; + + for (i = 0; i < f->quant_table_count; i++) { + f->initial_states[i] = av_malloc(f->context_count[i] * + sizeof(*f->initial_states[i])); + if (!f->initial_states[i]) + return AVERROR(ENOMEM); + memset(f->initial_states[i], 128, + f->context_count[i] * sizeof(*f->initial_states[i])); + } + return 0; +} + +void ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs) +{ + int i, j; + + for (i = 0; i < f->plane_count; i++) { + PlaneContext *p = &fs->plane[i]; + + p->interlace_bit_state[0] = 128; + p->interlace_bit_state[1] = 128; + + if (fs->ac) { + if (f->initial_states[p->quant_table_index]) { + memcpy(p->state, f->initial_states[p->quant_table_index], + CONTEXT_SIZE * p->context_count); + } else + memset(p->state, 128, CONTEXT_SIZE * p->context_count); + } else { + for (j = 0; j < p->context_count; j++) { + p->vlc_state[j].drift = 0; + p->vlc_state[j].error_sum = 4; //FFMAX((RANGE + 32)/64, 2); + p->vlc_state[j].bias = 0; + p->vlc_state[j].count = 1; + } + } + } +} + + +av_cold int ffv1_close(AVCodecContext *avctx) +{ + FFV1Context *s = avctx->priv_data; + int i, j; + + av_frame_unref(&s->last_picture); + + for (j = 0; j < s->slice_count; j++) { + FFV1Context *fs = s->slice_context[j]; + for (i = 0; i < s->plane_count; i++) { + PlaneContext *p = &fs->plane[i]; + + av_freep(&p->state); + av_freep(&p->vlc_state); + } + av_freep(&fs->sample_buffer); + } + + av_freep(&avctx->stats_out); + for (j = 0; j < s->quant_table_count; j++) { + av_freep(&s->initial_states[j]); + for (i = 0; i < s->slice_count; i++) { + FFV1Context *sf = s->slice_context[i]; + av_freep(&sf->rc_stat2[j]); + } + av_freep(&s->rc_stat2[j]); + } + + for (i = 0; i < s->slice_count; i++) + av_freep(&s->slice_context[i]); + + return 0; +} diff --git a/ffmpeg/libavcodec/ffv1.h b/ffmpeg/libavcodec/ffv1.h new file mode 100644 index 0000000..23633c9 --- /dev/null +++ b/ffmpeg/libavcodec/ffv1.h @@ -0,0 +1,216 @@ +/* + * FFV1 codec for libavcodec + * + * Copyright (c) 2003-2012 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 + */ + +#ifndef AVCODEC_FFV1_H +#define AVCODEC_FFV1_H + +/** + * @file + * FF Video Codec 1 (a lossless codec) + */ + +#include "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/timer.h" +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" +#include "put_bits.h" +#include "rangecoder.h" + +#ifdef __INTEL_COMPILER +#undef av_flatten +#define av_flatten +#endif + +#define MAX_PLANES 4 +#define CONTEXT_SIZE 32 + +#define MAX_QUANT_TABLES 8 +#define MAX_CONTEXT_INPUTS 5 + +extern const uint8_t ff_log2_run[41]; + +typedef struct VlcState { + int16_t drift; + uint16_t error_sum; + int8_t bias; + uint8_t count; +} VlcState; + +typedef struct PlaneContext { + int16_t quant_table[MAX_CONTEXT_INPUTS][256]; + int quant_table_index; + int context_count; + uint8_t (*state)[CONTEXT_SIZE]; + VlcState *vlc_state; + uint8_t interlace_bit_state[2]; +} PlaneContext; + +#define MAX_SLICES 256 + +typedef struct FFV1Context { + AVClass *class; + AVCodecContext *avctx; + RangeCoder c; + GetBitContext gb; + PutBitContext pb; + uint64_t rc_stat[256][2]; + uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2]; + int version; + int minor_version; + int width, height; + int chroma_planes; + int chroma_h_shift, chroma_v_shift; + int transparency; + int flags; + int picture_number; + AVFrame picture, last_picture; + + AVFrame *cur; + int plane_count; + int ac; ///< 1=range coder <-> 0=golomb rice + int ac_byte_count; ///< number of bytes used for AC coding + PlaneContext plane[MAX_PLANES]; + int16_t quant_table[MAX_CONTEXT_INPUTS][256]; + int16_t quant_tables[MAX_QUANT_TABLES][MAX_CONTEXT_INPUTS][256]; + int context_count[MAX_QUANT_TABLES]; + uint8_t state_transition[256]; + uint8_t (*initial_states[MAX_QUANT_TABLES])[32]; + int run_index; + int colorspace; + int16_t *sample_buffer; + + int ec; + int slice_damaged; + int key_frame_ok; + + int bits_per_raw_sample; + int packed_at_lsb; + + int gob_count; + int quant_table_count; + + DSPContext dsp; + + struct FFV1Context *slice_context[MAX_SLICES]; + int slice_count; + int num_v_slices; + int num_h_slices; + int slice_width; + int slice_height; + int slice_x; + int slice_y; +} FFV1Context; + +int ffv1_common_init(AVCodecContext *avctx); +int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs); +int ffv1_init_slices_state(FFV1Context *f); +int ffv1_init_slice_contexts(FFV1Context *f); +int ffv1_allocate_initial_states(FFV1Context *f); +void ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs); +int ffv1_close(AVCodecContext *avctx); + +static av_always_inline int fold(int diff, int bits) +{ + if (bits == 8) + diff = (int8_t)diff; + else { + diff += 1 << (bits - 1); + diff &= (1 << bits) - 1; + diff -= 1 << (bits - 1); + } + + return diff; +} + +static inline int predict(int16_t *src, int16_t *last) +{ + const int LT = last[-1]; + const int T = last[0]; + const int L = src[-1]; + + return mid_pred(L, L + T - LT, T); +} + +static inline int get_context(PlaneContext *p, int16_t *src, + int16_t *last, int16_t *last2) +{ + const int LT = last[-1]; + const int T = last[0]; + const int RT = last[1]; + const int L = src[-1]; + + if (p->quant_table[3][127]) { + const int TT = last2[0]; + const int LL = src[-2]; + return p->quant_table[0][(L - LT) & 0xFF] + + p->quant_table[1][(LT - T) & 0xFF] + + p->quant_table[2][(T - RT) & 0xFF] + + p->quant_table[3][(LL - L) & 0xFF] + + p->quant_table[4][(TT - T) & 0xFF]; + } else + return p->quant_table[0][(L - LT) & 0xFF] + + p->quant_table[1][(LT - T) & 0xFF] + + p->quant_table[2][(T - RT) & 0xFF]; +} + +static inline void update_vlc_state(VlcState *const state, const int v) +{ + int drift = state->drift; + int count = state->count; + state->error_sum += FFABS(v); + drift += v; + + if (count == 128) { // FIXME: variable + count >>= 1; + drift >>= 1; + state->error_sum >>= 1; + } + count++; + + if (drift <= -count) { + if (state->bias > -128) + state->bias--; + + drift += count; + if (drift <= -count) + drift = -count + 1; + } else if (drift > 0) { + if (state->bias < 127) + state->bias++; + + drift -= count; + if (drift > 0) + drift = 0; + } + + state->drift = drift; + state->count = count; +} + +#endif /* AVCODEC_FFV1_H */ diff --git a/ffmpeg/libavcodec/ffv1dec.c b/ffmpeg/libavcodec/ffv1dec.c new file mode 100644 index 0000000..21afa1d --- /dev/null +++ b/ffmpeg/libavcodec/ffv1dec.c @@ -0,0 +1,858 @@ +/* + * FFV1 decoder + * + * Copyright (c) 2003-2012 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 + */ + +/** + * @file + * FF Video Codec 1 (a lossless codec) decoder + */ + +#include "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/timer.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "put_bits.h" +#include "rangecoder.h" +#include "golomb.h" +#include "mathops.h" +#include "ffv1.h" + +static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state, + int is_signed) +{ + if (get_rac(c, state + 0)) + return 0; + else { + int i, e, a; + e = 0; + while (get_rac(c, state + 1 + FFMIN(e, 9))) // 1..10 + e++; + + a = 1; + for (i = e - 1; i >= 0; i--) + a += a + get_rac(c, state + 22 + FFMIN(i, 9)); // 22..31 + + e = -(is_signed && get_rac(c, state + 11 + FFMIN(e, 10))); // 11..21 + return (a ^ e) - e; + } +} + +static av_noinline int get_symbol(RangeCoder *c, uint8_t *state, int is_signed) +{ + return get_symbol_inline(c, state, is_signed); +} + +static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, + int bits) +{ + int k, i, v, ret; + + i = state->count; + k = 0; + while (i < state->error_sum) { // FIXME: optimize + k++; + i += i; + } + + v = get_sr_golomb(gb, k, 12, bits); + av_dlog(NULL, "v:%d bias:%d error:%d drift:%d count:%d k:%d", + v, state->bias, state->error_sum, state->drift, state->count, k); + +#if 0 // JPEG LS + if (k == 0 && 2 * state->drift <= -state->count) + v ^= (-1); +#else + v ^= ((2 * state->drift + state->count) >> 31); +#endif + + ret = fold(v + state->bias, bits); + + update_vlc_state(state, v); + + return ret; +} + +static av_always_inline void decode_line(FFV1Context *s, int w, + int16_t *sample[2], + int plane_index, int bits) +{ + PlaneContext *const p = &s->plane[plane_index]; + RangeCoder *const c = &s->c; + int x; + int run_count = 0; + int run_mode = 0; + int run_index = s->run_index; + + for (x = 0; x < w; x++) { + int diff, context, sign; + + context = get_context(p, sample[1] + x, sample[0] + x, sample[1] + x); + if (context < 0) { + context = -context; + sign = 1; + } else + sign = 0; + + av_assert2(context < p->context_count); + + if (s->ac) { + diff = get_symbol_inline(c, p->state[context], 1); + } else { + if (context == 0 && run_mode == 0) + run_mode = 1; + + if (run_mode) { + if (run_count == 0 && run_mode == 1) { + if (get_bits1(&s->gb)) { + run_count = 1 << ff_log2_run[run_index]; + if (x + run_count <= w) + run_index++; + } else { + if (ff_log2_run[run_index]) + run_count = get_bits(&s->gb, ff_log2_run[run_index]); + else + run_count = 0; + if (run_index) + run_index--; + run_mode = 2; + } + } + run_count--; + if (run_count < 0) { + run_mode = 0; + run_count = 0; + diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], + bits); + if (diff >= 0) + diff++; + } else + diff = 0; + } else + diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits); + + av_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", + run_count, run_index, run_mode, x, get_bits_count(&s->gb)); + } + + if (sign) + diff = -diff; + + sample[1][x] = (predict(sample[1] + x, sample[0] + x) + diff) & + ((1 << bits) - 1); + } + s->run_index = run_index; +} + +static void decode_plane(FFV1Context *s, uint8_t *src, + int w, int h, int stride, int plane_index) +{ + int x, y; + int16_t *sample[2]; + sample[0] = s->sample_buffer + 3; + sample[1] = s->sample_buffer + w + 6 + 3; + + s->run_index = 0; + + memset(s->sample_buffer, 0, 2 * (w + 6) * sizeof(*s->sample_buffer)); + + for (y = 0; y < h; y++) { + int16_t *temp = sample[0]; // FIXME: try a normal buffer + + sample[0] = sample[1]; + sample[1] = temp; + + sample[1][-1] = sample[0][0]; + sample[0][w] = sample[0][w - 1]; + +// { START_TIMER + if (s->avctx->bits_per_raw_sample <= 8) { + decode_line(s, w, sample, plane_index, 8); + for (x = 0; x < w; x++) + src[x + stride * y] = sample[1][x]; + } else { + decode_line(s, w, sample, plane_index, s->avctx->bits_per_raw_sample); + if (s->packed_at_lsb) { + for (x = 0; x < w; x++) { + ((uint16_t*)(src + stride*y))[x] = sample[1][x]; + } + } else { + for (x = 0; x < w; x++) { + ((uint16_t*)(src + stride*y))[x] = sample[1][x] << (16 - s->avctx->bits_per_raw_sample); + } + } + } +// STOP_TIMER("decode-line") } + } +} + +static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) +{ + int x, y, p; + int16_t *sample[4][2]; + int lbd = s->avctx->bits_per_raw_sample <= 8; + int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8; + int offset = 1 << bits; + + for (x = 0; x < 4; x++) { + sample[x][0] = s->sample_buffer + x * 2 * (w + 6) + 3; + sample[x][1] = s->sample_buffer + (x * 2 + 1) * (w + 6) + 3; + } + + s->run_index = 0; + + memset(s->sample_buffer, 0, 8 * (w + 6) * sizeof(*s->sample_buffer)); + + for (y = 0; y < h; y++) { + for (p = 0; p < 3 + s->transparency; p++) { + int16_t *temp = sample[p][0]; // FIXME: try a normal buffer + + sample[p][0] = sample[p][1]; + sample[p][1] = temp; + + sample[p][1][-1]= sample[p][0][0 ]; + sample[p][0][ w]= sample[p][0][w-1]; + if (lbd) + decode_line(s, w, sample[p], (p + 1)/2, 9); + else + decode_line(s, w, sample[p], (p + 1)/2, bits + 1); + } + for (x = 0; x < w; x++) { + int g = sample[0][1][x]; + int b = sample[1][1][x]; + int r = sample[2][1][x]; + int a = sample[3][1][x]; + + b -= offset; + r -= offset; + g -= (b + r) >> 2; + b += g; + r += g; + + if (lbd) + *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + (g<<8) + (r<<16) + (a<<24); + else { + *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; + *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; + *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; + } + } + } +} + +static int decode_slice_header(FFV1Context *f, FFV1Context *fs) +{ + RangeCoder *c = &fs->c; + uint8_t state[CONTEXT_SIZE]; + unsigned ps, i, context_count; + memset(state, 128, sizeof(state)); + + av_assert0(f->version > 2); + + fs->slice_x = get_symbol(c, state, 0) * f->width ; + fs->slice_y = get_symbol(c, state, 0) * f->height; + fs->slice_width = (get_symbol(c, state, 0) + 1) * f->width + fs->slice_x; + fs->slice_height = (get_symbol(c, state, 0) + 1) * f->height + fs->slice_y; + + fs->slice_x /= f->num_h_slices; + fs->slice_y /= f->num_v_slices; + fs->slice_width = fs->slice_width /f->num_h_slices - fs->slice_x; + fs->slice_height = fs->slice_height/f->num_v_slices - fs->slice_y; + if ((unsigned)fs->slice_width > f->width || (unsigned)fs->slice_height > f->height) + return -1; + if ( (unsigned)fs->slice_x + (uint64_t)fs->slice_width > f->width + || (unsigned)fs->slice_y + (uint64_t)fs->slice_height > f->height) + return -1; + + for (i = 0; i < f->plane_count; i++) { + PlaneContext * const p = &fs->plane[i]; + int idx = get_symbol(c, state, 0); + if (idx > (unsigned)f->quant_table_count) { + av_log(f->avctx, AV_LOG_ERROR, "quant_table_index out of range\n"); + return -1; + } + p->quant_table_index = idx; + memcpy(p->quant_table, f->quant_tables[idx], sizeof(p->quant_table)); + context_count = f->context_count[idx]; + + if (p->context_count < context_count) { + av_freep(&p->state); + av_freep(&p->vlc_state); + } + p->context_count = context_count; + } + + ps = get_symbol(c, state, 0); + if (ps == 1) { + f->cur->interlaced_frame = 1; + f->cur->top_field_first = 1; + } else if (ps == 2) { + f->cur->interlaced_frame = 1; + f->cur->top_field_first = 0; + } else if (ps == 3) { + f->cur->interlaced_frame = 0; + } + f->cur->sample_aspect_ratio.num = get_symbol(c, state, 0); + f->cur->sample_aspect_ratio.den = get_symbol(c, state, 0); + + return 0; +} + +static int decode_slice(AVCodecContext *c, void *arg) +{ + FFV1Context *fs = *(void **)arg; + FFV1Context *f = fs->avctx->priv_data; + int width, height, x, y, ret; + const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step_minus1 + 1; + AVFrame * const p = f->cur; + + if (f->version > 2) { + if (ffv1_init_slice_state(f, fs) < 0) + return AVERROR(ENOMEM); + if (decode_slice_header(f, fs) < 0) { + fs->slice_damaged = 1; + return AVERROR_INVALIDDATA; + } + } + if ((ret = ffv1_init_slice_state(f, fs)) < 0) + return ret; + if (f->cur->key_frame) + ffv1_clear_slice_state(f, fs); + + width = fs->slice_width; + height = fs->slice_height; + x = fs->slice_x; + y = fs->slice_y; + + if (!fs->ac) { + if (f->version == 3 && f->minor_version > 1 || f->version > 3) + get_rac(&fs->c, (uint8_t[]) { 129 }); + fs->ac_byte_count = f->version > 2 || (!x && !y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0; + init_get_bits(&fs->gb, + fs->c.bytestream_start + fs->ac_byte_count, + (fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count) * 8); + } + + av_assert1(width && height); + if (f->colorspace == 0) { + const int chroma_width = -((-width) >> f->chroma_h_shift); + const int chroma_height = -((-height) >> f->chroma_v_shift); + const int cx = x >> f->chroma_h_shift; + const int cy = y >> f->chroma_v_shift; + decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0); + + if (f->chroma_planes) { + decode_plane(fs, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1); + decode_plane(fs, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1); + } + if (fs->transparency) + decode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2); + } else { + uint8_t *planes[3] = { p->data[0] + ps * x + y * p->linesize[0], + p->data[1] + ps * x + y * p->linesize[1], + p->data[2] + ps * x + y * p->linesize[2] }; + decode_rgb_frame(fs, planes, width, height, p->linesize); + } + if (fs->ac && f->version > 2) { + int v; + get_rac(&fs->c, (uint8_t[]) { 129 }); + v = fs->c.bytestream_end - fs->c.bytestream - 2 - 5*f->ec; + if (v) { + av_log(f->avctx, AV_LOG_ERROR, "bytestream end mismatching by %d\n", v); + fs->slice_damaged = 1; + } + } + + emms_c(); + + return 0; +} + +static int read_quant_table(RangeCoder *c, int16_t *quant_table, int scale) +{ + int v; + int i = 0; + uint8_t state[CONTEXT_SIZE]; + + memset(state, 128, sizeof(state)); + + for (v = 0; i < 128; v++) { + unsigned len = get_symbol(c, state, 0) + 1; + + if (len > 128 - i) + return AVERROR_INVALIDDATA; + + while (len--) { + quant_table[i] = scale * v; + i++; + } + } + + for (i = 1; i < 128; i++) + quant_table[256 - i] = -quant_table[i]; + quant_table[128] = -quant_table[127]; + + return 2 * v - 1; +} + +static int read_quant_tables(RangeCoder *c, + int16_t quant_table[MAX_CONTEXT_INPUTS][256]) +{ + int i; + int context_count = 1; + + for (i = 0; i < 5; i++) { + context_count *= read_quant_table(c, quant_table[i], context_count); + if (context_count > 32768U) { + return AVERROR_INVALIDDATA; + } + } + return (context_count + 1) / 2; +} + +static int read_extra_header(FFV1Context *f) +{ + RangeCoder *const c = &f->c; + uint8_t state[CONTEXT_SIZE]; + int i, j, k, ret; + uint8_t state2[32][CONTEXT_SIZE]; + + memset(state2, 128, sizeof(state2)); + memset(state, 128, sizeof(state)); + + ff_init_range_decoder(c, f->avctx->extradata, f->avctx->extradata_size); + ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8); + + f->version = get_symbol(c, state, 0); + if (f->version > 2) { + c->bytestream_end -= 4; + f->minor_version = get_symbol(c, state, 0); + } + f->ac = f->avctx->coder_type = get_symbol(c, state, 0); + if (f->ac > 1) { + for (i = 1; i < 256; i++) + f->state_transition[i] = get_symbol(c, state, 1) + c->one_state[i]; + } + + f->colorspace = get_symbol(c, state, 0); //YUV cs type + f->avctx->bits_per_raw_sample = get_symbol(c, state, 0); + f->chroma_planes = get_rac(c, state); + f->chroma_h_shift = get_symbol(c, state, 0); + f->chroma_v_shift = get_symbol(c, state, 0); + f->transparency = get_rac(c, state); + f->plane_count = 2 + f->transparency; + f->num_h_slices = 1 + get_symbol(c, state, 0); + f->num_v_slices = 1 + get_symbol(c, state, 0); + + if (f->num_h_slices > (unsigned)f->width || !f->num_h_slices || + f->num_v_slices > (unsigned)f->height || !f->num_v_slices + ) { + av_log(f->avctx, AV_LOG_ERROR, "slice count invalid\n"); + return AVERROR_INVALIDDATA; + } + + f->quant_table_count = get_symbol(c, state, 0); + if (f->quant_table_count > (unsigned)MAX_QUANT_TABLES) + return AVERROR_INVALIDDATA; + + for (i = 0; i < f->quant_table_count; i++) { + f->context_count[i] = read_quant_tables(c, f->quant_tables[i]); + if (f->context_count[i] < 0) { + av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n"); + return AVERROR_INVALIDDATA; + } + } + if ((ret = ffv1_allocate_initial_states(f)) < 0) + return ret; + + for (i = 0; i < f->quant_table_count; i++) + if (get_rac(c, state)) { + for (j = 0; j < f->context_count[i]; j++) + for (k = 0; k < CONTEXT_SIZE; k++) { + int pred = j ? f->initial_states[i][j - 1][k] : 128; + f->initial_states[i][j][k] = + (pred + get_symbol(c, state2[k], 1)) & 0xFF; + } + } + + if (f->version > 2) { + f->ec = get_symbol(c, state, 0); + } + + if (f->version > 2) { + unsigned v; + v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, + f->avctx->extradata, f->avctx->extradata_size); + if (v) { + av_log(f->avctx, AV_LOG_ERROR, "CRC mismatch %X!\n", v); + return AVERROR_INVALIDDATA; + } + } + + return 0; +} + +static int read_header(FFV1Context *f) +{ + uint8_t state[CONTEXT_SIZE]; + int i, j, context_count = -1; //-1 to avoid warning + RangeCoder *const c = &f->slice_context[0]->c; + + memset(state, 128, sizeof(state)); + + if (f->version < 2) { + unsigned v= get_symbol(c, state, 0); + if (v >= 2) { + av_log(f->avctx, AV_LOG_ERROR, "invalid version %d in ver01 header\n", v); + return AVERROR_INVALIDDATA; + } + f->version = v; + f->ac = f->avctx->coder_type = get_symbol(c, state, 0); + if (f->ac > 1) { + for (i = 1; i < 256; i++) + f->state_transition[i] = get_symbol(c, state, 1) + c->one_state[i]; + } + + f->colorspace = get_symbol(c, state, 0); //YUV cs type + + if (f->version > 0) + f->avctx->bits_per_raw_sample = get_symbol(c, state, 0); + + f->chroma_planes = get_rac(c, state); + f->chroma_h_shift = get_symbol(c, state, 0); + f->chroma_v_shift = get_symbol(c, state, 0); + f->transparency = get_rac(c, state); + f->plane_count = 2 + f->transparency; + } + + if (f->colorspace == 0) { + if (!f->transparency && !f->chroma_planes) { + if (f->avctx->bits_per_raw_sample <= 8) + f->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + else + f->avctx->pix_fmt = AV_PIX_FMT_GRAY16; + } else if (f->avctx->bits_per_raw_sample<=8 && !f->transparency) { + switch(16 * f->chroma_h_shift + f->chroma_v_shift) { + case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P; break; + case 0x01: f->avctx->pix_fmt = AV_PIX_FMT_YUV440P; break; + case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P; break; + case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P; break; + case 0x20: f->avctx->pix_fmt = AV_PIX_FMT_YUV411P; break; + case 0x22: f->avctx->pix_fmt = AV_PIX_FMT_YUV410P; break; + default: + av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(ENOSYS); + } + } else if (f->avctx->bits_per_raw_sample <= 8 && f->transparency) { + switch(16*f->chroma_h_shift + f->chroma_v_shift) { + case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUVA444P; break; + case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUVA422P; break; + case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUVA420P; break; + default: + av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(ENOSYS); + } + } else if (f->avctx->bits_per_raw_sample == 9) { + f->packed_at_lsb = 1; + switch(16 * f->chroma_h_shift + f->chroma_v_shift) { + case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P9; break; + case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P9; break; + case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P9; break; + default: + av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(ENOSYS); + } + } else if (f->avctx->bits_per_raw_sample == 10) { + f->packed_at_lsb = 1; + switch(16 * f->chroma_h_shift + f->chroma_v_shift) { + case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P10; break; + case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P10; break; + case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P10; break; + default: + av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(ENOSYS); + } + } else { + switch(16 * f->chroma_h_shift + f->chroma_v_shift) { + case 0x00: f->avctx->pix_fmt = AV_PIX_FMT_YUV444P16; break; + case 0x10: f->avctx->pix_fmt = AV_PIX_FMT_YUV422P16; break; + case 0x11: f->avctx->pix_fmt = AV_PIX_FMT_YUV420P16; break; + default: + av_log(f->avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(ENOSYS); + } + } + } else if (f->colorspace == 1) { + if (f->chroma_h_shift || f->chroma_v_shift) { + av_log(f->avctx, AV_LOG_ERROR, + "chroma subsampling not supported in this colorspace\n"); + return AVERROR(ENOSYS); + } + if ( f->avctx->bits_per_raw_sample == 9) + f->avctx->pix_fmt = AV_PIX_FMT_GBRP9; + else if (f->avctx->bits_per_raw_sample == 10) + f->avctx->pix_fmt = AV_PIX_FMT_GBRP10; + else if (f->avctx->bits_per_raw_sample == 12) + f->avctx->pix_fmt = AV_PIX_FMT_GBRP12; + else if (f->avctx->bits_per_raw_sample == 14) + f->avctx->pix_fmt = AV_PIX_FMT_GBRP14; + else + if (f->transparency) f->avctx->pix_fmt = AV_PIX_FMT_RGB32; + else f->avctx->pix_fmt = AV_PIX_FMT_0RGB32; + } else { + av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n"); + return AVERROR(ENOSYS); + } + + av_dlog(f->avctx, "%d %d %d\n", + f->chroma_h_shift, f->chroma_v_shift, f->avctx->pix_fmt); + if (f->version < 2) { + context_count = read_quant_tables(c, f->quant_table); + if (context_count < 0) { + av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n"); + return AVERROR_INVALIDDATA; + } + } else if (f->version < 3) { + f->slice_count = get_symbol(c, state, 0); + } else { + const uint8_t *p = c->bytestream_end; + for (f->slice_count = 0; + f->slice_count < MAX_SLICES && 3 < p - c->bytestream_start; + f->slice_count++) { + int trailer = 3 + 5*!!f->ec; + int size = AV_RB24(p-trailer); + if (size + trailer > p - c->bytestream_start) + break; + p -= size + trailer; + } + } + if (f->slice_count > (unsigned)MAX_SLICES || f->slice_count <= 0) { + av_log(f->avctx, AV_LOG_ERROR, "slice count %d is invalid\n", f->slice_count); + return AVERROR_INVALIDDATA; + } + + for (j = 0; j < f->slice_count; j++) { + FFV1Context *fs = f->slice_context[j]; + fs->ac = f->ac; + fs->packed_at_lsb = f->packed_at_lsb; + + fs->slice_damaged = 0; + + if (f->version == 2) { + fs->slice_x = get_symbol(c, state, 0) * f->width ; + fs->slice_y = get_symbol(c, state, 0) * f->height; + fs->slice_width = (get_symbol(c, state, 0) + 1) * f->width + fs->slice_x; + fs->slice_height = (get_symbol(c, state, 0) + 1) * f->height + fs->slice_y; + + fs->slice_x /= f->num_h_slices; + fs->slice_y /= f->num_v_slices; + fs->slice_width = fs->slice_width / f->num_h_slices - fs->slice_x; + fs->slice_height = fs->slice_height / f->num_v_slices - fs->slice_y; + if ((unsigned)fs->slice_width > f->width || + (unsigned)fs->slice_height > f->height) + return AVERROR_INVALIDDATA; + if ( (unsigned)fs->slice_x + (uint64_t)fs->slice_width > f->width + || (unsigned)fs->slice_y + (uint64_t)fs->slice_height > f->height) + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < f->plane_count; i++) { + PlaneContext *const p = &fs->plane[i]; + + if (f->version == 2) { + int idx = get_symbol(c, state, 0); + if (idx > (unsigned)f->quant_table_count) { + av_log(f->avctx, AV_LOG_ERROR, + "quant_table_index out of range\n"); + return AVERROR_INVALIDDATA; + } + p->quant_table_index = idx; + memcpy(p->quant_table, f->quant_tables[idx], + sizeof(p->quant_table)); + context_count = f->context_count[idx]; + } else { + memcpy(p->quant_table, f->quant_table, sizeof(p->quant_table)); + } + + if (f->version <= 2) { + av_assert0(context_count >= 0); + if (p->context_count < context_count) { + av_freep(&p->state); + av_freep(&p->vlc_state); + } + p->context_count = context_count; + } + } + } + return 0; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + FFV1Context *f = avctx->priv_data; + int ret; + + if ((ret = ffv1_common_init(avctx)) < 0) + return ret; + + if (avctx->extradata && (ret = read_extra_header(f)) < 0) + return ret; + + if ((ret = ffv1_init_slice_contexts(f)) < 0) + return ret; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + FFV1Context *f = avctx->priv_data; + RangeCoder *const c = &f->slice_context[0]->c; + int i, ret; + uint8_t keystate = 128; + const uint8_t *buf_p; + AVFrame *const p = data; + + f->cur = p; + + ff_init_range_decoder(c, buf, buf_size); + ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8); + + p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P + if (get_rac(c, &keystate)) { + p->key_frame = 1; + f->key_frame_ok = 0; + if ((ret = read_header(f)) < 0) + return ret; + f->key_frame_ok = 1; + } else { + if (!f->key_frame_ok) { + av_log(avctx, AV_LOG_ERROR, + "Cannot decode non-keyframe without valid keyframe\n"); + return AVERROR_INVALIDDATA; + } + p->key_frame = 0; + } + + if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(avctx, AV_LOG_DEBUG, "ver:%d keyframe:%d coder:%d ec:%d slices:%d bps:%d\n", + f->version, p->key_frame, f->ac, f->ec, f->slice_count, f->avctx->bits_per_raw_sample); + + buf_p = buf + buf_size; + for (i = f->slice_count - 1; i >= 0; i--) { + FFV1Context *fs = f->slice_context[i]; + int trailer = 3 + 5*!!f->ec; + int v; + + if (i || f->version > 2) v = AV_RB24(buf_p-trailer) + trailer; + else v = buf_p - c->bytestream_start; + if (buf_p - c->bytestream_start < v) { + av_log(avctx, AV_LOG_ERROR, "Slice pointer chain broken\n"); + return AVERROR_INVALIDDATA; + } + buf_p -= v; + + if (f->ec) { + unsigned crc = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, buf_p, v); + if (crc) { + int64_t ts = avpkt->pts != AV_NOPTS_VALUE ? avpkt->pts : avpkt->dts; + av_log(f->avctx, AV_LOG_ERROR, "CRC mismatch %X!", crc); + if (ts != AV_NOPTS_VALUE && avctx->pkt_timebase.num) { + av_log(f->avctx, AV_LOG_ERROR, "at %f seconds\n", ts*av_q2d(avctx->pkt_timebase)); + } else if (ts != AV_NOPTS_VALUE) { + av_log(f->avctx, AV_LOG_ERROR, "at %"PRId64"\n", ts); + } else { + av_log(f->avctx, AV_LOG_ERROR, "\n"); + } + fs->slice_damaged = 1; + } + } + + if (i) { + ff_init_range_decoder(&fs->c, buf_p, v); + } else + fs->c.bytestream_end = (uint8_t *)(buf_p + v); + + fs->cur = p; + } + + avctx->execute(avctx, + decode_slice, + &f->slice_context[0], + NULL, + f->slice_count, + sizeof(void*)); + + for (i = f->slice_count - 1; i >= 0; i--) { + FFV1Context *fs = f->slice_context[i]; + int j; + if (fs->slice_damaged && f->last_picture.data[0]) { + const uint8_t *src[4]; + uint8_t *dst[4]; + for (j = 0; j < 4; j++) { + int sh = (j==1 || j==2) ? f->chroma_h_shift : 0; + int sv = (j==1 || j==2) ? f->chroma_v_shift : 0; + dst[j] = p->data[j] + p->linesize[j]* + (fs->slice_y>>sv) + (fs->slice_x>>sh); + src[j] = f->last_picture.data[j] + f->last_picture.linesize[j]* + (fs->slice_y>>sv) + (fs->slice_x>>sh); + } + av_image_copy(dst, p->linesize, (const uint8_t **)src, + f->last_picture.linesize, + avctx->pix_fmt, + fs->slice_width, + fs->slice_height); + } + } + + f->picture_number++; + + av_frame_unref(&f->last_picture); + if ((ret = av_frame_ref(&f->last_picture, p)) < 0) + return ret; + f->cur = NULL; + + *got_frame = 1; + + return buf_size; +} + +AVCodec ff_ffv1_decoder = { + .name = "ffv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FFV1, + .priv_data_size = sizeof(FFV1Context), + .init = decode_init, + .close = ffv1_close, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/ | + CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), +}; diff --git a/ffmpeg/libavcodec/ffv1enc.c b/ffmpeg/libavcodec/ffv1enc.c new file mode 100644 index 0000000..70fcd65 --- /dev/null +++ b/ffmpeg/libavcodec/ffv1enc.c @@ -0,0 +1,1169 @@ +/* + * FFV1 encoder + * + * Copyright (c) 2003-2012 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 + */ + +/** + * @file + * FF Video Codec 1 (a lossless codec) encoder + */ + +#include "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/timer.h" +#include "avcodec.h" +#include "internal.h" +#include "put_bits.h" +#include "rangecoder.h" +#include "golomb.h" +#include "mathops.h" +#include "ffv1.h" + +static const int8_t quant5_10bit[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, +}; + +static const int8_t quant5[256] = { + 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, +}; + +static const int8_t quant9_10bit[256] = { + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -0, -0, -0, -0, +}; + +static const int8_t quant11[256] = { + 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -4, -4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, -4, -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -1, +}; + +static const uint8_t ver2_state[256] = { + 0, 10, 10, 10, 10, 16, 16, 16, 28, 16, 16, 29, 42, 49, 20, 49, + 59, 25, 26, 26, 27, 31, 33, 33, 33, 34, 34, 37, 67, 38, 39, 39, + 40, 40, 41, 79, 43, 44, 45, 45, 48, 48, 64, 50, 51, 52, 88, 52, + 53, 74, 55, 57, 58, 58, 74, 60, 101, 61, 62, 84, 66, 66, 68, 69, + 87, 82, 71, 97, 73, 73, 82, 75, 111, 77, 94, 78, 87, 81, 83, 97, + 85, 83, 94, 86, 99, 89, 90, 99, 111, 92, 93, 134, 95, 98, 105, 98, + 105, 110, 102, 108, 102, 118, 103, 106, 106, 113, 109, 112, 114, 112, 116, 125, + 115, 116, 117, 117, 126, 119, 125, 121, 121, 123, 145, 124, 126, 131, 127, 129, + 165, 130, 132, 138, 133, 135, 145, 136, 137, 139, 146, 141, 143, 142, 144, 148, + 147, 155, 151, 149, 151, 150, 152, 157, 153, 154, 156, 168, 158, 162, 161, 160, + 172, 163, 169, 164, 166, 184, 167, 170, 177, 174, 171, 173, 182, 176, 180, 178, + 175, 189, 179, 181, 186, 183, 192, 185, 200, 187, 191, 188, 190, 197, 193, 196, + 197, 194, 195, 196, 198, 202, 199, 201, 210, 203, 207, 204, 205, 206, 208, 214, + 209, 211, 221, 212, 213, 215, 224, 216, 217, 218, 219, 220, 222, 228, 223, 225, + 226, 224, 227, 229, 240, 230, 231, 232, 233, 234, 235, 236, 238, 239, 237, 242, + 241, 243, 242, 244, 245, 246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 255, +}; + +static void find_best_state(uint8_t best_state[256][256], + const uint8_t one_state[256]) +{ + int i, j, k, m; + double l2tab[256]; + + for (i = 1; i < 256; i++) + l2tab[i] = log2(i / 256.0); + + for (i = 0; i < 256; i++) { + double best_len[256]; + double p = i / 256.0; + + for (j = 0; j < 256; j++) + best_len[j] = 1 << 30; + + for (j = FFMAX(i - 10, 1); j < FFMIN(i + 11, 256); j++) { + double occ[256] = { 0 }; + double len = 0; + occ[j] = 1.0; + for (k = 0; k < 256; k++) { + double newocc[256] = { 0 }; + for (m = 1; m < 256; m++) + if (occ[m]) { + len -=occ[m]*( p *l2tab[ m] + + (1-p)*l2tab[256-m]); + } + if (len < best_len[k]) { + best_len[k] = len; + best_state[i][k] = j; + } + for (m = 0; m < 256; m++) + if (occ[m]) { + newocc[ one_state[ m]] += occ[m] * p; + newocc[256 - one_state[256 - m]] += occ[m] * (1 - p); + } + memcpy(occ, newocc, sizeof(occ)); + } + } + } +} + +static av_always_inline av_flatten void put_symbol_inline(RangeCoder *c, + uint8_t *state, int v, + int is_signed, + uint64_t rc_stat[256][2], + uint64_t rc_stat2[32][2]) +{ + int i; + +#define put_rac(C, S, B) \ + do { \ + if (rc_stat) { \ + rc_stat[*(S)][B]++; \ + rc_stat2[(S) - state][B]++; \ + } \ + put_rac(C, S, B); \ + } while (0) + + if (v) { + const int a = FFABS(v); + const int e = av_log2(a); + put_rac(c, state + 0, 0); + if (e <= 9) { + for (i = 0; i < e; i++) + put_rac(c, state + 1 + i, 1); // 1..10 + put_rac(c, state + 1 + i, 0); + + for (i = e - 1; i >= 0; i--) + put_rac(c, state + 22 + i, (a >> i) & 1); // 22..31 + + if (is_signed) + put_rac(c, state + 11 + e, v < 0); // 11..21 + } else { + for (i = 0; i < e; i++) + put_rac(c, state + 1 + FFMIN(i, 9), 1); // 1..10 + put_rac(c, state + 1 + 9, 0); + + for (i = e - 1; i >= 0; i--) + put_rac(c, state + 22 + FFMIN(i, 9), (a >> i) & 1); // 22..31 + + if (is_signed) + put_rac(c, state + 11 + 10, v < 0); // 11..21 + } + } else { + put_rac(c, state + 0, 1); + } +#undef put_rac +} + +static av_noinline void put_symbol(RangeCoder *c, uint8_t *state, + int v, int is_signed) +{ + put_symbol_inline(c, state, v, is_signed, NULL, NULL); +} + + +static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state, + int v, int bits) +{ + int i, k, code; + v = fold(v - state->bias, bits); + + i = state->count; + k = 0; + while (i < state->error_sum) { // FIXME: optimize + k++; + i += i; + } + + av_assert2(k <= 13); + +#if 0 // JPEG LS + if (k == 0 && 2 * state->drift <= -state->count) + code = v ^ (-1); + else + code = v; +#else + code = v ^ ((2 * state->drift + state->count) >> 31); +#endif + + av_dlog(NULL, "v:%d/%d bias:%d error:%d drift:%d count:%d k:%d\n", v, code, + state->bias, state->error_sum, state->drift, state->count, k); + set_sr_golomb(pb, code, k, 12, bits); + + update_vlc_state(state, v); +} + +static av_always_inline int encode_line(FFV1Context *s, int w, + int16_t *sample[3], + int plane_index, int bits) +{ + PlaneContext *const p = &s->plane[plane_index]; + RangeCoder *const c = &s->c; + int x; + int run_index = s->run_index; + int run_count = 0; + int run_mode = 0; + + if (s->ac) { + if (c->bytestream_end - c->bytestream < w * 20) { + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return AVERROR_INVALIDDATA; + } + } else { + if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < w * 4) { + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return AVERROR_INVALIDDATA; + } + } + + for (x = 0; x < w; x++) { + int diff, context; + + context = get_context(p, sample[0] + x, sample[1] + x, sample[2] + x); + diff = sample[0][x] - predict(sample[0] + x, sample[1] + x); + + if (context < 0) { + context = -context; + diff = -diff; + } + + diff = fold(diff, bits); + + if (s->ac) { + if (s->flags & CODEC_FLAG_PASS1) { + put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat, + s->rc_stat2[p->quant_table_index][context]); + } else { + put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL); + } + } else { + if (context == 0) + run_mode = 1; + + if (run_mode) { + if (diff) { + while (run_count >= 1 << ff_log2_run[run_index]) { + run_count -= 1 << ff_log2_run[run_index]; + run_index++; + put_bits(&s->pb, 1, 1); + } + + put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count); + if (run_index) + run_index--; + run_count = 0; + run_mode = 0; + if (diff > 0) + diff--; + } else { + run_count++; + } + } + + av_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", + run_count, run_index, run_mode, x, + (int)put_bits_count(&s->pb)); + + if (run_mode == 0) + put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits); + } + } + if (run_mode) { + while (run_count >= 1 << ff_log2_run[run_index]) { + run_count -= 1 << ff_log2_run[run_index]; + run_index++; + put_bits(&s->pb, 1, 1); + } + + if (run_count) + put_bits(&s->pb, 1, 1); + } + s->run_index = run_index; + + return 0; +} + +static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h, + int stride, int plane_index) +{ + int x, y, i; + const int ring_size = s->avctx->context_model ? 3 : 2; + int16_t *sample[3]; + s->run_index = 0; + + memset(s->sample_buffer, 0, ring_size * (w + 6) * sizeof(*s->sample_buffer)); + + for (y = 0; y < h; y++) { + for (i = 0; i < ring_size; i++) + sample[i] = s->sample_buffer + (w + 6) * ((h + i - y) % ring_size) + 3; + + sample[0][-1]= sample[1][0 ]; + sample[1][ w]= sample[1][w-1]; +// { START_TIMER + if (s->bits_per_raw_sample <= 8) { + for (x = 0; x < w; x++) + sample[0][x] = src[x + stride * y]; + encode_line(s, w, sample, plane_index, 8); + } else { + if (s->packed_at_lsb) { + for (x = 0; x < w; x++) { + sample[0][x] = ((uint16_t*)(src + stride*y))[x]; + } + } else { + for (x = 0; x < w; x++) { + sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - s->bits_per_raw_sample); + } + } + encode_line(s, w, sample, plane_index, s->bits_per_raw_sample); + } +// STOP_TIMER("encode line") } + } +} + +static void encode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) +{ + int x, y, p, i; + const int ring_size = s->avctx->context_model ? 3 : 2; + int16_t *sample[4][3]; + int lbd = s->bits_per_raw_sample <= 8; + int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8; + int offset = 1 << bits; + + s->run_index = 0; + + memset(s->sample_buffer, 0, ring_size * MAX_PLANES * + (w + 6) * sizeof(*s->sample_buffer)); + + for (y = 0; y < h; y++) { + for (i = 0; i < ring_size; i++) + for (p = 0; p < MAX_PLANES; p++) + sample[p][i]= s->sample_buffer + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3; + + for (x = 0; x < w; x++) { + int b, g, r, av_uninit(a); + if (lbd) { + unsigned v = *((uint32_t*)(src[0] + x*4 + stride[0]*y)); + b = v & 0xFF; + g = (v >> 8) & 0xFF; + r = (v >> 16) & 0xFF; + a = v >> 24; + } else { + b = *((uint16_t*)(src[0] + x*2 + stride[0]*y)); + g = *((uint16_t*)(src[1] + x*2 + stride[1]*y)); + r = *((uint16_t*)(src[2] + x*2 + stride[2]*y)); + } + + b -= g; + r -= g; + g += (b + r) >> 2; + b += offset; + r += offset; + + sample[0][0][x] = g; + sample[1][0][x] = b; + sample[2][0][x] = r; + sample[3][0][x] = a; + } + for (p = 0; p < 3 + s->transparency; p++) { + sample[p][0][-1] = sample[p][1][0 ]; + sample[p][1][ w] = sample[p][1][w-1]; + if (lbd) + encode_line(s, w, sample[p], (p + 1) / 2, 9); + else + encode_line(s, w, sample[p], (p + 1) / 2, bits + 1); + } + } +} + +static void write_quant_table(RangeCoder *c, int16_t *quant_table) +{ + int last = 0; + int i; + uint8_t state[CONTEXT_SIZE]; + memset(state, 128, sizeof(state)); + + for (i = 1; i < 128; i++) + if (quant_table[i] != quant_table[i - 1]) { + put_symbol(c, state, i - last - 1, 0); + last = i; + } + put_symbol(c, state, i - last - 1, 0); +} + +static void write_quant_tables(RangeCoder *c, + int16_t quant_table[MAX_CONTEXT_INPUTS][256]) +{ + int i; + for (i = 0; i < 5; i++) + write_quant_table(c, quant_table[i]); +} + +static void write_header(FFV1Context *f) +{ + uint8_t state[CONTEXT_SIZE]; + int i, j; + RangeCoder *const c = &f->slice_context[0]->c; + + memset(state, 128, sizeof(state)); + + if (f->version < 2) { + put_symbol(c, state, f->version, 0); + put_symbol(c, state, f->ac, 0); + if (f->ac > 1) { + for (i = 1; i < 256; i++) + put_symbol(c, state, + f->state_transition[i] - c->one_state[i], 1); + } + put_symbol(c, state, f->colorspace, 0); //YUV cs type + if (f->version > 0) + put_symbol(c, state, f->bits_per_raw_sample, 0); + put_rac(c, state, f->chroma_planes); + put_symbol(c, state, f->chroma_h_shift, 0); + put_symbol(c, state, f->chroma_v_shift, 0); + put_rac(c, state, f->transparency); + + write_quant_tables(c, f->quant_table); + } else if (f->version < 3) { + put_symbol(c, state, f->slice_count, 0); + for (i = 0; i < f->slice_count; i++) { + FFV1Context *fs = f->slice_context[i]; + put_symbol(c, state, + (fs->slice_x + 1) * f->num_h_slices / f->width, 0); + put_symbol(c, state, + (fs->slice_y + 1) * f->num_v_slices / f->height, 0); + put_symbol(c, state, + (fs->slice_width + 1) * f->num_h_slices / f->width - 1, + 0); + put_symbol(c, state, + (fs->slice_height + 1) * f->num_v_slices / f->height - 1, + 0); + for (j = 0; j < f->plane_count; j++) { + put_symbol(c, state, f->plane[j].quant_table_index, 0); + av_assert0(f->plane[j].quant_table_index == f->avctx->context_model); + } + } + } +} + +static int write_extradata(FFV1Context *f) +{ + RangeCoder *const c = &f->c; + uint8_t state[CONTEXT_SIZE]; + int i, j, k; + uint8_t state2[32][CONTEXT_SIZE]; + unsigned v; + + memset(state2, 128, sizeof(state2)); + memset(state, 128, sizeof(state)); + + f->avctx->extradata_size = 10000 + 4 + + (11 * 11 * 5 * 5 * 5 + 11 * 11 * 11) * 32; + f->avctx->extradata = av_malloc(f->avctx->extradata_size); + ff_init_range_encoder(c, f->avctx->extradata, f->avctx->extradata_size); + ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8); + + put_symbol(c, state, f->version, 0); + if (f->version > 2) { + if (f->version == 3) + f->minor_version = 2; + put_symbol(c, state, f->minor_version, 0); + } + + put_symbol(c, state, f->ac, 0); + if (f->ac > 1) + for (i = 1; i < 256; i++) + put_symbol(c, state, f->state_transition[i] - c->one_state[i], 1); + + put_symbol(c, state, f->colorspace, 0); // YUV cs type + put_symbol(c, state, f->bits_per_raw_sample, 0); + put_rac(c, state, f->chroma_planes); + put_symbol(c, state, f->chroma_h_shift, 0); + put_symbol(c, state, f->chroma_v_shift, 0); + put_rac(c, state, f->transparency); + put_symbol(c, state, f->num_h_slices - 1, 0); + put_symbol(c, state, f->num_v_slices - 1, 0); + + put_symbol(c, state, f->quant_table_count, 0); + for (i = 0; i < f->quant_table_count; i++) + write_quant_tables(c, f->quant_tables[i]); + + for (i = 0; i < f->quant_table_count; i++) { + for (j = 0; j < f->context_count[i] * CONTEXT_SIZE; j++) + if (f->initial_states[i] && f->initial_states[i][0][j] != 128) + break; + if (j < f->context_count[i] * CONTEXT_SIZE) { + put_rac(c, state, 1); + for (j = 0; j < f->context_count[i]; j++) + for (k = 0; k < CONTEXT_SIZE; k++) { + int pred = j ? f->initial_states[i][j - 1][k] : 128; + put_symbol(c, state2[k], + (int8_t)(f->initial_states[i][j][k] - pred), 1); + } + } else { + put_rac(c, state, 0); + } + } + + if (f->version > 2) { + put_symbol(c, state, f->ec, 0); + } + + f->avctx->extradata_size = ff_rac_terminate(c); + v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, f->avctx->extradata, f->avctx->extradata_size); + AV_WL32(f->avctx->extradata + f->avctx->extradata_size, v); + f->avctx->extradata_size += 4; + + return 0; +} + +static int sort_stt(FFV1Context *s, uint8_t stt[256]) +{ + int i, i2, changed, print = 0; + + do { + changed = 0; + for (i = 12; i < 244; i++) { + for (i2 = i + 1; i2 < 245 && i2 < i + 4; i2++) { + +#define COST(old, new) \ + s->rc_stat[old][0] * -log2((256 - (new)) / 256.0) + \ + s->rc_stat[old][1] * -log2((new) / 256.0) + +#define COST2(old, new) \ + COST(old, new) + COST(256 - (old), 256 - (new)) + + double size0 = COST2(i, i) + COST2(i2, i2); + double sizeX = COST2(i, i2) + COST2(i2, i); + if (size0 - sizeX > size0*(1e-14) && i != 128 && i2 != 128) { + int j; + FFSWAP(int, stt[i], stt[i2]); + FFSWAP(int, s->rc_stat[i][0], s->rc_stat[i2][0]); + FFSWAP(int, s->rc_stat[i][1], s->rc_stat[i2][1]); + if (i != 256 - i2) { + FFSWAP(int, stt[256 - i], stt[256 - i2]); + FFSWAP(int, s->rc_stat[256 - i][0], s->rc_stat[256 - i2][0]); + FFSWAP(int, s->rc_stat[256 - i][1], s->rc_stat[256 - i2][1]); + } + for (j = 1; j < 256; j++) { + if (stt[j] == i) + stt[j] = i2; + else if (stt[j] == i2) + stt[j] = i; + if (i != 256 - i2) { + if (stt[256 - j] == 256 - i) + stt[256 - j] = 256 - i2; + else if (stt[256 - j] == 256 - i2) + stt[256 - j] = 256 - i; + } + } + print = changed = 1; + } + } + } + } while (changed); + return print; +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + FFV1Context *s = avctx->priv_data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int i, j, k, m, ret; + + ffv1_common_init(avctx); + + s->version = 0; + + if ((avctx->flags & (CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)) || avctx->slices>1) + s->version = FFMAX(s->version, 2); + + if (avctx->level == 3) { + s->version = 3; + } + + if (s->ec < 0) { + s->ec = (s->version >= 3); + } + + if (s->version >= 2 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(avctx, AV_LOG_ERROR, "Version 2 needed for requested features but version 2 is experimental and not enabled\n"); + return AVERROR_INVALIDDATA; + } + + s->ac = avctx->coder_type > 0 ? 2 : 0; + + s->plane_count = 3; + switch(avctx->pix_fmt) { + case AV_PIX_FMT_YUV444P9: + case AV_PIX_FMT_YUV422P9: + case AV_PIX_FMT_YUV420P9: + if (!avctx->bits_per_raw_sample) + s->bits_per_raw_sample = 9; + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV422P10: + s->packed_at_lsb = 1; + if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) + s->bits_per_raw_sample = 10; + case AV_PIX_FMT_GRAY16: + case AV_PIX_FMT_YUV444P16: + case AV_PIX_FMT_YUV422P16: + case AV_PIX_FMT_YUV420P16: + if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) { + s->bits_per_raw_sample = 16; + } else if (!s->bits_per_raw_sample) { + s->bits_per_raw_sample = avctx->bits_per_raw_sample; + } + if (s->bits_per_raw_sample <= 8) { + av_log(avctx, AV_LOG_ERROR, "bits_per_raw_sample invalid\n"); + return AVERROR_INVALIDDATA; + } + if (!s->ac && avctx->coder_type == -1) { + av_log(avctx, AV_LOG_INFO, "bits_per_raw_sample > 8, forcing coder 1\n"); + s->ac = 2; + } + if (!s->ac) { + av_log(avctx, AV_LOG_ERROR, "bits_per_raw_sample of more than 8 needs -coder 1 currently\n"); + return AVERROR(ENOSYS); + } + s->version = FFMAX(s->version, 1); + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV440P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_YUV410P: + s->chroma_planes = desc->nb_components < 3 ? 0 : 1; + s->colorspace = 0; + break; + case AV_PIX_FMT_YUVA444P: + case AV_PIX_FMT_YUVA422P: + case AV_PIX_FMT_YUVA420P: + s->chroma_planes = 1; + s->colorspace = 0; + s->transparency = 1; + break; + case AV_PIX_FMT_RGB32: + s->colorspace = 1; + s->transparency = 1; + break; + case AV_PIX_FMT_0RGB32: + s->colorspace = 1; + break; + case AV_PIX_FMT_GBRP9: + if (!avctx->bits_per_raw_sample) + s->bits_per_raw_sample = 9; + case AV_PIX_FMT_GBRP10: + if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) + s->bits_per_raw_sample = 10; + case AV_PIX_FMT_GBRP12: + if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) + s->bits_per_raw_sample = 12; + case AV_PIX_FMT_GBRP14: + if (!avctx->bits_per_raw_sample && !s->bits_per_raw_sample) + s->bits_per_raw_sample = 14; + else if (!s->bits_per_raw_sample) + s->bits_per_raw_sample = avctx->bits_per_raw_sample; + s->colorspace = 1; + s->chroma_planes = 1; + s->version = FFMAX(s->version, 1); + break; + default: + av_log(avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(ENOSYS); + } + if (s->transparency) { + av_log(avctx, AV_LOG_WARNING, "Storing alpha plane, this will require a recent FFV1 decoder to playback!\n"); + } + if (avctx->context_model > 1U) { + av_log(avctx, AV_LOG_ERROR, "Invalid context model %d, valid values are 0 and 1\n", avctx->context_model); + return AVERROR(EINVAL); + } + + if (s->ac > 1) + for (i = 1; i < 256; i++) + s->state_transition[i] = ver2_state[i]; + + for (i = 0; i < 256; i++) { + s->quant_table_count = 2; + if (s->bits_per_raw_sample <= 8) { + s->quant_tables[0][0][i]= quant11[i]; + s->quant_tables[0][1][i]= 11*quant11[i]; + s->quant_tables[0][2][i]= 11*11*quant11[i]; + s->quant_tables[1][0][i]= quant11[i]; + s->quant_tables[1][1][i]= 11*quant11[i]; + s->quant_tables[1][2][i]= 11*11*quant5 [i]; + s->quant_tables[1][3][i]= 5*11*11*quant5 [i]; + s->quant_tables[1][4][i]= 5*5*11*11*quant5 [i]; + } else { + s->quant_tables[0][0][i]= quant9_10bit[i]; + s->quant_tables[0][1][i]= 11*quant9_10bit[i]; + s->quant_tables[0][2][i]= 11*11*quant9_10bit[i]; + s->quant_tables[1][0][i]= quant9_10bit[i]; + s->quant_tables[1][1][i]= 11*quant9_10bit[i]; + s->quant_tables[1][2][i]= 11*11*quant5_10bit[i]; + s->quant_tables[1][3][i]= 5*11*11*quant5_10bit[i]; + s->quant_tables[1][4][i]= 5*5*11*11*quant5_10bit[i]; + } + } + s->context_count[0] = (11 * 11 * 11 + 1) / 2; + s->context_count[1] = (11 * 11 * 5 * 5 * 5 + 1) / 2; + memcpy(s->quant_table, s->quant_tables[avctx->context_model], + sizeof(s->quant_table)); + + for (i = 0; i < s->plane_count; i++) { + PlaneContext *const p = &s->plane[i]; + + memcpy(p->quant_table, s->quant_table, sizeof(p->quant_table)); + p->quant_table_index = avctx->context_model; + p->context_count = s->context_count[p->quant_table_index]; + } + + if ((ret = ffv1_allocate_initial_states(s)) < 0) + return ret; + + avctx->coded_frame = &s->picture; + if (!s->transparency) + s->plane_count = 2; + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift); + s->picture_number = 0; + + if (avctx->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) { + for (i = 0; i < s->quant_table_count; i++) { + s->rc_stat2[i] = av_mallocz(s->context_count[i] * + sizeof(*s->rc_stat2[i])); + if (!s->rc_stat2[i]) + return AVERROR(ENOMEM); + } + } + if (avctx->stats_in) { + char *p = avctx->stats_in; + uint8_t best_state[256][256]; + int gob_count = 0; + char *next; + + av_assert0(s->version >= 2); + + for (;;) { + for (j = 0; j < 256; j++) + for (i = 0; i < 2; i++) { + s->rc_stat[j][i] = strtol(p, &next, 0); + if (next == p) { + av_log(avctx, AV_LOG_ERROR, + "2Pass file invalid at %d %d [%s]\n", j, i, p); + return AVERROR_INVALIDDATA; + } + p = next; + } + for (i = 0; i < s->quant_table_count; i++) + for (j = 0; j < s->context_count[i]; j++) { + for (k = 0; k < 32; k++) + for (m = 0; m < 2; m++) { + s->rc_stat2[i][j][k][m] = strtol(p, &next, 0); + if (next == p) { + av_log(avctx, AV_LOG_ERROR, + "2Pass file invalid at %d %d %d %d [%s]\n", + i, j, k, m, p); + return AVERROR_INVALIDDATA; + } + p = next; + } + } + gob_count = strtol(p, &next, 0); + if (next == p || gob_count <= 0) { + av_log(avctx, AV_LOG_ERROR, "2Pass file invalid\n"); + return AVERROR_INVALIDDATA; + } + p = next; + while (*p == '\n' || *p == ' ') + p++; + if (p[0] == 0) + break; + } + sort_stt(s, s->state_transition); + + find_best_state(best_state, s->state_transition); + + for (i = 0; i < s->quant_table_count; i++) { + for (k = 0; k < 32; k++) { + double a=0, b=0; + int jp = 0; + for (j = 0; j < s->context_count[i]; j++) { + double p = 128; + if (s->rc_stat2[i][j][k][0] + s->rc_stat2[i][j][k][1] > 200 && j || a+b > 200) { + if (a+b) + p = 256.0 * b / (a + b); + s->initial_states[i][jp][k] = + best_state[av_clip(round(p), 1, 255)][av_clip((a + b) / gob_count, 0, 255)]; + for(jp++; jpinitial_states[i][jp][k] = s->initial_states[i][jp-1][k]; + a=b=0; + } + a += s->rc_stat2[i][j][k][0]; + b += s->rc_stat2[i][j][k][1]; + if (a+b) { + p = 256.0 * b / (a + b); + } + s->initial_states[i][j][k] = + best_state[av_clip(round(p), 1, 255)][av_clip((a + b) / gob_count, 0, 255)]; + } + } + } + } + + if (s->version > 1) { + s->num_v_slices = (avctx->width > 352 || avctx->height > 288 || !avctx->slices) ? 2 : 1; + for (; s->num_v_slices < 9; s->num_v_slices++) { + for (s->num_h_slices = s->num_v_slices; s->num_h_slices < 2*s->num_v_slices; s->num_h_slices++) { + if (avctx->slices == s->num_h_slices * s->num_v_slices && avctx->slices <= 64 || !avctx->slices) + goto slices_ok; + } + } + av_log(avctx, AV_LOG_ERROR, + "Unsupported number %d of slices requested, please specify a " + "supported number with -slices (ex:4,6,9,12,16, ...)\n", + avctx->slices); + return AVERROR(ENOSYS); +slices_ok: + write_extradata(s); + } + + if ((ret = ffv1_init_slice_contexts(s)) < 0) + return ret; + if ((ret = ffv1_init_slices_state(s)) < 0) + return ret; + +#define STATS_OUT_SIZE 1024 * 1024 * 6 + if (avctx->flags & CODEC_FLAG_PASS1) { + avctx->stats_out = av_mallocz(STATS_OUT_SIZE); + if (!avctx->stats_out) + return AVERROR(ENOMEM); + for (i = 0; i < s->quant_table_count; i++) + for (j = 0; j < s->slice_count; j++) { + FFV1Context *sf = s->slice_context[j]; + av_assert0(!sf->rc_stat2[i]); + sf->rc_stat2[i] = av_mallocz(s->context_count[i] * + sizeof(*sf->rc_stat2[i])); + if (!sf->rc_stat2[i]) + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static void encode_slice_header(FFV1Context *f, FFV1Context *fs) +{ + RangeCoder *c = &fs->c; + uint8_t state[CONTEXT_SIZE]; + int j; + memset(state, 128, sizeof(state)); + + put_symbol(c, state, (fs->slice_x +1)*f->num_h_slices / f->width , 0); + put_symbol(c, state, (fs->slice_y +1)*f->num_v_slices / f->height , 0); + put_symbol(c, state, (fs->slice_width +1)*f->num_h_slices / f->width -1, 0); + put_symbol(c, state, (fs->slice_height+1)*f->num_v_slices / f->height-1, 0); + for (j=0; jplane_count; j++) { + put_symbol(c, state, f->plane[j].quant_table_index, 0); + av_assert0(f->plane[j].quant_table_index == f->avctx->context_model); + } + if (!f->picture.interlaced_frame) + put_symbol(c, state, 3, 0); + else + put_symbol(c, state, 1 + !f->picture.top_field_first, 0); + put_symbol(c, state, f->picture.sample_aspect_ratio.num, 0); + put_symbol(c, state, f->picture.sample_aspect_ratio.den, 0); +} + +static int encode_slice(AVCodecContext *c, void *arg) +{ + FFV1Context *fs = *(void **)arg; + FFV1Context *f = fs->avctx->priv_data; + int width = fs->slice_width; + int height = fs->slice_height; + int x = fs->slice_x; + int y = fs->slice_y; + AVFrame *const p = &f->picture; + const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step_minus1 + 1; + + if (p->key_frame) + ffv1_clear_slice_state(f, fs); + if (f->version > 2) { + encode_slice_header(f, fs); + } + if (!fs->ac) { + if (f->version > 2) + put_rac(&fs->c, (uint8_t[]) { 129 }, 0); + fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&fs->c) : 0; + init_put_bits(&fs->pb, + fs->c.bytestream_start + fs->ac_byte_count, + fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count); + } + + if (f->colorspace == 0) { + const int chroma_width = -((-width) >> f->chroma_h_shift); + const int chroma_height = -((-height) >> f->chroma_v_shift); + const int cx = x >> f->chroma_h_shift; + const int cy = y >> f->chroma_v_shift; + + encode_plane(fs, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0); + + if (f->chroma_planes) { + encode_plane(fs, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1); + encode_plane(fs, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1); + } + if (fs->transparency) + encode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2); + } else { + uint8_t *planes[3] = {p->data[0] + ps*x + y*p->linesize[0], + p->data[1] + ps*x + y*p->linesize[1], + p->data[2] + ps*x + y*p->linesize[2]}; + encode_rgb_frame(fs, planes, width, height, p->linesize); + } + emms_c(); + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + FFV1Context *f = avctx->priv_data; + RangeCoder *const c = &f->slice_context[0]->c; + AVFrame *const p = &f->picture; + int used_count = 0; + uint8_t keystate = 128; + uint8_t *buf_p; + int i, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*((8*2+1+1)*4)/8 + + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + ff_init_range_encoder(c, pkt->data, pkt->size); + ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8); + + *p = *pict; + p->pict_type = AV_PICTURE_TYPE_I; + + if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) { + put_rac(c, &keystate, 1); + p->key_frame = 1; + f->gob_count++; + write_header(f); + } else { + put_rac(c, &keystate, 0); + p->key_frame = 0; + } + + if (f->ac > 1) { + int i; + for (i = 1; i < 256; i++) { + c->one_state[i] = f->state_transition[i]; + c->zero_state[256 - i] = 256 - c->one_state[i]; + } + } + + for (i = 1; i < f->slice_count; i++) { + FFV1Context *fs = f->slice_context[i]; + uint8_t *start = pkt->data + (pkt->size - used_count) * (int64_t)i / f->slice_count; + int len = pkt->size / f->slice_count; + ff_init_range_encoder(&fs->c, start, len); + } + avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL, + f->slice_count, sizeof(void *)); + + buf_p = pkt->data; + for (i = 0; i < f->slice_count; i++) { + FFV1Context *fs = f->slice_context[i]; + int bytes; + + if (fs->ac) { + uint8_t state = 129; + put_rac(&fs->c, &state, 0); + bytes = ff_rac_terminate(&fs->c); + } else { + flush_put_bits(&fs->pb); // FIXME: nicer padding + bytes = fs->ac_byte_count + (put_bits_count(&fs->pb) + 7) / 8; + } + if (i > 0 || f->version > 2) { + av_assert0(bytes < pkt->size / f->slice_count); + memmove(buf_p, fs->c.bytestream_start, bytes); + av_assert0(bytes < (1 << 24)); + AV_WB24(buf_p + bytes, bytes); + bytes += 3; + } + if (f->ec) { + unsigned v; + buf_p[bytes++] = 0; + v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, buf_p, bytes); + AV_WL32(buf_p + bytes, v); + bytes += 4; + } + buf_p += bytes; + } + + if ((avctx->flags & CODEC_FLAG_PASS1) && (f->picture_number & 31) == 0) { + int j, k, m; + char *p = avctx->stats_out; + char *end = p + STATS_OUT_SIZE; + + memset(f->rc_stat, 0, sizeof(f->rc_stat)); + for (i = 0; i < f->quant_table_count; i++) + memset(f->rc_stat2[i], 0, f->context_count[i] * sizeof(*f->rc_stat2[i])); + + for (j = 0; j < f->slice_count; j++) { + FFV1Context *fs = f->slice_context[j]; + for (i = 0; i < 256; i++) { + f->rc_stat[i][0] += fs->rc_stat[i][0]; + f->rc_stat[i][1] += fs->rc_stat[i][1]; + } + for (i = 0; i < f->quant_table_count; i++) { + for (k = 0; k < f->context_count[i]; k++) + for (m = 0; m < 32; m++) { + f->rc_stat2[i][k][m][0] += fs->rc_stat2[i][k][m][0]; + f->rc_stat2[i][k][m][1] += fs->rc_stat2[i][k][m][1]; + } + } + } + + for (j = 0; j < 256; j++) { + snprintf(p, end - p, "%" PRIu64 " %" PRIu64 " ", + f->rc_stat[j][0], f->rc_stat[j][1]); + p += strlen(p); + } + snprintf(p, end - p, "\n"); + + for (i = 0; i < f->quant_table_count; i++) { + for (j = 0; j < f->context_count[i]; j++) + for (m = 0; m < 32; m++) { + snprintf(p, end - p, "%" PRIu64 " %" PRIu64 " ", + f->rc_stat2[i][j][m][0], f->rc_stat2[i][j][m][1]); + p += strlen(p); + } + } + snprintf(p, end - p, "%d\n", f->gob_count); + } else if (avctx->flags & CODEC_FLAG_PASS1) + avctx->stats_out[0] = '\0'; + + f->picture_number++; + pkt->size = buf_p - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY * p->key_frame; + *got_packet = 1; + + return 0; +} + +#define OFFSET(x) offsetof(FFV1Context, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "slicecrc", "Protect slices with CRCs", OFFSET(ec), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { NULL } +}; + +static const AVClass class = { + .class_name = "ffv1 encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault ffv1_defaults[] = { + { "coder", "-1" }, + { NULL }, +}; + +AVCodec ff_ffv1_encoder = { + .name = "ffv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FFV1, + .priv_data_size = sizeof(FFV1Context), + .init = encode_init, + .encode2 = encode_frame, + .close = ffv1_close, + .capabilities = CODEC_CAP_SLICE_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_0RGB32, AV_PIX_FMT_RGB32, AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_GRAY16, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, + AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, + AV_PIX_FMT_NONE + + }, + .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), + .defaults = ffv1_defaults, + .priv_class = &class, +}; diff --git a/ffmpeg/libavcodec/ffwavesynth.c b/ffmpeg/libavcodec/ffwavesynth.c new file mode 100644 index 0000000..4f392f2 --- /dev/null +++ b/ffmpeg/libavcodec/ffwavesynth.c @@ -0,0 +1,484 @@ +/* + * Wavesynth pseudo-codec + * Copyright (c) 2011 Nicolas George + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "avcodec.h" +#include "internal.h" + + +#define SIN_BITS 14 +#define WS_MAX_CHANNELS 32 +#define INF_TS 0x7FFFFFFFFFFFFFFF + +#define PINK_UNIT 128 + +/* + Format of the extradata and packets + + THIS INFORMATION IS NOT PART OF THE PUBLIC API OR ABI. + IT CAN CHANGE WITHOUT NOTIFICATION. + + All numbers are in little endian. + + The codec extradata define a set of intervals with uniform content. + Overlapping intervals are added together. + + extradata: + uint32 number of intervals + ... intervals + + interval: + int64 start timestamp; time_base must be 1/sample_rate; + start timestamps must be in ascending order + int64 end timestamp + uint32 type + uint32 channels mask + ... additional information, depends on type + + sine interval (type fourcc "SINE"): + int32 start frequency, in 1/(1<<16) Hz + int32 end frequency + int32 start amplitude, 1<<16 is the full amplitude + int32 end amplitude + uint32 start phase, 0 is sin(0), 0x20000000 is sin(pi/2), etc.; + n | (1<<31) means to match the phase of previous channel #n + + pink noise interval (type fourcc "NOIS"): + int32 start amplitude + int32 end amplitude + + The input packets encode the time and duration of the requested segment. + + packet: + int64 start timestamp + int32 duration + +*/ + +enum ws_interval_type { + WS_SINE = MKTAG('S','I','N','E'), + WS_NOISE = MKTAG('N','O','I','S'), +}; + +struct ws_interval { + int64_t ts_start, ts_end; + uint64_t phi0, dphi0, ddphi; + uint64_t amp0, damp; + uint64_t phi, dphi, amp; + uint32_t channels; + enum ws_interval_type type; + int next; +}; + +struct wavesynth_context { + int64_t cur_ts; + int64_t next_ts; + int32_t *sin; + AVFrame frame; + struct ws_interval *inter; + uint32_t dither_state; + uint32_t pink_state; + int32_t pink_pool[PINK_UNIT]; + unsigned pink_need, pink_pos; + int nb_inter; + int cur_inter; + int next_inter; +}; + +#define LCG_A 1284865837 +#define LCG_C 4150755663 +#define LCG_AI 849225893 /* A*AI = 1 [mod 1<<32] */ + +static uint32_t lcg_next(uint32_t *s) +{ + *s = *s * LCG_A + LCG_C; + return *s; +} + +static void lcg_seek(uint32_t *s, int64_t dt) +{ + uint32_t a, c, t = *s; + + if (dt >= 0) { + a = LCG_A; + c = LCG_C; + } else { /* coefficients for a step backward */ + a = LCG_AI; + c = (uint32_t)(LCG_AI * LCG_C); + dt = -dt; + } + while (dt) { + if (dt & 1) + t = a * t + c; + c *= a + 1; /* coefficients for a double step */ + a *= a; + dt >>= 1; + } + *s = t; +} + +/* Emulate pink noise by summing white noise at the sampling frequency, + * white noise at half the sampling frequency (each value taken twice), + * etc., with a total of 8 octaves. + * This is known as the Voss-McCartney algorithm. */ + +static void pink_fill(struct wavesynth_context *ws) +{ + int32_t vt[7] = { 0 }, v = 0; + int i, j; + + ws->pink_pos = 0; + if (!ws->pink_need) + return; + for (i = 0; i < PINK_UNIT; i++) { + for (j = 0; j < 7; j++) { + if ((i >> j) & 1) + break; + v -= vt[j]; + vt[j] = (int32_t)lcg_next(&ws->pink_state) >> 3; + v += vt[j]; + } + ws->pink_pool[i] = v + ((int32_t)lcg_next(&ws->pink_state) >> 3); + } + lcg_next(&ws->pink_state); /* so we use exactly 256 steps */ +} + +/** + * @return (1<<64) * a / b, without overflow, if a < b + */ +static uint64_t frac64(uint64_t a, uint64_t b) +{ + uint64_t r = 0; + int i; + + if (b < (uint64_t)1 << 32) { /* b small, use two 32-bits steps */ + a <<= 32; + return ((a / b) << 32) | ((a % b) << 32) / b; + } + if (b < (uint64_t)1 << 48) { /* b medium, use four 16-bits steps */ + for (i = 0; i < 4; i++) { + a <<= 16; + r = (r << 16) | (a / b); + a %= b; + } + return r; + } + for (i = 63; i >= 0; i--) { + if (a >= (uint64_t)1 << 63 || a << 1 >= b) { + r |= (uint64_t)1 << i; + a = (a << 1) - b; + } else { + a <<= 1; + } + } + return r; +} + +static uint64_t phi_at(struct ws_interval *in, int64_t ts) +{ + uint64_t dt = ts - in->ts_start; + uint64_t dt2 = dt & 1 ? /* dt * (dt - 1) / 2 without overflow */ + dt * ((dt - 1) >> 1) : (dt >> 1) * (dt - 1); + return in->phi0 + dt * in->dphi0 + dt2 * in->ddphi; +} + +static void wavesynth_seek(struct wavesynth_context *ws, int64_t ts) +{ + int *last, i; + struct ws_interval *in; + + last = &ws->cur_inter; + for (i = 0; i < ws->nb_inter; i++) { + in = &ws->inter[i]; + if (ts < in->ts_start) + break; + if (ts >= in->ts_end) + continue; + *last = i; + last = &in->next; + in->phi = phi_at(in, ts); + in->dphi = in->dphi0 + (ts - in->ts_start) * in->ddphi; + in->amp = in->amp0 + (ts - in->ts_start) * in->damp; + } + ws->next_inter = i; + ws->next_ts = i < ws->nb_inter ? ws->inter[i].ts_start : INF_TS; + *last = -1; + lcg_seek(&ws->dither_state, ts - ws->cur_ts); + if (ws->pink_need) { + int64_t pink_ts_cur = (ws->cur_ts + PINK_UNIT - 1) & ~(PINK_UNIT - 1); + int64_t pink_ts_next = ts & ~(PINK_UNIT - 1); + int pos = ts & (PINK_UNIT - 1); + lcg_seek(&ws->pink_state, (pink_ts_next - pink_ts_cur) << 1); + if (pos) { + pink_fill(ws); + ws->pink_pos = pos; + } else { + ws->pink_pos = PINK_UNIT; + } + } + ws->cur_ts = ts; +} + +static int wavesynth_parse_extradata(AVCodecContext *avc) +{ + struct wavesynth_context *ws = avc->priv_data; + struct ws_interval *in; + uint8_t *edata, *edata_end; + int32_t f1, f2, a1, a2; + uint32_t phi; + int64_t dphi1, dphi2, dt, cur_ts = -0x8000000000000000; + int i; + + if (avc->extradata_size < 4) + return AVERROR(EINVAL); + edata = avc->extradata; + edata_end = edata + avc->extradata_size; + ws->nb_inter = AV_RL32(edata); + edata += 4; + if (ws->nb_inter < 0) + return AVERROR(EINVAL); + ws->inter = av_calloc(ws->nb_inter, sizeof(*ws->inter)); + if (!ws->inter) + return AVERROR(ENOMEM); + for (i = 0; i < ws->nb_inter; i++) { + in = &ws->inter[i]; + if (edata_end - edata < 24) + return AVERROR(EINVAL); + in->ts_start = AV_RL64(edata + 0); + in->ts_end = AV_RL64(edata + 8); + in->type = AV_RL32(edata + 16); + in->channels = AV_RL32(edata + 20); + edata += 24; + if (in->ts_start < cur_ts || in->ts_end <= in->ts_start) + return AVERROR(EINVAL); + cur_ts = in->ts_start; + dt = in->ts_end - in->ts_start; + switch (in->type) { + case WS_SINE: + if (edata_end - edata < 20) + return AVERROR(EINVAL); + f1 = AV_RL32(edata + 0); + f2 = AV_RL32(edata + 4); + a1 = AV_RL32(edata + 8); + a2 = AV_RL32(edata + 12); + phi = AV_RL32(edata + 16); + edata += 20; + dphi1 = frac64(f1, (int64_t)avc->sample_rate << 16); + dphi2 = frac64(f2, (int64_t)avc->sample_rate << 16); + in->dphi0 = dphi1; + in->ddphi = (dphi2 - dphi1) / dt; + if (phi & 0x80000000) { + phi &= ~0x80000000; + if (phi >= i) + return AVERROR(EINVAL); + in->phi0 = phi_at(&ws->inter[phi], in->ts_start); + } else { + in->phi0 = (uint64_t)phi << 33; + } + break; + case WS_NOISE: + if (edata_end - edata < 8) + return AVERROR(EINVAL); + a1 = AV_RL32(edata + 0); + a2 = AV_RL32(edata + 4); + edata += 8; + break; + default: + return AVERROR(EINVAL); + } + in->amp0 = (int64_t)a1 << 32; + in->damp = (((int64_t)a2 << 32) - ((int64_t)a1 << 32)) / dt; + } + if (edata != edata_end) + return AVERROR(EINVAL); + return 0; +} + +static av_cold int wavesynth_init(AVCodecContext *avc) +{ + struct wavesynth_context *ws = avc->priv_data; + int i, r; + + if (avc->channels > WS_MAX_CHANNELS) { + av_log(avc, AV_LOG_ERROR, + "This implementation is limited to %d channels.\n", + WS_MAX_CHANNELS); + return AVERROR(EINVAL); + } + r = wavesynth_parse_extradata(avc); + if (r < 0) { + av_log(avc, AV_LOG_ERROR, "Invalid intervals definitions.\n"); + goto fail; + } + ws->sin = av_malloc(sizeof(*ws->sin) << SIN_BITS); + if (!ws->sin) { + r = AVERROR(ENOMEM); + goto fail; + } + for (i = 0; i < 1 << SIN_BITS; i++) + ws->sin[i] = floor(32767 * sin(2 * M_PI * i / (1 << SIN_BITS))); + ws->dither_state = MKTAG('D','I','T','H'); + for (i = 0; i < ws->nb_inter; i++) + ws->pink_need += ws->inter[i].type == WS_NOISE; + ws->pink_state = MKTAG('P','I','N','K'); + ws->pink_pos = PINK_UNIT; + avcodec_get_frame_defaults(&ws->frame); + avc->coded_frame = &ws->frame; + wavesynth_seek(ws, 0); + avc->sample_fmt = AV_SAMPLE_FMT_S16; + return 0; + +fail: + av_free(ws->inter); + av_free(ws->sin); + return r; +} + +static void wavesynth_synth_sample(struct wavesynth_context *ws, int64_t ts, + int32_t *channels) +{ + int32_t amp, val, *cv; + struct ws_interval *in; + int i, *last, pink; + uint32_t c, all_ch = 0; + + i = ws->cur_inter; + last = &ws->cur_inter; + if (ws->pink_pos == PINK_UNIT) + pink_fill(ws); + pink = ws->pink_pool[ws->pink_pos++] >> 16; + while (i >= 0) { + in = &ws->inter[i]; + i = in->next; + if (ts >= in->ts_end) { + *last = i; + continue; + } + last = &in->next; + amp = in->amp >> 32; + in->amp += in->damp; + switch (in->type) { + case WS_SINE: + val = amp * ws->sin[in->phi >> (64 - SIN_BITS)]; + in->phi += in->dphi; + in->dphi += in->ddphi; + break; + case WS_NOISE: + val = amp * pink; + break; + default: + val = 0; + } + all_ch |= in->channels; + for (c = in->channels, cv = channels; c; c >>= 1, cv++) + if (c & 1) + *cv += val; + } + val = (int32_t)lcg_next(&ws->dither_state) >> 16; + for (c = all_ch, cv = channels; c; c >>= 1, cv++) + if (c & 1) + *cv += val; +} + +static void wavesynth_enter_intervals(struct wavesynth_context *ws, int64_t ts) +{ + int *last, i; + struct ws_interval *in; + + last = &ws->cur_inter; + for (i = ws->cur_inter; i >= 0; i = ws->inter[i].next) + last = &ws->inter[i].next; + for (i = ws->next_inter; i < ws->nb_inter; i++) { + in = &ws->inter[i]; + if (ts < in->ts_start) + break; + if (ts >= in->ts_end) + continue; + *last = i; + last = &in->next; + in->phi = in->phi0; + in->dphi = in->dphi0; + in->amp = in->amp0; + } + ws->next_inter = i; + ws->next_ts = i < ws->nb_inter ? ws->inter[i].ts_start : INF_TS; + *last = -1; +} + +static int wavesynth_decode(AVCodecContext *avc, void *rframe, int *rgot_frame, + AVPacket *packet) +{ + struct wavesynth_context *ws = avc->priv_data; + int64_t ts; + int duration; + int s, c, r; + int16_t *pcm; + int32_t channels[WS_MAX_CHANNELS]; + + *rgot_frame = 0; + if (packet->size != 12) + return AVERROR_INVALIDDATA; + ts = AV_RL64(packet->data); + if (ts != ws->cur_ts) + wavesynth_seek(ws, ts); + duration = AV_RL32(packet->data + 8); + if (duration <= 0) + return AVERROR(EINVAL); + ws->frame.nb_samples = duration; + r = ff_get_buffer(avc, &ws->frame, 0); + if (r < 0) + return r; + pcm = (int16_t *)ws->frame.data[0]; + for (s = 0; s < duration; s++, ts++) { + memset(channels, 0, avc->channels * sizeof(*channels)); + if (ts >= ws->next_ts) + wavesynth_enter_intervals(ws, ts); + wavesynth_synth_sample(ws, ts, channels); + for (c = 0; c < avc->channels; c++) + *(pcm++) = channels[c] >> 16; + } + ws->cur_ts += duration; + *rgot_frame = 1; + *(AVFrame *)rframe = ws->frame; + return packet->size; +} + +static av_cold int wavesynth_close(AVCodecContext *avc) +{ + struct wavesynth_context *ws = avc->priv_data; + + av_free(ws->sin); + av_free(ws->inter); + return 0; +} + +AVCodec ff_ffwavesynth_decoder = { + .name = "wavesynth", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_FFWAVESYNTH, + .priv_data_size = sizeof(struct wavesynth_context), + .init = wavesynth_init, + .close = wavesynth_close, + .decode = wavesynth_decode, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), +}; diff --git a/ffmpeg/libavcodec/flac.c b/ffmpeg/libavcodec/flac.c new file mode 100644 index 0000000..a79a809 --- /dev/null +++ b/ffmpeg/libavcodec/flac.c @@ -0,0 +1,246 @@ +/* + * FLAC common code + * Copyright (c) 2009 Justin Ruggles + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/crc.h" +#include "libavutil/log.h" +#include "bytestream.h" +#include "get_bits.h" +#include "flac.h" +#include "flacdata.h" + +static const int8_t sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 }; + +static const uint64_t flac_channel_layouts[8] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_6POINT1, + AV_CH_LAYOUT_7POINT1 +}; + +static int64_t get_utf8(GetBitContext *gb) +{ + int64_t val; + GET_UTF8(val, get_bits(gb, 8), return -1;) + return val; +} + +int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, + FLACFrameInfo *fi, int log_level_offset) +{ + int bs_code, sr_code, bps_code; + + /* frame sync code */ + if ((get_bits(gb, 15) & 0x7FFF) != 0x7FFC) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, "invalid sync code\n"); + return -1; + } + + /* variable block size stream code */ + fi->is_var_size = get_bits1(gb); + + /* block size and sample rate codes */ + bs_code = get_bits(gb, 4); + sr_code = get_bits(gb, 4); + + /* channels and decorrelation */ + fi->ch_mode = get_bits(gb, 4); + if (fi->ch_mode < FLAC_MAX_CHANNELS) { + fi->channels = fi->ch_mode + 1; + fi->ch_mode = FLAC_CHMODE_INDEPENDENT; + } else if (fi->ch_mode < FLAC_MAX_CHANNELS + FLAC_CHMODE_MID_SIDE) { + fi->channels = 2; + fi->ch_mode -= FLAC_MAX_CHANNELS - 1; + } else { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "invalid channel mode: %d\n", fi->ch_mode); + return -1; + } + + /* bits per sample */ + bps_code = get_bits(gb, 3); + if (bps_code == 3 || bps_code == 7) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "invalid sample size code (%d)\n", + bps_code); + return -1; + } + fi->bps = sample_size_table[bps_code]; + + /* reserved bit */ + if (get_bits1(gb)) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "broken stream, invalid padding\n"); + return -1; + } + + /* sample or frame count */ + fi->frame_or_sample_num = get_utf8(gb); + if (fi->frame_or_sample_num < 0) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "sample/frame number invalid; utf8 fscked\n"); + return -1; + } + + /* blocksize */ + if (bs_code == 0) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "reserved blocksize code: 0\n"); + return -1; + } else if (bs_code == 6) { + fi->blocksize = get_bits(gb, 8) + 1; + } else if (bs_code == 7) { + fi->blocksize = get_bits(gb, 16) + 1; + } else { + fi->blocksize = ff_flac_blocksize_table[bs_code]; + } + + /* sample rate */ + if (sr_code < 12) { + fi->samplerate = ff_flac_sample_rate_table[sr_code]; + } else if (sr_code == 12) { + fi->samplerate = get_bits(gb, 8) * 1000; + } else if (sr_code == 13) { + fi->samplerate = get_bits(gb, 16); + } else if (sr_code == 14) { + fi->samplerate = get_bits(gb, 16) * 10; + } else { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "illegal sample rate code %d\n", + sr_code); + return -1; + } + + /* header CRC-8 check */ + skip_bits(gb, 8); + if (av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, gb->buffer, + get_bits_count(gb)/8)) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, + "header crc mismatch\n"); + return -1; + } + + return 0; +} + +int ff_flac_get_max_frame_size(int blocksize, int ch, int bps) +{ + /* Technically, there is no limit to FLAC frame size, but an encoder + should not write a frame that is larger than if verbatim encoding mode + were to be used. */ + + int count; + + count = 16; /* frame header */ + count += ch * ((7+bps+7)/8); /* subframe headers */ + if (ch == 2) { + /* for stereo, need to account for using decorrelation */ + count += (( 2*bps+1) * blocksize + 7) / 8; + } else { + count += ( ch*bps * blocksize + 7) / 8; + } + count += 2; /* frame footer */ + + return count; +} + +int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start) +{ + if (!avctx->extradata || avctx->extradata_size < FLAC_STREAMINFO_SIZE) { + av_log(avctx, AV_LOG_ERROR, "extradata NULL or too small.\n"); + return 0; + } + if (AV_RL32(avctx->extradata) != MKTAG('f','L','a','C')) { + /* extradata contains STREAMINFO only */ + if (avctx->extradata_size != FLAC_STREAMINFO_SIZE) { + av_log(avctx, AV_LOG_WARNING, "extradata contains %d bytes too many.\n", + FLAC_STREAMINFO_SIZE-avctx->extradata_size); + } + *format = FLAC_EXTRADATA_FORMAT_STREAMINFO; + *streaminfo_start = avctx->extradata; + } else { + if (avctx->extradata_size < 8+FLAC_STREAMINFO_SIZE) { + av_log(avctx, AV_LOG_ERROR, "extradata too small.\n"); + return 0; + } + *format = FLAC_EXTRADATA_FORMAT_FULL_HEADER; + *streaminfo_start = &avctx->extradata[8]; + } + return 1; +} + +void ff_flac_set_channel_layout(AVCodecContext *avctx) +{ + if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts)) + avctx->channel_layout = flac_channel_layouts[avctx->channels - 1]; + else + avctx->channel_layout = 0; +} + +void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, + const uint8_t *buffer) +{ + GetBitContext gb; + init_get_bits(&gb, buffer, FLAC_STREAMINFO_SIZE*8); + + skip_bits(&gb, 16); /* skip min blocksize */ + s->max_blocksize = get_bits(&gb, 16); + if (s->max_blocksize < FLAC_MIN_BLOCKSIZE) { + av_log(avctx, AV_LOG_WARNING, "invalid max blocksize: %d\n", + s->max_blocksize); + s->max_blocksize = 16; + } + + skip_bits(&gb, 24); /* skip min frame size */ + s->max_framesize = get_bits_long(&gb, 24); + + s->samplerate = get_bits_long(&gb, 20); + s->channels = get_bits(&gb, 3) + 1; + s->bps = get_bits(&gb, 5) + 1; + + avctx->channels = s->channels; + avctx->sample_rate = s->samplerate; + avctx->bits_per_raw_sample = s->bps; + ff_flac_set_channel_layout(avctx); + + s->samples = get_bits64(&gb, 36); + + skip_bits_long(&gb, 64); /* md5 sum */ + skip_bits_long(&gb, 64); /* md5 sum */ +} + +void avpriv_flac_parse_block_header(const uint8_t *block_header, + int *last, int *type, int *size) +{ + int tmp = bytestream_get_byte(&block_header); + if (last) + *last = tmp & 0x80; + if (type) + *type = tmp & 0x7F; + if (size) + *size = bytestream_get_be24(&block_header); +} diff --git a/ffmpeg/libavcodec/flac.h b/ffmpeg/libavcodec/flac.h new file mode 100644 index 0000000..13e863b --- /dev/null +++ b/ffmpeg/libavcodec/flac.h @@ -0,0 +1,143 @@ +/* + * FLAC (Free Lossless Audio Codec) decoder/demuxer common functions + * Copyright (c) 2008 Justin Ruggles + * + * 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 + */ + +/** + * @file + * FLAC (Free Lossless Audio Codec) decoder/demuxer common functions + */ + +#ifndef AVCODEC_FLAC_H +#define AVCODEC_FLAC_H + +#include "avcodec.h" +#include "get_bits.h" + +#define FLAC_STREAMINFO_SIZE 34 +#define FLAC_MAX_CHANNELS 8 +#define FLAC_MIN_BLOCKSIZE 16 +#define FLAC_MAX_BLOCKSIZE 65535 +#define FLAC_MIN_FRAME_SIZE 11 + +enum { + FLAC_CHMODE_INDEPENDENT = 0, + FLAC_CHMODE_LEFT_SIDE = 1, + FLAC_CHMODE_RIGHT_SIDE = 2, + FLAC_CHMODE_MID_SIDE = 3, +}; + +enum { + FLAC_METADATA_TYPE_STREAMINFO = 0, + FLAC_METADATA_TYPE_PADDING, + FLAC_METADATA_TYPE_APPLICATION, + FLAC_METADATA_TYPE_SEEKTABLE, + FLAC_METADATA_TYPE_VORBIS_COMMENT, + FLAC_METADATA_TYPE_CUESHEET, + FLAC_METADATA_TYPE_PICTURE, + FLAC_METADATA_TYPE_INVALID = 127 +}; + +enum FLACExtradataFormat { + FLAC_EXTRADATA_FORMAT_STREAMINFO = 0, + FLAC_EXTRADATA_FORMAT_FULL_HEADER = 1 +}; + +#define FLACCOMMONINFO \ + int samplerate; /**< sample rate */\ + int channels; /**< number of channels */\ + int bps; /**< bits-per-sample */\ + +/** + * Data needed from the Streaminfo header for use by the raw FLAC demuxer + * and/or the FLAC decoder. + */ +#define FLACSTREAMINFO \ + FLACCOMMONINFO \ + int max_blocksize; /**< maximum block size, in samples */\ + int max_framesize; /**< maximum frame size, in bytes */\ + int64_t samples; /**< total number of samples */\ + +typedef struct FLACStreaminfo { + FLACSTREAMINFO +} FLACStreaminfo; + +typedef struct FLACFrameInfo { + FLACCOMMONINFO + int blocksize; /**< block size of the frame */ + int ch_mode; /**< channel decorrelation mode */ + int64_t frame_or_sample_num; /**< frame number or sample number */ + int is_var_size; /**< specifies if the stream uses variable + block sizes or a fixed block size; + also determines the meaning of + frame_or_sample_num */ +} FLACFrameInfo; + +/** + * Parse the Streaminfo metadata block + * @param[out] avctx codec context to set basic stream parameters + * @param[out] s where parsed information is stored + * @param[in] buffer pointer to start of 34-byte streaminfo data + */ +void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, + const uint8_t *buffer); + +/** + * Validate the FLAC extradata. + * @param[in] avctx codec context containing the extradata. + * @param[out] format extradata format. + * @param[out] streaminfo_start pointer to start of 34-byte STREAMINFO data. + * @return 1 if valid, 0 if not valid. + */ +int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, + enum FLACExtradataFormat *format, + uint8_t **streaminfo_start); + +/** + * Parse the metadata block parameters from the header. + * @param[in] block_header header data, at least 4 bytes + * @param[out] last indicator for last metadata block + * @param[out] type metadata block type + * @param[out] size metadata block size + */ +void avpriv_flac_parse_block_header(const uint8_t *block_header, + int *last, int *type, int *size); + +/** + * Calculate an estimate for the maximum frame size based on verbatim mode. + * @param blocksize block size, in samples + * @param ch number of channels + * @param bps bits-per-sample + */ +int ff_flac_get_max_frame_size(int blocksize, int ch, int bps); + +/** + * Validate and decode a frame header. + * @param avctx AVCodecContext to use as av_log() context + * @param gb GetBitContext from which to read frame header + * @param[out] fi frame information + * @param log_level_offset log level offset. can be used to silence error messages. + * @return non-zero on error, 0 if ok + */ +int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, + FLACFrameInfo *fi, int log_level_offset); + +void ff_flac_set_channel_layout(AVCodecContext *avctx); + +#endif /* AVCODEC_FLAC_H */ diff --git a/ffmpeg/libavcodec/flac_parser.c b/ffmpeg/libavcodec/flac_parser.c new file mode 100644 index 0000000..e2c6744 --- /dev/null +++ b/ffmpeg/libavcodec/flac_parser.c @@ -0,0 +1,692 @@ +/* + * FLAC parser + * Copyright (c) 2010 Michael Chinen + * + * 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 + */ + +/** + * @file + * FLAC parser + * + * The FLAC parser buffers input until FLAC_MIN_HEADERS has been found. + * Each time it finds and verifies a CRC-8 header it sees which of the + * FLAC_MAX_SEQUENTIAL_HEADERS that came before it have a valid CRC-16 footer + * that ends at the newly found header. + * Headers are scored by FLAC_HEADER_BASE_SCORE plus the max of it's crc-verified + * children, penalized by changes in sample rate, frame number, etc. + * The parser returns the frame with the highest score. + **/ + +#include "libavutil/crc.h" +#include "libavutil/fifo.h" +#include "bytestream.h" +#include "parser.h" +#include "flac.h" + +/** maximum number of adjacent headers that compare CRCs against each other */ +#define FLAC_MAX_SEQUENTIAL_HEADERS 3 +/** minimum number of headers buffered and checked before returning frames */ +#define FLAC_MIN_HEADERS 10 +/** estimate for average size of a FLAC frame */ +#define FLAC_AVG_FRAME_SIZE 8192 + +/** scoring settings for score_header */ +#define FLAC_HEADER_BASE_SCORE 10 +#define FLAC_HEADER_CHANGED_PENALTY 7 +#define FLAC_HEADER_CRC_FAIL_PENALTY 50 +#define FLAC_HEADER_NOT_PENALIZED_YET 100000 +#define FLAC_HEADER_NOT_SCORED_YET -100000 + +/** largest possible size of flac header */ +#define MAX_FRAME_HEADER_SIZE 16 + +typedef struct FLACHeaderMarker { + int offset; /**< byte offset from start of FLACParseContext->buffer */ + int *link_penalty; /**< pointer to array of local scores between this header + and the one at a distance equal array position */ + int max_score; /**< maximum score found after checking each child that + has a valid CRC */ + FLACFrameInfo fi; /**< decoded frame header info */ + struct FLACHeaderMarker *next; /**< next CRC-8 verified header that + immediately follows this one in + the bytestream */ + struct FLACHeaderMarker *best_child; /**< following frame header with + which this frame has the best + score with */ +} FLACHeaderMarker; + +typedef struct FLACParseContext { + AVCodecParserContext *pc; /**< parent context */ + AVCodecContext *avctx; /**< codec context pointer for logging */ + FLACHeaderMarker *headers; /**< linked-list that starts at the first + CRC-8 verified header within buffer */ + FLACHeaderMarker *best_header; /**< highest scoring header within buffer */ + int nb_headers_found; /**< number of headers found in the last + flac_parse() call */ + int nb_headers_buffered; /**< number of headers that are buffered */ + int best_header_valid; /**< flag set when the parser returns junk; + if set return best_header next time */ + AVFifoBuffer *fifo_buf; /**< buffer to store all data until headers + can be verified */ + int end_padded; /**< specifies if fifo_buf's end is padded */ + uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */ + int wrap_buf_allocated_size; /**< actual allocated size of the buffer */ +} FLACParseContext; + +static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, + FLACFrameInfo *fi) +{ + GetBitContext gb; + init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8); + return !ff_flac_decode_frame_header(avctx, &gb, fi, 127); +} + +/** + * Non-destructive fast fifo pointer fetching + * Returns a pointer from the specified offset. + * If possible the pointer points within the fifo buffer. + * Otherwise (if it would cause a wrap around,) a pointer to a user-specified + * buffer is used. + * The pointer can be NULL. In any case it will be reallocated to hold the size. + * If the returned pointer will be used after subsequent calls to flac_fifo_read_wrap + * then the subsequent calls should pass in a different wrap_buf so as to not + * overwrite the contents of the previous wrap_buf. + * This function is based on av_fifo_generic_read, which is why there is a comment + * about a memory barrier for SMP. + */ +static uint8_t* flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, + uint8_t** wrap_buf, int* allocated_size) +{ + AVFifoBuffer *f = fpc->fifo_buf; + uint8_t *start = f->rptr + offset; + uint8_t *tmp_buf; + + if (start >= f->end) + start -= f->end - f->buffer; + if (f->end - start >= len) + return start; + + tmp_buf = av_fast_realloc(*wrap_buf, allocated_size, len); + + if (!tmp_buf) { + av_log(fpc->avctx, AV_LOG_ERROR, + "couldn't reallocate wrap buffer of size %d", len); + return NULL; + } + *wrap_buf = tmp_buf; + do { + int seg_len = FFMIN(f->end - start, len); + memcpy(tmp_buf, start, seg_len); + tmp_buf = (uint8_t*)tmp_buf + seg_len; +// memory barrier needed for SMP here in theory + + start += seg_len - (f->end - f->buffer); + len -= seg_len; + } while (len > 0); + + return *wrap_buf; +} + +/** + * Return a pointer in the fifo buffer where the offset starts at until + * the wrap point or end of request. + * len will contain the valid length of the returned buffer. + * A second call to flac_fifo_read (with new offset and len) should be called + * to get the post-wrap buf if the returned len is less than the requested. + **/ +static uint8_t* flac_fifo_read(FLACParseContext *fpc, int offset, int *len) +{ + AVFifoBuffer *f = fpc->fifo_buf; + uint8_t *start = f->rptr + offset; + + if (start >= f->end) + start -= f->end - f->buffer; + *len = FFMIN(*len, f->end - start); + return start; +} + +static int find_headers_search_validate(FLACParseContext *fpc, int offset) +{ + FLACFrameInfo fi; + uint8_t *header_buf; + int size = 0; + header_buf = flac_fifo_read_wrap(fpc, offset, + MAX_FRAME_HEADER_SIZE, + &fpc->wrap_buf, + &fpc->wrap_buf_allocated_size); + if (frame_header_is_valid(fpc->avctx, header_buf, &fi)) { + FLACHeaderMarker **end_handle = &fpc->headers; + int i; + + size = 0; + while (*end_handle) { + end_handle = &(*end_handle)->next; + size++; + } + + *end_handle = av_mallocz(sizeof(FLACHeaderMarker)); + if (!*end_handle) { + av_log(fpc->avctx, AV_LOG_ERROR, + "couldn't allocate FLACHeaderMarker\n"); + return AVERROR(ENOMEM); + } + (*end_handle)->fi = fi; + (*end_handle)->offset = offset; + (*end_handle)->link_penalty = av_malloc(sizeof(int) * + FLAC_MAX_SEQUENTIAL_HEADERS); + for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) + (*end_handle)->link_penalty[i] = FLAC_HEADER_NOT_PENALIZED_YET; + + fpc->nb_headers_found++; + size++; + } + return size; +} + +static int find_headers_search(FLACParseContext *fpc, uint8_t *buf, int buf_size, + int search_start) + +{ + int size = 0, mod_offset = (buf_size - 1) % 4, i, j; + uint32_t x; + + for (i = 0; i < mod_offset; i++) { + if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8) + size = find_headers_search_validate(fpc, search_start + i); + } + + for (; i < buf_size - 1; i += 4) { + x = AV_RB32(buf + i); + if (((x & ~(x + 0x01010101)) & 0x80808080)) { + for (j = 0; j < 4; j++) { + if ((AV_RB16(buf + i + j) & 0xFFFE) == 0xFFF8) + size = find_headers_search_validate(fpc, search_start + i + j); + } + } + } + return size; +} + +static int find_new_headers(FLACParseContext *fpc, int search_start) +{ + FLACHeaderMarker *end; + int search_end, size = 0, read_len, temp; + uint8_t *buf; + fpc->nb_headers_found = 0; + + /* Search for a new header of at most 16 bytes. */ + search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1); + read_len = search_end - search_start + 1; + buf = flac_fifo_read(fpc, search_start, &read_len); + size = find_headers_search(fpc, buf, read_len, search_start); + search_start += read_len - 1; + + /* If fifo end was hit do the wrap around. */ + if (search_start != search_end) { + uint8_t wrap[2]; + + wrap[0] = buf[read_len - 1]; + read_len = search_end - search_start + 1; + + /* search_start + 1 is the post-wrap offset in the fifo. */ + buf = flac_fifo_read(fpc, search_start + 1, &read_len); + wrap[1] = buf[0]; + + if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) { + temp = find_headers_search_validate(fpc, search_start); + size = FFMAX(size, temp); + } + search_start++; + + /* Continue to do the last half of the wrap. */ + temp = find_headers_search(fpc, buf, read_len, search_start); + size = FFMAX(size, temp); + search_start += read_len - 1; + } + + /* Return the size even if no new headers were found. */ + if (!size && fpc->headers) + for (end = fpc->headers; end; end = end->next) + size++; + return size; +} + +static int check_header_mismatch(FLACParseContext *fpc, + FLACHeaderMarker *header, + FLACHeaderMarker *child, + int log_level_offset) +{ + FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi; + int deduction = 0, deduction_expected = 0, i; + if (child_fi->samplerate != header_fi->samplerate) { + deduction += FLAC_HEADER_CHANGED_PENALTY; + av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, + "sample rate change detected in adjacent frames\n"); + } + if (child_fi->bps != header_fi->bps) { + deduction += FLAC_HEADER_CHANGED_PENALTY; + av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, + "bits per sample change detected in adjacent frames\n"); + } + if (child_fi->is_var_size != header_fi->is_var_size) { + /* Changing blocking strategy not allowed per the spec */ + deduction += FLAC_HEADER_BASE_SCORE; + av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, + "blocking strategy change detected in adjacent frames\n"); + } + if (child_fi->channels != header_fi->channels) { + deduction += FLAC_HEADER_CHANGED_PENALTY; + av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, + "number of channels change detected in adjacent frames\n"); + } + /* Check sample and frame numbers. */ + if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num + != header_fi->blocksize) && + (child_fi->frame_or_sample_num + != header_fi->frame_or_sample_num + 1)) { + FLACHeaderMarker *curr; + int expected_frame_num, expected_sample_num; + /* If there are frames in the middle we expect this deduction, + as they are probably valid and this one follows it */ + + expected_frame_num = expected_sample_num = header_fi->frame_or_sample_num; + curr = header; + while (curr != child) { + /* Ignore frames that failed all crc checks */ + for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) { + if (curr->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY) { + expected_frame_num++; + expected_sample_num += curr->fi.blocksize; + break; + } + } + curr = curr->next; + } + + if (expected_frame_num == child_fi->frame_or_sample_num || + expected_sample_num == child_fi->frame_or_sample_num) + deduction_expected = deduction ? 0 : 1; + + deduction += FLAC_HEADER_CHANGED_PENALTY; + av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, + "sample/frame number mismatch in adjacent frames\n"); + } + + /* If we have suspicious headers, check the CRC between them */ + if (deduction && !deduction_expected) { + FLACHeaderMarker *curr; + int read_len; + uint8_t *buf; + uint32_t crc = 1; + int inverted_test = 0; + + /* Since CRC is expensive only do it if we haven't yet. + This assumes a CRC penalty is greater than all other check penalties */ + curr = header->next; + for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS && curr != child; i++) + curr = curr->next; + + if (header->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY || + header->link_penalty[i] == FLAC_HEADER_NOT_PENALIZED_YET) { + FLACHeaderMarker *start, *end; + + /* Although overlapping chains are scored, the crc should never + have to be computed twice for a single byte. */ + start = header; + end = child; + if (i > 0 && + header->link_penalty[i - 1] >= FLAC_HEADER_CRC_FAIL_PENALTY) { + while (start->next != child) + start = start->next; + inverted_test = 1; + } else if (i > 0 && + header->next->link_penalty[i-1] >= + FLAC_HEADER_CRC_FAIL_PENALTY ) { + end = header->next; + inverted_test = 1; + } + + read_len = end->offset - start->offset; + buf = flac_fifo_read(fpc, start->offset, &read_len); + crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len); + read_len = (end->offset - start->offset) - read_len; + + if (read_len) { + buf = flac_fifo_read(fpc, end->offset - read_len, &read_len); + crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len); + } + } + + if (!crc ^ !inverted_test) { + deduction += FLAC_HEADER_CRC_FAIL_PENALTY; + av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, + "crc check failed from offset %i (frame %"PRId64") to %i (frame %"PRId64")\n", + header->offset, header_fi->frame_or_sample_num, + child->offset, child_fi->frame_or_sample_num); + } + } + return deduction; +} + +/** + * Score a header. + * + * Give FLAC_HEADER_BASE_SCORE points to a frame for existing. + * If it has children, (subsequent frames of which the preceding CRC footer + * validates against this one,) then take the maximum score of the children, + * with a penalty of FLAC_HEADER_CHANGED_PENALTY applied for each change to + * bps, sample rate, channels, but not decorrelation mode, or blocksize, + * because it can change often. + **/ +static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header) +{ + FLACHeaderMarker *child; + int dist = 0; + int child_score; + + if (header->max_score != FLAC_HEADER_NOT_SCORED_YET) + return header->max_score; + + header->max_score = FLAC_HEADER_BASE_SCORE; + + /* Check and compute the children's scores. */ + child = header->next; + for (dist = 0; dist < FLAC_MAX_SEQUENTIAL_HEADERS && child; dist++) { + /* Look at the child's frame header info and penalize suspicious + changes between the headers. */ + if (header->link_penalty[dist] == FLAC_HEADER_NOT_PENALIZED_YET) { + header->link_penalty[dist] = check_header_mismatch(fpc, header, + child, AV_LOG_DEBUG); + } + child_score = score_header(fpc, child) - header->link_penalty[dist]; + + if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) { + /* Keep the child because the frame scoring is dynamic. */ + header->best_child = child; + header->max_score = FLAC_HEADER_BASE_SCORE + child_score; + } + child = child->next; + } + + return header->max_score; +} + +static void score_sequences(FLACParseContext *fpc) +{ + FLACHeaderMarker *curr; + int best_score = FLAC_HEADER_NOT_SCORED_YET; + /* First pass to clear all old scores. */ + for (curr = fpc->headers; curr; curr = curr->next) + curr->max_score = FLAC_HEADER_NOT_SCORED_YET; + + /* Do a second pass to score them all. */ + for (curr = fpc->headers; curr; curr = curr->next) { + if (score_header(fpc, curr) > best_score) { + fpc->best_header = curr; + best_score = curr->max_score; + } + } +} + +static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf, + int *poutbuf_size) +{ + FLACHeaderMarker *header = fpc->best_header; + FLACHeaderMarker *child = header->best_child; + if (!child) { + *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset; + } else { + *poutbuf_size = child->offset - header->offset; + + /* If the child has suspicious changes, log them */ + check_header_mismatch(fpc, header, child, 0); + } + + if (header->fi.channels != fpc->avctx->channels || + !fpc->avctx->channel_layout) { + fpc->avctx->channels = header->fi.channels; + ff_flac_set_channel_layout(fpc->avctx); + } + fpc->avctx->sample_rate = header->fi.samplerate; + fpc->pc->duration = header->fi.blocksize; + *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size, + &fpc->wrap_buf, + &fpc->wrap_buf_allocated_size); + + fpc->best_header_valid = 0; + /* Return the negative overread index so the client can compute pos. + This should be the amount overread to the beginning of the child */ + if (child) + return child->offset - av_fifo_size(fpc->fifo_buf); + return 0; +} + +static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + FLACParseContext *fpc = s->priv_data; + FLACHeaderMarker *curr; + int nb_headers; + const uint8_t *read_end = buf; + const uint8_t *read_start = buf; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + FLACFrameInfo fi; + if (frame_header_is_valid(avctx, buf, &fi)) + s->duration = fi.blocksize; + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; + } + + fpc->avctx = avctx; + if (fpc->best_header_valid) + return get_best_header(fpc, poutbuf, poutbuf_size); + + /* If a best_header was found last call remove it with the buffer data. */ + if (fpc->best_header && fpc->best_header->best_child) { + FLACHeaderMarker *temp; + FLACHeaderMarker *best_child = fpc->best_header->best_child; + + /* Remove headers in list until the end of the best_header. */ + for (curr = fpc->headers; curr != best_child; curr = temp) { + if (curr != fpc->best_header) { + av_log(avctx, AV_LOG_DEBUG, + "dropping low score %i frame header from offset %i to %i\n", + curr->max_score, curr->offset, curr->next->offset); + } + temp = curr->next; + av_freep(&curr->link_penalty); + av_free(curr); + fpc->nb_headers_buffered--; + } + /* Release returned data from ring buffer. */ + av_fifo_drain(fpc->fifo_buf, best_child->offset); + + /* Fix the offset for the headers remaining to match the new buffer. */ + for (curr = best_child->next; curr; curr = curr->next) + curr->offset -= best_child->offset; + + fpc->nb_headers_buffered--; + best_child->offset = 0; + fpc->headers = best_child; + if (fpc->nb_headers_buffered >= FLAC_MIN_HEADERS) { + fpc->best_header = best_child; + return get_best_header(fpc, poutbuf, poutbuf_size); + } + fpc->best_header = NULL; + } else if (fpc->best_header) { + /* No end frame no need to delete the buffer; probably eof */ + FLACHeaderMarker *temp; + + for (curr = fpc->headers; curr != fpc->best_header; curr = temp) { + temp = curr->next; + av_freep(&curr->link_penalty); + av_free(curr); + } + fpc->headers = fpc->best_header->next; + av_freep(&fpc->best_header->link_penalty); + av_freep(&fpc->best_header); + } + + /* Find and score new headers. */ + /* buf_size is to zero when padding, so check for this since we do */ + /* not want to try to read more input once we have found the end. */ + /* Note that as (non-modified) parameters, buf can be non-NULL, */ + /* while buf_size is 0. */ + while ((buf && buf_size && read_end < buf + buf_size && + fpc->nb_headers_buffered < FLAC_MIN_HEADERS) + || ((!buf || !buf_size) && !fpc->end_padded)) { + int start_offset; + + /* Pad the end once if EOF, to check the final region for headers. */ + if (!buf || !buf_size) { + fpc->end_padded = 1; + buf_size = MAX_FRAME_HEADER_SIZE; + read_end = read_start + MAX_FRAME_HEADER_SIZE; + } else { + /* The maximum read size is the upper-bound of what the parser + needs to have the required number of frames buffered */ + int nb_desired = FLAC_MIN_HEADERS - fpc->nb_headers_buffered + 1; + read_end = read_end + FFMIN(buf + buf_size - read_end, + nb_desired * FLAC_AVG_FRAME_SIZE); + } + + /* Fill the buffer. */ + if ( av_fifo_space(fpc->fifo_buf) < read_end - read_start + && av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) { + av_log(avctx, AV_LOG_ERROR, + "couldn't reallocate buffer of size %td\n", + (read_end - read_start) + av_fifo_size(fpc->fifo_buf)); + goto handle_error; + } + + if (buf && buf_size) { + av_fifo_generic_write(fpc->fifo_buf, (void*) read_start, + read_end - read_start, NULL); + } else { + int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; + av_fifo_generic_write(fpc->fifo_buf, (void*) pad, sizeof(pad), NULL); + } + + /* Tag headers and update sequences. */ + start_offset = av_fifo_size(fpc->fifo_buf) - + ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1)); + start_offset = FFMAX(0, start_offset); + nb_headers = find_new_headers(fpc, start_offset); + + if (nb_headers < 0) { + av_log(avctx, AV_LOG_ERROR, + "find_new_headers couldn't allocate FLAC header\n"); + goto handle_error; + } + + fpc->nb_headers_buffered = nb_headers; + /* Wait till FLAC_MIN_HEADERS to output a valid frame. */ + if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) { + if (buf && read_end < buf + buf_size) { + read_start = read_end; + continue; + } else { + goto handle_error; + } + } + + /* If headers found, update the scores since we have longer chains. */ + if (fpc->end_padded || fpc->nb_headers_found) + score_sequences(fpc); + + /* restore the state pre-padding */ + if (fpc->end_padded) { + int warp = fpc->fifo_buf->wptr - fpc->fifo_buf->buffer < MAX_FRAME_HEADER_SIZE; + /* HACK: drain the tail of the fifo */ + fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE; + fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE; + if (warp) { + fpc->fifo_buf->wptr += fpc->fifo_buf->end - + fpc->fifo_buf->buffer; + } + buf_size = 0; + read_start = read_end = NULL; + } + } + + curr = fpc->headers; + for (curr = fpc->headers; curr; curr = curr->next) + if (!fpc->best_header || curr->max_score > fpc->best_header->max_score) + fpc->best_header = curr; + + if (fpc->best_header) { + fpc->best_header_valid = 1; + if (fpc->best_header->offset > 0) { + /* Output a junk frame. */ + av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n", + fpc->best_header->offset); + + /* Set duration to 0. It is unknown or invalid in a junk frame. */ + s->duration = 0; + *poutbuf_size = fpc->best_header->offset; + *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, + &fpc->wrap_buf, + &fpc->wrap_buf_allocated_size); + return buf_size ? (read_end - buf) : (fpc->best_header->offset - + av_fifo_size(fpc->fifo_buf)); + } + if (!buf_size) + return get_best_header(fpc, poutbuf, poutbuf_size); + } + +handle_error: + *poutbuf = NULL; + *poutbuf_size = 0; + return read_end - buf; +} + +static int flac_parse_init(AVCodecParserContext *c) +{ + FLACParseContext *fpc = c->priv_data; + fpc->pc = c; + /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before + it drains. This is allocated early to avoid slow reallocation. */ + fpc->fifo_buf = av_fifo_alloc(FLAC_AVG_FRAME_SIZE * (FLAC_MIN_HEADERS + 3)); + return 0; +} + +static void flac_parse_close(AVCodecParserContext *c) +{ + FLACParseContext *fpc = c->priv_data; + FLACHeaderMarker *curr = fpc->headers, *temp; + + while (curr) { + temp = curr->next; + av_freep(&curr->link_penalty); + av_free(curr); + curr = temp; + } + av_fifo_free(fpc->fifo_buf); + av_free(fpc->wrap_buf); +} + +AVCodecParser ff_flac_parser = { + .codec_ids = { AV_CODEC_ID_FLAC }, + .priv_data_size = sizeof(FLACParseContext), + .parser_init = flac_parse_init, + .parser_parse = flac_parse, + .parser_close = flac_parse_close, +}; diff --git a/ffmpeg/libavcodec/flacdata.c b/ffmpeg/libavcodec/flacdata.c new file mode 100644 index 0000000..6fcbe39 --- /dev/null +++ b/ffmpeg/libavcodec/flacdata.c @@ -0,0 +1,33 @@ +/* + * FLAC data + * Copyright (c) 2003 Alex Beregszaszi + * + * 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 "internal.h" + +const int ff_flac_sample_rate_table[16] = +{ 0, + 88200, 176400, 192000, + 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000, + 0, 0, 0, 0 }; + +const int16_t ff_flac_blocksize_table[16] = { + 0, 192, 576<<0, 576<<1, 576<<2, 576<<3, 0, 0, +256<<0, 256<<1, 256<<2, 256<<3, 256<<4, 256<<5, 256<<6, 256<<7 +}; diff --git a/ffmpeg/libavcodec/flacdata.h b/ffmpeg/libavcodec/flacdata.h new file mode 100644 index 0000000..96a50b9 --- /dev/null +++ b/ffmpeg/libavcodec/flacdata.h @@ -0,0 +1,31 @@ +/* + * FLAC data header + * Copyright (c) 2003 Alex Beregszaszi + * + * 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 + */ + +#ifndef AVCODEC_FLACDATA_H +#define AVCODEC_FLACDATA_H + +#include "internal.h" + +extern const int ff_flac_sample_rate_table[16]; + +extern const int16_t ff_flac_blocksize_table[16]; + +#endif /* AVCODEC_FLACDATA_H */ diff --git a/ffmpeg/libavcodec/flacdec.c b/ffmpeg/libavcodec/flacdec.c new file mode 100644 index 0000000..aaddd2d --- /dev/null +++ b/ffmpeg/libavcodec/flacdec.c @@ -0,0 +1,592 @@ +/* + * FLAC (Free Lossless Audio Codec) decoder + * Copyright (c) 2003 Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * FLAC (Free Lossless Audio Codec) decoder + * @author Alex Beregszaszi + * @see http://flac.sourceforge.net/ + * + * This decoder can be used in 1 of 2 ways: Either raw FLAC data can be fed + * through, starting from the initial 'fLaC' signature; or by passing the + * 34-byte streaminfo structure through avctx->extradata[_size] followed + * by data starting with the 0xFFF8 marker. + */ + +#include + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/crc.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "bytestream.h" +#include "golomb.h" +#include "flac.h" +#include "flacdata.h" +#include "flacdsp.h" + +typedef struct FLACContext { + FLACSTREAMINFO + + AVCodecContext *avctx; ///< parent AVCodecContext + GetBitContext gb; ///< GetBitContext initialized to start at the current frame + + int blocksize; ///< number of samples in the current frame + int sample_shift; ///< shift required to make output samples 16-bit or 32-bit + int ch_mode; ///< channel decorrelation type in the current frame + int got_streaminfo; ///< indicates if the STREAMINFO has been read + + int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples + uint8_t *decoded_buffer; + unsigned int decoded_buffer_size; + + FLACDSPContext dsp; +} FLACContext; + +static int allocate_buffers(FLACContext *s); + +static void flac_set_bps(FLACContext *s) +{ + enum AVSampleFormat req = s->avctx->request_sample_fmt; + int need32 = s->bps > 16; + int want32 = av_get_bytes_per_sample(req) > 2; + int planar = av_sample_fmt_is_planar(req); + + if (need32 || want32) { + if (planar) + s->avctx->sample_fmt = AV_SAMPLE_FMT_S32P; + else + s->avctx->sample_fmt = AV_SAMPLE_FMT_S32; + s->sample_shift = 32 - s->bps; + } else { + if (planar) + s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + else + s->avctx->sample_fmt = AV_SAMPLE_FMT_S16; + s->sample_shift = 16 - s->bps; + } +} + +static av_cold int flac_decode_init(AVCodecContext *avctx) +{ + enum FLACExtradataFormat format; + uint8_t *streaminfo; + int ret; + FLACContext *s = avctx->priv_data; + s->avctx = avctx; + + /* for now, the raw FLAC header is allowed to be passed to the decoder as + frame data instead of extradata. */ + if (!avctx->extradata) + return 0; + + if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo)) + return -1; + + /* initialize based on the demuxer-supplied streamdata header */ + avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo); + ret = allocate_buffers(s); + if (ret < 0) + return ret; + flac_set_bps(s); + ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps); + s->got_streaminfo = 1; + + return 0; +} + +static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s) +{ + av_log(avctx, AV_LOG_DEBUG, " Max Blocksize: %d\n", s->max_blocksize); + av_log(avctx, AV_LOG_DEBUG, " Max Framesize: %d\n", s->max_framesize); + av_log(avctx, AV_LOG_DEBUG, " Samplerate: %d\n", s->samplerate); + av_log(avctx, AV_LOG_DEBUG, " Channels: %d\n", s->channels); + av_log(avctx, AV_LOG_DEBUG, " Bits: %d\n", s->bps); +} + +static int allocate_buffers(FLACContext *s) +{ + int buf_size; + + av_assert0(s->max_blocksize); + + buf_size = av_samples_get_buffer_size(NULL, s->channels, s->max_blocksize, + AV_SAMPLE_FMT_S32P, 0); + if (buf_size < 0) + return buf_size; + + av_fast_malloc(&s->decoded_buffer, &s->decoded_buffer_size, buf_size); + if (!s->decoded_buffer) + return AVERROR(ENOMEM); + + return av_samples_fill_arrays((uint8_t **)s->decoded, NULL, + s->decoded_buffer, s->channels, + s->max_blocksize, AV_SAMPLE_FMT_S32P, 0); +} + +/** + * Parse the STREAMINFO from an inline header. + * @param s the flac decoding context + * @param buf input buffer, starting with the "fLaC" marker + * @param buf_size buffer size + * @return non-zero if metadata is invalid + */ +static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size) +{ + int metadata_type, metadata_size, ret; + + if (buf_size < FLAC_STREAMINFO_SIZE+8) { + /* need more data */ + return 0; + } + avpriv_flac_parse_block_header(&buf[4], NULL, &metadata_type, &metadata_size); + if (metadata_type != FLAC_METADATA_TYPE_STREAMINFO || + metadata_size != FLAC_STREAMINFO_SIZE) { + return AVERROR_INVALIDDATA; + } + avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]); + ret = allocate_buffers(s); + if (ret < 0) + return ret; + flac_set_bps(s); + ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps); + s->got_streaminfo = 1; + + return 0; +} + +/** + * Determine the size of an inline header. + * @param buf input buffer, starting with the "fLaC" marker + * @param buf_size buffer size + * @return number of bytes in the header, or 0 if more data is needed + */ +static int get_metadata_size(const uint8_t *buf, int buf_size) +{ + int metadata_last, metadata_size; + const uint8_t *buf_end = buf + buf_size; + + buf += 4; + do { + if (buf_end - buf < 4) + return 0; + avpriv_flac_parse_block_header(buf, &metadata_last, NULL, &metadata_size); + buf += 4; + if (buf_end - buf < metadata_size) { + /* need more data in order to read the complete header */ + return 0; + } + buf += metadata_size; + } while (!metadata_last); + + return buf_size - (buf_end - buf); +} + +static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) +{ + int i, tmp, partition, method_type, rice_order; + int rice_bits, rice_esc; + int samples; + + method_type = get_bits(&s->gb, 2); + if (method_type > 1) { + av_log(s->avctx, AV_LOG_ERROR, "illegal residual coding method %d\n", + method_type); + return -1; + } + + rice_order = get_bits(&s->gb, 4); + + samples= s->blocksize >> rice_order; + if (pred_order > samples) { + av_log(s->avctx, AV_LOG_ERROR, "invalid predictor order: %i > %i\n", + pred_order, samples); + return -1; + } + + rice_bits = 4 + method_type; + rice_esc = (1 << rice_bits) - 1; + + decoded += pred_order; + i= pred_order; + for (partition = 0; partition < (1 << rice_order); partition++) { + tmp = get_bits(&s->gb, rice_bits); + if (tmp == rice_esc) { + tmp = get_bits(&s->gb, 5); + for (; i < samples; i++) + *decoded++ = get_sbits_long(&s->gb, tmp); + } else { + for (; i < samples; i++) { + *decoded++ = get_sr_golomb_flac(&s->gb, tmp, INT_MAX, 0); + } + } + i= 0; + } + + return 0; +} + +static int decode_subframe_fixed(FLACContext *s, int32_t *decoded, + int pred_order, int bps) +{ + const int blocksize = s->blocksize; + int av_uninit(a), av_uninit(b), av_uninit(c), av_uninit(d), i; + + /* warm up samples */ + for (i = 0; i < pred_order; i++) { + decoded[i] = get_sbits_long(&s->gb, bps); + } + + if (decode_residuals(s, decoded, pred_order) < 0) + return -1; + + if (pred_order > 0) + a = decoded[pred_order-1]; + if (pred_order > 1) + b = a - decoded[pred_order-2]; + if (pred_order > 2) + c = b - decoded[pred_order-2] + decoded[pred_order-3]; + if (pred_order > 3) + d = c - decoded[pred_order-2] + 2*decoded[pred_order-3] - decoded[pred_order-4]; + + switch (pred_order) { + case 0: + break; + case 1: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += decoded[i]; + break; + case 2: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += b += decoded[i]; + break; + case 3: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += b += c += decoded[i]; + break; + case 4: + for (i = pred_order; i < blocksize; i++) + decoded[i] = a += b += c += d += decoded[i]; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "illegal pred order %d\n", pred_order); + return -1; + } + + return 0; +} + +static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order, + int bps) +{ + int i; + int coeff_prec, qlevel; + int coeffs[32]; + + /* warm up samples */ + for (i = 0; i < pred_order; i++) { + decoded[i] = get_sbits_long(&s->gb, bps); + } + + coeff_prec = get_bits(&s->gb, 4) + 1; + if (coeff_prec == 16) { + av_log(s->avctx, AV_LOG_ERROR, "invalid coeff precision\n"); + return -1; + } + qlevel = get_sbits(&s->gb, 5); + if (qlevel < 0) { + av_log(s->avctx, AV_LOG_ERROR, "qlevel %d not supported, maybe buggy stream\n", + qlevel); + return -1; + } + + for (i = 0; i < pred_order; i++) { + coeffs[pred_order - i - 1] = get_sbits(&s->gb, coeff_prec); + } + + if (decode_residuals(s, decoded, pred_order) < 0) + return -1; + + s->dsp.lpc(decoded, coeffs, pred_order, qlevel, s->blocksize); + + return 0; +} + +static inline int decode_subframe(FLACContext *s, int channel) +{ + int32_t *decoded = s->decoded[channel]; + int type, wasted = 0; + int bps = s->bps; + int i, tmp; + + if (channel == 0) { + if (s->ch_mode == FLAC_CHMODE_RIGHT_SIDE) + bps++; + } else { + if (s->ch_mode == FLAC_CHMODE_LEFT_SIDE || s->ch_mode == FLAC_CHMODE_MID_SIDE) + bps++; + } + + if (get_bits1(&s->gb)) { + av_log(s->avctx, AV_LOG_ERROR, "invalid subframe padding\n"); + return -1; + } + type = get_bits(&s->gb, 6); + + if (get_bits1(&s->gb)) { + int left = get_bits_left(&s->gb); + wasted = 1; + if ( left < 0 || + (left < bps && !show_bits_long(&s->gb, left)) || + !show_bits_long(&s->gb, bps)) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid number of wasted bits > available bits (%d) - left=%d\n", + bps, left); + return AVERROR_INVALIDDATA; + } + while (!get_bits1(&s->gb)) + wasted++; + bps -= wasted; + } + if (bps > 32) { + avpriv_report_missing_feature(s->avctx, "Decorrelated bit depth > 32"); + return AVERROR_PATCHWELCOME; + } + +//FIXME use av_log2 for types + if (type == 0) { + tmp = get_sbits_long(&s->gb, bps); + for (i = 0; i < s->blocksize; i++) + decoded[i] = tmp; + } else if (type == 1) { + for (i = 0; i < s->blocksize; i++) + decoded[i] = get_sbits_long(&s->gb, bps); + } else if ((type >= 8) && (type <= 12)) { + if (decode_subframe_fixed(s, decoded, type & ~0x8, bps) < 0) + return -1; + } else if (type >= 32) { + if (decode_subframe_lpc(s, decoded, (type & ~0x20)+1, bps) < 0) + return -1; + } else { + av_log(s->avctx, AV_LOG_ERROR, "invalid coding type\n"); + return -1; + } + + if (wasted) { + int i; + for (i = 0; i < s->blocksize; i++) + decoded[i] <<= wasted; + } + + return 0; +} + +static int decode_frame(FLACContext *s) +{ + int i, ret; + GetBitContext *gb = &s->gb; + FLACFrameInfo fi; + + if (ff_flac_decode_frame_header(s->avctx, gb, &fi, 0)) { + av_log(s->avctx, AV_LOG_ERROR, "invalid frame header\n"); + return -1; + } + + if (s->channels && fi.channels != s->channels && s->got_streaminfo) { + s->channels = s->avctx->channels = fi.channels; + ff_flac_set_channel_layout(s->avctx); + ret = allocate_buffers(s); + if (ret < 0) + return ret; + } + s->channels = s->avctx->channels = fi.channels; + if (!s->avctx->channel_layout) + ff_flac_set_channel_layout(s->avctx); + s->ch_mode = fi.ch_mode; + + if (!s->bps && !fi.bps) { + av_log(s->avctx, AV_LOG_ERROR, "bps not found in STREAMINFO or frame header\n"); + return -1; + } + if (!fi.bps) { + fi.bps = s->bps; + } else if (s->bps && fi.bps != s->bps) { + av_log(s->avctx, AV_LOG_ERROR, "switching bps mid-stream is not " + "supported\n"); + return -1; + } + + if (!s->bps) { + s->bps = s->avctx->bits_per_raw_sample = fi.bps; + flac_set_bps(s); + } + + if (!s->max_blocksize) + s->max_blocksize = FLAC_MAX_BLOCKSIZE; + if (fi.blocksize > s->max_blocksize) { + av_log(s->avctx, AV_LOG_ERROR, "blocksize %d > %d\n", fi.blocksize, + s->max_blocksize); + return -1; + } + s->blocksize = fi.blocksize; + + if (!s->samplerate && !fi.samplerate) { + av_log(s->avctx, AV_LOG_ERROR, "sample rate not found in STREAMINFO" + " or frame header\n"); + return -1; + } + if (fi.samplerate == 0) + fi.samplerate = s->samplerate; + s->samplerate = s->avctx->sample_rate = fi.samplerate; + + if (!s->got_streaminfo) { + ret = allocate_buffers(s); + if (ret < 0) + return ret; + ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps); + s->got_streaminfo = 1; + dump_headers(s->avctx, (FLACStreaminfo *)s); + } + +// dump_headers(s->avctx, (FLACStreaminfo *)s); + + /* subframes */ + for (i = 0; i < s->channels; i++) { + if (decode_subframe(s, i) < 0) + return -1; + } + + align_get_bits(gb); + + /* frame footer */ + skip_bits(gb, 16); /* data crc */ + + return 0; +} + +static int flac_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + FLACContext *s = avctx->priv_data; + int bytes_read = 0; + int ret; + + *got_frame_ptr = 0; + + if (s->max_framesize == 0) { + s->max_framesize = + ff_flac_get_max_frame_size(s->max_blocksize ? s->max_blocksize : FLAC_MAX_BLOCKSIZE, + FLAC_MAX_CHANNELS, 32); + } + + if (buf_size > 5 && !memcmp(buf, "\177FLAC", 5)) { + av_log(s->avctx, AV_LOG_DEBUG, "skiping flac header packet 1\n"); + return buf_size; + } + + if (buf_size > 0 && (*buf & 0x7F) == FLAC_METADATA_TYPE_VORBIS_COMMENT) { + av_log(s->avctx, AV_LOG_DEBUG, "skiping vorbis comment\n"); + return buf_size; + } + + /* check that there is at least the smallest decodable amount of data. + this amount corresponds to the smallest valid FLAC frame possible. + FF F8 69 02 00 00 9A 00 00 34 46 */ + if (buf_size < FLAC_MIN_FRAME_SIZE) + return buf_size; + + /* check for inline header */ + if (AV_RB32(buf) == MKBETAG('f','L','a','C')) { + if (!s->got_streaminfo && parse_streaminfo(s, buf, buf_size)) { + av_log(s->avctx, AV_LOG_ERROR, "invalid header\n"); + return -1; + } + return get_metadata_size(buf, buf_size); + } + + /* decode frame */ + init_get_bits(&s->gb, buf, buf_size*8); + if (decode_frame(s) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n"); + return -1; + } + bytes_read = get_bits_count(&s->gb)/8; + + if ((s->avctx->err_recognition & AV_EF_CRCCHECK) && + av_crc(av_crc_get_table(AV_CRC_16_ANSI), + 0, buf, bytes_read)) { + av_log(s->avctx, AV_LOG_ERROR, "CRC error at PTS %"PRId64"\n", avpkt->pts); + if (s->avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = s->blocksize; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + s->dsp.decorrelate[s->ch_mode](frame->data, s->decoded, s->channels, + s->blocksize, s->sample_shift); + + if (bytes_read > buf_size) { + av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size); + return -1; + } + if (bytes_read < buf_size) { + av_log(s->avctx, AV_LOG_DEBUG, "underread: %d orig size: %d\n", + buf_size - bytes_read, buf_size); + } + + *got_frame_ptr = 1; + + return bytes_read; +} + +static av_cold int flac_decode_close(AVCodecContext *avctx) +{ + FLACContext *s = avctx->priv_data; + + av_freep(&s->decoded_buffer); + + return 0; +} + +AVCodec ff_flac_decoder = { + .name = "flac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_FLAC, + .priv_data_size = sizeof(FLACContext), + .init = flac_decode_init, + .close = flac_decode_close, + .decode = flac_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/flacdsp.c b/ffmpeg/libavcodec/flacdsp.c new file mode 100644 index 0000000..02eba3e --- /dev/null +++ b/ffmpeg/libavcodec/flacdsp.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * 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 "libavutil/attributes.h" +#include "libavutil/samplefmt.h" +#include "flacdsp.h" +#include "config.h" + +#define SAMPLE_SIZE 16 +#define PLANAR 0 +#include "flacdsp_template.c" +#include "flacdsp_lpc_template.c" + +#undef PLANAR +#define PLANAR 1 +#include "flacdsp_template.c" + +#undef SAMPLE_SIZE +#undef PLANAR +#define SAMPLE_SIZE 32 +#define PLANAR 0 +#include "flacdsp_template.c" +#include "flacdsp_lpc_template.c" + +#undef PLANAR +#define PLANAR 1 +#include "flacdsp_template.c" + +static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32], + int pred_order, int qlevel, int len) +{ + int i, j; + + for (i = pred_order; i < len - 1; i += 2, decoded += 2) { + int c = coeffs[0]; + int d = decoded[0]; + int s0 = 0, s1 = 0; + for (j = 1; j < pred_order; j++) { + s0 += c*d; + d = decoded[j]; + s1 += c*d; + c = coeffs[j]; + } + s0 += c*d; + d = decoded[j] += s0 >> qlevel; + s1 += c*d; + decoded[j + 1] += s1 >> qlevel; + } + if (i < len) { + int sum = 0; + for (j = 0; j < pred_order; j++) + sum += coeffs[j] * decoded[j]; + decoded[j] += sum >> qlevel; + } +} + +static void flac_lpc_32_c(int32_t *decoded, const int coeffs[32], + int pred_order, int qlevel, int len) +{ + int i, j; + + for (i = pred_order; i < len; i++, decoded++) { + int64_t sum = 0; + for (j = 0; j < pred_order; j++) + sum += (int64_t)coeffs[j] * decoded[j]; + decoded[j] += sum >> qlevel; + } + +} + +av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, + int bps) +{ + if (bps > 16) { + c->lpc = flac_lpc_32_c; + c->lpc_encode = flac_lpc_encode_c_32; + } else { + c->lpc = flac_lpc_16_c; + c->lpc_encode = flac_lpc_encode_c_16; + } + + switch (fmt) { + case AV_SAMPLE_FMT_S32: + c->decorrelate[0] = flac_decorrelate_indep_c_32; + c->decorrelate[1] = flac_decorrelate_ls_c_32; + c->decorrelate[2] = flac_decorrelate_rs_c_32; + c->decorrelate[3] = flac_decorrelate_ms_c_32; + break; + + case AV_SAMPLE_FMT_S32P: + c->decorrelate[0] = flac_decorrelate_indep_c_32p; + c->decorrelate[1] = flac_decorrelate_ls_c_32p; + c->decorrelate[2] = flac_decorrelate_rs_c_32p; + c->decorrelate[3] = flac_decorrelate_ms_c_32p; + break; + + case AV_SAMPLE_FMT_S16: + c->decorrelate[0] = flac_decorrelate_indep_c_16; + c->decorrelate[1] = flac_decorrelate_ls_c_16; + c->decorrelate[2] = flac_decorrelate_rs_c_16; + c->decorrelate[3] = flac_decorrelate_ms_c_16; + break; + + case AV_SAMPLE_FMT_S16P: + c->decorrelate[0] = flac_decorrelate_indep_c_16p; + c->decorrelate[1] = flac_decorrelate_ls_c_16p; + c->decorrelate[2] = flac_decorrelate_rs_c_16p; + c->decorrelate[3] = flac_decorrelate_ms_c_16p; + break; + } + + if (ARCH_ARM) + ff_flacdsp_init_arm(c, fmt, bps); +} diff --git a/ffmpeg/libavcodec/flacdsp.h b/ffmpeg/libavcodec/flacdsp.h new file mode 100644 index 0000000..5e66dc2 --- /dev/null +++ b/ffmpeg/libavcodec/flacdsp.h @@ -0,0 +1,37 @@ +/* + * 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 + */ + +#ifndef AVCODEC_FLACDSP_H +#define AVCODEC_FLACDSP_H + +#include +#include "libavutil/samplefmt.h" + +typedef struct FLACDSPContext { + void (*decorrelate[4])(uint8_t **out, int32_t **in, int channels, + int len, int shift); + void (*lpc)(int32_t *samples, const int coeffs[32], int order, + int qlevel, int len); + void (*lpc_encode)(int32_t *res, const int32_t *smp, int len, int order, + const int32_t *coefs, int shift); +} FLACDSPContext; + +void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int bps); +void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int bps); + +#endif /* AVCODEC_FLACDSP_H */ diff --git a/ffmpeg/libavcodec/flacdsp_lpc_template.c b/ffmpeg/libavcodec/flacdsp_lpc_template.c new file mode 100644 index 0000000..0c453ae --- /dev/null +++ b/ffmpeg/libavcodec/flacdsp_lpc_template.c @@ -0,0 +1,141 @@ +/* + * 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 "libavutil/avutil.h" +#include "mathops.h" + +#undef FUNC +#undef sum_type +#undef MUL +#undef CLIP +#undef FSUF + +#define FUNC(n) AV_JOIN(n ## _, SAMPLE_SIZE) + +#if SAMPLE_SIZE == 32 +# define sum_type int64_t +# define MUL(a, b) MUL64(a, b) +# define CLIP(x) av_clipl_int32(x) +#else +# define sum_type int32_t +# define MUL(a, b) ((a) * (b)) +# define CLIP(x) (x) +#endif + +#define LPC1(x) { \ + int c = coefs[(x)-1]; \ + p0 += MUL(c, s); \ + s = smp[i-(x)+1]; \ + p1 += MUL(c, s); \ +} + +static av_always_inline void FUNC(lpc_encode_unrolled)(int32_t *res, + const int32_t *smp, int len, int order, + const int32_t *coefs, int shift, int big) +{ + int i; + for (i = order; i < len; i += 2) { + int s = smp[i-order]; + sum_type p0 = 0, p1 = 0; + if (big) { + switch (order) { + case 32: LPC1(32) + case 31: LPC1(31) + case 30: LPC1(30) + case 29: LPC1(29) + case 28: LPC1(28) + case 27: LPC1(27) + case 26: LPC1(26) + case 25: LPC1(25) + case 24: LPC1(24) + case 23: LPC1(23) + case 22: LPC1(22) + case 21: LPC1(21) + case 20: LPC1(20) + case 19: LPC1(19) + case 18: LPC1(18) + case 17: LPC1(17) + case 16: LPC1(16) + case 15: LPC1(15) + case 14: LPC1(14) + case 13: LPC1(13) + case 12: LPC1(12) + case 11: LPC1(11) + case 10: LPC1(10) + case 9: LPC1( 9) + LPC1( 8) + LPC1( 7) + LPC1( 6) + LPC1( 5) + LPC1( 4) + LPC1( 3) + LPC1( 2) + LPC1( 1) + } + } else { + switch (order) { + case 8: LPC1( 8) + case 7: LPC1( 7) + case 6: LPC1( 6) + case 5: LPC1( 5) + case 4: LPC1( 4) + case 3: LPC1( 3) + case 2: LPC1( 2) + case 1: LPC1( 1) + } + } + res[i ] = smp[i ] - CLIP(p0 >> shift); + res[i+1] = smp[i+1] - CLIP(p1 >> shift); + } +} + +static void FUNC(flac_lpc_encode_c)(int32_t *res, const int32_t *smp, int len, + int order, const int32_t *coefs, int shift) +{ + int i; + for (i = 0; i < order; i++) + res[i] = smp[i]; +#if CONFIG_SMALL + for (i = order; i < len; i += 2) { + int j; + int s = smp[i]; + sum_type p0 = 0, p1 = 0; + for (j = 0; j < order; j++) { + int c = coefs[j]; + p1 += MUL(c, s); + s = smp[i-j-1]; + p0 += MUL(c, s); + } + res[i ] = smp[i ] - CLIP(p0 >> shift); + res[i+1] = smp[i+1] - CLIP(p1 >> shift); + } +#else + switch (order) { + case 1: FUNC(lpc_encode_unrolled)(res, smp, len, 1, coefs, shift, 0); break; + case 2: FUNC(lpc_encode_unrolled)(res, smp, len, 2, coefs, shift, 0); break; + case 3: FUNC(lpc_encode_unrolled)(res, smp, len, 3, coefs, shift, 0); break; + case 4: FUNC(lpc_encode_unrolled)(res, smp, len, 4, coefs, shift, 0); break; + case 5: FUNC(lpc_encode_unrolled)(res, smp, len, 5, coefs, shift, 0); break; + case 6: FUNC(lpc_encode_unrolled)(res, smp, len, 6, coefs, shift, 0); break; + case 7: FUNC(lpc_encode_unrolled)(res, smp, len, 7, coefs, shift, 0); break; + case 8: FUNC(lpc_encode_unrolled)(res, smp, len, 8, coefs, shift, 0); break; + default: FUNC(lpc_encode_unrolled)(res, smp, len, order, coefs, shift, 1); break; + } +#endif +} diff --git a/ffmpeg/libavcodec/flacdsp_template.c b/ffmpeg/libavcodec/flacdsp_template.c new file mode 100644 index 0000000..62c0a15 --- /dev/null +++ b/ffmpeg/libavcodec/flacdsp_template.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * 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 "libavutil/avutil.h" + +#undef FUNC +#undef FSUF +#undef sample +#undef sample_type +#undef OUT +#undef S + +#if SAMPLE_SIZE == 32 +# define sample_type int32_t +#else +# define sample_type int16_t +#endif + +#if PLANAR +# define FSUF AV_JOIN(SAMPLE_SIZE, p) +# define sample sample_type * +# define OUT(n) n +# define S(s, c, i) (s[c][i]) +#else +# define FSUF SAMPLE_SIZE +# define sample sample_type +# define OUT(n) n[0] +# define S(s, c, i) (*s++) +#endif + +#define FUNC(n) AV_JOIN(n ## _, FSUF) + +static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in, + int channels, int len, int shift) +{ + sample *samples = (sample *) OUT(out); + int i, j; + + for (j = 0; j < len; j++) + for (i = 0; i < channels; i++) + S(samples, i, j) = in[i][j] << shift; +} + +static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in, + int channels, int len, int shift) +{ + sample *samples = (sample *) OUT(out); + int i; + + for (i = 0; i < len; i++) { + int a = in[0][i]; + int b = in[1][i]; + S(samples, 0, i) = a << shift; + S(samples, 1, i) = (a - b) << shift; + } +} + +static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in, + int channels, int len, int shift) +{ + sample *samples = (sample *) OUT(out); + int i; + + for (i = 0; i < len; i++) { + int a = in[0][i]; + int b = in[1][i]; + S(samples, 0, i) = (a + b) << shift; + S(samples, 1, i) = b << shift; + } +} + +static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in, + int channels, int len, int shift) +{ + sample *samples = (sample *) OUT(out); + int i; + + for (i = 0; i < len; i++) { + int a = in[0][i]; + int b = in[1][i]; + a -= b >> 1; + S(samples, 0, i) = (a + b) << shift; + S(samples, 1, i) = a << shift; + } +} diff --git a/ffmpeg/libavcodec/flacenc.c b/ffmpeg/libavcodec/flacenc.c new file mode 100644 index 0000000..dc932c6 --- /dev/null +++ b/ffmpeg/libavcodec/flacenc.c @@ -0,0 +1,1358 @@ +/* + * FLAC audio encoder + * Copyright (c) 2006 Justin Ruggles + * + * 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 "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "libavutil/intmath.h" +#include "libavutil/md5.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dsputil.h" +#include "put_bits.h" +#include "golomb.h" +#include "internal.h" +#include "lpc.h" +#include "flac.h" +#include "flacdata.h" +#include "flacdsp.h" + +#define FLAC_SUBFRAME_CONSTANT 0 +#define FLAC_SUBFRAME_VERBATIM 1 +#define FLAC_SUBFRAME_FIXED 8 +#define FLAC_SUBFRAME_LPC 32 + +#define MAX_FIXED_ORDER 4 +#define MAX_PARTITION_ORDER 8 +#define MAX_PARTITIONS (1 << MAX_PARTITION_ORDER) +#define MAX_LPC_PRECISION 15 +#define MAX_LPC_SHIFT 15 + +enum CodingMode { + CODING_MODE_RICE = 4, + CODING_MODE_RICE2 = 5, +}; + +typedef struct CompressionOptions { + int compression_level; + int block_time_ms; + enum FFLPCType lpc_type; + int lpc_passes; + int lpc_coeff_precision; + int min_prediction_order; + int max_prediction_order; + int prediction_order_method; + int min_partition_order; + int max_partition_order; + int ch_mode; +} CompressionOptions; + +typedef struct RiceContext { + enum CodingMode coding_mode; + int porder; + int params[MAX_PARTITIONS]; +} RiceContext; + +typedef struct FlacSubframe { + int type; + int type_code; + int obits; + int wasted; + int order; + int32_t coefs[MAX_LPC_ORDER]; + int shift; + RiceContext rc; + int32_t samples[FLAC_MAX_BLOCKSIZE]; + int32_t residual[FLAC_MAX_BLOCKSIZE+1]; +} FlacSubframe; + +typedef struct FlacFrame { + FlacSubframe subframes[FLAC_MAX_CHANNELS]; + int blocksize; + int bs_code[2]; + uint8_t crc8; + int ch_mode; + int verbatim_only; +} FlacFrame; + +typedef struct FlacEncodeContext { + AVClass *class; + PutBitContext pb; + int channels; + int samplerate; + int sr_code[2]; + int bps_code; + int max_blocksize; + int min_framesize; + int max_framesize; + int max_encoded_framesize; + uint32_t frame_count; + uint64_t sample_count; + uint8_t md5sum[16]; + FlacFrame frame; + CompressionOptions options; + AVCodecContext *avctx; + LPCContext lpc_ctx; + struct AVMD5 *md5ctx; + uint8_t *md5_buffer; + unsigned int md5_buffer_size; + DSPContext dsp; + FLACDSPContext flac_dsp; +} FlacEncodeContext; + + +/** + * Write streaminfo metadata block to byte array. + */ +static void write_streaminfo(FlacEncodeContext *s, uint8_t *header) +{ + PutBitContext pb; + + memset(header, 0, FLAC_STREAMINFO_SIZE); + init_put_bits(&pb, header, FLAC_STREAMINFO_SIZE); + + /* streaminfo metadata block */ + put_bits(&pb, 16, s->max_blocksize); + put_bits(&pb, 16, s->max_blocksize); + put_bits(&pb, 24, s->min_framesize); + put_bits(&pb, 24, s->max_framesize); + put_bits(&pb, 20, s->samplerate); + put_bits(&pb, 3, s->channels-1); + put_bits(&pb, 5, s->avctx->bits_per_raw_sample - 1); + /* write 36-bit sample count in 2 put_bits() calls */ + put_bits(&pb, 24, (s->sample_count & 0xFFFFFF000LL) >> 12); + put_bits(&pb, 12, s->sample_count & 0x000000FFFLL); + flush_put_bits(&pb); + memcpy(&header[18], s->md5sum, 16); +} + + +/** + * Set blocksize based on samplerate. + * Choose the closest predefined blocksize >= BLOCK_TIME_MS milliseconds. + */ +static int select_blocksize(int samplerate, int block_time_ms) +{ + int i; + int target; + int blocksize; + + av_assert0(samplerate > 0); + blocksize = ff_flac_blocksize_table[1]; + target = (samplerate * block_time_ms) / 1000; + for (i = 0; i < 16; i++) { + if (target >= ff_flac_blocksize_table[i] && + ff_flac_blocksize_table[i] > blocksize) { + blocksize = ff_flac_blocksize_table[i]; + } + } + return blocksize; +} + + +static av_cold void dprint_compression_options(FlacEncodeContext *s) +{ + AVCodecContext *avctx = s->avctx; + CompressionOptions *opt = &s->options; + + av_log(avctx, AV_LOG_DEBUG, " compression: %d\n", opt->compression_level); + + switch (opt->lpc_type) { + case FF_LPC_TYPE_NONE: + av_log(avctx, AV_LOG_DEBUG, " lpc type: None\n"); + break; + case FF_LPC_TYPE_FIXED: + av_log(avctx, AV_LOG_DEBUG, " lpc type: Fixed pre-defined coefficients\n"); + break; + case FF_LPC_TYPE_LEVINSON: + av_log(avctx, AV_LOG_DEBUG, " lpc type: Levinson-Durbin recursion with Welch window\n"); + break; + case FF_LPC_TYPE_CHOLESKY: + av_log(avctx, AV_LOG_DEBUG, " lpc type: Cholesky factorization, %d pass%s\n", + opt->lpc_passes, opt->lpc_passes == 1 ? "" : "es"); + break; + } + + av_log(avctx, AV_LOG_DEBUG, " prediction order: %d, %d\n", + opt->min_prediction_order, opt->max_prediction_order); + + switch (opt->prediction_order_method) { + case ORDER_METHOD_EST: + av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "estimate"); + break; + case ORDER_METHOD_2LEVEL: + av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "2-level"); + break; + case ORDER_METHOD_4LEVEL: + av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "4-level"); + break; + case ORDER_METHOD_8LEVEL: + av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "8-level"); + break; + case ORDER_METHOD_SEARCH: + av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "full search"); + break; + case ORDER_METHOD_LOG: + av_log(avctx, AV_LOG_DEBUG, " order method: %s\n", "log search"); + break; + } + + + av_log(avctx, AV_LOG_DEBUG, " partition order: %d, %d\n", + opt->min_partition_order, opt->max_partition_order); + + av_log(avctx, AV_LOG_DEBUG, " block size: %d\n", avctx->frame_size); + + av_log(avctx, AV_LOG_DEBUG, " lpc precision: %d\n", + opt->lpc_coeff_precision); +} + + +static av_cold int flac_encode_init(AVCodecContext *avctx) +{ + int freq = avctx->sample_rate; + int channels = avctx->channels; + FlacEncodeContext *s = avctx->priv_data; + int i, level, ret; + uint8_t *streaminfo; + + s->avctx = avctx; + + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16: + avctx->bits_per_raw_sample = 16; + s->bps_code = 4; + break; + case AV_SAMPLE_FMT_S32: + if (avctx->bits_per_raw_sample != 24) + av_log(avctx, AV_LOG_WARNING, "encoding as 24 bits-per-sample\n"); + avctx->bits_per_raw_sample = 24; + s->bps_code = 6; + break; + } + + if (channels < 1 || channels > FLAC_MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "%d channels not supported (max %d)\n", + channels, FLAC_MAX_CHANNELS); + return AVERROR(EINVAL); + } + s->channels = channels; + + /* find samplerate in table */ + if (freq < 1) + return -1; + for (i = 4; i < 12; i++) { + if (freq == ff_flac_sample_rate_table[i]) { + s->samplerate = ff_flac_sample_rate_table[i]; + s->sr_code[0] = i; + s->sr_code[1] = 0; + break; + } + } + /* if not in table, samplerate is non-standard */ + if (i == 12) { + if (freq % 1000 == 0 && freq < 255000) { + s->sr_code[0] = 12; + s->sr_code[1] = freq / 1000; + } else if (freq % 10 == 0 && freq < 655350) { + s->sr_code[0] = 14; + s->sr_code[1] = freq / 10; + } else if (freq < 65535) { + s->sr_code[0] = 13; + s->sr_code[1] = freq; + } else { + av_log(avctx, AV_LOG_ERROR, "%d Hz not supported\n", freq); + return AVERROR(EINVAL); + } + s->samplerate = freq; + } + + /* set compression option defaults based on avctx->compression_level */ + if (avctx->compression_level < 0) + s->options.compression_level = 5; + else + s->options.compression_level = avctx->compression_level; + + level = s->options.compression_level; + if (level > 12) { + av_log(avctx, AV_LOG_ERROR, "invalid compression level: %d\n", + s->options.compression_level); + return AVERROR(EINVAL); + } + + s->options.block_time_ms = ((int[]){ 27, 27, 27,105,105,105,105,105,105,105,105,105,105})[level]; + + if (s->options.lpc_type == FF_LPC_TYPE_DEFAULT) + s->options.lpc_type = ((int[]){ FF_LPC_TYPE_FIXED, FF_LPC_TYPE_FIXED, FF_LPC_TYPE_FIXED, + FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, + FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, + FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, FF_LPC_TYPE_LEVINSON, + FF_LPC_TYPE_LEVINSON})[level]; + + s->options.min_prediction_order = ((int[]){ 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})[level]; + s->options.max_prediction_order = ((int[]){ 3, 4, 4, 6, 8, 8, 8, 8, 12, 12, 12, 32, 32})[level]; + + if (s->options.prediction_order_method < 0) + s->options.prediction_order_method = ((int[]){ ORDER_METHOD_EST, ORDER_METHOD_EST, ORDER_METHOD_EST, + ORDER_METHOD_EST, ORDER_METHOD_EST, ORDER_METHOD_EST, + ORDER_METHOD_4LEVEL, ORDER_METHOD_LOG, ORDER_METHOD_4LEVEL, + ORDER_METHOD_LOG, ORDER_METHOD_SEARCH, ORDER_METHOD_LOG, + ORDER_METHOD_SEARCH})[level]; + + if (s->options.min_partition_order > s->options.max_partition_order) { + av_log(avctx, AV_LOG_ERROR, "invalid partition orders: min=%d max=%d\n", + s->options.min_partition_order, s->options.max_partition_order); + return AVERROR(EINVAL); + } + if (s->options.min_partition_order < 0) + s->options.min_partition_order = ((int[]){ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})[level]; + if (s->options.max_partition_order < 0) + s->options.max_partition_order = ((int[]){ 2, 2, 3, 3, 3, 8, 8, 8, 8, 8, 8, 8, 8})[level]; + + if (s->options.lpc_type == FF_LPC_TYPE_NONE) { + s->options.min_prediction_order = 0; + } else if (avctx->min_prediction_order >= 0) { + if (s->options.lpc_type == FF_LPC_TYPE_FIXED) { + if (avctx->min_prediction_order > MAX_FIXED_ORDER) { + av_log(avctx, AV_LOG_ERROR, "invalid min prediction order: %d\n", + avctx->min_prediction_order); + return AVERROR(EINVAL); + } + } else if (avctx->min_prediction_order < MIN_LPC_ORDER || + avctx->min_prediction_order > MAX_LPC_ORDER) { + av_log(avctx, AV_LOG_ERROR, "invalid min prediction order: %d\n", + avctx->min_prediction_order); + return AVERROR(EINVAL); + } + s->options.min_prediction_order = avctx->min_prediction_order; + } + if (s->options.lpc_type == FF_LPC_TYPE_NONE) { + s->options.max_prediction_order = 0; + } else if (avctx->max_prediction_order >= 0) { + if (s->options.lpc_type == FF_LPC_TYPE_FIXED) { + if (avctx->max_prediction_order > MAX_FIXED_ORDER) { + av_log(avctx, AV_LOG_ERROR, "invalid max prediction order: %d\n", + avctx->max_prediction_order); + return AVERROR(EINVAL); + } + } else if (avctx->max_prediction_order < MIN_LPC_ORDER || + avctx->max_prediction_order > MAX_LPC_ORDER) { + av_log(avctx, AV_LOG_ERROR, "invalid max prediction order: %d\n", + avctx->max_prediction_order); + return AVERROR(EINVAL); + } + s->options.max_prediction_order = avctx->max_prediction_order; + } + if (s->options.max_prediction_order < s->options.min_prediction_order) { + av_log(avctx, AV_LOG_ERROR, "invalid prediction orders: min=%d max=%d\n", + s->options.min_prediction_order, s->options.max_prediction_order); + return AVERROR(EINVAL); + } + + if (avctx->frame_size > 0) { + if (avctx->frame_size < FLAC_MIN_BLOCKSIZE || + avctx->frame_size > FLAC_MAX_BLOCKSIZE) { + av_log(avctx, AV_LOG_ERROR, "invalid block size: %d\n", + avctx->frame_size); + return AVERROR(EINVAL); + } + } else { + s->avctx->frame_size = select_blocksize(s->samplerate, s->options.block_time_ms); + } + s->max_blocksize = s->avctx->frame_size; + + /* set maximum encoded frame size in verbatim mode */ + s->max_framesize = ff_flac_get_max_frame_size(s->avctx->frame_size, + s->channels, + s->avctx->bits_per_raw_sample); + + /* initialize MD5 context */ + s->md5ctx = av_md5_alloc(); + if (!s->md5ctx) + return AVERROR(ENOMEM); + av_md5_init(s->md5ctx); + + streaminfo = av_malloc(FLAC_STREAMINFO_SIZE); + if (!streaminfo) + return AVERROR(ENOMEM); + write_streaminfo(s, streaminfo); + avctx->extradata = streaminfo; + avctx->extradata_size = FLAC_STREAMINFO_SIZE; + + s->frame_count = 0; + s->min_framesize = s->max_framesize; + + if (channels == 3 && + avctx->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) || + channels == 4 && + avctx->channel_layout != AV_CH_LAYOUT_2_2 && + avctx->channel_layout != AV_CH_LAYOUT_QUAD || + channels == 5 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT0 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT0_BACK || + channels == 6 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT1 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT1_BACK) { + if (avctx->channel_layout) { + av_log(avctx, AV_LOG_ERROR, "Channel layout not supported by Flac, " + "output stream will have incorrect " + "channel layout.\n"); + } else { + av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The encoder " + "will use Flac channel layout for " + "%d channels.\n", channels); + } + } + + ret = ff_lpc_init(&s->lpc_ctx, avctx->frame_size, + s->options.max_prediction_order, FF_LPC_TYPE_LEVINSON); + + ff_dsputil_init(&s->dsp, avctx); + ff_flacdsp_init(&s->flac_dsp, avctx->sample_fmt, + avctx->bits_per_raw_sample); + + dprint_compression_options(s); + + return ret; +} + + +static void init_frame(FlacEncodeContext *s, int nb_samples) +{ + int i, ch; + FlacFrame *frame; + + frame = &s->frame; + + for (i = 0; i < 16; i++) { + if (nb_samples == ff_flac_blocksize_table[i]) { + frame->blocksize = ff_flac_blocksize_table[i]; + frame->bs_code[0] = i; + frame->bs_code[1] = 0; + break; + } + } + if (i == 16) { + frame->blocksize = nb_samples; + if (frame->blocksize <= 256) { + frame->bs_code[0] = 6; + frame->bs_code[1] = frame->blocksize-1; + } else { + frame->bs_code[0] = 7; + frame->bs_code[1] = frame->blocksize-1; + } + } + + for (ch = 0; ch < s->channels; ch++) { + FlacSubframe *sub = &frame->subframes[ch]; + + sub->wasted = 0; + sub->obits = s->avctx->bits_per_raw_sample; + + if (sub->obits > 16) + sub->rc.coding_mode = CODING_MODE_RICE2; + else + sub->rc.coding_mode = CODING_MODE_RICE; + } + + frame->verbatim_only = 0; +} + + +/** + * Copy channel-interleaved input samples into separate subframes. + */ +static void copy_samples(FlacEncodeContext *s, const void *samples) +{ + int i, j, ch; + FlacFrame *frame; + int shift = av_get_bytes_per_sample(s->avctx->sample_fmt) * 8 - + s->avctx->bits_per_raw_sample; + +#define COPY_SAMPLES(bits) do { \ + const int ## bits ## _t *samples0 = samples; \ + frame = &s->frame; \ + for (i = 0, j = 0; i < frame->blocksize; i++) \ + for (ch = 0; ch < s->channels; ch++, j++) \ + frame->subframes[ch].samples[i] = samples0[j] >> shift; \ +} while (0) + + if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S16) + COPY_SAMPLES(16); + else + COPY_SAMPLES(32); +} + + +static uint64_t rice_count_exact(int32_t *res, int n, int k) +{ + int i; + uint64_t count = 0; + + for (i = 0; i < n; i++) { + int32_t v = -2 * res[i] - 1; + v ^= v >> 31; + count += (v >> k) + 1 + k; + } + return count; +} + + +static uint64_t subframe_count_exact(FlacEncodeContext *s, FlacSubframe *sub, + int pred_order) +{ + int p, porder, psize; + int i, part_end; + uint64_t count = 0; + + /* subframe header */ + count += 8; + + /* subframe */ + if (sub->type == FLAC_SUBFRAME_CONSTANT) { + count += sub->obits; + } else if (sub->type == FLAC_SUBFRAME_VERBATIM) { + count += s->frame.blocksize * sub->obits; + } else { + /* warm-up samples */ + count += pred_order * sub->obits; + + /* LPC coefficients */ + if (sub->type == FLAC_SUBFRAME_LPC) + count += 4 + 5 + pred_order * s->options.lpc_coeff_precision; + + /* rice-encoded block */ + count += 2; + + /* partition order */ + porder = sub->rc.porder; + psize = s->frame.blocksize >> porder; + count += 4; + + /* residual */ + i = pred_order; + part_end = psize; + for (p = 0; p < 1 << porder; p++) { + int k = sub->rc.params[p]; + count += sub->rc.coding_mode; + count += rice_count_exact(&sub->residual[i], part_end - i, k); + i = part_end; + part_end = FFMIN(s->frame.blocksize, part_end + psize); + } + } + + return count; +} + + +#define rice_encode_count(sum, n, k) (((n)*((k)+1))+((sum-(n>>1))>>(k))) + +/** + * Solve for d/dk(rice_encode_count) = n-((sum-(n>>1))>>(k+1)) = 0. + */ +static int find_optimal_param(uint64_t sum, int n, int max_param) +{ + int k; + uint64_t sum2; + + if (sum <= n >> 1) + return 0; + sum2 = sum - (n >> 1); + k = av_log2(av_clipl_int32(sum2 / n)); + return FFMIN(k, max_param); +} + + +static uint64_t calc_optimal_rice_params(RiceContext *rc, int porder, + uint64_t *sums, int n, int pred_order) +{ + int i; + int k, cnt, part, max_param; + uint64_t all_bits; + + max_param = (1 << rc->coding_mode) - 2; + + part = (1 << porder); + all_bits = 4 * part; + + cnt = (n >> porder) - pred_order; + for (i = 0; i < part; i++) { + k = find_optimal_param(sums[i], cnt, max_param); + rc->params[i] = k; + all_bits += rice_encode_count(sums[i], cnt, k); + cnt = n >> porder; + } + + rc->porder = porder; + + return all_bits; +} + + +static void calc_sums(int pmin, int pmax, uint32_t *data, int n, int pred_order, + uint64_t sums[][MAX_PARTITIONS]) +{ + int i, j; + int parts; + uint32_t *res, *res_end; + + /* sums for highest level */ + parts = (1 << pmax); + res = &data[pred_order]; + res_end = &data[n >> pmax]; + for (i = 0; i < parts; i++) { + uint64_t sum = 0; + while (res < res_end) + sum += *(res++); + sums[pmax][i] = sum; + res_end += n >> pmax; + } + /* sums for lower levels */ + for (i = pmax - 1; i >= pmin; i--) { + parts = (1 << i); + for (j = 0; j < parts; j++) + sums[i][j] = sums[i+1][2*j] + sums[i+1][2*j+1]; + } +} + + +static uint64_t calc_rice_params(RiceContext *rc, int pmin, int pmax, + int32_t *data, int n, int pred_order) +{ + int i; + uint64_t bits[MAX_PARTITION_ORDER+1]; + int opt_porder; + RiceContext tmp_rc; + uint32_t *udata; + uint64_t sums[MAX_PARTITION_ORDER+1][MAX_PARTITIONS]; + + av_assert1(pmin >= 0 && pmin <= MAX_PARTITION_ORDER); + av_assert1(pmax >= 0 && pmax <= MAX_PARTITION_ORDER); + av_assert1(pmin <= pmax); + + tmp_rc.coding_mode = rc->coding_mode; + + udata = av_malloc(n * sizeof(uint32_t)); + for (i = 0; i < n; i++) + udata[i] = (2*data[i]) ^ (data[i]>>31); + + calc_sums(pmin, pmax, udata, n, pred_order, sums); + + opt_porder = pmin; + bits[pmin] = UINT32_MAX; + for (i = pmin; i <= pmax; i++) { + bits[i] = calc_optimal_rice_params(&tmp_rc, i, sums[i], n, pred_order); + if (bits[i] <= bits[opt_porder]) { + opt_porder = i; + *rc = tmp_rc; + } + } + + av_freep(&udata); + return bits[opt_porder]; +} + + +static int get_max_p_order(int max_porder, int n, int order) +{ + int porder = FFMIN(max_porder, av_log2(n^(n-1))); + if (order > 0) + porder = FFMIN(porder, av_log2(n/order)); + return porder; +} + + +static uint64_t find_subframe_rice_params(FlacEncodeContext *s, + FlacSubframe *sub, int pred_order) +{ + int pmin = get_max_p_order(s->options.min_partition_order, + s->frame.blocksize, pred_order); + int pmax = get_max_p_order(s->options.max_partition_order, + s->frame.blocksize, pred_order); + + uint64_t bits = 8 + pred_order * sub->obits + 2 + sub->rc.coding_mode; + if (sub->type == FLAC_SUBFRAME_LPC) + bits += 4 + 5 + pred_order * s->options.lpc_coeff_precision; + bits += calc_rice_params(&sub->rc, pmin, pmax, sub->residual, + s->frame.blocksize, pred_order); + return bits; +} + + +static void encode_residual_fixed(int32_t *res, const int32_t *smp, int n, + int order) +{ + int i; + + for (i = 0; i < order; i++) + res[i] = smp[i]; + + if (order == 0) { + for (i = order; i < n; i++) + res[i] = smp[i]; + } else if (order == 1) { + for (i = order; i < n; i++) + res[i] = smp[i] - smp[i-1]; + } else if (order == 2) { + int a = smp[order-1] - smp[order-2]; + for (i = order; i < n; i += 2) { + int b = smp[i ] - smp[i-1]; + res[i] = b - a; + a = smp[i+1] - smp[i ]; + res[i+1] = a - b; + } + } else if (order == 3) { + int a = smp[order-1] - smp[order-2]; + int c = smp[order-1] - 2*smp[order-2] + smp[order-3]; + for (i = order; i < n; i += 2) { + int b = smp[i ] - smp[i-1]; + int d = b - a; + res[i] = d - c; + a = smp[i+1] - smp[i ]; + c = a - b; + res[i+1] = c - d; + } + } else { + int a = smp[order-1] - smp[order-2]; + int c = smp[order-1] - 2*smp[order-2] + smp[order-3]; + int e = smp[order-1] - 3*smp[order-2] + 3*smp[order-3] - smp[order-4]; + for (i = order; i < n; i += 2) { + int b = smp[i ] - smp[i-1]; + int d = b - a; + int f = d - c; + res[i ] = f - e; + a = smp[i+1] - smp[i ]; + c = a - b; + e = c - d; + res[i+1] = e - f; + } + } +} + + +static int encode_residual_ch(FlacEncodeContext *s, int ch) +{ + int i, n; + int min_order, max_order, opt_order, omethod; + FlacFrame *frame; + FlacSubframe *sub; + int32_t coefs[MAX_LPC_ORDER][MAX_LPC_ORDER]; + int shift[MAX_LPC_ORDER]; + int32_t *res, *smp; + + frame = &s->frame; + sub = &frame->subframes[ch]; + res = sub->residual; + smp = sub->samples; + n = frame->blocksize; + + /* CONSTANT */ + for (i = 1; i < n; i++) + if(smp[i] != smp[0]) + break; + if (i == n) { + sub->type = sub->type_code = FLAC_SUBFRAME_CONSTANT; + res[0] = smp[0]; + return subframe_count_exact(s, sub, 0); + } + + /* VERBATIM */ + if (frame->verbatim_only || n < 5) { + sub->type = sub->type_code = FLAC_SUBFRAME_VERBATIM; + memcpy(res, smp, n * sizeof(int32_t)); + return subframe_count_exact(s, sub, 0); + } + + min_order = s->options.min_prediction_order; + max_order = s->options.max_prediction_order; + omethod = s->options.prediction_order_method; + + /* FIXED */ + sub->type = FLAC_SUBFRAME_FIXED; + if (s->options.lpc_type == FF_LPC_TYPE_NONE || + s->options.lpc_type == FF_LPC_TYPE_FIXED || n <= max_order) { + uint64_t bits[MAX_FIXED_ORDER+1]; + if (max_order > MAX_FIXED_ORDER) + max_order = MAX_FIXED_ORDER; + opt_order = 0; + bits[0] = UINT32_MAX; + for (i = min_order; i <= max_order; i++) { + encode_residual_fixed(res, smp, n, i); + bits[i] = find_subframe_rice_params(s, sub, i); + if (bits[i] < bits[opt_order]) + opt_order = i; + } + sub->order = opt_order; + sub->type_code = sub->type | sub->order; + if (sub->order != max_order) { + encode_residual_fixed(res, smp, n, sub->order); + find_subframe_rice_params(s, sub, sub->order); + } + return subframe_count_exact(s, sub, sub->order); + } + + /* LPC */ + sub->type = FLAC_SUBFRAME_LPC; + opt_order = ff_lpc_calc_coefs(&s->lpc_ctx, smp, n, min_order, max_order, + s->options.lpc_coeff_precision, coefs, shift, s->options.lpc_type, + s->options.lpc_passes, omethod, + MAX_LPC_SHIFT, 0); + + if (omethod == ORDER_METHOD_2LEVEL || + omethod == ORDER_METHOD_4LEVEL || + omethod == ORDER_METHOD_8LEVEL) { + int levels = 1 << omethod; + uint64_t bits[1 << ORDER_METHOD_8LEVEL]; + int order = -1; + int opt_index = levels-1; + opt_order = max_order-1; + bits[opt_index] = UINT32_MAX; + for (i = levels-1; i >= 0; i--) { + int last_order = order; + order = min_order + (((max_order-min_order+1) * (i+1)) / levels)-1; + order = av_clip(order, min_order - 1, max_order - 1); + if (order == last_order) + continue; + s->flac_dsp.lpc_encode(res, smp, n, order+1, coefs[order], + shift[order]); + bits[i] = find_subframe_rice_params(s, sub, order+1); + if (bits[i] < bits[opt_index]) { + opt_index = i; + opt_order = order; + } + } + opt_order++; + } else if (omethod == ORDER_METHOD_SEARCH) { + // brute-force optimal order search + uint64_t bits[MAX_LPC_ORDER]; + opt_order = 0; + bits[0] = UINT32_MAX; + for (i = min_order-1; i < max_order; i++) { + s->flac_dsp.lpc_encode(res, smp, n, i+1, coefs[i], shift[i]); + bits[i] = find_subframe_rice_params(s, sub, i+1); + if (bits[i] < bits[opt_order]) + opt_order = i; + } + opt_order++; + } else if (omethod == ORDER_METHOD_LOG) { + uint64_t bits[MAX_LPC_ORDER]; + int step; + + opt_order = min_order - 1 + (max_order-min_order)/3; + memset(bits, -1, sizeof(bits)); + + for (step = 16; step; step >>= 1) { + int last = opt_order; + for (i = last-step; i <= last+step; i += step) { + if (i < min_order-1 || i >= max_order || bits[i] < UINT32_MAX) + continue; + s->flac_dsp.lpc_encode(res, smp, n, i+1, coefs[i], shift[i]); + bits[i] = find_subframe_rice_params(s, sub, i+1); + if (bits[i] < bits[opt_order]) + opt_order = i; + } + } + opt_order++; + } + + sub->order = opt_order; + sub->type_code = sub->type | (sub->order-1); + sub->shift = shift[sub->order-1]; + for (i = 0; i < sub->order; i++) + sub->coefs[i] = coefs[sub->order-1][i]; + + s->flac_dsp.lpc_encode(res, smp, n, sub->order, sub->coefs, sub->shift); + + find_subframe_rice_params(s, sub, sub->order); + + return subframe_count_exact(s, sub, sub->order); +} + + +static int count_frame_header(FlacEncodeContext *s) +{ + uint8_t av_unused tmp; + int count; + + /* + <14> Sync code + <1> Reserved + <1> Blocking strategy + <4> Block size in inter-channel samples + <4> Sample rate + <4> Channel assignment + <3> Sample size in bits + <1> Reserved + */ + count = 32; + + /* coded frame number */ + PUT_UTF8(s->frame_count, tmp, count += 8;) + + /* explicit block size */ + if (s->frame.bs_code[0] == 6) + count += 8; + else if (s->frame.bs_code[0] == 7) + count += 16; + + /* explicit sample rate */ + count += ((s->sr_code[0] == 12) + (s->sr_code[0] > 12)) * 8; + + /* frame header CRC-8 */ + count += 8; + + return count; +} + + +static int encode_frame(FlacEncodeContext *s) +{ + int ch; + uint64_t count; + + count = count_frame_header(s); + + for (ch = 0; ch < s->channels; ch++) + count += encode_residual_ch(s, ch); + + count += (8 - (count & 7)) & 7; // byte alignment + count += 16; // CRC-16 + + count >>= 3; + if (count > INT_MAX) + return AVERROR_BUG; + return count; +} + + +static void remove_wasted_bits(FlacEncodeContext *s) +{ + int ch, i; + + for (ch = 0; ch < s->channels; ch++) { + FlacSubframe *sub = &s->frame.subframes[ch]; + int32_t v = 0; + + for (i = 0; i < s->frame.blocksize; i++) { + v |= sub->samples[i]; + if (v & 1) + break; + } + + if (v && !(v & 1)) { + v = av_ctz(v); + + for (i = 0; i < s->frame.blocksize; i++) + sub->samples[i] >>= v; + + sub->wasted = v; + sub->obits -= v; + + /* for 24-bit, check if removing wasted bits makes the range better + suited for using RICE instead of RICE2 for entropy coding */ + if (sub->obits <= 17) + sub->rc.coding_mode = CODING_MODE_RICE; + } + } +} + + +static int estimate_stereo_mode(int32_t *left_ch, int32_t *right_ch, int n, + int max_rice_param) +{ + int i, best; + int32_t lt, rt; + uint64_t sum[4]; + uint64_t score[4]; + int k; + + /* calculate sum of 2nd order residual for each channel */ + sum[0] = sum[1] = sum[2] = sum[3] = 0; + for (i = 2; i < n; i++) { + lt = left_ch[i] - 2*left_ch[i-1] + left_ch[i-2]; + rt = right_ch[i] - 2*right_ch[i-1] + right_ch[i-2]; + sum[2] += FFABS((lt + rt) >> 1); + sum[3] += FFABS(lt - rt); + sum[0] += FFABS(lt); + sum[1] += FFABS(rt); + } + /* estimate bit counts */ + for (i = 0; i < 4; i++) { + k = find_optimal_param(2 * sum[i], n, max_rice_param); + sum[i] = rice_encode_count( 2 * sum[i], n, k); + } + + /* calculate score for each mode */ + score[0] = sum[0] + sum[1]; + score[1] = sum[0] + sum[3]; + score[2] = sum[1] + sum[3]; + score[3] = sum[2] + sum[3]; + + /* return mode with lowest score */ + best = 0; + for (i = 1; i < 4; i++) + if (score[i] < score[best]) + best = i; + + return best; +} + + +/** + * Perform stereo channel decorrelation. + */ +static void channel_decorrelation(FlacEncodeContext *s) +{ + FlacFrame *frame; + int32_t *left, *right; + int i, n; + + frame = &s->frame; + n = frame->blocksize; + left = frame->subframes[0].samples; + right = frame->subframes[1].samples; + + if (s->channels != 2) { + frame->ch_mode = FLAC_CHMODE_INDEPENDENT; + return; + } + + if (s->options.ch_mode < 0) { + int max_rice_param = (1 << frame->subframes[0].rc.coding_mode) - 2; + frame->ch_mode = estimate_stereo_mode(left, right, n, max_rice_param); + } else + frame->ch_mode = s->options.ch_mode; + + /* perform decorrelation and adjust bits-per-sample */ + if (frame->ch_mode == FLAC_CHMODE_INDEPENDENT) + return; + if (frame->ch_mode == FLAC_CHMODE_MID_SIDE) { + int32_t tmp; + for (i = 0; i < n; i++) { + tmp = left[i]; + left[i] = (tmp + right[i]) >> 1; + right[i] = tmp - right[i]; + } + frame->subframes[1].obits++; + } else if (frame->ch_mode == FLAC_CHMODE_LEFT_SIDE) { + for (i = 0; i < n; i++) + right[i] = left[i] - right[i]; + frame->subframes[1].obits++; + } else { + for (i = 0; i < n; i++) + left[i] -= right[i]; + frame->subframes[0].obits++; + } +} + + +static void write_utf8(PutBitContext *pb, uint32_t val) +{ + uint8_t tmp; + PUT_UTF8(val, tmp, put_bits(pb, 8, tmp);) +} + + +static void write_frame_header(FlacEncodeContext *s) +{ + FlacFrame *frame; + int crc; + + frame = &s->frame; + + put_bits(&s->pb, 16, 0xFFF8); + put_bits(&s->pb, 4, frame->bs_code[0]); + put_bits(&s->pb, 4, s->sr_code[0]); + + if (frame->ch_mode == FLAC_CHMODE_INDEPENDENT) + put_bits(&s->pb, 4, s->channels-1); + else + put_bits(&s->pb, 4, frame->ch_mode + FLAC_MAX_CHANNELS - 1); + + put_bits(&s->pb, 3, s->bps_code); + put_bits(&s->pb, 1, 0); + write_utf8(&s->pb, s->frame_count); + + if (frame->bs_code[0] == 6) + put_bits(&s->pb, 8, frame->bs_code[1]); + else if (frame->bs_code[0] == 7) + put_bits(&s->pb, 16, frame->bs_code[1]); + + if (s->sr_code[0] == 12) + put_bits(&s->pb, 8, s->sr_code[1]); + else if (s->sr_code[0] > 12) + put_bits(&s->pb, 16, s->sr_code[1]); + + flush_put_bits(&s->pb); + crc = av_crc(av_crc_get_table(AV_CRC_8_ATM), 0, s->pb.buf, + put_bits_count(&s->pb) >> 3); + put_bits(&s->pb, 8, crc); +} + + +static void write_subframes(FlacEncodeContext *s) +{ + int ch; + + for (ch = 0; ch < s->channels; ch++) { + FlacSubframe *sub = &s->frame.subframes[ch]; + int i, p, porder, psize; + int32_t *part_end; + int32_t *res = sub->residual; + int32_t *frame_end = &sub->residual[s->frame.blocksize]; + + /* subframe header */ + put_bits(&s->pb, 1, 0); + put_bits(&s->pb, 6, sub->type_code); + put_bits(&s->pb, 1, !!sub->wasted); + if (sub->wasted) + put_bits(&s->pb, sub->wasted, 1); + + /* subframe */ + if (sub->type == FLAC_SUBFRAME_CONSTANT) { + put_sbits(&s->pb, sub->obits, res[0]); + } else if (sub->type == FLAC_SUBFRAME_VERBATIM) { + while (res < frame_end) + put_sbits(&s->pb, sub->obits, *res++); + } else { + /* warm-up samples */ + for (i = 0; i < sub->order; i++) + put_sbits(&s->pb, sub->obits, *res++); + + /* LPC coefficients */ + if (sub->type == FLAC_SUBFRAME_LPC) { + int cbits = s->options.lpc_coeff_precision; + put_bits( &s->pb, 4, cbits-1); + put_sbits(&s->pb, 5, sub->shift); + for (i = 0; i < sub->order; i++) + put_sbits(&s->pb, cbits, sub->coefs[i]); + } + + /* rice-encoded block */ + put_bits(&s->pb, 2, sub->rc.coding_mode - 4); + + /* partition order */ + porder = sub->rc.porder; + psize = s->frame.blocksize >> porder; + put_bits(&s->pb, 4, porder); + + /* residual */ + part_end = &sub->residual[psize]; + for (p = 0; p < 1 << porder; p++) { + int k = sub->rc.params[p]; + put_bits(&s->pb, sub->rc.coding_mode, k); + while (res < part_end) + set_sr_golomb_flac(&s->pb, *res++, k, INT32_MAX, 0); + part_end = FFMIN(frame_end, part_end + psize); + } + } + } +} + + +static void write_frame_footer(FlacEncodeContext *s) +{ + int crc; + flush_put_bits(&s->pb); + crc = av_bswap16(av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, s->pb.buf, + put_bits_count(&s->pb)>>3)); + put_bits(&s->pb, 16, crc); + flush_put_bits(&s->pb); +} + + +static int write_frame(FlacEncodeContext *s, AVPacket *avpkt) +{ + init_put_bits(&s->pb, avpkt->data, avpkt->size); + write_frame_header(s); + write_subframes(s); + write_frame_footer(s); + return put_bits_count(&s->pb) >> 3; +} + + +static int update_md5_sum(FlacEncodeContext *s, const void *samples) +{ + const uint8_t *buf; + int buf_size = s->frame.blocksize * s->channels * + ((s->avctx->bits_per_raw_sample + 7) / 8); + + if (s->avctx->bits_per_raw_sample > 16 || HAVE_BIGENDIAN) { + av_fast_malloc(&s->md5_buffer, &s->md5_buffer_size, buf_size); + if (!s->md5_buffer) + return AVERROR(ENOMEM); + } + + if (s->avctx->bits_per_raw_sample <= 16) { + buf = (const uint8_t *)samples; +#if HAVE_BIGENDIAN + s->dsp.bswap16_buf((uint16_t *)s->md5_buffer, + (const uint16_t *)samples, buf_size / 2); + buf = s->md5_buffer; +#endif + } else { + int i; + const int32_t *samples0 = samples; + uint8_t *tmp = s->md5_buffer; + + for (i = 0; i < s->frame.blocksize * s->channels; i++) { + int32_t v = samples0[i] >> 8; + *tmp++ = (v ) & 0xFF; + *tmp++ = (v >> 8) & 0xFF; + *tmp++ = (v >> 16) & 0xFF; + } + buf = s->md5_buffer; + } + av_md5_update(s->md5ctx, buf, buf_size); + + return 0; +} + + +static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + FlacEncodeContext *s; + int frame_bytes, out_bytes, ret; + + s = avctx->priv_data; + + /* when the last block is reached, update the header in extradata */ + if (!frame) { + s->max_framesize = s->max_encoded_framesize; + av_md5_final(s->md5ctx, s->md5sum); + write_streaminfo(s, avctx->extradata); + return 0; + } + + /* change max_framesize for small final frame */ + if (frame->nb_samples < s->frame.blocksize) { + s->max_framesize = ff_flac_get_max_frame_size(frame->nb_samples, + s->channels, + avctx->bits_per_raw_sample); + } + + init_frame(s, frame->nb_samples); + + copy_samples(s, frame->data[0]); + + channel_decorrelation(s); + + remove_wasted_bits(s); + + frame_bytes = encode_frame(s); + + /* fallback to verbatim mode if the compressed frame is larger than it + would be if encoded uncompressed. */ + if (frame_bytes < 0 || frame_bytes > s->max_framesize) { + s->frame.verbatim_only = 1; + frame_bytes = encode_frame(s); + if (frame_bytes < 0) { + av_log(avctx, AV_LOG_ERROR, "Bad frame count\n"); + return frame_bytes; + } + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, frame_bytes)) < 0) + return ret; + + out_bytes = write_frame(s, avpkt); + + s->frame_count++; + s->sample_count += frame->nb_samples; + if ((ret = update_md5_sum(s, frame->data[0])) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error updating MD5 checksum\n"); + return ret; + } + if (out_bytes > s->max_encoded_framesize) + s->max_encoded_framesize = out_bytes; + if (out_bytes < s->min_framesize) + s->min_framesize = out_bytes; + + avpkt->pts = frame->pts; + avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); + avpkt->size = out_bytes; + *got_packet_ptr = 1; + return 0; +} + + +static av_cold int flac_encode_close(AVCodecContext *avctx) +{ + if (avctx->priv_data) { + FlacEncodeContext *s = avctx->priv_data; + av_freep(&s->md5ctx); + av_freep(&s->md5_buffer); + ff_lpc_end(&s->lpc_ctx); + } + av_freep(&avctx->extradata); + avctx->extradata_size = 0; + return 0; +} + +#define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM +static const AVOption options[] = { +{ "lpc_coeff_precision", "LPC coefficient precision", offsetof(FlacEncodeContext, options.lpc_coeff_precision), AV_OPT_TYPE_INT, {.i64 = 15 }, 0, MAX_LPC_PRECISION, FLAGS }, +{ "lpc_type", "LPC algorithm", offsetof(FlacEncodeContext, options.lpc_type), AV_OPT_TYPE_INT, {.i64 = FF_LPC_TYPE_DEFAULT }, FF_LPC_TYPE_DEFAULT, FF_LPC_TYPE_NB-1, FLAGS, "lpc_type" }, +{ "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_NONE }, INT_MIN, INT_MAX, FLAGS, "lpc_type" }, +{ "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_FIXED }, INT_MIN, INT_MAX, FLAGS, "lpc_type" }, +{ "levinson", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_LEVINSON }, INT_MIN, INT_MAX, FLAGS, "lpc_type" }, +{ "cholesky", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LPC_TYPE_CHOLESKY }, INT_MIN, INT_MAX, FLAGS, "lpc_type" }, +{ "lpc_passes", "Number of passes to use for Cholesky factorization during LPC analysis", offsetof(FlacEncodeContext, options.lpc_passes), AV_OPT_TYPE_INT, {.i64 = 2 }, 1, INT_MAX, FLAGS }, +{ "min_partition_order", NULL, offsetof(FlacEncodeContext, options.min_partition_order), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_PARTITION_ORDER, FLAGS }, +{ "max_partition_order", NULL, offsetof(FlacEncodeContext, options.max_partition_order), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, MAX_PARTITION_ORDER, FLAGS }, +{ "prediction_order_method", "Search method for selecting prediction order", offsetof(FlacEncodeContext, options.prediction_order_method), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, ORDER_METHOD_LOG, FLAGS, "predm" }, +{ "estimation", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_EST }, INT_MIN, INT_MAX, FLAGS, "predm" }, +{ "2level", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_2LEVEL }, INT_MIN, INT_MAX, FLAGS, "predm" }, +{ "4level", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_4LEVEL }, INT_MIN, INT_MAX, FLAGS, "predm" }, +{ "8level", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_8LEVEL }, INT_MIN, INT_MAX, FLAGS, "predm" }, +{ "search", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_SEARCH }, INT_MIN, INT_MAX, FLAGS, "predm" }, +{ "log", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = ORDER_METHOD_LOG }, INT_MIN, INT_MAX, FLAGS, "predm" }, +{ "ch_mode", "Stereo decorrelation mode", offsetof(FlacEncodeContext, options.ch_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, FLAC_CHMODE_MID_SIDE, FLAGS, "ch_mode" }, +{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, +{ "indep", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_INDEPENDENT }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, +{ "left_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_LEFT_SIDE }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, +{ "right_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_RIGHT_SIDE }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, +{ "mid_side", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FLAC_CHMODE_MID_SIDE }, INT_MIN, INT_MAX, FLAGS, "ch_mode" }, +{ NULL }, +}; + +static const AVClass flac_encoder_class = { + "FLAC encoder", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_flac_encoder = { + .name = "flac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_FLAC, + .priv_data_size = sizeof(FlacEncodeContext), + .init = flac_encode_init, + .encode2 = flac_encode_frame, + .close = flac_encode_close, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY | CODEC_CAP_LOSSLESS, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), + .priv_class = &flac_encoder_class, +}; diff --git a/ffmpeg/libavcodec/flashsv.c b/ffmpeg/libavcodec/flashsv.c new file mode 100644 index 0000000..9982b5e --- /dev/null +++ b/ffmpeg/libavcodec/flashsv.c @@ -0,0 +1,551 @@ +/* + * Flash Screen Video decoder + * Copyright (C) 2004 Alex Beregszaszi + * Copyright (C) 2006 Benjamin Larsson + * + * 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 + */ + +/** + * @file + * Flash Screen Video decoder + * @author Alex Beregszaszi + * @author Benjamin Larsson + * @author Daniel Verkamp + * @author Konstantin Shishkov + * + * A description of the bitstream format for Flash Screen Video version 1/2 + * is part of the SWF File Format Specification (version 10), which can be + * downloaded from http://www.adobe.com/devnet/swf.html. + */ + +#include +#include +#include + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" + +typedef struct BlockInfo { + uint8_t *pos; + int size; +} BlockInfo; + +typedef struct FlashSVContext { + AVCodecContext *avctx; + AVFrame frame; + int image_width, image_height; + int block_width, block_height; + uint8_t *tmpblock; + int block_size; + z_stream zstream; + int ver; + const uint32_t *pal; + int is_keyframe; + uint8_t *keyframedata; + uint8_t *keyframe; + BlockInfo *blocks; + uint8_t *deflate_block; + int deflate_block_size; + int color_depth; + int zlibprime_curr, zlibprime_prev; + int diff_start, diff_height; +} FlashSVContext; + + +static int decode_hybrid(const uint8_t *sptr, uint8_t *dptr, int dx, int dy, + int h, int w, int stride, const uint32_t *pal) +{ + int x, y; + const uint8_t *orig_src = sptr; + + for (y = dx+h; y > dx; y--) { + uint8_t *dst = dptr + (y * stride) + dy * 3; + for (x = 0; x < w; x++) { + if (*sptr & 0x80) { + /* 15-bit color */ + unsigned c = AV_RB16(sptr) & ~0x8000; + unsigned b = c & 0x1F; + unsigned g = (c >> 5) & 0x1F; + unsigned r = c >> 10; + /* 000aaabb -> aaabbaaa */ + *dst++ = (b << 3) | (b >> 2); + *dst++ = (g << 3) | (g >> 2); + *dst++ = (r << 3) | (r >> 2); + sptr += 2; + } else { + /* palette index */ + uint32_t c = pal[*sptr++]; + bytestream_put_le24(&dst, c); + } + } + } + return sptr - orig_src; +} + +static av_cold int flashsv_decode_init(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + int zret; // Zlib return code + + s->avctx = avctx; + s->zstream.zalloc = Z_NULL; + s->zstream.zfree = Z_NULL; + s->zstream.opaque = Z_NULL; + zret = inflateInit(&s->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return 1; + } + avctx->pix_fmt = AV_PIX_FMT_BGR24; + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + + +static int flashsv2_prime(FlashSVContext *s, uint8_t *src, int size) +{ + z_stream zs; + int zret; // Zlib return code + + if (!src) + return AVERROR_INVALIDDATA; + + zs.zalloc = NULL; + zs.zfree = NULL; + zs.opaque = NULL; + + s->zstream.next_in = src; + s->zstream.avail_in = size; + s->zstream.next_out = s->tmpblock; + s->zstream.avail_out = s->block_size * 3; + inflate(&s->zstream, Z_SYNC_FLUSH); + + if (deflateInit(&zs, 0) != Z_OK) + return -1; + zs.next_in = s->tmpblock; + zs.avail_in = s->block_size * 3 - s->zstream.avail_out; + zs.next_out = s->deflate_block; + zs.avail_out = s->deflate_block_size; + deflate(&zs, Z_SYNC_FLUSH); + deflateEnd(&zs); + + if ((zret = inflateReset(&s->zstream)) != Z_OK) { + av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); + return AVERROR_UNKNOWN; + } + + s->zstream.next_in = s->deflate_block; + s->zstream.avail_in = s->deflate_block_size - zs.avail_out; + s->zstream.next_out = s->tmpblock; + s->zstream.avail_out = s->block_size * 3; + inflate(&s->zstream, Z_SYNC_FLUSH); + + return 0; +} + +static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt, + GetBitContext *gb, int block_size, + int width, int height, int x_pos, int y_pos, + int blk_idx) +{ + struct FlashSVContext *s = avctx->priv_data; + uint8_t *line = s->tmpblock; + int k; + int ret = inflateReset(&s->zstream); + if (ret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); + return AVERROR_UNKNOWN; + } + if (s->zlibprime_curr || s->zlibprime_prev) { + ret = flashsv2_prime(s, + s->blocks[blk_idx].pos, + s->blocks[blk_idx].size); + if (ret < 0) + return ret; + } + s->zstream.next_in = avpkt->data + get_bits_count(gb) / 8; + s->zstream.avail_in = block_size; + s->zstream.next_out = s->tmpblock; + s->zstream.avail_out = s->block_size * 3; + ret = inflate(&s->zstream, Z_FINISH); + if (ret == Z_DATA_ERROR) { + av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); + inflateSync(&s->zstream); + ret = inflate(&s->zstream, Z_FINISH); + } + + if (ret != Z_OK && ret != Z_STREAM_END) { + //return -1; + } + + if (s->is_keyframe) { + s->blocks[blk_idx].pos = s->keyframedata + (get_bits_count(gb) / 8); + s->blocks[blk_idx].size = block_size; + } + if (!s->color_depth) { + /* Flash Screen Video stores the image upside down, so copy + * lines to destination in reverse order. */ + for (k = 1; k <= s->diff_height; k++) { + memcpy(s->frame.data[0] + x_pos * 3 + + (s->image_height - y_pos - s->diff_start - k) * s->frame.linesize[0], + line, width * 3); + /* advance source pointer to next line */ + line += width * 3; + } + } else { + /* hybrid 15-bit/palette mode */ + decode_hybrid(s->tmpblock, s->frame.data[0], + s->image_height - (y_pos + 1 + s->diff_start + s->diff_height), + x_pos, s->diff_height, width, + s->frame.linesize[0], s->pal); + } + skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */ + return 0; +} + +static int calc_deflate_block_size(int tmpblock_size) +{ + z_stream zstream; + int size; + + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + if (deflateInit(&zstream, 0) != Z_OK) + return -1; + size = deflateBound(&zstream, tmpblock_size); + deflateEnd(&zstream); + + return size; +} + +static int flashsv_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + int buf_size = avpkt->size; + FlashSVContext *s = avctx->priv_data; + int h_blocks, v_blocks, h_part, v_part, i, j, ret; + GetBitContext gb; + int last_blockwidth = s->block_width; + int last_blockheight= s->block_height; + + /* no supplementary picture */ + if (buf_size == 0) + return 0; + if (buf_size < 4) + return -1; + + init_get_bits(&gb, avpkt->data, buf_size * 8); + + /* start to parse the bitstream */ + s->block_width = 16 * (get_bits(&gb, 4) + 1); + s->image_width = get_bits(&gb, 12); + s->block_height = 16 * (get_bits(&gb, 4) + 1); + s->image_height = get_bits(&gb, 12); + + if ( last_blockwidth != s->block_width + || last_blockheight!= s->block_height) + av_freep(&s->blocks); + + if (s->ver == 2) { + skip_bits(&gb, 6); + if (get_bits1(&gb)) { + avpriv_request_sample(avctx, "iframe"); + return AVERROR_PATCHWELCOME; + } + if (get_bits1(&gb)) { + avpriv_request_sample(avctx, "Custom palette"); + return AVERROR_PATCHWELCOME; + } + } + + /* calculate number of blocks and size of border (partial) blocks */ + h_blocks = s->image_width / s->block_width; + h_part = s->image_width % s->block_width; + v_blocks = s->image_height / s->block_height; + v_part = s->image_height % s->block_height; + + /* the block size could change between frames, make sure the buffer + * is large enough, if not, get a larger one */ + if (s->block_size < s->block_width * s->block_height) { + int tmpblock_size = 3 * s->block_width * s->block_height; + + s->tmpblock = av_realloc(s->tmpblock, tmpblock_size); + if (!s->tmpblock) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + if (s->ver == 2) { + s->deflate_block_size = calc_deflate_block_size(tmpblock_size); + if (s->deflate_block_size <= 0) { + av_log(avctx, AV_LOG_ERROR, "Can't determine deflate buffer size.\n"); + return -1; + } + s->deflate_block = av_realloc(s->deflate_block, s->deflate_block_size); + if (!s->deflate_block) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate deflate buffer.\n"); + return AVERROR(ENOMEM); + } + } + } + s->block_size = s->block_width * s->block_height; + + /* initialize the image size once */ + if (avctx->width == 0 && avctx->height == 0) { + avcodec_set_dimensions(avctx, s->image_width, s->image_height); + } + + /* check for changes of image width and image height */ + if (avctx->width != s->image_width || avctx->height != s->image_height) { + av_log(avctx, AV_LOG_ERROR, + "Frame width or height differs from first frame!\n"); + av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n", + avctx->height, avctx->width, s->image_height, s->image_width); + return AVERROR_INVALIDDATA; + } + + /* we care for keyframes only in Screen Video v2 */ + s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); + if (s->is_keyframe) { + s->keyframedata = av_realloc(s->keyframedata, avpkt->size); + memcpy(s->keyframedata, avpkt->data, avpkt->size); + } + if(s->ver == 2 && !s->blocks) + s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) + * sizeof(s->blocks[0])); + + av_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", + s->image_width, s->image_height, s->block_width, s->block_height, + h_blocks, v_blocks, h_part, v_part); + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + /* loop over all block columns */ + for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) { + + int y_pos = j * s->block_height; // vertical position in frame + int cur_blk_height = (j < v_blocks) ? s->block_height : v_part; + + /* loop over all block rows */ + for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) { + int x_pos = i * s->block_width; // horizontal position in frame + int cur_blk_width = (i < h_blocks) ? s->block_width : h_part; + int has_diff = 0; + + /* get the size of the compressed zlib chunk */ + int size = get_bits(&gb, 16); + + s->color_depth = 0; + s->zlibprime_curr = 0; + s->zlibprime_prev = 0; + s->diff_start = 0; + s->diff_height = cur_blk_height; + + if (8 * size > get_bits_left(&gb)) { + av_frame_unref(&s->frame); + return AVERROR_INVALIDDATA; + } + + if (s->ver == 2 && size) { + skip_bits(&gb, 3); + s->color_depth = get_bits(&gb, 2); + has_diff = get_bits1(&gb); + s->zlibprime_curr = get_bits1(&gb); + s->zlibprime_prev = get_bits1(&gb); + + if (s->color_depth != 0 && s->color_depth != 2) { + av_log(avctx, AV_LOG_ERROR, + "%dx%d invalid color depth %d\n", i, j, s->color_depth); + return AVERROR_INVALIDDATA; + } + + if (has_diff) { + if (!s->keyframe) { + av_log(avctx, AV_LOG_ERROR, + "inter frame without keyframe\n"); + return AVERROR_INVALIDDATA; + } + s->diff_start = get_bits(&gb, 8); + s->diff_height = get_bits(&gb, 8); + av_log(avctx, AV_LOG_DEBUG, + "%dx%d diff start %d height %d\n", + i, j, s->diff_start, s->diff_height); + size -= 2; + } + + if (s->zlibprime_prev) + av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j); + + if (s->zlibprime_curr) { + int col = get_bits(&gb, 8); + int row = get_bits(&gb, 8); + av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", i, j, col, row); + size -= 2; + avpriv_request_sample(avctx, "zlibprime_curr"); + return AVERROR_PATCHWELCOME; + } + if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) { + av_log(avctx, AV_LOG_ERROR, "no data available for zlib " + "priming\n"); + return AVERROR_INVALIDDATA; + } + size--; // account for flags byte + } + + if (has_diff) { + int k; + int off = (s->image_height - y_pos - 1) * s->frame.linesize[0]; + + for (k = 0; k < cur_blk_height; k++) + memcpy(s->frame.data[0] + off - k*s->frame.linesize[0] + x_pos*3, + s->keyframe + off - k*s->frame.linesize[0] + x_pos*3, + cur_blk_width * 3); + } + + /* skip unchanged blocks, which have size 0 */ + if (size) { + if (flashsv_decode_block(avctx, avpkt, &gb, size, + cur_blk_width, cur_blk_height, + x_pos, y_pos, + i + j * (h_blocks + !!h_part))) + av_log(avctx, AV_LOG_ERROR, + "error in decompression of block %dx%d\n", i, j); + } + } + } + if (s->is_keyframe && s->ver == 2) { + if (!s->keyframe) { + s->keyframe = av_malloc(s->frame.linesize[0] * avctx->height); + if (!s->keyframe) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n"); + return AVERROR(ENOMEM); + } + } + memcpy(s->keyframe, s->frame.data[0], s->frame.linesize[0] * avctx->height); + } + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + if ((get_bits_count(&gb) / 8) != buf_size) + av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", + buf_size, (get_bits_count(&gb) / 8)); + + /* report that the buffer was completely consumed */ + return buf_size; +} + + +static av_cold int flashsv_decode_end(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + inflateEnd(&s->zstream); + /* release the frame if needed */ + av_frame_unref(&s->frame); + + /* free the tmpblock */ + av_free(s->tmpblock); + + return 0; +} + + +#if CONFIG_FLASHSV_DECODER +AVCodec ff_flashsv_decoder = { + .name = "flashsv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLASHSV, + .priv_data_size = sizeof(FlashSVContext), + .init = flashsv_decode_init, + .close = flashsv_decode_end, + .decode = flashsv_decode_frame, + .capabilities = CODEC_CAP_DR1, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), +}; +#endif /* CONFIG_FLASHSV_DECODER */ + +#if CONFIG_FLASHSV2_DECODER +static const uint32_t ff_flashsv2_default_palette[128] = { + 0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF, + 0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300, + 0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066, + 0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900, + 0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC, + 0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF, + 0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF, + 0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF, + 0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC, + 0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC, + 0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699, + 0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999, + 0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966, + 0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666, + 0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933, + 0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333, + 0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300, + 0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633, + 0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966, + 0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99, + 0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB, + 0xDDDDDD, 0xEEEEEE +}; + +static av_cold int flashsv2_decode_init(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + flashsv_decode_init(avctx); + s->pal = ff_flashsv2_default_palette; + s->ver = 2; + + return 0; +} + +static av_cold int flashsv2_decode_end(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + + av_freep(&s->keyframedata); + av_freep(&s->blocks); + av_freep(&s->keyframe); + av_freep(&s->deflate_block); + flashsv_decode_end(avctx); + + return 0; +} + +AVCodec ff_flashsv2_decoder = { + .name = "flashsv2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLASHSV2, + .priv_data_size = sizeof(FlashSVContext), + .init = flashsv2_decode_init, + .close = flashsv2_decode_end, + .decode = flashsv_decode_frame, + .capabilities = CODEC_CAP_DR1, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), +}; +#endif /* CONFIG_FLASHSV2_DECODER */ diff --git a/ffmpeg/libavcodec/flashsv2enc.c b/ffmpeg/libavcodec/flashsv2enc.c new file mode 100644 index 0000000..1d0d196 --- /dev/null +++ b/ffmpeg/libavcodec/flashsv2enc.c @@ -0,0 +1,931 @@ +/* + * Flash Screen Video Version 2 encoder + * Copyright (C) 2009 Joshua Warner + * + * 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 + */ + +/** + * @file + * Flash Screen Video Version 2 encoder + * @author Joshua Warner + */ + +/* Differences from version 1 stream: + * NOTE: Currently, the only player that supports version 2 streams is Adobe Flash Player itself. + * * Supports sending only a range of scanlines in a block, + * indicating a difference from the corresponding block in the last keyframe. + * * Supports initializing the zlib dictionary with data from the corresponding + * block in the last keyframe, to improve compression. + * * Supports a hybrid 15-bit rgb / 7-bit palette color space. + */ + +/* TODO: + * Don't keep Block structures for both current frame and keyframe. + * Make better heuristics for deciding stream parameters (optimum_* functions). Currently these return constants. + * Figure out how to encode palette information in the stream, choose an optimum palette at each keyframe. + * Figure out how the zlibPrimeCompressCurrent flag works, implement support. + * Find other sample files (that weren't generated here), develop a decoder. + */ + +#include +#include +#include + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" +#include "put_bits.h" +#include "bytestream.h" + +#define HAS_IFRAME_IMAGE 0x02 +#define HAS_PALLET_INFO 0x01 + +#define COLORSPACE_BGR 0x00 +#define COLORSPACE_15_7 0x10 +#define HAS_DIFF_BLOCKS 0x04 +#define ZLIB_PRIME_COMPRESS_CURRENT 0x02 +#define ZLIB_PRIME_COMPRESS_PREVIOUS 0x01 + +// Disables experimental "smart" parameter-choosing code, as well as the statistics that it depends on. +// At the moment, the "smart" code is a great example of how the parameters *shouldn't* be chosen. +#define FLASHSV2_DUMB + +typedef struct Block { + uint8_t *enc; + uint8_t *sl_begin, *sl_end; + int enc_size; + uint8_t *data; + unsigned long data_size; + + uint8_t start, len; + uint8_t dirty; + uint8_t col, row, width, height; + uint8_t flags; +} Block; + +typedef struct Palette { + unsigned colors[128]; + uint8_t index[1 << 15]; +} Palette; + +typedef struct FlashSV2Context { + AVCodecContext *avctx; + uint8_t *current_frame; + uint8_t *key_frame; + AVFrame frame; + uint8_t *encbuffer; + uint8_t *keybuffer; + uint8_t *databuffer; + + uint8_t *blockbuffer; + int blockbuffer_size; + + Block *frame_blocks; + Block *key_blocks; + int frame_size; + int blocks_size; + + int use15_7, dist, comp; + + int rows, cols; + + int last_key_frame; + + int image_width, image_height; + int block_width, block_height; + uint8_t flags; + uint8_t use_custom_palette; + uint8_t palette_type; ///< 0=>default, 1=>custom - changed when palette regenerated. + Palette palette; +#ifndef FLASHSV2_DUMB + double tot_blocks; ///< blocks encoded since last keyframe + double diff_blocks; ///< blocks that were different since last keyframe + double tot_lines; ///< total scanlines in image since last keyframe + double diff_lines; ///< scanlines that were different since last keyframe + double raw_size; ///< size of raw frames since last keyframe + double comp_size; ///< size of compressed data since last keyframe + double uncomp_size; ///< size of uncompressed data since last keyframe + + double total_bits; ///< total bits written to stream so far +#endif +} FlashSV2Context; + +static av_cold void cleanup(FlashSV2Context * s) +{ + av_freep(&s->encbuffer); + av_freep(&s->keybuffer); + av_freep(&s->databuffer); + av_freep(&s->blockbuffer); + av_freep(&s->current_frame); + av_freep(&s->key_frame); + + av_freep(&s->frame_blocks); + av_freep(&s->key_blocks); +} + +static void init_blocks(FlashSV2Context * s, Block * blocks, + uint8_t * encbuf, uint8_t * databuf) +{ + int row, col; + Block *b; + for (col = 0; col < s->cols; col++) { + for (row = 0; row < s->rows; row++) { + b = blocks + (col + row * s->cols); + b->width = (col < s->cols - 1) ? + s->block_width : + s->image_width - col * s->block_width; + + b->height = (row < s->rows - 1) ? + s->block_height : + s->image_height - row * s->block_height; + + b->row = row; + b->col = col; + b->enc = encbuf; + b->data = databuf; + encbuf += b->width * b->height * 3; + databuf += !databuf ? 0 : b->width * b->height * 6; + } + } +} + +static void reset_stats(FlashSV2Context * s) +{ +#ifndef FLASHSV2_DUMB + s->diff_blocks = 0.1; + s->tot_blocks = 1; + s->diff_lines = 0.1; + s->tot_lines = 1; + s->raw_size = s->comp_size = s->uncomp_size = 10; +#endif +} + +static av_cold int flashsv2_encode_init(AVCodecContext * avctx) +{ + FlashSV2Context *s = avctx->priv_data; + + s->avctx = avctx; + + s->comp = avctx->compression_level; + if (s->comp == -1) + s->comp = 9; + if (s->comp < 0 || s->comp > 9) { + av_log(avctx, AV_LOG_ERROR, + "Compression level should be 0-9, not %d\n", s->comp); + return -1; + } + + + if ((avctx->width > 4095) || (avctx->height > 4095)) { + av_log(avctx, AV_LOG_ERROR, + "Input dimensions too large, input must be max 4096x4096 !\n"); + return -1; + } + if ((avctx->width < 16) || (avctx->height < 16)) { + av_log(avctx, AV_LOG_ERROR, + "Input dimensions too small, input must be at least 16x16 !\n"); + return -1; + } + + if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) + return -1; + + + s->last_key_frame = 0; + + s->image_width = avctx->width; + s->image_height = avctx->height; + + s->block_width = (s->image_width / 12) & ~15; + s->block_height = (s->image_height / 12) & ~15; + + if(!s->block_width) + s->block_width = 1; + if(!s->block_height) + s->block_height = 1; + + s->rows = (s->image_height + s->block_height - 1) / s->block_height; + s->cols = (s->image_width + s->block_width - 1) / s->block_width; + + s->frame_size = s->image_width * s->image_height * 3; + s->blocks_size = s->rows * s->cols * sizeof(Block); + + s->encbuffer = av_mallocz(s->frame_size); + s->keybuffer = av_mallocz(s->frame_size); + s->databuffer = av_mallocz(s->frame_size * 6); + s->current_frame = av_mallocz(s->frame_size); + s->key_frame = av_mallocz(s->frame_size); + s->frame_blocks = av_mallocz(s->blocks_size); + s->key_blocks = av_mallocz(s->blocks_size); + + s->blockbuffer = NULL; + s->blockbuffer_size = 0; + + init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer); + init_blocks(s, s->key_blocks, s->keybuffer, 0); + reset_stats(s); +#ifndef FLASHSV2_DUMB + s->total_bits = 1; +#endif + + s->use_custom_palette = 0; + s->palette_type = -1; // so that the palette will be generated in reconfigure_at_keyframe + + if (!s->encbuffer || !s->keybuffer || !s->databuffer + || !s->current_frame || !s->key_frame || !s->key_blocks + || !s->frame_blocks) { + av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); + cleanup(s); + return -1; + } + + return 0; +} + +static int new_key_frame(FlashSV2Context * s) +{ + int i; + memcpy(s->key_blocks, s->frame_blocks, s->blocks_size); + memcpy(s->key_frame, s->current_frame, s->frame_size); + + for (i = 0; i < s->rows * s->cols; i++) { + s->key_blocks[i].enc += (s->keybuffer - s->encbuffer); + s->key_blocks[i].sl_begin = 0; + s->key_blocks[i].sl_end = 0; + s->key_blocks[i].data = 0; + } + memcpy(s->keybuffer, s->encbuffer, s->frame_size); + + return 0; +} + +static int write_palette(FlashSV2Context * s, uint8_t * buf, int buf_size) +{ + //this isn't implemented yet! Default palette only! + return -1; +} + +static int write_header(FlashSV2Context * s, uint8_t * buf, int buf_size) +{ + PutBitContext pb; + int buf_pos, len; + + if (buf_size < 5) + return -1; + + init_put_bits(&pb, buf, buf_size * 8); + + put_bits(&pb, 4, (s->block_width >> 4) - 1); + put_bits(&pb, 12, s->image_width); + put_bits(&pb, 4, (s->block_height >> 4) - 1); + put_bits(&pb, 12, s->image_height); + + flush_put_bits(&pb); + buf_pos = 4; + + buf[buf_pos++] = s->flags; + + if (s->flags & HAS_PALLET_INFO) { + len = write_palette(s, buf + buf_pos, buf_size - buf_pos); + if (len < 0) + return -1; + buf_pos += len; + } + + return buf_pos; +} + +static int write_block(Block * b, uint8_t * buf, int buf_size) +{ + int buf_pos = 0; + unsigned block_size = b->data_size; + + if (b->flags & HAS_DIFF_BLOCKS) + block_size += 2; + if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT) + block_size += 2; + if (block_size > 0) + block_size += 1; + if (buf_size < block_size + 2) + return -1; + + buf[buf_pos++] = block_size >> 8; + buf[buf_pos++] = block_size; + + if (block_size == 0) + return buf_pos; + + buf[buf_pos++] = b->flags; + + if (b->flags & HAS_DIFF_BLOCKS) { + buf[buf_pos++] = (b->start); + buf[buf_pos++] = (b->len); + } + + if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT) { + //This feature of the format is poorly understood, and as of now, unused. + buf[buf_pos++] = (b->col); + buf[buf_pos++] = (b->row); + } + + memcpy(buf + buf_pos, b->data, b->data_size); + + buf_pos += b->data_size; + + return buf_pos; +} + +static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp) +{ + int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp); + return res == Z_OK ? 0 : -1; +} + +static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf, + int *buf_size, int comp) +{ + z_stream s; + int res; + s.zalloc = NULL; + s.zfree = NULL; + s.opaque = NULL; + res = deflateInit(&s, comp); + if (res < 0) + return -1; + + s.next_in = prime->enc; + s.avail_in = prime->enc_size; + while (s.avail_in > 0) { + s.next_out = buf; + s.avail_out = *buf_size; + res = deflate(&s, Z_SYNC_FLUSH); + if (res < 0) + return -1; + } + + s.next_in = b->sl_begin; + s.avail_in = b->sl_end - b->sl_begin; + s.next_out = buf; + s.avail_out = *buf_size; + res = deflate(&s, Z_FINISH); + deflateEnd(&s); + *buf_size -= s.avail_out; + if (res != Z_STREAM_END) + return -1; + return 0; +} + +static int encode_bgr(Block * b, const uint8_t * src, int stride) +{ + int i; + uint8_t *ptr = b->enc; + for (i = 0; i < b->start; i++) + memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3); + b->sl_begin = ptr + i * b->width * 3; + for (; i < b->start + b->len; i++) + memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3); + b->sl_end = ptr + i * b->width * 3; + for (; i < b->height; i++) + memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3); + b->enc_size = ptr + i * b->width * 3 - b->enc; + return b->enc_size; +} + +static inline unsigned pixel_color15(const uint8_t * src) +{ + return (src[0] >> 3) | ((src[1] & 0xf8) << 2) | ((src[2] & 0xf8) << 7); +} + +static inline unsigned int chroma_diff(unsigned int c1, unsigned int c2) +{ + unsigned int t1 = (c1 & 0x000000ff) + ((c1 & 0x0000ff00) >> 8) + ((c1 & 0x00ff0000) >> 16); + unsigned int t2 = (c2 & 0x000000ff) + ((c2 & 0x0000ff00) >> 8) + ((c2 & 0x00ff0000) >> 16); + + return abs(t1 - t2) + abs((c1 & 0x000000ff) - (c2 & 0x000000ff)) + + abs(((c1 & 0x0000ff00) >> 8) - ((c2 & 0x0000ff00) >> 8)) + + abs(((c1 & 0x00ff0000) >> 16) - ((c2 & 0x00ff0000) >> 16)); +} + +static inline int pixel_color7_fast(Palette * palette, unsigned c15) +{ + return palette->index[c15]; +} + +static int pixel_color7_slow(Palette * palette, unsigned color) +{ + int i, min = 0x7fffffff; + int minc = -1; + for (i = 0; i < 128; i++) { + int c1 = palette->colors[i]; + int diff = chroma_diff(c1, color); + if (diff < min) { + min = diff; + minc = i; + } + } + return minc; +} + +static inline unsigned pixel_bgr(const uint8_t * src) +{ + return (src[0]) | (src[1] << 8) | (src[2] << 16); +} + +static int write_pixel_15_7(Palette * palette, uint8_t * dest, const uint8_t * src, + int dist) +{ + unsigned c15 = pixel_color15(src); + unsigned color = pixel_bgr(src); + int d15 = chroma_diff(color, color & 0x00f8f8f8); + int c7 = pixel_color7_fast(palette, c15); + int d7 = chroma_diff(color, palette->colors[c7]); + if (dist + d15 >= d7) { + dest[0] = c7; + return 1; + } else { + dest[0] = 0x80 | (c15 >> 8); + dest[1] = c15 & 0xff; + return 2; + } +} + +static int update_palette_index(Palette * palette) +{ + int r, g, b; + unsigned int bgr, c15, index; + for (r = 4; r < 256; r += 8) { + for (g = 4; g < 256; g += 8) { + for (b = 4; b < 256; b += 8) { + bgr = b | (g << 8) | (r << 16); + c15 = (b >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7); + index = pixel_color7_slow(palette, bgr); + + palette->index[c15] = index; + } + } + } + return 0; +} + +static const unsigned int default_screen_video_v2_palette[128] = { + 0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF, + 0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300, + 0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066, + 0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900, + 0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC, + 0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF, + 0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF, + 0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF, + 0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC, + 0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC, + 0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699, + 0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999, + 0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966, + 0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666, + 0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933, + 0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333, + 0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300, + 0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633, + 0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966, + 0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99, + 0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB, + 0x00DDDDDD, 0x00EEEEEE +}; + +static int generate_default_palette(Palette * palette) +{ + memcpy(palette->colors, default_screen_video_v2_palette, + sizeof(default_screen_video_v2_palette)); + + return update_palette_index(palette); +} + +static int generate_optimum_palette(Palette * palette, const uint8_t * image, + int width, int height, int stride) +{ + //this isn't implemented yet! Default palette only! + return -1; +} + +static inline int encode_15_7_sl(Palette * palette, uint8_t * dest, + const uint8_t * src, int width, int dist) +{ + int len = 0, x; + for (x = 0; x < width; x++) { + len += write_pixel_15_7(palette, dest + len, src + 3 * x, dist); + } + return len; +} + +static int encode_15_7(Palette * palette, Block * b, const uint8_t * src, + int stride, int dist) +{ + int i; + uint8_t *ptr = b->enc; + for (i = 0; i < b->start; i++) + ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist); + b->sl_begin = ptr; + for (; i < b->start + b->len; i++) + ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist); + b->sl_end = ptr; + for (; i < b->height; i++) + ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist); + b->enc_size = ptr - b->enc; + return b->enc_size; +} + +static int encode_block(FlashSV2Context *s, Palette * palette, Block * b, + Block * prev, const uint8_t * src, int stride, int comp, + int dist, int keyframe) +{ + unsigned buf_size = b->width * b->height * 6; + uint8_t *buf = s->blockbuffer; + int res; + + if (b->flags & COLORSPACE_15_7) { + encode_15_7(palette, b, src, stride, dist); + } else { + encode_bgr(b, src, stride); + } + + if (b->len > 0) { + b->data_size = buf_size; + res = encode_zlib(b, b->data, &b->data_size, comp); + if (res) + return res; + + if (!keyframe) { + res = encode_zlibprime(b, prev, buf, &buf_size, comp); + if (res) + return res; + + if (buf_size < b->data_size) { + b->data_size = buf_size; + memcpy(b->data, buf, buf_size); + b->flags |= ZLIB_PRIME_COMPRESS_PREVIOUS; + } + } + } else { + b->data_size = 0; + } + return 0; +} + +static int compare_sl(FlashSV2Context * s, Block * b, const uint8_t * src, + uint8_t * frame, uint8_t * key, int y, int keyframe) +{ + if (memcmp(src, frame, b->width * 3) != 0) { + b->dirty = 1; + memcpy(frame, src, b->width * 3); +#ifndef FLASHSV2_DUMB + s->diff_lines++; +#endif + } + if (memcmp(src, key, b->width * 3) != 0) { + if (b->len == 0) + b->start = y; + b->len = y + 1 - b->start; + } + return 0; +} + +static int mark_all_blocks(FlashSV2Context * s, const uint8_t * src, int stride, + int keyframe) +{ + int sl, rsl, col, pos, possl; + Block *b; + for (sl = s->image_height - 1; sl >= 0; sl--) { + for (col = 0; col < s->cols; col++) { + rsl = s->image_height - sl - 1; + b = s->frame_blocks + col + rsl / s->block_height * s->cols; + possl = stride * sl + col * s->block_width * 3; + pos = s->image_width * rsl * 3 + col * s->block_width * 3; + compare_sl(s, b, src + possl, s->current_frame + pos, + s->key_frame + pos, rsl % s->block_height, keyframe); + } + } +#ifndef FLASHSV2_DUMB + s->tot_lines += s->image_height * s->cols; +#endif + return 0; +} + +static int encode_all_blocks(FlashSV2Context * s, int keyframe) +{ + int row, col, res; + uint8_t *data; + Block *b, *prev; + for (row = 0; row < s->rows; row++) { + for (col = 0; col < s->cols; col++) { + b = s->frame_blocks + (row * s->cols + col); + prev = s->key_blocks + (row * s->cols + col); + b->flags = s->use15_7 ? COLORSPACE_15_7 : 0; + if (keyframe) { + b->start = 0; + b->len = b->height; + } else if (!b->dirty) { + b->start = 0; + b->len = 0; + b->data_size = 0; + continue; + } else if (b->start != 0 || b->len != b->height) { + b->flags |= HAS_DIFF_BLOCKS; + } + data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3; + res = encode_block(s, &s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe); +#ifndef FLASHSV2_DUMB + if (b->dirty) + s->diff_blocks++; + s->comp_size += b->data_size; + s->uncomp_size += b->enc_size; +#endif + if (res) + return res; + } + } +#ifndef FLASHSV2_DUMB + s->raw_size += s->image_width * s->image_height * 3; + s->tot_blocks += s->rows * s->cols; +#endif + return 0; +} + +static int write_all_blocks(FlashSV2Context * s, uint8_t * buf, + int buf_size) +{ + int row, col, buf_pos = 0, len; + Block *b; + for (row = 0; row < s->rows; row++) { + for (col = 0; col < s->cols; col++) { + b = s->frame_blocks + row * s->cols + col; + len = write_block(b, buf + buf_pos, buf_size - buf_pos); + b->start = b->len = b->dirty = 0; + if (len < 0) + return len; + buf_pos += len; + } + } + return buf_pos; +} + +static int write_bitstream(FlashSV2Context * s, const uint8_t * src, int stride, + uint8_t * buf, int buf_size, int keyframe) +{ + int buf_pos, res; + + res = mark_all_blocks(s, src, stride, keyframe); + if (res) + return res; + res = encode_all_blocks(s, keyframe); + if (res) + return res; + + res = write_header(s, buf, buf_size); + if (res < 0) { + return res; + } else { + buf_pos = res; + } + res = write_all_blocks(s, buf + buf_pos, buf_size - buf_pos); + if (res < 0) + return res; + buf_pos += res; +#ifndef FLASHSV2_DUMB + s->total_bits += ((double) buf_pos) * 8.0; +#endif + + return buf_pos; +} + +static void recommend_keyframe(FlashSV2Context * s, int *keyframe) +{ +#ifndef FLASHSV2_DUMB + double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio; + if (s->avctx->gop_size > 0) { + block_ratio = s->diff_blocks / s->tot_blocks; + line_ratio = s->diff_lines / s->tot_lines; + enc_ratio = s->uncomp_size / s->raw_size; + comp_ratio = s->comp_size / s->uncomp_size; + data_ratio = s->comp_size / s->raw_size; + + if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) { + *keyframe = 1; + return; + } + } +#else + return; +#endif +} + +static const double block_size_fraction = 1.0 / 300; +static int optimum_block_width(FlashSV2Context * s) +{ +#ifndef FLASHSV2_DUMB + double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks; + double width = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_width; + int pwidth = ((int) width); + return FFCLIP(pwidth & ~15, 256, 16); +#else + return 64; +#endif +} + +static int optimum_block_height(FlashSV2Context * s) +{ +#ifndef FLASHSV2_DUMB + double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks; + double height = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_height; + int pheight = ((int) height); + return FFCLIP(pheight & ~15, 256, 16); +#else + return 64; +#endif +} + +static const double use15_7_threshold = 8192; + +static int optimum_use15_7(FlashSV2Context * s) +{ +#ifndef FLASHSV2_DUMB + double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) / + ((double) s->avctx->time_base.num) * s->avctx->frame_number; + if (ideal + use15_7_threshold < s->total_bits) { + return 1; + } else { + return 0; + } +#else + return s->avctx->global_quality == 0; +#endif +} + +static const double color15_7_factor = 100; + +static int optimum_dist(FlashSV2Context * s) +{ +#ifndef FLASHSV2_DUMB + double ideal = + s->avctx->bit_rate * s->avctx->time_base.den * + s->avctx->ticks_per_frame; + int dist = pow((s->total_bits / ideal) * color15_7_factor, 3); + av_log(s->avctx, AV_LOG_DEBUG, "dist: %d\n", dist); + return dist; +#else + return 15; +#endif +} + + +static int reconfigure_at_keyframe(FlashSV2Context * s, const uint8_t * image, + int stride) +{ + int update_palette = 0; + int res; + int block_width = optimum_block_width (s); + int block_height = optimum_block_height(s); + + s->rows = (s->image_height + block_height - 1) / block_height; + s->cols = (s->image_width + block_width - 1) / block_width; + + if (block_width != s->block_width || block_height != s->block_height) { + s->block_width = block_width; + s->block_height = block_height; + if (s->rows * s->cols > s->blocks_size / sizeof(Block)) { + s->frame_blocks = av_realloc(s->frame_blocks, s->rows * s->cols * sizeof(Block)); + s->key_blocks = av_realloc(s->key_blocks, s->cols * s->rows * sizeof(Block)); + if (!s->frame_blocks || !s->key_blocks) { + av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); + return -1; + } + s->blocks_size = s->rows * s->cols * sizeof(Block); + } + init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer); + init_blocks(s, s->key_blocks, s->keybuffer, 0); + + av_fast_malloc(&s->blockbuffer, &s->blockbuffer_size, block_width * block_height * 6); + if (!s->blockbuffer) { + av_log(s->avctx, AV_LOG_ERROR, "Could not allocate block buffer.\n"); + return AVERROR(ENOMEM); + } + } + + s->use15_7 = optimum_use15_7(s); + if (s->use15_7) { + if ((s->use_custom_palette && s->palette_type != 1) || update_palette) { + res = generate_optimum_palette(&s->palette, image, s->image_width, s->image_height, stride); + if (res) + return res; + s->palette_type = 1; + av_log(s->avctx, AV_LOG_DEBUG, "Generated optimum palette\n"); + } else if (!s->use_custom_palette && s->palette_type != 0) { + res = generate_default_palette(&s->palette); + if (res) + return res; + s->palette_type = 0; + av_log(s->avctx, AV_LOG_DEBUG, "Generated default palette\n"); + } + } + + + reset_stats(s); + + return 0; +} + +static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + FlashSV2Context *const s = avctx->priv_data; + AVFrame *const p = &s->frame; + int res; + int keyframe = 0; + + *p = *pict; + + if ((res = ff_alloc_packet2(avctx, pkt, s->frame_size + FF_MIN_BUFFER_SIZE)) < 0) + return res; + + /* First frame needs to be a keyframe */ + if (avctx->frame_number == 0) + keyframe = 1; + + /* Check the placement of keyframes */ + if (avctx->gop_size > 0) { + if (avctx->frame_number >= s->last_key_frame + avctx->gop_size) + keyframe = 1; + } + + if (!keyframe + && avctx->frame_number > s->last_key_frame + avctx->keyint_min) { + recommend_keyframe(s, &keyframe); + if (keyframe) + av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number); + } + + if (keyframe) { + res = reconfigure_at_keyframe(s, p->data[0], p->linesize[0]); + if (res) + return res; + } + + if (s->use15_7) + s->dist = optimum_dist(s); + + res = write_bitstream(s, p->data[0], p->linesize[0], pkt->data, pkt->size, keyframe); + + if (keyframe) { + new_key_frame(s); + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + s->last_key_frame = avctx->frame_number; + pkt->flags |= AV_PKT_FLAG_KEY; + av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number); + } else { + p->pict_type = AV_PICTURE_TYPE_P; + p->key_frame = 0; + } + + avctx->coded_frame = p; + + pkt->size = res; + *got_packet = 1; + + return 0; +} + +static av_cold int flashsv2_encode_end(AVCodecContext * avctx) +{ + FlashSV2Context *s = avctx->priv_data; + + cleanup(s); + + return 0; +} + +AVCodec ff_flashsv2_encoder = { + .name = "flashsv2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLASHSV2, + .priv_data_size = sizeof(FlashSV2Context), + .init = flashsv2_encode_init, + .encode2 = flashsv2_encode_frame, + .close = flashsv2_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"), +}; diff --git a/ffmpeg/libavcodec/flashsvenc.c b/ffmpeg/libavcodec/flashsvenc.c new file mode 100644 index 0000000..e6b181f --- /dev/null +++ b/ffmpeg/libavcodec/flashsvenc.c @@ -0,0 +1,288 @@ +/* + * Flash Screen Video encoder + * Copyright (C) 2004 Alex Beregszaszi + * Copyright (C) 2006 Benjamin Larsson + * + * 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 + */ + +/* Encoding development sponsored by http://fh-campuswien.ac.at */ + +/** + * @file + * Flash Screen Video encoder + * @author Alex Beregszaszi + * @author Benjamin Larsson + * + * A description of the bitstream format for Flash Screen Video version 1/2 + * is part of the SWF File Format Specification (version 10), which can be + * downloaded from http://www.adobe.com/devnet/swf.html. + */ + +/* + * Encoding ideas: A basic encoder would just use a fixed block size. + * Block sizes can be multiples of 16, from 16 to 256. The blocks don't + * have to be quadratic. A brute force search with a set of different + * block sizes should give a better result than to just use a fixed size. + * + * TODO: + * Don't reencode the frame in brute force mode if the frame is a dupe. + * Speed up. Make the difference check faster. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "put_bits.h" +#include "bytestream.h" + + +typedef struct FlashSVContext { + AVCodecContext *avctx; + uint8_t *previous_frame; + AVFrame frame; + int image_width, image_height; + int block_width, block_height; + uint8_t *tmpblock; + uint8_t *encbuffer; + int block_size; + z_stream zstream; + int last_key_frame; +} FlashSVContext; + +static int copy_region_enc(uint8_t *sptr, uint8_t *dptr, int dx, int dy, + int h, int w, int stride, uint8_t *pfptr) +{ + int i, j; + uint8_t *nsptr; + uint8_t *npfptr; + int diff = 0; + + for (i = dx + h; i > dx; i--) { + nsptr = sptr + i * stride + dy * 3; + npfptr = pfptr + i * stride + dy * 3; + for (j = 0; j < w * 3; j++) { + diff |= npfptr[j] ^ nsptr[j]; + dptr[j] = nsptr[j]; + } + dptr += w * 3; + } + if (diff) + return 1; + return 0; +} + +static av_cold int flashsv_encode_init(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + + s->avctx = avctx; + + if (avctx->width > 4095 || avctx->height > 4095) { + av_log(avctx, AV_LOG_ERROR, + "Input dimensions too large, input must be max 4096x4096 !\n"); + return AVERROR_INVALIDDATA; + } + + // Needed if zlib unused or init aborted before deflateInit + memset(&s->zstream, 0, sizeof(z_stream)); + + s->last_key_frame = 0; + + s->image_width = avctx->width; + s->image_height = avctx->height; + + s->tmpblock = av_mallocz(3 * 256 * 256); + s->encbuffer = av_mallocz(s->image_width * s->image_height * 3); + + if (!s->tmpblock || !s->encbuffer) { + av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + + +static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, + int buf_size, int block_width, int block_height, + uint8_t *previous_frame, int *I_frame) +{ + + PutBitContext pb; + int h_blocks, v_blocks, h_part, v_part, i, j; + int buf_pos, res; + int pred_blocks = 0; + + init_put_bits(&pb, buf, buf_size * 8); + + put_bits(&pb, 4, block_width / 16 - 1); + put_bits(&pb, 12, s->image_width); + put_bits(&pb, 4, block_height / 16 - 1); + put_bits(&pb, 12, s->image_height); + flush_put_bits(&pb); + buf_pos = 4; + + h_blocks = s->image_width / block_width; + h_part = s->image_width % block_width; + v_blocks = s->image_height / block_height; + v_part = s->image_height % block_height; + + /* loop over all block columns */ + for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) { + + int y_pos = j * block_height; // vertical position in frame + int cur_blk_height = (j < v_blocks) ? block_height : v_part; + + /* loop over all block rows */ + for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) { + int x_pos = i * block_width; // horizontal position in frame + int cur_blk_width = (i < h_blocks) ? block_width : h_part; + int ret = Z_OK; + uint8_t *ptr = buf + buf_pos; + + /* copy the block to the temp buffer before compression + * (if it differs from the previous frame's block) */ + res = copy_region_enc(p->data[0], s->tmpblock, + s->image_height - (y_pos + cur_blk_height + 1), + x_pos, cur_blk_height, cur_blk_width, + p->linesize[0], previous_frame); + + if (res || *I_frame) { + unsigned long zsize = 3 * block_width * block_height; + ret = compress2(ptr + 2, &zsize, s->tmpblock, + 3 * cur_blk_width * cur_blk_height, 9); + + //ret = deflateReset(&s->zstream); + if (ret != Z_OK) + av_log(s->avctx, AV_LOG_ERROR, + "error while compressing block %dx%d\n", i, j); + + bytestream_put_be16(&ptr, zsize); + buf_pos += zsize + 2; + av_dlog(s->avctx, "buf_pos = %d\n", buf_pos); + } else { + pred_blocks++; + bytestream_put_be16(&ptr, 0); + buf_pos += 2; + } + } + } + + if (pred_blocks) + *I_frame = 0; + else + *I_frame = 1; + + return buf_pos; +} + + +static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + FlashSVContext * const s = avctx->priv_data; + AVFrame * const p = &s->frame; + uint8_t *pfptr; + int res; + int I_frame = 0; + int opt_w = 4, opt_h = 4; + + *p = *pict; + + /* First frame needs to be a keyframe */ + if (avctx->frame_number == 0) { + s->previous_frame = av_mallocz(FFABS(p->linesize[0]) * s->image_height); + if (!s->previous_frame) { + av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n"); + return AVERROR(ENOMEM); + } + I_frame = 1; + } + + if (p->linesize[0] < 0) + pfptr = s->previous_frame - (s->image_height - 1) * p->linesize[0]; + else + pfptr = s->previous_frame; + + /* Check the placement of keyframes */ + if (avctx->gop_size > 0 && + avctx->frame_number >= s->last_key_frame + avctx->gop_size) { + I_frame = 1; + } + + if ((res = ff_alloc_packet2(avctx, pkt, s->image_width * s->image_height * 3)) < 0) + return res; + + pkt->size = encode_bitstream(s, p, pkt->data, pkt->size, opt_w * 16, opt_h * 16, + pfptr, &I_frame); + + //save the current frame + if (p->linesize[0] > 0) + memcpy(s->previous_frame, p->data[0], s->image_height * p->linesize[0]); + else + memcpy(s->previous_frame, + p->data[0] + p->linesize[0] * (s->image_height - 1), + s->image_height * FFABS(p->linesize[0])); + + //mark the frame type so the muxer can mux it correctly + if (I_frame) { + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + s->last_key_frame = avctx->frame_number; + av_dlog(avctx, "Inserting keyframe at frame %d\n", avctx->frame_number); + } else { + p->pict_type = AV_PICTURE_TYPE_P; + p->key_frame = 0; + } + + avctx->coded_frame = p; + + if (p->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int flashsv_encode_end(AVCodecContext *avctx) +{ + FlashSVContext *s = avctx->priv_data; + + deflateEnd(&s->zstream); + + av_free(s->encbuffer); + av_free(s->previous_frame); + av_free(s->tmpblock); + + return 0; +} + +AVCodec ff_flashsv_encoder = { + .name = "flashsv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLASHSV, + .priv_data_size = sizeof(FlashSVContext), + .init = flashsv_encode_init, + .encode2 = flashsv_encode_frame, + .close = flashsv_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"), +}; diff --git a/ffmpeg/libavcodec/flicvideo.c b/ffmpeg/libavcodec/flicvideo.c new file mode 100644 index 0000000..90885fc --- /dev/null +++ b/ffmpeg/libavcodec/flicvideo.c @@ -0,0 +1,813 @@ +/* + * FLI/FLC Animation Video Decoder + * Copyright (C) 2003, 2004 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Autodesk Animator FLI/FLC Video Decoder + * by Mike Melanson (melanson@pcisys.net) + * for more information on the .fli/.flc file format and all of its many + * variations, visit: + * http://www.compuphase.com/flic.htm + * + * This decoder outputs PAL8/RGB555/RGB565 and maybe one day RGB24 + * colorspace data, depending on the FLC. To use this decoder, be + * sure that your demuxer sends the FLI file header to the decoder via + * the extradata chunk in AVCodecContext. The chunk should be 128 bytes + * large. The only exception is for FLI files from the game "Magic Carpet", + * in which the header is only 12 bytes. + */ + +#include +#include +#include + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + +#define FLI_256_COLOR 4 +#define FLI_DELTA 7 +#define FLI_COLOR 11 +#define FLI_LC 12 +#define FLI_BLACK 13 +#define FLI_BRUN 15 +#define FLI_COPY 16 +#define FLI_MINI 18 +#define FLI_DTA_BRUN 25 +#define FLI_DTA_COPY 26 +#define FLI_DTA_LC 27 + +#define FLI_TYPE_CODE (0xAF11) +#define FLC_FLX_TYPE_CODE (0xAF12) +#define FLC_DTA_TYPE_CODE (0xAF44) /* Marks an "Extended FLC" comes from Dave's Targa Animator (DTA) */ +#define FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE (0xAF13) + +#define CHECK_PIXEL_PTR(n) \ + if (pixel_ptr + n > pixel_limit) { \ + av_log (s->avctx, AV_LOG_ERROR, "Invalid pixel_ptr = %d > pixel_limit = %d\n", \ + pixel_ptr + n, pixel_limit); \ + return AVERROR_INVALIDDATA; \ + } \ + +typedef struct FlicDecodeContext { + AVCodecContext *avctx; + AVFrame frame; + + unsigned int palette[256]; + int new_palette; + int fli_type; /* either 0xAF11 or 0xAF12, affects palette resolution */ +} FlicDecodeContext; + +static av_cold int flic_decode_init(AVCodecContext *avctx) +{ + FlicDecodeContext *s = avctx->priv_data; + unsigned char *fli_header = (unsigned char *)avctx->extradata; + int depth; + + if (avctx->extradata_size != 0 && + avctx->extradata_size != 12 && + avctx->extradata_size != 128 && + avctx->extradata_size != 256 && + avctx->extradata_size != 904 && + avctx->extradata_size != 1024) { + av_log(avctx, AV_LOG_ERROR, "Unexpected extradata size %d\n", avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + s->avctx = avctx; + + if (s->avctx->extradata_size == 12) { + /* special case for magic carpet FLIs */ + s->fli_type = FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE; + depth = 8; + } else if (avctx->extradata_size == 1024) { + uint8_t *ptr = avctx->extradata; + int i; + + for (i = 0; i < 256; i++) { + s->palette[i] = AV_RL32(ptr); + ptr += 4; + } + depth = 8; + /* FLI in MOV, see e.g. FFmpeg trac issue #626 */ + } else if (avctx->extradata_size == 0 || + avctx->extradata_size == 256 || + /* see FFmpeg ticket #1234 */ + avctx->extradata_size == 904) { + s->fli_type = FLI_TYPE_CODE; + depth = 8; + } else { + s->fli_type = AV_RL16(&fli_header[4]); + depth = AV_RL16(&fli_header[12]); + } + + if (depth == 0) { + depth = 8; /* Some FLC generators set depth to zero, when they mean 8Bpp. Fix up here */ + } + + if ((s->fli_type == FLC_FLX_TYPE_CODE) && (depth == 16)) { + depth = 15; /* Original Autodesk FLX's say the depth is 16Bpp when it is really 15Bpp */ + } + + switch (depth) { + case 8 : avctx->pix_fmt = AV_PIX_FMT_PAL8; break; + case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break; + case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break; + case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */ + av_log(avctx, AV_LOG_ERROR, "24Bpp FLC/FLX is unsupported due to no test files.\n"); + return AVERROR_PATCHWELCOME; + default : + av_log(avctx, AV_LOG_ERROR, "Unknown FLC/FLX depth of %d Bpp is unsupported.\n",depth); + return AVERROR_INVALIDDATA; + } + + avcodec_get_frame_defaults(&s->frame); + s->new_palette = 0; + + return 0; +} + +static int flic_decode_frame_8BPP(AVCodecContext *avctx, + void *data, int *got_frame, + const uint8_t *buf, int buf_size) +{ + FlicDecodeContext *s = avctx->priv_data; + + GetByteContext g2; + int pixel_ptr; + int palette_ptr; + unsigned char palette_idx1; + unsigned char palette_idx2; + + unsigned int frame_size; + int num_chunks; + + unsigned int chunk_size; + int chunk_type; + + int i, j, ret; + + int color_packets; + int color_changes; + int color_shift; + unsigned char r, g, b; + + int lines; + int compressed_lines; + int starting_line; + signed short line_packets; + int y_ptr; + int byte_run; + int pixel_skip; + int pixel_countdown; + unsigned char *pixels; + unsigned int pixel_limit; + + bytestream2_init(&g2, buf, buf_size); + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + pixels = s->frame.data[0]; + pixel_limit = s->avctx->height * s->frame.linesize[0]; + if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE)) + return AVERROR_INVALIDDATA; + frame_size = bytestream2_get_le32(&g2); + if (frame_size > buf_size) + frame_size = buf_size; + bytestream2_skip(&g2, 2); /* skip the magic number */ + num_chunks = bytestream2_get_le16(&g2); + bytestream2_skip(&g2, 8); /* skip padding */ + + frame_size -= 16; + + /* iterate through the chunks */ + while ((frame_size >= 6) && (num_chunks > 0)) { + int stream_ptr_after_chunk; + chunk_size = bytestream2_get_le32(&g2); + if (chunk_size > frame_size) { + av_log(avctx, AV_LOG_WARNING, + "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size); + chunk_size = frame_size; + } + stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size; + + chunk_type = bytestream2_get_le16(&g2); + + switch (chunk_type) { + case FLI_256_COLOR: + case FLI_COLOR: + /* check special case: If this file is from the Magic Carpet + * game and uses 6-bit colors even though it reports 256-color + * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during + * initialization) */ + if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE)) + color_shift = 0; + else + color_shift = 2; + /* set up the palette */ + color_packets = bytestream2_get_le16(&g2); + palette_ptr = 0; + for (i = 0; i < color_packets; i++) { + /* first byte is how many colors to skip */ + palette_ptr += bytestream2_get_byte(&g2); + + /* next byte indicates how many entries to change */ + color_changes = bytestream2_get_byte(&g2); + + /* if there are 0 color changes, there are actually 256 */ + if (color_changes == 0) + color_changes = 256; + + if (bytestream2_tell(&g2) + color_changes * 3 > stream_ptr_after_chunk) + break; + + for (j = 0; j < color_changes; j++) { + unsigned int entry; + + /* wrap around, for good measure */ + if ((unsigned)palette_ptr >= 256) + palette_ptr = 0; + + r = bytestream2_get_byte(&g2) << color_shift; + g = bytestream2_get_byte(&g2) << color_shift; + b = bytestream2_get_byte(&g2) << color_shift; + entry = 0xFFU << 24 | r << 16 | g << 8 | b; + if (color_shift == 2) + entry |= entry >> 6 & 0x30303; + if (s->palette[palette_ptr] != entry) + s->new_palette = 1; + s->palette[palette_ptr++] = entry; + } + } + break; + + case FLI_DELTA: + y_ptr = 0; + compressed_lines = bytestream2_get_le16(&g2); + while (compressed_lines > 0) { + if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) + break; + line_packets = bytestream2_get_le16(&g2); + if ((line_packets & 0xC000) == 0xC000) { + // line skip opcode + line_packets = -line_packets; + y_ptr += line_packets * s->frame.linesize[0]; + } else if ((line_packets & 0xC000) == 0x4000) { + av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets); + } else if ((line_packets & 0xC000) == 0x8000) { + // "last byte" opcode + pixel_ptr= y_ptr + s->frame.linesize[0] - 1; + CHECK_PIXEL_PTR(0); + pixels[pixel_ptr] = line_packets & 0xff; + } else { + compressed_lines--; + pixel_ptr = y_ptr; + CHECK_PIXEL_PTR(0); + pixel_countdown = s->avctx->width; + for (i = 0; i < line_packets; i++) { + if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) + break; + /* account for the skip bytes */ + pixel_skip = bytestream2_get_byte(&g2); + pixel_ptr += pixel_skip; + pixel_countdown -= pixel_skip; + byte_run = sign_extend(bytestream2_get_byte(&g2), 8); + if (byte_run < 0) { + byte_run = -byte_run; + palette_idx1 = bytestream2_get_byte(&g2); + palette_idx2 = bytestream2_get_byte(&g2); + CHECK_PIXEL_PTR(byte_run * 2); + for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { + pixels[pixel_ptr++] = palette_idx1; + pixels[pixel_ptr++] = palette_idx2; + } + } else { + CHECK_PIXEL_PTR(byte_run * 2); + if (bytestream2_tell(&g2) + byte_run * 2 > stream_ptr_after_chunk) + break; + for (j = 0; j < byte_run * 2; j++, pixel_countdown--) { + pixels[pixel_ptr++] = bytestream2_get_byte(&g2); + } + } + } + + y_ptr += s->frame.linesize[0]; + } + } + break; + + case FLI_LC: + /* line compressed */ + starting_line = bytestream2_get_le16(&g2); + y_ptr = 0; + y_ptr += starting_line * s->frame.linesize[0]; + + compressed_lines = bytestream2_get_le16(&g2); + while (compressed_lines > 0) { + pixel_ptr = y_ptr; + CHECK_PIXEL_PTR(0); + pixel_countdown = s->avctx->width; + if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) + break; + line_packets = bytestream2_get_byte(&g2); + if (line_packets > 0) { + for (i = 0; i < line_packets; i++) { + /* account for the skip bytes */ + if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) + break; + pixel_skip = bytestream2_get_byte(&g2); + pixel_ptr += pixel_skip; + pixel_countdown -= pixel_skip; + byte_run = sign_extend(bytestream2_get_byte(&g2),8); + if (byte_run > 0) { + CHECK_PIXEL_PTR(byte_run); + if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk) + break; + for (j = 0; j < byte_run; j++, pixel_countdown--) { + pixels[pixel_ptr++] = bytestream2_get_byte(&g2); + } + } else if (byte_run < 0) { + byte_run = -byte_run; + palette_idx1 = bytestream2_get_byte(&g2); + CHECK_PIXEL_PTR(byte_run); + for (j = 0; j < byte_run; j++, pixel_countdown--) { + pixels[pixel_ptr++] = palette_idx1; + } + } + } + } + + y_ptr += s->frame.linesize[0]; + compressed_lines--; + } + break; + + case FLI_BLACK: + /* set the whole frame to color 0 (which is usually black) */ + memset(pixels, 0, + s->frame.linesize[0] * s->avctx->height); + break; + + case FLI_BRUN: + /* Byte run compression: This chunk type only occurs in the first + * FLI frame and it will update the entire frame. */ + y_ptr = 0; + for (lines = 0; lines < s->avctx->height; lines++) { + pixel_ptr = y_ptr; + /* disregard the line packets; instead, iterate through all + * pixels on a row */ + bytestream2_skip(&g2, 1); + pixel_countdown = s->avctx->width; + while (pixel_countdown > 0) { + if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) + break; + byte_run = sign_extend(bytestream2_get_byte(&g2), 8); + if (!byte_run) { + av_log(avctx, AV_LOG_ERROR, "Invalid byte run value.\n"); + return AVERROR_INVALIDDATA; + } + + if (byte_run > 0) { + palette_idx1 = bytestream2_get_byte(&g2); + CHECK_PIXEL_PTR(byte_run); + for (j = 0; j < byte_run; j++) { + pixels[pixel_ptr++] = palette_idx1; + pixel_countdown--; + if (pixel_countdown < 0) + av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", + pixel_countdown, lines); + } + } else { /* copy bytes if byte_run < 0 */ + byte_run = -byte_run; + CHECK_PIXEL_PTR(byte_run); + if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk) + break; + for (j = 0; j < byte_run; j++) { + pixels[pixel_ptr++] = bytestream2_get_byte(&g2); + pixel_countdown--; + if (pixel_countdown < 0) + av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", + pixel_countdown, lines); + } + } + } + + y_ptr += s->frame.linesize[0]; + } + break; + + case FLI_COPY: + /* copy the chunk (uncompressed frame) */ + if (chunk_size - 6 != s->avctx->width * s->avctx->height) { + av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ + "has incorrect size, skipping chunk\n", chunk_size - 6); + bytestream2_skip(&g2, chunk_size - 6); + } else { + for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; + y_ptr += s->frame.linesize[0]) { + bytestream2_get_buffer(&g2, &pixels[y_ptr], + s->avctx->width); + } + } + break; + + case FLI_MINI: + /* some sort of a thumbnail? disregard this chunk... */ + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); + break; + } + + if (stream_ptr_after_chunk - bytestream2_tell(&g2) > 0) + bytestream2_skip(&g2, stream_ptr_after_chunk - bytestream2_tell(&g2)); + + frame_size -= chunk_size; + num_chunks--; + } + + /* by the end of the chunk, the stream ptr should equal the frame + * size (minus 1 or 2, possibly); if it doesn't, issue a warning */ + if (bytestream2_get_bytes_left(&g2) > 2) + av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ + "and final chunk ptr = %d\n", buf_size, + buf_size - bytestream2_get_bytes_left(&g2)); + + /* make the palette available on the way out */ + memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); + if (s->new_palette) { + s->frame.palette_has_changed = 1; + s->new_palette = 0; + } + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, + void *data, int *got_frame, + const uint8_t *buf, int buf_size) +{ + /* Note, the only difference between the 15Bpp and 16Bpp */ + /* Format is the pixel format, the packets are processed the same. */ + FlicDecodeContext *s = avctx->priv_data; + + GetByteContext g2; + int pixel_ptr; + unsigned char palette_idx1; + + unsigned int frame_size; + int num_chunks; + + unsigned int chunk_size; + int chunk_type; + + int i, j, ret; + + int lines; + int compressed_lines; + signed short line_packets; + int y_ptr; + int byte_run; + int pixel_skip; + int pixel_countdown; + unsigned char *pixels; + int pixel; + unsigned int pixel_limit; + + bytestream2_init(&g2, buf, buf_size); + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + pixels = s->frame.data[0]; + pixel_limit = s->avctx->height * s->frame.linesize[0]; + + frame_size = bytestream2_get_le32(&g2); + bytestream2_skip(&g2, 2); /* skip the magic number */ + num_chunks = bytestream2_get_le16(&g2); + bytestream2_skip(&g2, 8); /* skip padding */ + if (frame_size > buf_size) + frame_size = buf_size; + + frame_size -= 16; + + /* iterate through the chunks */ + while ((frame_size > 0) && (num_chunks > 0)) { + int stream_ptr_after_chunk; + chunk_size = bytestream2_get_le32(&g2); + if (chunk_size > frame_size) { + av_log(avctx, AV_LOG_WARNING, + "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size); + chunk_size = frame_size; + } + stream_ptr_after_chunk = bytestream2_tell(&g2) - 4 + chunk_size; + + chunk_type = bytestream2_get_le16(&g2); + + + switch (chunk_type) { + case FLI_256_COLOR: + case FLI_COLOR: + /* For some reason, it seems that non-palettized flics do + * include one of these chunks in their first frame. + * Why I do not know, it seems rather extraneous. */ + av_dlog(avctx, + "Unexpected Palette chunk %d in non-palettized FLC\n", + chunk_type); + bytestream2_skip(&g2, chunk_size - 6); + break; + + case FLI_DELTA: + case FLI_DTA_LC: + y_ptr = 0; + compressed_lines = bytestream2_get_le16(&g2); + while (compressed_lines > 0) { + if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) + break; + line_packets = bytestream2_get_le16(&g2); + if (line_packets < 0) { + line_packets = -line_packets; + y_ptr += line_packets * s->frame.linesize[0]; + } else { + compressed_lines--; + pixel_ptr = y_ptr; + CHECK_PIXEL_PTR(0); + pixel_countdown = s->avctx->width; + for (i = 0; i < line_packets; i++) { + /* account for the skip bytes */ + if (bytestream2_tell(&g2) + 2 > stream_ptr_after_chunk) + break; + pixel_skip = bytestream2_get_byte(&g2); + pixel_ptr += (pixel_skip*2); /* Pixel is 2 bytes wide */ + pixel_countdown -= pixel_skip; + byte_run = sign_extend(bytestream2_get_byte(&g2), 8); + if (byte_run < 0) { + byte_run = -byte_run; + pixel = bytestream2_get_le16(&g2); + CHECK_PIXEL_PTR(2 * byte_run); + for (j = 0; j < byte_run; j++, pixel_countdown -= 2) { + *((signed short*)(&pixels[pixel_ptr])) = pixel; + pixel_ptr += 2; + } + } else { + if (bytestream2_tell(&g2) + 2*byte_run > stream_ptr_after_chunk) + break; + CHECK_PIXEL_PTR(2 * byte_run); + for (j = 0; j < byte_run; j++, pixel_countdown--) { + *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2); + pixel_ptr += 2; + } + } + } + + y_ptr += s->frame.linesize[0]; + } + } + break; + + case FLI_LC: + av_log(avctx, AV_LOG_ERROR, "Unexpected FLI_LC chunk in non-paletised FLC\n"); + bytestream2_skip(&g2, chunk_size - 6); + break; + + case FLI_BLACK: + /* set the whole frame to 0x0000 which is black in both 15Bpp and 16Bpp modes. */ + memset(pixels, 0x0000, + s->frame.linesize[0] * s->avctx->height); + break; + + case FLI_BRUN: + y_ptr = 0; + for (lines = 0; lines < s->avctx->height; lines++) { + pixel_ptr = y_ptr; + /* disregard the line packets; instead, iterate through all + * pixels on a row */ + bytestream2_skip(&g2, 1); + pixel_countdown = (s->avctx->width * 2); + + while (pixel_countdown > 0) { + if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) + break; + byte_run = sign_extend(bytestream2_get_byte(&g2), 8); + if (byte_run > 0) { + palette_idx1 = bytestream2_get_byte(&g2); + CHECK_PIXEL_PTR(byte_run); + for (j = 0; j < byte_run; j++) { + pixels[pixel_ptr++] = palette_idx1; + pixel_countdown--; + if (pixel_countdown < 0) + av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) (linea%d)\n", + pixel_countdown, lines); + } + } else { /* copy bytes if byte_run < 0 */ + byte_run = -byte_run; + if (bytestream2_tell(&g2) + byte_run > stream_ptr_after_chunk) + break; + CHECK_PIXEL_PTR(byte_run); + for (j = 0; j < byte_run; j++) { + palette_idx1 = bytestream2_get_byte(&g2); + pixels[pixel_ptr++] = palette_idx1; + pixel_countdown--; + if (pixel_countdown < 0) + av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n", + pixel_countdown, lines); + } + } + } + + /* Now FLX is strange, in that it is "byte" as opposed to "pixel" run length compressed. + * This does not give us any good opportunity to perform word endian conversion + * during decompression. So if it is required (i.e., this is not a LE target, we do + * a second pass over the line here, swapping the bytes. + */ +#if HAVE_BIGENDIAN + pixel_ptr = y_ptr; + pixel_countdown = s->avctx->width; + while (pixel_countdown > 0) { + *((signed short*)(&pixels[pixel_ptr])) = AV_RL16(&buf[pixel_ptr]); + pixel_ptr += 2; + } +#endif + y_ptr += s->frame.linesize[0]; + } + break; + + case FLI_DTA_BRUN: + y_ptr = 0; + for (lines = 0; lines < s->avctx->height; lines++) { + pixel_ptr = y_ptr; + /* disregard the line packets; instead, iterate through all + * pixels on a row */ + bytestream2_skip(&g2, 1); + pixel_countdown = s->avctx->width; /* Width is in pixels, not bytes */ + + while (pixel_countdown > 0) { + if (bytestream2_tell(&g2) + 1 > stream_ptr_after_chunk) + break; + byte_run = sign_extend(bytestream2_get_byte(&g2), 8); + if (byte_run > 0) { + pixel = bytestream2_get_le16(&g2); + CHECK_PIXEL_PTR(2 * byte_run); + for (j = 0; j < byte_run; j++) { + *((signed short*)(&pixels[pixel_ptr])) = pixel; + pixel_ptr += 2; + pixel_countdown--; + if (pixel_countdown < 0) + av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", + pixel_countdown); + } + } else { /* copy pixels if byte_run < 0 */ + byte_run = -byte_run; + if (bytestream2_tell(&g2) + 2 * byte_run > stream_ptr_after_chunk) + break; + CHECK_PIXEL_PTR(2 * byte_run); + for (j = 0; j < byte_run; j++) { + *((signed short*)(&pixels[pixel_ptr])) = bytestream2_get_le16(&g2); + pixel_ptr += 2; + pixel_countdown--; + if (pixel_countdown < 0) + av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d)\n", + pixel_countdown); + } + } + } + + y_ptr += s->frame.linesize[0]; + } + break; + + case FLI_COPY: + case FLI_DTA_COPY: + /* copy the chunk (uncompressed frame) */ + if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) { + av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \ + "bigger than image, skipping chunk\n", chunk_size - 6); + bytestream2_skip(&g2, chunk_size - 6); + } else { + + for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height; + y_ptr += s->frame.linesize[0]) { + + pixel_countdown = s->avctx->width; + pixel_ptr = 0; + while (pixel_countdown > 0) { + *((signed short*)(&pixels[y_ptr + pixel_ptr])) = bytestream2_get_le16(&g2); + pixel_ptr += 2; + pixel_countdown--; + } + } + } + break; + + case FLI_MINI: + /* some sort of a thumbnail? disregard this chunk... */ + bytestream2_skip(&g2, chunk_size - 6); + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type); + break; + } + + frame_size -= chunk_size; + num_chunks--; + } + + /* by the end of the chunk, the stream ptr should equal the frame + * size (minus 1, possibly); if it doesn't, issue a warning */ + if ((bytestream2_get_bytes_left(&g2) != 0) && (bytestream2_get_bytes_left(&g2) != 1)) + av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ + "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2)); + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static int flic_decode_frame_24BPP(AVCodecContext *avctx, + void *data, int *got_frame, + const uint8_t *buf, int buf_size) +{ + av_log(avctx, AV_LOG_ERROR, "24Bpp FLC Unsupported due to lack of test files.\n"); + return AVERROR_PATCHWELCOME; +} + +static int flic_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + return flic_decode_frame_8BPP(avctx, data, got_frame, + buf, buf_size); + } + else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) || + (avctx->pix_fmt == AV_PIX_FMT_RGB565)) { + return flic_decode_frame_15_16BPP(avctx, data, got_frame, + buf, buf_size); + } + else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) { + return flic_decode_frame_24BPP(avctx, data, got_frame, + buf, buf_size); + } + + /* Should not get here, ever as the pix_fmt is processed */ + /* in flic_decode_init and the above if should deal with */ + /* the finite set of possibilites allowable by here. */ + /* But in case we do, just error out. */ + av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n"); + return AVERROR_BUG; +} + + +static av_cold int flic_decode_end(AVCodecContext *avctx) +{ + FlicDecodeContext *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_flic_decoder = { + .name = "flic", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLIC, + .priv_data_size = sizeof(FlicDecodeContext), + .init = flic_decode_init, + .close = flic_decode_end, + .decode = flic_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), +}; diff --git a/ffmpeg/libavcodec/flv.h b/ffmpeg/libavcodec/flv.h new file mode 100644 index 0000000..16bc88b --- /dev/null +++ b/ffmpeg/libavcodec/flv.h @@ -0,0 +1,33 @@ +/* + * FLV specific private header. + * 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 + */ + +#ifndef AVCODEC_FLV_H +#define AVCODEC_FLV_H + +#include "mpegvideo.h" +#include "get_bits.h" +#include "put_bits.h" + +void ff_flv_encode_picture_header(MpegEncContext * s, int picture_number); +void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, int last); + +int ff_flv_decode_picture_header(MpegEncContext *s); +void ff_flv2_decode_ac_esc(GetBitContext *gb, int *level, int *run, int *last); + +#endif /* AVCODEC_FLV_H */ diff --git a/ffmpeg/libavcodec/flvdec.c b/ffmpeg/libavcodec/flvdec.c new file mode 100644 index 0000000..bb693d7 --- /dev/null +++ b/ffmpeg/libavcodec/flvdec.c @@ -0,0 +1,134 @@ +/* + * FLV decoding. + * 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 "mpegvideo.h" +#include "h263.h" +#include "flv.h" +#include "libavutil/imgutils.h" + +void ff_flv2_decode_ac_esc(GetBitContext *gb, int *level, int *run, int *last){ + int is11 = get_bits1(gb); + *last = get_bits1(gb); + *run = get_bits(gb, 6); + if(is11){ + *level = get_sbits(gb, 11); + } else { + *level = get_sbits(gb, 7); + } +} + +int ff_flv_decode_picture_header(MpegEncContext *s) +{ + int format, width, height; + + /* picture header */ + if (get_bits_long(&s->gb, 17) != 1) { + av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); + return AVERROR_INVALIDDATA; + } + format = get_bits(&s->gb, 5); + if (format != 0 && format != 1) { + av_log(s->avctx, AV_LOG_ERROR, "Bad picture format\n"); + return AVERROR_INVALIDDATA; + } + s->h263_flv = format+1; + s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */ + format = get_bits(&s->gb, 3); + switch (format) { + case 0: + width = get_bits(&s->gb, 8); + height = get_bits(&s->gb, 8); + break; + case 1: + width = get_bits(&s->gb, 16); + height = get_bits(&s->gb, 16); + break; + case 2: + width = 352; + height = 288; + break; + case 3: + width = 176; + height = 144; + break; + case 4: + width = 128; + height = 96; + break; + case 5: + width = 320; + height = 240; + break; + case 6: + width = 160; + height = 120; + break; + default: + width = height = 0; + break; + } + if(av_image_check_size(width, height, 0, s->avctx)) + return AVERROR(EINVAL); + s->width = width; + s->height = height; + + s->pict_type = AV_PICTURE_TYPE_I + get_bits(&s->gb, 2); + s->droppable = s->pict_type > AV_PICTURE_TYPE_P; + if (s->droppable) + s->pict_type = AV_PICTURE_TYPE_P; + + skip_bits1(&s->gb); /* deblocking flag */ + s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + + s->h263_plus = 0; + + s->unrestricted_mv = 1; + s->h263_long_vectors = 0; + + /* PEI */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + s->f_code = 1; + + if(s->avctx->debug & FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "%c esc_type:%d, qp:%d num:%d\n", + s->droppable ? 'D' : av_get_picture_type_char(s->pict_type), + s->h263_flv - 1, s->qscale, s->picture_number); + } + + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + + return 0; +} + +AVCodec ff_flv_decoder = { + .name = "flv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLV1, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_h263_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), + .pix_fmts = ff_pixfmt_list_420, +}; diff --git a/ffmpeg/libavcodec/flvenc.c b/ffmpeg/libavcodec/flvenc.c new file mode 100644 index 0000000..a68a6fa --- /dev/null +++ b/ffmpeg/libavcodec/flvenc.c @@ -0,0 +1,100 @@ +/* + * FLV Encoding specific code. + * 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 "mpegvideo.h" +#include "h263.h" +#include "flv.h" + +void ff_flv_encode_picture_header(MpegEncContext * s, int picture_number) +{ + int format; + + avpriv_align_put_bits(&s->pb); + + put_bits(&s->pb, 17, 1); + put_bits(&s->pb, 5, (s->h263_flv-1)); /* 0: h263 escape codes 1: 11-bit escape codes */ + put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * s->avctx->time_base.num) / //FIXME use timestamp + s->avctx->time_base.den) & 0xff); /* TemporalReference */ + if (s->width == 352 && s->height == 288) + format = 2; + else if (s->width == 176 && s->height == 144) + format = 3; + else if (s->width == 128 && s->height == 96) + format = 4; + else if (s->width == 320 && s->height == 240) + format = 5; + else if (s->width == 160 && s->height == 120) + format = 6; + else if (s->width <= 255 && s->height <= 255) + format = 0; /* use 1 byte width & height */ + else + format = 1; /* use 2 bytes width & height */ + put_bits(&s->pb, 3, format); /* PictureSize */ + if (format == 0) { + put_bits(&s->pb, 8, s->width); + put_bits(&s->pb, 8, s->height); + } else if (format == 1) { + put_bits(&s->pb, 16, s->width); + put_bits(&s->pb, 16, s->height); + } + put_bits(&s->pb, 2, s->pict_type == AV_PICTURE_TYPE_P); /* PictureType */ + put_bits(&s->pb, 1, 1); /* DeblockingFlag: on */ + put_bits(&s->pb, 5, s->qscale); /* Quantizer */ + put_bits(&s->pb, 1, 0); /* ExtraInformation */ + + if(s->h263_aic){ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_aic_dc_scale_table; + }else{ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } +} + +void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, int last){ + if(level < 64) { // 7-bit level + put_bits(pb, 1, 0); + put_bits(pb, 1, last); + put_bits(pb, 6, run); + + put_sbits(pb, 7, slevel); + } else { + /* 11-bit level */ + put_bits(pb, 1, 1); + put_bits(pb, 1, last); + put_bits(pb, 6, run); + + put_sbits(pb, 11, slevel); + } +} + +FF_MPV_GENERIC_CLASS(flv) + +AVCodec ff_flv_encoder = { + .name = "flv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FLV1, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), + .priv_class = &flv_class, +}; diff --git a/ffmpeg/libavcodec/fmtconvert.c b/ffmpeg/libavcodec/fmtconvert.c new file mode 100644 index 0000000..79e9645 --- /dev/null +++ b/ffmpeg/libavcodec/fmtconvert.c @@ -0,0 +1,121 @@ +/* + * Format Conversion Utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 "avcodec.h" +#include "fmtconvert.h" +#include "libavutil/common.h" + +static void int32_to_float_fmul_scalar_c(float *dst, const int *src, float mul, int len){ + int i; + for(i=0; iint32_to_float_fmul_scalar = int32_to_float_fmul_scalar_c; + c->float_to_int16 = float_to_int16_c; + c->float_to_int16_interleave = float_to_int16_interleave_c; + c->float_interleave = ff_float_interleave_c; + + if (ARCH_ARM) ff_fmt_convert_init_arm(c, avctx); + if (HAVE_ALTIVEC) ff_fmt_convert_init_altivec(c, avctx); + if (ARCH_X86) ff_fmt_convert_init_x86(c, avctx); + if (HAVE_MIPSFPU) ff_fmt_convert_init_mips(c); +} + +/* ffdshow custom code */ +void float_interleave(float *dst, const float **src, long len, int channels) +{ + int i,j,c; + if(channels==2){ + for(i=0; i + * + * 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 + */ + +#ifndef AVCODEC_FMTCONVERT_H +#define AVCODEC_FMTCONVERT_H + +#include "avcodec.h" + +typedef struct FmtConvertContext { + /** + * Convert an array of int32_t to float and multiply by a float value. + * @param dst destination array of float. + * constraints: 16-byte aligned + * @param src source array of int32_t. + * constraints: 16-byte aligned + * @param len number of elements to convert. + * constraints: multiple of 8 + */ + void (*int32_to_float_fmul_scalar)(float *dst, const int *src, float mul, int len); + + /** + * Convert an array of float to an array of int16_t. + * + * Convert floats from in the range [-32768.0,32767.0] to ints + * without rescaling + * + * @param dst destination array of int16_t. + * constraints: 16-byte aligned + * @param src source array of float. + * constraints: 16-byte aligned + * @param len number of elements to convert. + * constraints: multiple of 8 + */ + void (*float_to_int16)(int16_t *dst, const float *src, long len); + + /** + * Convert multiple arrays of float to an interleaved array of int16_t. + * + * Convert floats from in the range [-32768.0,32767.0] to ints + * without rescaling + * + * @param dst destination array of interleaved int16_t. + * constraints: 16-byte aligned + * @param src source array of float arrays, one for each channel. + * constraints: 16-byte aligned + * @param len number of elements to convert. + * constraints: multiple of 8 + * @param channels number of channels + */ + void (*float_to_int16_interleave)(int16_t *dst, const float **src, + long len, int channels); + + /** + * Convert multiple arrays of float to an array of interleaved float. + * + * @param dst destination array of interleaved float. + * constraints: 16-byte aligned + * @param src source array of float arrays, one for each channel. + * constraints: 16-byte aligned + * @param len number of elements to convert. + * constraints: multiple of 8 + * @param channels number of channels + */ + void (*float_interleave)(float *dst, const float **src, unsigned int len, + int channels); +} FmtConvertContext; + +void ff_float_interleave_c(float *dst, const float **src, unsigned int len, + int channels); + +void ff_fmt_convert_init(FmtConvertContext *c, AVCodecContext *avctx); + +void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx); +void ff_fmt_convert_init_altivec(FmtConvertContext *c, AVCodecContext *avctx); +void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx); +void ff_fmt_convert_init_mips(FmtConvertContext *c); + +/* ffdshow custom code */ +void float_interleave(float *dst, const float **src, long len, int channels); +void float_interleave_noscale(float *dst, const float **src, long len, int channels); + +#endif /* AVCODEC_FMTCONVERT_H */ diff --git a/ffmpeg/libavcodec/frame_thread_encoder.c b/ffmpeg/libavcodec/frame_thread_encoder.c new file mode 100644 index 0000000..b11a54a --- /dev/null +++ b/ffmpeg/libavcodec/frame_thread_encoder.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2012 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 "frame_thread_encoder.h" + +#include "libavutil/fifo.h" +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" +#include "thread.h" + +#if HAVE_PTHREADS +#include +#elif HAVE_W32THREADS +#include "w32pthreads.h" +#elif HAVE_OS2THREADS +#include "os2threads.h" +#endif + +#define MAX_THREADS 64 +#define BUFFER_SIZE (2*MAX_THREADS) + +typedef struct{ + void *indata; + void *outdata; + int64_t return_code; + unsigned index; +} Task; + +typedef struct{ + AVCodecContext *parent_avctx; + pthread_mutex_t buffer_mutex; + + AVFifoBuffer *task_fifo; + pthread_mutex_t task_fifo_mutex; + pthread_cond_t task_fifo_cond; + + Task finished_tasks[BUFFER_SIZE]; + pthread_mutex_t finished_task_mutex; + pthread_cond_t finished_task_cond; + + unsigned task_index; + unsigned finished_task_index; + + pthread_t worker[MAX_THREADS]; + int exit; +} ThreadContext; + +static void * attribute_align_arg worker(void *v){ + AVCodecContext *avctx = v; + ThreadContext *c = avctx->internal->frame_thread_encoder; + AVPacket *pkt = NULL; + + while(!c->exit){ + int got_packet, ret; + AVFrame *frame; + Task task; + + if(!pkt) pkt= av_mallocz(sizeof(*pkt)); + if(!pkt) continue; + av_init_packet(pkt); + + pthread_mutex_lock(&c->task_fifo_mutex); + while (av_fifo_size(c->task_fifo) <= 0 || c->exit) { + if(c->exit){ + pthread_mutex_unlock(&c->task_fifo_mutex); + goto end; + } + pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex); + } + av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL); + pthread_mutex_unlock(&c->task_fifo_mutex); + frame = task.indata; + + ret = avcodec_encode_video2(avctx, pkt, frame, &got_packet); + pthread_mutex_lock(&c->buffer_mutex); + av_frame_unref(frame); + pthread_mutex_unlock(&c->buffer_mutex); + av_frame_free(&frame); + if(got_packet) { + av_dup_packet(pkt); + } else { + pkt->data = NULL; + pkt->size = 0; + } + pthread_mutex_lock(&c->finished_task_mutex); + c->finished_tasks[task.index].outdata = pkt; pkt = NULL; + c->finished_tasks[task.index].return_code = ret; + pthread_cond_signal(&c->finished_task_cond); + pthread_mutex_unlock(&c->finished_task_mutex); + } +end: + av_free(pkt); + pthread_mutex_lock(&c->buffer_mutex); + avcodec_close(avctx); + pthread_mutex_unlock(&c->buffer_mutex); + av_freep(&avctx); + return NULL; +} + +int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){ + int i=0; + ThreadContext *c; + + + if( !(avctx->thread_type & FF_THREAD_FRAME) + || !(avctx->codec->capabilities & CODEC_CAP_INTRA_ONLY)) + return 0; + + if(!avctx->thread_count) { + avctx->thread_count = ff_get_logical_cpus(avctx); + avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS); + } + + if(avctx->thread_count <= 1) + return 0; + + if(avctx->thread_count > MAX_THREADS) + return AVERROR(EINVAL); + + av_assert0(!avctx->internal->frame_thread_encoder); + c = avctx->internal->frame_thread_encoder = av_mallocz(sizeof(ThreadContext)); + if(!c) + return AVERROR(ENOMEM); + + c->parent_avctx = avctx; + + c->task_fifo = av_fifo_alloc(sizeof(Task) * BUFFER_SIZE); + if(!c->task_fifo) + goto fail; + + pthread_mutex_init(&c->task_fifo_mutex, NULL); + pthread_mutex_init(&c->finished_task_mutex, NULL); + pthread_mutex_init(&c->buffer_mutex, NULL); + pthread_cond_init(&c->task_fifo_cond, NULL); + pthread_cond_init(&c->finished_task_cond, NULL); + + for(i=0; ithread_count ; i++){ + AVDictionary *tmp = NULL; + void *tmpv; + AVCodecContext *thread_avctx = avcodec_alloc_context3(avctx->codec); + if(!thread_avctx) + goto fail; + tmpv = thread_avctx->priv_data; + *thread_avctx = *avctx; + thread_avctx->priv_data = tmpv; + thread_avctx->internal = NULL; + memcpy(thread_avctx->priv_data, avctx->priv_data, avctx->codec->priv_data_size); + thread_avctx->thread_count = 1; + thread_avctx->active_thread_type &= ~FF_THREAD_FRAME; + + av_dict_copy(&tmp, options, 0); + av_dict_set(&tmp, "threads", "1", 0); + if(avcodec_open2(thread_avctx, avctx->codec, &tmp) < 0) { + av_dict_free(&tmp); + goto fail; + } + av_dict_free(&tmp); + av_assert0(!thread_avctx->internal->frame_thread_encoder); + thread_avctx->internal->frame_thread_encoder = c; + if(pthread_create(&c->worker[i], NULL, worker, thread_avctx)) { + goto fail; + } + } + + avctx->active_thread_type = FF_THREAD_FRAME; + + return 0; +fail: + avctx->thread_count = i; + av_log(avctx, AV_LOG_ERROR, "ff_frame_thread_encoder_init failed\n"); + ff_frame_thread_encoder_free(avctx); + return -1; +} + +void ff_frame_thread_encoder_free(AVCodecContext *avctx){ + int i; + ThreadContext *c= avctx->internal->frame_thread_encoder; + + pthread_mutex_lock(&c->task_fifo_mutex); + c->exit = 1; + pthread_cond_broadcast(&c->task_fifo_cond); + pthread_mutex_unlock(&c->task_fifo_mutex); + + for (i=0; ithread_count; i++) { + pthread_join(c->worker[i], NULL); + } + + pthread_mutex_destroy(&c->task_fifo_mutex); + pthread_mutex_destroy(&c->finished_task_mutex); + pthread_mutex_destroy(&c->buffer_mutex); + pthread_cond_destroy(&c->task_fifo_cond); + pthread_cond_destroy(&c->finished_task_cond); + av_fifo_free(c->task_fifo); c->task_fifo = NULL; + av_freep(&avctx->internal->frame_thread_encoder); +} + +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr){ + ThreadContext *c = avctx->internal->frame_thread_encoder; + Task task; + int ret; + + av_assert1(!*got_packet_ptr); + + if(frame){ + if(!(avctx->flags & CODEC_FLAG_INPUT_PRESERVED)){ + AVFrame *new = av_frame_alloc(); + if(!new) + return AVERROR(ENOMEM); + pthread_mutex_lock(&c->buffer_mutex); + ret = ff_get_buffer(c->parent_avctx, new, 0); + pthread_mutex_unlock(&c->buffer_mutex); + if(ret<0) + return ret; + new->pts = frame->pts; + new->quality = frame->quality; + new->pict_type = frame->pict_type; + av_image_copy(new->data, new->linesize, (const uint8_t **)frame->data, frame->linesize, + avctx->pix_fmt, avctx->width, avctx->height); + frame = new; + } + + task.index = c->task_index; + task.indata = (void*)frame; + pthread_mutex_lock(&c->task_fifo_mutex); + av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL); + pthread_cond_signal(&c->task_fifo_cond); + pthread_mutex_unlock(&c->task_fifo_mutex); + + c->task_index = (c->task_index+1) % BUFFER_SIZE; + + if(!c->finished_tasks[c->finished_task_index].outdata && (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count) + return 0; + } + + if(c->task_index == c->finished_task_index) + return 0; + + pthread_mutex_lock(&c->finished_task_mutex); + while (!c->finished_tasks[c->finished_task_index].outdata) { + pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex); + } + task = c->finished_tasks[c->finished_task_index]; + *pkt = *(AVPacket*)(task.outdata); + if(pkt->data) + *got_packet_ptr = 1; + av_freep(&c->finished_tasks[c->finished_task_index].outdata); + c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE; + pthread_mutex_unlock(&c->finished_task_mutex); + + return task.return_code; +} diff --git a/ffmpeg/libavcodec/frame_thread_encoder.h b/ffmpeg/libavcodec/frame_thread_encoder.h new file mode 100644 index 0000000..1da0ce1 --- /dev/null +++ b/ffmpeg/libavcodec/frame_thread_encoder.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2012 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 "avcodec.h" + +int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options); +void ff_frame_thread_encoder_free(AVCodecContext *avctx); +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr); + diff --git a/ffmpeg/libavcodec/fraps.c b/ffmpeg/libavcodec/fraps.c new file mode 100644 index 0000000..00a38c6 --- /dev/null +++ b/ffmpeg/libavcodec/fraps.c @@ -0,0 +1,315 @@ +/* + * Fraps FPS1 decoder + * Copyright (c) 2005 Roine Gustafsson + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Lossless Fraps 'FPS1' decoder + * @author Roine Gustafsson (roine at users sf net) + * @author Konstantin Shishkov + * + * Codec algorithm for version 0 is taken from Transcode + * + * Version 2 files support by Konstantin Shishkov + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "huffman.h" +#include "bytestream.h" +#include "dsputil.h" +#include "internal.h" +#include "thread.h" + +#define FPS_TAG MKTAG('F', 'P', 'S', 'x') + +/** + * local variable storage + */ +typedef struct FrapsContext { + AVCodecContext *avctx; + uint8_t *tmpbuf; + int tmpbuf_size; + DSPContext dsp; +} FrapsContext; + + +/** + * initializes decoder + * @param avctx codec context + * @return 0 on success or negative if fails + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + FrapsContext * const s = avctx->priv_data; + + s->avctx = avctx; + s->tmpbuf = NULL; + + ff_dsputil_init(&s->dsp, avctx); + + return 0; +} + +/** + * Comparator - our nodes should ascend by count + * but with preserved symbol order + */ +static int huff_cmp(const void *va, const void *vb) +{ + const Node *a = va, *b = vb; + return (a->count - b->count)*256 + a->sym - b->sym; +} + +/** + * decode Fraps v2 packed plane + */ +static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, + int h, const uint8_t *src, int size, int Uoff, + const int step) +{ + int i, j, ret; + GetBitContext gb; + VLC vlc; + Node nodes[512]; + + for (i = 0; i < 256; i++) + nodes[i].count = bytestream_get_le32(&src); + size -= 1024; + if ((ret = ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp, + FF_HUFFMAN_FLAG_ZERO_COUNT)) < 0) + return ret; + /* we have built Huffman table and are ready to decode plane */ + + /* convert bits so they may be used by standard bitreader */ + s->dsp.bswap_buf((uint32_t *)s->tmpbuf, (const uint32_t *)src, size >> 2); + + init_get_bits(&gb, s->tmpbuf, size * 8); + for (j = 0; j < h; j++) { + for (i = 0; i < w*step; i += step) { + dst[i] = get_vlc2(&gb, vlc.table, 9, 3); + /* lines are stored as deltas between previous lines + * and we need to add 0x80 to the first lines of chroma planes + */ + if (j) + dst[i] += dst[i - stride]; + else if (Uoff) + dst[i] += 0x80; + if (get_bits_left(&gb) < 0) { + ff_free_vlc(&vlc); + return AVERROR_INVALIDDATA; + } + } + dst += stride; + } + ff_free_vlc(&vlc); + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + FrapsContext * const s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ThreadFrame frame = { .f = data }; + AVFrame * const f = data; + uint32_t header; + unsigned int version,header_size; + unsigned int x, y; + const uint32_t *buf32; + uint32_t *luma1,*luma2,*cb,*cr; + uint32_t offs[4]; + int i, j, ret, is_chroma; + const int planes = 3; + uint8_t *out; + + header = AV_RL32(buf); + version = header & 0xff; + header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */ + + if (version > 5) { + av_log(avctx, AV_LOG_ERROR, + "This file is encoded with Fraps version %d. " \ + "This codec can only decode versions <= 5.\n", version); + return AVERROR_PATCHWELCOME; + } + + buf += header_size; + + if (version < 2) { + unsigned needed_size = avctx->width * avctx->height * 3; + if (version == 0) needed_size /= 2; + needed_size += header_size; + /* bit 31 means same as previous pic */ + if (header & (1U<<31)) { + *got_frame = 0; + return buf_size; + } + if (buf_size != needed_size) { + av_log(avctx, AV_LOG_ERROR, + "Invalid frame length %d (should be %d)\n", + buf_size, needed_size); + return AVERROR_INVALIDDATA; + } + } else { + /* skip frame */ + if (buf_size == 8) { + *got_frame = 0; + return buf_size; + } + if (AV_RL32(buf) != FPS_TAG || buf_size < planes*1024 + 24) { + av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < planes; i++) { + offs[i] = AV_RL32(buf + 4 + i * 4); + if (offs[i] >= buf_size - header_size || (i && offs[i] <= offs[i - 1] + 1024)) { + av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i); + return AVERROR_INVALIDDATA; + } + } + offs[planes] = buf_size - header_size; + for (i = 0; i < planes; i++) { + av_fast_padded_malloc(&s->tmpbuf, &s->tmpbuf_size, offs[i + 1] - offs[i] - 1024); + if (!s->tmpbuf) + return AVERROR(ENOMEM); + } + } + + f->pict_type = AV_PICTURE_TYPE_I; + f->key_frame = 1; + + avctx->pix_fmt = version & 1 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + switch (version) { + case 0: + default: + /* Fraps v0 is a reordered YUV420 */ + if (((avctx->width % 8) != 0) || ((avctx->height % 2) != 0)) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n", + avctx->width, avctx->height); + return AVERROR_INVALIDDATA; + } + + buf32 = (const uint32_t*)buf; + for (y = 0; y < avctx->height / 2; y++) { + luma1 = (uint32_t*)&f->data[0][ y * 2 * f->linesize[0] ]; + luma2 = (uint32_t*)&f->data[0][ (y * 2 + 1) * f->linesize[0] ]; + cr = (uint32_t*)&f->data[1][ y * f->linesize[1] ]; + cb = (uint32_t*)&f->data[2][ y * f->linesize[2] ]; + for (x = 0; x < avctx->width; x += 8) { + *luma1++ = *buf32++; + *luma1++ = *buf32++; + *luma2++ = *buf32++; + *luma2++ = *buf32++; + *cr++ = *buf32++; + *cb++ = *buf32++; + } + } + break; + + case 1: + /* Fraps v1 is an upside-down BGR24 */ + for (y = 0; yheight; y++) + memcpy(&f->data[0][(avctx->height - y - 1) * f->linesize[0]], + &buf[y * avctx->width * 3], + 3 * avctx->width); + break; + + case 2: + case 4: + /** + * Fraps v2 is Huffman-coded YUV420 planes + * Fraps v4 is virtually the same + */ + for (i = 0; i < planes; i++) { + is_chroma = !!i; + if ((ret = fraps2_decode_plane(s, f->data[i], f->linesize[i], + avctx->width >> is_chroma, + avctx->height >> is_chroma, + buf + offs[i], offs[i + 1] - offs[i], + is_chroma, 1)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i); + return ret; + } + } + break; + case 3: + case 5: + /* Virtually the same as version 4, but is for RGB24 */ + for (i = 0; i < planes; i++) { + if ((ret = fraps2_decode_plane(s, f->data[0] + i + (f->linesize[0] * (avctx->height - 1)), + -f->linesize[0], avctx->width, avctx->height, + buf + offs[i], offs[i + 1] - offs[i], 0, 3)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i); + return ret; + } + } + out = f->data[0]; + // convert pseudo-YUV into real RGB + for (j = 0; j < avctx->height; j++) { + uint8_t *line_end = out + 3*avctx->width; + while (out < line_end) { + out[0] += out[1]; + out[2] += out[1]; + out += 3; + } + out += f->linesize[0] - 3*avctx->width; + } + break; + } + + *got_frame = 1; + + return buf_size; +} + + +/** + * closes decoder + * @param avctx codec context + * @return 0 on success or negative if fails + */ +static av_cold int decode_end(AVCodecContext *avctx) +{ + FrapsContext *s = (FrapsContext*)avctx->priv_data; + + av_freep(&s->tmpbuf); + return 0; +} + + +AVCodec ff_fraps_decoder = { + .name = "fraps", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FRAPS, + .priv_data_size = sizeof(FrapsContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Fraps"), +}; diff --git a/ffmpeg/libavcodec/frwu.c b/ffmpeg/libavcodec/frwu.c new file mode 100644 index 0000000..b1c7408 --- /dev/null +++ b/ffmpeg/libavcodec/frwu.c @@ -0,0 +1,128 @@ +/* + * Forward Uncompressed + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "libavutil/opt.h" + +typedef struct { + AVClass *av_class; + int change_field_order; +} FRWUContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "frwu needs even width\n"); + return AVERROR(EINVAL); + } + avctx->pix_fmt = AV_PIX_FMT_UYVY422; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + FRWUContext *s = avctx->priv_data; + int field, ret; + AVFrame *pic = data; + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = buf + avpkt->size; + + if (avpkt->size < avctx->width * 2 * avctx->height + 4 + 2*8) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small.\n"); + return AVERROR_INVALIDDATA; + } + if (bytestream_get_le32(&buf) != MKTAG('F', 'R', 'W', '1')) { + av_log(avctx, AV_LOG_ERROR, "incorrect marker\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + + for (field = 0; field < 2; field++) { + int i; + int field_h = (avctx->height + !field) >> 1; + int field_size, min_field_size = avctx->width * 2 * field_h; + uint8_t *dst = pic->data[0]; + if (buf_end - buf < 8) + return AVERROR_INVALIDDATA; + buf += 4; // flags? 0x80 == bottom field maybe? + field_size = bytestream_get_le32(&buf); + if (field_size < min_field_size) { + av_log(avctx, AV_LOG_ERROR, "Field size %i is too small (required %i)\n", field_size, min_field_size); + return AVERROR_INVALIDDATA; + } + if (buf_end - buf < field_size) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small, need %i, have %i\n", field_size, (int)(buf_end - buf)); + return AVERROR_INVALIDDATA; + } + if (field ^ s->change_field_order) { + dst += pic->linesize[0]; + } else if (s->change_field_order) { + dst += 2 * pic->linesize[0]; + } + for (i = 0; i < field_h; i++) { + if (s->change_field_order && field && i == field_h - 1) + dst = pic->data[0]; + memcpy(dst, buf, avctx->width * 2); + buf += avctx->width * 2; + dst += pic->linesize[0] << 1; + } + buf += field_size - min_field_size; + } + + *got_frame = 1; + + return avpkt->size; +} + +static const AVOption frwu_options[] = { + {"change_field_order", "Change field order", offsetof(FRWUContext, change_field_order), FF_OPT_TYPE_INT, + {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM}, + {NULL} +}; + +static const AVClass frwu_class = { + .class_name = "frwu Decoder", + .item_name = av_default_item_name, + .option = frwu_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_frwu_decoder = { + .name = "frwu", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FRWU, + .priv_data_size = sizeof(FRWUContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Forward Uncompressed"), + .priv_class = &frwu_class, +}; diff --git a/ffmpeg/libavcodec/g722.c b/ffmpeg/libavcodec/g722.c new file mode 100644 index 0000000..2c04c40 --- /dev/null +++ b/ffmpeg/libavcodec/g722.c @@ -0,0 +1,171 @@ +/* + * G.722 ADPCM audio encoder/decoder + * + * Copyright (c) CMU 1993 Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * Copyright (c) 2005 Steve Underwood + * Copyright (c) 2009 Kenan Gillet + * Copyright (c) 2010 Martin Storsjo + * + * 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 + */ + +/** + * @file + * G.722 ADPCM audio codec + * + * This G.722 decoder is a bit-exact implementation of the ITU G.722 + * specification for all three specified bitrates - 64000bps, 56000bps + * and 48000bps. It passes the ITU tests. + * + * @note For the 56000bps and 48000bps bitrates, the lowest 1 or 2 bits + * respectively of each byte are ignored. + */ + +#include "mathops.h" +#include "g722.h" + +static const int8_t sign_lookup[2] = { -1, 1 }; + +static const int16_t inv_log2_table[32] = { + 2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383, + 2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834, + 2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371, + 3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008 +}; +static const int16_t high_log_factor_step[2] = { 798, -214 }; +const int16_t ff_g722_high_inv_quant[4] = { -926, -202, 926, 202 }; +/** + * low_log_factor_step[index] == wl[rl42[index]] + */ +static const int16_t low_log_factor_step[16] = { + -60, 3042, 1198, 538, 334, 172, 58, -30, + 3042, 1198, 538, 334, 172, 58, -30, -60 +}; +const int16_t ff_g722_low_inv_quant4[16] = { + 0, -2557, -1612, -1121, -786, -530, -323, -150, + 2557, 1612, 1121, 786, 530, 323, 150, 0 +}; +const int16_t ff_g722_low_inv_quant6[64] = { + -17, -17, -17, -17, -3101, -2738, -2376, -2088, + -1873, -1689, -1535, -1399, -1279, -1170, -1072, -982, + -899, -822, -750, -682, -618, -558, -501, -447, + -396, -347, -300, -254, -211, -170, -130, -91, + 3101, 2738, 2376, 2088, 1873, 1689, 1535, 1399, + 1279, 1170, 1072, 982, 899, 822, 750, 682, + 618, 558, 501, 447, 396, 347, 300, 254, + 211, 170, 130, 91, 54, 17, -54, -17 +}; + +/** + * quadrature mirror filter (QMF) coefficients + * + * ITU-T G.722 Table 11 + */ +static const int16_t qmf_coeffs[12] = { + 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11, +}; + + +/** + * adaptive predictor + * + * @param cur_diff the dequantized and scaled delta calculated from the + * current codeword + */ +static void do_adaptive_prediction(struct G722Band *band, const int cur_diff) +{ + int sg[2], limit, i, cur_qtzd_reconst; + + const int cur_part_reconst = band->s_zero + cur_diff < 0; + + sg[0] = sign_lookup[cur_part_reconst != band->part_reconst_mem[0]]; + sg[1] = sign_lookup[cur_part_reconst == band->part_reconst_mem[1]]; + band->part_reconst_mem[1] = band->part_reconst_mem[0]; + band->part_reconst_mem[0] = cur_part_reconst; + + band->pole_mem[1] = av_clip((sg[0] * av_clip(band->pole_mem[0], -8191, 8191) >> 5) + + (sg[1] << 7) + (band->pole_mem[1] * 127 >> 7), -12288, 12288); + + limit = 15360 - band->pole_mem[1]; + band->pole_mem[0] = av_clip(-192 * sg[0] + (band->pole_mem[0] * 255 >> 8), -limit, limit); + + + if (cur_diff) { + for (i = 0; i < 6; i++) + band->zero_mem[i] = ((band->zero_mem[i]*255) >> 8) + + ((band->diff_mem[i]^cur_diff) < 0 ? -128 : 128); + } else + for (i = 0; i < 6; i++) + band->zero_mem[i] = (band->zero_mem[i]*255) >> 8; + + for (i = 5; i > 0; i--) + band->diff_mem[i] = band->diff_mem[i-1]; + band->diff_mem[0] = av_clip_int16(cur_diff << 1); + + band->s_zero = 0; + for (i = 5; i >= 0; i--) + band->s_zero += (band->zero_mem[i]*band->diff_mem[i]) >> 15; + + + cur_qtzd_reconst = av_clip_int16((band->s_predictor + cur_diff) << 1); + band->s_predictor = av_clip_int16(band->s_zero + + (band->pole_mem[0] * cur_qtzd_reconst >> 15) + + (band->pole_mem[1] * band->prev_qtzd_reconst >> 15)); + band->prev_qtzd_reconst = cur_qtzd_reconst; +} + +static inline int linear_scale_factor(const int log_factor) +{ + const int wd1 = inv_log2_table[(log_factor >> 6) & 31]; + const int shift = log_factor >> 11; + return shift < 0 ? wd1 >> -shift : wd1 << shift; +} + +void ff_g722_update_low_predictor(struct G722Band *band, const int ilow) +{ + do_adaptive_prediction(band, + band->scale_factor * ff_g722_low_inv_quant4[ilow] >> 10); + + // quantizer adaptation + band->log_factor = av_clip((band->log_factor * 127 >> 7) + + low_log_factor_step[ilow], 0, 18432); + band->scale_factor = linear_scale_factor(band->log_factor - (8 << 11)); +} + +void ff_g722_update_high_predictor(struct G722Band *band, const int dhigh, + const int ihigh) +{ + do_adaptive_prediction(band, dhigh); + + // quantizer adaptation + band->log_factor = av_clip((band->log_factor * 127 >> 7) + + high_log_factor_step[ihigh&1], 0, 22528); + band->scale_factor = linear_scale_factor(band->log_factor - (10 << 11)); +} + +void ff_g722_apply_qmf(const int16_t *prev_samples, int *xout1, int *xout2) +{ + int i; + + *xout1 = 0; + *xout2 = 0; + for (i = 0; i < 12; i++) { + MAC16(*xout2, prev_samples[2*i ], qmf_coeffs[i ]); + MAC16(*xout1, prev_samples[2*i+1], qmf_coeffs[11-i]); + } +} diff --git a/ffmpeg/libavcodec/g722.h b/ffmpeg/libavcodec/g722.h new file mode 100644 index 0000000..71d03fc --- /dev/null +++ b/ffmpeg/libavcodec/g722.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) CMU 1993 Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * Copyright (c) 2005 Steve Underwood + * Copyright (c) 2009 Kenan Gillet + * Copyright (c) 2010 Martin Storsjo + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_G722_H +#define AVCODEC_G722_H + +#include +#include "avcodec.h" + +#define PREV_SAMPLES_BUF_SIZE 1024 + +typedef struct G722Context { + const AVClass *class; + int bits_per_codeword; + int16_t prev_samples[PREV_SAMPLES_BUF_SIZE]; ///< memory of past decoded samples + int prev_samples_pos; ///< the number of values in prev_samples + + /** + * The band[0] and band[1] correspond respectively to the lower band and higher band. + */ + struct G722Band { + int16_t s_predictor; ///< predictor output value + int32_t s_zero; ///< previous output signal from zero predictor + int8_t part_reconst_mem[2]; ///< signs of previous partially reconstructed signals + int16_t prev_qtzd_reconst; ///< previous quantized reconstructed signal (internal value, using low_inv_quant4) + int16_t pole_mem[2]; ///< second-order pole section coefficient buffer + int32_t diff_mem[6]; ///< quantizer difference signal memory + int16_t zero_mem[6]; ///< Seventh-order zero section coefficient buffer + int16_t log_factor; ///< delayed 2-logarithmic quantizer factor + int16_t scale_factor; ///< delayed quantizer scale factor + } band[2]; + + struct TrellisNode { + struct G722Band state; + uint32_t ssd; + int path; + } *node_buf[2], **nodep_buf[2]; + + struct TrellisPath { + int value; + int prev; + } *paths[2]; +} G722Context; + +extern const int16_t ff_g722_high_inv_quant[4]; +extern const int16_t ff_g722_low_inv_quant4[16]; +extern const int16_t ff_g722_low_inv_quant6[64]; + +void ff_g722_update_low_predictor(struct G722Band *band, const int ilow); + +void ff_g722_update_high_predictor(struct G722Band *band, const int dhigh, + const int ihigh); + +void ff_g722_apply_qmf(const int16_t *prev_samples, int *xout1, int *xout2); + +#endif /* AVCODEC_G722_H */ diff --git a/ffmpeg/libavcodec/g722dec.c b/ffmpeg/libavcodec/g722dec.c new file mode 100644 index 0000000..1a489a7 --- /dev/null +++ b/ffmpeg/libavcodec/g722dec.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) CMU 1993 Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * Copyright (c) 2005 Steve Underwood + * Copyright (c) 2009 Kenan Gillet + * Copyright (c) 2010 Martin Storsjo + * + * 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 + */ + +/** + * @file + * G.722 ADPCM audio decoder + * + * This G.722 decoder is a bit-exact implementation of the ITU G.722 + * specification for all three specified bitrates - 64000bps, 56000bps + * and 48000bps. It passes the ITU tests. + * + * @note For the 56000bps and 48000bps bitrates, the lowest 1 or 2 bits + * respectively of each byte are ignored. + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "get_bits.h" +#include "g722.h" +#include "internal.h" + +#define OFFSET(x) offsetof(G722Context, x) +#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "bits_per_codeword", "Bits per G722 codeword", OFFSET(bits_per_codeword), AV_OPT_TYPE_FLAGS, { .i64 = 8 }, 6, 8, AD }, + { NULL } +}; + +static const AVClass g722_decoder_class = { + .class_name = "g722 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static av_cold int g722_decode_init(AVCodecContext * avctx) +{ + G722Context *c = avctx->priv_data; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + c->band[0].scale_factor = 8; + c->band[1].scale_factor = 2; + c->prev_samples_pos = 22; + + return 0; +} + +static const int16_t low_inv_quant5[32] = { + -35, -35, -2919, -2195, -1765, -1458, -1219, -1023, + -858, -714, -587, -473, -370, -276, -190, -110, + 2919, 2195, 1765, 1458, 1219, 1023, 858, 714, + 587, 473, 370, 276, 190, 110, 35, -35 +}; + +static const int16_t *low_inv_quants[3] = { ff_g722_low_inv_quant6, + low_inv_quant5, + ff_g722_low_inv_quant4 }; + +static int g722_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + G722Context *c = avctx->priv_data; + AVFrame *frame = data; + int16_t *out_buf; + int j, ret; + const int skip = 8 - c->bits_per_codeword; + const int16_t *quantizer_table = low_inv_quants[skip]; + GetBitContext gb; + + /* get output buffer */ + frame->nb_samples = avpkt->size * 2; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + out_buf = (int16_t *)frame->data[0]; + + init_get_bits(&gb, avpkt->data, avpkt->size * 8); + + for (j = 0; j < avpkt->size; j++) { + int ilow, ihigh, rlow, rhigh, dhigh; + int xout1, xout2; + + ihigh = get_bits(&gb, 2); + ilow = get_bits(&gb, 6 - skip); + skip_bits(&gb, skip); + + rlow = av_clip((c->band[0].scale_factor * quantizer_table[ilow] >> 10) + + c->band[0].s_predictor, -16384, 16383); + + ff_g722_update_low_predictor(&c->band[0], ilow >> (2 - skip)); + + dhigh = c->band[1].scale_factor * ff_g722_high_inv_quant[ihigh] >> 10; + rhigh = av_clip(dhigh + c->band[1].s_predictor, -16384, 16383); + + ff_g722_update_high_predictor(&c->band[1], dhigh, ihigh); + + c->prev_samples[c->prev_samples_pos++] = rlow + rhigh; + c->prev_samples[c->prev_samples_pos++] = rlow - rhigh; + ff_g722_apply_qmf(c->prev_samples + c->prev_samples_pos - 24, + &xout1, &xout2); + *out_buf++ = av_clip_int16(xout1 >> 11); + *out_buf++ = av_clip_int16(xout2 >> 11); + if (c->prev_samples_pos >= PREV_SAMPLES_BUF_SIZE) { + memmove(c->prev_samples, c->prev_samples + c->prev_samples_pos - 22, + 22 * sizeof(c->prev_samples[0])); + c->prev_samples_pos = 22; + } + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +AVCodec ff_adpcm_g722_decoder = { + .name = "g722", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_G722, + .priv_data_size = sizeof(G722Context), + .init = g722_decode_init, + .decode = g722_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), + .priv_class = &g722_decoder_class, +}; diff --git a/ffmpeg/libavcodec/g722enc.c b/ffmpeg/libavcodec/g722enc.c new file mode 100644 index 0000000..b276b4e --- /dev/null +++ b/ffmpeg/libavcodec/g722enc.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) CMU 1993 Computer Science, Speech Group + * Chengxiang Lu and Alex Hauptmann + * Copyright (c) 2005 Steve Underwood + * Copyright (c) 2009 Kenan Gillet + * Copyright (c) 2010 Martin Storsjo + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * G.722 ADPCM audio encoder + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +#include "g722.h" +#include "libavutil/common.h" + +#define FREEZE_INTERVAL 128 + +/* This is an arbitrary value. Allowing insanely large values leads to strange + problems, so we limit it to a reasonable value */ +#define MAX_FRAME_SIZE 32768 + +/* We clip the value of avctx->trellis to prevent data type overflows and + undefined behavior. Using larger values is insanely slow anyway. */ +#define MIN_TRELLIS 0 +#define MAX_TRELLIS 16 + +static av_cold int g722_encode_close(AVCodecContext *avctx) +{ + G722Context *c = avctx->priv_data; + int i; + for (i = 0; i < 2; i++) { + av_freep(&c->paths[i]); + av_freep(&c->node_buf[i]); + av_freep(&c->nodep_buf[i]); + } + return 0; +} + +static av_cold int g722_encode_init(AVCodecContext * avctx) +{ + G722Context *c = avctx->priv_data; + int ret; + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono tracks are allowed.\n"); + return AVERROR_INVALIDDATA; + } + + c->band[0].scale_factor = 8; + c->band[1].scale_factor = 2; + c->prev_samples_pos = 22; + + if (avctx->trellis) { + int frontier = 1 << avctx->trellis; + int max_paths = frontier * FREEZE_INTERVAL; + int i; + for (i = 0; i < 2; i++) { + c->paths[i] = av_mallocz(max_paths * sizeof(**c->paths)); + c->node_buf[i] = av_mallocz(2 * frontier * sizeof(**c->node_buf)); + c->nodep_buf[i] = av_mallocz(2 * frontier * sizeof(**c->nodep_buf)); + if (!c->paths[i] || !c->node_buf[i] || !c->nodep_buf[i]) { + ret = AVERROR(ENOMEM); + goto error; + } + } + } + + if (avctx->frame_size) { + /* validate frame size */ + if (avctx->frame_size & 1 || avctx->frame_size > MAX_FRAME_SIZE) { + int new_frame_size; + + if (avctx->frame_size == 1) + new_frame_size = 2; + else if (avctx->frame_size > MAX_FRAME_SIZE) + new_frame_size = MAX_FRAME_SIZE; + else + new_frame_size = avctx->frame_size - 1; + + av_log(avctx, AV_LOG_WARNING, "Requested frame size is not " + "allowed. Using %d instead of %d\n", new_frame_size, + avctx->frame_size); + avctx->frame_size = new_frame_size; + } + } else { + /* This is arbitrary. We use 320 because it's 20ms @ 16kHz, which is + a common packet size for VoIP applications */ + avctx->frame_size = 320; + } + avctx->delay = 22; + + if (avctx->trellis) { + /* validate trellis */ + if (avctx->trellis < MIN_TRELLIS || avctx->trellis > MAX_TRELLIS) { + int new_trellis = av_clip(avctx->trellis, MIN_TRELLIS, MAX_TRELLIS); + av_log(avctx, AV_LOG_WARNING, "Requested trellis value is not " + "allowed. Using %d instead of %d\n", new_trellis, + avctx->trellis); + avctx->trellis = new_trellis; + } + } + + return 0; +error: + g722_encode_close(avctx); + return ret; +} + +static const int16_t low_quant[33] = { + 35, 72, 110, 150, 190, 233, 276, 323, + 370, 422, 473, 530, 587, 650, 714, 786, + 858, 940, 1023, 1121, 1219, 1339, 1458, 1612, + 1765, 1980, 2195, 2557, 2919 +}; + +static inline void filter_samples(G722Context *c, const int16_t *samples, + int *xlow, int *xhigh) +{ + int xout1, xout2; + c->prev_samples[c->prev_samples_pos++] = samples[0]; + c->prev_samples[c->prev_samples_pos++] = samples[1]; + ff_g722_apply_qmf(c->prev_samples + c->prev_samples_pos - 24, &xout1, &xout2); + *xlow = xout1 + xout2 >> 14; + *xhigh = xout1 - xout2 >> 14; + if (c->prev_samples_pos >= PREV_SAMPLES_BUF_SIZE) { + memmove(c->prev_samples, + c->prev_samples + c->prev_samples_pos - 22, + 22 * sizeof(c->prev_samples[0])); + c->prev_samples_pos = 22; + } +} + +static inline int encode_high(const struct G722Band *state, int xhigh) +{ + int diff = av_clip_int16(xhigh - state->s_predictor); + int pred = 141 * state->scale_factor >> 8; + /* = diff >= 0 ? (diff < pred) + 2 : diff >= -pred */ + return ((diff ^ (diff >> (sizeof(diff)*8-1))) < pred) + 2*(diff >= 0); +} + +static inline int encode_low(const struct G722Band* state, int xlow) +{ + int diff = av_clip_int16(xlow - state->s_predictor); + /* = diff >= 0 ? diff : -(diff + 1) */ + int limit = diff ^ (diff >> (sizeof(diff)*8-1)); + int i = 0; + limit = limit + 1 << 10; + if (limit > low_quant[8] * state->scale_factor) + i = 9; + while (i < 29 && limit > low_quant[i] * state->scale_factor) + i++; + return (diff < 0 ? (i < 2 ? 63 : 33) : 61) - i; +} + +static void g722_encode_trellis(G722Context *c, int trellis, + uint8_t *dst, int nb_samples, + const int16_t *samples) +{ + int i, j, k; + int frontier = 1 << trellis; + struct TrellisNode **nodes[2]; + struct TrellisNode **nodes_next[2]; + int pathn[2] = {0, 0}, froze = -1; + struct TrellisPath *p[2]; + + for (i = 0; i < 2; i++) { + nodes[i] = c->nodep_buf[i]; + nodes_next[i] = c->nodep_buf[i] + frontier; + memset(c->nodep_buf[i], 0, 2 * frontier * sizeof(*c->nodep_buf[i])); + nodes[i][0] = c->node_buf[i] + frontier; + nodes[i][0]->ssd = 0; + nodes[i][0]->path = 0; + nodes[i][0]->state = c->band[i]; + } + + for (i = 0; i < nb_samples >> 1; i++) { + int xlow, xhigh; + struct TrellisNode *next[2]; + int heap_pos[2] = {0, 0}; + + for (j = 0; j < 2; j++) { + next[j] = c->node_buf[j] + frontier*(i & 1); + memset(nodes_next[j], 0, frontier * sizeof(**nodes_next)); + } + + filter_samples(c, &samples[2*i], &xlow, &xhigh); + + for (j = 0; j < frontier && nodes[0][j]; j++) { + /* Only k >> 2 affects the future adaptive state, therefore testing + * small steps that don't change k >> 2 is useless, the original + * value from encode_low is better than them. Since we step k + * in steps of 4, make sure range is a multiple of 4, so that + * we don't miss the original value from encode_low. */ + int range = j < frontier/2 ? 4 : 0; + struct TrellisNode *cur_node = nodes[0][j]; + + int ilow = encode_low(&cur_node->state, xlow); + + for (k = ilow - range; k <= ilow + range && k <= 63; k += 4) { + int decoded, dec_diff, pos; + uint32_t ssd; + struct TrellisNode* node; + + if (k < 0) + continue; + + decoded = av_clip((cur_node->state.scale_factor * + ff_g722_low_inv_quant6[k] >> 10) + + cur_node->state.s_predictor, -16384, 16383); + dec_diff = xlow - decoded; + +#define STORE_NODE(index, UPDATE, VALUE)\ + ssd = cur_node->ssd + dec_diff*dec_diff;\ + /* Check for wraparound. Using 64 bit ssd counters would \ + * be simpler, but is slower on x86 32 bit. */\ + if (ssd < cur_node->ssd)\ + continue;\ + if (heap_pos[index] < frontier) {\ + pos = heap_pos[index]++;\ + av_assert2(pathn[index] < FREEZE_INTERVAL * frontier);\ + node = nodes_next[index][pos] = next[index]++;\ + node->path = pathn[index]++;\ + } else {\ + /* Try to replace one of the leaf nodes with the new \ + * one, but not always testing the same leaf position */\ + pos = (frontier>>1) + (heap_pos[index] & ((frontier>>1) - 1));\ + if (ssd >= nodes_next[index][pos]->ssd)\ + continue;\ + heap_pos[index]++;\ + node = nodes_next[index][pos];\ + }\ + node->ssd = ssd;\ + node->state = cur_node->state;\ + UPDATE;\ + c->paths[index][node->path].value = VALUE;\ + c->paths[index][node->path].prev = cur_node->path;\ + /* Sift the newly inserted node up in the heap to restore \ + * the heap property */\ + while (pos > 0) {\ + int parent = (pos - 1) >> 1;\ + if (nodes_next[index][parent]->ssd <= ssd)\ + break;\ + FFSWAP(struct TrellisNode*, nodes_next[index][parent],\ + nodes_next[index][pos]);\ + pos = parent;\ + } + STORE_NODE(0, ff_g722_update_low_predictor(&node->state, k >> 2), k); + } + } + + for (j = 0; j < frontier && nodes[1][j]; j++) { + int ihigh; + struct TrellisNode *cur_node = nodes[1][j]; + + /* We don't try to get any initial guess for ihigh via + * encode_high - since there's only 4 possible values, test + * them all. Testing all of these gives a much, much larger + * gain than testing a larger range around ilow. */ + for (ihigh = 0; ihigh < 4; ihigh++) { + int dhigh, decoded, dec_diff, pos; + uint32_t ssd; + struct TrellisNode* node; + + dhigh = cur_node->state.scale_factor * + ff_g722_high_inv_quant[ihigh] >> 10; + decoded = av_clip(dhigh + cur_node->state.s_predictor, + -16384, 16383); + dec_diff = xhigh - decoded; + + STORE_NODE(1, ff_g722_update_high_predictor(&node->state, dhigh, ihigh), ihigh); + } + } + + for (j = 0; j < 2; j++) { + FFSWAP(struct TrellisNode**, nodes[j], nodes_next[j]); + + if (nodes[j][0]->ssd > (1 << 16)) { + for (k = 1; k < frontier && nodes[j][k]; k++) + nodes[j][k]->ssd -= nodes[j][0]->ssd; + nodes[j][0]->ssd = 0; + } + } + + if (i == froze + FREEZE_INTERVAL) { + p[0] = &c->paths[0][nodes[0][0]->path]; + p[1] = &c->paths[1][nodes[1][0]->path]; + for (j = i; j > froze; j--) { + dst[j] = p[1]->value << 6 | p[0]->value; + p[0] = &c->paths[0][p[0]->prev]; + p[1] = &c->paths[1][p[1]->prev]; + } + froze = i; + pathn[0] = pathn[1] = 0; + memset(nodes[0] + 1, 0, (frontier - 1)*sizeof(**nodes)); + memset(nodes[1] + 1, 0, (frontier - 1)*sizeof(**nodes)); + } + } + + p[0] = &c->paths[0][nodes[0][0]->path]; + p[1] = &c->paths[1][nodes[1][0]->path]; + for (j = i; j > froze; j--) { + dst[j] = p[1]->value << 6 | p[0]->value; + p[0] = &c->paths[0][p[0]->prev]; + p[1] = &c->paths[1][p[1]->prev]; + } + c->band[0] = nodes[0][0]->state; + c->band[1] = nodes[1][0]->state; +} + +static av_always_inline void encode_byte(G722Context *c, uint8_t *dst, + const int16_t *samples) +{ + int xlow, xhigh, ilow, ihigh; + filter_samples(c, samples, &xlow, &xhigh); + ihigh = encode_high(&c->band[1], xhigh); + ilow = encode_low (&c->band[0], xlow); + ff_g722_update_high_predictor(&c->band[1], c->band[1].scale_factor * + ff_g722_high_inv_quant[ihigh] >> 10, ihigh); + ff_g722_update_low_predictor(&c->band[0], ilow >> 2); + *dst = ihigh << 6 | ilow; +} + +static void g722_encode_no_trellis(G722Context *c, + uint8_t *dst, int nb_samples, + const int16_t *samples) +{ + int i; + for (i = 0; i < nb_samples; i += 2) + encode_byte(c, dst++, &samples[i]); +} + +static int g722_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + G722Context *c = avctx->priv_data; + const int16_t *samples = (const int16_t *)frame->data[0]; + int nb_samples, out_size, ret; + + out_size = (frame->nb_samples + 1) / 2; + if ((ret = ff_alloc_packet2(avctx, avpkt, out_size)) < 0) + return ret; + + nb_samples = frame->nb_samples - (frame->nb_samples & 1); + + if (avctx->trellis) + g722_encode_trellis(c, avctx->trellis, avpkt->data, nb_samples, samples); + else + g722_encode_no_trellis(c, avpkt->data, nb_samples, samples); + + /* handle last frame with odd frame_size */ + if (nb_samples < frame->nb_samples) { + int16_t last_samples[2] = { samples[nb_samples], samples[nb_samples] }; + encode_byte(c, &avpkt->data[nb_samples >> 1], last_samples); + } + + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_adpcm_g722_encoder = { + .name = "g722", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_G722, + .priv_data_size = sizeof(G722Context), + .init = g722_encode_init, + .close = g722_encode_close, + .encode2 = g722_encode_frame, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/g723_1.c b/ffmpeg/libavcodec/g723_1.c new file mode 100644 index 0000000..6254c9a --- /dev/null +++ b/ffmpeg/libavcodec/g723_1.c @@ -0,0 +1,2478 @@ +/* + * G.723.1 compatible decoder + * Copyright (c) 2006 Benjamin Larsson + * Copyright (c) 2010 Mohamed Naufal Basheer + * + * 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 + */ + +/** + * @file + * G.723.1 compatible decoder + */ + +#define BITSTREAM_READER_LE +#include "libavutil/channel_layout.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "acelp_vectors.h" +#include "celp_filters.h" +#include "celp_math.h" +#include "g723_1_data.h" +#include "internal.h" + +#define CNG_RANDOM_SEED 12345 + +typedef struct g723_1_context { + AVClass *class; + + G723_1_Subframe subframe[4]; + enum FrameType cur_frame_type; + enum FrameType past_frame_type; + enum Rate cur_rate; + uint8_t lsp_index[LSP_BANDS]; + int pitch_lag[2]; + int erased_frames; + + int16_t prev_lsp[LPC_ORDER]; + int16_t sid_lsp[LPC_ORDER]; + int16_t prev_excitation[PITCH_MAX]; + int16_t excitation[PITCH_MAX + FRAME_LEN + 4]; + int16_t synth_mem[LPC_ORDER]; + int16_t fir_mem[LPC_ORDER]; + int iir_mem[LPC_ORDER]; + + int random_seed; + int cng_random_seed; + int interp_index; + int interp_gain; + int sid_gain; + int cur_gain; + int reflection_coef; + int pf_gain; ///< formant postfilter + ///< gain scaling unit memory + int postfilter; + + int16_t audio[FRAME_LEN + LPC_ORDER + PITCH_MAX + 4]; + int16_t prev_data[HALF_FRAME_LEN]; + int16_t prev_weight_sig[PITCH_MAX]; + + + int16_t hpf_fir_mem; ///< highpass filter fir + int hpf_iir_mem; ///< and iir memories + int16_t perf_fir_mem[LPC_ORDER]; ///< perceptual filter fir + int16_t perf_iir_mem[LPC_ORDER]; ///< and iir memories + + int16_t harmonic_mem[PITCH_MAX]; +} G723_1_Context; + +static av_cold int g723_1_decode_init(AVCodecContext *avctx) +{ + G723_1_Context *p = avctx->priv_data; + + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->channels = 1; + p->pf_gain = 1 << 12; + + memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); + memcpy(p->sid_lsp, dc_lsp, LPC_ORDER * sizeof(*p->sid_lsp)); + + p->cng_random_seed = CNG_RANDOM_SEED; + p->past_frame_type = SID_FRAME; + + return 0; +} + +/** + * Unpack the frame into parameters. + * + * @param p the context + * @param buf pointer to the input buffer + * @param buf_size size of the input buffer + */ +static int unpack_bitstream(G723_1_Context *p, const uint8_t *buf, + int buf_size) +{ + GetBitContext gb; + int ad_cb_len; + int temp, info_bits, i; + + init_get_bits(&gb, buf, buf_size * 8); + + /* Extract frame type and rate info */ + info_bits = get_bits(&gb, 2); + + if (info_bits == 3) { + p->cur_frame_type = UNTRANSMITTED_FRAME; + return 0; + } + + /* Extract 24 bit lsp indices, 8 bit for each band */ + p->lsp_index[2] = get_bits(&gb, 8); + p->lsp_index[1] = get_bits(&gb, 8); + p->lsp_index[0] = get_bits(&gb, 8); + + if (info_bits == 2) { + p->cur_frame_type = SID_FRAME; + p->subframe[0].amp_index = get_bits(&gb, 6); + return 0; + } + + /* Extract the info common to both rates */ + p->cur_rate = info_bits ? RATE_5300 : RATE_6300; + p->cur_frame_type = ACTIVE_FRAME; + + p->pitch_lag[0] = get_bits(&gb, 7); + if (p->pitch_lag[0] > 123) /* test if forbidden code */ + return -1; + p->pitch_lag[0] += PITCH_MIN; + p->subframe[1].ad_cb_lag = get_bits(&gb, 2); + + p->pitch_lag[1] = get_bits(&gb, 7); + if (p->pitch_lag[1] > 123) + return -1; + p->pitch_lag[1] += PITCH_MIN; + p->subframe[3].ad_cb_lag = get_bits(&gb, 2); + p->subframe[0].ad_cb_lag = 1; + p->subframe[2].ad_cb_lag = 1; + + for (i = 0; i < SUBFRAMES; i++) { + /* Extract combined gain */ + temp = get_bits(&gb, 12); + ad_cb_len = 170; + p->subframe[i].dirac_train = 0; + if (p->cur_rate == RATE_6300 && p->pitch_lag[i >> 1] < SUBFRAME_LEN - 2) { + p->subframe[i].dirac_train = temp >> 11; + temp &= 0x7FF; + ad_cb_len = 85; + } + p->subframe[i].ad_cb_gain = FASTDIV(temp, GAIN_LEVELS); + if (p->subframe[i].ad_cb_gain < ad_cb_len) { + p->subframe[i].amp_index = temp - p->subframe[i].ad_cb_gain * + GAIN_LEVELS; + } else { + return -1; + } + } + + p->subframe[0].grid_index = get_bits1(&gb); + p->subframe[1].grid_index = get_bits1(&gb); + p->subframe[2].grid_index = get_bits1(&gb); + p->subframe[3].grid_index = get_bits1(&gb); + + if (p->cur_rate == RATE_6300) { + skip_bits1(&gb); /* skip reserved bit */ + + /* Compute pulse_pos index using the 13-bit combined position index */ + temp = get_bits(&gb, 13); + p->subframe[0].pulse_pos = temp / 810; + + temp -= p->subframe[0].pulse_pos * 810; + p->subframe[1].pulse_pos = FASTDIV(temp, 90); + + temp -= p->subframe[1].pulse_pos * 90; + p->subframe[2].pulse_pos = FASTDIV(temp, 9); + p->subframe[3].pulse_pos = temp - p->subframe[2].pulse_pos * 9; + + p->subframe[0].pulse_pos = (p->subframe[0].pulse_pos << 16) + + get_bits(&gb, 16); + p->subframe[1].pulse_pos = (p->subframe[1].pulse_pos << 14) + + get_bits(&gb, 14); + p->subframe[2].pulse_pos = (p->subframe[2].pulse_pos << 16) + + get_bits(&gb, 16); + p->subframe[3].pulse_pos = (p->subframe[3].pulse_pos << 14) + + get_bits(&gb, 14); + + p->subframe[0].pulse_sign = get_bits(&gb, 6); + p->subframe[1].pulse_sign = get_bits(&gb, 5); + p->subframe[2].pulse_sign = get_bits(&gb, 6); + p->subframe[3].pulse_sign = get_bits(&gb, 5); + } else { /* 5300 bps */ + p->subframe[0].pulse_pos = get_bits(&gb, 12); + p->subframe[1].pulse_pos = get_bits(&gb, 12); + p->subframe[2].pulse_pos = get_bits(&gb, 12); + p->subframe[3].pulse_pos = get_bits(&gb, 12); + + p->subframe[0].pulse_sign = get_bits(&gb, 4); + p->subframe[1].pulse_sign = get_bits(&gb, 4); + p->subframe[2].pulse_sign = get_bits(&gb, 4); + p->subframe[3].pulse_sign = get_bits(&gb, 4); + } + + return 0; +} + +/** + * Bitexact implementation of sqrt(val/2). + */ +static int16_t square_root(unsigned val) +{ + av_assert2(!(val & 0x80000000)); + + return (ff_sqrt(val << 1) >> 1) & (~1); +} + +/** + * Calculate the number of left-shifts required for normalizing the input. + * + * @param num input number + * @param width width of the input, 15 or 31 bits + */ +static int normalize_bits(int num, int width) +{ + return width - av_log2(num) - 1; +} + +#define normalize_bits_int16(num) normalize_bits(num, 15) +#define normalize_bits_int32(num) normalize_bits(num, 31) + +/** + * Scale vector contents based on the largest of their absolutes. + */ +static int scale_vector(int16_t *dst, const int16_t *vector, int length) +{ + int bits, max = 0; + int i; + + for (i = 0; i < length; i++) + max |= FFABS(vector[i]); + + bits= 14 - av_log2_16bit(max); + bits= FFMAX(bits, 0); + + for (i = 0; i < length; i++) + dst[i] = vector[i] << bits >> 3; + + return bits - 3; +} + +/** + * Perform inverse quantization of LSP frequencies. + * + * @param cur_lsp the current LSP vector + * @param prev_lsp the previous LSP vector + * @param lsp_index VQ indices + * @param bad_frame bad frame flag + */ +static void inverse_quant(int16_t *cur_lsp, int16_t *prev_lsp, + uint8_t *lsp_index, int bad_frame) +{ + int min_dist, pred; + int i, j, temp, stable; + + /* Check for frame erasure */ + if (!bad_frame) { + min_dist = 0x100; + pred = 12288; + } else { + min_dist = 0x200; + pred = 23552; + lsp_index[0] = lsp_index[1] = lsp_index[2] = 0; + } + + /* Get the VQ table entry corresponding to the transmitted index */ + cur_lsp[0] = lsp_band0[lsp_index[0]][0]; + cur_lsp[1] = lsp_band0[lsp_index[0]][1]; + cur_lsp[2] = lsp_band0[lsp_index[0]][2]; + cur_lsp[3] = lsp_band1[lsp_index[1]][0]; + cur_lsp[4] = lsp_band1[lsp_index[1]][1]; + cur_lsp[5] = lsp_band1[lsp_index[1]][2]; + cur_lsp[6] = lsp_band2[lsp_index[2]][0]; + cur_lsp[7] = lsp_band2[lsp_index[2]][1]; + cur_lsp[8] = lsp_band2[lsp_index[2]][2]; + cur_lsp[9] = lsp_band2[lsp_index[2]][3]; + + /* Add predicted vector & DC component to the previously quantized vector */ + for (i = 0; i < LPC_ORDER; i++) { + temp = ((prev_lsp[i] - dc_lsp[i]) * pred + (1 << 14)) >> 15; + cur_lsp[i] += dc_lsp[i] + temp; + } + + for (i = 0; i < LPC_ORDER; i++) { + cur_lsp[0] = FFMAX(cur_lsp[0], 0x180); + cur_lsp[LPC_ORDER - 1] = FFMIN(cur_lsp[LPC_ORDER - 1], 0x7e00); + + /* Stability check */ + for (j = 1; j < LPC_ORDER; j++) { + temp = min_dist + cur_lsp[j - 1] - cur_lsp[j]; + if (temp > 0) { + temp >>= 1; + cur_lsp[j - 1] -= temp; + cur_lsp[j] += temp; + } + } + stable = 1; + for (j = 1; j < LPC_ORDER; j++) { + temp = cur_lsp[j - 1] + min_dist - cur_lsp[j] - 4; + if (temp > 0) { + stable = 0; + break; + } + } + if (stable) + break; + } + if (!stable) + memcpy(cur_lsp, prev_lsp, LPC_ORDER * sizeof(*cur_lsp)); +} + +/** + * Bitexact implementation of 2ab scaled by 1/2^16. + * + * @param a 32 bit multiplicand + * @param b 16 bit multiplier + */ +#define MULL2(a, b) \ + MULL(a,b,15) + +/** + * Convert LSP frequencies to LPC coefficients. + * + * @param lpc buffer for LPC coefficients + */ +static void lsp2lpc(int16_t *lpc) +{ + int f1[LPC_ORDER / 2 + 1]; + int f2[LPC_ORDER / 2 + 1]; + int i, j; + + /* Calculate negative cosine */ + for (j = 0; j < LPC_ORDER; j++) { + int index = (lpc[j] >> 7) & 0x1FF; + int offset = lpc[j] & 0x7f; + int temp1 = cos_tab[index] << 16; + int temp2 = (cos_tab[index + 1] - cos_tab[index]) * + ((offset << 8) + 0x80) << 1; + + lpc[j] = -(av_sat_dadd32(1 << 15, temp1 + temp2) >> 16); + } + + /* + * Compute sum and difference polynomial coefficients + * (bitexact alternative to lsp2poly() in lsp.c) + */ + /* Initialize with values in Q28 */ + f1[0] = 1 << 28; + f1[1] = (lpc[0] << 14) + (lpc[2] << 14); + f1[2] = lpc[0] * lpc[2] + (2 << 28); + + f2[0] = 1 << 28; + f2[1] = (lpc[1] << 14) + (lpc[3] << 14); + f2[2] = lpc[1] * lpc[3] + (2 << 28); + + /* + * Calculate and scale the coefficients by 1/2 in + * each iteration for a final scaling factor of Q25 + */ + for (i = 2; i < LPC_ORDER / 2; i++) { + f1[i + 1] = f1[i - 1] + MULL2(f1[i], lpc[2 * i]); + f2[i + 1] = f2[i - 1] + MULL2(f2[i], lpc[2 * i + 1]); + + for (j = i; j >= 2; j--) { + f1[j] = MULL2(f1[j - 1], lpc[2 * i]) + + (f1[j] >> 1) + (f1[j - 2] >> 1); + f2[j] = MULL2(f2[j - 1], lpc[2 * i + 1]) + + (f2[j] >> 1) + (f2[j - 2] >> 1); + } + + f1[0] >>= 1; + f2[0] >>= 1; + f1[1] = ((lpc[2 * i] << 16 >> i) + f1[1]) >> 1; + f2[1] = ((lpc[2 * i + 1] << 16 >> i) + f2[1]) >> 1; + } + + /* Convert polynomial coefficients to LPC coefficients */ + for (i = 0; i < LPC_ORDER / 2; i++) { + int64_t ff1 = f1[i + 1] + f1[i]; + int64_t ff2 = f2[i + 1] - f2[i]; + + lpc[i] = av_clipl_int32(((ff1 + ff2) << 3) + (1 << 15)) >> 16; + lpc[LPC_ORDER - i - 1] = av_clipl_int32(((ff1 - ff2) << 3) + + (1 << 15)) >> 16; + } +} + +/** + * Quantize LSP frequencies by interpolation and convert them to + * the corresponding LPC coefficients. + * + * @param lpc buffer for LPC coefficients + * @param cur_lsp the current LSP vector + * @param prev_lsp the previous LSP vector + */ +static void lsp_interpolate(int16_t *lpc, int16_t *cur_lsp, int16_t *prev_lsp) +{ + int i; + int16_t *lpc_ptr = lpc; + + /* cur_lsp * 0.25 + prev_lsp * 0.75 */ + ff_acelp_weighted_vector_sum(lpc, cur_lsp, prev_lsp, + 4096, 12288, 1 << 13, 14, LPC_ORDER); + ff_acelp_weighted_vector_sum(lpc + LPC_ORDER, cur_lsp, prev_lsp, + 8192, 8192, 1 << 13, 14, LPC_ORDER); + ff_acelp_weighted_vector_sum(lpc + 2 * LPC_ORDER, cur_lsp, prev_lsp, + 12288, 4096, 1 << 13, 14, LPC_ORDER); + memcpy(lpc + 3 * LPC_ORDER, cur_lsp, LPC_ORDER * sizeof(*lpc)); + + for (i = 0; i < SUBFRAMES; i++) { + lsp2lpc(lpc_ptr); + lpc_ptr += LPC_ORDER; + } +} + +/** + * Generate a train of dirac functions with period as pitch lag. + */ +static void gen_dirac_train(int16_t *buf, int pitch_lag) +{ + int16_t vector[SUBFRAME_LEN]; + int i, j; + + memcpy(vector, buf, SUBFRAME_LEN * sizeof(*vector)); + for (i = pitch_lag; i < SUBFRAME_LEN; i += pitch_lag) { + for (j = 0; j < SUBFRAME_LEN - i; j++) + buf[i + j] += vector[j]; + } +} + +/** + * Generate fixed codebook excitation vector. + * + * @param vector decoded excitation vector + * @param subfrm current subframe + * @param cur_rate current bitrate + * @param pitch_lag closed loop pitch lag + * @param index current subframe index + */ +static void gen_fcb_excitation(int16_t *vector, G723_1_Subframe *subfrm, + enum Rate cur_rate, int pitch_lag, int index) +{ + int temp, i, j; + + memset(vector, 0, SUBFRAME_LEN * sizeof(*vector)); + + if (cur_rate == RATE_6300) { + if (subfrm->pulse_pos >= max_pos[index]) + return; + + /* Decode amplitudes and positions */ + j = PULSE_MAX - pulses[index]; + temp = subfrm->pulse_pos; + for (i = 0; i < SUBFRAME_LEN / GRID_SIZE; i++) { + temp -= combinatorial_table[j][i]; + if (temp >= 0) + continue; + temp += combinatorial_table[j++][i]; + if (subfrm->pulse_sign & (1 << (PULSE_MAX - j))) { + vector[subfrm->grid_index + GRID_SIZE * i] = + -fixed_cb_gain[subfrm->amp_index]; + } else { + vector[subfrm->grid_index + GRID_SIZE * i] = + fixed_cb_gain[subfrm->amp_index]; + } + if (j == PULSE_MAX) + break; + } + if (subfrm->dirac_train == 1) + gen_dirac_train(vector, pitch_lag); + } else { /* 5300 bps */ + int cb_gain = fixed_cb_gain[subfrm->amp_index]; + int cb_shift = subfrm->grid_index; + int cb_sign = subfrm->pulse_sign; + int cb_pos = subfrm->pulse_pos; + int offset, beta, lag; + + for (i = 0; i < 8; i += 2) { + offset = ((cb_pos & 7) << 3) + cb_shift + i; + vector[offset] = (cb_sign & 1) ? cb_gain : -cb_gain; + cb_pos >>= 3; + cb_sign >>= 1; + } + + /* Enhance harmonic components */ + lag = pitch_contrib[subfrm->ad_cb_gain << 1] + pitch_lag + + subfrm->ad_cb_lag - 1; + beta = pitch_contrib[(subfrm->ad_cb_gain << 1) + 1]; + + if (lag < SUBFRAME_LEN - 2) { + for (i = lag; i < SUBFRAME_LEN; i++) + vector[i] += beta * vector[i - lag] >> 15; + } + } +} + +/** + * Get delayed contribution from the previous excitation vector. + */ +static void get_residual(int16_t *residual, int16_t *prev_excitation, int lag) +{ + int offset = PITCH_MAX - PITCH_ORDER / 2 - lag; + int i; + + residual[0] = prev_excitation[offset]; + residual[1] = prev_excitation[offset + 1]; + + offset += 2; + for (i = 2; i < SUBFRAME_LEN + PITCH_ORDER - 1; i++) + residual[i] = prev_excitation[offset + (i - 2) % lag]; +} + +static int dot_product(const int16_t *a, const int16_t *b, int length) +{ + int sum = ff_dot_product(a,b,length); + return av_sat_add32(sum, sum); +} + +/** + * Generate adaptive codebook excitation. + */ +static void gen_acb_excitation(int16_t *vector, int16_t *prev_excitation, + int pitch_lag, G723_1_Subframe *subfrm, + enum Rate cur_rate) +{ + int16_t residual[SUBFRAME_LEN + PITCH_ORDER - 1]; + const int16_t *cb_ptr; + int lag = pitch_lag + subfrm->ad_cb_lag - 1; + + int i; + int sum; + + get_residual(residual, prev_excitation, lag); + + /* Select quantization table */ + if (cur_rate == RATE_6300 && pitch_lag < SUBFRAME_LEN - 2) { + cb_ptr = adaptive_cb_gain85; + } else + cb_ptr = adaptive_cb_gain170; + + /* Calculate adaptive vector */ + cb_ptr += subfrm->ad_cb_gain * 20; + for (i = 0; i < SUBFRAME_LEN; i++) { + sum = ff_dot_product(residual + i, cb_ptr, PITCH_ORDER); + vector[i] = av_sat_dadd32(1 << 15, av_sat_add32(sum, sum)) >> 16; + } +} + +/** + * Estimate maximum auto-correlation around pitch lag. + * + * @param buf buffer with offset applied + * @param offset offset of the excitation vector + * @param ccr_max pointer to the maximum auto-correlation + * @param pitch_lag decoded pitch lag + * @param length length of autocorrelation + * @param dir forward lag(1) / backward lag(-1) + */ +static int autocorr_max(const int16_t *buf, int offset, int *ccr_max, + int pitch_lag, int length, int dir) +{ + int limit, ccr, lag = 0; + int i; + + pitch_lag = FFMIN(PITCH_MAX - 3, pitch_lag); + if (dir > 0) + limit = FFMIN(FRAME_LEN + PITCH_MAX - offset - length, pitch_lag + 3); + else + limit = pitch_lag + 3; + + for (i = pitch_lag - 3; i <= limit; i++) { + ccr = dot_product(buf, buf + dir * i, length); + + if (ccr > *ccr_max) { + *ccr_max = ccr; + lag = i; + } + } + return lag; +} + +/** + * Calculate pitch postfilter optimal and scaling gains. + * + * @param lag pitch postfilter forward/backward lag + * @param ppf pitch postfilter parameters + * @param cur_rate current bitrate + * @param tgt_eng target energy + * @param ccr cross-correlation + * @param res_eng residual energy + */ +static void comp_ppf_gains(int lag, PPFParam *ppf, enum Rate cur_rate, + int tgt_eng, int ccr, int res_eng) +{ + int pf_residual; /* square of postfiltered residual */ + int temp1, temp2; + + ppf->index = lag; + + temp1 = tgt_eng * res_eng >> 1; + temp2 = ccr * ccr << 1; + + if (temp2 > temp1) { + if (ccr >= res_eng) { + ppf->opt_gain = ppf_gain_weight[cur_rate]; + } else { + ppf->opt_gain = (ccr << 15) / res_eng * + ppf_gain_weight[cur_rate] >> 15; + } + /* pf_res^2 = tgt_eng + 2*ccr*gain + res_eng*gain^2 */ + temp1 = (tgt_eng << 15) + (ccr * ppf->opt_gain << 1); + temp2 = (ppf->opt_gain * ppf->opt_gain >> 15) * res_eng; + pf_residual = av_sat_add32(temp1, temp2 + (1 << 15)) >> 16; + + if (tgt_eng >= pf_residual << 1) { + temp1 = 0x7fff; + } else { + temp1 = (tgt_eng << 14) / pf_residual; + } + + /* scaling_gain = sqrt(tgt_eng/pf_res^2) */ + ppf->sc_gain = square_root(temp1 << 16); + } else { + ppf->opt_gain = 0; + ppf->sc_gain = 0x7fff; + } + + ppf->opt_gain = av_clip_int16(ppf->opt_gain * ppf->sc_gain >> 15); +} + +/** + * Calculate pitch postfilter parameters. + * + * @param p the context + * @param offset offset of the excitation vector + * @param pitch_lag decoded pitch lag + * @param ppf pitch postfilter parameters + * @param cur_rate current bitrate + */ +static void comp_ppf_coeff(G723_1_Context *p, int offset, int pitch_lag, + PPFParam *ppf, enum Rate cur_rate) +{ + + int16_t scale; + int i; + int temp1, temp2; + + /* + * 0 - target energy + * 1 - forward cross-correlation + * 2 - forward residual energy + * 3 - backward cross-correlation + * 4 - backward residual energy + */ + int energy[5] = {0, 0, 0, 0, 0}; + int16_t *buf = p->audio + LPC_ORDER + offset; + int fwd_lag = autocorr_max(buf, offset, &energy[1], pitch_lag, + SUBFRAME_LEN, 1); + int back_lag = autocorr_max(buf, offset, &energy[3], pitch_lag, + SUBFRAME_LEN, -1); + + ppf->index = 0; + ppf->opt_gain = 0; + ppf->sc_gain = 0x7fff; + + /* Case 0, Section 3.6 */ + if (!back_lag && !fwd_lag) + return; + + /* Compute target energy */ + energy[0] = dot_product(buf, buf, SUBFRAME_LEN); + + /* Compute forward residual energy */ + if (fwd_lag) + energy[2] = dot_product(buf + fwd_lag, buf + fwd_lag, SUBFRAME_LEN); + + /* Compute backward residual energy */ + if (back_lag) + energy[4] = dot_product(buf - back_lag, buf - back_lag, SUBFRAME_LEN); + + /* Normalize and shorten */ + temp1 = 0; + for (i = 0; i < 5; i++) + temp1 = FFMAX(energy[i], temp1); + + scale = normalize_bits(temp1, 31); + for (i = 0; i < 5; i++) + energy[i] = (energy[i] << scale) >> 16; + + if (fwd_lag && !back_lag) { /* Case 1 */ + comp_ppf_gains(fwd_lag, ppf, cur_rate, energy[0], energy[1], + energy[2]); + } else if (!fwd_lag) { /* Case 2 */ + comp_ppf_gains(-back_lag, ppf, cur_rate, energy[0], energy[3], + energy[4]); + } else { /* Case 3 */ + + /* + * Select the largest of energy[1]^2/energy[2] + * and energy[3]^2/energy[4] + */ + temp1 = energy[4] * ((energy[1] * energy[1] + (1 << 14)) >> 15); + temp2 = energy[2] * ((energy[3] * energy[3] + (1 << 14)) >> 15); + if (temp1 >= temp2) { + comp_ppf_gains(fwd_lag, ppf, cur_rate, energy[0], energy[1], + energy[2]); + } else { + comp_ppf_gains(-back_lag, ppf, cur_rate, energy[0], energy[3], + energy[4]); + } + } +} + +/** + * Classify frames as voiced/unvoiced. + * + * @param p the context + * @param pitch_lag decoded pitch_lag + * @param exc_eng excitation energy estimation + * @param scale scaling factor of exc_eng + * + * @return residual interpolation index if voiced, 0 otherwise + */ +static int comp_interp_index(G723_1_Context *p, int pitch_lag, + int *exc_eng, int *scale) +{ + int offset = PITCH_MAX + 2 * SUBFRAME_LEN; + int16_t *buf = p->audio + LPC_ORDER; + + int index, ccr, tgt_eng, best_eng, temp; + + *scale = scale_vector(buf, p->excitation, FRAME_LEN + PITCH_MAX); + buf += offset; + + /* Compute maximum backward cross-correlation */ + ccr = 0; + index = autocorr_max(buf, offset, &ccr, pitch_lag, SUBFRAME_LEN * 2, -1); + ccr = av_sat_add32(ccr, 1 << 15) >> 16; + + /* Compute target energy */ + tgt_eng = dot_product(buf, buf, SUBFRAME_LEN * 2); + *exc_eng = av_sat_add32(tgt_eng, 1 << 15) >> 16; + + if (ccr <= 0) + return 0; + + /* Compute best energy */ + best_eng = dot_product(buf - index, buf - index, SUBFRAME_LEN * 2); + best_eng = av_sat_add32(best_eng, 1 << 15) >> 16; + + temp = best_eng * *exc_eng >> 3; + + if (temp < ccr * ccr) { + return index; + } else + return 0; +} + +/** + * Peform residual interpolation based on frame classification. + * + * @param buf decoded excitation vector + * @param out output vector + * @param lag decoded pitch lag + * @param gain interpolated gain + * @param rseed seed for random number generator + */ +static void residual_interp(int16_t *buf, int16_t *out, int lag, + int gain, int *rseed) +{ + int i; + if (lag) { /* Voiced */ + int16_t *vector_ptr = buf + PITCH_MAX; + /* Attenuate */ + for (i = 0; i < lag; i++) + out[i] = vector_ptr[i - lag] * 3 >> 2; + av_memcpy_backptr((uint8_t*)(out + lag), lag * sizeof(*out), + (FRAME_LEN - lag) * sizeof(*out)); + } else { /* Unvoiced */ + for (i = 0; i < FRAME_LEN; i++) { + *rseed = *rseed * 521 + 259; + out[i] = gain * *rseed >> 15; + } + memset(buf, 0, (FRAME_LEN + PITCH_MAX) * sizeof(*buf)); + } +} + +/** + * Perform IIR filtering. + * + * @param fir_coef FIR coefficients + * @param iir_coef IIR coefficients + * @param src source vector + * @param dest destination vector + * @param width width of the output, 16 bits(0) / 32 bits(1) + */ +#define iir_filter(fir_coef, iir_coef, src, dest, width)\ +{\ + int m, n;\ + int res_shift = 16 & ~-(width);\ + int in_shift = 16 - res_shift;\ +\ + for (m = 0; m < SUBFRAME_LEN; m++) {\ + int64_t filter = 0;\ + for (n = 1; n <= LPC_ORDER; n++) {\ + filter -= (fir_coef)[n - 1] * (src)[m - n] -\ + (iir_coef)[n - 1] * ((dest)[m - n] >> in_shift);\ + }\ +\ + (dest)[m] = av_clipl_int32(((src)[m] << 16) + (filter << 3) +\ + (1 << 15)) >> res_shift;\ + }\ +} + +/** + * Adjust gain of postfiltered signal. + * + * @param p the context + * @param buf postfiltered output vector + * @param energy input energy coefficient + */ +static void gain_scale(G723_1_Context *p, int16_t * buf, int energy) +{ + int num, denom, gain, bits1, bits2; + int i; + + num = energy; + denom = 0; + for (i = 0; i < SUBFRAME_LEN; i++) { + int temp = buf[i] >> 2; + temp *= temp; + denom = av_sat_dadd32(denom, temp); + } + + if (num && denom) { + bits1 = normalize_bits(num, 31); + bits2 = normalize_bits(denom, 31); + num = num << bits1 >> 1; + denom <<= bits2; + + bits2 = 5 + bits1 - bits2; + bits2 = FFMAX(0, bits2); + + gain = (num >> 1) / (denom >> 16); + gain = square_root(gain << 16 >> bits2); + } else { + gain = 1 << 12; + } + + for (i = 0; i < SUBFRAME_LEN; i++) { + p->pf_gain = (15 * p->pf_gain + gain + (1 << 3)) >> 4; + buf[i] = av_clip_int16((buf[i] * (p->pf_gain + (p->pf_gain >> 4)) + + (1 << 10)) >> 11); + } +} + +/** + * Perform formant filtering. + * + * @param p the context + * @param lpc quantized lpc coefficients + * @param buf input buffer + * @param dst output buffer + */ +static void formant_postfilter(G723_1_Context *p, int16_t *lpc, + int16_t *buf, int16_t *dst) +{ + int16_t filter_coef[2][LPC_ORDER]; + int filter_signal[LPC_ORDER + FRAME_LEN], *signal_ptr; + int i, j, k; + + memcpy(buf, p->fir_mem, LPC_ORDER * sizeof(*buf)); + memcpy(filter_signal, p->iir_mem, LPC_ORDER * sizeof(*filter_signal)); + + for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { + for (k = 0; k < LPC_ORDER; k++) { + filter_coef[0][k] = (-lpc[k] * postfilter_tbl[0][k] + + (1 << 14)) >> 15; + filter_coef[1][k] = (-lpc[k] * postfilter_tbl[1][k] + + (1 << 14)) >> 15; + } + iir_filter(filter_coef[0], filter_coef[1], buf + i, + filter_signal + i, 1); + lpc += LPC_ORDER; + } + + memcpy(p->fir_mem, buf + FRAME_LEN, LPC_ORDER * sizeof(int16_t)); + memcpy(p->iir_mem, filter_signal + FRAME_LEN, LPC_ORDER * sizeof(int)); + + buf += LPC_ORDER; + signal_ptr = filter_signal + LPC_ORDER; + for (i = 0; i < SUBFRAMES; i++) { + int temp; + int auto_corr[2]; + int scale, energy; + + /* Normalize */ + scale = scale_vector(dst, buf, SUBFRAME_LEN); + + /* Compute auto correlation coefficients */ + auto_corr[0] = dot_product(dst, dst + 1, SUBFRAME_LEN - 1); + auto_corr[1] = dot_product(dst, dst, SUBFRAME_LEN); + + /* Compute reflection coefficient */ + temp = auto_corr[1] >> 16; + if (temp) { + temp = (auto_corr[0] >> 2) / temp; + } + p->reflection_coef = (3 * p->reflection_coef + temp + 2) >> 2; + temp = -p->reflection_coef >> 1 & ~3; + + /* Compensation filter */ + for (j = 0; j < SUBFRAME_LEN; j++) { + dst[j] = av_sat_dadd32(signal_ptr[j], + (signal_ptr[j - 1] >> 16) * temp) >> 16; + } + + /* Compute normalized signal energy */ + temp = 2 * scale + 4; + if (temp < 0) { + energy = av_clipl_int32((int64_t)auto_corr[1] << -temp); + } else + energy = auto_corr[1] >> temp; + + gain_scale(p, dst, energy); + + buf += SUBFRAME_LEN; + signal_ptr += SUBFRAME_LEN; + dst += SUBFRAME_LEN; + } +} + +static int sid_gain_to_lsp_index(int gain) +{ + if (gain < 0x10) + return gain << 6; + else if (gain < 0x20) + return gain - 8 << 7; + else + return gain - 20 << 8; +} + +static inline int cng_rand(int *state, int base) +{ + *state = (*state * 521 + 259) & 0xFFFF; + return (*state & 0x7FFF) * base >> 15; +} + +static int estimate_sid_gain(G723_1_Context *p) +{ + int i, shift, seg, seg2, t, val, val_add, x, y; + + shift = 16 - p->cur_gain * 2; + if (shift > 0) + t = p->sid_gain << shift; + else + t = p->sid_gain >> -shift; + x = t * cng_filt[0] >> 16; + + if (x >= cng_bseg[2]) + return 0x3F; + + if (x >= cng_bseg[1]) { + shift = 4; + seg = 3; + } else { + shift = 3; + seg = (x >= cng_bseg[0]); + } + seg2 = FFMIN(seg, 3); + + val = 1 << shift; + val_add = val >> 1; + for (i = 0; i < shift; i++) { + t = seg * 32 + (val << seg2); + t *= t; + if (x >= t) + val += val_add; + else + val -= val_add; + val_add >>= 1; + } + + t = seg * 32 + (val << seg2); + y = t * t - x; + if (y <= 0) { + t = seg * 32 + (val + 1 << seg2); + t = t * t - x; + val = (seg2 - 1 << 4) + val; + if (t >= y) + val++; + } else { + t = seg * 32 + (val - 1 << seg2); + t = t * t - x; + val = (seg2 - 1 << 4) + val; + if (t >= y) + val--; + } + + return val; +} + +static void generate_noise(G723_1_Context *p) +{ + int i, j, idx, t; + int off[SUBFRAMES]; + int signs[SUBFRAMES / 2 * 11], pos[SUBFRAMES / 2 * 11]; + int tmp[SUBFRAME_LEN * 2]; + int16_t *vector_ptr; + int64_t sum; + int b0, c, delta, x, shift; + + p->pitch_lag[0] = cng_rand(&p->cng_random_seed, 21) + 123; + p->pitch_lag[1] = cng_rand(&p->cng_random_seed, 19) + 123; + + for (i = 0; i < SUBFRAMES; i++) { + p->subframe[i].ad_cb_gain = cng_rand(&p->cng_random_seed, 50) + 1; + p->subframe[i].ad_cb_lag = cng_adaptive_cb_lag[i]; + } + + for (i = 0; i < SUBFRAMES / 2; i++) { + t = cng_rand(&p->cng_random_seed, 1 << 13); + off[i * 2] = t & 1; + off[i * 2 + 1] = ((t >> 1) & 1) + SUBFRAME_LEN; + t >>= 2; + for (j = 0; j < 11; j++) { + signs[i * 11 + j] = (t & 1) * 2 - 1 << 14; + t >>= 1; + } + } + + idx = 0; + for (i = 0; i < SUBFRAMES; i++) { + for (j = 0; j < SUBFRAME_LEN / 2; j++) + tmp[j] = j; + t = SUBFRAME_LEN / 2; + for (j = 0; j < pulses[i]; j++, idx++) { + int idx2 = cng_rand(&p->cng_random_seed, t); + + pos[idx] = tmp[idx2] * 2 + off[i]; + tmp[idx2] = tmp[--t]; + } + } + + vector_ptr = p->audio + LPC_ORDER; + memcpy(vector_ptr, p->prev_excitation, + PITCH_MAX * sizeof(*p->excitation)); + for (i = 0; i < SUBFRAMES; i += 2) { + gen_acb_excitation(vector_ptr, vector_ptr, + p->pitch_lag[i >> 1], &p->subframe[i], + p->cur_rate); + gen_acb_excitation(vector_ptr + SUBFRAME_LEN, + vector_ptr + SUBFRAME_LEN, + p->pitch_lag[i >> 1], &p->subframe[i + 1], + p->cur_rate); + + t = 0; + for (j = 0; j < SUBFRAME_LEN * 2; j++) + t |= FFABS(vector_ptr[j]); + t = FFMIN(t, 0x7FFF); + if (!t) { + shift = 0; + } else { + shift = -10 + av_log2(t); + if (shift < -2) + shift = -2; + } + sum = 0; + if (shift < 0) { + for (j = 0; j < SUBFRAME_LEN * 2; j++) { + t = vector_ptr[j] << -shift; + sum += t * t; + tmp[j] = t; + } + } else { + for (j = 0; j < SUBFRAME_LEN * 2; j++) { + t = vector_ptr[j] >> shift; + sum += t * t; + tmp[j] = t; + } + } + + b0 = 0; + for (j = 0; j < 11; j++) + b0 += tmp[pos[(i / 2) * 11 + j]] * signs[(i / 2) * 11 + j]; + b0 = b0 * 2 * 2979LL + (1 << 29) >> 30; // approximated division by 11 + + c = p->cur_gain * (p->cur_gain * SUBFRAME_LEN >> 5); + if (shift * 2 + 3 >= 0) + c >>= shift * 2 + 3; + else + c <<= -(shift * 2 + 3); + c = (av_clipl_int32(sum << 1) - c) * 2979LL >> 15; + + delta = b0 * b0 * 2 - c; + if (delta <= 0) { + x = -b0; + } else { + delta = square_root(delta); + x = delta - b0; + t = delta + b0; + if (FFABS(t) < FFABS(x)) + x = -t; + } + shift++; + if (shift < 0) + x >>= -shift; + else + x <<= shift; + x = av_clip(x, -10000, 10000); + + for (j = 0; j < 11; j++) { + idx = (i / 2) * 11 + j; + vector_ptr[pos[idx]] = av_clip_int16(vector_ptr[pos[idx]] + + (x * signs[idx] >> 15)); + } + + /* copy decoded data to serve as a history for the next decoded subframes */ + memcpy(vector_ptr + PITCH_MAX, vector_ptr, + sizeof(*vector_ptr) * SUBFRAME_LEN * 2); + vector_ptr += SUBFRAME_LEN * 2; + } + /* Save the excitation for the next frame */ + memcpy(p->prev_excitation, p->audio + LPC_ORDER + FRAME_LEN, + PITCH_MAX * sizeof(*p->excitation)); +} + +static int g723_1_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + G723_1_Context *p = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int dec_mode = buf[0] & 3; + + PPFParam ppf[SUBFRAMES]; + int16_t cur_lsp[LPC_ORDER]; + int16_t lpc[SUBFRAMES * LPC_ORDER]; + int16_t acb_vector[SUBFRAME_LEN]; + int16_t *out; + int bad_frame = 0, i, j, ret; + int16_t *audio = p->audio; + + if (buf_size < frame_size[dec_mode]) { + if (buf_size) + av_log(avctx, AV_LOG_WARNING, + "Expected %d bytes, got %d - skipping packet\n", + frame_size[dec_mode], buf_size); + *got_frame_ptr = 0; + return buf_size; + } + + if (unpack_bitstream(p, buf, buf_size) < 0) { + bad_frame = 1; + if (p->past_frame_type == ACTIVE_FRAME) + p->cur_frame_type = ACTIVE_FRAME; + else + p->cur_frame_type = UNTRANSMITTED_FRAME; + } + + frame->nb_samples = FRAME_LEN; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + out = (int16_t *)frame->data[0]; + + if (p->cur_frame_type == ACTIVE_FRAME) { + if (!bad_frame) + p->erased_frames = 0; + else if (p->erased_frames != 3) + p->erased_frames++; + + inverse_quant(cur_lsp, p->prev_lsp, p->lsp_index, bad_frame); + lsp_interpolate(lpc, cur_lsp, p->prev_lsp); + + /* Save the lsp_vector for the next frame */ + memcpy(p->prev_lsp, cur_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); + + /* Generate the excitation for the frame */ + memcpy(p->excitation, p->prev_excitation, + PITCH_MAX * sizeof(*p->excitation)); + if (!p->erased_frames) { + int16_t *vector_ptr = p->excitation + PITCH_MAX; + + /* Update interpolation gain memory */ + p->interp_gain = fixed_cb_gain[(p->subframe[2].amp_index + + p->subframe[3].amp_index) >> 1]; + for (i = 0; i < SUBFRAMES; i++) { + gen_fcb_excitation(vector_ptr, &p->subframe[i], p->cur_rate, + p->pitch_lag[i >> 1], i); + gen_acb_excitation(acb_vector, &p->excitation[SUBFRAME_LEN * i], + p->pitch_lag[i >> 1], &p->subframe[i], + p->cur_rate); + /* Get the total excitation */ + for (j = 0; j < SUBFRAME_LEN; j++) { + int v = av_clip_int16(vector_ptr[j] << 1); + vector_ptr[j] = av_clip_int16(v + acb_vector[j]); + } + vector_ptr += SUBFRAME_LEN; + } + + vector_ptr = p->excitation + PITCH_MAX; + + p->interp_index = comp_interp_index(p, p->pitch_lag[1], + &p->sid_gain, &p->cur_gain); + + /* Peform pitch postfiltering */ + if (p->postfilter) { + i = PITCH_MAX; + for (j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + comp_ppf_coeff(p, i, p->pitch_lag[j >> 1], + ppf + j, p->cur_rate); + + for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + ff_acelp_weighted_vector_sum(p->audio + LPC_ORDER + i, + vector_ptr + i, + vector_ptr + i + ppf[j].index, + ppf[j].sc_gain, + ppf[j].opt_gain, + 1 << 14, 15, SUBFRAME_LEN); + } else { + audio = vector_ptr - LPC_ORDER; + } + + /* Save the excitation for the next frame */ + memcpy(p->prev_excitation, p->excitation + FRAME_LEN, + PITCH_MAX * sizeof(*p->excitation)); + } else { + p->interp_gain = (p->interp_gain * 3 + 2) >> 2; + if (p->erased_frames == 3) { + /* Mute output */ + memset(p->excitation, 0, + (FRAME_LEN + PITCH_MAX) * sizeof(*p->excitation)); + memset(p->prev_excitation, 0, + PITCH_MAX * sizeof(*p->excitation)); + memset(frame->data[0], 0, + (FRAME_LEN + LPC_ORDER) * sizeof(int16_t)); + } else { + int16_t *buf = p->audio + LPC_ORDER; + + /* Regenerate frame */ + residual_interp(p->excitation, buf, p->interp_index, + p->interp_gain, &p->random_seed); + + /* Save the excitation for the next frame */ + memcpy(p->prev_excitation, buf + (FRAME_LEN - PITCH_MAX), + PITCH_MAX * sizeof(*p->excitation)); + } + } + p->cng_random_seed = CNG_RANDOM_SEED; + } else { + if (p->cur_frame_type == SID_FRAME) { + p->sid_gain = sid_gain_to_lsp_index(p->subframe[0].amp_index); + inverse_quant(p->sid_lsp, p->prev_lsp, p->lsp_index, 0); + } else if (p->past_frame_type == ACTIVE_FRAME) { + p->sid_gain = estimate_sid_gain(p); + } + + if (p->past_frame_type == ACTIVE_FRAME) + p->cur_gain = p->sid_gain; + else + p->cur_gain = (p->cur_gain * 7 + p->sid_gain) >> 3; + generate_noise(p); + lsp_interpolate(lpc, p->sid_lsp, p->prev_lsp); + /* Save the lsp_vector for the next frame */ + memcpy(p->prev_lsp, p->sid_lsp, LPC_ORDER * sizeof(*p->prev_lsp)); + } + + p->past_frame_type = p->cur_frame_type; + + memcpy(p->audio, p->synth_mem, LPC_ORDER * sizeof(*p->audio)); + for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + ff_celp_lp_synthesis_filter(p->audio + i, &lpc[j * LPC_ORDER], + audio + i, SUBFRAME_LEN, LPC_ORDER, + 0, 1, 1 << 12); + memcpy(p->synth_mem, p->audio + FRAME_LEN, LPC_ORDER * sizeof(*p->audio)); + + if (p->postfilter) { + formant_postfilter(p, lpc, p->audio, out); + } else { // if output is not postfiltered it should be scaled by 2 + for (i = 0; i < FRAME_LEN; i++) + out[i] = av_clip_int16(p->audio[LPC_ORDER + i] << 1); + } + + *got_frame_ptr = 1; + + return frame_size[dec_mode]; +} + +#define OFFSET(x) offsetof(G723_1_Context, x) +#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +static const AVOption options[] = { + { "postfilter", "postfilter on/off", OFFSET(postfilter), AV_OPT_TYPE_INT, + { .i64 = 1 }, 0, 1, AD }, + { NULL } +}; + + +static const AVClass g723_1dec_class = { + .class_name = "G.723.1 decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_g723_1_decoder = { + .name = "g723_1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_G723_1, + .priv_data_size = sizeof(G723_1_Context), + .init = g723_1_decode_init, + .decode = g723_1_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .priv_class = &g723_1dec_class, +}; + +#if CONFIG_G723_1_ENCODER +#define BITSTREAM_WRITER_LE +#include "put_bits.h" + +static av_cold int g723_1_encode_init(AVCodecContext *avctx) +{ + G723_1_Context *p = avctx->priv_data; + + if (avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n"); + return -1; + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(EINVAL); + } + + if (avctx->bit_rate == 6300) { + p->cur_rate = RATE_6300; + } else if (avctx->bit_rate == 5300) { + av_log(avctx, AV_LOG_ERROR, "Bitrate not supported yet, use 6.3k\n"); + return AVERROR_PATCHWELCOME; + } else { + av_log(avctx, AV_LOG_ERROR, + "Bitrate not supported, use 6.3k\n"); + return AVERROR(EINVAL); + } + avctx->frame_size = 240; + memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(int16_t)); + + return 0; +} + +/** + * Remove DC component from the input signal. + * + * @param buf input signal + * @param fir zero memory + * @param iir pole memory + */ +static void highpass_filter(int16_t *buf, int16_t *fir, int *iir) +{ + int i; + for (i = 0; i < FRAME_LEN; i++) { + *iir = (buf[i] << 15) + ((-*fir) << 15) + MULL2(*iir, 0x7f00); + *fir = buf[i]; + buf[i] = av_clipl_int32((int64_t)*iir + (1 << 15)) >> 16; + } +} + +/** + * Estimate autocorrelation of the input vector. + * + * @param buf input buffer + * @param autocorr autocorrelation coefficients vector + */ +static void comp_autocorr(int16_t *buf, int16_t *autocorr) +{ + int i, scale, temp; + int16_t vector[LPC_FRAME]; + + scale_vector(vector, buf, LPC_FRAME); + + /* Apply the Hamming window */ + for (i = 0; i < LPC_FRAME; i++) + vector[i] = (vector[i] * hamming_window[i] + (1 << 14)) >> 15; + + /* Compute the first autocorrelation coefficient */ + temp = ff_dot_product(vector, vector, LPC_FRAME); + + /* Apply a white noise correlation factor of (1025/1024) */ + temp += temp >> 10; + + /* Normalize */ + scale = normalize_bits_int32(temp); + autocorr[0] = av_clipl_int32((int64_t)(temp << scale) + + (1 << 15)) >> 16; + + /* Compute the remaining coefficients */ + if (!autocorr[0]) { + memset(autocorr + 1, 0, LPC_ORDER * sizeof(int16_t)); + } else { + for (i = 1; i <= LPC_ORDER; i++) { + temp = ff_dot_product(vector, vector + i, LPC_FRAME - i); + temp = MULL2((temp << scale), binomial_window[i - 1]); + autocorr[i] = av_clipl_int32((int64_t)temp + (1 << 15)) >> 16; + } + } +} + +/** + * Use Levinson-Durbin recursion to compute LPC coefficients from + * autocorrelation values. + * + * @param lpc LPC coefficients vector + * @param autocorr autocorrelation coefficients vector + * @param error prediction error + */ +static void levinson_durbin(int16_t *lpc, int16_t *autocorr, int16_t error) +{ + int16_t vector[LPC_ORDER]; + int16_t partial_corr; + int i, j, temp; + + memset(lpc, 0, LPC_ORDER * sizeof(int16_t)); + + for (i = 0; i < LPC_ORDER; i++) { + /* Compute the partial correlation coefficient */ + temp = 0; + for (j = 0; j < i; j++) + temp -= lpc[j] * autocorr[i - j - 1]; + temp = ((autocorr[i] << 13) + temp) << 3; + + if (FFABS(temp) >= (error << 16)) + break; + + partial_corr = temp / (error << 1); + + lpc[i] = av_clipl_int32((int64_t)(partial_corr << 14) + + (1 << 15)) >> 16; + + /* Update the prediction error */ + temp = MULL2(temp, partial_corr); + error = av_clipl_int32((int64_t)(error << 16) - temp + + (1 << 15)) >> 16; + + memcpy(vector, lpc, i * sizeof(int16_t)); + for (j = 0; j < i; j++) { + temp = partial_corr * vector[i - j - 1] << 1; + lpc[j] = av_clipl_int32((int64_t)(lpc[j] << 16) - temp + + (1 << 15)) >> 16; + } + } +} + +/** + * Calculate LPC coefficients for the current frame. + * + * @param buf current frame + * @param prev_data 2 trailing subframes of the previous frame + * @param lpc LPC coefficients vector + */ +static void comp_lpc_coeff(int16_t *buf, int16_t *lpc) +{ + int16_t autocorr[(LPC_ORDER + 1) * SUBFRAMES]; + int16_t *autocorr_ptr = autocorr; + int16_t *lpc_ptr = lpc; + int i, j; + + for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { + comp_autocorr(buf + i, autocorr_ptr); + levinson_durbin(lpc_ptr, autocorr_ptr + 1, autocorr_ptr[0]); + + lpc_ptr += LPC_ORDER; + autocorr_ptr += LPC_ORDER + 1; + } +} + +static void lpc2lsp(int16_t *lpc, int16_t *prev_lsp, int16_t *lsp) +{ + int f[LPC_ORDER + 2]; ///< coefficients of the sum and difference + ///< polynomials (F1, F2) ordered as + ///< f1[0], f2[0], ...., f1[5], f2[5] + + int max, shift, cur_val, prev_val, count, p; + int i, j; + int64_t temp; + + /* Initialize f1[0] and f2[0] to 1 in Q25 */ + for (i = 0; i < LPC_ORDER; i++) + lsp[i] = (lpc[i] * bandwidth_expand[i] + (1 << 14)) >> 15; + + /* Apply bandwidth expansion on the LPC coefficients */ + f[0] = f[1] = 1 << 25; + + /* Compute the remaining coefficients */ + for (i = 0; i < LPC_ORDER / 2; i++) { + /* f1 */ + f[2 * i + 2] = -f[2 * i] - ((lsp[i] + lsp[LPC_ORDER - 1 - i]) << 12); + /* f2 */ + f[2 * i + 3] = f[2 * i + 1] - ((lsp[i] - lsp[LPC_ORDER - 1 - i]) << 12); + } + + /* Divide f1[5] and f2[5] by 2 for use in polynomial evaluation */ + f[LPC_ORDER] >>= 1; + f[LPC_ORDER + 1] >>= 1; + + /* Normalize and shorten */ + max = FFABS(f[0]); + for (i = 1; i < LPC_ORDER + 2; i++) + max = FFMAX(max, FFABS(f[i])); + + shift = normalize_bits_int32(max); + + for (i = 0; i < LPC_ORDER + 2; i++) + f[i] = av_clipl_int32((int64_t)(f[i] << shift) + (1 << 15)) >> 16; + + /** + * Evaluate F1 and F2 at uniform intervals of pi/256 along the + * unit circle and check for zero crossings. + */ + p = 0; + temp = 0; + for (i = 0; i <= LPC_ORDER / 2; i++) + temp += f[2 * i] * cos_tab[0]; + prev_val = av_clipl_int32(temp << 1); + count = 0; + for ( i = 1; i < COS_TBL_SIZE / 2; i++) { + /* Evaluate */ + temp = 0; + for (j = 0; j <= LPC_ORDER / 2; j++) + temp += f[LPC_ORDER - 2 * j + p] * cos_tab[i * j % COS_TBL_SIZE]; + cur_val = av_clipl_int32(temp << 1); + + /* Check for sign change, indicating a zero crossing */ + if ((cur_val ^ prev_val) < 0) { + int abs_cur = FFABS(cur_val); + int abs_prev = FFABS(prev_val); + int sum = abs_cur + abs_prev; + + shift = normalize_bits_int32(sum); + sum <<= shift; + abs_prev = abs_prev << shift >> 8; + lsp[count++] = ((i - 1) << 7) + (abs_prev >> 1) / (sum >> 16); + + if (count == LPC_ORDER) + break; + + /* Switch between sum and difference polynomials */ + p ^= 1; + + /* Evaluate */ + temp = 0; + for (j = 0; j <= LPC_ORDER / 2; j++){ + temp += f[LPC_ORDER - 2 * j + p] * + cos_tab[i * j % COS_TBL_SIZE]; + } + cur_val = av_clipl_int32(temp<<1); + } + prev_val = cur_val; + } + + if (count != LPC_ORDER) + memcpy(lsp, prev_lsp, LPC_ORDER * sizeof(int16_t)); +} + +/** + * Quantize the current LSP subvector. + * + * @param num band number + * @param offset offset of the current subvector in an LPC_ORDER vector + * @param size size of the current subvector + */ +#define get_index(num, offset, size) \ +{\ + int error, max = -1;\ + int16_t temp[4];\ + int i, j;\ + for (i = 0; i < LSP_CB_SIZE; i++) {\ + for (j = 0; j < size; j++){\ + temp[j] = (weight[j + (offset)] * lsp_band##num[i][j] +\ + (1 << 14)) >> 15;\ + }\ + error = dot_product(lsp + (offset), temp, size) << 1;\ + error -= dot_product(lsp_band##num[i], temp, size);\ + if (error > max) {\ + max = error;\ + lsp_index[num] = i;\ + }\ + }\ +} + +/** + * Vector quantize the LSP frequencies. + * + * @param lsp the current lsp vector + * @param prev_lsp the previous lsp vector + */ +static void lsp_quantize(uint8_t *lsp_index, int16_t *lsp, int16_t *prev_lsp) +{ + int16_t weight[LPC_ORDER]; + int16_t min, max; + int shift, i; + + /* Calculate the VQ weighting vector */ + weight[0] = (1 << 20) / (lsp[1] - lsp[0]); + weight[LPC_ORDER - 1] = (1 << 20) / + (lsp[LPC_ORDER - 1] - lsp[LPC_ORDER - 2]); + + for (i = 1; i < LPC_ORDER - 1; i++) { + min = FFMIN(lsp[i] - lsp[i - 1], lsp[i + 1] - lsp[i]); + if (min > 0x20) + weight[i] = (1 << 20) / min; + else + weight[i] = INT16_MAX; + } + + /* Normalize */ + max = 0; + for (i = 0; i < LPC_ORDER; i++) + max = FFMAX(weight[i], max); + + shift = normalize_bits_int16(max); + for (i = 0; i < LPC_ORDER; i++) { + weight[i] <<= shift; + } + + /* Compute the VQ target vector */ + for (i = 0; i < LPC_ORDER; i++) { + lsp[i] -= dc_lsp[i] + + (((prev_lsp[i] - dc_lsp[i]) * 12288 + (1 << 14)) >> 15); + } + + get_index(0, 0, 3); + get_index(1, 3, 3); + get_index(2, 6, 4); +} + +/** + * Apply the formant perceptual weighting filter. + * + * @param flt_coef filter coefficients + * @param unq_lpc unquantized lpc vector + */ +static void perceptual_filter(G723_1_Context *p, int16_t *flt_coef, + int16_t *unq_lpc, int16_t *buf) +{ + int16_t vector[FRAME_LEN + LPC_ORDER]; + int i, j, k, l = 0; + + memcpy(buf, p->iir_mem, sizeof(int16_t) * LPC_ORDER); + memcpy(vector, p->fir_mem, sizeof(int16_t) * LPC_ORDER); + memcpy(vector + LPC_ORDER, buf + LPC_ORDER, sizeof(int16_t) * FRAME_LEN); + + for (i = LPC_ORDER, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) { + for (k = 0; k < LPC_ORDER; k++) { + flt_coef[k + 2 * l] = (unq_lpc[k + l] * percept_flt_tbl[0][k] + + (1 << 14)) >> 15; + flt_coef[k + 2 * l + LPC_ORDER] = (unq_lpc[k + l] * + percept_flt_tbl[1][k] + + (1 << 14)) >> 15; + } + iir_filter(flt_coef + 2 * l, flt_coef + 2 * l + LPC_ORDER, vector + i, + buf + i, 0); + l += LPC_ORDER; + } + memcpy(p->iir_mem, buf + FRAME_LEN, sizeof(int16_t) * LPC_ORDER); + memcpy(p->fir_mem, vector + FRAME_LEN, sizeof(int16_t) * LPC_ORDER); +} + +/** + * Estimate the open loop pitch period. + * + * @param buf perceptually weighted speech + * @param start estimation is carried out from this position + */ +static int estimate_pitch(int16_t *buf, int start) +{ + int max_exp = 32; + int max_ccr = 0x4000; + int max_eng = 0x7fff; + int index = PITCH_MIN; + int offset = start - PITCH_MIN + 1; + + int ccr, eng, orig_eng, ccr_eng, exp; + int diff, temp; + + int i; + + orig_eng = ff_dot_product(buf + offset, buf + offset, HALF_FRAME_LEN); + + for (i = PITCH_MIN; i <= PITCH_MAX - 3; i++) { + offset--; + + /* Update energy and compute correlation */ + orig_eng += buf[offset] * buf[offset] - + buf[offset + HALF_FRAME_LEN] * buf[offset + HALF_FRAME_LEN]; + ccr = ff_dot_product(buf + start, buf + offset, HALF_FRAME_LEN); + if (ccr <= 0) + continue; + + /* Split into mantissa and exponent to maintain precision */ + exp = normalize_bits_int32(ccr); + ccr = av_clipl_int32((int64_t)(ccr << exp) + (1 << 15)) >> 16; + exp <<= 1; + ccr *= ccr; + temp = normalize_bits_int32(ccr); + ccr = ccr << temp >> 16; + exp += temp; + + temp = normalize_bits_int32(orig_eng); + eng = av_clipl_int32((int64_t)(orig_eng << temp) + (1 << 15)) >> 16; + exp -= temp; + + if (ccr >= eng) { + exp--; + ccr >>= 1; + } + if (exp > max_exp) + continue; + + if (exp + 1 < max_exp) + goto update; + + /* Equalize exponents before comparison */ + if (exp + 1 == max_exp) + temp = max_ccr >> 1; + else + temp = max_ccr; + ccr_eng = ccr * max_eng; + diff = ccr_eng - eng * temp; + if (diff > 0 && (i - index < PITCH_MIN || diff > ccr_eng >> 2)) { +update: + index = i; + max_exp = exp; + max_ccr = ccr; + max_eng = eng; + } + } + return index; +} + +/** + * Compute harmonic noise filter parameters. + * + * @param buf perceptually weighted speech + * @param pitch_lag open loop pitch period + * @param hf harmonic filter parameters + */ +static void comp_harmonic_coeff(int16_t *buf, int16_t pitch_lag, HFParam *hf) +{ + int ccr, eng, max_ccr, max_eng; + int exp, max, diff; + int energy[15]; + int i, j; + + for (i = 0, j = pitch_lag - 3; j <= pitch_lag + 3; i++, j++) { + /* Compute residual energy */ + energy[i << 1] = ff_dot_product(buf - j, buf - j, SUBFRAME_LEN); + /* Compute correlation */ + energy[(i << 1) + 1] = ff_dot_product(buf, buf - j, SUBFRAME_LEN); + } + + /* Compute target energy */ + energy[14] = ff_dot_product(buf, buf, SUBFRAME_LEN); + + /* Normalize */ + max = 0; + for (i = 0; i < 15; i++) + max = FFMAX(max, FFABS(energy[i])); + + exp = normalize_bits_int32(max); + for (i = 0; i < 15; i++) { + energy[i] = av_clipl_int32((int64_t)(energy[i] << exp) + + (1 << 15)) >> 16; + } + + hf->index = -1; + hf->gain = 0; + max_ccr = 1; + max_eng = 0x7fff; + + for (i = 0; i <= 6; i++) { + eng = energy[i << 1]; + ccr = energy[(i << 1) + 1]; + + if (ccr <= 0) + continue; + + ccr = (ccr * ccr + (1 << 14)) >> 15; + diff = ccr * max_eng - eng * max_ccr; + if (diff > 0) { + max_ccr = ccr; + max_eng = eng; + hf->index = i; + } + } + + if (hf->index == -1) { + hf->index = pitch_lag; + return; + } + + eng = energy[14] * max_eng; + eng = (eng >> 2) + (eng >> 3); + ccr = energy[(hf->index << 1) + 1] * energy[(hf->index << 1) + 1]; + if (eng < ccr) { + eng = energy[(hf->index << 1) + 1]; + + if (eng >= max_eng) + hf->gain = 0x2800; + else + hf->gain = ((eng << 15) / max_eng * 0x2800 + (1 << 14)) >> 15; + } + hf->index += pitch_lag - 3; +} + +/** + * Apply the harmonic noise shaping filter. + * + * @param hf filter parameters + */ +static void harmonic_filter(HFParam *hf, const int16_t *src, int16_t *dest) +{ + int i; + + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = hf->gain * src[i - hf->index] << 1; + dest[i] = av_clipl_int32((src[i] << 16) - temp + (1 << 15)) >> 16; + } +} + +static void harmonic_noise_sub(HFParam *hf, const int16_t *src, int16_t *dest) +{ + int i; + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = hf->gain * src[i - hf->index] << 1; + dest[i] = av_clipl_int32(((dest[i] - src[i]) << 16) + temp + + (1 << 15)) >> 16; + + } +} + +/** + * Combined synthesis and formant perceptual weighting filer. + * + * @param qnt_lpc quantized lpc coefficients + * @param perf_lpc perceptual filter coefficients + * @param perf_fir perceptual filter fir memory + * @param perf_iir perceptual filter iir memory + * @param scale the filter output will be scaled by 2^scale + */ +static void synth_percept_filter(int16_t *qnt_lpc, int16_t *perf_lpc, + int16_t *perf_fir, int16_t *perf_iir, + const int16_t *src, int16_t *dest, int scale) +{ + int i, j; + int16_t buf_16[SUBFRAME_LEN + LPC_ORDER]; + int64_t buf[SUBFRAME_LEN]; + + int16_t *bptr_16 = buf_16 + LPC_ORDER; + + memcpy(buf_16, perf_fir, sizeof(int16_t) * LPC_ORDER); + memcpy(dest - LPC_ORDER, perf_iir, sizeof(int16_t) * LPC_ORDER); + + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = 0; + for (j = 1; j <= LPC_ORDER; j++) + temp -= qnt_lpc[j - 1] * bptr_16[i - j]; + + buf[i] = (src[i] << 15) + (temp << 3); + bptr_16[i] = av_clipl_int32(buf[i] + (1 << 15)) >> 16; + } + + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t fir = 0, iir = 0; + for (j = 1; j <= LPC_ORDER; j++) { + fir -= perf_lpc[j - 1] * bptr_16[i - j]; + iir += perf_lpc[j + LPC_ORDER - 1] * dest[i - j]; + } + dest[i] = av_clipl_int32(((buf[i] + (fir << 3)) << scale) + (iir << 3) + + (1 << 15)) >> 16; + } + memcpy(perf_fir, buf_16 + SUBFRAME_LEN, sizeof(int16_t) * LPC_ORDER); + memcpy(perf_iir, dest + SUBFRAME_LEN - LPC_ORDER, + sizeof(int16_t) * LPC_ORDER); +} + +/** + * Compute the adaptive codebook contribution. + * + * @param buf input signal + * @param index the current subframe index + */ +static void acb_search(G723_1_Context *p, int16_t *residual, + int16_t *impulse_resp, const int16_t *buf, + int index) +{ + + int16_t flt_buf[PITCH_ORDER][SUBFRAME_LEN]; + + const int16_t *cb_tbl = adaptive_cb_gain85; + + int ccr_buf[PITCH_ORDER * SUBFRAMES << 2]; + + int pitch_lag = p->pitch_lag[index >> 1]; + int acb_lag = 1; + int acb_gain = 0; + int odd_frame = index & 1; + int iter = 3 + odd_frame; + int count = 0; + int tbl_size = 85; + + int i, j, k, l, max; + int64_t temp; + + if (!odd_frame) { + if (pitch_lag == PITCH_MIN) + pitch_lag++; + else + pitch_lag = FFMIN(pitch_lag, PITCH_MAX - 5); + } + + for (i = 0; i < iter; i++) { + get_residual(residual, p->prev_excitation, pitch_lag + i - 1); + + for (j = 0; j < SUBFRAME_LEN; j++) { + temp = 0; + for (k = 0; k <= j; k++) + temp += residual[PITCH_ORDER - 1 + k] * impulse_resp[j - k]; + flt_buf[PITCH_ORDER - 1][j] = av_clipl_int32((temp << 1) + + (1 << 15)) >> 16; + } + + for (j = PITCH_ORDER - 2; j >= 0; j--) { + flt_buf[j][0] = ((residual[j] << 13) + (1 << 14)) >> 15; + for (k = 1; k < SUBFRAME_LEN; k++) { + temp = (flt_buf[j + 1][k - 1] << 15) + + residual[j] * impulse_resp[k]; + flt_buf[j][k] = av_clipl_int32((temp << 1) + (1 << 15)) >> 16; + } + } + + /* Compute crosscorrelation with the signal */ + for (j = 0; j < PITCH_ORDER; j++) { + temp = ff_dot_product(buf, flt_buf[j], SUBFRAME_LEN); + ccr_buf[count++] = av_clipl_int32(temp << 1); + } + + /* Compute energies */ + for (j = 0; j < PITCH_ORDER; j++) { + ccr_buf[count++] = dot_product(flt_buf[j], flt_buf[j], + SUBFRAME_LEN); + } + + for (j = 1; j < PITCH_ORDER; j++) { + for (k = 0; k < j; k++) { + temp = ff_dot_product(flt_buf[j], flt_buf[k], SUBFRAME_LEN); + ccr_buf[count++] = av_clipl_int32(temp<<2); + } + } + } + + /* Normalize and shorten */ + max = 0; + for (i = 0; i < 20 * iter; i++) + max = FFMAX(max, FFABS(ccr_buf[i])); + + temp = normalize_bits_int32(max); + + for (i = 0; i < 20 * iter; i++){ + ccr_buf[i] = av_clipl_int32((int64_t)(ccr_buf[i] << temp) + + (1 << 15)) >> 16; + } + + max = 0; + for (i = 0; i < iter; i++) { + /* Select quantization table */ + if (!odd_frame && pitch_lag + i - 1 >= SUBFRAME_LEN - 2 || + odd_frame && pitch_lag >= SUBFRAME_LEN - 2) { + cb_tbl = adaptive_cb_gain170; + tbl_size = 170; + } + + for (j = 0, k = 0; j < tbl_size; j++, k += 20) { + temp = 0; + for (l = 0; l < 20; l++) + temp += ccr_buf[20 * i + l] * cb_tbl[k + l]; + temp = av_clipl_int32(temp); + + if (temp > max) { + max = temp; + acb_gain = j; + acb_lag = i; + } + } + } + + if (!odd_frame) { + pitch_lag += acb_lag - 1; + acb_lag = 1; + } + + p->pitch_lag[index >> 1] = pitch_lag; + p->subframe[index].ad_cb_lag = acb_lag; + p->subframe[index].ad_cb_gain = acb_gain; +} + +/** + * Subtract the adaptive codebook contribution from the input + * to obtain the residual. + * + * @param buf target vector + */ +static void sub_acb_contrib(const int16_t *residual, const int16_t *impulse_resp, + int16_t *buf) +{ + int i, j; + /* Subtract adaptive CB contribution to obtain the residual */ + for (i = 0; i < SUBFRAME_LEN; i++) { + int64_t temp = buf[i] << 14; + for (j = 0; j <= i; j++) + temp -= residual[j] * impulse_resp[i - j]; + + buf[i] = av_clipl_int32((temp << 2) + (1 << 15)) >> 16; + } +} + +/** + * Quantize the residual signal using the fixed codebook (MP-MLQ). + * + * @param optim optimized fixed codebook parameters + * @param buf excitation vector + */ +static void get_fcb_param(FCBParam *optim, int16_t *impulse_resp, + int16_t *buf, int pulse_cnt, int pitch_lag) +{ + FCBParam param; + int16_t impulse_r[SUBFRAME_LEN]; + int16_t temp_corr[SUBFRAME_LEN]; + int16_t impulse_corr[SUBFRAME_LEN]; + + int ccr1[SUBFRAME_LEN]; + int ccr2[SUBFRAME_LEN]; + int amp, err, max, max_amp_index, min, scale, i, j, k, l; + + int64_t temp; + + /* Update impulse response */ + memcpy(impulse_r, impulse_resp, sizeof(int16_t) * SUBFRAME_LEN); + param.dirac_train = 0; + if (pitch_lag < SUBFRAME_LEN - 2) { + param.dirac_train = 1; + gen_dirac_train(impulse_r, pitch_lag); + } + + for (i = 0; i < SUBFRAME_LEN; i++) + temp_corr[i] = impulse_r[i] >> 1; + + /* Compute impulse response autocorrelation */ + temp = dot_product(temp_corr, temp_corr, SUBFRAME_LEN); + + scale = normalize_bits_int32(temp); + impulse_corr[0] = av_clipl_int32((temp << scale) + (1 << 15)) >> 16; + + for (i = 1; i < SUBFRAME_LEN; i++) { + temp = dot_product(temp_corr + i, temp_corr, SUBFRAME_LEN - i); + impulse_corr[i] = av_clipl_int32((temp << scale) + (1 << 15)) >> 16; + } + + /* Compute crosscorrelation of impulse response with residual signal */ + scale -= 4; + for (i = 0; i < SUBFRAME_LEN; i++){ + temp = dot_product(buf + i, impulse_r, SUBFRAME_LEN - i); + if (scale < 0) + ccr1[i] = temp >> -scale; + else + ccr1[i] = av_clipl_int32(temp << scale); + } + + /* Search loop */ + for (i = 0; i < GRID_SIZE; i++) { + /* Maximize the crosscorrelation */ + max = 0; + for (j = i; j < SUBFRAME_LEN; j += GRID_SIZE) { + temp = FFABS(ccr1[j]); + if (temp >= max) { + max = temp; + param.pulse_pos[0] = j; + } + } + + /* Quantize the gain (max crosscorrelation/impulse_corr[0]) */ + amp = max; + min = 1 << 30; + max_amp_index = GAIN_LEVELS - 2; + for (j = max_amp_index; j >= 2; j--) { + temp = av_clipl_int32((int64_t)fixed_cb_gain[j] * + impulse_corr[0] << 1); + temp = FFABS(temp - amp); + if (temp < min) { + min = temp; + max_amp_index = j; + } + } + + max_amp_index--; + /* Select additional gain values */ + for (j = 1; j < 5; j++) { + for (k = i; k < SUBFRAME_LEN; k += GRID_SIZE) { + temp_corr[k] = 0; + ccr2[k] = ccr1[k]; + } + param.amp_index = max_amp_index + j - 2; + amp = fixed_cb_gain[param.amp_index]; + + param.pulse_sign[0] = (ccr2[param.pulse_pos[0]] < 0) ? -amp : amp; + temp_corr[param.pulse_pos[0]] = 1; + + for (k = 1; k < pulse_cnt; k++) { + max = -1 << 30; + for (l = i; l < SUBFRAME_LEN; l += GRID_SIZE) { + if (temp_corr[l]) + continue; + temp = impulse_corr[FFABS(l - param.pulse_pos[k - 1])]; + temp = av_clipl_int32((int64_t)temp * + param.pulse_sign[k - 1] << 1); + ccr2[l] -= temp; + temp = FFABS(ccr2[l]); + if (temp > max) { + max = temp; + param.pulse_pos[k] = l; + } + } + + param.pulse_sign[k] = (ccr2[param.pulse_pos[k]] < 0) ? + -amp : amp; + temp_corr[param.pulse_pos[k]] = 1; + } + + /* Create the error vector */ + memset(temp_corr, 0, sizeof(int16_t) * SUBFRAME_LEN); + + for (k = 0; k < pulse_cnt; k++) + temp_corr[param.pulse_pos[k]] = param.pulse_sign[k]; + + for (k = SUBFRAME_LEN - 1; k >= 0; k--) { + temp = 0; + for (l = 0; l <= k; l++) { + int prod = av_clipl_int32((int64_t)temp_corr[l] * + impulse_r[k - l] << 1); + temp = av_clipl_int32(temp + prod); + } + temp_corr[k] = temp << 2 >> 16; + } + + /* Compute square of error */ + err = 0; + for (k = 0; k < SUBFRAME_LEN; k++) { + int64_t prod; + prod = av_clipl_int32((int64_t)buf[k] * temp_corr[k] << 1); + err = av_clipl_int32(err - prod); + prod = av_clipl_int32((int64_t)temp_corr[k] * temp_corr[k]); + err = av_clipl_int32(err + prod); + } + + /* Minimize */ + if (err < optim->min_err) { + optim->min_err = err; + optim->grid_index = i; + optim->amp_index = param.amp_index; + optim->dirac_train = param.dirac_train; + + for (k = 0; k < pulse_cnt; k++) { + optim->pulse_sign[k] = param.pulse_sign[k]; + optim->pulse_pos[k] = param.pulse_pos[k]; + } + } + } + } +} + +/** + * Encode the pulse position and gain of the current subframe. + * + * @param optim optimized fixed CB parameters + * @param buf excitation vector + */ +static void pack_fcb_param(G723_1_Subframe *subfrm, FCBParam *optim, + int16_t *buf, int pulse_cnt) +{ + int i, j; + + j = PULSE_MAX - pulse_cnt; + + subfrm->pulse_sign = 0; + subfrm->pulse_pos = 0; + + for (i = 0; i < SUBFRAME_LEN >> 1; i++) { + int val = buf[optim->grid_index + (i << 1)]; + if (!val) { + subfrm->pulse_pos += combinatorial_table[j][i]; + } else { + subfrm->pulse_sign <<= 1; + if (val < 0) subfrm->pulse_sign++; + j++; + + if (j == PULSE_MAX) break; + } + } + subfrm->amp_index = optim->amp_index; + subfrm->grid_index = optim->grid_index; + subfrm->dirac_train = optim->dirac_train; +} + +/** + * Compute the fixed codebook excitation. + * + * @param buf target vector + * @param impulse_resp impulse response of the combined filter + */ +static void fcb_search(G723_1_Context *p, int16_t *impulse_resp, + int16_t *buf, int index) +{ + FCBParam optim; + int pulse_cnt = pulses[index]; + int i; + + optim.min_err = 1 << 30; + get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, SUBFRAME_LEN); + + if (p->pitch_lag[index >> 1] < SUBFRAME_LEN - 2) { + get_fcb_param(&optim, impulse_resp, buf, pulse_cnt, + p->pitch_lag[index >> 1]); + } + + /* Reconstruct the excitation */ + memset(buf, 0, sizeof(int16_t) * SUBFRAME_LEN); + for (i = 0; i < pulse_cnt; i++) + buf[optim.pulse_pos[i]] = optim.pulse_sign[i]; + + pack_fcb_param(&p->subframe[index], &optim, buf, pulse_cnt); + + if (optim.dirac_train) + gen_dirac_train(buf, p->pitch_lag[index >> 1]); +} + +/** + * Pack the frame parameters into output bitstream. + * + * @param frame output buffer + * @param size size of the buffer + */ +static int pack_bitstream(G723_1_Context *p, unsigned char *frame, int size) +{ + PutBitContext pb; + int info_bits, i, temp; + + init_put_bits(&pb, frame, size); + + if (p->cur_rate == RATE_6300) { + info_bits = 0; + put_bits(&pb, 2, info_bits); + } + + put_bits(&pb, 8, p->lsp_index[2]); + put_bits(&pb, 8, p->lsp_index[1]); + put_bits(&pb, 8, p->lsp_index[0]); + + put_bits(&pb, 7, p->pitch_lag[0] - PITCH_MIN); + put_bits(&pb, 2, p->subframe[1].ad_cb_lag); + put_bits(&pb, 7, p->pitch_lag[1] - PITCH_MIN); + put_bits(&pb, 2, p->subframe[3].ad_cb_lag); + + /* Write 12 bit combined gain */ + for (i = 0; i < SUBFRAMES; i++) { + temp = p->subframe[i].ad_cb_gain * GAIN_LEVELS + + p->subframe[i].amp_index; + if (p->cur_rate == RATE_6300) + temp += p->subframe[i].dirac_train << 11; + put_bits(&pb, 12, temp); + } + + put_bits(&pb, 1, p->subframe[0].grid_index); + put_bits(&pb, 1, p->subframe[1].grid_index); + put_bits(&pb, 1, p->subframe[2].grid_index); + put_bits(&pb, 1, p->subframe[3].grid_index); + + if (p->cur_rate == RATE_6300) { + skip_put_bits(&pb, 1); /* reserved bit */ + + /* Write 13 bit combined position index */ + temp = (p->subframe[0].pulse_pos >> 16) * 810 + + (p->subframe[1].pulse_pos >> 14) * 90 + + (p->subframe[2].pulse_pos >> 16) * 9 + + (p->subframe[3].pulse_pos >> 14); + put_bits(&pb, 13, temp); + + put_bits(&pb, 16, p->subframe[0].pulse_pos & 0xffff); + put_bits(&pb, 14, p->subframe[1].pulse_pos & 0x3fff); + put_bits(&pb, 16, p->subframe[2].pulse_pos & 0xffff); + put_bits(&pb, 14, p->subframe[3].pulse_pos & 0x3fff); + + put_bits(&pb, 6, p->subframe[0].pulse_sign); + put_bits(&pb, 5, p->subframe[1].pulse_sign); + put_bits(&pb, 6, p->subframe[2].pulse_sign); + put_bits(&pb, 5, p->subframe[3].pulse_sign); + } + + flush_put_bits(&pb); + return frame_size[info_bits]; +} + +static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + G723_1_Context *p = avctx->priv_data; + int16_t unq_lpc[LPC_ORDER * SUBFRAMES]; + int16_t qnt_lpc[LPC_ORDER * SUBFRAMES]; + int16_t cur_lsp[LPC_ORDER]; + int16_t weighted_lpc[LPC_ORDER * SUBFRAMES << 1]; + int16_t vector[FRAME_LEN + PITCH_MAX]; + int offset, ret; + int16_t *in = (const int16_t *)frame->data[0]; + + HFParam hf[4]; + int i, j; + + highpass_filter(in, &p->hpf_fir_mem, &p->hpf_iir_mem); + + memcpy(vector, p->prev_data, HALF_FRAME_LEN * sizeof(int16_t)); + memcpy(vector + HALF_FRAME_LEN, in, FRAME_LEN * sizeof(int16_t)); + + comp_lpc_coeff(vector, unq_lpc); + lpc2lsp(&unq_lpc[LPC_ORDER * 3], p->prev_lsp, cur_lsp); + lsp_quantize(p->lsp_index, cur_lsp, p->prev_lsp); + + /* Update memory */ + memcpy(vector + LPC_ORDER, p->prev_data + SUBFRAME_LEN, + sizeof(int16_t) * SUBFRAME_LEN); + memcpy(vector + LPC_ORDER + SUBFRAME_LEN, in, + sizeof(int16_t) * (HALF_FRAME_LEN + SUBFRAME_LEN)); + memcpy(p->prev_data, in + HALF_FRAME_LEN, + sizeof(int16_t) * HALF_FRAME_LEN); + memcpy(in, vector + LPC_ORDER, sizeof(int16_t) * FRAME_LEN); + + perceptual_filter(p, weighted_lpc, unq_lpc, vector); + + memcpy(in, vector + LPC_ORDER, sizeof(int16_t) * FRAME_LEN); + memcpy(vector, p->prev_weight_sig, sizeof(int16_t) * PITCH_MAX); + memcpy(vector + PITCH_MAX, in, sizeof(int16_t) * FRAME_LEN); + + scale_vector(vector, vector, FRAME_LEN + PITCH_MAX); + + p->pitch_lag[0] = estimate_pitch(vector, PITCH_MAX); + p->pitch_lag[1] = estimate_pitch(vector, PITCH_MAX + HALF_FRAME_LEN); + + for (i = PITCH_MAX, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + comp_harmonic_coeff(vector + i, p->pitch_lag[j >> 1], hf + j); + + memcpy(vector, p->prev_weight_sig, sizeof(int16_t) * PITCH_MAX); + memcpy(vector + PITCH_MAX, in, sizeof(int16_t) * FRAME_LEN); + memcpy(p->prev_weight_sig, vector + FRAME_LEN, sizeof(int16_t) * PITCH_MAX); + + for (i = 0, j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++) + harmonic_filter(hf + j, vector + PITCH_MAX + i, in + i); + + inverse_quant(cur_lsp, p->prev_lsp, p->lsp_index, 0); + lsp_interpolate(qnt_lpc, cur_lsp, p->prev_lsp); + + memcpy(p->prev_lsp, cur_lsp, sizeof(int16_t) * LPC_ORDER); + + offset = 0; + for (i = 0; i < SUBFRAMES; i++) { + int16_t impulse_resp[SUBFRAME_LEN]; + int16_t residual[SUBFRAME_LEN + PITCH_ORDER - 1]; + int16_t flt_in[SUBFRAME_LEN]; + int16_t zero[LPC_ORDER], fir[LPC_ORDER], iir[LPC_ORDER]; + + /** + * Compute the combined impulse response of the synthesis filter, + * formant perceptual weighting filter and harmonic noise shaping filter + */ + memset(zero, 0, sizeof(int16_t) * LPC_ORDER); + memset(vector, 0, sizeof(int16_t) * PITCH_MAX); + memset(flt_in, 0, sizeof(int16_t) * SUBFRAME_LEN); + + flt_in[0] = 1 << 13; /* Unit impulse */ + synth_percept_filter(qnt_lpc + offset, weighted_lpc + (offset << 1), + zero, zero, flt_in, vector + PITCH_MAX, 1); + harmonic_filter(hf + i, vector + PITCH_MAX, impulse_resp); + + /* Compute the combined zero input response */ + flt_in[0] = 0; + memcpy(fir, p->perf_fir_mem, sizeof(int16_t) * LPC_ORDER); + memcpy(iir, p->perf_iir_mem, sizeof(int16_t) * LPC_ORDER); + + synth_percept_filter(qnt_lpc + offset, weighted_lpc + (offset << 1), + fir, iir, flt_in, vector + PITCH_MAX, 0); + memcpy(vector, p->harmonic_mem, sizeof(int16_t) * PITCH_MAX); + harmonic_noise_sub(hf + i, vector + PITCH_MAX, in); + + acb_search(p, residual, impulse_resp, in, i); + gen_acb_excitation(residual, p->prev_excitation,p->pitch_lag[i >> 1], + &p->subframe[i], p->cur_rate); + sub_acb_contrib(residual, impulse_resp, in); + + fcb_search(p, impulse_resp, in, i); + + /* Reconstruct the excitation */ + gen_acb_excitation(impulse_resp, p->prev_excitation, p->pitch_lag[i >> 1], + &p->subframe[i], RATE_6300); + + memmove(p->prev_excitation, p->prev_excitation + SUBFRAME_LEN, + sizeof(int16_t) * (PITCH_MAX - SUBFRAME_LEN)); + for (j = 0; j < SUBFRAME_LEN; j++) + in[j] = av_clip_int16((in[j] << 1) + impulse_resp[j]); + memcpy(p->prev_excitation + PITCH_MAX - SUBFRAME_LEN, in, + sizeof(int16_t) * SUBFRAME_LEN); + + /* Update filter memories */ + synth_percept_filter(qnt_lpc + offset, weighted_lpc + (offset << 1), + p->perf_fir_mem, p->perf_iir_mem, + in, vector + PITCH_MAX, 0); + memmove(p->harmonic_mem, p->harmonic_mem + SUBFRAME_LEN, + sizeof(int16_t) * (PITCH_MAX - SUBFRAME_LEN)); + memcpy(p->harmonic_mem + PITCH_MAX - SUBFRAME_LEN, vector + PITCH_MAX, + sizeof(int16_t) * SUBFRAME_LEN); + + in += SUBFRAME_LEN; + offset += LPC_ORDER; + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, 24)) < 0) + return ret; + + *got_packet_ptr = 1; + avpkt->size = pack_bitstream(p, avpkt->data, avpkt->size); + return 0; +} + +AVCodec ff_g723_1_encoder = { + .name = "g723_1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_G723_1, + .priv_data_size = sizeof(G723_1_Context), + .init = g723_1_encode_init, + .encode2 = g723_1_encode_frame, + .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE}, +}; +#endif diff --git a/ffmpeg/libavcodec/g723_1_data.h b/ffmpeg/libavcodec/g723_1_data.h new file mode 100644 index 0000000..38a6c59 --- /dev/null +++ b/ffmpeg/libavcodec/g723_1_data.h @@ -0,0 +1,1329 @@ +/* + * G723.1 compatible decoder data tables. + * Copyright (c) 2006 Benjamin Larsson + * Copyright (c) 2010 Mohamed Naufal Basheer + * + * 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 + */ + +/** + * @file + * G723.1 compatible decoder data tables + */ + +#ifndef AVCODEC_G723_1_DATA_H +#define AVCODEC_G723_1_DATA_H + +#include + +#define SUBFRAMES 4 +#define SUBFRAME_LEN 60 +#define FRAME_LEN (SUBFRAME_LEN << 2) +#define HALF_FRAME_LEN (FRAME_LEN / 2) +#define LPC_FRAME (HALF_FRAME_LEN + SUBFRAME_LEN) +#define LPC_ORDER 10 +#define LSP_BANDS 3 +#define LSP_CB_SIZE 256 +#define PITCH_MIN 18 +#define PITCH_MAX (PITCH_MIN + 127) +#define PITCH_ORDER 5 +#define GRID_SIZE 2 +#define PULSE_MAX 6 +#define GAIN_LEVELS 24 +#define COS_TBL_SIZE 512 + +/** + * G723.1 frame types + */ +typedef enum FrameType { + ACTIVE_FRAME, ///< Active speech + SID_FRAME, ///< Silence Insertion Descriptor frame + UNTRANSMITTED_FRAME +} FrameType; + +static const uint8_t frame_size[4] = { 24, 20, 4, 1 }; + +typedef enum Rate { + RATE_6300, + RATE_5300 +} Rate; + +/** + * G723.1 unpacked data subframe + */ +typedef struct G723_1_Subframe { + int ad_cb_lag; ///< adaptive codebook lag + int ad_cb_gain; + int dirac_train; + int pulse_sign; + int grid_index; + int amp_index; + int pulse_pos; +} G723_1_Subframe; + +/** + * Pitch postfilter parameters + */ +typedef struct { + int index; ///< postfilter backward/forward lag + int16_t opt_gain; ///< optimal gain + int16_t sc_gain; ///< scaling gain +} PPFParam; + +/** + * Harmonic filter parameters + */ +typedef struct { + int index; + int gain; +} HFParam; + +/** + * Optimized fixed codebook excitation parameters + */ +typedef struct { + int min_err; + int amp_index; + int grid_index; + int dirac_train; + int pulse_pos[PULSE_MAX]; + int pulse_sign[PULSE_MAX]; +} FCBParam; + +/** + * Postfilter gain weighting factors scaled by 2^15 + */ +static const int16_t ppf_gain_weight[2] = {0x1800, 0x2000}; + +/** + * LSP DC component + */ +static const int16_t dc_lsp[LPC_ORDER] = { + 0x0c3b, + 0x1271, + 0x1e0a, + 0x2a36, + 0x3630, + 0x406f, + 0x4d28, + 0x56f4, + 0x638c, + 0x6c46 +}; + +/** + * Cosine table scaled by 2^14 + */ +static const int16_t cos_tab[COS_TBL_SIZE+1] = { + 16384, 16383, 16379, 16373, 16364, 16353, 16340, 16324, + 16305, 16284, 16261, 16235, 16207, 16176, 16143, 16107, + 16069, 16029, 15986, 15941, 15893, 15843, 15791, 15736, + 15679, 15619, 15557, 15493, 15426, 15357, 15286, 15213, + 15137, 15059, 14978, 14896, 14811, 14724, 14635, 14543, + 14449, 14354, 14256, 14155, 14053, 13949, 13842, 13733, + 13623, 13510, 13395, 13279, 13160, 13039, 12916, 12792, + 12665, 12537, 12406, 12274, 12140, 12004, 11866, 11727, + 11585, 11442, 11297, 11151, 11003, 10853, 10702, 10549, + 10394, 10238, 10080, 9921, 9760, 9598, 9434, 9269, + 9102, 8935, 8765, 8595, 8423, 8250, 8076, 7900, + 7723, 7545, 7366, 7186, 7005, 6823, 6639, 6455, + 6270, 6084, 5897, 5708, 5520, 5330, 5139, 4948, + 4756, 4563, 4370, 4176, 3981, 3786, 3590, 3393, + 3196, 2999, 2801, 2603, 2404, 2205, 2006, 1806, + 1606, 1406, 1205, 1005, 804, 603, 402, 201, + 0, -201, -402, -603, -804, -1005, -1205, -1406, + -1606, -1806, -2006, -2205, -2404, -2603, -2801, -2999, + -3196, -3393, -3590, -3786, -3981, -4176, -4370, -4563, + -4756, -4948, -5139, -5330, -5520, -5708, -5897, -6084, + -6270, -6455, -6639, -6823, -7005, -7186, -7366, -7545, + -7723, -7900, -8076, -8250, -8423, -8595, -8765, -8935, + -9102, -9269, -9434, -9598, -9760, -9921, -10080, -10238, + -10394, -10549, -10702, -10853, -11003, -11151, -11297, -11442, + -11585, -11727, -11866, -12004, -12140, -12274, -12406, -12537, + -12665, -12792, -12916, -13039, -13160, -13279, -13395, -13510, + -13623, -13733, -13842, -13949, -14053, -14155, -14256, -14354, + -14449, -14543, -14635, -14724, -14811, -14896, -14978, -15059, + -15137, -15213, -15286, -15357, -15426, -15493, -15557, -15619, + -15679, -15736, -15791, -15843, -15893, -15941, -15986, -16029, + -16069, -16107, -16143, -16176, -16207, -16235, -16261, -16284, + -16305, -16324, -16340, -16353, -16364, -16373, -16379, -16383, + -16384, -16383, -16379, -16373, -16364, -16353, -16340, -16324, + -16305, -16284, -16261, -16235, -16207, -16176, -16143, -16107, + -16069, -16029, -15986, -15941, -15893, -15843, -15791, -15736, + -15679, -15619, -15557, -15493, -15426, -15357, -15286, -15213, + -15137, -15059, -14978, -14896, -14811, -14724, -14635, -14543, + -14449, -14354, -14256, -14155, -14053, -13949, -13842, -13733, + -13623, -13510, -13395, -13279, -13160, -13039, -12916, -12792, + -12665, -12537, -12406, -12274, -12140, -12004, -11866, -11727, + -11585, -11442, -11297, -11151, -11003, -10853, -10702, -10549, + -10394, -10238, -10080, -9921, -9760, -9598, -9434, -9269, + -9102, -8935, -8765, -8595, -8423, -8250, -8076, -7900, + -7723, -7545, -7366, -7186, -7005, -6823, -6639, -6455, + -6270, -6084, -5897, -5708, -5520, -5330, -5139, -4948, + -4756, -4563, -4370, -4176, -3981, -3786, -3590, -3393, + -3196, -2999, -2801, -2603, -2404, -2205, -2006, -1806, + -1606, -1406, -1205, -1005, -804, -603, -402, -201, + 0, 201, 402, 603, 804, 1005, 1205, 1406, + 1606, 1806, 2006, 2205, 2404, 2603, 2801, 2999, + 3196, 3393, 3590, 3786, 3981, 4176, 4370, 4563, + 4756, 4948, 5139, 5330, 5520, 5708, 5897, 6084, + 6270, 6455, 6639, 6823, 7005, 7186, 7366, 7545, + 7723, 7900, 8076, 8250, 8423, 8595, 8765, 8935, + 9102, 9269, 9434, 9598, 9760, 9921, 10080, 10238, + 10394, 10549, 10702, 10853, 11003, 11151, 11297, 11442, + 11585, 11727, 11866, 12004, 12140, 12274, 12406, 12537, + 12665, 12792, 12916, 13039, 13160, 13279, 13395, 13510, + 13623, 13733, 13842, 13949, 14053, 14155, 14256, 14354, + 14449, 14543, 14635, 14724, 14811, 14896, 14978, 15059, + 15137, 15213, 15286, 15357, 15426, 15493, 15557, 15619, + 15679, 15736, 15791, 15843, 15893, 15941, 15986, 16029, + 16069, 16107, 16143, 16176, 16207, 16235, 16261, 16284, + 16305, 16324, 16340, 16353, 16364, 16373, 16379, 16383, + 16384 +}; + +/** + * LSP VQ tables + */ +static const int16_t lsp_band0[LSP_CB_SIZE][3] = { + { 0, 0, 0}, { -270, -1372, -1032}, { -541, -1650, -1382}, + { -723, -2011, -2213}, { -941, -1122, -1942}, { -780, -1145, -2454}, + { -884, -1309, -1373}, {-1051, -1523, -1766}, {-1083, -1622, -2300}, + { -777, -1377, -2147}, { -935, -1467, -2763}, { -802, -1327, -3471}, + { -935, -1959, -3999}, { -240, -89, 222}, { -661, -257, -160}, + { -994, -466, -419}, { -188, -164, -278}, { -342, -512, -415}, + { -607, -511, -797}, { 16, 19, -716}, { 374, 425, -972}, + { -346, 245, -282}, { -265, 506, -754}, { -620, -147, 1955}, + { -742, -860, 2597}, { -150, -352, 2704}, { 305, 880, 1954}, + { 123, 731, 2766}, { -348, 765, 3327}, { 618, 221, 3258}, + { -178, -47, 4219}, { 393, 1304, 3842}, { 698, 1702, 4801}, + { 63, -584, 1229}, { -215, -732, 1704}, { 172, -335, 1909}, + { -2, 216, 1797}, { 353, 127, 2205}, {-1208, 188, 11}, + { -513, -75, -683}, { -973, 222, -646}, { -616, -843, -388}, + { -950, -1113, -359}, {-1431, -623, -705}, {-1398, -1063, -178}, + { -45, -461, 35}, { -9, -657, -216}, { 127, -1078, 95}, + { -950, -1156, 584}, {-1480, -1494, 449}, { -120, -705, 516}, + { -368, -961, 727}, { -378, -526, 973}, { -793, -614, 676}, + { -801, -755, 1287}, {-1476, -340, 1636}, { -505, -1254, 1543}, + {-1243, -1622, 1532}, { -776, -1477, -655}, {-1151, -1296, -823}, + {-1153, -1672, -1124}, {-1291, -2003, -1702}, { -622, -1283, 57}, + { -471, -1611, 509}, {-1060, -1570, -139}, { -873, -2156, -536}, + {-1716, -2021, -364}, {-2150, -3218, -1291}, {-1248, -1945, -2904}, + {-1215, -2633, -2855}, { 167, -244, 84}, { 349, -412, -217}, + { -40, -352, 632}, { 227, -529, 405}, { 68, -383, -443}, + { 167, -558, -706}, { -275, -854, -14}, { -351, -1089, -449}, + { 341, -72, -289}, { 603, -106, -474}, { 322, -219, -649}, + { 179, -317, -998}, { 450, -291, -996}, { 555, 195, -525}, + { 784, 272, -831}, { -148, -384, -849}, { 82, -536, -1357}, + { 238, -172, -1354}, { 422, -268, -1841}, { 297, -737, -2079}, + { -111, -801, -598}, { 1, -668, -984}, { -131, -818, -1299}, + { -329, -521, -1310}, { -151, -778, -1834}, { -93, -352, -1746}, + { -568, -640, -1821}, { -509, -941, -2183}, { 464, -815, -1250}, + { 79, -1133, -1597}, { -184, -1353, -2123}, { -196, -410, -2427}, + { -192, -833, -2810}, { -259, -1382, -3045}, { -217, 4, -1166}, + { -800, -325, -1219}, { -363, -830, -898}, { -661, -1134, -960}, + { -386, -980, -1501}, { -627, -1159, -1722}, { -903, -829, -855}, + { -685, -829, -1313}, {-1065, -959, -1405}, { 441, 25, -847}, + { 655, -27, -1181}, { 1159, -110, -705}, { 856, 253, -1671}, + { 415, 404, -1}, { 322, 903, -398}, { 670, 499, -292}, + { 803, 591, -610}, { 1144, 591, -814}, { 717, 183, 393}, + { 857, 381, 106}, { 609, 62, -27}, { 792, 198, -325}, + { 735, 805, 88}, { 1142, 812, 78}, { 1028, 366, -292}, + { 1309, 743, -237}, { 1615, 589, -79}, { 1010, 639, -243}, + { 999, 964, -311}, { 1500, 1137, -615}, { 988, 357, 646}, + { 1227, 667, 683}, { 1164, 1565, 894}, { 1392, 2015, 477}, + { 1138, 533, 250}, { 1437, 896, 391}, { 1765, 1118, 99}, + { 1112, 1090, 802}, { 1596, 846, 1134}, { 937, 1161, 279}, + { 1719, 1254, 683}, { 1338, 1086, 35}, { 1419, 1324, 428}, + { 1428, 1524, 40}, { 2108, 1594, 89}, { 1015, 544, 1222}, + { 1121, 925, 1263}, { 1030, 1318, 1485}, { 1295, 789, 1817}, + { 1323, 1272, 1909}, { 1724, 1237, 1803}, { 1797, 1689, 858}, + { 2149, 1367, 1301}, { 2302, 1867, 761}, { 2863, 2351, 1053}, + { 52, 163, -76}, { 230, 309, -492}, { -71, 619, 39}, + { -218, 856, 499}, { -654, 736, -207}, { -535, 1259, 155}, + { -480, 1476, 643}, { 262, 1081, 102}, { 309, 1592, -182}, + { 627, 1629, 534}, { 337, 643, 456}, { 758, 670, 713}, + { 202, 1126, 658}, { 612, 1131, 666}, { 686, 1223, 1136}, + { -131, 377, 525}, { 42, 708, 907}, { 87, 1488, 1035}, + { 432, 2117, 904}, { 137, 981, 1332}, { -447, 1014, 1136}, + { -839, 1793, 1246}, { -559, 297, 198}, { -850, 685, 446}, + {-1273, 632, 826}, { -401, -544, 173}, { -753, -793, 144}, + { -436, -9, 772}, { -115, -243, 1310}, { -670, -269, 374}, + {-1027, -13, 639}, { -887, -81, 1137}, {-1277, -455, 158}, + {-1411, -720, 736}, { 172, 88, 403}, { 386, 255, 756}, + { -500, 522, 910}, { -958, 659, 1388}, { -395, 301, 1344}, + { -356, 768, 1813}, { -613, 841, 2419}, { 445, -122, 252}, + { 629, -87, 723}, { 283, -253, 870}, { 456, -116, 1381}, + { 757, 180, 1059}, { 532, 408, 1509}, { 947, 288, 1806}, + { 1325, 994, 2524}, { 892, 1219, 3023}, { 1397, 1596, 3406}, + { 1143, 1552, 2546}, { 1850, 1433, 2710}, { -10, 134, 1002}, + { 154, 499, 1323}, { 508, 792, 1117}, { 509, 1340, 1616}, + { 762, 862, 1608}, { 787, 740, 2320}, { 794, 1727, 1283}, + { 465, 2108, 1660}, { -120, 1451, 1613}, { -386, 2016, 2169}, + { 891, 1225, 2050}, { 456, 1480, 2185}, { 1493, 1283, 1209}, + { 1397, 1636, 1518}, { 1776, 1738, 1552}, { 1572, 1698, 2141}, + { 1389, 2126, 1271}, { 1959, 2413, 1119}, { 1365, 2892, 1505}, + { 2206, 1971, 1623}, { 2076, 1950, 2280}, { 1717, 2291, 1867}, + { 2366, 2515, 1953}, { 2865, 2838, 2522}, { 2535, 3465, 2011}, + { 3381, 4127, 2638}, { 836, 2667, 2289}, { 1761, 2773, 2337}, + { 1415, 3325, 2911}, { 2354, 3138, 3126}, { 2659, 4192, 4010}, + { 1048, 1786, 1818}, { 1242, 2111, 2240}, { 1512, 2079, 2780}, + { 1573, 2491, 3138}, { 2230, 2377, 2782}, { 416, 1773, 2704}, + { 725, 2336, 3297}, { 1252, 2373, 3978}, { 2094, 2268, 3568}, + { 2011, 2712, 4528}, { 1341, 3507, 3876}, { 1216, 3919, 4922}, + { 1693, 4793, 6012} +}; + +static const int16_t lsp_band1[LSP_CB_SIZE][3] = { + { 0, 0, 0}, {-2114, -1302, 76}, {-2652, -1278, -1368}, + {-2847, -828, -349}, {-3812, -2190, -349}, {-3946, -364, -449}, + {-2725, -4492, -3607}, {-3495, -4764, -1744}, { -51, -756, 84}, + { -153, -1191, 504}, { 108, -1418, 1167}, { -835, -896, 390}, + { -569, -1702, 87}, {-1151, -1818, 933}, {-1826, -2547, 411}, + {-1842, -1818, 1451}, {-2438, -1611, 781}, {-2747, -2477, 1311}, + { -940, 1252, 477}, {-1629, 1688, 602}, {-1202, 617, 280}, + {-1737, 393, 580}, {-1528, 1077, 1199}, {-2165, -161, 1408}, + {-2504, -1087, 2371}, {-3458, -175, 1395}, {-1397, -98, -843}, + {-2252, -177, -1149}, {-1489, -726, -1283}, {-1558, -265, -1744}, + {-1867, -821, -1897}, {-2062, -1516, -2340}, {-2595, -1142, -2861}, + { 170, 46, -819}, { -193, -204, -1151}, { 326, -196, -1532}, + { 780, 329, -816}, { 201, 369, -1243}, { 650, -209, -1060}, + { 1144, -15, -1216}, { 1203, -259, -1867}, { -890, -564, -1430}, + { -638, -852, -1921}, { 177, -739, -1358}, { -261, -526, -1666}, + { 206, -407, -2255}, { 338, -526, -822}, { 421, -1095, -1009}, + { 765, -607, -1408}, { 825, -1295, -2004}, { 357, -905, -1815}, + { -58, -1248, -1588}, { -596, -1436, -2046}, { -73, -1159, -2116}, + { -115, -1382, -2581}, { -160, -1723, -1952}, { -6, -2196, -2954}, + { -649, -1705, -2603}, { -617, -1453, -3282}, { -949, -2019, -3102}, + { -812, 1544, 1937}, {-1854, 574, 2000}, {-1463, 1140, 2649}, + {-2683, 1748, 1452}, {-2486, 2241, 2523}, { 783, 1910, 1435}, + { 581, 2682, 1376}, { 236, 2197, 1885}, { -453, 2943, 2057}, + { -682, 2178, 2565}, {-1342, 3201, 3328}, { -288, -184, 262}, + { 121, -149, -183}, { 758, -412, 206}, { 1038, -204, 853}, + { 1577, -457, 700}, { 937, -640, -567}, { 1508, -528, -1024}, + { -225, -527, -427}, { -564, -1095, -332}, { -742, -353, -186}, + {-1288, -459, 84}, {-1853, -484, -274}, {-1554, -731, 825}, + {-2425, -234, 382}, {-1722, 293, -271}, {-2515, 425, -564}, + {-2599, 818, 464}, { -358, 118, -375}, { -613, 198, -874}, + { -690, 683, -324}, {-1352, 1155, -168}, {-1093, 129, -324}, + {-1184, 611, -858}, { 433, 386, -372}, { -120, 486, -634}, + { 234, 851, -631}, { 602, 128, 46}, { 1099, 410, 159}, + { 715, -145, -424}, { 1198, -85, -593}, { 1390, 367, -358}, + { 1683, 362, -964}, { 1711, 622, 45}, { 2033, 833, -383}, + { 2890, 549, -506}, { 7, 401, 52}, { 72, 811, 415}, + { 566, 668, 41}, { 467, 1218, 130}, { 68, 957, -187}, + { -25, 1649, -103}, { -661, 260, 214}, { -925, -94, 612}, + { -321, -422, 965}, { -788, -672, 1783}, { 400, -673, 779}, + { 741, -595, 1635}, { -161, 307, 657}, { -382, 836, 871}, + { -814, 400, 1223}, { 364, 606, 1247}, { 57, 75, 1571}, + { 151, 471, 2287}, { -81, 1021, 1502}, { 227, 1470, 1097}, + { 658, 1275, 1653}, { 664, 1478, 2377}, { 263, -127, 444}, + { 264, 89, 969}, { 794, 171, 576}, { 821, 186, 1226}, + { 404, 462, 517}, { 339, 918, 794}, { 1280, 1423, 196}, + { 1453, 2019, 365}, { 1615, 1481, 672}, { 2394, 1708, 508}, + { 806, 1238, 573}, { 713, 1158, 1078}, { 1285, 1436, 1232}, + { 1790, 1188, 1141}, { 765, 643, 864}, { 1032, 797, 1279}, + { 900, 563, 1827}, { 1514, 673, 2312}, { 1544, 1129, 3240}, + { 1469, 1050, 1594}, { 1945, 1318, 1988}, { 2397, 2026, 2060}, + { 3538, 2057, 2620}, { 1249, -118, 74}, { 1727, 194, 421}, + { 2078, -50, -463}, { 970, 688, -432}, { 1149, 952, -110}, + { 1254, 1275, -651}, { 1386, 929, 401}, { 1960, 1167, 232}, + { 407, -752, -243}, { 859, -1118, 172}, { -227, -860, -992}, + { -796, -1175, -1380}, { 8, -1282, -388}, { 353, -1781, -1037}, + { -732, -397, -807}, { -853, -28, -1342}, {-1229, -1207, -1959}, + {-1015, -1125, -2543}, {-1452, -1791, -2725}, {-1891, -2416, -3269}, + { -918, -1629, -783}, { -580, -2155, -698}, {-1097, -2364, -96}, + {-1387, -1513, 7}, {-1588, -2076, -664}, {-1473, -2740, -784}, + {-2378, -3149, -56}, {-2856, -2092, -169}, {-3391, -3708, 316}, + {-1176, -890, -614}, {-1944, -1061, -800}, { -299, -1517, -1000}, + { -640, -1850, -1526}, {-1454, -1536, -1233}, {-1890, -1955, -1756}, + {-1086, -1921, -2122}, { -750, -2325, -2260}, {-1325, -2413, -2673}, + {-1114, -2542, -3459}, {-1341, -2901, -3963}, {-1160, -2226, -1393}, + {-1001, -2772, -1573}, {-1594, -2641, -1978}, {-1534, -3046, -2624}, + {-2224, -2196, -675}, {-2807, -3054, -1102}, {-2008, -2840, -1186}, + {-1980, -3332, -1695}, {-1715, -3562, -505}, {-2527, -4000, -1887}, + {-2333, -2734, -2296}, {-3440, -2401, -3211}, {-2008, -3528, -3337}, + {-2247, -3291, -4510}, { -475, 949, 155}, { -149, 1365, 545}, + { -757, 1644, 1083}, { -217, 2053, 1353}, {-1433, 2301, 1462}, + { 495, 1661, 529}, { 10, 2037, 740}, { 2082, 1898, 978}, + { 2831, 2294, 911}, { 842, 793, 420}, { 1223, 1023, 863}, + { 1237, 451, 780}, { 1744, 708, 822}, { 1533, 284, 1384}, + { 2135, 609, 1538}, { 2305, 626, 540}, { 2368, 1187, 955}, + { 2586, 1255, -7}, { 3116, 1131, 726}, { 3431, 1730, 428}, + { 2734, 1648, 1307}, { 2988, 1231, 2010}, { 3523, 2024, 1488}, + { 1034, 1657, 871}, { 1206, 2163, 1036}, { 1807, 2372, 1233}, + { 1808, 1769, 1493}, { 1573, 2332, 1779}, { 1216, 1609, 1866}, + { 1480, 1898, 2513}, { 465, 2708, 2776}, { 771, 3638, 3338}, + { 1869, 2599, 2623}, { 2825, 2745, 2468}, { 2638, 2439, 1585}, + { 2094, 2970, 1308}, { 2022, 3057, 1999}, { 3428, 2912, 1816}, + { 4536, 2974, 2129}, { 1046, 2563, 2086}, { 1363, 3562, 2318}, + { 2511, 1891, 2984}, { 1866, 2306, 3986}, { 3272, 2924, 3682}, + { 3146, 3564, 2272}, { 3592, 3968, 2822}, { 2431, 3369, 3069}, + { 1931, 4709, 3090}, { 2629, 4220, 3986}, { 4639, 4056, 3664}, + { 4035, 5334, 4912} +}; + +static const int16_t lsp_band2[LSP_CB_SIZE][4] = { + { 0, 0, 0, 0}, { 601, 512, -542, 334}, + { 428, 1087, -484, -132}, { 652, 622, -391, -572}, + { 378, 799, 141, -860}, { 1040, 409, 112, -554}, + { 1123, 670, -75, -847}, { 1421, 494, -315, -1095}, + { 787, 1001, 114, -460}, { 988, 1672, 216, -681}, + { 1007, 1241, -132, -1247}, { 1073, 399, 186, -5}, + { 1262, 193, -694, -129}, { 325, 196, 51, -641}, + { 861, -59, 350, -458}, { 1261, 567, 586, -346}, + { 1532, 885, 210, -517}, { 2027, 937, 113, -792}, + { 1383, 1064, 334, 38}, { 1964, 1468, 459, 133}, + { 2062, 1186, -98, -121}, { 2577, 1445, 506, -373}, + { 2310, 1682, -2, -960}, { 2876, 1939, 765, 138}, + { 3581, 2360, 649, -414}, { 219, 176, -398, -309}, + { 434, -78, -435, -880}, { -344, 301, 265, -552}, + { -915, 470, 657, -380}, { 419, -432, -163, -453}, + { 351, -953, 8, -562}, { 789, -43, 20, -958}, + { 302, -594, -352, -1159}, { 1040, 108, -668, -924}, + { 1333, 210, -1217, -1663}, { 483, 589, -350, -1140}, + { 1003, 824, -802, -1184}, { 745, 58, -589, -1443}, + { 346, 247, -915, -1683}, { 270, 796, -720, -2043}, + { 1208, 722, -222, -193}, { 1486, 1180, -412, -672}, + { 1722, 179, -69, -521}, { 2047, 860, -666, -1410}, + { -146, 222, -281, -805}, { -189, 90, -114, -1307}, + { -152, 1086, -241, -764}, { -439, 733, -601, -1302}, + { -833, -167, -351, -601}, { -856, -422, -411, -1059}, + { -747, -355, -582, -1644}, { -837, 210, -916, -1144}, + {-1800, 32, -878, -1687}, { -48, -23, -1146, 52}, + { -350, -409, -1656, -364}, { 265, -728, -858, -577}, + { 458, -247, -1141, -997}, { 691, -407, -1988, -1161}, + { -66, -104, -705, -1249}, { -431, -93, -1191, -1844}, + { 203, -732, -1000, -1693}, { 10, -832, -1846, -1819}, + { 493, -128, -1436, -1768}, { 488, -311, -1730, -2540}, + { -653, -532, -1150, -1172}, {-1086, -289, -1706, -1533}, + { -699, -1205, -1216, -1766}, {-1032, -1481, -2074, -1523}, + { -721, -1220, -2277, -2600}, { 12, -539, -1484, -1131}, + { -40, -911, -2106, -441}, { -471, -484, -2267, -1549}, + { -141, -988, -3006, -1721}, {-1545, -2102, -583, 342}, + {-1383, -2772, -386, -13}, {-2118, -2589, -1205, 72}, + {-2147, -3231, -965, 390}, {-2949, -3300, -621, 637}, + {-3907, -4138, -865, 803}, {-1287, -845, -375, -548}, + {-1416, -1169, -487, -1277}, {-1400, -1690, -1027, -418}, + {-2018, -1909, -1188, -1260}, {-1418, -2222, -2029, -128}, + {-2067, -2998, -2693, -310}, { -950, -1028, -1538, 185}, + {-1616, -915, -2205, -549}, { 19, -821, -1145, 352}, + { 184, -1175, -1356, -627}, { -547, -1088, -1661, -911}, + { -216, -1502, -2197, -948}, { -795, -1306, -2374, -451}, + { -924, -1889, -2796, -680}, { -600, -1614, -3609, -885}, + {-2392, -2528, 319, 303}, {-2908, -2095, -310, 573}, + {-3460, -2141, 49, -113}, {-2231, -448, 675, -146}, + {-2805, -532, 1231, 479}, {-2684, -486, -200, 611}, + {-3525, -971, -198, 704}, {-3707, 173, 349, 254}, + {-4734, -1447, -34, 880}, { 777, -512, 114, -10}, + { 1250, -66, 442, -5}, { 604, 613, 452, -352}, + { 1224, 777, 675, -1014}, {-1372, -79, -1208, -238}, + {-2389, -17, -1157, -818}, {-1504, -673, -1133, -1060}, + {-1984, -799, -2005, -1973}, {-2037, -798, -1068, -105}, + {-3190, -899, -1817, -194}, { -156, -886, 394, -318}, + { -258, -1283, 551, 202}, { -536, -1729, 910, 331}, + { -847, -1109, 795, -163}, {-1171, -1128, 715, 519}, + {-1080, -1319, 1685, 668}, {-1000, -1921, 96, 211}, + {-1487, -2148, 831, 174}, {-1139, -374, 414, -4}, + {-1517, -1383, 396, -352}, {-1012, 439, -59, -967}, + {-1812, 706, -440, -1030}, {-1971, -329, -34, -827}, + {-2472, -1588, -151, -606}, {-2161, 374, -281, 76}, + {-3012, 231, -15, -690}, { 1104, 566, 721, 209}, + { 1685, 564, 383, 98}, { 1898, 750, 792, -97}, + { 556, -64, 561, -93}, { 876, 162, 913, -22}, + { 961, 675, 1296, 140}, { 756, -396, 851, 544}, + { 360, -303, 1341, 396}, { 878, -22, 1464, 863}, + { -309, -273, 642, -129}, { -686, -82, 842, 454}, + { -5, -47, 1069, 998}, { -94, 967, 1277, 298}, + { -489, 385, 1473, 746}, { -369, -717, 1333, 242}, + { 281, -993, 1726, 924}, { 464, 601, 1575, 1376}, + { -250, 206, 2339, 1175}, { -438, 377, -597, -285}, + {-1020, 787, -790, -287}, { -458, -410, 215, 295}, + { -589, -860, -121, 797}, {-1175, 122, -437, 466}, + {-1480, -121, 367, 924}, { 234, 323, 770, -555}, + { 145, 30, 996, 26}, { 66, 849, 93, -145}, + { -117, 1261, 474, -399}, {-1495, 1051, 218, -506}, + {-1390, 694, 994, 88}, { 616, 7, 78, 304}, + { 1060, 52, -62, 835}, { 833, 454, 649, 1359}, + { -770, 464, 47, 93}, { -574, 1199, -39, 379}, + { 114, -98, 488, 485}, { 727, 244, 606, 696}, + { -76, 455, 671, 546}, { -565, -13, 145, 819}, + { -376, 569, 448, 1128}, { 218, 122, 265, 1167}, + { 230, 738, 932, 1003}, { 138, 477, 36, 450}, + { 404, 787, -73, 1000}, { 497, 1259, 387, 1231}, + { 17, 207, 195, -79}, { 562, 358, 53, -158}, + { 493, 387, 478, 189}, { 678, 831, 640, 558}, + { -197, 523, 613, 57}, { 429, 894, 769, 111}, + { 67, 1174, 568, 511}, { 1242, 824, 251, 840}, + { 1419, 1074, 864, 481}, { 924, 1474, 669, 724}, + { 1539, 1879, 654, 1590}, { 445, 337, 1111, 541}, + { 472, 1421, 1264, 1094}, { 794, 735, 1103, 668}, + { 1055, 863, 1192, 1020}, { 778, 1105, 806, 1798}, + { 1052, 1527, 1587, 2151}, { 881, 1552, 1265, 391}, + { 726, 872, 1812, 601}, { 1469, 280, 1008, 616}, + { 1403, 577, 1803, 1244}, { 1650, 1314, 1148, 1072}, + { 1297, 1669, 1911, 1026}, { 2093, 1044, 2115, 1189}, + { 1644, 1961, 2587, 1512}, { 25, -315, -9, -106}, + { 290, -339, 428, -444}, { -68, -783, 735, 772}, + { 245, -555, 468, 47}, { 334, -895, 814, 146}, + { 235, 368, -964, -959}, { -203, 315, -1566, -1217}, + { 801, 17, -276, -354}, { 894, -495, -789, -635}, + { 716, 291, -1189, -357}, { 560, -260, -733, -2}, + { 679, -508, -1429, 211}, { -51, -62, -428, 557}, + { 322, -638, -211, 614}, { -878, -1057, -84, -71}, + { -388, -1415, -167, -318}, { -754, -1574, 214, -539}, + {-1419, -2004, -92, -787}, { -47, -856, -347, -255}, + { 23, -1211, -173, 320}, { -658, -487, -893, 353}, + { -783, -1587, -584, 507}, {-1420, -859, -378, 441}, + {-2095, -1491, -137, 439}, { -321, -1450, -1288, -12}, + { -359, -2113, -553, -8}, { -831, -1918, -1561, 32}, + {-1014, -2487, -1359, -939}, { -475, -311, -169, -236}, + { -907, -426, 276, -611}, { -96, -400, 50, -710}, + { -426, -1022, -10, -985}, { -197, -258, -744, -575}, + { -611, -930, -771, -394}, { -267, -776, -612, -939}, + { -256, -1346, -802, -1122}, { -796, -1570, -825, -754}, + { 712, 876, 141, 227}, { 981, 1509, 85, 124}, + { 1462, 1228, 979, -39}, { 1734, 999, 1481, 440}, + { 2293, 1116, 769, 440}, { 2504, 1480, 1241, 356}, + { 2474, 1909, 1558, 810}, { 917, 1134, 607, -134}, + { 509, 1809, 781, -123}, { 1712, 1506, 559, -423}, + { 2037, 2317, 726, -155}, { 3031, 2676, 1203, 331}, + { 3664, 3274, 1768, 531}, { 1610, 1839, 867, 183}, + { 1774, 1972, 1538, 97}, { 1822, 2158, 1282, 659}, + { 2222, 2758, 1818, 900}, { 3251, 2124, 1723, 996}, + { 3633, 2336, 2408, 1453}, { 2923, 3517, 2567, 1318}, +}; + +/** + * Used for the coding/decoding of the pulses positions + * for the MP-MLQ codebook + */ +static const int32_t combinatorial_table[PULSE_MAX][SUBFRAME_LEN/GRID_SIZE] = { + {118755, 98280, 80730, 65780, 53130, + 42504, 33649, 26334, 20349, 15504, + 11628, 8568, 6188, 4368, 3003, + 2002, 1287, 792, 462, 252, + 126, 56, 21, 6, 1, + 0, 0, 0, 0, 0}, + + { 23751, 20475, 17550, 14950, 12650, + 10626, 8855, 7315, 5985, 4845, + 3876, 3060, 2380, 1820, 1365, + 1001, 715, 495, 330, 210, + 126, 70, 35, 15, 5, + 1, 0, 0, 0, 0}, + + { 3654, 3276, 2925, 2600, 2300, + 2024, 1771, 1540, 1330, 1140, + 969, 816, 680, 560, 455, + 364, 286, 220, 165, 120, + 84, 56, 35, 20, 10, + 4, 1, 0, 0, 0}, + + { 406, 378, 351, 325, 300, + 276, 253, 231, 210, 190, + 171, 153, 136, 120, 105, + 91, 78, 66, 55, 45, + 36, 28, 21, 15, 10, + 6, 3, 1, 0, 0}, + + { 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, + 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, + 4, 3, 2, 1, 0}, + + { 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1}, +}; + +static const int16_t pitch_contrib[340] = { + 60, 0, 0, 2489, 60, 0, 0, 5217, + 1, 6171, 0, 3953, 0, 10364, 1, 9357, + -1, 8843, 1, 9396, 0, 5794, -1, 10816, + 2, 11606, -2, 12072, 0, 8616, 1, 12170, + 0, 14440, 0, 7787, -1, 13721, 0, 18205, + 0, 14471, 0, 15807, 1, 15275, 0, 13480, + -1, 18375, -1, 0, 1, 11194, -1, 13010, + 1, 18836, -2, 20354, 1, 16233, -1, 0, + 60, 0, 0, 12130, 0, 13385, 1, 17834, + 1, 20875, 0, 21996, 1, 0, 1, 18277, + -1, 21321, 1, 13738, -1, 19094, -1, 20387, + -1, 0, 0, 21008, 60, 0, -2, 22807, + 0, 15900, 1, 0, 0, 17989, -1, 22259, + 1, 24395, 1, 23138, 0, 23948, 1, 22997, + 2, 22604, -1, 25942, 0, 26246, 1, 25321, + 0, 26423, 0, 24061, 0, 27247, 60, 0, + -1, 25572, 1, 23918, 1, 25930, 2, 26408, + -1, 19049, 1, 27357, -1, 24538, 60, 0, + -1, 25093, 0, 28549, 1, 0, 0, 22793, + -1, 25659, 0, 29377, 0, 30276, 0, 26198, + 1, 22521, -1, 28919, 0, 27384, 1, 30162, + -1, 0, 0, 24237, -1, 30062, 0, 21763, + 1, 30917, 60, 0, 0, 31284, 0, 29433, + 1, 26821, 1, 28655, 0, 31327, 2, 30799, + 1, 31389, 0, 32322, 1, 31760, -2, 31830, + 0, 26936, -1, 31180, 1, 30875, 0, 27873, + -1, 30429, 1, 31050, 0, 0, 0, 31912, + 1, 31611, 0, 31565, 0, 25557, 0, 31357, + 60, 0, 1, 29536, 1, 28985, -1, 26984, + -1, 31587, 2, 30836, -2, 31133, 0, 30243, + -1, 30742, -1, 32090, 60, 0, 2, 30902, + 60, 0, 0, 30027, 0, 29042, 60, 0, + 0, 31756, 0, 24553, 0, 25636, -2, 30501, + 60, 0, -1, 29617, 0, 30649, 60, 0, + 0, 29274, 2, 30415, 0, 27480, 0, 31213, + -1, 28147, 0, 30600, 1, 31652, 2, 29068, + 60, 0, 1, 28571, 1, 28730, 1, 31422, + 0, 28257, 0, 24797, 60, 0, 0, 0, + 60, 0, 0, 22105, 0, 27852, 60, 0, + 60, 0, -1, 24214, 0, 24642, 0, 23305, + 60, 0, 60, 0, 1, 22883, 0, 21601, + 60, 0, 2, 25650, 60, 0, -2, 31253, + -2, 25144, 0, 17998 +}; + +/** + * Number of non-zero pulses in the MP-MLQ excitation + */ +static const int8_t pulses[4] = {6, 5, 6, 5}; + +/** + * Size of the MP-MLQ fixed excitation codebooks + */ +static const int32_t max_pos[4] = {593775, 142506, 593775, 142506}; + +static const int16_t fixed_cb_gain[GAIN_LEVELS] = { + 1, 2, 3, 4, 6, 9, 13, 18, + 26, 38, 55, 80, 115, 166, 240, 348, + 502, 726, 1050, 1517, 2193, 3170, 4582, 6623, +}; + +static const int16_t adaptive_cb_gain85[85 * 20] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 800, 1496, 167, -256, + -338, -39, -136, -1, -4, -6, -73, -8, + -15, 12, 23, 2, 16, 30, 3, -5, + -462, -686, 493, 2575, 311, -13, -28, -14, + -404, -5, -19, 13, 20, 72, 107, -77, + 8, 13, -9, -48, 1483, 144, 784, 928, + 1243, -134, -1, -37, -52, -94, -13, -71, + -6, -84, -8, -44, -112, -10, -59, -70, + -77, 275, 3522, 1056, -1254, 0, -4, -757, + -68, -95, 1, 16, -59, 4, -17, -227, + -5, 21, 269, 80, -125, -40, -264, 381, + 5027, 0, 0, -4, -8, -1542, 0, -2, + 0, 2, 0, 6, 38, 12, 81, -117, + 138, 332, 2215, 2574, 1339, -1, -6, -299, + -404, -109, -2, -18, -44, -21, -52, -348, + -11, -27, -181, -210, 3685, 2883, -887, 866, + -1639, -828, -507, -48, -45, -164, -648, 199, + 156, -194, -152, 46, 368, 288, -88, 86, + 1396, 2146, 2235, 345, 942, -118, -281, -305, + -7, -54, -182, -190, -292, -29, -45, -47, + -80, -123, -128, -19, 13, 4475, 3549, -804, + -655, 0, -1222, -768, -39, -26, -3, -2, + -969, 0, 219, 174, 0, 179, 141, -32, + -724, 254, 242, 6049, 2462, -32, -3, -3, + -2233, -370, 11, 10, -3, 267, -94, -89, + 108, -38, -36, -909, 626, -1713, 6121, 4561, + -1061, -23, -179, -2287, -1270, -68, 65, -233, + 640, -174, 477, -1704, 40, -111, 396, 295, + -350, 1391, 7985, 511, -405, -7, -118, -3892, + -15, -10, 29, 170, -678, 10, -43, -249, + -8, 34, 197, 12, 3144, -529, 608, 2530, + 3878, -603, -17, -22, -390, -918, 101, -116, + 19, -485, 81, -93, -744, 125, -144, -599, + 2589, -689, 3045, 5603, -404, -409, -29, -566, + -1916, -10, 108, -481, 128, -885, 235, -1041, + 63, -17, 75, 138, 3107, 513, 1374, -3594, + -4922, -589, -16, -115, -788, -1478, -97, -260, + -43, 681, 112, 301, 933, 154, 413, -1079, + 2468, 6010, 1107, -390, 1961, -372, -2204, -74, + -9, -234, -905, -166, -406, 58, 143, 26, + -295, -719, -132, 46, 4773, 2766, 2368, 4862, + -4044, -1390, -467, -342, -1443, -998, -806, -690, + -399, -1416, -821, -702, 1178, 682, 584, 1200, + 1665, -1879, 1443, 1701, 8562, -169, -215, -127, + -176, -4475, 190, -146, 165, -172, 195, -149, + -870, 982, -754, -889, 2716, 9011, -1007, 755, + -1785, -450, -4956, -61, -34, -194, -1493, 167, + 554, -125, -415, 46, 296, 982, -109, 82, + -2727, 7548, 1285, 938, 3420, -453, -3478, -100, + -53, -714, 1256, 213, -592, 156, -432, -73, + 569, -1576, -268, -196, 3677, 882, 4050, 1202, + 2323, -825, -47, -1001, -88, -329, -198, -909, + -218, -269, -64, -297, -521, -125, -574, -170, + 2046, -753, 122, 10102, 603, -255, -34, 0, + -6229, -22, 94, -15, 5, -1261, 464, -75, + -75, 27, -4, -372, 449, -1815, 10690, 3870, + -527, -12, -201, -6976, -914, -16, 49, -293, + 1184, -106, 428, -2525, 14, -58, 344, 124, + -941, 2352, 5049, 3650, 2637, -54, -337, -1556, + -813, -424, 135, 290, -725, 209, -524, -1125, + 151, -378, -812, -587, -1879, 796, 3117, 9569, + -404, -215, -38, -593, -5589, -9, 91, 357, + -151, 1097, -464, -1821, -46, 19, 76, 236, + -1715, 2043, -2096, 9946, 4001, -179, -254, -268, + -6038, -977, 213, -219, 261, 1041, -1240, 1272, + 418, -498, 511, -2429, -5772, -618, -3921, 284, + -3155, -2033, -23, -938, -4, -607, -218, -1381, + -148, 100, 10, 68, -1111, -119, -755, 54, + 382, 4748, 8003, -2064, 2198, -8, -1376, -3909, + -260, -294, -110, -186, -2319, 48, 598, 1008, + -51, -637, -1073, 277, -867, 3015, 11926, -1675, + 947, -45, -555, -8681, -171, -54, 159, 631, + -2195, -88, 308, 1219, 50, -174, -690, 96, + -4933, -432, 6757, 3771, 1352, -1485, -11, -2786, + -867, -111, -130, 2034, 178, 1135, 99, -1555, + 407, 35, -557, -311, 152, 9726, 4231, -1928, + 1490, -1, -5774, -1092, -226, -135, -90, -39, + -2511, 17, 1144, 498, -13, -884, -384, 175, + 2512, 193, 9033, 5361, -3148, -385, -2, -4980, + -1754, -605, -29, -1385, -106, -822, -63, -2956, + 482, 37, 1735, 1030, 8464, 2844, 12, 549, + 2132, -4373, -493, 0, -18, -277, -1469, -6, + -2, -284, -95, 0, -1101, -370, -1, -71, + 2141, -2602, 7166, 9046, -1350, -279, -413, -3134, + -4994, -111, 340, -936, 1138, -1182, 1436, -3957, + 176, -214, 590, 745, -244, 278, 13307, 1227, + -161, -3, -4, -10808, -91, -1, 4, 198, + -226, 18, -20, -997, -2, 2, 131, 12, + -1947, 8217, 6269, 917, -2559, -231, -4121, -2399, + -51, -399, 976, 745, -3144, 108, -460, -350, + -304, 1283, 979, 143, -1810, 2061, -2781, 6056, + 10058, -200, -259, -472, -2238, -6174, 227, -307, + 349, 669, -761, 1028, 1111, -1265, 1707, -3717, + 7827, 9161, -3409, 2473, -1510, -3739, -5122, -709, + -373, -139, -4376, 1628, 1906, -1181, -1382, 514, + 721, 844, -314, 228, -1430, 8313, 9541, -2955, + 1626, -124, -4218, -5556, -533, -161, 725, 832, + -4841, -257, 1499, 1721, 142, -825, -947, 293, + 2819, -4247, 5391, 8673, 2756, -485, -1101, -1774, + -4591, -463, 730, -927, 1397, -1492, 2248, -2854, + -474, 714, -907, -1459, 141, 14552, 690, 257, + -112, -1, -12926, -29, -4, 0, -125, -5, + -613, -2, -228, -10, 0, 99, 4, 1, + 11938, -1859, 1806, -962, -884, -8699, -211, -199, + -56, -47, 1355, -1316, 205, 701, -109, 106, + 644, -100, 97, -51, 3728, 1982, 2264, 4584, + 3131, -848, -239, -312, -1282, -598, -451, -515, + -273, -1043, -554, -633, -712, -378, -432, -876, + -1181, 766, 720, 14303, -216, -85, -35, -31, + -12486, -2, 55, 51, -33, 1031, -668, -628, + -15, 10, 9, 189, -4385, 4826, 10112, 1569, + 3388, -1173, -1421, -6242, -150, -700, 1291, 2706, + -2979, 420, -462, -969, 906, -998, -2091, -324, + -448, 1932, 15591, -1842, 657, -12, -227, -14837, + -207, -26, 52, 427, -1838, -50, 217, 1753, + 18, -77, -626, 74, -4141, 1844, 3962, 5517, + 6220, -1046, -207, -958, -1858, -2361, 466, 1001, + -446, 1394, -621, -1334, 1572, -700, -1504, -2094, + 729, -2299, 14755, 3657, -952, -32, -322, -13288, + -816, -55, 102, -656, 2071, -162, 513, -3294, + 42, -133, 857, 212, -1385, 5801, 13339, -3137, + 1344, -117, -2054, -10861, -600, -110, 490, 1127, + -4723, -265, 1111, 2554, 113, -476, -1094, 257, + 4710, 9661, 1073, -2467, 3274, -1354, -5697, -70, + -371, -654, -2777, -308, -633, 709, 1455, 161, + -941, -1930, -214, 493, 1843, -3624, 12422, 6898, + -1559, -207, -802, -9419, -2904, -148, 407, -1397, + 2748, -775, 1526, -5230, 175, -344, 1182, 656, + 1433, 2394, 2507, 1380, 8780, -125, -349, -383, + -116, -4705, -209, -219, -366, -120, -201, -211, + -768, -1283, -1343, -740, -1712, 12915, 5883, -2197, + 991, -179, -10181, -2112, -294, -60, 1350, 615, + -4638, -229, 1732, 789, 103, -781, -356, 133, + 15072, 2158, -1245, 910, -496, -13865, -284, -94, + -50, -15, -1986, 1145, 164, -837, -119, 69, + 456, 65, -37, 27, 4655, 7319, 4916, 586, + -3381, -1322, -3270, -1475, -20, -697, -2079, -1396, + -2196, -166, -261, -175, 960, 1510, 1014, 120, + 1191, -2140, 5120, 13498, -1418, -86, -279, -1600, + -11121, -122, 155, -372, 669, -981, 1763, -4218, + 103, -185, 443, 1168, -1530, -817, 8191, 9632, + -1452, -143, -40, -4095, -5663, -128, -76, 765, + 408, 900, 480, -4815, -135, -72, 726, 854, + -3236, 607, 1696, -2106, 11485, -639, -22, -175, + -270, -8051, 119, 335, -62, -416, 78, 218, + 2268, -425, -1189, 1476, 3203, -1903, -837, 9679, + 7057, -626, -221, -42, -5718, -3039, 372, 163, + -97, -1892, 1124, 494, -1380, 819, 360, -4169, + 213, -655, 17015, 620, -384, -2, -26, -17671, + -23, -9, 8, -221, 681, -8, 24, -644, + 5, -15, 399, 14, 5088, 35, -3339, 3726, + 8488, -1580, 0, -680, -847, -4397, -10, 1037, + 7, -1157, -8, 759, -2636, -18, 1730, -1930, + -988, 1454, -2688, 15039, 2682, -59, -129, -441, + -13805, -439, 87, -162, 238, 907, -1335, 2467, + 161, -238, 440, -2462, -4865, -2842, -53, 5495, + 6523, -1445, -493, 0, -1843, -2597, -844, -16, + -9, 1632, 953, 18, 1937, 1131, 21, -2188, + 3076, 15069, -2914, 1810, -971, -577, -13860, -518, + -200, -57, -2829, 547, 2680, -339, -1665, 322, + 182, 893, -172, 107, 1311, 5355, 11054, 2299, + -3654, -105, -1750, -7458, -322, -814, -428, -885, + -3613, -184, -751, -1551, 292, 1194, 2465, 512, + 4035, 5619, 4618, 1815, 1912, -994, -1927, -1301, + -201, -223, -1384, -1137, -1583, -447, -622, -511, + -471, -656, -539, -211, -2131, 2754, -4501, 12879, + 7432, -277, -463, -1236, -10124, -3371, 358, -585, + 756, 1675, -2165, 3538, 967, -1249, 2042, -5842, + 5618, -515, 3219, -4149, 4857, -1926, -16, -632, + -1050, -1440, 176, -1104, 101, 1422, -130, 815, + -1666, 152, -954, 1230, 1838, -1709, 1139, 16867, + 716, -206, -178, -79, -17366, -31, 191, -127, + 118, -1892, 1759, -1173, -80, 74, -49, -737, + 1978, -3845, 10050, 11854, -2492, -238, -902, -6164, + -8576, -379, 464, -1213, 2358, -1431, 2782, -7271, + 301, -585, 1529, 1803, -2600, 11246, 11289, -3647, + 1463, -412, -7720, -7778, -812, -130, 1784, 1791, + -7749, -578, 2504, 2513, 232, -1004, -1008, 325, + 3442, 907, 2725, 8970, 3638, -723, -50, -453, + -4911, -808, -190, -572, -150, -1884, -496, -1492, + -764, -201, -605, -1992, -126, 17498, 3481, -2003, + 1090, 0, -18689, -739, -244, -72, 135, 26, + -3717, -15, 2139, 425, 8, -1165, -231, 133, + -1814, 1048, -2164, 4070, 16272, -200, -67, -285, + -1011, -16160, 116, -239, 138, 450, -260, 537, + 1801, -1041, 2149, -4042, 9354, 12580, -1883, 962, + -617, -5341, -9660, -216, -56, -23, -7183, 1075, + 1446, -549, -738, 110, 352, 474, -71, 36, + 1708, 4199, 7387, 6335, 1003, -178, -1076, -3330, + -2449, -61, -437, -770, -1893, -660, -1623, -2856, + -104, -257, -452, -388, -2624, 5623, 17310, -2353, + 592, -420, -1930, -18288, -338, -21, 900, 2772, + -5941, -376, 807, 2486, 94, -203, -625, 85, + 1211, -850, 1193, -1926, 15992, -89, -44, -86, + -226, -15609, 62, -88, 61, 142, -100, 140, + -1182, 830, -1165, 1880, 3983, -2054, 11506, -19, + 3622, -968, -257, -8080, 0, -801, 499, -2797, + 1442, 4, -2, 13, -880, 454, -2544, 4, + -786, -1354, 16092, 7246, -1665, -37, -111, -15805, + -3205, -169, -65, 772, 1330, 348, 599, -7117, + -80, -137, 1636, 736, -4316, -511, 6674, 11665, + 4633, -1137, -15, -2719, -8305, -1310, -134, 1758, + 208, 3073, 364, -4752, 1220, 144, -1887, -3299, + 7912, 4557, 1937, 1885, 7037, -3821, -1267, -229, + -216, -3022, -2200, -935, -538, -910, -524, -222, + -3398, -1957, -832, -809, 3434, 2967, 5867, 8196, + 8766, -720, -537, -2101, -4100, -4690, -622, -1230, + -1062, -1718, -1484, -2935, -1837, -1588, -3139, -4385, + 5881, 9176, 8119, 3934, 3355, -2111, -5139, -4023, + -944, -687, -3294, -2914, -4547, -1412, -2203, -1949, + -1204, -1879, -1662, -805 +}; + +static const int16_t adaptive_cb_gain170[170 * 20] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 776, 212, 715, 670, + 809, -36, -2, -31, -27, -39, -10, -33, + -9, -31, -8, -29, -38, -10, -35, -33, + 1296, 1316, -168, -320, -815, -102, -105, -1, + -6, -40, -104, 13, 13, 25, 25, -3, + 64, 65, -8, -15, -589, 680, 2478, 308, + -596, -21, -28, -375, -5, -21, 24, 89, + -102, 11, -12, -46, -21, 24, 90, 11, + -735, -487, -5, 2948, 468, -33, -14, 0, + -530, -13, -21, 0, 0, 132, 87, 0, + 21, 13, 0, -84, 1042, 1730, 1068, 333, + 626, -66, -182, -69, -6, -23, -110, -67, + -112, -21, -35, -21, -39, -66, -40, -12, + 486, -769, 4074, 2825, -1107, -14, -36, -1013, + -487, -74, 22, -120, 191, -83, 132, -702, + 32, -52, 275, 191, 1521, -767, -124, 4320, + 1026, -141, -35, 0, -1139, -64, 71, 11, + -5, -401, 202, 32, -95, 48, 7, -270, + 2425, 1267, 3439, -91, -1166, -359, -98, -722, + 0, -83, -187, -509, -266, 13, 7, 19, + 172, 90, 244, -6, -1251, 975, 173, 4039, + 2005, -95, -58, -1, -996, -245, 74, 13, + -10, 308, -240, -42, 153, -119, -21, -494, + 1820, 632, 1322, 2062, 1031, -202, -24, -106, + -259, -64, -70, -146, -51, -229, -79, -166, + -114, -39, -83, -129, -447, 4904, 244, -315, + -2038, -12, -1467, -3, -6, -253, 134, 6, + -73, -8, 94, 4, -55, 610, 30, -39, + -208, -1102, 463, -448, 5653, -2, -74, -13, + -12, -1950, -14, 5, 31, -5, -30, 12, + 71, 380, -159, 154, 4739, 2600, -1864, 856, + -1554, -1371, -412, -212, -44, -147, -752, 539, + 295, -247, -135, 97, 449, 246, -176, 81, + 1894, 3533, 35, -26, 2145, -219, -762, 0, + 0, -280, -408, -4, -7, 3, 5, 0, + -248, -462, -4, 3, -2699, 1841, 4072, 2443, + 1582, -444, -207, -1012, -364, -152, 303, 670, + -457, 402, -274, -607, 260, -177, -393, -236, + -844, 3358, 6106, -1059, -537, -43, -688, -2275, + -68, -17, 173, 314, -1251, -54, 217, 395, + -27, 110, 200, -34, 1251, 1016, 3020, 2210, + 1445, -95, -63, -556, -298, -127, -77, -230, + -187, -168, -137, -407, -110, -89, -266, -194, + 2099, 2277, 4038, 3533, -2870, -269, -316, -995, + -762, -503, -291, -517, -561, -452, -491, -871, + 367, 399, 707, 619, 400, -1114, 8516, 2422, + -1117, -9, -75, -4426, -358, -76, 27, -208, + 579, -59, 164, -1259, 27, -75, 580, 165, + -4398, -2011, 3912, -2407, 2258, -1180, -247, -934, + -353, -311, -540, 1050, 480, -646, -295, 575, + 606, 277, -539, 331, 1767, -1447, 4240, 6160, + -757, -190, -127, -1097, -2316, -35, 156, -457, + 374, -664, 544, -1594, 81, -66, 195, 284, + 1594, -1463, 1035, 6938, 1920, -155, -130, -65, + -2938, -225, 142, -100, 92, -675, 619, -438, + -186, 171, -121, -813, -562, 4716, 4085, -591, + 2421, -19, -1357, -1018, -21, -357, 162, 140, + -1175, -20, 170, 147, 83, -696, -603, 87, + 1552, 8778, -935, 354, -1424, -147, -4703, -53, + -7, -123, -831, 88, 501, -33, -189, 20, + 134, 763, -81, 30, 4831, -4431, 41, -1479, + -2976, -1424, -1198, 0, -133, -540, 1306, -12, + 11, 436, -400, 3, 877, -804, 7, -268, + 2090, 1192, 1006, 1645, 4853, -266, -86, -61, + -165, -1437, -152, -128, -73, -210, -119, -101, + -619, -353, -298, -487, 2386, 5712, 1426, -94, + 1350, -347, -1991, -124, 0, -111, -832, -207, + -497, 13, 32, 8, -196, -470, -117, 7, + -1349, 1091, 1659, 8891, 313, -111, -72, -168, + -4825, -5, 89, 136, -110, 732, -592, -900, + 25, -20, -31, -170, 9980, 916, -381, -808, + 88, -6080, -51, -8, -39, 0, -558, 232, + 21, 492, 45, -18, -53, -4, 2, 4, + 2338, -1031, -248, 3928, 6484, -333, -64, -3, + -942, -2566, 147, 35, -15, -560, 247, 59, + -925, 408, 98, -1555, 6166, -1240, -337, 3672, + -1277, -2320, -93, -6, -823, -99, 466, 126, + -25, -1382, 278, 75, 480, -96, -26, 286, + 4377, -132, -2588, 1701, 4865, -1169, -1, -409, + -176, -1444, 35, 691, -20, -454, 13, 268, + -1299, 39, 768, -505, 2594, 3295, 3944, 1481, + 682, -410, -662, -949, -133, -28, -521, -624, + -793, -234, -297, -356, -108, -137, -164, -61, + 4151, 624, 815, 4485, 2229, -1052, -23, -40, + -1228, -303, -158, -206, -31, -1136, -170, -223, + -565, -84, -111, -610, -3575, -361, 4924, 2791, + 4698, -780, -7, -1480, -475, -1347, -78, 1074, + 108, 609, 61, -839, 1025, 103, -1412, -800, + -2518, 3791, 8623, 315, 2465, -387, -877, -4538, + -6, -370, 582, 1325, -1995, 48, -73, -166, + 378, -570, -1297, -47, -691, 2989, 9957, -421, + -1142, -29, -545, -6051, -10, -79, 126, 420, + -1817, -17, 76, 256, -48, 208, 694, -29, + -1918, 104, -3190, -3410, -4440, -224, 0, -621, + -709, -1203, 12, -373, 20, -399, 21, -664, + -519, 28, -864, -924, -3359, -1668, 1854, 6939, + 1430, -688, -169, -209, -2939, -124, -341, 380, + 188, 1422, 706, -785, 293, 145, -161, -606, + 42, 9706, 3164, -952, 907, 0, -5750, -611, + -55, -50, -25, -8, -1874, 2, 564, 183, + -2, -537, -175, 52, 1607, 785, 2862, 4327, + 3307, -157, -37, -500, -1143, -667, -77, -280, + -137, -424, -207, -756, -324, -158, -577, -873, + 6801, 3416, 2227, 1682, -3217, -2823, -712, -302, + -172, -631, -1418, -924, -464, -698, -350, -228, + 1335, 670, 437, 330, 3459, 3898, 364, 7841, + -2640, -730, -927, -8, -3753, -425, -823, -76, + -86, -1655, -1865, -174, 557, 628, 58, 1263, + -5902, -3458, -2465, -1886, 4334, -2126, -730, -371, + -217, -1146, -1245, -888, -520, -679, -398, -283, + 1561, 915, 652, 499, -3710, 1133, 7849, 3443, + -215, -840, -78, -3760, -723, -2, 256, 1777, + -543, 779, -238, -1649, -48, 14, 103, 45, + 4132, 2828, 2, -4212, -4116, -1042, -488, 0, + -1083, -1034, -713, 0, 0, 1062, 727, 0, + 1038, 710, 0, -1058, 5875, 8496, -1796, 1376, + -1786, -2107, -4406, -197, -115, -194, -3047, 644, + 931, -493, -713, 150, 640, 926, -195, 150, + 3143, 3483, 3546, -793, 4489, -603, -740, -767, + -38, -1230, -668, -680, -754, 152, 168, 171, + -861, -954, -971, 217, 2845, 7965, 3695, -5432, + 3978, -494, -3873, -833, -1801, -966, -1383, -641, + -1796, 943, 2641, 1225, -691, -1934, -897, 1319, + 1538, 150, 7139, 2049, 3097, -144, -1, -3110, + -256, -585, -14, -670, -65, -192, -18, -892, + -290, -28, -1349, -387, 618, 7520, 4729, -238, + -3373, -23, -3452, -1365, -3, -694, -283, -178, + -2170, 8, 109, 68, 127, 1548, 973, -49, + 2965, -3013, 7912, 7076, -1997, -536, -554, -3821, + -3056, -243, 545, -1431, 1455, -1280, 1301, -3417, + 361, -367, 964, 862, 2443, -929, -1113, 9677, + 4138, -364, -52, -75, -5716, -1045, 138, 166, + -63, -1443, 549, 657, -617, 234, 281, -2444, + 1966, 3309, 10085, -3399, 2105, -236, -668, -6207, + -705, -270, -397, -1210, -2037, 408, 686, 2092, + -252, -425, -1295, 436, -112, -1368, 8868, 4822, + 2048, 0, -114, -4800, -1419, -256, -9, 61, + 740, 33, 402, -2610, 14, 171, -1108, -602, + -2597, 438, -1839, 6229, 7266, -411, -11, -206, + -2368, -3223, 69, -291, 49, 987, -166, 699, + 1152, -194, 816, -2763, 3454, 553, 9127, 4946, + -5596, -728, -18, -5084, -1493, -1911, -116, -1924, + -308, -1042, -166, -2755, 1179, 188, 3117, 1689, + -532, -663, 12262, 2495, -1004, -17, -26, -9177, + -380, -61, -21, 398, 496, 81, 101, -1867, + -32, -40, 751, 152, -2100, 1317, -1509, 11425, + 2997, -269, -105, -139, -7967, -548, 168, -193, + 121, 1464, -918, 1052, 384, -240, 276, -2090, + 1193, -2697, 11259, 5373, -763, -86, -444, -7737, + -1762, -35, 196, -819, 1853, -391, 884, -3692, + 55, -125, 525, 250, 2405, -471, 11079, 203, + 782, -353, -13, -7491, -2, -37, 69, -1626, + 318, -29, 5, -137, -114, 22, -529, -9, + -1871, 5685, 11290, -2662, 1353, -213, -1972, -7780, + -432, -111, 649, 1289, -3917, -304, 923, 1834, + 154, -469, -932, 220, -3768, 5927, -3093, 5041, + 5212, -866, -2144, -584, -1551, -1658, 1363, -711, + 1119, 1159, -1824, 951, 1198, -1885, 984, -1603, + -2546, 9502, 5969, -2440, 1928, -395, -5511, -2175, + -363, -226, 1477, 927, -3462, -379, 1415, 889, + 299, -1118, -702, 287, -4963, 3568, 4592, 5508, + 3451, -1503, -777, -1287, -1851, -727, 1080, 1391, + -1000, 1668, -1199, -1543, 1045, -751, -967, -1160, + 1745, -2586, 3983, 10899, -1551, -186, -408, -968, + -7250, -146, 275, -424, 628, -1161, 1720, -2649, + 165, -244, 377, 1032, 867, -456, -727, 3369, + 11822, -45, -12, -32, -692, -8531, 24, 38, + -20, -178, 93, 149, -625, 329, 525, -2431, + 7535, 2422, 1926, 1405, 1599, -3466, -358, -226, + -120, -156, -1114, -886, -284, -646, -207, -165, + -735, -236, -188, -137, 1041, -735, -142, 13209, + 1515, -66, -33, -1, -10649, -140, 46, 9, + -6, -839, 593, 114, -96, 68, 13, -1222, + 7950, 6745, -1444, -1008, 2721, -3857, -2777, -127, + -62, -452, -3273, 700, 594, 489, 415, -88, + -1320, -1120, 239, 167, -4754, -1379, 4522, -578, + -5733, -1379, -116, -1248, -20, -2006, -400, 1312, + 380, -167, -48, 159, -1663, -482, 1582, -202, + 3220, 5978, 5923, 2430, -2689, -633, -2181, -2141, + -360, -441, -1175, -1164, -2161, -477, -886, -878, + 528, 981, 972, 398, 377, 1312, 13978, -1470, + 677, -8, -105, -11925, -132, -28, -30, -321, + -1119, 33, 117, 1254, -15, -54, -577, 60, + -3435, 6770, 314, -885, 5686, -720, -2797, -6, + -47, -1973, 1419, 65, -129, -185, 366, 16, + 1192, -2349, -109, 307, 3171, 8774, -2260, 2679, + 3069, -613, -4699, -312, -438, -575, -1698, 437, + 1210, -518, -1435, 369, -594, -1643, 423, -501, + 5557, 1509, 5407, -125, -7386, -1884, -139, -1784, + 0, -3330, -511, -1834, -498, 42, 11, 41, + 2505, 680, 2438, -56, -2838, 2595, 13228, 271, + 1793, -491, -411, -10680, -4, -196, 449, 2291, + -2095, 47, -42, -219, 310, -284, -1447, -29, + 664, -278, 14966, 951, -711, -26, -4, -13672, + -55, -30, 11, -606, 253, -38, 16, -869, + 28, -12, 650, 41, 808, 1770, 8658, 5863, + -1486, -39, -191, -4576, -2098, -134, -87, -427, + -935, -289, -633, -3098, 73, 160, 785, 531, + 3063, 1539, 2000, -542, 9576, -572, -144, -244, + -17, -5597, -287, -374, -188, 101, 51, 66, + -1790, -900, -1169, 317, 514, 14083, -323, 896, + -891, -16, -12106, -6, -49, -48, -442, 10, + 277, -28, -770, 17, 27, 766, -17, 48, + 892, 158, 5237, 11057, -1603, -48, -1, -1674, + -7462, -156, -8, -285, -50, -602, -106, -3534, + 87, 15, 512, 1082, -1612, 2564, -4296, 12526, + 5710, -158, -401, -1126, -9576, -1990, 252, -422, + 672, 1232, -1960, 3284, 561, -893, 1497, -4365, + 4889, -6878, 612, 6109, 4753, -1459, -2887, -22, + -2277, -1379, 2052, -182, 257, -1823, 2564, -228, + -1418, 1995, -177, -1772, 3053, -506, 2403, 9625, + 1322, -569, -15, -352, -5655, -106, 94, -448, + 74, -1794, 297, -1412, -246, 40, -194, -777, + -754, 12904, 4480, -2113, 1471, -34, -10163, -1225, + -272, -132, 594, 206, -3529, -97, 1664, 577, + 67, -1159, -402, 189, 4255, 1476, 5055, 2393, + 2912, -1105, -132, -1559, -349, -517, -383, -1313, + -455, -621, -215, -738, -756, -262, -898, -425, + -1371, 535, 1417, 14604, -997, -114, -17, -122, + -13017, -60, 44, 118, -46, 1222, -477, -1263, + -83, 32, 86, 888, 5368, -1744, 4083, -1236, + 3753, -1758, -185, -1017, -93, -860, 571, -1338, + 434, 405, -131, 308, -1229, 399, -935, 283, + 1588, -3097, 14415, 3699, -1171, -154, -585, -12683, + -835, -83, 300, -1397, 2725, -358, 699, -3255, + 113, -221, 1030, 264, 212, 7989, 9471, -3344, + 2009, -2, -3895, -5475, -682, -246, -103, -123, + -4618, 43, 1630, 1933, -26, -979, -1161, 410, + 856, 2294, -627, 6930, 6929, -44, -321, -24, + -2931, -2930, -119, 32, 87, -362, -970, 265, + -362, -970, 265, -2931, 2357, -4187, 7162, 7683, + 3371, -339, -1070, -3131, -3603, -693, 602, -1030, + 1830, -1105, 1963, -3359, -485, 861, -1474, -1581, + 350, 4585, 14053, -3819, 1218, -7, -1283, -12054, + -890, -90, -97, -300, -3933, 81, 1068, 3275, + -26, -341, -1045, 284, -3248, 3531, 475, 2137, + 11711, -644, -761, -13, -278, -8372, 700, 94, + -102, 423, -460, -62, 2322, -2524, -340, -1528, + -3017, 3852, 1725, 8440, 5257, -555, -905, -181, + -4348, -1686, 709, 317, -405, 1554, -1984, -889, + 968, -1236, -553, -2708, -909, 3196, 15512, -2528, + 1066, -50, -623, -14686, -390, -69, 177, 861, + -3026, -140, 493, 2393, 59, -208, -1009, 164, + 959, -3370, 9617, 9545, -1761, -56, -693, -5645, + -5561, -189, 197, -563, 1978, -558, 1963, -5603, + 103, -362, 1034, 1026, 7575, 11796, -4845, 3252, + -1703, -3502, -8493, -1433, -645, -177, -5454, 2240, + 3488, -1503, -2341, 961, 787, 1226, -503, 338, + 6409, 1722, 1764, -4191, 6015, -2507, -181, -189, + -1072, -2208, -673, -690, -185, 1639, 440, 451, + -2353, -632, -647, 1538, -2420, 12161, 5038, 1286, + -2098, -357, -9027, -1549, -100, -268, 1796, 744, + -3740, 190, -954, -395, -310, 1557, 645, 164, + -2232, -1341, 7246, 9470, -1977, -304, -109, -3204, + -5474, -238, -182, 987, 593, 1290, 775, -4188, + -269, -161, 874, 1143, 1030, 7034, 4231, 1551, + 3077, -64, -3019, -1093, -146, -577, -442, -266, + -1816, -97, -666, -400, -193, -1321, -794, -291, + 5121, 11835, -477, -1749, 2298, -1601, -8549, -13, + -186, -322, -3699, 149, 344, 546, 1264, -50, + -718, -1660, 66, 245, -3328, 3827, 5921, 9976, + -1045, -676, -894, -2140, -6075, -66, 777, 1203, + -1383, 2027, -2330, -3605, -212, 244, 377, 636, + 3813, 5718, -4666, -3412, 5674, -887, -1995, -1329, + -710, -1965, -1331, 1086, 1628, 794, 1191, -972, + -1320, -1980, 1616, 1181, 1348, -3672, 13154, 6938, + -1690, -110, -823, -10561, -2938, -174, 302, -1082, + 2948, -570, 1555, -5570, 139, -379, 1357, 716, + 2151, -3586, 6949, 12131, -1224, -282, -785, -2947, + -8982, -91, 470, -912, 1521, -1592, 2655, -5145, + 160, -268, 519, 906, -2889, 9647, 10276, -2728, + 995, -509, -5680, -6445, -454, -60, 1701, 1812, + -6051, -481, 1606, 1711, 175, -586, -624, 165, + 6177, 2184, 555, 1985, 6589, -2329, -291, -18, + -240, -2650, -823, -209, -74, -748, -264, -67, + -2484, -878, -223, -798, -492, 391, 17166, -681, + 240, -14, -9, -17987, -28, -3, 11, 515, + -410, -20, 16, 713, 7, -5, -252, 10, + 12628, 5448, -2630, 3011, -2695, -9733, -1811, -422, + -553, -443, -4199, 2027, 874, -2321, -1001, 483, + 2077, 896, -432, 495, -3628, -534, 3447, 7002, + 6751, -803, -17, -725, -2992, -2782, -118, 763, + 112, 1550, 228, -1473, 1495, 220, -1420, -2885, + -5239, 5901, 8107, 3650, 4846, -1675, -2125, -4012, + -813, -1433, 1887, 2592, -2920, 1167, -1315, -1806, + 1550, -1745, -2398, -1080, 6157, 6678, 4099, -1074, + 2348, -2314, -2722, -1025, -70, -336, -2509, -1540, + -1670, 403, 437, 268, -882, -957, -587, 153, + 1079, 16099, 242, -881, 1690, -71, -15820, -3, + -47, -174, -1060, -16, -238, 58, 865, 13, + -111, -1661, -25, 90, -278, 227, -1039, 1636, + 16945, -4, -3, -65, -163, -17526, 3, -17, + 14, 27, -22, 103, 287, -234, 1074, -1693, + 15778, -1454, 574, -603, -107, -15195, -129, -20, + -22, 0, 1400, -553, 51, 581, -53, 21, + 103, -9, 3, -3, 2406, -836, 13224, 7993, + -4266, -353, -42, -10673, -3899, -1111, 122, -1942, + 674, -1174, 407, -6451, 626, -217, 3443, 2081, + 3184, 14368, -3336, 2255, -1801, -619, -12600, -679, + -310, -198, -2793, 648, 2926, -438, -1977, 459, + 350, 1580, -366, 247, -1698, 17076, 2504, -539, + -646, -176, -17798, -382, -17, -25, 1770, 259, + -2610, -55, 561, 82, -67, 673, 98, -21, + 2375, -797, -2696, 14483, 5383, -344, -38, -443, + -12803, -1769, 115, 391, -131, -2100, 705, 2384, + -780, 262, 886, -4759, -2691, 2554, -4520, 9573, + 10655, -442, -398, -1247, -5594, -6930, 419, -742, + 704, 1572, -1492, 2641, 1750, -1661, 2939, -6226, + -4332, -4399, -1657, 4880, 7375, -1145, -1181, -167, + -1453, -3319, -1163, -438, -444, 1290, 1310, 493, + 1950, 1980, 745, -2196, -3498, 7405, 9955, 2693, + -2971, -746, -3347, -6049, -442, -538, 1581, 2125, + -4499, 575, -1217, -1636, -634, 1342, 1805, 488, + 6717, -3792, 7739, 2798, 3489, -2754, -877, -3655, + -477, -743, 1554, -3173, 1791, -1147, 647, -1321, + -1430, 807, -1648, -595, 5263, 9770, 3463, 1069, + -3971, -1690, -5826, -732, -69, -962, -3138, -1112, + -2065, -343, -637, -226, 1275, 2368, 839, 259, + 1243, -2634, 16772, 1871, 332, -94, -423, -17169, + -213, -6, 199, -1273, 2696, -142, 300, -1915, + -25, 53, -339, -37, 2691, 2836, 3105, 5711, + 4817, -442, -491, -588, -1991, -1416, -465, -510, + -537, -938, -988, -1082, -791, -834, -913, -1679, + 4366, 2944, 7210, 3627, 1161, -1163, -529, -3172, + -803, -82, -784, -1921, -1295, -966, -651, -1596, + -309, -208, -511, -257, 13888, 3951, -671, -2305, + 3354, -11773, -953, -27, -324, -686, -3349, 569, + 161, 1954, 556, -94, -2843, -809, 137, 472, + 7053, 5847, 2929, 8378, -4794, -3036, -2086, -523, + -4284, -1403, -2517, -1261, -1045, -3607, -2990, -1498, + 2064, 1711, 857, 2451, -2191, 12838, 9182, -3915, + 1617, -293, -10059, -5146, -935, -159, 1717, 1228, + -7195, -523, 3068, 2194, 216, -1267, -906, 386, + -4881, 13114, 5767, -435, 4155, -1454, -10498, -2030, + -11, -1054, 3907, 1718, -4616, -129, 348, 153, + 1238, -3326, -1462, 110, 7843, -1250, 210, 7106, + -5203, -3754, -95, -2, -3082, -1652, 598, -100, + 16, -3402, 542, -91, 2491, -397, 66, 2257, + -2463, 8168, 14551, -3908, 1828, -370, -4072, -12923, + -932, -204, 1228, 2188, -7254, -587, 1948, 3471, + 274, -911, -1623, 436, -1579, 347, -272, -2735, + 16031, -152, -7, -4, -456, -15686, 33, -26, + 5, -263, 58, -45, 1545, -340, 266, 2676, + -6327, 1328, 5093, -5079, 7617, -2443, -107, -1583, + -1574, -3541, 513, 1967, -413, -1961, 411, 1578, + 2941, -617, -2367, 2361, 3286, -4509, 11306, 11025, + -2623, -659, -1241, -7802, -7419, -420, 904, -2267, + 3112, -2211, 3034, -7608, 526, -722, 1810, 1765, + 5567, 17853, -3754, 1166, -519, -1892, -19455, -860, + -83, -16, -6067, 1275, 4090, -396, -1271, 267, + 176, 566, -119, 37, -2136, -424, 15292, 5108, + -1648, -278, -10, -14273, -1593, -165, -55, 1993, + 396, 666, 132, -4768, -214, -42, 1538, 514, + 2267, -3297, 2549, 16563, -791, -313, -663, -396, + -16745, -38, 456, -352, 513, -2291, 3333, -2576, + 109, -159, 123, 799, 3655, 1899, -3364, 6279, + 12510, -815, -220, -690, -2406, -9552, -423, 750, + 390, -1400, -728, 1289, -2791, -1450, 2568, -4794, + 8052, 2285, -6193, 5138, 6003, -3957, -318, -2341, + -1611, -2199, -1123, 3044, 864, -2525, -716, 1942, + -2950, -837, 2269, -1882, -386, -2291, 7679, 15387, + -2723, -9, -320, -3599, -14452, -452, -54, 181, + 1074, 362, 2152, -7212, -64, -380, 1276, 2557, + 2777, -1173, 3984, 13079, 2508, -470, -84, -969, + -10440, -384, 198, -675, 285, -2217, 936, -3180, + -425, 179, -610, -2002, -1879, 1771, -2684, 16705, + 1833, -215, -191, -439, -17032, -205, 203, -308, + 290, 1916, -1805, 2736, 210, -198, 300, -1869, + 1052, 4495, 15519, 1467, -4032, -67, -1233, -14700, + -131, -992, -288, -997, -4257, -94, -402, -1389, + 259, 1106, 3819, 361, 3010, 2544, 6969, 7559, + 1996, -553, -395, -2964, -3487, -243, -467, -1280, + -1082, -1388, -1174, -3215, -366, -310, -849, -921, + -5209, -1867, 8713, 10351, 1549, -1656, -212, -4634, + -6540, -146, -593, 2770, 993, 3291, 1180, -5505, + 492, 176, -824, -979, -4314, 8513, 913, 7547, + -2723, -1135, -4423, -50, -3476, -452, 2241, 240, + -474, 1987, -3921, -420, -717, 1415, 151, 1254, + 12929, -1219, 2448, 1757, 6303, -10204, -90, -365, + -188, -2425, 962, -1932, 182, -1386, 130, -262, + -4974, 469, -941, -676, 6465, 4132, 3167, 3160, + 5697, -2551, -1042, -612, -609, -1981, -1630, -1249, + -798, -1247, -797, -611, -2248, -1437, -1101, -1099, + -3636, 4859, 18914, -1335, 810, -807, -1441, -21836, + -108, -40, 1078, 4198, -5609, -296, 396, 1541, + 179, -240, -936, 66, 8844, 7864, 654, -4063, + -5680, -4774, -3774, -26, -1007, -1969, -4245, -353, + -314, 2193, 1950, 162, 3066, 2726, 226, -1408, + 1859, 2634, 9228, 996, 9464, -211, -423, -5197, + -60, -5467, -299, -1047, -1483, -113, -160, -561, + -1074, -1521, -5330, -575, 2949, 12260, 10290, -497, + -3943, -530, -9174, -6463, -15, -949, -2206, -1852, + -7700, 89, 372, 312, 709, 2950, 2476, -119, + -2903, 1552, 14867, 9970, -496, -514, -147, -13491, + -6068, -15, 275, 2634, -1408, 1766, -944, -9047, + -87, 47, 450, 302, 3243, 8234, 7586, 3373, + 2151, -642, -4138, -3512, -694, -282, -1630, -1501, + -3812, -667, -1695, -1561, -425, -1081, -996, -442, + -9631, 60, 3501, 5359, 10150, -5662, 0, -748, + -1752, -6288, 35, 2058, -12, 3150, -19, -1145, + 5967, -37, -2169, -3320, -6874, -2553, -5446, -2195, + -7841, -2884, -397, -1810, -294, -3753, -1071, -2285, + -848, -921, -342, -729, -3290, -1221, -2606, -1050, + -3413, -1141, 4630, 13612, 7897, -711, -79, -1308, + -11310, -3806, -237, 964, 322, 2836, 948, -3847, + 1645, 550, -2231, -6561, 4410, -5678, 8006, -3992, + 3811, -1187, -1968, -3912, -973, -886, 1528, -2155, + 2775, 1074, -1383, 1951, -1025, 1321, -1862, 928, + 5659, 11535, 2203, -452, 7169, -1954, -8121, -296, + -12, -3137, -3984, -761, -1551, 156, 318, 60, + -2476, -5048, -964, 197, 2914, -2914, 3485, -3965, + 13675, -518, -518, -741, -959, -11414, 518, -620, + 620, 705, -705, 843, -2433, 2432, -2909, 3310, + 7843, 1907, 1022, 8882, 7972, -3755, -222, -63, + -4815, -3879, -913, -489, -119, -4252, -1034, -554, + -3816, -928, -497, -4322, 13807, 9531, 1436, 1612, + 1779, -11636, -5544, -125, -158, -193, -8032, -1210, + -835, -1358, -938, -141, -1499, -1035, -156, -175, + 13620, -5337, 5450, -2263, 1723, -11322, -1738, -1813, + -312, -181, 4436, -4531, 1775, 1881, -737, 752, + -1432, 561, -573, 238, 5297, 8374, 8872, 7694, + 6538, -1712, -4280, -4804, -3613, -2609, -2707, -2868, + -4534, -2487, -3932, -4166, -2113, -3341, -3540, -3070 +}; + +/** + * 0.65^i (Zero part) and 0.75^i (Pole part) scaled by 2^15 + */ +static const int16_t postfilter_tbl[2][LPC_ORDER] = { + /* Zero */ + {21299, 13844, 8999, 5849, 3802, 2471, 1606, 1044, 679, 441}, + /* Pole */ + {24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845} +}; + +/** + * Hamming window coefficients scaled by 2^15 + */ +static const int16_t hamming_window[LPC_FRAME] = { + 2621, 2631, 2659, 2705, 2770, 2853, 2955, 3074, 3212, 3367, + 3541, 3731, 3939, 4164, 4405, 4663, 4937, 5226, 5531, 5851, + 6186, 6534, 6897, 7273, 7661, 8062, 8475, 8899, 9334, 9780, + 10235, 10699, 11172, 11653, 12141, 12636, 13138, 13645, 14157, 14673, + 15193, 15716, 16242, 16769, 17298, 17827, 18356, 18884, 19411, 19935, + 20457, 20975, 21489, 21999, 22503, 23002, 23494, 23978, 24455, 24924, + 25384, 25834, 26274, 26704, 27122, 27529, 27924, 28306, 28675, 29031, + 29373, 29700, 30012, 30310, 30592, 30857, 31107, 31340, 31557, 31756, + 31938, 32102, 32249, 32377, 32488, 32580, 32654, 32710, 32747, 32766, + 32766, 32747, 32710, 32654, 32580, 32488, 32377, 32249, 32102, 31938, + 31756, 31557, 31340, 31107, 30857, 30592, 30310, 30012, 29700, 29373, + 29031, 28675, 28306, 27924, 27529, 27122, 26704, 26274, 25834, 25384, + 24924, 24455, 23978, 23494, 23002, 22503, 21999, 21489, 20975, 20457, + 19935, 19411, 18884, 18356, 17827, 17298, 16769, 16242, 15716, 15193, + 14673, 14157, 13645, 13138, 12636, 12141, 11653, 11172, 10699, 10235, + 9780, 9334, 8899, 8475, 8062, 7661, 7273, 6897, 6534, 6186, + 5851, 5531, 5226, 4937, 4663, 4405, 4164, 3939, 3731, 3541, + 3367, 3212, 3074, 2955, 2853, 2770, 2705, 2659, 2631, 2621 +}; + +/** + * Binomial window coefficients scaled by 2^15 + */ +static const int16_t binomial_window[LPC_ORDER] = { + 32749, 32695, 32604, 32477, 32315, 32118, 31887, 31622, 31324, 30995 +}; + +/** + * 0.994^i scaled by 2^15 + */ +static const int16_t bandwidth_expand[LPC_ORDER] = { + 32571, 32376, 32182, 31989, 31797, 31606, 31416, 31228, 31040, 30854 +}; + +/** + * 0.5^i scaled by 2^15 + */ +static const int16_t percept_flt_tbl[2][LPC_ORDER] = { + /* Zero part */ + {29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425}, + /* Pole part */ + {16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32} +}; + +static const int cng_adaptive_cb_lag[4] = { 1, 0, 1, 3 }; + +static const int cng_filt[4] = { 273, 998, 499, 333 }; + +static const int cng_bseg[3] = { 2048, 18432, 231233 }; + +#endif /* AVCODEC_G723_1_DATA_H */ diff --git a/ffmpeg/libavcodec/g726.c b/ffmpeg/libavcodec/g726.c new file mode 100644 index 0000000..58d0468 --- /dev/null +++ b/ffmpeg/libavcodec/g726.c @@ -0,0 +1,468 @@ +/* + * G.726 ADPCM audio codec + * Copyright (c) 2004 Roman Shaposhnik + * + * This is a very straightforward rendition of the G.726 + * Section 4 "Computational Details". + * + * 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 "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "put_bits.h" + +/** + * G.726 11bit float. + * G.726 Standard uses rather odd 11bit floating point arithmentic for + * numerous occasions. It's a mystery to me why they did it this way + * instead of simply using 32bit integer arithmetic. + */ +typedef struct Float11 { + uint8_t sign; /**< 1bit sign */ + uint8_t exp; /**< 4bit exponent */ + uint8_t mant; /**< 6bit mantissa */ +} Float11; + +static inline Float11* i2f(int i, Float11* f) +{ + f->sign = (i < 0); + if (f->sign) + i = -i; + f->exp = av_log2_16bit(i) + !!i; + f->mant = i? (i<<6) >> f->exp : 1<<5; + return f; +} + +static inline int16_t mult(Float11* f1, Float11* f2) +{ + int res, exp; + + exp = f1->exp + f2->exp; + res = (((f1->mant * f2->mant) + 0x30) >> 4); + res = exp > 19 ? res << (exp - 19) : res >> (19 - exp); + return (f1->sign ^ f2->sign) ? -res : res; +} + +static inline int sgn(int value) +{ + return (value < 0) ? -1 : 1; +} + +typedef struct G726Tables { + const int* quant; /**< quantization table */ + const int16_t* iquant; /**< inverse quantization table */ + const int16_t* W; /**< special table #1 ;-) */ + const uint8_t* F; /**< special table #2 */ +} G726Tables; + +typedef struct G726Context { + AVClass *class; + G726Tables tbls; /**< static tables needed for computation */ + + Float11 sr[2]; /**< prev. reconstructed samples */ + Float11 dq[6]; /**< prev. difference */ + int a[2]; /**< second order predictor coeffs */ + int b[6]; /**< sixth order predictor coeffs */ + int pk[2]; /**< signs of prev. 2 sez + dq */ + + int ap; /**< scale factor control */ + int yu; /**< fast scale factor */ + int yl; /**< slow scale factor */ + int dms; /**< short average magnitude of F[i] */ + int dml; /**< long average magnitude of F[i] */ + int td; /**< tone detect */ + + int se; /**< estimated signal for the next iteration */ + int sez; /**< estimated second order prediction */ + int y; /**< quantizer scaling factor for the next iteration */ + int code_size; +} G726Context; + +static const int quant_tbl16[] = /**< 16kbit/s 2bits per sample */ + { 260, INT_MAX }; +static const int16_t iquant_tbl16[] = + { 116, 365, 365, 116 }; +static const int16_t W_tbl16[] = + { -22, 439, 439, -22 }; +static const uint8_t F_tbl16[] = + { 0, 7, 7, 0 }; + +static const int quant_tbl24[] = /**< 24kbit/s 3bits per sample */ + { 7, 217, 330, INT_MAX }; +static const int16_t iquant_tbl24[] = + { INT16_MIN, 135, 273, 373, 373, 273, 135, INT16_MIN }; +static const int16_t W_tbl24[] = + { -4, 30, 137, 582, 582, 137, 30, -4 }; +static const uint8_t F_tbl24[] = + { 0, 1, 2, 7, 7, 2, 1, 0 }; + +static const int quant_tbl32[] = /**< 32kbit/s 4bits per sample */ + { -125, 79, 177, 245, 299, 348, 399, INT_MAX }; +static const int16_t iquant_tbl32[] = + { INT16_MIN, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, INT16_MIN }; +static const int16_t W_tbl32[] = + { -12, 18, 41, 64, 112, 198, 355, 1122, + 1122, 355, 198, 112, 64, 41, 18, -12}; +static const uint8_t F_tbl32[] = + { 0, 0, 0, 1, 1, 1, 3, 7, 7, 3, 1, 1, 1, 0, 0, 0 }; + +static const int quant_tbl40[] = /**< 40kbit/s 5bits per sample */ + { -122, -16, 67, 138, 197, 249, 297, 338, + 377, 412, 444, 474, 501, 527, 552, INT_MAX }; +static const int16_t iquant_tbl40[] = + { INT16_MIN, -66, 28, 104, 169, 224, 274, 318, + 358, 395, 429, 459, 488, 514, 539, 566, + 566, 539, 514, 488, 459, 429, 395, 358, + 318, 274, 224, 169, 104, 28, -66, INT16_MIN }; +static const int16_t W_tbl40[] = + { 14, 14, 24, 39, 40, 41, 58, 100, + 141, 179, 219, 280, 358, 440, 529, 696, + 696, 529, 440, 358, 280, 219, 179, 141, + 100, 58, 41, 40, 39, 24, 14, 14 }; +static const uint8_t F_tbl40[] = + { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6, + 6, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + +static const G726Tables G726Tables_pool[] = + {{ quant_tbl16, iquant_tbl16, W_tbl16, F_tbl16 }, + { quant_tbl24, iquant_tbl24, W_tbl24, F_tbl24 }, + { quant_tbl32, iquant_tbl32, W_tbl32, F_tbl32 }, + { quant_tbl40, iquant_tbl40, W_tbl40, F_tbl40 }}; + + +/** + * Para 4.2.2 page 18: Adaptive quantizer. + */ +static inline uint8_t quant(G726Context* c, int d) +{ + int sign, exp, i, dln; + + sign = i = 0; + if (d < 0) { + sign = 1; + d = -d; + } + exp = av_log2_16bit(d); + dln = ((exp<<7) + (((d<<7)>>exp)&0x7f)) - (c->y>>2); + + while (c->tbls.quant[i] < INT_MAX && c->tbls.quant[i] < dln) + ++i; + + if (sign) + i = ~i; + if (c->code_size != 2 && i == 0) /* I'm not sure this is a good idea */ + i = 0xff; + + return i; +} + +/** + * Para 4.2.3 page 22: Inverse adaptive quantizer. + */ +static inline int16_t inverse_quant(G726Context* c, int i) +{ + int dql, dex, dqt; + + dql = c->tbls.iquant[i] + (c->y >> 2); + dex = (dql>>7) & 0xf; /* 4bit exponent */ + dqt = (1<<7) + (dql & 0x7f); /* log2 -> linear */ + return (dql < 0) ? 0 : ((dqt<> 7); +} + +static int16_t g726_decode(G726Context* c, int I) +{ + int dq, re_signal, pk0, fa1, i, tr, ylint, ylfrac, thr2, al, dq0; + Float11 f; + int I_sig= I >> (c->code_size - 1); + + dq = inverse_quant(c, I); + + /* Transition detect */ + ylint = (c->yl >> 15); + ylfrac = (c->yl >> 10) & 0x1f; + thr2 = (ylint > 9) ? 0x1f << 10 : (0x20 + ylfrac) << ylint; + tr= (c->td == 1 && dq > ((3*thr2)>>2)); + + if (I_sig) /* get the sign */ + dq = -dq; + re_signal = c->se + dq; + + /* Update second order predictor coefficient A2 and A1 */ + pk0 = (c->sez + dq) ? sgn(c->sez + dq) : 0; + dq0 = dq ? sgn(dq) : 0; + if (tr) { + c->a[0] = 0; + c->a[1] = 0; + for (i=0; i<6; i++) + c->b[i] = 0; + } else { + /* This is a bit crazy, but it really is +255 not +256 */ + fa1 = av_clip((-c->a[0]*c->pk[0]*pk0)>>5, -256, 255); + + c->a[1] += 128*pk0*c->pk[1] + fa1 - (c->a[1]>>7); + c->a[1] = av_clip(c->a[1], -12288, 12288); + c->a[0] += 64*3*pk0*c->pk[0] - (c->a[0] >> 8); + c->a[0] = av_clip(c->a[0], -(15360 - c->a[1]), 15360 - c->a[1]); + + for (i=0; i<6; i++) + c->b[i] += 128*dq0*sgn(-c->dq[i].sign) - (c->b[i]>>8); + } + + /* Update Dq and Sr and Pk */ + c->pk[1] = c->pk[0]; + c->pk[0] = pk0 ? pk0 : 1; + c->sr[1] = c->sr[0]; + i2f(re_signal, &c->sr[0]); + for (i=5; i>0; i--) + c->dq[i] = c->dq[i-1]; + i2f(dq, &c->dq[0]); + c->dq[0].sign = I_sig; /* Isn't it crazy ?!?! */ + + c->td = c->a[1] < -11776; + + /* Update Ap */ + c->dms += (c->tbls.F[I]<<4) + ((- c->dms) >> 5); + c->dml += (c->tbls.F[I]<<4) + ((- c->dml) >> 7); + if (tr) + c->ap = 256; + else { + c->ap += (-c->ap) >> 4; + if (c->y <= 1535 || c->td || abs((c->dms << 2) - c->dml) >= (c->dml >> 3)) + c->ap += 0x20; + } + + /* Update Yu and Yl */ + c->yu = av_clip(c->y + c->tbls.W[I] + ((-c->y)>>5), 544, 5120); + c->yl += c->yu + ((-c->yl)>>6); + + /* Next iteration for Y */ + al = (c->ap >= 256) ? 1<<6 : c->ap >> 2; + c->y = (c->yl + (c->yu - (c->yl>>6))*al) >> 6; + + /* Next iteration for SE and SEZ */ + c->se = 0; + for (i=0; i<6; i++) + c->se += mult(i2f(c->b[i] >> 2, &f), &c->dq[i]); + c->sez = c->se >> 1; + for (i=0; i<2; i++) + c->se += mult(i2f(c->a[i] >> 2, &f), &c->sr[i]); + c->se >>= 1; + + return av_clip(re_signal << 2, -0xffff, 0xffff); +} + +static av_cold int g726_reset(G726Context *c) +{ + int i; + + c->tbls = G726Tables_pool[c->code_size - 2]; + for (i=0; i<2; i++) { + c->sr[i].mant = 1<<5; + c->pk[i] = 1; + } + for (i=0; i<6; i++) { + c->dq[i].mant = 1<<5; + } + c->yu = 544; + c->yl = 34816; + + c->y = 544; + + return 0; +} + +#if CONFIG_ADPCM_G726_ENCODER +static int16_t g726_encode(G726Context* c, int16_t sig) +{ + uint8_t i; + + i = quant(c, sig/4 - c->se) & ((1<code_size) - 1); + g726_decode(c, i); + return i; +} + +/* Interfacing to the libavcodec */ + +static av_cold int g726_encode_init(AVCodecContext *avctx) +{ + G726Context* c = avctx->priv_data; + + if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL && + avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Sample rates other than 8kHz are not " + "allowed when the compliance level is higher than unofficial. " + "Resample or reduce the compliance level.\n"); + return AVERROR(EINVAL); + } + av_assert0(avctx->sample_rate > 0); + + if(avctx->channels != 1){ + av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); + return AVERROR(EINVAL); + } + + if (avctx->bit_rate) + c->code_size = (avctx->bit_rate + avctx->sample_rate/2) / avctx->sample_rate; + + c->code_size = av_clip(c->code_size, 2, 5); + avctx->bit_rate = c->code_size * avctx->sample_rate; + avctx->bits_per_coded_sample = c->code_size; + + g726_reset(c); + + /* select a frame size that will end on a byte boundary and have a size of + approximately 1024 bytes */ + avctx->frame_size = ((int[]){ 4096, 2736, 2048, 1640 })[c->code_size - 2]; + + return 0; +} + +static int g726_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + G726Context *c = avctx->priv_data; + const int16_t *samples = (const int16_t *)frame->data[0]; + PutBitContext pb; + int i, ret, out_size; + + out_size = (frame->nb_samples * c->code_size + 7) / 8; + if ((ret = ff_alloc_packet2(avctx, avpkt, out_size)) < 0) + return ret; + init_put_bits(&pb, avpkt->data, avpkt->size); + + for (i = 0; i < frame->nb_samples; i++) + put_bits(&pb, c->code_size, g726_encode(c, *samples++)); + + flush_put_bits(&pb); + + avpkt->size = out_size; + *got_packet_ptr = 1; + return 0; +} + +#define OFFSET(x) offsetof(G726Context, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "code_size", "Bits per code", OFFSET(code_size), AV_OPT_TYPE_INT, { .i64 = 4 }, 2, 5, AE }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "g726", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { NULL }, +}; + +AVCodec ff_adpcm_g726_encoder = { + .name = "g726", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_G726, + .priv_data_size = sizeof(G726Context), + .init = g726_encode_init, + .encode2 = g726_encode_frame, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), + .priv_class = &class, + .defaults = defaults, +}; +#endif + +#if CONFIG_ADPCM_G726_DECODER +static av_cold int g726_decode_init(AVCodecContext *avctx) +{ + G726Context* c = avctx->priv_data; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + + c->code_size = avctx->bits_per_coded_sample; + if (c->code_size < 2 || c->code_size > 5) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of bits %d\n", c->code_size); + return AVERROR(EINVAL); + } + g726_reset(c); + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int g726_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + G726Context *c = avctx->priv_data; + int16_t *samples; + GetBitContext gb; + int out_samples, ret; + + out_samples = buf_size * 8 / c->code_size; + + /* get output buffer */ + frame->nb_samples = out_samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + + init_get_bits(&gb, buf, buf_size * 8); + + while (out_samples--) + *samples++ = g726_decode(c, get_bits(&gb, c->code_size)); + + if (get_bits_left(&gb) > 0) + av_log(avctx, AV_LOG_ERROR, "Frame invalidly split, missing parser?\n"); + + *got_frame_ptr = 1; + + return buf_size; +} + +static void g726_decode_flush(AVCodecContext *avctx) +{ + G726Context *c = avctx->priv_data; + g726_reset(c); +} + +AVCodec ff_adpcm_g726_decoder = { + .name = "g726", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ADPCM_G726, + .priv_data_size = sizeof(G726Context), + .init = g726_decode_init, + .decode = g726_decode_frame, + .flush = g726_decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), +}; +#endif diff --git a/ffmpeg/libavcodec/g729.h b/ffmpeg/libavcodec/g729.h new file mode 100644 index 0000000..6168313 --- /dev/null +++ b/ffmpeg/libavcodec/g729.h @@ -0,0 +1,29 @@ +/* + * G.729, G729 Annex D decoders + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ +#ifndef AVCODEC_G729_H +#define AVCODEC_G729_H + +/** + * subframe size + */ +#define SUBFRAME_SIZE 40 + +#endif // AVCODEC_G729_H diff --git a/ffmpeg/libavcodec/g729data.h b/ffmpeg/libavcodec/g729data.h new file mode 100644 index 0000000..365ca47 --- /dev/null +++ b/ffmpeg/libavcodec/g729data.h @@ -0,0 +1,382 @@ +/* + * data for G.729, G729 Annex D decoders + * Copyright (c) 2007 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_G729DATA_H +#define AVCODEC_G729DATA_H + +#include + +#define MA_NP 4 ///< Moving Average (MA) prediction order + +#define VQ_1ST_BITS 7 ///< first stage vector of quantizer (size in bits) +#define VQ_2ND_BITS 5 ///< second stage vector of quantizer (size in bits) + +#define GC_1ST_IDX_BITS_8K 3 ///< gain codebook (first stage) index, 8k mode (size in bits) +#define GC_2ND_IDX_BITS_8K 4 ///< gain codebook (second stage) index, 8k mode (size in bits) + +#define GC_1ST_IDX_BITS_6K4 3 ///< gain codebook (first stage) index, 6.4k mode (size in bits) +#define GC_2ND_IDX_BITS_6K4 3 ///< gain codebook (second stage) index, 6.4k mode (size in bits) + +/** + * first stage LSP codebook + * (10-dimensional, with 128 entries (3.24 of G.729) + */ +static const int16_t cb_lsp_1st[1< +#include + +#include "avcodec.h" +#include "libavutil/avutil.h" +#include "get_bits.h" +#include "dsputil.h" +#include "internal.h" + + +#include "g729.h" +#include "lsp.h" +#include "celp_math.h" +#include "celp_filters.h" +#include "acelp_filters.h" +#include "acelp_pitch_delay.h" +#include "acelp_vectors.h" +#include "g729data.h" +#include "g729postfilter.h" + +/** + * minimum quantized LSF value (3.2.4) + * 0.005 in Q13 + */ +#define LSFQ_MIN 40 + +/** + * maximum quantized LSF value (3.2.4) + * 3.135 in Q13 + */ +#define LSFQ_MAX 25681 + +/** + * minimum LSF distance (3.2.4) + * 0.0391 in Q13 + */ +#define LSFQ_DIFF_MIN 321 + +/// interpolation filter length +#define INTERPOL_LEN 11 + +/** + * minimum gain pitch value (3.8, Equation 47) + * 0.2 in (1.14) + */ +#define SHARP_MIN 3277 + +/** + * maximum gain pitch value (3.8, Equation 47) + * (EE) This does not comply with the specification. + * Specification says about 0.8, which should be + * 13107 in (1.14), but reference C code uses + * 13017 (equals to 0.7945) instead of it. + */ +#define SHARP_MAX 13017 + +/** + * MR_ENERGY (mean removed energy) = mean_energy + 10 * log10(2^26 * subframe_size) in (7.13) + */ +#define MR_ENERGY 1018156 + +#define DECISION_NOISE 0 +#define DECISION_INTERMEDIATE 1 +#define DECISION_VOICE 2 + +typedef enum { + FORMAT_G729_8K = 0, + FORMAT_G729D_6K4, + FORMAT_COUNT, +} G729Formats; + +typedef struct { + uint8_t ac_index_bits[2]; ///< adaptive codebook index for second subframe (size in bits) + uint8_t parity_bit; ///< parity bit for pitch delay + uint8_t gc_1st_index_bits; ///< gain codebook (first stage) index (size in bits) + uint8_t gc_2nd_index_bits; ///< gain codebook (second stage) index (size in bits) + uint8_t fc_signs_bits; ///< number of pulses in fixed-codebook vector + uint8_t fc_indexes_bits; ///< size (in bits) of fixed-codebook index entry +} G729FormatDescription; + +typedef struct { + DSPContext dsp; + AVFrame frame; + + /// past excitation signal buffer + int16_t exc_base[2*SUBFRAME_SIZE+PITCH_DELAY_MAX+INTERPOL_LEN]; + + int16_t* exc; ///< start of past excitation data in buffer + int pitch_delay_int_prev; ///< integer part of previous subframe's pitch delay (4.1.3) + + /// (2.13) LSP quantizer outputs + int16_t past_quantizer_output_buf[MA_NP + 1][10]; + int16_t* past_quantizer_outputs[MA_NP + 1]; + + int16_t lsfq[10]; ///< (2.13) quantized LSF coefficients from previous frame + int16_t lsp_buf[2][10]; ///< (0.15) LSP coefficients (previous and current frames) (3.2.5) + int16_t *lsp[2]; ///< pointers to lsp_buf + + int16_t quant_energy[4]; ///< (5.10) past quantized energy + + /// previous speech data for LP synthesis filter + int16_t syn_filter_data[10]; + + + /// residual signal buffer (used in long-term postfilter) + int16_t residual[SUBFRAME_SIZE + RES_PREV_DATA_SIZE]; + + /// previous speech data for residual calculation filter + int16_t res_filter_data[SUBFRAME_SIZE+10]; + + /// previous speech data for short-term postfilter + int16_t pos_filter_data[SUBFRAME_SIZE+10]; + + /// (1.14) pitch gain of current and five previous subframes + int16_t past_gain_pitch[6]; + + /// (14.1) gain code from current and previous subframe + int16_t past_gain_code[2]; + + /// voice decision on previous subframe (0-noise, 1-intermediate, 2-voice), G.729D + int16_t voice_decision; + + int16_t onset; ///< detected onset level (0-2) + int16_t was_periodic; ///< whether previous frame was declared as periodic or not (4.4) + int16_t ht_prev_data; ///< previous data for 4.2.3, equation 86 + int gain_coeff; ///< (1.14) gain coefficient (4.2.4) + uint16_t rand_value; ///< random number generator value (4.4.4) + int ma_predictor_prev; ///< switched MA predictor of LSP quantizer from last good frame + + /// (14.14) high-pass filter data (past input) + int hpf_f[2]; + + /// high-pass filter data (past output) + int16_t hpf_z[2]; +} G729Context; + +static const G729FormatDescription format_g729_8k = { + .ac_index_bits = {8,5}, + .parity_bit = 1, + .gc_1st_index_bits = GC_1ST_IDX_BITS_8K, + .gc_2nd_index_bits = GC_2ND_IDX_BITS_8K, + .fc_signs_bits = 4, + .fc_indexes_bits = 13, +}; + +static const G729FormatDescription format_g729d_6k4 = { + .ac_index_bits = {8,4}, + .parity_bit = 0, + .gc_1st_index_bits = GC_1ST_IDX_BITS_6K4, + .gc_2nd_index_bits = GC_2ND_IDX_BITS_6K4, + .fc_signs_bits = 2, + .fc_indexes_bits = 9, +}; + +/** + * @brief pseudo random number generator + */ +static inline uint16_t g729_prng(uint16_t value) +{ + return 31821 * value + 13849; +} + +/** + * Get parity bit of bit 2..7 + */ +static inline int get_parity(uint8_t value) +{ + return (0x6996966996696996ULL >> (value >> 2)) & 1; +} + +/** + * Decodes LSF (Line Spectral Frequencies) from L0-L3 (3.2.4). + * @param[out] lsfq (2.13) quantized LSF coefficients + * @param[in,out] past_quantizer_outputs (2.13) quantizer outputs from previous frames + * @param ma_predictor switched MA predictor of LSP quantizer + * @param vq_1st first stage vector of quantizer + * @param vq_2nd_low second stage lower vector of LSP quantizer + * @param vq_2nd_high second stage higher vector of LSP quantizer + */ +static void lsf_decode(int16_t* lsfq, int16_t* past_quantizer_outputs[MA_NP + 1], + int16_t ma_predictor, + int16_t vq_1st, int16_t vq_2nd_low, int16_t vq_2nd_high) +{ + int i,j; + static const uint8_t min_distance[2]={10, 5}; //(2.13) + int16_t* quantizer_output = past_quantizer_outputs[MA_NP]; + + for (i = 0; i < 5; i++) { + quantizer_output[i] = cb_lsp_1st[vq_1st][i ] + cb_lsp_2nd[vq_2nd_low ][i ]; + quantizer_output[i + 5] = cb_lsp_1st[vq_1st][i + 5] + cb_lsp_2nd[vq_2nd_high][i + 5]; + } + + for (j = 0; j < 2; j++) { + for (i = 1; i < 10; i++) { + int diff = (quantizer_output[i - 1] - quantizer_output[i] + min_distance[j]) >> 1; + if (diff > 0) { + quantizer_output[i - 1] -= diff; + quantizer_output[i ] += diff; + } + } + } + + for (i = 0; i < 10; i++) { + int sum = quantizer_output[i] * cb_ma_predictor_sum[ma_predictor][i]; + for (j = 0; j < MA_NP; j++) + sum += past_quantizer_outputs[j][i] * cb_ma_predictor[ma_predictor][j][i]; + + lsfq[i] = sum >> 15; + } + + ff_acelp_reorder_lsf(lsfq, LSFQ_DIFF_MIN, LSFQ_MIN, LSFQ_MAX, 10); +} + +/** + * Restores past LSP quantizer output using LSF from previous frame + * @param[in,out] lsfq (2.13) quantized LSF coefficients + * @param[in,out] past_quantizer_outputs (2.13) quantizer outputs from previous frames + * @param ma_predictor_prev MA predictor from previous frame + * @param lsfq_prev (2.13) quantized LSF coefficients from previous frame + */ +static void lsf_restore_from_previous(int16_t* lsfq, + int16_t* past_quantizer_outputs[MA_NP + 1], + int ma_predictor_prev) +{ + int16_t* quantizer_output = past_quantizer_outputs[MA_NP]; + int i,k; + + for (i = 0; i < 10; i++) { + int tmp = lsfq[i] << 15; + + for (k = 0; k < MA_NP; k++) + tmp -= past_quantizer_outputs[k][i] * cb_ma_predictor[ma_predictor_prev][k][i]; + + quantizer_output[i] = ((tmp >> 15) * cb_ma_predictor_sum_inv[ma_predictor_prev][i]) >> 12; + } +} + +/** + * Constructs new excitation signal and applies phase filter to it + * @param[out] out constructed speech signal + * @param in original excitation signal + * @param fc_cur (2.13) original fixed-codebook vector + * @param gain_code (14.1) gain code + * @param subframe_size length of the subframe + */ +static void g729d_get_new_exc( + int16_t* out, + const int16_t* in, + const int16_t* fc_cur, + int dstate, + int gain_code, + int subframe_size) +{ + int i; + int16_t fc_new[SUBFRAME_SIZE]; + + ff_celp_convolve_circ(fc_new, fc_cur, phase_filter[dstate], subframe_size); + + for(i=0; i> 14; + out[i] += (gain_code * fc_new[i] + 0x2000) >> 14; + } +} + +/** + * Makes decision about onset in current subframe + * @param past_onset decision result of previous subframe + * @param past_gain_code gain code of current and previous subframe + * + * @return onset decision result for current subframe + */ +static int g729d_onset_decision(int past_onset, const int16_t* past_gain_code) +{ + if((past_gain_code[0] >> 1) > past_gain_code[1]) + return 2; + else + return FFMAX(past_onset-1, 0); +} + +/** + * Makes decision about voice presence in current subframe + * @param onset onset level + * @param prev_voice_decision voice decision result from previous subframe + * @param past_gain_pitch pitch gain of current and previous subframes + * + * @return voice decision result for current subframe + */ +static int16_t g729d_voice_decision(int onset, int prev_voice_decision, const int16_t* past_gain_pitch) +{ + int i, low_gain_pitch_cnt, voice_decision; + + if(past_gain_pitch[0] >= 14745) // 0.9 + voice_decision = DECISION_VOICE; + else if (past_gain_pitch[0] <= 9830) // 0.6 + voice_decision = DECISION_NOISE; + else + voice_decision = DECISION_INTERMEDIATE; + + for(i=0, low_gain_pitch_cnt=0; i<6; i++) + if(past_gain_pitch[i] < 9830) + low_gain_pitch_cnt++; + + if(low_gain_pitch_cnt > 2 && !onset) + voice_decision = DECISION_NOISE; + + if(!onset && voice_decision > prev_voice_decision + 1) + voice_decision--; + + if(onset && voice_decision < DECISION_VOICE) + voice_decision++; + + return voice_decision; +} + +static int32_t scalarproduct_int16_c(const int16_t * v1, const int16_t * v2, int order) +{ + int res = 0; + + while (order--) + res += *v1++ * *v2++; + + return res; +} + +static av_cold int decoder_init(AVCodecContext * avctx) +{ + G729Context* ctx = avctx->priv_data; + int i,k; + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono sound is supported (requested channels: %d).\n", avctx->channels); + return AVERROR(EINVAL); + } + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + /* Both 8kbit/s and 6.4kbit/s modes uses two subframes per frame. */ + avctx->frame_size = SUBFRAME_SIZE << 1; + + ctx->gain_coeff = 16384; // 1.0 in (1.14) + + for (k = 0; k < MA_NP + 1; k++) { + ctx->past_quantizer_outputs[k] = ctx->past_quantizer_output_buf[k]; + for (i = 1; i < 11; i++) + ctx->past_quantizer_outputs[k][i - 1] = (18717 * i) >> 3; + } + + ctx->lsp[0] = ctx->lsp_buf[0]; + ctx->lsp[1] = ctx->lsp_buf[1]; + memcpy(ctx->lsp[0], lsp_init, 10 * sizeof(int16_t)); + + ctx->exc = &ctx->exc_base[PITCH_DELAY_MAX+INTERPOL_LEN]; + + ctx->pitch_delay_int_prev = PITCH_DELAY_MIN; + + /* random seed initialization */ + ctx->rand_value = 21845; + + /* quantized prediction error */ + for(i=0; i<4; i++) + ctx->quant_energy[i] = -14336; // -14 in (5.10) + + ff_dsputil_init(&ctx->dsp, avctx); + ctx->dsp.scalarproduct_int16 = scalarproduct_int16_c; + + avcodec_get_frame_defaults(&ctx->frame); + avctx->coded_frame = &ctx->frame; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int16_t *out_frame; + GetBitContext gb; + const G729FormatDescription *format; + int frame_erasure = 0; ///< frame erasure detected during decoding + int bad_pitch = 0; ///< parity check failed + int i; + int16_t *tmp; + G729Formats packet_type; + G729Context *ctx = avctx->priv_data; + int16_t lp[2][11]; // (3.12) + uint8_t ma_predictor; ///< switched MA predictor of LSP quantizer + uint8_t quantizer_1st; ///< first stage vector of quantizer + uint8_t quantizer_2nd_lo; ///< second stage lower vector of quantizer (size in bits) + uint8_t quantizer_2nd_hi; ///< second stage higher vector of quantizer (size in bits) + + int pitch_delay_int[2]; // pitch delay, integer part + int pitch_delay_3x; // pitch delay, multiplied by 3 + int16_t fc[SUBFRAME_SIZE]; // fixed-codebook vector + int16_t synth[SUBFRAME_SIZE+10]; // fixed-codebook vector + int j, ret; + int gain_before, gain_after; + int is_periodic = 0; // whether one of the subframes is declared as periodic or not + + ctx->frame.nb_samples = SUBFRAME_SIZE<<1; + if ((ret = ff_get_buffer(avctx, &ctx->frame, 0)) < 0) + return ret; + out_frame = (int16_t*) ctx->frame.data[0]; + + if (buf_size == 10) { + packet_type = FORMAT_G729_8K; + format = &format_g729_8k; + //Reset voice decision + ctx->onset = 0; + ctx->voice_decision = DECISION_VOICE; + av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729 @ 8kbit/s"); + } else if (buf_size == 8) { + packet_type = FORMAT_G729D_6K4; + format = &format_g729d_6k4; + av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729D @ 6.4kbit/s"); + } else { + av_log(avctx, AV_LOG_ERROR, "Packet size %d is unknown.\n", buf_size); + return AVERROR_INVALIDDATA; + } + + for (i=0; i < buf_size; i++) + frame_erasure |= buf[i]; + frame_erasure = !frame_erasure; + + init_get_bits(&gb, buf, 8*buf_size); + + ma_predictor = get_bits(&gb, 1); + quantizer_1st = get_bits(&gb, VQ_1ST_BITS); + quantizer_2nd_lo = get_bits(&gb, VQ_2ND_BITS); + quantizer_2nd_hi = get_bits(&gb, VQ_2ND_BITS); + + if(frame_erasure) + lsf_restore_from_previous(ctx->lsfq, ctx->past_quantizer_outputs, + ctx->ma_predictor_prev); + else { + lsf_decode(ctx->lsfq, ctx->past_quantizer_outputs, + ma_predictor, + quantizer_1st, quantizer_2nd_lo, quantizer_2nd_hi); + ctx->ma_predictor_prev = ma_predictor; + } + + tmp = ctx->past_quantizer_outputs[MA_NP]; + memmove(ctx->past_quantizer_outputs + 1, ctx->past_quantizer_outputs, + MA_NP * sizeof(int16_t*)); + ctx->past_quantizer_outputs[0] = tmp; + + ff_acelp_lsf2lsp(ctx->lsp[1], ctx->lsfq, 10); + + ff_acelp_lp_decode(&lp[0][0], &lp[1][0], ctx->lsp[1], ctx->lsp[0], 10); + + FFSWAP(int16_t*, ctx->lsp[1], ctx->lsp[0]); + + for (i = 0; i < 2; i++) { + int gain_corr_factor; + + uint8_t ac_index; ///< adaptive codebook index + uint8_t pulses_signs; ///< fixed-codebook vector pulse signs + int fc_indexes; ///< fixed-codebook indexes + uint8_t gc_1st_index; ///< gain codebook (first stage) index + uint8_t gc_2nd_index; ///< gain codebook (second stage) index + + ac_index = get_bits(&gb, format->ac_index_bits[i]); + if(!i && format->parity_bit) + bad_pitch = get_parity(ac_index) == get_bits1(&gb); + fc_indexes = get_bits(&gb, format->fc_indexes_bits); + pulses_signs = get_bits(&gb, format->fc_signs_bits); + gc_1st_index = get_bits(&gb, format->gc_1st_index_bits); + gc_2nd_index = get_bits(&gb, format->gc_2nd_index_bits); + + if (frame_erasure) + pitch_delay_3x = 3 * ctx->pitch_delay_int_prev; + else if(!i) { + if (bad_pitch) + pitch_delay_3x = 3 * ctx->pitch_delay_int_prev; + else + pitch_delay_3x = ff_acelp_decode_8bit_to_1st_delay3(ac_index); + } else { + int pitch_delay_min = av_clip(ctx->pitch_delay_int_prev - 5, + PITCH_DELAY_MIN, PITCH_DELAY_MAX - 9); + + if(packet_type == FORMAT_G729D_6K4) + pitch_delay_3x = ff_acelp_decode_4bit_to_2nd_delay3(ac_index, pitch_delay_min); + else + pitch_delay_3x = ff_acelp_decode_5_6_bit_to_2nd_delay3(ac_index, pitch_delay_min); + } + + /* Round pitch delay to nearest (used everywhere except ff_acelp_interpolate). */ + pitch_delay_int[i] = (pitch_delay_3x + 1) / 3; + if (pitch_delay_int[i] > PITCH_DELAY_MAX) { + av_log(avctx, AV_LOG_WARNING, "pitch_delay_int %d is too large\n", pitch_delay_int[i]); + pitch_delay_int[i] = PITCH_DELAY_MAX; + } + + if (frame_erasure) { + ctx->rand_value = g729_prng(ctx->rand_value); + fc_indexes = ctx->rand_value & ((1 << format->fc_indexes_bits) - 1); + + ctx->rand_value = g729_prng(ctx->rand_value); + pulses_signs = ctx->rand_value; + } + + + memset(fc, 0, sizeof(int16_t) * SUBFRAME_SIZE); + switch (packet_type) { + case FORMAT_G729_8K: + ff_acelp_fc_pulse_per_track(fc, ff_fc_4pulses_8bits_tracks_13, + ff_fc_4pulses_8bits_track_4, + fc_indexes, pulses_signs, 3, 3); + break; + case FORMAT_G729D_6K4: + ff_acelp_fc_pulse_per_track(fc, ff_fc_2pulses_9bits_track1_gray, + ff_fc_2pulses_9bits_track2_gray, + fc_indexes, pulses_signs, 1, 4); + break; + } + + /* + This filter enhances harmonic components of the fixed-codebook vector to + improve the quality of the reconstructed speech. + + / fc_v[i], i < pitch_delay + fc_v[i] = < + \ fc_v[i] + gain_pitch * fc_v[i-pitch_delay], i >= pitch_delay + */ + ff_acelp_weighted_vector_sum(fc + pitch_delay_int[i], + fc + pitch_delay_int[i], + fc, 1 << 14, + av_clip(ctx->past_gain_pitch[0], SHARP_MIN, SHARP_MAX), + 0, 14, + SUBFRAME_SIZE - pitch_delay_int[i]); + + memmove(ctx->past_gain_pitch+1, ctx->past_gain_pitch, 5 * sizeof(int16_t)); + ctx->past_gain_code[1] = ctx->past_gain_code[0]; + + if (frame_erasure) { + ctx->past_gain_pitch[0] = (29491 * ctx->past_gain_pitch[0]) >> 15; // 0.90 (0.15) + ctx->past_gain_code[0] = ( 2007 * ctx->past_gain_code[0] ) >> 11; // 0.98 (0.11) + + gain_corr_factor = 0; + } else { + if (packet_type == FORMAT_G729D_6K4) { + ctx->past_gain_pitch[0] = cb_gain_1st_6k4[gc_1st_index][0] + + cb_gain_2nd_6k4[gc_2nd_index][0]; + gain_corr_factor = cb_gain_1st_6k4[gc_1st_index][1] + + cb_gain_2nd_6k4[gc_2nd_index][1]; + + /* Without check below overflow can occur in ff_acelp_update_past_gain. + It is not issue for G.729, because gain_corr_factor in it's case is always + greater than 1024, while in G.729D it can be even zero. */ + gain_corr_factor = FFMAX(gain_corr_factor, 1024); +#ifndef G729_BITEXACT + gain_corr_factor >>= 1; +#endif + } else { + ctx->past_gain_pitch[0] = cb_gain_1st_8k[gc_1st_index][0] + + cb_gain_2nd_8k[gc_2nd_index][0]; + gain_corr_factor = cb_gain_1st_8k[gc_1st_index][1] + + cb_gain_2nd_8k[gc_2nd_index][1]; + } + + /* Decode the fixed-codebook gain. */ + ctx->past_gain_code[0] = ff_acelp_decode_gain_code(&ctx->dsp, gain_corr_factor, + fc, MR_ENERGY, + ctx->quant_energy, + ma_prediction_coeff, + SUBFRAME_SIZE, 4); +#ifdef G729_BITEXACT + /* + This correction required to get bit-exact result with + reference code, because gain_corr_factor in G.729D is + two times larger than in original G.729. + + If bit-exact result is not issue then gain_corr_factor + can be simpler divided by 2 before call to g729_get_gain_code + instead of using correction below. + */ + if (packet_type == FORMAT_G729D_6K4) { + gain_corr_factor >>= 1; + ctx->past_gain_code[0] >>= 1; + } +#endif + } + ff_acelp_update_past_gain(ctx->quant_energy, gain_corr_factor, 2, frame_erasure); + + /* Routine requires rounding to lowest. */ + ff_acelp_interpolate(ctx->exc + i * SUBFRAME_SIZE, + ctx->exc + i * SUBFRAME_SIZE - pitch_delay_3x / 3, + ff_acelp_interp_filter, 6, + (pitch_delay_3x % 3) << 1, + 10, SUBFRAME_SIZE); + + ff_acelp_weighted_vector_sum(ctx->exc + i * SUBFRAME_SIZE, + ctx->exc + i * SUBFRAME_SIZE, fc, + (!ctx->was_periodic && frame_erasure) ? 0 : ctx->past_gain_pitch[0], + ( ctx->was_periodic && frame_erasure) ? 0 : ctx->past_gain_code[0], + 1 << 13, 14, SUBFRAME_SIZE); + + memcpy(synth, ctx->syn_filter_data, 10 * sizeof(int16_t)); + + if (ff_celp_lp_synthesis_filter( + synth+10, + &lp[i][1], + ctx->exc + i * SUBFRAME_SIZE, + SUBFRAME_SIZE, + 10, + 1, + 0, + 0x800)) + /* Overflow occurred, downscale excitation signal... */ + for (j = 0; j < 2 * SUBFRAME_SIZE + PITCH_DELAY_MAX + INTERPOL_LEN; j++) + ctx->exc_base[j] >>= 2; + + /* ... and make synthesis again. */ + if (packet_type == FORMAT_G729D_6K4) { + int16_t exc_new[SUBFRAME_SIZE]; + + ctx->onset = g729d_onset_decision(ctx->onset, ctx->past_gain_code); + ctx->voice_decision = g729d_voice_decision(ctx->onset, ctx->voice_decision, ctx->past_gain_pitch); + + g729d_get_new_exc(exc_new, ctx->exc + i * SUBFRAME_SIZE, fc, ctx->voice_decision, ctx->past_gain_code[0], SUBFRAME_SIZE); + + ff_celp_lp_synthesis_filter( + synth+10, + &lp[i][1], + exc_new, + SUBFRAME_SIZE, + 10, + 0, + 0, + 0x800); + } else { + ff_celp_lp_synthesis_filter( + synth+10, + &lp[i][1], + ctx->exc + i * SUBFRAME_SIZE, + SUBFRAME_SIZE, + 10, + 0, + 0, + 0x800); + } + /* Save data (without postfilter) for use in next subframe. */ + memcpy(ctx->syn_filter_data, synth+SUBFRAME_SIZE, 10 * sizeof(int16_t)); + + /* Calculate gain of unfiltered signal for use in AGC. */ + gain_before = 0; + for (j = 0; j < SUBFRAME_SIZE; j++) + gain_before += FFABS(synth[j+10]); + + /* Call postfilter and also update voicing decision for use in next frame. */ + ff_g729_postfilter( + &ctx->dsp, + &ctx->ht_prev_data, + &is_periodic, + &lp[i][0], + pitch_delay_int[0], + ctx->residual, + ctx->res_filter_data, + ctx->pos_filter_data, + synth+10, + SUBFRAME_SIZE); + + /* Calculate gain of filtered signal for use in AGC. */ + gain_after = 0; + for(j=0; jgain_coeff = ff_g729_adaptive_gain_control( + gain_before, + gain_after, + synth+10, + SUBFRAME_SIZE, + ctx->gain_coeff); + + if (frame_erasure) + ctx->pitch_delay_int_prev = FFMIN(ctx->pitch_delay_int_prev + 1, PITCH_DELAY_MAX); + else + ctx->pitch_delay_int_prev = pitch_delay_int[i]; + + memcpy(synth+8, ctx->hpf_z, 2*sizeof(int16_t)); + ff_acelp_high_pass_filter( + out_frame + i*SUBFRAME_SIZE, + ctx->hpf_f, + synth+10, + SUBFRAME_SIZE); + memcpy(ctx->hpf_z, synth+8+SUBFRAME_SIZE, 2*sizeof(int16_t)); + } + + ctx->was_periodic = is_periodic; + + /* Save signal for use in next frame. */ + memmove(ctx->exc_base, ctx->exc_base + 2 * SUBFRAME_SIZE, (PITCH_DELAY_MAX+INTERPOL_LEN)*sizeof(int16_t)); + + *got_frame_ptr = 1; + *(AVFrame*)data = ctx->frame; + return buf_size; +} + +AVCodec ff_g729_decoder = { + .name = "g729", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_G729, + .priv_data_size = sizeof(G729Context), + .init = decoder_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("G.729"), +}; diff --git a/ffmpeg/libavcodec/g729postfilter.c b/ffmpeg/libavcodec/g729postfilter.c new file mode 100644 index 0000000..fc90374 --- /dev/null +++ b/ffmpeg/libavcodec/g729postfilter.c @@ -0,0 +1,610 @@ +/* + * G.729, G729 Annex D postfilter + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + +#include "avcodec.h" +#include "g729.h" +#include "acelp_pitch_delay.h" +#include "g729postfilter.h" +#include "celp_math.h" +#include "acelp_filters.h" +#include "acelp_vectors.h" +#include "celp_filters.h" + +#define FRAC_BITS 15 +#include "mathops.h" + +/** + * short interpolation filter (of length 33, according to spec) + * for computing signal with non-integer delay + */ +static const int16_t ff_g729_interp_filt_short[(ANALYZED_FRAC_DELAYS+1)*SHORT_INT_FILT_LEN] = { + 0, 31650, 28469, 23705, 18050, 12266, 7041, 2873, + 0, -1597, -2147, -1992, -1492, -933, -484, -188, +}; + +/** + * long interpolation filter (of length 129, according to spec) + * for computing signal with non-integer delay + */ +static const int16_t ff_g729_interp_filt_long[(ANALYZED_FRAC_DELAYS+1)*LONG_INT_FILT_LEN] = { + 0, 31915, 29436, 25569, 20676, 15206, 9639, 4439, + 0, -3390, -5579, -6549, -6414, -5392, -3773, -1874, + 0, 1595, 2727, 3303, 3319, 2850, 2030, 1023, + 0, -887, -1527, -1860, -1876, -1614, -1150, -579, + 0, 501, 859, 1041, 1044, 892, 631, 315, + 0, -266, -453, -543, -538, -455, -317, -156, + 0, 130, 218, 258, 253, 212, 147, 72, + 0, -59, -101, -122, -123, -106, -77, -40, +}; + +/** + * formant_pp_factor_num_pow[i] = FORMANT_PP_FACTOR_NUM^(i+1) + */ +static const int16_t formant_pp_factor_num_pow[10]= { + /* (0.15) */ + 18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83 +}; + +/** + * formant_pp_factor_den_pow[i] = FORMANT_PP_FACTOR_DEN^(i+1) + */ +static const int16_t formant_pp_factor_den_pow[10] = { + /* (0.15) */ + 22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925 +}; + +/** + * \brief Residual signal calculation (4.2.1 if G.729) + * \param out [out] output data filtered through A(z/FORMANT_PP_FACTOR_NUM) + * \param filter_coeffs (3.12) A(z/FORMANT_PP_FACTOR_NUM) filter coefficients + * \param in input speech data to process + * \param subframe_size size of one subframe + * + * \note in buffer must contain 10 items of previous speech data before top of the buffer + * \remark It is safe to pass the same buffer for input and output. + */ +static void residual_filter(int16_t* out, const int16_t* filter_coeffs, const int16_t* in, + int subframe_size) +{ + int i, n; + + for (n = subframe_size - 1; n >= 0; n--) { + int sum = 0x800; + for (i = 0; i < 10; i++) + sum += filter_coeffs[i] * in[n - i - 1]; + + out[n] = in[n] + (sum >> 12); + } +} + +/** + * \brief long-term postfilter (4.2.1) + * \param dsp initialized DSP context + * \param pitch_delay_int integer part of the pitch delay in the first subframe + * \param residual filtering input data + * \param residual_filt [out] speech signal with applied A(z/FORMANT_PP_FACTOR_NUM) filter + * \param subframe_size size of subframe + * + * \return 0 if long-term prediction gain is less than 3dB, 1 - otherwise + */ +static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int, + const int16_t* residual, int16_t *residual_filt, + int subframe_size) +{ + int i, k, tmp, tmp2; + int sum; + int L_temp0; + int L_temp1; + int64_t L64_temp0; + int64_t L64_temp1; + int16_t shift; + int corr_int_num, corr_int_den; + + int ener; + int16_t sh_ener; + + int16_t gain_num,gain_den; //selected signal's gain numerator and denominator + int16_t sh_gain_num, sh_gain_den; + int gain_num_square; + + int16_t gain_long_num,gain_long_den; //filtered through long interpolation filter signal's gain numerator and denominator + int16_t sh_gain_long_num, sh_gain_long_den; + + int16_t best_delay_int, best_delay_frac; + + int16_t delayed_signal_offset; + int lt_filt_factor_a, lt_filt_factor_b; + + int16_t * selected_signal; + const int16_t * selected_signal_const; //Necessary to avoid compiler warning + + int16_t sig_scaled[SUBFRAME_SIZE + RES_PREV_DATA_SIZE]; + int16_t delayed_signal[ANALYZED_FRAC_DELAYS][SUBFRAME_SIZE+1]; + int corr_den[ANALYZED_FRAC_DELAYS][2]; + + tmp = 0; + for(i=0; i 0) + for (i = 0; i < subframe_size + RES_PREV_DATA_SIZE; i++) + sig_scaled[i] = residual[i] >> shift; + else + for (i = 0; i < subframe_size + RES_PREV_DATA_SIZE; i++) + sig_scaled[i] = residual[i] << -shift; + + /* Start of best delay searching code */ + gain_num = 0; + + ener = dsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE, + sig_scaled + RES_PREV_DATA_SIZE, + subframe_size); + if (ener) { + sh_ener = FFMAX(av_log2(ener) - 14, 0); + ener >>= sh_ener; + /* Search for best pitch delay. + + sum{ r(n) * r(k,n) ] }^2 + R'(k)^2 := ------------------------- + sum{ r(k,n) * r(k,n) } + + + R(T) := sum{ r(n) * r(n-T) ] } + + + where + r(n-T) is integer delayed signal with delay T + r(k,n) is non-integer delayed signal with integer delay best_delay + and fractional delay k */ + + /* Find integer delay best_delay which maximizes correlation R(T). + + This is also equals to numerator of R'(0), + since the fine search (second step) is done with 1/8 + precision around best_delay. */ + corr_int_num = 0; + best_delay_int = pitch_delay_int - 1; + for (i = pitch_delay_int - 1; i <= pitch_delay_int + 1; i++) { + sum = dsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE, + sig_scaled + RES_PREV_DATA_SIZE - i, + subframe_size); + if (sum > corr_int_num) { + corr_int_num = sum; + best_delay_int = i; + } + } + if (corr_int_num) { + /* Compute denominator of pseudo-normalized correlation R'(0). */ + corr_int_den = dsp->scalarproduct_int16(sig_scaled - best_delay_int + RES_PREV_DATA_SIZE, + sig_scaled - best_delay_int + RES_PREV_DATA_SIZE, + subframe_size); + + /* Compute signals with non-integer delay k (with 1/8 precision), + where k is in [0;6] range. + Entire delay is qual to best_delay+(k+1)/8 + This is archieved by applying an interpolation filter of + legth 33 to source signal. */ + for (k = 0; k < ANALYZED_FRAC_DELAYS; k++) { + ff_acelp_interpolate(&delayed_signal[k][0], + &sig_scaled[RES_PREV_DATA_SIZE - best_delay_int], + ff_g729_interp_filt_short, + ANALYZED_FRAC_DELAYS+1, + 8 - k - 1, + SHORT_INT_FILT_LEN, + subframe_size + 1); + } + + /* Compute denominator of pseudo-normalized correlation R'(k). + + corr_den[k][0] is square root of R'(k) denominator, for int(T) == int(T0) + corr_den[k][1] is square root of R'(k) denominator, for int(T) == int(T0)+1 + + Also compute maximum value of above denominators over all k. */ + tmp = corr_int_den; + for (k = 0; k < ANALYZED_FRAC_DELAYS; k++) { + sum = dsp->scalarproduct_int16(&delayed_signal[k][1], + &delayed_signal[k][1], + subframe_size - 1); + corr_den[k][0] = sum + delayed_signal[k][0 ] * delayed_signal[k][0 ]; + corr_den[k][1] = sum + delayed_signal[k][subframe_size] * delayed_signal[k][subframe_size]; + + tmp = FFMAX3(tmp, corr_den[k][0], corr_den[k][1]); + } + + sh_gain_den = av_log2(tmp) - 14; + if (sh_gain_den >= 0) { + + sh_gain_num = FFMAX(sh_gain_den, sh_ener); + /* Loop through all k and find delay that maximizes + R'(k) correlation. + Search is done in [int(T0)-1; intT(0)+1] range + with 1/8 precision. */ + delayed_signal_offset = 1; + best_delay_frac = 0; + gain_den = corr_int_den >> sh_gain_den; + gain_num = corr_int_num >> sh_gain_num; + gain_num_square = gain_num * gain_num; + for (k = 0; k < ANALYZED_FRAC_DELAYS; k++) { + for (i = 0; i < 2; i++) { + int16_t gain_num_short, gain_den_short; + int gain_num_short_square; + /* Compute numerator of pseudo-normalized + correlation R'(k). */ + sum = dsp->scalarproduct_int16(&delayed_signal[k][i], + sig_scaled + RES_PREV_DATA_SIZE, + subframe_size); + gain_num_short = FFMAX(sum >> sh_gain_num, 0); + + /* + gain_num_short_square gain_num_square + R'(T)^2 = -----------------------, max R'(T)^2= -------------- + den gain_den + */ + gain_num_short_square = gain_num_short * gain_num_short; + gain_den_short = corr_den[k][i] >> sh_gain_den; + + tmp = MULL(gain_num_short_square, gain_den, FRAC_BITS); + tmp2 = MULL(gain_num_square, gain_den_short, FRAC_BITS); + + // R'(T)^2 > max R'(T)^2 + if (tmp > tmp2) { + gain_num = gain_num_short; + gain_den = gain_den_short; + gain_num_square = gain_num_short_square; + delayed_signal_offset = i; + best_delay_frac = k + 1; + } + } + } + + /* + R'(T)^2 + 2 * --------- < 1 + R(0) + */ + L64_temp0 = (int64_t)gain_num_square << ((sh_gain_num << 1) + 1); + L64_temp1 = ((int64_t)gain_den * ener) << (sh_gain_den + sh_ener); + if (L64_temp0 < L64_temp1) + gain_num = 0; + } // if(sh_gain_den >= 0) + } // if(corr_int_num) + } // if(ener) + /* End of best delay searching code */ + + if (!gain_num) { + memcpy(residual_filt, residual + RES_PREV_DATA_SIZE, subframe_size * sizeof(int16_t)); + + /* Long-term prediction gain is less than 3dB. Long-term postfilter is disabled. */ + return 0; + } + if (best_delay_frac) { + /* Recompute delayed signal with an interpolation filter of length 129. */ + ff_acelp_interpolate(residual_filt, + &sig_scaled[RES_PREV_DATA_SIZE - best_delay_int + delayed_signal_offset], + ff_g729_interp_filt_long, + ANALYZED_FRAC_DELAYS + 1, + 8 - best_delay_frac, + LONG_INT_FILT_LEN, + subframe_size + 1); + /* Compute R'(k) correlation's numerator. */ + sum = dsp->scalarproduct_int16(residual_filt, + sig_scaled + RES_PREV_DATA_SIZE, + subframe_size); + + if (sum < 0) { + gain_long_num = 0; + sh_gain_long_num = 0; + } else { + tmp = FFMAX(av_log2(sum) - 14, 0); + sum >>= tmp; + gain_long_num = sum; + sh_gain_long_num = tmp; + } + + /* Compute R'(k) correlation's denominator. */ + sum = dsp->scalarproduct_int16(residual_filt, residual_filt, subframe_size); + + tmp = FFMAX(av_log2(sum) - 14, 0); + sum >>= tmp; + gain_long_den = sum; + sh_gain_long_den = tmp; + + /* Select between original and delayed signal. + Delayed signal will be selected if it increases R'(k) + correlation. */ + L_temp0 = gain_num * gain_num; + L_temp0 = MULL(L_temp0, gain_long_den, FRAC_BITS); + + L_temp1 = gain_long_num * gain_long_num; + L_temp1 = MULL(L_temp1, gain_den, FRAC_BITS); + + tmp = ((sh_gain_long_num - sh_gain_num) << 1) - (sh_gain_long_den - sh_gain_den); + if (tmp > 0) + L_temp0 >>= tmp; + else + L_temp1 >>= -tmp; + + /* Check if longer filter increases the values of R'(k). */ + if (L_temp1 > L_temp0) { + /* Select long filter. */ + selected_signal = residual_filt; + gain_num = gain_long_num; + gain_den = gain_long_den; + sh_gain_num = sh_gain_long_num; + sh_gain_den = sh_gain_long_den; + } else + /* Select short filter. */ + selected_signal = &delayed_signal[best_delay_frac-1][delayed_signal_offset]; + + /* Rescale selected signal to original value. */ + if (shift > 0) + for (i = 0; i < subframe_size; i++) + selected_signal[i] <<= shift; + else + for (i = 0; i < subframe_size; i++) + selected_signal[i] >>= -shift; + + /* necessary to avoid compiler warning */ + selected_signal_const = selected_signal; + } // if(best_delay_frac) + else + selected_signal_const = residual + RES_PREV_DATA_SIZE - (best_delay_int + 1 - delayed_signal_offset); +#ifdef G729_BITEXACT + tmp = sh_gain_num - sh_gain_den; + if (tmp > 0) + gain_den >>= tmp; + else + gain_num >>= -tmp; + + if (gain_num > gain_den) + lt_filt_factor_a = MIN_LT_FILT_FACTOR_A; + else { + gain_num >>= 2; + gain_den >>= 1; + lt_filt_factor_a = (gain_den << 15) / (gain_den + gain_num); + } +#else + L64_temp0 = ((int64_t)gain_num) << (sh_gain_num - 1); + L64_temp1 = ((int64_t)gain_den) << sh_gain_den; + lt_filt_factor_a = FFMAX((L64_temp1 << 15) / (L64_temp1 + L64_temp0), MIN_LT_FILT_FACTOR_A); +#endif + + /* Filter through selected filter. */ + lt_filt_factor_b = 32767 - lt_filt_factor_a + 1; + + ff_acelp_weighted_vector_sum(residual_filt, residual + RES_PREV_DATA_SIZE, + selected_signal_const, + lt_filt_factor_a, lt_filt_factor_b, + 1<<14, 15, subframe_size); + + // Long-term prediction gain is larger than 3dB. + return 1; +} + +/** + * \brief Calculate reflection coefficient for tilt compensation filter (4.2.3). + * \param dsp initialized DSP context + * \param lp_gn (3.12) coefficients of A(z/FORMANT_PP_FACTOR_NUM) filter + * \param lp_gd (3.12) coefficients of A(z/FORMANT_PP_FACTOR_DEN) filter + * \param speech speech to update + * \param subframe_size size of subframe + * + * \return (3.12) reflection coefficient + * + * \remark The routine also calculates the gain term for the short-term + * filter (gf) and multiplies the speech data by 1/gf. + * + * \note All members of lp_gn, except 10-19 must be equal to zero. + */ +static int16_t get_tilt_comp(DSPContext *dsp, int16_t *lp_gn, + const int16_t *lp_gd, int16_t* speech, + int subframe_size) +{ + int rh1,rh0; // (3.12) + int temp; + int i; + int gain_term; + + lp_gn[10] = 4096; //1.0 in (3.12) + + /* Apply 1/A(z/FORMANT_PP_FACTOR_DEN) filter to hf. */ + ff_celp_lp_synthesis_filter(lp_gn + 11, lp_gd + 1, lp_gn + 11, 22, 10, 0, 0, 0x800); + /* Now lp_gn (starting with 10) contains impulse response + of A(z/FORMANT_PP_FACTOR_NUM)/A(z/FORMANT_PP_FACTOR_DEN) filter. */ + + rh0 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 10, 20); + rh1 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 11, 20); + + /* downscale to avoid overflow */ + temp = av_log2(rh0) - 14; + if (temp > 0) { + rh0 >>= temp; + rh1 >>= temp; + } + + if (FFABS(rh1) > rh0 || !rh0) + return 0; + + gain_term = 0; + for (i = 0; i < 20; i++) + gain_term += FFABS(lp_gn[i + 10]); + gain_term >>= 2; // (3.12) -> (5.10) + + if (gain_term > 0x400) { // 1.0 in (5.10) + temp = 0x2000000 / gain_term; // 1.0/gain_term in (0.15) + for (i = 0; i < subframe_size; i++) + speech[i] = (speech[i] * temp + 0x4000) >> 15; + } + + return -(rh1 << 15) / rh0; +} + +/** + * \brief Apply tilt compensation filter (4.2.3). + * \param res_pst [in/out] residual signal (partially filtered) + * \param k1 (3.12) reflection coefficient + * \param subframe_size size of subframe + * \param ht_prev_data previous data for 4.2.3, equation 86 + * + * \return new value for ht_prev_data +*/ +static int16_t apply_tilt_comp(int16_t* out, int16_t* res_pst, int refl_coeff, + int subframe_size, int16_t ht_prev_data) +{ + int tmp, tmp2; + int i; + int gt, ga; + int fact, sh_fact; + + if (refl_coeff > 0) { + gt = (refl_coeff * G729_TILT_FACTOR_PLUS + 0x4000) >> 15; + fact = 0x4000; // 0.5 in (0.15) + sh_fact = 15; + } else { + gt = (refl_coeff * G729_TILT_FACTOR_MINUS + 0x4000) >> 15; + fact = 0x800; // 0.5 in (3.12) + sh_fact = 12; + } + ga = (fact << 15) / av_clip_int16(32768 - FFABS(gt)); + gt >>= 1; + + /* Apply tilt compensation filter to signal. */ + tmp = res_pst[subframe_size - 1]; + + for (i = subframe_size - 1; i >= 1; i--) { + tmp2 = (res_pst[i] << 15) + ((gt * res_pst[i-1]) << 1); + tmp2 = (tmp2 + 0x4000) >> 15; + + tmp2 = (tmp2 * ga * 2 + fact) >> sh_fact; + out[i] = tmp2; + } + tmp2 = (res_pst[0] << 15) + ((gt * ht_prev_data) << 1); + tmp2 = (tmp2 + 0x4000) >> 15; + tmp2 = (tmp2 * ga * 2 + fact) >> sh_fact; + out[0] = tmp2; + + return tmp; +} + +void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing, + const int16_t *lp_filter_coeffs, int pitch_delay_int, + int16_t* residual, int16_t* res_filter_data, + int16_t* pos_filter_data, int16_t *speech, int subframe_size) +{ + int16_t residual_filt_buf[SUBFRAME_SIZE+11]; + int16_t lp_gn[33]; // (3.12) + int16_t lp_gd[11]; // (3.12) + int tilt_comp_coeff; + int i; + + /* Zero-filling is necessary for tilt-compensation filter. */ + memset(lp_gn, 0, 33 * sizeof(int16_t)); + + /* Calculate A(z/FORMANT_PP_FACTOR_NUM) filter coefficients. */ + for (i = 0; i < 10; i++) + lp_gn[i + 11] = (lp_filter_coeffs[i + 1] * formant_pp_factor_num_pow[i] + 0x4000) >> 15; + + /* Calculate A(z/FORMANT_PP_FACTOR_DEN) filter coefficients. */ + for (i = 0; i < 10; i++) + lp_gd[i + 1] = (lp_filter_coeffs[i + 1] * formant_pp_factor_den_pow[i] + 0x4000) >> 15; + + /* residual signal calculation (one-half of short-term postfilter) */ + memcpy(speech - 10, res_filter_data, 10 * sizeof(int16_t)); + residual_filter(residual + RES_PREV_DATA_SIZE, lp_gn + 11, speech, subframe_size); + /* Save data to use it in the next subframe. */ + memcpy(res_filter_data, speech + subframe_size - 10, 10 * sizeof(int16_t)); + + /* long-term filter. If long-term prediction gain is larger than 3dB (returned value is + nonzero) then declare current subframe as periodic. */ + *voicing = FFMAX(*voicing, long_term_filter(dsp, pitch_delay_int, + residual, residual_filt_buf + 10, + subframe_size)); + + /* shift residual for using in next subframe */ + memmove(residual, residual + subframe_size, RES_PREV_DATA_SIZE * sizeof(int16_t)); + + /* short-term filter tilt compensation */ + tilt_comp_coeff = get_tilt_comp(dsp, lp_gn, lp_gd, residual_filt_buf + 10, subframe_size); + + /* Apply second half of short-term postfilter: 1/A(z/FORMANT_PP_FACTOR_DEN) */ + ff_celp_lp_synthesis_filter(pos_filter_data + 10, lp_gd + 1, + residual_filt_buf + 10, + subframe_size, 10, 0, 0, 0x800); + memcpy(pos_filter_data, pos_filter_data + subframe_size, 10 * sizeof(int16_t)); + + *ht_prev_data = apply_tilt_comp(speech, pos_filter_data + 10, tilt_comp_coeff, + subframe_size, *ht_prev_data); +} + +/** + * \brief Adaptive gain control (4.2.4) + * \param gain_before gain of speech before applying postfilters + * \param gain_after gain of speech after applying postfilters + * \param speech [in/out] signal buffer + * \param subframe_size length of subframe + * \param gain_prev (3.12) previous value of gain coefficient + * + * \return (3.12) last value of gain coefficient + */ +int16_t ff_g729_adaptive_gain_control(int gain_before, int gain_after, int16_t *speech, + int subframe_size, int16_t gain_prev) +{ + int gain; // (3.12) + int n; + int exp_before, exp_after; + + if(!gain_after && gain_before) + return 0; + + if (gain_before) { + + exp_before = 14 - av_log2(gain_before); + gain_before = bidir_sal(gain_before, exp_before); + + exp_after = 14 - av_log2(gain_after); + gain_after = bidir_sal(gain_after, exp_after); + + if (gain_before < gain_after) { + gain = (gain_before << 15) / gain_after; + gain = bidir_sal(gain, exp_after - exp_before - 1); + } else { + gain = ((gain_before - gain_after) << 14) / gain_after + 0x4000; + gain = bidir_sal(gain, exp_after - exp_before); + } + gain = (gain * G729_AGC_FAC1 + 0x4000) >> 15; // gain * (1-0.9875) + } else + gain = 0; + + for (n = 0; n < subframe_size; n++) { + // gain_prev = gain + 0.9875 * gain_prev + gain_prev = (G729_AGC_FACTOR * gain_prev + 0x4000) >> 15; + gain_prev = av_clip_int16(gain + gain_prev); + speech[n] = av_clip_int16((speech[n] * gain_prev + 0x2000) >> 14); + } + return gain_prev; +} diff --git a/ffmpeg/libavcodec/g729postfilter.h b/ffmpeg/libavcodec/g729postfilter.h new file mode 100644 index 0000000..5239fc8 --- /dev/null +++ b/ffmpeg/libavcodec/g729postfilter.h @@ -0,0 +1,116 @@ +/* + * G.729, G729 Annex D postfilter + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ +#ifndef FFMPEG_G729POSTFILTER_H +#define FFMPEG_G729POSTFILTER_H + +#include +#include "dsputil.h" + +/** + * tilt compensation factor (G.729, k1>0) + * 0.2 in Q15 + */ +#define G729_TILT_FACTOR_PLUS 6554 + +/** + * tilt compensation factor (G.729, k1<0) + * 0.9 in Q15 + */ +#define G729_TILT_FACTOR_MINUS 29491 + +/* 4.2.2 */ +#define FORMANT_PP_FACTOR_NUM 18022 //0.55 in Q15 +#define FORMANT_PP_FACTOR_DEN 22938 //0.70 in Q15 + +/** + * gain adjustment factor (G.729, 4.2.4) + * 0.9875 in Q15 + */ +#define G729_AGC_FACTOR 32358 +#define G729_AGC_FAC1 (32768-G729_AGC_FACTOR) + +/** + * 1.0 / (1.0 + 0.5) in Q15 + * where 0.5 is the minimum value of + * weight factor, controlling amount of long-term postfiltering + */ +#define MIN_LT_FILT_FACTOR_A 21845 + +/** + * Short interpolation filter length + */ +#define SHORT_INT_FILT_LEN 2 + +/** + * Long interpolation filter length + */ +#define LONG_INT_FILT_LEN 8 + +/** + * Number of analyzed fractional pitch delays in second stage of long-term + * postfilter + */ +#define ANALYZED_FRAC_DELAYS 7 + +/** + * Amount of past residual signal data stored in buffer + */ +#define RES_PREV_DATA_SIZE (PITCH_DELAY_MAX + LONG_INT_FILT_LEN + 1) + +/** + * \brief Signal postfiltering (4.2) + * \param dsp initialized DSP context + * \param ht_prev_data [in/out] (Q12) pointer to variable receiving tilt + * compensation filter data from previous subframe + * \param voicing [in/out] (Q0) pointer to variable receiving voicing decision + * \param lp_filter_coeffs (Q12) LP filter coefficients + * \param pitch_delay_int integer part of the pitch delay + * \param residual [in/out] (Q0) residual signal buffer (used in long-term postfilter) + * \param res_filter_data [in/out] (Q0) speech data of previous subframe + * \param pos_filter_data [in/out] (Q0) previous speech data for short-term postfilter + * \param speech [in/out] (Q0) signal buffer + * \param subframe_size size of subframe + * + * Filtering has the following stages: + * Long-term postfilter (4.2.1) + * Short-term postfilter (4.2.2). + * Tilt-compensation (4.2.3) + */ +void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing, + const int16_t *lp_filter_coeffs, int pitch_delay_int, + int16_t* residual, int16_t* res_filter_data, + int16_t* pos_filter_data, int16_t *speech, + int subframe_size); + +/** + * \brief Adaptive gain control (4.2.4) + * \param gain_before (Q0) gain of speech before applying postfilters + * \param gain_after (Q0) gain of speech after applying postfilters + * \param speech [in/out] (Q0) signal buffer + * \param subframe_size length of subframe + * \param gain_prev (Q12) previous value of gain coefficient + * + * \return (Q12) last value of gain coefficient + */ +int16_t ff_g729_adaptive_gain_control(int gain_before, int gain_after, int16_t *speech, + int subframe_size, int16_t gain_prev); + +#endif // FFMPEG_G729POSTFILTER_H diff --git a/ffmpeg/libavcodec/get_bits.h b/ffmpeg/libavcodec/get_bits.h new file mode 100644 index 0000000..f16a508 --- /dev/null +++ b/ffmpeg/libavcodec/get_bits.h @@ -0,0 +1,631 @@ +/* + * copyright (c) 2004 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 + */ + +/** + * @file + * bitstream reader API header. + */ + +#ifndef AVCODEC_GET_BITS_H +#define AVCODEC_GET_BITS_H + +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/avassert.h" +#include "mathops.h" + +/* + * Safe bitstream reading: + * optionally, the get_bits API can check to ensure that we + * don't read past input buffer boundaries. This is protected + * with CONFIG_SAFE_BITSTREAM_READER at the global level, and + * then below that with UNCHECKED_BITSTREAM_READER at the per- + * decoder level. This means that decoders that check internally + * can "#define UNCHECKED_BITSTREAM_READER 1" to disable + * overread checks. + * Boundary checking causes a minor performance penalty so for + * applications that won't want/need this, it can be disabled + * globally using "#define CONFIG_SAFE_BITSTREAM_READER 0". + */ +#ifndef UNCHECKED_BITSTREAM_READER +#define UNCHECKED_BITSTREAM_READER !CONFIG_SAFE_BITSTREAM_READER +#endif + +typedef struct GetBitContext { + const uint8_t *buffer, *buffer_end; + int index; + int size_in_bits; + int size_in_bits_plus8; +} GetBitContext; + +#define VLC_TYPE int16_t + +typedef struct VLC { + int bits; + VLC_TYPE (*table)[2]; ///< code, bits + int table_size, table_allocated; +} VLC; + +typedef struct RL_VLC_ELEM { + int16_t level; + int8_t len; + uint8_t run; +} RL_VLC_ELEM; + +/* Bitstream reader API docs: + * name + * arbitrary name which is used as prefix for the internal variables + * + * gb + * getbitcontext + * + * OPEN_READER(name, gb) + * load gb into local variables + * + * CLOSE_READER(name, gb) + * store local vars in gb + * + * UPDATE_CACHE(name, gb) + * Refill the internal cache from the bitstream. + * After this call at least MIN_CACHE_BITS will be available. + * + * GET_CACHE(name, gb) + * Will output the contents of the internal cache, + * next bit is MSB of 32 or 64 bit (FIXME 64bit). + * + * SHOW_UBITS(name, gb, num) + * Will return the next num bits. + * + * SHOW_SBITS(name, gb, num) + * Will return the next num bits and do sign extension. + * + * SKIP_BITS(name, gb, num) + * Will skip over the next num bits. + * Note, this is equivalent to SKIP_CACHE; SKIP_COUNTER. + * + * SKIP_CACHE(name, gb, num) + * Will remove the next num bits from the cache (note SKIP_COUNTER + * MUST be called before UPDATE_CACHE / CLOSE_READER). + * + * SKIP_COUNTER(name, gb, num) + * Will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS). + * + * LAST_SKIP_BITS(name, gb, num) + * Like SKIP_BITS, to be used if next call is UPDATE_CACHE or CLOSE_READER. + * + * For examples see get_bits, show_bits, skip_bits, get_vlc. + */ + +#ifdef LONG_BITSTREAM_READER +# define MIN_CACHE_BITS 32 +#else +# define MIN_CACHE_BITS 25 +#endif + +#if UNCHECKED_BITSTREAM_READER +#define OPEN_READER(name, gb) \ + unsigned int name ## _index = (gb)->index; \ + unsigned int av_unused name ## _cache + +#define HAVE_BITS_REMAINING(name, gb) 1 +#else +#define OPEN_READER(name, gb) \ + unsigned int name ## _index = (gb)->index; \ + unsigned int av_unused name ## _cache = 0; \ + unsigned int av_unused name ## _size_plus8 = (gb)->size_in_bits_plus8 + +#define HAVE_BITS_REMAINING(name, gb) name ## _index < name ## _size_plus8 +#endif + +#define CLOSE_READER(name, gb) (gb)->index = name ## _index + +#ifdef BITSTREAM_READER_LE + +# ifdef LONG_BITSTREAM_READER +# define UPDATE_CACHE(name, gb) name ## _cache = \ + AV_RL64((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) +# else +# define UPDATE_CACHE(name, gb) name ## _cache = \ + AV_RL32((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7) +# endif + +# define SKIP_CACHE(name, gb, num) name ## _cache >>= (num) + +#else + +# ifdef LONG_BITSTREAM_READER +# define UPDATE_CACHE(name, gb) name ## _cache = \ + AV_RB64((gb)->buffer + (name ## _index >> 3)) >> (32 - (name ## _index & 7)) +# else +# define UPDATE_CACHE(name, gb) name ## _cache = \ + AV_RB32((gb)->buffer + (name ## _index >> 3)) << (name ## _index & 7) +# endif + +# define SKIP_CACHE(name, gb, num) name ## _cache <<= (num) + +#endif + +#if UNCHECKED_BITSTREAM_READER +# define SKIP_COUNTER(name, gb, num) name ## _index += (num) +#else +# define SKIP_COUNTER(name, gb, num) \ + name ## _index = FFMIN(name ## _size_plus8, name ## _index + (num)) +#endif + +#define SKIP_BITS(name, gb, num) \ + do { \ + SKIP_CACHE(name, gb, num); \ + SKIP_COUNTER(name, gb, num); \ + } while (0) + +#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) + +#ifdef BITSTREAM_READER_LE +# define SHOW_UBITS(name, gb, num) zero_extend(name ## _cache, num) +# define SHOW_SBITS(name, gb, num) sign_extend(name ## _cache, num) +#else +# define SHOW_UBITS(name, gb, num) NEG_USR32(name ## _cache, num) +# define SHOW_SBITS(name, gb, num) NEG_SSR32(name ## _cache, num) +#endif + +#define GET_CACHE(name, gb) ((uint32_t) name ## _cache) + +static inline int get_bits_count(const GetBitContext *s) +{ + return s->index; +} + +static inline void skip_bits_long(GetBitContext *s, int n) +{ +#if UNCHECKED_BITSTREAM_READER + s->index += n; +#else + s->index += av_clip(n, -s->index, s->size_in_bits_plus8 - s->index); +#endif +} + +/** + * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). + * if MSB not set it is negative + * @param n length in bits + */ +static inline int get_xbits(GetBitContext *s, int n) +{ + register int sign; + register int32_t cache; + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + cache = GET_CACHE(re, s); + sign = ~cache >> 31; + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; +} + +static inline int get_sbits(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER(re, s); + av_assert2(n>0 && n<=25); + UPDATE_CACHE(re, s); + tmp = SHOW_SBITS(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return tmp; +} + +/** + * Read 1-25 bits. + */ +static inline unsigned int get_bits(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER(re, s); + av_assert2(n>0 && n<=25); + UPDATE_CACHE(re, s); + tmp = SHOW_UBITS(re, s, n); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); + return tmp; +} + +/** + * Show 1-25 bits. + */ +static inline unsigned int show_bits(GetBitContext *s, int n) +{ + register int tmp; + OPEN_READER(re, s); + av_assert2(n>0 && n<=25); + UPDATE_CACHE(re, s); + tmp = SHOW_UBITS(re, s, n); + return tmp; +} + +static inline void skip_bits(GetBitContext *s, int n) +{ + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + LAST_SKIP_BITS(re, s, n); + CLOSE_READER(re, s); +} + +static inline unsigned int get_bits1(GetBitContext *s) +{ + unsigned int index = s->index; + uint8_t result = s->buffer[index >> 3]; +#ifdef BITSTREAM_READER_LE + result >>= index & 7; + result &= 1; +#else + result <<= index & 7; + result >>= 8 - 1; +#endif +#if !UNCHECKED_BITSTREAM_READER + if (s->index < s->size_in_bits_plus8) +#endif + index++; + s->index = index; + + return result; +} + +static inline unsigned int show_bits1(GetBitContext *s) +{ + return show_bits(s, 1); +} + +static inline void skip_bits1(GetBitContext *s) +{ + skip_bits(s, 1); +} + +/** + * Read 0-32 bits. + */ +static inline unsigned int get_bits_long(GetBitContext *s, int n) +{ + if (!n) { + return 0; + } else if (n <= MIN_CACHE_BITS) { + return get_bits(s, n); + } else { +#ifdef BITSTREAM_READER_LE + unsigned ret = get_bits(s, 16); + return ret | (get_bits(s, n - 16) << 16); +#else + unsigned ret = get_bits(s, 16) << (n - 16); + return ret | get_bits(s, n - 16); +#endif + } +} + +/** + * Read 0-64 bits. + */ +static inline uint64_t get_bits64(GetBitContext *s, int n) +{ + if (n <= 32) { + return get_bits_long(s, n); + } else { +#ifdef BITSTREAM_READER_LE + uint64_t ret = get_bits_long(s, 32); + return ret | (uint64_t) get_bits_long(s, n - 32) << 32; +#else + uint64_t ret = (uint64_t) get_bits_long(s, n - 32) << 32; + return ret | get_bits_long(s, 32); +#endif + } +} + +/** + * Read 0-32 bits as a signed integer. + */ +static inline int get_sbits_long(GetBitContext *s, int n) +{ + return sign_extend(get_bits_long(s, n), n); +} + +/** + * Show 0-32 bits. + */ +static inline unsigned int show_bits_long(GetBitContext *s, int n) +{ + if (n <= MIN_CACHE_BITS) { + return show_bits(s, n); + } else { + GetBitContext gb = *s; + return get_bits_long(&gb, n); + } +} + +static inline int check_marker(GetBitContext *s, const char *msg) +{ + int bit = get_bits1(s); + if (!bit) + av_log(NULL, AV_LOG_INFO, "Marker bit missing %s\n", msg); + + return bit; +} + +/** + * Initialize GetBitContext. + * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param bit_size the size of the buffer in bits + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, + int bit_size) +{ + int buffer_size; + int ret = 0; + + if (bit_size >= INT_MAX - 7 || bit_size < 0 || !buffer) { + buffer_size = bit_size = 0; + buffer = NULL; + ret = AVERROR_INVALIDDATA; + } + + buffer_size = (bit_size + 7) >> 3; + + s->buffer = buffer; + s->size_in_bits = bit_size; + s->size_in_bits_plus8 = bit_size + 8; + s->buffer_end = buffer + buffer_size; + s->index = 0; + + return ret; +} + +/** + * Initialize GetBitContext. + * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes + * larger than the actual read bits because some optimized bitstream + * readers read 32 or 64 bit at once and could read over the end + * @param byte_size the size of the buffer in bytes + * @return 0 on success, AVERROR_INVALIDDATA if the buffer_size would overflow. + */ +static inline int init_get_bits8(GetBitContext *s, const uint8_t *buffer, + int byte_size) +{ + if (byte_size > INT_MAX / 8 || byte_size < 0) + byte_size = -1; + return init_get_bits(s, buffer, byte_size * 8); +} + +static inline const uint8_t *align_get_bits(GetBitContext *s) +{ + int n = -get_bits_count(s) & 7; + if (n) + skip_bits(s, n); + return s->buffer + (s->index >> 3); +} + +#define init_vlc(vlc, nb_bits, nb_codes, \ + bits, bits_wrap, bits_size, \ + codes, codes_wrap, codes_size, \ + flags) \ + ff_init_vlc_sparse(vlc, nb_bits, nb_codes, \ + bits, bits_wrap, bits_size, \ + codes, codes_wrap, codes_size, \ + NULL, 0, 0, flags) + +int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + const void *symbols, int symbols_wrap, int symbols_size, + int flags); +void ff_free_vlc(VLC *vlc); + +#define INIT_VLC_LE 2 +#define INIT_VLC_USE_NEW_STATIC 4 + +#define INIT_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size) \ + do { \ + static VLC_TYPE table[static_size][2]; \ + (vlc)->table = table; \ + (vlc)->table_allocated = static_size; \ + init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \ + } while (0) + +/** + * If the vlc code is invalid and max_depth=1, then no bits will be removed. + * If the vlc code is invalid and max_depth>1, then the number of bits removed + * is undefined. + */ +#define GET_VLC(code, name, gb, table, bits, max_depth) \ + do { \ + int n, nb_bits; \ + unsigned int index; \ + \ + index = SHOW_UBITS(name, gb, bits); \ + code = table[index][0]; \ + n = table[index][1]; \ + \ + if (max_depth > 1 && n < 0) { \ + LAST_SKIP_BITS(name, gb, bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + if (max_depth > 2 && n < 0) { \ + LAST_SKIP_BITS(name, gb, nb_bits); \ + UPDATE_CACHE(name, gb); \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + code; \ + code = table[index][0]; \ + n = table[index][1]; \ + } \ + } \ + SKIP_BITS(name, gb, n); \ + } while (0) + +#define GET_RL_VLC(level, run, name, gb, table, bits, \ + max_depth, need_update) \ + do { \ + int n, nb_bits; \ + unsigned int index; \ + \ + index = SHOW_UBITS(name, gb, bits); \ + level = table[index].level; \ + n = table[index].len; \ + \ + if (max_depth > 1 && n < 0) { \ + SKIP_BITS(name, gb, bits); \ + if (need_update) { \ + UPDATE_CACHE(name, gb); \ + } \ + \ + nb_bits = -n; \ + \ + index = SHOW_UBITS(name, gb, nb_bits) + level; \ + level = table[index].level; \ + n = table[index].len; \ + } \ + run = table[index].run; \ + SKIP_BITS(name, gb, n); \ + } while (0) + +/** + * Parse a vlc code. + * @param bits is the number of bits which will be read at once, must be + * identical to nb_bits in init_vlc() + * @param max_depth is the number of times bits bits must be read to completely + * read the longest vlc code + * = (max_vlc_length + bits - 1) / bits + */ +static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth) +{ + int code; + + OPEN_READER(re, s); + UPDATE_CACHE(re, s); + + GET_VLC(code, re, s, table, bits, max_depth); + + CLOSE_READER(re, s); + + return code; +} + +static inline int decode012(GetBitContext *gb) +{ + int n; + n = get_bits1(gb); + if (n == 0) + return 0; + else + return get_bits1(gb) + 1; +} + +static inline int decode210(GetBitContext *gb) +{ + if (get_bits1(gb)) + return 0; + else + return 2 - get_bits1(gb); +} + +static inline int get_bits_left(GetBitContext *gb) +{ + return gb->size_in_bits - get_bits_count(gb); +} + +//#define TRACE + +#ifdef TRACE +static inline void print_bin(int bits, int n) +{ + int i; + + for (i = n - 1; i >= 0; i--) + av_log(NULL, AV_LOG_DEBUG, "%d", (bits >> i) & 1); + for (i = n; i < 24; i++) + av_log(NULL, AV_LOG_DEBUG, " "); +} + +static inline int get_bits_trace(GetBitContext *s, int n, const char *file, + const char *func, int line) +{ + int r = get_bits(s, n); + + print_bin(r, n); + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d bit @%5d in %s %s:%d\n", + r, n, r, get_bits_count(s) - n, file, func, line); + + return r; +} + +static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], + int bits, int max_depth, const char *file, + const char *func, int line) +{ + int show = show_bits(s, 24); + int pos = get_bits_count(s); + int r = get_vlc2(s, table, bits, max_depth); + int len = get_bits_count(s) - pos; + int bits2 = show >> (24 - len); + + print_bin(bits2, len); + + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d vlc @%5d in %s %s:%d\n", + bits2, len, r, pos, file, func, line); + + return r; +} + +static inline int get_xbits_trace(GetBitContext *s, int n, const char *file, + const char *func, int line) +{ + int show = show_bits(s, n); + int r = get_xbits(s, n); + + print_bin(show, n); + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d xbt @%5d in %s %s:%d\n", + show, n, r, get_bits_count(s) - n, file, func, line); + + return r; +} + +#define get_bits(s, n) get_bits_trace(s , n, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_bits1(s) get_bits_trace(s, 1, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define get_vlc(s, vlc) get_vlc_trace(s, (vlc)->table, (vlc)->bits, 3, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#define tprintf(p, ...) av_log(p, AV_LOG_DEBUG, __VA_ARGS__) + +#else //TRACE +#define tprintf(p, ...) { } +#endif + +#endif /* AVCODEC_GET_BITS_H */ diff --git a/ffmpeg/libavcodec/gif.c b/ffmpeg/libavcodec/gif.c new file mode 100644 index 0000000..de3e576 --- /dev/null +++ b/ffmpeg/libavcodec/gif.c @@ -0,0 +1,205 @@ +/* + * GIF encoder. + * Copyright (c) 2000 Fabrice Bellard + * Copyright (c) 2002 Francois Revol + * Copyright (c) 2006 Baptiste Coudurier + * + * 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 + */ + +/* + * First version by Francois Revol revol@free.fr + * + * Features and limitations: + * - uses only a global standard palette + * - tested with IE 5.0, Opera for BeOS, NetPositive (BeOS), and Mozilla (BeOS). + * + * Reference documents: + * http://www.goice.co.jp/member/mo/formats/gif.html + * http://astronomy.swin.edu.au/pbourke/dataformats/gif/ + * http://www.dcs.ed.ac.uk/home/mxr/gfx/2d/GIF89a.txt + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "lzw.h" + +/* The GIF format uses reversed order for bitstreams... */ +/* at least they don't use PDP_ENDIAN :) */ +#define BITSTREAM_WRITER_LE + +#include "put_bits.h" + +typedef struct { + AVFrame picture; + LZWState *lzw; + uint8_t *buf; +} GIFContext; + +/* GIF header */ +static int gif_image_write_header(AVCodecContext *avctx, + uint8_t **bytestream, uint32_t *palette) +{ + int i; + unsigned int v, smallest_alpha = 0xFF, alpha_component = 0; + + bytestream_put_buffer(bytestream, "GIF", 3); + bytestream_put_buffer(bytestream, "89a", 3); + bytestream_put_le16(bytestream, avctx->width); + bytestream_put_le16(bytestream, avctx->height); + + bytestream_put_byte(bytestream, 0xf7); /* flags: global clut, 256 entries */ + bytestream_put_byte(bytestream, 0x1f); /* background color index */ + bytestream_put_byte(bytestream, 0); /* aspect ratio */ + + /* the global palette */ + for(i=0;i<256;i++) { + v = palette[i]; + bytestream_put_be24(bytestream, v); + if (v >> 24 < smallest_alpha) { + smallest_alpha = v >> 24; + alpha_component = i; + } + } + + if (smallest_alpha < 128) { + bytestream_put_byte(bytestream, 0x21); /* Extension Introducer */ + bytestream_put_byte(bytestream, 0xf9); /* Graphic Control Label */ + bytestream_put_byte(bytestream, 0x04); /* block length */ + bytestream_put_byte(bytestream, 0x01); /* Transparent Color Flag */ + bytestream_put_le16(bytestream, 0x00); /* no delay */ + bytestream_put_byte(bytestream, alpha_component); + bytestream_put_byte(bytestream, 0x00); + } + + return 0; +} + +static int gif_image_write_image(AVCodecContext *avctx, + uint8_t **bytestream, uint8_t *end, + const uint8_t *buf, int linesize) +{ + GIFContext *s = avctx->priv_data; + int len = 0, height; + const uint8_t *ptr; + /* image block */ + + bytestream_put_byte(bytestream, 0x2c); + bytestream_put_le16(bytestream, 0); + bytestream_put_le16(bytestream, 0); + bytestream_put_le16(bytestream, avctx->width); + bytestream_put_le16(bytestream, avctx->height); + bytestream_put_byte(bytestream, 0x00); /* flags */ + /* no local clut */ + + bytestream_put_byte(bytestream, 0x08); + + ff_lzw_encode_init(s->lzw, s->buf, avctx->width*avctx->height, + 12, FF_LZW_GIF, put_bits); + + ptr = buf; + for (height = avctx->height; height--;) { + len += ff_lzw_encode(s->lzw, ptr, avctx->width); + ptr += linesize; + } + len += ff_lzw_encode_flush(s->lzw, flush_put_bits); + + ptr = s->buf; + while (len > 0) { + int size = FFMIN(255, len); + bytestream_put_byte(bytestream, size); + if (end - *bytestream < size) + return -1; + bytestream_put_buffer(bytestream, ptr, size); + ptr += size; + len -= size; + } + bytestream_put_byte(bytestream, 0x00); /* end of image block */ + bytestream_put_byte(bytestream, 0x3b); + return 0; +} + +static av_cold int gif_encode_init(AVCodecContext *avctx) +{ + GIFContext *s = avctx->priv_data; + + if (avctx->width > 65535 || avctx->height > 65535) { + av_log(avctx, AV_LOG_ERROR, "GIF does not support resolutions above 65535x65535\n"); + return -1; + } + + avctx->coded_frame = &s->picture; + s->lzw = av_mallocz(ff_lzw_encode_state_size); + if (!s->lzw) + return AVERROR(ENOMEM); + s->buf = av_malloc(avctx->width*avctx->height*2); + if (!s->buf) + return AVERROR(ENOMEM); + return 0; +} + +/* better than nothing gif encoder */ +static int gif_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + GIFContext *s = avctx->priv_data; + AVFrame *const p = &s->picture; + uint8_t *outbuf_ptr, *end; + int ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*7/5 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + outbuf_ptr = pkt->data; + end = pkt->data + pkt->size; + + *p = *pict; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + gif_image_write_header(avctx, &outbuf_ptr, (uint32_t *)pict->data[1]); + gif_image_write_image(avctx, &outbuf_ptr, end, pict->data[0], pict->linesize[0]); + + pkt->size = outbuf_ptr - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static int gif_encode_close(AVCodecContext *avctx) +{ + GIFContext *s = avctx->priv_data; + + av_freep(&s->lzw); + av_freep(&s->buf); + return 0; +} + +AVCodec ff_gif_encoder = { + .name = "gif", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_GIF, + .priv_data_size = sizeof(GIFContext), + .init = gif_encode_init, + .encode2 = gif_encode_frame, + .close = gif_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), +}; diff --git a/ffmpeg/libavcodec/gif.h b/ffmpeg/libavcodec/gif.h new file mode 100644 index 0000000..b557534 --- /dev/null +++ b/ffmpeg/libavcodec/gif.h @@ -0,0 +1,47 @@ +/* + * GIF format definitions + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2006 Baptiste Coudurier + * Copyright (c) 2012 Vitaliy E Sugrobov + * + * 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 + */ + +/** + * @file + * GIF format definitions. + */ + +#ifndef AVCODEC_GIFDEFS_H +#define AVCODEC_GIFDEFS_H + +#include + +static const uint8_t gif87a_sig[6] = "GIF87a"; +static const uint8_t gif89a_sig[6] = "GIF89a"; + +#define GCE_DISPOSAL_NONE 0 +#define GCE_DISPOSAL_INPLACE 1 +#define GCE_DISPOSAL_BACKGROUND 2 +#define GCE_DISPOSAL_RESTORE 3 + +#define GIF_TRAILER 0x3b +#define GIF_EXTENSION_INTRODUCER 0x21 +#define GIF_IMAGE_SEPARATOR 0x2c +#define GIF_GCE_EXT_LABEL 0xf9 + +#endif /* AVCODEC_GIFDEFS_H */ diff --git a/ffmpeg/libavcodec/gifdec.c b/ffmpeg/libavcodec/gifdec.c new file mode 100644 index 0000000..27364c9 --- /dev/null +++ b/ffmpeg/libavcodec/gifdec.c @@ -0,0 +1,545 @@ +/* + * GIF decoder + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2006 Baptiste Coudurier + * Copyright (c) 2012 Vitaliy E Sugrobov + * + * 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 + */ + +//#define DEBUG + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "lzw.h" +#include "gif.h" + +/* This value is intentionally set to "transparent white" color. + * It is much better to have white background instead of black + * when gif image converted to format which not support transparency. + */ +#define GIF_TRANSPARENT_COLOR 0x00ffffff + +typedef struct GifState { + const AVClass *class; + AVFrame *frame; + int screen_width; + int screen_height; + int has_global_palette; + int bits_per_pixel; + uint32_t bg_color; + int background_color_index; + int transparent_color_index; + int color_resolution; + /* intermediate buffer for storing color indices + * obtained from lzw-encoded data stream */ + uint8_t *idx_line; + int idx_line_size; + + /* after the frame is displayed, the disposal method is used */ + int gce_prev_disposal; + int gce_disposal; + /* rectangle describing area that must be disposed */ + int gce_l, gce_t, gce_w, gce_h; + /* depending on disposal method we store either part of the image + * drawn on the canvas or background color that + * should be used upon disposal */ + uint32_t * stored_img; + int stored_img_size; + int stored_bg_color; + + GetByteContext gb; + /* LZW compatible decoder */ + LZWState *lzw; + + /* aux buffers */ + uint32_t global_palette[256]; + uint32_t local_palette[256]; + + AVCodecContext *avctx; + int keyframe; + int keyframe_ok; + int trans_color; /**< color value that is used instead of transparent color */ +} GifState; + +static void gif_read_palette(GifState *s, uint32_t *pal, int nb) +{ + int i; + + for (i = 0; i < nb; i++, pal++) + *pal = (0xffu << 24) | bytestream2_get_be24u(&s->gb); +} + +static void gif_fill(AVFrame *picture, uint32_t color) +{ + uint32_t *p = (uint32_t *)picture->data[0]; + uint32_t *p_end = p + (picture->linesize[0] / sizeof(uint32_t)) * picture->height; + + for (; p < p_end; p++) + *p = color; +} + +static void gif_fill_rect(AVFrame *picture, uint32_t color, int l, int t, int w, int h) +{ + const int linesize = picture->linesize[0] / sizeof(uint32_t); + const uint32_t *py = (uint32_t *)picture->data[0] + t * linesize; + const uint32_t *pr, *pb = py + h * linesize; + uint32_t *px; + + for (; py < pb; py += linesize) { + px = (uint32_t *)py + l; + pr = px + w; + + for (; px < pr; px++) + *px = color; + } +} + +static void gif_copy_img_rect(const uint32_t *src, uint32_t *dst, + int linesize, int l, int t, int w, int h) +{ + const int y_start = t * linesize; + const uint32_t *src_px, + *src_py = src + y_start, + *dst_py = dst + y_start; + const uint32_t *src_pb = src_py + h * linesize; + uint32_t *dst_px; + + for (; src_py < src_pb; src_py += linesize, dst_py += linesize) { + src_px = src_py + l; + dst_px = (uint32_t *)dst_py + l; + + memcpy(dst_px, src_px, w * sizeof(uint32_t)); + } +} + +static int gif_read_image(GifState *s, AVFrame *frame) +{ + int left, top, width, height, bits_per_pixel, code_size, flags; + int is_interleaved, has_local_palette, y, pass, y1, linesize, pal_size; + uint32_t *ptr, *pal, *px, *pr, *ptr1; + int ret; + uint8_t *idx; + + /* At least 9 bytes of Image Descriptor. */ + if (bytestream2_get_bytes_left(&s->gb) < 9) + return AVERROR_INVALIDDATA; + + left = bytestream2_get_le16u(&s->gb); + top = bytestream2_get_le16u(&s->gb); + width = bytestream2_get_le16u(&s->gb); + height = bytestream2_get_le16u(&s->gb); + flags = bytestream2_get_byteu(&s->gb); + is_interleaved = flags & 0x40; + has_local_palette = flags & 0x80; + bits_per_pixel = (flags & 0x07) + 1; + + av_dlog(s->avctx, "image x=%d y=%d w=%d h=%d\n", left, top, width, height); + + if (has_local_palette) { + pal_size = 1 << bits_per_pixel; + + if (bytestream2_get_bytes_left(&s->gb) < pal_size * 3) + return AVERROR_INVALIDDATA; + + gif_read_palette(s, s->local_palette, pal_size); + pal = s->local_palette; + } else { + if (!s->has_global_palette) { + av_log(s->avctx, AV_LOG_ERROR, "picture doesn't have either global or local palette.\n"); + return AVERROR_INVALIDDATA; + } + + pal = s->global_palette; + } + + if (s->keyframe) { + if (s->transparent_color_index == -1 && s->has_global_palette) { + /* transparency wasn't set before the first frame, fill with background color */ + gif_fill(frame, s->bg_color); + } else { + /* otherwise fill with transparent color. + * this is necessary since by default picture filled with 0x80808080. */ + gif_fill(frame, s->trans_color); + } + } + + /* verify that all the image is inside the screen dimensions */ + if (left + width > s->screen_width || + top + height > s->screen_height) + return AVERROR_INVALIDDATA; + if (width <= 0 || height <= 0) + return AVERROR_INVALIDDATA; + + /* process disposal method */ + if (s->gce_prev_disposal == GCE_DISPOSAL_BACKGROUND) { + gif_fill_rect(frame, s->stored_bg_color, s->gce_l, s->gce_t, s->gce_w, s->gce_h); + } else if (s->gce_prev_disposal == GCE_DISPOSAL_RESTORE) { + gif_copy_img_rect(s->stored_img, (uint32_t *)frame->data[0], + frame->linesize[0] / sizeof(uint32_t), s->gce_l, s->gce_t, s->gce_w, s->gce_h); + } + + s->gce_prev_disposal = s->gce_disposal; + + if (s->gce_disposal != GCE_DISPOSAL_NONE) { + s->gce_l = left; s->gce_t = top; + s->gce_w = width; s->gce_h = height; + + if (s->gce_disposal == GCE_DISPOSAL_BACKGROUND) { + if (s->transparent_color_index >= 0) + s->stored_bg_color = s->trans_color; + else + s->stored_bg_color = s->bg_color; + } else if (s->gce_disposal == GCE_DISPOSAL_RESTORE) { + av_fast_malloc(&s->stored_img, &s->stored_img_size, frame->linesize[0] * frame->height); + if (!s->stored_img) + return AVERROR(ENOMEM); + + gif_copy_img_rect((uint32_t *)frame->data[0], s->stored_img, + frame->linesize[0] / sizeof(uint32_t), left, top, width, height); + } + } + + /* Expect at least 2 bytes: 1 for lzw code size and 1 for block size. */ + if (bytestream2_get_bytes_left(&s->gb) < 2) + return AVERROR_INVALIDDATA; + + /* now get the image data */ + code_size = bytestream2_get_byteu(&s->gb); + if ((ret = ff_lzw_decode_init(s->lzw, code_size, s->gb.buffer, + bytestream2_get_bytes_left(&s->gb), FF_LZW_GIF)) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "LZW init failed\n"); + return ret; + } + + /* read all the image */ + linesize = frame->linesize[0] / sizeof(uint32_t); + ptr1 = (uint32_t *)frame->data[0] + top * linesize + left; + ptr = ptr1; + pass = 0; + y1 = 0; + for (y = 0; y < height; y++) { + if (ff_lzw_decode(s->lzw, s->idx_line, width) == 0) + goto decode_tail; + + pr = ptr + width; + + for (px = ptr, idx = s->idx_line; px < pr; px++, idx++) { + if (*idx != s->transparent_color_index) + *px = pal[*idx]; + } + + if (is_interleaved) { + switch(pass) { + default: + case 0: + case 1: + y1 += 8; + ptr += linesize * 8; + if (y1 >= height) { + y1 = pass ? 2 : 4; + ptr = ptr1 + linesize * y1; + pass++; + } + break; + case 2: + y1 += 4; + ptr += linesize * 4; + if (y1 >= height) { + y1 = 1; + ptr = ptr1 + linesize; + pass++; + } + break; + case 3: + y1 += 2; + ptr += linesize * 2; + break; + } + } else { + ptr += linesize; + } + } + + decode_tail: + /* read the garbage data until end marker is found */ + ff_lzw_decode_tail(s->lzw); + + /* Graphic Control Extension's scope is single frame. + * Remove its influence. */ + s->transparent_color_index = -1; + s->gce_disposal = GCE_DISPOSAL_NONE; + + return 0; +} + +static int gif_read_extension(GifState *s) +{ + int ext_code, ext_len, gce_flags, gce_transparent_index; + + /* There must be at least 2 bytes: + * 1 for extension label and 1 for extension length. */ + if (bytestream2_get_bytes_left(&s->gb) < 2) + return AVERROR_INVALIDDATA; + + ext_code = bytestream2_get_byteu(&s->gb); + ext_len = bytestream2_get_byteu(&s->gb); + + av_dlog(s->avctx, "ext_code=0x%x len=%d\n", ext_code, ext_len); + + switch(ext_code) { + case GIF_GCE_EXT_LABEL: + if (ext_len != 4) + goto discard_ext; + + /* We need at least 5 bytes more: 4 is for extension body + * and 1 for next block size. */ + if (bytestream2_get_bytes_left(&s->gb) < 5) + return AVERROR_INVALIDDATA; + + gce_flags = bytestream2_get_byteu(&s->gb); + bytestream2_skipu(&s->gb, 2); // delay during which the frame is shown + gce_transparent_index = bytestream2_get_byteu(&s->gb); + if (gce_flags & 0x01) + s->transparent_color_index = gce_transparent_index; + else + s->transparent_color_index = -1; + s->gce_disposal = (gce_flags >> 2) & 0x7; + + av_dlog(s->avctx, "gce_flags=%x tcolor=%d disposal=%d\n", + gce_flags, + s->transparent_color_index, s->gce_disposal); + + if (s->gce_disposal > 3) { + s->gce_disposal = GCE_DISPOSAL_NONE; + av_dlog(s->avctx, "invalid value in gce_disposal (%d). Using default value of 0.\n", ext_len); + } + + ext_len = bytestream2_get_byteu(&s->gb); + break; + } + + /* NOTE: many extension blocks can come after */ + discard_ext: + while (ext_len) { + /* There must be at least ext_len bytes and 1 for next block size byte. */ + if (bytestream2_get_bytes_left(&s->gb) < ext_len + 1) + return AVERROR_INVALIDDATA; + + bytestream2_skipu(&s->gb, ext_len); + ext_len = bytestream2_get_byteu(&s->gb); + + av_dlog(s->avctx, "ext_len1=%d\n", ext_len); + } + return 0; +} + +static int gif_read_header1(GifState *s) +{ + uint8_t sig[6]; + int v, n; + int background_color_index; + + if (bytestream2_get_bytes_left(&s->gb) < 13) + return AVERROR_INVALIDDATA; + + /* read gif signature */ + bytestream2_get_bufferu(&s->gb, sig, 6); + if (memcmp(sig, gif87a_sig, 6) && + memcmp(sig, gif89a_sig, 6)) + return AVERROR_INVALIDDATA; + + /* read screen header */ + s->transparent_color_index = -1; + s->screen_width = bytestream2_get_le16u(&s->gb); + s->screen_height = bytestream2_get_le16u(&s->gb); + + v = bytestream2_get_byteu(&s->gb); + s->color_resolution = ((v & 0x70) >> 4) + 1; + s->has_global_palette = (v & 0x80); + s->bits_per_pixel = (v & 0x07) + 1; + background_color_index = bytestream2_get_byteu(&s->gb); + n = bytestream2_get_byteu(&s->gb); + if (n) { + s->avctx->sample_aspect_ratio.num = n + 15; + s->avctx->sample_aspect_ratio.den = 64; + } + + av_dlog(s->avctx, "screen_w=%d screen_h=%d bpp=%d global_palette=%d\n", + s->screen_width, s->screen_height, s->bits_per_pixel, + s->has_global_palette); + + if (s->has_global_palette) { + s->background_color_index = background_color_index; + n = 1 << s->bits_per_pixel; + if (bytestream2_get_bytes_left(&s->gb) < n * 3) + return AVERROR_INVALIDDATA; + + gif_read_palette(s, s->global_palette, n); + s->bg_color = s->global_palette[s->background_color_index]; + } else + s->background_color_index = -1; + + return 0; +} + +static int gif_parse_next_image(GifState *s, AVFrame *frame) +{ + while (bytestream2_get_bytes_left(&s->gb)) { + int code = bytestream2_get_byte(&s->gb); + int ret; + + av_dlog(s->avctx, "code=%02x '%c'\n", code, code); + + switch (code) { + case GIF_IMAGE_SEPARATOR: + return gif_read_image(s, frame); + case GIF_EXTENSION_INTRODUCER: + if ((ret = gif_read_extension(s)) < 0) + return ret; + break; + case GIF_TRAILER: + /* end of image */ + return AVERROR_EOF; + default: + /* erroneous block label */ + return AVERROR_INVALIDDATA; + } + } + return AVERROR_EOF; +} + +static av_cold int gif_decode_init(AVCodecContext *avctx) +{ + GifState *s = avctx->priv_data; + + s->avctx = avctx; + + avctx->pix_fmt = AV_PIX_FMT_RGB32; + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + ff_lzw_decode_open(&s->lzw); + return 0; +} + +static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + GifState *s = avctx->priv_data; + int ret; + + bytestream2_init(&s->gb, avpkt->data, avpkt->size); + + s->frame->pts = avpkt->pts; + s->frame->pkt_pts = avpkt->pts; + s->frame->pkt_dts = avpkt->dts; + av_frame_set_pkt_duration(s->frame, avpkt->duration); + + if (avpkt->size >= 6) { + s->keyframe = memcmp(avpkt->data, gif87a_sig, 6) == 0 || + memcmp(avpkt->data, gif89a_sig, 6) == 0; + } else { + s->keyframe = 0; + } + + if (s->keyframe) { + s->keyframe_ok = 0; + if ((ret = gif_read_header1(s)) < 0) + return ret; + + if ((ret = av_image_check_size(s->screen_width, s->screen_height, 0, avctx)) < 0) + return ret; + avcodec_set_dimensions(avctx, s->screen_width, s->screen_height); + + av_frame_unref(s->frame); + if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) + return ret; + + av_fast_malloc(&s->idx_line, &s->idx_line_size, s->screen_width); + if (!s->idx_line) + return AVERROR(ENOMEM); + + s->frame->pict_type = AV_PICTURE_TYPE_I; + s->frame->key_frame = 1; + s->keyframe_ok = 1; + } else { + if (!s->keyframe_ok) { + av_log(avctx, AV_LOG_ERROR, "cannot decode frame without keyframe\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + + s->frame->pict_type = AV_PICTURE_TYPE_P; + s->frame->key_frame = 0; + } + + ret = gif_parse_next_image(s, s->frame); + if (ret < 0) + return ret; + + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int gif_decode_close(AVCodecContext *avctx) +{ + GifState *s = avctx->priv_data; + + ff_lzw_decode_close(&s->lzw); + av_frame_free(&s->frame); + av_freep(&s->idx_line); + av_freep(&s->stored_img); + + return 0; +} + +static const AVOption options[] = { + { "trans_color", "color value (ARGB) that is used instead of transparent color", + offsetof(GifState, trans_color), AV_OPT_TYPE_INT, + {.i64 = GIF_TRANSPARENT_COLOR}, 0, 0xffffffff, + AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_VIDEO_PARAM }, + { NULL }, +}; + +static const AVClass decoder_class = { + .class_name = "gif decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DECODER, +}; + +AVCodec ff_gif_decoder = { + .name = "gif", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_GIF, + .priv_data_size = sizeof(GifState), + .init = gif_decode_init, + .close = gif_decode_close, + .decode = gif_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), + .priv_class = &decoder_class, +}; diff --git a/ffmpeg/libavcodec/golomb-test.c b/ffmpeg/libavcodec/golomb-test.c new file mode 100644 index 0000000..8adcdf6 --- /dev/null +++ b/ffmpeg/libavcodec/golomb-test.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2003 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 + +#include "libavutil/mem.h" + +#include "get_bits.h" +#include "golomb.h" +#include "put_bits.h" + +#define COUNT 8191 +#define SIZE (COUNT * 4) + +int main(void) +{ + int i, ret = 0; + uint8_t *temp; + PutBitContext pb; + GetBitContext gb; + + temp = av_malloc(SIZE); + if (!temp) + return 2; + + init_put_bits(&pb, temp, SIZE); + for (i = 0; i < COUNT; i++) + set_ue_golomb(&pb, i); + flush_put_bits(&pb); + + init_get_bits(&gb, temp, 8 * SIZE); + for (i = 0; i < COUNT; i++) { + int j, s = show_bits(&gb, 25); + + j = get_ue_golomb(&gb); + if (j != i) { + fprintf(stderr, "get_ue_golomb: expected %d, got %d. bits: %7x\n", + i, j, s); + ret = 1; + } + } + +#define EXTEND(i) (i << 3 | i & 7) + init_put_bits(&pb, temp, SIZE); + for (i = 0; i < COUNT; i++) + set_ue_golomb(&pb, EXTEND(i)); + flush_put_bits(&pb); + + init_get_bits(&gb, temp, 8 * SIZE); + for (i = 0; i < COUNT; i++) { + int j, s = show_bits_long(&gb, 32); + + j = get_ue_golomb_long(&gb); + if (j != EXTEND(i)) { + fprintf(stderr, "get_ue_golomb_long: expected %d, got %d. " + "bits: %8x\n", EXTEND(i), j, s); + ret = 1; + } + } + + init_put_bits(&pb, temp, SIZE); + for (i = 0; i < COUNT; i++) + set_se_golomb(&pb, i - COUNT / 2); + flush_put_bits(&pb); + + init_get_bits(&gb, temp, 8 * SIZE); + for (i = 0; i < COUNT; i++) { + int j, s = show_bits(&gb, 25); + + j = get_se_golomb(&gb); + if (j != i - COUNT / 2) { + fprintf(stderr, "get_se_golomb: expected %d, got %d. bits: %7x\n", + i - COUNT / 2, j, s); + ret = 1; + } + } + + av_free(temp); + + return ret; +} diff --git a/ffmpeg/libavcodec/golomb.c b/ffmpeg/libavcodec/golomb.c new file mode 100644 index 0000000..937ac22 --- /dev/null +++ b/ffmpeg/libavcodec/golomb.c @@ -0,0 +1,173 @@ +/* + * exp golomb vlc stuff + * Copyright (c) 2003 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 + */ + +/** + * @file + * @brief + * exp golomb vlc stuff + * @author Michael Niedermayer + */ + +#include "libavutil/common.h" + +const uint8_t ff_golomb_vlc_len[512]={ +19,17,15,15,13,13,13,13,11,11,11,11,11,11,11,11,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, +7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +}; + +const uint8_t ff_ue_golomb_vlc_code[512]={ +32,32,32,32,32,32,32,32,31,32,32,32,32,32,32,32,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, + 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const int8_t ff_se_golomb_vlc_code[512]={ + 17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17, 8, -8, 9, -9, 10,-10, 11,-11, 12,-12, 13,-13, 14,-14, 15,-15, + 4, 4, 4, 4, -4, -4, -4, -4, 5, 5, 5, 5, -5, -5, -5, -5, 6, 6, 6, 6, -6, -6, -6, -6, 7, 7, 7, 7, -7, -7, -7, -7, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + +const uint8_t ff_ue_golomb_len[256]={ + 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13, +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, +15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17, +}; + +const uint8_t ff_interleaved_golomb_vlc_len[256]={ +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +}; + +const uint8_t ff_interleaved_ue_golomb_vlc_code[256]={ + 15,16,7, 7, 17,18,8, 8, 3, 3, 3, 3, 3, 3, 3, 3, + 19,20,9, 9, 21,22,10,10,4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 23,24,11,11,25,26,12,12,5, 5, 5, 5, 5, 5, 5, 5, + 27,28,13,13,29,30,14,14,6, 6, 6, 6, 6, 6, 6, 6, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const int8_t ff_interleaved_se_golomb_vlc_code[256]={ + 8, -8, 4, 4, 9, -9, -4, -4, 2, 2, 2, 2, 2, 2, 2, 2, + 10,-10, 5, 5, 11,-11, -5, -5, -2, -2, -2, -2, -2, -2, -2, -2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 12,-12, 6, 6, 13,-13, -6, -6, 3, 3, 3, 3, 3, 3, 3, 3, + 14,-14, 7, 7, 15,-15, -7, -7, -3, -3, -3, -3, -3, -3, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const uint8_t ff_interleaved_dirac_golomb_vlc_code[256]={ +0, 1, 0, 0, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, +4, 5, 2, 2, 6, 7, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +8, 9, 4, 4, 10,11,5, 5, 2, 2, 2, 2, 2, 2, 2, 2, +12,13,6, 6, 14,15,7, 7, 3, 3, 3, 3, 3, 3, 3, 3, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; diff --git a/ffmpeg/libavcodec/golomb.h b/ffmpeg/libavcodec/golomb.h new file mode 100644 index 0000000..66607ad --- /dev/null +++ b/ffmpeg/libavcodec/golomb.h @@ -0,0 +1,557 @@ +/* + * exp golomb vlc stuff + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2004 Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * @brief + * exp golomb vlc stuff + * @author Michael Niedermayer and Alex Beregszaszi + */ + +#ifndef AVCODEC_GOLOMB_H +#define AVCODEC_GOLOMB_H + +#include +#include "get_bits.h" +#include "put_bits.h" + +#define INVALID_VLC 0x80000000 + +extern const uint8_t ff_golomb_vlc_len[512]; +extern const uint8_t ff_ue_golomb_vlc_code[512]; +extern const int8_t ff_se_golomb_vlc_code[512]; +extern const uint8_t ff_ue_golomb_len[256]; + +extern const uint8_t ff_interleaved_golomb_vlc_len[256]; +extern const uint8_t ff_interleaved_ue_golomb_vlc_code[256]; +extern const int8_t ff_interleaved_se_golomb_vlc_code[256]; +extern const uint8_t ff_interleaved_dirac_golomb_vlc_code[256]; + + + /** + * read unsigned exp golomb code. + */ +static inline int get_ue_golomb(GetBitContext *gb){ + unsigned int buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + if(buf >= (1<<27)){ + buf >>= 32 - 9; + LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_ue_golomb_vlc_code[buf]; + }else{ + log= 2*av_log2(buf) - 31; + LAST_SKIP_BITS(re, gb, 32 - log); + CLOSE_READER(re, gb); + if (CONFIG_FTRAPV && log < 0) { + av_log(0, AV_LOG_ERROR, "Invalid UE golomb code\n"); + return AVERROR_INVALIDDATA; + } + buf>>= log; + buf--; + + return buf; + } +} + +/** + * Read an unsigned Exp-Golomb code in the range 0 to UINT32_MAX-1. + */ +static inline unsigned get_ue_golomb_long(GetBitContext *gb) +{ + unsigned buf, log; + + buf = show_bits_long(gb, 32); + log = 31 - av_log2(buf); + skip_bits_long(gb, log); + + return get_bits_long(gb, log + 1) - 1; +} + + /** + * read unsigned exp golomb code, constraint to a max of 31. + * the return value is undefined if the stored value exceeds 31. + */ +static inline int get_ue_golomb_31(GetBitContext *gb){ + unsigned int buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + buf >>= 32 - 9; + LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_ue_golomb_vlc_code[buf]; +} + +static inline unsigned svq3_get_ue_golomb(GetBitContext *gb) +{ + uint32_t buf; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + if(buf&0xAA800000){ + buf >>= 32 - 8; + LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_interleaved_ue_golomb_vlc_code[buf]; + }else{ + unsigned ret = 1; + + do { + buf >>= 32 - 8; + LAST_SKIP_BITS(re, gb, FFMIN(ff_interleaved_golomb_vlc_len[buf], 8)); + + if (ff_interleaved_golomb_vlc_len[buf] != 9){ + ret <<= (ff_interleaved_golomb_vlc_len[buf] - 1) >> 1; + ret |= ff_interleaved_dirac_golomb_vlc_code[buf]; + break; + } + ret = (ret << 4) | ff_interleaved_dirac_golomb_vlc_code[buf]; + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + } while (ret<0x8000000U && HAVE_BITS_REMAINING(re, gb)); + + CLOSE_READER(re, gb); + return ret - 1; + } +} + +/** + * read unsigned truncated exp golomb code. + */ +static inline int get_te0_golomb(GetBitContext *gb, int range){ + av_assert2(range >= 1); + + if(range==1) return 0; + else if(range==2) return get_bits1(gb)^1; + else return get_ue_golomb(gb); +} + +/** + * read unsigned truncated exp golomb code. + */ +static inline int get_te_golomb(GetBitContext *gb, int range){ + av_assert2(range >= 1); + + if(range==2) return get_bits1(gb)^1; + else return get_ue_golomb(gb); +} + + +/** + * read signed exp golomb code. + */ +static inline int get_se_golomb(GetBitContext *gb){ + unsigned int buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + if(buf >= (1<<27)){ + buf >>= 32 - 9; + LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_se_golomb_vlc_code[buf]; + }else{ + log = av_log2(buf); + LAST_SKIP_BITS(re, gb, 31 - log); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + buf>>= log; + + LAST_SKIP_BITS(re, gb, 32 - log); + CLOSE_READER(re, gb); + + if(buf&1) buf= -(buf>>1); + else buf= (buf>>1); + + return buf; + } +} + +static inline int svq3_get_se_golomb(GetBitContext *gb){ + unsigned int buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + if(buf&0xAA800000){ + buf >>= 32 - 8; + LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]); + CLOSE_READER(re, gb); + + return ff_interleaved_se_golomb_vlc_code[buf]; + }else{ + LAST_SKIP_BITS(re, gb, 8); + UPDATE_CACHE(re, gb); + buf |= 1 | (GET_CACHE(re, gb) >> 8); + + if((buf & 0xAAAAAAAA) == 0) + return INVALID_VLC; + + for(log=31; (buf & 0x80000000) == 0; log--){ + buf = (buf << 2) - ((buf << log) >> (log - 1)) + (buf >> 30); + } + + LAST_SKIP_BITS(re, gb, 63 - 2*log - 8); + CLOSE_READER(re, gb); + + return (signed) (((((buf << log) >> log) - 1) ^ -(buf & 0x1)) + 1) >> 1; + } +} + +static inline int dirac_get_se_golomb(GetBitContext *gb){ + uint32_t buf; + uint32_t ret; + + ret = svq3_get_ue_golomb(gb); + + if (ret) { + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = SHOW_SBITS(re, gb, 1); + LAST_SKIP_BITS(re, gb, 1); + ret = (ret ^ buf) - buf; + CLOSE_READER(re, gb); + } + + return ret; +} + +/** + * read unsigned golomb rice code (ffv1). + */ +static inline int get_ur_golomb(GetBitContext *gb, int k, int limit, int esc_len){ + unsigned int buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + log= av_log2(buf); + + if(log > 31-limit){ + buf >>= log - k; + buf += (30-log)<= 32-MIN_CACHE_BITS+(MIN_CACHE_BITS==32) && 32-log < limit){ + buf >>= log - k; + buf += (30-log)<size_in_bits <= re_index) + return -1; + LAST_SKIP_BITS(re, gb, 1); + UPDATE_CACHE(re, gb); + } + SKIP_BITS(re, gb, 1); + + if(i < limit - 1){ + if(k){ + buf = SHOW_UBITS(re, gb, k); + LAST_SKIP_BITS(re, gb, k); + }else{ + buf=0; + } + + CLOSE_READER(re, gb); + return buf + (i<>1; + else return -(v>>1); + +// return (v>>1) ^ -(v&1); +} + +/** + * read signed golomb rice code (flac). + */ +static inline int get_sr_golomb_flac(GetBitContext *gb, int k, int limit, int esc_len){ + int v= get_ur_golomb_jpegls(gb, k, limit, esc_len); + return (v>>1) ^ -(v&1); +} + +/** + * read unsigned golomb rice code (shorten). + */ +static inline unsigned int get_ur_golomb_shorten(GetBitContext *gb, int k){ + return get_ur_golomb_jpegls(gb, k, INT_MAX, 0); +} + +/** + * read signed golomb rice code (shorten). + */ +static inline int get_sr_golomb_shorten(GetBitContext* gb, int k) +{ + int uvar = get_ur_golomb_jpegls(gb, k + 1, INT_MAX, 0); + if (uvar & 1) + return ~(uvar >> 1); + else + return uvar >> 1; +} + + + +#ifdef TRACE + +static inline int get_ue(GetBitContext *s, const char *file, const char *func, + int line) +{ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int i= get_ue_golomb(s); + int len= get_bits_count(s) - pos; + int bits= show>>(24-len); + + print_bin(bits, len); + + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d ue @%5d in %s %s:%d\n", bits, len, i, pos, file, func, line); + + return i; +} + +static inline int get_se(GetBitContext *s, const char *file, const char *func, + int line) +{ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int i= get_se_golomb(s); + int len= get_bits_count(s) - pos; + int bits= show>>(24-len); + + print_bin(bits, len); + + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d se @%5d in %s %s:%d\n", bits, len, i, pos, file, func, line); + + return i; +} + +static inline int get_te(GetBitContext *s, int r, char *file, const char *func, int line){ + int show= show_bits(s, 24); + int pos= get_bits_count(s); + int i= get_te0_golomb(s, r); + int len= get_bits_count(s) - pos; + int bits= show>>(24-len); + + print_bin(bits, len); + + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d te @%5d in %s %s:%d\n", bits, len, i, pos, file, func, line); + + return i; +} + +#define get_ue_golomb(a) get_ue(a, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_se_golomb(a) get_se(a, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_te_golomb(a, r) get_te(a, r, __FILE__, __PRETTY_FUNCTION__, __LINE__) +#define get_te0_golomb(a, r) get_te(a, r, __FILE__, __PRETTY_FUNCTION__, __LINE__) + +#endif + +/** + * write unsigned exp golomb code. + */ +static inline void set_ue_golomb(PutBitContext *pb, int i){ + int e; + + av_assert2(i>=0); + +#if 0 + if(i=0){ + put_bits(pb, 1, 1); + return; + } +#endif + if(i<256) + put_bits(pb, ff_ue_golomb_len[i], i+1); + else{ + e= av_log2(i+1); + + put_bits(pb, 2*e+1, i+1); + } +} + +/** + * write truncated unsigned exp golomb code. + */ +static inline void set_te_golomb(PutBitContext *pb, int i, int range){ + av_assert2(range >= 1); + av_assert2(i<=range); + + if(range==2) put_bits(pb, 1, i^1); + else set_ue_golomb(pb, i); +} + +/** + * write signed exp golomb code. 16 bits at most. + */ +static inline void set_se_golomb(PutBitContext *pb, int i){ +#if 0 + if(i<=0) i= -2*i; + else i= 2*i-1; +#elif 1 + i= 2*i-1; + if(i<0) i^= -1; //FIXME check if gcc does the right thing +#else + i= 2*i-1; + i^= (i>>31); +#endif + set_ue_golomb(pb, i); +} + +/** + * write unsigned golomb rice code (ffv1). + */ +static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit, int esc_len){ + int e; + + av_assert2(i>=0); + + e= i>>k; + if(e=0); + + e= (i>>k) + 1; + if(e 31) { + put_bits(pb, 31, 0); + e -= 31; + } + put_bits(pb, e, 1); + if(k) + put_sbits(pb, k, i); + }else{ + while(limit > 31) { + put_bits(pb, 31, 0); + limit -= 31; + } + put_bits(pb, limit , 1); + put_bits(pb, esc_len, i - 1); + } +} + +/** + * write signed golomb rice code (ffv1). + */ +static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit, int esc_len){ + int v; + + v = -2*i-1; + v ^= (v>>31); + + set_ur_golomb(pb, v, k, limit, esc_len); +} + +/** + * write signed golomb rice code (flac). + */ +static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k, int limit, int esc_len){ + int v; + + v = -2*i-1; + v ^= (v>>31); + + set_ur_golomb_jpegls(pb, v, k, limit, esc_len); +} + +#endif /* AVCODEC_GOLOMB_H */ diff --git a/ffmpeg/libavcodec/gsm.h b/ffmpeg/libavcodec/gsm.h new file mode 100644 index 0000000..e56f4cd --- /dev/null +++ b/ffmpeg/libavcodec/gsm.h @@ -0,0 +1,31 @@ +/* + * GSM common header + * + * 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 + */ + +#ifndef AVCODEC_GSM_H +#define AVCODEC_GSM_H + +/* bytes per block */ +#define GSM_BLOCK_SIZE 33 +#define GSM_MS_BLOCK_SIZE 65 + +/* samples per block */ +#define GSM_FRAME_SIZE 160 + +#endif /* AVCODEC_GSM_H */ diff --git a/ffmpeg/libavcodec/gsm_parser.c b/ffmpeg/libavcodec/gsm_parser.c new file mode 100644 index 0000000..dd26f7d --- /dev/null +++ b/ffmpeg/libavcodec/gsm_parser.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * GSM audio parser + * + * Splits packets into individual blocks. + */ + +#include "parser.h" +#include "gsm.h" + +typedef struct GSMParseContext { + ParseContext pc; + int block_size; + int duration; + int remaining; +} GSMParseContext; + +static int gsm_parse(AVCodecParserContext *s1, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + GSMParseContext *s = s1->priv_data; + ParseContext *pc = &s->pc; + int next; + + if (!s->block_size) { + switch (avctx->codec_id) { + case AV_CODEC_ID_GSM: + s->block_size = GSM_BLOCK_SIZE; + s->duration = GSM_FRAME_SIZE; + break; + case AV_CODEC_ID_GSM_MS: + s->block_size = GSM_MS_BLOCK_SIZE; + s->duration = GSM_FRAME_SIZE * 2; + break; + default: + *poutbuf = buf; + *poutbuf_size = buf_size; + av_log(avctx, AV_LOG_ERROR, "Invalid codec_id\n"); + return buf_size; + } + } + + if (!s->remaining) + s->remaining = s->block_size; + if (s->remaining <= buf_size) { + next = s->remaining; + s->remaining = 0; + } else { + next = END_NOT_FOUND; + s->remaining -= buf_size; + } + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + s1->duration = s->duration; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_gsm_parser = { + .codec_ids = { AV_CODEC_ID_GSM, AV_CODEC_ID_GSM_MS }, + .priv_data_size = sizeof(GSMParseContext), + .parser_parse = gsm_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/gsmdec.c b/ffmpeg/libavcodec/gsmdec.c new file mode 100644 index 0000000..dc64267 --- /dev/null +++ b/ffmpeg/libavcodec/gsmdec.c @@ -0,0 +1,128 @@ +/* + * gsm 06.10 decoder + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +/** + * @file + * GSM decoder + */ + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "msgsmdec.h" + +#include "gsmdec_template.c" + +static av_cold int gsm_init(AVCodecContext *avctx) +{ + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->sample_rate) + avctx->sample_rate = 8000; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + switch (avctx->codec_id) { + case AV_CODEC_ID_GSM: + avctx->frame_size = GSM_FRAME_SIZE; + avctx->block_align = GSM_BLOCK_SIZE; + break; + case AV_CODEC_ID_GSM_MS: + avctx->frame_size = 2 * GSM_FRAME_SIZE; + avctx->block_align = GSM_MS_BLOCK_SIZE; + } + + return 0; +} + +static int gsm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + int res; + GetBitContext gb; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int16_t *samples; + + if (buf_size < avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = avctx->frame_size; + if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + return res; + samples = (int16_t *)frame->data[0]; + + switch (avctx->codec_id) { + case AV_CODEC_ID_GSM: + init_get_bits(&gb, buf, buf_size * 8); + if (get_bits(&gb, 4) != 0xd) + av_log(avctx, AV_LOG_WARNING, "Missing GSM magic!\n"); + res = gsm_decode_block(avctx, samples, &gb); + if (res < 0) + return res; + break; + case AV_CODEC_ID_GSM_MS: + res = ff_msgsm_decode_block(avctx, samples, buf); + if (res < 0) + return res; + } + + *got_frame_ptr = 1; + + return avctx->block_align; +} + +static void gsm_flush(AVCodecContext *avctx) +{ + GSMContext *s = avctx->priv_data; + memset(s, 0, sizeof(*s)); +} + +#if CONFIG_GSM_DECODER +AVCodec ff_gsm_decoder = { + .name = "gsm", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_GSM, + .priv_data_size = sizeof(GSMContext), + .init = gsm_init, + .decode = gsm_decode_frame, + .flush = gsm_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("GSM"), +}; +#endif +#if CONFIG_GSM_MS_DECODER +AVCodec ff_gsm_ms_decoder = { + .name = "gsm_ms", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_GSM_MS, + .priv_data_size = sizeof(GSMContext), + .init = gsm_init, + .decode = gsm_decode_frame, + .flush = gsm_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("GSM Microsoft variant"), +}; +#endif diff --git a/ffmpeg/libavcodec/gsmdec_data.c b/ffmpeg/libavcodec/gsmdec_data.c new file mode 100644 index 0000000..4324ea2 --- /dev/null +++ b/ffmpeg/libavcodec/gsmdec_data.c @@ -0,0 +1,94 @@ +/* + * gsm 06.10 decoder data + * Copyright (c) 2010 Reimar Döffinger + * + * 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 "gsmdec_data.h" + +const uint16_t ff_gsm_long_term_gain_tab[4] = { + 3277, 11469, 21299, 32767 +}; + +const int16_t ff_gsm_dequant_tab[64][8] = { + { -28, -20, -12, -4, 4, 12, 20, 28}, + { -56, -40, -24, -8, 8, 24, 40, 56}, + { -84, -60, -36, -12, 12, 36, 60, 84}, + { -112, -80, -48, -16, 16, 48, 80, 112}, + { -140, -100, -60, -20, 20, 60, 100, 140}, + { -168, -120, -72, -24, 24, 72, 120, 168}, + { -196, -140, -84, -28, 28, 84, 140, 196}, + { -224, -160, -96, -32, 32, 96, 160, 224}, + { -252, -180, -108, -36, 36, 108, 180, 252}, + { -280, -200, -120, -40, 40, 120, 200, 280}, + { -308, -220, -132, -44, 44, 132, 220, 308}, + { -336, -240, -144, -48, 48, 144, 240, 336}, + { -364, -260, -156, -52, 52, 156, 260, 364}, + { -392, -280, -168, -56, 56, 168, 280, 392}, + { -420, -300, -180, -60, 60, 180, 300, 420}, + { -448, -320, -192, -64, 64, 192, 320, 448}, + { -504, -360, -216, -72, 72, 216, 360, 504}, + { -560, -400, -240, -80, 80, 240, 400, 560}, + { -616, -440, -264, -88, 88, 264, 440, 616}, + { -672, -480, -288, -96, 96, 288, 480, 672}, + { -728, -520, -312, -104, 104, 312, 520, 728}, + { -784, -560, -336, -112, 112, 336, 560, 784}, + { -840, -600, -360, -120, 120, 360, 600, 840}, + { -896, -640, -384, -128, 128, 384, 640, 896}, + { -1008, -720, -432, -144, 144, 432, 720, 1008}, + { -1120, -800, -480, -160, 160, 480, 800, 1120}, + { -1232, -880, -528, -176, 176, 528, 880, 1232}, + { -1344, -960, -576, -192, 192, 576, 960, 1344}, + { -1456, -1040, -624, -208, 208, 624, 1040, 1456}, + { -1568, -1120, -672, -224, 224, 672, 1120, 1568}, + { -1680, -1200, -720, -240, 240, 720, 1200, 1680}, + { -1792, -1280, -768, -256, 256, 768, 1280, 1792}, + { -2016, -1440, -864, -288, 288, 864, 1440, 2016}, + { -2240, -1600, -960, -320, 320, 960, 1600, 2240}, + { -2464, -1760, -1056, -352, 352, 1056, 1760, 2464}, + { -2688, -1920, -1152, -384, 384, 1152, 1920, 2688}, + { -2912, -2080, -1248, -416, 416, 1248, 2080, 2912}, + { -3136, -2240, -1344, -448, 448, 1344, 2240, 3136}, + { -3360, -2400, -1440, -480, 480, 1440, 2400, 3360}, + { -3584, -2560, -1536, -512, 512, 1536, 2560, 3584}, + { -4032, -2880, -1728, -576, 576, 1728, 2880, 4032}, + { -4480, -3200, -1920, -640, 640, 1920, 3200, 4480}, + { -4928, -3520, -2112, -704, 704, 2112, 3520, 4928}, + { -5376, -3840, -2304, -768, 768, 2304, 3840, 5376}, + { -5824, -4160, -2496, -832, 832, 2496, 4160, 5824}, + { -6272, -4480, -2688, -896, 896, 2688, 4480, 6272}, + { -6720, -4800, -2880, -960, 960, 2880, 4800, 6720}, + { -7168, -5120, -3072, -1024, 1024, 3072, 5120, 7168}, + { -8063, -5759, -3456, -1152, 1152, 3456, 5760, 8064}, + { -8959, -6399, -3840, -1280, 1280, 3840, 6400, 8960}, + { -9855, -7039, -4224, -1408, 1408, 4224, 7040, 9856}, + {-10751, -7679, -4608, -1536, 1536, 4608, 7680, 10752}, + {-11647, -8319, -4992, -1664, 1664, 4992, 8320, 11648}, + {-12543, -8959, -5376, -1792, 1792, 5376, 8960, 12544}, + {-13439, -9599, -5760, -1920, 1920, 5760, 9600, 13440}, + {-14335, -10239, -6144, -2048, 2048, 6144, 10240, 14336}, + {-16127, -11519, -6912, -2304, 2304, 6912, 11519, 16127}, + {-17919, -12799, -7680, -2560, 2560, 7680, 12799, 17919}, + {-19711, -14079, -8448, -2816, 2816, 8448, 14079, 19711}, + {-21503, -15359, -9216, -3072, 3072, 9216, 15359, 21503}, + {-23295, -16639, -9984, -3328, 3328, 9984, 16639, 23295}, + {-25087, -17919, -10752, -3584, 3584, 10752, 17919, 25087}, + {-26879, -19199, -11520, -3840, 3840, 11520, 19199, 26879}, + {-28671, -20479, -12288, -4096, 4096, 12288, 20479, 28671} +}; diff --git a/ffmpeg/libavcodec/gsmdec_data.h b/ffmpeg/libavcodec/gsmdec_data.h new file mode 100644 index 0000000..fd89ed6 --- /dev/null +++ b/ffmpeg/libavcodec/gsmdec_data.h @@ -0,0 +1,43 @@ +/* + * gsm 06.10 decoder data + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_GSMDEC_DATA_H +#define AVCODEC_GSMDEC_DATA_H + +#include +#include "avcodec.h" + +typedef struct GSMContext { + // Contains first 120 elements from the previous frame + // (used by long_term_synth according to the "lag"), + // then in the following 160 elements the current + // frame is constructed. + int16_t ref_buf[280]; + int v[9]; + int lar[2][8]; + int lar_idx; + int msr; +} GSMContext; + +extern const uint16_t ff_gsm_long_term_gain_tab[4]; +extern const int16_t ff_gsm_dequant_tab[64][8]; + +#endif /* AVCODEC_GSMDEC_DATA_H */ diff --git a/ffmpeg/libavcodec/gsmdec_template.c b/ffmpeg/libavcodec/gsmdec_template.c new file mode 100644 index 0000000..0f55953 --- /dev/null +++ b/ffmpeg/libavcodec/gsmdec_template.c @@ -0,0 +1,151 @@ +/* + * gsm 06.10 decoder + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +/** + * @file + * GSM decoder + */ + +#include "get_bits.h" +#include "gsm.h" +#include "gsmdec_data.h" + +static void apcm_dequant_add(GetBitContext *gb, int16_t *dst) +{ + int i; + int maxidx = get_bits(gb, 6); + const int16_t *tab = ff_gsm_dequant_tab[maxidx]; + for (i = 0; i < 13; i++) + dst[3*i] += tab[get_bits(gb, 3)]; +} + +static inline int gsm_mult(int a, int b) +{ + return (a * b + (1 << 14)) >> 15; +} + +static void long_term_synth(int16_t *dst, int lag, int gain_idx) +{ + int i; + const int16_t *src = dst - lag; + uint16_t gain = ff_gsm_long_term_gain_tab[gain_idx]; + for (i = 0; i < 40; i++) + dst[i] = gsm_mult(gain, src[i]); +} + +static inline int decode_log_area(int coded, int factor, int offset) +{ + coded <<= 10; + coded -= offset; + return gsm_mult(coded, factor) << 1; +} + +static av_noinline int get_rrp(int filtered) +{ + int abs = FFABS(filtered); + if (abs < 11059) abs <<= 1; + else if (abs < 20070) abs += 11059; + else abs = (abs >> 2) + 26112; + return filtered < 0 ? -abs : abs; +} + +static int filter_value(int in, int rrp[8], int v[9]) +{ + int i; + for (i = 7; i >= 0; i--) { + in -= gsm_mult(rrp[i], v[i]); + v[i + 1] = v[i] + gsm_mult(rrp[i], in); + } + v[0] = in; + return in; +} + +static void short_term_synth(GSMContext *ctx, int16_t *dst, const int16_t *src) +{ + int i; + int rrp[8]; + int *lar = ctx->lar[ctx->lar_idx]; + int *lar_prev = ctx->lar[ctx->lar_idx ^ 1]; + for (i = 0; i < 8; i++) + rrp[i] = get_rrp((lar_prev[i] >> 2) + (lar_prev[i] >> 1) + (lar[i] >> 2)); + for (i = 0; i < 13; i++) + dst[i] = filter_value(src[i], rrp, ctx->v); + + for (i = 0; i < 8; i++) + rrp[i] = get_rrp((lar_prev[i] >> 1) + (lar [i] >> 1)); + for (i = 13; i < 27; i++) + dst[i] = filter_value(src[i], rrp, ctx->v); + + for (i = 0; i < 8; i++) + rrp[i] = get_rrp((lar_prev[i] >> 2) + (lar [i] >> 1) + (lar[i] >> 2)); + for (i = 27; i < 40; i++) + dst[i] = filter_value(src[i], rrp, ctx->v); + + for (i = 0; i < 8; i++) + rrp[i] = get_rrp(lar[i]); + for (i = 40; i < 160; i++) + dst[i] = filter_value(src[i], rrp, ctx->v); + + ctx->lar_idx ^= 1; +} + +static int postprocess(int16_t *data, int msr) +{ + int i; + for (i = 0; i < 160; i++) { + msr = av_clip_int16(data[i] + gsm_mult(msr, 28180)); + data[i] = av_clip_int16(msr << 1) & ~7; + } + return msr; +} + +static int gsm_decode_block(AVCodecContext *avctx, int16_t *samples, + GetBitContext *gb) +{ + GSMContext *ctx = avctx->priv_data; + int i; + int16_t *ref_dst = ctx->ref_buf + 120; + int *lar = ctx->lar[ctx->lar_idx]; + lar[0] = decode_log_area(get_bits(gb, 6), 13107, 1 << 15); + lar[1] = decode_log_area(get_bits(gb, 6), 13107, 1 << 15); + lar[2] = decode_log_area(get_bits(gb, 5), 13107, (1 << 14) + 2048*2); + lar[3] = decode_log_area(get_bits(gb, 5), 13107, (1 << 14) - 2560*2); + lar[4] = decode_log_area(get_bits(gb, 4), 19223, (1 << 13) + 94*2); + lar[5] = decode_log_area(get_bits(gb, 4), 17476, (1 << 13) - 1792*2); + lar[6] = decode_log_area(get_bits(gb, 3), 31454, (1 << 12) - 341*2); + lar[7] = decode_log_area(get_bits(gb, 3), 29708, (1 << 12) - 1144*2); + + for (i = 0; i < 4; i++) { + int lag = get_bits(gb, 7); + int gain_idx = get_bits(gb, 2); + int offset = get_bits(gb, 2); + lag = av_clip(lag, 40, 120); + long_term_synth(ref_dst, lag, gain_idx); + apcm_dequant_add(gb, ref_dst + offset); + ref_dst += 40; + } + memcpy(ctx->ref_buf, ctx->ref_buf + 160, 120 * sizeof(*ctx->ref_buf)); + short_term_synth(ctx, samples, ctx->ref_buf + 120); + // for optimal speed this could be merged with short_term_synth, + // not done yet because it is a bit ugly + ctx->msr = postprocess(samples, ctx->msr); + return 0; +} diff --git a/ffmpeg/libavcodec/h261.c b/ffmpeg/libavcodec/h261.c new file mode 100644 index 0000000..f89d5c7 --- /dev/null +++ b/ffmpeg/libavcodec/h261.c @@ -0,0 +1,52 @@ +/* + * H261 common code + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * h261codec. + */ + +#include "avcodec.h" +#include "h261.h" + +#define IS_FIL(a) ((a)&MB_TYPE_H261_FIL) + +uint8_t ff_h261_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; + +void ff_h261_loop_filter(MpegEncContext *s){ + H261Context * h= (H261Context*)s; + const int linesize = s->linesize; + const int uvlinesize= s->uvlinesize; + uint8_t *dest_y = s->dest[0]; + uint8_t *dest_cb= s->dest[1]; + uint8_t *dest_cr= s->dest[2]; + + if(!(IS_FIL (h->mtype))) + return; + + s->dsp.h261_loop_filter(dest_y , linesize); + s->dsp.h261_loop_filter(dest_y + 8, linesize); + s->dsp.h261_loop_filter(dest_y + 8 * linesize , linesize); + s->dsp.h261_loop_filter(dest_y + 8 * linesize + 8, linesize); + s->dsp.h261_loop_filter(dest_cb, uvlinesize); + s->dsp.h261_loop_filter(dest_cr, uvlinesize); +} diff --git a/ffmpeg/libavcodec/h261.h b/ffmpeg/libavcodec/h261.h new file mode 100644 index 0000000..5b60dd6 --- /dev/null +++ b/ffmpeg/libavcodec/h261.h @@ -0,0 +1,51 @@ +/* + * H261 decoder + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * h261codec. + */ + +#ifndef AVCODEC_H261_H +#define AVCODEC_H261_H + +#include "mpegvideo.h" + +/** + * H261Context + */ +typedef struct H261Context{ + MpegEncContext s; + + int current_mba; + int previous_mba; + int mba_diff; + int mtype; + int current_mv_x; + int current_mv_y; + int gob_number; + int gob_start_code_skipped; // 1 if gob start code is already read before gob header is read +}H261Context; + +#define MB_TYPE_H261_FIL 0x800000 + +#endif /* AVCODEC_H261_H */ diff --git a/ffmpeg/libavcodec/h261_parser.c b/ffmpeg/libavcodec/h261_parser.c new file mode 100644 index 0000000..753687a --- /dev/null +++ b/ffmpeg/libavcodec/h261_parser.c @@ -0,0 +1,93 @@ +/* + * H261 parser + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * h261codec. + */ + +#include "parser.h" + + +static int h261_find_frame_end(ParseContext *pc, AVCodecContext* avctx, const uint8_t *buf, int buf_size){ + int vop_found, i, j; + uint32_t state; + + vop_found= pc->frame_start_found; + state= pc->state; + + for(i=0; i>j)&0xFFFFF0) == 0x000100){ + vop_found=1; + break; + } + } + } + if(vop_found){ + for(; i>j)&0xFFFFF0) == 0x000100){ + pc->frame_start_found=0; + pc->state= (state>>(3*8))+0xFF00; + return i-2; + } + } + } + } + + pc->frame_start_found= vop_found; + pc->state= state; + return END_NOT_FOUND; +} + +static int h261_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next= h261_find_frame_end(pc,avctx, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_h261_parser = { + .codec_ids = { AV_CODEC_ID_H261 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = h261_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/h261data.c b/ffmpeg/libavcodec/h261data.c new file mode 100644 index 0000000..a05161f --- /dev/null +++ b/ffmpeg/libavcodec/h261data.c @@ -0,0 +1,155 @@ +/* + * copyright (c) 2002-2004 Michael Niedermayer + * copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * H.261 tables. + */ + +#include +#include "h261.h" +#include "h261data.h" + +// H.261 VLC table for macroblock addressing +const uint8_t ff_h261_mba_code[35] = { + 1, 3, 2, 3, + 2, 3, 2, 7, + 6, 11, 10, 9, + 8, 7, 6, 23, + 22, 21, 20, 19, + 18, 35, 34, 33, + 32, 31, 30, 29, + 28, 27, 26, 25, + 24, + 15, //(MBA stuffing) + 1 //(start code) +}; + +const uint8_t ff_h261_mba_bits[35] = { + 1, 3, 3, 4, + 4, 5, 5, 7, + 7, 8, 8, 8, + 8, 8, 8, 10, + 10, 10, 10, 10, + 10, 11, 11, 11, + 11, 11, 11, 11, + 11, 11, 11, 11, + 11, + 11, //(MBA stuffing) + 16 //(start code) +}; + +//H.261 VLC table for macroblock type +const uint8_t ff_h261_mtype_code[10] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1 +}; + +const uint8_t ff_h261_mtype_bits[10] = { + 4, 7, 1, 5, + 9, 8, 10, 3, + 2, 6 +}; + +const int ff_h261_mtype_map[10]= { + MB_TYPE_INTRA4x4, + MB_TYPE_INTRA4x4 | MB_TYPE_QUANT, + MB_TYPE_CBP, + MB_TYPE_QUANT | MB_TYPE_CBP, + MB_TYPE_16x16, + MB_TYPE_CBP | MB_TYPE_16x16, + MB_TYPE_QUANT | MB_TYPE_CBP | MB_TYPE_16x16, + MB_TYPE_16x16 | MB_TYPE_H261_FIL, + MB_TYPE_CBP | MB_TYPE_16x16 | MB_TYPE_H261_FIL, + MB_TYPE_QUANT | MB_TYPE_CBP | MB_TYPE_16x16 | MB_TYPE_H261_FIL +}; + +//H.261 VLC table for motion vectors +const uint8_t ff_h261_mv_tab[17][2] = { + {1,1}, {1,2}, {1,3}, {1,4}, {3,6}, {5,7}, {4,7}, {3,7}, + {11,9}, {10,9}, {9,9}, {17,10}, {16,10}, {15,10}, {14,10}, {13,10}, {12,10} +}; + +//H.261 VLC table for coded block pattern +const uint8_t ff_h261_cbp_tab[63][2] = +{ + {11,5}, {9,5}, {13,6}, {13,4}, {23,7}, {19,7}, {31,8}, {12,4}, + {22,7}, {18,7}, {30,8}, {19,5}, {27,8}, {23,8}, {19,8}, {11,4}, + {21,7}, {17,7}, {29,8}, {17,5}, {25,8}, {21,8}, {17,8}, {15,6}, + {15,8}, {13,8}, {3,9}, {15,5}, {11,8}, {7,8}, {7,9}, {10,4}, + {20,7}, {16,7}, {28,8}, {14,6}, {14,8}, {12,8}, {2,9}, {16,5}, + {24,8}, {20,8}, {16,8}, {14,5}, {10,8}, {6,8}, {6,9}, {18,5}, + {26,8}, {22,8}, {18,8}, {13,5}, {9,8}, {5,8}, {5,9}, {12,5}, + {8,8}, {4,8}, {4,9}, {7,3}, {10,5}, {8,5}, {12,6} +}; + +//H.261 VLC table for transform coefficients +static const uint16_t h261_tcoeff_vlc[65][2] = { +{ 0x2, 2 }, { 0x3, 2 },{ 0x4, 4 },{ 0x5, 5 }, +{ 0x6, 7 },{ 0x26, 8 },{ 0x21, 8 },{ 0xa, 10 }, +{ 0x1d, 12 },{ 0x18, 12 },{ 0x13, 12 },{ 0x10 , 12 }, +{ 0x1a, 13},{ 0x19, 13 }, { 0x18, 13 }, { 0x17, 13 }, +{ 0x3, 3 }, { 0x6, 6 }, { 0x25 , 8 }, { 0xc, 10 }, +{ 0x1b, 12 }, { 0x16, 13 }, { 0x15, 13 }, { 0x5, 4}, +{ 0x4, 7}, { 0xb, 10 }, { 0x14, 12 }, { 0x14, 13 }, +{ 0x7, 5 }, { 0x24, 8 }, { 0x1c, 12 }, { 0x13, 13 }, +{ 0x6, 5 }, { 0xf, 10 }, { 0x12, 12}, { 0x7, 6}, +{ 0x9 , 10 }, { 0x12, 13 }, { 0x5, 6 }, { 0x1e, 12 }, +{ 0x4, 6 }, { 0x15, 12 }, { 0x7, 7 }, { 0x11, 12}, +{ 0x5, 7 }, { 0x11, 13 }, { 0x27, 8 }, { 0x10, 13 }, +{ 0x23, 8 }, { 0x22, 8 }, { 0x20, 8 }, { 0xe , 10 }, +{ 0xd, 10 }, { 0x8, 10 },{ 0x1f, 12 }, { 0x1a, 12 }, +{ 0x19, 12 }, { 0x17, 12 }, { 0x16, 12}, { 0x1f, 13}, +{ 0x1e, 13 }, { 0x1d, 13 }, { 0x1c, 13}, { 0x1b, 13}, +{ 0x1, 6 } //escape +}; + +static const int8_t h261_tcoeff_level[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 1, 2, 3, 4, 5, 6, 7, 1, + 2, 3, 4, 5, 1, 2, 3, 4, + 1, 2, 3, 1, 2, 3, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const int8_t h261_tcoeff_run[64] = { + 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 4, + 4, 4, 5, 5, 5, 6, 6, 7, + 7, 8, 8, 9, 9, 10, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26 +}; + +RLTable ff_h261_rl_tcoeff = { + 64, + 64, + h261_tcoeff_vlc, + h261_tcoeff_run, + h261_tcoeff_level, +}; diff --git a/ffmpeg/libavcodec/h261data.h b/ffmpeg/libavcodec/h261data.h new file mode 100644 index 0000000..e9e5244 --- /dev/null +++ b/ffmpeg/libavcodec/h261data.h @@ -0,0 +1,42 @@ +/* + * copyright (c) 2002-2004 Michael Niedermayer + * copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * H.261 tables. + */ + +#ifndef AVCODEC_H261DATA_H +#define AVCODEC_H261DATA_H + +#include +#include "h261.h" + +extern const uint8_t ff_h261_mba_code[35]; +extern const uint8_t ff_h261_mba_bits[35]; +extern const uint8_t ff_h261_mtype_code[10]; +extern const uint8_t ff_h261_mtype_bits[10]; +extern const int ff_h261_mtype_map[10]; +extern const uint8_t ff_h261_mv_tab[17][2]; +extern const uint8_t ff_h261_cbp_tab[63][2]; +extern RLTable ff_h261_rl_tcoeff; + +#endif /* AVCODEC_H261DATA_H */ diff --git a/ffmpeg/libavcodec/h261dec.c b/ffmpeg/libavcodec/h261dec.c new file mode 100644 index 0000000..03770be --- /dev/null +++ b/ffmpeg/libavcodec/h261dec.c @@ -0,0 +1,664 @@ +/* + * H261 decoder + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * H.261 decoder. + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h263.h" +#include "h261.h" +#include "h261data.h" + +#define H261_MBA_VLC_BITS 9 +#define H261_MTYPE_VLC_BITS 6 +#define H261_MV_VLC_BITS 7 +#define H261_CBP_VLC_BITS 9 +#define TCOEFF_VLC_BITS 9 +#define MBA_STUFFING 33 +#define MBA_STARTCODE 34 + +extern uint8_t ff_h261_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; + +static VLC h261_mba_vlc; +static VLC h261_mtype_vlc; +static VLC h261_mv_vlc; +static VLC h261_cbp_vlc; + +static int h261_decode_block(H261Context * h, int16_t * block, int n, int coded); + +static av_cold void h261_decode_init_vlc(H261Context *h){ + static int done = 0; + + if(!done){ + done = 1; + INIT_VLC_STATIC(&h261_mba_vlc, H261_MBA_VLC_BITS, 35, + ff_h261_mba_bits, 1, 1, + ff_h261_mba_code, 1, 1, 662); + INIT_VLC_STATIC(&h261_mtype_vlc, H261_MTYPE_VLC_BITS, 10, + ff_h261_mtype_bits, 1, 1, + ff_h261_mtype_code, 1, 1, 80); + INIT_VLC_STATIC(&h261_mv_vlc, H261_MV_VLC_BITS, 17, + &ff_h261_mv_tab[0][1], 2, 1, + &ff_h261_mv_tab[0][0], 2, 1, 144); + INIT_VLC_STATIC(&h261_cbp_vlc, H261_CBP_VLC_BITS, 63, + &ff_h261_cbp_tab[0][1], 2, 1, + &ff_h261_cbp_tab[0][0], 2, 1, 512); + ff_init_rl(&ff_h261_rl_tcoeff, ff_h261_rl_table_store); + INIT_VLC_RL(ff_h261_rl_tcoeff, 552); + } +} + +static av_cold int h261_decode_init(AVCodecContext *avctx){ + H261Context *h= avctx->priv_data; + MpegEncContext * const s = &h->s; + + // set defaults + ff_MPV_decode_defaults(s); + s->avctx = avctx; + + s->width = s->avctx->coded_width; + s->height = s->avctx->coded_height; + s->codec_id = s->avctx->codec->id; + + s->out_format = FMT_H261; + s->low_delay= 1; + avctx->pix_fmt= AV_PIX_FMT_YUV420P; + + s->codec_id= avctx->codec->id; + + h261_decode_init_vlc(h); + + h->gob_start_code_skipped = 0; + + return 0; +} + +/** + * Decode the group of blocks header or slice header. + * @return <0 if an error occurred + */ +static int h261_decode_gob_header(H261Context *h){ + unsigned int val; + MpegEncContext * const s = &h->s; + + if ( !h->gob_start_code_skipped ){ + /* Check for GOB Start Code */ + val = show_bits(&s->gb, 15); + if(val) + return -1; + + /* We have a GBSC */ + skip_bits(&s->gb, 16); + } + + h->gob_start_code_skipped = 0; + + h->gob_number = get_bits(&s->gb, 4); /* GN */ + s->qscale = get_bits(&s->gb, 5); /* GQUANT */ + + /* Check if gob_number is valid */ + if (s->mb_height==18){ //cif + if ((h->gob_number<=0) || (h->gob_number>12)) + return -1; + } + else{ //qcif + if ((h->gob_number!=1) && (h->gob_number!=3) && (h->gob_number!=5)) + return -1; + } + + /* GEI */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + + if(s->qscale==0) { + av_log(s->avctx, AV_LOG_ERROR, "qscale has forbidden 0 value\n"); + if (s->avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_COMPLIANT)) + return -1; + } + + // For the first transmitted macroblock in a GOB, MBA is the absolute address. For + // subsequent macroblocks, MBA is the difference between the absolute addresses of + // the macroblock and the last transmitted macroblock. + h->current_mba = 0; + h->mba_diff = 0; + + return 0; +} + +/** + * Decode the group of blocks / video packet header. + * @return <0 if no resync found + */ +static int ff_h261_resync(H261Context *h){ + MpegEncContext * const s = &h->s; + int left, ret; + + if ( h->gob_start_code_skipped ){ + ret= h261_decode_gob_header(h); + if(ret>=0) + return 0; + } + else{ + if(show_bits(&s->gb, 15)==0){ + ret= h261_decode_gob_header(h); + if(ret>=0) + return 0; + } + //OK, it is not where it is supposed to be ... + s->gb= s->last_resync_gb; + align_get_bits(&s->gb); + left= get_bits_left(&s->gb); + + for(;left>15+1+4+5; left-=8){ + if(show_bits(&s->gb, 15)==0){ + GetBitContext bak= s->gb; + + ret= h261_decode_gob_header(h); + if(ret>=0) + return 0; + + s->gb= bak; + } + skip_bits(&s->gb, 8); + } + } + + return -1; +} + +/** + * Decode skipped macroblocks. + * @return 0 + */ +static int h261_decode_mb_skipped(H261Context *h, int mba1, int mba2 ) +{ + MpegEncContext * const s = &h->s; + int i; + + s->mb_intra = 0; + + for(i=mba1; imb_x= ((h->gob_number-1) % 2) * 11 + i % 11; + s->mb_y= ((h->gob_number-1) / 2) * 3 + i / 11; + xy = s->mb_x + s->mb_y * s->mb_stride; + ff_init_block_index(s); + ff_update_block_index(s); + + for(j=0;j<6;j++) + s->block_last_index[j] = -1; + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = 1; + h->mtype &= ~MB_TYPE_H261_FIL; + + ff_MPV_decode_mb(s, s->block); + } + + return 0; +} + +static int decode_mv_component(GetBitContext *gb, int v){ + static const int mvmap[17] = { + 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16 + }; + int mv_diff = get_vlc2(gb, h261_mv_vlc.table, H261_MV_VLC_BITS, 2); + + /* check if mv_diff is valid */ + if ( mv_diff < 0 ) + return v; + + mv_diff = mvmap[mv_diff]; + + if(mv_diff && !get_bits1(gb)) + mv_diff= -mv_diff; + + v += mv_diff; + if (v <=-16) v+= 32; + else if(v >= 16) v-= 32; + + return v; +} + +static int h261_decode_mb(H261Context *h){ + MpegEncContext * const s = &h->s; + int i, cbp, xy; + + cbp = 63; + // Read mba + do{ + h->mba_diff = get_vlc2(&s->gb, h261_mba_vlc.table, H261_MBA_VLC_BITS, 2); + + /* Check for slice end */ + /* NOTE: GOB can be empty (no MB data) or exist only of MBA_stuffing */ + if (h->mba_diff == MBA_STARTCODE){ // start code + h->gob_start_code_skipped = 1; + return SLICE_END; + } + } + while( h->mba_diff == MBA_STUFFING ); // stuffing + + if ( h->mba_diff < 0 ){ + if (get_bits_left(&s->gb) <= 7) + return SLICE_END; + + av_log(s->avctx, AV_LOG_ERROR, "illegal mba at %d %d\n", s->mb_x, s->mb_y); + return SLICE_ERROR; + } + + h->mba_diff += 1; + h->current_mba += h->mba_diff; + + if ( h->current_mba > MBA_STUFFING ) + return SLICE_ERROR; + + s->mb_x= ((h->gob_number-1) % 2) * 11 + ((h->current_mba-1) % 11); + s->mb_y= ((h->gob_number-1) / 2) * 3 + ((h->current_mba-1) / 11); + xy = s->mb_x + s->mb_y * s->mb_stride; + ff_init_block_index(s); + ff_update_block_index(s); + + // Read mtype + h->mtype = get_vlc2(&s->gb, h261_mtype_vlc.table, H261_MTYPE_VLC_BITS, 2); + if (h->mtype < 0) { + av_log(s->avctx, AV_LOG_ERROR, "illegal mtype %d\n", h->mtype); + return SLICE_ERROR; + } + h->mtype = ff_h261_mtype_map[h->mtype]; + + // Read mquant + if ( IS_QUANT ( h->mtype ) ){ + ff_set_qscale(s, get_bits(&s->gb, 5)); + } + + s->mb_intra = IS_INTRA4x4(h->mtype); + + // Read mv + if ( IS_16X16 ( h->mtype ) ){ + // Motion vector data is included for all MC macroblocks. MVD is obtained from the macroblock vector by subtracting the + // vector of the preceding macroblock. For this calculation the vector of the preceding macroblock is regarded as zero in the + // following three situations: + // 1) evaluating MVD for macroblocks 1, 12 and 23; + // 2) evaluating MVD for macroblocks in which MBA does not represent a difference of 1; + // 3) MTYPE of the previous macroblock was not MC. + if ( ( h->current_mba == 1 ) || ( h->current_mba == 12 ) || ( h->current_mba == 23 ) || + ( h->mba_diff != 1)) + { + h->current_mv_x = 0; + h->current_mv_y = 0; + } + + h->current_mv_x= decode_mv_component(&s->gb, h->current_mv_x); + h->current_mv_y= decode_mv_component(&s->gb, h->current_mv_y); + }else{ + h->current_mv_x = 0; + h->current_mv_y = 0; + } + + // Read cbp + if ( HAS_CBP( h->mtype ) ){ + cbp = get_vlc2(&s->gb, h261_cbp_vlc.table, H261_CBP_VLC_BITS, 2) + 1; + } + + if(s->mb_intra){ + s->current_picture.mb_type[xy] = MB_TYPE_INTRA; + goto intra; + } + + //set motion vectors + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_L0; + s->mv[0][0][0] = h->current_mv_x * 2;//gets divided by 2 in motion compensation + s->mv[0][0][1] = h->current_mv_y * 2; + +intra: + /* decode each block */ + if(s->mb_intra || HAS_CBP(h->mtype)){ + s->dsp.clear_blocks(s->block[0]); + for (i = 0; i < 6; i++) { + if (h261_decode_block(h, s->block[i], i, cbp&32) < 0){ + return SLICE_ERROR; + } + cbp+=cbp; + } + }else{ + for (i = 0; i < 6; i++) + s->block_last_index[i]= -1; + } + + ff_MPV_decode_mb(s, s->block); + + return SLICE_OK; +} + +/** + * Decode a macroblock. + * @return <0 if an error occurred + */ +static int h261_decode_block(H261Context * h, int16_t * block, + int n, int coded) +{ + MpegEncContext * const s = &h->s; + int code, level, i, j, run; + RLTable *rl = &ff_h261_rl_tcoeff; + const uint8_t *scan_table; + + // For the variable length encoding there are two code tables, one being used for + // the first transmitted LEVEL in INTER, INTER+MC and INTER+MC+FIL blocks, the second + // for all other LEVELs except the first one in INTRA blocks which is fixed length + // coded with 8 bits. + // NOTE: the two code tables only differ in one VLC so we handle that manually. + scan_table = s->intra_scantable.permutated; + if (s->mb_intra){ + /* DC coef */ + level = get_bits(&s->gb, 8); + // 0 (00000000b) and -128 (10000000b) are FORBIDDEN + if((level&0x7F) == 0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal dc %d at %d %d\n", level, s->mb_x, s->mb_y); + return -1; + } + // The code 1000 0000 is not used, the reconstruction level of 1024 being coded as 1111 1111. + if (level == 255) + level = 128; + block[0] = level; + i = 1; + }else if(coded){ + // Run Level Code + // EOB Not possible for first level when cbp is available (that's why the table is different) + // 0 1 1s + // * * 0* + int check = show_bits(&s->gb, 2); + i = 0; + if ( check & 0x2 ){ + skip_bits(&s->gb, 2); + block[0] = ( check & 0x1 ) ? -1 : 1; + i = 1; + } + }else{ + i = 0; + } + if(!coded){ + s->block_last_index[n] = i - 1; + return 0; + } + for(;;){ + code = get_vlc2(&s->gb, rl->vlc.table, TCOEFF_VLC_BITS, 2); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal ac vlc code at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + if (code == rl->n) { + /* escape */ + // The remaining combinations of (run, level) are encoded with a 20-bit word consisting of 6 bits escape, 6 bits run and 8 bits level. + run = get_bits(&s->gb, 6); + level = get_sbits(&s->gb, 8); + }else if(code == 0){ + break; + }else{ + run = rl->table_run[code]; + level = rl->table_level[code]; + if (get_bits1(&s->gb)) + level = -level; + } + i += run; + if (i >= 64){ + av_log(s->avctx, AV_LOG_ERROR, "run overflow at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + j = scan_table[i]; + block[j] = level; + i++; + } + s->block_last_index[n] = i-1; + return 0; +} + +/** + * Decode the H.261 picture header. + * @return <0 if no startcode found + */ +static int h261_decode_picture_header(H261Context *h){ + MpegEncContext * const s = &h->s; + int format, i; + uint32_t startcode= 0; + + for(i= get_bits_left(&s->gb); i>24; i-=1){ + startcode = ((startcode << 1) | get_bits(&s->gb, 1)) & 0x000FFFFF; + + if(startcode == 0x10) + break; + } + + if (startcode != 0x10){ + av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); + return -1; + } + + /* temporal reference */ + i= get_bits(&s->gb, 5); /* picture timestamp */ + if(i < (s->picture_number&31)) + i += 32; + s->picture_number = (s->picture_number&~31) + i; + + s->avctx->time_base= (AVRational){1001, 30000}; + s->current_picture.f.pts = s->picture_number; + + + /* PTYPE starts here */ + skip_bits1(&s->gb); /* split screen off */ + skip_bits1(&s->gb); /* camera off */ + skip_bits1(&s->gb); /* freeze picture release off */ + + format = get_bits1(&s->gb); + + //only 2 formats possible + if (format == 0){//QCIF + s->width = 176; + s->height = 144; + s->mb_width = 11; + s->mb_height = 9; + }else{//CIF + s->width = 352; + s->height = 288; + s->mb_width = 22; + s->mb_height = 18; + } + + s->mb_num = s->mb_width * s->mb_height; + + skip_bits1(&s->gb); /* still image mode off */ + skip_bits1(&s->gb); /* Reserved */ + + /* PEI */ + while (get_bits1(&s->gb) != 0){ + skip_bits(&s->gb, 8); + } + + // h261 has no I-FRAMES, but if we pass AV_PICTURE_TYPE_I for the first frame, the codec crashes if it does + // not contain all I-blocks (e.g. when a packet is lost) + s->pict_type = AV_PICTURE_TYPE_P; + + h->gob_number = 0; + return 0; +} + +static int h261_decode_gob(H261Context *h){ + MpegEncContext * const s = &h->s; + + ff_set_qscale(s, s->qscale); + + /* decode mb's */ + while(h->current_mba <= MBA_STUFFING) + { + int ret; + /* DCT & quantize */ + ret= h261_decode_mb(h); + if(ret<0){ + if(ret==SLICE_END){ + h261_decode_mb_skipped(h, h->current_mba, 33); + return 0; + } + av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", s->mb_x + s->mb_y*s->mb_stride); + return -1; + } + + h261_decode_mb_skipped(h, h->current_mba-h->mba_diff, h->current_mba-1); + } + + return -1; +} + +/** + * returns the number of bytes consumed for building the current frame + */ +static int get_consumed_bytes(MpegEncContext *s, int buf_size){ + int pos= get_bits_count(&s->gb)>>3; + if(pos==0) pos=1; //avoid infinite loops (i doubt that is needed but ...) + if(pos+10>buf_size) pos=buf_size; // oops ;) + + return pos; +} + +static int h261_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + H261Context *h= avctx->priv_data; + MpegEncContext *s = &h->s; + int ret; + AVFrame *pict = data; + + av_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); + av_dlog(avctx, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); + s->flags= avctx->flags; + s->flags2= avctx->flags2; + + h->gob_start_code_skipped=0; + +retry: + + init_get_bits(&s->gb, buf, buf_size*8); + + if(!s->context_initialized){ + if (ff_MPV_common_init(s) < 0) //we need the idct permutaton for reading a custom matrix + return -1; + } + + //we need to set current_picture_ptr before reading the header, otherwise we cannot store anyting im there + if (s->current_picture_ptr == NULL || s->current_picture_ptr->f.data[0]) { + int i= ff_find_unused_picture(s, 0); + if (i < 0) + return i; + s->current_picture_ptr= &s->picture[i]; + } + + ret = h261_decode_picture_header(h); + + /* skip if the header was thrashed */ + if (ret < 0){ + av_log(s->avctx, AV_LOG_ERROR, "header damaged\n"); + return -1; + } + + if (s->width != avctx->coded_width || s->height != avctx->coded_height){ + ParseContext pc= s->parse_context; //FIXME move this demuxing hack to libavformat + s->parse_context.buffer=0; + ff_MPV_common_end(s); + s->parse_context= pc; + } + if (!s->context_initialized) { + avcodec_set_dimensions(avctx, s->width, s->height); + + goto retry; + } + + // for skipping the frame + s->current_picture.f.pict_type = s->pict_type; + s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==AV_PICTURE_TYPE_B) + ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=AV_PICTURE_TYPE_I) + || avctx->skip_frame >= AVDISCARD_ALL) + return get_consumed_bytes(s, buf_size); + + if(ff_MPV_frame_start(s, avctx) < 0) + return -1; + + ff_mpeg_er_frame_start(s); + + /* decode each macroblock */ + s->mb_x=0; + s->mb_y=0; + + while(h->gob_number < (s->mb_height==18 ? 12 : 5)){ + if(ff_h261_resync(h)<0) + break; + h261_decode_gob(h); + } + ff_MPV_frame_end(s); + + av_assert0(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type); + av_assert0(s->current_picture.f.pict_type == s->pict_type); + + if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->current_picture_ptr, pict); + + *got_frame = 1; + + return get_consumed_bytes(s, buf_size); +} + +static av_cold int h261_decode_end(AVCodecContext *avctx) +{ + H261Context *h= avctx->priv_data; + MpegEncContext *s = &h->s; + + ff_MPV_common_end(s); + return 0; +} + +AVCodec ff_h261_decoder = { + .name = "h261", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H261, + .priv_data_size = sizeof(H261Context), + .init = h261_decode_init, + .close = h261_decode_end, + .decode = h261_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("H.261"), +}; diff --git a/ffmpeg/libavcodec/h261enc.c b/ffmpeg/libavcodec/h261enc.c new file mode 100644 index 0000000..c22100c --- /dev/null +++ b/ffmpeg/libavcodec/h261enc.c @@ -0,0 +1,337 @@ +/* + * H261 encoder + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2004 Maarten Daniels + * + * 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 + */ + +/** + * @file + * H.261 encoder. + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h263.h" +#include "h261.h" +#include "h261data.h" + +extern uint8_t ff_h261_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; + +static void h261_encode_block(H261Context * h, int16_t * block, + int n); + +int ff_h261_get_picture_format(int width, int height){ + // QCIF + if (width == 176 && height == 144) + return 0; + // CIF + else if (width == 352 && height == 288) + return 1; + // ERROR + else + return -1; +} + +void ff_h261_encode_picture_header(MpegEncContext * s, int picture_number){ + H261Context * h = (H261Context *) s; + int format, temp_ref; + + avpriv_align_put_bits(&s->pb); + + /* Update the pointer to last GOB */ + s->ptr_lastgob = put_bits_ptr(&s->pb); + + put_bits(&s->pb, 20, 0x10); /* PSC */ + + temp_ref= s->picture_number * (int64_t)30000 * s->avctx->time_base.num / + (1001 * (int64_t)s->avctx->time_base.den); //FIXME maybe this should use a timestamp + put_sbits(&s->pb, 5, temp_ref); /* TemporalReference */ + + put_bits(&s->pb, 1, 0); /* split screen off */ + put_bits(&s->pb, 1, 0); /* camera off */ + put_bits(&s->pb, 1, 0); /* freeze picture release off */ + + format = ff_h261_get_picture_format(s->width, s->height); + + put_bits(&s->pb, 1, format); /* 0 == QCIF, 1 == CIF */ + + put_bits(&s->pb, 1, 0); /* still image mode */ + put_bits(&s->pb, 1, 0); /* reserved */ + + put_bits(&s->pb, 1, 0); /* no PEI */ + if(format == 0) + h->gob_number = -1; + else + h->gob_number = 0; + h->current_mba = 0; +} + +/** + * Encode a group of blocks header. + */ +static void h261_encode_gob_header(MpegEncContext * s, int mb_line){ + H261Context * h = (H261Context *)s; + if(ff_h261_get_picture_format(s->width, s->height) == 0){ + h->gob_number+=2; // QCIF + } + else{ + h->gob_number++; // CIF + } + put_bits(&s->pb, 16, 1); /* GBSC */ + put_bits(&s->pb, 4, h->gob_number); /* GN */ + put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + put_bits(&s->pb, 1, 0); /* no GEI */ + h->current_mba = 0; + h->previous_mba = 0; + h->current_mv_x=0; + h->current_mv_y=0; +} + +void ff_h261_reorder_mb_index(MpegEncContext* s){ + int index= s->mb_x + s->mb_y*s->mb_width; + + if(index % 33 == 0) + h261_encode_gob_header(s,0); + + /* for CIF the GOB's are fragmented in the middle of a scanline + that's why we need to adjust the x and y index of the macroblocks */ + if(ff_h261_get_picture_format(s->width,s->height) == 1){ // CIF + s->mb_x = index % 11 ; index /= 11; + s->mb_y = index % 3 ; index /= 3; + s->mb_x+= 11*(index % 2); index /= 2; + s->mb_y+= 3*index; + + ff_init_block_index(s); + ff_update_block_index(s); + } +} + +static void h261_encode_motion(H261Context * h, int val){ + MpegEncContext * const s = &h->s; + int sign, code; + if(val==0){ + code = 0; + put_bits(&s->pb,ff_h261_mv_tab[code][1],ff_h261_mv_tab[code][0]); + } + else{ + if(val > 15) + val -=32; + if(val < -16) + val+=32; + sign = val < 0; + code = sign ? -val : val; + put_bits(&s->pb,ff_h261_mv_tab[code][1],ff_h261_mv_tab[code][0]); + put_bits(&s->pb,1,sign); + } +} + +static inline int get_cbp(MpegEncContext * s, + int16_t block[6][64]) +{ + int i, cbp; + cbp= 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + return cbp; +} +void ff_h261_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y) +{ + H261Context * h = (H261Context *)s; + int mvd, mv_diff_x, mv_diff_y, i, cbp; + cbp = 63; // avoid warning + mvd = 0; + + h->current_mba++; + h->mtype = 0; + + if (!s->mb_intra){ + /* compute cbp */ + cbp= get_cbp(s, block); + + /* mvd indicates if this block is motion compensated */ + mvd = motion_x | motion_y; + + if((cbp | mvd | s->dquant ) == 0) { + /* skip macroblock */ + s->skip_count++; + h->current_mv_x=0; + h->current_mv_y=0; + return; + } + } + + /* MB is not skipped, encode MBA */ + put_bits(&s->pb, ff_h261_mba_bits[(h->current_mba-h->previous_mba)-1], ff_h261_mba_code[(h->current_mba-h->previous_mba)-1]); + + /* calculate MTYPE */ + if(!s->mb_intra){ + h->mtype++; + + if(mvd || s->loop_filter) + h->mtype+=3; + if(s->loop_filter) + h->mtype+=3; + if(cbp || s->dquant) + h->mtype++; + av_assert1(h->mtype > 1); + } + + if(s->dquant) + h->mtype++; + + put_bits(&s->pb, ff_h261_mtype_bits[h->mtype], ff_h261_mtype_code[h->mtype]); + + h->mtype = ff_h261_mtype_map[h->mtype]; + + if(IS_QUANT(h->mtype)){ + ff_set_qscale(s,s->qscale+s->dquant); + put_bits(&s->pb, 5, s->qscale); + } + + if(IS_16X16(h->mtype)){ + mv_diff_x = (motion_x >> 1) - h->current_mv_x; + mv_diff_y = (motion_y >> 1) - h->current_mv_y; + h->current_mv_x = (motion_x >> 1); + h->current_mv_y = (motion_y >> 1); + h261_encode_motion(h,mv_diff_x); + h261_encode_motion(h,mv_diff_y); + } + + h->previous_mba = h->current_mba; + + if(HAS_CBP(h->mtype)){ + av_assert1(cbp>0); + put_bits(&s->pb,ff_h261_cbp_tab[cbp-1][1],ff_h261_cbp_tab[cbp-1][0]); + } + for(i=0; i<6; i++) { + /* encode each block */ + h261_encode_block(h, block[i], i); + } + + if ( ( h->current_mba == 11 ) || ( h->current_mba == 22 ) || ( h->current_mba == 33 ) || ( !IS_16X16 ( h->mtype ) )){ + h->current_mv_x=0; + h->current_mv_y=0; + } +} + +void ff_h261_encode_init(MpegEncContext *s){ + static int done = 0; + + if (!done) { + done = 1; + ff_init_rl(&ff_h261_rl_tcoeff, ff_h261_rl_table_store); + } + + s->min_qcoeff= -127; + s->max_qcoeff= 127; + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; +} + + +/** + * Encode an 8x8 block. + * @param block the 8x8 block + * @param n block index (0-3 are luma, 4-5 are chroma) + */ +static void h261_encode_block(H261Context * h, int16_t * block, int n){ + MpegEncContext * const s = &h->s; + int level, run, i, j, last_index, last_non_zero, sign, slevel, code; + RLTable *rl; + + rl = &ff_h261_rl_tcoeff; + if (s->mb_intra) { + /* DC coef */ + level = block[0]; + /* 255 cannot be represented, so we clamp */ + if (level > 254) { + level = 254; + block[0] = 254; + } + /* 0 cannot be represented also */ + else if (level < 1) { + level = 1; + block[0] = 1; + } + if (level == 128) + put_bits(&s->pb, 8, 0xff); + else + put_bits(&s->pb, 8, level); + i = 1; + } else if((block[0]==1 || block[0] == -1) && (s->block_last_index[n] > -1)){ + //special case + put_bits(&s->pb,2,block[0]>0 ? 2 : 3 ); + i = 1; + } else { + i = 0; + } + + /* AC coefs */ + last_index = s->block_last_index[n]; + last_non_zero = i - 1; + for (; i <= last_index; i++) { + j = s->intra_scantable.permutated[i]; + level = block[j]; + if (level) { + run = i - last_non_zero - 1; + sign = 0; + slevel = level; + if (level < 0) { + sign = 1; + level = -level; + } + code = get_rl_index(rl, 0 /*no last in H.261, EOB is used*/, run, level); + if(run==0 && level < 16) + code+=1; + put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); + if (code == rl->n) { + put_bits(&s->pb, 6, run); + av_assert1(slevel != 0); + av_assert1(level <= 127); + put_sbits(&s->pb, 8, slevel); + } else { + put_bits(&s->pb, 1, sign); + } + last_non_zero = i; + } + } + if(last_index > -1){ + put_bits(&s->pb, rl->table_vlc[0][1], rl->table_vlc[0][0]);// END OF BLOCK + } +} + +FF_MPV_GENERIC_CLASS(h261) + +AVCodec ff_h261_encoder = { + .name = "h261", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H261, + .priv_data_size = sizeof(H261Context), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("H.261"), + .priv_class = &h261_class, +}; diff --git a/ffmpeg/libavcodec/h263.c b/ffmpeg/libavcodec/h263.c new file mode 100644 index 0000000..e60e58e --- /dev/null +++ b/ffmpeg/libavcodec/h263.c @@ -0,0 +1,384 @@ +/* + * H263/MPEG4 backend for encoder and decoder + * Copyright (c) 2000,2001 Fabrice Bellard + * H263+ support. + * Copyright (c) 2001 Juan J. Sierralta P + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * h263/mpeg4 codec. + */ + +//#define DEBUG +#include + +#include "avcodec.h" +#include "mpegvideo.h" +#include "h263.h" +#include "h263data.h" +#include "mathops.h" +#include "unary.h" +#include "flv.h" +#include "mpeg4video.h" + +//#undef NDEBUG +//#include + +uint8_t ff_h263_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; + + +void ff_h263_update_motion_val(MpegEncContext * s){ + const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; + //FIXME a lot of that is only needed for !low_delay + const int wrap = s->b8_stride; + const int xy = s->block_index[0]; + + s->current_picture.mbskip_table[mb_xy] = s->mb_skipped; + + if(s->mv_type != MV_TYPE_8X8){ + int motion_x, motion_y; + if (s->mb_intra) { + motion_x = 0; + motion_y = 0; + } else if (s->mv_type == MV_TYPE_16X16) { + motion_x = s->mv[0][0][0]; + motion_y = s->mv[0][0][1]; + } else /*if (s->mv_type == MV_TYPE_FIELD)*/ { + int i; + motion_x = s->mv[0][0][0] + s->mv[0][1][0]; + motion_y = s->mv[0][0][1] + s->mv[0][1][1]; + motion_x = (motion_x>>1) | (motion_x&1); + for(i=0; i<2; i++){ + s->p_field_mv_table[i][0][mb_xy][0]= s->mv[0][i][0]; + s->p_field_mv_table[i][0][mb_xy][1]= s->mv[0][i][1]; + } + s->current_picture.ref_index[0][4*mb_xy ] = + s->current_picture.ref_index[0][4*mb_xy + 1] = s->field_select[0][0]; + s->current_picture.ref_index[0][4*mb_xy + 2] = + s->current_picture.ref_index[0][4*mb_xy + 3] = s->field_select[0][1]; + } + + /* no update if 8X8 because it has been done during parsing */ + s->current_picture.motion_val[0][xy][0] = motion_x; + s->current_picture.motion_val[0][xy][1] = motion_y; + s->current_picture.motion_val[0][xy + 1][0] = motion_x; + s->current_picture.motion_val[0][xy + 1][1] = motion_y; + s->current_picture.motion_val[0][xy + wrap][0] = motion_x; + s->current_picture.motion_val[0][xy + wrap][1] = motion_y; + s->current_picture.motion_val[0][xy + 1 + wrap][0] = motion_x; + s->current_picture.motion_val[0][xy + 1 + wrap][1] = motion_y; + } + + if(s->encoding){ //FIXME encoding MUST be cleaned up + if (s->mv_type == MV_TYPE_8X8) + s->current_picture.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_8x8; + else if(s->mb_intra) + s->current_picture.mb_type[mb_xy] = MB_TYPE_INTRA; + else + s->current_picture.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_16x16; + } +} + +int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) +{ + int x, y, wrap, a, c, pred_dc; + int16_t *dc_val; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + (n & 1); + y = 2 * s->mb_y + ((n & 2) >> 1); + wrap = s->b8_stride; + dc_val = s->dc_val[0]; + } else { + x = s->mb_x; + y = s->mb_y; + wrap = s->mb_stride; + dc_val = s->dc_val[n - 4 + 1]; + } + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + /* No prediction outside GOB boundary */ + if(s->first_slice_line && n!=3){ + if(n!=2) c= 1024; + if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; + } + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + + /* we assume pred is positive */ + *dc_val_ptr = &dc_val[x + y * wrap]; + return pred_dc; +} + +void ff_h263_loop_filter(MpegEncContext * s){ + int qp_c; + const int linesize = s->linesize; + const int uvlinesize= s->uvlinesize; + const int xy = s->mb_y * s->mb_stride + s->mb_x; + uint8_t *dest_y = s->dest[0]; + uint8_t *dest_cb= s->dest[1]; + uint8_t *dest_cr= s->dest[2]; + +// if(s->pict_type==AV_PICTURE_TYPE_B && !s->readable) return; + + /* + Diag Top + Left Center + */ + if (!IS_SKIP(s->current_picture.mb_type[xy])) { + qp_c= s->qscale; + s->dsp.h263_v_loop_filter(dest_y+8*linesize , linesize, qp_c); + s->dsp.h263_v_loop_filter(dest_y+8*linesize+8, linesize, qp_c); + }else + qp_c= 0; + + if(s->mb_y){ + int qp_dt, qp_tt, qp_tc; + + if (IS_SKIP(s->current_picture.mb_type[xy - s->mb_stride])) + qp_tt=0; + else + qp_tt = s->current_picture.qscale_table[xy - s->mb_stride]; + + if(qp_c) + qp_tc= qp_c; + else + qp_tc= qp_tt; + + if(qp_tc){ + const int chroma_qp= s->chroma_qscale_table[qp_tc]; + s->dsp.h263_v_loop_filter(dest_y , linesize, qp_tc); + s->dsp.h263_v_loop_filter(dest_y+8, linesize, qp_tc); + + s->dsp.h263_v_loop_filter(dest_cb , uvlinesize, chroma_qp); + s->dsp.h263_v_loop_filter(dest_cr , uvlinesize, chroma_qp); + } + + if(qp_tt) + s->dsp.h263_h_loop_filter(dest_y-8*linesize+8 , linesize, qp_tt); + + if(s->mb_x){ + if (qp_tt || IS_SKIP(s->current_picture.mb_type[xy - 1 - s->mb_stride])) + qp_dt= qp_tt; + else + qp_dt = s->current_picture.qscale_table[xy - 1 - s->mb_stride]; + + if(qp_dt){ + const int chroma_qp= s->chroma_qscale_table[qp_dt]; + s->dsp.h263_h_loop_filter(dest_y -8*linesize , linesize, qp_dt); + s->dsp.h263_h_loop_filter(dest_cb-8*uvlinesize, uvlinesize, chroma_qp); + s->dsp.h263_h_loop_filter(dest_cr-8*uvlinesize, uvlinesize, chroma_qp); + } + } + } + + if(qp_c){ + s->dsp.h263_h_loop_filter(dest_y +8, linesize, qp_c); + if(s->mb_y + 1 == s->mb_height) + s->dsp.h263_h_loop_filter(dest_y+8*linesize+8, linesize, qp_c); + } + + if(s->mb_x){ + int qp_lc; + if (qp_c || IS_SKIP(s->current_picture.mb_type[xy - 1])) + qp_lc= qp_c; + else + qp_lc = s->current_picture.qscale_table[xy - 1]; + + if(qp_lc){ + s->dsp.h263_h_loop_filter(dest_y, linesize, qp_lc); + if(s->mb_y + 1 == s->mb_height){ + const int chroma_qp= s->chroma_qscale_table[qp_lc]; + s->dsp.h263_h_loop_filter(dest_y +8* linesize, linesize, qp_lc); + s->dsp.h263_h_loop_filter(dest_cb , uvlinesize, chroma_qp); + s->dsp.h263_h_loop_filter(dest_cr , uvlinesize, chroma_qp); + } + } + } +} + +void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) +{ + int x, y, wrap, a, c, pred_dc, scale, i; + int16_t *dc_val, *ac_val, *ac_val1; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + (n & 1); + y = 2 * s->mb_y + (n>> 1); + wrap = s->b8_stride; + dc_val = s->dc_val[0]; + ac_val = s->ac_val[0][0]; + scale = s->y_dc_scale; + } else { + x = s->mb_x; + y = s->mb_y; + wrap = s->mb_stride; + dc_val = s->dc_val[n - 4 + 1]; + ac_val = s->ac_val[n - 4 + 1][0]; + scale = s->c_dc_scale; + } + + ac_val += ((y) * wrap + (x)) * 16; + ac_val1 = ac_val; + + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + /* No prediction outside GOB boundary */ + if(s->first_slice_line && n!=3){ + if(n!=2) c= 1024; + if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; + } + + if (s->ac_pred) { + pred_dc = 1024; + if (s->h263_aic_dir) { + /* left prediction */ + if (a != 1024) { + ac_val -= 16; + for(i=1;i<8;i++) { + block[s->dsp.idct_permutation[i<<3]] += ac_val[i]; + } + pred_dc = a; + } + } else { + /* top prediction */ + if (c != 1024) { + ac_val -= 16 * wrap; + for(i=1;i<8;i++) { + block[s->dsp.idct_permutation[i ]] += ac_val[i + 8]; + } + pred_dc = c; + } + } + } else { + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + } + + /* we assume pred is positive */ + block[0]=block[0]*scale + pred_dc; + + if (block[0] < 0) + block[0] = 0; + else + block[0] |= 1; + + /* Update AC/DC tables */ + dc_val[(x) + (y) * wrap] = block[0]; + + /* left copy */ + for(i=1;i<8;i++) + ac_val1[i ] = block[s->dsp.idct_permutation[i<<3]]; + /* top copy */ + for(i=1;i<8;i++) + ac_val1[8 + i] = block[s->dsp.idct_permutation[i ]]; +} + +int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, + int *px, int *py) +{ + int wrap; + int16_t *A, *B, *C, (*mot_val)[2]; + static const int off[4]= {2, 1, 1, -1}; + + wrap = s->b8_stride; + mot_val = s->current_picture.motion_val[dir] + s->block_index[block]; + + A = mot_val[ - 1]; + /* special case for first (slice) line */ + if (s->first_slice_line && block<3) { + // we can't just change some MVs to simulate that as we need them for the B frames (and ME) + // and if we ever support non rectangular objects than we need to do a few ifs here anyway :( + if(block==0){ //most common case + if(s->mb_x == s->resync_mb_x){ //rare + *px= *py = 0; + }else if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare + C = mot_val[off[block] - wrap]; + if(s->mb_x==0){ + *px = C[0]; + *py = C[1]; + }else{ + *px = mid_pred(A[0], 0, C[0]); + *py = mid_pred(A[1], 0, C[1]); + } + }else{ + *px = A[0]; + *py = A[1]; + } + }else if(block==1){ + if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare + C = mot_val[off[block] - wrap]; + *px = mid_pred(A[0], 0, C[0]); + *py = mid_pred(A[1], 0, C[1]); + }else{ + *px = A[0]; + *py = A[1]; + } + }else{ /* block==2*/ + B = mot_val[ - wrap]; + C = mot_val[off[block] - wrap]; + if(s->mb_x == s->resync_mb_x) //rare + A[0]=A[1]=0; + + *px = mid_pred(A[0], B[0], C[0]); + *py = mid_pred(A[1], B[1], C[1]); + } + } else { + B = mot_val[ - wrap]; + C = mot_val[off[block] - wrap]; + *px = mid_pred(A[0], B[0], C[0]); + *py = mid_pred(A[1], B[1], C[1]); + } + return *mot_val; +} + + +/** + * Get the GOB height based on picture height. + */ +int ff_h263_get_gob_height(MpegEncContext *s){ + if (s->height <= 400) + return 1; + else if (s->height <= 800) + return 2; + else + return 4; +} diff --git a/ffmpeg/libavcodec/h263.h b/ffmpeg/libavcodec/h263.h new file mode 100644 index 0000000..a95cfb0 --- /dev/null +++ b/ffmpeg/libavcodec/h263.h @@ -0,0 +1,212 @@ +/* + * H263 internal header + * + * 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 + */ +#ifndef AVCODEC_H263_H +#define AVCODEC_H263_H + +#include +#include "libavutil/rational.h" +#include "get_bits.h" +#include "mpegvideo.h" +#include "rl.h" + +// The defines below define the number of bits that are read at once for +// reading vlc values. Changing these may improve speed and data cache needs +// be aware though that decreasing them may need the number of stages that is +// passed to get_vlc* to be increased. +#define INTRA_MCBPC_VLC_BITS 6 +#define INTER_MCBPC_VLC_BITS 7 +#define CBPY_VLC_BITS 6 +#define TEX_VLC_BITS 9 + +extern const AVRational ff_h263_pixel_aspect[16]; +extern const uint8_t ff_h263_cbpy_tab[16][2]; + +extern const uint8_t ff_cbpc_b_tab[4][2]; + +extern const uint8_t ff_mvtab[33][2]; + +extern const uint8_t ff_h263_intra_MCBPC_code[9]; +extern const uint8_t ff_h263_intra_MCBPC_bits[9]; + +extern const uint8_t ff_h263_inter_MCBPC_code[28]; +extern const uint8_t ff_h263_inter_MCBPC_bits[28]; +extern const uint8_t ff_h263_mbtype_b_tab[15][2]; + +extern VLC ff_h263_intra_MCBPC_vlc; +extern VLC ff_h263_inter_MCBPC_vlc; +extern VLC ff_h263_cbpy_vlc; + +extern RLTable ff_h263_rl_inter; + +extern RLTable ff_rl_intra_aic; + +extern const uint16_t ff_h263_format[8][2]; +extern const uint8_t ff_modified_quant_tab[2][32]; +extern const uint16_t ff_mba_max[6]; +extern const uint8_t ff_mba_length[7]; + +extern uint8_t ff_h263_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; + +extern const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[]; + + +int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code); +av_const int ff_h263_aspect_to_info(AVRational aspect); +int ff_h263_decode_init(AVCodecContext *avctx); +int ff_h263_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt); +int ff_h263_decode_end(AVCodecContext *avctx); +void ff_h263_encode_mb(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y); +void ff_h263_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line); +int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, + int *px, int *py); +void ff_h263_encode_init(MpegEncContext *s); +void ff_h263_decode_init_vlc(void); +int ff_h263_decode_picture_header(MpegEncContext *s); +int ff_h263_decode_gob_header(MpegEncContext *s); +void ff_h263_update_motion_val(MpegEncContext * s); +void ff_h263_loop_filter(MpegEncContext * s); +int ff_h263_decode_mba(MpegEncContext *s); +void ff_h263_encode_mba(MpegEncContext *s); +void ff_init_qscale_tab(MpegEncContext *s); +int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr); +void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n); + + +/** + * Print picture info if FF_DEBUG_PICT_INFO is set. + */ +void ff_h263_show_pict_info(MpegEncContext *s); + +int ff_intel_h263_decode_picture_header(MpegEncContext *s); +int ff_h263_decode_mb(MpegEncContext *s, + int16_t block[6][64]); + +/** + * Return the value of the 3bit "source format" syntax element. + * This represents some standard picture dimensions or indicates that + * width&height are explicitly stored later. + */ +int av_const h263_get_picture_format(int width, int height); + +void ff_clean_h263_qscales(MpegEncContext *s); +int ff_h263_resync(MpegEncContext *s); +const uint8_t *ff_h263_find_resync_marker(MpegEncContext *s, const uint8_t *p, const uint8_t *end); +int ff_h263_get_gob_height(MpegEncContext *s); +void ff_h263_encode_motion(MpegEncContext * s, int val, int f_code); + + +static inline int h263_get_motion_length(MpegEncContext * s, int val, int f_code){ + int l, bit_size, code; + + if (val == 0) { + return ff_mvtab[0][1]; + } else { + bit_size = f_code - 1; + /* modulo encoding */ + l= INT_BIT - 6 - bit_size; + val = (val<>l; + val--; + code = (val >> bit_size) + 1; + + return ff_mvtab[code][1] + 1 + bit_size; + } +} + +static inline void ff_h263_encode_motion_vector(MpegEncContext * s, int x, int y, int f_code){ + if(s->flags2 & CODEC_FLAG2_NO_OUTPUT){ + skip_put_bits(&s->pb, + h263_get_motion_length(s, x, f_code) + +h263_get_motion_length(s, y, f_code)); + }else{ + ff_h263_encode_motion(s, x, f_code); + ff_h263_encode_motion(s, y, f_code); + } +} + +static inline int get_p_cbp(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y){ + int cbp, i; + + if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) { + int best_cbpy_score= INT_MAX; + int best_cbpc_score= INT_MAX; + int cbpc = (-1), cbpy= (-1); + const int offset= (s->mv_type==MV_TYPE_16X16 ? 0 : 16) + (s->dquant ? 8 : 0); + const int lambda= s->lambda2 >> (FF_LAMBDA_SHIFT - 6); + + for(i=0; i<4; i++){ + int score= ff_h263_inter_MCBPC_bits[i + offset] * lambda; + if(i&1) score += s->coded_score[5]; + if(i&2) score += s->coded_score[4]; + + if(score < best_cbpc_score){ + best_cbpc_score= score; + cbpc= i; + } + } + + for(i=0; i<16; i++){ + int score= ff_h263_cbpy_tab[i ^ 0xF][1] * lambda; + if(i&1) score += s->coded_score[3]; + if(i&2) score += s->coded_score[2]; + if(i&4) score += s->coded_score[1]; + if(i&8) score += s->coded_score[0]; + + if(score < best_cbpy_score){ + best_cbpy_score= score; + cbpy= i; + } + } + cbp= cbpc + 4*cbpy; + if ((motion_x | motion_y | s->dquant) == 0 && s->mv_type==MV_TYPE_16X16){ + if(best_cbpy_score + best_cbpc_score + 2*lambda >= 0) + cbp= 0; + } + + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0 && ((cbp >> (5 - i))&1)==0 ){ + s->block_last_index[i]= -1; + s->dsp.clear_block(s->block[i]); + } + } + }else{ + cbp= 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + } + return cbp; +} + +static inline void memsetw(short *tab, int val, int n) +{ + int i; + for(i=0;i + * + * 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 + */ + +/** + * @file + * H.263 parser + */ + +#include "parser.h" +#include "h263_parser.h" + +int ff_h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ + int vop_found, i; + uint32_t state; + + vop_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!vop_found){ + for(i=0; i>(32-22) == 0x20){ + i++; + vop_found=1; + break; + } + } + } + + if(vop_found){ + for(; i>(32-22) == 0x20){ + pc->frame_start_found=0; + pc->state=-1; + return i-3; + } + } + } + pc->frame_start_found= vop_found; + pc->state= state; + + return END_NOT_FOUND; +} + +static int h263_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next= ff_h263_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_h263_parser = { + .codec_ids = { AV_CODEC_ID_H263 }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = h263_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/h263_parser.h b/ffmpeg/libavcodec/h263_parser.h new file mode 100644 index 0000000..565a222 --- /dev/null +++ b/ffmpeg/libavcodec/h263_parser.h @@ -0,0 +1,29 @@ +/* + * H.263 parser + * Copyright (c) 2002-2004 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 + */ + +#ifndef AVCODEC_H263_PARSER_H +#define AVCODEC_H263_PARSER_H + +#include "parser.h" + +int ff_h263_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size); + +#endif /* AVCODEC_H263_PARSER_H */ diff --git a/ffmpeg/libavcodec/h263data.h b/ffmpeg/libavcodec/h263data.h new file mode 100644 index 0000000..e245e2f --- /dev/null +++ b/ffmpeg/libavcodec/h263data.h @@ -0,0 +1,299 @@ +/* + * copyright (c) 2000,2001 Fabrice Bellard + * H263+ support + * copyright (c) 2001 Juan J. Sierralta P + * copyright (c) 2002-2004 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 + */ + +/** + * @file + * H.263 tables. + */ + +#ifndef AVCODEC_H263DATA_H +#define AVCODEC_H263DATA_H + +#include +#include "mpegvideo.h" + +/* intra MCBPC, mb_type = (intra), then (intraq) */ +const uint8_t ff_h263_intra_MCBPC_code[9] = { 1, 1, 2, 3, 1, 1, 2, 3, 1 }; +const uint8_t ff_h263_intra_MCBPC_bits[9] = { 1, 3, 3, 3, 4, 6, 6, 6, 9 }; + +/* inter MCBPC, mb_type = (inter), (intra), (interq), (intraq), (inter4v) */ +/* Changed the tables for interq and inter4v+q, following the standard ** Juanjo ** */ +const uint8_t ff_h263_inter_MCBPC_code[28] = { + 1, 3, 2, 5, + 3, 4, 3, 3, + 3, 7, 6, 5, + 4, 4, 3, 2, + 2, 5, 4, 5, + 1, 0, 0, 0, /* Stuffing */ + 2, 12, 14, 15, +}; +const uint8_t ff_h263_inter_MCBPC_bits[28] = { + 1, 4, 4, 6, /* inter */ + 5, 8, 8, 7, /* intra */ + 3, 7, 7, 9, /* interQ */ + 6, 9, 9, 9, /* intraQ */ + 3, 7, 7, 8, /* inter4 */ + 9, 0, 0, 0, /* Stuffing */ + 11, 13, 13, 13,/* inter4Q*/ +}; + +const uint8_t ff_h263_mbtype_b_tab[15][2] = { + {1, 1}, + {3, 3}, + {1, 5}, + {4, 4}, + {5, 4}, + {6, 6}, + {2, 4}, + {3, 4}, + {7, 6}, + {4, 6}, + {5, 6}, + {1, 6}, + {1,10}, + {1, 7}, + {1, 8}, +}; + +const uint8_t ff_cbpc_b_tab[4][2] = { +{0, 1}, +{2, 2}, +{7, 3}, +{6, 3}, +}; + +const uint8_t ff_h263_cbpy_tab[16][2] = +{ + {3,4}, {5,5}, {4,5}, {9,4}, {3,5}, {7,4}, {2,6}, {11,4}, + {2,5}, {3,6}, {5,4}, {10,4}, {4,4}, {8,4}, {6,4}, {3,2} +}; + +const uint8_t ff_mvtab[33][2] = +{ + {1,1}, {1,2}, {1,3}, {1,4}, {3,6}, {5,7}, {4,7}, {3,7}, + {11,9}, {10,9}, {9,9}, {17,10}, {16,10}, {15,10}, {14,10}, {13,10}, + {12,10}, {11,10}, {10,10}, {9,10}, {8,10}, {7,10}, {6,10}, {5,10}, + {4,10}, {7,11}, {6,11}, {5,11}, {4,11}, {3,11}, {2,11}, {3,12}, + {2,12} +}; + +/* third non intra table */ +const uint16_t ff_inter_vlc[103][2] = { +{ 0x2, 2 },{ 0xf, 4 },{ 0x15, 6 },{ 0x17, 7 }, +{ 0x1f, 8 },{ 0x25, 9 },{ 0x24, 9 },{ 0x21, 10 }, +{ 0x20, 10 },{ 0x7, 11 },{ 0x6, 11 },{ 0x20, 11 }, +{ 0x6, 3 },{ 0x14, 6 },{ 0x1e, 8 },{ 0xf, 10 }, +{ 0x21, 11 },{ 0x50, 12 },{ 0xe, 4 },{ 0x1d, 8 }, +{ 0xe, 10 },{ 0x51, 12 },{ 0xd, 5 },{ 0x23, 9 }, +{ 0xd, 10 },{ 0xc, 5 },{ 0x22, 9 },{ 0x52, 12 }, +{ 0xb, 5 },{ 0xc, 10 },{ 0x53, 12 },{ 0x13, 6 }, +{ 0xb, 10 },{ 0x54, 12 },{ 0x12, 6 },{ 0xa, 10 }, +{ 0x11, 6 },{ 0x9, 10 },{ 0x10, 6 },{ 0x8, 10 }, +{ 0x16, 7 },{ 0x55, 12 },{ 0x15, 7 },{ 0x14, 7 }, +{ 0x1c, 8 },{ 0x1b, 8 },{ 0x21, 9 },{ 0x20, 9 }, +{ 0x1f, 9 },{ 0x1e, 9 },{ 0x1d, 9 },{ 0x1c, 9 }, +{ 0x1b, 9 },{ 0x1a, 9 },{ 0x22, 11 },{ 0x23, 11 }, +{ 0x56, 12 },{ 0x57, 12 },{ 0x7, 4 },{ 0x19, 9 }, +{ 0x5, 11 },{ 0xf, 6 },{ 0x4, 11 },{ 0xe, 6 }, +{ 0xd, 6 },{ 0xc, 6 },{ 0x13, 7 },{ 0x12, 7 }, +{ 0x11, 7 },{ 0x10, 7 },{ 0x1a, 8 },{ 0x19, 8 }, +{ 0x18, 8 },{ 0x17, 8 },{ 0x16, 8 },{ 0x15, 8 }, +{ 0x14, 8 },{ 0x13, 8 },{ 0x18, 9 },{ 0x17, 9 }, +{ 0x16, 9 },{ 0x15, 9 },{ 0x14, 9 },{ 0x13, 9 }, +{ 0x12, 9 },{ 0x11, 9 },{ 0x7, 10 },{ 0x6, 10 }, +{ 0x5, 10 },{ 0x4, 10 },{ 0x24, 11 },{ 0x25, 11 }, +{ 0x26, 11 },{ 0x27, 11 },{ 0x58, 12 },{ 0x59, 12 }, +{ 0x5a, 12 },{ 0x5b, 12 },{ 0x5c, 12 },{ 0x5d, 12 }, +{ 0x5e, 12 },{ 0x5f, 12 },{ 0x3, 7 }, +}; + +const int8_t ff_inter_level[102] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 1, 2, 3, 4, + 5, 6, 1, 2, 3, 4, 1, 2, + 3, 1, 2, 3, 1, 2, 3, 1, + 2, 3, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 3, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +const int8_t ff_inter_run[102] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 0, 0, 0, 1, 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, 32, 33, 34, + 35, 36, 37, 38, 39, 40, +}; + +RLTable ff_h263_rl_inter = { + 102, + 58, + ff_inter_vlc, + ff_inter_run, + ff_inter_level, +}; + +static const uint16_t intra_vlc_aic[103][2] = { +{ 0x2, 2 }, { 0x6, 3 }, { 0xe, 4 }, { 0xc, 5 }, +{ 0xd, 5 }, { 0x10, 6 }, { 0x11, 6 }, { 0x12, 6 }, +{ 0x16, 7 }, { 0x1b, 8 }, { 0x20, 9 }, { 0x21, 9 }, +{ 0x1a, 9 }, { 0x1b, 9 }, { 0x1c, 9 }, { 0x1d, 9 }, +{ 0x1e, 9 }, { 0x1f, 9 }, { 0x23, 11 }, { 0x22, 11 }, +{ 0x57, 12 }, { 0x56, 12 }, { 0x55, 12 }, { 0x54, 12 }, +{ 0x53, 12 }, { 0xf, 4 }, { 0x14, 6 }, { 0x14, 7 }, +{ 0x1e, 8 }, { 0xf, 10 }, { 0x21, 11 }, { 0x50, 12 }, +{ 0xb, 5 }, { 0x15, 7 }, { 0xe, 10 }, { 0x9, 10 }, +{ 0x15, 6 }, { 0x1d, 8 }, { 0xd, 10 }, { 0x51, 12 }, +{ 0x13, 6 }, { 0x23, 9 }, { 0x7, 11 }, { 0x17, 7 }, +{ 0x22, 9 }, { 0x52, 12 }, { 0x1c, 8 }, { 0xc, 10 }, +{ 0x1f, 8 }, { 0xb, 10 }, { 0x25, 9 }, { 0xa, 10 }, +{ 0x24, 9 }, { 0x6, 11 }, { 0x21, 10 }, { 0x20, 10 }, +{ 0x8, 10 }, { 0x20, 11 }, { 0x7, 4 }, { 0xc, 6 }, +{ 0x10, 7 }, { 0x13, 8 }, { 0x11, 9 }, { 0x12, 9 }, +{ 0x4, 10 }, { 0x27, 11 }, { 0x26, 11 }, { 0x5f, 12 }, +{ 0xf, 6 }, { 0x13, 9 }, { 0x5, 10 }, { 0x25, 11 }, +{ 0xe, 6 }, { 0x14, 9 }, { 0x24, 11 }, { 0xd, 6 }, +{ 0x6, 10 }, { 0x5e, 12 }, { 0x11, 7 }, { 0x7, 10 }, +{ 0x13, 7 }, { 0x5d, 12 }, { 0x12, 7 }, { 0x5c, 12 }, +{ 0x14, 8 }, { 0x5b, 12 }, { 0x15, 8 }, { 0x1a, 8 }, +{ 0x19, 8 }, { 0x18, 8 }, { 0x17, 8 }, { 0x16, 8 }, +{ 0x19, 9 }, { 0x15, 9 }, { 0x16, 9 }, { 0x18, 9 }, +{ 0x17, 9 }, { 0x4, 11 }, { 0x5, 11 }, { 0x58, 12 }, +{ 0x59, 12 }, { 0x5a, 12 }, { 0x3, 7 }, +}; + +static const int8_t intra_run_aic[102] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 5, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 11, +12, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 3, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, +18, 19, 20, 21, 22, 23, +}; + +static const int8_t intra_level_aic[102] = { + 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, 1, 2, 3, 4, 5, 6, 7, + 1, 2, 3, 4, 1, 2, 3, 4, + 1, 2, 3, 1, 2, 3, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 1, + 1, 1, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 1, 2, 3, 4, + 1, 2, 3, 1, 2, 3, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +RLTable ff_rl_intra_aic = { + 102, + 58, + intra_vlc_aic, + intra_run_aic, + intra_level_aic, +}; + +const uint16_t ff_h263_format[8][2] = { + { 0, 0 }, + { 128, 96 }, + { 176, 144 }, + { 352, 288 }, + { 704, 576 }, + { 1408, 1152 }, +}; + +const uint8_t ff_aic_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, 2, 4, 6, 8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62 +}; + +const uint8_t ff_modified_quant_tab[2][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, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9,10,11,12,13,14,15,16,17,18,18,19,20,21,22,23,24,25,26,27,28 +},{ + 0, 2, 3, 4, 5, 6, 7, 8, 9,10,11,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,31,31,26 +} +}; + +const uint8_t ff_h263_chroma_qscale_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, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9,10,10,11,11,12,12,12,13,13,13,14,14,14,14,14,15,15,15,15,15 +}; + +const uint16_t ff_mba_max[6]={ + 47, 98, 395,1583,6335,9215 +}; + +const uint8_t ff_mba_length[7]={ + 6, 7, 9, 11, 13, 14, 14 +}; + +const uint8_t ff_h263_loop_filter_strength[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, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9,10,10,10,11,11,11,12,12,12 +}; + +const AVRational ff_h263_pixel_aspect[16]={ + {0, 1}, + {1, 1}, + {12, 11}, + {10, 11}, + {16, 11}, + {40, 33}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, + {0, 1}, +}; + +#endif /* AVCODEC_H263DATA_H */ diff --git a/ffmpeg/libavcodec/h263dec.c b/ffmpeg/libavcodec/h263dec.c new file mode 100644 index 0000000..66d00d4 --- /dev/null +++ b/ffmpeg/libavcodec/h263dec.c @@ -0,0 +1,813 @@ +/* + * H.263 decoder + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * H.263 decoder. + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +#include "libavutil/cpu.h" +#include "internal.h" +#include "avcodec.h" +#include "error_resilience.h" +#include "mpegvideo.h" +#include "h263.h" +#include "h263_parser.h" +#include "mpeg4video_parser.h" +#include "msmpeg4.h" +#include "vdpau_internal.h" +#include "thread.h" +#include "flv.h" +#include "mpeg4video.h" + +//#define DEBUG +//#define PRINT_FRAME_TIME + +av_cold int ff_h263_decode_init(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + int ret; + + s->avctx = avctx; + s->out_format = FMT_H263; + + s->width = avctx->coded_width; + s->height = avctx->coded_height; + s->workaround_bugs= avctx->workaround_bugs; + + // set defaults + ff_MPV_decode_defaults(s); + s->quant_precision=5; + s->decode_mb= ff_h263_decode_mb; + s->low_delay= 1; + if (avctx->codec->id == AV_CODEC_ID_MSS2) + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + else + avctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); + s->unrestricted_mv= 1; + + /* select sub codec */ + switch(avctx->codec->id) { + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + s->unrestricted_mv= 0; + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + break; + case AV_CODEC_ID_MPEG4: + break; + case AV_CODEC_ID_MSMPEG4V1: + s->h263_pred = 1; + s->msmpeg4_version=1; + break; + case AV_CODEC_ID_MSMPEG4V2: + s->h263_pred = 1; + s->msmpeg4_version=2; + break; + case AV_CODEC_ID_MSMPEG4V3: + s->h263_pred = 1; + s->msmpeg4_version=3; + break; + case AV_CODEC_ID_WMV1: + s->h263_pred = 1; + s->msmpeg4_version=4; + break; + case AV_CODEC_ID_WMV2: + s->h263_pred = 1; + s->msmpeg4_version=5; + break; + case AV_CODEC_ID_VC1: + case AV_CODEC_ID_WMV3: + case AV_CODEC_ID_VC1IMAGE: + case AV_CODEC_ID_WMV3IMAGE: + case AV_CODEC_ID_MSS2: + s->h263_pred = 1; + s->msmpeg4_version=6; + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + break; + case AV_CODEC_ID_H263I: + break; + case AV_CODEC_ID_FLV1: + s->h263_flv = 1; + break; + default: + return AVERROR(EINVAL); + } + s->codec_id= avctx->codec->id; + avctx->hwaccel= ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt); + + /* for h263, we allocate the images after having read the header */ + if (avctx->codec->id != AV_CODEC_ID_H263 && avctx->codec->id != AV_CODEC_ID_H263P && avctx->codec->id != AV_CODEC_ID_MPEG4) + if ((ret = ff_MPV_common_init(s)) < 0) + return ret; + + ff_h263_decode_init_vlc(); + + return 0; +} + +av_cold int ff_h263_decode_end(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + + ff_MPV_common_end(s); + return 0; +} + +/** + * Return the number of bytes consumed for building the current frame. + */ +static int get_consumed_bytes(MpegEncContext *s, int buf_size){ + int pos= (get_bits_count(&s->gb)+7)>>3; + + if(s->divx_packed || s->avctx->hwaccel){ + //we would have to scan through the whole buf to handle the weird reordering ... + return buf_size; + }else if(s->flags&CODEC_FLAG_TRUNCATED){ + pos -= s->parse_context.last_index; + if(pos<0) pos=0; // padding is not really read so this might be -1 + return pos; + }else{ + if(pos==0) pos=1; //avoid infinite loops (i doubt that is needed but ...) + if(pos+10>buf_size) pos=buf_size; // oops ;) + + return pos; + } +} + +static int decode_slice(MpegEncContext *s){ + const int part_mask= s->partitioned_frame ? (ER_AC_END|ER_AC_ERROR) : 0x7F; + const int mb_size= 16>>s->avctx->lowres; + int ret; + + s->last_resync_gb= s->gb; + s->first_slice_line= 1; + + s->resync_mb_x= s->mb_x; + s->resync_mb_y= s->mb_y; + + ff_set_qscale(s, s->qscale); + + if (s->avctx->hwaccel) { + const uint8_t *start= s->gb.buffer + get_bits_count(&s->gb)/8; + const uint8_t *end = ff_h263_find_resync_marker(s, start + 1, s->gb.buffer_end); + skip_bits_long(&s->gb, 8*(end - start)); + return s->avctx->hwaccel->decode_slice(s->avctx, start, end - start); + } + + if(s->partitioned_frame){ + const int qscale= s->qscale; + + if(CONFIG_MPEG4_DECODER && s->codec_id==AV_CODEC_ID_MPEG4){ + if ((ret = ff_mpeg4_decode_partitions(s)) < 0) + return ret; + } + + /* restore variables which were modified */ + s->first_slice_line=1; + s->mb_x= s->resync_mb_x; + s->mb_y= s->resync_mb_y; + ff_set_qscale(s, qscale); + } + + for(; s->mb_y < s->mb_height; s->mb_y++) { + /* per-row end of slice checks */ + if(s->msmpeg4_version){ + if(s->resync_mb_y + s->slice_height == s->mb_y){ + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END); + + return 0; + } + } + + if(s->msmpeg4_version==1){ + s->last_dc[0]= + s->last_dc[1]= + s->last_dc[2]= 128; + } + + ff_init_block_index(s); + for(; s->mb_x < s->mb_width; s->mb_x++) { + int ret; + + ff_update_block_index(s); + + if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){ + s->first_slice_line=0; + } + + /* DCT & quantize */ + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; +// s->mb_skipped = 0; + av_dlog(s, "%d %d %06X\n", + ret, get_bits_count(&s->gb), show_bits(&s->gb, 24)); + ret= s->decode_mb(s, s->block); + + if (s->pict_type!=AV_PICTURE_TYPE_B) + ff_h263_update_motion_val(s); + + if(ret<0){ + const int xy= s->mb_x + s->mb_y*s->mb_stride; + if(ret==SLICE_END){ + ff_MPV_decode_mb(s, s->block); + if(s->loop_filter) + ff_h263_loop_filter(s); + + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_END&part_mask); + + s->padding_bug_score--; + + if(++s->mb_x >= s->mb_width){ + s->mb_x=0; + ff_mpeg_draw_horiz_band(s, s->mb_y*mb_size, mb_size); + ff_MPV_report_decode_progress(s); + s->mb_y++; + } + return 0; + }else if(ret==SLICE_NOEND){ + av_log(s->avctx, AV_LOG_ERROR, "Slice mismatch at MB: %d\n", xy); + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, ER_MB_END&part_mask); + return AVERROR_INVALIDDATA; + } + av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", xy); + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR&part_mask); + + return AVERROR_INVALIDDATA; + } + + ff_MPV_decode_mb(s, s->block); + if(s->loop_filter) + ff_h263_loop_filter(s); + } + + ff_mpeg_draw_horiz_band(s, s->mb_y*mb_size, mb_size); + ff_MPV_report_decode_progress(s); + + s->mb_x= 0; + } + + av_assert1(s->mb_x==0 && s->mb_y==s->mb_height); + + if(s->codec_id==AV_CODEC_ID_MPEG4 + && (s->workaround_bugs&FF_BUG_AUTODETECT) + && get_bits_left(&s->gb) >= 48 + && show_bits(&s->gb, 24)==0x4010 + && !s->data_partitioning) + s->padding_bug_score+=32; + + /* try to detect the padding bug */ + if( s->codec_id==AV_CODEC_ID_MPEG4 + && (s->workaround_bugs&FF_BUG_AUTODETECT) + && get_bits_left(&s->gb) >=0 + && get_bits_left(&s->gb) < 137 +// && !s->resync_marker + && !s->data_partitioning){ + + const int bits_count= get_bits_count(&s->gb); + const int bits_left = s->gb.size_in_bits - bits_count; + + if(bits_left==0){ + s->padding_bug_score+=16; + } else if(bits_left != 1){ + int v= show_bits(&s->gb, 8); + v|= 0x7F >> (7-(bits_count&7)); + + if(v==0x7F && bits_left<=8) + s->padding_bug_score--; + else if(v==0x7F && ((get_bits_count(&s->gb)+8)&8) && bits_left<=16) + s->padding_bug_score+= 4; + else + s->padding_bug_score++; + } + } + + if(s->workaround_bugs&FF_BUG_AUTODETECT){ + if(s->padding_bug_score > -2 && !s->data_partitioning /*&& (s->divx_version>=0 || !s->resync_marker)*/) + s->workaround_bugs |= FF_BUG_NO_PADDING; + else + s->workaround_bugs &= ~FF_BUG_NO_PADDING; + } + + // handle formats which don't have unique end markers + if(s->msmpeg4_version || (s->workaround_bugs&FF_BUG_NO_PADDING)){ //FIXME perhaps solve this more cleanly + int left= get_bits_left(&s->gb); + int max_extra=7; + + /* no markers in M$ crap */ + if(s->msmpeg4_version && s->pict_type==AV_PICTURE_TYPE_I) + max_extra+= 17; + + /* buggy padding but the frame should still end approximately at the bitstream end */ + if((s->workaround_bugs&FF_BUG_NO_PADDING) && (s->err_recognition&(AV_EF_BUFFER|AV_EF_AGGRESSIVE))) + max_extra+= 48; + else if((s->workaround_bugs&FF_BUG_NO_PADDING)) + max_extra+= 256*256*256*64; + + if(left>max_extra){ + av_log(s->avctx, AV_LOG_ERROR, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24)); + } + else if(left<0){ + av_log(s->avctx, AV_LOG_ERROR, "overreading %d bits\n", -left); + }else + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END); + + return 0; + } + + av_log(s->avctx, AV_LOG_ERROR, "slice end not reached but screenspace end (%d left %06X, score= %d)\n", + get_bits_left(&s->gb), + show_bits(&s->gb, 24), s->padding_bug_score); + + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_END&part_mask); + + return AVERROR_INVALIDDATA; +} + +int ff_h263_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MpegEncContext *s = avctx->priv_data; + int ret; + AVFrame *pict = data; + +#ifdef PRINT_FRAME_TIME +uint64_t time= rdtsc(); +#endif + s->flags= avctx->flags; + s->flags2= avctx->flags2; + + /* no supplementary picture */ + if (buf_size == 0) { + /* special case for last picture */ + if (s->low_delay==0 && s->next_picture_ptr) { + if ((ret = av_frame_ref(pict, &s->next_picture_ptr->f)) < 0) + return ret; + s->next_picture_ptr= NULL; + + *got_frame = 1; + } + + return 0; + } + + if(s->flags&CODEC_FLAG_TRUNCATED){ + int next; + + if(CONFIG_MPEG4_DECODER && s->codec_id==AV_CODEC_ID_MPEG4){ + next= ff_mpeg4_find_frame_end(&s->parse_context, buf, buf_size); + }else if(CONFIG_H263_DECODER && s->codec_id==AV_CODEC_ID_H263){ + next= ff_h263_find_frame_end(&s->parse_context, buf, buf_size); + }else if(CONFIG_H263P_DECODER && s->codec_id==AV_CODEC_ID_H263P){ + next= ff_h263_find_frame_end(&s->parse_context, buf, buf_size); + }else{ + av_log(s->avctx, AV_LOG_ERROR, "this codec does not support truncated bitstreams\n"); + return AVERROR(EINVAL); + } + + if( ff_combine_frame(&s->parse_context, next, (const uint8_t **)&buf, &buf_size) < 0 ) + return buf_size; + } + + +retry: + if(s->divx_packed && s->bitstream_buffer_size){ + int i; + for(i=0; iavctx, AV_LOG_WARNING, "Discarding excessive bitstream in packed xvid\n"); + s->bitstream_buffer_size=0; + } + break; + } + } + } + + if(s->bitstream_buffer_size && (s->divx_packed || buf_size<20)){ //divx 5.01+/xvid frame reorder + init_get_bits(&s->gb, s->bitstream_buffer, s->bitstream_buffer_size*8); + }else + init_get_bits(&s->gb, buf, buf_size*8); + s->bitstream_buffer_size=0; + + if (!s->context_initialized) { + if ((ret = ff_MPV_common_init(s)) < 0) //we need the idct permutaton for reading a custom matrix + return ret; + } + + /* We need to set current_picture_ptr before reading the header, + * otherwise we cannot store anyting in there */ + if (s->current_picture_ptr == NULL || s->current_picture_ptr->f.data[0]) { + int i= ff_find_unused_picture(s, 0); + if (i < 0) + return i; + s->current_picture_ptr= &s->picture[i]; + } + + /* let's go :-) */ + if (CONFIG_WMV2_DECODER && s->msmpeg4_version==5) { + ret= ff_wmv2_decode_picture_header(s); + } else if (CONFIG_MSMPEG4_DECODER && s->msmpeg4_version) { + ret = ff_msmpeg4_decode_picture_header(s); + } else if (CONFIG_MPEG4_DECODER && s->h263_pred) { + if(s->avctx->extradata_size && s->picture_number==0){ + GetBitContext gb; + + init_get_bits(&gb, s->avctx->extradata, s->avctx->extradata_size*8); + ret = ff_mpeg4_decode_picture_header(s, &gb); + } + ret = ff_mpeg4_decode_picture_header(s, &s->gb); + } else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) { + ret = ff_intel_h263_decode_picture_header(s); + } else if (CONFIG_FLV_DECODER && s->h263_flv) { + ret = ff_flv_decode_picture_header(s); + } else { + ret = ff_h263_decode_picture_header(s); + } + + if (ret < 0 || ret==FRAME_SKIPPED) { + if ( s->width != avctx->coded_width + || s->height != avctx->coded_height) { + av_log(s->avctx, AV_LOG_WARNING, "Reverting picture dimensions change due to header decoding failure\n"); + s->width = avctx->coded_width; + s->height= avctx->coded_height; + } + } + if(ret==FRAME_SKIPPED) return get_consumed_bytes(s, buf_size); + + /* skip if the header was thrashed */ + if (ret < 0){ + av_log(s->avctx, AV_LOG_ERROR, "header damaged\n"); + return ret; + } + + avctx->has_b_frames= !s->low_delay; + + if(s->xvid_build==-1 && s->divx_version==-1 && s->lavc_build==-1){ + if(s->stream_codec_tag == AV_RL32("XVID") || + s->codec_tag == AV_RL32("XVID") || s->codec_tag == AV_RL32("XVIX") || + s->codec_tag == AV_RL32("RMP4") || s->codec_tag == AV_RL32("ZMP4") || + s->codec_tag == AV_RL32("SIPP") + ) + s->xvid_build= 0; +#if 0 + if(s->codec_tag == AV_RL32("DIVX") && s->vo_type==0 && s->vol_control_parameters==1 + && s->padding_bug_score > 0 && s->low_delay) // XVID with modified fourcc + s->xvid_build= 0; +#endif + } + + if(s->xvid_build==-1 && s->divx_version==-1 && s->lavc_build==-1){ + if(s->codec_tag == AV_RL32("DIVX") && s->vo_type==0 && s->vol_control_parameters==0) + s->divx_version= 400; //divx 4 + } + + if(s->xvid_build>=0 && s->divx_version>=0){ + s->divx_version= + s->divx_build= -1; + } + + if(s->workaround_bugs&FF_BUG_AUTODETECT){ + if(s->codec_tag == AV_RL32("XVIX")) + s->workaround_bugs|= FF_BUG_XVID_ILACE; + + if(s->codec_tag == AV_RL32("UMP4")){ + s->workaround_bugs|= FF_BUG_UMP4; + } + + if(s->divx_version>=500 && s->divx_build<1814){ + s->workaround_bugs|= FF_BUG_QPEL_CHROMA; + } + + if(s->divx_version>502 && s->divx_build<1814){ + s->workaround_bugs|= FF_BUG_QPEL_CHROMA2; + } + + if(s->xvid_build<=3U) + s->padding_bug_score= 256*256*256*64; + + if(s->xvid_build<=1U) + s->workaround_bugs|= FF_BUG_QPEL_CHROMA; + + if(s->xvid_build<=12U) + s->workaround_bugs|= FF_BUG_EDGE; + + if(s->xvid_build<=32U) + s->workaround_bugs|= FF_BUG_DC_CLIP; + +#define SET_QPEL_FUNC(postfix1, postfix2) \ + s->dsp.put_ ## postfix1 = ff_put_ ## postfix2;\ + s->dsp.put_no_rnd_ ## postfix1 = ff_put_no_rnd_ ## postfix2;\ + s->dsp.avg_ ## postfix1 = ff_avg_ ## postfix2; + + if(s->lavc_build<4653U) + s->workaround_bugs|= FF_BUG_STD_QPEL; + + if(s->lavc_build<4655U) + s->workaround_bugs|= FF_BUG_DIRECT_BLOCKSIZE; + + if(s->lavc_build<4670U){ + s->workaround_bugs|= FF_BUG_EDGE; + } + + if(s->lavc_build<=4712U) + s->workaround_bugs|= FF_BUG_DC_CLIP; + + if(s->divx_version>=0) + s->workaround_bugs|= FF_BUG_DIRECT_BLOCKSIZE; + if(s->divx_version==501 && s->divx_build==20020416) + s->padding_bug_score= 256*256*256*64; + + if(s->divx_version<500U){ + s->workaround_bugs|= FF_BUG_EDGE; + } + + if(s->divx_version>=0) + s->workaround_bugs|= FF_BUG_HPEL_CHROMA; +#if 0 + if(s->divx_version==500) + s->padding_bug_score= 256*256*256*64; + + /* very ugly XVID padding bug detection FIXME/XXX solve this differently + * Let us hope this at least works. + */ + if( s->resync_marker==0 && s->data_partitioning==0 && s->divx_version==-1 + && s->codec_id==AV_CODEC_ID_MPEG4 && s->vo_type==0) + s->workaround_bugs|= FF_BUG_NO_PADDING; + + if(s->lavc_build<4609U) //FIXME not sure about the version num but a 4609 file seems ok + s->workaround_bugs|= FF_BUG_NO_PADDING; +#endif + } + + if(s->workaround_bugs& FF_BUG_STD_QPEL){ + SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_old_c) + + SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_old_c) + SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_old_c) + } + + if(avctx->debug & FF_DEBUG_BUGS) + av_log(s->avctx, AV_LOG_DEBUG, "bugs: %X lavc_build:%d xvid_build:%d divx_version:%d divx_build:%d %s\n", + s->workaround_bugs, s->lavc_build, s->xvid_build, s->divx_version, s->divx_build, + s->divx_packed ? "p" : ""); + +#if HAVE_MMX + if (s->codec_id == AV_CODEC_ID_MPEG4 && s->xvid_build>=0 && avctx->idct_algo == FF_IDCT_AUTO && (av_get_cpu_flags() & AV_CPU_FLAG_MMX)) { + avctx->idct_algo= FF_IDCT_XVIDMMX; + ff_dct_common_init(s); + goto retry; + } +#endif + + /* After H263 & mpeg4 header decode we have the height, width,*/ + /* and other parameters. So then we could init the picture */ + /* FIXME: By the way H263 decoder is evolving it should have */ + /* an H263EncContext */ + + if ((!avctx->coded_width || !avctx->coded_height) && 0) { + ParseContext pc= s->parse_context; //FIXME move these demuxng hack to avformat + + s->parse_context.buffer=0; + ff_MPV_common_end(s); + s->parse_context= pc; + avcodec_set_dimensions(avctx, s->width, s->height); + + goto retry; + } + + if (s->width != avctx->coded_width || + s->height != avctx->coded_height || + s->context_reinit) { + /* H.263 could change picture size any time */ + s->context_reinit = 0; + + avcodec_set_dimensions(avctx, s->width, s->height); + + if ((ret = ff_MPV_common_frame_size_change(s))) + return ret; + } + + if((s->codec_id==AV_CODEC_ID_H263 || s->codec_id==AV_CODEC_ID_H263P || s->codec_id == AV_CODEC_ID_H263I)) + s->gob_index = ff_h263_get_gob_height(s); + + // for skipping the frame + s->current_picture.f.pict_type = s->pict_type; + s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + /* skip B-frames if we don't have reference frames */ + if (s->last_picture_ptr == NULL && + (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) + return get_consumed_bytes(s, buf_size); + if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==AV_PICTURE_TYPE_B) + || (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=AV_PICTURE_TYPE_I) + || avctx->skip_frame >= AVDISCARD_ALL) + return get_consumed_bytes(s, buf_size); + + if(s->next_p_frame_damaged){ + if(s->pict_type==AV_PICTURE_TYPE_B) + return get_consumed_bytes(s, buf_size); + else + s->next_p_frame_damaged=0; + } + + if((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){ + s->me.qpel_put= s->dsp.put_qpel_pixels_tab; + s->me.qpel_avg= s->dsp.avg_qpel_pixels_tab; + }else{ + s->me.qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab; + s->me.qpel_avg= s->dsp.avg_qpel_pixels_tab; + } + + if ((ret = ff_MPV_frame_start(s, avctx)) < 0) + return ret; + + if (!s->divx_packed) ff_thread_finish_setup(avctx); + + if (CONFIG_MPEG4_VDPAU_DECODER && (s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)) { + ff_vdpau_mpeg4_decode_picture(s, s->gb.buffer, s->gb.buffer_end - s->gb.buffer); + goto frame_end; + } + + if (avctx->hwaccel) { + if ((ret = avctx->hwaccel->start_frame(avctx, s->gb.buffer, s->gb.buffer_end - s->gb.buffer)) < 0) + return ret; + } + + ff_mpeg_er_frame_start(s); + + //the second part of the wmv2 header contains the MB skip bits which are stored in current_picture->mb_type + //which is not available before ff_MPV_frame_start() + if (CONFIG_WMV2_DECODER && s->msmpeg4_version==5){ + ret = ff_wmv2_decode_secondary_picture_header(s); + if(ret<0) return ret; + if(ret==1) goto intrax8_decoded; + } + + /* decode each macroblock */ + s->mb_x=0; + s->mb_y=0; + + ret = decode_slice(s); + while(s->mb_ymb_height){ + if(s->msmpeg4_version){ + if(s->slice_height==0 || s->mb_x!=0 || (s->mb_y%s->slice_height)!=0 || get_bits_left(&s->gb)<0) + break; + }else{ + int prev_x=s->mb_x, prev_y=s->mb_y; + if(ff_h263_resync(s)<0) + break; + if (prev_y * s->mb_width + prev_x < s->mb_y * s->mb_width + s->mb_x) + s->er.error_occurred = 1; + } + + if(s->msmpeg4_version<4 && s->h263_pred) + ff_mpeg4_clean_buffers(s); + + if (decode_slice(s) < 0) ret = AVERROR_INVALIDDATA; + } + + if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type==AV_PICTURE_TYPE_I) + if(!CONFIG_MSMPEG4_DECODER || ff_msmpeg4_decode_ext_header(s, buf_size) < 0){ + s->er.error_status_table[s->mb_num - 1] = ER_MB_ERROR; + } + + av_assert1(s->bitstream_buffer_size==0); +frame_end: + /* divx 5.01+ bitstream reorder stuff */ + if(s->codec_id==AV_CODEC_ID_MPEG4 && s->divx_packed){ + int current_pos= s->gb.buffer == s->bitstream_buffer ? 0 : (get_bits_count(&s->gb)>>3); + int startcode_found=0; + + if(buf_size - current_pos > 7){ + int i; + for(i=current_pos; ibitstream_buffer, + &s->allocated_bitstream_buffer_size, + buf_size - current_pos + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->bitstream_buffer) + return AVERROR(ENOMEM); + memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos); + s->bitstream_buffer_size= buf_size - current_pos; + } + } + +intrax8_decoded: + ff_er_frame_end(&s->er); + + if (avctx->hwaccel) { + if ((ret = avctx->hwaccel->end_frame(avctx)) < 0) + return ret; + } + + ff_MPV_frame_end(s); + + assert(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type); + assert(s->current_picture.f.pict_type == s->pict_type); + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { + if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->current_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); + } else if (s->last_picture_ptr != NULL) { + if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->last_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); + } + + if(s->last_picture_ptr || s->low_delay){ + *got_frame = 1; + } + +#ifdef PRINT_FRAME_TIME +av_log(avctx, AV_LOG_DEBUG, "%"PRId64"\n", rdtsc()-time); +#endif + + return (ret && (avctx->err_recognition & AV_EF_EXPLODE))?ret:get_consumed_bytes(s, buf_size); +} + +const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[] = { +#if CONFIG_VAAPI + AV_PIX_FMT_VAAPI_VLD, +#endif +#if CONFIG_VDPAU + AV_PIX_FMT_VDPAU, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +AVCodec ff_h263_decoder = { + .name = "h263", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_h263_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | + CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, + .flush = ff_mpeg_flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), + .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, +}; + +AVCodec ff_h263p_decoder = { + .name = "h263p", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263P, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_h263_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | + CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, + .flush = ff_mpeg_flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), + .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, +}; diff --git a/ffmpeg/libavcodec/h264.c b/ffmpeg/libavcodec/h264.c new file mode 100644 index 0000000..87322a2 --- /dev/null +++ b/ffmpeg/libavcodec/h264.c @@ -0,0 +1,5034 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 codec. + * @author Michael Niedermayer + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "internal.h" +#include "cabac.h" +#include "cabac_functions.h" +#include "dsputil.h" +#include "error_resilience.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h264.h" +#include "h264data.h" +#include "h264chroma.h" +#include "h264_mvpred.h" +#include "golomb.h" +#include "mathops.h" +#include "rectangle.h" +#include "svq3.h" +#include "thread.h" +#include "vdpau_internal.h" +#include "libavutil/avassert.h" + +// #undef NDEBUG +#include + +const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 }; + +static const uint8_t rem6[QP_MAX_NUM + 1] = { + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + 0, 1, 2, 3, +}; + +static const uint8_t div6[QP_MAX_NUM + 1] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13,13, 13, 13, 13, + 14,14,14,14, +}; + +static const enum AVPixelFormat h264_hwaccel_pixfmt_list_420[] = { +#if CONFIG_H264_DXVA2_HWACCEL + AV_PIX_FMT_DXVA2_VLD, +#endif +#if CONFIG_H264_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI_VLD, +#endif +#if CONFIG_H264_VDA_HWACCEL + AV_PIX_FMT_VDA_VLD, +#endif +#if CONFIG_H264_VDPAU_HWACCEL + AV_PIX_FMT_VDPAU, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat h264_hwaccel_pixfmt_list_jpeg_420[] = { +#if CONFIG_H264_DXVA2_HWACCEL + AV_PIX_FMT_DXVA2_VLD, +#endif +#if CONFIG_H264_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI_VLD, +#endif +#if CONFIG_H264_VDA_HWACCEL + AV_PIX_FMT_VDA_VLD, +#endif +#if CONFIG_H264_VDPAU_HWACCEL + AV_PIX_FMT_VDPAU, +#endif + AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_NONE +}; + +int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + return h ? h->sps.num_reorder_frames : 0; +} + +static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, + int (*mv)[2][4][2], + int mb_x, int mb_y, int mb_intra, int mb_skipped) +{ + H264Context *h = opaque; + + h->mb_x = mb_x; + h->mb_y = mb_y; + h->mb_xy = mb_x + mb_y * h->mb_stride; + memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache)); + av_assert1(ref >= 0); + /* FIXME: It is possible albeit uncommon that slice references + * differ between slices. We take the easy approach and ignore + * it for now. If this turns out to have any relevance in + * practice then correct remapping should be added. */ + if (ref >= h->ref_count[0]) + ref = 0; + if (!h->ref_list[0][ref].f.data[0]) { + av_log(h->avctx, AV_LOG_DEBUG, "Reference not available for error concealing\n"); + ref = 0; + } + if ((h->ref_list[0][ref].reference&3) != 3) { + av_log(h->avctx, AV_LOG_DEBUG, "Reference invalid\n"); + return; + } + fill_rectangle(&h->cur_pic.ref_index[0][4 * h->mb_xy], + 2, 2, 2, ref, 1); + fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); + fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, + pack16to32((*mv)[0][0][0], (*mv)[0][0][1]), 4); + h->mb_mbaff = + h->mb_field_decoding_flag = 0; + ff_h264_hl_decode_mb(h); +} + +void ff_h264_draw_horiz_band(H264Context *h, int y, int height) +{ + AVCodecContext *avctx = h->avctx; + Picture *cur = &h->cur_pic; + Picture *last = h->ref_list[0][0].f.data[0] ? &h->ref_list[0][0] : NULL; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int vshift = desc->log2_chroma_h; + const int field_pic = h->picture_structure != PICT_FRAME; + if (field_pic) { + height <<= 1; + y <<= 1; + } + + height = FFMIN(height, avctx->height - y); + + if (field_pic && h->first_field && !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) + return; + + if (avctx->draw_horiz_band) { + AVFrame *src; + int offset[AV_NUM_DATA_POINTERS]; + int i; + + if (cur->f.pict_type == AV_PICTURE_TYPE_B || h->low_delay || + (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) + src = &cur->f; + else if (last) + src = &last->f; + else + return; + + offset[0] = y * src->linesize[0]; + offset[1] = + offset[2] = (y >> vshift) * src->linesize[1]; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + + emms_c(); + + avctx->draw_horiz_band(avctx, src, offset, + y, h->picture_structure, height); + } +} + +static void unref_picture(H264Context *h, Picture *pic) +{ + int off = offsetof(Picture, tf) + sizeof(pic->tf); + int i; + + if (!pic->f.data[0]) + return; + + pic->period_since_free = 0; + ff_thread_release_buffer(h->avctx, &pic->tf); + av_buffer_unref(&pic->hwaccel_priv_buf); + + av_buffer_unref(&pic->qscale_table_buf); + av_buffer_unref(&pic->mb_type_buf); + for (i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } + + memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); +} + +static void release_unused_pictures(H264Context *h, int remove_current) +{ + int i; + + /* release non reference frames */ + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (h->DPB[i].f.data[0] && !h->DPB[i].reference && + (remove_current || &h->DPB[i] != h->cur_pic_ptr)) { + unref_picture(h, &h->DPB[i]); + } + } +} + +static int ref_picture(H264Context *h, Picture *dst, Picture *src) +{ + int ret, i; + + av_assert0(!dst->f.buf[0]); + av_assert0(src->f.buf[0]); + + src->tf.f = &src->f; + dst->tf.f = &dst->f; + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + + + dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf); + dst->mb_type_buf = av_buffer_ref(src->mb_type_buf); + if (!dst->qscale_table_buf || !dst->mb_type_buf) + goto fail; + dst->qscale_table = src->qscale_table; + dst->mb_type = src->mb_type; + + for (i = 0; i < 2; i ++) { + dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]); + dst->ref_index_buf[i] = av_buffer_ref(src->ref_index_buf[i]); + if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i]) + goto fail; + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; + } + + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + + for (i = 0; i < 2; i++) + dst->field_poc[i] = src->field_poc[i]; + + memcpy(dst->ref_poc, src->ref_poc, sizeof(src->ref_poc)); + memcpy(dst->ref_count, src->ref_count, sizeof(src->ref_count)); + + dst->poc = src->poc; + dst->frame_num = src->frame_num; + dst->mmco_reset = src->mmco_reset; + dst->pic_id = src->pic_id; + dst->long_ref = src->long_ref; + dst->mbaff = src->mbaff; + dst->field_picture = src->field_picture; + dst->needs_realloc = src->needs_realloc; + dst->reference = src->reference; + dst->sync = src->sync; + dst->period_since_free = src->period_since_free; + + return 0; +fail: + unref_picture(h, dst); + return ret; +} + + +static int alloc_scratch_buffers(H264Context *h, int linesize) +{ + int alloc_size = FFALIGN(FFABS(linesize) + 32, 32); + + if (h->bipred_scratchpad) + return 0; + + h->bipred_scratchpad = av_malloc(16 * 6 * alloc_size); + // edge emu needs blocksize + filter length - 1 + // (= 21x21 for h264) + h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 21); + h->me.scratchpad = av_mallocz(alloc_size * 2 * 16 * 2); + + if (!h->bipred_scratchpad || !h->edge_emu_buffer || !h->me.scratchpad) { + av_freep(&h->bipred_scratchpad); + av_freep(&h->edge_emu_buffer); + av_freep(&h->me.scratchpad); + return AVERROR(ENOMEM); + } + + h->me.temp = h->me.scratchpad; + + return 0; +} + +static int init_table_pools(H264Context *h) +{ + const int big_mb_num = h->mb_stride * (h->mb_height + 1) + 1; + const int mb_array_size = h->mb_stride * h->mb_height; + const int b4_stride = h->mb_width * 4 + 1; + const int b4_array_size = b4_stride * h->mb_height * 4; + + h->qscale_table_pool = av_buffer_pool_init(big_mb_num + h->mb_stride, + av_buffer_allocz); + h->mb_type_pool = av_buffer_pool_init((big_mb_num + h->mb_stride) * + sizeof(uint32_t), av_buffer_allocz); + h->motion_val_pool = av_buffer_pool_init(2 * (b4_array_size + 4) * + sizeof(int16_t), av_buffer_allocz); + h->ref_index_pool = av_buffer_pool_init(4 * mb_array_size, av_buffer_allocz); + + if (!h->qscale_table_pool || !h->mb_type_pool || !h->motion_val_pool || + !h->ref_index_pool) { + av_buffer_pool_uninit(&h->qscale_table_pool); + av_buffer_pool_uninit(&h->mb_type_pool); + av_buffer_pool_uninit(&h->motion_val_pool); + av_buffer_pool_uninit(&h->ref_index_pool); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int alloc_picture(H264Context *h, Picture *pic) +{ + int i, ret = 0; + + av_assert0(!pic->f.data[0]); + + pic->tf.f = &pic->f; + ret = ff_thread_get_buffer(h->avctx, &pic->tf, pic->reference ? + AV_GET_BUFFER_FLAG_REF : 0); + if (ret < 0) + goto fail; + + h->linesize = pic->f.linesize[0]; + h->uvlinesize = pic->f.linesize[1]; + + if (h->avctx->hwaccel) { + const AVHWAccel *hwaccel = h->avctx->hwaccel; + av_assert0(!pic->hwaccel_picture_private); + if (hwaccel->priv_data_size) { + pic->hwaccel_priv_buf = av_buffer_allocz(hwaccel->priv_data_size); + if (!pic->hwaccel_priv_buf) + return AVERROR(ENOMEM); + pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; + } + } + + if (!h->qscale_table_pool) { + ret = init_table_pools(h); + if (ret < 0) + goto fail; + } + + pic->qscale_table_buf = av_buffer_pool_get(h->qscale_table_pool); + pic->mb_type_buf = av_buffer_pool_get(h->mb_type_pool); + if (!pic->qscale_table_buf || !pic->mb_type_buf) + goto fail; + + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * h->mb_stride + 1; + pic->qscale_table = pic->qscale_table_buf->data + 2 * h->mb_stride + 1; + + for (i = 0; i < 2; i++) { + pic->motion_val_buf[i] = av_buffer_pool_get(h->motion_val_pool); + pic->ref_index_buf[i] = av_buffer_pool_get(h->ref_index_pool); + if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) + goto fail; + + pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; + pic->ref_index[i] = pic->ref_index_buf[i]->data; + } + + return 0; +fail: + unref_picture(h, pic); + return (ret < 0) ? ret : AVERROR(ENOMEM); +} + +static inline int pic_is_unused(H264Context *h, Picture *pic) +{ + if ( (h->avctx->active_thread_type & FF_THREAD_FRAME) + && pic->f.qscale_table //check if the frame has anything allocated + && pic->period_since_free < h->avctx->thread_count) + return 0; + if (pic->f.data[0] == NULL) + return 1; + if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) + return 1; + return 0; +} + +static int find_unused_picture(H264Context *h) +{ + int i; + + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (pic_is_unused(h, &h->DPB[i])) + break; + } + if (i == MAX_PICTURE_COUNT) + return AVERROR_INVALIDDATA; + + if (h->DPB[i].needs_realloc) { + h->DPB[i].needs_realloc = 0; + unref_picture(h, &h->DPB[i]); + } + + return i; +} + +/** + * Check if the top & left blocks are available if needed and + * change the dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra4x4_pred_mode(H264Context *h) +{ + static const int8_t top[12] = { + -1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0 + }; + static const int8_t left[12] = { + 0, -1, TOP_DC_PRED, 0, -1, -1, -1, 0, -1, DC_128_PRED + }; + int i; + + if (!(h->top_samples_available & 0x8000)) { + for (i = 0; i < 4; i++) { + int status = top[h->intra4x4_pred_mode_cache[scan8[0] + i]]; + if (status < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "top block unavailable for requested intra4x4 mode %d at %d %d\n", + status, h->mb_x, h->mb_y); + return -1; + } else if (status) { + h->intra4x4_pred_mode_cache[scan8[0] + i] = status; + } + } + } + + if ((h->left_samples_available & 0x8888) != 0x8888) { + static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 }; + for (i = 0; i < 4; i++) + if (!(h->left_samples_available & mask[i])) { + int status = left[h->intra4x4_pred_mode_cache[scan8[0] + 8 * i]]; + if (status < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "left block unavailable for requested intra4x4 mode %d at %d %d\n", + status, h->mb_x, h->mb_y); + return -1; + } else if (status) { + h->intra4x4_pred_mode_cache[scan8[0] + 8 * i] = status; + } + } + } + + return 0; +} // FIXME cleanup like ff_h264_check_intra_pred_mode + +/** + * Check if the top & left blocks are available if needed and + * change the dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma) +{ + static const int8_t top[7] = { LEFT_DC_PRED8x8, 1, -1, -1 }; + static const int8_t left[7] = { TOP_DC_PRED8x8, -1, 2, -1, DC_128_PRED8x8 }; + + if (mode > 6U) { + av_log(h->avctx, AV_LOG_ERROR, + "out of range intra chroma pred mode at %d %d\n", + h->mb_x, h->mb_y); + return -1; + } + + if (!(h->top_samples_available & 0x8000)) { + mode = top[mode]; + if (mode < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "top block unavailable for requested intra mode at %d %d\n", + h->mb_x, h->mb_y); + return -1; + } + } + + if ((h->left_samples_available & 0x8080) != 0x8080) { + mode = left[mode]; + if (is_chroma && (h->left_samples_available & 0x8080)) { + // mad cow disease mode, aka MBAFF + constrained_intra_pred + mode = ALZHEIMER_DC_L0T_PRED8x8 + + (!(h->left_samples_available & 0x8000)) + + 2 * (mode == DC_128_PRED8x8); + } + if (mode < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "left block unavailable for requested intra mode at %d %d\n", + h->mb_x, h->mb_y); + return -1; + } + } + + return mode; +} + +const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, + int *dst_length, int *consumed, int length) +{ + int i, si, di; + uint8_t *dst; + int bufidx; + + // src[0]&0x80; // forbidden bit + h->nal_ref_idc = src[0] >> 5; + h->nal_unit_type = src[0] & 0x1F; + + src++; + length--; + +#define STARTCODE_TEST \ + if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) { \ + if (src[i + 2] != 3) { \ + /* startcode, so we must be past the end */ \ + length = i; \ + } \ + break; \ + } +#if HAVE_FAST_UNALIGNED +#define FIND_FIRST_ZERO \ + if (i > 0 && !src[i]) \ + i--; \ + while (src[i]) \ + i++ +#if HAVE_FAST_64BIT + for (i = 0; i + 1 < length; i += 9) { + if (!((~AV_RN64A(src + i) & + (AV_RN64A(src + i) - 0x0100010001000101ULL)) & + 0x8000800080008080ULL)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 7; + } +#else + for (i = 0; i + 1 < length; i += 5) { + if (!((~AV_RN32A(src + i) & + (AV_RN32A(src + i) - 0x01000101U)) & + 0x80008080U)) + continue; + FIND_FIRST_ZERO; + STARTCODE_TEST; + i -= 3; + } +#endif +#else + for (i = 0; i + 1 < length; i += 2) { + if (src[i]) + continue; + if (i > 0 && src[i - 1] == 0) + i--; + STARTCODE_TEST; + } +#endif + + // use second escape buffer for inter data + bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; + + si = h->rbsp_buffer_size[bufidx]; + av_fast_padded_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+MAX_MBPAIR_SIZE); + dst = h->rbsp_buffer[bufidx]; + + if (dst == NULL) + return NULL; + + if(i>=length-1){ //no escaped 0 + *dst_length= length; + *consumed= length+1; //+1 for the header + if(h->avctx->flags2 & CODEC_FLAG2_FAST){ + return src; + }else{ + memcpy(dst, src, length); + return dst; + } + } + + memcpy(dst, src, i); + si = di = i; + while (si + 2 < length) { + // remove escapes (very rare 1:2^22) + if (src[si + 2] > 3) { + dst[di++] = src[si++]; + dst[di++] = src[si++]; + } else if (src[si] == 0 && src[si + 1] == 0) { + if (src[si + 2] == 3) { // escape + dst[di++] = 0; + dst[di++] = 0; + si += 3; + continue; + } else // next start code + goto nsc; + } + + dst[di++] = src[si++]; + } + while (si < length) + dst[di++] = src[si++]; +nsc: + + memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + *dst_length = di; + *consumed = si + 1; // +1 for the header + /* FIXME store exact number of bits in the getbitcontext + * (it is needed for decoding) */ + return dst; +} + +/** + * Identify the exact end of the bitstream + * @return the length of the trailing, or 0 if damaged + */ +static int decode_rbsp_trailing(H264Context *h, const uint8_t *src) +{ + int v = *src; + int r; + + tprintf(h->avctx, "rbsp trailing %X\n", v); + + for (r = 1; r < 9; r++) { + if (v & 1) + return r; + v >>= 1; + } + return 0; +} + +static inline int get_lowest_part_list_y(H264Context *h, Picture *pic, int n, + int height, int y_offset, int list) +{ + int raw_my = h->mv_cache[list][scan8[n]][1]; + int filter_height_down = (raw_my & 3) ? 3 : 0; + int full_my = (raw_my >> 2) + y_offset; + int bottom = full_my + filter_height_down + height; + + av_assert2(height >= 0); + + return FFMAX(0, bottom); +} + +static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, + int height, int y_offset, int list0, + int list1, int *nrefs) +{ + int my; + + y_offset += 16 * (h->mb_y >> MB_FIELD(h)); + + if (list0) { + int ref_n = h->ref_cache[0][scan8[n]]; + Picture *ref = &h->ref_list[0][ref_n]; + + // Error resilience puts the current picture in the ref list. + // Don't try to wait on these as it will cause a deadlock. + // Fields can wait on each other, though. + if (ref->tf.progress->data != h->cur_pic.tf.progress->data || + (ref->reference & 3) != h->picture_structure) { + my = get_lowest_part_list_y(h, ref, n, height, y_offset, 0); + if (refs[0][ref_n] < 0) + nrefs[0] += 1; + refs[0][ref_n] = FFMAX(refs[0][ref_n], my); + } + } + + if (list1) { + int ref_n = h->ref_cache[1][scan8[n]]; + Picture *ref = &h->ref_list[1][ref_n]; + + if (ref->tf.progress->data != h->cur_pic.tf.progress->data || + (ref->reference & 3) != h->picture_structure) { + my = get_lowest_part_list_y(h, ref, n, height, y_offset, 1); + if (refs[1][ref_n] < 0) + nrefs[1] += 1; + refs[1][ref_n] = FFMAX(refs[1][ref_n], my); + } + } +} + +/** + * Wait until all reference frames are available for MC operations. + * + * @param h the H264 context + */ +static void await_references(H264Context *h) +{ + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + int refs[2][48]; + int nrefs[2] = { 0 }; + int ref, list; + + memset(refs, -1, sizeof(refs)); + + if (IS_16X16(mb_type)) { + get_lowest_part_y(h, refs, 0, 16, 0, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); + } else if (IS_16X8(mb_type)) { + get_lowest_part_y(h, refs, 0, 8, 0, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); + get_lowest_part_y(h, refs, 8, 8, 8, + IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); + } else if (IS_8X16(mb_type)) { + get_lowest_part_y(h, refs, 0, 16, 0, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs); + get_lowest_part_y(h, refs, 4, 16, 0, + IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs); + } else { + int i; + + av_assert2(IS_8X8(mb_type)); + + for (i = 0; i < 4; i++) { + const int sub_mb_type = h->sub_mb_type[i]; + const int n = 4 * i; + int y_offset = (i & 2) << 2; + + if (IS_SUB_8X8(sub_mb_type)) { + get_lowest_part_y(h, refs, n, 8, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } else if (IS_SUB_8X4(sub_mb_type)) { + get_lowest_part_y(h, refs, n, 4, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + get_lowest_part_y(h, refs, n + 2, 4, y_offset + 4, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } else if (IS_SUB_4X8(sub_mb_type)) { + get_lowest_part_y(h, refs, n, 8, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + get_lowest_part_y(h, refs, n + 1, 8, y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } else { + int j; + av_assert2(IS_SUB_4X4(sub_mb_type)); + for (j = 0; j < 4; j++) { + int sub_y_offset = y_offset + 2 * (j & 2); + get_lowest_part_y(h, refs, n + j, 4, sub_y_offset, + IS_DIR(sub_mb_type, 0, 0), + IS_DIR(sub_mb_type, 0, 1), + nrefs); + } + } + } + } + + for (list = h->list_count - 1; list >= 0; list--) + for (ref = 0; ref < 48 && nrefs[list]; ref++) { + int row = refs[list][ref]; + if (row >= 0) { + Picture *ref_pic = &h->ref_list[list][ref]; + int ref_field = ref_pic->reference - 1; + int ref_field_picture = ref_pic->field_picture; + int pic_height = 16 * h->mb_height >> ref_field_picture; + + row <<= MB_MBAFF(h); + nrefs[list]--; + + if (!FIELD_PICTURE(h) && ref_field_picture) { // frame referencing two fields + ff_thread_await_progress(&ref_pic->tf, + FFMIN((row >> 1) - !(row & 1), + pic_height - 1), + 1); + ff_thread_await_progress(&ref_pic->tf, + FFMIN((row >> 1), pic_height - 1), + 0); + } else if (FIELD_PICTURE(h) && !ref_field_picture) { // field referencing one field of a frame + ff_thread_await_progress(&ref_pic->tf, + FFMIN(row * 2 + ref_field, + pic_height - 1), + 0); + } else if (FIELD_PICTURE(h)) { + ff_thread_await_progress(&ref_pic->tf, + FFMIN(row, pic_height - 1), + ref_field); + } else { + ff_thread_await_progress(&ref_pic->tf, + FFMIN(row, pic_height - 1), + 0); + } + } + } +} + +static av_always_inline void mc_dir_part(H264Context *h, Picture *pic, + int n, int square, int height, + int delta, int list, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int src_x_offset, int src_y_offset, + qpel_mc_func *qpix_op, + h264_chroma_mc_func chroma_op, + int pixel_shift, int chroma_idc) +{ + const int mx = h->mv_cache[list][scan8[n]][0] + src_x_offset * 8; + int my = h->mv_cache[list][scan8[n]][1] + src_y_offset * 8; + const int luma_xy = (mx & 3) + ((my & 3) << 2); + int offset = ((mx >> 2) << pixel_shift) + (my >> 2) * h->mb_linesize; + uint8_t *src_y = pic->f.data[0] + offset; + uint8_t *src_cb, *src_cr; + int extra_width = 0; + int extra_height = 0; + int emu = 0; + const int full_mx = mx >> 2; + const int full_my = my >> 2; + const int pic_width = 16 * h->mb_width; + const int pic_height = 16 * h->mb_height >> MB_FIELD(h); + int ysh; + + if (mx & 7) + extra_width -= 3; + if (my & 7) + extra_height -= 3; + + if (full_mx < 0 - extra_width || + full_my < 0 - extra_height || + full_mx + 16 /*FIXME*/ > pic_width + extra_width || + full_my + 16 /*FIXME*/ > pic_height + extra_height) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, + src_y - (2 << pixel_shift) - 2 * h->mb_linesize, + h->mb_linesize, + 16 + 5, 16 + 5 /*FIXME*/, full_mx - 2, + full_my - 2, pic_width, pic_height); + src_y = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + emu = 1; + } + + qpix_op[luma_xy](dest_y, src_y, h->mb_linesize); // FIXME try variable height perhaps? + if (!square) + qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize); + + if (CONFIG_GRAY && h->flags & CODEC_FLAG_GRAY) + return; + + if (chroma_idc == 3 /* yuv444 */) { + src_cb = pic->f.data[1] + offset; + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, + src_cb - (2 << pixel_shift) - 2 * h->mb_linesize, + h->mb_linesize, + 16 + 5, 16 + 5 /*FIXME*/, + full_mx - 2, full_my - 2, + pic_width, pic_height); + src_cb = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + } + qpix_op[luma_xy](dest_cb, src_cb, h->mb_linesize); // FIXME try variable height perhaps? + if (!square) + qpix_op[luma_xy](dest_cb + delta, src_cb + delta, h->mb_linesize); + + src_cr = pic->f.data[2] + offset; + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, + src_cr - (2 << pixel_shift) - 2 * h->mb_linesize, + h->mb_linesize, + 16 + 5, 16 + 5 /*FIXME*/, + full_mx - 2, full_my - 2, + pic_width, pic_height); + src_cr = h->edge_emu_buffer + (2 << pixel_shift) + 2 * h->mb_linesize; + } + qpix_op[luma_xy](dest_cr, src_cr, h->mb_linesize); // FIXME try variable height perhaps? + if (!square) + qpix_op[luma_xy](dest_cr + delta, src_cr + delta, h->mb_linesize); + return; + } + + ysh = 3 - (chroma_idc == 2 /* yuv422 */); + if (chroma_idc == 1 /* yuv420 */ && MB_FIELD(h)) { + // chroma offset when predicting from a field of opposite parity + my += 2 * ((h->mb_y & 1) - (pic->reference - 1)); + emu |= (my >> 3) < 0 || (my >> 3) + 8 >= (pic_height >> 1); + } + + src_cb = pic->f.data[1] + ((mx >> 3) << pixel_shift) + + (my >> ysh) * h->mb_uvlinesize; + src_cr = pic->f.data[2] + ((mx >> 3) << pixel_shift) + + (my >> ysh) * h->mb_uvlinesize; + + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cb, h->mb_uvlinesize, + 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), + pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); + src_cb = h->edge_emu_buffer; + } + chroma_op(dest_cb, src_cb, h->mb_uvlinesize, + height >> (chroma_idc == 1 /* yuv420 */), + mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); + + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src_cr, h->mb_uvlinesize, + 9, 8 * chroma_idc + 1, (mx >> 3), (my >> ysh), + pic_width >> 1, pic_height >> (chroma_idc == 1 /* yuv420 */)); + src_cr = h->edge_emu_buffer; + } + chroma_op(dest_cr, src_cr, h->mb_uvlinesize, height >> (chroma_idc == 1 /* yuv420 */), + mx & 7, (my << (chroma_idc == 2 /* yuv422 */)) & 7); +} + +static av_always_inline void mc_part_std(H264Context *h, int n, int square, + int height, int delta, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int x_offset, int y_offset, + qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put, + qpel_mc_func *qpix_avg, + h264_chroma_mc_func chroma_avg, + int list0, int list1, + int pixel_shift, int chroma_idc) +{ + qpel_mc_func *qpix_op = qpix_put; + h264_chroma_mc_func chroma_op = chroma_put; + + dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + if (chroma_idc == 3 /* yuv444 */) { + dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + } else if (chroma_idc == 2 /* yuv422 */) { + dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + } else { /* yuv420 */ + dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + } + x_offset += 8 * h->mb_x; + y_offset += 8 * (h->mb_y >> MB_FIELD(h)); + + if (list0) { + Picture *ref = &h->ref_list[0][h->ref_cache[0][scan8[n]]]; + mc_dir_part(h, ref, n, square, height, delta, 0, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, pixel_shift, chroma_idc); + + qpix_op = qpix_avg; + chroma_op = chroma_avg; + } + + if (list1) { + Picture *ref = &h->ref_list[1][h->ref_cache[1][scan8[n]]]; + mc_dir_part(h, ref, n, square, height, delta, 1, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_op, chroma_op, pixel_shift, chroma_idc); + } +} + +static av_always_inline void mc_part_weighted(H264Context *h, int n, int square, + int height, int delta, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int x_offset, int y_offset, + qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put, + h264_weight_func luma_weight_op, + h264_weight_func chroma_weight_op, + h264_biweight_func luma_weight_avg, + h264_biweight_func chroma_weight_avg, + int list0, int list1, + int pixel_shift, int chroma_idc) +{ + int chroma_height; + + dest_y += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + if (chroma_idc == 3 /* yuv444 */) { + chroma_height = height; + chroma_weight_avg = luma_weight_avg; + chroma_weight_op = luma_weight_op; + dest_cb += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + dest_cr += (2 * x_offset << pixel_shift) + 2 * y_offset * h->mb_linesize; + } else if (chroma_idc == 2 /* yuv422 */) { + chroma_height = height; + dest_cb += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + 2 * y_offset * h->mb_uvlinesize; + } else { /* yuv420 */ + chroma_height = height >> 1; + dest_cb += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + dest_cr += (x_offset << pixel_shift) + y_offset * h->mb_uvlinesize; + } + x_offset += 8 * h->mb_x; + y_offset += 8 * (h->mb_y >> MB_FIELD(h)); + + if (list0 && list1) { + /* don't optimize for luma-only case, since B-frames usually + * use implicit weights => chroma too. */ + uint8_t *tmp_cb = h->bipred_scratchpad; + uint8_t *tmp_cr = h->bipred_scratchpad + (16 << pixel_shift); + uint8_t *tmp_y = h->bipred_scratchpad + 16 * h->mb_uvlinesize; + int refn0 = h->ref_cache[0][scan8[n]]; + int refn1 = h->ref_cache[1][scan8[n]]; + + mc_dir_part(h, &h->ref_list[0][refn0], n, square, height, delta, 0, + dest_y, dest_cb, dest_cr, + x_offset, y_offset, qpix_put, chroma_put, + pixel_shift, chroma_idc); + mc_dir_part(h, &h->ref_list[1][refn1], n, square, height, delta, 1, + tmp_y, tmp_cb, tmp_cr, + x_offset, y_offset, qpix_put, chroma_put, + pixel_shift, chroma_idc); + + if (h->use_weight == 2) { + int weight0 = h->implicit_weight[refn0][refn1][h->mb_y & 1]; + int weight1 = 64 - weight0; + luma_weight_avg(dest_y, tmp_y, h->mb_linesize, + height, 5, weight0, weight1, 0); + chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, + chroma_height, 5, weight0, weight1, 0); + chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, + chroma_height, 5, weight0, weight1, 0); + } else { + luma_weight_avg(dest_y, tmp_y, h->mb_linesize, height, + h->luma_log2_weight_denom, + h->luma_weight[refn0][0][0], + h->luma_weight[refn1][1][0], + h->luma_weight[refn0][0][1] + + h->luma_weight[refn1][1][1]); + chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn0][0][0][0], + h->chroma_weight[refn1][1][0][0], + h->chroma_weight[refn0][0][0][1] + + h->chroma_weight[refn1][1][0][1]); + chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn0][0][1][0], + h->chroma_weight[refn1][1][1][0], + h->chroma_weight[refn0][0][1][1] + + h->chroma_weight[refn1][1][1][1]); + } + } else { + int list = list1 ? 1 : 0; + int refn = h->ref_cache[list][scan8[n]]; + Picture *ref = &h->ref_list[list][refn]; + mc_dir_part(h, ref, n, square, height, delta, list, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_put, chroma_put, pixel_shift, chroma_idc); + + luma_weight_op(dest_y, h->mb_linesize, height, + h->luma_log2_weight_denom, + h->luma_weight[refn][list][0], + h->luma_weight[refn][list][1]); + if (h->use_weight_chroma) { + chroma_weight_op(dest_cb, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn][list][0][0], + h->chroma_weight[refn][list][0][1]); + chroma_weight_op(dest_cr, h->mb_uvlinesize, chroma_height, + h->chroma_log2_weight_denom, + h->chroma_weight[refn][list][1][0], + h->chroma_weight[refn][list][1][1]); + } + } +} + +static av_always_inline void prefetch_motion(H264Context *h, int list, + int pixel_shift, int chroma_idc) +{ + /* fetch pixels for estimated mv 4 macroblocks ahead + * optimized for 64byte cache lines */ + const int refn = h->ref_cache[list][scan8[0]]; + if (refn >= 0) { + const int mx = (h->mv_cache[list][scan8[0]][0] >> 2) + 16 * h->mb_x + 8; + const int my = (h->mv_cache[list][scan8[0]][1] >> 2) + 16 * h->mb_y; + uint8_t **src = h->ref_list[list][refn].f.data; + int off = (mx << pixel_shift) + + (my + (h->mb_x & 3) * 4) * h->mb_linesize + + (64 << pixel_shift); + h->vdsp.prefetch(src[0] + off, h->linesize, 4); + if (chroma_idc == 3 /* yuv444 */) { + h->vdsp.prefetch(src[1] + off, h->linesize, 4); + h->vdsp.prefetch(src[2] + off, h->linesize, 4); + } else { + off= (((mx>>1)+64)<>1) + (h->mb_x&7))*h->uvlinesize; + h->vdsp.prefetch(src[1] + off, src[2] - src[1], 2); + } + } +} + +static void free_tables(H264Context *h, int free_rbsp) +{ + int i; + H264Context *hx; + + av_freep(&h->intra4x4_pred_mode); + av_freep(&h->chroma_pred_mode_table); + av_freep(&h->cbp_table); + av_freep(&h->mvd_table[0]); + av_freep(&h->mvd_table[1]); + av_freep(&h->direct_table); + av_freep(&h->non_zero_count); + av_freep(&h->slice_table_base); + h->slice_table = NULL; + av_freep(&h->list_counts); + + av_freep(&h->mb2b_xy); + av_freep(&h->mb2br_xy); + + for (i = 0; i < 3; i++) + av_freep(&h->visualization_buffer[i]); + + av_buffer_pool_uninit(&h->qscale_table_pool); + av_buffer_pool_uninit(&h->mb_type_pool); + av_buffer_pool_uninit(&h->motion_val_pool); + av_buffer_pool_uninit(&h->ref_index_pool); + + if (free_rbsp && h->DPB) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) + unref_picture(h, &h->DPB[i]); + av_freep(&h->DPB); + } else if (h->DPB) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) + h->DPB[i].needs_realloc = 1; + } + + h->cur_pic_ptr = NULL; + + for (i = 0; i < MAX_THREADS; i++) { + hx = h->thread_context[i]; + if (!hx) + continue; + av_freep(&hx->top_borders[1]); + av_freep(&hx->top_borders[0]); + av_freep(&hx->bipred_scratchpad); + av_freep(&hx->edge_emu_buffer); + av_freep(&hx->dc_val_base); + av_freep(&hx->me.scratchpad); + av_freep(&hx->er.mb_index2xy); + av_freep(&hx->er.error_status_table); + av_freep(&hx->er.er_temp_buffer); + av_freep(&hx->er.mbintra_table); + av_freep(&hx->er.mbskip_table); + + if (free_rbsp) { + av_freep(&hx->rbsp_buffer[1]); + av_freep(&hx->rbsp_buffer[0]); + hx->rbsp_buffer_size[0] = 0; + hx->rbsp_buffer_size[1] = 0; + } + if (i) + av_freep(&h->thread_context[i]); + } +} + +static void init_dequant8_coeff_table(H264Context *h) +{ + int i, j, q, x; + const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); + + for (i = 0; i < 6; i++) { + h->dequant8_coeff[i] = h->dequant8_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(h->pps.scaling_matrix8[j], h->pps.scaling_matrix8[i], + 64 * sizeof(uint8_t))) { + h->dequant8_coeff[i] = h->dequant8_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int shift = div6[q]; + int idx = rem6[q]; + for (x = 0; x < 64; x++) + h->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] = + ((uint32_t)dequant8_coeff_init[idx][dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] * + h->pps.scaling_matrix8[i][x]) << shift; + } + } +} + +static void init_dequant4_coeff_table(H264Context *h) +{ + int i, j, q, x; + const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8); + for (i = 0; i < 6; i++) { + h->dequant4_coeff[i] = h->dequant4_buffer[i]; + for (j = 0; j < i; j++) + if (!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i], + 16 * sizeof(uint8_t))) { + h->dequant4_coeff[i] = h->dequant4_buffer[j]; + break; + } + if (j < i) + continue; + + for (q = 0; q < max_qp + 1; q++) { + int shift = div6[q] + 2; + int idx = rem6[q]; + for (x = 0; x < 16; x++) + h->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] = + ((uint32_t)dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * + h->pps.scaling_matrix4[i][x]) << shift; + } + } +} + +static void init_dequant_tables(H264Context *h) +{ + int i, x; + init_dequant4_coeff_table(h); + if (h->pps.transform_8x8_mode) + init_dequant8_coeff_table(h); + if (h->sps.transform_bypass) { + for (i = 0; i < 6; i++) + for (x = 0; x < 16; x++) + h->dequant4_coeff[i][0][x] = 1 << 6; + if (h->pps.transform_8x8_mode) + for (i = 0; i < 6; i++) + for (x = 0; x < 64; x++) + h->dequant8_coeff[i][0][x] = 1 << 6; + } +} + +int ff_h264_alloc_tables(H264Context *h) +{ + const int big_mb_num = h->mb_stride * (h->mb_height + 1); + const int row_mb_num = 2*h->mb_stride*FFMAX(h->avctx->thread_count, 1); + int x, y, i; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->intra4x4_pred_mode, + row_mb_num * 8 * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->non_zero_count, + big_mb_num * 48 * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->slice_table_base, + (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->cbp_table, + big_mb_num * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->chroma_pred_mode_table, + big_mb_num * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[0], + 16 * row_mb_num * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->mvd_table[1], + 16 * row_mb_num * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->direct_table, + 4 * big_mb_num * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->list_counts, + big_mb_num * sizeof(uint8_t), fail) + + memset(h->slice_table_base, -1, + (big_mb_num + h->mb_stride) * sizeof(*h->slice_table_base)); + h->slice_table = h->slice_table_base + h->mb_stride * 2 + 1; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2b_xy, + big_mb_num * sizeof(uint32_t), fail); + FF_ALLOCZ_OR_GOTO(h->avctx, h->mb2br_xy, + big_mb_num * sizeof(uint32_t), fail); + for (y = 0; y < h->mb_height; y++) + for (x = 0; x < h->mb_width; x++) { + const int mb_xy = x + y * h->mb_stride; + const int b_xy = 4 * x + 4 * y * h->b_stride; + + h->mb2b_xy[mb_xy] = b_xy; + h->mb2br_xy[mb_xy] = 8 * (FMO ? mb_xy : (mb_xy % (2 * h->mb_stride))); + } + + if (!h->dequant4_coeff[0]) + init_dequant_tables(h); + + if (!h->DPB) { + h->DPB = av_mallocz_array(MAX_PICTURE_COUNT, sizeof(*h->DPB)); + if (!h->DPB) + return AVERROR(ENOMEM); + for (i = 0; i < MAX_PICTURE_COUNT; i++) + avcodec_get_frame_defaults(&h->DPB[i].f); + avcodec_get_frame_defaults(&h->cur_pic.f); + } + + return 0; + +fail: + free_tables(h, 1); + return -1; +} + +/** + * Mimic alloc_tables(), but for every context thread. + */ +static void clone_tables(H264Context *dst, H264Context *src, int i) +{ + dst->intra4x4_pred_mode = src->intra4x4_pred_mode + i * 8 * 2 * src->mb_stride; + dst->non_zero_count = src->non_zero_count; + dst->slice_table = src->slice_table; + dst->cbp_table = src->cbp_table; + dst->mb2b_xy = src->mb2b_xy; + dst->mb2br_xy = src->mb2br_xy; + dst->chroma_pred_mode_table = src->chroma_pred_mode_table; + dst->mvd_table[0] = src->mvd_table[0] + i * 8 * 2 * src->mb_stride; + dst->mvd_table[1] = src->mvd_table[1] + i * 8 * 2 * src->mb_stride; + dst->direct_table = src->direct_table; + dst->list_counts = src->list_counts; + dst->DPB = src->DPB; + dst->cur_pic_ptr = src->cur_pic_ptr; + dst->cur_pic = src->cur_pic; + dst->bipred_scratchpad = NULL; + dst->edge_emu_buffer = NULL; + dst->me.scratchpad = NULL; + ff_h264_pred_init(&dst->hpc, src->avctx->codec_id, src->sps.bit_depth_luma, + src->sps.chroma_format_idc); +} + +/** + * Init context + * Allocate buffers which are not shared amongst multiple threads. + */ +static int context_init(H264Context *h) +{ + ERContext *er = &h->er; + int mb_array_size = h->mb_height * h->mb_stride; + int y_size = (2 * h->mb_width + 1) * (2 * h->mb_height + 1); + int c_size = h->mb_stride * (h->mb_height + 1); + int yc_size = y_size + 2 * c_size; + int x, y, i; + + FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[0], + h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail) + FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[1], + h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail) + + h->ref_cache[0][scan8[5] + 1] = + h->ref_cache[0][scan8[7] + 1] = + h->ref_cache[0][scan8[13] + 1] = + h->ref_cache[1][scan8[5] + 1] = + h->ref_cache[1][scan8[7] + 1] = + h->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; + + if (CONFIG_ERROR_RESILIENCE) { + /* init ER */ + er->avctx = h->avctx; + er->dsp = &h->dsp; + er->decode_mb = h264_er_decode_mb; + er->opaque = h; + er->quarter_sample = 1; + + er->mb_num = h->mb_num; + er->mb_width = h->mb_width; + er->mb_height = h->mb_height; + er->mb_stride = h->mb_stride; + er->b8_stride = h->mb_width * 2 + 1; + + FF_ALLOCZ_OR_GOTO(h->avctx, er->mb_index2xy, (h->mb_num + 1) * sizeof(int), + fail); // error ressilience code looks cleaner with this + for (y = 0; y < h->mb_height; y++) + for (x = 0; x < h->mb_width; x++) + er->mb_index2xy[x + y * h->mb_width] = x + y * h->mb_stride; + + er->mb_index2xy[h->mb_height * h->mb_width] = (h->mb_height - 1) * + h->mb_stride + h->mb_width; + + FF_ALLOCZ_OR_GOTO(h->avctx, er->error_status_table, + mb_array_size * sizeof(uint8_t), fail); + + FF_ALLOC_OR_GOTO(h->avctx, er->mbintra_table, mb_array_size, fail); + memset(er->mbintra_table, 1, mb_array_size); + + FF_ALLOCZ_OR_GOTO(h->avctx, er->mbskip_table, mb_array_size + 2, fail); + + FF_ALLOC_OR_GOTO(h->avctx, er->er_temp_buffer, h->mb_height * h->mb_stride, + fail); + + FF_ALLOCZ_OR_GOTO(h->avctx, h->dc_val_base, yc_size * sizeof(int16_t), fail); + er->dc_val[0] = h->dc_val_base + h->mb_width * 2 + 2; + er->dc_val[1] = h->dc_val_base + y_size + h->mb_stride + 1; + er->dc_val[2] = er->dc_val[1] + c_size; + for (i = 0; i < yc_size; i++) + h->dc_val_base[i] = 1024; + } + + return 0; + +fail: + return -1; // free_tables will clean up for us +} + +static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, + int parse_extradata); + +int ff_h264_decode_extradata(H264Context *h, const uint8_t *buf, int size) +{ + AVCodecContext *avctx = h->avctx; + + if (!buf || size <= 0) + return -1; + + if (buf[0] == 1) { + int i, cnt, nalsize; + const unsigned char *p = buf; + + h->is_avc = 1; + + if (size < 7) { + av_log(avctx, AV_LOG_ERROR, "avcC too short\n"); + return -1; + } + /* sps and pps in the avcC always have length coded with 2 bytes, + * so put a fake nal_length_size = 2 while parsing them */ + h->nal_length_size = 2; + // Decode sps from avcC + cnt = *(p + 5) & 0x1f; // Number of sps + p += 6; + for (i = 0; i < cnt; i++) { + nalsize = AV_RB16(p) + 2; + if(nalsize > size - (p-buf)) + return -1; + if (decode_nal_units(h, p, nalsize, 1) < 0) { + av_log(avctx, AV_LOG_ERROR, + "Decoding sps %d from avcC failed\n", i); + return -1; + } + p += nalsize; + } + // Decode pps from avcC + cnt = *(p++); // Number of pps + for (i = 0; i < cnt; i++) { + nalsize = AV_RB16(p) + 2; + if(nalsize > size - (p-buf)) + return -1; + if (decode_nal_units(h, p, nalsize, 1) < 0) { + av_log(avctx, AV_LOG_ERROR, + "Decoding pps %d from avcC failed\n", i); + return -1; + } + p += nalsize; + } + // Now store right nal length size, that will be used to parse all other nals + h->nal_length_size = (buf[4] & 0x03) + 1; + } else { + h->is_avc = 0; + if (decode_nal_units(h, buf, size, 1) < 0) + return -1; + } + return size; +} + +av_cold int ff_h264_decode_init(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int i; + + h->avctx = avctx; + + h->width = h->avctx->width; + h->height = h->avctx->height; + + h->bit_depth_luma = 8; + h->chroma_format_idc = 1; + + h->avctx->bits_per_raw_sample = 8; + h->cur_chroma_format_idc = 1; + + ff_h264dsp_init(&h->h264dsp, 8, 1); + av_assert0(h->sps.bit_depth_chroma == 0); + ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma); + ff_h264qpel_init(&h->h264qpel, 8); + ff_h264_pred_init(&h->hpc, h->avctx->codec_id, 8, 1); + + h->dequant_coeff_pps = -1; + + if (CONFIG_ERROR_RESILIENCE) { + /* needed so that IDCT permutation is known early */ + ff_dsputil_init(&h->dsp, h->avctx); + } + ff_videodsp_init(&h->vdsp, 8); + + memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t)); + memset(h->pps.scaling_matrix8, 16, 2 * 64 * sizeof(uint8_t)); + + h->picture_structure = PICT_FRAME; + h->slice_context_count = 1; + h->workaround_bugs = avctx->workaround_bugs; + h->flags = avctx->flags; + + /* set defaults */ + // s->decode_mb = ff_h263_decode_mb; + if (!avctx->has_b_frames) + h->low_delay = 1; + + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + + ff_h264_decode_init_vlc(); + + h->pixel_shift = 0; + h->sps.bit_depth_luma = avctx->bits_per_raw_sample = 8; + + h->thread_context[0] = h; + h->outputed_poc = h->next_outputed_poc = INT_MIN; + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; + h->prev_poc_msb = 1 << 16; + h->prev_frame_num = -1; + h->x264_build = -1; + ff_h264_reset_sei(h); + if (avctx->codec_id == AV_CODEC_ID_H264) { + if (avctx->ticks_per_frame == 1) { + if(h->avctx->time_base.den < INT_MAX/2) { + h->avctx->time_base.den *= 2; + } else + h->avctx->time_base.num /= 2; + } + avctx->ticks_per_frame = 2; + } + + if (avctx->extradata_size > 0 && avctx->extradata && + ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size) < 0) { + ff_h264_free_context(h); + return -1; + } + + if (h->sps.bitstream_restriction_flag && + h->avctx->has_b_frames < h->sps.num_reorder_frames) { + h->avctx->has_b_frames = h->sps.num_reorder_frames; + h->low_delay = 0; + } + + ff_init_cabac_states(); + avctx->internal->allocate_progress = 1; + + return 0; +} + +#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size)))) +#undef REBASE_PICTURE +#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ + ((pic && pic >= old_ctx->DPB && \ + pic < old_ctx->DPB + MAX_PICTURE_COUNT) ? \ + &new_ctx->DPB[pic - old_ctx->DPB] : NULL) + +static void copy_picture_range(Picture **to, Picture **from, int count, + H264Context *new_base, + H264Context *old_base) +{ + int i; + + for (i = 0; i < count; i++) { + assert((IN_RANGE(from[i], old_base, sizeof(*old_base)) || + IN_RANGE(from[i], old_base->DPB, + sizeof(Picture) * MAX_PICTURE_COUNT) || + !from[i])); + to[i] = REBASE_PICTURE(from[i], new_base, old_base); + } +} + +static void copy_parameter_set(void **to, void **from, int count, int size) +{ + int i; + + for (i = 0; i < count; i++) { + if (to[i] && !from[i]) + av_freep(&to[i]); + else if (from[i] && !to[i]) + to[i] = av_malloc(size); + + if (from[i]) + memcpy(to[i], from[i], size); + } +} + +static int decode_init_thread_copy(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + + if (!avctx->internal->is_copy) + return 0; + memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); + memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); + + h->context_initialized = 0; + + return 0; +} + +#define copy_fields(to, from, start_field, end_field) \ + memcpy(&to->start_field, &from->start_field, \ + (char *)&to->end_field - (char *)&to->start_field) + +static int h264_slice_header_init(H264Context *, int); + +static int h264_set_parameter_from_sps(H264Context *h); + +static int decode_update_thread_context(AVCodecContext *dst, + const AVCodecContext *src) +{ + H264Context *h = dst->priv_data, *h1 = src->priv_data; + int inited = h->context_initialized, err = 0; + int context_reinitialized = 0; + int i, ret; + + if (dst == src) + return 0; + + if (inited && + (h->width != h1->width || + h->height != h1->height || + h->mb_width != h1->mb_width || + h->mb_height != h1->mb_height || + h->sps.bit_depth_luma != h1->sps.bit_depth_luma || + h->sps.chroma_format_idc != h1->sps.chroma_format_idc || + h->sps.colorspace != h1->sps.colorspace)) { + + /* set bits_per_raw_sample to the previous value. the check for changed + * bit depth in h264_set_parameter_from_sps() uses it and sets it to + * the current value */ + h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; + + av_freep(&h->bipred_scratchpad); + + h->width = h1->width; + h->height = h1->height; + h->mb_height = h1->mb_height; + h->mb_width = h1->mb_width; + h->mb_num = h1->mb_num; + h->mb_stride = h1->mb_stride; + h->b_stride = h1->b_stride; + // SPS/PPS + copy_parameter_set((void **)h->sps_buffers, (void **)h1->sps_buffers, + MAX_SPS_COUNT, sizeof(SPS)); + h->sps = h1->sps; + copy_parameter_set((void **)h->pps_buffers, (void **)h1->pps_buffers, + MAX_PPS_COUNT, sizeof(PPS)); + h->pps = h1->pps; + + if ((err = h264_slice_header_init(h, 1)) < 0) { + av_log(h->avctx, AV_LOG_ERROR, "h264_slice_header_init() failed"); + return err; + } + context_reinitialized = 1; + +#if 0 + h264_set_parameter_from_sps(h); + //Note we set context_reinitialized which will cause h264_set_parameter_from_sps to be reexecuted + h->cur_chroma_format_idc = h1->cur_chroma_format_idc; +#endif + } + /* update linesize on resize for h264. The h264 decoder doesn't + * necessarily call ff_MPV_frame_start in the new thread */ + h->linesize = h1->linesize; + h->uvlinesize = h1->uvlinesize; + + /* copy block_offset since frame_start may not be called */ + memcpy(h->block_offset, h1->block_offset, sizeof(h->block_offset)); + + if (!inited) { + for (i = 0; i < MAX_SPS_COUNT; i++) + av_freep(h->sps_buffers + i); + + for (i = 0; i < MAX_PPS_COUNT; i++) + av_freep(h->pps_buffers + i); + + memcpy(h, h1, offsetof(H264Context, intra_pcm_ptr)); + memcpy(&h->cabac, &h1->cabac, + sizeof(H264Context) - offsetof(H264Context, cabac)); + av_assert0((void*)&h->cabac == &h->mb_padding + 1); + + memset(h->sps_buffers, 0, sizeof(h->sps_buffers)); + memset(h->pps_buffers, 0, sizeof(h->pps_buffers)); + + memset(&h->er, 0, sizeof(h->er)); + memset(&h->me, 0, sizeof(h->me)); + h->avctx = dst; + h->DPB = NULL; + h->qscale_table_pool = NULL; + h->mb_type_pool = NULL; + h->ref_index_pool = NULL; + h->motion_val_pool = NULL; + + if (h1->context_initialized) { + h->context_initialized = 0; + + memset(&h->cur_pic, 0, sizeof(h->cur_pic)); + avcodec_get_frame_defaults(&h->cur_pic.f); + h->cur_pic.tf.f = &h->cur_pic.f; + + if (ff_h264_alloc_tables(h) < 0) { + av_log(dst, AV_LOG_ERROR, "Could not allocate memory for h264\n"); + return AVERROR(ENOMEM); + } + context_init(h); + } + + for (i = 0; i < 2; i++) { + h->rbsp_buffer[i] = NULL; + h->rbsp_buffer_size[i] = 0; + } + h->bipred_scratchpad = NULL; + h->edge_emu_buffer = NULL; + + h->thread_context[0] = h; + h->context_initialized = h1->context_initialized; + } + + h->avctx->coded_height = h1->avctx->coded_height; + h->avctx->coded_width = h1->avctx->coded_width; + h->avctx->width = h1->avctx->width; + h->avctx->height = h1->avctx->height; + h->coded_picture_number = h1->coded_picture_number; + h->first_field = h1->first_field; + h->picture_structure = h1->picture_structure; + h->qscale = h1->qscale; + h->droppable = h1->droppable; + h->data_partitioning = h1->data_partitioning; + h->low_delay = h1->low_delay; + + for (i = 0; h->DPB && i < MAX_PICTURE_COUNT; i++) { + h->DPB[i].period_since_free ++; + unref_picture(h, &h->DPB[i]); + if (h1->DPB[i].f.data[0] && + (ret = ref_picture(h, &h->DPB[i], &h1->DPB[i])) < 0) + return ret; + } + + h->cur_pic_ptr = REBASE_PICTURE(h1->cur_pic_ptr, h, h1); + unref_picture(h, &h->cur_pic); + if (h1->cur_pic.f.buf[0] && (ret = ref_picture(h, &h->cur_pic, &h1->cur_pic)) < 0) + return ret; + + h->workaround_bugs = h1->workaround_bugs; + h->low_delay = h1->low_delay; + h->droppable = h1->droppable; + + // extradata/NAL handling + h->is_avc = h1->is_avc; + + // SPS/PPS + copy_parameter_set((void **)h->sps_buffers, (void **)h1->sps_buffers, + MAX_SPS_COUNT, sizeof(SPS)); + h->sps = h1->sps; + copy_parameter_set((void **)h->pps_buffers, (void **)h1->pps_buffers, + MAX_PPS_COUNT, sizeof(PPS)); + h->pps = h1->pps; + + // Dequantization matrices + // FIXME these are big - can they be only copied when PPS changes? + copy_fields(h, h1, dequant4_buffer, dequant4_coeff); + + for (i = 0; i < 6; i++) + h->dequant4_coeff[i] = h->dequant4_buffer[0] + + (h1->dequant4_coeff[i] - h1->dequant4_buffer[0]); + + for (i = 0; i < 6; i++) + h->dequant8_coeff[i] = h->dequant8_buffer[0] + + (h1->dequant8_coeff[i] - h1->dequant8_buffer[0]); + + h->dequant_coeff_pps = h1->dequant_coeff_pps; + + // POC timing + copy_fields(h, h1, poc_lsb, redundant_pic_count); + + // reference lists + copy_fields(h, h1, short_ref, cabac_init_idc); + + copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1); + copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1); + copy_picture_range(h->delayed_pic, h1->delayed_pic, + MAX_DELAYED_PIC_COUNT + 2, h, h1); + + h->last_slice_type = h1->last_slice_type; + h->sync = h1->sync; + memcpy(h->last_ref_count, h1->last_ref_count, sizeof(h->last_ref_count)); + + if (context_reinitialized) + h264_set_parameter_from_sps(h); + + if (!h->cur_pic_ptr) + return 0; + + if (!h->droppable) { + err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); + h->prev_poc_msb = h->poc_msb; + h->prev_poc_lsb = h->poc_lsb; + } + h->prev_frame_num_offset = h->frame_num_offset; + h->prev_frame_num = h->frame_num; + h->outputed_poc = h->next_outputed_poc; + + return err; +} + +static int h264_frame_start(H264Context *h) +{ + Picture *pic; + int i, ret; + const int pixel_shift = h->pixel_shift; + int c[4] = { + 1<<(h->sps.bit_depth_luma-1), + 1<<(h->sps.bit_depth_chroma-1), + 1<<(h->sps.bit_depth_chroma-1), + -1 + }; + + if (!ff_thread_can_start_frame(h->avctx)) { + av_log(h->avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + + release_unused_pictures(h, 1); + h->cur_pic_ptr = NULL; + + i = find_unused_picture(h); + if (i < 0) { + av_log(h->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } + pic = &h->DPB[i]; + + pic->reference = h->droppable ? 0 : h->picture_structure; + pic->f.coded_picture_number = h->coded_picture_number++; + pic->field_picture = h->picture_structure != PICT_FRAME; + + /* + * Zero key_frame here; IDR markings per slice in frame or fields are ORed + * in later. + * See decode_nal_units(). + */ + pic->f.key_frame = 0; + pic->sync = 0; + pic->mmco_reset = 0; + + if ((ret = alloc_picture(h, pic)) < 0) + return ret; + if(!h->sync && !h->avctx->hwaccel && + !(h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)) + avpriv_color_frame(&pic->f, c); + + h->cur_pic_ptr = pic; + unref_picture(h, &h->cur_pic); + if ((ret = ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0) + return ret; + + if (CONFIG_ERROR_RESILIENCE) { + ff_er_frame_start(&h->er); + h->er.last_pic = + h->er.next_pic = NULL; + } + + assert(h->linesize && h->uvlinesize); + + for (i = 0; i < 16; i++) { + h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + } + for (i = 0; i < 16; i++) { + h->block_offset[16 + i] = + h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + 16 + i] = + h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 8 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + } + + /* Some macroblocks can be accessed before they're available in case + * of lost slices, MBAFF or threading. */ + memset(h->slice_table, -1, + (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table)); + + // s->decode = (h->flags & CODEC_FLAG_PSNR) || !s->encoding || + // h->cur_pic.reference /* || h->contains_intra */ || 1; + + /* We mark the current picture as non-reference after allocating it, so + * that if we break out due to an error it can be released automatically + * in the next ff_MPV_frame_start(). + */ + h->cur_pic_ptr->reference = 0; + + h->cur_pic_ptr->field_poc[0] = h->cur_pic_ptr->field_poc[1] = INT_MAX; + + h->next_output_pic = NULL; + + assert(h->cur_pic_ptr->long_ref == 0); + + return 0; +} + +/** + * Run setup operations that must be run after slice header decoding. + * This includes finding the next displayed frame. + * + * @param h h264 master context + * @param setup_finished enough NALs have been read that we can call + * ff_thread_finish_setup() + */ +static void decode_postinit(H264Context *h, int setup_finished) +{ + Picture *out = h->cur_pic_ptr; + Picture *cur = h->cur_pic_ptr; + int i, pics, out_of_order, out_idx; + + h->cur_pic_ptr->f.pict_type = h->pict_type; + + if (h->next_output_pic) + return; + + if (cur->field_poc[0] == INT_MAX || cur->field_poc[1] == INT_MAX) { + /* FIXME: if we have two PAFF fields in one packet, we can't start + * the next thread here. If we have one field per packet, we can. + * The check in decode_nal_units() is not good enough to find this + * yet, so we assume the worst for now. */ + // if (setup_finished) + // ff_thread_finish_setup(h->avctx); + return; + } + + cur->f.interlaced_frame = 0; + cur->f.repeat_pict = 0; + + /* Signal interlacing information externally. */ + /* Prioritize picture timing SEI information over used + * decoding process if it exists. */ + + if (h->sps.pic_struct_present_flag) { + switch (h->sei_pic_struct) { + case SEI_PIC_STRUCT_FRAME: + break; + case SEI_PIC_STRUCT_TOP_FIELD: + case SEI_PIC_STRUCT_BOTTOM_FIELD: + cur->f.interlaced_frame = 1; + break; + case SEI_PIC_STRUCT_TOP_BOTTOM: + case SEI_PIC_STRUCT_BOTTOM_TOP: + if (FIELD_OR_MBAFF_PICTURE(h)) + cur->f.interlaced_frame = 1; + else + // try to flag soft telecine progressive + cur->f.interlaced_frame = h->prev_interlaced_frame; + break; + case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + /* Signal the possibility of telecined film externally + * (pic_struct 5,6). From these hints, let the applications + * decide if they apply deinterlacing. */ + cur->f.repeat_pict = 1; + break; + case SEI_PIC_STRUCT_FRAME_DOUBLING: + cur->f.repeat_pict = 2; + break; + case SEI_PIC_STRUCT_FRAME_TRIPLING: + cur->f.repeat_pict = 4; + break; + } + + if ((h->sei_ct_type & 3) && + h->sei_pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP) + cur->f.interlaced_frame = (h->sei_ct_type & (1 << 1)) != 0; + } else { + /* Derive interlacing flag from used decoding process. */ + cur->f.interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); + } + h->prev_interlaced_frame = cur->f.interlaced_frame; + + if (cur->field_poc[0] != cur->field_poc[1]) { + /* Derive top_field_first from field pocs. */ + cur->f.top_field_first = cur->field_poc[0] < cur->field_poc[1]; + } else { + if (cur->f.interlaced_frame || h->sps.pic_struct_present_flag) { + /* Use picture timing SEI information. Even if it is a + * information of a past frame, better than nothing. */ + if (h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM || + h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP) + cur->f.top_field_first = 1; + else + cur->f.top_field_first = 0; + } else { + /* Most likely progressive */ + cur->f.top_field_first = 0; + } + } + + cur->mmco_reset = h->mmco_reset; + h->mmco_reset = 0; + // FIXME do something with unavailable reference frames + + /* Sort B-frames into display order */ + + if (h->sps.bitstream_restriction_flag && + h->avctx->has_b_frames < h->sps.num_reorder_frames) { + h->avctx->has_b_frames = h->sps.num_reorder_frames; + h->low_delay = 0; + } + + if (h->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT && + !h->sps.bitstream_restriction_flag) { + h->avctx->has_b_frames = MAX_DELAYED_PIC_COUNT - 1; + h->low_delay = 0; + } + + for (i = 0; 1; i++) { + if(i == MAX_DELAYED_PIC_COUNT || cur->poc < h->last_pocs[i]){ + if(i) + h->last_pocs[i-1] = cur->poc; + break; + } else if(i) { + h->last_pocs[i-1]= h->last_pocs[i]; + } + } + out_of_order = MAX_DELAYED_PIC_COUNT - i; + if( cur->f.pict_type == AV_PICTURE_TYPE_B + || (h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > INT_MIN && h->last_pocs[MAX_DELAYED_PIC_COUNT-1] - h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > 2)) + out_of_order = FFMAX(out_of_order, 1); + if (out_of_order == MAX_DELAYED_PIC_COUNT) { + av_log(h->avctx, AV_LOG_VERBOSE, "Invalid POC %d<%d\n", cur->poc, h->last_pocs[0]); + for (i = 1; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; + h->last_pocs[0] = cur->poc; + cur->mmco_reset = 1; + } else if(h->avctx->has_b_frames < out_of_order && !h->sps.bitstream_restriction_flag){ + av_log(h->avctx, AV_LOG_VERBOSE, "Increasing reorder buffer to %d\n", out_of_order); + h->avctx->has_b_frames = out_of_order; + h->low_delay = 0; + } + + pics = 0; + while (h->delayed_pic[pics]) + pics++; + + av_assert0(pics <= MAX_DELAYED_PIC_COUNT); + + h->delayed_pic[pics++] = cur; + if (cur->reference == 0) + cur->reference = DELAYED_PIC_REF; + + out = h->delayed_pic[0]; + out_idx = 0; + for (i = 1; h->delayed_pic[i] && + !h->delayed_pic[i]->f.key_frame && + !h->delayed_pic[i]->mmco_reset; + i++) + if (h->delayed_pic[i]->poc < out->poc) { + out = h->delayed_pic[i]; + out_idx = i; + } + if (h->avctx->has_b_frames == 0 && + (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset)) + h->next_outputed_poc = INT_MIN; + out_of_order = out->poc < h->next_outputed_poc; + + if (out_of_order || pics > h->avctx->has_b_frames) { + out->reference &= ~DELAYED_PIC_REF; + // for frame threading, the owner must be the second field's thread or + // else the first thread can release the picture and reuse it unsafely + for (i = out_idx; h->delayed_pic[i]; i++) + h->delayed_pic[i] = h->delayed_pic[i + 1]; + } + if (!out_of_order && pics > h->avctx->has_b_frames) { + h->next_output_pic = out; + if (out_idx == 0 && h->delayed_pic[0] && (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset)) { + h->next_outputed_poc = INT_MIN; + } else + h->next_outputed_poc = out->poc; + } else { + av_log(h->avctx, AV_LOG_DEBUG, "no picture %s\n", out_of_order ? "ooo" : ""); + } + + if (h->next_output_pic && h->next_output_pic->sync) { + h->sync |= 2; + } + + if (setup_finished) + ff_thread_finish_setup(h->avctx); +} + +static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, + uint8_t *src_cb, uint8_t *src_cr, + int linesize, int uvlinesize, + int simple) +{ + uint8_t *top_border; + int top_idx = 1; + const int pixel_shift = h->pixel_shift; + int chroma444 = CHROMA444; + int chroma422 = CHROMA422; + + src_y -= linesize; + src_cb -= uvlinesize; + src_cr -= uvlinesize; + + if (!simple && FRAME_MBAFF(h)) { + if (h->mb_y & 1) { + if (!MB_MBAFF(h)) { + top_border = h->top_borders[0][h->mb_x]; + AV_COPY128(top_border, src_y + 15 * linesize); + if (pixel_shift) + AV_COPY128(top_border + 16, src_y + 15 * linesize + 16); + if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (chroma444) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); + AV_COPY128(top_border + 48, src_cb + 15 * uvlinesize + 16); + AV_COPY128(top_border + 64, src_cr + 15 * uvlinesize); + AV_COPY128(top_border + 80, src_cr + 15 * uvlinesize + 16); + } else { + AV_COPY128(top_border + 16, src_cb + 15 * uvlinesize); + AV_COPY128(top_border + 32, src_cr + 15 * uvlinesize); + } + } else if (chroma422) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 15 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 15 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 15 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 15 * uvlinesize); + } + } else { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 7 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 7 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 7 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 7 * uvlinesize); + } + } + } + } + } else if (MB_MBAFF(h)) { + top_idx = 0; + } else + return; + } + + top_border = h->top_borders[top_idx][h->mb_x]; + /* There are two lines saved, the line above the top macroblock + * of a pair, and the line above the bottom macroblock. */ + AV_COPY128(top_border, src_y + 16 * linesize); + if (pixel_shift) + AV_COPY128(top_border + 16, src_y + 16 * linesize + 16); + + if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (chroma444) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 16 * linesize); + AV_COPY128(top_border + 48, src_cb + 16 * linesize + 16); + AV_COPY128(top_border + 64, src_cr + 16 * linesize); + AV_COPY128(top_border + 80, src_cr + 16 * linesize + 16); + } else { + AV_COPY128(top_border + 16, src_cb + 16 * linesize); + AV_COPY128(top_border + 32, src_cr + 16 * linesize); + } + } else if (chroma422) { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 16 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 16 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 16 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 16 * uvlinesize); + } + } else { + if (pixel_shift) { + AV_COPY128(top_border + 32, src_cb + 8 * uvlinesize); + AV_COPY128(top_border + 48, src_cr + 8 * uvlinesize); + } else { + AV_COPY64(top_border + 16, src_cb + 8 * uvlinesize); + AV_COPY64(top_border + 24, src_cr + 8 * uvlinesize); + } + } + } +} + +static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y, + uint8_t *src_cb, uint8_t *src_cr, + int linesize, int uvlinesize, + int xchg, int chroma444, + int simple, int pixel_shift) +{ + int deblock_topleft; + int deblock_top; + int top_idx = 1; + uint8_t *top_border_m1; + uint8_t *top_border; + + if (!simple && FRAME_MBAFF(h)) { + if (h->mb_y & 1) { + if (!MB_MBAFF(h)) + return; + } else { + top_idx = MB_MBAFF(h) ? 0 : 1; + } + } + + if (h->deblocking_filter == 2) { + deblock_topleft = h->slice_table[h->mb_xy - 1 - h->mb_stride] == h->slice_num; + deblock_top = h->top_type; + } else { + deblock_topleft = (h->mb_x > 0); + deblock_top = (h->mb_y > !!MB_FIELD(h)); + } + + src_y -= linesize + 1 + pixel_shift; + src_cb -= uvlinesize + 1 + pixel_shift; + src_cr -= uvlinesize + 1 + pixel_shift; + + top_border_m1 = h->top_borders[top_idx][h->mb_x - 1]; + top_border = h->top_borders[top_idx][h->mb_x]; + +#define XCHG(a, b, xchg) \ + if (pixel_shift) { \ + if (xchg) { \ + AV_SWAP64(b + 0, a + 0); \ + AV_SWAP64(b + 8, a + 8); \ + } else { \ + AV_COPY128(b, a); \ + } \ + } else if (xchg) \ + AV_SWAP64(b, a); \ + else \ + AV_COPY64(b, a); + + if (deblock_top) { + if (deblock_topleft) { + XCHG(top_border_m1 + (8 << pixel_shift), + src_y - (7 << pixel_shift), 1); + } + XCHG(top_border + (0 << pixel_shift), src_y + (1 << pixel_shift), xchg); + XCHG(top_border + (8 << pixel_shift), src_y + (9 << pixel_shift), 1); + if (h->mb_x + 1 < h->mb_width) { + XCHG(h->top_borders[top_idx][h->mb_x + 1], + src_y + (17 << pixel_shift), 1); + } + } + if (simple || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (chroma444) { + if (deblock_topleft) { + XCHG(top_border_m1 + (24 << pixel_shift), src_cb - (7 << pixel_shift), 1); + XCHG(top_border_m1 + (40 << pixel_shift), src_cr - (7 << pixel_shift), 1); + } + XCHG(top_border + (16 << pixel_shift), src_cb + (1 << pixel_shift), xchg); + XCHG(top_border + (24 << pixel_shift), src_cb + (9 << pixel_shift), 1); + XCHG(top_border + (32 << pixel_shift), src_cr + (1 << pixel_shift), xchg); + XCHG(top_border + (40 << pixel_shift), src_cr + (9 << pixel_shift), 1); + if (h->mb_x + 1 < h->mb_width) { + XCHG(h->top_borders[top_idx][h->mb_x + 1] + (16 << pixel_shift), src_cb + (17 << pixel_shift), 1); + XCHG(h->top_borders[top_idx][h->mb_x + 1] + (32 << pixel_shift), src_cr + (17 << pixel_shift), 1); + } + } else { + if (deblock_top) { + if (deblock_topleft) { + XCHG(top_border_m1 + (16 << pixel_shift), src_cb - (7 << pixel_shift), 1); + XCHG(top_border_m1 + (24 << pixel_shift), src_cr - (7 << pixel_shift), 1); + } + XCHG(top_border + (16 << pixel_shift), src_cb + 1 + pixel_shift, 1); + XCHG(top_border + (24 << pixel_shift), src_cr + 1 + pixel_shift, 1); + } + } + } +} + +static av_always_inline int dctcoef_get(int16_t *mb, int high_bit_depth, + int index) +{ + if (high_bit_depth) { + return AV_RN32A(((int32_t *)mb) + index); + } else + return AV_RN16A(mb + index); +} + +static av_always_inline void dctcoef_set(int16_t *mb, int high_bit_depth, + int index, int value) +{ + if (high_bit_depth) { + AV_WN32A(((int32_t *)mb) + index, value); + } else + AV_WN16A(mb + index, value); +} + +static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, + int mb_type, int is_h264, + int simple, + int transform_bypass, + int pixel_shift, + int *block_offset, + int linesize, + uint8_t *dest_y, int p) +{ + void (*idct_add)(uint8_t *dst, int16_t *block, int stride); + void (*idct_dc_add)(uint8_t *dst, int16_t *block, int stride); + int i; + int qscale = p == 0 ? h->qscale : h->chroma_qp[p - 1]; + block_offset += 16 * p; + if (IS_INTRA4x4(mb_type)) { + if (IS_8x8DCT(mb_type)) { + if (transform_bypass) { + idct_dc_add = + idct_add = h->h264dsp.h264_add_pixels8_clear; + } else { + idct_dc_add = h->h264dsp.h264_idct8_dc_add; + idct_add = h->h264dsp.h264_idct8_add; + } + for (i = 0; i < 16; i += 4) { + uint8_t *const ptr = dest_y + block_offset[i]; + const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; + if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { + h->hpc.pred8x8l_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else { + const int nnz = h->non_zero_count_cache[scan8[i + p * 16]]; + h->hpc.pred8x8l[dir](ptr, (h->topleft_samples_available << i) & 0x8000, + (h->topright_samples_available << i) & 0x4000, linesize); + if (nnz) { + if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) + idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + else + idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } + } + } + } else { + if (transform_bypass) { + idct_dc_add = + idct_add = h->h264dsp.h264_add_pixels4_clear; + } else { + idct_dc_add = h->h264dsp.h264_idct_dc_add; + idct_add = h->h264dsp.h264_idct_add; + } + for (i = 0; i < 16; i++) { + uint8_t *const ptr = dest_y + block_offset[i]; + const int dir = h->intra4x4_pred_mode_cache[scan8[i]]; + + if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) { + h->hpc.pred4x4_add[dir](ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else { + uint8_t *topright; + int nnz, tr; + uint64_t tr_high; + if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { + const int topright_avail = (h->topright_samples_available << i) & 0x8000; + av_assert2(h->mb_y || linesize <= block_offset[i]); + if (!topright_avail) { + if (pixel_shift) { + tr_high = ((uint16_t *)ptr)[3 - linesize / 2] * 0x0001000100010001ULL; + topright = (uint8_t *)&tr_high; + } else { + tr = ptr[3 - linesize] * 0x01010101u; + topright = (uint8_t *)&tr; + } + } else + topright = ptr + (4 << pixel_shift) - linesize; + } else + topright = NULL; + + h->hpc.pred4x4[dir](ptr, topright, linesize); + nnz = h->non_zero_count_cache[scan8[i + p * 16]]; + if (nnz) { + if (is_h264) { + if (nnz == 1 && dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) + idct_dc_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + else + idct_add(ptr, h->mb + (i * 16 + p * 256 << pixel_shift), linesize); + } else if (CONFIG_SVQ3_DECODER) + ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, qscale, 0); + } + } + } + } + } else { + h->hpc.pred16x16[h->intra16x16_pred_mode](dest_y, linesize); + if (is_h264) { + if (h->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) { + if (!transform_bypass) + h->h264dsp.h264_luma_dc_dequant_idct(h->mb + (p * 256 << pixel_shift), + h->mb_luma_dc[p], + h->dequant4_coeff[p][qscale][0]); + else { + static const uint8_t dc_mapping[16] = { + 0 * 16, 1 * 16, 4 * 16, 5 * 16, + 2 * 16, 3 * 16, 6 * 16, 7 * 16, + 8 * 16, 9 * 16, 12 * 16, 13 * 16, + 10 * 16, 11 * 16, 14 * 16, 15 * 16 }; + for (i = 0; i < 16; i++) + dctcoef_set(h->mb + (p * 256 << pixel_shift), + pixel_shift, dc_mapping[i], + dctcoef_get(h->mb_luma_dc[p], + pixel_shift, i)); + } + } + } else if (CONFIG_SVQ3_DECODER) + ff_svq3_luma_dc_dequant_idct_c(h->mb + p * 256, + h->mb_luma_dc[p], qscale); + } +} + +static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, + int is_h264, int simple, + int transform_bypass, + int pixel_shift, + int *block_offset, + int linesize, + uint8_t *dest_y, int p) +{ + void (*idct_add)(uint8_t *dst, int16_t *block, int stride); + int i; + block_offset += 16 * p; + if (!IS_INTRA4x4(mb_type)) { + if (is_h264) { + if (IS_INTRA16x16(mb_type)) { + if (transform_bypass) { + if (h->sps.profile_idc == 244 && + (h->intra16x16_pred_mode == VERT_PRED8x8 || + h->intra16x16_pred_mode == HOR_PRED8x8)) { + h->hpc.pred16x16_add[h->intra16x16_pred_mode](dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize); + } else { + for (i = 0; i < 16; i++) + if (h->non_zero_count_cache[scan8[i + p * 16]] || + dctcoef_get(h->mb, pixel_shift, i * 16 + p * 256)) + h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i], + h->mb + (i * 16 + p * 256 << pixel_shift), + linesize); + } + } else { + h->h264dsp.h264_idct_add16intra(dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize, + h->non_zero_count_cache + p * 5 * 8); + } + } else if (h->cbp & 15) { + if (transform_bypass) { + const int di = IS_8x8DCT(mb_type) ? 4 : 1; + idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear + : h->h264dsp.h264_add_pixels4_clear; + for (i = 0; i < 16; i += di) + if (h->non_zero_count_cache[scan8[i + p * 16]]) + idct_add(dest_y + block_offset[i], + h->mb + (i * 16 + p * 256 << pixel_shift), + linesize); + } else { + if (IS_8x8DCT(mb_type)) + h->h264dsp.h264_idct8_add4(dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize, + h->non_zero_count_cache + p * 5 * 8); + else + h->h264dsp.h264_idct_add16(dest_y, block_offset, + h->mb + (p * 256 << pixel_shift), + linesize, + h->non_zero_count_cache + p * 5 * 8); + } + } + } else if (CONFIG_SVQ3_DECODER) { + for (i = 0; i < 16; i++) + if (h->non_zero_count_cache[scan8[i + p * 16]] || h->mb[i * 16 + p * 256]) { + // FIXME benchmark weird rule, & below + uint8_t *const ptr = dest_y + block_offset[i]; + ff_svq3_add_idct_c(ptr, h->mb + i * 16 + p * 256, linesize, + h->qscale, IS_INTRA(mb_type) ? 1 : 0); + } + } + } +} + +#define BITS 8 +#define SIMPLE 1 +#include "h264_mb_template.c" + +#undef BITS +#define BITS 16 +#include "h264_mb_template.c" + +#undef SIMPLE +#define SIMPLE 0 +#include "h264_mb_template.c" + +void ff_h264_hl_decode_mb(H264Context *h) +{ + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + int is_complex = CONFIG_SMALL || h->is_complex || IS_INTRA_PCM(mb_type) || h->qscale == 0; + + if (CHROMA444) { + if (is_complex || h->pixel_shift) + hl_decode_mb_444_complex(h); + else + hl_decode_mb_444_simple_8(h); + } else if (is_complex) { + hl_decode_mb_complex(h); + } else if (h->pixel_shift) { + hl_decode_mb_simple_16(h); + } else + hl_decode_mb_simple_8(h); +} + +static int pred_weight_table(H264Context *h) +{ + int list, i; + int luma_def, chroma_def; + + h->use_weight = 0; + h->use_weight_chroma = 0; + h->luma_log2_weight_denom = get_ue_golomb(&h->gb); + if (h->sps.chroma_format_idc) + h->chroma_log2_weight_denom = get_ue_golomb(&h->gb); + luma_def = 1 << h->luma_log2_weight_denom; + chroma_def = 1 << h->chroma_log2_weight_denom; + + for (list = 0; list < 2; list++) { + h->luma_weight_flag[list] = 0; + h->chroma_weight_flag[list] = 0; + for (i = 0; i < h->ref_count[list]; i++) { + int luma_weight_flag, chroma_weight_flag; + + luma_weight_flag = get_bits1(&h->gb); + if (luma_weight_flag) { + h->luma_weight[i][list][0] = get_se_golomb(&h->gb); + h->luma_weight[i][list][1] = get_se_golomb(&h->gb); + if (h->luma_weight[i][list][0] != luma_def || + h->luma_weight[i][list][1] != 0) { + h->use_weight = 1; + h->luma_weight_flag[list] = 1; + } + } else { + h->luma_weight[i][list][0] = luma_def; + h->luma_weight[i][list][1] = 0; + } + + if (h->sps.chroma_format_idc) { + chroma_weight_flag = get_bits1(&h->gb); + if (chroma_weight_flag) { + int j; + for (j = 0; j < 2; j++) { + h->chroma_weight[i][list][j][0] = get_se_golomb(&h->gb); + h->chroma_weight[i][list][j][1] = get_se_golomb(&h->gb); + if (h->chroma_weight[i][list][j][0] != chroma_def || + h->chroma_weight[i][list][j][1] != 0) { + h->use_weight_chroma = 1; + h->chroma_weight_flag[list] = 1; + } + } + } else { + int j; + for (j = 0; j < 2; j++) { + h->chroma_weight[i][list][j][0] = chroma_def; + h->chroma_weight[i][list][j][1] = 0; + } + } + } + } + if (h->slice_type_nos != AV_PICTURE_TYPE_B) + break; + } + h->use_weight = h->use_weight || h->use_weight_chroma; + return 0; +} + +/** + * Initialize implicit_weight table. + * @param field 0/1 initialize the weight for interlaced MBAFF + * -1 initializes the rest + */ +static void implicit_weight_table(H264Context *h, int field) +{ + int ref0, ref1, i, cur_poc, ref_start, ref_count0, ref_count1; + + for (i = 0; i < 2; i++) { + h->luma_weight_flag[i] = 0; + h->chroma_weight_flag[i] = 0; + } + + if (field < 0) { + if (h->picture_structure == PICT_FRAME) { + cur_poc = h->cur_pic_ptr->poc; + } else { + cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure - 1]; + } + if (h->ref_count[0] == 1 && h->ref_count[1] == 1 && !FRAME_MBAFF(h) && + h->ref_list[0][0].poc + h->ref_list[1][0].poc == 2 * cur_poc) { + h->use_weight = 0; + h->use_weight_chroma = 0; + return; + } + ref_start = 0; + ref_count0 = h->ref_count[0]; + ref_count1 = h->ref_count[1]; + } else { + cur_poc = h->cur_pic_ptr->field_poc[field]; + ref_start = 16; + ref_count0 = 16 + 2 * h->ref_count[0]; + ref_count1 = 16 + 2 * h->ref_count[1]; + } + + h->use_weight = 2; + h->use_weight_chroma = 2; + h->luma_log2_weight_denom = 5; + h->chroma_log2_weight_denom = 5; + + for (ref0 = ref_start; ref0 < ref_count0; ref0++) { + int poc0 = h->ref_list[0][ref0].poc; + for (ref1 = ref_start; ref1 < ref_count1; ref1++) { + int w = 32; + if (!h->ref_list[0][ref0].long_ref && !h->ref_list[1][ref1].long_ref) { + int poc1 = h->ref_list[1][ref1].poc; + int td = av_clip(poc1 - poc0, -128, 127); + if (td) { + int tb = av_clip(cur_poc - poc0, -128, 127); + int tx = (16384 + (FFABS(td) >> 1)) / td; + int dist_scale_factor = (tb * tx + 32) >> 8; + if (dist_scale_factor >= -64 && dist_scale_factor <= 128) + w = 64 - dist_scale_factor; + } + } + if (field < 0) { + h->implicit_weight[ref0][ref1][0] = + h->implicit_weight[ref0][ref1][1] = w; + } else { + h->implicit_weight[ref0][ref1][field] = w; + } + } + } +} + +/** + * instantaneous decoder refresh. + */ +static void idr(H264Context *h) +{ + int i; + ff_h264_remove_all_refs(h); + h->prev_frame_num = 0; + h->prev_frame_num_offset = 0; + h->prev_poc_msb = 1<<16; + h->prev_poc_lsb = 0; + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + h->last_pocs[i] = INT_MIN; +} + +/* forget old pics after a seek */ +static void flush_change(H264Context *h) +{ + int i, j; + + h->outputed_poc = h->next_outputed_poc = INT_MIN; + h->prev_interlaced_frame = 1; + idr(h); + + h->prev_frame_num = -1; + if (h->cur_pic_ptr) { + h->cur_pic_ptr->reference = 0; + for (j=i=0; h->delayed_pic[i]; i++) + if (h->delayed_pic[i] != h->cur_pic_ptr) + h->delayed_pic[j++] = h->delayed_pic[i]; + h->delayed_pic[j] = NULL; + } + h->first_field = 0; + memset(h->ref_list[0], 0, sizeof(h->ref_list[0])); + memset(h->ref_list[1], 0, sizeof(h->ref_list[1])); + memset(h->default_ref_list[0], 0, sizeof(h->default_ref_list[0])); + memset(h->default_ref_list[1], 0, sizeof(h->default_ref_list[1])); + ff_h264_reset_sei(h); + h->recovery_frame= -1; + h->sync= 0; + h->list_count = 0; + h->current_slice = 0; +} + +/* forget old pics after a seek */ +static void flush_dpb(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int i; + + for (i = 0; i <= MAX_DELAYED_PIC_COUNT; i++) { + if (h->delayed_pic[i]) + h->delayed_pic[i]->reference = 0; + h->delayed_pic[i] = NULL; + } + + flush_change(h); + + if (h->DPB) + for (i = 0; i < MAX_PICTURE_COUNT; i++) + unref_picture(h, &h->DPB[i]); + h->cur_pic_ptr = NULL; + unref_picture(h, &h->cur_pic); + + h->mb_x = h->mb_y = 0; + + h->parse_context.state = -1; + h->parse_context.frame_start_found = 0; + h->parse_context.overread = 0; + h->parse_context.overread_index = 0; + h->parse_context.index = 0; + h->parse_context.last_index = 0; +} + +static int init_poc(H264Context *h) +{ + const int max_frame_num = 1 << h->sps.log2_max_frame_num; + int field_poc[2]; + Picture *cur = h->cur_pic_ptr; + + h->frame_num_offset = h->prev_frame_num_offset; + if (h->frame_num < h->prev_frame_num) + h->frame_num_offset += max_frame_num; + + if (h->sps.poc_type == 0) { + const int max_poc_lsb = 1 << h->sps.log2_max_poc_lsb; + + if (h->poc_lsb < h->prev_poc_lsb && h->prev_poc_lsb - h->poc_lsb >= max_poc_lsb / 2) + h->poc_msb = h->prev_poc_msb + max_poc_lsb; + else if (h->poc_lsb > h->prev_poc_lsb && h->prev_poc_lsb - h->poc_lsb < -max_poc_lsb / 2) + h->poc_msb = h->prev_poc_msb - max_poc_lsb; + else + h->poc_msb = h->prev_poc_msb; + field_poc[0] = + field_poc[1] = h->poc_msb + h->poc_lsb; + if (h->picture_structure == PICT_FRAME) + field_poc[1] += h->delta_poc_bottom; + } else if (h->sps.poc_type == 1) { + int abs_frame_num, expected_delta_per_poc_cycle, expectedpoc; + int i; + + if (h->sps.poc_cycle_length != 0) + abs_frame_num = h->frame_num_offset + h->frame_num; + else + abs_frame_num = 0; + + if (h->nal_ref_idc == 0 && abs_frame_num > 0) + abs_frame_num--; + + expected_delta_per_poc_cycle = 0; + for (i = 0; i < h->sps.poc_cycle_length; i++) + // FIXME integrate during sps parse + expected_delta_per_poc_cycle += h->sps.offset_for_ref_frame[i]; + + if (abs_frame_num > 0) { + int poc_cycle_cnt = (abs_frame_num - 1) / h->sps.poc_cycle_length; + int frame_num_in_poc_cycle = (abs_frame_num - 1) % h->sps.poc_cycle_length; + + expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle; + for (i = 0; i <= frame_num_in_poc_cycle; i++) + expectedpoc = expectedpoc + h->sps.offset_for_ref_frame[i]; + } else + expectedpoc = 0; + + if (h->nal_ref_idc == 0) + expectedpoc = expectedpoc + h->sps.offset_for_non_ref_pic; + + field_poc[0] = expectedpoc + h->delta_poc[0]; + field_poc[1] = field_poc[0] + h->sps.offset_for_top_to_bottom_field; + + if (h->picture_structure == PICT_FRAME) + field_poc[1] += h->delta_poc[1]; + } else { + int poc = 2 * (h->frame_num_offset + h->frame_num); + + if (!h->nal_ref_idc) + poc--; + + field_poc[0] = poc; + field_poc[1] = poc; + } + + if (h->picture_structure != PICT_BOTTOM_FIELD) + h->cur_pic_ptr->field_poc[0] = field_poc[0]; + if (h->picture_structure != PICT_TOP_FIELD) + h->cur_pic_ptr->field_poc[1] = field_poc[1]; + cur->poc = FFMIN(cur->field_poc[0], cur->field_poc[1]); + + return 0; +} + +/** + * initialize scan tables + */ +static void init_scan_tables(H264Context *h) +{ + int i; + for (i = 0; i < 16; i++) { +#define T(x) (x >> 2) | ((x << 2) & 0xF) + h->zigzag_scan[i] = T(zigzag_scan[i]); + h->field_scan[i] = T(field_scan[i]); +#undef T + } + for (i = 0; i < 64; i++) { +#define T(x) (x >> 3) | ((x & 7) << 3) + h->zigzag_scan8x8[i] = T(ff_zigzag_direct[i]); + h->zigzag_scan8x8_cavlc[i] = T(zigzag_scan8x8_cavlc[i]); + h->field_scan8x8[i] = T(field_scan8x8[i]); + h->field_scan8x8_cavlc[i] = T(field_scan8x8_cavlc[i]); +#undef T + } + if (h->sps.transform_bypass) { // FIXME same ugly + memcpy(h->zigzag_scan_q0 , zigzag_scan , sizeof(h->zigzag_scan_q0 )); + memcpy(h->zigzag_scan8x8_q0 , ff_zigzag_direct , sizeof(h->zigzag_scan8x8_q0 )); + memcpy(h->zigzag_scan8x8_cavlc_q0 , zigzag_scan8x8_cavlc , sizeof(h->zigzag_scan8x8_cavlc_q0)); + memcpy(h->field_scan_q0 , field_scan , sizeof(h->field_scan_q0 )); + memcpy(h->field_scan8x8_q0 , field_scan8x8 , sizeof(h->field_scan8x8_q0 )); + memcpy(h->field_scan8x8_cavlc_q0 , field_scan8x8_cavlc , sizeof(h->field_scan8x8_cavlc_q0 )); + } else { + memcpy(h->zigzag_scan_q0 , h->zigzag_scan , sizeof(h->zigzag_scan_q0 )); + memcpy(h->zigzag_scan8x8_q0 , h->zigzag_scan8x8 , sizeof(h->zigzag_scan8x8_q0 )); + memcpy(h->zigzag_scan8x8_cavlc_q0 , h->zigzag_scan8x8_cavlc , sizeof(h->zigzag_scan8x8_cavlc_q0)); + memcpy(h->field_scan_q0 , h->field_scan , sizeof(h->field_scan_q0 )); + memcpy(h->field_scan8x8_q0 , h->field_scan8x8 , sizeof(h->field_scan8x8_q0 )); + memcpy(h->field_scan8x8_cavlc_q0 , h->field_scan8x8_cavlc , sizeof(h->field_scan8x8_cavlc_q0 )); + } +} + +static int field_end(H264Context *h, int in_setup) +{ + AVCodecContext *const avctx = h->avctx; + int err = 0; + h->mb_y = 0; + + if (!in_setup && !h->droppable) + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + + if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_h264_set_reference_frames(h); + + if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) { + if (!h->droppable) { + err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index); + h->prev_poc_msb = h->poc_msb; + h->prev_poc_lsb = h->poc_lsb; + } + h->prev_frame_num_offset = h->frame_num_offset; + h->prev_frame_num = h->frame_num; + h->outputed_poc = h->next_outputed_poc; + } + + if (avctx->hwaccel) { + if (avctx->hwaccel->end_frame(avctx) < 0) + av_log(avctx, AV_LOG_ERROR, + "hardware accelerator failed to decode picture\n"); + } + + if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_h264_picture_complete(h); + + /* + * FIXME: Error handling code does not seem to support interlaced + * when slices span multiple rows + * The ff_er_add_slice calls don't work right for bottom + * fields; they cause massive erroneous error concealing + * Error marking covers both fields (top and bottom). + * This causes a mismatched s->error_count + * and a bad error table. Further, the error count goes to + * INT_MAX when called for bottom field, because mb_y is + * past end by one (callers fault) and resync_mb_y != 0 + * causes problems for the first MB line, too. + */ + if (CONFIG_ERROR_RESILIENCE && + !FIELD_PICTURE(h) && h->current_slice && !h->sps.new) { + h->er.cur_pic = h->cur_pic_ptr; + ff_er_frame_end(&h->er); + } + emms_c(); + + h->current_slice = 0; + + return err; +} + +/** + * Replicate H264 "master" context to thread contexts. + */ +static int clone_slice(H264Context *dst, H264Context *src) +{ + memcpy(dst->block_offset, src->block_offset, sizeof(dst->block_offset)); + dst->cur_pic_ptr = src->cur_pic_ptr; + dst->cur_pic = src->cur_pic; + dst->linesize = src->linesize; + dst->uvlinesize = src->uvlinesize; + dst->first_field = src->first_field; + + dst->prev_poc_msb = src->prev_poc_msb; + dst->prev_poc_lsb = src->prev_poc_lsb; + dst->prev_frame_num_offset = src->prev_frame_num_offset; + dst->prev_frame_num = src->prev_frame_num; + dst->short_ref_count = src->short_ref_count; + + memcpy(dst->short_ref, src->short_ref, sizeof(dst->short_ref)); + memcpy(dst->long_ref, src->long_ref, sizeof(dst->long_ref)); + memcpy(dst->default_ref_list, src->default_ref_list, sizeof(dst->default_ref_list)); + + memcpy(dst->dequant4_coeff, src->dequant4_coeff, sizeof(src->dequant4_coeff)); + memcpy(dst->dequant8_coeff, src->dequant8_coeff, sizeof(src->dequant8_coeff)); + + return 0; +} + +/** + * Compute profile from profile_idc and constraint_set?_flags. + * + * @param sps SPS + * + * @return profile as defined by FF_PROFILE_H264_* + */ +int ff_h264_get_profile(SPS *sps) +{ + int profile = sps->profile_idc; + + switch (sps->profile_idc) { + case FF_PROFILE_H264_BASELINE: + // constraint_set1_flag set to 1 + profile |= (sps->constraint_set_flags & 1 << 1) ? FF_PROFILE_H264_CONSTRAINED : 0; + break; + case FF_PROFILE_H264_HIGH_10: + case FF_PROFILE_H264_HIGH_422: + case FF_PROFILE_H264_HIGH_444_PREDICTIVE: + // constraint_set3_flag set to 1 + profile |= (sps->constraint_set_flags & 1 << 3) ? FF_PROFILE_H264_INTRA : 0; + break; + } + + return profile; +} + +static int h264_set_parameter_from_sps(H264Context *h) +{ + if (h->flags & CODEC_FLAG_LOW_DELAY || + (h->sps.bitstream_restriction_flag && + !h->sps.num_reorder_frames)) { + if (h->avctx->has_b_frames > 1 || h->delayed_pic[0]) + av_log(h->avctx, AV_LOG_WARNING, "Delayed frames seen. " + "Reenabling low delay requires a codec flush.\n"); + else + h->low_delay = 1; + } + + if (h->avctx->has_b_frames < 2) + h->avctx->has_b_frames = !h->low_delay; + + if (h->sps.bit_depth_luma != h->sps.bit_depth_chroma) { + avpriv_request_sample(h->avctx, + "Different chroma and luma bit depth"); + return AVERROR_PATCHWELCOME; + } + + if (h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || + h->cur_chroma_format_idc != h->sps.chroma_format_idc) { + if (h->avctx->codec && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU && + (h->sps.bit_depth_luma != 8 || h->sps.chroma_format_idc > 1)) { + av_log(h->avctx, AV_LOG_ERROR, + "VDPAU decoding does not support video colorspace.\n"); + return AVERROR_INVALIDDATA; + } + if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 14 && + h->sps.bit_depth_luma != 11 && h->sps.bit_depth_luma != 13) { + h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; + h->cur_chroma_format_idc = h->sps.chroma_format_idc; + h->pixel_shift = h->sps.bit_depth_luma > 8; + + ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, + h->sps.chroma_format_idc); + ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma); + ff_h264qpel_init(&h->h264qpel, h->sps.bit_depth_luma); + ff_h264_pred_init(&h->hpc, h->avctx->codec_id, h->sps.bit_depth_luma, + h->sps.chroma_format_idc); + if (CONFIG_ERROR_RESILIENCE) { + ff_dsputil_init(&h->dsp, h->avctx); + } + ff_videodsp_init(&h->vdsp, h->sps.bit_depth_luma); + } else { + av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", + h->sps.bit_depth_luma); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + +static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) +{ + switch (h->sps.bit_depth_luma) { + case 9: + if (CHROMA444) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP9; + } else + return AV_PIX_FMT_YUV444P9; + } else if (CHROMA422) + return AV_PIX_FMT_YUV422P9; + else + return AV_PIX_FMT_YUV420P9; + break; + case 10: + if (CHROMA444) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP10; + } else + return AV_PIX_FMT_YUV444P10; + } else if (CHROMA422) + return AV_PIX_FMT_YUV422P10; + else + return AV_PIX_FMT_YUV420P10; + break; + case 12: + if (CHROMA444) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP12; + } else + return AV_PIX_FMT_YUV444P12; + } else if (CHROMA422) + return AV_PIX_FMT_YUV422P12; + else + return AV_PIX_FMT_YUV420P12; + break; + case 14: + if (CHROMA444) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + return AV_PIX_FMT_GBRP14; + } else + return AV_PIX_FMT_YUV444P14; + } else if (CHROMA422) + return AV_PIX_FMT_YUV422P14; + else + return AV_PIX_FMT_YUV420P14; + break; + case 8: + if (CHROMA444) { + if (h->avctx->colorspace == AVCOL_SPC_RGB) { + av_log(h->avctx, AV_LOG_DEBUG, "Detected GBR colorspace.\n"); + return AV_PIX_FMT_GBR24P; + } else if (h->avctx->colorspace == AVCOL_SPC_YCGCO) { + av_log(h->avctx, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); + } + return h->avctx->color_range == AVCOL_RANGE_JPEG ? AV_PIX_FMT_YUVJ444P + : AV_PIX_FMT_YUV444P; + } else if (CHROMA422) { + return h->avctx->color_range == AVCOL_RANGE_JPEG ? AV_PIX_FMT_YUVJ422P + : AV_PIX_FMT_YUV422P; + } else { + int i; + const enum AVPixelFormat * fmt = h->avctx->codec->pix_fmts ? + h->avctx->codec->pix_fmts : + h->avctx->color_range == AVCOL_RANGE_JPEG ? + h264_hwaccel_pixfmt_list_jpeg_420 : + h264_hwaccel_pixfmt_list_420; + + for (i=0; fmt[i] != AV_PIX_FMT_NONE; i++) + if (fmt[i] == h->avctx->pix_fmt && !force_callback) + return fmt[i]; + return h->avctx->get_format(h->avctx, fmt); + } + break; + default: + av_log(h->avctx, AV_LOG_ERROR, + "Unsupported bit depth: %d\n", h->sps.bit_depth_luma); + return AVERROR_INVALIDDATA; + } +} + +static int h264_slice_header_init(H264Context *h, int reinit) +{ + int nb_slices = (HAVE_THREADS && + h->avctx->active_thread_type & FF_THREAD_SLICE) ? + h->avctx->thread_count : 1; + int i; + + if( FFALIGN(h->avctx->width , 16 ) == h->width + && FFALIGN(h->avctx->height, 16*(2 - h->sps.frame_mbs_only_flag)) == h->height + && !h->sps.crop_right && !h->sps.crop_bottom + && (h->avctx->width != h->width || h->avctx->height && h->height) + ) { + av_log(h->avctx, AV_LOG_DEBUG, "Using externally provided dimensions\n"); + h->avctx->coded_width = h->width; + h->avctx->coded_height = h->height; + } else{ + avcodec_set_dimensions(h->avctx, h->width, h->height); + h->avctx->width -= (2>>CHROMA444)*FFMIN(h->sps.crop_right, (8<avctx->height -= (1<chroma_y_shift)*FFMIN(h->sps.crop_bottom, (16>>h->chroma_y_shift)-1) * (2 - h->sps.frame_mbs_only_flag); + } + + h->avctx->sample_aspect_ratio = h->sps.sar; + av_assert0(h->avctx->sample_aspect_ratio.den); + av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt, + &h->chroma_x_shift, &h->chroma_y_shift); + + if (h->sps.timing_info_present_flag) { + int64_t den = h->sps.time_scale; + if (h->x264_build < 44U) + den *= 2; + av_reduce(&h->avctx->time_base.num, &h->avctx->time_base.den, + h->sps.num_units_in_tick, den, 1 << 30); + } + + h->avctx->hwaccel = ff_find_hwaccel(h->avctx->codec->id, h->avctx->pix_fmt); + + if (reinit) + free_tables(h, 0); + h->first_field = 0; + h->prev_interlaced_frame = 1; + + init_scan_tables(h); + if (ff_h264_alloc_tables(h) < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "Could not allocate memory for h264\n"); + return AVERROR(ENOMEM); + } + + if (nb_slices > MAX_THREADS || (nb_slices > h->mb_height && h->mb_height)) { + int max_slices; + if (h->mb_height) + max_slices = FFMIN(MAX_THREADS, h->mb_height); + else + max_slices = MAX_THREADS; + av_log(h->avctx, AV_LOG_WARNING, "too many threads/slices (%d)," + " reducing to %d\n", nb_slices, max_slices); + nb_slices = max_slices; + } + h->slice_context_count = nb_slices; + + if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_SLICE)) { + if (context_init(h) < 0) { + av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); + return -1; + } + } else { + for (i = 1; i < h->slice_context_count; i++) { + H264Context *c; + c = h->thread_context[i] = av_mallocz(sizeof(H264Context)); + c->avctx = h->avctx; + if (CONFIG_ERROR_RESILIENCE) { + c->dsp = h->dsp; + } + c->vdsp = h->vdsp; + c->h264dsp = h->h264dsp; + c->h264qpel = h->h264qpel; + c->h264chroma = h->h264chroma; + c->sps = h->sps; + c->pps = h->pps; + c->pixel_shift = h->pixel_shift; + c->cur_chroma_format_idc = h->cur_chroma_format_idc; + c->width = h->width; + c->height = h->height; + c->linesize = h->linesize; + c->uvlinesize = h->uvlinesize; + c->chroma_x_shift = h->chroma_x_shift; + c->chroma_y_shift = h->chroma_y_shift; + c->qscale = h->qscale; + c->droppable = h->droppable; + c->data_partitioning = h->data_partitioning; + c->low_delay = h->low_delay; + c->mb_width = h->mb_width; + c->mb_height = h->mb_height; + c->mb_stride = h->mb_stride; + c->mb_num = h->mb_num; + c->flags = h->flags; + c->workaround_bugs = h->workaround_bugs; + c->pict_type = h->pict_type; + + init_scan_tables(c); + clone_tables(c, h, i); + c->context_initialized = 1; + } + + for (i = 0; i < h->slice_context_count; i++) + if (context_init(h->thread_context[i]) < 0) { + av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); + return -1; + } + } + + h->context_initialized = 1; + + return 0; +} + +/** + * Decode a slice header. + * This will also call ff_MPV_common_init() and frame_start() as needed. + * + * @param h h264context + * @param h0 h264 master context (differs from 'h' when doing sliced based + * parallel decoding) + * + * @return 0 if okay, <0 if an error occurred, 1 if decoding must not be multithreaded + */ +static int decode_slice_header(H264Context *h, H264Context *h0) +{ + unsigned int first_mb_in_slice; + unsigned int pps_id; + int num_ref_idx_active_override_flag, ret; + unsigned int slice_type, tmp, i, j; + int default_ref_list_done = 0; + int last_pic_structure, last_pic_droppable; + int must_reinit; + int needs_reinit = 0; + + h->me.qpel_put = h->h264qpel.put_h264_qpel_pixels_tab; + h->me.qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab; + + first_mb_in_slice = get_ue_golomb_long(&h->gb); + + if (first_mb_in_slice == 0) { // FIXME better field boundary detection + if (h0->current_slice && FIELD_PICTURE(h)) { + field_end(h, 1); + } + + h0->current_slice = 0; + if (!h0->first_field) { + if (h->cur_pic_ptr && !h->droppable) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + } + h->cur_pic_ptr = NULL; + } + } + + slice_type = get_ue_golomb_31(&h->gb); + if (slice_type > 9) { + av_log(h->avctx, AV_LOG_ERROR, + "slice type too large (%d) at %d %d\n", + slice_type, h->mb_x, h->mb_y); + return -1; + } + if (slice_type > 4) { + slice_type -= 5; + h->slice_type_fixed = 1; + } else + h->slice_type_fixed = 0; + + slice_type = golomb_to_pict_type[slice_type]; + if (slice_type == AV_PICTURE_TYPE_I || + (h0->current_slice != 0 && + slice_type == h0->last_slice_type && + !memcmp(h0->last_ref_count, h0->ref_count, sizeof(h0->ref_count)))) { + default_ref_list_done = 1; + } + h->slice_type = slice_type; + h->slice_type_nos = slice_type & 3; + + // to make a few old functions happy, it's wrong though + h->pict_type = h->slice_type; + + pps_id = get_ue_golomb(&h->gb); + if (pps_id >= MAX_PPS_COUNT) { + av_log(h->avctx, AV_LOG_ERROR, "pps_id %d out of range\n", pps_id); + return -1; + } + if (!h0->pps_buffers[pps_id]) { + av_log(h->avctx, AV_LOG_ERROR, + "non-existing PPS %u referenced\n", + pps_id); + return -1; + } + h->pps = *h0->pps_buffers[pps_id]; + + if (!h0->sps_buffers[h->pps.sps_id]) { + av_log(h->avctx, AV_LOG_ERROR, + "non-existing SPS %u referenced\n", + h->pps.sps_id); + return -1; + } + + if (h->pps.sps_id != h->current_sps_id || + h0->sps_buffers[h->pps.sps_id]->new) { + h0->sps_buffers[h->pps.sps_id]->new = 0; + + h->current_sps_id = h->pps.sps_id; + h->sps = *h0->sps_buffers[h->pps.sps_id]; + + if (h->mb_width != h->sps.mb_width || + h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) || + h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || + h->cur_chroma_format_idc != h->sps.chroma_format_idc + ) + needs_reinit = 1; + + if (h->bit_depth_luma != h->sps.bit_depth_luma || + h->chroma_format_idc != h->sps.chroma_format_idc) { + h->bit_depth_luma = h->sps.bit_depth_luma; + h->chroma_format_idc = h->sps.chroma_format_idc; + needs_reinit = 1; + } + if ((ret = h264_set_parameter_from_sps(h)) < 0) + return ret; + } + + h->avctx->profile = ff_h264_get_profile(&h->sps); + h->avctx->level = h->sps.level_idc; + h->avctx->refs = h->sps.ref_frame_count; + + must_reinit = (h->context_initialized && + ( 16*h->sps.mb_width != h->avctx->coded_width + || 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height + || h->avctx->bits_per_raw_sample != h->sps.bit_depth_luma + || h->cur_chroma_format_idc != h->sps.chroma_format_idc + || av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio))); + if (h0->avctx->pix_fmt != get_pixel_format(h0, 0)) + must_reinit = 1; + + h->mb_width = h->sps.mb_width; + h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag); + h->mb_num = h->mb_width * h->mb_height; + h->mb_stride = h->mb_width + 1; + + h->b_stride = h->mb_width * 4; + + h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p + + h->width = 16 * h->mb_width; + h->height = 16 * h->mb_height; + + if (h->sps.video_signal_type_present_flag) { + h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG + : AVCOL_RANGE_MPEG; + if (h->sps.colour_description_present_flag) { + if (h->avctx->colorspace != h->sps.colorspace) + needs_reinit = 1; + h->avctx->color_primaries = h->sps.color_primaries; + h->avctx->color_trc = h->sps.color_trc; + h->avctx->colorspace = h->sps.colorspace; + } + } + + if (h->context_initialized && + ( + needs_reinit || + must_reinit)) { + + if (h != h0) { + av_log(h->avctx, AV_LOG_ERROR, "changing width/height on " + "slice %d\n", h0->current_slice + 1); + return AVERROR_INVALIDDATA; + } + + flush_change(h); + + if ((ret = get_pixel_format(h, 1)) < 0) + return ret; + h->avctx->pix_fmt = ret; + + av_log(h->avctx, AV_LOG_INFO, "Reinit context to %dx%d, " + "pix_fmt: %d\n", h->width, h->height, h->avctx->pix_fmt); + + if ((ret = h264_slice_header_init(h, 1)) < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "h264_slice_header_init() failed\n"); + return ret; + } + } + if (!h->context_initialized) { + if (h != h0) { + av_log(h->avctx, AV_LOG_ERROR, + "Cannot (re-)initialize context during parallel decoding.\n"); + return -1; + } + + if ((ret = get_pixel_format(h, 1)) < 0) + return ret; + h->avctx->pix_fmt = ret; + + if ((ret = h264_slice_header_init(h, 0)) < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "h264_slice_header_init() failed\n"); + return ret; + } + } + + if (h == h0 && h->dequant_coeff_pps != pps_id) { + h->dequant_coeff_pps = pps_id; + init_dequant_tables(h); + } + + h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num); + + h->mb_mbaff = 0; + h->mb_aff_frame = 0; + last_pic_structure = h0->picture_structure; + last_pic_droppable = h0->droppable; + h->droppable = h->nal_ref_idc == 0; + if (h->sps.frame_mbs_only_flag) { + h->picture_structure = PICT_FRAME; + } else { + if (!h->sps.direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) { + av_log(h->avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n"); + return -1; + } + if (get_bits1(&h->gb)) { // field_pic_flag + h->picture_structure = PICT_TOP_FIELD + get_bits1(&h->gb); // bottom_field_flag + } else { + h->picture_structure = PICT_FRAME; + h->mb_aff_frame = h->sps.mb_aff; + } + } + h->mb_field_decoding_flag = h->picture_structure != PICT_FRAME; + + if (h0->current_slice != 0) { + if (last_pic_structure != h->picture_structure || + last_pic_droppable != h->droppable) { + av_log(h->avctx, AV_LOG_ERROR, + "Changing field mode (%d -> %d) between slices is not allowed\n", + last_pic_structure, h->picture_structure); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_INVALIDDATA; + } else if (!h0->cur_pic_ptr) { + av_log(h->avctx, AV_LOG_ERROR, + "unset cur_pic_ptr on %d. slice\n", + h0->current_slice + 1); + return AVERROR_INVALIDDATA; + } + } else { + /* Shorten frame num gaps so we don't have to allocate reference + * frames just to throw them away */ + if (h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0) { + int unwrap_prev_frame_num = h->prev_frame_num; + int max_frame_num = 1 << h->sps.log2_max_frame_num; + + if (unwrap_prev_frame_num > h->frame_num) + unwrap_prev_frame_num -= max_frame_num; + + if ((h->frame_num - unwrap_prev_frame_num) > h->sps.ref_frame_count) { + unwrap_prev_frame_num = (h->frame_num - h->sps.ref_frame_count) - 1; + if (unwrap_prev_frame_num < 0) + unwrap_prev_frame_num += max_frame_num; + + h->prev_frame_num = unwrap_prev_frame_num; + } + } + + /* See if we have a decoded first field looking for a pair... + * Here, we're using that to see if we should mark previously + * decode frames as "finished". + * We have to do that before the "dummy" in-between frame allocation, + * since that can modify h->cur_pic_ptr. */ + if (h0->first_field) { + assert(h0->cur_pic_ptr); + assert(h0->cur_pic_ptr->f.data[0]); + assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF); + + /* Mark old field/frame as completed */ + if (!last_pic_droppable && h0->cur_pic_ptr->tf.owner == h0->avctx) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_BOTTOM_FIELD); + } + + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { + /* Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. */ + if (!last_pic_droppable && last_pic_structure != PICT_FRAME) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_TOP_FIELD); + } + } else { + if (h0->cur_pic_ptr->frame_num != h->frame_num) { + /* This and previous field were reference, but had + * different frame_nums. Consider this field first in + * pair. Throw away previous field except for reference + * purposes. */ + if (!last_pic_droppable && last_pic_structure != PICT_FRAME) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + last_pic_structure == PICT_TOP_FIELD); + } + } else { + /* Second field in complementary pair */ + if (!((last_pic_structure == PICT_TOP_FIELD && + h->picture_structure == PICT_BOTTOM_FIELD) || + (last_pic_structure == PICT_BOTTOM_FIELD && + h->picture_structure == PICT_TOP_FIELD))) { + av_log(h->avctx, AV_LOG_ERROR, + "Invalid field mode combination %d/%d\n", + last_pic_structure, h->picture_structure); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_INVALIDDATA; + } else if (last_pic_droppable != h->droppable) { + avpriv_request_sample(h->avctx, + "Found reference and non-reference fields in the same frame, which"); + h->picture_structure = last_pic_structure; + h->droppable = last_pic_droppable; + return AVERROR_PATCHWELCOME; + } + } + } + } + + while (h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0 && !h0->first_field && + h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) { + Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL; + av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", + h->frame_num, h->prev_frame_num); + if (!h->sps.gaps_in_frame_num_allowed_flag) + for(i=0; ilast_pocs); i++) + h->last_pocs[i] = INT_MIN; + if (h264_frame_start(h) < 0) + return -1; + h->prev_frame_num++; + h->prev_frame_num %= 1 << h->sps.log2_max_frame_num; + h->cur_pic_ptr->frame_num = h->prev_frame_num; + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); + if ((ret = ff_generate_sliding_window_mmcos(h, 1)) < 0 && + h->avctx->err_recognition & AV_EF_EXPLODE) + return ret; + if (ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index) < 0 && + (h->avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; + /* Error concealment: if a ref is missing, copy the previous ref in its place. + * FIXME: avoiding a memcpy would be nice, but ref handling makes many assumptions + * about there being no actual duplicates. + * FIXME: this doesn't copy padding for out-of-frame motion vectors. Given we're + * concealing a lost frame, this probably isn't noticeable by comparison, but it should + * be fixed. */ + if (h->short_ref_count) { + if (prev) { + av_image_copy(h->short_ref[0]->f.data, h->short_ref[0]->f.linesize, + (const uint8_t **)prev->f.data, prev->f.linesize, + h->avctx->pix_fmt, h->mb_width * 16, h->mb_height * 16); + h->short_ref[0]->poc = prev->poc + 2; + } + h->short_ref[0]->frame_num = h->prev_frame_num; + } + } + + /* See if we have a decoded first field looking for a pair... + * We're using that to see whether to continue decoding in that + * frame, or to allocate a new one. */ + if (h0->first_field) { + assert(h0->cur_pic_ptr); + assert(h0->cur_pic_ptr->f.data[0]); + assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF); + + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) { + /* Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. */ + h0->cur_pic_ptr = NULL; + h0->first_field = FIELD_PICTURE(h); + } else { + if (h0->cur_pic_ptr->frame_num != h->frame_num) { + ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX, + h0->picture_structure==PICT_BOTTOM_FIELD); + /* This and the previous field had different frame_nums. + * Consider this field first in pair. Throw away previous + * one except for reference purposes. */ + h0->first_field = 1; + h0->cur_pic_ptr = NULL; + } else { + /* Second field in complementary pair */ + h0->first_field = 0; + } + } + } else { + /* Frame or first field in a potentially complementary pair */ + h0->first_field = FIELD_PICTURE(h); + } + + if (!FIELD_PICTURE(h) || h0->first_field) { + if (h264_frame_start(h) < 0) { + h0->first_field = 0; + return -1; + } + } else { + release_unused_pictures(h, 0); + } + } + if (h != h0 && (ret = clone_slice(h, h0)) < 0) + return ret; + + /* can't be in alloc_tables because linesize isn't known there. + * FIXME: redo bipred weight to not require extra buffer? */ + for (i = 0; i < h->slice_context_count; i++) + if (h->thread_context[i]) { + ret = alloc_scratch_buffers(h->thread_context[i], h->linesize); + if (ret < 0) + return ret; + } + + h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup + + av_assert1(h->mb_num == h->mb_width * h->mb_height); + if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num || + first_mb_in_slice >= h->mb_num) { + av_log(h->avctx, AV_LOG_ERROR, "first_mb_in_slice overflow\n"); + return -1; + } + h->resync_mb_x = h->mb_x = first_mb_in_slice % h->mb_width; + h->resync_mb_y = h->mb_y = (first_mb_in_slice / h->mb_width) << FIELD_OR_MBAFF_PICTURE(h); + if (h->picture_structure == PICT_BOTTOM_FIELD) + h->resync_mb_y = h->mb_y = h->mb_y + 1; + av_assert1(h->mb_y < h->mb_height); + + if (h->picture_structure == PICT_FRAME) { + h->curr_pic_num = h->frame_num; + h->max_pic_num = 1 << h->sps.log2_max_frame_num; + } else { + h->curr_pic_num = 2 * h->frame_num + 1; + h->max_pic_num = 1 << (h->sps.log2_max_frame_num + 1); + } + + if (h->nal_unit_type == NAL_IDR_SLICE) + get_ue_golomb(&h->gb); /* idr_pic_id */ + + if (h->sps.poc_type == 0) { + h->poc_lsb = get_bits(&h->gb, h->sps.log2_max_poc_lsb); + + if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) + h->delta_poc_bottom = get_se_golomb(&h->gb); + } + + if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) { + h->delta_poc[0] = get_se_golomb(&h->gb); + + if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) + h->delta_poc[1] = get_se_golomb(&h->gb); + } + + init_poc(h); + + if (h->pps.redundant_pic_cnt_present) + h->redundant_pic_count = get_ue_golomb(&h->gb); + + // set defaults, might be overridden a few lines later + h->ref_count[0] = h->pps.ref_count[0]; + h->ref_count[1] = h->pps.ref_count[1]; + + if (h->slice_type_nos != AV_PICTURE_TYPE_I) { + unsigned max[2]; + max[0] = max[1] = h->picture_structure == PICT_FRAME ? 15 : 31; + + if (h->slice_type_nos == AV_PICTURE_TYPE_B) + h->direct_spatial_mv_pred = get_bits1(&h->gb); + num_ref_idx_active_override_flag = get_bits1(&h->gb); + + if (num_ref_idx_active_override_flag) { + h->ref_count[0] = get_ue_golomb(&h->gb) + 1; + if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + h->ref_count[1] = get_ue_golomb(&h->gb) + 1; + } else + // full range is spec-ok in this case, even for frames + h->ref_count[1] = 1; + } + + if (h->ref_count[0]-1 > max[0] || h->ref_count[1]-1 > max[1]){ + av_log(h->avctx, AV_LOG_ERROR, "reference overflow %u > %u or %u > %u\n", h->ref_count[0]-1, max[0], h->ref_count[1]-1, max[1]); + h->ref_count[0] = h->ref_count[1] = 0; + return AVERROR_INVALIDDATA; + } + + if (h->slice_type_nos == AV_PICTURE_TYPE_B) + h->list_count = 2; + else + h->list_count = 1; + } else { + h->list_count = 0; + h->ref_count[0] = h->ref_count[1] = 0; + } + + if (!default_ref_list_done) + ff_h264_fill_default_ref_list(h); + + if (h->slice_type_nos != AV_PICTURE_TYPE_I && + ff_h264_decode_ref_pic_list_reordering(h) < 0) { + h->ref_count[1] = h->ref_count[0] = 0; + return -1; + } + + if ((h->pps.weighted_pred && h->slice_type_nos == AV_PICTURE_TYPE_P) || + (h->pps.weighted_bipred_idc == 1 && + h->slice_type_nos == AV_PICTURE_TYPE_B)) + pred_weight_table(h); + else if (h->pps.weighted_bipred_idc == 2 && + h->slice_type_nos == AV_PICTURE_TYPE_B) { + implicit_weight_table(h, -1); + } else { + h->use_weight = 0; + for (i = 0; i < 2; i++) { + h->luma_weight_flag[i] = 0; + h->chroma_weight_flag[i] = 0; + } + } + + // If frame-mt is enabled, only update mmco tables for the first slice + // in a field. Subsequent slices can temporarily clobber h->mmco_index + // or h->mmco, which will cause ref list mix-ups and decoding errors + // further down the line. This may break decoding if the first slice is + // corrupt, thus we only do this if frame-mt is enabled. + if (h->nal_ref_idc && + ff_h264_decode_ref_pic_marking(h0, &h->gb, + !(h->avctx->active_thread_type & FF_THREAD_FRAME) || + h0->current_slice == 0) < 0 && + (h->avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; + + if (FRAME_MBAFF(h)) { + ff_h264_fill_mbaff_ref_list(h); + + if (h->pps.weighted_bipred_idc == 2 && h->slice_type_nos == AV_PICTURE_TYPE_B) { + implicit_weight_table(h, 0); + implicit_weight_table(h, 1); + } + } + + if (h->slice_type_nos == AV_PICTURE_TYPE_B && !h->direct_spatial_mv_pred) + ff_h264_direct_dist_scale_factor(h); + ff_h264_direct_ref_list_init(h); + + if (h->slice_type_nos != AV_PICTURE_TYPE_I && h->pps.cabac) { + tmp = get_ue_golomb_31(&h->gb); + if (tmp > 2) { + av_log(h->avctx, AV_LOG_ERROR, "cabac_init_idc overflow\n"); + return -1; + } + h->cabac_init_idc = tmp; + } + + h->last_qscale_diff = 0; + tmp = h->pps.init_qp + get_se_golomb(&h->gb); + if (tmp > 51 + 6 * (h->sps.bit_depth_luma - 8)) { + av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp); + return -1; + } + h->qscale = tmp; + h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); + h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); + // FIXME qscale / qp ... stuff + if (h->slice_type == AV_PICTURE_TYPE_SP) + get_bits1(&h->gb); /* sp_for_switch_flag */ + if (h->slice_type == AV_PICTURE_TYPE_SP || + h->slice_type == AV_PICTURE_TYPE_SI) + get_se_golomb(&h->gb); /* slice_qs_delta */ + + h->deblocking_filter = 1; + h->slice_alpha_c0_offset = 52; + h->slice_beta_offset = 52; + if (h->pps.deblocking_filter_parameters_present) { + tmp = get_ue_golomb_31(&h->gb); + if (tmp > 2) { + av_log(h->avctx, AV_LOG_ERROR, + "deblocking_filter_idc %u out of range\n", tmp); + return -1; + } + h->deblocking_filter = tmp; + if (h->deblocking_filter < 2) + h->deblocking_filter ^= 1; // 1<->0 + + if (h->deblocking_filter) { + h->slice_alpha_c0_offset += get_se_golomb(&h->gb) << 1; + h->slice_beta_offset += get_se_golomb(&h->gb) << 1; + if (h->slice_alpha_c0_offset > 104U || + h->slice_beta_offset > 104U) { + av_log(h->avctx, AV_LOG_ERROR, + "deblocking filter parameters %d %d out of range\n", + h->slice_alpha_c0_offset, h->slice_beta_offset); + return -1; + } + } + } + + if (h->avctx->skip_loop_filter >= AVDISCARD_ALL || + (h->avctx->skip_loop_filter >= AVDISCARD_NONKEY && + h->slice_type_nos != AV_PICTURE_TYPE_I) || + (h->avctx->skip_loop_filter >= AVDISCARD_BIDIR && + h->slice_type_nos == AV_PICTURE_TYPE_B) || + (h->avctx->skip_loop_filter >= AVDISCARD_NONREF && + h->nal_ref_idc == 0)) + h->deblocking_filter = 0; + + if (h->deblocking_filter == 1 && h0->max_contexts > 1) { + if (h->avctx->flags2 & CODEC_FLAG2_FAST) { + /* Cheat slightly for speed: + * Do not bother to deblock across slices. */ + h->deblocking_filter = 2; + } else { + h0->max_contexts = 1; + if (!h0->single_decode_warning) { + av_log(h->avctx, AV_LOG_INFO, + "Cannot parallelize deblocking type 1, decoding such frames in sequential order\n"); + h0->single_decode_warning = 1; + } + if (h != h0) { + av_log(h->avctx, AV_LOG_ERROR, + "Deblocking switched inside frame.\n"); + return 1; + } + } + } + h->qp_thresh = 15 + 52 - + FFMIN(h->slice_alpha_c0_offset, h->slice_beta_offset) - + FFMAX3(0, + h->pps.chroma_qp_index_offset[0], + h->pps.chroma_qp_index_offset[1]) + + 6 * (h->sps.bit_depth_luma - 8); + + h0->last_slice_type = slice_type; + memcpy(h0->last_ref_count, h0->ref_count, sizeof(h0->last_ref_count)); + h->slice_num = ++h0->current_slice; + + if (h->slice_num) + h0->slice_row[(h->slice_num-1)&(MAX_SLICES-1)]= h->resync_mb_y; + if ( h0->slice_row[h->slice_num&(MAX_SLICES-1)] + 3 >= h->resync_mb_y + && h0->slice_row[h->slice_num&(MAX_SLICES-1)] <= h->resync_mb_y + && h->slice_num >= MAX_SLICES) { + //in case of ASO this check needs to be updated depending on how we decide to assign slice numbers in this case + av_log(h->avctx, AV_LOG_WARNING, "Possibly too many slices (%d >= %d), increase MAX_SLICES and recompile if there are artifacts\n", h->slice_num, MAX_SLICES); + } + + for (j = 0; j < 2; j++) { + int id_list[16]; + int *ref2frm = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][j]; + for (i = 0; i < 16; i++) { + id_list[i] = 60; + if (j < h->list_count && i < h->ref_count[j] && h->ref_list[j][i].f.buf[0]) { + int k; + AVBuffer *buf = h->ref_list[j][i].f.buf[0]->buffer; + for (k = 0; k < h->short_ref_count; k++) + if (h->short_ref[k]->f.buf[0]->buffer == buf) { + id_list[i] = k; + break; + } + for (k = 0; k < h->long_ref_count; k++) + if (h->long_ref[k] && h->long_ref[k]->f.buf[0]->buffer == buf) { + id_list[i] = h->short_ref_count + k; + break; + } + } + } + + ref2frm[0] = + ref2frm[1] = -1; + for (i = 0; i < 16; i++) + ref2frm[i + 2] = 4 * id_list[i] + + (h->ref_list[j][i].reference & 3); + ref2frm[18 + 0] = + ref2frm[18 + 1] = -1; + for (i = 16; i < 48; i++) + ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] + + (h->ref_list[j][i].reference & 3); + } + + if (h->ref_count[0]) h->er.last_pic = &h->ref_list[0][0]; + if (h->ref_count[1]) h->er.next_pic = &h->ref_list[1][0]; + + if (h->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(h->avctx, AV_LOG_DEBUG, + "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", + h->slice_num, + (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"), + first_mb_in_slice, + av_get_picture_type_char(h->slice_type), + h->slice_type_fixed ? " fix" : "", + h->nal_unit_type == NAL_IDR_SLICE ? " IDR" : "", + pps_id, h->frame_num, + h->cur_pic_ptr->field_poc[0], + h->cur_pic_ptr->field_poc[1], + h->ref_count[0], h->ref_count[1], + h->qscale, + h->deblocking_filter, + h->slice_alpha_c0_offset / 2 - 26, h->slice_beta_offset / 2 - 26, + h->use_weight, + h->use_weight == 1 && h->use_weight_chroma ? "c" : "", + h->slice_type == AV_PICTURE_TYPE_B ? (h->direct_spatial_mv_pred ? "SPAT" : "TEMP") : ""); + } + + return 0; +} + +int ff_h264_get_slice_type(const H264Context *h) +{ + switch (h->slice_type) { + case AV_PICTURE_TYPE_P: + return 0; + case AV_PICTURE_TYPE_B: + return 1; + case AV_PICTURE_TYPE_I: + return 2; + case AV_PICTURE_TYPE_SP: + return 3; + case AV_PICTURE_TYPE_SI: + return 4; + default: + return -1; + } +} + +static av_always_inline void fill_filter_caches_inter(H264Context *h, + int mb_type, int top_xy, + int left_xy[LEFT_MBS], + int top_type, + int left_type[LEFT_MBS], + int mb_xy, int list) +{ + int b_stride = h->b_stride; + int16_t(*mv_dst)[2] = &h->mv_cache[list][scan8[0]]; + int8_t *ref_cache = &h->ref_cache[list][scan8[0]]; + if (IS_INTER(mb_type) || IS_DIRECT(mb_type)) { + if (USES_LIST(top_type, list)) { + const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; + const int b8_xy = 4 * top_xy + 2; + int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); + AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]); + ref_cache[0 - 1 * 8] = + ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 0]]; + ref_cache[2 - 1 * 8] = + ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 1]]; + } else { + AV_ZERO128(mv_dst - 1 * 8); + AV_WN32A(&ref_cache[0 - 1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + } + + if (!IS_INTERLACED(mb_type ^ left_type[LTOP])) { + if (USES_LIST(left_type[LTOP], list)) { + const int b_xy = h->mb2b_xy[left_xy[LTOP]] + 3; + const int b8_xy = 4 * left_xy[LTOP] + 1; + int (*ref2frm)[64] =(void*)( h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); + AV_COPY32(mv_dst - 1 + 0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]); + AV_COPY32(mv_dst - 1 + 8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]); + AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]); + AV_COPY32(mv_dst - 1 + 24, h->cur_pic.motion_val[list][b_xy + b_stride * 3]); + ref_cache[-1 + 0] = + ref_cache[-1 + 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 0]]; + ref_cache[-1 + 16] = + ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 1]]; + } else { + AV_ZERO32(mv_dst - 1 + 0); + AV_ZERO32(mv_dst - 1 + 8); + AV_ZERO32(mv_dst - 1 + 16); + AV_ZERO32(mv_dst - 1 + 24); + ref_cache[-1 + 0] = + ref_cache[-1 + 8] = + ref_cache[-1 + 16] = + ref_cache[-1 + 24] = LIST_NOT_USED; + } + } + } + + if (!USES_LIST(mb_type, list)) { + fill_rectangle(mv_dst, 4, 4, 8, pack16to32(0, 0), 4); + AV_WN32A(&ref_cache[0 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + AV_WN32A(&ref_cache[1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + AV_WN32A(&ref_cache[2 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + AV_WN32A(&ref_cache[3 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u); + return; + } + + { + int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy]; + int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF(h) ? 20 : 2)); + uint32_t ref01 = (pack16to32(ref2frm[list][ref[0]], ref2frm[list][ref[1]]) & 0x00FF00FF) * 0x0101; + uint32_t ref23 = (pack16to32(ref2frm[list][ref[2]], ref2frm[list][ref[3]]) & 0x00FF00FF) * 0x0101; + AV_WN32A(&ref_cache[0 * 8], ref01); + AV_WN32A(&ref_cache[1 * 8], ref01); + AV_WN32A(&ref_cache[2 * 8], ref23); + AV_WN32A(&ref_cache[3 * 8], ref23); + } + + { + int16_t(*mv_src)[2] = &h->cur_pic.motion_val[list][4 * h->mb_x + 4 * h->mb_y * b_stride]; + AV_COPY128(mv_dst + 8 * 0, mv_src + 0 * b_stride); + AV_COPY128(mv_dst + 8 * 1, mv_src + 1 * b_stride); + AV_COPY128(mv_dst + 8 * 2, mv_src + 2 * b_stride); + AV_COPY128(mv_dst + 8 * 3, mv_src + 3 * b_stride); + } +} + +/** + * + * @return non zero if the loop filter can be skipped + */ +static int fill_filter_caches(H264Context *h, int mb_type) +{ + const int mb_xy = h->mb_xy; + int top_xy, left_xy[LEFT_MBS]; + int top_type, left_type[LEFT_MBS]; + uint8_t *nnz; + uint8_t *nnz_cache; + + top_xy = mb_xy - (h->mb_stride << MB_FIELD(h)); + + /* Wow, what a mess, why didn't they simplify the interlacing & intra + * stuff, I can't imagine that these complex rules are worth it. */ + + left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; + if (FRAME_MBAFF(h)) { + const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); + const int curr_mb_field_flag = IS_INTERLACED(mb_type); + if (h->mb_y & 1) { + if (left_mb_field_flag != curr_mb_field_flag) + left_xy[LTOP] -= h->mb_stride; + } else { + if (curr_mb_field_flag) + top_xy += h->mb_stride & + (((h->cur_pic.mb_type[top_xy] >> 7) & 1) - 1); + if (left_mb_field_flag != curr_mb_field_flag) + left_xy[LBOT] += h->mb_stride; + } + } + + h->top_mb_xy = top_xy; + h->left_mb_xy[LTOP] = left_xy[LTOP]; + h->left_mb_xy[LBOT] = left_xy[LBOT]; + { + /* For sufficiently low qp, filtering wouldn't do anything. + * This is a conservative estimate: could also check beta_offset + * and more accurate chroma_qp. */ + int qp_thresh = h->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice + int qp = h->cur_pic.qscale_table[mb_xy]; + if (qp <= qp_thresh && + (left_xy[LTOP] < 0 || + ((qp + h->cur_pic.qscale_table[left_xy[LTOP]] + 1) >> 1) <= qp_thresh) && + (top_xy < 0 || + ((qp + h->cur_pic.qscale_table[top_xy] + 1) >> 1) <= qp_thresh)) { + if (!FRAME_MBAFF(h)) + return 1; + if ((left_xy[LTOP] < 0 || + ((qp + h->cur_pic.qscale_table[left_xy[LBOT]] + 1) >> 1) <= qp_thresh) && + (top_xy < h->mb_stride || + ((qp + h->cur_pic.qscale_table[top_xy - h->mb_stride] + 1) >> 1) <= qp_thresh)) + return 1; + } + } + + top_type = h->cur_pic.mb_type[top_xy]; + left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; + left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; + if (h->deblocking_filter == 2) { + if (h->slice_table[top_xy] != h->slice_num) + top_type = 0; + if (h->slice_table[left_xy[LBOT]] != h->slice_num) + left_type[LTOP] = left_type[LBOT] = 0; + } else { + if (h->slice_table[top_xy] == 0xFFFF) + top_type = 0; + if (h->slice_table[left_xy[LBOT]] == 0xFFFF) + left_type[LTOP] = left_type[LBOT] = 0; + } + h->top_type = top_type; + h->left_type[LTOP] = left_type[LTOP]; + h->left_type[LBOT] = left_type[LBOT]; + + if (IS_INTRA(mb_type)) + return 0; + + fill_filter_caches_inter(h, mb_type, top_xy, left_xy, + top_type, left_type, mb_xy, 0); + if (h->list_count == 2) + fill_filter_caches_inter(h, mb_type, top_xy, left_xy, + top_type, left_type, mb_xy, 1); + + nnz = h->non_zero_count[mb_xy]; + nnz_cache = h->non_zero_count_cache; + AV_COPY32(&nnz_cache[4 + 8 * 1], &nnz[0]); + AV_COPY32(&nnz_cache[4 + 8 * 2], &nnz[4]); + AV_COPY32(&nnz_cache[4 + 8 * 3], &nnz[8]); + AV_COPY32(&nnz_cache[4 + 8 * 4], &nnz[12]); + h->cbp = h->cbp_table[mb_xy]; + + if (top_type) { + nnz = h->non_zero_count[top_xy]; + AV_COPY32(&nnz_cache[4 + 8 * 0], &nnz[3 * 4]); + } + + if (left_type[LTOP]) { + nnz = h->non_zero_count[left_xy[LTOP]]; + nnz_cache[3 + 8 * 1] = nnz[3 + 0 * 4]; + nnz_cache[3 + 8 * 2] = nnz[3 + 1 * 4]; + nnz_cache[3 + 8 * 3] = nnz[3 + 2 * 4]; + nnz_cache[3 + 8 * 4] = nnz[3 + 3 * 4]; + } + + /* CAVLC 8x8dct requires NNZ values for residual decoding that differ + * from what the loop filter needs */ + if (!CABAC(h) && h->pps.transform_8x8_mode) { + if (IS_8x8DCT(top_type)) { + nnz_cache[4 + 8 * 0] = + nnz_cache[5 + 8 * 0] = (h->cbp_table[top_xy] & 0x4000) >> 12; + nnz_cache[6 + 8 * 0] = + nnz_cache[7 + 8 * 0] = (h->cbp_table[top_xy] & 0x8000) >> 12; + } + if (IS_8x8DCT(left_type[LTOP])) { + nnz_cache[3 + 8 * 1] = + nnz_cache[3 + 8 * 2] = (h->cbp_table[left_xy[LTOP]] & 0x2000) >> 12; // FIXME check MBAFF + } + if (IS_8x8DCT(left_type[LBOT])) { + nnz_cache[3 + 8 * 3] = + nnz_cache[3 + 8 * 4] = (h->cbp_table[left_xy[LBOT]] & 0x8000) >> 12; // FIXME check MBAFF + } + + if (IS_8x8DCT(mb_type)) { + nnz_cache[scan8[0]] = + nnz_cache[scan8[1]] = + nnz_cache[scan8[2]] = + nnz_cache[scan8[3]] = (h->cbp & 0x1000) >> 12; + + nnz_cache[scan8[0 + 4]] = + nnz_cache[scan8[1 + 4]] = + nnz_cache[scan8[2 + 4]] = + nnz_cache[scan8[3 + 4]] = (h->cbp & 0x2000) >> 12; + + nnz_cache[scan8[0 + 8]] = + nnz_cache[scan8[1 + 8]] = + nnz_cache[scan8[2 + 8]] = + nnz_cache[scan8[3 + 8]] = (h->cbp & 0x4000) >> 12; + + nnz_cache[scan8[0 + 12]] = + nnz_cache[scan8[1 + 12]] = + nnz_cache[scan8[2 + 12]] = + nnz_cache[scan8[3 + 12]] = (h->cbp & 0x8000) >> 12; + } + } + + return 0; +} + +static void loop_filter(H264Context *h, int start_x, int end_x) +{ + uint8_t *dest_y, *dest_cb, *dest_cr; + int linesize, uvlinesize, mb_x, mb_y; + const int end_mb_y = h->mb_y + FRAME_MBAFF(h); + const int old_slice_type = h->slice_type; + const int pixel_shift = h->pixel_shift; + const int block_h = 16 >> h->chroma_y_shift; + + if (h->deblocking_filter) { + for (mb_x = start_x; mb_x < end_x; mb_x++) + for (mb_y = end_mb_y - FRAME_MBAFF(h); mb_y <= end_mb_y; mb_y++) { + int mb_xy, mb_type; + mb_xy = h->mb_xy = mb_x + mb_y * h->mb_stride; + h->slice_num = h->slice_table[mb_xy]; + mb_type = h->cur_pic.mb_type[mb_xy]; + h->list_count = h->list_counts[mb_xy]; + + if (FRAME_MBAFF(h)) + h->mb_mbaff = + h->mb_field_decoding_flag = !!IS_INTERLACED(mb_type); + + h->mb_x = mb_x; + h->mb_y = mb_y; + dest_y = h->cur_pic.f.data[0] + + ((mb_x << pixel_shift) + mb_y * h->linesize) * 16; + dest_cb = h->cur_pic.f.data[1] + + (mb_x << pixel_shift) * (8 << CHROMA444) + + mb_y * h->uvlinesize * block_h; + dest_cr = h->cur_pic.f.data[2] + + (mb_x << pixel_shift) * (8 << CHROMA444) + + mb_y * h->uvlinesize * block_h; + // FIXME simplify above + + if (MB_FIELD(h)) { + linesize = h->mb_linesize = h->linesize * 2; + uvlinesize = h->mb_uvlinesize = h->uvlinesize * 2; + if (mb_y & 1) { // FIXME move out of this function? + dest_y -= h->linesize * 15; + dest_cb -= h->uvlinesize * (block_h - 1); + dest_cr -= h->uvlinesize * (block_h - 1); + } + } else { + linesize = h->mb_linesize = h->linesize; + uvlinesize = h->mb_uvlinesize = h->uvlinesize; + } + backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + uvlinesize, 0); + if (fill_filter_caches(h, mb_type)) + continue; + h->chroma_qp[0] = get_chroma_qp(h, 0, h->cur_pic.qscale_table[mb_xy]); + h->chroma_qp[1] = get_chroma_qp(h, 1, h->cur_pic.qscale_table[mb_xy]); + + if (FRAME_MBAFF(h)) { + ff_h264_filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, + linesize, uvlinesize); + } else { + ff_h264_filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, + dest_cr, linesize, uvlinesize); + } + } + } + h->slice_type = old_slice_type; + h->mb_x = end_x; + h->mb_y = end_mb_y - FRAME_MBAFF(h); + h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); + h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); +} + +static void predict_field_decoding_flag(H264Context *h) +{ + const int mb_xy = h->mb_x + h->mb_y * h->mb_stride; + int mb_type = (h->slice_table[mb_xy - 1] == h->slice_num) ? + h->cur_pic.mb_type[mb_xy - 1] : + (h->slice_table[mb_xy - h->mb_stride] == h->slice_num) ? + h->cur_pic.mb_type[mb_xy - h->mb_stride] : 0; + h->mb_mbaff = h->mb_field_decoding_flag = IS_INTERLACED(mb_type) ? 1 : 0; +} + +/** + * Draw edges and report progress for the last MB row. + */ +static void decode_finish_row(H264Context *h) +{ + int top = 16 * (h->mb_y >> FIELD_PICTURE(h)); + int pic_height = 16 * h->mb_height >> FIELD_PICTURE(h); + int height = 16 << FRAME_MBAFF(h); + int deblock_border = (16 + 4) << FRAME_MBAFF(h); + + if (h->deblocking_filter) { + if ((top + height) >= pic_height) + height += deblock_border; + top -= deblock_border; + } + + if (top >= pic_height || (top + height) < 0) + return; + + height = FFMIN(height, pic_height - top); + if (top < 0) { + height = top + height; + top = 0; + } + + ff_h264_draw_horiz_band(h, top, height); + + if (h->droppable) + return; + + ff_thread_report_progress(&h->cur_pic_ptr->tf, top + height - 1, + h->picture_structure == PICT_BOTTOM_FIELD); +} + +static void er_add_slice(H264Context *h, int startx, int starty, + int endx, int endy, int status) +{ + if (CONFIG_ERROR_RESILIENCE) { + ERContext *er = &h->er; + + er->ref_count = h->ref_count[0]; + ff_er_add_slice(er, startx, starty, endx, endy, status); + } +} + +static int decode_slice(struct AVCodecContext *avctx, void *arg) +{ + H264Context *h = *(void **)arg; + int lf_x_start = h->mb_x; + + h->mb_skip_run = -1; + + av_assert0(h->block_offset[15] == (4 * ((scan8[15] - scan8[0]) & 7) << h->pixel_shift) + 4 * h->linesize * ((scan8[15] - scan8[0]) >> 3)); + + h->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME || + avctx->codec_id != AV_CODEC_ID_H264 || + (CONFIG_GRAY && (h->flags & CODEC_FLAG_GRAY)); + + if (h->pps.cabac) { + /* realign */ + align_get_bits(&h->gb); + + /* init cabac */ + ff_init_cabac_decoder(&h->cabac, + h->gb.buffer + get_bits_count(&h->gb) / 8, + (get_bits_left(&h->gb) + 7) / 8); + + ff_h264_init_cabac_states(h); + + for (;;) { + // START_TIMER + int ret = ff_h264_decode_mb_cabac(h); + int eos; + // STOP_TIMER("decode_mb_cabac") + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + + // FIXME optimal? or let mb_decode decode 16x32 ? + if (ret >= 0 && FRAME_MBAFF(h)) { + h->mb_y++; + + ret = ff_h264_decode_mb_cabac(h); + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + h->mb_y--; + } + eos = get_cabac_terminate(&h->cabac); + + if ((h->workaround_bugs & FF_BUG_TRUNCATED) && + h->cabac.bytestream > h->cabac.bytestream_end + 2) { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, + h->mb_y, ER_MB_END); + if (h->mb_x >= lf_x_start) + loop_filter(h, lf_x_start, h->mb_x + 1); + return 0; + } + if (h->cabac.bytestream > h->cabac.bytestream_end + 2 ) + av_log(h->avctx, AV_LOG_DEBUG, "bytestream overread %td\n", h->cabac.bytestream_end - h->cabac.bytestream); + if (ret < 0 || h->cabac.bytestream > h->cabac.bytestream_end + 4) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding MB %d %d, bytestream (%td)\n", + h->mb_x, h->mb_y, + h->cabac.bytestream_end - h->cabac.bytestream); + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, + h->mb_y, ER_MB_ERROR); + return -1; + } + + if (++h->mb_x >= h->mb_width) { + loop_filter(h, lf_x_start, h->mb_x); + h->mb_x = lf_x_start = 0; + decode_finish_row(h); + ++h->mb_y; + if (FIELD_OR_MBAFF_PICTURE(h)) { + ++h->mb_y; + if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) + predict_field_decoding_flag(h); + } + } + + if (eos || h->mb_y >= h->mb_height) { + tprintf(h->avctx, "slice end %d %d\n", + get_bits_count(&h->gb), h->gb.size_in_bits); + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1, + h->mb_y, ER_MB_END); + if (h->mb_x > lf_x_start) + loop_filter(h, lf_x_start, h->mb_x); + return 0; + } + } + } else { + for (;;) { + int ret = ff_h264_decode_mb_cavlc(h); + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + + // FIXME optimal? or let mb_decode decode 16x32 ? + if (ret >= 0 && FRAME_MBAFF(h)) { + h->mb_y++; + ret = ff_h264_decode_mb_cavlc(h); + + if (ret >= 0) + ff_h264_hl_decode_mb(h); + h->mb_y--; + } + + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding MB %d %d\n", h->mb_x, h->mb_y); + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, + h->mb_y, ER_MB_ERROR); + return -1; + } + + if (++h->mb_x >= h->mb_width) { + loop_filter(h, lf_x_start, h->mb_x); + h->mb_x = lf_x_start = 0; + decode_finish_row(h); + ++h->mb_y; + if (FIELD_OR_MBAFF_PICTURE(h)) { + ++h->mb_y; + if (FRAME_MBAFF(h) && h->mb_y < h->mb_height) + predict_field_decoding_flag(h); + } + if (h->mb_y >= h->mb_height) { + tprintf(h->avctx, "slice end %d %d\n", + get_bits_count(&h->gb), h->gb.size_in_bits); + + if ( get_bits_left(&h->gb) == 0 + || get_bits_left(&h->gb) > 0 && !(h->avctx->err_recognition & AV_EF_AGGRESSIVE)) { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, + h->mb_x - 1, h->mb_y, + ER_MB_END); + + return 0; + } else { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, + h->mb_x, h->mb_y, + ER_MB_END); + + return -1; + } + } + } + + if (get_bits_left(&h->gb) <= 0 && h->mb_skip_run <= 0) { + tprintf(h->avctx, "slice end %d %d\n", + get_bits_count(&h->gb), h->gb.size_in_bits); + if (get_bits_left(&h->gb) == 0) { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, + h->mb_x - 1, h->mb_y, + ER_MB_END); + if (h->mb_x > lf_x_start) + loop_filter(h, lf_x_start, h->mb_x); + + return 0; + } else { + er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x, + h->mb_y, ER_MB_ERROR); + + return -1; + } + } + } + } +} + +/** + * Call decode_slice() for each context. + * + * @param h h264 master context + * @param context_count number of contexts to execute + */ +static int execute_decode_slices(H264Context *h, int context_count) +{ + AVCodecContext *const avctx = h->avctx; + H264Context *hx; + int i; + + if (h->avctx->hwaccel || + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + return 0; + if (context_count == 1) { + return decode_slice(avctx, &h); + } else { + av_assert0(context_count > 0); + for (i = 1; i < context_count; i++) { + hx = h->thread_context[i]; + if (CONFIG_ERROR_RESILIENCE) { + hx->er.error_count = 0; + } + hx->x264_build = h->x264_build; + } + + avctx->execute(avctx, decode_slice, h->thread_context, + NULL, context_count, sizeof(void *)); + + /* pull back stuff from slices to master context */ + hx = h->thread_context[context_count - 1]; + h->mb_x = hx->mb_x; + h->mb_y = hx->mb_y; + h->droppable = hx->droppable; + h->picture_structure = hx->picture_structure; + if (CONFIG_ERROR_RESILIENCE) { + for (i = 1; i < context_count; i++) + h->er.error_count += h->thread_context[i]->er.error_count; + } + } + + return 0; +} + +static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size, + int parse_extradata) +{ + AVCodecContext *const avctx = h->avctx; + H264Context *hx; ///< thread context + int buf_index; + int context_count; + int next_avc; + int pass = !(avctx->active_thread_type & FF_THREAD_FRAME); + int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts + int nal_index; + int idr_cleared=0; + int first_slice = 0; + + h->nal_unit_type= 0; + + if(!h->slice_context_count) + h->slice_context_count= 1; + h->max_contexts = h->slice_context_count; + if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS)) { + h->current_slice = 0; + if (!h->first_field) + h->cur_pic_ptr = NULL; + ff_h264_reset_sei(h); + } + + if (h->nal_length_size == 4) { + if (buf_size > 8 && AV_RB32(buf) == 1 && AV_RB32(buf+5) > (unsigned)buf_size) { + h->is_avc = 0; + }else if(buf_size > 3 && AV_RB32(buf) > 1 && AV_RB32(buf) <= (unsigned)buf_size) + h->is_avc = 1; + } + + for (; pass <= 1; pass++) { + buf_index = 0; + context_count = 0; + next_avc = h->is_avc ? 0 : buf_size; + nal_index = 0; + for (;;) { + int consumed; + int dst_length; + int bit_length; + const uint8_t *ptr; + int i, nalsize = 0; + int err; + + if (buf_index >= next_avc) { + if (buf_index >= buf_size - h->nal_length_size) + break; + nalsize = 0; + for (i = 0; i < h->nal_length_size; i++) + nalsize = (nalsize << 8) | buf[buf_index++]; + if (nalsize <= 0 || nalsize > buf_size - buf_index) { + av_log(h->avctx, AV_LOG_ERROR, + "AVC: nal size %d\n", nalsize); + break; + } + next_avc = buf_index + nalsize; + } else { + // start code prefix search + for (; buf_index + 3 < next_avc; buf_index++) + // This should always succeed in the first iteration. + if (buf[buf_index] == 0 && + buf[buf_index + 1] == 0 && + buf[buf_index + 2] == 1) + break; + + if (buf_index + 3 >= buf_size) { + buf_index = buf_size; + break; + } + + buf_index += 3; + if (buf_index >= next_avc) + continue; + } + + hx = h->thread_context[context_count]; + + ptr = ff_h264_decode_nal(hx, buf + buf_index, &dst_length, + &consumed, next_avc - buf_index); + if (ptr == NULL || dst_length < 0) { + buf_index = -1; + goto end; + } + i = buf_index + consumed; + if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc && + buf[i] == 0x00 && buf[i + 1] == 0x00 && + buf[i + 2] == 0x01 && buf[i + 3] == 0xE0) + h->workaround_bugs |= FF_BUG_TRUNCATED; + + if (!(h->workaround_bugs & FF_BUG_TRUNCATED)) + while(dst_length > 0 && ptr[dst_length - 1] == 0) + dst_length--; + bit_length = !dst_length ? 0 + : (8 * dst_length - + decode_rbsp_trailing(h, ptr + dst_length - 1)); + + if (h->avctx->debug & FF_DEBUG_STARTCODE) + av_log(h->avctx, AV_LOG_DEBUG, "NAL %d/%d at %d/%d length %d pass %d\n", hx->nal_unit_type, hx->nal_ref_idc, buf_index, buf_size, dst_length, pass); + + if (h->is_avc && (nalsize != consumed) && nalsize) + av_log(h->avctx, AV_LOG_DEBUG, + "AVC: Consumed only %d bytes instead of %d\n", + consumed, nalsize); + + buf_index += consumed; + nal_index++; + + if (pass == 0) { + /* packets can sometimes contain multiple PPS/SPS, + * e.g. two PAFF field pictures in one packet, or a demuxer + * which splits NALs strangely if so, when frame threading we + * can't start the next thread until we've read all of them */ + switch (hx->nal_unit_type) { + case NAL_SPS: + case NAL_PPS: + nals_needed = nal_index; + break; + case NAL_DPA: + case NAL_IDR_SLICE: + case NAL_SLICE: + init_get_bits(&hx->gb, ptr, bit_length); + if (!get_ue_golomb(&hx->gb) || !first_slice) + nals_needed = nal_index; + if (!first_slice) + first_slice = hx->nal_unit_type; + } + continue; + } + + if (!first_slice) + switch (hx->nal_unit_type) { + case NAL_DPA: + case NAL_IDR_SLICE: + case NAL_SLICE: + first_slice = hx->nal_unit_type; + } + + // FIXME do not discard SEI id + if (avctx->skip_frame >= AVDISCARD_NONREF && h->nal_ref_idc == 0) + continue; + +again: + /* Ignore per frame NAL unit type during extradata + * parsing. Decoding slices is not possible in codec init + * with frame-mt */ + if (parse_extradata) { + switch (hx->nal_unit_type) { + case NAL_IDR_SLICE: + case NAL_SLICE: + case NAL_DPA: + case NAL_DPB: + case NAL_DPC: + case NAL_AUXILIARY_SLICE: + av_log(h->avctx, AV_LOG_WARNING, "Ignoring NAL %d in global header/extradata\n", hx->nal_unit_type); + hx->nal_unit_type = NAL_FF_IGNORE; + } + } + + err = 0; + + switch (hx->nal_unit_type) { + case NAL_IDR_SLICE: + if (first_slice != NAL_IDR_SLICE) { + av_log(h->avctx, AV_LOG_ERROR, + "Invalid mix of idr and non-idr slices\n"); + buf_index = -1; + goto end; + } + if(!idr_cleared) + idr(h); // FIXME ensure we don't lose some frames if there is reordering + idr_cleared = 1; + case NAL_SLICE: + init_get_bits(&hx->gb, ptr, bit_length); + hx->intra_gb_ptr = + hx->inter_gb_ptr = &hx->gb; + hx->data_partitioning = 0; + + if ((err = decode_slice_header(hx, h))) + break; + + if (h->sei_recovery_frame_cnt >= 0 && (h->frame_num != h->sei_recovery_frame_cnt || hx->slice_type_nos != AV_PICTURE_TYPE_I)) + h->valid_recovery_point = 1; + + if ( h->sei_recovery_frame_cnt >= 0 + && ( h->recovery_frame<0 + || ((h->recovery_frame - h->frame_num) & ((1 << h->sps.log2_max_frame_num)-1)) > h->sei_recovery_frame_cnt)) { + h->recovery_frame = (h->frame_num + h->sei_recovery_frame_cnt) % + (1 << h->sps.log2_max_frame_num); + + if (!h->valid_recovery_point) + h->recovery_frame = h->frame_num; + } + + h->cur_pic_ptr->f.key_frame |= + (hx->nal_unit_type == NAL_IDR_SLICE); + + if (h->recovery_frame == h->frame_num) { + h->cur_pic_ptr->sync |= 1; + h->recovery_frame = -1; + } + + h->sync |= !!h->cur_pic_ptr->f.key_frame; + h->sync |= 3*!!(avctx->flags2 & CODEC_FLAG2_SHOW_ALL); + h->cur_pic_ptr->sync |= h->sync; + + if (h->current_slice == 1) { + if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS)) + decode_postinit(h, nal_index >= nals_needed); + + if (h->avctx->hwaccel && + h->avctx->hwaccel->start_frame(h->avctx, NULL, 0) < 0) + return -1; + if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_h264_picture_start(h); + } + + if (hx->redundant_pic_count == 0 && + (avctx->skip_frame < AVDISCARD_NONREF || + hx->nal_ref_idc) && + (avctx->skip_frame < AVDISCARD_BIDIR || + hx->slice_type_nos != AV_PICTURE_TYPE_B) && + (avctx->skip_frame < AVDISCARD_NONKEY || + hx->slice_type_nos == AV_PICTURE_TYPE_I) && + avctx->skip_frame < AVDISCARD_ALL) { + if (avctx->hwaccel) { + if (avctx->hwaccel->decode_slice(avctx, + &buf[buf_index - consumed], + consumed) < 0) + return -1; + } else if (CONFIG_H264_VDPAU_DECODER && + h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) { + static const uint8_t start_code[] = { + 0x00, 0x00, 0x01 }; + ff_vdpau_add_data_chunk(h->cur_pic_ptr->f.data[0], start_code, + sizeof(start_code)); + ff_vdpau_add_data_chunk(h->cur_pic_ptr->f.data[0], &buf[buf_index - consumed], + consumed); + } else + context_count++; + } + break; + case NAL_DPA: + init_get_bits(&hx->gb, ptr, bit_length); + hx->intra_gb_ptr = + hx->inter_gb_ptr = NULL; + + if ((err = decode_slice_header(hx, h)) < 0) + break; + + hx->data_partitioning = 1; + break; + case NAL_DPB: + init_get_bits(&hx->intra_gb, ptr, bit_length); + hx->intra_gb_ptr = &hx->intra_gb; + break; + case NAL_DPC: + init_get_bits(&hx->inter_gb, ptr, bit_length); + hx->inter_gb_ptr = &hx->inter_gb; + + av_log(h->avctx, AV_LOG_ERROR, "Partitioned H.264 support is incomplete\n"); + break; + + if (hx->redundant_pic_count == 0 && + hx->intra_gb_ptr && + hx->data_partitioning && + h->cur_pic_ptr && h->context_initialized && + (avctx->skip_frame < AVDISCARD_NONREF || hx->nal_ref_idc) && + (avctx->skip_frame < AVDISCARD_BIDIR || + hx->slice_type_nos != AV_PICTURE_TYPE_B) && + (avctx->skip_frame < AVDISCARD_NONKEY || + hx->slice_type_nos == AV_PICTURE_TYPE_I) && + avctx->skip_frame < AVDISCARD_ALL) + context_count++; + break; + case NAL_SEI: + init_get_bits(&h->gb, ptr, bit_length); + ff_h264_decode_sei(h); + break; + case NAL_SPS: + init_get_bits(&h->gb, ptr, bit_length); + if (ff_h264_decode_seq_parameter_set(h) < 0 && (h->is_avc ? (nalsize != consumed) && nalsize : 1)) { + av_log(h->avctx, AV_LOG_DEBUG, + "SPS decoding failure, trying again with the complete NAL\n"); + if (h->is_avc) + av_assert0(next_avc - buf_index + consumed == nalsize); + if ((next_avc - buf_index + consumed - 1) >= INT_MAX/8) + break; + init_get_bits(&h->gb, &buf[buf_index + 1 - consumed], + 8*(next_avc - buf_index + consumed - 1)); + ff_h264_decode_seq_parameter_set(h); + } + + break; + case NAL_PPS: + init_get_bits(&h->gb, ptr, bit_length); + ff_h264_decode_picture_parameter_set(h, bit_length); + break; + case NAL_AUD: + case NAL_END_SEQUENCE: + case NAL_END_STREAM: + case NAL_FILLER_DATA: + case NAL_SPS_EXT: + case NAL_AUXILIARY_SLICE: + break; + case NAL_FF_IGNORE: + break; + default: + av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n", + hx->nal_unit_type, bit_length); + } + + if (context_count == h->max_contexts) { + execute_decode_slices(h, context_count); + context_count = 0; + } + + if (err < 0) + av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n"); + else if (err == 1) { + /* Slice could not be decoded in parallel mode, copy down + * NAL unit stuff to context 0 and restart. Note that + * rbsp_buffer is not transferred, but since we no longer + * run in parallel mode this should not be an issue. */ + h->nal_unit_type = hx->nal_unit_type; + h->nal_ref_idc = hx->nal_ref_idc; + hx = h; + goto again; + } + } + } + if (context_count) + execute_decode_slices(h, context_count); + +end: + /* clean up */ + if (h->cur_pic_ptr && !h->droppable) { + ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, + h->picture_structure == PICT_BOTTOM_FIELD); + } + + return buf_index; +} + +/** + * Return the number of bytes consumed for building the current frame. + */ +static int get_consumed_bytes(int pos, int buf_size) +{ + if (pos == 0) + pos = 1; // avoid infinite loops (i doubt that is needed but ...) + if (pos + 10 > buf_size) + pos = buf_size; // oops ;) + + return pos; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + H264Context *h = avctx->priv_data; + AVFrame *pict = data; + int buf_index = 0; + Picture *out; + int i, out_idx; + int ret; + + h->flags = avctx->flags; + + /* end of stream, output what is still in the buffers */ + if (buf_size == 0) { + out: + + h->cur_pic_ptr = NULL; + h->first_field = 0; + + // FIXME factorize this with the output code below + out = h->delayed_pic[0]; + out_idx = 0; + for (i = 1; + h->delayed_pic[i] && + !h->delayed_pic[i]->f.key_frame && + !h->delayed_pic[i]->mmco_reset; + i++) + if (h->delayed_pic[i]->poc < out->poc) { + out = h->delayed_pic[i]; + out_idx = i; + } + + for (i = out_idx; h->delayed_pic[i]; i++) + h->delayed_pic[i] = h->delayed_pic[i + 1]; + + if (out) { + out->reference &= ~DELAYED_PIC_REF; + if ((ret = av_frame_ref(pict, &out->f)) < 0) + return ret; + *got_frame = 1; + } + + return buf_index; + } + if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){ + int cnt= buf[5]&0x1f; + const uint8_t *p= buf+6; + while(cnt--){ + int nalsize= AV_RB16(p) + 2; + if(nalsize > buf_size - (p-buf) || p[2]!=0x67) + goto not_extra; + p += nalsize; + } + cnt = *(p++); + if(!cnt) + goto not_extra; + while(cnt--){ + int nalsize= AV_RB16(p) + 2; + if(nalsize > buf_size - (p-buf) || p[2]!=0x68) + goto not_extra; + p += nalsize; + } + + return ff_h264_decode_extradata(h, buf, buf_size); + } +not_extra: + + buf_index = decode_nal_units(h, buf, buf_size, 0); + if (buf_index < 0) + return -1; + + if (!h->cur_pic_ptr && h->nal_unit_type == NAL_END_SEQUENCE) { + av_assert0(buf_index <= buf_size); + goto out; + } + + if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS) && !h->cur_pic_ptr) { + if (avctx->skip_frame >= AVDISCARD_NONREF || + buf_size >= 4 && !memcmp("Q264", buf, 4)) + return buf_size; + av_log(avctx, AV_LOG_ERROR, "no frame!\n"); + return -1; + } + + if (!(avctx->flags2 & CODEC_FLAG2_CHUNKS) || + (h->mb_y >= h->mb_height && h->mb_height)) { + if (avctx->flags2 & CODEC_FLAG2_CHUNKS) + decode_postinit(h, 1); + + field_end(h, 0); + + /* Wait for second field. */ + *got_frame = 0; + if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) { + if ((ret = av_frame_ref(pict, &h->next_output_pic->f)) < 0) + return ret; + *got_frame = 1; + if (CONFIG_MPEGVIDEO) { + ff_print_debug_info2(h->avctx, h->next_output_pic, pict, h->er.mbskip_table, + &h->low_delay, + h->mb_width, h->mb_height, h->mb_stride, 1); + } + } + } + + assert(pict->data[0] || !*got_frame); + + return get_consumed_bytes(buf_index, buf_size); +} + +av_cold void ff_h264_free_context(H264Context *h) +{ + int i; + + free_tables(h, 1); // FIXME cleanup init stuff perhaps + + for (i = 0; i < MAX_SPS_COUNT; i++) + av_freep(h->sps_buffers + i); + + for (i = 0; i < MAX_PPS_COUNT; i++) + av_freep(h->pps_buffers + i); +} + +static av_cold int h264_decode_end(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + int i; + + ff_h264_remove_all_refs(h); + ff_h264_free_context(h); + + if (h->DPB) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + unref_picture(h, &h->DPB[i]); + } + } + av_freep(&h->DPB); + + unref_picture(h, &h->cur_pic); + + return 0; +} + +static const AVProfile profiles[] = { + { FF_PROFILE_H264_BASELINE, "Baseline" }, + { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" }, + { FF_PROFILE_H264_MAIN, "Main" }, + { FF_PROFILE_H264_EXTENDED, "Extended" }, + { FF_PROFILE_H264_HIGH, "High" }, + { FF_PROFILE_H264_HIGH_10, "High 10" }, + { FF_PROFILE_H264_HIGH_10_INTRA, "High 10 Intra" }, + { FF_PROFILE_H264_HIGH_422, "High 4:2:2" }, + { FF_PROFILE_H264_HIGH_422_INTRA, "High 4:2:2 Intra" }, + { FF_PROFILE_H264_HIGH_444, "High 4:4:4" }, + { FF_PROFILE_H264_HIGH_444_PREDICTIVE, "High 4:4:4 Predictive" }, + { FF_PROFILE_H264_HIGH_444_INTRA, "High 4:4:4 Intra" }, + { FF_PROFILE_H264_CAVLC_444, "CAVLC 4:4:4" }, + { FF_PROFILE_UNKNOWN }, +}; + +static const AVOption h264_options[] = { + {"is_avc", "is avc", offsetof(H264Context, is_avc), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0}, + {"nal_length_size", "nal_length_size", offsetof(H264Context, nal_length_size), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 4, 0}, + {NULL} +}; + +static const AVClass h264_class = { + .class_name = "H264 Decoder", + .item_name = av_default_item_name, + .option = h264_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVClass h264_vdpau_class = { + .class_name = "H264 VDPAU Decoder", + .item_name = av_default_item_name, + .option = h264_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h264_decoder = { + .name = "h264", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(H264Context), + .init = ff_h264_decode_init, + .close = h264_decode_end, + .decode = decode_frame, + .capabilities = /*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | + CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS | + CODEC_CAP_FRAME_THREADS, + .flush = flush_dpb, + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(decode_update_thread_context), + .profiles = NULL_IF_CONFIG_SMALL(profiles), + .priv_class = &h264_class, +}; + +#if CONFIG_H264_VDPAU_DECODER +AVCodec ff_h264_vdpau_decoder = { + .name = "h264_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(H264Context), + .init = ff_h264_decode_init, + .close = h264_decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU, + .flush = flush_dpb, + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (VDPAU acceleration)"), + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VDPAU_H264, + AV_PIX_FMT_NONE}, + .profiles = NULL_IF_CONFIG_SMALL(profiles), + .priv_class = &h264_vdpau_class, +}; +#endif diff --git a/ffmpeg/libavcodec/h264.h b/ffmpeg/libavcodec/h264.h new file mode 100644 index 0000000..f20401d --- /dev/null +++ b/ffmpeg/libavcodec/h264.h @@ -0,0 +1,977 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 codec. + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_H264_H +#define AVCODEC_H264_H + +#include "libavutil/intreadwrite.h" +#include "cabac.h" +#include "error_resilience.h" +#include "get_bits.h" +#include "mpegvideo.h" +#include "h264chroma.h" +#include "h264dsp.h" +#include "h264pred.h" +#include "h264qpel.h" +#include "rectangle.h" + +#define MAX_SPS_COUNT 32 +#define MAX_PPS_COUNT 256 + +#define MAX_MMCO_COUNT 66 + +#define MAX_DELAYED_PIC_COUNT 16 + +#define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytes + +/* Compiling in interlaced support reduces the speed + * of progressive decoding by about 2%. */ +#define ALLOW_INTERLACE + +#define FMO 0 + +/** + * The maximum number of slices supported by the decoder. + * must be a power of 2 + */ +#define MAX_SLICES 16 + +#ifdef ALLOW_INTERLACE +#define MB_MBAFF(h) h->mb_mbaff +#define MB_FIELD(h) h->mb_field_decoding_flag +#define FRAME_MBAFF(h) h->mb_aff_frame +#define FIELD_PICTURE(h) (h->picture_structure != PICT_FRAME) +#define LEFT_MBS 2 +#define LTOP 0 +#define LBOT 1 +#define LEFT(i) (i) +#else +#define MB_MBAFF(h) 0 +#define MB_FIELD(h) 0 +#define FRAME_MBAFF(h) 0 +#define FIELD_PICTURE(h) 0 +#undef IS_INTERLACED +#define IS_INTERLACED(mb_type) 0 +#define LEFT_MBS 1 +#define LTOP 0 +#define LBOT 0 +#define LEFT(i) 0 +#endif +#define FIELD_OR_MBAFF_PICTURE(h) (FRAME_MBAFF(h) || FIELD_PICTURE(h)) + +#ifndef CABAC +#define CABAC(h) h->pps.cabac +#endif + +#define CHROMA (h->sps.chroma_format_idc) +#define CHROMA422 (h->sps.chroma_format_idc == 2) +#define CHROMA444 (h->sps.chroma_format_idc == 3) + +#define EXTENDED_SAR 255 + +#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit +#define MB_TYPE_8x8DCT 0x01000000 +#define IS_REF0(a) ((a) & MB_TYPE_REF0) +#define IS_8x8DCT(a) ((a) & MB_TYPE_8x8DCT) + +#define QP_MAX_NUM (51 + 6*6) // The maximum supported qp + +/* NAL unit types */ +enum { + NAL_SLICE = 1, + NAL_DPA, + NAL_DPB, + NAL_DPC, + NAL_IDR_SLICE, + NAL_SEI, + NAL_SPS, + NAL_PPS, + NAL_AUD, + NAL_END_SEQUENCE, + NAL_END_STREAM, + NAL_FILLER_DATA, + NAL_SPS_EXT, + NAL_AUXILIARY_SLICE = 19, + NAL_FF_IGNORE = 0xff0f001, +}; + +/** + * SEI message types + */ +typedef enum { + SEI_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) + SEI_TYPE_PIC_TIMING = 1, ///< picture timing + SEI_TYPE_USER_DATA_ITU_T_T35 = 4, ///< user data registered by ITU-T Recommendation T.35 + SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data + SEI_TYPE_RECOVERY_POINT = 6 ///< recovery point (frame # to decoder sync) +} SEI_Type; + +/** + * pic_struct in picture timing SEI message + */ +typedef enum { + SEI_PIC_STRUCT_FRAME = 0, ///< 0: %frame + SEI_PIC_STRUCT_TOP_FIELD = 1, ///< 1: top field + SEI_PIC_STRUCT_BOTTOM_FIELD = 2, ///< 2: bottom field + SEI_PIC_STRUCT_TOP_BOTTOM = 3, ///< 3: top field, bottom field, in that order + SEI_PIC_STRUCT_BOTTOM_TOP = 4, ///< 4: bottom field, top field, in that order + SEI_PIC_STRUCT_TOP_BOTTOM_TOP = 5, ///< 5: top field, bottom field, top field repeated, in that order + SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///< 6: bottom field, top field, bottom field repeated, in that order + SEI_PIC_STRUCT_FRAME_DOUBLING = 7, ///< 7: %frame doubling + SEI_PIC_STRUCT_FRAME_TRIPLING = 8 ///< 8: %frame tripling +} SEI_PicStructType; + +/** + * Sequence parameter set + */ +typedef struct SPS { + int profile_idc; + int level_idc; + int chroma_format_idc; + int transform_bypass; ///< qpprime_y_zero_transform_bypass_flag + int log2_max_frame_num; ///< log2_max_frame_num_minus4 + 4 + int poc_type; ///< pic_order_cnt_type + int log2_max_poc_lsb; ///< log2_max_pic_order_cnt_lsb_minus4 + int delta_pic_order_always_zero_flag; + int offset_for_non_ref_pic; + int offset_for_top_to_bottom_field; + int poc_cycle_length; ///< num_ref_frames_in_pic_order_cnt_cycle + int ref_frame_count; ///< num_ref_frames + int gaps_in_frame_num_allowed_flag; + int mb_width; ///< pic_width_in_mbs_minus1 + 1 + int mb_height; ///< pic_height_in_map_units_minus1 + 1 + int frame_mbs_only_flag; + int mb_aff; ///< mb_adaptive_frame_field_flag + int direct_8x8_inference_flag; + int crop; ///< frame_cropping_flag + unsigned int crop_left; ///< frame_cropping_rect_left_offset + unsigned int crop_right; ///< frame_cropping_rect_right_offset + unsigned int crop_top; ///< frame_cropping_rect_top_offset + unsigned int crop_bottom; ///< frame_cropping_rect_bottom_offset + int vui_parameters_present_flag; + AVRational sar; + int video_signal_type_present_flag; + int full_range; + int colour_description_present_flag; + enum AVColorPrimaries color_primaries; + enum AVColorTransferCharacteristic color_trc; + enum AVColorSpace colorspace; + int timing_info_present_flag; + uint32_t num_units_in_tick; + uint32_t time_scale; + int fixed_frame_rate_flag; + short offset_for_ref_frame[256]; // FIXME dyn aloc? + int bitstream_restriction_flag; + int num_reorder_frames; + int scaling_matrix_present; + uint8_t scaling_matrix4[6][16]; + uint8_t scaling_matrix8[6][64]; + int nal_hrd_parameters_present_flag; + int vcl_hrd_parameters_present_flag; + int pic_struct_present_flag; + int time_offset_length; + int cpb_cnt; ///< See H.264 E.1.2 + int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1 + int cpb_removal_delay_length; ///< cpb_removal_delay_length_minus1 + 1 + int dpb_output_delay_length; ///< dpb_output_delay_length_minus1 + 1 + int bit_depth_luma; ///< bit_depth_luma_minus8 + 8 + int bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 + int residual_color_transform_flag; ///< residual_colour_transform_flag + int constraint_set_flags; ///< constraint_set[0-3]_flag + int new; ///< flag to keep track if the decoder context needs re-init due to changed SPS +} SPS; + +/** + * Picture parameter set + */ +typedef struct PPS { + unsigned int sps_id; + int cabac; ///< entropy_coding_mode_flag + int pic_order_present; ///< pic_order_present_flag + int slice_group_count; ///< num_slice_groups_minus1 + 1 + int mb_slice_group_map_type; + unsigned int ref_count[2]; ///< num_ref_idx_l0/1_active_minus1 + 1 + int weighted_pred; ///< weighted_pred_flag + int weighted_bipred_idc; + int init_qp; ///< pic_init_qp_minus26 + 26 + int init_qs; ///< pic_init_qs_minus26 + 26 + int chroma_qp_index_offset[2]; + int deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag + int constrained_intra_pred; ///< constrained_intra_pred_flag + int redundant_pic_cnt_present; ///< redundant_pic_cnt_present_flag + int transform_8x8_mode; ///< transform_8x8_mode_flag + uint8_t scaling_matrix4[6][16]; + uint8_t scaling_matrix8[6][64]; + uint8_t chroma_qp_table[2][QP_MAX_NUM+1]; ///< pre-scaled (with chroma_qp_index_offset) version of qp_table + int chroma_qp_diff; +} PPS; + +/** + * Memory management control operation opcode. + */ +typedef enum MMCOOpcode { + MMCO_END = 0, + MMCO_SHORT2UNUSED, + MMCO_LONG2UNUSED, + MMCO_SHORT2LONG, + MMCO_SET_MAX_LONG, + MMCO_RESET, + MMCO_LONG, +} MMCOOpcode; + +/** + * Memory management control operation. + */ +typedef struct MMCO { + MMCOOpcode opcode; + int short_pic_num; ///< pic_num without wrapping (pic_num & max_pic_num) + int long_arg; ///< index, pic_num, or num long refs depending on opcode +} MMCO; + +/** + * H264Context + */ +typedef struct H264Context { + AVCodecContext *avctx; + VideoDSPContext vdsp; + H264DSPContext h264dsp; + H264ChromaContext h264chroma; + H264QpelContext h264qpel; + MotionEstContext me; + ParseContext parse_context; + GetBitContext gb; + DSPContext dsp; + ERContext er; + + Picture *DPB; + Picture *cur_pic_ptr; + Picture cur_pic; + + int pixel_shift; ///< 0 for 8-bit H264, 1 for high-bit-depth H264 + int chroma_qp[2]; // QPc + + int qp_thresh; ///< QP threshold to skip loopfilter + + int width, height; + int linesize, uvlinesize; + int chroma_x_shift, chroma_y_shift; + + int qscale; + int droppable; + int data_partitioning; + int coded_picture_number; + int low_delay; + + int context_initialized; + int flags; + int workaround_bugs; + + int prev_mb_skipped; + int next_mb_skipped; + + // prediction stuff + int chroma_pred_mode; + int intra16x16_pred_mode; + + int topleft_mb_xy; + int top_mb_xy; + int topright_mb_xy; + int left_mb_xy[LEFT_MBS]; + + int topleft_type; + int top_type; + int topright_type; + int left_type[LEFT_MBS]; + + const uint8_t *left_block; + int topleft_partition; + + int8_t intra4x4_pred_mode_cache[5 * 8]; + int8_t(*intra4x4_pred_mode); + H264PredContext hpc; + unsigned int topleft_samples_available; + unsigned int top_samples_available; + unsigned int topright_samples_available; + unsigned int left_samples_available; + uint8_t (*top_borders[2])[(16 * 3) * 2]; + + /** + * non zero coeff count cache. + * is 64 if not available. + */ + DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8]; + + uint8_t (*non_zero_count)[48]; + + /** + * Motion vector cache. + */ + DECLARE_ALIGNED(16, int16_t, mv_cache)[2][5 * 8][2]; + DECLARE_ALIGNED(8, int8_t, ref_cache)[2][5 * 8]; +#define LIST_NOT_USED -1 // FIXME rename? +#define PART_NOT_AVAILABLE -2 + + /** + * number of neighbors (top and/or left) that used 8x8 dct + */ + int neighbor_transform_size; + + /** + * block_offset[ 0..23] for frame macroblocks + * block_offset[24..47] for field macroblocks + */ + int block_offset[2 * (16 * 3)]; + + uint32_t *mb2b_xy; // FIXME are these 4 a good idea? + uint32_t *mb2br_xy; + int b_stride; // FIXME use s->b4_stride + + int mb_linesize; ///< may be equal to s->linesize or s->linesize * 2, for mbaff + int mb_uvlinesize; + + unsigned current_sps_id; ///< id of the current SPS + SPS sps; ///< current sps + + /** + * current pps + */ + PPS pps; // FIXME move to Picture perhaps? (->no) do we need that? + + uint32_t dequant4_buffer[6][QP_MAX_NUM + 1][16]; // FIXME should these be moved down? + uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64]; + uint32_t(*dequant4_coeff[6])[16]; + uint32_t(*dequant8_coeff[6])[64]; + + int slice_num; + uint16_t *slice_table; ///< slice_table_base + 2*mb_stride + 1 + int slice_type; + int slice_type_nos; ///< S free slice type (SI/SP are remapped to I/P) + int slice_type_fixed; + + // interlacing specific flags + int mb_aff_frame; + int mb_field_decoding_flag; + int mb_mbaff; ///< mb_aff_frame && mb_field_decoding_flag + int picture_structure; + int first_field; + + DECLARE_ALIGNED(8, uint16_t, sub_mb_type)[4]; + + // Weighted pred stuff + int use_weight; + int use_weight_chroma; + int luma_log2_weight_denom; + int chroma_log2_weight_denom; + // The following 2 can be changed to int8_t but that causes 10cpu cycles speedloss + int luma_weight[48][2][2]; + int chroma_weight[48][2][2][2]; + int implicit_weight[48][48][2]; + + int direct_spatial_mv_pred; + int col_parity; + int col_fieldoff; + int dist_scale_factor[32]; + int dist_scale_factor_field[2][32]; + int map_col_to_list0[2][16 + 32]; + int map_col_to_list0_field[2][2][16 + 32]; + + /** + * num_ref_idx_l0/1_active_minus1 + 1 + */ + unsigned int ref_count[2]; ///< counts frames or fields, depending on current mb mode + unsigned int list_count; + uint8_t *list_counts; ///< Array of list_count per MB specifying the slice type + Picture ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs. + * Reordered version of default_ref_list + * according to picture reordering in slice header */ + int ref2frm[MAX_SLICES][2][64]; ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1 + + // data partitioning + GetBitContext intra_gb; + GetBitContext inter_gb; + GetBitContext *intra_gb_ptr; + GetBitContext *inter_gb_ptr; + + const uint8_t *intra_pcm_ptr; + DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2]; ///< as a dct coeffecient is int32_t in high depth, we need to reserve twice the space. + DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2]; + int16_t mb_padding[256 * 2]; ///< as mb is addressed by scantable[i] and scantable is uint8_t we can either check that i is not too large or ensure that there is some unused stuff after mb + + /** + * Cabac + */ + CABACContext cabac; + uint8_t cabac_state[1024]; + + /* 0x100 -> non null luma_dc, 0x80/0x40 -> non null chroma_dc (cb/cr), 0x?0 -> chroma_cbp(0, 1, 2), 0x0? luma_cbp */ + uint16_t *cbp_table; + int cbp; + int top_cbp; + int left_cbp; + /* chroma_pred_mode for i4x4 or i16x16, else 0 */ + uint8_t *chroma_pred_mode_table; + int last_qscale_diff; + uint8_t (*mvd_table[2])[2]; + DECLARE_ALIGNED(16, uint8_t, mvd_cache)[2][5 * 8][2]; + uint8_t *direct_table; + uint8_t direct_cache[5 * 8]; + + uint8_t zigzag_scan[16]; + uint8_t zigzag_scan8x8[64]; + uint8_t zigzag_scan8x8_cavlc[64]; + uint8_t field_scan[16]; + uint8_t field_scan8x8[64]; + uint8_t field_scan8x8_cavlc[64]; + uint8_t zigzag_scan_q0[16]; + uint8_t zigzag_scan8x8_q0[64]; + uint8_t zigzag_scan8x8_cavlc_q0[64]; + uint8_t field_scan_q0[16]; + uint8_t field_scan8x8_q0[64]; + uint8_t field_scan8x8_cavlc_q0[64]; + + int x264_build; + + int mb_x, mb_y; + int resync_mb_x; + int resync_mb_y; + int mb_skip_run; + int mb_height, mb_width; + int mb_stride; + int mb_num; + int mb_xy; + + int is_complex; + + // deblock + int deblocking_filter; ///< disable_deblocking_filter_idc with 1 <-> 0 + int slice_alpha_c0_offset; + int slice_beta_offset; + + // ============================================================= + // Things below are not used in the MB or more inner code + + int nal_ref_idc; + int nal_unit_type; + uint8_t *rbsp_buffer[2]; + unsigned int rbsp_buffer_size[2]; + + /** + * Used to parse AVC variant of h264 + */ + int is_avc; ///< this flag is != 0 if codec is avc1 + int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) + int got_first; ///< this flag is != 0 if we've parsed a frame + + int bit_depth_luma; ///< luma bit depth from sps to detect changes + int chroma_format_idc; ///< chroma format from sps to detect changes + + SPS *sps_buffers[MAX_SPS_COUNT]; + PPS *pps_buffers[MAX_PPS_COUNT]; + + int dequant_coeff_pps; ///< reinit tables when pps changes + + uint16_t *slice_table_base; + + // POC stuff + int poc_lsb; + int poc_msb; + int delta_poc_bottom; + int delta_poc[2]; + int frame_num; + int prev_poc_msb; ///< poc_msb of the last reference pic for POC type 0 + int prev_poc_lsb; ///< poc_lsb of the last reference pic for POC type 0 + int frame_num_offset; ///< for POC type 2 + int prev_frame_num_offset; ///< for POC type 2 + int prev_frame_num; ///< frame_num of the last pic for POC type 1/2 + + /** + * frame_num for frames or 2 * frame_num + 1 for field pics. + */ + int curr_pic_num; + + /** + * max_frame_num or 2 * max_frame_num for field pics. + */ + int max_pic_num; + + int redundant_pic_count; + + Picture default_ref_list[2][32]; ///< base reference list for all slices of a coded picture + Picture *short_ref[32]; + Picture *long_ref[32]; + Picture *delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // FIXME size? + int last_pocs[MAX_DELAYED_PIC_COUNT]; + Picture *next_output_pic; + int outputed_poc; + int next_outputed_poc; + + /** + * memory management control operations buffer. + */ + MMCO mmco[MAX_MMCO_COUNT]; + int mmco_index; + int mmco_reset; + + int long_ref_count; ///< number of actual long term references + int short_ref_count; ///< number of actual short term references + + int cabac_init_idc; + + /** + * @name Members for slice based multithreading + * @{ + */ + struct H264Context *thread_context[MAX_THREADS]; + + /** + * current slice number, used to initialize slice_num of each thread/context + */ + int current_slice; + + /** + * Max number of threads / contexts. + * This is equal to AVCodecContext.thread_count unless + * multithreaded decoding is impossible, in which case it is + * reduced to 1. + */ + int max_contexts; + + int slice_context_count; + + /** + * 1 if the single thread fallback warning has already been + * displayed, 0 otherwise. + */ + int single_decode_warning; + + enum AVPictureType pict_type; + + int last_slice_type; + unsigned int last_ref_count[2]; + /** @} */ + + /** + * pic_struct in picture timing SEI message + */ + SEI_PicStructType sei_pic_struct; + + /** + * Complement sei_pic_struct + * SEI_PIC_STRUCT_TOP_BOTTOM and SEI_PIC_STRUCT_BOTTOM_TOP indicate interlaced frames. + * However, soft telecined frames may have these values. + * This is used in an attempt to flag soft telecine progressive. + */ + int prev_interlaced_frame; + + /** + * Bit set of clock types for fields/frames in picture timing SEI message. + * For each found ct_type, appropriate bit is set (e.g., bit 1 for + * interlaced). + */ + int sei_ct_type; + + /** + * dpb_output_delay in picture timing SEI message, see H.264 C.2.2 + */ + int sei_dpb_output_delay; + + /** + * cpb_removal_delay in picture timing SEI message, see H.264 C.1.2 + */ + int sei_cpb_removal_delay; + + /** + * recovery_frame_cnt from SEI message + * + * Set to -1 if no recovery point SEI message found or to number of frames + * before playback synchronizes. Frames having recovery point are key + * frames. + */ + int sei_recovery_frame_cnt; + /** + * recovery_frame is the frame_num at which the next frame should + * be fully constructed. + * + * Set to -1 when not expecting a recovery point. + */ + int recovery_frame; + + /** + * Are the SEI recovery points looking valid. + */ + int valid_recovery_point; + + int luma_weight_flag[2]; ///< 7.4.3.2 luma_weight_lX_flag + int chroma_weight_flag[2]; ///< 7.4.3.2 chroma_weight_lX_flag + + // Timestamp stuff + int sei_buffering_period_present; ///< Buffering period SEI flag + int initial_cpb_removal_delay[32]; ///< Initial timestamps for CPBs + + int cur_chroma_format_idc; + uint8_t *bipred_scratchpad; + + int16_t slice_row[MAX_SLICES]; ///< to detect when MAX_SLICES is too low + + int sync; ///< did we had a keyframe or recovery point + + uint8_t parse_history[4]; + int parse_history_count; + int parse_last_mb; + uint8_t *edge_emu_buffer; + int16_t *dc_val_base; + + uint8_t *visualization_buffer[3]; ///< temporary buffer vor MV visualization + + AVBufferPool *qscale_table_pool; + AVBufferPool *mb_type_pool; + AVBufferPool *motion_val_pool; + AVBufferPool *ref_index_pool; +} H264Context; + +extern const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-14). +extern const uint16_t ff_h264_mb_sizes[4]; + +/** + * Decode SEI + */ +int ff_h264_decode_sei(H264Context *h); + +/** + * Decode SPS + */ +int ff_h264_decode_seq_parameter_set(H264Context *h); + +/** + * compute profile from sps + */ +int ff_h264_get_profile(SPS *sps); + +/** + * Decode PPS + */ +int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length); + +/** + * Decode a network abstraction layer unit. + * @param consumed is the number of bytes used as input + * @param length is the length of the array + * @param dst_length is the number of decoded bytes FIXME here + * or a decode rbsp tailing? + * @return decoded bytes, might be src+1 if no escapes + */ +const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, + int *dst_length, int *consumed, int length); + +/** + * Free any data that may have been allocated in the H264 context + * like SPS, PPS etc. + */ +void ff_h264_free_context(H264Context *h); + +/** + * Reconstruct bitstream slice_type. + */ +int ff_h264_get_slice_type(const H264Context *h); + +/** + * Allocate tables. + * needs width/height + */ +int ff_h264_alloc_tables(H264Context *h); + +/** + * Fill the default_ref_list. + */ +int ff_h264_fill_default_ref_list(H264Context *h); + +int ff_h264_decode_ref_pic_list_reordering(H264Context *h); +void ff_h264_fill_mbaff_ref_list(H264Context *h); +void ff_h264_remove_all_refs(H264Context *h); + +/** + * Execute the reference picture marking (memory management control operations). + */ +int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count); + +int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, + int first_slice); + +int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice); + +/** + * Check if the top & left blocks are available if needed & change the + * dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra4x4_pred_mode(H264Context *h); + +/** + * Check if the top & left blocks are available if needed & change the + * dc mode so it only uses the available blocks. + */ +int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma); + +void ff_h264_hl_decode_mb(H264Context *h); +int ff_h264_decode_extradata(H264Context *h, const uint8_t *buf, int size); +int ff_h264_decode_init(AVCodecContext *avctx); +void ff_h264_decode_init_vlc(void); + +/** + * Decode a macroblock + * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error + */ +int ff_h264_decode_mb_cavlc(H264Context *h); + +/** + * Decode a CABAC coded macroblock + * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error + */ +int ff_h264_decode_mb_cabac(H264Context *h); + +void ff_h264_init_cabac_states(H264Context *h); + +void ff_h264_direct_dist_scale_factor(H264Context *const h); +void ff_h264_direct_ref_list_init(H264Context *const h); +void ff_h264_pred_direct_motion(H264Context *const h, int *mb_type); + +void ff_h264_filter_mb_fast(H264Context *h, int mb_x, int mb_y, + uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize); +void ff_h264_filter_mb(H264Context *h, int mb_x, int mb_y, + uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, + unsigned int linesize, unsigned int uvlinesize); + +/** + * Reset SEI values at the beginning of the frame. + * + * @param h H.264 context. + */ +void ff_h264_reset_sei(H264Context *h); + +/* + * o-o o-o + * / / / + * o-o o-o + * ,---' + * o-o o-o + * / / / + * o-o o-o + */ + +/* Scan8 organization: + * 0 1 2 3 4 5 6 7 + * 0 DY y y y y y + * 1 y Y Y Y Y + * 2 y Y Y Y Y + * 3 y Y Y Y Y + * 4 y Y Y Y Y + * 5 DU u u u u u + * 6 u U U U U + * 7 u U U U U + * 8 u U U U U + * 9 u U U U U + * 10 DV v v v v v + * 11 v V V V V + * 12 v V V V V + * 13 v V V V V + * 14 v V V V V + * DY/DU/DV are for luma/chroma DC. + */ + +#define LUMA_DC_BLOCK_INDEX 48 +#define CHROMA_DC_BLOCK_INDEX 49 + +// This table must be here because scan8[constant] must be known at compiletime +static const uint8_t scan8[16 * 3 + 3] = { + 4 + 1 * 8, 5 + 1 * 8, 4 + 2 * 8, 5 + 2 * 8, + 6 + 1 * 8, 7 + 1 * 8, 6 + 2 * 8, 7 + 2 * 8, + 4 + 3 * 8, 5 + 3 * 8, 4 + 4 * 8, 5 + 4 * 8, + 6 + 3 * 8, 7 + 3 * 8, 6 + 4 * 8, 7 + 4 * 8, + 4 + 6 * 8, 5 + 6 * 8, 4 + 7 * 8, 5 + 7 * 8, + 6 + 6 * 8, 7 + 6 * 8, 6 + 7 * 8, 7 + 7 * 8, + 4 + 8 * 8, 5 + 8 * 8, 4 + 9 * 8, 5 + 9 * 8, + 6 + 8 * 8, 7 + 8 * 8, 6 + 9 * 8, 7 + 9 * 8, + 4 + 11 * 8, 5 + 11 * 8, 4 + 12 * 8, 5 + 12 * 8, + 6 + 11 * 8, 7 + 11 * 8, 6 + 12 * 8, 7 + 12 * 8, + 4 + 13 * 8, 5 + 13 * 8, 4 + 14 * 8, 5 + 14 * 8, + 6 + 13 * 8, 7 + 13 * 8, 6 + 14 * 8, 7 + 14 * 8, + 0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8 +}; + +static av_always_inline uint32_t pack16to32(int a, int b) +{ +#if HAVE_BIGENDIAN + return (b & 0xFFFF) + (a << 16); +#else + return (a & 0xFFFF) + (b << 16); +#endif +} + +static av_always_inline uint16_t pack8to16(int a, int b) +{ +#if HAVE_BIGENDIAN + return (b & 0xFF) + (a << 8); +#else + return (a & 0xFF) + (b << 8); +#endif +} + +/** + * Get the chroma qp. + */ +static av_always_inline int get_chroma_qp(H264Context *h, int t, int qscale) +{ + return h->pps.chroma_qp_table[t][qscale]; +} + +/** + * Get the predicted intra4x4 prediction mode. + */ +static av_always_inline int pred_intra_mode(H264Context *h, int n) +{ + const int index8 = scan8[n]; + const int left = h->intra4x4_pred_mode_cache[index8 - 1]; + const int top = h->intra4x4_pred_mode_cache[index8 - 8]; + const int min = FFMIN(left, top); + + tprintf(h->avctx, "mode:%d %d min:%d\n", left, top, min); + + if (min < 0) + return DC_PRED; + else + return min; +} + +static av_always_inline void write_back_intra_pred_mode(H264Context *h) +{ + int8_t *i4x4 = h->intra4x4_pred_mode + h->mb2br_xy[h->mb_xy]; + int8_t *i4x4_cache = h->intra4x4_pred_mode_cache; + + AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4); + i4x4[4] = i4x4_cache[7 + 8 * 3]; + i4x4[5] = i4x4_cache[7 + 8 * 2]; + i4x4[6] = i4x4_cache[7 + 8 * 1]; +} + +static av_always_inline void write_back_non_zero_count(H264Context *h) +{ + const int mb_xy = h->mb_xy; + uint8_t *nnz = h->non_zero_count[mb_xy]; + uint8_t *nnz_cache = h->non_zero_count_cache; + + AV_COPY32(&nnz[ 0], &nnz_cache[4 + 8 * 1]); + AV_COPY32(&nnz[ 4], &nnz_cache[4 + 8 * 2]); + AV_COPY32(&nnz[ 8], &nnz_cache[4 + 8 * 3]); + AV_COPY32(&nnz[12], &nnz_cache[4 + 8 * 4]); + AV_COPY32(&nnz[16], &nnz_cache[4 + 8 * 6]); + AV_COPY32(&nnz[20], &nnz_cache[4 + 8 * 7]); + AV_COPY32(&nnz[32], &nnz_cache[4 + 8 * 11]); + AV_COPY32(&nnz[36], &nnz_cache[4 + 8 * 12]); + + if (!h->chroma_y_shift) { + AV_COPY32(&nnz[24], &nnz_cache[4 + 8 * 8]); + AV_COPY32(&nnz[28], &nnz_cache[4 + 8 * 9]); + AV_COPY32(&nnz[40], &nnz_cache[4 + 8 * 13]); + AV_COPY32(&nnz[44], &nnz_cache[4 + 8 * 14]); + } +} + +static av_always_inline void write_back_motion_list(H264Context *h, + int b_stride, + int b_xy, int b8_xy, + int mb_type, int list) +{ + int16_t(*mv_dst)[2] = &h->cur_pic.motion_val[list][b_xy]; + int16_t(*mv_src)[2] = &h->mv_cache[list][scan8[0]]; + AV_COPY128(mv_dst + 0 * b_stride, mv_src + 8 * 0); + AV_COPY128(mv_dst + 1 * b_stride, mv_src + 8 * 1); + AV_COPY128(mv_dst + 2 * b_stride, mv_src + 8 * 2); + AV_COPY128(mv_dst + 3 * b_stride, mv_src + 8 * 3); + if (CABAC(h)) { + uint8_t (*mvd_dst)[2] = &h->mvd_table[list][FMO ? 8 * h->mb_xy + : h->mb2br_xy[h->mb_xy]]; + uint8_t(*mvd_src)[2] = &h->mvd_cache[list][scan8[0]]; + if (IS_SKIP(mb_type)) { + AV_ZERO128(mvd_dst); + } else { + AV_COPY64(mvd_dst, mvd_src + 8 * 3); + AV_COPY16(mvd_dst + 3 + 3, mvd_src + 3 + 8 * 0); + AV_COPY16(mvd_dst + 3 + 2, mvd_src + 3 + 8 * 1); + AV_COPY16(mvd_dst + 3 + 1, mvd_src + 3 + 8 * 2); + } + } + + { + int8_t *ref_index = &h->cur_pic.ref_index[list][b8_xy]; + int8_t *ref_cache = h->ref_cache[list]; + ref_index[0 + 0 * 2] = ref_cache[scan8[0]]; + ref_index[1 + 0 * 2] = ref_cache[scan8[4]]; + ref_index[0 + 1 * 2] = ref_cache[scan8[8]]; + ref_index[1 + 1 * 2] = ref_cache[scan8[12]]; + } +} + +static av_always_inline void write_back_motion(H264Context *h, int mb_type) +{ + const int b_stride = h->b_stride; + const int b_xy = 4 * h->mb_x + 4 * h->mb_y * h->b_stride; // try mb2b(8)_xy + const int b8_xy = 4 * h->mb_xy; + + if (USES_LIST(mb_type, 0)) { + write_back_motion_list(h, b_stride, b_xy, b8_xy, mb_type, 0); + } else { + fill_rectangle(&h->cur_pic.ref_index[0][b8_xy], + 2, 2, 2, (uint8_t)LIST_NOT_USED, 1); + } + if (USES_LIST(mb_type, 1)) + write_back_motion_list(h, b_stride, b_xy, b8_xy, mb_type, 1); + + if (h->slice_type_nos == AV_PICTURE_TYPE_B && CABAC(h)) { + if (IS_8X8(mb_type)) { + uint8_t *direct_table = &h->direct_table[4 * h->mb_xy]; + direct_table[1] = h->sub_mb_type[1] >> 1; + direct_table[2] = h->sub_mb_type[2] >> 1; + direct_table[3] = h->sub_mb_type[3] >> 1; + } + } +} + +static av_always_inline int get_dct8x8_allowed(H264Context *h) +{ + if (h->sps.direct_8x8_inference_flag) + return !(AV_RN64A(h->sub_mb_type) & + ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8) * + 0x0001000100010001ULL)); + else + return !(AV_RN64A(h->sub_mb_type) & + ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8 | MB_TYPE_DIRECT2) * + 0x0001000100010001ULL)); +} + +void ff_h264_draw_horiz_band(H264Context *h, int y, int height); + +#endif /* AVCODEC_H264_H */ diff --git a/ffmpeg/libavcodec/h264_cabac.c b/ffmpeg/libavcodec/h264_cabac.c new file mode 100644 index 0000000..6f7224e --- /dev/null +++ b/ffmpeg/libavcodec/h264_cabac.c @@ -0,0 +1,2425 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... cabac decoding + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 cabac decoding. + * @author Michael Niedermayer + */ + +#define CABAC(h) 1 +#define UNCHECKED_BITSTREAM_READER 1 + +#include "config.h" +#include "cabac.h" +#include "cabac_functions.h" +#include "internal.h" +#include "avcodec.h" +#include "h264.h" +#include "h264data.h" +#include "h264_mvpred.h" +#include "golomb.h" +#include "libavutil/avassert.h" + +#if ARCH_X86 +#include "x86/h264_i386.h" +#endif + +/* Cabac pre state table */ + +static const int8_t cabac_context_init_I[1024][2] = +{ + /* 0 - 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28,127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 - 23 unsused for I */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, + + /* 24- 39 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + + /* 40 - 53 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, + + /* 54 - 59 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, + + /* 60 - 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 -> 87 */ + { 0, 11 }, { 1, 55 }, { 0, 69 }, { -17, 127 }, + { -13, 102 },{ 0, 82 }, { -7, 74 }, { -21, 107 }, + { -27, 127 },{ -31, 127 },{ -24, 127 }, { -18, 95 }, + { -27, 127 },{ -21, 114 },{ -30, 127 }, { -17, 123 }, + { -12, 115 },{ -16, 122 }, + + /* 88 -> 104 */ + { -11, 115 },{ -12, 63 }, { -2, 68 }, { -15, 84 }, + { -13, 104 },{ -3, 70 }, { -8, 93 }, { -10, 90 }, + { -30, 127 },{ -1, 74 }, { -6, 97 }, { -7, 91 }, + { -20, 127 },{ -4, 56 }, { -5, 82 }, { -7, 76 }, + { -22, 125 }, + + /* 105 -> 135 */ + { -7, 93 }, { -11, 87 }, { -3, 77 }, { -5, 71 }, + { -4, 63 }, { -4, 68 }, { -12, 84 }, { -7, 62 }, + { -7, 65 }, { 8, 61 }, { 5, 56 }, { -2, 66 }, + { 1, 64 }, { 0, 61 }, { -2, 78 }, { 1, 50 }, + { 7, 52 }, { 10, 35 }, { 0, 44 }, { 11, 38 }, + { 1, 45 }, { 0, 46 }, { 5, 44 }, { 31, 17 }, + { 1, 51 }, { 7, 50 }, { 28, 19 }, { 16, 33 }, + { 14, 62 }, { -13, 108 },{ -15, 100 }, + + /* 136 -> 165 */ + { -13, 101 },{ -13, 91 }, { -12, 94 }, { -10, 88 }, + { -16, 84 }, { -10, 86 }, { -7, 83 }, { -13, 87 }, + { -19, 94 }, { 1, 70 }, { 0, 72 }, { -5, 74 }, + { 18, 59 }, { -8, 102 }, { -15, 100 }, { 0, 95 }, + { -4, 75 }, { 2, 72 }, { -11, 75 }, { -3, 71 }, + { 15, 46 }, { -13, 69 }, { 0, 62 }, { 0, 65 }, + { 21, 37 }, { -15, 72 }, { 9, 57 }, { 16, 54 }, + { 0, 62 }, { 12, 72 }, + + /* 166 -> 196 */ + { 24, 0 }, { 15, 9 }, { 8, 25 }, { 13, 18 }, + { 15, 9 }, { 13, 19 }, { 10, 37 }, { 12, 18 }, + { 6, 29 }, { 20, 33 }, { 15, 30 }, { 4, 45 }, + { 1, 58 }, { 0, 62 }, { 7, 61 }, { 12, 38 }, + { 11, 45 }, { 15, 39 }, { 11, 42 }, { 13, 44 }, + { 16, 45 }, { 12, 41 }, { 10, 49 }, { 30, 34 }, + { 18, 42 }, { 10, 55 }, { 17, 51 }, { 17, 46 }, + { 0, 89 }, { 26, -19 }, { 22, -17 }, + + /* 197 -> 226 */ + { 26, -17 }, { 30, -25 }, { 28, -20 }, { 33, -23 }, + { 37, -27 }, { 33, -23 }, { 40, -28 }, { 38, -17 }, + { 33, -11 }, { 40, -15 }, { 41, -6 }, { 38, 1 }, + { 41, 17 }, { 30, -6 }, { 27, 3 }, { 26, 22 }, + { 37, -16 }, { 35, -4 }, { 38, -8 }, { 38, -3 }, + { 37, 3 }, { 38, 5 }, { 42, 0 }, { 35, 16 }, + { 39, 22 }, { 14, 48 }, { 27, 37 }, { 21, 60 }, + { 12, 68 }, { 2, 97 }, + + /* 227 -> 251 */ + { -3, 71 }, { -6, 42 }, { -5, 50 }, { -3, 54 }, + { -2, 62 }, { 0, 58 }, { 1, 63 }, { -2, 72 }, + { -1, 74 }, { -9, 91 }, { -5, 67 }, { -5, 27 }, + { -3, 39 }, { -2, 44 }, { 0, 46 }, { -16, 64 }, + { -8, 68 }, { -10, 78 }, { -6, 77 }, { -10, 86 }, + { -12, 92 }, { -15, 55 }, { -10, 60 }, { -6, 62 }, + { -4, 65 }, + + /* 252 -> 275 */ + { -12, 73 }, { -8, 76 }, { -7, 80 }, { -9, 88 }, + { -17, 110 },{ -11, 97 }, { -20, 84 }, { -11, 79 }, + { -6, 73 }, { -4, 74 }, { -13, 86 }, { -13, 96 }, + { -11, 97 }, { -19, 117 },{ -8, 78 }, { -5, 33 }, + { -4, 48 }, { -2, 53 }, { -3, 62 }, { -13, 71 }, + { -10, 79 }, { -12, 86 }, { -13, 90 }, { -14, 97 }, + + /* 276 a bit special (not used, bypass is used instead) */ + { 0, 0 }, + + /* 277 -> 307 */ + { -6, 93 }, { -6, 84 }, { -8, 79 }, { 0, 66 }, + { -1, 71 }, { 0, 62 }, { -2, 60 }, { -2, 59 }, + { -5, 75 }, { -3, 62 }, { -4, 58 }, { -9, 66 }, + { -1, 79 }, { 0, 71 }, { 3, 68 }, { 10, 44 }, + { -7, 62 }, { 15, 36 }, { 14, 40 }, { 16, 27 }, + { 12, 29 }, { 1, 44 }, { 20, 36 }, { 18, 32 }, + { 5, 42 }, { 1, 48 }, { 10, 62 }, { 17, 46 }, + { 9, 64 }, { -12, 104 },{ -11, 97 }, + + /* 308 -> 337 */ + { -16, 96 }, { -7, 88 }, { -8, 85 }, { -7, 85 }, + { -9, 85 }, { -13, 88 }, { 4, 66 }, { -3, 77 }, + { -3, 76 }, { -6, 76 }, { 10, 58 }, { -1, 76 }, + { -1, 83 }, { -7, 99 }, { -14, 95 }, { 2, 95 }, + { 0, 76 }, { -5, 74 }, { 0, 70 }, { -11, 75 }, + { 1, 68 }, { 0, 65 }, { -14, 73 }, { 3, 62 }, + { 4, 62 }, { -1, 68 }, { -13, 75 }, { 11, 55 }, + { 5, 64 }, { 12, 70 }, + + /* 338 -> 368 */ + { 15, 6 }, { 6, 19 }, { 7, 16 }, { 12, 14 }, + { 18, 13 }, { 13, 11 }, { 13, 15 }, { 15, 16 }, + { 12, 23 }, { 13, 23 }, { 15, 20 }, { 14, 26 }, + { 14, 44 }, { 17, 40 }, { 17, 47 }, { 24, 17 }, + { 21, 21 }, { 25, 22 }, { 31, 27 }, { 22, 29 }, + { 19, 35 }, { 14, 50 }, { 10, 57 }, { 7, 63 }, + { -2, 77 }, { -4, 82 }, { -3, 94 }, { 9, 69 }, + { -12, 109 },{ 36, -35 }, { 36, -34 }, + + /* 369 -> 398 */ + { 32, -26 }, { 37, -30 }, { 44, -32 }, { 34, -18 }, + { 34, -15 }, { 40, -15 }, { 33, -7 }, { 35, -5 }, + { 33, 0 }, { 38, 2 }, { 33, 13 }, { 23, 35 }, + { 13, 58 }, { 29, -3 }, { 26, 0 }, { 22, 30 }, + { 31, -7 }, { 35, -15 }, { 34, -3 }, { 34, 3 }, + { 36, -1 }, { 34, 5 }, { 32, 11 }, { 35, 5 }, + { 34, 12 }, { 39, 11 }, { 30, 29 }, { 34, 26 }, + { 29, 39 }, { 19, 66 }, + + /* 399 -> 435 */ + { 31, 21 }, { 31, 31 }, { 25, 50 }, + { -17, 120 }, { -20, 112 }, { -18, 114 }, { -11, 85 }, + { -15, 92 }, { -14, 89 }, { -26, 71 }, { -15, 81 }, + { -14, 80 }, { 0, 68 }, { -14, 70 }, { -24, 56 }, + { -23, 68 }, { -24, 50 }, { -11, 74 }, { 23, -13 }, + { 26, -13 }, { 40, -15 }, { 49, -14 }, { 44, 3 }, + { 45, 6 }, { 44, 34 }, { 33, 54 }, { 19, 82 }, + { -3, 75 }, { -1, 23 }, { 1, 34 }, { 1, 43 }, + { 0, 54 }, { -2, 55 }, { 0, 61 }, { 1, 64 }, + { 0, 68 }, { -9, 92 }, + + /* 436 -> 459 */ + { -14, 106 }, { -13, 97 }, { -15, 90 }, { -12, 90 }, + { -18, 88 }, { -10, 73 }, { -9, 79 }, { -14, 86 }, + { -10, 73 }, { -10, 70 }, { -10, 69 }, { -5, 66 }, + { -9, 64 }, { -5, 58 }, { 2, 59 }, { 21, -10 }, + { 24, -11 }, { 28, -8 }, { 28, -1 }, { 29, 3 }, + { 29, 9 }, { 35, 20 }, { 29, 36 }, { 14, 67 }, + + /* 460 -> 1024 */ + { -17, 123 }, { -12, 115 }, { -16, 122 }, { -11, 115 }, + { -12, 63 }, { -2, 68 }, { -15, 84 }, { -13, 104 }, + { -3, 70 }, { -8, 93 }, { -10, 90 }, { -30, 127 }, + { -17, 123 }, { -12, 115 }, { -16, 122 }, { -11, 115 }, + { -12, 63 }, { -2, 68 }, { -15, 84 }, { -13, 104 }, + { -3, 70 }, { -8, 93 }, { -10, 90 }, { -30, 127 }, + { -7, 93 }, { -11, 87 }, { -3, 77 }, { -5, 71 }, + { -4, 63 }, { -4, 68 }, { -12, 84 }, { -7, 62 }, + { -7, 65 }, { 8, 61 }, { 5, 56 }, { -2, 66 }, + { 1, 64 }, { 0, 61 }, { -2, 78 }, { 1, 50 }, + { 7, 52 }, { 10, 35 }, { 0, 44 }, { 11, 38 }, + { 1, 45 }, { 0, 46 }, { 5, 44 }, { 31, 17 }, + { 1, 51 }, { 7, 50 }, { 28, 19 }, { 16, 33 }, + { 14, 62 }, { -13, 108 }, { -15, 100 }, { -13, 101 }, + { -13, 91 }, { -12, 94 }, { -10, 88 }, { -16, 84 }, + { -10, 86 }, { -7, 83 }, { -13, 87 }, { -19, 94 }, + { 1, 70 }, { 0, 72 }, { -5, 74 }, { 18, 59 }, + { -7, 93 }, { -11, 87 }, { -3, 77 }, { -5, 71 }, + { -4, 63 }, { -4, 68 }, { -12, 84 }, { -7, 62 }, + { -7, 65 }, { 8, 61 }, { 5, 56 }, { -2, 66 }, + { 1, 64 }, { 0, 61 }, { -2, 78 }, { 1, 50 }, + { 7, 52 }, { 10, 35 }, { 0, 44 }, { 11, 38 }, + { 1, 45 }, { 0, 46 }, { 5, 44 }, { 31, 17 }, + { 1, 51 }, { 7, 50 }, { 28, 19 }, { 16, 33 }, + { 14, 62 }, { -13, 108 }, { -15, 100 }, { -13, 101 }, + { -13, 91 }, { -12, 94 }, { -10, 88 }, { -16, 84 }, + { -10, 86 }, { -7, 83 }, { -13, 87 }, { -19, 94 }, + { 1, 70 }, { 0, 72 }, { -5, 74 }, { 18, 59 }, + { 24, 0 }, { 15, 9 }, { 8, 25 }, { 13, 18 }, + { 15, 9 }, { 13, 19 }, { 10, 37 }, { 12, 18 }, + { 6, 29 }, { 20, 33 }, { 15, 30 }, { 4, 45 }, + { 1, 58 }, { 0, 62 }, { 7, 61 }, { 12, 38 }, + { 11, 45 }, { 15, 39 }, { 11, 42 }, { 13, 44 }, + { 16, 45 }, { 12, 41 }, { 10, 49 }, { 30, 34 }, + { 18, 42 }, { 10, 55 }, { 17, 51 }, { 17, 46 }, + { 0, 89 }, { 26, -19 }, { 22, -17 }, { 26, -17 }, + { 30, -25 }, { 28, -20 }, { 33, -23 }, { 37, -27 }, + { 33, -23 }, { 40, -28 }, { 38, -17 }, { 33, -11 }, + { 40, -15 }, { 41, -6 }, { 38, 1 }, { 41, 17 }, + { 24, 0 }, { 15, 9 }, { 8, 25 }, { 13, 18 }, + { 15, 9 }, { 13, 19 }, { 10, 37 }, { 12, 18 }, + { 6, 29 }, { 20, 33 }, { 15, 30 }, { 4, 45 }, + { 1, 58 }, { 0, 62 }, { 7, 61 }, { 12, 38 }, + { 11, 45 }, { 15, 39 }, { 11, 42 }, { 13, 44 }, + { 16, 45 }, { 12, 41 }, { 10, 49 }, { 30, 34 }, + { 18, 42 }, { 10, 55 }, { 17, 51 }, { 17, 46 }, + { 0, 89 }, { 26, -19 }, { 22, -17 }, { 26, -17 }, + { 30, -25 }, { 28, -20 }, { 33, -23 }, { 37, -27 }, + { 33, -23 }, { 40, -28 }, { 38, -17 }, { 33, -11 }, + { 40, -15 }, { 41, -6 }, { 38, 1 }, { 41, 17 }, + { -17, 120 }, { -20, 112 }, { -18, 114 }, { -11, 85 }, + { -15, 92 }, { -14, 89 }, { -26, 71 }, { -15, 81 }, + { -14, 80 }, { 0, 68 }, { -14, 70 }, { -24, 56 }, + { -23, 68 }, { -24, 50 }, { -11, 74 }, { -14, 106 }, + { -13, 97 }, { -15, 90 }, { -12, 90 }, { -18, 88 }, + { -10, 73 }, { -9, 79 }, { -14, 86 }, { -10, 73 }, + { -10, 70 }, { -10, 69 }, { -5, 66 }, { -9, 64 }, + { -5, 58 }, { 2, 59 }, { 23, -13 }, { 26, -13 }, + { 40, -15 }, { 49, -14 }, { 44, 3 }, { 45, 6 }, + { 44, 34 }, { 33, 54 }, { 19, 82 }, { 21, -10 }, + { 24, -11 }, { 28, -8 }, { 28, -1 }, { 29, 3 }, + { 29, 9 }, { 35, 20 }, { 29, 36 }, { 14, 67 }, + { -3, 75 }, { -1, 23 }, { 1, 34 }, { 1, 43 }, + { 0, 54 }, { -2, 55 }, { 0, 61 }, { 1, 64 }, + { 0, 68 }, { -9, 92 }, { -17, 120 }, { -20, 112 }, + { -18, 114 }, { -11, 85 }, { -15, 92 }, { -14, 89 }, + { -26, 71 }, { -15, 81 }, { -14, 80 }, { 0, 68 }, + { -14, 70 }, { -24, 56 }, { -23, 68 }, { -24, 50 }, + { -11, 74 }, { -14, 106 }, { -13, 97 }, { -15, 90 }, + { -12, 90 }, { -18, 88 }, { -10, 73 }, { -9, 79 }, + { -14, 86 }, { -10, 73 }, { -10, 70 }, { -10, 69 }, + { -5, 66 }, { -9, 64 }, { -5, 58 }, { 2, 59 }, + { 23, -13 }, { 26, -13 }, { 40, -15 }, { 49, -14 }, + { 44, 3 }, { 45, 6 }, { 44, 34 }, { 33, 54 }, + { 19, 82 }, { 21, -10 }, { 24, -11 }, { 28, -8 }, + { 28, -1 }, { 29, 3 }, { 29, 9 }, { 35, 20 }, + { 29, 36 }, { 14, 67 }, { -3, 75 }, { -1, 23 }, + { 1, 34 }, { 1, 43 }, { 0, 54 }, { -2, 55 }, + { 0, 61 }, { 1, 64 }, { 0, 68 }, { -9, 92 }, + { -6, 93 }, { -6, 84 }, { -8, 79 }, { 0, 66 }, + { -1, 71 }, { 0, 62 }, { -2, 60 }, { -2, 59 }, + { -5, 75 }, { -3, 62 }, { -4, 58 }, { -9, 66 }, + { -1, 79 }, { 0, 71 }, { 3, 68 }, { 10, 44 }, + { -7, 62 }, { 15, 36 }, { 14, 40 }, { 16, 27 }, + { 12, 29 }, { 1, 44 }, { 20, 36 }, { 18, 32 }, + { 5, 42 }, { 1, 48 }, { 10, 62 }, { 17, 46 }, + { 9, 64 }, { -12, 104 }, { -11, 97 }, { -16, 96 }, + { -7, 88 }, { -8, 85 }, { -7, 85 }, { -9, 85 }, + { -13, 88 }, { 4, 66 }, { -3, 77 }, { -3, 76 }, + { -6, 76 }, { 10, 58 }, { -1, 76 }, { -1, 83 }, + { -6, 93 }, { -6, 84 }, { -8, 79 }, { 0, 66 }, + { -1, 71 }, { 0, 62 }, { -2, 60 }, { -2, 59 }, + { -5, 75 }, { -3, 62 }, { -4, 58 }, { -9, 66 }, + { -1, 79 }, { 0, 71 }, { 3, 68 }, { 10, 44 }, + { -7, 62 }, { 15, 36 }, { 14, 40 }, { 16, 27 }, + { 12, 29 }, { 1, 44 }, { 20, 36 }, { 18, 32 }, + { 5, 42 }, { 1, 48 }, { 10, 62 }, { 17, 46 }, + { 9, 64 }, { -12, 104 }, { -11, 97 }, { -16, 96 }, + { -7, 88 }, { -8, 85 }, { -7, 85 }, { -9, 85 }, + { -13, 88 }, { 4, 66 }, { -3, 77 }, { -3, 76 }, + { -6, 76 }, { 10, 58 }, { -1, 76 }, { -1, 83 }, + { 15, 6 }, { 6, 19 }, { 7, 16 }, { 12, 14 }, + { 18, 13 }, { 13, 11 }, { 13, 15 }, { 15, 16 }, + { 12, 23 }, { 13, 23 }, { 15, 20 }, { 14, 26 }, + { 14, 44 }, { 17, 40 }, { 17, 47 }, { 24, 17 }, + { 21, 21 }, { 25, 22 }, { 31, 27 }, { 22, 29 }, + { 19, 35 }, { 14, 50 }, { 10, 57 }, { 7, 63 }, + { -2, 77 }, { -4, 82 }, { -3, 94 }, { 9, 69 }, + { -12, 109 }, { 36, -35 }, { 36, -34 }, { 32, -26 }, + { 37, -30 }, { 44, -32 }, { 34, -18 }, { 34, -15 }, + { 40, -15 }, { 33, -7 }, { 35, -5 }, { 33, 0 }, + { 38, 2 }, { 33, 13 }, { 23, 35 }, { 13, 58 }, + { 15, 6 }, { 6, 19 }, { 7, 16 }, { 12, 14 }, + { 18, 13 }, { 13, 11 }, { 13, 15 }, { 15, 16 }, + { 12, 23 }, { 13, 23 }, { 15, 20 }, { 14, 26 }, + { 14, 44 }, { 17, 40 }, { 17, 47 }, { 24, 17 }, + { 21, 21 }, { 25, 22 }, { 31, 27 }, { 22, 29 }, + { 19, 35 }, { 14, 50 }, { 10, 57 }, { 7, 63 }, + { -2, 77 }, { -4, 82 }, { -3, 94 }, { 9, 69 }, + { -12, 109 }, { 36, -35 }, { 36, -34 }, { 32, -26 }, + { 37, -30 }, { 44, -32 }, { 34, -18 }, { 34, -15 }, + { 40, -15 }, { 33, -7 }, { 35, -5 }, { 33, 0 }, + { 38, 2 }, { 33, 13 }, { 23, 35 }, { 13, 58 }, + { -3, 71 }, { -6, 42 }, { -5, 50 }, { -3, 54 }, + { -2, 62 }, { 0, 58 }, { 1, 63 }, { -2, 72 }, + { -1, 74 }, { -9, 91 }, { -5, 67 }, { -5, 27 }, + { -3, 39 }, { -2, 44 }, { 0, 46 }, { -16, 64 }, + { -8, 68 }, { -10, 78 }, { -6, 77 }, { -10, 86 }, + { -12, 92 }, { -15, 55 }, { -10, 60 }, { -6, 62 }, + { -4, 65 }, { -12, 73 }, { -8, 76 }, { -7, 80 }, + { -9, 88 }, { -17, 110 }, { -3, 71 }, { -6, 42 }, + { -5, 50 }, { -3, 54 }, { -2, 62 }, { 0, 58 }, + { 1, 63 }, { -2, 72 }, { -1, 74 }, { -9, 91 }, + { -5, 67 }, { -5, 27 }, { -3, 39 }, { -2, 44 }, + { 0, 46 }, { -16, 64 }, { -8, 68 }, { -10, 78 }, + { -6, 77 }, { -10, 86 }, { -12, 92 }, { -15, 55 }, + { -10, 60 }, { -6, 62 }, { -4, 65 }, { -12, 73 }, + { -8, 76 }, { -7, 80 }, { -9, 88 }, { -17, 110 }, + { -3, 70 }, { -8, 93 }, { -10, 90 }, { -30, 127 }, + { -3, 70 }, { -8, 93 }, { -10, 90 }, { -30, 127 }, + { -3, 70 }, { -8, 93 }, { -10, 90 }, { -30, 127 } +}; + +static const int8_t cabac_context_init_PB[3][1024][2] = +{ + /* i_cabac_init_idc == 0 */ + { + /* 0 - 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 - 23 */ + { 23, 33 }, { 23, 2 }, { 21, 0 }, { 1, 9 }, + { 0, 49 }, { -37, 118 }, { 5, 57 }, { -13, 78 }, + { -11, 65 }, { 1, 62 }, { 12, 49 }, { -4, 73 }, + { 17, 50 }, + + /* 24 - 39 */ + { 18, 64 }, { 9, 43 }, { 29, 0 }, { 26, 67 }, + { 16, 90 }, { 9, 104 }, { -46, 127 }, { -20, 104 }, + { 1, 67 }, { -13, 78 }, { -11, 65 }, { 1, 62 }, + { -6, 86 }, { -17, 95 }, { -6, 61 }, { 9, 45 }, + + /* 40 - 53 */ + { -3, 69 }, { -6, 81 }, { -11, 96 }, { 6, 55 }, + { 7, 67 }, { -5, 86 }, { 2, 88 }, { 0, 58 }, + { -3, 76 }, { -10, 94 }, { 5, 54 }, { 4, 69 }, + { -3, 81 }, { 0, 88 }, + + /* 54 - 59 */ + { -7, 67 }, { -5, 74 }, { -4, 74 }, { -5, 80 }, + { -7, 72 }, { 1, 58 }, + + /* 60 - 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 - 87 */ + { 0, 45 }, { -4, 78 }, { -3, 96 }, { -27, 126 }, + { -28, 98 }, { -25, 101 }, { -23, 67 }, { -28, 82 }, + { -20, 94 }, { -16, 83 }, { -22, 110 }, { -21, 91 }, + { -18, 102 }, { -13, 93 }, { -29, 127 }, { -7, 92 }, + { -5, 89 }, { -7, 96 }, { -13, 108 }, { -3, 46 }, + { -1, 65 }, { -1, 57 }, { -9, 93 }, { -3, 74 }, + { -9, 92 }, { -8, 87 }, { -23, 126 }, { 5, 54 }, + { 6, 60 }, { 6, 59 }, { 6, 69 }, { -1, 48 }, + { 0, 68 }, { -4, 69 }, { -8, 88 }, + + /* 105 -> 165 */ + { -2, 85 }, { -6, 78 }, { -1, 75 }, { -7, 77 }, + { 2, 54 }, { 5, 50 }, { -3, 68 }, { 1, 50 }, + { 6, 42 }, { -4, 81 }, { 1, 63 }, { -4, 70 }, + { 0, 67 }, { 2, 57 }, { -2, 76 }, { 11, 35 }, + { 4, 64 }, { 1, 61 }, { 11, 35 }, { 18, 25 }, + { 12, 24 }, { 13, 29 }, { 13, 36 }, { -10, 93 }, + { -7, 73 }, { -2, 73 }, { 13, 46 }, { 9, 49 }, + { -7, 100 }, { 9, 53 }, { 2, 53 }, { 5, 53 }, + { -2, 61 }, { 0, 56 }, { 0, 56 }, { -13, 63 }, + { -5, 60 }, { -1, 62 }, { 4, 57 }, { -6, 69 }, + { 4, 57 }, { 14, 39 }, { 4, 51 }, { 13, 68 }, + { 3, 64 }, { 1, 61 }, { 9, 63 }, { 7, 50 }, + { 16, 39 }, { 5, 44 }, { 4, 52 }, { 11, 48 }, + { -5, 60 }, { -1, 59 }, { 0, 59 }, { 22, 33 }, + { 5, 44 }, { 14, 43 }, { -1, 78 }, { 0, 60 }, + { 9, 69 }, + + /* 166 - 226 */ + { 11, 28 }, { 2, 40 }, { 3, 44 }, { 0, 49 }, + { 0, 46 }, { 2, 44 }, { 2, 51 }, { 0, 47 }, + { 4, 39 }, { 2, 62 }, { 6, 46 }, { 0, 54 }, + { 3, 54 }, { 2, 58 }, { 4, 63 }, { 6, 51 }, + { 6, 57 }, { 7, 53 }, { 6, 52 }, { 6, 55 }, + { 11, 45 }, { 14, 36 }, { 8, 53 }, { -1, 82 }, + { 7, 55 }, { -3, 78 }, { 15, 46 }, { 22, 31 }, + { -1, 84 }, { 25, 7 }, { 30, -7 }, { 28, 3 }, + { 28, 4 }, { 32, 0 }, { 34, -1 }, { 30, 6 }, + { 30, 6 }, { 32, 9 }, { 31, 19 }, { 26, 27 }, + { 26, 30 }, { 37, 20 }, { 28, 34 }, { 17, 70 }, + { 1, 67 }, { 5, 59 }, { 9, 67 }, { 16, 30 }, + { 18, 32 }, { 18, 35 }, { 22, 29 }, { 24, 31 }, + { 23, 38 }, { 18, 43 }, { 20, 41 }, { 11, 63 }, + { 9, 59 }, { 9, 64 }, { -1, 94 }, { -2, 89 }, + { -9, 108 }, + + /* 227 - 275 */ + { -6, 76 }, { -2, 44 }, { 0, 45 }, { 0, 52 }, + { -3, 64 }, { -2, 59 }, { -4, 70 }, { -4, 75 }, + { -8, 82 }, { -17, 102 }, { -9, 77 }, { 3, 24 }, + { 0, 42 }, { 0, 48 }, { 0, 55 }, { -6, 59 }, + { -7, 71 }, { -12, 83 }, { -11, 87 }, { -30, 119 }, + { 1, 58 }, { -3, 29 }, { -1, 36 }, { 1, 38 }, + { 2, 43 }, { -6, 55 }, { 0, 58 }, { 0, 64 }, + { -3, 74 }, { -10, 90 }, { 0, 70 }, { -4, 29 }, + { 5, 31 }, { 7, 42 }, { 1, 59 }, { -2, 58 }, + { -3, 72 }, { -3, 81 }, { -11, 97 }, { 0, 58 }, + { 8, 5 }, { 10, 14 }, { 14, 18 }, { 13, 27 }, + { 2, 40 }, { 0, 58 }, { -3, 70 }, { -6, 79 }, + { -8, 85 }, + + /* 276 a bit special (not used, bypass is used instead) */ + { 0, 0 }, + + /* 277 - 337 */ + { -13, 106 }, { -16, 106 }, { -10, 87 }, { -21, 114 }, + { -18, 110 }, { -14, 98 }, { -22, 110 }, { -21, 106 }, + { -18, 103 }, { -21, 107 }, { -23, 108 }, { -26, 112 }, + { -10, 96 }, { -12, 95 }, { -5, 91 }, { -9, 93 }, + { -22, 94 }, { -5, 86 }, { 9, 67 }, { -4, 80 }, + { -10, 85 }, { -1, 70 }, { 7, 60 }, { 9, 58 }, + { 5, 61 }, { 12, 50 }, { 15, 50 }, { 18, 49 }, + { 17, 54 }, { 10, 41 }, { 7, 46 }, { -1, 51 }, + { 7, 49 }, { 8, 52 }, { 9, 41 }, { 6, 47 }, + { 2, 55 }, { 13, 41 }, { 10, 44 }, { 6, 50 }, + { 5, 53 }, { 13, 49 }, { 4, 63 }, { 6, 64 }, + { -2, 69 }, { -2, 59 }, { 6, 70 }, { 10, 44 }, + { 9, 31 }, { 12, 43 }, { 3, 53 }, { 14, 34 }, + { 10, 38 }, { -3, 52 }, { 13, 40 }, { 17, 32 }, + { 7, 44 }, { 7, 38 }, { 13, 50 }, { 10, 57 }, + { 26, 43 }, + + /* 338 - 398 */ + { 14, 11 }, { 11, 14 }, { 9, 11 }, { 18, 11 }, + { 21, 9 }, { 23, -2 }, { 32, -15 }, { 32, -15 }, + { 34, -21 }, { 39, -23 }, { 42, -33 }, { 41, -31 }, + { 46, -28 }, { 38, -12 }, { 21, 29 }, { 45, -24 }, + { 53, -45 }, { 48, -26 }, { 65, -43 }, { 43, -19 }, + { 39, -10 }, { 30, 9 }, { 18, 26 }, { 20, 27 }, + { 0, 57 }, { -14, 82 }, { -5, 75 }, { -19, 97 }, + { -35, 125 }, { 27, 0 }, { 28, 0 }, { 31, -4 }, + { 27, 6 }, { 34, 8 }, { 30, 10 }, { 24, 22 }, + { 33, 19 }, { 22, 32 }, { 26, 31 }, { 21, 41 }, + { 26, 44 }, { 23, 47 }, { 16, 65 }, { 14, 71 }, + { 8, 60 }, { 6, 63 }, { 17, 65 }, { 21, 24 }, + { 23, 20 }, { 26, 23 }, { 27, 32 }, { 28, 23 }, + { 28, 24 }, { 23, 40 }, { 24, 32 }, { 28, 29 }, + { 23, 42 }, { 19, 57 }, { 22, 53 }, { 22, 61 }, + { 11, 86 }, + + /* 399 - 435 */ + { 12, 40 }, { 11, 51 }, { 14, 59 }, + { -4, 79 }, { -7, 71 }, { -5, 69 }, { -9, 70 }, + { -8, 66 }, { -10, 68 }, { -19, 73 }, { -12, 69 }, + { -16, 70 }, { -15, 67 }, { -20, 62 }, { -19, 70 }, + { -16, 66 }, { -22, 65 }, { -20, 63 }, { 9, -2 }, + { 26, -9 }, { 33, -9 }, { 39, -7 }, { 41, -2 }, + { 45, 3 }, { 49, 9 }, { 45, 27 }, { 36, 59 }, + { -6, 66 }, { -7, 35 }, { -7, 42 }, { -8, 45 }, + { -5, 48 }, { -12, 56 }, { -6, 60 }, { -5, 62 }, + { -8, 66 }, { -8, 76 }, + + /* 436 - 459 */ + { -5, 85 }, { -6, 81 }, { -10, 77 }, { -7, 81 }, + { -17, 80 }, { -18, 73 }, { -4, 74 }, { -10, 83 }, + { -9, 71 }, { -9, 67 }, { -1, 61 }, { -8, 66 }, + { -14, 66 }, { 0, 59 }, { 2, 59 }, { 21, -13 }, + { 33, -14 }, { 39, -7 }, { 46, -2 }, { 51, 2 }, + { 60, 6 }, { 61, 17 }, { 55, 34 }, { 42, 62 }, + + /* 460 - 1024 */ + { -7, 92 }, { -5, 89 }, { -7, 96 }, { -13, 108 }, + { -3, 46 }, { -1, 65 }, { -1, 57 }, { -9, 93 }, + { -3, 74 }, { -9, 92 }, { -8, 87 }, { -23, 126 }, + { -7, 92 }, { -5, 89 }, { -7, 96 }, { -13, 108 }, + { -3, 46 }, { -1, 65 }, { -1, 57 }, { -9, 93 }, + { -3, 74 }, { -9, 92 }, { -8, 87 }, { -23, 126 }, + { -2, 85 }, { -6, 78 }, { -1, 75 }, { -7, 77 }, + { 2, 54 }, { 5, 50 }, { -3, 68 }, { 1, 50 }, + { 6, 42 }, { -4, 81 }, { 1, 63 }, { -4, 70 }, + { 0, 67 }, { 2, 57 }, { -2, 76 }, { 11, 35 }, + { 4, 64 }, { 1, 61 }, { 11, 35 }, { 18, 25 }, + { 12, 24 }, { 13, 29 }, { 13, 36 }, { -10, 93 }, + { -7, 73 }, { -2, 73 }, { 13, 46 }, { 9, 49 }, + { -7, 100 }, { 9, 53 }, { 2, 53 }, { 5, 53 }, + { -2, 61 }, { 0, 56 }, { 0, 56 }, { -13, 63 }, + { -5, 60 }, { -1, 62 }, { 4, 57 }, { -6, 69 }, + { 4, 57 }, { 14, 39 }, { 4, 51 }, { 13, 68 }, + { -2, 85 }, { -6, 78 }, { -1, 75 }, { -7, 77 }, + { 2, 54 }, { 5, 50 }, { -3, 68 }, { 1, 50 }, + { 6, 42 }, { -4, 81 }, { 1, 63 }, { -4, 70 }, + { 0, 67 }, { 2, 57 }, { -2, 76 }, { 11, 35 }, + { 4, 64 }, { 1, 61 }, { 11, 35 }, { 18, 25 }, + { 12, 24 }, { 13, 29 }, { 13, 36 }, { -10, 93 }, + { -7, 73 }, { -2, 73 }, { 13, 46 }, { 9, 49 }, + { -7, 100 }, { 9, 53 }, { 2, 53 }, { 5, 53 }, + { -2, 61 }, { 0, 56 }, { 0, 56 }, { -13, 63 }, + { -5, 60 }, { -1, 62 }, { 4, 57 }, { -6, 69 }, + { 4, 57 }, { 14, 39 }, { 4, 51 }, { 13, 68 }, + { 11, 28 }, { 2, 40 }, { 3, 44 }, { 0, 49 }, + { 0, 46 }, { 2, 44 }, { 2, 51 }, { 0, 47 }, + { 4, 39 }, { 2, 62 }, { 6, 46 }, { 0, 54 }, + { 3, 54 }, { 2, 58 }, { 4, 63 }, { 6, 51 }, + { 6, 57 }, { 7, 53 }, { 6, 52 }, { 6, 55 }, + { 11, 45 }, { 14, 36 }, { 8, 53 }, { -1, 82 }, + { 7, 55 }, { -3, 78 }, { 15, 46 }, { 22, 31 }, + { -1, 84 }, { 25, 7 }, { 30, -7 }, { 28, 3 }, + { 28, 4 }, { 32, 0 }, { 34, -1 }, { 30, 6 }, + { 30, 6 }, { 32, 9 }, { 31, 19 }, { 26, 27 }, + { 26, 30 }, { 37, 20 }, { 28, 34 }, { 17, 70 }, + { 11, 28 }, { 2, 40 }, { 3, 44 }, { 0, 49 }, + { 0, 46 }, { 2, 44 }, { 2, 51 }, { 0, 47 }, + { 4, 39 }, { 2, 62 }, { 6, 46 }, { 0, 54 }, + { 3, 54 }, { 2, 58 }, { 4, 63 }, { 6, 51 }, + { 6, 57 }, { 7, 53 }, { 6, 52 }, { 6, 55 }, + { 11, 45 }, { 14, 36 }, { 8, 53 }, { -1, 82 }, + { 7, 55 }, { -3, 78 }, { 15, 46 }, { 22, 31 }, + { -1, 84 }, { 25, 7 }, { 30, -7 }, { 28, 3 }, + { 28, 4 }, { 32, 0 }, { 34, -1 }, { 30, 6 }, + { 30, 6 }, { 32, 9 }, { 31, 19 }, { 26, 27 }, + { 26, 30 }, { 37, 20 }, { 28, 34 }, { 17, 70 }, + { -4, 79 }, { -7, 71 }, { -5, 69 }, { -9, 70 }, + { -8, 66 }, { -10, 68 }, { -19, 73 }, { -12, 69 }, + { -16, 70 }, { -15, 67 }, { -20, 62 }, { -19, 70 }, + { -16, 66 }, { -22, 65 }, { -20, 63 }, { -5, 85 }, + { -6, 81 }, { -10, 77 }, { -7, 81 }, { -17, 80 }, + { -18, 73 }, { -4, 74 }, { -10, 83 }, { -9, 71 }, + { -9, 67 }, { -1, 61 }, { -8, 66 }, { -14, 66 }, + { 0, 59 }, { 2, 59 }, { 9, -2 }, { 26, -9 }, + { 33, -9 }, { 39, -7 }, { 41, -2 }, { 45, 3 }, + { 49, 9 }, { 45, 27 }, { 36, 59 }, { 21, -13 }, + { 33, -14 }, { 39, -7 }, { 46, -2 }, { 51, 2 }, + { 60, 6 }, { 61, 17 }, { 55, 34 }, { 42, 62 }, + { -6, 66 }, { -7, 35 }, { -7, 42 }, { -8, 45 }, + { -5, 48 }, { -12, 56 }, { -6, 60 }, { -5, 62 }, + { -8, 66 }, { -8, 76 }, { -4, 79 }, { -7, 71 }, + { -5, 69 }, { -9, 70 }, { -8, 66 }, { -10, 68 }, + { -19, 73 }, { -12, 69 }, { -16, 70 }, { -15, 67 }, + { -20, 62 }, { -19, 70 }, { -16, 66 }, { -22, 65 }, + { -20, 63 }, { -5, 85 }, { -6, 81 }, { -10, 77 }, + { -7, 81 }, { -17, 80 }, { -18, 73 }, { -4, 74 }, + { -10, 83 }, { -9, 71 }, { -9, 67 }, { -1, 61 }, + { -8, 66 }, { -14, 66 }, { 0, 59 }, { 2, 59 }, + { 9, -2 }, { 26, -9 }, { 33, -9 }, { 39, -7 }, + { 41, -2 }, { 45, 3 }, { 49, 9 }, { 45, 27 }, + { 36, 59 }, { 21, -13 }, { 33, -14 }, { 39, -7 }, + { 46, -2 }, { 51, 2 }, { 60, 6 }, { 61, 17 }, + { 55, 34 }, { 42, 62 }, { -6, 66 }, { -7, 35 }, + { -7, 42 }, { -8, 45 }, { -5, 48 }, { -12, 56 }, + { -6, 60 }, { -5, 62 }, { -8, 66 }, { -8, 76 }, + { -13, 106 }, { -16, 106 }, { -10, 87 }, { -21, 114 }, + { -18, 110 }, { -14, 98 }, { -22, 110 }, { -21, 106 }, + { -18, 103 }, { -21, 107 }, { -23, 108 }, { -26, 112 }, + { -10, 96 }, { -12, 95 }, { -5, 91 }, { -9, 93 }, + { -22, 94 }, { -5, 86 }, { 9, 67 }, { -4, 80 }, + { -10, 85 }, { -1, 70 }, { 7, 60 }, { 9, 58 }, + { 5, 61 }, { 12, 50 }, { 15, 50 }, { 18, 49 }, + { 17, 54 }, { 10, 41 }, { 7, 46 }, { -1, 51 }, + { 7, 49 }, { 8, 52 }, { 9, 41 }, { 6, 47 }, + { 2, 55 }, { 13, 41 }, { 10, 44 }, { 6, 50 }, + { 5, 53 }, { 13, 49 }, { 4, 63 }, { 6, 64 }, + { -13, 106 }, { -16, 106 }, { -10, 87 }, { -21, 114 }, + { -18, 110 }, { -14, 98 }, { -22, 110 }, { -21, 106 }, + { -18, 103 }, { -21, 107 }, { -23, 108 }, { -26, 112 }, + { -10, 96 }, { -12, 95 }, { -5, 91 }, { -9, 93 }, + { -22, 94 }, { -5, 86 }, { 9, 67 }, { -4, 80 }, + { -10, 85 }, { -1, 70 }, { 7, 60 }, { 9, 58 }, + { 5, 61 }, { 12, 50 }, { 15, 50 }, { 18, 49 }, + { 17, 54 }, { 10, 41 }, { 7, 46 }, { -1, 51 }, + { 7, 49 }, { 8, 52 }, { 9, 41 }, { 6, 47 }, + { 2, 55 }, { 13, 41 }, { 10, 44 }, { 6, 50 }, + { 5, 53 }, { 13, 49 }, { 4, 63 }, { 6, 64 }, + { 14, 11 }, { 11, 14 }, { 9, 11 }, { 18, 11 }, + { 21, 9 }, { 23, -2 }, { 32, -15 }, { 32, -15 }, + { 34, -21 }, { 39, -23 }, { 42, -33 }, { 41, -31 }, + { 46, -28 }, { 38, -12 }, { 21, 29 }, { 45, -24 }, + { 53, -45 }, { 48, -26 }, { 65, -43 }, { 43, -19 }, + { 39, -10 }, { 30, 9 }, { 18, 26 }, { 20, 27 }, + { 0, 57 }, { -14, 82 }, { -5, 75 }, { -19, 97 }, + { -35, 125 }, { 27, 0 }, { 28, 0 }, { 31, -4 }, + { 27, 6 }, { 34, 8 }, { 30, 10 }, { 24, 22 }, + { 33, 19 }, { 22, 32 }, { 26, 31 }, { 21, 41 }, + { 26, 44 }, { 23, 47 }, { 16, 65 }, { 14, 71 }, + { 14, 11 }, { 11, 14 }, { 9, 11 }, { 18, 11 }, + { 21, 9 }, { 23, -2 }, { 32, -15 }, { 32, -15 }, + { 34, -21 }, { 39, -23 }, { 42, -33 }, { 41, -31 }, + { 46, -28 }, { 38, -12 }, { 21, 29 }, { 45, -24 }, + { 53, -45 }, { 48, -26 }, { 65, -43 }, { 43, -19 }, + { 39, -10 }, { 30, 9 }, { 18, 26 }, { 20, 27 }, + { 0, 57 }, { -14, 82 }, { -5, 75 }, { -19, 97 }, + { -35, 125 }, { 27, 0 }, { 28, 0 }, { 31, -4 }, + { 27, 6 }, { 34, 8 }, { 30, 10 }, { 24, 22 }, + { 33, 19 }, { 22, 32 }, { 26, 31 }, { 21, 41 }, + { 26, 44 }, { 23, 47 }, { 16, 65 }, { 14, 71 }, + { -6, 76 }, { -2, 44 }, { 0, 45 }, { 0, 52 }, + { -3, 64 }, { -2, 59 }, { -4, 70 }, { -4, 75 }, + { -8, 82 }, { -17, 102 }, { -9, 77 }, { 3, 24 }, + { 0, 42 }, { 0, 48 }, { 0, 55 }, { -6, 59 }, + { -7, 71 }, { -12, 83 }, { -11, 87 }, { -30, 119 }, + { 1, 58 }, { -3, 29 }, { -1, 36 }, { 1, 38 }, + { 2, 43 }, { -6, 55 }, { 0, 58 }, { 0, 64 }, + { -3, 74 }, { -10, 90 }, { -6, 76 }, { -2, 44 }, + { 0, 45 }, { 0, 52 }, { -3, 64 }, { -2, 59 }, + { -4, 70 }, { -4, 75 }, { -8, 82 }, { -17, 102 }, + { -9, 77 }, { 3, 24 }, { 0, 42 }, { 0, 48 }, + { 0, 55 }, { -6, 59 }, { -7, 71 }, { -12, 83 }, + { -11, 87 }, { -30, 119 }, { 1, 58 }, { -3, 29 }, + { -1, 36 }, { 1, 38 }, { 2, 43 }, { -6, 55 }, + { 0, 58 }, { 0, 64 }, { -3, 74 }, { -10, 90 }, + { -3, 74 }, { -9, 92 }, { -8, 87 }, { -23, 126 }, + { -3, 74 }, { -9, 92 }, { -8, 87 }, { -23, 126 }, + { -3, 74 }, { -9, 92 }, { -8, 87 }, { -23, 126 } + }, + + /* i_cabac_init_idc == 1 */ + { + /* 0 - 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 - 23 */ + { 22, 25 }, { 34, 0 }, { 16, 0 }, { -2, 9 }, + { 4, 41 }, { -29, 118 }, { 2, 65 }, { -6, 71 }, + { -13, 79 }, { 5, 52 }, { 9, 50 }, { -3, 70 }, + { 10, 54 }, + + /* 24 - 39 */ + { 26, 34 }, { 19, 22 }, { 40, 0 }, { 57, 2 }, + { 41, 36 }, { 26, 69 }, { -45, 127 }, { -15, 101 }, + { -4, 76 }, { -6, 71 }, { -13, 79 }, { 5, 52 }, + { 6, 69 }, { -13, 90 }, { 0, 52 }, { 8, 43 }, + + /* 40 - 53 */ + { -2, 69 },{ -5, 82 },{ -10, 96 },{ 2, 59 }, + { 2, 75 },{ -3, 87 },{ -3, 100 },{ 1, 56 }, + { -3, 74 },{ -6, 85 },{ 0, 59 },{ -3, 81 }, + { -7, 86 },{ -5, 95 }, + + /* 54 - 59 */ + { -1, 66 },{ -1, 77 },{ 1, 70 },{ -2, 86 }, + { -5, 72 },{ 0, 61 }, + + /* 60 - 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 - 104 */ + { 13, 15 }, { 7, 51 }, { 2, 80 }, { -39, 127 }, + { -18, 91 }, { -17, 96 }, { -26, 81 }, { -35, 98 }, + { -24, 102 }, { -23, 97 }, { -27, 119 }, { -24, 99 }, + { -21, 110 }, { -18, 102 }, { -36, 127 }, { 0, 80 }, + { -5, 89 }, { -7, 94 }, { -4, 92 }, { 0, 39 }, + { 0, 65 }, { -15, 84 }, { -35, 127 }, { -2, 73 }, + { -12, 104 }, { -9, 91 }, { -31, 127 }, { 3, 55 }, + { 7, 56 }, { 7, 55 }, { 8, 61 }, { -3, 53 }, + { 0, 68 }, { -7, 74 }, { -9, 88 }, + + /* 105 -> 165 */ + { -13, 103 }, { -13, 91 }, { -9, 89 }, { -14, 92 }, + { -8, 76 }, { -12, 87 }, { -23, 110 }, { -24, 105 }, + { -10, 78 }, { -20, 112 }, { -17, 99 }, { -78, 127 }, + { -70, 127 }, { -50, 127 }, { -46, 127 }, { -4, 66 }, + { -5, 78 }, { -4, 71 }, { -8, 72 }, { 2, 59 }, + { -1, 55 }, { -7, 70 }, { -6, 75 }, { -8, 89 }, + { -34, 119 }, { -3, 75 }, { 32, 20 }, { 30, 22 }, + { -44, 127 }, { 0, 54 }, { -5, 61 }, { 0, 58 }, + { -1, 60 }, { -3, 61 }, { -8, 67 }, { -25, 84 }, + { -14, 74 }, { -5, 65 }, { 5, 52 }, { 2, 57 }, + { 0, 61 }, { -9, 69 }, { -11, 70 }, { 18, 55 }, + { -4, 71 }, { 0, 58 }, { 7, 61 }, { 9, 41 }, + { 18, 25 }, { 9, 32 }, { 5, 43 }, { 9, 47 }, + { 0, 44 }, { 0, 51 }, { 2, 46 }, { 19, 38 }, + { -4, 66 }, { 15, 38 }, { 12, 42 }, { 9, 34 }, + { 0, 89 }, + + /* 166 - 226 */ + { 4, 45 }, { 10, 28 }, { 10, 31 }, { 33, -11 }, + { 52, -43 }, { 18, 15 }, { 28, 0 }, { 35, -22 }, + { 38, -25 }, { 34, 0 }, { 39, -18 }, { 32, -12 }, + { 102, -94 }, { 0, 0 }, { 56, -15 }, { 33, -4 }, + { 29, 10 }, { 37, -5 }, { 51, -29 }, { 39, -9 }, + { 52, -34 }, { 69, -58 }, { 67, -63 }, { 44, -5 }, + { 32, 7 }, { 55, -29 }, { 32, 1 }, { 0, 0 }, + { 27, 36 }, { 33, -25 }, { 34, -30 }, { 36, -28 }, + { 38, -28 }, { 38, -27 }, { 34, -18 }, { 35, -16 }, + { 34, -14 }, { 32, -8 }, { 37, -6 }, { 35, 0 }, + { 30, 10 }, { 28, 18 }, { 26, 25 }, { 29, 41 }, + { 0, 75 }, { 2, 72 }, { 8, 77 }, { 14, 35 }, + { 18, 31 }, { 17, 35 }, { 21, 30 }, { 17, 45 }, + { 20, 42 }, { 18, 45 }, { 27, 26 }, { 16, 54 }, + { 7, 66 }, { 16, 56 }, { 11, 73 }, { 10, 67 }, + { -10, 116 }, + + /* 227 - 275 */ + { -23, 112 }, { -15, 71 }, { -7, 61 }, { 0, 53 }, + { -5, 66 }, { -11, 77 }, { -9, 80 }, { -9, 84 }, + { -10, 87 }, { -34, 127 }, { -21, 101 }, { -3, 39 }, + { -5, 53 }, { -7, 61 }, { -11, 75 }, { -15, 77 }, + { -17, 91 }, { -25, 107 }, { -25, 111 }, { -28, 122 }, + { -11, 76 }, { -10, 44 }, { -10, 52 }, { -10, 57 }, + { -9, 58 }, { -16, 72 }, { -7, 69 }, { -4, 69 }, + { -5, 74 }, { -9, 86 }, { 2, 66 }, { -9, 34 }, + { 1, 32 }, { 11, 31 }, { 5, 52 }, { -2, 55 }, + { -2, 67 }, { 0, 73 }, { -8, 89 }, { 3, 52 }, + { 7, 4 }, { 10, 8 }, { 17, 8 }, { 16, 19 }, + { 3, 37 }, { -1, 61 }, { -5, 73 }, { -1, 70 }, + { -4, 78 }, + + /* 276 a bit special (not used, bypass is used instead) */ + { 0, 0 }, + + /* 277 - 337 */ + { -21, 126 }, { -23, 124 }, { -20, 110 }, { -26, 126 }, + { -25, 124 }, { -17, 105 }, { -27, 121 }, { -27, 117 }, + { -17, 102 }, { -26, 117 }, { -27, 116 }, { -33, 122 }, + { -10, 95 }, { -14, 100 }, { -8, 95 }, { -17, 111 }, + { -28, 114 }, { -6, 89 }, { -2, 80 }, { -4, 82 }, + { -9, 85 }, { -8, 81 }, { -1, 72 }, { 5, 64 }, + { 1, 67 }, { 9, 56 }, { 0, 69 }, { 1, 69 }, + { 7, 69 }, { -7, 69 }, { -6, 67 }, { -16, 77 }, + { -2, 64 }, { 2, 61 }, { -6, 67 }, { -3, 64 }, + { 2, 57 }, { -3, 65 }, { -3, 66 }, { 0, 62 }, + { 9, 51 }, { -1, 66 }, { -2, 71 }, { -2, 75 }, + { -1, 70 }, { -9, 72 }, { 14, 60 }, { 16, 37 }, + { 0, 47 }, { 18, 35 }, { 11, 37 }, { 12, 41 }, + { 10, 41 }, { 2, 48 }, { 12, 41 }, { 13, 41 }, + { 0, 59 }, { 3, 50 }, { 19, 40 }, { 3, 66 }, + { 18, 50 }, + + /* 338 - 398 */ + { 19, -6 }, { 18, -6 }, { 14, 0 }, { 26, -12 }, + { 31, -16 }, { 33, -25 }, { 33, -22 }, { 37, -28 }, + { 39, -30 }, { 42, -30 }, { 47, -42 }, { 45, -36 }, + { 49, -34 }, { 41, -17 }, { 32, 9 }, { 69, -71 }, + { 63, -63 }, { 66, -64 }, { 77, -74 }, { 54, -39 }, + { 52, -35 }, { 41, -10 }, { 36, 0 }, { 40, -1 }, + { 30, 14 }, { 28, 26 }, { 23, 37 }, { 12, 55 }, + { 11, 65 }, { 37, -33 }, { 39, -36 }, { 40, -37 }, + { 38, -30 }, { 46, -33 }, { 42, -30 }, { 40, -24 }, + { 49, -29 }, { 38, -12 }, { 40, -10 }, { 38, -3 }, + { 46, -5 }, { 31, 20 }, { 29, 30 }, { 25, 44 }, + { 12, 48 }, { 11, 49 }, { 26, 45 }, { 22, 22 }, + { 23, 22 }, { 27, 21 }, { 33, 20 }, { 26, 28 }, + { 30, 24 }, { 27, 34 }, { 18, 42 }, { 25, 39 }, + { 18, 50 }, { 12, 70 }, { 21, 54 }, { 14, 71 }, + { 11, 83 }, + + /* 399 - 435 */ + { 25, 32 }, { 21, 49 }, { 21, 54 }, + { -5, 85 }, { -6, 81 }, { -10, 77 }, { -7, 81 }, + { -17, 80 }, { -18, 73 }, { -4, 74 }, { -10, 83 }, + { -9, 71 }, { -9, 67 }, { -1, 61 }, { -8, 66 }, + { -14, 66 }, { 0, 59 }, { 2, 59 }, { 17, -10 }, + { 32, -13 }, { 42, -9 }, { 49, -5 }, { 53, 0 }, + { 64, 3 }, { 68, 10 }, { 66, 27 }, { 47, 57 }, + { -5, 71 }, { 0, 24 }, { -1, 36 }, { -2, 42 }, + { -2, 52 }, { -9, 57 }, { -6, 63 }, { -4, 65 }, + { -4, 67 }, { -7, 82 }, + + /* 436 - 459 */ + { -3, 81 }, { -3, 76 }, { -7, 72 }, { -6, 78 }, + { -12, 72 }, { -14, 68 }, { -3, 70 }, { -6, 76 }, + { -5, 66 }, { -5, 62 }, { 0, 57 }, { -4, 61 }, + { -9, 60 }, { 1, 54 }, { 2, 58 }, { 17, -10 }, + { 32, -13 }, { 42, -9 }, { 49, -5 }, { 53, 0 }, + { 64, 3 }, { 68, 10 }, { 66, 27 }, { 47, 57 }, + + /* 460 - 1024 */ + { 0, 80 }, { -5, 89 }, { -7, 94 }, { -4, 92 }, + { 0, 39 }, { 0, 65 }, { -15, 84 }, { -35, 127 }, + { -2, 73 }, { -12, 104 }, { -9, 91 }, { -31, 127 }, + { 0, 80 }, { -5, 89 }, { -7, 94 }, { -4, 92 }, + { 0, 39 }, { 0, 65 }, { -15, 84 }, { -35, 127 }, + { -2, 73 }, { -12, 104 }, { -9, 91 }, { -31, 127 }, + { -13, 103 }, { -13, 91 }, { -9, 89 }, { -14, 92 }, + { -8, 76 }, { -12, 87 }, { -23, 110 }, { -24, 105 }, + { -10, 78 }, { -20, 112 }, { -17, 99 }, { -78, 127 }, + { -70, 127 }, { -50, 127 }, { -46, 127 }, { -4, 66 }, + { -5, 78 }, { -4, 71 }, { -8, 72 }, { 2, 59 }, + { -1, 55 }, { -7, 70 }, { -6, 75 }, { -8, 89 }, + { -34, 119 }, { -3, 75 }, { 32, 20 }, { 30, 22 }, + { -44, 127 }, { 0, 54 }, { -5, 61 }, { 0, 58 }, + { -1, 60 }, { -3, 61 }, { -8, 67 }, { -25, 84 }, + { -14, 74 }, { -5, 65 }, { 5, 52 }, { 2, 57 }, + { 0, 61 }, { -9, 69 }, { -11, 70 }, { 18, 55 }, + { -13, 103 }, { -13, 91 }, { -9, 89 }, { -14, 92 }, + { -8, 76 }, { -12, 87 }, { -23, 110 }, { -24, 105 }, + { -10, 78 }, { -20, 112 }, { -17, 99 }, { -78, 127 }, + { -70, 127 }, { -50, 127 }, { -46, 127 }, { -4, 66 }, + { -5, 78 }, { -4, 71 }, { -8, 72 }, { 2, 59 }, + { -1, 55 }, { -7, 70 }, { -6, 75 }, { -8, 89 }, + { -34, 119 }, { -3, 75 }, { 32, 20 }, { 30, 22 }, + { -44, 127 }, { 0, 54 }, { -5, 61 }, { 0, 58 }, + { -1, 60 }, { -3, 61 }, { -8, 67 }, { -25, 84 }, + { -14, 74 }, { -5, 65 }, { 5, 52 }, { 2, 57 }, + { 0, 61 }, { -9, 69 }, { -11, 70 }, { 18, 55 }, + { 4, 45 }, { 10, 28 }, { 10, 31 }, { 33, -11 }, + { 52, -43 }, { 18, 15 }, { 28, 0 }, { 35, -22 }, + { 38, -25 }, { 34, 0 }, { 39, -18 }, { 32, -12 }, + { 102, -94 }, { 0, 0 }, { 56, -15 }, { 33, -4 }, + { 29, 10 }, { 37, -5 }, { 51, -29 }, { 39, -9 }, + { 52, -34 }, { 69, -58 }, { 67, -63 }, { 44, -5 }, + { 32, 7 }, { 55, -29 }, { 32, 1 }, { 0, 0 }, + { 27, 36 }, { 33, -25 }, { 34, -30 }, { 36, -28 }, + { 38, -28 }, { 38, -27 }, { 34, -18 }, { 35, -16 }, + { 34, -14 }, { 32, -8 }, { 37, -6 }, { 35, 0 }, + { 30, 10 }, { 28, 18 }, { 26, 25 }, { 29, 41 }, + { 4, 45 }, { 10, 28 }, { 10, 31 }, { 33, -11 }, + { 52, -43 }, { 18, 15 }, { 28, 0 }, { 35, -22 }, + { 38, -25 }, { 34, 0 }, { 39, -18 }, { 32, -12 }, + { 102, -94 }, { 0, 0 }, { 56, -15 }, { 33, -4 }, + { 29, 10 }, { 37, -5 }, { 51, -29 }, { 39, -9 }, + { 52, -34 }, { 69, -58 }, { 67, -63 }, { 44, -5 }, + { 32, 7 }, { 55, -29 }, { 32, 1 }, { 0, 0 }, + { 27, 36 }, { 33, -25 }, { 34, -30 }, { 36, -28 }, + { 38, -28 }, { 38, -27 }, { 34, -18 }, { 35, -16 }, + { 34, -14 }, { 32, -8 }, { 37, -6 }, { 35, 0 }, + { 30, 10 }, { 28, 18 }, { 26, 25 }, { 29, 41 }, + { -5, 85 }, { -6, 81 }, { -10, 77 }, { -7, 81 }, + { -17, 80 }, { -18, 73 }, { -4, 74 }, { -10, 83 }, + { -9, 71 }, { -9, 67 }, { -1, 61 }, { -8, 66 }, + { -14, 66 }, { 0, 59 }, { 2, 59 }, { -3, 81 }, + { -3, 76 }, { -7, 72 }, { -6, 78 }, { -12, 72 }, + { -14, 68 }, { -3, 70 }, { -6, 76 }, { -5, 66 }, + { -5, 62 }, { 0, 57 }, { -4, 61 }, { -9, 60 }, + { 1, 54 }, { 2, 58 }, { 17, -10 }, { 32, -13 }, + { 42, -9 }, { 49, -5 }, { 53, 0 }, { 64, 3 }, + { 68, 10 }, { 66, 27 }, { 47, 57 }, { 17, -10 }, + { 32, -13 }, { 42, -9 }, { 49, -5 }, { 53, 0 }, + { 64, 3 }, { 68, 10 }, { 66, 27 }, { 47, 57 }, + { -5, 71 }, { 0, 24 }, { -1, 36 }, { -2, 42 }, + { -2, 52 }, { -9, 57 }, { -6, 63 }, { -4, 65 }, + { -4, 67 }, { -7, 82 }, { -5, 85 }, { -6, 81 }, + { -10, 77 }, { -7, 81 }, { -17, 80 }, { -18, 73 }, + { -4, 74 }, { -10, 83 }, { -9, 71 }, { -9, 67 }, + { -1, 61 }, { -8, 66 }, { -14, 66 }, { 0, 59 }, + { 2, 59 }, { -3, 81 }, { -3, 76 }, { -7, 72 }, + { -6, 78 }, { -12, 72 }, { -14, 68 }, { -3, 70 }, + { -6, 76 }, { -5, 66 }, { -5, 62 }, { 0, 57 }, + { -4, 61 }, { -9, 60 }, { 1, 54 }, { 2, 58 }, + { 17, -10 }, { 32, -13 }, { 42, -9 }, { 49, -5 }, + { 53, 0 }, { 64, 3 }, { 68, 10 }, { 66, 27 }, + { 47, 57 }, { 17, -10 }, { 32, -13 }, { 42, -9 }, + { 49, -5 }, { 53, 0 }, { 64, 3 }, { 68, 10 }, + { 66, 27 }, { 47, 57 }, { -5, 71 }, { 0, 24 }, + { -1, 36 }, { -2, 42 }, { -2, 52 }, { -9, 57 }, + { -6, 63 }, { -4, 65 }, { -4, 67 }, { -7, 82 }, + { -21, 126 }, { -23, 124 }, { -20, 110 }, { -26, 126 }, + { -25, 124 }, { -17, 105 }, { -27, 121 }, { -27, 117 }, + { -17, 102 }, { -26, 117 }, { -27, 116 }, { -33, 122 }, + { -10, 95 }, { -14, 100 }, { -8, 95 }, { -17, 111 }, + { -28, 114 }, { -6, 89 }, { -2, 80 }, { -4, 82 }, + { -9, 85 }, { -8, 81 }, { -1, 72 }, { 5, 64 }, + { 1, 67 }, { 9, 56 }, { 0, 69 }, { 1, 69 }, + { 7, 69 }, { -7, 69 }, { -6, 67 }, { -16, 77 }, + { -2, 64 }, { 2, 61 }, { -6, 67 }, { -3, 64 }, + { 2, 57 }, { -3, 65 }, { -3, 66 }, { 0, 62 }, + { 9, 51 }, { -1, 66 }, { -2, 71 }, { -2, 75 }, + { -21, 126 }, { -23, 124 }, { -20, 110 }, { -26, 126 }, + { -25, 124 }, { -17, 105 }, { -27, 121 }, { -27, 117 }, + { -17, 102 }, { -26, 117 }, { -27, 116 }, { -33, 122 }, + { -10, 95 }, { -14, 100 }, { -8, 95 }, { -17, 111 }, + { -28, 114 }, { -6, 89 }, { -2, 80 }, { -4, 82 }, + { -9, 85 }, { -8, 81 }, { -1, 72 }, { 5, 64 }, + { 1, 67 }, { 9, 56 }, { 0, 69 }, { 1, 69 }, + { 7, 69 }, { -7, 69 }, { -6, 67 }, { -16, 77 }, + { -2, 64 }, { 2, 61 }, { -6, 67 }, { -3, 64 }, + { 2, 57 }, { -3, 65 }, { -3, 66 }, { 0, 62 }, + { 9, 51 }, { -1, 66 }, { -2, 71 }, { -2, 75 }, + { 19, -6 }, { 18, -6 }, { 14, 0 }, { 26, -12 }, + { 31, -16 }, { 33, -25 }, { 33, -22 }, { 37, -28 }, + { 39, -30 }, { 42, -30 }, { 47, -42 }, { 45, -36 }, + { 49, -34 }, { 41, -17 }, { 32, 9 }, { 69, -71 }, + { 63, -63 }, { 66, -64 }, { 77, -74 }, { 54, -39 }, + { 52, -35 }, { 41, -10 }, { 36, 0 }, { 40, -1 }, + { 30, 14 }, { 28, 26 }, { 23, 37 }, { 12, 55 }, + { 11, 65 }, { 37, -33 }, { 39, -36 }, { 40, -37 }, + { 38, -30 }, { 46, -33 }, { 42, -30 }, { 40, -24 }, + { 49, -29 }, { 38, -12 }, { 40, -10 }, { 38, -3 }, + { 46, -5 }, { 31, 20 }, { 29, 30 }, { 25, 44 }, + { 19, -6 }, { 18, -6 }, { 14, 0 }, { 26, -12 }, + { 31, -16 }, { 33, -25 }, { 33, -22 }, { 37, -28 }, + { 39, -30 }, { 42, -30 }, { 47, -42 }, { 45, -36 }, + { 49, -34 }, { 41, -17 }, { 32, 9 }, { 69, -71 }, + { 63, -63 }, { 66, -64 }, { 77, -74 }, { 54, -39 }, + { 52, -35 }, { 41, -10 }, { 36, 0 }, { 40, -1 }, + { 30, 14 }, { 28, 26 }, { 23, 37 }, { 12, 55 }, + { 11, 65 }, { 37, -33 }, { 39, -36 }, { 40, -37 }, + { 38, -30 }, { 46, -33 }, { 42, -30 }, { 40, -24 }, + { 49, -29 }, { 38, -12 }, { 40, -10 }, { 38, -3 }, + { 46, -5 }, { 31, 20 }, { 29, 30 }, { 25, 44 }, + { -23, 112 }, { -15, 71 }, { -7, 61 }, { 0, 53 }, + { -5, 66 }, { -11, 77 }, { -9, 80 }, { -9, 84 }, + { -10, 87 }, { -34, 127 }, { -21, 101 }, { -3, 39 }, + { -5, 53 }, { -7, 61 }, { -11, 75 }, { -15, 77 }, + { -17, 91 }, { -25, 107 }, { -25, 111 }, { -28, 122 }, + { -11, 76 }, { -10, 44 }, { -10, 52 }, { -10, 57 }, + { -9, 58 }, { -16, 72 }, { -7, 69 }, { -4, 69 }, + { -5, 74 }, { -9, 86 }, { -23, 112 }, { -15, 71 }, + { -7, 61 }, { 0, 53 }, { -5, 66 }, { -11, 77 }, + { -9, 80 }, { -9, 84 }, { -10, 87 }, { -34, 127 }, + { -21, 101 }, { -3, 39 }, { -5, 53 }, { -7, 61 }, + { -11, 75 }, { -15, 77 }, { -17, 91 }, { -25, 107 }, + { -25, 111 }, { -28, 122 }, { -11, 76 }, { -10, 44 }, + { -10, 52 }, { -10, 57 }, { -9, 58 }, { -16, 72 }, + { -7, 69 }, { -4, 69 }, { -5, 74 }, { -9, 86 }, + { -2, 73 }, { -12, 104 }, { -9, 91 }, { -31, 127 }, + { -2, 73 }, { -12, 104 }, { -9, 91 }, { -31, 127 }, + { -2, 73 }, { -12, 104 }, { -9, 91 }, { -31, 127 } + }, + + /* i_cabac_init_idc == 2 */ + { + /* 0 - 10 */ + { 20, -15 }, { 2, 54 }, { 3, 74 }, { 20, -15 }, + { 2, 54 }, { 3, 74 }, { -28, 127 }, { -23, 104 }, + { -6, 53 }, { -1, 54 }, { 7, 51 }, + + /* 11 - 23 */ + { 29, 16 }, { 25, 0 }, { 14, 0 }, { -10, 51 }, + { -3, 62 }, { -27, 99 }, { 26, 16 }, { -4, 85 }, + { -24, 102 }, { 5, 57 }, { 6, 57 }, { -17, 73 }, + { 14, 57 }, + + /* 24 - 39 */ + { 20, 40 }, { 20, 10 }, { 29, 0 }, { 54, 0 }, + { 37, 42 }, { 12, 97 }, { -32, 127 }, { -22, 117 }, + { -2, 74 }, { -4, 85 }, { -24, 102 }, { 5, 57 }, + { -6, 93 }, { -14, 88 }, { -6, 44 }, { 4, 55 }, + + /* 40 - 53 */ + { -11, 89 },{ -15, 103 },{ -21, 116 },{ 19, 57 }, + { 20, 58 },{ 4, 84 },{ 6, 96 },{ 1, 63 }, + { -5, 85 },{ -13, 106 },{ 5, 63 },{ 6, 75 }, + { -3, 90 },{ -1, 101 }, + + /* 54 - 59 */ + { 3, 55 },{ -4, 79 },{ -2, 75 },{ -12, 97 }, + { -7, 50 },{ 1, 60 }, + + /* 60 - 69 */ + { 0, 41 }, { 0, 63 }, { 0, 63 }, { 0, 63 }, + { -9, 83 }, { 4, 86 }, { 0, 97 }, { -7, 72 }, + { 13, 41 }, { 3, 62 }, + + /* 70 - 104 */ + { 7, 34 }, { -9, 88 }, { -20, 127 }, { -36, 127 }, + { -17, 91 }, { -14, 95 }, { -25, 84 }, { -25, 86 }, + { -12, 89 }, { -17, 91 }, { -31, 127 }, { -14, 76 }, + { -18, 103 }, { -13, 90 }, { -37, 127 }, { 11, 80 }, + { 5, 76 }, { 2, 84 }, { 5, 78 }, { -6, 55 }, + { 4, 61 }, { -14, 83 }, { -37, 127 }, { -5, 79 }, + { -11, 104 }, { -11, 91 }, { -30, 127 }, { 0, 65 }, + { -2, 79 }, { 0, 72 }, { -4, 92 }, { -6, 56 }, + { 3, 68 }, { -8, 71 }, { -13, 98 }, + + /* 105 -> 165 */ + { -4, 86 }, { -12, 88 }, { -5, 82 }, { -3, 72 }, + { -4, 67 }, { -8, 72 }, { -16, 89 }, { -9, 69 }, + { -1, 59 }, { 5, 66 }, { 4, 57 }, { -4, 71 }, + { -2, 71 }, { 2, 58 }, { -1, 74 }, { -4, 44 }, + { -1, 69 }, { 0, 62 }, { -7, 51 }, { -4, 47 }, + { -6, 42 }, { -3, 41 }, { -6, 53 }, { 8, 76 }, + { -9, 78 }, { -11, 83 }, { 9, 52 }, { 0, 67 }, + { -5, 90 }, { 1, 67 }, { -15, 72 }, { -5, 75 }, + { -8, 80 }, { -21, 83 }, { -21, 64 }, { -13, 31 }, + { -25, 64 }, { -29, 94 }, { 9, 75 }, { 17, 63 }, + { -8, 74 }, { -5, 35 }, { -2, 27 }, { 13, 91 }, + { 3, 65 }, { -7, 69 }, { 8, 77 }, { -10, 66 }, + { 3, 62 }, { -3, 68 }, { -20, 81 }, { 0, 30 }, + { 1, 7 }, { -3, 23 }, { -21, 74 }, { 16, 66 }, + { -23, 124 }, { 17, 37 }, { 44, -18 }, { 50, -34 }, + { -22, 127 }, + + /* 166 - 226 */ + { 4, 39 }, { 0, 42 }, { 7, 34 }, { 11, 29 }, + { 8, 31 }, { 6, 37 }, { 7, 42 }, { 3, 40 }, + { 8, 33 }, { 13, 43 }, { 13, 36 }, { 4, 47 }, + { 3, 55 }, { 2, 58 }, { 6, 60 }, { 8, 44 }, + { 11, 44 }, { 14, 42 }, { 7, 48 }, { 4, 56 }, + { 4, 52 }, { 13, 37 }, { 9, 49 }, { 19, 58 }, + { 10, 48 }, { 12, 45 }, { 0, 69 }, { 20, 33 }, + { 8, 63 }, { 35, -18 }, { 33, -25 }, { 28, -3 }, + { 24, 10 }, { 27, 0 }, { 34, -14 }, { 52, -44 }, + { 39, -24 }, { 19, 17 }, { 31, 25 }, { 36, 29 }, + { 24, 33 }, { 34, 15 }, { 30, 20 }, { 22, 73 }, + { 20, 34 }, { 19, 31 }, { 27, 44 }, { 19, 16 }, + { 15, 36 }, { 15, 36 }, { 21, 28 }, { 25, 21 }, + { 30, 20 }, { 31, 12 }, { 27, 16 }, { 24, 42 }, + { 0, 93 }, { 14, 56 }, { 15, 57 }, { 26, 38 }, + { -24, 127 }, + + /* 227 - 275 */ + { -24, 115 }, { -22, 82 }, { -9, 62 }, { 0, 53 }, + { 0, 59 }, { -14, 85 }, { -13, 89 }, { -13, 94 }, + { -11, 92 }, { -29, 127 }, { -21, 100 }, { -14, 57 }, + { -12, 67 }, { -11, 71 }, { -10, 77 }, { -21, 85 }, + { -16, 88 }, { -23, 104 }, { -15, 98 }, { -37, 127 }, + { -10, 82 }, { -8, 48 }, { -8, 61 }, { -8, 66 }, + { -7, 70 }, { -14, 75 }, { -10, 79 }, { -9, 83 }, + { -12, 92 }, { -18, 108 }, { -4, 79 }, { -22, 69 }, + { -16, 75 }, { -2, 58 }, { 1, 58 }, { -13, 78 }, + { -9, 83 }, { -4, 81 }, { -13, 99 }, { -13, 81 }, + { -6, 38 }, { -13, 62 }, { -6, 58 }, { -2, 59 }, + { -16, 73 }, { -10, 76 }, { -13, 86 }, { -9, 83 }, + { -10, 87 }, + + /* 276 a bit special (not used, bypass is used instead) */ + { 0, 0 }, + + /* 277 - 337 */ + { -22, 127 }, { -25, 127 }, { -25, 120 }, { -27, 127 }, + { -19, 114 }, { -23, 117 }, { -25, 118 }, { -26, 117 }, + { -24, 113 }, { -28, 118 }, { -31, 120 }, { -37, 124 }, + { -10, 94 }, { -15, 102 }, { -10, 99 }, { -13, 106 }, + { -50, 127 }, { -5, 92 }, { 17, 57 }, { -5, 86 }, + { -13, 94 }, { -12, 91 }, { -2, 77 }, { 0, 71 }, + { -1, 73 }, { 4, 64 }, { -7, 81 }, { 5, 64 }, + { 15, 57 }, { 1, 67 }, { 0, 68 }, { -10, 67 }, + { 1, 68 }, { 0, 77 }, { 2, 64 }, { 0, 68 }, + { -5, 78 }, { 7, 55 }, { 5, 59 }, { 2, 65 }, + { 14, 54 }, { 15, 44 }, { 5, 60 }, { 2, 70 }, + { -2, 76 }, { -18, 86 }, { 12, 70 }, { 5, 64 }, + { -12, 70 }, { 11, 55 }, { 5, 56 }, { 0, 69 }, + { 2, 65 }, { -6, 74 }, { 5, 54 }, { 7, 54 }, + { -6, 76 }, { -11, 82 }, { -2, 77 }, { -2, 77 }, + { 25, 42 }, + + /* 338 - 398 */ + { 17, -13 }, { 16, -9 }, { 17, -12 }, { 27, -21 }, + { 37, -30 }, { 41, -40 }, { 42, -41 }, { 48, -47 }, + { 39, -32 }, { 46, -40 }, { 52, -51 }, { 46, -41 }, + { 52, -39 }, { 43, -19 }, { 32, 11 }, { 61, -55 }, + { 56, -46 }, { 62, -50 }, { 81, -67 }, { 45, -20 }, + { 35, -2 }, { 28, 15 }, { 34, 1 }, { 39, 1 }, + { 30, 17 }, { 20, 38 }, { 18, 45 }, { 15, 54 }, + { 0, 79 }, { 36, -16 }, { 37, -14 }, { 37, -17 }, + { 32, 1 }, { 34, 15 }, { 29, 15 }, { 24, 25 }, + { 34, 22 }, { 31, 16 }, { 35, 18 }, { 31, 28 }, + { 33, 41 }, { 36, 28 }, { 27, 47 }, { 21, 62 }, + { 18, 31 }, { 19, 26 }, { 36, 24 }, { 24, 23 }, + { 27, 16 }, { 24, 30 }, { 31, 29 }, { 22, 41 }, + { 22, 42 }, { 16, 60 }, { 15, 52 }, { 14, 60 }, + { 3, 78 }, { -16, 123 }, { 21, 53 }, { 22, 56 }, + { 25, 61 }, + + /* 399 - 435 */ + { 21, 33 }, { 19, 50 }, { 17, 61 }, + { -3, 78 }, { -8, 74 }, { -9, 72 }, { -10, 72 }, + { -18, 75 }, { -12, 71 }, { -11, 63 }, { -5, 70 }, + { -17, 75 }, { -14, 72 }, { -16, 67 }, { -8, 53 }, + { -14, 59 }, { -9, 52 }, { -11, 68 }, { 9, -2 }, + { 30, -10 }, { 31, -4 }, { 33, -1 }, { 33, 7 }, + { 31, 12 }, { 37, 23 }, { 31, 38 }, { 20, 64 }, + { -9, 71 }, { -7, 37 }, { -8, 44 }, { -11, 49 }, + { -10, 56 }, { -12, 59 }, { -8, 63 }, { -9, 67 }, + { -6, 68 }, { -10, 79 }, + + /* 436 - 459 */ + { -3, 78 }, { -8, 74 }, { -9, 72 }, { -10, 72 }, + { -18, 75 }, { -12, 71 }, { -11, 63 }, { -5, 70 }, + { -17, 75 }, { -14, 72 }, { -16, 67 }, { -8, 53 }, + { -14, 59 }, { -9, 52 }, { -11, 68 }, { 9, -2 }, + { 30, -10 }, { 31, -4 }, { 33, -1 }, { 33, 7 }, + { 31, 12 }, { 37, 23 }, { 31, 38 }, { 20, 64 }, + + /* 460 - 1024 */ + { 11, 80 }, { 5, 76 }, { 2, 84 }, { 5, 78 }, + { -6, 55 }, { 4, 61 }, { -14, 83 }, { -37, 127 }, + { -5, 79 }, { -11, 104 }, { -11, 91 }, { -30, 127 }, + { 11, 80 }, { 5, 76 }, { 2, 84 }, { 5, 78 }, + { -6, 55 }, { 4, 61 }, { -14, 83 }, { -37, 127 }, + { -5, 79 }, { -11, 104 }, { -11, 91 }, { -30, 127 }, + { -4, 86 }, { -12, 88 }, { -5, 82 }, { -3, 72 }, + { -4, 67 }, { -8, 72 }, { -16, 89 }, { -9, 69 }, + { -1, 59 }, { 5, 66 }, { 4, 57 }, { -4, 71 }, + { -2, 71 }, { 2, 58 }, { -1, 74 }, { -4, 44 }, + { -1, 69 }, { 0, 62 }, { -7, 51 }, { -4, 47 }, + { -6, 42 }, { -3, 41 }, { -6, 53 }, { 8, 76 }, + { -9, 78 }, { -11, 83 }, { 9, 52 }, { 0, 67 }, + { -5, 90 }, { 1, 67 }, { -15, 72 }, { -5, 75 }, + { -8, 80 }, { -21, 83 }, { -21, 64 }, { -13, 31 }, + { -25, 64 }, { -29, 94 }, { 9, 75 }, { 17, 63 }, + { -8, 74 }, { -5, 35 }, { -2, 27 }, { 13, 91 }, + { -4, 86 }, { -12, 88 }, { -5, 82 }, { -3, 72 }, + { -4, 67 }, { -8, 72 }, { -16, 89 }, { -9, 69 }, + { -1, 59 }, { 5, 66 }, { 4, 57 }, { -4, 71 }, + { -2, 71 }, { 2, 58 }, { -1, 74 }, { -4, 44 }, + { -1, 69 }, { 0, 62 }, { -7, 51 }, { -4, 47 }, + { -6, 42 }, { -3, 41 }, { -6, 53 }, { 8, 76 }, + { -9, 78 }, { -11, 83 }, { 9, 52 }, { 0, 67 }, + { -5, 90 }, { 1, 67 }, { -15, 72 }, { -5, 75 }, + { -8, 80 }, { -21, 83 }, { -21, 64 }, { -13, 31 }, + { -25, 64 }, { -29, 94 }, { 9, 75 }, { 17, 63 }, + { -8, 74 }, { -5, 35 }, { -2, 27 }, { 13, 91 }, + { 4, 39 }, { 0, 42 }, { 7, 34 }, { 11, 29 }, + { 8, 31 }, { 6, 37 }, { 7, 42 }, { 3, 40 }, + { 8, 33 }, { 13, 43 }, { 13, 36 }, { 4, 47 }, + { 3, 55 }, { 2, 58 }, { 6, 60 }, { 8, 44 }, + { 11, 44 }, { 14, 42 }, { 7, 48 }, { 4, 56 }, + { 4, 52 }, { 13, 37 }, { 9, 49 }, { 19, 58 }, + { 10, 48 }, { 12, 45 }, { 0, 69 }, { 20, 33 }, + { 8, 63 }, { 35, -18 }, { 33, -25 }, { 28, -3 }, + { 24, 10 }, { 27, 0 }, { 34, -14 }, { 52, -44 }, + { 39, -24 }, { 19, 17 }, { 31, 25 }, { 36, 29 }, + { 24, 33 }, { 34, 15 }, { 30, 20 }, { 22, 73 }, + { 4, 39 }, { 0, 42 }, { 7, 34 }, { 11, 29 }, + { 8, 31 }, { 6, 37 }, { 7, 42 }, { 3, 40 }, + { 8, 33 }, { 13, 43 }, { 13, 36 }, { 4, 47 }, + { 3, 55 }, { 2, 58 }, { 6, 60 }, { 8, 44 }, + { 11, 44 }, { 14, 42 }, { 7, 48 }, { 4, 56 }, + { 4, 52 }, { 13, 37 }, { 9, 49 }, { 19, 58 }, + { 10, 48 }, { 12, 45 }, { 0, 69 }, { 20, 33 }, + { 8, 63 }, { 35, -18 }, { 33, -25 }, { 28, -3 }, + { 24, 10 }, { 27, 0 }, { 34, -14 }, { 52, -44 }, + { 39, -24 }, { 19, 17 }, { 31, 25 }, { 36, 29 }, + { 24, 33 }, { 34, 15 }, { 30, 20 }, { 22, 73 }, + { -3, 78 }, { -8, 74 }, { -9, 72 }, { -10, 72 }, + { -18, 75 }, { -12, 71 }, { -11, 63 }, { -5, 70 }, + { -17, 75 }, { -14, 72 }, { -16, 67 }, { -8, 53 }, + { -14, 59 }, { -9, 52 }, { -11, 68 }, { -3, 78 }, + { -8, 74 }, { -9, 72 }, { -10, 72 }, { -18, 75 }, + { -12, 71 }, { -11, 63 }, { -5, 70 }, { -17, 75 }, + { -14, 72 }, { -16, 67 }, { -8, 53 }, { -14, 59 }, + { -9, 52 }, { -11, 68 }, { 9, -2 }, { 30, -10 }, + { 31, -4 }, { 33, -1 }, { 33, 7 }, { 31, 12 }, + { 37, 23 }, { 31, 38 }, { 20, 64 }, { 9, -2 }, + { 30, -10 }, { 31, -4 }, { 33, -1 }, { 33, 7 }, + { 31, 12 }, { 37, 23 }, { 31, 38 }, { 20, 64 }, + { -9, 71 }, { -7, 37 }, { -8, 44 }, { -11, 49 }, + { -10, 56 }, { -12, 59 }, { -8, 63 }, { -9, 67 }, + { -6, 68 }, { -10, 79 }, { -3, 78 }, { -8, 74 }, + { -9, 72 }, { -10, 72 }, { -18, 75 }, { -12, 71 }, + { -11, 63 }, { -5, 70 }, { -17, 75 }, { -14, 72 }, + { -16, 67 }, { -8, 53 }, { -14, 59 }, { -9, 52 }, + { -11, 68 }, { -3, 78 }, { -8, 74 }, { -9, 72 }, + { -10, 72 }, { -18, 75 }, { -12, 71 }, { -11, 63 }, + { -5, 70 }, { -17, 75 }, { -14, 72 }, { -16, 67 }, + { -8, 53 }, { -14, 59 }, { -9, 52 }, { -11, 68 }, + { 9, -2 }, { 30, -10 }, { 31, -4 }, { 33, -1 }, + { 33, 7 }, { 31, 12 }, { 37, 23 }, { 31, 38 }, + { 20, 64 }, { 9, -2 }, { 30, -10 }, { 31, -4 }, + { 33, -1 }, { 33, 7 }, { 31, 12 }, { 37, 23 }, + { 31, 38 }, { 20, 64 }, { -9, 71 }, { -7, 37 }, + { -8, 44 }, { -11, 49 }, { -10, 56 }, { -12, 59 }, + { -8, 63 }, { -9, 67 }, { -6, 68 }, { -10, 79 }, + { -22, 127 }, { -25, 127 }, { -25, 120 }, { -27, 127 }, + { -19, 114 }, { -23, 117 }, { -25, 118 }, { -26, 117 }, + { -24, 113 }, { -28, 118 }, { -31, 120 }, { -37, 124 }, + { -10, 94 }, { -15, 102 }, { -10, 99 }, { -13, 106 }, + { -50, 127 }, { -5, 92 }, { 17, 57 }, { -5, 86 }, + { -13, 94 }, { -12, 91 }, { -2, 77 }, { 0, 71 }, + { -1, 73 }, { 4, 64 }, { -7, 81 }, { 5, 64 }, + { 15, 57 }, { 1, 67 }, { 0, 68 }, { -10, 67 }, + { 1, 68 }, { 0, 77 }, { 2, 64 }, { 0, 68 }, + { -5, 78 }, { 7, 55 }, { 5, 59 }, { 2, 65 }, + { 14, 54 }, { 15, 44 }, { 5, 60 }, { 2, 70 }, + { -22, 127 }, { -25, 127 }, { -25, 120 }, { -27, 127 }, + { -19, 114 }, { -23, 117 }, { -25, 118 }, { -26, 117 }, + { -24, 113 }, { -28, 118 }, { -31, 120 }, { -37, 124 }, + { -10, 94 }, { -15, 102 }, { -10, 99 }, { -13, 106 }, + { -50, 127 }, { -5, 92 }, { 17, 57 }, { -5, 86 }, + { -13, 94 }, { -12, 91 }, { -2, 77 }, { 0, 71 }, + { -1, 73 }, { 4, 64 }, { -7, 81 }, { 5, 64 }, + { 15, 57 }, { 1, 67 }, { 0, 68 }, { -10, 67 }, + { 1, 68 }, { 0, 77 }, { 2, 64 }, { 0, 68 }, + { -5, 78 }, { 7, 55 }, { 5, 59 }, { 2, 65 }, + { 14, 54 }, { 15, 44 }, { 5, 60 }, { 2, 70 }, + { 17, -13 }, { 16, -9 }, { 17, -12 }, { 27, -21 }, + { 37, -30 }, { 41, -40 }, { 42, -41 }, { 48, -47 }, + { 39, -32 }, { 46, -40 }, { 52, -51 }, { 46, -41 }, + { 52, -39 }, { 43, -19 }, { 32, 11 }, { 61, -55 }, + { 56, -46 }, { 62, -50 }, { 81, -67 }, { 45, -20 }, + { 35, -2 }, { 28, 15 }, { 34, 1 }, { 39, 1 }, + { 30, 17 }, { 20, 38 }, { 18, 45 }, { 15, 54 }, + { 0, 79 }, { 36, -16 }, { 37, -14 }, { 37, -17 }, + { 32, 1 }, { 34, 15 }, { 29, 15 }, { 24, 25 }, + { 34, 22 }, { 31, 16 }, { 35, 18 }, { 31, 28 }, + { 33, 41 }, { 36, 28 }, { 27, 47 }, { 21, 62 }, + { 17, -13 }, { 16, -9 }, { 17, -12 }, { 27, -21 }, + { 37, -30 }, { 41, -40 }, { 42, -41 }, { 48, -47 }, + { 39, -32 }, { 46, -40 }, { 52, -51 }, { 46, -41 }, + { 52, -39 }, { 43, -19 }, { 32, 11 }, { 61, -55 }, + { 56, -46 }, { 62, -50 }, { 81, -67 }, { 45, -20 }, + { 35, -2 }, { 28, 15 }, { 34, 1 }, { 39, 1 }, + { 30, 17 }, { 20, 38 }, { 18, 45 }, { 15, 54 }, + { 0, 79 }, { 36, -16 }, { 37, -14 }, { 37, -17 }, + { 32, 1 }, { 34, 15 }, { 29, 15 }, { 24, 25 }, + { 34, 22 }, { 31, 16 }, { 35, 18 }, { 31, 28 }, + { 33, 41 }, { 36, 28 }, { 27, 47 }, { 21, 62 }, + { -24, 115 }, { -22, 82 }, { -9, 62 }, { 0, 53 }, + { 0, 59 }, { -14, 85 }, { -13, 89 }, { -13, 94 }, + { -11, 92 }, { -29, 127 }, { -21, 100 }, { -14, 57 }, + { -12, 67 }, { -11, 71 }, { -10, 77 }, { -21, 85 }, + { -16, 88 }, { -23, 104 }, { -15, 98 }, { -37, 127 }, + { -10, 82 }, { -8, 48 }, { -8, 61 }, { -8, 66 }, + { -7, 70 }, { -14, 75 }, { -10, 79 }, { -9, 83 }, + { -12, 92 }, { -18, 108 }, { -24, 115 }, { -22, 82 }, + { -9, 62 }, { 0, 53 }, { 0, 59 }, { -14, 85 }, + { -13, 89 }, { -13, 94 }, { -11, 92 }, { -29, 127 }, + { -21, 100 }, { -14, 57 }, { -12, 67 }, { -11, 71 }, + { -10, 77 }, { -21, 85 }, { -16, 88 }, { -23, 104 }, + { -15, 98 }, { -37, 127 }, { -10, 82 }, { -8, 48 }, + { -8, 61 }, { -8, 66 }, { -7, 70 }, { -14, 75 }, + { -10, 79 }, { -9, 83 }, { -12, 92 }, { -18, 108 }, + { -5, 79 }, { -11, 104 }, { -11, 91 }, { -30, 127 }, + { -5, 79 }, { -11, 104 }, { -11, 91 }, { -30, 127 }, + { -5, 79 }, { -11, 104 }, { -11, 91 }, { -30, 127 } + } +}; + +void ff_h264_init_cabac_states(H264Context *h) { + int i; + const int8_t (*tab)[2]; + const int slice_qp = av_clip(h->qscale - 6*(h->sps.bit_depth_luma-8), 0, 51); + + if( h->slice_type_nos == AV_PICTURE_TYPE_I ) tab = cabac_context_init_I; + else tab = cabac_context_init_PB[h->cabac_init_idc]; + + /* calculate pre-state */ + for( i= 0; i < 1024; i++ ) { + int pre = 2*(((tab[i][0] * slice_qp) >>4 ) + tab[i][1]) - 127; + + pre^= pre>>31; + if(pre > 124) + pre= 124 + (pre&1); + + h->cabac_state[i] = pre; + } +} + +static int decode_cabac_field_decoding_flag(H264Context *h) { + const long mbb_xy = h->mb_xy - 2L*h->mb_stride; + + unsigned long ctx = 0; + + ctx += h->mb_field_decoding_flag & !!h->mb_x; //for FMO:(s->current_picture.mb_type[mba_xy] >> 7) & (h->slice_table[mba_xy] == h->slice_num); + ctx += (h->cur_pic.mb_type[mbb_xy] >> 7) & (h->slice_table[mbb_xy] == h->slice_num); + + return get_cabac_noinline( &h->cabac, &(h->cabac_state+70)[ctx] ); +} + +static int decode_cabac_intra_mb_type(H264Context *h, int ctx_base, int intra_slice) { + uint8_t *state= &h->cabac_state[ctx_base]; + int mb_type; + + if(intra_slice){ + int ctx=0; + if( h->left_type[LTOP] & (MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)) + ctx++; + if( h->top_type & (MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)) + ctx++; + if( get_cabac_noinline( &h->cabac, &state[ctx] ) == 0 ) + return 0; /* I4x4 */ + state += 2; + }else{ + if( get_cabac_noinline( &h->cabac, state ) == 0 ) + return 0; /* I4x4 */ + } + + if( get_cabac_terminate( &h->cabac ) ) + return 25; /* PCM */ + + mb_type = 1; /* I16x16 */ + mb_type += 12 * get_cabac_noinline( &h->cabac, &state[1] ); /* cbp_luma != 0 */ + if( get_cabac_noinline( &h->cabac, &state[2] ) ) /* cbp_chroma */ + mb_type += 4 + 4 * get_cabac_noinline( &h->cabac, &state[2+intra_slice] ); + mb_type += 2 * get_cabac_noinline( &h->cabac, &state[3+intra_slice] ); + mb_type += 1 * get_cabac_noinline( &h->cabac, &state[3+2*intra_slice] ); + return mb_type; +} + +static int decode_cabac_mb_skip( H264Context *h, int mb_x, int mb_y ) { + int mba_xy, mbb_xy; + int ctx = 0; + + if (FRAME_MBAFF(h)) { //FIXME merge with the stuff in fill_caches? + int mb_xy = mb_x + (mb_y&~1)*h->mb_stride; + mba_xy = mb_xy - 1; + if( (mb_y&1) + && h->slice_table[mba_xy] == h->slice_num + && MB_FIELD(h) == !!IS_INTERLACED( h->cur_pic.mb_type[mba_xy] ) ) + mba_xy += h->mb_stride; + if (MB_FIELD(h)) { + mbb_xy = mb_xy - h->mb_stride; + if( !(mb_y&1) + && h->slice_table[mbb_xy] == h->slice_num + && IS_INTERLACED( h->cur_pic.mb_type[mbb_xy] ) ) + mbb_xy -= h->mb_stride; + }else + mbb_xy = mb_x + (mb_y-1)*h->mb_stride; + }else{ + int mb_xy = h->mb_xy; + mba_xy = mb_xy - 1; + mbb_xy = mb_xy - (h->mb_stride << FIELD_PICTURE(h)); + } + + if( h->slice_table[mba_xy] == h->slice_num && !IS_SKIP(h->cur_pic.mb_type[mba_xy] )) + ctx++; + if( h->slice_table[mbb_xy] == h->slice_num && !IS_SKIP(h->cur_pic.mb_type[mbb_xy] )) + ctx++; + + if( h->slice_type_nos == AV_PICTURE_TYPE_B ) + ctx += 13; + return get_cabac_noinline( &h->cabac, &h->cabac_state[11+ctx] ); +} + +static int decode_cabac_mb_intra4x4_pred_mode( H264Context *h, int pred_mode ) { + int mode = 0; + + if( get_cabac( &h->cabac, &h->cabac_state[68] ) ) + return pred_mode; + + mode += 1 * get_cabac( &h->cabac, &h->cabac_state[69] ); + mode += 2 * get_cabac( &h->cabac, &h->cabac_state[69] ); + mode += 4 * get_cabac( &h->cabac, &h->cabac_state[69] ); + + return mode + ( mode >= pred_mode ); +} + +static int decode_cabac_mb_chroma_pre_mode( H264Context *h) { + const int mba_xy = h->left_mb_xy[0]; + const int mbb_xy = h->top_mb_xy; + + int ctx = 0; + + /* No need to test for IS_INTRA4x4 and IS_INTRA16x16, as we set chroma_pred_mode_table to 0 */ + if( h->left_type[LTOP] && h->chroma_pred_mode_table[mba_xy] != 0 ) + ctx++; + + if( h->top_type && h->chroma_pred_mode_table[mbb_xy] != 0 ) + ctx++; + + if( get_cabac_noinline( &h->cabac, &h->cabac_state[64+ctx] ) == 0 ) + return 0; + + if( get_cabac_noinline( &h->cabac, &h->cabac_state[64+3] ) == 0 ) + return 1; + if( get_cabac_noinline( &h->cabac, &h->cabac_state[64+3] ) == 0 ) + return 2; + else + return 3; +} + +static int decode_cabac_mb_cbp_luma( H264Context *h) { + int cbp_b, cbp_a, ctx, cbp = 0; + + cbp_a = h->left_cbp; + cbp_b = h->top_cbp; + + ctx = !(cbp_a & 0x02) + 2 * !(cbp_b & 0x04); + cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]); + ctx = !(cbp & 0x01) + 2 * !(cbp_b & 0x08); + cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]) << 1; + ctx = !(cbp_a & 0x08) + 2 * !(cbp & 0x01); + cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]) << 2; + ctx = !(cbp & 0x04) + 2 * !(cbp & 0x02); + cbp += get_cabac_noinline(&h->cabac, &h->cabac_state[73 + ctx]) << 3; + return cbp; +} +static int decode_cabac_mb_cbp_chroma( H264Context *h) { + int ctx; + int cbp_a, cbp_b; + + cbp_a = (h->left_cbp>>4)&0x03; + cbp_b = (h-> top_cbp>>4)&0x03; + + ctx = 0; + if( cbp_a > 0 ) ctx++; + if( cbp_b > 0 ) ctx += 2; + if( get_cabac_noinline( &h->cabac, &h->cabac_state[77 + ctx] ) == 0 ) + return 0; + + ctx = 4; + if( cbp_a == 2 ) ctx++; + if( cbp_b == 2 ) ctx += 2; + return 1 + get_cabac_noinline( &h->cabac, &h->cabac_state[77 + ctx] ); +} + +static int decode_cabac_p_mb_sub_type( H264Context *h ) { + if( get_cabac( &h->cabac, &h->cabac_state[21] ) ) + return 0; /* 8x8 */ + if( !get_cabac( &h->cabac, &h->cabac_state[22] ) ) + return 1; /* 8x4 */ + if( get_cabac( &h->cabac, &h->cabac_state[23] ) ) + return 2; /* 4x8 */ + return 3; /* 4x4 */ +} +static int decode_cabac_b_mb_sub_type( H264Context *h ) { + int type; + if( !get_cabac( &h->cabac, &h->cabac_state[36] ) ) + return 0; /* B_Direct_8x8 */ + if( !get_cabac( &h->cabac, &h->cabac_state[37] ) ) + return 1 + get_cabac( &h->cabac, &h->cabac_state[39] ); /* B_L0_8x8, B_L1_8x8 */ + type = 3; + if( get_cabac( &h->cabac, &h->cabac_state[38] ) ) { + if( get_cabac( &h->cabac, &h->cabac_state[39] ) ) + return 11 + get_cabac( &h->cabac, &h->cabac_state[39] ); /* B_L1_4x4, B_Bi_4x4 */ + type += 4; + } + type += 2*get_cabac( &h->cabac, &h->cabac_state[39] ); + type += get_cabac( &h->cabac, &h->cabac_state[39] ); + return type; +} + +static int decode_cabac_mb_ref( H264Context *h, int list, int n ) { + int refa = h->ref_cache[list][scan8[n] - 1]; + int refb = h->ref_cache[list][scan8[n] - 8]; + int ref = 0; + int ctx = 0; + + if( h->slice_type_nos == AV_PICTURE_TYPE_B) { + if( refa > 0 && !(h->direct_cache[scan8[n] - 1]&(MB_TYPE_DIRECT2>>1)) ) + ctx++; + if( refb > 0 && !(h->direct_cache[scan8[n] - 8]&(MB_TYPE_DIRECT2>>1)) ) + ctx += 2; + } else { + if( refa > 0 ) + ctx++; + if( refb > 0 ) + ctx += 2; + } + + while( get_cabac( &h->cabac, &h->cabac_state[54+ctx] ) ) { + ref++; + ctx = (ctx>>2)+4; + if(ref >= 32 /*h->ref_list[list]*/){ + return -1; + } + } + return ref; +} + +static int decode_cabac_mb_mvd( H264Context *h, int ctxbase, int amvd, int *mvda) { + int mvd; + + if(!get_cabac(&h->cabac, &h->cabac_state[ctxbase+((amvd-3)>>(INT_BIT-1))+((amvd-33)>>(INT_BIT-1))+2])){ +// if(!get_cabac(&h->cabac, &h->cabac_state[ctxbase+(amvd>2)+(amvd>32)])){ + *mvda= 0; + return 0; + } + + mvd= 1; + ctxbase+= 3; + while( mvd < 9 && get_cabac( &h->cabac, &h->cabac_state[ctxbase] ) ) { + if( mvd < 4 ) + ctxbase++; + mvd++; + } + + if( mvd >= 9 ) { + int k = 3; + while( get_cabac_bypass( &h->cabac ) ) { + mvd += 1 << k; + k++; + if(k>24){ + av_log(h->avctx, AV_LOG_ERROR, "overflow in decode_cabac_mb_mvd\n"); + return INT_MIN; + } + } + while( k-- ) { + mvd += get_cabac_bypass( &h->cabac )<cabac, -mvd ); +} + +#define DECODE_CABAC_MB_MVD( h, list, n )\ +{\ + int amvd0 = h->mvd_cache[list][scan8[n] - 1][0] +\ + h->mvd_cache[list][scan8[n] - 8][0];\ + int amvd1 = h->mvd_cache[list][scan8[n] - 1][1] +\ + h->mvd_cache[list][scan8[n] - 8][1];\ +\ + mx += decode_cabac_mb_mvd( h, 40, amvd0, &mpx );\ + my += decode_cabac_mb_mvd( h, 47, amvd1, &mpy );\ +} + +static av_always_inline int get_cabac_cbf_ctx( H264Context *h, int cat, int idx, int max_coeff, int is_dc ) { + int nza, nzb; + int ctx = 0; + static const uint16_t base_ctx[14] = {85,89,93,97,101,1012,460,464,468,1016,472,476,480,1020}; + + if( is_dc ) { + if( cat == 3 ) { + idx -= CHROMA_DC_BLOCK_INDEX; + nza = (h->left_cbp>>(6+idx))&0x01; + nzb = (h-> top_cbp>>(6+idx))&0x01; + } else { + idx -= LUMA_DC_BLOCK_INDEX; + nza = h->left_cbp&(0x100< top_cbp&(0x100<non_zero_count_cache[scan8[idx] - 1]; + nzb = h->non_zero_count_cache[scan8[idx] - 8]; + } + + if( nza > 0 ) + ctx++; + + if( nzb > 0 ) + ctx += 2; + + return base_ctx[cat] + ctx; +} + +static av_always_inline void +decode_cabac_residual_internal(H264Context *h, int16_t *block, + int cat, int n, const uint8_t *scantable, + const uint32_t *qmul, int max_coeff, + int is_dc, int chroma422) +{ + static const int significant_coeff_flag_offset[2][14] = { + { 105+0, 105+15, 105+29, 105+44, 105+47, 402, 484+0, 484+15, 484+29, 660, 528+0, 528+15, 528+29, 718 }, + { 277+0, 277+15, 277+29, 277+44, 277+47, 436, 776+0, 776+15, 776+29, 675, 820+0, 820+15, 820+29, 733 } + }; + static const int last_coeff_flag_offset[2][14] = { + { 166+0, 166+15, 166+29, 166+44, 166+47, 417, 572+0, 572+15, 572+29, 690, 616+0, 616+15, 616+29, 748 }, + { 338+0, 338+15, 338+29, 338+44, 338+47, 451, 864+0, 864+15, 864+29, 699, 908+0, 908+15, 908+29, 757 } + }; + static const int coeff_abs_level_m1_offset[14] = { + 227+0, 227+10, 227+20, 227+30, 227+39, 426, 952+0, 952+10, 952+20, 708, 982+0, 982+10, 982+20, 766 + }; + static const uint8_t significant_coeff_flag_offset_8x8[2][63] = { + { 0, 1, 2, 3, 4, 5, 5, 4, 4, 3, 3, 4, 4, 4, 5, 5, + 4, 4, 4, 4, 3, 3, 6, 7, 7, 7, 8, 9,10, 9, 8, 7, + 7, 6,11,12,13,11, 6, 7, 8, 9,14,10, 9, 8, 6,11, + 12,13,11, 6, 9,14,10, 9,11,12,13,11,14,10,12 }, + { 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 7, 8, 4, 5, + 6, 9,10,10, 8,11,12,11, 9, 9,10,10, 8,11,12,11, + 9, 9,10,10, 8,11,12,11, 9, 9,10,10, 8,13,13, 9, + 9,10,10, 8,13,13, 9, 9,10,10,14,14,14,14,14 } + }; + static const uint8_t sig_coeff_offset_dc[7] = { 0, 0, 1, 1, 2, 2, 2 }; + /* node ctx: 0..3: abslevel1 (with abslevelgt1 == 0). + * 4..7: abslevelgt1 + 3 (and abslevel1 doesn't matter). + * map node ctx => cabac ctx for level=1 */ + static const uint8_t coeff_abs_level1_ctx[8] = { 1, 2, 3, 4, 0, 0, 0, 0 }; + /* map node ctx => cabac ctx for level>1 */ + static const uint8_t coeff_abs_levelgt1_ctx[2][8] = { + { 5, 5, 5, 5, 6, 7, 8, 9 }, + { 5, 5, 5, 5, 6, 7, 8, 8 }, // 422/dc case + }; + static const uint8_t coeff_abs_level_transition[2][8] = { + /* update node ctx after decoding a level=1 */ + { 1, 2, 3, 3, 4, 5, 6, 7 }, + /* update node ctx after decoding a level>1 */ + { 4, 4, 4, 4, 5, 6, 7, 7 } + }; + + int index[64]; + + int av_unused last; + int coeff_count = 0; + int node_ctx = 0; + + uint8_t *significant_coeff_ctx_base; + uint8_t *last_coeff_ctx_base; + uint8_t *abs_level_m1_ctx_base; + +#if !ARCH_X86 +#define CABAC_ON_STACK +#endif +#ifdef CABAC_ON_STACK +#define CC &cc + CABACContext cc; + cc.range = h->cabac.range; + cc.low = h->cabac.low; + cc.bytestream= h->cabac.bytestream; +#else +#define CC &h->cabac +#endif + + significant_coeff_ctx_base = h->cabac_state + + significant_coeff_flag_offset[MB_FIELD(h)][cat]; + last_coeff_ctx_base = h->cabac_state + + last_coeff_flag_offset[MB_FIELD(h)][cat]; + abs_level_m1_ctx_base = h->cabac_state + + coeff_abs_level_m1_offset[cat]; + + if( !is_dc && max_coeff == 64 ) { +#define DECODE_SIGNIFICANCE( coefs, sig_off, last_off ) \ + for(last= 0; last < coefs; last++) { \ + uint8_t *sig_ctx = significant_coeff_ctx_base + sig_off; \ + if( get_cabac( CC, sig_ctx )) { \ + uint8_t *last_ctx = last_coeff_ctx_base + last_off; \ + index[coeff_count++] = last; \ + if( get_cabac( CC, last_ctx ) ) { \ + last= max_coeff; \ + break; \ + } \ + } \ + }\ + if( last == max_coeff -1 ) {\ + index[coeff_count++] = last;\ + } + const uint8_t *sig_off = significant_coeff_flag_offset_8x8[MB_FIELD(h)]; +#ifdef decode_significance + coeff_count = decode_significance_8x8(CC, significant_coeff_ctx_base, index, + last_coeff_ctx_base, sig_off); + } else { + if (is_dc && chroma422) { // dc 422 + DECODE_SIGNIFICANCE(7, sig_coeff_offset_dc[last], sig_coeff_offset_dc[last]); + } else { + coeff_count = decode_significance(CC, max_coeff, significant_coeff_ctx_base, index, + last_coeff_ctx_base-significant_coeff_ctx_base); + } +#else + DECODE_SIGNIFICANCE( 63, sig_off[last], ff_h264_last_coeff_flag_offset_8x8[last] ); + } else { + if (is_dc && chroma422) { // dc 422 + DECODE_SIGNIFICANCE(7, sig_coeff_offset_dc[last], sig_coeff_offset_dc[last]); + } else { + DECODE_SIGNIFICANCE(max_coeff - 1, last, last); + } +#endif + } + av_assert2(coeff_count > 0); + + if( is_dc ) { + if( cat == 3 ) + h->cbp_table[h->mb_xy] |= 0x40 << (n - CHROMA_DC_BLOCK_INDEX); + else + h->cbp_table[h->mb_xy] |= 0x100 << (n - LUMA_DC_BLOCK_INDEX); + h->non_zero_count_cache[scan8[n]] = coeff_count; + } else { + if( max_coeff == 64 ) + fill_rectangle(&h->non_zero_count_cache[scan8[n]], 2, 2, 8, coeff_count, 1); + else { + av_assert2( cat == 1 || cat == 2 || cat == 4 || cat == 7 || cat == 8 || cat == 11 || cat == 12 ); + h->non_zero_count_cache[scan8[n]] = coeff_count; + } + } + + +#define STORE_BLOCK(type) \ + do { \ + uint8_t *ctx = coeff_abs_level1_ctx[node_ctx] + abs_level_m1_ctx_base; \ + \ + int j= scantable[index[--coeff_count]]; \ + \ + if( get_cabac( CC, ctx ) == 0 ) { \ + node_ctx = coeff_abs_level_transition[0][node_ctx]; \ + if( is_dc ) { \ + ((type*)block)[j] = get_cabac_bypass_sign( CC, -1); \ + }else{ \ + ((type*)block)[j] = (get_cabac_bypass_sign( CC, -qmul[j]) + 32) >> 6; \ + } \ + } else { \ + int coeff_abs = 2; \ + ctx = coeff_abs_levelgt1_ctx[is_dc && chroma422][node_ctx] + abs_level_m1_ctx_base; \ + node_ctx = coeff_abs_level_transition[1][node_ctx]; \ +\ + while( coeff_abs < 15 && get_cabac( CC, ctx ) ) { \ + coeff_abs++; \ + } \ +\ + if( coeff_abs >= 15 ) { \ + int j = 0; \ + while(get_cabac_bypass( CC ) && j<30) { \ + j++; \ + } \ +\ + coeff_abs=1; \ + while( j-- ) { \ + coeff_abs += coeff_abs + get_cabac_bypass( CC ); \ + } \ + coeff_abs+= 14; \ + } \ +\ + if( is_dc ) { \ + ((type*)block)[j] = get_cabac_bypass_sign( CC, -coeff_abs ); \ + }else{ \ + ((type*)block)[j] = ((int)(get_cabac_bypass_sign( CC, -coeff_abs ) * qmul[j] + 32)) >> 6; \ + } \ + } \ + } while ( coeff_count ); + + if (h->pixel_shift) { + STORE_BLOCK(int32_t) + } else { + STORE_BLOCK(int16_t) + } +#ifdef CABAC_ON_STACK + h->cabac.range = cc.range ; + h->cabac.low = cc.low ; + h->cabac.bytestream= cc.bytestream; +#endif + +} + +static void decode_cabac_residual_dc_internal(H264Context *h, int16_t *block, + int cat, int n, + const uint8_t *scantable, + int max_coeff) +{ + decode_cabac_residual_internal(h, block, cat, n, scantable, NULL, max_coeff, 1, 0); +} + +static void decode_cabac_residual_dc_internal_422(H264Context *h, int16_t *block, + int cat, int n, const uint8_t *scantable, + int max_coeff) +{ + decode_cabac_residual_internal(h, block, cat, n, scantable, NULL, max_coeff, 1, 1); +} + +static void decode_cabac_residual_nondc_internal(H264Context *h, int16_t *block, + int cat, int n, + const uint8_t *scantable, + const uint32_t *qmul, + int max_coeff) +{ + decode_cabac_residual_internal(h, block, cat, n, scantable, qmul, max_coeff, 0, 0); +} + +/* cat: 0-> DC 16x16 n = 0 + * 1-> AC 16x16 n = luma4x4idx + * 2-> Luma4x4 n = luma4x4idx + * 3-> DC Chroma n = iCbCr + * 4-> AC Chroma n = 16 + 4 * iCbCr + chroma4x4idx + * 5-> Luma8x8 n = 4 * luma8x8idx */ + +/* Partially inline the CABAC residual decode: inline the coded block flag. + * This has very little impact on binary size and improves performance + * because it allows improved constant propagation into get_cabac_cbf_ctx, + * as well as because most blocks have zero CBFs. */ + +static av_always_inline void decode_cabac_residual_dc(H264Context *h, + int16_t *block, + int cat, int n, + const uint8_t *scantable, + int max_coeff) +{ + /* read coded block flag */ + if( get_cabac( &h->cabac, &h->cabac_state[get_cabac_cbf_ctx( h, cat, n, max_coeff, 1 ) ] ) == 0 ) { + h->non_zero_count_cache[scan8[n]] = 0; + return; + } + decode_cabac_residual_dc_internal( h, block, cat, n, scantable, max_coeff ); +} + +static av_always_inline void +decode_cabac_residual_dc_422(H264Context *h, int16_t *block, + int cat, int n, const uint8_t *scantable, + int max_coeff) +{ + /* read coded block flag */ + if (get_cabac(&h->cabac, &h->cabac_state[get_cabac_cbf_ctx(h, cat, n, max_coeff, 1)]) == 0) { + h->non_zero_count_cache[scan8[n]] = 0; + return; + } + decode_cabac_residual_dc_internal_422(h, block, cat, n, scantable, max_coeff); +} + +static av_always_inline void decode_cabac_residual_nondc(H264Context *h, + int16_t *block, + int cat, int n, + const uint8_t *scantable, + const uint32_t *qmul, + int max_coeff) +{ + /* read coded block flag */ + if( (cat != 5 || CHROMA444) && get_cabac( &h->cabac, &h->cabac_state[get_cabac_cbf_ctx( h, cat, n, max_coeff, 0 ) ] ) == 0 ) { + if( max_coeff == 64 ) { + fill_rectangle(&h->non_zero_count_cache[scan8[n]], 2, 2, 8, 0, 1); + } else { + h->non_zero_count_cache[scan8[n]] = 0; + } + return; + } + decode_cabac_residual_nondc_internal( h, block, cat, n, scantable, qmul, max_coeff ); +} + +static av_always_inline void decode_cabac_luma_residual( H264Context *h, const uint8_t *scan, const uint8_t *scan8x8, int pixel_shift, int mb_type, int cbp, int p ) +{ + static const uint8_t ctx_cat[4][3] = {{0,6,10},{1,7,11},{2,8,12},{5,9,13}}; + const uint32_t *qmul; + int i8x8, i4x4; + int qscale = p == 0 ? h->qscale : h->chroma_qp[p-1]; + if( IS_INTRA16x16( mb_type ) ) { + AV_ZERO128(h->mb_luma_dc[p]+0); + AV_ZERO128(h->mb_luma_dc[p]+8); + AV_ZERO128(h->mb_luma_dc[p]+16); + AV_ZERO128(h->mb_luma_dc[p]+24); + decode_cabac_residual_dc(h, h->mb_luma_dc[p], ctx_cat[0][p], LUMA_DC_BLOCK_INDEX+p, scan, 16); + + if( cbp&15 ) { + qmul = h->dequant4_coeff[p][qscale]; + for( i4x4 = 0; i4x4 < 16; i4x4++ ) { + const int index = 16*p + i4x4; + decode_cabac_residual_nondc(h, h->mb + (16*index << pixel_shift), ctx_cat[1][p], index, scan + 1, qmul, 15); + } + } else { + fill_rectangle(&h->non_zero_count_cache[scan8[16*p]], 4, 4, 8, 0, 1); + } + } else { + int cqm = (IS_INTRA( mb_type ) ? 0:3) + p; + for( i8x8 = 0; i8x8 < 4; i8x8++ ) { + if( cbp & (1<mb + (16*index << pixel_shift), ctx_cat[3][p], index, + scan8x8, h->dequant8_coeff[cqm][qscale], 64); + } else { + qmul = h->dequant4_coeff[cqm][qscale]; + for( i4x4 = 0; i4x4 < 4; i4x4++ ) { + const int index = 16*p + 4*i8x8 + i4x4; +//START_TIMER + decode_cabac_residual_nondc(h, h->mb + (16*index << pixel_shift), ctx_cat[2][p], index, scan, qmul, 16); +//STOP_TIMER("decode_residual") + } + } + } else { + fill_rectangle(&h->non_zero_count_cache[scan8[4*i8x8+16*p]], 2, 2, 8, 0, 1); + } + } + } +} + +/** + * Decode a macroblock. + * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR if an error is noticed + */ +int ff_h264_decode_mb_cabac(H264Context *h) { + int mb_xy; + int mb_type, partition_count, cbp = 0; + int dct8x8_allowed= h->pps.transform_8x8_mode; + int decode_chroma = h->sps.chroma_format_idc == 1 || h->sps.chroma_format_idc == 2; + const int pixel_shift = h->pixel_shift; + unsigned local_ref_count[2]; + + mb_xy = h->mb_xy = h->mb_x + h->mb_y*h->mb_stride; + + tprintf(h->avctx, "pic:%d mb:%d/%d\n", h->frame_num, h->mb_x, h->mb_y); + if( h->slice_type_nos != AV_PICTURE_TYPE_I ) { + int skip; + /* a skipped mb needs the aff flag from the following mb */ + if (FRAME_MBAFF(h) && (h->mb_y & 1) == 1 && h->prev_mb_skipped) + skip = h->next_mb_skipped; + else + skip = decode_cabac_mb_skip( h, h->mb_x, h->mb_y ); + /* read skip flags */ + if( skip ) { + if (FRAME_MBAFF(h) && (h->mb_y & 1) == 0) { + h->cur_pic.mb_type[mb_xy] = MB_TYPE_SKIP; + h->next_mb_skipped = decode_cabac_mb_skip( h, h->mb_x, h->mb_y+1 ); + if(!h->next_mb_skipped) + h->mb_mbaff = h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h); + } + + decode_mb_skip(h); + + h->cbp_table[mb_xy] = 0; + h->chroma_pred_mode_table[mb_xy] = 0; + h->last_qscale_diff = 0; + + return 0; + + } + } + if (FRAME_MBAFF(h)) { + if( (h->mb_y&1) == 0 ) + h->mb_mbaff = + h->mb_field_decoding_flag = decode_cabac_field_decoding_flag(h); + } + + h->prev_mb_skipped = 0; + + fill_decode_neighbors(h, -(MB_FIELD(h))); + + if( h->slice_type_nos == AV_PICTURE_TYPE_B ) { + int ctx = 0; + av_assert2(h->slice_type_nos == AV_PICTURE_TYPE_B); + + if( !IS_DIRECT( h->left_type[LTOP]-1 ) ) + ctx++; + if( !IS_DIRECT( h->top_type-1 ) ) + ctx++; + + if( !get_cabac_noinline( &h->cabac, &h->cabac_state[27+ctx] ) ){ + mb_type= 0; /* B_Direct_16x16 */ + }else if( !get_cabac_noinline( &h->cabac, &h->cabac_state[27+3] ) ) { + mb_type= 1 + get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); /* B_L[01]_16x16 */ + }else{ + int bits; + bits = get_cabac_noinline( &h->cabac, &h->cabac_state[27+4] ) << 3; + bits+= get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ) << 2; + bits+= get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ) << 1; + bits+= get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); + if( bits < 8 ){ + mb_type= bits + 3; /* B_Bi_16x16 through B_L1_L0_16x8 */ + }else if( bits == 13 ){ + mb_type= decode_cabac_intra_mb_type(h, 32, 0); + goto decode_intra_mb; + }else if( bits == 14 ){ + mb_type= 11; /* B_L1_L0_8x16 */ + }else if( bits == 15 ){ + mb_type= 22; /* B_8x8 */ + }else{ + bits= ( bits<<1 ) + get_cabac_noinline( &h->cabac, &h->cabac_state[27+5] ); + mb_type= bits - 4; /* B_L0_Bi_* through B_Bi_Bi_* */ + } + } + partition_count= b_mb_type_info[mb_type].partition_count; + mb_type= b_mb_type_info[mb_type].type; + } else if( h->slice_type_nos == AV_PICTURE_TYPE_P ) { + if( get_cabac_noinline( &h->cabac, &h->cabac_state[14] ) == 0 ) { + /* P-type */ + if( get_cabac_noinline( &h->cabac, &h->cabac_state[15] ) == 0 ) { + /* P_L0_D16x16, P_8x8 */ + mb_type= 3 * get_cabac_noinline( &h->cabac, &h->cabac_state[16] ); + } else { + /* P_L0_D8x16, P_L0_D16x8 */ + mb_type= 2 - get_cabac_noinline( &h->cabac, &h->cabac_state[17] ); + } + partition_count= p_mb_type_info[mb_type].partition_count; + mb_type= p_mb_type_info[mb_type].type; + } else { + mb_type= decode_cabac_intra_mb_type(h, 17, 0); + goto decode_intra_mb; + } + } else { + mb_type= decode_cabac_intra_mb_type(h, 3, 1); + if(h->slice_type == AV_PICTURE_TYPE_SI && mb_type) + mb_type--; + av_assert2(h->slice_type_nos == AV_PICTURE_TYPE_I); +decode_intra_mb: + partition_count = 0; + cbp= i_mb_type_info[mb_type].cbp; + h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode; + mb_type= i_mb_type_info[mb_type].type; + } + if(MB_FIELD(h)) + mb_type |= MB_TYPE_INTERLACED; + + h->slice_table[ mb_xy ]= h->slice_num; + + if(IS_INTRA_PCM(mb_type)) { + const int mb_size = ff_h264_mb_sizes[h->sps.chroma_format_idc] * + h->sps.bit_depth_luma >> 3; + const uint8_t *ptr; + + // We assume these blocks are very rare so we do not optimize it. + // FIXME The two following lines get the bitstream position in the cabac + // decode, I think it should be done by a function in cabac.h (or cabac.c). + ptr= h->cabac.bytestream; + if(h->cabac.low&0x1) ptr--; + if(CABAC_BITS==16){ + if(h->cabac.low&0x1FF) ptr--; + } + + // The pixels are stored in the same order as levels in h->mb array. + if ((int) (h->cabac.bytestream_end - ptr) < mb_size) + return -1; + h->intra_pcm_ptr = ptr; + ptr += mb_size; + + ff_init_cabac_decoder(&h->cabac, ptr, h->cabac.bytestream_end - ptr); + + // All blocks are present + h->cbp_table[mb_xy] = 0xf7ef; + h->chroma_pred_mode_table[mb_xy] = 0; + // In deblocking, the quantizer is 0 + h->cur_pic.qscale_table[mb_xy] = 0; + // All coeffs are present + memset(h->non_zero_count[mb_xy], 16, 48); + h->cur_pic.mb_type[mb_xy] = mb_type; + h->last_qscale_diff = 0; + return 0; + } + + local_ref_count[0] = h->ref_count[0] << MB_MBAFF(h); + local_ref_count[1] = h->ref_count[1] << MB_MBAFF(h); + + fill_decode_caches(h, mb_type); + + if( IS_INTRA( mb_type ) ) { + int i, pred_mode; + if( IS_INTRA4x4( mb_type ) ) { + if( dct8x8_allowed && get_cabac_noinline( &h->cabac, &h->cabac_state[399 + h->neighbor_transform_size] ) ) { + mb_type |= MB_TYPE_8x8DCT; + for( i = 0; i < 16; i+=4 ) { + int pred = pred_intra_mode( h, i ); + int mode = decode_cabac_mb_intra4x4_pred_mode( h, pred ); + fill_rectangle( &h->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 ); + } + } else { + for( i = 0; i < 16; i++ ) { + int pred = pred_intra_mode( h, i ); + h->intra4x4_pred_mode_cache[ scan8[i] ] = decode_cabac_mb_intra4x4_pred_mode( h, pred ); + + av_dlog(h->avctx, "i4x4 pred=%d mode=%d\n", pred, + h->intra4x4_pred_mode_cache[scan8[i]]); + } + } + write_back_intra_pred_mode(h); + if( ff_h264_check_intra4x4_pred_mode(h) < 0 ) return -1; + } else { + h->intra16x16_pred_mode= ff_h264_check_intra_pred_mode( h, h->intra16x16_pred_mode, 0 ); + if( h->intra16x16_pred_mode < 0 ) return -1; + } + if(decode_chroma){ + h->chroma_pred_mode_table[mb_xy] = + pred_mode = decode_cabac_mb_chroma_pre_mode( h ); + + pred_mode= ff_h264_check_intra_pred_mode( h, pred_mode, 1 ); + if( pred_mode < 0 ) return -1; + h->chroma_pred_mode= pred_mode; + } else { + h->chroma_pred_mode= DC_128_PRED8x8; + } + } else if( partition_count == 4 ) { + int i, j, sub_partition_count[4], list, ref[2][4]; + + if( h->slice_type_nos == AV_PICTURE_TYPE_B ) { + for( i = 0; i < 4; i++ ) { + h->sub_mb_type[i] = decode_cabac_b_mb_sub_type( h ); + sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count; + h->sub_mb_type[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].type; + } + if( IS_DIRECT(h->sub_mb_type[0] | h->sub_mb_type[1] | + h->sub_mb_type[2] | h->sub_mb_type[3]) ) { + ff_h264_pred_direct_motion(h, &mb_type); + h->ref_cache[0][scan8[4]] = + h->ref_cache[1][scan8[4]] = + h->ref_cache[0][scan8[12]] = + h->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE; + for( i = 0; i < 4; i++ ) + fill_rectangle( &h->direct_cache[scan8[4*i]], 2, 2, 8, (h->sub_mb_type[i]>>1)&0xFF, 1 ); + } + } else { + for( i = 0; i < 4; i++ ) { + h->sub_mb_type[i] = decode_cabac_p_mb_sub_type( h ); + sub_partition_count[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count; + h->sub_mb_type[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].type; + } + } + + for( list = 0; list < h->list_count; list++ ) { + for( i = 0; i < 4; i++ ) { + if(IS_DIRECT(h->sub_mb_type[i])) continue; + if(IS_DIR(h->sub_mb_type[i], 0, list)){ + if (local_ref_count[list] > 1) { + ref[list][i] = decode_cabac_mb_ref( h, list, 4*i ); + if (ref[list][i] >= (unsigned)local_ref_count[list]) { + av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref[list][i], local_ref_count[list]); + return -1; + } + }else + ref[list][i] = 0; + } else { + ref[list][i] = -1; + } + h->ref_cache[list][ scan8[4*i]+1 ]= + h->ref_cache[list][ scan8[4*i]+8 ]=h->ref_cache[list][ scan8[4*i]+9 ]= ref[list][i]; + } + } + + if(dct8x8_allowed) + dct8x8_allowed = get_dct8x8_allowed(h); + + for(list=0; listlist_count; list++){ + for(i=0; i<4; i++){ + h->ref_cache[list][ scan8[4*i] ]=h->ref_cache[list][ scan8[4*i]+1 ]; + if(IS_DIRECT(h->sub_mb_type[i])){ + fill_rectangle(h->mvd_cache[list][scan8[4*i]], 2, 2, 8, 0, 2); + continue; + } + + if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){ + const int sub_mb_type= h->sub_mb_type[i]; + const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1; + for(j=0; jmv_cache[list][ scan8[index] ]; + uint8_t (* mvd_cache)[2]= &h->mvd_cache[list][ scan8[index] ]; + pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mx, &my); + DECODE_CABAC_MB_MVD( h, list, index) + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + if(IS_SUB_8X8(sub_mb_type)){ + mv_cache[ 1 ][0]= + mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx; + mv_cache[ 1 ][1]= + mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my; + + mvd_cache[ 1 ][0]= + mvd_cache[ 8 ][0]= mvd_cache[ 9 ][0]= mpx; + mvd_cache[ 1 ][1]= + mvd_cache[ 8 ][1]= mvd_cache[ 9 ][1]= mpy; + }else if(IS_SUB_8X4(sub_mb_type)){ + mv_cache[ 1 ][0]= mx; + mv_cache[ 1 ][1]= my; + + mvd_cache[ 1 ][0]= mpx; + mvd_cache[ 1 ][1]= mpy; + }else if(IS_SUB_4X8(sub_mb_type)){ + mv_cache[ 8 ][0]= mx; + mv_cache[ 8 ][1]= my; + + mvd_cache[ 8 ][0]= mpx; + mvd_cache[ 8 ][1]= mpy; + } + mv_cache[ 0 ][0]= mx; + mv_cache[ 0 ][1]= my; + + mvd_cache[ 0 ][0]= mpx; + mvd_cache[ 0 ][1]= mpy; + } + }else{ + fill_rectangle(h->mv_cache [list][ scan8[4*i] ], 2, 2, 8, 0, 4); + fill_rectangle(h->mvd_cache[list][ scan8[4*i] ], 2, 2, 8, 0, 2); + } + } + } + } else if( IS_DIRECT(mb_type) ) { + ff_h264_pred_direct_motion(h, &mb_type); + fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 2); + fill_rectangle(h->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 2); + dct8x8_allowed &= h->sps.direct_8x8_inference_flag; + } else { + int list, i; + if(IS_16X16(mb_type)){ + for(list=0; listlist_count; list++){ + if(IS_DIR(mb_type, 0, list)){ + int ref; + if (local_ref_count[list] > 1) { + ref= decode_cabac_mb_ref(h, list, 0); + if (ref >= (unsigned)local_ref_count[list]) { + av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, local_ref_count[list]); + return -1; + } + }else + ref=0; + fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1); + } + } + for(list=0; listlist_count; list++){ + if(IS_DIR(mb_type, 0, list)){ + int mx,my,mpx,mpy; + pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mx, &my); + DECODE_CABAC_MB_MVD( h, list, 0) + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + fill_rectangle(h->mvd_cache[list][ scan8[0] ], 4, 4, 8, pack8to16(mpx,mpy), 2); + fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4); + } + } + } + else if(IS_16X8(mb_type)){ + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + if(IS_DIR(mb_type, i, list)){ + int ref; + if (local_ref_count[list] > 1) { + ref= decode_cabac_mb_ref( h, list, 8*i ); + if (ref >= (unsigned)local_ref_count[list]) { + av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, local_ref_count[list]); + return -1; + } + }else + ref=0; + fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, ref, 1); + }else + fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1); + } + } + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + if(IS_DIR(mb_type, i, list)){ + int mx,my,mpx,mpy; + pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mx, &my); + DECODE_CABAC_MB_MVD( h, list, 8*i) + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack8to16(mpx,mpy), 2); + fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4); + }else{ + fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 2); + fill_rectangle(h-> mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4); + } + } + } + }else{ + av_assert2(IS_8X16(mb_type)); + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + if(IS_DIR(mb_type, i, list)){ //FIXME optimize + int ref; + if (local_ref_count[list] > 1) { + ref= decode_cabac_mb_ref( h, list, 4*i ); + if (ref >= (unsigned)local_ref_count[list]) { + av_log(h->avctx, AV_LOG_ERROR, "Reference %d >= %d\n", ref, local_ref_count[list]); + return -1; + } + }else + ref=0; + fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, ref, 1); + }else + fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1); + } + } + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + if(IS_DIR(mb_type, i, list)){ + int mx,my,mpx,mpy; + pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mx, &my); + DECODE_CABAC_MB_MVD( h, list, 4*i) + + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack8to16(mpx,mpy), 2); + fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4); + }else{ + fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 2); + fill_rectangle(h-> mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4); + } + } + } + } + } + + if( IS_INTER( mb_type ) ) { + h->chroma_pred_mode_table[mb_xy] = 0; + write_back_motion( h, mb_type ); + } + + if( !IS_INTRA16x16( mb_type ) ) { + cbp = decode_cabac_mb_cbp_luma( h ); + if(decode_chroma) + cbp |= decode_cabac_mb_cbp_chroma( h ) << 4; + } else { + if (!decode_chroma && cbp>15) { + av_log(h->avctx, AV_LOG_ERROR, "gray chroma\n"); + return AVERROR_INVALIDDATA; + } + } + + h->cbp_table[mb_xy] = h->cbp = cbp; + + if( dct8x8_allowed && (cbp&15) && !IS_INTRA( mb_type ) ) { + mb_type |= MB_TYPE_8x8DCT * get_cabac_noinline( &h->cabac, &h->cabac_state[399 + h->neighbor_transform_size] ); + } + + /* It would be better to do this in fill_decode_caches, but we don't know + * the transform mode of the current macroblock there. */ + if (CHROMA444 && IS_8x8DCT(mb_type)){ + int i; + uint8_t *nnz_cache = h->non_zero_count_cache; + for (i = 0; i < 2; i++){ + if (h->left_type[LEFT(i)] && !IS_8x8DCT(h->left_type[LEFT(i)])){ + nnz_cache[3+8* 1 + 2*8*i]= + nnz_cache[3+8* 2 + 2*8*i]= + nnz_cache[3+8* 6 + 2*8*i]= + nnz_cache[3+8* 7 + 2*8*i]= + nnz_cache[3+8*11 + 2*8*i]= + nnz_cache[3+8*12 + 2*8*i]= IS_INTRA(mb_type) ? 64 : 0; + } + } + if (h->top_type && !IS_8x8DCT(h->top_type)){ + uint32_t top_empty = CABAC(h) && !IS_INTRA(mb_type) ? 0 : 0x40404040; + AV_WN32A(&nnz_cache[4+8* 0], top_empty); + AV_WN32A(&nnz_cache[4+8* 5], top_empty); + AV_WN32A(&nnz_cache[4+8*10], top_empty); + } + } + h->cur_pic.mb_type[mb_xy] = mb_type; + + if( cbp || IS_INTRA16x16( mb_type ) ) { + const uint8_t *scan, *scan8x8; + const uint32_t *qmul; + + if(IS_INTERLACED(mb_type)){ + scan8x8= h->qscale ? h->field_scan8x8 : h->field_scan8x8_q0; + scan= h->qscale ? h->field_scan : h->field_scan_q0; + }else{ + scan8x8= h->qscale ? h->zigzag_scan8x8 : h->zigzag_scan8x8_q0; + scan= h->qscale ? h->zigzag_scan : h->zigzag_scan_q0; + } + + // decode_cabac_mb_dqp + if(get_cabac_noinline( &h->cabac, &h->cabac_state[60 + (h->last_qscale_diff != 0)])){ + int val = 1; + int ctx= 2; + const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8); + + while( get_cabac_noinline( &h->cabac, &h->cabac_state[60 + ctx] ) ) { + ctx= 3; + val++; + if(val > 2*max_qp){ //prevent infinite loop + av_log(h->avctx, AV_LOG_ERROR, "cabac decode of qscale diff failed at %d %d\n", h->mb_x, h->mb_y); + return -1; + } + } + + if( val&0x01 ) + val= (val + 1)>>1 ; + else + val= -((val + 1)>>1); + h->last_qscale_diff = val; + h->qscale += val; + if(((unsigned)h->qscale) > max_qp){ + if(h->qscale<0) h->qscale+= max_qp+1; + else h->qscale-= max_qp+1; + } + h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale); + h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale); + }else + h->last_qscale_diff=0; + + decode_cabac_luma_residual(h, scan, scan8x8, pixel_shift, mb_type, cbp, 0); + if(CHROMA444){ + decode_cabac_luma_residual(h, scan, scan8x8, pixel_shift, mb_type, cbp, 1); + decode_cabac_luma_residual(h, scan, scan8x8, pixel_shift, mb_type, cbp, 2); + } else if (CHROMA422) { + if( cbp&0x30 ){ + int c; + for (c = 0; c < 2; c++) + decode_cabac_residual_dc_422(h, h->mb + ((256 + 16*16*c) << pixel_shift), 3, + CHROMA_DC_BLOCK_INDEX + c, + chroma422_dc_scan, 8); + } + + if( cbp&0x20 ) { + int c, i, i8x8; + for( c = 0; c < 2; c++ ) { + int16_t *mb = h->mb + (16*(16 + 16*c) << pixel_shift); + qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[c]]; + for (i8x8 = 0; i8x8 < 2; i8x8++) { + for (i = 0; i < 4; i++) { + const int index = 16 + 16 * c + 8*i8x8 + i; + decode_cabac_residual_nondc(h, mb, 4, index, scan + 1, qmul, 15); + mb += 16<non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + } + } else /* yuv420 */ { + if( cbp&0x30 ){ + int c; + for (c = 0; c < 2; c++) + decode_cabac_residual_dc(h, h->mb + ((256 + 16*16*c) << pixel_shift), 3, CHROMA_DC_BLOCK_INDEX+c, chroma_dc_scan, 4); + } + + if( cbp&0x20 ) { + int c, i; + for( c = 0; c < 2; c++ ) { + qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[c]]; + for( i = 0; i < 4; i++ ) { + const int index = 16 + 16 * c + i; + decode_cabac_residual_nondc(h, h->mb + (16*index << pixel_shift), 4, index, scan + 1, qmul, 15); + } + } + } else { + fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + } + } + } else { + fill_rectangle(&h->non_zero_count_cache[scan8[ 0]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + h->last_qscale_diff = 0; + } + + h->cur_pic.qscale_table[mb_xy] = h->qscale; + write_back_non_zero_count(h); + + return 0; +} diff --git a/ffmpeg/libavcodec/h264_cavlc.c b/ffmpeg/libavcodec/h264_cavlc.c new file mode 100644 index 0000000..63f8d78 --- /dev/null +++ b/ffmpeg/libavcodec/h264_cavlc.c @@ -0,0 +1,1162 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... cavlc bitstream decoding + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 cavlc bitstream decoding. + * @author Michael Niedermayer + */ + +#define CABAC(h) 0 +#define UNCHECKED_BITSTREAM_READER 1 + +#include "internal.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h264.h" +#include "h264data.h" // FIXME FIXME FIXME +#include "h264_mvpred.h" +#include "golomb.h" +#include "libavutil/avassert.h" + + +static const uint8_t golomb_to_inter_cbp_gray[16]={ + 0, 1, 2, 4, 8, 3, 5,10,12,15, 7,11,13,14, 6, 9, +}; + +static const uint8_t golomb_to_intra4x4_cbp_gray[16]={ +15, 0, 7,11,13,14, 3, 5,10,12, 1, 2, 4, 8, 6, 9, +}; + +static const uint8_t chroma_dc_coeff_token_len[4*5]={ + 2, 0, 0, 0, + 6, 1, 0, 0, + 6, 6, 3, 0, + 6, 7, 7, 6, + 6, 8, 8, 7, +}; + +static const uint8_t chroma_dc_coeff_token_bits[4*5]={ + 1, 0, 0, 0, + 7, 1, 0, 0, + 4, 6, 1, 0, + 3, 3, 2, 5, + 2, 3, 2, 0, +}; + +static const uint8_t chroma422_dc_coeff_token_len[4*9]={ + 1, 0, 0, 0, + 7, 2, 0, 0, + 7, 7, 3, 0, + 9, 7, 7, 5, + 9, 9, 7, 6, + 10, 10, 9, 7, + 11, 11, 10, 7, + 12, 12, 11, 10, + 13, 12, 12, 11, +}; + +static const uint8_t chroma422_dc_coeff_token_bits[4*9]={ + 1, 0, 0, 0, + 15, 1, 0, 0, + 14, 13, 1, 0, + 7, 12, 11, 1, + 6, 5, 10, 1, + 7, 6, 4, 9, + 7, 6, 5, 8, + 7, 6, 5, 4, + 7, 5, 4, 4, +}; + +static const uint8_t coeff_token_len[4][4*17]={ +{ + 1, 0, 0, 0, + 6, 2, 0, 0, 8, 6, 3, 0, 9, 8, 7, 5, 10, 9, 8, 6, + 11,10, 9, 7, 13,11,10, 8, 13,13,11, 9, 13,13,13,10, + 14,14,13,11, 14,14,14,13, 15,15,14,14, 15,15,15,14, + 16,15,15,15, 16,16,16,15, 16,16,16,16, 16,16,16,16, +}, +{ + 2, 0, 0, 0, + 6, 2, 0, 0, 6, 5, 3, 0, 7, 6, 6, 4, 8, 6, 6, 4, + 8, 7, 7, 5, 9, 8, 8, 6, 11, 9, 9, 6, 11,11,11, 7, + 12,11,11, 9, 12,12,12,11, 12,12,12,11, 13,13,13,12, + 13,13,13,13, 13,14,13,13, 14,14,14,13, 14,14,14,14, +}, +{ + 4, 0, 0, 0, + 6, 4, 0, 0, 6, 5, 4, 0, 6, 5, 5, 4, 7, 5, 5, 4, + 7, 5, 5, 4, 7, 6, 6, 4, 7, 6, 6, 4, 8, 7, 7, 5, + 8, 8, 7, 6, 9, 8, 8, 7, 9, 9, 8, 8, 9, 9, 9, 8, + 10, 9, 9, 9, 10,10,10,10, 10,10,10,10, 10,10,10,10, +}, +{ + 6, 0, 0, 0, + 6, 6, 0, 0, 6, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +} +}; + +static const uint8_t coeff_token_bits[4][4*17]={ +{ + 1, 0, 0, 0, + 5, 1, 0, 0, 7, 4, 1, 0, 7, 6, 5, 3, 7, 6, 5, 3, + 7, 6, 5, 4, 15, 6, 5, 4, 11,14, 5, 4, 8,10,13, 4, + 15,14, 9, 4, 11,10,13,12, 15,14, 9,12, 11,10,13, 8, + 15, 1, 9,12, 11,14,13, 8, 7,10, 9,12, 4, 6, 5, 8, +}, +{ + 3, 0, 0, 0, + 11, 2, 0, 0, 7, 7, 3, 0, 7,10, 9, 5, 7, 6, 5, 4, + 4, 6, 5, 6, 7, 6, 5, 8, 15, 6, 5, 4, 11,14,13, 4, + 15,10, 9, 4, 11,14,13,12, 8,10, 9, 8, 15,14,13,12, + 11,10, 9,12, 7,11, 6, 8, 9, 8,10, 1, 7, 6, 5, 4, +}, +{ + 15, 0, 0, 0, + 15,14, 0, 0, 11,15,13, 0, 8,12,14,12, 15,10,11,11, + 11, 8, 9,10, 9,14,13, 9, 8,10, 9, 8, 15,14,13,13, + 11,14,10,12, 15,10,13,12, 11,14, 9,12, 8,10,13, 8, + 13, 7, 9,12, 9,12,11,10, 5, 8, 7, 6, 1, 4, 3, 2, +}, +{ + 3, 0, 0, 0, + 0, 1, 0, 0, 4, 5, 6, 0, 8, 9,10,11, 12,13,14,15, + 16,17,18,19, 20,21,22,23, 24,25,26,27, 28,29,30,31, + 32,33,34,35, 36,37,38,39, 40,41,42,43, 44,45,46,47, + 48,49,50,51, 52,53,54,55, 56,57,58,59, 60,61,62,63, +} +}; + +static const uint8_t total_zeros_len[16][16]= { + {1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9}, + {3,3,3,3,3,4,4,4,4,5,5,6,6,6,6}, + {4,3,3,3,4,4,3,3,4,5,5,6,5,6}, + {5,3,4,4,3,3,3,4,3,4,5,5,5}, + {4,4,4,3,3,3,3,3,4,5,4,5}, + {6,5,3,3,3,3,3,3,4,3,6}, + {6,5,3,3,3,2,3,4,3,6}, + {6,4,5,3,2,2,3,3,6}, + {6,6,4,2,2,3,2,5}, + {5,5,3,2,2,2,4}, + {4,4,3,3,1,3}, + {4,4,2,1,3}, + {3,3,1,2}, + {2,2,1}, + {1,1}, +}; + +static const uint8_t total_zeros_bits[16][16]= { + {1,3,2,3,2,3,2,3,2,3,2,3,2,3,2,1}, + {7,6,5,4,3,5,4,3,2,3,2,3,2,1,0}, + {5,7,6,5,4,3,4,3,2,3,2,1,1,0}, + {3,7,5,4,6,5,4,3,3,2,2,1,0}, + {5,4,3,7,6,5,4,3,2,1,1,0}, + {1,1,7,6,5,4,3,2,1,1,0}, + {1,1,5,4,3,3,2,1,1,0}, + {1,1,1,3,3,2,2,1,0}, + {1,0,1,3,2,1,1,1}, + {1,0,1,3,2,1,1}, + {0,1,1,2,1,3}, + {0,1,1,1,1}, + {0,1,1,1}, + {0,1,1}, + {0,1}, +}; + +static const uint8_t chroma_dc_total_zeros_len[3][4]= { + { 1, 2, 3, 3,}, + { 1, 2, 2, 0,}, + { 1, 1, 0, 0,}, +}; + +static const uint8_t chroma_dc_total_zeros_bits[3][4]= { + { 1, 1, 1, 0,}, + { 1, 1, 0, 0,}, + { 1, 0, 0, 0,}, +}; + +static const uint8_t chroma422_dc_total_zeros_len[7][8]= { + { 1, 3, 3, 4, 4, 4, 5, 5 }, + { 3, 2, 3, 3, 3, 3, 3 }, + { 3, 3, 2, 2, 3, 3 }, + { 3, 2, 2, 2, 3 }, + { 2, 2, 2, 2 }, + { 2, 2, 1 }, + { 1, 1 }, +}; + +static const uint8_t chroma422_dc_total_zeros_bits[7][8]= { + { 1, 2, 3, 2, 3, 1, 1, 0 }, + { 0, 1, 1, 4, 5, 6, 7 }, + { 0, 1, 1, 2, 6, 7 }, + { 6, 0, 1, 2, 7 }, + { 0, 1, 2, 3 }, + { 0, 1, 1 }, + { 0, 1 }, +}; + +static const uint8_t run_len[7][16]={ + {1,1}, + {1,2,2}, + {2,2,2,2}, + {2,2,2,3,3}, + {2,2,3,3,3,3}, + {2,3,3,3,3,3,3}, + {3,3,3,3,3,3,3,4,5,6,7,8,9,10,11}, +}; + +static const uint8_t run_bits[7][16]={ + {1,0}, + {1,1,0}, + {3,2,1,0}, + {3,2,1,1,0}, + {3,2,3,2,1,0}, + {3,0,1,3,2,5,4}, + {7,6,5,4,3,2,1,1,1,1,1,1,1,1,1}, +}; + +static VLC coeff_token_vlc[4]; +static VLC_TYPE coeff_token_vlc_tables[520+332+280+256][2]; +static const int coeff_token_vlc_tables_size[4]={520,332,280,256}; + +static VLC chroma_dc_coeff_token_vlc; +static VLC_TYPE chroma_dc_coeff_token_vlc_table[256][2]; +static const int chroma_dc_coeff_token_vlc_table_size = 256; + +static VLC chroma422_dc_coeff_token_vlc; +static VLC_TYPE chroma422_dc_coeff_token_vlc_table[8192][2]; +static const int chroma422_dc_coeff_token_vlc_table_size = 8192; + +static VLC total_zeros_vlc[15]; +static VLC_TYPE total_zeros_vlc_tables[15][512][2]; +static const int total_zeros_vlc_tables_size = 512; + +static VLC chroma_dc_total_zeros_vlc[3]; +static VLC_TYPE chroma_dc_total_zeros_vlc_tables[3][8][2]; +static const int chroma_dc_total_zeros_vlc_tables_size = 8; + +static VLC chroma422_dc_total_zeros_vlc[7]; +static VLC_TYPE chroma422_dc_total_zeros_vlc_tables[7][32][2]; +static const int chroma422_dc_total_zeros_vlc_tables_size = 32; + +static VLC run_vlc[6]; +static VLC_TYPE run_vlc_tables[6][8][2]; +static const int run_vlc_tables_size = 8; + +static VLC run7_vlc; +static VLC_TYPE run7_vlc_table[96][2]; +static const int run7_vlc_table_size = 96; + +#define LEVEL_TAB_BITS 8 +static int8_t cavlc_level_tab[7][1<non_zero_count_cache[index8 - 1]; + const int top = h->non_zero_count_cache[index8 - 8]; + int i= left + top; + + if(i<64) i= (i+1)>>1; + + tprintf(h->avctx, "pred_nnz L%X T%X n%d s%d P%X\n", left, top, n, scan8[n], i&31); + + return i&31; +} + +static av_cold void init_cavlc_level_tab(void){ + int suffix_length; + unsigned int i; + + for(suffix_length=0; suffix_length<7; suffix_length++){ + for(i=0; i<(1<> (av_log2(i) - suffix_length)) - (1 << suffix_length); + int mask = -(level_code&1); + level_code = (((2 + level_code) >> 1) ^ mask) - mask; + cavlc_level_tab[suffix_length][i][0]= level_code; + cavlc_level_tab[suffix_length][i][1]= prefix + 1 + suffix_length; + }else if(prefix + 1 <= LEVEL_TAB_BITS){ + cavlc_level_tab[suffix_length][i][0]= prefix+100; + cavlc_level_tab[suffix_length][i][1]= prefix + 1; + }else{ + cavlc_level_tab[suffix_length][i][0]= LEVEL_TAB_BITS+100; + cavlc_level_tab[suffix_length][i][1]= LEVEL_TAB_BITS; + } + } + } +} + +av_cold void ff_h264_decode_init_vlc(void){ + static int done = 0; + + if (!done) { + int i; + int offset; + done = 1; + + chroma_dc_coeff_token_vlc.table = chroma_dc_coeff_token_vlc_table; + chroma_dc_coeff_token_vlc.table_allocated = chroma_dc_coeff_token_vlc_table_size; + init_vlc(&chroma_dc_coeff_token_vlc, CHROMA_DC_COEFF_TOKEN_VLC_BITS, 4*5, + &chroma_dc_coeff_token_len [0], 1, 1, + &chroma_dc_coeff_token_bits[0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + + chroma422_dc_coeff_token_vlc.table = chroma422_dc_coeff_token_vlc_table; + chroma422_dc_coeff_token_vlc.table_allocated = chroma422_dc_coeff_token_vlc_table_size; + init_vlc(&chroma422_dc_coeff_token_vlc, CHROMA422_DC_COEFF_TOKEN_VLC_BITS, 4*9, + &chroma422_dc_coeff_token_len [0], 1, 1, + &chroma422_dc_coeff_token_bits[0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + + offset = 0; + for(i=0; i<4; i++){ + coeff_token_vlc[i].table = coeff_token_vlc_tables+offset; + coeff_token_vlc[i].table_allocated = coeff_token_vlc_tables_size[i]; + init_vlc(&coeff_token_vlc[i], COEFF_TOKEN_VLC_BITS, 4*17, + &coeff_token_len [i][0], 1, 1, + &coeff_token_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + offset += coeff_token_vlc_tables_size[i]; + } + /* + * This is a one time safety check to make sure that + * the packed static coeff_token_vlc table sizes + * were initialized correctly. + */ + av_assert0(offset == FF_ARRAY_ELEMS(coeff_token_vlc_tables)); + + for(i=0; i<3; i++){ + chroma_dc_total_zeros_vlc[i].table = chroma_dc_total_zeros_vlc_tables[i]; + chroma_dc_total_zeros_vlc[i].table_allocated = chroma_dc_total_zeros_vlc_tables_size; + init_vlc(&chroma_dc_total_zeros_vlc[i], + CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 4, + &chroma_dc_total_zeros_len [i][0], 1, 1, + &chroma_dc_total_zeros_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + } + + for(i=0; i<7; i++){ + chroma422_dc_total_zeros_vlc[i].table = chroma422_dc_total_zeros_vlc_tables[i]; + chroma422_dc_total_zeros_vlc[i].table_allocated = chroma422_dc_total_zeros_vlc_tables_size; + init_vlc(&chroma422_dc_total_zeros_vlc[i], + CHROMA422_DC_TOTAL_ZEROS_VLC_BITS, 8, + &chroma422_dc_total_zeros_len [i][0], 1, 1, + &chroma422_dc_total_zeros_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + } + + for(i=0; i<15; i++){ + total_zeros_vlc[i].table = total_zeros_vlc_tables[i]; + total_zeros_vlc[i].table_allocated = total_zeros_vlc_tables_size; + init_vlc(&total_zeros_vlc[i], + TOTAL_ZEROS_VLC_BITS, 16, + &total_zeros_len [i][0], 1, 1, + &total_zeros_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + } + + for(i=0; i<6; i++){ + run_vlc[i].table = run_vlc_tables[i]; + run_vlc[i].table_allocated = run_vlc_tables_size; + init_vlc(&run_vlc[i], + RUN_VLC_BITS, 7, + &run_len [i][0], 1, 1, + &run_bits[i][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + } + run7_vlc.table = run7_vlc_table, + run7_vlc.table_allocated = run7_vlc_table_size; + init_vlc(&run7_vlc, RUN7_VLC_BITS, 16, + &run_len [6][0], 1, 1, + &run_bits[6][0], 1, 1, + INIT_VLC_USE_NEW_STATIC); + + init_cavlc_level_tab(); + } +} + +/** + * + */ +static inline int get_level_prefix(GetBitContext *gb){ + unsigned int buf; + int log; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf=GET_CACHE(re, gb); + + log= 32 - av_log2(buf); +#ifdef TRACE + print_bin(buf>>(32-log), log); + av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d lpr @%5d in %s get_level_prefix\n", buf>>(32-log), log, log-1, get_bits_count(gb), __FILE__); +#endif + + LAST_SKIP_BITS(re, gb, log); + CLOSE_READER(re, gb); + + return log-1; +} + +/** + * Decode a residual block. + * @param n block index + * @param scantable scantable + * @param max_coeff number of coefficients in the block + * @return <0 if an error occurred + */ +static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff){ + static const int coeff_token_table_index[17]= {0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + int level[16]; + int zeros_left, coeff_token, total_coeff, i, trailing_ones, run_before; + + //FIXME put trailing_onex into the context + + if(max_coeff <= 8){ + if (max_coeff == 4) + coeff_token = get_vlc2(gb, chroma_dc_coeff_token_vlc.table, CHROMA_DC_COEFF_TOKEN_VLC_BITS, 1); + else + coeff_token = get_vlc2(gb, chroma422_dc_coeff_token_vlc.table, CHROMA422_DC_COEFF_TOKEN_VLC_BITS, 1); + total_coeff= coeff_token>>2; + }else{ + if(n >= LUMA_DC_BLOCK_INDEX){ + total_coeff= pred_non_zero_count(h, (n - LUMA_DC_BLOCK_INDEX)*16); + coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2); + total_coeff= coeff_token>>2; + }else{ + total_coeff= pred_non_zero_count(h, n); + coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2); + total_coeff= coeff_token>>2; + } + } + h->non_zero_count_cache[ scan8[n] ]= total_coeff; + + //FIXME set last_non_zero? + + if(total_coeff==0) + return 0; + if(total_coeff > (unsigned)max_coeff) { + av_log(h->avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", h->mb_x, h->mb_y, total_coeff); + return -1; + } + + trailing_ones= coeff_token&3; + tprintf(h->avctx, "trailing:%d, total:%d\n", trailing_ones, total_coeff); + av_assert2(total_coeff<=16); + + i = show_bits(gb, 3); + skip_bits(gb, trailing_ones); + level[0] = 1-((i&4)>>1); + level[1] = 1-((i&2) ); + level[2] = 1-((i&1)<<1); + + if(trailing_ones 10 & trailing_ones < 3; + int bitsi= show_bits(gb, LEVEL_TAB_BITS); + int level_code= cavlc_level_tab[suffix_length][bitsi][0]; + + skip_bits(gb, cavlc_level_tab[suffix_length][bitsi][1]); + if(level_code >= 100){ + prefix= level_code - 100; + if(prefix == LEVEL_TAB_BITS) + prefix += get_level_prefix(gb); + + //first coefficient has suffix_length equal to 0 or 1 + if(prefix<14){ //FIXME try to build a large unified VLC table for all this + if(suffix_length) + level_code= (prefix<<1) + get_bits1(gb); //part + else + level_code= prefix; //part + }else if(prefix==14){ + if(suffix_length) + level_code= (prefix<<1) + get_bits1(gb); //part + else + level_code= prefix + get_bits(gb, 4); //part + }else{ + level_code= 30; + if(prefix>=16){ + if(prefix > 25+3){ + av_log(h->avctx, AV_LOG_ERROR, "Invalid level prefix\n"); + return -1; + } + level_code += (1<<(prefix-3))-4096; + } + level_code += get_bits(gb, prefix-3); //part + } + + if(trailing_ones < 3) level_code += 2; + + suffix_length = 2; + mask= -(level_code&1); + level[trailing_ones]= (((2+level_code)>>1) ^ mask) - mask; + }else{ + level_code += ((level_code>>31)|1) & -(trailing_ones < 3); + + suffix_length = 1 + (level_code + 3U > 6U); + level[trailing_ones]= level_code; + } + + //remaining coefficients have suffix_length > 0 + for(i=trailing_ones+1;i= 100){ + prefix= level_code - 100; + if(prefix == LEVEL_TAB_BITS){ + prefix += get_level_prefix(gb); + } + if(prefix<15){ + level_code = (prefix<=16) + level_code += (1<<(prefix-3))-4096; + } + mask= -(level_code&1); + level_code= (((2+level_code)>>1) ^ mask) - mask; + } + level[i]= level_code; + suffix_length+= suffix_limit[suffix_length] + level_code > 2U*suffix_limit[suffix_length]; + } + } + + if(total_coeff == max_coeff) + zeros_left=0; + else{ + if (max_coeff <= 8) { + if (max_coeff == 4) + zeros_left = get_vlc2(gb, (chroma_dc_total_zeros_vlc-1)[total_coeff].table, + CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 1); + else + zeros_left = get_vlc2(gb, (chroma422_dc_total_zeros_vlc-1)[total_coeff].table, + CHROMA422_DC_TOTAL_ZEROS_VLC_BITS, 1); + } else { + zeros_left= get_vlc2(gb, (total_zeros_vlc-1)[ total_coeff ].table, TOTAL_ZEROS_VLC_BITS, 1); + } + } + +#define STORE_BLOCK(type) \ + scantable += zeros_left + total_coeff - 1; \ + if(n >= LUMA_DC_BLOCK_INDEX){ \ + ((type*)block)[*scantable] = level[0]; \ + for(i=1;i 0;i++) { \ + if(zeros_left < 7) \ + run_before= get_vlc2(gb, (run_vlc-1)[zeros_left].table, RUN_VLC_BITS, 1); \ + else \ + run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \ + zeros_left -= run_before; \ + scantable -= 1 + run_before; \ + ((type*)block)[*scantable]= level[i]; \ + } \ + for(;i>6; \ + for(i=1;i 0;i++) { \ + if(zeros_left < 7) \ + run_before= get_vlc2(gb, (run_vlc-1)[zeros_left].table, RUN_VLC_BITS, 1); \ + else \ + run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \ + zeros_left -= run_before; \ + scantable -= 1 + run_before; \ + ((type*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6; \ + } \ + for(;i>6; \ + } \ + } + + if (h->pixel_shift) { + STORE_BLOCK(int32_t) + } else { + STORE_BLOCK(int16_t) + } + + if(zeros_left<0){ + av_log(h->avctx, AV_LOG_ERROR, "negative number of zero coeffs at %d %d\n", h->mb_x, h->mb_y); + return -1; + } + + return 0; +} + +static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext *gb, const uint8_t *scan, const uint8_t *scan8x8, int pixel_shift, int mb_type, int cbp, int p){ + int i4x4, i8x8; + int qscale = p == 0 ? h->qscale : h->chroma_qp[p-1]; + if(IS_INTRA16x16(mb_type)){ + AV_ZERO128(h->mb_luma_dc[p]+0); + AV_ZERO128(h->mb_luma_dc[p]+8); + AV_ZERO128(h->mb_luma_dc[p]+16); + AV_ZERO128(h->mb_luma_dc[p]+24); + if( decode_residual(h, h->intra_gb_ptr, h->mb_luma_dc[p], LUMA_DC_BLOCK_INDEX+p, scan, NULL, 16) < 0){ + return -1; //FIXME continue if partitioned and other return -1 too + } + + av_assert2((cbp&15) == 0 || (cbp&15) == 15); + + if(cbp&15){ + for(i8x8=0; i8x8<4; i8x8++){ + for(i4x4=0; i4x4<4; i4x4++){ + const int index= i4x4 + 4*i8x8 + p*16; + if( decode_residual(h, h->intra_gb_ptr, h->mb + (16*index << pixel_shift), + index, scan + 1, h->dequant4_coeff[p][qscale], 15) < 0 ){ + return -1; + } + } + } + return 0xf; + }else{ + fill_rectangle(&h->non_zero_count_cache[scan8[p*16]], 4, 4, 8, 0, 1); + return 0; + } + }else{ + int cqm = (IS_INTRA( mb_type ) ? 0:3)+p; + /* For CAVLC 4:4:4, we need to keep track of the luma 8x8 CBP for deblocking nnz purposes. */ + int new_cbp = 0; + for(i8x8=0; i8x8<4; i8x8++){ + if(cbp & (1<mb[64*i8x8+256*p << pixel_shift]; + uint8_t *nnz; + for(i4x4=0; i4x4<4; i4x4++){ + const int index= i4x4 + 4*i8x8 + p*16; + if( decode_residual(h, gb, buf, index, scan8x8+16*i4x4, + h->dequant8_coeff[cqm][qscale], 16) < 0 ) + return -1; + } + nnz= &h->non_zero_count_cache[ scan8[4*i8x8+p*16] ]; + nnz[0] += nnz[1] + nnz[8] + nnz[9]; + new_cbp |= !!nnz[0] << i8x8; + }else{ + for(i4x4=0; i4x4<4; i4x4++){ + const int index= i4x4 + 4*i8x8 + p*16; + if( decode_residual(h, gb, h->mb + (16*index << pixel_shift), index, + scan, h->dequant4_coeff[cqm][qscale], 16) < 0 ){ + return -1; + } + new_cbp |= h->non_zero_count_cache[ scan8[index] ] << i8x8; + } + } + }else{ + uint8_t * const nnz= &h->non_zero_count_cache[ scan8[4*i8x8+p*16] ]; + nnz[0] = nnz[1] = nnz[8] = nnz[9] = 0; + } + } + return new_cbp; + } +} + +int ff_h264_decode_mb_cavlc(H264Context *h){ + int mb_xy; + int partition_count; + unsigned int mb_type, cbp; + int dct8x8_allowed= h->pps.transform_8x8_mode; + int decode_chroma = h->sps.chroma_format_idc == 1 || h->sps.chroma_format_idc == 2; + const int pixel_shift = h->pixel_shift; + unsigned local_ref_count[2]; + + mb_xy = h->mb_xy = h->mb_x + h->mb_y*h->mb_stride; + + tprintf(h->avctx, "pic:%d mb:%d/%d\n", h->frame_num, h->mb_x, h->mb_y); + cbp = 0; /* avoid warning. FIXME: find a solution without slowing + down the code */ + if(h->slice_type_nos != AV_PICTURE_TYPE_I){ + if(h->mb_skip_run==-1) + h->mb_skip_run= get_ue_golomb(&h->gb); + + if (h->mb_skip_run--) { + if(FRAME_MBAFF(h) && (h->mb_y&1) == 0){ + if(h->mb_skip_run==0) + h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&h->gb); + } + decode_mb_skip(h); + return 0; + } + } + if (FRAME_MBAFF(h)) { + if( (h->mb_y&1) == 0 ) + h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&h->gb); + } + + h->prev_mb_skipped= 0; + + mb_type= get_ue_golomb(&h->gb); + if(h->slice_type_nos == AV_PICTURE_TYPE_B){ + if(mb_type < 23){ + partition_count= b_mb_type_info[mb_type].partition_count; + mb_type= b_mb_type_info[mb_type].type; + }else{ + mb_type -= 23; + goto decode_intra_mb; + } + }else if(h->slice_type_nos == AV_PICTURE_TYPE_P){ + if(mb_type < 5){ + partition_count= p_mb_type_info[mb_type].partition_count; + mb_type= p_mb_type_info[mb_type].type; + }else{ + mb_type -= 5; + goto decode_intra_mb; + } + }else{ + av_assert2(h->slice_type_nos == AV_PICTURE_TYPE_I); + if(h->slice_type == AV_PICTURE_TYPE_SI && mb_type) + mb_type--; +decode_intra_mb: + if(mb_type > 25){ + av_log(h->avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_picture_type_char(h->slice_type), h->mb_x, h->mb_y); + return -1; + } + partition_count=0; + cbp= i_mb_type_info[mb_type].cbp; + h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode; + mb_type= i_mb_type_info[mb_type].type; + } + + if(MB_FIELD(h)) + mb_type |= MB_TYPE_INTERLACED; + + h->slice_table[ mb_xy ]= h->slice_num; + + if(IS_INTRA_PCM(mb_type)){ + const int mb_size = ff_h264_mb_sizes[h->sps.chroma_format_idc] * + h->sps.bit_depth_luma; + + // We assume these blocks are very rare so we do not optimize it. + h->intra_pcm_ptr = align_get_bits(&h->gb); + skip_bits_long(&h->gb, mb_size); + + // In deblocking, the quantizer is 0 + h->cur_pic.qscale_table[mb_xy] = 0; + // All coeffs are present + memset(h->non_zero_count[mb_xy], 16, 48); + + h->cur_pic.mb_type[mb_xy] = mb_type; + return 0; + } + + local_ref_count[0] = h->ref_count[0] << MB_MBAFF(h); + local_ref_count[1] = h->ref_count[1] << MB_MBAFF(h); + + fill_decode_neighbors(h, mb_type); + fill_decode_caches(h, mb_type); + + //mb_pred + if(IS_INTRA(mb_type)){ + int pred_mode; +// init_top_left_availability(h); + if(IS_INTRA4x4(mb_type)){ + int i; + int di = 1; + if(dct8x8_allowed && get_bits1(&h->gb)){ + mb_type |= MB_TYPE_8x8DCT; + di = 4; + } + +// fill_intra4x4_pred_table(h); + for(i=0; i<16; i+=di){ + int mode= pred_intra_mode(h, i); + + if(!get_bits1(&h->gb)){ + const int rem_mode= get_bits(&h->gb, 3); + mode = rem_mode + (rem_mode >= mode); + } + + if(di==4) + fill_rectangle( &h->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 ); + else + h->intra4x4_pred_mode_cache[ scan8[i] ] = mode; + } + write_back_intra_pred_mode(h); + if( ff_h264_check_intra4x4_pred_mode(h) < 0) + return -1; + }else{ + h->intra16x16_pred_mode= ff_h264_check_intra_pred_mode(h, h->intra16x16_pred_mode, 0); + if(h->intra16x16_pred_mode < 0) + return -1; + } + if(decode_chroma){ + pred_mode= ff_h264_check_intra_pred_mode(h, get_ue_golomb_31(&h->gb), 1); + if(pred_mode < 0) + return -1; + h->chroma_pred_mode= pred_mode; + } else { + h->chroma_pred_mode = DC_128_PRED8x8; + } + }else if(partition_count==4){ + int i, j, sub_partition_count[4], list, ref[2][4]; + + if(h->slice_type_nos == AV_PICTURE_TYPE_B){ + for(i=0; i<4; i++){ + h->sub_mb_type[i]= get_ue_golomb_31(&h->gb); + if(h->sub_mb_type[i] >=13){ + av_log(h->avctx, AV_LOG_ERROR, "B sub_mb_type %u out of range at %d %d\n", h->sub_mb_type[i], h->mb_x, h->mb_y); + return -1; + } + sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count; + h->sub_mb_type[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].type; + } + if( IS_DIRECT(h->sub_mb_type[0]|h->sub_mb_type[1]|h->sub_mb_type[2]|h->sub_mb_type[3])) { + ff_h264_pred_direct_motion(h, &mb_type); + h->ref_cache[0][scan8[4]] = + h->ref_cache[1][scan8[4]] = + h->ref_cache[0][scan8[12]] = + h->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE; + } + }else{ + av_assert2(h->slice_type_nos == AV_PICTURE_TYPE_P); //FIXME SP correct ? + for(i=0; i<4; i++){ + h->sub_mb_type[i]= get_ue_golomb_31(&h->gb); + if(h->sub_mb_type[i] >=4){ + av_log(h->avctx, AV_LOG_ERROR, "P sub_mb_type %u out of range at %d %d\n", h->sub_mb_type[i], h->mb_x, h->mb_y); + return -1; + } + sub_partition_count[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count; + h->sub_mb_type[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].type; + } + } + + for(list=0; listlist_count; list++){ + int ref_count= IS_REF0(mb_type) ? 1 : local_ref_count[list]; + for(i=0; i<4; i++){ + if(IS_DIRECT(h->sub_mb_type[i])) continue; + if(IS_DIR(h->sub_mb_type[i], 0, list)){ + unsigned int tmp; + if(ref_count == 1){ + tmp= 0; + }else if(ref_count == 2){ + tmp= get_bits1(&h->gb)^1; + }else{ + tmp= get_ue_golomb_31(&h->gb); + if(tmp>=ref_count){ + av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", tmp); + return -1; + } + } + ref[list][i]= tmp; + }else{ + //FIXME + ref[list][i] = -1; + } + } + } + + if(dct8x8_allowed) + dct8x8_allowed = get_dct8x8_allowed(h); + + for(list=0; listlist_count; list++){ + for(i=0; i<4; i++){ + if(IS_DIRECT(h->sub_mb_type[i])) { + h->ref_cache[list][ scan8[4*i] ] = h->ref_cache[list][ scan8[4*i]+1 ]; + continue; + } + h->ref_cache[list][ scan8[4*i] ]=h->ref_cache[list][ scan8[4*i]+1 ]= + h->ref_cache[list][ scan8[4*i]+8 ]=h->ref_cache[list][ scan8[4*i]+9 ]= ref[list][i]; + + if(IS_DIR(h->sub_mb_type[i], 0, list)){ + const int sub_mb_type= h->sub_mb_type[i]; + const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1; + for(j=0; jmv_cache[list][ scan8[index] ]; + pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mx, &my); + mx += get_se_golomb(&h->gb); + my += get_se_golomb(&h->gb); + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + if(IS_SUB_8X8(sub_mb_type)){ + mv_cache[ 1 ][0]= + mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx; + mv_cache[ 1 ][1]= + mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my; + }else if(IS_SUB_8X4(sub_mb_type)){ + mv_cache[ 1 ][0]= mx; + mv_cache[ 1 ][1]= my; + }else if(IS_SUB_4X8(sub_mb_type)){ + mv_cache[ 8 ][0]= mx; + mv_cache[ 8 ][1]= my; + } + mv_cache[ 0 ][0]= mx; + mv_cache[ 0 ][1]= my; + } + }else{ + uint32_t *p= (uint32_t *)&h->mv_cache[list][ scan8[4*i] ][0]; + p[0] = p[1]= + p[8] = p[9]= 0; + } + } + } + }else if(IS_DIRECT(mb_type)){ + ff_h264_pred_direct_motion(h, &mb_type); + dct8x8_allowed &= h->sps.direct_8x8_inference_flag; + }else{ + int list, mx, my, i; + //FIXME we should set ref_idx_l? to 0 if we use that later ... + if(IS_16X16(mb_type)){ + for(list=0; listlist_count; list++){ + unsigned int val; + if(IS_DIR(mb_type, 0, list)){ + if(local_ref_count[list]==1){ + val= 0; + }else if(local_ref_count[list]==2){ + val= get_bits1(&h->gb)^1; + }else{ + val= get_ue_golomb_31(&h->gb); + if(val >= local_ref_count[list]){ + av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", val); + return -1; + } + } + fill_rectangle(&h->ref_cache[list][ scan8[0] ], 4, 4, 8, val, 1); + } + } + for(list=0; listlist_count; list++){ + if(IS_DIR(mb_type, 0, list)){ + pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mx, &my); + mx += get_se_golomb(&h->gb); + my += get_se_golomb(&h->gb); + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4); + } + } + } + else if(IS_16X8(mb_type)){ + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + unsigned int val; + if(IS_DIR(mb_type, i, list)){ + if(local_ref_count[list] == 1){ + val= 0; + }else if(local_ref_count[list] == 2){ + val= get_bits1(&h->gb)^1; + }else{ + val= get_ue_golomb_31(&h->gb); + if(val >= local_ref_count[list]){ + av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", val); + return -1; + } + } + }else + val= LIST_NOT_USED&0xFF; + fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 1); + } + } + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + unsigned int val; + if(IS_DIR(mb_type, i, list)){ + pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mx, &my); + mx += get_se_golomb(&h->gb); + my += get_se_golomb(&h->gb); + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + val= pack16to32(mx,my); + }else + val=0; + fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 4); + } + } + }else{ + av_assert2(IS_8X16(mb_type)); + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + unsigned int val; + if(IS_DIR(mb_type, i, list)){ //FIXME optimize + if(local_ref_count[list]==1){ + val= 0; + }else if(local_ref_count[list]==2){ + val= get_bits1(&h->gb)^1; + }else{ + val= get_ue_golomb_31(&h->gb); + if(val >= local_ref_count[list]){ + av_log(h->avctx, AV_LOG_ERROR, "ref %u overflow\n", val); + return -1; + } + } + }else + val= LIST_NOT_USED&0xFF; + fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 1); + } + } + for(list=0; listlist_count; list++){ + for(i=0; i<2; i++){ + unsigned int val; + if(IS_DIR(mb_type, i, list)){ + pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mx, &my); + mx += get_se_golomb(&h->gb); + my += get_se_golomb(&h->gb); + tprintf(h->avctx, "final mv:%d %d\n", mx, my); + + val= pack16to32(mx,my); + }else + val=0; + fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 4); + } + } + } + } + + if(IS_INTER(mb_type)) + write_back_motion(h, mb_type); + + if(!IS_INTRA16x16(mb_type)){ + cbp= get_ue_golomb(&h->gb); + + if(decode_chroma){ + if(cbp > 47){ + av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, h->mb_x, h->mb_y); + return -1; + } + if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp[cbp]; + else cbp= golomb_to_inter_cbp [cbp]; + }else{ + if(cbp > 15){ + av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, h->mb_x, h->mb_y); + return -1; + } + if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp_gray[cbp]; + else cbp= golomb_to_inter_cbp_gray[cbp]; + } + } else { + if (!decode_chroma && cbp>15) { + av_log(h->avctx, AV_LOG_ERROR, "gray chroma\n"); + return AVERROR_INVALIDDATA; + } + } + + if(dct8x8_allowed && (cbp&15) && !IS_INTRA(mb_type)){ + mb_type |= MB_TYPE_8x8DCT*get_bits1(&h->gb); + } + h->cbp= + h->cbp_table[mb_xy]= cbp; + h->cur_pic.mb_type[mb_xy] = mb_type; + + if(cbp || IS_INTRA16x16(mb_type)){ + int i4x4, i8x8, chroma_idx; + int dquant; + int ret; + GetBitContext *gb= IS_INTRA(mb_type) ? h->intra_gb_ptr : h->inter_gb_ptr; + const uint8_t *scan, *scan8x8; + const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8); + + if(IS_INTERLACED(mb_type)){ + scan8x8= h->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0; + scan= h->qscale ? h->field_scan : h->field_scan_q0; + }else{ + scan8x8= h->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0; + scan= h->qscale ? h->zigzag_scan : h->zigzag_scan_q0; + } + + dquant= get_se_golomb(&h->gb); + + h->qscale += dquant; + + if(((unsigned)h->qscale) > max_qp){ + if(h->qscale<0) h->qscale+= max_qp+1; + else h->qscale-= max_qp+1; + if(((unsigned)h->qscale) > max_qp){ + av_log(h->avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, h->mb_x, h->mb_y); + return -1; + } + } + + h->chroma_qp[0]= get_chroma_qp(h, 0, h->qscale); + h->chroma_qp[1]= get_chroma_qp(h, 1, h->qscale); + + if( (ret = decode_luma_residual(h, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 0)) < 0 ){ + return -1; + } + h->cbp_table[mb_xy] |= ret << 12; + if(CHROMA444){ + if( decode_luma_residual(h, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 1) < 0 ){ + return -1; + } + if( decode_luma_residual(h, gb, scan, scan8x8, pixel_shift, mb_type, cbp, 2) < 0 ){ + return -1; + } + } else { + const int num_c8x8 = h->sps.chroma_format_idc; + + if(cbp&0x30){ + for(chroma_idx=0; chroma_idx<2; chroma_idx++) + if (decode_residual(h, gb, h->mb + ((256 + 16*16*chroma_idx) << pixel_shift), + CHROMA_DC_BLOCK_INDEX+chroma_idx, + CHROMA422 ? chroma422_dc_scan : chroma_dc_scan, + NULL, 4*num_c8x8) < 0) { + return -1; + } + } + + if(cbp&0x20){ + for(chroma_idx=0; chroma_idx<2; chroma_idx++){ + const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[chroma_idx]]; + int16_t *mb = h->mb + (16*(16 + 16*chroma_idx) << pixel_shift); + for (i8x8=0; i8x8non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + } + } + }else{ + fill_rectangle(&h->non_zero_count_cache[scan8[ 0]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[16]], 4, 4, 8, 0, 1); + fill_rectangle(&h->non_zero_count_cache[scan8[32]], 4, 4, 8, 0, 1); + } + h->cur_pic.qscale_table[mb_xy] = h->qscale; + write_back_non_zero_count(h); + + return 0; +} diff --git a/ffmpeg/libavcodec/h264_direct.c b/ffmpeg/libavcodec/h264_direct.c new file mode 100644 index 0000000..2f49d0a --- /dev/null +++ b/ffmpeg/libavcodec/h264_direct.c @@ -0,0 +1,628 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... direct mb/block decoding + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 direct mb/block decoding. + * @author Michael Niedermayer + */ + +#include "internal.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h264.h" +#include "rectangle.h" +#include "thread.h" + +//#undef NDEBUG +#include + + +static int get_scale_factor(H264Context * const h, int poc, int poc1, int i){ + int poc0 = h->ref_list[0][i].poc; + int td = av_clip(poc1 - poc0, -128, 127); + if(td == 0 || h->ref_list[0][i].long_ref){ + return 256; + }else{ + int tb = av_clip(poc - poc0, -128, 127); + int tx = (16384 + (FFABS(td) >> 1)) / td; + return av_clip((tb*tx + 32) >> 6, -1024, 1023); + } +} + +void ff_h264_direct_dist_scale_factor(H264Context * const h){ + const int poc = h->cur_pic_ptr->field_poc[h->picture_structure == PICT_BOTTOM_FIELD]; + const int poc1 = h->ref_list[1][0].poc; + int i, field; + + if (FRAME_MBAFF(h)) + for (field = 0; field < 2; field++){ + const int poc = h->cur_pic_ptr->field_poc[field]; + const int poc1 = h->ref_list[1][0].field_poc[field]; + for (i = 0; i < 2 * h->ref_count[0]; i++) + h->dist_scale_factor_field[field][i^field] = + get_scale_factor(h, poc, poc1, i+16); + } + + for (i = 0; i < h->ref_count[0]; i++){ + h->dist_scale_factor[i] = get_scale_factor(h, poc, poc1, i); + } +} + +static void fill_colmap(H264Context *h, int map[2][16+32], int list, int field, int colfield, int mbafi){ + Picture * const ref1 = &h->ref_list[1][0]; + int j, old_ref, rfield; + int start= mbafi ? 16 : 0; + int end = mbafi ? 16+2*h->ref_count[0] : h->ref_count[0]; + int interl= mbafi || h->picture_structure != PICT_FRAME; + + /* bogus; fills in for missing frames */ + memset(map[list], 0, sizeof(map[list])); + + for(rfield=0; rfield<2; rfield++){ + for(old_ref=0; old_refref_count[colfield][list]; old_ref++){ + int poc = ref1->ref_poc[colfield][list][old_ref]; + + if (!interl) + poc |= 3; + else if( interl && (poc&3) == 3) // FIXME: store all MBAFF references so this is not needed + poc= (poc&~3) + rfield + 1; + + for(j=start; jref_list[0][j].frame_num + (h->ref_list[0][j].reference & 3) == poc) { + int cur_ref= mbafi ? (j-16)^field : j; + if (ref1->mbaff) + map[list][2 * old_ref + (rfield^field) + 16] = cur_ref; + if(rfield == field || !interl) + map[list][old_ref] = cur_ref; + break; + } + } + } + } +} + +void ff_h264_direct_ref_list_init(H264Context * const h){ + Picture * const ref1 = &h->ref_list[1][0]; + Picture * const cur = h->cur_pic_ptr; + int list, j, field; + int sidx= (h->picture_structure&1)^1; + int ref1sidx = (ref1->reference&1)^1; + + for(list=0; list<2; list++){ + cur->ref_count[sidx][list] = h->ref_count[list]; + for(j=0; jref_count[list]; j++) + cur->ref_poc[sidx][list][j] = 4 * h->ref_list[list][j].frame_num + (h->ref_list[list][j].reference & 3); + } + + if(h->picture_structure == PICT_FRAME){ + memcpy(cur->ref_count[1], cur->ref_count[0], sizeof(cur->ref_count[0])); + memcpy(cur->ref_poc [1], cur->ref_poc [0], sizeof(cur->ref_poc [0])); + } + + cur->mbaff = FRAME_MBAFF(h); + + h->col_fieldoff= 0; + if(h->picture_structure == PICT_FRAME){ + int cur_poc = h->cur_pic_ptr->poc; + int *col_poc = h->ref_list[1]->field_poc; + h->col_parity= (FFABS(col_poc[0] - cur_poc) >= FFABS(col_poc[1] - cur_poc)); + ref1sidx=sidx= h->col_parity; + } else if (!(h->picture_structure & h->ref_list[1][0].reference) && !h->ref_list[1][0].mbaff) { // FL -> FL & differ parity + h->col_fieldoff = 2 * h->ref_list[1][0].reference - 3; + } + + if (h->slice_type_nos != AV_PICTURE_TYPE_B || h->direct_spatial_mv_pred) + return; + + for(list=0; list<2; list++){ + fill_colmap(h, h->map_col_to_list0, list, sidx, ref1sidx, 0); + if (FRAME_MBAFF(h)) + for(field=0; field<2; field++) + fill_colmap(h, h->map_col_to_list0_field[field], list, field, field, 1); + } +} + +static void await_reference_mb_row(H264Context * const h, Picture *ref, int mb_y) +{ + int ref_field = ref->reference - 1; + int ref_field_picture = ref->field_picture; + int ref_height = 16*h->mb_height >> ref_field_picture; + + if(!HAVE_THREADS || !(h->avctx->active_thread_type&FF_THREAD_FRAME)) + return; + + //FIXME it can be safe to access mb stuff + //even if pixels aren't deblocked yet + + ff_thread_await_progress(&ref->tf, + FFMIN(16 * mb_y >> ref_field_picture, ref_height - 1), + ref_field_picture && ref_field); +} + +static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ + int b8_stride = 2; + int b4_stride = h->b_stride; + int mb_xy = h->mb_xy, mb_y = h->mb_y; + int mb_type_col[2]; + const int16_t (*l1mv0)[2], (*l1mv1)[2]; + const int8_t *l1ref0, *l1ref1; + const int is_b8x8 = IS_8X8(*mb_type); + unsigned int sub_mb_type= MB_TYPE_L0L1; + int i8, i4; + int ref[2]; + int mv[2]; + int list; + + assert(h->ref_list[1][0].reference & 3); + + await_reference_mb_row(h, &h->ref_list[1][0], h->mb_y + !!IS_INTERLACED(*mb_type)); + +#define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM) + + + /* ref = min(neighbors) */ + for(list=0; list<2; list++){ + int left_ref = h->ref_cache[list][scan8[0] - 1]; + int top_ref = h->ref_cache[list][scan8[0] - 8]; + int refc = h->ref_cache[list][scan8[0] - 8 + 4]; + const int16_t *C= h->mv_cache[list][ scan8[0] - 8 + 4]; + if(refc == PART_NOT_AVAILABLE){ + refc = h->ref_cache[list][scan8[0] - 8 - 1]; + C = h-> mv_cache[list][scan8[0] - 8 - 1]; + } + ref[list] = FFMIN3((unsigned)left_ref, (unsigned)top_ref, (unsigned)refc); + if(ref[list] >= 0){ + //this is just pred_motion() but with the cases removed that cannot happen for direct blocks + const int16_t * const A= h->mv_cache[list][ scan8[0] - 1 ]; + const int16_t * const B= h->mv_cache[list][ scan8[0] - 8 ]; + + int match_count= (left_ref==ref[list]) + (top_ref==ref[list]) + (refc==ref[list]); + if(match_count > 1){ //most common + mv[list]= pack16to32(mid_pred(A[0], B[0], C[0]), + mid_pred(A[1], B[1], C[1]) ); + }else { + assert(match_count==1); + if(left_ref==ref[list]){ + mv[list]= AV_RN32A(A); + }else if(top_ref==ref[list]){ + mv[list]= AV_RN32A(B); + }else{ + mv[list]= AV_RN32A(C); + } + } + }else{ + int mask= ~(MB_TYPE_L0 << (2*list)); + mv[list] = 0; + ref[list] = -1; + if(!is_b8x8) + *mb_type &= mask; + sub_mb_type &= mask; + } + } + if(ref[0] < 0 && ref[1] < 0){ + ref[0] = ref[1] = 0; + if(!is_b8x8) + *mb_type |= MB_TYPE_L0L1; + sub_mb_type |= MB_TYPE_L0L1; + } + + if(!(is_b8x8|mv[0]|mv[1])){ + fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); + fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); + fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); + fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4); + *mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2; + return; + } + + if (IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL + if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL + mb_y = (h->mb_y&~1) + h->col_parity; + mb_xy= h->mb_x + ((h->mb_y&~1) + h->col_parity)*h->mb_stride; + b8_stride = 0; + }else{ + mb_y += h->col_fieldoff; + mb_xy += h->mb_stride*h->col_fieldoff; // non zero for FL -> FL & differ parity + } + goto single_col; + }else{ // AFL/AFR/FR/FL -> AFR/FR + if(IS_INTERLACED(*mb_type)){ // AFL /FL -> AFR/FR + mb_y = h->mb_y&~1; + mb_xy= h->mb_x + (h->mb_y&~1)*h->mb_stride; + mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; + mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + h->mb_stride]; + b8_stride = 2+4*h->mb_stride; + b4_stride *= 6; + if (IS_INTERLACED(mb_type_col[0]) != IS_INTERLACED(mb_type_col[1])) { + mb_type_col[0] &= ~MB_TYPE_INTERLACED; + mb_type_col[1] &= ~MB_TYPE_INTERLACED; + } + + sub_mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_SUB_8x8 */ + if( (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA) + && (mb_type_col[1] & MB_TYPE_16x16_OR_INTRA) + && !is_b8x8){ + *mb_type |= MB_TYPE_16x8 |MB_TYPE_DIRECT2; /* B_16x8 */ + }else{ + *mb_type |= MB_TYPE_8x8; + } + }else{ // AFR/FR -> AFR/FR +single_col: + mb_type_col[0] = + mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy]; + + sub_mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_SUB_8x8 */ + if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){ + *mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_16x16 */ + }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){ + *mb_type |= MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16)); + }else{ + if(!h->sps.direct_8x8_inference_flag){ + /* FIXME save sub mb types from previous frames (or derive from MVs) + * so we know exactly what block size to use */ + sub_mb_type += (MB_TYPE_8x8-MB_TYPE_16x16); /* B_SUB_4x4 */ + } + *mb_type |= MB_TYPE_8x8; + } + } + } + + await_reference_mb_row(h, &h->ref_list[1][0], mb_y); + + l1mv0 = (void*)&h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]]; + l1mv1 = (void*)&h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]]; + l1ref0 = &h->ref_list[1][0].ref_index [0][4 * mb_xy]; + l1ref1 = &h->ref_list[1][0].ref_index [1][4 * mb_xy]; + if(!b8_stride){ + if(h->mb_y&1){ + l1ref0 += 2; + l1ref1 += 2; + l1mv0 += 2*b4_stride; + l1mv1 += 2*b4_stride; + } + } + + + if(IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])){ + int n=0; + for(i8=0; i8<4; i8++){ + int x8 = i8&1; + int y8 = i8>>1; + int xy8 = x8+y8*b8_stride; + int xy4 = 3*x8+y8*b4_stride; + int a,b; + + if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + continue; + h->sub_mb_type[i8] = sub_mb_type; + + fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[0], 1); + fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[1], 1); + if(!IS_INTRA(mb_type_col[y8]) && !h->ref_list[1][0].long_ref + && ( (l1ref0[xy8] == 0 && FFABS(l1mv0[xy4][0]) <= 1 && FFABS(l1mv0[xy4][1]) <= 1) + || (l1ref0[xy8] < 0 && l1ref1[xy8] == 0 && FFABS(l1mv1[xy4][0]) <= 1 && FFABS(l1mv1[xy4][1]) <= 1))){ + a=b=0; + if(ref[0] > 0) + a= mv[0]; + if(ref[1] > 0) + b= mv[1]; + n++; + }else{ + a= mv[0]; + b= mv[1]; + } + fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, a, 4); + fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, b, 4); + } + if(!is_b8x8 && !(n&3)) + *mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2; + }else if(IS_16X16(*mb_type)){ + int a,b; + + fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); + fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); + if(!IS_INTRA(mb_type_col[0]) && !h->ref_list[1][0].long_ref + && ( (l1ref0[0] == 0 && FFABS(l1mv0[0][0]) <= 1 && FFABS(l1mv0[0][1]) <= 1) + || (l1ref0[0] < 0 && l1ref1[0] == 0 && FFABS(l1mv1[0][0]) <= 1 && FFABS(l1mv1[0][1]) <= 1 + && h->x264_build>33U))){ + a=b=0; + if(ref[0] > 0) + a= mv[0]; + if(ref[1] > 0) + b= mv[1]; + }else{ + a= mv[0]; + b= mv[1]; + } + fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, a, 4); + fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, b, 4); + }else{ + int n=0; + for(i8=0; i8<4; i8++){ + const int x8 = i8&1; + const int y8 = i8>>1; + + if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + continue; + h->sub_mb_type[i8] = sub_mb_type; + + fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, mv[0], 4); + fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, mv[1], 4); + fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[0], 1); + fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[1], 1); + + assert(b8_stride==2); + /* col_zero_flag */ + if(!IS_INTRA(mb_type_col[0]) && !h->ref_list[1][0].long_ref && ( l1ref0[i8] == 0 + || (l1ref0[i8] < 0 && l1ref1[i8] == 0 + && h->x264_build>33U))){ + const int16_t (*l1mv)[2]= l1ref0[i8] == 0 ? l1mv0 : l1mv1; + if(IS_SUB_8X8(sub_mb_type)){ + const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride]; + if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){ + if(ref[0] == 0) + fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4); + if(ref[1] == 0) + fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4); + n+=4; + } + }else{ + int m=0; + for(i4=0; i4<4; i4++){ + const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride]; + if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){ + if(ref[0] == 0) + AV_ZERO32(h->mv_cache[0][scan8[i8*4+i4]]); + if(ref[1] == 0) + AV_ZERO32(h->mv_cache[1][scan8[i8*4+i4]]); + m++; + } + } + if(!(m&3)) + h->sub_mb_type[i8]+= MB_TYPE_16x16 - MB_TYPE_8x8; + n+=m; + } + } + } + if(!is_b8x8 && !(n&15)) + *mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2; + } +} + +static void pred_temp_direct_motion(H264Context * const h, int *mb_type){ + int b8_stride = 2; + int b4_stride = h->b_stride; + int mb_xy = h->mb_xy, mb_y = h->mb_y; + int mb_type_col[2]; + const int16_t (*l1mv0)[2], (*l1mv1)[2]; + const int8_t *l1ref0, *l1ref1; + const int is_b8x8 = IS_8X8(*mb_type); + unsigned int sub_mb_type; + int i8, i4; + + assert(h->ref_list[1][0].reference & 3); + + await_reference_mb_row(h, &h->ref_list[1][0], h->mb_y + !!IS_INTERLACED(*mb_type)); + + if (IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL + if (!IS_INTERLACED(*mb_type)) { // AFR/FR -> AFL/FL + mb_y = (h->mb_y&~1) + h->col_parity; + mb_xy= h->mb_x + ((h->mb_y&~1) + h->col_parity)*h->mb_stride; + b8_stride = 0; + }else{ + mb_y += h->col_fieldoff; + mb_xy += h->mb_stride*h->col_fieldoff; // non zero for FL -> FL & differ parity + } + goto single_col; + }else{ // AFL/AFR/FR/FL -> AFR/FR + if(IS_INTERLACED(*mb_type)){ // AFL /FL -> AFR/FR + mb_y = h->mb_y&~1; + mb_xy= h->mb_x + (h->mb_y&~1)*h->mb_stride; + mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; + mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + h->mb_stride]; + b8_stride = 2+4*h->mb_stride; + b4_stride *= 6; + if (IS_INTERLACED(mb_type_col[0]) != IS_INTERLACED(mb_type_col[1])) { + mb_type_col[0] &= ~MB_TYPE_INTERLACED; + mb_type_col[1] &= ~MB_TYPE_INTERLACED; + } + + sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */ + + if( (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA) + && (mb_type_col[1] & MB_TYPE_16x16_OR_INTRA) + && !is_b8x8){ + *mb_type |= MB_TYPE_16x8 |MB_TYPE_L0L1|MB_TYPE_DIRECT2; /* B_16x8 */ + }else{ + *mb_type |= MB_TYPE_8x8|MB_TYPE_L0L1; + } + }else{ // AFR/FR -> AFR/FR +single_col: + mb_type_col[0] = + mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy]; + + sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */ + if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){ + *mb_type |= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */ + }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){ + *mb_type |= MB_TYPE_L0L1|MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16)); + }else{ + if(!h->sps.direct_8x8_inference_flag){ + /* FIXME save sub mb types from previous frames (or derive from MVs) + * so we know exactly what block size to use */ + sub_mb_type = MB_TYPE_8x8|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_4x4 */ + } + *mb_type |= MB_TYPE_8x8|MB_TYPE_L0L1; + } + } + } + + await_reference_mb_row(h, &h->ref_list[1][0], mb_y); + + l1mv0 = (void*)&h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]]; + l1mv1 = (void*)&h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]]; + l1ref0 = &h->ref_list[1][0].ref_index [0][4 * mb_xy]; + l1ref1 = &h->ref_list[1][0].ref_index [1][4 * mb_xy]; + if(!b8_stride){ + if(h->mb_y&1){ + l1ref0 += 2; + l1ref1 += 2; + l1mv0 += 2*b4_stride; + l1mv1 += 2*b4_stride; + } + } + + { + const int *map_col_to_list0[2] = {h->map_col_to_list0[0], h->map_col_to_list0[1]}; + const int *dist_scale_factor = h->dist_scale_factor; + int ref_offset; + + if (FRAME_MBAFF(h) && IS_INTERLACED(*mb_type)) { + map_col_to_list0[0] = h->map_col_to_list0_field[h->mb_y&1][0]; + map_col_to_list0[1] = h->map_col_to_list0_field[h->mb_y&1][1]; + dist_scale_factor =h->dist_scale_factor_field[h->mb_y&1]; + } + ref_offset = (h->ref_list[1][0].mbaff<<4) & (mb_type_col[0]>>3); //if(h->ref_list[1][0].mbaff && IS_INTERLACED(mb_type_col[0])) ref_offset=16 else 0 + + if(IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])){ + int y_shift = 2*!IS_INTERLACED(*mb_type); + assert(h->sps.direct_8x8_inference_flag); + + for(i8=0; i8<4; i8++){ + const int x8 = i8&1; + const int y8 = i8>>1; + int ref0, scale; + const int16_t (*l1mv)[2]= l1mv0; + + if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + continue; + h->sub_mb_type[i8] = sub_mb_type; + + fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1); + if(IS_INTRA(mb_type_col[y8])){ + fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1); + fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4); + fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4); + continue; + } + + ref0 = l1ref0[x8 + y8*b8_stride]; + if(ref0 >= 0) + ref0 = map_col_to_list0[0][ref0 + ref_offset]; + else{ + ref0 = map_col_to_list0[1][l1ref1[x8 + y8*b8_stride] + ref_offset]; + l1mv= l1mv1; + } + scale = dist_scale_factor[ref0]; + fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1); + + { + const int16_t *mv_col = l1mv[x8*3 + y8*b4_stride]; + int my_col = (mv_col[1]<> 8; + int my = (scale * my_col + 128) >> 8; + fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4); + fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-my_col), 4); + } + } + return; + } + + /* one-to-one mv scaling */ + + if(IS_16X16(*mb_type)){ + int ref, mv0, mv1; + + fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1); + if(IS_INTRA(mb_type_col[0])){ + ref=mv0=mv1=0; + }else{ + const int ref0 = l1ref0[0] >= 0 ? map_col_to_list0[0][l1ref0[0] + ref_offset] + : map_col_to_list0[1][l1ref1[0] + ref_offset]; + const int scale = dist_scale_factor[ref0]; + const int16_t *mv_col = l1ref0[0] >= 0 ? l1mv0[0] : l1mv1[0]; + int mv_l0[2]; + mv_l0[0] = (scale * mv_col[0] + 128) >> 8; + mv_l0[1] = (scale * mv_col[1] + 128) >> 8; + ref= ref0; + mv0= pack16to32(mv_l0[0],mv_l0[1]); + mv1= pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]); + } + fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); + fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4); + fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4); + }else{ + for(i8=0; i8<4; i8++){ + const int x8 = i8&1; + const int y8 = i8>>1; + int ref0, scale; + const int16_t (*l1mv)[2]= l1mv0; + + if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8])) + continue; + h->sub_mb_type[i8] = sub_mb_type; + fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1); + if(IS_INTRA(mb_type_col[0])){ + fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1); + fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4); + fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4); + continue; + } + + assert(b8_stride == 2); + ref0 = l1ref0[i8]; + if(ref0 >= 0) + ref0 = map_col_to_list0[0][ref0 + ref_offset]; + else{ + ref0 = map_col_to_list0[1][l1ref1[i8] + ref_offset]; + l1mv= l1mv1; + } + scale = dist_scale_factor[ref0]; + + fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1); + if(IS_SUB_8X8(sub_mb_type)){ + const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride]; + int mx = (scale * mv_col[0] + 128) >> 8; + int my = (scale * mv_col[1] + 128) >> 8; + fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4); + fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-mv_col[1]), 4); + }else + for(i4=0; i4<4; i4++){ + const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride]; + int16_t *mv_l0 = h->mv_cache[0][scan8[i8*4+i4]]; + mv_l0[0] = (scale * mv_col[0] + 128) >> 8; + mv_l0[1] = (scale * mv_col[1] + 128) >> 8; + AV_WN32A(h->mv_cache[1][scan8[i8*4+i4]], + pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1])); + } + } + } + } +} + +void ff_h264_pred_direct_motion(H264Context * const h, int *mb_type){ + if(h->direct_spatial_mv_pred){ + pred_spatial_direct_motion(h, mb_type); + }else{ + pred_temp_direct_motion(h, mb_type); + } +} diff --git a/ffmpeg/libavcodec/h264_loopfilter.c b/ffmpeg/libavcodec/h264_loopfilter.c new file mode 100644 index 0000000..e617588 --- /dev/null +++ b/ffmpeg/libavcodec/h264_loopfilter.c @@ -0,0 +1,826 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... loop filter + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 loop filter. + * @author Michael Niedermayer + */ + +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "internal.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h264.h" +#include "mathops.h" +#include "rectangle.h" + +/* Deblocking filter (p153) */ +static const uint8_t alpha_table[52*3] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, + 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, + 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, + 80, 90,101,113,127,144,162,182,203,226, + 255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255, +}; +static const uint8_t beta_table[52*3] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, + 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, + 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, + 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, +}; +static const uint8_t tc0_table[52*3][4] = { + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, + {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 }, + {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 1, 1 }, {-1, 0, 1, 1 }, {-1, 1, 1, 1 }, + {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, + {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 }, + {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 }, + {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 }, + {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, + {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, +}; + +/* intra: 0 if this loopfilter call is guaranteed to be inter (bS < 4), 1 if it might be intra (bS == 4) */ +static av_always_inline void filter_mb_edgev(uint8_t *pix, int stride, + const int16_t bS[4], + unsigned int qp, int a, int b, + H264Context *h, int intra) +{ + const unsigned int index_a = qp + a; + const int alpha = alpha_table[index_a]; + const int beta = beta_table[qp + b]; + if (alpha ==0 || beta == 0) return; + + if( bS[0] < 4 || !intra ) { + int8_t tc[4]; + tc[0] = tc0_table[index_a][bS[0]]; + tc[1] = tc0_table[index_a][bS[1]]; + tc[2] = tc0_table[index_a][bS[2]]; + tc[3] = tc0_table[index_a][bS[3]]; + h->h264dsp.h264_h_loop_filter_luma(pix, stride, alpha, beta, tc); + } else { + h->h264dsp.h264_h_loop_filter_luma_intra(pix, stride, alpha, beta); + } +} + +static av_always_inline void filter_mb_edgecv(uint8_t *pix, int stride, + const int16_t bS[4], + unsigned int qp, int a, int b, + H264Context *h, int intra) +{ + const unsigned int index_a = qp + a; + const int alpha = alpha_table[index_a]; + const int beta = beta_table[qp + b]; + if (alpha ==0 || beta == 0) return; + + if( bS[0] < 4 || !intra ) { + int8_t tc[4]; + tc[0] = tc0_table[index_a][bS[0]]+1; + tc[1] = tc0_table[index_a][bS[1]]+1; + tc[2] = tc0_table[index_a][bS[2]]+1; + tc[3] = tc0_table[index_a][bS[3]]+1; + h->h264dsp.h264_h_loop_filter_chroma(pix, stride, alpha, beta, tc); + } else { + h->h264dsp.h264_h_loop_filter_chroma_intra(pix, stride, alpha, beta); + } +} + +static av_always_inline void filter_mb_mbaff_edgev(H264Context *h, uint8_t *pix, + int stride, + const int16_t bS[7], int bsi, + int qp, int a, int b, + int intra) +{ + const unsigned int index_a = qp + a; + const int alpha = alpha_table[index_a]; + const int beta = beta_table[qp + b]; + if (alpha ==0 || beta == 0) return; + + if( bS[0] < 4 || !intra ) { + int8_t tc[4]; + tc[0] = tc0_table[index_a][bS[0*bsi]]; + tc[1] = tc0_table[index_a][bS[1*bsi]]; + tc[2] = tc0_table[index_a][bS[2*bsi]]; + tc[3] = tc0_table[index_a][bS[3*bsi]]; + h->h264dsp.h264_h_loop_filter_luma_mbaff(pix, stride, alpha, beta, tc); + } else { + h->h264dsp.h264_h_loop_filter_luma_mbaff_intra(pix, stride, alpha, beta); + } +} + +static av_always_inline void filter_mb_mbaff_edgecv(H264Context *h, + uint8_t *pix, int stride, + const int16_t bS[7], + int bsi, int qp, int a, + int b, int intra) +{ + const unsigned int index_a = qp + a; + const int alpha = alpha_table[index_a]; + const int beta = beta_table[qp + b]; + if (alpha ==0 || beta == 0) return; + + if( bS[0] < 4 || !intra ) { + int8_t tc[4]; + tc[0] = tc0_table[index_a][bS[0*bsi]] + 1; + tc[1] = tc0_table[index_a][bS[1*bsi]] + 1; + tc[2] = tc0_table[index_a][bS[2*bsi]] + 1; + tc[3] = tc0_table[index_a][bS[3*bsi]] + 1; + h->h264dsp.h264_h_loop_filter_chroma_mbaff(pix, stride, alpha, beta, tc); + } else { + h->h264dsp.h264_h_loop_filter_chroma_mbaff_intra(pix, stride, alpha, beta); + } +} + +static av_always_inline void filter_mb_edgeh(uint8_t *pix, int stride, + const int16_t bS[4], + unsigned int qp, int a, int b, + H264Context *h, int intra) +{ + const unsigned int index_a = qp + a; + const int alpha = alpha_table[index_a]; + const int beta = beta_table[qp + b]; + if (alpha ==0 || beta == 0) return; + + if( bS[0] < 4 || !intra ) { + int8_t tc[4]; + tc[0] = tc0_table[index_a][bS[0]]; + tc[1] = tc0_table[index_a][bS[1]]; + tc[2] = tc0_table[index_a][bS[2]]; + tc[3] = tc0_table[index_a][bS[3]]; + h->h264dsp.h264_v_loop_filter_luma(pix, stride, alpha, beta, tc); + } else { + h->h264dsp.h264_v_loop_filter_luma_intra(pix, stride, alpha, beta); + } +} + +static av_always_inline void filter_mb_edgech(uint8_t *pix, int stride, + const int16_t bS[4], + unsigned int qp, int a, int b, + H264Context *h, int intra) +{ + const unsigned int index_a = qp + a; + const int alpha = alpha_table[index_a]; + const int beta = beta_table[qp + b]; + if (alpha ==0 || beta == 0) return; + + if( bS[0] < 4 || !intra ) { + int8_t tc[4]; + tc[0] = tc0_table[index_a][bS[0]]+1; + tc[1] = tc0_table[index_a][bS[1]]+1; + tc[2] = tc0_table[index_a][bS[2]]+1; + tc[3] = tc0_table[index_a][bS[3]]+1; + h->h264dsp.h264_v_loop_filter_chroma(pix, stride, alpha, beta, tc); + } else { + h->h264dsp.h264_v_loop_filter_chroma_intra(pix, stride, alpha, beta); + } +} + +static av_always_inline void h264_filter_mb_fast_internal(H264Context *h, + int mb_x, int mb_y, + uint8_t *img_y, + uint8_t *img_cb, + uint8_t *img_cr, + unsigned int linesize, + unsigned int uvlinesize, + int pixel_shift) +{ + int chroma = CHROMA && !(CONFIG_GRAY && (h->flags&CODEC_FLAG_GRAY)); + int chroma444 = CHROMA444; + int chroma422 = CHROMA422; + + int mb_xy = h->mb_xy; + int left_type= h->left_type[LTOP]; + int top_type= h->top_type; + + int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8); + int a = h->slice_alpha_c0_offset - qp_bd_offset; + int b = h->slice_beta_offset - qp_bd_offset; + + int mb_type = h->cur_pic.mb_type[mb_xy]; + int qp = h->cur_pic.qscale_table[mb_xy]; + int qp0 = h->cur_pic.qscale_table[mb_xy - 1]; + int qp1 = h->cur_pic.qscale_table[h->top_mb_xy]; + int qpc = get_chroma_qp( h, 0, qp ); + int qpc0 = get_chroma_qp( h, 0, qp0 ); + int qpc1 = get_chroma_qp( h, 0, qp1 ); + qp0 = (qp + qp0 + 1) >> 1; + qp1 = (qp + qp1 + 1) >> 1; + qpc0 = (qpc + qpc0 + 1) >> 1; + qpc1 = (qpc + qpc1 + 1) >> 1; + + if( IS_INTRA(mb_type) ) { + static const int16_t bS4[4] = {4,4,4,4}; + static const int16_t bS3[4] = {3,3,3,3}; + const int16_t *bSH = FIELD_PICTURE(h) ? bS3 : bS4; + if(left_type) + filter_mb_edgev( &img_y[4*0<cbp&7) == 7 && !chroma444 ) { + edges = 4; + AV_WN64A(bS[0][0], 0x0002000200020002ULL); + AV_WN64A(bS[0][2], 0x0002000200020002ULL); + AV_WN64A(bS[1][0], 0x0002000200020002ULL); + AV_WN64A(bS[1][2], 0x0002000200020002ULL); + } else { + int mask_edge1 = (3*(((5*mb_type)>>5)&1)) | (mb_type>>4); //(mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 : (mb_type & MB_TYPE_16x8) ? 1 : 0; + int mask_edge0 = 3*((mask_edge1>>1) & ((5*left_type)>>5)&1); // (mb_type & (MB_TYPE_16x16 | MB_TYPE_8x16)) && (h->left_type[LTOP] & (MB_TYPE_16x16 | MB_TYPE_8x16)) ? 3 : 0; + int step = 1+(mb_type>>24); //IS_8x8DCT(mb_type) ? 2 : 1; + edges = 4 - 3*((mb_type>>3) & !(h->cbp & 15)); //(mb_type & MB_TYPE_16x16) && !(h->cbp & 15) ? 1 : 4; + h->h264dsp.h264_loop_filter_strength( bS, h->non_zero_count_cache, h->ref_cache, h->mv_cache, + h->list_count==2, edges, step, mask_edge0, mask_edge1, FIELD_PICTURE(h)); + } + if( IS_INTRA(left_type) ) + AV_WN64A(bS[0][0], 0x0004000400040004ULL); + if( IS_INTRA(top_type) ) + AV_WN64A(bS[1][0], FIELD_PICTURE(h) ? 0x0003000300030003ULL : 0x0004000400040004ULL); + +#define FILTER(hv,dir,edge,intra)\ + if(AV_RN64A(bS[dir][edge])) { \ + filter_mb_edge##hv( &img_y[4*edge*(dir?linesize:1<h264dsp.h264_loop_filter_strength || h->pps.chroma_qp_diff) { + ff_h264_filter_mb(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize); + return; + } + +#if CONFIG_SMALL + h264_filter_mb_fast_internal(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, h->pixel_shift); +#else + if(h->pixel_shift){ + h264_filter_mb_fast_internal(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, 1); + }else{ + h264_filter_mb_fast_internal(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, 0); + } +#endif +} + +static int check_mv(H264Context *h, long b_idx, long bn_idx, int mvy_limit){ + int v; + + v= h->ref_cache[0][b_idx] != h->ref_cache[0][bn_idx]; + if(!v && h->ref_cache[0][b_idx]!=-1) + v= h->mv_cache[0][b_idx][0] - h->mv_cache[0][bn_idx][0] + 3 >= 7U | + FFABS( h->mv_cache[0][b_idx][1] - h->mv_cache[0][bn_idx][1] ) >= mvy_limit; + + if(h->list_count==2){ + if(!v) + v = h->ref_cache[1][b_idx] != h->ref_cache[1][bn_idx] | + h->mv_cache[1][b_idx][0] - h->mv_cache[1][bn_idx][0] + 3 >= 7U | + FFABS( h->mv_cache[1][b_idx][1] - h->mv_cache[1][bn_idx][1] ) >= mvy_limit; + + if(v){ + if(h->ref_cache[0][b_idx] != h->ref_cache[1][bn_idx] | + h->ref_cache[1][b_idx] != h->ref_cache[0][bn_idx]) + return 1; + return + h->mv_cache[0][b_idx][0] - h->mv_cache[1][bn_idx][0] + 3 >= 7U | + FFABS( h->mv_cache[0][b_idx][1] - h->mv_cache[1][bn_idx][1] ) >= mvy_limit | + h->mv_cache[1][b_idx][0] - h->mv_cache[0][bn_idx][0] + 3 >= 7U | + FFABS( h->mv_cache[1][b_idx][1] - h->mv_cache[0][bn_idx][1] ) >= mvy_limit; + } + } + + return v; +} + +static av_always_inline void filter_mb_dir(H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize, int mb_xy, int mb_type, int mvy_limit, int first_vertical_edge_done, int a, int b, int chroma, int dir) { + int edge; + int chroma_qp_avg[2]; + int chroma444 = CHROMA444; + int chroma422 = CHROMA422; + const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy; + const int mbm_type = dir == 0 ? h->left_type[LTOP] : h->top_type; + + // how often to recheck mv-based bS when iterating between edges + static const uint8_t mask_edge_tab[2][8]={{0,3,3,3,1,1,1,1}, + {0,3,1,1,3,3,3,3}}; + const int mask_edge = mask_edge_tab[dir][(mb_type>>3)&7]; + const int edges = mask_edge== 3 && !(h->cbp&15) ? 1 : 4; + + // how often to recheck mv-based bS when iterating along each edge + const int mask_par0 = mb_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)); + + if(mbm_type && !first_vertical_edge_done){ + + if (FRAME_MBAFF(h) && (dir == 1) && ((mb_y&1) == 0) + && IS_INTERLACED(mbm_type&~mb_type) + ) { + // This is a special case in the norm where the filtering must + // be done twice (one each of the field) even if we are in a + // frame macroblock. + // + unsigned int tmp_linesize = 2 * linesize; + unsigned int tmp_uvlinesize = 2 * uvlinesize; + int mbn_xy = mb_xy - 2 * h->mb_stride; + int j; + + for(j=0; j<2; j++, mbn_xy += h->mb_stride){ + DECLARE_ALIGNED(8, int16_t, bS)[4]; + int qp; + if (IS_INTRA(mb_type | h->cur_pic.mb_type[mbn_xy])) { + AV_WN64A(bS, 0x0003000300030003ULL); + } else { + if (!CABAC(h) && IS_8x8DCT(h->cur_pic.mb_type[mbn_xy])) { + bS[0]= 1+((h->cbp_table[mbn_xy] & 0x4000)||h->non_zero_count_cache[scan8[0]+0]); + bS[1]= 1+((h->cbp_table[mbn_xy] & 0x4000)||h->non_zero_count_cache[scan8[0]+1]); + bS[2]= 1+((h->cbp_table[mbn_xy] & 0x8000)||h->non_zero_count_cache[scan8[0]+2]); + bS[3]= 1+((h->cbp_table[mbn_xy] & 0x8000)||h->non_zero_count_cache[scan8[0]+3]); + }else{ + const uint8_t *mbn_nnz = h->non_zero_count[mbn_xy] + 3*4; + int i; + for( i = 0; i < 4; i++ ) { + bS[i] = 1 + !!(h->non_zero_count_cache[scan8[0]+i] | mbn_nnz[i]); + } + } + } + // Do not use s->qscale as luma quantizer because it has not the same + // value in IPCM macroblocks. + qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbn_xy] + 1) >> 1; + tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize); + { int i; for (i = 0; i < 4; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); } + filter_mb_edgeh( &img_y[j*linesize], tmp_linesize, bS, qp, a, b, h, 0 ); + chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1; + chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, h->cur_pic.qscale_table[mbn_xy]) + 1) >> 1; + if (chroma) { + if (chroma444) { + filter_mb_edgeh (&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], a, b, h, 0); + filter_mb_edgeh (&img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[1], a, b, h, 0); + } else { + filter_mb_edgech(&img_cb[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[0], a, b, h, 0); + filter_mb_edgech(&img_cr[j*uvlinesize], tmp_uvlinesize, bS, chroma_qp_avg[1], a, b, h, 0); + } + } + } + }else{ + DECLARE_ALIGNED(8, int16_t, bS)[4]; + int qp; + + if( IS_INTRA(mb_type|mbm_type)) { + AV_WN64A(bS, 0x0003000300030003ULL); + if ( (!IS_INTERLACED(mb_type|mbm_type)) + || ((FRAME_MBAFF(h) || (h->picture_structure != PICT_FRAME)) && (dir == 0)) + ) + AV_WN64A(bS, 0x0004000400040004ULL); + } else { + int i; + int mv_done; + + if( dir && FRAME_MBAFF(h) && IS_INTERLACED(mb_type ^ mbm_type)) { + AV_WN64A(bS, 0x0001000100010001ULL); + mv_done = 1; + } + else if( mask_par0 && ((mbm_type & (MB_TYPE_16x16 | (MB_TYPE_8x16 >> dir)))) ) { + int b_idx= 8 + 4; + int bn_idx= b_idx - (dir ? 8:1); + + bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, 8 + 4, bn_idx, mvy_limit); + mv_done = 1; + } + else + mv_done = 0; + + for( i = 0; i < 4; i++ ) { + int x = dir == 0 ? 0 : i; + int y = dir == 0 ? i : 0; + int b_idx= 8 + 4 + x + 8*y; + int bn_idx= b_idx - (dir ? 8:1); + + if( h->non_zero_count_cache[b_idx] | + h->non_zero_count_cache[bn_idx] ) { + bS[i] = 2; + } + else if(!mv_done) + { + bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit); + } + } + } + + /* Filter edge */ + // Do not use s->qscale as luma quantizer because it has not the same + // value in IPCM macroblocks. + if(bS[0]+bS[1]+bS[2]+bS[3]){ + qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbm_xy] + 1) >> 1; + //tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], h->cur_pic.qscale_table[mbn_xy]); + tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); + //{ int i; for (i = 0; i < 4; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); } + chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1; + chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1; + if( dir == 0 ) { + filter_mb_edgev( &img_y[0], linesize, bS, qp, a, b, h, 1 ); + if (chroma) { + if (chroma444) { + filter_mb_edgev ( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1); + filter_mb_edgev ( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1); + } else { + filter_mb_edgecv( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1); + filter_mb_edgecv( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1); + } + } + } else { + filter_mb_edgeh( &img_y[0], linesize, bS, qp, a, b, h, 1 ); + if (chroma) { + if (chroma444) { + filter_mb_edgeh ( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1); + filter_mb_edgeh ( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1); + } else { + filter_mb_edgech( &img_cb[0], uvlinesize, bS, chroma_qp_avg[0], a, b, h, 1); + filter_mb_edgech( &img_cr[0], uvlinesize, bS, chroma_qp_avg[1], a, b, h, 1); + } + } + } + } + } + } + + /* Calculate bS */ + for( edge = 1; edge < edges; edge++ ) { + DECLARE_ALIGNED(8, int16_t, bS)[4]; + int qp; + const int deblock_edge = !IS_8x8DCT(mb_type & (edge<<24)); // (edge&1) && IS_8x8DCT(mb_type) + + if (!deblock_edge && (!chroma422 || dir == 0)) + continue; + + if( IS_INTRA(mb_type)) { + AV_WN64A(bS, 0x0003000300030003ULL); + } else { + int i; + int mv_done; + + if( edge & mask_edge ) { + AV_ZERO64(bS); + mv_done = 1; + } + else if( mask_par0 ) { + int b_idx= 8 + 4 + edge * (dir ? 8:1); + int bn_idx= b_idx - (dir ? 8:1); + + bS[0] = bS[1] = bS[2] = bS[3] = check_mv(h, b_idx, bn_idx, mvy_limit); + mv_done = 1; + } + else + mv_done = 0; + + for( i = 0; i < 4; i++ ) { + int x = dir == 0 ? edge : i; + int y = dir == 0 ? i : edge; + int b_idx= 8 + 4 + x + 8*y; + int bn_idx= b_idx - (dir ? 8:1); + + if( h->non_zero_count_cache[b_idx] | + h->non_zero_count_cache[bn_idx] ) { + bS[i] = 2; + } + else if(!mv_done) + { + bS[i] = check_mv(h, b_idx, bn_idx, mvy_limit); + } + } + + if(bS[0]+bS[1]+bS[2]+bS[3] == 0) + continue; + } + + /* Filter edge */ + // Do not use s->qscale as luma quantizer because it has not the same + // value in IPCM macroblocks. + qp = h->cur_pic.qscale_table[mb_xy]; + //tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], h->cur_pic.qscale_table[mbn_xy]); + tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize); + //{ int i; for (i = 0; i < 4; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); } + if( dir == 0 ) { + filter_mb_edgev( &img_y[4*edge << h->pixel_shift], linesize, bS, qp, a, b, h, 0 ); + if (chroma) { + if (chroma444) { + filter_mb_edgev ( &img_cb[4*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); + filter_mb_edgev ( &img_cr[4*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + } else if( (edge&1) == 0 ) { + filter_mb_edgecv( &img_cb[2*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); + filter_mb_edgecv( &img_cr[2*edge << h->pixel_shift], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + } + } + } else { + if (chroma422) { + if (deblock_edge) + filter_mb_edgeh(&img_y[4*edge*linesize], linesize, bS, qp, a, b, h, 0); + if (chroma) { + filter_mb_edgech(&img_cb[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); + filter_mb_edgech(&img_cr[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + } + } else { + filter_mb_edgeh(&img_y[4*edge*linesize], linesize, bS, qp, a, b, h, 0); + if (chroma) { + if (chroma444) { + filter_mb_edgeh (&img_cb[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); + filter_mb_edgeh (&img_cr[4*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + } else if ((edge&1) == 0) { + filter_mb_edgech(&img_cb[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[0], a, b, h, 0); + filter_mb_edgech(&img_cr[2*edge*uvlinesize], uvlinesize, bS, h->chroma_qp[1], a, b, h, 0); + } + } + } + } + } +} + +void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { + const int mb_xy= mb_x + mb_y*h->mb_stride; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4; + int first_vertical_edge_done = 0; + av_unused int dir; + int chroma = CHROMA && !(CONFIG_GRAY && (h->flags&CODEC_FLAG_GRAY)); + int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8); + int a = h->slice_alpha_c0_offset - qp_bd_offset; + int b = h->slice_beta_offset - qp_bd_offset; + + if (FRAME_MBAFF(h) + // and current and left pair do not have the same interlaced type + && IS_INTERLACED(mb_type^h->left_type[LTOP]) + // and left mb is in available to us + && h->left_type[LTOP]) { + /* First vertical edge is different in MBAFF frames + * There are 8 different bS to compute and 2 different Qp + */ + DECLARE_ALIGNED(8, int16_t, bS)[8]; + int qp[2]; + int bqp[2]; + int rqp[2]; + int mb_qp, mbn0_qp, mbn1_qp; + int i; + first_vertical_edge_done = 1; + + if( IS_INTRA(mb_type) ) { + AV_WN64A(&bS[0], 0x0004000400040004ULL); + AV_WN64A(&bS[4], 0x0004000400040004ULL); + } else { + static const uint8_t offset[2][2][8]={ + { + {3+4*0, 3+4*0, 3+4*0, 3+4*0, 3+4*1, 3+4*1, 3+4*1, 3+4*1}, + {3+4*2, 3+4*2, 3+4*2, 3+4*2, 3+4*3, 3+4*3, 3+4*3, 3+4*3}, + },{ + {3+4*0, 3+4*1, 3+4*2, 3+4*3, 3+4*0, 3+4*1, 3+4*2, 3+4*3}, + {3+4*0, 3+4*1, 3+4*2, 3+4*3, 3+4*0, 3+4*1, 3+4*2, 3+4*3}, + } + }; + const uint8_t *off= offset[MB_FIELD(h)][mb_y&1]; + for( i = 0; i < 8; i++ ) { + int j= MB_FIELD(h) ? i>>2 : i&1; + int mbn_xy = h->left_mb_xy[LEFT(j)]; + int mbn_type= h->left_type[LEFT(j)]; + + if( IS_INTRA( mbn_type ) ) + bS[i] = 4; + else{ + bS[i] = 1 + !!(h->non_zero_count_cache[12+8*(i>>1)] | + ((!h->pps.cabac && IS_8x8DCT(mbn_type)) ? + (h->cbp_table[mbn_xy] & (((MB_FIELD(h) ? (i&2) : (mb_y&1)) ? 8 : 2) << 12)) + : + h->non_zero_count[mbn_xy][ off[i] ])); + } + } + } + + mb_qp = h->cur_pic.qscale_table[mb_xy]; + mbn0_qp = h->cur_pic.qscale_table[h->left_mb_xy[0]]; + mbn1_qp = h->cur_pic.qscale_table[h->left_mb_xy[1]]; + qp[0] = ( mb_qp + mbn0_qp + 1 ) >> 1; + bqp[0] = ( get_chroma_qp( h, 0, mb_qp ) + + get_chroma_qp( h, 0, mbn0_qp ) + 1 ) >> 1; + rqp[0] = ( get_chroma_qp( h, 1, mb_qp ) + + get_chroma_qp( h, 1, mbn0_qp ) + 1 ) >> 1; + qp[1] = ( mb_qp + mbn1_qp + 1 ) >> 1; + bqp[1] = ( get_chroma_qp( h, 0, mb_qp ) + + get_chroma_qp( h, 0, mbn1_qp ) + 1 ) >> 1; + rqp[1] = ( get_chroma_qp( h, 1, mb_qp ) + + get_chroma_qp( h, 1, mbn1_qp ) + 1 ) >> 1; + + /* Filter edge */ + tprintf(h->avctx, "filter mb:%d/%d MBAFF, QPy:%d/%d, QPb:%d/%d QPr:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], bqp[0], bqp[1], rqp[0], rqp[1], linesize, uvlinesize); + { int i; for (i = 0; i < 8; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); } + if (MB_FIELD(h)) { + filter_mb_mbaff_edgev ( h, img_y , linesize, bS , 1, qp [0], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_y + 8* linesize, linesize, bS+4, 1, qp [1], a, b, 1 ); + if (chroma){ + if (CHROMA444) { + filter_mb_mbaff_edgev ( h, img_cb, uvlinesize, bS , 1, bqp[0], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_cb + 8*uvlinesize, uvlinesize, bS+4, 1, bqp[1], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_cr, uvlinesize, bS , 1, rqp[0], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_cr + 8*uvlinesize, uvlinesize, bS+4, 1, rqp[1], a, b, 1 ); + } else if (CHROMA422) { + filter_mb_mbaff_edgecv(h, img_cb, uvlinesize, bS , 1, bqp[0], a, b, 1); + filter_mb_mbaff_edgecv(h, img_cb + 8*uvlinesize, uvlinesize, bS+4, 1, bqp[1], a, b, 1); + filter_mb_mbaff_edgecv(h, img_cr, uvlinesize, bS , 1, rqp[0], a, b, 1); + filter_mb_mbaff_edgecv(h, img_cr + 8*uvlinesize, uvlinesize, bS+4, 1, rqp[1], a, b, 1); + }else{ + filter_mb_mbaff_edgecv( h, img_cb, uvlinesize, bS , 1, bqp[0], a, b, 1 ); + filter_mb_mbaff_edgecv( h, img_cb + 4*uvlinesize, uvlinesize, bS+4, 1, bqp[1], a, b, 1 ); + filter_mb_mbaff_edgecv( h, img_cr, uvlinesize, bS , 1, rqp[0], a, b, 1 ); + filter_mb_mbaff_edgecv( h, img_cr + 4*uvlinesize, uvlinesize, bS+4, 1, rqp[1], a, b, 1 ); + } + } + }else{ + filter_mb_mbaff_edgev ( h, img_y , 2* linesize, bS , 2, qp [0], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_y + linesize, 2* linesize, bS+1, 2, qp [1], a, b, 1 ); + if (chroma){ + if (CHROMA444) { + filter_mb_mbaff_edgev ( h, img_cb, 2*uvlinesize, bS , 2, bqp[0], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_cb + uvlinesize, 2*uvlinesize, bS+1, 2, bqp[1], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_cr, 2*uvlinesize, bS , 2, rqp[0], a, b, 1 ); + filter_mb_mbaff_edgev ( h, img_cr + uvlinesize, 2*uvlinesize, bS+1, 2, rqp[1], a, b, 1 ); + }else{ + filter_mb_mbaff_edgecv( h, img_cb, 2*uvlinesize, bS , 2, bqp[0], a, b, 1 ); + filter_mb_mbaff_edgecv( h, img_cb + uvlinesize, 2*uvlinesize, bS+1, 2, bqp[1], a, b, 1 ); + filter_mb_mbaff_edgecv( h, img_cr, 2*uvlinesize, bS , 2, rqp[0], a, b, 1 ); + filter_mb_mbaff_edgecv( h, img_cr + uvlinesize, 2*uvlinesize, bS+1, 2, rqp[1], a, b, 1 ); + } + } + } + } + +#if CONFIG_SMALL + for( dir = 0; dir < 2; dir++ ) + filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, dir ? 0 : first_vertical_edge_done, a, b, chroma, dir); +#else + filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, first_vertical_edge_done, a, b, chroma, 0); + filter_mb_dir(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize, mb_xy, mb_type, mvy_limit, 0, a, b, chroma, 1); +#endif +} diff --git a/ffmpeg/libavcodec/h264_mb_template.c b/ffmpeg/libavcodec/h264_mb_template.c new file mode 100644 index 0000000..8ef93a1 --- /dev/null +++ b/ffmpeg/libavcodec/h264_mb_template.c @@ -0,0 +1,367 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 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 + */ + +#undef FUNC +#undef PIXEL_SHIFT + +#if SIMPLE +# define FUNC(n) AV_JOIN(n ## _simple_, BITS) +# define PIXEL_SHIFT (BITS >> 4) +#else +# define FUNC(n) n ## _complex +# define PIXEL_SHIFT h->pixel_shift +#endif + +#undef CHROMA_IDC +#define CHROMA_IDC 1 +#include "h264_mc_template.c" + +#undef CHROMA_IDC +#define CHROMA_IDC 2 +#include "h264_mc_template.c" + +static av_noinline void FUNC(hl_decode_mb)(H264Context *h) +{ + const int mb_x = h->mb_x; + const int mb_y = h->mb_y; + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + uint8_t *dest_y, *dest_cb, *dest_cr; + int linesize, uvlinesize /*dct_offset*/; + int i, j; + int *block_offset = &h->block_offset[0]; + const int transform_bypass = !SIMPLE && (h->qscale == 0 && h->sps.transform_bypass); + /* is_h264 should always be true if SVQ3 is disabled. */ + const int is_h264 = !CONFIG_SVQ3_DECODER || SIMPLE || h->avctx->codec_id == AV_CODEC_ID_H264; + void (*idct_add)(uint8_t *dst, int16_t *block, int stride); + const int block_h = 16 >> h->chroma_y_shift; + const int chroma422 = CHROMA422; + + dest_y = h->cur_pic.f.data[0] + ((mb_x << PIXEL_SHIFT) + mb_y * h->linesize) * 16; + dest_cb = h->cur_pic.f.data[1] + (mb_x << PIXEL_SHIFT) * 8 + mb_y * h->uvlinesize * block_h; + dest_cr = h->cur_pic.f.data[2] + (mb_x << PIXEL_SHIFT) * 8 + mb_y * h->uvlinesize * block_h; + + h->vdsp.prefetch(dest_y + (h->mb_x & 3) * 4 * h->linesize + (64 << PIXEL_SHIFT), h->linesize, 4); + h->vdsp.prefetch(dest_cb + (h->mb_x & 7) * h->uvlinesize + (64 << PIXEL_SHIFT), dest_cr - dest_cb, 2); + + h->list_counts[mb_xy] = h->list_count; + + if (!SIMPLE && MB_FIELD(h)) { + linesize = h->mb_linesize = h->linesize * 2; + uvlinesize = h->mb_uvlinesize = h->uvlinesize * 2; + block_offset = &h->block_offset[48]; + if (mb_y & 1) { // FIXME move out of this function? + dest_y -= h->linesize * 15; + dest_cb -= h->uvlinesize * (block_h - 1); + dest_cr -= h->uvlinesize * (block_h - 1); + } + if (FRAME_MBAFF(h)) { + int list; + for (list = 0; list < h->list_count; list++) { + if (!USES_LIST(mb_type, list)) + continue; + if (IS_16X16(mb_type)) { + int8_t *ref = &h->ref_cache[list][scan8[0]]; + fill_rectangle(ref, 4, 4, 8, (16 + *ref) ^ (h->mb_y & 1), 1); + } else { + for (i = 0; i < 16; i += 4) { + int ref = h->ref_cache[list][scan8[i]]; + if (ref >= 0) + fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, + 8, (16 + ref) ^ (h->mb_y & 1), 1); + } + } + } + } + } else { + linesize = h->mb_linesize = h->linesize; + uvlinesize = h->mb_uvlinesize = h->uvlinesize; + // dct_offset = s->linesize * 16; + } + + if (!SIMPLE && IS_INTRA_PCM(mb_type)) { + const int bit_depth = h->sps.bit_depth_luma; + if (PIXEL_SHIFT) { + int j; + GetBitContext gb; + init_get_bits(&gb, h->intra_pcm_ptr, + ff_h264_mb_sizes[h->sps.chroma_format_idc] * bit_depth); + + for (i = 0; i < 16; i++) { + uint16_t *tmp_y = (uint16_t *)(dest_y + i * linesize); + for (j = 0; j < 16; j++) + tmp_y[j] = get_bits(&gb, bit_depth); + } + if (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (!h->sps.chroma_format_idc) { + for (i = 0; i < block_h; i++) { + uint16_t *tmp_cb = (uint16_t *)(dest_cb + i * uvlinesize); + uint16_t *tmp_cr = (uint16_t *)(dest_cr + i * uvlinesize); + for (j = 0; j < 8; j++) { + tmp_cb[j] = tmp_cr[j] = 1 << (bit_depth - 1); + } + } + } else { + for (i = 0; i < block_h; i++) { + uint16_t *tmp_cb = (uint16_t *)(dest_cb + i * uvlinesize); + for (j = 0; j < 8; j++) + tmp_cb[j] = get_bits(&gb, bit_depth); + } + for (i = 0; i < block_h; i++) { + uint16_t *tmp_cr = (uint16_t *)(dest_cr + i * uvlinesize); + for (j = 0; j < 8; j++) + tmp_cr[j] = get_bits(&gb, bit_depth); + } + } + } + } else { + for (i = 0; i < 16; i++) + memcpy(dest_y + i * linesize, h->intra_pcm_ptr + i * 16, 16); + if (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + if (!h->sps.chroma_format_idc) { + for (i = 0; i < 8; i++) { + memset(dest_cb + i*uvlinesize, 1 << (bit_depth - 1), 8); + memset(dest_cr + i*uvlinesize, 1 << (bit_depth - 1), 8); + } + } else { + const uint8_t *src_cb = h->intra_pcm_ptr + 256; + const uint8_t *src_cr = h->intra_pcm_ptr + 256 + block_h * 8; + for (i = 0; i < block_h; i++) { + memcpy(dest_cb + i * uvlinesize, src_cb + i * 8, 8); + memcpy(dest_cr + i * uvlinesize, src_cr + i * 8, 8); + } + } + } + } + } else { + if (IS_INTRA(mb_type)) { + if (h->deblocking_filter) + xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + uvlinesize, 1, 0, SIMPLE, PIXEL_SHIFT); + + if (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) { + h->hpc.pred8x8[h->chroma_pred_mode](dest_cb, uvlinesize); + h->hpc.pred8x8[h->chroma_pred_mode](dest_cr, uvlinesize); + } + + hl_decode_mb_predict_luma(h, mb_type, is_h264, SIMPLE, + transform_bypass, PIXEL_SHIFT, + block_offset, linesize, dest_y, 0); + + if (h->deblocking_filter) + xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, + uvlinesize, 0, 0, SIMPLE, PIXEL_SHIFT); + } else if (is_h264) { + if (chroma422) { + FUNC(hl_motion_422)(h, dest_y, dest_cb, dest_cr, + h->me.qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, + h->me.qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + h->h264dsp.weight_h264_pixels_tab, + h->h264dsp.biweight_h264_pixels_tab); + } else { + FUNC(hl_motion_420)(h, dest_y, dest_cb, dest_cr, + h->me.qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, + h->me.qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + h->h264dsp.weight_h264_pixels_tab, + h->h264dsp.biweight_h264_pixels_tab); + } + } + + hl_decode_mb_idct_luma(h, mb_type, is_h264, SIMPLE, transform_bypass, + PIXEL_SHIFT, block_offset, linesize, dest_y, 0); + + if ((SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) && + (h->cbp & 0x30)) { + uint8_t *dest[2] = { dest_cb, dest_cr }; + if (transform_bypass) { + if (IS_INTRA(mb_type) && h->sps.profile_idc == 244 && + (h->chroma_pred_mode == VERT_PRED8x8 || + h->chroma_pred_mode == HOR_PRED8x8)) { + h->hpc.pred8x8_add[h->chroma_pred_mode](dest[0], + block_offset + 16, + h->mb + (16 * 16 * 1 << PIXEL_SHIFT), + uvlinesize); + h->hpc.pred8x8_add[h->chroma_pred_mode](dest[1], + block_offset + 32, + h->mb + (16 * 16 * 2 << PIXEL_SHIFT), + uvlinesize); + } else { + idct_add = h->h264dsp.h264_add_pixels4_clear; + for (j = 1; j < 3; j++) { + for (i = j * 16; i < j * 16 + 4; i++) + if (h->non_zero_count_cache[scan8[i]] || + dctcoef_get(h->mb, PIXEL_SHIFT, i * 16)) + idct_add(dest[j - 1] + block_offset[i], + h->mb + (i * 16 << PIXEL_SHIFT), + uvlinesize); + if (chroma422) { + for (i = j * 16 + 4; i < j * 16 + 8; i++) + if (h->non_zero_count_cache[scan8[i + 4]] || + dctcoef_get(h->mb, PIXEL_SHIFT, i * 16)) + idct_add(dest[j - 1] + block_offset[i + 4], + h->mb + (i * 16 << PIXEL_SHIFT), + uvlinesize); + } + } + } + } else { + if (is_h264) { + int qp[2]; + if (chroma422) { + qp[0] = h->chroma_qp[0] + 3; + qp[1] = h->chroma_qp[1] + 3; + } else { + qp[0] = h->chroma_qp[0]; + qp[1] = h->chroma_qp[1]; + } + if (h->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 0]]) + h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + (16 * 16 * 1 << PIXEL_SHIFT), + h->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][qp[0]][0]); + if (h->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 1]]) + h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + (16 * 16 * 2 << PIXEL_SHIFT), + h->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][qp[1]][0]); + h->h264dsp.h264_idct_add8(dest, block_offset, + h->mb, uvlinesize, + h->non_zero_count_cache); + } else if (CONFIG_SVQ3_DECODER) { + h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16 * 16 * 1, + h->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][h->chroma_qp[0]][0]); + h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16 * 16 * 2, + h->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][h->chroma_qp[1]][0]); + for (j = 1; j < 3; j++) { + for (i = j * 16; i < j * 16 + 4; i++) + if (h->non_zero_count_cache[scan8[i]] || h->mb[i * 16]) { + uint8_t *const ptr = dest[j - 1] + block_offset[i]; + ff_svq3_add_idct_c(ptr, h->mb + i * 16, + uvlinesize, + ff_h264_chroma_qp[0][h->qscale + 12] - 12, 2); + } + } + } + } + } + } +} + +#if !SIMPLE || BITS == 8 + +#undef CHROMA_IDC +#define CHROMA_IDC 3 +#include "h264_mc_template.c" + +static av_noinline void FUNC(hl_decode_mb_444)(H264Context *h) +{ + const int mb_x = h->mb_x; + const int mb_y = h->mb_y; + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + uint8_t *dest[3]; + int linesize; + int i, j, p; + int *block_offset = &h->block_offset[0]; + const int transform_bypass = !SIMPLE && (h->qscale == 0 && h->sps.transform_bypass); + const int plane_count = (SIMPLE || !CONFIG_GRAY || !(h->flags & CODEC_FLAG_GRAY)) ? 3 : 1; + + for (p = 0; p < plane_count; p++) { + dest[p] = h->cur_pic.f.data[p] + + ((mb_x << PIXEL_SHIFT) + mb_y * h->linesize) * 16; + h->vdsp.prefetch(dest[p] + (h->mb_x & 3) * 4 * h->linesize + (64 << PIXEL_SHIFT), + h->linesize, 4); + } + + h->list_counts[mb_xy] = h->list_count; + + if (!SIMPLE && MB_FIELD(h)) { + linesize = h->mb_linesize = h->mb_uvlinesize = h->linesize * 2; + block_offset = &h->block_offset[48]; + if (mb_y & 1) // FIXME move out of this function? + for (p = 0; p < 3; p++) + dest[p] -= h->linesize * 15; + if (FRAME_MBAFF(h)) { + int list; + for (list = 0; list < h->list_count; list++) { + if (!USES_LIST(mb_type, list)) + continue; + if (IS_16X16(mb_type)) { + int8_t *ref = &h->ref_cache[list][scan8[0]]; + fill_rectangle(ref, 4, 4, 8, (16 + *ref) ^ (h->mb_y & 1), 1); + } else { + for (i = 0; i < 16; i += 4) { + int ref = h->ref_cache[list][scan8[i]]; + if (ref >= 0) + fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, + 8, (16 + ref) ^ (h->mb_y & 1), 1); + } + } + } + } + } else { + linesize = h->mb_linesize = h->mb_uvlinesize = h->linesize; + } + + if (!SIMPLE && IS_INTRA_PCM(mb_type)) { + if (PIXEL_SHIFT) { + const int bit_depth = h->sps.bit_depth_luma; + GetBitContext gb; + init_get_bits(&gb, h->intra_pcm_ptr, 768 * bit_depth); + + for (p = 0; p < plane_count; p++) + for (i = 0; i < 16; i++) { + uint16_t *tmp = (uint16_t *)(dest[p] + i * linesize); + for (j = 0; j < 16; j++) + tmp[j] = get_bits(&gb, bit_depth); + } + } else { + for (p = 0; p < plane_count; p++) + for (i = 0; i < 16; i++) + memcpy(dest[p] + i * linesize, + h->intra_pcm_ptr + p * 256 + i * 16, 16); + } + } else { + if (IS_INTRA(mb_type)) { + if (h->deblocking_filter) + xchg_mb_border(h, dest[0], dest[1], dest[2], linesize, + linesize, 1, 1, SIMPLE, PIXEL_SHIFT); + + for (p = 0; p < plane_count; p++) + hl_decode_mb_predict_luma(h, mb_type, 1, SIMPLE, + transform_bypass, PIXEL_SHIFT, + block_offset, linesize, dest[p], p); + + if (h->deblocking_filter) + xchg_mb_border(h, dest[0], dest[1], dest[2], linesize, + linesize, 0, 1, SIMPLE, PIXEL_SHIFT); + } else { + FUNC(hl_motion_444)(h, dest[0], dest[1], dest[2], + h->me.qpel_put, h->h264chroma.put_h264_chroma_pixels_tab, + h->me.qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab, + h->h264dsp.weight_h264_pixels_tab, + h->h264dsp.biweight_h264_pixels_tab); + } + + for (p = 0; p < plane_count; p++) + hl_decode_mb_idct_luma(h, mb_type, 1, SIMPLE, transform_bypass, + PIXEL_SHIFT, block_offset, linesize, + dest[p], p); + } +} + +#endif diff --git a/ffmpeg/libavcodec/h264_mc_template.c b/ffmpeg/libavcodec/h264_mc_template.c new file mode 100644 index 0000000..7aec43b --- /dev/null +++ b/ffmpeg/libavcodec/h264_mc_template.c @@ -0,0 +1,159 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... decoder + * Copyright (c) 2003 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 + */ + +#undef MCFUNC + +#if CHROMA_IDC == 1 +# define MCFUNC(n) FUNC(n ## _420) +#elif CHROMA_IDC == 2 +# define MCFUNC(n) FUNC(n ## _422) +#elif CHROMA_IDC == 3 +# define MCFUNC(n) FUNC(n ## _444) +#endif + +#undef mc_part +#define mc_part MCFUNC(mc_part) + +static void mc_part(H264Context *h, int n, int square, + int height, int delta, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int x_offset, int y_offset, + qpel_mc_func *qpix_put, + h264_chroma_mc_func chroma_put, + qpel_mc_func *qpix_avg, + h264_chroma_mc_func chroma_avg, + h264_weight_func *weight_op, + h264_biweight_func *weight_avg, + int list0, int list1) +{ + if ((h->use_weight == 2 && list0 && list1 && + (h->implicit_weight[h->ref_cache[0][scan8[n]]][h->ref_cache[1][scan8[n]]][h->mb_y & 1] != 32)) || + h->use_weight == 1) + mc_part_weighted(h, n, square, height, delta, dest_y, dest_cb, dest_cr, + x_offset, y_offset, qpix_put, chroma_put, + weight_op[0], weight_op[1], weight_avg[0], + weight_avg[1], list0, list1, PIXEL_SHIFT, CHROMA_IDC); + else + mc_part_std(h, n, square, height, delta, dest_y, dest_cb, dest_cr, + x_offset, y_offset, qpix_put, chroma_put, qpix_avg, + chroma_avg, list0, list1, PIXEL_SHIFT, CHROMA_IDC); +} + +static void MCFUNC(hl_motion)(H264Context *h, uint8_t *dest_y, + uint8_t *dest_cb, uint8_t *dest_cr, + qpel_mc_func(*qpix_put)[16], + h264_chroma_mc_func(*chroma_put), + qpel_mc_func(*qpix_avg)[16], + h264_chroma_mc_func(*chroma_avg), + h264_weight_func *weight_op, + h264_biweight_func *weight_avg) +{ + const int mb_xy = h->mb_xy; + const int mb_type = h->cur_pic.mb_type[mb_xy]; + + av_assert2(IS_INTER(mb_type)); + + if (HAVE_THREADS && (h->avctx->active_thread_type & FF_THREAD_FRAME)) + await_references(h); + prefetch_motion(h, 0, PIXEL_SHIFT, CHROMA_IDC); + + if (IS_16X16(mb_type)) { + mc_part(h, 0, 1, 16, 0, dest_y, dest_cb, dest_cr, 0, 0, + qpix_put[0], chroma_put[0], qpix_avg[0], chroma_avg[0], + weight_op, weight_avg, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1)); + } else if (IS_16X8(mb_type)) { + mc_part(h, 0, 0, 8, 8 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, 0, 0, + qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0], + weight_op, weight_avg, + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1)); + mc_part(h, 8, 0, 8, 8 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, 0, 4, + qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0], + weight_op, weight_avg, + IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1)); + } else if (IS_8X16(mb_type)) { + mc_part(h, 0, 0, 16, 8 * h->mb_linesize, dest_y, dest_cb, dest_cr, 0, 0, + qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1], + &weight_op[1], &weight_avg[1], + IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1)); + mc_part(h, 4, 0, 16, 8 * h->mb_linesize, dest_y, dest_cb, dest_cr, 4, 0, + qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1], + &weight_op[1], &weight_avg[1], + IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1)); + } else { + int i; + + av_assert2(IS_8X8(mb_type)); + + for (i = 0; i < 4; i++) { + const int sub_mb_type = h->sub_mb_type[i]; + const int n = 4 * i; + int x_offset = (i & 1) << 2; + int y_offset = (i & 2) << 1; + + if (IS_SUB_8X8(sub_mb_type)) { + mc_part(h, n, 1, 8, 0, dest_y, dest_cb, dest_cr, + x_offset, y_offset, + qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1], + &weight_op[1], &weight_avg[1], + IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); + } else if (IS_SUB_8X4(sub_mb_type)) { + mc_part(h, n, 0, 4, 4 << PIXEL_SHIFT, dest_y, dest_cb, dest_cr, + x_offset, y_offset, + qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1], + &weight_op[1], &weight_avg[1], + IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); + mc_part(h, n + 2, 0, 4, 4 << PIXEL_SHIFT, + dest_y, dest_cb, dest_cr, x_offset, y_offset + 2, + qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1], + &weight_op[1], &weight_avg[1], + IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); + } else if (IS_SUB_4X8(sub_mb_type)) { + mc_part(h, n, 0, 8, 4 * h->mb_linesize, + dest_y, dest_cb, dest_cr, x_offset, y_offset, + qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2], + &weight_op[2], &weight_avg[2], + IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); + mc_part(h, n + 1, 0, 8, 4 * h->mb_linesize, + dest_y, dest_cb, dest_cr, x_offset + 2, y_offset, + qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2], + &weight_op[2], &weight_avg[2], + IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); + } else { + int j; + av_assert2(IS_SUB_4X4(sub_mb_type)); + for (j = 0; j < 4; j++) { + int sub_x_offset = x_offset + 2 * (j & 1); + int sub_y_offset = y_offset + (j & 2); + mc_part(h, n + j, 1, 4, 0, + dest_y, dest_cb, dest_cr, sub_x_offset, sub_y_offset, + qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2], + &weight_op[2], &weight_avg[2], + IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1)); + } + } + } + } + + prefetch_motion(h, 1, PIXEL_SHIFT, CHROMA_IDC); +} + diff --git a/ffmpeg/libavcodec/h264_mp4toannexb_bsf.c b/ffmpeg/libavcodec/h264_mp4toannexb_bsf.c new file mode 100644 index 0000000..2dea933 --- /dev/null +++ b/ffmpeg/libavcodec/h264_mp4toannexb_bsf.c @@ -0,0 +1,188 @@ +/* + * H.264 MP4 to Annex B byte stream format filter + * Copyright (c) 2007 Benoit Fouet + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "avcodec.h" + +typedef struct H264BSFContext { + uint8_t length_size; + uint8_t first_idr; + int extradata_parsed; +} H264BSFContext; + +static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *sps_pps, uint32_t sps_pps_size, + const uint8_t *in, uint32_t in_size) { + uint32_t offset = *poutbuf_size; + uint8_t nal_header_size = offset ? 3 : 4; + void *tmp; + + *poutbuf_size += sps_pps_size+in_size+nal_header_size; + tmp = av_realloc(*poutbuf, *poutbuf_size); + if (!tmp) + return AVERROR(ENOMEM); + *poutbuf = tmp; + if (sps_pps) + memcpy(*poutbuf+offset, sps_pps, sps_pps_size); + memcpy(*poutbuf+sps_pps_size+nal_header_size+offset, in, in_size); + if (!offset) { + AV_WB32(*poutbuf+sps_pps_size, 1); + } else { + (*poutbuf+offset+sps_pps_size)[0] = (*poutbuf+offset+sps_pps_size)[1] = 0; + (*poutbuf+offset+sps_pps_size)[2] = 1; + } + + return 0; +} + +static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int keyframe) { + H264BSFContext *ctx = bsfc->priv_data; + int i; + uint8_t unit_type; + int32_t nal_size; + uint32_t cumul_size = 0; + const uint8_t *buf_end = buf + buf_size; + int ret = AVERROR(EINVAL); + + /* nothing to filter */ + if (!avctx->extradata || avctx->extradata_size < 6) { + *poutbuf = (uint8_t*) buf; + *poutbuf_size = buf_size; + return 0; + } + + /* retrieve sps and pps NAL units from extradata */ + if (!ctx->extradata_parsed) { + uint16_t unit_size; + uint64_t total_size = 0; + uint8_t *out = NULL, unit_nb, sps_done = 0, sps_seen = 0, pps_seen = 0; + const uint8_t *extradata = avctx->extradata+4; + static const uint8_t nalu_header[4] = {0, 0, 0, 1}; + + /* retrieve length coded size */ + ctx->length_size = (*extradata++ & 0x3) + 1; + + /* retrieve sps and pps unit(s) */ + unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */ + if (!unit_nb) { + goto pps; + } else { + sps_seen = 1; + } + + while (unit_nb--) { + void *tmp; + + unit_size = AV_RB16(extradata); + total_size += unit_size+4; + if (total_size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE || + extradata+2+unit_size > avctx->extradata+avctx->extradata_size) { + av_free(out); + return AVERROR(EINVAL); + } + tmp = av_realloc(out, total_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!tmp) { + av_free(out); + return AVERROR(ENOMEM); + } + out = tmp; + memcpy(out+total_size-unit_size-4, nalu_header, 4); + memcpy(out+total_size-unit_size, extradata+2, unit_size); + extradata += 2+unit_size; +pps: + if (!unit_nb && !sps_done++) { + unit_nb = *extradata++; /* number of pps unit(s) */ + if (unit_nb) + pps_seen = 1; + } + } + + if(out) + memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + if (!sps_seen) + av_log(avctx, AV_LOG_WARNING, "Warning: SPS NALU missing or invalid. The resulting stream may not play.\n"); + if (!pps_seen) + av_log(avctx, AV_LOG_WARNING, "Warning: PPS NALU missing or invalid. The resulting stream may not play.\n"); + + av_free(avctx->extradata); + avctx->extradata = out; + avctx->extradata_size = total_size; + ctx->first_idr = 1; + ctx->extradata_parsed = 1; + } + + *poutbuf_size = 0; + *poutbuf = NULL; + do { + ret= AVERROR(EINVAL); + if (buf + ctx->length_size > buf_end) + goto fail; + + for (nal_size = 0, i = 0; ilength_size; i++) + nal_size = (nal_size << 8) | buf[i]; + + buf += ctx->length_size; + unit_type = *buf & 0x1f; + + if (buf + nal_size > buf_end || nal_size < 0) + goto fail; + + /* prepend only to the first type 5 NAL unit of an IDR picture */ + if (ctx->first_idr && unit_type == 5) { + if ((ret=alloc_and_copy(poutbuf, poutbuf_size, + avctx->extradata, avctx->extradata_size, + buf, nal_size)) < 0) + goto fail; + ctx->first_idr = 0; + } else { + if ((ret=alloc_and_copy(poutbuf, poutbuf_size, + NULL, 0, + buf, nal_size)) < 0) + goto fail; + if (!ctx->first_idr && unit_type == 1) + ctx->first_idr = 1; + } + + buf += nal_size; + cumul_size += nal_size + ctx->length_size; + } while (cumul_size < buf_size); + + return 1; + +fail: + av_freep(poutbuf); + *poutbuf_size = 0; + return ret; +} + +AVBitStreamFilter ff_h264_mp4toannexb_bsf = { + "h264_mp4toannexb", + sizeof(H264BSFContext), + h264_mp4toannexb_filter, +}; diff --git a/ffmpeg/libavcodec/h264_mvpred.h b/ffmpeg/libavcodec/h264_mvpred.h new file mode 100644 index 0000000..361c1d7 --- /dev/null +++ b/ffmpeg/libavcodec/h264_mvpred.h @@ -0,0 +1,829 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... motion vector predicion + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 motion vector predicion. + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_H264_MVPRED_H +#define AVCODEC_H264_MVPRED_H + +#include "internal.h" +#include "avcodec.h" +#include "h264.h" +#include "libavutil/avassert.h" + + +static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C, + int i, int list, int part_width) +{ + const int topright_ref = h->ref_cache[list][i - 8 + part_width]; + + /* there is no consistent mapping of mvs to neighboring locations that will + * make mbaff happy, so we can't move all this logic to fill_caches */ + if (FRAME_MBAFF(h)) { +#define SET_DIAG_MV(MV_OP, REF_OP, XY, Y4) \ + const int xy = XY, y4 = Y4; \ + const int mb_type = mb_types[xy + (y4 >> 2) * h->mb_stride]; \ + if (!USES_LIST(mb_type, list)) \ + return LIST_NOT_USED; \ + mv = h->cur_pic_ptr->motion_val[list][h->mb2b_xy[xy] + 3 + y4 * h->b_stride]; \ + h->mv_cache[list][scan8[0] - 2][0] = mv[0]; \ + h->mv_cache[list][scan8[0] - 2][1] = mv[1] MV_OP; \ + return h->cur_pic_ptr->ref_index[list][4 * xy + 1 + (y4 & ~1)] REF_OP; + + if (topright_ref == PART_NOT_AVAILABLE + && i >= scan8[0] + 8 && (i & 7) == 4 + && h->ref_cache[list][scan8[0] - 1] != PART_NOT_AVAILABLE) { + const uint32_t *mb_types = h->cur_pic_ptr->mb_type; + const int16_t *mv; + AV_ZERO32(h->mv_cache[list][scan8[0] - 2]); + *C = h->mv_cache[list][scan8[0] - 2]; + + if (!MB_FIELD(h) && IS_INTERLACED(h->left_type[0])) { + SET_DIAG_MV(* 2, >> 1, h->left_mb_xy[0] + h->mb_stride, + (h->mb_y & 1) * 2 + (i >> 5)); + } + if (MB_FIELD(h) && !IS_INTERLACED(h->left_type[0])) { + // left shift will turn LIST_NOT_USED into PART_NOT_AVAILABLE, but that's OK. + SET_DIAG_MV(/ 2, << 1, h->left_mb_xy[i >= 36], ((i >> 2)) & 3); + } + } +#undef SET_DIAG_MV + } + + if (topright_ref != PART_NOT_AVAILABLE) { + *C = h->mv_cache[list][i - 8 + part_width]; + return topright_ref; + } else { + tprintf(h->avctx, "topright MV not available\n"); + + *C = h->mv_cache[list][i - 8 - 1]; + return h->ref_cache[list][i - 8 - 1]; + } +} + +/** + * Get the predicted MV. + * @param n the block index + * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4) + * @param mx the x component of the predicted motion vector + * @param my the y component of the predicted motion vector + */ +static av_always_inline void pred_motion(H264Context *const h, int n, + int part_width, int list, int ref, + int *const mx, int *const my) +{ + const int index8 = scan8[n]; + const int top_ref = h->ref_cache[list][index8 - 8]; + const int left_ref = h->ref_cache[list][index8 - 1]; + const int16_t *const A = h->mv_cache[list][index8 - 1]; + const int16_t *const B = h->mv_cache[list][index8 - 8]; + const int16_t *C; + int diagonal_ref, match_count; + + av_assert2(part_width == 1 || part_width == 2 || part_width == 4); + +/* mv_cache + * B . . A T T T T + * U . . L . . , . + * U . . L . . . . + * U . . L . . , . + * . . . L . . . . + */ + + diagonal_ref = fetch_diagonal_mv(h, &C, index8, list, part_width); + match_count = (diagonal_ref == ref) + (top_ref == ref) + (left_ref == ref); + tprintf(h->avctx, "pred_motion match_count=%d\n", match_count); + if (match_count > 1) { //most common + *mx = mid_pred(A[0], B[0], C[0]); + *my = mid_pred(A[1], B[1], C[1]); + } else if (match_count == 1) { + if (left_ref == ref) { + *mx = A[0]; + *my = A[1]; + } else if (top_ref == ref) { + *mx = B[0]; + *my = B[1]; + } else { + *mx = C[0]; + *my = C[1]; + } + } else { + if (top_ref == PART_NOT_AVAILABLE && + diagonal_ref == PART_NOT_AVAILABLE && + left_ref != PART_NOT_AVAILABLE) { + *mx = A[0]; + *my = A[1]; + } else { + *mx = mid_pred(A[0], B[0], C[0]); + *my = mid_pred(A[1], B[1], C[1]); + } + } + + tprintf(h->avctx, + "pred_motion (%2d %2d %2d) (%2d %2d %2d) (%2d %2d %2d) -> (%2d %2d %2d) at %2d %2d %d list %d\n", + top_ref, B[0], B[1], diagonal_ref, C[0], C[1], left_ref, + A[0], A[1], ref, *mx, *my, h->mb_x, h->mb_y, n, list); +} + +/** + * Get the directionally predicted 16x8 MV. + * @param n the block index + * @param mx the x component of the predicted motion vector + * @param my the y component of the predicted motion vector + */ +static av_always_inline void pred_16x8_motion(H264Context *const h, + int n, int list, int ref, + int *const mx, int *const my) +{ + if (n == 0) { + const int top_ref = h->ref_cache[list][scan8[0] - 8]; + const int16_t *const B = h->mv_cache[list][scan8[0] - 8]; + + tprintf(h->avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", + top_ref, B[0], B[1], h->mb_x, h->mb_y, n, list); + + if (top_ref == ref) { + *mx = B[0]; + *my = B[1]; + return; + } + } else { + const int left_ref = h->ref_cache[list][scan8[8] - 1]; + const int16_t *const A = h->mv_cache[list][scan8[8] - 1]; + + tprintf(h->avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", + left_ref, A[0], A[1], h->mb_x, h->mb_y, n, list); + + if (left_ref == ref) { + *mx = A[0]; + *my = A[1]; + return; + } + } + + //RARE + pred_motion(h, n, 4, list, ref, mx, my); +} + +/** + * Get the directionally predicted 8x16 MV. + * @param n the block index + * @param mx the x component of the predicted motion vector + * @param my the y component of the predicted motion vector + */ +static av_always_inline void pred_8x16_motion(H264Context *const h, + int n, int list, int ref, + int *const mx, int *const my) +{ + if (n == 0) { + const int left_ref = h->ref_cache[list][scan8[0] - 1]; + const int16_t *const A = h->mv_cache[list][scan8[0] - 1]; + + tprintf(h->avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", + left_ref, A[0], A[1], h->mb_x, h->mb_y, n, list); + + if (left_ref == ref) { + *mx = A[0]; + *my = A[1]; + return; + } + } else { + const int16_t *C; + int diagonal_ref; + + diagonal_ref = fetch_diagonal_mv(h, &C, scan8[4], list, 2); + + tprintf(h->avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", + diagonal_ref, C[0], C[1], h->mb_x, h->mb_y, n, list); + + if (diagonal_ref == ref) { + *mx = C[0]; + *my = C[1]; + return; + } + } + + //RARE + pred_motion(h, n, 2, list, ref, mx, my); +} + +#define FIX_MV_MBAFF(type, refn, mvn, idx) \ + if (FRAME_MBAFF(h)) { \ + if (MB_FIELD(h)) { \ + if (!IS_INTERLACED(type)) { \ + refn <<= 1; \ + AV_COPY32(mvbuf[idx], mvn); \ + mvbuf[idx][1] /= 2; \ + mvn = mvbuf[idx]; \ + } \ + } else { \ + if (IS_INTERLACED(type)) { \ + refn >>= 1; \ + AV_COPY32(mvbuf[idx], mvn); \ + mvbuf[idx][1] <<= 1; \ + mvn = mvbuf[idx]; \ + } \ + } \ + } + +static av_always_inline void pred_pskip_motion(H264Context *const h) +{ + DECLARE_ALIGNED(4, static const int16_t, zeromv)[2] = { 0 }; + DECLARE_ALIGNED(4, int16_t, mvbuf)[3][2]; + int8_t *ref = h->cur_pic.ref_index[0]; + int16_t(*mv)[2] = h->cur_pic.motion_val[0]; + int top_ref, left_ref, diagonal_ref, match_count, mx, my; + const int16_t *A, *B, *C; + int b_stride = h->b_stride; + + fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1); + + /* To avoid doing an entire fill_decode_caches, we inline the relevant + * parts here. + * FIXME: this is a partial duplicate of the logic in fill_decode_caches, + * but it's faster this way. Is there a way to avoid this duplication? + */ + if (USES_LIST(h->left_type[LTOP], 0)) { + left_ref = ref[4 * h->left_mb_xy[LTOP] + 1 + (h->left_block[0] & ~1)]; + A = mv[h->mb2b_xy[h->left_mb_xy[LTOP]] + 3 + b_stride * h->left_block[0]]; + FIX_MV_MBAFF(h->left_type[LTOP], left_ref, A, 0); + if (!(left_ref | AV_RN32A(A))) + goto zeromv; + } else if (h->left_type[LTOP]) { + left_ref = LIST_NOT_USED; + A = zeromv; + } else { + goto zeromv; + } + + if (USES_LIST(h->top_type, 0)) { + top_ref = ref[4 * h->top_mb_xy + 2]; + B = mv[h->mb2b_xy[h->top_mb_xy] + 3 * b_stride]; + FIX_MV_MBAFF(h->top_type, top_ref, B, 1); + if (!(top_ref | AV_RN32A(B))) + goto zeromv; + } else if (h->top_type) { + top_ref = LIST_NOT_USED; + B = zeromv; + } else { + goto zeromv; + } + + tprintf(h->avctx, "pred_pskip: (%d) (%d) at %2d %2d\n", + top_ref, left_ref, h->mb_x, h->mb_y); + + if (USES_LIST(h->topright_type, 0)) { + diagonal_ref = ref[4 * h->topright_mb_xy + 2]; + C = mv[h->mb2b_xy[h->topright_mb_xy] + 3 * b_stride]; + FIX_MV_MBAFF(h->topright_type, diagonal_ref, C, 2); + } else if (h->topright_type) { + diagonal_ref = LIST_NOT_USED; + C = zeromv; + } else { + if (USES_LIST(h->topleft_type, 0)) { + diagonal_ref = ref[4 * h->topleft_mb_xy + 1 + + (h->topleft_partition & 2)]; + C = mv[h->mb2b_xy[h->topleft_mb_xy] + 3 + b_stride + + (h->topleft_partition & 2 * b_stride)]; + FIX_MV_MBAFF(h->topleft_type, diagonal_ref, C, 2); + } else if (h->topleft_type) { + diagonal_ref = LIST_NOT_USED; + C = zeromv; + } else { + diagonal_ref = PART_NOT_AVAILABLE; + C = zeromv; + } + } + + match_count = !diagonal_ref + !top_ref + !left_ref; + tprintf(h->avctx, "pred_pskip_motion match_count=%d\n", match_count); + if (match_count > 1) { + mx = mid_pred(A[0], B[0], C[0]); + my = mid_pred(A[1], B[1], C[1]); + } else if (match_count == 1) { + if (!left_ref) { + mx = A[0]; + my = A[1]; + } else if (!top_ref) { + mx = B[0]; + my = B[1]; + } else { + mx = C[0]; + my = C[1]; + } + } else { + mx = mid_pred(A[0], B[0], C[0]); + my = mid_pred(A[1], B[1], C[1]); + } + + fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx, my), 4); + return; + +zeromv: + fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); + return; +} + +static void fill_decode_neighbors(H264Context *h, int mb_type) +{ + const int mb_xy = h->mb_xy; + int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS]; + static const uint8_t left_block_options[4][32] = { + { 0, 1, 2, 3, 7, 10, 8, 11, 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4, 3 + 3 * 4, 1 + 4 * 4, 1 + 8 * 4, 1 + 5 * 4, 1 + 9 * 4 }, + { 2, 2, 3, 3, 8, 11, 8, 11, 3 + 2 * 4, 3 + 2 * 4, 3 + 3 * 4, 3 + 3 * 4, 1 + 5 * 4, 1 + 9 * 4, 1 + 5 * 4, 1 + 9 * 4 }, + { 0, 0, 1, 1, 7, 10, 7, 10, 3 + 0 * 4, 3 + 0 * 4, 3 + 1 * 4, 3 + 1 * 4, 1 + 4 * 4, 1 + 8 * 4, 1 + 4 * 4, 1 + 8 * 4 }, + { 0, 2, 0, 2, 7, 10, 7, 10, 3 + 0 * 4, 3 + 2 * 4, 3 + 0 * 4, 3 + 2 * 4, 1 + 4 * 4, 1 + 8 * 4, 1 + 4 * 4, 1 + 8 * 4 } + }; + + h->topleft_partition = -1; + + top_xy = mb_xy - (h->mb_stride << MB_FIELD(h)); + + /* Wow, what a mess, why didn't they simplify the interlacing & intra + * stuff, I can't imagine that these complex rules are worth it. */ + + topleft_xy = top_xy - 1; + topright_xy = top_xy + 1; + left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; + h->left_block = left_block_options[0]; + if (FRAME_MBAFF(h)) { + const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); + const int curr_mb_field_flag = IS_INTERLACED(mb_type); + if (h->mb_y & 1) { + if (left_mb_field_flag != curr_mb_field_flag) { + left_xy[LBOT] = left_xy[LTOP] = mb_xy - h->mb_stride - 1; + if (curr_mb_field_flag) { + left_xy[LBOT] += h->mb_stride; + h->left_block = left_block_options[3]; + } else { + topleft_xy += h->mb_stride; + /* take top left mv from the middle of the mb, as opposed + * to all other modes which use the bottom right partition */ + h->topleft_partition = 0; + h->left_block = left_block_options[1]; + } + } + } else { + if (curr_mb_field_flag) { + topleft_xy += h->mb_stride & (((h->cur_pic.mb_type[top_xy - 1] >> 7) & 1) - 1); + topright_xy += h->mb_stride & (((h->cur_pic.mb_type[top_xy + 1] >> 7) & 1) - 1); + top_xy += h->mb_stride & (((h->cur_pic.mb_type[top_xy] >> 7) & 1) - 1); + } + if (left_mb_field_flag != curr_mb_field_flag) { + if (curr_mb_field_flag) { + left_xy[LBOT] += h->mb_stride; + h->left_block = left_block_options[3]; + } else { + h->left_block = left_block_options[2]; + } + } + } + } + + h->topleft_mb_xy = topleft_xy; + h->top_mb_xy = top_xy; + h->topright_mb_xy = topright_xy; + h->left_mb_xy[LTOP] = left_xy[LTOP]; + h->left_mb_xy[LBOT] = left_xy[LBOT]; + //FIXME do we need all in the context? + + h->topleft_type = h->cur_pic.mb_type[topleft_xy]; + h->top_type = h->cur_pic.mb_type[top_xy]; + h->topright_type = h->cur_pic.mb_type[topright_xy]; + h->left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; + h->left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; + + if (FMO) { + if (h->slice_table[topleft_xy] != h->slice_num) + h->topleft_type = 0; + if (h->slice_table[top_xy] != h->slice_num) + h->top_type = 0; + if (h->slice_table[left_xy[LTOP]] != h->slice_num) + h->left_type[LTOP] = h->left_type[LBOT] = 0; + } else { + if (h->slice_table[topleft_xy] != h->slice_num) { + h->topleft_type = 0; + if (h->slice_table[top_xy] != h->slice_num) + h->top_type = 0; + if (h->slice_table[left_xy[LTOP]] != h->slice_num) + h->left_type[LTOP] = h->left_type[LBOT] = 0; + } + } + if (h->slice_table[topright_xy] != h->slice_num) + h->topright_type = 0; +} + +static void fill_decode_caches(H264Context *h, int mb_type) +{ + int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS]; + int topleft_type, top_type, topright_type, left_type[LEFT_MBS]; + const uint8_t *left_block = h->left_block; + int i; + uint8_t *nnz; + uint8_t *nnz_cache; + + topleft_xy = h->topleft_mb_xy; + top_xy = h->top_mb_xy; + topright_xy = h->topright_mb_xy; + left_xy[LTOP] = h->left_mb_xy[LTOP]; + left_xy[LBOT] = h->left_mb_xy[LBOT]; + topleft_type = h->topleft_type; + top_type = h->top_type; + topright_type = h->topright_type; + left_type[LTOP] = h->left_type[LTOP]; + left_type[LBOT] = h->left_type[LBOT]; + + if (!IS_SKIP(mb_type)) { + if (IS_INTRA(mb_type)) { + int type_mask = h->pps.constrained_intra_pred ? IS_INTRA(-1) : -1; + h->topleft_samples_available = + h->top_samples_available = + h->left_samples_available = 0xFFFF; + h->topright_samples_available = 0xEEEA; + + if (!(top_type & type_mask)) { + h->topleft_samples_available = 0xB3FF; + h->top_samples_available = 0x33FF; + h->topright_samples_available = 0x26EA; + } + if (IS_INTERLACED(mb_type) != IS_INTERLACED(left_type[LTOP])) { + if (IS_INTERLACED(mb_type)) { + if (!(left_type[LTOP] & type_mask)) { + h->topleft_samples_available &= 0xDFFF; + h->left_samples_available &= 0x5FFF; + } + if (!(left_type[LBOT] & type_mask)) { + h->topleft_samples_available &= 0xFF5F; + h->left_samples_available &= 0xFF5F; + } + } else { + int left_typei = h->cur_pic.mb_type[left_xy[LTOP] + h->mb_stride]; + + av_assert2(left_xy[LTOP] == left_xy[LBOT]); + if (!((left_typei & type_mask) && (left_type[LTOP] & type_mask))) { + h->topleft_samples_available &= 0xDF5F; + h->left_samples_available &= 0x5F5F; + } + } + } else { + if (!(left_type[LTOP] & type_mask)) { + h->topleft_samples_available &= 0xDF5F; + h->left_samples_available &= 0x5F5F; + } + } + + if (!(topleft_type & type_mask)) + h->topleft_samples_available &= 0x7FFF; + + if (!(topright_type & type_mask)) + h->topright_samples_available &= 0xFBFF; + + if (IS_INTRA4x4(mb_type)) { + if (IS_INTRA4x4(top_type)) { + AV_COPY32(h->intra4x4_pred_mode_cache + 4 + 8 * 0, h->intra4x4_pred_mode + h->mb2br_xy[top_xy]); + } else { + h->intra4x4_pred_mode_cache[4 + 8 * 0] = + h->intra4x4_pred_mode_cache[5 + 8 * 0] = + h->intra4x4_pred_mode_cache[6 + 8 * 0] = + h->intra4x4_pred_mode_cache[7 + 8 * 0] = 2 - 3 * !(top_type & type_mask); + } + for (i = 0; i < 2; i++) { + if (IS_INTRA4x4(left_type[LEFT(i)])) { + int8_t *mode = h->intra4x4_pred_mode + h->mb2br_xy[left_xy[LEFT(i)]]; + h->intra4x4_pred_mode_cache[3 + 8 * 1 + 2 * 8 * i] = mode[6 - left_block[0 + 2 * i]]; + h->intra4x4_pred_mode_cache[3 + 8 * 2 + 2 * 8 * i] = mode[6 - left_block[1 + 2 * i]]; + } else { + h->intra4x4_pred_mode_cache[3 + 8 * 1 + 2 * 8 * i] = + h->intra4x4_pred_mode_cache[3 + 8 * 2 + 2 * 8 * i] = 2 - 3 * !(left_type[LEFT(i)] & type_mask); + } + } + } + } + + /* + * 0 . T T. T T T T + * 1 L . .L . . . . + * 2 L . .L . . . . + * 3 . T TL . . . . + * 4 L . .L . . . . + * 5 L . .. . . . . + */ + /* FIXME: constraint_intra_pred & partitioning & nnz + * (let us hope this is just a typo in the spec) */ + nnz_cache = h->non_zero_count_cache; + if (top_type) { + nnz = h->non_zero_count[top_xy]; + AV_COPY32(&nnz_cache[4 + 8 * 0], &nnz[4 * 3]); + if (!h->chroma_y_shift) { + AV_COPY32(&nnz_cache[4 + 8 * 5], &nnz[4 * 7]); + AV_COPY32(&nnz_cache[4 + 8 * 10], &nnz[4 * 11]); + } else { + AV_COPY32(&nnz_cache[4 + 8 * 5], &nnz[4 * 5]); + AV_COPY32(&nnz_cache[4 + 8 * 10], &nnz[4 * 9]); + } + } else { + uint32_t top_empty = CABAC(h) && !IS_INTRA(mb_type) ? 0 : 0x40404040; + AV_WN32A(&nnz_cache[4 + 8 * 0], top_empty); + AV_WN32A(&nnz_cache[4 + 8 * 5], top_empty); + AV_WN32A(&nnz_cache[4 + 8 * 10], top_empty); + } + + for (i = 0; i < 2; i++) { + if (left_type[LEFT(i)]) { + nnz = h->non_zero_count[left_xy[LEFT(i)]]; + nnz_cache[3 + 8 * 1 + 2 * 8 * i] = nnz[left_block[8 + 0 + 2 * i]]; + nnz_cache[3 + 8 * 2 + 2 * 8 * i] = nnz[left_block[8 + 1 + 2 * i]]; + if (CHROMA444) { + nnz_cache[3 + 8 * 6 + 2 * 8 * i] = nnz[left_block[8 + 0 + 2 * i] + 4 * 4]; + nnz_cache[3 + 8 * 7 + 2 * 8 * i] = nnz[left_block[8 + 1 + 2 * i] + 4 * 4]; + nnz_cache[3 + 8 * 11 + 2 * 8 * i] = nnz[left_block[8 + 0 + 2 * i] + 8 * 4]; + nnz_cache[3 + 8 * 12 + 2 * 8 * i] = nnz[left_block[8 + 1 + 2 * i] + 8 * 4]; + } else if (CHROMA422) { + nnz_cache[3 + 8 * 6 + 2 * 8 * i] = nnz[left_block[8 + 0 + 2 * i] - 2 + 4 * 4]; + nnz_cache[3 + 8 * 7 + 2 * 8 * i] = nnz[left_block[8 + 1 + 2 * i] - 2 + 4 * 4]; + nnz_cache[3 + 8 * 11 + 2 * 8 * i] = nnz[left_block[8 + 0 + 2 * i] - 2 + 8 * 4]; + nnz_cache[3 + 8 * 12 + 2 * 8 * i] = nnz[left_block[8 + 1 + 2 * i] - 2 + 8 * 4]; + } else { + nnz_cache[3 + 8 * 6 + 8 * i] = nnz[left_block[8 + 4 + 2 * i]]; + nnz_cache[3 + 8 * 11 + 8 * i] = nnz[left_block[8 + 5 + 2 * i]]; + } + } else { + nnz_cache[3 + 8 * 1 + 2 * 8 * i] = + nnz_cache[3 + 8 * 2 + 2 * 8 * i] = + nnz_cache[3 + 8 * 6 + 2 * 8 * i] = + nnz_cache[3 + 8 * 7 + 2 * 8 * i] = + nnz_cache[3 + 8 * 11 + 2 * 8 * i] = + nnz_cache[3 + 8 * 12 + 2 * 8 * i] = CABAC(h) && !IS_INTRA(mb_type) ? 0 : 64; + } + } + + if (CABAC(h)) { + // top_cbp + if (top_type) + h->top_cbp = h->cbp_table[top_xy]; + else + h->top_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; + // left_cbp + if (left_type[LTOP]) { + h->left_cbp = (h->cbp_table[left_xy[LTOP]] & 0x7F0) | + ((h->cbp_table[left_xy[LTOP]] >> (left_block[0] & (~1))) & 2) | + (((h->cbp_table[left_xy[LBOT]] >> (left_block[2] & (~1))) & 2) << 2); + } else { + h->left_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; + } + } + } + + if (IS_INTER(mb_type) || (IS_DIRECT(mb_type) && h->direct_spatial_mv_pred)) { + int list; + int b_stride = h->b_stride; + for (list = 0; list < h->list_count; list++) { + int8_t *ref_cache = &h->ref_cache[list][scan8[0]]; + int8_t *ref = h->cur_pic.ref_index[list]; + int16_t(*mv_cache)[2] = &h->mv_cache[list][scan8[0]]; + int16_t(*mv)[2] = h->cur_pic.motion_val[list]; + if (!USES_LIST(mb_type, list)) + continue; + av_assert2(!(IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred)); + + if (USES_LIST(top_type, list)) { + const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride; + AV_COPY128(mv_cache[0 - 1 * 8], mv[b_xy + 0]); + ref_cache[0 - 1 * 8] = + ref_cache[1 - 1 * 8] = ref[4 * top_xy + 2]; + ref_cache[2 - 1 * 8] = + ref_cache[3 - 1 * 8] = ref[4 * top_xy + 3]; + } else { + AV_ZERO128(mv_cache[0 - 1 * 8]); + AV_WN32A(&ref_cache[0 - 1 * 8], + ((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE) & 0xFF) * 0x01010101u); + } + + if (mb_type & (MB_TYPE_16x8 | MB_TYPE_8x8)) { + for (i = 0; i < 2; i++) { + int cache_idx = -1 + i * 2 * 8; + if (USES_LIST(left_type[LEFT(i)], list)) { + const int b_xy = h->mb2b_xy[left_xy[LEFT(i)]] + 3; + const int b8_xy = 4 * left_xy[LEFT(i)] + 1; + AV_COPY32(mv_cache[cache_idx], + mv[b_xy + b_stride * left_block[0 + i * 2]]); + AV_COPY32(mv_cache[cache_idx + 8], + mv[b_xy + b_stride * left_block[1 + i * 2]]); + ref_cache[cache_idx] = ref[b8_xy + (left_block[0 + i * 2] & ~1)]; + ref_cache[cache_idx + 8] = ref[b8_xy + (left_block[1 + i * 2] & ~1)]; + } else { + AV_ZERO32(mv_cache[cache_idx]); + AV_ZERO32(mv_cache[cache_idx + 8]); + ref_cache[cache_idx] = + ref_cache[cache_idx + 8] = (left_type[LEFT(i)]) ? LIST_NOT_USED + : PART_NOT_AVAILABLE; + } + } + } else { + if (USES_LIST(left_type[LTOP], list)) { + const int b_xy = h->mb2b_xy[left_xy[LTOP]] + 3; + const int b8_xy = 4 * left_xy[LTOP] + 1; + AV_COPY32(mv_cache[-1], mv[b_xy + b_stride * left_block[0]]); + ref_cache[-1] = ref[b8_xy + (left_block[0] & ~1)]; + } else { + AV_ZERO32(mv_cache[-1]); + ref_cache[-1] = left_type[LTOP] ? LIST_NOT_USED + : PART_NOT_AVAILABLE; + } + } + + if (USES_LIST(topright_type, list)) { + const int b_xy = h->mb2b_xy[topright_xy] + 3 * b_stride; + AV_COPY32(mv_cache[4 - 1 * 8], mv[b_xy]); + ref_cache[4 - 1 * 8] = ref[4 * topright_xy + 2]; + } else { + AV_ZERO32(mv_cache[4 - 1 * 8]); + ref_cache[4 - 1 * 8] = topright_type ? LIST_NOT_USED + : PART_NOT_AVAILABLE; + } + if(ref_cache[2 - 1*8] < 0 || ref_cache[4 - 1*8] < 0){ + if (USES_LIST(topleft_type, list)) { + const int b_xy = h->mb2b_xy[topleft_xy] + 3 + b_stride + + (h->topleft_partition & 2 * b_stride); + const int b8_xy = 4 * topleft_xy + 1 + (h->topleft_partition & 2); + AV_COPY32(mv_cache[-1 - 1 * 8], mv[b_xy]); + ref_cache[-1 - 1 * 8] = ref[b8_xy]; + } else { + AV_ZERO32(mv_cache[-1 - 1 * 8]); + ref_cache[-1 - 1 * 8] = topleft_type ? LIST_NOT_USED + : PART_NOT_AVAILABLE; + } + } + + if ((mb_type & (MB_TYPE_SKIP | MB_TYPE_DIRECT2)) && !FRAME_MBAFF(h)) + continue; + + if (!(mb_type & (MB_TYPE_SKIP | MB_TYPE_DIRECT2))) { + uint8_t(*mvd_cache)[2] = &h->mvd_cache[list][scan8[0]]; + uint8_t(*mvd)[2] = h->mvd_table[list]; + ref_cache[2 + 8 * 0] = + ref_cache[2 + 8 * 2] = PART_NOT_AVAILABLE; + AV_ZERO32(mv_cache[2 + 8 * 0]); + AV_ZERO32(mv_cache[2 + 8 * 2]); + + if (CABAC(h)) { + if (USES_LIST(top_type, list)) { + const int b_xy = h->mb2br_xy[top_xy]; + AV_COPY64(mvd_cache[0 - 1 * 8], mvd[b_xy + 0]); + } else { + AV_ZERO64(mvd_cache[0 - 1 * 8]); + } + if (USES_LIST(left_type[LTOP], list)) { + const int b_xy = h->mb2br_xy[left_xy[LTOP]] + 6; + AV_COPY16(mvd_cache[-1 + 0 * 8], mvd[b_xy - left_block[0]]); + AV_COPY16(mvd_cache[-1 + 1 * 8], mvd[b_xy - left_block[1]]); + } else { + AV_ZERO16(mvd_cache[-1 + 0 * 8]); + AV_ZERO16(mvd_cache[-1 + 1 * 8]); + } + if (USES_LIST(left_type[LBOT], list)) { + const int b_xy = h->mb2br_xy[left_xy[LBOT]] + 6; + AV_COPY16(mvd_cache[-1 + 2 * 8], mvd[b_xy - left_block[2]]); + AV_COPY16(mvd_cache[-1 + 3 * 8], mvd[b_xy - left_block[3]]); + } else { + AV_ZERO16(mvd_cache[-1 + 2 * 8]); + AV_ZERO16(mvd_cache[-1 + 3 * 8]); + } + AV_ZERO16(mvd_cache[2 + 8 * 0]); + AV_ZERO16(mvd_cache[2 + 8 * 2]); + if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + uint8_t *direct_cache = &h->direct_cache[scan8[0]]; + uint8_t *direct_table = h->direct_table; + fill_rectangle(direct_cache, 4, 4, 8, MB_TYPE_16x16 >> 1, 1); + + if (IS_DIRECT(top_type)) { + AV_WN32A(&direct_cache[-1 * 8], + 0x01010101u * (MB_TYPE_DIRECT2 >> 1)); + } else if (IS_8X8(top_type)) { + int b8_xy = 4 * top_xy; + direct_cache[0 - 1 * 8] = direct_table[b8_xy + 2]; + direct_cache[2 - 1 * 8] = direct_table[b8_xy + 3]; + } else { + AV_WN32A(&direct_cache[-1 * 8], + 0x01010101 * (MB_TYPE_16x16 >> 1)); + } + + if (IS_DIRECT(left_type[LTOP])) + direct_cache[-1 + 0 * 8] = MB_TYPE_DIRECT2 >> 1; + else if (IS_8X8(left_type[LTOP])) + direct_cache[-1 + 0 * 8] = direct_table[4 * left_xy[LTOP] + 1 + (left_block[0] & ~1)]; + else + direct_cache[-1 + 0 * 8] = MB_TYPE_16x16 >> 1; + + if (IS_DIRECT(left_type[LBOT])) + direct_cache[-1 + 2 * 8] = MB_TYPE_DIRECT2 >> 1; + else if (IS_8X8(left_type[LBOT])) + direct_cache[-1 + 2 * 8] = direct_table[4 * left_xy[LBOT] + 1 + (left_block[2] & ~1)]; + else + direct_cache[-1 + 2 * 8] = MB_TYPE_16x16 >> 1; + } + } + } + +#define MAP_MVS \ + MAP_F2F(scan8[0] - 1 - 1 * 8, topleft_type) \ + MAP_F2F(scan8[0] + 0 - 1 * 8, top_type) \ + MAP_F2F(scan8[0] + 1 - 1 * 8, top_type) \ + MAP_F2F(scan8[0] + 2 - 1 * 8, top_type) \ + MAP_F2F(scan8[0] + 3 - 1 * 8, top_type) \ + MAP_F2F(scan8[0] + 4 - 1 * 8, topright_type) \ + MAP_F2F(scan8[0] - 1 + 0 * 8, left_type[LTOP]) \ + MAP_F2F(scan8[0] - 1 + 1 * 8, left_type[LTOP]) \ + MAP_F2F(scan8[0] - 1 + 2 * 8, left_type[LBOT]) \ + MAP_F2F(scan8[0] - 1 + 3 * 8, left_type[LBOT]) + + if (FRAME_MBAFF(h)) { + if (MB_FIELD(h)) { + +#define MAP_F2F(idx, mb_type) \ + if (!IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \ + h->ref_cache[list][idx] <<= 1; \ + h->mv_cache[list][idx][1] /= 2; \ + h->mvd_cache[list][idx][1] >>= 1; \ + } + + MAP_MVS + } else { + +#undef MAP_F2F +#define MAP_F2F(idx, mb_type) \ + if (IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \ + h->ref_cache[list][idx] >>= 1; \ + h->mv_cache[list][idx][1] <<= 1; \ + h->mvd_cache[list][idx][1] <<= 1; \ + } + + MAP_MVS +#undef MAP_F2F + } + } + } + } + + h->neighbor_transform_size = !!IS_8x8DCT(top_type) + !!IS_8x8DCT(left_type[LTOP]); +} + +/** + * decodes a P_SKIP or B_SKIP macroblock + */ +static void av_unused decode_mb_skip(H264Context *h) +{ + const int mb_xy = h->mb_xy; + int mb_type = 0; + + memset(h->non_zero_count[mb_xy], 0, 48); + + if (MB_FIELD(h)) + mb_type |= MB_TYPE_INTERLACED; + + if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + // just for fill_caches. pred_direct_motion will set the real mb_type + mb_type |= MB_TYPE_L0L1 | MB_TYPE_DIRECT2 | MB_TYPE_SKIP; + if (h->direct_spatial_mv_pred) { + fill_decode_neighbors(h, mb_type); + fill_decode_caches(h, mb_type); //FIXME check what is needed and what not ... + } + ff_h264_pred_direct_motion(h, &mb_type); + mb_type |= MB_TYPE_SKIP; + } else { + mb_type |= MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_SKIP; + + fill_decode_neighbors(h, mb_type); + pred_pskip_motion(h); + } + + write_back_motion(h, mb_type); + h->cur_pic.mb_type[mb_xy] = mb_type; + h->cur_pic.qscale_table[mb_xy] = h->qscale; + h->slice_table[mb_xy] = h->slice_num; + h->prev_mb_skipped = 1; +} + +#endif /* AVCODEC_H264_MVPRED_H */ diff --git a/ffmpeg/libavcodec/h264_parser.c b/ffmpeg/libavcodec/h264_parser.c new file mode 100644 index 0000000..44b92b7 --- /dev/null +++ b/ffmpeg/libavcodec/h264_parser.c @@ -0,0 +1,398 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... parser + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 parser. + * @author Michael Niedermayer + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +#include "parser.h" +#include "h264data.h" +#include "golomb.h" + + +static int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_size) +{ + int i, j; + uint32_t state; + ParseContext *pc = &h->parse_context; + int next_avc= h->is_avc ? 0 : buf_size; + +// mb_addr= pc->mb_addr - 1; + state= pc->state; + if(state>13) + state= 7; + + if(h->is_avc && !h->nal_length_size) + av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal length size invalid\n"); + + for(i=0; i= next_avc) { + int nalsize = 0; + i = next_avc; + for(j = 0; j < h->nal_length_size; j++) + nalsize = (nalsize << 8) | buf[i++]; + if(nalsize <= 0 || nalsize > buf_size - i){ + av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal size %d remaining %d\n", nalsize, buf_size - i); + return buf_size; + } + next_avc= i + nalsize; + state= 5; + } + + if(state==7){ +#if HAVE_FAST_UNALIGNED + /* we check i7, 1->4, 0->5 + else if(buf[i]) state = 7; + else state>>=1; //2->1, 1->0, 0->0 + }else if(state<=5){ + int v= buf[i] & 0x1F; + if(v==6 || v==7 || v==8 || v==9){ + if(pc->frame_start_found){ + i++; + goto found; + } + }else if(v==1 || v==2 || v==5){ + state+=8; + continue; + } + state= 7; + }else{ + h->parse_history[h->parse_history_count++]= buf[i]; + if(h->parse_history_count>3){ + unsigned int mb, last_mb= h->parse_last_mb; + GetBitContext gb; + + init_get_bits(&gb, h->parse_history, 8*h->parse_history_count); + h->parse_history_count=0; + mb= get_ue_golomb_long(&gb); + last_mb= h->parse_last_mb; + h->parse_last_mb= mb; + if(pc->frame_start_found){ + if(mb <= last_mb) + goto found; + }else + pc->frame_start_found = 1; + state= 7; + } + } + } + pc->state= state; + if(h->is_avc) + return next_avc; + return END_NOT_FOUND; + +found: + pc->state=7; + pc->frame_start_found= 0; + if(h->is_avc) + return next_avc; + return i-(state&5) - 3*(state>7); +} + +/** + * Parse NAL units of found picture and decode some basic information. + * + * @param s parser context. + * @param avctx codec context. + * @param buf buffer with field/frame data. + * @param buf_size size of the buffer. + */ +static inline int parse_nal_units(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + H264Context *h = s->priv_data; + const uint8_t *buf_end = buf + buf_size; + unsigned int pps_id; + unsigned int slice_type; + int state = -1; + const uint8_t *ptr; + int q264 = buf_size >=4 && !memcmp("Q264", buf, 4); + + /* set some sane default values */ + s->pict_type = AV_PICTURE_TYPE_I; + s->key_frame = 0; + + h->avctx= avctx; + h->sei_recovery_frame_cnt = -1; + h->sei_dpb_output_delay = 0; + h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; + + if (!buf_size) + return 0; + + for(;;) { + int src_length, dst_length, consumed, nalsize = 0; + if (h->is_avc) { + int i; + if (h->nal_length_size >= buf_end - buf) break; + nalsize = 0; + for (i = 0; i < h->nal_length_size; i++) + nalsize = (nalsize << 8) | *buf++; + if (nalsize <= 0 || nalsize > buf_end - buf) { + av_log(h->avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize); + break; + } + src_length = nalsize; + } else { + buf = avpriv_mpv_find_start_code(buf, buf_end, &state); + if(buf >= buf_end) + break; + --buf; + src_length = buf_end - buf; + } + switch (state & 0x1f) { + case NAL_SLICE: + case NAL_IDR_SLICE: + // Do not walk the whole buffer just to decode slice header + if (src_length > 20) + src_length = 20; + break; + } + ptr= ff_h264_decode_nal(h, buf, &dst_length, &consumed, src_length); + if (ptr==NULL || dst_length < 0) + break; + + init_get_bits(&h->gb, ptr, 8*dst_length); + switch(h->nal_unit_type) { + case NAL_SPS: + ff_h264_decode_seq_parameter_set(h); + break; + case NAL_PPS: + ff_h264_decode_picture_parameter_set(h, h->gb.size_in_bits); + break; + case NAL_SEI: + ff_h264_decode_sei(h); + break; + case NAL_IDR_SLICE: + s->key_frame = 1; + /* fall through */ + case NAL_SLICE: + get_ue_golomb_long(&h->gb); // skip first_mb_in_slice + slice_type = get_ue_golomb_31(&h->gb); + s->pict_type = golomb_to_pict_type[slice_type % 5]; + if (h->sei_recovery_frame_cnt >= 0) { + /* key frame, since recovery_frame_cnt is set */ + s->key_frame = 1; + } + pps_id= get_ue_golomb(&h->gb); + if(pps_id>=MAX_PPS_COUNT) { + av_log(h->avctx, AV_LOG_ERROR, "pps_id out of range\n"); + return -1; + } + if(!h->pps_buffers[pps_id]) { + av_log(h->avctx, AV_LOG_ERROR, "non-existing PPS referenced\n"); + return -1; + } + h->pps= *h->pps_buffers[pps_id]; + if(!h->sps_buffers[h->pps.sps_id]) { + av_log(h->avctx, AV_LOG_ERROR, "non-existing SPS referenced\n"); + return -1; + } + h->sps = *h->sps_buffers[h->pps.sps_id]; + h->frame_num = get_bits(&h->gb, h->sps.log2_max_frame_num); + + avctx->profile = ff_h264_get_profile(&h->sps); + avctx->level = h->sps.level_idc; + + if(h->sps.frame_mbs_only_flag){ + h->picture_structure= PICT_FRAME; + }else{ + if(get_bits1(&h->gb)) { //field_pic_flag + h->picture_structure= PICT_TOP_FIELD + get_bits1(&h->gb); //bottom_field_flag + } else { + h->picture_structure= PICT_FRAME; + } + } + + if(h->sps.pic_struct_present_flag) { + switch (h->sei_pic_struct) { + case SEI_PIC_STRUCT_TOP_FIELD: + case SEI_PIC_STRUCT_BOTTOM_FIELD: + s->repeat_pict = 0; + break; + case SEI_PIC_STRUCT_FRAME: + case SEI_PIC_STRUCT_TOP_BOTTOM: + case SEI_PIC_STRUCT_BOTTOM_TOP: + s->repeat_pict = 1; + break; + case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + s->repeat_pict = 2; + break; + case SEI_PIC_STRUCT_FRAME_DOUBLING: + s->repeat_pict = 3; + break; + case SEI_PIC_STRUCT_FRAME_TRIPLING: + s->repeat_pict = 5; + break; + default: + s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0; + break; + } + } else { + s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0; + } + + return 0; /* no need to evaluate the rest */ + } + buf += h->is_avc ? nalsize : consumed; + } + if (q264) + return 0; + /* didn't find a picture! */ + av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit with size %d\n", buf_size); + return -1; +} + +static int h264_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + H264Context *h = s->priv_data; + ParseContext *pc = &h->parse_context; + int next; + + if (!h->got_first) { + h->got_first = 1; + if (avctx->extradata_size) { + h->avctx = avctx; + // must be done like in decoder, otherwise opening the parser, + // letting it create extradata and then closing and opening again + // will cause has_b_frames to be always set. + // Note that estimate_timings_from_pts does exactly this. + if (!avctx->has_b_frames) + h->low_delay = 1; + ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size); + } + } + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= ff_h264_find_frame_end(h, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + if(next<0 && next != END_NOT_FOUND){ + av_assert1(pc->last_index + next >= 0 ); + ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state + } + } + + parse_nal_units(s, avctx, buf, buf_size); + + if (h->sei_cpb_removal_delay >= 0) { + s->dts_sync_point = h->sei_buffering_period_present; + s->dts_ref_dts_delta = h->sei_cpb_removal_delay; + s->pts_dts_delta = h->sei_dpb_output_delay; + } else { + s->dts_sync_point = INT_MIN; + s->dts_ref_dts_delta = INT_MIN; + s->pts_dts_delta = INT_MIN; + } + + if (s->flags & PARSER_FLAG_ONCE) { + s->flags &= PARSER_FLAG_COMPLETE_FRAMES; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +static int h264_split(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + int i; + uint32_t state = -1; + int has_sps= 0; + + for(i=0; i<=buf_size; i++){ + if((state&0xFFFFFF1F) == 0x107) + has_sps=1; +/* if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){ + }*/ + if((state&0xFFFFFF00) == 0x100 && (state&0xFFFFFF1F) != 0x107 && (state&0xFFFFFF1F) != 0x108 && (state&0xFFFFFF1F) != 0x109){ + if(has_sps){ + while(i>4 && buf[i-5]==0) i--; + return i-4; + } + } + if (ipriv_data; + ParseContext *pc = &h->parse_context; + + av_free(pc->buffer); + ff_h264_free_context(h); +} + +static int init(AVCodecParserContext *s) +{ + H264Context *h = s->priv_data; + h->thread_context[0] = h; + h->slice_context_count = 1; + return 0; +} + +AVCodecParser ff_h264_parser = { + .codec_ids = { AV_CODEC_ID_H264 }, + .priv_data_size = sizeof(H264Context), + .parser_init = init, + .parser_parse = h264_parse, + .parser_close = close, + .split = h264_split, +}; diff --git a/ffmpeg/libavcodec/h264_ps.c b/ffmpeg/libavcodec/h264_ps.c new file mode 100644 index 0000000..8638ce2 --- /dev/null +++ b/ffmpeg/libavcodec/h264_ps.c @@ -0,0 +1,688 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... parameter set decoding + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 parameter set decoding. + * @author Michael Niedermayer + */ + +#include "libavutil/imgutils.h" +#include "internal.h" +#include "avcodec.h" +#include "h264.h" +#include "h264data.h" //FIXME FIXME FIXME (just for zigzag_scan) +#include "golomb.h" + + +//#undef NDEBUG +#include + +#define MAX_LOG2_MAX_FRAME_NUM (12 + 4) +#define MIN_LOG2_MAX_FRAME_NUM 4 + +static const AVRational pixel_aspect[17]={ + {0, 1}, + {1, 1}, + {12, 11}, + {10, 11}, + {16, 11}, + {40, 33}, + {24, 11}, + {20, 11}, + {32, 11}, + {80, 33}, + {18, 11}, + {15, 11}, + {64, 33}, + {160,99}, + {4, 3}, + {3, 2}, + {2, 1}, +}; + +#define QP(qP,depth) ( (qP)+6*((depth)-8) ) + +#define CHROMA_QP_TABLE_END(d) \ + QP(0,d), QP(1,d), QP(2,d), QP(3,d), QP(4,d), QP(5,d),\ + QP(6,d), QP(7,d), QP(8,d), QP(9,d), QP(10,d), QP(11,d),\ + QP(12,d), QP(13,d), QP(14,d), QP(15,d), QP(16,d), QP(17,d),\ + QP(18,d), QP(19,d), QP(20,d), QP(21,d), QP(22,d), QP(23,d),\ + QP(24,d), QP(25,d), QP(26,d), QP(27,d), QP(28,d), QP(29,d),\ + QP(29,d), QP(30,d), QP(31,d), QP(32,d), QP(32,d), QP(33,d),\ + QP(34,d), QP(34,d), QP(35,d), QP(35,d), QP(36,d), QP(36,d),\ + QP(37,d), QP(37,d), QP(37,d), QP(38,d), QP(38,d), QP(38,d),\ + QP(39,d), QP(39,d), QP(39,d), QP(39,d) + +const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM+1] = { + { + CHROMA_QP_TABLE_END(8) + }, + { + 0, 1, 2, 3, 4, 5, + CHROMA_QP_TABLE_END(9) + }, + { + 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + CHROMA_QP_TABLE_END(10) + }, + { + 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12,13,14,15, 16, 17, + CHROMA_QP_TABLE_END(11) + }, + { + 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, + 12,13,14,15, 16, 17, + 18,19,20,21, 22, 23, + CHROMA_QP_TABLE_END(12) + }, + { + 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, + CHROMA_QP_TABLE_END(13) + }, + { + 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,32,33, 34, 35, + CHROMA_QP_TABLE_END(14) + }, +}; + +static const uint8_t default_scaling4[2][16]={ +{ 6,13,20,28, + 13,20,28,32, + 20,28,32,37, + 28,32,37,42 +},{ + 10,14,20,24, + 14,20,24,27, + 20,24,27,30, + 24,27,30,34 +}}; + +static const uint8_t default_scaling8[2][64]={ +{ 6,10,13,16,18,23,25,27, + 10,11,16,18,23,25,27,29, + 13,16,18,23,25,27,29,31, + 16,18,23,25,27,29,31,33, + 18,23,25,27,29,31,33,36, + 23,25,27,29,31,33,36,38, + 25,27,29,31,33,36,38,40, + 27,29,31,33,36,38,40,42 +},{ + 9,13,15,17,19,21,22,24, + 13,13,17,19,21,22,24,25, + 15,17,19,21,22,24,25,27, + 17,19,21,22,24,25,27,28, + 19,21,22,24,25,27,28,30, + 21,22,24,25,27,28,30,32, + 22,24,25,27,28,30,32,33, + 24,25,27,28,30,32,33,35 +}}; + +static inline int decode_hrd_parameters(H264Context *h, SPS *sps){ + int cpb_count, i; + cpb_count = get_ue_golomb_31(&h->gb) + 1; + + if(cpb_count > 32U){ + av_log(h->avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count); + return -1; + } + + get_bits(&h->gb, 4); /* bit_rate_scale */ + get_bits(&h->gb, 4); /* cpb_size_scale */ + for(i=0; igb); /* bit_rate_value_minus1 */ + get_ue_golomb_long(&h->gb); /* cpb_size_value_minus1 */ + get_bits1(&h->gb); /* cbr_flag */ + } + sps->initial_cpb_removal_delay_length = get_bits(&h->gb, 5) + 1; + sps->cpb_removal_delay_length = get_bits(&h->gb, 5) + 1; + sps->dpb_output_delay_length = get_bits(&h->gb, 5) + 1; + sps->time_offset_length = get_bits(&h->gb, 5); + sps->cpb_cnt = cpb_count; + return 0; +} + +static inline int decode_vui_parameters(H264Context *h, SPS *sps){ + int aspect_ratio_info_present_flag; + unsigned int aspect_ratio_idc; + + aspect_ratio_info_present_flag= get_bits1(&h->gb); + + if( aspect_ratio_info_present_flag ) { + aspect_ratio_idc= get_bits(&h->gb, 8); + if( aspect_ratio_idc == EXTENDED_SAR ) { + sps->sar.num= get_bits(&h->gb, 16); + sps->sar.den= get_bits(&h->gb, 16); + }else if(aspect_ratio_idc < FF_ARRAY_ELEMS(pixel_aspect)){ + sps->sar= pixel_aspect[aspect_ratio_idc]; + }else{ + av_log(h->avctx, AV_LOG_ERROR, "illegal aspect ratio\n"); + return -1; + } + }else{ + sps->sar.num= + sps->sar.den= 0; + } +// s->avctx->aspect_ratio= sar_width*s->width / (float)(s->height*sar_height); + + if(get_bits1(&h->gb)){ /* overscan_info_present_flag */ + get_bits1(&h->gb); /* overscan_appropriate_flag */ + } + + sps->video_signal_type_present_flag = get_bits1(&h->gb); + if(sps->video_signal_type_present_flag){ + get_bits(&h->gb, 3); /* video_format */ + sps->full_range = get_bits1(&h->gb); /* video_full_range_flag */ + + sps->colour_description_present_flag = get_bits1(&h->gb); + if(sps->colour_description_present_flag){ + sps->color_primaries = get_bits(&h->gb, 8); /* colour_primaries */ + sps->color_trc = get_bits(&h->gb, 8); /* transfer_characteristics */ + sps->colorspace = get_bits(&h->gb, 8); /* matrix_coefficients */ + if (sps->color_primaries >= AVCOL_PRI_NB) + sps->color_primaries = AVCOL_PRI_UNSPECIFIED; + if (sps->color_trc >= AVCOL_TRC_NB) + sps->color_trc = AVCOL_TRC_UNSPECIFIED; + if (sps->colorspace >= AVCOL_SPC_NB) + sps->colorspace = AVCOL_SPC_UNSPECIFIED; + } + } + + if(get_bits1(&h->gb)){ /* chroma_location_info_present_flag */ + h->avctx->chroma_sample_location = get_ue_golomb(&h->gb)+1; /* chroma_sample_location_type_top_field */ + get_ue_golomb(&h->gb); /* chroma_sample_location_type_bottom_field */ + } + + sps->timing_info_present_flag = get_bits1(&h->gb); + if(sps->timing_info_present_flag){ + sps->num_units_in_tick = get_bits_long(&h->gb, 32); + sps->time_scale = get_bits_long(&h->gb, 32); + if(!sps->num_units_in_tick || !sps->time_scale){ + av_log(h->avctx, AV_LOG_ERROR, "time_scale/num_units_in_tick invalid or unsupported (%d/%d)\n", sps->time_scale, sps->num_units_in_tick); + return -1; + } + sps->fixed_frame_rate_flag = get_bits1(&h->gb); + } + + sps->nal_hrd_parameters_present_flag = get_bits1(&h->gb); + if(sps->nal_hrd_parameters_present_flag) + if(decode_hrd_parameters(h, sps) < 0) + return -1; + sps->vcl_hrd_parameters_present_flag = get_bits1(&h->gb); + if(sps->vcl_hrd_parameters_present_flag) + if(decode_hrd_parameters(h, sps) < 0) + return -1; + if(sps->nal_hrd_parameters_present_flag || sps->vcl_hrd_parameters_present_flag) + get_bits1(&h->gb); /* low_delay_hrd_flag */ + sps->pic_struct_present_flag = get_bits1(&h->gb); + if(!get_bits_left(&h->gb)) + return 0; + sps->bitstream_restriction_flag = get_bits1(&h->gb); + if(sps->bitstream_restriction_flag){ + get_bits1(&h->gb); /* motion_vectors_over_pic_boundaries_flag */ + get_ue_golomb(&h->gb); /* max_bytes_per_pic_denom */ + get_ue_golomb(&h->gb); /* max_bits_per_mb_denom */ + get_ue_golomb(&h->gb); /* log2_max_mv_length_horizontal */ + get_ue_golomb(&h->gb); /* log2_max_mv_length_vertical */ + sps->num_reorder_frames= get_ue_golomb(&h->gb); + get_ue_golomb(&h->gb); /*max_dec_frame_buffering*/ + + if (get_bits_left(&h->gb) < 0) { + sps->num_reorder_frames=0; + sps->bitstream_restriction_flag= 0; + } + + if(sps->num_reorder_frames > 16U /*max_dec_frame_buffering || max_dec_frame_buffering > 16*/){ + av_log(h->avctx, AV_LOG_ERROR, "illegal num_reorder_frames %d\n", sps->num_reorder_frames); + return -1; + } + } + + if (get_bits_left(&h->gb) < 0) { + av_log(h->avctx, AV_LOG_ERROR, "Overread VUI by %d bits\n", -get_bits_left(&h->gb)); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static void decode_scaling_list(H264Context *h, uint8_t *factors, int size, + const uint8_t *jvt_list, const uint8_t *fallback_list){ + int i, last = 8, next = 8; + const uint8_t *scan = size == 16 ? zigzag_scan : ff_zigzag_direct; + if(!get_bits1(&h->gb)) /* matrix not written, we use the predicted one */ + memcpy(factors, fallback_list, size*sizeof(uint8_t)); + else + for(i=0;igb)) & 0xff; + if(!i && !next){ /* matrix not written, we use the preset one */ + memcpy(factors, jvt_list, size*sizeof(uint8_t)); + break; + } + last = factors[scan[i]] = next ? next : last; + } +} + +static void decode_scaling_matrices(H264Context *h, SPS *sps, PPS *pps, int is_sps, + uint8_t (*scaling_matrix4)[16], uint8_t (*scaling_matrix8)[64]){ + int fallback_sps = !is_sps && sps->scaling_matrix_present; + const uint8_t *fallback[4] = { + fallback_sps ? sps->scaling_matrix4[0] : default_scaling4[0], + fallback_sps ? sps->scaling_matrix4[3] : default_scaling4[1], + fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0], + fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1] + }; + if(get_bits1(&h->gb)){ + sps->scaling_matrix_present |= is_sps; + decode_scaling_list(h,scaling_matrix4[0],16,default_scaling4[0],fallback[0]); // Intra, Y + decode_scaling_list(h,scaling_matrix4[1],16,default_scaling4[0],scaling_matrix4[0]); // Intra, Cr + decode_scaling_list(h,scaling_matrix4[2],16,default_scaling4[0],scaling_matrix4[1]); // Intra, Cb + decode_scaling_list(h,scaling_matrix4[3],16,default_scaling4[1],fallback[1]); // Inter, Y + decode_scaling_list(h,scaling_matrix4[4],16,default_scaling4[1],scaling_matrix4[3]); // Inter, Cr + decode_scaling_list(h,scaling_matrix4[5],16,default_scaling4[1],scaling_matrix4[4]); // Inter, Cb + if(is_sps || pps->transform_8x8_mode){ + decode_scaling_list(h,scaling_matrix8[0],64,default_scaling8[0],fallback[2]); // Intra, Y + decode_scaling_list(h,scaling_matrix8[3],64,default_scaling8[1],fallback[3]); // Inter, Y + if(sps->chroma_format_idc == 3){ + decode_scaling_list(h,scaling_matrix8[1],64,default_scaling8[0],scaling_matrix8[0]); // Intra, Cr + decode_scaling_list(h,scaling_matrix8[4],64,default_scaling8[1],scaling_matrix8[3]); // Inter, Cr + decode_scaling_list(h,scaling_matrix8[2],64,default_scaling8[0],scaling_matrix8[1]); // Intra, Cb + decode_scaling_list(h,scaling_matrix8[5],64,default_scaling8[1],scaling_matrix8[4]); // Inter, Cb + } + } + } +} + +int ff_h264_decode_seq_parameter_set(H264Context *h){ + int profile_idc, level_idc, constraint_set_flags = 0; + unsigned int sps_id; + int i, log2_max_frame_num_minus4; + SPS *sps; + + profile_idc= get_bits(&h->gb, 8); + constraint_set_flags |= get_bits1(&h->gb) << 0; //constraint_set0_flag + constraint_set_flags |= get_bits1(&h->gb) << 1; //constraint_set1_flag + constraint_set_flags |= get_bits1(&h->gb) << 2; //constraint_set2_flag + constraint_set_flags |= get_bits1(&h->gb) << 3; //constraint_set3_flag + constraint_set_flags |= get_bits1(&h->gb) << 4; //constraint_set4_flag + constraint_set_flags |= get_bits1(&h->gb) << 5; //constraint_set5_flag + get_bits(&h->gb, 2); // reserved + level_idc= get_bits(&h->gb, 8); + sps_id= get_ue_golomb_31(&h->gb); + + if(sps_id >= MAX_SPS_COUNT) { + av_log(h->avctx, AV_LOG_ERROR, "sps_id (%d) out of range\n", sps_id); + return -1; + } + sps= av_mallocz(sizeof(SPS)); + if(sps == NULL) + return -1; + + sps->time_offset_length = 24; + sps->profile_idc= profile_idc; + sps->constraint_set_flags = constraint_set_flags; + sps->level_idc= level_idc; + sps->full_range = -1; + + memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4)); + memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8)); + sps->scaling_matrix_present = 0; + sps->colorspace = 2; //AVCOL_SPC_UNSPECIFIED + + if (sps->profile_idc == 100 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 244 || + sps->profile_idc == 44 || sps->profile_idc == 83 || + sps->profile_idc == 86 || sps->profile_idc == 118 || + sps->profile_idc == 128 || sps->profile_idc == 144) { + sps->chroma_format_idc= get_ue_golomb_31(&h->gb); + if (sps->chroma_format_idc > 3U) { + av_log(h->avctx, AV_LOG_ERROR, "chroma_format_idc %d is illegal\n", sps->chroma_format_idc); + goto fail; + } else if(sps->chroma_format_idc == 3) { + sps->residual_color_transform_flag = get_bits1(&h->gb); + if(sps->residual_color_transform_flag) { + av_log(h->avctx, AV_LOG_ERROR, "separate color planes are not supported\n"); + goto fail; + } + } + sps->bit_depth_luma = get_ue_golomb(&h->gb) + 8; + sps->bit_depth_chroma = get_ue_golomb(&h->gb) + 8; + if (sps->bit_depth_luma > 14U || sps->bit_depth_chroma > 14U || sps->bit_depth_luma != sps->bit_depth_chroma) { + av_log(h->avctx, AV_LOG_ERROR, "illegal bit depth value (%d, %d)\n", + sps->bit_depth_luma, sps->bit_depth_chroma); + goto fail; + } + sps->transform_bypass = get_bits1(&h->gb); + decode_scaling_matrices(h, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8); + }else{ + sps->chroma_format_idc= 1; + sps->bit_depth_luma = 8; + sps->bit_depth_chroma = 8; + } + + log2_max_frame_num_minus4 = get_ue_golomb(&h->gb); + if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 || + log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) { + av_log(h->avctx, AV_LOG_ERROR, + "log2_max_frame_num_minus4 out of range (0-12): %d\n", + log2_max_frame_num_minus4); + goto fail; + } + sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4; + + sps->poc_type= get_ue_golomb_31(&h->gb); + + if(sps->poc_type == 0){ //FIXME #define + unsigned t = get_ue_golomb(&h->gb); + if(t>12){ + av_log(h->avctx, AV_LOG_ERROR, "log2_max_poc_lsb (%d) is out of range\n", t); + goto fail; + } + sps->log2_max_poc_lsb= t + 4; + } else if(sps->poc_type == 1){//FIXME #define + sps->delta_pic_order_always_zero_flag= get_bits1(&h->gb); + sps->offset_for_non_ref_pic= get_se_golomb(&h->gb); + sps->offset_for_top_to_bottom_field= get_se_golomb(&h->gb); + sps->poc_cycle_length = get_ue_golomb(&h->gb); + + if((unsigned)sps->poc_cycle_length >= FF_ARRAY_ELEMS(sps->offset_for_ref_frame)){ + av_log(h->avctx, AV_LOG_ERROR, "poc_cycle_length overflow %u\n", sps->poc_cycle_length); + goto fail; + } + + for(i=0; ipoc_cycle_length; i++) + sps->offset_for_ref_frame[i]= get_se_golomb(&h->gb); + }else if(sps->poc_type != 2){ + av_log(h->avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type); + goto fail; + } + + sps->ref_frame_count= get_ue_golomb_31(&h->gb); + if (h->avctx->codec_tag == MKTAG('S', 'M', 'V', '2')) + sps->ref_frame_count= FFMAX(2, sps->ref_frame_count); + if(sps->ref_frame_count > MAX_PICTURE_COUNT-2 || sps->ref_frame_count > 16U){ + av_log(h->avctx, AV_LOG_ERROR, "too many reference frames\n"); + goto fail; + } + sps->gaps_in_frame_num_allowed_flag= get_bits1(&h->gb); + sps->mb_width = get_ue_golomb(&h->gb) + 1; + sps->mb_height= get_ue_golomb(&h->gb) + 1; + if((unsigned)sps->mb_width >= INT_MAX/16 || (unsigned)sps->mb_height >= INT_MAX/16 || + av_image_check_size(16*sps->mb_width, 16*sps->mb_height, 0, h->avctx)){ + av_log(h->avctx, AV_LOG_ERROR, "mb_width/height overflow\n"); + goto fail; + } + + sps->frame_mbs_only_flag= get_bits1(&h->gb); + if(!sps->frame_mbs_only_flag) + sps->mb_aff= get_bits1(&h->gb); + else + sps->mb_aff= 0; + + sps->direct_8x8_inference_flag= get_bits1(&h->gb); + +#ifndef ALLOW_INTERLACE + if(sps->mb_aff) + av_log(h->avctx, AV_LOG_ERROR, "MBAFF support not included; enable it at compile-time.\n"); +#endif + sps->crop= get_bits1(&h->gb); + if(sps->crop){ + int crop_vertical_limit = sps->chroma_format_idc & 2 ? 16 : 8; + int crop_horizontal_limit = sps->chroma_format_idc == 3 ? 16 : 8; + sps->crop_left = get_ue_golomb(&h->gb); + sps->crop_right = get_ue_golomb(&h->gb); + sps->crop_top = get_ue_golomb(&h->gb); + sps->crop_bottom= get_ue_golomb(&h->gb); + if (h->avctx->flags2 & CODEC_FLAG2_IGNORE_CROP) { + av_log(h->avctx, AV_LOG_DEBUG, + "discarding sps cropping, " + "original values are l:%u r:%u t:%u b:%u\n", + sps->crop_left, + sps->crop_right, + sps->crop_top, + sps->crop_bottom); + + sps->crop_left = + sps->crop_right = + sps->crop_top = + sps->crop_bottom = 0; + } + if(sps->crop_left || sps->crop_top){ + av_log(h->avctx, AV_LOG_ERROR, "insane cropping not completely supported, this could look slightly wrong ... (left: %d, top: %d)\n", sps->crop_left, sps->crop_top); + } + if(sps->crop_right >= crop_horizontal_limit || sps->crop_bottom >= crop_vertical_limit){ + av_log(h->avctx, AV_LOG_ERROR, "brainfart cropping not supported, cropping disabled (right: %d, bottom: %d)\n", sps->crop_right, sps->crop_bottom); + /* It is very unlikely that partial cropping will make anybody happy. + * Not cropping at all fixes for example playback of Sisvel 3D streams + * in applications supporting Sisvel 3D. */ + sps->crop_left = + sps->crop_right = + sps->crop_top = + sps->crop_bottom= 0; + } + }else{ + sps->crop_left = + sps->crop_right = + sps->crop_top = + sps->crop_bottom= 0; + } + + sps->vui_parameters_present_flag= get_bits1(&h->gb); + if( sps->vui_parameters_present_flag ) + if (decode_vui_parameters(h, sps) < 0) + goto fail; + + if(!sps->sar.den) + sps->sar.den= 1; + + if(h->avctx->debug&FF_DEBUG_PICT_INFO){ + static const char csp[4][5] = { "Gray", "420", "422", "444" }; + av_log(h->avctx, AV_LOG_DEBUG, "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%d/%d/%d/%d %s %s %d/%d b%d reo:%d\n", + sps_id, sps->profile_idc, sps->level_idc, + sps->poc_type, + sps->ref_frame_count, + sps->mb_width, sps->mb_height, + sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"), + sps->direct_8x8_inference_flag ? "8B8" : "", + sps->crop_left, sps->crop_right, + sps->crop_top, sps->crop_bottom, + sps->vui_parameters_present_flag ? "VUI" : "", + csp[sps->chroma_format_idc], + sps->timing_info_present_flag ? sps->num_units_in_tick : 0, + sps->timing_info_present_flag ? sps->time_scale : 0, + sps->bit_depth_luma, + h->sps.bitstream_restriction_flag ? sps->num_reorder_frames : -1 + ); + } + sps->new = 1; + + av_free(h->sps_buffers[sps_id]); + h->sps_buffers[sps_id] = sps; + h->sps = *sps; + h->current_sps_id = sps_id; + + return 0; +fail: + av_free(sps); + return -1; +} + +static void +build_qp_table(PPS *pps, int t, int index, const int depth) +{ + int i; + const int max_qp = 51 + 6*(depth-8); + for(i = 0; i < max_qp+1; i++) + pps->chroma_qp_table[t][i] = ff_h264_chroma_qp[depth-8][av_clip(i + index, 0, max_qp)]; +} + +static int more_rbsp_data_in_pps(H264Context *h, PPS *pps) +{ + const SPS *sps = h->sps_buffers[pps->sps_id]; + int profile_idc = sps->profile_idc; + + if ((profile_idc == 66 || profile_idc == 77 || + profile_idc == 88) && (sps->constraint_set_flags & 7)) { + av_log(h->avctx, AV_LOG_VERBOSE, + "Current profile doesn't provide more RBSP data in PPS, skipping\n"); + return 0; + } + + return 1; +} + +int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length){ + unsigned int pps_id= get_ue_golomb(&h->gb); + PPS *pps; + const int qp_bd_offset = 6*(h->sps.bit_depth_luma-8); + int bits_left; + + if(pps_id >= MAX_PPS_COUNT) { + av_log(h->avctx, AV_LOG_ERROR, "pps_id (%d) out of range\n", pps_id); + return -1; + } else if (h->sps.bit_depth_luma > 14) { + av_log(h->avctx, AV_LOG_ERROR, "Invalid luma bit depth=%d\n", h->sps.bit_depth_luma); + return AVERROR_INVALIDDATA; + } else if (h->sps.bit_depth_luma == 11 || h->sps.bit_depth_luma == 13) { + av_log(h->avctx, AV_LOG_ERROR, "Unimplemented luma bit depth=%d\n", h->sps.bit_depth_luma); + return AVERROR_PATCHWELCOME; + } + + pps= av_mallocz(sizeof(PPS)); + if(pps == NULL) + return -1; + pps->sps_id= get_ue_golomb_31(&h->gb); + if((unsigned)pps->sps_id>=MAX_SPS_COUNT || h->sps_buffers[pps->sps_id] == NULL){ + av_log(h->avctx, AV_LOG_ERROR, "sps_id out of range\n"); + goto fail; + } + + pps->cabac= get_bits1(&h->gb); + pps->pic_order_present= get_bits1(&h->gb); + pps->slice_group_count= get_ue_golomb(&h->gb) + 1; + if(pps->slice_group_count > 1 ){ + pps->mb_slice_group_map_type= get_ue_golomb(&h->gb); + av_log(h->avctx, AV_LOG_ERROR, "FMO not supported\n"); + switch(pps->mb_slice_group_map_type){ + case 0: +#if 0 +| for( i = 0; i <= num_slice_groups_minus1; i++ ) | | | +| run_length[ i ] |1 |ue(v) | +#endif + break; + case 2: +#if 0 +| for( i = 0; i < num_slice_groups_minus1; i++ ) | | | +|{ | | | +| top_left_mb[ i ] |1 |ue(v) | +| bottom_right_mb[ i ] |1 |ue(v) | +| } | | | +#endif + break; + case 3: + case 4: + case 5: +#if 0 +| slice_group_change_direction_flag |1 |u(1) | +| slice_group_change_rate_minus1 |1 |ue(v) | +#endif + break; + case 6: +#if 0 +| slice_group_id_cnt_minus1 |1 |ue(v) | +| for( i = 0; i <= slice_group_id_cnt_minus1; i++ | | | +|) | | | +| slice_group_id[ i ] |1 |u(v) | +#endif + break; + } + } + pps->ref_count[0]= get_ue_golomb(&h->gb) + 1; + pps->ref_count[1]= get_ue_golomb(&h->gb) + 1; + if(pps->ref_count[0]-1 > 32-1 || pps->ref_count[1]-1 > 32-1){ + av_log(h->avctx, AV_LOG_ERROR, "reference overflow (pps)\n"); + goto fail; + } + + pps->weighted_pred= get_bits1(&h->gb); + pps->weighted_bipred_idc= get_bits(&h->gb, 2); + pps->init_qp= get_se_golomb(&h->gb) + 26 + qp_bd_offset; + pps->init_qs= get_se_golomb(&h->gb) + 26 + qp_bd_offset; + pps->chroma_qp_index_offset[0]= get_se_golomb(&h->gb); + pps->deblocking_filter_parameters_present= get_bits1(&h->gb); + pps->constrained_intra_pred= get_bits1(&h->gb); + pps->redundant_pic_cnt_present = get_bits1(&h->gb); + + pps->transform_8x8_mode= 0; + h->dequant_coeff_pps= -1; //contents of sps/pps can change even if id doesn't, so reinit + memcpy(pps->scaling_matrix4, h->sps_buffers[pps->sps_id]->scaling_matrix4, sizeof(pps->scaling_matrix4)); + memcpy(pps->scaling_matrix8, h->sps_buffers[pps->sps_id]->scaling_matrix8, sizeof(pps->scaling_matrix8)); + + bits_left = bit_length - get_bits_count(&h->gb); + if(bits_left > 0 && more_rbsp_data_in_pps(h, pps)){ + pps->transform_8x8_mode= get_bits1(&h->gb); + decode_scaling_matrices(h, h->sps_buffers[pps->sps_id], pps, 0, pps->scaling_matrix4, pps->scaling_matrix8); + pps->chroma_qp_index_offset[1]= get_se_golomb(&h->gb); //second_chroma_qp_index_offset + } else { + pps->chroma_qp_index_offset[1]= pps->chroma_qp_index_offset[0]; + } + + build_qp_table(pps, 0, pps->chroma_qp_index_offset[0], h->sps.bit_depth_luma); + build_qp_table(pps, 1, pps->chroma_qp_index_offset[1], h->sps.bit_depth_luma); + if(pps->chroma_qp_index_offset[0] != pps->chroma_qp_index_offset[1]) + pps->chroma_qp_diff= 1; + + if(h->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(h->avctx, AV_LOG_DEBUG, "pps:%u sps:%u %s slice_groups:%d ref:%d/%d %s qp:%d/%d/%d/%d %s %s %s %s\n", + pps_id, pps->sps_id, + pps->cabac ? "CABAC" : "CAVLC", + pps->slice_group_count, + pps->ref_count[0], pps->ref_count[1], + pps->weighted_pred ? "weighted" : "", + pps->init_qp, pps->init_qs, pps->chroma_qp_index_offset[0], pps->chroma_qp_index_offset[1], + pps->deblocking_filter_parameters_present ? "LPAR" : "", + pps->constrained_intra_pred ? "CONSTR" : "", + pps->redundant_pic_cnt_present ? "REDU" : "", + pps->transform_8x8_mode ? "8x8DCT" : "" + ); + } + + av_free(h->pps_buffers[pps_id]); + h->pps_buffers[pps_id]= pps; + return 0; +fail: + av_free(pps); + return -1; +} diff --git a/ffmpeg/libavcodec/h264_refs.c b/ffmpeg/libavcodec/h264_refs.c new file mode 100644 index 0000000..c3e7b7c --- /dev/null +++ b/ffmpeg/libavcodec/h264_refs.c @@ -0,0 +1,813 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... reference picture handling + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 reference picture handling. + * @author Michael Niedermayer + */ + +#include "libavutil/avassert.h" +#include "internal.h" +#include "avcodec.h" +#include "h264.h" +#include "golomb.h" + +//#undef NDEBUG +#include + +#define COPY_PICTURE(dst, src) \ +do {\ + *(dst) = *(src);\ + (dst)->f.extended_data = (dst)->f.data;\ + (dst)->tf.f = &(dst)->f;\ +} while (0) + + +static void pic_as_field(Picture *pic, const int parity){ + int i; + for (i = 0; i < 4; ++i) { + if (parity == PICT_BOTTOM_FIELD) + pic->f.data[i] += pic->f.linesize[i]; + pic->reference = parity; + pic->f.linesize[i] *= 2; + } + pic->poc= pic->field_poc[parity == PICT_BOTTOM_FIELD]; +} + +static int split_field_copy(Picture *dest, Picture *src, int parity, int id_add) +{ + int match = !!(src->reference & parity); + + if (match) { + COPY_PICTURE(dest, src); + if (parity != PICT_FRAME) { + pic_as_field(dest, parity); + dest->pic_id *= 2; + dest->pic_id += id_add; + } + } + + return match; +} + +static int build_def_list(Picture *def, Picture **in, int len, int is_long, int sel) +{ + int i[2] = { 0 }; + int index = 0; + + while (i[0] < len || i[1] < len) { + while (i[0] < len && !(in[i[0]] && (in[i[0]]->reference & sel))) + i[0]++; + while (i[1] < len && !(in[i[1]] && (in[i[1]]->reference & (sel ^ 3)))) + i[1]++; + if (i[0] < len) { + in[i[0]]->pic_id = is_long ? i[0] : in[i[0]]->frame_num; + split_field_copy(&def[index++], in[i[0]++], sel, 1); + } + if (i[1] < len) { + in[i[1]]->pic_id = is_long ? i[1] : in[i[1]]->frame_num; + split_field_copy(&def[index++], in[i[1]++], sel ^ 3, 0); + } + } + + return index; +} + +static int add_sorted(Picture **sorted, Picture **src, int len, int limit, int dir) +{ + int i, best_poc; + int out_i = 0; + + for (;;) { + best_poc = dir ? INT_MIN : INT_MAX; + + for (i = 0; i < len; i++) { + const int poc = src[i]->poc; + if (((poc > limit) ^ dir) && ((poc < best_poc) ^ dir)) { + best_poc = poc; + sorted[out_i] = src[i]; + } + } + if (best_poc == (dir ? INT_MIN : INT_MAX)) + break; + limit = sorted[out_i++]->poc - dir; + } + return out_i; +} + +int ff_h264_fill_default_ref_list(H264Context *h) +{ + int i, len; + + if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + Picture *sorted[32]; + int cur_poc, list; + int lens[2]; + + if (FIELD_PICTURE(h)) + cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure == PICT_BOTTOM_FIELD]; + else + cur_poc = h->cur_pic_ptr->poc; + + for (list = 0; list < 2; list++) { + len = add_sorted(sorted, h->short_ref, h->short_ref_count, cur_poc, 1 ^ list); + len += add_sorted(sorted + len, h->short_ref, h->short_ref_count, cur_poc, 0 ^ list); + av_assert0(len <= 32); + len = build_def_list(h->default_ref_list[list], sorted, len, 0, h->picture_structure); + len += build_def_list(h->default_ref_list[list] + len, h->long_ref, 16, 1, h->picture_structure); + av_assert0(len <= 32); + + if (len < h->ref_count[list]) + memset(&h->default_ref_list[list][len], 0, sizeof(Picture) * (h->ref_count[list] - len)); + lens[list] = len; + } + + if (lens[0] == lens[1] && lens[1] > 1) { + for (i = 0; h->default_ref_list[0][i].f.data[0] == h->default_ref_list[1][i].f.data[0] && i < lens[0]; i++); + if (i == lens[0]) { + Picture tmp; + COPY_PICTURE(&tmp, &h->default_ref_list[1][0]); + COPY_PICTURE(&h->default_ref_list[1][0], &h->default_ref_list[1][1]); + COPY_PICTURE(&h->default_ref_list[1][1], &tmp); + } + } + } else { + len = build_def_list(h->default_ref_list[0], h->short_ref, h->short_ref_count, 0, h->picture_structure); + len += build_def_list(h->default_ref_list[0] + len, h-> long_ref, 16, 1, h->picture_structure); + av_assert0(len <= 32); + if (len < h->ref_count[0]) + memset(&h->default_ref_list[0][len], 0, sizeof(Picture) * (h->ref_count[0] - len)); + } +#ifdef TRACE + for (i = 0; i < h->ref_count[0]; i++) { + tprintf(h->avctx, "List0: %s fn:%d 0x%p\n", + (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), + h->default_ref_list[0][i].pic_id, + h->default_ref_list[0][i].f.data[0]); + } + if (h->slice_type_nos == AV_PICTURE_TYPE_B) { + for (i = 0; i < h->ref_count[1]; i++) { + tprintf(h->avctx, "List1: %s fn:%d 0x%p\n", + (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), + h->default_ref_list[1][i].pic_id, + h->default_ref_list[1][i].f.data[0]); + } + } +#endif + return 0; +} + +static void print_short_term(H264Context *h); +static void print_long_term(H264Context *h); + +/** + * Extract structure information about the picture described by pic_num in + * the current decoding context (frame or field). Note that pic_num is + * picture number without wrapping (so, 0<=pic_numpicture_structure; + if (FIELD_PICTURE(h)) { + if (!(pic_num & 1)) + /* opposite field */ + *structure ^= PICT_FRAME; + pic_num >>= 1; + } + + return pic_num; +} + +int ff_h264_decode_ref_pic_list_reordering(H264Context *h) +{ + int list, index, pic_structure, i; + + print_short_term(h); + print_long_term(h); + + for (list = 0; list < h->list_count; list++) { + for (i = 0; i < h->ref_count[list]; i++) + COPY_PICTURE(&h->ref_list[list][i], &h->default_ref_list[list][i]); + + if (get_bits1(&h->gb)) { + int pred = h->curr_pic_num; + + for (index = 0; ; index++) { + unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(&h->gb); + unsigned int pic_id; + int i; + Picture *ref = NULL; + + if (reordering_of_pic_nums_idc == 3) + break; + + if (index >= h->ref_count[list]) { + av_log(h->avctx, AV_LOG_ERROR, "reference count overflow\n"); + return -1; + } + + if (reordering_of_pic_nums_idc < 3) { + if (reordering_of_pic_nums_idc < 2) { + const unsigned int abs_diff_pic_num = get_ue_golomb(&h->gb) + 1; + int frame_num; + + if (abs_diff_pic_num > h->max_pic_num) { + av_log(h->avctx, AV_LOG_ERROR, "abs_diff_pic_num overflow\n"); + return -1; + } + + if (reordering_of_pic_nums_idc == 0) + pred -= abs_diff_pic_num; + else + pred += abs_diff_pic_num; + pred &= h->max_pic_num - 1; + + frame_num = pic_num_extract(h, pred, &pic_structure); + + for (i = h->short_ref_count - 1; i >= 0; i--) { + ref = h->short_ref[i]; + assert(ref->reference); + assert(!ref->long_ref); + if (ref->frame_num == frame_num && + (ref->reference & pic_structure)) + break; + } + if (i >= 0) + ref->pic_id = pred; + } else { + int long_idx; + pic_id = get_ue_golomb(&h->gb); //long_term_pic_idx + + long_idx = pic_num_extract(h, pic_id, &pic_structure); + + if (long_idx > 31) { + av_log(h->avctx, AV_LOG_ERROR, "long_term_pic_idx overflow\n"); + return -1; + } + ref = h->long_ref[long_idx]; + assert(!(ref && !ref->reference)); + if (ref && (ref->reference & pic_structure)) { + ref->pic_id = pic_id; + assert(ref->long_ref); + i = 0; + } else { + i = -1; + } + } + + if (i < 0) { + av_log(h->avctx, AV_LOG_ERROR, "reference picture missing during reorder\n"); + memset(&h->ref_list[list][index], 0, sizeof(Picture)); //FIXME + } else { + for (i = index; i + 1 < h->ref_count[list]; i++) { + if (ref->long_ref == h->ref_list[list][i].long_ref && + ref->pic_id == h->ref_list[list][i].pic_id) + break; + } + for (; i > index; i--) { + COPY_PICTURE(&h->ref_list[list][i], &h->ref_list[list][i - 1]); + } + COPY_PICTURE(&h->ref_list[list][index], ref); + if (FIELD_PICTURE(h)) { + pic_as_field(&h->ref_list[list][index], pic_structure); + } + } + } else { + av_log(h->avctx, AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc\n"); + return -1; + } + } + } + } + for (list = 0; list < h->list_count; list++) { + for (index = 0; index < h->ref_count[list]; index++) { + if ( !h->ref_list[list][index].f.data[0] + || (!FIELD_PICTURE(h) && (h->ref_list[list][index].reference&3) != 3)) { + int i; + av_log(h->avctx, AV_LOG_ERROR, "Missing reference picture, default is %d\n", h->default_ref_list[list][0].poc); + for (i = 0; i < FF_ARRAY_ELEMS(h->last_pocs); i++) + h->last_pocs[i] = INT_MIN; + if (h->default_ref_list[list][0].f.data[0] + && !(!FIELD_PICTURE(h) && (h->default_ref_list[list][0].reference&3) != 3)) + COPY_PICTURE(&h->ref_list[list][index], &h->default_ref_list[list][0]); + else + return -1; + } + } + } + + return 0; +} + +void ff_h264_fill_mbaff_ref_list(H264Context *h) +{ + int list, i, j; + for (list = 0; list < h->list_count; list++) { + for (i = 0; i < h->ref_count[list]; i++) { + Picture *frame = &h->ref_list[list][i]; + Picture *field = &h->ref_list[list][16 + 2 * i]; + COPY_PICTURE(field, frame); + for (j = 0; j < 3; j++) + field[0].f.linesize[j] <<= 1; + field[0].reference = PICT_TOP_FIELD; + field[0].poc = field[0].field_poc[0]; + COPY_PICTURE(field + 1, field); + for (j = 0; j < 3; j++) + field[1].f.data[j] += frame->f.linesize[j]; + field[1].reference = PICT_BOTTOM_FIELD; + field[1].poc = field[1].field_poc[1]; + + h->luma_weight[16 + 2 * i][list][0] = h->luma_weight[16 + 2 * i + 1][list][0] = h->luma_weight[i][list][0]; + h->luma_weight[16 + 2 * i][list][1] = h->luma_weight[16 + 2 * i + 1][list][1] = h->luma_weight[i][list][1]; + for (j = 0; j < 2; j++) { + h->chroma_weight[16 + 2 * i][list][j][0] = h->chroma_weight[16 + 2 * i + 1][list][j][0] = h->chroma_weight[i][list][j][0]; + h->chroma_weight[16 + 2 * i][list][j][1] = h->chroma_weight[16 + 2 * i + 1][list][j][1] = h->chroma_weight[i][list][j][1]; + } + } + } +} + +/** + * Mark a picture as no longer needed for reference. The refmask + * argument allows unreferencing of individual fields or the whole frame. + * If the picture becomes entirely unreferenced, but is being held for + * display purposes, it is marked as such. + * @param refmask mask of fields to unreference; the mask is bitwise + * anded with the reference marking of pic + * @return non-zero if pic becomes entirely unreferenced (except possibly + * for display purposes) zero if one of the fields remains in + * reference + */ +static inline int unreference_pic(H264Context *h, Picture *pic, int refmask) +{ + int i; + if (pic->reference &= refmask) { + return 0; + } else { + for(i = 0; h->delayed_pic[i]; i++) + if(pic == h->delayed_pic[i]){ + pic->reference = DELAYED_PIC_REF; + break; + } + return 1; + } +} + +/** + * Find a Picture in the short term reference list by frame number. + * @param frame_num frame number to search for + * @param idx the index into h->short_ref where returned picture is found + * undefined if no picture found. + * @return pointer to the found picture, or NULL if no pic with the provided + * frame number is found + */ +static Picture *find_short(H264Context *h, int frame_num, int *idx) +{ + int i; + + for (i = 0; i < h->short_ref_count; i++) { + Picture *pic = h->short_ref[i]; + if (h->avctx->debug & FF_DEBUG_MMCO) + av_log(h->avctx, AV_LOG_DEBUG, "%d %d %p\n", i, pic->frame_num, pic); + if (pic->frame_num == frame_num) { + *idx = i; + return pic; + } + } + return NULL; +} + +/** + * Remove a picture from the short term reference list by its index in + * that list. This does no checking on the provided index; it is assumed + * to be valid. Other list entries are shifted down. + * @param i index into h->short_ref of picture to remove. + */ +static void remove_short_at_index(H264Context *h, int i) +{ + assert(i >= 0 && i < h->short_ref_count); + h->short_ref[i] = NULL; + if (--h->short_ref_count) + memmove(&h->short_ref[i], &h->short_ref[i + 1], + (h->short_ref_count - i) * sizeof(Picture*)); +} + +/** + * + * @return the removed picture or NULL if an error occurs + */ +static Picture *remove_short(H264Context *h, int frame_num, int ref_mask) +{ + Picture *pic; + int i; + + if (h->avctx->debug & FF_DEBUG_MMCO) + av_log(h->avctx, AV_LOG_DEBUG, "remove short %d count %d\n", frame_num, h->short_ref_count); + + pic = find_short(h, frame_num, &i); + if (pic) { + if (unreference_pic(h, pic, ref_mask)) + remove_short_at_index(h, i); + } + + return pic; +} + +/** + * Remove a picture from the long term reference list by its index in + * that list. + * @return the removed picture or NULL if an error occurs + */ +static Picture *remove_long(H264Context *h, int i, int ref_mask) +{ + Picture *pic; + + pic = h->long_ref[i]; + if (pic) { + if (unreference_pic(h, pic, ref_mask)) { + assert(h->long_ref[i]->long_ref == 1); + h->long_ref[i]->long_ref = 0; + h->long_ref[i] = NULL; + h->long_ref_count--; + } + } + + return pic; +} + +void ff_h264_remove_all_refs(H264Context *h) +{ + int i; + + for (i = 0; i < 16; i++) { + remove_long(h, i, 0); + } + assert(h->long_ref_count == 0); + + for (i = 0; i < h->short_ref_count; i++) { + unreference_pic(h, h->short_ref[i], 0); + h->short_ref[i] = NULL; + } + h->short_ref_count = 0; + + memset(h->default_ref_list, 0, sizeof(h->default_ref_list)); + memset(h->ref_list, 0, sizeof(h->ref_list)); +} + +/** + * print short term list + */ +static void print_short_term(H264Context *h) +{ + uint32_t i; + if (h->avctx->debug & FF_DEBUG_MMCO) { + av_log(h->avctx, AV_LOG_DEBUG, "short term list:\n"); + for (i = 0; i < h->short_ref_count; i++) { + Picture *pic = h->short_ref[i]; + av_log(h->avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", + i, pic->frame_num, pic->poc, pic->f.data[0]); + } + } +} + +/** + * print long term list + */ +static void print_long_term(H264Context *h) +{ + uint32_t i; + if (h->avctx->debug & FF_DEBUG_MMCO) { + av_log(h->avctx, AV_LOG_DEBUG, "long term list:\n"); + for (i = 0; i < 16; i++) { + Picture *pic = h->long_ref[i]; + if (pic) { + av_log(h->avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", + i, pic->frame_num, pic->poc, pic->f.data[0]); + } + } + } +} + +static int check_opcodes(MMCO *mmco1, MMCO *mmco2, int n_mmcos) +{ + int i; + + for (i = 0; i < n_mmcos; i++) { + if (mmco1[i].opcode != mmco2[i].opcode) { + av_log(NULL, AV_LOG_ERROR, "MMCO opcode [%d, %d] at %d mismatches between slices\n", + mmco1[i].opcode, mmco2[i].opcode, i); + return -1; + } + } + + return 0; +} + +int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice) +{ + MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp; + int mmco_index = 0, i; + + if (h->short_ref_count && + h->long_ref_count + h->short_ref_count >= h->sps.ref_frame_count && + !(FIELD_PICTURE(h) && !h->first_field && h->cur_pic_ptr->reference)) { + mmco[0].opcode = MMCO_SHORT2UNUSED; + mmco[0].short_pic_num = h->short_ref[h->short_ref_count - 1]->frame_num; + mmco_index = 1; + if (FIELD_PICTURE(h)) { + mmco[0].short_pic_num *= 2; + mmco[1].opcode = MMCO_SHORT2UNUSED; + mmco[1].short_pic_num = mmco[0].short_pic_num + 1; + mmco_index = 2; + } + } + + if (first_slice) { + h->mmco_index = mmco_index; + } else if (!first_slice && mmco_index >= 0 && + (mmco_index != h->mmco_index || + (i = check_opcodes(h->mmco, mmco_temp, mmco_index)))) { + av_log(h->avctx, AV_LOG_ERROR, + "Inconsistent MMCO state between slices [%d, %d]\n", + mmco_index, h->mmco_index); + return AVERROR_INVALIDDATA; + } + return 0; +} + +int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) +{ + int i, av_uninit(j); + int current_ref_assigned = 0, err = 0; + Picture *av_uninit(pic); + + if ((h->avctx->debug & FF_DEBUG_MMCO) && mmco_count == 0) + av_log(h->avctx, AV_LOG_DEBUG, "no mmco here\n"); + + for (i = 0; i < mmco_count; i++) { + int av_uninit(structure), av_uninit(frame_num); + if (h->avctx->debug & FF_DEBUG_MMCO) + av_log(h->avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode, + h->mmco[i].short_pic_num, h->mmco[i].long_arg); + + if (mmco[i].opcode == MMCO_SHORT2UNUSED || + mmco[i].opcode == MMCO_SHORT2LONG) { + frame_num = pic_num_extract(h, mmco[i].short_pic_num, &structure); + pic = find_short(h, frame_num, &j); + if (!pic) { + if (mmco[i].opcode != MMCO_SHORT2LONG || + !h->long_ref[mmco[i].long_arg] || + h->long_ref[mmco[i].long_arg]->frame_num != frame_num) { + av_log(h->avctx, AV_LOG_ERROR, "mmco: unref short failure\n"); + err = AVERROR_INVALIDDATA; + } + continue; + } + } + + switch (mmco[i].opcode) { + case MMCO_SHORT2UNUSED: + if (h->avctx->debug & FF_DEBUG_MMCO) + av_log(h->avctx, AV_LOG_DEBUG, "mmco: unref short %d count %d\n", + h->mmco[i].short_pic_num, h->short_ref_count); + remove_short(h, frame_num, structure ^ PICT_FRAME); + break; + case MMCO_SHORT2LONG: + if (h->long_ref[mmco[i].long_arg] != pic) + remove_long(h, mmco[i].long_arg, 0); + + remove_short_at_index(h, j); + h->long_ref[ mmco[i].long_arg ] = pic; + if (h->long_ref[mmco[i].long_arg]) { + h->long_ref[mmco[i].long_arg]->long_ref = 1; + h->long_ref_count++; + } + break; + case MMCO_LONG2UNUSED: + j = pic_num_extract(h, mmco[i].long_arg, &structure); + pic = h->long_ref[j]; + if (pic) { + remove_long(h, j, structure ^ PICT_FRAME); + } else if (h->avctx->debug & FF_DEBUG_MMCO) + av_log(h->avctx, AV_LOG_DEBUG, "mmco: unref long failure\n"); + break; + case MMCO_LONG: + // Comment below left from previous code as it is an interresting note. + /* First field in pair is in short term list or + * at a different long term index. + * This is not allowed; see 7.4.3.3, notes 2 and 3. + * Report the problem and keep the pair where it is, + * and mark this field valid. + */ + + if (h->long_ref[mmco[i].long_arg] != h->cur_pic_ptr) { + remove_long(h, mmco[i].long_arg, 0); + + h->long_ref[mmco[i].long_arg] = h->cur_pic_ptr; + h->long_ref[mmco[i].long_arg]->long_ref = 1; + h->long_ref_count++; + } + + h->cur_pic_ptr->reference |= h->picture_structure; + current_ref_assigned = 1; + break; + case MMCO_SET_MAX_LONG: + assert(mmco[i].long_arg <= 16); + // just remove the long term which index is greater than new max + for (j = mmco[i].long_arg; j < 16; j++) { + remove_long(h, j, 0); + } + break; + case MMCO_RESET: + while (h->short_ref_count) { + remove_short(h, h->short_ref[0]->frame_num, 0); + } + for (j = 0; j < 16; j++) { + remove_long(h, j, 0); + } + h->frame_num = h->cur_pic_ptr->frame_num = 0; + h->mmco_reset = 1; + h->cur_pic_ptr->mmco_reset = 1; + for (j = 0; j < MAX_DELAYED_PIC_COUNT; j++) + h->last_pocs[j] = INT_MIN; + break; + default: assert(0); + } + } + + if (!current_ref_assigned) { + /* Second field of complementary field pair; the first field of + * which is already referenced. If short referenced, it + * should be first entry in short_ref. If not, it must exist + * in long_ref; trying to put it on the short list here is an + * error in the encoded bit stream (ref: 7.4.3.3, NOTE 2 and 3). + */ + if (h->short_ref_count && h->short_ref[0] == h->cur_pic_ptr) { + /* Just mark the second field valid */ + h->cur_pic_ptr->reference = PICT_FRAME; + } else if (h->cur_pic_ptr->long_ref) { + av_log(h->avctx, AV_LOG_ERROR, "illegal short term reference " + "assignment for second field " + "in complementary field pair " + "(first field is long term)\n"); + err = AVERROR_INVALIDDATA; + } else { + pic = remove_short(h, h->cur_pic_ptr->frame_num, 0); + if (pic) { + av_log(h->avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n"); + err = AVERROR_INVALIDDATA; + } + + if (h->short_ref_count) + memmove(&h->short_ref[1], &h->short_ref[0], + h->short_ref_count * sizeof(Picture*)); + + h->short_ref[0] = h->cur_pic_ptr; + h->short_ref_count++; + h->cur_pic_ptr->reference |= h->picture_structure; + } + } + + if (h->long_ref_count + h->short_ref_count > FFMAX(h->sps.ref_frame_count, 1)) { + + /* We have too many reference frames, probably due to corrupted + * stream. Need to discard one frame. Prevents overrun of the + * short_ref and long_ref buffers. + */ + av_log(h->avctx, AV_LOG_ERROR, + "number of reference frames (%d+%d) exceeds max (%d; probably " + "corrupt input), discarding one\n", + h->long_ref_count, h->short_ref_count, h->sps.ref_frame_count); + err = AVERROR_INVALIDDATA; + + if (h->long_ref_count && !h->short_ref_count) { + for (i = 0; i < 16; ++i) + if (h->long_ref[i]) + break; + + assert(i < 16); + remove_long(h, i, 0); + } else { + pic = h->short_ref[h->short_ref_count - 1]; + remove_short(h, pic->frame_num, 0); + } + } + + print_short_term(h); + print_long_term(h); + + if(err >= 0 && h->long_ref_count==0 && h->short_ref_count<=2 && h->pps.ref_count[0]<=1 + (h->picture_structure != PICT_FRAME) && h->cur_pic_ptr->f.pict_type == AV_PICTURE_TYPE_I){ + h->cur_pic_ptr->sync |= 1; + if(!h->avctx->has_b_frames) + h->sync = 2; + } + + return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0; +} + +int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, + int first_slice) +{ + int i, ret; + MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp; + int mmco_index = 0; + + if (h->nal_unit_type == NAL_IDR_SLICE) { // FIXME fields + skip_bits1(gb); // broken_link + if (get_bits1(gb)) { + mmco[0].opcode = MMCO_LONG; + mmco[0].long_arg = 0; + mmco_index = 1; + } + } else { + if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag + for (i = 0; i < MAX_MMCO_COUNT; i++) { + MMCOOpcode opcode = get_ue_golomb_31(gb); + + mmco[i].opcode = opcode; + if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG) { + mmco[i].short_pic_num = + (h->curr_pic_num - get_ue_golomb(gb) - 1) & + (h->max_pic_num - 1); +#if 0 + if (mmco[i].short_pic_num >= h->short_ref_count || + h->short_ref[ mmco[i].short_pic_num ] == NULL){ + av_log(s->avctx, AV_LOG_ERROR, + "illegal short ref in memory management control " + "operation %d\n", mmco); + return -1; + } +#endif + } + if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED || + opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG) { + unsigned int long_arg = get_ue_golomb_31(gb); + if (long_arg >= 32 || + (long_arg >= 16 && !(opcode == MMCO_SET_MAX_LONG && + long_arg == 16) && + !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE(h)))) { + av_log(h->avctx, AV_LOG_ERROR, + "illegal long ref in memory management control " + "operation %d\n", opcode); + return -1; + } + mmco[i].long_arg = long_arg; + } + + if (opcode > (unsigned) MMCO_LONG) { + av_log(h->avctx, AV_LOG_ERROR, + "illegal memory management control operation %d\n", + opcode); + return -1; + } + if (opcode == MMCO_END) + break; + } + mmco_index = i; + } else { + if (first_slice) { + ret = ff_generate_sliding_window_mmcos(h, first_slice); + if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE) + return ret; + } + mmco_index = -1; + } + } + + if (first_slice && mmco_index != -1) { + h->mmco_index = mmco_index; + } else if (!first_slice && mmco_index >= 0 && + (mmco_index != h->mmco_index || + (i = check_opcodes(h->mmco, mmco_temp, mmco_index)))) { + av_log(h->avctx, AV_LOG_ERROR, + "Inconsistent MMCO state between slices [%d, %d]\n", + mmco_index, h->mmco_index); + return AVERROR_INVALIDDATA; + } + + return 0; +} diff --git a/ffmpeg/libavcodec/h264_sei.c b/ffmpeg/libavcodec/h264_sei.c new file mode 100644 index 0000000..be6cb58 --- /dev/null +++ b/ffmpeg/libavcodec/h264_sei.c @@ -0,0 +1,251 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... sei decoding + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 sei decoding. + * @author Michael Niedermayer + */ + +#include "internal.h" +#include "avcodec.h" +#include "h264.h" +#include "golomb.h" + +//#undef NDEBUG +#include + +static const uint8_t sei_num_clock_ts_table[9]={ + 1, 1, 1, 2, 2, 3, 3, 2, 3 +}; + +void ff_h264_reset_sei(H264Context *h) { + h->sei_recovery_frame_cnt = -1; + h->sei_dpb_output_delay = 0; + h->sei_cpb_removal_delay = -1; + h->sei_buffering_period_present = 0; +} + +static int decode_picture_timing(H264Context *h){ + if(h->sps.nal_hrd_parameters_present_flag || h->sps.vcl_hrd_parameters_present_flag){ + h->sei_cpb_removal_delay = get_bits_long(&h->gb, h->sps.cpb_removal_delay_length); + h->sei_dpb_output_delay = get_bits_long(&h->gb, h->sps.dpb_output_delay_length); + } + if(h->sps.pic_struct_present_flag){ + unsigned int i, num_clock_ts; + h->sei_pic_struct = get_bits(&h->gb, 4); + h->sei_ct_type = 0; + + if (h->sei_pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING) + return -1; + + num_clock_ts = sei_num_clock_ts_table[h->sei_pic_struct]; + + for (i = 0 ; i < num_clock_ts ; i++){ + if(get_bits(&h->gb, 1)){ /* clock_timestamp_flag */ + unsigned int full_timestamp_flag; + h->sei_ct_type |= 1<gb, 2); + skip_bits(&h->gb, 1); /* nuit_field_based_flag */ + skip_bits(&h->gb, 5); /* counting_type */ + full_timestamp_flag = get_bits(&h->gb, 1); + skip_bits(&h->gb, 1); /* discontinuity_flag */ + skip_bits(&h->gb, 1); /* cnt_dropped_flag */ + skip_bits(&h->gb, 8); /* n_frames */ + if(full_timestamp_flag){ + skip_bits(&h->gb, 6); /* seconds_value 0..59 */ + skip_bits(&h->gb, 6); /* minutes_value 0..59 */ + skip_bits(&h->gb, 5); /* hours_value 0..23 */ + }else{ + if(get_bits(&h->gb, 1)){ /* seconds_flag */ + skip_bits(&h->gb, 6); /* seconds_value range 0..59 */ + if(get_bits(&h->gb, 1)){ /* minutes_flag */ + skip_bits(&h->gb, 6); /* minutes_value 0..59 */ + if(get_bits(&h->gb, 1)) /* hours_flag */ + skip_bits(&h->gb, 5); /* hours_value 0..23 */ + } + } + } + if(h->sps.time_offset_length > 0) + skip_bits(&h->gb, h->sps.time_offset_length); /* time_offset */ + } + } + + if(h->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(h->avctx, AV_LOG_DEBUG, "ct_type:%X pic_struct:%d\n", h->sei_ct_type, h->sei_pic_struct); + } + return 0; +} + +static int decode_user_data_itu_t_t35(H264Context *h, int size) { + uint32_t user_identifier; + int dtg_active_format; + + if (size < 7) + return -1; + size -= 7; + + skip_bits(&h->gb, 8); // country_code + skip_bits(&h->gb, 16); // provider_code + user_identifier = get_bits_long(&h->gb, 32); + + switch (user_identifier) { + case 0x44544731: // "DTG1" - AFD_data + if (size < 1) + return -1; + skip_bits(&h->gb, 1); + if (get_bits(&h->gb, 1)) { + skip_bits(&h->gb, 6); + if (size < 2) + return -1; + skip_bits(&h->gb, 4); + dtg_active_format = get_bits(&h->gb, 4); + h->avctx->dtg_active_format = dtg_active_format; + } else { + skip_bits(&h->gb, 6); + } + break; + default: + skip_bits(&h->gb, size * 8); + break; + } + + return 0; +} + +static int decode_unregistered_user_data(H264Context *h, int size){ + uint8_t user_data[16+256]; + int e, build, i; + + if(size<16) + return -1; + + for(i=0; igb, 8); + } + + user_data[i]= 0; + e= sscanf(user_data+16, "x264 - core %d"/*%s - H.264/MPEG-4 AVC codec - Copyleft 2005 - http://www.videolan.org/x264.html*/, &build); + if(e==1 && build>0) + h->x264_build= build; + if(e==1 && build==1 && !strncmp(user_data+16, "x264 - core 0000", 16)) + h->x264_build = 67; + + if(h->avctx->debug & FF_DEBUG_BUGS) + av_log(h->avctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data+16); + + for(; igb, 8); + + return 0; +} + +static int decode_recovery_point(H264Context *h){ + h->sei_recovery_frame_cnt = get_ue_golomb(&h->gb); + skip_bits(&h->gb, 4); /* 1b exact_match_flag, 1b broken_link_flag, 2b changing_slice_group_idc */ + + if(h->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(h->avctx, AV_LOG_DEBUG, "sei_recovery_frame_cnt: %d\n", h->sei_recovery_frame_cnt); + + return 0; +} + +static int decode_buffering_period(H264Context *h){ + unsigned int sps_id; + int sched_sel_idx; + SPS *sps; + + sps_id = get_ue_golomb_31(&h->gb); + if(sps_id > 31 || !h->sps_buffers[sps_id]) { + av_log(h->avctx, AV_LOG_ERROR, "non-existing SPS %d referenced in buffering period\n", sps_id); + return -1; + } + sps = h->sps_buffers[sps_id]; + + // NOTE: This is really so duplicated in the standard... See H.264, D.1.1 + if (sps->nal_hrd_parameters_present_flag) { + for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) { + h->initial_cpb_removal_delay[sched_sel_idx] = get_bits_long(&h->gb, sps->initial_cpb_removal_delay_length); + skip_bits(&h->gb, sps->initial_cpb_removal_delay_length); // initial_cpb_removal_delay_offset + } + } + if (sps->vcl_hrd_parameters_present_flag) { + for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) { + h->initial_cpb_removal_delay[sched_sel_idx] = get_bits_long(&h->gb, sps->initial_cpb_removal_delay_length); + skip_bits(&h->gb, sps->initial_cpb_removal_delay_length); // initial_cpb_removal_delay_offset + } + } + + h->sei_buffering_period_present = 1; + return 0; +} + +int ff_h264_decode_sei(H264Context *h){ + while (get_bits_left(&h->gb) > 16) { + int size, type; + + type=0; + do{ + if (get_bits_left(&h->gb) < 8) + return -1; + type+= show_bits(&h->gb, 8); + }while(get_bits(&h->gb, 8) == 255); + + size=0; + do{ + if (get_bits_left(&h->gb) < 8) + return -1; + size+= show_bits(&h->gb, 8); + }while(get_bits(&h->gb, 8) == 255); + + if(h->avctx->debug&FF_DEBUG_STARTCODE) + av_log(h->avctx, AV_LOG_DEBUG, "SEI %d len:%d\n", type, size); + + switch(type){ + case SEI_TYPE_PIC_TIMING: // Picture timing SEI + if(decode_picture_timing(h) < 0) + return -1; + break; + case SEI_TYPE_USER_DATA_ITU_T_T35: + if(decode_user_data_itu_t_t35(h, size) < 0) + return -1; + break; + case SEI_TYPE_USER_DATA_UNREGISTERED: + if(decode_unregistered_user_data(h, size) < 0) + return -1; + break; + case SEI_TYPE_RECOVERY_POINT: + if(decode_recovery_point(h) < 0) + return -1; + break; + case SEI_BUFFERING_PERIOD: + if(decode_buffering_period(h) < 0) + return -1; + break; + default: + skip_bits(&h->gb, 8*size); + } + + //FIXME check bits here + align_get_bits(&h->gb); + } + + return 0; +} diff --git a/ffmpeg/libavcodec/h264addpx_template.c b/ffmpeg/libavcodec/h264addpx_template.c new file mode 100644 index 0000000..046b6c2 --- /dev/null +++ b/ffmpeg/libavcodec/h264addpx_template.c @@ -0,0 +1,72 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2011 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 DSP functions. + * @author Michael Niedermayer + */ + +#include "bit_depth_template.c" + +static void FUNCC(ff_h264_add_pixels4)(uint8_t *_dst, int16_t *_src, int stride) +{ + int i; + pixel *dst = (pixel *) _dst; + dctcoef *src = (dctcoef *) _src; + stride /= sizeof(pixel); + + for (i = 0; i < 4; i++) { + dst[0] += src[0]; + dst[1] += src[1]; + dst[2] += src[2]; + dst[3] += src[3]; + + dst += stride; + src += 4; + } + + memset(_src, 0, sizeof(dctcoef) * 16); +} + +static void FUNCC(ff_h264_add_pixels8)(uint8_t *_dst, int16_t *_src, int stride) +{ + int i; + pixel *dst = (pixel *) _dst; + dctcoef *src = (dctcoef *) _src; + stride /= sizeof(pixel); + + for (i = 0; i < 8; i++) { + dst[0] += src[0]; + dst[1] += src[1]; + dst[2] += src[2]; + dst[3] += src[3]; + dst[4] += src[4]; + dst[5] += src[5]; + dst[6] += src[6]; + dst[7] += src[7]; + + dst += stride; + src += 8; + } + + memset(_src, 0, sizeof(dctcoef) * 64); +} diff --git a/ffmpeg/libavcodec/h264chroma.c b/ffmpeg/libavcodec/h264chroma.c new file mode 100644 index 0000000..3b780a0 --- /dev/null +++ b/ffmpeg/libavcodec/h264chroma.c @@ -0,0 +1,54 @@ +/* + * 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 "config.h" +#include "h264chroma.h" + +#define BIT_DEPTH 8 +#include "h264chroma_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 16 +#include "h264chroma_template.c" +#undef BIT_DEPTH + +#define SET_CHROMA(depth) \ + c->put_h264_chroma_pixels_tab[0] = put_h264_chroma_mc8_ ## depth ## _c; \ + c->put_h264_chroma_pixels_tab[1] = put_h264_chroma_mc4_ ## depth ## _c; \ + c->put_h264_chroma_pixels_tab[2] = put_h264_chroma_mc2_ ## depth ## _c; \ + c->avg_h264_chroma_pixels_tab[0] = avg_h264_chroma_mc8_ ## depth ## _c; \ + c->avg_h264_chroma_pixels_tab[1] = avg_h264_chroma_mc4_ ## depth ## _c; \ + c->avg_h264_chroma_pixels_tab[2] = avg_h264_chroma_mc2_ ## depth ## _c; \ + +void ff_h264chroma_init(H264ChromaContext *c, int bit_depth) +{ + if (bit_depth > 8 && bit_depth <= 16) { + SET_CHROMA(16); + } else { + SET_CHROMA(8); + } + + if (ARCH_ARM) + ff_h264chroma_init_arm(c, bit_depth); + if (ARCH_PPC) + ff_h264chroma_init_ppc(c, bit_depth); + if (ARCH_SH4) + ff_h264chroma_init_sh4(c, bit_depth); + if (ARCH_X86) + ff_h264chroma_init_x86(c, bit_depth); +} diff --git a/ffmpeg/libavcodec/h264chroma.h b/ffmpeg/libavcodec/h264chroma.h new file mode 100644 index 0000000..4e035b0 --- /dev/null +++ b/ffmpeg/libavcodec/h264chroma.h @@ -0,0 +1,38 @@ +/* + * 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 + */ + +#ifndef AVCODEC_H264CHROMA_H +#define AVCODEC_H264CHROMA_H + +#include + +typedef void (*h264_chroma_mc_func)(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int srcStride, int h, int x, int y); + +typedef struct H264ChromaContext { + h264_chroma_mc_func put_h264_chroma_pixels_tab[3]; + h264_chroma_mc_func avg_h264_chroma_pixels_tab[3]; +} H264ChromaContext; + +void ff_h264chroma_init(H264ChromaContext *c, int bit_depth); + +void ff_h264chroma_init_arm(H264ChromaContext *c, int bit_depth); +void ff_h264chroma_init_ppc(H264ChromaContext *c, int bit_depth); +void ff_h264chroma_init_sh4(H264ChromaContext *c, int bit_depth); +void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth); + +#endif /* AVCODEC_H264CHROMA_H */ diff --git a/ffmpeg/libavcodec/h264chroma_template.c b/ffmpeg/libavcodec/h264chroma_template.c new file mode 100644 index 0000000..93559d7 --- /dev/null +++ b/ffmpeg/libavcodec/h264chroma_template.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 "libavutil/avassert.h" + +#include "bit_depth_template.c" + +#define H264_CHROMA_MC(OPNAME, OP)\ +static void FUNCC(OPNAME ## h264_chroma_mc2)(uint8_t *_dst/*align 8*/, uint8_t *_src/*align 1*/, int stride, int h, int x, int y){\ + pixel *dst = (pixel*)_dst;\ + pixel *src = (pixel*)_src;\ + const int A=(8-x)*(8-y);\ + const int B=( x)*(8-y);\ + const int C=(8-x)*( y);\ + const int D=( x)*( y);\ + int i;\ + stride >>= sizeof(pixel)-1;\ + \ + av_assert2(x<8 && y<8 && x>=0 && y>=0);\ +\ + if(D){\ + for(i=0; i>= sizeof(pixel)-1;\ + \ + av_assert2(x<8 && y<8 && x>=0 && y>=0);\ +\ + if(D){\ + for(i=0; i>= sizeof(pixel)-1;\ + \ + av_assert2(x<8 && y<8 && x>=0 && y>=0);\ +\ + if(D){\ + for(i=0; i>6)+1)>>1) +#define op_put(a, b) a = (((b) + 32)>>6) + +H264_CHROMA_MC(put_ , op_put) +H264_CHROMA_MC(avg_ , op_avg) +#undef op_avg +#undef op_put diff --git a/ffmpeg/libavcodec/h264data.h b/ffmpeg/libavcodec/h264data.h new file mode 100644 index 0000000..f3fc7f9 --- /dev/null +++ b/ffmpeg/libavcodec/h264data.h @@ -0,0 +1,272 @@ +/* + * H26L/H264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * @brief + * H264 / AVC / MPEG4 part10 codec data table + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_H264DATA_H +#define AVCODEC_H264DATA_H + +#include + +#include "libavutil/rational.h" +#include "mpegvideo.h" +#include "h264.h" + +static const uint8_t golomb_to_pict_type[5] = { + AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I, + AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI +}; + +static const uint8_t golomb_to_intra4x4_cbp[48] = { + 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46, + 16, 3, 5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1, 2, 4, + 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41 +}; + +static const uint8_t golomb_to_inter_cbp[48] = { + 0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13, + 14, 6, 9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46, + 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41 +}; + +static const uint8_t zigzag_scan[16+1] = { + 0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4, + 1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4, + 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4, + 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4, +}; + +static const uint8_t field_scan[16+1] = { + 0 + 0 * 4, 0 + 1 * 4, 1 + 0 * 4, 0 + 2 * 4, + 0 + 3 * 4, 1 + 1 * 4, 1 + 2 * 4, 1 + 3 * 4, + 2 + 0 * 4, 2 + 1 * 4, 2 + 2 * 4, 2 + 3 * 4, + 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4, 3 + 3 * 4, +}; + +static const uint8_t luma_dc_zigzag_scan[16] = { + 0 * 16 + 0 * 64, 1 * 16 + 0 * 64, 2 * 16 + 0 * 64, 0 * 16 + 2 * 64, + 3 * 16 + 0 * 64, 0 * 16 + 1 * 64, 1 * 16 + 1 * 64, 2 * 16 + 1 * 64, + 1 * 16 + 2 * 64, 2 * 16 + 2 * 64, 3 * 16 + 2 * 64, 0 * 16 + 3 * 64, + 3 * 16 + 1 * 64, 1 * 16 + 3 * 64, 2 * 16 + 3 * 64, 3 * 16 + 3 * 64, +}; + +static const uint8_t luma_dc_field_scan[16] = { + 0 * 16 + 0 * 64, 2 * 16 + 0 * 64, 1 * 16 + 0 * 64, 0 * 16 + 2 * 64, + 2 * 16 + 2 * 64, 3 * 16 + 0 * 64, 1 * 16 + 2 * 64, 3 * 16 + 2 * 64, + 0 * 16 + 1 * 64, 2 * 16 + 1 * 64, 0 * 16 + 3 * 64, 2 * 16 + 3 * 64, + 1 * 16 + 1 * 64, 3 * 16 + 1 * 64, 1 * 16 + 3 * 64, 3 * 16 + 3 * 64, +}; + +static const uint8_t chroma_dc_scan[4] = { + (0 + 0 * 2) * 16, (1 + 0 * 2) * 16, + (0 + 1 * 2) * 16, (1 + 1 * 2) * 16, +}; + +static const uint8_t chroma422_dc_scan[8] = { + (0 + 0 * 2) * 16, (0 + 1 * 2) * 16, + (1 + 0 * 2) * 16, (0 + 2 * 2) * 16, + (0 + 3 * 2) * 16, (1 + 1 * 2) * 16, + (1 + 2 * 2) * 16, (1 + 3 * 2) * 16, +}; + +// zigzag_scan8x8_cavlc[i] = zigzag_scan8x8[(i/4) + 16*(i%4)] +static const uint8_t zigzag_scan8x8_cavlc[64+1] = { + 0 + 0 * 8, 1 + 1 * 8, 1 + 2 * 8, 2 + 2 * 8, + 4 + 1 * 8, 0 + 5 * 8, 3 + 3 * 8, 7 + 0 * 8, + 3 + 4 * 8, 1 + 7 * 8, 5 + 3 * 8, 6 + 3 * 8, + 2 + 7 * 8, 6 + 4 * 8, 5 + 6 * 8, 7 + 5 * 8, + 1 + 0 * 8, 2 + 0 * 8, 0 + 3 * 8, 3 + 1 * 8, + 3 + 2 * 8, 0 + 6 * 8, 4 + 2 * 8, 6 + 1 * 8, + 2 + 5 * 8, 2 + 6 * 8, 6 + 2 * 8, 5 + 4 * 8, + 3 + 7 * 8, 7 + 3 * 8, 4 + 7 * 8, 7 + 6 * 8, + 0 + 1 * 8, 3 + 0 * 8, 0 + 4 * 8, 4 + 0 * 8, + 2 + 3 * 8, 1 + 5 * 8, 5 + 1 * 8, 5 + 2 * 8, + 1 + 6 * 8, 3 + 5 * 8, 7 + 1 * 8, 4 + 5 * 8, + 4 + 6 * 8, 7 + 4 * 8, 5 + 7 * 8, 6 + 7 * 8, + 0 + 2 * 8, 2 + 1 * 8, 1 + 3 * 8, 5 + 0 * 8, + 1 + 4 * 8, 2 + 4 * 8, 6 + 0 * 8, 4 + 3 * 8, + 0 + 7 * 8, 4 + 4 * 8, 7 + 2 * 8, 3 + 6 * 8, + 5 + 5 * 8, 6 + 5 * 8, 6 + 6 * 8, 7 + 7 * 8, +}; + +static const uint8_t field_scan8x8[64+1] = { + 0 + 0 * 8, 0 + 1 * 8, 0 + 2 * 8, 1 + 0 * 8, + 1 + 1 * 8, 0 + 3 * 8, 0 + 4 * 8, 1 + 2 * 8, + 2 + 0 * 8, 1 + 3 * 8, 0 + 5 * 8, 0 + 6 * 8, + 0 + 7 * 8, 1 + 4 * 8, 2 + 1 * 8, 3 + 0 * 8, + 2 + 2 * 8, 1 + 5 * 8, 1 + 6 * 8, 1 + 7 * 8, + 2 + 3 * 8, 3 + 1 * 8, 4 + 0 * 8, 3 + 2 * 8, + 2 + 4 * 8, 2 + 5 * 8, 2 + 6 * 8, 2 + 7 * 8, + 3 + 3 * 8, 4 + 1 * 8, 5 + 0 * 8, 4 + 2 * 8, + 3 + 4 * 8, 3 + 5 * 8, 3 + 6 * 8, 3 + 7 * 8, + 4 + 3 * 8, 5 + 1 * 8, 6 + 0 * 8, 5 + 2 * 8, + 4 + 4 * 8, 4 + 5 * 8, 4 + 6 * 8, 4 + 7 * 8, + 5 + 3 * 8, 6 + 1 * 8, 6 + 2 * 8, 5 + 4 * 8, + 5 + 5 * 8, 5 + 6 * 8, 5 + 7 * 8, 6 + 3 * 8, + 7 + 0 * 8, 7 + 1 * 8, 6 + 4 * 8, 6 + 5 * 8, + 6 + 6 * 8, 6 + 7 * 8, 7 + 2 * 8, 7 + 3 * 8, + 7 + 4 * 8, 7 + 5 * 8, 7 + 6 * 8, 7 + 7 * 8, +}; + +static const uint8_t field_scan8x8_cavlc[64+1] = { + 0 + 0 * 8, 1 + 1 * 8, 2 + 0 * 8, 0 + 7 * 8, + 2 + 2 * 8, 2 + 3 * 8, 2 + 4 * 8, 3 + 3 * 8, + 3 + 4 * 8, 4 + 3 * 8, 4 + 4 * 8, 5 + 3 * 8, + 5 + 5 * 8, 7 + 0 * 8, 6 + 6 * 8, 7 + 4 * 8, + 0 + 1 * 8, 0 + 3 * 8, 1 + 3 * 8, 1 + 4 * 8, + 1 + 5 * 8, 3 + 1 * 8, 2 + 5 * 8, 4 + 1 * 8, + 3 + 5 * 8, 5 + 1 * 8, 4 + 5 * 8, 6 + 1 * 8, + 5 + 6 * 8, 7 + 1 * 8, 6 + 7 * 8, 7 + 5 * 8, + 0 + 2 * 8, 0 + 4 * 8, 0 + 5 * 8, 2 + 1 * 8, + 1 + 6 * 8, 4 + 0 * 8, 2 + 6 * 8, 5 + 0 * 8, + 3 + 6 * 8, 6 + 0 * 8, 4 + 6 * 8, 6 + 2 * 8, + 5 + 7 * 8, 6 + 4 * 8, 7 + 2 * 8, 7 + 6 * 8, + 1 + 0 * 8, 1 + 2 * 8, 0 + 6 * 8, 3 + 0 * 8, + 1 + 7 * 8, 3 + 2 * 8, 2 + 7 * 8, 4 + 2 * 8, + 3 + 7 * 8, 5 + 2 * 8, 4 + 7 * 8, 5 + 4 * 8, + 6 + 3 * 8, 6 + 5 * 8, 7 + 3 * 8, 7 + 7 * 8, +}; + +typedef struct IMbInfo { + uint16_t type; + uint8_t pred_mode; + uint8_t cbp; +} IMbInfo; + +static const IMbInfo i_mb_type_info[26] = { + { MB_TYPE_INTRA4x4, -1, -1 }, + { MB_TYPE_INTRA16x16, 2, 0 }, + { MB_TYPE_INTRA16x16, 1, 0 }, + { MB_TYPE_INTRA16x16, 0, 0 }, + { MB_TYPE_INTRA16x16, 3, 0 }, + { MB_TYPE_INTRA16x16, 2, 16 }, + { MB_TYPE_INTRA16x16, 1, 16 }, + { MB_TYPE_INTRA16x16, 0, 16 }, + { MB_TYPE_INTRA16x16, 3, 16 }, + { MB_TYPE_INTRA16x16, 2, 32 }, + { MB_TYPE_INTRA16x16, 1, 32 }, + { MB_TYPE_INTRA16x16, 0, 32 }, + { MB_TYPE_INTRA16x16, 3, 32 }, + { MB_TYPE_INTRA16x16, 2, 15 + 0 }, + { MB_TYPE_INTRA16x16, 1, 15 + 0 }, + { MB_TYPE_INTRA16x16, 0, 15 + 0 }, + { MB_TYPE_INTRA16x16, 3, 15 + 0 }, + { MB_TYPE_INTRA16x16, 2, 15 + 16 }, + { MB_TYPE_INTRA16x16, 1, 15 + 16 }, + { MB_TYPE_INTRA16x16, 0, 15 + 16 }, + { MB_TYPE_INTRA16x16, 3, 15 + 16 }, + { MB_TYPE_INTRA16x16, 2, 15 + 32 }, + { MB_TYPE_INTRA16x16, 1, 15 + 32 }, + { MB_TYPE_INTRA16x16, 0, 15 + 32 }, + { MB_TYPE_INTRA16x16, 3, 15 + 32 }, + { MB_TYPE_INTRA_PCM, -1, -1 }, +}; + +typedef struct PMbInfo { + uint16_t type; + uint8_t partition_count; +} PMbInfo; + +static const PMbInfo p_mb_type_info[5] = { + { MB_TYPE_16x16 | MB_TYPE_P0L0, 1 }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2 }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2 }, + { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 4 }, + { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_REF0, 4 }, +}; + +static const PMbInfo p_sub_mb_type_info[4] = { + { MB_TYPE_16x16 | MB_TYPE_P0L0, 1 }, + { MB_TYPE_16x8 | MB_TYPE_P0L0, 2 }, + { MB_TYPE_8x16 | MB_TYPE_P0L0, 2 }, + { MB_TYPE_8x8 | MB_TYPE_P0L0, 4 }, +}; + +static const PMbInfo b_mb_type_info[23] = { + { MB_TYPE_DIRECT2 | MB_TYPE_L0L1, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L0, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L1, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1, 1, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, }, +}; + +static const PMbInfo b_sub_mb_type_info[13] = { + { MB_TYPE_DIRECT2, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L0, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L1, 1, }, + { MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1, 1, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, }, + { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 4, }, + { MB_TYPE_8x8 | MB_TYPE_P0L1 | MB_TYPE_P1L1, 4, }, + { MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, }, +}; + +static const uint8_t dequant4_coeff_init[6][3] = { + { 10, 13, 16 }, + { 11, 14, 18 }, + { 13, 16, 20 }, + { 14, 18, 23 }, + { 16, 20, 25 }, + { 18, 23, 29 }, +}; + +static const uint8_t dequant8_coeff_init_scan[16] = { + 0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1 +}; + +static const uint8_t dequant8_coeff_init[6][6] = { + { 20, 18, 32, 19, 25, 24 }, + { 22, 19, 35, 21, 28, 26 }, + { 26, 23, 42, 24, 33, 31 }, + { 28, 25, 45, 26, 35, 33 }, + { 32, 28, 51, 30, 40, 38 }, + { 36, 32, 58, 34, 46, 43 }, +}; + +#endif /* AVCODEC_H264DATA_H */ diff --git a/ffmpeg/libavcodec/h264dsp.c b/ffmpeg/libavcodec/h264dsp.c new file mode 100644 index 0000000..da9e417 --- /dev/null +++ b/ffmpeg/libavcodec/h264dsp.c @@ -0,0 +1,153 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2010 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 DSP functions. + * @author Michael Niedermayer + */ + +#include +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "h264dsp.h" +#include "h264idct.h" +#include "libavutil/common.h" + +#define BIT_DEPTH 8 +#include "h264dsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 9 +#include "h264dsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 10 +#include "h264dsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 12 +#include "h264dsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 14 +#include "h264dsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 8 +#include "h264addpx_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 16 +#include "h264addpx_template.c" +#undef BIT_DEPTH + +void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_format_idc) +{ +#undef FUNC +#define FUNC(a, depth) a ## _ ## depth ## _c + +#define ADDPX_DSP(depth) \ + c->h264_add_pixels4_clear = FUNC(ff_h264_add_pixels4, depth);\ + c->h264_add_pixels8_clear = FUNC(ff_h264_add_pixels8, depth) + + if (bit_depth > 8 && bit_depth <= 16) { + ADDPX_DSP(16); + } else { + ADDPX_DSP(8); + } + +#define H264_DSP(depth) \ + c->h264_idct_add= FUNC(ff_h264_idct_add, depth);\ + c->h264_idct8_add= FUNC(ff_h264_idct8_add, depth);\ + c->h264_idct_dc_add= FUNC(ff_h264_idct_dc_add, depth);\ + c->h264_idct8_dc_add= FUNC(ff_h264_idct8_dc_add, depth);\ + c->h264_idct_add16 = FUNC(ff_h264_idct_add16, depth);\ + c->h264_idct8_add4 = FUNC(ff_h264_idct8_add4, depth);\ + if (chroma_format_idc == 1)\ + c->h264_idct_add8 = FUNC(ff_h264_idct_add8, depth);\ + else\ + c->h264_idct_add8 = FUNC(ff_h264_idct_add8_422, depth);\ + c->h264_idct_add16intra= FUNC(ff_h264_idct_add16intra, depth);\ + c->h264_luma_dc_dequant_idct= FUNC(ff_h264_luma_dc_dequant_idct, depth);\ + if (chroma_format_idc == 1)\ + c->h264_chroma_dc_dequant_idct= FUNC(ff_h264_chroma_dc_dequant_idct, depth);\ + else\ + c->h264_chroma_dc_dequant_idct= FUNC(ff_h264_chroma422_dc_dequant_idct, depth);\ +\ + c->weight_h264_pixels_tab[0]= FUNC(weight_h264_pixels16, depth);\ + c->weight_h264_pixels_tab[1]= FUNC(weight_h264_pixels8, depth);\ + c->weight_h264_pixels_tab[2]= FUNC(weight_h264_pixels4, depth);\ + c->weight_h264_pixels_tab[3]= FUNC(weight_h264_pixels2, depth);\ + c->biweight_h264_pixels_tab[0]= FUNC(biweight_h264_pixels16, depth);\ + c->biweight_h264_pixels_tab[1]= FUNC(biweight_h264_pixels8, depth);\ + c->biweight_h264_pixels_tab[2]= FUNC(biweight_h264_pixels4, depth);\ + c->biweight_h264_pixels_tab[3]= FUNC(biweight_h264_pixels2, depth);\ +\ + c->h264_v_loop_filter_luma= FUNC(h264_v_loop_filter_luma, depth);\ + c->h264_h_loop_filter_luma= FUNC(h264_h_loop_filter_luma, depth);\ + c->h264_h_loop_filter_luma_mbaff= FUNC(h264_h_loop_filter_luma_mbaff, depth);\ + c->h264_v_loop_filter_luma_intra= FUNC(h264_v_loop_filter_luma_intra, depth);\ + c->h264_h_loop_filter_luma_intra= FUNC(h264_h_loop_filter_luma_intra, depth);\ + c->h264_h_loop_filter_luma_mbaff_intra= FUNC(h264_h_loop_filter_luma_mbaff_intra, depth);\ + c->h264_v_loop_filter_chroma= FUNC(h264_v_loop_filter_chroma, depth);\ + if (chroma_format_idc == 1)\ + c->h264_h_loop_filter_chroma= FUNC(h264_h_loop_filter_chroma, depth);\ + else\ + c->h264_h_loop_filter_chroma= FUNC(h264_h_loop_filter_chroma422, depth);\ + if (chroma_format_idc == 1)\ + c->h264_h_loop_filter_chroma_mbaff= FUNC(h264_h_loop_filter_chroma_mbaff, depth);\ + else\ + c->h264_h_loop_filter_chroma_mbaff= FUNC(h264_h_loop_filter_chroma422_mbaff, depth);\ + c->h264_v_loop_filter_chroma_intra= FUNC(h264_v_loop_filter_chroma_intra, depth);\ + if (chroma_format_idc == 1)\ + c->h264_h_loop_filter_chroma_intra= FUNC(h264_h_loop_filter_chroma_intra, depth);\ + else\ + c->h264_h_loop_filter_chroma_intra= FUNC(h264_h_loop_filter_chroma422_intra, depth);\ + if (chroma_format_idc == 1)\ + c->h264_h_loop_filter_chroma_mbaff_intra= FUNC(h264_h_loop_filter_chroma_mbaff_intra, depth);\ + else\ + c->h264_h_loop_filter_chroma_mbaff_intra= FUNC(h264_h_loop_filter_chroma422_mbaff_intra, depth);\ + c->h264_loop_filter_strength= NULL; + + switch (bit_depth) { + case 9: + H264_DSP(9); + break; + case 10: + H264_DSP(10); + break; + case 12: + H264_DSP(12); + break; + case 14: + H264_DSP(14); + break; + default: + av_assert0(bit_depth<=8); + H264_DSP(8); + break; + } + + if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc); + if (HAVE_ALTIVEC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc); + if (ARCH_X86) ff_h264dsp_init_x86(c, bit_depth, chroma_format_idc); +} diff --git a/ffmpeg/libavcodec/h264dsp.h b/ffmpeg/libavcodec/h264dsp.h new file mode 100644 index 0000000..98ea15c --- /dev/null +++ b/ffmpeg/libavcodec/h264dsp.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2003-2010 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 + */ + +/** + * @file + * H.264 DSP functions. + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_H264DSP_H +#define AVCODEC_H264DSP_H + +#include + +typedef void (*h264_weight_func)(uint8_t *block, int stride, int height, + int log2_denom, int weight, int offset); +typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src, + int stride, int height, int log2_denom, + int weightd, int weights, int offset); + +/** + * Context for storing H.264 DSP functions + */ +typedef struct H264DSPContext { + /* weighted MC */ + h264_weight_func weight_h264_pixels_tab[4]; + h264_biweight_func biweight_h264_pixels_tab[4]; + + /* loop filter */ + void (*h264_v_loop_filter_luma)(uint8_t *pix /*align 16*/, int stride, + int alpha, int beta, int8_t *tc0); + void (*h264_h_loop_filter_luma)(uint8_t *pix /*align 4 */, int stride, + int alpha, int beta, int8_t *tc0); + void (*h264_h_loop_filter_luma_mbaff)(uint8_t *pix /*align 16*/, int stride, + int alpha, int beta, int8_t *tc0); + /* v/h_loop_filter_luma_intra: align 16 */ + void (*h264_v_loop_filter_luma_intra)(uint8_t *pix, int stride, + int alpha, int beta); + void (*h264_h_loop_filter_luma_intra)(uint8_t *pix, int stride, + int alpha, int beta); + void (*h264_h_loop_filter_luma_mbaff_intra)(uint8_t *pix /*align 16*/, + int stride, int alpha, int beta); + void (*h264_v_loop_filter_chroma)(uint8_t *pix /*align 8*/, int stride, + int alpha, int beta, int8_t *tc0); + void (*h264_h_loop_filter_chroma)(uint8_t *pix /*align 4*/, int stride, + int alpha, int beta, int8_t *tc0); + void (*h264_h_loop_filter_chroma_mbaff)(uint8_t *pix /*align 8*/, + int stride, int alpha, int beta, + int8_t *tc0); + void (*h264_v_loop_filter_chroma_intra)(uint8_t *pix /*align 8*/, + int stride, int alpha, int beta); + void (*h264_h_loop_filter_chroma_intra)(uint8_t *pix /*align 8*/, + int stride, int alpha, int beta); + void (*h264_h_loop_filter_chroma_mbaff_intra)(uint8_t *pix /*align 8*/, + int stride, int alpha, int beta); + // h264_loop_filter_strength: simd only. the C version is inlined in h264.c + void (*h264_loop_filter_strength)(int16_t bS[2][4][4], uint8_t nnz[40], + int8_t ref[2][40], int16_t mv[2][40][2], + int bidir, int edges, int step, + int mask_mv0, int mask_mv1, int field); + + /* IDCT */ + void (*h264_idct_add)(uint8_t *dst /*align 4*/, + int16_t *block /*align 16*/, int stride); + void (*h264_idct8_add)(uint8_t *dst /*align 8*/, + int16_t *block /*align 16*/, int stride); + void (*h264_idct_dc_add)(uint8_t *dst /*align 4*/, + int16_t *block /*align 16*/, int stride); + void (*h264_idct8_dc_add)(uint8_t *dst /*align 8*/, + int16_t *block /*align 16*/, int stride); + + void (*h264_idct_add16)(uint8_t *dst /*align 16*/, const int *blockoffset, + int16_t *block /*align 16*/, int stride, + const uint8_t nnzc[15 * 8]); + void (*h264_idct8_add4)(uint8_t *dst /*align 16*/, const int *blockoffset, + int16_t *block /*align 16*/, int stride, + const uint8_t nnzc[15 * 8]); + void (*h264_idct_add8)(uint8_t **dst /*align 16*/, const int *blockoffset, + int16_t *block /*align 16*/, int stride, + const uint8_t nnzc[15 * 8]); + void (*h264_idct_add16intra)(uint8_t *dst /*align 16*/, const int *blockoffset, + int16_t *block /*align 16*/, + int stride, const uint8_t nnzc[15 * 8]); + void (*h264_luma_dc_dequant_idct)(int16_t *output, + int16_t *input /*align 16*/, int qmul); + void (*h264_chroma_dc_dequant_idct)(int16_t *block, int qmul); + + /* bypass-transform */ + void (*h264_add_pixels8_clear)(uint8_t *dst, int16_t *block, int stride); + void (*h264_add_pixels4_clear)(uint8_t *dst, int16_t *block, int stride); +} H264DSPContext; + +void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc); +void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc); +void ff_h264dsp_init_ppc(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc); +void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc); + +#endif /* AVCODEC_H264DSP_H */ diff --git a/ffmpeg/libavcodec/h264dsp_template.c b/ffmpeg/libavcodec/h264dsp_template.c new file mode 100644 index 0000000..4d5faf0 --- /dev/null +++ b/ffmpeg/libavcodec/h264dsp_template.c @@ -0,0 +1,328 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2011 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 DSP functions. + * @author Michael Niedermayer + */ + +#include "bit_depth_template.c" + +#define op_scale1(x) block[x] = av_clip_pixel( (block[x]*weight + offset) >> log2_denom ) +#define op_scale2(x) dst[x] = av_clip_pixel( (src[x]*weights + dst[x]*weightd + offset) >> (log2_denom+1)) +#define H264_WEIGHT(W) \ +static void FUNCC(weight_h264_pixels ## W)(uint8_t *_block, int stride, int height, \ + int log2_denom, int weight, int offset) \ +{ \ + int y; \ + pixel *block = (pixel*)_block; \ + stride >>= sizeof(pixel)-1; \ + offset <<= (log2_denom + (BIT_DEPTH-8)); \ + if(log2_denom) offset += 1<<(log2_denom-1); \ + for (y = 0; y < height; y++, block += stride) { \ + op_scale1(0); \ + op_scale1(1); \ + if(W==2) continue; \ + op_scale1(2); \ + op_scale1(3); \ + if(W==4) continue; \ + op_scale1(4); \ + op_scale1(5); \ + op_scale1(6); \ + op_scale1(7); \ + if(W==8) continue; \ + op_scale1(8); \ + op_scale1(9); \ + op_scale1(10); \ + op_scale1(11); \ + op_scale1(12); \ + op_scale1(13); \ + op_scale1(14); \ + op_scale1(15); \ + } \ +} \ +static void FUNCC(biweight_h264_pixels ## W)(uint8_t *_dst, uint8_t *_src, int stride, int height, \ + int log2_denom, int weightd, int weights, int offset) \ +{ \ + int y; \ + pixel *dst = (pixel*)_dst; \ + pixel *src = (pixel*)_src; \ + stride >>= sizeof(pixel)-1; \ + offset <<= (BIT_DEPTH-8); \ + offset = ((offset + 1) | 1) << log2_denom; \ + for (y = 0; y < height; y++, dst += stride, src += stride) { \ + op_scale2(0); \ + op_scale2(1); \ + if(W==2) continue; \ + op_scale2(2); \ + op_scale2(3); \ + if(W==4) continue; \ + op_scale2(4); \ + op_scale2(5); \ + op_scale2(6); \ + op_scale2(7); \ + if(W==8) continue; \ + op_scale2(8); \ + op_scale2(9); \ + op_scale2(10); \ + op_scale2(11); \ + op_scale2(12); \ + op_scale2(13); \ + op_scale2(14); \ + op_scale2(15); \ + } \ +} + +H264_WEIGHT(16) +H264_WEIGHT(8) +H264_WEIGHT(4) +H264_WEIGHT(2) + +#undef op_scale1 +#undef op_scale2 +#undef H264_WEIGHT + +static av_always_inline av_flatten void FUNCC(h264_loop_filter_luma)(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta, int8_t *tc0) +{ + pixel *pix = (pixel*)p_pix; + int i, d; + xstride >>= sizeof(pixel)-1; + ystride >>= sizeof(pixel)-1; + alpha <<= BIT_DEPTH - 8; + beta <<= BIT_DEPTH - 8; + for( i = 0; i < 4; i++ ) { + const int tc_orig = tc0[i] << (BIT_DEPTH - 8); + if( tc_orig < 0 ) { + pix += inner_iters*ystride; + continue; + } + for( d = 0; d < inner_iters; d++ ) { + const int p0 = pix[-1*xstride]; + const int p1 = pix[-2*xstride]; + const int p2 = pix[-3*xstride]; + const int q0 = pix[0]; + const int q1 = pix[1*xstride]; + const int q2 = pix[2*xstride]; + + if( FFABS( p0 - q0 ) < alpha && + FFABS( p1 - p0 ) < beta && + FFABS( q1 - q0 ) < beta ) { + + int tc = tc_orig; + int i_delta; + + if( FFABS( p2 - p0 ) < beta ) { + if(tc_orig) + pix[-2*xstride] = p1 + av_clip( (( p2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - p1, -tc_orig, tc_orig ); + tc++; + } + if( FFABS( q2 - q0 ) < beta ) { + if(tc_orig) + pix[ xstride] = q1 + av_clip( (( q2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - q1, -tc_orig, tc_orig ); + tc++; + } + + i_delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); + pix[-xstride] = av_clip_pixel( p0 + i_delta ); /* p0' */ + pix[0] = av_clip_pixel( q0 - i_delta ); /* q0' */ + } + pix += ystride; + } + } +} +static void FUNCC(h264_v_loop_filter_luma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_luma)(pix, stride, sizeof(pixel), 4, alpha, beta, tc0); +} +static void FUNCC(h264_h_loop_filter_luma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_luma)(pix, sizeof(pixel), stride, 4, alpha, beta, tc0); +} +static void FUNCC(h264_h_loop_filter_luma_mbaff)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_luma)(pix, sizeof(pixel), stride, 2, alpha, beta, tc0); +} + +static av_always_inline av_flatten void FUNCC(h264_loop_filter_luma_intra)(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta) +{ + pixel *pix = (pixel*)p_pix; + int d; + xstride >>= sizeof(pixel)-1; + ystride >>= sizeof(pixel)-1; + alpha <<= BIT_DEPTH - 8; + beta <<= BIT_DEPTH - 8; + for( d = 0; d < 4 * inner_iters; d++ ) { + const int p2 = pix[-3*xstride]; + const int p1 = pix[-2*xstride]; + const int p0 = pix[-1*xstride]; + + const int q0 = pix[ 0*xstride]; + const int q1 = pix[ 1*xstride]; + const int q2 = pix[ 2*xstride]; + + if( FFABS( p0 - q0 ) < alpha && + FFABS( p1 - p0 ) < beta && + FFABS( q1 - q0 ) < beta ) { + + if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){ + if( FFABS( p2 - p0 ) < beta) + { + const int p3 = pix[-4*xstride]; + /* p0', p1', p2' */ + pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3; + pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2; + pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3; + } else { + /* p0' */ + pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; + } + if( FFABS( q2 - q0 ) < beta) + { + const int q3 = pix[3*xstride]; + /* q0', q1', q2' */ + pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3; + pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2; + pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3; + } else { + /* q0' */ + pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; + } + }else{ + /* p0', q0' */ + pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; + pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2; + } + } + pix += ystride; + } +} +static void FUNCC(h264_v_loop_filter_luma_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_luma_intra)(pix, stride, sizeof(pixel), 4, alpha, beta); +} +static void FUNCC(h264_h_loop_filter_luma_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_luma_intra)(pix, sizeof(pixel), stride, 4, alpha, beta); +} +static void FUNCC(h264_h_loop_filter_luma_mbaff_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_luma_intra)(pix, sizeof(pixel), stride, 2, alpha, beta); +} + +static av_always_inline av_flatten void FUNCC(h264_loop_filter_chroma)(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta, int8_t *tc0) +{ + pixel *pix = (pixel*)p_pix; + int i, d; + alpha <<= BIT_DEPTH - 8; + beta <<= BIT_DEPTH - 8; + xstride >>= sizeof(pixel)-1; + ystride >>= sizeof(pixel)-1; + for( i = 0; i < 4; i++ ) { + const int tc = ((tc0[i] - 1) << (BIT_DEPTH - 8)) + 1; + if( tc <= 0 ) { + pix += inner_iters*ystride; + continue; + } + for( d = 0; d < inner_iters; d++ ) { + const int p0 = pix[-1*xstride]; + const int p1 = pix[-2*xstride]; + const int q0 = pix[0]; + const int q1 = pix[1*xstride]; + + if( FFABS( p0 - q0 ) < alpha && + FFABS( p1 - p0 ) < beta && + FFABS( q1 - q0 ) < beta ) { + + int delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); + + pix[-xstride] = av_clip_pixel( p0 + delta ); /* p0' */ + pix[0] = av_clip_pixel( q0 - delta ); /* q0' */ + } + pix += ystride; + } + } +} +static void FUNCC(h264_v_loop_filter_chroma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_chroma)(pix, stride, sizeof(pixel), 2, alpha, beta, tc0); +} +static void FUNCC(h264_h_loop_filter_chroma)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_chroma)(pix, sizeof(pixel), stride, 2, alpha, beta, tc0); +} +static void FUNCC(h264_h_loop_filter_chroma_mbaff)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_chroma)(pix, sizeof(pixel), stride, 1, alpha, beta, tc0); +} +static void FUNCC(h264_h_loop_filter_chroma422)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_chroma)(pix, sizeof(pixel), stride, 4, alpha, beta, tc0); +} +static void FUNCC(h264_h_loop_filter_chroma422_mbaff)(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) +{ + FUNCC(h264_loop_filter_chroma)(pix, sizeof(pixel), stride, 2, alpha, beta, tc0); +} + +static av_always_inline av_flatten void FUNCC(h264_loop_filter_chroma_intra)(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta) +{ + pixel *pix = (pixel*)p_pix; + int d; + xstride >>= sizeof(pixel)-1; + ystride >>= sizeof(pixel)-1; + alpha <<= BIT_DEPTH - 8; + beta <<= BIT_DEPTH - 8; + for( d = 0; d < 4 * inner_iters; d++ ) { + const int p0 = pix[-1*xstride]; + const int p1 = pix[-2*xstride]; + const int q0 = pix[0]; + const int q1 = pix[1*xstride]; + + if( FFABS( p0 - q0 ) < alpha && + FFABS( p1 - p0 ) < beta && + FFABS( q1 - q0 ) < beta ) { + + pix[-xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */ + pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */ + } + pix += ystride; + } +} +static void FUNCC(h264_v_loop_filter_chroma_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_chroma_intra)(pix, stride, sizeof(pixel), 2, alpha, beta); +} +static void FUNCC(h264_h_loop_filter_chroma_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_chroma_intra)(pix, sizeof(pixel), stride, 2, alpha, beta); +} +static void FUNCC(h264_h_loop_filter_chroma_mbaff_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_chroma_intra)(pix, sizeof(pixel), stride, 1, alpha, beta); +} +static void FUNCC(h264_h_loop_filter_chroma422_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_chroma_intra)(pix, sizeof(pixel), stride, 4, alpha, beta); +} +static void FUNCC(h264_h_loop_filter_chroma422_mbaff_intra)(uint8_t *pix, int stride, int alpha, int beta) +{ + FUNCC(h264_loop_filter_chroma_intra)(pix, sizeof(pixel), stride, 2, alpha, beta); +} diff --git a/ffmpeg/libavcodec/h264idct.c b/ffmpeg/libavcodec/h264idct.c new file mode 100644 index 0000000..6a771af --- /dev/null +++ b/ffmpeg/libavcodec/h264idct.c @@ -0,0 +1,48 @@ +/* + * H.264 IDCT + * Copyright (c) 2004 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 + */ + +/** + * @file + * H.264 IDCT. + * @author Michael Niedermayer + */ + +#include "h264idct.h" + +#define BIT_DEPTH 8 +#include "h264idct_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 9 +#include "h264idct_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 10 +#include "h264idct_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 12 +#include "h264idct_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 14 +#include "h264idct_template.c" +#undef BIT_DEPTH diff --git a/ffmpeg/libavcodec/h264idct.h b/ffmpeg/libavcodec/h264idct.h new file mode 100644 index 0000000..17e0051 --- /dev/null +++ b/ffmpeg/libavcodec/h264idct.h @@ -0,0 +1,44 @@ +/* + * 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 + */ + +#ifndef AVCODEC_H264IDCT_H +#define AVCODEC_H264IDCT_H + +#include + +#define H264_IDCT(depth) \ +void ff_h264_idct8_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\ +void ff_h264_idct_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\ +void ff_h264_idct8_dc_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\ +void ff_h264_idct_dc_add_ ## depth ## _c(uint8_t *dst, int16_t *block, int stride);\ +void ff_h264_idct_add16_ ## depth ## _c(uint8_t *dst, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\ +void ff_h264_idct_add16intra_ ## depth ## _c(uint8_t *dst, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\ +void ff_h264_idct8_add4_ ## depth ## _c(uint8_t *dst, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\ +void ff_h264_idct_add8_422_ ## depth ## _c(uint8_t **dest, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\ +void ff_h264_idct_add8_ ## depth ## _c(uint8_t **dest, const int *blockoffset, int16_t *block, int stride, const uint8_t nnzc[6*8]);\ +void ff_h264_luma_dc_dequant_idct_ ## depth ## _c(int16_t *output, int16_t *input, int qmul);\ +void ff_h264_chroma422_dc_dequant_idct_ ## depth ## _c(int16_t *block, int qmul);\ +void ff_h264_chroma_dc_dequant_idct_ ## depth ## _c(int16_t *block, int qmul); + +H264_IDCT( 8) +H264_IDCT( 9) +H264_IDCT(10) +H264_IDCT(12) +H264_IDCT(14) + +#endif /* AVCODEC_H264IDCT_H */ diff --git a/ffmpeg/libavcodec/h264idct_template.c b/ffmpeg/libavcodec/h264idct_template.c new file mode 100644 index 0000000..9f16e1d --- /dev/null +++ b/ffmpeg/libavcodec/h264idct_template.c @@ -0,0 +1,323 @@ +/* + * H.264 IDCT + * Copyright (c) 2004-2011 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 + */ + +/** + * @file + * H.264 IDCT. + * @author Michael Niedermayer + */ + +#include "bit_depth_template.c" +#include "libavutil/common.h" +#include "h264.h" + +void FUNCC(ff_h264_idct_add)(uint8_t *_dst, int16_t *_block, int stride) +{ + int i; + pixel *dst = (pixel*)_dst; + dctcoef *block = (dctcoef*)_block; + stride >>= sizeof(pixel)-1; + + block[0] += 1 << 5; + + for(i=0; i<4; i++){ + const int z0= block[i + 4*0] + block[i + 4*2]; + const int z1= block[i + 4*0] - block[i + 4*2]; + const int z2= (block[i + 4*1]>>1) - block[i + 4*3]; + const int z3= block[i + 4*1] + (block[i + 4*3]>>1); + + block[i + 4*0]= z0 + z3; + block[i + 4*1]= z1 + z2; + block[i + 4*2]= z1 - z2; + block[i + 4*3]= z0 - z3; + } + + for(i=0; i<4; i++){ + const int z0= block[0 + 4*i] + block[2 + 4*i]; + const int z1= block[0 + 4*i] - block[2 + 4*i]; + const int z2= (block[1 + 4*i]>>1) - block[3 + 4*i]; + const int z3= block[1 + 4*i] + (block[3 + 4*i]>>1); + + dst[i + 0*stride]= av_clip_pixel(dst[i + 0*stride] + ((z0 + z3) >> 6)); + dst[i + 1*stride]= av_clip_pixel(dst[i + 1*stride] + ((z1 + z2) >> 6)); + dst[i + 2*stride]= av_clip_pixel(dst[i + 2*stride] + ((z1 - z2) >> 6)); + dst[i + 3*stride]= av_clip_pixel(dst[i + 3*stride] + ((z0 - z3) >> 6)); + } + + memset(block, 0, 16 * sizeof(dctcoef)); +} + +void FUNCC(ff_h264_idct8_add)(uint8_t *_dst, int16_t *_block, int stride){ + int i; + pixel *dst = (pixel*)_dst; + dctcoef *block = (dctcoef*)_block; + stride >>= sizeof(pixel)-1; + + block[0] += 32; + + for( i = 0; i < 8; i++ ) + { + const int a0 = block[i+0*8] + block[i+4*8]; + const int a2 = block[i+0*8] - block[i+4*8]; + const int a4 = (block[i+2*8]>>1) - block[i+6*8]; + const int a6 = (block[i+6*8]>>1) + block[i+2*8]; + + const int b0 = a0 + a6; + const int b2 = a2 + a4; + const int b4 = a2 - a4; + const int b6 = a0 - a6; + + const int a1 = -block[i+3*8] + block[i+5*8] - block[i+7*8] - (block[i+7*8]>>1); + const int a3 = block[i+1*8] + block[i+7*8] - block[i+3*8] - (block[i+3*8]>>1); + const int a5 = -block[i+1*8] + block[i+7*8] + block[i+5*8] + (block[i+5*8]>>1); + const int a7 = block[i+3*8] + block[i+5*8] + block[i+1*8] + (block[i+1*8]>>1); + + const int b1 = (a7>>2) + a1; + const int b3 = a3 + (a5>>2); + const int b5 = (a3>>2) - a5; + const int b7 = a7 - (a1>>2); + + block[i+0*8] = b0 + b7; + block[i+7*8] = b0 - b7; + block[i+1*8] = b2 + b5; + block[i+6*8] = b2 - b5; + block[i+2*8] = b4 + b3; + block[i+5*8] = b4 - b3; + block[i+3*8] = b6 + b1; + block[i+4*8] = b6 - b1; + } + for( i = 0; i < 8; i++ ) + { + const int a0 = block[0+i*8] + block[4+i*8]; + const int a2 = block[0+i*8] - block[4+i*8]; + const int a4 = (block[2+i*8]>>1) - block[6+i*8]; + const int a6 = (block[6+i*8]>>1) + block[2+i*8]; + + const int b0 = a0 + a6; + const int b2 = a2 + a4; + const int b4 = a2 - a4; + const int b6 = a0 - a6; + + const int a1 = -block[3+i*8] + block[5+i*8] - block[7+i*8] - (block[7+i*8]>>1); + const int a3 = block[1+i*8] + block[7+i*8] - block[3+i*8] - (block[3+i*8]>>1); + const int a5 = -block[1+i*8] + block[7+i*8] + block[5+i*8] + (block[5+i*8]>>1); + const int a7 = block[3+i*8] + block[5+i*8] + block[1+i*8] + (block[1+i*8]>>1); + + const int b1 = (a7>>2) + a1; + const int b3 = a3 + (a5>>2); + const int b5 = (a3>>2) - a5; + const int b7 = a7 - (a1>>2); + + dst[i + 0*stride] = av_clip_pixel( dst[i + 0*stride] + ((b0 + b7) >> 6) ); + dst[i + 1*stride] = av_clip_pixel( dst[i + 1*stride] + ((b2 + b5) >> 6) ); + dst[i + 2*stride] = av_clip_pixel( dst[i + 2*stride] + ((b4 + b3) >> 6) ); + dst[i + 3*stride] = av_clip_pixel( dst[i + 3*stride] + ((b6 + b1) >> 6) ); + dst[i + 4*stride] = av_clip_pixel( dst[i + 4*stride] + ((b6 - b1) >> 6) ); + dst[i + 5*stride] = av_clip_pixel( dst[i + 5*stride] + ((b4 - b3) >> 6) ); + dst[i + 6*stride] = av_clip_pixel( dst[i + 6*stride] + ((b2 - b5) >> 6) ); + dst[i + 7*stride] = av_clip_pixel( dst[i + 7*stride] + ((b0 - b7) >> 6) ); + } + + memset(block, 0, 64 * sizeof(dctcoef)); +} + +// assumes all AC coefs are 0 +void FUNCC(ff_h264_idct_dc_add)(uint8_t *_dst, int16_t *_block, int stride){ + int i, j; + pixel *dst = (pixel*)_dst; + dctcoef *block = (dctcoef*)_block; + int dc = (block[0] + 32) >> 6; + stride >>= sizeof(pixel)-1; + block[0] = 0; + for( j = 0; j < 4; j++ ) + { + for( i = 0; i < 4; i++ ) + dst[i] = av_clip_pixel( dst[i] + dc ); + dst += stride; + } +} + +void FUNCC(ff_h264_idct8_dc_add)(uint8_t *_dst, int16_t *_block, int stride){ + int i, j; + pixel *dst = (pixel*)_dst; + dctcoef *block = (dctcoef*)_block; + int dc = (block[0] + 32) >> 6; + block[0] = 0; + stride >>= sizeof(pixel)-1; + for( j = 0; j < 8; j++ ) + { + for( i = 0; i < 8; i++ ) + dst[i] = av_clip_pixel( dst[i] + dc ); + dst += stride; + } +} + +void FUNCC(ff_h264_idct_add16)(uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i; + for(i=0; i<16; i++){ + int nnz = nnzc[ scan8[i] ]; + if(nnz){ + if(nnz==1 && ((dctcoef*)block)[i*16]) FUNCC(ff_h264_idct_dc_add)(dst + block_offset[i], block + i*16*sizeof(pixel), stride); + else FUNCC(ff_h264_idct_add )(dst + block_offset[i], block + i*16*sizeof(pixel), stride); + } + } +} + +void FUNCC(ff_h264_idct_add16intra)(uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i; + for(i=0; i<16; i++){ + if(nnzc[ scan8[i] ]) FUNCC(ff_h264_idct_add )(dst + block_offset[i], block + i*16*sizeof(pixel), stride); + else if(((dctcoef*)block)[i*16]) FUNCC(ff_h264_idct_dc_add)(dst + block_offset[i], block + i*16*sizeof(pixel), stride); + } +} + +void FUNCC(ff_h264_idct8_add4)(uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i; + for(i=0; i<16; i+=4){ + int nnz = nnzc[ scan8[i] ]; + if(nnz){ + if(nnz==1 && ((dctcoef*)block)[i*16]) FUNCC(ff_h264_idct8_dc_add)(dst + block_offset[i], block + i*16*sizeof(pixel), stride); + else FUNCC(ff_h264_idct8_add )(dst + block_offset[i], block + i*16*sizeof(pixel), stride); + } + } +} + +void FUNCC(ff_h264_idct_add8)(uint8_t **dest, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i, j; + for(j=1; j<3; j++){ + for(i=j*16; i> 8)); + output[stride* 1+offset]= ((((z1 + z2)*qmul + 128 ) >> 8)); + output[stride* 4+offset]= ((((z1 - z2)*qmul + 128 ) >> 8)); + output[stride* 5+offset]= ((((z0 - z3)*qmul + 128 ) >> 8)); + } +#undef stride +} + +void FUNCC(ff_h264_chroma422_dc_dequant_idct)(int16_t *_block, int qmul){ + const int stride= 16*2; + const int xStride= 16; + int i; + int temp[8]; + static const uint8_t x_offset[2]={0, 16}; + dctcoef *block = (dctcoef*)_block; + + for(i=0; i<4; i++){ + temp[2*i+0] = block[stride*i + xStride*0] + block[stride*i + xStride*1]; + temp[2*i+1] = block[stride*i + xStride*0] - block[stride*i + xStride*1]; + } + + for(i=0; i<2; i++){ + const int offset= x_offset[i]; + const int z0= temp[2*0+i] + temp[2*2+i]; + const int z1= temp[2*0+i] - temp[2*2+i]; + const int z2= temp[2*1+i] - temp[2*3+i]; + const int z3= temp[2*1+i] + temp[2*3+i]; + + block[stride*0+offset]= ((z0 + z3)*qmul + 128) >> 8; + block[stride*1+offset]= ((z1 + z2)*qmul + 128) >> 8; + block[stride*2+offset]= ((z1 - z2)*qmul + 128) >> 8; + block[stride*3+offset]= ((z0 - z3)*qmul + 128) >> 8; + } +} + +void FUNCC(ff_h264_chroma_dc_dequant_idct)(int16_t *_block, int qmul){ + const int stride= 16*2; + const int xStride= 16; + int a,b,c,d,e; + dctcoef *block = (dctcoef*)_block; + + a= block[stride*0 + xStride*0]; + b= block[stride*0 + xStride*1]; + c= block[stride*1 + xStride*0]; + d= block[stride*1 + xStride*1]; + + e= a-b; + a= a+b; + b= c-d; + c= c+d; + + block[stride*0 + xStride*0]= ((a+c)*qmul) >> 7; + block[stride*0 + xStride*1]= ((e+b)*qmul) >> 7; + block[stride*1 + xStride*0]= ((a-c)*qmul) >> 7; + block[stride*1 + xStride*1]= ((e-b)*qmul) >> 7; +} diff --git a/ffmpeg/libavcodec/h264pred.c b/ffmpeg/libavcodec/h264pred.c new file mode 100644 index 0000000..e5f1f5a --- /dev/null +++ b/ffmpeg/libavcodec/h264pred.c @@ -0,0 +1,593 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 prediction functions. + * @author Michael Niedermayer + */ + +#include "libavutil/avassert.h" +#include "dsputil.h" +#include "h264pred.h" +#include "avcodec.h" // for AV_CODEC_ID_* + +#define BIT_DEPTH 8 +#include "h264pred_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 9 +#include "h264pred_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 10 +#include "h264pred_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 12 +#include "h264pred_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 14 +#include "h264pred_template.c" +#undef BIT_DEPTH + +static void pred4x4_vertical_vp8_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + const unsigned lt = src[-1-1*stride]; + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + uint32_t v = PACK_4U8((lt + 2*t0 + t1 + 2) >> 2, + (t0 + 2*t1 + t2 + 2) >> 2, + (t1 + 2*t2 + t3 + 2) >> 2, + (t2 + 2*t3 + t4 + 2) >> 2); + + AV_WN32A(src+0*stride, v); + AV_WN32A(src+1*stride, v); + AV_WN32A(src+2*stride, v); + AV_WN32A(src+3*stride, v); +} + +static void pred4x4_horizontal_vp8_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + const unsigned lt = src[-1-1*stride]; + LOAD_LEFT_EDGE + + AV_WN32A(src+0*stride, ((lt + 2*l0 + l1 + 2) >> 2)*0x01010101); + AV_WN32A(src+1*stride, ((l0 + 2*l1 + l2 + 2) >> 2)*0x01010101); + AV_WN32A(src+2*stride, ((l1 + 2*l2 + l3 + 2) >> 2)*0x01010101); + AV_WN32A(src+3*stride, ((l2 + 2*l3 + l3 + 2) >> 2)*0x01010101); +} + +static void pred4x4_down_left_svq3_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_TOP_EDGE + LOAD_LEFT_EDGE + + src[0+0*stride]=(l1 + t1)>>1; + src[1+0*stride]= + src[0+1*stride]=(l2 + t2)>>1; + src[2+0*stride]= + src[1+1*stride]= + src[0+2*stride]= + src[3+0*stride]= + src[2+1*stride]= + src[1+2*stride]= + src[0+3*stride]= + src[3+1*stride]= + src[2+2*stride]= + src[1+3*stride]= + src[3+2*stride]= + src[2+3*stride]= + src[3+3*stride]=(l3 + t3)>>1; +} + +static void pred4x4_down_left_rv40_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + LOAD_LEFT_EDGE + LOAD_DOWN_LEFT_EDGE + + src[0+0*stride]=(t0 + t2 + 2*t1 + 2 + l0 + l2 + 2*l1 + 2)>>3; + src[1+0*stride]= + src[0+1*stride]=(t1 + t3 + 2*t2 + 2 + l1 + l3 + 2*l2 + 2)>>3; + src[2+0*stride]= + src[1+1*stride]= + src[0+2*stride]=(t2 + t4 + 2*t3 + 2 + l2 + l4 + 2*l3 + 2)>>3; + src[3+0*stride]= + src[2+1*stride]= + src[1+2*stride]= + src[0+3*stride]=(t3 + t5 + 2*t4 + 2 + l3 + l5 + 2*l4 + 2)>>3; + src[3+1*stride]= + src[2+2*stride]= + src[1+3*stride]=(t4 + t6 + 2*t5 + 2 + l4 + l6 + 2*l5 + 2)>>3; + src[3+2*stride]= + src[2+3*stride]=(t5 + t7 + 2*t6 + 2 + l5 + l7 + 2*l6 + 2)>>3; + src[3+3*stride]=(t6 + t7 + 1 + l6 + l7 + 1)>>2; +} + +static void pred4x4_down_left_rv40_nodown_c(uint8_t *src, + const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + LOAD_LEFT_EDGE + + src[0+0*stride]=(t0 + t2 + 2*t1 + 2 + l0 + l2 + 2*l1 + 2)>>3; + src[1+0*stride]= + src[0+1*stride]=(t1 + t3 + 2*t2 + 2 + l1 + l3 + 2*l2 + 2)>>3; + src[2+0*stride]= + src[1+1*stride]= + src[0+2*stride]=(t2 + t4 + 2*t3 + 2 + l2 + 3*l3 + 2)>>3; + src[3+0*stride]= + src[2+1*stride]= + src[1+2*stride]= + src[0+3*stride]=(t3 + t5 + 2*t4 + 2 + l3*4 + 2)>>3; + src[3+1*stride]= + src[2+2*stride]= + src[1+3*stride]=(t4 + t6 + 2*t5 + 2 + l3*4 + 2)>>3; + src[3+2*stride]= + src[2+3*stride]=(t5 + t7 + 2*t6 + 2 + l3*4 + 2)>>3; + src[3+3*stride]=(t6 + t7 + 1 + 2*l3 + 1)>>2; +} + +static void pred4x4_vertical_left_rv40(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride, + const int l0, const int l1, const int l2, + const int l3, const int l4) +{ + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + + src[0+0*stride]=(2*t0 + 2*t1 + l1 + 2*l2 + l3 + 4)>>3; + src[1+0*stride]= + src[0+2*stride]=(t1 + t2 + 1)>>1; + src[2+0*stride]= + src[1+2*stride]=(t2 + t3 + 1)>>1; + src[3+0*stride]= + src[2+2*stride]=(t3 + t4+ 1)>>1; + src[3+2*stride]=(t4 + t5+ 1)>>1; + src[0+1*stride]=(t0 + 2*t1 + t2 + l2 + 2*l3 + l4 + 4)>>3; + src[1+1*stride]= + src[0+3*stride]=(t1 + 2*t2 + t3 + 2)>>2; + src[2+1*stride]= + src[1+3*stride]=(t2 + 2*t3 + t4 + 2)>>2; + src[3+1*stride]= + src[2+3*stride]=(t3 + 2*t4 + t5 + 2)>>2; + src[3+3*stride]=(t4 + 2*t5 + t6 + 2)>>2; +} + +static void pred4x4_vertical_left_rv40_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_LEFT_EDGE + LOAD_DOWN_LEFT_EDGE + + pred4x4_vertical_left_rv40(src, topright, stride, l0, l1, l2, l3, l4); +} + +static void pred4x4_vertical_left_rv40_nodown_c(uint8_t *src, + const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_LEFT_EDGE + + pred4x4_vertical_left_rv40(src, topright, stride, l0, l1, l2, l3, l3); +} + +static void pred4x4_vertical_left_vp8_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + + src[0+0*stride]=(t0 + t1 + 1)>>1; + src[1+0*stride]= + src[0+2*stride]=(t1 + t2 + 1)>>1; + src[2+0*stride]= + src[1+2*stride]=(t2 + t3 + 1)>>1; + src[3+0*stride]= + src[2+2*stride]=(t3 + t4 + 1)>>1; + src[0+1*stride]=(t0 + 2*t1 + t2 + 2)>>2; + src[1+1*stride]= + src[0+3*stride]=(t1 + 2*t2 + t3 + 2)>>2; + src[2+1*stride]= + src[1+3*stride]=(t2 + 2*t3 + t4 + 2)>>2; + src[3+1*stride]= + src[2+3*stride]=(t3 + 2*t4 + t5 + 2)>>2; + src[3+2*stride]=(t4 + 2*t5 + t6 + 2)>>2; + src[3+3*stride]=(t5 + 2*t6 + t7 + 2)>>2; +} + +static void pred4x4_horizontal_up_rv40_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_LEFT_EDGE + LOAD_DOWN_LEFT_EDGE + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + + src[0+0*stride]=(t1 + 2*t2 + t3 + 2*l0 + 2*l1 + 4)>>3; + src[1+0*stride]=(t2 + 2*t3 + t4 + l0 + 2*l1 + l2 + 4)>>3; + src[2+0*stride]= + src[0+1*stride]=(t3 + 2*t4 + t5 + 2*l1 + 2*l2 + 4)>>3; + src[3+0*stride]= + src[1+1*stride]=(t4 + 2*t5 + t6 + l1 + 2*l2 + l3 + 4)>>3; + src[2+1*stride]= + src[0+2*stride]=(t5 + 2*t6 + t7 + 2*l2 + 2*l3 + 4)>>3; + src[3+1*stride]= + src[1+2*stride]=(t6 + 3*t7 + l2 + 3*l3 + 4)>>3; + src[3+2*stride]= + src[1+3*stride]=(l3 + 2*l4 + l5 + 2)>>2; + src[0+3*stride]= + src[2+2*stride]=(t6 + t7 + l3 + l4 + 2)>>2; + src[2+3*stride]=(l4 + l5 + 1)>>1; + src[3+3*stride]=(l4 + 2*l5 + l6 + 2)>>2; +} + +static void pred4x4_horizontal_up_rv40_nodown_c(uint8_t *src, + const uint8_t *topright, + ptrdiff_t stride) +{ + LOAD_LEFT_EDGE + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + + src[0+0*stride]=(t1 + 2*t2 + t3 + 2*l0 + 2*l1 + 4)>>3; + src[1+0*stride]=(t2 + 2*t3 + t4 + l0 + 2*l1 + l2 + 4)>>3; + src[2+0*stride]= + src[0+1*stride]=(t3 + 2*t4 + t5 + 2*l1 + 2*l2 + 4)>>3; + src[3+0*stride]= + src[1+1*stride]=(t4 + 2*t5 + t6 + l1 + 2*l2 + l3 + 4)>>3; + src[2+1*stride]= + src[0+2*stride]=(t5 + 2*t6 + t7 + 2*l2 + 2*l3 + 4)>>3; + src[3+1*stride]= + src[1+2*stride]=(t6 + 3*t7 + l2 + 3*l3 + 4)>>3; + src[3+2*stride]= + src[1+3*stride]=l3; + src[0+3*stride]= + src[2+2*stride]=(t6 + t7 + 2*l3 + 2)>>2; + src[2+3*stride]= + src[3+3*stride]=l3; +} + +static void pred4x4_tm_vp8_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP - src[-1-stride]; + uint8_t *top = src-stride; + int y; + + for (y = 0; y < 4; y++) { + uint8_t *cm_in = cm + src[-1]; + src[0] = cm_in[top[0]]; + src[1] = cm_in[top[1]]; + src[2] = cm_in[top[2]]; + src[3] = cm_in[top[3]]; + src += stride; + } +} + +static void pred16x16_plane_svq3_c(uint8_t *src, ptrdiff_t stride) +{ + pred16x16_plane_compat_8_c(src, stride, 1, 0); +} + +static void pred16x16_plane_rv40_c(uint8_t *src, ptrdiff_t stride) +{ + pred16x16_plane_compat_8_c(src, stride, 0, 1); +} + +static void pred16x16_tm_vp8_c(uint8_t *src, ptrdiff_t stride) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP - src[-1-stride]; + uint8_t *top = src-stride; + int y; + + for (y = 0; y < 16; y++) { + uint8_t *cm_in = cm + src[-1]; + src[0] = cm_in[top[0]]; + src[1] = cm_in[top[1]]; + src[2] = cm_in[top[2]]; + src[3] = cm_in[top[3]]; + src[4] = cm_in[top[4]]; + src[5] = cm_in[top[5]]; + src[6] = cm_in[top[6]]; + src[7] = cm_in[top[7]]; + src[8] = cm_in[top[8]]; + src[9] = cm_in[top[9]]; + src[10] = cm_in[top[10]]; + src[11] = cm_in[top[11]]; + src[12] = cm_in[top[12]]; + src[13] = cm_in[top[13]]; + src[14] = cm_in[top[14]]; + src[15] = cm_in[top[15]]; + src += stride; + } +} + +static void pred8x8_left_dc_rv40_c(uint8_t *src, ptrdiff_t stride) +{ + int i; + unsigned dc0; + + dc0=0; + for(i=0;i<8; i++) + dc0+= src[-1+i*stride]; + dc0= 0x01010101*((dc0 + 4)>>3); + + for(i=0; i<8; i++){ + ((uint32_t*)(src+i*stride))[0]= + ((uint32_t*)(src+i*stride))[1]= dc0; + } +} + +static void pred8x8_top_dc_rv40_c(uint8_t *src, ptrdiff_t stride) +{ + int i; + unsigned dc0; + + dc0=0; + for(i=0;i<8; i++) + dc0+= src[i-stride]; + dc0= 0x01010101*((dc0 + 4)>>3); + + for(i=0; i<8; i++){ + ((uint32_t*)(src+i*stride))[0]= + ((uint32_t*)(src+i*stride))[1]= dc0; + } +} + +static void pred8x8_dc_rv40_c(uint8_t *src, ptrdiff_t stride) +{ + int i; + unsigned dc0 = 0; + + for(i=0;i<4; i++){ + dc0+= src[-1+i*stride] + src[i-stride]; + dc0+= src[4+i-stride]; + dc0+= src[-1+(i+4)*stride]; + } + dc0= 0x01010101*((dc0 + 8)>>4); + + for(i=0; i<4; i++){ + ((uint32_t*)(src+i*stride))[0]= dc0; + ((uint32_t*)(src+i*stride))[1]= dc0; + } + for(i=4; i<8; i++){ + ((uint32_t*)(src+i*stride))[0]= dc0; + ((uint32_t*)(src+i*stride))[1]= dc0; + } +} + +static void pred8x8_tm_vp8_c(uint8_t *src, ptrdiff_t stride) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP - src[-1-stride]; + uint8_t *top = src-stride; + int y; + + for (y = 0; y < 8; y++) { + uint8_t *cm_in = cm + src[-1]; + src[0] = cm_in[top[0]]; + src[1] = cm_in[top[1]]; + src[2] = cm_in[top[2]]; + src[3] = cm_in[top[3]]; + src[4] = cm_in[top[4]]; + src[5] = cm_in[top[5]]; + src[6] = cm_in[top[6]]; + src[7] = cm_in[top[7]]; + src += stride; + } +} + +/** + * Set the intra prediction function pointers. + */ +void ff_h264_pred_init(H264PredContext *h, int codec_id, const int bit_depth, + int chroma_format_idc) +{ +#undef FUNC +#undef FUNCC +#define FUNC(a, depth) a ## _ ## depth +#define FUNCC(a, depth) a ## _ ## depth ## _c +#define FUNCD(a) a ## _c + +#define H264_PRED(depth) \ + if(codec_id != AV_CODEC_ID_RV40){\ + if(codec_id == AV_CODEC_ID_VP8) {\ + h->pred4x4[VERT_PRED ]= FUNCD(pred4x4_vertical_vp8);\ + h->pred4x4[HOR_PRED ]= FUNCD(pred4x4_horizontal_vp8);\ + } else {\ + h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ + h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ + }\ + h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ + if(codec_id == AV_CODEC_ID_SVQ3)\ + h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCD(pred4x4_down_left_svq3);\ + else\ + h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCC(pred4x4_down_left , depth);\ + h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ + h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ + h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ + if (codec_id == AV_CODEC_ID_VP8) {\ + h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_vp8);\ + } else\ + h->pred4x4[VERT_LEFT_PRED ]= FUNCC(pred4x4_vertical_left , depth);\ + h->pred4x4[HOR_UP_PRED ]= FUNCC(pred4x4_horizontal_up , depth);\ + if(codec_id != AV_CODEC_ID_VP8) {\ + h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ + h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ + h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ + } else {\ + h->pred4x4[TM_VP8_PRED ]= FUNCD(pred4x4_tm_vp8);\ + h->pred4x4[DC_127_PRED ]= FUNCC(pred4x4_127_dc , depth);\ + h->pred4x4[DC_129_PRED ]= FUNCC(pred4x4_129_dc , depth);\ + h->pred4x4[VERT_VP8_PRED ]= FUNCC(pred4x4_vertical , depth);\ + h->pred4x4[HOR_VP8_PRED ]= FUNCC(pred4x4_horizontal , depth);\ + }\ + }else{\ + h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ + h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ + h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ + h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCD(pred4x4_down_left_rv40);\ + h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ + h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ + h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ + h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_rv40);\ + h->pred4x4[HOR_UP_PRED ]= FUNCD(pred4x4_horizontal_up_rv40);\ + h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ + h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ + h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ + h->pred4x4[DIAG_DOWN_LEFT_PRED_RV40_NODOWN]= FUNCD(pred4x4_down_left_rv40_nodown);\ + h->pred4x4[HOR_UP_PRED_RV40_NODOWN]= FUNCD(pred4x4_horizontal_up_rv40_nodown);\ + h->pred4x4[VERT_LEFT_PRED_RV40_NODOWN]= FUNCD(pred4x4_vertical_left_rv40_nodown);\ + }\ +\ + h->pred8x8l[VERT_PRED ]= FUNCC(pred8x8l_vertical , depth);\ + h->pred8x8l[HOR_PRED ]= FUNCC(pred8x8l_horizontal , depth);\ + h->pred8x8l[DC_PRED ]= FUNCC(pred8x8l_dc , depth);\ + h->pred8x8l[DIAG_DOWN_LEFT_PRED ]= FUNCC(pred8x8l_down_left , depth);\ + h->pred8x8l[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred8x8l_down_right , depth);\ + h->pred8x8l[VERT_RIGHT_PRED ]= FUNCC(pred8x8l_vertical_right , depth);\ + h->pred8x8l[HOR_DOWN_PRED ]= FUNCC(pred8x8l_horizontal_down , depth);\ + h->pred8x8l[VERT_LEFT_PRED ]= FUNCC(pred8x8l_vertical_left , depth);\ + h->pred8x8l[HOR_UP_PRED ]= FUNCC(pred8x8l_horizontal_up , depth);\ + h->pred8x8l[LEFT_DC_PRED ]= FUNCC(pred8x8l_left_dc , depth);\ + h->pred8x8l[TOP_DC_PRED ]= FUNCC(pred8x8l_top_dc , depth);\ + h->pred8x8l[DC_128_PRED ]= FUNCC(pred8x8l_128_dc , depth);\ +\ + if (chroma_format_idc == 1) {\ + h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x8_vertical , depth);\ + h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x8_horizontal , depth);\ + } else {\ + h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x16_vertical , depth);\ + h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x16_horizontal , depth);\ + }\ + if (codec_id != AV_CODEC_ID_VP8) {\ + if (chroma_format_idc == 1) {\ + h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x8_plane , depth);\ + } else {\ + h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x16_plane , depth);\ + }\ + } else\ + h->pred8x8[PLANE_PRED8x8]= FUNCD(pred8x8_tm_vp8);\ + if(codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP8){\ + if (chroma_format_idc == 1) {\ + h->pred8x8[DC_PRED8x8 ]= FUNCC(pred8x8_dc , depth);\ + h->pred8x8[LEFT_DC_PRED8x8]= FUNCC(pred8x8_left_dc , depth);\ + h->pred8x8[TOP_DC_PRED8x8 ]= FUNCC(pred8x8_top_dc , depth);\ + h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8 ]= FUNC(pred8x8_mad_cow_dc_l0t, depth);\ + h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8 ]= FUNC(pred8x8_mad_cow_dc_0lt, depth);\ + h->pred8x8[ALZHEIMER_DC_L00_PRED8x8 ]= FUNC(pred8x8_mad_cow_dc_l00, depth);\ + h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8 ]= FUNC(pred8x8_mad_cow_dc_0l0, depth);\ + } else {\ + h->pred8x8[DC_PRED8x8 ]= FUNCC(pred8x16_dc , depth);\ + h->pred8x8[LEFT_DC_PRED8x8]= FUNCC(pred8x16_left_dc , depth);\ + h->pred8x8[TOP_DC_PRED8x8 ]= FUNCC(pred8x16_top_dc , depth);\ + h->pred8x8[ALZHEIMER_DC_L0T_PRED8x8 ]= FUNC(pred8x16_mad_cow_dc_l0t, depth);\ + h->pred8x8[ALZHEIMER_DC_0LT_PRED8x8 ]= FUNC(pred8x16_mad_cow_dc_0lt, depth);\ + h->pred8x8[ALZHEIMER_DC_L00_PRED8x8 ]= FUNC(pred8x16_mad_cow_dc_l00, depth);\ + h->pred8x8[ALZHEIMER_DC_0L0_PRED8x8 ]= FUNC(pred8x16_mad_cow_dc_0l0, depth);\ + }\ + }else{\ + h->pred8x8[DC_PRED8x8 ]= FUNCD(pred8x8_dc_rv40);\ + h->pred8x8[LEFT_DC_PRED8x8]= FUNCD(pred8x8_left_dc_rv40);\ + h->pred8x8[TOP_DC_PRED8x8 ]= FUNCD(pred8x8_top_dc_rv40);\ + if (codec_id == AV_CODEC_ID_VP8) {\ + h->pred8x8[DC_127_PRED8x8]= FUNCC(pred8x8_127_dc , depth);\ + h->pred8x8[DC_129_PRED8x8]= FUNCC(pred8x8_129_dc , depth);\ + }\ + }\ + if (chroma_format_idc == 1) {\ + h->pred8x8[DC_128_PRED8x8 ]= FUNCC(pred8x8_128_dc , depth);\ + } else {\ + h->pred8x8[DC_128_PRED8x8 ]= FUNCC(pred8x16_128_dc , depth);\ + }\ +\ + h->pred16x16[DC_PRED8x8 ]= FUNCC(pred16x16_dc , depth);\ + h->pred16x16[VERT_PRED8x8 ]= FUNCC(pred16x16_vertical , depth);\ + h->pred16x16[HOR_PRED8x8 ]= FUNCC(pred16x16_horizontal , depth);\ + switch(codec_id){\ + case AV_CODEC_ID_SVQ3:\ + h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_svq3);\ + break;\ + case AV_CODEC_ID_RV40:\ + h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_rv40);\ + break;\ + case AV_CODEC_ID_VP8:\ + h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_tm_vp8);\ + h->pred16x16[DC_127_PRED8x8]= FUNCC(pred16x16_127_dc , depth);\ + h->pred16x16[DC_129_PRED8x8]= FUNCC(pred16x16_129_dc , depth);\ + break;\ + default:\ + h->pred16x16[PLANE_PRED8x8 ]= FUNCC(pred16x16_plane , depth);\ + break;\ + }\ + h->pred16x16[LEFT_DC_PRED8x8]= FUNCC(pred16x16_left_dc , depth);\ + h->pred16x16[TOP_DC_PRED8x8 ]= FUNCC(pred16x16_top_dc , depth);\ + h->pred16x16[DC_128_PRED8x8 ]= FUNCC(pred16x16_128_dc , depth);\ +\ + /* special lossless h/v prediction for h264 */ \ + h->pred4x4_add [VERT_PRED ]= FUNCC(pred4x4_vertical_add , depth);\ + h->pred4x4_add [ HOR_PRED ]= FUNCC(pred4x4_horizontal_add , depth);\ + h->pred8x8l_add [VERT_PRED ]= FUNCC(pred8x8l_vertical_add , depth);\ + h->pred8x8l_add [ HOR_PRED ]= FUNCC(pred8x8l_horizontal_add , depth);\ + if (chroma_format_idc == 1) {\ + h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x8_vertical_add , depth);\ + h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x8_horizontal_add , depth);\ + } else {\ + h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x16_vertical_add , depth);\ + h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x16_horizontal_add , depth);\ + }\ + h->pred16x16_add[VERT_PRED8x8]= FUNCC(pred16x16_vertical_add , depth);\ + h->pred16x16_add[ HOR_PRED8x8]= FUNCC(pred16x16_horizontal_add , depth);\ + + if(!chroma_format_idc) + chroma_format_idc = 1; + + switch (bit_depth) { + case 9: + H264_PRED(9) + break; + case 10: + H264_PRED(10) + break; + case 12: + H264_PRED(12) + break; + case 14: + H264_PRED(14) + break; + default: + av_assert0(bit_depth<=8); + H264_PRED(8) + break; + } + + if (ARCH_ARM) ff_h264_pred_init_arm(h, codec_id, bit_depth, chroma_format_idc); + if (ARCH_X86) ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc); +} diff --git a/ffmpeg/libavcodec/h264pred.h b/ffmpeg/libavcodec/h264pred.h new file mode 100644 index 0000000..ed67d2e --- /dev/null +++ b/ffmpeg/libavcodec/h264pred.h @@ -0,0 +1,119 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 prediction functions. + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_H264PRED_H +#define AVCODEC_H264PRED_H + +#include +#include + +/** + * Prediction types + */ +//@{ +#define VERT_PRED 0 +#define HOR_PRED 1 +#define DC_PRED 2 +#define DIAG_DOWN_LEFT_PRED 3 +#define DIAG_DOWN_RIGHT_PRED 4 +#define VERT_RIGHT_PRED 5 +#define HOR_DOWN_PRED 6 +#define VERT_LEFT_PRED 7 +#define HOR_UP_PRED 8 + +// DC edge (not for VP8) +#define LEFT_DC_PRED 9 +#define TOP_DC_PRED 10 +#define DC_128_PRED 11 + +// RV40 specific +#define DIAG_DOWN_LEFT_PRED_RV40_NODOWN 12 +#define HOR_UP_PRED_RV40_NODOWN 13 +#define VERT_LEFT_PRED_RV40_NODOWN 14 + +// VP8 specific +#define TM_VP8_PRED 9 ///< "True Motion", used instead of plane +#define VERT_VP8_PRED 10 ///< for VP8, #VERT_PRED is the average of + ///< (left col+cur col x2+right col) / 4; + ///< this is the "unaveraged" one +#define HOR_VP8_PRED 11 ///< unaveraged version of #HOR_PRED, see + ///< #VERT_VP8_PRED for details +#define DC_127_PRED 12 +#define DC_129_PRED 13 + +#define DC_PRED8x8 0 +#define HOR_PRED8x8 1 +#define VERT_PRED8x8 2 +#define PLANE_PRED8x8 3 + +// DC edge +#define LEFT_DC_PRED8x8 4 +#define TOP_DC_PRED8x8 5 +#define DC_128_PRED8x8 6 + +// H264/SVQ3 (8x8) specific +#define ALZHEIMER_DC_L0T_PRED8x8 7 +#define ALZHEIMER_DC_0LT_PRED8x8 8 +#define ALZHEIMER_DC_L00_PRED8x8 9 +#define ALZHEIMER_DC_0L0_PRED8x8 10 + +// VP8 specific +#define DC_127_PRED8x8 7 +#define DC_129_PRED8x8 8 +//@} + +/** + * Context for storing H.264 prediction functions + */ +typedef struct H264PredContext { + void(*pred4x4[9 + 3 + 3])(uint8_t *src, const uint8_t *topright, + ptrdiff_t stride); + void(*pred8x8l[9 + 3])(uint8_t *src, int topleft, int topright, + ptrdiff_t stride); + void(*pred8x8[4 + 3 + 4])(uint8_t *src, ptrdiff_t stride); + void(*pred16x16[4 + 3 + 2])(uint8_t *src, ptrdiff_t stride); + + void(*pred4x4_add[2])(uint8_t *pix /*align 4*/, + int16_t *block /*align 16*/, ptrdiff_t stride); + void(*pred8x8l_add[2])(uint8_t *pix /*align 8*/, + int16_t *block /*align 16*/, ptrdiff_t stride); + void(*pred8x8_add[3])(uint8_t *pix /*align 8*/, + const int *block_offset, + int16_t *block /*align 16*/, ptrdiff_t stride); + void(*pred16x16_add[3])(uint8_t *pix /*align 16*/, + const int *block_offset, + int16_t *block /*align 16*/, ptrdiff_t stride); +} H264PredContext; + +void ff_h264_pred_init(H264PredContext *h, int codec_id, + const int bit_depth, const int chroma_format_idc); +void ff_h264_pred_init_arm(H264PredContext *h, int codec_id, + const int bit_depth, const int chroma_format_idc); +void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, + const int bit_depth, const int chroma_format_idc); + +#endif /* AVCODEC_H264PRED_H */ diff --git a/ffmpeg/libavcodec/h264pred_template.c b/ffmpeg/libavcodec/h264pred_template.c new file mode 100644 index 0000000..8d8d62e --- /dev/null +++ b/ffmpeg/libavcodec/h264pred_template.c @@ -0,0 +1,1280 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2011 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 prediction functions. + * @author Michael Niedermayer + */ + +#include "mathops.h" + +#include "bit_depth_template.c" + +static void FUNCC(pred4x4_vertical)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a= AV_RN4PA(src-stride); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + +static void FUNCC(pred4x4_horizontal)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + AV_WN4PA(src+0*stride, PIXEL_SPLAT_X4(src[-1+0*stride])); + AV_WN4PA(src+1*stride, PIXEL_SPLAT_X4(src[-1+1*stride])); + AV_WN4PA(src+2*stride, PIXEL_SPLAT_X4(src[-1+2*stride])); + AV_WN4PA(src+3*stride, PIXEL_SPLAT_X4(src[-1+3*stride])); +} + +static void FUNCC(pred4x4_dc)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const int dc= ( src[-stride] + src[1-stride] + src[2-stride] + src[3-stride] + + src[-1+0*stride] + src[-1+1*stride] + src[-1+2*stride] + src[-1+3*stride] + 4) >>3; + const pixel4 a = PIXEL_SPLAT_X4(dc); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + +static void FUNCC(pred4x4_left_dc)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const int dc= ( src[-1+0*stride] + src[-1+1*stride] + src[-1+2*stride] + src[-1+3*stride] + 2) >>2; + const pixel4 a = PIXEL_SPLAT_X4(dc); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + +static void FUNCC(pred4x4_top_dc)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const int dc= ( src[-stride] + src[1-stride] + src[2-stride] + src[3-stride] + 2) >>2; + const pixel4 a = PIXEL_SPLAT_X4(dc); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + +static void FUNCC(pred4x4_128_dc)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a = PIXEL_SPLAT_X4(1<<(BIT_DEPTH-1)); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + +static void FUNCC(pred4x4_127_dc)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a = PIXEL_SPLAT_X4((1<<(BIT_DEPTH-1))-1); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + +static void FUNCC(pred4x4_129_dc)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a = PIXEL_SPLAT_X4((1<<(BIT_DEPTH-1))+1); + + AV_WN4PA(src+0*stride, a); + AV_WN4PA(src+1*stride, a); + AV_WN4PA(src+2*stride, a); + AV_WN4PA(src+3*stride, a); +} + + +#define LOAD_TOP_RIGHT_EDGE\ + const unsigned av_unused t4 = topright[0];\ + const unsigned av_unused t5 = topright[1];\ + const unsigned av_unused t6 = topright[2];\ + const unsigned av_unused t7 = topright[3];\ + +#define LOAD_DOWN_LEFT_EDGE\ + const unsigned av_unused l4 = src[-1+4*stride];\ + const unsigned av_unused l5 = src[-1+5*stride];\ + const unsigned av_unused l6 = src[-1+6*stride];\ + const unsigned av_unused l7 = src[-1+7*stride];\ + +#define LOAD_LEFT_EDGE\ + const unsigned av_unused l0 = src[-1+0*stride];\ + const unsigned av_unused l1 = src[-1+1*stride];\ + const unsigned av_unused l2 = src[-1+2*stride];\ + const unsigned av_unused l3 = src[-1+3*stride];\ + +#define LOAD_TOP_EDGE\ + const unsigned av_unused t0 = src[ 0-1*stride];\ + const unsigned av_unused t1 = src[ 1-1*stride];\ + const unsigned av_unused t2 = src[ 2-1*stride];\ + const unsigned av_unused t3 = src[ 3-1*stride];\ + +static void FUNCC(pred4x4_down_right)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const int lt= src[-1-1*stride]; + LOAD_TOP_EDGE + LOAD_LEFT_EDGE + + src[0+3*stride]=(l3 + 2*l2 + l1 + 2)>>2; + src[0+2*stride]= + src[1+3*stride]=(l2 + 2*l1 + l0 + 2)>>2; + src[0+1*stride]= + src[1+2*stride]= + src[2+3*stride]=(l1 + 2*l0 + lt + 2)>>2; + src[0+0*stride]= + src[1+1*stride]= + src[2+2*stride]= + src[3+3*stride]=(l0 + 2*lt + t0 + 2)>>2; + src[1+0*stride]= + src[2+1*stride]= + src[3+2*stride]=(lt + 2*t0 + t1 + 2)>>2; + src[2+0*stride]= + src[3+1*stride]=(t0 + 2*t1 + t2 + 2)>>2; + src[3+0*stride]=(t1 + 2*t2 + t3 + 2)>>2; +} + +static void FUNCC(pred4x4_down_left)(uint8_t *_src, const uint8_t *_topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + const pixel *topright = (const pixel*)_topright; + int stride = _stride>>(sizeof(pixel)-1); + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE +// LOAD_LEFT_EDGE + + src[0+0*stride]=(t0 + t2 + 2*t1 + 2)>>2; + src[1+0*stride]= + src[0+1*stride]=(t1 + t3 + 2*t2 + 2)>>2; + src[2+0*stride]= + src[1+1*stride]= + src[0+2*stride]=(t2 + t4 + 2*t3 + 2)>>2; + src[3+0*stride]= + src[2+1*stride]= + src[1+2*stride]= + src[0+3*stride]=(t3 + t5 + 2*t4 + 2)>>2; + src[3+1*stride]= + src[2+2*stride]= + src[1+3*stride]=(t4 + t6 + 2*t5 + 2)>>2; + src[3+2*stride]= + src[2+3*stride]=(t5 + t7 + 2*t6 + 2)>>2; + src[3+3*stride]=(t6 + 3*t7 + 2)>>2; +} + +static void FUNCC(pred4x4_vertical_right)(uint8_t *_src, + const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const int lt= src[-1-1*stride]; + LOAD_TOP_EDGE + LOAD_LEFT_EDGE + + src[0+0*stride]= + src[1+2*stride]=(lt + t0 + 1)>>1; + src[1+0*stride]= + src[2+2*stride]=(t0 + t1 + 1)>>1; + src[2+0*stride]= + src[3+2*stride]=(t1 + t2 + 1)>>1; + src[3+0*stride]=(t2 + t3 + 1)>>1; + src[0+1*stride]= + src[1+3*stride]=(l0 + 2*lt + t0 + 2)>>2; + src[1+1*stride]= + src[2+3*stride]=(lt + 2*t0 + t1 + 2)>>2; + src[2+1*stride]= + src[3+3*stride]=(t0 + 2*t1 + t2 + 2)>>2; + src[3+1*stride]=(t1 + 2*t2 + t3 + 2)>>2; + src[0+2*stride]=(lt + 2*l0 + l1 + 2)>>2; + src[0+3*stride]=(l0 + 2*l1 + l2 + 2)>>2; +} + +static void FUNCC(pred4x4_vertical_left)(uint8_t *_src, + const uint8_t *_topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + const pixel *topright = (const pixel*)_topright; + int stride = _stride>>(sizeof(pixel)-1); + LOAD_TOP_EDGE + LOAD_TOP_RIGHT_EDGE + + src[0+0*stride]=(t0 + t1 + 1)>>1; + src[1+0*stride]= + src[0+2*stride]=(t1 + t2 + 1)>>1; + src[2+0*stride]= + src[1+2*stride]=(t2 + t3 + 1)>>1; + src[3+0*stride]= + src[2+2*stride]=(t3 + t4+ 1)>>1; + src[3+2*stride]=(t4 + t5+ 1)>>1; + src[0+1*stride]=(t0 + 2*t1 + t2 + 2)>>2; + src[1+1*stride]= + src[0+3*stride]=(t1 + 2*t2 + t3 + 2)>>2; + src[2+1*stride]= + src[1+3*stride]=(t2 + 2*t3 + t4 + 2)>>2; + src[3+1*stride]= + src[2+3*stride]=(t3 + 2*t4 + t5 + 2)>>2; + src[3+3*stride]=(t4 + 2*t5 + t6 + 2)>>2; +} + +static void FUNCC(pred4x4_horizontal_up)(uint8_t *_src, const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + LOAD_LEFT_EDGE + + src[0+0*stride]=(l0 + l1 + 1)>>1; + src[1+0*stride]=(l0 + 2*l1 + l2 + 2)>>2; + src[2+0*stride]= + src[0+1*stride]=(l1 + l2 + 1)>>1; + src[3+0*stride]= + src[1+1*stride]=(l1 + 2*l2 + l3 + 2)>>2; + src[2+1*stride]= + src[0+2*stride]=(l2 + l3 + 1)>>1; + src[3+1*stride]= + src[1+2*stride]=(l2 + 2*l3 + l3 + 2)>>2; + src[3+2*stride]= + src[1+3*stride]= + src[0+3*stride]= + src[2+2*stride]= + src[2+3*stride]= + src[3+3*stride]=l3; +} + +static void FUNCC(pred4x4_horizontal_down)(uint8_t *_src, + const uint8_t *topright, + ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const int lt= src[-1-1*stride]; + LOAD_TOP_EDGE + LOAD_LEFT_EDGE + + src[0+0*stride]= + src[2+1*stride]=(lt + l0 + 1)>>1; + src[1+0*stride]= + src[3+1*stride]=(l0 + 2*lt + t0 + 2)>>2; + src[2+0*stride]=(lt + 2*t0 + t1 + 2)>>2; + src[3+0*stride]=(t0 + 2*t1 + t2 + 2)>>2; + src[0+1*stride]= + src[2+2*stride]=(l0 + l1 + 1)>>1; + src[1+1*stride]= + src[3+2*stride]=(lt + 2*l0 + l1 + 2)>>2; + src[0+2*stride]= + src[2+3*stride]=(l1 + l2+ 1)>>1; + src[1+2*stride]= + src[3+3*stride]=(l0 + 2*l1 + l2 + 2)>>2; + src[0+3*stride]=(l2 + l3 + 1)>>1; + src[1+3*stride]=(l1 + 2*l2 + l3 + 2)>>2; +} + +static void FUNCC(pred16x16_vertical)(uint8_t *_src, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a = AV_RN4PA(((pixel4*)(src-stride))+0); + const pixel4 b = AV_RN4PA(((pixel4*)(src-stride))+1); + const pixel4 c = AV_RN4PA(((pixel4*)(src-stride))+2); + const pixel4 d = AV_RN4PA(((pixel4*)(src-stride))+3); + + for(i=0; i<16; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, a); + AV_WN4PA(((pixel4*)(src+i*stride))+1, b); + AV_WN4PA(((pixel4*)(src+i*stride))+2, c); + AV_WN4PA(((pixel4*)(src+i*stride))+3, d); + } +} + +static void FUNCC(pred16x16_horizontal)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + for(i=0; i<16; i++){ + const pixel4 a = PIXEL_SPLAT_X4(src[-1+i*stride]); + + AV_WN4PA(((pixel4*)(src+i*stride))+0, a); + AV_WN4PA(((pixel4*)(src+i*stride))+1, a); + AV_WN4PA(((pixel4*)(src+i*stride))+2, a); + AV_WN4PA(((pixel4*)(src+i*stride))+3, a); + } +} + +#define PREDICT_16x16_DC(v)\ + for(i=0; i<16; i++){\ + AV_WN4PA(src+ 0, v);\ + AV_WN4PA(src+ 4, v);\ + AV_WN4PA(src+ 8, v);\ + AV_WN4PA(src+12, v);\ + src += stride;\ + } + +static void FUNCC(pred16x16_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i, dc=0; + pixel *src = (pixel*)_src; + pixel4 dcsplat; + stride >>= sizeof(pixel)-1; + + for(i=0;i<16; i++){ + dc+= src[-1+i*stride]; + } + + for(i=0;i<16; i++){ + dc+= src[i-stride]; + } + + dcsplat = PIXEL_SPLAT_X4((dc+16)>>5); + PREDICT_16x16_DC(dcsplat); +} + +static void FUNCC(pred16x16_left_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i, dc=0; + pixel *src = (pixel*)_src; + pixel4 dcsplat; + stride >>= sizeof(pixel)-1; + + for(i=0;i<16; i++){ + dc+= src[-1+i*stride]; + } + + dcsplat = PIXEL_SPLAT_X4((dc+8)>>4); + PREDICT_16x16_DC(dcsplat); +} + +static void FUNCC(pred16x16_top_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i, dc=0; + pixel *src = (pixel*)_src; + pixel4 dcsplat; + stride >>= sizeof(pixel)-1; + + for(i=0;i<16; i++){ + dc+= src[i-stride]; + } + + dcsplat = PIXEL_SPLAT_X4((dc+8)>>4); + PREDICT_16x16_DC(dcsplat); +} + +#define PRED16x16_X(n, v) \ +static void FUNCC(pred16x16_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\ +{\ + int i;\ + pixel *src = (pixel*)_src;\ + stride >>= sizeof(pixel)-1;\ + PREDICT_16x16_DC(PIXEL_SPLAT_X4(v));\ +} + +PRED16x16_X(127, (1<<(BIT_DEPTH-1))-1) +PRED16x16_X(128, (1<<(BIT_DEPTH-1))+0) +PRED16x16_X(129, (1<<(BIT_DEPTH-1))+1) + +static inline void FUNCC(pred16x16_plane_compat)(uint8_t *_src, + ptrdiff_t _stride, + const int svq3, + const int rv40) +{ + int i, j, k; + int a; + INIT_CLIP + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel * const src0 = src +7-stride; + const pixel * src1 = src +8*stride-1; + const pixel * src2 = src1-2*stride; // == src+6*stride-1; + int H = src0[1] - src0[-1]; + int V = src1[0] - src2[ 0]; + for(k=2; k<=8; ++k) { + src1 += stride; src2 -= stride; + H += k*(src0[k] - src0[-k]); + V += k*(src1[0] - src2[ 0]); + } + if(svq3){ + H = ( 5*(H/4) ) / 16; + V = ( 5*(V/4) ) / 16; + + /* required for 100% accuracy */ + i = H; H = V; V = i; + }else if(rv40){ + H = ( H + (H>>2) ) >> 4; + V = ( V + (V>>2) ) >> 4; + }else{ + H = ( 5*H+32 ) >> 6; + V = ( 5*V+32 ) >> 6; + } + + a = 16*(src1[0] + src2[16] + 1) - 7*(V+H); + for(j=16; j>0; --j) { + int b = a; + a += V; + for(i=-16; i<0; i+=4) { + src[16+i] = CLIP((b ) >> 5); + src[17+i] = CLIP((b+ H) >> 5); + src[18+i] = CLIP((b+2*H) >> 5); + src[19+i] = CLIP((b+3*H) >> 5); + b += 4*H; + } + src += stride; + } +} + +static void FUNCC(pred16x16_plane)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred16x16_plane_compat)(src, stride, 0, 0); +} + +static void FUNCC(pred8x8_vertical)(uint8_t *_src, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a= AV_RN4PA(((pixel4*)(src-stride))+0); + const pixel4 b= AV_RN4PA(((pixel4*)(src-stride))+1); + + for(i=0; i<8; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, a); + AV_WN4PA(((pixel4*)(src+i*stride))+1, b); + } +} + +static void FUNCC(pred8x16_vertical)(uint8_t *_src, ptrdiff_t _stride) +{ + int i; + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel4 a= AV_RN4PA(((pixel4*)(src-stride))+0); + const pixel4 b= AV_RN4PA(((pixel4*)(src-stride))+1); + + for(i=0; i<16; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, a); + AV_WN4PA(((pixel4*)(src+i*stride))+1, b); + } +} + +static void FUNCC(pred8x8_horizontal)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + for(i=0; i<8; i++){ + const pixel4 a = PIXEL_SPLAT_X4(src[-1+i*stride]); + AV_WN4PA(((pixel4*)(src+i*stride))+0, a); + AV_WN4PA(((pixel4*)(src+i*stride))+1, a); + } +} + +static void FUNCC(pred8x16_horizontal)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + for(i=0; i<16; i++){ + const pixel4 a = PIXEL_SPLAT_X4(src[-1+i*stride]); + AV_WN4PA(((pixel4*)(src+i*stride))+0, a); + AV_WN4PA(((pixel4*)(src+i*stride))+1, a); + } +} + +#define PRED8x8_X(n, v)\ +static void FUNCC(pred8x8_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\ +{\ + int i;\ + const pixel4 a = PIXEL_SPLAT_X4(v);\ + pixel *src = (pixel*)_src;\ + stride >>= sizeof(pixel)-1;\ + for(i=0; i<8; i++){\ + AV_WN4PA(((pixel4*)(src+i*stride))+0, a);\ + AV_WN4PA(((pixel4*)(src+i*stride))+1, a);\ + }\ +} + +PRED8x8_X(127, (1<<(BIT_DEPTH-1))-1) +PRED8x8_X(128, (1<<(BIT_DEPTH-1))+0) +PRED8x8_X(129, (1<<(BIT_DEPTH-1))+1) + +static void FUNCC(pred8x16_128_dc)(uint8_t *_src, ptrdiff_t stride) +{ + FUNCC(pred8x8_128_dc)(_src, stride); + FUNCC(pred8x8_128_dc)(_src+8*stride, stride); +} + +static void FUNCC(pred8x8_left_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + int dc0, dc2; + pixel4 dc0splat, dc2splat; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + dc0=dc2=0; + for(i=0;i<4; i++){ + dc0+= src[-1+i*stride]; + dc2+= src[-1+(i+4)*stride]; + } + dc0splat = PIXEL_SPLAT_X4((dc0 + 2)>>2); + dc2splat = PIXEL_SPLAT_X4((dc2 + 2)>>2); + + for(i=0; i<4; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc0splat); + } + for(i=4; i<8; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc2splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc2splat); + } +} + +static void FUNCC(pred8x16_left_dc)(uint8_t *_src, ptrdiff_t stride) +{ + FUNCC(pred8x8_left_dc)(_src, stride); + FUNCC(pred8x8_left_dc)(_src+8*stride, stride); +} + +static void FUNCC(pred8x8_top_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + int dc0, dc1; + pixel4 dc0splat, dc1splat; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + dc0=dc1=0; + for(i=0;i<4; i++){ + dc0+= src[i-stride]; + dc1+= src[4+i-stride]; + } + dc0splat = PIXEL_SPLAT_X4((dc0 + 2)>>2); + dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2); + + for(i=0; i<4; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat); + } + for(i=4; i<8; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat); + } +} + +static void FUNCC(pred8x16_top_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + int dc0, dc1; + pixel4 dc0splat, dc1splat; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + dc0=dc1=0; + for(i=0;i<4; i++){ + dc0+= src[i-stride]; + dc1+= src[4+i-stride]; + } + dc0splat = PIXEL_SPLAT_X4((dc0 + 2)>>2); + dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2); + + for(i=0; i<16; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat); + } +} + +static void FUNCC(pred8x8_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + int dc0, dc1, dc2; + pixel4 dc0splat, dc1splat, dc2splat, dc3splat; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + dc0=dc1=dc2=0; + for(i=0;i<4; i++){ + dc0+= src[-1+i*stride] + src[i-stride]; + dc1+= src[4+i-stride]; + dc2+= src[-1+(i+4)*stride]; + } + dc0splat = PIXEL_SPLAT_X4((dc0 + 4)>>3); + dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2); + dc2splat = PIXEL_SPLAT_X4((dc2 + 2)>>2); + dc3splat = PIXEL_SPLAT_X4((dc1 + dc2 + 4)>>3); + + for(i=0; i<4; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat); + } + for(i=4; i<8; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc2splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc3splat); + } +} + +static void FUNCC(pred8x16_dc)(uint8_t *_src, ptrdiff_t stride) +{ + int i; + int dc0, dc1, dc2, dc3, dc4; + pixel4 dc0splat, dc1splat, dc2splat, dc3splat, dc4splat, dc5splat, dc6splat, dc7splat; + pixel *src = (pixel*)_src; + stride >>= sizeof(pixel)-1; + + dc0=dc1=dc2=dc3=dc4=0; + for(i=0;i<4; i++){ + dc0+= src[-1+i*stride] + src[i-stride]; + dc1+= src[4+i-stride]; + dc2+= src[-1+(i+4)*stride]; + dc3+= src[-1+(i+8)*stride]; + dc4+= src[-1+(i+12)*stride]; + } + dc0splat = PIXEL_SPLAT_X4((dc0 + 4)>>3); + dc1splat = PIXEL_SPLAT_X4((dc1 + 2)>>2); + dc2splat = PIXEL_SPLAT_X4((dc2 + 2)>>2); + dc3splat = PIXEL_SPLAT_X4((dc1 + dc2 + 4)>>3); + dc4splat = PIXEL_SPLAT_X4((dc3 + 2)>>2); + dc5splat = PIXEL_SPLAT_X4((dc1 + dc3 + 4)>>3); + dc6splat = PIXEL_SPLAT_X4((dc4 + 2)>>2); + dc7splat = PIXEL_SPLAT_X4((dc1 + dc4 + 4)>>3); + + for(i=0; i<4; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc0splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc1splat); + } + for(i=4; i<8; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc2splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc3splat); + } + for(i=8; i<12; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc4splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc5splat); + } + for(i=12; i<16; i++){ + AV_WN4PA(((pixel4*)(src+i*stride))+0, dc6splat); + AV_WN4PA(((pixel4*)(src+i*stride))+1, dc7splat); + } +} + +//the following 4 function should not be optimized! +static void FUNC(pred8x8_mad_cow_dc_l0t)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x8_top_dc)(src, stride); + FUNCC(pred4x4_dc)(src, NULL, stride); +} + +static void FUNC(pred8x16_mad_cow_dc_l0t)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x16_top_dc)(src, stride); + FUNCC(pred4x4_dc)(src, NULL, stride); +} + +static void FUNC(pred8x8_mad_cow_dc_0lt)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x8_dc)(src, stride); + FUNCC(pred4x4_top_dc)(src, NULL, stride); +} + +static void FUNC(pred8x16_mad_cow_dc_0lt)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x16_dc)(src, stride); + FUNCC(pred4x4_top_dc)(src, NULL, stride); +} + +static void FUNC(pred8x8_mad_cow_dc_l00)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x8_left_dc)(src, stride); + FUNCC(pred4x4_128_dc)(src + 4*stride , NULL, stride); + FUNCC(pred4x4_128_dc)(src + 4*stride + 4*sizeof(pixel), NULL, stride); +} + +static void FUNC(pred8x16_mad_cow_dc_l00)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x16_left_dc)(src, stride); + FUNCC(pred4x4_128_dc)(src + 4*stride , NULL, stride); + FUNCC(pred4x4_128_dc)(src + 4*stride + 4*sizeof(pixel), NULL, stride); +} + +static void FUNC(pred8x8_mad_cow_dc_0l0)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x8_left_dc)(src, stride); + FUNCC(pred4x4_128_dc)(src , NULL, stride); + FUNCC(pred4x4_128_dc)(src + 4*sizeof(pixel), NULL, stride); +} + +static void FUNC(pred8x16_mad_cow_dc_0l0)(uint8_t *src, ptrdiff_t stride) +{ + FUNCC(pred8x16_left_dc)(src, stride); + FUNCC(pred4x4_128_dc)(src , NULL, stride); + FUNCC(pred4x4_128_dc)(src + 4*sizeof(pixel), NULL, stride); +} + +static void FUNCC(pred8x8_plane)(uint8_t *_src, ptrdiff_t _stride) +{ + int j, k; + int a; + INIT_CLIP + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel * const src0 = src +3-stride; + const pixel * src1 = src +4*stride-1; + const pixel * src2 = src1-2*stride; // == src+2*stride-1; + int H = src0[1] - src0[-1]; + int V = src1[0] - src2[ 0]; + for(k=2; k<=4; ++k) { + src1 += stride; src2 -= stride; + H += k*(src0[k] - src0[-k]); + V += k*(src1[0] - src2[ 0]); + } + H = ( 17*H+16 ) >> 5; + V = ( 17*V+16 ) >> 5; + + a = 16*(src1[0] + src2[8]+1) - 3*(V+H); + for(j=8; j>0; --j) { + int b = a; + a += V; + src[0] = CLIP((b ) >> 5); + src[1] = CLIP((b+ H) >> 5); + src[2] = CLIP((b+2*H) >> 5); + src[3] = CLIP((b+3*H) >> 5); + src[4] = CLIP((b+4*H) >> 5); + src[5] = CLIP((b+5*H) >> 5); + src[6] = CLIP((b+6*H) >> 5); + src[7] = CLIP((b+7*H) >> 5); + src += stride; + } +} + +static void FUNCC(pred8x16_plane)(uint8_t *_src, ptrdiff_t _stride) +{ + int j, k; + int a; + INIT_CLIP + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + const pixel * const src0 = src +3-stride; + const pixel * src1 = src +8*stride-1; + const pixel * src2 = src1-2*stride; // == src+6*stride-1; + int H = src0[1] - src0[-1]; + int V = src1[0] - src2[ 0]; + + for (k = 2; k <= 4; ++k) { + src1 += stride; src2 -= stride; + H += k*(src0[k] - src0[-k]); + V += k*(src1[0] - src2[ 0]); + } + for (; k <= 8; ++k) { + src1 += stride; src2 -= stride; + V += k*(src1[0] - src2[0]); + } + + H = (17*H+16) >> 5; + V = (5*V+32) >> 6; + + a = 16*(src1[0] + src2[8] + 1) - 7*V - 3*H; + for(j=16; j>0; --j) { + int b = a; + a += V; + src[0] = CLIP((b ) >> 5); + src[1] = CLIP((b+ H) >> 5); + src[2] = CLIP((b+2*H) >> 5); + src[3] = CLIP((b+3*H) >> 5); + src[4] = CLIP((b+4*H) >> 5); + src[5] = CLIP((b+5*H) >> 5); + src[6] = CLIP((b+6*H) >> 5); + src[7] = CLIP((b+7*H) >> 5); + src += stride; + } +} + +#define SRC(x,y) src[(x)+(y)*stride] +#define PL(y) \ + const int l##y = (SRC(-1,y-1) + 2*SRC(-1,y) + SRC(-1,y+1) + 2) >> 2; +#define PREDICT_8x8_LOAD_LEFT \ + const int l0 = ((has_topleft ? SRC(-1,-1) : SRC(-1,0)) \ + + 2*SRC(-1,0) + SRC(-1,1) + 2) >> 2; \ + PL(1) PL(2) PL(3) PL(4) PL(5) PL(6) \ + const int l7 av_unused = (SRC(-1,6) + 3*SRC(-1,7) + 2) >> 2 + +#define PT(x) \ + const int t##x = (SRC(x-1,-1) + 2*SRC(x,-1) + SRC(x+1,-1) + 2) >> 2; +#define PREDICT_8x8_LOAD_TOP \ + const int t0 = ((has_topleft ? SRC(-1,-1) : SRC(0,-1)) \ + + 2*SRC(0,-1) + SRC(1,-1) + 2) >> 2; \ + PT(1) PT(2) PT(3) PT(4) PT(5) PT(6) \ + const int t7 av_unused = ((has_topright ? SRC(8,-1) : SRC(7,-1)) \ + + 2*SRC(7,-1) + SRC(6,-1) + 2) >> 2 + +#define PTR(x) \ + t##x = (SRC(x-1,-1) + 2*SRC(x,-1) + SRC(x+1,-1) + 2) >> 2; +#define PREDICT_8x8_LOAD_TOPRIGHT \ + int t8, t9, t10, t11, t12, t13, t14, t15; \ + if(has_topright) { \ + PTR(8) PTR(9) PTR(10) PTR(11) PTR(12) PTR(13) PTR(14) \ + t15 = (SRC(14,-1) + 3*SRC(15,-1) + 2) >> 2; \ + } else t8=t9=t10=t11=t12=t13=t14=t15= SRC(7,-1); + +#define PREDICT_8x8_LOAD_TOPLEFT \ + const int lt = (SRC(-1,0) + 2*SRC(-1,-1) + SRC(0,-1) + 2) >> 2 + +#define PREDICT_8x8_DC(v) \ + int y; \ + for( y = 0; y < 8; y++ ) { \ + AV_WN4PA(((pixel4*)src)+0, v); \ + AV_WN4PA(((pixel4*)src)+1, v); \ + src += stride; \ + } + +static void FUNCC(pred8x8l_128_dc)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + + PREDICT_8x8_DC(PIXEL_SPLAT_X4(1<<(BIT_DEPTH-1))); +} +static void FUNCC(pred8x8l_left_dc)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + + PREDICT_8x8_LOAD_LEFT; + const pixel4 dc = PIXEL_SPLAT_X4((l0+l1+l2+l3+l4+l5+l6+l7+4) >> 3); + PREDICT_8x8_DC(dc); +} +static void FUNCC(pred8x8l_top_dc)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + + PREDICT_8x8_LOAD_TOP; + const pixel4 dc = PIXEL_SPLAT_X4((t0+t1+t2+t3+t4+t5+t6+t7+4) >> 3); + PREDICT_8x8_DC(dc); +} +static void FUNCC(pred8x8l_dc)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + + PREDICT_8x8_LOAD_LEFT; + PREDICT_8x8_LOAD_TOP; + const pixel4 dc = PIXEL_SPLAT_X4((l0+l1+l2+l3+l4+l5+l6+l7 + +t0+t1+t2+t3+t4+t5+t6+t7+8) >> 4); + PREDICT_8x8_DC(dc); +} +static void FUNCC(pred8x8l_horizontal)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + pixel4 a; + + PREDICT_8x8_LOAD_LEFT; +#define ROW(y) a = PIXEL_SPLAT_X4(l##y); \ + AV_WN4PA(src+y*stride, a); \ + AV_WN4PA(src+y*stride+4, a); + ROW(0); ROW(1); ROW(2); ROW(3); ROW(4); ROW(5); ROW(6); ROW(7); +#undef ROW +} +static void FUNCC(pred8x8l_vertical)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + int y; + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + pixel4 a, b; + + PREDICT_8x8_LOAD_TOP; + src[0] = t0; + src[1] = t1; + src[2] = t2; + src[3] = t3; + src[4] = t4; + src[5] = t5; + src[6] = t6; + src[7] = t7; + a = AV_RN4PA(((pixel4*)src)+0); + b = AV_RN4PA(((pixel4*)src)+1); + for( y = 1; y < 8; y++ ) { + AV_WN4PA(((pixel4*)(src+y*stride))+0, a); + AV_WN4PA(((pixel4*)(src+y*stride))+1, b); + } +} +static void FUNCC(pred8x8l_down_left)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_TOP; + PREDICT_8x8_LOAD_TOPRIGHT; + SRC(0,0)= (t0 + 2*t1 + t2 + 2) >> 2; + SRC(0,1)=SRC(1,0)= (t1 + 2*t2 + t3 + 2) >> 2; + SRC(0,2)=SRC(1,1)=SRC(2,0)= (t2 + 2*t3 + t4 + 2) >> 2; + SRC(0,3)=SRC(1,2)=SRC(2,1)=SRC(3,0)= (t3 + 2*t4 + t5 + 2) >> 2; + SRC(0,4)=SRC(1,3)=SRC(2,2)=SRC(3,1)=SRC(4,0)= (t4 + 2*t5 + t6 + 2) >> 2; + SRC(0,5)=SRC(1,4)=SRC(2,3)=SRC(3,2)=SRC(4,1)=SRC(5,0)= (t5 + 2*t6 + t7 + 2) >> 2; + SRC(0,6)=SRC(1,5)=SRC(2,4)=SRC(3,3)=SRC(4,2)=SRC(5,1)=SRC(6,0)= (t6 + 2*t7 + t8 + 2) >> 2; + SRC(0,7)=SRC(1,6)=SRC(2,5)=SRC(3,4)=SRC(4,3)=SRC(5,2)=SRC(6,1)=SRC(7,0)= (t7 + 2*t8 + t9 + 2) >> 2; + SRC(1,7)=SRC(2,6)=SRC(3,5)=SRC(4,4)=SRC(5,3)=SRC(6,2)=SRC(7,1)= (t8 + 2*t9 + t10 + 2) >> 2; + SRC(2,7)=SRC(3,6)=SRC(4,5)=SRC(5,4)=SRC(6,3)=SRC(7,2)= (t9 + 2*t10 + t11 + 2) >> 2; + SRC(3,7)=SRC(4,6)=SRC(5,5)=SRC(6,4)=SRC(7,3)= (t10 + 2*t11 + t12 + 2) >> 2; + SRC(4,7)=SRC(5,6)=SRC(6,5)=SRC(7,4)= (t11 + 2*t12 + t13 + 2) >> 2; + SRC(5,7)=SRC(6,6)=SRC(7,5)= (t12 + 2*t13 + t14 + 2) >> 2; + SRC(6,7)=SRC(7,6)= (t13 + 2*t14 + t15 + 2) >> 2; + SRC(7,7)= (t14 + 3*t15 + 2) >> 2; +} +static void FUNCC(pred8x8l_down_right)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_TOP; + PREDICT_8x8_LOAD_LEFT; + PREDICT_8x8_LOAD_TOPLEFT; + SRC(0,7)= (l7 + 2*l6 + l5 + 2) >> 2; + SRC(0,6)=SRC(1,7)= (l6 + 2*l5 + l4 + 2) >> 2; + SRC(0,5)=SRC(1,6)=SRC(2,7)= (l5 + 2*l4 + l3 + 2) >> 2; + SRC(0,4)=SRC(1,5)=SRC(2,6)=SRC(3,7)= (l4 + 2*l3 + l2 + 2) >> 2; + SRC(0,3)=SRC(1,4)=SRC(2,5)=SRC(3,6)=SRC(4,7)= (l3 + 2*l2 + l1 + 2) >> 2; + SRC(0,2)=SRC(1,3)=SRC(2,4)=SRC(3,5)=SRC(4,6)=SRC(5,7)= (l2 + 2*l1 + l0 + 2) >> 2; + SRC(0,1)=SRC(1,2)=SRC(2,3)=SRC(3,4)=SRC(4,5)=SRC(5,6)=SRC(6,7)= (l1 + 2*l0 + lt + 2) >> 2; + SRC(0,0)=SRC(1,1)=SRC(2,2)=SRC(3,3)=SRC(4,4)=SRC(5,5)=SRC(6,6)=SRC(7,7)= (l0 + 2*lt + t0 + 2) >> 2; + SRC(1,0)=SRC(2,1)=SRC(3,2)=SRC(4,3)=SRC(5,4)=SRC(6,5)=SRC(7,6)= (lt + 2*t0 + t1 + 2) >> 2; + SRC(2,0)=SRC(3,1)=SRC(4,2)=SRC(5,3)=SRC(6,4)=SRC(7,5)= (t0 + 2*t1 + t2 + 2) >> 2; + SRC(3,0)=SRC(4,1)=SRC(5,2)=SRC(6,3)=SRC(7,4)= (t1 + 2*t2 + t3 + 2) >> 2; + SRC(4,0)=SRC(5,1)=SRC(6,2)=SRC(7,3)= (t2 + 2*t3 + t4 + 2) >> 2; + SRC(5,0)=SRC(6,1)=SRC(7,2)= (t3 + 2*t4 + t5 + 2) >> 2; + SRC(6,0)=SRC(7,1)= (t4 + 2*t5 + t6 + 2) >> 2; + SRC(7,0)= (t5 + 2*t6 + t7 + 2) >> 2; +} +static void FUNCC(pred8x8l_vertical_right)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_TOP; + PREDICT_8x8_LOAD_LEFT; + PREDICT_8x8_LOAD_TOPLEFT; + SRC(0,6)= (l5 + 2*l4 + l3 + 2) >> 2; + SRC(0,7)= (l6 + 2*l5 + l4 + 2) >> 2; + SRC(0,4)=SRC(1,6)= (l3 + 2*l2 + l1 + 2) >> 2; + SRC(0,5)=SRC(1,7)= (l4 + 2*l3 + l2 + 2) >> 2; + SRC(0,2)=SRC(1,4)=SRC(2,6)= (l1 + 2*l0 + lt + 2) >> 2; + SRC(0,3)=SRC(1,5)=SRC(2,7)= (l2 + 2*l1 + l0 + 2) >> 2; + SRC(0,1)=SRC(1,3)=SRC(2,5)=SRC(3,7)= (l0 + 2*lt + t0 + 2) >> 2; + SRC(0,0)=SRC(1,2)=SRC(2,4)=SRC(3,6)= (lt + t0 + 1) >> 1; + SRC(1,1)=SRC(2,3)=SRC(3,5)=SRC(4,7)= (lt + 2*t0 + t1 + 2) >> 2; + SRC(1,0)=SRC(2,2)=SRC(3,4)=SRC(4,6)= (t0 + t1 + 1) >> 1; + SRC(2,1)=SRC(3,3)=SRC(4,5)=SRC(5,7)= (t0 + 2*t1 + t2 + 2) >> 2; + SRC(2,0)=SRC(3,2)=SRC(4,4)=SRC(5,6)= (t1 + t2 + 1) >> 1; + SRC(3,1)=SRC(4,3)=SRC(5,5)=SRC(6,7)= (t1 + 2*t2 + t3 + 2) >> 2; + SRC(3,0)=SRC(4,2)=SRC(5,4)=SRC(6,6)= (t2 + t3 + 1) >> 1; + SRC(4,1)=SRC(5,3)=SRC(6,5)=SRC(7,7)= (t2 + 2*t3 + t4 + 2) >> 2; + SRC(4,0)=SRC(5,2)=SRC(6,4)=SRC(7,6)= (t3 + t4 + 1) >> 1; + SRC(5,1)=SRC(6,3)=SRC(7,5)= (t3 + 2*t4 + t5 + 2) >> 2; + SRC(5,0)=SRC(6,2)=SRC(7,4)= (t4 + t5 + 1) >> 1; + SRC(6,1)=SRC(7,3)= (t4 + 2*t5 + t6 + 2) >> 2; + SRC(6,0)=SRC(7,2)= (t5 + t6 + 1) >> 1; + SRC(7,1)= (t5 + 2*t6 + t7 + 2) >> 2; + SRC(7,0)= (t6 + t7 + 1) >> 1; +} +static void FUNCC(pred8x8l_horizontal_down)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_TOP; + PREDICT_8x8_LOAD_LEFT; + PREDICT_8x8_LOAD_TOPLEFT; + SRC(0,7)= (l6 + l7 + 1) >> 1; + SRC(1,7)= (l5 + 2*l6 + l7 + 2) >> 2; + SRC(0,6)=SRC(2,7)= (l5 + l6 + 1) >> 1; + SRC(1,6)=SRC(3,7)= (l4 + 2*l5 + l6 + 2) >> 2; + SRC(0,5)=SRC(2,6)=SRC(4,7)= (l4 + l5 + 1) >> 1; + SRC(1,5)=SRC(3,6)=SRC(5,7)= (l3 + 2*l4 + l5 + 2) >> 2; + SRC(0,4)=SRC(2,5)=SRC(4,6)=SRC(6,7)= (l3 + l4 + 1) >> 1; + SRC(1,4)=SRC(3,5)=SRC(5,6)=SRC(7,7)= (l2 + 2*l3 + l4 + 2) >> 2; + SRC(0,3)=SRC(2,4)=SRC(4,5)=SRC(6,6)= (l2 + l3 + 1) >> 1; + SRC(1,3)=SRC(3,4)=SRC(5,5)=SRC(7,6)= (l1 + 2*l2 + l3 + 2) >> 2; + SRC(0,2)=SRC(2,3)=SRC(4,4)=SRC(6,5)= (l1 + l2 + 1) >> 1; + SRC(1,2)=SRC(3,3)=SRC(5,4)=SRC(7,5)= (l0 + 2*l1 + l2 + 2) >> 2; + SRC(0,1)=SRC(2,2)=SRC(4,3)=SRC(6,4)= (l0 + l1 + 1) >> 1; + SRC(1,1)=SRC(3,2)=SRC(5,3)=SRC(7,4)= (lt + 2*l0 + l1 + 2) >> 2; + SRC(0,0)=SRC(2,1)=SRC(4,2)=SRC(6,3)= (lt + l0 + 1) >> 1; + SRC(1,0)=SRC(3,1)=SRC(5,2)=SRC(7,3)= (l0 + 2*lt + t0 + 2) >> 2; + SRC(2,0)=SRC(4,1)=SRC(6,2)= (t1 + 2*t0 + lt + 2) >> 2; + SRC(3,0)=SRC(5,1)=SRC(7,2)= (t2 + 2*t1 + t0 + 2) >> 2; + SRC(4,0)=SRC(6,1)= (t3 + 2*t2 + t1 + 2) >> 2; + SRC(5,0)=SRC(7,1)= (t4 + 2*t3 + t2 + 2) >> 2; + SRC(6,0)= (t5 + 2*t4 + t3 + 2) >> 2; + SRC(7,0)= (t6 + 2*t5 + t4 + 2) >> 2; +} +static void FUNCC(pred8x8l_vertical_left)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_TOP; + PREDICT_8x8_LOAD_TOPRIGHT; + SRC(0,0)= (t0 + t1 + 1) >> 1; + SRC(0,1)= (t0 + 2*t1 + t2 + 2) >> 2; + SRC(0,2)=SRC(1,0)= (t1 + t2 + 1) >> 1; + SRC(0,3)=SRC(1,1)= (t1 + 2*t2 + t3 + 2) >> 2; + SRC(0,4)=SRC(1,2)=SRC(2,0)= (t2 + t3 + 1) >> 1; + SRC(0,5)=SRC(1,3)=SRC(2,1)= (t2 + 2*t3 + t4 + 2) >> 2; + SRC(0,6)=SRC(1,4)=SRC(2,2)=SRC(3,0)= (t3 + t4 + 1) >> 1; + SRC(0,7)=SRC(1,5)=SRC(2,3)=SRC(3,1)= (t3 + 2*t4 + t5 + 2) >> 2; + SRC(1,6)=SRC(2,4)=SRC(3,2)=SRC(4,0)= (t4 + t5 + 1) >> 1; + SRC(1,7)=SRC(2,5)=SRC(3,3)=SRC(4,1)= (t4 + 2*t5 + t6 + 2) >> 2; + SRC(2,6)=SRC(3,4)=SRC(4,2)=SRC(5,0)= (t5 + t6 + 1) >> 1; + SRC(2,7)=SRC(3,5)=SRC(4,3)=SRC(5,1)= (t5 + 2*t6 + t7 + 2) >> 2; + SRC(3,6)=SRC(4,4)=SRC(5,2)=SRC(6,0)= (t6 + t7 + 1) >> 1; + SRC(3,7)=SRC(4,5)=SRC(5,3)=SRC(6,1)= (t6 + 2*t7 + t8 + 2) >> 2; + SRC(4,6)=SRC(5,4)=SRC(6,2)=SRC(7,0)= (t7 + t8 + 1) >> 1; + SRC(4,7)=SRC(5,5)=SRC(6,3)=SRC(7,1)= (t7 + 2*t8 + t9 + 2) >> 2; + SRC(5,6)=SRC(6,4)=SRC(7,2)= (t8 + t9 + 1) >> 1; + SRC(5,7)=SRC(6,5)=SRC(7,3)= (t8 + 2*t9 + t10 + 2) >> 2; + SRC(6,6)=SRC(7,4)= (t9 + t10 + 1) >> 1; + SRC(6,7)=SRC(7,5)= (t9 + 2*t10 + t11 + 2) >> 2; + SRC(7,6)= (t10 + t11 + 1) >> 1; + SRC(7,7)= (t10 + 2*t11 + t12 + 2) >> 2; +} +static void FUNCC(pred8x8l_horizontal_up)(uint8_t *_src, int has_topleft, + int has_topright, ptrdiff_t _stride) +{ + pixel *src = (pixel*)_src; + int stride = _stride>>(sizeof(pixel)-1); + PREDICT_8x8_LOAD_LEFT; + SRC(0,0)= (l0 + l1 + 1) >> 1; + SRC(1,0)= (l0 + 2*l1 + l2 + 2) >> 2; + SRC(0,1)=SRC(2,0)= (l1 + l2 + 1) >> 1; + SRC(1,1)=SRC(3,0)= (l1 + 2*l2 + l3 + 2) >> 2; + SRC(0,2)=SRC(2,1)=SRC(4,0)= (l2 + l3 + 1) >> 1; + SRC(1,2)=SRC(3,1)=SRC(5,0)= (l2 + 2*l3 + l4 + 2) >> 2; + SRC(0,3)=SRC(2,2)=SRC(4,1)=SRC(6,0)= (l3 + l4 + 1) >> 1; + SRC(1,3)=SRC(3,2)=SRC(5,1)=SRC(7,0)= (l3 + 2*l4 + l5 + 2) >> 2; + SRC(0,4)=SRC(2,3)=SRC(4,2)=SRC(6,1)= (l4 + l5 + 1) >> 1; + SRC(1,4)=SRC(3,3)=SRC(5,2)=SRC(7,1)= (l4 + 2*l5 + l6 + 2) >> 2; + SRC(0,5)=SRC(2,4)=SRC(4,3)=SRC(6,2)= (l5 + l6 + 1) >> 1; + SRC(1,5)=SRC(3,4)=SRC(5,3)=SRC(7,2)= (l5 + 2*l6 + l7 + 2) >> 2; + SRC(0,6)=SRC(2,5)=SRC(4,4)=SRC(6,3)= (l6 + l7 + 1) >> 1; + SRC(1,6)=SRC(3,5)=SRC(5,4)=SRC(7,3)= (l6 + 3*l7 + 2) >> 2; + SRC(0,7)=SRC(1,7)=SRC(2,6)=SRC(2,7)=SRC(3,6)= + SRC(3,7)=SRC(4,5)=SRC(4,6)=SRC(4,7)=SRC(5,5)= + SRC(5,6)=SRC(5,7)=SRC(6,4)=SRC(6,5)=SRC(6,6)= + SRC(6,7)=SRC(7,4)=SRC(7,5)=SRC(7,6)=SRC(7,7)= l7; +} +#undef PREDICT_8x8_LOAD_LEFT +#undef PREDICT_8x8_LOAD_TOP +#undef PREDICT_8x8_LOAD_TOPLEFT +#undef PREDICT_8x8_LOAD_TOPRIGHT +#undef PREDICT_8x8_DC +#undef PTR +#undef PT +#undef PL +#undef SRC + +static void FUNCC(pred4x4_vertical_add)(uint8_t *_pix, int16_t *_block, + ptrdiff_t stride) +{ + int i; + pixel *pix = (pixel*)_pix; + const dctcoef *block = (const dctcoef*)_block; + stride >>= sizeof(pixel)-1; + pix -= stride; + for(i=0; i<4; i++){ + pixel v = pix[0]; + pix[1*stride]= v += block[0]; + pix[2*stride]= v += block[4]; + pix[3*stride]= v += block[8]; + pix[4*stride]= v + block[12]; + pix++; + block++; + } + + memset(_block, 0, sizeof(dctcoef) * 16); +} + +static void FUNCC(pred4x4_horizontal_add)(uint8_t *_pix, int16_t *_block, + ptrdiff_t stride) +{ + int i; + pixel *pix = (pixel*)_pix; + const dctcoef *block = (const dctcoef*)_block; + stride >>= sizeof(pixel)-1; + for(i=0; i<4; i++){ + pixel v = pix[-1]; + pix[0]= v += block[0]; + pix[1]= v += block[1]; + pix[2]= v += block[2]; + pix[3]= v + block[3]; + pix+= stride; + block+= 4; + } + + memset(_block, 0, sizeof(dctcoef) * 16); +} + +static void FUNCC(pred8x8l_vertical_add)(uint8_t *_pix, int16_t *_block, + ptrdiff_t stride) +{ + int i; + pixel *pix = (pixel*)_pix; + const dctcoef *block = (const dctcoef*)_block; + stride >>= sizeof(pixel)-1; + pix -= stride; + for(i=0; i<8; i++){ + pixel v = pix[0]; + pix[1*stride]= v += block[0]; + pix[2*stride]= v += block[8]; + pix[3*stride]= v += block[16]; + pix[4*stride]= v += block[24]; + pix[5*stride]= v += block[32]; + pix[6*stride]= v += block[40]; + pix[7*stride]= v += block[48]; + pix[8*stride]= v + block[56]; + pix++; + block++; + } + + memset(_block, 0, sizeof(dctcoef) * 64); +} + +static void FUNCC(pred8x8l_horizontal_add)(uint8_t *_pix, int16_t *_block, + ptrdiff_t stride) +{ + int i; + pixel *pix = (pixel*)_pix; + const dctcoef *block = (const dctcoef*)_block; + stride >>= sizeof(pixel)-1; + for(i=0; i<8; i++){ + pixel v = pix[-1]; + pix[0]= v += block[0]; + pix[1]= v += block[1]; + pix[2]= v += block[2]; + pix[3]= v += block[3]; + pix[4]= v += block[4]; + pix[5]= v += block[5]; + pix[6]= v += block[6]; + pix[7]= v + block[7]; + pix+= stride; + block+= 8; + } + + memset(_block, 0, sizeof(dctcoef) * 64); +} + +static void FUNCC(pred16x16_vertical_add)(uint8_t *pix, const int *block_offset, + int16_t *block, + ptrdiff_t stride) +{ + int i; + for(i=0; i<16; i++) + FUNCC(pred4x4_vertical_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride); +} + +static void FUNCC(pred16x16_horizontal_add)(uint8_t *pix, + const int *block_offset, + int16_t *block, + ptrdiff_t stride) +{ + int i; + for(i=0; i<16; i++) + FUNCC(pred4x4_horizontal_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride); +} + +static void FUNCC(pred8x8_vertical_add)(uint8_t *pix, const int *block_offset, + int16_t *block, ptrdiff_t stride) +{ + int i; + for(i=0; i<4; i++) + FUNCC(pred4x4_vertical_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride); +} + +static void FUNCC(pred8x16_vertical_add)(uint8_t *pix, const int *block_offset, + int16_t *block, ptrdiff_t stride) +{ + int i; + for(i=0; i<4; i++) + FUNCC(pred4x4_vertical_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride); + for(i=4; i<8; i++) + FUNCC(pred4x4_vertical_add)(pix + block_offset[i+4], block + i*16*sizeof(pixel), stride); +} + +static void FUNCC(pred8x8_horizontal_add)(uint8_t *pix, const int *block_offset, + int16_t *block, + ptrdiff_t stride) +{ + int i; + for(i=0; i<4; i++) + FUNCC(pred4x4_horizontal_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride); +} + +static void FUNCC(pred8x16_horizontal_add)(uint8_t *pix, + const int *block_offset, + int16_t *block, ptrdiff_t stride) +{ + int i; + for(i=0; i<4; i++) + FUNCC(pred4x4_horizontal_add)(pix + block_offset[i], block + i*16*sizeof(pixel), stride); + for(i=4; i<8; i++) + FUNCC(pred4x4_horizontal_add)(pix + block_offset[i+4], block + i*16*sizeof(pixel), stride); +} diff --git a/ffmpeg/libavcodec/h264qpel.c b/ffmpeg/libavcodec/h264qpel.c new file mode 100644 index 0000000..f46da8f --- /dev/null +++ b/ffmpeg/libavcodec/h264qpel.c @@ -0,0 +1,104 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2010 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 "h264qpel.h" + +#define pixeltmp int16_t +#define BIT_DEPTH 8 +#include "h264qpel_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 9 +#include "h264qpel_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 10 +#include "h264qpel_template.c" +#undef BIT_DEPTH +#undef pixeltmp + +#define pixeltmp int32_t +#define BIT_DEPTH 12 +#include "h264qpel_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 14 +#include "h264qpel_template.c" +#undef BIT_DEPTH + + +void ff_h264qpel_init(H264QpelContext *c, int bit_depth) +{ +#undef FUNCC +#define FUNCC(f, depth) f ## _ ## depth ## _c + +#define dspfunc2(PFX, IDX, NUM, depth) \ + c->PFX ## _pixels_tab[IDX][ 0] = FUNCC(PFX ## NUM ## _mc00, depth); \ + c->PFX ## _pixels_tab[IDX][ 1] = FUNCC(PFX ## NUM ## _mc10, depth); \ + c->PFX ## _pixels_tab[IDX][ 2] = FUNCC(PFX ## NUM ## _mc20, depth); \ + c->PFX ## _pixels_tab[IDX][ 3] = FUNCC(PFX ## NUM ## _mc30, depth); \ + c->PFX ## _pixels_tab[IDX][ 4] = FUNCC(PFX ## NUM ## _mc01, depth); \ + c->PFX ## _pixels_tab[IDX][ 5] = FUNCC(PFX ## NUM ## _mc11, depth); \ + c->PFX ## _pixels_tab[IDX][ 6] = FUNCC(PFX ## NUM ## _mc21, depth); \ + c->PFX ## _pixels_tab[IDX][ 7] = FUNCC(PFX ## NUM ## _mc31, depth); \ + c->PFX ## _pixels_tab[IDX][ 8] = FUNCC(PFX ## NUM ## _mc02, depth); \ + c->PFX ## _pixels_tab[IDX][ 9] = FUNCC(PFX ## NUM ## _mc12, depth); \ + c->PFX ## _pixels_tab[IDX][10] = FUNCC(PFX ## NUM ## _mc22, depth); \ + c->PFX ## _pixels_tab[IDX][11] = FUNCC(PFX ## NUM ## _mc32, depth); \ + c->PFX ## _pixels_tab[IDX][12] = FUNCC(PFX ## NUM ## _mc03, depth); \ + c->PFX ## _pixels_tab[IDX][13] = FUNCC(PFX ## NUM ## _mc13, depth); \ + c->PFX ## _pixels_tab[IDX][14] = FUNCC(PFX ## NUM ## _mc23, depth); \ + c->PFX ## _pixels_tab[IDX][15] = FUNCC(PFX ## NUM ## _mc33, depth) + +#define SET_QPEL(depth) \ + dspfunc2(put_h264_qpel, 0, 16, depth); \ + dspfunc2(put_h264_qpel, 1, 8, depth); \ + dspfunc2(put_h264_qpel, 2, 4, depth); \ + dspfunc2(put_h264_qpel, 3, 2, depth); \ + dspfunc2(avg_h264_qpel, 0, 16, depth); \ + dspfunc2(avg_h264_qpel, 1, 8, depth); \ + dspfunc2(avg_h264_qpel, 2, 4, depth) + + switch (bit_depth) { + default: + SET_QPEL(8); + break; + case 9: + SET_QPEL(9); + break; + case 10: + SET_QPEL(10); + break; + case 12: + SET_QPEL(12); + break; + case 14: + SET_QPEL(14); + break; + } + + if (ARCH_ARM) + ff_h264qpel_init_arm(c, bit_depth); + if (ARCH_PPC) + ff_h264qpel_init_ppc(c, bit_depth); + if (ARCH_X86) + ff_h264qpel_init_x86(c, bit_depth); +} diff --git a/ffmpeg/libavcodec/h264qpel.h b/ffmpeg/libavcodec/h264qpel.h new file mode 100644 index 0000000..6abfac0 --- /dev/null +++ b/ffmpeg/libavcodec/h264qpel.h @@ -0,0 +1,38 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2010 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 + */ + +#ifndef AVCODEC_H264QPEL_H +#define AVCODEC_H264QPEL_H + +#include "dsputil.h" + +typedef struct H264QpelContext { + qpel_mc_func put_h264_qpel_pixels_tab[4][16]; + qpel_mc_func avg_h264_qpel_pixels_tab[4][16]; +} H264QpelContext; + +void ff_h264qpel_init(H264QpelContext *c, int bit_depth); + +void ff_h264qpel_init_arm(H264QpelContext *c, int bit_depth); +void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth); +void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth); + +#endif /* AVCODEC_H264QPEL_H */ diff --git a/ffmpeg/libavcodec/h264qpel_template.c b/ffmpeg/libavcodec/h264qpel_template.c new file mode 100644 index 0000000..48eb8c8 --- /dev/null +++ b/ffmpeg/libavcodec/h264qpel_template.c @@ -0,0 +1,549 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003-2010 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 "libavutil/common.h" +#include "bit_depth_template.c" +#include "hpel_template.c" + +static inline void FUNC(copy_block2)(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) +{ + int i; + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + src -= 2*srcStride;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + src -= 2*srcStride;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + for(i=0; i>= sizeof(pixel)-1;\ + srcStride >>= sizeof(pixel)-1;\ + src -= 2*srcStride;\ + for(i=0; i>5)+1)>>1) +//#define op_avg2(a, b) a = (((a)*w1+cm[((b) + 16)>>5]*w2 + o + 64)>>7) +#define op_put(a, b) a = CLIP(((b) + 16)>>5) +#define op2_avg(a, b) a = (((a)+CLIP(((b) + 512)>>10)+1)>>1) +#define op2_put(a, b) a = CLIP(((b) + 512)>>10) + +H264_LOWPASS(put_ , op_put, op2_put) +H264_LOWPASS(avg_ , op_avg, op2_avg) +H264_MC(put_, 2) +H264_MC(put_, 4) +H264_MC(put_, 8) +H264_MC(put_, 16) +H264_MC(avg_, 4) +H264_MC(avg_, 8) +H264_MC(avg_, 16) + +#undef op_avg +#undef op_put +#undef op2_avg +#undef op2_put diff --git a/ffmpeg/libavcodec/hpel_template.c b/ffmpeg/libavcodec/hpel_template.c new file mode 100644 index 0000000..3b46999 --- /dev/null +++ b/ffmpeg/libavcodec/hpel_template.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +#define DEF_HPEL(OPNAME, OP) \ +static inline void FUNCC(OPNAME ## _pixels2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\ + int i;\ + for(i=0; i + * + * gmc & q-pel & 32/64 bit based MC 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 + */ + +/** + * @file + * Half-pel DSP functions. + */ + +#include "libavutil/attributes.h" +#include "hpeldsp.h" + +#define BIT_DEPTH 8 +#include "hpeldsp_template.c" + +av_cold void ff_hpeldsp_init(HpelDSPContext* c, int flags) +{ +#define hpel_funcs(prefix, idx, num) \ + c->prefix ## _pixels_tab idx [0] = prefix ## _pixels ## num ## _8_c; \ + c->prefix ## _pixels_tab idx [1] = prefix ## _pixels ## num ## _x2_8_c; \ + c->prefix ## _pixels_tab idx [2] = prefix ## _pixels ## num ## _y2_8_c; \ + c->prefix ## _pixels_tab idx [3] = prefix ## _pixels ## num ## _xy2_8_c + + hpel_funcs(put, [0], 16); + hpel_funcs(put, [1], 8); + hpel_funcs(put, [2], 4); + hpel_funcs(put, [3], 2); + hpel_funcs(put_no_rnd, [0], 16); + hpel_funcs(put_no_rnd, [1], 8); + hpel_funcs(avg, [0], 16); + hpel_funcs(avg, [1], 8); + hpel_funcs(avg, [2], 4); + hpel_funcs(avg, [3], 2); + hpel_funcs(avg_no_rnd,, 16); + + if (ARCH_X86) ff_hpeldsp_init_x86 (c, flags); + if (ARCH_ARM) ff_hpeldsp_init_arm (c, flags); + if (HAVE_VIS) ff_hpeldsp_init_vis (c, flags); + if (ARCH_ALPHA) ff_hpeldsp_init_alpha (c, flags); + if (ARCH_PPC) ff_hpeldsp_init_ppc (c, flags); + if (ARCH_SH4) ff_hpeldsp_init_sh4 (c, flags); + if (ARCH_BFIN) ff_hpeldsp_init_bfin (c, flags); +} diff --git a/ffmpeg/libavcodec/hpeldsp.h b/ffmpeg/libavcodec/hpeldsp.h new file mode 100644 index 0000000..57a4cc1 --- /dev/null +++ b/ffmpeg/libavcodec/hpeldsp.h @@ -0,0 +1,105 @@ +/* + * Half-pel DSP functions. + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * Half-pel DSP functions. + */ + +#ifndef AVCODEC_HPELDSP_H +#define AVCODEC_HPELDSP_H + +#include +#include + +/* add and put pixel (decoding) */ +// blocksizes for op_pixels_func are 8x4,8x8 16x8 16x16 +// h for op_pixels_func is limited to {width/2, width} but never larger +// than 16 and never smaller than 4 +typedef void (*op_pixels_func)(uint8_t *block /*align width (8 or 16)*/, + const uint8_t *pixels /*align 1*/, + ptrdiff_t line_size, int h); + +/** + * Half-pel DSP context. + */ +typedef struct HpelDSPContext { + /** + * Halfpel motion compensation with rounding (a+b+1)>>1. + * this is an array[4][4] of motion compensation functions for 4 + * horizontal blocksizes (8,16) and the 4 halfpel positions
+ * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func put_pixels_tab[4][4]; + + /** + * Halfpel motion compensation with rounding (a+b+1)>>1. + * This is an array[4][4] of motion compensation functions for 4 + * horizontal blocksizes (8,16) and the 4 halfpel positions
+ * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination into which the result is averaged (a+b+1)>>1 + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func avg_pixels_tab[4][4]; + + /** + * Halfpel motion compensation with no rounding (a+b)>>1. + * this is an array[4][4] of motion compensation functions for 2 + * horizontal blocksizes (8,16) and the 4 halfpel positions
+ * *pixels_tab[ 0->16xH 1->8xH ][ xhalfpel + 2*yhalfpel ] + * @param block destination where the result is stored + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func put_no_rnd_pixels_tab[4][4]; + + /** + * Halfpel motion compensation with no rounding (a+b)>>1. + * this is an array[4] of motion compensation functions for 1 + * horizontal blocksize (16) and the 4 halfpel positions
+ * *pixels_tab[0][ xhalfpel + 2*yhalfpel ] + * @param block destination into which the result is averaged (a+b)>>1 + * @param pixels source + * @param line_size number of bytes in a horizontal line of block + * @param h height + */ + op_pixels_func avg_no_rnd_pixels_tab[4]; +} HpelDSPContext; + +void ff_hpeldsp_init(HpelDSPContext* p, int flags); + +void ff_hpeldsp_init_alpha(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_arm(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_bfin(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_x86(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_ppc(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_sh4(HpelDSPContext* c, int flags); +void ff_hpeldsp_init_vis(HpelDSPContext* c, int flags); + +#endif /* AVCODEC_HPELDSP_H */ diff --git a/ffmpeg/libavcodec/hpeldsp_template.c b/ffmpeg/libavcodec/hpeldsp_template.c new file mode 100644 index 0000000..9c9fd2b --- /dev/null +++ b/ffmpeg/libavcodec/hpeldsp_template.c @@ -0,0 +1,254 @@ +/* + * Half-pel DSP functions. + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * gmc & q-pel & 32/64 bit based MC 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 + */ + +/** + * @file + * Half-pel DSP functions. + */ + +#include "bit_depth_template.c" + +#include "hpel_template.c" + +#define PIXOP2(OPNAME, OP) \ +static inline void FUNC(OPNAME ## _no_rnd_pixels8_l2)(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, \ + int src_stride1, int src_stride2, int h){\ + int i;\ + for(i=0; i>= sizeof(pixel)-1;\ + a0= pixels[0];\ + b0= pixels[1] + 2;\ + a0 += b0;\ + b0 += pixels[2];\ +\ + pixels+=line_size;\ + for(i=0; i>2; /* FIXME non put */\ + block[1]= (b1+b0)>>2;\ +\ + pixels+=line_size;\ + block +=line_size;\ +\ + a0= pixels[0];\ + b0= pixels[1] + 2;\ + a0 += b0;\ + b0 += pixels[2];\ +\ + block[0]= (a1+a0)>>2;\ + block[1]= (b1+b0)>>2;\ + pixels+=line_size;\ + block +=line_size;\ + }\ +}\ +\ +static inline void FUNCC(OPNAME ## _pixels4_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ +{\ + /* FIXME HIGH BIT DEPTH */\ + int i;\ + const uint32_t a= AV_RN32(pixels );\ + const uint32_t b= AV_RN32(pixels+1);\ + uint32_t l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + uint32_t l1,h1;\ +\ + pixels+=line_size;\ + for(i=0; i>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + a= AV_RN32(pixels );\ + b= AV_RN32(pixels+1);\ + l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + }\ +}\ +\ +static inline void FUNCC(OPNAME ## _pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ +{\ + /* FIXME HIGH BIT DEPTH */\ + int j;\ + for(j=0; j<2; j++){\ + int i;\ + const uint32_t a= AV_RN32(pixels );\ + const uint32_t b= AV_RN32(pixels+1);\ + uint32_t l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + uint32_t l1,h1;\ +\ + pixels+=line_size;\ + for(i=0; i>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + a= AV_RN32(pixels );\ + b= AV_RN32(pixels+1);\ + l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x02020202UL;\ + h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + }\ + pixels+=4-line_size*(h+1);\ + block +=4-line_size*h;\ + }\ +}\ +\ +static inline void FUNCC(OPNAME ## _no_rnd_pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)\ +{\ + /* FIXME HIGH BIT DEPTH */\ + int j;\ + for(j=0; j<2; j++){\ + int i;\ + const uint32_t a= AV_RN32(pixels );\ + const uint32_t b= AV_RN32(pixels+1);\ + uint32_t l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x01010101UL;\ + uint32_t h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + uint32_t l1,h1;\ +\ + pixels+=line_size;\ + for(i=0; i>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + a= AV_RN32(pixels );\ + b= AV_RN32(pixels+1);\ + l0= (a&0x03030303UL)\ + + (b&0x03030303UL)\ + + 0x01010101UL;\ + h0= ((a&0xFCFCFCFCUL)>>2)\ + + ((b&0xFCFCFCFCUL)>>2);\ + OP(*((uint32_t*)block), h0+h1+(((l0+l1)>>2)&0x0F0F0F0FUL));\ + pixels+=line_size;\ + block +=line_size;\ + }\ + pixels+=4-line_size*(h+1);\ + block +=4-line_size*h;\ + }\ +}\ +\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_x2) , FUNCC(OPNAME ## _pixels8_x2) , 8*sizeof(pixel))\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_y2) , FUNCC(OPNAME ## _pixels8_y2) , 8*sizeof(pixel))\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _pixels16_xy2), FUNCC(OPNAME ## _pixels8_xy2), 8*sizeof(pixel))\ +av_unused CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16) , FUNCC(OPNAME ## _pixels8) , 8*sizeof(pixel))\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_x2) , FUNCC(OPNAME ## _no_rnd_pixels8_x2) , 8*sizeof(pixel))\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_y2) , FUNCC(OPNAME ## _no_rnd_pixels8_y2) , 8*sizeof(pixel))\ +CALL_2X_PIXELS(FUNCC(OPNAME ## _no_rnd_pixels16_xy2), FUNCC(OPNAME ## _no_rnd_pixels8_xy2), 8*sizeof(pixel))\ + +#define op_avg(a, b) a = rnd_avg_pixel4(a, b) +#define op_put(a, b) a = b +#if BIT_DEPTH == 8 +#define put_no_rnd_pixels8_8_c put_pixels8_8_c +PIXOP2(avg, op_avg) +PIXOP2(put, op_put) +#endif +#undef op_avg +#undef op_put diff --git a/ffmpeg/libavcodec/huffman.c b/ffmpeg/libavcodec/huffman.c new file mode 100644 index 0000000..27fed9f --- /dev/null +++ b/ffmpeg/libavcodec/huffman.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2006 Konstantin Shishkov + * Copyright (c) 2007 Loren Merritt + * + * 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 + */ + +/** + * @file + * huffman tree builder and VLC generator + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "huffman.h" + +/* symbol for Huffman tree node */ +#define HNODE -1 + +typedef struct { + uint64_t val; + int name; +} HeapElem; + +static void heap_sift(HeapElem *h, int root, int size) +{ + while (root * 2 + 1 < size) { + int child = root * 2 + 1; + if (child < size - 1 && h[child].val > h[child+1].val) + child++; + if (h[root].val > h[child].val) { + FFSWAP(HeapElem, h[root], h[child]); + root = child; + } else + break; + } +} + +void ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats) +{ + HeapElem h[256]; + int up[2*256]; + int len[2*256]; + int offset, i, next; + int size = 256; + + for (offset = 1; ; offset <<= 1) { + for (i=0; i < size; i++) { + h[i].name = i; + h[i].val = (stats[i] << 8) + offset; + } + for (i = size / 2 - 1; i >= 0; i--) + heap_sift(h, i, size); + + for (next = size; next < size * 2 - 1; next++) { + // merge the two smallest entries, and put it back in the heap + uint64_t min1v = h[0].val; + up[h[0].name] = next; + h[0].val = INT64_MAX; + heap_sift(h, 0, size); + up[h[0].name] = next; + h[0].name = next; + h[0].val += min1v; + heap_sift(h, 0, size); + } + + len[2 * size - 2] = 0; + for (i = 2 * size - 3; i >= size; i--) + len[i] = len[up[i]] + 1; + for (i = 0; i < size; i++) { + dst[i] = len[up[i]] + 1; + if (dst[i] >= 32) break; + } + if (i==size) break; + } +} + +static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, + Node *nodes, int node, + uint32_t pfx, int pl, int *pos, int no_zero_count) +{ + int s; + + s = nodes[node].sym; + if (s != HNODE || (no_zero_count && !nodes[node].count)) { + bits[*pos] = pfx; + lens[*pos] = pl; + xlat[*pos] = s; + (*pos)++; + } else { + pfx <<= 1; + pl++; + get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0, pfx, pl, + pos, no_zero_count); + pfx |= 1; + get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0 + 1, pfx, pl, + pos, no_zero_count); + } +} + +static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags) +{ + int no_zero_count = !(flags & FF_HUFFMAN_FLAG_ZERO_COUNT); + uint32_t bits[256]; + int16_t lens[256]; + uint8_t xlat[256]; + int pos = 0; + + get_tree_codes(bits, lens, xlat, nodes, head, 0, 0, + &pos, no_zero_count); + return ff_init_vlc_sparse(vlc, 9, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); +} + + +/** + * nodes size must be 2*nb_codes + * first nb_codes nodes.count must be set + */ +int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, + Node *nodes, HuffCmp cmp, int flags) +{ + int i, j; + int cur_node; + int64_t sum = 0; + + for (i = 0; i < nb_codes; i++) { + nodes[i].sym = i; + nodes[i].n0 = -2; + sum += nodes[i].count; + } + + if (sum >> 31) { + av_log(avctx, AV_LOG_ERROR, + "Too high symbol frequencies. " + "Tree construction is not possible\n"); + return -1; + } + qsort(nodes, nb_codes, sizeof(Node), cmp); + cur_node = nb_codes; + nodes[nb_codes*2-1].count = 0; + for (i = 0; i < nb_codes * 2 - 1; i += 2) { + uint32_t cur_count = nodes[i].count + nodes[i+1].count; + // find correct place to insert new node, and + // make space for the new node while at it + for(j = cur_node; j > i + 2; j--){ + if(cur_count > nodes[j-1].count || + (cur_count == nodes[j-1].count && + !(flags & FF_HUFFMAN_FLAG_HNODE_FIRST))) + break; + nodes[j] = nodes[j - 1]; + } + nodes[j].sym = HNODE; + nodes[j].count = cur_count; + nodes[j].n0 = i; + cur_node++; + } + if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error building tree\n"); + return -1; + } + return 0; +} diff --git a/ffmpeg/libavcodec/huffman.h b/ffmpeg/libavcodec/huffman.h new file mode 100644 index 0000000..4f9ccba --- /dev/null +++ b/ffmpeg/libavcodec/huffman.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * huffman tree builder and VLC generator + */ + +#ifndef AVCODEC_HUFFMAN_H +#define AVCODEC_HUFFMAN_H + +#include "avcodec.h" +#include "get_bits.h" + +typedef struct Node { + int16_t sym; + int16_t n0; + uint32_t count; +} Node; + +#define FF_HUFFMAN_FLAG_HNODE_FIRST 0x01 +#define FF_HUFFMAN_FLAG_ZERO_COUNT 0x02 + +typedef int (*HuffCmp)(const void *va, const void *vb); +int ff_huff_build_tree(AVCodecContext *avctx, VLC *vlc, int nb_codes, + Node *nodes, HuffCmp cmp, int flags); + +void ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats); + +#endif /* AVCODEC_HUFFMAN_H */ diff --git a/ffmpeg/libavcodec/huffyuv.c b/ffmpeg/libavcodec/huffyuv.c new file mode 100644 index 0000000..b4ef76f --- /dev/null +++ b/ffmpeg/libavcodec/huffyuv.c @@ -0,0 +1,97 @@ +/* + * huffyuv codec for libavcodec + * + * Copyright (c) 2002-2003 Michael Niedermayer + * + * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of + * the algorithm used + * + * 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 + */ + +/** + * @file + * huffyuv codec for libavcodec. + */ + +#include + +#include "libavutil/mem.h" + +#include "avcodec.h" +#include "huffyuv.h" + +int ff_huffyuv_generate_bits_table(uint32_t *dst, const uint8_t *len_table) +{ + int len, index; + uint32_t bits = 0; + + for (len = 32; len > 0; len--) { + for (index = 0; index < 256; index++) { + if (len_table[index] == len) + dst[index] = bits++; + } + if (bits & 1) { + av_log(NULL, AV_LOG_ERROR, "Error generating huffman table\n"); + return -1; + } + bits >>= 1; + } + return 0; +} + +av_cold int ff_huffyuv_alloc_temp(HYuvContext *s) +{ + int i; + + if (s->bitstream_bpp<24) { + for (i=0; i<3; i++) { + s->temp[i]= av_malloc(s->width + 16); + if (!s->temp[i]) + return AVERROR(ENOMEM); + } + } else { + s->temp[0]= av_mallocz(4*s->width + 16); + if (!s->temp[0]) + return AVERROR(ENOMEM); + } + return 0; +} + +av_cold void ff_huffyuv_common_init(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + + s->avctx = avctx; + s->flags = avctx->flags; + + ff_dsputil_init(&s->dsp, avctx); + + s->width = avctx->width; + s->height = avctx->height; + + av_assert1(s->width > 0 && s->height > 0); +} + +av_cold void ff_huffyuv_common_end(HYuvContext *s) +{ + int i; + + for(i = 0; i < 3; i++) { + av_freep(&s->temp[i]); + } +} diff --git a/ffmpeg/libavcodec/huffyuv.h b/ffmpeg/libavcodec/huffyuv.h new file mode 100644 index 0000000..e34b562 --- /dev/null +++ b/ffmpeg/libavcodec/huffyuv.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2002-2003 Michael Niedermayer + * + * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of + * the algorithm used + * + * 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 + */ + +/** + * @file + * huffyuv codec for libavcodec. + */ + +#ifndef AVCODEC_HUFFYUV_H +#define AVCODEC_HUFFYUV_H + +#include + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "put_bits.h" + +#define VLC_BITS 11 + +#if HAVE_BIGENDIAN +#define B 3 +#define G 2 +#define R 1 +#define A 0 +#else +#define B 0 +#define G 1 +#define R 2 +#define A 3 +#endif + +typedef enum Predictor { + LEFT = 0, + PLANE, + MEDIAN, +} Predictor; + +typedef struct HYuvContext { + AVCodecContext *avctx; + Predictor predictor; + GetBitContext gb; + PutBitContext pb; + int interlaced; + int decorrelate; + int bitstream_bpp; + int version; + int yuy2; //use yuy2 instead of 422P + int bgr32; //use bgr32 instead of bgr24 + int width, height; + int flags; + int context; + int picture_number; + int last_slice_end; + uint8_t *temp[3]; + uint64_t stats[3][256]; + uint8_t len[3][256]; + uint32_t bits[3][256]; + uint32_t pix_bgr_map[1< + * + * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of + * the algorithm used + * + * 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 + */ + +/** + * @file + * huffyuv decoder + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "huffyuv.h" +#include "thread.h" + +#define classic_shift_luma_table_size 42 +static const unsigned char classic_shift_luma[classic_shift_luma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = { + 34,36,35,69,135,232,9,16,10,24,11,23,12,16,13,10,14,8,15,8, + 16,8,17,20,16,10,207,206,205,236,11,8,10,21,9,23,8,8,199,70, + 69,68, 0, + 0,0,0,0,0,0,0,0, +}; + +#define classic_shift_chroma_table_size 59 +static const unsigned char classic_shift_chroma[classic_shift_chroma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = { + 66,36,37,38,39,40,41,75,76,77,110,239,144,81,82,83,84,85,118,183, + 56,57,88,89,56,89,154,57,58,57,26,141,57,56,58,57,58,57,184,119, + 214,245,116,83,82,49,80,79,78,77,44,75,41,40,39,38,37,36,34, 0, + 0,0,0,0,0,0,0,0, +}; + +static const unsigned char classic_add_luma[256] = { + 3, 9, 5, 12, 10, 35, 32, 29, 27, 50, 48, 45, 44, 41, 39, 37, + 73, 70, 68, 65, 64, 61, 58, 56, 53, 50, 49, 46, 44, 41, 38, 36, + 68, 65, 63, 61, 58, 55, 53, 51, 48, 46, 45, 43, 41, 39, 38, 36, + 35, 33, 32, 30, 29, 27, 26, 25, 48, 47, 46, 44, 43, 41, 40, 39, + 37, 36, 35, 34, 32, 31, 30, 28, 27, 26, 24, 23, 22, 20, 19, 37, + 35, 34, 33, 31, 30, 29, 27, 26, 24, 23, 21, 20, 18, 17, 15, 29, + 27, 26, 24, 22, 21, 19, 17, 16, 14, 26, 25, 23, 21, 19, 18, 16, + 15, 27, 25, 23, 21, 19, 17, 16, 14, 26, 25, 23, 21, 18, 17, 14, + 12, 17, 19, 13, 4, 9, 2, 11, 1, 7, 8, 0, 16, 3, 14, 6, + 12, 10, 5, 15, 18, 11, 10, 13, 15, 16, 19, 20, 22, 24, 27, 15, + 18, 20, 22, 24, 26, 14, 17, 20, 22, 24, 27, 15, 18, 20, 23, 25, + 28, 16, 19, 22, 25, 28, 32, 36, 21, 25, 29, 33, 38, 42, 45, 49, + 28, 31, 34, 37, 40, 42, 44, 47, 49, 50, 52, 54, 56, 57, 59, 60, + 62, 64, 66, 67, 69, 35, 37, 39, 40, 42, 43, 45, 47, 48, 51, 52, + 54, 55, 57, 59, 60, 62, 63, 66, 67, 69, 71, 72, 38, 40, 42, 43, + 46, 47, 49, 51, 26, 28, 30, 31, 33, 34, 18, 19, 11, 13, 7, 8, +}; + +static const unsigned char classic_add_chroma[256] = { + 3, 1, 2, 2, 2, 2, 3, 3, 7, 5, 7, 5, 8, 6, 11, 9, + 7, 13, 11, 10, 9, 8, 7, 5, 9, 7, 6, 4, 7, 5, 8, 7, + 11, 8, 13, 11, 19, 15, 22, 23, 20, 33, 32, 28, 27, 29, 51, 77, + 43, 45, 76, 81, 46, 82, 75, 55, 56,144, 58, 80, 60, 74,147, 63, + 143, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 27, 30, 21, 22, + 17, 14, 5, 6,100, 54, 47, 50, 51, 53,106,107,108,109,110,111, + 112,113,114,115, 4,117,118, 92, 94,121,122, 3,124,103, 2, 1, + 0,129,130,131,120,119,126,125,136,137,138,139,140,141,142,134, + 135,132,133,104, 64,101, 62, 57,102, 95, 93, 59, 61, 28, 97, 96, + 52, 49, 48, 29, 32, 25, 24, 46, 23, 98, 45, 44, 43, 20, 42, 41, + 19, 18, 99, 40, 15, 39, 38, 16, 13, 12, 11, 37, 10, 9, 8, 36, + 7,128,127,105,123,116, 35, 34, 33,145, 31, 79, 42,146, 78, 26, + 83, 48, 49, 50, 44, 47, 26, 31, 30, 18, 17, 19, 21, 24, 25, 13, + 14, 16, 17, 18, 20, 21, 12, 14, 15, 9, 10, 6, 9, 6, 5, 8, + 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) +{ + int i, val, repeat; + + for (i = 0; i < 256;) { + 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) { + av_log(NULL, AV_LOG_ERROR, "Error reading huffman table\n"); + return -1; + } + while (repeat--) + dst[i++] = val; + } + return 0; +} + +static int generate_joint_tables(HYuvContext *s) +{ + uint16_t symbols[1 << VLC_BITS]; + uint16_t bits[1 << VLC_BITS]; + uint8_t len[1 << VLC_BITS]; + int ret; + + if (s->bitstream_bpp < 24) { + int p, i, y, u; + for (p = 0; p < 3; p++) { + for (i = y = 0; y < 256; y++) { + int len0 = s->len[0][y]; + int limit = VLC_BITS - len0; + if(limit <= 0 || !len0) + continue; + for (u = 0; u < 256; 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[0][y] << len1) + s->bits[p][u]; + symbols[i] = (y << 8) + u; + if(symbols[i] != 0xffff) // reserved to mean "invalid" + i++; + } + } + ff_free_vlc(&s->vlc[3 + p]); + if ((ret = ff_init_vlc_sparse(&s->vlc[3 + p], VLC_BITS, i, len, 1, 1, + bits, 2, 2, symbols, 2, 2, 0)) < 0) + return ret; + } + } else { + uint8_t (*map)[4] = (uint8_t(*)[4])s->pix_bgr_map; + int i, b, g, r, code; + int p0 = s->decorrelate; + int p1 = !s->decorrelate; + // restrict the range to +/-16 because that's pretty much guaranteed to + // cover all the combinations that fit in 11 bits total, and it doesn't + // matter if we miss a few rare codes. + for (i = 0, g = -16; g < 16; g++) { + int len0 = s->len[p0][g & 255]; + int limit0 = VLC_BITS - len0; + if (limit0 < 2 || !len0) + continue; + for (b = -16; b < 16; b++) { + int len1 = s->len[p1][b & 255]; + int limit1 = limit0 - len1; + if (limit1 < 1 || !len1) + continue; + code = (s->bits[p0][g & 255] << len1) + s->bits[p1][b & 255]; + for (r = -16; r < 16; r++) { + int len2 = s->len[2][r & 255]; + if (len2 > limit1 || !len2) + continue; + av_assert0(i < (1 << VLC_BITS)); + len[i] = len0 + len1 + len2; + bits[i] = (code << len2) + s->bits[2][r & 255]; + if (s->decorrelate) { + map[i][G] = g; + map[i][B] = g + b; + map[i][R] = g + r; + } else { + map[i][B] = g; + map[i][G] = b; + map[i][R] = r; + } + i++; + } + } + } + ff_free_vlc(&s->vlc[3]); + if ((ret = init_vlc(&s->vlc[3], VLC_BITS, i, len, 1, 1, bits, 2, 2, 0)) < 0) + return ret; + } + return 0; +} + +static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length) +{ + GetBitContext gb; + int i; + int ret; + + init_get_bits(&gb, src, length * 8); + + for (i = 0; i < 3; i++) { + if (read_len_table(s->len[i], &gb) < 0) + return -1; + if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i]) < 0) { + return -1; + } + ff_free_vlc(&s->vlc[i]); + if ((ret = init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, + s->bits[i], 4, 4, 0)) < 0) + return ret; + } + + if ((ret = generate_joint_tables(s)) < 0) + return ret; + + return (get_bits_count(&gb) + 7) / 8; +} + +static int read_old_huffman_tables(HYuvContext *s) +{ + GetBitContext gb; + int i; + int ret; + + init_get_bits(&gb, classic_shift_luma, + classic_shift_luma_table_size * 8); + if (read_len_table(s->len[0], &gb) < 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) + return -1; + + for(i=0; i<256; i++) s->bits[0][i] = classic_add_luma [i]; + for(i=0; i<256; i++) s->bits[1][i] = classic_add_chroma[i]; + + if (s->bitstream_bpp >= 24) { + memcpy(s->bits[1], s->bits[0], 256 * sizeof(uint32_t)); + memcpy(s->len[1] , s->len [0], 256 * sizeof(uint8_t)); + } + memcpy(s->bits[2], s->bits[1], 256 * sizeof(uint32_t)); + memcpy(s->len[2] , s->len [1], 256 * sizeof(uint8_t)); + + for (i = 0; i < 3; i++) { + ff_free_vlc(&s->vlc[i]); + if ((ret = init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1, + s->bits[i], 4, 4, 0)) < 0) + return ret; + } + + if ((ret = generate_joint_tables(s)) < 0) + return ret; + + return 0; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + + ff_huffyuv_common_init(avctx); + memset(s->vlc, 0, 3 * sizeof(VLC)); + + avcodec_get_frame_defaults(&s->picture); + s->interlaced = s->height > 288; + + s->bgr32 = 1; + + if (avctx->extradata_size) { + if ((avctx->bits_per_coded_sample & 7) && + avctx->bits_per_coded_sample != 12) + s->version = 1; // do such files exist at all? + else + s->version = 2; + } else + s->version = 0; + + if (s->version == 2) { + int method, interlace; + + if (avctx->extradata_size < 4) + return -1; + + method = ((uint8_t*)avctx->extradata)[0]; + s->decorrelate = method & 64 ? 1 : 0; + s->predictor = method & 63; + s->bitstream_bpp = ((uint8_t*)avctx->extradata)[1]; + if (s->bitstream_bpp == 0) + s->bitstream_bpp = avctx->bits_per_coded_sample & ~7; + interlace = (((uint8_t*)avctx->extradata)[2] & 0x30) >> 4; + s->interlaced = (interlace == 1) ? 1 : (interlace == 2) ? 0 : s->interlaced; + s->context = ((uint8_t*)avctx->extradata)[2] & 0x40 ? 1 : 0; + + if ( read_huffman_tables(s, ((uint8_t*)avctx->extradata) + 4, + avctx->extradata_size - 4) < 0) + return AVERROR_INVALIDDATA; + }else{ + switch (avctx->bits_per_coded_sample & 7) { + case 1: + s->predictor = LEFT; + s->decorrelate = 0; + break; + case 2: + s->predictor = LEFT; + s->decorrelate = 1; + break; + case 3: + s->predictor = PLANE; + s->decorrelate = avctx->bits_per_coded_sample >= 24; + break; + case 4: + s->predictor = MEDIAN; + s->decorrelate = 0; + break; + default: + s->predictor = LEFT; //OLD + s->decorrelate = 0; + break; + } + s->bitstream_bpp = avctx->bits_per_coded_sample & ~7; + s->context = 0; + + if (read_old_huffman_tables(s) < 0) + return AVERROR_INVALIDDATA; + } + + switch (s->bitstream_bpp) { + case 12: + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + break; + case 16: + if (s->yuy2) { + avctx->pix_fmt = AV_PIX_FMT_YUYV422; + } else { + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + } + break; + case 24: + case 32: + if (s->bgr32) { + avctx->pix_fmt = AV_PIX_FMT_RGB32; + } else { + avctx->pix_fmt = AV_PIX_FMT_BGR24; + } + break; + default: + return AVERROR_INVALIDDATA; + } + + if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUV420P) && avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n"); + return AVERROR_INVALIDDATA; + } + if (s->predictor == MEDIAN && avctx->pix_fmt == AV_PIX_FMT_YUV422P && avctx->width%4) { + av_log(avctx, AV_LOG_ERROR, "width must be a multiple of 4 this colorspace and predictor\n"); + return AVERROR_INVALIDDATA; + } + if (ff_huffyuv_alloc_temp(s)) { + ff_huffyuv_common_end(s); + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int decode_init_thread_copy(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + int i; + + if (ff_huffyuv_alloc_temp(s)) { + ff_huffyuv_common_end(s); + return AVERROR(ENOMEM); + } + + for (i = 0; i < 6; i++) + s->vlc[i].table = NULL; + + if (s->version == 2) { + if (read_huffman_tables(s, ((uint8_t*)avctx->extradata) + 4, + avctx->extradata_size) < 0) + return AVERROR_INVALIDDATA; + } else { + if (read_old_huffman_tables(s) < 0) + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/* TODO instead of restarting the read when the code isn't in the first level + * of the joint table, jump into the 2nd level of the individual table. */ +#define READ_2PIX(dst0, dst1, plane1){\ + uint16_t code = get_vlc2(&s->gb, s->vlc[3+plane1].table, VLC_BITS, 1);\ + if(code != 0xffff){\ + dst0 = code>>8;\ + dst1 = code;\ + }else{\ + dst0 = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);\ + dst1 = get_vlc2(&s->gb, s->vlc[plane1].table, VLC_BITS, 3);\ + }\ +} + +static void decode_422_bitstream(HYuvContext *s, int count) +{ + int i; + + count /= 2; + + if (count >= (get_bits_left(&s->gb)) / (31 * 4)) { + for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) { + READ_2PIX(s->temp[0][2 * i ], s->temp[1][i], 1); + READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2); + } + } else { + for (i = 0; i < count; i++) { + READ_2PIX(s->temp[0][2 * i ], s->temp[1][i], 1); + READ_2PIX(s->temp[0][2 * i + 1], s->temp[2][i], 2); + } + } +} + +static void decode_gray_bitstream(HYuvContext *s, int count) +{ + 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(s->temp[0][2 * i], s->temp[0][2 * i + 1], 0); + } + } else { + for(i=0; itemp[0][2 * i], s->temp[0][2 * i + 1], 0); + } + } +} + +static av_always_inline void decode_bgr_1(HYuvContext *s, int count, + int decorrelate, int alpha) +{ + int i; + for (i = 0; i < count; i++) { + int code = get_vlc2(&s->gb, s->vlc[3].table, VLC_BITS, 1); + if (code != -1) { + *(uint32_t*)&s->temp[0][4 * i] = s->pix_bgr_map[code]; + } else if(decorrelate) { + s->temp[0][4 * i + G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3); + s->temp[0][4 * i + B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3) + + s->temp[0][4 * i + G]; + s->temp[0][4 * i + R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3) + + s->temp[0][4 * i + G]; + } else { + s->temp[0][4 * i + B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3); + s->temp[0][4 * i + G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3); + s->temp[0][4 * i + R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); + } + if (alpha) + s->temp[0][4 * i + A] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); + } +} + +static void decode_bgr_bitstream(HYuvContext *s, int count) +{ + if (s->decorrelate) { + if (s->bitstream_bpp==24) + decode_bgr_1(s, count, 1, 0); + else + decode_bgr_1(s, count, 1, 1); + } else { + if (s->bitstream_bpp==24) + decode_bgr_1(s, count, 0, 0); + else + decode_bgr_1(s, count, 0, 1); + } +} + +static void draw_slice(HYuvContext *s, AVFrame *frame, int y) +{ + int h, cy, i; + int offset[AV_NUM_DATA_POINTERS]; + + if (s->avctx->draw_horiz_band==NULL) + return; + + h = y - s->last_slice_end; + y -= h; + + if (s->bitstream_bpp == 12) { + cy = y>>1; + } else { + cy = y; + } + + offset[0] = frame->linesize[0] * y; + offset[1] = frame->linesize[1] * cy; + offset[2] = frame->linesize[2] * cy; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + emms_c(); + + s->avctx->draw_horiz_band(s->avctx, frame, offset, y, 3, h); + + s->last_slice_end = y + h; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + HYuvContext *s = avctx->priv_data; + const int width = s->width; + const int width2 = s->width>>1; + const int height = s->height; + int fake_ystride, fake_ustride, fake_vstride; + ThreadFrame frame = { .f = data }; + AVFrame * const p = data; + int table_size = 0, ret; + + av_fast_padded_malloc(&s->bitstream_buffer, + &s->bitstream_buffer_size, + buf_size); + if (!s->bitstream_buffer) + return AVERROR(ENOMEM); + + s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, + (const uint32_t*)buf, buf_size / 4); + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + if (s->context) { + table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size); + if (table_size < 0) + return AVERROR_INVALIDDATA; + } + + if ((unsigned)(buf_size-table_size) >= INT_MAX / 8) + return AVERROR_INVALIDDATA; + + init_get_bits(&s->gb, s->bitstream_buffer+table_size, + (buf_size-table_size) * 8); + + fake_ystride = s->interlaced ? p->linesize[0] * 2 : p->linesize[0]; + fake_ustride = s->interlaced ? p->linesize[1] * 2 : p->linesize[1]; + fake_vstride = s->interlaced ? p->linesize[2] * 2 : p->linesize[2]; + + s->last_slice_end = 0; + + if (s->bitstream_bpp < 24) { + int y, cy; + int lefty, leftu, leftv; + int lefttopy, lefttopu, lefttopv; + + if (s->yuy2) { + p->data[0][3] = get_bits(&s->gb, 8); + p->data[0][2] = get_bits(&s->gb, 8); + p->data[0][1] = get_bits(&s->gb, 8); + p->data[0][0] = get_bits(&s->gb, 8); + + av_log(avctx, AV_LOG_ERROR, + "YUY2 output is not implemented yet\n"); + return AVERROR_PATCHWELCOME; + } else { + + leftv = p->data[2][0] = get_bits(&s->gb, 8); + lefty = p->data[0][1] = get_bits(&s->gb, 8); + leftu = p->data[1][0] = get_bits(&s->gb, 8); + p->data[0][0] = get_bits(&s->gb, 8); + + switch (s->predictor) { + case LEFT: + case PLANE: + decode_422_bitstream(s, width-2); + lefty = s->dsp.add_hfyu_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty); + if (!(s->flags&CODEC_FLAG_GRAY)) { + leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + 1, s->temp[1], width2 - 1, leftu); + leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + 1, s->temp[2], width2 - 1, leftv); + } + + for (cy = y = 1; y < s->height; y++, cy++) { + uint8_t *ydst, *udst, *vdst; + + if (s->bitstream_bpp == 12) { + decode_gray_bitstream(s, width); + + ydst = p->data[0] + p->linesize[0] * y; + + lefty = s->dsp.add_hfyu_left_prediction(ydst, s->temp[0], width, lefty); + if (s->predictor == PLANE) { + if (y > s->interlaced) + s->dsp.add_bytes(ydst, ydst - fake_ystride, width); + } + y++; + if (y >= s->height) break; + } + + draw_slice(s, p, y); + + ydst = p->data[0] + p->linesize[0]*y; + udst = p->data[1] + p->linesize[1]*cy; + vdst = p->data[2] + p->linesize[2]*cy; + + decode_422_bitstream(s, width); + lefty = s->dsp.add_hfyu_left_prediction(ydst, s->temp[0], width, lefty); + if (!(s->flags & CODEC_FLAG_GRAY)) { + leftu= s->dsp.add_hfyu_left_prediction(udst, s->temp[1], width2, leftu); + leftv= s->dsp.add_hfyu_left_prediction(vdst, s->temp[2], width2, leftv); + } + if (s->predictor == PLANE) { + if (cy > s->interlaced) { + s->dsp.add_bytes(ydst, ydst - fake_ystride, width); + if (!(s->flags & CODEC_FLAG_GRAY)) { + s->dsp.add_bytes(udst, udst - fake_ustride, width2); + s->dsp.add_bytes(vdst, vdst - fake_vstride, width2); + } + } + } + } + draw_slice(s, p, height); + + break; + case MEDIAN: + /* first line except first 2 pixels is left predicted */ + decode_422_bitstream(s, width - 2); + lefty= s->dsp.add_hfyu_left_prediction(p->data[0] + 2, s->temp[0], width - 2, lefty); + if (!(s->flags & CODEC_FLAG_GRAY)) { + leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + 1, s->temp[1], width2 - 1, leftu); + leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + 1, s->temp[2], width2 - 1, leftv); + } + + cy = y = 1; + + /* second line is left predicted for interlaced case */ + if (s->interlaced) { + decode_422_bitstream(s, width); + lefty = s->dsp.add_hfyu_left_prediction(p->data[0] + p->linesize[0], s->temp[0], width, lefty); + if (!(s->flags & CODEC_FLAG_GRAY)) { + leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + p->linesize[2], s->temp[1], width2, leftu); + leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + p->linesize[1], s->temp[2], width2, leftv); + } + y++; cy++; + } + + /* next 4 pixels are left predicted too */ + decode_422_bitstream(s, 4); + lefty = s->dsp.add_hfyu_left_prediction(p->data[0] + fake_ystride, s->temp[0], 4, lefty); + if (!(s->flags&CODEC_FLAG_GRAY)) { + leftu = s->dsp.add_hfyu_left_prediction(p->data[1] + fake_ustride, s->temp[1], 2, leftu); + leftv = s->dsp.add_hfyu_left_prediction(p->data[2] + fake_vstride, s->temp[2], 2, leftv); + } + + /* next line except the first 4 pixels is median predicted */ + lefttopy = p->data[0][3]; + decode_422_bitstream(s, width - 4); + s->dsp.add_hfyu_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy); + if (!(s->flags&CODEC_FLAG_GRAY)) { + lefttopu = p->data[1][1]; + lefttopv = p->data[2][1]; + s->dsp.add_hfyu_median_prediction(p->data[1] + fake_ustride+2, p->data[1] + 2, s->temp[1], width2 - 2, &leftu, &lefttopu); + s->dsp.add_hfyu_median_prediction(p->data[2] + fake_vstride+2, p->data[2] + 2, s->temp[2], width2 - 2, &leftv, &lefttopv); + } + y++; cy++; + + for (; ybitstream_bpp == 12) { + while (2 * cy > y) { + decode_gray_bitstream(s, width); + ydst = p->data[0] + p->linesize[0] * y; + s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); + y++; + } + if (y >= height) break; + } + draw_slice(s, p, y); + + decode_422_bitstream(s, width); + + ydst = p->data[0] + p->linesize[0] * y; + udst = p->data[1] + p->linesize[1] * cy; + vdst = p->data[2] + p->linesize[2] * cy; + + s->dsp.add_hfyu_median_prediction(ydst, ydst - fake_ystride, s->temp[0], width, &lefty, &lefttopy); + if (!(s->flags & CODEC_FLAG_GRAY)) { + s->dsp.add_hfyu_median_prediction(udst, udst - fake_ustride, s->temp[1], width2, &leftu, &lefttopu); + s->dsp.add_hfyu_median_prediction(vdst, vdst - fake_vstride, s->temp[2], width2, &leftv, &lefttopv); + } + } + + draw_slice(s, p, height); + break; + } + } + } else { + int y; + int leftr, leftg, leftb, lefta; + const int last_line = (height - 1) * p->linesize[0]; + + if (s->bitstream_bpp == 32) { + lefta = p->data[0][last_line+A] = get_bits(&s->gb, 8); + leftr = p->data[0][last_line+R] = get_bits(&s->gb, 8); + leftg = p->data[0][last_line+G] = get_bits(&s->gb, 8); + leftb = p->data[0][last_line+B] = get_bits(&s->gb, 8); + } else { + leftr = p->data[0][last_line+R] = get_bits(&s->gb, 8); + leftg = p->data[0][last_line+G] = get_bits(&s->gb, 8); + leftb = p->data[0][last_line+B] = get_bits(&s->gb, 8); + lefta = p->data[0][last_line+A] = 255; + skip_bits(&s->gb, 8); + } + + if (s->bgr32) { + switch (s->predictor) { + case LEFT: + case PLANE: + decode_bgr_bitstream(s, width - 1); + s->dsp.add_hfyu_left_prediction_bgr32(p->data[0] + last_line+4, s->temp[0], width - 1, &leftr, &leftg, &leftb, &lefta); + + for (y = s->height - 2; y >= 0; y--) { //Yes it is stored upside down. + decode_bgr_bitstream(s, width); + + s->dsp.add_hfyu_left_prediction_bgr32(p->data[0] + p->linesize[0]*y, s->temp[0], width, &leftr, &leftg, &leftb, &lefta); + if (s->predictor == PLANE) { + if (s->bitstream_bpp != 32) lefta = 0; + if ((y & s->interlaced) == 0 && + y < s->height - 1 - s->interlaced) { + s->dsp.add_bytes(p->data[0] + p->linesize[0] * y, + p->data[0] + p->linesize[0] * y + + fake_ystride, fake_ystride); + } + } + } + // just 1 large slice as this is not possible in reverse order + draw_slice(s, p, height); + break; + default: + av_log(avctx, AV_LOG_ERROR, + "prediction type not supported!\n"); + } + }else{ + av_log(avctx, AV_LOG_ERROR, + "BGR24 output is not implemented yet\n"); + return AVERROR_PATCHWELCOME; + } + } + emms_c(); + + *got_frame = 1; + + return (get_bits_count(&s->gb) + 31) / 32 * 4 + table_size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + int i; + + ff_huffyuv_common_end(s); + av_freep(&s->bitstream_buffer); + + for (i = 0; i < 6; i++) { + ff_free_vlc(&s->vlc[i]); + } + + return 0; +} + +#if CONFIG_HUFFYUV_DECODER +AVCodec ff_huffyuv_decoder = { + .name = "huffyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HUFFYUV, + .priv_data_size = sizeof(HYuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_FRAME_THREADS, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), +}; +#endif + +#if CONFIG_FFVHUFF_DECODER +AVCodec ff_ffvhuff_decoder = { + .name = "ffvhuff", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FFVHUFF, + .priv_data_size = sizeof(HYuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_FRAME_THREADS, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), +}; +#endif diff --git a/ffmpeg/libavcodec/huffyuvenc.c b/ffmpeg/libavcodec/huffyuvenc.c new file mode 100644 index 0000000..95dcb88 --- /dev/null +++ b/ffmpeg/libavcodec/huffyuvenc.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2002-2003 Michael Niedermayer + * + * see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of + * the algorithm used + * + * 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 + */ + +/** + * @file + * huffyuv encoder + */ + +#include "avcodec.h" +#include "huffyuv.h" +#include "huffman.h" +#include "internal.h" +#include "put_bits.h" + +static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst, + const uint8_t *src, int w, int left) +{ + int i; + if (w < 32) { + for (i = 0; i < w; i++) { + const int temp = src[i]; + dst[i] = temp - left; + left = temp; + } + return left; + } else { + for (i = 0; i < 16; i++) { + const int temp = src[i]; + dst[i] = temp - left; + left = temp; + } + s->dsp.diff_bytes(dst + 16, src + 16, src + 15, w - 16); + return src[w-1]; + } +} + +static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst, + const uint8_t *src, int w, + int *red, int *green, int *blue, int *alpha) +{ + int i; + int r,g,b,a; + r = *red; + g = *green; + b = *blue; + a = *alpha; + for (i = 0; i < FFMIN(w, 4); i++) { + const int rt = src[i * 4 + R]; + const int gt = src[i * 4 + G]; + const int bt = src[i * 4 + B]; + const int at = src[i * 4 + A]; + dst[i * 4 + R] = rt - r; + dst[i * 4 + G] = gt - g; + dst[i * 4 + B] = bt - b; + dst[i * 4 + A] = at - a; + r = rt; + g = gt; + b = bt; + a = at; + } + + s->dsp.diff_bytes(dst + 16, src + 16, src + 12, w * 4 - 16); + + *red = src[(w - 1) * 4 + R]; + *green = src[(w - 1) * 4 + G]; + *blue = src[(w - 1) * 4 + B]; + *alpha = src[(w - 1) * 4 + A]; +} + +static inline void sub_left_prediction_rgb24(HYuvContext *s, uint8_t *dst, const uint8_t *src, int w, int *red, int *green, int *blue){ + int i; + int r,g,b; + r = *red; + g = *green; + b = *blue; + for (i = 0; i < FFMIN(w,16); i++) { + const int rt = src[i*3 + 0]; + const int gt = src[i*3 + 1]; + const int bt = src[i*3 + 2]; + dst[i*3 + 0] = rt - r; + dst[i*3 + 1] = gt - g; + dst[i*3 + 2] = bt - b; + r = rt; + g = gt; + b = bt; + } + + s->dsp.diff_bytes(dst + 48, src + 48, src + 48 - 3, w*3 - 48); + + *red = src[(w - 1)*3 + 0]; + *green = src[(w - 1)*3 + 1]; + *blue = src[(w - 1)*3 + 2]; +} + +static int store_table(HYuvContext *s, const uint8_t *len, uint8_t *buf) +{ + int i; + int index = 0; + + for (i = 0; i < 256;) { + int val = len[i]; + int repeat = 0; + + for (; i < 256 && len[i] == val && repeat < 255; i++) + repeat++; + + av_assert0(val < 32 && val >0 && repeat<256 && repeat>0); + if (repeat > 7) { + buf[index++] = val; + buf[index++] = repeat; + } else { + buf[index++] = val | (repeat << 5); + } + } + + return index; +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + int i, j; + + ff_huffyuv_common_init(avctx); + + avctx->extradata = av_mallocz(1024*30); // 256*3+4 == 772 + avctx->stats_out = av_mallocz(1024*30); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132 + if (!avctx->extradata || !avctx->stats_out) { + av_freep(&avctx->stats_out); + return AVERROR(ENOMEM); + } + s->version = 2; + + avctx->coded_frame = &s->picture; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + if (s->width & 1) { + av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n"); + return AVERROR(EINVAL); + } + s->bitstream_bpp = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 12 : 16; + break; + case AV_PIX_FMT_RGB32: + s->bitstream_bpp = 32; + break; + case AV_PIX_FMT_RGB24: + s->bitstream_bpp = 24; + break; + default: + av_log(avctx, AV_LOG_ERROR, "format not supported\n"); + return AVERROR(EINVAL); + } + avctx->bits_per_coded_sample = s->bitstream_bpp; + s->decorrelate = s->bitstream_bpp >= 24; + s->predictor = avctx->prediction_method; + s->interlaced = avctx->flags&CODEC_FLAG_INTERLACED_ME ? 1 : 0; + if (avctx->context_model == 1) { + s->context = avctx->context_model; + if (s->flags & (CODEC_FLAG_PASS1|CODEC_FLAG_PASS2)) { + av_log(avctx, AV_LOG_ERROR, + "context=1 is not compatible with " + "2 pass huffyuv encoding\n"); + return AVERROR(EINVAL); + } + }else s->context= 0; + + if (avctx->codec->id == AV_CODEC_ID_HUFFYUV) { + if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) { + av_log(avctx, AV_LOG_ERROR, + "Error: YV12 is not supported by huffyuv; use " + "vcodec=ffvhuff or format=422p\n"); + return AVERROR(EINVAL); + } + if (avctx->context_model) { + av_log(avctx, AV_LOG_ERROR, + "Error: per-frame huffman tables are not supported " + "by huffyuv; use vcodec=ffvhuff\n"); + return AVERROR(EINVAL); + } + if (s->interlaced != ( s->height > 288 )) + av_log(avctx, AV_LOG_INFO, + "using huffyuv 2.2.0 or newer interlacing flag\n"); + } + + if (s->bitstream_bpp >= 24 && s->predictor == MEDIAN) { + av_log(avctx, AV_LOG_ERROR, + "Error: RGB is incompatible with median predictor\n"); + return AVERROR(EINVAL); + } + + ((uint8_t*)avctx->extradata)[0] = s->predictor | (s->decorrelate << 6); + ((uint8_t*)avctx->extradata)[1] = s->bitstream_bpp; + ((uint8_t*)avctx->extradata)[2] = s->interlaced ? 0x10 : 0x20; + if (s->context) + ((uint8_t*)avctx->extradata)[2] |= 0x40; + ((uint8_t*)avctx->extradata)[3] = 0; + s->avctx->extradata_size = 4; + + if (avctx->stats_in) { + char *p = avctx->stats_in; + + for (i = 0; i < 3; i++) + for (j = 0; j < 256; j++) + s->stats[i][j] = 1; + + for (;;) { + for (i = 0; i < 3; i++) { + char *next; + + for (j = 0; j < 256; j++) { + s->stats[i][j] += strtol(p, &next, 0); + if (next == p) return -1; + p = next; + } + } + if (p[0] == 0 || p[1] == 0 || p[2] == 0) break; + } + } else { + for (i = 0; i < 3; i++) + for (j = 0; j < 256; j++) { + int d = FFMIN(j, 256 - j); + + s->stats[i][j] = 100000000 / (d + 1); + } + } + + for (i = 0; i < 3; i++) { + ff_huff_gen_len_table(s->len[i], s->stats[i]); + + if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i]) < 0) { + return -1; + } + + s->avctx->extradata_size += + store_table(s, s->len[i], &((uint8_t*)s->avctx->extradata)[s->avctx->extradata_size]); + } + + if (s->context) { + for (i = 0; i < 3; i++) { + int pels = s->width * s->height / (i ? 40 : 10); + for (j = 0; j < 256; j++) { + int d = FFMIN(j, 256 - j); + s->stats[i][j] = pels/(d + 1); + } + } + } else { + for (i = 0; i < 3; i++) + for (j = 0; j < 256; j++) + s->stats[i][j]= 0; + } + + if (ff_huffyuv_alloc_temp(s)) { + ff_huffyuv_common_end(s); + return AVERROR(ENOMEM); + } + + s->picture_number=0; + + return 0; +} +static int encode_422_bitstream(HYuvContext *s, int offset, int count) +{ + int i; + const uint8_t *y = s->temp[0] + offset; + const uint8_t *u = s->temp[1] + offset / 2; + const uint8_t *v = s->temp[2] + offset / 2; + + if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < 2 * 4 * count) { + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + +#define LOAD4\ + int y0 = y[2 * i];\ + int y1 = y[2 * i + 1];\ + int u0 = u[i];\ + int v0 = v[i]; + + count /= 2; + + if (s->flags & CODEC_FLAG_PASS1) { + for(i = 0; i < count; i++) { + LOAD4; + s->stats[0][y0]++; + s->stats[1][u0]++; + s->stats[0][y1]++; + s->stats[2][v0]++; + } + } + if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT) + return 0; + if (s->context) { + for (i = 0; i < count; i++) { + LOAD4; + s->stats[0][y0]++; + put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]); + s->stats[1][u0]++; + put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]); + s->stats[0][y1]++; + put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]); + s->stats[2][v0]++; + put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]); + } + } else { + for(i = 0; i < count; i++) { + LOAD4; + put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]); + put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]); + put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]); + put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]); + } + } + return 0; +} + +static int encode_gray_bitstream(HYuvContext *s, int count) +{ + int i; + + if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < 4 * count) { + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + +#define LOAD2\ + int y0 = s->temp[0][2 * i];\ + int y1 = s->temp[0][2 * i + 1]; +#define STAT2\ + s->stats[0][y0]++;\ + s->stats[0][y1]++; +#define WRITE2\ + put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);\ + put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]); + + count /= 2; + + if (s->flags & CODEC_FLAG_PASS1) { + for (i = 0; i < count; i++) { + LOAD2; + STAT2; + } + } + if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT) + return 0; + + if (s->context) { + for (i = 0; i < count; i++) { + LOAD2; + STAT2; + WRITE2; + } + } else { + for (i = 0; i < count; i++) { + LOAD2; + WRITE2; + } + } + return 0; +} + +static inline int encode_bgra_bitstream(HYuvContext *s, int count, int planes) +{ + int i; + + if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 4*planes*count) { + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + +#define LOAD3\ + int g = s->temp[0][planes==3 ? 3*i + 1 : 4*i + G];\ + int b = (s->temp[0][planes==3 ? 3*i + 2 : 4*i + B] - g) & 0xff;\ + int r = (s->temp[0][planes==3 ? 3*i + 0 : 4*i + R] - g) & 0xff;\ + int a = s->temp[0][planes*i + A]; +#define STAT3\ + s->stats[0][b]++;\ + s->stats[1][g]++;\ + s->stats[2][r]++;\ + if(planes==4) s->stats[2][a]++; +#define WRITE3\ + put_bits(&s->pb, s->len[1][g], s->bits[1][g]);\ + put_bits(&s->pb, s->len[0][b], s->bits[0][b]);\ + put_bits(&s->pb, s->len[2][r], s->bits[2][r]);\ + if(planes==4) put_bits(&s->pb, s->len[2][a], s->bits[2][a]); + + if ((s->flags & CODEC_FLAG_PASS1) && + (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)) { + for (i = 0; i < count; i++) { + LOAD3; + STAT3; + } + } else if (s->context || (s->flags & CODEC_FLAG_PASS1)) { + for (i = 0; i < count; i++) { + LOAD3; + STAT3; + WRITE3; + } + } else { + for (i = 0; i < count; i++) { + LOAD3; + WRITE3; + } + } + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + HYuvContext *s = avctx->priv_data; + const int width = s->width; + const int width2 = s->width>>1; + const int height = s->height; + const int fake_ystride = s->interlaced ? pict->linesize[0]*2 : pict->linesize[0]; + const int fake_ustride = s->interlaced ? pict->linesize[1]*2 : pict->linesize[1]; + const int fake_vstride = s->interlaced ? pict->linesize[2]*2 : pict->linesize[2]; + AVFrame * const p = &s->picture; + int i, j, size = 0, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, width * height * 3 * 4 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + *p = *pict; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + if (s->context) { + for (i = 0; i < 3; i++) { + ff_huff_gen_len_table(s->len[i], s->stats[i]); + if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i]) < 0) + return -1; + size += store_table(s, s->len[i], &pkt->data[size]); + } + + for (i = 0; i < 3; i++) + for (j = 0; j < 256; j++) + s->stats[i][j] >>= 1; + } + + init_put_bits(&s->pb, pkt->data + size, pkt->size - size); + + if (avctx->pix_fmt == AV_PIX_FMT_YUV422P || + avctx->pix_fmt == AV_PIX_FMT_YUV420P) { + int lefty, leftu, leftv, y, cy; + + put_bits(&s->pb, 8, leftv = p->data[2][0]); + put_bits(&s->pb, 8, lefty = p->data[0][1]); + put_bits(&s->pb, 8, leftu = p->data[1][0]); + put_bits(&s->pb, 8, p->data[0][0]); + + lefty = sub_left_prediction(s, s->temp[0], p->data[0], width , 0); + leftu = sub_left_prediction(s, s->temp[1], p->data[1], width2, 0); + leftv = sub_left_prediction(s, s->temp[2], p->data[2], width2, 0); + + encode_422_bitstream(s, 2, width-2); + + if (s->predictor==MEDIAN) { + int lefttopy, lefttopu, lefttopv; + cy = y = 1; + if (s->interlaced) { + lefty = sub_left_prediction(s, s->temp[0], p->data[0] + p->linesize[0], width , lefty); + leftu = sub_left_prediction(s, s->temp[1], p->data[1] + p->linesize[1], width2, leftu); + leftv = sub_left_prediction(s, s->temp[2], p->data[2] + p->linesize[2], width2, leftv); + + encode_422_bitstream(s, 0, width); + y++; cy++; + } + + lefty = sub_left_prediction(s, s->temp[0], p->data[0] + fake_ystride, 4, lefty); + leftu = sub_left_prediction(s, s->temp[1], p->data[1] + fake_ustride, 2, leftu); + leftv = sub_left_prediction(s, s->temp[2], p->data[2] + fake_vstride, 2, leftv); + + encode_422_bitstream(s, 0, 4); + + lefttopy = p->data[0][3]; + lefttopu = p->data[1][1]; + lefttopv = p->data[2][1]; + s->dsp.sub_hfyu_median_prediction(s->temp[0], p->data[0]+4, p->data[0] + fake_ystride + 4, width - 4 , &lefty, &lefttopy); + s->dsp.sub_hfyu_median_prediction(s->temp[1], p->data[1]+2, p->data[1] + fake_ustride + 2, width2 - 2, &leftu, &lefttopu); + s->dsp.sub_hfyu_median_prediction(s->temp[2], p->data[2]+2, p->data[2] + fake_vstride + 2, width2 - 2, &leftv, &lefttopv); + encode_422_bitstream(s, 0, width - 4); + y++; cy++; + + for (; y < height; y++,cy++) { + uint8_t *ydst, *udst, *vdst; + + if (s->bitstream_bpp == 12) { + while (2 * cy > y) { + ydst = p->data[0] + p->linesize[0] * y; + s->dsp.sub_hfyu_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy); + encode_gray_bitstream(s, width); + y++; + } + if (y >= height) break; + } + ydst = p->data[0] + p->linesize[0] * y; + udst = p->data[1] + p->linesize[1] * cy; + vdst = p->data[2] + p->linesize[2] * cy; + + s->dsp.sub_hfyu_median_prediction(s->temp[0], ydst - fake_ystride, ydst, width , &lefty, &lefttopy); + s->dsp.sub_hfyu_median_prediction(s->temp[1], udst - fake_ustride, udst, width2, &leftu, &lefttopu); + s->dsp.sub_hfyu_median_prediction(s->temp[2], vdst - fake_vstride, vdst, width2, &leftv, &lefttopv); + + encode_422_bitstream(s, 0, width); + } + } else { + for (cy = y = 1; y < height; y++, cy++) { + uint8_t *ydst, *udst, *vdst; + + /* encode a luma only line & y++ */ + if (s->bitstream_bpp == 12) { + ydst = p->data[0] + p->linesize[0] * y; + + if (s->predictor == PLANE && s->interlaced < y) { + s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); + + lefty = sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty); + } else { + lefty = sub_left_prediction(s, s->temp[0], ydst, width , lefty); + } + encode_gray_bitstream(s, width); + y++; + if (y >= height) break; + } + + ydst = p->data[0] + p->linesize[0] * y; + udst = p->data[1] + p->linesize[1] * cy; + vdst = p->data[2] + p->linesize[2] * cy; + + if (s->predictor == PLANE && s->interlaced < cy) { + s->dsp.diff_bytes(s->temp[1], ydst, ydst - fake_ystride, width); + s->dsp.diff_bytes(s->temp[2], udst, udst - fake_ustride, width2); + s->dsp.diff_bytes(s->temp[2] + width2, vdst, vdst - fake_vstride, width2); + + lefty = sub_left_prediction(s, s->temp[0], s->temp[1], width , lefty); + leftu = sub_left_prediction(s, s->temp[1], s->temp[2], width2, leftu); + leftv = sub_left_prediction(s, s->temp[2], s->temp[2] + width2, width2, leftv); + } else { + lefty = sub_left_prediction(s, s->temp[0], ydst, width , lefty); + leftu = sub_left_prediction(s, s->temp[1], udst, width2, leftu); + leftv = sub_left_prediction(s, s->temp[2], vdst, width2, leftv); + } + + encode_422_bitstream(s, 0, width); + } + } + } else if(avctx->pix_fmt == AV_PIX_FMT_RGB32) { + uint8_t *data = p->data[0] + (height - 1) * p->linesize[0]; + const int stride = -p->linesize[0]; + const int fake_stride = -fake_ystride; + int y; + int leftr, leftg, leftb, lefta; + + put_bits(&s->pb, 8, lefta = data[A]); + put_bits(&s->pb, 8, leftr = data[R]); + put_bits(&s->pb, 8, leftg = data[G]); + put_bits(&s->pb, 8, leftb = data[B]); + + sub_left_prediction_bgr32(s, s->temp[0], data + 4, width - 1, &leftr, &leftg, &leftb, &lefta); + encode_bgra_bitstream(s, width - 1, 4); + + for (y = 1; y < s->height; y++) { + uint8_t *dst = data + y*stride; + if (s->predictor == PLANE && s->interlaced < y) { + s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, width * 4); + sub_left_prediction_bgr32(s, s->temp[0], s->temp[1], width, &leftr, &leftg, &leftb, &lefta); + } else { + sub_left_prediction_bgr32(s, s->temp[0], dst, width, &leftr, &leftg, &leftb, &lefta); + } + encode_bgra_bitstream(s, width, 4); + } + }else if(avctx->pix_fmt == AV_PIX_FMT_RGB24){ + uint8_t *data = p->data[0] + (height-1)*p->linesize[0]; + const int stride = -p->linesize[0]; + const int fake_stride = -fake_ystride; + int y; + int leftr, leftg, leftb; + + put_bits(&s->pb, 8, leftr= data[0]); + put_bits(&s->pb, 8, leftg= data[1]); + put_bits(&s->pb, 8, leftb= data[2]); + put_bits(&s->pb, 8, 0); + + sub_left_prediction_rgb24(s, s->temp[0], data+3, width-1, &leftr, &leftg, &leftb); + encode_bgra_bitstream(s, width-1, 3); + + for(y=1; yheight; y++){ + uint8_t *dst = data + y*stride; + if(s->predictor == PLANE && s->interlaced < y){ + s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, width*3); + sub_left_prediction_rgb24(s, s->temp[0], s->temp[1], width, &leftr, &leftg, &leftb); + }else{ + sub_left_prediction_rgb24(s, s->temp[0], dst, width, &leftr, &leftg, &leftb); + } + encode_bgra_bitstream(s, width, 3); + } + } else { + av_log(avctx, AV_LOG_ERROR, "Format not supported!\n"); + } + emms_c(); + + size += (put_bits_count(&s->pb) + 31) / 8; + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 15, 0); + size /= 4; + + if ((s->flags&CODEC_FLAG_PASS1) && (s->picture_number & 31) == 0) { + int j; + char *p = avctx->stats_out; + char *end = p + 1024*30; + for (i = 0; i < 3; i++) { + for (j = 0; j < 256; j++) { + snprintf(p, end-p, "%"PRIu64" ", s->stats[i][j]); + p += strlen(p); + s->stats[i][j]= 0; + } + snprintf(p, end-p, "\n"); + p++; + } + } else + avctx->stats_out[0] = '\0'; + if (!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)) { + flush_put_bits(&s->pb); + s->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); + } + + s->picture_number++; + + pkt->size = size * 4; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int encode_end(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + + ff_huffyuv_common_end(s); + + av_freep(&avctx->extradata); + av_freep(&avctx->stats_out); + + return 0; +} + +#if CONFIG_HUFFYUV_ENCODER +AVCodec ff_huffyuv_encoder = { + .name = "huffyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HUFFYUV, + .priv_data_size = sizeof(HYuvContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), +}; +#endif + +#if CONFIG_FFVHUFF_ENCODER +AVCodec ff_ffvhuff_encoder = { + .name = "ffvhuff", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_FFVHUFF, + .priv_data_size = sizeof(HYuvContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), +}; +#endif diff --git a/ffmpeg/libavcodec/idcinvideo.c b/ffmpeg/libavcodec/idcinvideo.c new file mode 100644 index 0000000..3596080 --- /dev/null +++ b/ffmpeg/libavcodec/idcinvideo.c @@ -0,0 +1,253 @@ +/* + * id Quake II CIN Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * id Quake II Cin Video Decoder by Dr. Tim Ferguson + * For more information about the id CIN format, visit: + * http://www.csse.monash.edu.au/~timf/ + * + * This video decoder outputs PAL8 colorspace data. Interacting with this + * decoder is a little involved. During initialization, the demuxer must + * transmit the 65536-byte Huffman table(s) to the decoder via extradata. + * Then, whenever a palette change is encountered while demuxing the file, + * the demuxer must use the same extradata space to transmit an + * AVPaletteControl structure. + * + * id CIN video is purely Huffman-coded, intraframe-only codec. It achieves + * a little more compression by exploiting the fact that adjacent pixels + * tend to be similar. + * + * Note that this decoder could use libavcodec's optimized VLC facilities + * rather than naive, tree-based Huffman decoding. However, there are 256 + * Huffman tables. Plus, the VLC bit coding order is right -> left instead + * or left -> right, so all of the bits would have to be reversed. Further, + * the original Quake II implementation likely used a similar naive + * decoding algorithm and it worked fine on much lower spec machines. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/internal.h" + +#define HUFFMAN_TABLE_SIZE 64 * 1024 +#define HUF_TOKENS 256 +#define PALETTE_COUNT 256 + +typedef struct +{ + int count; + unsigned char used; + int children[2]; +} hnode; + +typedef struct IdcinContext { + + AVCodecContext *avctx; + + const unsigned char *buf; + int size; + + hnode huff_nodes[256][HUF_TOKENS*2]; + int num_huff_nodes[256]; + + uint32_t pal[256]; +} IdcinContext; + +/** + * Find the lowest probability node in a Huffman table, and mark it as + * being assigned to a higher probability. + * @return the node index of the lowest unused node, or -1 if all nodes + * are used. + */ +static int huff_smallest_node(hnode *hnodes, int num_hnodes) { + int i; + int best, best_node; + + best = 99999999; + best_node = -1; + for(i = 0; i < num_hnodes; i++) { + if(hnodes[i].used) + continue; + if(!hnodes[i].count) + continue; + if(hnodes[i].count < best) { + best = hnodes[i].count; + best_node = i; + } + } + + if(best_node == -1) + return -1; + hnodes[best_node].used = 1; + return best_node; +} + +/* + * Build the Huffman tree using the generated/loaded probabilities histogram. + * + * On completion: + * huff_nodes[prev][i < HUF_TOKENS] - are the nodes at the base of the tree. + * huff_nodes[prev][i >= HUF_TOKENS] - are used to construct the tree. + * num_huff_nodes[prev] - contains the index to the root node of the tree. + * That is: huff_nodes[prev][num_huff_nodes[prev]] is the root node. + */ +static av_cold void huff_build_tree(IdcinContext *s, int prev) { + hnode *node, *hnodes; + int num_hnodes, i; + + num_hnodes = HUF_TOKENS; + hnodes = s->huff_nodes[prev]; + for(i = 0; i < HUF_TOKENS * 2; i++) + hnodes[i].used = 0; + + while (1) { + node = &hnodes[num_hnodes]; /* next free node */ + + /* pick two lowest counts */ + node->children[0] = huff_smallest_node(hnodes, num_hnodes); + if(node->children[0] == -1) + break; /* reached the root node */ + + node->children[1] = huff_smallest_node(hnodes, num_hnodes); + if(node->children[1] == -1) + break; /* reached the root node */ + + /* combine nodes probability for new node */ + node->count = hnodes[node->children[0]].count + + hnodes[node->children[1]].count; + num_hnodes++; + } + + s->num_huff_nodes[prev] = num_hnodes - 1; +} + +static av_cold int idcin_decode_init(AVCodecContext *avctx) +{ + IdcinContext *s = avctx->priv_data; + int i, j, histogram_index = 0; + unsigned char *histograms; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + /* make sure the Huffman tables make it */ + if (s->avctx->extradata_size != HUFFMAN_TABLE_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, " id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE); + return -1; + } + + /* build the 256 Huffman decode trees */ + histograms = (unsigned char *)s->avctx->extradata; + for (i = 0; i < 256; i++) { + for(j = 0; j < HUF_TOKENS; j++) + s->huff_nodes[i][j].count = histograms[histogram_index++]; + huff_build_tree(s, i); + } + + return 0; +} + +static int idcin_decode_vlcs(IdcinContext *s, AVFrame *frame) +{ + hnode *hnodes; + long x, y; + int prev; + unsigned char v = 0; + int bit_pos, node_num, dat_pos; + + prev = bit_pos = dat_pos = 0; + for (y = 0; y < (frame->linesize[0] * s->avctx->height); + y += frame->linesize[0]) { + for (x = y; x < y + s->avctx->width; x++) { + node_num = s->num_huff_nodes[prev]; + hnodes = s->huff_nodes[prev]; + + while(node_num >= HUF_TOKENS) { + if(!bit_pos) { + if(dat_pos >= s->size) { + av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n"); + return -1; + } + bit_pos = 8; + v = s->buf[dat_pos++]; + } + + node_num = hnodes[node_num].children[v & 0x01]; + v = v >> 1; + bit_pos--; + } + + frame->data[0][x] = node_num; + prev = node_num; + } + } + + return 0; +} + +static int idcin_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + IdcinContext *s = avctx->priv_data; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + AVFrame *frame = data; + int ret; + + s->buf = buf; + s->size = buf_size; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (idcin_decode_vlcs(s, frame)) + return AVERROR_INVALIDDATA; + + if (pal) { + frame->palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + /* make the palette available on the way out */ + memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +AVCodec ff_idcin_decoder = { + .name = "idcinvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_IDCIN, + .priv_data_size = sizeof(IdcinContext), + .init = idcin_decode_init, + .decode = idcin_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"), +}; diff --git a/ffmpeg/libavcodec/iff.c b/ffmpeg/libavcodec/iff.c new file mode 100644 index 0000000..716a731 --- /dev/null +++ b/ffmpeg/libavcodec/iff.c @@ -0,0 +1,896 @@ +/* + * IFF ACBM/DEEP/ILBM/PBM bitmap decoder + * Copyright (c) 2010 Peter Ross + * Copyright (c) 2010 Sebastian Vater + * + * 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 + */ + +/** + * @file + * IFF ACBM/DEEP/ILBM/PBM bitmap decoder + */ + +#include "libavutil/imgutils.h" +#include "bytestream.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" + +// TODO: masking bits +typedef enum { + MASK_NONE, + MASK_HAS_MASK, + MASK_HAS_TRANSPARENT_COLOR, + MASK_LASSO +} mask_type; + +typedef struct { + AVFrame *frame; + int planesize; + uint8_t * planebuf; + uint8_t * ham_buf; ///< temporary buffer for planar to chunky conversation + uint32_t *ham_palbuf; ///< HAM decode table + uint32_t *mask_buf; ///< temporary buffer for palette indices + uint32_t *mask_palbuf; ///< masking palette table + unsigned compression; ///< delta compression method used + unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM) + unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise) + unsigned flags; ///< 1 for EHB, 0 is no extra half darkening + unsigned transparency; ///< TODO: transparency color index in palette + unsigned masking; ///< TODO: masking method used + int init; // 1 if buffer and palette data already initialized, 0 otherwise + int16_t tvdc[16]; ///< TVDC lookup table +} IffContext; + +#define LUT8_PART(plane, v) \ + AV_LE2NE64C(UINT64_C(0x0000000)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1000000)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0010000)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1010000)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0000100)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1000100)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0010100)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1010100)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0000001)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1000001)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0010001)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1010001)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0000101)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1000101)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x0010101)<<32 | v) << plane, \ + AV_LE2NE64C(UINT64_C(0x1010101)<<32 | v) << plane + +#define LUT8(plane) { \ + LUT8_PART(plane, 0x0000000), \ + LUT8_PART(plane, 0x1000000), \ + LUT8_PART(plane, 0x0010000), \ + LUT8_PART(plane, 0x1010000), \ + LUT8_PART(plane, 0x0000100), \ + LUT8_PART(plane, 0x1000100), \ + LUT8_PART(plane, 0x0010100), \ + LUT8_PART(plane, 0x1010100), \ + LUT8_PART(plane, 0x0000001), \ + LUT8_PART(plane, 0x1000001), \ + LUT8_PART(plane, 0x0010001), \ + LUT8_PART(plane, 0x1010001), \ + LUT8_PART(plane, 0x0000101), \ + LUT8_PART(plane, 0x1000101), \ + LUT8_PART(plane, 0x0010101), \ + LUT8_PART(plane, 0x1010101), \ +} + +// 8 planes * 8-bit mask +static const uint64_t plane8_lut[8][256] = { + LUT8(0), LUT8(1), LUT8(2), LUT8(3), + LUT8(4), LUT8(5), LUT8(6), LUT8(7), +}; + +#define LUT32(plane) { \ + 0, 0, 0, 0, \ + 0, 0, 0, 1 << plane, \ + 0, 0, 1 << plane, 0, \ + 0, 0, 1 << plane, 1 << plane, \ + 0, 1 << plane, 0, 0, \ + 0, 1 << plane, 0, 1 << plane, \ + 0, 1 << plane, 1 << plane, 0, \ + 0, 1 << plane, 1 << plane, 1 << plane, \ + 1 << plane, 0, 0, 0, \ + 1 << plane, 0, 0, 1 << plane, \ + 1 << plane, 0, 1 << plane, 0, \ + 1 << plane, 0, 1 << plane, 1 << plane, \ + 1 << plane, 1 << plane, 0, 0, \ + 1 << plane, 1 << plane, 0, 1 << plane, \ + 1 << plane, 1 << plane, 1 << plane, 0, \ + 1 << plane, 1 << plane, 1 << plane, 1 << plane, \ +} + +// 32 planes * 4-bit mask * 4 lookup tables each +static const uint32_t plane32_lut[32][16*4] = { + LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3), + LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7), + LUT32( 8), LUT32( 9), LUT32(10), LUT32(11), + LUT32(12), LUT32(13), LUT32(14), LUT32(15), + LUT32(16), LUT32(17), LUT32(18), LUT32(19), + LUT32(20), LUT32(21), LUT32(22), LUT32(23), + LUT32(24), LUT32(25), LUT32(26), LUT32(27), + LUT32(28), LUT32(29), LUT32(30), LUT32(31), +}; + +// Gray to RGB, required for palette table of grayscale images with bpp < 8 +static av_always_inline uint32_t gray2rgb(const uint32_t x) { + return x << 16 | x << 8 | x; +} + +/** + * Convert CMAP buffer (stored in extradata) to lavc palette format + */ +static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) +{ + IffContext *s = avctx->priv_data; + int count, i; + const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); + int palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); + + if (avctx->bits_per_coded_sample > 8) { + av_log(avctx, AV_LOG_ERROR, "bits_per_coded_sample > 8 not supported\n"); + return AVERROR_INVALIDDATA; + } + + count = 1 << avctx->bits_per_coded_sample; + // If extradata is smaller than actually needed, fill the remaining with black. + count = FFMIN(palette_size / 3, count); + if (count) { + for (i=0; i < count; i++) { + pal[i] = 0xFF000000 | AV_RB24(palette + i*3); + } + if (s->flags && count >= 32) { // EHB + for (i = 0; i < 32; i++) + pal[i + 32] = 0xFF000000 | (AV_RB24(palette + i*3) & 0xFEFEFE) >> 1; + count = FFMAX(count, 64); + } + } else { // Create gray-scale color palette for bps < 8 + count = 1 << avctx->bits_per_coded_sample; + + for (i=0; i < count; i++) { + pal[i] = 0xFF000000 | gray2rgb((i * 255) >> avctx->bits_per_coded_sample); + } + } + if (s->masking == MASK_HAS_MASK) { + memcpy(pal + (1 << avctx->bits_per_coded_sample), pal, count * 4); + for (i = 0; i < count; i++) + pal[i] &= 0xFFFFFF; + } else if (s->masking == MASK_HAS_TRANSPARENT_COLOR && + s->transparency < 1 << avctx->bits_per_coded_sample) + pal[s->transparency] &= 0xFFFFFF; + return 0; +} + +/** + * Extracts the IFF extra context and updates internal + * decoder structures. + * + * @param avctx the AVCodecContext where to extract extra context to + * @param avpkt the AVPacket to extract extra context from or NULL to use avctx + * @return 0 in case of success, a negative error code otherwise + */ +static int extract_header(AVCodecContext *const avctx, + const AVPacket *const avpkt) { + const uint8_t *buf; + unsigned buf_size; + IffContext *s = avctx->priv_data; + int i, palette_size; + + if (avctx->extradata_size < 2) { + av_log(avctx, AV_LOG_ERROR, "not enough extradata\n"); + return AVERROR_INVALIDDATA; + } + palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); + + if (avpkt) { + int image_size; + if (avpkt->size < 2) + return AVERROR_INVALIDDATA; + image_size = avpkt->size - AV_RB16(avpkt->data); + buf = avpkt->data; + buf_size = bytestream_get_be16(&buf); + if (buf_size <= 1 || image_size <= 1) { + av_log(avctx, AV_LOG_ERROR, + "Invalid image size received: %u -> image data offset: %d\n", + buf_size, image_size); + return AVERROR_INVALIDDATA; + } + } else { + buf = avctx->extradata; + buf_size = bytestream_get_be16(&buf); + if (buf_size <= 1 || palette_size < 0) { + av_log(avctx, AV_LOG_ERROR, + "Invalid palette size received: %u -> palette data offset: %d\n", + buf_size, palette_size); + return AVERROR_INVALIDDATA; + } + } + + if (buf_size >= 41) { + s->compression = bytestream_get_byte(&buf); + s->bpp = bytestream_get_byte(&buf); + s->ham = bytestream_get_byte(&buf); + s->flags = bytestream_get_byte(&buf); + s->transparency = bytestream_get_be16(&buf); + s->masking = bytestream_get_byte(&buf); + for (i = 0; i < 16; i++) + s->tvdc[i] = bytestream_get_be16(&buf); + + if (s->masking == MASK_HAS_MASK) { + if (s->bpp >= 8 && !s->ham) { + avctx->pix_fmt = AV_PIX_FMT_RGB32; + av_freep(&s->mask_buf); + av_freep(&s->mask_palbuf); + s->mask_buf = av_malloc((s->planesize * 32) + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->mask_buf) + return AVERROR(ENOMEM); + if (s->bpp > 16) { + av_log(avctx, AV_LOG_ERROR, "bpp %d too large for palette\n", s->bpp); + av_freep(&s->mask_buf); + return AVERROR(ENOMEM); + } + s->mask_palbuf = av_malloc((2 << s->bpp) * sizeof(uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->mask_palbuf) { + av_freep(&s->mask_buf); + return AVERROR(ENOMEM); + } + } + s->bpp++; + } else if (s->masking != MASK_NONE && s->masking != MASK_HAS_TRANSPARENT_COLOR) { + av_log(avctx, AV_LOG_ERROR, "Masking not supported\n"); + return AVERROR_PATCHWELCOME; + } + if (!s->bpp || s->bpp > 32) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of bitplanes: %u\n", s->bpp); + return AVERROR_INVALIDDATA; + } else if (s->ham >= 8) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of hold bits for HAM: %u\n", s->ham); + return AVERROR_INVALIDDATA; + } + + av_freep(&s->ham_buf); + av_freep(&s->ham_palbuf); + + if (s->ham) { + int i, count = FFMIN(palette_size / 3, 1 << s->ham); + int ham_count; + const uint8_t *const palette = avctx->extradata + AV_RB16(avctx->extradata); + + s->ham_buf = av_malloc((s->planesize * 8) + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->ham_buf) + return AVERROR(ENOMEM); + + ham_count = 8 * (1 << s->ham); + s->ham_palbuf = av_malloc((ham_count << !!(s->masking == MASK_HAS_MASK)) * sizeof (uint32_t) + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->ham_palbuf) { + av_freep(&s->ham_buf); + return AVERROR(ENOMEM); + } + + if (count) { // HAM with color palette attached + // prefill with black and palette and set HAM take direct value mask to zero + memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof (uint32_t)); + for (i=0; i < count; i++) { + s->ham_palbuf[i*2+1] = 0xFF000000 | AV_RL24(palette + i*3); + } + count = 1 << s->ham; + } else { // HAM with grayscale color palette + count = 1 << s->ham; + for (i=0; i < count; i++) { + s->ham_palbuf[i*2] = 0xFF000000; // take direct color value from palette + s->ham_palbuf[i*2+1] = 0xFF000000 | av_le2ne32(gray2rgb((i * 255) >> s->ham)); + } + } + for (i=0; i < count; i++) { + uint32_t tmp = i << (8 - s->ham); + tmp |= tmp >> s->ham; + s->ham_palbuf[(i+count)*2] = 0xFF00FFFF; // just modify blue color component + s->ham_palbuf[(i+count*2)*2] = 0xFFFFFF00; // just modify red color component + s->ham_palbuf[(i+count*3)*2] = 0xFFFF00FF; // just modify green color component + s->ham_palbuf[(i+count)*2+1] = 0xFF000000 | tmp << 16; + s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp; + s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8; + } + if (s->masking == MASK_HAS_MASK) { + for (i = 0; i < ham_count; i++) + s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000; + } + } + } + + return 0; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + IffContext *s = avctx->priv_data; + int err; + + if (avctx->bits_per_coded_sample <= 8) { + int palette_size; + + if (avctx->extradata_size >= 2) + palette_size = avctx->extradata_size - AV_RB16(avctx->extradata); + else + palette_size = 0; + avctx->pix_fmt = (avctx->bits_per_coded_sample < 8) || + (avctx->extradata_size >= 2 && palette_size) ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; + } else if (avctx->bits_per_coded_sample <= 32) { + if (avctx->codec_tag == MKTAG('R','G','B','8')) { + avctx->pix_fmt = AV_PIX_FMT_RGB32; + } else if (avctx->codec_tag == MKTAG('R','G','B','N')) { + avctx->pix_fmt = AV_PIX_FMT_RGB444; + } else if (avctx->codec_tag != MKTAG('D','E','E','P')) { + if (avctx->bits_per_coded_sample == 24) { + avctx->pix_fmt = AV_PIX_FMT_0BGR32; + } else if (avctx->bits_per_coded_sample == 32) { + avctx->pix_fmt = AV_PIX_FMT_BGR32; + } else { + avpriv_request_sample(avctx, "unknown bits_per_coded_sample"); + return AVERROR_PATCHWELCOME; + } + } + } else { + return AVERROR_INVALIDDATA; + } + + if ((err = av_image_check_size(avctx->width, avctx->height, 0, avctx))) + return err; + s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary + s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->planebuf) + return AVERROR(ENOMEM); + + s->bpp = avctx->bits_per_coded_sample; + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + if ((err = extract_header(avctx, NULL)) < 0) + return err; + + return 0; +} + +/** + * Decode interleaved plane buffer up to 8bpp + * @param dst Destination buffer + * @param buf Source buffer + * @param buf_size + * @param plane plane number to decode as + */ +static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane) +{ + const uint64_t *lut = plane8_lut[plane]; + if (plane >= 8) { + av_log(NULL, AV_LOG_WARNING, "Ignoring extra planes beyond 8\n"); + return; + } + do { + uint64_t v = AV_RN64A(dst) | lut[*buf++]; + AV_WN64A(dst, v); + dst += 8; + } while (--buf_size); +} + +/** + * Decode interleaved plane buffer up to 24bpp + * @param dst Destination buffer + * @param buf Source buffer + * @param buf_size + * @param plane plane number to decode as + */ +static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane) +{ + const uint32_t *lut = plane32_lut[plane]; + do { + unsigned mask = (*buf >> 2) & ~3; + dst[0] |= lut[mask++]; + dst[1] |= lut[mask++]; + dst[2] |= lut[mask++]; + dst[3] |= lut[mask]; + mask = (*buf++ << 2) & 0x3F; + dst[4] |= lut[mask++]; + dst[5] |= lut[mask++]; + dst[6] |= lut[mask++]; + dst[7] |= lut[mask]; + dst += 8; + } while (--buf_size); +} + +#define DECODE_HAM_PLANE32(x) \ + first = buf[x] << 1; \ + second = buf[(x)+1] << 1; \ + delta &= pal[first++]; \ + delta |= pal[first]; \ + dst[x] = delta; \ + delta &= pal[second++]; \ + delta |= pal[second]; \ + dst[(x)+1] = delta + +/** + * Converts one line of HAM6/8-encoded chunky buffer to 24bpp. + * + * @param dst the destination 24bpp buffer + * @param buf the source 8bpp chunky buffer + * @param pal the HAM decode table + * @param buf_size the plane size in bytes + */ +static void decode_ham_plane32(uint32_t *dst, const uint8_t *buf, + const uint32_t *const pal, unsigned buf_size) +{ + uint32_t delta = pal[1]; /* first palette entry */ + do { + uint32_t first, second; + DECODE_HAM_PLANE32(0); + DECODE_HAM_PLANE32(2); + DECODE_HAM_PLANE32(4); + DECODE_HAM_PLANE32(6); + buf += 8; + dst += 8; + } while (--buf_size); +} + +static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf, + const uint32_t *const pal, unsigned width) +{ + do { + *dst++ = pal[*buf++]; + } while (--width); +} + +/** + * Decode one complete byterun1 encoded line. + * + * @param dst the destination buffer where to store decompressed bitstream + * @param dst_size the destination plane size in bytes + * @param buf the source byterun1 compressed bitstream + * @param buf_end the EOF of source byterun1 compressed bitstream + * @return number of consumed bytes in byterun1 compressed bitstream +*/ +static int decode_byterun(uint8_t *dst, int dst_size, + const uint8_t *buf, const uint8_t *const buf_end) { + const uint8_t *const buf_start = buf; + unsigned x; + for (x = 0; x < dst_size && buf < buf_end;) { + unsigned length; + const int8_t value = *buf++; + if (value >= 0) { + length = value + 1; + memcpy(dst + x, buf, FFMIN3(length, dst_size - x, buf_end - buf)); + buf += length; + } else if (value > -128) { + length = -value + 1; + memset(dst + x, *buf++, FFMIN(length, dst_size - x)); + } else { // noop + continue; + } + x += length; + } + return buf - buf_start; +} + +#define DECODE_RGBX_COMMON(type) \ + if (!length) { \ + length = bytestream2_get_byte(gb); \ + if (!length) { \ + length = bytestream2_get_be16(gb); \ + if (!length) \ + return; \ + } \ + } \ + for (i = 0; i < length; i++) { \ + *(type *)(dst + y*linesize + x * sizeof(type)) = pixel; \ + x += 1; \ + if (x >= width) { \ + y += 1; \ + if (y >= height) \ + return; \ + x = 0; \ + } \ + } + +/** + * Decode RGB8 buffer + * @param[out] dst Destination buffer + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) + * @param linesize Line size of destination buffer (bytes) + */ +static void decode_rgb8(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize) +{ + int x = 0, y = 0, i, length; + while (bytestream2_get_bytes_left(gb) >= 4) { + uint32_t pixel = 0xFF000000 | bytestream2_get_be24(gb); + length = bytestream2_get_byte(gb) & 0x7F; + DECODE_RGBX_COMMON(uint32_t) + } +} + +/** + * Decode RGBN buffer + * @param[out] dst Destination buffer + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) + * @param linesize Line size of destination buffer (bytes) + */ +static void decode_rgbn(GetByteContext *gb, uint8_t *dst, int width, int height, int linesize) +{ + int x = 0, y = 0, i, length; + while (bytestream2_get_bytes_left(gb) >= 2) { + uint32_t pixel = bytestream2_get_be16u(gb); + length = pixel & 0x7; + pixel >>= 4; + DECODE_RGBX_COMMON(uint16_t) + } +} + +/** + * Decode DEEP RLE 32-bit buffer + * @param[out] dst Destination buffer + * @param[in] src Source buffer + * @param src_size Source buffer size (bytes) + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) + * @param linesize Line size of destination buffer (bytes) + */ +static void decode_deep_rle32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize) +{ + const uint8_t *src_end = src + src_size; + int x = 0, y = 0, i; + while (src + 5 <= src_end) { + int opcode; + opcode = *(int8_t *)src++; + if (opcode >= 0) { + int size = opcode + 1; + for (i = 0; i < size; i++) { + int length = FFMIN(size - i, width); + memcpy(dst + y*linesize + x * 4, src, length * 4); + src += length * 4; + x += length; + i += length; + if (x >= width) { + x = 0; + y += 1; + if (y >= height) + return; + } + } + } else { + int size = -opcode + 1; + uint32_t pixel = AV_RN32(src); + for (i = 0; i < size; i++) { + *(uint32_t *)(dst + y*linesize + x * 4) = pixel; + x += 1; + if (x >= width) { + x = 0; + y += 1; + if (y >= height) + return; + } + } + src += 4; + } + } +} + +/** + * Decode DEEP TVDC 32-bit buffer + * @param[out] dst Destination buffer + * @param[in] src Source buffer + * @param src_size Source buffer size (bytes) + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) + * @param linesize Line size of destination buffer (bytes) + * @param[int] tvdc TVDC lookup table + */ +static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize, const int16_t *tvdc) +{ + int x = 0, y = 0, plane = 0; + int8_t pixel = 0; + int i, j; + + for (i = 0; i < src_size * 2;) { +#define GETNIBBLE ((i & 1) ? (src[i>>1] & 0xF) : (src[i>>1] >> 4)) + int d = tvdc[GETNIBBLE]; + i++; + if (d) { + pixel += d; + dst[y * linesize + x*4 + plane] = pixel; + x++; + } else { + if (i >= src_size * 2) + return; + d = GETNIBBLE + 1; + i++; + d = FFMIN(d, width - x); + for (j = 0; j < d; j++) { + dst[y * linesize + x*4 + plane] = pixel; + x++; + } + } + if (x >= width) { + plane++; + if (plane >= 4) { + y++; + if (y >= height) + return; + plane = 0; + } + x = 0; + pixel = 0; + i = (i + 1) & ~1; + } + } +} + +static int unsupported(AVCodecContext *avctx) +{ + IffContext *s = avctx->priv_data; + avpriv_request_sample(avctx, "bitmap (compression %i, bpp %i, ham %i)", s->compression, s->bpp, s->ham); + return AVERROR_INVALIDDATA; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + IffContext *s = avctx->priv_data; + const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL; + const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0; + const uint8_t *buf_end = buf+buf_size; + int y, plane, res; + GetByteContext gb; + + if ((res = extract_header(avctx, avpkt)) < 0) + return res; + if ((res = ff_reget_buffer(avctx, s->frame)) < 0) + return res; + if (!s->init && avctx->bits_per_coded_sample <= 8 && + avctx->pix_fmt == AV_PIX_FMT_PAL8) { + if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame->data[1])) < 0) + return res; + } else if (!s->init && avctx->bits_per_coded_sample <= 8 && + avctx->pix_fmt == AV_PIX_FMT_RGB32) { + if ((res = cmap_read_palette(avctx, s->mask_palbuf)) < 0) + return res; + } + s->init = 1; + + switch (s->compression) { + case 0: + if (avctx->codec_tag == MKTAG('A','C','B','M')) { + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]); + for (plane = 0; plane < s->bpp; plane++) { + for(y = 0; y < avctx->height && buf < buf_end; y++ ) { + uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ]; + decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); + buf += s->planesize; + } + } + } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 + memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]); + for(y = 0; y < avctx->height; y++) { + uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; + memset(s->ham_buf, 0, s->planesize * 8); + for (plane = 0; plane < s->bpp; plane++) { + const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize; + if (start >= buf_end) + break; + decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane); + } + decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize); + } + } else + return unsupported(avctx); + } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3); + int x; + for(y = 0; y < avctx->height && buf < buf_end; y++ ) { + uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; + memcpy(row, buf, FFMIN(raw_width, buf_end - buf)); + buf += raw_width; + if (avctx->pix_fmt == AV_PIX_FMT_BGR32) { + for(x = 0; x < avctx->width; x++) + row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4); + } + } + } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + for(y = 0; y < avctx->height; y++ ) { + uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ]; + memset(row, 0, avctx->width); + for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { + decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane); + buf += s->planesize; + } + } + } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 + for (y = 0; y < avctx->height; y++) { + uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ]; + memset(s->ham_buf, 0, s->planesize * 8); + for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { + decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane); + buf += s->planesize; + } + decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize); + } + } else { // AV_PIX_FMT_BGR32 + for(y = 0; y < avctx->height; y++ ) { + uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]]; + memset(row, 0, avctx->width << 2); + for (plane = 0; plane < s->bpp && buf < buf_end; plane++) { + decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane); + buf += s->planesize; + } + } + } + } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + for(y = 0; y < avctx->height && buf_end > buf; y++ ) { + uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]]; + memcpy(row, buf, FFMIN(avctx->width, buf_end - buf)); + buf += avctx->width + (avctx->width % 2); // padding if odd + } + } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 + for (y = 0; y < avctx->height && buf_end > buf; y++) { + uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ]; + memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf)); + buf += avctx->width + (avctx->width & 1); // padding if odd + decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize); + } + } else + return unsupported(avctx); + } + break; + case 1: + if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + for(y = 0; y < avctx->height ; y++ ) { + uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ]; + memset(row, 0, avctx->width); + for (plane = 0; plane < s->bpp; plane++) { + buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); + decodeplane8(row, s->planebuf, s->planesize, plane); + } + } + } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32 + for (y = 0; y < avctx->height ; y++ ) { + uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]]; + memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t)); + for (plane = 0; plane < s->bpp; plane++) { + buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); + decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane); + } + lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width); + } + } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32 + for (y = 0; y < avctx->height ; y++) { + uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]]; + memset(s->ham_buf, 0, s->planesize * 8); + for (plane = 0; plane < s->bpp; plane++) { + buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); + decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane); + } + decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize); + } + } else { //AV_PIX_FMT_BGR32 + for(y = 0; y < avctx->height ; y++ ) { + uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]]; + memset(row, 0, avctx->width << 2); + for (plane = 0; plane < s->bpp; plane++) { + buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end); + decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane); + } + } + } + } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + for(y = 0; y < avctx->height ; y++ ) { + uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]]; + buf += decode_byterun(row, avctx->width, buf, buf_end); + } + } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32 + for (y = 0; y < avctx->height ; y++) { + uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]]; + buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end); + decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize); + } + } else + return unsupported(avctx); + } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { // IFF-DEEP + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (av_get_bits_per_pixel(desc) == 32) + decode_deep_rle32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0]); + else + return unsupported(avctx); + } + break; + case 4: + bytestream2_init(&gb, buf, buf_size); + if (avctx->codec_tag == MKTAG('R','G','B','8')) + decode_rgb8(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); + else if (avctx->codec_tag == MKTAG('R','G','B','N')) + decode_rgbn(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); + else + return unsupported(avctx); + break; + case 5: + if (avctx->codec_tag == MKTAG('D','E','E','P')) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (av_get_bits_per_pixel(desc) == 32) + decode_deep_tvdc32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0], s->tvdc); + else + return unsupported(avctx); + } else + return unsupported(avctx); + break; + default: + return unsupported(avctx); + } + + if ((res = av_frame_ref(data, s->frame)) < 0) + return res; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + IffContext *s = avctx->priv_data; + av_frame_free(&s->frame); + av_freep(&s->planebuf); + av_freep(&s->ham_buf); + av_freep(&s->ham_palbuf); + return 0; +} + +#if CONFIG_IFF_ILBM_DECODER +AVCodec ff_iff_ilbm_decoder = { + .name = "iff", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_IFF_ILBM, + .priv_data_size = sizeof(IffContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("IFF"), +}; +#endif +#if CONFIG_IFF_BYTERUN1_DECODER +AVCodec ff_iff_byterun1_decoder = { + .name = "iff", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_IFF_BYTERUN1, + .priv_data_size = sizeof(IffContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("IFF"), +}; +#endif diff --git a/ffmpeg/libavcodec/iirfilter.c b/ffmpeg/libavcodec/iirfilter.c new file mode 100644 index 0000000..049150e --- /dev/null +++ b/ffmpeg/libavcodec/iirfilter.c @@ -0,0 +1,352 @@ +/* + * IIR filter + * Copyright (c) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * different IIR filters implementation + */ + +#include "iirfilter.h" +#include +#include "libavutil/common.h" + +/** + * IIR filter global parameters + */ +typedef struct FFIIRFilterCoeffs{ + int order; + float gain; + int *cx; + float *cy; +}FFIIRFilterCoeffs; + +/** + * IIR filter state + */ +typedef struct FFIIRFilterState{ + float x[1]; +}FFIIRFilterState; + +/// maximum supported filter order +#define MAXORDER 30 + +static int butterworth_init_coeffs(void *avc, struct FFIIRFilterCoeffs *c, + enum IIRFilterMode filt_mode, + int order, float cutoff_ratio, + float stopband) +{ + int i, j; + double wa; + double p[MAXORDER + 1][2]; + + if (filt_mode != FF_FILTER_MODE_LOWPASS) { + av_log(avc, AV_LOG_ERROR, "Butterworth filter currently only supports " + "low-pass filter mode\n"); + return -1; + } + if (order & 1) { + av_log(avc, AV_LOG_ERROR, "Butterworth filter currently only supports " + "even filter orders\n"); + return -1; + } + + wa = 2 * tan(M_PI * 0.5 * cutoff_ratio); + + c->cx[0] = 1; + for(i = 1; i < (order >> 1) + 1; i++) + c->cx[i] = c->cx[i - 1] * (order - i + 1LL) / i; + + p[0][0] = 1.0; + p[0][1] = 0.0; + for(i = 1; i <= order; i++) + p[i][0] = p[i][1] = 0.0; + for(i = 0; i < order; i++){ + double zp[2]; + double th = (i + (order >> 1) + 0.5) * M_PI / order; + double a_re, a_im, c_re, c_im; + zp[0] = cos(th) * wa; + zp[1] = sin(th) * wa; + a_re = zp[0] + 2.0; + c_re = zp[0] - 2.0; + a_im = + c_im = zp[1]; + zp[0] = (a_re * c_re + a_im * c_im) / (c_re * c_re + c_im * c_im); + zp[1] = (a_im * c_re - a_re * c_im) / (c_re * c_re + c_im * c_im); + + for(j = order; j >= 1; j--) + { + a_re = p[j][0]; + a_im = p[j][1]; + p[j][0] = a_re*zp[0] - a_im*zp[1] + p[j-1][0]; + p[j][1] = a_re*zp[1] + a_im*zp[0] + p[j-1][1]; + } + a_re = p[0][0]*zp[0] - p[0][1]*zp[1]; + p[0][1] = p[0][0]*zp[1] + p[0][1]*zp[0]; + p[0][0] = a_re; + } + c->gain = p[order][0]; + for(i = 0; i < order; i++){ + c->gain += p[i][0]; + c->cy[i] = (-p[i][0] * p[order][0] + -p[i][1] * p[order][1]) / + (p[order][0] * p[order][0] + p[order][1] * p[order][1]); + } + c->gain /= 1 << order; + + return 0; +} + +static int biquad_init_coeffs(void *avc, struct FFIIRFilterCoeffs *c, + enum IIRFilterMode filt_mode, int order, + float cutoff_ratio, float stopband) +{ + double cos_w0, sin_w0; + double a0, x0, x1; + + if (filt_mode != FF_FILTER_MODE_HIGHPASS && + filt_mode != FF_FILTER_MODE_LOWPASS) { + av_log(avc, AV_LOG_ERROR, "Biquad filter currently only supports " + "high-pass and low-pass filter modes\n"); + return -1; + } + if (order != 2) { + av_log(avc, AV_LOG_ERROR, "Biquad filter must have order of 2\n"); + return -1; + } + + cos_w0 = cos(M_PI * cutoff_ratio); + sin_w0 = sin(M_PI * cutoff_ratio); + + a0 = 1.0 + (sin_w0 / 2.0); + + if (filt_mode == FF_FILTER_MODE_HIGHPASS) { + c->gain = ((1.0 + cos_w0) / 2.0) / a0; + x0 = ((1.0 + cos_w0) / 2.0) / a0; + x1 = (-(1.0 + cos_w0)) / a0; + } else { // FF_FILTER_MODE_LOWPASS + c->gain = ((1.0 - cos_w0) / 2.0) / a0; + x0 = ((1.0 - cos_w0) / 2.0) / a0; + x1 = (1.0 - cos_w0) / a0; + } + c->cy[0] = (-1.0 + (sin_w0 / 2.0)) / a0; + c->cy[1] = (2.0 * cos_w0) / a0; + + // divide by gain to make the x coeffs integers. + // during filtering, the delay state will include the gain multiplication + c->cx[0] = lrintf(x0 / c->gain); + c->cx[1] = lrintf(x1 / c->gain); + + return 0; +} + +av_cold struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc, + enum IIRFilterType filt_type, + enum IIRFilterMode filt_mode, + int order, float cutoff_ratio, + float stopband, float ripple) +{ + FFIIRFilterCoeffs *c; + int ret = 0; + + if (order <= 0 || order > MAXORDER || cutoff_ratio >= 1.0) + return NULL; + + FF_ALLOCZ_OR_GOTO(avc, c, sizeof(FFIIRFilterCoeffs), + init_fail); + FF_ALLOC_OR_GOTO (avc, c->cx, sizeof(c->cx[0]) * ((order >> 1) + 1), + init_fail); + FF_ALLOC_OR_GOTO (avc, c->cy, sizeof(c->cy[0]) * order, + init_fail); + c->order = order; + + switch (filt_type) { + case FF_FILTER_TYPE_BUTTERWORTH: + ret = butterworth_init_coeffs(avc, c, filt_mode, order, cutoff_ratio, + stopband); + break; + case FF_FILTER_TYPE_BIQUAD: + ret = biquad_init_coeffs(avc, c, filt_mode, order, cutoff_ratio, + stopband); + break; + default: + av_log(avc, AV_LOG_ERROR, "filter type is not currently implemented\n"); + goto init_fail; + } + + if (!ret) + return c; + +init_fail: + ff_iir_filter_free_coeffs(c); + return NULL; +} + +av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order) +{ + FFIIRFilterState* s = av_mallocz(sizeof(FFIIRFilterState) + sizeof(s->x[0]) * (order - 1)); + return s; +} + +#define CONV_S16(dest, source) dest = av_clip_int16(lrintf(source)); + +#define CONV_FLT(dest, source) dest = source; + +#define FILTER_BW_O4_1(i0, i1, i2, i3, fmt) \ + in = *src0 * c->gain \ + + c->cy[0]*s->x[i0] + c->cy[1]*s->x[i1] \ + + c->cy[2]*s->x[i2] + c->cy[3]*s->x[i3]; \ + res = (s->x[i0] + in )*1 \ + + (s->x[i1] + s->x[i3])*4 \ + + s->x[i2] *6; \ + CONV_##fmt(*dst0, res) \ + s->x[i0] = in; \ + src0 += sstep; \ + dst0 += dstep; + +#define FILTER_BW_O4(type, fmt) { \ + int i; \ + const type *src0 = src; \ + type *dst0 = dst; \ + for (i = 0; i < size; i += 4) { \ + float in, res; \ + FILTER_BW_O4_1(0, 1, 2, 3, fmt); \ + FILTER_BW_O4_1(1, 2, 3, 0, fmt); \ + FILTER_BW_O4_1(2, 3, 0, 1, fmt); \ + FILTER_BW_O4_1(3, 0, 1, 2, fmt); \ + } \ +} + +#define FILTER_DIRECT_FORM_II(type, fmt) { \ + int i; \ + const type *src0 = src; \ + type *dst0 = dst; \ + for (i = 0; i < size; i++) { \ + int j; \ + float in, res; \ + in = *src0 * c->gain; \ + for(j = 0; j < c->order; j++) \ + in += c->cy[j] * s->x[j]; \ + res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1]; \ + for(j = 1; j < c->order >> 1; j++) \ + res += (s->x[j] + s->x[c->order - j]) * c->cx[j]; \ + for(j = 0; j < c->order - 1; j++) \ + s->x[j] = s->x[j + 1]; \ + CONV_##fmt(*dst0, res) \ + s->x[c->order - 1] = in; \ + src0 += sstep; \ + dst0 += dstep; \ + } \ +} + +#define FILTER_O2(type, fmt) { \ + int i; \ + const type *src0 = src; \ + type *dst0 = dst; \ + for (i = 0; i < size; i++) { \ + float in = *src0 * c->gain + \ + s->x[0] * c->cy[0] + \ + s->x[1] * c->cy[1]; \ + CONV_##fmt(*dst0, s->x[0] + in + s->x[1] * c->cx[1]) \ + s->x[0] = s->x[1]; \ + s->x[1] = in; \ + src0 += sstep; \ + dst0 += dstep; \ + } \ +} + +void ff_iir_filter(const struct FFIIRFilterCoeffs *c, + struct FFIIRFilterState *s, int size, + const int16_t *src, int sstep, int16_t *dst, int dstep) +{ + if (c->order == 2) { + FILTER_O2(int16_t, S16) + } else if (c->order == 4) { + FILTER_BW_O4(int16_t, S16) + } else { + FILTER_DIRECT_FORM_II(int16_t, S16) + } +} + +void ff_iir_filter_flt(const struct FFIIRFilterCoeffs *c, + struct FFIIRFilterState *s, int size, + const float *src, int sstep, float *dst, int dstep) +{ + if (c->order == 2) { + FILTER_O2(float, FLT) + } else if (c->order == 4) { + FILTER_BW_O4(float, FLT) + } else { + FILTER_DIRECT_FORM_II(float, FLT) + } +} + +av_cold void ff_iir_filter_free_state(struct FFIIRFilterState *state) +{ + av_free(state); +} + +av_cold void ff_iir_filter_free_coeffs(struct FFIIRFilterCoeffs *coeffs) +{ + if(coeffs){ + av_free(coeffs->cx); + av_free(coeffs->cy); + } + av_free(coeffs); +} + +void ff_iir_filter_init(FFIIRFilterContext *f) { + f->filter_flt = ff_iir_filter_flt; + + if (HAVE_MIPSFPU) + ff_iir_filter_init_mips(f); +} + +#ifdef TEST +#include + +#define FILT_ORDER 4 +#define SIZE 1024 +int main(void) +{ + struct FFIIRFilterCoeffs *fcoeffs = NULL; + struct FFIIRFilterState *fstate = NULL; + float cutoff_coeff = 0.4; + int16_t x[SIZE], y[SIZE]; + int i; + + fcoeffs = ff_iir_filter_init_coeffs(NULL, FF_FILTER_TYPE_BUTTERWORTH, + FF_FILTER_MODE_LOWPASS, FILT_ORDER, + cutoff_coeff, 0.0, 0.0); + fstate = ff_iir_filter_init_state(FILT_ORDER); + + for (i = 0; i < SIZE; i++) { + x[i] = lrint(0.75 * INT16_MAX * sin(0.5*M_PI*i*i/SIZE)); + } + + ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1); + + for (i = 0; i < SIZE; i++) + printf("%6d %6d\n", x[i], y[i]); + + ff_iir_filter_free_coeffs(fcoeffs); + ff_iir_filter_free_state(fstate); + return 0; +} +#endif /* TEST */ diff --git a/ffmpeg/libavcodec/iirfilter.h b/ffmpeg/libavcodec/iirfilter.h new file mode 100644 index 0000000..4ea6642 --- /dev/null +++ b/ffmpeg/libavcodec/iirfilter.h @@ -0,0 +1,145 @@ +/* + * IIR filter + * Copyright (c) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * IIR filter interface + */ + +#ifndef AVCODEC_IIRFILTER_H +#define AVCODEC_IIRFILTER_H + +#include "avcodec.h" + +struct FFIIRFilterCoeffs; +struct FFIIRFilterState; + +enum IIRFilterType{ + FF_FILTER_TYPE_BESSEL, + FF_FILTER_TYPE_BIQUAD, + FF_FILTER_TYPE_BUTTERWORTH, + FF_FILTER_TYPE_CHEBYSHEV, + FF_FILTER_TYPE_ELLIPTIC, +}; + +enum IIRFilterMode{ + FF_FILTER_MODE_LOWPASS, + FF_FILTER_MODE_HIGHPASS, + FF_FILTER_MODE_BANDPASS, + FF_FILTER_MODE_BANDSTOP, +}; + +typedef struct FFIIRFilterContext { + /** + * Perform IIR filtering on floating-point input samples. + * + * @param coeffs pointer to filter coefficients + * @param state pointer to filter state + * @param size input length + * @param src source samples + * @param sstep source stride + * @param dst filtered samples (destination may be the same as input) + * @param dstep destination stride + */ + void (*filter_flt)(const struct FFIIRFilterCoeffs *coeffs, + struct FFIIRFilterState *state, int size, + const float *src, int sstep, float *dst, int dstep); +} FFIIRFilterContext; + +/** + * Initialize FFIIRFilterContext + */ +void ff_iir_filter_init(FFIIRFilterContext *f); +void ff_iir_filter_init_mips(FFIIRFilterContext *f); + +/** + * Initialize filter coefficients. + * + * @param avc a pointer to an arbitrary struct of which the first + * field is a pointer to an AVClass struct + * @param filt_type filter type (e.g. Butterworth) + * @param filt_mode filter mode (e.g. lowpass) + * @param order filter order + * @param cutoff_ratio cutoff to input frequency ratio + * @param stopband stopband to input frequency ratio (used by bandpass and bandstop filter modes) + * @param ripple ripple factor (used only in Chebyshev filters) + * + * @return pointer to filter coefficients structure or NULL if filter cannot be created + */ +struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc, + enum IIRFilterType filt_type, + enum IIRFilterMode filt_mode, + int order, float cutoff_ratio, + float stopband, float ripple); + +/** + * Create new filter state. + * + * @param order filter order + * + * @return pointer to new filter state or NULL if state creation fails + */ +struct FFIIRFilterState* ff_iir_filter_init_state(int order); + +/** + * Free filter coefficients. + * + * @param coeffs pointer allocated with ff_iir_filter_init_coeffs() + */ +void ff_iir_filter_free_coeffs(struct FFIIRFilterCoeffs *coeffs); + +/** + * Free filter state. + * + * @param state pointer allocated with ff_iir_filter_init_state() + */ +void ff_iir_filter_free_state(struct FFIIRFilterState *state); + +/** + * Perform IIR filtering on signed 16-bit input samples. + * + * @param coeffs pointer to filter coefficients + * @param state pointer to filter state + * @param size input length + * @param src source samples + * @param sstep source stride + * @param dst filtered samples (destination may be the same as input) + * @param dstep destination stride + */ +void ff_iir_filter(const struct FFIIRFilterCoeffs *coeffs, struct FFIIRFilterState *state, + int size, const int16_t *src, int sstep, int16_t *dst, int dstep); + +/** + * Perform IIR filtering on floating-point input samples. + * + * @param coeffs pointer to filter coefficients + * @param state pointer to filter state + * @param size input length + * @param src source samples + * @param sstep source stride + * @param dst filtered samples (destination may be the same as input) + * @param dstep destination stride + */ +void ff_iir_filter_flt(const struct FFIIRFilterCoeffs *coeffs, + struct FFIIRFilterState *state, int size, + const float *src, int sstep, float *dst, int dstep); + +#endif /* AVCODEC_IIRFILTER_H */ diff --git a/ffmpeg/libavcodec/imc.c b/ffmpeg/libavcodec/imc.c new file mode 100644 index 0000000..eb7c255 --- /dev/null +++ b/ffmpeg/libavcodec/imc.c @@ -0,0 +1,1025 @@ +/* + * IMC compatible decoder + * Copyright (c) 2002-2004 Maxim Poliakovski + * Copyright (c) 2006 Benjamin Larsson + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * IMC - Intel Music Coder + * A mdct based codec using a 256 points large transform + * divided into 32 bands with some mix of scale factors. + * Only mono is supported. + * + */ + + +#include +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "libavutil/internal.h" +#include "libavutil/libm.h" +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "fft.h" +#include "internal.h" +#include "sinewin.h" + +#include "imcdata.h" + +#define IMC_BLOCK_SIZE 64 +#define IMC_FRAME_ID 0x21 +#define BANDS 32 +#define COEFFS 256 + +typedef struct IMCChannel { + float old_floor[BANDS]; + float flcoeffs1[BANDS]; + float flcoeffs2[BANDS]; + float flcoeffs3[BANDS]; + float flcoeffs4[BANDS]; + float flcoeffs5[BANDS]; + float flcoeffs6[BANDS]; + float CWdecoded[COEFFS]; + + int bandWidthT[BANDS]; ///< codewords per band + int bitsBandT[BANDS]; ///< how many bits per codeword in band + int CWlengthT[COEFFS]; ///< how many bits in each codeword + int levlCoeffBuf[BANDS]; + int bandFlagsBuf[BANDS]; ///< flags for each band + int sumLenArr[BANDS]; ///< bits for all coeffs in band + int skipFlagRaw[BANDS]; ///< skip flags are stored in raw form or not + int skipFlagBits[BANDS]; ///< bits used to code skip flags + int skipFlagCount[BANDS]; ///< skipped coeffients per band + int skipFlags[COEFFS]; ///< skip coefficient decoding or not + int codewords[COEFFS]; ///< raw codewords read from bitstream + + float last_fft_im[COEFFS]; + + int decoder_reset; +} IMCChannel; + +typedef struct { + IMCChannel chctx[2]; + + /** MDCT tables */ + //@{ + float mdct_sine_window[COEFFS]; + float post_cos[COEFFS]; + float post_sin[COEFFS]; + float pre_coef1[COEFFS]; + float pre_coef2[COEFFS]; + //@} + + float sqrt_tab[30]; + GetBitContext gb; + + DSPContext dsp; + AVFloatDSPContext fdsp; + FFTContext fft; + DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2]; + float *out_samples; + + int8_t cyclTab[32], cyclTab2[32]; + float weights1[31], weights2[31]; +} IMCContext; + +static VLC huffman_vlc[4][4]; + +#define VLC_TABLES_SIZE 9512 + +static const int vlc_offsets[17] = { + 0, 640, 1156, 1732, 2308, 2852, 3396, 3924, + 4452, 5220, 5860, 6628, 7268, 7908, 8424, 8936, VLC_TABLES_SIZE +}; + +static VLC_TYPE vlc_tables[VLC_TABLES_SIZE][2]; + +static inline double freq2bark(double freq) +{ + return 3.5 * atan((freq / 7500.0) * (freq / 7500.0)) + 13.0 * atan(freq * 0.00076); +} + +static av_cold void iac_generate_tabs(IMCContext *q, int sampling_rate) +{ + double freqmin[32], freqmid[32], freqmax[32]; + double scale = sampling_rate / (256.0 * 2.0 * 2.0); + double nyquist_freq = sampling_rate * 0.5; + double freq, bark, prev_bark = 0, tf, tb; + int i, j; + + for (i = 0; i < 32; i++) { + freq = (band_tab[i] + band_tab[i + 1] - 1) * scale; + bark = freq2bark(freq); + + if (i > 0) { + tb = bark - prev_bark; + q->weights1[i - 1] = pow(10.0, -1.0 * tb); + q->weights2[i - 1] = pow(10.0, -2.7 * tb); + } + prev_bark = bark; + + freqmid[i] = freq; + + tf = freq; + while (tf < nyquist_freq) { + tf += 0.5; + tb = freq2bark(tf); + if (tb > bark + 0.5) + break; + } + freqmax[i] = tf; + + tf = freq; + while (tf > 0.0) { + tf -= 0.5; + tb = freq2bark(tf); + if (tb <= bark - 0.5) + break; + } + freqmin[i] = tf; + } + + for (i = 0; i < 32; i++) { + freq = freqmax[i]; + for (j = 31; j > 0 && freq <= freqmid[j]; j--); + q->cyclTab[i] = j + 1; + + freq = freqmin[i]; + for (j = 0; j < 32 && freq >= freqmid[j]; j++); + q->cyclTab2[i] = j - 1; + } +} + +static av_cold int imc_decode_init(AVCodecContext *avctx) +{ + int i, j, ret; + IMCContext *q = avctx->priv_data; + double r1, r2; + + if (avctx->codec_id == AV_CODEC_ID_IMC) + avctx->channels = 1; + + if (avctx->channels > 2) { + avpriv_request_sample(avctx, "Number of channels > 2"); + return AVERROR_PATCHWELCOME; + } + + for (j = 0; j < avctx->channels; j++) { + q->chctx[j].decoder_reset = 1; + + for (i = 0; i < BANDS; i++) + q->chctx[j].old_floor[i] = 1.0; + + for (i = 0; i < COEFFS / 2; i++) + q->chctx[j].last_fft_im[i] = 0; + } + + /* Build mdct window, a simple sine window normalized with sqrt(2) */ + ff_sine_window_init(q->mdct_sine_window, COEFFS); + for (i = 0; i < COEFFS; i++) + q->mdct_sine_window[i] *= sqrt(2.0); + for (i = 0; i < COEFFS / 2; i++) { + q->post_cos[i] = (1.0f / 32768) * cos(i / 256.0 * M_PI); + q->post_sin[i] = (1.0f / 32768) * sin(i / 256.0 * M_PI); + + r1 = sin((i * 4.0 + 1.0) / 1024.0 * M_PI); + r2 = cos((i * 4.0 + 1.0) / 1024.0 * M_PI); + + if (i & 0x1) { + q->pre_coef1[i] = (r1 + r2) * sqrt(2.0); + q->pre_coef2[i] = -(r1 - r2) * sqrt(2.0); + } else { + q->pre_coef1[i] = -(r1 + r2) * sqrt(2.0); + q->pre_coef2[i] = (r1 - r2) * sqrt(2.0); + } + } + + /* Generate a square root table */ + + for (i = 0; i < 30; i++) + q->sqrt_tab[i] = sqrt(i); + + /* initialize the VLC tables */ + for (i = 0; i < 4 ; i++) { + for (j = 0; j < 4; j++) { + huffman_vlc[i][j].table = &vlc_tables[vlc_offsets[i * 4 + j]]; + huffman_vlc[i][j].table_allocated = vlc_offsets[i * 4 + j + 1] - vlc_offsets[i * 4 + j]; + init_vlc(&huffman_vlc[i][j], 9, imc_huffman_sizes[i], + imc_huffman_lens[i][j], 1, 1, + imc_huffman_bits[i][j], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + } + + if (avctx->codec_id == AV_CODEC_ID_IAC) { + iac_generate_tabs(q, avctx->sample_rate); + } else { + memcpy(q->cyclTab, cyclTab, sizeof(cyclTab)); + memcpy(q->cyclTab2, cyclTab2, sizeof(cyclTab2)); + memcpy(q->weights1, imc_weights1, sizeof(imc_weights1)); + memcpy(q->weights2, imc_weights2, sizeof(imc_weights2)); + } + + if ((ret = ff_fft_init(&q->fft, 7, 1))) { + av_log(avctx, AV_LOG_INFO, "FFT init failed\n"); + return ret; + } + ff_dsputil_init(&q->dsp, avctx); + avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO + : AV_CH_LAYOUT_STEREO; + + return 0; +} + +static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1, + float *flcoeffs2, int *bandWidthT, + float *flcoeffs3, float *flcoeffs5) +{ + float workT1[BANDS]; + float workT2[BANDS]; + float workT3[BANDS]; + float snr_limit = 1.e-30; + float accum = 0.0; + int i, cnt2; + + for (i = 0; i < BANDS; i++) { + flcoeffs5[i] = workT2[i] = 0.0; + if (bandWidthT[i]) { + workT1[i] = flcoeffs1[i] * flcoeffs1[i]; + flcoeffs3[i] = 2.0 * flcoeffs2[i]; + } else { + workT1[i] = 0.0; + flcoeffs3[i] = -30000.0; + } + workT3[i] = bandWidthT[i] * workT1[i] * 0.01; + if (workT3[i] <= snr_limit) + workT3[i] = 0.0; + } + + for (i = 0; i < BANDS; i++) { + for (cnt2 = i; cnt2 < q->cyclTab[i]; cnt2++) + flcoeffs5[cnt2] = flcoeffs5[cnt2] + workT3[i]; + workT2[cnt2 - 1] = workT2[cnt2 - 1] + workT3[i]; + } + + for (i = 1; i < BANDS; i++) { + accum = (workT2[i - 1] + accum) * q->weights1[i - 1]; + flcoeffs5[i] += accum; + } + + for (i = 0; i < BANDS; i++) + workT2[i] = 0.0; + + for (i = 0; i < BANDS; i++) { + for (cnt2 = i - 1; cnt2 > q->cyclTab2[i]; cnt2--) + flcoeffs5[cnt2] += workT3[i]; + workT2[cnt2+1] += workT3[i]; + } + + accum = 0.0; + + for (i = BANDS-2; i >= 0; i--) { + accum = (workT2[i+1] + accum) * q->weights2[i]; + flcoeffs5[i] += accum; + // there is missing code here, but it seems to never be triggered + } +} + + +static void imc_read_level_coeffs(IMCContext *q, int stream_format_code, + int *levlCoeffs) +{ + int i; + VLC *hufftab[4]; + int start = 0; + const uint8_t *cb_sel; + int s; + + s = stream_format_code >> 1; + hufftab[0] = &huffman_vlc[s][0]; + hufftab[1] = &huffman_vlc[s][1]; + hufftab[2] = &huffman_vlc[s][2]; + hufftab[3] = &huffman_vlc[s][3]; + cb_sel = imc_cb_select[s]; + + if (stream_format_code & 4) + start = 1; + if (start) + levlCoeffs[0] = get_bits(&q->gb, 7); + for (i = start; i < BANDS; i++) { + levlCoeffs[i] = get_vlc2(&q->gb, hufftab[cb_sel[i]]->table, + hufftab[cb_sel[i]]->bits, 2); + if (levlCoeffs[i] == 17) + levlCoeffs[i] += get_bits(&q->gb, 4); + } +} + +static void imc_decode_level_coefficients(IMCContext *q, int *levlCoeffBuf, + float *flcoeffs1, float *flcoeffs2) +{ + int i, level; + float tmp, tmp2; + // maybe some frequency division thingy + + flcoeffs1[0] = 20000.0 / exp2 (levlCoeffBuf[0] * 0.18945); // 0.18945 = log2(10) * 0.05703125 + flcoeffs2[0] = log2f(flcoeffs1[0]); + tmp = flcoeffs1[0]; + tmp2 = flcoeffs2[0]; + + for (i = 1; i < BANDS; i++) { + level = levlCoeffBuf[i]; + if (level == 16) { + flcoeffs1[i] = 1.0; + flcoeffs2[i] = 0.0; + } else { + if (level < 17) + level -= 7; + else if (level <= 24) + level -= 32; + else + level -= 16; + + tmp *= imc_exp_tab[15 + level]; + tmp2 += 0.83048 * level; // 0.83048 = log2(10) * 0.25 + flcoeffs1[i] = tmp; + flcoeffs2[i] = tmp2; + } + } +} + + +static void imc_decode_level_coefficients2(IMCContext *q, int *levlCoeffBuf, + float *old_floor, float *flcoeffs1, + float *flcoeffs2) +{ + int i; + /* FIXME maybe flag_buf = noise coding and flcoeffs1 = new scale factors + * and flcoeffs2 old scale factors + * might be incomplete due to a missing table that is in the binary code + */ + for (i = 0; i < BANDS; i++) { + flcoeffs1[i] = 0; + if (levlCoeffBuf[i] < 16) { + flcoeffs1[i] = imc_exp_tab2[levlCoeffBuf[i]] * old_floor[i]; + flcoeffs2[i] = (levlCoeffBuf[i] - 7) * 0.83048 + flcoeffs2[i]; // 0.83048 = log2(10) * 0.25 + } else { + flcoeffs1[i] = old_floor[i]; + } + } +} + +/** + * Perform bit allocation depending on bits available + */ +static int bit_allocation(IMCContext *q, IMCChannel *chctx, + int stream_format_code, int freebits, int flag) +{ + int i, j; + const float limit = -1.e20; + float highest = 0.0; + int indx; + int t1 = 0; + int t2 = 1; + float summa = 0.0; + int iacc = 0; + int summer = 0; + int rres, cwlen; + float lowest = 1.e10; + int low_indx = 0; + float workT[32]; + int flg; + int found_indx = 0; + + for (i = 0; i < BANDS; i++) + highest = FFMAX(highest, chctx->flcoeffs1[i]); + + for (i = 0; i < BANDS - 1; i++) + chctx->flcoeffs4[i] = chctx->flcoeffs3[i] - log2f(chctx->flcoeffs5[i]); + chctx->flcoeffs4[BANDS - 1] = limit; + + highest = highest * 0.25; + + for (i = 0; i < BANDS; i++) { + indx = -1; + if ((band_tab[i + 1] - band_tab[i]) == chctx->bandWidthT[i]) + indx = 0; + + if ((band_tab[i + 1] - band_tab[i]) > chctx->bandWidthT[i]) + indx = 1; + + if (((band_tab[i + 1] - band_tab[i]) / 2) >= chctx->bandWidthT[i]) + indx = 2; + + if (indx == -1) + return AVERROR_INVALIDDATA; + + chctx->flcoeffs4[i] += xTab[(indx * 2 + (chctx->flcoeffs1[i] < highest)) * 2 + flag]; + } + + if (stream_format_code & 0x2) { + chctx->flcoeffs4[0] = limit; + chctx->flcoeffs4[1] = limit; + chctx->flcoeffs4[2] = limit; + chctx->flcoeffs4[3] = limit; + } + + for (i = (stream_format_code & 0x2) ? 4 : 0; i < BANDS - 1; i++) { + iacc += chctx->bandWidthT[i]; + summa += chctx->bandWidthT[i] * chctx->flcoeffs4[i]; + } + chctx->bandWidthT[BANDS - 1] = 0; + summa = (summa * 0.5 - freebits) / iacc; + + + for (i = 0; i < BANDS / 2; i++) { + rres = summer - freebits; + if ((rres >= -8) && (rres <= 8)) + break; + + summer = 0; + iacc = 0; + + for (j = (stream_format_code & 0x2) ? 4 : 0; j < BANDS; j++) { + cwlen = av_clipf(((chctx->flcoeffs4[j] * 0.5) - summa + 0.5), 0, 6); + + chctx->bitsBandT[j] = cwlen; + summer += chctx->bandWidthT[j] * cwlen; + + if (cwlen > 0) + iacc += chctx->bandWidthT[j]; + } + + flg = t2; + t2 = 1; + if (freebits < summer) + t2 = -1; + if (i == 0) + flg = t2; + if (flg != t2) + t1++; + + summa = (float)(summer - freebits) / ((t1 + 1) * iacc) + summa; + } + + for (i = (stream_format_code & 0x2) ? 4 : 0; i < BANDS; i++) { + for (j = band_tab[i]; j < band_tab[i + 1]; j++) + chctx->CWlengthT[j] = chctx->bitsBandT[i]; + } + + if (freebits > summer) { + for (i = 0; i < BANDS; i++) { + workT[i] = (chctx->bitsBandT[i] == 6) ? -1.e20 + : (chctx->bitsBandT[i] * -2 + chctx->flcoeffs4[i] - 0.415); + } + + highest = 0.0; + + do { + if (highest <= -1.e20) + break; + + found_indx = 0; + highest = -1.e20; + + for (i = 0; i < BANDS; i++) { + if (workT[i] > highest) { + highest = workT[i]; + found_indx = i; + } + } + + if (highest > -1.e20) { + workT[found_indx] -= 2.0; + if (++chctx->bitsBandT[found_indx] == 6) + workT[found_indx] = -1.e20; + + for (j = band_tab[found_indx]; j < band_tab[found_indx + 1] && (freebits > summer); j++) { + chctx->CWlengthT[j]++; + summer++; + } + } + } while (freebits > summer); + } + if (freebits < summer) { + for (i = 0; i < BANDS; i++) { + workT[i] = chctx->bitsBandT[i] ? (chctx->bitsBandT[i] * -2 + chctx->flcoeffs4[i] + 1.585) + : 1.e20; + } + if (stream_format_code & 0x2) { + workT[0] = 1.e20; + workT[1] = 1.e20; + workT[2] = 1.e20; + workT[3] = 1.e20; + } + while (freebits < summer) { + lowest = 1.e10; + low_indx = 0; + for (i = 0; i < BANDS; i++) { + if (workT[i] < lowest) { + lowest = workT[i]; + low_indx = i; + } + } + // if (lowest >= 1.e10) + // break; + workT[low_indx] = lowest + 2.0; + + if (!--chctx->bitsBandT[low_indx]) + workT[low_indx] = 1.e20; + + for (j = band_tab[low_indx]; j < band_tab[low_indx+1] && (freebits < summer); j++) { + if (chctx->CWlengthT[j] > 0) { + chctx->CWlengthT[j]--; + summer--; + } + } + } + } + return 0; +} + +static void imc_get_skip_coeff(IMCContext *q, IMCChannel *chctx) +{ + int i, j; + + memset(chctx->skipFlagBits, 0, sizeof(chctx->skipFlagBits)); + memset(chctx->skipFlagCount, 0, sizeof(chctx->skipFlagCount)); + for (i = 0; i < BANDS; i++) { + if (!chctx->bandFlagsBuf[i] || !chctx->bandWidthT[i]) + continue; + + if (!chctx->skipFlagRaw[i]) { + chctx->skipFlagBits[i] = band_tab[i + 1] - band_tab[i]; + + for (j = band_tab[i]; j < band_tab[i + 1]; j++) { + chctx->skipFlags[j] = get_bits1(&q->gb); + if (chctx->skipFlags[j]) + chctx->skipFlagCount[i]++; + } + } else { + for (j = band_tab[i]; j < band_tab[i + 1] - 1; j += 2) { + if (!get_bits1(&q->gb)) { // 0 + chctx->skipFlagBits[i]++; + chctx->skipFlags[j] = 1; + chctx->skipFlags[j + 1] = 1; + chctx->skipFlagCount[i] += 2; + } else { + if (get_bits1(&q->gb)) { // 11 + chctx->skipFlagBits[i] += 2; + chctx->skipFlags[j] = 0; + chctx->skipFlags[j + 1] = 1; + chctx->skipFlagCount[i]++; + } else { + chctx->skipFlagBits[i] += 3; + chctx->skipFlags[j + 1] = 0; + if (!get_bits1(&q->gb)) { // 100 + chctx->skipFlags[j] = 1; + chctx->skipFlagCount[i]++; + } else { // 101 + chctx->skipFlags[j] = 0; + } + } + } + } + + if (j < band_tab[i + 1]) { + chctx->skipFlagBits[i]++; + if ((chctx->skipFlags[j] = get_bits1(&q->gb))) + chctx->skipFlagCount[i]++; + } + } + } +} + +/** + * Increase highest' band coefficient sizes as some bits won't be used + */ +static void imc_adjust_bit_allocation(IMCContext *q, IMCChannel *chctx, + int summer) +{ + float workT[32]; + int corrected = 0; + int i, j; + float highest = 0; + int found_indx = 0; + + for (i = 0; i < BANDS; i++) { + workT[i] = (chctx->bitsBandT[i] == 6) ? -1.e20 + : (chctx->bitsBandT[i] * -2 + chctx->flcoeffs4[i] - 0.415); + } + + while (corrected < summer) { + if (highest <= -1.e20) + break; + + highest = -1.e20; + + for (i = 0; i < BANDS; i++) { + if (workT[i] > highest) { + highest = workT[i]; + found_indx = i; + } + } + + if (highest > -1.e20) { + workT[found_indx] -= 2.0; + if (++(chctx->bitsBandT[found_indx]) == 6) + workT[found_indx] = -1.e20; + + for (j = band_tab[found_indx]; j < band_tab[found_indx+1] && (corrected < summer); j++) { + if (!chctx->skipFlags[j] && (chctx->CWlengthT[j] < 6)) { + chctx->CWlengthT[j]++; + corrected++; + } + } + } + } +} + +static void imc_imdct256(IMCContext *q, IMCChannel *chctx, int channels) +{ + int i; + float re, im; + float *dst1 = q->out_samples; + float *dst2 = q->out_samples + (COEFFS - 1); + + /* prerotation */ + for (i = 0; i < COEFFS / 2; i++) { + q->samples[i].re = -(q->pre_coef1[i] * chctx->CWdecoded[COEFFS - 1 - i * 2]) - + (q->pre_coef2[i] * chctx->CWdecoded[i * 2]); + q->samples[i].im = (q->pre_coef2[i] * chctx->CWdecoded[COEFFS - 1 - i * 2]) - + (q->pre_coef1[i] * chctx->CWdecoded[i * 2]); + } + + /* FFT */ + q->fft.fft_permute(&q->fft, q->samples); + q->fft.fft_calc(&q->fft, q->samples); + + /* postrotation, window and reorder */ + for (i = 0; i < COEFFS / 2; i++) { + re = ( q->samples[i].re * q->post_cos[i]) + (-q->samples[i].im * q->post_sin[i]); + im = (-q->samples[i].im * q->post_cos[i]) - ( q->samples[i].re * q->post_sin[i]); + *dst1 = (q->mdct_sine_window[COEFFS - 1 - i * 2] * chctx->last_fft_im[i]) + + (q->mdct_sine_window[i * 2] * re); + *dst2 = (q->mdct_sine_window[i * 2] * chctx->last_fft_im[i]) + - (q->mdct_sine_window[COEFFS - 1 - i * 2] * re); + dst1 += 2; + dst2 -= 2; + chctx->last_fft_im[i] = im; + } +} + +static int inverse_quant_coeff(IMCContext *q, IMCChannel *chctx, + int stream_format_code) +{ + int i, j; + int middle_value, cw_len, max_size; + const float *quantizer; + + for (i = 0; i < BANDS; i++) { + for (j = band_tab[i]; j < band_tab[i + 1]; j++) { + chctx->CWdecoded[j] = 0; + cw_len = chctx->CWlengthT[j]; + + if (cw_len <= 0 || chctx->skipFlags[j]) + continue; + + max_size = 1 << cw_len; + middle_value = max_size >> 1; + + if (chctx->codewords[j] >= max_size || chctx->codewords[j] < 0) + return AVERROR_INVALIDDATA; + + if (cw_len >= 4) { + quantizer = imc_quantizer2[(stream_format_code & 2) >> 1]; + if (chctx->codewords[j] >= middle_value) + chctx->CWdecoded[j] = quantizer[chctx->codewords[j] - 8] * chctx->flcoeffs6[i]; + else + chctx->CWdecoded[j] = -quantizer[max_size - chctx->codewords[j] - 8 - 1] * chctx->flcoeffs6[i]; + }else{ + quantizer = imc_quantizer1[((stream_format_code & 2) >> 1) | (chctx->bandFlagsBuf[i] << 1)]; + if (chctx->codewords[j] >= middle_value) + chctx->CWdecoded[j] = quantizer[chctx->codewords[j] - 1] * chctx->flcoeffs6[i]; + else + chctx->CWdecoded[j] = -quantizer[max_size - 2 - chctx->codewords[j]] * chctx->flcoeffs6[i]; + } + } + } + return 0; +} + + +static int imc_get_coeffs(IMCContext *q, IMCChannel *chctx) +{ + int i, j, cw_len, cw; + + for (i = 0; i < BANDS; i++) { + if (!chctx->sumLenArr[i]) + continue; + if (chctx->bandFlagsBuf[i] || chctx->bandWidthT[i]) { + for (j = band_tab[i]; j < band_tab[i + 1]; j++) { + cw_len = chctx->CWlengthT[j]; + cw = 0; + + if (get_bits_count(&q->gb) + cw_len > 512) { + av_dlog(NULL, "Band %i coeff %i cw_len %i\n", i, j, cw_len); + return AVERROR_INVALIDDATA; + } + + if (cw_len && (!chctx->bandFlagsBuf[i] || !chctx->skipFlags[j])) + cw = get_bits(&q->gb, cw_len); + + chctx->codewords[j] = cw; + } + } + } + return 0; +} + +static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) +{ + int stream_format_code; + int imc_hdr, i, j, ret; + int flag; + int bits, summer; + int counter, bitscount; + IMCChannel *chctx = q->chctx + ch; + + + /* Check the frame header */ + imc_hdr = get_bits(&q->gb, 9); + if (imc_hdr & 0x18) { + av_log(avctx, AV_LOG_ERROR, "frame header check failed!\n"); + av_log(avctx, AV_LOG_ERROR, "got %X.\n", imc_hdr); + return AVERROR_INVALIDDATA; + } + stream_format_code = get_bits(&q->gb, 3); + + if (stream_format_code & 1) { + avpriv_request_sample(avctx, "Stream format %X", stream_format_code); + return AVERROR_PATCHWELCOME; + } + + if (stream_format_code & 0x04) + chctx->decoder_reset = 1; + + if (chctx->decoder_reset) { + for (i = 0; i < BANDS; i++) + chctx->old_floor[i] = 1.0; + for (i = 0; i < COEFFS; i++) + chctx->CWdecoded[i] = 0; + chctx->decoder_reset = 0; + } + + flag = get_bits1(&q->gb); + imc_read_level_coeffs(q, stream_format_code, chctx->levlCoeffBuf); + + if (stream_format_code & 0x4) + imc_decode_level_coefficients(q, chctx->levlCoeffBuf, + chctx->flcoeffs1, chctx->flcoeffs2); + else + imc_decode_level_coefficients2(q, chctx->levlCoeffBuf, chctx->old_floor, + chctx->flcoeffs1, chctx->flcoeffs2); + + for(i=0; iflcoeffs1[i] > INT_MAX) { + av_log(avctx, AV_LOG_ERROR, "scalefactor out of range\n"); + return AVERROR_INVALIDDATA; + } + } + + memcpy(chctx->old_floor, chctx->flcoeffs1, 32 * sizeof(float)); + + counter = 0; + for (i = 0; i < BANDS; i++) { + if (chctx->levlCoeffBuf[i] == 16) { + chctx->bandWidthT[i] = 0; + counter++; + } else + chctx->bandWidthT[i] = band_tab[i + 1] - band_tab[i]; + } + memset(chctx->bandFlagsBuf, 0, BANDS * sizeof(int)); + for (i = 0; i < BANDS - 1; i++) { + if (chctx->bandWidthT[i]) + chctx->bandFlagsBuf[i] = get_bits1(&q->gb); + } + + imc_calculate_coeffs(q, chctx->flcoeffs1, chctx->flcoeffs2, chctx->bandWidthT, chctx->flcoeffs3, chctx->flcoeffs5); + + bitscount = 0; + /* first 4 bands will be assigned 5 bits per coefficient */ + if (stream_format_code & 0x2) { + bitscount += 15; + + chctx->bitsBandT[0] = 5; + chctx->CWlengthT[0] = 5; + chctx->CWlengthT[1] = 5; + chctx->CWlengthT[2] = 5; + for (i = 1; i < 4; i++) { + bits = (chctx->levlCoeffBuf[i] == 16) ? 0 : 5; + chctx->bitsBandT[i] = bits; + for (j = band_tab[i]; j < band_tab[i + 1]; j++) { + chctx->CWlengthT[j] = bits; + bitscount += bits; + } + } + } + if (avctx->codec_id == AV_CODEC_ID_IAC) { + bitscount += !!chctx->bandWidthT[BANDS - 1]; + if (!(stream_format_code & 0x2)) + bitscount += 16; + } + + if ((ret = bit_allocation(q, chctx, stream_format_code, + 512 - bitscount - get_bits_count(&q->gb), + flag)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Bit allocations failed\n"); + chctx->decoder_reset = 1; + return ret; + } + + for (i = 0; i < BANDS; i++) { + chctx->sumLenArr[i] = 0; + chctx->skipFlagRaw[i] = 0; + for (j = band_tab[i]; j < band_tab[i + 1]; j++) + chctx->sumLenArr[i] += chctx->CWlengthT[j]; + if (chctx->bandFlagsBuf[i]) + if ((((band_tab[i + 1] - band_tab[i]) * 1.5) > chctx->sumLenArr[i]) && (chctx->sumLenArr[i] > 0)) + chctx->skipFlagRaw[i] = 1; + } + + imc_get_skip_coeff(q, chctx); + + for (i = 0; i < BANDS; i++) { + chctx->flcoeffs6[i] = chctx->flcoeffs1[i]; + /* band has flag set and at least one coded coefficient */ + if (chctx->bandFlagsBuf[i] && (band_tab[i + 1] - band_tab[i]) != chctx->skipFlagCount[i]) { + chctx->flcoeffs6[i] *= q->sqrt_tab[ band_tab[i + 1] - band_tab[i]] / + q->sqrt_tab[(band_tab[i + 1] - band_tab[i] - chctx->skipFlagCount[i])]; + } + } + + /* calculate bits left, bits needed and adjust bit allocation */ + bits = summer = 0; + + for (i = 0; i < BANDS; i++) { + if (chctx->bandFlagsBuf[i]) { + for (j = band_tab[i]; j < band_tab[i + 1]; j++) { + if (chctx->skipFlags[j]) { + summer += chctx->CWlengthT[j]; + chctx->CWlengthT[j] = 0; + } + } + bits += chctx->skipFlagBits[i]; + summer -= chctx->skipFlagBits[i]; + } + } + imc_adjust_bit_allocation(q, chctx, summer); + + for (i = 0; i < BANDS; i++) { + chctx->sumLenArr[i] = 0; + + for (j = band_tab[i]; j < band_tab[i + 1]; j++) + if (!chctx->skipFlags[j]) + chctx->sumLenArr[i] += chctx->CWlengthT[j]; + } + + memset(chctx->codewords, 0, sizeof(chctx->codewords)); + + if (imc_get_coeffs(q, chctx) < 0) { + av_log(avctx, AV_LOG_ERROR, "Read coefficients failed\n"); + chctx->decoder_reset = 1; + return AVERROR_INVALIDDATA; + } + + if (inverse_quant_coeff(q, chctx, stream_format_code) < 0) { + av_log(avctx, AV_LOG_ERROR, "Inverse quantization of coefficients failed\n"); + chctx->decoder_reset = 1; + return AVERROR_INVALIDDATA; + } + + memset(chctx->skipFlags, 0, sizeof(chctx->skipFlags)); + + imc_imdct256(q, chctx, avctx->channels); + + return 0; +} + +static int imc_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int ret, i; + + IMCContext *q = avctx->priv_data; + + LOCAL_ALIGNED_16(uint16_t, buf16, [IMC_BLOCK_SIZE / 2]); + + if (buf_size < IMC_BLOCK_SIZE * avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "frame too small!\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = COEFFS; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (i = 0; i < avctx->channels; i++) { + q->out_samples = (float *)frame->extended_data[i]; + + q->dsp.bswap16_buf(buf16, (const uint16_t*)buf, IMC_BLOCK_SIZE / 2); + + init_get_bits(&q->gb, (const uint8_t*)buf16, IMC_BLOCK_SIZE * 8); + + buf += IMC_BLOCK_SIZE; + + if ((ret = imc_decode_block(avctx, q, i)) < 0) + return ret; + } + + if (avctx->channels == 2) { + q->fdsp.butterflies_float((float *)frame->extended_data[0], + (float *)frame->extended_data[1], COEFFS); + } + + *got_frame_ptr = 1; + + return IMC_BLOCK_SIZE * avctx->channels; +} + + +static av_cold int imc_decode_close(AVCodecContext * avctx) +{ + IMCContext *q = avctx->priv_data; + + ff_fft_end(&q->fft); + + return 0; +} + +static av_cold void flush(AVCodecContext *avctx) +{ + IMCContext *q = avctx->priv_data; + + q->chctx[0].decoder_reset = + q->chctx[1].decoder_reset = 1; +} + +#if CONFIG_IMC_DECODER +AVCodec ff_imc_decoder = { + .name = "imc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_IMC, + .priv_data_size = sizeof(IMCContext), + .init = imc_decode_init, + .close = imc_decode_close, + .decode = imc_decode_frame, + .flush = flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_IAC_DECODER +AVCodec ff_iac_decoder = { + .name = "iac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_IAC, + .priv_data_size = sizeof(IMCContext), + .init = imc_decode_init, + .close = imc_decode_close, + .decode = imc_decode_frame, + .flush = flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; +#endif diff --git a/ffmpeg/libavcodec/imcdata.h b/ffmpeg/libavcodec/imcdata.h new file mode 100644 index 0000000..64e7c71 --- /dev/null +++ b/ffmpeg/libavcodec/imcdata.h @@ -0,0 +1,169 @@ +/* + * IMC compatible decoder + * Copyright (c) 2002-2004 Maxim Poliakovski + * Copyright (c) 2006 Benjamin Larsson + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_IMCDATA_H +#define AVCODEC_IMCDATA_H + +#include + +static const uint16_t band_tab[33] = { + 0, 3, 6, 9, 12, 16, 20, 24, 29, 34, 40, + 46, 53, 60, 68, 76, 84, 93, 102, 111, 121, 131, + 141, 151, 162, 173, 184, 195, 207, 219, 231, 243, 256, +}; + + +static const int8_t cyclTab[32] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, +}; + +static const int8_t cyclTab2[32] = { + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 21, 22, +23, 24, 25, 26, 27, 28, 29}; + +static const float imc_weights1[31] = { + 0.119595, 0.123124, 0.129192, 9.97377e-2, 8.1923e-2, 9.61153e-2, 8.77885e-2, 8.61174e-2, + 9.00882e-2, 9.91658e-2, 0.112991, 0.131126, 0.152886, 0.177292, 0.221782, 0.244917, 0.267386, + 0.306816, 0.323046, 0.33729, 0.366773, 0.392557, 0.398076, 0.403302, 0.42451, 0.444777, + 0.449188, 0.455445, 0.477853, 0.500669, 0.510395}; + +static const float imc_weights2[31] = { + 3.23466e-3, 3.49886e-3, 3.98413e-3, 1.98116e-3, 1.16465e-3, 1.79283e-3, 1.40372e-3, 1.33274e-3, + 1.50523e-3, 1.95064e-3, 2.77472e-3, 4.14725e-3, 6.2776e-3, 9.36401e-3, 1.71397e-2, 2.24052e-2, + 2.83971e-2, 4.11689e-2, 4.73165e-2, 5.31631e-2, 6.66614e-2, 8.00824e-2, 8.31588e-2, 8.61397e-2, + 9.89229e-2, 0.112197, 0.115227, 0.119613, 0.136174, 0.15445, 0.162685}; + +static const float imc_quantizer1[4][8] = { + { 8.4431201e-1, 4.7358301e-1, 1.448354, 2.7073899e-1, 7.4449003e-1, 1.241991, 1.845484, 0.0}, + { 8.6876702e-1, 4.7659001e-1, 1.478224, 2.5672799e-1, 7.55777e-1, 1.3229851, 2.03438, 0.0}, + { 7.5891501e-1, 6.2272799e-1, 1.271322, 3.47904e-1, 7.5317699e-1, 1.150767, 1.628476, 0.0}, + { 7.65257e-1, 6.44647e-1, 1.263824, 3.4548101e-1, 7.6384902e-1, 1.214466, 1.7638789, 0.0}, +}; + +static const float imc_quantizer2[2][56] = { + { 1.39236e-1, 3.50548e-1, 5.9547901e-1, 8.5772401e-1, 1.121545, 1.3882281, 1.695882, 2.1270809, + 7.2221003e-2, 1.85177e-1, 2.9521701e-1, 4.12568e-1, 5.4068601e-1, 6.7679501e-1, 8.1196898e-1, 9.4765198e-1, + 1.0779999, 1.203415, 1.337265, 1.481871, 1.639982, 1.814766, 2.0701399, 2.449862, + 3.7533998e-2, 1.02722e-1, 1.6021401e-1, 2.16043e-1, 2.7231601e-1, 3.3025399e-1, 3.9022601e-1, 4.52849e-1, + 5.1794899e-1, 5.8529502e-1, 6.53956e-1, 7.2312802e-1, 7.9150802e-1, 8.5891002e-1, 9.28141e-1, 9.9706203e-1, + 1.062153, 1.12564, 1.189834, 1.256122, 1.324469, 1.3955311, 1.468906, 1.545084, + 1.6264729, 1.711524, 1.802705, 1.91023, 2.0533991, 2.22333, 2.4830019, 3.253329 }, + { 1.11654e-1, 3.54469e-1, 6.4232099e-1, 9.6128798e-1, 1.295053, 1.61777, 1.989839, 2.51107, + 5.7721999e-2, 1.69879e-1, 2.97589e-1, 4.3858799e-1, 5.9039903e-1, 7.4934798e-1, 9.1628098e-1, 1.087297, + 1.262751, 1.4288321, 1.6040879, 1.79067, 2.000668, 2.2394669, 2.649332, 5.2760072, + 2.9722e-2, 8.7316997e-2, 1.4445201e-1, 2.04247e-1, 2.6879501e-1, 3.3716801e-1, 4.08811e-1, 4.8306999e-1, + 5.6049401e-1, 6.3955498e-1, 7.2044599e-1, 8.0427998e-1, 8.8933599e-1, 9.7537601e-1, 1.062461, 1.1510431, + 1.240236, 1.326715, 1.412513, 1.500502, 1.591749, 1.686413, 1.785239, 1.891233, + 2.0051291, 2.127681, 2.2709141, 2.475826, 2.7219379, 3.101985, 4.686213, 6.2287788}, +}; + + +static const float xTab[14] = {7.6, 3.6, 4.4, 3.7, 6.1, 5.1, 2.3, 1.6, 6.2, 1.5, 1.8, 1.2, 0, 0}; //10014048 + +/* precomputed table for 10^(i/4), i=-15..16 */ +static const float imc_exp_tab[32] = { + 1.778280e-4, 3.162278e-4, 5.623413e-4, 1.000000e-3, + 1.778280e-3, 3.162278e-3, 5.623413e-3, 1.000000e-2, + 1.778280e-2, 3.162278e-2, 5.623413e-2, 1.000000e-1, + 1.778280e-1, 3.162278e-1, 5.623413e-1, 1.000000e00, + 1.778280e00, 3.162278e00, 5.623413e00, 1.000000e01, + 1.778280e01, 3.162278e01, 5.623413e01, 1.000000e02, + 1.778280e02, 3.162278e02, 5.623413e02, 1.000000e03, + 1.778280e03, 3.162278e03, 5.623413e03, 1.000000e04 +}; +static const float * const imc_exp_tab2 = imc_exp_tab + 8; + + +static const uint8_t imc_cb_select[4][32] = { + { 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2 }, + { 0, 2, 0, 3, 2, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2 }, + { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const uint8_t imc_huffman_sizes[4] = { + 17, 17, 18, 18 +}; + +static const uint8_t imc_huffman_lens[4][4][18] = { + { + { 16, 15, 13, 11, 8, 5, 3, 1, 2, 4, 6, 9, 10, 12, 14, 16, 7, 0 }, + { 10, 8, 7, 6, 4, 4, 3, 2, 2, 3, 4, 6, 7, 9, 11, 11, 7, 0 }, + { 15, 15, 14, 11, 8, 6, 4, 2, 1, 4, 5, 7, 9, 10, 12, 13, 4, 0 }, + { 13, 11, 10, 8, 6, 4, 2, 2, 2, 3, 5, 7, 9, 12, 15, 15, 14, 0 }, + }, + { + { 14, 12, 10, 8, 7, 4, 2, 2, 2, 3, 5, 7, 9, 11, 13, 14, 7, 0 }, + { 14, 13, 11, 8, 6, 4, 3, 2, 2, 3, 5, 7, 9, 10, 12, 14, 3, 0 }, + { 13, 12, 10, 7, 5, 4, 3, 2, 2, 3, 4, 6, 8, 9, 11, 13, 4, 0 }, + { 13, 12, 10, 7, 5, 4, 3, 2, 2, 3, 4, 6, 8, 9, 11, 13, 4, 0 }, + }, + { + { 16, 14, 12, 10, 8, 5, 3, 1, 2, 4, 7, 9, 11, 13, 15, 17, 6, 17 }, + { 15, 13, 11, 8, 6, 4, 2, 2, 2, 3, 5, 7, 10, 12, 14, 16, 9, 16 }, + { 14, 12, 11, 9, 8, 6, 3, 1, 2, 5, 7, 10, 13, 15, 16, 17, 4, 17 }, + { 16, 14, 12, 9, 7, 5, 2, 2, 2, 3, 4, 6, 8, 11, 13, 15, 10, 16 }, + }, + { + { 13, 11, 10, 8, 7, 5, 2, 2, 2, 4, 6, 9, 12, 14, 15, 16, 3, 16 }, + { 11, 11, 10, 9, 8, 7, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 5 }, + { 9, 9, 7, 6, 5, 4, 3, 3, 2, 3, 4, 5, 4, 5, 5, 6, 8, 6 }, + { 13, 12, 10, 8, 5, 3, 3, 2, 2, 3, 4, 7, 9, 11, 14, 15, 6, 15 }, + } +}; + +static const uint16_t imc_huffman_bits[4][4][18] = { + { + { 0xCC32, 0x6618, 0x1987, 0x0660, 0x00CD, 0x0018, 0x0007, 0x0000, 0x0002, 0x000D, 0x0032, 0x0199, 0x0331, 0x0CC2, 0x330D, 0xCC33, 0x0067, 0x0000 }, + { 0x02FE, 0x00BE, 0x005E, 0x002D, 0x000A, 0x0009, 0x0003, 0x0003, 0x0000, 0x0002, 0x0008, 0x002C, 0x005D, 0x017E, 0x05FE, 0x05FF, 0x005C, 0x0000 }, + { 0x5169, 0x5168, 0x28B5, 0x0517, 0x00A3, 0x0029, 0x0008, 0x0003, 0x0000, 0x0009, 0x0015, 0x0050, 0x0144, 0x028A, 0x0A2C, 0x145B, 0x000B, 0x0000 }, + { 0x1231, 0x048D, 0x0247, 0x0090, 0x0025, 0x0008, 0x0001, 0x0003, 0x0000, 0x0005, 0x0013, 0x0049, 0x0122, 0x0919, 0x48C3, 0x48C2, 0x2460, 0x0000 }, + }, + { + { 0x2D1D, 0x0B46, 0x02D0, 0x00B5, 0x0059, 0x000A, 0x0003, 0x0001, 0x0000, 0x0004, 0x0017, 0x005B, 0x0169, 0x05A2, 0x168F, 0x2D1C, 0x0058, 0x0000 }, + { 0x1800, 0x0C01, 0x0301, 0x0061, 0x0019, 0x0007, 0x0004, 0x0003, 0x0000, 0x0005, 0x000D, 0x0031, 0x00C1, 0x0181, 0x0601, 0x1801, 0x0002, 0x0000 }, + { 0x1556, 0x0AAA, 0x02AB, 0x0054, 0x0014, 0x000B, 0x0002, 0x0003, 0x0000, 0x0003, 0x0008, 0x002B, 0x00AB, 0x0154, 0x0554, 0x1557, 0x0009, 0x0000 }, + { 0x1556, 0x0AAA, 0x02AB, 0x0054, 0x0014, 0x000B, 0x0002, 0x0003, 0x0000, 0x0003, 0x0008, 0x002B, 0x00AB, 0x0154, 0x0554, 0x1557, 0x0009, 0x0000 }, + }, + { + { 0x2993, 0x0A65, 0x0298, 0x00A7, 0x0028, 0x0004, 0x0000, 0x0001, 0x0001, 0x0003, 0x0015, 0x0052, 0x014D, 0x0533, 0x14C8, 0x5324, 0x000B, 0x5325 }, + { 0x09B8, 0x026F, 0x009A, 0x0012, 0x0005, 0x0000, 0x0001, 0x0002, 0x0003, 0x0001, 0x0003, 0x0008, 0x004C, 0x0136, 0x04DD, 0x1373, 0x0027, 0x1372 }, + { 0x0787, 0x01E0, 0x00F1, 0x003D, 0x001F, 0x0006, 0x0001, 0x0001, 0x0001, 0x0002, 0x000E, 0x0079, 0x03C2, 0x0F0D, 0x1E19, 0x3C30, 0x0000, 0x3C31 }, + { 0x4B06, 0x12C0, 0x04B1, 0x0097, 0x0024, 0x0008, 0x0002, 0x0003, 0x0000, 0x0003, 0x0005, 0x0013, 0x004A, 0x0259, 0x0961, 0x2582, 0x012D, 0x4B07 }, + }, + { + { 0x0A5A, 0x0297, 0x014A, 0x0053, 0x0028, 0x000B, 0x0003, 0x0000, 0x0002, 0x0004, 0x0015, 0x00A4, 0x052C, 0x14B7, 0x296C, 0x52DB, 0x0003, 0x52DA }, + { 0x0193, 0x0192, 0x00C8, 0x0065, 0x0033, 0x0018, 0x0007, 0x0004, 0x0000, 0x0004, 0x0005, 0x0007, 0x0006, 0x0003, 0x0005, 0x0005, 0x000D, 0x0004 }, + { 0x0012, 0x0013, 0x0005, 0x0003, 0x0000, 0x0003, 0x0005, 0x0004, 0x0003, 0x0003, 0x0005, 0x0005, 0x0004, 0x0004, 0x0003, 0x0005, 0x0008, 0x0004 }, + { 0x0D66, 0x06B2, 0x01AD, 0x006A, 0x000C, 0x0005, 0x0004, 0x0000, 0x0003, 0x0002, 0x0007, 0x0034, 0x00D7, 0x0358, 0x1ACF, 0x359C, 0x001B, 0x359D }, + } +}; + +#endif /* AVCODEC_IMCDATA_H */ diff --git a/ffmpeg/libavcodec/imgconvert.c b/ffmpeg/libavcodec/imgconvert.c new file mode 100644 index 0000000..cf3c967 --- /dev/null +++ b/ffmpeg/libavcodec/imgconvert.c @@ -0,0 +1,665 @@ +/* + * Misc image conversion routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * misc image conversion routines + */ + +/* TODO: + * - write 'ffimg' program to test all the image related stuff + * - move all api to slice based system + * - integrate deinterlacing, postprocessing and scaling in the conversion process + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "imgconvert.h" +#include "internal.h" +#include "libavutil/avassert.h" +#include "libavutil/colorspace.h" +#include "libavutil/common.h" +#include "libavutil/pixdesc.h" +#include "libavutil/imgutils.h" + +#if HAVE_MMX_EXTERNAL +#include "x86/dsputil_mmx.h" +#endif + +#define FF_COLOR_NA -1 +#define FF_COLOR_RGB 0 /**< RGB color space */ +#define FF_COLOR_GRAY 1 /**< gray color space */ +#define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ +#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ + +#if HAVE_MMX_EXTERNAL +#define deinterlace_line_inplace ff_deinterlace_line_inplace_mmx +#define deinterlace_line ff_deinterlace_line_mmx +#else +#define deinterlace_line_inplace deinterlace_line_inplace_c +#define deinterlace_line deinterlace_line_c +#endif + +#define pixdesc_has_alpha(pixdesc) \ + ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & PIX_FMT_PAL) + + +void avcodec_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + *h_shift = desc->log2_chroma_w; + *v_shift = desc->log2_chroma_h; +} + +static int get_color_type(const AVPixFmtDescriptor *desc) { + if(desc->nb_components == 1 || desc->nb_components == 2) + return FF_COLOR_GRAY; + + if(desc->name && !strncmp(desc->name, "yuvj", 4)) + return FF_COLOR_YUV_JPEG; + + if(desc->flags & PIX_FMT_RGB) + return FF_COLOR_RGB; + + if(desc->nb_components == 0) + return FF_COLOR_NA; + + return FF_COLOR_YUV; +} + +static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int i; + + if (!desc || !desc->nb_components) { + *min = *max = 0; + return AVERROR(EINVAL); + } + + *min = INT_MAX, *max = -INT_MAX; + for (i = 0; i < desc->nb_components; i++) { + *min = FFMIN(desc->comp[i].depth_minus1+1, *min); + *max = FFMAX(desc->comp[i].depth_minus1+1, *max); + } + return 0; +} + +static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + unsigned *lossp, unsigned consider) +{ + const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt); + const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt); + int src_color, dst_color; + int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth; + int ret, loss, i, nb_components; + int score = INT_MAX; + + if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) + return ~0; + + /* compute loss */ + *lossp = loss = 0; + + if (dst_pix_fmt == src_pix_fmt) + return INT_MAX; + + if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) + return ret; + if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) + return ret; + + src_color = get_color_type(src_desc); + dst_color = get_color_type(dst_desc); + nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); + + for (i = 0; i < nb_components; i++) + if (src_desc->comp[i].depth_minus1 > dst_desc->comp[i].depth_minus1 && (consider & FF_LOSS_DEPTH)) { + loss |= FF_LOSS_DEPTH; + score -= 65536 >> dst_desc->comp[i].depth_minus1; + } + + if (consider & FF_LOSS_RESOLUTION) { + if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) { + loss |= FF_LOSS_RESOLUTION; + score -= 256 << dst_desc->log2_chroma_w; + } + if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) { + loss |= FF_LOSS_RESOLUTION; + score -= 256 << dst_desc->log2_chroma_h; + } + // dont favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side + if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 && + dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) { + score += 512; + } + } + + if(consider & FF_LOSS_COLORSPACE) + switch(dst_color) { + case FF_COLOR_RGB: + if (src_color != FF_COLOR_RGB && + src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_GRAY: + if (src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV: + if (src_color != FF_COLOR_YUV) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV_JPEG: + if (src_color != FF_COLOR_YUV_JPEG && + src_color != FF_COLOR_YUV && + src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + default: + /* fail safe test */ + if (src_color != dst_color) + loss |= FF_LOSS_COLORSPACE; + break; + } + if(loss & FF_LOSS_COLORSPACE) + score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1); + + if (dst_color == FF_COLOR_GRAY && + src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) { + loss |= FF_LOSS_CHROMA; + score -= 2 * 65536; + } + if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) { + loss |= FF_LOSS_ALPHA; + score -= 65536; + } + if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) && + (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) { + loss |= FF_LOSS_COLORQUANT; + score -= 65536; + } + + *lossp = loss; + return score; +} + +int avcodec_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha) +{ + int loss; + int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA); + if (ret < 0) + return ret; + return loss; +} + +enum AVPixelFormat avcodec_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) +{ + enum AVPixelFormat dst_pix_fmt; + int loss1, loss2, loss_mask; + const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1); + const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2); + int score1, score2; + + loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ + if(!has_alpha) + loss_mask &= ~FF_LOSS_ALPHA; + + dst_pix_fmt = AV_PIX_FMT_NONE; + score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask); + score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask); + + if (score1 == score2) { + if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) { + dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1; + } else { + dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1; + } + } else { + dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1; + } + + if (loss_ptr) + *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); + return dst_pix_fmt; +} + +#if AV_HAVE_INCOMPATIBLE_FORK_ABI +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr){ + return avcodec_find_best_pix_fmt_of_list(pix_fmt_list, src_pix_fmt, has_alpha, loss_ptr); +} +#else +enum AVPixelFormat avcodec_find_best_pix_fmt2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) +{ + return avcodec_find_best_pix_fmt_of_2(dst_pix_fmt1, dst_pix_fmt2, src_pix_fmt, has_alpha, loss_ptr); +} +#endif + +enum AVPixelFormat avcodec_find_best_pix_fmt_of_list(enum AVPixelFormat *pix_fmt_list, + enum AVPixelFormat src_pix_fmt, + int has_alpha, int *loss_ptr){ + int i; + + enum AVPixelFormat best = AV_PIX_FMT_NONE; + + for(i=0; pix_fmt_list[i] != AV_PIX_FMT_NONE; i++) + best = avcodec_find_best_pix_fmt_of_2(best, pix_fmt_list[i], src_pix_fmt, has_alpha, loss_ptr); + + return best; +} + +/* 2x2 -> 1x1 */ +void ff_shrink22(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w; + const uint8_t *s1, *s2; + uint8_t *d; + + for(;height > 0; height--) { + s1 = src; + s2 = s1 + src_wrap; + d = dst; + for(w = width;w >= 4; w-=4) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; + d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; + d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; + s1 += 8; + s2 += 8; + d += 4; + } + for(;w > 0; w--) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + s1 += 2; + s2 += 2; + d++; + } + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 4x4 -> 1x1 */ +void ff_shrink44(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w; + const uint8_t *s1, *s2, *s3, *s4; + uint8_t *d; + + for(;height > 0; height--) { + s1 = src; + s2 = s1 + src_wrap; + s3 = s2 + src_wrap; + s4 = s3 + src_wrap; + d = dst; + for(w = width;w > 0; w--) { + d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + + s2[0] + s2[1] + s2[2] + s2[3] + + s3[0] + s3[1] + s3[2] + s3[3] + + s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; + s1 += 4; + s2 += 4; + s3 += 4; + s4 += 4; + d++; + } + src += 4 * src_wrap; + dst += dst_wrap; + } +} + +/* 8x8 -> 1x1 */ +void ff_shrink88(uint8_t *dst, int dst_wrap, + const uint8_t *src, int src_wrap, + int width, int height) +{ + int w, i; + + for(;height > 0; height--) { + for(w = width;w > 0; w--) { + int tmp=0; + for(i=0; i<8; i++){ + tmp += src[0] + src[1] + src[2] + src[3] + src[4] + src[5] + src[6] + src[7]; + src += src_wrap; + } + *(dst++) = (tmp + 32)>>6; + src += 8 - 8*src_wrap; + } + src += 8*src_wrap - 8*width; + dst += dst_wrap - width; + } +} + +/* return true if yuv planar */ +static inline int is_yuv_planar(const AVPixFmtDescriptor *desc) +{ + int i; + int planes[4] = { 0 }; + + if ( desc->flags & PIX_FMT_RGB + || !(desc->flags & PIX_FMT_PLANAR)) + return 0; + + /* set the used planes */ + for (i = 0; i < desc->nb_components; i++) + planes[desc->comp[i].plane] = 1; + + /* if there is an unused plane, the format is not planar */ + for (i = 0; i < desc->nb_components; i++) + if (!planes[i]) + return 0; + return 1; +} + +int av_picture_crop(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int top_band, int left_band) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int y_shift; + int x_shift; + + if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB) + return -1; + + y_shift = desc->log2_chroma_h; + x_shift = desc->log2_chroma_w; + + if (is_yuv_planar(desc)) { + dst->data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band; + dst->data[1] = src->data[1] + ((top_band >> y_shift) * src->linesize[1]) + (left_band >> x_shift); + dst->data[2] = src->data[2] + ((top_band >> y_shift) * src->linesize[2]) + (left_band >> x_shift); + } else{ + if(top_band % (1<data[0] = src->data[0] + (top_band * src->linesize[0]) + left_band; + } + + dst->linesize[0] = src->linesize[0]; + dst->linesize[1] = src->linesize[1]; + dst->linesize[2] = src->linesize[2]; + return 0; +} + +int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width, + enum AVPixelFormat pix_fmt, int padtop, int padbottom, int padleft, int padright, + int *color) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + uint8_t *optr; + int y_shift; + int x_shift; + int yheight; + int i, y; + + if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB || + !is_yuv_planar(desc)) return -1; + + for (i = 0; i < 3; i++) { + x_shift = i ? desc->log2_chroma_w : 0; + y_shift = i ? desc->log2_chroma_h : 0; + + if (padtop || padleft) { + memset(dst->data[i], color[i], + dst->linesize[i] * (padtop >> y_shift) + (padleft >> x_shift)); + } + + if (padleft || padright) { + optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + + (dst->linesize[i] - (padright >> x_shift)); + yheight = (height - 1 - (padtop + padbottom)) >> y_shift; + for (y = 0; y < yheight; y++) { + memset(optr, color[i], (padleft + padright) >> x_shift); + optr += dst->linesize[i]; + } + } + + if (src) { /* first line */ + uint8_t *iptr = src->data[i]; + optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + + (padleft >> x_shift); + memcpy(optr, iptr, (width - padleft - padright) >> x_shift); + iptr += src->linesize[i]; + optr = dst->data[i] + dst->linesize[i] * (padtop >> y_shift) + + (dst->linesize[i] - (padright >> x_shift)); + yheight = (height - 1 - (padtop + padbottom)) >> y_shift; + for (y = 0; y < yheight; y++) { + memset(optr, color[i], (padleft + padright) >> x_shift); + memcpy(optr + ((padleft + padright) >> x_shift), iptr, + (width - padleft - padright) >> x_shift); + iptr += src->linesize[i]; + optr += dst->linesize[i]; + } + } + + if (padbottom || padright) { + optr = dst->data[i] + dst->linesize[i] * + ((height - padbottom) >> y_shift) - (padright >> x_shift); + memset(optr, color[i],dst->linesize[i] * + (padbottom >> y_shift) + (padright >> x_shift)); + } + } + return 0; +} + +#if FF_API_DEINTERLACE + +#if !HAVE_MMX_EXTERNAL +/* filter parameters: [-1 4 2 4 -1] // 8 */ +static void deinterlace_line_c(uint8_t *dst, + const uint8_t *lum_m4, const uint8_t *lum_m3, + const uint8_t *lum_m2, const uint8_t *lum_m1, + const uint8_t *lum, + int size) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int sum; + + for(;size > 0;size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + sum += lum_m1[0] << 2; + sum += -lum[0]; + dst[0] = cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + dst++; + } +} + +static void deinterlace_line_inplace_c(uint8_t *lum_m4, uint8_t *lum_m3, + uint8_t *lum_m2, uint8_t *lum_m1, + uint8_t *lum, int size) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int sum; + + for(;size > 0;size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + lum_m4[0]=lum_m2[0]; + sum += lum_m1[0] << 2; + sum += -lum[0]; + lum_m2[0] = cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + } +} +#endif /* !HAVE_MMX_EXTERNAL */ + +/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The + top field is copied as is, but the bottom field is deinterlaced + against the top field. */ +static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap, + const uint8_t *src1, int src_wrap, + int width, int height) +{ + const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2; + int y; + + src_m2 = src1; + src_m1 = src1; + src_0=&src_m1[src_wrap]; + src_p1=&src_0[src_wrap]; + src_p2=&src_p1[src_wrap]; + for(y=0;y<(height-2);y+=2) { + memcpy(dst,src_m1,width); + dst += dst_wrap; + deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width); + src_m2 = src_0; + src_m1 = src_p1; + src_0 = src_p2; + src_p1 += 2*src_wrap; + src_p2 += 2*src_wrap; + dst += dst_wrap; + } + memcpy(dst,src_m1,width); + dst += dst_wrap; + /* do last line */ + deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width); +} + +static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, + int width, int height) +{ + uint8_t *src_m1, *src_0, *src_p1, *src_p2; + int y; + uint8_t *buf; + buf = av_malloc(width); + + src_m1 = src1; + memcpy(buf,src_m1,width); + src_0=&src_m1[src_wrap]; + src_p1=&src_0[src_wrap]; + src_p2=&src_p1[src_wrap]; + for(y=0;y<(height-2);y+=2) { + deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width); + src_m1 = src_p1; + src_0 = src_p2; + src_p1 += 2*src_wrap; + src_p2 += 2*src_wrap; + } + /* do last line */ + deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width); + av_free(buf); +} + +int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + enum AVPixelFormat pix_fmt, int width, int height) +{ + int i; + + if (pix_fmt != AV_PIX_FMT_YUV420P && + pix_fmt != AV_PIX_FMT_YUVJ420P && + pix_fmt != AV_PIX_FMT_YUV422P && + pix_fmt != AV_PIX_FMT_YUVJ422P && + pix_fmt != AV_PIX_FMT_YUV444P && + pix_fmt != AV_PIX_FMT_YUV411P && + pix_fmt != AV_PIX_FMT_GRAY8) + return -1; + if ((width & 3) != 0 || (height & 3) != 0) + return -1; + + for(i=0;i<3;i++) { + if (i == 1) { + switch(pix_fmt) { + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P: + width >>= 1; + height >>= 1; + break; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUVJ422P: + width >>= 1; + break; + case AV_PIX_FMT_YUV411P: + width >>= 2; + break; + default: + break; + } + if (pix_fmt == AV_PIX_FMT_GRAY8) { + break; + } + } + if (src == dst) { + deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], + width, height); + } else { + deinterlace_bottom_field(dst->data[i],dst->linesize[i], + src->data[i], src->linesize[i], + width, height); + } + } + emms_c(); + return 0; +} + +#endif /* FF_API_DEINTERLACE */ + +#ifdef TEST + +int main(void){ + int i; + int err=0; + int skip = 0; + + for (i=0; iname) { + skip ++; + continue; + } + if (skip) { + av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); + skip = 0; + } + av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d colortype:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc), get_color_type(desc)); + if ((!(desc->flags & PIX_FMT_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { + av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); + err = 1; + } + } + return err; +} + +#endif diff --git a/ffmpeg/libavcodec/imgconvert.h b/ffmpeg/libavcodec/imgconvert.h new file mode 100644 index 0000000..df8cee7 --- /dev/null +++ b/ffmpeg/libavcodec/imgconvert.h @@ -0,0 +1,29 @@ +/* + * 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 + */ + +#ifndef AVCODEC_IMGCONVERT_H +#define AVCODEC_IMGCONVERT_H + +#include + +/* 1/2^n downscaling functions */ +void ff_shrink22(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); +void ff_shrink44(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); +void ff_shrink88(uint8_t *dst, int dst_wrap, const uint8_t *src, int src_wrap, int width, int height); + +#endif /* AVCODEC_IMGCONVERT_H */ diff --git a/ffmpeg/libavcodec/imx_dump_header_bsf.c b/ffmpeg/libavcodec/imx_dump_header_bsf.c new file mode 100644 index 0000000..9f276bc --- /dev/null +++ b/ffmpeg/libavcodec/imx_dump_header_bsf.c @@ -0,0 +1,59 @@ +/* + * imx dump header bitstream filter + * Copyright (c) 2007 Baptiste Coudurier + * + * 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 + */ + +/** + * @file + * imx dump header bitstream filter + * modifies bitstream to fit in mov and be decoded by final cut pro decoder + */ + +#include "avcodec.h" +#include "bytestream.h" + + +static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe) +{ + /* MXF essence element key */ + static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 }; + uint8_t *poutbufp; + + if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO) { + av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n"); + return 0; + } + + *poutbuf = av_malloc(buf_size + 20 + FF_INPUT_BUFFER_PADDING_SIZE); + poutbufp = *poutbuf; + bytestream_put_buffer(&poutbufp, imx_header, 16); + bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */ + bytestream_put_be24(&poutbufp, buf_size); + bytestream_put_buffer(&poutbufp, buf, buf_size); + *poutbuf_size = poutbufp - *poutbuf; + return 1; +} + +AVBitStreamFilter ff_imx_dump_header_bsf = { + "imxdump", + 0, + imx_dump_header, +}; diff --git a/ffmpeg/libavcodec/indeo2.c b/ffmpeg/libavcodec/indeo2.c new file mode 100644 index 0000000..f8e7415 --- /dev/null +++ b/ffmpeg/libavcodec/indeo2.c @@ -0,0 +1,258 @@ +/* + * Intel Indeo 2 codec + * Copyright (c) 2005 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Intel Indeo 2 decoder. + */ + +#define BITSTREAM_READER_LE +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "get_bits.h" +#include "indeo2data.h" +#include "internal.h" +#include "mathops.h" + +typedef struct Ir2Context{ + AVCodecContext *avctx; + AVFrame picture; + GetBitContext gb; + int decode_delta; +} Ir2Context; + +#define CODE_VLC_BITS 14 +static VLC ir2_vlc; + +/* Indeo 2 codes are in range 0x01..0x7F and 0x81..0x90 */ +static inline int ir2_get_code(GetBitContext *gb) +{ + return get_vlc2(gb, ir2_vlc.table, CODE_VLC_BITS, 1) + 1; +} + +static int ir2_decode_plane(Ir2Context *ctx, int width, int height, uint8_t *dst, + int stride, const uint8_t *table) +{ + int i; + int j; + int out = 0; + int c; + int t; + + if (width & 1) + return AVERROR_INVALIDDATA; + + /* first line contain absolute values, other lines contain deltas */ + while (out < width) { + c = ir2_get_code(&ctx->gb); + if (c >= 0x80) { /* we have a run */ + c -= 0x7F; + if (out + c*2 > width) + return AVERROR_INVALIDDATA; + for (i = 0; i < c * 2; i++) + dst[out++] = 0x80; + } else { /* copy two values from table */ + dst[out++] = table[c * 2]; + dst[out++] = table[(c * 2) + 1]; + } + } + dst += stride; + + for (j = 1; j < height; j++) { + out = 0; + while (out < width) { + c = ir2_get_code(&ctx->gb); + if (c >= 0x80) { /* we have a skip */ + c -= 0x7F; + if (out + c*2 > width) + return AVERROR_INVALIDDATA; + for (i = 0; i < c * 2; i++) { + dst[out] = dst[out - stride]; + out++; + } + } else { /* add two deltas from table */ + t = dst[out - stride] + (table[c * 2] - 128); + t = av_clip_uint8(t); + dst[out] = t; + out++; + t = dst[out - stride] + (table[(c * 2) + 1] - 128); + t = av_clip_uint8(t); + dst[out] = t; + out++; + } + } + dst += stride; + } + return 0; +} + +static int ir2_decode_plane_inter(Ir2Context *ctx, int width, int height, uint8_t *dst, + int stride, const uint8_t *table) +{ + int j; + int out = 0; + int c; + int t; + + if (width & 1) + return AVERROR_INVALIDDATA; + + for (j = 0; j < height; j++) { + out = 0; + while (out < width) { + c = ir2_get_code(&ctx->gb); + if (c >= 0x80) { /* we have a skip */ + c -= 0x7F; + out += c * 2; + } else { /* add two deltas from table */ + t = dst[out] + (((table[c * 2] - 128)*3) >> 2); + t = av_clip_uint8(t); + dst[out] = t; + out++; + t = dst[out] + (((table[(c * 2) + 1] - 128)*3) >> 2); + t = av_clip_uint8(t); + dst[out] = t; + out++; + } + } + dst += stride; + } + return 0; +} + +static int ir2_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + Ir2Context * const s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *picture = data; + AVFrame * const p = &s->picture; + int start, ret; + + if ((ret = ff_reget_buffer(avctx, p)) < 0) + return ret; + + start = 48; /* hardcoded for now */ + + if (start >= buf_size) { + av_log(s->avctx, AV_LOG_ERROR, "input buffer size too small (%d)\n", buf_size); + return AVERROR_INVALIDDATA; + } + + s->decode_delta = buf[18]; + + /* decide whether frame uses deltas or not */ +#ifndef BITSTREAM_READER_LE + for (i = 0; i < buf_size; i++) + buf[i] = ff_reverse[buf[i]]; +#endif + + init_get_bits(&s->gb, buf + start, (buf_size - start) * 8); + + if (s->decode_delta) { /* intraframe */ + if ((ret = ir2_decode_plane(s, avctx->width, avctx->height, + s->picture.data[0], s->picture.linesize[0], + ir2_luma_table)) < 0) + return ret; + + /* swapped U and V */ + if ((ret = ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2, + s->picture.data[2], s->picture.linesize[2], + ir2_luma_table)) < 0) + return ret; + if ((ret = ir2_decode_plane(s, avctx->width >> 2, avctx->height >> 2, + s->picture.data[1], s->picture.linesize[1], + ir2_luma_table)) < 0) + return ret; + } else { /* interframe */ + if ((ret = ir2_decode_plane_inter(s, avctx->width, avctx->height, + s->picture.data[0], s->picture.linesize[0], + ir2_luma_table)) < 0) + return ret; + /* swapped U and V */ + if ((ret = ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2, + s->picture.data[2], s->picture.linesize[2], + ir2_luma_table)) < 0) + return ret; + if ((ret = ir2_decode_plane_inter(s, avctx->width >> 2, avctx->height >> 2, + s->picture.data[1], s->picture.linesize[1], + ir2_luma_table)) < 0) + return ret; + } + + if ((ret = av_frame_ref(picture, &s->picture)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int ir2_decode_init(AVCodecContext *avctx) +{ + Ir2Context * const ic = avctx->priv_data; + static VLC_TYPE vlc_tables[1 << CODE_VLC_BITS][2]; + + avcodec_get_frame_defaults(&ic->picture); + ic->avctx = avctx; + + avctx->pix_fmt= AV_PIX_FMT_YUV410P; + + avcodec_get_frame_defaults(&ic->picture); + + ir2_vlc.table = vlc_tables; + ir2_vlc.table_allocated = 1 << CODE_VLC_BITS; +#ifdef BITSTREAM_READER_LE + init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES, + &ir2_codes[0][1], 4, 2, + &ir2_codes[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); +#else + init_vlc(&ir2_vlc, CODE_VLC_BITS, IR2_CODES, + &ir2_codes[0][1], 4, 2, + &ir2_codes[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); +#endif + + return 0; +} + +static av_cold int ir2_decode_end(AVCodecContext *avctx) +{ + Ir2Context * const ic = avctx->priv_data; + AVFrame *pic = &ic->picture; + + av_frame_unref(pic); + + return 0; +} + +AVCodec ff_indeo2_decoder = { + .name = "indeo2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_INDEO2, + .priv_data_size = sizeof(Ir2Context), + .init = ir2_decode_init, + .close = ir2_decode_end, + .decode = ir2_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 2"), +}; diff --git a/ffmpeg/libavcodec/indeo2data.h b/ffmpeg/libavcodec/indeo2data.h new file mode 100644 index 0000000..0d6d82f --- /dev/null +++ b/ffmpeg/libavcodec/indeo2data.h @@ -0,0 +1,141 @@ +/* + * Intel Indeo 2 codec + * copyright (c) 2005 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_INDEO2DATA_H +#define AVCODEC_INDEO2DATA_H + +#include + +#define IR2_CODES 143 +static const uint16_t ir2_codes[IR2_CODES][2] = { +#ifdef BITSTREAM_READER_LE +{0x0000, 3}, {0x0004, 3}, {0x0006, 3}, {0x0001, 5}, +{0x0009, 5}, {0x0019, 5}, {0x000D, 5}, {0x001D, 5}, +{0x0023, 6}, {0x0013, 6}, {0x0033, 6}, {0x000B, 6}, +{0x002B, 6}, {0x001B, 6}, {0x0007, 8}, {0x0087, 8}, +{0x0027, 8}, {0x00A7, 8}, {0x0067, 8}, {0x00E7, 8}, +{0x0097, 8}, {0x0057, 8}, {0x0037, 8}, {0x00B7, 8}, +{0x00F7, 8}, {0x000F, 9}, {0x008F, 9}, {0x018F, 9}, +{0x014F, 9}, {0x00CF, 9}, {0x002F, 9}, {0x012F, 9}, +{0x01AF, 9}, {0x006F, 9}, {0x00EF, 9}, {0x01EF, 9}, +{0x001F, 10}, {0x021F, 10}, {0x011F, 10}, {0x031F, 10}, +{0x009F, 10}, {0x029F, 10}, {0x019F, 10}, {0x039F, 10}, +{0x005F, 10}, {0x025F, 10}, {0x015F, 10}, {0x035F, 10}, +{0x00DF, 10}, {0x02DF, 10}, {0x01DF, 10}, {0x03DF, 10}, +{0x003F, 13}, {0x103F, 13}, {0x083F, 13}, {0x183F, 13}, +{0x043F, 13}, {0x143F, 13}, {0x0C3F, 13}, {0x1C3F, 13}, +{0x023F, 13}, {0x123F, 13}, {0x0A3F, 13}, {0x1A3F, 13}, +{0x063F, 13}, {0x163F, 13}, {0x0E3F, 13}, {0x1E3F, 13}, +{0x013F, 13}, {0x113F, 13}, {0x093F, 13}, {0x193F, 13}, +{0x053F, 13}, {0x153F, 13}, {0x0D3F, 13}, {0x1D3F, 13}, +{0x033F, 13}, {0x133F, 13}, {0x0B3F, 13}, {0x1B3F, 13}, +{0x073F, 13}, {0x173F, 13}, {0x0F3F, 13}, {0x1F3F, 13}, +{0x00BF, 13}, {0x10BF, 13}, {0x08BF, 13}, {0x18BF, 13}, +{0x04BF, 13}, {0x14BF, 13}, {0x0CBF, 13}, {0x1CBF, 13}, +{0x02BF, 13}, {0x12BF, 13}, {0x0ABF, 13}, {0x1ABF, 13}, +{0x06BF, 13}, {0x16BF, 13}, {0x0EBF, 13}, {0x1EBF, 13}, +{0x01BF, 13}, {0x11BF, 13}, {0x09BF, 13}, {0x19BF, 13}, +{0x05BF, 13}, {0x15BF, 13}, {0x0DBF, 13}, {0x1DBF, 13}, +{0x03BF, 13}, {0x13BF, 13}, {0x0BBF, 13}, {0x1BBF, 13}, +{0x07BF, 13}, {0x17BF, 13}, {0x0FBF, 13}, {0x1FBF, 13}, +{0x007F, 14}, {0x207F, 14}, {0x107F, 14}, {0x307F, 14}, +{0x087F, 14}, {0x287F, 14}, {0x187F, 14}, {0x387F, 14}, +{0x047F, 14}, {0x247F, 14}, {0x147F, 14}, {0x0002, 3}, +{0x0011, 5}, {0x0005, 5}, {0x0015, 5}, {0x0003, 6}, +{0x003B, 6}, {0x0047, 8}, {0x00C7, 8}, {0x0017, 8}, +{0x00D7, 8}, {0x0077, 8}, {0x010F, 9}, {0x004F, 9}, +{0x01CF, 9}, {0x00AF, 9}, {0x016F, 9}, +#else + {0x0000, 3}, {0x0001, 3}, {0x0003, 3}, {0x0010, 5}, + {0x0012, 5}, {0x0013, 5}, {0x0016, 5}, {0x0017, 5}, + {0x0031, 6}, {0x0032, 6}, {0x0033, 6}, {0x0034, 6}, + {0x0035, 6}, {0x0036, 6}, {0x00E0, 8}, {0x00E1, 8}, + {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, {0x00E7, 8}, + {0x00E9, 8}, {0x00EA, 8}, {0x00EC, 8}, {0x00ED, 8}, + {0x00EF, 8}, {0x01E0, 9}, {0x01E2, 9}, {0x01E3, 9}, + {0x01E5, 9}, {0x01E6, 9}, {0x01E8, 9}, {0x01E9, 9}, + {0x01EB, 9}, {0x01EC, 9}, {0x01EE, 9}, {0x01EF, 9}, + {0x03E0, 10}, {0x03E1, 10}, {0x03E2, 10}, {0x03E3, 10}, + {0x03E4, 10}, {0x03E5, 10}, {0x03E6, 10}, {0x03E7, 10}, + {0x03E8, 10}, {0x03E9, 10}, {0x03EA, 10}, {0x03EB, 10}, + {0x03EC, 10}, {0x03ED, 10}, {0x03EE, 10}, {0x03EF, 10}, + {0x1F80, 13}, {0x1F81, 13}, {0x1F82, 13}, {0x1F83, 13}, + {0x1F84, 13}, {0x1F85, 13}, {0x1F86, 13}, {0x1F87, 13}, + {0x1F88, 13}, {0x1F89, 13}, {0x1F8A, 13}, {0x1F8B, 13}, + {0x1F8C, 13}, {0x1F8D, 13}, {0x1F8E, 13}, {0x1F8F, 13}, + {0x1F90, 13}, {0x1F91, 13}, {0x1F92, 13}, {0x1F93, 13}, + {0x1F94, 13}, {0x1F95, 13}, {0x1F96, 13}, {0x1F97, 13}, + {0x1F98, 13}, {0x1F99, 13}, {0x1F9A, 13}, {0x1F9B, 13}, + {0x1F9C, 13}, {0x1F9D, 13}, {0x1F9E, 13}, {0x1F9F, 13}, + {0x1FA0, 13}, {0x1FA1, 13}, {0x1FA2, 13}, {0x1FA3, 13}, + {0x1FA4, 13}, {0x1FA5, 13}, {0x1FA6, 13}, {0x1FA7, 13}, + {0x1FA8, 13}, {0x1FA9, 13}, {0x1FAA, 13}, {0x1FAB, 13}, + {0x1FAC, 13}, {0x1FAD, 13}, {0x1FAE, 13}, {0x1FAF, 13}, + {0x1FB0, 13}, {0x1FB1, 13}, {0x1FB2, 13}, {0x1FB3, 13}, + {0x1FB4, 13}, {0x1FB5, 13}, {0x1FB6, 13}, {0x1FB7, 13}, + {0x1FB8, 13}, {0x1FB9, 13}, {0x1FBA, 13}, {0x1FBB, 13}, + {0x1FBC, 13}, {0x1FBD, 13}, {0x1FBE, 13}, {0x1FBF, 13}, + {0x3F80, 14}, {0x3F81, 14}, {0x3F82, 14}, {0x3F83, 14}, + {0x3F84, 14}, {0x3F85, 14}, {0x3F86, 14}, {0x3F87, 14}, + {0x3F88, 14}, {0x3F89, 14}, {0x3F8A, 14}, {0x0002, 3}, + {0x0011, 5}, {0x0014, 5}, {0x0015, 5}, {0x0030, 6}, + {0x0037, 6}, {0x00E2, 8}, {0x00E3, 8}, {0x00E8, 8}, + {0x00EB, 8}, {0x00EE, 8}, {0x01E1, 9}, {0x01E4, 9}, + {0x01E7, 9}, {0x01EA, 9}, {0x01ED, 9} +#endif +}; + +static const uint8_t ir2_luma_table[256] = { + 0x80, 0x80, 0x84, 0x84, 0x7C, 0x7C, 0x7F, 0x85, + 0x81, 0x7B, 0x85, 0x7F, 0x7B, 0x81, 0x8C, 0x8C, + 0x74, 0x74, 0x83, 0x8D, 0x7D, 0x73, 0x8D, 0x83, + 0x73, 0x7D, 0x77, 0x89, 0x89, 0x77, 0x89, 0x77, + 0x77, 0x89, 0x8C, 0x95, 0x74, 0x6B, 0x95, 0x8C, + 0x6B, 0x74, 0x7C, 0x90, 0x84, 0x70, 0x90, 0x7C, + 0x70, 0x84, 0x96, 0x96, 0x6A, 0x6A, 0x82, 0x98, + 0x7E, 0x68, 0x98, 0x82, 0x68, 0x7E, 0x97, 0xA2, + 0x69, 0x5E, 0xA2, 0x97, 0x5E, 0x69, 0xA2, 0xA2, + 0x5E, 0x5E, 0x8B, 0xA3, 0x75, 0x5D, 0xA3, 0x8B, + 0x5D, 0x75, 0x71, 0x95, 0x8F, 0x6B, 0x95, 0x71, + 0x6B, 0x8F, 0x78, 0x9D, 0x88, 0x63, 0x9D, 0x78, + 0x63, 0x88, 0x7F, 0xA7, 0x81, 0x59, 0xA7, 0x7F, + 0x59, 0x81, 0xA4, 0xB1, 0x5C, 0x4F, 0xB1, 0xA4, + 0x4F, 0x5C, 0x96, 0xB1, 0x6A, 0x4F, 0xB1, 0x96, + 0x4F, 0x6A, 0xB2, 0xB2, 0x4E, 0x4E, 0x65, 0x9B, + 0x9B, 0x65, 0x9B, 0x65, 0x65, 0x9B, 0x89, 0xB4, + 0x77, 0x4C, 0xB4, 0x89, 0x4C, 0x77, 0x6A, 0xA3, + 0x96, 0x5D, 0xA3, 0x6A, 0x5D, 0x96, 0x73, 0xAC, + 0x8D, 0x54, 0xAC, 0x73, 0x54, 0x8D, 0xB4, 0xC3, + 0x4C, 0x3D, 0xC3, 0xB4, 0x3D, 0x4C, 0xA4, 0xC3, + 0x5C, 0x3D, 0xC3, 0xA4, 0x3D, 0x5C, 0xC4, 0xC4, + 0x3C, 0x3C, 0x96, 0xC6, 0x6A, 0x3A, 0xC6, 0x96, + 0x3A, 0x6A, 0x7C, 0xBA, 0x84, 0x46, 0xBA, 0x7C, + 0x46, 0x84, 0x5B, 0xAB, 0xA5, 0x55, 0xAB, 0x5B, + 0x55, 0xA5, 0x63, 0xB4, 0x9D, 0x4C, 0xB4, 0x63, + 0x4C, 0x9D, 0x86, 0xCA, 0x7A, 0x36, 0xCA, 0x86, + 0x36, 0x7A, 0xB6, 0xD7, 0x4A, 0x29, 0xD7, 0xB6, + 0x29, 0x4A, 0xC8, 0xD7, 0x38, 0x29, 0xD7, 0xC8, + 0x29, 0x38, 0xA4, 0xD8, 0x5C, 0x28, 0xD8, 0xA4, + 0x28, 0x5C, 0x6C, 0xC1, 0x94, 0x3F, 0xC1, 0x6C, + 0x3F, 0x94, 0xD9, 0xD9, 0x27, 0x27, 0x80, 0x80 +}; + +#endif /* AVCODEC_INDEO2DATA_H */ diff --git a/ffmpeg/libavcodec/indeo3.c b/ffmpeg/libavcodec/indeo3.c new file mode 100644 index 0000000..a8b6e64 --- /dev/null +++ b/ffmpeg/libavcodec/indeo3.c @@ -0,0 +1,1138 @@ +/* + * Indeo Video v3 compatible decoder + * Copyright (c) 2009 - 2011 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * This is a decoder for Intel Indeo Video v3. + * It is based on vector quantization, run-length coding and motion compensation. + * Known container formats: .avi and .mov + * Known FOURCCs: 'IV31', 'IV32' + * + * @see http://wiki.multimedia.cx/index.php?title=Indeo_3 + */ + +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "copy_block.h" +#include "bytestream.h" +#include "get_bits.h" +#include "hpeldsp.h" +#include "internal.h" + +#include "indeo3data.h" + +/* RLE opcodes. */ +enum { + RLE_ESC_F9 = 249, ///< same as RLE_ESC_FA + do the same with next block + RLE_ESC_FA = 250, ///< INTRA: skip block, INTER: copy data from reference + RLE_ESC_FB = 251, ///< apply null delta to N blocks / skip N blocks + RLE_ESC_FC = 252, ///< same as RLE_ESC_FD + do the same with next block + RLE_ESC_FD = 253, ///< apply null delta to all remaining lines of this block + RLE_ESC_FE = 254, ///< apply null delta to all lines up to the 3rd line + RLE_ESC_FF = 255 ///< apply null delta to all lines up to the 2nd line +}; + + +/* Some constants for parsing frame bitstream flags. */ +#define BS_8BIT_PEL (1 << 1) ///< 8bit pixel bitdepth indicator +#define BS_KEYFRAME (1 << 2) ///< intra frame indicator +#define BS_MV_Y_HALF (1 << 4) ///< vertical mv halfpel resolution indicator +#define BS_MV_X_HALF (1 << 5) ///< horizontal mv halfpel resolution indicator +#define BS_NONREF (1 << 8) ///< nonref (discardable) frame indicator +#define BS_BUFFER 9 ///< indicates which of two frame buffers should be used + + +typedef struct Plane { + uint8_t *buffers[2]; + uint8_t *pixels[2]; ///< pointer to the actual pixel data of the buffers above + uint32_t width; + uint32_t height; + uint32_t pitch; +} Plane; + +#define CELL_STACK_MAX 20 + +typedef struct Cell { + int16_t xpos; ///< cell coordinates in 4x4 blocks + int16_t ypos; + int16_t width; ///< cell width in 4x4 blocks + int16_t height; ///< cell height in 4x4 blocks + uint8_t tree; ///< tree id: 0- MC tree, 1 - VQ tree + const int8_t *mv_ptr; ///< ptr to the motion vector if any +} Cell; + +typedef struct Indeo3DecodeContext { + AVCodecContext *avctx; + HpelDSPContext hdsp; + + GetBitContext gb; + int need_resync; + int skip_bits; + const uint8_t *next_cell_data; + const uint8_t *last_byte; + const int8_t *mc_vectors; + unsigned num_vectors; ///< number of motion vectors in mc_vectors + + int16_t width, height; + uint32_t frame_num; ///< current frame number (zero-based) + uint32_t data_size; ///< size of the frame data in bytes + uint16_t frame_flags; ///< frame properties + uint8_t cb_offset; ///< needed for selecting VQ tables + uint8_t buf_sel; ///< active frame buffer: 0 - primary, 1 -secondary + const uint8_t *y_data_ptr; + const uint8_t *v_data_ptr; + const uint8_t *u_data_ptr; + int32_t y_data_size; + int32_t v_data_size; + int32_t u_data_size; + const uint8_t *alt_quant; ///< secondary VQ table set for the modes 1 and 4 + Plane planes[3]; +} Indeo3DecodeContext; + + +static uint8_t requant_tab[8][128]; + +/* + * Build the static requantization table. + * This table is used to remap pixel values according to a specific + * quant index and thus avoid overflows while adding deltas. + */ +static av_cold void build_requant_tab(void) +{ + static int8_t offsets[8] = { 1, 1, 2, -3, -3, 3, 4, 4 }; + static int8_t deltas [8] = { 0, 1, 0, 4, 4, 1, 0, 1 }; + + int i, j, step; + + for (i = 0; i < 8; i++) { + step = i + 2; + for (j = 0; j < 128; j++) + requant_tab[i][j] = (j + offsets[i]) / step * step + deltas[i]; + } + + /* some last elements calculated above will have values >= 128 */ + /* pixel values shall never exceed 127 so set them to non-overflowing values */ + /* according with the quantization step of the respective section */ + requant_tab[0][127] = 126; + requant_tab[1][119] = 118; + requant_tab[1][120] = 118; + requant_tab[2][126] = 124; + requant_tab[2][127] = 124; + requant_tab[6][124] = 120; + requant_tab[6][125] = 120; + requant_tab[6][126] = 120; + requant_tab[6][127] = 120; + + /* Patch for compatibility with the Intel's binary decoders */ + requant_tab[1][7] = 10; + requant_tab[4][8] = 10; +} + + +static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx, + AVCodecContext *avctx, int luma_width, int luma_height) +{ + int p, chroma_width, chroma_height; + int luma_pitch, chroma_pitch, luma_size, chroma_size; + + if (luma_width < 16 || luma_width > 640 || + luma_height < 16 || luma_height > 480 || + luma_width & 3 || luma_height & 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid picture dimensions: %d x %d!\n", + luma_width, luma_height); + return AVERROR_INVALIDDATA; + } + + ctx->width = luma_width ; + ctx->height = luma_height; + + chroma_width = FFALIGN(luma_width >> 2, 4); + chroma_height = FFALIGN(luma_height >> 2, 4); + + luma_pitch = FFALIGN(luma_width, 16); + chroma_pitch = FFALIGN(chroma_width, 16); + + /* Calculate size of the luminance plane. */ + /* Add one line more for INTRA prediction. */ + luma_size = luma_pitch * (luma_height + 1); + + /* Calculate size of a chrominance planes. */ + /* Add one line more for INTRA prediction. */ + chroma_size = chroma_pitch * (chroma_height + 1); + + /* allocate frame buffers */ + for (p = 0; p < 3; p++) { + ctx->planes[p].pitch = !p ? luma_pitch : chroma_pitch; + ctx->planes[p].width = !p ? luma_width : chroma_width; + ctx->planes[p].height = !p ? luma_height : chroma_height; + + ctx->planes[p].buffers[0] = av_malloc(!p ? luma_size : chroma_size); + ctx->planes[p].buffers[1] = av_malloc(!p ? luma_size : chroma_size); + + /* fill the INTRA prediction lines with the middle pixel value = 64 */ + memset(ctx->planes[p].buffers[0], 0x40, ctx->planes[p].pitch); + memset(ctx->planes[p].buffers[1], 0x40, ctx->planes[p].pitch); + + /* set buffer pointers = buf_ptr + pitch and thus skip the INTRA prediction line */ + ctx->planes[p].pixels[0] = ctx->planes[p].buffers[0] + ctx->planes[p].pitch; + ctx->planes[p].pixels[1] = ctx->planes[p].buffers[1] + ctx->planes[p].pitch; + memset(ctx->planes[p].pixels[0], 0, ctx->planes[p].pitch * ctx->planes[p].height); + memset(ctx->planes[p].pixels[1], 0, ctx->planes[p].pitch * ctx->planes[p].height); + } + + return 0; +} + + +static av_cold void free_frame_buffers(Indeo3DecodeContext *ctx) +{ + int p; + + ctx->width= + ctx->height= 0; + + for (p = 0; p < 3; p++) { + av_freep(&ctx->planes[p].buffers[0]); + av_freep(&ctx->planes[p].buffers[1]); + ctx->planes[p].pixels[0] = ctx->planes[p].pixels[1] = 0; + } +} + + +/** + * Copy pixels of the cell(x + mv_x, y + mv_y) from the previous frame into + * the cell(x, y) in the current frame. + * + * @param ctx pointer to the decoder context + * @param plane pointer to the plane descriptor + * @param cell pointer to the cell descriptor + */ +static void copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) +{ + int h, w, mv_x, mv_y, offset, offset_dst; + uint8_t *src, *dst; + + /* setup output and reference pointers */ + offset_dst = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2); + dst = plane->pixels[ctx->buf_sel] + offset_dst; + if(cell->mv_ptr){ + mv_y = cell->mv_ptr[0]; + mv_x = cell->mv_ptr[1]; + }else + mv_x= mv_y= 0; + offset = offset_dst + mv_y * plane->pitch + mv_x; + src = plane->pixels[ctx->buf_sel ^ 1] + offset; + + h = cell->height << 2; + + for (w = cell->width; w > 0;) { + /* copy using 16xH blocks */ + if (!((cell->xpos << 2) & 15) && w >= 4) { + for (; w >= 4; src += 16, dst += 16, w -= 4) + ctx->hdsp.put_no_rnd_pixels_tab[0][0](dst, src, plane->pitch, h); + } + + /* copy using 8xH blocks */ + if (!((cell->xpos << 2) & 7) && w >= 2) { + ctx->hdsp.put_no_rnd_pixels_tab[1][0](dst, src, plane->pitch, h); + w -= 2; + src += 8; + dst += 8; + } + + if (w >= 1) { + copy_block4(dst, src, plane->pitch, plane->pitch, h); + w--; + src += 4; + dst += 4; + } + } +} + + +/* Average 4/8 pixels at once without rounding using SWAR */ +#define AVG_32(dst, src, ref) \ + AV_WN32A(dst, ((AV_RN32A(src) + AV_RN32A(ref)) >> 1) & 0x7F7F7F7FUL) + +#define AVG_64(dst, src, ref) \ + AV_WN64A(dst, ((AV_RN64A(src) + AV_RN64A(ref)) >> 1) & 0x7F7F7F7F7F7F7F7FULL) + + +/* + * Replicate each even pixel as follows: + * ABCDEFGH -> AACCEEGG + */ +static inline uint64_t replicate64(uint64_t a) { +#if HAVE_BIGENDIAN + a &= 0xFF00FF00FF00FF00ULL; + a |= a >> 8; +#else + a &= 0x00FF00FF00FF00FFULL; + a |= a << 8; +#endif + return a; +} + +static inline uint32_t replicate32(uint32_t a) { +#if HAVE_BIGENDIAN + a &= 0xFF00FF00UL; + a |= a >> 8; +#else + a &= 0x00FF00FFUL; + a |= a << 8; +#endif + return a; +} + + +/* Fill n lines with 64bit pixel value pix */ +static inline void fill_64(uint8_t *dst, const uint64_t pix, int32_t n, + int32_t row_offset) +{ + for (; n > 0; dst += row_offset, n--) + AV_WN64A(dst, pix); +} + + +/* Error codes for cell decoding. */ +enum { + IV3_NOERR = 0, + IV3_BAD_RLE = 1, + IV3_BAD_DATA = 2, + IV3_BAD_COUNTER = 3, + IV3_UNSUPPORTED = 4, + IV3_OUT_OF_DATA = 5 +}; + + +#define BUFFER_PRECHECK \ +if (*data_ptr >= last_ptr) \ + return IV3_OUT_OF_DATA; \ + +#define RLE_BLOCK_COPY \ + if (cell->mv_ptr || !skip_flag) \ + copy_block4(dst, ref, row_offset, row_offset, 4 << v_zoom) + +#define RLE_BLOCK_COPY_8 \ + pix64 = AV_RN64A(ref);\ + if (is_first_row) {/* special prediction case: top line of a cell */\ + pix64 = replicate64(pix64);\ + fill_64(dst + row_offset, pix64, 7, row_offset);\ + AVG_64(dst, ref, dst + row_offset);\ + } else \ + fill_64(dst, pix64, 8, row_offset) + +#define RLE_LINES_COPY \ + copy_block4(dst, ref, row_offset, row_offset, num_lines << v_zoom) + +#define RLE_LINES_COPY_M10 \ + pix64 = AV_RN64A(ref);\ + if (is_top_of_cell) {\ + pix64 = replicate64(pix64);\ + fill_64(dst + row_offset, pix64, (num_lines << 1) - 1, row_offset);\ + AVG_64(dst, ref, dst + row_offset);\ + } else \ + fill_64(dst, pix64, num_lines << 1, row_offset) + +#define APPLY_DELTA_4 \ + AV_WN16A(dst + line_offset ,\ + (AV_RN16A(ref ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ + AV_WN16A(dst + line_offset + 2,\ + (AV_RN16A(ref + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ + if (mode >= 3) {\ + if (is_top_of_cell && !cell->ypos) {\ + AV_COPY32(dst, dst + row_offset);\ + } else {\ + AVG_32(dst, ref, dst + row_offset);\ + }\ + } + +#define APPLY_DELTA_8 \ + /* apply two 32-bit VQ deltas to next even line */\ + if (is_top_of_cell) { \ + AV_WN32A(dst + row_offset , \ + (replicate32(AV_RN32A(ref )) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + AV_WN32A(dst + row_offset + 4, \ + (replicate32(AV_RN32A(ref + 4)) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + } else { \ + AV_WN32A(dst + row_offset , \ + (AV_RN32A(ref ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + AV_WN32A(dst + row_offset + 4, \ + (AV_RN32A(ref + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + } \ + /* odd lines are not coded but rather interpolated/replicated */\ + /* first line of the cell on the top of image? - replicate */\ + /* otherwise - interpolate */\ + if (is_top_of_cell && !cell->ypos) {\ + AV_COPY64(dst, dst + row_offset);\ + } else \ + AVG_64(dst, ref, dst + row_offset); + + +#define APPLY_DELTA_1011_INTER \ + if (mode == 10) { \ + AV_WN32A(dst , \ + (AV_RN32A(dst ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + AV_WN32A(dst + 4 , \ + (AV_RN32A(dst + 4 ) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + AV_WN32A(dst + row_offset , \ + (AV_RN32A(dst + row_offset ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ + AV_WN32A(dst + row_offset + 4, \ + (AV_RN32A(dst + row_offset + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ + } else { \ + AV_WN16A(dst , \ + (AV_RN16A(dst ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ + AV_WN16A(dst + 2 , \ + (AV_RN16A(dst + 2 ) + delta_tab->deltas[dyad2]) & 0x7F7F);\ + AV_WN16A(dst + row_offset , \ + (AV_RN16A(dst + row_offset ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ + AV_WN16A(dst + row_offset + 2, \ + (AV_RN16A(dst + row_offset + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ + } + + +static int decode_cell_data(Indeo3DecodeContext *ctx, Cell *cell, + uint8_t *block, uint8_t *ref_block, + int pitch, int h_zoom, int v_zoom, int mode, + const vqEntry *delta[2], int swap_quads[2], + const uint8_t **data_ptr, const uint8_t *last_ptr) +{ + int x, y, line, num_lines; + int rle_blocks = 0; + uint8_t code, *dst, *ref; + const vqEntry *delta_tab; + unsigned int dyad1, dyad2; + uint64_t pix64; + int skip_flag = 0, is_top_of_cell, is_first_row = 1; + int row_offset, blk_row_offset, line_offset; + + row_offset = pitch; + blk_row_offset = (row_offset << (2 + v_zoom)) - (cell->width << 2); + line_offset = v_zoom ? row_offset : 0; + + if (cell->height & v_zoom || cell->width & h_zoom) + return IV3_BAD_DATA; + + for (y = 0; y < cell->height; is_first_row = 0, y += 1 + v_zoom) { + for (x = 0; x < cell->width; x += 1 + h_zoom) { + ref = ref_block; + dst = block; + + if (rle_blocks > 0) { + if (mode <= 4) { + RLE_BLOCK_COPY; + } else if (mode == 10 && !cell->mv_ptr) { + RLE_BLOCK_COPY_8; + } + rle_blocks--; + } else { + for (line = 0; line < 4;) { + num_lines = 1; + is_top_of_cell = is_first_row && !line; + + /* select primary VQ table for odd, secondary for even lines */ + if (mode <= 4) + delta_tab = delta[line & 1]; + else + delta_tab = delta[1]; + BUFFER_PRECHECK; + code = bytestream_get_byte(data_ptr); + if (code < 248) { + if (code < delta_tab->num_dyads) { + BUFFER_PRECHECK; + dyad1 = bytestream_get_byte(data_ptr); + dyad2 = code; + if (dyad1 >= delta_tab->num_dyads || dyad1 >= 248) + return IV3_BAD_DATA; + } else { + /* process QUADS */ + code -= delta_tab->num_dyads; + dyad1 = code / delta_tab->quad_exp; + dyad2 = code % delta_tab->quad_exp; + if (swap_quads[line & 1]) + FFSWAP(unsigned int, dyad1, dyad2); + } + if (mode <= 4) { + APPLY_DELTA_4; + } else if (mode == 10 && !cell->mv_ptr) { + APPLY_DELTA_8; + } else { + APPLY_DELTA_1011_INTER; + } + } else { + /* process RLE codes */ + switch (code) { + case RLE_ESC_FC: + skip_flag = 0; + rle_blocks = 1; + code = 253; + /* FALLTHROUGH */ + case RLE_ESC_FF: + case RLE_ESC_FE: + case RLE_ESC_FD: + num_lines = 257 - code - line; + if (num_lines <= 0) + return IV3_BAD_RLE; + if (mode <= 4) { + RLE_LINES_COPY; + } else if (mode == 10 && !cell->mv_ptr) { + RLE_LINES_COPY_M10; + } + break; + case RLE_ESC_FB: + BUFFER_PRECHECK; + code = bytestream_get_byte(data_ptr); + rle_blocks = (code & 0x1F) - 1; /* set block counter */ + if (code >= 64 || rle_blocks < 0) + return IV3_BAD_COUNTER; + skip_flag = code & 0x20; + num_lines = 4 - line; /* enforce next block processing */ + if (mode >= 10 || (cell->mv_ptr || !skip_flag)) { + if (mode <= 4) { + RLE_LINES_COPY; + } else if (mode == 10 && !cell->mv_ptr) { + RLE_LINES_COPY_M10; + } + } + break; + case RLE_ESC_F9: + skip_flag = 1; + rle_blocks = 1; + /* FALLTHROUGH */ + case RLE_ESC_FA: + if (line) + return IV3_BAD_RLE; + num_lines = 4; /* enforce next block processing */ + if (cell->mv_ptr) { + if (mode <= 4) { + RLE_LINES_COPY; + } else if (mode == 10 && !cell->mv_ptr) { + RLE_LINES_COPY_M10; + } + } + break; + default: + return IV3_UNSUPPORTED; + } + } + + line += num_lines; + ref += row_offset * (num_lines << v_zoom); + dst += row_offset * (num_lines << v_zoom); + } + } + + /* move to next horizontal block */ + block += 4 << h_zoom; + ref_block += 4 << h_zoom; + } + + /* move to next line of blocks */ + ref_block += blk_row_offset; + block += blk_row_offset; + } + return IV3_NOERR; +} + + +/** + * Decode a vector-quantized cell. + * It consists of several routines, each of which handles one or more "modes" + * with which a cell can be encoded. + * + * @param ctx pointer to the decoder context + * @param avctx ptr to the AVCodecContext + * @param plane pointer to the plane descriptor + * @param cell pointer to the cell descriptor + * @param data_ptr pointer to the compressed data + * @param last_ptr pointer to the last byte to catch reads past end of buffer + * @return number of consumed bytes or negative number in case of error + */ +static int decode_cell(Indeo3DecodeContext *ctx, AVCodecContext *avctx, + Plane *plane, Cell *cell, const uint8_t *data_ptr, + const uint8_t *last_ptr) +{ + int x, mv_x, mv_y, mode, vq_index, prim_indx, second_indx; + int zoom_fac; + int offset, error = 0, swap_quads[2]; + uint8_t code, *block, *ref_block = 0; + const vqEntry *delta[2]; + const uint8_t *data_start = data_ptr; + + /* get coding mode and VQ table index from the VQ descriptor byte */ + code = *data_ptr++; + mode = code >> 4; + vq_index = code & 0xF; + + /* setup output and reference pointers */ + offset = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2); + block = plane->pixels[ctx->buf_sel] + offset; + + if (cell->mv_ptr) { + mv_y = cell->mv_ptr[0]; + mv_x = cell->mv_ptr[1]; + if ( mv_x + 4*cell->xpos < 0 + || mv_y + 4*cell->ypos < 0 + || mv_x + 4*cell->xpos + 4*cell->width > plane->width + || mv_y + 4*cell->ypos + 4*cell->height > plane->height) { + av_log(avctx, AV_LOG_ERROR, "motion vector %d %d outside reference\n", mv_x + 4*cell->xpos, mv_y + 4*cell->ypos); + return AVERROR_INVALIDDATA; + } + } + + if (!cell->mv_ptr) { + /* use previous line as reference for INTRA cells */ + ref_block = block - plane->pitch; + } else if (mode >= 10) { + /* for mode 10 and 11 INTER first copy the predicted cell into the current one */ + /* so we don't need to do data copying for each RLE code later */ + copy_cell(ctx, plane, cell); + } else { + /* set the pointer to the reference pixels for modes 0-4 INTER */ + mv_y = cell->mv_ptr[0]; + mv_x = cell->mv_ptr[1]; + offset += mv_y * plane->pitch + mv_x; + ref_block = plane->pixels[ctx->buf_sel ^ 1] + offset; + } + + /* select VQ tables as follows: */ + /* modes 0 and 3 use only the primary table for all lines in a block */ + /* while modes 1 and 4 switch between primary and secondary tables on alternate lines */ + if (mode == 1 || mode == 4) { + code = ctx->alt_quant[vq_index]; + prim_indx = (code >> 4) + ctx->cb_offset; + second_indx = (code & 0xF) + ctx->cb_offset; + } else { + vq_index += ctx->cb_offset; + prim_indx = second_indx = vq_index; + } + + if (prim_indx >= 24 || second_indx >= 24) { + av_log(avctx, AV_LOG_ERROR, "Invalid VQ table indexes! Primary: %d, secondary: %d!\n", + prim_indx, second_indx); + return AVERROR_INVALIDDATA; + } + + delta[0] = &vq_tab[second_indx]; + delta[1] = &vq_tab[prim_indx]; + swap_quads[0] = second_indx >= 16; + swap_quads[1] = prim_indx >= 16; + + /* requantize the prediction if VQ index of this cell differs from VQ index */ + /* of the predicted cell in order to avoid overflows. */ + if (vq_index >= 8 && ref_block) { + for (x = 0; x < cell->width << 2; x++) + ref_block[x] = requant_tab[vq_index & 7][ref_block[x] & 127]; + } + + error = IV3_NOERR; + + switch (mode) { + case 0: /*------------------ MODES 0 & 1 (4x4 block processing) --------------------*/ + case 1: + case 3: /*------------------ MODES 3 & 4 (4x8 block processing) --------------------*/ + case 4: + if (mode >= 3 && cell->mv_ptr) { + av_log(avctx, AV_LOG_ERROR, "Attempt to apply Mode 3/4 to an INTER cell!\n"); + return AVERROR_INVALIDDATA; + } + + zoom_fac = mode >= 3; + error = decode_cell_data(ctx, cell, block, ref_block, plane->pitch, + 0, zoom_fac, mode, delta, swap_quads, + &data_ptr, last_ptr); + break; + case 10: /*-------------------- MODE 10 (8x8 block processing) ---------------------*/ + case 11: /*----------------- MODE 11 (4x8 INTER block processing) ------------------*/ + if (mode == 10 && !cell->mv_ptr) { /* MODE 10 INTRA processing */ + error = decode_cell_data(ctx, cell, block, ref_block, plane->pitch, + 1, 1, mode, delta, swap_quads, + &data_ptr, last_ptr); + } else { /* mode 10 and 11 INTER processing */ + if (mode == 11 && !cell->mv_ptr) { + av_log(avctx, AV_LOG_ERROR, "Attempt to use Mode 11 for an INTRA cell!\n"); + return AVERROR_INVALIDDATA; + } + + zoom_fac = mode == 10; + error = decode_cell_data(ctx, cell, block, ref_block, plane->pitch, + zoom_fac, 1, mode, delta, swap_quads, + &data_ptr, last_ptr); + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported coding mode: %d\n", mode); + return AVERROR_INVALIDDATA; + }//switch mode + + switch (error) { + case IV3_BAD_RLE: + av_log(avctx, AV_LOG_ERROR, "Mode %d: RLE code %X is not allowed at the current line\n", + mode, data_ptr[-1]); + return AVERROR_INVALIDDATA; + case IV3_BAD_DATA: + av_log(avctx, AV_LOG_ERROR, "Mode %d: invalid VQ data\n", mode); + return AVERROR_INVALIDDATA; + case IV3_BAD_COUNTER: + av_log(avctx, AV_LOG_ERROR, "Mode %d: RLE-FB invalid counter: %d\n", mode, code); + return AVERROR_INVALIDDATA; + case IV3_UNSUPPORTED: + av_log(avctx, AV_LOG_ERROR, "Mode %d: unsupported RLE code: %X\n", mode, data_ptr[-1]); + return AVERROR_INVALIDDATA; + case IV3_OUT_OF_DATA: + av_log(avctx, AV_LOG_ERROR, "Mode %d: attempt to read past end of buffer\n", mode); + return AVERROR_INVALIDDATA; + } + + return data_ptr - data_start; /* report number of bytes consumed from the input buffer */ +} + + +/* Binary tree codes. */ +enum { + H_SPLIT = 0, + V_SPLIT = 1, + INTRA_NULL = 2, + INTER_DATA = 3 +}; + + +#define SPLIT_CELL(size, new_size) (new_size) = ((size) > 2) ? ((((size) + 2) >> 2) << 1) : 1 + +#define UPDATE_BITPOS(n) \ + ctx->skip_bits += (n); \ + ctx->need_resync = 1 + +#define RESYNC_BITSTREAM \ + if (ctx->need_resync && !(get_bits_count(&ctx->gb) & 7)) { \ + skip_bits_long(&ctx->gb, ctx->skip_bits); \ + ctx->skip_bits = 0; \ + ctx->need_resync = 0; \ + } + +#define CHECK_CELL \ + if (curr_cell.xpos + curr_cell.width > (plane->width >> 2) || \ + curr_cell.ypos + curr_cell.height > (plane->height >> 2)) { \ + av_log(avctx, AV_LOG_ERROR, "Invalid cell: x=%d, y=%d, w=%d, h=%d\n", \ + curr_cell.xpos, curr_cell.ypos, curr_cell.width, curr_cell.height); \ + return AVERROR_INVALIDDATA; \ + } + + +static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, + Plane *plane, int code, Cell *ref_cell, + const int depth, const int strip_width) +{ + Cell curr_cell; + int bytes_used; + int mv_x, mv_y; + + if (depth <= 0) { + av_log(avctx, AV_LOG_ERROR, "Stack overflow (corrupted binary tree)!\n"); + return AVERROR_INVALIDDATA; // unwind recursion + } + + curr_cell = *ref_cell; // clone parent cell + if (code == H_SPLIT) { + SPLIT_CELL(ref_cell->height, curr_cell.height); + ref_cell->ypos += curr_cell.height; + ref_cell->height -= curr_cell.height; + if (ref_cell->height <= 0 || curr_cell.height <= 0) + return AVERROR_INVALIDDATA; + } else if (code == V_SPLIT) { + if (curr_cell.width > strip_width) { + /* split strip */ + curr_cell.width = (curr_cell.width <= (strip_width << 1) ? 1 : 2) * strip_width; + } else + SPLIT_CELL(ref_cell->width, curr_cell.width); + ref_cell->xpos += curr_cell.width; + ref_cell->width -= curr_cell.width; + if (ref_cell->width <= 0 || curr_cell.width <= 0) + return AVERROR_INVALIDDATA; + } + + while (get_bits_left(&ctx->gb) >= 2) { /* loop until return */ + RESYNC_BITSTREAM; + switch (code = get_bits(&ctx->gb, 2)) { + case H_SPLIT: + case V_SPLIT: + if (parse_bintree(ctx, avctx, plane, code, &curr_cell, depth - 1, strip_width)) + return AVERROR_INVALIDDATA; + break; + case INTRA_NULL: + if (!curr_cell.tree) { /* MC tree INTRA code */ + curr_cell.mv_ptr = 0; /* mark the current strip as INTRA */ + curr_cell.tree = 1; /* enter the VQ tree */ + } else { /* VQ tree NULL code */ + RESYNC_BITSTREAM; + code = get_bits(&ctx->gb, 2); + if (code >= 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid VQ_NULL code: %d\n", code); + return AVERROR_INVALIDDATA; + } + if (code == 1) + av_log(avctx, AV_LOG_ERROR, "SkipCell procedure not implemented yet!\n"); + + CHECK_CELL + if (!curr_cell.mv_ptr) + return AVERROR_INVALIDDATA; + + mv_y = curr_cell.mv_ptr[0]; + mv_x = curr_cell.mv_ptr[1]; + if ( mv_x + 4*curr_cell.xpos < 0 + || mv_y + 4*curr_cell.ypos < 0 + || mv_x + 4*curr_cell.xpos + 4*curr_cell.width > plane->width + || mv_y + 4*curr_cell.ypos + 4*curr_cell.height > plane->height) { + av_log(avctx, AV_LOG_ERROR, "motion vector %d %d outside reference\n", mv_x + 4*curr_cell.xpos, mv_y + 4*curr_cell.ypos); + return AVERROR_INVALIDDATA; + } + + copy_cell(ctx, plane, &curr_cell); + return 0; + } + break; + case INTER_DATA: + if (!curr_cell.tree) { /* MC tree INTER code */ + unsigned mv_idx; + /* get motion vector index and setup the pointer to the mv set */ + if (!ctx->need_resync) + ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; + if (ctx->next_cell_data >= ctx->last_byte) { + av_log(avctx, AV_LOG_ERROR, "motion vector out of array\n"); + return AVERROR_INVALIDDATA; + } + mv_idx = *(ctx->next_cell_data++); + if (mv_idx >= ctx->num_vectors) { + av_log(avctx, AV_LOG_ERROR, "motion vector index out of range\n"); + return AVERROR_INVALIDDATA; + } + curr_cell.mv_ptr = &ctx->mc_vectors[mv_idx << 1]; + curr_cell.tree = 1; /* enter the VQ tree */ + UPDATE_BITPOS(8); + } else { /* VQ tree DATA code */ + if (!ctx->need_resync) + ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; + + CHECK_CELL + bytes_used = decode_cell(ctx, avctx, plane, &curr_cell, + ctx->next_cell_data, ctx->last_byte); + if (bytes_used < 0) + return AVERROR_INVALIDDATA; + + UPDATE_BITPOS(bytes_used << 3); + ctx->next_cell_data += bytes_used; + return 0; + } + break; + } + }//while + + return AVERROR_INVALIDDATA; +} + + +static int decode_plane(Indeo3DecodeContext *ctx, AVCodecContext *avctx, + Plane *plane, const uint8_t *data, int32_t data_size, + int32_t strip_width) +{ + Cell curr_cell; + unsigned num_vectors; + + /* each plane data starts with mc_vector_count field, */ + /* an optional array of motion vectors followed by the vq data */ + num_vectors = bytestream_get_le32(&data); data_size -= 4; + if (num_vectors > 256) { + av_log(ctx->avctx, AV_LOG_ERROR, + "Read invalid number of motion vectors %d\n", num_vectors); + return AVERROR_INVALIDDATA; + } + if (num_vectors * 2 > data_size) + return AVERROR_INVALIDDATA; + + ctx->num_vectors = num_vectors; + ctx->mc_vectors = num_vectors ? data : 0; + + /* init the bitreader */ + init_get_bits(&ctx->gb, &data[num_vectors * 2], (data_size - num_vectors * 2) << 3); + ctx->skip_bits = 0; + ctx->need_resync = 0; + + ctx->last_byte = data + data_size; + + /* initialize the 1st cell and set its dimensions to whole plane */ + curr_cell.xpos = curr_cell.ypos = 0; + curr_cell.width = plane->width >> 2; + curr_cell.height = plane->height >> 2; + curr_cell.tree = 0; // we are in the MC tree now + curr_cell.mv_ptr = 0; // no motion vector = INTRA cell + + return parse_bintree(ctx, avctx, plane, INTRA_NULL, &curr_cell, CELL_STACK_MAX, strip_width); +} + + +#define OS_HDR_ID MKBETAG('F', 'R', 'M', 'H') + +static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + const uint8_t *buf_ptr = buf, *bs_hdr; + uint32_t frame_num, word2, check_sum, data_size; + uint32_t y_offset, u_offset, v_offset, starts[3], ends[3]; + uint16_t height, width; + int i, j; + + /* parse and check the OS header */ + frame_num = bytestream_get_le32(&buf_ptr); + word2 = bytestream_get_le32(&buf_ptr); + check_sum = bytestream_get_le32(&buf_ptr); + data_size = bytestream_get_le32(&buf_ptr); + + if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) { + av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n"); + return AVERROR_INVALIDDATA; + } + + /* parse the bitstream header */ + bs_hdr = buf_ptr; + buf_size -= 16; + + if (bytestream_get_le16(&buf_ptr) != 32) { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n"); + return AVERROR_INVALIDDATA; + } + + ctx->frame_num = frame_num; + ctx->frame_flags = bytestream_get_le16(&buf_ptr); + ctx->data_size = (bytestream_get_le32(&buf_ptr) + 7) >> 3; + ctx->cb_offset = *buf_ptr++; + + if (ctx->data_size == 16) + return 4; + if (ctx->data_size > buf_size) + ctx->data_size = buf_size; + + buf_ptr += 3; // skip reserved byte and checksum + + /* check frame dimensions */ + height = bytestream_get_le16(&buf_ptr); + width = bytestream_get_le16(&buf_ptr); + if (av_image_check_size(width, height, 0, avctx)) + return AVERROR_INVALIDDATA; + + if (width != ctx->width || height != ctx->height) { + int res; + + av_dlog(avctx, "Frame dimensions changed!\n"); + + if (width < 16 || width > 640 || + height < 16 || height > 480 || + width & 3 || height & 3) { + av_log(avctx, AV_LOG_ERROR, + "Invalid picture dimensions: %d x %d!\n", width, height); + return AVERROR_INVALIDDATA; + } + free_frame_buffers(ctx); + if ((res = allocate_frame_buffers(ctx, avctx, width, height)) < 0) + return res; + avcodec_set_dimensions(avctx, width, height); + } + + y_offset = bytestream_get_le32(&buf_ptr); + v_offset = bytestream_get_le32(&buf_ptr); + u_offset = bytestream_get_le32(&buf_ptr); + + /* unfortunately there is no common order of planes in the buffer */ + /* so we use that sorting algo for determining planes data sizes */ + starts[0] = y_offset; + starts[1] = v_offset; + starts[2] = u_offset; + + for (j = 0; j < 3; j++) { + ends[j] = ctx->data_size; + for (i = 2; i >= 0; i--) + if (starts[i] < ends[j] && starts[i] > starts[j]) + ends[j] = starts[i]; + } + + ctx->y_data_size = ends[0] - starts[0]; + ctx->v_data_size = ends[1] - starts[1]; + ctx->u_data_size = ends[2] - starts[2]; + if (FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 || + FFMIN3(ctx->y_data_size, ctx->v_data_size, ctx->u_data_size) <= 0) { + av_log(avctx, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n"); + return AVERROR_INVALIDDATA; + } + + ctx->y_data_ptr = bs_hdr + y_offset; + ctx->v_data_ptr = bs_hdr + v_offset; + ctx->u_data_ptr = bs_hdr + u_offset; + ctx->alt_quant = buf_ptr + sizeof(uint32_t); + + if (ctx->data_size == 16) { + av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n"); + return 16; + } + + if (ctx->frame_flags & BS_8BIT_PEL) { + avpriv_request_sample(avctx, "8-bit pixel format"); + return AVERROR_PATCHWELCOME; + } + + if (ctx->frame_flags & BS_MV_X_HALF || ctx->frame_flags & BS_MV_Y_HALF) { + avpriv_request_sample(avctx, "Halfpel motion vectors"); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + + +/** + * Convert and output the current plane. + * All pixel values will be upsampled by shifting right by one bit. + * + * @param[in] plane pointer to the descriptor of the plane being processed + * @param[in] buf_sel indicates which frame buffer the input data stored in + * @param[out] dst pointer to the buffer receiving converted pixels + * @param[in] dst_pitch pitch for moving to the next y line + * @param[in] dst_height output plane height + */ +static void output_plane(const Plane *plane, int buf_sel, uint8_t *dst, + int dst_pitch, int dst_height) +{ + int x,y; + const uint8_t *src = plane->pixels[buf_sel]; + uint32_t pitch = plane->pitch; + + dst_height = FFMIN(dst_height, plane->height); + for (y = 0; y < dst_height; y++) { + /* convert four pixels at once using SWAR */ + for (x = 0; x < plane->width >> 2; x++) { + AV_WN32A(dst, (AV_RN32A(src) & 0x7F7F7F7F) << 1); + src += 4; + dst += 4; + } + + for (x <<= 2; x < plane->width; x++) + *dst++ = *src++ << 1; + + src += pitch - plane->width; + dst += dst_pitch - plane->width; + } +} + + +static av_cold int decode_init(AVCodecContext *avctx) +{ + Indeo3DecodeContext *ctx = avctx->priv_data; + + ctx->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + + build_requant_tab(); + + ff_hpeldsp_init(&ctx->hdsp, avctx->flags); + + return allocate_frame_buffers(ctx, avctx, avctx->width, avctx->height); +} + + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + Indeo3DecodeContext *ctx = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *frame = data; + int res; + + res = decode_frame_headers(ctx, avctx, buf, buf_size); + if (res < 0) + return res; + + /* skip sync(null) frames */ + if (res) { + // we have processed 16 bytes but no data was decoded + *got_frame = 0; + return buf_size; + } + + /* skip droppable INTER frames if requested */ + if (ctx->frame_flags & BS_NONREF && + (avctx->skip_frame >= AVDISCARD_NONREF)) + return 0; + + /* skip INTER frames if requested */ + if (!(ctx->frame_flags & BS_KEYFRAME) && avctx->skip_frame >= AVDISCARD_NONKEY) + return 0; + + /* use BS_BUFFER flag for buffer switching */ + ctx->buf_sel = (ctx->frame_flags >> BS_BUFFER) & 1; + + if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + return res; + + /* decode luma plane */ + if ((res = decode_plane(ctx, avctx, ctx->planes, ctx->y_data_ptr, ctx->y_data_size, 40))) + return res; + + /* decode chroma planes */ + if ((res = decode_plane(ctx, avctx, &ctx->planes[1], ctx->u_data_ptr, ctx->u_data_size, 10))) + return res; + + if ((res = decode_plane(ctx, avctx, &ctx->planes[2], ctx->v_data_ptr, ctx->v_data_size, 10))) + return res; + + output_plane(&ctx->planes[0], ctx->buf_sel, + frame->data[0], frame->linesize[0], + avctx->height); + output_plane(&ctx->planes[1], ctx->buf_sel, + frame->data[1], frame->linesize[1], + (avctx->height + 3) >> 2); + output_plane(&ctx->planes[2], ctx->buf_sel, + frame->data[2], frame->linesize[2], + (avctx->height + 3) >> 2); + + *got_frame = 1; + + return buf_size; +} + + +static av_cold int decode_close(AVCodecContext *avctx) +{ + free_frame_buffers(avctx->priv_data); + + return 0; +} + +AVCodec ff_indeo3_decoder = { + .name = "indeo3", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_INDEO3, + .priv_data_size = sizeof(Indeo3DecodeContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/indeo3data.h b/ffmpeg/libavcodec/indeo3data.h new file mode 100644 index 0000000..e7e28a3 --- /dev/null +++ b/ffmpeg/libavcodec/indeo3data.h @@ -0,0 +1,362 @@ +/* + * Indeo Video v3 compatible decoder + * Copyright (c) 2009 - 2011 Maxim Poliakovski + * + * 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 + */ + +#ifndef AVCODEC_INDEO3DATA_H +#define AVCODEC_INDEO3DATA_H + +#include + +#include "config.h" + +/* + * Define compressed VQ tables. + */ + +#define TAB_1_1 \ + PD( 0, 0), E2( 2, 2), E4( -1, 3), E2( 4, 4), E4( 1, 5),\ + E2( -4, 4), E4( -2, 6), E4( 4, 9), E2( 9, 9), E4( 1, 10),\ + E4( -5, 8), E4( 9, 15), E4( -3, 12), E4( 4, 16), E2( 16, 16),\ + E4( 0, 18), E2( -12, 12), E4( -9, 16), E4( 11, 27), E4( 19, 28),\ + E4( -6, 22), E4( 4, 29), E2( 30, 30), E4( -2, 33), E4( -18, 23),\ + E4( -15, 30), E4( 22, 46), E4( 13, 47), E4( 35, 49), E4( -11, 41),\ + E4( 4, 51), E2( 54, 54), E2( -34, 34), E4( -29, 42), E4( -6, 60),\ + E4( 27, 76), E4( 43, 77), E4( -24, 55), E4( 14, 79), E4( 63, 83),\ + E4( -20, 74), E4( 2, 88), E2( 93, 93), E4( -52, 61), E4( 52, 120),\ + E4( -45, 75), E4( 75, 125), E4( 33, 122), E4( -13, 103), E4( -40, 96),\ + E4( -34, 127), E2( -89, 89), E4( -78, 105), E2( 12, 12), E2( 23, 23),\ + E2( 42, 42), E2( 73, 73) + +#define TAB_1_2 \ + PD( 0, 0), E2( 3, 3), E4( -1, 4), E2( 7, 7), E4( 2, 8),\ + E4( -2, 9), E2( -6, 6), E4( 6, 13), E2( 13, 13), E4( 1, 14),\ + E4( -8, 12), E4( 14, 23), E4( -5, 18), E4( 6, 24), E2( 24, 24),\ + E4( -1, 27), E2( -17, 17), E4( -13, 23), E4( 16, 40), E4( 28, 41),\ + E4( -9, 33), E4( 6, 43), E2( 46, 46), E4( -4, 50), E4( -27, 34),\ + E4( -22, 45), E4( 34, 69), E4( 19, 70), E4( 53, 73), E4( -17, 62),\ + E4( 5, 77), E2( 82, 82), E2( -51, 51), E4( -43, 64), E4( -10, 90),\ + E4( 41, 114), E4( 64, 116), E4( -37, 82), E4( 22, 119), E4( 95, 124),\ + E4( -30, 111), E4( -78, 92), E4( -68, 113), E2( 18, 18), E2( 34, 34),\ + E2( 63, 63), E2( 109, 109) + +#define TAB_1_3 \ + PD( 0, 0), E2( 4, 4), E4( -1, 5), E4( 3, 10), E2( 9, 9),\ + E2( -7, 7), E4( -3, 12), E4( 8, 17), E2( 17, 17), E4( 1, 19),\ + E4( -11, 16), E4( -6, 23), E4( 18, 31), E4( 8, 32), E2( 33, 33),\ + E4( -1, 36), E2( -23, 23), E4( -17, 31), E4( 21, 54), E4( 37, 55),\ + E4( -12, 44), E4( 8, 57), E2( 61, 61), E4( -5, 66), E4( -36, 45),\ + E4( -29, 60), E4( 45, 92), E4( 25, 93), E4( 71, 97), E4( -22, 83),\ + E4( 7, 102), E2( 109, 109), E2( -68, 68), E4( -57, 85), E4( -13, 120),\ + E4( -49, 110), E4(-104, 123), E2( 24, 24), E2( 46, 46), E2( 84, 84) + +#define TAB_1_4 \ + PD( 0, 0), E2( 5, 5), E4( -2, 7), E2( 11, 11), E4( 3, 13),\ + E2( -9, 9), E4( -4, 15), E4( 11, 22), E2( 21, 21), E4( 2, 24),\ + E4( -14, 20), E4( 23, 38), E4( -8, 29), E4( 11, 39), E2( 41, 41),\ + E4( -1, 45), E2( -29, 29), E4( -22, 39), E4( 27, 67), E4( 47, 69),\ + E4( -15, 56), E4( 11, 71), E2( 76, 76), E4( -6, 83), E4( -45, 57),\ + E4( -36, 75), E4( 56, 115), E4( 31, 117), E4( 88, 122), E4( -28, 104),\ + E2( -85, 85), E4( -72, 106), E2( 30, 30), E2( 58, 58), E2( 105, 105) + +#define TAB_1_5 \ + PD( 0, 0), E2( 6, 6), E4( -2, 8), E2( 13, 13), E4( 4, 15),\ + E2( -11, 11), E4( -5, 18), E4( 13, 26), E2( 26, 26), E4( 2, 29),\ + E4( -16, 24), E4( 28, 46), E4( -9, 35), E4( 13, 47), E2( 49, 49),\ + E4( -1, 54), E2( -35, 35), E4( -26, 47), E4( 32, 81), E4( 56, 83),\ + E4( -18, 67), E4( 13, 86), E2( 91, 91), E4( -7, 99), E4( -54, 68),\ + E4( -44, 90), E4( -33, 124), E2(-103, 103), E4( -86, 127), E2( 37, 37),\ + E2( 69, 69) + +#define TAB_1_6 \ + PD( 0, 0), E2( 7, 7), E4( -3, 10), E2( 16, 16), E4( 5, 18),\ + E2( -13, 13), E4( -6, 21), E4( 15, 30), E2( 30, 30), E4( 2, 34),\ + E4( -19, 28), E4( 32, 54), E4( -11, 41), E4( 15, 55), E2( 57, 57),\ + E4( -1, 63), E2( -40, 40), E4( -30, 55), E4( 37, 94), E4( 65, 96),\ + E4( -21, 78), E4( 15, 100), E2( 106, 106), E4( -8, 116), E4( -63, 79),\ + E4( -51, 105), E2(-120, 120), E2( 43, 43), E2( 80, 80) + +#define TAB_1_7 \ + PD( 0, 0), E2( 8, 8), E4( -3, 11), E2( 18, 18), E4( 5, 20),\ + E2( -15, 15), E4( -7, 24), E4( 17, 35), E2( 34, 34), E4( 3, 38),\ + E4( -22, 32), E4( 37, 61), E4( -13, 47), E4( 17, 63), E2( 65, 65),\ + E4( -1, 72), E2( -46, 46), E4( -35, 63), E4( 43, 107), E4( 75, 110),\ + E4( -24, 89), E4( 17, 114), E2( 121, 121), E4( -72, 91), E4( -58, 120),\ + E2( 49, 49), E2( 92, 92) + +#define TAB_1_8 \ + PD( 0, 0), E2( 9, 9), E4( -3, 12), E2( 20, 20), E4( 6, 23),\ + E2( -17, 17), E4( -7, 27), E4( 19, 39), E2( 39, 39), E4( 3, 43),\ + E4( -24, 36), E4( 42, 69), E4( -14, 53), E4( 19, 71), E2( 73, 73),\ + E4( -2, 80), E2( -52, 52), E4( -39, 70), E4( 48, 121), E4( 84, 124),\ + E4( -27, 100), E4( -81, 102), E2( 55, 55), E2( 104, 104) + +#define TAB_2_1 \ + PD( 0, 0), E2( 2, 2), E4( 0, 2), E2( 4, 4), E4( 0, 4),\ + E2( -4, 4), E4( -2, 6), E4( 4, 8), E2( 8, 8), E4( 0, 10),\ + E4( -4, 8), E4( 8, 14), E4( -2, 12), E4( 4, 16), E2( 16, 16),\ + E4( 0, 18), E2( -12, 12), E4( -8, 16), E4( 10, 26), E4( 18, 28),\ + E4( -6, 22), E4( 4, 28), E2( 30, 30), E4( -2, 32), E4( -18, 22),\ + E4( -14, 30), E4( 22, 46), E4( 12, 46), E4( 34, 48), E4( -10, 40),\ + E4( 4, 50), E2( 54, 54), E2( -34, 34), E4( -28, 42), E4( -6, 60),\ + E4( 26, 76), E4( 42, 76), E4( -24, 54), E4( 14, 78), E4( 62, 82),\ + E4( -20, 74), E4( 2, 88), E2( 92, 92), E4( -52, 60), E4( 52, 118),\ + E4( -44, 74), E4( 74, 118), E4( 32, 118), E4( -12, 102), E4( -40, 96),\ + E4( -34, 118), E2( -88, 88), E4( -78, 104), E2( 12, 12), E2( 22, 22),\ + E2( 42, 42), E2( 72, 72) + +#define TAB_2_2 \ + PD( 0, 0), E2( 3, 3), E4( 0, 3), E2( 6, 6), E4( 3, 9),\ + E4( -3, 9), E2( -6, 6), E4( 6, 12), E2( 12, 12), E4( 0, 15),\ + E4( -9, 12), E4( 15, 24), E4( -6, 18), E4( 6, 24), E2( 24, 24),\ + E4( 0, 27), E2( -18, 18), E4( -12, 24), E4( 15, 39), E4( 27, 42),\ + E4( -9, 33), E4( 6, 42), E2( 45, 45), E4( -3, 51), E4( -27, 33),\ + E4( -21, 45), E4( 33, 69), E4( 18, 69), E4( 54, 72), E4( -18, 63),\ + E4( 6, 78), E2( 81, 81), E2( -51, 51), E4( -42, 63), E4( -9, 90),\ + E4( 42, 114), E4( 63, 117), E4( -36, 81), E4( 21, 120), E4( 96, 123),\ + E4( -30, 111), E4( -78, 93), E4( -69, 114), E2( 18, 18), E2( 33, 33),\ + E2( 63, 63), E2( 108, 108) + +#define TAB_2_3 \ + PD( 0, 0), E2( 4, 4), E4( 0, 4), E4( 4, 8), E2( 8, 8),\ + E2( -8, 8), E4( -4, 12), E4( 8, 16), E2( 16, 16), E4( 0, 20),\ + E4( -12, 16), E4( -4, 24), E4( 16, 32), E4( 8, 32), E2( 32, 32),\ + E4( 0, 36), E2( -24, 24), E4( -16, 32), E4( 20, 52), E4( 36, 56),\ + E4( -12, 44), E4( 8, 56), E2( 60, 60), E4( -4, 64), E4( -36, 44),\ + E4( -28, 60), E4( 44, 92), E4( 24, 92), E4( 72, 96), E4( -20, 84),\ + E4( 8, 100), E2( 108, 108), E2( -68, 68), E4( -56, 84), E4( -12, 120),\ + E4( -48, 108), E4(-104, 124), E2( 24, 24), E2( 44, 44), E2( 84, 84) + +#define TAB_2_4 \ + PD( 0, 0), E2( 5, 5), E4( 0, 5), E2( 10, 10), E4( 5, 15),\ + E2( -10, 10), E4( -5, 15), E4( 10, 20), E2( 20, 20), E4( 0, 25),\ + E4( -15, 20), E4( 25, 40), E4( -10, 30), E4( 10, 40), E2( 40, 40),\ + E4( 0, 45), E2( -30, 30), E4( -20, 40), E4( 25, 65), E4( 45, 70),\ + E4( -15, 55), E4( 10, 70), E2( 75, 75), E4( -5, 85), E4( -45, 55),\ + E4( -35, 75), E4( 55, 115), E4( 30, 115), E4( 90, 120), E4( -30, 105),\ + E2( -85, 85), E4( -70, 105), E2( 30, 30), E2( 60, 60), E2( 105, 105) + +#define TAB_2_5 \ + PD( 0, 0), E2( 6, 6), E4( 0, 6), E2( 12, 12), E4( 6, 12),\ + E2( -12, 12), E4( -6, 18), E4( 12, 24), E2( 24, 24), E4( 0, 30),\ + E4( -18, 24), E4( 30, 48), E4( -6, 36), E4( 12, 48), E2( 48, 48),\ + E4( 0, 54), E2( -36, 36), E4( -24, 48), E4( 30, 78), E4( 54, 84),\ + E4( -18, 66), E4( 12, 84), E2( 90, 90), E4( -6, 96), E4( -54, 66),\ + E4( -42, 90), E4( -30, 126), E2(-102, 102), E4( -84, 126), E2( 36, 36),\ + E2( 66, 66) + +#define TAB_2_6 \ + PD( 0, 0), E2( 7, 7), E4( 0, 7), E2( 14, 14), E4( 7, 21),\ + E2( -14, 14), E4( -7, 21), E4( 14, 28), E2( 28, 28), E4( 0, 35),\ + E4( -21, 28), E4( 35, 56), E4( -14, 42), E4( 14, 56), E2( 56, 56),\ + E4( 0, 63), E2( -42, 42), E4( -28, 56), E4( 35, 91), E4( 63, 98),\ + E4( -21, 77), E4( 14, 98), E2( 105, 105), E4( -7, 119), E4( -63, 77),\ + E4( -49, 105), E2(-119, 119), E2( 42, 42), E2( 77, 77) + +#define TAB_2_7 \ + PD( 0, 0), E2( 8, 8), E4( 0, 8), E2( 16, 16), E4( 8, 16),\ + E2( -16, 16), E4( -8, 24), E4( 16, 32), E2( 32, 32), E4( 0, 40),\ + E4( -24, 32), E4( 40, 64), E4( -16, 48), E4( 16, 64), E2( 64, 64),\ + E4( 0, 72), E2( -48, 48), E4( -32, 64), E4( 40, 104), E4( 72, 112),\ + E4( -24, 88), E4( 16, 112), E2( 120, 120), E4( -72, 88), E4( -56, 120),\ + E2( 48, 48), E2( 88, 88) + +#define TAB_2_8 \ + PD( 0, 0), E2( 9, 9), E4( 0, 9), E2( 18, 18), E4( 9, 27),\ + E2( -18, 18), E4( -9, 27), E4( 18, 36), E2( 36, 36), E4( 0, 45),\ + E4( -27, 36), E4( 45, 72), E4( -18, 54), E4( 18, 72), E2( 72, 72),\ + E4( 0, 81), E2( -54, 54), E4( -36, 72), E4( 45, 117), E4( 81, 126),\ + E4( -27, 99), E4( -81, 99), E2( 54, 54), E2( 108, 108) + +#define TAB_3_1 \ + PD( 0, 0), E2( 2, 2), E4( 0, 3), E2( 6, 6), E4( 0, 7),\ + E2( -5, 5), E2( 5, -5), E4( 6, 11), E4( 0, 8), E2( 11, 11),\ + E4( 0, 12), E4( 12, 17), E2( 17, 17), E4( 6, 18), E4( -8, 11),\ + E4( 0, 15), E4( 0, 20), E4( 18, 25), E4( 11, 25), E2( 25, 25),\ + E2( -14, 14), E2( 14, -14), E4( 0, 26), E4( -11, 18), E4( -7, 22),\ + E4( 26, 34), E4( 18, 34), E2( 34, 34), E4( 11, 35), E4( 0, 29),\ + E4( -19, 22), E4( -15, 26), E4( 0, 37), E4( 27, 44), E4( 36, 44),\ + E4( 18, 44), E4( -10, 33), E2( 45, 45) + +#define TAB_3_2 \ + PD( 0, 0), E4( 0, 2), E2( 2, 2), E2( 6, 6), E4( 0, 6),\ + E2( -4, 4), E2( 10, -6), E2( 0, -12), PD( -6, -12), E2( 6, -12),\ + PD( 6, 12), E2( -14, 0), E2( 12, 12), E2( 0, -18), E2( 14, -12),\ + PD( -18, -6), E2( 18, -6), PD( 18, 6), PD( -10, -18), E2( 10, -18),\ + PD( 10, 18), E2( -22, 0), E2( 0, -24), PD( -22, -12), E2( 22, -12),\ + PD( 22, 12), PD( -8, -24), E2( 8, -24), PD( 8, 24), PD( -26, -6),\ + E2( 26, -6), PD( 26, 6), E2( -28, 0), E2( 20, 20), E2( -14, -26),\ + E2( -30, -12), E2( -10, -32), E2( -18, -32), E2( -26, -26), E2( -34, -20),\ + E2( -38, -12), E2( -32, -32), PD( 32, 32), PD( -22, -40), E2( -34, -34) + +#define TAB_3_3 \ + PD( 0, 0), E4( 0, 2), E2( 4, 4), E2( 10, 10), E4( 0, 10),\ + E2( -6, 6), E2( 14, -8), E2( -18, 0), E2( 10, -16), E2( 0, -24),\ + PD( -24, -8), E2( 24, -8), PD( 24, 8), E2( 18, 18), E2( 20, -16),\ + PD( -14, -26), E2( 14, -26), PD( 14, 26), E2( -30, 0), E2( 0, -34),\ + PD( -34, -8), E2( 34, -8), PD( 34, 8), PD( -30, -18), E2( 30, -18),\ + PD( 30, 18), PD( -10, -34), E2( 10, -34), PD( 10, 34), E2( -20, -34),\ + E2( -40, 0), E2( 30, 30), E2( -40, -18), E2( 0, -44), E2( -16, -44),\ + PD( -36, -36), E2( -36, -36), E2( -26, -44), E2( -46, -26), E2( -52, -18),\ + PD( -20, -54), E2( -44, -44), PD( -32, -54), PD( -46, -46), E2( -46, -46) + +#define TAB_3_4 \ + PD( 0, 0), E4( 0, 4), E2( 4, 4), E2( 12, 12), E4( 0, 12),\ + E2( -8, 8), E2( 8, -16), E2( 0, -24), PD( -24, -8), E2( 24, -8),\ + PD( 24, 8), E2( 20, -16), E2( -28, 0), PD( -16, -24), E2( 16, -24),\ + PD( 16, 24), E2( 0, -32), PD( -28, -16), E2( 28, -16), PD( 28, 16),\ + PD( -8, -32), PD( 8, -32), PD( -32, -8), E2( 32, -8), PD( 32, 8),\ + PD( -8, 32), PD( 8, 32), E2( 24, 24), E2( 24, -24), E2( -20, -32),\ + E2( -40, 0), E2( -40, -16), PD( 0, -44), PD( 0, -44), E2( -44, 0),\ + PD( 0, 44), PD( 0, 44), E2( -32, -32), E2( -16, -44), PD( -24, -44),\ + E2( -44, -24), PD( 24, 44), E2( -48, -16), PD( -36, -36), E2( -36, -36),\ + PD( 36, 36), PD( -20, -52), E2( 40, 40), PD( -32, -52) + +#define TAB_3_5 \ + PD( 0, 0), E2( 2, 2), E2( 6, 6), E2( 12, 12), E2( 20, 20),\ + E2( 32, 32), E2( 46, 46) + + +/** + * Pack two delta values (a,b) into one 16bit word + * according with endianness of the host machine. + */ +#if HAVE_BIGENDIAN +#define PD(a,b) (((a) << 8) + (b)) +#else +#define PD(a,b) (((b) << 8) + (a)) +#endif + +/** + * Expand a pair of delta values (a,b) + * into two/four delta entries. + */ +#define E2(a, b) PD(a, b), PD(-(a), -(b)) +#define E4(a, b) PD(a, b), PD(-(a), -(b)), PD(b, a), PD(-(b), -(a)) + +/* + * VQ tables for 4x4 block modes. + * Let the compiler decompress and build the tables for us. + */ +static const int16_t delta_tab_1_1[195] = { TAB_1_1 }; +static const int16_t delta_tab_1_2[159] = { TAB_1_2 }; +static const int16_t delta_tab_1_3[133] = { TAB_1_3 }; +static const int16_t delta_tab_1_4[115] = { TAB_1_4 }; +static const int16_t delta_tab_1_5[101] = { TAB_1_5 }; +static const int16_t delta_tab_1_6[93] = { TAB_1_6 }; +static const int16_t delta_tab_1_7[87] = { TAB_1_7 }; +static const int16_t delta_tab_1_8[77] = { TAB_1_8 }; + +static const int16_t delta_tab_2_1[195] = { TAB_2_1 }; +static const int16_t delta_tab_2_2[159] = { TAB_2_2 }; +static const int16_t delta_tab_2_3[133] = { TAB_2_3 }; +static const int16_t delta_tab_2_4[115] = { TAB_2_4 }; +static const int16_t delta_tab_2_5[101] = { TAB_2_5 }; +static const int16_t delta_tab_2_6[93] = { TAB_2_6 }; +static const int16_t delta_tab_2_7[87] = { TAB_2_7 }; +static const int16_t delta_tab_2_8[77] = { TAB_2_8 }; + +static const int16_t delta_tab_3_1[128] = { TAB_3_1 }; +static const int16_t delta_tab_3_2[79] = { TAB_3_2 }; +static const int16_t delta_tab_3_3[79] = { TAB_3_3 }; +static const int16_t delta_tab_3_4[79] = { TAB_3_4 }; +static const int16_t delta_tab_3_5[79] = { TAB_3_5 }; + +#undef PD + +/** + * Pack four delta values (a,a,b,b) into one 32bit word + * according with endianness of the host machine. + */ +#if HAVE_BIGENDIAN +#define PD(a,b) (((a) << 24) + ((a) << 16) + ((b) << 8) + (b)) +#else +#define PD(a,b) (((b) << 24) + ((b) << 16) + ((a) << 8) + (a)) +#endif + +/* + * VQ tables for 8x8 block modes. + * Those are based on the same delta tables by using + * each value twice: ABCD --> AABBCCDD. + */ +static const int32_t delta_tab_1_1_m10[195] = { TAB_1_1 }; +static const int32_t delta_tab_1_2_m10[159] = { TAB_1_2 }; +static const int32_t delta_tab_1_3_m10[133] = { TAB_1_3 }; +static const int32_t delta_tab_1_4_m10[115] = { TAB_1_4 }; +static const int32_t delta_tab_1_5_m10[101] = { TAB_1_5 }; +static const int32_t delta_tab_1_6_m10[93] = { TAB_1_6 }; +static const int32_t delta_tab_1_7_m10[87] = { TAB_1_7 }; +static const int32_t delta_tab_1_8_m10[77] = { TAB_1_8 }; + +static const int32_t delta_tab_2_1_m10[195] = { TAB_2_1 }; +static const int32_t delta_tab_2_2_m10[159] = { TAB_2_2 }; +static const int32_t delta_tab_2_3_m10[133] = { TAB_2_3 }; +static const int32_t delta_tab_2_4_m10[115] = { TAB_2_4 }; +static const int32_t delta_tab_2_5_m10[101] = { TAB_2_5 }; +static const int32_t delta_tab_2_6_m10[93] = { TAB_2_6 }; +static const int32_t delta_tab_2_7_m10[87] = { TAB_2_7 }; +static const int32_t delta_tab_2_8_m10[77] = { TAB_2_8 }; + +static const int32_t delta_tab_3_1_m10[128] = { TAB_3_1 }; +static const int32_t delta_tab_3_2_m10[79] = { TAB_3_2 }; +static const int32_t delta_tab_3_3_m10[79] = { TAB_3_3 }; +static const int32_t delta_tab_3_4_m10[79] = { TAB_3_4 }; +static const int32_t delta_tab_3_5_m10[79] = { TAB_3_5 }; + + +typedef struct vqEntry { + const int16_t *deltas; ///< delta tables for 4x4 block modes + const int32_t *deltas_m10; ///< delta tables for 8x8 block modes + uint8_t num_dyads; ///< number of two-pixel deltas + uint8_t quad_exp; ///< log2 of four-pixel deltas +} vqEntry; + +static const vqEntry vq_tab[24] = { + /* set 1 */ + { delta_tab_1_1, delta_tab_1_1_m10, 195, 7 }, + { delta_tab_1_2, delta_tab_1_2_m10, 159, 9 }, + { delta_tab_1_3, delta_tab_1_3_m10, 133, 10 }, + { delta_tab_1_4, delta_tab_1_4_m10, 115, 11 }, + { delta_tab_1_5, delta_tab_1_5_m10, 101, 12 }, + { delta_tab_1_6, delta_tab_1_6_m10, 93, 12 }, + { delta_tab_1_7, delta_tab_1_7_m10, 87, 12 }, + { delta_tab_1_8, delta_tab_1_8_m10, 77, 13 }, + + /* set 2 */ + { delta_tab_2_1, delta_tab_2_1_m10, 195, 7 }, + { delta_tab_2_2, delta_tab_2_2_m10, 159, 9 }, + { delta_tab_2_3, delta_tab_2_3_m10, 133, 10 }, + { delta_tab_2_4, delta_tab_2_4_m10, 115, 11 }, + { delta_tab_2_5, delta_tab_2_5_m10, 101, 12 }, + { delta_tab_2_6, delta_tab_2_6_m10, 93, 12 }, + { delta_tab_2_7, delta_tab_2_7_m10, 87, 12 }, + { delta_tab_2_8, delta_tab_2_8_m10, 77, 13 }, + + /* set 3 */ + { delta_tab_3_1, delta_tab_3_1_m10, 128, 11 }, + { delta_tab_3_2, delta_tab_3_2_m10, 79, 13 }, + { delta_tab_3_3, delta_tab_3_3_m10, 79, 13 }, + { delta_tab_3_4, delta_tab_3_4_m10, 79, 13 }, + { delta_tab_3_5, delta_tab_3_5_m10, 79, 13 }, + { delta_tab_3_5, delta_tab_3_5_m10, 79, 13 }, + { delta_tab_3_5, delta_tab_3_5_m10, 79, 13 }, + { delta_tab_3_5, delta_tab_3_5_m10, 79, 13 } +}; + +#endif /* AVCODEC_INDEO3DATA_H */ diff --git a/ffmpeg/libavcodec/indeo4.c b/ffmpeg/libavcodec/indeo4.c new file mode 100644 index 0000000..a958b50 --- /dev/null +++ b/ffmpeg/libavcodec/indeo4.c @@ -0,0 +1,659 @@ +/* + * Indeo Video Interactive v4 compatible decoder + * Copyright (c) 2009-2011 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Indeo Video Interactive version 4 decoder + * + * Indeo 4 data is usually transported within .avi or .mov files. + * Known FOURCCs: 'IV41' + */ + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "get_bits.h" +#include "ivi_dsp.h" +#include "ivi_common.h" +#include "indeo4data.h" + +/** + * Indeo 4 frame types. + */ +enum { + FRAMETYPE_INTRA = 0, + FRAMETYPE_INTRA1 = 1, ///< intra frame with slightly different bitstream coding + FRAMETYPE_INTER = 2, ///< non-droppable P-frame + FRAMETYPE_BIDIR = 3, ///< bidirectional frame + FRAMETYPE_INTER_NOREF = 4, ///< droppable P-frame + FRAMETYPE_NULL_FIRST = 5, ///< empty frame with no data + FRAMETYPE_NULL_LAST = 6 ///< empty frame with no data +}; + +#define IVI4_PIC_SIZE_ESC 7 + + +static const struct { + InvTransformPtr *inv_trans; + DCTransformPtr *dc_trans; + int is_2d_trans; +} transforms[18] = { + { ff_ivi_inverse_haar_8x8, ff_ivi_dc_haar_2d, 1 }, + { NULL, NULL, 0 }, /* inverse Haar 8x1 */ + { NULL, NULL, 0 }, /* inverse Haar 1x8 */ + { ff_ivi_put_pixels_8x8, ff_ivi_put_dc_pixel_8x8, 1 }, + { ff_ivi_inverse_slant_8x8, ff_ivi_dc_slant_2d, 1 }, + { ff_ivi_row_slant8, ff_ivi_dc_row_slant, 1 }, + { ff_ivi_col_slant8, ff_ivi_dc_col_slant, 1 }, + { NULL, NULL, 0 }, /* inverse DCT 8x8 */ + { NULL, NULL, 0 }, /* inverse DCT 8x1 */ + { NULL, NULL, 0 }, /* inverse DCT 1x8 */ + { NULL, NULL, 0 }, /* inverse Haar 4x4 */ + { ff_ivi_inverse_slant_4x4, ff_ivi_dc_slant_2d, 1 }, + { NULL, NULL, 0 }, /* no transform 4x4 */ + { NULL, NULL, 0 }, /* inverse Haar 1x4 */ + { NULL, NULL, 0 }, /* inverse Haar 4x1 */ + { NULL, NULL, 0 }, /* inverse slant 1x4 */ + { NULL, NULL, 0 }, /* inverse slant 4x1 */ + { NULL, NULL, 0 }, /* inverse DCT 4x4 */ +}; + +/** + * Decode subdivision of a plane. + * This is a simplified version that checks for two supported subdivisions: + * - 1 wavelet band per plane, size factor 1:1, code pattern: 3 + * - 4 wavelet bands per plane, size factor 1:4, code pattern: 2,3,3,3,3 + * Anything else is either unsupported or corrupt. + * + * @param[in,out] gb the GetBit context + * @return number of wavelet bands or 0 on error + */ +static int decode_plane_subdivision(GetBitContext *gb) +{ + int i; + + switch (get_bits(gb, 2)) { + case 3: + return 1; + case 2: + for (i = 0; i < 4; i++) + if (get_bits(gb, 2) != 3) + return 0; + return 4; + default: + return 0; + } +} + +static inline int scale_tile_size(int def_size, int size_factor) +{ + return size_factor == 15 ? def_size : (size_factor + 1) << 5; +} + +/** + * Decode Indeo 4 picture header. + * + * @param[in,out] ctx pointer to the decoder context + * @param[in] avctx pointer to the AVCodecContext + * @return result code: 0 = OK, negative number = error + */ +static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) +{ + int pic_size_indx, i, p; + IVIPicConfig pic_conf; + + if (get_bits(&ctx->gb, 18) != 0x3FFF8) { + av_log(avctx, AV_LOG_ERROR, "Invalid picture start code!\n"); + return AVERROR_INVALIDDATA; + } + + ctx->prev_frame_type = ctx->frame_type; + ctx->frame_type = get_bits(&ctx->gb, 3); + if (ctx->frame_type == 7) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame type: %d\n", ctx->frame_type); + return AVERROR_INVALIDDATA; + } + +#if IVI4_STREAM_ANALYSER + if (ctx->frame_type == FRAMETYPE_BIDIR) + ctx->has_b_frames = 1; +#endif + + ctx->transp_status = get_bits1(&ctx->gb); +#if IVI4_STREAM_ANALYSER + if (ctx->transp_status) { + ctx->has_transp = 1; + } +#endif + + /* unknown bit: Mac decoder ignores this bit, XANIM returns error */ + if (get_bits1(&ctx->gb)) { + av_log(avctx, AV_LOG_ERROR, "Sync bit is set!\n"); + return AVERROR_INVALIDDATA; + } + + ctx->data_size = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 24) : 0; + + /* null frames don't contain anything else so we just return */ + if (ctx->frame_type >= FRAMETYPE_NULL_FIRST) { + av_dlog(avctx, "Null frame encountered!\n"); + return 0; + } + + /* Check key lock status. If enabled - ignore lock word. */ + /* Usually we have to prompt the user for the password, but */ + /* we don't do that because Indeo 4 videos can be decoded anyway */ + if (get_bits1(&ctx->gb)) { + skip_bits_long(&ctx->gb, 32); + av_dlog(avctx, "Password-protected clip!\n"); + } + + pic_size_indx = get_bits(&ctx->gb, 3); + if (pic_size_indx == IVI4_PIC_SIZE_ESC) { + pic_conf.pic_height = get_bits(&ctx->gb, 16); + pic_conf.pic_width = get_bits(&ctx->gb, 16); + } else { + pic_conf.pic_height = ivi4_common_pic_sizes[pic_size_indx * 2 + 1]; + pic_conf.pic_width = ivi4_common_pic_sizes[pic_size_indx * 2 ]; + } + + /* Decode tile dimensions. */ + if (get_bits1(&ctx->gb)) { + pic_conf.tile_height = scale_tile_size(pic_conf.pic_height, get_bits(&ctx->gb, 4)); + pic_conf.tile_width = scale_tile_size(pic_conf.pic_width, get_bits(&ctx->gb, 4)); +#if IVI4_STREAM_ANALYSER + ctx->uses_tiling = 1; +#endif + } else { + pic_conf.tile_height = pic_conf.pic_height; + pic_conf.tile_width = pic_conf.pic_width; + } + + /* Decode chroma subsampling. We support only 4:4 aka YVU9. */ + if (get_bits(&ctx->gb, 2)) { + av_log(avctx, AV_LOG_ERROR, "Only YVU9 picture format is supported!\n"); + return AVERROR_INVALIDDATA; + } + pic_conf.chroma_height = (pic_conf.pic_height + 3) >> 2; + pic_conf.chroma_width = (pic_conf.pic_width + 3) >> 2; + + /* decode subdivision of the planes */ + pic_conf.luma_bands = decode_plane_subdivision(&ctx->gb); + pic_conf.chroma_bands = 0; + if (pic_conf.luma_bands) + pic_conf.chroma_bands = decode_plane_subdivision(&ctx->gb); + ctx->is_scalable = pic_conf.luma_bands != 1 || pic_conf.chroma_bands != 1; + if (ctx->is_scalable && (pic_conf.luma_bands != 4 || pic_conf.chroma_bands != 1)) { + av_log(avctx, AV_LOG_ERROR, "Scalability: unsupported subdivision! Luma bands: %d, chroma bands: %d\n", + pic_conf.luma_bands, pic_conf.chroma_bands); + return AVERROR_INVALIDDATA; + } + + /* check if picture layout was changed and reallocate buffers */ + if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf)) { + if (ff_ivi_init_planes(ctx->planes, &pic_conf)) { + av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n"); + return AVERROR(ENOMEM); + } + + ctx->pic_conf = pic_conf; + + /* set default macroblock/block dimensions */ + for (p = 0; p <= 2; p++) { + for (i = 0; i < (!p ? pic_conf.luma_bands : pic_conf.chroma_bands); i++) { + ctx->planes[p].bands[i].mb_size = !p ? (!ctx->is_scalable ? 16 : 8) : 4; + ctx->planes[p].bands[i].blk_size = !p ? 8 : 4; + } + } + + if (ff_ivi_init_tiles(ctx->planes, ctx->pic_conf.tile_width, + ctx->pic_conf.tile_height)) { + av_log(avctx, AV_LOG_ERROR, + "Couldn't reallocate internal structures!\n"); + return AVERROR(ENOMEM); + } + } + + ctx->frame_num = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 20) : 0; + + /* skip decTimeEst field if present */ + if (get_bits1(&ctx->gb)) + skip_bits(&ctx->gb, 8); + + /* decode macroblock and block huffman codebooks */ + if (ff_ivi_dec_huff_desc(&ctx->gb, get_bits1(&ctx->gb), IVI_MB_HUFF, &ctx->mb_vlc, avctx) || + ff_ivi_dec_huff_desc(&ctx->gb, get_bits1(&ctx->gb), IVI_BLK_HUFF, &ctx->blk_vlc, avctx)) + return AVERROR_INVALIDDATA; + + ctx->rvmap_sel = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 3) : 8; + + ctx->in_imf = get_bits1(&ctx->gb); + ctx->in_q = get_bits1(&ctx->gb); + + ctx->pic_glob_quant = get_bits(&ctx->gb, 5); + + /* TODO: ignore this parameter if unused */ + ctx->unknown1 = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 3) : 0; + + ctx->checksum = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 16) : 0; + + /* skip picture header extension if any */ + while (get_bits1(&ctx->gb)) { + av_dlog(avctx, "Pic hdr extension encountered!\n"); + skip_bits(&ctx->gb, 8); + } + + if (get_bits1(&ctx->gb)) { + av_log(avctx, AV_LOG_ERROR, "Bad blocks bits encountered!\n"); + } + + align_get_bits(&ctx->gb); + + return 0; +} + + +/** + * Decode Indeo 4 band header. + * + * @param[in,out] ctx pointer to the decoder context + * @param[in,out] band pointer to the band descriptor + * @param[in] avctx pointer to the AVCodecContext + * @return result code: 0 = OK, negative number = error + */ +static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band, + AVCodecContext *avctx) +{ + int plane, band_num, indx, transform_id, scan_indx; + int i; + int quant_mat; + + plane = get_bits(&ctx->gb, 2); + band_num = get_bits(&ctx->gb, 4); + if (band->plane != plane || band->band_num != band_num) { + av_log(avctx, AV_LOG_ERROR, "Invalid band header sequence!\n"); + return AVERROR_INVALIDDATA; + } + + band->is_empty = get_bits1(&ctx->gb); + if (!band->is_empty) { + /* skip header size + * If header size is not given, header size is 4 bytes. */ + if (get_bits1(&ctx->gb)) + skip_bits(&ctx->gb, 16); + + band->is_halfpel = get_bits(&ctx->gb, 2); + if (band->is_halfpel >= 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid/unsupported mv resolution: %d!\n", + band->is_halfpel); + return AVERROR_INVALIDDATA; + } +#if IVI4_STREAM_ANALYSER + if (!band->is_halfpel) + ctx->uses_fullpel = 1; +#endif + + band->checksum_present = get_bits1(&ctx->gb); + if (band->checksum_present) + band->checksum = get_bits(&ctx->gb, 16); + + indx = get_bits(&ctx->gb, 2); + if (indx == 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid block size!\n"); + return AVERROR_INVALIDDATA; + } + band->mb_size = 16 >> indx; + band->blk_size = 8 >> (indx >> 1); + + band->inherit_mv = get_bits1(&ctx->gb); + band->inherit_qdelta = get_bits1(&ctx->gb); + + band->glob_quant = get_bits(&ctx->gb, 5); + + if (!get_bits1(&ctx->gb) || ctx->frame_type == FRAMETYPE_INTRA) { + transform_id = get_bits(&ctx->gb, 5); + if (transform_id >= FF_ARRAY_ELEMS(transforms) || + !transforms[transform_id].inv_trans) { + avpriv_request_sample(avctx, "Transform %d", transform_id); + return AVERROR_PATCHWELCOME; + } + if ((transform_id >= 7 && transform_id <= 9) || + transform_id == 17) { + avpriv_request_sample(avctx, "DCT transform"); + return AVERROR_PATCHWELCOME; + } + + if (transform_id < 10 && band->blk_size < 8) { + av_log(avctx, AV_LOG_ERROR, "wrong transform size!\n"); + return AVERROR_INVALIDDATA; + } +#if IVI4_STREAM_ANALYSER + if ((transform_id >= 0 && transform_id <= 2) || transform_id == 10) + ctx->uses_haar = 1; +#endif + + band->inv_transform = transforms[transform_id].inv_trans; + band->dc_transform = transforms[transform_id].dc_trans; + band->is_2d_trans = transforms[transform_id].is_2d_trans; + band->transform_size= (transform_id < 10) ? 8 : 4; + + scan_indx = get_bits(&ctx->gb, 4); + if ((scan_indx>4 && scan_indx<10) != (band->blk_size==4)) { + av_log(avctx, AV_LOG_ERROR, "mismatching scan table!\n"); + return AVERROR_INVALIDDATA; + } + if (scan_indx == 15) { + av_log(avctx, AV_LOG_ERROR, "Custom scan pattern encountered!\n"); + return AVERROR_INVALIDDATA; + } + band->scan = scan_index_to_tab[scan_indx]; + band->scan_size = band->blk_size; + + quant_mat = get_bits(&ctx->gb, 5); + if (quant_mat == 31) { + av_log(avctx, AV_LOG_ERROR, "Custom quant matrix encountered!\n"); + return AVERROR_INVALIDDATA; + } + if (quant_mat > 21) { + av_log(avctx, AV_LOG_ERROR, "Invalid quant matrix encountered!\n"); + return AVERROR_INVALIDDATA; + } + band->quant_mat = quant_mat; + } + if (quant_index_to_tab[band->quant_mat] > 4 && band->blk_size == 4) { + av_log(avctx, AV_LOG_ERROR, "Invalid quant matrix for 4x4 block encountered!\n"); + band->quant_mat = 0; + return AVERROR_INVALIDDATA; + } + if (band->scan_size != band->blk_size) { + av_log(avctx, AV_LOG_ERROR, "mismatching scan table!\n"); + return AVERROR_INVALIDDATA; + } + if (band->transform_size == 8 && band->blk_size < 8) { + av_log(avctx, AV_LOG_ERROR, "mismatching transform_size!\n"); + return AVERROR_INVALIDDATA; + } + + /* decode block huffman codebook */ + if (ff_ivi_dec_huff_desc(&ctx->gb, get_bits1(&ctx->gb), IVI_BLK_HUFF, + &band->blk_vlc, avctx)) + return AVERROR_INVALIDDATA; + + /* select appropriate rvmap table for this band */ + band->rvmap_sel = get_bits1(&ctx->gb) ? get_bits(&ctx->gb, 3) : 8; + + /* decode rvmap probability corrections if any */ + band->num_corr = 0; /* there is no corrections */ + if (get_bits1(&ctx->gb)) { + band->num_corr = get_bits(&ctx->gb, 8); /* get number of correction pairs */ + if (band->num_corr > 61) { + av_log(avctx, AV_LOG_ERROR, "Too many corrections: %d\n", + band->num_corr); + return AVERROR_INVALIDDATA; + } + + /* read correction pairs */ + for (i = 0; i < band->num_corr * 2; i++) + band->corr[i] = get_bits(&ctx->gb, 8); + } + } + + if (band->blk_size == 8) { + band->intra_base = &ivi4_quant_8x8_intra[quant_index_to_tab[band->quant_mat]][0]; + band->inter_base = &ivi4_quant_8x8_inter[quant_index_to_tab[band->quant_mat]][0]; + } else { + band->intra_base = &ivi4_quant_4x4_intra[quant_index_to_tab[band->quant_mat]][0]; + band->inter_base = &ivi4_quant_4x4_inter[quant_index_to_tab[band->quant_mat]][0]; + } + + /* Indeo 4 doesn't use scale tables */ + band->intra_scale = NULL; + band->inter_scale = NULL; + + align_get_bits(&ctx->gb); + + if (!band->scan) { + av_log(avctx, AV_LOG_ERROR, "band->scan not set\n"); + return AVERROR_INVALIDDATA; + } + + return 0; +} + + +/** + * Decode information (block type, cbp, quant delta, motion vector) + * for all macroblocks in the current tile. + * + * @param[in,out] ctx pointer to the decoder context + * @param[in,out] band pointer to the band descriptor + * @param[in,out] tile pointer to the tile descriptor + * @param[in] avctx pointer to the AVCodecContext + * @return result code: 0 = OK, negative number = error + */ +static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, + IVITile *tile, AVCodecContext *avctx) +{ + int x, y, mv_x, mv_y, mv_delta, offs, mb_offset, blks_per_mb, + mv_scale, mb_type_bits, s; + IVIMbInfo *mb, *ref_mb; + int row_offset = band->mb_size * band->pitch; + + mb = tile->mbs; + ref_mb = tile->ref_mbs; + offs = tile->ypos * band->pitch + tile->xpos; + + blks_per_mb = band->mb_size != band->blk_size ? 4 : 1; + mb_type_bits = ctx->frame_type == FRAMETYPE_BIDIR ? 2 : 1; + + /* scale factor for motion vectors */ + mv_scale = (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3); + mv_x = mv_y = 0; + + if (((tile->width + band->mb_size-1)/band->mb_size) * ((tile->height + band->mb_size-1)/band->mb_size) != tile->num_MBs) { + av_log(avctx, AV_LOG_ERROR, "num_MBs mismatch %d %d %d %d\n", tile->width, tile->height, band->mb_size, tile->num_MBs); + return -1; + } + + for (y = tile->ypos; y < tile->ypos + tile->height; y += band->mb_size) { + mb_offset = offs; + + for (x = tile->xpos; x < tile->xpos + tile->width; x += band->mb_size) { + mb->xpos = x; + mb->ypos = y; + mb->buf_offs = mb_offset; + + if (get_bits1(&ctx->gb)) { + if (ctx->frame_type == FRAMETYPE_INTRA) { + av_log(avctx, AV_LOG_ERROR, "Empty macroblock in an INTRA picture!\n"); + return AVERROR_INVALIDDATA; + } + mb->type = 1; /* empty macroblocks are always INTER */ + mb->cbp = 0; /* all blocks are empty */ + + mb->q_delta = 0; + if (!band->plane && !band->band_num && ctx->in_q) { + mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mb->q_delta = IVI_TOSIGNED(mb->q_delta); + } + + mb->mv_x = mb->mv_y = 0; /* no motion vector coded */ + if (band->inherit_mv && ref_mb) { + /* motion vector inheritance */ + if (mv_scale) { + mb->mv_x = ivi_scale_mv(ref_mb->mv_x, mv_scale); + mb->mv_y = ivi_scale_mv(ref_mb->mv_y, mv_scale); + } else { + mb->mv_x = ref_mb->mv_x; + mb->mv_y = ref_mb->mv_y; + } + } + } else { + if (band->inherit_mv && ref_mb) { + mb->type = ref_mb->type; /* copy mb_type from corresponding reference mb */ + } else if (ctx->frame_type == FRAMETYPE_INTRA || + ctx->frame_type == FRAMETYPE_INTRA1) { + mb->type = 0; /* mb_type is always INTRA for intra-frames */ + } else { + mb->type = get_bits(&ctx->gb, mb_type_bits); + } + + mb->cbp = get_bits(&ctx->gb, blks_per_mb); + + mb->q_delta = 0; + if (band->inherit_qdelta) { + if (ref_mb) mb->q_delta = ref_mb->q_delta; + } else if (mb->cbp || (!band->plane && !band->band_num && + ctx->in_q)) { + mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mb->q_delta = IVI_TOSIGNED(mb->q_delta); + } + + if (!mb->type) { + mb->mv_x = mb->mv_y = 0; /* there is no motion vector in intra-macroblocks */ + } else { + if (band->inherit_mv && ref_mb) { + /* motion vector inheritance */ + if (mv_scale) { + mb->mv_x = ivi_scale_mv(ref_mb->mv_x, mv_scale); + mb->mv_y = ivi_scale_mv(ref_mb->mv_y, mv_scale); + } else { + mb->mv_x = ref_mb->mv_x; + mb->mv_y = ref_mb->mv_y; + } + } else { + /* decode motion vector deltas */ + mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mv_y += IVI_TOSIGNED(mv_delta); + mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mv_x += IVI_TOSIGNED(mv_delta); + mb->mv_x = mv_x; + mb->mv_y = mv_y; + } + } + } + + s= band->is_halfpel; + if (mb->type) + if ( x + (mb->mv_x >>s) + (y+ (mb->mv_y >>s))*band->pitch < 0 || + x + ((mb->mv_x+s)>>s) + band->mb_size - 1 + + (y+band->mb_size - 1 +((mb->mv_y+s)>>s))*band->pitch > band->bufsize -1) { + av_log(avctx, AV_LOG_ERROR, "motion vector %d %d outside reference\n", x*s + mb->mv_x, y*s + mb->mv_y); + return AVERROR_INVALIDDATA; + } + + mb++; + if (ref_mb) + ref_mb++; + mb_offset += band->mb_size; + } + + offs += row_offset; + } + + align_get_bits(&ctx->gb); + + return 0; +} + + +/** + * Rearrange decoding and reference buffers. + * + * @param[in,out] ctx pointer to the decoder context + */ +static void switch_buffers(IVI45DecContext *ctx) +{ + switch (ctx->prev_frame_type) { + case FRAMETYPE_INTRA: + case FRAMETYPE_INTRA1: + case FRAMETYPE_INTER: + ctx->buf_switch ^= 1; + ctx->dst_buf = ctx->buf_switch; + ctx->ref_buf = ctx->buf_switch ^ 1; + break; + case FRAMETYPE_INTER_NOREF: + break; + } + + switch (ctx->frame_type) { + case FRAMETYPE_INTRA: + case FRAMETYPE_INTRA1: + ctx->buf_switch = 0; + /* FALLTHROUGH */ + case FRAMETYPE_INTER: + ctx->dst_buf = ctx->buf_switch; + ctx->ref_buf = ctx->buf_switch ^ 1; + break; + case FRAMETYPE_INTER_NOREF: + case FRAMETYPE_NULL_FIRST: + case FRAMETYPE_NULL_LAST: + break; + } +} + + +static int is_nonnull_frame(IVI45DecContext *ctx) +{ + return ctx->frame_type < FRAMETYPE_NULL_FIRST; +} + + +static av_cold int decode_init(AVCodecContext *avctx) +{ + IVI45DecContext *ctx = avctx->priv_data; + + ff_ivi_init_static_vlc(); + + /* copy rvmap tables in our context so we can apply changes to them */ + memcpy(ctx->rvmap_tabs, ff_ivi_rvmap_tabs, sizeof(ff_ivi_rvmap_tabs)); + + /* Force allocation of the internal buffers */ + /* during picture header decoding. */ + ctx->pic_conf.pic_width = 0; + ctx->pic_conf.pic_height = 0; + + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + + ctx->decode_pic_hdr = decode_pic_hdr; + ctx->decode_band_hdr = decode_band_hdr; + ctx->decode_mb_info = decode_mb_info; + ctx->switch_buffers = switch_buffers; + ctx->is_nonnull_frame = is_nonnull_frame; + + return 0; +} + + +AVCodec ff_indeo4_decoder = { + .name = "indeo4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_INDEO4, + .priv_data_size = sizeof(IVI45DecContext), + .init = decode_init, + .close = ff_ivi_decode_close, + .decode = ff_ivi_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 4"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/indeo4data.h b/ffmpeg/libavcodec/indeo4data.h new file mode 100644 index 0000000..9b8945a --- /dev/null +++ b/ffmpeg/libavcodec/indeo4data.h @@ -0,0 +1,350 @@ +/* + * Indeo Video Interactive 4 compatible decoder + * Copyright (c) 2009-2010 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * This file contains data needed for the Indeo 4 decoder. + */ + +#ifndef AVCODEC_INDEO4DATA_H +#define AVCODEC_INDEO4DATA_H + +#include +#include "dsputil.h" +#include "ivi_common.h" + +/** + * standard picture dimensions + */ +static const uint16_t ivi4_common_pic_sizes[14] = { + 640, 480, 320, 240, 160, 120, 704, 480, 352, 240, 352, 288, 176, 144 +}; + +/** + * Indeo 4 8x8 scan (zigzag) patterns + */ +static const uint8_t ivi4_alternate_scan_8x8[64] = { + 0, 8, 1, 9, 16, 24, 2, 3, 17, 25, 10, 11, 32, 40, 48, 56, + 4, 5, 6, 7, 33, 41, 49, 57, 18, 19, 26, 27, 12, 13, 14, 15, + 34, 35, 43, 42, 50, 51, 59, 58, 20, 21, 22, 23, 31, 30, 29, 28, + 36, 37, 38, 39, 47, 46, 45, 44, 52, 53, 54, 55, 63, 62, 61, 60 +}; + +static const uint8_t ivi4_alternate_scan_4x4[16] = { + 0, 1, 4, 5, 8, 12, 2, 3, 9, 13, 6, 7, 10, 11, 14, 15 +}; + +static const uint8_t ivi4_vertical_scan_4x4[16] = { + 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 +}; + +static const uint8_t ivi4_horizontal_scan_4x4[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static const uint8_t *scan_index_to_tab[15] = { + // for 8x8 transforms + ff_zigzag_direct, + ivi4_alternate_scan_8x8, + ff_ivi_horizontal_scan_8x8, + ff_ivi_vertical_scan_8x8, + ff_zigzag_direct, + + // for 4x4 transforms + ff_ivi_direct_scan_4x4, + ivi4_alternate_scan_4x4, + ivi4_vertical_scan_4x4, + ivi4_horizontal_scan_4x4, + ff_ivi_direct_scan_4x4, + + // TODO: check if those are needed + ff_ivi_horizontal_scan_8x8, + ff_ivi_horizontal_scan_8x8, + ff_ivi_horizontal_scan_8x8, + ff_ivi_horizontal_scan_8x8, + ff_ivi_horizontal_scan_8x8 +}; + +/** + * Indeo 4 dequant tables + */ +static const uint16_t ivi4_quant_8x8_intra[9][64] = { + { + 43, 342, 385, 470, 555, 555, 598, 726, + 342, 342, 470, 513, 555, 598, 726, 769, + 385, 470, 555, 555, 598, 726, 726, 811, + 470, 470, 555, 555, 598, 726, 769, 854, + 470, 555, 555, 598, 683, 726, 854, 1025, + 555, 555, 598, 683, 726, 854, 1025, 1153, + 555, 555, 598, 726, 811, 982, 1195, 1451, + 555, 598, 726, 811, 982, 1195, 1451, 1793 + }, + { + 86, 1195, 2390, 2390, 4865, 4865, 4865, 4865, + 1195, 1195, 2390, 2390, 4865, 4865, 4865, 4865, + 2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827, + 2390, 2390, 4865, 4865, 6827, 6827, 6827, 6827, + 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827, + 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827, + 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827, + 4865, 4865, 6827, 6827, 6827, 6827, 6827, 6827 + }, + { + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835, + 235, 1067, 1195, 1323, 1451, 1579, 1707, 1835 + }, + { + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414, + 1707, 1707, 3414, 3414, 3414, 3414, 3414, 3414 + }, + { + 897, 897, 897, 897, 897, 897, 897, 897, + 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, + 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, + 1409, 1409, 1409, 1409, 1409, 1409, 1409, 1409, + 1579, 1579, 1579, 1579, 1579, 1579, 1579, 1579, + 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, + 1921, 1921, 1921, 1921, 1921, 1921, 1921, 1921, + 2091, 2091, 2091, 2091, 2091, 2091, 2091, 2091 + }, + { + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414 + }, + { + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390, + 2390, 2390, 2390, 2390, 2390, 2390, 2390, 2390 + }, + { + 22, 171, 214, 257, 257, 299, 299, 342, + 171, 171, 257, 257, 299, 299, 342, 385, + 214, 257, 257, 299, 299, 342, 342, 385, + 257, 257, 257, 299, 299, 342, 385, 427, + 257, 257, 299, 299, 342, 385, 427, 513, + 257, 299, 299, 342, 385, 427, 513, 598, + 299, 299, 299, 385, 385, 470, 598, 726, + 299, 299, 385, 385, 470, 598, 726, 897 + }, + { + 86, 598, 1195, 1195, 2390, 2390, 2390, 2390, + 598, 598, 1195, 1195, 2390, 2390, 2390, 2390, + 1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414, + 1195, 1195, 2390, 2390, 3414, 3414, 3414, 3414, + 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414, + 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414, + 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414, + 2390, 2390, 3414, 3414, 3414, 3414, 3414, 3414 + } +}; + +static const uint16_t ivi4_quant_8x8_inter[9][64] = { + { + 427, 427, 470, 427, 427, 427, 470, 470, + 427, 427, 470, 427, 427, 427, 470, 470, + 470, 470, 470, 470, 470, 470, 470, 470, + 427, 427, 470, 470, 427, 427, 470, 470, + 427, 427, 470, 427, 427, 427, 470, 470, + 427, 427, 470, 427, 427, 427, 470, 470, + 470, 470, 470, 470, 470, 470, 470, 470, + 470, 470, 470, 470, 470, 470, 470, 470 + }, + { + 1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414, + 1707, 1707, 2433, 2433, 3414, 3414, 3414, 3414, + 2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822, + 2433, 2433, 3414, 3414, 4822, 4822, 4822, 4822, + 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414, + 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414, + 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414, + 3414, 3414, 4822, 4822, 3414, 3414, 3414, 3414 + }, + { + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281, + 1195, 1195, 1281, 1238, 1195, 1195, 1281, 1281 + }, + { + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433, + 2433, 2433, 3414, 3414, 2433, 2433, 2433, 2433 + }, + { + 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, + 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, + 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, + 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, + 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, + 1195, 1195, 1195, 1195, 1195, 1195, 1195, 1195, + 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, + 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281 + }, + { + 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433, + 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 3414, 3414, 3414, 3414, 3414, 3414, 3414, 3414, + 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433, + 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433, + 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433, + 2433, 2433, 2433, 2433, 2433, 2433, 2433, 2433 + }, + { + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707, + 1707, 1707, 1707, 1707, 1707, 1707, 1707, 1707 + }, + { + 86, 171, 171, 214, 214, 214, 214, 257, + 171, 171, 214, 214, 214, 214, 257, 257, + 171, 214, 214, 214, 214, 257, 257, 257, + 214, 214, 214, 214, 257, 257, 257, 299, + 214, 214, 214, 257, 257, 257, 299, 299, + 214, 214, 257, 257, 257, 299, 299, 299, + 214, 257, 257, 257, 299, 299, 299, 342, + 257, 257, 257, 299, 299, 299, 342, 342 + }, + { + 854, 854, 1195, 1195, 1707, 1707, 1707, 1707, + 854, 854, 1195, 1195, 1707, 1707, 1707, 1707, + 1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390, + 1195, 1195, 1707, 1707, 2390, 2390, 2390, 2390, + 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707, + 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707, + 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707, + 1707, 1707, 2390, 2390, 1707, 1707, 1707, 1707 + } +}; + +static const uint16_t ivi4_quant_4x4_intra[5][16] = { + { + 22, 214, 257, 299, + 214, 257, 299, 342, + 257, 299, 342, 427, + 299, 342, 427, 513 + }, + { + 129, 1025, 1451, 1451, + 1025, 1025, 1451, 1451, + 1451, 1451, 2049, 2049, + 1451, 1451, 2049, 2049 + }, + { + 43, 171, 171, 171, + 43, 171, 171, 171, + 43, 171, 171, 171, + 43, 171, 171, 171 + }, + { + 43, 43, 43, 43, + 171, 171, 171, 171, + 171, 171, 171, 171, + 171, 171, 171, 171 + }, + { + 43, 43, 43, 43, + 43, 43, 43, 43, + 43, 43, 43, 43, + 43, 43, 43, 43 + } +}; + +static const uint16_t ivi4_quant_4x4_inter[5][16] = { + { + 107, 214, 257, 299, + 214, 257, 299, 299, + 257, 299, 299, 342, + 299, 299, 342, 342 + }, + { + 513, 1025, 1238, 1238, + 1025, 1025, 1238, 1238, + 1238, 1238, 1451, 1451, + 1238, 1238, 1451, 1451 + }, + { + 43, 171, 171, 171, + 43, 171, 171, 171, + 43, 171, 171, 171, + 43, 171, 171, 171 + }, + { + 43, 43, 43, 43, + 171, 171, 171, 171, + 171, 171, 171, 171, + 171, 171, 171, 171 + }, + { + 43, 43, 43, 43, + 43, 43, 43, 43, + 43, 43, 43, 43, + 43, 43, 43, 43 + } +}; + +/** + * Table for mapping quant matrix index from the bitstream + * into internal quant table number. + */ +static const uint8_t quant_index_to_tab[22] = { + 0, 1, 0, 2, 1, 3, 0, 4, 1, 5, 0, 1, 6, 7, 8, // for 8x8 quant matrixes + 0, 1, 2, 2, 3, 3, 4 // for 4x4 quant matrixes +}; + +#endif /* AVCODEC_INDEO4DATA_H */ diff --git a/ffmpeg/libavcodec/indeo5.c b/ffmpeg/libavcodec/indeo5.c new file mode 100644 index 0000000..65bd9f2 --- /dev/null +++ b/ffmpeg/libavcodec/indeo5.c @@ -0,0 +1,676 @@ +/* + * Indeo Video Interactive v5 compatible decoder + * Copyright (c) 2009 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * Indeo Video Interactive version 5 decoder + * + * Indeo5 data is usually transported within .avi or .mov files. + * Known FOURCCs: 'IV50' + */ + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "ivi_dsp.h" +#include "ivi_common.h" +#include "indeo5data.h" + +/** + * Indeo5 frame types. + */ +enum { + FRAMETYPE_INTRA = 0, + FRAMETYPE_INTER = 1, ///< non-droppable P-frame + FRAMETYPE_INTER_SCAL = 2, ///< droppable P-frame used in the scalability mode + FRAMETYPE_INTER_NOREF = 3, ///< droppable P-frame + FRAMETYPE_NULL = 4 ///< empty frame with no data +}; + +#define IVI5_PIC_SIZE_ESC 15 + +/** + * Decode Indeo5 GOP (Group of pictures) header. + * This header is present in key frames only. + * It defines parameters for all frames in a GOP. + * + * @param[in,out] ctx ptr to the decoder context + * @param[in] avctx ptr to the AVCodecContext + * @return result code: 0 = OK, -1 = error + */ +static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx) +{ + int result, i, p, tile_size, pic_size_indx, mb_size, blk_size, is_scalable; + int quant_mat, blk_size_changed = 0; + IVIBandDesc *band, *band1, *band2; + IVIPicConfig pic_conf; + + ctx->gop_flags = get_bits(&ctx->gb, 8); + + ctx->gop_hdr_size = (ctx->gop_flags & 1) ? get_bits(&ctx->gb, 16) : 0; + + if (ctx->gop_flags & IVI5_IS_PROTECTED) + ctx->lock_word = get_bits_long(&ctx->gb, 32); + + tile_size = (ctx->gop_flags & 0x40) ? 64 << get_bits(&ctx->gb, 2) : 0; + if (tile_size > 256) { + av_log(avctx, AV_LOG_ERROR, "Invalid tile size: %d\n", tile_size); + return -1; + } + + /* decode number of wavelet bands */ + /* num_levels * 3 + 1 */ + pic_conf.luma_bands = get_bits(&ctx->gb, 2) * 3 + 1; + pic_conf.chroma_bands = get_bits1(&ctx->gb) * 3 + 1; + is_scalable = pic_conf.luma_bands != 1 || pic_conf.chroma_bands != 1; + if (is_scalable && (pic_conf.luma_bands != 4 || pic_conf.chroma_bands != 1)) { + av_log(avctx, AV_LOG_ERROR, "Scalability: unsupported subdivision! Luma bands: %d, chroma bands: %d\n", + pic_conf.luma_bands, pic_conf.chroma_bands); + return -1; + } + + pic_size_indx = get_bits(&ctx->gb, 4); + if (pic_size_indx == IVI5_PIC_SIZE_ESC) { + pic_conf.pic_height = get_bits(&ctx->gb, 13); + pic_conf.pic_width = get_bits(&ctx->gb, 13); + } else { + pic_conf.pic_height = ivi5_common_pic_sizes[pic_size_indx * 2 + 1] << 2; + pic_conf.pic_width = ivi5_common_pic_sizes[pic_size_indx * 2 ] << 2; + } + + if (ctx->gop_flags & 2) { + av_log(avctx, AV_LOG_ERROR, "YV12 picture format not supported!\n"); + return -1; + } + + pic_conf.chroma_height = (pic_conf.pic_height + 3) >> 2; + pic_conf.chroma_width = (pic_conf.pic_width + 3) >> 2; + + if (!tile_size) { + pic_conf.tile_height = pic_conf.pic_height; + pic_conf.tile_width = pic_conf.pic_width; + } else { + pic_conf.tile_height = pic_conf.tile_width = tile_size; + } + + /* check if picture layout was changed and reallocate buffers */ + if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf)) { + result = ff_ivi_init_planes(ctx->planes, &pic_conf); + if (result) { + av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n"); + return -1; + } + ctx->pic_conf = pic_conf; + ctx->is_scalable = is_scalable; + blk_size_changed = 1; /* force reallocation of the internal structures */ + } + + for (p = 0; p <= 1; p++) { + for (i = 0; i < (!p ? pic_conf.luma_bands : pic_conf.chroma_bands); i++) { + band = &ctx->planes[p].bands[i]; + + band->is_halfpel = get_bits1(&ctx->gb); + + mb_size = get_bits1(&ctx->gb); + blk_size = 8 >> get_bits1(&ctx->gb); + mb_size = blk_size << !mb_size; + + if (p==0 && blk_size==4) { + av_log(avctx, AV_LOG_ERROR, "4x4 luma blocks are unsupported!\n"); + return AVERROR_PATCHWELCOME; + } + + blk_size_changed = mb_size != band->mb_size || blk_size != band->blk_size; + if (blk_size_changed) { + band->mb_size = mb_size; + band->blk_size = blk_size; + } + + if (get_bits1(&ctx->gb)) { + av_log(avctx, AV_LOG_ERROR, "Extended transform info encountered!\n"); + return -1; + } + + /* select transform function and scan pattern according to plane and band number */ + switch ((p << 2) + i) { + case 0: + band->inv_transform = ff_ivi_inverse_slant_8x8; + band->dc_transform = ff_ivi_dc_slant_2d; + band->scan = ff_zigzag_direct; + band->transform_size= 8; + break; + + case 1: + band->inv_transform = ff_ivi_row_slant8; + band->dc_transform = ff_ivi_dc_row_slant; + band->scan = ff_ivi_vertical_scan_8x8; + band->transform_size= 8; + break; + + case 2: + band->inv_transform = ff_ivi_col_slant8; + band->dc_transform = ff_ivi_dc_col_slant; + band->scan = ff_ivi_horizontal_scan_8x8; + band->transform_size= 8; + break; + + case 3: + band->inv_transform = ff_ivi_put_pixels_8x8; + band->dc_transform = ff_ivi_put_dc_pixel_8x8; + band->scan = ff_ivi_horizontal_scan_8x8; + band->transform_size= 8; + break; + + case 4: + band->inv_transform = ff_ivi_inverse_slant_4x4; + band->dc_transform = ff_ivi_dc_slant_2d; + band->scan = ff_ivi_direct_scan_4x4; + band->transform_size= 4; + break; + } + + band->is_2d_trans = band->inv_transform == ff_ivi_inverse_slant_8x8 || + band->inv_transform == ff_ivi_inverse_slant_4x4; + + /* select dequant matrix according to plane and band number */ + if (!p) { + quant_mat = (pic_conf.luma_bands > 1) ? i+1 : 0; + } else { + quant_mat = 5; + } + + if (band->blk_size == 8) { + if(quant_mat >= 5){ + av_log(avctx, AV_LOG_ERROR, "quant_mat %d too large!\n", quant_mat); + return -1; + } + band->intra_base = &ivi5_base_quant_8x8_intra[quant_mat][0]; + band->inter_base = &ivi5_base_quant_8x8_inter[quant_mat][0]; + band->intra_scale = &ivi5_scale_quant_8x8_intra[quant_mat][0]; + band->inter_scale = &ivi5_scale_quant_8x8_inter[quant_mat][0]; + } else { + band->intra_base = ivi5_base_quant_4x4_intra; + band->inter_base = ivi5_base_quant_4x4_inter; + band->intra_scale = ivi5_scale_quant_4x4_intra; + band->inter_scale = ivi5_scale_quant_4x4_inter; + } + + if (get_bits(&ctx->gb, 2)) { + av_log(avctx, AV_LOG_ERROR, "End marker missing!\n"); + return -1; + } + } + } + + /* copy chroma parameters into the 2nd chroma plane */ + for (i = 0; i < pic_conf.chroma_bands; i++) { + band1 = &ctx->planes[1].bands[i]; + band2 = &ctx->planes[2].bands[i]; + + band2->width = band1->width; + band2->height = band1->height; + band2->mb_size = band1->mb_size; + band2->blk_size = band1->blk_size; + band2->is_halfpel = band1->is_halfpel; + band2->intra_base = band1->intra_base; + band2->inter_base = band1->inter_base; + band2->intra_scale = band1->intra_scale; + band2->inter_scale = band1->inter_scale; + band2->scan = band1->scan; + band2->inv_transform = band1->inv_transform; + band2->dc_transform = band1->dc_transform; + band2->is_2d_trans = band1->is_2d_trans; + band2->transform_size= band1->transform_size; + } + + /* reallocate internal structures if needed */ + if (blk_size_changed) { + result = ff_ivi_init_tiles(ctx->planes, pic_conf.tile_width, + pic_conf.tile_height); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Couldn't reallocate internal structures!\n"); + return -1; + } + } + + if (ctx->gop_flags & 8) { + if (get_bits(&ctx->gb, 3)) { + av_log(avctx, AV_LOG_ERROR, "Alignment bits are not zero!\n"); + return -1; + } + + if (get_bits1(&ctx->gb)) + skip_bits_long(&ctx->gb, 24); /* skip transparency fill color */ + } + + align_get_bits(&ctx->gb); + + skip_bits(&ctx->gb, 23); /* FIXME: unknown meaning */ + + /* skip GOP extension if any */ + if (get_bits1(&ctx->gb)) { + do { + i = get_bits(&ctx->gb, 16); + } while (i & 0x8000); + } + + align_get_bits(&ctx->gb); + + return 0; +} + + +/** + * Skip a header extension. + * + * @param[in,out] gb the GetBit context + */ +static inline void skip_hdr_extension(GetBitContext *gb) +{ + int i, len; + + do { + len = get_bits(gb, 8); + for (i = 0; i < len; i++) skip_bits(gb, 8); + } while(len); +} + + +/** + * Decode Indeo5 picture header. + * + * @param[in,out] ctx ptr to the decoder context + * @param[in] avctx ptr to the AVCodecContext + * @return result code: 0 = OK, -1 = error + */ +static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx) +{ + if (get_bits(&ctx->gb, 5) != 0x1F) { + av_log(avctx, AV_LOG_ERROR, "Invalid picture start code!\n"); + return -1; + } + + ctx->prev_frame_type = ctx->frame_type; + ctx->frame_type = get_bits(&ctx->gb, 3); + if (ctx->frame_type >= 5) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame type: %d \n", ctx->frame_type); + return -1; + } + + ctx->frame_num = get_bits(&ctx->gb, 8); + + if (ctx->frame_type == FRAMETYPE_INTRA) { + ctx->gop_invalid = 1; + if (decode_gop_header(ctx, avctx)) { + av_log(avctx, AV_LOG_ERROR, "Invalid GOP header, skipping frames.\n"); + return AVERROR_INVALIDDATA; + } + ctx->gop_invalid = 0; + } + + if (ctx->frame_type == FRAMETYPE_INTER_SCAL && !ctx->is_scalable) { + av_log(avctx, AV_LOG_ERROR, "Scalable inter frame in non scaleable stream\n"); + ctx->frame_type = FRAMETYPE_INTER; + return AVERROR_INVALIDDATA; + } + + if (ctx->frame_type != FRAMETYPE_NULL) { + ctx->frame_flags = get_bits(&ctx->gb, 8); + + ctx->pic_hdr_size = (ctx->frame_flags & 1) ? get_bits_long(&ctx->gb, 24) : 0; + + ctx->checksum = (ctx->frame_flags & 0x10) ? get_bits(&ctx->gb, 16) : 0; + + /* skip unknown extension if any */ + if (ctx->frame_flags & 0x20) + skip_hdr_extension(&ctx->gb); /* XXX: untested */ + + /* decode macroblock huffman codebook */ + if (ff_ivi_dec_huff_desc(&ctx->gb, ctx->frame_flags & 0x40, IVI_MB_HUFF, &ctx->mb_vlc, avctx)) + return -1; + + skip_bits(&ctx->gb, 3); /* FIXME: unknown meaning! */ + } + + align_get_bits(&ctx->gb); + + return 0; +} + + +/** + * Decode Indeo5 band header. + * + * @param[in,out] ctx ptr to the decoder context + * @param[in,out] band ptr to the band descriptor + * @param[in] avctx ptr to the AVCodecContext + * @return result code: 0 = OK, -1 = error + */ +static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band, + AVCodecContext *avctx) +{ + int i; + uint8_t band_flags; + + band_flags = get_bits(&ctx->gb, 8); + + if (band_flags & 1) { + band->is_empty = 1; + return 0; + } + + band->data_size = (ctx->frame_flags & 0x80) ? get_bits_long(&ctx->gb, 24) : 0; + + band->inherit_mv = band_flags & 2; + band->inherit_qdelta = band_flags & 8; + band->qdelta_present = band_flags & 4; + if (!band->qdelta_present) band->inherit_qdelta = 1; + + /* decode rvmap probability corrections if any */ + band->num_corr = 0; /* there are no corrections */ + if (band_flags & 0x10) { + band->num_corr = get_bits(&ctx->gb, 8); /* get number of correction pairs */ + if (band->num_corr > 61) { + av_log(avctx, AV_LOG_ERROR, "Too many corrections: %d\n", + band->num_corr); + return -1; + } + + /* read correction pairs */ + for (i = 0; i < band->num_corr * 2; i++) + band->corr[i] = get_bits(&ctx->gb, 8); + } + + /* select appropriate rvmap table for this band */ + band->rvmap_sel = (band_flags & 0x40) ? get_bits(&ctx->gb, 3) : 8; + + /* decode block huffman codebook */ + if (ff_ivi_dec_huff_desc(&ctx->gb, band_flags & 0x80, IVI_BLK_HUFF, &band->blk_vlc, avctx)) + return -1; + + band->checksum_present = get_bits1(&ctx->gb); + if (band->checksum_present) + band->checksum = get_bits(&ctx->gb, 16); + + band->glob_quant = get_bits(&ctx->gb, 5); + + /* skip unknown extension if any */ + if (band_flags & 0x20) { /* XXX: untested */ + align_get_bits(&ctx->gb); + skip_hdr_extension(&ctx->gb); + } + + align_get_bits(&ctx->gb); + + return 0; +} + + +/** + * Decode info (block type, cbp, quant delta, motion vector) + * for all macroblocks in the current tile. + * + * @param[in,out] ctx ptr to the decoder context + * @param[in,out] band ptr to the band descriptor + * @param[in,out] tile ptr to the tile descriptor + * @param[in] avctx ptr to the AVCodecContext + * @return result code: 0 = OK, -1 = error + */ +static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band, + IVITile *tile, AVCodecContext *avctx) +{ + int x, y, mv_x, mv_y, mv_delta, offs, mb_offset, + mv_scale, blks_per_mb, s; + IVIMbInfo *mb, *ref_mb; + int row_offset = band->mb_size * band->pitch; + + mb = tile->mbs; + ref_mb = tile->ref_mbs; + offs = tile->ypos * band->pitch + tile->xpos; + + if (!ref_mb && + ((band->qdelta_present && band->inherit_qdelta) || band->inherit_mv)) + return AVERROR_INVALIDDATA; + + if (tile->num_MBs != IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)) { + av_log(avctx, AV_LOG_ERROR, "Allocated tile size %d mismatches parameters %d\n", + tile->num_MBs, IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)); + return AVERROR_INVALIDDATA; + } + + /* scale factor for motion vectors */ + mv_scale = (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3); + mv_x = mv_y = 0; + + for (y = tile->ypos; y < (tile->ypos + tile->height); y += band->mb_size) { + mb_offset = offs; + + for (x = tile->xpos; x < (tile->xpos + tile->width); x += band->mb_size) { + mb->xpos = x; + mb->ypos = y; + mb->buf_offs = mb_offset; + + if (get_bits1(&ctx->gb)) { + if (ctx->frame_type == FRAMETYPE_INTRA) { + av_log(avctx, AV_LOG_ERROR, "Empty macroblock in an INTRA picture!\n"); + return -1; + } + mb->type = 1; /* empty macroblocks are always INTER */ + mb->cbp = 0; /* all blocks are empty */ + + mb->q_delta = 0; + if (!band->plane && !band->band_num && (ctx->frame_flags & 8)) { + mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mb->q_delta = IVI_TOSIGNED(mb->q_delta); + } + + mb->mv_x = mb->mv_y = 0; /* no motion vector coded */ + if (band->inherit_mv && ref_mb){ + /* motion vector inheritance */ + if (mv_scale) { + mb->mv_x = ivi_scale_mv(ref_mb->mv_x, mv_scale); + mb->mv_y = ivi_scale_mv(ref_mb->mv_y, mv_scale); + } else { + mb->mv_x = ref_mb->mv_x; + mb->mv_y = ref_mb->mv_y; + } + } + } else { + if (band->inherit_mv && ref_mb) { + mb->type = ref_mb->type; /* copy mb_type from corresponding reference mb */ + } else if (ctx->frame_type == FRAMETYPE_INTRA) { + mb->type = 0; /* mb_type is always INTRA for intra-frames */ + } else { + mb->type = get_bits1(&ctx->gb); + } + + blks_per_mb = band->mb_size != band->blk_size ? 4 : 1; + mb->cbp = get_bits(&ctx->gb, blks_per_mb); + + mb->q_delta = 0; + if (band->qdelta_present) { + if (band->inherit_qdelta) { + if (ref_mb) mb->q_delta = ref_mb->q_delta; + } else if (mb->cbp || (!band->plane && !band->band_num && + (ctx->frame_flags & 8))) { + mb->q_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mb->q_delta = IVI_TOSIGNED(mb->q_delta); + } + } + + if (!mb->type) { + mb->mv_x = mb->mv_y = 0; /* there is no motion vector in intra-macroblocks */ + } else { + if (band->inherit_mv && ref_mb){ + /* motion vector inheritance */ + if (mv_scale) { + mb->mv_x = ivi_scale_mv(ref_mb->mv_x, mv_scale); + mb->mv_y = ivi_scale_mv(ref_mb->mv_y, mv_scale); + } else { + mb->mv_x = ref_mb->mv_x; + mb->mv_y = ref_mb->mv_y; + } + } else { + /* decode motion vector deltas */ + mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mv_y += IVI_TOSIGNED(mv_delta); + mv_delta = get_vlc2(&ctx->gb, ctx->mb_vlc.tab->table, + IVI_VLC_BITS, 1); + mv_x += IVI_TOSIGNED(mv_delta); + mb->mv_x = mv_x; + mb->mv_y = mv_y; + } + } + } + + s= band->is_halfpel; + if (mb->type) + if ( x + (mb->mv_x >>s) + (y+ (mb->mv_y >>s))*band->pitch < 0 || + x + ((mb->mv_x+s)>>s) + band->mb_size - 1 + + (y+band->mb_size - 1 +((mb->mv_y+s)>>s))*band->pitch > band->bufsize - 1) { + av_log(avctx, AV_LOG_ERROR, "motion vector %d %d outside reference\n", x*s + mb->mv_x, y*s + mb->mv_y); + return AVERROR_INVALIDDATA; + } + + mb++; + if (ref_mb) + ref_mb++; + mb_offset += band->mb_size; + } + + offs += row_offset; + } + + align_get_bits(&ctx->gb); + + return 0; +} + + +/** + * Switch buffers. + * + * @param[in,out] ctx ptr to the decoder context + */ +static void switch_buffers(IVI45DecContext *ctx) +{ + switch (ctx->prev_frame_type) { + case FRAMETYPE_INTRA: + case FRAMETYPE_INTER: + ctx->buf_switch ^= 1; + ctx->dst_buf = ctx->buf_switch; + ctx->ref_buf = ctx->buf_switch ^ 1; + break; + case FRAMETYPE_INTER_SCAL: + if (!ctx->inter_scal) { + ctx->ref2_buf = 2; + ctx->inter_scal = 1; + } + FFSWAP(int, ctx->dst_buf, ctx->ref2_buf); + ctx->ref_buf = ctx->ref2_buf; + break; + case FRAMETYPE_INTER_NOREF: + break; + } + + switch (ctx->frame_type) { + case FRAMETYPE_INTRA: + ctx->buf_switch = 0; + /* FALLTHROUGH */ + case FRAMETYPE_INTER: + ctx->inter_scal = 0; + ctx->dst_buf = ctx->buf_switch; + ctx->ref_buf = ctx->buf_switch ^ 1; + break; + case FRAMETYPE_INTER_SCAL: + case FRAMETYPE_INTER_NOREF: + case FRAMETYPE_NULL: + break; + } +} + + +static int is_nonnull_frame(IVI45DecContext *ctx) +{ + return ctx->frame_type != FRAMETYPE_NULL; +} + + +/** + * Initialize Indeo5 decoder. + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + IVI45DecContext *ctx = avctx->priv_data; + int result; + + ff_ivi_init_static_vlc(); + + /* copy rvmap tables in our context so we can apply changes to them */ + memcpy(ctx->rvmap_tabs, ff_ivi_rvmap_tabs, sizeof(ff_ivi_rvmap_tabs)); + + /* set the initial picture layout according to the basic profile: + there is only one band per plane (no scalability), only one tile (no local decoding) + and picture format = YVU9 */ + ctx->pic_conf.pic_width = avctx->width; + ctx->pic_conf.pic_height = avctx->height; + ctx->pic_conf.chroma_width = (avctx->width + 3) >> 2; + ctx->pic_conf.chroma_height = (avctx->height + 3) >> 2; + ctx->pic_conf.tile_width = avctx->width; + ctx->pic_conf.tile_height = avctx->height; + ctx->pic_conf.luma_bands = ctx->pic_conf.chroma_bands = 1; + + result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf); + if (result) { + av_log(avctx, AV_LOG_ERROR, "Couldn't allocate color planes!\n"); + return -1; + } + + ctx->buf_switch = 0; + ctx->inter_scal = 0; + + ctx->decode_pic_hdr = decode_pic_hdr; + ctx->decode_band_hdr = decode_band_hdr; + ctx->decode_mb_info = decode_mb_info; + ctx->switch_buffers = switch_buffers; + ctx->is_nonnull_frame = is_nonnull_frame; + + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + + return 0; +} + +AVCodec ff_indeo5_decoder = { + .name = "indeo5", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_INDEO5, + .priv_data_size = sizeof(IVI45DecContext), + .init = decode_init, + .close = ff_ivi_decode_close, + .decode = ff_ivi_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 5"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/indeo5data.h b/ffmpeg/libavcodec/indeo5data.h new file mode 100644 index 0000000..a6217d0 --- /dev/null +++ b/ffmpeg/libavcodec/indeo5data.h @@ -0,0 +1,162 @@ +/* + * Indeo Video Interactive 5 compatible decoder + * Copyright (c) 2009 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * This file contains data needed for the Indeo5 decoder. + */ + +#ifndef AVCODEC_INDEO5DATA_H +#define AVCODEC_INDEO5DATA_H + +#include + +/** + * standard picture dimensions (width, height divided by 4) + */ +static const uint8_t ivi5_common_pic_sizes[30] = { + 160, 120, 80, 60, 40, 30, 176, 120, 88, 60, 88, 72, 44, 36, 60, 45, 160, 60, + 176, 60, 20, 15, 22, 18, 0, 0, 0, 0, 0, 0 +}; + + +/** + * Indeo5 dequantization matrixes consist of two tables: base table + * and scale table. The base table defines the dequantization matrix + * itself and the scale table tells how this matrix should be scaled + * for a particular quant level (0...24). + * + * ivi5_base_quant_bbb_ttt - base tables for block size 'bbb' of type 'ttt' + * ivi5_scale_quant_bbb_ttt - scale tables for block size 'bbb' of type 'ttt' + */ +static const uint16_t ivi5_base_quant_8x8_inter[5][64] = { + {0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a, 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e, + 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62, 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66, + 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a, 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e, + 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76, + }, + {0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a, 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e, + 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62, 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66, + 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a, 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e, + 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76, + }, + {0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + }, + {0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + }, + {0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + } +}; + +static const uint16_t ivi5_base_quant_8x8_intra[5][64] = { + {0x1a, 0x2e, 0x36, 0x42, 0x46, 0x4a, 0x4e, 0x5a, 0x2e, 0x32, 0x3e, 0x42, 0x46, 0x4e, 0x56, 0x6a, + 0x36, 0x3e, 0x3e, 0x44, 0x4a, 0x54, 0x66, 0x72, 0x42, 0x42, 0x44, 0x4a, 0x52, 0x62, 0x6c, 0x7a, + 0x46, 0x46, 0x4a, 0x52, 0x5e, 0x66, 0x72, 0x8e, 0x4a, 0x4e, 0x54, 0x62, 0x66, 0x6e, 0x86, 0xa6, + 0x4e, 0x56, 0x66, 0x6c, 0x72, 0x86, 0x9a, 0xca, 0x5a, 0x6a, 0x72, 0x7a, 0x8e, 0xa6, 0xca, 0xfe, + }, + {0x26, 0x3a, 0x3e, 0x46, 0x4a, 0x4e, 0x52, 0x5a, 0x3a, 0x3e, 0x42, 0x46, 0x4a, 0x4e, 0x56, 0x5e, + 0x3e, 0x42, 0x46, 0x48, 0x4c, 0x52, 0x5a, 0x62, 0x46, 0x46, 0x48, 0x4a, 0x4e, 0x56, 0x5e, 0x66, + 0x4a, 0x4a, 0x4c, 0x4e, 0x52, 0x5a, 0x62, 0x6a, 0x4e, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x66, 0x6e, + 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x72, 0x5a, 0x5e, 0x62, 0x66, 0x6a, 0x6e, 0x72, 0x76, + }, + {0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, 0x4e, 0xaa, 0xf2, 0xd4, 0xde, 0xc2, 0xd6, 0xc2, + }, + {0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, + }, + {0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, + } +}; + +static const uint16_t ivi5_base_quant_4x4_inter[16] = { + 0x1e, 0x3e, 0x4a, 0x52, 0x3e, 0x4a, 0x52, 0x56, 0x4a, 0x52, 0x56, 0x5e, 0x52, 0x56, 0x5e, 0x66 +}; + +static const uint16_t ivi5_base_quant_4x4_intra[16] = { + 0x1e, 0x3e, 0x4a, 0x52, 0x3e, 0x4a, 0x52, 0x5e, 0x4a, 0x52, 0x5e, 0x7a, 0x52, 0x5e, 0x7a, 0x92 +}; + + +static const uint8_t ivi5_scale_quant_8x8_inter[5][24] = { + {0x0b, 0x11, 0x13, 0x14, 0x15, 0x16, 0x18, 0x1a, 0x1b, 0x1d, 0x20, 0x22, + 0x23, 0x25, 0x28, 0x2a, 0x2e, 0x32, 0x35, 0x39, 0x3d, 0x41, 0x44, 0x4a, + }, + {0x07, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x29, 0x2d, 0x31, 0x35, + 0x3a, 0x3f, 0x44, 0x4a, 0x50, 0x56, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x7e, + }, + {0x15, 0x25, 0x28, 0x2d, 0x30, 0x34, 0x3a, 0x3d, 0x42, 0x48, 0x4c, 0x51, + 0x56, 0x5b, 0x60, 0x65, 0x6b, 0x70, 0x76, 0x7c, 0x82, 0x88, 0x8f, 0x97, + }, + {0x13, 0x1f, 0x20, 0x22, 0x25, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36, 0x39, + 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x5e, 0x62, + }, + {0x3c, 0x52, 0x58, 0x5d, 0x63, 0x68, 0x68, 0x6d, 0x73, 0x78, 0x7c, 0x80, + 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa3, 0xa9, 0xad, 0xb1, 0xb5, 0xba, + }, +}; + +static const uint8_t ivi5_scale_quant_8x8_intra[5][24] = { + {0x0b, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x20, + 0x22, 0x24, 0x27, 0x28, 0x2a, 0x2d, 0x2f, 0x31, 0x34, 0x37, 0x39, 0x3c, + }, + {0x01, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1b, 0x1e, 0x22, 0x25, 0x28, 0x2c, + 0x30, 0x34, 0x38, 0x3d, 0x42, 0x47, 0x4c, 0x52, 0x58, 0x5e, 0x65, 0x6c, + }, + {0x13, 0x22, 0x27, 0x2a, 0x2d, 0x33, 0x36, 0x3c, 0x41, 0x45, 0x49, 0x4e, + 0x53, 0x58, 0x5d, 0x63, 0x69, 0x6f, 0x75, 0x7c, 0x82, 0x88, 0x8e, 0x95, + }, + {0x13, 0x1f, 0x21, 0x24, 0x27, 0x29, 0x2d, 0x2f, 0x34, 0x37, 0x3a, 0x3d, + 0x40, 0x44, 0x48, 0x4c, 0x4f, 0x52, 0x56, 0x5a, 0x5e, 0x62, 0x66, 0x6b, + }, + {0x31, 0x42, 0x47, 0x47, 0x4d, 0x52, 0x58, 0x58, 0x5d, 0x63, 0x67, 0x6b, + 0x6f, 0x73, 0x78, 0x7c, 0x80, 0x84, 0x89, 0x8e, 0x93, 0x98, 0x9d, 0xa4, + } +}; + +static const uint8_t ivi5_scale_quant_4x4_inter[24] = { + 0x0b, 0x0d, 0x0d, 0x0e, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, +}; + +static const uint8_t ivi5_scale_quant_4x4_intra[24] = { + 0x01, 0x0b, 0x0b, 0x0d, 0x0d, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 +}; + + +#endif /* AVCODEC_INDEO5DATA_H */ diff --git a/ffmpeg/libavcodec/intelh263dec.c b/ffmpeg/libavcodec/intelh263dec.c new file mode 100644 index 0000000..ac2695e --- /dev/null +++ b/ffmpeg/libavcodec/intelh263dec.c @@ -0,0 +1,138 @@ +/* + * H.263i decoder + * + * 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 "mpegvideo.h" +#include "h263.h" + +/* don't understand why they choose a different header ! */ +int ff_intel_h263_decode_picture_header(MpegEncContext *s) +{ + int format; + + /* picture header */ + if (get_bits_long(&s->gb, 22) != 0x20) { + av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); + return -1; + } + s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */ + + if (get_bits1(&s->gb) != 1) { + av_log(s->avctx, AV_LOG_ERROR, "Bad marker\n"); + return -1; /* marker */ + } + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "Bad H263 id\n"); + return -1; /* h263 id */ + } + skip_bits1(&s->gb); /* split screen off */ + skip_bits1(&s->gb); /* camera off */ + skip_bits1(&s->gb); /* freeze picture release off */ + + format = get_bits(&s->gb, 3); + if (format == 0 || format == 6) { + av_log(s->avctx, AV_LOG_ERROR, "Intel H263 free format not supported\n"); + return -1; + } + s->h263_plus = 0; + + s->pict_type = AV_PICTURE_TYPE_I + get_bits1(&s->gb); + + s->h263_long_vectors = get_bits1(&s->gb); + + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "SAC not supported\n"); + return -1; /* SAC: off */ + } + s->obmc= get_bits1(&s->gb); + s->unrestricted_mv = s->obmc || s->h263_long_vectors; + s->pb_frame = get_bits1(&s->gb); + + if (format < 6) { + s->width = ff_h263_format[format][0]; + s->height = ff_h263_format[format][1]; + s->avctx->sample_aspect_ratio.num = 12; + s->avctx->sample_aspect_ratio.den = 11; + } else { + format = get_bits(&s->gb, 3); + if(format == 0 || format == 7){ + av_log(s->avctx, AV_LOG_ERROR, "Wrong Intel H263 format\n"); + return -1; + } + if(get_bits(&s->gb, 2)) + av_log(s->avctx, AV_LOG_ERROR, "Bad value for reserved field\n"); + s->loop_filter = get_bits1(&s->gb) * !s->avctx->lowres; + if(get_bits1(&s->gb)) + av_log(s->avctx, AV_LOG_ERROR, "Bad value for reserved field\n"); + if(get_bits1(&s->gb)) + s->pb_frame = 2; + if(get_bits(&s->gb, 5)) + av_log(s->avctx, AV_LOG_ERROR, "Bad value for reserved field\n"); + if(get_bits(&s->gb, 5) != 1) + av_log(s->avctx, AV_LOG_ERROR, "Invalid marker\n"); + } + if(format == 6){ + int ar = get_bits(&s->gb, 4); + skip_bits(&s->gb, 9); // display width + skip_bits1(&s->gb); + skip_bits(&s->gb, 9); // display height + if(ar == 15){ + s->avctx->sample_aspect_ratio.num = get_bits(&s->gb, 8); // aspect ratio - width + s->avctx->sample_aspect_ratio.den = get_bits(&s->gb, 8); // aspect ratio - height + } else { + s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[ar]; + } + if (s->avctx->sample_aspect_ratio.num == 0) + av_log(s->avctx, AV_LOG_ERROR, "Invalid aspect ratio.\n"); + } + + s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */ + + if(s->pb_frame){ + skip_bits(&s->gb, 3); //temporal reference for B-frame + skip_bits(&s->gb, 2); //dbquant + } + + /* PEI */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + s->f_code = 1; + + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + + ff_h263_show_pict_info(s); + + return 0; +} + +AVCodec ff_h263i_decoder = { + .name = "h263i", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263I, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_h263_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Intel H.263"), + .pix_fmts = ff_pixfmt_list_420, +}; diff --git a/ffmpeg/libavcodec/internal.h b/ffmpeg/libavcodec/internal.h new file mode 100644 index 0000000..e51757f --- /dev/null +++ b/ffmpeg/libavcodec/internal.h @@ -0,0 +1,230 @@ +/* + * 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 + */ + +/** + * @file + * common internal api header. + */ + +#ifndef AVCODEC_INTERNAL_H +#define AVCODEC_INTERNAL_H + +#include + +#include "libavutil/buffer.h" +#include "libavutil/mathematics.h" +#include "libavutil/pixfmt.h" +#include "avcodec.h" + +#define FF_SANE_NB_CHANNELS 63U + +typedef struct FramePool { + /** + * Pools for each data plane. For audio all the planes have the same size, + * so only pools[0] is used. + */ + AVBufferPool *pools[4]; + + /* + * Pool parameters + */ + int format; + int width, height; + int stride_align[AV_NUM_DATA_POINTERS]; + int linesize[4]; + int planes; + int channels; + int samples; +} FramePool; + +typedef struct AVCodecInternal { + /** + * Whether the parent AVCodecContext is a copy of the context which had + * init() called on it. + * This is used by multithreading - shared tables and picture pointers + * should be freed from the original context only. + */ + int is_copy; + + /** + * Whether to allocate progress for frame threading. + * + * The codec must set it to 1 if it uses ff_thread_await/report_progress(), + * then progress will be allocated in ff_thread_get_buffer(). The frames + * then MUST be freed with ff_thread_release_buffer(). + * + * If the codec does not need to call the progress functions (there are no + * dependencies between the frames), it should leave this at 0. Then it can + * decode straight to the user-provided frames (which the user will then + * free with av_frame_unref()), there is no need to call + * ff_thread_release_buffer(). + */ + int allocate_progress; + +#if FF_API_OLD_ENCODE_AUDIO + /** + * Internal sample count used by avcodec_encode_audio() to fabricate pts. + * Can be removed along with avcodec_encode_audio(). + */ + int sample_count; +#endif + + /** + * An audio frame with less than required samples has been submitted and + * padded with silence. Reject all subsequent frames. + */ + int last_audio_frame; + + AVFrame to_free; + + FramePool *pool; + + /** + * temporary buffer used for encoders to store their bitstream + */ + uint8_t *byte_buffer; + unsigned int byte_buffer_size; + + void *frame_thread_encoder; + + /** + * Number of audio samples to skip at the start of the next decoded frame + */ + int skip_samples; +} AVCodecInternal; + +struct AVCodecDefault { + const uint8_t *key; + const uint8_t *value; +}; + +/** + * Return the hardware accelerated codec for codec codec_id and + * pixel format pix_fmt. + * + * @param codec_id the codec to match + * @param pix_fmt the pixel format to match + * @return the hardware accelerated codec, or NULL if none was found. + */ +AVHWAccel *ff_find_hwaccel(enum AVCodecID codec_id, enum AVPixelFormat pix_fmt); + +/** + * Return the index into tab at which {a,b} match elements {[0],[1]} of tab. + * If there is no such matching pair then size is returned. + */ +int ff_match_2uint16(const uint16_t (*tab)[2], int size, int a, int b); + +unsigned int avpriv_toupper4(unsigned int x); + +/** + * does needed setup of pkt_pts/pos and such for (re)get_buffer(); + */ +int ff_init_buffer_info(AVCodecContext *s, AVFrame *frame); + + +void avpriv_color_frame(AVFrame *frame, const int color[4]); + +/** + * Remove and free all side data from packet. + */ +void ff_packet_free_side_data(AVPacket *pkt); + +extern volatile int ff_avcodec_locked; +int ff_lock_avcodec(AVCodecContext *log_ctx); +int ff_unlock_avcodec(void); + +int avpriv_lock_avformat(void); +int avpriv_unlock_avformat(void); + +/** + * Maximum size in bytes of extradata. + * This value was chosen such that every bit of the buffer is + * addressable by a 32-bit signed integer as used by get_bits. + */ +#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - FF_INPUT_BUFFER_PADDING_SIZE) + +/** + * Check AVPacket size and/or allocate data. + * + * Encoders supporting AVCodec.encode2() can use this as a convenience to + * ensure the output packet data is large enough, whether provided by the user + * or allocated in this function. + * + * @param avctx the AVCodecContext of the encoder + * @param avpkt the AVPacket + * If avpkt->data is already set, avpkt->size is checked + * to ensure it is large enough. + * If avpkt->data is NULL, a new buffer is allocated. + * avpkt->size is set to the specified size. + * All other AVPacket fields will be reset with av_init_packet(). + * @param size the minimum required packet size + * @return 0 on success, negative error code on failure + */ +int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size); + +int ff_alloc_packet(AVPacket *avpkt, int size); + +/** + * Rescale from sample rate to AVCodecContext.time_base. + */ +static av_always_inline int64_t ff_samples_to_time_base(AVCodecContext *avctx, + int64_t samples) +{ + if(samples == AV_NOPTS_VALUE) + return AV_NOPTS_VALUE; + return av_rescale_q(samples, (AVRational){ 1, avctx->sample_rate }, + avctx->time_base); +} + +/** + * Get a buffer for a frame. This is a wrapper around + * AVCodecContext.get_buffer() and should be used instead calling get_buffer() + * directly. + */ +int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags); + +/** + * Identical in function to av_frame_make_writable(), except it uses + * ff_get_buffer() to allocate the buffer when needed. + */ +int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame); + +int ff_thread_can_start_frame(AVCodecContext *avctx); + +int ff_get_logical_cpus(AVCodecContext *avctx); + +int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx); + +/** + * Call avcodec_open2 recursively by decrementing counter, unlocking mutex, + * calling the function and then restoring again. Assumes the mutex is + * already locked + */ +int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); + +/** + * Call avcodec_close recursively, counterpart to avcodec_open2_recursive. + */ +int ff_codec_close_recursive(AVCodecContext *avctx); + +/** + * Finalize buf into extradata and set its size appropriately. + */ +int avpriv_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf); + +#endif /* AVCODEC_INTERNAL_H */ diff --git a/ffmpeg/libavcodec/interplayvideo.c b/ffmpeg/libavcodec/interplayvideo.c new file mode 100644 index 0000000..4f710b8 --- /dev/null +++ b/ffmpeg/libavcodec/interplayvideo.c @@ -0,0 +1,1027 @@ +/* + * Interplay MVE Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Interplay MVE Video Decoder by Mike Melanson (melanson@pcisys.net) + * For more information about the Interplay MVE format, visit: + * http://www.pcisys.net/~melanson/codecs/interplay-mve.txt + * This code is written in such a way that the identifiers match up + * with the encoding descriptions in the document. + * + * This decoder presently only supports a PAL8 output colorspace. + * + * An Interplay video frame consists of 2 parts: The decoding map and + * the video data. A demuxer must load these 2 parts together in a single + * buffer before sending it through the stream to this decoder. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "hpeldsp.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" + +#define PALETTE_COUNT 256 + +typedef struct IpvideoContext { + + AVCodecContext *avctx; + HpelDSPContext hdsp; + AVFrame *second_last_frame; + AVFrame *last_frame; + const unsigned char *decoding_map; + int decoding_map_size; + + int is_16bpp; + GetByteContext stream_ptr, mv_ptr; + unsigned char *pixel_ptr; + int line_inc; + int stride; + int upper_motion_limit_offset; + + uint32_t pal[256]; +} IpvideoContext; + +static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y) +{ + int current_offset = s->pixel_ptr - dst->data[0]; + int motion_offset = current_offset + delta_y * dst->linesize[0] + + delta_x * (1 + s->is_16bpp); + if (motion_offset < 0) { + av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset); + return AVERROR_INVALIDDATA; + } else if (motion_offset > s->upper_motion_limit_offset) { + av_log(s->avctx, AV_LOG_ERROR, "motion offset above limit (%d >= %d)\n", + motion_offset, s->upper_motion_limit_offset); + return AVERROR_INVALIDDATA; + } + if (src->data[0] == NULL) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid decode type, corrupted header?\n"); + return AVERROR(EINVAL); + } + s->hdsp.put_pixels_tab[!s->is_16bpp][0](s->pixel_ptr, src->data[0] + motion_offset, + dst->linesize[0], 8); + return 0; +} + +static int ipvideo_decode_block_opcode_0x0(IpvideoContext *s, AVFrame *frame) +{ + return copy_from(s, s->last_frame, frame, 0, 0); +} + +static int ipvideo_decode_block_opcode_0x1(IpvideoContext *s, AVFrame *frame) +{ + return copy_from(s, s->second_last_frame, frame, 0, 0); +} + +static int ipvideo_decode_block_opcode_0x2(IpvideoContext *s, AVFrame *frame) +{ + unsigned char B; + int x, y; + + /* copy block from 2 frames ago using a motion vector; need 1 more byte */ + if (!s->is_16bpp) { + B = bytestream2_get_byte(&s->stream_ptr); + } else { + B = bytestream2_get_byte(&s->mv_ptr); + } + + if (B < 56) { + x = 8 + (B % 7); + y = B / 7; + } else { + x = -14 + ((B - 56) % 29); + y = 8 + ((B - 56) / 29); + } + + av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + return copy_from(s, s->second_last_frame, frame, x, y); +} + +static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s, AVFrame *frame) +{ + unsigned char B; + int x, y; + + /* copy 8x8 block from current frame from an up/left block */ + + /* need 1 more byte for motion */ + if (!s->is_16bpp) { + B = bytestream2_get_byte(&s->stream_ptr); + } else { + B = bytestream2_get_byte(&s->mv_ptr); + } + + if (B < 56) { + x = -(8 + (B % 7)); + y = -(B / 7); + } else { + x = -(-14 + ((B - 56) % 29)); + y = -( 8 + ((B - 56) / 29)); + } + + av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + return copy_from(s, frame, frame, x, y); +} + +static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char B, BL, BH; + + /* copy a block from the previous frame; need 1 more byte */ + if (!s->is_16bpp) { + B = bytestream2_get_byte(&s->stream_ptr); + } else { + B = bytestream2_get_byte(&s->mv_ptr); + } + + BL = B & 0x0F; + BH = (B >> 4) & 0x0F; + x = -8 + BL; + y = -8 + BH; + + av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y); + return copy_from(s, s->last_frame, frame, x, y); +} + +static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s, AVFrame *frame) +{ + signed char x, y; + + /* copy a block from the previous frame using an expanded range; + * need 2 more bytes */ + x = bytestream2_get_byte(&s->stream_ptr); + y = bytestream2_get_byte(&s->stream_ptr); + + av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y); + return copy_from(s, s->last_frame, frame, x, y); +} + +static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s, AVFrame *frame) +{ + /* mystery opcode? skip multiple blocks? */ + av_log(s->avctx, AV_LOG_ERROR, "Help! Mystery opcode 0x6 seen\n"); + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0x7(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char P[2]; + unsigned int flags; + + /* 2-color encoding */ + P[0] = bytestream2_get_byte(&s->stream_ptr); + P[1] = bytestream2_get_byte(&s->stream_ptr); + + if (P[0] <= P[1]) { + + /* need 8 more bytes from the stream */ + for (y = 0; y < 8; y++) { + flags = bytestream2_get_byte(&s->stream_ptr) | 0x100; + for (; flags != 1; flags >>= 1) + *s->pixel_ptr++ = P[flags & 1]; + s->pixel_ptr += s->line_inc; + } + + } else { + + /* need 2 more bytes from the stream */ + flags = bytestream2_get_le16(&s->stream_ptr); + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x += 2, flags >>= 1) { + s->pixel_ptr[x ] = + s->pixel_ptr[x + 1 ] = + s->pixel_ptr[x + s->stride] = + s->pixel_ptr[x + 1 + s->stride] = P[flags & 1]; + } + s->pixel_ptr += s->stride * 2; + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0x8(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char P[4]; + unsigned int flags = 0; + + /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on + * either top and bottom or left and right halves */ + P[0] = bytestream2_get_byte(&s->stream_ptr); + P[1] = bytestream2_get_byte(&s->stream_ptr); + + if (P[0] <= P[1]) { + for (y = 0; y < 16; y++) { + // new values for each 4x4 block + if (!(y & 3)) { + if (y) { + P[0] = bytestream2_get_byte(&s->stream_ptr); + P[1] = bytestream2_get_byte(&s->stream_ptr); + } + flags = bytestream2_get_le16(&s->stream_ptr); + } + + for (x = 0; x < 4; x++, flags >>= 1) + *s->pixel_ptr++ = P[flags & 1]; + s->pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) s->pixel_ptr -= 8 * s->stride - 4; + } + + } else { + flags = bytestream2_get_le32(&s->stream_ptr); + P[2] = bytestream2_get_byte(&s->stream_ptr); + P[3] = bytestream2_get_byte(&s->stream_ptr); + + if (P[2] <= P[3]) { + + /* vertical split; left & right halves are 2-color encoded */ + + for (y = 0; y < 16; y++) { + for (x = 0; x < 4; x++, flags >>= 1) + *s->pixel_ptr++ = P[flags & 1]; + s->pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) { + s->pixel_ptr -= 8 * s->stride - 4; + P[0] = P[2]; + P[1] = P[3]; + flags = bytestream2_get_le32(&s->stream_ptr); + } + } + + } else { + + /* horizontal split; top & bottom halves are 2-color encoded */ + + for (y = 0; y < 8; y++) { + if (y == 4) { + P[0] = P[2]; + P[1] = P[3]; + flags = bytestream2_get_le32(&s->stream_ptr); + } + + for (x = 0; x < 8; x++, flags >>= 1) + *s->pixel_ptr++ = P[flags & 1]; + s->pixel_ptr += s->line_inc; + } + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0x9(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char P[4]; + + /* 4-color encoding */ + bytestream2_get_buffer(&s->stream_ptr, P, 4); + + if (P[0] <= P[1]) { + if (P[2] <= P[3]) { + + /* 1 of 4 colors for each pixel, need 16 more bytes */ + for (y = 0; y < 8; y++) { + /* get the next set of 8 2-bit flags */ + int flags = bytestream2_get_le16(&s->stream_ptr); + for (x = 0; x < 8; x++, flags >>= 2) + *s->pixel_ptr++ = P[flags & 0x03]; + s->pixel_ptr += s->line_inc; + } + + } else { + uint32_t flags; + + /* 1 of 4 colors for each 2x2 block, need 4 more bytes */ + flags = bytestream2_get_le32(&s->stream_ptr); + + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x += 2, flags >>= 2) { + s->pixel_ptr[x ] = + s->pixel_ptr[x + 1 ] = + s->pixel_ptr[x + s->stride] = + s->pixel_ptr[x + 1 + s->stride] = P[flags & 0x03]; + } + s->pixel_ptr += s->stride * 2; + } + + } + } else { + uint64_t flags; + + /* 1 of 4 colors for each 2x1 or 1x2 block, need 8 more bytes */ + flags = bytestream2_get_le64(&s->stream_ptr); + if (P[2] <= P[3]) { + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x += 2, flags >>= 2) { + s->pixel_ptr[x ] = + s->pixel_ptr[x + 1] = P[flags & 0x03]; + } + s->pixel_ptr += s->stride; + } + } else { + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x++, flags >>= 2) { + s->pixel_ptr[x ] = + s->pixel_ptr[x + s->stride] = P[flags & 0x03]; + } + s->pixel_ptr += s->stride * 2; + } + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char P[8]; + int flags = 0; + + bytestream2_get_buffer(&s->stream_ptr, P, 4); + + /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on + * either top and bottom or left and right halves */ + if (P[0] <= P[1]) { + + /* 4-color encoding for each quadrant; need 32 bytes */ + for (y = 0; y < 16; y++) { + // new values for each 4x4 block + if (!(y & 3)) { + if (y) bytestream2_get_buffer(&s->stream_ptr, P, 4); + flags = bytestream2_get_le32(&s->stream_ptr); + } + + for (x = 0; x < 4; x++, flags >>= 2) + *s->pixel_ptr++ = P[flags & 0x03]; + + s->pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) s->pixel_ptr -= 8 * s->stride - 4; + } + + } else { + // vertical split? + int vert; + uint64_t flags = bytestream2_get_le64(&s->stream_ptr); + + bytestream2_get_buffer(&s->stream_ptr, P + 4, 4); + vert = P[4] <= P[5]; + + /* 4-color encoding for either left and right or top and bottom + * halves */ + + for (y = 0; y < 16; y++) { + for (x = 0; x < 4; x++, flags >>= 2) + *s->pixel_ptr++ = P[flags & 0x03]; + + if (vert) { + s->pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) s->pixel_ptr -= 8 * s->stride - 4; + } else if (y & 1) s->pixel_ptr += s->line_inc; + + // load values for second half + if (y == 7) { + memcpy(P, P + 4, 4); + flags = bytestream2_get_le64(&s->stream_ptr); + } + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xB(IpvideoContext *s, AVFrame *frame) +{ + int y; + + /* 64-color encoding (each pixel in block is a different color) */ + for (y = 0; y < 8; y++) { + bytestream2_get_buffer(&s->stream_ptr, s->pixel_ptr, 8); + s->pixel_ptr += s->stride; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xC(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + + /* 16-color block encoding: each 2x2 block is a different color */ + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x += 2) { + s->pixel_ptr[x ] = + s->pixel_ptr[x + 1 ] = + s->pixel_ptr[x + s->stride] = + s->pixel_ptr[x + 1 + s->stride] = bytestream2_get_byte(&s->stream_ptr); + } + s->pixel_ptr += s->stride * 2; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xD(IpvideoContext *s, AVFrame *frame) +{ + int y; + unsigned char P[2]; + + /* 4-color block encoding: each 4x4 block is a different color */ + for (y = 0; y < 8; y++) { + if (!(y & 3)) { + P[0] = bytestream2_get_byte(&s->stream_ptr); + P[1] = bytestream2_get_byte(&s->stream_ptr); + } + memset(s->pixel_ptr, P[0], 4); + memset(s->pixel_ptr + 4, P[1], 4); + s->pixel_ptr += s->stride; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xE(IpvideoContext *s, AVFrame *frame) +{ + int y; + unsigned char pix; + + /* 1-color encoding: the whole block is 1 solid color */ + pix = bytestream2_get_byte(&s->stream_ptr); + + for (y = 0; y < 8; y++) { + memset(s->pixel_ptr, pix, 8); + s->pixel_ptr += s->stride; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xF(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char sample[2]; + + /* dithered encoding */ + sample[0] = bytestream2_get_byte(&s->stream_ptr); + sample[1] = bytestream2_get_byte(&s->stream_ptr); + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x += 2) { + *s->pixel_ptr++ = sample[ y & 1 ]; + *s->pixel_ptr++ = sample[!(y & 1)]; + } + s->pixel_ptr += s->line_inc; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0x6_16(IpvideoContext *s, AVFrame *frame) +{ + signed char x, y; + + /* copy a block from the second last frame using an expanded range */ + x = bytestream2_get_byte(&s->stream_ptr); + y = bytestream2_get_byte(&s->stream_ptr); + + av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y); + return copy_from(s, s->second_last_frame, frame, x, y); +} + +static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t P[2]; + unsigned int flags; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 2-color encoding */ + P[0] = bytestream2_get_le16(&s->stream_ptr); + P[1] = bytestream2_get_le16(&s->stream_ptr); + + if (!(P[0] & 0x8000)) { + + for (y = 0; y < 8; y++) { + flags = bytestream2_get_byte(&s->stream_ptr) | 0x100; + for (; flags != 1; flags >>= 1) + *pixel_ptr++ = P[flags & 1]; + pixel_ptr += s->line_inc; + } + + } else { + + flags = bytestream2_get_le16(&s->stream_ptr); + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x += 2, flags >>= 1) { + pixel_ptr[x ] = + pixel_ptr[x + 1 ] = + pixel_ptr[x + s->stride] = + pixel_ptr[x + 1 + s->stride] = P[flags & 1]; + } + pixel_ptr += s->stride * 2; + } + } + + return 0; +} + +static int ipvideo_decode_block_opcode_0x8_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t P[4]; + unsigned int flags = 0; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 2-color encoding for each 4x4 quadrant, or 2-color encoding on + * either top and bottom or left and right halves */ + P[0] = bytestream2_get_le16(&s->stream_ptr); + P[1] = bytestream2_get_le16(&s->stream_ptr); + + if (!(P[0] & 0x8000)) { + + for (y = 0; y < 16; y++) { + // new values for each 4x4 block + if (!(y & 3)) { + if (y) { + P[0] = bytestream2_get_le16(&s->stream_ptr); + P[1] = bytestream2_get_le16(&s->stream_ptr); + } + flags = bytestream2_get_le16(&s->stream_ptr); + } + + for (x = 0; x < 4; x++, flags >>= 1) + *pixel_ptr++ = P[flags & 1]; + pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) pixel_ptr -= 8 * s->stride - 4; + } + + } else { + + flags = bytestream2_get_le32(&s->stream_ptr); + P[2] = bytestream2_get_le16(&s->stream_ptr); + P[3] = bytestream2_get_le16(&s->stream_ptr); + + if (!(P[2] & 0x8000)) { + + /* vertical split; left & right halves are 2-color encoded */ + + for (y = 0; y < 16; y++) { + for (x = 0; x < 4; x++, flags >>= 1) + *pixel_ptr++ = P[flags & 1]; + pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) { + pixel_ptr -= 8 * s->stride - 4; + P[0] = P[2]; + P[1] = P[3]; + flags = bytestream2_get_le32(&s->stream_ptr); + } + } + + } else { + + /* horizontal split; top & bottom halves are 2-color encoded */ + + for (y = 0; y < 8; y++) { + if (y == 4) { + P[0] = P[2]; + P[1] = P[3]; + flags = bytestream2_get_le32(&s->stream_ptr); + } + + for (x = 0; x < 8; x++, flags >>= 1) + *pixel_ptr++ = P[flags & 1]; + pixel_ptr += s->line_inc; + } + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0x9_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t P[4]; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 4-color encoding */ + for (x = 0; x < 4; x++) + P[x] = bytestream2_get_le16(&s->stream_ptr); + + if (!(P[0] & 0x8000)) { + if (!(P[2] & 0x8000)) { + + /* 1 of 4 colors for each pixel */ + for (y = 0; y < 8; y++) { + /* get the next set of 8 2-bit flags */ + int flags = bytestream2_get_le16(&s->stream_ptr); + for (x = 0; x < 8; x++, flags >>= 2) + *pixel_ptr++ = P[flags & 0x03]; + pixel_ptr += s->line_inc; + } + + } else { + uint32_t flags; + + /* 1 of 4 colors for each 2x2 block */ + flags = bytestream2_get_le32(&s->stream_ptr); + + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x += 2, flags >>= 2) { + pixel_ptr[x ] = + pixel_ptr[x + 1 ] = + pixel_ptr[x + s->stride] = + pixel_ptr[x + 1 + s->stride] = P[flags & 0x03]; + } + pixel_ptr += s->stride * 2; + } + + } + } else { + uint64_t flags; + + /* 1 of 4 colors for each 2x1 or 1x2 block */ + flags = bytestream2_get_le64(&s->stream_ptr); + if (!(P[2] & 0x8000)) { + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x += 2, flags >>= 2) { + pixel_ptr[x ] = + pixel_ptr[x + 1] = P[flags & 0x03]; + } + pixel_ptr += s->stride; + } + } else { + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x++, flags >>= 2) { + pixel_ptr[x ] = + pixel_ptr[x + s->stride] = P[flags & 0x03]; + } + pixel_ptr += s->stride * 2; + } + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xA_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t P[8]; + int flags = 0; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + for (x = 0; x < 4; x++) + P[x] = bytestream2_get_le16(&s->stream_ptr); + + /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on + * either top and bottom or left and right halves */ + if (!(P[0] & 0x8000)) { + + /* 4-color encoding for each quadrant */ + for (y = 0; y < 16; y++) { + // new values for each 4x4 block + if (!(y & 3)) { + if (y) + for (x = 0; x < 4; x++) + P[x] = bytestream2_get_le16(&s->stream_ptr); + flags = bytestream2_get_le32(&s->stream_ptr); + } + + for (x = 0; x < 4; x++, flags >>= 2) + *pixel_ptr++ = P[flags & 0x03]; + + pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) pixel_ptr -= 8 * s->stride - 4; + } + + } else { + // vertical split? + int vert; + uint64_t flags = bytestream2_get_le64(&s->stream_ptr); + + for (x = 4; x < 8; x++) + P[x] = bytestream2_get_le16(&s->stream_ptr); + vert = !(P[4] & 0x8000); + + /* 4-color encoding for either left and right or top and bottom + * halves */ + + for (y = 0; y < 16; y++) { + for (x = 0; x < 4; x++, flags >>= 2) + *pixel_ptr++ = P[flags & 0x03]; + + if (vert) { + pixel_ptr += s->stride - 4; + // switch to right half + if (y == 7) pixel_ptr -= 8 * s->stride - 4; + } else if (y & 1) pixel_ptr += s->line_inc; + + // load values for second half + if (y == 7) { + memcpy(P, P + 4, 8); + flags = bytestream2_get_le64(&s->stream_ptr); + } + } + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xB_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 64-color encoding (each pixel in block is a different color) */ + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + pixel_ptr[x] = bytestream2_get_le16(&s->stream_ptr); + pixel_ptr += s->stride; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xC_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 16-color block encoding: each 2x2 block is a different color */ + for (y = 0; y < 8; y += 2) { + for (x = 0; x < 8; x += 2) { + pixel_ptr[x ] = + pixel_ptr[x + 1 ] = + pixel_ptr[x + s->stride] = + pixel_ptr[x + 1 + s->stride] = bytestream2_get_le16(&s->stream_ptr); + } + pixel_ptr += s->stride * 2; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xD_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t P[2]; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 4-color block encoding: each 4x4 block is a different color */ + for (y = 0; y < 8; y++) { + if (!(y & 3)) { + P[0] = bytestream2_get_le16(&s->stream_ptr); + P[1] = bytestream2_get_le16(&s->stream_ptr); + } + for (x = 0; x < 8; x++) + pixel_ptr[x] = P[x >> 2]; + pixel_ptr += s->stride; + } + + /* report success */ + return 0; +} + +static int ipvideo_decode_block_opcode_0xE_16(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + uint16_t pix; + uint16_t *pixel_ptr = (uint16_t*)s->pixel_ptr; + + /* 1-color encoding: the whole block is 1 solid color */ + pix = bytestream2_get_le16(&s->stream_ptr); + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + pixel_ptr[x] = pix; + pixel_ptr += s->stride; + } + + /* report success */ + return 0; +} + +static int (* const ipvideo_decode_block[])(IpvideoContext *s, AVFrame *frame) = { + ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1, + ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3, + ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5, + ipvideo_decode_block_opcode_0x6, ipvideo_decode_block_opcode_0x7, + ipvideo_decode_block_opcode_0x8, ipvideo_decode_block_opcode_0x9, + ipvideo_decode_block_opcode_0xA, ipvideo_decode_block_opcode_0xB, + ipvideo_decode_block_opcode_0xC, ipvideo_decode_block_opcode_0xD, + ipvideo_decode_block_opcode_0xE, ipvideo_decode_block_opcode_0xF, +}; + +static int (* const ipvideo_decode_block16[])(IpvideoContext *s, AVFrame *frame) = { + ipvideo_decode_block_opcode_0x0, ipvideo_decode_block_opcode_0x1, + ipvideo_decode_block_opcode_0x2, ipvideo_decode_block_opcode_0x3, + ipvideo_decode_block_opcode_0x4, ipvideo_decode_block_opcode_0x5, + ipvideo_decode_block_opcode_0x6_16, ipvideo_decode_block_opcode_0x7_16, + ipvideo_decode_block_opcode_0x8_16, ipvideo_decode_block_opcode_0x9_16, + ipvideo_decode_block_opcode_0xA_16, ipvideo_decode_block_opcode_0xB_16, + ipvideo_decode_block_opcode_0xC_16, ipvideo_decode_block_opcode_0xD_16, + ipvideo_decode_block_opcode_0xE_16, ipvideo_decode_block_opcode_0x1, +}; + +static void ipvideo_decode_opcodes(IpvideoContext *s, AVFrame *frame) +{ + int x, y; + unsigned char opcode; + int ret; + GetBitContext gb; + + bytestream2_skip(&s->stream_ptr, 14); /* data starts 14 bytes in */ + if (!s->is_16bpp) { + /* this is PAL8, so make the palette available */ + memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); + + s->stride = frame->linesize[0]; + } else { + s->stride = frame->linesize[0] >> 1; + s->mv_ptr = s->stream_ptr; + bytestream2_skip(&s->mv_ptr, bytestream2_get_le16(&s->stream_ptr)); + } + s->line_inc = s->stride - 8; + s->upper_motion_limit_offset = (s->avctx->height - 8) * frame->linesize[0] + + (s->avctx->width - 8) * (1 + s->is_16bpp); + + init_get_bits(&gb, s->decoding_map, s->decoding_map_size * 8); + for (y = 0; y < s->avctx->height; y += 8) { + for (x = 0; x < s->avctx->width; x += 8) { + opcode = get_bits(&gb, 4); + + av_dlog(s->avctx, + " block @ (%3d, %3d): encoding 0x%X, data ptr offset %d\n", + x, y, opcode, bytestream2_tell(&s->stream_ptr)); + + if (!s->is_16bpp) { + s->pixel_ptr = frame->data[0] + x + + y*frame->linesize[0]; + ret = ipvideo_decode_block[opcode](s, frame); + } else { + s->pixel_ptr = frame->data[0] + x*2 + + y*frame->linesize[0]; + ret = ipvideo_decode_block16[opcode](s, frame); + } + if (ret != 0) { + av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n", + s->avctx->frame_number, x, y); + return; + } + } + } + if (bytestream2_get_bytes_left(&s->stream_ptr) > 1) { + av_log(s->avctx, AV_LOG_ERROR, + "decode finished with %d bytes left over\n", + bytestream2_get_bytes_left(&s->stream_ptr)); + } +} + +static av_cold int ipvideo_decode_init(AVCodecContext *avctx) +{ + IpvideoContext *s = avctx->priv_data; + + s->avctx = avctx; + + s->is_16bpp = avctx->bits_per_coded_sample == 16; + avctx->pix_fmt = s->is_16bpp ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_PAL8; + + ff_hpeldsp_init(&s->hdsp, avctx->flags); + + s->last_frame = av_frame_alloc(); + s->second_last_frame = av_frame_alloc(); + if (!s->last_frame || !s->second_last_frame) { + av_frame_free(&s->last_frame); + av_frame_free(&s->second_last_frame); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int ipvideo_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + IpvideoContext *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + /* decoding map contains 4 bits of information per 8x8 block */ + s->decoding_map_size = avctx->width * avctx->height / (8 * 8 * 2); + + /* compressed buffer needs to be large enough to at least hold an entire + * decoding map */ + if (buf_size < s->decoding_map_size) + return buf_size; + + if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) { + av_frame_unref(s->last_frame); + av_frame_unref(s->second_last_frame); + } + + s->decoding_map = buf; + bytestream2_init(&s->stream_ptr, buf + s->decoding_map_size, + buf_size - s->decoding_map_size); + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if (!s->is_16bpp) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + if (pal) { + frame->palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + } + + ipvideo_decode_opcodes(s, frame); + + *got_frame = 1; + + /* shuffle frames */ + av_frame_unref(s->second_last_frame); + FFSWAP(AVFrame*, s->second_last_frame, s->last_frame); + if ((ret = av_frame_ref(s->last_frame, frame)) < 0) + return ret; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int ipvideo_decode_end(AVCodecContext *avctx) +{ + IpvideoContext *s = avctx->priv_data; + + av_frame_free(&s->last_frame); + av_frame_free(&s->second_last_frame); + + return 0; +} + +AVCodec ff_interplay_video_decoder = { + .name = "interplayvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_INTERPLAY_VIDEO, + .priv_data_size = sizeof(IpvideoContext), + .init = ipvideo_decode_init, + .close = ipvideo_decode_end, + .decode = ipvideo_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE, + .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"), +}; diff --git a/ffmpeg/libavcodec/intrax8.c b/ffmpeg/libavcodec/intrax8.c new file mode 100644 index 0000000..67e16ab --- /dev/null +++ b/ffmpeg/libavcodec/intrax8.c @@ -0,0 +1,789 @@ +/* + * 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 + */ + +/** + * @file + * @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1 + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "error_resilience.h" +#include "get_bits.h" +#include "mpegvideo.h" +#include "msmpeg4data.h" +#include "intrax8huf.h" +#include "intrax8.h" +#include "intrax8dsp.h" + +#define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits) + +#define DC_VLC_BITS 9 +#define AC_VLC_BITS 9 +#define OR_VLC_BITS 7 + +#define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS) +#define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS) +#define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS) + +static VLC j_ac_vlc[2][2][8]; //[quant<13],[intra/inter],[select] +static VLC j_dc_vlc[2][8]; //[quant], [select] +static VLC j_orient_vlc[2][4]; //[quant], [select] + +static av_cold void x8_vlc_init(void){ + int i; + int offset = 0; + int sizeidx = 0; + static const uint16_t sizes[8*4 + 8*2 + 2 + 4] = { + 576, 548, 582, 618, 546, 616, 560, 642, + 584, 582, 704, 664, 512, 544, 656, 640, + 512, 648, 582, 566, 532, 614, 596, 648, + 586, 552, 584, 590, 544, 578, 584, 624, + + 528, 528, 526, 528, 536, 528, 526, 544, + 544, 512, 512, 528, 528, 544, 512, 544, + + 128, 128, 128, 128, 128, 128}; + + static VLC_TYPE table[28150][2]; + +#define init_ac_vlc(dst,src) \ + dst.table = &table[offset]; \ + dst.table_allocated = sizes[sizeidx]; \ + offset += sizes[sizeidx++]; \ + init_vlc(&dst, \ + AC_VLC_BITS,77, \ + &src[1],4,2, \ + &src[0],4,2, \ + INIT_VLC_USE_NEW_STATIC) +//set ac tables + for(i=0;i<8;i++){ + init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] ); + init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] ); + init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] ); + init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] ); + } +#undef init_ac_vlc + +//set dc tables +#define init_dc_vlc(dst,src) \ + dst.table = &table[offset]; \ + dst.table_allocated = sizes[sizeidx]; \ + offset += sizes[sizeidx++]; \ + init_vlc(&dst, \ + DC_VLC_BITS,34, \ + &src[1],4,2, \ + &src[0],4,2, \ + INIT_VLC_USE_NEW_STATIC); + for(i=0;i<8;i++){ + init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); + init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]); + } +#undef init_dc_vlc + +//set orient tables +#define init_or_vlc(dst,src) \ + dst.table = &table[offset]; \ + dst.table_allocated = sizes[sizeidx]; \ + offset += sizes[sizeidx++]; \ + init_vlc(&dst, \ + OR_VLC_BITS,12, \ + &src[1],4,2, \ + &src[0],4,2, \ + INIT_VLC_USE_NEW_STATIC); + for(i=0;i<2;i++){ + init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); + } + for(i=0;i<4;i++){ + init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0]) + } + if (offset != sizeof(table)/sizeof(VLC_TYPE)/2) + av_log(NULL, AV_LOG_ERROR, "table size %i does not match needed %i\n", (int)(sizeof(table)/sizeof(VLC_TYPE)/2), offset); +} +#undef init_or_vlc + +static void x8_reset_vlc_tables(IntraX8Context * w){ + memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc)); + memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc)); + w->j_orient_vlc=NULL; +} + +static inline void x8_select_ac_table(IntraX8Context * const w , int mode){ + MpegEncContext * const s= w->s; + int table_index; + + av_assert2(mode<4); + + if( w->j_ac_vlc[mode] ) return; + + table_index = get_bits(&s->gb, 3); + w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables + av_assert2(w->j_ac_vlc[mode]); +} + +static inline int x8_get_orient_vlc(IntraX8Context * w){ + MpegEncContext * const s= w->s; + int table_index; + + if(!w->j_orient_vlc ){ + table_index = get_bits(&s->gb, 1+(w->quant<13) ); + w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index]; + } + + return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD); +} + +#define extra_bits(eb) (eb) +#define extra_run (0xFF<<8) +#define extra_level (0x00<<8) +#define run_offset(r) ((r)<<16) +#define level_offset(l) ((l)<<24) +static const uint32_t ac_decode_table[]={ + /*46*/ extra_bits(3) | extra_run | run_offset(16) | level_offset( 0), + /*47*/ extra_bits(3) | extra_run | run_offset(24) | level_offset( 0), + /*48*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), + /*49*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), + + /*50*/ extra_bits(5) | extra_run | run_offset(32) | level_offset( 0), + /*51*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), + + /*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), + /*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8), + /*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12), + /*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16), + /*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24), + + /*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), + /*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), + + /*59*/ extra_bits(2) | extra_run | run_offset(16) | level_offset( 0), + /*60*/ extra_bits(2) | extra_run | run_offset(20) | level_offset( 0), + /*61*/ extra_bits(2) | extra_run | run_offset(24) | level_offset( 0), + /*62*/ extra_bits(2) | extra_run | run_offset(28) | level_offset( 0), + /*63*/ extra_bits(4) | extra_run | run_offset(32) | level_offset( 0), + /*64*/ extra_bits(4) | extra_run | run_offset(48) | level_offset( 0), + + /*65*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), + /*66*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), + /*67*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), + + /*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), + /*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8), + /*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16), + + /*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), + /*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), +}; +//extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits; +#undef extra_bits +#undef extra_run +#undef extra_level +#undef run_offset +#undef level_offset + +static void x8_get_ac_rlf(IntraX8Context * const w, const int mode, + int * const run, int * const level, int * const final){ + MpegEncContext * const s= w->s; + int i,e; + +// x8_select_ac_table(w,mode); + i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD); + + if(i<46){ //[0-45] + int t,l; + if(i<0){ + (*level)=(*final)=//prevent 'may be used unilitialized' + (*run)=64;//this would cause error exit in the ac loop + return; + } + + (*final) = t = (i>22); + i-=23*t; +/* + i== 0-15 r=0-15 l=0 ;r=i& %01111 + i==16-19 r=0-3 l=1 ;r=i& %00011 + i==20-21 r=0-1 l=2 ;r=i& %00001 + i==22 r=0 l=3 ;r=i& %00000 +l=lut_l[i/2]={0,0,0,0,0,0,0,0,1,1,2,3}[i>>1];// 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 +t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */ + l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/ + t=(0x01030F>>(l<<3)); + + (*run) = i&t; + (*level) = l; + }else if(i<73){//[46-72] + uint32_t sm; + uint32_t mask; + + i-=46; + sm=ac_decode_table[i]; + + e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits + mask=sm&0xff;sm>>=8; //1bit + + (*run) =(sm&0xff) + (e&( mask));//6bits + (*level)=(sm>>8) + (e&(~mask));//5bits + (*final)=i>(58-46); + }else if(i<75){//[73-74] + static const uint8_t crazy_mix_runlevel[32]={ + 0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63, + 0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83, + 0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64, + 0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84}; + + (*final)=!(i&1); + e=get_bits(&s->gb,5);//get the extra bits + (*run) =crazy_mix_runlevel[e]>>4; + (*level)=crazy_mix_runlevel[e]&0x0F; + }else{ + (*level)=get_bits( &s->gb, 7-3*(i&1)); + (*run) =get_bits( &s->gb, 6); + (*final)=get_bits1(&s->gb); + } + return; +} + +//static const uint8_t dc_extra_sbits[] ={0, 1,1, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7 }; +static const uint8_t dc_index_offset[] ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193}; + +static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){ + MpegEncContext * const s= w->s; + int i,e,c; + + av_assert2(mode<3); + if( !w->j_dc_vlc[mode] ) { + int table_index; + table_index = get_bits(&s->gb, 3); + //4 modes, same table + w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index]; + } + + i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD); + + /*(i>=17) {i-=17;final=1;}*/ + c= i>16; + (*final)=c; + i-=17*c; + + if(i<=0){ + (*level)=0; + return -i; + } + c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[] + c-=c>1; + + e=get_bits(&s->gb,c);//get the extra bits + i=dc_index_offset[i]+(e>>1); + + e= -(e & 1);//0,0xffffff + (*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1) + return 0; +} +//end of huffman + +static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){ + MpegEncContext * const s= w->s; + int range; + int sum; + int quant; + + w->dsp.setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer, + s->current_picture.f.linesize[chroma>0], + &range, &sum, w->edges); + if(chroma){ + w->orient=w->chroma_orient; + quant=w->quant_dc_chroma; + }else{ + quant=w->quant; + } + + w->flat_dc=0; + if(range < quant || range < 3){ + w->orient=0; + if(range < 3){//yep you read right, a +-1 idct error may break decoding! + w->flat_dc=1; + sum+=9; + w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899 + } + } + if(chroma) + return 0; + + av_assert2(w->orient < 3); + if(range < 2*w->quant){ + if( (w->edges&3) == 0){ + if(w->orient==1) w->orient=11; + if(w->orient==2) w->orient=10; + }else{ + w->orient=0; + } + w->raw_orient=0; + }else{ + static const uint8_t prediction_table[3][12]={ + {0,8,4, 10,11, 2,6,9,1,3,5,7}, + {4,0,8, 11,10, 3,5,2,6,9,1,7}, + {8,0,4, 10,11, 1,7,2,6,9,3,5} + }; + w->raw_orient=x8_get_orient_vlc(w); + if(w->raw_orient<0) return -1; + av_assert2(w->raw_orient < 12 ); + av_assert2(w->orient<3); + w->orient=prediction_table[w->orient][w->raw_orient]; + } + return 0; +} + +static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){ + MpegEncContext * const s= w->s; + + w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8); +/* + y=2n+0 ->//0 2 4 + y=2n+1 ->//1 3 5 +*/ +} +static void x8_get_prediction_chroma(IntraX8Context * const w){ + MpegEncContext * const s= w->s; + + w->edges = 1*( !(s->mb_x>>1) ); + w->edges|= 2*( !(s->mb_y>>1) ); + w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd + + w->raw_orient=0; + if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC + w->chroma_orient=4<<((0xCC>>w->edges)&1); + return; + } + w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)] +} + +static void x8_get_prediction(IntraX8Context * const w){ + MpegEncContext * const s= w->s; + int a,b,c,i; + + w->edges = 1*( !s->mb_x ); + w->edges|= 2*( !s->mb_y ); + w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) ); + + switch(w->edges&3){ + case 0: + break; + case 1: + //take the one from the above block[0][y-1] + w->est_run = w->prediction_table[!(s->mb_y&1)]>>2; + w->orient = 1; + return; + case 2: + //take the one from the previous block[x-1][0] + w->est_run = w->prediction_table[2*s->mb_x-2]>>2; + w->orient = 2; + return; + case 3: + w->est_run = 16; + w->orient = 0; + return; + } + //no edge cases + b= w->prediction_table[2*s->mb_x + !(s->mb_y&1) ];//block[x ][y-1] + a= w->prediction_table[2*s->mb_x-2 + (s->mb_y&1) ];//block[x-1][y ] + c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1] + + w->est_run = FFMIN(b,a); + /* This condition has nothing to do with w->edges, even if it looks + similar it would trigger if e.g. x=3;y=2; + I guess somebody wrote something wrong and it became standard. */ + if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run); + w->est_run>>=2; + + a&=3; + b&=3; + c&=3; + + i=( 0xFFEAF4C4>>(2*b+8*a) )&3; + if(i!=3) w->orient=i; + else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3; +/* +lut1[b][a]={ +->{0, 1, 0, pad}, + {0, 1, X, pad}, + {2, 2, 2, pad}} + pad 2 2 2; pad X 1 0; pad 0 1 0 <- +-> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4 + +lut2[q>12][c]={ + ->{0,2,1,pad}, + {2,2,2,pad}} + pad 2 2 2; pad 1 2 0 <- +-> 11 10'10 10 '11 01'10 00=>0xEAD8 +*/ +} + + +static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){ + MpegEncContext * const s= w->s; + int t; +#define B(x,y) s->block[0][s->dsp.idct_permutation[(x)+(y)*8]] +#define T(x) ((x) * dc_level + 0x8000) >> 16; + switch(direction){ + case 0: + t = T(3811);//h + B(1,0) -= t; + B(0,1) -= t; + + t = T(487);//e + B(2,0) -= t; + B(0,2) -= t; + + t = T(506);//f + B(3,0) -= t; + B(0,3) -= t; + + t = T(135);//c + B(4,0) -= t; + B(0,4) -= t; + B(2,1) += t; + B(1,2) += t; + B(3,1) += t; + B(1,3) += t; + + t = T(173);//d + B(5,0) -= t; + B(0,5) -= t; + + t = T(61);//b + B(6,0) -= t; + B(0,6) -= t; + B(5,1) += t; + B(1,5) += t; + + t = T(42); //a + B(7,0) -= t; + B(0,7) -= t; + B(4,1) += t; + B(1,4) += t; + B(4,4) += t; + + t = T(1084);//g + B(1,1) += t; + + s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); + break; + case 1: + B(0,1) -= T(6269); + B(0,3) -= T( 708); + B(0,5) -= T( 172); + B(0,7) -= T( 73); + + s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); + break; + case 2: + B(1,0) -= T(6269); + B(3,0) -= T( 708); + B(5,0) -= T( 172); + B(7,0) -= T( 73); + + s->block_last_index[0] = FFMAX(s->block_last_index[0], 7); + break; + } +#undef B +#undef T +} + +static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){ + int k; + for(k=0;k<8;k++){ + memset(dst,pix,8); + dst+=linesize; + } +} + +static const int16_t quant_table[64] = { + 256, 256, 256, 256, 256, 256, 259, 262, + 265, 269, 272, 275, 278, 282, 285, 288, + 292, 295, 299, 303, 306, 310, 314, 317, + 321, 325, 329, 333, 337, 341, 345, 349, + 353, 358, 362, 366, 371, 375, 379, 384, + 389, 393, 398, 403, 408, 413, 417, 422, + 428, 433, 438, 443, 448, 454, 459, 465, + 470, 476, 482, 488, 493, 499, 505, 511 +}; + +static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ + MpegEncContext * const s= w->s; + + uint8_t * scantable; + int final,run,level; + int ac_mode,dc_mode,est_run,dc_level; + int pos,n; + int zeros_only; + int use_quant_matrix; + int sign; + + av_assert2(w->orient<12); + s->dsp.clear_block(s->block[0]); + + if(chroma){ + dc_mode=2; + }else{ + dc_mode=!!w->est_run;//0,1 + } + + if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1; + n=0; + zeros_only=0; + if(!final){//decode ac + use_quant_matrix=w->use_quant_matrix; + if(chroma){ + ac_mode = 1; + est_run = 64;//not used + }else{ + if (w->raw_orient < 3){ + use_quant_matrix = 0; + } + if(w->raw_orient > 4){ + ac_mode = 0; + est_run = 64; + }else{ + if(w->est_run > 1){ + ac_mode = 2; + est_run=w->est_run; + }else{ + ac_mode = 3; + est_run = 64; + } + } + } + x8_select_ac_table(w,ac_mode); + /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<- + -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */ + scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated; + pos=0; + do { + n++; + if( n >= est_run ){ + ac_mode=3; + x8_select_ac_table(w,3); + } + + x8_get_ac_rlf(w,ac_mode,&run,&level,&final); + + pos+=run+1; + if(pos>63){ + //this also handles vlc error in x8_get_ac_rlf + return -1; + } + level= (level+1) * w->dquant; + level+= w->qsum; + + sign = - get_bits1(&s->gb); + level = (level ^ sign) - sign; + + if(use_quant_matrix){ + level = (level*quant_table[pos])>>8; + } + s->block[0][ scantable[pos] ]=level; + }while(!final); + + s->block_last_index[0]=pos; + }else{//DC only + s->block_last_index[0]=0; + if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1] + int32_t divide_quant= !chroma ? w->divide_quant_dc_luma: + w->divide_quant_dc_chroma; + int32_t dc_quant = !chroma ? w->quant: + w->quant_dc_chroma; + + //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding + dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13; + + dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3), + s->dest[chroma], s->current_picture.f.linesize[!!chroma]); + + goto block_placed; + } + zeros_only = (dc_level == 0); + } + if(!chroma){ + s->block[0][0] = dc_level*w->quant; + }else{ + s->block[0][0] = dc_level*w->quant_dc_chroma; + } + + //there is !zero_only check in the original, but dc_level check is enough + if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){ + int direction; + /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<- + -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */ + direction= (0x6A017C>>(w->orient*2))&3; + if (direction != 3){ + x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[] + } + } + + if(w->flat_dc){ + dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.f.linesize[!!chroma]); + }else{ + w->dsp.spatial_compensation[w->orient]( s->edge_emu_buffer, + s->dest[chroma], + s->current_picture.f.linesize[!!chroma] ); + } + if(!zeros_only) + s->dsp.idct_add ( s->dest[chroma], + s->current_picture.f.linesize[!!chroma], + s->block[0] ); + +block_placed: + + if(!chroma){ + x8_update_predictions(w,w->orient,n); + } + + if(s->loop_filter){ + uint8_t* ptr = s->dest[chroma]; + int linesize = s->current_picture.f.linesize[!!chroma]; + + if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ + w->dsp.h_loop_filter(ptr, linesize, w->quant); + } + if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){ + w->dsp.v_loop_filter(ptr, linesize, w->quant); + } + } + return 0; +} + +static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_* +//not s->linesize as this would be wrong for field pics +//not that IntraX8 has interlacing support ;) + const int linesize = s->current_picture.f.linesize[0]; + const int uvlinesize = s->current_picture.f.linesize[1]; + + s->dest[0] = s->current_picture.f.data[0]; + s->dest[1] = s->current_picture.f.data[1]; + s->dest[2] = s->current_picture.f.data[2]; + + s->dest[0] += s->mb_y * linesize << 3; + s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows + s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2; +} + +/** + * Initialize IntraX8 frame decoder. + * Requires valid MpegEncContext with valid s->mb_width before calling. + * @param w pointer to IntraX8Context + * @param s pointer to MpegEncContext of the parent codec + */ +av_cold void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){ + + w->s=s; + x8_vlc_init(); + av_assert0(s->mb_width>0); + w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb + + ff_init_scantable(s->dsp.idct_permutation, &w->scantable[0], ff_wmv1_scantable[0]); + ff_init_scantable(s->dsp.idct_permutation, &w->scantable[1], ff_wmv1_scantable[2]); + ff_init_scantable(s->dsp.idct_permutation, &w->scantable[2], ff_wmv1_scantable[3]); + + ff_intrax8dsp_init(&w->dsp); +} + +/** + * Destroy IntraX8 frame structure. + * @param w pointer to IntraX8Context + */ +av_cold void ff_intrax8_common_end(IntraX8Context * w) +{ + av_freep(&w->prediction_table); +} + +/** + * Decode single IntraX8 frame. + * The parent codec must fill s->loopfilter and s->gb (bitstream). + * The parent codec must call MPV_frame_start(), ff_er_frame_start() before calling this function. + * The parent codec must call ff_er_frame_end(), MPV_frame_end() after calling this function. + * This function does not use MPV_decode_mb(). + * lowres decoding is theoretically impossible. + * @param w pointer to IntraX8Context + * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1. + * @param quant_offset offset away from zero + */ +//FIXME extern uint8_t ff_wmv3_dc_scale_table[32]; +int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){ + MpegEncContext * const s= w->s; + int mb_xy; + w->use_quant_matrix = get_bits1(&s->gb); + + w->dquant = dquant; + w->quant = dquant >> 1; + w->qsum = quant_offset; + + w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant; + if(w->quant < 5){ + w->quant_dc_chroma = w->quant; + w->divide_quant_dc_chroma = w->divide_quant_dc_luma; + }else{ + w->quant_dc_chroma = w->quant+((w->quant+3)>>3); + w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma; + } + x8_reset_vlc_tables(w); + + s->resync_mb_x=0; + s->resync_mb_y=0; + + for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){ + x8_init_block_index(s); + mb_xy=(s->mb_y>>1)*s->mb_stride; + + for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){ + x8_get_prediction(w); + if(x8_setup_spatial_predictor(w,0)) goto error; + if(x8_decode_intra_mb(w,0)) goto error; + + if( s->mb_x & s->mb_y & 1 ){ + x8_get_prediction_chroma(w); + + /*when setting up chroma, no vlc is read, + so no error condition can be reached*/ + x8_setup_spatial_predictor(w,1); + if(x8_decode_intra_mb(w,1)) goto error; + + x8_setup_spatial_predictor(w,2); + if(x8_decode_intra_mb(w,2)) goto error; + + s->dest[1]+= 8; + s->dest[2]+= 8; + + /*emulate MB info in the relevant tables*/ + s->mbskip_table [mb_xy]=0; + s->mbintra_table[mb_xy]=1; + s->current_picture.qscale_table[mb_xy] = w->quant; + mb_xy++; + } + s->dest[0]+= 8; + } + if(s->mb_y&1){ + ff_mpeg_draw_horiz_band(s, (s->mb_y-1)*8, 16); + } + } + +error: + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, + (s->mb_x>>1)-1, (s->mb_y>>1)-1, + ER_MB_END ); + return 0; +} diff --git a/ffmpeg/libavcodec/intrax8.h b/ffmpeg/libavcodec/intrax8.h new file mode 100644 index 0000000..40d689a --- /dev/null +++ b/ffmpeg/libavcodec/intrax8.h @@ -0,0 +1,59 @@ +/* + * 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 + */ + +#ifndef AVCODEC_INTRAX8_H +#define AVCODEC_INTRAX8_H + +#include "get_bits.h" +#include "mpegvideo.h" +#include "intrax8dsp.h" + +typedef struct IntraX8Context { + VLC * j_ac_vlc[4];//they point to the static j_mb_vlc + VLC * j_orient_vlc; + VLC * j_dc_vlc[3]; + + int use_quant_matrix; +//set by ff_intrax8_common_init + uint8_t * prediction_table;//2*(mb_w*2) + ScanTable scantable[3]; +//set by the caller codec + MpegEncContext * s; + IntraX8DSPContext dsp; + int quant; + int dquant; + int qsum; +//calculated per frame + int quant_dc_chroma; + int divide_quant_dc_luma; + int divide_quant_dc_chroma; +//changed per block + int edges; + int flat_dc; + int predicted_dc; + int raw_orient; + int chroma_orient; + int orient; + int est_run; +} IntraX8Context; + +void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s); +void ff_intrax8_common_end(IntraX8Context * w); +int ff_intrax8_decode_picture(IntraX8Context * w, int quant, int halfpq); + +#endif /* AVCODEC_INTRAX8_H */ diff --git a/ffmpeg/libavcodec/intrax8dsp.c b/ffmpeg/libavcodec/intrax8dsp.c new file mode 100644 index 0000000..1b34f89 --- /dev/null +++ b/ffmpeg/libavcodec/intrax8dsp.c @@ -0,0 +1,432 @@ +/* + * 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 + */ + +/** +* @file + *@brief IntraX8 frame subdecoder image manipulation routines + */ + +#include "intrax8dsp.h" +#include "libavutil/common.h" + +/* +area positions, #3 is 1 pixel only, other are 8 pixels + |66666666| + 3|44444444|55555555| +- -+--------+--------+ +1 2|XXXXXXXX| +1 2|XXXXXXXX| +1 2|XXXXXXXX| +1 2|XXXXXXXX| +1 2|XXXXXXXX| +1 2|XXXXXXXX| +1 2|XXXXXXXX| +1 2|XXXXXXXX| +^-start +*/ + +#define area1 (0) +#define area2 (8) +#define area3 (8+8) +#define area4 (8+8+1) +#define area5 (8+8+1+8) +#define area6 (8+8+1+16) + +/** + Collect statistics and prepare the edge pixels required by the other spatial compensation functions. + + * @param src pointer to the beginning of the processed block + * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do. + * @param linesize byte offset between 2 vertical pixels in the source image + * @param range pointer to the variable where the edge pixel range is to be stored (max-min values) + * @param psum pointer to the variable where the edge pixel sum is to be stored + * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels. + and some of the edge pixels should be interpolated, the flag has the following meaning: + 1 - mb_x==0 - first block in the row, interpolate area #1,#2,#3; + 2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6; + note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas; + 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5; +*/ +static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize, + int * range, int * psum, int edges){ + uint8_t * ptr; + int sum; + int i; + int min_pix,max_pix; + uint8_t c; + + if((edges&3)==3){ + *psum=0x80*(8+1+8+2); + *range=0; + memset(dst,0x80,16+1+16+8); + //this triggers flat_dc for sure. + //flat_dc avoids all (other) prediction modes, but requires dc_level decoding. + return; + } + + min_pix=256; + max_pix=-1; + + sum=0; + + if(!(edges&1)){//(mb_x!=0)//there is previous block on this row + ptr=src-1;//left column, area 2 + for(i=7;i>=0;i--){ + c=*(ptr-1);//area1, same mb as area2, no need to check + dst[area1+i]=c; + c=*(ptr); + + sum+=c; + min_pix=FFMIN(min_pix,c); + max_pix=FFMAX(max_pix,c); + dst[area2+i]=c; + + ptr+=linesize; + } + } + + if(!(edges&2)){ //(mb_y!=0)//there is row above + ptr=src-linesize;//top line + for(i=0;i<8;i++){ + c=*(ptr+i); + sum+=c; + min_pix=FFMIN(min_pix, c); + max_pix=FFMAX(max_pix, c); + } + if(edges&4){//last block on the row? + memset(dst+area5,c,8);//set with last pixel fr + memcpy(dst+area4, ptr, 8); + }else{ + memcpy(dst+area4, ptr, 16);//both area4 and 5 + } + memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block + } + //now calculate the stuff we need + if(edges&3){//mb_x==0 || mb_y==0){ + int avg=(sum+4)>>3; + if(edges&1){ //(mb_x==0) {//implies mb_y!=0 + memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged + }else{//implies y==0 x!=0 + memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6 + } + sum+=avg*9; + }else{ + uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column + dst[area3]=c; + sum+=c; + //edge pixel is not part of min/max + } + (*range) = max_pix - min_pix; + sum += *(dst+area5) + *(dst+area5+1); + *psum = sum; +} + + +static const uint16_t zero_prediction_weights[64*2] = { + 640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72, + 480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97, + 354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132, + 257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180, + 198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231, + 161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288, + 122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390, + 110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499 +}; + +static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){ + int i,j; + int x,y; + unsigned int p;//power divided by 2 + int a; + uint16_t left_sum[2][8] = { { 0 } }; + uint16_t top_sum[2][8] = { { 0 } }; + + for(i=0;i<8;i++){ + a=src[area2+7-i]<<4; + for(j=0;j<8;j++){ + p=abs(i-j); + left_sum[p&1][j]+= a>>(p>>1); + } + } + + for(i=0;i<8;i++){ + a=src[area4+i]<<4; + for(j=0;j<8;j++){ + p=abs(i-j); + top_sum[p&1][j]+= a>>(p>>1); + } + } + for(;i<10;i++){ + a=src[area4+i]<<4; + for(j=5;j<8;j++){ + p=abs(i-j); + top_sum[p&1][j]+= a>>(p>>1); + } + } + for(;i<12;i++){ + a=src[area4+i]<<4; + for(j=7;j<8;j++){ + p=abs(i-j); + top_sum[p&1][j]+= a>>(p>>1); + } + } + + for(i=0;i<8;i++){ + top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2 + left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8; + } + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x] = ( + (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] + + (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] + + 0x8000 + )>>16; + } + dst+=linesize; + } +} +static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ]; + } + dst+=linesize; + } +} +static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=src[area4 +1+y+x]; + } + dst+=linesize; + } +} +static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=src[area4 +((y+1)>>1)+x]; + } + dst+=linesize; + } +} +static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1; + } + dst+=linesize; + } +} +static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + if(2*x-y<0){ + dst[x]=src[area2+9+2*x-y]; + }else{ + dst[x]=src[area4 +x-((y+1)>>1)]; + } + } + dst+=linesize; + } +} +static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=src[area3+x-y]; + } + dst+=linesize; + } +} +static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + if(x-2*y>0){ + dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1; + }else{ + dst[x]=src[area2+8-y +(x>>1)]; + } + } + dst+=linesize; + } +} +static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1; + } + dst+=linesize; + } +} +static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=src[area2+6-FFMIN(x+y,6)]; + } + dst+=linesize; + } +} +static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3; + } + dst+=linesize; + } +} +static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){ + int x,y; + + for(y=0;y<8;y++){ + for(x=0;x<8;x++){ + dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3; + } + dst+=linesize; + } +} + +static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){ + int i,t; + int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9; + int ql=(quant+10)>>3; + + for(i=0; i<8; i++,ptr+=b_stride){ + p0=ptr[-5*a_stride]; + p1=ptr[-4*a_stride]; + p2=ptr[-3*a_stride]; + p3=ptr[-2*a_stride]; + p4=ptr[-1*a_stride]; + p5=ptr[ 0 ]; + p6=ptr[ 1*a_stride]; + p7=ptr[ 2*a_stride]; + p8=ptr[ 3*a_stride]; + p9=ptr[ 4*a_stride]; + + t= + (FFABS(p1-p2) <= ql) + + (FFABS(p2-p3) <= ql) + + (FFABS(p3-p4) <= ql) + + (FFABS(p4-p5) <= ql); + if(t>0){//You need at least 1 to be able to reach a total score of 6. + t+= + (FFABS(p5-p6) <= ql) + + (FFABS(p6-p7) <= ql) + + (FFABS(p7-p8) <= ql) + + (FFABS(p8-p9) <= ql) + + (FFABS(p0-p1) <= ql); + if(t>=6){ + int min,max; + + min=max=p1; + min=FFMIN(min,p3); max=FFMAX(max,p3); + min=FFMIN(min,p5); max=FFMAX(max,p5); + min=FFMIN(min,p8); max=FFMAX(max,p8); + if(max-min<2*quant){//early stop + min=FFMIN(min,p2); max=FFMAX(max,p2); + min=FFMIN(min,p4); max=FFMAX(max,p4); + min=FFMIN(min,p6); max=FFMAX(max,p6); + min=FFMIN(min,p7); max=FFMAX(max,p7); + if(max-min<2*quant){ + ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3; + ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3; + ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3; + ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3; + continue; + }; + } + } + } + { + int x,x0,x1,x2; + int m; + + x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3; + if(FFABS(x0) < quant){ + x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3; + x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3; + + x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) ); + m=p4-p5; + + if( x > 0 && (m^x0) <0){ + int32_t sign; + + sign=m>>31; + m=(m^sign)-sign;//abs(m) + m>>=1; + + x=(5*x)>>3; + + if(x>m) x=m; + + x=(x^sign)-sign; + + ptr[-1*a_stride] -= x; + ptr[ 0] += x; + } + } + } + } +} + +static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){ + x8_loop_filter(src, stride, 1, qscale); +} + +static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){ + x8_loop_filter(src, 1, stride, qscale); +} + +av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp) +{ + dsp->h_loop_filter=x8_h_loop_filter; + dsp->v_loop_filter=x8_v_loop_filter; + dsp->setup_spatial_compensation=x8_setup_spatial_compensation; + dsp->spatial_compensation[0]=spatial_compensation_0; + dsp->spatial_compensation[1]=spatial_compensation_1; + dsp->spatial_compensation[2]=spatial_compensation_2; + dsp->spatial_compensation[3]=spatial_compensation_3; + dsp->spatial_compensation[4]=spatial_compensation_4; + dsp->spatial_compensation[5]=spatial_compensation_5; + dsp->spatial_compensation[6]=spatial_compensation_6; + dsp->spatial_compensation[7]=spatial_compensation_7; + dsp->spatial_compensation[8]=spatial_compensation_8; + dsp->spatial_compensation[9]=spatial_compensation_9; + dsp->spatial_compensation[10]=spatial_compensation_10; + dsp->spatial_compensation[11]=spatial_compensation_11; +} diff --git a/ffmpeg/libavcodec/intrax8dsp.h b/ffmpeg/libavcodec/intrax8dsp.h new file mode 100644 index 0000000..1e4a3af --- /dev/null +++ b/ffmpeg/libavcodec/intrax8dsp.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef AVCODEC_INTRAX8DSP_H +#define AVCODEC_INTRAX8DSP_H + +#include + +typedef struct IntraX8DSPContext { + void (*v_loop_filter)(uint8_t *src, int stride, int qscale); + void (*h_loop_filter)(uint8_t *src, int stride, int qscale); + + void (*spatial_compensation[12])(uint8_t *src , uint8_t *dst, int linesize); + void (*setup_spatial_compensation)(uint8_t *src, uint8_t *dst, int linesize, + int *range, int *sum, int edges); +} IntraX8DSPContext; + +void ff_intrax8dsp_init(IntraX8DSPContext *dsp); + +#endif /* AVCODEC_INTRAX8DSP_H */ diff --git a/ffmpeg/libavcodec/intrax8huf.h b/ffmpeg/libavcodec/intrax8huf.h new file mode 100644 index 0000000..375906b --- /dev/null +++ b/ffmpeg/libavcodec/intrax8huf.h @@ -0,0 +1,918 @@ +/* + * 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 + */ + +#ifndef AVCODEC_INTRAX8HUF_H +#define AVCODEC_INTRAX8HUF_H + +#include + + +static const uint16_t x8_orient_lowquant_table[4][12][2]={ + {//0 + {0x0000, 1}, {0x0004, 3}, {0x0005, 3}, {0x000C, 4}, + {0x000D, 4}, {0x0038, 6}, {0x001D, 5}, {0x0039, 6}, + {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6}, + },{//1 + {0x0000, 5}, {0x0001, 5}, {0x0002, 5}, {0x0001, 2}, + {0x0002, 2}, {0x0002, 4}, {0x0003, 5}, {0x0006, 3}, + {0x0003, 4}, {0x000E, 4}, {0x001E, 5}, {0x001F, 5}, + },{//2 + {0x0000, 2}, {0x0001, 2}, {0x0004, 3}, {0x0005, 3}, + {0x0006, 3}, {0x0038, 6}, {0x0039, 6}, {0x001D, 5}, + {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6}, + },{//3 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0001, 2}, + {0x0002, 2}, {0x0018, 5}, {0x0019, 5}, {0x000D, 4}, + {0x001C, 5}, {0x001D, 5}, {0x001E, 5}, {0x001F, 5}, + } +}; + +static const uint16_t x8_orient_highquant_table[2][12][2]={ + {//0 + {0x0000, 2}, {0x0001, 2}, {0x0004, 3}, {0x0005, 3}, + {0x0006, 3}, {0x0038, 6}, {0x001D, 5}, {0x0039, 6}, + {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, {0x003F, 6}, + },{//1 + {0x0000, 1}, {0x0002, 2}, {0x0006, 3}, {0x001C, 5}, + {0x001D, 5}, {0x0078, 7}, {0x003D, 6}, {0x0079, 7}, + {0x007C, 7}, {0x007D, 7}, {0x007E, 7}, {0x007F, 7}, + } +}; +#define MAX_OR_VLC_BITS 7 + + +static const uint16_t x8_dc_lowquant_table[8][34][2]={ + {//0 + {0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0004, 5}, + {0x0005, 5}, {0x0006, 5}, {0x000E, 6}, {0x000F, 6}, + {0x0040, 8}, {0x0041, 8}, {0x0840, 13}, {0x0841, 13}, + {0x0842, 13}, {0x0843, 13}, {0x0844, 13}, {0x0845, 13}, + {0x0846, 13}, {0x0002, 2}, {0x0003, 2}, {0x0003, 3}, + {0x0005, 4}, {0x0009, 5}, {0x0011, 6}, {0x0043, 8}, + {0x0085, 9}, {0x0847, 13}, {0x0848, 13}, {0x0849, 13}, + {0x084A, 13}, {0x084B, 13}, {0x084C, 13}, {0x084D, 13}, + {0x084E, 13}, {0x084F, 13}, + },{//1 + {0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4}, + {0x0006, 4}, {0x0004, 3}, {0x0007, 4}, {0x0005, 3}, + {0x000C, 4}, {0x000D, 4}, {0x001C, 5}, {0x003A, 6}, + {0x01D8, 9}, {0x01D9, 9}, {0x1DA0, 13}, {0x1DA1, 13}, + {0x1DA2, 13}, {0x003C, 6}, {0x003D, 6}, {0x003E, 6}, + {0x0077, 7}, {0x01DB, 9}, {0x007E, 7}, {0x00FE, 8}, + {0x01FE, 9}, {0x1DA3, 13}, {0x1DA4, 13}, {0x1DA5, 13}, + {0x0ED3, 12}, {0x0ED4, 12}, {0x01FF, 9}, {0x0ED5, 12}, + {0x0ED6, 12}, {0x0ED7, 12}, + },{//2 + {0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4}, + {0x0006, 4}, {0x0007, 4}, {0x0008, 4}, {0x0009, 4}, + {0x0028, 6}, {0x0029, 6}, {0x0054, 7}, {0x0055, 7}, + {0x0AC0, 12}, {0x0AC1, 12}, {0x0AC2, 12}, {0x0AC3, 12}, + {0x0AC4, 12}, {0x000B, 4}, {0x0006, 3}, {0x000E, 4}, + {0x001E, 5}, {0x003E, 6}, {0x003F, 6}, {0x0057, 7}, + {0x00AD, 8}, {0x0AC5, 12}, {0x0AC6, 12}, {0x0AC7, 12}, + {0x0AC8, 12}, {0x0AC9, 12}, {0x0ACA, 12}, {0x0ACB, 12}, + {0x0566, 11}, {0x0567, 11}, + },{//3 + {0x0000, 4}, {0x0001, 2}, {0x0001, 3}, {0x0004, 3}, + {0x0005, 3}, {0x0006, 3}, {0x0001, 4}, {0x000E, 4}, + {0x003C, 6}, {0x003D, 6}, {0x007C, 7}, {0x00FA, 8}, + {0x3EC0, 14}, {0x3EC1, 14}, {0x3EC2, 14}, {0x3EC3, 14}, + {0x1F62, 13}, {0x01F7, 9}, {0x007E, 7}, {0x00FE, 8}, + {0x00FF, 8}, {0x1F63, 13}, {0x1F64, 13}, {0x1F65, 13}, + {0x1F66, 13}, {0x1F67, 13}, {0x1F68, 13}, {0x1F69, 13}, + {0x1F6A, 13}, {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13}, + {0x1F6E, 13}, {0x1F6F, 13}, + },{//4 + {0x0000, 7}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7}, + {0x0004, 7}, {0x0005, 7}, {0x0006, 7}, {0x0007, 7}, + {0x0008, 7}, {0x0009, 7}, {0x000A, 7}, {0x000B, 7}, + {0x000C, 7}, {0x000D, 7}, {0x000E, 7}, {0x000F, 7}, + {0x0010, 7}, {0x0001, 1}, {0x0001, 2}, {0x0011, 7}, + {0x0012, 7}, {0x0013, 7}, {0x0014, 7}, {0x0015, 7}, + {0x0016, 7}, {0x0017, 7}, {0x0018, 7}, {0x0019, 7}, + {0x001A, 7}, {0x001B, 7}, {0x001C, 7}, {0x001D, 7}, + {0x001E, 7}, {0x001F, 7}, + },{//5 + {0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0008, 6}, + {0x0009, 6}, {0x000A, 6}, {0x0016, 7}, {0x000C, 6}, + {0x0017, 7}, {0x000D, 6}, {0x0038, 8}, {0x001D, 7}, + {0x0039, 8}, {0x0780, 13}, {0x0781, 13}, {0x0782, 13}, + {0x0783, 13}, {0x0002, 3}, {0x0001, 1}, {0x0003, 3}, + {0x001F, 7}, {0x003D, 8}, {0x0079, 9}, {0x0784, 13}, + {0x0785, 13}, {0x0786, 13}, {0x0787, 13}, {0x0788, 13}, + {0x0789, 13}, {0x078A, 13}, {0x078B, 13}, {0x078C, 13}, + {0x078D, 13}, {0x03C7, 12}, + },{//6 + {0x0000, 4}, {0x0001, 2}, {0x0001, 3}, {0x0004, 3}, + {0x0001, 4}, {0x000A, 4}, {0x0016, 5}, {0x002E, 6}, + {0x005E, 7}, {0x005F, 7}, {0x00C0, 8}, {0x3040, 14}, + {0x3041, 14}, {0x0305, 10}, {0x0183, 9}, {0x3042, 14}, + {0x3043, 14}, {0x000D, 4}, {0x0007, 3}, {0x0019, 5}, + {0x0031, 6}, {0x00C2, 8}, {0x00C3, 8}, {0x3044, 14}, + {0x3045, 14}, {0x3046, 14}, {0x3047, 14}, {0x3048, 14}, + {0x3049, 14}, {0x304A, 14}, {0x304B, 14}, {0x304C, 14}, + {0x304D, 14}, {0x1827, 13}, + },{//7 + {0x0000, 6}, {0x0001, 6}, {0x0002, 6}, {0x0006, 7}, + {0x0007, 7}, {0x0004, 6}, {0x0005, 6}, {0x0006, 6}, + {0x000E, 7}, {0x001E, 8}, {0x001F, 8}, {0x0040, 9}, + {0x0082, 10}, {0x0830, 14}, {0x0831, 14}, {0x0832, 14}, + {0x0833, 14}, {0x0001, 1}, {0x0001, 2}, {0x0003, 4}, + {0x0005, 5}, {0x0009, 6}, {0x0011, 7}, {0x0021, 8}, + {0x0834, 14}, {0x0835, 14}, {0x0836, 14}, {0x0837, 14}, + {0x0838, 14}, {0x0839, 14}, {0x083A, 14}, {0x083B, 14}, + {0x041E, 13}, {0x041F, 13}, + } +}; + +static const uint16_t x8_dc_highquant_table[8][34][2]={ + {//0 + {0x0000, 5}, {0x0001, 4}, {0x0002, 4}, {0x0001, 5}, + {0x0006, 5}, {0x0004, 4}, {0x0007, 5}, {0x000A, 5}, + {0x002C, 7}, {0x002D, 7}, {0x05C0, 12}, {0x05C1, 12}, + {0x05C2, 12}, {0x05C3, 12}, {0x05C4, 12}, {0x05C5, 12}, + {0x05C6, 12}, {0x0003, 3}, {0x0002, 2}, {0x0006, 3}, + {0x000E, 4}, {0x001E, 5}, {0x001F, 5}, {0x002F, 7}, + {0x005D, 8}, {0x05C7, 12}, {0x05C8, 12}, {0x05C9, 12}, + {0x05CA, 12}, {0x05CB, 12}, {0x05CC, 12}, {0x05CD, 12}, + {0x05CE, 12}, {0x05CF, 12}, + },{//1 + {0x0000, 3}, {0x0001, 3}, {0x0002, 3}, {0x0006, 4}, + {0x0007, 4}, {0x0004, 3}, {0x000A, 4}, {0x000B, 4}, + {0x0030, 6}, {0x0062, 7}, {0x0063, 7}, {0x0640, 11}, + {0x0641, 11}, {0x0642, 11}, {0x0643, 11}, {0x0644, 11}, + {0x0645, 11}, {0x0033, 6}, {0x000D, 4}, {0x001C, 5}, + {0x001D, 5}, {0x003C, 6}, {0x001F, 5}, {0x0065, 7}, + {0x007A, 7}, {0x0646, 11}, {0x007B, 7}, {0x0647, 11}, + {0x0648, 11}, {0x0649, 11}, {0x064A, 11}, {0x064B, 11}, + {0x0326, 10}, {0x0327, 10}, + },{//2 + {0x0000, 7}, {0x0001, 7}, {0x0001, 6}, {0x0004, 7}, + {0x0003, 6}, {0x0005, 7}, {0x0010, 8}, {0x0011, 8}, + {0x0240, 13}, {0x0241, 13}, {0x0242, 13}, {0x0243, 13}, + {0x0244, 13}, {0x0245, 13}, {0x0246, 13}, {0x0247, 13}, + {0x0124, 12}, {0x0001, 1}, {0x0001, 2}, {0x0001, 3}, + {0x0003, 5}, {0x0005, 6}, {0x0013, 8}, {0x0125, 12}, + {0x0126, 12}, {0x0127, 12}, {0x0128, 12}, {0x0129, 12}, + {0x012A, 12}, {0x012B, 12}, {0x012C, 12}, {0x012D, 12}, + {0x012E, 12}, {0x012F, 12}, + },{//3 + {0x0000, 4}, {0x0001, 3}, {0x0002, 3}, {0x0001, 4}, + {0x0006, 4}, {0x0004, 3}, {0x0005, 3}, {0x0006, 3}, + {0x000E, 5}, {0x000F, 5}, {0x0070, 7}, {0x0710, 11}, + {0x0711, 11}, {0x0712, 11}, {0x0713, 11}, {0x0714, 11}, + {0x0715, 11}, {0x001D, 5}, {0x0072, 7}, {0x003C, 6}, + {0x003D, 6}, {0x0073, 7}, {0x007C, 7}, {0x007D, 7}, + {0x007E, 7}, {0x0716, 11}, {0x0717, 11}, {0x0718, 11}, + {0x007F, 7}, {0x0719, 11}, {0x071A, 11}, {0x071B, 11}, + {0x038E, 10}, {0x038F, 10}, + },{//4 + {0x0000, 8}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7}, + {0x0002, 9}, {0x0008, 8}, {0x0003, 9}, {0x0240, 14}, + {0x0241, 14}, {0x0242, 14}, {0x0243, 14}, {0x0244, 14}, + {0x0245, 14}, {0x0246, 14}, {0x0247, 14}, {0x0124, 13}, + {0x0125, 13}, {0x0001, 2}, {0x0001, 1}, {0x0001, 3}, + {0x0001, 4}, {0x0003, 6}, {0x0005, 7}, {0x0013, 9}, + {0x0126, 13}, {0x0127, 13}, {0x0128, 13}, {0x0129, 13}, + {0x012A, 13}, {0x012B, 13}, {0x012C, 13}, {0x012D, 13}, + {0x012E, 13}, {0x012F, 13}, + },{//5 + {0x0000, 7}, {0x0001, 7}, {0x0001, 6}, {0x0002, 6}, + {0x0003, 6}, {0x0004, 6}, {0x0005, 6}, {0x0006, 6}, + {0x0007, 6}, {0x0008, 6}, {0x0009, 6}, {0x000A, 6}, + {0x000B, 6}, {0x000C, 6}, {0x000D, 6}, {0x000E, 6}, + {0x000F, 6}, {0x0010, 6}, {0x0011, 6}, {0x0012, 6}, + {0x0013, 6}, {0x0014, 6}, {0x0015, 6}, {0x0016, 6}, + {0x0017, 6}, {0x0018, 6}, {0x0019, 6}, {0x0001, 1}, + {0x001A, 6}, {0x001B, 6}, {0x001C, 6}, {0x001D, 6}, + {0x001E, 6}, {0x001F, 6}, + },{//6 + {0x0000, 5}, {0x0001, 4}, {0x0001, 5}, {0x0004, 5}, + {0x000A, 6}, {0x0006, 5}, {0x000B, 6}, {0x000E, 6}, + {0x003C, 8}, {0x003D, 8}, {0x07C0, 13}, {0x07C1, 13}, + {0x07C2, 13}, {0x07C3, 13}, {0x07C4, 13}, {0x07C5, 13}, + {0x07C6, 13}, {0x0001, 2}, {0x0002, 2}, {0x0006, 3}, + {0x000E, 4}, {0x001E, 5}, {0x001F, 5}, {0x003F, 8}, + {0x007D, 9}, {0x07C7, 13}, {0x07C8, 13}, {0x07C9, 13}, + {0x07CA, 13}, {0x07CB, 13}, {0x07CC, 13}, {0x07CD, 13}, + {0x07CE, 13}, {0x07CF, 13}, + },{//7 + {0x0000, 7}, {0x0001, 7}, {0x0002, 7}, {0x0003, 7}, + {0x0004, 7}, {0x0005, 7}, {0x0006, 7}, {0x0007, 7}, + {0x0008, 7}, {0x0009, 7}, {0x000A, 7}, {0x000B, 7}, + {0x000C, 7}, {0x000D, 7}, {0x000E, 7}, {0x000F, 7}, + {0x0010, 7}, {0x0001, 1}, {0x0001, 2}, {0x0011, 7}, + {0x0012, 7}, {0x0013, 7}, {0x0014, 7}, {0x0015, 7}, + {0x0016, 7}, {0x0017, 7}, {0x0018, 7}, {0x0019, 7}, + {0x001A, 7}, {0x001B, 7}, {0x001C, 7}, {0x001D, 7}, + {0x001E, 7}, {0x001F, 7}, + } +}; +#define MAX_DC_VLC_BITS 14 + + +static const uint16_t x8_ac0_lowquant_table[8][77][2]={ + {//0 + {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, + {0x001E, 6}, {0x003E, 7}, {0x003F, 7}, {0x0040, 7}, + {0x0104, 9}, {0x0083, 8}, {0x0084, 8}, {0x0085, 8}, + {0x020A, 10}, {0x020B, 10}, {0x0218, 10}, {0x0219, 10}, + {0x0009, 4}, {0x0044, 7}, {0x010D, 9}, {0x021C, 10}, + {0x0023, 6}, {0x0045, 7}, {0x0050, 7}, {0x000B, 4}, + {0x000C, 4}, {0x0015, 5}, {0x001A, 5}, {0x001B, 5}, + {0x0029, 6}, {0x0038, 6}, {0x0039, 6}, {0x003A, 6}, + {0x0051, 7}, {0x0076, 7}, {0x0077, 7}, {0x0078, 7}, + {0x0079, 7}, {0x007A, 7}, {0x007B, 7}, {0x00F8, 8}, + {0x010F, 9}, {0x021D, 10}, {0x3E40, 14}, {0x3E41, 14}, + {0x3E42, 14}, {0x3E43, 14}, {0x03E5, 10}, {0x3E44, 14}, + {0x01F3, 9}, {0x3E45, 14}, {0x3E46, 14}, {0x3E47, 14}, + {0x00FA, 8}, {0x3E48, 14}, {0x3E49, 14}, {0x3E4A, 14}, + {0x3E4B, 14}, {0x03EC, 10}, {0x3E4C, 14}, {0x007E, 7}, + {0x00FE, 8}, {0x00FF, 8}, {0x01F7, 9}, {0x3E4D, 14}, + {0x3E4E, 14}, {0x3E4F, 14}, {0x3ED0, 14}, {0x3ED1, 14}, + {0x3ED2, 14}, {0x3ED3, 14}, {0x3ED4, 14}, {0x3ED5, 14}, + {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13}, {0x1F6E, 13}, + {0x1F6F, 13}, + },{//1 + {0x0000, 3}, {0x0004, 5}, {0x0014, 7}, {0x000B, 6}, + {0x000C, 6}, {0x002A, 8}, {0x002B, 8}, {0x0034, 8}, + {0x0D40, 14}, {0x0D41, 14}, {0x001B, 7}, {0x0D42, 14}, + {0x0D43, 14}, {0x0D44, 14}, {0x0D45, 14}, {0x0D46, 14}, + {0x000E, 6}, {0x003C, 8}, {0x0D47, 14}, {0x003D, 8}, + {0x0D48, 14}, {0x0D49, 14}, {0x0D4A, 14}, {0x0001, 2}, + {0x0004, 3}, {0x0014, 5}, {0x000B, 4}, {0x000C, 4}, + {0x000D, 4}, {0x002A, 6}, {0x001F, 7}, {0x0056, 7}, + {0x0057, 7}, {0x0070, 7}, {0x00E2, 8}, {0x0072, 7}, + {0x003A, 6}, {0x003B, 6}, {0x003C, 6}, {0x003D, 6}, + {0x00E3, 8}, {0x0D4B, 14}, {0x00E6, 8}, {0x00E7, 8}, + {0x00F8, 8}, {0x0D4C, 14}, {0x0D4D, 14}, {0x0D4E, 14}, + {0x00F9, 8}, {0x0D4F, 14}, {0x0D50, 14}, {0x0D51, 14}, + {0x06A9, 13}, {0x06AA, 13}, {0x06AB, 13}, {0x06AC, 13}, + {0x06AD, 13}, {0x06AE, 13}, {0x06AF, 13}, {0x003F, 6}, + {0x06B0, 13}, {0x06B1, 13}, {0x06B2, 13}, {0x06B3, 13}, + {0x06B4, 13}, {0x007D, 7}, {0x06B5, 13}, {0x06B6, 13}, + {0x06B7, 13}, {0x06B8, 13}, {0x06B9, 13}, {0x06BA, 13}, + {0x06BB, 13}, {0x06BC, 13}, {0x06BD, 13}, {0x06BE, 13}, + {0x06BF, 13}, + },{//2 + {0x0000, 2}, {0x0002, 3}, {0x0003, 3}, {0x0008, 4}, + {0x0012, 5}, {0x0013, 5}, {0x0028, 6}, {0x0029, 6}, + {0x0054, 7}, {0x0055, 7}, {0x0056, 7}, {0x00AE, 8}, + {0x00AF, 8}, {0x00B0, 8}, {0x0162, 9}, {0x02C6, 10}, + {0x000C, 4}, {0x002D, 6}, {0x00B2, 8}, {0x0166, 9}, + {0x002E, 6}, {0x0167, 9}, {0x00BC, 8}, {0x001A, 5}, + {0x0036, 6}, {0x0037, 6}, {0x0038, 6}, {0x005F, 7}, + {0x0072, 7}, {0x0073, 7}, {0x0074, 7}, {0x0075, 7}, + {0x0076, 7}, {0x0077, 7}, {0x0078, 7}, {0x0079, 7}, + {0x007A, 7}, {0x007B, 7}, {0x00BD, 8}, {0xB1C0, 16}, + {0xB1C1, 16}, {0x58E1, 15}, {0x0B1D, 12}, {0x58E2, 15}, + {0x58E3, 15}, {0x58E4, 15}, {0x00F8, 8}, {0x03E4, 10}, + {0x01F3, 9}, {0x0B1E, 12}, {0x58E5, 15}, {0x58E6, 15}, + {0x00FA, 8}, {0x58E7, 15}, {0x58F8, 15}, {0x58F9, 15}, + {0x58FA, 15}, {0x01F6, 9}, {0x58FB, 15}, {0x007E, 7}, + {0x00FE, 8}, {0x00FF, 8}, {0x07CA, 11}, {0x0F96, 12}, + {0x58FC, 15}, {0x58FD, 15}, {0x58FE, 15}, {0x58FF, 15}, + {0x7CB8, 15}, {0x7CB9, 15}, {0x7CBA, 15}, {0x7CBB, 15}, + {0x7CBC, 15}, {0x01F7, 9}, {0x7CBD, 15}, {0x7CBE, 15}, + {0x7CBF, 15}, + },{//3 + {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, + {0x000F, 5}, {0x0020, 6}, {0x0021, 6}, {0x0044, 7}, + {0x0045, 7}, {0x008C, 8}, {0x008D, 8}, {0x011C, 9}, + {0x011D, 9}, {0x011E, 9}, {0x023E, 10}, {0x023F, 10}, + {0x0005, 3}, {0x0012, 5}, {0x004C, 7}, {0x004D, 7}, + {0x000C, 4}, {0x004E, 7}, {0x001A, 5}, {0x0036, 6}, + {0x004F, 7}, {0x006E, 7}, {0x006F, 7}, {0x00E0, 8}, + {0x00E1, 8}, {0x00E2, 8}, {0x00E3, 8}, {0x00E4, 8}, + {0x00E5, 8}, {0x01CC, 9}, {0x00E7, 8}, {0x00E8, 8}, + {0x00E9, 8}, {0x01CD, 9}, {0x0750, 11}, {0x03A9, 10}, + {0x0751, 11}, {0x7540, 15}, {0x03AB, 10}, {0x7541, 15}, + {0x7542, 15}, {0x7543, 15}, {0x01D6, 9}, {0x0755, 11}, + {0x0076, 7}, {0x0EA9, 12}, {0x7544, 15}, {0x7545, 15}, + {0x001E, 5}, {0x0077, 7}, {0x00F8, 8}, {0x03AE, 10}, + {0x075E, 11}, {0x007D, 7}, {0x03E4, 10}, {0x00FC, 8}, + {0x00FD, 8}, {0x03E5, 10}, {0x03E6, 10}, {0x0EBE, 12}, + {0x7546, 15}, {0x07CE, 11}, {0x7547, 15}, {0x75F8, 15}, + {0x75F9, 15}, {0x75FA, 15}, {0x75FB, 15}, {0x75FC, 15}, + {0x75FD, 15}, {0x007F, 7}, {0x3AFF, 14}, {0x0F9E, 12}, + {0x0F9F, 12}, + },{//4 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0012, 6}, {0x0013, 6}, {0x0014, 6}, {0x002A, 7}, + {0x0016, 6}, {0x002B, 7}, {0x005C, 8}, {0x005D, 8}, + {0x005E, 8}, {0x00BE, 9}, {0x00BF, 9}, {0x0060, 8}, + {0x0007, 4}, {0x000D, 5}, {0x0019, 6}, {0x0020, 6}, + {0x0009, 4}, {0x0021, 6}, {0x0011, 5}, {0x0014, 5}, + {0x002A, 6}, {0x002B, 6}, {0x002C, 6}, {0x002D, 6}, + {0x002E, 6}, {0x002F, 6}, {0x0030, 6}, {0x0031, 7}, + {0x0062, 7}, {0x0063, 7}, {0x0064, 7}, {0x0065, 7}, + {0x0066, 7}, {0x0061, 8}, {0x0670, 11}, {0x0068, 7}, + {0x0069, 7}, {0x00CF, 8}, {0x019D, 9}, {0x01A8, 9}, + {0x01A9, 9}, {0x0339, 10}, {0x01AA, 9}, {0x0356, 10}, + {0x0036, 6}, {0x00D6, 8}, {0x6710, 15}, {0x6711, 15}, + {0x000E, 4}, {0x006E, 7}, {0x01AE, 9}, {0x6712, 15}, + {0x6713, 15}, {0x003C, 6}, {0x0357, 10}, {0x006F, 7}, + {0x00F4, 8}, {0x00F5, 8}, {0x035E, 10}, {0x01EC, 9}, + {0x6714, 15}, {0x01ED, 9}, {0x035F, 10}, {0x03DC, 10}, + {0x03DD, 10}, {0x6715, 15}, {0x338B, 14}, {0x338C, 14}, + {0x338D, 14}, {0x001F, 5}, {0x01EF, 9}, {0x338E, 14}, + {0x338F, 14}, + },{//5 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, + {0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x006A, 8}, + {0x006B, 8}, {0x006C, 8}, {0x00DA, 9}, {0x036C, 11}, + {0x006E, 8}, {0x01B7, 10}, {0x036D, 11}, {0x3780, 15}, + {0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x003E, 7}, + {0x000A, 4}, {0x002C, 6}, {0x0017, 5}, {0x002D, 6}, + {0x003F, 7}, {0x00C0, 8}, {0x0061, 7}, {0x00C1, 8}, + {0x0062, 7}, {0x00C6, 8}, {0x0064, 7}, {0x00C7, 8}, + {0x00CA, 8}, {0x00DF, 9}, {0x0196, 9}, {0x0197, 9}, + {0x0198, 9}, {0x0199, 9}, {0x0379, 11}, {0x019A, 9}, + {0x01BD, 10}, {0x066C, 11}, {0x3781, 15}, {0x0337, 10}, + {0x066D, 11}, {0x0670, 11}, {0x0339, 10}, {0x0671, 11}, + {0x0034, 6}, {0x00CF, 8}, {0x3782, 15}, {0x3783, 15}, + {0x000E, 4}, {0x001B, 5}, {0x006A, 7}, {0x006B, 7}, + {0x019D, 9}, {0x003C, 6}, {0x00F4, 8}, {0x00F5, 8}, + {0x03D8, 10}, {0x07B2, 11}, {0x3784, 15}, {0x03DA, 10}, + {0x3785, 15}, {0x03DB, 10}, {0x03DC, 10}, {0x3786, 15}, + {0x3787, 15}, {0x1BC4, 14}, {0x1BC5, 14}, {0x1BC6, 14}, + {0x1BC7, 14}, {0x001F, 5}, {0x03DD, 10}, {0x07B3, 11}, + {0x01EF, 9}, + },{//6 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6}, + {0x0017, 6}, {0x0060, 8}, {0x00C2, 9}, {0x0186, 10}, + {0x0187, 10}, {0x00C4, 9}, {0x3140, 15}, {0x3141, 15}, + {0x018B, 10}, {0x3142, 15}, {0x018C, 10}, {0x3143, 15}, + {0x0007, 4}, {0x000D, 5}, {0x0064, 8}, {0x0065, 8}, + {0x0010, 5}, {0x00C7, 9}, {0x0066, 8}, {0x0005, 3}, + {0x0006, 3}, {0x0009, 4}, {0x0011, 5}, {0x0038, 6}, + {0x0039, 6}, {0x0074, 7}, {0x0075, 7}, {0x0076, 7}, + {0x0067, 8}, {0x00EE, 8}, {0x01DE, 9}, {0x00F0, 8}, + {0x018D, 10}, {0x3144, 15}, {0x01DF, 9}, {0x003D, 6}, + {0x003E, 6}, {0x01E2, 9}, {0x03C6, 10}, {0x00F2, 8}, + {0x00F3, 8}, {0x03C7, 10}, {0x3145, 15}, {0x3146, 15}, + {0x01F8, 9}, {0x3147, 15}, {0x3148, 15}, {0x3149, 15}, + {0x00FD, 8}, {0x314A, 15}, {0x314B, 15}, {0x314C, 15}, + {0x314D, 15}, {0x01F9, 9}, {0x314E, 15}, {0x01FC, 9}, + {0x314F, 15}, {0x3150, 15}, {0x3151, 15}, {0x3152, 15}, + {0x3153, 15}, {0x03FA, 10}, {0x03FB, 10}, {0x3154, 15}, + {0x3155, 15}, {0x3156, 15}, {0x3157, 15}, {0x3158, 15}, + {0x3159, 15}, {0x00FF, 8}, {0x18AD, 14}, {0x18AE, 14}, + {0x18AF, 14}, + },{//7 + {0x0000, 4}, {0x0080, 11}, {0x0081, 11}, {0x0082, 11}, + {0x0083, 11}, {0x0084, 11}, {0x0085, 11}, {0x0086, 11}, + {0x0087, 11}, {0x0088, 11}, {0x0089, 11}, {0x008A, 11}, + {0x008B, 11}, {0x008C, 11}, {0x008D, 11}, {0x008E, 11}, + {0x008F, 11}, {0x0048, 10}, {0x0049, 10}, {0x004A, 10}, + {0x004B, 10}, {0x004C, 10}, {0x004D, 10}, {0x0001, 1}, + {0x0001, 2}, {0x004E, 10}, {0x0002, 4}, {0x0003, 4}, + {0x004F, 10}, {0x0050, 10}, {0x0051, 10}, {0x0052, 10}, + {0x0053, 10}, {0x0054, 10}, {0x0055, 10}, {0x0056, 10}, + {0x0057, 10}, {0x0058, 10}, {0x0059, 10}, {0x005A, 10}, + {0x005B, 10}, {0x005C, 10}, {0x005D, 10}, {0x005E, 10}, + {0x005F, 10}, {0x0060, 10}, {0x0061, 10}, {0x0062, 10}, + {0x0063, 10}, {0x0064, 10}, {0x0065, 10}, {0x0066, 10}, + {0x0067, 10}, {0x0068, 10}, {0x0069, 10}, {0x006A, 10}, + {0x006B, 10}, {0x006C, 10}, {0x006D, 10}, {0x006E, 10}, + {0x006F, 10}, {0x0070, 10}, {0x0071, 10}, {0x0072, 10}, + {0x0073, 10}, {0x0074, 10}, {0x0075, 10}, {0x0076, 10}, + {0x0077, 10}, {0x0078, 10}, {0x0079, 10}, {0x007A, 10}, + {0x007B, 10}, {0x007C, 10}, {0x007D, 10}, {0x007E, 10}, + {0x007F, 10}, + } +}; + +static const uint16_t x8_ac0_highquant_table[8][77][2]={ + {//0 + {0x0000, 3}, {0x0002, 4}, {0x000C, 6}, {0x000D, 6}, + {0x001C, 7}, {0x000F, 6}, {0x1D00, 15}, {0x003B, 8}, + {0x1D01, 15}, {0x0075, 9}, {0x1D02, 15}, {0x0080, 9}, + {0x1D03, 15}, {0x1D04, 15}, {0x1D05, 15}, {0x0E83, 14}, + {0x0009, 5}, {0x0011, 6}, {0x0081, 9}, {0x0082, 9}, + {0x0021, 7}, {0x0028, 7}, {0x0083, 9}, {0x0002, 2}, + {0x0003, 3}, {0x000C, 4}, {0x000D, 4}, {0x000B, 5}, + {0x0015, 6}, {0x0052, 8}, {0x0070, 7}, {0x0039, 6}, + {0x0071, 7}, {0x0053, 8}, {0x0E84, 14}, {0x0074, 7}, + {0x0075, 7}, {0x0076, 7}, {0x01DC, 9}, {0x001E, 5}, + {0x003E, 6}, {0x01DD, 9}, {0x00EF, 8}, {0x01F8, 9}, + {0x01F9, 9}, {0x0E85, 14}, {0x0E86, 14}, {0x0E87, 14}, + {0x00FD, 8}, {0x0E88, 14}, {0x0E89, 14}, {0x0E8A, 14}, + {0x0E8B, 14}, {0x0E8C, 14}, {0x0E8D, 14}, {0x0E8E, 14}, + {0x0E8F, 14}, {0x0E90, 14}, {0x0E91, 14}, {0x01FC, 9}, + {0x0E92, 14}, {0x0E93, 14}, {0x0E94, 14}, {0x0E95, 14}, + {0x0E96, 14}, {0x0E97, 14}, {0x01FD, 9}, {0x0E98, 14}, + {0x01FE, 9}, {0x0E99, 14}, {0x0E9A, 14}, {0x0E9B, 14}, + {0x0E9C, 14}, {0x01FF, 9}, {0x0E9D, 14}, {0x0E9E, 14}, + {0x0E9F, 14}, + },{//1 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0012, 6}, {0x0013, 6}, {0x0014, 6}, {0x0015, 6}, + {0x002C, 7}, {0x005A, 8}, {0x005B, 8}, {0x005C, 8}, + {0x005D, 8}, {0x1780, 14}, {0x0179, 10}, {0x017A, 10}, + {0x0006, 4}, {0x000E, 5}, {0x001E, 6}, {0x003E, 7}, + {0x0010, 5}, {0x0022, 6}, {0x0012, 5}, {0x000A, 4}, + {0x0013, 5}, {0x0016, 5}, {0x0023, 6}, {0x002E, 6}, + {0x002F, 6}, {0x0030, 6}, {0x0031, 6}, {0x003F, 7}, + {0x005F, 8}, {0x00C8, 8}, {0x0065, 7}, {0x0066, 7}, + {0x0067, 7}, {0x0068, 7}, {0x00C9, 8}, {0x0069, 7}, + {0x006A, 7}, {0x00D6, 8}, {0x00D7, 8}, {0x00D8, 8}, + {0x1781, 14}, {0x017B, 10}, {0x01B2, 9}, {0x1782, 14}, + {0x001C, 5}, {0x01B3, 9}, {0x1783, 14}, {0x1784, 14}, + {0x001D, 5}, {0x00DA, 8}, {0x1785, 14}, {0x1786, 14}, + {0x1787, 14}, {0x0037, 6}, {0x00DB, 8}, {0x0078, 7}, + {0x00F2, 8}, {0x01E6, 9}, {0x00F4, 8}, {0x1788, 14}, + {0x1789, 14}, {0x00F5, 8}, {0x01E7, 9}, {0x178A, 14}, + {0x178B, 14}, {0x178C, 14}, {0x178D, 14}, {0x01EC, 9}, + {0x178E, 14}, {0x001F, 5}, {0x00F7, 8}, {0x01ED, 9}, + {0x178F, 14}, + },{//2 + {0x0000, 4}, {0x0002, 5}, {0x0180, 12}, {0x0181, 12}, + {0x0182, 12}, {0x0183, 12}, {0x0184, 12}, {0x0185, 12}, + {0x0186, 12}, {0x0187, 12}, {0x0188, 12}, {0x0189, 12}, + {0x00C5, 11}, {0x00C6, 11}, {0x00C7, 11}, {0x00C8, 11}, + {0x00C9, 11}, {0x00CA, 11}, {0x00CB, 11}, {0x00CC, 11}, + {0x00CD, 11}, {0x00CE, 11}, {0x00CF, 11}, {0x0001, 1}, + {0x0001, 2}, {0x0004, 5}, {0x0005, 5}, {0x0006, 5}, + {0x00D0, 11}, {0x00D1, 11}, {0x00D2, 11}, {0x00D3, 11}, + {0x00D4, 11}, {0x00D5, 11}, {0x00D6, 11}, {0x00D7, 11}, + {0x00D8, 11}, {0x00D9, 11}, {0x00DA, 11}, {0x0007, 5}, + {0x00DB, 11}, {0x00DC, 11}, {0x00DD, 11}, {0x00DE, 11}, + {0x00DF, 11}, {0x00E0, 11}, {0x00E1, 11}, {0x00E2, 11}, + {0x00E3, 11}, {0x00E4, 11}, {0x00E5, 11}, {0x00E6, 11}, + {0x00E7, 11}, {0x00E8, 11}, {0x00E9, 11}, {0x00EA, 11}, + {0x00EB, 11}, {0x00EC, 11}, {0x00ED, 11}, {0x00EE, 11}, + {0x00EF, 11}, {0x00F0, 11}, {0x00F1, 11}, {0x00F2, 11}, + {0x00F3, 11}, {0x00F4, 11}, {0x00F5, 11}, {0x00F6, 11}, + {0x00F7, 11}, {0x00F8, 11}, {0x00F9, 11}, {0x00FA, 11}, + {0x00FB, 11}, {0x00FC, 11}, {0x00FD, 11}, {0x00FE, 11}, + {0x00FF, 11}, + },{//3 + {0x0000, 8}, {0x0001, 8}, {0x0002, 8}, {0x0003, 8}, + {0x0004, 8}, {0x0005, 8}, {0x0006, 8}, {0x0007, 8}, + {0x0008, 8}, {0x0009, 8}, {0x000A, 8}, {0x000B, 8}, + {0x000C, 8}, {0x000D, 8}, {0x000E, 8}, {0x000F, 8}, + {0x0010, 8}, {0x0011, 8}, {0x0012, 8}, {0x0013, 8}, + {0x0014, 8}, {0x0015, 8}, {0x0016, 8}, {0x0001, 1}, + {0x0017, 8}, {0x000C, 7}, {0x000D, 7}, {0x000E, 7}, + {0x000F, 7}, {0x0010, 7}, {0x0011, 7}, {0x0012, 7}, + {0x0013, 7}, {0x0014, 7}, {0x0015, 7}, {0x0016, 7}, + {0x0017, 7}, {0x0018, 7}, {0x0019, 7}, {0x001A, 7}, + {0x001B, 7}, {0x001C, 7}, {0x001D, 7}, {0x001E, 7}, + {0x001F, 7}, {0x0020, 7}, {0x0021, 7}, {0x0022, 7}, + {0x0023, 7}, {0x0024, 7}, {0x0025, 7}, {0x0026, 7}, + {0x0027, 7}, {0x0028, 7}, {0x0029, 7}, {0x002A, 7}, + {0x002B, 7}, {0x002C, 7}, {0x002D, 7}, {0x002E, 7}, + {0x002F, 7}, {0x0030, 7}, {0x0031, 7}, {0x0032, 7}, + {0x0033, 7}, {0x0034, 7}, {0x0035, 7}, {0x0036, 7}, + {0x0037, 7}, {0x0038, 7}, {0x0039, 7}, {0x003A, 7}, + {0x003B, 7}, {0x003C, 7}, {0x003D, 7}, {0x003E, 7}, + {0x003F, 7}, + },{//4 + {0x0000, 9}, {0x0001, 9}, {0x0002, 9}, {0x0003, 9}, + {0x0004, 9}, {0x0005, 9}, {0x0006, 9}, {0x0007, 9}, + {0x0008, 9}, {0x0009, 9}, {0x000A, 9}, {0x000B, 9}, + {0x000C, 9}, {0x000D, 9}, {0x000E, 9}, {0x000F, 9}, + {0x0010, 9}, {0x0011, 9}, {0x0012, 9}, {0x0013, 9}, + {0x0014, 9}, {0x0015, 9}, {0x000B, 8}, {0x0001, 2}, + {0x0001, 1}, {0x000C, 8}, {0x000D, 8}, {0x000E, 8}, + {0x000F, 8}, {0x0010, 8}, {0x0011, 8}, {0x0012, 8}, + {0x0013, 8}, {0x0014, 8}, {0x0015, 8}, {0x0016, 8}, + {0x0017, 8}, {0x0018, 8}, {0x0019, 8}, {0x001A, 8}, + {0x001B, 8}, {0x001C, 8}, {0x001D, 8}, {0x001E, 8}, + {0x001F, 8}, {0x0020, 8}, {0x0021, 8}, {0x0022, 8}, + {0x0023, 8}, {0x0024, 8}, {0x0025, 8}, {0x0026, 8}, + {0x0027, 8}, {0x0028, 8}, {0x0029, 8}, {0x002A, 8}, + {0x002B, 8}, {0x002C, 8}, {0x002D, 8}, {0x002E, 8}, + {0x002F, 8}, {0x0030, 8}, {0x0031, 8}, {0x0032, 8}, + {0x0033, 8}, {0x0034, 8}, {0x0035, 8}, {0x0036, 8}, + {0x0037, 8}, {0x0038, 8}, {0x0039, 8}, {0x003A, 8}, + {0x003B, 8}, {0x003C, 8}, {0x003D, 8}, {0x003E, 8}, + {0x003F, 8}, + },{//5 + {0x0000, 10}, {0x0001, 10}, {0x0002, 10}, {0x0003, 10}, + {0x0004, 10}, {0x0005, 10}, {0x0006, 10}, {0x0007, 10}, + {0x0008, 10}, {0x0009, 10}, {0x000A, 10}, {0x000B, 10}, + {0x000C, 10}, {0x000D, 10}, {0x000E, 10}, {0x000F, 10}, + {0x0010, 10}, {0x0011, 10}, {0x0012, 10}, {0x0013, 10}, + {0x000A, 9}, {0x000B, 9}, {0x000C, 9}, {0x0001, 1}, + {0x0001, 3}, {0x000D, 9}, {0x000E, 9}, {0x0001, 2}, + {0x000F, 9}, {0x0010, 9}, {0x0011, 9}, {0x0012, 9}, + {0x0013, 9}, {0x0014, 9}, {0x0015, 9}, {0x0016, 9}, + {0x0017, 9}, {0x0018, 9}, {0x0019, 9}, {0x001A, 9}, + {0x001B, 9}, {0x001C, 9}, {0x001D, 9}, {0x001E, 9}, + {0x001F, 9}, {0x0020, 9}, {0x0021, 9}, {0x0022, 9}, + {0x0023, 9}, {0x0024, 9}, {0x0025, 9}, {0x0026, 9}, + {0x0027, 9}, {0x0028, 9}, {0x0029, 9}, {0x002A, 9}, + {0x002B, 9}, {0x002C, 9}, {0x002D, 9}, {0x002E, 9}, + {0x002F, 9}, {0x0030, 9}, {0x0031, 9}, {0x0032, 9}, + {0x0033, 9}, {0x0034, 9}, {0x0035, 9}, {0x0036, 9}, + {0x0037, 9}, {0x0038, 9}, {0x0039, 9}, {0x003A, 9}, + {0x003B, 9}, {0x003C, 9}, {0x003D, 9}, {0x003E, 9}, + {0x003F, 9}, + },{//6 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, + {0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x006A, 8}, + {0x006B, 8}, {0x006C, 8}, {0x00DA, 9}, {0x00DB, 9}, + {0x01B8, 10}, {0x00DD, 9}, {0x01B9, 10}, {0x3780, 15}, + {0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x001F, 6}, + {0x000A, 4}, {0x0058, 7}, {0x0017, 5}, {0x0018, 5}, + {0x0059, 7}, {0x005A, 7}, {0x005B, 7}, {0x00C8, 8}, + {0x0065, 7}, {0x0066, 7}, {0x00C9, 8}, {0x00CE, 8}, + {0x00CF, 8}, {0x00D0, 8}, {0x00D1, 8}, {0x00D2, 8}, + {0x00D3, 8}, {0x00DF, 9}, {0x00D4, 8}, {0x00D5, 8}, + {0x00D6, 8}, {0x01AE, 9}, {0x3781, 15}, {0x01BD, 10}, + {0x035E, 10}, {0x035F, 10}, {0x3782, 15}, {0x0360, 10}, + {0x0037, 6}, {0x01B1, 9}, {0x3783, 15}, {0x3784, 15}, + {0x000E, 4}, {0x003C, 6}, {0x0361, 10}, {0x3785, 15}, + {0x1BC3, 14}, {0x003D, 6}, {0x00D9, 8}, {0x1BC4, 14}, + {0x0368, 10}, {0x1BC5, 14}, {0x1BC6, 14}, {0x1BC7, 14}, + {0x1BC8, 14}, {0x00DB, 8}, {0x0369, 10}, {0x036A, 10}, + {0x1BC9, 14}, {0x1BCA, 14}, {0x1BCB, 14}, {0x1BCC, 14}, + {0x1BCD, 14}, {0x001F, 5}, {0x036B, 10}, {0x1BCE, 14}, + {0x1BCF, 14}, + },{//7 + {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5}, + {0x0010, 6}, {0x0044, 8}, {0x0023, 7}, {0x0012, 6}, + {0x0026, 7}, {0x08A0, 13}, {0x004E, 8}, {0x004F, 8}, + {0x08A1, 13}, {0x08A2, 13}, {0x08A3, 13}, {0x0050, 8}, + {0x0006, 4}, {0x000B, 5}, {0x0029, 7}, {0x0015, 6}, + {0x001C, 6}, {0x003A, 7}, {0x001E, 6}, {0x0004, 3}, + {0x0014, 5}, {0x0015, 5}, {0x000B, 4}, {0x001F, 6}, + {0x0030, 6}, {0x0031, 6}, {0x0019, 5}, {0x0051, 8}, + {0x0034, 6}, {0x0035, 6}, {0x0036, 6}, {0x0037, 6}, + {0x0076, 8}, {0x0077, 8}, {0x0070, 7}, {0x001D, 5}, + {0x0071, 7}, {0x0072, 7}, {0x08A4, 13}, {0x0073, 7}, + {0x00F0, 8}, {0x08A5, 13}, {0x08A6, 13}, {0x08A7, 13}, + {0x0079, 7}, {0x007A, 7}, {0x08A8, 13}, {0x08A9, 13}, + {0x00F1, 8}, {0x08AA, 13}, {0x08AB, 13}, {0x08AC, 13}, + {0x08AD, 13}, {0x00F6, 8}, {0x08AE, 13}, {0x007C, 7}, + {0x00F7, 8}, {0x08AF, 13}, {0x08B0, 13}, {0x08B1, 13}, + {0x08B2, 13}, {0x00FA, 8}, {0x08B3, 13}, {0x08B4, 13}, + {0x08B5, 13}, {0x08B6, 13}, {0x08B7, 13}, {0x00FB, 8}, + {0x045C, 12}, {0x003F, 6}, {0x045D, 12}, {0x045E, 12}, + {0x045F, 12}, + } +}; + +static const uint16_t x8_ac1_lowquant_table[8][77][2]={ + {//0 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0012, 6}, {0x0026, 7}, {0x0014, 6}, {0x004E, 8}, + {0x004F, 8}, {0x00A8, 9}, {0x0152, 10}, {0x00AA, 9}, + {0x00AB, 9}, {0x00AC, 9}, {0x2A60, 15}, {0x02A7, 11}, + {0x0006, 4}, {0x000B, 5}, {0x001C, 6}, {0x003A, 7}, + {0x000F, 5}, {0x003B, 7}, {0x0010, 5}, {0x0005, 3}, + {0x0009, 4}, {0x0011, 5}, {0x0018, 5}, {0x0019, 5}, + {0x001A, 5}, {0x0036, 6}, {0x0037, 6}, {0x0070, 7}, + {0x0057, 8}, {0x00E2, 8}, {0x00E3, 8}, {0x00E4, 8}, + {0x00E5, 8}, {0x00AD, 9}, {0x0398, 10}, {0x003A, 6}, + {0x0076, 7}, {0x00E7, 8}, {0x00EE, 8}, {0x00EF, 8}, + {0x0732, 11}, {0x039A, 10}, {0x0733, 11}, {0x2A61, 15}, + {0x0078, 7}, {0x1531, 14}, {0x1532, 14}, {0x1533, 14}, + {0x003D, 6}, {0x039B, 10}, {0x1534, 14}, {0x1535, 14}, + {0x1536, 14}, {0x0079, 7}, {0x1537, 14}, {0x00F8, 8}, + {0x01F2, 9}, {0x07CC, 11}, {0x03E7, 10}, {0x07CD, 11}, + {0x3E80, 14}, {0x00FB, 8}, {0x03E9, 10}, {0x3E81, 14}, + {0x3E82, 14}, {0x3E83, 14}, {0x3E84, 14}, {0x3E85, 14}, + {0x3E86, 14}, {0x003F, 6}, {0x01F5, 9}, {0x07D1, 11}, + {0x3E87, 14}, + },{//1 + {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, + {0x001E, 6}, {0x001F, 6}, {0x0040, 7}, {0x0082, 8}, + {0x0083, 8}, {0x0084, 8}, {0x010A, 9}, {0x010B, 9}, + {0x0430, 11}, {0x0431, 11}, {0x0432, 11}, {0x0433, 11}, + {0x0005, 3}, {0x0011, 5}, {0x0024, 6}, {0x004A, 7}, + {0x000C, 4}, {0x0026, 6}, {0x000D, 4}, {0x0087, 8}, + {0x010D, 9}, {0x0258, 10}, {0x012D, 9}, {0x0259, 10}, + {0x025C, 10}, {0x0974, 12}, {0x025E, 10}, {0x025F, 10}, + {0x0270, 10}, {0x0271, 10}, {0x04BB, 11}, {0x0975, 12}, + {0x0272, 10}, {0x09CC, 12}, {0x09CD, 12}, {0x4E70, 15}, + {0x4E71, 15}, {0x4E72, 15}, {0x4E73, 15}, {0x273A, 14}, + {0x273B, 14}, {0x273C, 14}, {0x04E8, 11}, {0x04E9, 11}, + {0x009E, 8}, {0x0275, 10}, {0x09D8, 12}, {0x273D, 14}, + {0x000E, 4}, {0x003C, 6}, {0x007A, 7}, {0x009F, 8}, + {0x0277, 10}, {0x003E, 6}, {0x00F6, 8}, {0x04ED, 11}, + {0x03DC, 10}, {0x273E, 14}, {0x07BA, 11}, {0x09D9, 12}, + {0x273F, 14}, {0x3DD8, 14}, {0x3DD9, 14}, {0x3DDA, 14}, + {0x3DDB, 14}, {0x3DDC, 14}, {0x3DDD, 14}, {0x3DDE, 14}, + {0x3DDF, 14}, {0x003F, 6}, {0x07BC, 11}, {0x07BD, 11}, + {0x03DF, 10}, + },{//2 + {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x000E, 6}, + {0x001E, 7}, {0x003E, 8}, {0x003F, 8}, {0x0040, 8}, + {0x0104, 10}, {0x0083, 9}, {0x0105, 10}, {0x0108, 10}, + {0x4240, 16}, {0x010A, 10}, {0x010B, 10}, {0x4241, 16}, + {0x0003, 3}, {0x0009, 5}, {0x0011, 6}, {0x0043, 8}, + {0x0004, 3}, {0x000A, 5}, {0x000A, 4}, {0x002C, 7}, + {0x00B4, 9}, {0x00B5, 9}, {0x00B6, 9}, {0x00B7, 9}, + {0x00B8, 9}, {0x0172, 10}, {0x0173, 10}, {0x0174, 10}, + {0x0175, 10}, {0x0176, 10}, {0x0177, 10}, {0x00BC, 9}, + {0x017A, 10}, {0x0213, 11}, {0x4242, 16}, {0x017B, 10}, + {0x02F8, 11}, {0x017D, 10}, {0x02F9, 11}, {0x017E, 10}, + {0x4243, 16}, {0x02FE, 11}, {0x2122, 15}, {0x2123, 15}, + {0x0058, 7}, {0x0164, 9}, {0x2124, 15}, {0x2125, 15}, + {0x0006, 3}, {0x000E, 4}, {0x002D, 6}, {0x002E, 6}, + {0x00B3, 8}, {0x001E, 5}, {0x005E, 7}, {0x2126, 15}, + {0x2127, 15}, {0x2128, 15}, {0x2129, 15}, {0x02FF, 11}, + {0x212A, 15}, {0x0594, 11}, {0x0595, 11}, {0x0596, 11}, + {0x212B, 15}, {0x212C, 15}, {0x212D, 15}, {0x212E, 15}, + {0x212F, 15}, {0x001F, 5}, {0x0597, 11}, {0x00BE, 8}, + {0x00BF, 8}, + },{//3 + {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x0007, 4}, + {0x0010, 5}, {0x0011, 5}, {0x0024, 6}, {0x0025, 6}, + {0x0026, 6}, {0x0027, 6}, {0x0050, 7}, {0x0051, 7}, + {0x00A4, 8}, {0x00A5, 8}, {0x00A6, 8}, {0x014E, 9}, + {0x000B, 4}, {0x002A, 6}, {0x0056, 7}, {0x014F, 9}, + {0x0030, 6}, {0x00AE, 8}, {0x0062, 7}, {0x0032, 6}, + {0x0033, 6}, {0x0034, 6}, {0x0035, 6}, {0x0036, 6}, + {0x0063, 7}, {0x006E, 7}, {0x006F, 7}, {0x0070, 7}, + {0x0071, 7}, {0x0072, 7}, {0x0073, 7}, {0x0074, 7}, + {0x00AF, 8}, {0x00EA, 8}, {0x01D6, 9}, {0x075C, 11}, + {0x03AF, 10}, {0x75D0, 15}, {0x75D1, 15}, {0x75D2, 15}, + {0x75D3, 15}, {0x75D4, 15}, {0x0076, 7}, {0x00EE, 8}, + {0x00EF, 8}, {0x0EBB, 12}, {0x01E0, 9}, {0x75D5, 15}, + {0x0079, 7}, {0x01E1, 9}, {0x75D6, 15}, {0x75D7, 15}, + {0x7880, 15}, {0x00F4, 8}, {0x0789, 11}, {0x003E, 6}, + {0x007B, 7}, {0x00F5, 8}, {0x00FC, 8}, {0x007F, 7}, + {0x01E3, 9}, {0x078A, 11}, {0x078B, 11}, {0x7881, 15}, + {0x7882, 15}, {0x7883, 15}, {0x3C42, 14}, {0x3C43, 14}, + {0x3C44, 14}, {0x00FD, 8}, {0x3C45, 14}, {0x3C46, 14}, + {0x3C47, 14}, + },{//4 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6}, + {0x0017, 6}, {0x0030, 7}, {0x0031, 7}, {0x0064, 8}, + {0x0065, 8}, {0x0066, 8}, {0x00CE, 9}, {0x00CF, 9}, + {0x01A0, 10}, {0x01A1, 10}, {0x1A20, 14}, {0x0689, 12}, + {0x0004, 3}, {0x000E, 5}, {0x001B, 6}, {0x0035, 7}, + {0x000A, 4}, {0x001E, 6}, {0x0016, 5}, {0x0017, 5}, + {0x001F, 6}, {0x0030, 6}, {0x0031, 6}, {0x0064, 7}, + {0x0065, 7}, {0x0069, 8}, {0x0066, 7}, {0x00CE, 8}, + {0x00CF, 8}, {0x00D0, 8}, {0x00D1, 8}, {0x00D2, 8}, + {0x01A6, 9}, {0x01A3, 10}, {0x034E, 10}, {0x006A, 7}, + {0x00D6, 8}, {0x01AE, 9}, {0x01AF, 9}, {0x034F, 10}, + {0x0345, 11}, {0x01B0, 9}, {0x01B1, 9}, {0x0364, 10}, + {0x006D, 7}, {0x00DC, 8}, {0x0D94, 12}, {0x0D95, 12}, + {0x000E, 4}, {0x003C, 6}, {0x00DD, 8}, {0x00DE, 8}, + {0x01B3, 9}, {0x003D, 6}, {0x00DF, 8}, {0x01F0, 9}, + {0x03E2, 10}, {0x03E3, 10}, {0x06CB, 11}, {0x03E4, 10}, + {0x07CA, 11}, {0x01F3, 9}, {0x01F4, 9}, {0x07CB, 11}, + {0x07D4, 11}, {0x1A21, 14}, {0x1A22, 14}, {0x07D5, 11}, + {0x1A23, 14}, {0x003F, 6}, {0x01F6, 9}, {0x01F7, 9}, + {0x03EB, 10}, + },{//5 + {0x0000, 2}, {0x0002, 3}, {0x0006, 4}, {0x000E, 5}, + {0x000F, 5}, {0x0020, 6}, {0x0021, 6}, {0x0044, 7}, + {0x0045, 7}, {0x0046, 7}, {0x008E, 8}, {0x008F, 8}, + {0x0090, 8}, {0x0122, 9}, {0x0246, 10}, {0x0124, 9}, + {0x0005, 3}, {0x0013, 5}, {0x004A, 7}, {0x0093, 8}, + {0x0018, 5}, {0x004B, 7}, {0x0032, 6}, {0x001A, 5}, + {0x0033, 6}, {0x006C, 7}, {0x006D, 7}, {0x006E, 7}, + {0x00DE, 8}, {0x00DF, 8}, {0x0070, 7}, {0x00E2, 8}, + {0x00E3, 8}, {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, + {0x00E7, 8}, {0x0125, 9}, {0x01D0, 9}, {0x048E, 11}, + {0x091E, 12}, {0x091F, 12}, {0x7440, 15}, {0x1D11, 13}, + {0x7441, 15}, {0x7442, 15}, {0x00E9, 8}, {0x01D4, 9}, + {0x00EB, 8}, {0x03A3, 10}, {0x01D5, 9}, {0x1D12, 13}, + {0x001E, 5}, {0x0076, 7}, {0x01DC, 9}, {0x01DD, 9}, + {0x7443, 15}, {0x007C, 7}, {0x0745, 11}, {0x00EF, 8}, + {0x00FA, 8}, {0x00FB, 8}, {0x01F8, 9}, {0x00FD, 8}, + {0x07E4, 11}, {0x0FCA, 12}, {0x1D13, 13}, {0x7E58, 15}, + {0x7E59, 15}, {0x7E5A, 15}, {0x7E5B, 15}, {0x7E5C, 15}, + {0x7E5D, 15}, {0x007F, 7}, {0x3F2F, 14}, {0x07E6, 11}, + {0x07E7, 11}, + },{//6 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0009, 5}, {0x0014, 6}, {0x0015, 6}, {0x002C, 7}, + {0x005A, 8}, {0x005B, 8}, {0x005C, 8}, {0x00BA, 9}, + {0x00BB, 9}, {0x00BC, 9}, {0x02F4, 11}, {0x05EA, 12}, + {0x0003, 3}, {0x0010, 5}, {0x0022, 6}, {0x0046, 7}, + {0x0009, 4}, {0x0028, 6}, {0x0015, 5}, {0x000B, 4}, + {0x0018, 5}, {0x0029, 6}, {0x0032, 6}, {0x0047, 7}, + {0x0066, 7}, {0x0067, 7}, {0x0068, 7}, {0x0069, 7}, + {0x006A, 7}, {0x005F, 8}, {0x00D6, 8}, {0x00D7, 8}, + {0x01B0, 9}, {0x00D9, 8}, {0x017B, 10}, {0x006D, 7}, + {0x00DC, 8}, {0x01B1, 9}, {0x06E8, 11}, {0x01BB, 9}, + {0x0375, 10}, {0x05EB, 12}, {0x01BC, 9}, {0x6E90, 15}, + {0x0038, 6}, {0x0072, 7}, {0x6E91, 15}, {0x6E92, 15}, + {0x001D, 5}, {0x0073, 7}, {0x01BD, 9}, {0x06F8, 11}, + {0x6E93, 15}, {0x003C, 6}, {0x01BF, 9}, {0x00F4, 8}, + {0x01EA, 9}, {0x037D, 10}, {0x03D6, 10}, {0x06F9, 11}, + {0x6E94, 15}, {0x00F6, 8}, {0x01EE, 9}, {0x6E95, 15}, + {0x6E96, 15}, {0x6E97, 15}, {0x374C, 14}, {0x374D, 14}, + {0x374E, 14}, {0x001F, 5}, {0x03D7, 10}, {0x01EF, 9}, + {0x374F, 14}, + },{//7 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x0016, 6}, + {0x002E, 7}, {0x002F, 7}, {0x0060, 8}, {0x0061, 8}, + {0x00C4, 9}, {0x00C5, 9}, {0x00C6, 9}, {0x018E, 10}, + {0x31E0, 15}, {0x31E1, 15}, {0x31E2, 15}, {0x31E3, 15}, + {0x0004, 3}, {0x000D, 5}, {0x0019, 6}, {0x0038, 7}, + {0x000A, 4}, {0x001D, 6}, {0x000B, 4}, {0x0072, 8}, + {0x0073, 8}, {0x00F0, 9}, {0x01E2, 10}, {0x00F2, 9}, + {0x01E3, 10}, {0x00F3, 9}, {0x01E8, 10}, {0x01E9, 10}, + {0x31E4, 15}, {0x01EA, 10}, {0x031F, 11}, {0x03D6, 11}, + {0x31E5, 15}, {0x01EC, 10}, {0x31E6, 15}, {0x00F7, 9}, + {0x03D7, 11}, {0x31E7, 15}, {0x31E8, 15}, {0x03DA, 11}, + {0x03DB, 11}, {0x31E9, 15}, {0x03E0, 11}, {0x31EA, 15}, + {0x003F, 7}, {0x01F1, 10}, {0x31EB, 15}, {0x31EC, 15}, + {0x0006, 3}, {0x001C, 5}, {0x0074, 7}, {0x0075, 7}, + {0x00F9, 9}, {0x001E, 5}, {0x0076, 7}, {0x00FA, 9}, + {0x03E1, 11}, {0x31ED, 15}, {0x18F7, 14}, {0x1F60, 14}, + {0x1F61, 14}, {0x01DC, 9}, {0x01DD, 9}, {0x1F62, 14}, + {0x1F63, 14}, {0x1F64, 14}, {0x1F65, 14}, {0x1F66, 14}, + {0x1F67, 14}, {0x001F, 5}, {0x03ED, 11}, {0x00EF, 8}, + {0x01F7, 10}, + } +}; + +static const uint16_t x8_ac1_highquant_table[8][77][2]={ + {//0 + {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5}, + {0x0008, 5}, {0x0009, 5}, {0x0014, 6}, {0x002A, 7}, + {0x0016, 6}, {0x002B, 7}, {0x005C, 8}, {0x002F, 7}, + {0x0030, 7}, {0x005D, 8}, {0x0062, 8}, {0x00C6, 9}, + {0x0007, 4}, {0x0019, 6}, {0x001A, 6}, {0x0036, 7}, + {0x0010, 5}, {0x006E, 8}, {0x0022, 6}, {0x0009, 4}, + {0x000A, 4}, {0x0016, 5}, {0x0023, 6}, {0x002E, 6}, + {0x002F, 6}, {0x0030, 6}, {0x0062, 7}, {0x0063, 7}, + {0x0064, 7}, {0x0065, 7}, {0x0066, 7}, {0x0067, 7}, + {0x0068, 7}, {0x0069, 7}, {0x006A, 7}, {0x006B, 7}, + {0x006C, 7}, {0x00C7, 9}, {0x00DE, 9}, {0x00DF, 9}, + {0x06D0, 11}, {0x01B5, 9}, {0x0037, 6}, {0x00DB, 8}, + {0x001C, 5}, {0x0074, 7}, {0x01D4, 9}, {0x01D5, 9}, + {0x0076, 7}, {0x0369, 10}, {0x3688, 14}, {0x3689, 14}, + {0x368A, 14}, {0x0077, 7}, {0x03AC, 10}, {0x0078, 7}, + {0x00F2, 8}, {0x01D7, 9}, {0x00F3, 8}, {0x007A, 7}, + {0x368B, 14}, {0x007B, 7}, {0x007C, 7}, {0x03AD, 10}, + {0x03E8, 10}, {0x368C, 14}, {0x368D, 14}, {0x03E9, 10}, + {0x368E, 14}, {0x003F, 6}, {0x01F5, 9}, {0x00FB, 8}, + {0x368F, 14}, + },{//1 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, + {0x0018, 6}, {0x0032, 7}, {0x0033, 7}, {0x0034, 7}, + {0x006A, 8}, {0x00D6, 9}, {0x00D7, 9}, {0x00D8, 9}, + {0x00D9, 9}, {0x3680, 15}, {0x01B5, 10}, {0x0369, 11}, + {0x0004, 3}, {0x000E, 5}, {0x001E, 6}, {0x0037, 7}, + {0x000A, 4}, {0x0016, 5}, {0x000C, 4}, {0x001F, 6}, + {0x005C, 7}, {0x005D, 7}, {0x00BC, 8}, {0x00BD, 8}, + {0x005F, 7}, {0x00D0, 8}, {0x00DB, 9}, {0x00D1, 8}, + {0x01A4, 9}, {0x01A5, 9}, {0x01A6, 9}, {0x01A7, 9}, + {0x0350, 10}, {0x06A2, 11}, {0x06A3, 11}, {0x01A9, 9}, + {0x01AA, 9}, {0x06AC, 11}, {0x3681, 15}, {0x0357, 10}, + {0x3682, 15}, {0x3683, 15}, {0x3684, 15}, {0x3685, 15}, + {0x0036, 6}, {0x00D6, 8}, {0x3686, 15}, {0x3687, 15}, + {0x000E, 4}, {0x006E, 7}, {0x00D7, 8}, {0x06AD, 11}, + {0x3688, 15}, {0x001E, 5}, {0x00DE, 8}, {0x06F8, 11}, + {0x037D, 10}, {0x3689, 15}, {0x368A, 15}, {0x368B, 15}, + {0x368C, 15}, {0x01BF, 9}, {0x368D, 15}, {0x1B47, 14}, + {0x37C8, 14}, {0x37C9, 14}, {0x37CA, 14}, {0x37CB, 14}, + {0x37CC, 14}, {0x001F, 5}, {0x37CD, 14}, {0x37CE, 14}, + {0x37CF, 14}, + },{//2 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0012, 6}, {0x0026, 7}, {0x0014, 6}, {0x0027, 7}, + {0x00A8, 9}, {0x00A9, 9}, {0x0055, 8}, {0x2B00, 15}, + {0x00AD, 9}, {0x2B01, 15}, {0x2B02, 15}, {0x2B03, 15}, + {0x0003, 3}, {0x000B, 5}, {0x0040, 7}, {0x0041, 7}, + {0x0009, 4}, {0x0021, 6}, {0x0011, 5}, {0x000A, 4}, + {0x000B, 4}, {0x0018, 5}, {0x0032, 6}, {0x0033, 6}, + {0x0034, 6}, {0x0035, 6}, {0x006C, 7}, {0x0057, 8}, + {0x006D, 7}, {0x00DC, 8}, {0x0159, 10}, {0x00DD, 8}, + {0x01BC, 9}, {0x037A, 10}, {0x037B, 10}, {0x0038, 6}, + {0x0072, 7}, {0x01BE, 9}, {0x01BF, 9}, {0x00E6, 8}, + {0x039C, 10}, {0x01CF, 9}, {0x2B04, 15}, {0x2B05, 15}, + {0x0074, 7}, {0x01D4, 9}, {0x2B06, 15}, {0x2B07, 15}, + {0x001E, 5}, {0x00EB, 8}, {0x1584, 14}, {0x1585, 14}, + {0x1586, 14}, {0x003B, 6}, {0x01D5, 9}, {0x01F0, 9}, + {0x039D, 10}, {0x03E2, 10}, {0x1587, 14}, {0x1588, 14}, + {0x1589, 14}, {0x00F9, 8}, {0x158A, 14}, {0x158B, 14}, + {0x03E3, 10}, {0x158C, 14}, {0x158D, 14}, {0x01F4, 9}, + {0x158E, 14}, {0x003F, 6}, {0x00FB, 8}, {0x01F5, 9}, + {0x158F, 14}, + },{//3 + {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x0007, 5}, + {0x0010, 6}, {0x0011, 6}, {0x0024, 7}, {0x0025, 7}, + {0x0013, 6}, {0x0014, 6}, {0x002A, 7}, {0x002B, 7}, + {0x00B0, 9}, {0x00B1, 9}, {0x002D, 7}, {0x0059, 8}, + {0x000C, 5}, {0x0017, 6}, {0x00D0, 9}, {0x0035, 7}, + {0x001B, 6}, {0x0038, 7}, {0x0039, 7}, {0x0004, 3}, + {0x0005, 3}, {0x000F, 5}, {0x0018, 5}, {0x001D, 6}, + {0x0032, 6}, {0x0033, 6}, {0x0068, 7}, {0x0069, 7}, + {0x0069, 8}, {0x00D4, 8}, {0x00D5, 8}, {0x00D6, 8}, + {0x006C, 7}, {0x0037, 6}, {0x006D, 7}, {0x0070, 7}, + {0x0039, 6}, {0x00D7, 8}, {0x00D1, 9}, {0x3880, 14}, + {0x3881, 14}, {0x3882, 14}, {0x0074, 7}, {0x01C5, 9}, + {0x0075, 7}, {0x00E3, 8}, {0x3883, 14}, {0x3884, 14}, + {0x00EC, 8}, {0x3885, 14}, {0x1C43, 13}, {0x1C44, 13}, + {0x1C45, 13}, {0x00ED, 8}, {0x1C46, 13}, {0x003C, 6}, + {0x0077, 7}, {0x01E8, 9}, {0x003E, 6}, {0x007B, 7}, + {0x1C47, 13}, {0x007E, 7}, {0x007F, 7}, {0x1C48, 13}, + {0x1C49, 13}, {0x1C4A, 13}, {0x1C4B, 13}, {0x1C4C, 13}, + {0x1C4D, 13}, {0x00F5, 8}, {0x1C4E, 13}, {0x01E9, 9}, + {0x1C4F, 13}, + },{//4 + {0x0000, 2}, {0x0004, 4}, {0x000A, 5}, {0x000B, 5}, + {0x0018, 6}, {0x0019, 6}, {0x0034, 7}, {0x0035, 7}, + {0x0036, 7}, {0x006E, 8}, {0x00DE, 9}, {0x00DF, 9}, + {0x01C0, 10}, {0x01C1, 10}, {0x01C2, 10}, {0x3860, 15}, + {0x0004, 3}, {0x000F, 5}, {0x001D, 6}, {0x0039, 7}, + {0x000A, 4}, {0x002C, 6}, {0x002D, 6}, {0x000C, 4}, + {0x0017, 5}, {0x0034, 6}, {0x0035, 6}, {0x0036, 6}, + {0x006E, 7}, {0x006F, 7}, {0x0070, 7}, {0x0071, 7}, + {0x0071, 8}, {0x00E4, 8}, {0x00E5, 8}, {0x00E6, 8}, + {0x00E7, 8}, {0x00E8, 8}, {0x03A4, 10}, {0x0075, 7}, + {0x00EC, 8}, {0x01D3, 9}, {0x01DA, 9}, {0x03A5, 10}, + {0x03B6, 10}, {0x070D, 12}, {0x03B7, 10}, {0x070E, 12}, + {0x003C, 6}, {0x00EE, 8}, {0x3861, 15}, {0x3862, 15}, + {0x003D, 6}, {0x01DE, 9}, {0x3863, 15}, {0x3864, 15}, + {0x3865, 15}, {0x007C, 7}, {0x070F, 12}, {0x03BE, 10}, + {0x03BF, 10}, {0x3866, 15}, {0x0FA0, 12}, {0x07D1, 11}, + {0x3867, 15}, {0x00FB, 8}, {0x01F5, 9}, {0x7D08, 15}, + {0x0FA4, 12}, {0x7D09, 15}, {0x7D0A, 15}, {0x7D0B, 15}, + {0x3E86, 14}, {0x003F, 6}, {0x0FA5, 12}, {0x07D3, 11}, + {0x3E87, 14}, + },{//5 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0009, 5}, {0x0014, 6}, {0x002A, 7}, {0x0056, 8}, + {0x02B8, 11}, {0x00AF, 9}, {0x02B9, 11}, {0x015D, 10}, + {0x02C0, 11}, {0x2C10, 15}, {0x2C11, 15}, {0x2C12, 15}, + {0x0006, 4}, {0x000E, 5}, {0x0017, 6}, {0x002D, 7}, + {0x000F, 5}, {0x0040, 7}, {0x0021, 6}, {0x0005, 3}, + {0x0009, 4}, {0x0011, 5}, {0x0018, 5}, {0x0019, 5}, + {0x001A, 5}, {0x0036, 6}, {0x0037, 6}, {0x0041, 7}, + {0x0059, 8}, {0x00E0, 8}, {0x00E1, 8}, {0x0071, 7}, + {0x00E4, 8}, {0x00B1, 9}, {0x02C2, 11}, {0x001D, 5}, + {0x0073, 7}, {0x00E5, 8}, {0x00F0, 8}, {0x0079, 7}, + {0x03C4, 10}, {0x01E3, 9}, {0x01E8, 9}, {0x2C13, 15}, + {0x007B, 7}, {0x2C14, 15}, {0x2C15, 15}, {0x2C16, 15}, + {0x007C, 7}, {0x02C3, 11}, {0x2C17, 15}, {0x160C, 14}, + {0x160D, 14}, {0x007D, 7}, {0x160E, 14}, {0x01E9, 9}, + {0x03C5, 10}, {0x03D4, 10}, {0x01EB, 9}, {0x160F, 14}, + {0x3D50, 14}, {0x00FC, 8}, {0x07AB, 11}, {0x3D51, 14}, + {0x3D52, 14}, {0x3D53, 14}, {0x3D54, 14}, {0x01FA, 9}, + {0x3D55, 14}, {0x007F, 7}, {0x01FB, 9}, {0x3D56, 14}, + {0x3D57, 14}, + },{//6 + {0x0000, 3}, {0x0002, 4}, {0x0003, 4}, {0x0008, 5}, + {0x0009, 5}, {0x000A, 5}, {0x000B, 5}, {0x0018, 6}, + {0x0032, 7}, {0x000D, 5}, {0x0033, 7}, {0x0E00, 13}, + {0x0039, 7}, {0x0E01, 13}, {0x003A, 7}, {0x0E02, 13}, + {0x0008, 4}, {0x001E, 6}, {0x003B, 7}, {0x003E, 7}, + {0x0012, 5}, {0x003F, 7}, {0x0013, 5}, {0x0028, 6}, + {0x0029, 6}, {0x0054, 7}, {0x002B, 6}, {0x0055, 7}, + {0x0058, 7}, {0x0E03, 13}, {0x0059, 7}, {0x005A, 7}, + {0x0E04, 13}, {0x0E05, 13}, {0x0703, 12}, {0x005B, 7}, + {0x005C, 7}, {0x0704, 12}, {0x0705, 12}, {0x005D, 7}, + {0x0706, 12}, {0x0707, 12}, {0x0708, 12}, {0x0709, 12}, + {0x070A, 12}, {0x070B, 12}, {0x0018, 5}, {0x002F, 6}, + {0x000D, 4}, {0x0019, 5}, {0x070C, 12}, {0x0070, 7}, + {0x001D, 5}, {0x070D, 12}, {0x070E, 12}, {0x070F, 12}, + {0x0710, 12}, {0x0039, 6}, {0x0711, 12}, {0x003C, 6}, + {0x0712, 12}, {0x0713, 12}, {0x0714, 12}, {0x0715, 12}, + {0x0716, 12}, {0x003D, 6}, {0x0717, 12}, {0x0718, 12}, + {0x0719, 12}, {0x071A, 12}, {0x071B, 12}, {0x071C, 12}, + {0x071D, 12}, {0x001F, 5}, {0x071E, 12}, {0x0071, 7}, + {0x071F, 12}, + },{//7 + {0x0000, 3}, {0x0002, 4}, {0x0006, 5}, {0x000E, 6}, + {0x000F, 6}, {0x0040, 8}, {0x0041, 8}, {0x0042, 8}, + {0x0218, 11}, {0x2190, 15}, {0x2191, 15}, {0x2192, 15}, + {0x2193, 15}, {0x2194, 15}, {0x2195, 15}, {0x2196, 15}, + {0x0005, 4}, {0x0011, 6}, {0x0024, 7}, {0x0087, 9}, + {0x000C, 5}, {0x004A, 8}, {0x004B, 8}, {0x0002, 2}, + {0x0006, 3}, {0x000D, 5}, {0x000E, 5}, {0x000F, 5}, + {0x0013, 6}, {0x0038, 6}, {0x00E4, 8}, {0x00E5, 8}, + {0x01CC, 9}, {0x00E7, 8}, {0x0074, 7}, {0x00EA, 8}, + {0x01CD, 9}, {0x021A, 11}, {0x2197, 15}, {0x001E, 5}, + {0x0076, 7}, {0x00EB, 8}, {0x01DC, 9}, {0x00EF, 8}, + {0x01DD, 9}, {0x01F0, 9}, {0x2198, 15}, {0x2199, 15}, + {0x00F9, 8}, {0x03E2, 10}, {0x219A, 15}, {0x219B, 15}, + {0x00FA, 8}, {0x219C, 15}, {0x219D, 15}, {0x219E, 15}, + {0x219F, 15}, {0x01F6, 9}, {0x21B0, 15}, {0x00FC, 8}, + {0x01F7, 9}, {0x21B1, 15}, {0x21B2, 15}, {0x21B3, 15}, + {0x21B4, 15}, {0x01FA, 9}, {0x21B5, 15}, {0x21B6, 15}, + {0x21B7, 15}, {0x21B8, 15}, {0x21B9, 15}, {0x03E3, 10}, + {0x10DD, 14}, {0x007F, 7}, {0x01FB, 9}, {0x10DE, 14}, + {0x10DF, 14}, + } +}; +#define MAX_AC_VLC_BITS 16 + +#endif /* AVCODEC_INTRAX8HUF_H */ diff --git a/ffmpeg/libavcodec/ituh263dec.c b/ffmpeg/libavcodec/ituh263dec.c new file mode 100644 index 0000000..5d604ef --- /dev/null +++ b/ffmpeg/libavcodec/ituh263dec.c @@ -0,0 +1,1157 @@ +/* + * ITU H263 bitstream decoder + * Copyright (c) 2000,2001 Fabrice Bellard + * H263+ support. + * Copyright (c) 2001 Juan J. Sierralta P + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * h263 decoder. + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +//#define DEBUG +#include + +#include "libavutil/internal.h" +#include "libavutil/mathematics.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h263.h" +#include "mathops.h" +#include "unary.h" +#include "flv.h" +#include "mpeg4video.h" + +// The defines below define the number of bits that are read at once for +// reading vlc values. Changing these may improve speed and data cache needs +// be aware though that decreasing them may need the number of stages that is +// passed to get_vlc* to be increased. +#define MV_VLC_BITS 9 +#define H263_MBTYPE_B_VLC_BITS 6 +#define CBPC_B_VLC_BITS 3 + +static const int h263_mb_type_b_map[15]= { + MB_TYPE_DIRECT2 | MB_TYPE_L0L1, + MB_TYPE_DIRECT2 | MB_TYPE_L0L1 | MB_TYPE_CBP, + MB_TYPE_DIRECT2 | MB_TYPE_L0L1 | MB_TYPE_CBP | MB_TYPE_QUANT, + MB_TYPE_L0 | MB_TYPE_16x16, + MB_TYPE_L0 | MB_TYPE_CBP | MB_TYPE_16x16, + MB_TYPE_L0 | MB_TYPE_CBP | MB_TYPE_QUANT | MB_TYPE_16x16, + MB_TYPE_L1 | MB_TYPE_16x16, + MB_TYPE_L1 | MB_TYPE_CBP | MB_TYPE_16x16, + MB_TYPE_L1 | MB_TYPE_CBP | MB_TYPE_QUANT | MB_TYPE_16x16, + MB_TYPE_L0L1 | MB_TYPE_16x16, + MB_TYPE_L0L1 | MB_TYPE_CBP | MB_TYPE_16x16, + MB_TYPE_L0L1 | MB_TYPE_CBP | MB_TYPE_QUANT | MB_TYPE_16x16, + 0, //stuffing + MB_TYPE_INTRA4x4 | MB_TYPE_CBP, + MB_TYPE_INTRA4x4 | MB_TYPE_CBP | MB_TYPE_QUANT, +}; + +void ff_h263_show_pict_info(MpegEncContext *s){ + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "qp:%d %c size:%d rnd:%d%s%s%s%s%s%s%s%s%s %d/%d\n", + s->qscale, av_get_picture_type_char(s->pict_type), + s->gb.size_in_bits, 1-s->no_rounding, + s->obmc ? " AP" : "", + s->umvplus ? " UMV" : "", + s->h263_long_vectors ? " LONG" : "", + s->h263_plus ? " +" : "", + s->h263_aic ? " AIC" : "", + s->alt_inter_vlc ? " AIV" : "", + s->modified_quant ? " MQ" : "", + s->loop_filter ? " LOOP" : "", + s->h263_slice_structured ? " SS" : "", + s->avctx->time_base.den, s->avctx->time_base.num + ); + } +} + +/***********************************************/ +/* decoding */ + +VLC ff_h263_intra_MCBPC_vlc; +VLC ff_h263_inter_MCBPC_vlc; +VLC ff_h263_cbpy_vlc; +static VLC mv_vlc; +static VLC h263_mbtype_b_vlc; +static VLC cbpc_b_vlc; + +/* init vlcs */ + +/* XXX: find a better solution to handle static init */ +void ff_h263_decode_init_vlc(void) +{ + static volatile int done = 0; + + if (!done) { + INIT_VLC_STATIC(&ff_h263_intra_MCBPC_vlc, INTRA_MCBPC_VLC_BITS, 9, + ff_h263_intra_MCBPC_bits, 1, 1, + ff_h263_intra_MCBPC_code, 1, 1, 72); + INIT_VLC_STATIC(&ff_h263_inter_MCBPC_vlc, INTER_MCBPC_VLC_BITS, 28, + ff_h263_inter_MCBPC_bits, 1, 1, + ff_h263_inter_MCBPC_code, 1, 1, 198); + INIT_VLC_STATIC(&ff_h263_cbpy_vlc, CBPY_VLC_BITS, 16, + &ff_h263_cbpy_tab[0][1], 2, 1, + &ff_h263_cbpy_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&mv_vlc, MV_VLC_BITS, 33, + &ff_mvtab[0][1], 2, 1, + &ff_mvtab[0][0], 2, 1, 538); + ff_init_rl(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); + ff_init_rl(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); + INIT_VLC_RL(ff_h263_rl_inter, 554); + INIT_VLC_RL(ff_rl_intra_aic, 554); + INIT_VLC_STATIC(&h263_mbtype_b_vlc, H263_MBTYPE_B_VLC_BITS, 15, + &ff_h263_mbtype_b_tab[0][1], 2, 1, + &ff_h263_mbtype_b_tab[0][0], 2, 1, 80); + INIT_VLC_STATIC(&cbpc_b_vlc, CBPC_B_VLC_BITS, 4, + &ff_cbpc_b_tab[0][1], 2, 1, + &ff_cbpc_b_tab[0][0], 2, 1, 8); + done = 1; + } +} + +int ff_h263_decode_mba(MpegEncContext *s) +{ + int i, mb_pos; + + for(i=0; i<6; i++){ + if(s->mb_num-1 <= ff_mba_max[i]) break; + } + mb_pos= get_bits(&s->gb, ff_mba_length[i]); + s->mb_x= mb_pos % s->mb_width; + s->mb_y= mb_pos / s->mb_width; + + return mb_pos; +} + +/** + * Decode the group of blocks header or slice header. + * @return <0 if an error occurred + */ +static int h263_decode_gob_header(MpegEncContext *s) +{ + unsigned int val, gob_number; + int left; + + /* Check for GOB Start Code */ + val = show_bits(&s->gb, 16); + if(val) + return -1; + + /* We have a GBSC probably with GSTUFF */ + skip_bits(&s->gb, 16); /* Drop the zeros */ + left= get_bits_left(&s->gb); + //MN: we must check the bits left or we might end in a infinite loop (or segfault) + for(;left>13; left--){ + if(get_bits1(&s->gb)) break; /* Seek the '1' bit */ + } + if(left<=13) + return -1; + + if(s->h263_slice_structured){ + if(get_bits1(&s->gb)==0) + return -1; + + ff_h263_decode_mba(s); + + if(s->mb_num > 1583) + if(get_bits1(&s->gb)==0) + return -1; + + s->qscale = get_bits(&s->gb, 5); /* SQUANT */ + if(get_bits1(&s->gb)==0) + return -1; + skip_bits(&s->gb, 2); /* GFID */ + }else{ + gob_number = get_bits(&s->gb, 5); /* GN */ + s->mb_x= 0; + s->mb_y= s->gob_index* gob_number; + skip_bits(&s->gb, 2); /* GFID */ + s->qscale = get_bits(&s->gb, 5); /* GQUANT */ + } + + if(s->mb_y >= s->mb_height) + return -1; + + if(s->qscale==0) + return -1; + + return 0; +} + +/** + * Find the next resync_marker. + * @param p pointer to buffer to scan + * @param end pointer to the end of the buffer + * @return pointer to the next resync_marker, or end if none was found + */ +const uint8_t *ff_h263_find_resync_marker(MpegEncContext *s, const uint8_t *av_restrict p, const uint8_t *av_restrict end) +{ + av_assert2(p < end); + + end-=2; + p++; + if(s->resync_marker){ + int prefix_len = ff_mpeg4_get_video_packet_prefix_length(s); + for(;p> (23-prefix_len)) == 1)) return p - 1; + else if (!p[ 1] && ((p[2] >> (23-prefix_len)) == 1)) return p; + } + } + } + return end+2; +} + +/** + * Decode the group of blocks / video packet header. + * @return bit position of the resync_marker, or <0 if none was found + */ +int ff_h263_resync(MpegEncContext *s){ + int left, pos, ret; + + if(s->codec_id==AV_CODEC_ID_MPEG4){ + skip_bits1(&s->gb); + align_get_bits(&s->gb); + } + + if(show_bits(&s->gb, 16)==0){ + pos= get_bits_count(&s->gb); + if(CONFIG_MPEG4_DECODER && s->codec_id==AV_CODEC_ID_MPEG4) + ret= ff_mpeg4_decode_video_packet_header(s); + else + ret= h263_decode_gob_header(s); + if(ret>=0) + return pos; + } + //OK, it's not where it is supposed to be ... + s->gb= s->last_resync_gb; + align_get_bits(&s->gb); + left= get_bits_left(&s->gb); + + for(;left>16+1+5+5; left-=8){ + if(show_bits(&s->gb, 16)==0){ + GetBitContext bak= s->gb; + + pos= get_bits_count(&s->gb); + if(CONFIG_MPEG4_DECODER && s->codec_id==AV_CODEC_ID_MPEG4) + ret= ff_mpeg4_decode_video_packet_header(s); + else + ret= h263_decode_gob_header(s); + if(ret>=0) + return pos; + + s->gb= bak; + } + skip_bits(&s->gb, 8); + } + + return -1; +} + +int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code) +{ + int code, val, sign, shift; + code = get_vlc2(&s->gb, mv_vlc.table, MV_VLC_BITS, 2); + + if (code == 0) + return pred; + if (code < 0) + return 0xffff; + + sign = get_bits1(&s->gb); + shift = f_code - 1; + val = code; + if (shift) { + val = (val - 1) << shift; + val |= get_bits(&s->gb, shift); + val++; + } + if (sign) + val = -val; + val += pred; + + /* modulo decoding */ + if (!s->h263_long_vectors) { + val = sign_extend(val, 5 + f_code); + } else { + /* horrible h263 long vector mode */ + if (pred < -31 && val < -63) + val += 64; + if (pred > 32 && val > 63) + val -= 64; + + } + return val; +} + + +/* Decode RVLC of H.263+ UMV */ +static int h263p_decode_umotion(MpegEncContext * s, int pred) +{ + int code = 0, sign; + + if (get_bits1(&s->gb)) /* Motion difference = 0 */ + return pred; + + code = 2 + get_bits1(&s->gb); + + while (get_bits1(&s->gb)) + { + code <<= 1; + code += get_bits1(&s->gb); + } + sign = code & 1; + code >>= 1; + + code = (sign) ? (pred - code) : (pred + code); + av_dlog(s->avctx,"H.263+ UMV Motion = %d\n", code); + return code; + +} + +/** + * read the next MVs for OBMC. yes this is a ugly hack, feel free to send a patch :) + */ +static void preview_obmc(MpegEncContext *s){ + GetBitContext gb= s->gb; + + int cbpc, i, pred_x, pred_y, mx, my; + int16_t *mot_val; + const int xy= s->mb_x + 1 + s->mb_y * s->mb_stride; + const int stride= s->b8_stride*2; + + for(i=0; i<4; i++) + s->block_index[i]+= 2; + for(i=4; i<6; i++) + s->block_index[i]+= 1; + s->mb_x++; + + av_assert2(s->pict_type == AV_PICTURE_TYPE_P); + + do{ + if (get_bits1(&s->gb)) { + /* skip mb */ + mot_val = s->current_picture.motion_val[0][s->block_index[0]]; + mot_val[0 ]= mot_val[2 ]= + mot_val[0+stride]= mot_val[2+stride]= 0; + mot_val[1 ]= mot_val[3 ]= + mot_val[1+stride]= mot_val[3+stride]= 0; + + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + goto end; + } + cbpc = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); + }while(cbpc == 20); + + if(cbpc & 4){ + s->current_picture.mb_type[xy] = MB_TYPE_INTRA; + }else{ + get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + if (cbpc & 8) { + if(s->modified_quant){ + if(get_bits1(&s->gb)) skip_bits(&s->gb, 1); + else skip_bits(&s->gb, 5); + }else + skip_bits(&s->gb, 2); + } + + if ((cbpc & 16) == 0) { + s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_L0; + /* 16x16 motion prediction */ + mot_val= ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + if (s->umvplus) + mx = h263p_decode_umotion(s, pred_x); + else + mx = ff_h263_decode_motion(s, pred_x, 1); + + if (s->umvplus) + my = h263p_decode_umotion(s, pred_y); + else + my = ff_h263_decode_motion(s, pred_y, 1); + + mot_val[0 ]= mot_val[2 ]= + mot_val[0+stride]= mot_val[2+stride]= mx; + mot_val[1 ]= mot_val[3 ]= + mot_val[1+stride]= mot_val[3+stride]= my; + } else { + s->current_picture.mb_type[xy] = MB_TYPE_8x8 | MB_TYPE_L0; + for(i=0;i<4;i++) { + mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); + if (s->umvplus) + mx = h263p_decode_umotion(s, pred_x); + else + mx = ff_h263_decode_motion(s, pred_x, 1); + + if (s->umvplus) + my = h263p_decode_umotion(s, pred_y); + else + my = ff_h263_decode_motion(s, pred_y, 1); + if (s->umvplus && (mx - pred_x) == 1 && (my - pred_y) == 1) + skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */ + mot_val[0] = mx; + mot_val[1] = my; + } + } + } +end: + + for(i=0; i<4; i++) + s->block_index[i]-= 2; + for(i=4; i<6; i++) + s->block_index[i]-= 1; + s->mb_x--; + + s->gb= gb; +} + +static void h263_decode_dquant(MpegEncContext *s){ + static const int8_t quant_tab[4] = { -1, -2, 1, 2 }; + + if(s->modified_quant){ + if(get_bits1(&s->gb)) + s->qscale= ff_modified_quant_tab[get_bits1(&s->gb)][ s->qscale ]; + else + s->qscale= get_bits(&s->gb, 5); + }else + s->qscale += quant_tab[get_bits(&s->gb, 2)]; + ff_set_qscale(s, s->qscale); +} + +static int h263_decode_block(MpegEncContext * s, int16_t * block, + int n, int coded) +{ + int code, level, i, j, last, run; + RLTable *rl = &ff_h263_rl_inter; + const uint8_t *scan_table; + GetBitContext gb= s->gb; + + scan_table = s->intra_scantable.permutated; + if (s->h263_aic && s->mb_intra) { + rl = &ff_rl_intra_aic; + i = 0; + if (s->ac_pred) { + if (s->h263_aic_dir) + scan_table = s->intra_v_scantable.permutated; /* left */ + else + scan_table = s->intra_h_scantable.permutated; /* top */ + } + } else if (s->mb_intra) { + /* DC coef */ + if(s->codec_id == AV_CODEC_ID_RV10){ +#if CONFIG_RV10_DECODER + if (s->rv10_version == 3 && s->pict_type == AV_PICTURE_TYPE_I) { + int component, diff; + component = (n <= 3 ? 0 : n - 4 + 1); + level = s->last_dc[component]; + if (s->rv10_first_dc_coded[component]) { + diff = ff_rv_decode_dc(s, n); + if (diff == 0xffff) + return -1; + level += diff; + level = level & 0xff; /* handle wrap round */ + s->last_dc[component] = level; + } else { + s->rv10_first_dc_coded[component] = 1; + } + } else { + level = get_bits(&s->gb, 8); + if (level == 255) + level = 128; + } +#endif + }else{ + level = get_bits(&s->gb, 8); + if((level&0x7F) == 0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal dc %d at %d %d\n", level, s->mb_x, s->mb_y); + if(s->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT)) + return -1; + } + if (level == 255) + level = 128; + } + block[0] = level; + i = 1; + } else { + i = 0; + } + if (!coded) { + if (s->mb_intra && s->h263_aic) + goto not_coded; + s->block_last_index[n] = i - 1; + return 0; + } +retry: + for(;;) { + code = get_vlc2(&s->gb, rl->vlc.table, TEX_VLC_BITS, 2); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal ac vlc code at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + if (code == rl->n) { + /* escape */ + if (CONFIG_FLV_DECODER && s->h263_flv > 1) { + ff_flv2_decode_ac_esc(&s->gb, &level, &run, &last); + } else { + last = get_bits1(&s->gb); + run = get_bits(&s->gb, 6); + level = (int8_t)get_bits(&s->gb, 8); + if(level == -128){ + if (s->codec_id == AV_CODEC_ID_RV10) { + /* XXX: should patch encoder too */ + level = get_sbits(&s->gb, 12); + }else{ + level = get_bits(&s->gb, 5); + level |= get_sbits(&s->gb, 6)<<5; + } + } + } + } else { + run = rl->table_run[code]; + level = rl->table_level[code]; + last = code >= rl->last; + if (get_bits1(&s->gb)) + level = -level; + } + i += run; + if (i >= 64){ + if(s->alt_inter_vlc && rl == &ff_h263_rl_inter && !s->mb_intra){ + //Looks like a hack but no, it's the way it is supposed to work ... + rl = &ff_rl_intra_aic; + i = 0; + s->gb= gb; + s->dsp.clear_block(block); + goto retry; + } + av_log(s->avctx, AV_LOG_ERROR, "run overflow at %dx%d i:%d\n", s->mb_x, s->mb_y, s->mb_intra); + return -1; + } + j = scan_table[i]; + block[j] = level; + if (last) + break; + i++; + } +not_coded: + if (s->mb_intra && s->h263_aic) { + ff_h263_pred_acdc(s, block, n); + i = 63; + } + s->block_last_index[n] = i; + return 0; +} + +static int h263_skip_b_part(MpegEncContext *s, int cbp) +{ + LOCAL_ALIGNED_16(int16_t, dblock, [64]); + int i, mbi; + int bli[6]; + + /* we have to set s->mb_intra to zero to decode B-part of PB-frame correctly + * but real value should be restored in order to be used later (in OBMC condition) + */ + mbi = s->mb_intra; + memcpy(bli, s->block_last_index, sizeof(bli)); + s->mb_intra = 0; + for (i = 0; i < 6; i++) { + if (h263_decode_block(s, dblock, i, cbp&32) < 0) + return -1; + cbp+=cbp; + } + s->mb_intra = mbi; + memcpy(s->block_last_index, bli, sizeof(bli)); + return 0; +} + +static int h263_get_modb(GetBitContext *gb, int pb_frame, int *cbpb) +{ + int c, mv = 1; + + if (pb_frame < 3) { // h.263 Annex G and i263 PB-frame + c = get_bits1(gb); + if (pb_frame == 2 && c) + mv = !get_bits1(gb); + } else { // h.263 Annex M improved PB-frame + mv = get_unary(gb, 0, 4) + 1; + c = mv & 1; + mv = !!(mv & 2); + } + if(c) + *cbpb = get_bits(gb, 6); + return mv; +} + +int ff_h263_decode_mb(MpegEncContext *s, + int16_t block[6][64]) +{ + int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant; + int16_t *mot_val; + const int xy= s->mb_x + s->mb_y * s->mb_stride; + int cbpb = 0, pb_mv_count = 0; + + av_assert2(!s->h263_pred); + + if (s->pict_type == AV_PICTURE_TYPE_P) { + do{ + if (get_bits1(&s->gb)) { + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = !(s->obmc | s->loop_filter); + goto end; + } + cbpc = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); + if (cbpc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "cbpc damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + }while(cbpc == 20); + + s->dsp.clear_blocks(s->block[0]); + + dquant = cbpc & 8; + s->mb_intra = ((cbpc & 4) != 0); + if (s->mb_intra) goto intra; + + if(s->pb_frame && get_bits1(&s->gb)) + pb_mv_count = h263_get_modb(&s->gb, s->pb_frame, &cbpb); + cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + + if(s->alt_inter_vlc==0 || (cbpc & 3)!=3) + cbpy ^= 0xF; + + cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) { + h263_decode_dquant(s); + } + + s->mv_dir = MV_DIR_FORWARD; + if ((cbpc & 16) == 0) { + s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_L0; + /* 16x16 motion prediction */ + s->mv_type = MV_TYPE_16X16; + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + if (s->umvplus) + mx = h263p_decode_umotion(s, pred_x); + else + mx = ff_h263_decode_motion(s, pred_x, 1); + + if (mx >= 0xffff) + return -1; + + if (s->umvplus) + my = h263p_decode_umotion(s, pred_y); + else + my = ff_h263_decode_motion(s, pred_y, 1); + + if (my >= 0xffff) + return -1; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + + if (s->umvplus && (mx - pred_x) == 1 && (my - pred_y) == 1) + skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */ + } else { + s->current_picture.mb_type[xy] = MB_TYPE_8x8 | MB_TYPE_L0; + s->mv_type = MV_TYPE_8X8; + for(i=0;i<4;i++) { + mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); + if (s->umvplus) + mx = h263p_decode_umotion(s, pred_x); + else + mx = ff_h263_decode_motion(s, pred_x, 1); + if (mx >= 0xffff) + return -1; + + if (s->umvplus) + my = h263p_decode_umotion(s, pred_y); + else + my = ff_h263_decode_motion(s, pred_y, 1); + if (my >= 0xffff) + return -1; + s->mv[0][i][0] = mx; + s->mv[0][i][1] = my; + if (s->umvplus && (mx - pred_x) == 1 && (my - pred_y) == 1) + skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */ + mot_val[0] = mx; + mot_val[1] = my; + } + } + } else if(s->pict_type==AV_PICTURE_TYPE_B) { + int mb_type; + const int stride= s->b8_stride; + int16_t *mot_val0 = s->current_picture.motion_val[0][2 * (s->mb_x + s->mb_y * stride)]; + int16_t *mot_val1 = s->current_picture.motion_val[1][2 * (s->mb_x + s->mb_y * stride)]; +// const int mv_xy= s->mb_x + 1 + s->mb_y * s->mb_stride; + + //FIXME ugly + mot_val0[0 ]= mot_val0[2 ]= mot_val0[0+2*stride]= mot_val0[2+2*stride]= + mot_val0[1 ]= mot_val0[3 ]= mot_val0[1+2*stride]= mot_val0[3+2*stride]= + mot_val1[0 ]= mot_val1[2 ]= mot_val1[0+2*stride]= mot_val1[2+2*stride]= + mot_val1[1 ]= mot_val1[3 ]= mot_val1[1+2*stride]= mot_val1[3+2*stride]= 0; + + do{ + mb_type= get_vlc2(&s->gb, h263_mbtype_b_vlc.table, H263_MBTYPE_B_VLC_BITS, 2); + if (mb_type < 0){ + av_log(s->avctx, AV_LOG_ERROR, "b mb_type damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + mb_type= h263_mb_type_b_map[ mb_type ]; + }while(!mb_type); + + s->mb_intra = IS_INTRA(mb_type); + if(HAS_CBP(mb_type)){ + s->dsp.clear_blocks(s->block[0]); + cbpc = get_vlc2(&s->gb, cbpc_b_vlc.table, CBPC_B_VLC_BITS, 1); + if(s->mb_intra){ + dquant = IS_QUANT(mb_type); + goto intra; + } + + cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + + if (cbpy < 0){ + av_log(s->avctx, AV_LOG_ERROR, "b cbpy damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + if(s->alt_inter_vlc==0 || (cbpc & 3)!=3) + cbpy ^= 0xF; + + cbp = (cbpc & 3) | (cbpy << 2); + }else + cbp=0; + + av_assert2(!s->mb_intra); + + if(IS_QUANT(mb_type)){ + h263_decode_dquant(s); + } + + if(IS_DIRECT(mb_type)){ + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; + mb_type |= ff_mpeg4_set_direct_mv(s, 0, 0); + }else{ + s->mv_dir = 0; + s->mv_type= MV_TYPE_16X16; +//FIXME UMV + + if(USES_LIST(mb_type, 0)){ + int16_t *mot_val= ff_h263_pred_motion(s, 0, 0, &mx, &my); + s->mv_dir = MV_DIR_FORWARD; + + mx = ff_h263_decode_motion(s, mx, 1); + my = ff_h263_decode_motion(s, my, 1); + + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + mot_val[0 ]= mot_val[2 ]= mot_val[0+2*stride]= mot_val[2+2*stride]= mx; + mot_val[1 ]= mot_val[3 ]= mot_val[1+2*stride]= mot_val[3+2*stride]= my; + } + + if(USES_LIST(mb_type, 1)){ + int16_t *mot_val= ff_h263_pred_motion(s, 0, 1, &mx, &my); + s->mv_dir |= MV_DIR_BACKWARD; + + mx = ff_h263_decode_motion(s, mx, 1); + my = ff_h263_decode_motion(s, my, 1); + + s->mv[1][0][0] = mx; + s->mv[1][0][1] = my; + mot_val[0 ]= mot_val[2 ]= mot_val[0+2*stride]= mot_val[2+2*stride]= mx; + mot_val[1 ]= mot_val[3 ]= mot_val[1+2*stride]= mot_val[3+2*stride]= my; + } + } + + s->current_picture.mb_type[xy] = mb_type; + } else { /* I-Frame */ + do{ + cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2); + if (cbpc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "I cbpc damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + }while(cbpc == 8); + + s->dsp.clear_blocks(s->block[0]); + + dquant = cbpc & 4; + s->mb_intra = 1; +intra: + s->current_picture.mb_type[xy] = MB_TYPE_INTRA; + if (s->h263_aic) { + s->ac_pred = get_bits1(&s->gb); + if(s->ac_pred){ + s->current_picture.mb_type[xy] = MB_TYPE_INTRA | MB_TYPE_ACPRED; + + s->h263_aic_dir = get_bits1(&s->gb); + } + }else + s->ac_pred = 0; + + if(s->pb_frame && get_bits1(&s->gb)) + pb_mv_count = h263_get_modb(&s->gb, s->pb_frame, &cbpb); + cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + if(cbpy<0){ + av_log(s->avctx, AV_LOG_ERROR, "I cbpy damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) { + h263_decode_dquant(s); + } + + pb_mv_count += !!s->pb_frame; + } + + while(pb_mv_count--){ + ff_h263_decode_motion(s, 0, 1); + ff_h263_decode_motion(s, 0, 1); + } + + /* decode each block */ + for (i = 0; i < 6; i++) { + if (h263_decode_block(s, block[i], i, cbp&32) < 0) + return -1; + cbp+=cbp; + } + + if(s->pb_frame && h263_skip_b_part(s, cbpb) < 0) + return -1; + if(s->obmc && !s->mb_intra){ + if(s->pict_type == AV_PICTURE_TYPE_P && s->mb_x+1mb_width && s->mb_num_left != 1) + preview_obmc(s); + } +end: + + /* per-MB end of slice check */ + { + int v= show_bits(&s->gb, 16); + + if (get_bits_left(&s->gb) < 16) { + v >>= 16 - get_bits_left(&s->gb); + } + + if(v==0) + return SLICE_END; + } + + return SLICE_OK; +} + +/* most is hardcoded. should extend to handle all h263 streams */ +int ff_h263_decode_picture_header(MpegEncContext *s) +{ + int format, width, height, i; + uint32_t startcode; + + align_get_bits(&s->gb); + + startcode= get_bits(&s->gb, 22-8); + + for(i= get_bits_left(&s->gb); i>24; i-=8) { + startcode = ((startcode << 8) | get_bits(&s->gb, 8)) & 0x003FFFFF; + + if(startcode == 0x20) + break; + } + + if (startcode != 0x20) { + av_log(s->avctx, AV_LOG_ERROR, "Bad picture start code\n"); + return -1; + } + /* temporal reference */ + i = get_bits(&s->gb, 8); /* picture timestamp */ + if( (s->picture_number&~0xFF)+i < s->picture_number) + i+= 256; + s->current_picture_ptr->f.pts = + s->picture_number= (s->picture_number&~0xFF) + i; + + /* PTYPE starts here */ + if (get_bits1(&s->gb) != 1) { + /* marker */ + av_log(s->avctx, AV_LOG_ERROR, "Bad marker\n"); + return -1; + } + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "Bad H263 id\n"); + return -1; /* h263 id */ + } + skip_bits1(&s->gb); /* split screen off */ + skip_bits1(&s->gb); /* camera off */ + skip_bits1(&s->gb); /* freeze picture release off */ + + format = get_bits(&s->gb, 3); + /* + 0 forbidden + 1 sub-QCIF + 10 QCIF + 7 extended PTYPE (PLUSPTYPE) + */ + + if (format != 7 && format != 6) { + s->h263_plus = 0; + /* H.263v1 */ + width = ff_h263_format[format][0]; + height = ff_h263_format[format][1]; + if (!width) + return -1; + + s->pict_type = AV_PICTURE_TYPE_I + get_bits1(&s->gb); + + s->h263_long_vectors = get_bits1(&s->gb); + + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "H263 SAC not supported\n"); + return -1; /* SAC: off */ + } + s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ + s->unrestricted_mv = s->h263_long_vectors || s->obmc; + + s->pb_frame = get_bits1(&s->gb); + s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */ + + s->width = width; + s->height = height; + s->avctx->sample_aspect_ratio= (AVRational){12,11}; + s->avctx->time_base= (AVRational){1001, 30000}; + } else { + int ufep; + + /* H.263v2 */ + s->h263_plus = 1; + ufep = get_bits(&s->gb, 3); /* Update Full Extended PTYPE */ + + /* ufep other than 0 and 1 are reserved */ + if (ufep == 1) { + /* OPPTYPE */ + format = get_bits(&s->gb, 3); + av_dlog(s->avctx, "ufep=1, format: %d\n", format); + s->custom_pcf= get_bits1(&s->gb); + s->umvplus = get_bits1(&s->gb); /* Unrestricted Motion Vector */ + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "Syntax-based Arithmetic Coding (SAC) not supported\n"); + } + s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ + s->h263_aic = get_bits1(&s->gb); /* Advanced Intra Coding (AIC) */ + s->loop_filter= get_bits1(&s->gb); + s->unrestricted_mv = s->umvplus || s->obmc || s->loop_filter; + if(s->avctx->lowres) + s->loop_filter = 0; + + s->h263_slice_structured= get_bits1(&s->gb); + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "Reference Picture Selection not supported\n"); + } + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "Independent Segment Decoding not supported\n"); + } + s->alt_inter_vlc= get_bits1(&s->gb); + s->modified_quant= get_bits1(&s->gb); + if(s->modified_quant) + s->chroma_qscale_table= ff_h263_chroma_qscale_table; + + skip_bits(&s->gb, 1); /* Prevent start code emulation */ + + skip_bits(&s->gb, 3); /* Reserved */ + } else if (ufep != 0) { + av_log(s->avctx, AV_LOG_ERROR, "Bad UFEP type (%d)\n", ufep); + return -1; + } + + /* MPPTYPE */ + s->pict_type = get_bits(&s->gb, 3); + switch(s->pict_type){ + case 0: s->pict_type= AV_PICTURE_TYPE_I;break; + case 1: s->pict_type= AV_PICTURE_TYPE_P;break; + case 2: s->pict_type= AV_PICTURE_TYPE_P;s->pb_frame = 3;break; + case 3: s->pict_type= AV_PICTURE_TYPE_B;break; + case 7: s->pict_type= AV_PICTURE_TYPE_I;break; //ZYGO + default: + return -1; + } + skip_bits(&s->gb, 2); + s->no_rounding = get_bits1(&s->gb); + skip_bits(&s->gb, 4); + + /* Get the picture dimensions */ + if (ufep) { + if (format == 6) { + /* Custom Picture Format (CPFMT) */ + s->aspect_ratio_info = get_bits(&s->gb, 4); + av_dlog(s->avctx, "aspect: %d\n", s->aspect_ratio_info); + /* aspect ratios: + 0 - forbidden + 1 - 1:1 + 2 - 12:11 (CIF 4:3) + 3 - 10:11 (525-type 4:3) + 4 - 16:11 (CIF 16:9) + 5 - 40:33 (525-type 16:9) + 6-14 - reserved + */ + width = (get_bits(&s->gb, 9) + 1) * 4; + skip_bits1(&s->gb); + height = get_bits(&s->gb, 9) * 4; + av_dlog(s->avctx, "\nH.263+ Custom picture: %dx%d\n",width,height); + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + /* aspected dimensions */ + s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 8); + s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 8); + }else{ + s->avctx->sample_aspect_ratio= ff_h263_pixel_aspect[s->aspect_ratio_info]; + } + } else { + width = ff_h263_format[format][0]; + height = ff_h263_format[format][1]; + s->avctx->sample_aspect_ratio= (AVRational){12,11}; + } + if ((width == 0) || (height == 0)) + return -1; + s->width = width; + s->height = height; + + if(s->custom_pcf){ + int gcd; + s->avctx->time_base.den= 1800000; + s->avctx->time_base.num= 1000 + get_bits1(&s->gb); + s->avctx->time_base.num*= get_bits(&s->gb, 7); + if(s->avctx->time_base.num == 0){ + av_log(s, AV_LOG_ERROR, "zero framerate\n"); + return -1; + } + gcd= av_gcd(s->avctx->time_base.den, s->avctx->time_base.num); + s->avctx->time_base.den /= gcd; + s->avctx->time_base.num /= gcd; + }else{ + s->avctx->time_base= (AVRational){1001, 30000}; + } + } + + if(s->custom_pcf){ + skip_bits(&s->gb, 2); //extended Temporal reference + } + + if (ufep) { + if (s->umvplus) { + if(get_bits1(&s->gb)==0) /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */ + skip_bits1(&s->gb); + } + if(s->h263_slice_structured){ + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "rectangular slices not supported\n"); + } + if (get_bits1(&s->gb) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "unordered slices not supported\n"); + } + } + } + + s->qscale = get_bits(&s->gb, 5); + } + + if (s->width == 0 || s->height == 0) { + av_log(s->avctx, AV_LOG_ERROR, "dimensions 0\n"); + return -1; + } + s->mb_width = (s->width + 15) / 16; + s->mb_height = (s->height + 15) / 16; + s->mb_num = s->mb_width * s->mb_height; + + if (s->pb_frame) { + skip_bits(&s->gb, 3); /* Temporal reference for B-pictures */ + if (s->custom_pcf) + skip_bits(&s->gb, 2); //extended Temporal reference + skip_bits(&s->gb, 2); /* Quantization information for B-pictures */ + } + + if (s->pict_type!=AV_PICTURE_TYPE_B) { + s->time = s->picture_number; + s->pp_time = s->time - s->last_non_b_time; + s->last_non_b_time = s->time; + }else{ + s->time = s->picture_number; + s->pb_time = s->pp_time - (s->last_non_b_time - s->time); + if (s->pp_time <=s->pb_time || + s->pp_time <= s->pp_time - s->pb_time || + s->pp_time <= 0){ + s->pp_time = 2; + s->pb_time = 1; + } + ff_mpeg4_init_direct_mv(s); + } + + /* PEI */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + + if(s->h263_slice_structured){ + if (get_bits1(&s->gb) != 1) { + av_log(s->avctx, AV_LOG_ERROR, "SEPB1 marker missing\n"); + return -1; + } + + ff_h263_decode_mba(s); + + if (get_bits1(&s->gb) != 1) { + av_log(s->avctx, AV_LOG_ERROR, "SEPB2 marker missing\n"); + return -1; + } + } + s->f_code = 1; + + if(s->h263_aic){ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_aic_dc_scale_table; + }else{ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } + + ff_h263_show_pict_info(s); + if (s->pict_type == AV_PICTURE_TYPE_I && s->codec_tag == AV_RL32("ZYGO") && get_bits_left(&s->gb) >= 85 + 13*3*16 + 50){ + int i,j; + for(i=0; i<85; i++) av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb)); + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + for(i=0; i<13; i++){ + for(j=0; j<3; j++){ + int v= get_bits(&s->gb, 8); + v |= get_sbits(&s->gb, 8)<<8; + av_log(s->avctx, AV_LOG_DEBUG, " %5d", v); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + for(i=0; i<50; i++) av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb)); + } + + return 0; +} diff --git a/ffmpeg/libavcodec/ituh263enc.c b/ffmpeg/libavcodec/ituh263enc.c new file mode 100644 index 0000000..9a03f02 --- /dev/null +++ b/ffmpeg/libavcodec/ituh263enc.c @@ -0,0 +1,837 @@ +/* + * ITU H263 bitstream encoder + * Copyright (c) 2000,2001 Fabrice Bellard + * H263+ support. + * Copyright (c) 2001 Juan J. Sierralta P + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * h263 bitstream encoder. + */ + +//#define DEBUG +#include + +#include "avcodec.h" +#include "mpegvideo.h" +#include "h263.h" +#include "mathops.h" +#include "unary.h" +#include "flv.h" +#include "mpeg4video.h" +#include "internal.h" + +/** + * Table of number of bits a motion vector component needs. + */ +static uint8_t mv_penalty[MAX_FCODE+1][MAX_MV*2+1]; + +/** + * Minimal fcode that a motion vector component would need. + */ +static uint8_t fcode_tab[MAX_MV*2+1]; + +/** + * Minimal fcode that a motion vector component would need in umv. + * All entries in this table are 1. + */ +static uint8_t umv_fcode_tab[MAX_MV*2+1]; + +//unified encoding tables for run length encoding of coefficients +//unified in the sense that the specification specifies the encoding in several steps. +static uint8_t uni_h263_intra_aic_rl_len [64*64*2*2]; +static uint8_t uni_h263_inter_rl_len [64*64*2*2]; +//#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128 + (run)*256 + (level)) +//#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128*64 + (run) + (level)*64) +#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level)) + +static const uint8_t wrong_run[102] = { + 1, 2, 3, 5, 4, 10, 9, 8, +11, 15, 17, 16, 23, 22, 21, 20, +19, 18, 25, 24, 27, 26, 11, 7, + 6, 1, 2, 13, 2, 2, 2, 2, + 6, 12, 3, 9, 1, 3, 4, 3, + 7, 4, 1, 1, 5, 5, 14, 6, + 1, 7, 1, 8, 1, 1, 1, 1, +10, 1, 1, 5, 9, 17, 25, 24, +29, 33, 32, 41, 2, 23, 28, 31, + 3, 22, 30, 4, 27, 40, 8, 26, + 6, 39, 7, 38, 16, 37, 15, 10, +11, 12, 13, 14, 1, 21, 20, 18, +19, 2, 1, 34, 35, 36 +}; + +/** + * Return the 4 bit value that specifies the given aspect ratio. + * This may be one of the standard aspect ratios or it specifies + * that the aspect will be stored explicitly later. + */ +av_const int ff_h263_aspect_to_info(AVRational aspect){ + int i; + + if(aspect.num==0) aspect= (AVRational){1,1}; + + for(i=1; i<6; i++){ + if(av_cmp_q(ff_h263_pixel_aspect[i], aspect) == 0){ + return i; + } + } + + return FF_ASPECT_EXTENDED; +} + +void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) +{ + int format, coded_frame_rate, coded_frame_rate_base, i, temp_ref; + int best_clock_code=1; + int best_divisor=60; + int best_error= INT_MAX; + + if(s->h263_plus){ + for(i=0; i<2; i++){ + int div, error; + div= (s->avctx->time_base.num*1800000LL + 500LL*s->avctx->time_base.den) / ((1000LL+i)*s->avctx->time_base.den); + div= av_clip(div, 1, 127); + error= FFABS(s->avctx->time_base.num*1800000LL - (1000LL+i)*s->avctx->time_base.den*div); + if(error < best_error){ + best_error= error; + best_divisor= div; + best_clock_code= i; + } + } + } + s->custom_pcf= best_clock_code!=1 || best_divisor!=60; + coded_frame_rate= 1800000; + coded_frame_rate_base= (1000+best_clock_code)*best_divisor; + + avpriv_align_put_bits(&s->pb); + + /* Update the pointer to last GOB */ + s->ptr_lastgob = put_bits_ptr(&s->pb); + put_bits(&s->pb, 22, 0x20); /* PSC */ + temp_ref= s->picture_number * (int64_t)coded_frame_rate * s->avctx->time_base.num / //FIXME use timestamp + (coded_frame_rate_base * (int64_t)s->avctx->time_base.den); + put_sbits(&s->pb, 8, temp_ref); /* TemporalReference */ + + put_bits(&s->pb, 1, 1); /* marker */ + put_bits(&s->pb, 1, 0); /* h263 id */ + put_bits(&s->pb, 1, 0); /* split screen off */ + put_bits(&s->pb, 1, 0); /* camera off */ + put_bits(&s->pb, 1, 0); /* freeze picture release off */ + + format = ff_match_2uint16(ff_h263_format, FF_ARRAY_ELEMS(ff_h263_format), s->width, s->height); + if (!s->h263_plus) { + /* H.263v1 */ + put_bits(&s->pb, 3, format); + put_bits(&s->pb, 1, (s->pict_type == AV_PICTURE_TYPE_P)); + /* By now UMV IS DISABLED ON H.263v1, since the restrictions + of H.263v1 UMV implies to check the predicted MV after + calculation of the current MB to see if we're on the limits */ + put_bits(&s->pb, 1, 0); /* Unrestricted Motion Vector: off */ + put_bits(&s->pb, 1, 0); /* SAC: off */ + put_bits(&s->pb, 1, s->obmc); /* Advanced Prediction */ + put_bits(&s->pb, 1, 0); /* only I/P frames, no PB frame */ + put_bits(&s->pb, 5, s->qscale); + put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */ + } else { + int ufep=1; + /* H.263v2 */ + /* H.263 Plus PTYPE */ + + put_bits(&s->pb, 3, 7); + put_bits(&s->pb,3,ufep); /* Update Full Extended PTYPE */ + if (format == 8) + put_bits(&s->pb,3,6); /* Custom Source Format */ + else + put_bits(&s->pb, 3, format); + + put_bits(&s->pb,1, s->custom_pcf); + put_bits(&s->pb,1, s->umvplus); /* Unrestricted Motion Vector */ + put_bits(&s->pb,1,0); /* SAC: off */ + put_bits(&s->pb,1,s->obmc); /* Advanced Prediction Mode */ + put_bits(&s->pb,1,s->h263_aic); /* Advanced Intra Coding */ + put_bits(&s->pb,1,s->loop_filter); /* Deblocking Filter */ + put_bits(&s->pb,1,s->h263_slice_structured); /* Slice Structured */ + put_bits(&s->pb,1,0); /* Reference Picture Selection: off */ + put_bits(&s->pb,1,0); /* Independent Segment Decoding: off */ + put_bits(&s->pb,1,s->alt_inter_vlc); /* Alternative Inter VLC */ + put_bits(&s->pb,1,s->modified_quant); /* Modified Quantization: */ + put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ + put_bits(&s->pb,3,0); /* Reserved */ + + put_bits(&s->pb, 3, s->pict_type == AV_PICTURE_TYPE_P); + + put_bits(&s->pb,1,0); /* Reference Picture Resampling: off */ + put_bits(&s->pb,1,0); /* Reduced-Resolution Update: off */ + put_bits(&s->pb,1,s->no_rounding); /* Rounding Type */ + put_bits(&s->pb,2,0); /* Reserved */ + put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ + + /* This should be here if PLUSPTYPE */ + put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */ + + if (format == 8) { + /* Custom Picture Format (CPFMT) */ + s->aspect_ratio_info= ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio); + + put_bits(&s->pb,4,s->aspect_ratio_info); + put_bits(&s->pb,9,(s->width >> 2) - 1); + put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ + put_bits(&s->pb,9,(s->height >> 2)); + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED){ + put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.num); + put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.den); + } + } + if(s->custom_pcf){ + if(ufep){ + put_bits(&s->pb, 1, best_clock_code); + put_bits(&s->pb, 7, best_divisor); + } + put_sbits(&s->pb, 2, temp_ref>>8); + } + + /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */ + if (s->umvplus) +// put_bits(&s->pb,1,1); /* Limited according tables of Annex D */ +//FIXME check actual requested range + put_bits(&s->pb,2,1); /* unlimited */ + if(s->h263_slice_structured) + put_bits(&s->pb,2,0); /* no weird submodes */ + + put_bits(&s->pb, 5, s->qscale); + } + + put_bits(&s->pb, 1, 0); /* no PEI */ + + if(s->h263_slice_structured){ + put_bits(&s->pb, 1, 1); + + av_assert1(s->mb_x == 0 && s->mb_y == 0); + ff_h263_encode_mba(s); + + put_bits(&s->pb, 1, 1); + } + + if(s->h263_aic){ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_aic_dc_scale_table; + }else{ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } +} + +/** + * Encode a group of blocks header. + */ +void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line) +{ + put_bits(&s->pb, 17, 1); /* GBSC */ + + if(s->h263_slice_structured){ + put_bits(&s->pb, 1, 1); + + ff_h263_encode_mba(s); + + if(s->mb_num > 1583) + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 2, s->pict_type == AV_PICTURE_TYPE_I); /* GFID */ + }else{ + int gob_number= mb_line / s->gob_index; + + put_bits(&s->pb, 5, gob_number); /* GN */ + put_bits(&s->pb, 2, s->pict_type == AV_PICTURE_TYPE_I); /* GFID */ + put_bits(&s->pb, 5, s->qscale); /* GQUANT */ + } +} + +/** + * modify qscale so that encoding is actually possible in h263 (limit difference to -2..2) + */ +void ff_clean_h263_qscales(MpegEncContext *s){ + int i; + int8_t * const qscale_table = s->current_picture.qscale_table; + + ff_init_qscale_tab(s); + + for(i=1; imb_num; i++){ + if(qscale_table[ s->mb_index2xy[i] ] - qscale_table[ s->mb_index2xy[i-1] ] >2) + qscale_table[ s->mb_index2xy[i] ]= qscale_table[ s->mb_index2xy[i-1] ]+2; + } + for(i=s->mb_num-2; i>=0; i--){ + if(qscale_table[ s->mb_index2xy[i] ] - qscale_table[ s->mb_index2xy[i+1] ] >2) + qscale_table[ s->mb_index2xy[i] ]= qscale_table[ s->mb_index2xy[i+1] ]+2; + } + + if(s->codec_id != AV_CODEC_ID_H263P){ + for(i=1; imb_num; i++){ + int mb_xy= s->mb_index2xy[i]; + + if(qscale_table[mb_xy] != qscale_table[s->mb_index2xy[i-1]] && (s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_INTER4V)){ + s->mb_type[mb_xy]|= CANDIDATE_MB_TYPE_INTER; + } + } + } +} + +static const int dquant_code[5]= {1,0,9,2,3}; + +/** + * Encode an 8x8 block. + * @param block the 8x8 block + * @param n block index (0-3 are luma, 4-5 are chroma) + */ +static void h263_encode_block(MpegEncContext * s, int16_t * block, int n) +{ + int level, run, last, i, j, last_index, last_non_zero, sign, slevel, code; + RLTable *rl; + + rl = &ff_h263_rl_inter; + if (s->mb_intra && !s->h263_aic) { + /* DC coef */ + level = block[0]; + /* 255 cannot be represented, so we clamp */ + if (level > 254) { + level = 254; + block[0] = 254; + } + /* 0 cannot be represented also */ + else if (level < 1) { + level = 1; + block[0] = 1; + } + if (level == 128) //FIXME check rv10 + put_bits(&s->pb, 8, 0xff); + else + put_bits(&s->pb, 8, level); + i = 1; + } else { + i = 0; + if (s->h263_aic && s->mb_intra) + rl = &ff_rl_intra_aic; + + if(s->alt_inter_vlc && !s->mb_intra){ + int aic_vlc_bits=0; + int inter_vlc_bits=0; + int wrong_pos=-1; + int aic_code; + + last_index = s->block_last_index[n]; + last_non_zero = i - 1; + for (; i <= last_index; i++) { + j = s->intra_scantable.permutated[i]; + level = block[j]; + if (level) { + run = i - last_non_zero - 1; + last = (i == last_index); + + if(level<0) level= -level; + + code = get_rl_index(rl, last, run, level); + aic_code = get_rl_index(&ff_rl_intra_aic, last, run, level); + inter_vlc_bits += rl->table_vlc[code][1]+1; + aic_vlc_bits += ff_rl_intra_aic.table_vlc[aic_code][1]+1; + + if (code == rl->n) { + inter_vlc_bits += 1+6+8-1; + } + if (aic_code == ff_rl_intra_aic.n) { + aic_vlc_bits += 1+6+8-1; + wrong_pos += run + 1; + }else + wrong_pos += wrong_run[aic_code]; + last_non_zero = i; + } + } + i = 0; + if(aic_vlc_bits < inter_vlc_bits && wrong_pos > 63) + rl = &ff_rl_intra_aic; + } + } + + /* AC coefs */ + last_index = s->block_last_index[n]; + last_non_zero = i - 1; + for (; i <= last_index; i++) { + j = s->intra_scantable.permutated[i]; + level = block[j]; + if (level) { + run = i - last_non_zero - 1; + last = (i == last_index); + sign = 0; + slevel = level; + if (level < 0) { + sign = 1; + level = -level; + } + code = get_rl_index(rl, last, run, level); + put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); + if (code == rl->n) { + if(!CONFIG_FLV_ENCODER || s->h263_flv <= 1){ + put_bits(&s->pb, 1, last); + put_bits(&s->pb, 6, run); + + av_assert2(slevel != 0); + + if(level < 128) + put_sbits(&s->pb, 8, slevel); + else{ + put_bits(&s->pb, 8, 128); + put_sbits(&s->pb, 5, slevel); + put_sbits(&s->pb, 6, slevel>>5); + } + }else{ + ff_flv2_encode_ac_esc(&s->pb, slevel, level, run, last); + } + } else { + put_bits(&s->pb, 1, sign); + } + last_non_zero = i; + } + } +} + +/* Encode MV differences on H.263+ with Unrestricted MV mode */ +static void h263p_encode_umotion(MpegEncContext * s, int val) +{ + short sval = 0; + short i = 0; + short n_bits = 0; + short temp_val; + int code = 0; + int tcode; + + if ( val == 0) + put_bits(&s->pb, 1, 1); + else if (val == 1) + put_bits(&s->pb, 3, 0); + else if (val == -1) + put_bits(&s->pb, 3, 2); + else { + + sval = ((val < 0) ? (short)(-val):(short)val); + temp_val = sval; + + while (temp_val != 0) { + temp_val = temp_val >> 1; + n_bits++; + } + + i = n_bits - 1; + while (i > 0) { + tcode = (sval & (1 << (i-1))) >> (i-1); + tcode = (tcode << 1) | 1; + code = (code << 2) | tcode; + i--; + } + code = ((code << 1) | (val < 0)) << 1; + put_bits(&s->pb, (2*n_bits)+1, code); + } +} + +void ff_h263_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y) +{ + int cbpc, cbpy, i, cbp, pred_x, pred_y; + int16_t pred_dc; + int16_t rec_intradc[6]; + int16_t *dc_ptr[6]; + const int interleaved_stats= (s->flags&CODEC_FLAG_PASS1); + + if (!s->mb_intra) { + /* compute cbp */ + cbp= get_p_cbp(s, block, motion_x, motion_y); + + if ((cbp | motion_x | motion_y | s->dquant | (s->mv_type - MV_TYPE_16X16)) == 0) { + /* skip macroblock */ + put_bits(&s->pb, 1, 1); + if(interleaved_stats){ + s->misc_bits++; + s->last_bits++; + } + s->skip_count++; + + return; + } + put_bits(&s->pb, 1, 0); /* mb coded */ + + cbpc = cbp & 3; + cbpy = cbp >> 2; + if(s->alt_inter_vlc==0 || cbpc!=3) + cbpy ^= 0xF; + if(s->dquant) cbpc+= 8; + if(s->mv_type==MV_TYPE_16X16){ + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc], + ff_h263_inter_MCBPC_code[cbpc]); + + put_bits(&s->pb, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + if(s->dquant) + put_bits(&s->pb, 2, dquant_code[s->dquant+2]); + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + /* motion vectors: 16x16 mode */ + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + + if (!s->umvplus) { + ff_h263_encode_motion_vector(s, motion_x - pred_x, + motion_y - pred_y, 1); + } + else { + h263p_encode_umotion(s, motion_x - pred_x); + h263p_encode_umotion(s, motion_y - pred_y); + if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1)) + /* To prevent Start Code emulation */ + put_bits(&s->pb,1,1); + } + }else{ + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc+16], + ff_h263_inter_MCBPC_code[cbpc+16]); + put_bits(&s->pb, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + if(s->dquant) + put_bits(&s->pb, 2, dquant_code[s->dquant+2]); + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + for(i=0; i<4; i++){ + /* motion vectors: 8x8 mode*/ + ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); + + motion_x = s->current_picture.motion_val[0][s->block_index[i]][0]; + motion_y = s->current_picture.motion_val[0][s->block_index[i]][1]; + if (!s->umvplus) { + ff_h263_encode_motion_vector(s, motion_x - pred_x, + motion_y - pred_y, 1); + } + else { + h263p_encode_umotion(s, motion_x - pred_x); + h263p_encode_umotion(s, motion_y - pred_y); + if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1)) + /* To prevent Start Code emulation */ + put_bits(&s->pb,1,1); + } + } + } + + if(interleaved_stats){ + s->mv_bits+= get_bits_diff(s); + } + } else { + av_assert2(s->mb_intra); + + cbp = 0; + if (s->h263_aic) { + /* Predict DC */ + for(i=0; i<6; i++) { + int16_t level = block[i][0]; + int scale; + + if(i<4) scale= s->y_dc_scale; + else scale= s->c_dc_scale; + + pred_dc = ff_h263_pred_dc(s, i, &dc_ptr[i]); + level -= pred_dc; + /* Quant */ + if (level >= 0) + level = (level + (scale>>1))/scale; + else + level = (level - (scale>>1))/scale; + + /* AIC can change CBP */ + if (level == 0 && s->block_last_index[i] == 0) + s->block_last_index[i] = -1; + + if(!s->modified_quant){ + if (level < -127) + level = -127; + else if (level > 127) + level = 127; + } + + block[i][0] = level; + /* Reconstruction */ + rec_intradc[i] = scale*level + pred_dc; + /* Oddify */ + rec_intradc[i] |= 1; + //if ((rec_intradc[i] % 2) == 0) + // rec_intradc[i]++; + /* Clipping */ + if (rec_intradc[i] < 0) + rec_intradc[i] = 0; + else if (rec_intradc[i] > 2047) + rec_intradc[i] = 2047; + + /* Update AC/DC tables */ + *dc_ptr[i] = rec_intradc[i]; + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + }else{ + for(i=0; i<6; i++) { + /* compute cbp */ + if (s->block_last_index[i] >= 1) + cbp |= 1 << (5 - i); + } + } + + cbpc = cbp & 3; + if (s->pict_type == AV_PICTURE_TYPE_I) { + if(s->dquant) cbpc+=4; + put_bits(&s->pb, + ff_h263_intra_MCBPC_bits[cbpc], + ff_h263_intra_MCBPC_code[cbpc]); + } else { + if(s->dquant) cbpc+=8; + put_bits(&s->pb, 1, 0); /* mb coded */ + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc + 4], + ff_h263_inter_MCBPC_code[cbpc + 4]); + } + if (s->h263_aic) { + /* XXX: currently, we do not try to use ac prediction */ + put_bits(&s->pb, 1, 0); /* no AC prediction */ + } + cbpy = cbp >> 2; + put_bits(&s->pb, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + if(s->dquant) + put_bits(&s->pb, 2, dquant_code[s->dquant+2]); + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + } + + for(i=0; i<6; i++) { + /* encode each block */ + h263_encode_block(s, block[i], i); + + /* Update INTRADC for decoding */ + if (s->h263_aic && s->mb_intra) { + block[i][0] = rec_intradc[i]; + + } + } + + if(interleaved_stats){ + if (!s->mb_intra) { + s->p_tex_bits+= get_bits_diff(s); + s->f_count++; + }else{ + s->i_tex_bits+= get_bits_diff(s); + s->i_count++; + } + } +} + +void ff_h263_encode_motion(MpegEncContext * s, int val, int f_code) +{ + int range, bit_size, sign, code, bits; + + if (val == 0) { + /* zero vector */ + code = 0; + put_bits(&s->pb, ff_mvtab[code][1], ff_mvtab[code][0]); + } else { + bit_size = f_code - 1; + range = 1 << bit_size; + /* modulo encoding */ + val = sign_extend(val, 6 + bit_size); + sign = val>>31; + val= (val^sign)-sign; + sign&=1; + + val--; + code = (val >> bit_size) + 1; + bits = val & (range - 1); + + put_bits(&s->pb, ff_mvtab[code][1] + 1, (ff_mvtab[code][0] << 1) | sign); + if (bit_size > 0) { + put_bits(&s->pb, bit_size, bits); + } + } +} + +static void init_mv_penalty_and_fcode(MpegEncContext *s) +{ + int f_code; + int mv; + + for(f_code=1; f_code<=MAX_FCODE; f_code++){ + for(mv=-MAX_MV; mv<=MAX_MV; mv++){ + int len; + + if(mv==0) len= ff_mvtab[0][1]; + else{ + int val, bit_size, code; + + bit_size = f_code - 1; + + val=mv; + if (val < 0) + val = -val; + val--; + code = (val >> bit_size) + 1; + if(code<33){ + len= ff_mvtab[code][1] + 1 + bit_size; + }else{ + len= ff_mvtab[32][1] + av_log2(code>>5) + 2 + bit_size; + } + } + + mv_penalty[f_code][mv+MAX_MV]= len; + } + } + + for(f_code=MAX_FCODE; f_code>0; f_code--){ + for(mv=-(16<= 64); + av_assert0(MAX_RUN >= 63); + + for(slevel=-64; slevel<64; slevel++){ + if(slevel==0) continue; + for(run=0; run<64; run++){ + for(last=0; last<=1; last++){ + const int index= UNI_MPEG4_ENC_INDEX(last, run, slevel+64); + int level= slevel < 0 ? -slevel : slevel; + int sign= slevel < 0 ? 1 : 0; + int bits, len, code; + + len_tab[index]= 100; + + /* ESC0 */ + code= get_rl_index(rl, last, run, level); + bits= rl->table_vlc[code][0]; + len= rl->table_vlc[code][1]; + bits=bits*2+sign; len++; + + if(code!=rl->n && len < len_tab[index]){ + if(bits_tab) bits_tab[index]= bits; + len_tab [index]= len; + } + /* ESC */ + bits= rl->table_vlc[rl->n][0]; + len = rl->table_vlc[rl->n][1]; + bits=bits*2+last; len++; + bits=bits*64+run; len+=6; + bits=bits*256+(level&0xff); len+=8; + + if(len < len_tab[index]){ + if(bits_tab) bits_tab[index]= bits; + len_tab [index]= len; + } + } + } + } +} + +void ff_h263_encode_init(MpegEncContext *s) +{ + static int done = 0; + + if (!done) { + done = 1; + + ff_init_rl(&ff_h263_rl_inter, ff_h263_static_rl_table_store[0]); + ff_init_rl(&ff_rl_intra_aic, ff_h263_static_rl_table_store[1]); + + init_uni_h263_rl_tab(&ff_rl_intra_aic, NULL, uni_h263_intra_aic_rl_len); + init_uni_h263_rl_tab(&ff_h263_rl_inter , NULL, uni_h263_inter_rl_len); + + init_mv_penalty_and_fcode(s); + } + s->me.mv_penalty= mv_penalty; //FIXME exact table for msmpeg4 & h263p + + s->intra_ac_vlc_length =s->inter_ac_vlc_length = uni_h263_inter_rl_len; + s->intra_ac_vlc_last_length=s->inter_ac_vlc_last_length= uni_h263_inter_rl_len + 128*64; + if(s->h263_aic){ + s->intra_ac_vlc_length = uni_h263_intra_aic_rl_len; + s->intra_ac_vlc_last_length= uni_h263_intra_aic_rl_len + 128*64; + } + s->ac_esc_length= 7+1+6+8; + + // use fcodes >1 only for mpeg4 & h263 & h263p FIXME + switch(s->codec_id){ + case AV_CODEC_ID_MPEG4: + s->fcode_tab= fcode_tab; + break; + case AV_CODEC_ID_H263P: + if(s->umvplus) + s->fcode_tab= umv_fcode_tab; + if(s->modified_quant){ + s->min_qcoeff= -2047; + s->max_qcoeff= 2047; + }else{ + s->min_qcoeff= -127; + s->max_qcoeff= 127; + } + break; + //Note for mpeg4 & h263 the dc-scale table will be set per frame as needed later + case AV_CODEC_ID_FLV1: + if (s->h263_flv > 1) { + s->min_qcoeff= -1023; + s->max_qcoeff= 1023; + } else { + s->min_qcoeff= -127; + s->max_qcoeff= 127; + } + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + break; + default: //nothing needed - default table already set in mpegvideo.c + s->min_qcoeff= -127; + s->max_qcoeff= 127; + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } +} + +void ff_h263_encode_mba(MpegEncContext *s) +{ + int i, mb_pos; + + for(i=0; i<6; i++){ + if(s->mb_num-1 <= ff_mba_max[i]) break; + } + mb_pos= s->mb_x + s->mb_width*s->mb_y; + put_bits(&s->pb, ff_mba_length[i], mb_pos); +} diff --git a/ffmpeg/libavcodec/ivi_common.c b/ffmpeg/libavcodec/ivi_common.c new file mode 100644 index 0000000..265c645 --- /dev/null +++ b/ffmpeg/libavcodec/ivi_common.c @@ -0,0 +1,1375 @@ +/* + * common functions for Indeo Video Interactive codecs (Indeo4 and Indeo5) + * + * Copyright (c) 2009 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * This file contains functions and data shared by both Indeo4 and + * Indeo5 decoders. + */ + +#define BITSTREAM_READER_LE +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" +#include "ivi_common.h" +#include "ivi_dsp.h" + +extern const IVIHuffDesc ff_ivi_mb_huff_desc[8]; ///< static macroblock huffman tables +extern const IVIHuffDesc ff_ivi_blk_huff_desc[8]; ///< static block huffman tables + +static VLC ivi_mb_vlc_tabs [8]; ///< static macroblock Huffman tables +static VLC ivi_blk_vlc_tabs[8]; ///< static block Huffman tables + +/** + * Reverse "nbits" bits of the value "val" and return the result + * in the least significant bits. + */ +static uint16_t inv_bits(uint16_t val, int nbits) +{ + uint16_t res; + + if (nbits <= 8) { + res = ff_reverse[val] >> (8-nbits); + } else + res = ((ff_reverse[val & 0xFF] << 8) + (ff_reverse[val >> 8])) >> (16-nbits); + + return res; +} + +/* + * Generate a huffman codebook from the given descriptor + * and convert it into the FFmpeg VLC table. + * + * @param[in] cb pointer to codebook descriptor + * @param[out] vlc where to place the generated VLC table + * @param[in] flag flag: 1 - for static or 0 for dynamic tables + * @return result code: 0 - OK, -1 = error (invalid codebook descriptor) + */ +static int ivi_create_huff_from_desc(const IVIHuffDesc *cb, VLC *vlc, int flag) +{ + int pos, i, j, codes_per_row, prefix, not_last_row; + uint16_t codewords[256]; /* FIXME: move this temporal storage out? */ + uint8_t bits[256]; + + pos = 0; /* current position = 0 */ + + for (i = 0; i < cb->num_rows; i++) { + codes_per_row = 1 << cb->xbits[i]; + not_last_row = (i != cb->num_rows - 1); + prefix = ((1 << i) - 1) << (cb->xbits[i] + not_last_row); + + for (j = 0; j < codes_per_row; j++) { + if (pos >= 256) /* Some Indeo5 codebooks can have more than 256 */ + break; /* elements, but only 256 codes are allowed! */ + + bits[pos] = i + cb->xbits[i] + not_last_row; + if (bits[pos] > IVI_VLC_BITS) + return -1; /* invalid descriptor */ + + codewords[pos] = inv_bits((prefix | j), bits[pos]); + if (!bits[pos]) + bits[pos] = 1; + + pos++; + }//for j + }//for i + + /* number of codewords = pos */ + return init_vlc(vlc, IVI_VLC_BITS, pos, bits, 1, 1, codewords, 2, 2, + (flag ? INIT_VLC_USE_NEW_STATIC : 0) | INIT_VLC_LE); +} + +void ff_ivi_init_static_vlc(void) +{ + int i; + static VLC_TYPE table_data[8192 * 16][2]; + static int initialized_vlcs = 0; + + if (initialized_vlcs) + return; + for (i = 0; i < 8; i++) { + ivi_mb_vlc_tabs[i].table = table_data + i * 2 * 8192; + ivi_mb_vlc_tabs[i].table_allocated = 8192; + ivi_create_huff_from_desc(&ff_ivi_mb_huff_desc[i], &ivi_mb_vlc_tabs[i], 1); + ivi_blk_vlc_tabs[i].table = table_data + (i * 2 + 1) * 8192; + ivi_blk_vlc_tabs[i].table_allocated = 8192; + ivi_create_huff_from_desc(&ff_ivi_blk_huff_desc[i], &ivi_blk_vlc_tabs[i], 1); + } + initialized_vlcs = 1; +} + +/* + * Copy huffman codebook descriptors. + * + * @param[out] dst ptr to the destination descriptor + * @param[in] src ptr to the source descriptor + */ +static void ivi_huff_desc_copy(IVIHuffDesc *dst, const IVIHuffDesc *src) +{ + dst->num_rows = src->num_rows; + memcpy(dst->xbits, src->xbits, src->num_rows); +} + +/* + * Compare two huffman codebook descriptors. + * + * @param[in] desc1 ptr to the 1st descriptor to compare + * @param[in] desc2 ptr to the 2nd descriptor to compare + * @return comparison result: 0 - equal, 1 - not equal + */ +static int ivi_huff_desc_cmp(const IVIHuffDesc *desc1, const IVIHuffDesc *desc2) +{ + return desc1->num_rows != desc2->num_rows + || memcmp(desc1->xbits, desc2->xbits, desc1->num_rows); +} + +int ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab, + IVIHuffTab *huff_tab, AVCodecContext *avctx) +{ + int i, result; + IVIHuffDesc new_huff; + + if (!desc_coded) { + /* select default table */ + huff_tab->tab = (which_tab) ? &ivi_blk_vlc_tabs[7] + : &ivi_mb_vlc_tabs [7]; + } else { + huff_tab->tab_sel = get_bits(gb, 3); + if (huff_tab->tab_sel == 7) { + /* custom huffman table (explicitly encoded) */ + new_huff.num_rows = get_bits(gb, 4); + if (!new_huff.num_rows) { + av_log(avctx, AV_LOG_ERROR, "Empty custom Huffman table!\n"); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < new_huff.num_rows; i++) + new_huff.xbits[i] = get_bits(gb, 4); + + /* Have we got the same custom table? Rebuild if not. */ + if (ivi_huff_desc_cmp(&new_huff, &huff_tab->cust_desc) || !huff_tab->cust_tab.table) { + ivi_huff_desc_copy(&huff_tab->cust_desc, &new_huff); + + if (huff_tab->cust_tab.table) + ff_free_vlc(&huff_tab->cust_tab); + result = ivi_create_huff_from_desc(&huff_tab->cust_desc, + &huff_tab->cust_tab, 0); + if (result) { + huff_tab->cust_desc.num_rows = 0; // reset faulty description + av_log(avctx, AV_LOG_ERROR, + "Error while initializing custom vlc table!\n"); + return result; + } + } + huff_tab->tab = &huff_tab->cust_tab; + } else { + /* select one of predefined tables */ + huff_tab->tab = (which_tab) ? &ivi_blk_vlc_tabs[huff_tab->tab_sel] + : &ivi_mb_vlc_tabs [huff_tab->tab_sel]; + } + } + + return 0; +} + +/* + * Free planes, bands and macroblocks buffers. + * + * @param[in] planes pointer to the array of the plane descriptors + */ +static av_cold void ivi_free_buffers(IVIPlaneDesc *planes) +{ + int p, b, t; + + for (p = 0; p < 3; p++) { + if (planes[p].bands) + for (b = 0; b < planes[p].num_bands; b++) { + av_freep(&planes[p].bands[b].bufs[0]); + av_freep(&planes[p].bands[b].bufs[1]); + av_freep(&planes[p].bands[b].bufs[2]); + + if (planes[p].bands[b].blk_vlc.cust_tab.table) + ff_free_vlc(&planes[p].bands[b].blk_vlc.cust_tab); + for (t = 0; t < planes[p].bands[b].num_tiles; t++) + av_freep(&planes[p].bands[b].tiles[t].mbs); + av_freep(&planes[p].bands[b].tiles); + } + av_freep(&planes[p].bands); + } +} + +av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg) +{ + int p, b; + uint32_t b_width, b_height, align_fac, width_aligned, height_aligned, buf_size; + IVIBandDesc *band; + + ivi_free_buffers(planes); + + /* fill in the descriptor of the luminance plane */ + planes[0].width = cfg->pic_width; + planes[0].height = cfg->pic_height; + planes[0].num_bands = cfg->luma_bands; + + /* fill in the descriptors of the chrominance planes */ + planes[1].width = planes[2].width = (cfg->pic_width + 3) >> 2; + planes[1].height = planes[2].height = (cfg->pic_height + 3) >> 2; + planes[1].num_bands = planes[2].num_bands = cfg->chroma_bands; + + for (p = 0; p < 3; p++) { + planes[p].bands = av_mallocz(planes[p].num_bands * sizeof(IVIBandDesc)); + if (!planes[p].bands) + return AVERROR(ENOMEM); + + /* select band dimensions: if there is only one band then it + * has the full size, if there are several bands each of them + * has only half size */ + b_width = planes[p].num_bands == 1 ? planes[p].width : (planes[p].width + 1) >> 1; + b_height = planes[p].num_bands == 1 ? planes[p].height : (planes[p].height + 1) >> 1; + + /* luma band buffers will be aligned on 16x16 (max macroblock size) */ + /* chroma band buffers will be aligned on 8x8 (max macroblock size) */ + align_fac = p ? 8 : 16; + width_aligned = FFALIGN(b_width , align_fac); + height_aligned = FFALIGN(b_height, align_fac); + buf_size = width_aligned * height_aligned * sizeof(int16_t); + + for (b = 0; b < planes[p].num_bands; b++) { + band = &planes[p].bands[b]; /* select appropriate plane/band */ + band->plane = p; + band->band_num = b; + band->width = b_width; + band->height = b_height; + band->pitch = width_aligned; + band->aheight = height_aligned; + band->bufs[0] = av_mallocz(buf_size); + band->bufs[1] = av_mallocz(buf_size); + band->bufsize = buf_size/2; + if (!band->bufs[0] || !band->bufs[1]) + return AVERROR(ENOMEM); + + /* allocate the 3rd band buffer for scalability mode */ + if (cfg->luma_bands > 1) { + band->bufs[2] = av_mallocz(buf_size); + if (!band->bufs[2]) + return AVERROR(ENOMEM); + } + + planes[p].bands[0].blk_vlc.cust_desc.num_rows = 0; /* reset custom vlc */ + } + } + + return 0; +} + +av_cold int ff_ivi_init_tiles(IVIPlaneDesc *planes, int tile_width, int tile_height) +{ + int p, b, x, y, x_tiles, y_tiles, t_width, t_height; + IVIBandDesc *band; + IVITile *tile, *ref_tile; + + for (p = 0; p < 3; p++) { + t_width = !p ? tile_width : (tile_width + 3) >> 2; + t_height = !p ? tile_height : (tile_height + 3) >> 2; + + if (!p && planes[0].num_bands == 4) { + t_width >>= 1; + t_height >>= 1; + } + if(t_width<=0 || t_height<=0) + return AVERROR(EINVAL); + + for (b = 0; b < planes[p].num_bands; b++) { + band = &planes[p].bands[b]; + x_tiles = IVI_NUM_TILES(band->width, t_width); + y_tiles = IVI_NUM_TILES(band->height, t_height); + band->num_tiles = x_tiles * y_tiles; + + av_freep(&band->tiles); + band->tiles = av_mallocz(band->num_tiles * sizeof(IVITile)); + if (!band->tiles) + return AVERROR(ENOMEM); + + tile = band->tiles; + + /* use the first luma band as reference for motion vectors + * and quant */ + ref_tile = planes[0].bands[0].tiles; + + for (y = 0; y < band->height; y += t_height) { + for (x = 0; x < band->width; x += t_width) { + tile->xpos = x; + tile->ypos = y; + tile->mb_size = band->mb_size; + tile->width = FFMIN(band->width - x, t_width); + tile->height = FFMIN(band->height - y, t_height); + tile->is_empty = tile->data_size = 0; + /* calculate number of macroblocks */ + tile->num_MBs = IVI_MBs_PER_TILE(tile->width, tile->height, + band->mb_size); + + av_freep(&tile->mbs); + tile->mbs = av_malloc(tile->num_MBs * sizeof(IVIMbInfo)); + if (!tile->mbs) + return AVERROR(ENOMEM); + + tile->ref_mbs = 0; + if (p || b) { + if (tile->num_MBs <= ref_tile->num_MBs) { + tile->ref_mbs = ref_tile->mbs; + }else + av_log(NULL, AV_LOG_DEBUG, "Cannot use ref_tile, too few mbs\n"); + ref_tile++; + } + + tile++; + } + } + + }// for b + }// for p + + return 0; +} + +/* + * Decode size of the tile data. + * The size is stored as a variable-length field having the following format: + * if (tile_data_size < 255) than this field is only one byte long + * if (tile_data_size >= 255) than this field four is byte long: 0xFF X1 X2 X3 + * where X1-X3 is size of the tile data + * + * @param[in,out] gb the GetBit context + * @return size of the tile data in bytes + */ +static int ivi_dec_tile_data_size(GetBitContext *gb) +{ + int len; + + len = 0; + if (get_bits1(gb)) { + len = get_bits(gb, 8); + if (len == 255) + len = get_bits_long(gb, 24); + } + + /* align the bitstream reader on the byte boundary */ + align_get_bits(gb); + + return len; +} + +/* + * Decode block data: + * extract huffman-coded transform coefficients from the bitstream, + * dequantize them, apply inverse transform and motion compensation + * in order to reconstruct the picture. + * + * @param[in,out] gb the GetBit context + * @param[in] band pointer to the band descriptor + * @param[in] tile pointer to the tile descriptor + * @return result code: 0 - OK, -1 = error (corrupted blocks data) + */ +static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile, + AVCodecContext *avctx) +{ + int mbn, blk, num_blocks, num_coeffs, blk_size, scan_pos, run, val, + pos, is_intra, mc_type = 0, av_uninit(mv_x), av_uninit(mv_y), col_mask; + uint8_t col_flags[8]; + int32_t prev_dc, trvec[64]; + uint32_t cbp, av_uninit(sym), lo, hi, quant, buf_offs, q; + IVIMbInfo *mb; + RVMapDesc *rvmap = band->rv_map; + void (*mc_with_delta_func)(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + void (*mc_no_delta_func) (int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + const uint16_t *base_tab; + const uint8_t *scale_tab; + + prev_dc = 0; /* init intra prediction for the DC coefficient */ + + blk_size = band->blk_size; + col_mask = blk_size - 1; /* column mask for tracking non-zero coeffs */ + num_blocks = (band->mb_size != blk_size) ? 4 : 1; /* number of blocks per mb */ + num_coeffs = blk_size * blk_size; + if (blk_size == 8) { + mc_with_delta_func = ff_ivi_mc_8x8_delta; + mc_no_delta_func = ff_ivi_mc_8x8_no_delta; + } else { + mc_with_delta_func = ff_ivi_mc_4x4_delta; + mc_no_delta_func = ff_ivi_mc_4x4_no_delta; + } + + for (mbn = 0, mb = tile->mbs; mbn < tile->num_MBs; mb++, mbn++) { + is_intra = !mb->type; + cbp = mb->cbp; + buf_offs = mb->buf_offs; + + quant = av_clip(band->glob_quant + mb->q_delta, 0, 23); + + base_tab = is_intra ? band->intra_base : band->inter_base; + scale_tab = is_intra ? band->intra_scale : band->inter_scale; + if (scale_tab) + quant = scale_tab[quant]; + + if (!is_intra) { + mv_x = mb->mv_x; + mv_y = mb->mv_y; + if (band->is_halfpel) { + mc_type = ((mv_y & 1) << 1) | (mv_x & 1); + mv_x >>= 1; + mv_y >>= 1; /* convert halfpel vectors into fullpel ones */ + } + if (mb->type) { + int dmv_x, dmv_y, cx, cy; + + dmv_x = mb->mv_x >> band->is_halfpel; + dmv_y = mb->mv_y >> band->is_halfpel; + cx = mb->mv_x & band->is_halfpel; + cy = mb->mv_y & band->is_halfpel; + + if ( mb->xpos + dmv_x < 0 + || mb->xpos + dmv_x + band->mb_size + cx > band->pitch + || mb->ypos + dmv_y < 0 + || mb->ypos + dmv_y + band->mb_size + cy > band->aheight) { + return AVERROR_INVALIDDATA; + } + } + } + + for (blk = 0; blk < num_blocks; blk++) { + /* adjust block position in the buffer according to its number */ + if (blk & 1) { + buf_offs += blk_size; + } else if (blk == 2) { + buf_offs -= blk_size; + buf_offs += blk_size * band->pitch; + } + + if (cbp & 1) { /* block coded ? */ + if (!band->scan) { + av_log(avctx, AV_LOG_ERROR, "Scan pattern is not set.\n"); + return AVERROR_INVALIDDATA; + } + + scan_pos = -1; + memset(trvec, 0, num_coeffs*sizeof(trvec[0])); /* zero transform vector */ + memset(col_flags, 0, sizeof(col_flags)); /* zero column flags */ + + while (scan_pos <= num_coeffs) { + sym = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); + if (sym == rvmap->eob_sym) + break; /* End of block */ + + if (sym == rvmap->esc_sym) { /* Escape - run/val explicitly coded using 3 vlc codes */ + run = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1) + 1; + lo = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); + hi = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1); + val = IVI_TOSIGNED((hi << 6) | lo); /* merge them and convert into signed val */ + } else { + if (sym >= 256U) { + av_log(avctx, AV_LOG_ERROR, "Invalid sym encountered: %d.\n", sym); + return -1; + } + run = rvmap->runtab[sym]; + val = rvmap->valtab[sym]; + } + + /* de-zigzag and dequantize */ + scan_pos += run; + if (scan_pos >= (unsigned)num_coeffs) + break; + pos = band->scan[scan_pos]; + + if (!val) + av_dlog(avctx, "Val = 0 encountered!\n"); + + q = (base_tab[pos] * quant) >> 9; + if (q > 1) + val = val * q + FFSIGN(val) * (((q ^ 1) - 1) >> 1); + trvec[pos] = val; + col_flags[pos & col_mask] |= !!val; /* track columns containing non-zero coeffs */ + }// while + + if (scan_pos >= num_coeffs && sym != rvmap->eob_sym) + return -1; /* corrupt block data */ + + /* undoing DC coeff prediction for intra-blocks */ + if (is_intra && band->is_2d_trans) { + prev_dc += trvec[0]; + trvec[0] = prev_dc; + col_flags[0] |= !!prev_dc; + } + if(band->transform_size > band->blk_size){ + av_log(NULL, AV_LOG_ERROR, "Too large transform\n"); + return AVERROR_INVALIDDATA; + } + /* apply inverse transform */ + band->inv_transform(trvec, band->buf + buf_offs, + band->pitch, col_flags); + + /* apply motion compensation */ + if (!is_intra) + mc_with_delta_func(band->buf + buf_offs, + band->ref_buf + buf_offs + mv_y * band->pitch + mv_x, + band->pitch, mc_type); + } else { + /* block not coded */ + /* for intra blocks apply the dc slant transform */ + /* for inter - perform the motion compensation without delta */ + if (is_intra) { + band->dc_transform(&prev_dc, band->buf + buf_offs, + band->pitch, blk_size); + } else + mc_no_delta_func(band->buf + buf_offs, + band->ref_buf + buf_offs + mv_y * band->pitch + mv_x, + band->pitch, mc_type); + } + + cbp >>= 1; + }// for blk + }// for mbn + + align_get_bits(gb); + + return 0; +} + +/** + * Handle empty tiles by performing data copying and motion + * compensation respectively. + * + * @param[in] avctx ptr to the AVCodecContext + * @param[in] band pointer to the band descriptor + * @param[in] tile pointer to the tile descriptor + * @param[in] mv_scale scaling factor for motion vectors + */ +static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band, + IVITile *tile, int32_t mv_scale) +{ + int x, y, need_mc, mbn, blk, num_blocks, mv_x, mv_y, mc_type; + int offs, mb_offset, row_offset; + IVIMbInfo *mb, *ref_mb; + const int16_t *src; + int16_t *dst; + void (*mc_no_delta_func)(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, + int mc_type); + + if (tile->num_MBs != IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)) { + av_log(avctx, AV_LOG_ERROR, "Allocated tile size %d mismatches " + "parameters %d in ivi_process_empty_tile()\n", + tile->num_MBs, IVI_MBs_PER_TILE(tile->width, tile->height, band->mb_size)); + return AVERROR_INVALIDDATA; + } + + offs = tile->ypos * band->pitch + tile->xpos; + mb = tile->mbs; + ref_mb = tile->ref_mbs; + row_offset = band->mb_size * band->pitch; + need_mc = 0; /* reset the mc tracking flag */ + + for (y = tile->ypos; y < (tile->ypos + tile->height); y += band->mb_size) { + mb_offset = offs; + + for (x = tile->xpos; x < (tile->xpos + tile->width); x += band->mb_size) { + mb->xpos = x; + mb->ypos = y; + mb->buf_offs = mb_offset; + + mb->type = 1; /* set the macroblocks type = INTER */ + mb->cbp = 0; /* all blocks are empty */ + + if (!band->qdelta_present && !band->plane && !band->band_num) { + mb->q_delta = band->glob_quant; + mb->mv_x = 0; + mb->mv_y = 0; + } + + if (band->inherit_qdelta && ref_mb) + mb->q_delta = ref_mb->q_delta; + + if (band->inherit_mv && ref_mb) { + /* motion vector inheritance */ + if (mv_scale) { + mb->mv_x = ivi_scale_mv(ref_mb->mv_x, mv_scale); + mb->mv_y = ivi_scale_mv(ref_mb->mv_y, mv_scale); + } else { + mb->mv_x = ref_mb->mv_x; + mb->mv_y = ref_mb->mv_y; + } + need_mc |= mb->mv_x || mb->mv_y; /* tracking non-zero motion vectors */ + { + int dmv_x, dmv_y, cx, cy; + + dmv_x = mb->mv_x >> band->is_halfpel; + dmv_y = mb->mv_y >> band->is_halfpel; + cx = mb->mv_x & band->is_halfpel; + cy = mb->mv_y & band->is_halfpel; + + if ( mb->xpos + dmv_x < 0 + || mb->xpos + dmv_x + band->mb_size + cx > band->pitch + || mb->ypos + dmv_y < 0 + || mb->ypos + dmv_y + band->mb_size + cy > band->aheight) { + av_log(avctx, AV_LOG_ERROR, "MV out of bounds\n"); + return AVERROR_INVALIDDATA; + } + } + } + + mb++; + if (ref_mb) + ref_mb++; + mb_offset += band->mb_size; + } // for x + offs += row_offset; + } // for y + + if (band->inherit_mv && need_mc) { /* apply motion compensation if there is at least one non-zero motion vector */ + num_blocks = (band->mb_size != band->blk_size) ? 4 : 1; /* number of blocks per mb */ + mc_no_delta_func = (band->blk_size == 8) ? ff_ivi_mc_8x8_no_delta + : ff_ivi_mc_4x4_no_delta; + + for (mbn = 0, mb = tile->mbs; mbn < tile->num_MBs; mb++, mbn++) { + mv_x = mb->mv_x; + mv_y = mb->mv_y; + if (!band->is_halfpel) { + mc_type = 0; /* we have only fullpel vectors */ + } else { + mc_type = ((mv_y & 1) << 1) | (mv_x & 1); + mv_x >>= 1; + mv_y >>= 1; /* convert halfpel vectors into fullpel ones */ + } + + for (blk = 0; blk < num_blocks; blk++) { + /* adjust block position in the buffer according with its number */ + offs = mb->buf_offs + band->blk_size * ((blk & 1) + !!(blk & 2) * band->pitch); + mc_no_delta_func(band->buf + offs, + band->ref_buf + offs + mv_y * band->pitch + mv_x, + band->pitch, mc_type); + } + } + } else { + /* copy data from the reference tile into the current one */ + src = band->ref_buf + tile->ypos * band->pitch + tile->xpos; + dst = band->buf + tile->ypos * band->pitch + tile->xpos; + for (y = 0; y < tile->height; y++) { + memcpy(dst, src, tile->width*sizeof(band->buf[0])); + src += band->pitch; + dst += band->pitch; + } + } + + return 0; +} + + +#ifdef DEBUG +static uint16_t ivi_calc_band_checksum(IVIBandDesc *band) +{ + int x, y; + int16_t *src, checksum; + + src = band->buf; + checksum = 0; + + for (y = 0; y < band->height; src += band->pitch, y++) + for (x = 0; x < band->width; x++) + checksum += src[x]; + + return checksum; +} +#endif + +/* + * Convert and output the current plane. + * This conversion is done by adding back the bias value of 128 + * (subtracted in the encoder) and clipping the result. + * + * @param[in] plane pointer to the descriptor of the plane being processed + * @param[out] dst pointer to the buffer receiving converted pixels + * @param[in] dst_pitch pitch for moving to the next y line + */ +static void ivi_output_plane(IVIPlaneDesc *plane, uint8_t *dst, int dst_pitch) +{ + int x, y; + const int16_t *src = plane->bands[0].buf; + uint32_t pitch = plane->bands[0].pitch; + + if (!src) + return; + + for (y = 0; y < plane->height; y++) { + for (x = 0; x < plane->width; x++) + dst[x] = av_clip_uint8(src[x] + 128); + src += pitch; + dst += dst_pitch; + } +} + +/** + * Decode an Indeo 4 or 5 band. + * + * @param[in,out] ctx ptr to the decoder context + * @param[in,out] band ptr to the band descriptor + * @param[in] avctx ptr to the AVCodecContext + * @return result code: 0 = OK, -1 = error + */ +static int decode_band(IVI45DecContext *ctx, + IVIBandDesc *band, AVCodecContext *avctx) +{ + int result, i, t, idx1, idx2, pos; + IVITile *tile; + + band->buf = band->bufs[ctx->dst_buf]; + if (!band->buf) { + av_log(avctx, AV_LOG_ERROR, "Band buffer points to no data!\n"); + return AVERROR_INVALIDDATA; + } + band->ref_buf = band->bufs[ctx->ref_buf]; + band->data_ptr = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3); + + result = ctx->decode_band_hdr(ctx, band, avctx); + if (result) { + av_log(avctx, AV_LOG_ERROR, "Error while decoding band header: %d\n", + result); + return result; + } + + if (band->is_empty) { + av_log(avctx, AV_LOG_ERROR, "Empty band encountered!\n"); + return AVERROR_INVALIDDATA; + } + + band->rv_map = &ctx->rvmap_tabs[band->rvmap_sel]; + + /* apply corrections to the selected rvmap table if present */ + for (i = 0; i < band->num_corr; i++) { + idx1 = band->corr[i * 2]; + idx2 = band->corr[i * 2 + 1]; + FFSWAP(uint8_t, band->rv_map->runtab[idx1], band->rv_map->runtab[idx2]); + FFSWAP(int16_t, band->rv_map->valtab[idx1], band->rv_map->valtab[idx2]); + if (idx1 == band->rv_map->eob_sym || idx2 == band->rv_map->eob_sym) + band->rv_map->eob_sym ^= idx1 ^ idx2; + if (idx1 == band->rv_map->esc_sym || idx2 == band->rv_map->esc_sym) + band->rv_map->esc_sym ^= idx1 ^ idx2; + } + + pos = get_bits_count(&ctx->gb); + + for (t = 0; t < band->num_tiles; t++) { + tile = &band->tiles[t]; + + if (tile->mb_size != band->mb_size) { + av_log(avctx, AV_LOG_ERROR, "MB sizes mismatch: %d vs. %d\n", + band->mb_size, tile->mb_size); + return AVERROR_INVALIDDATA; + } + tile->is_empty = get_bits1(&ctx->gb); + if (tile->is_empty) { + result = ivi_process_empty_tile(avctx, band, tile, + (ctx->planes[0].bands[0].mb_size >> 3) - (band->mb_size >> 3)); + if (result < 0) + break; + av_dlog(avctx, "Empty tile encountered!\n"); + } else { + tile->data_size = ivi_dec_tile_data_size(&ctx->gb); + if (!tile->data_size) { + av_log(avctx, AV_LOG_ERROR, "Tile data size is zero!\n"); + result = AVERROR_INVALIDDATA; + break; + } + + result = ctx->decode_mb_info(ctx, band, tile, avctx); + if (result < 0) + break; + + result = ivi_decode_blocks(&ctx->gb, band, tile, avctx); + if (result < 0 || ((get_bits_count(&ctx->gb) - pos) >> 3) != tile->data_size) { + av_log(avctx, AV_LOG_ERROR, "Corrupted tile data encountered!\n"); + break; + } + + pos += tile->data_size << 3; // skip to next tile + } + } + + /* restore the selected rvmap table by applying its corrections in reverse order */ + for (i = band->num_corr-1; i >= 0; i--) { + idx1 = band->corr[i*2]; + idx2 = band->corr[i*2+1]; + FFSWAP(uint8_t, band->rv_map->runtab[idx1], band->rv_map->runtab[idx2]); + FFSWAP(int16_t, band->rv_map->valtab[idx1], band->rv_map->valtab[idx2]); + if (idx1 == band->rv_map->eob_sym || idx2 == band->rv_map->eob_sym) + band->rv_map->eob_sym ^= idx1 ^ idx2; + if (idx1 == band->rv_map->esc_sym || idx2 == band->rv_map->esc_sym) + band->rv_map->esc_sym ^= idx1 ^ idx2; + } + +#ifdef DEBUG + if (band->checksum_present) { + uint16_t chksum = ivi_calc_band_checksum(band); + if (chksum != band->checksum) { + av_log(avctx, AV_LOG_ERROR, + "Band checksum mismatch! Plane %d, band %d, received: %x, calculated: %x\n", + band->plane, band->band_num, band->checksum, chksum); + } + } +#endif + + align_get_bits(&ctx->gb); + + return result; +} + +int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + IVI45DecContext *ctx = avctx->priv_data; + const uint8_t *buf = avpkt->data; + AVFrame *frame = data; + int buf_size = avpkt->size; + int result, p, b; + + init_get_bits(&ctx->gb, buf, buf_size * 8); + ctx->frame_data = buf; + ctx->frame_size = buf_size; + + result = ctx->decode_pic_hdr(ctx, avctx); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Error while decoding picture header: %d\n", result); + return -1; + } + if (ctx->gop_invalid) + return AVERROR_INVALIDDATA; + + if (ctx->gop_flags & IVI5_IS_PROTECTED) { + av_log(avctx, AV_LOG_ERROR, "Password-protected clip!\n"); + return -1; + } + + ctx->switch_buffers(ctx); + + //{ START_TIMER; + + if (ctx->is_nonnull_frame(ctx)) { + ctx->buf_invalid[ctx->dst_buf] = 1; + for (p = 0; p < 3; p++) { + for (b = 0; b < ctx->planes[p].num_bands; b++) { + result = decode_band(ctx, &ctx->planes[p].bands[b], avctx); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Error while decoding band: %d, plane: %d\n", b, p); + return -1; + } + } + } + ctx->buf_invalid[ctx->dst_buf] = 0; + } + if (ctx->buf_invalid[ctx->dst_buf]) + return -1; + + //STOP_TIMER("decode_planes"); } + + /* If the bidirectional mode is enabled, next I and the following P frame will */ + /* be sent together. Unfortunately the approach below seems to be the only way */ + /* to handle the B-frames mode. That's exactly the same Intel decoders do. */ + if (avctx->codec_id == AV_CODEC_ID_INDEO4 && ctx->frame_type == 0/*FRAMETYPE_INTRA*/) { + while (get_bits(&ctx->gb, 8)); // skip version string + skip_bits_long(&ctx->gb, 64); // skip padding, TODO: implement correct 8-bytes alignment + if (get_bits_left(&ctx->gb) > 18 && show_bits(&ctx->gb, 18) == 0x3FFF8) + av_log(avctx, AV_LOG_ERROR, "Buffer contains IP frames!\n"); + } + + if (!ctx->is_nonnull_frame(ctx)) + return buf_size; + + avcodec_set_dimensions(avctx, ctx->planes[0].width, ctx->planes[0].height); + if ((result = ff_get_buffer(avctx, frame, 0)) < 0) + return result; + + if (ctx->is_scalable) { + if (avctx->codec_id == AV_CODEC_ID_INDEO4) + ff_ivi_recompose_haar(&ctx->planes[0], frame->data[0], frame->linesize[0]); + else + ff_ivi_recompose53 (&ctx->planes[0], frame->data[0], frame->linesize[0]); + } else { + ivi_output_plane(&ctx->planes[0], frame->data[0], frame->linesize[0]); + } + + ivi_output_plane(&ctx->planes[2], frame->data[1], frame->linesize[1]); + ivi_output_plane(&ctx->planes[1], frame->data[2], frame->linesize[2]); + + *got_frame = 1; + + return buf_size; +} + +/** + * Close Indeo5 decoder and clean up its context. + */ +av_cold int ff_ivi_decode_close(AVCodecContext *avctx) +{ + IVI45DecContext *ctx = avctx->priv_data; + + ivi_free_buffers(&ctx->planes[0]); + + if (ctx->mb_vlc.cust_tab.table) + ff_free_vlc(&ctx->mb_vlc.cust_tab); + +#if IVI4_STREAM_ANALYSER + if (avctx->codec_id == AV_CODEC_ID_INDEO4) { + if (ctx->is_scalable) + av_log(avctx, AV_LOG_ERROR, "This video uses scalability mode!\n"); + if (ctx->uses_tiling) + av_log(avctx, AV_LOG_ERROR, "This video uses local decoding!\n"); + if (ctx->has_b_frames) + av_log(avctx, AV_LOG_ERROR, "This video contains B-frames!\n"); + if (ctx->has_transp) + av_log(avctx, AV_LOG_ERROR, "Transparency mode is enabled!\n"); + if (ctx->uses_haar) + av_log(avctx, AV_LOG_ERROR, "This video uses Haar transform!\n"); + if (ctx->uses_fullpel) + av_log(avctx, AV_LOG_ERROR, "This video uses fullpel motion vectors!\n"); + } +#endif + + return 0; +} + + +/** + * These are 2x8 predefined Huffman codebooks for coding macroblock/block + * signals. They are specified using "huffman descriptors" in order to + * avoid huge static tables. The decoding tables will be generated at + * startup from these descriptors. + */ +const IVIHuffDesc ff_ivi_mb_huff_desc[8] = { + {8, {0, 4, 5, 4, 4, 4, 6, 6}}, + {12, {0, 2, 2, 3, 3, 3, 3, 5, 3, 2, 2, 2}}, + {12, {0, 2, 3, 4, 3, 3, 3, 3, 4, 3, 2, 2}}, + {12, {0, 3, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2}}, + {13, {0, 4, 4, 3, 3, 3, 3, 2, 3, 3, 2, 1, 1}}, + {9, {0, 4, 4, 4, 4, 3, 3, 3, 2}}, + {10, {0, 4, 4, 4, 4, 3, 3, 2, 2, 2}}, + {12, {0, 4, 4, 4, 3, 3, 2, 3, 2, 2, 2, 2}} +}; + +const IVIHuffDesc ff_ivi_blk_huff_desc[8] = { + {10, {1, 2, 3, 4, 4, 7, 5, 5, 4, 1}}, + {11, {2, 3, 4, 4, 4, 7, 5, 4, 3, 3, 2}}, + {12, {2, 4, 5, 5, 5, 5, 6, 4, 4, 3, 1, 1}}, + {13, {3, 3, 4, 4, 5, 6, 6, 4, 4, 3, 2, 1, 1}}, + {11, {3, 4, 4, 5, 5, 5, 6, 5, 4, 2, 2}}, + {13, {3, 4, 5, 5, 5, 5, 6, 4, 3, 3, 2, 1, 1}}, + {13, {3, 4, 5, 5, 5, 6, 5, 4, 3, 3, 2, 1, 1}}, + {9, {3, 4, 4, 5, 5, 5, 6, 5, 5}} +}; + + +/** + * Scan patterns shared between indeo4 and indeo5 + */ +const uint8_t ff_ivi_vertical_scan_8x8[64] = { + 0, 8, 16, 24, 32, 40, 48, 56, + 1, 9, 17, 25, 33, 41, 49, 57, + 2, 10, 18, 26, 34, 42, 50, 58, + 3, 11, 19, 27, 35, 43, 51, 59, + 4, 12, 20, 28, 36, 44, 52, 60, + 5, 13, 21, 29, 37, 45, 53, 61, + 6, 14, 22, 30, 38, 46, 54, 62, + 7, 15, 23, 31, 39, 47, 55, 63 +}; + +const uint8_t ff_ivi_horizontal_scan_8x8[64] = { + 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, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63 +}; + +const uint8_t ff_ivi_direct_scan_4x4[16] = { + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; + + +/** + * Run-value (RLE) tables. + */ +const RVMapDesc ff_ivi_rvmap_tabs[9] = { +{ /* MapTab0 */ + 5, /* eob_sym */ + 2, /* esc_sym */ + /* run table */ + {1, 1, 0, 1, 1, 0, 1, 1, 2, 2, 1, 1, 1, 1, 3, 3, + 1, 1, 2, 2, 1, 1, 4, 4, 1, 1, 1, 1, 2, 2, 5, 5, + 1, 1, 3, 3, 1, 1, 6, 6, 1, 2, 1, 2, 7, 7, 1, 1, + 8, 8, 1, 1, 4, 2, 1, 4, 2, 1, 3, 3, 1, 1, 1, 9, + 9, 1, 2, 1, 2, 1, 5, 5, 1, 1, 10, 10, 1, 1, 3, 3, + 2, 2, 1, 1, 11, 11, 6, 4, 4, 1, 6, 1, 2, 1, 2, 12, + 8, 1, 12, 7, 8, 7, 1, 16, 1, 16, 1, 3, 3, 13, 1, 13, + 2, 2, 1, 15, 1, 5, 14, 15, 1, 5, 14, 1, 17, 8, 17, 8, + 1, 4, 4, 2, 2, 1, 25, 25, 24, 24, 1, 3, 1, 3, 1, 8, + 6, 7, 6, 1, 18, 8, 18, 1, 7, 23, 2, 2, 23, 1, 1, 21, + 22, 9, 9, 22, 19, 1, 21, 5, 19, 5, 1, 33, 20, 33, 20, 8, + 4, 4, 1, 32, 2, 2, 8, 3, 32, 26, 3, 1, 7, 7, 26, 6, + 1, 6, 1, 1, 16, 1, 10, 1, 10, 2, 16, 29, 28, 2, 29, 28, + 1, 27, 5, 8, 5, 27, 1, 8, 3, 7, 3, 31, 41, 31, 1, 41, + 6, 1, 6, 7, 4, 4, 1, 1, 2, 1, 2, 11, 34, 30, 11, 1, + 30, 15, 15, 34, 36, 40, 36, 40, 35, 35, 37, 37, 39, 39, 38, 38}, + + /* value table */ + { 1, -1, 0, 2, -2, 0, 3, -3, 1, -1, 4, -4, 5, -5, 1, -1, + 6, -6, 2, -2, 7, -7, 1, -1, 8, -8, 9, -9, 3, -3, 1, -1, + 10, -10, 2, -2, 11, -11, 1, -1, 12, 4, -12, -4, 1, -1, 13, -13, + 1, -1, 14, -14, 2, 5, 15, -2, -5, -15, -3, 3, 16, -16, 17, 1, + -1, -17, 6, 18, -6, -18, 2, -2, 19, -19, 1, -1, 20, -20, 4, -4, + 7, -7, 21, -21, 1, -1, 2, 3, -3, 22, -2, -22, 8, 23, -8, 1, + 2, -23, -1, 2, -2, -2, 24, 1, -24, -1, 25, 5, -5, 1, -25, -1, + 9, -9, 26, 1, -26, 3, 1, -1, 27, -3, -1, -27, 1, 3, -1, -3, + 28, -4, 4, 10, -10, -28, 1, -1, 1, -1, 29, 6, -29, -6, 30, -4, + 3, 3, -3, -30, 1, 4, -1, 31, -3, 1, 11, -11, -1, -31, 32, -1, + -1, 2, -2, 1, 1, -32, 1, 4, -1, -4, 33, -1, 1, 1, -1, 5, + 5, -5, -33, -1, -12, 12, -5, -7, 1, 1, 7, 34, 4, -4, -1, 4, + -34, -4, 35, 36, -2, -35, -2, -36, 2, 13, 2, -1, 1, -13, 1, -1, + 37, 1, -5, 6, 5, -1, 38, -6, -8, 5, 8, -1, 1, 1, -37, -1, + 5, 39, -5, -5, 6, -6, -38, -39, -14, 40, 14, 2, 1, 1, -2, -40, + -1, -2, 2, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1} +},{ + /* MapTab1 */ + 0, /* eob_sym */ + 38, /* esc_sym */ + /* run table */ + {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 8, 6, 8, 7, + 7, 9, 9, 10, 10, 11, 11, 1, 12, 1, 12, 13, 13, 16, 14, 16, + 14, 15, 15, 17, 17, 18, 0, 18, 19, 20, 21, 19, 22, 21, 20, 22, + 25, 24, 2, 25, 24, 23, 23, 2, 26, 28, 26, 28, 29, 27, 29, 27, + 33, 33, 1, 32, 1, 3, 32, 30, 36, 3, 36, 30, 31, 31, 35, 34, + 37, 41, 34, 35, 37, 4, 41, 4, 49, 8, 8, 49, 40, 38, 5, 38, + 40, 39, 5, 39, 42, 43, 42, 7, 57, 6, 43, 44, 6, 50, 7, 44, + 57, 48, 50, 48, 45, 45, 46, 47, 51, 46, 47, 58, 1, 51, 58, 1, + 52, 59, 53, 9, 52, 55, 55, 59, 53, 56, 54, 56, 54, 9, 64, 64, + 60, 63, 60, 63, 61, 62, 61, 62, 2, 10, 2, 10, 11, 1, 11, 13, + 12, 1, 12, 13, 16, 16, 8, 8, 14, 3, 3, 15, 14, 15, 4, 4, + 1, 17, 17, 5, 1, 7, 7, 5, 6, 1, 2, 2, 6, 22, 1, 25, + 21, 22, 8, 24, 1, 21, 25, 24, 8, 18, 18, 23, 9, 20, 23, 33, + 29, 33, 20, 1, 19, 1, 29, 36, 9, 36, 19, 41, 28, 57, 32, 3, + 28, 3, 1, 27, 49, 49, 1, 32, 26, 26, 2, 4, 4, 7, 57, 41, + 2, 7, 10, 5, 37, 16, 10, 27, 8, 8, 13, 16, 37, 13, 1, 5}, + + /* value table */ + {0, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, + -1, 1, -1, 1, -1, 1, -1, 2, 1, -2, -1, 1, -1, 1, 1, -1, + -1, 1, -1, 1, -1, 1, 0, -1, 1, 1, 1, -1, 1, -1, -1, -1, + 1, 1, 2, -1, -1, 1, -1, -2, 1, 1, -1, -1, 1, 1, -1, -1, + 1, -1, 3, 1, -3, 2, -1, 1, 1, -2, -1, -1, -1, 1, 1, 1, + 1, 1, -1, -1, -1, 2, -1, -2, 1, 2, -2, -1, 1, 1, 2, -1, + -1, 1, -2, -1, 1, 1, -1, 2, 1, 2, -1, 1, -2, -1, -2, -1, + -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 4, -1, -1, -4, + 1, 1, 1, 2, -1, -1, 1, -1, -1, 1, -1, -1, 1, -2, 1, -1, + 1, 1, -1, -1, 1, 1, -1, -1, 3, 2, -3, -2, 2, 5, -2, 2, + 2, -5, -2, -2, -2, 2, -3, 3, 2, 3, -3, 2, -2, -2, 3, -3, + 6, 2, -2, 3, -6, 3, -3, -3, 3, 7, -4, 4, -3, 2, -7, 2, + 2, -2, -4, 2, 8, -2, -2, -2, 4, 2, -2, 2, 3, 2, -2, -2, + 2, 2, -2, -8, -2, 9, -2, 2, -3, -2, 2, -2, 2, 2, 2, 4, + -2, -4, 10, 2, 2, -2, -9, -2, 2, -2, 5, 4, -4, 4, -2, 2, + -5, -4, -3, 4, 2, -3, 3, -2, -5, 5, 3, 3, -2, -3, -10, -4} +},{ + /* MapTab2 */ + 2, /* eob_sym */ + 11, /* esc_sym */ + /* run table */ + {1, 1, 0, 2, 2, 1, 1, 3, 3, 4, 4, 0, 1, 1, 5, 5, + 2, 2, 6, 6, 7, 7, 1, 8, 1, 8, 3, 3, 9, 9, 1, 2, + 2, 1, 4, 10, 4, 10, 11, 11, 1, 5, 12, 12, 1, 5, 13, 13, + 3, 3, 6, 6, 2, 2, 14, 14, 16, 16, 15, 7, 15, 8, 8, 7, + 1, 1, 17, 17, 4, 4, 1, 1, 18, 18, 2, 2, 5, 5, 25, 3, + 9, 3, 25, 9, 19, 24, 19, 24, 1, 21, 20, 1, 21, 22, 20, 22, + 23, 23, 8, 6, 33, 6, 8, 33, 7, 7, 26, 26, 1, 32, 1, 32, + 28, 4, 28, 10, 29, 27, 27, 10, 41, 4, 29, 2, 2, 41, 36, 31, + 49, 31, 34, 30, 34, 36, 30, 35, 1, 49, 11, 5, 35, 11, 1, 3, + 3, 5, 37, 37, 8, 40, 8, 40, 12, 12, 42, 42, 1, 38, 16, 57, + 1, 6, 16, 39, 38, 6, 7, 7, 13, 13, 39, 43, 2, 43, 57, 2, + 50, 9, 44, 9, 50, 4, 15, 48, 44, 4, 1, 15, 48, 14, 14, 1, + 45, 45, 8, 3, 5, 8, 51, 47, 3, 46, 46, 47, 5, 51, 1, 17, + 17, 58, 1, 58, 2, 52, 52, 2, 53, 7, 59, 6, 6, 56, 53, 55, + 7, 55, 1, 54, 59, 56, 54, 10, 1, 10, 4, 60, 1, 60, 8, 4, + 8, 64, 64, 61, 1, 63, 3, 63, 62, 61, 5, 11, 5, 3, 11, 62}, + + /* value table */ + { 1, -1, 0, 1, -1, 2, -2, 1, -1, 1, -1, 0, 3, -3, 1, -1, + 2, -2, 1, -1, 1, -1, 4, 1, -4, -1, 2, -2, 1, -1, 5, 3, + -3, -5, 2, 1, -2, -1, 1, -1, 6, 2, 1, -1, -6, -2, 1, -1, + 3, -3, 2, -2, 4, -4, 1, -1, 1, -1, 1, 2, -1, 2, -2, -2, + 7, -7, 1, -1, 3, -3, 8, -8, 1, -1, 5, -5, 3, -3, 1, 4, + 2, -4, -1, -2, 1, 1, -1, -1, 9, 1, 1, -9, -1, 1, -1, -1, + 1, -1, 3, -3, 1, 3, -3, -1, 3, -3, 1, -1, 10, 1, -10, -1, + 1, 4, -1, 2, 1, -1, 1, -2, 1, -4, -1, 6, -6, -1, 1, 1, + 1, -1, 1, 1, -1, -1, -1, 1, 11, -1, -2, 4, -1, 2, -11, 5, + -5, -4, -1, 1, 4, 1, -4, -1, -2, 2, 1, -1, 12, 1, -2, 1, + -12, 4, 2, 1, -1, -4, 4, -4, 2, -2, -1, 1, 7, -1, -1, -7, + -1, -3, 1, 3, 1, 5, 2, 1, -1, -5, 13, -2, -1, 2, -2, -13, + 1, -1, 5, 6, 5, -5, 1, 1, -6, 1, -1, -1, -5, -1, 14, 2, + -2, 1, -14, -1, 8, 1, -1, -8, 1, 5, 1, 5, -5, 1, -1, 1, + -5, -1, 15, 1, -1, -1, -1, 3, -15, -3, 6, 1, 16, -1, 6, -6, + -6, 1, -1, 1, -16, 1, 7, -1, 1, -1, -6, -3, 6, -7, 3, -1} +},{ + /* MapTab3 */ + 0, /* eob_sym */ + 35, /* esc_sym */ + /* run table */ + {0, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6, 7, + 7, 8, 8, 9, 9, 2, 2, 10, 10, 1, 1, 11, 11, 12, 12, 3, + 3, 13, 13, 0, 14, 14, 16, 15, 16, 15, 4, 4, 17, 1, 17, 1, + 5, 5, 18, 18, 2, 2, 6, 6, 8, 19, 7, 8, 7, 19, 20, 20, + 21, 21, 22, 24, 22, 24, 23, 23, 1, 1, 25, 25, 3, 3, 26, 26, + 9, 9, 27, 27, 28, 28, 33, 29, 4, 33, 29, 1, 4, 1, 32, 32, + 2, 2, 31, 10, 30, 10, 30, 31, 34, 34, 5, 5, 36, 36, 35, 41, + 35, 11, 41, 11, 37, 1, 8, 8, 37, 6, 1, 6, 40, 7, 7, 40, + 12, 38, 12, 39, 39, 38, 49, 13, 49, 13, 3, 42, 3, 42, 16, 16, + 43, 43, 14, 14, 1, 1, 44, 15, 44, 15, 2, 2, 57, 48, 50, 48, + 57, 50, 4, 45, 45, 4, 46, 47, 47, 46, 1, 51, 1, 17, 17, 51, + 8, 9, 9, 5, 58, 8, 58, 5, 52, 52, 55, 56, 53, 56, 55, 59, + 59, 53, 54, 1, 6, 54, 7, 7, 6, 1, 2, 3, 2, 3, 64, 60, + 60, 10, 10, 64, 61, 62, 61, 63, 1, 63, 62, 1, 18, 24, 18, 4, + 25, 4, 8, 21, 21, 1, 24, 22, 25, 22, 8, 11, 19, 11, 23, 1, + 20, 23, 19, 20, 5, 12, 5, 1, 16, 2, 12, 13, 2, 13, 1, 16}, + + /* value table */ + { 0, 1, -1, 1, -1, 1, -1, 1, -1, 2, -2, 1, -1, 1, -1, 1, + -1, 1, -1, 1, -1, 2, -2, 1, -1, 3, -3, 1, -1, 1, -1, 2, + -2, 1, -1, 0, 1, -1, 1, 1, -1, -1, 2, -2, 1, 4, -1, -4, + 2, -2, 1, -1, -3, 3, 2, -2, 2, 1, 2, -2, -2, -1, 1, -1, + 1, -1, 1, 1, -1, -1, 1, -1, 5, -5, 1, -1, 3, -3, 1, -1, + 2, -2, 1, -1, 1, -1, 1, 1, 3, -1, -1, 6, -3, -6, -1, 1, + 4, -4, 1, 2, 1, -2, -1, -1, 1, -1, 3, -3, 1, -1, 1, 1, + -1, 2, -1, -2, 1, 7, -3, 3, -1, 3, -7, -3, 1, -3, 3, -1, + 2, 1, -2, 1, -1, -1, 1, 2, -1, -2, -4, -1, 4, 1, 2, -2, + 1, -1, -2, 2, 8, -8, -1, 2, 1, -2, -5, 5, 1, -1, -1, 1, + -1, 1, 4, -1, 1, -4, -1, -1, 1, 1, 9, 1, -9, 2, -2, -1, + -4, 3, -3, -4, -1, 4, 1, 4, 1, -1, 1, -1, 1, 1, -1, 1, + -1, -1, -1, 10, 4, 1, 4, -4, -4, -10, 6, 5, -6, -5, 1, -1, + 1, 3, -3, -1, 1, -1, -1, -1, 11, 1, 1, -11, -2, -2, 2, 5, + -2, -5, -5, 2, -2, 12, 2, -2, 2, 2, 5, -3, -2, 3, -2, -12, + -2, 2, 2, 2, -5, 3, 5, 13, -3, 7, -3, -3, -7, 3, -13, 3} +},{ + /* MapTab4 */ + 0, /* eob_sym */ + 34, /* esc_sym */ + /* run table */ + {0, 1, 1, 1, 2, 2, 1, 3, 3, 1, 1, 1, 4, 4, 1, 5, + 2, 1, 5, 2, 1, 1, 6, 6, 1, 1, 1, 1, 1, 7, 3, 1, + 2, 3, 0, 1, 2, 7, 1, 1, 1, 8, 1, 1, 8, 1, 1, 1, + 9, 1, 9, 1, 2, 1, 1, 2, 1, 1, 10, 4, 1, 10, 1, 4, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 3, 2, 1, 5, 1, 1, 1, + 2, 5, 1, 11, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 1, 6, 1, 6, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 12, + 3, 1, 12, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 5, + 1, 1, 1, 1, 1, 7, 1, 7, 1, 1, 2, 3, 1, 1, 1, 1, + 5, 1, 1, 1, 1, 1, 1, 2, 13, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 13, 2, 1, 1, 4, 1, 1, 1, + 3, 1, 6, 1, 1, 1, 14, 1, 1, 1, 1, 1, 14, 6, 1, 1, + 1, 1, 15, 2, 4, 1, 2, 3, 15, 1, 1, 1, 8, 1, 1, 8, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1}, + + /* value table */ + { 0, 1, -1, 2, 1, -1, -2, 1, -1, 3, -3, 4, 1, -1, -4, 1, + 2, 5, -1, -2, -5, 6, 1, -1, -6, 7, -7, 8, -8, 1, 2, 9, + 3, -2, 0, -9, -3, -1, 10, -10, 11, 1, -11, 12, -1, -12, 13, -13, + 1, 14, -1, -14, 4, 15, -15, -4, 16, -16, 1, 2, 17, -1, -17, -2, + 18, -18, 19, -19, 20, 3, -20, 21, -21, -3, 5, 22, 2, -22, -23, 23, + -5, -2, 24, 1, -24, -1, 25, -25, 26, -26, -27, 27, 28, 29, -28, -29, + 6, 30, 2, -31, -2, -30, 31, -6, -32, 32, 33, -33, 34, -35, -34, 1, + 4, -36, -1, 35, 37, 36, 7, -37, 38, -4, -38, 39, 41, 40, -40, -39, + 3, 42, -43, -41, -7, -42, 43, -3, 44, -44, 45, -45, 46, 47, 8, -47, + -48, -46, 50, -50, 48, 49, 51, -49, 52, -52, 5, -51, -8, -53, 53, 3, + -56, 56, 55, 54, -54, 2, 60, -2, -55, 58, 9, -5, 59, 57, -57, -63, + -3, -58, -60, -61, 61, -59, -62, -9, 1, 64, 62, 69, -64, 63, 65, -67, + -68, 66, -65, 68, -66, -69, 67, -70, -1, 10, 71, -71, 4, 73, 72, 70, + 6, -76, -3, 74, -78, -74, 1, 78, 80, -72, -75, 76, -1, 3, -73, 79, + 75, 77, 1, 11, -4, -79, -10, -6, -1, -77, -83, -80, 2, 81, -84, -2, + 83, -81, 82, -82, 84, -87, -86, 85, -11, -85, 86, -89, 87, -88, 88, 89} +},{ + /* MapTab5 */ + 2, /* eob_sym */ + 33, /* esc_sym */ + /* run table */ + {1, 1, 0, 2, 1, 2, 1, 3, 3, 1, 1, 4, 4, 2, 2, 1, + 1, 5, 5, 6, 1, 6, 1, 7, 7, 3, 3, 2, 8, 2, 8, 1, + 1, 0, 9, 9, 1, 1, 10, 4, 10, 4, 11, 11, 2, 1, 2, 1, + 12, 12, 3, 3, 1, 1, 13, 5, 5, 13, 14, 1, 1, 14, 2, 2, + 6, 6, 15, 1, 1, 15, 16, 4, 7, 16, 4, 7, 1, 1, 3, 3, + 8, 8, 2, 2, 1, 1, 17, 17, 1, 1, 18, 18, 5, 5, 2, 2, + 1, 1, 9, 19, 9, 19, 20, 3, 3, 20, 1, 10, 21, 1, 10, 4, + 4, 21, 22, 6, 6, 22, 1, 1, 23, 24, 2, 2, 23, 24, 11, 1, + 1, 11, 7, 25, 7, 1, 1, 25, 8, 8, 3, 26, 3, 1, 12, 2, + 2, 26, 1, 12, 5, 5, 27, 4, 1, 4, 1, 27, 28, 1, 28, 13, + 1, 13, 2, 29, 2, 1, 32, 6, 1, 30, 14, 29, 14, 6, 3, 31, + 3, 1, 30, 1, 32, 31, 33, 9, 33, 1, 1, 7, 9, 7, 2, 2, + 1, 1, 4, 36, 34, 4, 5, 10, 10, 5, 34, 1, 1, 35, 8, 8, + 36, 3, 35, 1, 15, 3, 2, 1, 16, 15, 16, 2, 37, 1, 37, 1, + 1, 1, 6, 6, 38, 1, 38, 11, 1, 39, 39, 40, 11, 2, 41, 4, + 40, 1, 2, 4, 1, 1, 1, 41, 3, 1, 3, 1, 5, 7, 5, 7}, + + /* value table */ + { 1, -1, 0, 1, 2, -1, -2, 1, -1, 3, -3, 1, -1, 2, -2, 4, + -4, 1, -1, 1, 5, -1, -5, 1, -1, 2, -2, 3, 1, -3, -1, 6, + -6, 0, 1, -1, 7, -7, 1, 2, -1, -2, 1, -1, 4, 8, -4, -8, + 1, -1, 3, -3, 9, -9, 1, 2, -2, -1, 1, 10, -10, -1, 5, -5, + 2, -2, 1, 11, -11, -1, 1, 3, 2, -1, -3, -2, 12, -12, 4, -4, + 2, -2, -6, 6, 13, -13, 1, -1, 14, -14, 1, -1, 3, -3, 7, -7, + 15, -15, 2, 1, -2, -1, 1, 5, -5, -1, -16, 2, 1, 16, -2, 4, + -4, -1, 1, 3, -3, -1, 17, -17, 1, 1, -8, 8, -1, -1, 2, 18, + -18, -2, 3, 1, -3, 19, -19, -1, 3, -3, 6, 1, -6, 20, 2, 9, + -9, -1, -20, -2, 4, -4, 1, -5, 21, 5, -21, -1, 1, -22, -1, 2, + 22, -2, 10, 1, -10, 23, 1, 4, -23, 1, 2, -1, -2, -4, -7, 1, + 7, -24, -1, 24, -1, -1, 1, 3, -1, -25, 25, 4, -3, -4, 11, -11, + 26, -26, 6, 1, 1, -6, -5, -3, 3, 5, -1, -27, 27, 1, 4, -4, + -1, -8, -1, 28, 2, 8, -12, -28, -2, -2, 2, 12, -1, 29, 1, -29, + 30, -30, 5, -5, 1, -31, -1, 3, 31, -1, 1, 1, -3, -13, 1, -7, + -1, -32, 13, 7, 32, 33, -33, -1, -9, -34, 9, 34, -6, 5, 6, -5} +},{ + /* MapTab6 */ + 2, /* eob_sym */ + 13, /* esc_sym */ + /* run table */ + {1, 1, 0, 1, 1, 2, 2, 1, 1, 3, 3, 1, 1, 0, 2, 2, + 4, 1, 4, 1, 1, 1, 5, 5, 1, 1, 6, 6, 2, 2, 1, 1, + 3, 3, 7, 7, 1, 1, 8, 8, 1, 1, 2, 2, 1, 9, 1, 9, + 4, 4, 10, 1, 1, 10, 1, 1, 11, 11, 3, 3, 1, 2, 1, 2, + 1, 1, 12, 12, 5, 5, 1, 1, 13, 1, 1, 13, 2, 2, 1, 1, + 6, 6, 1, 1, 4, 14, 4, 14, 3, 1, 3, 1, 1, 1, 15, 7, + 15, 2, 2, 7, 1, 1, 1, 8, 1, 8, 16, 16, 1, 1, 1, 1, + 2, 1, 1, 2, 1, 1, 3, 5, 5, 3, 4, 1, 1, 4, 1, 1, + 17, 17, 9, 1, 1, 9, 2, 2, 1, 1, 10, 10, 1, 6, 1, 1, + 6, 18, 1, 1, 18, 1, 1, 1, 2, 2, 3, 1, 3, 1, 1, 1, + 4, 1, 19, 1, 19, 7, 1, 1, 20, 1, 4, 20, 1, 7, 11, 2, + 1, 11, 21, 2, 8, 5, 1, 8, 1, 5, 21, 1, 1, 1, 22, 1, + 1, 22, 1, 1, 3, 3, 1, 23, 2, 12, 24, 1, 1, 2, 1, 1, + 12, 23, 1, 1, 24, 1, 1, 1, 4, 1, 1, 1, 2, 1, 6, 6, + 4, 2, 1, 1, 1, 1, 1, 1, 1, 14, 13, 3, 1, 25, 9, 25, + 14, 1, 9, 3, 13, 1, 1, 1, 1, 1, 10, 1, 1, 2, 10, 2}, + + /* value table */ + {-20, -1, 0, 2, -2, 1, -1, 3, -3, 1, -1, 4, -4, 0, 2, -2, + 1, 5, -1, -5, 6, -6, 1, -1, 7, -7, 1, -1, 3, -3, 8, -8, + 2, -2, 1, -1, 9, -9, 1, -1, 10, -10, 4, -4, 11, 1, -11, -1, + 2, -2, 1, 12, -12, -1, 13, -13, 1, -1, 3, -3, 14, 5, -14, -5, + -15, 15, -1, 1, 2, -2, 16, -16, 1, 17, -17, -1, 6, -6, 18, -18, + 2, -2, -19, 19, -3, 1, 3, -1, 4, 20, -4, 1, -21, 21, 1, 2, + -1, -7, 7, -2, 22, -22, 23, 2, -23, -2, 1, -1, -24, 24, -25, 25, + -8, -26, 26, 8, -27, 27, 5, 3, -3, -5, -4, 28, -28, 4, 29, -29, + 1, -1, -2, -30, 30, 2, 9, -9, -31, 31, 2, -2, -32, 3, 32, -33, + -3, 1, 33, -34, -1, 34, -35, 35, -10, 10, -6, 36, 6, -36, 37, -37, + -5, 38, 1, -38, -1, 3, 39, -39, -1, 40, 5, 1, -40, -3, 2, -11, + -41, -2, 1, 11, -3, -4, 41, 3, 42, 4, -1, -43, -42, 43, 1, -44, + 45, -1, 44, -45, -7, 7, -46, 1, -12, 2, 1, -47, 46, 12, 47, 48, + -2, -1, -48, 49, -1, -50, -49, 50, -6, -51, 51, 52, -13, 53, -4, 4, + 6, 13, -53, -52, -54, 55, 54, -55, -56, -2, 2, -8, 56, 1, -3, -1, + 2, 58, 3, 8, -2, 57, -58, -60, -59, -57, -3, 60, 59, -14, 3, 14} +},{ + /* MapTab7 */ + 2, /* eob_sym */ + 38, /* esc_sym */ + /* run table */ + {1, 1, 0, 2, 2, 1, 1, 3, 3, 4, 4, 5, 5, 1, 1, 6, + 6, 2, 2, 7, 7, 8, 8, 1, 1, 3, 3, 9, 9, 10, 10, 1, + 1, 2, 2, 4, 4, 11, 0, 11, 12, 12, 13, 13, 1, 1, 5, 5, + 14, 14, 15, 16, 15, 16, 3, 3, 1, 6, 1, 6, 2, 2, 7, 7, + 8, 8, 17, 17, 1, 1, 4, 4, 18, 18, 2, 2, 1, 19, 1, 20, + 19, 20, 21, 21, 3, 3, 22, 22, 5, 5, 24, 1, 1, 23, 9, 23, + 24, 9, 2, 2, 10, 1, 1, 10, 6, 6, 25, 4, 4, 25, 7, 7, + 26, 8, 1, 8, 3, 1, 26, 3, 11, 11, 27, 27, 2, 28, 1, 2, + 28, 1, 12, 12, 5, 5, 29, 13, 13, 29, 32, 1, 1, 33, 31, 30, + 32, 4, 30, 33, 4, 31, 3, 14, 1, 1, 3, 34, 34, 2, 2, 14, + 6, 6, 35, 36, 35, 36, 1, 15, 1, 16, 16, 15, 7, 9, 7, 9, + 37, 8, 8, 37, 1, 1, 39, 2, 38, 39, 2, 40, 5, 38, 40, 5, + 3, 3, 4, 4, 10, 10, 1, 1, 1, 1, 41, 2, 41, 2, 6, 6, + 1, 1, 11, 42, 11, 43, 3, 42, 3, 17, 4, 43, 1, 17, 7, 1, + 8, 44, 4, 7, 44, 5, 8, 2, 5, 1, 2, 48, 45, 1, 12, 45, + 12, 48, 13, 13, 1, 9, 9, 46, 1, 46, 47, 47, 49, 18, 18, 49}, + + /* value table */ + { 1, -1, 0, 1, -1, 2, -2, 1, -1, 1, -1, 1, -1, 3, -3, 1, + -1, -2, 2, 1, -1, 1, -1, 4, -4, -2, 2, 1, -1, 1, -1, 5, + -5, -3, 3, 2, -2, 1, 0, -1, 1, -1, 1, -1, 6, -6, 2, -2, + 1, -1, 1, 1, -1, -1, -3, 3, 7, 2, -7, -2, -4, 4, 2, -2, + 2, -2, 1, -1, 8, -8, 3, -3, 1, -1, -5, 5, 9, 1, -9, 1, + -1, -1, 1, -1, -4, 4, 1, -1, 3, -3, 1, -10, 10, 1, 2, -1, + -1, -2, 6, -6, 2, 11, -11, -2, 3, -3, 1, -4, 4, -1, 3, -3, + 1, 3, 12, -3, -5, -12, -1, 5, 2, -2, 1, -1, -7, 1, 13, 7, + -1, -13, 2, -2, 4, -4, 1, 2, -2, -1, 1, 14, -14, 1, 1, 1, + -1, -5, -1, -1, 5, -1, -6, 2, -15, 15, 6, 1, -1, -8, 8, -2, + -4, 4, 1, 1, -1, -1, 16, 2, -16, -2, 2, -2, 4, 3, -4, -3, + -1, -4, 4, 1, -17, 17, -1, -9, 1, 1, 9, 1, -5, -1, -1, 5, + -7, 7, 6, -6, 3, -3, 18, -18, 19, -19, 1, -10, -1, 10, -5, 5, + 20, -20, -3, 1, 3, 1, 8, -1, -8, 2, 7, -1, -21, -2, 5, 21, + 5, -1, -7, -5, 1, -6, -5, -11, 6, 22, 11, 1, 1, -22, -3, -1, + 3, -1, 3, -3, -23, 4, -4, 1, 23, -1, 1, -1, 1, -2, 2, -1} +},{ + /* MapTab8 */ + 4, /* eob_sym */ + 11, /* esc_sym */ + /* run table */ + {1, 1, 1, 1, 0, 2, 2, 1, 1, 3, 3, 0, 1, 1, 2, 2, + 4, 4, 1, 1, 5, 5, 1, 1, 2, 2, 3, 3, 6, 6, 1, 1, + 7, 7, 8, 1, 8, 2, 2, 1, 4, 4, 1, 3, 1, 3, 9, 9, + 2, 2, 1, 5, 1, 5, 10, 10, 1, 1, 11, 11, 3, 6, 3, 4, + 4, 6, 2, 2, 1, 12, 1, 12, 7, 13, 7, 13, 1, 1, 8, 8, + 2, 2, 14, 14, 16, 15, 16, 5, 5, 1, 3, 15, 1, 3, 4, 4, + 1, 1, 17, 17, 2, 2, 6, 6, 1, 18, 1, 18, 22, 21, 22, 21, + 25, 24, 25, 19, 9, 20, 9, 23, 19, 24, 20, 3, 23, 7, 3, 1, + 1, 7, 28, 26, 29, 5, 28, 26, 5, 8, 29, 4, 8, 27, 2, 2, + 4, 27, 1, 1, 10, 36, 10, 33, 33, 36, 30, 1, 32, 32, 1, 30, + 6, 31, 31, 35, 3, 6, 11, 11, 3, 2, 35, 2, 34, 1, 34, 1, + 37, 37, 12, 7, 12, 5, 41, 5, 4, 7, 1, 8, 13, 4, 1, 41, + 13, 38, 8, 38, 9, 1, 40, 40, 9, 1, 39, 2, 2, 49, 39, 42, + 3, 3, 14, 16, 49, 14, 16, 42, 43, 43, 6, 6, 15, 1, 1, 15, + 44, 44, 1, 1, 50, 48, 4, 5, 4, 7, 5, 2, 10, 10, 48, 7, + 50, 45, 2, 1, 45, 8, 8, 1, 46, 46, 3, 47, 47, 3, 1, 1}, + + /* value table */ + { 1, -1, 2, -2, 0, 1, -1, 3, -3, 1, -1, 0, 4, -4, 2, -2, + 1, -1, 5, -5, 1, -1, 6, -6, 3, -3, 2, -2, 1, -1, 7, -7, + 1, -1, 1, 8, -1, 4, -4, -8, 2, -2, 9, 3, -9, -3, 1, -1, + 5, -5, 10, 2, -10, -2, 1, -1, 11, -11, 1, -1, -4, 2, 4, 3, + -3, -2, 6, -6, 12, 1, -12, -1, 2, 1, -2, -1, 13, -13, 2, -2, + 7, -7, 1, -1, 1, 1, -1, 3, -3, 14, 5, -1, -14, -5, 4, -4, + 15, -15, 1, -1, 8, -8, -3, 3, 16, 1, -16, -1, 1, 1, -1, -1, + 1, 1, -1, 1, 2, 1, -2, 1, -1, -1, -1, 6, -1, 3, -6, 17, + -17, -3, 1, 1, 1, 4, -1, -1, -4, 3, -1, 5, -3, -1, -9, 9, + -5, 1, 18, -18, 2, 1, -2, 1, -1, -1, 1, 19, -1, 1, -19, -1, + 4, 1, -1, 1, 7, -4, -2, 2, -7, 10, -1, -10, 1, 20, -1, -20, + 1, -1, 2, 4, -2, 5, 1, -5, 6, -4, 21, 4, 2, -6, -21, -1, + -2, 1, -4, -1, -3, 22, -1, 1, 3, -22, -1, 11, -11, 1, 1, 1, + 8, -8, 2, 2, -1, -2, -2, -1, 1, -1, -5, 5, 2, 23, -23, -2, + 1, -1, 24, -24, -1, -1, 7, 6, -7, 5, -6, 12, -3, 3, 1, -5, + 1, 1, -12, 25, -1, -5, 5, -25, -1, 1, 9, 1, -1, -9, 26, -26} +} +}; diff --git a/ffmpeg/libavcodec/ivi_common.h b/ffmpeg/libavcodec/ivi_common.h new file mode 100644 index 0000000..130fd12 --- /dev/null +++ b/ffmpeg/libavcodec/ivi_common.h @@ -0,0 +1,321 @@ +/* + * common functions for Indeo Video Interactive codecs (Indeo4 and Indeo5) + * + * Copyright (c) 2009 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * This file contains structures and macros shared by both Indeo4 and + * Indeo5 decoders. + */ + +#ifndef AVCODEC_IVI_COMMON_H +#define AVCODEC_IVI_COMMON_H + +#include "avcodec.h" +#include "get_bits.h" +#include + +#define IVI_VLC_BITS 13 ///< max number of bits of the ivi's huffman codes +#define IVI4_STREAM_ANALYSER 0 +#define IVI5_IS_PROTECTED 0x20 + +/** + * huffman codebook descriptor + */ +typedef struct IVIHuffDesc { + int32_t num_rows; + uint8_t xbits[16]; +} IVIHuffDesc; + +/** + * macroblock/block huffman table descriptor + */ +typedef struct IVIHuffTab { + int32_t tab_sel; /// index of one of the predefined tables + /// or "7" for custom one + VLC *tab; /// pointer to the table associated with tab_sel + + /// the following are used only when tab_sel == 7 + IVIHuffDesc cust_desc; /// custom Huffman codebook descriptor + VLC cust_tab; /// vlc table for custom codebook +} IVIHuffTab; + +enum { + IVI_MB_HUFF = 0, /// Huffman table is used for coding macroblocks + IVI_BLK_HUFF = 1 /// Huffman table is used for coding blocks +}; + + +/** + * Common scan patterns (defined in ivi_common.c) + */ +extern const uint8_t ff_ivi_vertical_scan_8x8[64]; +extern const uint8_t ff_ivi_horizontal_scan_8x8[64]; +extern const uint8_t ff_ivi_direct_scan_4x4[16]; + + +/** + * Declare inverse transform function types + */ +typedef void (InvTransformPtr)(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags); +typedef void (DCTransformPtr) (const int32_t *in, int16_t *out, uint32_t pitch, int blk_size); + + +/** + * run-value (RLE) table descriptor + */ +typedef struct RVMapDesc { + uint8_t eob_sym; ///< end of block symbol + uint8_t esc_sym; ///< escape symbol + uint8_t runtab[256]; + int8_t valtab[256]; +} RVMapDesc; + +extern const RVMapDesc ff_ivi_rvmap_tabs[9]; + + +/** + * information for Indeo macroblock (16x16, 8x8 or 4x4) + */ +typedef struct IVIMbInfo { + int16_t xpos; + int16_t ypos; + uint32_t buf_offs; ///< address in the output buffer for this mb + uint8_t type; ///< macroblock type: 0 - INTRA, 1 - INTER + uint8_t cbp; ///< coded block pattern + int8_t q_delta; ///< quant delta + int8_t mv_x; ///< motion vector (x component) + int8_t mv_y; ///< motion vector (y component) +} IVIMbInfo; + + +/** + * information for Indeo tile + */ +typedef struct IVITile { + int xpos; + int ypos; + int width; + int height; + int mb_size; + int is_empty; ///< = 1 if this tile doesn't contain any data + int data_size; ///< size of the data in bytes + int num_MBs; ///< number of macroblocks in this tile + IVIMbInfo *mbs; ///< array of macroblock descriptors + IVIMbInfo *ref_mbs; ///< ptr to the macroblock descriptors of the reference tile +} IVITile; + + +/** + * information for Indeo wavelet band + */ +typedef struct IVIBandDesc { + int plane; ///< plane number this band belongs to + int band_num; ///< band number + int width; + int height; + int aheight; ///< aligned band height + const uint8_t *data_ptr; ///< ptr to the first byte of the band data + int data_size; ///< size of the band data + int16_t *buf; ///< pointer to the output buffer for this band + int16_t *ref_buf; ///< pointer to the reference frame buffer (for motion compensation) + int16_t *bufs[3]; ///< array of pointers to the band buffers + int pitch; ///< pitch associated with the buffers above + int is_empty; ///< = 1 if this band doesn't contain any data + int mb_size; ///< macroblock size + int blk_size; ///< block size + int is_halfpel; ///< precision of the motion compensation: 0 - fullpel, 1 - halfpel + int inherit_mv; ///< tells if motion vector is inherited from reference macroblock + int inherit_qdelta; ///< tells if quantiser delta is inherited from reference macroblock + int qdelta_present; ///< tells if Qdelta signal is present in the bitstream (Indeo5 only) + int quant_mat; ///< dequant matrix index + int glob_quant; ///< quant base for this band + const uint8_t *scan; ///< ptr to the scan pattern + int scan_size; ///< size of the scantable + + IVIHuffTab blk_vlc; ///< vlc table for decoding block data + + int num_corr; ///< number of correction entries + uint8_t corr[61*2]; ///< rvmap correction pairs + int rvmap_sel; ///< rvmap table selector + RVMapDesc *rv_map; ///< ptr to the RLE table for this band + int num_tiles; ///< number of tiles in this band + IVITile *tiles; ///< array of tile descriptors + InvTransformPtr *inv_transform; + DCTransformPtr *dc_transform; + int is_2d_trans; ///< 1 indicates that the two-dimensional inverse transform is used + int transform_size; ///< block size of the transform + int32_t checksum; ///< for debug purposes + int checksum_present; + int bufsize; ///< band buffer size in bytes + const uint16_t *intra_base; ///< quantization matrix for intra blocks + const uint16_t *inter_base; ///< quantization matrix for inter blocks + const uint8_t *intra_scale; ///< quantization coefficient for intra blocks + const uint8_t *inter_scale; ///< quantization coefficient for inter blocks +} IVIBandDesc; + + +/** + * color plane (luma or chroma) information + */ +typedef struct IVIPlaneDesc { + uint16_t width; + uint16_t height; + uint8_t num_bands; ///< number of bands this plane subdivided into + IVIBandDesc *bands; ///< array of band descriptors +} IVIPlaneDesc; + + +typedef struct IVIPicConfig { + uint16_t pic_width; + uint16_t pic_height; + uint16_t chroma_width; + uint16_t chroma_height; + uint16_t tile_width; + uint16_t tile_height; + uint8_t luma_bands; + uint8_t chroma_bands; +} IVIPicConfig; + +typedef struct IVI45DecContext { + GetBitContext gb; + RVMapDesc rvmap_tabs[9]; ///< local corrected copy of the static rvmap tables + + uint32_t frame_num; + int frame_type; + int prev_frame_type; ///< frame type of the previous frame + uint32_t data_size; ///< size of the frame data in bytes from picture header + int is_scalable; + int transp_status; ///< transparency mode status: 1 - enabled + const uint8_t *frame_data; ///< input frame data pointer + int inter_scal; ///< signals a sequence of scalable inter frames + uint32_t frame_size; ///< frame size in bytes + uint32_t pic_hdr_size; ///< picture header size in bytes + uint8_t frame_flags; + uint16_t checksum; ///< frame checksum + + IVIPicConfig pic_conf; + IVIPlaneDesc planes[3]; ///< color planes + + int buf_switch; ///< used to switch between three buffers + int dst_buf; ///< buffer index for the currently decoded frame + int ref_buf; ///< inter frame reference buffer index + int ref2_buf; ///< temporal storage for switching buffers + + IVIHuffTab mb_vlc; ///< current macroblock table descriptor + IVIHuffTab blk_vlc; ///< current block table descriptor + + uint8_t rvmap_sel; + uint8_t in_imf; + uint8_t in_q; ///< flag for explicitly stored quantiser delta + uint8_t pic_glob_quant; + uint8_t unknown1; + + uint16_t gop_hdr_size; + uint8_t gop_flags; + uint32_t lock_word; + +#if IVI4_STREAM_ANALYSER + uint8_t has_b_frames; + uint8_t has_transp; + uint8_t uses_tiling; + uint8_t uses_haar; + uint8_t uses_fullpel; +#endif + + int (*decode_pic_hdr) (struct IVI45DecContext *ctx, AVCodecContext *avctx); + int (*decode_band_hdr) (struct IVI45DecContext *ctx, IVIBandDesc *band, AVCodecContext *avctx); + int (*decode_mb_info) (struct IVI45DecContext *ctx, IVIBandDesc *band, IVITile *tile, AVCodecContext *avctx); + void (*switch_buffers) (struct IVI45DecContext *ctx); + int (*is_nonnull_frame)(struct IVI45DecContext *ctx); + + int gop_invalid; + int buf_invalid[3]; +} IVI45DecContext; + +/** compare some properties of two pictures */ +static inline int ivi_pic_config_cmp(IVIPicConfig *str1, IVIPicConfig *str2) +{ + return str1->pic_width != str2->pic_width || str1->pic_height != str2->pic_height || + str1->chroma_width != str2->chroma_width || str1->chroma_height != str2->chroma_height || + str1->tile_width != str2->tile_width || str1->tile_height != str2->tile_height || + str1->luma_bands != str2->luma_bands || str1->chroma_bands != str2->chroma_bands; +} + +/** calculate number of tiles in a stride */ +#define IVI_NUM_TILES(stride, tile_size) (((stride) + (tile_size) - 1) / (tile_size)) + +/** calculate number of macroblocks in a tile */ +#define IVI_MBs_PER_TILE(tile_width, tile_height, mb_size) \ + ((((tile_width) + (mb_size) - 1) / (mb_size)) * (((tile_height) + (mb_size) - 1) / (mb_size))) + +/** convert unsigned values into signed ones (the sign is in the LSB) */ +#define IVI_TOSIGNED(val) (-(((val) >> 1) ^ -((val) & 1))) + +/** scale motion vector */ +static inline int ivi_scale_mv(int mv, int mv_scale) +{ + return (mv + (mv > 0) + (mv_scale - 1)) >> mv_scale; +} + +/** + * Initialize static codes used for macroblock and block decoding. + */ +void ff_ivi_init_static_vlc(void); + +/** + * Decode a huffman codebook descriptor from the bitstream + * and select specified huffman table. + * + * @param[in,out] gb the GetBit context + * @param[in] desc_coded flag signalling if table descriptor was coded + * @param[in] which_tab codebook purpose (IVI_MB_HUFF or IVI_BLK_HUFF) + * @param[out] huff_tab pointer to the descriptor of the selected table + * @param[in] avctx AVCodecContext pointer + * @return zero on success, negative value otherwise + */ +int ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab, + IVIHuffTab *huff_tab, AVCodecContext *avctx); + +/** + * Initialize planes (prepares descriptors, allocates buffers etc). + * + * @param[in,out] planes pointer to the array of the plane descriptors + * @param[in] cfg pointer to the ivi_pic_config structure describing picture layout + * @return result code: 0 - OK + */ +int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg); + +/** + * Initialize tile and macroblock descriptors. + * + * @param[in,out] planes pointer to the array of the plane descriptors + * @param[in] tile_width tile width + * @param[in] tile_height tile height + * @return result code: 0 - OK + */ +int ff_ivi_init_tiles(IVIPlaneDesc *planes, int tile_width, int tile_height); + +int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt); +int ff_ivi_decode_close(AVCodecContext *avctx); + +#endif /* AVCODEC_IVI_COMMON_H */ diff --git a/ffmpeg/libavcodec/ivi_dsp.c b/ffmpeg/libavcodec/ivi_dsp.c new file mode 100644 index 0000000..84e2436 --- /dev/null +++ b/ffmpeg/libavcodec/ivi_dsp.c @@ -0,0 +1,623 @@ +/* + * DSP functions for Indeo Video Interactive codecs (Indeo4 and Indeo5) + * + * Copyright (c) 2009-2011 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * DSP functions (inverse transforms, motion compensation, wavelet recompostions) + * for Indeo Video Interactive codecs. + */ + +#include "avcodec.h" +#include "ivi_common.h" +#include "ivi_dsp.h" + +void ff_ivi_recompose53(const IVIPlaneDesc *plane, uint8_t *dst, + const int dst_pitch) +{ + int x, y, indx; + int32_t p0, p1, p2, p3, tmp0, tmp1, tmp2; + int32_t b0_1, b0_2, b1_1, b1_2, b1_3, b2_1, b2_2, b2_3, b2_4, b2_5, b2_6; + int32_t b3_1, b3_2, b3_3, b3_4, b3_5, b3_6, b3_7, b3_8, b3_9; + int32_t pitch, back_pitch; + const short *b0_ptr, *b1_ptr, *b2_ptr, *b3_ptr; + const int num_bands = 4; + + /* all bands should have the same pitch */ + pitch = plane->bands[0].pitch; + + /* pixels at the position "y-1" will be set to pixels at the "y" for the 1st iteration */ + back_pitch = 0; + + /* get pointers to the wavelet bands */ + b0_ptr = plane->bands[0].buf; + b1_ptr = plane->bands[1].buf; + b2_ptr = plane->bands[2].buf; + b3_ptr = plane->bands[3].buf; + + for (y = 0; y < plane->height; y += 2) { + + if (y+2 >= plane->height) + pitch= 0; + /* load storage variables with values */ + if (num_bands > 0) { + b0_1 = b0_ptr[0]; + b0_2 = b0_ptr[pitch]; + } + + if (num_bands > 1) { + b1_1 = b1_ptr[back_pitch]; + b1_2 = b1_ptr[0]; + b1_3 = b1_1 - b1_2*6 + b1_ptr[pitch]; + } + + if (num_bands > 2) { + b2_2 = b2_ptr[0]; // b2[x, y ] + b2_3 = b2_2; // b2[x+1,y ] = b2[x,y] + b2_5 = b2_ptr[pitch]; // b2[x ,y+1] + b2_6 = b2_5; // b2[x+1,y+1] = b2[x,y+1] + } + + if (num_bands > 3) { + b3_2 = b3_ptr[back_pitch]; // b3[x ,y-1] + b3_3 = b3_2; // b3[x+1,y-1] = b3[x ,y-1] + b3_5 = b3_ptr[0]; // b3[x ,y ] + b3_6 = b3_5; // b3[x+1,y ] = b3[x ,y ] + b3_8 = b3_2 - b3_5*6 + b3_ptr[pitch]; + b3_9 = b3_8; + } + + for (x = 0, indx = 0; x < plane->width; x+=2, indx++) { + if (x+2 >= plane->width) { + b0_ptr --; + b1_ptr --; + b2_ptr --; + b3_ptr --; + } + + /* some values calculated in the previous iterations can */ + /* be reused in the next ones, so do appropriate copying */ + b2_1 = b2_2; // b2[x-1,y ] = b2[x, y ] + b2_2 = b2_3; // b2[x ,y ] = b2[x+1,y ] + b2_4 = b2_5; // b2[x-1,y+1] = b2[x ,y+1] + b2_5 = b2_6; // b2[x ,y+1] = b2[x+1,y+1] + b3_1 = b3_2; // b3[x-1,y-1] = b3[x ,y-1] + b3_2 = b3_3; // b3[x ,y-1] = b3[x+1,y-1] + b3_4 = b3_5; // b3[x-1,y ] = b3[x ,y ] + b3_5 = b3_6; // b3[x ,y ] = b3[x+1,y ] + b3_7 = b3_8; // vert_HPF(x-1) + b3_8 = b3_9; // vert_HPF(x ) + + p0 = p1 = p2 = p3 = 0; + + /* process the LL-band by applying LPF both vertically and horizontally */ + if (num_bands > 0) { + tmp0 = b0_1; + tmp2 = b0_2; + b0_1 = b0_ptr[indx+1]; + b0_2 = b0_ptr[pitch+indx+1]; + tmp1 = tmp0 + b0_1; + + p0 = tmp0 << 4; + p1 = tmp1 << 3; + p2 = (tmp0 + tmp2) << 3; + p3 = (tmp1 + tmp2 + b0_2) << 2; + } + + /* process the HL-band by applying HPF vertically and LPF horizontally */ + if (num_bands > 1) { + tmp0 = b1_2; + tmp1 = b1_1; + b1_2 = b1_ptr[indx+1]; + b1_1 = b1_ptr[back_pitch+indx+1]; + + tmp2 = tmp1 - tmp0*6 + b1_3; + b1_3 = b1_1 - b1_2*6 + b1_ptr[pitch+indx+1]; + + p0 += (tmp0 + tmp1) << 3; + p1 += (tmp0 + tmp1 + b1_1 + b1_2) << 2; + p2 += tmp2 << 2; + p3 += (tmp2 + b1_3) << 1; + } + + /* process the LH-band by applying LPF vertically and HPF horizontally */ + if (num_bands > 2) { + b2_3 = b2_ptr[indx+1]; + b2_6 = b2_ptr[pitch+indx+1]; + + tmp0 = b2_1 + b2_2; + tmp1 = b2_1 - b2_2*6 + b2_3; + + p0 += tmp0 << 3; + p1 += tmp1 << 2; + p2 += (tmp0 + b2_4 + b2_5) << 2; + p3 += (tmp1 + b2_4 - b2_5*6 + b2_6) << 1; + } + + /* process the HH-band by applying HPF both vertically and horizontally */ + if (num_bands > 3) { + b3_6 = b3_ptr[indx+1]; // b3[x+1,y ] + b3_3 = b3_ptr[back_pitch+indx+1]; // b3[x+1,y-1] + + tmp0 = b3_1 + b3_4; + tmp1 = b3_2 + b3_5; + tmp2 = b3_3 + b3_6; + + b3_9 = b3_3 - b3_6*6 + b3_ptr[pitch+indx+1]; + + p0 += (tmp0 + tmp1) << 2; + p1 += (tmp0 - tmp1*6 + tmp2) << 1; + p2 += (b3_7 + b3_8) << 1; + p3 += b3_7 - b3_8*6 + b3_9; + } + + /* output four pixels */ + dst[x] = av_clip_uint8((p0 >> 6) + 128); + dst[x+1] = av_clip_uint8((p1 >> 6) + 128); + dst[dst_pitch+x] = av_clip_uint8((p2 >> 6) + 128); + dst[dst_pitch+x+1] = av_clip_uint8((p3 >> 6) + 128); + }// for x + + dst += dst_pitch << 1; + + back_pitch = -pitch; + + b0_ptr += pitch + 1; + b1_ptr += pitch + 1; + b2_ptr += pitch + 1; + b3_ptr += pitch + 1; + } +} + +void ff_ivi_recompose_haar(const IVIPlaneDesc *plane, uint8_t *dst, + const int dst_pitch) +{ + int x, y, indx, b0, b1, b2, b3, p0, p1, p2, p3; + const short *b0_ptr, *b1_ptr, *b2_ptr, *b3_ptr; + int32_t pitch; + + /* all bands should have the same pitch */ + pitch = plane->bands[0].pitch; + + /* get pointers to the wavelet bands */ + b0_ptr = plane->bands[0].buf; + b1_ptr = plane->bands[1].buf; + b2_ptr = plane->bands[2].buf; + b3_ptr = plane->bands[3].buf; + + for (y = 0; y < plane->height; y += 2) { + for (x = 0, indx = 0; x < plane->width; x += 2, indx++) { + /* load coefficients */ + b0 = b0_ptr[indx]; //should be: b0 = (num_bands > 0) ? b0_ptr[indx] : 0; + b1 = b1_ptr[indx]; //should be: b1 = (num_bands > 1) ? b1_ptr[indx] : 0; + b2 = b2_ptr[indx]; //should be: b2 = (num_bands > 2) ? b2_ptr[indx] : 0; + b3 = b3_ptr[indx]; //should be: b3 = (num_bands > 3) ? b3_ptr[indx] : 0; + + /* haar wavelet recomposition */ + p0 = (b0 + b1 + b2 + b3 + 2) >> 2; + p1 = (b0 + b1 - b2 - b3 + 2) >> 2; + p2 = (b0 - b1 + b2 - b3 + 2) >> 2; + p3 = (b0 - b1 - b2 + b3 + 2) >> 2; + + /* bias, convert and output four pixels */ + dst[x] = av_clip_uint8(p0 + 128); + dst[x + 1] = av_clip_uint8(p1 + 128); + dst[dst_pitch + x] = av_clip_uint8(p2 + 128); + dst[dst_pitch + x + 1] = av_clip_uint8(p3 + 128); + }// for x + + dst += dst_pitch << 1; + + b0_ptr += pitch; + b1_ptr += pitch; + b2_ptr += pitch; + b3_ptr += pitch; + }// for y +} + +/** butterfly operation for the inverse Haar transform */ +#define IVI_HAAR_BFLY(s1, s2, o1, o2, t) \ + t = (s1 - s2) >> 1;\ + o1 = (s1 + s2) >> 1;\ + o2 = t;\ + +/** inverse 8-point Haar transform */ +#define INV_HAAR8(s1, s5, s3, s7, s2, s4, s6, s8,\ + d1, d2, d3, d4, d5, d6, d7, d8,\ + t0, t1, t2, t3, t4, t5, t6, t7, t8) {\ + t1 = s1 << 1; t5 = s5 << 1;\ + IVI_HAAR_BFLY(t1, t5, t1, t5, t0); IVI_HAAR_BFLY(t1, s3, t1, t3, t0);\ + IVI_HAAR_BFLY(t5, s7, t5, t7, t0); IVI_HAAR_BFLY(t1, s2, t1, t2, t0);\ + IVI_HAAR_BFLY(t3, s4, t3, t4, t0); IVI_HAAR_BFLY(t5, s6, t5, t6, t0);\ + IVI_HAAR_BFLY(t7, s8, t7, t8, t0);\ + d1 = COMPENSATE(t1);\ + d2 = COMPENSATE(t2);\ + d3 = COMPENSATE(t3);\ + d4 = COMPENSATE(t4);\ + d5 = COMPENSATE(t5);\ + d6 = COMPENSATE(t6);\ + d7 = COMPENSATE(t7);\ + d8 = COMPENSATE(t8); } + +/** inverse 4-point Haar transform */ +#define INV_HAAR4(s1, s3, s5, s7) {\ + HAAR_BFLY(s1, s5); HAAR_BFLY(s1, s3); HAAR_BFLY(s5, s7);\ + s1 = COMPENSATE(s1);\ + s3 = COMPENSATE(s3);\ + s5 = COMPENSATE(s5);\ + s7 = COMPENSATE(s7); } + +void ff_ivi_inverse_haar_8x8(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags) +{ + int i, shift, sp1, sp2, sp3, sp4; + const int32_t *src; + int32_t *dst; + int tmp[64]; + int t0, t1, t2, t3, t4, t5, t6, t7, t8; + + /* apply the InvHaar8 to all columns */ +#define COMPENSATE(x) (x) + src = in; + dst = tmp; + for (i = 0; i < 8; i++) { + if (flags[i]) { + /* pre-scaling */ + shift = !(i & 4); + sp1 = src[ 0] << shift; + sp2 = src[ 8] << shift; + sp3 = src[16] << shift; + sp4 = src[24] << shift; + INV_HAAR8( sp1, sp2, sp3, sp4, + src[32], src[40], src[48], src[56], + dst[ 0], dst[ 8], dst[16], dst[24], + dst[32], dst[40], dst[48], dst[56], + t0, t1, t2, t3, t4, t5, t6, t7, t8); + } else + dst[ 0] = dst[ 8] = dst[16] = dst[24] = + dst[32] = dst[40] = dst[48] = dst[56] = 0; + + src++; + dst++; + } +#undef COMPENSATE + + /* apply the InvHaar8 to all rows */ +#define COMPENSATE(x) (x) + src = tmp; + for (i = 0; i < 8; i++) { + if ( !src[0] && !src[1] && !src[2] && !src[3] + && !src[4] && !src[5] && !src[6] && !src[7]) { + memset(out, 0, 8 * sizeof(out[0])); + } else { + INV_HAAR8(src[0], src[1], src[2], src[3], + src[4], src[5], src[6], src[7], + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + t0, t1, t2, t3, t4, t5, t6, t7, t8); + } + src += 8; + out += pitch; + } +#undef COMPENSATE +} + +void ff_ivi_dc_haar_2d(const int32_t *in, int16_t *out, uint32_t pitch, + int blk_size) +{ + int x, y; + int16_t dc_coeff; + + dc_coeff = (*in + 0) >> 3; + + for (y = 0; y < blk_size; out += pitch, y++) { + for (x = 0; x < blk_size; x++) + out[x] = dc_coeff; + } +} + +/** butterfly operation for the inverse slant transform */ +#define IVI_SLANT_BFLY(s1, s2, o1, o2, t) \ + t = s1 - s2;\ + o1 = s1 + s2;\ + o2 = t;\ + +/** This is a reflection a,b = 1/2, 5/4 for the inverse slant transform */ +#define IVI_IREFLECT(s1, s2, o1, o2, t) \ + t = ((s1 + s2*2 + 2) >> 2) + s1;\ + o2 = ((s1*2 - s2 + 2) >> 2) - s2;\ + o1 = t;\ + +/** This is a reflection a,b = 1/2, 7/8 for the inverse slant transform */ +#define IVI_SLANT_PART4(s1, s2, o1, o2, t) \ + t = s2 + ((s1*4 - s2 + 4) >> 3);\ + o2 = s1 + ((-s1 - s2*4 + 4) >> 3);\ + o1 = t;\ + +/** inverse slant8 transform */ +#define IVI_INV_SLANT8(s1, s4, s8, s5, s2, s6, s3, s7,\ + d1, d2, d3, d4, d5, d6, d7, d8,\ + t0, t1, t2, t3, t4, t5, t6, t7, t8) {\ + IVI_SLANT_PART4(s4, s5, t4, t5, t0);\ +\ + IVI_SLANT_BFLY(s1, t5, t1, t5, t0); IVI_SLANT_BFLY(s2, s6, t2, t6, t0);\ + IVI_SLANT_BFLY(s7, s3, t7, t3, t0); IVI_SLANT_BFLY(t4, s8, t4, t8, t0);\ +\ + IVI_SLANT_BFLY(t1, t2, t1, t2, t0); IVI_IREFLECT (t4, t3, t4, t3, t0);\ + IVI_SLANT_BFLY(t5, t6, t5, t6, t0); IVI_IREFLECT (t8, t7, t8, t7, t0);\ + IVI_SLANT_BFLY(t1, t4, t1, t4, t0); IVI_SLANT_BFLY(t2, t3, t2, t3, t0);\ + IVI_SLANT_BFLY(t5, t8, t5, t8, t0); IVI_SLANT_BFLY(t6, t7, t6, t7, t0);\ + d1 = COMPENSATE(t1);\ + d2 = COMPENSATE(t2);\ + d3 = COMPENSATE(t3);\ + d4 = COMPENSATE(t4);\ + d5 = COMPENSATE(t5);\ + d6 = COMPENSATE(t6);\ + d7 = COMPENSATE(t7);\ + d8 = COMPENSATE(t8);} + +/** inverse slant4 transform */ +#define IVI_INV_SLANT4(s1, s4, s2, s3, d1, d2, d3, d4, t0, t1, t2, t3, t4) {\ + IVI_SLANT_BFLY(s1, s2, t1, t2, t0); IVI_IREFLECT (s4, s3, t4, t3, t0);\ +\ + IVI_SLANT_BFLY(t1, t4, t1, t4, t0); IVI_SLANT_BFLY(t2, t3, t2, t3, t0);\ + d1 = COMPENSATE(t1);\ + d2 = COMPENSATE(t2);\ + d3 = COMPENSATE(t3);\ + d4 = COMPENSATE(t4);} + +void ff_ivi_inverse_slant_8x8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) +{ + int i; + const int32_t *src; + int32_t *dst; + int tmp[64]; + int t0, t1, t2, t3, t4, t5, t6, t7, t8; + +#define COMPENSATE(x) (x) + src = in; + dst = tmp; + for (i = 0; i < 8; i++) { + if (flags[i]) { + IVI_INV_SLANT8(src[0], src[8], src[16], src[24], src[32], src[40], src[48], src[56], + dst[0], dst[8], dst[16], dst[24], dst[32], dst[40], dst[48], dst[56], + t0, t1, t2, t3, t4, t5, t6, t7, t8); + } else + dst[0] = dst[8] = dst[16] = dst[24] = dst[32] = dst[40] = dst[48] = dst[56] = 0; + + src++; + dst++; + } +#undef COMPENSATE + +#define COMPENSATE(x) ((x + 1)>>1) + src = tmp; + for (i = 0; i < 8; i++) { + if (!src[0] && !src[1] && !src[2] && !src[3] && !src[4] && !src[5] && !src[6] && !src[7]) { + memset(out, 0, 8*sizeof(out[0])); + } else { + IVI_INV_SLANT8(src[0], src[1], src[2], src[3], src[4], src[5], src[6], src[7], + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + t0, t1, t2, t3, t4, t5, t6, t7, t8); + } + src += 8; + out += pitch; + } +#undef COMPENSATE +} + +void ff_ivi_inverse_slant_4x4(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) +{ + int i; + const int32_t *src; + int32_t *dst; + int tmp[16]; + int t0, t1, t2, t3, t4; + +#define COMPENSATE(x) (x) + src = in; + dst = tmp; + for (i = 0; i < 4; i++) { + if (flags[i]) { + IVI_INV_SLANT4(src[0], src[4], src[8], src[12], + dst[0], dst[4], dst[8], dst[12], + t0, t1, t2, t3, t4); + } else + dst[0] = dst[4] = dst[8] = dst[12] = 0; + + src++; + dst++; + } +#undef COMPENSATE + +#define COMPENSATE(x) ((x + 1)>>1) + src = tmp; + for (i = 0; i < 4; i++) { + if (!src[0] && !src[1] && !src[2] && !src[3]) { + out[0] = out[1] = out[2] = out[3] = 0; + } else { + IVI_INV_SLANT4(src[0], src[1], src[2], src[3], + out[0], out[1], out[2], out[3], + t0, t1, t2, t3, t4); + } + src += 4; + out += pitch; + } +#undef COMPENSATE +} + +void ff_ivi_dc_slant_2d(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size) +{ + int x, y; + int16_t dc_coeff; + + dc_coeff = (*in + 1) >> 1; + + for (y = 0; y < blk_size; out += pitch, y++) { + for (x = 0; x < blk_size; x++) + out[x] = dc_coeff; + } +} + +void ff_ivi_row_slant8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) +{ + int i; + int t0, t1, t2, t3, t4, t5, t6, t7, t8; + +#define COMPENSATE(x) ((x + 1)>>1) + for (i = 0; i < 8; i++) { + if (!in[0] && !in[1] && !in[2] && !in[3] && !in[4] && !in[5] && !in[6] && !in[7]) { + memset(out, 0, 8*sizeof(out[0])); + } else { + IVI_INV_SLANT8( in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7], + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + t0, t1, t2, t3, t4, t5, t6, t7, t8); + } + in += 8; + out += pitch; + } +#undef COMPENSATE +} + +void ff_ivi_dc_row_slant(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size) +{ + int x, y; + int16_t dc_coeff; + + dc_coeff = (*in + 1) >> 1; + + for (x = 0; x < blk_size; x++) + out[x] = dc_coeff; + + out += pitch; + + for (y = 1; y < blk_size; out += pitch, y++) { + for (x = 0; x < blk_size; x++) + out[x] = 0; + } +} + +void ff_ivi_col_slant8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags) +{ + int i, row2, row4, row8; + int t0, t1, t2, t3, t4, t5, t6, t7, t8; + + row2 = pitch << 1; + row4 = pitch << 2; + row8 = pitch << 3; + +#define COMPENSATE(x) ((x + 1)>>1) + for (i = 0; i < 8; i++) { + if (flags[i]) { + IVI_INV_SLANT8(in[0], in[8], in[16], in[24], in[32], in[40], in[48], in[56], + out[0], out[pitch], out[row2], out[row2 + pitch], out[row4], + out[row4 + pitch], out[row4 + row2], out[row8 - pitch], + t0, t1, t2, t3, t4, t5, t6, t7, t8); + } else { + out[0] = out[pitch] = out[row2] = out[row2 + pitch] = out[row4] = + out[row4 + pitch] = out[row4 + row2] = out[row8 - pitch] = 0; + } + + in++; + out++; + } +#undef COMPENSATE +} + +void ff_ivi_dc_col_slant(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size) +{ + int x, y; + int16_t dc_coeff; + + dc_coeff = (*in + 1) >> 1; + + for (y = 0; y < blk_size; out += pitch, y++) { + out[0] = dc_coeff; + for (x = 1; x < blk_size; x++) + out[x] = 0; + } +} + +void ff_ivi_put_pixels_8x8(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags) +{ + int x, y; + + for (y = 0; y < 8; out += pitch, in += 8, y++) + for (x = 0; x < 8; x++) + out[x] = in[x]; +} + +void ff_ivi_put_dc_pixel_8x8(const int32_t *in, int16_t *out, uint32_t pitch, + int blk_size) +{ + int y; + + out[0] = in[0]; + memset(out + 1, 0, 7*sizeof(out[0])); + out += pitch; + + for (y = 1; y < 8; out += pitch, y++) + memset(out, 0, 8*sizeof(out[0])); +} + +#define IVI_MC_TEMPLATE(size, suffix, OP) \ +void ff_ivi_mc_ ## size ##x## size ## suffix (int16_t *buf, const int16_t *ref_buf, \ + uint32_t pitch, int mc_type) \ +{ \ + int i, j; \ + const int16_t *wptr; \ +\ + switch (mc_type) { \ + case 0: /* fullpel (no interpolation) */ \ + for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) { \ + for (j = 0; j < size; j++) {\ + OP(buf[j], ref_buf[j]); \ + } \ + } \ + break; \ + case 1: /* horizontal halfpel interpolation */ \ + for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) \ + for (j = 0; j < size; j++) \ + OP(buf[j], (ref_buf[j] + ref_buf[j+1]) >> 1); \ + break; \ + case 2: /* vertical halfpel interpolation */ \ + wptr = ref_buf + pitch; \ + for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \ + for (j = 0; j < size; j++) \ + OP(buf[j], (ref_buf[j] + wptr[j]) >> 1); \ + break; \ + case 3: /* vertical and horizontal halfpel interpolation */ \ + wptr = ref_buf + pitch; \ + for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \ + for (j = 0; j < size; j++) \ + OP(buf[j], (ref_buf[j] + ref_buf[j+1] + wptr[j] + wptr[j+1]) >> 2); \ + break; \ + } \ +} \ + +#define OP_PUT(a, b) (a) = (b) +#define OP_ADD(a, b) (a) += (b) + +IVI_MC_TEMPLATE(8, _no_delta, OP_PUT) +IVI_MC_TEMPLATE(8, _delta, OP_ADD) +IVI_MC_TEMPLATE(4, _no_delta, OP_PUT) +IVI_MC_TEMPLATE(4, _delta, OP_ADD) diff --git a/ffmpeg/libavcodec/ivi_dsp.h b/ffmpeg/libavcodec/ivi_dsp.h new file mode 100644 index 0000000..e95bb11 --- /dev/null +++ b/ffmpeg/libavcodec/ivi_dsp.h @@ -0,0 +1,205 @@ +/* + * DSP functions for Indeo Video Interactive codecs (Indeo4 and Indeo5) + * + * Copyright (c) 2009-2011 Maxim Poliakovski + * + * 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 + */ + +/** + * @file + * DSP functions (inverse transforms, motion compensations, wavelet recompostion) + * for Indeo Video Interactive codecs. + */ + +#ifndef AVCODEC_IVI_DSP_H +#define AVCODEC_IVI_DSP_H + +#include "avcodec.h" +#include "ivi_common.h" + +/** + * 5/3 wavelet recomposition filter for Indeo5 + * + * @param[in] plane pointer to the descriptor of the plane being processed + * @param[out] dst pointer to the destination buffer + * @param[in] dst_pitch pitch of the destination buffer + */ +void ff_ivi_recompose53(const IVIPlaneDesc *plane, uint8_t *dst, + const int dst_pitch); + +/** + * Haar wavelet recomposition filter for Indeo 4 + * + * @param[in] plane pointer to the descriptor of the plane being processed + * @param[out] dst pointer to the destination buffer + * @param[in] dst_pitch pitch of the destination buffer + */ +void ff_ivi_recompose_haar(const IVIPlaneDesc *plane, uint8_t *dst, + const int dst_pitch); + +/** + * two-dimensional inverse Haar 8x8 transform for Indeo 4 + * + * @param[in] in pointer to the vector of transform coefficients + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] flags pointer to the array of column flags: + * != 0 - non_empty column, 0 - empty one + * (this array must be filled by caller) + */ +void ff_ivi_inverse_haar_8x8(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags); + +/** + * DC-only two-dimensional inverse Haar transform for Indeo 4. + * Performing the inverse transform in this case is equivalent to + * spreading DC_coeff >> 3 over the whole block. + * + * @param[in] in pointer to the dc coefficient + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] blk_size transform block size + */ +void ff_ivi_dc_haar_2d(const int32_t *in, int16_t *out, uint32_t pitch, + int blk_size); + +/** + * two-dimensional inverse slant 8x8 transform + * + * @param[in] in pointer to the vector of transform coefficients + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] flags pointer to the array of column flags: + * != 0 - non_empty column, 0 - empty one + * (this array must be filled by caller) + */ +void ff_ivi_inverse_slant_8x8(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags); + +/** + * two-dimensional inverse slant 4x4 transform + * + * @param[in] in pointer to the vector of transform coefficients + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] flags pointer to the array of column flags: + * != 0 - non_empty column, 0 - empty one + * (this array must be filled by caller) + */ +void ff_ivi_inverse_slant_4x4(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags); + +/** + * DC-only two-dimensional inverse slant transform. + * Performing the inverse slant transform in this case is equivalent to + * spreading (DC_coeff + 1)/2 over the whole block. + * It works much faster than performing the slant transform on a vector of zeroes. + * + * @param[in] in pointer to the dc coefficient + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] blk_size transform block size + */ +void ff_ivi_dc_slant_2d(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size); + +/** + * inverse 1D row slant transform + * + * @param[in] in pointer to the vector of transform coefficients + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] flags pointer to the array of column flags (unused here) + */ +void ff_ivi_row_slant8(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags); + +/** + * inverse 1D column slant transform + * + * @param[in] in pointer to the vector of transform coefficients + * @param[out] out pointer to the output buffer (frame) + * @param[in] pitch pitch to move to the next y line + * @param[in] flags pointer to the array of column flags: + * != 0 - non_empty column, 0 - empty one + * (this array must be filled by caller) + */ +void ff_ivi_col_slant8(const int32_t *in, int16_t *out, uint32_t pitch, + const uint8_t *flags); + +/** + * DC-only inverse row slant transform + */ +void ff_ivi_dc_row_slant(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size); + +/** + * DC-only inverse column slant transform + */ +void ff_ivi_dc_col_slant(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size); + +/** + * Copy the pixels into the frame buffer. + */ +void ff_ivi_put_pixels_8x8(const int32_t *in, int16_t *out, uint32_t pitch, const uint8_t *flags); + +/** + * Copy the DC coefficient into the first pixel of the block and + * zero all others. + */ +void ff_ivi_put_dc_pixel_8x8(const int32_t *in, int16_t *out, uint32_t pitch, int blk_size); + +/** + * 8x8 block motion compensation with adding delta + * + * @param[in,out] buf pointer to the block in the current frame buffer containing delta + * @param[in] ref_buf pointer to the corresponding block in the reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type + */ +void ff_ivi_mc_8x8_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + +/** + * 4x4 block motion compensation with adding delta + * + * @param[in,out] buf pointer to the block in the current frame buffer containing delta + * @param[in] ref_buf pointer to the corresponding block in the reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type + */ +void ff_ivi_mc_4x4_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + +/** + * motion compensation without adding delta + * + * @param[in,out] buf pointer to the block in the current frame receiving the result + * @param[in] ref_buf pointer to the corresponding block in the reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type + */ +void ff_ivi_mc_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + +/** + * 4x4 block motion compensation without adding delta + * + * @param[in,out] buf pointer to the block in the current frame receiving the result + * @param[in] ref_buf pointer to the corresponding block in the reference frame + * @param[in] pitch pitch for moving to the next y line + * @param[in] mc_type interpolation type + */ +void ff_ivi_mc_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type); + +#endif /* AVCODEC_IVI_DSP_H */ diff --git a/ffmpeg/libavcodec/j2k.c b/ffmpeg/libavcodec/j2k.c new file mode 100644 index 0000000..e3c0c13 --- /dev/null +++ b/ffmpeg/libavcodec/j2k.c @@ -0,0 +1,391 @@ +/* + * JPEG2000 encoder and decoder common functions + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * JPEG2000 image encoder and decoder common functions + * @file + * @author Kamil Nowosad + */ + + +#include "avcodec.h" +#include "j2k.h" + +#define SHL(a, n) ((n)>=0 ? (a) << (n) : (a) >> -(n)) + +#if 0 +void ff_j2k_printv(int *tab, int l) +{ + int i; + for (i = 0; i < l; i++) + av_log(NULL, AV_LOG_DEBUG, "%.3d ", tab[i]); + av_log(NULL, AV_LOG_DEBUG, "\n"); +} + +void ff_j2k_printu(uint8_t *tab, int l) +{ + int i; + for (i = 0; i < l; i++) + av_log(NULL, AV_LOG_DEBUG, "%.3hd ", tab[i]); + av_log(NULL, AV_LOG_DEBUG, "\n"); +} +#endif + +/* tag tree routines */ + +/** allocate the memory for tag tree */ + +static int tag_tree_size(int w, int h) +{ + int res = 0; + while (w > 1 || h > 1){ + res += w * h; + w = (w+1) >> 1; + h = (h+1) >> 1; + } + return res + 1; +} + +J2kTgtNode *ff_j2k_tag_tree_init(int w, int h) +{ + int pw = w, ph = h; + J2kTgtNode *res, *t, *t2; + + t = res = av_mallocz(tag_tree_size(w, h)*sizeof(J2kTgtNode)); + + if (res == NULL) + return NULL; + + while (w > 1 || h > 1){ + int i, j; + pw = w; + ph = h; + + w = (w+1) >> 1; + h = (h+1) >> 1; + t2 = t + pw*ph; + + for (i = 0; i < ph; i++) + for (j = 0; j < pw; j++){ + t[i*pw + j].parent = &t2[(i>>1)*w + (j>>1)]; + } + t = t2; + } + t[0].parent = NULL; + return res; +} + +static void tag_tree_zero(J2kTgtNode *t, int w, int h) +{ + int i, siz = tag_tree_size(w, h); + + for (i = 0; i < siz; i++){ + t[i].val = 0; + t[i].vis = 0; + } +} + +uint8_t ff_j2k_nbctxno_lut[256][4]; + +static int getnbctxno(int flag, int bandno, int vert_causal_ctx_csty_symbol) +{ + int h, v, d; + + h = ((flag & J2K_T1_SIG_E) ? 1:0)+ + ((flag & J2K_T1_SIG_W) ? 1:0); + v = ((flag & J2K_T1_SIG_N) ? 1:0); + if (!vert_causal_ctx_csty_symbol) + v = v + ((flag & J2K_T1_SIG_S) ? 1:0); + d = ((flag & J2K_T1_SIG_NE) ? 1:0)+ + ((flag & J2K_T1_SIG_NW) ? 1:0); + if (!vert_causal_ctx_csty_symbol) + d = d + ((flag & J2K_T1_SIG_SE) ? 1:0)+ + ((flag & J2K_T1_SIG_SW) ? 1:0); + if (bandno < 3){ + if (bandno == 1) + FFSWAP(int, h, v); + if (h == 2) return 8; + if (h == 1){ + if (v >= 1) return 7; + if (d >= 1) return 6; + return 5; + } + if (v == 2) return 4; + if (v == 1) return 3; + if (d >= 2) return 2; + if (d == 1) return 1; + return 0; + } else{ + if (d >= 3) return 8; + if (d == 2){ + if (h+v >= 1) return 7; + return 6; + } + if (d == 1){ + if (h+v >= 2) return 5; + if (h+v == 1) return 4; + return 3; + } + if (h+v >= 2) return 2; + if (h+v == 1) return 1; + return 0; + } +} + +uint8_t ff_j2k_sgnctxno_lut[16][16], ff_j2k_xorbit_lut[16][16]; + +static int getsgnctxno(int flag, uint8_t *xorbit) +{ + int vcontrib, hcontrib; + static const int contribtab[3][3] = {{0, -1, 1}, {-1, -1, 0}, {1, 0, 1}}; + static const int ctxlbltab[3][3] = {{13, 12, 11}, {10, 9, 10}, {11, 12, 13}}; + static const int xorbittab[3][3] = {{1, 1, 1,}, {1, 0, 0}, {0, 0, 0}}; + + hcontrib = contribtab[flag & J2K_T1_SIG_E ? flag & J2K_T1_SGN_E ? 1:2:0] + [flag & J2K_T1_SIG_W ? flag & J2K_T1_SGN_W ? 1:2:0]+1; + vcontrib = contribtab[flag & J2K_T1_SIG_S ? flag & J2K_T1_SGN_S ? 1:2:0] + [flag & J2K_T1_SIG_N ? flag & J2K_T1_SGN_N ? 1:2:0]+1; + *xorbit = xorbittab[hcontrib][vcontrib]; + return ctxlbltab[hcontrib][vcontrib]; +} + +void ff_j2k_init_tier1_luts(void) +{ + int i, j; + for (i = 0; i < 256; i++) + for (j = 0; j < 4; j++) + ff_j2k_nbctxno_lut[i][j] = getnbctxno(i, j, 0); + for (i = 0; i < 16; i++) + for (j = 0; j < 16; j++) + ff_j2k_sgnctxno_lut[i][j] = getsgnctxno(i + (j << 8), &ff_j2k_xorbit_lut[i][j]); +} + +void ff_j2k_set_significant(J2kT1Context *t1, int x, int y, int negative) +{ + x++; y++; + t1->flags[y][x] |= J2K_T1_SIG; + if (negative){ + t1->flags[y][x+1] |= J2K_T1_SIG_W | J2K_T1_SGN_W; + t1->flags[y][x-1] |= J2K_T1_SIG_E | J2K_T1_SGN_E; + t1->flags[y+1][x] |= J2K_T1_SIG_N | J2K_T1_SGN_N; + t1->flags[y-1][x] |= J2K_T1_SIG_S | J2K_T1_SGN_S; + } else{ + t1->flags[y][x+1] |= J2K_T1_SIG_W; + t1->flags[y][x-1] |= J2K_T1_SIG_E; + t1->flags[y+1][x] |= J2K_T1_SIG_N; + t1->flags[y-1][x] |= J2K_T1_SIG_S; + } + t1->flags[y+1][x+1] |= J2K_T1_SIG_NW; + t1->flags[y+1][x-1] |= J2K_T1_SIG_NE; + t1->flags[y-1][x+1] |= J2K_T1_SIG_SW; + t1->flags[y-1][x-1] |= J2K_T1_SIG_SE; +} + +int ff_j2k_init_component(J2kComponent *comp, J2kCodingStyle *codsty, J2kQuantStyle *qntsty, int cbps, int dx, int dy) +{ + int reslevelno, bandno, gbandno = 0, ret, i, j, csize = 1; + + if (ret=ff_j2k_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels-1, codsty->transform)) + return ret; + for (i = 0; i < 2; i++) + csize *= comp->coord[i][1] - comp->coord[i][0]; + + comp->data = av_malloc(csize * sizeof(int)); + if (!comp->data) + return AVERROR(ENOMEM); + comp->reslevel = av_malloc(codsty->nreslevels * sizeof(J2kResLevel)); + + if (!comp->reslevel) + return AVERROR(ENOMEM); + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + int declvl = codsty->nreslevels - reslevelno; + J2kResLevel *reslevel = comp->reslevel + reslevelno; + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + reslevel->coord[i][j] = + ff_j2k_ceildivpow2(comp->coord[i][j], declvl - 1); + + if (reslevelno == 0) + reslevel->nbands = 1; + else + reslevel->nbands = 3; + + if (reslevel->coord[0][1] == reslevel->coord[0][0]) + reslevel->num_precincts_x = 0; + else + reslevel->num_precincts_x = ff_j2k_ceildivpow2(reslevel->coord[0][1], codsty->log2_prec_width) + - (reslevel->coord[0][0] >> codsty->log2_prec_width); + + if (reslevel->coord[1][1] == reslevel->coord[1][0]) + reslevel->num_precincts_y = 0; + else + reslevel->num_precincts_y = ff_j2k_ceildivpow2(reslevel->coord[1][1], codsty->log2_prec_height) + - (reslevel->coord[1][0] >> codsty->log2_prec_height); + + reslevel->band = av_malloc(reslevel->nbands * sizeof(J2kBand)); + if (!reslevel->band) + return AVERROR(ENOMEM); + for (bandno = 0; bandno < reslevel->nbands; bandno++, gbandno++){ + J2kBand *band = reslevel->band + bandno; + int cblkno, precx, precy, precno; + int x0, y0, x1, y1; + int xi0, yi0, xi1, yi1; + int cblkperprecw, cblkperprech; + + if (qntsty->quantsty != J2K_QSTY_NONE){ + static const uint8_t lut_gain[2][4] = {{0, 0, 0, 0}, {0, 1, 1, 2}}; + int numbps; + + numbps = cbps + lut_gain[codsty->transform][bandno + reslevelno>0]; + band->stepsize = SHL(2048 + qntsty->mant[gbandno], 2 + numbps - qntsty->expn[gbandno]); + } else + band->stepsize = 1 << 13; + + if (reslevelno == 0){ // the same everywhere + band->codeblock_width = 1 << FFMIN(codsty->log2_cblk_width, codsty->log2_prec_width-1); + band->codeblock_height = 1 << FFMIN(codsty->log2_cblk_height, codsty->log2_prec_height-1); + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + band->coord[i][j] = ff_j2k_ceildivpow2(comp->coord[i][j], declvl-1); + } else{ + band->codeblock_width = 1 << FFMIN(codsty->log2_cblk_width, codsty->log2_prec_width); + band->codeblock_height = 1 << FFMIN(codsty->log2_cblk_height, codsty->log2_prec_height); + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + band->coord[i][j] = ff_j2k_ceildivpow2(comp->coord[i][j] - (((bandno+1>>i)&1) << declvl-1), declvl); + } + band->cblknx = ff_j2k_ceildiv(band->coord[0][1], band->codeblock_width) - band->coord[0][0] / band->codeblock_width; + band->cblkny = ff_j2k_ceildiv(band->coord[1][1], band->codeblock_height) - band->coord[1][0] / band->codeblock_height; + + for (j = 0; j < 2; j++) + band->coord[0][j] = ff_j2k_ceildiv(band->coord[0][j], dx); + for (j = 0; j < 2; j++) + band->coord[1][j] = ff_j2k_ceildiv(band->coord[1][j], dy); + + band->cblknx = ff_j2k_ceildiv(band->cblknx, dx); + band->cblkny = ff_j2k_ceildiv(band->cblkny, dy); + + band->cblk = av_malloc(sizeof(J2kCblk) * band->cblknx * band->cblkny); + if (!band->cblk) + return AVERROR(ENOMEM); + band->prec = av_malloc(sizeof(J2kCblk) * reslevel->num_precincts_x * reslevel->num_precincts_y); + if (!band->prec) + return AVERROR(ENOMEM); + + for (cblkno = 0; cblkno < band->cblknx * band->cblkny; cblkno++){ + J2kCblk *cblk = band->cblk + cblkno; + cblk->zero = 0; + cblk->lblock = 3; + cblk->length = 0; + cblk->lengthinc = 0; + cblk->npasses = 0; + } + + y0 = band->coord[1][0]; + y1 = ((band->coord[1][0] + (1<log2_prec_height)) & ~((1<log2_prec_height)-1)) - y0; + yi0 = 0; + yi1 = ff_j2k_ceildivpow2(y1 - y0, codsty->log2_cblk_height) << codsty->log2_cblk_height; + yi1 = FFMIN(yi1, band->cblkny); + cblkperprech = 1<<(codsty->log2_prec_height - codsty->log2_cblk_height); + for (precy = 0, precno = 0; precy < reslevel->num_precincts_y; precy++){ + for (precx = 0; precx < reslevel->num_precincts_x; precx++, precno++){ + band->prec[precno].yi0 = yi0; + band->prec[precno].yi1 = yi1; + } + yi1 += cblkperprech; + yi0 = yi1 - cblkperprech; + yi1 = FFMIN(yi1, band->cblkny); + } + x0 = band->coord[0][0]; + x1 = ((band->coord[0][0] + (1<log2_prec_width)) & ~((1<log2_prec_width)-1)) - x0; + xi0 = 0; + xi1 = ff_j2k_ceildivpow2(x1 - x0, codsty->log2_cblk_width) << codsty->log2_cblk_width; + xi1 = FFMIN(xi1, band->cblknx); + + cblkperprecw = 1<<(codsty->log2_prec_width - codsty->log2_cblk_width); + for (precx = 0, precno = 0; precx < reslevel->num_precincts_x; precx++){ + for (precy = 0; precy < reslevel->num_precincts_y; precy++, precno = 0){ + J2kPrec *prec = band->prec + precno; + prec->xi0 = xi0; + prec->xi1 = xi1; + prec->cblkincl = ff_j2k_tag_tree_init(prec->xi1 - prec->xi0, + prec->yi1 - prec->yi0); + prec->zerobits = ff_j2k_tag_tree_init(prec->xi1 - prec->xi0, + prec->yi1 - prec->yi0); + if (!prec->cblkincl || !prec->zerobits) + return AVERROR(ENOMEM); + + } + xi1 += cblkperprecw; + xi0 = xi1 - cblkperprecw; + xi1 = FFMIN(xi1, band->cblknx); + } + } + } + return 0; +} + +void ff_j2k_reinit(J2kComponent *comp, J2kCodingStyle *codsty) +{ + int reslevelno, bandno, cblkno, precno; + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + J2kResLevel *rlevel = comp->reslevel + reslevelno; + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + J2kBand *band = rlevel->band + bandno; + for(precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++){ + J2kPrec *prec = band->prec + precno; + tag_tree_zero(prec->zerobits, prec->xi1 - prec->xi0, prec->yi1 - prec->yi0); + tag_tree_zero(prec->cblkincl, prec->xi1 - prec->xi0, prec->yi1 - prec->yi0); + } + for (cblkno = 0; cblkno < band->cblknx * band->cblkny; cblkno++){ + J2kCblk *cblk = band->cblk + cblkno; + cblk->length = 0; + cblk->lblock = 3; + } + } + } +} + +void ff_j2k_cleanup(J2kComponent *comp, J2kCodingStyle *codsty) +{ + int reslevelno, bandno, precno; + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + J2kResLevel *reslevel = comp->reslevel + reslevelno; + + for (bandno = 0; bandno < reslevel->nbands ; bandno++){ + J2kBand *band = reslevel->band + bandno; + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + J2kPrec *prec = band->prec + precno; + av_freep(&prec->zerobits); + av_freep(&prec->cblkincl); + } + av_freep(&band->cblk); + av_freep(&band->prec); + } + av_freep(&reslevel->band); + } + + ff_j2k_dwt_destroy(&comp->dwt); + av_freep(&comp->reslevel); + av_freep(&comp->data); +} diff --git a/ffmpeg/libavcodec/j2k.h b/ffmpeg/libavcodec/j2k.h new file mode 100644 index 0000000..85d5cd0 --- /dev/null +++ b/ffmpeg/libavcodec/j2k.h @@ -0,0 +1,234 @@ +/* + * JPEG2000 tables + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +#ifndef AVCODEC_J2K_H +#define AVCODEC_J2K_H + +/** + * JPEG2000 tables + * @file + * @author Kamil Nowosad + */ + +#include "mqc.h" +#include "j2k_dwt.h" + +enum J2kMarkers{ + J2K_SOC = 0xff4f, ///< start of codestream + J2K_SIZ = 0xff51, ///< image and tile size + J2K_COD, ///< coding style default + J2K_COC, ///< coding style component + J2K_TLM = 0xff55, ///< packed packet headers, tile-part header + J2K_PLM = 0xff57, ///< tile-part lengths + J2K_PLT, ///< packet length, main header + J2K_QCD = 0xff5c, ///< quantization default + J2K_QCC, ///< quantization component + J2K_RGN, ///< region of interest + J2K_POC, ///< progression order change + J2K_PPM, ///< packet length, tile-part header + J2K_PPT, ///< packed packet headers, main header + J2K_CRG = 0xff63, ///< component registration + J2K_COM, ///< comment + J2K_SOT = 0xff90, ///< start of tile-part + J2K_SOP, ///< start of packet + J2K_EPH, ///< end of packet header + J2K_SOD, ///< start of data + J2K_EOC = 0xffd9, ///< end of codestream +}; + +enum J2kQuantsty{ ///< quantization style + J2K_QSTY_NONE, ///< no quantization + J2K_QSTY_SI, ///< scalar derived + J2K_QSTY_SE ///< scalar expoounded +}; + +#define J2K_MAX_CBLKW 64 +#define J2K_MAX_CBLKH 64 + +// T1 flags +// flags determining significance of neighbour coefficients +#define J2K_T1_SIG_N 0x0001 +#define J2K_T1_SIG_E 0x0002 +#define J2K_T1_SIG_W 0x0004 +#define J2K_T1_SIG_S 0x0008 +#define J2K_T1_SIG_NE 0x0010 +#define J2K_T1_SIG_NW 0x0020 +#define J2K_T1_SIG_SE 0x0040 +#define J2K_T1_SIG_SW 0x0080 +#define J2K_T1_SIG_NB (J2K_T1_SIG_N | J2K_T1_SIG_E | J2K_T1_SIG_S | J2K_T1_SIG_W \ + |J2K_T1_SIG_NE | J2K_T1_SIG_NW | J2K_T1_SIG_SE | J2K_T1_SIG_SW) +// flags determining sign bit of neighbour coefficients +#define J2K_T1_SGN_N 0x0100 +#define J2K_T1_SGN_S 0x0200 +#define J2K_T1_SGN_W 0x0400 +#define J2K_T1_SGN_E 0x0800 + +#define J2K_T1_VIS 0x1000 +#define J2K_T1_SIG 0x2000 +#define J2K_T1_REF 0x4000 + +#define J2K_T1_SGN 0x8000 + +// Codeblock coding styles +#define J2K_CBLK_BYPASS 0x01 // Selective arithmetic coding bypass +#define J2K_CBLK_RESET 0x02 // Reset context probabilities +#define J2K_CBLK_TERMALL 0x04 // Terminate after each coding pass +#define J2K_CBLK_VSC 0x08 // Vertical stripe causal context formation +#define J2K_CBLK_PREDTERM 0x10 // Predictable termination +#define J2K_CBLK_SEGSYM 0x20 // Segmentation symbols present + +// Coding styles +#define J2K_CSTY_PREC 0x01 // Precincts defined in coding style +#define J2K_CSTY_SOP 0x02 // SOP marker present +#define J2K_CSTY_EPH 0x04 // EPH marker present + +typedef struct { + int data[J2K_MAX_CBLKW][J2K_MAX_CBLKH]; + int flags[J2K_MAX_CBLKW+2][J2K_MAX_CBLKH+2]; + MqcState mqc; +} J2kT1Context; + +typedef struct J2kTgtNode { + uint8_t val; + uint8_t vis; + struct J2kTgtNode *parent; +} J2kTgtNode; + +typedef struct { + uint8_t nreslevels; ///< number of resolution levels + uint8_t log2_cblk_width, + log2_cblk_height; ///< exponent of codeblock size + uint8_t transform; ///< DWT type + uint8_t csty; ///< coding style + uint8_t log2_prec_width, + log2_prec_height; ///< precinct size + uint8_t nlayers; ///< number of layers + uint8_t mct; ///< multiple component transformation + uint8_t cblk_style; ///< codeblock coding style +} J2kCodingStyle; + +typedef struct { + uint8_t expn[32 * 3]; ///< quantization exponent + uint16_t mant[32 * 3]; ///< quantization mantissa + uint8_t quantsty; ///< quantization style + uint8_t nguardbits; ///< number of guard bits +} J2kQuantStyle; + +typedef struct { + uint16_t rate; + int64_t disto; +} J2kPass; + +typedef struct { + uint8_t npasses; + uint8_t ninclpasses; ///< number coding of passes included in codestream + uint8_t nonzerobits; + uint16_t length; + uint16_t lengthinc; + uint8_t lblock; + uint8_t zero; + uint8_t data[8192]; + J2kPass passes[100]; +} J2kCblk; ///< code block + +typedef struct { + uint16_t xi0, xi1, yi0, yi1; ///< codeblock indexes ([xi0, xi1)) + J2kTgtNode *zerobits; + J2kTgtNode *cblkincl; +} J2kPrec; ///< precinct + +typedef struct { + uint16_t coord[2][2]; ///< border coordinates {{x0, x1}, {y0, y1}} + uint16_t codeblock_width, codeblock_height; + uint16_t cblknx, cblkny; + uint32_t stepsize; ///< quantization stepsize (* 2^13) + J2kPrec *prec; + J2kCblk *cblk; +} J2kBand; ///< subband + +typedef struct { + uint8_t nbands; + uint16_t coord[2][2]; ///< border coordinates {{x0, x1}, {y0, y1}} + uint16_t num_precincts_x, num_precincts_y; ///< number of precincts in x/y direction + uint8_t log2_prec_width, log2_prec_height; ///< exponent of precinct size + J2kBand *band; +} J2kResLevel; ///< resolution level + +typedef struct { + J2kResLevel *reslevel; + DWTContext dwt; + int *data; + uint16_t coord[2][2]; ///< border coordinates {{x0, x1}, {y0, y1}} +} J2kComponent; + +/* debug routines */ +#if 0 +#undef fprintf +#undef printf +void ff_j2k_printv(int *tab, int l); +void ff_j2k_printu(uint8_t *tab, int l); +#endif + +/* misc tools */ +static inline int ff_j2k_ceildivpow2(int a, int b) +{ + return (a + (1 << b) - 1)>> b; +} + +static inline int ff_j2k_ceildiv(int a, int b) +{ + return (a + b - 1) / b; +} + +/* tag tree routines */ +J2kTgtNode *ff_j2k_tag_tree_init(int w, int h); + +/* TIER-1 routines */ +void ff_j2k_init_tier1_luts(void); + +void ff_j2k_set_significant(J2kT1Context *t1, int x, int y, int negative); + +extern uint8_t ff_j2k_nbctxno_lut[256][4]; + +static inline int ff_j2k_getnbctxno(int flag, int bandno, int vert_causal_ctx_csty_symbol) +{ + return ff_j2k_nbctxno_lut[flag&255][bandno]; +} + +static inline int ff_j2k_getrefctxno(int flag) +{ + static const uint8_t refctxno_lut[2][2] = {{14, 15}, {16, 16}}; + return refctxno_lut[(flag>>14)&1][(flag & 255) != 0]; +} + +extern uint8_t ff_j2k_sgnctxno_lut[16][16], ff_j2k_xorbit_lut[16][16]; + +static inline int ff_j2k_getsgnctxno(int flag, int *xorbit) +{ + *xorbit = ff_j2k_xorbit_lut[flag&15][(flag>>8)&15]; + return ff_j2k_sgnctxno_lut[flag&15][(flag>>8)&15]; +} + +int ff_j2k_init_component(J2kComponent *comp, J2kCodingStyle *codsty, J2kQuantStyle *qntsty, int cbps, int dx, int dy); +void ff_j2k_reinit(J2kComponent *comp, J2kCodingStyle *codsty); +void ff_j2k_cleanup(J2kComponent *comp, J2kCodingStyle *codsty); + +#endif /* AVCODEC_J2K_H */ diff --git a/ffmpeg/libavcodec/j2k_dwt.c b/ffmpeg/libavcodec/j2k_dwt.c new file mode 100644 index 0000000..6f1457f --- /dev/null +++ b/ffmpeg/libavcodec/j2k_dwt.c @@ -0,0 +1,386 @@ +/* + * Discrete wavelet transform + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * Discrete wavelet transform + * @file + * @author Kamil Nowosad + */ + +#include "j2k_dwt.h" + +static const float scale97[] = {1.625786, 1.230174}; + +static inline void extend53(int *p, int i0, int i1) +{ + p[i0 - 1] = p[i0 + 1]; + p[i1 ] = p[i1 - 2]; + p[i0 - 2] = p[i0 + 2]; + p[i1 + 1] = p[i1 - 3]; +} + +static inline void extend97(float *p, int i0, int i1) +{ + int i; + + for (i = 1; i <= 4; i++){ + p[i0 - i] = p[i0 + i]; + p[i1 + i - 1] = p[i1 - i - 1]; + } +} + +static void sd_1d53(int *p, int i0, int i1) +{ + int i; + + if (i1 == i0 + 1) + return; + + extend53(p, i0, i1); + + for (i = (i0+1)/2 - 1; i < (i1+1)/2; i++) + p[2*i+1] -= (p[2*i] + p[2*i+2]) >> 1; + for (i = (i0+1)/2; i < (i1+1)/2; i++) + p[2*i] += (p[2*i-1] + p[2*i+1] + 2) >> 2; +} + +static void dwt_encode53(DWTContext *s, int *t) +{ + int lev, + w = s->linelen[s->ndeclevels-1][0]; + int *line = s->linebuf; + line += 3; + + for (lev = s->ndeclevels-1; lev >= 0; lev--){ + int lh = s->linelen[lev][0], + lv = s->linelen[lev][1], + mh = s->mod[lev][0], + mv = s->mod[lev][1], + lp; + int *l; + + // HOR_SD + l = line + mh; + for (lp = 0; lp < lv; lp++){ + int i, j = 0; + + for (i = 0; i < lh; i++) + l[i] = t[w*lp + i]; + + sd_1d53(line, mh, mh + lh); + + // copy back and deinterleave + for (i = mh; i < lh; i+=2, j++) + t[w*lp + j] = l[i]; + for (i = 1-mh; i < lh; i+=2, j++) + t[w*lp + j] = l[i]; + } + + // VER_SD + l = line + mv; + for (lp = 0; lp < lh; lp++) { + int i, j = 0; + + for (i = 0; i < lv; i++) + l[i] = t[w*i + lp]; + + sd_1d53(line, mv, mv + lv); + + // copy back and deinterleave + for (i = mv; i < lv; i+=2, j++) + t[w*j + lp] = l[i]; + for (i = 1-mv; i < lv; i+=2, j++) + t[w*j + lp] = l[i]; + } + } +} + +static void sd_1d97(float *p, int i0, int i1) +{ + int i; + + if (i1 == i0 + 1) + return; + + extend97(p, i0, i1); + i0++; i1++; + + for (i = i0/2 - 2; i < i1/2 + 1; i++) + p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]); + for (i = i0/2 - 1; i < i1/2 + 1; i++) + p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]); + for (i = i0/2 - 1; i < i1/2; i++) + p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]); + for (i = i0/2; i < i1/2; i++) + p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]); +} + +static void dwt_encode97(DWTContext *s, int *t) +{ + int lev, + w = s->linelen[s->ndeclevels-1][0]; + float *line = s->linebuf; + line += 5; + + for (lev = s->ndeclevels-1; lev >= 0; lev--){ + int lh = s->linelen[lev][0], + lv = s->linelen[lev][1], + mh = s->mod[lev][0], + mv = s->mod[lev][1], + lp; + float *l; + + // HOR_SD + l = line + mh; + for (lp = 0; lp < lv; lp++){ + int i, j = 0; + + for (i = 0; i < lh; i++) + l[i] = t[w*lp + i]; + + sd_1d97(line, mh, mh + lh); + + // copy back and deinterleave + for (i = mh; i < lh; i+=2, j++) + t[w*lp + j] = scale97[mh] * l[i] / 2; + for (i = 1-mh; i < lh; i+=2, j++) + t[w*lp + j] = scale97[mh] * l[i] / 2; + } + + // VER_SD + l = line + mv; + for (lp = 0; lp < lh; lp++) { + int i, j = 0; + + for (i = 0; i < lv; i++) + l[i] = t[w*i + lp]; + + sd_1d97(line, mv, mv + lv); + + // copy back and deinterleave + for (i = mv; i < lv; i+=2, j++) + t[w*j + lp] = scale97[mv] * l[i] / 2; + for (i = 1-mv; i < lv; i+=2, j++) + t[w*j + lp] = scale97[mv] * l[i] / 2; + } + } +} + +static void sr_1d53(int *p, int i0, int i1) +{ + int i; + + if (i1 == i0 + 1) + return; + + extend53(p, i0, i1); + + for (i = i0/2; i < i1/2 + 1; i++) + p[2*i] -= (p[2*i-1] + p[2*i+1] + 2) >> 2; + for (i = i0/2; i < i1/2; i++) + p[2*i+1] += (p[2*i] + p[2*i+2]) >> 1; +} + +static void dwt_decode53(DWTContext *s, int *t) +{ + int lev, + w = s->linelen[s->ndeclevels-1][0]; + int *line = s->linebuf; + line += 3; + + for (lev = 0; lev < s->ndeclevels; lev++){ + int lh = s->linelen[lev][0], + lv = s->linelen[lev][1], + mh = s->mod[lev][0], + mv = s->mod[lev][1], + lp; + int *l; + + // HOR_SD + l = line + mh; + for (lp = 0; lp < lv; lp++){ + int i, j = 0; + // copy with interleaving + for (i = mh; i < lh; i+=2, j++) + l[i] = t[w*lp + j]; + for (i = 1-mh; i < lh; i+=2, j++) + l[i] = t[w*lp + j]; + + sr_1d53(line, mh, mh + lh); + + for (i = 0; i < lh; i++) + t[w*lp + i] = l[i]; + } + + // VER_SD + l = line + mv; + for (lp = 0; lp < lh; lp++){ + int i, j = 0; + // copy with interleaving + for (i = mv; i < lv; i+=2, j++) + l[i] = t[w*j + lp]; + for (i = 1-mv; i < lv; i+=2, j++) + l[i] = t[w*j + lp]; + + sr_1d53(line, mv, mv + lv); + + for (i = 0; i < lv; i++) + t[w*i + lp] = l[i]; + } + } +} + +static void sr_1d97(float *p, int i0, int i1) +{ + int i; + + if (i1 == i0 + 1) + return; + + extend97(p, i0, i1); + + for (i = i0/2 - 1; i < i1/2 + 2; i++) + p[2*i] -= 0.443506 * (p[2*i-1] + p[2*i+1]); + for (i = i0/2 - 1; i < i1/2 + 1; i++) + p[2*i+1] -= 0.882911 * (p[2*i] + p[2*i+2]); + for (i = i0/2; i < i1/2 + 1; i++) + p[2*i] += 0.052980 * (p[2*i-1] + p[2*i+1]); + for (i = i0/2; i < i1/2; i++) + p[2*i+1] += 1.586134 * (p[2*i] + p[2*i+2]); +} + +static void dwt_decode97(DWTContext *s, int *t) +{ + int lev, + w = s->linelen[s->ndeclevels-1][0]; + float *line = s->linebuf; + line += 5; + + for (lev = 0; lev < s->ndeclevels; lev++){ + int lh = s->linelen[lev][0], + lv = s->linelen[lev][1], + mh = s->mod[lev][0], + mv = s->mod[lev][1], + lp; + float *l; + + // HOR_SD + l = line + mh; + for (lp = 0; lp < lv; lp++){ + int i, j = 0; + // copy with interleaving + for (i = mh; i < lh; i+=2, j++) + l[i] = scale97[1-mh] * t[w*lp + j]; + for (i = 1-mh; i < lh; i+=2, j++) + l[i] = scale97[1-mh] * t[w*lp + j]; + + sr_1d97(line, mh, mh + lh); + + for (i = 0; i < lh; i++) + t[w*lp + i] = l[i]; + } + + // VER_SD + l = line + mv; + for (lp = 0; lp < lh; lp++){ + int i, j = 0; + // copy with interleaving + for (i = mv; i < lv; i+=2, j++) + l[i] = scale97[1-mv] * t[w*j + lp]; + for (i = 1-mv; i < lv; i+=2, j++) + l[i] = scale97[1-mv] * t[w*j + lp]; + + sr_1d97(line, mv, mv + lv); + + for (i = 0; i < lv; i++) + t[w*i + lp] = l[i]; + } + } +} + +int ff_j2k_dwt_init(DWTContext *s, uint16_t border[2][2], int decomp_levels, int type) +{ + int i, j, lev = decomp_levels, maxlen, + b[2][2]; + + if ((unsigned)decomp_levels >= FF_DWT_MAX_DECLVLS) + return AVERROR_INVALIDDATA; + s->ndeclevels = decomp_levels; + s->type = type; + + for (i = 0; i < 2; i++) + for(j = 0; j < 2; j++) + b[i][j] = border[i][j]; + + maxlen = FFMAX(b[0][1] - b[0][0], + b[1][1] - b[1][0]); + + while(--lev >= 0){ + for (i = 0; i < 2; i++){ + s->linelen[lev][i] = b[i][1] - b[i][0]; + s->mod[lev][i] = b[i][0] & 1; + for (j = 0; j < 2; j++) + b[i][j] = (b[i][j] + 1) >> 1; + } + } + if (type == FF_DWT97) + s->linebuf = av_malloc((maxlen + 12) * sizeof(float)); + else if (type == FF_DWT53) + s->linebuf = av_malloc((maxlen + 6) * sizeof(int)); + else + return -1; + + if (!s->linebuf) + return AVERROR(ENOMEM); + + return 0; +} + +int ff_j2k_dwt_encode(DWTContext *s, int *t) +{ + switch(s->type){ + case FF_DWT97: + dwt_encode97(s, t); break; + case FF_DWT53: + dwt_encode53(s, t); break; + default: + return -1; + } + return 0; +} + +int ff_j2k_dwt_decode(DWTContext *s, int *t) +{ + switch(s->type){ + case FF_DWT97: + dwt_decode97(s, t); break; + case FF_DWT53: + dwt_decode53(s, t); break; + default: + return -1; + } + return 0; +} + +void ff_j2k_dwt_destroy(DWTContext *s) +{ + av_freep(&s->linebuf); +} diff --git a/ffmpeg/libavcodec/j2k_dwt.h b/ffmpeg/libavcodec/j2k_dwt.h new file mode 100644 index 0000000..a2a25a6 --- /dev/null +++ b/ffmpeg/libavcodec/j2k_dwt.h @@ -0,0 +1,63 @@ +/* + * Discrete wavelet transform + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +#ifndef AVCODEC_DWT_H +#define AVCODEC_DWT_H + +/** + * Discrete wavelet transform + * @file + * @author Kamil Nowosad + */ + +#include "avcodec.h" + +#define FF_DWT_MAX_DECLVLS 32 ///< max number of decomposition levels + +enum DWTType{ + FF_DWT97, + FF_DWT53 +}; + +typedef struct { + ///line lengths {horizontal, vertical} in consecutive decomposition levels + uint16_t linelen[FF_DWT_MAX_DECLVLS][2]; + uint8_t mod[FF_DWT_MAX_DECLVLS][2]; ///< coordinates (x0, y0) of decomp. levels mod 2 + uint8_t ndeclevels; ///< number of decomposition levels + uint8_t type; ///< 0 for 9/7; 1 for 5/3 + void *linebuf; ///< buffer used by transform (int or float) +} DWTContext; + +/** + * initialize DWT + * @param s DWT context + * @param border coordinates of transformed region {{x0, x1}, {y0, y1}} + * @param decomp_levels number of decomposition levels + * @param type 0 for DWT 9/7; 1 for DWT 5/3 + */ +int ff_j2k_dwt_init(DWTContext *s, uint16_t border[2][2], int decomp_levels, int type); + +int ff_j2k_dwt_encode(DWTContext *s, int *t); +int ff_j2k_dwt_decode(DWTContext *s, int *t); + +void ff_j2k_dwt_destroy(DWTContext *s); + +#endif /* AVCODEC_DWT_H */ diff --git a/ffmpeg/libavcodec/j2kdec.c b/ffmpeg/libavcodec/j2kdec.c new file mode 100644 index 0000000..6dcaf73 --- /dev/null +++ b/ffmpeg/libavcodec/j2kdec.c @@ -0,0 +1,1093 @@ +/* + * JPEG2000 image decoder + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * JPEG2000 image decoder + * @file + * @author Kamil Nowosad + */ + +// #define DEBUG + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "j2k.h" +#include "libavutil/common.h" + +#define JP2_SIG_TYPE 0x6A502020 +#define JP2_SIG_VALUE 0x0D0A870A +#define JP2_CODESTREAM 0x6A703263 + +#define HAD_COC 0x01 +#define HAD_QCC 0x02 + +typedef struct { + J2kComponent *comp; + uint8_t properties[4]; + J2kCodingStyle codsty[4]; + J2kQuantStyle qntsty[4]; +} J2kTile; + +typedef struct { + AVCodecContext *avctx; + AVFrame *picture; + GetByteContext g; + + int width, height; ///< image width and height + int image_offset_x, image_offset_y; + int tile_offset_x, tile_offset_y; + uint8_t cbps[4]; ///< bits per sample in particular components + uint8_t sgnd[4]; ///< if a component is signed + uint8_t properties[4]; + int cdx[4], cdy[4]; + int precision; + int ncomponents; + int tile_width, tile_height; ///< tile size + int numXtiles, numYtiles; + int maxtilelen; + + J2kCodingStyle codsty[4]; + J2kQuantStyle qntsty[4]; + + int bit_index; + + int curtileno; + + J2kTile *tile; +} J2kDecoderContext; + +static int get_bits(J2kDecoderContext *s, int n) +{ + int res = 0; + + while (--n >= 0){ + res <<= 1; + if (s->bit_index == 0) { + s->bit_index = 7 + (bytestream2_get_byte(&s->g) != 0xFFu); + } + s->bit_index--; + res |= (bytestream2_peek_byte(&s->g) >> s->bit_index) & 1; + } + return res; +} + +static void j2k_flush(J2kDecoderContext *s) +{ + if (bytestream2_get_byte(&s->g) == 0xff) + bytestream2_skip(&s->g, 1); + s->bit_index = 8; +} +#if 0 +void printcomp(J2kComponent *comp) +{ + int i; + for (i = 0; i < comp->y1 - comp->y0; i++) + ff_j2k_printv(comp->data + i * (comp->x1 - comp->x0), comp->x1 - comp->x0); +} + +static void nspaces(FILE *fd, int n) +{ + while(n--) putc(' ', fd); +} + +static void dump(J2kDecoderContext *s, FILE *fd) +{ + int tileno, compno, reslevelno, bandno, precno; + fprintf(fd, "XSiz = %d, YSiz = %d, tile_width = %d, tile_height = %d\n" + "numXtiles = %d, numYtiles = %d, ncomponents = %d\n" + "tiles:\n", + s->width, s->height, s->tile_width, s->tile_height, + s->numXtiles, s->numYtiles, s->ncomponents); + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + J2kTile *tile = s->tile + tileno; + nspaces(fd, 2); + fprintf(fd, "tile %d:\n", tileno); + for(compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + nspaces(fd, 4); + fprintf(fd, "component %d:\n", compno); + nspaces(fd, 4); + fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d\n", + comp->x0, comp->x1, comp->y0, comp->y1); + for(reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + J2kResLevel *reslevel = comp->reslevel + reslevelno; + nspaces(fd, 6); + fprintf(fd, "reslevel %d:\n", reslevelno); + nspaces(fd, 6); + fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d, nbands = %d\n", + reslevel->x0, reslevel->x1, reslevel->y0, + reslevel->y1, reslevel->nbands); + for(bandno = 0; bandno < reslevel->nbands; bandno++){ + J2kBand *band = reslevel->band + bandno; + nspaces(fd, 8); + fprintf(fd, "band %d:\n", bandno); + nspaces(fd, 8); + fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d," + "codeblock_width = %d, codeblock_height = %d cblknx = %d cblkny = %d\n", + band->x0, band->x1, + band->y0, band->y1, + band->codeblock_width, band->codeblock_height, + band->cblknx, band->cblkny); + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + J2kPrec *prec = band->prec + precno; + nspaces(fd, 10); + fprintf(fd, "prec %d:\n", precno); + nspaces(fd, 10); + fprintf(fd, "xi0 = %d, xi1 = %d, yi0 = %d, yi1 = %d\n", + prec->xi0, prec->xi1, prec->yi0, prec->yi1); + } + } + } + } + } +} +#endif + +/** decode the value stored in node */ +static int tag_tree_decode(J2kDecoderContext *s, J2kTgtNode *node, int threshold) +{ + J2kTgtNode *stack[30]; + int sp = -1, curval = 0; + + if(!node) + return AVERROR(EINVAL); + + while(node && !node->vis){ + stack[++sp] = node; + node = node->parent; + } + + if (node) + curval = node->val; + else + curval = stack[sp]->val; + + while(curval < threshold && sp >= 0){ + if (curval < stack[sp]->val) + curval = stack[sp]->val; + while (curval < threshold){ + int ret; + if ((ret = get_bits(s, 1)) > 0){ + stack[sp]->vis++; + break; + } else if (!ret) + curval++; + else + return ret; + } + stack[sp]->val = curval; + sp--; + } + return curval; +} + +/* marker segments */ +/** get sizes and offsets of image, tiles; number of components */ +static int get_siz(J2kDecoderContext *s) +{ + int i, ret; + + if (bytestream2_get_bytes_left(&s->g) < 36) + return AVERROR(EINVAL); + + bytestream2_get_be16u(&s->g); // Rsiz (skipped) + s->width = bytestream2_get_be32u(&s->g); // width + s->height = bytestream2_get_be32u(&s->g); // height + s->image_offset_x = bytestream2_get_be32u(&s->g); // X0Siz + s->image_offset_y = bytestream2_get_be32u(&s->g); // Y0Siz + + s->tile_width = bytestream2_get_be32u(&s->g); // XTSiz + s->tile_height = bytestream2_get_be32u(&s->g); // YTSiz + s->tile_offset_x = bytestream2_get_be32u(&s->g); // XT0Siz + s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz + s->ncomponents = bytestream2_get_be16u(&s->g); // CSiz + + if(s->ncomponents <= 0 || s->ncomponents > 4) { + av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents); + return AVERROR(EINVAL); + } + if(s->tile_width<=0 || s->tile_height<=0) + return AVERROR(EINVAL); + + if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents) + return AVERROR(EINVAL); + + for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i + uint8_t x = bytestream2_get_byteu(&s->g); + s->cbps[i] = (x & 0x7f) + 1; + s->precision = FFMAX(s->cbps[i], s->precision); + s->sgnd[i] = !!(x & 0x80); + s->cdx[i] = bytestream2_get_byteu(&s->g); + s->cdy[i] = bytestream2_get_byteu(&s->g); + } + + s->numXtiles = ff_j2k_ceildiv(s->width - s->tile_offset_x, s->tile_width); + s->numYtiles = ff_j2k_ceildiv(s->height - s->tile_offset_y, s->tile_height); + + if(s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(J2kTile)) + return AVERROR(EINVAL); + + s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(J2kTile)); + if (!s->tile) + return AVERROR(ENOMEM); + + for (i = 0; i < s->numXtiles * s->numYtiles; i++){ + J2kTile *tile = s->tile + i; + + tile->comp = av_mallocz(s->ncomponents * sizeof(J2kComponent)); + if (!tile->comp) + return AVERROR(ENOMEM); + } + + s->avctx->width = s->width - s->image_offset_x; + s->avctx->height = s->height - s->image_offset_y; + + switch(s->ncomponents){ + case 1: + if (s->precision > 8) { + s->avctx->pix_fmt = AV_PIX_FMT_GRAY16; + } else { + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + } + break; + case 3: + if (s->precision > 8) { + s->avctx->pix_fmt = AV_PIX_FMT_RGB48; + } else { + s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + } + break; + case 4: + s->avctx->pix_fmt = AV_PIX_FMT_RGBA; + break; + } + + + if ((ret = ff_get_buffer(s->avctx, s->picture, 0)) < 0) + return ret; + + s->picture->pict_type = AV_PICTURE_TYPE_I; + s->picture->key_frame = 1; + + return 0; +} + +/** get common part for COD and COC segments */ +static int get_cox(J2kDecoderContext *s, J2kCodingStyle *c) +{ + if (bytestream2_get_bytes_left(&s->g) < 5) + return AVERROR(EINVAL); + c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1 + c->log2_cblk_width = bytestream2_get_byteu(&s->g) + 2; // cblk width + c->log2_cblk_height = bytestream2_get_byteu(&s->g) + 2; // cblk height + + c->cblk_style = bytestream2_get_byteu(&s->g); + if (c->cblk_style != 0){ // cblk style + av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style); + } + c->transform = bytestream2_get_byteu(&s->g); // transformation + if (c->csty & J2K_CSTY_PREC) { + int i; + + for (i = 0; i < c->nreslevels; i++) + bytestream2_get_byte(&s->g); + } + return 0; +} + +/** get coding parameters for a particular tile or whole image*/ +static int get_cod(J2kDecoderContext *s, J2kCodingStyle *c, uint8_t *properties) +{ + J2kCodingStyle tmp; + int compno; + + if (bytestream2_get_bytes_left(&s->g) < 5) + return AVERROR(EINVAL); + + tmp.log2_prec_width = + tmp.log2_prec_height = 15; + + tmp.csty = bytestream2_get_byteu(&s->g); + + if (bytestream2_get_byteu(&s->g)){ // progression level + av_log(s->avctx, AV_LOG_ERROR, "only LRCP progression supported\n"); + return -1; + } + + tmp.nlayers = bytestream2_get_be16u(&s->g); + tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation + + get_cox(s, &tmp); + for (compno = 0; compno < s->ncomponents; compno++){ + if (!(properties[compno] & HAD_COC)) + memcpy(c + compno, &tmp, sizeof(J2kCodingStyle)); + } + return 0; +} + +/** get coding parameters for a component in the whole image on a particular tile */ +static int get_coc(J2kDecoderContext *s, J2kCodingStyle *c, uint8_t *properties) +{ + int compno; + + if (bytestream2_get_bytes_left(&s->g) < 2) + return AVERROR(EINVAL); + + compno = bytestream2_get_byteu(&s->g); + + c += compno; + c->csty = bytestream2_get_byte(&s->g); + get_cox(s, c); + + properties[compno] |= HAD_COC; + return 0; +} + +/** get common part for QCD and QCC segments */ +static int get_qcx(J2kDecoderContext *s, int n, J2kQuantStyle *q) +{ + int i, x; + + if (bytestream2_get_bytes_left(&s->g) < 1) + return AVERROR(EINVAL); + + x = bytestream2_get_byteu(&s->g); // Sqcd + + q->nguardbits = x >> 5; + q->quantsty = x & 0x1f; + + if (q->quantsty == J2K_QSTY_NONE){ + n -= 3; + if (bytestream2_get_bytes_left(&s->g) < n || 32*3 < n) + return AVERROR(EINVAL); + for (i = 0; i < n; i++) + q->expn[i] = bytestream2_get_byteu(&s->g) >> 3; + } else if (q->quantsty == J2K_QSTY_SI){ + if (bytestream2_get_bytes_left(&s->g) < 2) + return AVERROR(EINVAL); + x = bytestream2_get_be16u(&s->g); + q->expn[0] = x >> 11; + q->mant[0] = x & 0x7ff; + for (i = 1; i < 32 * 3; i++){ + int curexpn = FFMAX(0, q->expn[0] - (i-1)/3); + q->expn[i] = curexpn; + q->mant[i] = q->mant[0]; + } + } else{ + n = (n - 3) >> 1; + if (bytestream2_get_bytes_left(&s->g) < 2 * n || 32*3 < n) + return AVERROR(EINVAL); + for (i = 0; i < n; i++){ + x = bytestream2_get_be16u(&s->g); + q->expn[i] = x >> 11; + q->mant[i] = x & 0x7ff; + } + } + return 0; +} + +/** get quantization parameters for a particular tile or a whole image */ +static int get_qcd(J2kDecoderContext *s, int n, J2kQuantStyle *q, uint8_t *properties) +{ + J2kQuantStyle tmp; + int compno; + + if (get_qcx(s, n, &tmp)) + return -1; + for (compno = 0; compno < s->ncomponents; compno++) + if (!(properties[compno] & HAD_QCC)) + memcpy(q + compno, &tmp, sizeof(J2kQuantStyle)); + return 0; +} + +/** get quantization parameters for a component in the whole image on in a particular tile */ +static int get_qcc(J2kDecoderContext *s, int n, J2kQuantStyle *q, uint8_t *properties) +{ + int compno; + + if (bytestream2_get_bytes_left(&s->g) < 1) + return AVERROR(EINVAL); + + compno = bytestream2_get_byteu(&s->g); + properties[compno] |= HAD_QCC; + return get_qcx(s, n-1, q+compno); +} + +/** get start of tile segment */ +static uint8_t get_sot(J2kDecoderContext *s) +{ + if (bytestream2_get_bytes_left(&s->g) < 8) + return AVERROR(EINVAL); + + s->curtileno = bytestream2_get_be16u(&s->g); ///< Isot + if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){ + s->curtileno=0; + return AVERROR(EINVAL); + } + + bytestream2_skipu(&s->g, 4); ///< Psot (ignored) + + if (!bytestream2_get_byteu(&s->g)){ ///< TPsot + J2kTile *tile = s->tile + s->curtileno; + + /* copy defaults */ + memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(J2kCodingStyle)); + memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(J2kQuantStyle)); + } + bytestream2_get_byteu(&s->g); ///< TNsot + + return 0; +} + +static int init_tile(J2kDecoderContext *s, int tileno) +{ + int compno, + tilex = tileno % s->numXtiles, + tiley = tileno / s->numXtiles; + J2kTile *tile = s->tile + tileno; + + if (!tile->comp) + return AVERROR(ENOMEM); + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + J2kCodingStyle *codsty = tile->codsty + compno; + J2kQuantStyle *qntsty = tile->qntsty + compno; + int ret; // global bandno + + comp->coord[0][0] = FFMAX(tilex * s->tile_width + s->tile_offset_x, s->image_offset_x); + comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width + s->tile_offset_x, s->width); + comp->coord[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y); + comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height + s->tile_offset_y, s->height); + + if (ret = ff_j2k_init_component(comp, codsty, qntsty, s->cbps[compno], s->cdx[compno], s->cdy[compno])) + return ret; + } + return 0; +} + +/** read the number of coding passes */ +static int getnpasses(J2kDecoderContext *s) +{ + int num; + if (!get_bits(s, 1)) + return 1; + if (!get_bits(s, 1)) + return 2; + if ((num = get_bits(s, 2)) != 3) + return num < 0 ? num : 3 + num; + if ((num = get_bits(s, 5)) != 31) + return num < 0 ? num : 6 + num; + num = get_bits(s, 7); + return num < 0 ? num : 37 + num; +} + +static int getlblockinc(J2kDecoderContext *s) +{ + int res = 0, ret; + while (ret = get_bits(s, 1)){ + if (ret < 0) + return ret; + res++; + } + return res; +} + +static int decode_packet(J2kDecoderContext *s, J2kCodingStyle *codsty, J2kResLevel *rlevel, int precno, + int layno, uint8_t *expn, int numgbits) +{ + int bandno, cblkny, cblknx, cblkno, ret; + + if (!(ret = get_bits(s, 1))){ + j2k_flush(s); + return 0; + } else if (ret < 0) + return ret; + + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + J2kBand *band = rlevel->band + bandno; + J2kPrec *prec = band->prec + precno; + int pos = 0; + + if (band->coord[0][0] == band->coord[0][1] + || band->coord[1][0] == band->coord[1][1]) + continue; + + for (cblkny = prec->yi0; cblkny < prec->yi1; cblkny++) + for(cblknx = prec->xi0, cblkno = cblkny * band->cblknx + cblknx; cblknx < prec->xi1; cblknx++, cblkno++, pos++){ + J2kCblk *cblk = band->cblk + cblkno; + int incl, newpasses, llen; + + if (cblk->npasses) + incl = get_bits(s, 1); + else + incl = tag_tree_decode(s, prec->cblkincl + pos, layno+1) == layno; + if (!incl) + continue; + else if (incl < 0) + return incl; + + if (!cblk->npasses) + cblk->nonzerobits = expn[bandno] + numgbits - 1 - tag_tree_decode(s, prec->zerobits + pos, 100); + if ((newpasses = getnpasses(s)) < 0) + return newpasses; + if ((llen = getlblockinc(s)) < 0) + return llen; + cblk->lblock += llen; + if ((ret = get_bits(s, av_log2(newpasses) + cblk->lblock)) < 0) + return ret; + cblk->lengthinc = ret; + cblk->npasses += newpasses; + } + } + j2k_flush(s); + + if (codsty->csty & J2K_CSTY_EPH) { + if (bytestream2_peek_be16(&s->g) == J2K_EPH) { + bytestream2_skip(&s->g, 2); + } else { + av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found.\n"); + } + } + + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + J2kBand *band = rlevel->band + bandno; + int yi, cblknw = band->prec[precno].xi1 - band->prec[precno].xi0; + for (yi = band->prec[precno].yi0; yi < band->prec[precno].yi1; yi++){ + int xi; + for (xi = band->prec[precno].xi0; xi < band->prec[precno].xi1; xi++){ + J2kCblk *cblk = band->cblk + yi * cblknw + xi; + if (bytestream2_get_bytes_left(&s->g) < cblk->lengthinc) + return AVERROR(EINVAL); + bytestream2_get_bufferu(&s->g, cblk->data, cblk->lengthinc); + cblk->length += cblk->lengthinc; + cblk->lengthinc = 0; + } + } + } + return 0; +} + +static int decode_packets(J2kDecoderContext *s, J2kTile *tile) +{ + int layno, reslevelno, compno, precno, ok_reslevel; + s->bit_index = 8; + for (layno = 0; layno < tile->codsty[0].nlayers; layno++){ + ok_reslevel = 1; + for (reslevelno = 0; ok_reslevel; reslevelno++){ + ok_reslevel = 0; + for (compno = 0; compno < s->ncomponents; compno++){ + J2kCodingStyle *codsty = tile->codsty + compno; + J2kQuantStyle *qntsty = tile->qntsty + compno; + if (reslevelno < codsty->nreslevels){ + J2kResLevel *rlevel = tile->comp[compno].reslevel + reslevelno; + ok_reslevel = 1; + for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++){ + if (decode_packet(s, codsty, rlevel, precno, layno, qntsty->expn + + (reslevelno ? 3*(reslevelno-1)+1 : 0), qntsty->nguardbits)) + return -1; + } + } + } + } + } + return 0; +} + +/* TIER-1 routines */ +static void decode_sigpass(J2kT1Context *t1, int width, int height, int bpno, int bandno, int bpass_csty_symbol, + int vert_causal_ctx_csty_symbol) +{ + int mask = 3 << (bpno - 1), y0, x, y; + + for (y0 = 0; y0 < height; y0 += 4) + for (x = 0; x < width; x++) + for (y = y0; y < height && y < y0+4; y++){ + if ((t1->flags[y+1][x+1] & J2K_T1_SIG_NB) + && !(t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS))){ + int vert_causal_ctx_csty_loc_symbol = vert_causal_ctx_csty_symbol && (x == 3 && y == 3); + if (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_j2k_getnbctxno(t1->flags[y+1][x+1], bandno, + vert_causal_ctx_csty_loc_symbol))){ + int xorbit, ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit); + if (bpass_csty_symbol) + t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask; + else + t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ? + -mask : mask; + + ff_j2k_set_significant(t1, x, y, t1->data[y][x] < 0); + } + t1->flags[y+1][x+1] |= J2K_T1_VIS; + } + } +} + +static void decode_refpass(J2kT1Context *t1, int width, int height, int bpno) +{ + int phalf, nhalf; + int y0, x, y; + + phalf = 1 << (bpno - 1); + nhalf = -phalf; + + for (y0 = 0; y0 < height; y0 += 4) + for (x = 0; x < width; x++) + for (y = y0; y < height && y < y0+4; y++){ + if ((t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS)) == J2K_T1_SIG){ + int ctxno = ff_j2k_getrefctxno(t1->flags[y+1][x+1]); + int r = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? phalf : nhalf; + t1->data[y][x] += t1->data[y][x] < 0 ? -r : r; + t1->flags[y+1][x+1] |= J2K_T1_REF; + } + } +} + +static void decode_clnpass(J2kDecoderContext *s, J2kT1Context *t1, int width, int height, + int bpno, int bandno, int seg_symbols) +{ + int mask = 3 << (bpno - 1), y0, x, y, runlen, dec; + + for (y0 = 0; y0 < height; y0 += 4) { + for (x = 0; x < width; x++){ + if (y0 + 3 < height && !( + (t1->flags[y0+1][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) || + (t1->flags[y0+2][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) || + (t1->flags[y0+3][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) || + (t1->flags[y0+4][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)))){ + if (!ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_RL)) + continue; + runlen = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); + runlen = (runlen << 1) | ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); + dec = 1; + } else{ + runlen = 0; + dec = 0; + } + + for (y = y0 + runlen; y < y0 + 4 && y < height; y++){ + if (!dec){ + if (!(t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS))) + dec = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_j2k_getnbctxno(t1->flags[y+1][x+1], + bandno, 0)); + } + if (dec){ + int xorbit, ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit); + t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ? -mask : mask; + ff_j2k_set_significant(t1, x, y, t1->data[y][x] < 0); + } + dec = 0; + t1->flags[y+1][x+1] &= ~J2K_T1_VIS; + } + } + } + if (seg_symbols) { + int val; + val = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); + val = (val << 1) + ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); + val = (val << 1) + ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); + val = (val << 1) + ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); + if (val != 0xa) { + av_log(s->avctx, AV_LOG_ERROR,"Segmentation symbol value incorrect\n"); + } + } +} + +static int decode_cblk(J2kDecoderContext *s, J2kCodingStyle *codsty, J2kT1Context *t1, J2kCblk *cblk, + int width, int height, int bandpos) +{ + int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y, clnpass_cnt = 0; + int bpass_csty_symbol = J2K_CBLK_BYPASS & codsty->cblk_style; + int vert_causal_ctx_csty_symbol = J2K_CBLK_VSC & codsty->cblk_style; + + for (y = 0; y < height+2; y++) + memset(t1->flags[y], 0, (width+2)*sizeof(int)); + + for (y = 0; y < height; y++) + memset(t1->data[y], 0, width*sizeof(int)); + + cblk->data[cblk->length] = 0xff; + cblk->data[cblk->length+1] = 0xff; + ff_mqc_initdec(&t1->mqc, cblk->data); + + while(passno--){ + switch(pass_t){ + case 0: decode_sigpass(t1, width, height, bpno+1, bandpos, + bpass_csty_symbol && (clnpass_cnt >= 4), vert_causal_ctx_csty_symbol); + break; + case 1: decode_refpass(t1, width, height, bpno+1); + if (bpass_csty_symbol && clnpass_cnt >= 4) + ff_mqc_initdec(&t1->mqc, cblk->data); + break; + case 2: decode_clnpass(s, t1, width, height, bpno+1, bandpos, + codsty->cblk_style & J2K_CBLK_SEGSYM); + clnpass_cnt = clnpass_cnt + 1; + if (bpass_csty_symbol && clnpass_cnt >= 4) + ff_mqc_initdec(&t1->mqc, cblk->data); + break; + } + + pass_t++; + if (pass_t == 3){ + bpno--; + pass_t = 0; + } + } + return 0; +} + +static void mct_decode(J2kDecoderContext *s, J2kTile *tile) +{ + int i, *src[3], i0, i1, i2, csize = 1; + + for (i = 0; i < 3; i++) + src[i] = tile->comp[i].data; + + for (i = 0; i < 2; i++) + csize *= tile->comp[0].coord[i][1] - tile->comp[0].coord[i][0]; + + if (tile->codsty[0].transform == FF_DWT97){ + for (i = 0; i < csize; i++){ + i0 = *src[0] + (*src[2] * 46802 >> 16); + i1 = *src[0] - (*src[1] * 22553 + *src[2] * 46802 >> 16); + i2 = *src[0] + (116130 * *src[1] >> 16); + *src[0]++ = i0; + *src[1]++ = i1; + *src[2]++ = i2; + } + } else{ + for (i = 0; i < csize; i++){ + i1 = *src[0] - (*src[2] + *src[1] >> 2); + i0 = i1 + *src[2]; + i2 = i1 + *src[1]; + *src[0]++ = i0; + *src[1]++ = i1; + *src[2]++ = i2; + } + } +} + +static int decode_tile(J2kDecoderContext *s, J2kTile *tile) +{ + int compno, reslevelno, bandno; + int x, y, *src[4]; + uint8_t *line; + J2kT1Context t1; + + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + J2kCodingStyle *codsty = tile->codsty + compno; + + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + J2kResLevel *rlevel = comp->reslevel + reslevelno; + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + J2kBand *band = rlevel->band + bandno; + int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos; + + bandpos = bandno + (reslevelno > 0); + + yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0]; + y0 = yy0; + yy1 = FFMIN(ff_j2k_ceildiv(band->coord[1][0] + 1, band->codeblock_height) * band->codeblock_height, + band->coord[1][1]) - band->coord[1][0] + yy0; + + if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1]) + continue; + + for (cblky = 0; cblky < band->cblkny; cblky++){ + if (reslevelno == 0 || bandno == 1) + xx0 = 0; + else + xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0]; + x0 = xx0; + xx1 = FFMIN(ff_j2k_ceildiv(band->coord[0][0] + 1, band->codeblock_width) * band->codeblock_width, + band->coord[0][1]) - band->coord[0][0] + xx0; + + for (cblkx = 0; cblkx < band->cblknx; cblkx++, cblkno++){ + int y, x; + decode_cblk(s, codsty, &t1, band->cblk + cblkno, xx1 - xx0, yy1 - yy0, bandpos); + if (codsty->transform == FF_DWT53){ + for (y = yy0; y < yy1; y+=s->cdy[compno]){ + int *ptr = t1.data[y-yy0]; + for (x = xx0; x < xx1; x+=s->cdx[compno]){ + comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] = *ptr++ >> 1; + } + } + } else{ + for (y = yy0; y < yy1; y+=s->cdy[compno]){ + int *ptr = t1.data[y-yy0]; + for (x = xx0; x < xx1; x+=s->cdx[compno]){ + int tmp = ((int64_t)*ptr++) * ((int64_t)band->stepsize) >> 13, tmp2; + tmp2 = FFABS(tmp>>1) + (tmp&1); + comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] = tmp < 0 ? -tmp2 : tmp2; + } + } + } + xx0 = xx1; + xx1 = FFMIN(xx1 + band->codeblock_width, band->coord[0][1] - band->coord[0][0] + x0); + } + yy0 = yy1; + yy1 = FFMIN(yy1 + band->codeblock_height, band->coord[1][1] - band->coord[1][0] + y0); + } + } + } + ff_j2k_dwt_decode(&comp->dwt, comp->data); + src[compno] = comp->data; + } + if (tile->codsty[0].mct) + mct_decode(s, tile); + + if (s->precision <= 8) { + for (compno = 0; compno < s->ncomponents; compno++){ + y = tile->comp[compno].coord[1][0] - s->image_offset_y; + line = s->picture->data[0] + y * s->picture->linesize[0]; + for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]){ + uint8_t *dst; + + x = tile->comp[compno].coord[0][0] - s->image_offset_x; + dst = line + x * s->ncomponents + compno; + + for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s->cdx[compno]) { + *src[compno] += 1 << (s->cbps[compno]-1); + if (*src[compno] < 0) + *src[compno] = 0; + else if (*src[compno] >= (1 << s->cbps[compno])) + *src[compno] = (1 << s->cbps[compno]) - 1; + *dst = *src[compno]++; + dst += s->ncomponents; + } + line += s->picture->linesize[0]; + } + } + } else { + for (compno = 0; compno < s->ncomponents; compno++) { + y = tile->comp[compno].coord[1][0] - s->image_offset_y; + line = s->picture->data[0] + y * s->picture->linesize[0]; + for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) { + uint16_t *dst; + + x = tile->comp[compno].coord[0][0] - s->image_offset_x; + dst = (uint16_t *)(line + (x * s->ncomponents + compno) * 2); + for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s-> cdx[compno]) { + int32_t val; + + val = *src[compno]++ << (16 - s->cbps[compno]); + val += 1 << 15; + val = av_clip(val, 0, (1 << 16) - 1); + *dst = val; + dst += s->ncomponents; + } + line += s->picture->linesize[0]; + } + } + } + return 0; +} + +static void cleanup(J2kDecoderContext *s) +{ + int tileno, compno; + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = s->tile[tileno].comp + compno; + J2kCodingStyle *codsty = s->tile[tileno].codsty + compno; + + ff_j2k_cleanup(comp, codsty); + } + av_freep(&s->tile[tileno].comp); + } + av_freep(&s->tile); +} + +static int decode_codestream(J2kDecoderContext *s) +{ + J2kCodingStyle *codsty = s->codsty; + J2kQuantStyle *qntsty = s->qntsty; + uint8_t *properties = s->properties; + + for (;;){ + int oldpos, marker, len, ret = 0; + + if (bytestream2_get_bytes_left(&s->g) < 2){ + av_log(s->avctx, AV_LOG_ERROR, "Missing EOC\n"); + break; + } + + marker = bytestream2_get_be16u(&s->g); + av_dlog(s->avctx, "marker 0x%.4X at pos 0x%x\n", marker, bytestream2_tell(&s->g) - 4); + oldpos = bytestream2_tell(&s->g); + + if (marker == J2K_SOD){ + J2kTile *tile = s->tile + s->curtileno; + if (ret = init_tile(s, s->curtileno)) { + av_log(s->avctx, AV_LOG_ERROR, "tile initialization failed\n"); + return ret; + } + if (ret = decode_packets(s, tile)) { + av_log(s->avctx, AV_LOG_ERROR, "packets decoding failed\n"); + return ret; + } + continue; + } + if (marker == J2K_EOC) + break; + + if (bytestream2_get_bytes_left(&s->g) < 2) + return AVERROR(EINVAL); + len = bytestream2_get_be16u(&s->g); + switch (marker){ + case J2K_SIZ: + ret = get_siz(s); + break; + case J2K_COC: + ret = get_coc(s, codsty, properties); + break; + case J2K_COD: + ret = get_cod(s, codsty, properties); + break; + case J2K_QCC: + ret = get_qcc(s, len, qntsty, properties); + break; + case J2K_QCD: + ret = get_qcd(s, len, qntsty, properties); + break; + case J2K_SOT: + if (!(ret = get_sot(s))){ + codsty = s->tile[s->curtileno].codsty; + qntsty = s->tile[s->curtileno].qntsty; + properties = s->tile[s->curtileno].properties; + } + break; + case J2K_COM: + // the comment is ignored + bytestream2_skip(&s->g, len - 2); + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "unsupported marker 0x%.4X at pos 0x%x\n", marker, bytestream2_tell(&s->g) - 4); + bytestream2_skip(&s->g, len - 2); + break; + } + if (bytestream2_tell(&s->g) - oldpos != len || ret){ + av_log(s->avctx, AV_LOG_ERROR, "error during processing marker segment %.4x\n", marker); + return ret ? ret : -1; + } + } + return 0; +} + +static int jp2_find_codestream(J2kDecoderContext *s) +{ + uint32_t atom_size, atom; + int found_codestream = 0, search_range = 10; + + while(!found_codestream && search_range && bytestream2_get_bytes_left(&s->g) >= 8) { + atom_size = bytestream2_get_be32u(&s->g); + atom = bytestream2_get_be32u(&s->g); + if (atom == JP2_CODESTREAM) { + found_codestream = 1; + } else { + if (bytestream2_get_bytes_left(&s->g) < atom_size - 8) + return 0; + bytestream2_skipu(&s->g, atom_size - 8); + search_range--; + } + } + + if (found_codestream) + return 1; + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + J2kDecoderContext *s = avctx->priv_data; + AVFrame *picture = data; + int tileno, ret; + + s->picture = picture; + + bytestream2_init(&s->g, avpkt->data, avpkt->size); + s->curtileno = -1; + + if (bytestream2_get_bytes_left(&s->g) < 2) { + ret = AVERROR(EINVAL); + goto err_out; + } + + // check if the image is in jp2 format + if (bytestream2_get_bytes_left(&s->g) >= 12 && + (bytestream2_get_be32u(&s->g) == 12) && + (bytestream2_get_be32u(&s->g) == JP2_SIG_TYPE) && + (bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) { + if(!jp2_find_codestream(s)) { + av_log(avctx, AV_LOG_ERROR, "couldn't find jpeg2k codestream atom\n"); + ret = -1; + goto err_out; + } + } else { + bytestream2_seek(&s->g, 0, SEEK_SET); + } + + if (bytestream2_get_be16u(&s->g) != J2K_SOC){ + av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n"); + ret = -1; + goto err_out; + } + if (ret = decode_codestream(s)) + goto err_out; + + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++) + if (ret = decode_tile(s, s->tile + tileno)) + goto err_out; + + cleanup(s); + + *got_frame = 1; + + return bytestream2_tell(&s->g); + +err_out: + cleanup(s); + return ret; +} + +static av_cold int j2kdec_init(AVCodecContext *avctx) +{ + J2kDecoderContext *s = avctx->priv_data; + + s->avctx = avctx; + + ff_j2k_init_tier1_luts(); + + return 0; +} + +AVCodec ff_jpeg2000_decoder = { + .name = "j2k", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEG2000, + .priv_data_size = sizeof(J2kDecoderContext), + .init = j2kdec_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_EXPERIMENTAL, + .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), +}; diff --git a/ffmpeg/libavcodec/j2kenc.c b/ffmpeg/libavcodec/j2kenc.c new file mode 100644 index 0000000..5d447ed --- /dev/null +++ b/ffmpeg/libavcodec/j2kenc.c @@ -0,0 +1,1046 @@ +/* + * JPEG2000 image encoder + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * JPEG2000 image encoder + * @file + * @author Kamil Nowosad + */ + +#include +#include "avcodec.h" +#include "internal.h" +#include "bytestream.h" +#include "j2k.h" +#include "libavutil/common.h" + +#define NMSEDEC_BITS 7 +#define NMSEDEC_FRACBITS (NMSEDEC_BITS-1) +#define WMSEDEC_SHIFT 13 ///< must be >= 13 +#define LAMBDA_SCALE (100000000LL << (WMSEDEC_SHIFT - 13)) + +static int lut_nmsedec_ref [1<y1 - comp->y0; i++) + ff_j2k_printv(comp->data + i * (comp->x1 - comp->x0), comp->x1 - comp->x0); +} + +static void dump(J2kEncoderContext *s, FILE *fd) +{ + int tileno, compno, reslevelno, bandno, precno; + fprintf(fd, "XSiz = %d, YSiz = %d, tile_width = %d, tile_height = %d\n" + "numXtiles = %d, numYtiles = %d, ncomponents = %d\n" + "tiles:\n", + s->width, s->height, s->tile_width, s->tile_height, + s->numXtiles, s->numYtiles, s->ncomponents); + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + J2kTile *tile = s->tile + tileno; + nspaces(fd, 2); + fprintf(fd, "tile %d:\n", tileno); + for(compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + nspaces(fd, 4); + fprintf(fd, "component %d:\n", compno); + nspaces(fd, 4); + fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d\n", + comp->x0, comp->x1, comp->y0, comp->y1); + for(reslevelno = 0; reslevelno < s->nreslevels; reslevelno++){ + J2kResLevel *reslevel = comp->reslevel + reslevelno; + nspaces(fd, 6); + fprintf(fd, "reslevel %d:\n", reslevelno); + nspaces(fd, 6); + fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d, nbands = %d\n", + reslevel->x0, reslevel->x1, reslevel->y0, + reslevel->y1, reslevel->nbands); + for(bandno = 0; bandno < reslevel->nbands; bandno++){ + J2kBand *band = reslevel->band + bandno; + nspaces(fd, 8); + fprintf(fd, "band %d:\n", bandno); + nspaces(fd, 8); + fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d," + "codeblock_width = %d, codeblock_height = %d cblknx = %d cblkny = %d\n", + band->x0, band->x1, + band->y0, band->y1, + band->codeblock_width, band->codeblock_height, + band->cblknx, band->cblkny); + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + J2kPrec *prec = band->prec + precno; + nspaces(fd, 10); + fprintf(fd, "prec %d:\n", precno); + nspaces(fd, 10); + fprintf(fd, "xi0 = %d, xi1 = %d, yi0 = %d, yi1 = %d\n", + prec->xi0, prec->xi1, prec->yi0, prec->yi1); + } + } + } + } + } +} +#endif + +/* bitstream routines */ + +/** put n times val bit */ +static void put_bits(J2kEncoderContext *s, int val, int n) // TODO: optimize +{ + while (n-- > 0){ + if (s->bit_index == 8) + { + s->bit_index = *s->buf == 0xff; + *(++s->buf) = 0; + } + *s->buf |= val << (7 - s->bit_index++); + } +} + +/** put n least significant bits of a number num */ +static void put_num(J2kEncoderContext *s, int num, int n) +{ + while(--n >= 0) + put_bits(s, (num >> n) & 1, 1); +} + +/** flush the bitstream */ +static void j2k_flush(J2kEncoderContext *s) +{ + if (s->bit_index){ + s->bit_index = 0; + s->buf++; + } +} + +/* tag tree routines */ + +/** code the value stored in node */ +static void tag_tree_code(J2kEncoderContext *s, J2kTgtNode *node, int threshold) +{ + J2kTgtNode *stack[30]; + int sp = 1, curval = 0; + stack[0] = node; + + node = node->parent; + while(node){ + if (node->vis){ + curval = node->val; + break; + } + node->vis++; + stack[sp++] = node; + node = node->parent; + } + while(--sp >= 0){ + if (stack[sp]->val >= threshold){ + put_bits(s, 0, threshold - curval); + break; + } + put_bits(s, 0, stack[sp]->val - curval); + put_bits(s, 1, 1); + curval = stack[sp]->val; + } +} + +/** update the value in node */ +static void tag_tree_update(J2kTgtNode *node) +{ + int lev = 0; + while (node->parent){ + if (node->parent->val <= node->val) + break; + node->parent->val = node->val; + node = node->parent; + lev++; + } +} + +static int put_siz(J2kEncoderContext *s) +{ + int i; + + if (s->buf_end - s->buf < 40 + 3 * s->ncomponents) + return -1; + + bytestream_put_be16(&s->buf, J2K_SIZ); + bytestream_put_be16(&s->buf, 38 + 3 * s->ncomponents); // Lsiz + bytestream_put_be16(&s->buf, 0); // Rsiz + bytestream_put_be32(&s->buf, s->width); // width + bytestream_put_be32(&s->buf, s->height); // height + bytestream_put_be32(&s->buf, 0); // X0Siz + bytestream_put_be32(&s->buf, 0); // Y0Siz + + bytestream_put_be32(&s->buf, s->tile_width); // XTSiz + bytestream_put_be32(&s->buf, s->tile_height); // YTSiz + bytestream_put_be32(&s->buf, 0); // XT0Siz + bytestream_put_be32(&s->buf, 0); // YT0Siz + bytestream_put_be16(&s->buf, s->ncomponents); // CSiz + + for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i + bytestream_put_byte(&s->buf, 7); + bytestream_put_byte(&s->buf, i?1<chroma_shift[0]:1); + bytestream_put_byte(&s->buf, i?1<chroma_shift[1]:1); + } + return 0; +} + +static int put_cod(J2kEncoderContext *s) +{ + J2kCodingStyle *codsty = &s->codsty; + + if (s->buf_end - s->buf < 14) + return -1; + + bytestream_put_be16(&s->buf, J2K_COD); + bytestream_put_be16(&s->buf, 12); // Lcod + bytestream_put_byte(&s->buf, 0); // Scod + // SGcod + bytestream_put_byte(&s->buf, 0); // progression level + bytestream_put_be16(&s->buf, 1); // num of layers + if(s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){ + bytestream_put_byte(&s->buf, 2); // ICT + }else{ + bytestream_put_byte(&s->buf, 0); // unspecified + } + // SPcod + bytestream_put_byte(&s->buf, codsty->nreslevels - 1); // num of decomp. levels + bytestream_put_byte(&s->buf, codsty->log2_cblk_width-2); // cblk width + bytestream_put_byte(&s->buf, codsty->log2_cblk_height-2); // cblk height + bytestream_put_byte(&s->buf, 0); // cblk style + bytestream_put_byte(&s->buf, codsty->transform); // transformation + return 0; +} + +static int put_qcd(J2kEncoderContext *s, int compno) +{ + int i, size; + J2kCodingStyle *codsty = &s->codsty; + J2kQuantStyle *qntsty = &s->qntsty; + + if (qntsty->quantsty == J2K_QSTY_NONE) + size = 4 + 3 * (codsty->nreslevels-1); + else // QSTY_SE + size = 5 + 6 * (codsty->nreslevels-1); + + if (s->buf_end - s->buf < size + 2) + return -1; + + bytestream_put_be16(&s->buf, J2K_QCD); + bytestream_put_be16(&s->buf, size); // LQcd + bytestream_put_byte(&s->buf, (qntsty->nguardbits << 5) | qntsty->quantsty); // Sqcd + if (qntsty->quantsty == J2K_QSTY_NONE) + for (i = 0; i < codsty->nreslevels * 3 - 2; i++) + bytestream_put_byte(&s->buf, qntsty->expn[i] << 3); + else // QSTY_SE + for (i = 0; i < codsty->nreslevels * 3 - 2; i++) + bytestream_put_be16(&s->buf, (qntsty->expn[i] << 11) | qntsty->mant[i]); + return 0; +} + +static uint8_t *put_sot(J2kEncoderContext *s, int tileno) +{ + uint8_t *psotptr; + + if (s->buf_end - s->buf < 12) + return NULL; + + bytestream_put_be16(&s->buf, J2K_SOT); + bytestream_put_be16(&s->buf, 10); // Lsot + bytestream_put_be16(&s->buf, tileno); // Isot + + psotptr = s->buf; + bytestream_put_be32(&s->buf, 0); // Psot (filled in later) + + bytestream_put_byte(&s->buf, 0); // TPsot + bytestream_put_byte(&s->buf, 1); // TNsot + return psotptr; +} + +/** + * compute the sizes of tiles, resolution levels, bands, etc. + * allocate memory for them + * divide the input image into tile-components + */ +static int init_tiles(J2kEncoderContext *s) +{ + int tileno, tilex, tiley, compno; + J2kCodingStyle *codsty = &s->codsty; + J2kQuantStyle *qntsty = &s->qntsty; + + s->numXtiles = ff_j2k_ceildiv(s->width, s->tile_width); + s->numYtiles = ff_j2k_ceildiv(s->height, s->tile_height); + + s->tile = av_malloc(s->numXtiles * s->numYtiles * sizeof(J2kTile)); + if (!s->tile) + return AVERROR(ENOMEM); + for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++) + for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){ + J2kTile *tile = s->tile + tileno; + + tile->comp = av_malloc(s->ncomponents * sizeof(J2kComponent)); + if (!tile->comp) + return AVERROR(ENOMEM); + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + int ret, i, j; + + comp->coord[0][0] = tilex * s->tile_width; + comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width, s->width); + comp->coord[1][0] = tiley * s->tile_height; + comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height, s->height); + if (compno > 0) + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + comp->coord[i][j] = ff_j2k_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]); + + if (ret = ff_j2k_init_component(comp, codsty, qntsty, s->cbps[compno], compno?1<chroma_shift[0]:1, compno?1<chroma_shift[1]:1)) + return ret; + } + } + return 0; +} + +static void copy_frame(J2kEncoderContext *s) +{ + int tileno, compno, i, y, x; + uint8_t *line; + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + J2kTile *tile = s->tile + tileno; + if (s->planar){ + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + int *dst = comp->data; + line = s->picture.data[compno] + + comp->coord[1][0] * s->picture.linesize[compno] + + comp->coord[0][0]; + for (y = comp->coord[1][0]; y < comp->coord[1][1]; y++){ + uint8_t *ptr = line; + for (x = comp->coord[0][0]; x < comp->coord[0][1]; x++) + *dst++ = *ptr++ - (1 << 7); + line += s->picture.linesize[compno]; + } + } + } else{ + line = s->picture.data[0] + tile->comp[0].coord[1][0] * s->picture.linesize[0] + + tile->comp[0].coord[0][0] * s->ncomponents; + + i = 0; + for (y = tile->comp[0].coord[1][0]; y < tile->comp[0].coord[1][1]; y++){ + uint8_t *ptr = line; + for (x = tile->comp[0].coord[0][0]; x < tile->comp[0].coord[0][1]; x++, i++){ + for (compno = 0; compno < s->ncomponents; compno++){ + tile->comp[compno].data[i] = *ptr++ - (1 << 7); + } + } + line += s->picture.linesize[0]; + } + } + } +} + +static void init_quantization(J2kEncoderContext *s) +{ + int compno, reslevelno, bandno; + J2kQuantStyle *qntsty = &s->qntsty; + J2kCodingStyle *codsty = &s->codsty; + + for (compno = 0; compno < s->ncomponents; compno++){ + int gbandno = 0; + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + int nbands, lev = codsty->nreslevels - reslevelno - 1; + nbands = reslevelno ? 3 : 1; + for (bandno = 0; bandno < nbands; bandno++, gbandno++){ + int expn, mant; + + if (codsty->transform == FF_DWT97){ + int bandpos = bandno + (reslevelno>0), + ss = 81920000 / dwt_norms[0][bandpos][lev], + log = av_log2(ss); + mant = (11 - log < 0 ? ss >> log - 11 : ss << 11 - log) & 0x7ff; + expn = s->cbps[compno] - log + 13; + } else + expn = ((bandno&2)>>1) + (reslevelno>0) + s->cbps[compno]; + + qntsty->expn[gbandno] = expn; + qntsty->mant[gbandno] = mant; + } + } + } +} + +static void init_luts(void) +{ + int i, a, + mask = ~((1<> (NMSEDEC_BITS-2)&2) + 1; + lut_nmsedec_ref[i] = FFMAX((-2*i + (1< NMSEDEC_FRACBITS) + return lut_nmsedec_sig[(x >> (bpno - NMSEDEC_FRACBITS)) & ((1 << NMSEDEC_BITS) - 1)]; + return lut_nmsedec_sig0[x & ((1 << NMSEDEC_BITS) - 1)]; +} + +static int getnmsedec_ref(int x, int bpno) +{ + if (bpno > NMSEDEC_FRACBITS) + return lut_nmsedec_ref[(x >> (bpno - NMSEDEC_FRACBITS)) & ((1 << NMSEDEC_BITS) - 1)]; + return lut_nmsedec_ref0[x & ((1 << NMSEDEC_BITS) - 1)]; +} + +static void encode_sigpass(J2kT1Context *t1, int width, int height, int bandno, int *nmsedec, int bpno) +{ + int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS); + int vert_causal_ctx_csty_loc_symbol; + for (y0 = 0; y0 < height; y0 += 4) + for (x = 0; x < width; x++) + for (y = y0; y < height && y < y0+4; y++){ + if (!(t1->flags[y+1][x+1] & J2K_T1_SIG) && (t1->flags[y+1][x+1] & J2K_T1_SIG_NB)){ + int ctxno = ff_j2k_getnbctxno(t1->flags[y+1][x+1], bandno, vert_causal_ctx_csty_loc_symbol), + bit = t1->data[y][x] & mask ? 1 : 0; + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, bit); + if (bit){ + int xorbit; + int ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit); + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit); + *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS); + ff_j2k_set_significant(t1, x, y, t1->flags[y+1][x+1] >> 15); + } + t1->flags[y+1][x+1] |= J2K_T1_VIS; + } + } +} + +static void encode_refpass(J2kT1Context *t1, int width, int height, int *nmsedec, int bpno) +{ + int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS); + for (y0 = 0; y0 < height; y0 += 4) + for (x = 0; x < width; x++) + for (y = y0; y < height && y < y0+4; y++) + if ((t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS)) == J2K_T1_SIG){ + int ctxno = ff_j2k_getrefctxno(t1->flags[y+1][x+1]); + *nmsedec += getnmsedec_ref(t1->data[y][x], bpno + NMSEDEC_FRACBITS); + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0); + t1->flags[y+1][x+1] |= J2K_T1_REF; + } +} + +static void encode_clnpass(J2kT1Context *t1, int width, int height, int bandno, int *nmsedec, int bpno) +{ + int y0, x, y, mask = 1 << (bpno + NMSEDEC_FRACBITS); + int vert_causal_ctx_csty_loc_symbol; + for (y0 = 0; y0 < height; y0 += 4) + for (x = 0; x < width; x++){ + if (y0 + 3 < height && !( + (t1->flags[y0+1][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) || + (t1->flags[y0+2][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) || + (t1->flags[y0+3][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) || + (t1->flags[y0+4][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)))) + { + // aggregation mode + int rlen; + for (rlen = 0; rlen < 4; rlen++) + if (t1->data[y0+rlen][x] & mask) + break; + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_RL, rlen != 4); + if (rlen == 4) + continue; + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI, rlen >> 1); + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI, rlen & 1); + for (y = y0 + rlen; y < y0 + 4; y++){ + if (!(t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS))){ + int ctxno = ff_j2k_getnbctxno(t1->flags[y+1][x+1], bandno, vert_causal_ctx_csty_loc_symbol); + if (y > y0 + rlen) + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0); + if (t1->data[y][x] & mask){ // newly significant + int xorbit; + int ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit); + *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS); + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit); + ff_j2k_set_significant(t1, x, y, t1->flags[y+1][x+1] >> 15); + } + } + t1->flags[y+1][x+1] &= ~J2K_T1_VIS; + } + } else{ + for (y = y0; y < y0 + 4 && y < height; y++){ + if (!(t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS))){ + int ctxno = ff_j2k_getnbctxno(t1->flags[y+1][x+1], bandno, vert_causal_ctx_csty_loc_symbol); + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, t1->data[y][x] & mask ? 1:0); + if (t1->data[y][x] & mask){ // newly significant + int xorbit; + int ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit); + *nmsedec += getnmsedec_sig(t1->data[y][x], bpno + NMSEDEC_FRACBITS); + ff_mqc_encode(&t1->mqc, t1->mqc.cx_states + ctxno, (t1->flags[y+1][x+1] >> 15) ^ xorbit); + ff_j2k_set_significant(t1, x, y, t1->flags[y+1][x+1] >> 15); + } + } + t1->flags[y+1][x+1] &= ~J2K_T1_VIS; + } + } + } +} + +static void encode_cblk(J2kEncoderContext *s, J2kT1Context *t1, J2kCblk *cblk, J2kTile *tile, + int width, int height, int bandpos, int lev) +{ + int pass_t = 2, passno, x, y, max=0, nmsedec, bpno; + int64_t wmsedec = 0; + + for (y = 0; y < height+2; y++) + memset(t1->flags[y], 0, (width+2)*sizeof(int)); + + for (y = 0; y < height; y++){ + for (x = 0; x < width; x++){ + if (t1->data[y][x] < 0){ + t1->flags[y+1][x+1] |= J2K_T1_SGN; + t1->data[y][x] = -t1->data[y][x]; + } + max = FFMAX(max, t1->data[y][x]); + } + } + + if (max == 0){ + cblk->nonzerobits = 0; + bpno = 0; + } else{ + cblk->nonzerobits = av_log2(max) + 1 - NMSEDEC_FRACBITS; + bpno = cblk->nonzerobits - 1; + } + + ff_mqc_initenc(&t1->mqc, cblk->data); + + for (passno = 0; bpno >= 0; passno++){ + nmsedec=0; + + switch(pass_t){ + case 0: encode_sigpass(t1, width, height, bandpos, &nmsedec, bpno); + break; + case 1: encode_refpass(t1, width, height, &nmsedec, bpno); + break; + case 2: encode_clnpass(t1, width, height, bandpos, &nmsedec, bpno); + break; + } + + cblk->passes[passno].rate = 3 + ff_mqc_length(&t1->mqc); + wmsedec += (int64_t)nmsedec << (2*bpno); + cblk->passes[passno].disto = wmsedec; + + if (++pass_t == 3){ + pass_t = 0; + bpno--; + } + } + cblk->npasses = passno; + cblk->ninclpasses = passno; + + // TODO: optional flush on each pass + cblk->passes[passno-1].rate = ff_mqc_flush(&t1->mqc); +} + +/* tier-2 routines: */ + +static void putnumpasses(J2kEncoderContext *s, int n) +{ + if (n == 1) + put_num(s, 0, 1); + else if (n == 2) + put_num(s, 2, 2); + else if (n <= 5) + put_num(s, 0xc | (n-3), 4); + else if (n <= 36) + put_num(s, 0x1e0 | (n-6), 9); + else + put_num(s, 0xff80 | (n-37), 16); +} + + +static int encode_packet(J2kEncoderContext *s, J2kResLevel *rlevel, int precno, + uint8_t *expn, int numgbits) +{ + int bandno, empty = 1; + + // init bitstream + *s->buf = 0; + s->bit_index = 0; + + // header + + // is the packet empty? + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + if (rlevel->band[bandno].coord[0][0] < rlevel->band[bandno].coord[0][1] + && rlevel->band[bandno].coord[1][0] < rlevel->band[bandno].coord[1][1]){ + empty = 0; + break; + } + } + + put_bits(s, !empty, 1); + if (empty){ + j2k_flush(s); + return 0; + } + + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + J2kBand *band = rlevel->band + bandno; + J2kPrec *prec = band->prec + precno; + int yi, xi, pos; + int cblknw = prec->xi1 - prec->xi0; + + if (band->coord[0][0] == band->coord[0][1] + || band->coord[1][0] == band->coord[1][1]) + continue; + + for (pos=0, yi = prec->yi0; yi < prec->yi1; yi++){ + for (xi = prec->xi0; xi < prec->xi1; xi++, pos++){ + prec->cblkincl[pos].val = band->cblk[yi * cblknw + xi].ninclpasses == 0; + tag_tree_update(prec->cblkincl + pos); + prec->zerobits[pos].val = expn[bandno] + numgbits - 1 - band->cblk[yi * cblknw + xi].nonzerobits; + tag_tree_update(prec->zerobits + pos); + } + } + + for (pos=0, yi = prec->yi0; yi < prec->yi1; yi++){ + for (xi = prec->xi0; xi < prec->xi1; xi++, pos++){ + int pad = 0, llen, length; + J2kCblk *cblk = band->cblk + yi * cblknw + xi; + + if (s->buf_end - s->buf < 20) // approximately + return -1; + + // inclusion information + tag_tree_code(s, prec->cblkincl + pos, 1); + if (!cblk->ninclpasses) + continue; + // zerobits information + tag_tree_code(s, prec->zerobits + pos, 100); + // number of passes + putnumpasses(s, cblk->ninclpasses); + + length = cblk->passes[cblk->ninclpasses-1].rate; + llen = av_log2(length) - av_log2(cblk->ninclpasses) - 2; + if (llen < 0){ + pad = -llen; + llen = 0; + } + // length of code block + put_bits(s, 1, llen); + put_bits(s, 0, 1); + put_num(s, length, av_log2(length)+1+pad); + } + } + } + j2k_flush(s); + for (bandno = 0; bandno < rlevel->nbands; bandno++){ + J2kBand *band = rlevel->band + bandno; + J2kPrec *prec = band->prec + precno; + int yi, cblknw = prec->xi1 - prec->xi0; + for (yi = prec->yi0; yi < prec->yi1; yi++){ + int xi; + for (xi = prec->xi0; xi < prec->xi1; xi++){ + J2kCblk *cblk = band->cblk + yi * cblknw + xi; + if (cblk->ninclpasses){ + if (s->buf_end - s->buf < cblk->passes[cblk->ninclpasses-1].rate) + return -1; + bytestream_put_buffer(&s->buf, cblk->data, cblk->passes[cblk->ninclpasses-1].rate); + } + } + } + } + return 0; +} + +static int encode_packets(J2kEncoderContext *s, J2kTile *tile, int tileno) +{ + int compno, reslevelno, ret; + J2kCodingStyle *codsty = &s->codsty; + J2kQuantStyle *qntsty = &s->qntsty; + + av_log(s->avctx, AV_LOG_DEBUG, "tier2\n"); + // lay-rlevel-comp-pos progression + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + for (compno = 0; compno < s->ncomponents; compno++){ + int precno; + J2kResLevel *reslevel = s->tile[tileno].comp[compno].reslevel + reslevelno; + for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){ + if (ret = encode_packet(s, reslevel, precno, qntsty->expn + (reslevelno ? 3*reslevelno-2 : 0), + qntsty->nguardbits)) + return ret; + } + } + } + av_log(s->avctx, AV_LOG_DEBUG, "after tier2\n"); + return 0; +} + +static int getcut(J2kCblk *cblk, int64_t lambda, int dwt_norm) +{ + int passno, res = 0; + for (passno = 0; passno < cblk->npasses; passno++){ + int dr; + int64_t dd; + + dr = cblk->passes[passno].rate + - (res ? cblk->passes[res-1].rate:0); + dd = cblk->passes[passno].disto + - (res ? cblk->passes[res-1].disto:0); + + if (((dd * dwt_norm) >> WMSEDEC_SHIFT) * dwt_norm >= dr * lambda) + res = passno+1; + } + return res; +} + +static void truncpasses(J2kEncoderContext *s, J2kTile *tile) +{ + int compno, reslevelno, bandno, cblkno, lev; + J2kCodingStyle *codsty = &s->codsty; + + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = tile->comp + compno; + + for (reslevelno = 0, lev = codsty->nreslevels-1; reslevelno < codsty->nreslevels; reslevelno++, lev--){ + J2kResLevel *reslevel = comp->reslevel + reslevelno; + + for (bandno = 0; bandno < reslevel->nbands ; bandno++){ + int bandpos = bandno + (reslevelno > 0); + J2kBand *band = reslevel->band + bandno; + + for (cblkno = 0; cblkno < band->cblknx * band->cblkny; cblkno++){ + J2kCblk *cblk = band->cblk + cblkno; + + cblk->ninclpasses = getcut(cblk, s->lambda, + (int64_t)dwt_norms[codsty->transform][bandpos][lev] * (int64_t)band->stepsize >> 13); + } + } + } + } +} + +static int encode_tile(J2kEncoderContext *s, J2kTile *tile, int tileno) +{ + int compno, reslevelno, bandno, ret; + J2kT1Context t1; + J2kCodingStyle *codsty = &s->codsty; + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = s->tile[tileno].comp + compno; + + av_log(s->avctx, AV_LOG_DEBUG,"dwt\n"); + if (ret = ff_j2k_dwt_encode(&comp->dwt, comp->data)) + return ret; + av_log(s->avctx, AV_LOG_DEBUG,"after dwt -> tier1\n"); + + for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){ + J2kResLevel *reslevel = comp->reslevel + reslevelno; + + for (bandno = 0; bandno < reslevel->nbands ; bandno++){ + J2kBand *band = reslevel->band + bandno; + int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos; + yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0]; + y0 = yy0; + yy1 = FFMIN(ff_j2k_ceildiv(band->coord[1][0] + 1, band->codeblock_height) * band->codeblock_height, + band->coord[1][1]) - band->coord[1][0] + yy0; + + if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1]) + continue; + + bandpos = bandno + (reslevelno > 0); + + for (cblky = 0; cblky < band->cblkny; cblky++){ + if (reslevelno == 0 || bandno == 1) + xx0 = 0; + else + xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0]; + x0 = xx0; + xx1 = FFMIN(ff_j2k_ceildiv(band->coord[0][0] + 1, band->codeblock_width) * band->codeblock_width, + band->coord[0][1]) - band->coord[0][0] + xx0; + + for (cblkx = 0; cblkx < band->cblknx; cblkx++, cblkno++){ + int y, x; + if (codsty->transform == FF_DWT53){ + for (y = yy0; y < yy1; y++){ + int *ptr = t1.data[y-yy0]; + for (x = xx0; x < xx1; x++){ + *ptr++ = comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] << NMSEDEC_FRACBITS; + } + } + } else{ + for (y = yy0; y < yy1; y++){ + int *ptr = t1.data[y-yy0]; + for (x = xx0; x < xx1; x++){ + *ptr = (comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x]); + *ptr = (int64_t)*ptr * (int64_t)(8192 * 8192 / band->stepsize) >> 13 - NMSEDEC_FRACBITS; + ptr++; + } + } + } + encode_cblk(s, &t1, band->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0, + bandpos, codsty->nreslevels - reslevelno - 1); + xx0 = xx1; + xx1 = FFMIN(xx1 + band->codeblock_width, band->coord[0][1] - band->coord[0][0] + x0); + } + yy0 = yy1; + yy1 = FFMIN(yy1 + band->codeblock_height, band->coord[1][1] - band->coord[1][0] + y0); + } + } + } + av_log(s->avctx, AV_LOG_DEBUG, "after tier1\n"); + } + + av_log(s->avctx, AV_LOG_DEBUG, "rate control\n"); + truncpasses(s, tile); + if (ret = encode_packets(s, tile, tileno)) + return ret; + av_log(s->avctx, AV_LOG_DEBUG, "after rate control\n"); + return 0; +} + +static void cleanup(J2kEncoderContext *s) +{ + int tileno, compno; + J2kCodingStyle *codsty = &s->codsty; + + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + for (compno = 0; compno < s->ncomponents; compno++){ + J2kComponent *comp = s->tile[tileno].comp + compno; + ff_j2k_cleanup(comp, codsty); + } + av_freep(&s->tile[tileno].comp); + } + av_freep(&s->tile); +} + +static void reinit(J2kEncoderContext *s) +{ + int tileno, compno; + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + J2kTile *tile = s->tile + tileno; + for (compno = 0; compno < s->ncomponents; compno++) + ff_j2k_reinit(tile->comp + compno, &s->codsty); + } +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + int tileno, ret; + J2kEncoderContext *s = avctx->priv_data; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + // init: + s->buf = s->buf_start = pkt->data; + s->buf_end = pkt->data + pkt->size; + + s->picture = *pict; + avctx->coded_frame= &s->picture; + + s->lambda = s->picture.quality * LAMBDA_SCALE; + + copy_frame(s); + reinit(s); + + if (s->buf_end - s->buf < 2) + return -1; + bytestream_put_be16(&s->buf, J2K_SOC); + if (ret = put_siz(s)) + return ret; + if (ret = put_cod(s)) + return ret; + if (ret = put_qcd(s, 0)) + return ret; + + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){ + uint8_t *psotptr; + if (!(psotptr = put_sot(s, tileno))) + return -1; + if (s->buf_end - s->buf < 2) + return -1; + bytestream_put_be16(&s->buf, J2K_SOD); + if (ret = encode_tile(s, s->tile + tileno, tileno)) + return ret; + bytestream_put_be32(&psotptr, s->buf - psotptr + 6); + } + if (s->buf_end - s->buf < 2) + return -1; + bytestream_put_be16(&s->buf, J2K_EOC); + + av_log(s->avctx, AV_LOG_DEBUG, "end\n"); + pkt->size = s->buf - s->buf_start; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int j2kenc_init(AVCodecContext *avctx) +{ + int i, ret; + J2kEncoderContext *s = avctx->priv_data; + J2kCodingStyle *codsty = &s->codsty; + J2kQuantStyle *qntsty = &s->qntsty; + + s->avctx = avctx; + av_log(s->avctx, AV_LOG_DEBUG, "init\n"); + + // defaults: + // TODO: implement setting non-standard precinct size + codsty->log2_prec_width = 15; + codsty->log2_prec_height = 15; + codsty->nreslevels = 7; + codsty->log2_cblk_width = 4; + codsty->log2_cblk_height = 4; + codsty->transform = 1; + + qntsty->nguardbits = 1; + + s->tile_width = 256; + s->tile_height = 256; + + if (codsty->transform == FF_DWT53) + qntsty->quantsty = J2K_QSTY_NONE; + else + qntsty->quantsty = J2K_QSTY_SE; + + s->width = avctx->width; + s->height = avctx->height; + + for (i = 0; i < 3; i++) + s->cbps[i] = 8; + + if (avctx->pix_fmt == AV_PIX_FMT_RGB24){ + s->ncomponents = 3; + } else if (avctx->pix_fmt == AV_PIX_FMT_GRAY8){ + s->ncomponents = 1; + } else{ // planar YUV + s->planar = 1; + s->ncomponents = 3; + avcodec_get_chroma_sub_sample(avctx->pix_fmt, + s->chroma_shift, s->chroma_shift + 1); + } + + ff_j2k_init_tier1_luts(); + + init_luts(); + + init_quantization(s); + if (ret=init_tiles(s)) + return ret; + + av_log(s->avctx, AV_LOG_DEBUG, "after init\n"); + + return 0; +} + +static int j2kenc_destroy(AVCodecContext *avctx) +{ + J2kEncoderContext *s = avctx->priv_data; + + cleanup(s); + return 0; +} + +AVCodec ff_jpeg2000_encoder = { + .name = "j2k", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEG2000, + .priv_data_size = sizeof(J2kEncoderContext), + .init = j2kenc_init, + .encode2 = encode_frame, + .close = j2kenc_destroy, + .capabilities = CODEC_CAP_EXPERIMENTAL, + .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8, +/* AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,*/ + AV_PIX_FMT_NONE + } +}; diff --git a/ffmpeg/libavcodec/jacosub.h b/ffmpeg/libavcodec/jacosub.h new file mode 100644 index 0000000..c3665ae --- /dev/null +++ b/ffmpeg/libavcodec/jacosub.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012 Clément Bœsch + * + * 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 + */ + +/** + * @file + * JACOsub shared utils + */ + +#ifndef AVCODEC_JACOSUB_H +#define AVCODEC_JACOSUB_H + +#include "libavutil/common.h" + +#define JSS_MAX_LINESIZE 512 + +static av_always_inline int jss_whitespace(char c) +{ + return c == ' ' || (c >= '\t' && c <= '\r'); +} + +static av_always_inline const char *jss_skip_whitespace(const char *p) +{ + while (jss_whitespace(*p)) + p++; + return p; +} + +#endif /* AVCODEC_JACOSUB_H */ diff --git a/ffmpeg/libavcodec/jacosubdec.c b/ffmpeg/libavcodec/jacosubdec.c new file mode 100644 index 0000000..b64fac8 --- /dev/null +++ b/ffmpeg/libavcodec/jacosubdec.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2012 Clément Bœsch + * + * 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 + */ + +/** + * @file + * JACOsub subtitle decoder + * @see http://unicorn.us.com/jacosub/jscripts.html + */ + +#include +#include "ass.h" +#include "jacosub.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" + +#undef time + +static int insert_text(AVBPrint *dst, const char *in, const char *arg) +{ + av_bprintf(dst, "%s", arg); + return 0; +} + +static int insert_datetime(AVBPrint *dst, const char *in, const char *arg) +{ + char buf[16] = {0}; + time_t now = time(0); + struct tm ltime; + +#if HAVE_LOCALTIME_R + localtime_r(&now, <ime); +#else + ltime = *localtime(&now); +#endif + strftime(buf, sizeof(buf), arg, <ime); + av_bprintf(dst, "%s", buf); + return 0; +} + +static int insert_color(AVBPrint *dst, const char *in, const char *arg) +{ + return 1; // skip id +} + +static int insert_font(AVBPrint *dst, const char *in, const char *arg) +{ + return 1; // skip id +} + +static const struct { + const char *from; + const char *arg; + int (*func)(AVBPrint *dst, const char *in, const char *arg); +} ass_codes_map[] = { + {"\\~", "~", insert_text}, // tilde doesn't need escaping + {"~", "{\\h}", insert_text}, // hard space + {"\\n", "\\N", insert_text}, // newline + {"\\D", "%d %b %Y", insert_datetime}, // current date + {"\\T", "%H:%M", insert_datetime}, // current time + {"\\N", "{\\r}", insert_text}, // reset to default style + {"\\I", "{\\i1}", insert_text}, // italic on + {"\\i", "{\\i0}", insert_text}, // italic off + {"\\B", "{\\b1}", insert_text}, // bold on + {"\\b", "{\\b0}", insert_text}, // bold off + {"\\U", "{\\u1}", insert_text}, // underline on + {"\\u", "{\\u0}", insert_text}, // underline off + {"\\C", "", insert_color}, // TODO: color + {"\\F", "", insert_font}, // TODO: font +}; + +enum { + ALIGN_VB = 1<<0, // vertical bottom, default + ALIGN_VM = 1<<1, // vertical middle + ALIGN_VT = 1<<2, // vertical top + ALIGN_JC = 1<<3, // justify center, default + ALIGN_JL = 1<<4, // justify left + ALIGN_JR = 1<<5, // justify right +}; + +static void jacosub_to_ass(AVCodecContext *avctx, AVBPrint *dst, const char *src) +{ + int i, valign = 0, halign = 0; + char c = av_toupper(*src); + char directives[128] = {0}; + + /* extract the optional directives */ + if ((c >= 'A' && c <= 'Z') || c == '[') { + char *p = directives; + char *pend = directives + sizeof(directives) - 1; + + do *p++ = av_toupper(*src++); + while (*src && !jss_whitespace(*src) && p < pend); + *p = 0; + src = jss_skip_whitespace(src); + } + + /* handle directives (TODO: handle more of them, and more reliably) */ + if (strstr(directives, "VB")) valign = ALIGN_VB; + else if (strstr(directives, "VM")) valign = ALIGN_VM; + else if (strstr(directives, "VT")) valign = ALIGN_VT; + if (strstr(directives, "JC")) halign = ALIGN_JC; + else if (strstr(directives, "JL")) halign = ALIGN_JL; + else if (strstr(directives, "JR")) halign = ALIGN_JR; + if (valign || halign) { + if (!valign) valign = ALIGN_VB; + if (!halign) halign = ALIGN_JC; + switch (valign | halign) { + case ALIGN_VB | ALIGN_JL: av_bprintf(dst, "{\\an1}"); break; // bottom left + case ALIGN_VB | ALIGN_JC: av_bprintf(dst, "{\\an2}"); break; // bottom center + case ALIGN_VB | ALIGN_JR: av_bprintf(dst, "{\\an3}"); break; // bottom right + case ALIGN_VM | ALIGN_JL: av_bprintf(dst, "{\\an4}"); break; // middle left + case ALIGN_VM | ALIGN_JC: av_bprintf(dst, "{\\an5}"); break; // middle center + case ALIGN_VM | ALIGN_JR: av_bprintf(dst, "{\\an6}"); break; // middle right + case ALIGN_VT | ALIGN_JL: av_bprintf(dst, "{\\an7}"); break; // top left + case ALIGN_VT | ALIGN_JC: av_bprintf(dst, "{\\an8}"); break; // top center + case ALIGN_VT | ALIGN_JR: av_bprintf(dst, "{\\an9}"); break; // top right + } + } + + /* process timed line */ + while (*src && *src != '\n') { + + /* text continue on the next line */ + if (src[0] == '\\' && src[1] == '\n') { + src += 2; + while (jss_whitespace(*src)) + src++; + continue; + } + + /* special character codes */ + for (i = 0; i < FF_ARRAY_ELEMS(ass_codes_map); i++) { + const char *from = ass_codes_map[i].from; + const char *arg = ass_codes_map[i].arg; + size_t codemap_len = strlen(from); + + if (!strncmp(src, from, codemap_len)) { + src += codemap_len; + src += ass_codes_map[i].func(dst, src, arg); + break; + } + } + + /* simple char copy */ + if (i == FF_ARRAY_ELEMS(ass_codes_map)) + av_bprintf(dst, "%c", *src++); + } + av_bprintf(dst, "\r\n"); +} + +static int jacosub_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + + if (avpkt->size <= 0) + goto end; + + if (*ptr) { + AVBPrint buffer; + char *dec_sub; + + // skip timers + ptr = jss_skip_whitespace(ptr); + ptr = strchr(ptr, ' '); if (!ptr) goto end; ptr++; + ptr = strchr(ptr, ' '); if (!ptr) goto end; ptr++; + + av_bprint_init(&buffer, JSS_MAX_LINESIZE, JSS_MAX_LINESIZE); + jacosub_to_ass(avctx, &buffer, ptr); + av_bprint_finalize(&buffer, &dec_sub); + ff_ass_add_rect(sub, dec_sub, avpkt->pts, avpkt->duration, 0); + av_free(dec_sub); + } + +end: + *got_sub_ptr = sub->num_rects > 0; + return avpkt->size; +} + +AVCodec ff_jacosub_decoder = { + .name = "jacosub", + .long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_JACOSUB, + .init = ff_ass_subtitle_header_default, + .decode = jacosub_decode_frame, +}; diff --git a/ffmpeg/libavcodec/jfdctfst.c b/ffmpeg/libavcodec/jfdctfst.c new file mode 100644 index 0000000..bbcf598 --- /dev/null +++ b/ffmpeg/libavcodec/jfdctfst.c @@ -0,0 +1,332 @@ +/* + * This file is part of the Independent JPEG Group's software. + * + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and + * you, its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1994-1996, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to + * these conditions: + * (1) If any part of the source code for this software is distributed, then + * this README file must be included, with this copyright and no-warranty + * notice unaltered; and any additions, deletions, or changes to the original + * files must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work + * of the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG + * code, not just to the unmodified library. If you use our work, you ought + * to acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company + * name in advertising or publicity relating to this software or products + * derived from it. This software may be referred to only as "the Independent + * JPEG Group's software". + * + * We specifically permit and encourage the use of this software as the basis + * of commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +/** + * @file + * Independent JPEG Group's fast AAN dct. + */ + +#include +#include +#include "libavutil/common.h" +#include "dct.h" + +#define DCTSIZE 8 +#define GLOBAL(x) x +#define RIGHT_SHIFT(x, n) ((x) >> (n)) + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((int32_t) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((int32_t) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((int32_t) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((int32_t) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a int16_t variable by an int32_t constant, and immediately + * descale to yield a int16_t result. + */ + +#define MULTIPLY(var,const) ((int16_t) DESCALE((var) * (const), CONST_BITS)) + +static av_always_inline void row_fdct(int16_t * data){ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z1, z2, z3, z4, z5, z11, z13; + int16_t *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } +} + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +ff_fdct_ifast (int16_t * data) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z1, z2, z3, z4, z5, z11, z13; + int16_t *dataptr; + int ctr; + + row_fdct(data); + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +/* + * Perform the forward 2-4-8 DCT on one block of samples. + */ + +GLOBAL(void) +ff_fdct_ifast248 (int16_t * data) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z1; + int16_t *dataptr; + int ctr; + + row_fdct(data); + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + tmp4 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + tmp6 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + tmp7 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + tmp13 = tmp0 - tmp3; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); + dataptr[DCTSIZE*2] = tmp13 + z1; + dataptr[DCTSIZE*6] = tmp13 - z1; + + tmp10 = tmp4 + tmp7; + tmp11 = tmp5 + tmp6; + tmp12 = tmp5 - tmp6; + tmp13 = tmp4 - tmp7; + + dataptr[DCTSIZE*1] = tmp10 + tmp11; + dataptr[DCTSIZE*5] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); + dataptr[DCTSIZE*3] = tmp13 + z1; + dataptr[DCTSIZE*7] = tmp13 - z1; + + dataptr++; /* advance pointer to next column */ + } +} + + +#undef GLOBAL +#undef CONST_BITS +#undef DESCALE +#undef FIX_0_541196100 +#undef FIX_1_306562965 diff --git a/ffmpeg/libavcodec/jfdctint.c b/ffmpeg/libavcodec/jfdctint.c new file mode 100644 index 0000000..ed6b7ff --- /dev/null +++ b/ffmpeg/libavcodec/jfdctint.c @@ -0,0 +1,25 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define BIT_DEPTH 8 +#include "jfdctint_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 10 +#include "jfdctint_template.c" +#undef BIT_DEPTH diff --git a/ffmpeg/libavcodec/jfdctint_template.c b/ffmpeg/libavcodec/jfdctint_template.c new file mode 100644 index 0000000..c6a1638 --- /dev/null +++ b/ffmpeg/libavcodec/jfdctint_template.c @@ -0,0 +1,403 @@ +/* + * This file is part of the Independent JPEG Group's software. + * + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and + * you, its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1991-1996, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to + * these conditions: + * (1) If any part of the source code for this software is distributed, then + * this README file must be included, with this copyright and no-warranty + * notice unaltered; and any additions, deletions, or changes to the original + * files must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work + * of the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG + * code, not just to the unmodified library. If you use our work, you ought + * to acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company + * name in advertising or publicity relating to this software or products + * derived from it. This software may be referred to only as "the Independent + * JPEG Group's software". + * + * We specifically permit and encourage the use of this software as the basis + * of commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +/** + * @file + * Independent JPEG Group's slow & accurate dct. + */ + +#include "libavutil/common.h" +#include "dct.h" + +#include "bit_depth_template.c" + +#define DCTSIZE 8 +#define BITS_IN_JSAMPLE BIT_DEPTH +#define GLOBAL(x) x +#define RIGHT_SHIFT(x, n) ((x) >> (n)) +#define MULTIPLY16C16(var,const) ((var)*(const)) + +#if 1 //def USE_ACCURATE_ROUNDING +#define DESCALE(x,n) RIGHT_SHIFT((x) + (1 << ((n) - 1)), n) +#else +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 +#error "Sorry, this code only copes with 8x8 DCTs." +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is int32_t anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#undef CONST_BITS +#undef PASS1_BITS +#undef OUT_SHIFT + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 4 /* set this to 2 if 16x16 multiplies are faster */ +#define OUT_SHIFT PASS1_BITS +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#define OUT_SHIFT (PASS1_BITS + 1) +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((int32_t) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((int32_t) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((int32_t) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((int32_t) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((int32_t) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((int32_t) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((int32_t) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((int32_t) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((int32_t) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((int32_t) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((int32_t) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((int32_t) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an int32_t variable by an int32_t constant to yield an int32_t result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 && CONST_BITS<=13 && PASS1_BITS<=2 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +static av_always_inline void FUNC(row_fdct)(int16_t *data) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z1, z2, z3, z4, z5; + int16_t *dataptr; + int ctr; + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (int16_t) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (int16_t) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (int16_t) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (int16_t) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (int16_t) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (int16_t) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (int16_t) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (int16_t) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } +} + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +FUNC(ff_jpeg_fdct_islow)(int16_t *data) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z1, z2, z3, z4, z5; + int16_t *dataptr; + int ctr; + + FUNC(row_fdct)(data); + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = DESCALE(tmp10 + tmp11, OUT_SHIFT); + dataptr[DCTSIZE*4] = DESCALE(tmp10 - tmp11, OUT_SHIFT); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS + OUT_SHIFT); + dataptr[DCTSIZE*6] = DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS + OUT_SHIFT); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = DESCALE(tmp4 + z1 + z3, CONST_BITS + OUT_SHIFT); + dataptr[DCTSIZE*5] = DESCALE(tmp5 + z2 + z4, CONST_BITS + OUT_SHIFT); + dataptr[DCTSIZE*3] = DESCALE(tmp6 + z2 + z3, CONST_BITS + OUT_SHIFT); + dataptr[DCTSIZE*1] = DESCALE(tmp7 + z1 + z4, CONST_BITS + OUT_SHIFT); + + dataptr++; /* advance pointer to next column */ + } +} + +/* + * The secret of DCT2-4-8 is really simple -- you do the usual 1-DCT + * on the rows and then, instead of doing even and odd, part on the columns + * you do even part two times. + */ +GLOBAL(void) +FUNC(ff_fdct248_islow)(int16_t *data) +{ + int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int tmp10, tmp11, tmp12, tmp13; + int z1; + int16_t *dataptr; + int ctr; + + FUNC(row_fdct)(data); + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + tmp4 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + tmp6 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + tmp7 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + tmp13 = tmp0 - tmp3; + + dataptr[DCTSIZE*0] = DESCALE(tmp10 + tmp11, OUT_SHIFT); + dataptr[DCTSIZE*4] = DESCALE(tmp10 - tmp11, OUT_SHIFT); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+OUT_SHIFT); + dataptr[DCTSIZE*6] = DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+OUT_SHIFT); + + tmp10 = tmp4 + tmp7; + tmp11 = tmp5 + tmp6; + tmp12 = tmp5 - tmp6; + tmp13 = tmp4 - tmp7; + + dataptr[DCTSIZE*1] = DESCALE(tmp10 + tmp11, OUT_SHIFT); + dataptr[DCTSIZE*5] = DESCALE(tmp10 - tmp11, OUT_SHIFT); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*3] = DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS + OUT_SHIFT); + dataptr[DCTSIZE*7] = DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS + OUT_SHIFT); + + dataptr++; /* advance pointer to next column */ + } +} diff --git a/ffmpeg/libavcodec/jpegls.c b/ffmpeg/libavcodec/jpegls.c new file mode 100644 index 0000000..dc5c9cf --- /dev/null +++ b/ffmpeg/libavcodec/jpegls.c @@ -0,0 +1,87 @@ +/* + * JPEG-LS common code + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * JPEG-LS common code. + */ + +#include "jpegls.h" + +void ff_jpegls_init_state(JLSState *state){ + int i; + + state->twonear = state->near * 2 + 1; + state->range = ((state->maxval + state->twonear - 1) / state->twonear) + 1; + + // QBPP = ceil(log2(RANGE)) + for(state->qbpp = 0; (1 << state->qbpp) < state->range; state->qbpp++); + + state->bpp = FFMAX(av_log2(state->maxval)+1, 2); + state->limit = 2*(state->bpp + FFMAX(state->bpp, 8)) - state->qbpp; + + for(i = 0; i < 367; i++) { + state->A[i] = FFMAX((state->range + 32) >> 6, 2); + state->N[i] = 1; + } + +} + +/** + * Custom value clipping function used in T1, T2, T3 calculation + */ +static inline int iso_clip(int v, int vmin, int vmax){ + if(v > vmax || v < vmin) return vmin; + else return v; +} + +void ff_jpegls_reset_coding_parameters(JLSState *s, int reset_all){ + const int basic_t1= 3; + const int basic_t2= 7; + const int basic_t3= 21; + int factor; + + if(s->maxval==0 || reset_all) s->maxval= (1 << s->bpp) - 1; + + if(s->maxval >=128){ + factor= (FFMIN(s->maxval, 4095) + 128)>>8; + + if(s->T1==0 || reset_all) + s->T1= iso_clip(factor*(basic_t1-2) + 2 + 3*s->near, s->near+1, s->maxval); + if(s->T2==0 || reset_all) + s->T2= iso_clip(factor*(basic_t2-3) + 3 + 5*s->near, s->T1, s->maxval); + if(s->T3==0 || reset_all) + s->T3= iso_clip(factor*(basic_t3-4) + 4 + 7*s->near, s->T2, s->maxval); + }else{ + factor= 256 / (s->maxval + 1); + + if(s->T1==0 || reset_all) + s->T1= iso_clip(FFMAX(2, basic_t1/factor + 3*s->near), s->near+1, s->maxval); + if(s->T2==0 || reset_all) + s->T2= iso_clip(FFMAX(3, basic_t2/factor + 5*s->near), s->T1, s->maxval); + if(s->T3==0 || reset_all) + s->T3= iso_clip(FFMAX(4, basic_t3/factor + 7*s->near), s->T2, s->maxval); + } + + if(s->reset==0 || reset_all) s->reset= 64; + av_dlog(NULL, "[JPEG-LS RESET] T=%i,%i,%i\n", s->T1, s->T2, s->T3); +} diff --git a/ffmpeg/libavcodec/jpegls.h b/ffmpeg/libavcodec/jpegls.h new file mode 100644 index 0000000..0a6ead3 --- /dev/null +++ b/ffmpeg/libavcodec/jpegls.h @@ -0,0 +1,114 @@ +/* + * JPEG-LS common code + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * JPEG-LS common code. + */ + +#ifndef AVCODEC_JPEGLS_H +#define AVCODEC_JPEGLS_H + +#include "avcodec.h" +#include "libavutil/common.h" + +typedef struct JpeglsContext{ + AVCodecContext *avctx; + AVFrame picture; +}JpeglsContext; + +typedef struct JLSState{ + int T1, T2, T3; + int A[367], B[367], C[365], N[367]; + int limit, reset, bpp, qbpp, maxval, range; + int near, twonear; + int run_index[4]; +}JLSState; + +extern const uint8_t ff_log2_run[32]; + +/** + * Calculate initial JPEG-LS parameters + */ +void ff_jpegls_init_state(JLSState *state); + +/** + * Calculate quantized gradient value, used for context determination + */ +static inline int ff_jpegls_quantize(JLSState *s, int v){ //FIXME optimize + if(v==0) return 0; + if(v < 0){ + if(v <= -s->T3) return -4; + if(v <= -s->T2) return -3; + if(v <= -s->T1) return -2; + if(v < -s->near) return -1; + return 0; + }else{ + if(v <= s->near) return 0; + if(v < s->T1) return 1; + if(v < s->T2) return 2; + if(v < s->T3) return 3; + return 4; + } +} + +/** + * Calculate JPEG-LS codec values + */ +void ff_jpegls_reset_coding_parameters(JLSState *s, int reset_all); + + +static inline void ff_jpegls_downscale_state(JLSState *state, int Q){ + if(state->N[Q] == state->reset){ + state->A[Q] >>=1; + state->B[Q] >>=1; + state->N[Q] >>=1; + } + state->N[Q]++; +} + +static inline int ff_jpegls_update_state_regular(JLSState *state, int Q, int err){ + if(FFABS(err) > 0xFFFF) + return -0x10000; + state->A[Q] += FFABS(err); + err *= state->twonear; + state->B[Q] += err; + + ff_jpegls_downscale_state(state, Q); + + if(state->B[Q] <= -state->N[Q]) { + state->B[Q]= FFMAX(state->B[Q] + state->N[Q], 1-state->N[Q]); + if(state->C[Q] > -128) + state->C[Q]--; + }else if(state->B[Q] > 0){ + state->B[Q]= FFMIN(state->B[Q] - state->N[Q], 0); + if(state->C[Q] < 127) + state->C[Q]++; + } + + return err; +} + +#define R(a, i ) (bits == 8 ? ((uint8_t*)(a))[i] : ((uint16_t*)(a))[i] ) +#define W(a, i, v) (bits == 8 ? (((uint8_t*)(a))[i]=v) : (((uint16_t*)(a))[i]=v)) + +#endif /* AVCODEC_JPEGLS_H */ diff --git a/ffmpeg/libavcodec/jpeglsdec.c b/ffmpeg/libavcodec/jpeglsdec.c new file mode 100644 index 0000000..516a82f --- /dev/null +++ b/ffmpeg/libavcodec/jpeglsdec.c @@ -0,0 +1,385 @@ +/* + * JPEG-LS decoder + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * JPEG-LS decoder. + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "golomb.h" +#include "mathops.h" +#include "mjpeg.h" +#include "mjpegdec.h" +#include "jpegls.h" +#include "jpeglsdec.h" + + +/* +* Uncomment this to significantly speed up decoding of broken JPEG-LS +* (or test broken JPEG-LS decoder) and slow down ordinary decoding a bit. +* +* There is no Golomb code with length >= 32 bits possible, so check and +* avoid situation of 32 zeros, FFmpeg Golomb decoder is painfully slow +* on this errors. +*/ +//#define JLS_BROKEN + + +/** + * Decode LSE block with initialization parameters + */ +int ff_jpegls_decode_lse(MJpegDecodeContext *s) +{ + int id; + + skip_bits(&s->gb, 16); /* length: FIXME: verify field validity */ + id = get_bits(&s->gb, 8); + + switch(id){ + case 1: + s->maxval= get_bits(&s->gb, 16); + s->t1= get_bits(&s->gb, 16); + s->t2= get_bits(&s->gb, 16); + s->t3= get_bits(&s->gb, 16); + s->reset= get_bits(&s->gb, 16); + +// ff_jpegls_reset_coding_parameters(s, 0); + //FIXME quant table? + break; + case 2: + case 3: + av_log(s->avctx, AV_LOG_ERROR, "palette not supported\n"); + return -1; + case 4: + av_log(s->avctx, AV_LOG_ERROR, "oversize image not supported\n"); + return -1; + default: + av_log(s->avctx, AV_LOG_ERROR, "invalid id %d\n", id); + return -1; + } + av_dlog(s->avctx, "ID=%i, T=%i,%i,%i\n", id, s->t1, s->t2, s->t3); + + return 0; +} + +/** + * Get context-dependent Golomb code, decode it and update context + */ +static inline int ls_get_code_regular(GetBitContext *gb, JLSState *state, int Q){ + int k, ret; + + for(k = 0; (state->N[Q] << k) < state->A[Q]; k++); + +#ifdef JLS_BROKEN + if(!show_bits_long(gb, 32))return -1; +#endif + ret = get_ur_golomb_jpegls(gb, k, state->limit, state->qbpp); + + /* decode mapped error */ + if(ret & 1) + ret = -((ret + 1) >> 1); + else + ret >>= 1; + + /* for NEAR=0, k=0 and 2*B[Q] <= - N[Q] mapping is reversed */ + if(!state->near && !k && (2 * state->B[Q] <= -state->N[Q])) + ret = -(ret + 1); + + ret= ff_jpegls_update_state_regular(state, Q, ret); + + return ret; +} + +/** + * Get Golomb code, decode it and update state for run termination + */ +static inline int ls_get_code_runterm(GetBitContext *gb, JLSState *state, int RItype, int limit_add){ + int k, ret, temp, map; + int Q = 365 + RItype; + + temp= state->A[Q]; + if(RItype) + temp += state->N[Q] >> 1; + + for(k = 0; (state->N[Q] << k) < temp; k++); + +#ifdef JLS_BROKEN + if(!show_bits_long(gb, 32))return -1; +#endif + ret = get_ur_golomb_jpegls(gb, k, state->limit - limit_add - 1, state->qbpp); + + /* decode mapped error */ + map = 0; + if(!k && (RItype || ret) && (2 * state->B[Q] < state->N[Q])) + map = 1; + ret += RItype + map; + + if(ret & 1){ + ret = map - ((ret + 1) >> 1); + state->B[Q]++; + } else { + ret = ret >> 1; + } + + /* update state */ + state->A[Q] += FFABS(ret) - RItype; + ret *= state->twonear; + ff_jpegls_downscale_state(state, Q); + + return ret; +} + +/** + * Decode one line of image + */ +static inline void ls_decode_line(JLSState *state, MJpegDecodeContext *s, void *last, void *dst, int last2, int w, int stride, int comp, int bits){ + int i, x = 0; + int Ra, Rb, Rc, Rd; + int D0, D1, D2; + + while(x < w) { + int err, pred; + + /* compute gradients */ + Ra = x ? R(dst, x - stride) : R(last, x); + Rb = R(last, x); + Rc = x ? R(last, x - stride) : last2; + Rd = (x >= w - stride) ? R(last, x) : R(last, x + stride); + D0 = Rd - Rb; + D1 = Rb - Rc; + D2 = Rc - Ra; + /* run mode */ + if((FFABS(D0) <= state->near) && (FFABS(D1) <= state->near) && (FFABS(D2) <= state->near)) { + int r; + int RItype; + + /* decode full runs while available */ + while(get_bits1(&s->gb)) { + int r; + r = 1 << ff_log2_run[state->run_index[comp]]; + if(x + r * stride > w) { + r = (w - x) / stride; + } + for(i = 0; i < r; i++) { + W(dst, x, Ra); + x += stride; + } + /* if EOL reached, we stop decoding */ + if(r != (1 << ff_log2_run[state->run_index[comp]])) + return; + if(state->run_index[comp] < 31) + state->run_index[comp]++; + if(x + stride > w) + return; + } + /* decode aborted run */ + r = ff_log2_run[state->run_index[comp]]; + if(r) + r = get_bits_long(&s->gb, r); + if(x + r * stride > w) { + r = (w - x) / stride; + } + for(i = 0; i < r; i++) { + W(dst, x, Ra); + x += stride; + } + + /* decode run termination value */ + Rb = R(last, x); + RItype = (FFABS(Ra - Rb) <= state->near) ? 1 : 0; + err = ls_get_code_runterm(&s->gb, state, RItype, ff_log2_run[state->run_index[comp]]); + if(state->run_index[comp]) + state->run_index[comp]--; + + if(state->near && RItype){ + pred = Ra + err; + } else { + if(Rb < Ra) + pred = Rb - err; + else + pred = Rb + err; + } + } else { /* regular mode */ + int context, sign; + + context = ff_jpegls_quantize(state, D0) * 81 + ff_jpegls_quantize(state, D1) * 9 + ff_jpegls_quantize(state, D2); + pred = mid_pred(Ra, Ra + Rb - Rc, Rb); + + if(context < 0){ + context = -context; + sign = 1; + }else{ + sign = 0; + } + + if(sign){ + pred = av_clip(pred - state->C[context], 0, state->maxval); + err = -ls_get_code_regular(&s->gb, state, context); + } else { + pred = av_clip(pred + state->C[context], 0, state->maxval); + err = ls_get_code_regular(&s->gb, state, context); + } + + /* we have to do something more for near-lossless coding */ + pred += err; + } + if(state->near){ + if(pred < -state->near) + pred += state->range * state->twonear; + else if(pred > state->maxval + state->near) + pred -= state->range * state->twonear; + pred = av_clip(pred, 0, state->maxval); + } + + pred &= state->maxval; + W(dst, x, pred); + x += stride; + } +} + +int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transform, int ilv){ + int i, t = 0; + uint8_t *zero, *last, *cur; + JLSState *state; + int off = 0, stride = 1, width, shift; + + zero = av_mallocz(s->picture.linesize[0]); + last = zero; + cur = s->picture.data[0]; + + state = av_mallocz(sizeof(JLSState)); + /* initialize JPEG-LS state from JPEG parameters */ + state->near = near; + state->bpp = (s->bits < 2) ? 2 : s->bits; + state->maxval = s->maxval; + state->T1 = s->t1; + state->T2 = s->t2; + state->T3 = s->t3; + state->reset = s->reset; + ff_jpegls_reset_coding_parameters(state, 0); + ff_jpegls_init_state(state); + + if(s->bits <= 8) + shift = point_transform + (8 - s->bits); + else + shift = point_transform + (16 - s->bits); + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(s->avctx, AV_LOG_DEBUG, "JPEG-LS params: %ix%i NEAR=%i MV=%i T(%i,%i,%i) RESET=%i, LIMIT=%i, qbpp=%i, RANGE=%i\n", + s->width, s->height, state->near, state->maxval, + state->T1, state->T2, state->T3, + state->reset, state->limit, state->qbpp, state->range); + av_log(s->avctx, AV_LOG_DEBUG, "JPEG params: ILV=%i Pt=%i BPP=%i, scan = %i\n", + ilv, point_transform, s->bits, s->cur_scan); + } + if(ilv == 0) { /* separate planes */ + stride = (s->nb_components > 1) ? 3 : 1; + off = av_clip(s->cur_scan - 1, 0, stride - 1); + width = s->width * stride; + cur += off; + for(i = 0; i < s->height; i++) { + if(s->bits <= 8){ + ls_decode_line(state, s, last, cur, t, width, stride, off, 8); + t = last[0]; + }else{ + ls_decode_line(state, s, last, cur, t, width, stride, off, 16); + t = *((uint16_t*)last); + } + last = cur; + cur += s->picture.linesize[0]; + + if (s->restart_interval && !--s->restart_count) { + align_get_bits(&s->gb); + skip_bits(&s->gb, 16); /* skip RSTn */ + } + } + } else if(ilv == 1) { /* line interleaving */ + int j; + int Rc[3] = {0, 0, 0}; + stride = (s->nb_components > 1) ? 3 : 1; + memset(cur, 0, s->picture.linesize[0]); + width = s->width * stride; + for(i = 0; i < s->height; i++) { + for(j = 0; j < stride; j++) { + ls_decode_line(state, s, last + j, cur + j, Rc[j], width, stride, j, 8); + Rc[j] = last[j]; + + if (s->restart_interval && !--s->restart_count) { + align_get_bits(&s->gb); + skip_bits(&s->gb, 16); /* skip RSTn */ + } + } + last = cur; + cur += s->picture.linesize[0]; + } + } else if(ilv == 2) { /* sample interleaving */ + av_log(s->avctx, AV_LOG_ERROR, "Sample interleaved images are not supported.\n"); + av_free(state); + av_free(zero); + return -1; + } + + if(shift){ /* we need to do point transform or normalize samples */ + int x, w; + + w = s->width * s->nb_components; + + if(s->bits <= 8){ + uint8_t *src = s->picture.data[0]; + + for(i = 0; i < s->height; i++){ + for(x = off; x < w; x+= stride){ + src[x] <<= shift; + } + src += s->picture.linesize[0]; + } + }else{ + uint16_t *src = (uint16_t*) s->picture.data[0]; + + for(i = 0; i < s->height; i++){ + for(x = 0; x < w; x++){ + src[x] <<= shift; + } + src += s->picture.linesize[0]/2; + } + } + } + av_free(state); + av_free(zero); + + return 0; +} + + +AVCodec ff_jpegls_decoder = { + .name = "jpegls", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEGLS, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = ff_mjpeg_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), +}; diff --git a/ffmpeg/libavcodec/jpeglsdec.h b/ffmpeg/libavcodec/jpeglsdec.h new file mode 100644 index 0000000..5204ecb --- /dev/null +++ b/ffmpeg/libavcodec/jpeglsdec.h @@ -0,0 +1,41 @@ +/* + * JPEG-LS decoder + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * JPEG-LS decoder. + */ + +#ifndef AVCODEC_JPEGLSDEC_H +#define AVCODEC_JPEGLSDEC_H + +#include "mjpeg.h" +#include "mjpegdec.h" + +/** + * Decode LSE block with initialization parameters + */ +int ff_jpegls_decode_lse(MJpegDecodeContext *s); + +int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, int point_transform, int ilv); + +#endif /* AVCODEC_JPEGLSDEC_H */ diff --git a/ffmpeg/libavcodec/jpeglsenc.c b/ffmpeg/libavcodec/jpeglsenc.c new file mode 100644 index 0000000..be979aa --- /dev/null +++ b/ffmpeg/libavcodec/jpeglsenc.c @@ -0,0 +1,409 @@ +/* + * JPEG-LS encoder + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * JPEG-LS encoder. + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "put_bits.h" +#include "golomb.h" +#include "internal.h" +#include "mathops.h" +#include "mjpeg.h" +#include "jpegls.h" + + +/** + * Encode error from regular symbol + */ +static inline void ls_encode_regular(JLSState *state, PutBitContext *pb, int Q, int err){ + int k; + int val; + int map; + + for(k = 0; (state->N[Q] << k) < state->A[Q]; k++); + + map = !state->near && !k && (2 * state->B[Q] <= -state->N[Q]); + + if(err < 0) + err += state->range; + if(err >= ((state->range + 1) >> 1)) { + err -= state->range; + val = 2 * FFABS(err) - 1 - map; + } else + val = 2 * err + map; + + set_ur_golomb_jpegls(pb, val, k, state->limit, state->qbpp); + + ff_jpegls_update_state_regular(state, Q, err); +} + +/** + * Encode error from run termination + */ +static inline void ls_encode_runterm(JLSState *state, PutBitContext *pb, int RItype, int err, int limit_add){ + int k; + int val, map; + int Q = 365 + RItype; + int temp; + + temp = state->A[Q]; + if(RItype) + temp += state->N[Q] >> 1; + for(k = 0; (state->N[Q] << k) < temp; k++); + map = 0; + if(!k && err && (2 * state->B[Q] < state->N[Q])) + map = 1; + + if(err < 0) + val = - (2 * err) - 1 - RItype + map; + else + val = 2 * err - RItype - map; + set_ur_golomb_jpegls(pb, val, k, state->limit - limit_add - 1, state->qbpp); + + if(err < 0) + state->B[Q]++; + state->A[Q] += (val + 1 - RItype) >> 1; + + ff_jpegls_downscale_state(state, Q); +} + +/** + * Encode run value as specified by JPEG-LS standard + */ +static inline void ls_encode_run(JLSState *state, PutBitContext *pb, int run, int comp, int trail){ + while(run >= (1 << ff_log2_run[state->run_index[comp]])){ + put_bits(pb, 1, 1); + run -= 1 << ff_log2_run[state->run_index[comp]]; + if(state->run_index[comp] < 31) + state->run_index[comp]++; + } + /* if hit EOL, encode another full run, else encode aborted run */ + if(!trail && run) { + put_bits(pb, 1, 1); + }else if(trail){ + put_bits(pb, 1, 0); + if(ff_log2_run[state->run_index[comp]]) + put_bits(pb, ff_log2_run[state->run_index[comp]], run); + } +} + +/** + * Encode one line of image + */ +static inline void ls_encode_line(JLSState *state, PutBitContext *pb, void *last, void *cur, int last2, int w, int stride, int comp, int bits){ + int x = 0; + int Ra, Rb, Rc, Rd; + int D0, D1, D2; + + while(x < w) { + int err, pred, sign; + + /* compute gradients */ + Ra = x ? R(cur, x - stride) : R(last, x); + Rb = R(last, x); + Rc = x ? R(last, x - stride) : last2; + Rd = (x >= w - stride) ? R(last, x) : R(last, x + stride); + D0 = Rd - Rb; + D1 = Rb - Rc; + D2 = Rc - Ra; + + /* run mode */ + if((FFABS(D0) <= state->near) && (FFABS(D1) <= state->near) && (FFABS(D2) <= state->near)) { + int RUNval, RItype, run; + + run = 0; + RUNval = Ra; + while(x < w && (FFABS(R(cur, x) - RUNval) <= state->near)){ + run++; + W(cur, x, Ra); + x += stride; + } + ls_encode_run(state, pb, run, comp, x < w); + if(x >= w) + return; + Rb = R(last, x); + RItype = (FFABS(Ra - Rb) <= state->near); + pred = RItype ? Ra : Rb; + err = R(cur, x) - pred; + + if(!RItype && Ra > Rb) + err = -err; + + if(state->near){ + if(err > 0) + err = (state->near + err) / state->twonear; + else + err = -(state->near - err) / state->twonear; + + if(RItype || (Rb >= Ra)) + Ra = av_clip(pred + err * state->twonear, 0, state->maxval); + else + Ra = av_clip(pred - err * state->twonear, 0, state->maxval); + W(cur, x, Ra); + } + if(err < 0) + err += state->range; + if(err >= ((state->range + 1) >> 1)) + err -= state->range; + + ls_encode_runterm(state, pb, RItype, err, ff_log2_run[state->run_index[comp]]); + + if(state->run_index[comp] > 0) + state->run_index[comp]--; + } else { /* regular mode */ + int context; + + context = ff_jpegls_quantize(state, D0) * 81 + ff_jpegls_quantize(state, D1) * 9 + ff_jpegls_quantize(state, D2); + pred = mid_pred(Ra, Ra + Rb - Rc, Rb); + + if(context < 0){ + context = -context; + sign = 1; + pred = av_clip(pred - state->C[context], 0, state->maxval); + err = pred - R(cur, x); + }else{ + sign = 0; + pred = av_clip(pred + state->C[context], 0, state->maxval); + err = R(cur, x) - pred; + } + + if(state->near){ + if(err > 0) + err = (state->near + err) / state->twonear; + else + err = -(state->near - err) / state->twonear; + if(!sign) + Ra = av_clip(pred + err * state->twonear, 0, state->maxval); + else + Ra = av_clip(pred - err * state->twonear, 0, state->maxval); + W(cur, x, Ra); + } + + ls_encode_regular(state, pb, context, err); + } + x += stride; + } +} + +static void ls_store_lse(JLSState *state, PutBitContext *pb){ + /* Test if we have default params and don't need to store LSE */ + JLSState state2 = { 0 }; + state2.bpp = state->bpp; + state2.near = state->near; + ff_jpegls_reset_coding_parameters(&state2, 1); + if(state->T1 == state2.T1 && state->T2 == state2.T2 && state->T3 == state2.T3 && state->reset == state2.reset) + return; + /* store LSE type 1 */ + put_marker(pb, LSE); + put_bits(pb, 16, 13); + put_bits(pb, 8, 1); + put_bits(pb, 16, state->maxval); + put_bits(pb, 16, state->T1); + put_bits(pb, 16, state->T2); + put_bits(pb, 16, state->T3); + put_bits(pb, 16, state->reset); +} + +static int encode_picture_ls(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + JpeglsContext * const s = avctx->priv_data; + AVFrame * const p = &s->picture; + const int near = avctx->prediction_method; + PutBitContext pb, pb2; + GetBitContext gb; + uint8_t *buf2, *zero, *cur, *last; + JLSState *state; + int i, size, ret; + int comps; + + *p = *pict; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + if(avctx->pix_fmt == AV_PIX_FMT_GRAY8 || avctx->pix_fmt == AV_PIX_FMT_GRAY16) + comps = 1; + else + comps = 3; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*comps*4 + + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + buf2 = av_malloc(pkt->size); + + init_put_bits(&pb, pkt->data, pkt->size); + init_put_bits(&pb2, buf2, pkt->size); + + /* write our own JPEG header, can't use mjpeg_picture_header */ + put_marker(&pb, SOI); + put_marker(&pb, SOF48); + put_bits(&pb, 16, 8 + comps * 3); // header size depends on components + put_bits(&pb, 8, (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8); // bpp + put_bits(&pb, 16, avctx->height); + put_bits(&pb, 16, avctx->width); + put_bits(&pb, 8, comps); // components + for(i = 1; i <= comps; i++) { + put_bits(&pb, 8, i); // component ID + put_bits(&pb, 8, 0x11); // subsampling: none + put_bits(&pb, 8, 0); // Tiq, used by JPEG-LS ext + } + + put_marker(&pb, SOS); + put_bits(&pb, 16, 6 + comps * 2); + put_bits(&pb, 8, comps); + for(i = 1; i <= comps; i++) { + put_bits(&pb, 8, i); // component ID + put_bits(&pb, 8, 0); // mapping index: none + } + put_bits(&pb, 8, near); + put_bits(&pb, 8, (comps > 1) ? 1 : 0); // interleaving: 0 - plane, 1 - line + put_bits(&pb, 8, 0); // point transform: none + + state = av_mallocz(sizeof(JLSState)); + /* initialize JPEG-LS state from JPEG parameters */ + state->near = near; + state->bpp = (avctx->pix_fmt == AV_PIX_FMT_GRAY16) ? 16 : 8; + ff_jpegls_reset_coding_parameters(state, 0); + ff_jpegls_init_state(state); + + ls_store_lse(state, &pb); + + zero = av_mallocz(FFABS(p->linesize[0])); + if (!zero) { + av_free(state); + return AVERROR(ENOMEM); + } + last = zero; + cur = p->data[0]; + if(avctx->pix_fmt == AV_PIX_FMT_GRAY8){ + int t = 0; + + for(i = 0; i < avctx->height; i++) { + ls_encode_line(state, &pb2, last, cur, t, avctx->width, 1, 0, 8); + t = last[0]; + last = cur; + cur += p->linesize[0]; + } + }else if(avctx->pix_fmt == AV_PIX_FMT_GRAY16){ + int t = 0; + + for(i = 0; i < avctx->height; i++) { + ls_encode_line(state, &pb2, last, cur, t, avctx->width, 1, 0, 16); + t = *((uint16_t*)last); + last = cur; + cur += p->linesize[0]; + } + }else if(avctx->pix_fmt == AV_PIX_FMT_RGB24){ + int j, width; + int Rc[3] = {0, 0, 0}; + + width = avctx->width * 3; + for(i = 0; i < avctx->height; i++) { + for(j = 0; j < 3; j++) { + ls_encode_line(state, &pb2, last + j, cur + j, Rc[j], width, 3, j, 8); + Rc[j] = last[j]; + } + last = cur; + cur += s->picture.linesize[0]; + } + }else if(avctx->pix_fmt == AV_PIX_FMT_BGR24){ + int j, width; + int Rc[3] = {0, 0, 0}; + + width = avctx->width * 3; + for(i = 0; i < avctx->height; i++) { + for(j = 2; j >= 0; j--) { + ls_encode_line(state, &pb2, last + j, cur + j, Rc[j], width, 3, j, 8); + Rc[j] = last[j]; + } + last = cur; + cur += s->picture.linesize[0]; + } + } + + av_freep(&zero); + av_freep(&state); + + // the specification says that after doing 0xff escaping unused bits in the + // last byte must be set to 0, so just append 7 "optional" zero-bits to + // avoid special-casing. + put_bits(&pb2, 7, 0); + size = put_bits_count(&pb2); + flush_put_bits(&pb2); + /* do escape coding */ + init_get_bits(&gb, buf2, size); + size -= 7; + while(get_bits_count(&gb) < size){ + int v; + v = get_bits(&gb, 8); + put_bits(&pb, 8, v); + if(v == 0xFF){ + v = get_bits(&gb, 7); + put_bits(&pb, 8, v); + } + } + avpriv_align_put_bits(&pb); + av_free(buf2); + + /* End of image */ + put_marker(&pb, EOI); + flush_put_bits(&pb); + + emms_c(); + + pkt->size = put_bits_count(&pb) >> 3; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int encode_init_ls(AVCodecContext *ctx) { + JpeglsContext *c = (JpeglsContext*)ctx->priv_data; + + c->avctx = ctx; + ctx->coded_frame = &c->picture; + + if(ctx->pix_fmt != AV_PIX_FMT_GRAY8 && ctx->pix_fmt != AV_PIX_FMT_GRAY16 && ctx->pix_fmt != AV_PIX_FMT_RGB24 && ctx->pix_fmt != AV_PIX_FMT_BGR24){ + av_log(ctx, AV_LOG_ERROR, "Only grayscale and RGB24/BGR24 images are supported\n"); + return -1; + } + return 0; +} + +AVCodec ff_jpegls_encoder = { + .name = "jpegls", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEGLS, + .priv_data_size = sizeof(JpeglsContext), + .init = encode_init_ls, + .encode2 = encode_picture_ls, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), +}; diff --git a/ffmpeg/libavcodec/jrevdct.c b/ffmpeg/libavcodec/jrevdct.c new file mode 100644 index 0000000..91780b2 --- /dev/null +++ b/ffmpeg/libavcodec/jrevdct.c @@ -0,0 +1,1155 @@ +/* + * This file is part of the Independent JPEG Group's software. + * + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and + * you, its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1991, 1992, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to + * these conditions: + * (1) If any part of the source code for this software is distributed, then + * this README file must be included, with this copyright and no-warranty + * notice unaltered; and any additions, deletions, or changes to the original + * files must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work + * of the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG + * code, not just to the unmodified library. If you use our work, you ought + * to acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company + * name in advertising or publicity relating to this software or products + * derived from it. This software may be referred to only as "the Independent + * JPEG Group's software". + * + * We specifically permit and encourage the use of this software as the basis + * of commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + * + * This file contains the basic inverse-DCT transformation subroutine. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * I've made lots of modifications to attempt to take advantage of the + * sparse nature of the DCT matrices we're getting. Although the logic + * is cumbersome, it's straightforward and the resulting code is much + * faster. + * + * A better way to do this would be to pass in the DCT block as a sparse + * matrix, perhaps with the difference cases encoded. + */ + +/** + * @file + * Independent JPEG Group's LLM idct. + */ + +#include "libavutil/common.h" +#include "dct.h" + +#define EIGHT_BIT_SAMPLES + +#define DCTSIZE 8 +#define DCTSIZE2 64 + +#define GLOBAL + +#define RIGHT_SHIFT(x, n) ((x) >> (n)) + +typedef int16_t DCTBLOCK[DCTSIZE2]; + +#define CONST_BITS 13 + +/* + * This routine is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate int32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#ifdef EIGHT_BIT_SAMPLES +#define PASS1_BITS 2 +#else +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +#define ONE ((int32_t) 1) + +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * IMPORTANT: if your compiler doesn't do this arithmetic at compile time, + * you will pay a significant penalty in run time. In that case, figure + * the correct integer constant values and insert them by hand. + */ + +/* Actually FIX is no longer used, we precomputed them all */ +#define FIX(x) ((int32_t) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an int32_t value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an int32_t variable by an int32_t constant to yield an int32_t result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; + * this provides a useful speedup on many machines. + * There is no way to specify a 16x16->32 multiply in portable C, but + * some C compilers will do the right thing if you provide the correct + * combination of casts. + * NB: for 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#ifdef EIGHT_BIT_SAMPLES +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY(var,const) (((int16_t) (var)) * ((int16_t) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY(var,const) (((int16_t) (var)) * ((int32_t) (const))) +#endif +#endif + +#ifndef MULTIPLY /* default definition */ +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + Unlike our decoder where we approximate the FIXes, we need to use exact +ones here or successive P-frames will drift too much with Reference frame coding +*/ +#define FIX_0_211164243 1730 +#define FIX_0_275899380 2260 +#define FIX_0_298631336 2446 +#define FIX_0_390180644 3196 +#define FIX_0_509795579 4176 +#define FIX_0_541196100 4433 +#define FIX_0_601344887 4926 +#define FIX_0_765366865 6270 +#define FIX_0_785694958 6436 +#define FIX_0_899976223 7373 +#define FIX_1_061594337 8697 +#define FIX_1_111140466 9102 +#define FIX_1_175875602 9633 +#define FIX_1_306562965 10703 +#define FIX_1_387039845 11363 +#define FIX_1_451774981 11893 +#define FIX_1_501321110 12299 +#define FIX_1_662939225 13623 +#define FIX_1_847759065 15137 +#define FIX_1_961570560 16069 +#define FIX_2_053119869 16819 +#define FIX_2_172734803 17799 +#define FIX_2_562915447 20995 +#define FIX_3_072711026 25172 + +/* + * Perform the inverse DCT on one block of coefficients. + */ + +void ff_j_rev_dct(DCTBLOCK data) +{ + int32_t tmp0, tmp1, tmp2, tmp3; + int32_t tmp10, tmp11, tmp12, tmp13; + int32_t z1, z2, z3, z4, z5; + int32_t d0, d1, d2, d3, d4, d5, d6, d7; + register int16_t *dataptr; + int rowctr; + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any row in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * row DCT calculations can be simplified this way. + */ + + register int *idataptr = (int*)dataptr; + + /* WARNING: we do the same permutation as MMX idct to simplify the + video core */ + d0 = dataptr[0]; + d2 = dataptr[1]; + d4 = dataptr[2]; + d6 = dataptr[3]; + d1 = dataptr[4]; + d3 = dataptr[5]; + d5 = dataptr[6]; + d7 = dataptr[7]; + + if ((d1 | d2 | d3 | d4 | d5 | d6 | d7) == 0) { + /* AC terms all zero */ + if (d0) { + /* Compute a 32 bit value to assign. */ + int16_t dcval = (int16_t) (d0 << PASS1_BITS); + register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000); + + idataptr[0] = v; + idataptr[1] = v; + idataptr[2] = v; + idataptr[3] = v; + } + + dataptr += DCTSIZE; /* advance pointer to next row */ + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ +{ + if (d6) { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } + } else { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } + } + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + if (d7) { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5 + d3; + z3 = d7 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ + z2 = d5 + d3; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d5, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d5, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 = z1 + z4; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z4 = d5 + d1; + z5 = MULTIPLY(d7 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z3 = MULTIPLY(-d7, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 = z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z5 = MULTIPLY(d5 + d7, FIX_1_175875602); + + z3 += z5; + z4 += z5; + + tmp0 += z3; + tmp1 += z4; + tmp2 = z2 + z3; + tmp3 = z1 + z4; + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d1, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d1, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 = z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ + z3 = d7 + d3; + + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + tmp2 = MULTIPLY(d3, FIX_0_509795579); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z5 = MULTIPLY(z3, FIX_1_175875602); + z3 = MULTIPLY(-z3, FIX_0_785694958); + + tmp0 += z3; + tmp1 = z2 + z5; + tmp2 += z3; + tmp3 = z1 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z5 = MULTIPLY(z1, FIX_1_175875602); + + z1 = MULTIPLY(z1, FIX_0_275899380); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp0 = MULTIPLY(-d7, FIX_1_662939225); + z4 = MULTIPLY(-d1, FIX_0_390180644); + tmp3 = MULTIPLY(d1, FIX_1_111140466); + + tmp0 += z1; + tmp1 = z4 + z5; + tmp2 = z3 + z5; + tmp3 += z1; + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_1_387039845); + tmp1 = MULTIPLY(d7, FIX_1_175875602); + tmp2 = MULTIPLY(-d7, FIX_0_785694958); + tmp3 = MULTIPLY(d7, FIX_0_275899380); + } + } + } + } else { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(d3 + z4, FIX_1_175875602); + + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-d1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-d3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 = z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + + z5 = MULTIPLY(z2, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_1_662939225); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z2 = MULTIPLY(-z2, FIX_1_387039845); + tmp2 = MULTIPLY(d3, FIX_1_111140466); + z3 = MULTIPLY(-d3, FIX_1_961570560); + + tmp0 = z3 + z5; + tmp1 += z2; + tmp2 += z2; + tmp3 = z4 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ + z4 = d5 + d1; + + z5 = MULTIPLY(z4, FIX_1_175875602); + z1 = MULTIPLY(-d1, FIX_0_899976223); + tmp3 = MULTIPLY(d1, FIX_0_601344887); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(z4, FIX_0_785694958); + + tmp0 = z1 + z5; + tmp1 += z4; + tmp2 = z2 + z5; + tmp3 += z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ + tmp0 = MULTIPLY(d5, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_0_275899380); + tmp2 = MULTIPLY(-d5, FIX_1_387039845); + tmp3 = MULTIPLY(d5, FIX_0_785694958); + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ + z5 = d1 + d3; + tmp3 = MULTIPLY(d1, FIX_0_211164243); + tmp2 = MULTIPLY(-d3, FIX_1_451774981); + z1 = MULTIPLY(d1, FIX_1_061594337); + z2 = MULTIPLY(-d3, FIX_2_172734803); + z4 = MULTIPLY(z5, FIX_0_785694958); + z5 = MULTIPLY(z5, FIX_1_175875602); + + tmp0 = z1 - z4; + tmp1 = z2 + z4; + tmp2 += z5; + tmp3 += z5; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(-d3, FIX_0_785694958); + tmp1 = MULTIPLY(-d3, FIX_1_387039845); + tmp2 = MULTIPLY(-d3, FIX_0_275899380); + tmp3 = MULTIPLY(d3, FIX_1_175875602); + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(d1, FIX_0_275899380); + tmp1 = MULTIPLY(d1, FIX_0_785694958); + tmp2 = MULTIPLY(d1, FIX_1_175875602); + tmp3 = MULTIPLY(d1, FIX_1_387039845); + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = tmp1 = tmp2 = tmp3 = 0; + } + } + } + } +} + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[0] = (int16_t) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + dataptr[7] = (int16_t) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + dataptr[1] = (int16_t) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + dataptr[6] = (int16_t) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + dataptr[2] = (int16_t) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (int16_t) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + dataptr[3] = (int16_t) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + dataptr[4] = (int16_t) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + dataptr = data; + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Columns of zeroes can be exploited in the same way as we did with rows. + * However, the row calculation has created many nonzero AC terms, so the + * simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + + d0 = dataptr[DCTSIZE*0]; + d1 = dataptr[DCTSIZE*1]; + d2 = dataptr[DCTSIZE*2]; + d3 = dataptr[DCTSIZE*3]; + d4 = dataptr[DCTSIZE*4]; + d5 = dataptr[DCTSIZE*5]; + d6 = dataptr[DCTSIZE*6]; + d7 = dataptr[DCTSIZE*7]; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + if (d6) { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } + } else { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } + } + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + if (d7) { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5 + d3; + z3 = d7 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ + z2 = d5 + d3; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d5, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d5, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 = z1 + z4; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z3 = MULTIPLY(-d7, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 = z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z5 = MULTIPLY(d5 + d7, FIX_1_175875602); + + z3 += z5; + z4 += z5; + + tmp0 += z3; + tmp1 += z4; + tmp2 = z2 + z3; + tmp3 = z1 + z4; + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d1, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d1, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 = z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ + z3 = d7 + d3; + + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + tmp2 = MULTIPLY(d3, FIX_0_509795579); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z5 = MULTIPLY(z3, FIX_1_175875602); + z3 = MULTIPLY(-z3, FIX_0_785694958); + + tmp0 += z3; + tmp1 = z2 + z5; + tmp2 += z3; + tmp3 = z1 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z5 = MULTIPLY(z1, FIX_1_175875602); + + z1 = MULTIPLY(z1, FIX_0_275899380); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp0 = MULTIPLY(-d7, FIX_1_662939225); + z4 = MULTIPLY(-d1, FIX_0_390180644); + tmp3 = MULTIPLY(d1, FIX_1_111140466); + + tmp0 += z1; + tmp1 = z4 + z5; + tmp2 = z3 + z5; + tmp3 += z1; + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_1_387039845); + tmp1 = MULTIPLY(d7, FIX_1_175875602); + tmp2 = MULTIPLY(-d7, FIX_0_785694958); + tmp3 = MULTIPLY(d7, FIX_0_275899380); + } + } + } + } else { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(d3 + z4, FIX_1_175875602); + + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-d1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-d3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 = z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + + z5 = MULTIPLY(z2, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_1_662939225); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z2 = MULTIPLY(-z2, FIX_1_387039845); + tmp2 = MULTIPLY(d3, FIX_1_111140466); + z3 = MULTIPLY(-d3, FIX_1_961570560); + + tmp0 = z3 + z5; + tmp1 += z2; + tmp2 += z2; + tmp3 = z4 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ + z4 = d5 + d1; + + z5 = MULTIPLY(z4, FIX_1_175875602); + z1 = MULTIPLY(-d1, FIX_0_899976223); + tmp3 = MULTIPLY(d1, FIX_0_601344887); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(z4, FIX_0_785694958); + + tmp0 = z1 + z5; + tmp1 += z4; + tmp2 = z2 + z5; + tmp3 += z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ + tmp0 = MULTIPLY(d5, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_0_275899380); + tmp2 = MULTIPLY(-d5, FIX_1_387039845); + tmp3 = MULTIPLY(d5, FIX_0_785694958); + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ + z5 = d1 + d3; + tmp3 = MULTIPLY(d1, FIX_0_211164243); + tmp2 = MULTIPLY(-d3, FIX_1_451774981); + z1 = MULTIPLY(d1, FIX_1_061594337); + z2 = MULTIPLY(-d3, FIX_2_172734803); + z4 = MULTIPLY(z5, FIX_0_785694958); + z5 = MULTIPLY(z5, FIX_1_175875602); + + tmp0 = z1 - z4; + tmp1 = z2 + z4; + tmp2 += z5; + tmp3 += z5; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(-d3, FIX_0_785694958); + tmp1 = MULTIPLY(-d3, FIX_1_387039845); + tmp2 = MULTIPLY(-d3, FIX_0_275899380); + tmp3 = MULTIPLY(d3, FIX_1_175875602); + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(d1, FIX_0_275899380); + tmp1 = MULTIPLY(d1, FIX_0_785694958); + tmp2 = MULTIPLY(d1, FIX_1_175875602); + tmp3 = MULTIPLY(d1, FIX_1_387039845); + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = tmp1 = tmp2 = tmp3 = 0; + } + } + } + } + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[DCTSIZE*0] = (int16_t) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*7] = (int16_t) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*1] = (int16_t) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*6] = (int16_t) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*2] = (int16_t) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*5] = (int16_t) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*3] = (int16_t) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*4] = (int16_t) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3); + + dataptr++; /* advance pointer to next column */ + } +} + +#undef DCTSIZE +#define DCTSIZE 4 +#define DCTSTRIDE 8 + +void ff_j_rev_dct4(DCTBLOCK data) +{ + int32_t tmp0, tmp1, tmp2, tmp3; + int32_t tmp10, tmp11, tmp12, tmp13; + int32_t z1; + int32_t d0, d2, d4, d6; + register int16_t *dataptr; + int rowctr; + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + data[0] += 4; + + dataptr = data; + + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any row in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * row DCT calculations can be simplified this way. + */ + + register int *idataptr = (int*)dataptr; + + d0 = dataptr[0]; + d2 = dataptr[1]; + d4 = dataptr[2]; + d6 = dataptr[3]; + + if ((d2 | d4 | d6) == 0) { + /* AC terms all zero */ + if (d0) { + /* Compute a 32 bit value to assign. */ + int16_t dcval = (int16_t) (d0 << PASS1_BITS); + register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000); + + idataptr[0] = v; + idataptr[1] = v; + } + + dataptr += DCTSTRIDE; /* advance pointer to next row */ + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + if (d6) { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } + } else { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } + } + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[0] = (int16_t) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[1] = (int16_t) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[2] = (int16_t) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[3] = (int16_t) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSTRIDE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + dataptr = data; + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Columns of zeroes can be exploited in the same way as we did with rows. + * However, the row calculation has created many nonzero AC terms, so the + * simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + + d0 = dataptr[DCTSTRIDE*0]; + d2 = dataptr[DCTSTRIDE*1]; + d4 = dataptr[DCTSTRIDE*2]; + d6 = dataptr[DCTSTRIDE*3]; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + if (d6) { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } + } else { + if (d2) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } + } + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[DCTSTRIDE*0] = tmp10 >> (CONST_BITS+PASS1_BITS+3); + dataptr[DCTSTRIDE*1] = tmp11 >> (CONST_BITS+PASS1_BITS+3); + dataptr[DCTSTRIDE*2] = tmp12 >> (CONST_BITS+PASS1_BITS+3); + dataptr[DCTSTRIDE*3] = tmp13 >> (CONST_BITS+PASS1_BITS+3); + + dataptr++; /* advance pointer to next column */ + } +} + +void ff_j_rev_dct2(DCTBLOCK data){ + int d00, d01, d10, d11; + + data[0] += 4; + d00 = data[0+0*DCTSTRIDE] + data[1+0*DCTSTRIDE]; + d01 = data[0+0*DCTSTRIDE] - data[1+0*DCTSTRIDE]; + d10 = data[0+1*DCTSTRIDE] + data[1+1*DCTSTRIDE]; + d11 = data[0+1*DCTSTRIDE] - data[1+1*DCTSTRIDE]; + + data[0+0*DCTSTRIDE]= (d00 + d10)>>3; + data[1+0*DCTSTRIDE]= (d01 + d11)>>3; + data[0+1*DCTSTRIDE]= (d00 - d10)>>3; + data[1+1*DCTSTRIDE]= (d01 - d11)>>3; +} + +void ff_j_rev_dct1(DCTBLOCK data){ + data[0] = (data[0] + 4)>>3; +} + +#undef FIX +#undef CONST_BITS diff --git a/ffmpeg/libavcodec/jvdec.c b/ffmpeg/libavcodec/jvdec.c new file mode 100644 index 0000000..18cc73f --- /dev/null +++ b/ffmpeg/libavcodec/jvdec.c @@ -0,0 +1,220 @@ +/* + * Bitmap Brothers JV video decoder + * Copyright (c) 2011 Peter Ross + * + * 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 + */ + +/** + * @file + * Bitmap Brothers JV video decoder + * @author Peter Ross + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" + +typedef struct JvContext { + DSPContext dsp; + AVFrame frame; + uint32_t palette[AVPALETTE_COUNT]; + int palette_has_changed; +} JvContext; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + JvContext *s = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + ff_dsputil_init(&s->dsp, avctx); + avcodec_get_frame_defaults(&s->frame); + return 0; +} + +/** + * Decode 2x2 block + */ +static inline void decode2x2(GetBitContext *gb, uint8_t *dst, int linesize) +{ + int i, j, v[2]; + + switch (get_bits(gb, 2)) { + case 1: + v[0] = get_bits(gb, 8); + for (j = 0; j < 2; j++) + memset(dst + j*linesize, v[0], 2); + break; + case 2: + v[0] = get_bits(gb, 8); + v[1] = get_bits(gb, 8); + for (j = 0; j < 2; j++) + for (i = 0; i < 2; i++) + dst[j*linesize + i] = v[get_bits1(gb)]; + break; + case 3: + for (j = 0; j < 2; j++) + for (i = 0; i < 2; i++) + dst[j*linesize + i] = get_bits(gb, 8); + } +} + +/** + * Decode 4x4 block + */ +static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize) +{ + int i, j, v[2]; + + switch (get_bits(gb, 2)) { + case 1: + v[0] = get_bits(gb, 8); + for (j = 0; j < 4; j++) + memset(dst + j*linesize, v[0], 4); + break; + case 2: + v[0] = get_bits(gb, 8); + v[1] = get_bits(gb, 8); + for (j = 2; j >= 0; j -= 2) { + for (i = 0; i < 4; i++) + dst[j*linesize + i] = v[get_bits1(gb)]; + for (i = 0; i < 4; i++) + dst[(j+1)*linesize + i] = v[get_bits1(gb)]; + } + break; + case 3: + for (j = 0; j < 4; j += 2) + for (i = 0; i < 4; i += 2) + decode2x2(gb, dst + j*linesize + i, linesize); + } +} + +/** + * Decode 8x8 block + */ +static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize, DSPContext *dsp) +{ + int i, j, v[2]; + + switch (get_bits(gb, 2)) { + case 1: + v[0] = get_bits(gb, 8); + dsp->fill_block_tab[1](dst, v[0], linesize, 8); + break; + case 2: + v[0] = get_bits(gb, 8); + v[1] = get_bits(gb, 8); + for (j = 7; j >= 0; j--) + for (i = 0; i < 8; i++) + dst[j*linesize + i] = v[get_bits1(gb)]; + break; + case 3: + for (j = 0; j < 8; j += 4) + for (i = 0; i < 8; i += 4) + decode4x4(gb, dst + j*linesize + i, linesize); + } +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + JvContext *s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = buf + avpkt->size; + int video_size, video_type, i, j, ret; + + if (avpkt->size < 6) + return AVERROR_INVALIDDATA; + + video_size = AV_RL32(buf); + video_type = buf[4]; + buf += 5; + + if (video_size) { + if (video_size < 0 || video_size > avpkt->size - 5) { + av_log(avctx, AV_LOG_ERROR, "video size %d invalid\n", video_size); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + if (video_type == 0 || video_type == 1) { + GetBitContext gb; + init_get_bits(&gb, buf, 8 * video_size); + + for (j = 0; j < avctx->height; j += 8) + for (i = 0; i < avctx->width; i += 8) + decode8x8(&gb, s->frame.data[0] + j*s->frame.linesize[0] + i, + s->frame.linesize[0], &s->dsp); + + buf += video_size; + } else if (video_type == 2) { + int v = *buf++; + for (j = 0; j < avctx->height; j++) + memset(s->frame.data[0] + j*s->frame.linesize[0], v, avctx->width); + } else { + av_log(avctx, AV_LOG_WARNING, "unsupported frame type %i\n", video_type); + return AVERROR_INVALIDDATA; + } + } + + if (buf_end - buf >= AVPALETTE_COUNT * 3) { + for (i = 0; i < AVPALETTE_COUNT; i++) { + uint32_t pal = AV_RB24(buf); + s->palette[i] = 0xFFU << 24 | pal << 2 | ((pal >> 4) & 0x30303); + buf += 3; + } + s->palette_has_changed = 1; + } + + if (video_size) { + s->frame.key_frame = 1; + s->frame.pict_type = AV_PICTURE_TYPE_I; + s->frame.palette_has_changed = s->palette_has_changed; + s->palette_has_changed = 0; + memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + *got_frame = 1; + } + + return avpkt->size; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + JvContext *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_jv_decoder = { + .name = "jv", + .long_name = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JV, + .priv_data_size = sizeof(JvContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/kbdwin.c b/ffmpeg/libavcodec/kbdwin.c new file mode 100644 index 0000000..5a62e9d --- /dev/null +++ b/ffmpeg/libavcodec/kbdwin.c @@ -0,0 +1,47 @@ +/* + * 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 "libavutil/avassert.h" +#include "libavutil/mathematics.h" +#include "libavutil/attributes.h" +#include "kbdwin.h" + +#define BESSEL_I0_ITER 50 // default: 50 iterations of Bessel I0 approximation + +av_cold void ff_kbd_window_init(float *window, float alpha, int n) +{ + int i, j; + double sum = 0.0, bessel, tmp; + double local_window[FF_KBD_WINDOW_MAX]; + double alpha2 = (alpha * M_PI / n) * (alpha * M_PI / n); + + av_assert0(n <= FF_KBD_WINDOW_MAX); + + for (i = 0; i < n; i++) { + tmp = i * (n - i) * alpha2; + bessel = 1.0; + for (j = BESSEL_I0_ITER; j > 0; j--) + bessel = bessel * tmp / (j * j) + 1; + sum += bessel; + local_window[i] = sum; + } + + sum++; + for (i = 0; i < n; i++) + window[i] = sqrt(local_window[i] / sum); +} diff --git a/ffmpeg/libavcodec/kbdwin.h b/ffmpeg/libavcodec/kbdwin.h new file mode 100644 index 0000000..4b93975 --- /dev/null +++ b/ffmpeg/libavcodec/kbdwin.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef AVCODEC_KBDWIN_H +#define AVCODEC_KBDWIN_H + +/** + * Maximum window size for ff_kbd_window_init. + */ +#define FF_KBD_WINDOW_MAX 1024 + +/** + * Generate a Kaiser-Bessel Derived Window. + * @param window pointer to half window + * @param alpha determines window shape + * @param n size of half window, max FF_KBD_WINDOW_MAX + */ +void ff_kbd_window_init(float *window, float alpha, int n); + +#endif /* AVCODEC_KBDWIN_H */ diff --git a/ffmpeg/libavcodec/kgv1dec.c b/ffmpeg/libavcodec/kgv1dec.c new file mode 100644 index 0000000..9c48239 --- /dev/null +++ b/ffmpeg/libavcodec/kgv1dec.c @@ -0,0 +1,185 @@ +/* + * Kega Game Video (KGV1) decoder + * Copyright (c) 2010 Daniel Verkamp + * + * 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 + */ + +/** + * @file + * Kega Game Video decoder + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct { + AVCodecContext *avctx; + AVFrame prev; +} KgvContext; + +static void decode_flush(AVCodecContext *avctx) +{ + KgvContext * const c = avctx->priv_data; + + av_frame_unref(&c->prev); +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = buf + avpkt->size; + KgvContext * const c = avctx->priv_data; + int offsets[8]; + uint8_t *out, *prev; + int outcnt = 0, maxcnt; + int w, h, i, res; + + if (avpkt->size < 2) + return AVERROR_INVALIDDATA; + + w = (buf[0] + 1) * 8; + h = (buf[1] + 1) * 8; + buf += 2; + + if ((res = av_image_check_size(w, h, 0, avctx)) < 0) + return res; + + if (w != avctx->width || h != avctx->height) { + av_frame_unref(&c->prev); + avcodec_set_dimensions(avctx, w, h); + } + + maxcnt = w * h; + + if ((res = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return res; + out = frame->data[0]; + if (c->prev.data[0]) { + prev = c->prev.data[0]; + } else { + prev = NULL; + } + + for (i = 0; i < 8; i++) + offsets[i] = -1; + + while (outcnt < maxcnt && buf_end - 2 >= buf) { + int code = AV_RL16(buf); + buf += 2; + + if (!(code & 0x8000)) { + AV_WN16A(&out[2 * outcnt], code); // rgb555 pixel coded directly + outcnt++; + } else { + int count; + + if ((code & 0x6000) == 0x6000) { + // copy from previous frame + int oidx = (code >> 10) & 7; + int start; + + count = (code & 0x3FF) + 3; + + if (offsets[oidx] < 0) { + if (buf_end - 3 < buf) + break; + offsets[oidx] = AV_RL24(buf); + buf += 3; + } + + start = (outcnt + offsets[oidx]) % maxcnt; + + if (maxcnt - start < count || maxcnt - outcnt < count) + break; + + if (!prev) { + av_log(avctx, AV_LOG_ERROR, + "Frame reference does not exist\n"); + break; + } + + memcpy(out + 2 * outcnt, prev + 2 * start, 2 * count); + } else { + // copy from earlier in this frame + int offset = (code & 0x1FFF) + 1; + + if (!(code & 0x6000)) { + count = 2; + } else if ((code & 0x6000) == 0x2000) { + count = 3; + } else { + if (buf_end - 1 < buf) + break; + count = 4 + *buf++; + } + + if (outcnt < offset || maxcnt - outcnt < count) + break; + + av_memcpy_backptr(out + 2 * outcnt, 2 * offset, 2 * count); + } + outcnt += count; + } + } + + if (outcnt - maxcnt) + av_log(avctx, AV_LOG_DEBUG, "frame finished with %d diff\n", outcnt - maxcnt); + + av_frame_unref(&c->prev); + if ((res = av_frame_ref(&c->prev, frame)) < 0) + return res; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + KgvContext * const c = avctx->priv_data; + + c->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_RGB555; + avctx->flags |= CODEC_FLAG_EMU_EDGE; + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + decode_flush(avctx); + return 0; +} + +AVCodec ff_kgv1_decoder = { + .name = "kgv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_KGV1, + .priv_data_size = sizeof(KgvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .flush = decode_flush, + .long_name = NULL_IF_CONFIG_SMALL("Kega Game Video"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/kmvc.c b/ffmpeg/libavcodec/kmvc.c new file mode 100644 index 0000000..20aae67 --- /dev/null +++ b/ffmpeg/libavcodec/kmvc.c @@ -0,0 +1,442 @@ +/* + * KMVC decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Karl Morton's Video Codec decoder + */ + +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define KMVC_KEYFRAME 0x80 +#define KMVC_PALETTE 0x40 +#define KMVC_METHOD 0x0F +#define MAX_PALSIZE 256 + +/* + * Decoder context + */ +typedef struct KmvcContext { + AVCodecContext *avctx; + + int setpal; + int palsize; + uint32_t pal[MAX_PALSIZE]; + uint8_t *cur, *prev; + uint8_t *frm0, *frm1; + GetByteContext g; +} KmvcContext; + +typedef struct BitBuf { + int bits; + int bitbuf; +} BitBuf; + +#define BLK(data, x, y) data[(x) + (y) * 320] + +#define kmvc_init_getbits(bb, g) bb.bits = 7; bb.bitbuf = bytestream2_get_byte(g); + +#define kmvc_getbit(bb, g, res) {\ + res = 0; \ + if (bb.bitbuf & (1 << bb.bits)) res = 1; \ + bb.bits--; \ + if(bb.bits == -1) { \ + bb.bitbuf = bytestream2_get_byte(g); \ + bb.bits = 7; \ + } \ +} + +static int kmvc_decode_intra_8x8(KmvcContext * ctx, int w, int h) +{ + BitBuf bb; + int res, val; + int i, j; + int bx, by; + int l0x, l1x, l0y, l1y; + int mx, my; + + kmvc_init_getbits(bb, &ctx->g); + + for (by = 0; by < h; by += 8) + for (bx = 0; bx < w; bx += 8) { + if (!bytestream2_get_bytes_left(&ctx->g)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); + return AVERROR_INVALIDDATA; + } + kmvc_getbit(bb, &ctx->g, res); + if (!res) { // fill whole 8x8 block + val = bytestream2_get_byte(&ctx->g); + for (i = 0; i < 64; i++) + BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; + } else { // handle four 4x4 subblocks + for (i = 0; i < 4; i++) { + l0x = bx + (i & 1) * 4; + l0y = by + (i & 2) * 2; + kmvc_getbit(bb, &ctx->g, res); + if (!res) { + kmvc_getbit(bb, &ctx->g, res); + if (!res) { // fill whole 4x4 block + val = bytestream2_get_byte(&ctx->g); + for (j = 0; j < 16; j++) + BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; + } else { // copy block from already decoded place + val = bytestream2_get_byte(&ctx->g); + mx = val & 0xF; + my = val >> 4; + if ((l0x-mx) + 320*(l0y-my) < 0 || (l0x-mx) + 320*(l0y-my) > 316*196) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); + return AVERROR_INVALIDDATA; + } + for (j = 0; j < 16; j++) + BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = + BLK(ctx->cur, l0x + (j & 3) - mx, l0y + (j >> 2) - my); + } + } else { // descend to 2x2 sub-sub-blocks + for (j = 0; j < 4; j++) { + l1x = l0x + (j & 1) * 2; + l1y = l0y + (j & 2); + kmvc_getbit(bb, &ctx->g, res); + if (!res) { + kmvc_getbit(bb, &ctx->g, res); + if (!res) { // fill whole 2x2 block + val = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x, l1y) = val; + BLK(ctx->cur, l1x + 1, l1y) = val; + BLK(ctx->cur, l1x, l1y + 1) = val; + BLK(ctx->cur, l1x + 1, l1y + 1) = val; + } else { // copy block from already decoded place + val = bytestream2_get_byte(&ctx->g); + mx = val & 0xF; + my = val >> 4; + if ((l1x-mx) + 320*(l1y-my) < 0 || (l1x-mx) + 320*(l1y-my) > 318*198) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); + return AVERROR_INVALIDDATA; + } + BLK(ctx->cur, l1x, l1y) = BLK(ctx->cur, l1x - mx, l1y - my); + BLK(ctx->cur, l1x + 1, l1y) = + BLK(ctx->cur, l1x + 1 - mx, l1y - my); + BLK(ctx->cur, l1x, l1y + 1) = + BLK(ctx->cur, l1x - mx, l1y + 1 - my); + BLK(ctx->cur, l1x + 1, l1y + 1) = + BLK(ctx->cur, l1x + 1 - mx, l1y + 1 - my); + } + } else { // read values for block + BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); + } + } + } + } + } + } + + return 0; +} + +static int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h) +{ + BitBuf bb; + int res, val; + int i, j; + int bx, by; + int l0x, l1x, l0y, l1y; + int mx, my; + + kmvc_init_getbits(bb, &ctx->g); + + for (by = 0; by < h; by += 8) + for (bx = 0; bx < w; bx += 8) { + kmvc_getbit(bb, &ctx->g, res); + if (!res) { + kmvc_getbit(bb, &ctx->g, res); + if (!res) { // fill whole 8x8 block + if (!bytestream2_get_bytes_left(&ctx->g)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); + return AVERROR_INVALIDDATA; + } + val = bytestream2_get_byte(&ctx->g); + for (i = 0; i < 64; i++) + BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = val; + } else { // copy block from previous frame + for (i = 0; i < 64; i++) + BLK(ctx->cur, bx + (i & 0x7), by + (i >> 3)) = + BLK(ctx->prev, bx + (i & 0x7), by + (i >> 3)); + } + } else { // handle four 4x4 subblocks + if (!bytestream2_get_bytes_left(&ctx->g)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Data overrun\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < 4; i++) { + l0x = bx + (i & 1) * 4; + l0y = by + (i & 2) * 2; + kmvc_getbit(bb, &ctx->g, res); + if (!res) { + kmvc_getbit(bb, &ctx->g, res); + if (!res) { // fill whole 4x4 block + val = bytestream2_get_byte(&ctx->g); + for (j = 0; j < 16; j++) + BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = val; + } else { // copy block + val = bytestream2_get_byte(&ctx->g); + mx = (val & 0xF) - 8; + my = (val >> 4) - 8; + if ((l0x+mx) + 320*(l0y+my) < 0 || (l0x+mx) + 320*(l0y+my) > 318*198) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); + return AVERROR_INVALIDDATA; + } + for (j = 0; j < 16; j++) + BLK(ctx->cur, l0x + (j & 3), l0y + (j >> 2)) = + BLK(ctx->prev, l0x + (j & 3) + mx, l0y + (j >> 2) + my); + } + } else { // descend to 2x2 sub-sub-blocks + for (j = 0; j < 4; j++) { + l1x = l0x + (j & 1) * 2; + l1y = l0y + (j & 2); + kmvc_getbit(bb, &ctx->g, res); + if (!res) { + kmvc_getbit(bb, &ctx->g, res); + if (!res) { // fill whole 2x2 block + val = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x, l1y) = val; + BLK(ctx->cur, l1x + 1, l1y) = val; + BLK(ctx->cur, l1x, l1y + 1) = val; + BLK(ctx->cur, l1x + 1, l1y + 1) = val; + } else { // copy block + val = bytestream2_get_byte(&ctx->g); + mx = (val & 0xF) - 8; + my = (val >> 4) - 8; + if ((l1x+mx) + 320*(l1y+my) < 0 || (l1x+mx) + 320*(l1y+my) > 318*198) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid MV\n"); + return AVERROR_INVALIDDATA; + } + BLK(ctx->cur, l1x, l1y) = BLK(ctx->prev, l1x + mx, l1y + my); + BLK(ctx->cur, l1x + 1, l1y) = + BLK(ctx->prev, l1x + 1 + mx, l1y + my); + BLK(ctx->cur, l1x, l1y + 1) = + BLK(ctx->prev, l1x + mx, l1y + 1 + my); + BLK(ctx->cur, l1x + 1, l1y + 1) = + BLK(ctx->prev, l1x + 1 + mx, l1y + 1 + my); + } + } else { // read values for block + BLK(ctx->cur, l1x, l1y) = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x + 1, l1y) = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x, l1y + 1) = bytestream2_get_byte(&ctx->g); + BLK(ctx->cur, l1x + 1, l1y + 1) = bytestream2_get_byte(&ctx->g); + } + } + } + } + } + } + + return 0; +} + +static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + KmvcContext *const ctx = avctx->priv_data; + AVFrame *frame = data; + uint8_t *out, *src; + int i, ret; + int header; + int blocksize; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + bytestream2_init(&ctx->g, avpkt->data, avpkt->size); + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + header = bytestream2_get_byte(&ctx->g); + + /* blocksize 127 is really palette change event */ + if (bytestream2_peek_byte(&ctx->g) == 127) { + bytestream2_skip(&ctx->g, 3); + for (i = 0; i < 127; i++) { + ctx->pal[i + (header & 0x81)] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); + bytestream2_skip(&ctx->g, 1); + } + bytestream2_seek(&ctx->g, -127 * 4 - 3, SEEK_CUR); + } + + if (header & KMVC_KEYFRAME) { + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + } else { + frame->key_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_P; + } + + if (header & KMVC_PALETTE) { + frame->palette_has_changed = 1; + // palette starts from index 1 and has 127 entries + for (i = 1; i <= ctx->palsize; i++) { + ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g); + } + } + + if (pal) { + frame->palette_has_changed = 1; + memcpy(ctx->pal, pal, AVPALETTE_SIZE); + } + + if (ctx->setpal) { + ctx->setpal = 0; + frame->palette_has_changed = 1; + } + + /* make the palette available on the way out */ + memcpy(frame->data[1], ctx->pal, 1024); + + blocksize = bytestream2_get_byte(&ctx->g); + + if (blocksize != 8 && blocksize != 127) { + av_log(avctx, AV_LOG_ERROR, "Block size = %i\n", blocksize); + return AVERROR_INVALIDDATA; + } + memset(ctx->cur, 0, 320 * 200); + switch (header & KMVC_METHOD) { + case 0: + case 1: // used in palette changed event + memcpy(ctx->cur, ctx->prev, 320 * 200); + break; + case 3: + kmvc_decode_intra_8x8(ctx, avctx->width, avctx->height); + break; + case 4: + kmvc_decode_inter_8x8(ctx, avctx->width, avctx->height); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown compression method %i\n", header & KMVC_METHOD); + return AVERROR_INVALIDDATA; + } + + out = frame->data[0]; + src = ctx->cur; + for (i = 0; i < avctx->height; i++) { + memcpy(out, src, avctx->width); + src += 320; + out += frame->linesize[0]; + } + + /* flip buffers */ + if (ctx->cur == ctx->frm0) { + ctx->cur = ctx->frm1; + ctx->prev = ctx->frm0; + } else { + ctx->cur = ctx->frm0; + ctx->prev = ctx->frm1; + } + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return avpkt->size; +} + + + +/* + * Init kmvc decoder + */ +static av_cold int decode_init(AVCodecContext * avctx) +{ + KmvcContext *const c = avctx->priv_data; + int i; + + c->avctx = avctx; + + if (avctx->width > 320 || avctx->height > 200) { + av_log(avctx, AV_LOG_ERROR, "KMVC supports frames <= 320x200\n"); + return AVERROR(EINVAL); + } + + c->frm0 = av_mallocz(320 * 200); + c->frm1 = av_mallocz(320 * 200); + c->cur = c->frm0; + c->prev = c->frm1; + + for (i = 0; i < 256; i++) { + c->pal[i] = 0xFFU << 24 | i * 0x10101; + } + + if (avctx->extradata_size < 12) { + av_log(avctx, AV_LOG_WARNING, + "Extradata missing, decoding may not work properly...\n"); + c->palsize = 127; + } else { + c->palsize = AV_RL16(avctx->extradata + 10); + if (c->palsize >= (unsigned)MAX_PALSIZE) { + c->palsize = 127; + av_log(avctx, AV_LOG_ERROR, "KMVC palette too large\n"); + return AVERROR_INVALIDDATA; + } + } + + if (avctx->extradata_size == 1036) { // palette in extradata + uint8_t *src = avctx->extradata + 12; + for (i = 0; i < 256; i++) { + c->pal[i] = AV_RL32(src); + src += 4; + } + c->setpal = 1; + } + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + return 0; +} + + + +/* + * Uninit kmvc decoder + */ +static av_cold int decode_end(AVCodecContext * avctx) +{ + KmvcContext *const c = avctx->priv_data; + + av_freep(&c->frm0); + av_freep(&c->frm1); + + return 0; +} + +AVCodec ff_kmvc_decoder = { + .name = "kmvc", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_KMVC, + .priv_data_size = sizeof(KmvcContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Karl Morton's video codec"), +}; diff --git a/ffmpeg/libavcodec/lagarith.c b/ffmpeg/libavcodec/lagarith.c new file mode 100644 index 0000000..8599784 --- /dev/null +++ b/ffmpeg/libavcodec/lagarith.c @@ -0,0 +1,714 @@ +/* + * Lagarith lossless decoder + * Copyright (c) 2009 Nathan Caldwell + * + * 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 + */ + +/** + * @file + * Lagarith lossless decoder + * @author Nathan Caldwell + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "mathops.h" +#include "dsputil.h" +#include "lagarithrac.h" +#include "thread.h" + +enum LagarithFrameType { + FRAME_RAW = 1, /**< uncompressed */ + FRAME_U_RGB24 = 2, /**< unaligned RGB24 */ + FRAME_ARITH_YUY2 = 3, /**< arithmetic coded YUY2 */ + FRAME_ARITH_RGB24 = 4, /**< arithmetic coded RGB24 */ + FRAME_SOLID_GRAY = 5, /**< solid grayscale color frame */ + FRAME_SOLID_COLOR = 6, /**< solid non-grayscale color frame */ + FRAME_OLD_ARITH_RGB = 7, /**< obsolete arithmetic coded RGB (no longer encoded by upstream since version 1.1.0) */ + FRAME_ARITH_RGBA = 8, /**< arithmetic coded RGBA */ + FRAME_SOLID_RGBA = 9, /**< solid RGBA color frame */ + FRAME_ARITH_YV12 = 10, /**< arithmetic coded YV12 */ + FRAME_REDUCED_RES = 11, /**< reduced resolution YV12 frame */ +}; + +typedef struct LagarithContext { + AVCodecContext *avctx; + DSPContext dsp; + int zeros; /**< number of consecutive zero bytes encountered */ + int zeros_rem; /**< number of zero bytes remaining to output */ + uint8_t *rgb_planes; + int rgb_stride; +} LagarithContext; + +/** + * Compute the 52bit mantissa of 1/(double)denom. + * This crazy format uses floats in an entropy coder and we have to match x86 + * rounding exactly, thus ordinary floats aren't portable enough. + * @param denom denominator + * @return 52bit mantissa + * @see softfloat_mul + */ +static uint64_t softfloat_reciprocal(uint32_t denom) +{ + int shift = av_log2(denom - 1) + 1; + uint64_t ret = (1ULL << 52) / denom; + uint64_t err = (1ULL << 52) - ret * denom; + ret <<= shift; + err <<= shift; + err += denom / 2; + return ret + err / denom; +} + +/** + * (uint32_t)(x*f), where f has the given mantissa, and exponent 0 + * Used in combination with softfloat_reciprocal computes x/(double)denom. + * @param x 32bit integer factor + * @param mantissa mantissa of f with exponent 0 + * @return 32bit integer value (x*f) + * @see softfloat_reciprocal + */ +static uint32_t softfloat_mul(uint32_t x, uint64_t mantissa) +{ + uint64_t l = x * (mantissa & 0xffffffff); + uint64_t h = x * (mantissa >> 32); + h += l >> 32; + l &= 0xffffffff; + l += 1 << av_log2(h >> 21); + h += l >> 32; + return h >> 20; +} + +static uint8_t lag_calc_zero_run(int8_t x) +{ + return (x << 1) ^ (x >> 7); +} + +static int lag_decode_prob(GetBitContext *gb, uint32_t *value) +{ + static const uint8_t series[] = { 1, 2, 3, 5, 8, 13, 21 }; + int i; + int bit = 0; + int bits = 0; + int prevbit = 0; + unsigned val; + + for (i = 0; i < 7; i++) { + if (prevbit && bit) + break; + prevbit = bit; + bit = get_bits1(gb); + if (bit && !prevbit) + bits += series[i]; + } + bits--; + if (bits < 0 || bits > 31) { + *value = 0; + return -1; + } else if (bits == 0) { + *value = 0; + return 0; + } + + val = get_bits_long(gb, bits); + val |= 1 << bits; + + *value = val - 1; + + return 0; +} + +static int lag_read_prob_header(lag_rac *rac, GetBitContext *gb) +{ + int i, j, scale_factor; + unsigned prob, cumulative_target; + unsigned cumul_prob = 0; + unsigned scaled_cumul_prob = 0; + + rac->prob[0] = 0; + rac->prob[257] = UINT_MAX; + /* Read probabilities from bitstream */ + for (i = 1; i < 257; i++) { + if (lag_decode_prob(gb, &rac->prob[i]) < 0) { + av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability encountered.\n"); + return -1; + } + if ((uint64_t)cumul_prob + rac->prob[i] > UINT_MAX) { + av_log(rac->avctx, AV_LOG_ERROR, "Integer overflow encountered in cumulative probability calculation.\n"); + return -1; + } + cumul_prob += rac->prob[i]; + if (!rac->prob[i]) { + if (lag_decode_prob(gb, &prob)) { + av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability run encountered.\n"); + return -1; + } + if (prob > 256 - i) + prob = 256 - i; + for (j = 0; j < prob; j++) + rac->prob[++i] = 0; + } + } + + if (!cumul_prob) { + av_log(rac->avctx, AV_LOG_ERROR, "All probabilities are 0!\n"); + return -1; + } + + /* Scale probabilities so cumulative probability is an even power of 2. */ + scale_factor = av_log2(cumul_prob); + + if (cumul_prob & (cumul_prob - 1)) { + uint64_t mul = softfloat_reciprocal(cumul_prob); + for (i = 1; i < 257; i++) { + rac->prob[i] = softfloat_mul(rac->prob[i], mul); + scaled_cumul_prob += rac->prob[i]; + } + + scale_factor++; + cumulative_target = 1 << scale_factor; + + if (scaled_cumul_prob > cumulative_target) { + av_log(rac->avctx, AV_LOG_ERROR, + "Scaled probabilities are larger than target!\n"); + return -1; + } + + scaled_cumul_prob = cumulative_target - scaled_cumul_prob; + + for (i = 1; scaled_cumul_prob; i = (i & 0x7f) + 1) { + if (rac->prob[i]) { + rac->prob[i]++; + scaled_cumul_prob--; + } + /* Comment from reference source: + * if (b & 0x80 == 0) { // order of operations is 'wrong'; it has been left this way + * // since the compression change is negligible and fixing it + * // breaks backwards compatibility + * b =- (signed int)b; + * b &= 0xFF; + * } else { + * b++; + * b &= 0x7f; + * } + */ + } + } + + rac->scale = scale_factor; + + /* Fill probability array with cumulative probability for each symbol. */ + for (i = 1; i < 257; i++) + rac->prob[i] += rac->prob[i - 1]; + + return 0; +} + +static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1, + uint8_t *diff, int w, int *left, + int *left_top) +{ + /* This is almost identical to add_hfyu_median_prediction in dsputil.h. + * However the &0xFF on the gradient predictor yealds incorrect output + * for lagarith. + */ + int i; + uint8_t l, lt; + + l = *left; + lt = *left_top; + + for (i = 0; i < w; i++) { + l = mid_pred(l, src1[i], l + src1[i] - lt) + diff[i]; + lt = src1[i]; + dst[i] = l; + } + + *left = l; + *left_top = lt; +} + +static void lag_pred_line(LagarithContext *l, uint8_t *buf, + int width, int stride, int line) +{ + int L, TL; + + if (!line) { + /* Left prediction only for first line */ + L = l->dsp.add_hfyu_left_prediction(buf, buf, + width, 0); + } else { + /* Left pixel is actually prev_row[width] */ + L = buf[width - stride - 1]; + + if (line == 1) { + /* Second line, left predict first pixel, the rest of the line is median predicted + * NOTE: In the case of RGB this pixel is top predicted */ + TL = l->avctx->pix_fmt == AV_PIX_FMT_YUV420P ? buf[-stride] : L; + } else { + /* Top left is 2 rows back, last pixel */ + TL = buf[width - (2 * stride) - 1]; + } + + add_lag_median_prediction(buf, buf - stride, buf, + width, &L, &TL); + } +} + +static void lag_pred_line_yuy2(LagarithContext *l, uint8_t *buf, + int width, int stride, int line, + int is_luma) +{ + int L, TL; + + if (!line) { + L= buf[0]; + if (is_luma) + buf[0] = 0; + l->dsp.add_hfyu_left_prediction(buf, buf, width, 0); + if (is_luma) + buf[0] = L; + return; + } + if (line == 1) { + const int HEAD = is_luma ? 4 : 2; + int i; + + L = buf[width - stride - 1]; + TL = buf[HEAD - stride - 1]; + for (i = 0; i < HEAD; i++) { + L += buf[i]; + buf[i] = L; + } + for (; idsp.add_hfyu_median_prediction(buf, buf - stride, buf, width, + &L, &TL); + } +} + +static int lag_decode_line(LagarithContext *l, lag_rac *rac, + uint8_t *dst, int width, int stride, + int esc_count) +{ + int i = 0; + int ret = 0; + + if (!esc_count) + esc_count = -1; + + /* Output any zeros remaining from the previous run */ +handle_zeros: + if (l->zeros_rem) { + int count = FFMIN(l->zeros_rem, width - i); + memset(dst + i, 0, count); + i += count; + l->zeros_rem -= count; + } + + while (i < width) { + dst[i] = lag_get_rac(rac); + ret++; + + if (dst[i]) + l->zeros = 0; + else + l->zeros++; + + i++; + if (l->zeros == esc_count) { + int index = lag_get_rac(rac); + ret++; + + l->zeros = 0; + + l->zeros_rem = lag_calc_zero_run(index); + goto handle_zeros; + } + } + return ret; +} + +static int lag_decode_zero_run_line(LagarithContext *l, uint8_t *dst, + const uint8_t *src, const uint8_t *src_end, + int width, int esc_count) +{ + int i = 0; + int count; + uint8_t zero_run = 0; + const uint8_t *src_start = src; + uint8_t mask1 = -(esc_count < 2); + uint8_t mask2 = -(esc_count < 3); + uint8_t *end = dst + (width - 2); + +output_zeros: + if (l->zeros_rem) { + count = FFMIN(l->zeros_rem, width - i); + if (end - dst < count) { + av_log(l->avctx, AV_LOG_ERROR, "Too many zeros remaining.\n"); + return AVERROR_INVALIDDATA; + } + + memset(dst, 0, count); + l->zeros_rem -= count; + dst += count; + } + + while (dst < end) { + i = 0; + while (!zero_run && dst + i < end) { + i++; + if (i+2 >= src_end - src) + return AVERROR_INVALIDDATA; + zero_run = + !(src[i] | (src[i + 1] & mask1) | (src[i + 2] & mask2)); + } + if (zero_run) { + zero_run = 0; + i += esc_count; + memcpy(dst, src, i); + dst += i; + l->zeros_rem = lag_calc_zero_run(src[i]); + + src += i + 1; + goto output_zeros; + } else { + memcpy(dst, src, i); + src += i; + dst += i; + } + } + return src - src_start; +} + + + +static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst, + int width, int height, int stride, + const uint8_t *src, int src_size) +{ + int i = 0; + int read = 0; + uint32_t length; + uint32_t offset = 1; + int esc_count; + GetBitContext gb; + lag_rac rac; + const uint8_t *src_end = src + src_size; + + rac.avctx = l->avctx; + l->zeros = 0; + + if(src_size < 2) + return AVERROR_INVALIDDATA; + + esc_count = src[0]; + if (esc_count < 4) { + length = width * height; + if(src_size < 5) + return AVERROR_INVALIDDATA; + if (esc_count && AV_RL32(src + 1) < length) { + length = AV_RL32(src + 1); + offset += 4; + } + + init_get_bits(&gb, src + offset, src_size * 8); + + if (lag_read_prob_header(&rac, &gb) < 0) + return -1; + + ff_lag_rac_init(&rac, &gb, length - stride); + + for (i = 0; i < height; i++) + read += lag_decode_line(l, &rac, dst + (i * stride), width, + stride, esc_count); + + if (read > length) + av_log(l->avctx, AV_LOG_WARNING, + "Output more bytes than length (%d of %d)\n", read, + length); + } else if (esc_count < 8) { + esc_count -= 4; + if (esc_count > 0) { + /* Zero run coding only, no range coding. */ + for (i = 0; i < height; i++) { + int res = lag_decode_zero_run_line(l, dst + (i * stride), src, + src_end, width, esc_count); + if (res < 0) + return res; + src += res; + } + } else { + if (src_size < width * height) + return AVERROR_INVALIDDATA; // buffer not big enough + /* Plane is stored uncompressed */ + for (i = 0; i < height; i++) { + memcpy(dst + (i * stride), src, width); + src += width; + } + } + } else if (esc_count == 0xff) { + /* Plane is a solid run of given value */ + for (i = 0; i < height; i++) + memset(dst + i * stride, src[1], width); + /* Do not apply prediction. + Note: memset to 0 above, setting first value to src[1] + and applying prediction gives the same result. */ + return 0; + } else { + av_log(l->avctx, AV_LOG_ERROR, + "Invalid zero run escape code! (%#x)\n", esc_count); + return -1; + } + + if (l->avctx->pix_fmt != AV_PIX_FMT_YUV422P) { + for (i = 0; i < height; i++) { + lag_pred_line(l, dst, width, stride, i); + dst += stride; + } + } else { + for (i = 0; i < height; i++) { + lag_pred_line_yuy2(l, dst, width, stride, i, + width == l->avctx->width); + dst += stride; + } + } + + return 0; +} + +/** + * Decode a frame. + * @param avctx codec context + * @param data output AVFrame + * @param data_size size of output data or 0 if no picture is returned + * @param avpkt input packet + * @return number of consumed bytes on success or negative if decode fails + */ +static int lag_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + unsigned int buf_size = avpkt->size; + LagarithContext *l = avctx->priv_data; + ThreadFrame frame = { .f = data }; + AVFrame *const p = data; + uint8_t frametype = 0; + uint32_t offset_gu = 0, offset_bv = 0, offset_ry = 9; + uint32_t offs[4]; + uint8_t *srcs[4], *dst; + int i, j, planes = 3; + int ret; + + p->key_frame = 1; + + frametype = buf[0]; + + offset_gu = AV_RL32(buf + 1); + offset_bv = AV_RL32(buf + 5); + + switch (frametype) { + case FRAME_SOLID_RGBA: + avctx->pix_fmt = AV_PIX_FMT_RGB32; + case FRAME_SOLID_GRAY: + if (frametype == FRAME_SOLID_GRAY) + if (avctx->bits_per_coded_sample == 24) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else { + avctx->pix_fmt = AV_PIX_FMT_0RGB32; + planes = 4; + } + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + dst = p->data[0]; + if (frametype == FRAME_SOLID_RGBA) { + for (j = 0; j < avctx->height; j++) { + for (i = 0; i < avctx->width; i++) + AV_WN32(dst + i * 4, offset_gu); + dst += p->linesize[0]; + } + } else { + for (j = 0; j < avctx->height; j++) { + memset(dst, buf[1], avctx->width * planes); + dst += p->linesize[0]; + } + } + break; + case FRAME_ARITH_RGBA: + avctx->pix_fmt = AV_PIX_FMT_RGB32; + planes = 4; + offset_ry += 4; + offs[3] = AV_RL32(buf + 9); + case FRAME_ARITH_RGB24: + case FRAME_U_RGB24: + if (frametype == FRAME_ARITH_RGB24 || frametype == FRAME_U_RGB24) + avctx->pix_fmt = AV_PIX_FMT_RGB24; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + offs[0] = offset_bv; + offs[1] = offset_gu; + offs[2] = offset_ry; + + if (!l->rgb_planes) { + l->rgb_stride = FFALIGN(avctx->width, 16); + l->rgb_planes = av_malloc(l->rgb_stride * avctx->height * 4 + 16); + if (!l->rgb_planes) { + av_log(avctx, AV_LOG_ERROR, "cannot allocate temporary buffer\n"); + return AVERROR(ENOMEM); + } + } + for (i = 0; i < planes; i++) + srcs[i] = l->rgb_planes + (i + 1) * l->rgb_stride * avctx->height - l->rgb_stride; + for (i = 0; i < planes; i++) + if (buf_size <= offs[i]) { + av_log(avctx, AV_LOG_ERROR, + "Invalid frame offsets\n"); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < planes; i++) + lag_decode_arith_plane(l, srcs[i], + avctx->width, avctx->height, + -l->rgb_stride, buf + offs[i], + buf_size - offs[i]); + dst = p->data[0]; + for (i = 0; i < planes; i++) + srcs[i] = l->rgb_planes + i * l->rgb_stride * avctx->height; + for (j = 0; j < avctx->height; j++) { + for (i = 0; i < avctx->width; i++) { + uint8_t r, g, b, a; + r = srcs[0][i]; + g = srcs[1][i]; + b = srcs[2][i]; + r += g; + b += g; + if (frametype == FRAME_ARITH_RGBA) { + a = srcs[3][i]; + AV_WN32(dst + i * 4, MKBETAG(a, r, g, b)); + } else { + dst[i * 3 + 0] = r; + dst[i * 3 + 1] = g; + dst[i * 3 + 2] = b; + } + } + dst += p->linesize[0]; + for (i = 0; i < planes; i++) + srcs[i] += l->rgb_stride; + } + break; + case FRAME_ARITH_YUY2: + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + if (offset_ry >= buf_size || + offset_gu >= buf_size || + offset_bv >= buf_size) { + av_log(avctx, AV_LOG_ERROR, + "Invalid frame offsets\n"); + return AVERROR_INVALIDDATA; + } + + lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height, + p->linesize[0], buf + offset_ry, + buf_size - offset_ry); + lag_decode_arith_plane(l, p->data[1], avctx->width / 2, + avctx->height, p->linesize[1], + buf + offset_gu, buf_size - offset_gu); + lag_decode_arith_plane(l, p->data[2], avctx->width / 2, + avctx->height, p->linesize[2], + buf + offset_bv, buf_size - offset_bv); + break; + case FRAME_ARITH_YV12: + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + if (buf_size <= offset_ry || buf_size <= offset_gu || buf_size <= offset_bv) { + return AVERROR_INVALIDDATA; + } + + if (offset_ry >= buf_size || + offset_gu >= buf_size || + offset_bv >= buf_size) { + av_log(avctx, AV_LOG_ERROR, + "Invalid frame offsets\n"); + return AVERROR_INVALIDDATA; + } + + lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height, + p->linesize[0], buf + offset_ry, + buf_size - offset_ry); + lag_decode_arith_plane(l, p->data[2], avctx->width / 2, + avctx->height / 2, p->linesize[2], + buf + offset_gu, buf_size - offset_gu); + lag_decode_arith_plane(l, p->data[1], avctx->width / 2, + avctx->height / 2, p->linesize[1], + buf + offset_bv, buf_size - offset_bv); + break; + default: + av_log(avctx, AV_LOG_ERROR, + "Unsupported Lagarith frame type: %#x\n", frametype); + return AVERROR_PATCHWELCOME; + } + + *got_frame = 1; + + return buf_size; +} + +static av_cold int lag_decode_init(AVCodecContext *avctx) +{ + LagarithContext *l = avctx->priv_data; + l->avctx = avctx; + + ff_dsputil_init(&l->dsp, avctx); + + return 0; +} + +static av_cold int lag_decode_end(AVCodecContext *avctx) +{ + LagarithContext *l = avctx->priv_data; + + av_freep(&l->rgb_planes); + + return 0; +} + +AVCodec ff_lagarith_decoder = { + .name = "lagarith", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_LAGARITH, + .priv_data_size = sizeof(LagarithContext), + .init = lag_decode_init, + .close = lag_decode_end, + .decode = lag_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Lagarith lossless"), +}; diff --git a/ffmpeg/libavcodec/lagarithrac.c b/ffmpeg/libavcodec/lagarithrac.c new file mode 100644 index 0000000..895acb0 --- /dev/null +++ b/ffmpeg/libavcodec/lagarithrac.c @@ -0,0 +1,59 @@ +/* + * Lagarith range decoder + * Copyright (c) 2009 Nathan Caldwell + * Copyright (c) 2009 David Conrad + * + * 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 + */ + +/** + * @file + * Lagarith range decoder + * @author Nathan Caldwell + * @author David Conrad + */ + +#include "get_bits.h" +#include "lagarithrac.h" + +void ff_lag_rac_init(lag_rac *l, GetBitContext *gb, int length) +{ + int i, j, left; + + /* According to reference decoder "1st byte is garbage", + * however, it gets skipped by the call to align_get_bits() + */ + align_get_bits(gb); + left = get_bits_left(gb) >> 3; + l->bytestream_start = + l->bytestream = gb->buffer + get_bits_count(gb) / 8; + l->bytestream_end = l->bytestream_start + left; + + l->range = 0x80; + l->low = *l->bytestream >> 1; + l->hash_shift = FFMAX((int)l->scale - 8, 0); + + for (i = j = 0; i < 256; i++) { + unsigned r = i << l->hash_shift; + while (l->prob[j + 1] <= r) + j++; + l->range_hash[i] = j; + } + + /* Add conversion factor to hash_shift so we don't have to in lag_get_rac. */ + l->hash_shift += 23; +} diff --git a/ffmpeg/libavcodec/lagarithrac.h b/ffmpeg/libavcodec/lagarithrac.h new file mode 100644 index 0000000..9892d11 --- /dev/null +++ b/ffmpeg/libavcodec/lagarithrac.h @@ -0,0 +1,119 @@ +/* + * Lagarith range decoder + * Copyright (c) 2009 Nathan Caldwell + * Copyright (c) 2009 David Conrad + * + * 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 + */ + +/** + * @file + * Lagarith range decoder + * @author Nathan Caldwell + * @author David Conrad + */ + +#ifndef AVCODEC_LAGARITHRAC_H +#define AVCODEC_LAGARITHRAC_H + +#include +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "get_bits.h" + +typedef struct lag_rac { + AVCodecContext *avctx; + unsigned low; + unsigned range; + unsigned scale; /**< Number of bits of precision in range. */ + unsigned hash_shift; /**< Number of bits to shift to calculate hash for radix search. */ + + const uint8_t *bytestream_start; /**< Start of input bytestream. */ + const uint8_t *bytestream; /**< Current position in input bytestream. */ + const uint8_t *bytestream_end; /**< End position of input bytestream. */ + + uint32_t prob[258]; /**< Table of cumulative probability for each symbol. */ + uint8_t range_hash[256]; /**< Hash table mapping upper byte to approximate symbol. */ +} lag_rac; + +void ff_lag_rac_init(lag_rac *l, GetBitContext *gb, int length); + +/* TODO: Optimize */ +static inline void lag_rac_refill(lag_rac *l) +{ + while (l->range <= 0x800000) { + l->low <<= 8; + l->range <<= 8; + l->low |= 0xff & (AV_RB16(l->bytestream) >> 1); + if (l->bytestream < l->bytestream_end) + l->bytestream++; + } +} + +/** + * Decode a single byte from the compressed plane described by *l. + * @param l pointer to lag_rac for the current plane + * @return next byte of decoded data + */ +static inline uint8_t lag_get_rac(lag_rac *l) +{ + unsigned range_scaled, low_scaled, div; + int val; + uint8_t shift; + + lag_rac_refill(l); + + range_scaled = l->range >> l->scale; + + if (l->low < range_scaled * l->prob[255]) { + /* val = 0 is frequent enough to deserve a shortcut */ + if (l->low < range_scaled * l->prob[1]) { + val = 0; + } else { + /* FIXME __builtin_clz is ~20% faster here, but not allowed in generic code. */ + shift = 30 - av_log2(range_scaled); + div = ((range_scaled << shift) + (1 << 23) - 1) >> 23; + /* low>>24 ensures that any cases too big for exact FASTDIV are + * under- rather than over-estimated + */ + low_scaled = FASTDIV(l->low - (l->low >> 24), div); + shift -= l->hash_shift; + shift &= 31; + low_scaled = (low_scaled << shift) | (low_scaled >> (32 - shift)); + /* low_scaled is now a lower bound of low/range_scaled */ + val = l->range_hash[(uint8_t) low_scaled]; + while (l->low >= range_scaled * l->prob[val + 1]) + val++; + } + + l->range = range_scaled * (l->prob[val + 1] - l->prob[val]); + } else { + val = 255; + l->range -= range_scaled * l->prob[255]; + } + + if (!l->range) + l->range = 0x80; + + l->low -= range_scaled * l->prob[val]; + + return val; +} + + +#endif /* AVCODEC_LAGARITHRAC_H */ diff --git a/ffmpeg/libavcodec/latm_parser.c b/ffmpeg/libavcodec/latm_parser.c new file mode 100644 index 0000000..3820f58 --- /dev/null +++ b/ffmpeg/libavcodec/latm_parser.c @@ -0,0 +1,112 @@ +/* + * copyright (c) 2008 Paul Kendall + * + * 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 + */ + +/** + * @file + * AAC LATM parser + */ + +#include +#include "parser.h" + +#define LATM_HEADER 0x56e000 // 0x2b7 (11 bits) +#define LATM_MASK 0xFFE000 // top 11 bits +#define LATM_SIZE_MASK 0x001FFF // bottom 13 bits + +typedef struct LATMParseContext{ + ParseContext pc; + int count; +} LATMParseContext; + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int latm_find_frame_end(AVCodecParserContext *s1, const uint8_t *buf, + int buf_size) +{ + LATMParseContext *s = s1->priv_data; + ParseContext *pc = &s->pc; + int pic_found, i; + uint32_t state; + + pic_found = pc->frame_start_found; + state = pc->state; + + if (!pic_found) { + for (i = 0; i < buf_size; i++) { + state = (state<<8) | buf[i]; + if ((state & LATM_MASK) == LATM_HEADER) { + i++; + s->count = -i; + pic_found = 1; + break; + } + } + } + + if (pic_found) { + /* EOF considered as end of frame */ + if (buf_size == 0) + return 0; + if ((state & LATM_SIZE_MASK) - s->count <= buf_size) { + pc->frame_start_found = 0; + pc->state = -1; + return (state & LATM_SIZE_MASK) - s->count; + } + } + + s->count += buf_size; + pc->frame_start_found = pic_found; + pc->state = state; + + return END_NOT_FOUND; +} + +static int latm_parse(AVCodecParserContext *s1, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + LATMParseContext *s = s1->priv_data; + ParseContext *pc = &s->pc; + int next; + + if (s1->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = latm_find_frame_end(s1, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_aac_latm_parser = { + .codec_ids = { AV_CODEC_ID_AAC_LATM }, + .priv_data_size = sizeof(LATMParseContext), + .parser_parse = latm_parse, + .parser_close = ff_parse_close +}; diff --git a/ffmpeg/libavcodec/lcl.h b/ffmpeg/libavcodec/lcl.h new file mode 100644 index 0000000..b60c0e9 --- /dev/null +++ b/ffmpeg/libavcodec/lcl.h @@ -0,0 +1,49 @@ +/* + * LCL (LossLess Codec Library) Codec + * Copyright (c) 2002-2004 Roberto Togni + * + * 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 + */ + +#ifndef AVCODEC_LCL_H +#define AVCODEC_LCL_H + +#define BMPTYPE_YUV 1 +#define BMPTYPE_RGB 2 + +#define IMGTYPE_YUV111 0 +#define IMGTYPE_YUV422 1 +#define IMGTYPE_RGB24 2 +#define IMGTYPE_YUV411 3 +#define IMGTYPE_YUV211 4 +#define IMGTYPE_YUV420 5 + +#define COMP_MSZH 0 +#define COMP_MSZH_NOCOMP 1 +#define COMP_ZLIB_HISPEED 1 +#define COMP_ZLIB_HICOMP 9 +#define COMP_ZLIB_NORMAL -1 + +#define FLAG_MULTITHREAD 1 +#define FLAG_NULLFRAME 2 +#define FLAG_PNGFILTER 4 +#define FLAGMASK_UNUSED 0xf8 + +#define CODEC_MSZH 1 +#define CODEC_ZLIB 3 + +#endif /* AVCODEC_LCL_H */ diff --git a/ffmpeg/libavcodec/lcldec.c b/ffmpeg/libavcodec/lcldec.c new file mode 100644 index 0000000..7948199 --- /dev/null +++ b/ffmpeg/libavcodec/lcldec.c @@ -0,0 +1,665 @@ +/* + * LCL (LossLess Codec Library) Codec + * Copyright (c) 2002-2004 Roberto Togni + * + * 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 + */ + +/** + * @file + * LCL (LossLess Codec Library) Video Codec + * Decoder for MSZH and ZLIB codecs + * Experimental encoder for ZLIB RGB24 + * + * Fourcc: MSZH, ZLIB + * + * Original Win32 dll: + * Ver2.23 By Kenji Oshima 2000.09.20 + * avimszh.dll, avizlib.dll + * + * A description of the decoding algorithm can be found here: + * http://www.pcisys.net/~melanson/codecs + * + * Supports: BGR24 (RGB 24bpp) + * + */ + +#include +#include + +#include "libavutil/mem.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "lcl.h" + +#if CONFIG_ZLIB_DECODER +#include +#endif + +/* + * Decoder context + */ +typedef struct LclDecContext { + // Image type + int imgtype; + // Compression type + int compression; + // Flags + int flags; + // Decompressed data size + unsigned int decomp_size; + // Decompression buffer + unsigned char* decomp_buf; +#if CONFIG_ZLIB_DECODER + z_stream zstream; +#endif +} LclDecContext; + + +/** + * @param srcptr compressed source buffer, must be padded with at least 5 extra bytes + * @param destptr must be padded sufficiently for av_memcpy_backptr + */ +static unsigned int mszh_decomp(const unsigned char * srcptr, int srclen, unsigned char * destptr, unsigned int destsize) +{ + unsigned char *destptr_bak = destptr; + unsigned char *destptr_end = destptr + destsize; + const unsigned char *srcptr_end = srcptr + srclen; + unsigned mask = *srcptr++; + unsigned maskbit = 0x80; + + while (srcptr < srcptr_end && destptr < destptr_end) { + if (!(mask & maskbit)) { + memcpy(destptr, srcptr, 4); + destptr += 4; + srcptr += 4; + } else { + unsigned ofs = bytestream_get_le16(&srcptr); + unsigned cnt = (ofs >> 11) + 1; + ofs &= 0x7ff; + ofs = FFMIN(ofs, destptr - destptr_bak); + cnt *= 4; + cnt = FFMIN(cnt, destptr_end - destptr); + if (ofs) { + av_memcpy_backptr(destptr, ofs, cnt); + } else { + // Not known what the correct behaviour is, but + // this at least avoids uninitialized data. + memset(destptr, 0, cnt); + } + destptr += cnt; + } + maskbit >>= 1; + if (!maskbit) { + mask = *srcptr++; + while (!mask) { + if (destptr_end - destptr < 32 || srcptr_end - srcptr < 32) break; + memcpy(destptr, srcptr, 32); + destptr += 32; + srcptr += 32; + mask = *srcptr++; + } + maskbit = 0x80; + } + } + + return destptr - destptr_bak; +} + + +#if CONFIG_ZLIB_DECODER +/** + * @brief decompress a zlib-compressed data block into decomp_buf + * @param src compressed input buffer + * @param src_len data length in input buffer + * @param offset offset in decomp_buf + * @param expected expected decompressed length + */ +static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, int offset, int expected) +{ + LclDecContext *c = avctx->priv_data; + int zret = inflateReset(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); + return AVERROR_UNKNOWN; + } + c->zstream.next_in = (uint8_t *)src; + c->zstream.avail_in = src_len; + c->zstream.next_out = c->decomp_buf + offset; + c->zstream.avail_out = c->decomp_size - offset; + zret = inflate(&c->zstream, Z_FINISH); + if (zret != Z_OK && zret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret); + return AVERROR_UNKNOWN; + } + if (expected != (unsigned int)c->zstream.total_out) { + av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n", + expected, c->zstream.total_out); + return AVERROR_UNKNOWN; + } + return c->zstream.total_out; +} +#endif + + +/* + * + * Decode a frame + * + */ +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + LclDecContext * const c = avctx->priv_data; + unsigned char *encoded = (unsigned char *)buf; + unsigned int pixel_ptr; + int row, col; + unsigned char *outptr; + uint8_t *y_out, *u_out, *v_out; + unsigned int width = avctx->width; // Real image width + unsigned int height = avctx->height; // Real image height + unsigned int mszh_dlen; + unsigned char yq, y1q, uq, vq; + int uqvq, ret; + unsigned int mthread_inlen, mthread_outlen; + unsigned int len = buf_size; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + outptr = frame->data[0]; // Output image pointer + + /* Decompress frame */ + switch (avctx->codec_id) { + case AV_CODEC_ID_MSZH: + switch (c->compression) { + case COMP_MSZH: + if (c->imgtype == IMGTYPE_RGB24 && len == width * height * 3) { + ; + } else if (c->flags & FLAG_MULTITHREAD) { + mthread_inlen = AV_RL32(encoded); + if (len < 8) { + av_log(avctx, AV_LOG_ERROR, "len %d is too small\n", len); + return AVERROR_INVALIDDATA; + } + mthread_inlen = FFMIN(mthread_inlen, len - 8); + mthread_outlen = AV_RL32(encoded+4); + mthread_outlen = FFMIN(mthread_outlen, c->decomp_size); + mszh_dlen = mszh_decomp(encoded + 8, mthread_inlen, c->decomp_buf, c->decomp_size); + if (mthread_outlen != mszh_dlen) { + av_log(avctx, AV_LOG_ERROR, "Mthread1 decoded size differs (%d != %d)\n", + mthread_outlen, mszh_dlen); + return AVERROR_INVALIDDATA; + } + mszh_dlen = mszh_decomp(encoded + 8 + mthread_inlen, len - 8 - mthread_inlen, + c->decomp_buf + mthread_outlen, c->decomp_size - mthread_outlen); + if (mthread_outlen != mszh_dlen) { + av_log(avctx, AV_LOG_ERROR, "Mthread2 decoded size differs (%d != %d)\n", + mthread_outlen, mszh_dlen); + return AVERROR_INVALIDDATA; + } + encoded = c->decomp_buf; + len = c->decomp_size; + } else { + mszh_dlen = mszh_decomp(encoded, len, c->decomp_buf, c->decomp_size); + if (c->decomp_size != mszh_dlen) { + av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %d)\n", + c->decomp_size, mszh_dlen); + return AVERROR_INVALIDDATA; + } + encoded = c->decomp_buf; + len = mszh_dlen; + } + break; + case COMP_MSZH_NOCOMP: { + int bppx2; + switch (c->imgtype) { + case IMGTYPE_YUV111: + case IMGTYPE_RGB24: + bppx2 = 6; + break; + case IMGTYPE_YUV422: + case IMGTYPE_YUV211: + bppx2 = 4; + break; + case IMGTYPE_YUV411: + case IMGTYPE_YUV420: + bppx2 = 3; + break; + default: + bppx2 = 0; // will error out below + break; + } + if (len < ((width * height * bppx2) >> 1)) + return AVERROR_INVALIDDATA; + break; + } + default: + av_log(avctx, AV_LOG_ERROR, "BUG! Unknown MSZH compression in frame decoder.\n"); + return AVERROR_INVALIDDATA; + } + break; +#if CONFIG_ZLIB_DECODER + case AV_CODEC_ID_ZLIB: + /* Using the original dll with normal compression (-1) and RGB format + * gives a file with ZLIB fourcc, but frame is really uncompressed. + * To be sure that's true check also frame size */ + if (c->compression == COMP_ZLIB_NORMAL && c->imgtype == IMGTYPE_RGB24 && + len == width * height * 3) { + if (c->flags & FLAG_PNGFILTER) { + memcpy(c->decomp_buf, encoded, len); + encoded = c->decomp_buf; + } else { + break; + } + } else if (c->flags & FLAG_MULTITHREAD) { + mthread_inlen = AV_RL32(encoded); + mthread_inlen = FFMIN(mthread_inlen, len - 8); + mthread_outlen = AV_RL32(encoded+4); + mthread_outlen = FFMIN(mthread_outlen, c->decomp_size); + ret = zlib_decomp(avctx, encoded + 8, mthread_inlen, 0, mthread_outlen); + if (ret < 0) return ret; + ret = zlib_decomp(avctx, encoded + 8 + mthread_inlen, len - 8 - mthread_inlen, + mthread_outlen, mthread_outlen); + if (ret < 0) return ret; + } else { + int ret = zlib_decomp(avctx, encoded, len, 0, c->decomp_size); + if (ret < 0) return ret; + } + encoded = c->decomp_buf; + len = c->decomp_size; + break; +#endif + default: + av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in frame decoder compression switch.\n"); + return AVERROR_INVALIDDATA; + } + + + /* Apply PNG filter */ + if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) { + switch (c->imgtype) { + case IMGTYPE_YUV111: + case IMGTYPE_RGB24: + for (row = 0; row < height; row++) { + pixel_ptr = row * width * 3; + yq = encoded[pixel_ptr++]; + uqvq = AV_RL16(encoded+pixel_ptr); + pixel_ptr += 2; + for (col = 1; col < width; col++) { + encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; + uqvq -= AV_RL16(encoded+pixel_ptr+1); + AV_WL16(encoded+pixel_ptr+1, uqvq); + pixel_ptr += 3; + } + } + break; + case IMGTYPE_YUV422: + for (row = 0; row < height; row++) { + pixel_ptr = row * width * 2; + yq = uq = vq =0; + for (col = 0; col < width/4; col++) { + encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; + encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; + encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2]; + encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3]; + encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; + encoded[pixel_ptr+5] = uq -= encoded[pixel_ptr+5]; + encoded[pixel_ptr+6] = vq -= encoded[pixel_ptr+6]; + encoded[pixel_ptr+7] = vq -= encoded[pixel_ptr+7]; + pixel_ptr += 8; + } + } + break; + case IMGTYPE_YUV411: + for (row = 0; row < height; row++) { + pixel_ptr = row * width / 2 * 3; + yq = uq = vq =0; + for (col = 0; col < width/4; col++) { + encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; + encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; + encoded[pixel_ptr+2] = yq -= encoded[pixel_ptr+2]; + encoded[pixel_ptr+3] = yq -= encoded[pixel_ptr+3]; + encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; + encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5]; + pixel_ptr += 6; + } + } + break; + case IMGTYPE_YUV211: + for (row = 0; row < height; row++) { + pixel_ptr = row * width * 2; + yq = uq = vq =0; + for (col = 0; col < width/2; col++) { + encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; + encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; + encoded[pixel_ptr+2] = uq -= encoded[pixel_ptr+2]; + encoded[pixel_ptr+3] = vq -= encoded[pixel_ptr+3]; + pixel_ptr += 4; + } + } + break; + case IMGTYPE_YUV420: + for (row = 0; row < height/2; row++) { + pixel_ptr = row * width * 3; + yq = y1q = uq = vq =0; + for (col = 0; col < width/2; col++) { + encoded[pixel_ptr] = yq -= encoded[pixel_ptr]; + encoded[pixel_ptr+1] = yq -= encoded[pixel_ptr+1]; + encoded[pixel_ptr+2] = y1q -= encoded[pixel_ptr+2]; + encoded[pixel_ptr+3] = y1q -= encoded[pixel_ptr+3]; + encoded[pixel_ptr+4] = uq -= encoded[pixel_ptr+4]; + encoded[pixel_ptr+5] = vq -= encoded[pixel_ptr+5]; + pixel_ptr += 6; + } + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in pngfilter switch.\n"); + return AVERROR_INVALIDDATA; + } + } + + /* Convert colorspace */ + y_out = frame->data[0] + (height - 1) * frame->linesize[0]; + u_out = frame->data[1] + (height - 1) * frame->linesize[1]; + v_out = frame->data[2] + (height - 1) * frame->linesize[2]; + switch (c->imgtype) { + case IMGTYPE_YUV111: + for (row = 0; row < height; row++) { + for (col = 0; col < width; col++) { + y_out[col] = *encoded++; + u_out[col] = *encoded++ + 128; + v_out[col] = *encoded++ + 128; + } + y_out -= frame->linesize[0]; + u_out -= frame->linesize[1]; + v_out -= frame->linesize[2]; + } + break; + case IMGTYPE_YUV422: + for (row = 0; row < height; row++) { + for (col = 0; col < width - 3; col += 4) { + memcpy(y_out + col, encoded, 4); + encoded += 4; + u_out[ col >> 1 ] = *encoded++ + 128; + u_out[(col >> 1) + 1] = *encoded++ + 128; + v_out[ col >> 1 ] = *encoded++ + 128; + v_out[(col >> 1) + 1] = *encoded++ + 128; + } + y_out -= frame->linesize[0]; + u_out -= frame->linesize[1]; + v_out -= frame->linesize[2]; + } + break; + case IMGTYPE_RGB24: + for (row = height - 1; row >= 0; row--) { + pixel_ptr = row * frame->linesize[0]; + memcpy(outptr + pixel_ptr, encoded, 3 * width); + encoded += 3 * width; + } + break; + case IMGTYPE_YUV411: + for (row = 0; row < height; row++) { + for (col = 0; col < width - 3; col += 4) { + memcpy(y_out + col, encoded, 4); + encoded += 4; + u_out[col >> 2] = *encoded++ + 128; + v_out[col >> 2] = *encoded++ + 128; + } + y_out -= frame->linesize[0]; + u_out -= frame->linesize[1]; + v_out -= frame->linesize[2]; + } + break; + case IMGTYPE_YUV211: + for (row = 0; row < height; row++) { + for (col = 0; col < width - 1; col += 2) { + memcpy(y_out + col, encoded, 2); + encoded += 2; + u_out[col >> 1] = *encoded++ + 128; + v_out[col >> 1] = *encoded++ + 128; + } + y_out -= frame->linesize[0]; + u_out -= frame->linesize[1]; + v_out -= frame->linesize[2]; + } + break; + case IMGTYPE_YUV420: + u_out = frame->data[1] + ((height >> 1) - 1) * frame->linesize[1]; + v_out = frame->data[2] + ((height >> 1) - 1) * frame->linesize[2]; + for (row = 0; row < height - 1; row += 2) { + for (col = 0; col < width - 1; col += 2) { + memcpy(y_out + col, encoded, 2); + encoded += 2; + memcpy(y_out + col - frame->linesize[0], encoded, 2); + encoded += 2; + u_out[col >> 1] = *encoded++ + 128; + v_out[col >> 1] = *encoded++ + 128; + } + y_out -= frame->linesize[0] << 1; + u_out -= frame->linesize[1]; + v_out -= frame->linesize[2]; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "BUG! Unknown imagetype in image decoder.\n"); + return AVERROR_INVALIDDATA; + } + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +/* + * + * Init lcl decoder + * + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + LclDecContext * const c = avctx->priv_data; + unsigned int basesize = avctx->width * avctx->height; + unsigned int max_basesize = FFALIGN(avctx->width, 4) * + FFALIGN(avctx->height, 4); + unsigned int max_decomp_size; + + if (avctx->extradata_size < 8) { + av_log(avctx, AV_LOG_ERROR, "Extradata size too small.\n"); + return AVERROR_INVALIDDATA; + } + + /* Check codec type */ + if ((avctx->codec_id == AV_CODEC_ID_MSZH && avctx->extradata[7] != CODEC_MSZH) || + (avctx->codec_id == AV_CODEC_ID_ZLIB && avctx->extradata[7] != CODEC_ZLIB)) { + av_log(avctx, AV_LOG_ERROR, "Codec id and codec type mismatch. This should not happen.\n"); + } + + /* Detect image type */ + switch (c->imgtype = avctx->extradata[4]) { + case IMGTYPE_YUV111: + c->decomp_size = basesize * 3; + max_decomp_size = max_basesize * 3; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 1:1:1.\n"); + break; + case IMGTYPE_YUV422: + c->decomp_size = basesize * 2; + max_decomp_size = max_basesize * 2; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:2.\n"); + break; + case IMGTYPE_RGB24: + c->decomp_size = basesize * 3; + max_decomp_size = max_basesize * 3; + avctx->pix_fmt = AV_PIX_FMT_BGR24; + av_log(avctx, AV_LOG_DEBUG, "Image type is RGB 24.\n"); + break; + case IMGTYPE_YUV411: + c->decomp_size = basesize / 2 * 3; + max_decomp_size = max_basesize / 2 * 3; + avctx->pix_fmt = AV_PIX_FMT_YUV411P; + av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:1:1.\n"); + break; + case IMGTYPE_YUV211: + c->decomp_size = basesize * 2; + max_decomp_size = max_basesize * 2; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 2:1:1.\n"); + break; + case IMGTYPE_YUV420: + c->decomp_size = basesize / 2 * 3; + max_decomp_size = max_basesize / 2 * 3; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + av_log(avctx, AV_LOG_DEBUG, "Image type is YUV 4:2:0.\n"); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported image format %d.\n", c->imgtype); + return AVERROR_INVALIDDATA; + } + + /* Detect compression method */ + c->compression = (int8_t)avctx->extradata[5]; + switch (avctx->codec_id) { + case AV_CODEC_ID_MSZH: + switch (c->compression) { + case COMP_MSZH: + av_log(avctx, AV_LOG_DEBUG, "Compression enabled.\n"); + break; + case COMP_MSZH_NOCOMP: + c->decomp_size = 0; + av_log(avctx, AV_LOG_DEBUG, "No compression.\n"); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported compression format for MSZH (%d).\n", c->compression); + return AVERROR_INVALIDDATA; + } + break; +#if CONFIG_ZLIB_DECODER + case AV_CODEC_ID_ZLIB: + switch (c->compression) { + case COMP_ZLIB_HISPEED: + av_log(avctx, AV_LOG_DEBUG, "High speed compression.\n"); + break; + case COMP_ZLIB_HICOMP: + av_log(avctx, AV_LOG_DEBUG, "High compression.\n"); + break; + case COMP_ZLIB_NORMAL: + av_log(avctx, AV_LOG_DEBUG, "Normal compression.\n"); + break; + default: + if (c->compression < Z_NO_COMPRESSION || c->compression > Z_BEST_COMPRESSION) { + av_log(avctx, AV_LOG_ERROR, "Unsupported compression level for ZLIB: (%d).\n", c->compression); + return AVERROR_INVALIDDATA; + } + av_log(avctx, AV_LOG_DEBUG, "Compression level for ZLIB: (%d).\n", c->compression); + } + break; +#endif + default: + av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in compression switch.\n"); + return AVERROR_INVALIDDATA; + } + + /* Allocate decompression buffer */ + if (c->decomp_size) { + if ((c->decomp_buf = av_malloc(max_decomp_size)) == NULL) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + } + + /* Detect flags */ + c->flags = avctx->extradata[6]; + if (c->flags & FLAG_MULTITHREAD) + av_log(avctx, AV_LOG_DEBUG, "Multithread encoder flag set.\n"); + if (c->flags & FLAG_NULLFRAME) + av_log(avctx, AV_LOG_DEBUG, "Nullframe insertion flag set.\n"); + if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) + av_log(avctx, AV_LOG_DEBUG, "PNG filter flag set.\n"); + if (c->flags & FLAGMASK_UNUSED) + av_log(avctx, AV_LOG_ERROR, "Unknown flag set (%d).\n", c->flags); + + /* If needed init zlib */ +#if CONFIG_ZLIB_DECODER + if (avctx->codec_id == AV_CODEC_ID_ZLIB) { + int zret; + c->zstream.zalloc = Z_NULL; + c->zstream.zfree = Z_NULL; + c->zstream.opaque = Z_NULL; + zret = inflateInit(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + av_freep(&c->decomp_buf); + return AVERROR_UNKNOWN; + } + } +#endif + + return 0; +} + +/* + * + * Uninit lcl decoder + * + */ +static av_cold int decode_end(AVCodecContext *avctx) +{ + LclDecContext * const c = avctx->priv_data; + + av_freep(&c->decomp_buf); +#if CONFIG_ZLIB_DECODER + if (avctx->codec_id == AV_CODEC_ID_ZLIB) + inflateEnd(&c->zstream); +#endif + + return 0; +} + +#if CONFIG_MSZH_DECODER +AVCodec ff_mszh_decoder = { + .name = "mszh", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSZH, + .priv_data_size = sizeof(LclDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), +}; +#endif + +#if CONFIG_ZLIB_DECODER +AVCodec ff_zlib_decoder = { + .name = "zlib", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ZLIB, + .priv_data_size = sizeof(LclDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), +}; +#endif diff --git a/ffmpeg/libavcodec/lclenc.c b/ffmpeg/libavcodec/lclenc.c new file mode 100644 index 0000000..09beb98 --- /dev/null +++ b/ffmpeg/libavcodec/lclenc.c @@ -0,0 +1,197 @@ +/* + * LCL (LossLess Codec Library) Codec + * Copyright (c) 2002-2004 Roberto Togni + * + * 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 + */ + +/** + * @file + * LCL (LossLess Codec Library) Video Codec + * Decoder for MSZH and ZLIB codecs + * Experimental encoder for ZLIB RGB24 + * + * Fourcc: MSZH, ZLIB + * + * Original Win32 dll: + * Ver2.23 By Kenji Oshima 2000.09.20 + * avimszh.dll, avizlib.dll + * + * A description of the decoding algorithm can be found here: + * http://www.pcisys.net/~melanson/codecs + * + * Supports: BGR24 (RGB 24bpp) + * + */ + +#include +#include + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +#include "lcl.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +#include + +/* + * Decoder context + */ +typedef struct LclEncContext { + + AVCodecContext *avctx; + AVFrame pic; + + // Image type + int imgtype; + // Compression type + int compression; + // Flags + int flags; + z_stream zstream; +} LclEncContext; + +/* + * + * Encode a frame + * + */ +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + LclEncContext *c = avctx->priv_data; + AVFrame * const p = &c->pic; + int i, ret; + int zret; // Zlib return code + int max_size = deflateBound(&c->zstream, avctx->width * avctx->height * 3); + + if ((ret = ff_alloc_packet2(avctx, pkt, max_size)) < 0) + return ret; + + *p = *pict; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + if(avctx->pix_fmt != AV_PIX_FMT_BGR24){ + av_log(avctx, AV_LOG_ERROR, "Format not supported!\n"); + return -1; + } + + zret = deflateReset(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Deflate reset error: %d\n", zret); + return -1; + } + c->zstream.next_out = pkt->data; + c->zstream.avail_out = pkt->size; + + for(i = avctx->height - 1; i >= 0; i--) { + c->zstream.next_in = p->data[0]+p->linesize[0]*i; + c->zstream.avail_in = avctx->width*3; + zret = deflate(&c->zstream, Z_NO_FLUSH); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); + return -1; + } + } + zret = deflate(&c->zstream, Z_FINISH); + if (zret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); + return -1; + } + + pkt->size = c->zstream.total_out; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +/* + * + * Init lcl encoder + * + */ +static av_cold int encode_init(AVCodecContext *avctx) +{ + LclEncContext *c = avctx->priv_data; + int zret; // Zlib return code + + c->avctx= avctx; + + av_assert0(avctx->width && avctx->height); + + avctx->extradata= av_mallocz(8); + avctx->coded_frame= &c->pic; + + c->compression = avctx->compression_level == FF_COMPRESSION_DEFAULT ? + COMP_ZLIB_NORMAL : + av_clip(avctx->compression_level, 0, 9); + c->flags = 0; + c->imgtype = IMGTYPE_RGB24; + avctx->bits_per_coded_sample= 24; + + avctx->extradata[0]= 4; + avctx->extradata[1]= 0; + avctx->extradata[2]= 0; + avctx->extradata[3]= 0; + avctx->extradata[4]= c->imgtype; + avctx->extradata[5]= c->compression; + avctx->extradata[6]= c->flags; + avctx->extradata[7]= CODEC_ZLIB; + c->avctx->extradata_size= 8; + + c->zstream.zalloc = Z_NULL; + c->zstream.zfree = Z_NULL; + c->zstream.opaque = Z_NULL; + zret = deflateInit(&c->zstream, c->compression); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Deflate init error: %d\n", zret); + return 1; + } + + return 0; +} + +/* + * + * Uninit lcl encoder + * + */ +static av_cold int encode_end(AVCodecContext *avctx) +{ + LclEncContext *c = avctx->priv_data; + + av_freep(&avctx->extradata); + deflateEnd(&c->zstream); + + return 0; +} + +AVCodec ff_zlib_encoder = { + .name = "zlib", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ZLIB, + .priv_data_size = sizeof(LclEncContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), +}; diff --git a/ffmpeg/libavcodec/libaacplus.c b/ffmpeg/libavcodec/libaacplus.c new file mode 100644 index 0000000..05c9e38 --- /dev/null +++ b/ffmpeg/libavcodec/libaacplus.c @@ -0,0 +1,141 @@ +/* + * Interface to libaacplus for aac+ (sbr+ps) encoding + * Copyright (c) 2010 tipok + * + * 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 + */ + +/** + * @file + * Interface to libaacplus for aac+ (sbr+ps) encoding. + */ + +#include + +#include "avcodec.h" +#include "internal.h" + +typedef struct aacPlusAudioContext { + aacplusEncHandle aacplus_handle; + unsigned long max_output_bytes; + unsigned long samples_input; +} aacPlusAudioContext; + +static av_cold int aacPlus_encode_init(AVCodecContext *avctx) +{ + aacPlusAudioContext *s = avctx->priv_data; + aacplusEncConfiguration *aacplus_cfg; + + /* number of channels */ + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels); + return -1; + } + + s->aacplus_handle = aacplusEncOpen(avctx->sample_rate, avctx->channels, + &s->samples_input, &s->max_output_bytes); + if(!s->aacplus_handle) { + av_log(avctx, AV_LOG_ERROR, "can't open encoder\n"); + return -1; + } + + /* check aacplus version */ + aacplus_cfg = aacplusEncGetCurrentConfiguration(s->aacplus_handle); + + /* put the options in the configuration struct */ + if(avctx->profile != FF_PROFILE_AAC_LOW && avctx->profile != FF_PROFILE_UNKNOWN) { + av_log(avctx, AV_LOG_ERROR, "invalid AAC profile: %d, only LC supported\n", avctx->profile); + aacplusEncClose(s->aacplus_handle); + return -1; + } + + aacplus_cfg->bitRate = avctx->bit_rate; + aacplus_cfg->bandWidth = avctx->cutoff; + aacplus_cfg->outputFormat = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER); + aacplus_cfg->inputFormat = AACPLUS_INPUT_16BIT; + if (!aacplusEncSetConfiguration(s->aacplus_handle, aacplus_cfg)) { + av_log(avctx, AV_LOG_ERROR, "libaacplus doesn't support this output format!\n"); + return -1; + } + + avctx->frame_size = s->samples_input / avctx->channels; + +#if FF_API_OLD_ENCODE_AUDIO + avctx->coded_frame= avcodec_alloc_frame(); + avctx->coded_frame->key_frame= 1; +#endif + + /* Set decoder specific info */ + avctx->extradata_size = 0; + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + + unsigned char *buffer = NULL; + unsigned long decoder_specific_info_size; + + if (aacplusEncGetDecoderSpecificInfo(s->aacplus_handle, &buffer, + &decoder_specific_info_size) == 1) { + avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE); + avctx->extradata_size = decoder_specific_info_size; + memcpy(avctx->extradata, buffer, avctx->extradata_size); + } + free(buffer); + } + return 0; +} + +static int aacPlus_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + aacPlusAudioContext *s = avctx->priv_data; + int32_t *input_buffer = (int32_t *)frame->data[0]; + int ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, s->max_output_bytes)) < 0) + return ret; + + pkt->size = aacplusEncEncode(s->aacplus_handle, input_buffer, + s->samples_input, pkt->data, pkt->size); + *got_packet = 1; + pkt->pts = frame->pts; + return 0; +} + +static av_cold int aacPlus_encode_close(AVCodecContext *avctx) +{ + aacPlusAudioContext *s = avctx->priv_data; + +#if FF_API_OLD_ENCODE_AUDIO + av_freep(&avctx->coded_frame); +#endif + av_freep(&avctx->extradata); + + aacplusEncClose(s->aacplus_handle); + return 0; +} + +AVCodec ff_libaacplus_encoder = { + .name = "libaacplus", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(aacPlusAudioContext), + .init = aacPlus_encode_init, + .encode2 = aacPlus_encode_frame, + .close = aacPlus_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libaacplus AAC+ (Advanced Audio Codec with SBR+PS)"), +}; diff --git a/ffmpeg/libavcodec/libavcodec.pc b/ffmpeg/libavcodec/libavcodec.pc new file mode 100644 index 0000000..7554a34 --- /dev/null +++ b/ffmpeg/libavcodec/libavcodec.pc @@ -0,0 +1,14 @@ +prefix=/usr/local +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: libavcodec +Description: FFmpeg codec library +Version: 55.1.100 +Requires: +Requires.private: libavutil = 52.22.100 +Conflicts: +Libs: -L${libdir} -lavcodec +Libs.private: -ldl -lXfixes -lXext -lX11 -lxvidcore -lx264 -lvorbisenc -lvorbis -logg -ltheoraenc -ltheoradec -logg -lschroedinger-1.0 -lmp3lame -lfaac -lm -pthread -lz +Cflags: -I${includedir} diff --git a/ffmpeg/libavcodec/libavcodec.v b/ffmpeg/libavcodec/libavcodec.v new file mode 100644 index 0000000..826a547 --- /dev/null +++ b/ffmpeg/libavcodec/libavcodec.v @@ -0,0 +1,33 @@ +LIBAVCODEC_$MAJOR { + global: av*; + #deprecated, remove after next bump + audio_resample; + audio_resample_close; + dsputil_init; + ff_dsputil_init; + ff_find_pix_fmt; + ff_framenum_to_drop_timecode; + ff_framenum_to_smtpe_timecode; + ff_raw_pix_fmt_tags; + ff_init_smtpe_timecode; + ff_fft*; + ff_mdct*; + ff_dct*; + ff_rdft*; + ff_prores_idct_put_10_sse2; + ff_simple_idct*; + ff_aanscales; + ff_faan*; + ff_mmx_idct; + ff_fdct*; + fdct_ifast; + j_rev_dct; + ff_mmxext_idct; + ff_idct_xvid*; + ff_jpeg_fdct*; + #XBMC's configure checks for ff_vdpau_vc1_decode_picture() + ff_vdpau_vc1_decode_picture; + ff_dnxhd_get_cid_table; + ff_dnxhd_cid_table; + local: *; +}; diff --git a/ffmpeg/libavcodec/libcelt_dec.c b/ffmpeg/libavcodec/libcelt_dec.c new file mode 100644 index 0000000..53bbb72 --- /dev/null +++ b/ffmpeg/libavcodec/libcelt_dec.c @@ -0,0 +1,140 @@ +/* + * Xiph CELT decoder using libcelt + * Copyright (c) 2011 Nicolas George + * + * 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 +#include "avcodec.h" +#include "internal.h" +#include "libavutil/intreadwrite.h" + +struct libcelt_context { + CELTMode *mode; + CELTDecoder *dec; + int discard; +}; + +static int ff_celt_error_to_averror(int err) +{ + switch (err) { + case CELT_BAD_ARG: return AVERROR(EINVAL); +#ifdef CELT_BUFFER_TOO_SMALL + case CELT_BUFFER_TOO_SMALL: return AVERROR(ENOBUFS); +#endif + case CELT_INTERNAL_ERROR: return AVERROR(EFAULT); + case CELT_CORRUPTED_DATA: return AVERROR_INVALIDDATA; + case CELT_UNIMPLEMENTED: return AVERROR(ENOSYS); +#ifdef ENOTRECOVERABLE + case CELT_INVALID_STATE: return AVERROR(ENOTRECOVERABLE); +#endif + case CELT_ALLOC_FAIL: return AVERROR(ENOMEM); + default: return AVERROR(EINVAL); + } +} + +static int ff_celt_bitstream_version_hack(CELTMode *mode) +{ + CELTHeader header = { .version_id = 0 }; + celt_header_init(&header, mode, 960, 2); + return header.version_id; +} + +static av_cold int libcelt_dec_init(AVCodecContext *c) +{ + struct libcelt_context *celt = c->priv_data; + int err; + + if (!c->channels || !c->frame_size || + c->frame_size > INT_MAX / sizeof(int16_t) / c->channels) + return AVERROR(EINVAL); + celt->mode = celt_mode_create(c->sample_rate, c->frame_size, &err); + if (!celt->mode) + return ff_celt_error_to_averror(err); + celt->dec = celt_decoder_create_custom(celt->mode, c->channels, &err); + if (!celt->dec) { + celt_mode_destroy(celt->mode); + return ff_celt_error_to_averror(err); + } + if (c->extradata_size >= 4) { + celt->discard = AV_RL32(c->extradata); + if (celt->discard < 0 || celt->discard >= c->frame_size) { + av_log(c, AV_LOG_WARNING, + "Invalid overlap (%d), ignored.\n", celt->discard); + celt->discard = 0; + } + } + if (c->extradata_size >= 8) { + unsigned version = AV_RL32(c->extradata + 4); + unsigned lib_version = ff_celt_bitstream_version_hack(celt->mode); + if (version != lib_version) + av_log(c, AV_LOG_WARNING, + "CELT bitstream version 0x%x may be " + "improperly decoded by libcelt for version 0x%x.\n", + version, lib_version); + } + c->sample_fmt = AV_SAMPLE_FMT_S16; + return 0; +} + +static av_cold int libcelt_dec_close(AVCodecContext *c) +{ + struct libcelt_context *celt = c->priv_data; + + celt_decoder_destroy(celt->dec); + celt_mode_destroy(celt->mode); + return 0; +} + +static int libcelt_dec_decode(AVCodecContext *c, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + struct libcelt_context *celt = c->priv_data; + AVFrame *frame = data; + int err; + int16_t *pcm; + + frame->nb_samples = c->frame_size; + if ((err = ff_get_buffer(c, frame, 0)) < 0) + return err; + pcm = (int16_t *)frame->data[0]; + err = celt_decode(celt->dec, pkt->data, pkt->size, pcm, c->frame_size); + if (err < 0) + return ff_celt_error_to_averror(err); + if (celt->discard) { + frame->nb_samples -= celt->discard; + memmove(pcm, pcm + celt->discard * c->channels, + frame->nb_samples * c->channels * sizeof(int16_t)); + celt->discard = 0; + } + *got_frame_ptr = 1; + return pkt->size; +} + +AVCodec ff_libcelt_decoder = { + .name = "libcelt", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_CELT, + .priv_data_size = sizeof(struct libcelt_context), + .init = libcelt_dec_init, + .close = libcelt_dec_close, + .decode = libcelt_dec_decode, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Xiph CELT decoder using libcelt"), +}; diff --git a/ffmpeg/libavcodec/libfaac.c b/ffmpeg/libavcodec/libfaac.c new file mode 100644 index 0000000..ac18fe2 --- /dev/null +++ b/ffmpeg/libavcodec/libfaac.c @@ -0,0 +1,237 @@ +/* + * Interface to libfaac for aac encoding + * Copyright (c) 2002 Gildas Bazin + * + * 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 + */ + +/** + * @file + * Interface to libfaac for aac encoding. + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" + + +/* libfaac has an encoder delay of 1024 samples */ +#define FAAC_DELAY_SAMPLES 1024 + +typedef struct FaacAudioContext { + faacEncHandle faac_handle; + AudioFrameQueue afq; +} FaacAudioContext; + +static av_cold int Faac_encode_close(AVCodecContext *avctx) +{ + FaacAudioContext *s = avctx->priv_data; + + av_freep(&avctx->extradata); + ff_af_queue_close(&s->afq); + + if (s->faac_handle) + faacEncClose(s->faac_handle); + + return 0; +} + +static const int channel_maps[][6] = { + { 2, 0, 1 }, //< C L R + { 2, 0, 1, 3 }, //< C L R Cs + { 2, 0, 1, 3, 4 }, //< C L R Ls Rs + { 2, 0, 1, 4, 5, 3 }, //< C L R Ls Rs LFE +}; + +static av_cold int Faac_encode_init(AVCodecContext *avctx) +{ + FaacAudioContext *s = avctx->priv_data; + faacEncConfigurationPtr faac_cfg; + unsigned long samples_input, max_bytes_output; + int ret; + + /* number of channels */ + if (avctx->channels < 1 || avctx->channels > 6) { + av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed\n", avctx->channels); + ret = AVERROR(EINVAL); + goto error; + } + + s->faac_handle = faacEncOpen(avctx->sample_rate, + avctx->channels, + &samples_input, &max_bytes_output); + if (!s->faac_handle) { + av_log(avctx, AV_LOG_ERROR, "error in faacEncOpen()\n"); + ret = AVERROR_UNKNOWN; + goto error; + } + + /* check faac version */ + faac_cfg = faacEncGetCurrentConfiguration(s->faac_handle); + if (faac_cfg->version != FAAC_CFG_VERSION) { + av_log(avctx, AV_LOG_ERROR, "wrong libfaac version (compiled for: %d, using %d)\n", FAAC_CFG_VERSION, faac_cfg->version); + ret = AVERROR(EINVAL); + goto error; + } + + /* put the options in the configuration struct */ + switch(avctx->profile) { + case FF_PROFILE_AAC_MAIN: + faac_cfg->aacObjectType = MAIN; + break; + case FF_PROFILE_UNKNOWN: + case FF_PROFILE_AAC_LOW: + faac_cfg->aacObjectType = LOW; + break; + case FF_PROFILE_AAC_SSR: + faac_cfg->aacObjectType = SSR; + break; + case FF_PROFILE_AAC_LTP: + faac_cfg->aacObjectType = LTP; + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid AAC profile\n"); + ret = AVERROR(EINVAL); + goto error; + } + faac_cfg->mpegVersion = MPEG4; + faac_cfg->useTns = 0; + faac_cfg->allowMidside = 1; + faac_cfg->bitRate = avctx->bit_rate / avctx->channels; + faac_cfg->bandWidth = avctx->cutoff; + if(avctx->flags & CODEC_FLAG_QSCALE) { + faac_cfg->bitRate = 0; + faac_cfg->quantqual = avctx->global_quality / FF_QP2LAMBDA; + } + faac_cfg->outputFormat = 1; + faac_cfg->inputFormat = FAAC_INPUT_16BIT; + if (avctx->channels > 2) + memcpy(faac_cfg->channel_map, channel_maps[avctx->channels-3], + avctx->channels * sizeof(int)); + + avctx->frame_size = samples_input / avctx->channels; + + /* Set decoder specific info */ + avctx->extradata_size = 0; + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + + unsigned char *buffer = NULL; + unsigned long decoder_specific_info_size; + + if (!faacEncGetDecoderSpecificInfo(s->faac_handle, &buffer, + &decoder_specific_info_size)) { + avctx->extradata = av_malloc(decoder_specific_info_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + ret = AVERROR(ENOMEM); + goto error; + } + avctx->extradata_size = decoder_specific_info_size; + memcpy(avctx->extradata, buffer, avctx->extradata_size); + faac_cfg->outputFormat = 0; + } + free(buffer); + } + + if (!faacEncSetConfiguration(s->faac_handle, faac_cfg)) { + av_log(avctx, AV_LOG_ERROR, "libfaac doesn't support this output format!\n"); + ret = AVERROR(EINVAL); + goto error; + } + + avctx->delay = FAAC_DELAY_SAMPLES; + ff_af_queue_init(avctx, &s->afq); + + return 0; +error: + Faac_encode_close(avctx); + return ret; +} + +static int Faac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + FaacAudioContext *s = avctx->priv_data; + int bytes_written, ret; + int num_samples = frame ? frame->nb_samples : 0; + void *samples = frame ? frame->data[0] : NULL; + + if ((ret = ff_alloc_packet2(avctx, avpkt, (7 + 768) * avctx->channels)) < 0) + return ret; + + bytes_written = faacEncEncode(s->faac_handle, samples, + num_samples * avctx->channels, + avpkt->data, avpkt->size); + if (bytes_written < 0) { + av_log(avctx, AV_LOG_ERROR, "faacEncEncode() error\n"); + return bytes_written; + } + + /* add current frame to the queue */ + if (frame) { + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } + + if (!bytes_written) + return 0; + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = bytes_written; + *got_packet_ptr = 1; + return 0; +} + +static const AVProfile profiles[] = { + { FF_PROFILE_AAC_MAIN, "Main" }, + { FF_PROFILE_AAC_LOW, "LC" }, + { FF_PROFILE_AAC_SSR, "SSR" }, + { FF_PROFILE_AAC_LTP, "LTP" }, + { FF_PROFILE_UNKNOWN }, +}; + +static const uint64_t faac_channel_layouts[] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + 0 +}; + +AVCodec ff_libfaac_encoder = { + .name = "libfaac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(FaacAudioContext), + .init = Faac_encode_init, + .encode2 = Faac_encode_frame, + .close = Faac_encode_close, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libfaac AAC (Advanced Audio Coding)"), + .profiles = NULL_IF_CONFIG_SMALL(profiles), + .channel_layouts = faac_channel_layouts, +}; diff --git a/ffmpeg/libavcodec/libfdk-aacenc.c b/ffmpeg/libavcodec/libfdk-aacenc.c new file mode 100644 index 0000000..e3992e1 --- /dev/null +++ b/ffmpeg/libavcodec/libfdk-aacenc.c @@ -0,0 +1,411 @@ +/* + * AAC encoder wrapper + * Copyright (c) 2012 Martin Storsjo + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" + +typedef struct AACContext { + const AVClass *class; + HANDLE_AACENCODER handle; + int afterburner; + int eld_sbr; + int signaling; + int latm; + int header_period; + int vbr; + + AudioFrameQueue afq; +} AACContext; + +static const AVOption aac_enc_options[] = { + { "afterburner", "Afterburner (improved quality)", offsetof(AACContext, afterburner), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "eld_sbr", "Enable SBR for ELD (for SBR in other configurations, use the -profile parameter)", offsetof(AACContext, eld_sbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "signaling", "SBR/PS signaling style", offsetof(AACContext, signaling), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 2, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, "signaling" }, + { "default", "Choose signaling implicitly (explicit hierarchical by default, implicit if global header is disabled)", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, "signaling" }, + { "implicit", "Implicit backwards compatible signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, "signaling" }, + { "explicit_sbr", "Explicit SBR, implicit PS signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, "signaling" }, + { "explicit_hierarchical", "Explicit hierarchical signaling", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM, "signaling" }, + { "latm", "Output LATM/LOAS encapsulated data", offsetof(AACContext, latm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "header_period", "StreamMuxConfig and PCE repetition period (in frames)", offsetof(AACContext, header_period), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xffff, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "vbr", "VBR mode (1-5)", offsetof(AACContext, vbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 5, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { NULL } +}; + +static const AVClass aac_enc_class = { + "libfdk_aac", av_default_item_name, aac_enc_options, LIBAVUTIL_VERSION_INT +}; + +static const char *aac_get_error(AACENC_ERROR err) +{ + switch (err) { + case AACENC_OK: + return "No error"; + case AACENC_INVALID_HANDLE: + return "Invalid handle"; + case AACENC_MEMORY_ERROR: + return "Memory allocation error"; + case AACENC_UNSUPPORTED_PARAMETER: + return "Unsupported parameter"; + case AACENC_INVALID_CONFIG: + return "Invalid config"; + case AACENC_INIT_ERROR: + return "Initialization error"; + case AACENC_INIT_AAC_ERROR: + return "AAC library initialization error"; + case AACENC_INIT_SBR_ERROR: + return "SBR library initialization error"; + case AACENC_INIT_TP_ERROR: + return "Transport library initialization error"; + case AACENC_INIT_META_ERROR: + return "Metadata library initialization error"; + case AACENC_ENCODE_ERROR: + return "Encoding error"; + case AACENC_ENCODE_EOF: + return "End of file"; + default: + return "Unknown error"; + } +} + +static int aac_encode_close(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + + if (s->handle) + aacEncClose(&s->handle); + av_freep(&avctx->extradata); + ff_af_queue_close(&s->afq); + + return 0; +} + +static av_cold int aac_encode_init(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + int ret = AVERROR(EINVAL); + AACENC_InfoStruct info = { 0 }; + CHANNEL_MODE mode; + AACENC_ERROR err; + int aot = FF_PROFILE_AAC_LOW + 1; + int sce = 0, cpe = 0; + + if ((err = aacEncOpen(&s->handle, 0, avctx->channels)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to open the encoder: %s\n", + aac_get_error(err)); + goto error; + } + + if (avctx->profile != FF_PROFILE_UNKNOWN) + aot = avctx->profile + 1; + + if ((err = aacEncoder_SetParam(s->handle, AACENC_AOT, aot)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set the AOT %d: %s\n", + aot, aac_get_error(err)); + goto error; + } + + if (aot == FF_PROFILE_AAC_ELD + 1 && s->eld_sbr) { + if ((err = aacEncoder_SetParam(s->handle, AACENC_SBR_MODE, + 1)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to enable SBR for ELD: %s\n", + aac_get_error(err)); + goto error; + } + } + + if ((err = aacEncoder_SetParam(s->handle, AACENC_SAMPLERATE, + avctx->sample_rate)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set the sample rate %d: %s\n", + avctx->sample_rate, aac_get_error(err)); + goto error; + } + + switch (avctx->channels) { + case 1: mode = MODE_1; sce = 1; cpe = 0; break; + case 2: mode = MODE_2; sce = 0; cpe = 1; break; + case 3: mode = MODE_1_2; sce = 1; cpe = 1; break; + case 4: mode = MODE_1_2_1; sce = 2; cpe = 1; break; + case 5: mode = MODE_1_2_2; sce = 1; cpe = 2; break; + case 6: mode = MODE_1_2_2_1; sce = 2; cpe = 2; break; + default: + av_log(avctx, AV_LOG_ERROR, + "Unsupported number of channels %d\n", avctx->channels); + goto error; + } + + if ((err = aacEncoder_SetParam(s->handle, AACENC_CHANNELMODE, + mode)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, + "Unable to set channel mode %d: %s\n", mode, aac_get_error(err)); + goto error; + } + + if ((err = aacEncoder_SetParam(s->handle, AACENC_CHANNELORDER, + 1)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, + "Unable to set wav channel order %d: %s\n", + mode, aac_get_error(err)); + goto error; + } + + if (avctx->flags & CODEC_FLAG_QSCALE || s->vbr) { + int mode = s->vbr ? s->vbr : avctx->global_quality; + if (mode < 1 || mode > 5) { + av_log(avctx, AV_LOG_WARNING, + "VBR quality %d out of range, should be 1-5\n", mode); + mode = av_clip(mode, 1, 5); + } + av_log(avctx, AV_LOG_WARNING, + "Note, the VBR setting is unsupported and only works with " + "some parameter combinations\n"); + if ((err = aacEncoder_SetParam(s->handle, AACENC_BITRATEMODE, + mode)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set the VBR bitrate mode %d: %s\n", + mode, aac_get_error(err)); + goto error; + } + } else { + if (avctx->bit_rate <= 0) { + if (avctx->profile == FF_PROFILE_AAC_HE_V2) { + sce = 1; + cpe = 0; + } + avctx->bit_rate = (96*sce + 128*cpe) * avctx->sample_rate / 44; + if (avctx->profile == FF_PROFILE_AAC_HE || + avctx->profile == FF_PROFILE_AAC_HE_V2 || + s->eld_sbr) + avctx->bit_rate /= 2; + } + if ((err = aacEncoder_SetParam(s->handle, AACENC_BITRATE, + avctx->bit_rate)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set the bitrate %d: %s\n", + avctx->bit_rate, aac_get_error(err)); + goto error; + } + } + + /* Choose bitstream format - if global header is requested, use + * raw access units, otherwise use ADTS. */ + if ((err = aacEncoder_SetParam(s->handle, AACENC_TRANSMUX, + avctx->flags & CODEC_FLAG_GLOBAL_HEADER ? 0 : s->latm ? 10 : 2)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set the transmux format: %s\n", + aac_get_error(err)); + goto error; + } + + if (s->latm && s->header_period) { + if ((err = aacEncoder_SetParam(s->handle, AACENC_HEADER_PERIOD, + s->header_period)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set header period: %s\n", + aac_get_error(err)); + goto error; + } + } + + /* If no signaling mode is chosen, use explicit hierarchical signaling + * if using mp4 mode (raw access units, with global header) and + * implicit signaling if using ADTS. */ + if (s->signaling < 0) + s->signaling = avctx->flags & CODEC_FLAG_GLOBAL_HEADER ? 2 : 0; + + if ((err = aacEncoder_SetParam(s->handle, AACENC_SIGNALING_MODE, + s->signaling)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set signaling mode %d: %s\n", + s->signaling, aac_get_error(err)); + goto error; + } + + if ((err = aacEncoder_SetParam(s->handle, AACENC_AFTERBURNER, + s->afterburner)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set afterburner to %d: %s\n", + s->afterburner, aac_get_error(err)); + goto error; + } + + if (avctx->cutoff > 0) { + if (avctx->cutoff < (avctx->sample_rate + 255) >> 8 || avctx->cutoff > 20000) { + av_log(avctx, AV_LOG_ERROR, "cutoff valid range is %d-20000\n", + (avctx->sample_rate + 255) >> 8); + goto error; + } + if ((err = aacEncoder_SetParam(s->handle, AACENC_BANDWIDTH, + avctx->cutoff)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set the encoder bandwidth to %d: %s\n", + avctx->cutoff, aac_get_error(err)); + goto error; + } + } + + if ((err = aacEncEncode(s->handle, NULL, NULL, NULL, NULL)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to initialize the encoder: %s\n", + aac_get_error(err)); + return AVERROR(EINVAL); + } + + if ((err = aacEncInfo(s->handle, &info)) != AACENC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to get encoder info: %s\n", + aac_get_error(err)); + goto error; + } + + avctx->frame_size = info.frameLength; + avctx->delay = info.encoderDelay; + ff_af_queue_init(avctx, &s->afq); + + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + avctx->extradata_size = info.confSize; + avctx->extradata = av_mallocz(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + ret = AVERROR(ENOMEM); + goto error; + } + + memcpy(avctx->extradata, info.confBuf, info.confSize); + } + return 0; +error: + aac_encode_close(avctx); + return ret; +} + +static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AACContext *s = avctx->priv_data; + AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 }; + AACENC_InArgs in_args = { 0 }; + AACENC_OutArgs out_args = { 0 }; + int in_buffer_identifier = IN_AUDIO_DATA; + int in_buffer_size, in_buffer_element_size; + int out_buffer_identifier = OUT_BITSTREAM_DATA; + int out_buffer_size, out_buffer_element_size; + void *in_ptr, *out_ptr; + int ret; + AACENC_ERROR err; + + /* handle end-of-stream small frame and flushing */ + if (!frame) { + in_args.numInSamples = -1; + } else { + in_ptr = frame->data[0]; + in_buffer_size = 2 * avctx->channels * frame->nb_samples; + in_buffer_element_size = 2; + + in_args.numInSamples = avctx->channels * frame->nb_samples; + in_buf.numBufs = 1; + in_buf.bufs = &in_ptr; + in_buf.bufferIdentifiers = &in_buffer_identifier; + in_buf.bufSizes = &in_buffer_size; + in_buf.bufElSizes = &in_buffer_element_size; + + /* add current frame to the queue */ + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } + + /* The maximum packet size is 6144 bits aka 768 bytes per channel. */ + if ((ret = ff_alloc_packet2(avctx, avpkt, FFMAX(8192, 768 * avctx->channels))) < 0) + return ret; + + out_ptr = avpkt->data; + out_buffer_size = avpkt->size; + out_buffer_element_size = 1; + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_buffer_identifier; + out_buf.bufSizes = &out_buffer_size; + out_buf.bufElSizes = &out_buffer_element_size; + + if ((err = aacEncEncode(s->handle, &in_buf, &out_buf, &in_args, + &out_args)) != AACENC_OK) { + if (!frame && err == AACENC_ENCODE_EOF) + return 0; + av_log(avctx, AV_LOG_ERROR, "Unable to encode frame: %s\n", + aac_get_error(err)); + return AVERROR(EINVAL); + } + + if (!out_args.numOutBytes) + return 0; + + /* Get the next frame pts & duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = out_args.numOutBytes; + *got_packet_ptr = 1; + return 0; +} + +static const AVProfile profiles[] = { + { FF_PROFILE_AAC_LOW, "LC" }, + { FF_PROFILE_AAC_HE, "HE-AAC" }, + { FF_PROFILE_AAC_HE_V2, "HE-AACv2" }, + { FF_PROFILE_AAC_LD, "LD" }, + { FF_PROFILE_AAC_ELD, "ELD" }, + { FF_PROFILE_UNKNOWN }, +}; + +static const AVCodecDefault aac_encode_defaults[] = { + { "b", "0" }, + { NULL } +}; + +static const uint64_t aac_channel_layout[] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + 0, +}; + +static const int aac_sample_rates[] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 0 +}; + +AVCodec ff_libfdk_aac_encoder = { + .name = "libfdk_aac", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(AACContext), + .init = aac_encode_init, + .encode2 = aac_encode_frame, + .close = aac_encode_close, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), + .priv_class = &aac_enc_class, + .defaults = aac_encode_defaults, + .profiles = profiles, + .supported_samplerates = aac_sample_rates, + .channel_layouts = aac_channel_layout, +}; diff --git a/ffmpeg/libavcodec/libgsm.c b/ffmpeg/libavcodec/libgsm.c new file mode 100644 index 0000000..8250a15 --- /dev/null +++ b/ffmpeg/libavcodec/libgsm.c @@ -0,0 +1,254 @@ +/* + * Interface to libgsm for gsm encoding/decoding + * Copyright (c) 2005 Alban Bedel + * Copyright (c) 2006, 2007 Michel Bardiaux + * + * 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 + */ + +/** + * @file + * Interface to libgsm for gsm encoding/decoding + */ + +// The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html + +#include "config.h" +#if HAVE_GSM_H +#include +#else +#include +#endif + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "internal.h" +#include "gsm.h" + +static av_cold int libgsm_encode_close(AVCodecContext *avctx) { + gsm_destroy(avctx->priv_data); + avctx->priv_data = NULL; + return 0; +} + +static av_cold int libgsm_encode_init(AVCodecContext *avctx) { + if (avctx->channels > 1) { + av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n", + avctx->channels); + return -1; + } + + if (avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n", + avctx->sample_rate); + if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) + return -1; + } + if (avctx->bit_rate != 13000 /* Official */ && + avctx->bit_rate != 13200 /* Very common */ && + avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) { + av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %dbps\n", + avctx->bit_rate); + if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) + return -1; + } + + avctx->priv_data = gsm_create(); + if (!avctx->priv_data) + goto error; + + switch(avctx->codec_id) { + case AV_CODEC_ID_GSM: + avctx->frame_size = GSM_FRAME_SIZE; + avctx->block_align = GSM_BLOCK_SIZE; + break; + case AV_CODEC_ID_GSM_MS: { + int one = 1; + gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one); + avctx->frame_size = 2*GSM_FRAME_SIZE; + avctx->block_align = GSM_MS_BLOCK_SIZE; + } + } + + return 0; +error: + libgsm_encode_close(avctx); + return -1; +} + +static int libgsm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + int ret; + gsm_signal *samples = (gsm_signal *)frame->data[0]; + struct gsm_state *state = avctx->priv_data; + + if ((ret = ff_alloc_packet2(avctx, avpkt, avctx->block_align)) < 0) + return ret; + + switch(avctx->codec_id) { + case AV_CODEC_ID_GSM: + gsm_encode(state, samples, avpkt->data); + break; + case AV_CODEC_ID_GSM_MS: + gsm_encode(state, samples, avpkt->data); + gsm_encode(state, samples + GSM_FRAME_SIZE, avpkt->data + 32); + } + + *got_packet_ptr = 1; + return 0; +} + + +#if CONFIG_LIBGSM_ENCODER +AVCodec ff_libgsm_encoder = { + .name = "libgsm", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_GSM, + .init = libgsm_encode_init, + .encode2 = libgsm_encode_frame, + .close = libgsm_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"), +}; +#endif +#if CONFIG_LIBGSM_MS_ENCODER +AVCodec ff_libgsm_ms_encoder = { + .name = "libgsm_ms", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_GSM_MS, + .init = libgsm_encode_init, + .encode2 = libgsm_encode_frame, + .close = libgsm_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"), +}; +#endif + +typedef struct LibGSMDecodeContext { + struct gsm_state *state; +} LibGSMDecodeContext; + +static av_cold int libgsm_decode_init(AVCodecContext *avctx) { + LibGSMDecodeContext *s = avctx->priv_data; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->sample_rate) + avctx->sample_rate = 8000; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + s->state = gsm_create(); + + switch(avctx->codec_id) { + case AV_CODEC_ID_GSM: + avctx->frame_size = GSM_FRAME_SIZE; + avctx->block_align = GSM_BLOCK_SIZE; + break; + case AV_CODEC_ID_GSM_MS: { + int one = 1; + gsm_option(s->state, GSM_OPT_WAV49, &one); + avctx->frame_size = 2 * GSM_FRAME_SIZE; + avctx->block_align = GSM_MS_BLOCK_SIZE; + } + } + + return 0; +} + +static av_cold int libgsm_decode_close(AVCodecContext *avctx) { + LibGSMDecodeContext *s = avctx->priv_data; + + gsm_destroy(s->state); + s->state = NULL; + return 0; +} + +static int libgsm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + int i, ret; + LibGSMDecodeContext *s = avctx->priv_data; + AVFrame *frame = data; + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int16_t *samples; + + if (buf_size < avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = avctx->frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + + for (i = 0; i < avctx->frame_size / GSM_FRAME_SIZE; i++) { + if ((ret = gsm_decode(s->state, buf, samples)) < 0) + return -1; + buf += GSM_BLOCK_SIZE; + samples += GSM_FRAME_SIZE; + } + + *got_frame_ptr = 1; + + return avctx->block_align; +} + +static void libgsm_flush(AVCodecContext *avctx) { + LibGSMDecodeContext *s = avctx->priv_data; + int one = 1; + + gsm_destroy(s->state); + s->state = gsm_create(); + if (avctx->codec_id == AV_CODEC_ID_GSM_MS) + gsm_option(s->state, GSM_OPT_WAV49, &one); +} + +#if CONFIG_LIBGSM_DECODER +AVCodec ff_libgsm_decoder = { + .name = "libgsm", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_GSM, + .priv_data_size = sizeof(LibGSMDecodeContext), + .init = libgsm_decode_init, + .close = libgsm_decode_close, + .decode = libgsm_decode_frame, + .flush = libgsm_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"), +}; +#endif +#if CONFIG_LIBGSM_MS_DECODER +AVCodec ff_libgsm_ms_decoder = { + .name = "libgsm_ms", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_GSM_MS, + .priv_data_size = sizeof(LibGSMDecodeContext), + .init = libgsm_decode_init, + .close = libgsm_decode_close, + .decode = libgsm_decode_frame, + .flush = libgsm_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"), +}; +#endif diff --git a/ffmpeg/libavcodec/libilbc.c b/ffmpeg/libavcodec/libilbc.c new file mode 100644 index 0000000..b4163c6 --- /dev/null +++ b/ffmpeg/libavcodec/libilbc.c @@ -0,0 +1,197 @@ +/* + * iLBC decoder/encoder stub + * Copyright (c) 2012 Martin Storsjo + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" + +static int get_mode(AVCodecContext *avctx) +{ + if (avctx->block_align == 38) + return 20; + else if (avctx->block_align == 50) + return 30; + else if (avctx->bit_rate > 0) + return avctx->bit_rate <= 14000 ? 30 : 20; + else + return -1; +} + +typedef struct ILBCDecContext { + const AVClass *class; + iLBC_Dec_Inst_t decoder; + int enhance; +} ILBCDecContext; + +static const AVOption ilbc_dec_options[] = { + { "enhance", "Enhance the decoded audio (adds delay)", offsetof(ILBCDecContext, enhance), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM }, + { NULL } +}; + +static const AVClass ilbc_dec_class = { + .class_name = "libilbc", + .item_name = av_default_item_name, + .option = ilbc_dec_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static av_cold int ilbc_decode_init(AVCodecContext *avctx) +{ + ILBCDecContext *s = avctx->priv_data; + int mode; + + if ((mode = get_mode(avctx)) < 0) { + av_log(avctx, AV_LOG_ERROR, "iLBC frame mode not indicated\n"); + return AVERROR(EINVAL); + } + + WebRtcIlbcfix_InitDecode(&s->decoder, mode, s->enhance); + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_rate = 8000; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int ilbc_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ILBCDecContext *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + if (s->decoder.no_of_bytes > buf_size) { + av_log(avctx, AV_LOG_ERROR, "iLBC frame too short (%u, should be %u)\n", + buf_size, s->decoder.no_of_bytes); + return AVERROR_INVALIDDATA; + } + + frame->nb_samples = s->decoder.blockl; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + WebRtcIlbcfix_DecodeImpl((WebRtc_Word16*) frame->data[0], + (const WebRtc_UWord16*) buf, &s->decoder, 1); + + *got_frame_ptr = 1; + + return s->decoder.no_of_bytes; +} + +AVCodec ff_libilbc_decoder = { + .name = "libilbc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ILBC, + .priv_data_size = sizeof(ILBCDecContext), + .init = ilbc_decode_init, + .decode = ilbc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), + .priv_class = &ilbc_dec_class, +}; + +typedef struct ILBCEncContext { + const AVClass *class; + iLBC_Enc_Inst_t encoder; + int mode; +} ILBCEncContext; + +static const AVOption ilbc_enc_options[] = { + { "mode", "iLBC mode (20 or 30 ms frames)", offsetof(ILBCEncContext, mode), AV_OPT_TYPE_INT, { .i64 = 20 }, 20, 30, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { NULL } +}; + +static const AVClass ilbc_enc_class = { + .class_name = "libilbc", + .item_name = av_default_item_name, + .option = ilbc_enc_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static av_cold int ilbc_encode_init(AVCodecContext *avctx) +{ + ILBCEncContext *s = avctx->priv_data; + int mode; + + if (avctx->sample_rate != 8000) { + av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n"); + return AVERROR(EINVAL); + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(EINVAL); + } + + if ((mode = get_mode(avctx)) > 0) + s->mode = mode; + else + s->mode = s->mode != 30 ? 20 : 30; + WebRtcIlbcfix_InitEncode(&s->encoder, s->mode); + + avctx->block_align = s->encoder.no_of_bytes; + avctx->frame_size = s->encoder.blockl; + + return 0; +} + +static int ilbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + ILBCEncContext *s = avctx->priv_data; + int ret; + + if ((ret = ff_alloc_packet2(avctx, avpkt, 50)) < 0) + return ret; + + WebRtcIlbcfix_EncodeImpl((WebRtc_UWord16*) avpkt->data, (const WebRtc_Word16*) frame->data[0], &s->encoder); + + avpkt->size = s->encoder.no_of_bytes; + *got_packet_ptr = 1; + return 0; +} + +static const AVCodecDefault ilbc_encode_defaults[] = { + { "b", "0" }, + { NULL } +}; + +AVCodec ff_libilbc_encoder = { + .name = "libilbc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ILBC, + .priv_data_size = sizeof(ILBCEncContext), + .init = ilbc_encode_init, + .encode2 = ilbc_encode_frame, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), + .defaults = ilbc_encode_defaults, + .priv_class = &ilbc_enc_class, +}; diff --git a/ffmpeg/libavcodec/libmp3lame.c b/ffmpeg/libavcodec/libmp3lame.c new file mode 100644 index 0000000..94e3582 --- /dev/null +++ b/ffmpeg/libavcodec/libmp3lame.c @@ -0,0 +1,305 @@ +/* + * Interface to libmp3lame for mp3 encoding + * Copyright (c) 2002 Lennert Buytenhek + * + * 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 + */ + +/** + * @file + * Interface to libmp3lame for mp3 encoding. + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" +#include "mpegaudio.h" +#include "mpegaudiodecheader.h" + +#define BUFFER_SIZE (7200 + 2 * MPA_FRAME_SIZE + MPA_FRAME_SIZE / 4+1000) // FIXME: Buffer size to small? Adding 1000 to make up for it. + +typedef struct LAMEContext { + AVClass *class; + AVCodecContext *avctx; + lame_global_flags *gfp; + uint8_t *buffer; + int buffer_index; + int buffer_size; + int reservoir; + float *samples_flt[2]; + AudioFrameQueue afq; + AVFloatDSPContext fdsp; +} LAMEContext; + + +static int realloc_buffer(LAMEContext *s) +{ + if (!s->buffer || s->buffer_size - s->buffer_index < BUFFER_SIZE) { + uint8_t *tmp; + int new_size = s->buffer_index + 2 * BUFFER_SIZE; + + av_dlog(s->avctx, "resizing output buffer: %d -> %d\n", s->buffer_size, + new_size); + tmp = av_realloc(s->buffer, new_size); + if (!tmp) { + av_freep(&s->buffer); + s->buffer_size = s->buffer_index = 0; + return AVERROR(ENOMEM); + } + s->buffer = tmp; + s->buffer_size = new_size; + } + return 0; +} + +static av_cold int mp3lame_encode_close(AVCodecContext *avctx) +{ + LAMEContext *s = avctx->priv_data; + + av_freep(&s->samples_flt[0]); + av_freep(&s->samples_flt[1]); + av_freep(&s->buffer); + + ff_af_queue_close(&s->afq); + + lame_close(s->gfp); + return 0; +} + +static av_cold int mp3lame_encode_init(AVCodecContext *avctx) +{ + LAMEContext *s = avctx->priv_data; + int ret; + + s->avctx = avctx; + + /* initialize LAME and get defaults */ + if ((s->gfp = lame_init()) == NULL) + return AVERROR(ENOMEM); + + + lame_set_num_channels(s->gfp, avctx->channels); + lame_set_mode(s->gfp, avctx->channels > 1 ? JOINT_STEREO : MONO); + + /* sample rate */ + lame_set_in_samplerate (s->gfp, avctx->sample_rate); + lame_set_out_samplerate(s->gfp, avctx->sample_rate); + + /* algorithmic quality */ + if (avctx->compression_level == FF_COMPRESSION_DEFAULT) + lame_set_quality(s->gfp, 5); + else + lame_set_quality(s->gfp, avctx->compression_level); + + /* rate control */ + if (avctx->flags & CODEC_FLAG_QSCALE) { + lame_set_VBR(s->gfp, vbr_default); + lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA); + } else { + if (avctx->bit_rate) + lame_set_brate(s->gfp, avctx->bit_rate / 1000); + } + + /* do not get a Xing VBR header frame from LAME */ + lame_set_bWriteVbrTag(s->gfp,0); + + /* bit reservoir usage */ + lame_set_disable_reservoir(s->gfp, !s->reservoir); + + /* set specified parameters */ + if (lame_init_params(s->gfp) < 0) { + ret = -1; + goto error; + } + + /* get encoder delay */ + avctx->delay = lame_get_encoder_delay(s->gfp) + 528 + 1; + ff_af_queue_init(avctx, &s->afq); + + avctx->frame_size = lame_get_framesize(s->gfp); + + /* allocate float sample buffers */ + if (avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) { + int ch; + for (ch = 0; ch < avctx->channels; ch++) { + s->samples_flt[ch] = av_malloc(avctx->frame_size * + sizeof(*s->samples_flt[ch])); + if (!s->samples_flt[ch]) { + ret = AVERROR(ENOMEM); + goto error; + } + } + } + + ret = realloc_buffer(s); + if (ret < 0) + goto error; + + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + return 0; +error: + mp3lame_encode_close(avctx); + return ret; +} + +#define ENCODE_BUFFER(func, buf_type, buf_name) do { \ + lame_result = func(s->gfp, \ + (const buf_type *)buf_name[0], \ + (const buf_type *)buf_name[1], frame->nb_samples, \ + s->buffer + s->buffer_index, \ + s->buffer_size - s->buffer_index); \ +} while (0) + +static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + LAMEContext *s = avctx->priv_data; + MPADecodeHeader hdr; + int len, ret, ch; + int lame_result; + + if (frame) { + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16P: + ENCODE_BUFFER(lame_encode_buffer, int16_t, frame->data); + break; + case AV_SAMPLE_FMT_S32P: + ENCODE_BUFFER(lame_encode_buffer_int, int32_t, frame->data); + break; + case AV_SAMPLE_FMT_FLTP: + if (frame->linesize[0] < 4 * FFALIGN(frame->nb_samples, 8)) { + av_log(avctx, AV_LOG_ERROR, "inadequate AVFrame plane padding\n"); + return AVERROR(EINVAL); + } + for (ch = 0; ch < avctx->channels; ch++) { + s->fdsp.vector_fmul_scalar(s->samples_flt[ch], + (const float *)frame->data[ch], + 32768.0f, + FFALIGN(frame->nb_samples, 8)); + } + ENCODE_BUFFER(lame_encode_buffer_float, float, s->samples_flt); + break; + default: + return AVERROR_BUG; + } + } else { + lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index, + s->buffer_size - s->buffer_index); + } + if (lame_result < 0) { + if (lame_result == -1) { + av_log(avctx, AV_LOG_ERROR, + "lame: output buffer too small (buffer index: %d, free bytes: %d)\n", + s->buffer_index, s->buffer_size - s->buffer_index); + } + return -1; + } + s->buffer_index += lame_result; + ret = realloc_buffer(s); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "error reallocating output buffer\n"); + return ret; + } + + /* add current frame to the queue */ + if (frame) { + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } + + /* Move 1 frame from the LAME buffer to the output packet, if available. + We have to parse the first frame header in the output buffer to + determine the frame size. */ + if (s->buffer_index < 4) + return 0; + if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) { + av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); + return -1; + } + len = hdr.frame_size; + av_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, + s->buffer_index); + if (len <= s->buffer_index) { + if ((ret = ff_alloc_packet2(avctx, avpkt, len)) < 0) + return ret; + memcpy(avpkt->data, s->buffer, len); + s->buffer_index -= len; + memmove(s->buffer, s->buffer + len, s->buffer_index); + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = len; + *got_packet_ptr = 1; + } + return 0; +} + +#define OFFSET(x) offsetof(LAMEContext, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "reservoir", "Use bit reservoir.", OFFSET(reservoir), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AE }, + { NULL }, +}; + +static const AVClass libmp3lame_class = { + .class_name = "libmp3lame encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault libmp3lame_defaults[] = { + { "b", "0" }, + { NULL }, +}; + +static const int libmp3lame_sample_rates[] = { + 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, 0 +}; + +AVCodec ff_libmp3lame_encoder = { + .name = "libmp3lame", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3, + .priv_data_size = sizeof(LAMEContext), + .init = mp3lame_encode_init, + .encode2 = mp3lame_encode_frame, + .close = mp3lame_encode_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = libmp3lame_sample_rates, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + 0 }, + .long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), + .priv_class = &libmp3lame_class, + .defaults = libmp3lame_defaults, +}; diff --git a/ffmpeg/libavcodec/libopencore-amr.c b/ffmpeg/libavcodec/libopencore-amr.c new file mode 100644 index 0000000..c991106 --- /dev/null +++ b/ffmpeg/libavcodec/libopencore-amr.c @@ -0,0 +1,379 @@ +/* + * AMR Audio decoder stub + * Copyright (c) 2003 the ffmpeg project + * + * 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 "libavutil/avstring.h" +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" + +static int amr_decode_fix_avctx(AVCodecContext *avctx) +{ + const int is_amr_wb = 1 + (avctx->codec_id == AV_CODEC_ID_AMR_WB); + + if (!avctx->sample_rate) + avctx->sample_rate = 8000 * is_amr_wb; + + if (avctx->channels > 1) { + avpriv_report_missing_feature(avctx, "multi-channel AMR"); + return AVERROR_PATCHWELCOME; + } + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + return 0; +} + +#if CONFIG_LIBOPENCORE_AMRNB + +#include +#include + +typedef struct AMRContext { + AVClass *av_class; + void *dec_state; + void *enc_state; + int enc_bitrate; + int enc_mode; + int enc_dtx; + int enc_last_frame; + AudioFrameQueue afq; +} AMRContext; + +#if CONFIG_LIBOPENCORE_AMRNB_DECODER +static av_cold int amr_nb_decode_init(AVCodecContext *avctx) +{ + AMRContext *s = avctx->priv_data; + int ret; + + if ((ret = amr_decode_fix_avctx(avctx)) < 0) + return ret; + + s->dec_state = Decoder_Interface_init(); + if (!s->dec_state) { + av_log(avctx, AV_LOG_ERROR, "Decoder_Interface_init error\n"); + return -1; + } + + return 0; +} + +static av_cold int amr_nb_decode_close(AVCodecContext *avctx) +{ + AMRContext *s = avctx->priv_data; + + Decoder_Interface_exit(s->dec_state); + + return 0; +} + +static int amr_nb_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AMRContext *s = avctx->priv_data; + static const uint8_t block_size[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 }; + enum Mode dec_mode; + int packet_size, ret; + + av_dlog(avctx, "amr_decode_frame buf=%p buf_size=%d frame_count=%d!!\n", + buf, buf_size, avctx->frame_number); + + /* get output buffer */ + frame->nb_samples = 160; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + dec_mode = (buf[0] >> 3) & 0x000F; + packet_size = block_size[dec_mode] + 1; + + if (packet_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n", + buf_size, packet_size); + return AVERROR_INVALIDDATA; + } + + av_dlog(avctx, "packet_size=%d buf= 0x%X %X %X %X\n", + packet_size, buf[0], buf[1], buf[2], buf[3]); + /* call decoder */ + Decoder_Interface_Decode(s->dec_state, buf, (short *)frame->data[0], 0); + + *got_frame_ptr = 1; + + return packet_size; +} + +AVCodec ff_libopencore_amrnb_decoder = { + .name = "libopencore_amrnb", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AMR_NB, + .priv_data_size = sizeof(AMRContext), + .init = amr_nb_decode_init, + .close = amr_nb_decode_close, + .decode = amr_nb_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band)"), +}; +#endif /* CONFIG_LIBOPENCORE_AMRNB_DECODER */ + +#if CONFIG_LIBOPENCORE_AMRNB_ENCODER +/* Common code for fixed and float version*/ +typedef struct AMR_bitrates { + int rate; + enum Mode mode; +} AMR_bitrates; + +/* Match desired bitrate */ +static int get_bitrate_mode(int bitrate, void *log_ctx) +{ + /* make the correspondance between bitrate and mode */ + static const AMR_bitrates rates[] = { + { 4750, MR475 }, { 5150, MR515 }, { 5900, MR59 }, { 6700, MR67 }, + { 7400, MR74 }, { 7950, MR795 }, { 10200, MR102 }, { 12200, MR122 } + }; + int i, best = -1, min_diff = 0; + char log_buf[200]; + + for (i = 0; i < 8; i++) { + if (rates[i].rate == bitrate) + return rates[i].mode; + if (best < 0 || abs(rates[i].rate - bitrate) < min_diff) { + best = i; + min_diff = abs(rates[i].rate - bitrate); + } + } + /* no bitrate matching exactly, log a warning */ + snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of "); + for (i = 0; i < 8; i++) + av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i].rate / 1000.f); + av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best].rate / 1000.f); + av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf); + + return best; +} + +static const AVOption options[] = { + { "dtx", "Allow DTX (generate comfort noise)", offsetof(AMRContext, enc_dtx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { NULL } +}; + +static const AVClass class = { + "libopencore_amrnb", av_default_item_name, options, LIBAVUTIL_VERSION_INT +}; + +static av_cold int amr_nb_encode_init(AVCodecContext *avctx) +{ + AMRContext *s = avctx->priv_data; + + if (avctx->sample_rate != 8000 && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n"); + return AVERROR(ENOSYS); + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(ENOSYS); + } + + avctx->frame_size = 160; + avctx->delay = 50; + ff_af_queue_init(avctx, &s->afq); + + s->enc_state = Encoder_Interface_init(s->enc_dtx); + if (!s->enc_state) { + av_log(avctx, AV_LOG_ERROR, "Encoder_Interface_init error\n"); + av_freep(&avctx->coded_frame); + return -1; + } + + s->enc_mode = get_bitrate_mode(avctx->bit_rate, avctx); + s->enc_bitrate = avctx->bit_rate; + + return 0; +} + +static av_cold int amr_nb_encode_close(AVCodecContext *avctx) +{ + AMRContext *s = avctx->priv_data; + + Encoder_Interface_exit(s->enc_state); + ff_af_queue_close(&s->afq); + return 0; +} + +static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AMRContext *s = avctx->priv_data; + int written, ret; + int16_t *flush_buf = NULL; + const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL; + + if (s->enc_bitrate != avctx->bit_rate) { + s->enc_mode = get_bitrate_mode(avctx->bit_rate, avctx); + s->enc_bitrate = avctx->bit_rate; + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, 32)) < 0) + return ret; + + if (frame) { + if (frame->nb_samples < avctx->frame_size) { + flush_buf = av_mallocz(avctx->frame_size * sizeof(*flush_buf)); + if (!flush_buf) + return AVERROR(ENOMEM); + memcpy(flush_buf, samples, frame->nb_samples * sizeof(*flush_buf)); + samples = flush_buf; + if (frame->nb_samples < avctx->frame_size - avctx->delay) + s->enc_last_frame = -1; + } + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) { + av_freep(&flush_buf); + return ret; + } + } else { + if (s->enc_last_frame < 0) + return 0; + flush_buf = av_mallocz(avctx->frame_size * sizeof(*flush_buf)); + if (!flush_buf) + return AVERROR(ENOMEM); + samples = flush_buf; + s->enc_last_frame = -1; + } + + written = Encoder_Interface_Encode(s->enc_state, s->enc_mode, samples, + avpkt->data, 0); + av_dlog(avctx, "amr_nb_encode_frame encoded %u bytes, bitrate %u, first byte was %#02x\n", + written, s->enc_mode, avpkt->data[0]); + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = written; + *got_packet_ptr = 1; + av_freep(&flush_buf); + return 0; +} + +AVCodec ff_libopencore_amrnb_encoder = { + .name = "libopencore_amrnb", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AMR_NB, + .priv_data_size = sizeof(AMRContext), + .init = amr_nb_encode_init, + .encode2 = amr_nb_encode_frame, + .close = amr_nb_encode_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band)"), + .priv_class = &class, +}; +#endif /* CONFIG_LIBOPENCORE_AMRNB_ENCODER */ + +#endif /* CONFIG_LIBOPENCORE_AMRNB */ + +/* -----------AMR wideband ------------*/ +#if CONFIG_LIBOPENCORE_AMRWB_DECODER + +#include +#include + +typedef struct AMRWBContext { + void *state; +} AMRWBContext; + +static av_cold int amr_wb_decode_init(AVCodecContext *avctx) +{ + AMRWBContext *s = avctx->priv_data; + int ret; + + if ((ret = amr_decode_fix_avctx(avctx)) < 0) + return ret; + + s->state = D_IF_init(); + + return 0; +} + +static int amr_wb_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AMRWBContext *s = avctx->priv_data; + int mode, ret; + int packet_size; + static const uint8_t block_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1}; + + /* get output buffer */ + frame->nb_samples = 320; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + mode = (buf[0] >> 3) & 0x000F; + packet_size = block_size[mode]; + + if (packet_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n", + buf_size, packet_size + 1); + return AVERROR_INVALIDDATA; + } + if (!packet_size) { + av_log(avctx, AV_LOG_ERROR, "amr packet_size invalid\n"); + return AVERROR_INVALIDDATA; + } + + D_IF_decode(s->state, buf, (short *)frame->data[0], _good_frame); + + *got_frame_ptr = 1; + + return packet_size; +} + +static int amr_wb_decode_close(AVCodecContext *avctx) +{ + AMRWBContext *s = avctx->priv_data; + + D_IF_exit(s->state); + return 0; +} + +AVCodec ff_libopencore_amrwb_decoder = { + .name = "libopencore_amrwb", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AMR_WB, + .priv_data_size = sizeof(AMRWBContext), + .init = amr_wb_decode_init, + .close = amr_wb_decode_close, + .decode = amr_wb_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-WB (Adaptive Multi-Rate Wide-Band)"), +}; + +#endif /* CONFIG_LIBOPENCORE_AMRWB_DECODER */ diff --git a/ffmpeg/libavcodec/libopenjpegdec.c b/ffmpeg/libavcodec/libopenjpegdec.c new file mode 100644 index 0000000..f8b6165 --- /dev/null +++ b/ffmpeg/libavcodec/libopenjpegdec.c @@ -0,0 +1,408 @@ +/* + * JPEG 2000 decoding support via OpenJPEG + * Copyright (c) 2009 Jaikrishnan Menon + * + * 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 + */ + +/** + * @file + * JPEG 2000 decoder using libopenjpeg + */ + +#define OPJ_STATIC + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "libavutil/pixfmt.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "thread.h" + +#if HAVE_OPENJPEG_1_5_OPENJPEG_H +# include +#else +# include +#endif + +#define JP2_SIG_TYPE 0x6A502020 +#define JP2_SIG_VALUE 0x0D0A870A + +// pix_fmts with lower bpp have to be listed before +// similar pix_fmts with higher bpp. +#define RGB_PIXEL_FORMATS AV_PIX_FMT_RGB24,AV_PIX_FMT_RGBA,AV_PIX_FMT_RGB48,AV_PIX_FMT_RGBA64 +#define GRAY_PIXEL_FORMATS AV_PIX_FMT_GRAY8,AV_PIX_FMT_GRAY8A,AV_PIX_FMT_GRAY16 +#define YUV_PIXEL_FORMATS AV_PIX_FMT_YUV410P,AV_PIX_FMT_YUV411P,AV_PIX_FMT_YUVA420P, \ + AV_PIX_FMT_YUV420P,AV_PIX_FMT_YUV422P,AV_PIX_FMT_YUVA422P, \ + AV_PIX_FMT_YUV440P,AV_PIX_FMT_YUV444P,AV_PIX_FMT_YUVA444P, \ + AV_PIX_FMT_YUV420P9,AV_PIX_FMT_YUV422P9,AV_PIX_FMT_YUV444P9, \ + AV_PIX_FMT_YUVA420P9,AV_PIX_FMT_YUVA422P9,AV_PIX_FMT_YUVA444P9, \ + AV_PIX_FMT_YUV420P10,AV_PIX_FMT_YUV422P10,AV_PIX_FMT_YUV444P10, \ + AV_PIX_FMT_YUVA420P10,AV_PIX_FMT_YUVA422P10,AV_PIX_FMT_YUVA444P10, \ + AV_PIX_FMT_YUV420P12,AV_PIX_FMT_YUV422P12,AV_PIX_FMT_YUV444P12, \ + AV_PIX_FMT_YUV420P14,AV_PIX_FMT_YUV422P14,AV_PIX_FMT_YUV444P14, \ + AV_PIX_FMT_YUV420P16,AV_PIX_FMT_YUV422P16,AV_PIX_FMT_YUV444P16, \ + AV_PIX_FMT_YUVA420P16,AV_PIX_FMT_YUVA422P16,AV_PIX_FMT_YUVA444P16 + +static const enum AVPixelFormat libopenjpeg_rgb_pix_fmts[] = {RGB_PIXEL_FORMATS}; +static const enum AVPixelFormat libopenjpeg_gray_pix_fmts[] = {GRAY_PIXEL_FORMATS}; +static const enum AVPixelFormat libopenjpeg_yuv_pix_fmts[] = {YUV_PIXEL_FORMATS}; +static const enum AVPixelFormat libopenjpeg_all_pix_fmts[] = {RGB_PIXEL_FORMATS,GRAY_PIXEL_FORMATS,YUV_PIXEL_FORMATS}; + +typedef struct { + AVClass *class; + opj_dparameters_t dec_params; + int lowqual; +} LibOpenJPEGContext; + +static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int match = 1; + + if (desc->nb_components != image->numcomps) { + return 0; + } + + switch (desc->nb_components) { + case 4: match = match && desc->comp[3].depth_minus1 + 1 >= image->comps[3].prec && + 1 == image->comps[3].dx && + 1 == image->comps[3].dy; + case 3: match = match && desc->comp[2].depth_minus1 + 1 >= image->comps[2].prec && + 1 << desc->log2_chroma_w == image->comps[2].dx && + 1 << desc->log2_chroma_h == image->comps[2].dy; + case 2: match = match && desc->comp[1].depth_minus1 + 1 >= image->comps[1].prec && + 1 << desc->log2_chroma_w == image->comps[1].dx && + 1 << desc->log2_chroma_h == image->comps[1].dy; + case 1: match = match && desc->comp[0].depth_minus1 + 1 >= image->comps[0].prec && + 1 == image->comps[0].dx && + 1 == image->comps[0].dy; + default: + break; + } + + return match; +} + +static inline enum AVPixelFormat libopenjpeg_guess_pix_fmt(const opj_image_t *image) { + int index; + const enum AVPixelFormat *possible_fmts = NULL; + int possible_fmts_nb = 0; + + switch (image->color_space) { + case CLRSPC_SRGB: + possible_fmts = libopenjpeg_rgb_pix_fmts; + possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_rgb_pix_fmts); + break; + case CLRSPC_GRAY: + possible_fmts = libopenjpeg_gray_pix_fmts; + possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_gray_pix_fmts); + break; + case CLRSPC_SYCC: + possible_fmts = libopenjpeg_yuv_pix_fmts; + possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_yuv_pix_fmts); + break; + default: + possible_fmts = libopenjpeg_all_pix_fmts; + possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_all_pix_fmts); + break; + } + + for (index = 0; index < possible_fmts_nb; ++index) { + if (libopenjpeg_matches_pix_fmt(image, possible_fmts[index])) { + return possible_fmts[index]; + } + } + + return AV_PIX_FMT_NONE; +} + +static inline int libopenjpeg_ispacked(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int i, component_plane; + + if (pix_fmt == AV_PIX_FMT_GRAY16) + return 0; + + component_plane = desc->comp[0].plane; + for (i = 1; i < desc->nb_components; i++) { + if (component_plane != desc->comp[i].plane) + return 0; + } + return 1; +} + +static inline void libopenjpeg_copy_to_packed8(AVFrame *picture, opj_image_t *image) { + uint8_t *img_ptr; + int index, x, y, c; + for (y = 0; y < picture->height; y++) { + index = y*picture->width; + img_ptr = picture->data[0] + y*picture->linesize[0]; + for (x = 0; x < picture->width; x++, index++) { + for (c = 0; c < image->numcomps; c++) { + *img_ptr++ = image->comps[c].data[index]; + } + } + } +} + +static inline void libopenjpeg_copy_to_packed16(AVFrame *picture, opj_image_t *image) { + uint16_t *img_ptr; + int index, x, y, c; + int adjust[4]; + for (x = 0; x < image->numcomps; x++) + adjust[x] = FFMAX(FFMIN(16 - image->comps[x].prec, 8), 0); + + for (y = 0; y < picture->height; y++) { + index = y*picture->width; + img_ptr = (uint16_t*) (picture->data[0] + y*picture->linesize[0]); + for (x = 0; x < picture->width; x++, index++) { + for (c = 0; c < image->numcomps; c++) { + *img_ptr++ = image->comps[c].data[index] << adjust[c]; + } + } + } +} + +static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t *image) { + int *comp_data; + uint8_t *img_ptr; + int index, x, y; + + for (index = 0; index < image->numcomps; index++) { + comp_data = image->comps[index].data; + for (y = 0; y < image->comps[index].h; y++) { + img_ptr = picture->data[index] + y * picture->linesize[index]; + for (x = 0; x < image->comps[index].w; x++) { + *img_ptr = (uint8_t) *comp_data; + img_ptr++; + comp_data++; + } + } + } +} + +static inline void libopenjpeg_copyto16(AVFrame *picture, opj_image_t *image) { + int *comp_data; + uint16_t *img_ptr; + int index, x, y; + for (index = 0; index < image->numcomps; index++) { + comp_data = image->comps[index].data; + for (y = 0; y < image->comps[index].h; y++) { + img_ptr = (uint16_t*) (picture->data[index] + y * picture->linesize[index]); + for (x = 0; x < image->comps[index].w; x++) { + *img_ptr = *comp_data; + img_ptr++; + comp_data++; + } + } + } +} + +static av_cold int libopenjpeg_decode_init(AVCodecContext *avctx) +{ + LibOpenJPEGContext *ctx = avctx->priv_data; + + opj_set_default_decoder_parameters(&ctx->dec_params); + return 0; +} + +static int libopenjpeg_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + LibOpenJPEGContext *ctx = avctx->priv_data; + ThreadFrame frame = { .f = data }; + AVFrame *picture = data; + const AVPixFmtDescriptor *desc; + opj_dinfo_t *dec; + opj_cio_t *stream; + opj_image_t *image; + int width, height, ret = -1; + int pixel_size = 0; + int ispacked = 0; + int i; + + *got_frame = 0; + + // Check if input is a raw jpeg2k codestream or in jp2 wrapping + if ((AV_RB32(buf) == 12) && + (AV_RB32(buf + 4) == JP2_SIG_TYPE) && + (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { + dec = opj_create_decompress(CODEC_JP2); + } else { + /* If the AVPacket contains a jp2c box, then skip to + * the starting byte of the codestream. */ + if (AV_RB32(buf + 4) == AV_RB32("jp2c")) + buf += 8; + dec = opj_create_decompress(CODEC_J2K); + } + + if (!dec) { + av_log(avctx, AV_LOG_ERROR, "Error initializing decoder.\n"); + return -1; + } + opj_set_event_mgr((opj_common_ptr)dec, NULL, NULL); + ctx->dec_params.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; + ctx->dec_params.cp_layer = ctx->lowqual; + // Tie decoder with decoding parameters + opj_setup_decoder(dec, &ctx->dec_params); + stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); + + if (!stream) { + av_log(avctx, AV_LOG_ERROR, + "Codestream could not be opened for reading.\n"); + opj_destroy_decompress(dec); + return -1; + } + + // Decode the header only. + image = opj_decode_with_info(dec, stream, NULL); + opj_cio_close(stream); + + if (!image) { + av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); + opj_destroy_decompress(dec); + return -1; + } + + width = image->x1 - image->x0; + height = image->y1 - image->y0; + + if (av_image_check_size(width, height, 0, avctx) < 0) { + av_log(avctx, AV_LOG_ERROR, + "%dx%d dimension invalid.\n", width, height); + goto done; + } + + avcodec_set_dimensions(avctx, width, height); + + if (avctx->pix_fmt != AV_PIX_FMT_NONE) + if (!libopenjpeg_matches_pix_fmt(image, avctx->pix_fmt)) + avctx->pix_fmt = AV_PIX_FMT_NONE; + + if (avctx->pix_fmt == AV_PIX_FMT_NONE) + avctx->pix_fmt = libopenjpeg_guess_pix_fmt(image); + + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unable to determine pixel format\n"); + goto done; + } + for (i = 0; i < image->numcomps; i++) + if (image->comps[i].prec > avctx->bits_per_raw_sample) + avctx->bits_per_raw_sample = image->comps[i].prec; + + if (ff_thread_get_buffer(avctx, &frame, 0) < 0) + goto done; + + ctx->dec_params.cp_limit_decoding = NO_LIMITATION; + ctx->dec_params.cp_reduce = avctx->lowres; + // Tie decoder with decoding parameters. + opj_setup_decoder(dec, &ctx->dec_params); + stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); + if (!stream) { + av_log(avctx, AV_LOG_ERROR, + "Codestream could not be opened for reading.\n"); + goto done; + } + + opj_image_destroy(image); + // Decode the codestream + image = opj_decode_with_info(dec, stream, NULL); + opj_cio_close(stream); + + if (!image) { + av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); + goto done; + } + + desc = av_pix_fmt_desc_get(avctx->pix_fmt); + pixel_size = desc->comp[0].step_minus1 + 1; + ispacked = libopenjpeg_ispacked(avctx->pix_fmt); + + switch (pixel_size) { + case 1: + if (ispacked) { + libopenjpeg_copy_to_packed8(picture, image); + } else { + libopenjpeg_copyto8(picture, image); + } + break; + case 2: + if (ispacked) { + libopenjpeg_copy_to_packed8(picture, image); + } else { + libopenjpeg_copyto16(picture, image); + } + break; + case 3: + case 4: + if (ispacked) { + libopenjpeg_copy_to_packed8(picture, image); + } + break; + case 6: + case 8: + if (ispacked) { + libopenjpeg_copy_to_packed16(picture, image); + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "unsupported pixel size %d\n", pixel_size); + goto done; + } + + *got_frame = 1; + ret = buf_size; + +done: + opj_image_destroy(image); + opj_destroy_decompress(dec); + return ret; +} + +#define OFFSET(x) offsetof(LibOpenJPEGContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +static const AVOption options[] = { + { "lowqual", "Limit the number of layers used for decoding", OFFSET(lowqual), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "libopenjpeg", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libopenjpeg_decoder = { + .name = "libopenjpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEG2000, + .priv_data_size = sizeof(LibOpenJPEGContext), + .init = libopenjpeg_decode_init, + .decode = libopenjpeg_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .max_lowres = 31, + .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), + .priv_class = &class, +}; diff --git a/ffmpeg/libavcodec/libopenjpegenc.c b/ffmpeg/libavcodec/libopenjpegenc.c new file mode 100644 index 0000000..c355083 --- /dev/null +++ b/ffmpeg/libavcodec/libopenjpegenc.c @@ -0,0 +1,581 @@ +/* + * JPEG 2000 encoding support via OpenJPEG + * Copyright (c) 2011 Michael Bradshaw + * + * 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 + */ + +/** + * @file + * JPEG 2000 encoder using libopenjpeg + */ + +#define OPJ_STATIC + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" + +#if HAVE_OPENJPEG_1_5_OPENJPEG_H +# include +#else +# include +#endif + +typedef struct { + AVClass *avclass; + opj_image_t *image; + opj_cparameters_t enc_params; + opj_cinfo_t *compress; + opj_event_mgr_t event_mgr; + int format; + int profile; + int prog_order; + int cinema_mode; + int numresolution; + int numlayers; + int disto_alloc; + int fixed_alloc; + int fixed_quality; +} LibOpenJPEGContext; + +static void error_callback(const char *msg, void *data) +{ + av_log(data, AV_LOG_ERROR, "%s\n", msg); +} + +static void warning_callback(const char *msg, void *data) +{ + av_log(data, AV_LOG_WARNING, "%s\n", msg); +} + +static void info_callback(const char *msg, void *data) +{ + av_log(data, AV_LOG_DEBUG, "%s\n", msg); +} + +static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + opj_image_cmptparm_t *cmptparm; + opj_image_t *img; + int i; + int sub_dx[4]; + int sub_dy[4]; + int numcomps; + OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN; + + sub_dx[0] = sub_dx[3] = 1; + sub_dy[0] = sub_dy[3] = 1; + sub_dx[1] = sub_dx[2] = 1 << desc->log2_chroma_w; + sub_dy[1] = sub_dy[2] = 1 << desc->log2_chroma_h; + + numcomps = desc->nb_components; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_GRAY8A: + case AV_PIX_FMT_GRAY16: + color_space = CLRSPC_GRAY; + break; + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_RGB48: + case AV_PIX_FMT_RGBA64: + case AV_PIX_FMT_GBR24P: + case AV_PIX_FMT_GBRP9: + case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRP12: + case AV_PIX_FMT_GBRP14: + case AV_PIX_FMT_GBRP16: + color_space = CLRSPC_SRGB; + break; + case AV_PIX_FMT_YUV410P: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV440P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUVA420P: + case AV_PIX_FMT_YUVA422P: + case AV_PIX_FMT_YUVA444P: + case AV_PIX_FMT_YUV420P9: + case AV_PIX_FMT_YUV422P9: + case AV_PIX_FMT_YUV444P9: + case AV_PIX_FMT_YUVA420P9: + case AV_PIX_FMT_YUVA422P9: + case AV_PIX_FMT_YUVA444P9: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV422P10: + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUVA420P10: + case AV_PIX_FMT_YUVA422P10: + case AV_PIX_FMT_YUVA444P10: + case AV_PIX_FMT_YUV420P12: + case AV_PIX_FMT_YUV422P12: + case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUV420P14: + case AV_PIX_FMT_YUV422P14: + case AV_PIX_FMT_YUV444P14: + case AV_PIX_FMT_YUV420P16: + case AV_PIX_FMT_YUV422P16: + case AV_PIX_FMT_YUV444P16: + case AV_PIX_FMT_YUVA420P16: + case AV_PIX_FMT_YUVA422P16: + case AV_PIX_FMT_YUVA444P16: + color_space = CLRSPC_SYCC; + break; + default: + av_log(avctx, AV_LOG_ERROR, + "The requested pixel format '%s' is not supported\n", + av_get_pix_fmt_name(avctx->pix_fmt)); + return NULL; + } + + cmptparm = av_mallocz(numcomps * sizeof(*cmptparm)); + if (!cmptparm) { + av_log(avctx, AV_LOG_ERROR, "Not enough memory\n"); + return NULL; + } + for (i = 0; i < numcomps; i++) { + cmptparm[i].prec = desc->comp[i].depth_minus1 + 1; + cmptparm[i].bpp = desc->comp[i].depth_minus1 + 1; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = sub_dx[i]; + cmptparm[i].dy = sub_dy[i]; + cmptparm[i].w = avctx->width / sub_dx[i]; + cmptparm[i].h = avctx->height / sub_dy[i]; + } + + img = opj_image_create(numcomps, cmptparm, color_space); + av_freep(&cmptparm); + return img; +} + +static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) +{ + LibOpenJPEGContext *ctx = avctx->priv_data; + int err = AVERROR(ENOMEM); + + opj_set_default_encoder_parameters(&ctx->enc_params); + + ctx->enc_params.cp_rsiz = ctx->profile; + ctx->enc_params.mode = !!avctx->global_quality; + ctx->enc_params.cp_cinema = ctx->cinema_mode; + ctx->enc_params.prog_order = ctx->prog_order; + ctx->enc_params.numresolution = ctx->numresolution; + ctx->enc_params.cp_disto_alloc = ctx->disto_alloc; + ctx->enc_params.cp_fixed_alloc = ctx->fixed_alloc; + ctx->enc_params.cp_fixed_quality = ctx->fixed_quality; + ctx->enc_params.tcp_numlayers = ctx->numlayers; + ctx->enc_params.tcp_rates[0] = FFMAX(avctx->compression_level, 0) * 2; + + if (ctx->cinema_mode > 0) { + ctx->enc_params.irreversible = 1; + ctx->enc_params.tcp_mct = 1; + ctx->enc_params.tile_size_on = 0; + /* no subsampling */ + ctx->enc_params.cp_tdx=1; + ctx->enc_params.cp_tdy=1; + ctx->enc_params.subsampling_dx = 1; + ctx->enc_params.subsampling_dy = 1; + /* Tile and Image shall be at (0,0) */ + ctx->enc_params.cp_tx0 = 0; + ctx->enc_params.cp_ty0 = 0; + ctx->enc_params.image_offset_x0 = 0; + ctx->enc_params.image_offset_y0 = 0; + /* Codeblock size= 32*32 */ + ctx->enc_params.cblockw_init = 32; + ctx->enc_params.cblockh_init = 32; + ctx->enc_params.csty |= 0x01; + /* No ROI */ + ctx->enc_params.roi_compno = -1; + + if (ctx->enc_params.prog_order != CPRL) { + av_log(avctx, AV_LOG_ERROR, "prog_order forced to CPRL\n"); + ctx->enc_params.prog_order = CPRL; + } + ctx->enc_params.tp_flag = 'C'; + ctx->enc_params.tp_on = 1; + } + + ctx->compress = opj_create_compress(ctx->format); + if (!ctx->compress) { + av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n"); + return AVERROR(ENOMEM); + } + + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); + goto fail; + } + + ctx->image = mj2_create_image(avctx, &ctx->enc_params); + if (!ctx->image) { + av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n"); + err = AVERROR(EINVAL); + goto fail; + } + + memset(&ctx->event_mgr, 0, sizeof(opj_event_mgr_t)); + ctx->event_mgr.info_handler = info_callback; + ctx->event_mgr.error_handler = error_callback; + ctx->event_mgr.warning_handler = warning_callback; + opj_set_event_mgr((opj_common_ptr)ctx->compress, &ctx->event_mgr, avctx); + + return 0; + +fail: + av_freep(&ctx->compress); + av_freep(&avctx->coded_frame); + return err; +} + +static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +{ + int compno; + int x; + int y; + int image_index; + int frame_index; + const int numcomps = image->numcomps; + + for (compno = 0; compno < numcomps; ++compno) { + if (image->comps[compno].w > frame->linesize[0] / numcomps) { + av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); + return 0; + } + } + + for (compno = 0; compno < numcomps; ++compno) { + for (y = 0; y < avctx->height; ++y) { + image_index = y * avctx->width; + frame_index = y * frame->linesize[0] + compno; + for (x = 0; x < avctx->width; ++x) { + image->comps[compno].data[image_index++] = frame->data[0][frame_index]; + frame_index += numcomps; + } + } + } + + return 1; +} + +static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +{ + int compno; + int x; + int y; + int image_index; + int frame_index; + const int numcomps = image->numcomps; + uint16_t *frame_ptr = (uint16_t*)frame->data[0]; + + for (compno = 0; compno < numcomps; ++compno) { + if (image->comps[compno].w > frame->linesize[0] / numcomps) { + av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); + return 0; + } + } + + for (compno = 0; compno < numcomps; ++compno) { + for (y = 0; y < avctx->height; ++y) { + image_index = y * avctx->width; + frame_index = y * (frame->linesize[0] / 2) + compno; + for (x = 0; x < avctx->width; ++x) { + image->comps[compno].data[image_index++] = frame_ptr[frame_index]; + frame_index += numcomps; + } + } + } + + return 1; +} + +static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +{ + int compno; + int x; + int y; + int width; + int height; + int image_index; + int frame_index; + const int numcomps = image->numcomps; + + for (compno = 0; compno < numcomps; ++compno) { + if (image->comps[compno].w > frame->linesize[compno]) { + av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); + return 0; + } + } + + for (compno = 0; compno < numcomps; ++compno) { + width = avctx->width / image->comps[compno].dx; + height = avctx->height / image->comps[compno].dy; + for (y = 0; y < height; ++y) { + image_index = y * width; + frame_index = y * frame->linesize[compno]; + for (x = 0; x < width; ++x) + image->comps[compno].data[image_index++] = frame->data[compno][frame_index++]; + } + } + + return 1; +} + +static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +{ + int compno; + int x; + int y; + int width; + int height; + int image_index; + int frame_index; + const int numcomps = image->numcomps; + uint16_t *frame_ptr; + + for (compno = 0; compno < numcomps; ++compno) { + if (image->comps[compno].w > frame->linesize[compno]) { + av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); + return 0; + } + } + + for (compno = 0; compno < numcomps; ++compno) { + width = avctx->width / image->comps[compno].dx; + height = avctx->height / image->comps[compno].dy; + frame_ptr = (uint16_t*)frame->data[compno]; + for (y = 0; y < height; ++y) { + image_index = y * width; + frame_index = y * (frame->linesize[compno] / 2); + for (x = 0; x < width; ++x) + image->comps[compno].data[image_index++] = frame_ptr[frame_index++]; + } + } + + return 1; +} + +static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + LibOpenJPEGContext *ctx = avctx->priv_data; + opj_cinfo_t *compress = ctx->compress; + opj_image_t *image = ctx->image; + opj_cio_t *stream; + int cpyresult = 0; + int ret, len; + AVFrame gbrframe; + + // x0, y0 is the top left corner of the image + // x1, y1 is the width, height of the reference grid + image->x0 = 0; + image->y0 = 0; + image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1; + image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_GRAY8A: + cpyresult = libopenjpeg_copy_packed8(avctx, frame, image); + break; + case AV_PIX_FMT_RGB48: + case AV_PIX_FMT_RGBA64: + cpyresult = libopenjpeg_copy_packed16(avctx, frame, image); + break; + case AV_PIX_FMT_GBR24P: + case AV_PIX_FMT_GBRP9: + case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRP12: + case AV_PIX_FMT_GBRP14: + case AV_PIX_FMT_GBRP16: + gbrframe = *frame; + gbrframe.data[0] = frame->data[2]; // swap to be rgb + gbrframe.data[1] = frame->data[0]; + gbrframe.data[2] = frame->data[1]; + gbrframe.linesize[0] = frame->linesize[2]; + gbrframe.linesize[1] = frame->linesize[0]; + gbrframe.linesize[2] = frame->linesize[1]; + if (avctx->pix_fmt == AV_PIX_FMT_GBR24P) { + cpyresult = libopenjpeg_copy_unpacked8(avctx, &gbrframe, image); + } else { + cpyresult = libopenjpeg_copy_unpacked16(avctx, &gbrframe, image); + } + break; + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_YUV410P: + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV440P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUVA420P: + case AV_PIX_FMT_YUVA422P: + case AV_PIX_FMT_YUVA444P: + cpyresult = libopenjpeg_copy_unpacked8(avctx, frame, image); + break; + case AV_PIX_FMT_GRAY16: + case AV_PIX_FMT_YUV420P9: + case AV_PIX_FMT_YUV422P9: + case AV_PIX_FMT_YUV444P9: + case AV_PIX_FMT_YUVA420P9: + case AV_PIX_FMT_YUVA422P9: + case AV_PIX_FMT_YUVA444P9: + case AV_PIX_FMT_YUV444P10: + case AV_PIX_FMT_YUV422P10: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUVA444P10: + case AV_PIX_FMT_YUVA422P10: + case AV_PIX_FMT_YUVA420P10: + case AV_PIX_FMT_YUV420P12: + case AV_PIX_FMT_YUV422P12: + case AV_PIX_FMT_YUV444P12: + case AV_PIX_FMT_YUV420P14: + case AV_PIX_FMT_YUV422P14: + case AV_PIX_FMT_YUV444P14: + case AV_PIX_FMT_YUV444P16: + case AV_PIX_FMT_YUV422P16: + case AV_PIX_FMT_YUV420P16: + case AV_PIX_FMT_YUVA444P16: + case AV_PIX_FMT_YUVA422P16: + case AV_PIX_FMT_YUVA420P16: + cpyresult = libopenjpeg_copy_unpacked16(avctx, frame, image); + break; + default: + av_log(avctx, AV_LOG_ERROR, + "The frame's pixel format '%s' is not supported\n", + av_get_pix_fmt_name(avctx->pix_fmt)); + return AVERROR(EINVAL); + break; + } + + if (!cpyresult) { + av_log(avctx, AV_LOG_ERROR, + "Could not copy the frame data to the internal image buffer\n"); + return -1; + } + + opj_setup_encoder(compress, &ctx->enc_params, image); + stream = opj_cio_open((opj_common_ptr)compress, NULL, 0); + if (!stream) { + av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); + return AVERROR(ENOMEM); + } + + if (!opj_encode(compress, stream, image, NULL)) { + opj_cio_close(stream); + av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); + return -1; + } + + len = cio_tell(stream); + if ((ret = ff_alloc_packet2(avctx, pkt, len)) < 0) { + opj_cio_close(stream); + return ret; + } + + memcpy(pkt->data, stream->buffer, len); + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + opj_cio_close(stream); + return 0; +} + +static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx) +{ + LibOpenJPEGContext *ctx = avctx->priv_data; + + opj_destroy_compress(ctx->compress); + opj_image_destroy(ctx->image); + av_freep(&avctx->coded_frame); + return 0; +} + +#define OFFSET(x) offsetof(LibOpenJPEGContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "format", "Codec Format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = CODEC_JP2 }, CODEC_J2K, CODEC_JP2, VE, "format" }, + { "j2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_J2K }, 0, 0, VE, "format" }, + { "jp2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CODEC_JP2 }, 0, 0, VE, "format" }, + { "profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = STD_RSIZ }, STD_RSIZ, CINEMA4K, VE, "profile" }, + { "jpeg2000", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = STD_RSIZ }, 0, 0, VE, "profile" }, + { "cinema2k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA2K }, 0, 0, VE, "profile" }, + { "cinema4k", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA4K }, 0, 0, VE, "profile" }, + { "cinema_mode", "Digital Cinema", OFFSET(cinema_mode), AV_OPT_TYPE_INT, { .i64 = OFF }, OFF, CINEMA4K_24, VE, "cinema_mode" }, + { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OFF }, 0, 0, VE, "cinema_mode" }, + { "2k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA2K_24 }, 0, 0, VE, "cinema_mode" }, + { "2k_48", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA2K_48 }, 0, 0, VE, "cinema_mode" }, + { "4k_24", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CINEMA4K_24 }, 0, 0, VE, "cinema_mode" }, + { "prog_order", "Progression Order", OFFSET(prog_order), AV_OPT_TYPE_INT, { .i64 = LRCP }, LRCP, CPRL, VE, "prog_order" }, + { "lrcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LRCP }, 0, 0, VE, "prog_order" }, + { "rlcp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = RLCP }, 0, 0, VE, "prog_order" }, + { "rpcl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = RPCL }, 0, 0, VE, "prog_order" }, + { "pcrl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PCRL }, 0, 0, VE, "prog_order" }, + { "cprl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPRL }, 0, 0, VE, "prog_order" }, + { "numresolution", NULL, OFFSET(numresolution), AV_OPT_TYPE_INT, { .i64 = 6 }, 1, INT_MAX, VE }, + { "numlayers", NULL, OFFSET(numlayers), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 10, VE }, + { "disto_alloc", NULL, OFFSET(disto_alloc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { "fixed_alloc", NULL, OFFSET(fixed_alloc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "fixed_quality", NULL, OFFSET(fixed_quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "libopenjpeg", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libopenjpeg_encoder = { + .name = "libopenjpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_JPEG2000, + .priv_data_size = sizeof(LibOpenJPEGContext), + .init = libopenjpeg_encode_init, + .encode2 = libopenjpeg_encode_frame, + .close = libopenjpeg_encode_close, + .capabilities = 0, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, + AV_PIX_FMT_GBR24P, + AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA422P, + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10, + AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, + AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), + .priv_class = &class, +}; diff --git a/ffmpeg/libavcodec/libopus.c b/ffmpeg/libavcodec/libopus.c new file mode 100644 index 0000000..16395c7 --- /dev/null +++ b/ffmpeg/libavcodec/libopus.c @@ -0,0 +1,48 @@ +/* + * libopus encoder/decoder common code + * Copyright (c) 2012 Nicolas George + * + * 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 "libavutil/common.h" +#include "libavutil/error.h" +#include "libopus.h" + +int ff_opus_error_to_averror(int err) +{ + switch (err) { + case OPUS_BAD_ARG: + return AVERROR(EINVAL); + case OPUS_BUFFER_TOO_SMALL: + return AVERROR_UNKNOWN; + case OPUS_INTERNAL_ERROR: + return AVERROR(EFAULT); + case OPUS_INVALID_PACKET: + return AVERROR_INVALIDDATA; + case OPUS_UNIMPLEMENTED: + return AVERROR(ENOSYS); + case OPUS_INVALID_STATE: + return AVERROR_UNKNOWN; + case OPUS_ALLOC_FAIL: + return AVERROR(ENOMEM); + default: + return AVERROR(EINVAL); + } +} diff --git a/ffmpeg/libavcodec/libopus.h b/ffmpeg/libavcodec/libopus.h new file mode 100644 index 0000000..a8223d1 --- /dev/null +++ b/ffmpeg/libavcodec/libopus.h @@ -0,0 +1,27 @@ +/* + * libopus encoder/decoder common code + * Copyright (c) 2012 Nicolas George + * + * 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 + */ + +#ifndef AVCODEC_LIBOPUS_H +#define AVCODEC_LIBOPUS_H + +int ff_opus_error_to_averror(int err); + +#endif /* AVCODEC_LIBOPUS_H */ diff --git a/ffmpeg/libavcodec/libopusdec.c b/ffmpeg/libavcodec/libopusdec.c new file mode 100644 index 0000000..9b5cfe7 --- /dev/null +++ b/ffmpeg/libavcodec/libopusdec.c @@ -0,0 +1,198 @@ +/* + * Opus decoder using libopus + * Copyright (c) 2012 Nicolas George + * + * 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 + +#include "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" +#include "vorbis.h" +#include "mathops.h" +#include "libopus.h" + +struct libopus_context { + OpusMSDecoder *dec; + int pre_skip; +#ifndef OPUS_SET_GAIN + union { int i; double d; } gain; +#endif +}; + +#define OPUS_HEAD_SIZE 19 + +static av_cold int libopus_decode_init(AVCodecContext *avc) +{ + struct libopus_context *opus = avc->priv_data; + int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; + uint8_t mapping_arr[8] = { 0, 1 }, *mapping; + + avc->sample_rate = 48000; + avc->sample_fmt = avc->request_sample_fmt == AV_SAMPLE_FMT_FLT ? + AV_SAMPLE_FMT_FLT : AV_SAMPLE_FMT_S16; + avc->channel_layout = avc->channels > 8 ? 0 : + ff_vorbis_channel_layouts[avc->channels - 1]; + + if (avc->extradata_size >= OPUS_HEAD_SIZE) { + opus->pre_skip = AV_RL16(avc->extradata + 10); + gain_db = sign_extend(AV_RL16(avc->extradata + 16), 16); + channel_map = AV_RL8 (avc->extradata + 18); + } + if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + avc->channels) { + nb_streams = avc->extradata[OPUS_HEAD_SIZE + 0]; + nb_coupled = avc->extradata[OPUS_HEAD_SIZE + 1]; + if (nb_streams + nb_coupled != avc->channels) + av_log(avc, AV_LOG_WARNING, "Inconsistent channel mapping.\n"); + mapping = avc->extradata + OPUS_HEAD_SIZE + 2; + } else { + if (avc->channels > 2 || channel_map) { + av_log(avc, AV_LOG_ERROR, + "No channel mapping for %d channels.\n", avc->channels); + return AVERROR(EINVAL); + } + nb_streams = 1; + nb_coupled = avc->channels > 1; + mapping = mapping_arr; + } + + if (avc->channels > 2 && avc->channels <= 8) { + const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; + int ch; + + /* Remap channels from vorbis order to ffmpeg order */ + for (ch = 0; ch < avc->channels; ch++) + mapping_arr[ch] = mapping[vorbis_offset[ch]]; + mapping = mapping_arr; + } + + opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, + nb_streams, nb_coupled, + mapping, &ret); + if (!opus->dec) { + av_log(avc, AV_LOG_ERROR, "Unable to create decoder: %s\n", + opus_strerror(ret)); + return ff_opus_error_to_averror(ret); + } + +#ifdef OPUS_SET_GAIN + ret = opus_multistream_decoder_ctl(opus->dec, OPUS_SET_GAIN(gain_db)); + if (ret != OPUS_OK) + av_log(avc, AV_LOG_WARNING, "Failed to set gain: %s\n", + opus_strerror(ret)); +#else + { + double gain_lin = pow(10, gain_db / (20.0 * 256)); + if (avc->sample_fmt == AV_SAMPLE_FMT_FLT) + opus->gain.d = gain_lin; + else + opus->gain.i = FFMIN(gain_lin * 65536, INT_MAX); + } +#endif + + avc->internal->skip_samples = opus->pre_skip; + avc->delay = 3840; /* Decoder delay (in samples) at 48kHz */ + + return 0; +} + +static av_cold int libopus_decode_close(AVCodecContext *avc) +{ + struct libopus_context *opus = avc->priv_data; + + opus_multistream_decoder_destroy(opus->dec); + return 0; +} + +#define MAX_FRAME_SIZE (960 * 6) + +static int libopus_decode(AVCodecContext *avc, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + struct libopus_context *opus = avc->priv_data; + AVFrame *frame = data; + int ret, nb_samples; + + frame->nb_samples = MAX_FRAME_SIZE; + if ((ret = ff_get_buffer(avc, frame, 0)) < 0) + return ret; + + if (avc->sample_fmt == AV_SAMPLE_FMT_S16) + nb_samples = opus_multistream_decode(opus->dec, pkt->data, pkt->size, + (opus_int16 *)frame->data[0], + frame->nb_samples, 0); + else + nb_samples = opus_multistream_decode_float(opus->dec, pkt->data, pkt->size, + (float *)frame->data[0], + frame->nb_samples, 0); + + if (nb_samples < 0) { + av_log(avc, AV_LOG_ERROR, "Decoding error: %s\n", + opus_strerror(nb_samples)); + return ff_opus_error_to_averror(nb_samples); + } + +#ifndef OPUS_SET_GAIN + { + int i = avc->channels * nb_samples; + if (avc->sample_fmt == AV_SAMPLE_FMT_FLT) { + float *pcm = (float *)frame->data[0]; + for (; i > 0; i--, pcm++) + *pcm = av_clipf(*pcm * opus->gain.d, -1, 1); + } else { + int16_t *pcm = (int16_t *)frame->data[0]; + for (; i > 0; i--, pcm++) + *pcm = av_clip_int16(((int64_t)opus->gain.i * *pcm) >> 16); + } + } +#endif + + frame->nb_samples = nb_samples; + *got_frame_ptr = 1; + + return pkt->size; +} + +static void libopus_flush(AVCodecContext *avc) +{ + struct libopus_context *opus = avc->priv_data; + + opus_multistream_decoder_ctl(opus->dec, OPUS_RESET_STATE); + /* The stream can have been extracted by a tool that is not Opus-aware. + Therefore, any packet can become the first of the stream. */ + avc->internal->skip_samples = opus->pre_skip; +} + +AVCodec ff_libopus_decoder = { + .name = "libopus", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_OPUS, + .priv_data_size = sizeof(struct libopus_context), + .init = libopus_decode_init, + .close = libopus_decode_close, + .decode = libopus_decode, + .flush = libopus_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/libopusenc.c b/ffmpeg/libavcodec/libopusenc.c new file mode 100644 index 0000000..04c297d --- /dev/null +++ b/ffmpeg/libavcodec/libopusenc.c @@ -0,0 +1,426 @@ +/* + * Opus encoder using libopus + * Copyright (c) 2012 Nathan Caldwell + * + * 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 + +#include "libavutil/opt.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "libopus.h" +#include "vorbis.h" +#include "audio_frame_queue.h" + +typedef struct LibopusEncOpts { + int vbr; + int application; + int packet_loss; + int complexity; + float frame_duration; + int packet_size; + int max_bandwidth; +} LibopusEncOpts; + +typedef struct LibopusEncContext { + AVClass *class; + OpusMSEncoder *enc; + int stream_count; + uint8_t *samples; + LibopusEncOpts opts; + AudioFrameQueue afq; +} LibopusEncContext; + +static const uint8_t opus_coupled_streams[8] = { + 0, 1, 1, 2, 2, 2, 2, 3 +}; + +/* Opus internal to Vorbis channel order mapping written in the header */ +static const uint8_t opus_vorbis_channel_map[8][8] = { + { 0 }, + { 0, 1 }, + { 0, 2, 1 }, + { 0, 1, 2, 3 }, + { 0, 4, 1, 2, 3 }, + { 0, 4, 1, 2, 3, 5 }, + { 0, 4, 1, 2, 3, 5, 6 }, + { 0, 6, 1, 2, 3, 4, 5, 7 }, +}; + +/* libavcodec to libopus channel order mapping, passed to libopus */ +static const uint8_t libavcodec_libopus_channel_map[8][8] = { + { 0 }, + { 0, 1 }, + { 0, 1, 2 }, + { 0, 1, 2, 3 }, + { 0, 1, 3, 4, 2 }, + { 0, 1, 4, 5, 2, 3 }, + { 0, 1, 5, 6, 2, 4, 3 }, + { 0, 1, 6, 7, 4, 5, 2, 3 }, +}; + +static void libopus_write_header(AVCodecContext *avctx, int stream_count, + int coupled_stream_count, + const uint8_t *channel_mapping) +{ + uint8_t *p = avctx->extradata; + int channels = avctx->channels; + + bytestream_put_buffer(&p, "OpusHead", 8); + bytestream_put_byte(&p, 1); /* Version */ + bytestream_put_byte(&p, channels); + bytestream_put_le16(&p, avctx->delay); /* Lookahead samples at 48kHz */ + bytestream_put_le32(&p, avctx->sample_rate); /* Original sample rate */ + bytestream_put_le16(&p, 0); /* Gain of 0dB is recommended. */ + + /* Channel mapping */ + if (channels > 2) { + bytestream_put_byte(&p, channels <= 8 ? 1 : 255); + bytestream_put_byte(&p, stream_count); + bytestream_put_byte(&p, coupled_stream_count); + bytestream_put_buffer(&p, channel_mapping, channels); + } else { + bytestream_put_byte(&p, 0); + } +} + +static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc, + LibopusEncOpts *opts) +{ + int ret; + + if (avctx->global_quality) { + av_log(avctx, AV_LOG_ERROR, + "Quality-based encoding not supported, " + "please specify a bitrate and VBR setting.\n"); + return AVERROR(EINVAL); + } + + ret = opus_multistream_encoder_ctl(enc, OPUS_SET_BITRATE(avctx->bit_rate)); + if (ret != OPUS_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to set bitrate: %s\n", opus_strerror(ret)); + return ret; + } + + ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_COMPLEXITY(opts->complexity)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set complexity: %s\n", opus_strerror(ret)); + + ret = opus_multistream_encoder_ctl(enc, OPUS_SET_VBR(!!opts->vbr)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set VBR: %s\n", opus_strerror(ret)); + + ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_VBR_CONSTRAINT(opts->vbr == 2)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set constrained VBR: %s\n", opus_strerror(ret)); + + ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_PACKET_LOSS_PERC(opts->packet_loss)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set expected packet loss percentage: %s\n", + opus_strerror(ret)); + + if (avctx->cutoff) { + ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_MAX_BANDWIDTH(opts->max_bandwidth)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to set maximum bandwidth: %s\n", opus_strerror(ret)); + } + + return OPUS_OK; +} + +static int av_cold libopus_encode_init(AVCodecContext *avctx) +{ + LibopusEncContext *opus = avctx->priv_data; + const uint8_t *channel_mapping; + OpusMSEncoder *enc; + int ret = OPUS_OK; + int coupled_stream_count, header_size, frame_size; + + coupled_stream_count = opus_coupled_streams[avctx->channels - 1]; + opus->stream_count = avctx->channels - coupled_stream_count; + channel_mapping = libavcodec_libopus_channel_map[avctx->channels - 1]; + + /* FIXME: Opus can handle up to 255 channels. However, the mapping for + * anything greater than 8 is undefined. */ + if (avctx->channels > 8) + av_log(avctx, AV_LOG_WARNING, + "Channel layout undefined for %d channels.\n", avctx->channels); + + if (!avctx->bit_rate) { + /* Sane default copied from opusenc */ + avctx->bit_rate = 64000 * opus->stream_count + + 32000 * coupled_stream_count; + av_log(avctx, AV_LOG_WARNING, + "No bit rate set. Defaulting to %d bps.\n", avctx->bit_rate); + } + + if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "The bit rate %d bps is unsupported. " + "Please choose a value between 500 and %d.\n", avctx->bit_rate, + 256000 * avctx->channels); + return AVERROR(EINVAL); + } + + frame_size = opus->opts.frame_duration * 48000 / 1000; + switch (frame_size) { + case 120: + case 240: + if (opus->opts.application != OPUS_APPLICATION_RESTRICTED_LOWDELAY) + av_log(avctx, AV_LOG_WARNING, + "LPC mode cannot be used with a frame duration of less " + "than 10ms. Enabling restricted low-delay mode.\n" + "Use a longer frame duration if this is not what you want.\n"); + /* Frame sizes less than 10 ms can only use MDCT mode, so switching to + * RESTRICTED_LOWDELAY avoids an unnecessary extra 2.5ms lookahead. */ + opus->opts.application = OPUS_APPLICATION_RESTRICTED_LOWDELAY; + case 480: + case 960: + case 1920: + case 2880: + opus->opts.packet_size = + avctx->frame_size = frame_size * avctx->sample_rate / 48000; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid frame duration: %g.\n" + "Frame duration must be exactly one of: 2.5, 5, 10, 20, 40 or 60.\n", + opus->opts.frame_duration); + return AVERROR(EINVAL); + } + + if (avctx->compression_level < 0 || avctx->compression_level > 10) { + av_log(avctx, AV_LOG_WARNING, + "Compression level must be in the range 0 to 10. " + "Defaulting to 10.\n"); + opus->opts.complexity = 10; + } else { + opus->opts.complexity = avctx->compression_level; + } + + if (avctx->cutoff) { + switch (avctx->cutoff) { + case 4000: + opus->opts.max_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + break; + case 6000: + opus->opts.max_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + break; + case 8000: + opus->opts.max_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + break; + case 12000: + opus->opts.max_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + break; + case 20000: + opus->opts.max_bandwidth = OPUS_BANDWIDTH_FULLBAND; + break; + default: + av_log(avctx, AV_LOG_WARNING, + "Invalid frequency cutoff: %d. Using default maximum bandwidth.\n" + "Cutoff frequency must be exactly one of: 4000, 6000, 8000, 12000 or 20000.\n", + avctx->cutoff); + avctx->cutoff = 0; + } + } + + enc = opus_multistream_encoder_create(avctx->sample_rate, avctx->channels, + opus->stream_count, + coupled_stream_count, + channel_mapping, + opus->opts.application, &ret); + if (ret != OPUS_OK) { + av_log(avctx, AV_LOG_ERROR, + "Failed to create encoder: %s\n", opus_strerror(ret)); + return ff_opus_error_to_averror(ret); + } + + ret = libopus_configure_encoder(avctx, enc, &opus->opts); + if (ret != OPUS_OK) { + ret = ff_opus_error_to_averror(ret); + goto fail; + } + + header_size = 19 + (avctx->channels > 2 ? 2 + avctx->channels : 0); + avctx->extradata = av_malloc(header_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate extradata.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + avctx->extradata_size = header_size; + + opus->samples = av_mallocz(frame_size * avctx->channels * + av_get_bytes_per_sample(avctx->sample_fmt)); + if (!opus->samples) { + av_log(avctx, AV_LOG_ERROR, "Failed to allocate samples buffer.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = opus_multistream_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&avctx->delay)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, + "Unable to get number of lookahead samples: %s\n", + opus_strerror(ret)); + + libopus_write_header(avctx, opus->stream_count, coupled_stream_count, + opus_vorbis_channel_map[avctx->channels - 1]); + + ff_af_queue_init(avctx, &opus->afq); + + opus->enc = enc; + + return 0; + +fail: + opus_multistream_encoder_destroy(enc); + av_freep(&avctx->extradata); + return ret; +} + +static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + LibopusEncContext *opus = avctx->priv_data; + const int sample_size = avctx->channels * + av_get_bytes_per_sample(avctx->sample_fmt); + uint8_t *audio; + int ret; + + if (frame) { + ff_af_queue_add(&opus->afq, frame); + if (frame->nb_samples < opus->opts.packet_size) { + audio = opus->samples; + memcpy(audio, frame->data[0], frame->nb_samples * sample_size); + } else + audio = frame->data[0]; + } else { + if (!opus->afq.remaining_samples) + return 0; + audio = opus->samples; + memset(audio, 0, opus->opts.packet_size * sample_size); + } + + /* Maximum packet size taken from opusenc in opus-tools. 60ms packets + * consist of 3 frames in one packet. The maximum frame size is 1275 + * bytes along with the largest possible packet header of 7 bytes. */ + if ((ret = ff_alloc_packet2(avctx, avpkt, (1275 * 3 + 7) * opus->stream_count)) < 0) + return ret; + + if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) + ret = opus_multistream_encode_float(opus->enc, (float *)audio, + opus->opts.packet_size, + avpkt->data, avpkt->size); + else + ret = opus_multistream_encode(opus->enc, (opus_int16 *)audio, + opus->opts.packet_size, + avpkt->data, avpkt->size); + + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error encoding frame: %s\n", opus_strerror(ret)); + return ff_opus_error_to_averror(ret); + } + + av_shrink_packet(avpkt, ret); + + ff_af_queue_remove(&opus->afq, opus->opts.packet_size, + &avpkt->pts, &avpkt->duration); + + *got_packet_ptr = 1; + + return 0; +} + +static int av_cold libopus_encode_close(AVCodecContext *avctx) +{ + LibopusEncContext *opus = avctx->priv_data; + + opus_multistream_encoder_destroy(opus->enc); + + ff_af_queue_close(&opus->afq); + + av_freep(&opus->samples); + av_freep(&avctx->extradata); + + return 0; +} + +#define OFFSET(x) offsetof(LibopusEncContext, opts.x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption libopus_options[] = { + { "application", "Intended application type", OFFSET(application), AV_OPT_TYPE_INT, { .i64 = OPUS_APPLICATION_AUDIO }, OPUS_APPLICATION_VOIP, OPUS_APPLICATION_RESTRICTED_LOWDELAY, FLAGS, "application" }, + { "voip", "Favor improved speech intelligibility", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_VOIP }, 0, 0, FLAGS, "application" }, + { "audio", "Favor faithfulness to the input", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_AUDIO }, 0, 0, FLAGS, "application" }, + { "lowdelay", "Restrict to only the lowest delay modes", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_RESTRICTED_LOWDELAY }, 0, 0, FLAGS, "application" }, + { "frame_duration", "Duration of a frame in milliseconds", OFFSET(frame_duration), AV_OPT_TYPE_FLOAT, { .dbl = 10.0 }, 2.5, 60.0, FLAGS }, + { "packet_loss", "Expected packet loss percentage", OFFSET(packet_loss), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, FLAGS }, + { "vbr", "Variable bit rate mode", OFFSET(vbr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 2, FLAGS, "vbr" }, + { "off", "Use constant bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "vbr" }, + { "on", "Use variable bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "vbr" }, + { "constrained", "Use constrained VBR", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "vbr" }, + { NULL }, +}; + +static const AVClass libopus_class = { + .class_name = "libopus", + .item_name = av_default_item_name, + .option = libopus_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault libopus_defaults[] = { + { "b", "0" }, + { "compression_level", "10" }, + { NULL }, +}; + +static const int libopus_sample_rates[] = { + 48000, 24000, 16000, 12000, 8000, 0, +}; + +AVCodec ff_libopus_encoder = { + .name = "libopus", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_OPUS, + .priv_data_size = sizeof(LibopusEncContext), + .init = libopus_encode_init, + .encode2 = libopus_encode, + .close = libopus_encode_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, + .channel_layouts = ff_vorbis_channel_layouts, + .supported_samplerates = libopus_sample_rates, + .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), + .priv_class = &libopus_class, + .defaults = libopus_defaults, +}; diff --git a/ffmpeg/libavcodec/libschroedinger.c b/ffmpeg/libavcodec/libschroedinger.c new file mode 100644 index 0000000..f452d70 --- /dev/null +++ b/ffmpeg/libavcodec/libschroedinger.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2008 BBC, Anuradha Suraparaju + * + * 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 + */ + +/** +* @file +* function definitions common to libschroedinger decoder and encoder +*/ + +#include "libschroedinger.h" +#include "libavutil/mem.h" + +static const SchroVideoFormatInfo ff_schro_video_format_info[] = { + { 640, 480, 24000, 1001}, + { 176, 120, 15000, 1001}, + { 176, 144, 25, 2 }, + { 352, 240, 15000, 1001}, + { 352, 288, 25, 2 }, + { 704, 480, 15000, 1001}, + { 704, 576, 25, 2 }, + { 720, 480, 30000, 1001}, + { 720, 576, 25, 1 }, + { 1280, 720, 60000, 1001}, + { 1280, 720, 50, 1 }, + { 1920, 1080, 30000, 1001}, + { 1920, 1080, 25, 1 }, + { 1920, 1080, 60000, 1001}, + { 1920, 1080, 50, 1 }, + { 2048, 1080, 24, 1 }, + { 4096, 2160, 24, 1 }, +}; + +static unsigned int get_video_format_idx(AVCodecContext *avctx) +{ + unsigned int ret_idx = 0; + unsigned int idx; + unsigned int num_formats = sizeof(ff_schro_video_format_info) / + sizeof(ff_schro_video_format_info[0]); + + for (idx = 1; idx < num_formats; ++idx) { + const SchroVideoFormatInfo *vf = &ff_schro_video_format_info[idx]; + if (avctx->width == vf->width && + avctx->height == vf->height) { + ret_idx = idx; + if (avctx->time_base.den == vf->frame_rate_num && + avctx->time_base.num == vf->frame_rate_denom) + return idx; + } + } + return ret_idx; +} + +void ff_schro_queue_init(FFSchroQueue *queue) +{ + queue->p_head = queue->p_tail = NULL; + queue->size = 0; +} + +void ff_schro_queue_free(FFSchroQueue *queue, void (*free_func)(void *)) +{ + while (queue->p_head) + free_func(ff_schro_queue_pop(queue)); +} + +int ff_schro_queue_push_back(FFSchroQueue *queue, void *p_data) +{ + FFSchroQueueElement *p_new = av_mallocz(sizeof(FFSchroQueueElement)); + + if (!p_new) + return -1; + + p_new->data = p_data; + + if (!queue->p_head) + queue->p_head = p_new; + else + queue->p_tail->next = p_new; + queue->p_tail = p_new; + + ++queue->size; + return 0; +} + +void *ff_schro_queue_pop(FFSchroQueue *queue) +{ + FFSchroQueueElement *top = queue->p_head; + + if (top) { + void *data = top->data; + queue->p_head = queue->p_head->next; + --queue->size; + av_freep(&top); + return data; + } + + return NULL; +} + +/** +* Schroedinger video preset table. Ensure that this tables matches up correctly +* with the ff_schro_video_format_info table. +*/ +static const SchroVideoFormatEnum ff_schro_video_formats[]={ + SCHRO_VIDEO_FORMAT_CUSTOM , + SCHRO_VIDEO_FORMAT_QSIF , + SCHRO_VIDEO_FORMAT_QCIF , + SCHRO_VIDEO_FORMAT_SIF , + SCHRO_VIDEO_FORMAT_CIF , + SCHRO_VIDEO_FORMAT_4SIF , + SCHRO_VIDEO_FORMAT_4CIF , + SCHRO_VIDEO_FORMAT_SD480I_60 , + SCHRO_VIDEO_FORMAT_SD576I_50 , + SCHRO_VIDEO_FORMAT_HD720P_60 , + SCHRO_VIDEO_FORMAT_HD720P_50 , + SCHRO_VIDEO_FORMAT_HD1080I_60 , + SCHRO_VIDEO_FORMAT_HD1080I_50 , + SCHRO_VIDEO_FORMAT_HD1080P_60 , + SCHRO_VIDEO_FORMAT_HD1080P_50 , + SCHRO_VIDEO_FORMAT_DC2K_24 , + SCHRO_VIDEO_FORMAT_DC4K_24 , +}; + +SchroVideoFormatEnum ff_get_schro_video_format_preset(AVCodecContext *avctx) +{ + unsigned int num_formats = sizeof(ff_schro_video_formats) / + sizeof(ff_schro_video_formats[0]); + + unsigned int idx = get_video_format_idx(avctx); + + return (idx < num_formats) ? ff_schro_video_formats[idx] : + SCHRO_VIDEO_FORMAT_CUSTOM; +} + +int ff_get_schro_frame_format (SchroChromaFormat schro_pix_fmt, + SchroFrameFormat *schro_frame_fmt) +{ + unsigned int num_formats = sizeof(schro_pixel_format_map) / + sizeof(schro_pixel_format_map[0]); + + int idx; + + for (idx = 0; idx < num_formats; ++idx) { + if (schro_pixel_format_map[idx].schro_pix_fmt == schro_pix_fmt) { + *schro_frame_fmt = schro_pixel_format_map[idx].schro_frame_fmt; + return 0; + } + } + return -1; +} + +static void free_schro_frame(SchroFrame *frame, void *priv) +{ + AVPicture *p_pic = priv; + + if (!p_pic) + return; + + avpicture_free(p_pic); + av_freep(&p_pic); +} + +SchroFrame *ff_create_schro_frame(AVCodecContext *avctx, + SchroFrameFormat schro_frame_fmt) +{ + AVPicture *p_pic; + SchroFrame *p_frame; + int y_width, uv_width; + int y_height, uv_height; + int i; + + y_width = avctx->width; + y_height = avctx->height; + uv_width = y_width >> (SCHRO_FRAME_FORMAT_H_SHIFT(schro_frame_fmt)); + uv_height = y_height >> (SCHRO_FRAME_FORMAT_V_SHIFT(schro_frame_fmt)); + + p_pic = av_mallocz(sizeof(AVPicture)); + if (!p_pic || avpicture_alloc(p_pic, avctx->pix_fmt, y_width, y_height) < 0) { + av_free(p_pic); + return NULL; + } + + p_frame = schro_frame_new(); + p_frame->format = schro_frame_fmt; + p_frame->width = y_width; + p_frame->height = y_height; + schro_frame_set_free_callback(p_frame, free_schro_frame, (void *)p_pic); + + for (i = 0; i < 3; ++i) { + p_frame->components[i].width = i ? uv_width : y_width; + p_frame->components[i].stride = p_pic->linesize[i]; + p_frame->components[i].height = i ? uv_height : y_height; + p_frame->components[i].length = + p_frame->components[i].stride * p_frame->components[i].height; + p_frame->components[i].data = p_pic->data[i]; + + if (i) { + p_frame->components[i].v_shift = + SCHRO_FRAME_FORMAT_V_SHIFT(p_frame->format); + p_frame->components[i].h_shift = + SCHRO_FRAME_FORMAT_H_SHIFT(p_frame->format); + } + } + + return p_frame; +} diff --git a/ffmpeg/libavcodec/libschroedinger.h b/ffmpeg/libavcodec/libschroedinger.h new file mode 100644 index 0000000..12fe57c --- /dev/null +++ b/ffmpeg/libavcodec/libschroedinger.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2008 BBC, Anuradha Suraparaju + * + * 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 + */ + +/** +* @file +* data structures common to libschroedinger decoder and encoder +*/ + +#ifndef AVCODEC_LIBSCHROEDINGER_H +#define AVCODEC_LIBSCHROEDINGER_H + +#include +#include + +#include "avcodec.h" + +typedef struct SchroVideoFormatInfo { + uint16_t width; + uint16_t height; + uint16_t frame_rate_num; + uint16_t frame_rate_denom; +} SchroVideoFormatInfo; + +/** +* contains a single encoded frame returned from Dirac or Schroedinger +*/ +typedef struct FFSchroEncodedFrame { + /** encoded frame data */ + uint8_t *p_encbuf; + + /** encoded frame size */ + uint32_t size; + + /** encoded frame number. Will be used as pts */ + uint32_t frame_num; + + /** key frame flag. 1 : is key frame , 0 : in not key frame */ + uint16_t key_frame; +} FFSchroEncodedFrame; + +/** +* queue element +*/ +typedef struct FFSchroQueueElement { + /** Data to be stored in queue*/ + void *data; + /** Pointer to next element queue */ + struct FFSchroQueueElement *next; +} FFSchroQueueElement; + + +/** +* A simple queue implementation used in libschroedinger +*/ +typedef struct FFSchroQueue { + /** Pointer to head of queue */ + FFSchroQueueElement *p_head; + /** Pointer to tail of queue */ + FFSchroQueueElement *p_tail; + /** Queue size*/ + int size; +} FFSchroQueue; + +/** +* Initialise the queue +*/ +void ff_schro_queue_init(FFSchroQueue *queue); + +/** +* Add an element to the end of the queue +*/ +int ff_schro_queue_push_back(FFSchroQueue *queue, void *p_data); + +/** +* Return the first element in the queue +*/ +void *ff_schro_queue_pop(FFSchroQueue *queue); + +/** +* Free the queue resources. free_func is a function supplied by the caller to +* free any resources allocated by the caller. The data field of the queue +* element is passed to it. +*/ +void ff_schro_queue_free(FFSchroQueue *queue, void (*free_func)(void *)); + +static const struct { + enum AVPixelFormat ff_pix_fmt; + SchroChromaFormat schro_pix_fmt; + SchroFrameFormat schro_frame_fmt; +} schro_pixel_format_map[] = { + { AV_PIX_FMT_YUV420P, SCHRO_CHROMA_420, SCHRO_FRAME_FORMAT_U8_420 }, + { AV_PIX_FMT_YUV422P, SCHRO_CHROMA_422, SCHRO_FRAME_FORMAT_U8_422 }, + { AV_PIX_FMT_YUV444P, SCHRO_CHROMA_444, SCHRO_FRAME_FORMAT_U8_444 }, +}; + +/** +* Returns the video format preset matching the input video dimensions and +* time base. +*/ +SchroVideoFormatEnum ff_get_schro_video_format_preset (AVCodecContext *avctx); + +/** +* Sets the Schroedinger frame format corresponding to the Schro chroma format +* passed. Returns 0 on success, -1 on failure. +*/ +int ff_get_schro_frame_format(SchroChromaFormat schro_chroma_fmt, + SchroFrameFormat *schro_frame_fmt); + +/** +* Create a Schro frame based on the dimensions and frame format +* passed. Returns a pointer to a frame on success, NULL on failure. +*/ +SchroFrame *ff_create_schro_frame(AVCodecContext *avctx, + SchroFrameFormat schro_frame_fmt); + +#endif /* AVCODEC_LIBSCHROEDINGER_H */ diff --git a/ffmpeg/libavcodec/libschroedingerdec.c b/ffmpeg/libavcodec/libschroedingerdec.c new file mode 100644 index 0000000..2e0ce5d --- /dev/null +++ b/ffmpeg/libavcodec/libschroedingerdec.c @@ -0,0 +1,386 @@ +/* + * Dirac decoder support via Schroedinger libraries + * Copyright (c) 2008 BBC, Anuradha Suraparaju + * + * 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 + */ + +/** +* @file +* Dirac decoder support via libschroedinger-1.0 libraries. More details about +* the Schroedinger project can be found at http://www.diracvideo.org/. +* The library implements Dirac Specification Version 2.2. +* (http://dirac.sourceforge.net/specification.html). +*/ + +#include + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "avcodec.h" +#include "internal.h" +#include "libschroedinger.h" + +#include +#include +#include + +/** SchroFrame and Pts relation */ +typedef struct LibSchroFrameContext { + SchroFrame *frame; + int64_t pts; +} LibSchroFrameContext; + +/** libschroedinger decoder private data */ +typedef struct SchroDecoderParams { + /** Schroedinger video format */ + SchroVideoFormat *format; + + /** Schroedinger frame format */ + SchroFrameFormat frame_format; + + /** decoder handle */ + SchroDecoder* decoder; + + /** queue storing decoded frames */ + FFSchroQueue dec_frame_queue; + + /** end of sequence signalled */ + int eos_signalled; + + /** end of sequence pulled */ + int eos_pulled; +} SchroDecoderParams; + +typedef struct SchroParseUnitContext { + const uint8_t *buf; + int buf_size; +} SchroParseUnitContext; + + +static void libschroedinger_decode_buffer_free(SchroBuffer *schro_buf, + void *priv) +{ + av_freep(&priv); +} + +static void parse_context_init(SchroParseUnitContext *parse_ctx, + const uint8_t *buf, int buf_size) +{ + parse_ctx->buf = buf; + parse_ctx->buf_size = buf_size; +} + +static SchroBuffer *find_next_parse_unit(SchroParseUnitContext *parse_ctx) +{ + SchroBuffer *enc_buf = NULL; + int next_pu_offset = 0; + unsigned char *in_buf; + + if (parse_ctx->buf_size < 13 || + parse_ctx->buf[0] != 'B' || + parse_ctx->buf[1] != 'B' || + parse_ctx->buf[2] != 'C' || + parse_ctx->buf[3] != 'D') + return NULL; + + next_pu_offset = (parse_ctx->buf[5] << 24) + + (parse_ctx->buf[6] << 16) + + (parse_ctx->buf[7] << 8) + + parse_ctx->buf[8]; + + if (next_pu_offset == 0 && + SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_ctx->buf[4])) + next_pu_offset = 13; + + if (next_pu_offset <= 0 || parse_ctx->buf_size < next_pu_offset) + return NULL; + + in_buf = av_malloc(next_pu_offset); + if (!in_buf) { + av_log(parse_ctx, AV_LOG_ERROR, "Unable to allocate input buffer\n"); + return NULL; + } + + memcpy(in_buf, parse_ctx->buf, next_pu_offset); + enc_buf = schro_buffer_new_with_data(in_buf, next_pu_offset); + enc_buf->free = libschroedinger_decode_buffer_free; + enc_buf->priv = in_buf; + + parse_ctx->buf += next_pu_offset; + parse_ctx->buf_size -= next_pu_offset; + + return enc_buf; +} + +/** +* Returns FFmpeg chroma format. +*/ +static enum AVPixelFormat get_chroma_format(SchroChromaFormat schro_pix_fmt) +{ + int num_formats = sizeof(schro_pixel_format_map) / + sizeof(schro_pixel_format_map[0]); + int idx; + + for (idx = 0; idx < num_formats; ++idx) + if (schro_pixel_format_map[idx].schro_pix_fmt == schro_pix_fmt) + return schro_pixel_format_map[idx].ff_pix_fmt; + return AV_PIX_FMT_NONE; +} + +static av_cold int libschroedinger_decode_init(AVCodecContext *avctx) +{ + + SchroDecoderParams *p_schro_params = avctx->priv_data; + /* First of all, initialize our supporting libraries. */ + schro_init(); + + schro_debug_set_level(avctx->debug); + p_schro_params->decoder = schro_decoder_new(); + schro_decoder_set_skip_ratio(p_schro_params->decoder, 1); + + if (!p_schro_params->decoder) + return -1; + + /* Initialize the decoded frame queue. */ + ff_schro_queue_init(&p_schro_params->dec_frame_queue); + return 0; +} + +static void libschroedinger_decode_frame_free(void *frame) +{ + schro_frame_unref(frame); +} + +static void libschroedinger_handle_first_access_unit(AVCodecContext *avctx) +{ + SchroDecoderParams *p_schro_params = avctx->priv_data; + SchroDecoder *decoder = p_schro_params->decoder; + + p_schro_params->format = schro_decoder_get_video_format(decoder); + + /* Tell FFmpeg about sequence details. */ + if (av_image_check_size(p_schro_params->format->width, + p_schro_params->format->height, 0, avctx) < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid dimensions (%dx%d)\n", + p_schro_params->format->width, p_schro_params->format->height); + avctx->height = avctx->width = 0; + return; + } + avctx->height = p_schro_params->format->height; + avctx->width = p_schro_params->format->width; + avctx->pix_fmt = get_chroma_format(p_schro_params->format->chroma_format); + + if (ff_get_schro_frame_format(p_schro_params->format->chroma_format, + &p_schro_params->frame_format) == -1) { + av_log(avctx, AV_LOG_ERROR, + "This codec currently only supports planar YUV 4:2:0, 4:2:2 " + "and 4:4:4 formats.\n"); + return; + } + + avctx->time_base.den = p_schro_params->format->frame_rate_numerator; + avctx->time_base.num = p_schro_params->format->frame_rate_denominator; +} + +static int libschroedinger_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int64_t pts = avpkt->pts; + SchroTag *tag; + + SchroDecoderParams *p_schro_params = avctx->priv_data; + SchroDecoder *decoder = p_schro_params->decoder; + SchroBuffer *enc_buf; + SchroFrame* frame; + AVFrame *avframe = data; + int state; + int go = 1; + int outer = 1; + SchroParseUnitContext parse_ctx; + LibSchroFrameContext *framewithpts = NULL; + + *got_frame = 0; + + parse_context_init(&parse_ctx, buf, buf_size); + if (!buf_size) { + if (!p_schro_params->eos_signalled) { + state = schro_decoder_push_end_of_stream(decoder); + p_schro_params->eos_signalled = 1; + } + } + + /* Loop through all the individual parse units in the input buffer */ + do { + if ((enc_buf = find_next_parse_unit(&parse_ctx))) { + /* Set Schrotag with the pts to be recovered after decoding*/ + enc_buf->tag = schro_tag_new(av_malloc(sizeof(int64_t)), av_free); + if (!enc_buf->tag->value) { + av_log(avctx, AV_LOG_ERROR, "Unable to allocate SchroTag\n"); + return AVERROR(ENOMEM); + } + AV_WN(64, enc_buf->tag->value, pts); + /* Push buffer into decoder. */ + if (SCHRO_PARSE_CODE_IS_PICTURE(enc_buf->data[4]) && + SCHRO_PARSE_CODE_NUM_REFS(enc_buf->data[4]) > 0) + avctx->has_b_frames = 1; + state = schro_decoder_push(decoder, enc_buf); + if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) + libschroedinger_handle_first_access_unit(avctx); + go = 1; + } else + outer = 0; + + while (go) { + /* Parse data and process result. */ + state = schro_decoder_wait(decoder); + switch (state) { + case SCHRO_DECODER_FIRST_ACCESS_UNIT: + libschroedinger_handle_first_access_unit(avctx); + break; + + case SCHRO_DECODER_NEED_BITS: + /* Need more input data - stop iterating over what we have. */ + go = 0; + break; + + case SCHRO_DECODER_NEED_FRAME: + /* Decoder needs a frame - create one and push it in. */ + frame = ff_create_schro_frame(avctx, + p_schro_params->frame_format); + schro_decoder_add_output_picture(decoder, frame); + break; + + case SCHRO_DECODER_OK: + /* Pull a frame out of the decoder. */ + tag = schro_decoder_get_picture_tag(decoder); + frame = schro_decoder_pull(decoder); + + if (frame) { + /* Add relation between schroframe and pts. */ + framewithpts = av_malloc(sizeof(LibSchroFrameContext)); + if (!framewithpts) { + av_log(avctx, AV_LOG_ERROR, "Unable to allocate FrameWithPts\n"); + return AVERROR(ENOMEM); + } + framewithpts->frame = frame; + framewithpts->pts = AV_RN64(tag->value); + ff_schro_queue_push_back(&p_schro_params->dec_frame_queue, + framewithpts); + } + break; + case SCHRO_DECODER_EOS: + go = 0; + p_schro_params->eos_pulled = 1; + schro_decoder_reset(decoder); + outer = 0; + break; + + case SCHRO_DECODER_ERROR: + return -1; + break; + } + } + } while (outer); + + /* Grab next frame to be returned from the top of the queue. */ + framewithpts = ff_schro_queue_pop(&p_schro_params->dec_frame_queue); + + if (framewithpts && framewithpts->frame) { + int ret; + + if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0) + return ret; + + memcpy(avframe->data[0], + framewithpts->frame->components[0].data, + framewithpts->frame->components[0].length); + + memcpy(avframe->data[1], + framewithpts->frame->components[1].data, + framewithpts->frame->components[1].length); + + memcpy(avframe->data[2], + framewithpts->frame->components[2].data, + framewithpts->frame->components[2].length); + + /* Fill frame with current buffer data from Schroedinger. */ + avframe->pkt_pts = framewithpts->pts; + avframe->linesize[0] = framewithpts->frame->components[0].stride; + avframe->linesize[1] = framewithpts->frame->components[1].stride; + avframe->linesize[2] = framewithpts->frame->components[2].stride; + + *got_frame = 1; + + /* Now free the frame resources. */ + libschroedinger_decode_frame_free(framewithpts->frame); + av_free(framewithpts); + } else { + data = NULL; + *got_frame = 0; + } + return buf_size; +} + + +static av_cold int libschroedinger_decode_close(AVCodecContext *avctx) +{ + SchroDecoderParams *p_schro_params = avctx->priv_data; + /* Free the decoder. */ + schro_decoder_free(p_schro_params->decoder); + av_freep(&p_schro_params->format); + + /* Free data in the output frame queue. */ + ff_schro_queue_free(&p_schro_params->dec_frame_queue, + libschroedinger_decode_frame_free); + + return 0; +} + +static void libschroedinger_flush(AVCodecContext *avctx) +{ + /* Got a seek request. Free the decoded frames queue and then reset + * the decoder */ + SchroDecoderParams *p_schro_params = avctx->priv_data; + + /* Free data in the output frame queue. */ + ff_schro_queue_free(&p_schro_params->dec_frame_queue, + libschroedinger_decode_frame_free); + + ff_schro_queue_init(&p_schro_params->dec_frame_queue); + schro_decoder_reset(p_schro_params->decoder); + p_schro_params->eos_pulled = 0; + p_schro_params->eos_signalled = 0; +} + +AVCodec ff_libschroedinger_decoder = { + .name = "libschroedinger", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DIRAC, + .priv_data_size = sizeof(SchroDecoderParams), + .init = libschroedinger_decode_init, + .close = libschroedinger_decode_close, + .decode = libschroedinger_decode_frame, + .capabilities = CODEC_CAP_DELAY, + .flush = libschroedinger_flush, + .long_name = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"), +}; diff --git a/ffmpeg/libavcodec/libschroedingerenc.c b/ffmpeg/libavcodec/libschroedingerenc.c new file mode 100644 index 0000000..297c6c5 --- /dev/null +++ b/ffmpeg/libavcodec/libschroedingerenc.c @@ -0,0 +1,446 @@ +/* + * Dirac encoder support via Schroedinger libraries + * Copyright (c) 2008 BBC, Anuradha Suraparaju + * + * 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 + */ + +/** +* @file +* Dirac encoder support via libschroedinger-1.0 libraries. More details about +* the Schroedinger project can be found at http://www.diracvideo.org/. +* The library implements Dirac Specification Version 2.2 +* (http://dirac.sourceforge.net/specification.html). +*/ + +#include +#include +#include + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +#include "libschroedinger.h" +#include "bytestream.h" + + +/** libschroedinger encoder private data */ +typedef struct SchroEncoderParams { + /** Schroedinger video format */ + SchroVideoFormat *format; + + /** Schroedinger frame format */ + SchroFrameFormat frame_format; + + /** frame being encoded */ + AVFrame picture; + + /** frame size */ + int frame_size; + + /** Schroedinger encoder handle*/ + SchroEncoder* encoder; + + /** buffer to store encoder output before writing it to the frame queue*/ + unsigned char *enc_buf; + + /** Size of encoder buffer*/ + int enc_buf_size; + + /** queue storing encoded frames */ + FFSchroQueue enc_frame_queue; + + /** end of sequence signalled */ + int eos_signalled; + + /** end of sequence pulled */ + int eos_pulled; + + /* counter for frames submitted to encoder, used as dts */ + int64_t dts; +} SchroEncoderParams; + +/** +* Works out Schro-compatible chroma format. +*/ +static int set_chroma_format(AVCodecContext *avctx) +{ + int num_formats = sizeof(schro_pixel_format_map) / + sizeof(schro_pixel_format_map[0]); + int idx; + + SchroEncoderParams *p_schro_params = avctx->priv_data; + + for (idx = 0; idx < num_formats; ++idx) { + if (schro_pixel_format_map[idx].ff_pix_fmt == avctx->pix_fmt) { + p_schro_params->format->chroma_format = + schro_pixel_format_map[idx].schro_pix_fmt; + return 0; + } + } + + av_log(avctx, AV_LOG_ERROR, + "This codec currently only supports planar YUV 4:2:0, 4:2:2" + " and 4:4:4 formats.\n"); + + return -1; +} + +static int libschroedinger_encode_init(AVCodecContext *avctx) +{ + SchroEncoderParams *p_schro_params = avctx->priv_data; + SchroVideoFormatEnum preset; + + /* Initialize the libraries that libschroedinger depends on. */ + schro_init(); + + /* Create an encoder object. */ + p_schro_params->encoder = schro_encoder_new(); + + if (!p_schro_params->encoder) { + av_log(avctx, AV_LOG_ERROR, + "Unrecoverable Error: schro_encoder_new failed. "); + return -1; + } + + /* Initialize the format. */ + preset = ff_get_schro_video_format_preset(avctx); + p_schro_params->format = + schro_encoder_get_video_format(p_schro_params->encoder); + schro_video_format_set_std_video_format(p_schro_params->format, preset); + p_schro_params->format->width = avctx->width; + p_schro_params->format->height = avctx->height; + + if (set_chroma_format(avctx) == -1) + return -1; + + if (avctx->color_primaries == AVCOL_PRI_BT709) { + p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_HDTV; + } else if (avctx->color_primaries == AVCOL_PRI_BT470BG) { + p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_SDTV_625; + } else if (avctx->color_primaries == AVCOL_PRI_SMPTE170M) { + p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_SDTV_525; + } + + if (avctx->colorspace == AVCOL_SPC_BT709) { + p_schro_params->format->colour_matrix = SCHRO_COLOUR_MATRIX_HDTV; + } else if (avctx->colorspace == AVCOL_SPC_BT470BG) { + p_schro_params->format->colour_matrix = SCHRO_COLOUR_MATRIX_SDTV; + } + + if (avctx->color_trc == AVCOL_TRC_BT709) { + p_schro_params->format->transfer_function = SCHRO_TRANSFER_CHAR_TV_GAMMA; + } + + if (ff_get_schro_frame_format(p_schro_params->format->chroma_format, + &p_schro_params->frame_format) == -1) { + av_log(avctx, AV_LOG_ERROR, + "This codec currently supports only planar YUV 4:2:0, 4:2:2" + " and 4:4:4 formats.\n"); + return -1; + } + + p_schro_params->format->frame_rate_numerator = avctx->time_base.den; + p_schro_params->format->frame_rate_denominator = avctx->time_base.num; + + p_schro_params->frame_size = avpicture_get_size(avctx->pix_fmt, + avctx->width, + avctx->height); + + avctx->coded_frame = &p_schro_params->picture; + + if (!avctx->gop_size) { + schro_encoder_setting_set_double(p_schro_params->encoder, + "gop_structure", + SCHRO_ENCODER_GOP_INTRA_ONLY); + + if (avctx->coder_type == FF_CODER_TYPE_VLC) + schro_encoder_setting_set_double(p_schro_params->encoder, + "enable_noarith", 1); + } else { + schro_encoder_setting_set_double(p_schro_params->encoder, + "au_distance", avctx->gop_size); + avctx->has_b_frames = 1; + p_schro_params->dts = -1; + } + + /* FIXME - Need to handle SCHRO_ENCODER_RATE_CONTROL_LOW_DELAY. */ + if (avctx->flags & CODEC_FLAG_QSCALE) { + if (!avctx->global_quality) { + /* lossless coding */ + schro_encoder_setting_set_double(p_schro_params->encoder, + "rate_control", + SCHRO_ENCODER_RATE_CONTROL_LOSSLESS); + } else { + int quality; + schro_encoder_setting_set_double(p_schro_params->encoder, + "rate_control", + SCHRO_ENCODER_RATE_CONTROL_CONSTANT_QUALITY); + + quality = avctx->global_quality / FF_QP2LAMBDA; + if (quality > 10) + quality = 10; + schro_encoder_setting_set_double(p_schro_params->encoder, + "quality", quality); + } + } else { + schro_encoder_setting_set_double(p_schro_params->encoder, + "rate_control", + SCHRO_ENCODER_RATE_CONTROL_CONSTANT_BITRATE); + + schro_encoder_setting_set_double(p_schro_params->encoder, + "bitrate", avctx->bit_rate); + } + + if (avctx->flags & CODEC_FLAG_INTERLACED_ME) + /* All material can be coded as interlaced or progressive + irrespective of the type of source material. */ + schro_encoder_setting_set_double(p_schro_params->encoder, + "interlaced_coding", 1); + + schro_encoder_setting_set_double(p_schro_params->encoder, "open_gop", + !(avctx->flags & CODEC_FLAG_CLOSED_GOP)); + + /* FIXME: Signal range hardcoded to 8-bit data until both libschroedinger + * and libdirac support other bit-depth data. */ + schro_video_format_set_std_signal_range(p_schro_params->format, + SCHRO_SIGNAL_RANGE_8BIT_VIDEO); + + /* Set the encoder format. */ + schro_encoder_set_video_format(p_schro_params->encoder, + p_schro_params->format); + + /* Set the debug level. */ + schro_debug_set_level(avctx->debug); + + schro_encoder_start(p_schro_params->encoder); + + /* Initialize the encoded frame queue. */ + ff_schro_queue_init(&p_schro_params->enc_frame_queue); + return 0; +} + +static SchroFrame *libschroedinger_frame_from_data(AVCodecContext *avctx, + const AVFrame *frame) +{ + SchroEncoderParams *p_schro_params = avctx->priv_data; + SchroFrame *in_frame; + /* Input line size may differ from what the codec supports. Especially + * when transcoding from one format to another. So use avpicture_layout + * to copy the frame. */ + in_frame = ff_create_schro_frame(avctx, p_schro_params->frame_format); + + if (in_frame) + avpicture_layout((const AVPicture *)frame, avctx->pix_fmt, + avctx->width, avctx->height, + in_frame->components[0].data, + p_schro_params->frame_size); + + return in_frame; +} + +static void libschroedinger_free_frame(void *data) +{ + FFSchroEncodedFrame *enc_frame = data; + + av_freep(&enc_frame->p_encbuf); + av_free(enc_frame); +} + +static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + int enc_size = 0; + SchroEncoderParams *p_schro_params = avctx->priv_data; + SchroEncoder *encoder = p_schro_params->encoder; + struct FFSchroEncodedFrame *p_frame_output = NULL; + int go = 1; + SchroBuffer *enc_buf; + int presentation_frame; + int parse_code; + int last_frame_in_sequence = 0; + int pkt_size, ret; + + if (!frame) { + /* Push end of sequence if not already signalled. */ + if (!p_schro_params->eos_signalled) { + schro_encoder_end_of_stream(encoder); + p_schro_params->eos_signalled = 1; + } + } else { + /* Allocate frame data to schro input buffer. */ + SchroFrame *in_frame = libschroedinger_frame_from_data(avctx, frame); + /* Load next frame. */ + schro_encoder_push_frame(encoder, in_frame); + } + + if (p_schro_params->eos_pulled) + go = 0; + + /* Now check to see if we have any output from the encoder. */ + while (go) { + SchroStateEnum state; + state = schro_encoder_wait(encoder); + switch (state) { + case SCHRO_STATE_HAVE_BUFFER: + case SCHRO_STATE_END_OF_STREAM: + enc_buf = schro_encoder_pull(encoder, &presentation_frame); + av_assert0(enc_buf->length > 0); + parse_code = enc_buf->data[4]; + + /* All non-frame data is prepended to actual frame data to + * be able to set the pts correctly. So we don't write data + * to the frame output queue until we actually have a frame + */ + p_schro_params->enc_buf = av_realloc(p_schro_params->enc_buf, + p_schro_params->enc_buf_size + enc_buf->length); + + memcpy(p_schro_params->enc_buf + p_schro_params->enc_buf_size, + enc_buf->data, enc_buf->length); + p_schro_params->enc_buf_size += enc_buf->length; + + + if (state == SCHRO_STATE_END_OF_STREAM) { + p_schro_params->eos_pulled = 1; + go = 0; + } + + if (!SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { + schro_buffer_unref(enc_buf); + break; + } + + /* Create output frame. */ + p_frame_output = av_mallocz(sizeof(FFSchroEncodedFrame)); + /* Set output data. */ + p_frame_output->size = p_schro_params->enc_buf_size; + p_frame_output->p_encbuf = p_schro_params->enc_buf; + if (SCHRO_PARSE_CODE_IS_INTRA(parse_code) && + SCHRO_PARSE_CODE_IS_REFERENCE(parse_code)) + p_frame_output->key_frame = 1; + + /* Parse the coded frame number from the bitstream. Bytes 14 + * through 17 represesent the frame number. */ + p_frame_output->frame_num = AV_RB32(enc_buf->data + 13); + + ff_schro_queue_push_back(&p_schro_params->enc_frame_queue, + p_frame_output); + p_schro_params->enc_buf_size = 0; + p_schro_params->enc_buf = NULL; + + schro_buffer_unref(enc_buf); + + break; + + case SCHRO_STATE_NEED_FRAME: + go = 0; + break; + + case SCHRO_STATE_AGAIN: + break; + + default: + av_log(avctx, AV_LOG_ERROR, "Unknown Schro Encoder state\n"); + return -1; + } + } + + /* Copy 'next' frame in queue. */ + + if (p_schro_params->enc_frame_queue.size == 1 && + p_schro_params->eos_pulled) + last_frame_in_sequence = 1; + + p_frame_output = ff_schro_queue_pop(&p_schro_params->enc_frame_queue); + + if (!p_frame_output) + return 0; + + pkt_size = p_frame_output->size; + if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) + pkt_size += p_schro_params->enc_buf_size; + if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size)) < 0) + goto error; + + memcpy(pkt->data, p_frame_output->p_encbuf, p_frame_output->size); + avctx->coded_frame->key_frame = p_frame_output->key_frame; + /* Use the frame number of the encoded frame as the pts. It is OK to + * do so since Dirac is a constant frame rate codec. It expects input + * to be of constant frame rate. */ + pkt->pts = + avctx->coded_frame->pts = p_frame_output->frame_num; + pkt->dts = p_schro_params->dts++; + enc_size = p_frame_output->size; + + /* Append the end of sequence information to the last frame in the + * sequence. */ + if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) { + memcpy(pkt->data + enc_size, p_schro_params->enc_buf, + p_schro_params->enc_buf_size); + enc_size += p_schro_params->enc_buf_size; + av_freep(&p_schro_params->enc_buf); + p_schro_params->enc_buf_size = 0; + } + + if (p_frame_output->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + +error: + /* free frame */ + libschroedinger_free_frame(p_frame_output); + return ret; +} + + +static int libschroedinger_encode_close(AVCodecContext *avctx) +{ + SchroEncoderParams *p_schro_params = avctx->priv_data; + + /* Close the encoder. */ + schro_encoder_free(p_schro_params->encoder); + + /* Free data in the output frame queue. */ + ff_schro_queue_free(&p_schro_params->enc_frame_queue, + libschroedinger_free_frame); + + + /* Free the encoder buffer. */ + if (p_schro_params->enc_buf_size) + av_freep(&p_schro_params->enc_buf); + + /* Free the video format structure. */ + av_freep(&p_schro_params->format); + + return 0; +} + + +AVCodec ff_libschroedinger_encoder = { + .name = "libschroedinger", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_DIRAC, + .priv_data_size = sizeof(SchroEncoderParams), + .init = libschroedinger_encode_init, + .encode2 = libschroedinger_encode_frame, + .close = libschroedinger_encode_close, + .capabilities = CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"), +}; diff --git a/ffmpeg/libavcodec/libspeexdec.c b/ffmpeg/libavcodec/libspeexdec.c new file mode 100644 index 0000000..7c1ffa6 --- /dev/null +++ b/ffmpeg/libavcodec/libspeexdec.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2008 David Conrad + * + * 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 +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct { + SpeexBits bits; + SpeexStereoState stereo; + void *dec_state; + int frame_size; +} LibSpeexContext; + + +static av_cold int libspeex_decode_init(AVCodecContext *avctx) +{ + LibSpeexContext *s = avctx->priv_data; + const SpeexMode *mode; + SpeexHeader *header = NULL; + int spx_mode; + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + if (avctx->extradata && avctx->extradata_size >= 80) { + header = speex_packet_to_header(avctx->extradata, + avctx->extradata_size); + if (!header) + av_log(avctx, AV_LOG_WARNING, "Invalid Speex header\n"); + } + if (header) { + avctx->sample_rate = header->rate; + avctx->channels = header->nb_channels; + spx_mode = header->mode; + speex_header_free(header); + } else { + switch (avctx->sample_rate) { + case 8000: spx_mode = 0; break; + case 16000: spx_mode = 1; break; + case 32000: spx_mode = 2; break; + default: + /* libspeex can handle any mode if initialized as ultra-wideband */ + av_log(avctx, AV_LOG_WARNING, "Invalid sample rate: %d\n" + "Decoding as 32kHz ultra-wideband\n", + avctx->sample_rate); + spx_mode = 2; + } + } + + mode = speex_lib_get_mode(spx_mode); + if (!mode) { + av_log(avctx, AV_LOG_ERROR, "Unknown Speex mode %d", spx_mode); + return AVERROR_INVALIDDATA; + } + s->frame_size = 160 << spx_mode; + if (!avctx->sample_rate) + avctx->sample_rate = 8000 << spx_mode; + + if (avctx->channels < 1 || avctx->channels > 2) { + /* libspeex can handle mono or stereo if initialized as stereo */ + av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n" + "Decoding as stereo.\n", avctx->channels); + avctx->channels = 2; + } + avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + + speex_bits_init(&s->bits); + s->dec_state = speex_decoder_init(mode); + if (!s->dec_state) { + av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex decoder.\n"); + return -1; + } + + if (avctx->channels == 2) { + SpeexCallback callback; + callback.callback_id = SPEEX_INBAND_STEREO; + callback.func = speex_std_stereo_request_handler; + callback.data = &s->stereo; + s->stereo = (SpeexStereoState)SPEEX_STEREO_STATE_INIT; + speex_decoder_ctl(s->dec_state, SPEEX_SET_HANDLER, &callback); + } + + return 0; +} + +static int libspeex_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + LibSpeexContext *s = avctx->priv_data; + AVFrame *frame = data; + int16_t *output; + int ret, consumed = 0; + + /* get output buffer */ + frame->nb_samples = s->frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + output = (int16_t *)frame->data[0]; + + /* if there is not enough data left for the smallest possible frame or the + next 5 bits are a terminator code, reset the libspeex buffer using the + current packet, otherwise ignore the current packet and keep decoding + frames from the libspeex buffer. */ + if (speex_bits_remaining(&s->bits) < 5 || + speex_bits_peek_unsigned(&s->bits, 5) == 0xF) { + /* check for flush packet */ + if (!buf || !buf_size) { + *got_frame_ptr = 0; + return buf_size; + } + /* set new buffer */ + speex_bits_read_from(&s->bits, buf, buf_size); + consumed = buf_size; + } + + /* decode a single frame */ + ret = speex_decode_int(s->dec_state, &s->bits, output); + if (ret <= -2) { + av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); + return AVERROR_INVALIDDATA; + } + if (avctx->channels == 2) + speex_decode_stereo_int(output, s->frame_size, &s->stereo); + + *got_frame_ptr = 1; + + return consumed; +} + +static av_cold int libspeex_decode_close(AVCodecContext *avctx) +{ + LibSpeexContext *s = avctx->priv_data; + + speex_bits_destroy(&s->bits); + speex_decoder_destroy(s->dec_state); + + return 0; +} + +static av_cold void libspeex_decode_flush(AVCodecContext *avctx) +{ + LibSpeexContext *s = avctx->priv_data; + speex_bits_reset(&s->bits); +} + +AVCodec ff_libspeex_decoder = { + .name = "libspeex", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SPEEX, + .priv_data_size = sizeof(LibSpeexContext), + .init = libspeex_decode_init, + .close = libspeex_decode_close, + .decode = libspeex_decode_frame, + .flush = libspeex_decode_flush, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DELAY | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), +}; diff --git a/ffmpeg/libavcodec/libspeexenc.c b/ffmpeg/libavcodec/libspeexenc.c new file mode 100644 index 0000000..b96ca1b --- /dev/null +++ b/ffmpeg/libavcodec/libspeexenc.c @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2009 Justin Ruggles + * Copyright (c) 2009 Xuggle Incorporated + * + * 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 + */ + +/** + * @file + * libspeex Speex audio encoder + * + * Usage Guide + * This explains the values that need to be set prior to initialization in + * order to control various encoding parameters. + * + * Channels + * Speex only supports mono or stereo, so avctx->channels must be set to + * 1 or 2. + * + * Sample Rate / Encoding Mode + * Speex has 3 modes, each of which uses a specific sample rate. + * narrowband : 8 kHz + * wideband : 16 kHz + * ultra-wideband : 32 kHz + * avctx->sample_rate must be set to one of these 3 values. This will be + * used to set the encoding mode. + * + * Rate Control + * VBR mode is turned on by setting CODEC_FLAG_QSCALE in avctx->flags. + * avctx->global_quality is used to set the encoding quality. + * For CBR mode, avctx->bit_rate can be used to set the constant bitrate. + * Alternatively, the 'cbr_quality' option can be set from 0 to 10 to set + * a constant bitrate based on quality. + * For ABR mode, set avctx->bit_rate and set the 'abr' option to 1. + * Approx. Bitrate Range: + * narrowband : 2400 - 25600 bps + * wideband : 4000 - 43200 bps + * ultra-wideband : 4400 - 45200 bps + * + * Complexity + * Encoding complexity is controlled by setting avctx->compression_level. + * The valid range is 0 to 10. A higher setting gives generally better + * quality at the expense of encoding speed. This does not affect the + * bit rate. + * + * Frames-per-Packet + * The encoder defaults to using 1 frame-per-packet. However, it is + * sometimes desirable to use multiple frames-per-packet to reduce the + * amount of container overhead. This can be done by setting the + * 'frames_per_packet' option to a value 1 to 8. + * + * + * Optional features + * Speex encoder supports several optional features, which can be useful + * for some conditions. + * + * Voice Activity Detection + * When enabled, voice activity detection detects whether the audio + * being encoded is speech or silence/background noise. VAD is always + * implicitly activated when encoding in VBR, so the option is only useful + * in non-VBR operation. In this case, Speex detects non-speech periods and + * encodes them with just enough bits to reproduce the background noise. + * + * Discontinuous Transmission (DTX) + * DTX is an addition to VAD/VBR operation, that allows to stop transmitting + * completely when the background noise is stationary. + * In file-based operation only 5 bits are used for such frames. + */ + +#include +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "audio_frame_queue.h" + +/* TODO: Think about converting abr, vad, dtx and such flags to a bit field */ +typedef struct { + AVClass *class; ///< AVClass for private options + SpeexBits bits; ///< libspeex bitwriter context + SpeexHeader header; ///< libspeex header struct + void *enc_state; ///< libspeex encoder state + int frames_per_packet; ///< number of frames to encode in each packet + float vbr_quality; ///< VBR quality 0.0 to 10.0 + int cbr_quality; ///< CBR quality 0 to 10 + int abr; ///< flag to enable ABR + int vad; ///< flag to enable VAD + int dtx; ///< flag to enable DTX + int pkt_frame_count; ///< frame count for the current packet + AudioFrameQueue afq; ///< frame queue +} LibSpeexEncContext; + +static av_cold void print_enc_params(AVCodecContext *avctx, + LibSpeexEncContext *s) +{ + const char *mode_str = "unknown"; + + av_log(avctx, AV_LOG_DEBUG, "channels: %d\n", avctx->channels); + switch (s->header.mode) { + case SPEEX_MODEID_NB: mode_str = "narrowband"; break; + case SPEEX_MODEID_WB: mode_str = "wideband"; break; + case SPEEX_MODEID_UWB: mode_str = "ultra-wideband"; break; + } + av_log(avctx, AV_LOG_DEBUG, "mode: %s\n", mode_str); + if (s->header.vbr) { + av_log(avctx, AV_LOG_DEBUG, "rate control: VBR\n"); + av_log(avctx, AV_LOG_DEBUG, " quality: %f\n", s->vbr_quality); + } else if (s->abr) { + av_log(avctx, AV_LOG_DEBUG, "rate control: ABR\n"); + av_log(avctx, AV_LOG_DEBUG, " bitrate: %d bps\n", avctx->bit_rate); + } else { + av_log(avctx, AV_LOG_DEBUG, "rate control: CBR\n"); + av_log(avctx, AV_LOG_DEBUG, " bitrate: %d bps\n", avctx->bit_rate); + } + av_log(avctx, AV_LOG_DEBUG, "complexity: %d\n", + avctx->compression_level); + av_log(avctx, AV_LOG_DEBUG, "frame size: %d samples\n", + avctx->frame_size); + av_log(avctx, AV_LOG_DEBUG, "frames per packet: %d\n", + s->frames_per_packet); + av_log(avctx, AV_LOG_DEBUG, "packet size: %d\n", + avctx->frame_size * s->frames_per_packet); + av_log(avctx, AV_LOG_DEBUG, "voice activity detection: %d\n", s->vad); + av_log(avctx, AV_LOG_DEBUG, "discontinuous transmission: %d\n", s->dtx); +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + LibSpeexEncContext *s = avctx->priv_data; + const SpeexMode *mode; + uint8_t *header_data; + int header_size; + int32_t complexity; + + /* channels */ + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid channels (%d). Only stereo and " + "mono are supported\n", avctx->channels); + return AVERROR(EINVAL); + } + + /* sample rate and encoding mode */ + switch (avctx->sample_rate) { + case 8000: mode = &speex_nb_mode; break; + case 16000: mode = &speex_wb_mode; break; + case 32000: mode = &speex_uwb_mode; break; + default: + av_log(avctx, AV_LOG_ERROR, "Sample rate of %d Hz is not supported. " + "Resample to 8, 16, or 32 kHz.\n", avctx->sample_rate); + return AVERROR(EINVAL); + } + + /* initialize libspeex */ + s->enc_state = speex_encoder_init(mode); + if (!s->enc_state) { + av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex\n"); + return -1; + } + speex_init_header(&s->header, avctx->sample_rate, avctx->channels, mode); + + /* rate control method and parameters */ + if (avctx->flags & CODEC_FLAG_QSCALE) { + /* VBR */ + s->header.vbr = 1; + s->vad = 1; /* VAD is always implicitly activated for VBR */ + speex_encoder_ctl(s->enc_state, SPEEX_SET_VBR, &s->header.vbr); + s->vbr_quality = av_clipf(avctx->global_quality / (float)FF_QP2LAMBDA, + 0.0f, 10.0f); + speex_encoder_ctl(s->enc_state, SPEEX_SET_VBR_QUALITY, &s->vbr_quality); + } else { + s->header.bitrate = avctx->bit_rate; + if (avctx->bit_rate > 0) { + /* CBR or ABR by bitrate */ + if (s->abr) { + speex_encoder_ctl(s->enc_state, SPEEX_SET_ABR, + &s->header.bitrate); + speex_encoder_ctl(s->enc_state, SPEEX_GET_ABR, + &s->header.bitrate); + } else { + speex_encoder_ctl(s->enc_state, SPEEX_SET_BITRATE, + &s->header.bitrate); + speex_encoder_ctl(s->enc_state, SPEEX_GET_BITRATE, + &s->header.bitrate); + } + } else { + /* CBR by quality */ + speex_encoder_ctl(s->enc_state, SPEEX_SET_QUALITY, + &s->cbr_quality); + speex_encoder_ctl(s->enc_state, SPEEX_GET_BITRATE, + &s->header.bitrate); + } + /* stereo side information adds about 800 bps to the base bitrate */ + /* TODO: this should be calculated exactly */ + avctx->bit_rate = s->header.bitrate + (avctx->channels == 2 ? 800 : 0); + } + + /* VAD is activated with VBR or can be turned on by itself */ + if (s->vad) + speex_encoder_ctl(s->enc_state, SPEEX_SET_VAD, &s->vad); + + /* Activiting Discontinuous Transmission */ + if (s->dtx) { + speex_encoder_ctl(s->enc_state, SPEEX_SET_DTX, &s->dtx); + if (!(s->abr || s->vad || s->header.vbr)) + av_log(avctx, AV_LOG_WARNING, "DTX is not much of use without ABR, VAD or VBR\n"); + } + + /* set encoding complexity */ + if (avctx->compression_level > FF_COMPRESSION_DEFAULT) { + complexity = av_clip(avctx->compression_level, 0, 10); + speex_encoder_ctl(s->enc_state, SPEEX_SET_COMPLEXITY, &complexity); + } + speex_encoder_ctl(s->enc_state, SPEEX_GET_COMPLEXITY, &complexity); + avctx->compression_level = complexity; + + /* set packet size */ + avctx->frame_size = s->header.frame_size; + s->header.frames_per_packet = s->frames_per_packet; + + /* set encoding delay */ + speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &avctx->delay); + ff_af_queue_init(avctx, &s->afq); + + /* create header packet bytes from header struct */ + /* note: libspeex allocates the memory for header_data, which is freed + below with speex_header_free() */ + header_data = speex_header_to_packet(&s->header, &header_size); + + /* allocate extradata and coded_frame */ + avctx->extradata = av_malloc(header_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + speex_header_free(header_data); + speex_encoder_destroy(s->enc_state); + av_log(avctx, AV_LOG_ERROR, "memory allocation error\n"); + return AVERROR(ENOMEM); + } + + /* copy header packet to extradata */ + memcpy(avctx->extradata, header_data, header_size); + avctx->extradata_size = header_size; + speex_header_free(header_data); + + /* init libspeex bitwriter */ + speex_bits_init(&s->bits); + + print_enc_params(avctx, s); + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + LibSpeexEncContext *s = avctx->priv_data; + int16_t *samples = frame ? (int16_t *)frame->data[0] : NULL; + int ret; + + if (samples) { + /* encode Speex frame */ + if (avctx->channels == 2) + speex_encode_stereo_int(samples, s->header.frame_size, &s->bits); + speex_encode_int(s->enc_state, samples, &s->bits); + s->pkt_frame_count++; + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } else { + /* handle end-of-stream */ + if (!s->pkt_frame_count) + return 0; + /* add extra terminator codes for unused frames in last packet */ + while (s->pkt_frame_count < s->frames_per_packet) { + speex_bits_pack(&s->bits, 15, 5); + s->pkt_frame_count++; + } + } + + /* write output if all frames for the packet have been encoded */ + if (s->pkt_frame_count == s->frames_per_packet) { + s->pkt_frame_count = 0; + if ((ret = ff_alloc_packet2(avctx, avpkt, speex_bits_nbytes(&s->bits))) < 0) + return ret; + ret = speex_bits_write(&s->bits, avpkt->data, avpkt->size); + speex_bits_reset(&s->bits); + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, s->frames_per_packet * avctx->frame_size, + &avpkt->pts, &avpkt->duration); + + avpkt->size = ret; + *got_packet_ptr = 1; + return 0; + } + return 0; +} + +static av_cold int encode_close(AVCodecContext *avctx) +{ + LibSpeexEncContext *s = avctx->priv_data; + + speex_bits_destroy(&s->bits); + speex_encoder_destroy(s->enc_state); + + ff_af_queue_close(&s->afq); + av_freep(&avctx->extradata); + + return 0; +} + +#define OFFSET(x) offsetof(LibSpeexEncContext, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "abr", "Use average bit rate", OFFSET(abr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE }, + { "cbr_quality", "Set quality value (0 to 10) for CBR", OFFSET(cbr_quality), AV_OPT_TYPE_INT, { .i64 = 8 }, 0, 10, AE }, + { "frames_per_packet", "Number of frames to encode in each packet", OFFSET(frames_per_packet), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 8, AE }, + { "vad", "Voice Activity Detection", OFFSET(vad), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE }, + { "dtx", "Discontinuous Transmission", OFFSET(dtx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "libspeex", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { "compression_level", "3" }, + { NULL }, +}; + +AVCodec ff_libspeex_encoder = { + .name = "libspeex", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SPEEX, + .priv_data_size = sizeof(LibSpeexEncContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .capabilities = CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + 0 }, + .supported_samplerates = (const int[]){ 8000, 16000, 32000, 0 }, + .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), + .priv_class = &class, + .defaults = defaults, +}; diff --git a/ffmpeg/libavcodec/libstagefright.cpp b/ffmpeg/libavcodec/libstagefright.cpp new file mode 100644 index 0000000..a6fd1b9 --- /dev/null +++ b/ffmpeg/libavcodec/libstagefright.cpp @@ -0,0 +1,597 @@ +/* + * Interface to the Android Stagefright library for + * H/W accelerated H.264 decoding + * + * Copyright (C) 2011 Mohamed Naufal + * Copyright (C) 2011 Martin Storsjö + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "avcodec.h" +#include "libavutil/imgutils.h" +} + +#define OMX_QCOM_COLOR_FormatYVU420SemiPlanar 0x7FA30C00 + +using namespace android; + +struct Frame { + status_t status; + size_t size; + int64_t time; + int key; + uint8_t *buffer; + AVFrame *vframe; +}; + +struct TimeStamp { + int64_t pts; + int64_t reordered_opaque; +}; + +class CustomSource; + +struct StagefrightContext { + AVCodecContext *avctx; + AVBitStreamFilterContext *bsfc; + uint8_t* orig_extradata; + int orig_extradata_size; + sp *source; + List *in_queue, *out_queue; + pthread_mutex_t in_mutex, out_mutex; + pthread_cond_t condition; + pthread_t decode_thread_id; + + Frame *end_frame; + bool source_done; + volatile sig_atomic_t thread_started, thread_exited, stop_decode; + + AVFrame *prev_frame; + std::map *ts_map; + int64_t frame_index; + + uint8_t *dummy_buf; + int dummy_bufsize; + + OMXClient *client; + sp *decoder; + const char *decoder_component; +}; + +class CustomSource : public MediaSource { +public: + CustomSource(AVCodecContext *avctx, sp meta) { + s = (StagefrightContext*)avctx->priv_data; + source_meta = meta; + frame_size = (avctx->width * avctx->height * 3) / 2; + buf_group.add_buffer(new MediaBuffer(frame_size)); + } + + virtual sp getFormat() { + return source_meta; + } + + virtual status_t start(MetaData *params) { + return OK; + } + + virtual status_t stop() { + return OK; + } + + virtual status_t read(MediaBuffer **buffer, + const MediaSource::ReadOptions *options) { + Frame *frame; + status_t ret; + + if (s->thread_exited) + return ERROR_END_OF_STREAM; + pthread_mutex_lock(&s->in_mutex); + + while (s->in_queue->empty()) + pthread_cond_wait(&s->condition, &s->in_mutex); + + frame = *s->in_queue->begin(); + ret = frame->status; + + if (ret == OK) { + ret = buf_group.acquire_buffer(buffer); + if (ret == OK) { + memcpy((*buffer)->data(), frame->buffer, frame->size); + (*buffer)->set_range(0, frame->size); + (*buffer)->meta_data()->clear(); + (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame,frame->key); + (*buffer)->meta_data()->setInt64(kKeyTime, frame->time); + } else { + av_log(s->avctx, AV_LOG_ERROR, "Failed to acquire MediaBuffer\n"); + } + av_freep(&frame->buffer); + } + + s->in_queue->erase(s->in_queue->begin()); + pthread_mutex_unlock(&s->in_mutex); + + av_freep(&frame); + return ret; + } + +private: + MediaBufferGroup buf_group; + sp source_meta; + StagefrightContext *s; + int frame_size; +}; + +void* decode_thread(void *arg) +{ + AVCodecContext *avctx = (AVCodecContext*)arg; + StagefrightContext *s = (StagefrightContext*)avctx->priv_data; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(avctx->pix_fmt); + Frame* frame; + MediaBuffer *buffer; + int32_t w, h; + int decode_done = 0; + int ret; + int src_linesize[3]; + const uint8_t *src_data[3]; + int64_t out_frame_index = 0; + + do { + buffer = NULL; + frame = (Frame*)av_mallocz(sizeof(Frame)); + if (!frame) { + frame = s->end_frame; + frame->status = AVERROR(ENOMEM); + decode_done = 1; + s->end_frame = NULL; + goto push_frame; + } + frame->status = (*s->decoder)->read(&buffer); + if (frame->status == OK) { + sp outFormat = (*s->decoder)->getFormat(); + outFormat->findInt32(kKeyWidth , &w); + outFormat->findInt32(kKeyHeight, &h); + frame->vframe = (AVFrame*)av_mallocz(sizeof(AVFrame)); + if (!frame->vframe) { + frame->status = AVERROR(ENOMEM); + decode_done = 1; + buffer->release(); + goto push_frame; + } + ret = ff_get_buffer(avctx, frame->vframe); + if (ret < 0) { + frame->status = ret; + decode_done = 1; + buffer->release(); + goto push_frame; + } + + // The OMX.SEC decoder doesn't signal the modified width/height + if (s->decoder_component && !strncmp(s->decoder_component, "OMX.SEC", 7) && + (w & 15 || h & 15)) { + if (((w + 15)&~15) * ((h + 15)&~15) * 3/2 == buffer->range_length()) { + w = (w + 15)&~15; + h = (h + 15)&~15; + } + } + + if (!avctx->width || !avctx->height || avctx->width > w || avctx->height > h) { + avctx->width = w; + avctx->height = h; + } + + src_linesize[0] = av_image_get_linesize(avctx->pix_fmt, w, 0); + src_linesize[1] = av_image_get_linesize(avctx->pix_fmt, w, 1); + src_linesize[2] = av_image_get_linesize(avctx->pix_fmt, w, 2); + + src_data[0] = (uint8_t*)buffer->data(); + src_data[1] = src_data[0] + src_linesize[0] * h; + src_data[2] = src_data[1] + src_linesize[1] * -(-h>>pix_desc->log2_chroma_h); + av_image_copy(frame->vframe->data, frame->vframe->linesize, + src_data, src_linesize, + avctx->pix_fmt, avctx->width, avctx->height); + + buffer->meta_data()->findInt64(kKeyTime, &out_frame_index); + if (out_frame_index && s->ts_map->count(out_frame_index) > 0) { + frame->vframe->pts = (*s->ts_map)[out_frame_index].pts; + frame->vframe->reordered_opaque = (*s->ts_map)[out_frame_index].reordered_opaque; + s->ts_map->erase(out_frame_index); + } + buffer->release(); + } else if (frame->status == INFO_FORMAT_CHANGED) { + if (buffer) + buffer->release(); + av_free(frame); + continue; + } else { + decode_done = 1; + } +push_frame: + while (true) { + pthread_mutex_lock(&s->out_mutex); + if (s->out_queue->size() >= 10) { + pthread_mutex_unlock(&s->out_mutex); + usleep(10000); + continue; + } + break; + } + s->out_queue->push_back(frame); + pthread_mutex_unlock(&s->out_mutex); + } while (!decode_done && !s->stop_decode); + + s->thread_exited = true; + + return 0; +} + +static av_cold int Stagefright_init(AVCodecContext *avctx) +{ + StagefrightContext *s = (StagefrightContext*)avctx->priv_data; + sp meta, outFormat; + int32_t colorFormat = 0; + int ret; + + if (!avctx->extradata || !avctx->extradata_size || avctx->extradata[0] != 1) + return -1; + + s->avctx = avctx; + s->bsfc = av_bitstream_filter_init("h264_mp4toannexb"); + if (!s->bsfc) { + av_log(avctx, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n"); + return -1; + } + + s->orig_extradata_size = avctx->extradata_size; + s->orig_extradata = (uint8_t*) av_mallocz(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->orig_extradata) { + ret = AVERROR(ENOMEM); + goto fail; + } + memcpy(s->orig_extradata, avctx->extradata, avctx->extradata_size); + + meta = new MetaData; + if (meta == NULL) { + ret = AVERROR(ENOMEM); + goto fail; + } + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); + meta->setInt32(kKeyWidth, avctx->width); + meta->setInt32(kKeyHeight, avctx->height); + meta->setData(kKeyAVCC, kTypeAVCC, avctx->extradata, avctx->extradata_size); + + android::ProcessState::self()->startThreadPool(); + + s->source = new sp(); + *s->source = new CustomSource(avctx, meta); + s->in_queue = new List; + s->out_queue = new List; + s->ts_map = new std::map; + s->client = new OMXClient; + s->end_frame = (Frame*)av_mallocz(sizeof(Frame)); + if (s->source == NULL || !s->in_queue || !s->out_queue || !s->client || + !s->ts_map || !s->end_frame) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if (s->client->connect() != OK) { + av_log(avctx, AV_LOG_ERROR, "Cannot connect OMX client\n"); + ret = -1; + goto fail; + } + + s->decoder = new sp(); + *s->decoder = OMXCodec::Create(s->client->interface(), meta, + false, *s->source, NULL, + OMXCodec::kClientNeedsFramebuffer); + if ((*s->decoder)->start() != OK) { + av_log(avctx, AV_LOG_ERROR, "Cannot start decoder\n"); + ret = -1; + s->client->disconnect(); + goto fail; + } + + outFormat = (*s->decoder)->getFormat(); + outFormat->findInt32(kKeyColorFormat, &colorFormat); + if (colorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar || + colorFormat == OMX_COLOR_FormatYUV420SemiPlanar) + avctx->pix_fmt = AV_PIX_FMT_NV21; + else if (colorFormat == OMX_COLOR_FormatYCbYCr) + avctx->pix_fmt = AV_PIX_FMT_YUYV422; + else if (colorFormat == OMX_COLOR_FormatCbYCrY) + avctx->pix_fmt = AV_PIX_FMT_UYVY422; + else + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + outFormat->findCString(kKeyDecoderComponent, &s->decoder_component); + if (s->decoder_component) + s->decoder_component = av_strdup(s->decoder_component); + + pthread_mutex_init(&s->in_mutex, NULL); + pthread_mutex_init(&s->out_mutex, NULL); + pthread_cond_init(&s->condition, NULL); + return 0; + +fail: + av_bitstream_filter_close(s->bsfc); + av_freep(&s->orig_extradata); + av_freep(&s->end_frame); + delete s->in_queue; + delete s->out_queue; + delete s->ts_map; + delete s->client; + return ret; +} + +static int Stagefright_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + StagefrightContext *s = (StagefrightContext*)avctx->priv_data; + Frame *frame; + status_t status; + int orig_size = avpkt->size; + AVPacket pkt = *avpkt; + AVFrame *ret_frame; + + if (!s->thread_started) { + pthread_create(&s->decode_thread_id, NULL, &decode_thread, avctx); + s->thread_started = true; + } + + if (avpkt && avpkt->data) { + av_bitstream_filter_filter(s->bsfc, avctx, NULL, &pkt.data, &pkt.size, + avpkt->data, avpkt->size, avpkt->flags & AV_PKT_FLAG_KEY); + avpkt = &pkt; + } + + if (!s->source_done) { + if(!s->dummy_buf) { + s->dummy_buf = (uint8_t*)av_malloc(avpkt->size); + if (!s->dummy_buf) + return AVERROR(ENOMEM); + s->dummy_bufsize = avpkt->size; + memcpy(s->dummy_buf, avpkt->data, avpkt->size); + } + + frame = (Frame*)av_mallocz(sizeof(Frame)); + if (avpkt->data) { + frame->status = OK; + frame->size = avpkt->size; + frame->key = avpkt->flags & AV_PKT_FLAG_KEY ? 1 : 0; + frame->buffer = (uint8_t*)av_malloc(avpkt->size); + if (!frame->buffer) { + av_freep(&frame); + return AVERROR(ENOMEM); + } + uint8_t *ptr = avpkt->data; + // The OMX.SEC decoder fails without this. + if (avpkt->size == orig_size + avctx->extradata_size) { + ptr += avctx->extradata_size; + frame->size = orig_size; + } + memcpy(frame->buffer, ptr, orig_size); + if (avpkt == &pkt) + av_free(avpkt->data); + + frame->time = ++s->frame_index; + (*s->ts_map)[s->frame_index].pts = avpkt->pts; + (*s->ts_map)[s->frame_index].reordered_opaque = avctx->reordered_opaque; + } else { + frame->status = ERROR_END_OF_STREAM; + s->source_done = true; + } + + while (true) { + if (s->thread_exited) { + s->source_done = true; + break; + } + pthread_mutex_lock(&s->in_mutex); + if (s->in_queue->size() >= 10) { + pthread_mutex_unlock(&s->in_mutex); + usleep(10000); + continue; + } + s->in_queue->push_back(frame); + pthread_cond_signal(&s->condition); + pthread_mutex_unlock(&s->in_mutex); + break; + } + } + while (true) { + pthread_mutex_lock(&s->out_mutex); + if (!s->out_queue->empty()) break; + pthread_mutex_unlock(&s->out_mutex); + if (s->source_done) { + usleep(10000); + continue; + } else { + return orig_size; + } + } + + frame = *s->out_queue->begin(); + s->out_queue->erase(s->out_queue->begin()); + pthread_mutex_unlock(&s->out_mutex); + + ret_frame = frame->vframe; + status = frame->status; + av_freep(&frame); + + if (status == ERROR_END_OF_STREAM) + return 0; + if (status != OK) { + if (status == AVERROR(ENOMEM)) + return status; + av_log(avctx, AV_LOG_ERROR, "Decode failed: %x\n", status); + return -1; + } + + if (s->prev_frame) { + avctx->release_buffer(avctx, s->prev_frame); + av_freep(&s->prev_frame); + } + s->prev_frame = ret_frame; + + *got_frame = 1; + *(AVFrame*)data = *ret_frame; + return orig_size; +} + +static av_cold int Stagefright_close(AVCodecContext *avctx) +{ + StagefrightContext *s = (StagefrightContext*)avctx->priv_data; + Frame *frame; + + if (s->thread_started) { + if (!s->thread_exited) { + s->stop_decode = 1; + + // Make sure decode_thread() doesn't get stuck + pthread_mutex_lock(&s->out_mutex); + while (!s->out_queue->empty()) { + frame = *s->out_queue->begin(); + s->out_queue->erase(s->out_queue->begin()); + if (frame->vframe) { + avctx->release_buffer(avctx, frame->vframe); + av_freep(&frame->vframe); + } + av_freep(&frame); + } + pthread_mutex_unlock(&s->out_mutex); + + // Feed a dummy frame prior to signalling EOF. + // This is required to terminate the decoder(OMX.SEC) + // when only one frame is read during stream info detection. + if (s->dummy_buf && (frame = (Frame*)av_mallocz(sizeof(Frame)))) { + frame->status = OK; + frame->size = s->dummy_bufsize; + frame->key = 1; + frame->buffer = s->dummy_buf; + pthread_mutex_lock(&s->in_mutex); + s->in_queue->push_back(frame); + pthread_cond_signal(&s->condition); + pthread_mutex_unlock(&s->in_mutex); + s->dummy_buf = NULL; + } + + pthread_mutex_lock(&s->in_mutex); + s->end_frame->status = ERROR_END_OF_STREAM; + s->in_queue->push_back(s->end_frame); + pthread_cond_signal(&s->condition); + pthread_mutex_unlock(&s->in_mutex); + s->end_frame = NULL; + } + + pthread_join(s->decode_thread_id, NULL); + + if (s->prev_frame) { + avctx->release_buffer(avctx, s->prev_frame); + av_freep(&s->prev_frame); + } + + s->thread_started = false; + } + + while (!s->in_queue->empty()) { + frame = *s->in_queue->begin(); + s->in_queue->erase(s->in_queue->begin()); + if (frame->size) + av_freep(&frame->buffer); + av_freep(&frame); + } + + while (!s->out_queue->empty()) { + frame = *s->out_queue->begin(); + s->out_queue->erase(s->out_queue->begin()); + if (frame->vframe) { + avctx->release_buffer(avctx, frame->vframe); + av_freep(&frame->vframe); + } + av_freep(&frame); + } + + (*s->decoder)->stop(); + s->client->disconnect(); + + if (s->decoder_component) + av_freep(&s->decoder_component); + av_freep(&s->dummy_buf); + av_freep(&s->end_frame); + + // Reset the extradata back to the original mp4 format, so that + // the next invocation (both when decoding and when called from + // av_find_stream_info) get the original mp4 format extradata. + av_freep(&avctx->extradata); + avctx->extradata = s->orig_extradata; + avctx->extradata_size = s->orig_extradata_size; + + delete s->in_queue; + delete s->out_queue; + delete s->ts_map; + delete s->client; + delete s->decoder; + delete s->source; + + pthread_mutex_destroy(&s->in_mutex); + pthread_mutex_destroy(&s->out_mutex); + pthread_cond_destroy(&s->condition); + av_bitstream_filter_close(s->bsfc); + return 0; +} + +AVCodec ff_libstagefright_h264_decoder = { + "libstagefright_h264", + NULL_IF_CONFIG_SMALL("libstagefright H.264"), + AVMEDIA_TYPE_VIDEO, + AV_CODEC_ID_H264, + CODEC_CAP_DELAY, + NULL, //supported_framerates + NULL, //pix_fmts + NULL, //supported_samplerates + NULL, //sample_fmts + NULL, //channel_layouts + 0, //max_lowres + NULL, //priv_class + NULL, //profiles + sizeof(StagefrightContext), + NULL, //next + NULL, //init_thread_copy + NULL, //update_thread_context + NULL, //defaults + NULL, //init_static_data + Stagefright_init, + NULL, //encode + NULL, //encode2 + Stagefright_decode_frame, + Stagefright_close, +}; diff --git a/ffmpeg/libavcodec/libtheoraenc.c b/ffmpeg/libavcodec/libtheoraenc.c new file mode 100644 index 0000000..893370f --- /dev/null +++ b/ffmpeg/libavcodec/libtheoraenc.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2006 Paul Richards + * + * 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 + */ + +/** + * @file + * @brief Theora encoder using libtheora. + * @author Paul Richards + * + * A lot of this is copy / paste from other output codecs in + * libavcodec or pure guesswork (or both). + * + * I have used t_ prefixes on variables which are libtheora types + * and o_ prefixes on variables which are libogg types. + */ + +/* FFmpeg includes */ +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" +#include "libavutil/log.h" +#include "libavutil/base64.h" +#include "avcodec.h" +#include "internal.h" + +/* libtheora includes */ +#include + +typedef struct TheoraContext { + th_enc_ctx *t_state; + uint8_t *stats; + int stats_size; + int stats_offset; + int uv_hshift; + int uv_vshift; + int keyframe_mask; +} TheoraContext; + +/** Concatenate an ogg_packet into the extradata. */ +static int concatenate_packet(unsigned int* offset, + AVCodecContext* avc_context, + const ogg_packet* packet) +{ + const char* message = NULL; + uint8_t* newdata = NULL; + int newsize = avc_context->extradata_size + 2 + packet->bytes; + int ret; + + if (packet->bytes < 0) { + message = "ogg_packet has negative size"; + ret = AVERROR_INVALIDDATA; + } else if (packet->bytes > 0xffff) { + message = "ogg_packet is larger than 65535 bytes"; + ret = AVERROR_INVALIDDATA; + } else if (newsize < avc_context->extradata_size) { + message = "extradata_size would overflow"; + ret = AVERROR_INVALIDDATA; + } else { + newdata = av_realloc(avc_context->extradata, newsize); + if (!newdata) + message = "av_realloc failed"; + ret = AVERROR(ENOMEM); + } + if (message) { + av_log(avc_context, AV_LOG_ERROR, "concatenate_packet failed: %s\n", message); + return ret; + } + + avc_context->extradata = newdata; + avc_context->extradata_size = newsize; + AV_WB16(avc_context->extradata + (*offset), packet->bytes); + *offset += 2; + memcpy(avc_context->extradata + (*offset), packet->packet, packet->bytes); + (*offset) += packet->bytes; + return 0; +} + +static int get_stats(AVCodecContext *avctx, int eos) +{ +#ifdef TH_ENCCTL_2PASS_OUT + TheoraContext *h = avctx->priv_data; + uint8_t *buf; + int bytes; + + bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_OUT, &buf, sizeof(buf)); + if (bytes < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting first pass stats\n"); + return AVERROR_EXTERNAL; + } + if (!eos) { + h->stats = av_fast_realloc(h->stats, &h->stats_size, + h->stats_offset + bytes); + memcpy(h->stats + h->stats_offset, buf, bytes); + h->stats_offset += bytes; + } else { + int b64_size = AV_BASE64_SIZE(h->stats_offset); + // libtheora generates a summary header at the end + memcpy(h->stats, buf, bytes); + avctx->stats_out = av_malloc(b64_size); + av_base64_encode(avctx->stats_out, b64_size, h->stats, h->stats_offset); + } + return 0; +#else + av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n"); + return AVERROR(ENOSUP); +#endif +} + +// libtheora won't read the entire buffer we give it at once, so we have to +// repeatedly submit it... +static int submit_stats(AVCodecContext *avctx) +{ +#ifdef TH_ENCCTL_2PASS_IN + TheoraContext *h = avctx->priv_data; + int bytes; + if (!h->stats) { + if (!avctx->stats_in) { + av_log(avctx, AV_LOG_ERROR, "No statsfile for second pass\n"); + return AVERROR(EINVAL); + } + h->stats_size = strlen(avctx->stats_in) * 3/4; + h->stats = av_malloc(h->stats_size); + h->stats_size = av_base64_decode(h->stats, avctx->stats_in, h->stats_size); + } + while (h->stats_size - h->stats_offset > 0) { + bytes = th_encode_ctl(h->t_state, TH_ENCCTL_2PASS_IN, + h->stats + h->stats_offset, + h->stats_size - h->stats_offset); + if (bytes < 0) { + av_log(avctx, AV_LOG_ERROR, "Error submitting stats\n"); + return AVERROR_EXTERNAL; + } + if (!bytes) + return 0; + h->stats_offset += bytes; + } + return 0; +#else + av_log(avctx, AV_LOG_ERROR, "libtheora too old to support 2pass\n"); + return AVERROR(ENOSUP); +#endif +} + +static av_cold int encode_init(AVCodecContext* avc_context) +{ + th_info t_info; + th_comment t_comment; + ogg_packet o_packet; + unsigned int offset; + TheoraContext *h = avc_context->priv_data; + uint32_t gop_size = avc_context->gop_size; + int ret; + + /* Set up the theora_info struct */ + th_info_init(&t_info); + t_info.frame_width = FFALIGN(avc_context->width, 16); + t_info.frame_height = FFALIGN(avc_context->height, 16); + t_info.pic_width = avc_context->width; + t_info.pic_height = avc_context->height; + t_info.pic_x = 0; + t_info.pic_y = 0; + /* Swap numerator and denominator as time_base in AVCodecContext gives the + * time period between frames, but theora_info needs the framerate. */ + t_info.fps_numerator = avc_context->time_base.den; + t_info.fps_denominator = avc_context->time_base.num; + if (avc_context->sample_aspect_ratio.num) { + t_info.aspect_numerator = avc_context->sample_aspect_ratio.num; + t_info.aspect_denominator = avc_context->sample_aspect_ratio.den; + } else { + t_info.aspect_numerator = 1; + t_info.aspect_denominator = 1; + } + + if (avc_context->color_primaries == AVCOL_PRI_BT470M) + t_info.colorspace = TH_CS_ITU_REC_470M; + else if (avc_context->color_primaries == AVCOL_PRI_BT470BG) + t_info.colorspace = TH_CS_ITU_REC_470BG; + else + t_info.colorspace = TH_CS_UNSPECIFIED; + + if (avc_context->pix_fmt == AV_PIX_FMT_YUV420P) + t_info.pixel_fmt = TH_PF_420; + else if (avc_context->pix_fmt == AV_PIX_FMT_YUV422P) + t_info.pixel_fmt = TH_PF_422; + else if (avc_context->pix_fmt == AV_PIX_FMT_YUV444P) + t_info.pixel_fmt = TH_PF_444; + else { + av_log(avc_context, AV_LOG_ERROR, "Unsupported pix_fmt\n"); + return AVERROR(EINVAL); + } + avcodec_get_chroma_sub_sample(avc_context->pix_fmt, &h->uv_hshift, &h->uv_vshift); + + if (avc_context->flags & CODEC_FLAG_QSCALE) { + /* to be constant with the libvorbis implementation, clip global_quality to 0 - 10 + Theora accepts a quality parameter p, which is: + * 0 <= p <=63 + * an int value + */ + t_info.quality = av_clipf(avc_context->global_quality / (float)FF_QP2LAMBDA, 0, 10) * 6.3; + t_info.target_bitrate = 0; + } else { + t_info.target_bitrate = avc_context->bit_rate; + t_info.quality = 0; + } + + /* Now initialise libtheora */ + h->t_state = th_encode_alloc(&t_info); + if (!h->t_state) { + av_log(avc_context, AV_LOG_ERROR, "theora_encode_init failed\n"); + return AVERROR_EXTERNAL; + } + + h->keyframe_mask = (1 << t_info.keyframe_granule_shift) - 1; + /* Clear up theora_info struct */ + th_info_clear(&t_info); + + if (th_encode_ctl(h->t_state, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, + &gop_size, sizeof(gop_size))) { + av_log(avc_context, AV_LOG_ERROR, "Error setting GOP size\n"); + return AVERROR_EXTERNAL; + } + + // need to enable 2 pass (via TH_ENCCTL_2PASS_) before encoding headers + if (avc_context->flags & CODEC_FLAG_PASS1) { + if ((ret = get_stats(avc_context, 0)) < 0) + return ret; + } else if (avc_context->flags & CODEC_FLAG_PASS2) { + if ((ret = submit_stats(avc_context)) < 0) + return ret; + } + + /* + Output first header packet consisting of theora + header, comment, and tables. + + Each one is prefixed with a 16bit size, then they + are concatenated together into libavcodec's extradata. + */ + offset = 0; + + /* Headers */ + th_comment_init(&t_comment); + + while (th_encode_flushheader(h->t_state, &t_comment, &o_packet)) + if ((ret = concatenate_packet(&offset, avc_context, &o_packet)) < 0) + return ret; + + th_comment_clear(&t_comment); + + /* Set up the output AVFrame */ + avc_context->coded_frame= avcodec_alloc_frame(); + + return 0; +} + +static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + th_ycbcr_buffer t_yuv_buffer; + TheoraContext *h = avc_context->priv_data; + ogg_packet o_packet; + int result, i, ret; + + // EOS, finish and get 1st pass stats if applicable + if (!frame) { + th_encode_packetout(h->t_state, 1, &o_packet); + if (avc_context->flags & CODEC_FLAG_PASS1) + if ((ret = get_stats(avc_context, 1)) < 0) + return ret; + return 0; + } + + /* Copy planes to the theora yuv_buffer */ + for (i = 0; i < 3; i++) { + t_yuv_buffer[i].width = FFALIGN(avc_context->width, 16) >> (i && h->uv_hshift); + t_yuv_buffer[i].height = FFALIGN(avc_context->height, 16) >> (i && h->uv_vshift); + t_yuv_buffer[i].stride = frame->linesize[i]; + t_yuv_buffer[i].data = frame->data[i]; + } + + if (avc_context->flags & CODEC_FLAG_PASS2) + if ((ret = submit_stats(avc_context)) < 0) + return ret; + + /* Now call into theora_encode_YUVin */ + result = th_encode_ycbcr_in(h->t_state, t_yuv_buffer); + if (result) { + const char* message; + switch (result) { + case -1: + message = "differing frame sizes"; + break; + case TH_EINVAL: + message = "encoder is not ready or is finished"; + break; + default: + message = "unknown reason"; + break; + } + av_log(avc_context, AV_LOG_ERROR, "theora_encode_YUVin failed (%s) [%d]\n", message, result); + return AVERROR_EXTERNAL; + } + + if (avc_context->flags & CODEC_FLAG_PASS1) + if ((ret = get_stats(avc_context, 0)) < 0) + return ret; + + /* Pick up returned ogg_packet */ + result = th_encode_packetout(h->t_state, 0, &o_packet); + switch (result) { + case 0: + /* No packet is ready */ + return 0; + case 1: + /* Success, we have a packet */ + break; + default: + av_log(avc_context, AV_LOG_ERROR, "theora_encode_packetout failed [%d]\n", result); + return AVERROR_EXTERNAL; + } + + /* Copy ogg_packet content out to buffer */ + if ((ret = ff_alloc_packet2(avc_context, pkt, o_packet.bytes)) < 0) + return ret; + memcpy(pkt->data, o_packet.packet, o_packet.bytes); + + // HACK: assumes no encoder delay, this is true until libtheora becomes + // multithreaded (which will be disabled unless explicitly requested) + pkt->pts = pkt->dts = frame->pts; + avc_context->coded_frame->key_frame = !(o_packet.granulepos & h->keyframe_mask); + if (avc_context->coded_frame->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int encode_close(AVCodecContext* avc_context) +{ + TheoraContext *h = avc_context->priv_data; + + th_encode_free(h->t_state); + av_freep(&h->stats); + av_freep(&avc_context->coded_frame); + av_freep(&avc_context->stats_out); + av_freep(&avc_context->extradata); + avc_context->extradata_size = 0; + + return 0; +} + +/** AVCodec struct exposed to libavcodec */ +AVCodec ff_libtheora_encoder = { + .name = "libtheora", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_THEORA, + .priv_data_size = sizeof(TheoraContext), + .init = encode_init, + .close = encode_close, + .encode2 = encode_frame, + .capabilities = CODEC_CAP_DELAY, // needed to get the statsfile summary + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), +}; diff --git a/ffmpeg/libavcodec/libtwolame.c b/ffmpeg/libavcodec/libtwolame.c new file mode 100644 index 0000000..8858714 --- /dev/null +++ b/ffmpeg/libavcodec/libtwolame.c @@ -0,0 +1,196 @@ +/* + * Interface to libtwolame for mp2 encoding + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +/** + * @file + * Interface to libtwolame for mp2 encoding. + */ + +#include + +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "mpegaudio.h" + +typedef struct TWOLAMEContext { + AVClass *class; + int mode; + int psymodel; + int energy; + int error_protection; + int copyright; + int original; + + twolame_options *glopts; + int64_t next_pts; +} TWOLAMEContext; + +static av_cold int twolame_encode_close(AVCodecContext *avctx) +{ + TWOLAMEContext *s = avctx->priv_data; + twolame_close(&s->glopts); + return 0; +} + +static av_cold int twolame_encode_init(AVCodecContext *avctx) +{ + TWOLAMEContext *s = avctx->priv_data; + int ret; + + avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME; + + s->glopts = twolame_init(); + if (!s->glopts) + return AVERROR(ENOMEM); + + twolame_set_verbosity(s->glopts, 0); + twolame_set_mode(s->glopts, s->mode); + twolame_set_psymodel(s->glopts, s->psymodel); + twolame_set_energy_levels(s->glopts, s->energy); + twolame_set_error_protection(s->glopts, s->error_protection); + + twolame_set_num_channels(s->glopts, avctx->channels); + twolame_set_in_samplerate(s->glopts, avctx->sample_rate); + twolame_set_out_samplerate(s->glopts, avctx->sample_rate); + if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) { + twolame_set_VBR(s->glopts, TRUE); + twolame_set_VBR_level(s->glopts, avctx->global_quality); + av_log(avctx, AV_LOG_WARNING, "VBR mode is experimental!\n"); + } else { + twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000); + } + + if ((ret = twolame_init_params(s->glopts))) + goto error; + + return 0; +error: + twolame_encode_close(avctx); + return ret; +} + +static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + TWOLAMEContext *s = avctx->priv_data; + int ret; + + if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE)) < 0) + return ret; + + if (frame) { + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_FLT: + ret = twolame_encode_buffer_float32_interleaved(s->glopts, + frame->data[0], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + case AV_SAMPLE_FMT_FLTP: + ret = twolame_encode_buffer_float32(s->glopts, + frame->data[0], frame->data[1], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + case AV_SAMPLE_FMT_S16: + ret = twolame_encode_buffer_interleaved(s->glopts, + frame->data[0], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + case AV_SAMPLE_FMT_S16P: + ret = twolame_encode_buffer(s->glopts, + frame->data[0], frame->data[1], + frame->nb_samples, + avpkt->data, avpkt->size); + break; + default: + return AVERROR_BUG; + } + } else { + ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size); + } + + if (ret > 0) { + avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size); + if (frame) { + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts; + } else { + avpkt->pts = s->next_pts; + } + if (avpkt->pts != AV_NOPTS_VALUE) + s->next_pts = avpkt->pts + avpkt->duration; + + avpkt->size = ret; + *got_packet_ptr = 1; + return 0; + } + + return ret; +} + +#define OFFSET(x) offsetof(TWOLAMEContext, x) +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "mode", "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"}, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE }, 0, 0, AE, "mode" }, + { "stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO }, 0, 0, AE, "mode" }, + { "joint_stereo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO }, 0, 0, AE, "mode" }, + { "dual_channel", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL }, 0, 0, AE, "mode" }, + { "mono", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO }, 0, 0, AE, "mode" }, + { "psymodel", "Psychoacoustic Model", OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE}, + { "energy_levels","enable energy levels", OFFSET(energy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "copyright", "set MPEG Audio Copyright flag", OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { "original", "set MPEG Audio Original flag", OFFSET(original), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AE}, + { NULL }, +}; + +static const AVClass libtwolame_class = { + .class_name = "libtwolame encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libtwolame_encoder = { + .name = "libtwolame", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP2, + .priv_data_size = sizeof(TWOLAMEContext), + .init = twolame_encode_init, + .encode2 = twolame_encode_frame, + .close = twolame_encode_close, + .capabilities = CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + 0 }, + .supported_samplerates = (const int[]){ 16000, 22050, 24000, 32000, 44100, 48000, 0 }, + .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"), + .priv_class = &libtwolame_class, +}; diff --git a/ffmpeg/libavcodec/libutvideo.h b/ffmpeg/libavcodec/libutvideo.h new file mode 100644 index 0000000..b35d19c --- /dev/null +++ b/ffmpeg/libavcodec/libutvideo.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011-2012 Derek Buitenhuis + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * version 2 of the License. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +/** + * @file + * Known FOURCCs: + * 'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA) + */ + +#ifndef AVCODEC_LIBUTVIDEO_H +#define AVCODEC_LIBUTVIDEO_H + +#include +#include +#include + +/* + * Ut Video version 12.0.0 changed the RGB format names and removed + * the _WIN names, so if the new names are absent, define them + * against the old names so compatibility with pre-v12 versions + * is maintained. + */ +#if !defined(UTVF_NFCC_BGR_BU) +#define UTVF_NFCC_BGR_BU UTVF_RGB24_WIN +#endif + +#if !defined(UTVF_NFCC_BGRA_BU) +#define UTVF_NFCC_BGRA_BU UTVF_RGB32_WIN +#endif + +typedef struct { + uint32_t version; + uint32_t original_format; + uint32_t frameinfo_size; + uint32_t flags; +} UtVideoExtra; + +typedef struct { + CCodec *codec; + unsigned int buf_size; + uint8_t *buffer; +} UtVideoContext; + +#endif /* AVCODEC_LIBUTVIDEO_H */ diff --git a/ffmpeg/libavcodec/libutvideodec.cpp b/ffmpeg/libavcodec/libutvideodec.cpp new file mode 100644 index 0000000..bc491e2 --- /dev/null +++ b/ffmpeg/libavcodec/libutvideodec.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2011 Derek Buitenhuis + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * version 2 of the License. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +/** + * @file + * Known FOURCCs: + * 'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA) + */ + +extern "C" { +#include "avcodec.h" +} + +#include "libutvideo.h" +#include "get_bits.h" + +static av_cold int utvideo_decode_init(AVCodecContext *avctx) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + UtVideoExtra info; + int format; + int begin_ret; + + if (avctx->extradata_size != 4*4) { + av_log(avctx, AV_LOG_ERROR, "Extradata size mismatch.\n"); + return -1; + } + + /* Read extradata */ + info.version = AV_RL32(avctx->extradata); + info.original_format = AV_RL32(avctx->extradata + 4); + info.frameinfo_size = AV_RL32(avctx->extradata + 8); + info.flags = AV_RL32(avctx->extradata + 12); + + /* Pick format based on FOURCC */ + switch (avctx->codec_tag) { + case MKTAG('U', 'L', 'Y', '0'): + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + format = UTVF_YV12; + break; + case MKTAG('U', 'L', 'Y', '2'): + avctx->pix_fmt = AV_PIX_FMT_YUYV422; + format = UTVF_YUY2; + break; + case MKTAG('U', 'L', 'R', 'G'): + avctx->pix_fmt = AV_PIX_FMT_BGR24; + format = UTVF_NFCC_BGR_BU; + break; + case MKTAG('U', 'L', 'R', 'A'): + avctx->pix_fmt = AV_PIX_FMT_RGB32; + format = UTVF_NFCC_BGRA_BU; + break; + default: + av_log(avctx, AV_LOG_ERROR, + "Not a Ut Video FOURCC: %X\n", avctx->codec_tag); + return -1; + } + + /* Only allocate the buffer once */ + utv->buf_size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + utv->buffer = (uint8_t *)av_malloc(utv->buf_size * sizeof(uint8_t)); + + if (utv->buffer == NULL) { + av_log(avctx, AV_LOG_ERROR, "Unable to allocate output buffer.\n"); + return -1; + } + + /* Allocate the output frame */ + avctx->coded_frame = avcodec_alloc_frame(); + + /* Ut Video only supports 8-bit */ + avctx->bits_per_raw_sample = 8; + + /* Is it interlaced? */ + avctx->coded_frame->interlaced_frame = info.flags & 0x800 ? 1 : 0; + + /* Apparently Ut Video doesn't store this info... */ + avctx->coded_frame->top_field_first = 1; + + /* + * Create a Ut Video instance. Since the function wants + * an "interface name" string, pass it the name of the lib. + */ + utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec"); + + /* Initialize Decoding */ + begin_ret = utv->codec->DecodeBegin(format, avctx->width, avctx->height, + CBGROSSWIDTH_WINDOWS, &info, sizeof(UtVideoExtra)); + + /* Check to see if the decoder initlized properly */ + if (begin_ret != 0) { + av_log(avctx, AV_LOG_ERROR, + "Could not initialize decoder: %d\n", begin_ret); + return -1; + } + + return 0; +} + +static int utvideo_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + AVFrame *pic = avctx->coded_frame; + int w = avctx->width, h = avctx->height; + + /* Set flags */ + pic->reference = 0; + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + + /* Decode the frame */ + utv->codec->DecodeFrame(utv->buffer, avpkt->data, true); + + /* Set the output data depending on the colorspace */ + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + pic->linesize[0] = w; + pic->linesize[1] = pic->linesize[2] = w / 2; + pic->data[0] = utv->buffer; + pic->data[2] = utv->buffer + (w * h); + pic->data[1] = pic->data[2] + (w * h / 4); + break; + case AV_PIX_FMT_YUYV422: + pic->linesize[0] = w * 2; + pic->data[0] = utv->buffer; + break; + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_RGB32: + /* Make the linesize negative, since Ut Video uses bottom-up BGR */ + pic->linesize[0] = -1 * w * (avctx->pix_fmt == AV_PIX_FMT_BGR24 ? 3 : 4); + pic->data[0] = utv->buffer + utv->buf_size + pic->linesize[0]; + break; + } + + *got_frame = 1; + *(AVFrame *)data = *pic; + + return avpkt->size; +} + +static av_cold int utvideo_decode_close(AVCodecContext *avctx) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + + /* Free output */ + av_freep(&avctx->coded_frame); + av_freep(&utv->buffer); + + /* Finish decoding and clean up the instance */ + utv->codec->DecodeEnd(); + CCodec::DeleteInstance(utv->codec); + + return 0; +} + +AVCodec ff_libutvideo_decoder = { + "libutvideo", + NULL_IF_CONFIG_SMALL("Ut Video"), + AVMEDIA_TYPE_VIDEO, + AV_CODEC_ID_UTVIDEO, + 0, //capabilities + NULL, //supported_framerates + NULL, //pix_fmts + NULL, //supported_samplerates + NULL, //sample_fmts + NULL, //channel_layouts + 0, //max_lowres + NULL, //priv_class + NULL, //profiles + sizeof(UtVideoContext), + NULL, //next + NULL, //init_thread_copy + NULL, //update_thread_context + NULL, //defaults + NULL, //init_static_data + utvideo_decode_init, + NULL, //encode + NULL, //encode2 + utvideo_decode_frame, + utvideo_decode_close, +}; diff --git a/ffmpeg/libavcodec/libutvideoenc.cpp b/ffmpeg/libavcodec/libutvideoenc.cpp new file mode 100644 index 0000000..07205f7 --- /dev/null +++ b/ffmpeg/libavcodec/libutvideoenc.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2012 Derek Buitenhuis + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * version 2 of the License. + * + * 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 + * General Public License for more details. + * + * You should have received a copy of the GNU 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 + */ + +/** + * @file + * Known FOURCCs: + * 'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA) + */ + +extern "C" { +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "internal.h" +} + +#include "libutvideo.h" +#include "put_bits.h" + +static av_cold int utvideo_encode_init(AVCodecContext *avctx) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + UtVideoExtra *info; + uint32_t flags, in_format; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + in_format = UTVF_YV12; + avctx->bits_per_coded_sample = 12; + avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); + break; + case AV_PIX_FMT_YUYV422: + in_format = UTVF_YUYV; + avctx->bits_per_coded_sample = 16; + avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); + break; + case AV_PIX_FMT_BGR24: + in_format = UTVF_NFCC_BGR_BU; + avctx->bits_per_coded_sample = 24; + avctx->codec_tag = MKTAG('U', 'L', 'R', 'G'); + break; + case AV_PIX_FMT_RGB32: + in_format = UTVF_NFCC_BGRA_BU; + avctx->bits_per_coded_sample = 32; + avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); + break; + default: + return AVERROR(EINVAL); + } + + /* Check before we alloc anything */ + if (avctx->prediction_method != 0 && avctx->prediction_method != 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid prediction method.\n"); + return AVERROR(EINVAL); + } + + flags = ((avctx->prediction_method + 1) << 8) | (avctx->thread_count - 1); + + avctx->priv_data = utv; + avctx->coded_frame = avcodec_alloc_frame(); + + /* Alloc extradata buffer */ + info = (UtVideoExtra *)av_malloc(sizeof(*info)); + + if (info == NULL) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata buffer.\n"); + return AVERROR(ENOMEM); + } + + /* + * We use this buffer to hold the data that Ut Video returns, + * since we cannot decode planes separately with it. + */ + utv->buf_size = avpicture_get_size(avctx->pix_fmt, + avctx->width, avctx->height); + utv->buffer = (uint8_t *)av_malloc(utv->buf_size); + + if (utv->buffer == NULL) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate output buffer.\n"); + return AVERROR(ENOMEM); + } + + /* + * Create a Ut Video instance. Since the function wants + * an "interface name" string, pass it the name of the lib. + */ + utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec"); + + /* Initialize encoder */ + utv->codec->EncodeBegin(in_format, avctx->width, avctx->height, + CBGROSSWIDTH_WINDOWS); + + /* Get extradata from encoder */ + avctx->extradata_size = utv->codec->EncodeGetExtraDataSize(); + utv->codec->EncodeGetExtraData(info, avctx->extradata_size, in_format, + avctx->width, avctx->height, + CBGROSSWIDTH_WINDOWS); + avctx->extradata = (uint8_t *)info; + + /* Set flags */ + utv->codec->SetState(&flags, sizeof(flags)); + + return 0; +} + +static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + int w = avctx->width, h = avctx->height; + int ret, rgb_size, i; + bool keyframe; + uint8_t *y, *u, *v; + uint8_t *dst; + + /* Alloc buffer */ + if ((ret = ff_alloc_packet2(avctx, pkt, utv->buf_size)) < 0) + return ret; + + dst = pkt->data; + + /* Move input if needed data into Ut Video friendly buffer */ + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUV420P: + y = utv->buffer; + u = y + w * h; + v = u + w * h / 4; + for (i = 0; i < h; i++) { + memcpy(y, pic->data[0] + i * pic->linesize[0], w); + y += w; + } + for (i = 0; i < h / 2; i++) { + memcpy(u, pic->data[2] + i * pic->linesize[2], w >> 1); + memcpy(v, pic->data[1] + i * pic->linesize[1], w >> 1); + u += w >> 1; + v += w >> 1; + } + break; + case AV_PIX_FMT_YUYV422: + for (i = 0; i < h; i++) + memcpy(utv->buffer + i * (w << 1), + pic->data[0] + i * pic->linesize[0], w << 1); + break; + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_RGB32: + /* Ut Video takes bottom-up BGR */ + rgb_size = avctx->pix_fmt == AV_PIX_FMT_BGR24 ? 3 : 4; + for (i = 0; i < h; i++) + memcpy(utv->buffer + (h - i - 1) * w * rgb_size, + pic->data[0] + i * pic->linesize[0], + w * rgb_size); + break; + default: + return AVERROR(EINVAL); + } + + /* Encode frame */ + pkt->size = utv->codec->EncodeFrame(dst, &keyframe, utv->buffer); + + if (!pkt->size) { + av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed!\n"); + return AVERROR_INVALIDDATA; + } + + /* + * Ut Video is intra-only and every frame is a keyframe, + * and the API always returns true. In case something + * durastic changes in the future, such as inter support, + * assert that this is true. + */ + av_assert2(keyframe == true); + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int utvideo_encode_close(AVCodecContext *avctx) +{ + UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; + + av_freep(&avctx->coded_frame); + av_freep(&avctx->extradata); + av_freep(&utv->buffer); + + utv->codec->EncodeEnd(); + CCodec::DeleteInstance(utv->codec); + + return 0; +} + +AVCodec ff_libutvideo_encoder = { + "libutvideo", + NULL_IF_CONFIG_SMALL("Ut Video"), + AVMEDIA_TYPE_VIDEO, + AV_CODEC_ID_UTVIDEO, + CODEC_CAP_AUTO_THREADS | CODEC_CAP_LOSSLESS, + NULL, /* supported_framerates */ + (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUYV422, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE + }, + NULL, /* supported_samplerates */ + NULL, /* sample_fmts */ + NULL, /* channel_layouts */ + 0, /* max_lowres */ + NULL, /* priv_class */ + NULL, /* profiles */ + sizeof(UtVideoContext), + NULL, /* next */ + NULL, /* init_thread_copy */ + NULL, /* update_thread_context */ + NULL, /* defaults */ + NULL, /* init_static_data */ + utvideo_encode_init, + NULL, /* encode */ + utvideo_encode_frame, + NULL, /* decode */ + utvideo_encode_close, + NULL, /* flush */ +}; diff --git a/ffmpeg/libavcodec/libvo-aacenc.c b/ffmpeg/libavcodec/libvo-aacenc.c new file mode 100644 index 0000000..4f4cbe7 --- /dev/null +++ b/ffmpeg/libavcodec/libvo-aacenc.c @@ -0,0 +1,200 @@ +/* + * AAC encoder wrapper + * Copyright (c) 2010 Martin Storsjo + * + * 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 + +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" +#include "mpeg4audio.h" + +#define FRAME_SIZE 1024 +#define ENC_DELAY 1600 + +typedef struct AACContext { + VO_AUDIO_CODECAPI codec_api; + VO_HANDLE handle; + VO_MEM_OPERATOR mem_operator; + VO_CODEC_INIT_USERDATA user_data; + VO_PBYTE end_buffer; + AudioFrameQueue afq; + int last_frame; + int last_samples; +} AACContext; + + +static int aac_encode_close(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + + s->codec_api.Uninit(s->handle); + av_freep(&avctx->extradata); + ff_af_queue_close(&s->afq); + av_freep(&s->end_buffer); + + return 0; +} + +static av_cold int aac_encode_init(AVCodecContext *avctx) +{ + AACContext *s = avctx->priv_data; + AACENC_PARAM params = { 0 }; + int index, ret; + + avctx->frame_size = FRAME_SIZE; + avctx->delay = ENC_DELAY; + s->last_frame = 2; + ff_af_queue_init(avctx, &s->afq); + + s->end_buffer = av_mallocz(avctx->frame_size * avctx->channels * 2); + if (!s->end_buffer) { + ret = AVERROR(ENOMEM); + goto error; + } + + voGetAACEncAPI(&s->codec_api); + + s->mem_operator.Alloc = cmnMemAlloc; + s->mem_operator.Copy = cmnMemCopy; + s->mem_operator.Free = cmnMemFree; + s->mem_operator.Set = cmnMemSet; + s->mem_operator.Check = cmnMemCheck; + s->user_data.memflag = VO_IMF_USERMEMOPERATOR; + s->user_data.memData = &s->mem_operator; + s->codec_api.Init(&s->handle, VO_AUDIO_CodingAAC, &s->user_data); + + params.sampleRate = avctx->sample_rate; + params.bitRate = avctx->bit_rate; + params.nChannels = avctx->channels; + params.adtsUsed = !(avctx->flags & CODEC_FLAG_GLOBAL_HEADER); + if (s->codec_api.SetParam(s->handle, VO_PID_AAC_ENCPARAM, ¶ms) + != VO_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unable to set encoding parameters\n"); + ret = AVERROR(EINVAL); + goto error; + } + + for (index = 0; index < 16; index++) + if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[index]) + break; + if (index == 16) { + av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate %d\n", + avctx->sample_rate); + ret = AVERROR(ENOSYS); + goto error; + } + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + avctx->extradata_size = 2; + avctx->extradata = av_mallocz(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + ret = AVERROR(ENOMEM); + goto error; + } + + avctx->extradata[0] = 0x02 << 3 | index >> 1; + avctx->extradata[1] = (index & 0x01) << 7 | avctx->channels << 3; + } + return 0; +error: + aac_encode_close(avctx); + return ret; +} + +static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AACContext *s = avctx->priv_data; + VO_CODECBUFFER input = { 0 }, output = { 0 }; + VO_AUDIO_OUTPUTINFO output_info = { { 0 } }; + VO_PBYTE samples; + int ret; + + /* handle end-of-stream small frame and flushing */ + if (!frame) { + if (s->last_frame <= 0) + return 0; + if (s->last_samples > 0 && s->last_samples < ENC_DELAY - FRAME_SIZE) { + s->last_samples = 0; + s->last_frame--; + } + s->last_frame--; + memset(s->end_buffer, 0, 2 * avctx->channels * avctx->frame_size); + samples = s->end_buffer; + } else { + if (frame->nb_samples < avctx->frame_size) { + s->last_samples = frame->nb_samples; + memcpy(s->end_buffer, frame->data[0], 2 * avctx->channels * frame->nb_samples); + samples = s->end_buffer; + } else { + samples = (VO_PBYTE)frame->data[0]; + } + /* add current frame to the queue */ + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, FFMAX(8192, 768 * avctx->channels))) < 0) + return ret; + + input.Buffer = samples; + input.Length = 2 * avctx->channels * avctx->frame_size; + output.Buffer = avpkt->data; + output.Length = avpkt->size; + + s->codec_api.SetInputData(s->handle, &input); + if (s->codec_api.GetOutputData(s->handle, &output, &output_info) + != VO_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unable to encode frame\n"); + return AVERROR(EINVAL); + } + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = output.Length; + *got_packet_ptr = 1; + return 0; +} + +/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build + * failures */ +static const int mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + +AVCodec ff_libvo_aacenc_encoder = { + .name = "libvo_aacenc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(AACContext), + .init = aac_encode_init, + .encode2 = aac_encode_frame, + .close = aac_encode_close, + .supported_samplerates = mpeg4audio_sample_rates, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Android VisualOn AAC (Advanced Audio Coding)"), +}; diff --git a/ffmpeg/libavcodec/libvo-amrwbenc.c b/ffmpeg/libavcodec/libvo-amrwbenc.c new file mode 100644 index 0000000..a068cd0 --- /dev/null +++ b/ffmpeg/libavcodec/libvo-amrwbenc.c @@ -0,0 +1,152 @@ +/* + * AMR Audio encoder stub + * Copyright (c) 2003 the ffmpeg project + * + * 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 +#include + +#include "libavutil/avstring.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" + +#define MAX_PACKET_SIZE (1 + (477 + 7) / 8) + +typedef struct AMRWBContext { + AVClass *av_class; + void *state; + int mode; + int last_bitrate; + int allow_dtx; +} AMRWBContext; + +static const AVOption options[] = { + { "dtx", "Allow DTX (generate comfort noise)", offsetof(AMRWBContext, allow_dtx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { NULL } +}; + +static const AVClass class = { + "libvo_amrwbenc", av_default_item_name, options, LIBAVUTIL_VERSION_INT +}; + +static int get_wb_bitrate_mode(int bitrate, void *log_ctx) +{ + /* make the correspondance between bitrate and mode */ + static const int rates[] = { 6600, 8850, 12650, 14250, 15850, 18250, + 19850, 23050, 23850 }; + int i, best = -1, min_diff = 0; + char log_buf[200]; + + for (i = 0; i < 9; i++) { + if (rates[i] == bitrate) + return i; + if (best < 0 || abs(rates[i] - bitrate) < min_diff) { + best = i; + min_diff = abs(rates[i] - bitrate); + } + } + /* no bitrate matching exactly, log a warning */ + snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of "); + for (i = 0; i < 9; i++) + av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i] / 1000.f); + av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best] / 1000.f); + av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf); + + return best; +} + +static av_cold int amr_wb_encode_init(AVCodecContext *avctx) +{ + AMRWBContext *s = avctx->priv_data; + + if (avctx->sample_rate != 16000 && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + av_log(avctx, AV_LOG_ERROR, "Only 16000Hz sample rate supported\n"); + return AVERROR(ENOSYS); + } + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); + return AVERROR(ENOSYS); + } + + s->mode = get_wb_bitrate_mode(avctx->bit_rate, avctx); + s->last_bitrate = avctx->bit_rate; + + avctx->frame_size = 320; + avctx->delay = 80; + + s->state = E_IF_init(); + + return 0; +} + +static int amr_wb_encode_close(AVCodecContext *avctx) +{ + AMRWBContext *s = avctx->priv_data; + + E_IF_exit(s->state); + return 0; +} + +static int amr_wb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + AMRWBContext *s = avctx->priv_data; + const int16_t *samples = (const int16_t *)frame->data[0]; + int size, ret; + + if ((ret = ff_alloc_packet2(avctx, avpkt, MAX_PACKET_SIZE)) < 0) + return ret; + + if (s->last_bitrate != avctx->bit_rate) { + s->mode = get_wb_bitrate_mode(avctx->bit_rate, avctx); + s->last_bitrate = avctx->bit_rate; + } + size = E_IF_encode(s->state, s->mode, samples, avpkt->data, s->allow_dtx); + if (size <= 0 || size > MAX_PACKET_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Error encoding frame\n"); + return AVERROR(EINVAL); + } + + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + + avpkt->size = size; + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_libvo_amrwbenc_encoder = { + .name = "libvo_amrwbenc", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AMR_WB, + .priv_data_size = sizeof(AMRWBContext), + .init = amr_wb_encode_init, + .encode2 = amr_wb_encode_frame, + .close = amr_wb_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Android VisualOn AMR-WB " + "(Adaptive Multi-Rate Wide-Band)"), + .priv_class = &class, +}; diff --git a/ffmpeg/libavcodec/libvorbisdec.c b/ffmpeg/libavcodec/libvorbisdec.c new file mode 100644 index 0000000..c4142cd --- /dev/null +++ b/ffmpeg/libavcodec/libvorbisdec.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2002 Mark Hills + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct OggVorbisDecContext { + vorbis_info vi; /**< vorbis_info used during init */ + vorbis_dsp_state vd; /**< DSP state used for analysis */ + vorbis_block vb; /**< vorbis_block used for analysis */ + vorbis_comment vc; /**< VorbisComment info */ + ogg_packet op; /**< ogg packet */ +} OggVorbisDecContext; + +static int oggvorbis_decode_init(AVCodecContext *avccontext) { + OggVorbisDecContext *context = avccontext->priv_data ; + uint8_t *p= avccontext->extradata; + int i, hsizes[3]; + unsigned char *headers[3], *extradata = avccontext->extradata; + + vorbis_info_init(&context->vi) ; + vorbis_comment_init(&context->vc) ; + + if(! avccontext->extradata_size || ! p) { + av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n"); + return -1; + } + + if(p[0] == 0 && p[1] == 30) { + for(i = 0; i < 3; i++){ + hsizes[i] = bytestream_get_be16((const uint8_t **)&p); + headers[i] = p; + p += hsizes[i]; + } + } else if(*p == 2) { + unsigned int offset = 1; + p++; + for(i=0; i<2; i++) { + hsizes[i] = 0; + while((*p == 0xFF) && (offset < avccontext->extradata_size)) { + hsizes[i] += 0xFF; + offset++; + p++; + } + if(offset >= avccontext->extradata_size - 1) { + av_log(avccontext, AV_LOG_ERROR, + "vorbis header sizes damaged\n"); + return -1; + } + hsizes[i] += *p; + offset++; + p++; + } + hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset; +#if 0 + av_log(avccontext, AV_LOG_DEBUG, + "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n", + hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size); +#endif + headers[0] = extradata + offset; + headers[1] = extradata + offset + hsizes[0]; + headers[2] = extradata + offset + hsizes[0] + hsizes[1]; + } else { + av_log(avccontext, AV_LOG_ERROR, + "vorbis initial header len is wrong: %d\n", *p); + return -1; + } + + for(i=0; i<3; i++){ + context->op.b_o_s= i==0; + context->op.bytes = hsizes[i]; + context->op.packet = headers[i]; + if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){ + av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1); + return -1; + } + } + + avccontext->channels = context->vi.channels; + avccontext->sample_rate = context->vi.rate; + avccontext->sample_fmt = AV_SAMPLE_FMT_S16; + avccontext->time_base= (AVRational){1, avccontext->sample_rate}; + + vorbis_synthesis_init(&context->vd, &context->vi); + vorbis_block_init(&context->vd, &context->vb); + + return 0 ; +} + + +static inline int conv(int samples, float **pcm, char *buf, int channels) { + int i, j; + ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ; + float *mono ; + + for(i = 0 ; i < channels ; i++){ + ptr = &data[i]; + mono = pcm[i] ; + + for(j = 0 ; j < samples ; j++) { + *ptr = av_clip_int16(mono[j] * 32767.f); + ptr += channels; + } + } + + return 0 ; +} + +static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + OggVorbisDecContext *context = avccontext->priv_data ; + AVFrame *frame = data; + float **pcm ; + ogg_packet *op= &context->op; + int samples, total_samples, total_bytes; + int ret; + int16_t *output; + + if(!avpkt->size){ + //FIXME flush + return 0; + } + + frame->nb_samples = 8192*4; + if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0) + return ret; + output = (int16_t *)frame->data[0]; + + + op->packet = avpkt->data; + op->bytes = avpkt->size; + +// av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %"PRId64" %"PRId64" %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate); + +/* for(i=0; ibytes; i++) + av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]); + av_log(avccontext, AV_LOG_DEBUG, "\n");*/ + + if(vorbis_synthesis(&context->vb, op) == 0) + vorbis_synthesis_blockin(&context->vd, &context->vb) ; + + total_samples = 0 ; + total_bytes = 0 ; + + while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) { + conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ; + total_bytes += samples * 2 * context->vi.channels ; + total_samples += samples ; + vorbis_synthesis_read(&context->vd, samples) ; + } + + frame->nb_samples = total_samples; + *got_frame_ptr = 1; + return avpkt->size; +} + + +static int oggvorbis_decode_close(AVCodecContext *avccontext) { + OggVorbisDecContext *context = avccontext->priv_data ; + + vorbis_info_clear(&context->vi) ; + vorbis_comment_clear(&context->vc) ; + + return 0 ; +} + + +AVCodec ff_libvorbis_decoder = { + .name = "libvorbis", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VORBIS, + .priv_data_size = sizeof(OggVorbisDecContext), + .init = oggvorbis_decode_init, + .decode = oggvorbis_decode_frame, + .close = oggvorbis_decode_close, + .capabilities = CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("libvorbis"), +}; diff --git a/ffmpeg/libavcodec/libvorbisenc.c b/ffmpeg/libavcodec/libvorbisenc.c new file mode 100644 index 0000000..d3f86cc --- /dev/null +++ b/ffmpeg/libavcodec/libvorbisenc.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2002 Mark Hills + * + * 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 "libavutil/avassert.h" +#include "libavutil/fifo.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" +#include "vorbis.h" +#include "vorbis_parser.h" + + +/* Number of samples the user should send in each call. + * This value is used because it is the LCD of all possible frame sizes, so + * an output packet will always start at the same point as one of the input + * packets. + */ +#define OGGVORBIS_FRAME_SIZE 64 + +#define BUFFER_SIZE (1024 * 64) + +typedef struct OggVorbisEncContext { + AVClass *av_class; /**< class for AVOptions */ + AVFrame frame; + vorbis_info vi; /**< vorbis_info used during init */ + vorbis_dsp_state vd; /**< DSP state used for analysis */ + vorbis_block vb; /**< vorbis_block used for analysis */ + AVFifoBuffer *pkt_fifo; /**< output packet buffer */ + int eof; /**< end-of-file flag */ + int dsp_initialized; /**< vd has been initialized */ + vorbis_comment vc; /**< VorbisComment info */ + double iblock; /**< impulse block bias option */ + VorbisParseContext vp; /**< parse context to get durations */ + AudioFrameQueue afq; /**< frame queue for timestamps */ +} OggVorbisEncContext; + +static const AVOption options[] = { + { "iblock", "Sets the impulse block bias", offsetof(OggVorbisEncContext, iblock), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, -15, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { NULL } +}; + +static const AVCodecDefault defaults[] = { + { "b", "0" }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "libvorbis", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int vorbis_error_to_averror(int ov_err) +{ + switch (ov_err) { + case OV_EFAULT: return AVERROR_BUG; + case OV_EINVAL: return AVERROR(EINVAL); + case OV_EIMPL: return AVERROR(EINVAL); + default: return AVERROR_UNKNOWN; + } +} + +static av_cold int oggvorbis_init_encoder(vorbis_info *vi, + AVCodecContext *avctx) +{ + OggVorbisEncContext *s = avctx->priv_data; + double cfreq; + int ret; + + if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) { + /* variable bitrate + * NOTE: we use the oggenc range of -1 to 10 for global_quality for + * user convenience, but libvorbis uses -0.1 to 1.0. + */ + float q = avctx->global_quality / (float)FF_QP2LAMBDA; + /* default to 3 if the user did not set quality or bitrate */ + if (!(avctx->flags & CODEC_FLAG_QSCALE)) + q = 3.0; + if ((ret = vorbis_encode_setup_vbr(vi, avctx->channels, + avctx->sample_rate, + q / 10.0))) + goto error; + } else { + int minrate = avctx->rc_min_rate > 0 ? avctx->rc_min_rate : -1; + int maxrate = avctx->rc_max_rate > 0 ? avctx->rc_max_rate : -1; + + /* average bitrate */ + if ((ret = vorbis_encode_setup_managed(vi, avctx->channels, + avctx->sample_rate, maxrate, + avctx->bit_rate, minrate))) + goto error; + + /* variable bitrate by estimate, disable slow rate management */ + if (minrate == -1 && maxrate == -1) + if ((ret = vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, NULL))) + goto error; /* should not happen */ + } + + /* cutoff frequency */ + if (avctx->cutoff > 0) { + cfreq = avctx->cutoff / 1000.0; + if ((ret = vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))) + goto error; /* should not happen */ + } + + /* impulse block bias */ + if (s->iblock) { + if ((ret = vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &s->iblock))) + goto error; + } + + if (avctx->channels == 3 && + avctx->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) || + avctx->channels == 4 && + avctx->channel_layout != AV_CH_LAYOUT_2_2 && + avctx->channel_layout != AV_CH_LAYOUT_QUAD || + avctx->channels == 5 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT0 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT0_BACK || + avctx->channels == 6 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT1 && + avctx->channel_layout != AV_CH_LAYOUT_5POINT1_BACK || + avctx->channels == 7 && + avctx->channel_layout != (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) || + avctx->channels == 8 && + avctx->channel_layout != AV_CH_LAYOUT_7POINT1) { + if (avctx->channel_layout) { + char name[32]; + av_get_channel_layout_string(name, sizeof(name), avctx->channels, + avctx->channel_layout); + av_log(avctx, AV_LOG_ERROR, "%s not supported by Vorbis: " + "output stream will have incorrect " + "channel layout.\n", name); + } else { + av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The encoder " + "will use Vorbis channel layout for " + "%d channels.\n", avctx->channels); + } + } + + if ((ret = vorbis_encode_setup_init(vi))) + goto error; + + return 0; +error: + return vorbis_error_to_averror(ret); +} + +/* How many bytes are needed for a buffer of length 'l' */ +static int xiph_len(int l) +{ + return 1 + l / 255 + l; +} + +static av_cold int oggvorbis_encode_close(AVCodecContext *avctx) +{ + OggVorbisEncContext *s = avctx->priv_data; + + /* notify vorbisenc this is EOF */ + if (s->dsp_initialized) + vorbis_analysis_wrote(&s->vd, 0); + + vorbis_block_clear(&s->vb); + vorbis_dsp_clear(&s->vd); + vorbis_info_clear(&s->vi); + + av_fifo_free(s->pkt_fifo); + ff_af_queue_close(&s->afq); + av_freep(&avctx->extradata); + + return 0; +} + +static av_cold int oggvorbis_encode_init(AVCodecContext *avctx) +{ + OggVorbisEncContext *s = avctx->priv_data; + ogg_packet header, header_comm, header_code; + uint8_t *p; + unsigned int offset; + int ret; + + vorbis_info_init(&s->vi); + if ((ret = oggvorbis_init_encoder(&s->vi, avctx))) { + av_log(avctx, AV_LOG_ERROR, "encoder setup failed\n"); + goto error; + } + if ((ret = vorbis_analysis_init(&s->vd, &s->vi))) { + av_log(avctx, AV_LOG_ERROR, "analysis init failed\n"); + ret = vorbis_error_to_averror(ret); + goto error; + } + s->dsp_initialized = 1; + if ((ret = vorbis_block_init(&s->vd, &s->vb))) { + av_log(avctx, AV_LOG_ERROR, "dsp init failed\n"); + ret = vorbis_error_to_averror(ret); + goto error; + } + + vorbis_comment_init(&s->vc); + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) + vorbis_comment_add_tag(&s->vc, "encoder", LIBAVCODEC_IDENT); + + if ((ret = vorbis_analysis_headerout(&s->vd, &s->vc, &header, &header_comm, + &header_code))) { + ret = vorbis_error_to_averror(ret); + goto error; + } + + avctx->extradata_size = 1 + xiph_len(header.bytes) + + xiph_len(header_comm.bytes) + + header_code.bytes; + p = avctx->extradata = av_malloc(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!p) { + ret = AVERROR(ENOMEM); + goto error; + } + p[0] = 2; + offset = 1; + offset += av_xiphlacing(&p[offset], header.bytes); + offset += av_xiphlacing(&p[offset], header_comm.bytes); + memcpy(&p[offset], header.packet, header.bytes); + offset += header.bytes; + memcpy(&p[offset], header_comm.packet, header_comm.bytes); + offset += header_comm.bytes; + memcpy(&p[offset], header_code.packet, header_code.bytes); + offset += header_code.bytes; + av_assert0(offset == avctx->extradata_size); + + if ((ret = avpriv_vorbis_parse_extradata(avctx, &s->vp)) < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid extradata\n"); + return ret; + } + + vorbis_comment_clear(&s->vc); + + avctx->frame_size = OGGVORBIS_FRAME_SIZE; + ff_af_queue_init(avctx, &s->afq); + + s->pkt_fifo = av_fifo_alloc(BUFFER_SIZE); + if (!s->pkt_fifo) { + ret = AVERROR(ENOMEM); + goto error; + } + + return 0; +error: + oggvorbis_encode_close(avctx); + return ret; +} + +static int oggvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + OggVorbisEncContext *s = avctx->priv_data; + ogg_packet op; + int ret, duration; + + /* send samples to libvorbis */ + if (frame) { + const int samples = frame->nb_samples; + float **buffer; + int c, channels = s->vi.channels; + + buffer = vorbis_analysis_buffer(&s->vd, samples); + for (c = 0; c < channels; c++) { + int co = (channels > 8) ? c : + ff_vorbis_encoding_channel_layout_offsets[channels - 1][c]; + memcpy(buffer[c], frame->extended_data[co], + samples * sizeof(*buffer[c])); + } + if ((ret = vorbis_analysis_wrote(&s->vd, samples)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n"); + return vorbis_error_to_averror(ret); + } + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } else { + if (!s->eof) + if ((ret = vorbis_analysis_wrote(&s->vd, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n"); + return vorbis_error_to_averror(ret); + } + s->eof = 1; + } + + /* retrieve available packets from libvorbis */ + while ((ret = vorbis_analysis_blockout(&s->vd, &s->vb)) == 1) { + if ((ret = vorbis_analysis(&s->vb, NULL)) < 0) + break; + if ((ret = vorbis_bitrate_addblock(&s->vb)) < 0) + break; + + /* add any available packets to the output packet buffer */ + while ((ret = vorbis_bitrate_flushpacket(&s->vd, &op)) == 1) { + if (av_fifo_space(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) { + av_log(avctx, AV_LOG_ERROR, "packet buffer is too small\n"); + return AVERROR_BUG; + } + av_fifo_generic_write(s->pkt_fifo, &op, sizeof(ogg_packet), NULL); + av_fifo_generic_write(s->pkt_fifo, op.packet, op.bytes, NULL); + } + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "error getting available packets\n"); + break; + } + } + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "error getting available packets\n"); + return vorbis_error_to_averror(ret); + } + + /* check for available packets */ + if (av_fifo_size(s->pkt_fifo) < sizeof(ogg_packet)) + return 0; + + av_fifo_generic_read(s->pkt_fifo, &op, sizeof(ogg_packet), NULL); + + if ((ret = ff_alloc_packet2(avctx, avpkt, op.bytes)) < 0) + return ret; + av_fifo_generic_read(s->pkt_fifo, avpkt->data, op.bytes, NULL); + + avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos); + + duration = avpriv_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size); + if (duration > 0) { + /* we do not know encoder delay until we get the first packet from + * libvorbis, so we have to update the AudioFrameQueue counts */ + if (!avctx->delay && s->afq.frames) { + avctx->delay = duration; + av_assert0(!s->afq.remaining_delay); + s->afq.frames->duration += duration; + s->afq.frames->pts -= duration; + s->afq.remaining_samples += duration; + } + ff_af_queue_remove(&s->afq, duration, &avpkt->pts, &avpkt->duration); + } + + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_libvorbis_encoder = { + .name = "libvorbis", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VORBIS, + .priv_data_size = sizeof(OggVorbisEncContext), + .init = oggvorbis_encode_init, + .encode2 = oggvorbis_encode_frame, + .close = oggvorbis_encode_close, + .capabilities = CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libvorbis"), + .priv_class = &class, + .defaults = defaults, +}; diff --git a/ffmpeg/libavcodec/libvpxdec.c b/ffmpeg/libavcodec/libvpxdec.c new file mode 100644 index 0000000..5e80a9f --- /dev/null +++ b/ffmpeg/libavcodec/libvpxdec.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2010, Google, Inc. + * + * 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 + */ + +/** + * @file + * VP8 decoder support via libvpx + */ + +#define VPX_CODEC_DISABLE_COMPAT 1 +#include +#include + +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct VP8DecoderContext { + struct vpx_codec_ctx decoder; +} VP8Context; + +static av_cold int vpx_init(AVCodecContext *avctx, + const struct vpx_codec_iface *iface) +{ + VP8Context *ctx = avctx->priv_data; + struct vpx_codec_dec_cfg deccfg = { + /* token partitions+1 would be a decent choice */ + .threads = FFMIN(avctx->thread_count, 16) + }; + + av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); + av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); + + if (vpx_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != VPX_CODEC_OK) { + const char *error = vpx_codec_error(&ctx->decoder); + av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n", + error); + return AVERROR(EINVAL); + } + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + return 0; +} + +static int vp8_decode(AVCodecContext *avctx, + void *data, int *got_frame, AVPacket *avpkt) +{ + VP8Context *ctx = avctx->priv_data; + AVFrame *picture = data; + const void *iter = NULL; + struct vpx_image *img; + int ret; + + if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) != + VPX_CODEC_OK) { + const char *error = vpx_codec_error(&ctx->decoder); + const char *detail = vpx_codec_error_detail(&ctx->decoder); + + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error); + if (detail) + av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", + detail); + return AVERROR_INVALIDDATA; + } + + if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) { + if (img->fmt != VPX_IMG_FMT_I420) { + av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n", + img->fmt); + return AVERROR_INVALIDDATA; + } + + if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) { + av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", + avctx->width, avctx->height, img->d_w, img->d_h); + if (av_image_check_size(img->d_w, img->d_h, 0, avctx)) + return AVERROR_INVALIDDATA; + avcodec_set_dimensions(avctx, img->d_w, img->d_h); + } + if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) + return ret; + av_image_copy(picture->data, picture->linesize, img->planes, + img->stride, avctx->pix_fmt, img->d_w, img->d_h); + *got_frame = 1; + } + return avpkt->size; +} + +static av_cold int vp8_free(AVCodecContext *avctx) +{ + VP8Context *ctx = avctx->priv_data; + vpx_codec_destroy(&ctx->decoder); + return 0; +} + +#if CONFIG_LIBVPX_VP8_DECODER +static av_cold int vp8_init(AVCodecContext *avctx) +{ + return vpx_init(avctx, &vpx_codec_vp8_dx_algo); +} + +AVCodec ff_libvpx_vp8_decoder = { + .name = "libvpx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP8, + .priv_data_size = sizeof(VP8Context), + .init = vp8_init, + .close = vp8_free, + .decode = vp8_decode, + .capabilities = CODEC_CAP_AUTO_THREADS | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), +}; +#endif /* CONFIG_LIBVPX_VP8_DECODER */ + +#if CONFIG_LIBVPX_VP9_DECODER +static av_cold int vp9_init(AVCodecContext *avctx) +{ + return vpx_init(avctx, &vpx_codec_vp9_dx_algo); +} + +AVCodec ff_libvpx_vp9_decoder = { + .name = "libvpx-vp9", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .priv_data_size = sizeof(VP8Context), + .init = vp9_init, + .close = vp8_free, + .decode = vp8_decode, + .capabilities = CODEC_CAP_AUTO_THREADS | CODEC_CAP_EXPERIMENTAL, + .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), +}; +#endif /* CONFIG_LIBVPX_VP9_DECODER */ diff --git a/ffmpeg/libavcodec/libvpxenc.c b/ffmpeg/libavcodec/libvpxenc.c new file mode 100644 index 0000000..4f1adb8 --- /dev/null +++ b/ffmpeg/libavcodec/libvpxenc.c @@ -0,0 +1,729 @@ +/* + * Copyright (c) 2010, Google, Inc. + * + * 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 + */ + +/** + * @file + * VP8 encoder support via libvpx + */ + +#define VPX_DISABLE_CTRL_TYPECHECKS 1 +#define VPX_CODEC_DISABLE_COMPAT 1 +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/avassert.h" +#include "libavutil/base64.h" +#include "libavutil/common.h" +#include "libavutil/mathematics.h" +#include "libavutil/opt.h" + +/** + * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. + * One encoded frame returned from the library. + */ +struct FrameListData { + void *buf; /**< compressed data buffer */ + size_t sz; /**< length of compressed data */ + int64_t pts; /**< time stamp to show frame + (in timebase units) */ + unsigned long duration; /**< duration to show frame + (in timebase units) */ + uint32_t flags; /**< flags for this frame */ + uint64_t sse[4]; + int have_sse; /**< true if we have pending sse[] */ + uint64_t frame_number; + struct FrameListData *next; +}; + +typedef struct VP8EncoderContext { + AVClass *class; + struct vpx_codec_ctx encoder; + struct vpx_image rawimg; + struct vpx_fixed_buf twopass_stats; + int deadline; //i.e., RT/GOOD/BEST + uint64_t sse[4]; + int have_sse; /**< true if we have pending sse[] */ + uint64_t frame_number; + struct FrameListData *coded_frame_list; + + int cpu_used; + /** + * VP8 specific flags, see VP8F_* below. + */ + int flags; +#define VP8F_ERROR_RESILIENT 0x00000001 ///< Enable measures appropriate for streaming over lossy links +#define VP8F_AUTO_ALT_REF 0x00000002 ///< Enable automatic alternate reference frame generation + + int auto_alt_ref; + + int arnr_max_frames; + int arnr_strength; + int arnr_type; + + int lag_in_frames; + int error_resilient; + int crf; + int max_intra_rate; +} VP8Context; + +/** String mappings for enum vp8e_enc_control_id */ +static const char *const ctlidstr[] = { + [VP8E_UPD_ENTROPY] = "VP8E_UPD_ENTROPY", + [VP8E_UPD_REFERENCE] = "VP8E_UPD_REFERENCE", + [VP8E_USE_REFERENCE] = "VP8E_USE_REFERENCE", + [VP8E_SET_ROI_MAP] = "VP8E_SET_ROI_MAP", + [VP8E_SET_ACTIVEMAP] = "VP8E_SET_ACTIVEMAP", + [VP8E_SET_SCALEMODE] = "VP8E_SET_SCALEMODE", + [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED", + [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF", + [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY", + [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS", + [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD", + [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS", + [VP8E_GET_LAST_QUANTIZER] = "VP8E_GET_LAST_QUANTIZER", + [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", + [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", + [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", + [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", + [VP8E_SET_MAX_INTRA_BITRATE_PCT] = "VP8E_SET_MAX_INTRA_BITRATE_PCT", +}; + +static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) +{ + VP8Context *ctx = avctx->priv_data; + const char *error = vpx_codec_error(&ctx->encoder); + const char *detail = vpx_codec_error_detail(&ctx->encoder); + + av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error); + if (detail) + av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail); +} + +static av_cold void dump_enc_cfg(AVCodecContext *avctx, + const struct vpx_codec_enc_cfg *cfg) +{ + int width = -30; + int level = AV_LOG_DEBUG; + + av_log(avctx, level, "vpx_codec_enc_cfg\n"); + av_log(avctx, level, "generic settings\n" + " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" + " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", + width, "g_usage:", cfg->g_usage, + width, "g_threads:", cfg->g_threads, + width, "g_profile:", cfg->g_profile, + width, "g_w:", cfg->g_w, + width, "g_h:", cfg->g_h, + width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, + width, "g_error_resilient:", cfg->g_error_resilient, + width, "g_pass:", cfg->g_pass, + width, "g_lag_in_frames:", cfg->g_lag_in_frames); + av_log(avctx, level, "rate control settings\n" + " %*s%u\n %*s%u\n %*s%u\n %*s%u\n" + " %*s%d\n %*s%p(%zu)\n %*s%u\n", + width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, + width, "rc_resize_allowed:", cfg->rc_resize_allowed, + width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh, + width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh, + width, "rc_end_usage:", cfg->rc_end_usage, + width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, + width, "rc_target_bitrate:", cfg->rc_target_bitrate); + av_log(avctx, level, "quantizer settings\n" + " %*s%u\n %*s%u\n", + width, "rc_min_quantizer:", cfg->rc_min_quantizer, + width, "rc_max_quantizer:", cfg->rc_max_quantizer); + av_log(avctx, level, "bitrate tolerance\n" + " %*s%u\n %*s%u\n", + width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, + width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); + av_log(avctx, level, "decoder buffer model\n" + " %*s%u\n %*s%u\n %*s%u\n", + width, "rc_buf_sz:", cfg->rc_buf_sz, + width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, + width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); + av_log(avctx, level, "2 pass rate control settings\n" + " %*s%u\n %*s%u\n %*s%u\n", + width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, + width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, + width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); + av_log(avctx, level, "keyframing settings\n" + " %*s%d\n %*s%u\n %*s%u\n", + width, "kf_mode:", cfg->kf_mode, + width, "kf_min_dist:", cfg->kf_min_dist, + width, "kf_max_dist:", cfg->kf_max_dist); + av_log(avctx, level, "\n"); +} + +static void coded_frame_add(void *list, struct FrameListData *cx_frame) +{ + struct FrameListData **p = list; + + while (*p != NULL) + p = &(*p)->next; + *p = cx_frame; + cx_frame->next = NULL; +} + +static av_cold void free_coded_frame(struct FrameListData *cx_frame) +{ + av_freep(&cx_frame->buf); + av_freep(&cx_frame); +} + +static av_cold void free_frame_list(struct FrameListData *list) +{ + struct FrameListData *p = list; + + while (p) { + list = list->next; + free_coded_frame(p); + p = list; + } +} + +static av_cold int codecctl_int(AVCodecContext *avctx, + enum vp8e_enc_control_id id, int val) +{ + VP8Context *ctx = avctx->priv_data; + char buf[80]; + int width = -30; + int res; + + snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); + av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val); + + res = vpx_codec_control(&ctx->encoder, id, val); + if (res != VPX_CODEC_OK) { + snprintf(buf, sizeof(buf), "Failed to set %s codec control", + ctlidstr[id]); + log_encoder_error(avctx, buf); + } + + return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL); +} + +static av_cold int vp8_free(AVCodecContext *avctx) +{ + VP8Context *ctx = avctx->priv_data; + + vpx_codec_destroy(&ctx->encoder); + av_freep(&ctx->twopass_stats.buf); + av_freep(&avctx->coded_frame); + av_freep(&avctx->stats_out); + free_frame_list(ctx->coded_frame_list); + return 0; +} + +static av_cold int vpx_init(AVCodecContext *avctx, + const struct vpx_codec_iface *iface) +{ + VP8Context *ctx = avctx->priv_data; + struct vpx_codec_enc_cfg enccfg; + vpx_codec_flags_t flags = (avctx->flags & CODEC_FLAG_PSNR) ? VPX_CODEC_USE_PSNR : 0; + int res; + + av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); + av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); + + if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n", + vpx_codec_err_to_string(res)); + return AVERROR(EINVAL); + } + + if(!avctx->bit_rate) + if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) { + av_log( avctx, AV_LOG_ERROR, "Rate control parameters set without a bitrate\n"); + return AVERROR(EINVAL); + } + + dump_enc_cfg(avctx, &enccfg); + + enccfg.g_w = avctx->width; + enccfg.g_h = avctx->height; + enccfg.g_timebase.num = avctx->time_base.num; + enccfg.g_timebase.den = avctx->time_base.den; + enccfg.g_threads = avctx->thread_count; + enccfg.g_lag_in_frames= ctx->lag_in_frames; + + if (avctx->flags & CODEC_FLAG_PASS1) + enccfg.g_pass = VPX_RC_FIRST_PASS; + else if (avctx->flags & CODEC_FLAG_PASS2) + enccfg.g_pass = VPX_RC_LAST_PASS; + else + enccfg.g_pass = VPX_RC_ONE_PASS; + + if (avctx->rc_min_rate == avctx->rc_max_rate && + avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) + enccfg.rc_end_usage = VPX_CBR; + else if (ctx->crf) + enccfg.rc_end_usage = VPX_CQ; + + if (avctx->bit_rate) { + enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, + AV_ROUND_NEAR_INF); + } else { + if (enccfg.rc_end_usage == VPX_CQ) { + enccfg.rc_target_bitrate = 1000000; + } else { + avctx->bit_rate = enccfg.rc_target_bitrate * 1000; + av_log(avctx, AV_LOG_WARNING, + "Neither bitrate nor constrained quality specified, using default bitrate of %dkbit/sec\n", + enccfg.rc_target_bitrate); + } + } + + if (avctx->qmin >= 0) + enccfg.rc_min_quantizer = avctx->qmin; + if (avctx->qmax > 0) + enccfg.rc_max_quantizer = avctx->qmax; + + if (enccfg.rc_end_usage == VPX_CQ) { + if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) { + av_log(avctx, AV_LOG_ERROR, + "CQ level must be between minimum and maximum quantizer value (%d-%d)\n", + enccfg.rc_min_quantizer, enccfg.rc_max_quantizer); + return AVERROR(EINVAL); + } + } + + enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold; + + //0-100 (0 => CBR, 100 => VBR) + enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); + if (avctx->bit_rate) + enccfg.rc_2pass_vbr_minsection_pct = + avctx->rc_min_rate * 100LL / avctx->bit_rate; + if (avctx->rc_max_rate) + enccfg.rc_2pass_vbr_maxsection_pct = + avctx->rc_max_rate * 100LL / avctx->bit_rate; + + if (avctx->rc_buffer_size) + enccfg.rc_buf_sz = + avctx->rc_buffer_size * 1000LL / avctx->bit_rate; + if (avctx->rc_initial_buffer_occupancy) + enccfg.rc_buf_initial_sz = + avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; + enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; + enccfg.rc_undershoot_pct = round(avctx->rc_buffer_aggressivity * 100); + + //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO + if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size) + enccfg.kf_min_dist = avctx->keyint_min; + if (avctx->gop_size >= 0) + enccfg.kf_max_dist = avctx->gop_size; + + if (enccfg.g_pass == VPX_RC_FIRST_PASS) + enccfg.g_lag_in_frames = 0; + else if (enccfg.g_pass == VPX_RC_LAST_PASS) { + int decode_size; + + if (!avctx->stats_in) { + av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n"); + return AVERROR_INVALIDDATA; + } + + ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; + ctx->twopass_stats.buf = av_malloc(ctx->twopass_stats.sz); + if (!ctx->twopass_stats.buf) { + av_log(avctx, AV_LOG_ERROR, + "Stat buffer alloc (%zu bytes) failed\n", + ctx->twopass_stats.sz); + return AVERROR(ENOMEM); + } + decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, + ctx->twopass_stats.sz); + if (decode_size < 0) { + av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n"); + return AVERROR_INVALIDDATA; + } + + ctx->twopass_stats.sz = decode_size; + enccfg.rc_twopass_stats_in = ctx->twopass_stats; + } + + /* 0-3: For non-zero values the encoder increasingly optimizes for reduced + complexity playback on low powered devices at the expense of encode + quality. */ + if (avctx->profile != FF_PROFILE_UNKNOWN) + enccfg.g_profile = avctx->profile; + + enccfg.g_error_resilient = ctx->error_resilient || ctx->flags & VP8F_ERROR_RESILIENT; + + dump_enc_cfg(avctx, &enccfg); + /* Construct Encoder Context */ + res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, flags); + if (res != VPX_CODEC_OK) { + log_encoder_error(avctx, "Failed to initialize encoder"); + return AVERROR(EINVAL); + } + + //codec control failures are currently treated only as warnings + av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); + if (ctx->cpu_used != INT_MIN) + codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used); + if (ctx->flags & VP8F_AUTO_ALT_REF) + ctx->auto_alt_ref = 1; + if (ctx->auto_alt_ref >= 0) + codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref); + if (ctx->arnr_max_frames >= 0) + codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames); + if (ctx->arnr_strength >= 0) + codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength); + if (ctx->arnr_type >= 0) + codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type); + codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); + codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); + codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, avctx->mb_threshold); + codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf); + if (ctx->max_intra_rate >= 0) + codecctl_int(avctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, ctx->max_intra_rate); + + av_log(avctx, AV_LOG_DEBUG, "Using deadline: %d\n", ctx->deadline); + + //provide dummy value to initialize wrapper, values will be updated each _encode() + vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, + (unsigned char*)1); + + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); + vp8_free(avctx); + return AVERROR(ENOMEM); + } + return 0; +} + +static inline void cx_pktcpy(struct FrameListData *dst, + const struct vpx_codec_cx_pkt *src, + VP8Context *ctx) +{ + dst->pts = src->data.frame.pts; + dst->duration = src->data.frame.duration; + dst->flags = src->data.frame.flags; + dst->sz = src->data.frame.sz; + dst->buf = src->data.frame.buf; + dst->have_sse = 0; + /* For alt-ref frame, don't store PSNR or increment frame_number */ + if (!(dst->flags & VPX_FRAME_IS_INVISIBLE)) { + dst->frame_number = ++ctx->frame_number; + dst->have_sse = ctx->have_sse; + if (ctx->have_sse) { + /* associate last-seen SSE to the frame. */ + /* Transfers ownership from ctx to dst. */ + /* WARNING! This makes the assumption that PSNR_PKT comes + just before the frame it refers to! */ + memcpy(dst->sse, ctx->sse, sizeof(dst->sse)); + ctx->have_sse = 0; + } + } else { + dst->frame_number = -1; /* sanity marker */ + } +} + +/** + * Store coded frame information in format suitable for return from encode2(). + * + * Write information from @a cx_frame to @a pkt + * @return packet data size on success + * @return a negative AVERROR on error + */ +static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, + AVPacket *pkt, AVFrame *coded_frame) +{ + int ret = ff_alloc_packet2(avctx, pkt, cx_frame->sz); + if (ret >= 0) { + memcpy(pkt->data, cx_frame->buf, pkt->size); + pkt->pts = pkt->dts = cx_frame->pts; + coded_frame->pts = cx_frame->pts; + coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY); + + if (coded_frame->key_frame) { + coded_frame->pict_type = AV_PICTURE_TYPE_I; + pkt->flags |= AV_PKT_FLAG_KEY; + } else + coded_frame->pict_type = AV_PICTURE_TYPE_P; + + if (cx_frame->have_sse) { + int i; + /* Beware of the Y/U/V/all order! */ + coded_frame->error[0] = cx_frame->sse[1]; + coded_frame->error[1] = cx_frame->sse[2]; + coded_frame->error[2] = cx_frame->sse[3]; + coded_frame->error[3] = 0; // alpha + for (i = 0; i < 4; ++i) { + avctx->error[i] += coded_frame->error[i]; + } + cx_frame->have_sse = 0; + } + } else { + return ret; + } + return pkt->size; +} + +/** + * Queue multiple output frames from the encoder, returning the front-most. + * In cases where vpx_codec_get_cx_data() returns more than 1 frame append + * the frame queue. Return the head frame if available. + * @return Stored frame size + * @return AVERROR(EINVAL) on output size error + * @return AVERROR(ENOMEM) on coded frame queue data allocation error + */ +static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, + AVFrame *coded_frame) +{ + VP8Context *ctx = avctx->priv_data; + const struct vpx_codec_cx_pkt *pkt; + const void *iter = NULL; + int size = 0; + + if (ctx->coded_frame_list) { + struct FrameListData *cx_frame = ctx->coded_frame_list; + /* return the leading frame if we've already begun queueing */ + size = storeframe(avctx, cx_frame, pkt_out, coded_frame); + if (size < 0) + return size; + ctx->coded_frame_list = cx_frame->next; + free_coded_frame(cx_frame); + } + + /* consume all available output from the encoder before returning. buffers + are only good through the next vpx_codec call */ + while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter))) { + switch (pkt->kind) { + case VPX_CODEC_CX_FRAME_PKT: + if (!size) { + struct FrameListData cx_frame; + + /* avoid storing the frame when the list is empty and we haven't yet + provided a frame for output */ + av_assert0(!ctx->coded_frame_list); + cx_pktcpy(&cx_frame, pkt, ctx); + size = storeframe(avctx, &cx_frame, pkt_out, coded_frame); + if (size < 0) + return size; + } else { + struct FrameListData *cx_frame = + av_malloc(sizeof(struct FrameListData)); + + if (!cx_frame) { + av_log(avctx, AV_LOG_ERROR, + "Frame queue element alloc failed\n"); + return AVERROR(ENOMEM); + } + cx_pktcpy(cx_frame, pkt, ctx); + cx_frame->buf = av_malloc(cx_frame->sz); + + if (!cx_frame->buf) { + av_log(avctx, AV_LOG_ERROR, + "Data buffer alloc (%zu bytes) failed\n", + cx_frame->sz); + av_free(cx_frame); + return AVERROR(ENOMEM); + } + memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); + coded_frame_add(&ctx->coded_frame_list, cx_frame); + } + break; + case VPX_CODEC_STATS_PKT: { + struct vpx_fixed_buf *stats = &ctx->twopass_stats; + stats->buf = av_realloc_f(stats->buf, 1, + stats->sz + pkt->data.twopass_stats.sz); + if (!stats->buf) { + av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n"); + return AVERROR(ENOMEM); + } + memcpy((uint8_t*)stats->buf + stats->sz, + pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); + stats->sz += pkt->data.twopass_stats.sz; + break; + } + case VPX_CODEC_PSNR_PKT: + av_assert0(!ctx->have_sse); + ctx->sse[0] = pkt->data.psnr.sse[0]; + ctx->sse[1] = pkt->data.psnr.sse[1]; + ctx->sse[2] = pkt->data.psnr.sse[2]; + ctx->sse[3] = pkt->data.psnr.sse[3]; + ctx->have_sse = 1; + break; + case VPX_CODEC_CUSTOM_PKT: + //ignore unsupported/unrecognized packet types + break; + } + } + + return size; +} + +static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + VP8Context *ctx = avctx->priv_data; + struct vpx_image *rawimg = NULL; + int64_t timestamp = 0; + int res, coded_size; + vpx_enc_frame_flags_t flags = 0; + + if (frame) { + rawimg = &ctx->rawimg; + rawimg->planes[VPX_PLANE_Y] = frame->data[0]; + rawimg->planes[VPX_PLANE_U] = frame->data[1]; + rawimg->planes[VPX_PLANE_V] = frame->data[2]; + rawimg->stride[VPX_PLANE_Y] = frame->linesize[0]; + rawimg->stride[VPX_PLANE_U] = frame->linesize[1]; + rawimg->stride[VPX_PLANE_V] = frame->linesize[2]; + timestamp = frame->pts; + if (frame->pict_type == AV_PICTURE_TYPE_I) + flags |= VPX_EFLAG_FORCE_KF; + } + + res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, + avctx->ticks_per_frame, flags, ctx->deadline); + if (res != VPX_CODEC_OK) { + log_encoder_error(avctx, "Error encoding frame"); + return AVERROR_INVALIDDATA; + } + coded_size = queue_frames(avctx, pkt, avctx->coded_frame); + + if (!frame && avctx->flags & CODEC_FLAG_PASS1) { + unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz); + + avctx->stats_out = av_malloc(b64_size); + if (!avctx->stats_out) { + av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n", + b64_size); + return AVERROR(ENOMEM); + } + av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, + ctx->twopass_stats.sz); + } + + *got_packet = !!coded_size; + return 0; +} + +#define OFFSET(x) offsetof(VP8Context, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = INT_MIN}, INT_MIN, INT_MAX, VE}, + { "auto-alt-ref", "Enable use of alternate reference " + "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, + { "lag-in-frames", "Number of frames to look ahead for " + "alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, + { "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, + { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, + { "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "arnr_type"}, + { "backward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "arnr_type" }, + { "forward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "arnr_type" }, + { "centered", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "arnr_type" }, + { "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, + { "best", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"}, + { "good", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"}, + { "realtime", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME}, 0, 0, VE, "quality"}, + { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"}, + { "max-intra-rate", "Maximum I-frame bitrate (pct) 0=unlimited", OFFSET(max_intra_rate), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, +#ifdef VPX_ERROR_RESILIENT_DEFAULT + { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"}, + { "partitions", "The frame partitions are independently decodable " + "by the bool decoder, meaning that partitions can be decoded even " + "though earlier partitions have been lost. Note that intra predicition" + " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, +#endif +{"speed", "", offsetof(VP8Context, cpu_used), AV_OPT_TYPE_INT, {.i64 = 3}, -16, 16, VE}, +{"quality", "", offsetof(VP8Context, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, +{"vp8flags", "", offsetof(VP8Context, flags), FF_OPT_TYPE_FLAGS, {.i64 = 0}, 0, UINT_MAX, VE, "flags"}, +{"error_resilient", "enable error resilience", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_ERROR_RESILIENT}, INT_MIN, INT_MAX, VE, "flags"}, +{"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_AUTO_ALT_REF}, INT_MIN, INT_MAX, VE, "flags"}, +{"arnr_max_frames", "altref noise reduction max frame count", offsetof(VP8Context, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 15, VE}, +{"arnr_strength", "altref noise reduction filter strength", offsetof(VP8Context, arnr_strength), AV_OPT_TYPE_INT, {.i64 = 3}, 0, 6, VE}, +{"arnr_type", "altref noise reduction filter type", offsetof(VP8Context, arnr_type), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 3, VE}, +{"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VP8Context, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = 25}, 0, 25, VE}, + { "crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE }, + { NULL } +}; + +static const AVCodecDefault defaults[] = { + { "qmin", "-1" }, + { "qmax", "-1" }, + { "g", "-1" }, + { "keyint_min", "-1" }, + { NULL }, +}; + +#if CONFIG_LIBVPX_VP8_ENCODER +static av_cold int vp8_init(AVCodecContext *avctx) +{ + return vpx_init(avctx, &vpx_codec_vp8_cx_algo); +} + +static const AVClass class_vp8 = { + .class_name = "libvpx encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libvpx_vp8_encoder = { + .name = "libvpx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP8, + .priv_data_size = sizeof(VP8Context), + .init = vp8_init, + .encode2 = vp8_encode, + .close = vp8_free, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), + .priv_class = &class_vp8, + .defaults = defaults, +}; +#endif /* CONFIG_LIBVPX_VP8_ENCODER */ + +#if CONFIG_LIBVPX_VP9_ENCODER +static av_cold int vp9_init(AVCodecContext *avctx) +{ + return vpx_init(avctx, &vpx_codec_vp9_cx_algo); +} + +static const AVClass class_vp9 = { + .class_name = "libvpx encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_libvpx_vp9_encoder = { + .name = "libvpx-vp9", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .priv_data_size = sizeof(VP8Context), + .init = vp9_init, + .encode2 = vp8_encode, + .close = vp8_free, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS | CODEC_CAP_EXPERIMENTAL, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), + .priv_class = &class_vp9, + .defaults = defaults, +}; +#endif /* CONFIG_LIBVPX_VP9_ENCODER */ diff --git a/ffmpeg/libavcodec/libx264.c b/ffmpeg/libavcodec/libx264.c new file mode 100644 index 0000000..7e8fa65 --- /dev/null +++ b/ffmpeg/libavcodec/libx264.c @@ -0,0 +1,751 @@ +/* + * H.264 encoding using the x264 library + * Copyright (C) 2005 Mans Rullgard + * + * 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 "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "internal.h" +#include +#include +#include +#include +#include +#include + +typedef struct X264Context { + AVClass *class; + x264_param_t params; + x264_t *enc; + x264_picture_t pic; + uint8_t *sei; + int sei_size; + AVFrame out_pic; + char *preset; + char *tune; + char *profile; + char *level; + int fastfirstpass; + char *wpredp; + char *x264opts; + float crf; + float crf_max; + int cqp; + int aq_mode; + float aq_strength; + char *psy_rd; + int psy; + int rc_lookahead; + int weightp; + int weightb; + int ssim; + int intra_refresh; + int b_bias; + int b_pyramid; + int mixed_refs; + int dct8x8; + int fast_pskip; + int aud; + int mbtree; + char *deblock; + float cplxblur; + char *partitions; + int direct_pred; + int slice_max_size; + char *stats; + int nal_hrd; + char *x264_params; +} X264Context; + +static void X264_log(void *p, int level, const char *fmt, va_list args) +{ + static const int level_map[] = { + [X264_LOG_ERROR] = AV_LOG_ERROR, + [X264_LOG_WARNING] = AV_LOG_WARNING, + [X264_LOG_INFO] = AV_LOG_INFO, + [X264_LOG_DEBUG] = AV_LOG_DEBUG + }; + + if (level < 0 || level > X264_LOG_DEBUG) + return; + + av_vlog(p, level_map[level], fmt, args); +} + + +static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, + x264_nal_t *nals, int nnal) +{ + X264Context *x4 = ctx->priv_data; + uint8_t *p; + int i, size = x4->sei_size, ret; + + if (!nnal) + return 0; + + for (i = 0; i < nnal; i++) + size += nals[i].i_payload; + + if ((ret = ff_alloc_packet2(ctx, pkt, size)) < 0) + return ret; + + p = pkt->data; + + /* Write the SEI as part of the first frame. */ + if (x4->sei_size > 0 && nnal > 0) { + if (x4->sei_size > size) { + av_log(ctx, AV_LOG_ERROR, "Error: nal buffer is too small\n"); + return -1; + } + memcpy(p, x4->sei, x4->sei_size); + p += x4->sei_size; + x4->sei_size = 0; + av_freep(&x4->sei); + } + + for (i = 0; i < nnal; i++){ + memcpy(p, nals[i].p_payload, nals[i].i_payload); + p += nals[i].i_payload; + } + + return 1; +} + +static int avfmt2_num_planes(int avfmt) +{ + switch (avfmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P9: + case AV_PIX_FMT_YUV420P10: + case AV_PIX_FMT_YUV444P: + return 3; + + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_RGB24: + return 1; + + default: + return 3; + } +} + +static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, + int *got_packet) +{ + X264Context *x4 = ctx->priv_data; + x264_nal_t *nal; + int nnal, i, ret; + x264_picture_t pic_out; + + x264_picture_init( &x4->pic ); + x4->pic.img.i_csp = x4->params.i_csp; + if (x264_bit_depth > 8) + x4->pic.img.i_csp |= X264_CSP_HIGH_DEPTH; + x4->pic.img.i_plane = avfmt2_num_planes(ctx->pix_fmt); + + if (frame) { + for (i = 0; i < x4->pic.img.i_plane; i++) { + x4->pic.img.plane[i] = frame->data[i]; + x4->pic.img.i_stride[i] = frame->linesize[i]; + } + + x4->pic.i_pts = frame->pts; + x4->pic.i_type = + frame->pict_type == AV_PICTURE_TYPE_I ? X264_TYPE_KEYFRAME : + frame->pict_type == AV_PICTURE_TYPE_P ? X264_TYPE_P : + frame->pict_type == AV_PICTURE_TYPE_B ? X264_TYPE_B : + X264_TYPE_AUTO; + if (x4->params.b_interlaced && x4->params.b_tff != frame->top_field_first) { + x4->params.b_tff = frame->top_field_first; + x264_encoder_reconfig(x4->enc, &x4->params); + } + if (x4->params.vui.i_sar_height != ctx->sample_aspect_ratio.den || + x4->params.vui.i_sar_width != ctx->sample_aspect_ratio.num) { + x4->params.vui.i_sar_height = ctx->sample_aspect_ratio.den; + x4->params.vui.i_sar_width = ctx->sample_aspect_ratio.num; + x264_encoder_reconfig(x4->enc, &x4->params); + } + } + + do { + if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0) + return -1; + + ret = encode_nals(ctx, pkt, nal, nnal); + if (ret < 0) + return -1; + } while (!ret && !frame && x264_encoder_delayed_frames(x4->enc)); + + pkt->pts = pic_out.i_pts; + pkt->dts = pic_out.i_dts; + + switch (pic_out.i_type) { + case X264_TYPE_IDR: + case X264_TYPE_I: + x4->out_pic.pict_type = AV_PICTURE_TYPE_I; + break; + case X264_TYPE_P: + x4->out_pic.pict_type = AV_PICTURE_TYPE_P; + break; + case X264_TYPE_B: + case X264_TYPE_BREF: + x4->out_pic.pict_type = AV_PICTURE_TYPE_B; + break; + } + + pkt->flags |= AV_PKT_FLAG_KEY*pic_out.b_keyframe; + if (ret) + x4->out_pic.quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + + *got_packet = ret; + return 0; +} + +static av_cold int X264_close(AVCodecContext *avctx) +{ + X264Context *x4 = avctx->priv_data; + + av_freep(&avctx->extradata); + av_free(x4->sei); + + if (x4->enc) + x264_encoder_close(x4->enc); + + return 0; +} + +#define OPT_STR(opt, param) \ + do { \ + int ret; \ + if (param && (ret = x264_param_parse(&x4->params, opt, param)) < 0) { \ + if(ret == X264_PARAM_BAD_NAME) \ + av_log(avctx, AV_LOG_ERROR, \ + "bad option '%s': '%s'\n", opt, param); \ + else \ + av_log(avctx, AV_LOG_ERROR, \ + "bad value for '%s': '%s'\n", opt, param); \ + return -1; \ + } \ + } while (0) + +static int convert_pix_fmt(enum AVPixelFormat pix_fmt) +{ + switch (pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P9: + case AV_PIX_FMT_YUV420P10: return X264_CSP_I420; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P10: return X264_CSP_I422; + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV444P9: + case AV_PIX_FMT_YUV444P10: return X264_CSP_I444; +#ifdef X264_CSP_BGR + case AV_PIX_FMT_BGR24: + return X264_CSP_BGR; + + case AV_PIX_FMT_RGB24: + return X264_CSP_RGB; +#endif + }; + return 0; +} + +#define PARSE_X264_OPT(name, var)\ + if (x4->var && x264_param_parse(&x4->params, name, x4->var) < 0) {\ + av_log(avctx, AV_LOG_ERROR, "Error parsing option '%s' with value '%s'.\n", name, x4->var);\ + return AVERROR(EINVAL);\ + } + +static av_cold int X264_init(AVCodecContext *avctx) +{ + X264Context *x4 = avctx->priv_data; + int sw,sh; + + x264_param_default(&x4->params); + + x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; + + x4->params.rc.f_pb_factor = avctx->b_quant_factor; + x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset; + if (x4->preset || x4->tune) + if (x264_param_default_preset(&x4->params, x4->preset, x4->tune) < 0) { + int i; + av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", x4->preset, x4->tune); + av_log(avctx, AV_LOG_INFO, "Possible presets:"); + for (i = 0; x264_preset_names[i]; i++) + av_log(avctx, AV_LOG_INFO, " %s", x264_preset_names[i]); + av_log(avctx, AV_LOG_INFO, "\n"); + av_log(avctx, AV_LOG_INFO, "Possible tunes:"); + for (i = 0; x264_tune_names[i]; i++) + av_log(avctx, AV_LOG_INFO, " %s", x264_tune_names[i]); + av_log(avctx, AV_LOG_INFO, "\n"); + return AVERROR(EINVAL); + } + + if (avctx->level > 0) + x4->params.i_level_idc = avctx->level; + + x4->params.pf_log = X264_log; + x4->params.p_log_private = avctx; + x4->params.i_log_level = X264_LOG_DEBUG; + x4->params.i_csp = convert_pix_fmt(avctx->pix_fmt); + + OPT_STR("weightp", x4->wpredp); + + if (avctx->bit_rate) { + x4->params.rc.i_bitrate = avctx->bit_rate / 1000; + x4->params.rc.i_rc_method = X264_RC_ABR; + } + x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000; + x4->params.rc.i_vbv_max_bitrate = avctx->rc_max_rate / 1000; + x4->params.rc.b_stat_write = avctx->flags & CODEC_FLAG_PASS1; + if (avctx->flags & CODEC_FLAG_PASS2) { + x4->params.rc.b_stat_read = 1; + } else { + if (x4->crf >= 0) { + x4->params.rc.i_rc_method = X264_RC_CRF; + x4->params.rc.f_rf_constant = x4->crf; + } else if (x4->cqp >= 0) { + x4->params.rc.i_rc_method = X264_RC_CQP; + x4->params.rc.i_qp_constant = x4->cqp; + } + + if (x4->crf_max >= 0) + x4->params.rc.f_rf_constant_max = x4->crf_max; + } + + if (avctx->rc_buffer_size && avctx->rc_initial_buffer_occupancy > 0 && + (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) { + x4->params.rc.f_vbv_buffer_init = + (float)avctx->rc_initial_buffer_occupancy / avctx->rc_buffer_size; + } + + OPT_STR("level", x4->level); + + if(x4->x264opts){ + const char *p= x4->x264opts; + while(p){ + char param[256]={0}, val[256]={0}; + if(sscanf(p, "%255[^:=]=%255[^:]", param, val) == 1){ + OPT_STR(param, "1"); + }else + OPT_STR(param, val); + p= strchr(p, ':'); + p+=!!p; + } + } + + if (avctx->i_quant_factor > 0) + x4->params.rc.f_ip_factor = 1 / fabs(avctx->i_quant_factor); + + if (avctx->me_method == ME_EPZS) + x4->params.analyse.i_me_method = X264_ME_DIA; + else if (avctx->me_method == ME_HEX) + x4->params.analyse.i_me_method = X264_ME_HEX; + else if (avctx->me_method == ME_UMH) + x4->params.analyse.i_me_method = X264_ME_UMH; + else if (avctx->me_method == ME_FULL) + x4->params.analyse.i_me_method = X264_ME_ESA; + else if (avctx->me_method == ME_TESA) + x4->params.analyse.i_me_method = X264_ME_TESA; + + if (avctx->gop_size >= 0) + x4->params.i_keyint_max = avctx->gop_size; + if (avctx->max_b_frames >= 0) + x4->params.i_bframe = avctx->max_b_frames; + if (avctx->scenechange_threshold >= 0) + x4->params.i_scenecut_threshold = avctx->scenechange_threshold; + if (avctx->qmin >= 0) + x4->params.rc.i_qp_min = avctx->qmin; + if (avctx->qmax >= 0) + x4->params.rc.i_qp_max = avctx->qmax; + if (avctx->max_qdiff >= 0) + x4->params.rc.i_qp_step = avctx->max_qdiff; + if (avctx->qblur >= 0) + x4->params.rc.f_qblur = avctx->qblur; /* temporally blur quants */ + if (avctx->qcompress >= 0) + x4->params.rc.f_qcompress = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */ + if (avctx->refs >= 0) + x4->params.i_frame_reference = avctx->refs; + if (avctx->trellis >= 0) + x4->params.analyse.i_trellis = avctx->trellis; + if (avctx->me_range >= 0) + x4->params.analyse.i_me_range = avctx->me_range; + if (avctx->noise_reduction >= 0) + x4->params.analyse.i_noise_reduction = avctx->noise_reduction; + if (avctx->me_subpel_quality >= 0) + x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; + if (avctx->b_frame_strategy >= 0) + x4->params.i_bframe_adaptive = avctx->b_frame_strategy; + if (avctx->keyint_min >= 0) + x4->params.i_keyint_min = avctx->keyint_min; + if (avctx->coder_type >= 0) + x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC; + if (avctx->me_cmp >= 0) + x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; + + if (x4->aq_mode >= 0) + x4->params.rc.i_aq_mode = x4->aq_mode; + if (x4->aq_strength >= 0) + x4->params.rc.f_aq_strength = x4->aq_strength; + PARSE_X264_OPT("psy-rd", psy_rd); + PARSE_X264_OPT("deblock", deblock); + PARSE_X264_OPT("partitions", partitions); + PARSE_X264_OPT("stats", stats); + if (x4->psy >= 0) + x4->params.analyse.b_psy = x4->psy; + if (x4->rc_lookahead >= 0) + x4->params.rc.i_lookahead = x4->rc_lookahead; + if (x4->weightp >= 0) + x4->params.analyse.i_weighted_pred = x4->weightp; + if (x4->weightb >= 0) + x4->params.analyse.b_weighted_bipred = x4->weightb; + if (x4->cplxblur >= 0) + x4->params.rc.f_complexity_blur = x4->cplxblur; + + if (x4->ssim >= 0) + x4->params.analyse.b_ssim = x4->ssim; + if (x4->intra_refresh >= 0) + x4->params.b_intra_refresh = x4->intra_refresh; + if (x4->b_bias != INT_MIN) + x4->params.i_bframe_bias = x4->b_bias; + if (x4->b_pyramid >= 0) + x4->params.i_bframe_pyramid = x4->b_pyramid; + if (x4->mixed_refs >= 0) + x4->params.analyse.b_mixed_references = x4->mixed_refs; + if (x4->dct8x8 >= 0) + x4->params.analyse.b_transform_8x8 = x4->dct8x8; + if (x4->fast_pskip >= 0) + x4->params.analyse.b_fast_pskip = x4->fast_pskip; + if (x4->aud >= 0) + x4->params.b_aud = x4->aud; + if (x4->mbtree >= 0) + x4->params.rc.b_mb_tree = x4->mbtree; + if (x4->direct_pred >= 0) + x4->params.analyse.i_direct_mv_pred = x4->direct_pred; + + if (x4->slice_max_size >= 0) + x4->params.i_slice_max_size = x4->slice_max_size; + else { + /* + * Allow x264 to be instructed through AVCodecContext about the maximum + * size of the RTP payload. For example, this enables the production of + * payload suitable for the H.264 RTP packetization-mode 0 i.e. single + * NAL unit per RTP packet. + */ + if (avctx->rtp_payload_size) + x4->params.i_slice_max_size = avctx->rtp_payload_size; + } + + if (x4->fastfirstpass) + x264_param_apply_fastfirstpass(&x4->params); + + /* Allow specifying the x264 profile through AVCodecContext. */ + if (!x4->profile) + switch (avctx->profile) { + case FF_PROFILE_H264_BASELINE: + x4->profile = av_strdup("baseline"); + break; + case FF_PROFILE_H264_HIGH: + x4->profile = av_strdup("high"); + break; + case FF_PROFILE_H264_HIGH_10: + x4->profile = av_strdup("high10"); + break; + case FF_PROFILE_H264_HIGH_422: + x4->profile = av_strdup("high422"); + break; + case FF_PROFILE_H264_HIGH_444: + x4->profile = av_strdup("high444"); + break; + case FF_PROFILE_H264_MAIN: + x4->profile = av_strdup("main"); + break; + default: + break; + } + + if (x4->nal_hrd >= 0) + x4->params.i_nal_hrd = x4->nal_hrd; + + if (x4->profile) + if (x264_param_apply_profile(&x4->params, x4->profile) < 0) { + int i; + av_log(avctx, AV_LOG_ERROR, "Error setting profile %s.\n", x4->profile); + av_log(avctx, AV_LOG_INFO, "Possible profiles:"); + for (i = 0; x264_profile_names[i]; i++) + av_log(avctx, AV_LOG_INFO, " %s", x264_profile_names[i]); + av_log(avctx, AV_LOG_INFO, "\n"); + return AVERROR(EINVAL); + } + + x4->params.i_width = avctx->width; + x4->params.i_height = avctx->height; + av_reduce(&sw, &sh, avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 4096); + x4->params.vui.i_sar_width = sw; + x4->params.vui.i_sar_height = sh; + x4->params.i_fps_num = x4->params.i_timebase_den = avctx->time_base.den; + x4->params.i_fps_den = x4->params.i_timebase_num = avctx->time_base.num; + + x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR; + + x4->params.i_threads = avctx->thread_count; + if (avctx->thread_type) + x4->params.b_sliced_threads = avctx->thread_type == FF_THREAD_SLICE; + + x4->params.b_interlaced = avctx->flags & CODEC_FLAG_INTERLACED_DCT; + + x4->params.b_open_gop = !(avctx->flags & CODEC_FLAG_CLOSED_GOP); + + x4->params.i_slice_count = avctx->slices; + + x4->params.vui.b_fullrange = avctx->pix_fmt == AV_PIX_FMT_YUVJ420P; + + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) + x4->params.b_repeat_headers = 0; + + if (x4->x264_params) { + AVDictionary *dict = NULL; + AVDictionaryEntry *en = NULL; + + if (!av_dict_parse_string(&dict, x4->x264_params, "=", ":", 0)) { + while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) { + if (x264_param_parse(&x4->params, en->key, en->value) < 0) + av_log(avctx, AV_LOG_WARNING, + "Error parsing option '%s = %s'.\n", + en->key, en->value); + } + + av_dict_free(&dict); + } + } + + // update AVCodecContext with x264 parameters + avctx->has_b_frames = x4->params.i_bframe ? + x4->params.i_bframe_pyramid ? 2 : 1 : 0; + if (avctx->max_b_frames < 0) + avctx->max_b_frames = 0; + + avctx->bit_rate = x4->params.rc.i_bitrate*1000; + + x4->enc = x264_encoder_open(&x4->params); + if (!x4->enc) + return -1; + + avctx->coded_frame = &x4->out_pic; + + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + x264_nal_t *nal; + uint8_t *p; + int nnal, s, i; + + s = x264_encoder_headers(x4->enc, &nal, &nnal); + avctx->extradata = p = av_malloc(s); + + for (i = 0; i < nnal; i++) { + /* Don't put the SEI in extradata. */ + if (nal[i].i_type == NAL_SEI) { + av_log(avctx, AV_LOG_INFO, "%s\n", nal[i].p_payload+25); + x4->sei_size = nal[i].i_payload; + x4->sei = av_malloc(x4->sei_size); + memcpy(x4->sei, nal[i].p_payload, nal[i].i_payload); + continue; + } + memcpy(p, nal[i].p_payload, nal[i].i_payload); + p += nal[i].i_payload; + } + avctx->extradata_size = p - avctx->extradata; + } + + return 0; +} + +static const enum AVPixelFormat pix_fmts_8bit[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV444P, + AV_PIX_FMT_NONE +}; +static const enum AVPixelFormat pix_fmts_9bit[] = { + AV_PIX_FMT_YUV420P9, + AV_PIX_FMT_YUV444P9, + AV_PIX_FMT_NONE +}; +static const enum AVPixelFormat pix_fmts_10bit[] = { + AV_PIX_FMT_YUV420P10, + AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_YUV444P10, + AV_PIX_FMT_NONE +}; +static const enum AVPixelFormat pix_fmts_8bit_rgb[] = { +#ifdef X264_CSP_BGR + AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB24, +#endif + AV_PIX_FMT_NONE +}; + +static av_cold void X264_init_static(AVCodec *codec) +{ + if (x264_bit_depth == 8) + codec->pix_fmts = pix_fmts_8bit; + else if (x264_bit_depth == 9) + codec->pix_fmts = pix_fmts_9bit; + else if (x264_bit_depth == 10) + codec->pix_fmts = pix_fmts_10bit; +} + +#define OFFSET(x) offsetof(X264Context, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "preset", "Set the encoding preset (cf. x264 --fullhelp)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE}, + { "tune", "Tune the encoding params (cf. x264 --fullhelp)", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "profile", "Set profile restrictions (cf. x264 --fullhelp) ", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "fastfirstpass", "Use fast settings when encoding first pass", OFFSET(fastfirstpass), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE}, + {"level", "Specify level (as defined by Annex A)", OFFSET(level), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, + {"passlogfile", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, + {"wpredp", "Weighted prediction for P-frames", OFFSET(wpredp), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, + {"x264opts", "x264 options", OFFSET(x264opts), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, + { "crf", "Select the quality for constant quality mode", OFFSET(crf), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, + { "crf_max", "In CRF mode, prevents VBV from lowering quality beyond this point.",OFFSET(crf_max), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, + { "qp", "Constant quantization parameter rate control method",OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + { "aq-mode", "AQ method", OFFSET(aq_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "aq_mode"}, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_NONE}, INT_MIN, INT_MAX, VE, "aq_mode" }, + { "variance", "Variance AQ (complexity mask)", 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_VARIANCE}, INT_MIN, INT_MAX, VE, "aq_mode" }, + { "autovariance", "Auto-variance AQ (experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_AUTOVARIANCE}, INT_MIN, INT_MAX, VE, "aq_mode" }, + { "aq-strength", "AQ strength. Reduces blocking and blurring in flat and textured areas.", OFFSET(aq_strength), AV_OPT_TYPE_FLOAT, {.dbl = -1}, -1, FLT_MAX, VE}, + { "psy", "Use psychovisual optimizations.", OFFSET(psy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { "psy-rd", "Strength of psychovisual optimization, in : format.", OFFSET(psy_rd), AV_OPT_TYPE_STRING, {0 }, 0, 0, VE}, + { "rc-lookahead", "Number of frames to look ahead for frametype and ratecontrol", OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + { "weightb", "Weighted prediction for B-frames.", OFFSET(weightb), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { "weightp", "Weighted prediction analysis method.", OFFSET(weightp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "weightp" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_WEIGHTP_NONE}, INT_MIN, INT_MAX, VE, "weightp" }, + { "simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_WEIGHTP_SIMPLE}, INT_MIN, INT_MAX, VE, "weightp" }, + { "smart", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_WEIGHTP_SMART}, INT_MIN, INT_MAX, VE, "weightp" }, + { "ssim", "Calculate and print SSIM stats.", OFFSET(ssim), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { "intra-refresh", "Use Periodic Intra Refresh instead of IDR frames.",OFFSET(intra_refresh),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + { "b-bias", "Influences how often B-frames are used", OFFSET(b_bias), AV_OPT_TYPE_INT, { .i64 = INT_MIN}, INT_MIN, INT_MAX, VE }, + { "b-pyramid", "Keep some B-frames as references.", OFFSET(b_pyramid), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "b_pyramid" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_B_PYRAMID_NONE}, INT_MIN, INT_MAX, VE, "b_pyramid" }, + { "strict", "Strictly hierarchical pyramid", 0, AV_OPT_TYPE_CONST, {.i64 = X264_B_PYRAMID_STRICT}, INT_MIN, INT_MAX, VE, "b_pyramid" }, + { "normal", "Non-strict (not Blu-ray compatible)", 0, AV_OPT_TYPE_CONST, {.i64 = X264_B_PYRAMID_NORMAL}, INT_MIN, INT_MAX, VE, "b_pyramid" }, + { "mixed-refs", "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, VE }, + { "8x8dct", "High profile 8x8 transform.", OFFSET(dct8x8), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE}, + { "fast-pskip", NULL, OFFSET(fast_pskip), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE}, + { "aud", "Use access unit delimiters.", OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE}, + { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE}, + { "deblock", "Loop filter parameters, in form.", OFFSET(deblock), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "cplxblur", "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE}, + { "partitions", "A comma-separated list of partitions to consider. " + "Possible values: p8x8, p4x4, b8x8, i8x8, i4x4, none, all", OFFSET(partitions), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "direct-pred", "Direct MV prediction mode", OFFSET(direct_pred), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "direct-pred" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_DIRECT_PRED_NONE }, 0, 0, VE, "direct-pred" }, + { "spatial", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_DIRECT_PRED_SPATIAL }, 0, 0, VE, "direct-pred" }, + { "temporal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_DIRECT_PRED_TEMPORAL }, 0, 0, VE, "direct-pred" }, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = X264_DIRECT_PRED_AUTO }, 0, 0, VE, "direct-pred" }, + { "slice-max-size","Limit the size of each slice in bytes", OFFSET(slice_max_size),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + { "stats", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "nal-hrd", "Signal HRD information (requires vbv-bufsize; " + "cbr not allowed in .mp4)", OFFSET(nal_hrd), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "nal-hrd" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_NONE}, INT_MIN, INT_MAX, VE, "nal-hrd" }, + { "vbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_VBR}, INT_MIN, INT_MAX, VE, "nal-hrd" }, + { "cbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = X264_NAL_HRD_CBR}, INT_MIN, INT_MAX, VE, "nal-hrd" }, + { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { NULL }, +}; + +static const AVClass class = { + .class_name = "libx264", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVClass rgbclass = { + .class_name = "libx264rgb", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault x264_defaults[] = { + { "b", "0" }, + { "bf", "-1" }, + { "flags2", "0" }, + { "g", "-1" }, + { "i_qfactor", "-1" }, + { "qmin", "-1" }, + { "qmax", "-1" }, + { "qdiff", "-1" }, + { "qblur", "-1" }, + { "qcomp", "-1" }, +// { "rc_lookahead", "-1" }, + { "refs", "-1" }, + { "sc_threshold", "-1" }, + { "trellis", "-1" }, + { "nr", "-1" }, + { "me_range", "-1" }, + { "me_method", "-1" }, + { "subq", "-1" }, + { "b_strategy", "-1" }, + { "keyint_min", "-1" }, + { "coder", "-1" }, + { "cmp", "-1" }, + { "threads", AV_STRINGIFY(X264_THREADS_AUTO) }, + { "thread_type", "0" }, + { "flags", "+cgop" }, + { "rc_init_occupancy","-1" }, + { NULL }, +}; + +AVCodec ff_libx264_encoder = { + .name = "libx264", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(X264Context), + .init = X264_init, + .encode2 = X264_frame, + .close = X264_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .priv_class = &class, + .defaults = x264_defaults, + .init_static_data = X264_init_static, +}; + +AVCodec ff_libx264rgb_encoder = { + .name = "libx264rgb", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(X264Context), + .init = X264_init, + .encode2 = X264_frame, + .close = X264_close, + .capabilities = CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB"), + .priv_class = &rgbclass, + .defaults = x264_defaults, + .pix_fmts = pix_fmts_8bit_rgb, +}; diff --git a/ffmpeg/libavcodec/libxavs.c b/ffmpeg/libavcodec/libxavs.c new file mode 100644 index 0000000..442fc0e --- /dev/null +++ b/ffmpeg/libavcodec/libxavs.c @@ -0,0 +1,432 @@ +/* + * AVS encoding using the xavs library + * Copyright (C) 2010 Amanda, Y.N. Wu + * + * 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 +#include +#include +#include +#include +#include +#include "avcodec.h" +#include "internal.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" + +#define END_OF_STREAM 0x001 + +#define XAVS_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */ +#define XAVS_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */ +#define XAVS_PART_B8X8 0x100 /* Analyze b16x8, b*/ + +typedef struct XavsContext { + AVClass *class; + xavs_param_t params; + xavs_t *enc; + xavs_picture_t pic; + uint8_t *sei; + int sei_size; + AVFrame out_pic; + int end_of_stream; + float crf; + int cqp; + int b_bias; + float cplxblur; + int direct_pred; + int aud; + int fast_pskip; + int mbtree; + int mixed_refs; + + int64_t *pts_buffer; + int out_frame_count; +} XavsContext; + +static void XAVS_log(void *p, int level, const char *fmt, va_list args) +{ + static const int level_map[] = { + [XAVS_LOG_ERROR] = AV_LOG_ERROR, + [XAVS_LOG_WARNING] = AV_LOG_WARNING, + [XAVS_LOG_INFO] = AV_LOG_INFO, + [XAVS_LOG_DEBUG] = AV_LOG_DEBUG + }; + + if (level < 0 || level > XAVS_LOG_DEBUG) + return; + + av_vlog(p, level_map[level], fmt, args); +} + +static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, + xavs_nal_t *nals, int nnal) +{ + XavsContext *x4 = ctx->priv_data; + uint8_t *p; + int i, s, ret, size = x4->sei_size + FF_MIN_BUFFER_SIZE; + + if (!nnal) + return 0; + + for (i = 0; i < nnal; i++) + size += nals[i].i_payload; + + if ((ret = ff_alloc_packet2(ctx, pkt, size)) < 0) + return ret; + p = pkt->data; + + /* Write the SEI as part of the first frame. */ + if (x4->sei_size > 0 && nnal > 0) { + memcpy(p, x4->sei, x4->sei_size); + p += x4->sei_size; + x4->sei_size = 0; + } + + for (i = 0; i < nnal; i++) { + s = xavs_nal_encode(p, &size, 1, nals + i); + if (s < 0) + return -1; + p += s; + } + pkt->size = p - pkt->data; + + return 1; +} + +static int XAVS_frame(AVCodecContext *ctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + XavsContext *x4 = ctx->priv_data; + xavs_nal_t *nal; + int nnal, i, ret; + xavs_picture_t pic_out; + + x4->pic.img.i_csp = XAVS_CSP_I420; + x4->pic.img.i_plane = 3; + + if (frame) { + for (i = 0; i < 3; i++) { + x4->pic.img.plane[i] = frame->data[i]; + x4->pic.img.i_stride[i] = frame->linesize[i]; + } + + x4->pic.i_pts = frame->pts; + x4->pic.i_type = XAVS_TYPE_AUTO; + x4->pts_buffer[ctx->frame_number % (ctx->max_b_frames+1)] = frame->pts; + } + + if (xavs_encoder_encode(x4->enc, &nal, &nnal, + frame? &x4->pic: NULL, &pic_out) < 0) + return -1; + + ret = encode_nals(ctx, pkt, nal, nnal); + + if (ret < 0) + return -1; + + if (!ret) { + if (!frame && !(x4->end_of_stream)) { + if ((ret = ff_alloc_packet2(ctx, pkt, 4)) < 0) + return ret; + + pkt->data[0] = 0x0; + pkt->data[1] = 0x0; + pkt->data[2] = 0x01; + pkt->data[3] = 0xb1; + pkt->dts = 2*x4->pts_buffer[(x4->out_frame_count-1)%(ctx->max_b_frames+1)] - + x4->pts_buffer[(x4->out_frame_count-2)%(ctx->max_b_frames+1)]; + x4->end_of_stream = END_OF_STREAM; + *got_packet = 1; + } + return 0; + } + + x4->out_pic.pts = pic_out.i_pts; + pkt->pts = pic_out.i_pts; + if (ctx->has_b_frames) { + if (!x4->out_frame_count) + pkt->dts = pkt->pts - (x4->pts_buffer[1] - x4->pts_buffer[0]); + else + pkt->dts = x4->pts_buffer[(x4->out_frame_count-1)%(ctx->max_b_frames+1)]; + } else + pkt->dts = pkt->pts; + + switch (pic_out.i_type) { + case XAVS_TYPE_IDR: + case XAVS_TYPE_I: + x4->out_pic.pict_type = AV_PICTURE_TYPE_I; + break; + case XAVS_TYPE_P: + x4->out_pic.pict_type = AV_PICTURE_TYPE_P; + break; + case XAVS_TYPE_B: + case XAVS_TYPE_BREF: + x4->out_pic.pict_type = AV_PICTURE_TYPE_B; + break; + } + + /* There is no IDR frame in AVS JiZhun */ + /* Sequence header is used as a flag */ + if (pic_out.i_type == XAVS_TYPE_I) { + x4->out_pic.key_frame = 1; + pkt->flags |= AV_PKT_FLAG_KEY; + } + + x4->out_pic.quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + + x4->out_frame_count++; + *got_packet = ret; + return 0; +} + +static av_cold int XAVS_close(AVCodecContext *avctx) +{ + XavsContext *x4 = avctx->priv_data; + + av_freep(&avctx->extradata); + av_free(x4->sei); + av_freep(&x4->pts_buffer); + + if (x4->enc) + xavs_encoder_close(x4->enc); + + return 0; +} + +static av_cold int XAVS_init(AVCodecContext *avctx) +{ + XavsContext *x4 = avctx->priv_data; + + x4->sei_size = 0; + xavs_param_default(&x4->params); + + x4->params.pf_log = XAVS_log; + x4->params.p_log_private = avctx; + x4->params.i_keyint_max = avctx->gop_size; + if (avctx->bit_rate) { + x4->params.rc.i_bitrate = avctx->bit_rate / 1000; + x4->params.rc.i_rc_method = XAVS_RC_ABR; + } + x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000; + x4->params.rc.i_vbv_max_bitrate = avctx->rc_max_rate / 1000; + x4->params.rc.b_stat_write = avctx->flags & CODEC_FLAG_PASS1; + if (avctx->flags & CODEC_FLAG_PASS2) { + x4->params.rc.b_stat_read = 1; + } else { + if (x4->crf >= 0) { + x4->params.rc.i_rc_method = XAVS_RC_CRF; + x4->params.rc.f_rf_constant = x4->crf; + } else if (x4->cqp >= 0) { + x4->params.rc.i_rc_method = XAVS_RC_CQP; + x4->params.rc.i_qp_constant = x4->cqp; + } + } + + if (x4->aud >= 0) + x4->params.b_aud = x4->aud; + if (x4->mbtree >= 0) + x4->params.rc.b_mb_tree = x4->mbtree; + if (x4->direct_pred >= 0) + x4->params.analyse.i_direct_mv_pred = x4->direct_pred; + if (x4->fast_pskip >= 0) + x4->params.analyse.b_fast_pskip = x4->fast_pskip; + if (x4->mixed_refs >= 0) + x4->params.analyse.b_mixed_references = x4->mixed_refs; + if (x4->b_bias != INT_MIN) + x4->params.i_bframe_bias = x4->b_bias; + if (x4->cplxblur >= 0) + x4->params.rc.f_complexity_blur = x4->cplxblur; + + x4->params.i_bframe = avctx->max_b_frames; + /* cabac is not included in AVS JiZhun Profile */ + x4->params.b_cabac = 0; + + x4->params.i_bframe_adaptive = avctx->b_frame_strategy; + + avctx->has_b_frames = !!avctx->max_b_frames; + + /* AVS doesn't allow B picture as reference */ + /* The max allowed reference frame number of B is 2 */ + x4->params.i_keyint_min = avctx->keyint_min; + if (x4->params.i_keyint_min > x4->params.i_keyint_max) + x4->params.i_keyint_min = x4->params.i_keyint_max; + + x4->params.i_scenecut_threshold = avctx->scenechange_threshold; + + // x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; + + x4->params.rc.i_qp_min = avctx->qmin; + x4->params.rc.i_qp_max = avctx->qmax; + x4->params.rc.i_qp_step = avctx->max_qdiff; + + x4->params.rc.f_qcompress = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */ + x4->params.rc.f_qblur = avctx->qblur; /* temporally blur quants */ + + x4->params.i_frame_reference = avctx->refs; + + x4->params.i_width = avctx->width; + x4->params.i_height = avctx->height; + x4->params.vui.i_sar_width = avctx->sample_aspect_ratio.num; + x4->params.vui.i_sar_height = avctx->sample_aspect_ratio.den; + /* This is only used for counting the fps */ + x4->params.i_fps_num = avctx->time_base.den; + x4->params.i_fps_den = avctx->time_base.num; + x4->params.analyse.inter = XAVS_ANALYSE_I8x8 |XAVS_ANALYSE_PSUB16x16| XAVS_ANALYSE_BSUB16x16; + + switch (avctx->me_method) { + case ME_EPZS: + x4->params.analyse.i_me_method = XAVS_ME_DIA; + break; + case ME_HEX: + x4->params.analyse.i_me_method = XAVS_ME_HEX; + break; + case ME_UMH: + x4->params.analyse.i_me_method = XAVS_ME_UMH; + break; + case ME_FULL: + x4->params.analyse.i_me_method = XAVS_ME_ESA; + break; + case ME_TESA: + x4->params.analyse.i_me_method = XAVS_ME_TESA; + break; + default: + x4->params.analyse.i_me_method = XAVS_ME_HEX; + } + + x4->params.analyse.i_me_range = avctx->me_range; + x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; + + x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; + /* AVS P2 only enables 8x8 transform */ + x4->params.analyse.b_transform_8x8 = 1; //avctx->flags2 & CODEC_FLAG2_8X8DCT; + + x4->params.analyse.i_trellis = avctx->trellis; + x4->params.analyse.i_noise_reduction = avctx->noise_reduction; + + if (avctx->level > 0) + x4->params.i_level_idc = avctx->level; + + x4->params.rc.f_rate_tolerance = + (float)avctx->bit_rate_tolerance/avctx->bit_rate; + + if ((avctx->rc_buffer_size) && + (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) { + x4->params.rc.f_vbv_buffer_init = + (float)avctx->rc_initial_buffer_occupancy / avctx->rc_buffer_size; + } else + x4->params.rc.f_vbv_buffer_init = 0.9; + + /* TAG:do we have MB tree RC method */ + /* what is the RC method we are now using? Default NO */ + x4->params.rc.f_ip_factor = 1 / fabs(avctx->i_quant_factor); + x4->params.rc.f_pb_factor = avctx->b_quant_factor; + x4->params.analyse.i_chroma_qp_offset = avctx->chromaoffset; + + x4->params.analyse.b_psnr = avctx->flags & CODEC_FLAG_PSNR; + x4->params.i_log_level = XAVS_LOG_DEBUG; + x4->params.i_threads = avctx->thread_count; + x4->params.b_interlaced = avctx->flags & CODEC_FLAG_INTERLACED_DCT; + + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) + x4->params.b_repeat_headers = 0; + + x4->enc = xavs_encoder_open(&x4->params); + if (!x4->enc) + return -1; + + if (!(x4->pts_buffer = av_mallocz((avctx->max_b_frames+1) * sizeof(*x4->pts_buffer)))) + return AVERROR(ENOMEM); + + avctx->coded_frame = &x4->out_pic; + /* TAG: Do we have GLOBAL HEADER in AVS */ + /* We Have PPS and SPS in AVS */ + if (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) { + xavs_nal_t *nal; + int nnal, s, i, size; + uint8_t *p; + + s = xavs_encoder_headers(x4->enc, &nal, &nnal); + + avctx->extradata = p = av_malloc(s); + for (i = 0; i < nnal; i++) { + /* Don't put the SEI in extradata. */ + if (nal[i].i_type == NAL_SEI) { + x4->sei = av_malloc( 5 + nal[i].i_payload * 4 / 3 ); + if (xavs_nal_encode(x4->sei, &x4->sei_size, 1, nal + i) < 0) + return -1; + + continue; + } + size = xavs_nal_encode(p, &s, 1, nal + i); + if (size < 0) + return -1; + p += size; + } + avctx->extradata_size = p - avctx->extradata; + } + return 0; +} + +#define OFFSET(x) offsetof(XavsContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "crf", "Select the quality for constant quality mode", OFFSET(crf), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE }, + { "qp", "Constant quantization parameter rate control method",OFFSET(cqp), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, VE }, + { "b-bias", "Influences how often B-frames are used", OFFSET(b_bias), AV_OPT_TYPE_INT, {.i64 = INT_MIN}, INT_MIN, INT_MAX, VE }, + { "cplxblur", "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE}, + { "direct-pred", "Direct MV prediction mode", OFFSET(direct_pred), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, VE, "direct-pred" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_NONE }, 0, 0, VE, "direct-pred" }, + { "spatial", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_SPATIAL }, 0, 0, VE, "direct-pred" }, + { "temporal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_TEMPORAL }, 0, 0, VE, "direct-pred" }, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = XAVS_DIRECT_PRED_AUTO }, 0, 0, VE, "direct-pred" }, + { "aud", "Use access unit delimiters.", OFFSET(aud), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 1, VE}, + { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 1, VE}, + { "mixed-refs", "One reference per partition, as opposed to one reference per macroblock", OFFSET(mixed_refs), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE }, + { "fast-pskip", NULL, OFFSET(fast_pskip), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 1, VE}, + { NULL }, +}; + +static const AVClass class = { + .class_name = "libxavs", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVCodecDefault xavs_defaults[] = { + { "b", "0" }, + { NULL }, +}; + +AVCodec ff_libxavs_encoder = { + .name = "libxavs", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_CAVS, + .priv_data_size = sizeof(XavsContext), + .init = XAVS_init, + .encode2 = XAVS_frame, + .close = XAVS_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"), + .priv_class = &class, + .defaults = xavs_defaults, +}; diff --git a/ffmpeg/libavcodec/libxvid.c b/ffmpeg/libavcodec/libxvid.c new file mode 100644 index 0000000..05a12db --- /dev/null +++ b/ffmpeg/libavcodec/libxvid.c @@ -0,0 +1,775 @@ +/* + * Interface to xvidcore for mpeg4 encoding + * Copyright (c) 2004 Adam Thayer + * + * 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 + */ + +/** + * @file + * Interface to xvidcore for MPEG-4 compliant encoding. + * @author Adam Thayer (krevnik@comcast.net) + */ + +#include +#include +#include "avcodec.h" +#include "internal.h" +#include "libavutil/file.h" +#include "libavutil/cpu.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" +#include "libxvid.h" +#include "mpegvideo.h" + +/** + * Buffer management macros. + */ +#define BUFFER_SIZE 1024 +#define BUFFER_REMAINING(x) (BUFFER_SIZE - strlen(x)) +#define BUFFER_CAT(x) (&((x)[strlen(x)])) + +/** + * Structure for the private Xvid context. + * This stores all the private context for the codec. + */ +struct xvid_context { + void *encoder_handle; /**< Handle for Xvid encoder */ + int xsize; /**< Frame x size */ + int ysize; /**< Frame y size */ + int vop_flags; /**< VOP flags for Xvid encoder */ + int vol_flags; /**< VOL flags for Xvid encoder */ + int me_flags; /**< Motion Estimation flags */ + int qscale; /**< Do we use constant scale? */ + int quicktime_format; /**< Are we in a QT-based format? */ + AVFrame encoded_picture; /**< Encoded frame information */ + char *twopassbuffer; /**< Character buffer for two-pass */ + char *old_twopassbuffer; /**< Old character buffer (two-pass) */ + char *twopassfile; /**< second pass temp file name */ + int twopassfd; + unsigned char *intra_matrix; /**< P-Frame Quant Matrix */ + unsigned char *inter_matrix; /**< I-Frame Quant Matrix */ +}; + +/** + * Structure for the private first-pass plugin. + */ +struct xvid_ff_pass1 { + int version; /**< Xvid version */ + struct xvid_context *context; /**< Pointer to private context */ +}; + +static int xvid_encode_close(AVCodecContext *avctx); + +/* + * Xvid 2-Pass Kludge Section + * + * Xvid's default 2-pass doesn't allow us to create data as we need to, so + * this section spends time replacing the first pass plugin so we can write + * statistic information as libavcodec requests in. We have another kludge + * that allows us to pass data to the second pass in Xvid without a custom + * rate-control plugin. + */ + +/** + * Initialize the two-pass plugin and context. + * + * @param param Input construction parameter structure + * @param handle Private context handle + * @return Returns XVID_ERR_xxxx on failure, or 0 on success. + */ +static int xvid_ff_2pass_create(xvid_plg_create_t * param, + void ** handle) { + struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; + char *log = x->context->twopassbuffer; + + /* Do a quick bounds check */ + if( log == NULL ) + return XVID_ERR_FAIL; + + /* We use snprintf() */ + /* This is because we can safely prevent a buffer overflow */ + log[0] = 0; + snprintf(log, BUFFER_REMAINING(log), + "# ffmpeg 2-pass log file, using xvid codec\n"); + snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), + "# Do not modify. libxvidcore version: %d.%d.%d\n\n", + XVID_VERSION_MAJOR(XVID_VERSION), + XVID_VERSION_MINOR(XVID_VERSION), + XVID_VERSION_PATCH(XVID_VERSION)); + + *handle = x->context; + return 0; +} + +/** + * Destroy the two-pass plugin context. + * + * @param ref Context pointer for the plugin + * @param param Destrooy context + * @return Returns 0, success guaranteed + */ +static int xvid_ff_2pass_destroy(struct xvid_context *ref, + xvid_plg_destroy_t *param) { + /* Currently cannot think of anything to do on destruction */ + /* Still, the framework should be here for reference/use */ + if( ref->twopassbuffer != NULL ) + ref->twopassbuffer[0] = 0; + return 0; +} + +/** + * Enable fast encode mode during the first pass. + * + * @param ref Context pointer for the plugin + * @param param Frame data + * @return Returns 0, success guaranteed + */ +static int xvid_ff_2pass_before(struct xvid_context *ref, + xvid_plg_data_t *param) { + int motion_remove; + int motion_replacements; + int vop_remove; + + /* Nothing to do here, result is changed too much */ + if( param->zone && param->zone->mode == XVID_ZONE_QUANT ) + return 0; + + /* We can implement a 'turbo' first pass mode here */ + param->quant = 2; + + /* Init values */ + motion_remove = ~XVID_ME_CHROMA_PVOP & + ~XVID_ME_CHROMA_BVOP & + ~XVID_ME_EXTSEARCH16 & + ~XVID_ME_ADVANCEDDIAMOND16; + motion_replacements = XVID_ME_FAST_MODEINTERPOLATE | + XVID_ME_SKIP_DELTASEARCH | + XVID_ME_FASTREFINE16 | + XVID_ME_BFRAME_EARLYSTOP; + vop_remove = ~XVID_VOP_MODEDECISION_RD & + ~XVID_VOP_FAST_MODEDECISION_RD & + ~XVID_VOP_TRELLISQUANT & + ~XVID_VOP_INTER4V & + ~XVID_VOP_HQACPRED; + + param->vol_flags &= ~XVID_VOL_GMC; + param->vop_flags &= vop_remove; + param->motion_flags &= motion_remove; + param->motion_flags |= motion_replacements; + + return 0; +} + +/** + * Capture statistic data and write it during first pass. + * + * @param ref Context pointer for the plugin + * @param param Statistic data + * @return Returns XVID_ERR_xxxx on failure, or 0 on success + */ +static int xvid_ff_2pass_after(struct xvid_context *ref, + xvid_plg_data_t *param) { + char *log = ref->twopassbuffer; + const char *frame_types = " ipbs"; + char frame_type; + + /* Quick bounds check */ + if( log == NULL ) + return XVID_ERR_FAIL; + + /* Convert the type given to us into a character */ + if( param->type < 5 && param->type > 0 ) { + frame_type = frame_types[param->type]; + } else { + return XVID_ERR_FAIL; + } + + snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), + "%c %d %d %d %d %d %d\n", + frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks, + param->stats.ublks, param->stats.length, param->stats.hlength); + + return 0; +} + +/** + * Dispatch function for our custom plugin. + * This handles the dispatch for the Xvid plugin. It passes data + * on to other functions for actual processing. + * + * @param ref Context pointer for the plugin + * @param cmd The task given for us to complete + * @param p1 First parameter (varies) + * @param p2 Second parameter (varies) + * @return Returns XVID_ERR_xxxx on failure, or 0 on success + */ +static int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) +{ + switch( cmd ) { + case XVID_PLG_INFO: + case XVID_PLG_FRAME: + return 0; + + case XVID_PLG_BEFORE: + return xvid_ff_2pass_before(ref, p1); + + case XVID_PLG_CREATE: + return xvid_ff_2pass_create(p1, p2); + + case XVID_PLG_AFTER: + return xvid_ff_2pass_after(ref, p1); + + case XVID_PLG_DESTROY: + return xvid_ff_2pass_destroy(ref, p1); + + default: + return XVID_ERR_FAIL; + } +} + +/** + * Routine to create a global VO/VOL header for MP4 container. + * What we do here is extract the header from the Xvid bitstream + * as it is encoded. We also strip the repeated headers from the + * bitstream when a global header is requested for MPEG-4 ISO + * compliance. + * + * @param avctx AVCodecContext pointer to context + * @param frame Pointer to encoded frame data + * @param header_len Length of header to search + * @param frame_len Length of encoded frame data + * @return Returns new length of frame data + */ +static int xvid_strip_vol_header(AVCodecContext *avctx, + AVPacket *pkt, + unsigned int header_len, + unsigned int frame_len) { + int vo_len = 0, i; + + for( i = 0; i < header_len - 3; i++ ) { + if( pkt->data[i] == 0x00 && + pkt->data[i+1] == 0x00 && + pkt->data[i+2] == 0x01 && + pkt->data[i+3] == 0xB6 ) { + vo_len = i; + break; + } + } + + if( vo_len > 0 ) { + /* We need to store the header, so extract it */ + if( avctx->extradata == NULL ) { + avctx->extradata = av_malloc(vo_len); + memcpy(avctx->extradata, pkt->data, vo_len); + avctx->extradata_size = vo_len; + } + /* Less dangerous now, memmove properly copies the two + chunks of overlapping data */ + memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len); + pkt->size = frame_len - vo_len; + } + return 0; +} + +/** + * Routine to correct a possibly erroneous framerate being fed to us. + * Xvid currently chokes on framerates where the ticks per frame is + * extremely large. This function works to correct problems in this area + * by estimating a new framerate and taking the simpler fraction of + * the two presented. + * + * @param avctx Context that contains the framerate to correct. + */ +static void xvid_correct_framerate(AVCodecContext *avctx) +{ + int frate, fbase; + int est_frate, est_fbase; + int gcd; + float est_fps, fps; + + frate = avctx->time_base.den; + fbase = avctx->time_base.num; + + gcd = av_gcd(frate, fbase); + if( gcd > 1 ) { + frate /= gcd; + fbase /= gcd; + } + + if( frate <= 65000 && fbase <= 65000 ) { + avctx->time_base.den = frate; + avctx->time_base.num = fbase; + return; + } + + fps = (float)frate / (float)fbase; + est_fps = roundf(fps * 1000.0) / 1000.0; + + est_frate = (int)est_fps; + if( est_fps > (int)est_fps ) { + est_frate = (est_frate + 1) * 1000; + est_fbase = (int)roundf((float)est_frate / est_fps); + } else + est_fbase = 1; + + gcd = av_gcd(est_frate, est_fbase); + if( gcd > 1 ) { + est_frate /= gcd; + est_fbase /= gcd; + } + + if( fbase > est_fbase ) { + avctx->time_base.den = est_frate; + avctx->time_base.num = est_fbase; + av_log(avctx, AV_LOG_DEBUG, + "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", + est_fps, (((est_fps - fps)/fps) * 100.0)); + } else { + avctx->time_base.den = frate; + avctx->time_base.num = fbase; + } +} + +static av_cold int xvid_encode_init(AVCodecContext *avctx) { + int xerr, i; + int xvid_flags = avctx->flags; + struct xvid_context *x = avctx->priv_data; + uint16_t *intra, *inter; + int fd; + + xvid_plugin_single_t single = { 0 }; + struct xvid_ff_pass1 rc2pass1 = { 0 }; + xvid_plugin_2pass2_t rc2pass2 = { 0 }; + xvid_gbl_init_t xvid_gbl_init = { 0 }; + xvid_enc_create_t xvid_enc_create = { 0 }; + xvid_enc_plugin_t plugins[7]; + + x->twopassfd = -1; + + /* Bring in VOP flags from ffmpeg command-line */ + x->vop_flags = XVID_VOP_HALFPEL; /* Bare minimum quality */ + if( xvid_flags & CODEC_FLAG_4MV ) + x->vop_flags |= XVID_VOP_INTER4V; /* Level 3 */ + if( avctx->trellis + ) + x->vop_flags |= XVID_VOP_TRELLISQUANT; /* Level 5 */ + if( xvid_flags & CODEC_FLAG_AC_PRED ) + x->vop_flags |= XVID_VOP_HQACPRED; /* Level 6 */ + if( xvid_flags & CODEC_FLAG_GRAY ) + x->vop_flags |= XVID_VOP_GREYSCALE; + + /* Decide which ME quality setting to use */ + x->me_flags = 0; + switch( avctx->me_method ) { + case ME_FULL: /* Quality 6 */ + x->me_flags |= XVID_ME_EXTSEARCH16 + | XVID_ME_EXTSEARCH8; + + case ME_EPZS: /* Quality 4 */ + x->me_flags |= XVID_ME_ADVANCEDDIAMOND8 + | XVID_ME_HALFPELREFINE8 + | XVID_ME_CHROMA_PVOP + | XVID_ME_CHROMA_BVOP; + + case ME_LOG: /* Quality 2 */ + case ME_PHODS: + case ME_X1: + x->me_flags |= XVID_ME_ADVANCEDDIAMOND16 + | XVID_ME_HALFPELREFINE16; + + case ME_ZERO: /* Quality 0 */ + default: + break; + } + + /* Decide how we should decide blocks */ + switch( avctx->mb_decision ) { + case 2: + x->vop_flags |= XVID_VOP_MODEDECISION_RD; + x->me_flags |= XVID_ME_HALFPELREFINE8_RD + | XVID_ME_QUARTERPELREFINE8_RD + | XVID_ME_EXTSEARCH_RD + | XVID_ME_CHECKPREDICTION_RD; + case 1: + if( !(x->vop_flags & XVID_VOP_MODEDECISION_RD) ) + x->vop_flags |= XVID_VOP_FAST_MODEDECISION_RD; + x->me_flags |= XVID_ME_HALFPELREFINE16_RD + | XVID_ME_QUARTERPELREFINE16_RD; + + default: + break; + } + + /* Bring in VOL flags from ffmpeg command-line */ + x->vol_flags = 0; + if( xvid_flags & CODEC_FLAG_GMC ) { + x->vol_flags |= XVID_VOL_GMC; + x->me_flags |= XVID_ME_GME_REFINE; + } + if( xvid_flags & CODEC_FLAG_QPEL ) { + x->vol_flags |= XVID_VOL_QUARTERPEL; + x->me_flags |= XVID_ME_QUARTERPELREFINE16; + if( x->vop_flags & XVID_VOP_INTER4V ) + x->me_flags |= XVID_ME_QUARTERPELREFINE8; + } + + xvid_gbl_init.version = XVID_VERSION; + xvid_gbl_init.debug = 0; + +#if ARCH_PPC + /* Xvid's PPC support is borked, use libavcodec to detect */ +#if HAVE_ALTIVEC + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { + xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ALTIVEC; + } else +#endif + xvid_gbl_init.cpu_flags = XVID_CPU_FORCE; +#else + /* Xvid can detect on x86 */ + xvid_gbl_init.cpu_flags = 0; +#endif + + /* Initialize */ + xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL); + + /* Create the encoder reference */ + xvid_enc_create.version = XVID_VERSION; + + /* Store the desired frame size */ + xvid_enc_create.width = x->xsize = avctx->width; + xvid_enc_create.height = x->ysize = avctx->height; + + /* Xvid can determine the proper profile to use */ + /* xvid_enc_create.profile = XVID_PROFILE_S_L3; */ + + /* We don't use zones */ + xvid_enc_create.zones = NULL; + xvid_enc_create.num_zones = 0; + + xvid_enc_create.num_threads = avctx->thread_count; + + xvid_enc_create.plugins = plugins; + xvid_enc_create.num_plugins = 0; + + /* Initialize Buffers */ + x->twopassbuffer = NULL; + x->old_twopassbuffer = NULL; + x->twopassfile = NULL; + + if( xvid_flags & CODEC_FLAG_PASS1 ) { + rc2pass1.version = XVID_VERSION; + rc2pass1.context = x; + x->twopassbuffer = av_malloc(BUFFER_SIZE); + x->old_twopassbuffer = av_malloc(BUFFER_SIZE); + if( x->twopassbuffer == NULL || x->old_twopassbuffer == NULL ) { + av_log(avctx, AV_LOG_ERROR, + "Xvid: Cannot allocate 2-pass log buffers\n"); + goto fail; + } + x->twopassbuffer[0] = x->old_twopassbuffer[0] = 0; + + plugins[xvid_enc_create.num_plugins].func = xvid_ff_2pass; + plugins[xvid_enc_create.num_plugins].param = &rc2pass1; + xvid_enc_create.num_plugins++; + } else if( xvid_flags & CODEC_FLAG_PASS2 ) { + rc2pass2.version = XVID_VERSION; + rc2pass2.bitrate = avctx->bit_rate; + + fd = av_tempfile("xvidff.", &x->twopassfile, 0, avctx); + if( fd == -1 ) { + av_log(avctx, AV_LOG_ERROR, + "Xvid: Cannot write 2-pass pipe\n"); + goto fail; + } + x->twopassfd = fd; + + if( avctx->stats_in == NULL ) { + av_log(avctx, AV_LOG_ERROR, + "Xvid: No 2-pass information loaded for second pass\n"); + goto fail; + } + + if( strlen(avctx->stats_in) > + write(fd, avctx->stats_in, strlen(avctx->stats_in)) ) { + av_log(avctx, AV_LOG_ERROR, + "Xvid: Cannot write to 2-pass pipe\n"); + goto fail; + } + + rc2pass2.filename = x->twopassfile; + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2; + plugins[xvid_enc_create.num_plugins].param = &rc2pass2; + xvid_enc_create.num_plugins++; + } else if( !(xvid_flags & CODEC_FLAG_QSCALE) ) { + /* Single Pass Bitrate Control! */ + single.version = XVID_VERSION; + single.bitrate = avctx->bit_rate; + + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single; + plugins[xvid_enc_create.num_plugins].param = &single; + xvid_enc_create.num_plugins++; + } + + /* Luminance Masking */ + if( 0.0 != avctx->lumi_masking ) { + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking; + plugins[xvid_enc_create.num_plugins].param = NULL; + xvid_enc_create.num_plugins++; + } + + /* Frame Rate and Key Frames */ + xvid_correct_framerate(avctx); + xvid_enc_create.fincr = avctx->time_base.num; + xvid_enc_create.fbase = avctx->time_base.den; + if( avctx->gop_size > 0 ) + xvid_enc_create.max_key_interval = avctx->gop_size; + else + xvid_enc_create.max_key_interval = 240; /* Xvid's best default */ + + /* Quants */ + if( xvid_flags & CODEC_FLAG_QSCALE ) x->qscale = 1; + else x->qscale = 0; + + xvid_enc_create.min_quant[0] = avctx->qmin; + xvid_enc_create.min_quant[1] = avctx->qmin; + xvid_enc_create.min_quant[2] = avctx->qmin; + xvid_enc_create.max_quant[0] = avctx->qmax; + xvid_enc_create.max_quant[1] = avctx->qmax; + xvid_enc_create.max_quant[2] = avctx->qmax; + + /* Quant Matrices */ + x->intra_matrix = x->inter_matrix = NULL; + if( avctx->mpeg_quant ) + x->vol_flags |= XVID_VOL_MPEGQUANT; + if( (avctx->intra_matrix || avctx->inter_matrix) ) { + x->vol_flags |= XVID_VOL_MPEGQUANT; + + if( avctx->intra_matrix ) { + intra = avctx->intra_matrix; + x->intra_matrix = av_malloc(sizeof(unsigned char) * 64); + } else + intra = NULL; + if( avctx->inter_matrix ) { + inter = avctx->inter_matrix; + x->inter_matrix = av_malloc(sizeof(unsigned char) * 64); + } else + inter = NULL; + + for( i = 0; i < 64; i++ ) { + if( intra ) + x->intra_matrix[i] = (unsigned char)intra[i]; + if( inter ) + x->inter_matrix[i] = (unsigned char)inter[i]; + } + } + + /* Misc Settings */ + xvid_enc_create.frame_drop_ratio = 0; + xvid_enc_create.global = 0; + if( xvid_flags & CODEC_FLAG_CLOSED_GOP ) + xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP; + + /* Determines which codec mode we are operating in */ + avctx->extradata = NULL; + avctx->extradata_size = 0; + if( xvid_flags & CODEC_FLAG_GLOBAL_HEADER ) { + /* In this case, we are claiming to be MPEG4 */ + x->quicktime_format = 1; + avctx->codec_id = AV_CODEC_ID_MPEG4; + } else { + /* We are claiming to be Xvid */ + x->quicktime_format = 0; + if(!avctx->codec_tag) + avctx->codec_tag = AV_RL32("xvid"); + } + + /* Bframes */ + xvid_enc_create.max_bframes = avctx->max_b_frames; + xvid_enc_create.bquant_offset = 100 * avctx->b_quant_offset; + xvid_enc_create.bquant_ratio = 100 * avctx->b_quant_factor; + if( avctx->max_b_frames > 0 && !x->quicktime_format ) xvid_enc_create.global |= XVID_GLOBAL_PACKED; + + /* Create encoder context */ + xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); + if( xerr ) { + av_log(avctx, AV_LOG_ERROR, "Xvid: Could not create encoder reference\n"); + goto fail; + } + + x->encoder_handle = xvid_enc_create.handle; + avctx->coded_frame = &x->encoded_picture; + + return 0; +fail: + xvid_encode_close(avctx); + return -1; +} + +static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *picture, int *got_packet) +{ + int xerr, i, ret, user_packet = !!pkt->data; + char *tmp; + struct xvid_context *x = avctx->priv_data; + AVFrame *p = &x->encoded_picture; + int mb_width = (avctx->width + 15) / 16; + int mb_height = (avctx->height + 15) / 16; + + xvid_enc_frame_t xvid_enc_frame = { 0 }; + xvid_enc_stats_t xvid_enc_stats = { 0 }; + + if ((ret = ff_alloc_packet2(avctx, pkt, mb_width*mb_height*MAX_MB_BYTES + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + /* Start setting up the frame */ + xvid_enc_frame.version = XVID_VERSION; + xvid_enc_stats.version = XVID_VERSION; + *p = *picture; + + /* Let Xvid know where to put the frame. */ + xvid_enc_frame.bitstream = pkt->data; + xvid_enc_frame.length = pkt->size; + + /* Initialize input image fields */ + if( avctx->pix_fmt != AV_PIX_FMT_YUV420P ) { + av_log(avctx, AV_LOG_ERROR, "Xvid: Color spaces other than 420p not supported\n"); + return -1; + } + + xvid_enc_frame.input.csp = XVID_CSP_PLANAR; /* YUV420P */ + + for( i = 0; i < 4; i++ ) { + xvid_enc_frame.input.plane[i] = picture->data[i]; + xvid_enc_frame.input.stride[i] = picture->linesize[i]; + } + + /* Encoder Flags */ + xvid_enc_frame.vop_flags = x->vop_flags; + xvid_enc_frame.vol_flags = x->vol_flags; + xvid_enc_frame.motion = x->me_flags; + xvid_enc_frame.type = + picture->pict_type == AV_PICTURE_TYPE_I ? XVID_TYPE_IVOP : + picture->pict_type == AV_PICTURE_TYPE_P ? XVID_TYPE_PVOP : + picture->pict_type == AV_PICTURE_TYPE_B ? XVID_TYPE_BVOP : + XVID_TYPE_AUTO; + + /* Pixel aspect ratio setting */ + if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.num > 255 || + avctx->sample_aspect_ratio.den < 0 || avctx->sample_aspect_ratio.den > 255) { + av_log(avctx, AV_LOG_ERROR, "Invalid pixel aspect ratio %i/%i\n", + avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); + return -1; + } + xvid_enc_frame.par = XVID_PAR_EXT; + xvid_enc_frame.par_width = avctx->sample_aspect_ratio.num; + xvid_enc_frame.par_height = avctx->sample_aspect_ratio.den; + + /* Quant Setting */ + if( x->qscale ) xvid_enc_frame.quant = picture->quality / FF_QP2LAMBDA; + else xvid_enc_frame.quant = 0; + + /* Matrices */ + xvid_enc_frame.quant_intra_matrix = x->intra_matrix; + xvid_enc_frame.quant_inter_matrix = x->inter_matrix; + + /* Encode */ + xerr = xvid_encore(x->encoder_handle, XVID_ENC_ENCODE, + &xvid_enc_frame, &xvid_enc_stats); + + /* Two-pass log buffer swapping */ + avctx->stats_out = NULL; + if( x->twopassbuffer ) { + tmp = x->old_twopassbuffer; + x->old_twopassbuffer = x->twopassbuffer; + x->twopassbuffer = tmp; + x->twopassbuffer[0] = 0; + if( x->old_twopassbuffer[0] != 0 ) { + avctx->stats_out = x->old_twopassbuffer; + } + } + + if (xerr > 0) { + *got_packet = 1; + + p->quality = xvid_enc_stats.quant * FF_QP2LAMBDA; + if( xvid_enc_stats.type == XVID_TYPE_PVOP ) + p->pict_type = AV_PICTURE_TYPE_P; + else if( xvid_enc_stats.type == XVID_TYPE_BVOP ) + p->pict_type = AV_PICTURE_TYPE_B; + else if( xvid_enc_stats.type == XVID_TYPE_SVOP ) + p->pict_type = AV_PICTURE_TYPE_S; + else + p->pict_type = AV_PICTURE_TYPE_I; + if( xvid_enc_frame.out_flags & XVID_KEYFRAME ) { + p->key_frame = 1; + pkt->flags |= AV_PKT_FLAG_KEY; + if( x->quicktime_format ) + return xvid_strip_vol_header(avctx, pkt, + xvid_enc_stats.hlength, xerr); + } else + p->key_frame = 0; + + pkt->size = xerr; + + return 0; + } else { + if (!user_packet) + av_free_packet(pkt); + if (!xerr) + return 0; + av_log(avctx, AV_LOG_ERROR, "Xvid: Encoding Error Occurred: %i\n", xerr); + return -1; + } +} + +static av_cold int xvid_encode_close(AVCodecContext *avctx) { + struct xvid_context *x = avctx->priv_data; + + if(x->encoder_handle) + xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL); + x->encoder_handle = NULL; + + av_freep(&avctx->extradata); + if( x->twopassbuffer != NULL ) { + av_freep(&x->twopassbuffer); + av_freep(&x->old_twopassbuffer); + avctx->stats_out = NULL; + } + if (x->twopassfd>=0) { + unlink(x->twopassfile); + close(x->twopassfd); + x->twopassfd = -1; + } + av_freep(&x->twopassfile); + av_freep(&x->intra_matrix); + av_freep(&x->inter_matrix); + + return 0; +} + +AVCodec ff_libxvid_encoder = { + .name = "libxvid", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .priv_data_size = sizeof(struct xvid_context), + .init = xvid_encode_init, + .encode2 = xvid_encode_frame, + .close = xvid_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("libxvidcore MPEG-4 part 2"), +}; diff --git a/ffmpeg/libavcodec/libxvid.h b/ffmpeg/libavcodec/libxvid.h new file mode 100644 index 0000000..90ecd6f --- /dev/null +++ b/ffmpeg/libavcodec/libxvid.h @@ -0,0 +1,32 @@ +/* + * copyright (C) 2006 Corey Hickey + * + * 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 + */ + +#ifndef AVCODEC_LIBXVID_H +#define AVCODEC_LIBXVID_H + +/** + * @file + * common functions for use with the Xvid wrappers + */ + + +int ff_tempfile(const char *prefix, char **filename); + +#endif /* AVCODEC_LIBXVID_H */ diff --git a/ffmpeg/libavcodec/libxvid_rc.c b/ffmpeg/libavcodec/libxvid_rc.c new file mode 100644 index 0000000..4a5842f --- /dev/null +++ b/ffmpeg/libavcodec/libxvid_rc.c @@ -0,0 +1,141 @@ +/* + * Xvid rate control wrapper for lavc video encoders + * + * Copyright (c) 2006 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 "config.h" +#include +#include +#include "libavutil/file.h" +#include "avcodec.h" +#include "libxvid.h" +#include "mpegvideo.h" + +#undef NDEBUG +#include + +int ff_xvid_rate_control_init(MpegEncContext *s){ + char *tmp_name; + int fd, i; + xvid_plg_create_t xvid_plg_create = { 0 }; + xvid_plugin_2pass2_t xvid_2pass2 = { 0 }; + + fd=av_tempfile("xvidrc.", &tmp_name, 0, s->avctx); + if (fd == -1) { + av_log(NULL, AV_LOG_ERROR, "Can't create temporary pass2 file.\n"); + return -1; + } + + for(i=0; irc_context.num_entries; i++){ + static const char frame_types[] = " ipbs"; + char tmp[256]; + RateControlEntry *rce; + + rce= &s->rc_context.entry[i]; + + snprintf(tmp, sizeof(tmp), "%c %d %d %d %d %d %d\n", + frame_types[rce->pict_type], (int)lrintf(rce->qscale / FF_QP2LAMBDA), rce->i_count, s->mb_num - rce->i_count - rce->skip_count, + rce->skip_count, (rce->i_tex_bits + rce->p_tex_bits + rce->misc_bits+7)/8, (rce->header_bits+rce->mv_bits+7)/8); + + if (write(fd, tmp, strlen(tmp)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Error %s writing 2pass logfile\n", strerror(errno)); + av_free(tmp_name); + close(fd); + return AVERROR(errno); + } + } + + close(fd); + + xvid_2pass2.version= XVID_MAKE_VERSION(1,1,0); + xvid_2pass2.filename= tmp_name; + xvid_2pass2.bitrate= s->avctx->bit_rate; + xvid_2pass2.vbv_size= s->avctx->rc_buffer_size; + xvid_2pass2.vbv_maxrate= s->avctx->rc_max_rate; + xvid_2pass2.vbv_initial= s->avctx->rc_initial_buffer_occupancy; + + xvid_plg_create.version= XVID_MAKE_VERSION(1,1,0); + xvid_plg_create.fbase= s->avctx->time_base.den; + xvid_plg_create.fincr= s->avctx->time_base.num; + xvid_plg_create.param= &xvid_2pass2; + + if(xvid_plugin_2pass2(NULL, XVID_PLG_CREATE, &xvid_plg_create, &s->rc_context.non_lavc_opaque)<0){ + av_log(NULL, AV_LOG_ERROR, "xvid_plugin_2pass2 failed\n"); + return -1; + } + return 0; +} + +float ff_xvid_rate_estimate_qscale(MpegEncContext *s, int dry_run){ + xvid_plg_data_t xvid_plg_data = { 0 }; + + xvid_plg_data.version= XVID_MAKE_VERSION(1,1,0); + xvid_plg_data.width = s->width; + xvid_plg_data.height= s->height; + xvid_plg_data.mb_width = s->mb_width; + xvid_plg_data.mb_height= s->mb_height; + xvid_plg_data.fbase= s->avctx->time_base.den; + xvid_plg_data.fincr= s->avctx->time_base.num; + xvid_plg_data.min_quant[0]= s->avctx->qmin; + xvid_plg_data.min_quant[1]= s->avctx->qmin; + xvid_plg_data.min_quant[2]= s->avctx->qmin; //FIXME i/b factor & offset + xvid_plg_data.max_quant[0]= s->avctx->qmax; + xvid_plg_data.max_quant[1]= s->avctx->qmax; + xvid_plg_data.max_quant[2]= s->avctx->qmax; //FIXME i/b factor & offset + xvid_plg_data.bquant_offset = 0; // 100 * s->avctx->b_quant_offset; + xvid_plg_data.bquant_ratio = 100; // * s->avctx->b_quant_factor; + + if(!s->rc_context.dry_run_qscale){ + if(s->picture_number){ + xvid_plg_data.length= + xvid_plg_data.stats.length= (s->frame_bits + 7)/8; + xvid_plg_data.frame_num= s->rc_context.last_picture_number; + xvid_plg_data.quant= s->qscale; + + xvid_plg_data.type= s->last_pict_type; + if(xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, XVID_PLG_AFTER, &xvid_plg_data, NULL)){ + av_log(s->avctx, AV_LOG_ERROR, "xvid_plugin_2pass2(handle, XVID_PLG_AFTER, ...) FAILED\n"); + return -1; + } + } + s->rc_context.last_picture_number= + xvid_plg_data.frame_num= s->picture_number; + xvid_plg_data.quant= 0; + if(xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, XVID_PLG_BEFORE, &xvid_plg_data, NULL)){ + av_log(s->avctx, AV_LOG_ERROR, "xvid_plugin_2pass2(handle, XVID_PLG_BEFORE, ...) FAILED\n"); + return -1; + } + s->rc_context.dry_run_qscale= xvid_plg_data.quant; + } + xvid_plg_data.quant= s->rc_context.dry_run_qscale; + if(!dry_run) + s->rc_context.dry_run_qscale= 0; + + if(s->pict_type == AV_PICTURE_TYPE_B) //FIXME this is not exactly identical to xvid + return xvid_plg_data.quant * FF_QP2LAMBDA * s->avctx->b_quant_factor + s->avctx->b_quant_offset; + else + return xvid_plg_data.quant * FF_QP2LAMBDA; +} + +void ff_xvid_rate_control_uninit(MpegEncContext *s){ + xvid_plg_destroy_t xvid_plg_destroy; + + xvid_plugin_2pass2(s->rc_context.non_lavc_opaque, XVID_PLG_DESTROY, &xvid_plg_destroy, NULL); +} diff --git a/ffmpeg/libavcodec/ljpegenc.c b/ffmpeg/libavcodec/ljpegenc.c new file mode 100644 index 0000000..76c3cb9 --- /dev/null +++ b/ffmpeg/libavcodec/ljpegenc.c @@ -0,0 +1,236 @@ +/* + * lossless JPEG encoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * lossless JPEG encoder. + */ + +#include "avcodec.h" +#include "internal.h" +#include "mpegvideo.h" +#include "mjpeg.h" +#include "mjpegenc.h" + + +static int encode_picture_lossless(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + MpegEncContext * const s = avctx->priv_data; + MJpegContext * const m = s->mjpeg_ctx; + const int width= s->width; + const int height= s->height; + AVFrame * const p = &s->current_picture.f; + const int predictor= avctx->prediction_method+1; + const int mb_width = (width + s->mjpeg_hsample[0] - 1) / s->mjpeg_hsample[0]; + const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0]; + int ret, max_pkt_size = FF_MIN_BUFFER_SIZE; + + if (avctx->pix_fmt == AV_PIX_FMT_BGRA) + max_pkt_size += width * height * 3 * 4; + else { + max_pkt_size += mb_width * mb_height * 3 * 4 + * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]; + } + + if (!s->edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(s, pict->linesize[0])) < 0) { + av_log(avctx, AV_LOG_ERROR, "failed to allocate context scratch buffers.\n"); + return ret; + } + + if ((ret = ff_alloc_packet2(avctx, pkt, max_pkt_size)) < 0) + return ret; + + init_put_bits(&s->pb, pkt->data, pkt->size); + + av_frame_unref(p); + ret = av_frame_ref(p, pict); + if (ret < 0) + return ret; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + ff_mjpeg_encode_picture_header(s); + + s->header_bits= put_bits_count(&s->pb); + + if(avctx->pix_fmt == AV_PIX_FMT_BGR0 + || avctx->pix_fmt == AV_PIX_FMT_BGRA + || avctx->pix_fmt == AV_PIX_FMT_BGR24){ + int x, y, i; + const int linesize= p->linesize[0]; + uint16_t (*buffer)[4]= (void *) s->rd_scratchpad; + int left[3], top[3], topleft[3]; + + for(i=0; i<3; i++){ + buffer[0][i]= 1 << (9 - 1); + } + + for(y = 0; y < height; y++) { + const int modified_predictor= y ? predictor : 1; + uint8_t *ptr = p->data[0] + (linesize * y); + + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < width*3*4){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + + for(i=0; i<3; i++){ + top[i]= left[i]= topleft[i]= buffer[0][i]; + } + for(x = 0; x < width; x++) { + if(avctx->pix_fmt == AV_PIX_FMT_BGR24){ + buffer[x][1] = ptr[3*x+0] - ptr[3*x+1] + 0x100; + buffer[x][2] = ptr[3*x+2] - ptr[3*x+1] + 0x100; + buffer[x][0] = (ptr[3*x+0] + 2*ptr[3*x+1] + ptr[3*x+2])>>2; + }else{ + buffer[x][1] = ptr[4*x+0] - ptr[4*x+1] + 0x100; + buffer[x][2] = ptr[4*x+2] - ptr[4*x+1] + 0x100; + buffer[x][0] = (ptr[4*x+0] + 2*ptr[4*x+1] + ptr[4*x+2])>>2; + } + + for(i=0;i<3;i++) { + int pred, diff; + + PREDICT(pred, topleft[i], top[i], left[i], modified_predictor); + + topleft[i]= top[i]; + top[i]= buffer[x+1][i]; + + left[i]= buffer[x][i]; + + diff= ((left[i] - pred + 0x100)&0x1FF) - 0x100; + + if(i==0) + ff_mjpeg_encode_dc(s, diff, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly + else + ff_mjpeg_encode_dc(s, diff, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); + } + } + } + }else{ + int mb_x, mb_y, i; + + for(mb_y = 0; mb_y < mb_height; mb_y++) { + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < mb_width * 4 * 3 * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + for(mb_x = 0; mb_x < mb_width; mb_x++) { + if(mb_x==0 || mb_y==0){ + for(i=0;i<3;i++) { + uint8_t *ptr; + int x, y, h, v, linesize; + h = s->mjpeg_hsample[i]; + v = s->mjpeg_vsample[i]; + linesize= p->linesize[i]; + + for(y=0; ydata[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + if(y==0 && mb_y==0){ + if(x==0 && mb_x==0){ + pred= 128; + }else{ + pred= ptr[-1]; + } + }else{ + if(x==0 && mb_x==0){ + pred= ptr[-linesize]; + }else{ + PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); + } + } + + if(i==0) + ff_mjpeg_encode_dc(s, *ptr - pred, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly + else + ff_mjpeg_encode_dc(s, *ptr - pred, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); + } + } + } + }else{ + for(i=0;i<3;i++) { + uint8_t *ptr; + int x, y, h, v, linesize; + h = s->mjpeg_hsample[i]; + v = s->mjpeg_vsample[i]; + linesize= p->linesize[i]; + + for(y=0; ydata[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); + + if(i==0) + ff_mjpeg_encode_dc(s, *ptr - pred, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly + else + ff_mjpeg_encode_dc(s, *ptr - pred, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); + } + } + } + } + } + } + } + + emms_c(); + av_assert0(s->esc_pos == s->header_bits >> 3); + ff_mjpeg_encode_stuffing(s); + ff_mjpeg_encode_picture_trailer(s); + s->picture_number++; + + flush_put_bits(&s->pb); + pkt->size = put_bits_ptr(&s->pb) - s->pb.buf; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +// return (put_bits_count(&f->pb)+7)/8; +} + + +AVCodec ff_ljpeg_encoder = { //FIXME avoid MPV_* lossless JPEG should not need them + .name = "ljpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_LJPEG, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = encode_picture_lossless, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_BGR0, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), +}; diff --git a/ffmpeg/libavcodec/loco.c b/ffmpeg/libavcodec/loco.c new file mode 100644 index 0000000..ffb9742 --- /dev/null +++ b/ffmpeg/libavcodec/loco.c @@ -0,0 +1,312 @@ +/* + * LOCO codec + * Copyright (c) 2005 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * LOCO codec. + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "golomb.h" +#include "internal.h" +#include "mathops.h" + +enum LOCO_MODE { + LOCO_UNKN = 0, + LOCO_CYUY2 = -1, + LOCO_CRGB = -2, + LOCO_CRGBA = -3, + LOCO_CYV12 = -4, + LOCO_YUY2 = 1, + LOCO_UYVY = 2, + LOCO_RGB = 3, + LOCO_RGBA = 4, + LOCO_YV12 = 5, +}; + +typedef struct LOCOContext { + AVCodecContext *avctx; + int lossy; + int mode; +} LOCOContext; + +typedef struct RICEContext { + GetBitContext gb; + int save, run, run2; /* internal rice decoder state */ + int sum, count; /* sum and count for getting rice parameter */ + int lossy; +} RICEContext; + +static int loco_get_rice_param(RICEContext *r) +{ + int cnt = 0; + int val = r->count; + + while (r->sum > val && cnt < 9) { + val <<= 1; + cnt++; + } + + return cnt; +} + +static inline void loco_update_rice_param(RICEContext *r, int val) +{ + r->sum += val; + r->count++; + + if (r->count == 16) { + r->sum >>= 1; + r->count >>= 1; + } +} + +static inline int loco_get_rice(RICEContext *r) +{ + int v; + if (r->run > 0) { /* we have zero run */ + r->run--; + loco_update_rice_param(r, 0); + return 0; + } + v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); + loco_update_rice_param(r, (v + 1) >> 1); + if (!v) { + if (r->save >= 0) { + r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); + if (r->run > 1) + r->save += r->run + 1; + else + r->save -= 3; + } else + r->run2++; + } else { + v = ((v >> 1) + r->lossy) ^ -(v & 1); + if (r->run2 > 0) { + if (r->run2 > 2) + r->save += r->run2; + else + r->save -= 3; + r->run2 = 0; + } + } + + return v; +} + +/* LOCO main predictor - LOCO-I/JPEG-LS predictor */ +static inline int loco_predict(uint8_t* data, int stride, int step) +{ + int a, b, c; + + a = data[-stride]; + b = data[-step]; + c = data[-stride - step]; + + return mid_pred(a, a + b - c, b); +} + +static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, + int stride, const uint8_t *buf, int buf_size, int step) +{ + RICEContext rc; + int val; + int i, j; + + if(buf_size<=0) + return -1; + + init_get_bits(&rc.gb, buf, buf_size*8); + rc.save = 0; + rc.run = 0; + rc.run2 = 0; + rc.lossy = l->lossy; + + rc.sum = 8; + rc.count = 1; + + /* restore top left pixel */ + val = loco_get_rice(&rc); + data[0] = 128 + val; + /* restore top line */ + for (i = 1; i < width; i++) { + val = loco_get_rice(&rc); + data[i * step] = data[i * step - step] + val; + } + data += stride; + for (j = 1; j < height; j++) { + /* restore left column */ + val = loco_get_rice(&rc); + data[0] = data[-stride] + val; + /* restore all other pixels */ + for (i = 1; i < width; i++) { + val = loco_get_rice(&rc); + data[i * step] = loco_predict(&data[i * step], stride, step) + val; + } + data += stride; + } + + return (get_bits_count(&rc.gb) + 7) >> 3; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + LOCOContext * const l = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame * const p = data; + int decoded, ret; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->key_frame = 1; + +#define ADVANCE_BY_DECODED do { \ + if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \ + buf += decoded; buf_size -= decoded; \ +} while(0) + switch(l->mode) { + case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: + decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, + p->linesize[0], buf, buf_size, 1); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, + p->linesize[1], buf, buf_size, 1); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, + p->linesize[2], buf, buf_size, 1); + break; + case LOCO_CYV12: case LOCO_YV12: + decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, + p->linesize[0], buf, buf_size, 1); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, + p->linesize[2], buf, buf_size, 1); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, + p->linesize[1], buf, buf_size, 1); + break; + case LOCO_CRGB: case LOCO_RGB: + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 3); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 3); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 3); + break; + case LOCO_CRGBA: + case LOCO_RGBA: + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 4); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 4); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 4); + ADVANCE_BY_DECODED; + decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height, + -p->linesize[0], buf, buf_size, 4); + break; + default: + av_assert0(0); + } + + if (decoded < 0 || decoded > buf_size) + goto buf_too_small; + buf_size -= decoded; + + *got_frame = 1; + + return avpkt->size - buf_size; +buf_too_small: + av_log(avctx, AV_LOG_ERROR, "Input data too small.\n"); + return AVERROR(EINVAL); +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + LOCOContext * const l = avctx->priv_data; + int version; + + l->avctx = avctx; + if (avctx->extradata_size < 12) { + av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + version = AV_RL32(avctx->extradata); + switch (version) { + case 1: + l->lossy = 0; + break; + case 2: + l->lossy = AV_RL32(avctx->extradata + 8); + break; + default: + l->lossy = AV_RL32(avctx->extradata + 8); + avpriv_request_sample(avctx, "LOCO codec version %i", version); + } + + l->mode = AV_RL32(avctx->extradata + 4); + switch (l->mode) { + case LOCO_CYUY2: + case LOCO_YUY2: + case LOCO_UYVY: + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + break; + case LOCO_CRGB: + case LOCO_RGB: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case LOCO_CYV12: + case LOCO_YV12: + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + break; + case LOCO_CRGBA: + case LOCO_RGBA: + avctx->pix_fmt = AV_PIX_FMT_BGRA; + break; + default: + av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); + return AVERROR_INVALIDDATA; + } + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); + + return 0; +} + +AVCodec ff_loco_decoder = { + .name = "loco", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_LOCO, + .priv_data_size = sizeof(LOCOContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LOCO"), +}; diff --git a/ffmpeg/libavcodec/log2_tab.c b/ffmpeg/libavcodec/log2_tab.c new file mode 100644 index 0000000..47a1df0 --- /dev/null +++ b/ffmpeg/libavcodec/log2_tab.c @@ -0,0 +1 @@ +#include "libavutil/log2_tab.c" diff --git a/ffmpeg/libavcodec/lpc.c b/ffmpeg/libavcodec/lpc.c new file mode 100644 index 0000000..4149135 --- /dev/null +++ b/ffmpeg/libavcodec/lpc.c @@ -0,0 +1,287 @@ +/* + * LPC utility code + * Copyright (c) 2006 Justin Ruggles + * + * 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 "libavutil/common.h" +#include "libavutil/lls.h" + +#define LPC_USE_DOUBLE +#include "lpc.h" +#include "libavutil/avassert.h" + + +/** + * Apply Welch window function to audio block + */ +static void lpc_apply_welch_window_c(const int32_t *data, int len, + double *w_data) +{ + int i, n2; + double w; + double c; + + /* The optimization in commit fa4ed8c does not support odd len. + * If someone wants odd len extend that change. */ + av_assert2(!(len & 1)); + + n2 = (len >> 1); + c = 2.0 / (len - 1.0); + + w_data+=n2; + data+=n2; + for(i=0; i qmax) && (sh > 0)) { + sh--; + } + + /* since negative shift values are unsupported in decoder, scale down + coefficients instead */ + if(sh == 0 && cmax > qmax) { + double scale = ((double)qmax) / cmax; + for(i=0; i=min_order-1; i--) { + if(ref[i] > 0.10) { + est = i+1; + break; + } + } + return est; +} + +int ff_lpc_calc_ref_coefs(LPCContext *s, + const int32_t *samples, int order, double *ref) +{ + double autoc[MAX_LPC_ORDER + 1]; + + s->lpc_apply_welch_window(samples, s->blocksize, s->windowed_samples); + s->lpc_compute_autocorr(s->windowed_samples, s->blocksize, order, autoc); + compute_ref_coefs(autoc, order, ref, NULL); + + return order; +} + +/** + * Calculate LPC coefficients for multiple orders + * + * @param lpc_type LPC method for determining coefficients, + * see #FFLPCType for details + */ +int ff_lpc_calc_coefs(LPCContext *s, + const int32_t *samples, int blocksize, int min_order, + int max_order, int precision, + int32_t coefs[][MAX_LPC_ORDER], int *shift, + enum FFLPCType lpc_type, int lpc_passes, + int omethod, int max_shift, int zero_shift) +{ + double autoc[MAX_LPC_ORDER+1]; + double ref[MAX_LPC_ORDER]; + double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER]; + int i, j, pass; + int opt_order; + + av_assert2(max_order >= MIN_LPC_ORDER && max_order <= MAX_LPC_ORDER && + lpc_type > FF_LPC_TYPE_FIXED); + + /* reinit LPC context if parameters have changed */ + if (blocksize != s->blocksize || max_order != s->max_order || + lpc_type != s->lpc_type) { + ff_lpc_end(s); + ff_lpc_init(s, blocksize, max_order, lpc_type); + } + + if (lpc_type == FF_LPC_TYPE_LEVINSON) { + s->lpc_apply_welch_window(samples, blocksize, s->windowed_samples); + + s->lpc_compute_autocorr(s->windowed_samples, blocksize, max_order, autoc); + + compute_lpc_coefs(autoc, max_order, &lpc[0][0], MAX_LPC_ORDER, 0, 1); + + for(i=0; i>pass) + fabs(eval - var[0]); + inv = 1/eval; + rinv = sqrt(inv); + for(j=0; j<=max_order; j++) + var[j] *= rinv; + weight += inv; + }else + weight++; + + avpriv_update_lls(&m[pass&1], var, 1.0); + } + avpriv_solve_lls(&m[pass&1], 0.001, 0); + } + + for(i=0; i0; i--) + ref[i] = ref[i-1] - ref[i]; + } else + av_assert0(0); + opt_order = max_order; + + if(omethod == ORDER_METHOD_EST) { + opt_order = estimate_best_order(ref, min_order, max_order); + i = opt_order-1; + quantize_lpc_coefs(lpc[i], i+1, precision, coefs[i], &shift[i], max_shift, zero_shift); + } else { + for(i=min_order-1; iblocksize = blocksize; + s->max_order = max_order; + s->lpc_type = lpc_type; + + if (lpc_type == FF_LPC_TYPE_LEVINSON) { + s->windowed_buffer = av_mallocz((blocksize + 2 + FFALIGN(max_order, 4)) * + sizeof(*s->windowed_samples)); + if (!s->windowed_buffer) + return AVERROR(ENOMEM); + s->windowed_samples = s->windowed_buffer + FFALIGN(max_order, 4); + } else { + s->windowed_samples = NULL; + } + + s->lpc_apply_welch_window = lpc_apply_welch_window_c; + s->lpc_compute_autocorr = lpc_compute_autocorr_c; + + if (ARCH_X86) + ff_lpc_init_x86(s); + + return 0; +} + +av_cold void ff_lpc_end(LPCContext *s) +{ + av_freep(&s->windowed_buffer); +} diff --git a/ffmpeg/libavcodec/lpc.h b/ffmpeg/libavcodec/lpc.h new file mode 100644 index 0000000..8fa56ad --- /dev/null +++ b/ffmpeg/libavcodec/lpc.h @@ -0,0 +1,197 @@ +/* + * LPC utility code + * Copyright (c) 2006 Justin Ruggles + * + * 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 + */ + +#ifndef AVCODEC_LPC_H +#define AVCODEC_LPC_H + +#include +#include "libavutil/avassert.h" + +#define ORDER_METHOD_EST 0 +#define ORDER_METHOD_2LEVEL 1 +#define ORDER_METHOD_4LEVEL 2 +#define ORDER_METHOD_8LEVEL 3 +#define ORDER_METHOD_SEARCH 4 +#define ORDER_METHOD_LOG 5 + +#define MIN_LPC_ORDER 1 +#define MAX_LPC_ORDER 32 + +/** + * LPC analysis type + */ +enum FFLPCType { + FF_LPC_TYPE_DEFAULT = -1, ///< use the codec default LPC type + FF_LPC_TYPE_NONE = 0, ///< do not use LPC prediction or use all zero coefficients + FF_LPC_TYPE_FIXED = 1, ///< fixed LPC coefficients + FF_LPC_TYPE_LEVINSON = 2, ///< Levinson-Durbin recursion + FF_LPC_TYPE_CHOLESKY = 3, ///< Cholesky factorization + FF_LPC_TYPE_NB , ///< Not part of ABI +}; + +typedef struct LPCContext { + int blocksize; + int max_order; + enum FFLPCType lpc_type; + double *windowed_buffer; + double *windowed_samples; + + /** + * Apply a Welch window to an array of input samples. + * The output samples have the same scale as the input, but are in double + * sample format. + * @param data input samples + * @param len number of input samples + * @param w_data output samples + */ + void (*lpc_apply_welch_window)(const int32_t *data, int len, + double *w_data); + /** + * Perform autocorrelation on input samples with delay of 0 to lag. + * @param data input samples. + * constraints: no alignment needed, but must have have at + * least lag*sizeof(double) valid bytes preceding it, and + * size must be at least (len+1)*sizeof(double) if data is + * 16-byte aligned or (len+2)*sizeof(double) if data is + * unaligned. + * @param len number of input samples to process + * @param lag maximum delay to calculate + * @param autoc output autocorrelation coefficients. + * constraints: array size must be at least lag+1. + */ + void (*lpc_compute_autocorr)(const double *data, int len, int lag, + double *autoc); +} LPCContext; + + +/** + * Calculate LPC coefficients for multiple orders + */ +int ff_lpc_calc_coefs(LPCContext *s, + const int32_t *samples, int blocksize, int min_order, + int max_order, int precision, + int32_t coefs[][MAX_LPC_ORDER], int *shift, + enum FFLPCType lpc_type, int lpc_passes, + int omethod, int max_shift, int zero_shift); + +int ff_lpc_calc_ref_coefs(LPCContext *s, + const int32_t *samples, int order, double *ref); + +/** + * Initialize LPCContext. + */ +int ff_lpc_init(LPCContext *s, int blocksize, int max_order, + enum FFLPCType lpc_type); +void ff_lpc_init_x86(LPCContext *s); + +/** + * Uninitialize LPCContext. + */ +void ff_lpc_end(LPCContext *s); + +#ifdef LPC_USE_DOUBLE +#define LPC_TYPE double +#else +#define LPC_TYPE float +#endif + +/** + * Schur recursion. + * Produces reflection coefficients from autocorrelation data. + */ +static inline void compute_ref_coefs(const LPC_TYPE *autoc, int max_order, + LPC_TYPE *ref, LPC_TYPE *error) +{ + int i, j; + LPC_TYPE err; + LPC_TYPE gen0[MAX_LPC_ORDER], gen1[MAX_LPC_ORDER]; + + for (i = 0; i < max_order; i++) + gen0[i] = gen1[i] = autoc[i + 1]; + + err = autoc[0]; + ref[0] = -gen1[0] / err; + err += gen1[0] * ref[0]; + if (error) + error[0] = err; + for (i = 1; i < max_order; i++) { + for (j = 0; j < max_order - i; j++) { + gen1[j] = gen1[j + 1] + ref[i - 1] * gen0[j]; + gen0[j] = gen1[j + 1] * ref[i - 1] + gen0[j]; + } + ref[i] = -gen1[0] / err; + err += gen1[0] * ref[i]; + if (error) + error[i] = err; + } +} + +/** + * Levinson-Durbin recursion. + * Produce LPC coefficients from autocorrelation data. + */ +static inline int compute_lpc_coefs(const LPC_TYPE *autoc, int max_order, + LPC_TYPE *lpc, int lpc_stride, int fail, + int normalize) +{ + int i, j; + LPC_TYPE err; + LPC_TYPE *lpc_last = lpc; + + av_assert2(normalize || !fail); + + if (normalize) + err = *autoc++; + + if (fail && (autoc[max_order - 1] == 0 || err <= 0)) + return -1; + + for(i=0; i>1; j++) { + LPC_TYPE f = lpc_last[ j]; + LPC_TYPE b = lpc_last[i-1-j]; + lpc[ j] = f + r * b; + lpc[i-1-j] = b + r * f; + } + + if (fail && err < 0) + return -1; + + lpc_last = lpc; + lpc += lpc_stride; + } + + return 0; +} + +#endif /* AVCODEC_LPC_H */ diff --git a/ffmpeg/libavcodec/lsp.c b/ffmpeg/libavcodec/lsp.c new file mode 100644 index 0000000..17f59ea --- /dev/null +++ b/ffmpeg/libavcodec/lsp.c @@ -0,0 +1,235 @@ +/* + * LSP routines for ACELP-based codecs + * + * Copyright (c) 2007 Reynaldo H. Verdejo Pinochet (QCELP decoder) + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 "avcodec.h" +#define FRAC_BITS 14 +#include "mathops.h" +#include "lsp.h" +#include "libavcodec/mips/lsp_mips.h" +#include "libavutil/avassert.h" + +void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, int lsfq_max, int lp_order) +{ + int i, j; + + /* sort lsfq in ascending order. float bubble agorithm, + O(n) if data already sorted, O(n^2) - otherwise */ + for(i=0; i=0 && lsfq[j] > lsfq[j+1]; j--) + FFSWAP(int16_t, lsfq[j], lsfq[j+1]); + + for(i=0; i> 8; + + av_assert2(arg <= 0x3fff); + + return tab_cos[ind] + (offset * (tab_cos[ind+1] - tab_cos[ind]) >> 8); +} + +void ff_acelp_lsf2lsp(int16_t *lsp, const int16_t *lsf, int lp_order) +{ + int i; + + /* Convert LSF to LSP, lsp=cos(lsf) */ + for(i=0; i> 15); // divide by PI and (0,13) -> (0,14) +} + +void ff_acelp_lsf2lspd(double *lsp, const float *lsf, int lp_order) +{ + int i; + + for(i = 0; i < lp_order; i++) + lsp[i] = cos(2.0 * M_PI * lsf[i]); +} + +/** + * @brief decodes polynomial coefficients from LSP + * @param[out] f decoded polynomial coefficients (-0x20000000 <= (3.22) <= 0x1fffffff) + * @param lsp LSP coefficients (-0x8000 <= (0.15) <= 0x7fff) + */ +static void lsp2poly(int* f, const int16_t* lsp, int lp_half_order) +{ + int i, j; + + f[0] = 0x400000; // 1.0 in (3.22) + f[1] = -lsp[0] << 8; // *2 and (0.15) -> (3.22) + + for(i=2; i<=lp_half_order; i++) + { + f[i] = f[i-2]; + for(j=i; j>1; j--) + f[j] -= MULL(f[j-1], lsp[2*i-2], FRAC_BITS) - f[j-2]; + + f[1] -= lsp[2*i-2] << 8; + } +} + +void ff_acelp_lsp2lpc(int16_t* lp, const int16_t* lsp, int lp_half_order) +{ + int i; + int f1[MAX_LP_HALF_ORDER+1]; // (3.22) + int f2[MAX_LP_HALF_ORDER+1]; // (3.22) + + lsp2poly(f1, lsp , lp_half_order); + lsp2poly(f2, lsp+1, lp_half_order); + + /* 3.2.6 of G.729, Equations 25 and 26*/ + lp[0] = 4096; + for(i=1; i> 11; // divide by 2 and (3.22) -> (3.12) + lp[(lp_half_order << 1) + 1 - i] = (ff1 - ff2) >> 11; // divide by 2 and (3.22) -> (3.12) + } +} + +void ff_amrwb_lsp2lpc(const double *lsp, float *lp, int lp_order) +{ + int lp_half_order = lp_order >> 1; + double buf[MAX_LP_HALF_ORDER + 1]; + double pa[MAX_LP_HALF_ORDER + 1]; + double *qa = buf + 1; + int i,j; + + qa[-1] = 0.0; + + ff_lsp2polyf(lsp , pa, lp_half_order ); + ff_lsp2polyf(lsp + 1, qa, lp_half_order - 1); + + for (i = 1, j = lp_order - 1; i < lp_half_order; i++, j--) { + double paf = pa[i] * (1 + lsp[lp_order - 1]); + double qaf = (qa[i] - qa[i-2]) * (1 - lsp[lp_order - 1]); + lp[i-1] = (paf + qaf) * 0.5; + lp[j-1] = (paf - qaf) * 0.5; + } + + lp[lp_half_order - 1] = (1.0 + lsp[lp_order - 1]) * + pa[lp_half_order] * 0.5; + + lp[lp_order - 1] = lsp[lp_order - 1]; +} + +void ff_acelp_lp_decode(int16_t* lp_1st, int16_t* lp_2nd, const int16_t* lsp_2nd, const int16_t* lsp_prev, int lp_order) +{ + int16_t lsp_1st[MAX_LP_ORDER]; // (0.15) + int i; + + /* LSP values for first subframe (3.2.5 of G.729, Equation 24)*/ + for(i=0; i> 1) + (lsp_prev[i] >> 1); +#else + lsp_1st[i] = (lsp_2nd[i] + lsp_prev[i]) >> 1; +#endif + + ff_acelp_lsp2lpc(lp_1st, lsp_1st, lp_order >> 1); + + /* LSP values for second subframe (3.2.5 of G.729)*/ + ff_acelp_lsp2lpc(lp_2nd, lsp_2nd, lp_order >> 1); +} + +#ifndef ff_lsp2polyf +void ff_lsp2polyf(const double *lsp, double *f, int lp_half_order) +{ + int i, j; + + f[0] = 1.0; + f[1] = -2 * lsp[0]; + lsp -= 2; + for(i=2; i<=lp_half_order; i++) + { + double val = -2 * lsp[2*i]; + f[i] = val * f[i-1] + 2*f[i-2]; + for(j=i-1; j>1; j--) + f[j] += f[j-1] * val + f[j-2]; + f[1] += val; + } +} +#endif /* ff_lsp2polyf */ + +void ff_acelp_lspd2lpc(const double *lsp, float *lpc, int lp_half_order) +{ + double pa[MAX_LP_HALF_ORDER+1], qa[MAX_LP_HALF_ORDER+1]; + float *lpc2 = lpc + (lp_half_order << 1) - 1; + + av_assert2(lp_half_order <= MAX_LP_HALF_ORDER); + + ff_lsp2polyf(lsp, pa, lp_half_order); + ff_lsp2polyf(lsp + 1, qa, lp_half_order); + + while (lp_half_order--) { + double paf = pa[lp_half_order+1] + pa[lp_half_order]; + double qaf = qa[lp_half_order+1] - qa[lp_half_order]; + + lpc [ lp_half_order] = 0.5*(paf+qaf); + lpc2[-lp_half_order] = 0.5*(paf-qaf); + } +} + +void ff_sort_nearly_sorted_floats(float *vals, int len) +{ + int i,j; + + for (i = 0; i < len - 1; i++) + for (j = i; j >= 0 && vals[j] > vals[j+1]; j--) + FFSWAP(float, vals[j], vals[j+1]); +} diff --git a/ffmpeg/libavcodec/lsp.h b/ffmpeg/libavcodec/lsp.h new file mode 100644 index 0000000..46a2d47 --- /dev/null +++ b/ffmpeg/libavcodec/lsp.h @@ -0,0 +1,130 @@ +/* + * LSP computing for ACELP-based codecs + * + * Copyright (c) 2008 Vladimir Voroshilov + * + * 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 + */ + +#ifndef AVCODEC_LSP_H +#define AVCODEC_LSP_H + +#include + +/** + (I.F) means fixed-point value with F fractional and I integer bits +*/ + +/** + * @brief ensure a minimum distance between LSFs + * @param[in,out] lsfq LSF to check and adjust + * @param lsfq_min_distance minimum distance between LSFs + * @param lsfq_min minimum allowed LSF value + * @param lsfq_max maximum allowed LSF value + * @param lp_order LP filter order + */ +void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, int lsfq_max, int lp_order); + +/** + * Adjust the quantized LSFs so they are increasing and not too close. + * + * This step is not mentioned in the AMR spec but is in the reference C decoder. + * Omitting this step creates audible distortion on the sinusoidal sweep + * test vectors in 3GPP TS 26.074. + * + * @param[in,out] lsf LSFs in Hertz + * @param min_spacing minimum distance between two consecutive lsf values + * @param size size of the lsf vector + */ +void ff_set_min_dist_lsf(float *lsf, double min_spacing, int size); + +/** + * @brief Convert LSF to LSP + * @param[out] lsp LSP coefficients (-0x8000 <= (0.15) < 0x8000) + * @param lsf normalized LSF coefficients (0 <= (2.13) < 0x2000 * PI) + * @param lp_order LP filter order + * + * @remark It is safe to pass the same array into the lsf and lsp parameters. + */ +void ff_acelp_lsf2lsp(int16_t *lsp, const int16_t *lsf, int lp_order); + +/** + * Floating point version of ff_acelp_lsf2lsp() + */ +void ff_acelp_lsf2lspd(double *lsp, const float *lsf, int lp_order); + +/** + * @brief LSP to LP conversion (3.2.6 of G.729) + * @param[out] lp decoded LP coefficients (-0x8000 <= (3.12) < 0x8000) + * @param lsp LSP coefficients (-0x8000 <= (0.15) < 0x8000) + * @param lp_half_order LP filter order, divided by 2 + */ +void ff_acelp_lsp2lpc(int16_t* lp, const int16_t* lsp, int lp_half_order); + +/** + * LSP to LP conversion (5.2.4 of AMR-WB) + */ +void ff_amrwb_lsp2lpc(const double *lsp, float *lp, int lp_order); + +/** + * @brief Interpolate LSP for the first subframe and convert LSP -> LP for both subframes (3.2.5 and 3.2.6 of G.729) + * @param[out] lp_1st decoded LP coefficients for first subframe (-0x8000 <= (3.12) < 0x8000) + * @param[out] lp_2nd decoded LP coefficients for second subframe (-0x8000 <= (3.12) < 0x8000) + * @param lsp_2nd LSP coefficients of the second subframe (-0x8000 <= (0.15) < 0x8000) + * @param lsp_prev LSP coefficients from the second subframe of the previous frame (-0x8000 <= (0.15) < 0x8000) + * @param lp_order LP filter order + */ +void ff_acelp_lp_decode(int16_t* lp_1st, int16_t* lp_2nd, const int16_t* lsp_2nd, const int16_t* lsp_prev, int lp_order); + + +#define MAX_LP_HALF_ORDER 10 +#define MAX_LP_ORDER (2*MAX_LP_HALF_ORDER) + +/** + * Reconstruct LPC coefficients from the line spectral pair frequencies. + * + * @param lsp line spectral pairs in cosine domain + * @param lpc linear predictive coding coefficients + * @param lp_half_order half the number of the amount of LPCs to be + * reconstructed, need to be smaller or equal to MAX_LP_HALF_ORDER + * + * @note buffers should have a minimux size of 2*lp_half_order elements. + * + * TIA/EIA/IS-733 2.4.3.3.5 + */ +void ff_acelp_lspd2lpc(const double *lsp, float *lpc, int lp_half_order); + +/** + * Sort values in ascending order. + * + * @note O(n) if data already sorted, O(n^2) - otherwise + */ +void ff_sort_nearly_sorted_floats(float *vals, int len); + +/** + * Compute the Pa / (1 + z(-1)) or Qa / (1 - z(-1)) coefficients + * needed for LSP to LPC conversion. + * We only need to calculate the 6 first elements of the polynomial. + * + * @param lsp line spectral pairs in cosine domain + * @param[out] f polynomial input/output as a vector + * + * TIA/EIA/IS-733 2.4.3.3.5-1/2 + */ +void ff_lsp2polyf(const double *lsp, double *f, int lp_half_order); + +#endif /* AVCODEC_LSP_H */ diff --git a/ffmpeg/libavcodec/lzw.c b/ffmpeg/libavcodec/lzw.c new file mode 100644 index 0000000..43e3e05 --- /dev/null +++ b/ffmpeg/libavcodec/lzw.c @@ -0,0 +1,234 @@ +/* + * LZW decoder + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * @brief LZW decoding routines + * @author Fabrice Bellard + * @author modified for use in TIFF by Konstantin Shishkov + */ + +#include "avcodec.h" +#include "lzw.h" +#include "libavutil/mem.h" + +#define LZW_MAXBITS 12 +#define LZW_SIZTABLE (1<mode == FF_LZW_GIF) { + while (s->bbits < s->cursize) { + if (!s->bs) { + s->bs = *s->pbuf++; + } + s->bbuf |= (*s->pbuf++) << s->bbits; + s->bbits += 8; + s->bs--; + } + c = s->bbuf; + s->bbuf >>= s->cursize; + } else { // TIFF + while (s->bbits < s->cursize) { + s->bbuf = (s->bbuf << 8) | (*s->pbuf++); + s->bbits += 8; + } + c = s->bbuf >> (s->bbits - s->cursize); + } + s->bbits -= s->cursize; + return c & s->curmask; +} + +void ff_lzw_decode_tail(LZWState *p) +{ + struct LZWState *s = (struct LZWState *)p; + + if(s->mode == FF_LZW_GIF) { + while (s->bs > 0) { + if (s->bs >= s->ebuf - s->pbuf) { + s->pbuf = s->ebuf; + break; + } else { + s->pbuf += s->bs; + s->bs = *s->pbuf++; + } + } + }else + s->pbuf= s->ebuf; +} + +av_cold void ff_lzw_decode_open(LZWState **p) +{ + *p = av_mallocz(sizeof(struct LZWState)); +} + +av_cold void ff_lzw_decode_close(LZWState **p) +{ + av_freep(p); +} + +/** + * Initialize LZW decoder + * @param p LZW context + * @param csize initial code size in bits + * @param buf input data + * @param buf_size input data size + * @param mode decoder working mode - either GIF or TIFF + */ +int ff_lzw_decode_init(LZWState *p, int csize, const uint8_t *buf, int buf_size, int mode) +{ + struct LZWState *s = (struct LZWState *)p; + + if(csize < 1 || csize >= LZW_MAXBITS) + return -1; + /* read buffer */ + s->pbuf = buf; + s->ebuf = s->pbuf + buf_size; + s->bbuf = 0; + s->bbits = 0; + s->bs = 0; + + /* decoder */ + s->codesize = csize; + s->cursize = s->codesize + 1; + s->curmask = mask[s->cursize]; + s->top_slot = 1 << s->cursize; + s->clear_code = 1 << s->codesize; + s->end_code = s->clear_code + 1; + s->slot = s->newcodes = s->clear_code + 2; + s->oc = s->fc = -1; + s->sp = s->stack; + + s->mode = mode; + s->extra_slot = s->mode == FF_LZW_TIFF; + return 0; +} + +/** + * Decode given number of bytes + * NOTE: the algorithm here is inspired from the LZW GIF decoder + * written by Steven A. Bennett in 1987. + * + * @param p LZW context + * @param buf output buffer + * @param len number of bytes to decode + * @return number of bytes decoded + */ +int ff_lzw_decode(LZWState *p, uint8_t *buf, int len){ + int l, c, code, oc, fc; + uint8_t *sp; + struct LZWState *s = (struct LZWState *)p; + + if (s->end_code < 0) + return 0; + + l = len; + sp = s->sp; + oc = s->oc; + fc = s->fc; + + for (;;) { + while (sp > s->stack) { + *buf++ = *(--sp); + if ((--l) == 0) + goto the_end; + } + if (s->ebuf < s->pbuf) { + av_log(NULL, AV_LOG_ERROR, "lzw overread\n"); + goto the_end; + } + c = lzw_get_code(s); + if (c == s->end_code) { + break; + } else if (c == s->clear_code) { + s->cursize = s->codesize + 1; + s->curmask = mask[s->cursize]; + s->slot = s->newcodes; + s->top_slot = 1 << s->cursize; + fc= oc= -1; + } else { + code = c; + if (code == s->slot && fc>=0) { + *sp++ = fc; + code = oc; + }else if(code >= s->slot) + break; + while (code >= s->newcodes) { + *sp++ = s->suffix[code]; + code = s->prefix[code]; + } + *sp++ = code; + if (s->slot < s->top_slot && oc>=0) { + s->suffix[s->slot] = code; + s->prefix[s->slot++] = oc; + } + fc = code; + oc = c; + if (s->slot >= s->top_slot - s->extra_slot) { + if (s->cursize < LZW_MAXBITS) { + s->top_slot <<= 1; + s->curmask = mask[++s->cursize]; + } + } + } + } + s->end_code = -1; + the_end: + s->sp = sp; + s->oc = oc; + s->fc = fc; + return len - l; +} diff --git a/ffmpeg/libavcodec/lzw.h b/ffmpeg/libavcodec/lzw.h new file mode 100644 index 0000000..4653c1c --- /dev/null +++ b/ffmpeg/libavcodec/lzw.h @@ -0,0 +1,63 @@ +/* + * LZW decoder + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * @brief LZW decoding routines + * @author Fabrice Bellard + * @author modified for use in TIFF by Konstantin Shishkov + */ + +#ifndef AVCODEC_LZW_H +#define AVCODEC_LZW_H + +#include + +struct PutBitContext; + +enum FF_LZW_MODES{ + FF_LZW_GIF, + FF_LZW_TIFF +}; + +/* clients should not know what LZWState is */ +typedef void LZWState; + +/* first two functions de/allocate memory for LZWState */ +void ff_lzw_decode_open(LZWState **p); +void ff_lzw_decode_close(LZWState **p); +int ff_lzw_decode_init(LZWState *s, int csize, const uint8_t *buf, int buf_size, int mode); +int ff_lzw_decode(LZWState *s, uint8_t *buf, int len); +void ff_lzw_decode_tail(LZWState *lzw); + +/** LZW encode state */ +struct LZWEncodeState; +extern const int ff_lzw_encode_state_size; + +void ff_lzw_encode_init(struct LZWEncodeState *s, uint8_t *outbuf, int outsize, + int maxbits, enum FF_LZW_MODES mode, + void (*lzw_put_bits)(struct PutBitContext *, int, unsigned int)); +int ff_lzw_encode(struct LZWEncodeState * s, const uint8_t * inbuf, int insize); +int ff_lzw_encode_flush(struct LZWEncodeState *s, + void (*lzw_flush_put_bits)(struct PutBitContext *)); + +#endif /* AVCODEC_LZW_H */ diff --git a/ffmpeg/libavcodec/lzwenc.c b/ffmpeg/libavcodec/lzwenc.c new file mode 100644 index 0000000..7e30765 --- /dev/null +++ b/ffmpeg/libavcodec/lzwenc.c @@ -0,0 +1,269 @@ +/* + * LZW encoder + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +/** + * @file + * LZW encoder + * @author Bartlomiej Wolowiec + */ + +#include "avcodec.h" +#include "put_bits.h" +#include "lzw.h" + +#define LZW_MAXBITS 12 +#define LZW_SIZTABLE (1<= LZW_HASH_SIZE) + head -= LZW_HASH_SIZE; + av_assert2(head >= 0 && head < LZW_HASH_SIZE); + return head; +} + +/** + * Hash function calculates next hash value + * @param head Actual hash code + * @param offset Offset calculated by hashOffset + * @return New hash value + */ +static inline int hashNext(int head, const int offset) +{ + head -= offset; + if(head < 0) + head += LZW_HASH_SIZE; + return head; +} + +/** + * Hash function calculates hash offset + * @param head Actual hash code + * @return Hash offset + */ +static inline int hashOffset(const int head) +{ + return head ? LZW_HASH_SIZE - head : 1; +} + +/** + * Write one code to stream + * @param s LZW state + * @param c code to write + */ +static inline void writeCode(LZWEncodeState * s, int c) +{ + assert(0 <= c && c < 1 << s->bits); + s->put_bits(&s->pb, s->bits, c); +} + + +/** + * Find LZW code for block + * @param s LZW state + * @param c Last character in block + * @param hash_prefix LZW code for prefix + * @return LZW code for block or -1 if not found in table + */ +static inline int findCode(LZWEncodeState * s, uint8_t c, int hash_prefix) +{ + int h = hash(FFMAX(hash_prefix, 0), c); + int hash_offset = hashOffset(h); + + while (s->tab[h].hash_prefix != LZW_PREFIX_FREE) { + if ((s->tab[h].suffix == c) + && (s->tab[h].hash_prefix == hash_prefix)) + return h; + h = hashNext(h, hash_offset); + } + + return h; +} + +/** + * Add block to LZW code table + * @param s LZW state + * @param c Last character in block + * @param hash_prefix LZW code for prefix + * @param hash_code LZW code for bytes block + */ +static inline void addCode(LZWEncodeState * s, uint8_t c, int hash_prefix, int hash_code) +{ + s->tab[hash_code].code = s->tabsize; + s->tab[hash_code].suffix = c; + s->tab[hash_code].hash_prefix = hash_prefix; + + s->tabsize++; + + if (s->tabsize >= (1 << s->bits) + (s->mode == FF_LZW_GIF)) + s->bits++; +} + +/** + * Clear LZW code table + * @param s LZW state + */ +static void clearTable(LZWEncodeState * s) +{ + int i, h; + + writeCode(s, s->clear_code); + s->bits = 9; + for (i = 0; i < LZW_HASH_SIZE; i++) { + s->tab[i].hash_prefix = LZW_PREFIX_FREE; + } + for (i = 0; i < 256; i++) { + h = hash(0, i); + s->tab[h].code = i; + s->tab[h].suffix = i; + s->tab[h].hash_prefix = LZW_PREFIX_EMPTY; + } + s->tabsize = 258; +} + +/** + * Calculate number of bytes written + * @param s LZW encode state + * @return Number of bytes written + */ +static int writtenBytes(LZWEncodeState *s){ + int ret = put_bits_count(&s->pb) >> 3; + ret -= s->output_bytes; + s->output_bytes += ret; + return ret; +} + +/** + * Initialize LZW encoder. Please set s->clear_code, s->end_code and s->maxbits before run. + * @param s LZW state + * @param outbuf Output buffer + * @param outsize Size of output buffer + * @param maxbits Maximum length of code + */ +void ff_lzw_encode_init(LZWEncodeState *s, uint8_t *outbuf, int outsize, + int maxbits, enum FF_LZW_MODES mode, + void (*lzw_put_bits)(PutBitContext *, int, unsigned)) +{ + s->clear_code = 256; + s->end_code = 257; + s->maxbits = maxbits; + init_put_bits(&s->pb, outbuf, outsize); + s->bufsize = outsize; + assert(s->maxbits >= 9 && s->maxbits <= LZW_MAXBITS); + s->maxcode = 1 << s->maxbits; + s->output_bytes = 0; + s->last_code = LZW_PREFIX_EMPTY; + s->bits = 9; + s->mode = mode; + s->put_bits = lzw_put_bits; +} + +/** + * LZW main compress function + * @param s LZW state + * @param inbuf Input buffer + * @param insize Size of input buffer + * @return Number of bytes written or -1 on error + */ +int ff_lzw_encode(LZWEncodeState * s, const uint8_t * inbuf, int insize) +{ + int i; + + if(insize * 3 > (s->bufsize - s->output_bytes) * 2){ + return -1; + } + + if (s->last_code == LZW_PREFIX_EMPTY) + clearTable(s); + + for (i = 0; i < insize; i++) { + uint8_t c = *inbuf++; + int code = findCode(s, c, s->last_code); + if (s->tab[code].hash_prefix == LZW_PREFIX_FREE) { + writeCode(s, s->last_code); + addCode(s, c, s->last_code, code); + code= hash(0, c); + } + s->last_code = s->tab[code].code; + if (s->tabsize >= s->maxcode - 1) { + clearTable(s); + } + } + + return writtenBytes(s); +} + +/** + * Write end code and flush bitstream + * @param s LZW state + * @return Number of bytes written or -1 on error + */ +int ff_lzw_encode_flush(LZWEncodeState *s, + void (*lzw_flush_put_bits)(PutBitContext *)) +{ + if (s->last_code != -1) + writeCode(s, s->last_code); + writeCode(s, s->end_code); + lzw_flush_put_bits(&s->pb); + s->last_code = -1; + + return writtenBytes(s); +} diff --git a/ffmpeg/libavcodec/mace.c b/ffmpeg/libavcodec/mace.c new file mode 100644 index 0000000..94bf2e7 --- /dev/null +++ b/ffmpeg/libavcodec/mace.c @@ -0,0 +1,304 @@ +/* + * MACE decoder + * Copyright (c) 2002 Laszlo Torok + * + * 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 + */ + +/** + * @file + * MACE decoder. + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/common.h" + +/* + * Adapted to libavcodec by Francois Revol + * (removed 68k REG stuff, changed types, added some statics and consts, + * libavcodec api, context stuff, interlaced stereo out). + */ + +static const int16_t MACEtab1[] = {-13, 8, 76, 222, 222, 76, 8, -13}; + +static const int16_t MACEtab3[] = {-18, 140, 140, -18}; + +static const int16_t MACEtab2[][4] = { + { 37, 116, 206, 330}, { 39, 121, 216, 346}, + { 41, 127, 225, 361}, { 42, 132, 235, 377}, + { 44, 137, 245, 392}, { 46, 144, 256, 410}, + { 48, 150, 267, 428}, { 51, 157, 280, 449}, + { 53, 165, 293, 470}, { 55, 172, 306, 490}, + { 58, 179, 319, 511}, { 60, 187, 333, 534}, + { 63, 195, 348, 557}, { 66, 205, 364, 583}, + { 69, 214, 380, 609}, { 72, 223, 396, 635}, + { 75, 233, 414, 663}, { 79, 244, 433, 694}, + { 82, 254, 453, 725}, { 86, 265, 472, 756}, + { 90, 278, 495, 792}, { 94, 290, 516, 826}, + { 98, 303, 538, 862}, { 102, 316, 562, 901}, + { 107, 331, 588, 942}, { 112, 345, 614, 983}, + { 117, 361, 641, 1027}, { 122, 377, 670, 1074}, + { 127, 394, 701, 1123}, { 133, 411, 732, 1172}, + { 139, 430, 764, 1224}, { 145, 449, 799, 1280}, + { 152, 469, 835, 1337}, { 159, 490, 872, 1397}, + { 166, 512, 911, 1459}, { 173, 535, 951, 1523}, + { 181, 558, 993, 1590}, { 189, 584, 1038, 1663}, + { 197, 610, 1085, 1738}, { 206, 637, 1133, 1815}, + { 215, 665, 1183, 1895}, { 225, 695, 1237, 1980}, + { 235, 726, 1291, 2068}, { 246, 759, 1349, 2161}, + { 257, 792, 1409, 2257}, { 268, 828, 1472, 2357}, + { 280, 865, 1538, 2463}, { 293, 903, 1606, 2572}, + { 306, 944, 1678, 2688}, { 319, 986, 1753, 2807}, + { 334, 1030, 1832, 2933}, { 349, 1076, 1914, 3065}, + { 364, 1124, 1999, 3202}, { 380, 1174, 2088, 3344}, + { 398, 1227, 2182, 3494}, { 415, 1281, 2278, 3649}, + { 434, 1339, 2380, 3811}, { 453, 1398, 2486, 3982}, + { 473, 1461, 2598, 4160}, { 495, 1526, 2714, 4346}, + { 517, 1594, 2835, 4540}, { 540, 1665, 2961, 4741}, + { 564, 1740, 3093, 4953}, { 589, 1818, 3232, 5175}, + { 615, 1898, 3375, 5405}, { 643, 1984, 3527, 5647}, + { 671, 2072, 3683, 5898}, { 701, 2164, 3848, 6161}, + { 733, 2261, 4020, 6438}, { 766, 2362, 4199, 6724}, + { 800, 2467, 4386, 7024}, { 836, 2578, 4583, 7339}, + { 873, 2692, 4786, 7664}, { 912, 2813, 5001, 8008}, + { 952, 2938, 5223, 8364}, { 995, 3070, 5457, 8739}, + { 1039, 3207, 5701, 9129}, { 1086, 3350, 5956, 9537}, + { 1134, 3499, 6220, 9960}, { 1185, 3655, 6497, 10404}, + { 1238, 3818, 6788, 10869}, { 1293, 3989, 7091, 11355}, + { 1351, 4166, 7407, 11861}, { 1411, 4352, 7738, 12390}, + { 1474, 4547, 8084, 12946}, { 1540, 4750, 8444, 13522}, + { 1609, 4962, 8821, 14126}, { 1680, 5183, 9215, 14756}, + { 1756, 5415, 9626, 15415}, { 1834, 5657, 10057, 16104}, + { 1916, 5909, 10505, 16822}, { 2001, 6173, 10975, 17574}, + { 2091, 6448, 11463, 18356}, { 2184, 6736, 11974, 19175}, + { 2282, 7037, 12510, 20032}, { 2383, 7351, 13068, 20926}, + { 2490, 7679, 13652, 21861}, { 2601, 8021, 14260, 22834}, + { 2717, 8380, 14897, 23854}, { 2838, 8753, 15561, 24918}, + { 2965, 9144, 16256, 26031}, { 3097, 9553, 16982, 27193}, + { 3236, 9979, 17740, 28407}, { 3380, 10424, 18532, 29675}, + { 3531, 10890, 19359, 31000}, { 3688, 11375, 20222, 32382}, + { 3853, 11883, 21125, 32767}, { 4025, 12414, 22069, 32767}, + { 4205, 12967, 23053, 32767}, { 4392, 13546, 24082, 32767}, + { 4589, 14151, 25157, 32767}, { 4793, 14783, 26280, 32767}, + { 5007, 15442, 27452, 32767}, { 5231, 16132, 28678, 32767}, + { 5464, 16851, 29957, 32767}, { 5708, 17603, 31294, 32767}, + { 5963, 18389, 32691, 32767}, { 6229, 19210, 32767, 32767}, + { 6507, 20067, 32767, 32767}, { 6797, 20963, 32767, 32767}, + { 7101, 21899, 32767, 32767}, { 7418, 22876, 32767, 32767}, + { 7749, 23897, 32767, 32767}, { 8095, 24964, 32767, 32767}, + { 8456, 26078, 32767, 32767}, { 8833, 27242, 32767, 32767}, + { 9228, 28457, 32767, 32767}, { 9639, 29727, 32767, 32767} +}; + +static const int16_t MACEtab4[][2] = { + { 64, 216}, { 67, 226}, { 70, 236}, { 74, 246}, + { 77, 257}, { 80, 268}, { 84, 280}, { 88, 294}, + { 92, 307}, { 96, 321}, { 100, 334}, { 104, 350}, + { 109, 365}, { 114, 382}, { 119, 399}, { 124, 416}, + { 130, 434}, { 136, 454}, { 142, 475}, { 148, 495}, + { 155, 519}, { 162, 541}, { 169, 564}, { 176, 590}, + { 185, 617}, { 193, 644}, { 201, 673}, { 210, 703}, + { 220, 735}, { 230, 767}, { 240, 801}, { 251, 838}, + { 262, 876}, { 274, 914}, { 286, 955}, { 299, 997}, + { 312, 1041}, { 326, 1089}, { 341, 1138}, { 356, 1188}, + { 372, 1241}, { 388, 1297}, { 406, 1354}, { 424, 1415}, + { 443, 1478}, { 462, 1544}, { 483, 1613}, { 505, 1684}, + { 527, 1760}, { 551, 1838}, { 576, 1921}, { 601, 2007}, + { 628, 2097}, { 656, 2190}, { 686, 2288}, { 716, 2389}, + { 748, 2496}, { 781, 2607}, { 816, 2724}, { 853, 2846}, + { 891, 2973}, { 930, 3104}, { 972, 3243}, { 1016, 3389}, + { 1061, 3539}, { 1108, 3698}, { 1158, 3862}, { 1209, 4035}, + { 1264, 4216}, { 1320, 4403}, { 1379, 4599}, { 1441, 4806}, + { 1505, 5019}, { 1572, 5244}, { 1642, 5477}, { 1715, 5722}, + { 1792, 5978}, { 1872, 6245}, { 1955, 6522}, { 2043, 6813}, + { 2134, 7118}, { 2229, 7436}, { 2329, 7767}, { 2432, 8114}, + { 2541, 8477}, { 2655, 8854}, { 2773, 9250}, { 2897, 9663}, + { 3026, 10094}, { 3162, 10546}, { 3303, 11016}, { 3450, 11508}, + { 3604, 12020}, { 3765, 12556}, { 3933, 13118}, { 4108, 13703}, + { 4292, 14315}, { 4483, 14953}, { 4683, 15621}, { 4892, 16318}, + { 5111, 17046}, { 5339, 17807}, { 5577, 18602}, { 5826, 19433}, + { 6086, 20300}, { 6358, 21205}, { 6642, 22152}, { 6938, 23141}, + { 7248, 24173}, { 7571, 25252}, { 7909, 26380}, { 8262, 27557}, + { 8631, 28786}, { 9016, 30072}, { 9419, 31413}, { 9839, 32767}, + { 10278, 32767}, { 10737, 32767}, { 11216, 32767}, { 11717, 32767}, + { 12240, 32767}, { 12786, 32767}, { 13356, 32767}, { 13953, 32767}, + { 14576, 32767}, { 15226, 32767}, { 15906, 32767}, { 16615, 32767} +}; + +static const struct { + const int16_t *tab1; const int16_t *tab2; int stride; +} tabs[] = { + {MACEtab1, &MACEtab2[0][0], 4}, + {MACEtab3, &MACEtab4[0][0], 2}, + {MACEtab1, &MACEtab2[0][0], 4} +}; + +#define QT_8S_2_16S(x) (((x) & 0xFF00) | (((x) >> 8) & 0xFF)) + +typedef struct ChannelData { + int16_t index, factor, prev2, previous, level; +} ChannelData; + +typedef struct MACEContext { + ChannelData chd[2]; +} MACEContext; + +/** + * MACE version of av_clip_int16(). We have to do this to keep binary + * identical output to the binary decoder. + */ +static inline int16_t mace_broken_clip_int16(int n) +{ + if (n > 32767) + return 32767; + else if (n < -32768) + return -32767; + else + return n; +} + +static int16_t read_table(ChannelData *chd, uint8_t val, int tab_idx) +{ + int16_t current; + + if (val < tabs[tab_idx].stride) + current = tabs[tab_idx].tab2[((chd->index & 0x7f0) >> 4) * tabs[tab_idx].stride + val]; + else + current = - 1 - tabs[tab_idx].tab2[((chd->index & 0x7f0) >> 4)*tabs[tab_idx].stride + 2*tabs[tab_idx].stride-val-1]; + + if (( chd->index += tabs[tab_idx].tab1[val]-(chd->index >> 5) ) < 0) + chd->index = 0; + + return current; +} + +static void chomp3(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx) +{ + + int16_t current = read_table(chd, val, tab_idx); + + current = mace_broken_clip_int16(current + chd->level); + + chd->level = current - (current >> 3); + *output = QT_8S_2_16S(current); +} + +static void chomp6(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx) +{ + int16_t current = read_table(chd, val, tab_idx); + + if ((chd->previous ^ current) >= 0) { + chd->factor = FFMIN(chd->factor + 506, 32767); + } else { + if (chd->factor - 314 < -32768) + chd->factor = -32767; + else + chd->factor -= 314; + } + + current = mace_broken_clip_int16(current + chd->level); + + chd->level = (current*chd->factor) >> 15; + current >>= 1; + + output[0] = QT_8S_2_16S(chd->previous + chd->prev2 - + ((chd->prev2-current) >> 2)); + output[1] = QT_8S_2_16S(chd->previous + current + + ((chd->prev2-current) >> 2)); + chd->prev2 = chd->previous; + chd->previous = current; +} + +static av_cold int mace_decode_init(AVCodecContext * avctx) +{ + if (avctx->channels > 2 || avctx->channels <= 0) + return -1; + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + + return 0; +} + +static int mace_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int16_t **samples; + MACEContext *ctx = avctx->priv_data; + int i, j, k, l, ret; + int is_mace3 = (avctx->codec_id == AV_CODEC_ID_MACE3); + + /* get output buffer */ + frame->nb_samples = 3 * (buf_size << (1 - is_mace3)) / avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t **)frame->extended_data; + + for(i = 0; i < avctx->channels; i++) { + int16_t *output = samples[i]; + + for (j=0; j < buf_size / (avctx->channels << is_mace3); j++) + for (k=0; k < (1 << is_mace3); k++) { + uint8_t pkt = buf[(i << is_mace3) + + (j*avctx->channels << is_mace3) + k]; + + uint8_t val[2][3] = {{pkt >> 5, (pkt >> 3) & 3, pkt & 7 }, + {pkt & 7 , (pkt >> 3) & 3, pkt >> 5}}; + + for (l=0; l < 3; l++) { + if (is_mace3) + chomp3(&ctx->chd[i], output, val[1][l], l); + else + chomp6(&ctx->chd[i], output, val[0][l], l); + + output += 1 << (1-is_mace3); + } + } + } + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_mace3_decoder = { + .name = "mace3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MACE3, + .priv_data_size = sizeof(MACEContext), + .init = mace_decode_init, + .decode = mace_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; + +AVCodec ff_mace6_decoder = { + .name = "mace6", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MACE6, + .priv_data_size = sizeof(MACEContext), + .init = mace_decode_init, + .decode = mace_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/mathops.h b/ffmpeg/libavcodec/mathops.h new file mode 100644 index 0000000..592f5a5 --- /dev/null +++ b/ffmpeg/libavcodec/mathops.h @@ -0,0 +1,218 @@ +/* + * simple math operations + * Copyright (c) 2001, 2002 Fabrice Bellard + * Copyright (c) 2006 Michael Niedermayer et al + * + * 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 + */ +#ifndef AVCODEC_MATHOPS_H +#define AVCODEC_MATHOPS_H + +#include + +#include "libavutil/common.h" +#include "config.h" + +extern const uint32_t ff_inverse[257]; +extern const uint8_t ff_reverse[256]; +extern const uint8_t ff_sqrt_tab[256]; + +#if ARCH_ARM +# include "arm/mathops.h" +#elif ARCH_AVR32 +# include "avr32/mathops.h" +#elif ARCH_BFIN +# include "bfin/mathops.h" +#elif ARCH_MIPS +# include "mips/mathops.h" +#elif ARCH_PPC +# include "ppc/mathops.h" +#elif ARCH_X86 +# include "x86/mathops.h" +#endif + +/* generic implementation */ + +#ifndef MUL64 +# define MUL64(a,b) ((int64_t)(a) * (int64_t)(b)) +#endif + +#ifndef MULL +# define MULL(a,b,s) (MUL64(a, b) >> (s)) +#endif + +#ifndef MULH +static av_always_inline int MULH(int a, int b){ + return MUL64(a, b) >> 32; +} +#endif + +#ifndef UMULH +static av_always_inline unsigned UMULH(unsigned a, unsigned b){ + return ((uint64_t)(a) * (uint64_t)(b))>>32; +} +#endif + +#ifndef MAC64 +# define MAC64(d, a, b) ((d) += MUL64(a, b)) +#endif + +#ifndef MLS64 +# define MLS64(d, a, b) ((d) -= MUL64(a, b)) +#endif + +/* signed 16x16 -> 32 multiply add accumulate */ +#ifndef MAC16 +# define MAC16(rt, ra, rb) rt += (ra) * (rb) +#endif + +/* signed 16x16 -> 32 multiply */ +#ifndef MUL16 +# define MUL16(ra, rb) ((ra) * (rb)) +#endif + +#ifndef MLS16 +# define MLS16(rt, ra, rb) ((rt) -= (ra) * (rb)) +#endif + +/* median of 3 */ +#ifndef mid_pred +#define mid_pred mid_pred +static inline av_const int mid_pred(int a, int b, int c) +{ +#if 0 + int t= (a-b)&((a-b)>>31); + a-=t; + b+=t; + b-= (b-c)&((b-c)>>31); + b+= (a-b)&((a-b)>>31); + + return b; +#else + if(a>b){ + if(c>b){ + if(c>a) b=a; + else b=c; + } + }else{ + if(b>c){ + if(c>a) b=c; + else b=a; + } + } + return b; +#endif +} +#endif + +#ifndef sign_extend +static inline av_const int sign_extend(int val, unsigned bits) +{ + unsigned shift = 8 * sizeof(int) - bits; + union { unsigned u; int s; } v = { (unsigned) val << shift }; + return v.s >> shift; +} +#endif + +#ifndef zero_extend +static inline av_const unsigned zero_extend(unsigned val, unsigned bits) +{ + return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits); +} +#endif + +#ifndef COPY3_IF_LT +#define COPY3_IF_LT(x, y, a, b, c, d)\ +if ((y) < (x)) {\ + (x) = (y);\ + (a) = (b);\ + (c) = (d);\ +} +#endif + +#ifndef MASK_ABS +#define MASK_ABS(mask, level) do { \ + mask = level >> 31; \ + level = (level ^ mask) - mask; \ + } while (0) +#endif + +#ifndef NEG_SSR32 +# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s))) +#endif + +#ifndef NEG_USR32 +# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s))) +#endif + +#if HAVE_BIGENDIAN +# ifndef PACK_2U8 +# define PACK_2U8(a,b) (((a) << 8) | (b)) +# endif +# ifndef PACK_4U8 +# define PACK_4U8(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) +# endif +# ifndef PACK_2U16 +# define PACK_2U16(a,b) (((a) << 16) | (b)) +# endif +#else +# ifndef PACK_2U8 +# define PACK_2U8(a,b) (((b) << 8) | (a)) +# endif +# ifndef PACK_4U2 +# define PACK_4U8(a,b,c,d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a)) +# endif +# ifndef PACK_2U16 +# define PACK_2U16(a,b) (((b) << 16) | (a)) +# endif +#endif + +#ifndef PACK_2S8 +# define PACK_2S8(a,b) PACK_2U8((a)&255, (b)&255) +#endif +#ifndef PACK_4S8 +# define PACK_4S8(a,b,c,d) PACK_4U8((a)&255, (b)&255, (c)&255, (d)&255) +#endif +#ifndef PACK_2S16 +# define PACK_2S16(a,b) PACK_2U16((a)&0xffff, (b)&0xffff) +#endif + +#ifndef FASTDIV +# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a) * ff_inverse[b]) >> 32)) +#endif /* FASTDIV */ + +static inline av_const unsigned int ff_sqrt(unsigned int a) +{ + unsigned int b; + + if (a < 255) return (ff_sqrt_tab[a + 1] - 1) >> 4; + else if (a < (1 << 12)) b = ff_sqrt_tab[a >> 4] >> 2; +#if !CONFIG_SMALL + else if (a < (1 << 14)) b = ff_sqrt_tab[a >> 6] >> 1; + else if (a < (1 << 16)) b = ff_sqrt_tab[a >> 8] ; +#endif + else { + int s = av_log2_16bit(a >> 16) >> 1; + unsigned int c = a >> (s + 2); + b = ff_sqrt_tab[c >> (s + 8)]; + b = FASTDIV(c,b) + (b << s); + } + + return b - (a < b * b); +} + +#endif /* AVCODEC_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/mathtables.c b/ffmpeg/libavcodec/mathtables.c new file mode 100644 index 0000000..126b05f --- /dev/null +++ b/ffmpeg/libavcodec/mathtables.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2002-2004 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 + +/* a*inverse[b]>>32 == a/b for all 0<=a<=16909558 && 2<=b<=256 + * for a>16909558, is an overestimate by less than 1 part in 1<<24 */ +const uint32_t ff_inverse[257]={ + 0, 4294967295U,2147483648U,1431655766, 1073741824, 858993460, 715827883, 613566757, + 536870912, 477218589, 429496730, 390451573, 357913942, 330382100, 306783379, 286331154, + 268435456, 252645136, 238609295, 226050911, 214748365, 204522253, 195225787, 186737709, + 178956971, 171798692, 165191050, 159072863, 153391690, 148102321, 143165577, 138547333, + 134217728, 130150525, 126322568, 122713352, 119304648, 116080198, 113025456, 110127367, + 107374183, 104755300, 102261127, 99882961, 97612894, 95443718, 93368855, 91382283, + 89478486, 87652394, 85899346, 84215046, 82595525, 81037119, 79536432, 78090315, + 76695845, 75350304, 74051161, 72796056, 71582789, 70409300, 69273667, 68174085, + 67108864, 66076420, 65075263, 64103990, 63161284, 62245903, 61356676, 60492498, + 59652324, 58835169, 58040099, 57266231, 56512728, 55778797, 55063684, 54366675, + 53687092, 53024288, 52377650, 51746594, 51130564, 50529028, 49941481, 49367441, + 48806447, 48258060, 47721859, 47197443, 46684428, 46182445, 45691142, 45210183, + 44739243, 44278014, 43826197, 43383509, 42949673, 42524429, 42107523, 41698712, + 41297763, 40904451, 40518560, 40139882, 39768216, 39403370, 39045158, 38693400, + 38347923, 38008561, 37675152, 37347542, 37025581, 36709123, 36398028, 36092163, + 35791395, 35495598, 35204650, 34918434, 34636834, 34359739, 34087043, 33818641, + 33554432, 33294321, 33038210, 32786010, 32537632, 32292988, 32051995, 31814573, + 31580642, 31350127, 31122952, 30899046, 30678338, 30460761, 30246249, 30034737, + 29826162, 29620465, 29417585, 29217465, 29020050, 28825284, 28633116, 28443493, + 28256364, 28071682, 27889399, 27709467, 27531842, 27356480, 27183338, 27012373, + 26843546, 26676816, 26512144, 26349493, 26188825, 26030105, 25873297, 25718368, + 25565282, 25414008, 25264514, 25116768, 24970741, 24826401, 24683721, 24542671, + 24403224, 24265352, 24129030, 23994231, 23860930, 23729102, 23598722, 23469767, + 23342214, 23216040, 23091223, 22967740, 22845571, 22724695, 22605092, 22486740, + 22369622, 22253717, 22139007, 22025474, 21913099, 21801865, 21691755, 21582751, + 21474837, 21367997, 21262215, 21157475, 21053762, 20951060, 20849356, 20748635, + 20648882, 20550083, 20452226, 20355296, 20259280, 20164166, 20069941, 19976593, + 19884108, 19792477, 19701685, 19611723, 19522579, 19434242, 19346700, 19259944, + 19173962, 19088744, 19004281, 18920561, 18837576, 18755316, 18673771, 18592933, + 18512791, 18433337, 18354562, 18276457, 18199014, 18122225, 18046082, 17970575, + 17895698, 17821442, 17747799, 17674763, 17602325, 17530479, 17459217, 17388532, + 17318417, 17248865, 17179870, 17111424, 17043522, 16976156, 16909321, 16843010, + 16777216 +}; + +const uint8_t ff_sqrt_tab[256]={ + 0, 16, 23, 28, 32, 36, 40, 43, 46, 48, 51, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 77, 79, 80, 82, 84, 85, 87, 88, 90, + 91, 92, 94, 95, 96, 98, 99,100,102,103,104,105,107,108,109,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,127, +128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,144,145,146,147,148,149,150,151,151,152,153,154,155,156,156, +157,158,159,160,160,161,162,163,164,164,165,166,167,168,168,169,170,171,171,172,173,174,174,175,176,176,177,178,179,179,180,181, +182,182,183,184,184,185,186,186,187,188,188,189,190,190,191,192,192,193,194,194,195,196,196,197,198,198,199,200,200,201,202,202, +203,204,204,205,205,206,207,207,208,208,209,210,210,211,212,212,213,213,214,215,215,216,216,217,218,218,219,219,220,220,221,222, +222,223,223,224,224,225,226,226,227,227,228,228,229,230,230,231,231,232,232,233,233,234,235,235,236,236,237,237,238,238,239,239, +240,240,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,255,255 +}; + +const uint8_t ff_reverse[256] = { +0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0, +0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8, +0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4, +0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC, +0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2, +0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA, +0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6, +0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE, +0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1, +0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9, +0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5, +0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD, +0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3, +0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB, +0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7, +0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF, +}; + +#define times4(x) x, x, x, x + +const uint8_t ff_cropTbl[256 + 2 * 1024] = { +times4(times4(times4(times4(times4(0x00))))), +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, +0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, +0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, +0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, +0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, +0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, +0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, +0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, +0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, +0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, +0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, +0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, +0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, +times4(times4(times4(times4(times4(0xFF)))))}; + +const uint8_t ff_zigzag_direct[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; diff --git a/ffmpeg/libavcodec/mdct.c b/ffmpeg/libavcodec/mdct.c new file mode 100644 index 0000000..2232024 --- /dev/null +++ b/ffmpeg/libavcodec/mdct.c @@ -0,0 +1,203 @@ +/* + * MDCT/IMDCT transforms + * Copyright (c) 2002 Fabrice Bellard + * + * 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 +#include "libavutil/common.h" +#include "libavutil/mathematics.h" +#include "fft.h" +#include "fft-internal.h" + +/** + * @file + * MDCT/IMDCT transforms. + */ + +#if CONFIG_FFT_FLOAT +# define RSCALE(x) (x) +#else +# define RSCALE(x) ((x) >> 1) +#endif + +/** + * init MDCT or IMDCT computation. + */ +av_cold int ff_mdct_init(FFTContext *s, int nbits, int inverse, double scale) +{ + int n, n4, i; + double alpha, theta; + int tstep; + + memset(s, 0, sizeof(*s)); + n = 1 << nbits; + s->mdct_bits = nbits; + s->mdct_size = n; + n4 = n >> 2; + s->mdct_permutation = FF_MDCT_PERM_NONE; + + if (ff_fft_init(s, s->mdct_bits - 2, inverse) < 0) + goto fail; + + s->tcos = av_malloc(n/2 * sizeof(FFTSample)); + if (!s->tcos) + goto fail; + + switch (s->mdct_permutation) { + case FF_MDCT_PERM_NONE: + s->tsin = s->tcos + n4; + tstep = 1; + break; + case FF_MDCT_PERM_INTERLEAVE: + s->tsin = s->tcos + 1; + tstep = 2; + break; + default: + goto fail; + } + + theta = 1.0 / 8.0 + (scale < 0 ? n4 : 0); + scale = sqrt(fabs(scale)); + for(i=0;itcos[i*tstep] = FIX15(-cos(alpha) * scale); + s->tsin[i*tstep] = FIX15(-sin(alpha) * scale); + } + return 0; + fail: + ff_mdct_end(s); + return -1; +} + +/** + * Compute the middle half of the inverse MDCT of size N = 2^nbits, + * thus excluding the parts that can be derived by symmetry + * @param output N/2 samples + * @param input N/2 samples + */ +void ff_imdct_half_c(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int k, n8, n4, n2, n, j; + const uint16_t *revtab = s->revtab; + const FFTSample *tcos = s->tcos; + const FFTSample *tsin = s->tsin; + const FFTSample *in1, *in2; + FFTComplex *z = (FFTComplex *)output; + + n = 1 << s->mdct_bits; + n2 = n >> 1; + n4 = n >> 2; + n8 = n >> 3; + + /* pre rotation */ + in1 = input; + in2 = input + n2 - 1; + for(k = 0; k < n4; k++) { + j=revtab[k]; + CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]); + in1 += 2; + in2 -= 2; + } + s->fft_calc(s, z); + + /* post rotation + reordering */ + for(k = 0; k < n8; k++) { + FFTSample r0, i0, r1, i1; + CMUL(r0, i1, z[n8-k-1].im, z[n8-k-1].re, tsin[n8-k-1], tcos[n8-k-1]); + CMUL(r1, i0, z[n8+k ].im, z[n8+k ].re, tsin[n8+k ], tcos[n8+k ]); + z[n8-k-1].re = r0; + z[n8-k-1].im = i0; + z[n8+k ].re = r1; + z[n8+k ].im = i1; + } +} + +/** + * Compute inverse MDCT of size N = 2^nbits + * @param output N samples + * @param input N/2 samples + */ +void ff_imdct_calc_c(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int k; + int n = 1 << s->mdct_bits; + int n2 = n >> 1; + int n4 = n >> 2; + + ff_imdct_half_c(s, output+n4, input); + + for(k = 0; k < n4; k++) { + output[k] = -output[n2-k-1]; + output[n-k-1] = output[n2+k]; + } +} + +/** + * Compute MDCT of size N = 2^nbits + * @param input N samples + * @param out N/2 samples + */ +void ff_mdct_calc_c(FFTContext *s, FFTSample *out, const FFTSample *input) +{ + int i, j, n, n8, n4, n2, n3; + FFTDouble re, im; + const uint16_t *revtab = s->revtab; + const FFTSample *tcos = s->tcos; + const FFTSample *tsin = s->tsin; + FFTComplex *x = (FFTComplex *)out; + + n = 1 << s->mdct_bits; + n2 = n >> 1; + n4 = n >> 2; + n8 = n >> 3; + n3 = 3 * n4; + + /* pre rotation */ + for(i=0;ifft_calc(s, x); + + /* post rotation */ + for(i=0;itcos); + ff_fft_end(s); +} diff --git a/ffmpeg/libavcodec/mdct_fixed.c b/ffmpeg/libavcodec/mdct_fixed.c new file mode 100644 index 0000000..794a3e0 --- /dev/null +++ b/ffmpeg/libavcodec/mdct_fixed.c @@ -0,0 +1,64 @@ +/* + * 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 + */ + +#define CONFIG_FFT_FLOAT 0 +#include "mdct.c" + +/* same as ff_mdct_calcw_c with double-width unscaled output */ +void ff_mdct_calcw_c(FFTContext *s, FFTDouble *out, const FFTSample *input) +{ + int i, j, n, n8, n4, n2, n3; + FFTDouble re, im; + const uint16_t *revtab = s->revtab; + const FFTSample *tcos = s->tcos; + const FFTSample *tsin = s->tsin; + FFTComplex *x = s->tmp_buf; + FFTDComplex *o = (FFTDComplex *)out; + + n = 1 << s->mdct_bits; + n2 = n >> 1; + n4 = n >> 2; + n8 = n >> 3; + n3 = 3 * n4; + + /* pre rotation */ + for(i=0;ifft_calc(s, x); + + /* post rotation */ + for(i=0;i + * + * 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 + */ + +/** + * @file + * Sony PlayStation MDEC (Motion DECoder) + * This is very similar to intra-only MPEG-1. + */ + +#include "avcodec.h" +#include "mpegvideo.h" +#include "mpeg12.h" +#include "thread.h" + +typedef struct MDECContext { + AVCodecContext *avctx; + DSPContext dsp; + ThreadFrame frame; + GetBitContext gb; + ScanTable scantable; + int version; + int qscale; + int last_dc[3]; + int mb_width; + int mb_height; + int mb_x, mb_y; + DECLARE_ALIGNED(16, int16_t, block)[6][64]; + uint8_t *bitstream_buffer; + unsigned int bitstream_buffer_size; + int block_last_index[6]; +} MDECContext; + +//very similar to MPEG-1 +static inline int mdec_decode_block_intra(MDECContext *a, int16_t *block, int n) +{ + int level, diff, i, j, run; + int component; + RLTable *rl = &ff_rl_mpeg1; + uint8_t * const scantable = a->scantable.permutated; + const uint16_t *quant_matrix = ff_mpeg1_default_intra_matrix; + const int qscale = a->qscale; + + /* DC coefficient */ + if (a->version == 2) { + block[0] = 2 * get_sbits(&a->gb, 10) + 1024; + } else { + component = (n <= 3 ? 0 : n - 4 + 1); + diff = decode_dc(&a->gb, component); + if (diff >= 0xffff) + return AVERROR_INVALIDDATA; + a->last_dc[component] += diff; + block[0] = a->last_dc[component] << 3; + } + + i = 0; + { + OPEN_READER(re, &a->gb); + /* now quantify & encode AC coefficients */ + for (;;) { + UPDATE_CACHE(re, &a->gb); + GET_RL_VLC(level, run, re, &a->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level == 127) { + break; + } else if (level != 0) { + i += run; + j = scantable[i]; + level = (level * qscale * quant_matrix[j]) >> 3; + level = (level ^ SHOW_SBITS(re, &a->gb, 1)) - SHOW_SBITS(re, &a->gb, 1); + LAST_SKIP_BITS(re, &a->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &a->gb, 6)+1; LAST_SKIP_BITS(re, &a->gb, 6); + UPDATE_CACHE(re, &a->gb); + level = SHOW_SBITS(re, &a->gb, 10); SKIP_BITS(re, &a->gb, 10); + i += run; + j = scantable[i]; + if (level < 0) { + level = -level; + level = (level * qscale * quant_matrix[j]) >> 3; + level = (level - 1) | 1; + level = -level; + } else { + level = (level * qscale * quant_matrix[j]) >> 3; + level = (level - 1) | 1; + } + } + if (i > 63) { + av_log(a->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", a->mb_x, a->mb_y); + return AVERROR_INVALIDDATA; + } + + block[j] = level; + } + CLOSE_READER(re, &a->gb); + } + a->block_last_index[n] = i; + return 0; +} + +static inline int decode_mb(MDECContext *a, int16_t block[6][64]) +{ + int i, ret; + const int block_index[6] = { 5, 4, 0, 1, 2, 3 }; + + a->dsp.clear_blocks(block[0]); + + for (i = 0; i < 6; i++) { + if ((ret = mdec_decode_block_intra(a, block[block_index[i]], + block_index[i])) < 0) + return ret; + if (get_bits_left(&a->gb) < 0) + return AVERROR_INVALIDDATA; + } + return 0; +} + +static inline void idct_put(MDECContext *a, AVFrame *frame, int mb_x, int mb_y) +{ + int16_t (*block)[64] = a->block; + int linesize = frame->linesize[0]; + + uint8_t *dest_y = frame->data[0] + (mb_y * 16* linesize ) + mb_x * 16; + uint8_t *dest_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8; + uint8_t *dest_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8; + + a->dsp.idct_put(dest_y, linesize, block[0]); + a->dsp.idct_put(dest_y + 8, linesize, block[1]); + a->dsp.idct_put(dest_y + 8 * linesize, linesize, block[2]); + a->dsp.idct_put(dest_y + 8 * linesize + 8, linesize, block[3]); + + if (!(a->avctx->flags & CODEC_FLAG_GRAY)) { + a->dsp.idct_put(dest_cb, frame->linesize[1], block[4]); + a->dsp.idct_put(dest_cr, frame->linesize[2], block[5]); + } +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + MDECContext * const a = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ThreadFrame frame = { .f = data }; + int i, ret; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + frame.f->pict_type = AV_PICTURE_TYPE_I; + frame.f->key_frame = 1; + + av_fast_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!a->bitstream_buffer) + return AVERROR(ENOMEM); + for (i = 0; i < buf_size; i += 2) { + a->bitstream_buffer[i] = buf[i + 1]; + a->bitstream_buffer[i + 1] = buf[i]; + } + init_get_bits(&a->gb, a->bitstream_buffer, buf_size * 8); + + /* skip over 4 preamble bytes in stream (typically 0xXX 0xXX 0x00 0x38) */ + skip_bits(&a->gb, 32); + + a->qscale = get_bits(&a->gb, 16); + a->version = get_bits(&a->gb, 16); + + a->last_dc[0] = a->last_dc[1] = a->last_dc[2] = 128; + + for (a->mb_x = 0; a->mb_x < a->mb_width; a->mb_x++) { + for (a->mb_y = 0; a->mb_y < a->mb_height; a->mb_y++) { + if ((ret = decode_mb(a, a->block)) < 0) + return ret; + + idct_put(a, frame.f, a->mb_x, a->mb_y); + } + } + + *got_frame = 1; + + return (get_bits_count(&a->gb) + 31) / 32 * 4; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + MDECContext * const a = avctx->priv_data; + + a->mb_width = (avctx->coded_width + 15) / 16; + a->mb_height = (avctx->coded_height + 15) / 16; + + a->avctx = avctx; + + ff_dsputil_init(&a->dsp, avctx); + ff_mpeg12_init_vlcs(); + ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_zigzag_direct); + + if (avctx->idct_algo == FF_IDCT_AUTO) + avctx->idct_algo = FF_IDCT_SIMPLE; + avctx->pix_fmt = AV_PIX_FMT_YUVJ420P; + + return 0; +} + +static av_cold int decode_init_thread_copy(AVCodecContext *avctx) +{ + MDECContext * const a = avctx->priv_data; + + a->avctx = avctx; + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + MDECContext * const a = avctx->priv_data; + + av_freep(&a->bitstream_buffer); + a->bitstream_buffer_size = 0; + + return 0; +} + +AVCodec ff_mdec_decoder = { + .name = "mdec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MDEC, + .priv_data_size = sizeof(MDECContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Sony PlayStation MDEC (Motion DECoder)"), + .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy) +}; diff --git a/ffmpeg/libavcodec/microdvddec.c b/ffmpeg/libavcodec/microdvddec.c new file mode 100644 index 0000000..f3c640f --- /dev/null +++ b/ffmpeg/libavcodec/microdvddec.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2012 Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * MicroDVD subtitle decoder + * + * Based on the specifications found here: + * https://trac.videolan.org/vlc/ticket/1825#comment:6 + */ + +#include "libavutil/avstring.h" +#include "libavutil/parseutils.h" +#include "libavutil/bprint.h" +#include "avcodec.h" +#include "ass.h" + +static int indexof(const char *s, int c) +{ + char *f = strchr(s, c); + return f ? (f - s) : -1; +} + +struct microdvd_tag { + char key; + int persistent; + uint32_t data1; + uint32_t data2; + char *data_string; + int data_string_len; +}; + +#define MICRODVD_PERSISTENT_OFF 0 +#define MICRODVD_PERSISTENT_ON 1 +#define MICRODVD_PERSISTENT_OPENED 2 + +// Color, Font, Size, cHarset, stYle, Position, cOordinate +#define MICRODVD_TAGS "cfshyYpo" + +static void microdvd_set_tag(struct microdvd_tag *tags, struct microdvd_tag tag) +{ + int tag_index = indexof(MICRODVD_TAGS, tag.key); + + if (tag_index < 0) + return; + memcpy(&tags[tag_index], &tag, sizeof(tag)); +} + +// italic, bold, underline, strike-through +#define MICRODVD_STYLES "ibus" + +static char *microdvd_load_tags(struct microdvd_tag *tags, char *s) +{ + while (*s == '{') { + char *start = s; + char tag_char = *(s + 1); + struct microdvd_tag tag = {0}; + + if (!tag_char || *(s + 2) != ':') + break; + s += 3; + + switch (tag_char) { + + /* Style */ + case 'Y': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 'y': + while (*s && *s != '}') { + int style_index = indexof(MICRODVD_STYLES, *s); + + if (style_index >= 0) + tag.data1 |= (1 << style_index); + s++; + } + if (*s != '}') + break; + /* We must distinguish persistent and non-persistent styles + * to handle this kind of style tags: {y:ib}{Y:us} */ + tag.key = tag_char; + break; + + /* Color */ + case 'C': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 'c': + if (*s == '$') + s++; + tag.data1 = strtol(s, &s, 16) & 0x00ffffff; + if (*s != '}') + break; + tag.key = 'c'; + break; + + /* Font name */ + case 'F': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 'f': { + int len = indexof(s, '}'); + if (len < 0) + break; + tag.data_string = s; + tag.data_string_len = len; + s += len; + tag.key = 'f'; + break; + } + + /* Font size */ + case 'S': + tag.persistent = MICRODVD_PERSISTENT_ON; + case 's': + tag.data1 = strtol(s, &s, 10); + if (*s != '}') + break; + tag.key = 's'; + break; + + /* Charset */ + case 'H': { + //TODO: not yet handled, just parsed. + int len = indexof(s, '}'); + if (len < 0) + break; + tag.data_string = s; + tag.data_string_len = len; + s += len; + tag.key = 'h'; + break; + } + + /* Position */ + case 'P': + tag.persistent = MICRODVD_PERSISTENT_ON; + tag.data1 = (*s++ == '1'); + if (*s != '}') + break; + tag.key = 'p'; + break; + + /* Coordinates */ + case 'o': + tag.persistent = MICRODVD_PERSISTENT_ON; + tag.data1 = strtol(s, &s, 10); + if (*s != ',') + break; + s++; + tag.data2 = strtol(s, &s, 10); + if (*s != '}') + break; + tag.key = 'o'; + break; + + default: /* Unknown tag, we consider it's text */ + break; + } + + if (tag.key == 0) + return start; + + microdvd_set_tag(tags, tag); + s++; + } + return s; +} + +static void microdvd_open_tags(AVBPrint *new_line, struct microdvd_tag *tags) +{ + int i, sidx; + for (i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) { + if (tags[i].persistent == MICRODVD_PERSISTENT_OPENED) + continue; + switch (tags[i].key) { + case 'Y': + case 'y': + for (sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++) + if (tags[i].data1 & (1 << sidx)) + av_bprintf(new_line, "{\\%c1}", MICRODVD_STYLES[sidx]); + break; + + case 'c': + av_bprintf(new_line, "{\\c&H%06X&}", tags[i].data1); + break; + + case 'f': + av_bprintf(new_line, "{\\fn%.*s}", + tags[i].data_string_len, tags[i].data_string); + break; + + case 's': + av_bprintf(new_line, "{\\fs%d}", tags[i].data1); + break; + + case 'p': + if (tags[i].data1 == 0) + av_bprintf(new_line, "{\\an8}"); + break; + + case 'o': + av_bprintf(new_line, "{\\pos(%d,%d)}", + tags[i].data1, tags[i].data2); + break; + } + if (tags[i].persistent == MICRODVD_PERSISTENT_ON) + tags[i].persistent = MICRODVD_PERSISTENT_OPENED; + } +} + +static void microdvd_close_no_persistent_tags(AVBPrint *new_line, + struct microdvd_tag *tags) +{ + int i, sidx; + + for (i = sizeof(MICRODVD_TAGS) - 2; i >= 0; i--) { + if (tags[i].persistent != MICRODVD_PERSISTENT_OFF) + continue; + switch (tags[i].key) { + + case 'y': + for (sidx = sizeof(MICRODVD_STYLES) - 2; sidx >= 0; sidx--) + if (tags[i].data1 & (1 << sidx)) + av_bprintf(new_line, "{\\%c0}", MICRODVD_STYLES[sidx]); + break; + + case 'c': + av_bprintf(new_line, "{\\c}"); + break; + + case 'f': + av_bprintf(new_line, "{\\fn}"); + break; + + case 's': + av_bprintf(new_line, "{\\fs}"); + break; + } + tags[i].key = 0; + } +} + +static int microdvd_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + AVBPrint new_line; + char c; + char *decoded_sub; + char *line = avpkt->data; + char *end = avpkt->data + avpkt->size; + struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}}; + + if (avpkt->size <= 0) + return avpkt->size; + + /* To be removed later */ + if (sscanf(line, "{%*d}{%*[0123456789]}%c", &c) == 1 && + line[avpkt->size - 1] == '\n') { + av_log(avctx, AV_LOG_ERROR, "AVPacket is not clean (contains timing " + "information and a trailing line break). You need to upgrade " + "your libavformat or sanitize your packet.\n"); + return AVERROR_INVALIDDATA; + } + + av_bprint_init(&new_line, 0, 2048); + + // subtitle content + while (line < end && *line) { + + // parse MicroDVD tags, and open them in ASS + line = microdvd_load_tags(tags, line); + microdvd_open_tags(&new_line, tags); + + // simple copy until EOL or forced carriage return + while (line < end && *line && *line != '|') { + av_bprint_chars(&new_line, *line, 1); + line++; + } + + // line split + if (line < end && *line == '|') { + microdvd_close_no_persistent_tags(&new_line, tags); + av_bprintf(&new_line, "\\N"); + line++; + } + } + if (new_line.len) { + av_bprintf(&new_line, "\r\n"); + + av_bprint_finalize(&new_line, &decoded_sub); + if (*decoded_sub) { + int64_t start = avpkt->pts; + int64_t duration = avpkt->duration; + int ts_start = av_rescale_q(start, avctx->time_base, (AVRational){1,100}); + int ts_duration = duration != -1 ? + av_rescale_q(duration, avctx->time_base, (AVRational){1,100}) : -1; + ff_ass_add_rect(sub, decoded_sub, ts_start, ts_duration, 0); + } + av_free(decoded_sub); + } + + *got_sub_ptr = sub->num_rects > 0; + return avpkt->size; +} + +static int microdvd_init(AVCodecContext *avctx) +{ + int i, sidx; + AVBPrint font_buf; + int font_size = ASS_DEFAULT_FONT_SIZE; + int color = ASS_DEFAULT_COLOR; + int bold = ASS_DEFAULT_BOLD; + int italic = ASS_DEFAULT_ITALIC; + int underline = ASS_DEFAULT_UNDERLINE; + int alignment = ASS_DEFAULT_ALIGNMENT; + struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}}; + + av_bprint_init(&font_buf, 0, AV_BPRINT_SIZE_AUTOMATIC); + av_bprintf(&font_buf, "%s", ASS_DEFAULT_FONT); + + if (avctx->extradata) { + microdvd_load_tags(tags, avctx->extradata); + for (i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) { + switch (av_tolower(tags[i].key)) { + case 'y': + for (sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++) { + if (tags[i].data1 & (1 << sidx)) { + switch (MICRODVD_STYLES[sidx]) { + case 'i': italic = 1; break; + case 'b': bold = 1; break; + case 'u': underline = 1; break; + } + } + } + break; + + case 'c': color = tags[i].data1; break; + case 's': font_size = tags[i].data1; break; + case 'p': alignment = 8; break; + + case 'f': + av_bprint_clear(&font_buf); + av_bprintf(&font_buf, "%.*s", + tags[i].data_string_len, tags[i].data_string); + break; + } + } + } + return ff_ass_subtitle_header(avctx, font_buf.str, font_size, color, + ASS_DEFAULT_BACK_COLOR, bold, italic, + underline, alignment); +} + +AVCodec ff_microdvd_decoder = { + .name = "microdvd", + .long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_MICRODVD, + .init = microdvd_init, + .decode = microdvd_decode_frame, +}; diff --git a/ffmpeg/libavcodec/mimic.c b/ffmpeg/libavcodec/mimic.c new file mode 100644 index 0000000..85c6a1a --- /dev/null +++ b/ffmpeg/libavcodec/mimic.c @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2005 Ole André Vadla RavnÃ¥s + * Copyright (C) 2008 Ramiro Polla + * + * 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 +#include + +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "bytestream.h" +#include "dsputil.h" +#include "hpeldsp.h" +#include "thread.h" + +#define MIMIC_HEADER_SIZE 20 + +typedef struct { + AVCodecContext *avctx; + + int num_vblocks[3]; + int num_hblocks[3]; + + void *swap_buf; + int swap_buf_size; + + int cur_index; + int prev_index; + + ThreadFrame frames [16]; + AVPicture flipped_ptrs[16]; + + DECLARE_ALIGNED(16, int16_t, dct_block)[64]; + + GetBitContext gb; + ScanTable scantable; + DSPContext dsp; + HpelDSPContext hdsp; + VLC vlc; + + /* Kept in the context so multithreading can have a constant to read from */ + int next_cur_index; + int next_prev_index; +} MimicContext; + +static const uint32_t huffcodes[] = { + 0x0000000a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000b, + 0x0000001b, 0x00000038, 0x00000078, 0x00000079, 0x0000007a, 0x000000f9, + 0x000000fa, 0x000003fb, 0x000007f8, 0x000007f9, 0x000007fa, 0x000007fb, + 0x00000ff8, 0x00000ff9, 0x00000001, 0x00000039, 0x0000007b, 0x000000fb, + 0x000001f8, 0x000001f9, 0x00000ffa, 0x00000ffb, 0x00001ff8, 0x00001ff9, + 0x00001ffa, 0x00001ffb, 0x00003ff8, 0x00003ff9, 0x00003ffa, 0x00000000, + 0x00000004, 0x0000003a, 0x000001fa, 0x00003ffb, 0x00007ff8, 0x00007ff9, + 0x00007ffa, 0x00007ffb, 0x0000fff8, 0x0000fff9, 0x0000fffa, 0x0000fffb, + 0x0001fff8, 0x0001fff9, 0x0001fffa, 0x00000000, 0x0000000c, 0x000000f8, + 0x000001fb, 0x0001fffb, 0x0003fff8, 0x0003fff9, 0x0003fffa, 0x0003fffb, + 0x0007fff8, 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, + 0x000ffffa, 0x00000000, 0x0000001a, 0x000003f8, 0x000ffffb, 0x001ffff8, + 0x001ffff9, 0x001ffffa, 0x001ffffb, 0x003ffff8, 0x003ffff9, 0x003ffffa, + 0x003ffffb, 0x007ffff8, 0x007ffff9, 0x007ffffa, 0x007ffffb, 0x00000000, + 0x0000003b, 0x000003f9, 0x00fffff8, 0x00fffff9, 0x00fffffa, 0x00fffffb, + 0x01fffff8, 0x01fffff9, 0x01fffffa, 0x01fffffb, 0x03fffff8, 0x03fffff9, + 0x03fffffa, 0x03fffffb, 0x07fffff8, 0x00000000, 0x000003fa, 0x07fffff9, + 0x07fffffa, 0x07fffffb, 0x0ffffff8, 0x0ffffff9, 0x0ffffffa, 0x0ffffffb, + 0x1ffffff8, 0x1ffffff9, 0x1ffffffa, 0x1ffffffb, 0x3ffffff8, 0x3ffffff9, + 0x3ffffffa, +}; + +static const uint8_t huffbits[] = { + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 4, 5, 6, 7, 7, 7, 8, + 8, 10, 11, 11, 11, 11, 12, 12, 2, 6, 7, 8, + 9, 9, 12, 12, 13, 13, 13, 13, 14, 14, 14, 0, + 3, 6, 9, 14, 15, 15, 15, 15, 16, 16, 16, 16, + 17, 17, 17, 0, 4, 8, 9, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 0, 5, 10, 20, 21, + 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 0, + 6, 10, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, + 26, 26, 27, 0, 10, 27, 27, 27, 28, 28, 28, 28, + 29, 29, 29, 29, 30, 30, 30, +}; + +static const uint8_t col_zag[64] = { + 0, 8, 1, 2, 9, 16, 24, 17, + 10, 3, 4, 11, 18, 25, 32, 40, + 33, 26, 19, 12, 5, 6, 13, 20, + 27, 34, 41, 48, 56, 49, 42, 35, + 28, 21, 14, 7, 15, 22, 29, 36, + 43, 50, 57, 58, 51, 44, 37, 30, + 23, 31, 38, 45, 52, 59, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, +}; + +static av_cold int mimic_decode_end(AVCodecContext *avctx) +{ + MimicContext *ctx = avctx->priv_data; + int i; + + av_free(ctx->swap_buf); + + for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { + if (ctx->frames[i].f) + ff_thread_release_buffer(avctx, &ctx->frames[i]); + av_frame_free(&ctx->frames[i].f); + } + + if (!avctx->internal->is_copy) + ff_free_vlc(&ctx->vlc); + + return 0; +} + +static av_cold int mimic_decode_init(AVCodecContext *avctx) +{ + MimicContext *ctx = avctx->priv_data; + int ret, i; + + avctx->internal->allocate_progress = 1; + + ctx->prev_index = 0; + ctx->cur_index = 15; + + if ((ret = init_vlc(&ctx->vlc, 11, FF_ARRAY_ELEMS(huffbits), + huffbits, 1, 1, huffcodes, 4, 4, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error initializing vlc table\n"); + return ret; + } + ff_dsputil_init(&ctx->dsp, avctx); + ff_hpeldsp_init(&ctx->hdsp, avctx->flags); + ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, col_zag); + + for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { + ctx->frames[i].f = av_frame_alloc(); + if (!ctx->frames[i].f) { + mimic_decode_end(avctx); + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static int mimic_decode_update_thread_context(AVCodecContext *avctx, const AVCodecContext *avctx_from) +{ + MimicContext *dst = avctx->priv_data, *src = avctx_from->priv_data; + int i, ret; + + if (avctx == avctx_from) + return 0; + + dst->cur_index = src->next_cur_index; + dst->prev_index = src->next_prev_index; + + memcpy(dst->flipped_ptrs, src->flipped_ptrs, sizeof(src->flipped_ptrs)); + + for (i = 0; i < FF_ARRAY_ELEMS(dst->frames); i++) { + ff_thread_release_buffer(avctx, &dst->frames[i]); + if (src->frames[i].f->data[0]) { + ret = ff_thread_ref_frame(&dst->frames[i], &src->frames[i]); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static const int8_t vlcdec_lookup[9][64] = { + { 0, }, + { -1, 1, }, + { -3, 3, -2, 2, }, + { -7, 7, -6, 6, -5, 5, -4, 4, }, + { -15, 15, -14, 14, -13, 13, -12, 12, + -11, 11, -10, 10, -9, 9, -8, 8, }, + { -31, 31, -30, 30, -29, 29, -28, 28, + -27, 27, -26, 26, -25, 25, -24, 24, + -23, 23, -22, 22, -21, 21, -20, 20, + -19, 19, -18, 18, -17, 17, -16, 16, }, + { -63, 63, -62, 62, -61, 61, -60, 60, + -59, 59, -58, 58, -57, 57, -56, 56, + -55, 55, -54, 54, -53, 53, -52, 52, + -51, 51, -50, 50, -49, 49, -48, 48, + -47, 47, -46, 46, -45, 45, -44, 44, + -43, 43, -42, 42, -41, 41, -40, 40, + -39, 39, -38, 38, -37, 37, -36, 36, + -35, 35, -34, 34, -33, 33, -32, 32, }, + { -127, 127, -126, 126, -125, 125, -124, 124, + -123, 123, -122, 122, -121, 121, -120, 120, + -119, 119, -118, 118, -117, 117, -116, 116, + -115, 115, -114, 114, -113, 113, -112, 112, + -111, 111, -110, 110, -109, 109, -108, 108, + -107, 107, -106, 106, -105, 105, -104, 104, + -103, 103, -102, 102, -101, 101, -100, 100, + -99, 99, -98, 98, -97, 97, -96, 96, }, + { -95, 95, -94, 94, -93, 93, -92, 92, + -91, 91, -90, 90, -89, 89, -88, 88, + -87, 87, -86, 86, -85, 85, -84, 84, + -83, 83, -82, 82, -81, 81, -80, 80, + -79, 79, -78, 78, -77, 77, -76, 76, + -75, 75, -74, 74, -73, 73, -72, 72, + -71, 71, -70, 70, -69, 69, -68, 68, + -67, 67, -66, 66, -65, 65, -64, 64, }, +}; + +static int vlc_decode_block(MimicContext *ctx, int num_coeffs, int qscale) +{ + int16_t *block = ctx->dct_block; + unsigned int pos; + + ctx->dsp.clear_block(block); + + block[0] = get_bits(&ctx->gb, 8) << 3; + + for (pos = 1; pos < num_coeffs; pos++) { + uint32_t vlc, num_bits; + int value; + int coeff; + + vlc = get_vlc2(&ctx->gb, ctx->vlc.table, ctx->vlc.bits, 3); + if (!vlc) /* end-of-block code */ + return 0; + if (vlc == -1) + return AVERROR_INVALIDDATA; + + /* pos_add and num_bits are coded in the vlc code */ + pos += vlc & 15; // pos_add + num_bits = vlc >> 4; // num_bits + + if (pos >= 64) + return AVERROR_INVALIDDATA; + + value = get_bits(&ctx->gb, num_bits); + + /* FFmpeg's IDCT behaves somewhat different from the original code, so + * a factor of 4 was added to the input */ + + coeff = vlcdec_lookup[num_bits][value]; + if (pos < 3) + coeff <<= 4; + else /* TODO Use >> 10 instead of / 1001 */ + coeff = (coeff * qscale) / 1001; + + block[ctx->scantable.permutated[pos]] = coeff; + } + + return 0; +} + +static int decode(MimicContext *ctx, int quality, int num_coeffs, + int is_iframe) +{ + int ret, y, x, plane, cur_row = 0; + + for (plane = 0; plane < 3; plane++) { + const int is_chroma = !!plane; + const int qscale = av_clip(10000 - quality, is_chroma ? 1000 : 2000, + 10000) << 2; + const int stride = ctx->flipped_ptrs[ctx->cur_index ].linesize[plane]; + const uint8_t *src = ctx->flipped_ptrs[ctx->prev_index].data[plane]; + uint8_t *dst = ctx->flipped_ptrs[ctx->cur_index ].data[plane]; + + for (y = 0; y < ctx->num_vblocks[plane]; y++) { + for (x = 0; x < ctx->num_hblocks[plane]; x++) { + /* Check for a change condition in the current block. + * - iframes always change. + * - Luma plane changes on get_bits1 == 0 + * - Chroma planes change on get_bits1 == 1 */ + if (is_iframe || get_bits1(&ctx->gb) == is_chroma) { + /* Luma planes may use a backreference from the 15 last + * frames preceding the previous. (get_bits1 == 1) + * Chroma planes don't use backreferences. */ + if (is_chroma || is_iframe || !get_bits1(&ctx->gb)) { + if ((ret = vlc_decode_block(ctx, num_coeffs, + qscale)) < 0) { + av_log(ctx->avctx, AV_LOG_ERROR, "Error decoding " + "block.\n"); + return ret; + } + ctx->dsp.idct_put(dst, stride, ctx->dct_block); + } else { + unsigned int backref = get_bits(&ctx->gb, 4); + int index = (ctx->cur_index + backref) & 15; + uint8_t *p = ctx->flipped_ptrs[index].data[0]; + + if (index != ctx->cur_index && p) { + ff_thread_await_progress(&ctx->frames[index], + cur_row, 0); + p += src - + ctx->flipped_ptrs[ctx->prev_index].data[plane]; + ctx->hdsp.put_pixels_tab[1][0](dst, p, stride, 8); + } else { + av_log(ctx->avctx, AV_LOG_ERROR, + "No such backreference! Buggy sample.\n"); + } + } + } else { + ff_thread_await_progress(&ctx->frames[ctx->prev_index], + cur_row, 0); + ctx->hdsp.put_pixels_tab[1][0](dst, src, stride, 8); + } + src += 8; + dst += 8; + } + src += (stride - ctx->num_hblocks[plane]) << 3; + dst += (stride - ctx->num_hblocks[plane]) << 3; + + ff_thread_report_progress(&ctx->frames[ctx->cur_index], + cur_row++, 0); + } + } + + return 0; +} + +/** + * Flip the buffer upside-down and put it in the YVU order to match the + * way Mimic encodes frames. + */ +static void prepare_avpic(MimicContext *ctx, AVPicture *dst, AVFrame *src) +{ + int i; + dst->data[0] = src->data[0] + ( ctx->avctx->height - 1) * src->linesize[0]; + dst->data[1] = src->data[2] + ((ctx->avctx->height >> 1) - 1) * src->linesize[2]; + dst->data[2] = src->data[1] + ((ctx->avctx->height >> 1) - 1) * src->linesize[1]; + for (i = 0; i < 3; i++) + dst->linesize[i] = -src->linesize[i]; +} + +static int mimic_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int swap_buf_size = buf_size - MIMIC_HEADER_SIZE; + MimicContext *ctx = avctx->priv_data; + GetByteContext gb; + int is_pframe; + int width, height; + int quality, num_coeffs; + int res; + + if (buf_size <= MIMIC_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "insufficient data\n"); + return AVERROR_INVALIDDATA; + } + + bytestream2_init(&gb, buf, MIMIC_HEADER_SIZE); + bytestream2_skip(&gb, 2); /* some constant (always 256) */ + quality = bytestream2_get_le16u(&gb); + width = bytestream2_get_le16u(&gb); + height = bytestream2_get_le16u(&gb); + bytestream2_skip(&gb, 4); /* some constant */ + is_pframe = bytestream2_get_le32u(&gb); + num_coeffs = bytestream2_get_byteu(&gb); + bytestream2_skip(&gb, 3); /* some constant */ + + if (!ctx->avctx) { + int i; + + if (!(width == 160 && height == 120) && + !(width == 320 && height == 240)) { + av_log(avctx, AV_LOG_ERROR, "invalid width/height!\n"); + return AVERROR_INVALIDDATA; + } + + ctx->avctx = avctx; + avctx->width = width; + avctx->height = height; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + for (i = 0; i < 3; i++) { + ctx->num_vblocks[i] = -((-height) >> (3 + !!i)); + ctx->num_hblocks[i] = width >> (3 + !!i); + } + } else if (width != ctx->avctx->width || height != ctx->avctx->height) { + avpriv_request_sample(avctx, "Resolution changing"); + return AVERROR_PATCHWELCOME; + } + + if (is_pframe && !ctx->frames[ctx->prev_index].f->data[0]) { + av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n"); + return AVERROR_INVALIDDATA; + } + + ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); + ctx->frames[ctx->cur_index].f->pict_type = is_pframe ? AV_PICTURE_TYPE_P : + AV_PICTURE_TYPE_I; + if ((res = ff_thread_get_buffer(avctx, &ctx->frames[ctx->cur_index], + AV_GET_BUFFER_FLAG_REF)) < 0) + return res; + + ctx->next_prev_index = ctx->cur_index; + ctx->next_cur_index = (ctx->cur_index - 1) & 15; + + prepare_avpic(ctx, &ctx->flipped_ptrs[ctx->cur_index], + ctx->frames[ctx->cur_index].f); + + ff_thread_finish_setup(avctx); + + av_fast_padded_malloc(&ctx->swap_buf, &ctx->swap_buf_size, swap_buf_size); + if (!ctx->swap_buf) + return AVERROR(ENOMEM); + + ctx->dsp.bswap_buf(ctx->swap_buf, + (const uint32_t*) (buf + MIMIC_HEADER_SIZE), + swap_buf_size >> 2); + init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3); + + res = decode(ctx, quality, num_coeffs, !is_pframe); + ff_thread_report_progress(&ctx->frames[ctx->cur_index], INT_MAX, 0); + if (res < 0) { + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) { + ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); + return res; + } + } + + if ((res = av_frame_ref(data, ctx->frames[ctx->cur_index].f)) < 0) + return res; + *got_frame = 1; + + ctx->prev_index = ctx->next_prev_index; + ctx->cur_index = ctx->next_cur_index; + + /* Only release frames that aren't used for backreferences anymore */ + ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); + + return buf_size; +} + +static av_cold int mimic_init_thread_copy(AVCodecContext *avctx) +{ + MimicContext *ctx = avctx->priv_data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { + ctx->frames[i].f = av_frame_alloc(); + if (!ctx->frames[i].f) { + mimic_decode_end(avctx); + return AVERROR(ENOMEM); + } + } + + return 0; +} + +AVCodec ff_mimic_decoder = { + .name = "mimic", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MIMIC, + .priv_data_size = sizeof(MimicContext), + .init = mimic_decode_init, + .close = mimic_decode_end, + .decode = mimic_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Mimic"), + .update_thread_context = ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context), + .init_thread_copy = ONLY_IF_THREADS_ENABLED(mimic_init_thread_copy), +}; diff --git a/ffmpeg/libavcodec/mips/Makefile b/ffmpeg/libavcodec/mips/Makefile new file mode 100644 index 0000000..a2ea412 --- /dev/null +++ b/ffmpeg/libavcodec/mips/Makefile @@ -0,0 +1,21 @@ +MIPSFPU-OBJS-$(CONFIG_AMRNB_DECODER) += mips/acelp_filters_mips.o \ + mips/celp_filters_mips.o \ + mips/celp_math_mips.o \ + mips/acelp_vectors_mips.o +MIPSFPU-OBJS-$(CONFIG_AMRWB_DECODER) += mips/acelp_filters_mips.o \ + mips/celp_filters_mips.o \ + mips/amrwbdec_mips.o \ + mips/celp_math_mips.o \ + mips/acelp_vectors_mips.o +MIPSFPU-OBJS-$(CONFIG_MPEGAUDIODSP) += mips/mpegaudiodsp_mips_float.o +MIPSDSPR1-OBJS-$(CONFIG_MPEGAUDIODSP) += mips/mpegaudiodsp_mips_fixed.o +OBJS-$(CONFIG_FFT) += mips/fft_init_table.o +MIPSFPU-OBJS-$(CONFIG_FFT) += mips/fft_mips.o +MIPSFPU-OBJS += mips/fmtconvert_mips.o +OBJS-$(CONFIG_AC3DSP) += mips/ac3dsp_mips.o +OBJS-$(CONFIG_AAC_DECODER) += mips/aacdec_mips.o \ + mips/aacsbr_mips.o \ + mips/sbrdsp_mips.o \ + mips/aacpsdsp_mips.o +MIPSDSPR1-OBJS-$(CONFIG_AAC_ENCODER) += mips/aaccoder_mips.o +MIPSFPU-OBJS-$(CONFIG_AAC_ENCODER) += mips/iirfilter_mips.o diff --git a/ffmpeg/libavcodec/mips/aaccoder_mips.c b/ffmpeg/libavcodec/mips/aaccoder_mips.c new file mode 100644 index 0000000..d6210d1 --- /dev/null +++ b/ffmpeg/libavcodec/mips/aaccoder_mips.c @@ -0,0 +1,2498 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Stanislav Ocovaj (socovaj@mips.com) + * Szabolcs Pal (sabolc@mips.com) + * + * AAC coefficients encoder optimized for MIPS floating-point architecture + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/aaccoder.c + */ + +#include "libavutil/libm.h" + +#include +#include "libavutil/mathematics.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/put_bits.h" +#include "libavcodec/aac.h" +#include "libavcodec/aacenc.h" +#include "libavcodec/aactab.h" + +#if HAVE_INLINE_ASM +typedef struct BandCodingPath { + int prev_idx; + float cost; + int run; +} BandCodingPath; + +static const uint8_t run_value_bits_long[64] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 15 +}; + +static const uint8_t run_value_bits_short[16] = { + 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 9 +}; + +static const uint8_t *run_value_bits[2] = { + run_value_bits_long, run_value_bits_short +}; + +static const uint8_t uquad_sign_bits[81] = { + 0, 1, 1, 1, 2, 2, 1, 2, 2, + 1, 2, 2, 2, 3, 3, 2, 3, 3, + 1, 2, 2, 2, 3, 3, 2, 3, 3, + 1, 2, 2, 2, 3, 3, 2, 3, 3, + 2, 3, 3, 3, 4, 4, 3, 4, 4, + 2, 3, 3, 3, 4, 4, 3, 4, 4, + 1, 2, 2, 2, 3, 3, 2, 3, 3, + 2, 3, 3, 3, 4, 4, 3, 4, 4, + 2, 3, 3, 3, 4, 4, 3, 4, 4 +}; + +static const uint8_t upair7_sign_bits[64] = { + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t upair12_sign_bits[169] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static const uint8_t esc_sign_bits[289] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static void abs_pow34_v(float *out, const float *in, const int size) { +#ifndef USE_REALLY_FULL_SEARCH + int i; + float a, b, c, d; + float ax, bx, cx, dx; + + for (i = 0; i < size; i += 4) { + a = fabsf(in[i ]); + b = fabsf(in[i+1]); + c = fabsf(in[i+2]); + d = fabsf(in[i+3]); + + ax = sqrtf(a); + bx = sqrtf(b); + cx = sqrtf(c); + dx = sqrtf(d); + + a = a * ax; + b = b * bx; + c = c * cx; + d = d * dx; + + out[i ] = sqrtf(a); + out[i+1] = sqrtf(b); + out[i+2] = sqrtf(c); + out[i+3] = sqrtf(d); + } +#endif /* USE_REALLY_FULL_SEARCH */ +} + +static float find_max_val(int group_len, int swb_size, const float *scaled) { + float maxval = 0.0f; + int w2, i; + for (w2 = 0; w2 < group_len; w2++) { + for (i = 0; i < swb_size; i++) { + maxval = FFMAX(maxval, scaled[w2*128+i]); + } + } + return maxval; +} + +static int find_min_book(float maxval, int sf) { + float Q = ff_aac_pow2sf_tab[POW_SF2_ZERO - sf + SCALE_ONE_POS - SCALE_DIV_512]; + float Q34 = sqrtf(Q * sqrtf(Q)); + int qmaxval, cb; + qmaxval = maxval * Q34 + 0.4054f; + if (qmaxval == 0) cb = 0; + else if (qmaxval == 1) cb = 1; + else if (qmaxval == 2) cb = 3; + else if (qmaxval <= 4) cb = 5; + else if (qmaxval <= 7) cb = 7; + else if (qmaxval <= 12) cb = 9; + else cb = 11; + return cb; +} + +/** + * Functions developed from template function and optimized for quantizing and encoding band + */ +static void quantize_and_encode_band_cost_SQUAD_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; + + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + for (i = 0; i < size; i += 4) { + int curidx; + int *in_int = (int *)&in[i]; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "slt %[qc1], $zero, %[qc1] \n\t" + "slt %[qc2], $zero, %[qc2] \n\t" + "slt %[qc3], $zero, %[qc3] \n\t" + "slt %[qc4], $zero, %[qc4] \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "srl $t0, $t0, 31 \n\t" + "srl $t1, $t1, 31 \n\t" + "srl $t2, $t2, 31 \n\t" + "srl $t3, $t3, 31 \n\t" + "subu $t4, $zero, %[qc1] \n\t" + "subu $t5, $zero, %[qc2] \n\t" + "subu $t6, $zero, %[qc3] \n\t" + "subu $t7, $zero, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t5, $t1 \n\t" + "movn %[qc3], $t6, $t2 \n\t" + "movn %[qc4], $t7, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", + "memory" + ); + + curidx = qc1; + curidx *= 3; + curidx += qc2; + curidx *= 3; + curidx += qc3; + curidx *= 3; + curidx += qc4; + curidx += 40; + + put_bits(pb, p_bits[curidx], p_codes[curidx]); + } +} + +static void quantize_and_encode_band_cost_UQUAD_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; + + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + for (i = 0; i < size; i += 4) { + int curidx, sign, count; + int *in_int = (int *)&in[i]; + uint8_t v_bits; + unsigned int v_codes; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 2 \n\t" + "ori %[sign], $zero, 0 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign], $t0, %[qc1] \n\t" + "slt $t1, $t1, $zero \n\t" + "slt $t2, $t2, $zero \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign], $t0, %[qc2] \n\t" + "slt $t4, $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count], $zero, %[qc3] \n\t" + "sll $t0, %[sign], 1 \n\t" + "or $t0, $t0, $t2 \n\t" + "movn %[sign], $t0, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count], %[count], $t4 \n\t" + "addu %[count], %[count], $t1 \n\t" + "sll $t0, %[sign], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign], $t0, %[qc4] \n\t" + "addu %[count], %[count], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign]"=&r"(sign), [count]"=&r"(count) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = qc1; + curidx *= 3; + curidx += qc2; + curidx *= 3; + curidx += qc3; + curidx *= 3; + curidx += qc4; + + v_codes = (p_codes[curidx] << count) | (sign & ((1 << count) - 1)); + v_bits = p_bits[curidx] + count; + put_bits(pb, v_bits, v_codes); + } +} + +static void quantize_and_encode_band_cost_SPAIR_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; + + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + for (i = 0; i < size; i += 4) { + int curidx, curidx2; + int *in_int = (int *)&in[i]; + uint8_t v_bits; + unsigned int v_codes; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 4 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "srl $t0, $t0, 31 \n\t" + "srl $t1, $t1, 31 \n\t" + "srl $t2, $t2, 31 \n\t" + "srl $t3, $t3, 31 \n\t" + "subu $t4, $zero, %[qc1] \n\t" + "subu $t5, $zero, %[qc2] \n\t" + "subu $t6, $zero, %[qc3] \n\t" + "subu $t7, $zero, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t5, $t1 \n\t" + "movn %[qc3], $t6, $t2 \n\t" + "movn %[qc4], $t7, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", + "memory" + ); + + curidx = 9 * qc1; + curidx += qc2 + 40; + + curidx2 = 9 * qc3; + curidx2 += qc4 + 40; + + v_codes = (p_codes[curidx] << p_bits[curidx2]) | (p_codes[curidx2]); + v_bits = p_bits[curidx] + p_bits[curidx2]; + put_bits(pb, v_bits, v_codes); + } +} + +static void quantize_and_encode_band_cost_UPAIR7_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t*) ff_aac_spectral_bits[cb-1]; + uint16_t *p_codes = (uint16_t*)ff_aac_spectral_codes[cb-1]; + + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + for (i = 0; i < size; i += 4) { + int curidx, sign1, count1, sign2, count2; + int *in_int = (int *)&in[i]; + uint8_t v_bits; + unsigned int v_codes; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 7 \n\t" + "ori %[sign1], $zero, 0 \n\t" + "ori %[sign2], $zero, 0 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign1], $t0, %[qc1] \n\t" + "slt $t2, $t2, $zero \n\t" + "movn %[sign2], $t2, %[qc3] \n\t" + "slt $t1, $t1, $zero \n\t" + "sll $t0, %[sign1], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign1], $t0, %[qc2] \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign2], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign2], $t0, %[qc4] \n\t" + "slt %[count1], $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count2], $zero, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count1], %[count1], $t1 \n\t" + "addu %[count2], %[count2], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign1]"=&r"(sign1), [count1]"=&r"(count1), + [sign2]"=&r"(sign2), [count2]"=&r"(count2) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = 8 * qc1; + curidx += qc2; + + v_codes = (p_codes[curidx] << count1) | sign1; + v_bits = p_bits[curidx] + count1; + put_bits(pb, v_bits, v_codes); + + curidx = 8 * qc3; + curidx += qc4; + + v_codes = (p_codes[curidx] << count2) | sign2; + v_bits = p_bits[curidx] + count2; + put_bits(pb, v_bits, v_codes); + } +} + +static void quantize_and_encode_band_cost_UPAIR12_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t*) ff_aac_spectral_bits[cb-1]; + uint16_t *p_codes = (uint16_t*)ff_aac_spectral_codes[cb-1]; + + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + for (i = 0; i < size; i += 4) { + int curidx, sign1, count1, sign2, count2; + int *in_int = (int *)&in[i]; + uint8_t v_bits; + unsigned int v_codes; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 12 \n\t" + "ori %[sign1], $zero, 0 \n\t" + "ori %[sign2], $zero, 0 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign1], $t0, %[qc1] \n\t" + "slt $t2, $t2, $zero \n\t" + "movn %[sign2], $t2, %[qc3] \n\t" + "slt $t1, $t1, $zero \n\t" + "sll $t0, %[sign1], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign1], $t0, %[qc2] \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign2], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign2], $t0, %[qc4] \n\t" + "slt %[count1], $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count2], $zero, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count1], %[count1], $t1 \n\t" + "addu %[count2], %[count2], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign1]"=&r"(sign1), [count1]"=&r"(count1), + [sign2]"=&r"(sign2), [count2]"=&r"(count2) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = 13 * qc1; + curidx += qc2; + + v_codes = (p_codes[curidx] << count1) | sign1; + v_bits = p_bits[curidx] + count1; + put_bits(pb, v_bits, v_codes); + + curidx = 13 * qc3; + curidx += qc4; + + v_codes = (p_codes[curidx] << count2) | sign2; + v_bits = p_bits[curidx] + count2; + put_bits(pb, v_bits, v_codes); + } +} + +static void quantize_and_encode_band_cost_ESC_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t* )ff_aac_spectral_bits[cb-1]; + uint16_t *p_codes = (uint16_t*)ff_aac_spectral_codes[cb-1]; + float *p_vectors = (float* )ff_aac_codebook_vectors[cb-1]; + + abs_pow34_v(s->scoefs, in, size); + scaled = s->scoefs; + + if (cb < 11) { + for (i = 0; i < size; i += 4) { + int curidx, curidx2, sign1, count1, sign2, count2; + int *in_int = (int *)&in[i]; + uint8_t v_bits; + unsigned int v_codes; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 16 \n\t" + "ori %[sign1], $zero, 0 \n\t" + "ori %[sign2], $zero, 0 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign1], $t0, %[qc1] \n\t" + "slt $t2, $t2, $zero \n\t" + "movn %[sign2], $t2, %[qc3] \n\t" + "slt $t1, $t1, $zero \n\t" + "sll $t0, %[sign1], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign1], $t0, %[qc2] \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign2], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign2], $t0, %[qc4] \n\t" + "slt %[count1], $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count2], $zero, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count1], %[count1], $t1 \n\t" + "addu %[count2], %[count2], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign1]"=&r"(sign1), [count1]"=&r"(count1), + [sign2]"=&r"(sign2), [count2]"=&r"(count2) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = 17 * qc1; + curidx += qc2; + curidx2 = 17 * qc3; + curidx2 += qc4; + + v_codes = (p_codes[curidx] << count1) | sign1; + v_bits = p_bits[curidx] + count1; + put_bits(pb, v_bits, v_codes); + + v_codes = (p_codes[curidx2] << count2) | sign2; + v_bits = p_bits[curidx2] + count2; + put_bits(pb, v_bits, v_codes); + } + } else { + for (i = 0; i < size; i += 4) { + int curidx, curidx2, sign1, count1, sign2, count2; + int *in_int = (int *)&in[i]; + uint8_t v_bits; + unsigned int v_codes; + int c1, c2, c3, c4; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 16 \n\t" + "ori %[sign1], $zero, 0 \n\t" + "ori %[sign2], $zero, 0 \n\t" + "shll_s.w %[c1], %[qc1], 18 \n\t" + "shll_s.w %[c2], %[qc2], 18 \n\t" + "shll_s.w %[c3], %[qc3], 18 \n\t" + "shll_s.w %[c4], %[qc4], 18 \n\t" + "srl %[c1], %[c1], 18 \n\t" + "srl %[c2], %[c2], 18 \n\t" + "srl %[c3], %[c3], 18 \n\t" + "srl %[c4], %[c4], 18 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign1], $t0, %[qc1] \n\t" + "slt $t2, $t2, $zero \n\t" + "movn %[sign2], $t2, %[qc3] \n\t" + "slt $t1, $t1, $zero \n\t" + "sll $t0, %[sign1], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign1], $t0, %[qc2] \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign2], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign2], $t0, %[qc4] \n\t" + "slt %[count1], $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count2], $zero, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count1], %[count1], $t1 \n\t" + "addu %[count2], %[count2], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign1]"=&r"(sign1), [count1]"=&r"(count1), + [sign2]"=&r"(sign2), [count2]"=&r"(count2), + [c1]"=&r"(c1), [c2]"=&r"(c2), + [c3]"=&r"(c3), [c4]"=&r"(c4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = 17 * qc1; + curidx += qc2; + + curidx2 = 17 * qc3; + curidx2 += qc4; + + v_codes = (p_codes[curidx] << count1) | sign1; + v_bits = p_bits[curidx] + count1; + put_bits(pb, v_bits, v_codes); + + if (p_vectors[curidx*2 ] == 64.0f) { + int len = av_log2(c1); + v_codes = (((1 << (len - 3)) - 2) << len) | (c1 & ((1 << len) - 1)); + put_bits(pb, len * 2 - 3, v_codes); + } + if (p_vectors[curidx*2+1] == 64.0f) { + int len = av_log2(c2); + v_codes = (((1 << (len - 3)) - 2) << len) | (c2 & ((1 << len) - 1)); + put_bits(pb, len*2-3, v_codes); + } + + v_codes = (p_codes[curidx2] << count2) | sign2; + v_bits = p_bits[curidx2] + count2; + put_bits(pb, v_bits, v_codes); + + if (p_vectors[curidx2*2 ] == 64.0f) { + int len = av_log2(c3); + v_codes = (((1 << (len - 3)) - 2) << len) | (c3 & ((1 << len) - 1)); + put_bits(pb, len* 2 - 3, v_codes); + } + if (p_vectors[curidx2*2+1] == 64.0f) { + int len = av_log2(c4); + v_codes = (((1 << (len - 3)) - 2) << len) | (c4 & ((1 << len) - 1)); + put_bits(pb, len * 2 - 3, v_codes); + } + } + } +} + +static void (*const quantize_and_encode_band_cost_arr[])(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) = { + NULL, + quantize_and_encode_band_cost_SQUAD_mips, + quantize_and_encode_band_cost_SQUAD_mips, + quantize_and_encode_band_cost_UQUAD_mips, + quantize_and_encode_band_cost_UQUAD_mips, + quantize_and_encode_band_cost_SPAIR_mips, + quantize_and_encode_band_cost_SPAIR_mips, + quantize_and_encode_band_cost_UPAIR7_mips, + quantize_and_encode_band_cost_UPAIR7_mips, + quantize_and_encode_band_cost_UPAIR12_mips, + quantize_and_encode_band_cost_UPAIR12_mips, + quantize_and_encode_band_cost_ESC_mips, +}; + +#define quantize_and_encode_band_cost( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) \ + quantize_and_encode_band_cost_arr[cb]( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) + +static void quantize_and_encode_band_mips(struct AACEncContext *s, PutBitContext *pb, + const float *in, int size, int scale_idx, + int cb, const float lambda) +{ + quantize_and_encode_band_cost(s, pb, in, NULL, size, scale_idx, cb, lambda, + INFINITY, NULL); +} + +/** + * Functions developed from template function and optimized for getting the number of bits + */ +static float get_band_numbits_ZERO_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + return 0; +} + +static float get_band_numbits_SQUAD_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + + for (i = 0; i < size; i += 4) { + int curidx; + int *in_int = (int *)&in[i]; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "slt %[qc1], $zero, %[qc1] \n\t" + "slt %[qc2], $zero, %[qc2] \n\t" + "slt %[qc3], $zero, %[qc3] \n\t" + "slt %[qc4], $zero, %[qc4] \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "srl $t0, $t0, 31 \n\t" + "srl $t1, $t1, 31 \n\t" + "srl $t2, $t2, 31 \n\t" + "srl $t3, $t3, 31 \n\t" + "subu $t4, $zero, %[qc1] \n\t" + "subu $t5, $zero, %[qc2] \n\t" + "subu $t6, $zero, %[qc3] \n\t" + "subu $t7, $zero, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t5, $t1 \n\t" + "movn %[qc3], $t6, $t2 \n\t" + "movn %[qc4], $t7, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", + "memory" + ); + + curidx = qc1; + curidx *= 3; + curidx += qc2; + curidx *= 3; + curidx += qc3; + curidx *= 3; + curidx += qc4; + curidx += 40; + + curbits += p_bits[curidx]; + } + return curbits; +} + +static float get_band_numbits_UQUAD_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int curbits = 0; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + + for (i = 0; i < size; i += 4) { + int curidx; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 2 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : + : "t0", "t1", "t2", "t3", "t4" + ); + + curidx = qc1; + curidx *= 3; + curidx += qc2; + curidx *= 3; + curidx += qc3; + curidx *= 3; + curidx += qc4; + + curbits += p_bits[curidx]; + curbits += uquad_sign_bits[curidx]; + } + return curbits; +} + +static float get_band_numbits_SPAIR_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t*)ff_aac_spectral_bits[cb-1]; + + for (i = 0; i < size; i += 4) { + int curidx, curidx2; + int *in_int = (int *)&in[i]; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 4 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "srl $t0, $t0, 31 \n\t" + "srl $t1, $t1, 31 \n\t" + "srl $t2, $t2, 31 \n\t" + "srl $t3, $t3, 31 \n\t" + "subu $t4, $zero, %[qc1] \n\t" + "subu $t5, $zero, %[qc2] \n\t" + "subu $t6, $zero, %[qc3] \n\t" + "subu $t7, $zero, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t5, $t1 \n\t" + "movn %[qc3], $t6, $t2 \n\t" + "movn %[qc4], $t7, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", + "memory" + ); + + curidx = 9 * qc1; + curidx += qc2 + 40; + + curidx2 = 9 * qc3; + curidx2 += qc4 + 40; + + curbits += p_bits[curidx] + p_bits[curidx2]; + } + return curbits; +} + +static float get_band_numbits_UPAIR7_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + + for (i = 0; i < size; i += 4) { + int curidx, curidx2; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 7 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : + : "t0", "t1", "t2", "t3", "t4" + ); + + curidx = 8 * qc1; + curidx += qc2; + + curidx2 = 8 * qc3; + curidx2 += qc4; + + curbits += p_bits[curidx] + + upair7_sign_bits[curidx] + + p_bits[curidx2] + + upair7_sign_bits[curidx2]; + } + return curbits; +} + +static float get_band_numbits_UPAIR12_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + + for (i = 0; i < size; i += 4) { + int curidx, curidx2; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 12 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : + : "t0", "t1", "t2", "t3", "t4" + ); + + curidx = 13 * qc1; + curidx += qc2; + + curidx2 = 13 * qc3; + curidx2 += qc4; + + curbits += p_bits[curidx] + + p_bits[curidx2] + + upair12_sign_bits[curidx] + + upair12_sign_bits[curidx2]; + } + return curbits; +} + +static float get_band_numbits_ESC_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + int i; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t*)ff_aac_spectral_bits[cb-1]; + + for (i = 0; i < size; i += 4) { + int curidx, curidx2; + int cond0, cond1, cond2, cond3; + int c1, c2, c3, c4; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 15 \n\t" + "ori $t5, $zero, 16 \n\t" + "shll_s.w %[c1], %[qc1], 18 \n\t" + "shll_s.w %[c2], %[qc2], 18 \n\t" + "shll_s.w %[c3], %[qc3], 18 \n\t" + "shll_s.w %[c4], %[qc4], 18 \n\t" + "srl %[c1], %[c1], 18 \n\t" + "srl %[c2], %[c2], 18 \n\t" + "srl %[c3], %[c3], 18 \n\t" + "srl %[c4], %[c4], 18 \n\t" + "slt %[cond0], $t4, %[qc1] \n\t" + "slt %[cond1], $t4, %[qc2] \n\t" + "slt %[cond2], $t4, %[qc3] \n\t" + "slt %[cond3], $t4, %[qc4] \n\t" + "movn %[qc1], $t5, %[cond0] \n\t" + "movn %[qc2], $t5, %[cond1] \n\t" + "movn %[qc3], $t5, %[cond2] \n\t" + "movn %[qc4], $t5, %[cond3] \n\t" + "ori $t5, $zero, 31 \n\t" + "clz %[c1], %[c1] \n\t" + "clz %[c2], %[c2] \n\t" + "clz %[c3], %[c3] \n\t" + "clz %[c4], %[c4] \n\t" + "subu %[c1], $t5, %[c1] \n\t" + "subu %[c2], $t5, %[c2] \n\t" + "subu %[c3], $t5, %[c3] \n\t" + "subu %[c4], $t5, %[c4] \n\t" + "sll %[c1], %[c1], 1 \n\t" + "sll %[c2], %[c2], 1 \n\t" + "sll %[c3], %[c3], 1 \n\t" + "sll %[c4], %[c4], 1 \n\t" + "addiu %[c1], %[c1], -3 \n\t" + "addiu %[c2], %[c2], -3 \n\t" + "addiu %[c3], %[c3], -3 \n\t" + "addiu %[c4], %[c4], -3 \n\t" + "subu %[cond0], $zero, %[cond0] \n\t" + "subu %[cond1], $zero, %[cond1] \n\t" + "subu %[cond2], $zero, %[cond2] \n\t" + "subu %[cond3], $zero, %[cond3] \n\t" + "and %[c1], %[c1], %[cond0] \n\t" + "and %[c2], %[c2], %[cond1] \n\t" + "and %[c3], %[c3], %[cond2] \n\t" + "and %[c4], %[c4], %[cond3] \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [cond0]"=&r"(cond0), [cond1]"=&r"(cond1), + [cond2]"=&r"(cond2), [cond3]"=&r"(cond3), + [c1]"=&r"(c1), [c2]"=&r"(c2), + [c3]"=&r"(c3), [c4]"=&r"(c4) + : + : "t4", "t5" + ); + + curidx = 17 * qc1; + curidx += qc2; + + curidx2 = 17 * qc3; + curidx2 += qc4; + + curbits += p_bits[curidx]; + curbits += esc_sign_bits[curidx]; + curbits += p_bits[curidx2]; + curbits += esc_sign_bits[curidx2]; + + curbits += c1; + curbits += c2; + curbits += c3; + curbits += c4; + } + return curbits; +} + +static float (*const get_band_numbits_arr[])(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) = { + get_band_numbits_ZERO_mips, + get_band_numbits_SQUAD_mips, + get_band_numbits_SQUAD_mips, + get_band_numbits_UQUAD_mips, + get_band_numbits_UQUAD_mips, + get_band_numbits_SPAIR_mips, + get_band_numbits_SPAIR_mips, + get_band_numbits_UPAIR7_mips, + get_band_numbits_UPAIR7_mips, + get_band_numbits_UPAIR12_mips, + get_band_numbits_UPAIR12_mips, + get_band_numbits_ESC_mips, +}; + +#define get_band_numbits( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) \ + get_band_numbits_arr[cb]( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) + +static float quantize_band_cost_bits(struct AACEncContext *s, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + return get_band_numbits(s, NULL, in, scaled, size, scale_idx, cb, lambda, uplim, bits); +} + +/** + * Functions developed from template function and optimized for getting the band cost + */ +#if HAVE_MIPSFPU +static float get_band_cost_ZERO_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + int i; + float cost = 0; + + for (i = 0; i < size; i += 4) { + cost += in[i ] * in[i ]; + cost += in[i+1] * in[i+1]; + cost += in[i+2] * in[i+2]; + cost += in[i+3] * in[i+3]; + } + if (bits) + *bits = 0; + return cost * lambda; +} + +static float get_band_cost_SQUAD_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + int i; + float cost = 0; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + float *p_codes = (float *)ff_aac_codebook_vectors[cb-1]; + + for (i = 0; i < size; i += 4) { + const float *vec; + int curidx; + int *in_int = (int *)&in[i]; + float *in_pos = (float *)&in[i]; + float di0, di1, di2, di3; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "slt %[qc1], $zero, %[qc1] \n\t" + "slt %[qc2], $zero, %[qc2] \n\t" + "slt %[qc3], $zero, %[qc3] \n\t" + "slt %[qc4], $zero, %[qc4] \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "srl $t0, $t0, 31 \n\t" + "srl $t1, $t1, 31 \n\t" + "srl $t2, $t2, 31 \n\t" + "srl $t3, $t3, 31 \n\t" + "subu $t4, $zero, %[qc1] \n\t" + "subu $t5, $zero, %[qc2] \n\t" + "subu $t6, $zero, %[qc3] \n\t" + "subu $t7, $zero, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t5, $t1 \n\t" + "movn %[qc3], $t6, $t2 \n\t" + "movn %[qc4], $t7, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", + "memory" + ); + + curidx = qc1; + curidx *= 3; + curidx += qc2; + curidx *= 3; + curidx += qc3; + curidx *= 3; + curidx += qc4; + curidx += 40; + + curbits += p_bits[curidx]; + vec = &p_codes[curidx*4]; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "lwc1 $f0, 0(%[in_pos]) \n\t" + "lwc1 $f1, 0(%[vec]) \n\t" + "lwc1 $f2, 4(%[in_pos]) \n\t" + "lwc1 $f3, 4(%[vec]) \n\t" + "lwc1 $f4, 8(%[in_pos]) \n\t" + "lwc1 $f5, 8(%[vec]) \n\t" + "lwc1 $f6, 12(%[in_pos]) \n\t" + "lwc1 $f7, 12(%[vec]) \n\t" + "nmsub.s %[di0], $f0, $f1, %[IQ] \n\t" + "nmsub.s %[di1], $f2, $f3, %[IQ] \n\t" + "nmsub.s %[di2], $f4, $f5, %[IQ] \n\t" + "nmsub.s %[di3], $f6, $f7, %[IQ] \n\t" + + ".set pop \n\t" + + : [di0]"=&f"(di0), [di1]"=&f"(di1), + [di2]"=&f"(di2), [di3]"=&f"(di3) + : [in_pos]"r"(in_pos), [vec]"r"(vec), + [IQ]"f"(IQ) + : "$f0", "$f1", "$f2", "$f3", + "$f4", "$f5", "$f6", "$f7", + "memory" + ); + + cost += di0 * di0 + di1 * di1 + + di2 * di2 + di3 * di3; + } + + if (bits) + *bits = curbits; + return cost * lambda + curbits; +} + +static float get_band_cost_UQUAD_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + int i; + float cost = 0; + int curbits = 0; + int qc1, qc2, qc3, qc4; + + uint8_t *p_bits = (uint8_t*)ff_aac_spectral_bits[cb-1]; + float *p_codes = (float *)ff_aac_codebook_vectors[cb-1]; + + for (i = 0; i < size; i += 4) { + const float *vec; + int curidx; + float *in_pos = (float *)&in[i]; + float di0, di1, di2, di3; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 2 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : + : "t0", "t1", "t2", "t3", "t4" + ); + + curidx = qc1; + curidx *= 3; + curidx += qc2; + curidx *= 3; + curidx += qc3; + curidx *= 3; + curidx += qc4; + + curbits += p_bits[curidx]; + curbits += uquad_sign_bits[curidx]; + vec = &p_codes[curidx*4]; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "lwc1 %[di0], 0(%[in_pos]) \n\t" + "lwc1 %[di1], 4(%[in_pos]) \n\t" + "lwc1 %[di2], 8(%[in_pos]) \n\t" + "lwc1 %[di3], 12(%[in_pos]) \n\t" + "abs.s %[di0], %[di0] \n\t" + "abs.s %[di1], %[di1] \n\t" + "abs.s %[di2], %[di2] \n\t" + "abs.s %[di3], %[di3] \n\t" + "lwc1 $f0, 0(%[vec]) \n\t" + "lwc1 $f1, 4(%[vec]) \n\t" + "lwc1 $f2, 8(%[vec]) \n\t" + "lwc1 $f3, 12(%[vec]) \n\t" + "nmsub.s %[di0], %[di0], $f0, %[IQ] \n\t" + "nmsub.s %[di1], %[di1], $f1, %[IQ] \n\t" + "nmsub.s %[di2], %[di2], $f2, %[IQ] \n\t" + "nmsub.s %[di3], %[di3], $f3, %[IQ] \n\t" + + ".set pop \n\t" + + : [di0]"=&f"(di0), [di1]"=&f"(di1), + [di2]"=&f"(di2), [di3]"=&f"(di3) + : [in_pos]"r"(in_pos), [vec]"r"(vec), + [IQ]"f"(IQ) + : "$f0", "$f1", "$f2", "$f3", + "memory" + ); + + cost += di0 * di0 + di1 * di1 + + di2 * di2 + di3 * di3; + } + + if (bits) + *bits = curbits; + return cost * lambda + curbits; +} + +static float get_band_cost_SPAIR_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + int i; + float cost = 0; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + float *p_codes = (float *)ff_aac_codebook_vectors[cb-1]; + + for (i = 0; i < size; i += 4) { + const float *vec, *vec2; + int curidx, curidx2; + int *in_int = (int *)&in[i]; + float *in_pos = (float *)&in[i]; + float di0, di1, di2, di3; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 4 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "srl $t0, $t0, 31 \n\t" + "srl $t1, $t1, 31 \n\t" + "srl $t2, $t2, 31 \n\t" + "srl $t3, $t3, 31 \n\t" + "subu $t4, $zero, %[qc1] \n\t" + "subu $t5, $zero, %[qc2] \n\t" + "subu $t6, $zero, %[qc3] \n\t" + "subu $t7, $zero, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t5, $t1 \n\t" + "movn %[qc3], $t6, $t2 \n\t" + "movn %[qc4], $t7, $t3 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", + "t4", "t5", "t6", "t7", + "memory" + ); + + curidx = 9 * qc1; + curidx += qc2 + 40; + + curidx2 = 9 * qc3; + curidx2 += qc4 + 40; + + curbits += p_bits[curidx]; + curbits += p_bits[curidx2]; + + vec = &p_codes[curidx*2]; + vec2 = &p_codes[curidx2*2]; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "lwc1 $f0, 0(%[in_pos]) \n\t" + "lwc1 $f1, 0(%[vec]) \n\t" + "lwc1 $f2, 4(%[in_pos]) \n\t" + "lwc1 $f3, 4(%[vec]) \n\t" + "lwc1 $f4, 8(%[in_pos]) \n\t" + "lwc1 $f5, 0(%[vec2]) \n\t" + "lwc1 $f6, 12(%[in_pos]) \n\t" + "lwc1 $f7, 4(%[vec2]) \n\t" + "nmsub.s %[di0], $f0, $f1, %[IQ] \n\t" + "nmsub.s %[di1], $f2, $f3, %[IQ] \n\t" + "nmsub.s %[di2], $f4, $f5, %[IQ] \n\t" + "nmsub.s %[di3], $f6, $f7, %[IQ] \n\t" + + ".set pop \n\t" + + : [di0]"=&f"(di0), [di1]"=&f"(di1), + [di2]"=&f"(di2), [di3]"=&f"(di3) + : [in_pos]"r"(in_pos), [vec]"r"(vec), + [vec2]"r"(vec2), [IQ]"f"(IQ) + : "$f0", "$f1", "$f2", "$f3", + "$f4", "$f5", "$f6", "$f7", + "memory" + ); + + cost += di0 * di0 + di1 * di1 + + di2 * di2 + di3 * di3; + } + + if (bits) + *bits = curbits; + return cost * lambda + curbits; +} + +static float get_band_cost_UPAIR7_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + int i; + float cost = 0; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + float *p_codes = (float *)ff_aac_codebook_vectors[cb-1]; + + for (i = 0; i < size; i += 4) { + const float *vec, *vec2; + int curidx, curidx2, sign1, count1, sign2, count2; + int *in_int = (int *)&in[i]; + float *in_pos = (float *)&in[i]; + float di0, di1, di2, di3; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 7 \n\t" + "ori %[sign1], $zero, 0 \n\t" + "ori %[sign2], $zero, 0 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign1], $t0, %[qc1] \n\t" + "slt $t2, $t2, $zero \n\t" + "movn %[sign2], $t2, %[qc3] \n\t" + "slt $t1, $t1, $zero \n\t" + "sll $t0, %[sign1], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign1], $t0, %[qc2] \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign2], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign2], $t0, %[qc4] \n\t" + "slt %[count1], $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count2], $zero, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count1], %[count1], $t1 \n\t" + "addu %[count2], %[count2], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign1]"=&r"(sign1), [count1]"=&r"(count1), + [sign2]"=&r"(sign2), [count2]"=&r"(count2) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = 8 * qc1; + curidx += qc2; + + curidx2 = 8 * qc3; + curidx2 += qc4; + + curbits += p_bits[curidx]; + curbits += upair7_sign_bits[curidx]; + vec = &p_codes[curidx*2]; + + curbits += p_bits[curidx2]; + curbits += upair7_sign_bits[curidx2]; + vec2 = &p_codes[curidx2*2]; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "lwc1 %[di0], 0(%[in_pos]) \n\t" + "lwc1 %[di1], 4(%[in_pos]) \n\t" + "lwc1 %[di2], 8(%[in_pos]) \n\t" + "lwc1 %[di3], 12(%[in_pos]) \n\t" + "abs.s %[di0], %[di0] \n\t" + "abs.s %[di1], %[di1] \n\t" + "abs.s %[di2], %[di2] \n\t" + "abs.s %[di3], %[di3] \n\t" + "lwc1 $f0, 0(%[vec]) \n\t" + "lwc1 $f1, 4(%[vec]) \n\t" + "lwc1 $f2, 0(%[vec2]) \n\t" + "lwc1 $f3, 4(%[vec2]) \n\t" + "nmsub.s %[di0], %[di0], $f0, %[IQ] \n\t" + "nmsub.s %[di1], %[di1], $f1, %[IQ] \n\t" + "nmsub.s %[di2], %[di2], $f2, %[IQ] \n\t" + "nmsub.s %[di3], %[di3], $f3, %[IQ] \n\t" + + ".set pop \n\t" + + : [di0]"=&f"(di0), [di1]"=&f"(di1), + [di2]"=&f"(di2), [di3]"=&f"(di3) + : [in_pos]"r"(in_pos), [vec]"r"(vec), + [vec2]"r"(vec2), [IQ]"f"(IQ) + : "$f0", "$f1", "$f2", "$f3", + "memory" + ); + + cost += di0 * di0 + di1 * di1 + + di2 * di2 + di3 * di3; + } + + if (bits) + *bits = curbits; + return cost * lambda + curbits; +} + +static float get_band_cost_UPAIR12_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + int i; + float cost = 0; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; + float *p_codes = (float *)ff_aac_codebook_vectors[cb-1]; + + for (i = 0; i < size; i += 4) { + const float *vec, *vec2; + int curidx, curidx2; + int sign1, count1, sign2, count2; + int *in_int = (int *)&in[i]; + float *in_pos = (float *)&in[i]; + float di0, di1, di2, di3; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 12 \n\t" + "ori %[sign1], $zero, 0 \n\t" + "ori %[sign2], $zero, 0 \n\t" + "slt $t0, $t4, %[qc1] \n\t" + "slt $t1, $t4, %[qc2] \n\t" + "slt $t2, $t4, %[qc3] \n\t" + "slt $t3, $t4, %[qc4] \n\t" + "movn %[qc1], $t4, $t0 \n\t" + "movn %[qc2], $t4, $t1 \n\t" + "movn %[qc3], $t4, $t2 \n\t" + "movn %[qc4], $t4, $t3 \n\t" + "lw $t0, 0(%[in_int]) \n\t" + "lw $t1, 4(%[in_int]) \n\t" + "lw $t2, 8(%[in_int]) \n\t" + "lw $t3, 12(%[in_int]) \n\t" + "slt $t0, $t0, $zero \n\t" + "movn %[sign1], $t0, %[qc1] \n\t" + "slt $t2, $t2, $zero \n\t" + "movn %[sign2], $t2, %[qc3] \n\t" + "slt $t1, $t1, $zero \n\t" + "sll $t0, %[sign1], 1 \n\t" + "or $t0, $t0, $t1 \n\t" + "movn %[sign1], $t0, %[qc2] \n\t" + "slt $t3, $t3, $zero \n\t" + "sll $t0, %[sign2], 1 \n\t" + "or $t0, $t0, $t3 \n\t" + "movn %[sign2], $t0, %[qc4] \n\t" + "slt %[count1], $zero, %[qc1] \n\t" + "slt $t1, $zero, %[qc2] \n\t" + "slt %[count2], $zero, %[qc3] \n\t" + "slt $t2, $zero, %[qc4] \n\t" + "addu %[count1], %[count1], $t1 \n\t" + "addu %[count2], %[count2], $t2 \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [sign1]"=&r"(sign1), [count1]"=&r"(count1), + [sign2]"=&r"(sign2), [count2]"=&r"(count2) + : [in_int]"r"(in_int) + : "t0", "t1", "t2", "t3", "t4", + "memory" + ); + + curidx = 13 * qc1; + curidx += qc2; + + curidx2 = 13 * qc3; + curidx2 += qc4; + + curbits += p_bits[curidx]; + curbits += p_bits[curidx2]; + curbits += upair12_sign_bits[curidx]; + curbits += upair12_sign_bits[curidx2]; + vec = &p_codes[curidx*2]; + vec2 = &p_codes[curidx2*2]; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "lwc1 %[di0], 0(%[in_pos]) \n\t" + "lwc1 %[di1], 4(%[in_pos]) \n\t" + "lwc1 %[di2], 8(%[in_pos]) \n\t" + "lwc1 %[di3], 12(%[in_pos]) \n\t" + "abs.s %[di0], %[di0] \n\t" + "abs.s %[di1], %[di1] \n\t" + "abs.s %[di2], %[di2] \n\t" + "abs.s %[di3], %[di3] \n\t" + "lwc1 $f0, 0(%[vec]) \n\t" + "lwc1 $f1, 4(%[vec]) \n\t" + "lwc1 $f2, 0(%[vec2]) \n\t" + "lwc1 $f3, 4(%[vec2]) \n\t" + "nmsub.s %[di0], %[di0], $f0, %[IQ] \n\t" + "nmsub.s %[di1], %[di1], $f1, %[IQ] \n\t" + "nmsub.s %[di2], %[di2], $f2, %[IQ] \n\t" + "nmsub.s %[di3], %[di3], $f3, %[IQ] \n\t" + + ".set pop \n\t" + + : [di0]"=&f"(di0), [di1]"=&f"(di1), + [di2]"=&f"(di2), [di3]"=&f"(di3) + : [in_pos]"r"(in_pos), [vec]"r"(vec), + [vec2]"r"(vec2), [IQ]"f"(IQ) + : "$f0", "$f1", "$f2", "$f3", + "memory" + ); + + cost += di0 * di0 + di1 * di1 + + di2 * di2 + di3 * di3; + } + + if (bits) + *bits = curbits; + return cost * lambda + curbits; +} + +static float get_band_cost_ESC_mips(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; + const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; + const float CLIPPED_ESCAPE = 165140.0f * IQ; + int i; + float cost = 0; + int qc1, qc2, qc3, qc4; + int curbits = 0; + + uint8_t *p_bits = (uint8_t*)ff_aac_spectral_bits[cb-1]; + float *p_codes = (float* )ff_aac_codebook_vectors[cb-1]; + + for (i = 0; i < size; i += 4) { + const float *vec, *vec2; + int curidx, curidx2; + float t1, t2, t3, t4; + float di1, di2, di3, di4; + int cond0, cond1, cond2, cond3; + int c1, c2, c3, c4; + + qc1 = scaled[i ] * Q34 + 0.4054f; + qc2 = scaled[i+1] * Q34 + 0.4054f; + qc3 = scaled[i+2] * Q34 + 0.4054f; + qc4 = scaled[i+3] * Q34 + 0.4054f; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + + "ori $t4, $zero, 15 \n\t" + "ori $t5, $zero, 16 \n\t" + "shll_s.w %[c1], %[qc1], 18 \n\t" + "shll_s.w %[c2], %[qc2], 18 \n\t" + "shll_s.w %[c3], %[qc3], 18 \n\t" + "shll_s.w %[c4], %[qc4], 18 \n\t" + "srl %[c1], %[c1], 18 \n\t" + "srl %[c2], %[c2], 18 \n\t" + "srl %[c3], %[c3], 18 \n\t" + "srl %[c4], %[c4], 18 \n\t" + "slt %[cond0], $t4, %[qc1] \n\t" + "slt %[cond1], $t4, %[qc2] \n\t" + "slt %[cond2], $t4, %[qc3] \n\t" + "slt %[cond3], $t4, %[qc4] \n\t" + "movn %[qc1], $t5, %[cond0] \n\t" + "movn %[qc2], $t5, %[cond1] \n\t" + "movn %[qc3], $t5, %[cond2] \n\t" + "movn %[qc4], $t5, %[cond3] \n\t" + + ".set pop \n\t" + + : [qc1]"+r"(qc1), [qc2]"+r"(qc2), + [qc3]"+r"(qc3), [qc4]"+r"(qc4), + [cond0]"=&r"(cond0), [cond1]"=&r"(cond1), + [cond2]"=&r"(cond2), [cond3]"=&r"(cond3), + [c1]"=&r"(c1), [c2]"=&r"(c2), + [c3]"=&r"(c3), [c4]"=&r"(c4) + : + : "t4", "t5" + ); + + curidx = 17 * qc1; + curidx += qc2; + + curidx2 = 17 * qc3; + curidx2 += qc4; + + curbits += p_bits[curidx]; + curbits += esc_sign_bits[curidx]; + vec = &p_codes[curidx*2]; + + curbits += p_bits[curidx2]; + curbits += esc_sign_bits[curidx2]; + vec2 = &p_codes[curidx2*2]; + + curbits += (av_log2(c1) * 2 - 3) & (-cond0); + curbits += (av_log2(c2) * 2 - 3) & (-cond1); + curbits += (av_log2(c3) * 2 - 3) & (-cond2); + curbits += (av_log2(c4) * 2 - 3) & (-cond3); + + t1 = fabsf(in[i ]); + t2 = fabsf(in[i+1]); + t3 = fabsf(in[i+2]); + t4 = fabsf(in[i+3]); + + if (cond0) { + if (t1 >= CLIPPED_ESCAPE) { + di1 = t1 - CLIPPED_ESCAPE; + } else { + di1 = t1 - c1 * cbrtf(c1) * IQ; + } + } else + di1 = t1 - vec[0] * IQ; + + if (cond1) { + if (t2 >= CLIPPED_ESCAPE) { + di2 = t2 - CLIPPED_ESCAPE; + } else { + di2 = t2 - c2 * cbrtf(c2) * IQ; + } + } else + di2 = t2 - vec[1] * IQ; + + if (cond2) { + if (t3 >= CLIPPED_ESCAPE) { + di3 = t3 - CLIPPED_ESCAPE; + } else { + di3 = t3 - c3 * cbrtf(c3) * IQ; + } + } else + di3 = t3 - vec2[0] * IQ; + + if (cond3) { + if (t4 >= CLIPPED_ESCAPE) { + di4 = t4 - CLIPPED_ESCAPE; + } else { + di4 = t4 - c4 * cbrtf(c4) * IQ; + } + } else + di4 = t4 - vec2[1]*IQ; + + cost += di1 * di1 + di2 * di2 + + di3 * di3 + di4 * di4; + } + + if (bits) + *bits = curbits; + return cost * lambda + curbits; +} + +static float (*const get_band_cost_arr[])(struct AACEncContext *s, + PutBitContext *pb, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) = { + get_band_cost_ZERO_mips, + get_band_cost_SQUAD_mips, + get_band_cost_SQUAD_mips, + get_band_cost_UQUAD_mips, + get_band_cost_UQUAD_mips, + get_band_cost_SPAIR_mips, + get_band_cost_SPAIR_mips, + get_band_cost_UPAIR7_mips, + get_band_cost_UPAIR7_mips, + get_band_cost_UPAIR12_mips, + get_band_cost_UPAIR12_mips, + get_band_cost_ESC_mips, +}; + +#define get_band_cost( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) \ + get_band_cost_arr[cb]( \ + s, pb, in, scaled, size, scale_idx, cb, \ + lambda, uplim, bits) + +static float quantize_band_cost(struct AACEncContext *s, const float *in, + const float *scaled, int size, int scale_idx, + int cb, const float lambda, const float uplim, + int *bits) +{ + return get_band_cost(s, NULL, in, scaled, size, scale_idx, cb, lambda, uplim, bits); +} + +static void search_for_quantizers_twoloop_mips(AVCodecContext *avctx, + AACEncContext *s, + SingleChannelElement *sce, + const float lambda) +{ + int start = 0, i, w, w2, g; + int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels; + float dists[128] = { 0 }, uplims[128]; + float maxvals[128]; + int fflag, minscaler; + int its = 0; + int allz = 0; + float minthr = INFINITY; + + destbits = FFMIN(destbits, 5800); + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + int nz = 0; + float uplim = 0.0f; + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; + uplim += band->threshold; + if (band->energy <= band->threshold || band->threshold == 0.0f) { + sce->zeroes[(w+w2)*16+g] = 1; + continue; + } + nz = 1; + } + uplims[w*16+g] = uplim *512; + sce->zeroes[w*16+g] = !nz; + if (nz) + minthr = FFMIN(minthr, uplim); + allz |= nz; + } + } + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + if (sce->zeroes[w*16+g]) { + sce->sf_idx[w*16+g] = SCALE_ONE_POS; + continue; + } + sce->sf_idx[w*16+g] = SCALE_ONE_POS + FFMIN(log2f(uplims[w*16+g]/minthr)*4,59); + } + } + + if (!allz) + return; + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *scaled = s->scoefs + start; + maxvals[w*16+g] = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], scaled); + start += sce->ics.swb_sizes[g]; + } + } + + do { + int tbits, qstep; + minscaler = sce->sf_idx[0]; + qstep = its ? 1 : 32; + do { + int prev = -1; + tbits = 0; + fflag = 0; + + if (qstep > 1) { + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *coefs = sce->coeffs + start; + const float *scaled = s->scoefs + start; + int bits = 0; + int cb; + + if (sce->zeroes[w*16+g] || sce->sf_idx[w*16+g] >= 218) { + start += sce->ics.swb_sizes[g]; + continue; + } + minscaler = FFMIN(minscaler, sce->sf_idx[w*16+g]); + cb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + int b; + bits += quantize_band_cost_bits(s, coefs + w2*128, + scaled + w2*128, + sce->ics.swb_sizes[g], + sce->sf_idx[w*16+g], + cb, + 1.0f, + INFINITY, + &b); + } + if (prev != -1) { + bits += ff_aac_scalefactor_bits[sce->sf_idx[w*16+g] - prev + SCALE_DIFF_ZERO]; + } + tbits += bits; + start += sce->ics.swb_sizes[g]; + prev = sce->sf_idx[w*16+g]; + } + } + } + else { + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + start = w*128; + for (g = 0; g < sce->ics.num_swb; g++) { + const float *coefs = sce->coeffs + start; + const float *scaled = s->scoefs + start; + int bits = 0; + int cb; + float dist = 0.0f; + + if (sce->zeroes[w*16+g] || sce->sf_idx[w*16+g] >= 218) { + start += sce->ics.swb_sizes[g]; + continue; + } + minscaler = FFMIN(minscaler, sce->sf_idx[w*16+g]); + cb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); + for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { + int b; + dist += quantize_band_cost(s, coefs + w2*128, + scaled + w2*128, + sce->ics.swb_sizes[g], + sce->sf_idx[w*16+g], + cb, + 1.0f, + INFINITY, + &b); + bits += b; + } + dists[w*16+g] = dist - bits; + if (prev != -1) { + bits += ff_aac_scalefactor_bits[sce->sf_idx[w*16+g] - prev + SCALE_DIFF_ZERO]; + } + tbits += bits; + start += sce->ics.swb_sizes[g]; + prev = sce->sf_idx[w*16+g]; + } + } + } + if (tbits > destbits) { + for (i = 0; i < 128; i++) + if (sce->sf_idx[i] < 218 - qstep) + sce->sf_idx[i] += qstep; + } else { + for (i = 0; i < 128; i++) + if (sce->sf_idx[i] > 60 - qstep) + sce->sf_idx[i] -= qstep; + } + qstep >>= 1; + if (!qstep && tbits > destbits*1.02 && sce->sf_idx[0] < 217) + qstep = 1; + } while (qstep); + + fflag = 0; + minscaler = av_clip(minscaler, 60, 255 - SCALE_MAX_DIFF); + for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { + for (g = 0; g < sce->ics.num_swb; g++) { + int prevsc = sce->sf_idx[w*16+g]; + if (dists[w*16+g] > uplims[w*16+g] && sce->sf_idx[w*16+g] > 60) { + if (find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]-1)) + sce->sf_idx[w*16+g]--; + else + sce->sf_idx[w*16+g]-=2; + } + sce->sf_idx[w*16+g] = av_clip(sce->sf_idx[w*16+g], minscaler, minscaler + SCALE_MAX_DIFF); + sce->sf_idx[w*16+g] = FFMIN(sce->sf_idx[w*16+g], 219); + if (sce->sf_idx[w*16+g] != prevsc) + fflag = 1; + sce->band_type[w*16+g] = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]); + } + } + its++; + } while (fflag && its < 10); +} + +static void search_for_ms_mips(AACEncContext *s, ChannelElement *cpe, + const float lambda) +{ + int start = 0, i, w, w2, g; + float M[128], S[128]; + float *L34 = s->scoefs, *R34 = s->scoefs + 128, *M34 = s->scoefs + 128*2, *S34 = s->scoefs + 128*3; + SingleChannelElement *sce0 = &cpe->ch[0]; + SingleChannelElement *sce1 = &cpe->ch[1]; + if (!cpe->common_window) + return; + for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) { + for (g = 0; g < sce0->ics.num_swb; g++) { + if (!cpe->ch[0].zeroes[w*16+g] && !cpe->ch[1].zeroes[w*16+g]) { + float dist1 = 0.0f, dist2 = 0.0f; + for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) { + FFPsyBand *band0 = &s->psy.ch[s->cur_channel+0].psy_bands[(w+w2)*16+g]; + FFPsyBand *band1 = &s->psy.ch[s->cur_channel+1].psy_bands[(w+w2)*16+g]; + float minthr = FFMIN(band0->threshold, band1->threshold); + float maxthr = FFMAX(band0->threshold, band1->threshold); + for (i = 0; i < sce0->ics.swb_sizes[g]; i+=4) { + M[i ] = (sce0->coeffs[start+w2*128+i ] + + sce1->coeffs[start+w2*128+i ]) * 0.5; + M[i+1] = (sce0->coeffs[start+w2*128+i+1] + + sce1->coeffs[start+w2*128+i+1]) * 0.5; + M[i+2] = (sce0->coeffs[start+w2*128+i+2] + + sce1->coeffs[start+w2*128+i+2]) * 0.5; + M[i+3] = (sce0->coeffs[start+w2*128+i+3] + + sce1->coeffs[start+w2*128+i+3]) * 0.5; + + S[i ] = M[i ] + - sce1->coeffs[start+w2*128+i ]; + S[i+1] = M[i+1] + - sce1->coeffs[start+w2*128+i+1]; + S[i+2] = M[i+2] + - sce1->coeffs[start+w2*128+i+2]; + S[i+3] = M[i+3] + - sce1->coeffs[start+w2*128+i+3]; + } + abs_pow34_v(L34, sce0->coeffs+start+w2*128, sce0->ics.swb_sizes[g]); + abs_pow34_v(R34, sce1->coeffs+start+w2*128, sce0->ics.swb_sizes[g]); + abs_pow34_v(M34, M, sce0->ics.swb_sizes[g]); + abs_pow34_v(S34, S, sce0->ics.swb_sizes[g]); + dist1 += quantize_band_cost(s, sce0->coeffs + start + w2*128, + L34, + sce0->ics.swb_sizes[g], + sce0->sf_idx[(w+w2)*16+g], + sce0->band_type[(w+w2)*16+g], + lambda / band0->threshold, INFINITY, NULL); + dist1 += quantize_band_cost(s, sce1->coeffs + start + w2*128, + R34, + sce1->ics.swb_sizes[g], + sce1->sf_idx[(w+w2)*16+g], + sce1->band_type[(w+w2)*16+g], + lambda / band1->threshold, INFINITY, NULL); + dist2 += quantize_band_cost(s, M, + M34, + sce0->ics.swb_sizes[g], + sce0->sf_idx[(w+w2)*16+g], + sce0->band_type[(w+w2)*16+g], + lambda / maxthr, INFINITY, NULL); + dist2 += quantize_band_cost(s, S, + S34, + sce1->ics.swb_sizes[g], + sce1->sf_idx[(w+w2)*16+g], + sce1->band_type[(w+w2)*16+g], + lambda / minthr, INFINITY, NULL); + } + cpe->ms_mask[w*16+g] = dist2 < dist1; + } + start += sce0->ics.swb_sizes[g]; + } + } +} +#endif /*HAVE_MIPSFPU */ + +static void codebook_trellis_rate_mips(AACEncContext *s, SingleChannelElement *sce, + int win, int group_len, const float lambda) +{ + BandCodingPath path[120][12]; + int w, swb, cb, start, size; + int i, j; + const int max_sfb = sce->ics.max_sfb; + const int run_bits = sce->ics.num_windows == 1 ? 5 : 3; + const int run_esc = (1 << run_bits) - 1; + int idx, ppos, count; + int stackrun[120], stackcb[120], stack_len; + float next_minbits = INFINITY; + int next_mincb = 0; + + abs_pow34_v(s->scoefs, sce->coeffs, 1024); + start = win*128; + for (cb = 0; cb < 12; cb++) { + path[0][cb].cost = run_bits+4; + path[0][cb].prev_idx = -1; + path[0][cb].run = 0; + } + for (swb = 0; swb < max_sfb; swb++) { + size = sce->ics.swb_sizes[swb]; + if (sce->zeroes[win*16 + swb]) { + float cost_stay_here = path[swb][0].cost; + float cost_get_here = next_minbits + run_bits + 4; + if ( run_value_bits[sce->ics.num_windows == 8][path[swb][0].run] + != run_value_bits[sce->ics.num_windows == 8][path[swb][0].run+1]) + cost_stay_here += run_bits; + if (cost_get_here < cost_stay_here) { + path[swb+1][0].prev_idx = next_mincb; + path[swb+1][0].cost = cost_get_here; + path[swb+1][0].run = 1; + } else { + path[swb+1][0].prev_idx = 0; + path[swb+1][0].cost = cost_stay_here; + path[swb+1][0].run = path[swb][0].run + 1; + } + next_minbits = path[swb+1][0].cost; + next_mincb = 0; + for (cb = 1; cb < 12; cb++) { + path[swb+1][cb].cost = 61450; + path[swb+1][cb].prev_idx = -1; + path[swb+1][cb].run = 0; + } + } else { + float minbits = next_minbits; + int mincb = next_mincb; + int startcb = sce->band_type[win*16+swb]; + next_minbits = INFINITY; + next_mincb = 0; + for (cb = 0; cb < startcb; cb++) { + path[swb+1][cb].cost = 61450; + path[swb+1][cb].prev_idx = -1; + path[swb+1][cb].run = 0; + } + for (cb = startcb; cb < 12; cb++) { + float cost_stay_here, cost_get_here; + float bits = 0.0f; + for (w = 0; w < group_len; w++) { + bits += quantize_band_cost_bits(s, sce->coeffs + start + w*128, + s->scoefs + start + w*128, size, + sce->sf_idx[(win+w)*16+swb], cb, + 0, INFINITY, NULL); + } + cost_stay_here = path[swb][cb].cost + bits; + cost_get_here = minbits + bits + run_bits + 4; + if ( run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run] + != run_value_bits[sce->ics.num_windows == 8][path[swb][cb].run+1]) + cost_stay_here += run_bits; + if (cost_get_here < cost_stay_here) { + path[swb+1][cb].prev_idx = mincb; + path[swb+1][cb].cost = cost_get_here; + path[swb+1][cb].run = 1; + } else { + path[swb+1][cb].prev_idx = cb; + path[swb+1][cb].cost = cost_stay_here; + path[swb+1][cb].run = path[swb][cb].run + 1; + } + if (path[swb+1][cb].cost < next_minbits) { + next_minbits = path[swb+1][cb].cost; + next_mincb = cb; + } + } + } + start += sce->ics.swb_sizes[swb]; + } + + stack_len = 0; + idx = 0; + for (cb = 1; cb < 12; cb++) + if (path[max_sfb][cb].cost < path[max_sfb][idx].cost) + idx = cb; + ppos = max_sfb; + while (ppos > 0) { + av_assert1(idx >= 0); + cb = idx; + stackrun[stack_len] = path[ppos][cb].run; + stackcb [stack_len] = cb; + idx = path[ppos-path[ppos][cb].run+1][cb].prev_idx; + ppos -= path[ppos][cb].run; + stack_len++; + } + + start = 0; + for (i = stack_len - 1; i >= 0; i--) { + put_bits(&s->pb, 4, stackcb[i]); + count = stackrun[i]; + memset(sce->zeroes + win*16 + start, !stackcb[i], count); + for (j = 0; j < count; j++) { + sce->band_type[win*16 + start] = stackcb[i]; + start++; + } + while (count >= run_esc) { + put_bits(&s->pb, run_bits, run_esc); + count -= run_esc; + } + put_bits(&s->pb, run_bits, count); + } +} +#endif /* HAVE_INLINE_ASM */ + +void ff_aac_coder_init_mips(AACEncContext *c) { +#if HAVE_INLINE_ASM + AACCoefficientsEncoder *e = c->coder; + int option = c->options.aac_coder; + + if (option == 2) { + e->quantize_and_encode_band = quantize_and_encode_band_mips; + e->encode_window_bands_info = codebook_trellis_rate_mips; +#if HAVE_MIPSFPU + e->search_for_quantizers = search_for_quantizers_twoloop_mips; + e->search_for_ms = search_for_ms_mips; +#endif /* HAVE_MIPSFPU */ + } +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/mips/aacdec_mips.c b/ffmpeg/libavcodec/mips/aacdec_mips.c new file mode 100644 index 0000000..e403366 --- /dev/null +++ b/ffmpeg/libavcodec/mips/aacdec_mips.c @@ -0,0 +1,831 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Darko Laus (darko@mips.com) + * Djordje Pesut (djordje@mips.com) + * Mirjana Vulin (mvulin@mips.com) + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/aacdec.c + */ + +#include "libavcodec/aac.h" +#include "aacdec_mips.h" +#include "libavcodec/aactab.h" +#include "libavcodec/sinewin.h" + +#if HAVE_INLINE_ASM +static av_always_inline int lcg_random(unsigned previous_val) +{ + union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 }; + return v.s; +} + +static void imdct_and_windowing_mips(AACContext *ac, SingleChannelElement *sce) +{ + IndividualChannelStream *ics = &sce->ics; + float *in = sce->coeffs; + float *out = sce->ret; + float *saved = sce->saved; + const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128; + float *buf = ac->buf_mdct; + int i; + + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + for (i = 0; i < 1024; i += 128) + ac->mdct_small.imdct_half(&ac->mdct_small, buf + i, in + i); + } else + ac->mdct.imdct_half(&ac->mdct, buf, in); + + /* window overlapping + * NOTE: To simplify the overlapping code, all 'meaningless' short to long + * and long to short transitions are considered to be short to short + * transitions. This leaves just two cases (long to long and short to short) + * with a little special sauce for EIGHT_SHORT_SEQUENCE. + */ + if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) && + (ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) { + ac->fdsp.vector_fmul_window( out, saved, buf, lwindow_prev, 512); + } else { + { + float *buf1 = saved; + float *buf2 = out; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + int loop_end; + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 1792 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf1), + [dst]"+r"(buf2) + : + : "memory" + ); + } + + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + { + float wi; + float wj; + int i; + float temp0, temp1, temp2, temp3; + float *dst0 = out + 448 + 0*128; + float *dst1 = dst0 + 64 + 63; + float *dst2 = saved + 63; + float *win0 = (float*)swindow; + float *win1 = win0 + 64 + 63; + float *win0_prev = (float*)swindow_prev; + float *win1_prev = win0_prev + 64 + 63; + float *src0_prev = saved + 448; + float *src1_prev = buf + 0*128 + 63; + float *src0 = buf + 0*128 + 64; + float *src1 = buf + 1*128 + 63; + + for(i = 0; i < 64; i++) + { + temp0 = src0_prev[0]; + temp1 = src1_prev[0]; + wi = *win0_prev; + wj = *win1_prev; + temp2 = src0[0]; + temp3 = src1[0]; + dst0[0] = temp0 * wj - temp1 * wi; + dst1[0] = temp0 * wi + temp1 * wj; + + wi = *win0; + wj = *win1; + + temp0 = src0[128]; + temp1 = src1[128]; + dst0[128] = temp2 * wj - temp3 * wi; + dst1[128] = temp2 * wi + temp3 * wj; + + temp2 = src0[256]; + temp3 = src1[256]; + dst0[256] = temp0 * wj - temp1 * wi; + dst1[256] = temp0 * wi + temp1 * wj; + dst0[384] = temp2 * wj - temp3 * wi; + dst1[384] = temp2 * wi + temp3 * wj; + + temp0 = src0[384]; + temp1 = src1[384]; + dst0[512] = temp0 * wj - temp1 * wi; + dst2[0] = temp0 * wi + temp1 * wj; + + src0++; + src1--; + src0_prev++; + src1_prev--; + win0++; + win1--; + win0_prev++; + win1_prev--; + dst0++; + dst1--; + dst2--; + } + } + } else { + ac->fdsp.vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64); + { + float *buf1 = buf + 64; + float *buf2 = out + 576; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + int loop_end; + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 1792 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf1), + [dst]"+r"(buf2) + : + : "memory" + ); + } + } + } + + // buffer update + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + ac->fdsp.vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64); + ac->fdsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64); + ac->fdsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64); + { + float *buf1 = buf + 7*128 + 64; + float *buf2 = saved + 448; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + int loop_end; + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 256 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf1), + [dst]"+r"(buf2) + : + : "memory" + ); + } + } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) { + float *buf1 = buf + 512; + float *buf2 = saved; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + int loop_end; + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 1792 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf1), + [dst]"+r"(buf2) + : + : "memory" + ); + { + float *buf1 = buf + 7*128 + 64; + float *buf2 = saved + 448; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + int loop_end; + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 256 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf1), + [dst]"+r"(buf2) + : + : "memory" + ); + } + } else { // LONG_STOP or ONLY_LONG + float *buf1 = buf + 512; + float *buf2 = saved; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + int loop_end; + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 2048 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf1), + [dst]"+r"(buf2) + : + : "memory" + ); + } +} + +static void apply_ltp_mips(AACContext *ac, SingleChannelElement *sce) +{ + const LongTermPrediction *ltp = &sce->ics.ltp; + const uint16_t *offsets = sce->ics.swb_offset; + int i, sfb; + int j, k; + + if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) { + float *predTime = sce->ret; + float *predFreq = ac->buf_mdct; + float *p_predTime; + int16_t num_samples = 2048; + + if (ltp->lag < 1024) + num_samples = ltp->lag + 1024; + j = (2048 - num_samples) >> 2; + k = (2048 - num_samples) & 3; + p_predTime = &predTime[num_samples]; + + for (i = 0; i < num_samples; i++) + predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef; + for (i = 0; i < j; i++) { + + /* loop unrolled 4 times */ + __asm__ volatile ( + "sw $0, 0(%[p_predTime]) \n\t" + "sw $0, 4(%[p_predTime]) \n\t" + "sw $0, 8(%[p_predTime]) \n\t" + "sw $0, 12(%[p_predTime]) \n\t" + "addiu %[p_predTime], %[p_predTime], 16 \n\t" + + : [p_predTime]"+r"(p_predTime) + : + : "memory" + ); + } + for (i = 0; i < k; i++) { + + __asm__ volatile ( + "sw $0, 0(%[p_predTime]) \n\t" + "addiu %[p_predTime], %[p_predTime], 4 \n\t" + + : [p_predTime]"+r"(p_predTime) + : + : "memory" + ); + } + + ac->windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics); + + if (sce->tns.present) + ac->apply_tns(predFreq, &sce->tns, &sce->ics, 0); + + for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++) + if (ltp->used[sfb]) + for (i = offsets[sfb]; i < offsets[sfb + 1]; i++) + sce->coeffs[i] += predFreq[i]; + } +} + +#if HAVE_MIPSFPU +static void update_ltp_mips(AACContext *ac, SingleChannelElement *sce) +{ + IndividualChannelStream *ics = &sce->ics; + float *saved = sce->saved; + float *saved_ltp = sce->coeffs; + const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024; + const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128; + int i; + int loop_end, loop_end1, loop_end2; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10, temp11; + + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) { + float *buf = saved; + float *buf0 = saved_ltp; + float *p_saved_ltp = saved_ltp + 576; + float *ptr1 = &saved_ltp[512]; + float *ptr2 = &ac->buf_mdct[1023]; + float *ptr3 = (float*)&swindow[63]; + loop_end1 = (int)(p_saved_ltp + 448); + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 2048 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [src]"+r"(buf), + [dst]"+r"(buf0) + : + : "memory" + ); + + /* loop unrolled 8 times */ + __asm__ volatile ( + "1: \n\t" + "sw $0, 0(%[p_saved_ltp]) \n\t" + "sw $0, 4(%[p_saved_ltp]) \n\t" + "sw $0, 8(%[p_saved_ltp]) \n\t" + "sw $0, 12(%[p_saved_ltp]) \n\t" + "sw $0, 16(%[p_saved_ltp]) \n\t" + "sw $0, 20(%[p_saved_ltp]) \n\t" + "sw $0, 24(%[p_saved_ltp]) \n\t" + "sw $0, 28(%[p_saved_ltp]) \n\t" + "addiu %[p_saved_ltp], %[p_saved_ltp], 32 \n\t" + "bne %[p_saved_ltp], %[loop_end1], 1b \n\t" + + : [p_saved_ltp]"+r"(p_saved_ltp) + : [loop_end1]"r"(loop_end1) + : "memory" + ); + + ac->fdsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64); + for (i = 0; i < 16; i++){ + /* loop unrolled 4 times */ + __asm__ volatile ( + "lwc1 %[temp0], 0(%[ptr2]) \n\t" + "lwc1 %[temp1], -4(%[ptr2]) \n\t" + "lwc1 %[temp2], -8(%[ptr2]) \n\t" + "lwc1 %[temp3], -12(%[ptr2]) \n\t" + "lwc1 %[temp4], 0(%[ptr3]) \n\t" + "lwc1 %[temp5], -4(%[ptr3]) \n\t" + "lwc1 %[temp6], -8(%[ptr3]) \n\t" + "lwc1 %[temp7], -12(%[ptr3]) \n\t" + "mul.s %[temp8], %[temp0], %[temp4] \n\t" + "mul.s %[temp9], %[temp1], %[temp5] \n\t" + "mul.s %[temp10], %[temp2], %[temp6] \n\t" + "mul.s %[temp11], %[temp3], %[temp7] \n\t" + "swc1 %[temp8], 0(%[ptr1]) \n\t" + "swc1 %[temp9], 4(%[ptr1]) \n\t" + "swc1 %[temp10], 8(%[ptr1]) \n\t" + "swc1 %[temp11], 12(%[ptr1]) \n\t" + "addiu %[ptr1], %[ptr1], 16 \n\t" + "addiu %[ptr2], %[ptr2], -16 \n\t" + "addiu %[ptr3], %[ptr3], -16 \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), + [temp8]"=&f"(temp8), [temp9]"=&f"(temp9), + [temp10]"=&f"(temp10), [temp11]"=&f"(temp11), + [ptr1]"+r"(ptr1), [ptr2]"+r"(ptr2), [ptr3]"+r"(ptr3) + : + : "memory" + ); + } + } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) { + float *buff0 = saved; + float *buff1 = saved_ltp; + float *ptr1 = &saved_ltp[512]; + float *ptr2 = &ac->buf_mdct[1023]; + float *ptr3 = (float*)&swindow[63]; + loop_end = (int)(saved + 448); + + /* loop unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "sw $0, 2304(%[dst]) \n\t" + "sw $0, 2308(%[dst]) \n\t" + "sw $0, 2312(%[dst]) \n\t" + "sw $0, 2316(%[dst]) \n\t" + "sw $0, 2320(%[dst]) \n\t" + "sw $0, 2324(%[dst]) \n\t" + "sw $0, 2328(%[dst]) \n\t" + "sw $0, 2332(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [src]"+r"(buff0), [dst]"+r"(buff1) + : [loop_end]"r"(loop_end) + : "memory" + ); + ac->fdsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64); + for (i = 0; i < 16; i++){ + /* loop unrolled 8 times */ + __asm__ volatile ( + "lwc1 %[temp0], 0(%[ptr2]) \n\t" + "lwc1 %[temp1], -4(%[ptr2]) \n\t" + "lwc1 %[temp2], -8(%[ptr2]) \n\t" + "lwc1 %[temp3], -12(%[ptr2]) \n\t" + "lwc1 %[temp4], 0(%[ptr3]) \n\t" + "lwc1 %[temp5], -4(%[ptr3]) \n\t" + "lwc1 %[temp6], -8(%[ptr3]) \n\t" + "lwc1 %[temp7], -12(%[ptr3]) \n\t" + "mul.s %[temp8], %[temp0], %[temp4] \n\t" + "mul.s %[temp9], %[temp1], %[temp5] \n\t" + "mul.s %[temp10], %[temp2], %[temp6] \n\t" + "mul.s %[temp11], %[temp3], %[temp7] \n\t" + "swc1 %[temp8], 0(%[ptr1]) \n\t" + "swc1 %[temp9], 4(%[ptr1]) \n\t" + "swc1 %[temp10], 8(%[ptr1]) \n\t" + "swc1 %[temp11], 12(%[ptr1]) \n\t" + "addiu %[ptr1], %[ptr1], 16 \n\t" + "addiu %[ptr2], %[ptr2], -16 \n\t" + "addiu %[ptr3], %[ptr3], -16 \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), + [temp8]"=&f"(temp8), [temp9]"=&f"(temp9), + [temp10]"=&f"(temp10), [temp11]"=&f"(temp11), + [ptr1]"+r"(ptr1), [ptr2]"+r"(ptr2), [ptr3]"+r"(ptr3) + : + : "memory" + ); + } + } else { // LONG_STOP or ONLY_LONG + float *ptr1, *ptr2, *ptr3; + ac->fdsp.vector_fmul_reverse(saved_ltp, ac->buf_mdct + 512, &lwindow[512], 512); + + ptr1 = &saved_ltp[512]; + ptr2 = &ac->buf_mdct[1023]; + ptr3 = (float*)&lwindow[511]; + + for (i = 0; i < 512; i+=4){ + /* loop unrolled 4 times */ + __asm__ volatile ( + "lwc1 %[temp0], 0(%[ptr2]) \n\t" + "lwc1 %[temp1], -4(%[ptr2]) \n\t" + "lwc1 %[temp2], -8(%[ptr2]) \n\t" + "lwc1 %[temp3], -12(%[ptr2]) \n\t" + "lwc1 %[temp4], 0(%[ptr3]) \n\t" + "lwc1 %[temp5], -4(%[ptr3]) \n\t" + "lwc1 %[temp6], -8(%[ptr3]) \n\t" + "lwc1 %[temp7], -12(%[ptr3]) \n\t" + "mul.s %[temp8], %[temp0], %[temp4] \n\t" + "mul.s %[temp9], %[temp1], %[temp5] \n\t" + "mul.s %[temp10], %[temp2], %[temp6] \n\t" + "mul.s %[temp11], %[temp3], %[temp7] \n\t" + "swc1 %[temp8], 0(%[ptr1]) \n\t" + "swc1 %[temp9], 4(%[ptr1]) \n\t" + "swc1 %[temp10], 8(%[ptr1]) \n\t" + "swc1 %[temp11], 12(%[ptr1]) \n\t" + "addiu %[ptr1], %[ptr1], 16 \n\t" + "addiu %[ptr2], %[ptr2], -16 \n\t" + "addiu %[ptr3], %[ptr3], -16 \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), + [temp8]"=&f"(temp8), [temp9]"=&f"(temp9), + [temp10]"=&f"(temp10), [temp11]"=&f"(temp11), + [ptr1]"+r"(ptr1), [ptr2]"+r"(ptr2), + [ptr3]"+r"(ptr3) + : + : "memory" + ); + } + } + + { + float *buf1 = sce->ltp_state+1024; + float *buf2 = sce->ltp_state; + float *buf3 = sce->ret; + float *buf4 = sce->ltp_state+1024; + float *buf5 = saved_ltp; + float *buf6 = sce->ltp_state+2048; + + /* loops unrolled 8 times */ + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "addiu %[loop_end], %[src], 4096 \n\t" + "addiu %[loop_end1], %[src1], 4096 \n\t" + "addiu %[loop_end2], %[src2], 4096 \n\t" + "1: \n\t" + "lw %[temp0], 0(%[src]) \n\t" + "lw %[temp1], 4(%[src]) \n\t" + "lw %[temp2], 8(%[src]) \n\t" + "lw %[temp3], 12(%[src]) \n\t" + "lw %[temp4], 16(%[src]) \n\t" + "lw %[temp5], 20(%[src]) \n\t" + "lw %[temp6], 24(%[src]) \n\t" + "lw %[temp7], 28(%[src]) \n\t" + "addiu %[src], %[src], 32 \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + "bne %[src], %[loop_end], 1b \n\t" + " addiu %[dst], %[dst], 32 \n\t" + "2: \n\t" + "lw %[temp0], 0(%[src1]) \n\t" + "lw %[temp1], 4(%[src1]) \n\t" + "lw %[temp2], 8(%[src1]) \n\t" + "lw %[temp3], 12(%[src1]) \n\t" + "lw %[temp4], 16(%[src1]) \n\t" + "lw %[temp5], 20(%[src1]) \n\t" + "lw %[temp6], 24(%[src1]) \n\t" + "lw %[temp7], 28(%[src1]) \n\t" + "addiu %[src1], %[src1], 32 \n\t" + "sw %[temp0], 0(%[dst1]) \n\t" + "sw %[temp1], 4(%[dst1]) \n\t" + "sw %[temp2], 8(%[dst1]) \n\t" + "sw %[temp3], 12(%[dst1]) \n\t" + "sw %[temp4], 16(%[dst1]) \n\t" + "sw %[temp5], 20(%[dst1]) \n\t" + "sw %[temp6], 24(%[dst1]) \n\t" + "sw %[temp7], 28(%[dst1]) \n\t" + "bne %[src1], %[loop_end1], 2b \n\t" + " addiu %[dst1], %[dst1], 32 \n\t" + "3: \n\t" + "lw %[temp0], 0(%[src2]) \n\t" + "lw %[temp1], 4(%[src2]) \n\t" + "lw %[temp2], 8(%[src2]) \n\t" + "lw %[temp3], 12(%[src2]) \n\t" + "lw %[temp4], 16(%[src2]) \n\t" + "lw %[temp5], 20(%[src2]) \n\t" + "lw %[temp6], 24(%[src2]) \n\t" + "lw %[temp7], 28(%[src2]) \n\t" + "addiu %[src2], %[src2], 32 \n\t" + "sw %[temp0], 0(%[dst2]) \n\t" + "sw %[temp1], 4(%[dst2]) \n\t" + "sw %[temp2], 8(%[dst2]) \n\t" + "sw %[temp3], 12(%[dst2]) \n\t" + "sw %[temp4], 16(%[dst2]) \n\t" + "sw %[temp5], 20(%[dst2]) \n\t" + "sw %[temp6], 24(%[dst2]) \n\t" + "sw %[temp7], 28(%[dst2]) \n\t" + "bne %[src2], %[loop_end2], 3b \n\t" + " addiu %[dst2], %[dst2], 32 \n\t" + ".set pop \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [loop_end]"=&r"(loop_end), [loop_end1]"=&r"(loop_end1), + [loop_end2]"=&r"(loop_end2), [src]"+r"(buf1), + [dst]"+r"(buf2), [src1]"+r"(buf3), [dst1]"+r"(buf4), + [src2]"+r"(buf5), [dst2]"+r"(buf6) + : + : "memory" + ); + } +} +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ + +void ff_aacdec_init_mips(AACContext *c) +{ +#if HAVE_INLINE_ASM + c->imdct_and_windowing = imdct_and_windowing_mips; + c->apply_ltp = apply_ltp_mips; +#if HAVE_MIPSFPU + c->update_ltp = update_ltp_mips; +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/mips/aacdec_mips.h b/ffmpeg/libavcodec/mips/aacdec_mips.h new file mode 100644 index 0000000..9ba3079 --- /dev/null +++ b/ffmpeg/libavcodec/mips/aacdec_mips.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Darko Laus (darko@mips.com) + * Djordje Pesut (djordje@mips.com) + * Mirjana Vulin (mvulin@mips.com) + * + * AAC Spectral Band Replication decoding functions optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/aacdec.c + */ + +#ifndef AVCODEC_MIPS_AACDEC_FLOAT_H +#define AVCODEC_MIPS_AACDEC_FLOAT_H + +#include "libavcodec/aac.h" + +#if HAVE_INLINE_ASM && HAVE_MIPSFPU +static inline float *VMUL2_mips(float *dst, const float *v, unsigned idx, + const float *scale) +{ + float temp0, temp1, temp2; + int temp3, temp4; + float *ret; + + __asm__ volatile( + "andi %[temp3], %[idx], 15 \n\t" + "ext %[temp4], %[idx], 4, 4 \n\t" + "sll %[temp3], %[temp3], 2 \n\t" + "sll %[temp4], %[temp4], 2 \n\t" + "lwc1 %[temp2], 0(%[scale]) \n\t" + "lwxc1 %[temp0], %[temp3](%[v]) \n\t" + "lwxc1 %[temp1], %[temp4](%[v]) \n\t" + "mul.s %[temp0], %[temp0], %[temp2] \n\t" + "mul.s %[temp1], %[temp1], %[temp2] \n\t" + "addiu %[ret], %[dst], 8 \n\t" + "swc1 %[temp0], 0(%[dst]) \n\t" + "swc1 %[temp1], 4(%[dst]) \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [ret]"=&r"(ret) + : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v), + [dst]"r"(dst) + : "memory" + ); + return ret; +} + +static inline float *VMUL4_mips(float *dst, const float *v, unsigned idx, + const float *scale) +{ + int temp0, temp1, temp2, temp3; + float temp4, temp5, temp6, temp7, temp8; + float *ret; + + __asm__ volatile( + "andi %[temp0], %[idx], 3 \n\t" + "ext %[temp1], %[idx], 2, 2 \n\t" + "ext %[temp2], %[idx], 4, 2 \n\t" + "ext %[temp3], %[idx], 6, 2 \n\t" + "sll %[temp0], %[temp0], 2 \n\t" + "sll %[temp1], %[temp1], 2 \n\t" + "sll %[temp2], %[temp2], 2 \n\t" + "sll %[temp3], %[temp3], 2 \n\t" + "lwc1 %[temp4], 0(%[scale]) \n\t" + "lwxc1 %[temp5], %[temp0](%[v]) \n\t" + "lwxc1 %[temp6], %[temp1](%[v]) \n\t" + "lwxc1 %[temp7], %[temp2](%[v]) \n\t" + "lwxc1 %[temp8], %[temp3](%[v]) \n\t" + "mul.s %[temp5], %[temp5], %[temp4] \n\t" + "mul.s %[temp6], %[temp6], %[temp4] \n\t" + "mul.s %[temp7], %[temp7], %[temp4] \n\t" + "mul.s %[temp8], %[temp8], %[temp4] \n\t" + "addiu %[ret], %[dst], 16 \n\t" + "swc1 %[temp5], 0(%[dst]) \n\t" + "swc1 %[temp6], 4(%[dst]) \n\t" + "swc1 %[temp7], 8(%[dst]) \n\t" + "swc1 %[temp8], 12(%[dst]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), + [temp8]"=&f"(temp8), [ret]"=&r"(ret) + : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v), + [dst]"r"(dst) + : "memory" + ); + return ret; +} + +static inline float *VMUL2S_mips(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + int temp0, temp1, temp2, temp3, temp4, temp5; + float temp6, temp7, temp8, temp9; + float *ret; + + __asm__ volatile( + "andi %[temp0], %[idx], 15 \n\t" + "ext %[temp1], %[idx], 4, 4 \n\t" + "lw %[temp4], 0(%[scale]) \n\t" + "srl %[temp2], %[sign], 1 \n\t" + "sll %[temp3], %[sign], 31 \n\t" + "sll %[temp2], %[temp2], 31 \n\t" + "sll %[temp0], %[temp0], 2 \n\t" + "sll %[temp1], %[temp1], 2 \n\t" + "lwxc1 %[temp8], %[temp0](%[v]) \n\t" + "lwxc1 %[temp9], %[temp1](%[v]) \n\t" + "xor %[temp5], %[temp4], %[temp2] \n\t" + "xor %[temp4], %[temp4], %[temp3] \n\t" + "mtc1 %[temp5], %[temp6] \n\t" + "mtc1 %[temp4], %[temp7] \n\t" + "mul.s %[temp8], %[temp8], %[temp6] \n\t" + "mul.s %[temp9], %[temp9], %[temp7] \n\t" + "addiu %[ret], %[dst], 8 \n\t" + "swc1 %[temp8], 0(%[dst]) \n\t" + "swc1 %[temp9], 4(%[dst]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), + [temp8]"=&f"(temp8), [temp9]"=&f"(temp9), + [ret]"=&r"(ret) + : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v), + [dst]"r"(dst), [sign]"r"(sign) + : "memory" + ); + return ret; +} + +static inline float *VMUL4S_mips(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + int temp0, temp1, temp2, temp3, temp4; + float temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17; + float *ret; + unsigned int mask = 1U << 31; + + __asm__ volatile( + "lw %[temp0], 0(%[scale]) \n\t" + "and %[temp1], %[idx], 3 \n\t" + "ext %[temp2], %[idx], 2, 2 \n\t" + "ext %[temp3], %[idx], 4, 2 \n\t" + "ext %[temp4], %[idx], 6, 2 \n\t" + "sll %[temp1], %[temp1], 2 \n\t" + "sll %[temp2], %[temp2], 2 \n\t" + "sll %[temp3], %[temp3], 2 \n\t" + "sll %[temp4], %[temp4], 2 \n\t" + "lwxc1 %[temp10], %[temp1](%[v]) \n\t" + "lwxc1 %[temp11], %[temp2](%[v]) \n\t" + "lwxc1 %[temp12], %[temp3](%[v]) \n\t" + "lwxc1 %[temp13], %[temp4](%[v]) \n\t" + "and %[temp1], %[sign], %[mask] \n\t" + "ext %[temp2], %[idx], 12, 1 \n\t" + "ext %[temp3], %[idx], 13, 1 \n\t" + "ext %[temp4], %[idx], 14, 1 \n\t" + "sllv %[sign], %[sign], %[temp2] \n\t" + "xor %[temp1], %[temp0], %[temp1] \n\t" + "and %[temp2], %[sign], %[mask] \n\t" + "mtc1 %[temp1], %[temp14] \n\t" + "xor %[temp2], %[temp0], %[temp2] \n\t" + "sllv %[sign], %[sign], %[temp3] \n\t" + "mtc1 %[temp2], %[temp15] \n\t" + "and %[temp3], %[sign], %[mask] \n\t" + "sllv %[sign], %[sign], %[temp4] \n\t" + "xor %[temp3], %[temp0], %[temp3] \n\t" + "and %[temp4], %[sign], %[mask] \n\t" + "mtc1 %[temp3], %[temp16] \n\t" + "xor %[temp4], %[temp0], %[temp4] \n\t" + "mtc1 %[temp4], %[temp17] \n\t" + "mul.s %[temp10], %[temp10], %[temp14] \n\t" + "mul.s %[temp11], %[temp11], %[temp15] \n\t" + "mul.s %[temp12], %[temp12], %[temp16] \n\t" + "mul.s %[temp13], %[temp13], %[temp17] \n\t" + "addiu %[ret], %[dst], 16 \n\t" + "swc1 %[temp10], 0(%[dst]) \n\t" + "swc1 %[temp11], 4(%[dst]) \n\t" + "swc1 %[temp12], 8(%[dst]) \n\t" + "swc1 %[temp13], 12(%[dst]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp10]"=&f"(temp10), + [temp11]"=&f"(temp11), [temp12]"=&f"(temp12), + [temp13]"=&f"(temp13), [temp14]"=&f"(temp14), + [temp15]"=&f"(temp15), [temp16]"=&f"(temp16), + [temp17]"=&f"(temp17), [ret]"=&r"(ret), + [sign]"+r"(sign) + : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v), + [dst]"r"(dst), [mask]"r"(mask) + : "memory" + ); + return ret; +} + +#define VMUL2 VMUL2_mips +#define VMUL4 VMUL4_mips +#define VMUL2S VMUL2S_mips +#define VMUL4S VMUL4S_mips +#endif /* HAVE_INLINE_ASM && HAVE_MIPSFPU */ + +#endif /* AVCODEC_MIPS_AACDEC_FLOAT_H */ diff --git a/ffmpeg/libavcodec/mips/aacpsdsp_mips.c b/ffmpeg/libavcodec/mips/aacpsdsp_mips.c new file mode 100644 index 0000000..4730a7f --- /dev/null +++ b/ffmpeg/libavcodec/mips/aacpsdsp_mips.c @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Darko Laus (darko@mips.com) + * Djordje Pesut (djordje@mips.com) + * Mirjana Vulin (mvulin@mips.com) + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/aacpsdsp.c + */ + +#include "config.h" +#include "libavcodec/aacpsdsp.h" + +#if HAVE_INLINE_ASM +static void ps_hybrid_analysis_ileave_mips(float (*out)[32][2], float L[2][38][64], + int i, int len) +{ + int temp0, temp1, temp2, temp3; + int temp4, temp5, temp6, temp7; + float *out1=&out[i][0][0]; + float *L1=&L[0][0][i]; + float *j=out1+ len*2; + + for (; i < 64; i++) { + + /* loop unrolled 8 times */ + __asm__ volatile ( + "1: \n\t" + "lw %[temp0], 0(%[L1]) \n\t" + "lw %[temp1], 9728(%[L1]) \n\t" + "lw %[temp2], 256(%[L1]) \n\t" + "lw %[temp3], 9984(%[L1]) \n\t" + "lw %[temp4], 512(%[L1]) \n\t" + "lw %[temp5], 10240(%[L1]) \n\t" + "lw %[temp6], 768(%[L1]) \n\t" + "lw %[temp7], 10496(%[L1]) \n\t" + "sw %[temp0], 0(%[out1]) \n\t" + "sw %[temp1], 4(%[out1]) \n\t" + "sw %[temp2], 8(%[out1]) \n\t" + "sw %[temp3], 12(%[out1]) \n\t" + "sw %[temp4], 16(%[out1]) \n\t" + "sw %[temp5], 20(%[out1]) \n\t" + "sw %[temp6], 24(%[out1]) \n\t" + "sw %[temp7], 28(%[out1]) \n\t" + "addiu %[out1], %[out1], 32 \n\t" + "addiu %[L1], %[L1], 1024 \n\t" + "bne %[out1], %[j], 1b \n\t" + + : [out1]"+r"(out1), [L1]"+r"(L1), [j]"+r"(j), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) + : [len]"r"(len) + : "memory" + ); + out1-=(len<<1)-64; + L1-=(len<<6)-1; + j+=len*2; + } +} + +static void ps_hybrid_synthesis_deint_mips(float out[2][38][64], + float (*in)[32][2], + int i, int len) +{ + int n; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + float *out1 = (float*)out + i; + float *out2 = (float*)out + 2432 + i; + float *in1 = (float*)in + 64 * i; + float *in2 = (float*)in + 64 * i + 1; + + for (; i < 64; i++) { + for (n = 0; n < 7; n++) { + + /* loop unrolled 8 times */ + __asm__ volatile ( + "lw %[temp0], 0(%[in1]) \n\t" + "lw %[temp1], 0(%[in2]) \n\t" + "lw %[temp2], 8(%[in1]) \n\t" + "lw %[temp3], 8(%[in2]) \n\t" + "lw %[temp4], 16(%[in1]) \n\t" + "lw %[temp5], 16(%[in2]) \n\t" + "lw %[temp6], 24(%[in1]) \n\t" + "lw %[temp7], 24(%[in2]) \n\t" + "addiu %[out1], %[out1], 1024 \n\t" + "addiu %[out2], %[out2], 1024 \n\t" + "addiu %[in1], %[in1], 32 \n\t" + "addiu %[in2], %[in2], 32 \n\t" + "sw %[temp0], -1024(%[out1]) \n\t" + "sw %[temp1], -1024(%[out2]) \n\t" + "sw %[temp2], -768(%[out1]) \n\t" + "sw %[temp3], -768(%[out2]) \n\t" + "sw %[temp4], -512(%[out1]) \n\t" + "sw %[temp5], -512(%[out2]) \n\t" + "sw %[temp6], -256(%[out1]) \n\t" + "sw %[temp7], -256(%[out2]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [out1]"+r"(out1), [out2]"+r"(out2), + [in1]"+r"(in1), [in2]"+r"(in2) + : + : "memory" + ); + } + /* loop unrolled 8 times */ + __asm__ volatile ( + "lw %[temp0], 0(%[in1]) \n\t" + "lw %[temp1], 0(%[in2]) \n\t" + "lw %[temp2], 8(%[in1]) \n\t" + "lw %[temp3], 8(%[in2]) \n\t" + "lw %[temp4], 16(%[in1]) \n\t" + "lw %[temp5], 16(%[in2]) \n\t" + "lw %[temp6], 24(%[in1]) \n\t" + "lw %[temp7], 24(%[in2]) \n\t" + "addiu %[out1], %[out1], -7164 \n\t" + "addiu %[out2], %[out2], -7164 \n\t" + "addiu %[in1], %[in1], 32 \n\t" + "addiu %[in2], %[in2], 32 \n\t" + "sw %[temp0], 7164(%[out1]) \n\t" + "sw %[temp1], 7164(%[out2]) \n\t" + "sw %[temp2], 7420(%[out1]) \n\t" + "sw %[temp3], 7420(%[out2]) \n\t" + "sw %[temp4], 7676(%[out1]) \n\t" + "sw %[temp5], 7676(%[out2]) \n\t" + "sw %[temp6], 7932(%[out1]) \n\t" + "sw %[temp7], 7932(%[out2]) \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [out1]"+r"(out1), [out2]"+r"(out2), + [in1]"+r"(in1), [in2]"+r"(in2) + : + : "memory" + ); + } +} + +#if HAVE_MIPSFPU +static void ps_add_squares_mips(float *dst, const float (*src)[2], int n) +{ + int i; + float temp0, temp1, temp2, temp3, temp4, temp5; + float temp6, temp7, temp8, temp9, temp10, temp11; + float *src0 = (float*)&src[0][0]; + float *dst0 = &dst[0]; + + for (i = 0; i < 8; i++) { + /* loop unrolled 4 times */ + __asm__ volatile ( + "lwc1 %[temp0], 0(%[src0]) \n\t" + "lwc1 %[temp1], 4(%[src0]) \n\t" + "lwc1 %[temp2], 8(%[src0]) \n\t" + "lwc1 %[temp3], 12(%[src0]) \n\t" + "lwc1 %[temp4], 16(%[src0]) \n\t" + "lwc1 %[temp5], 20(%[src0]) \n\t" + "lwc1 %[temp6], 24(%[src0]) \n\t" + "lwc1 %[temp7], 28(%[src0]) \n\t" + "lwc1 %[temp8], 0(%[dst0]) \n\t" + "lwc1 %[temp9], 4(%[dst0]) \n\t" + "lwc1 %[temp10], 8(%[dst0]) \n\t" + "lwc1 %[temp11], 12(%[dst0]) \n\t" + "mul.s %[temp1], %[temp1], %[temp1] \n\t" + "mul.s %[temp3], %[temp3], %[temp3] \n\t" + "mul.s %[temp5], %[temp5], %[temp5] \n\t" + "mul.s %[temp7], %[temp7], %[temp7] \n\t" + "madd.s %[temp0], %[temp1], %[temp0], %[temp0] \n\t" + "madd.s %[temp2], %[temp3], %[temp2], %[temp2] \n\t" + "madd.s %[temp4], %[temp5], %[temp4], %[temp4] \n\t" + "madd.s %[temp6], %[temp7], %[temp6], %[temp6] \n\t" + "add.s %[temp0], %[temp8], %[temp0] \n\t" + "add.s %[temp2], %[temp9], %[temp2] \n\t" + "add.s %[temp4], %[temp10], %[temp4] \n\t" + "add.s %[temp6], %[temp11], %[temp6] \n\t" + "swc1 %[temp0], 0(%[dst0]) \n\t" + "swc1 %[temp2], 4(%[dst0]) \n\t" + "swc1 %[temp4], 8(%[dst0]) \n\t" + "swc1 %[temp6], 12(%[dst0]) \n\t" + "addiu %[dst0], %[dst0], 16 \n\t" + "addiu %[src0], %[src0], 32 \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [dst0]"+r"(dst0), [src0]"+r"(src0), + [temp10]"=&f"(temp10), [temp11]"=&f"(temp11) + : + : "memory" + ); + } +} + +static void ps_mul_pair_single_mips(float (*dst)[2], float (*src0)[2], float *src1, + int n) +{ + float temp0, temp1, temp2; + float *p_d, *p_s0, *p_s1, *end; + p_d = &dst[0][0]; + p_s0 = &src0[0][0]; + p_s1 = &src1[0]; + end = p_s1 + n; + + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "lwc1 %[temp2], 0(%[p_s1]) \n\t" + "lwc1 %[temp0], 0(%[p_s0]) \n\t" + "lwc1 %[temp1], 4(%[p_s0]) \n\t" + "addiu %[p_d], %[p_d], 8 \n\t" + "mul.s %[temp0], %[temp0], %[temp2] \n\t" + "mul.s %[temp1], %[temp1], %[temp2] \n\t" + "addiu %[p_s0], %[p_s0], 8 \n\t" + "swc1 %[temp0], -8(%[p_d]) \n\t" + "swc1 %[temp1], -4(%[p_d]) \n\t" + "bne %[p_s1], %[end], 1b \n\t" + " addiu %[p_s1], %[p_s1], 4 \n\t" + ".set pop \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [p_d]"+r"(p_d), + [p_s0]"+r"(p_s0), [p_s1]"+r"(p_s1) + : [end]"r"(end) + : "memory" + ); +} + +static void ps_decorrelate_mips(float (*out)[2], float (*delay)[2], + float (*ap_delay)[PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2], + const float phi_fract[2], float (*Q_fract)[2], + const float *transient_gain, + float g_decay_slope, + int len) +{ + float *p_delay = &delay[0][0]; + float *p_out = &out[0][0]; + float *p_ap_delay = &ap_delay[0][0][0]; + float *p_t_gain = (float*)transient_gain; + float *p_Q_fract = &Q_fract[0][0]; + float ag0, ag1, ag2; + float phi_fract0 = phi_fract[0]; + float phi_fract1 = phi_fract[1]; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; + + len = (int)((int*)p_delay + (len << 1)); + + /* merged 2 loops */ + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + "li.s %[ag0], 0.65143905753106 \n\t" + "li.s %[ag1], 0.56471812200776 \n\t" + "li.s %[ag2], 0.48954165955695 \n\t" + "mul.s %[ag0], %[ag0], %[g_decay_slope] \n\t" + "mul.s %[ag1], %[ag1], %[g_decay_slope] \n\t" + "mul.s %[ag2], %[ag2], %[g_decay_slope] \n\t" + "1: \n\t" + "lwc1 %[temp0], 0(%[p_delay]) \n\t" + "lwc1 %[temp1], 4(%[p_delay]) \n\t" + "lwc1 %[temp4], 16(%[p_ap_delay]) \n\t" + "lwc1 %[temp5], 20(%[p_ap_delay]) \n\t" + "mul.s %[temp3], %[temp0], %[phi_fract1] \n\t" + "lwc1 %[temp6], 0(%[p_Q_fract]) \n\t" + "mul.s %[temp2], %[temp1], %[phi_fract1] \n\t" + "lwc1 %[temp7], 4(%[p_Q_fract]) \n\t" + "madd.s %[temp3], %[temp3], %[temp1], %[phi_fract0] \n\t" + "msub.s %[temp2], %[temp2], %[temp0], %[phi_fract0] \n\t" + "mul.s %[temp8], %[temp5], %[temp7] \n\t" + "mul.s %[temp9], %[temp4], %[temp7] \n\t" + "lwc1 %[temp7], 12(%[p_Q_fract]) \n\t" + "mul.s %[temp0], %[ag0], %[temp2] \n\t" + "mul.s %[temp1], %[ag0], %[temp3] \n\t" + "msub.s %[temp8], %[temp8], %[temp4], %[temp6] \n\t" + "lwc1 %[temp4], 304(%[p_ap_delay]) \n\t" + "madd.s %[temp9], %[temp9], %[temp5], %[temp6] \n\t" + "lwc1 %[temp5], 308(%[p_ap_delay]) \n\t" + "sub.s %[temp0], %[temp8], %[temp0] \n\t" + "sub.s %[temp1], %[temp9], %[temp1] \n\t" + "madd.s %[temp2], %[temp2], %[ag0], %[temp0] \n\t" + "lwc1 %[temp6], 8(%[p_Q_fract]) \n\t" + "madd.s %[temp3], %[temp3], %[ag0], %[temp1] \n\t" + "mul.s %[temp8], %[temp5], %[temp7] \n\t" + "mul.s %[temp9], %[temp4], %[temp7] \n\t" + "lwc1 %[temp7], 20(%[p_Q_fract]) \n\t" + "msub.s %[temp8], %[temp8], %[temp4], %[temp6] \n\t" + "swc1 %[temp2], 40(%[p_ap_delay]) \n\t" + "mul.s %[temp2], %[ag1], %[temp0] \n\t" + "swc1 %[temp3], 44(%[p_ap_delay]) \n\t" + "mul.s %[temp3], %[ag1], %[temp1] \n\t" + "lwc1 %[temp4], 592(%[p_ap_delay]) \n\t" + "madd.s %[temp9], %[temp9], %[temp5], %[temp6] \n\t" + "lwc1 %[temp5], 596(%[p_ap_delay]) \n\t" + "sub.s %[temp2], %[temp8], %[temp2] \n\t" + "sub.s %[temp3], %[temp9], %[temp3] \n\t" + "lwc1 %[temp6], 16(%[p_Q_fract]) \n\t" + "madd.s %[temp0], %[temp0], %[ag1], %[temp2] \n\t" + "madd.s %[temp1], %[temp1], %[ag1], %[temp3] \n\t" + "mul.s %[temp8], %[temp5], %[temp7] \n\t" + "mul.s %[temp9], %[temp4], %[temp7] \n\t" + "msub.s %[temp8], %[temp8], %[temp4], %[temp6] \n\t" + "madd.s %[temp9], %[temp9], %[temp5], %[temp6] \n\t" + "swc1 %[temp0], 336(%[p_ap_delay]) \n\t" + "mul.s %[temp0], %[ag2], %[temp2] \n\t" + "swc1 %[temp1], 340(%[p_ap_delay]) \n\t" + "mul.s %[temp1], %[ag2], %[temp3] \n\t" + "lwc1 %[temp4], 0(%[p_t_gain]) \n\t" + "sub.s %[temp0], %[temp8], %[temp0] \n\t" + "addiu %[p_ap_delay], %[p_ap_delay], 8 \n\t" + "sub.s %[temp1], %[temp9], %[temp1] \n\t" + "addiu %[p_t_gain], %[p_t_gain], 4 \n\t" + "madd.s %[temp2], %[temp2], %[ag2], %[temp0] \n\t" + "addiu %[p_delay], %[p_delay], 8 \n\t" + "madd.s %[temp3], %[temp3], %[ag2], %[temp1] \n\t" + "addiu %[p_out], %[p_out], 8 \n\t" + "mul.s %[temp5], %[temp4], %[temp0] \n\t" + "mul.s %[temp6], %[temp4], %[temp1] \n\t" + "swc1 %[temp2], 624(%[p_ap_delay]) \n\t" + "swc1 %[temp3], 628(%[p_ap_delay]) \n\t" + "swc1 %[temp5], -8(%[p_out]) \n\t" + "swc1 %[temp6], -4(%[p_out]) \n\t" + "bne %[p_delay], %[len], 1b \n\t" + " swc1 %[temp6], -4(%[p_out]) \n\t" + ".set pop \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [p_delay]"+r"(p_delay), [p_ap_delay]"+r"(p_ap_delay), + [p_Q_fract]"+r"(p_Q_fract), [p_t_gain]"+r"(p_t_gain), [p_out]"+r"(p_out), + [ag0]"=&f"(ag0), [ag1]"=&f"(ag1), [ag2]"=&f"(ag2) + : [phi_fract0]"f"(phi_fract0), [phi_fract1]"f"(phi_fract1), + [len]"r"(len), [g_decay_slope]"f"(g_decay_slope) + : "memory" + ); +} + +static void ps_stereo_interpolate_mips(float (*l)[2], float (*r)[2], + float h[2][4], float h_step[2][4], + int len) +{ + float h0 = h[0][0]; + float h1 = h[0][1]; + float h2 = h[0][2]; + float h3 = h[0][3]; + float hs0 = h_step[0][0]; + float hs1 = h_step[0][1]; + float hs2 = h_step[0][2]; + float hs3 = h_step[0][3]; + float temp0, temp1, temp2, temp3; + float l_re, l_im, r_re, r_im; + + len = (int)((int*)l + (len << 1)); + + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "add.s %[h0], %[h0], %[hs0] \n\t" + "lwc1 %[l_re], 0(%[l]) \n\t" + "add.s %[h1], %[h1], %[hs1] \n\t" + "lwc1 %[r_re], 0(%[r]) \n\t" + "add.s %[h2], %[h2], %[hs2] \n\t" + "lwc1 %[l_im], 4(%[l]) \n\t" + "add.s %[h3], %[h3], %[hs3] \n\t" + "lwc1 %[r_im], 4(%[r]) \n\t" + "mul.s %[temp0], %[h0], %[l_re] \n\t" + "addiu %[l], %[l], 8 \n\t" + "mul.s %[temp2], %[h1], %[l_re] \n\t" + "addiu %[r], %[r], 8 \n\t" + "madd.s %[temp0], %[temp0], %[h2], %[r_re] \n\t" + "madd.s %[temp2], %[temp2], %[h3], %[r_re] \n\t" + "mul.s %[temp1], %[h0], %[l_im] \n\t" + "mul.s %[temp3], %[h1], %[l_im] \n\t" + "madd.s %[temp1], %[temp1], %[h2], %[r_im] \n\t" + "madd.s %[temp3], %[temp3], %[h3], %[r_im] \n\t" + "swc1 %[temp0], -8(%[l]) \n\t" + "swc1 %[temp2], -8(%[r]) \n\t" + "swc1 %[temp1], -4(%[l]) \n\t" + "bne %[l], %[len], 1b \n\t" + " swc1 %[temp3], -4(%[r]) \n\t" + ".set pop \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [h0]"+f"(h0), [h1]"+f"(h1), [h2]"+f"(h2), + [h3]"+f"(h3), [l]"+r"(l), [r]"+r"(r), + [l_re]"=&f"(l_re), [l_im]"=&f"(l_im), + [r_re]"=&f"(r_re), [r_im]"=&f"(r_im) + : [hs0]"f"(hs0), [hs1]"f"(hs1), [hs2]"f"(hs2), + [hs3]"f"(hs3), [len]"r"(len) + : "memory" + ); +} +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ + +void ff_psdsp_init_mips(PSDSPContext *s) +{ +#if HAVE_INLINE_ASM + s->hybrid_analysis_ileave = ps_hybrid_analysis_ileave_mips; + s->hybrid_synthesis_deint = ps_hybrid_synthesis_deint_mips; +#if HAVE_MIPSFPU + s->add_squares = ps_add_squares_mips; + s->mul_pair_single = ps_mul_pair_single_mips; + s->decorrelate = ps_decorrelate_mips; + s->stereo_interpolate[0] = ps_stereo_interpolate_mips; +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/mips/aacsbr_mips.c b/ffmpeg/libavcodec/mips/aacsbr_mips.c new file mode 100644 index 0000000..53a5fd0 --- /dev/null +++ b/ffmpeg/libavcodec/mips/aacsbr_mips.c @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Djordje Pesut (djordje@mips.com) + * Mirjana Vulin (mvulin@mips.com) + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/aacsbr.c + */ + +#include "libavcodec/aac.h" +#include "libavcodec/aacsbr.h" + +#define ENVELOPE_ADJUSTMENT_OFFSET 2 + +#if HAVE_INLINE_ASM +static int sbr_lf_gen_mips(AACContext *ac, SpectralBandReplication *sbr, + float X_low[32][40][2], const float W[2][32][32][2], + int buf_idx) +{ + int i, k; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + float *p_x_low = &X_low[0][8][0]; + float *p_w = (float*)&W[buf_idx][0][0][0]; + float *p_x1_low = &X_low[0][0][0]; + float *p_w1 = (float*)&W[1-buf_idx][24][0][0]; + + float *loop_end=p_x1_low + 2560; + + /* loop unrolled 8 times */ + __asm__ volatile ( + "1: \n\t" + "sw $0, 0(%[p_x1_low]) \n\t" + "sw $0, 4(%[p_x1_low]) \n\t" + "sw $0, 8(%[p_x1_low]) \n\t" + "sw $0, 12(%[p_x1_low]) \n\t" + "sw $0, 16(%[p_x1_low]) \n\t" + "sw $0, 20(%[p_x1_low]) \n\t" + "sw $0, 24(%[p_x1_low]) \n\t" + "sw $0, 28(%[p_x1_low]) \n\t" + "addiu %[p_x1_low], %[p_x1_low], 32 \n\t" + "bne %[p_x1_low], %[loop_end], 1b \n\t" + "addiu %[p_x1_low], %[p_x1_low], -10240 \n\t" + + : [p_x1_low]"+r"(p_x1_low) + : [loop_end]"r"(loop_end) + : "memory" + ); + + for (k = 0; k < sbr->kx[1]; k++) { + for (i = 0; i < 32; i+=4) { + /* loop unrolled 4 times */ + __asm__ volatile ( + "lw %[temp0], 0(%[p_w]) \n\t" + "lw %[temp1], 4(%[p_w]) \n\t" + "lw %[temp2], 256(%[p_w]) \n\t" + "lw %[temp3], 260(%[p_w]) \n\t" + "lw %[temp4], 512(%[p_w]) \n\t" + "lw %[temp5], 516(%[p_w]) \n\t" + "lw %[temp6], 768(%[p_w]) \n\t" + "lw %[temp7], 772(%[p_w]) \n\t" + "sw %[temp0], 0(%[p_x_low]) \n\t" + "sw %[temp1], 4(%[p_x_low]) \n\t" + "sw %[temp2], 8(%[p_x_low]) \n\t" + "sw %[temp3], 12(%[p_x_low]) \n\t" + "sw %[temp4], 16(%[p_x_low]) \n\t" + "sw %[temp5], 20(%[p_x_low]) \n\t" + "sw %[temp6], 24(%[p_x_low]) \n\t" + "sw %[temp7], 28(%[p_x_low]) \n\t" + "addiu %[p_x_low], %[p_x_low], 32 \n\t" + "addiu %[p_w], %[p_w], 1024 \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [p_w]"+r"(p_w), [p_x_low]"+r"(p_x_low) + : + : "memory" + ); + } + p_x_low += 16; + p_w -= 2046; + } + + for (k = 0; k < sbr->kx[0]; k++) { + for (i = 0; i < 2; i++) { + + /* loop unrolled 4 times */ + __asm__ volatile ( + "lw %[temp0], 0(%[p_w1]) \n\t" + "lw %[temp1], 4(%[p_w1]) \n\t" + "lw %[temp2], 256(%[p_w1]) \n\t" + "lw %[temp3], 260(%[p_w1]) \n\t" + "lw %[temp4], 512(%[p_w1]) \n\t" + "lw %[temp5], 516(%[p_w1]) \n\t" + "lw %[temp6], 768(%[p_w1]) \n\t" + "lw %[temp7], 772(%[p_w1]) \n\t" + "sw %[temp0], 0(%[p_x1_low]) \n\t" + "sw %[temp1], 4(%[p_x1_low]) \n\t" + "sw %[temp2], 8(%[p_x1_low]) \n\t" + "sw %[temp3], 12(%[p_x1_low]) \n\t" + "sw %[temp4], 16(%[p_x1_low]) \n\t" + "sw %[temp5], 20(%[p_x1_low]) \n\t" + "sw %[temp6], 24(%[p_x1_low]) \n\t" + "sw %[temp7], 28(%[p_x1_low]) \n\t" + "addiu %[p_x1_low], %[p_x1_low], 32 \n\t" + "addiu %[p_w1], %[p_w1], 1024 \n\t" + + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7), + [p_w1]"+r"(p_w1), [p_x1_low]"+r"(p_x1_low) + : + : "memory" + ); + } + p_x1_low += 64; + p_w1 -= 510; + } + return 0; +} + +static int sbr_x_gen_mips(SpectralBandReplication *sbr, float X[2][38][64], + const float Y0[38][64][2], const float Y1[38][64][2], + const float X_low[32][40][2], int ch) +{ + int k, i; + const int i_f = 32; + int temp0, temp1, temp2, temp3; + const float *X_low1, *Y01, *Y11; + float *x1=&X[0][0][0]; + float *j=x1+4864; + const int i_Temp = FFMAX(2*sbr->data[ch].t_env_num_env_old - i_f, 0); + + /* loop unrolled 8 times */ + __asm__ volatile ( + "1: \n\t" + "sw $0, 0(%[x1]) \n\t" + "sw $0, 4(%[x1]) \n\t" + "sw $0, 8(%[x1]) \n\t" + "sw $0, 12(%[x1]) \n\t" + "sw $0, 16(%[x1]) \n\t" + "sw $0, 20(%[x1]) \n\t" + "sw $0, 24(%[x1]) \n\t" + "sw $0, 28(%[x1]) \n\t" + "addiu %[x1], %[x1], 32 \n\t" + "bne %[x1], %[j], 1b \n\t" + "addiu %[x1], %[x1], -19456 \n\t" + + : [x1]"+r"(x1) + : [j]"r"(j) + : "memory" + ); + + if (i_Temp != 0) { + + X_low1=&X_low[0][2][0]; + + for (k = 0; k < sbr->kx[0]; k++) { + + __asm__ volatile ( + "move %[i], $zero \n\t" + "2: \n\t" + "lw %[temp0], 0(%[X_low1]) \n\t" + "lw %[temp1], 4(%[X_low1]) \n\t" + "sw %[temp0], 0(%[x1]) \n\t" + "sw %[temp1], 9728(%[x1]) \n\t" + "addiu %[x1], %[x1], 256 \n\t" + "addiu %[X_low1], %[X_low1], 8 \n\t" + "addiu %[i], %[i], 1 \n\t" + "bne %[i], %[i_Temp], 2b \n\t" + + : [x1]"+r"(x1), [X_low1]"+r"(X_low1), [i]"=&r"(i), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [i_Temp]"r"(i_Temp) + : "memory" + ); + x1-=(i_Temp<<6)-1; + X_low1-=(i_Temp<<1)-80; + } + + x1=&X[0][0][k]; + Y01=(float*)&Y0[32][k][0]; + + for (; k < sbr->kx[0] + sbr->m[0]; k++) { + __asm__ volatile ( + "move %[i], $zero \n\t" + "3: \n\t" + "lw %[temp0], 0(%[Y01]) \n\t" + "lw %[temp1], 4(%[Y01]) \n\t" + "sw %[temp0], 0(%[x1]) \n\t" + "sw %[temp1], 9728(%[x1]) \n\t" + "addiu %[x1], %[x1], 256 \n\t" + "addiu %[Y01], %[Y01], 512 \n\t" + "addiu %[i], %[i], 1 \n\t" + "bne %[i], %[i_Temp], 3b \n\t" + + : [x1]"+r"(x1), [Y01]"+r"(Y01), [i]"=&r"(i), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [i_Temp]"r"(i_Temp) + : "memory" + ); + x1 -=(i_Temp<<6)-1; + Y01 -=(i_Temp<<7)-2; + } + } + + x1=&X[0][i_Temp][0]; + X_low1=&X_low[0][i_Temp+2][0]; + temp3=38; + + for (k = 0; k < sbr->kx[1]; k++) { + + __asm__ volatile ( + "move %[i], %[i_Temp] \n\t" + "4: \n\t" + "lw %[temp0], 0(%[X_low1]) \n\t" + "lw %[temp1], 4(%[X_low1]) \n\t" + "sw %[temp0], 0(%[x1]) \n\t" + "sw %[temp1], 9728(%[x1]) \n\t" + "addiu %[x1], %[x1], 256 \n\t" + "addiu %[X_low1], %[X_low1], 8 \n\t" + "addiu %[i], %[i], 1 \n\t" + "bne %[i], %[temp3], 4b \n\t" + + : [x1]"+r"(x1), [X_low1]"+r"(X_low1), [i]"=&r"(i), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2) + : [i_Temp]"r"(i_Temp), [temp3]"r"(temp3) + : "memory" + ); + x1 -= ((38-i_Temp)<<6)-1; + X_low1 -= ((38-i_Temp)<<1)- 80; + } + + x1=&X[0][i_Temp][k]; + Y11=&Y1[i_Temp][k][0]; + temp2=32; + + for (; k < sbr->kx[1] + sbr->m[1]; k++) { + + __asm__ volatile ( + "move %[i], %[i_Temp] \n\t" + "5: \n\t" + "lw %[temp0], 0(%[Y11]) \n\t" + "lw %[temp1], 4(%[Y11]) \n\t" + "sw %[temp0], 0(%[x1]) \n\t" + "sw %[temp1], 9728(%[x1]) \n\t" + "addiu %[x1], %[x1], 256 \n\t" + "addiu %[Y11], %[Y11], 512 \n\t" + "addiu %[i], %[i], 1 \n\t" + "bne %[i], %[temp2], 5b \n\t" + + : [x1]"+r"(x1), [Y11]"+r"(Y11), [i]"=&r"(i), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1) + : [i_Temp]"r"(i_Temp), [temp3]"r"(temp3), + [temp2]"r"(temp2) + : "memory" + ); + + x1 -= ((32-i_Temp)<<6)-1; + Y11 -= ((32-i_Temp)<<7)-2; + } + return 0; +} + +#if HAVE_MIPSFPU +static void sbr_hf_assemble_mips(float Y1[38][64][2], + const float X_high[64][40][2], + SpectralBandReplication *sbr, SBRData *ch_data, + const int e_a[2]) +{ + int e, i, j, m; + const int h_SL = 4 * !sbr->bs_smoothing_mode; + const int kx = sbr->kx[1]; + const int m_max = sbr->m[1]; + static const float h_smooth[5] = { + 0.33333333333333, + 0.30150283239582, + 0.21816949906249, + 0.11516383427084, + 0.03183050093751, + }; + + float (*g_temp)[48] = ch_data->g_temp, (*q_temp)[48] = ch_data->q_temp; + int indexnoise = ch_data->f_indexnoise; + int indexsine = ch_data->f_indexsine; + float *g_temp1, *q_temp1, *pok, *pok1; + float temp1, temp2, temp3, temp4; + int size = m_max; + + if (sbr->reset) { + for (i = 0; i < h_SL; i++) { + memcpy(g_temp[i + 2*ch_data->t_env[0]], sbr->gain[0], m_max * sizeof(sbr->gain[0][0])); + memcpy(q_temp[i + 2*ch_data->t_env[0]], sbr->q_m[0], m_max * sizeof(sbr->q_m[0][0])); + } + } else if (h_SL) { + memcpy(g_temp[2*ch_data->t_env[0]], g_temp[2*ch_data->t_env_num_env_old], 4*sizeof(g_temp[0])); + memcpy(q_temp[2*ch_data->t_env[0]], q_temp[2*ch_data->t_env_num_env_old], 4*sizeof(q_temp[0])); + } + + for (e = 0; e < ch_data->bs_num_env; e++) { + for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) { + g_temp1 = g_temp[h_SL + i]; + pok = sbr->gain[e]; + q_temp1 = q_temp[h_SL + i]; + pok1 = sbr->q_m[e]; + + /* loop unrolled 4 times */ + for (j=0; j<(size>>2); j++) { + __asm__ volatile ( + "lw %[temp1], 0(%[pok]) \n\t" + "lw %[temp2], 4(%[pok]) \n\t" + "lw %[temp3], 8(%[pok]) \n\t" + "lw %[temp4], 12(%[pok]) \n\t" + "sw %[temp1], 0(%[g_temp1]) \n\t" + "sw %[temp2], 4(%[g_temp1]) \n\t" + "sw %[temp3], 8(%[g_temp1]) \n\t" + "sw %[temp4], 12(%[g_temp1]) \n\t" + "lw %[temp1], 0(%[pok1]) \n\t" + "lw %[temp2], 4(%[pok1]) \n\t" + "lw %[temp3], 8(%[pok1]) \n\t" + "lw %[temp4], 12(%[pok1]) \n\t" + "sw %[temp1], 0(%[q_temp1]) \n\t" + "sw %[temp2], 4(%[q_temp1]) \n\t" + "sw %[temp3], 8(%[q_temp1]) \n\t" + "sw %[temp4], 12(%[q_temp1]) \n\t" + "addiu %[pok], %[pok], 16 \n\t" + "addiu %[g_temp1], %[g_temp1], 16 \n\t" + "addiu %[pok1], %[pok1], 16 \n\t" + "addiu %[q_temp1], %[q_temp1], 16 \n\t" + + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [pok]"+r"(pok), [g_temp1]"+r"(g_temp1), + [pok1]"+r"(pok1), [q_temp1]"+r"(q_temp1) + : + : "memory" + ); + } + + for (j=0; j<(size&3); j++) { + __asm__ volatile ( + "lw %[temp1], 0(%[pok]) \n\t" + "lw %[temp2], 0(%[pok1]) \n\t" + "sw %[temp1], 0(%[g_temp1]) \n\t" + "sw %[temp2], 0(%[q_temp1]) \n\t" + "addiu %[pok], %[pok], 4 \n\t" + "addiu %[g_temp1], %[g_temp1], 4 \n\t" + "addiu %[pok1], %[pok1], 4 \n\t" + "addiu %[q_temp1], %[q_temp1], 4 \n\t" + + : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&r"(temp4), + [pok]"+r"(pok), [g_temp1]"+r"(g_temp1), + [pok1]"+r"(pok1), [q_temp1]"+r"(q_temp1) + : + : "memory" + ); + } + } + } + + for (e = 0; e < ch_data->bs_num_env; e++) { + for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) { + LOCAL_ALIGNED_16(float, g_filt_tab, [48]); + LOCAL_ALIGNED_16(float, q_filt_tab, [48]); + float *g_filt, *q_filt; + + if (h_SL && e != e_a[0] && e != e_a[1]) { + g_filt = g_filt_tab; + q_filt = q_filt_tab; + + for (m = 0; m < m_max; m++) { + const int idx1 = i + h_SL; + g_filt[m] = 0.0f; + q_filt[m] = 0.0f; + + for (j = 0; j <= h_SL; j++) { + g_filt[m] += g_temp[idx1 - j][m] * h_smooth[j]; + q_filt[m] += q_temp[idx1 - j][m] * h_smooth[j]; + } + } + } else { + g_filt = g_temp[i + h_SL]; + q_filt = q_temp[i]; + } + + sbr->dsp.hf_g_filt(Y1[i] + kx, X_high + kx, g_filt, m_max, + i + ENVELOPE_ADJUSTMENT_OFFSET); + + if (e != e_a[0] && e != e_a[1]) { + sbr->dsp.hf_apply_noise[indexsine](Y1[i] + kx, sbr->s_m[e], + q_filt, indexnoise, + kx, m_max); + } else { + int idx = indexsine&1; + int A = (1-((indexsine+(kx & 1))&2)); + int B = (A^(-idx)) + idx; + float *out = &Y1[i][kx][idx]; + float *in = sbr->s_m[e]; + float temp0, temp1, temp2, temp3, temp4, temp5; + float A_f = (float)A; + float B_f = (float)B; + + for (m = 0; m+1 < m_max; m+=2) { + + temp2 = out[0]; + temp3 = out[2]; + + __asm__ volatile( + "lwc1 %[temp0], 0(%[in]) \n\t" + "lwc1 %[temp1], 4(%[in]) \n\t" + "madd.s %[temp4], %[temp2], %[temp0], %[A_f] \n\t" + "madd.s %[temp5], %[temp3], %[temp1], %[B_f] \n\t" + "swc1 %[temp4], 0(%[out]) \n\t" + "swc1 %[temp5], 8(%[out]) \n\t" + "addiu %[in], %[in], 8 \n\t" + "addiu %[out], %[out], 16 \n\t" + + : [temp0]"=&f" (temp0), [temp1]"=&f"(temp1), + [temp4]"=&f" (temp4), [temp5]"=&f"(temp5), + [in]"+r"(in), [out]"+r"(out) + : [A_f]"f"(A_f), [B_f]"f"(B_f), [temp2]"f"(temp2), + [temp3]"f"(temp3) + : "memory" + ); + } + if(m_max&1) + out[2*m ] += in[m ] * A; + } + indexnoise = (indexnoise + m_max) & 0x1ff; + indexsine = (indexsine + 1) & 3; + } + } + ch_data->f_indexnoise = indexnoise; + ch_data->f_indexsine = indexsine; +} + +static void sbr_hf_inverse_filter_mips(SBRDSPContext *dsp, + float (*alpha0)[2], float (*alpha1)[2], + const float X_low[32][40][2], int k0) +{ + int k; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, c; + float *phi1, *alpha_1, *alpha_0, res1, res2, temp_real, temp_im; + + c = 1.000001f; + + for (k = 0; k < k0; k++) { + LOCAL_ALIGNED_16(float, phi, [3], [2][2]); + float dk; + phi1 = &phi[0][0][0]; + alpha_1 = &alpha1[k][0]; + alpha_0 = &alpha0[k][0]; + dsp->autocorrelate(X_low[k], phi); + + __asm__ volatile ( + "lwc1 %[temp0], 40(%[phi1]) \n\t" + "lwc1 %[temp1], 16(%[phi1]) \n\t" + "lwc1 %[temp2], 24(%[phi1]) \n\t" + "lwc1 %[temp3], 28(%[phi1]) \n\t" + "mul.s %[dk], %[temp0], %[temp1] \n\t" + "lwc1 %[temp4], 0(%[phi1]) \n\t" + "mul.s %[res2], %[temp2], %[temp2] \n\t" + "lwc1 %[temp5], 4(%[phi1]) \n\t" + "madd.s %[res2], %[res2], %[temp3], %[temp3] \n\t" + "lwc1 %[temp6], 8(%[phi1]) \n\t" + "div.s %[res2], %[res2], %[c] \n\t" + "lwc1 %[temp0], 12(%[phi1]) \n\t" + "sub.s %[dk], %[dk], %[res2] \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [res2]"=&f"(res2), [dk]"=&f"(dk) + : [phi1]"r"(phi1), [c]"f"(c) + : "memory" + ); + + if (!dk) { + alpha_1[0] = 0; + alpha_1[1] = 0; + } else { + __asm__ volatile ( + "mul.s %[temp_real], %[temp4], %[temp2] \n\t" + "nmsub.s %[temp_real], %[temp_real], %[temp5], %[temp3] \n\t" + "nmsub.s %[temp_real], %[temp_real], %[temp6], %[temp1] \n\t" + "mul.s %[temp_im], %[temp4], %[temp3] \n\t" + "madd.s %[temp_im], %[temp_im], %[temp5], %[temp2] \n\t" + "nmsub.s %[temp_im], %[temp_im], %[temp0], %[temp1] \n\t" + "div.s %[temp_real], %[temp_real], %[dk] \n\t" + "div.s %[temp_im], %[temp_im], %[dk] \n\t" + "swc1 %[temp_real], 0(%[alpha_1]) \n\t" + "swc1 %[temp_im], 4(%[alpha_1]) \n\t" + + : [temp_real]"=&f" (temp_real), [temp_im]"=&f"(temp_im) + : [phi1]"r"(phi1), [temp0]"f"(temp0), [temp1]"f"(temp1), + [temp2]"f"(temp2), [temp3]"f"(temp3), [temp4]"f"(temp4), + [temp5]"f"(temp5), [temp6]"f"(temp6), + [alpha_1]"r"(alpha_1), [dk]"f"(dk) + : "memory" + ); + } + + if (!phi1[4]) { + alpha_0[0] = 0; + alpha_0[1] = 0; + } else { + __asm__ volatile ( + "lwc1 %[temp6], 0(%[alpha_1]) \n\t" + "lwc1 %[temp7], 4(%[alpha_1]) \n\t" + "mul.s %[temp_real], %[temp6], %[temp2] \n\t" + "add.s %[temp_real], %[temp_real], %[temp4] \n\t" + "madd.s %[temp_real], %[temp_real], %[temp7], %[temp3] \n\t" + "mul.s %[temp_im], %[temp7], %[temp2] \n\t" + "add.s %[temp_im], %[temp_im], %[temp5] \n\t" + "nmsub.s %[temp_im], %[temp_im], %[temp6], %[temp3] \n\t" + "div.s %[temp_real], %[temp_real], %[temp1] \n\t" + "div.s %[temp_im], %[temp_im], %[temp1] \n\t" + "neg.s %[temp_real], %[temp_real] \n\t" + "neg.s %[temp_im], %[temp_im] \n\t" + "swc1 %[temp_real], 0(%[alpha_0]) \n\t" + "swc1 %[temp_im], 4(%[alpha_0]) \n\t" + + : [temp_real]"=&f"(temp_real), [temp_im]"=&f"(temp_im), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), + [res1]"=&f"(res1), [res2]"=&f"(res2) + : [alpha_1]"r"(alpha_1), [alpha_0]"r"(alpha_0), + [temp0]"f"(temp0), [temp1]"f"(temp1), [temp2]"f"(temp2), + [temp3]"f"(temp3), [temp4]"f"(temp4), [temp5]"f"(temp5) + : "memory" + ); + } + + __asm__ volatile ( + "lwc1 %[temp1], 0(%[alpha_1]) \n\t" + "lwc1 %[temp2], 4(%[alpha_1]) \n\t" + "lwc1 %[temp_real], 0(%[alpha_0]) \n\t" + "lwc1 %[temp_im], 4(%[alpha_0]) \n\t" + "mul.s %[res1], %[temp1], %[temp1] \n\t" + "madd.s %[res1], %[res1], %[temp2], %[temp2] \n\t" + "mul.s %[res2], %[temp_real], %[temp_real] \n\t" + "madd.s %[res2], %[res2], %[temp_im], %[temp_im] \n\t" + + : [temp_real]"=&f"(temp_real), [temp_im]"=&f"(temp_im), + [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [res1]"=&f"(res1), [res2]"=&f"(res2) + : [alpha_1]"r"(alpha_1), [alpha_0]"r"(alpha_0) + : "memory" + ); + + if (res1 >= 16.0f || res2 >= 16.0f) { + alpha_1[0] = 0; + alpha_1[1] = 0; + alpha_0[0] = 0; + alpha_0[1] = 0; + } + } +} +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ + +void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c) +{ +#if HAVE_INLINE_ASM + c->sbr_lf_gen = sbr_lf_gen_mips; + c->sbr_x_gen = sbr_x_gen_mips; +#if HAVE_MIPSFPU + c->sbr_hf_inverse_filter = sbr_hf_inverse_filter_mips; + c->sbr_hf_assemble = sbr_hf_assemble_mips; +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/mips/aacsbr_mips.h b/ffmpeg/libavcodec/mips/aacsbr_mips.h new file mode 100644 index 0000000..8e6ad7d --- /dev/null +++ b/ffmpeg/libavcodec/mips/aacsbr_mips.h @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Djordje Pesut (djordje@mips.com) + * Mirjana Vulin (mvulin@mips.com) + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/aacsbr.c + */ + +#ifndef AVCODEC_MIPS_AACSBR_FLOAT_H +#define AVCODEC_MIPS_AACSBR_FLOAT_H + +#include "libavcodec/aac.h" +#include "libavcodec/sbr.h" + +#if HAVE_INLINE_ASM +static void sbr_qmf_analysis_mips(AVFloatDSPContext *fdsp, FFTContext *mdct, + SBRDSPContext *sbrdsp, const float *in, float *x, + float z[320], float W[2][32][32][2], int buf_idx) +{ + int i; + float *w0; + float *w1; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + w0 = x; + w1 = x + 1024; + for(i = 0; i < 36; i++) + { + /* loop unrolled 8 times */ + __asm__ volatile( + "lw %[temp0], 0(%[w1]) \n\t" + "lw %[temp1], 4(%[w1]) \n\t" + "lw %[temp2], 8(%[w1]) \n\t" + "lw %[temp3], 12(%[w1]) \n\t" + "lw %[temp4], 16(%[w1]) \n\t" + "lw %[temp5], 20(%[w1]) \n\t" + "lw %[temp6], 24(%[w1]) \n\t" + "lw %[temp7], 28(%[w1]) \n\t" + "sw %[temp0], 0(%[w0]) \n\t" + "sw %[temp1], 4(%[w0]) \n\t" + "sw %[temp2], 8(%[w0]) \n\t" + "sw %[temp3], 12(%[w0]) \n\t" + "sw %[temp4], 16(%[w0]) \n\t" + "sw %[temp5], 20(%[w0]) \n\t" + "sw %[temp6], 24(%[w0]) \n\t" + "sw %[temp7], 28(%[w0]) \n\t" + "addiu %[w0], %[w0], 32 \n\t" + "addiu %[w1], %[w1], 32 \n\t" + + : [w0]"+r"(w0), [w1]"+r"(w1), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) + : + : "memory" + ); + } + + w0 = x + 288; + w1 = (float*)in; + for(i = 0; i < 128; i++) + { + /* loop unrolled 8 times */ + __asm__ volatile( + "lw %[temp0], 0(%[w1]) \n\t" + "lw %[temp1], 4(%[w1]) \n\t" + "lw %[temp2], 8(%[w1]) \n\t" + "lw %[temp3], 12(%[w1]) \n\t" + "lw %[temp4], 16(%[w1]) \n\t" + "lw %[temp5], 20(%[w1]) \n\t" + "lw %[temp6], 24(%[w1]) \n\t" + "lw %[temp7], 28(%[w1]) \n\t" + "sw %[temp0], 0(%[w0]) \n\t" + "sw %[temp1], 4(%[w0]) \n\t" + "sw %[temp2], 8(%[w0]) \n\t" + "sw %[temp3], 12(%[w0]) \n\t" + "sw %[temp4], 16(%[w0]) \n\t" + "sw %[temp5], 20(%[w0]) \n\t" + "sw %[temp6], 24(%[w0]) \n\t" + "sw %[temp7], 28(%[w0]) \n\t" + "addiu %[w0], %[w0], 32 \n\t" + "addiu %[w1], %[w1], 32 \n\t" + + : [w0]"+r"(w0), [w1]"+r"(w1), + [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), + [temp2]"=&r"(temp2), [temp3]"=&r"(temp3), + [temp4]"=&r"(temp4), [temp5]"=&r"(temp5), + [temp6]"=&r"(temp6), [temp7]"=&r"(temp7) + : + : "memory" + ); + } + + for (i = 0; i < 32; i++) { // numTimeSlots*RATE = 16*2 as 960 sample frames + // are not supported + fdsp->vector_fmul_reverse(z, sbr_qmf_window_ds, x, 320); + sbrdsp->sum64x5(z); + sbrdsp->qmf_pre_shuffle(z); + mdct->imdct_half(mdct, z, z+64); + sbrdsp->qmf_post_shuffle(W[buf_idx][i], z); + x += 32; + } +} + +#if HAVE_MIPSFPU +static void sbr_qmf_synthesis_mips(FFTContext *mdct, + SBRDSPContext *sbrdsp, AVFloatDSPContext *fdsp, + float *out, float X[2][38][64], + float mdct_buf[2][64], + float *v0, int *v_off, const unsigned int div) +{ + int i, n; + const float *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us; + const int step = 128 >> div; + float *v; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12, temp13; + float temp14, temp15, temp16, temp17, temp18, temp19; + float *vv0, *s0, *dst; + dst = out; + + for (i = 0; i < 32; i++) { + if (*v_off < step) { + int saved_samples = (1280 - 128) >> div; + memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(float)); + *v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - step; + } else { + *v_off -= step; + } + v = v0 + *v_off; + if (div) { + for (n = 0; n < 32; n++) { + X[0][i][ n] = -X[0][i][n]; + X[0][i][32+n] = X[1][i][31-n]; + } + mdct->imdct_half(mdct, mdct_buf[0], X[0][i]); + sbrdsp->qmf_deint_neg(v, mdct_buf[0]); + } else { + sbrdsp->neg_odd_64(X[1][i]); + mdct->imdct_half(mdct, mdct_buf[0], X[0][i]); + mdct->imdct_half(mdct, mdct_buf[1], X[1][i]); + sbrdsp->qmf_deint_bfly(v, mdct_buf[1], mdct_buf[0]); + } + + if(div == 0) + { + float *v0_end; + vv0 = v; + v0_end = v + 60; + s0 = (float*)sbr_qmf_window; + + /* 10 calls of function vector_fmul_add merged into one loop + and loop unrolled 4 times */ + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + "lwc1 %[temp4], 0(%[v0]) \n\t" + "lwc1 %[temp5], 0(%[s0]) \n\t" + "lwc1 %[temp6], 4(%[v0]) \n\t" + "lwc1 %[temp7], 4(%[s0]) \n\t" + "lwc1 %[temp8], 8(%[v0]) \n\t" + "lwc1 %[temp9], 8(%[s0]) \n\t" + "lwc1 %[temp10], 12(%[v0]) \n\t" + "lwc1 %[temp11], 12(%[s0]) \n\t" + "lwc1 %[temp12], 768(%[v0]) \n\t" + "lwc1 %[temp13], 256(%[s0]) \n\t" + "lwc1 %[temp14], 772(%[v0]) \n\t" + "lwc1 %[temp15], 260(%[s0]) \n\t" + "lwc1 %[temp16], 776(%[v0]) \n\t" + "lwc1 %[temp17], 264(%[s0]) \n\t" + "lwc1 %[temp18], 780(%[v0]) \n\t" + "lwc1 %[temp19], 268(%[s0]) \n\t" + "1: \n\t" + "mul.s %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 1024(%[v0]) \n\t" + "mul.s %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 512(%[s0]) \n\t" + "mul.s %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 1028(%[v0]) \n\t" + "mul.s %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 516(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 1032(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 520(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 1036(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 524(%[s0]) \n\t" + "lwc1 %[temp12], 1792(%[v0]) \n\t" + "lwc1 %[temp13], 768(%[s0]) \n\t" + "lwc1 %[temp14], 1796(%[v0]) \n\t" + "lwc1 %[temp15], 772(%[s0]) \n\t" + "lwc1 %[temp16], 1800(%[v0]) \n\t" + "lwc1 %[temp17], 776(%[s0]) \n\t" + "lwc1 %[temp18], 1804(%[v0]) \n\t" + "lwc1 %[temp19], 780(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 2048(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 1024(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 2052(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 1028(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 2056(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 1032(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 2060(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 1036(%[s0]) \n\t" + "lwc1 %[temp12], 2816(%[v0]) \n\t" + "lwc1 %[temp13], 1280(%[s0]) \n\t" + "lwc1 %[temp14], 2820(%[v0]) \n\t" + "lwc1 %[temp15], 1284(%[s0]) \n\t" + "lwc1 %[temp16], 2824(%[v0]) \n\t" + "lwc1 %[temp17], 1288(%[s0]) \n\t" + "lwc1 %[temp18], 2828(%[v0]) \n\t" + "lwc1 %[temp19], 1292(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 3072(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 1536(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 3076(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 1540(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 3080(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 1544(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 3084(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 1548(%[s0]) \n\t" + "lwc1 %[temp12], 3840(%[v0]) \n\t" + "lwc1 %[temp13], 1792(%[s0]) \n\t" + "lwc1 %[temp14], 3844(%[v0]) \n\t" + "lwc1 %[temp15], 1796(%[s0]) \n\t" + "lwc1 %[temp16], 3848(%[v0]) \n\t" + "lwc1 %[temp17], 1800(%[s0]) \n\t" + "lwc1 %[temp18], 3852(%[v0]) \n\t" + "lwc1 %[temp19], 1804(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 4096(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 2048(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 4100(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 2052(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 4104(%[v0]) \n\t" + "addiu %[dst], %[dst], 16 \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 2056(%[s0]) \n\t" + "addiu %[s0], %[s0], 16 \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 4108(%[v0]) \n\t" + "addiu %[v0], %[v0], 16 \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 2044(%[s0]) \n\t" + "lwc1 %[temp12], 4848(%[v0]) \n\t" + "lwc1 %[temp13], 2288(%[s0]) \n\t" + "lwc1 %[temp14], 4852(%[v0]) \n\t" + "lwc1 %[temp15], 2292(%[s0]) \n\t" + "lwc1 %[temp16], 4856(%[v0]) \n\t" + "lwc1 %[temp17], 2296(%[s0]) \n\t" + "lwc1 %[temp18], 4860(%[v0]) \n\t" + "lwc1 %[temp19], 2300(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 0(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 0(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 4(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 4(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 8(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 8(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 12(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 12(%[s0]) \n\t" + "lwc1 %[temp12], 768(%[v0]) \n\t" + "lwc1 %[temp13], 256(%[s0]) \n\t" + "lwc1 %[temp14], 772(%[v0]) \n\t" + "lwc1 %[temp15], 260(%[s0]) \n\t" + "lwc1 %[temp16], 776(%[v0]) \n\t" + "lwc1 %[temp17], 264(%[s0]) \n\t" + "lwc1 %[temp18], 780(%[v0]) \n\t" + "lwc1 %[temp19], 268(%[s0]) \n\t" + "swc1 %[temp0], -16(%[dst]) \n\t" + "swc1 %[temp1], -12(%[dst]) \n\t" + "swc1 %[temp2], -8(%[dst]) \n\t" + "bne %[v0], %[v0_end], 1b \n\t" + " swc1 %[temp3], -4(%[dst]) \n\t" + "mul.s %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 1024(%[v0]) \n\t" + "mul.s %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 512(%[s0]) \n\t" + "mul.s %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 1028(%[v0]) \n\t" + "mul.s %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 516(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 1032(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 520(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 1036(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 524(%[s0]) \n\t" + "lwc1 %[temp12], 1792(%[v0]) \n\t" + "lwc1 %[temp13], 768(%[s0]) \n\t" + "lwc1 %[temp14], 1796(%[v0]) \n\t" + "lwc1 %[temp15], 772(%[s0]) \n\t" + "lwc1 %[temp16], 1800(%[v0]) \n\t" + "lwc1 %[temp17], 776(%[s0]) \n\t" + "lwc1 %[temp18], 1804(%[v0]) \n\t" + "lwc1 %[temp19], 780(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 2048(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 1024(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 2052(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 1028(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 2056(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 1032(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 2060(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 1036(%[s0]) \n\t" + "lwc1 %[temp12], 2816(%[v0]) \n\t" + "lwc1 %[temp13], 1280(%[s0]) \n\t" + "lwc1 %[temp14], 2820(%[v0]) \n\t" + "lwc1 %[temp15], 1284(%[s0]) \n\t" + "lwc1 %[temp16], 2824(%[v0]) \n\t" + "lwc1 %[temp17], 1288(%[s0]) \n\t" + "lwc1 %[temp18], 2828(%[v0]) \n\t" + "lwc1 %[temp19], 1292(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 3072(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 1536(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 3076(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 1540(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 3080(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 1544(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 3084(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 1548(%[s0]) \n\t" + "lwc1 %[temp12], 3840(%[v0]) \n\t" + "lwc1 %[temp13], 1792(%[s0]) \n\t" + "lwc1 %[temp14], 3844(%[v0]) \n\t" + "lwc1 %[temp15], 1796(%[s0]) \n\t" + "lwc1 %[temp16], 3848(%[v0]) \n\t" + "lwc1 %[temp17], 1800(%[s0]) \n\t" + "lwc1 %[temp18], 3852(%[v0]) \n\t" + "lwc1 %[temp19], 1804(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp4], 4096(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp5], 2048(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp6], 4100(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp7], 2052(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "lwc1 %[temp8], 4104(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "lwc1 %[temp9], 2056(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "lwc1 %[temp10], 4108(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "lwc1 %[temp11], 2060(%[s0]) \n\t" + "lwc1 %[temp12], 4864(%[v0]) \n\t" + "lwc1 %[temp13], 2304(%[s0]) \n\t" + "lwc1 %[temp14], 4868(%[v0]) \n\t" + "lwc1 %[temp15], 2308(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t" + "lwc1 %[temp16], 4872(%[v0]) \n\t" + "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t" + "lwc1 %[temp17], 2312(%[s0]) \n\t" + "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t" + "lwc1 %[temp18], 4876(%[v0]) \n\t" + "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t" + "lwc1 %[temp19], 2316(%[s0]) \n\t" + "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t" + "addiu %[dst], %[dst], 16 \n\t" + "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t" + "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t" + "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t" + "swc1 %[temp0], -16(%[dst]) \n\t" + "swc1 %[temp1], -12(%[dst]) \n\t" + "swc1 %[temp2], -8(%[dst]) \n\t" + "swc1 %[temp3], -4(%[dst]) \n\t" + ".set pop \n\t" + + : [dst]"+r"(dst), [v0]"+r"(vv0), [s0]"+r"(s0), + [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [temp10]"=&f"(temp10), [temp11]"=&f"(temp11), + [temp12]"=&f"(temp12), [temp13]"=&f"(temp13), [temp14]"=&f"(temp14), + [temp15]"=&f"(temp15), [temp16]"=&f"(temp16), [temp17]"=&f"(temp17), + [temp18]"=&f"(temp18), [temp19]"=&f"(temp19) + : [v0_end]"r"(v0_end) + : "memory" + ); + } + else + { + fdsp->vector_fmul (out, v , sbr_qmf_window , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 192 >> div), sbr_qmf_window + ( 64 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 256 >> div), sbr_qmf_window + (128 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 448 >> div), sbr_qmf_window + (192 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 512 >> div), sbr_qmf_window + (256 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 704 >> div), sbr_qmf_window + (320 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 768 >> div), sbr_qmf_window + (384 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + ( 960 >> div), sbr_qmf_window + (448 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + (1024 >> div), sbr_qmf_window + (512 >> div), out , 64 >> div); + fdsp->vector_fmul_add(out, v + (1216 >> div), sbr_qmf_window + (576 >> div), out , 64 >> div); + out += 64 >> div; + } + } +} + +#define sbr_qmf_analysis sbr_qmf_analysis_mips +#define sbr_qmf_synthesis sbr_qmf_synthesis_mips + +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_MIPS_AACSBR_FLOAT_H */ diff --git a/ffmpeg/libavcodec/mips/ac3dsp_mips.c b/ffmpeg/libavcodec/mips/ac3dsp_mips.c new file mode 100644 index 0000000..f33c6f1 --- /dev/null +++ b/ffmpeg/libavcodec/mips/ac3dsp_mips.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Branimir Vasic (bvasic@mips.com) + * Nedeljko Babic (nbabic@mips.com) + * + * Various AC-3 DSP Utils optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/ac3dsp.c + */ + +#include "config.h" +#include "libavcodec/ac3dsp.h" +#include "libavcodec/ac3.h" + + +#if HAVE_INLINE_ASM +#if HAVE_MIPSDSPR1 +static void ac3_bit_alloc_calc_bap_mips(int16_t *mask, int16_t *psd, + int start, int end, + int snr_offset, int floor, + const uint8_t *bap_tab, uint8_t *bap) +{ + int band, band_end, cond; + int m, address1, address2; + int16_t *psd1, *psd_end; + uint8_t *bap1; + + if (snr_offset == -960) { + memset(bap, 0, AC3_MAX_COEFS); + return; + } + + psd1 = &psd[start]; + bap1 = &bap[start]; + band = ff_ac3_bin_to_band_tab[start]; + + do { + m = (FFMAX(mask[band] - snr_offset - floor, 0) & 0x1FE0) + floor; + band_end = ff_ac3_band_start_tab[++band]; + band_end = FFMIN(band_end, end); + psd_end = psd + band_end - 1; + + __asm__ volatile ( + "slt %[cond], %[psd1], %[psd_end] \n\t" + "beqz %[cond], 1f \n\t" + "2: \n\t" + "lh %[address1], 0(%[psd1]) \n\t" + "lh %[address2], 2(%[psd1]) \n\t" + "addiu %[psd1], %[psd1], 4 \n\t" + "subu %[address1], %[address1], %[m] \n\t" + "sra %[address1], %[address1], 5 \n\t" + "addiu %[address1], %[address1], -32 \n\t" + "shll_s.w %[address1], %[address1], 26 \n\t" + "subu %[address2], %[address2], %[m] \n\t" + "sra %[address2], %[address2], 5 \n\t" + "sra %[address1], %[address1], 26 \n\t" + "addiu %[address1], %[address1], 32 \n\t" + "lbux %[address1], %[address1](%[bap_tab]) \n\t" + "addiu %[address2], %[address2], -32 \n\t" + "shll_s.w %[address2], %[address2], 26 \n\t" + "sb %[address1], 0(%[bap1]) \n\t" + "slt %[cond], %[psd1], %[psd_end] \n\t" + "sra %[address2], %[address2], 26 \n\t" + "addiu %[address2], %[address2], 32 \n\t" + "lbux %[address2], %[address2](%[bap_tab]) \n\t" + "sb %[address2], 1(%[bap1]) \n\t" + "addiu %[bap1], %[bap1], 2 \n\t" + "bnez %[cond], 2b \n\t" + "addiu %[psd_end], %[psd_end], 2 \n\t" + "slt %[cond], %[psd1], %[psd_end] \n\t" + "beqz %[cond], 3f \n\t" + "1: \n\t" + "lh %[address1], 0(%[psd1]) \n\t" + "addiu %[psd1], %[psd1], 2 \n\t" + "subu %[address1], %[address1], %[m] \n\t" + "sra %[address1], %[address1], 5 \n\t" + "addiu %[address1], %[address1], -32 \n\t" + "shll_s.w %[address1], %[address1], 26 \n\t" + "sra %[address1], %[address1], 26 \n\t" + "addiu %[address1], %[address1], 32 \n\t" + "lbux %[address1], %[address1](%[bap_tab]) \n\t" + "sb %[address1], 0(%[bap1]) \n\t" + "addiu %[bap1], %[bap1], 1 \n\t" + "3: \n\t" + + : [address1]"=&r"(address1), [address2]"=&r"(address2), + [cond]"=&r"(cond), [bap1]"+r"(bap1), + [psd1]"+r"(psd1), [psd_end]"+r"(psd_end) + : [m]"r"(m), [bap_tab]"r"(bap_tab) + : "memory" + ); + } while (end > band_end); +} + +static void ac3_update_bap_counts_mips(uint16_t mant_cnt[16], uint8_t *bap, + int len) +{ + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + __asm__ volatile ( + "andi %[temp3], %[len], 3 \n\t" + "addu %[temp2], %[bap], %[len] \n\t" + "addu %[temp4], %[bap], %[temp3] \n\t" + "beq %[temp2], %[temp4], 4f \n\t" + "1: \n\t" + "lbu %[temp0], -1(%[temp2]) \n\t" + "lbu %[temp5], -2(%[temp2]) \n\t" + "lbu %[temp6], -3(%[temp2]) \n\t" + "sll %[temp0], %[temp0], 1 \n\t" + "addu %[temp0], %[mant_cnt], %[temp0] \n\t" + "sll %[temp5], %[temp5], 1 \n\t" + "addu %[temp5], %[mant_cnt], %[temp5] \n\t" + "lhu %[temp1], 0(%[temp0]) \n\t" + "sll %[temp6], %[temp6], 1 \n\t" + "addu %[temp6], %[mant_cnt], %[temp6] \n\t" + "addiu %[temp1], %[temp1], 1 \n\t" + "sh %[temp1], 0(%[temp0]) \n\t" + "lhu %[temp1], 0(%[temp5]) \n\t" + "lbu %[temp7], -4(%[temp2]) \n\t" + "addiu %[temp2], %[temp2], -4 \n\t" + "addiu %[temp1], %[temp1], 1 \n\t" + "sh %[temp1], 0(%[temp5]) \n\t" + "lhu %[temp1], 0(%[temp6]) \n\t" + "sll %[temp7], %[temp7], 1 \n\t" + "addu %[temp7], %[mant_cnt], %[temp7] \n\t" + "addiu %[temp1], %[temp1],1 \n\t" + "sh %[temp1], 0(%[temp6]) \n\t" + "lhu %[temp1], 0(%[temp7]) \n\t" + "addiu %[temp1], %[temp1], 1 \n\t" + "sh %[temp1], 0(%[temp7]) \n\t" + "bne %[temp2], %[temp4], 1b \n\t" + "4: \n\t" + "beqz %[temp3], 2f \n\t" + "3: \n\t" + "addiu %[temp3], %[temp3], -1 \n\t" + "lbu %[temp0], -1(%[temp2]) \n\t" + "addiu %[temp2], %[temp2], -1 \n\t" + "sll %[temp0], %[temp0], 1 \n\t" + "addu %[temp0], %[mant_cnt], %[temp0] \n\t" + "lhu %[temp1], 0(%[temp0]) \n\t" + "addiu %[temp1], %[temp1], 1 \n\t" + "sh %[temp1], 0(%[temp0]) \n\t" + "bgtz %[temp3], 3b \n\t" + "2: \n\t" + + : [temp0] "=&r" (temp0), [temp1] "=&r" (temp1), + [temp2] "=&r" (temp2), [temp3] "=&r" (temp3), + [temp4] "=&r" (temp4), [temp5] "=&r" (temp5), + [temp6] "=&r" (temp6), [temp7] "=&r" (temp7) + : [len] "r" (len), [bap] "r" (bap), + [mant_cnt] "r" (mant_cnt) + : "memory" + ); +} +#endif + +#if HAVE_MIPSFPU && HAVE_MIPS32R2 +static void float_to_fixed24_mips(int32_t *dst, const float *src, unsigned int len) +{ + const float scale = 1 << 24; + float src0, src1, src2, src3, src4, src5, src6, src7; + int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + do { + __asm__ volatile ( + "lwc1 %[src0], 0(%[src]) \n\t" + "lwc1 %[src1], 4(%[src]) \n\t" + "lwc1 %[src2], 8(%[src]) \n\t" + "lwc1 %[src3], 12(%[src]) \n\t" + "lwc1 %[src4], 16(%[src]) \n\t" + "lwc1 %[src5], 20(%[src]) \n\t" + "lwc1 %[src6], 24(%[src]) \n\t" + "lwc1 %[src7], 28(%[src]) \n\t" + "mul.s %[src0], %[src0], %[scale] \n\t" + "mul.s %[src1], %[src1], %[scale] \n\t" + "mul.s %[src2], %[src2], %[scale] \n\t" + "mul.s %[src3], %[src3], %[scale] \n\t" + "mul.s %[src4], %[src4], %[scale] \n\t" + "mul.s %[src5], %[src5], %[scale] \n\t" + "mul.s %[src6], %[src6], %[scale] \n\t" + "mul.s %[src7], %[src7], %[scale] \n\t" + "cvt.w.s %[src0], %[src0] \n\t" + "cvt.w.s %[src1], %[src1] \n\t" + "cvt.w.s %[src2], %[src2] \n\t" + "cvt.w.s %[src3], %[src3] \n\t" + "cvt.w.s %[src4], %[src4] \n\t" + "cvt.w.s %[src5], %[src5] \n\t" + "cvt.w.s %[src6], %[src6] \n\t" + "cvt.w.s %[src7], %[src7] \n\t" + "mfc1 %[temp0], %[src0] \n\t" + "mfc1 %[temp1], %[src1] \n\t" + "mfc1 %[temp2], %[src2] \n\t" + "mfc1 %[temp3], %[src3] \n\t" + "mfc1 %[temp4], %[src4] \n\t" + "mfc1 %[temp5], %[src5] \n\t" + "mfc1 %[temp6], %[src6] \n\t" + "mfc1 %[temp7], %[src7] \n\t" + "sw %[temp0], 0(%[dst]) \n\t" + "sw %[temp1], 4(%[dst]) \n\t" + "sw %[temp2], 8(%[dst]) \n\t" + "sw %[temp3], 12(%[dst]) \n\t" + "sw %[temp4], 16(%[dst]) \n\t" + "sw %[temp5], 20(%[dst]) \n\t" + "sw %[temp6], 24(%[dst]) \n\t" + "sw %[temp7], 28(%[dst]) \n\t" + + : [dst] "+r" (dst), [src] "+r" (src), + [src0] "=&f" (src0), [src1] "=&f" (src1), + [src2] "=&f" (src2), [src3] "=&f" (src3), + [src4] "=&f" (src4), [src5] "=&f" (src5), + [src6] "=&f" (src6), [src7] "=&f" (src7), + [temp0] "=r" (temp0), [temp1] "=r" (temp1), + [temp2] "=r" (temp2), [temp3] "=r" (temp3), + [temp4] "=r" (temp4), [temp5] "=r" (temp5), + [temp6] "=r" (temp6), [temp7] "=r" (temp7) + : [scale] "f" (scale) + : "memory" + ); + src = src + 8; + dst = dst + 8; + len -= 8; + } while (len > 0); +} + +static void ac3_downmix_mips(float **samples, float (*matrix)[2], + int out_ch, int in_ch, int len) +{ + int i, j, i1, i2, i3; + float v0, v1, v2, v3; + float v4, v5, v6, v7; + float samples0, samples1, samples2, samples3, matrix_j, matrix_j2; + float *samples_p,*matrix_p, **samples_x, **samples_end, **samples_sw; + + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + + "li %[i1], 2 \n\t" + "sll %[len], 2 \n\t" + "move %[i], $zero \n\t" + "sll %[j], %[in_ch], 2 \n\t" + + "bne %[out_ch], %[i1], 3f \n\t" // if (out_ch == 2) + " li %[i2], 1 \n\t" + + "2: \n\t" // start of the for loop (for (i = 0; i < len; i+=4)) + "move %[matrix_p], %[matrix] \n\t" + "move %[samples_x], %[samples] \n\t" + "mtc1 $zero, %[v0] \n\t" + "mtc1 $zero, %[v1] \n\t" + "mtc1 $zero, %[v2] \n\t" + "mtc1 $zero, %[v3] \n\t" + "mtc1 $zero, %[v4] \n\t" + "mtc1 $zero, %[v5] \n\t" + "mtc1 $zero, %[v6] \n\t" + "mtc1 $zero, %[v7] \n\t" + "addiu %[i1], %[i], 4 \n\t" + "addiu %[i2], %[i], 8 \n\t" + "lw %[samples_p], 0(%[samples_x]) \n\t" + "addiu %[i3], %[i], 12 \n\t" + "addu %[samples_end], %[samples_x], %[j] \n\t" + "move %[samples_sw], %[samples_p] \n\t" + + "1: \n\t" // start of the inner for loop (for (j = 0; j < in_ch; j++)) + "lwc1 %[matrix_j], 0(%[matrix_p]) \n\t" + "lwc1 %[matrix_j2], 4(%[matrix_p]) \n\t" + "lwxc1 %[samples0], %[i](%[samples_p]) \n\t" + "lwxc1 %[samples1], %[i1](%[samples_p]) \n\t" + "lwxc1 %[samples2], %[i2](%[samples_p]) \n\t" + "lwxc1 %[samples3], %[i3](%[samples_p]) \n\t" + "addiu %[matrix_p], 8 \n\t" + "addiu %[samples_x], 4 \n\t" + "madd.s %[v0], %[v0], %[samples0], %[matrix_j] \n\t" + "madd.s %[v1], %[v1], %[samples1], %[matrix_j] \n\t" + "madd.s %[v2], %[v2], %[samples2], %[matrix_j] \n\t" + "madd.s %[v3], %[v3], %[samples3], %[matrix_j] \n\t" + "madd.s %[v4], %[v4], %[samples0], %[matrix_j2]\n\t" + "madd.s %[v5], %[v5], %[samples1], %[matrix_j2]\n\t" + "madd.s %[v6], %[v6], %[samples2], %[matrix_j2]\n\t" + "madd.s %[v7], %[v7], %[samples3], %[matrix_j2]\n\t" + "bne %[samples_x], %[samples_end], 1b \n\t" + " lw %[samples_p], 0(%[samples_x]) \n\t" + + "lw %[samples_p], 4(%[samples]) \n\t" + "swxc1 %[v0], %[i](%[samples_sw]) \n\t" + "swxc1 %[v1], %[i1](%[samples_sw]) \n\t" + "swxc1 %[v2], %[i2](%[samples_sw]) \n\t" + "swxc1 %[v3], %[i3](%[samples_sw]) \n\t" + "swxc1 %[v4], %[i](%[samples_p]) \n\t" + "addiu %[i], 16 \n\t" + "swxc1 %[v5], %[i1](%[samples_p]) \n\t" + "swxc1 %[v6], %[i2](%[samples_p]) \n\t" + "bne %[i], %[len], 2b \n\t" + " swxc1 %[v7], %[i3](%[samples_p]) \n\t" + + "3: \n\t" + "bne %[out_ch], %[i2], 6f \n\t" // if (out_ch == 1) + " nop \n\t" + + "5: \n\t" // start of the outer for loop (for (i = 0; i < len; i+=4)) + "move %[matrix_p], %[matrix] \n\t" + "move %[samples_x], %[samples] \n\t" + "mtc1 $zero, %[v0] \n\t" + "mtc1 $zero, %[v1] \n\t" + "mtc1 $zero, %[v2] \n\t" + "mtc1 $zero, %[v3] \n\t" + "addiu %[i1], %[i], 4 \n\t" + "addiu %[i2], %[i], 8 \n\t" + "lw %[samples_p], 0(%[samples_x]) \n\t" + "addiu %[i3], %[i], 12 \n\t" + "addu %[samples_end], %[samples_x], %[j] \n\t" + "move %[samples_sw], %[samples_p] \n\t" + + "4: \n\t" // start of the inner for loop (for (j = 0; j < in_ch; j++)) + "lwc1 %[matrix_j], 0(%[matrix_p]) \n\t" + "lwxc1 %[samples0], %[i](%[samples_p]) \n\t" + "lwxc1 %[samples1], %[i1](%[samples_p]) \n\t" + "lwxc1 %[samples2], %[i2](%[samples_p]) \n\t" + "lwxc1 %[samples3], %[i3](%[samples_p]) \n\t" + "addiu %[matrix_p], 8 \n\t" + "addiu %[samples_x], 4 \n\t" + "madd.s %[v0], %[v0], %[samples0], %[matrix_j] \n\t" + "madd.s %[v1], %[v1], %[samples1], %[matrix_j] \n\t" + "madd.s %[v2], %[v2], %[samples2], %[matrix_j] \n\t" + "madd.s %[v3], %[v3], %[samples3], %[matrix_j] \n\t" + "bne %[samples_x], %[samples_end], 4b \n\t" + " lw %[samples_p], 0(%[samples_x]) \n\t" + + "swxc1 %[v0], %[i](%[samples_sw]) \n\t" + "addiu %[i], 16 \n\t" + "swxc1 %[v1], %[i1](%[samples_sw]) \n\t" + "swxc1 %[v2], %[i2](%[samples_sw]) \n\t" + "bne %[i], %[len], 5b \n\t" + " swxc1 %[v3], %[i3](%[samples_sw]) \n\t" + "6: \n\t" + + ".set pop" + :[samples_p]"=&r"(samples_p), [matrix_j]"=&f"(matrix_j), [matrix_j2]"=&f"(matrix_j2), + [samples0]"=&f"(samples0), [samples1]"=&f"(samples1), + [samples2]"=&f"(samples2), [samples3]"=&f"(samples3), + [v0]"=&f"(v0), [v1]"=&f"(v1), [v2]"=&f"(v2), [v3]"=&f"(v3), + [v4]"=&f"(v4), [v5]"=&f"(v5), [v6]"=&f"(v6), [v7]"=&f"(v7), + [samples_x]"=&r"(samples_x), [matrix_p]"=&r"(matrix_p), + [samples_end]"=&r"(samples_end), [samples_sw]"=&r"(samples_sw), + [i1]"=&r"(i1), [i2]"=&r"(i2), [i3]"=&r"(i3), [i]"=&r"(i), + [j]"=&r"(j), [len]"+r"(len) + :[samples]"r"(samples), [matrix]"r"(matrix), + [in_ch]"r"(in_ch), [out_ch]"r"(out_ch) + :"memory" + ); +} +#endif +#endif /* HAVE_INLINE_ASM */ + +void ff_ac3dsp_init_mips(AC3DSPContext *c, int bit_exact) { +#if HAVE_INLINE_ASM +#if HAVE_MIPSDSPR1 + c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_mips; + c->update_bap_counts = ac3_update_bap_counts_mips; +#endif +#if HAVE_MIPSFPU && HAVE_MIPS32R2 + c->float_to_fixed24 = float_to_fixed24_mips; + c->downmix = ac3_downmix_mips; +#endif +#endif + +} diff --git a/ffmpeg/libavcodec/mips/acelp_filters_mips.c b/ffmpeg/libavcodec/mips/acelp_filters_mips.c new file mode 100644 index 0000000..c8d980a --- /dev/null +++ b/ffmpeg/libavcodec/mips/acelp_filters_mips.c @@ -0,0 +1,216 @@ + /* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * various filters for ACELP-based codecs optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/acelp_filters.c + */ +#include "config.h" +#include "libavutil/attributes.h" +#include "libavcodec/acelp_filters.h" + +#if HAVE_INLINE_ASM +static void ff_acelp_interpolatef_mips(float *out, const float *in, + const float *filter_coeffs, int precision, + int frac_pos, int filter_length, int length) +{ + int n, i; + int prec = precision * 4; + int fc_offset = precision - frac_pos; + float in_val_p, in_val_m, fc_val_p, fc_val_m; + + for (n = 0; n < length; n++) { + /** + * four pointers are defined in order to minimize number of + * computations done in inner loop + */ + const float *p_in_p = &in[n]; + const float *p_in_m = &in[n-1]; + const float *p_filter_coeffs_p = &filter_coeffs[frac_pos]; + const float *p_filter_coeffs_m = filter_coeffs + fc_offset; + float v = 0; + + for (i = 0; i < filter_length;i++) { + __asm__ volatile ( + "lwc1 %[in_val_p], 0(%[p_in_p]) \n\t" + "lwc1 %[fc_val_p], 0(%[p_filter_coeffs_p]) \n\t" + "lwc1 %[in_val_m], 0(%[p_in_m]) \n\t" + "lwc1 %[fc_val_m], 0(%[p_filter_coeffs_m]) \n\t" + "addiu %[p_in_p], %[p_in_p], 4 \n\t" + "madd.s %[v],%[v], %[in_val_p],%[fc_val_p] \n\t" + "addiu %[p_in_m], %[p_in_m], -4 \n\t" + "addu %[p_filter_coeffs_p], %[p_filter_coeffs_p], %[prec] \n\t" + "addu %[p_filter_coeffs_m], %[p_filter_coeffs_m], %[prec] \n\t" + "madd.s %[v],%[v],%[in_val_m], %[fc_val_m] \n\t" + + : [v] "=&f" (v),[p_in_p] "+r" (p_in_p), [p_in_m] "+r" (p_in_m), + [p_filter_coeffs_p] "+r" (p_filter_coeffs_p), + [in_val_p] "=&f" (in_val_p), [in_val_m] "=&f" (in_val_m), + [fc_val_p] "=&f" (fc_val_p), [fc_val_m] "=&f" (fc_val_m), + [p_filter_coeffs_m] "+r" (p_filter_coeffs_m) + : [prec] "r" (prec) + : "memory" + ); + } + out[n] = v; + } +} + +static void ff_acelp_apply_order_2_transfer_function_mips(float *out, const float *in, + const float zero_coeffs[2], + const float pole_coeffs[2], + float gain, float mem[2], int n) +{ + /** + * loop is unrolled eight times + */ + + __asm__ volatile ( + "lwc1 $f0, 0(%[mem]) \n\t" + "blez %[n], ff_acelp_apply_order_2_transfer_function_end%= \n\t" + "lwc1 $f1, 4(%[mem]) \n\t" + "lwc1 $f2, 0(%[pole_coeffs]) \n\t" + "lwc1 $f3, 4(%[pole_coeffs]) \n\t" + "lwc1 $f4, 0(%[zero_coeffs]) \n\t" + "lwc1 $f5, 4(%[zero_coeffs]) \n\t" + + "ff_acelp_apply_order_2_transfer_function_madd%=: \n\t" + + "lwc1 $f6, 0(%[in]) \n\t" + "mul.s $f9, $f3, $f1 \n\t" + "mul.s $f7, $f2, $f0 \n\t" + "msub.s $f7, $f7, %[gain], $f6 \n\t" + "sub.s $f7, $f7, $f9 \n\t" + "madd.s $f8, $f7, $f4, $f0 \n\t" + "madd.s $f8, $f8, $f5, $f1 \n\t" + "lwc1 $f11, 4(%[in]) \n\t" + "mul.s $f12, $f3, $f0 \n\t" + "mul.s $f13, $f2, $f7 \n\t" + "msub.s $f13, $f13, %[gain], $f11 \n\t" + "sub.s $f13, $f13, $f12 \n\t" + "madd.s $f14, $f13, $f4, $f7 \n\t" + "madd.s $f14, $f14, $f5, $f0 \n\t" + "swc1 $f8, 0(%[out]) \n\t" + "lwc1 $f6, 8(%[in]) \n\t" + "mul.s $f9, $f3, $f7 \n\t" + "mul.s $f15, $f2, $f13 \n\t" + "msub.s $f15, $f15, %[gain], $f6 \n\t" + "sub.s $f15, $f15, $f9 \n\t" + "madd.s $f8, $f15, $f4, $f13 \n\t" + "madd.s $f8, $f8, $f5, $f7 \n\t" + "swc1 $f14, 4(%[out]) \n\t" + "lwc1 $f11, 12(%[in]) \n\t" + "mul.s $f12, $f3, $f13 \n\t" + "mul.s $f16, $f2, $f15 \n\t" + "msub.s $f16, $f16, %[gain], $f11 \n\t" + "sub.s $f16, $f16, $f12 \n\t" + "madd.s $f14, $f16, $f4, $f15 \n\t" + "madd.s $f14, $f14, $f5, $f13 \n\t" + "swc1 $f8, 8(%[out]) \n\t" + "lwc1 $f6, 16(%[in]) \n\t" + "mul.s $f9, $f3, $f15 \n\t" + "mul.s $f7, $f2, $f16 \n\t" + "msub.s $f7, $f7, %[gain], $f6 \n\t" + "sub.s $f7, $f7, $f9 \n\t" + "madd.s $f8, $f7, $f4, $f16 \n\t" + "madd.s $f8, $f8, $f5, $f15 \n\t" + "swc1 $f14, 12(%[out]) \n\t" + "lwc1 $f11, 20(%[in]) \n\t" + "mul.s $f12, $f3, $f16 \n\t" + "mul.s $f13, $f2, $f7 \n\t" + "msub.s $f13, $f13, %[gain], $f11 \n\t" + "sub.s $f13, $f13, $f12 \n\t" + "madd.s $f14, $f13, $f4, $f7 \n\t" + "madd.s $f14, $f14, $f5, $f16 \n\t" + "swc1 $f8, 16(%[out]) \n\t" + "lwc1 $f6, 24(%[in]) \n\t" + "mul.s $f9, $f3, $f7 \n\t" + "mul.s $f15, $f2, $f13 \n\t" + "msub.s $f15, $f15, %[gain], $f6 \n\t" + "sub.s $f1, $f15, $f9 \n\t" + "madd.s $f8, $f1, $f4, $f13 \n\t" + "madd.s $f8, $f8, $f5, $f7 \n\t" + "swc1 $f14, 20(%[out]) \n\t" + "lwc1 $f11, 28(%[in]) \n\t" + "mul.s $f12, $f3, $f13 \n\t" + "mul.s $f16, $f2, $f1 \n\t" + "msub.s $f16, $f16, %[gain], $f11 \n\t" + "sub.s $f0, $f16, $f12 \n\t" + "madd.s $f14, $f0, $f4, $f1 \n\t" + "madd.s $f14, $f14, $f5, $f13 \n\t" + "swc1 $f8, 24(%[out]) \n\t" + "addiu %[out], 32 \n\t" + "addiu %[in], 32 \n\t" + "addiu %[n], -8 \n\t" + "swc1 $f14, -4(%[out]) \n\t" + "bnez %[n], ff_acelp_apply_order_2_transfer_function_madd%= \n\t" + "swc1 $f1, 4(%[mem]) \n\t" + "swc1 $f0, 0(%[mem]) \n\t" + + "ff_acelp_apply_order_2_transfer_function_end%=: \n\t" + + : [out] "+r" (out), + [in] "+r" (in), [gain] "+f" (gain), + [n] "+r" (n), [mem] "+r" (mem) + : [zero_coeffs] "r" (zero_coeffs), + [pole_coeffs] "r" (pole_coeffs) + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", + "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", + "$f12", "$f13", "$f14", "$f15", "$f16", "memory" + ); +} +#endif /* HAVE_INLINE_ASM */ + +void ff_acelp_filter_init_mips(ACELPFContext *c) +{ +#if HAVE_INLINE_ASM + c->acelp_interpolatef = ff_acelp_interpolatef_mips; + c->acelp_apply_order_2_transfer_function = ff_acelp_apply_order_2_transfer_function_mips; +#endif +} diff --git a/ffmpeg/libavcodec/mips/acelp_vectors_mips.c b/ffmpeg/libavcodec/mips/acelp_vectors_mips.c new file mode 100644 index 0000000..8770df8 --- /dev/null +++ b/ffmpeg/libavcodec/mips/acelp_vectors_mips.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * adaptive and fixed codebook vector operations for ACELP-based codecs + * optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/acelp_vectors.c + */ +#include "config.h" +#include "libavcodec/acelp_vectors.h" + +#if HAVE_INLINE_ASM +static void ff_weighted_vector_sumf_mips( + float *out, const float *in_a, const float *in_b, + float weight_coeff_a, float weight_coeff_b, int length) +{ + const float *a_end = in_a + length; + + /* loop unrolled two times */ + __asm__ volatile ( + "blez %[length], ff_weighted_vector_sumf_end%= \n\t" + + "ff_weighted_vector_sumf_madd%=: \n\t" + "lwc1 $f0, 0(%[in_a]) \n\t" + "lwc1 $f3, 4(%[in_a]) \n\t" + "lwc1 $f1, 0(%[in_b]) \n\t" + "lwc1 $f4, 4(%[in_b]) \n\t" + "mul.s $f2, %[weight_coeff_a], $f0 \n\t" + "mul.s $f5, %[weight_coeff_a], $f3 \n\t" + "madd.s $f2, $f2, %[weight_coeff_b], $f1 \n\t" + "madd.s $f5, $f5, %[weight_coeff_b], $f4 \n\t" + "addiu %[in_a], 8 \n\t" + "addiu %[in_b], 8 \n\t" + "swc1 $f2, 0(%[out]) \n\t" + "swc1 $f5, 4(%[out]) \n\t" + "addiu %[out], 8 \n\t" + "bne %[in_a], %[a_end], ff_weighted_vector_sumf_madd%= \n\t" + + "ff_weighted_vector_sumf_end%=: \n\t" + + : [out] "+r" (out), [in_a] "+r" (in_a), [in_b] "+r" (in_b) + : [weight_coeff_a] "f" (weight_coeff_a), + [weight_coeff_b] "f" (weight_coeff_b), + [length] "r" (length), [a_end]"r"(a_end) + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "memory" + ); +} +#endif /* HAVE_INLINE_ASM */ + +void ff_acelp_vectors_init_mips(ACELPVContext *c) +{ +#if HAVE_INLINE_ASM + c->weighted_vector_sumf = ff_weighted_vector_sumf_mips; +#endif +} diff --git a/ffmpeg/libavcodec/mips/amrwbdec_mips.c b/ffmpeg/libavcodec/mips/amrwbdec_mips.c new file mode 100644 index 0000000..1d6ed2d --- /dev/null +++ b/ffmpeg/libavcodec/mips/amrwbdec_mips.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/amrwbdec.c + */ +#include "libavutil/avutil.h" +#include "libavcodec/amrwbdata.h" +#include "amrwbdec_mips.h" + +#if HAVE_INLINE_ASM +void hb_fir_filter_mips(float *out, const float fir_coef[HB_FIR_SIZE + 1], + float mem[HB_FIR_SIZE], const float *in) +{ + int i; + float data[AMRWB_SFR_SIZE_16k + HB_FIR_SIZE]; // past and current samples + + memcpy(data, mem, HB_FIR_SIZE * sizeof(float)); + memcpy(data + HB_FIR_SIZE, in, AMRWB_SFR_SIZE_16k * sizeof(float)); + + for (i = 0; i < AMRWB_SFR_SIZE_16k; i++) { + float output; + float * p_data = (data+i); + + /** + * inner loop is entirely unrolled and instructions are scheduled + * to minimize pipeline stall + */ + __asm__ volatile( + "mtc1 $zero, %[output] \n\t" + "lwc1 $f0, 0(%[p_data]) \n\t" + "lwc1 $f1, 0(%[fir_coef]) \n\t" + "lwc1 $f2, 4(%[p_data]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f3, 4(%[fir_coef]) \n\t" + "lwc1 $f4, 8(%[p_data]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + "lwc1 $f5, 8(%[fir_coef]) \n\t" + + "lwc1 $f0, 12(%[p_data]) \n\t" + "lwc1 $f1, 12(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f2, 16(%[p_data]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f3, 16(%[fir_coef]) \n\t" + "lwc1 $f4, 20(%[p_data]) \n\t" + "lwc1 $f5, 20(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + + "lwc1 $f0, 24(%[p_data]) \n\t" + "lwc1 $f1, 24(%[fir_coef]) \n\t" + "lwc1 $f2, 28(%[p_data]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f3, 28(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f4, 32(%[p_data]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + "lwc1 $f5, 32(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + + "lwc1 $f0, 36(%[p_data]) \n\t" + "lwc1 $f1, 36(%[fir_coef]) \n\t" + "lwc1 $f2, 40(%[p_data]) \n\t" + "lwc1 $f3, 40(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f4, 44(%[p_data]) \n\t" + "lwc1 $f5, 44(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + + "lwc1 $f0, 48(%[p_data]) \n\t" + "lwc1 $f1, 48(%[fir_coef]) \n\t" + "lwc1 $f2, 52(%[p_data]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f3, 52(%[fir_coef]) \n\t" + "lwc1 $f4, 56(%[p_data]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f5, 56(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + + "lwc1 $f0, 60(%[p_data]) \n\t" + "lwc1 $f1, 60(%[fir_coef]) \n\t" + "lwc1 $f2, 64(%[p_data]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f3, 64(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f4, 68(%[p_data]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + "lwc1 $f5, 68(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + + "lwc1 $f0, 72(%[p_data]) \n\t" + "lwc1 $f1, 72(%[fir_coef]) \n\t" + "lwc1 $f2, 76(%[p_data]) \n\t" + "lwc1 $f3, 76(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f4, 80(%[p_data]) \n\t" + "lwc1 $f5, 80(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + + "lwc1 $f0, 84(%[p_data]) \n\t" + "lwc1 $f1, 84(%[fir_coef]) \n\t" + "lwc1 $f2, 88(%[p_data]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f3, 88(%[fir_coef]) \n\t" + "lwc1 $f4, 92(%[p_data]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f5, 92(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + + "lwc1 $f0, 96(%[p_data]) \n\t" + "lwc1 $f1, 96(%[fir_coef]) \n\t" + "lwc1 $f2, 100(%[p_data]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f3, 100(%[fir_coef]) \n\t" + "lwc1 $f4, 104(%[p_data]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f5, 104(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + + "lwc1 $f0, 108(%[p_data]) \n\t" + "lwc1 $f1, 108(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "lwc1 $f2, 112(%[p_data]) \n\t" + "lwc1 $f3, 112(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + "lwc1 $f4, 116(%[p_data]) \n\t" + "lwc1 $f5, 116(%[fir_coef]) \n\t" + "lwc1 $f0, 120(%[p_data]) \n\t" + "madd.s %[output], %[output], $f2, $f3 \n\t" + "lwc1 $f1, 120(%[fir_coef]) \n\t" + "madd.s %[output], %[output], $f4, $f5 \n\t" + "madd.s %[output], %[output], $f0, $f1 \n\t" + + : [output]"=&f"(output) + : [fir_coef]"r"(fir_coef), [p_data]"r"(p_data) + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "memory" + ); + out[i] = output; + } + memcpy(mem, data + AMRWB_SFR_SIZE_16k, HB_FIR_SIZE * sizeof(float)); +} +#endif /* HAVE_INLINE_ASM */ diff --git a/ffmpeg/libavcodec/mips/amrwbdec_mips.h b/ffmpeg/libavcodec/mips/amrwbdec_mips.h new file mode 100644 index 0000000..a469918 --- /dev/null +++ b/ffmpeg/libavcodec/mips/amrwbdec_mips.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/amrwbdec.c + */ +#ifndef AVCODEC_AMRWBDEC_MIPS_H +#define AVCODEC_AMRWBDEC_MIPS_H +#include "config.h" + +#if HAVE_MIPSFPU && HAVE_INLINE_ASM +void hb_fir_filter_mips(float *out, const float fir_coef[], + float mem[], const float *in); +#define hb_fir_filter hb_fir_filter_mips +#endif + +#endif /* AVCODEC_AMRWBDEC_MIPS_H */ diff --git a/ffmpeg/libavcodec/mips/celp_filters_mips.c b/ffmpeg/libavcodec/mips/celp_filters_mips.c new file mode 100644 index 0000000..ef5b07b --- /dev/null +++ b/ffmpeg/libavcodec/mips/celp_filters_mips.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * various filters for CELP-based codecs optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/celp_filters.c + */ +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavcodec/celp_filters.h" + +#if HAVE_INLINE_ASM +static void ff_celp_lp_synthesis_filterf_mips(float *out, + const float *filter_coeffs, + const float* in, int buffer_length, + int filter_length) +{ + int i,n; + + float out0, out1, out2, out3; + float old_out0, old_out1, old_out2, old_out3; + float a,b,c; + const float *p_filter_coeffs; + float *p_out; + + a = filter_coeffs[0]; + b = filter_coeffs[1]; + c = filter_coeffs[2]; + b -= filter_coeffs[0] * filter_coeffs[0]; + c -= filter_coeffs[1] * filter_coeffs[0]; + c -= filter_coeffs[0] * b; + + old_out0 = out[-4]; + old_out1 = out[-3]; + old_out2 = out[-2]; + old_out3 = out[-1]; + for (n = 0; n <= buffer_length - 4; n+=4) { + p_filter_coeffs = filter_coeffs; + p_out = out; + + out0 = in[0]; + out1 = in[1]; + out2 = in[2]; + out3 = in[3]; + + __asm__ volatile( + "lwc1 $f2, 8(%[filter_coeffs]) \n\t" + "lwc1 $f1, 4(%[filter_coeffs]) \n\t" + "lwc1 $f0, 0(%[filter_coeffs]) \n\t" + "nmsub.s %[out0], %[out0], $f2, %[old_out1] \n\t" + "nmsub.s %[out1], %[out1], $f2, %[old_out2] \n\t" + "nmsub.s %[out2], %[out2], $f2, %[old_out3] \n\t" + "lwc1 $f3, 12(%[filter_coeffs]) \n\t" + "nmsub.s %[out0], %[out0], $f1, %[old_out2] \n\t" + "nmsub.s %[out1], %[out1], $f1, %[old_out3] \n\t" + "nmsub.s %[out2], %[out2], $f3, %[old_out2] \n\t" + "nmsub.s %[out0], %[out0], $f0, %[old_out3] \n\t" + "nmsub.s %[out3], %[out3], $f3, %[old_out3] \n\t" + "nmsub.s %[out1], %[out1], $f3, %[old_out1] \n\t" + "nmsub.s %[out0], %[out0], $f3, %[old_out0] \n\t" + + : [out0]"+f"(out0), [out1]"+f"(out1), + [out2]"+f"(out2), [out3]"+f"(out3) + : [old_out0]"f"(old_out0), [old_out1]"f"(old_out1), + [old_out2]"f"(old_out2), [old_out3]"f"(old_out3), + [filter_coeffs]"r"(filter_coeffs) + : "$f0", "$f1", "$f2", "$f3", "$f4", "memory" + ); + + for (i = 5; i <= filter_length; i += 2) { + __asm__ volatile( + "lwc1 %[old_out3], -20(%[p_out]) \n\t" + "lwc1 $f5, 16(%[p_filter_coeffs]) \n\t" + "addiu %[p_out], -8 \n\t" + "addiu %[p_filter_coeffs], 8 \n\t" + "nmsub.s %[out1], %[out1], $f5, %[old_out0] \n\t" + "nmsub.s %[out3], %[out3], $f5, %[old_out2] \n\t" + "lwc1 $f4, 12(%[p_filter_coeffs]) \n\t" + "lwc1 %[old_out2], -16(%[p_out]) \n\t" + "nmsub.s %[out0], %[out0], $f5, %[old_out3] \n\t" + "nmsub.s %[out2], %[out2], $f5, %[old_out1] \n\t" + "nmsub.s %[out1], %[out1], $f4, %[old_out3] \n\t" + "nmsub.s %[out3], %[out3], $f4, %[old_out1] \n\t" + "mov.s %[old_out1], %[old_out3] \n\t" + "nmsub.s %[out0], %[out0], $f4, %[old_out2] \n\t" + "nmsub.s %[out2], %[out2], $f4, %[old_out0] \n\t" + + : [out0]"+f"(out0), [out1]"+f"(out1), + [out2]"+f"(out2), [out3]"+f"(out3), [old_out0]"+f"(old_out0), + [old_out1]"+f"(old_out1), [old_out2]"+f"(old_out2), + [old_out3]"+f"(old_out3),[p_filter_coeffs]"+r"(p_filter_coeffs), + [p_out]"+r"(p_out) + : + : "$f4", "$f5", "memory" + ); + FFSWAP(float, old_out0, old_out2); + } + + __asm__ volatile( + "nmsub.s %[out3], %[out3], %[a], %[out2] \n\t" + "nmsub.s %[out2], %[out2], %[a], %[out1] \n\t" + "nmsub.s %[out3], %[out3], %[b], %[out1] \n\t" + "nmsub.s %[out1], %[out1], %[a], %[out0] \n\t" + "nmsub.s %[out2], %[out2], %[b], %[out0] \n\t" + "nmsub.s %[out3], %[out3], %[c], %[out0] \n\t" + + : [out0]"+f"(out0), [out1]"+f"(out1), + [out2]"+f"(out2), [out3]"+f"(out3) + : [a]"f"(a), [b]"f"(b), [c]"f"(c) + ); + + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + + old_out0 = out0; + old_out1 = out1; + old_out2 = out2; + old_out3 = out3; + + out += 4; + in += 4; + } + + out -= n; + in -= n; + for (; n < buffer_length; n++) { + float out_val, out_val_i, fc_val; + p_filter_coeffs = filter_coeffs; + p_out = &out[n]; + out_val = in[n]; + for (i = 1; i <= filter_length; i++) { + __asm__ volatile( + "lwc1 %[fc_val], 0(%[p_filter_coeffs]) \n\t" + "lwc1 %[out_val_i], -4(%[p_out]) \n\t" + "addiu %[p_filter_coeffs], 4 \n\t" + "addiu %[p_out], -4 \n\t" + "nmsub.s %[out_val], %[out_val], %[fc_val], %[out_val_i] \n\t" + + : [fc_val]"=&f"(fc_val), [out_val]"+f"(out_val), + [out_val_i]"=&f"(out_val_i), [p_out]"+r"(p_out), + [p_filter_coeffs]"+r"(p_filter_coeffs) + : + : "memory" + ); + } + out[n] = out_val; + } +} + +static void ff_celp_lp_zero_synthesis_filterf_mips(float *out, + const float *filter_coeffs, + const float *in, int buffer_length, + int filter_length) +{ + int i,n; + float sum_out8, sum_out7, sum_out6, sum_out5, sum_out4, fc_val; + float sum_out3, sum_out2, sum_out1; + const float *p_filter_coeffs, *p_in; + + for (n = 0; n < buffer_length; n+=8) { + p_in = &in[n]; + p_filter_coeffs = filter_coeffs; + sum_out8 = in[n+7]; + sum_out7 = in[n+6]; + sum_out6 = in[n+5]; + sum_out5 = in[n+4]; + sum_out4 = in[n+3]; + sum_out3 = in[n+2]; + sum_out2 = in[n+1]; + sum_out1 = in[n]; + i = filter_length; + + /* i is always greater than 0 + * outer loop is unrolled eight times so there is less memory access + * inner loop is unrolled two times + */ + __asm__ volatile( + "filt_lp_inner%=: \n\t" + "lwc1 %[fc_val], 0(%[p_filter_coeffs]) \n\t" + "lwc1 $f7, 6*4(%[p_in]) \n\t" + "lwc1 $f6, 5*4(%[p_in]) \n\t" + "lwc1 $f5, 4*4(%[p_in]) \n\t" + "lwc1 $f4, 3*4(%[p_in]) \n\t" + "lwc1 $f3, 2*4(%[p_in]) \n\t" + "lwc1 $f2, 4(%[p_in]) \n\t" + "lwc1 $f1, 0(%[p_in]) \n\t" + "lwc1 $f0, -4(%[p_in]) \n\t" + "addiu %[i], -2 \n\t" + "madd.s %[sum_out8], %[sum_out8], %[fc_val], $f7 \n\t" + "madd.s %[sum_out7], %[sum_out7], %[fc_val], $f6 \n\t" + "madd.s %[sum_out6], %[sum_out6], %[fc_val], $f5 \n\t" + "madd.s %[sum_out5], %[sum_out5], %[fc_val], $f4 \n\t" + "madd.s %[sum_out4], %[sum_out4], %[fc_val], $f3 \n\t" + "madd.s %[sum_out3], %[sum_out3], %[fc_val], $f2 \n\t" + "madd.s %[sum_out2], %[sum_out2], %[fc_val], $f1 \n\t" + "madd.s %[sum_out1], %[sum_out1], %[fc_val], $f0 \n\t" + "lwc1 %[fc_val], 4(%[p_filter_coeffs]) \n\t" + "lwc1 $f7, -8(%[p_in]) \n\t" + "addiu %[p_filter_coeffs], 8 \n\t" + "addiu %[p_in], -8 \n\t" + "madd.s %[sum_out8], %[sum_out8], %[fc_val], $f6 \n\t" + "madd.s %[sum_out7], %[sum_out7], %[fc_val], $f5 \n\t" + "madd.s %[sum_out6], %[sum_out6], %[fc_val], $f4 \n\t" + "madd.s %[sum_out5], %[sum_out5], %[fc_val], $f3 \n\t" + "madd.s %[sum_out4], %[sum_out4], %[fc_val], $f2 \n\t" + "madd.s %[sum_out3], %[sum_out3], %[fc_val], $f1 \n\t" + "madd.s %[sum_out2], %[sum_out2], %[fc_val], $f0 \n\t" + "madd.s %[sum_out1], %[sum_out1], %[fc_val], $f7 \n\t" + "bgtz %[i], filt_lp_inner%= \n\t" + + : [sum_out8]"+f"(sum_out8), [sum_out7]"+f"(sum_out7), + [sum_out6]"+f"(sum_out6), [sum_out5]"+f"(sum_out5), + [sum_out4]"+f"(sum_out4), [sum_out3]"+f"(sum_out3), + [sum_out2]"+f"(sum_out2), [sum_out1]"+f"(sum_out1), + [fc_val]"=&f"(fc_val), [p_filter_coeffs]"+r"(p_filter_coeffs), + [p_in]"+r"(p_in), [i]"+r"(i) + : + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "memory" + ); + + out[n+7] = sum_out8; + out[n+6] = sum_out7; + out[n+5] = sum_out6; + out[n+4] = sum_out5; + out[n+3] = sum_out4; + out[n+2] = sum_out3; + out[n+1] = sum_out2; + out[n] = sum_out1; + } +} +#endif /* HAVE_INLINE_ASM */ + +void ff_celp_filter_init_mips(CELPFContext *c) +{ +#if HAVE_INLINE_ASM + c->celp_lp_synthesis_filterf = ff_celp_lp_synthesis_filterf_mips; + c->celp_lp_zero_synthesis_filterf = ff_celp_lp_zero_synthesis_filterf_mips; +#endif +} diff --git a/ffmpeg/libavcodec/mips/celp_math_mips.c b/ffmpeg/libavcodec/mips/celp_math_mips.c new file mode 100644 index 0000000..d7ccc23 --- /dev/null +++ b/ffmpeg/libavcodec/mips/celp_math_mips.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * Math operations optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/celp_math.c + */ +#include "config.h" +#include "libavcodec/celp_math.h" + +#if HAVE_INLINE_ASM +static float ff_dot_productf_mips(const float* a, const float* b, + int length) +{ + float sum; + const float* a_end = a + length; + + __asm__ volatile ( + "mtc1 $zero, %[sum] \n\t" + "blez %[length], ff_dot_productf_end%= \n\t" + "ff_dot_productf_madd%=: \n\t" + "lwc1 $f2, 0(%[a]) \n\t" + "lwc1 $f1, 0(%[b]) \n\t" + "addiu %[a], %[a], 4 \n\t" + "addiu %[b], %[b], 4 \n\t" + "madd.s %[sum], %[sum], $f1, $f2 \n\t" + "bne %[a], %[a_end], ff_dot_productf_madd%= \n\t" + "ff_dot_productf_end%=: \n\t" + + : [sum] "=&f" (sum), [a] "+r" (a), [b] "+r" (b) + : [a_end]"r"(a_end), [length] "r" (length) + : "$f1", "$f2", "memory" + ); + return sum; +} +#endif /* HAVE_INLINE_ASM */ + +void ff_celp_math_init_mips(CELPMContext *c) +{ +#if HAVE_INLINE_ASM + c->dot_productf = ff_dot_productf_mips; +#endif +} diff --git a/ffmpeg/libavcodec/mips/compute_antialias_fixed.h b/ffmpeg/libavcodec/mips/compute_antialias_fixed.h new file mode 100644 index 0000000..a967f67 --- /dev/null +++ b/ffmpeg/libavcodec/mips/compute_antialias_fixed.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Bojan Zivkovic (bojan@mips.com) + * + * Compute antialias function optimised for MIPS fixed-point architecture + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/mpegaudiodec.c + */ + +#ifndef AVCODEC_MIPS_COMPUTE_ANTIALIAS_FIXED_H +#define AVCODEC_MIPS_COMPUTE_ANTIALIAS_FIXED_H + +#if HAVE_INLINE_ASM +static void compute_antialias_mips_fixed(MPADecodeContext *s, + GranuleDef *g) +{ + int32_t *ptr, *csa; + int n, i; + int MAX_lo = 0xffffffff; + + /* we antialias only "long" bands */ + if (g->block_type == 2) { + if (!g->switch_point) + return; + /* XXX: check this for 8000Hz case */ + n = 1; + } else { + n = SBLIMIT - 1; + } + + + ptr = g->sb_hybrid + 18; + + for(i = n;i > 0;i--) { + int tmp0, tmp1, tmp2, tmp00, tmp11; + int temp_reg1, temp_reg2, temp_reg3, temp_reg4, temp_reg5, temp_reg6; + csa = &csa_table[0][0]; + + /** + * instructions are scheduled to minimize pipeline stall. + */ + __asm__ volatile ( + "lw %[tmp0], -1*4(%[ptr]) \n\t" + "lw %[tmp1], 0*4(%[ptr]) \n\t" + "lw %[temp_reg1], 0*4(%[csa]) \n\t" + "lw %[temp_reg2], 2*4(%[csa]) \n\t" + "add %[tmp2], %[tmp0], %[tmp1] \n\t" + "lw %[temp_reg3], 3*4(%[csa]) \n\t" + "mult $ac0, %[tmp2], %[temp_reg1] \n\t" + "mult $ac1, %[tmp2], %[temp_reg1] \n\t" + "lw %[tmp00], -2*4(%[ptr]) \n\t" + "lw %[tmp11], 1*4(%[ptr]) \n\t" + "lw %[temp_reg4], 4*4(%[csa]) \n\t" + "mtlo %[MAX_lo], $ac0 \n\t" + "mtlo $zero, $ac1 \n\t" + "msub $ac0, %[tmp1], %[temp_reg2] \n\t" + "madd $ac1, %[tmp0], %[temp_reg3] \n\t" + "add %[tmp2], %[tmp00], %[tmp11] \n\t" + "lw %[temp_reg5], 6*4(%[csa]) \n\t" + "mult $ac2, %[tmp2], %[temp_reg4] \n\t" + "mult $ac3, %[tmp2], %[temp_reg4] \n\t" + "mfhi %[temp_reg1], $ac0 \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "lw %[temp_reg6], 7*4(%[csa]) \n\t" + "mtlo %[MAX_lo], $ac2 \n\t" + "msub $ac2, %[tmp11], %[temp_reg5] \n\t" + "mtlo $zero, $ac3 \n\t" + "madd $ac3, %[tmp00], %[temp_reg6] \n\t" + "sll %[temp_reg1], %[temp_reg1], 2 \n\t" + "sw %[temp_reg1], -1*4(%[ptr]) \n\t" + "mfhi %[temp_reg4], $ac2 \n\t" + "sll %[temp_reg2], %[temp_reg2], 2 \n\t" + "mfhi %[temp_reg5], $ac3 \n\t" + "sw %[temp_reg2], 0*4(%[ptr]) \n\t" + "lw %[tmp0], -3*4(%[ptr]) \n\t" + "lw %[tmp1], 2*4(%[ptr]) \n\t" + "lw %[temp_reg1], 8*4(%[csa]) \n\t" + "sll %[temp_reg4], %[temp_reg4], 2 \n\t" + "add %[tmp2], %[tmp0], %[tmp1] \n\t" + "sll %[temp_reg5], %[temp_reg5], 2 \n\t" + "mult $ac0, %[tmp2], %[temp_reg1] \n\t" + "mult $ac1, %[tmp2], %[temp_reg1] \n\t" + "sw %[temp_reg4], -2*4(%[ptr]) \n\t" + "sw %[temp_reg5], 1*4(%[ptr]) \n\t" + "lw %[temp_reg2], 10*4(%[csa]) \n\t" + "mtlo %[MAX_lo], $ac0 \n\t" + "lw %[temp_reg3], 11*4(%[csa]) \n\t" + "msub $ac0, %[tmp1], %[temp_reg2] \n\t" + "mtlo $zero, $ac1 \n\t" + "madd $ac1, %[tmp0], %[temp_reg3] \n\t" + "lw %[tmp00], -4*4(%[ptr]) \n\t" + "lw %[tmp11], 3*4(%[ptr]) \n\t" + "mfhi %[temp_reg1], $ac0 \n\t" + "lw %[temp_reg4], 12*4(%[csa]) \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "add %[tmp2], %[tmp00], %[tmp11] \n\t" + "mult $ac2, %[tmp2], %[temp_reg4] \n\t" + "mult $ac3, %[tmp2], %[temp_reg4] \n\t" + "lw %[temp_reg5], 14*4(%[csa]) \n\t" + "lw %[temp_reg6], 15*4(%[csa]) \n\t" + "sll %[temp_reg1], %[temp_reg1], 2 \n\t" + "mtlo %[MAX_lo], $ac2 \n\t" + "msub $ac2, %[tmp11], %[temp_reg5] \n\t" + "mtlo $zero, $ac3 \n\t" + "madd $ac3, %[tmp00], %[temp_reg6] \n\t" + "sll %[temp_reg2], %[temp_reg2], 2 \n\t" + "sw %[temp_reg1], -3*4(%[ptr]) \n\t" + "mfhi %[temp_reg4], $ac2 \n\t" + "sw %[temp_reg2], 2*4(%[ptr]) \n\t" + "mfhi %[temp_reg5], $ac3 \n\t" + "lw %[tmp0], -5*4(%[ptr]) \n\t" + "lw %[tmp1], 4*4(%[ptr]) \n\t" + "lw %[temp_reg1], 16*4(%[csa]) \n\t" + "lw %[temp_reg2], 18*4(%[csa]) \n\t" + "add %[tmp2], %[tmp0], %[tmp1] \n\t" + "lw %[temp_reg3], 19*4(%[csa]) \n\t" + "mult $ac0, %[tmp2], %[temp_reg1] \n\t" + "mult $ac1, %[tmp2], %[temp_reg1] \n\t" + "sll %[temp_reg4], %[temp_reg4], 2 \n\t" + "sll %[temp_reg5], %[temp_reg5], 2 \n\t" + "sw %[temp_reg4], -4*4(%[ptr]) \n\t" + "mtlo %[MAX_lo], $ac0 \n\t" + "msub $ac0, %[tmp1], %[temp_reg2] \n\t" + "mtlo $zero, $ac1 \n\t" + "madd $ac1, %[tmp0], %[temp_reg3] \n\t" + "sw %[temp_reg5], 3*4(%[ptr]) \n\t" + "lw %[tmp00], -6*4(%[ptr]) \n\t" + "mfhi %[temp_reg1], $ac0 \n\t" + "lw %[tmp11], 5*4(%[ptr]) \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "lw %[temp_reg4], 20*4(%[csa]) \n\t" + "add %[tmp2], %[tmp00], %[tmp11] \n\t" + "lw %[temp_reg5], 22*4(%[csa]) \n\t" + "mult $ac2, %[tmp2], %[temp_reg4] \n\t" + "mult $ac3, %[tmp2], %[temp_reg4] \n\t" + "lw %[temp_reg6], 23*4(%[csa]) \n\t" + "sll %[temp_reg1], %[temp_reg1], 2 \n\t" + "sll %[temp_reg2], %[temp_reg2], 2 \n\t" + "mtlo %[MAX_lo], $ac2 \n\t" + "msub $ac2, %[tmp11], %[temp_reg5] \n\t" + "mtlo $zero, $ac3 \n\t" + "madd $ac3, %[tmp00], %[temp_reg6] \n\t" + "sw %[temp_reg1], -5*4(%[ptr]) \n\t" + "sw %[temp_reg2], 4*4(%[ptr]) \n\t" + "mfhi %[temp_reg4], $ac2 \n\t" + "lw %[tmp0], -7*4(%[ptr]) \n\t" + "mfhi %[temp_reg5], $ac3 \n\t" + "lw %[tmp1], 6*4(%[ptr]) \n\t" + "lw %[temp_reg1], 24*4(%[csa]) \n\t" + "lw %[temp_reg2], 26*4(%[csa]) \n\t" + "add %[tmp2], %[tmp0], %[tmp1] \n\t" + "lw %[temp_reg3], 27*4(%[csa]) \n\t" + "mult $ac0, %[tmp2], %[temp_reg1] \n\t" + "mult $ac1, %[tmp2], %[temp_reg1] \n\t" + "sll %[temp_reg4], %[temp_reg4], 2 \n\t" + "sll %[temp_reg5], %[temp_reg5], 2 \n\t" + "sw %[temp_reg4], -6*4(%[ptr]) \n\t" + "mtlo %[MAX_lo], $ac0 \n\t" + "msub $ac0, %[tmp1], %[temp_reg2] \n\t" + "mtlo $zero, $ac1 \n\t" + "madd $ac1, %[tmp0], %[temp_reg3] \n\t" + "sw %[temp_reg5], 5*4(%[ptr]) \n\t" + "lw %[tmp00], -8*4(%[ptr]) \n\t" + "mfhi %[temp_reg1], $ac0 \n\t" + "lw %[tmp11], 7*4(%[ptr]) \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "lw %[temp_reg4], 28*4(%[csa]) \n\t" + "add %[tmp2], %[tmp00], %[tmp11] \n\t" + "lw %[temp_reg5], 30*4(%[csa]) \n\t" + "mult $ac2, %[tmp2], %[temp_reg4] \n\t" + "mult $ac3, %[tmp2], %[temp_reg4] \n\t" + "lw %[temp_reg6], 31*4(%[csa]) \n\t" + "sll %[temp_reg1], %[temp_reg1], 2 \n\t" + "sll %[temp_reg2], %[temp_reg2], 2 \n\t" + "mtlo %[MAX_lo], $ac2 \n\t" + "msub $ac2, %[tmp11], %[temp_reg5] \n\t" + "mtlo $zero, $ac3 \n\t" + "madd $ac3, %[tmp00], %[temp_reg6] \n\t" + "sw %[temp_reg1], -7*4(%[ptr]) \n\t" + "sw %[temp_reg2], 6*4(%[ptr]) \n\t" + "mfhi %[temp_reg4], $ac2 \n\t" + "mfhi %[temp_reg5], $ac3 \n\t" + "sll %[temp_reg4], %[temp_reg4], 2 \n\t" + "sll %[temp_reg5], %[temp_reg5], 2 \n\t" + "sw %[temp_reg4], -8*4(%[ptr]) \n\t" + "sw %[temp_reg5], 7*4(%[ptr]) \n\t" + + : [tmp0] "=&r" (tmp0), [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), + [tmp00] "=&r" (tmp00), [tmp11] "=&r" (tmp11), + [temp_reg1] "=&r" (temp_reg1), [temp_reg2] "=&r" (temp_reg2), + [temp_reg3] "=&r" (temp_reg3), [temp_reg4] "=&r" (temp_reg4), + [temp_reg5] "=&r" (temp_reg5), [temp_reg6] "=&r" (temp_reg6) + : [csa] "r" (csa), [ptr] "r" (ptr), + [MAX_lo] "r" (MAX_lo) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", + "$ac3hi", "$ac3lo" + ); + + ptr += 18; + } +} +#define compute_antialias compute_antialias_mips_fixed +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_MIPS_COMPUTE_ANTIALIAS_FIXED_H */ diff --git a/ffmpeg/libavcodec/mips/compute_antialias_float.h b/ffmpeg/libavcodec/mips/compute_antialias_float.h new file mode 100644 index 0000000..0f6f03f --- /dev/null +++ b/ffmpeg/libavcodec/mips/compute_antialias_float.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Bojan Zivkovic (bojan@mips.com) + * + * Compute antialias function optimised for MIPS floating-point architecture + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/mpegaudiodec.c + */ + +#ifndef AVCODEC_MIPS_COMPUTE_ANTIALIAS_FLOAT_H +#define AVCODEC_MIPS_COMPUTE_ANTIALIAS_FLOAT_H + +#if HAVE_INLINE_ASM +static void compute_antialias_mips_float(MPADecodeContext *s, + GranuleDef *g) +{ + float *ptr, *ptr_end; + float *csa = &csa_table[0][0]; + int n; + /* temporary variables */ + float in1, in2, in3, in4, in5, in6, in7, in8; + float out1, out2, out3, out4; + + ptr = g->sb_hybrid + 18; + /* we antialias only "long" bands */ + if (g->block_type == 2) { + if (!g->switch_point) + return; + /* XXX: check this for 8000Hz case */ + n = 1; + ptr_end = ptr + 18; + } else { + n = 31; + ptr_end = ptr + 558; + } + + /** + * instructions are scheduled to minimize pipeline stall. + */ + + __asm__ volatile ( + "compute_antialias_float_loop%=: \t\n" + "lwc1 %[in1], -1*4(%[ptr]) \t\n" + "lwc1 %[in2], 0(%[csa]) \t\n" + "lwc1 %[in3], 1*4(%[csa]) \t\n" + "lwc1 %[in4], 0(%[ptr]) \t\n" + "lwc1 %[in5], -2*4(%[ptr]) \t\n" + "lwc1 %[in6], 4*4(%[csa]) \t\n" + "mul.s %[out1], %[in1], %[in2] \t\n" + "mul.s %[out2], %[in1], %[in3] \t\n" + "lwc1 %[in7], 5*4(%[csa]) \t\n" + "lwc1 %[in8], 1*4(%[ptr]) \t\n" + "nmsub.s %[out1], %[out1], %[in3], %[in4] \t\n" + "madd.s %[out2], %[out2], %[in2], %[in4] \t\n" + "mul.s %[out3], %[in5], %[in6] \t\n" + "mul.s %[out4], %[in5], %[in7] \t\n" + "lwc1 %[in1], -3*4(%[ptr]) \t\n" + "swc1 %[out1], -1*4(%[ptr]) \t\n" + "swc1 %[out2], 0(%[ptr]) \t\n" + "nmsub.s %[out3], %[out3], %[in7], %[in8] \t\n" + "madd.s %[out4], %[out4], %[in6], %[in8] \t\n" + "lwc1 %[in2], 8*4(%[csa]) \t\n" + "swc1 %[out3], -2*4(%[ptr]) \t\n" + "swc1 %[out4], 1*4(%[ptr]) \t\n" + "lwc1 %[in3], 9*4(%[csa]) \t\n" + "lwc1 %[in4], 2*4(%[ptr]) \t\n" + "mul.s %[out1], %[in1], %[in2] \t\n" + "lwc1 %[in5], -4*4(%[ptr]) \t\n" + "lwc1 %[in6], 12*4(%[csa]) \t\n" + "mul.s %[out2], %[in1], %[in3] \t\n" + "lwc1 %[in7], 13*4(%[csa]) \t\n" + "nmsub.s %[out1], %[out1], %[in3], %[in4] \t\n" + "lwc1 %[in8], 3*4(%[ptr]) \t\n" + "mul.s %[out3], %[in5], %[in6] \t\n" + "madd.s %[out2], %[out2], %[in2], %[in4] \t\n" + "mul.s %[out4], %[in5], %[in7] \t\n" + "swc1 %[out1], -3*4(%[ptr]) \t\n" + "lwc1 %[in1], -5*4(%[ptr]) \t\n" + "nmsub.s %[out3], %[out3], %[in7], %[in8] \t\n" + "swc1 %[out2], 2*4(%[ptr]) \t\n" + "madd.s %[out4], %[out4], %[in6], %[in8] \t\n" + "lwc1 %[in2], 16*4(%[csa]) \t\n" + "lwc1 %[in3], 17*4(%[csa]) \t\n" + "swc1 %[out3], -4*4(%[ptr]) \t\n" + "lwc1 %[in4], 4*4(%[ptr]) \t\n" + "swc1 %[out4], 3*4(%[ptr]) \t\n" + "mul.s %[out1], %[in1], %[in2] \t\n" + "mul.s %[out2], %[in1], %[in3] \t\n" + "lwc1 %[in5], -6*4(%[ptr]) \t\n" + "lwc1 %[in6], 20*4(%[csa]) \t\n" + "lwc1 %[in7], 21*4(%[csa]) \t\n" + "nmsub.s %[out1], %[out1], %[in3], %[in4] \t\n" + "madd.s %[out2], %[out2], %[in2], %[in4] \t\n" + "lwc1 %[in8], 5*4(%[ptr]) \t\n" + "mul.s %[out3], %[in5], %[in6] \t\n" + "mul.s %[out4], %[in5], %[in7] \t\n" + "swc1 %[out1], -5*4(%[ptr]) \t\n" + "swc1 %[out2], 4*4(%[ptr]) \t\n" + "lwc1 %[in1], -7*4(%[ptr]) \t\n" + "nmsub.s %[out3], %[out3], %[in7], %[in8] \t\n" + "madd.s %[out4], %[out4], %[in6], %[in8] \t\n" + "lwc1 %[in2], 24*4(%[csa]) \t\n" + "lwc1 %[in3], 25*4(%[csa]) \t\n" + "lwc1 %[in4], 6*4(%[ptr]) \t\n" + "swc1 %[out3], -6*4(%[ptr]) \t\n" + "swc1 %[out4], 5*4(%[ptr]) \t\n" + "mul.s %[out1], %[in1], %[in2] \t\n" + "lwc1 %[in5], -8*4(%[ptr]) \t\n" + "mul.s %[out2], %[in1], %[in3] \t\n" + "lwc1 %[in6], 28*4(%[csa]) \t\n" + "lwc1 %[in7], 29*4(%[csa]) \t\n" + "nmsub.s %[out1], %[out1], %[in3], %[in4] \t\n" + "lwc1 %[in8], 7*4(%[ptr]) \t\n" + "madd.s %[out2], %[out2], %[in2], %[in4] \t\n" + "mul.s %[out3], %[in5], %[in6] \t\n" + "mul.s %[out4], %[in5], %[in7] \t\n" + "swc1 %[out1], -7*4(%[ptr]) \t\n" + "swc1 %[out2], 6*4(%[ptr]) \t\n" + "addiu %[ptr], %[ptr], 72 \t\n" + "nmsub.s %[out3], %[out3], %[in7], %[in8] \t\n" + "madd.s %[out4], %[out4], %[in6], %[in8] \t\n" + "swc1 %[out3], -26*4(%[ptr]) \t\n" + "swc1 %[out4], -11*4(%[ptr]) \t\n" + "bne %[ptr], %[ptr_end], compute_antialias_float_loop%= \t\n" + + : [ptr] "+r" (ptr), + [in1] "=&f" (in1), [in2] "=&f" (in2), + [in3] "=&f" (in3), [in4] "=&f" (in4), + [in5] "=&f" (in5), [in6] "=&f" (in6), + [in7] "=&f" (in7), [in8] "=&f" (in8), + [out1] "=&f" (out1), [out2] "=&f" (out2), + [out3] "=&f" (out3), [out4] "=&f" (out4) + : [csa] "r" (csa), [ptr_end] "r" (ptr_end) + : "memory" + ); +} +#define compute_antialias compute_antialias_mips_float +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_MIPS_COMPUTE_ANTIALIAS_FLOAT_H */ diff --git a/ffmpeg/libavcodec/mips/fft_init_table.c b/ffmpeg/libavcodec/mips/fft_init_table.c new file mode 100644 index 0000000..9c2e998 --- /dev/null +++ b/ffmpeg/libavcodec/mips/fft_init_table.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Stanislav Ocovaj (socovaj@mips.com) + * + * 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 + */ + +/** + * @file + * definitions and initialization of LUT table for MIPS FFT + */ +#include "fft_table.h" + +uint16_t fft_offsets_lut[0x2aab]; + +void ff_fft_lut_init(uint16_t *table, int off, int size, int *index) +{ + if (size < 16) { + table[*index] = off >> 2; + (*index)++; + } + else { + ff_fft_lut_init(table, off, size>>1, index); + ff_fft_lut_init(table, off+(size>>1), size>>2, index); + ff_fft_lut_init(table, off+3*(size>>2), size>>2, index); + } +} diff --git a/ffmpeg/libavcodec/mips/fft_mips.c b/ffmpeg/libavcodec/mips/fft_mips.c new file mode 100644 index 0000000..ae4ed30 --- /dev/null +++ b/ffmpeg/libavcodec/mips/fft_mips.c @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Stanislav Ocovaj (socovaj@mips.com) + * Author: Zoran Lukic (zoranl@mips.com) + * + * Optimized MDCT/IMDCT and FFT transforms + * + * 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 "config.h" +#include "libavcodec/fft.h" +#include "fft_table.h" + +/** + * FFT transform + */ + +#if HAVE_INLINE_ASM +static void ff_fft_calc_mips(FFTContext *s, FFTComplex *z) +{ + int nbits, i, n, num_transforms, offset, step; + int n4, n2, n34; + FFTSample tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + FFTComplex *tmpz; + float w_re, w_im; + float *w_re_ptr, *w_im_ptr; + const int fft_size = (1 << s->nbits); + int s_n = s->nbits; + int tem1, tem2; + float pom, pom1, pom2, pom3; + float temp, temp1, temp3, temp4; + FFTComplex * tmpz_n2, * tmpz_n34, * tmpz_n4; + FFTComplex * tmpz_n2_i, * tmpz_n34_i, * tmpz_n4_i, * tmpz_i; + + /** + *num_transforms = (0x2aab >> (16 - s->nbits)) | 1; + */ + __asm__ volatile ( + "li %[tem1], 16 \n\t" + "sub %[s_n], %[tem1], %[s_n] \n\t" + "li %[tem2], 10923 \n\t" + "srav %[tem2], %[tem2], %[s_n] \n\t" + "ori %[num_t],%[tem2], 1 \n\t" + : [num_t]"=r"(num_transforms), [s_n]"+r"(s_n), + [tem1]"=&r"(tem1), [tem2]"=&r"(tem2) + ); + + + for (n=0; n> 1) | 1; + + for (n=0; nnbits; nbits++) { + /* + * num_transforms = (num_transforms >> 1) | 1; + */ + __asm__ volatile ( + "sra %[num_t], %[num_t], 1 \n\t" + "ori %[num_t], %[num_t], 1 \n\t" + + : [num_t] "+r" (num_transforms) + ); + n2 = 2 * n4; + n34 = 3 * n4; + + for (n=0; n>= 1; + n4 <<= 1; + } +} + +/** + * MDCT/IMDCT transforms. + */ + +static void ff_imdct_half_mips(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int k, n8, n4, n2, n, j; + const uint16_t *revtab = s->revtab; + const FFTSample *tcos = s->tcos; + const FFTSample *tsin = s->tsin; + const FFTSample *in1, *in2, *in3, *in4; + FFTComplex *z = (FFTComplex *)output; + + int j1; + const float *tcos1, *tsin1, *tcos2, *tsin2; + float temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, + temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; + FFTComplex *z1, *z2; + + n = 1 << s->mdct_bits; + n2 = n >> 1; + n4 = n >> 2; + n8 = n >> 3; + + /* pre rotation */ + in1 = input; + in2 = input + n2 - 1; + in3 = input + 2; + in4 = input + n2 - 3; + + tcos1 = tcos; + tsin1 = tsin; + + /* n4 = 64 or 128 */ + for(k = 0; k < n4; k += 2) { + j = revtab[k ]; + j1 = revtab[k + 1]; + + __asm__ volatile ( + "lwc1 %[temp1], 0(%[in2]) \t\n" + "lwc1 %[temp2], 0(%[tcos1]) \t\n" + "lwc1 %[temp3], 0(%[tsin1]) \t\n" + "lwc1 %[temp4], 0(%[in1]) \t\n" + "lwc1 %[temp5], 0(%[in4]) \t\n" + "mul.s %[temp9], %[temp1], %[temp2] \t\n" + "mul.s %[temp10], %[temp1], %[temp3] \t\n" + "lwc1 %[temp6], 4(%[tcos1]) \t\n" + "lwc1 %[temp7], 4(%[tsin1]) \t\n" + "nmsub.s %[temp9], %[temp9], %[temp4], %[temp3] \t\n" + "madd.s %[temp10], %[temp10], %[temp4], %[temp2] \t\n" + "mul.s %[temp11], %[temp5], %[temp6] \t\n" + "mul.s %[temp12], %[temp5], %[temp7] \t\n" + "lwc1 %[temp8], 0(%[in3]) \t\n" + "addiu %[tcos1], %[tcos1], 8 \t\n" + "addiu %[tsin1], %[tsin1], 8 \t\n" + "addiu %[in1], %[in1], 16 \t\n" + "nmsub.s %[temp11], %[temp11], %[temp8], %[temp7] \t\n" + "madd.s %[temp12], %[temp12], %[temp8], %[temp6] \t\n" + "addiu %[in2], %[in2], -16 \t\n" + "addiu %[in3], %[in3], 16 \t\n" + "addiu %[in4], %[in4], -16 \t\n" + + : [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), + [temp5]"=&f"(temp5), [temp6]"=&f"(temp6), + [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [temp10]"=&f"(temp10), + [temp11]"=&f"(temp11), [temp12]"=&f"(temp12), + [tsin1]"+r"(tsin1), [tcos1]"+r"(tcos1), + [in1]"+r"(in1), [in2]"+r"(in2), + [in3]"+r"(in3), [in4]"+r"(in4) + : + : "memory" + ); + + z[j ].re = temp9; + z[j ].im = temp10; + z[j1].re = temp11; + z[j1].im = temp12; + } + + s->fft_calc(s, z); + + /* post rotation + reordering */ + /* n8 = 32 or 64 */ + for(k = 0; k < n8; k += 2) { + tcos1 = &tcos[n8 - k - 2]; + tsin1 = &tsin[n8 - k - 2]; + tcos2 = &tcos[n8 + k]; + tsin2 = &tsin[n8 + k]; + z1 = &z[n8 - k - 2]; + z2 = &z[n8 + k ]; + + __asm__ volatile ( + "lwc1 %[temp1], 12(%[z1]) \t\n" + "lwc1 %[temp2], 4(%[tsin1]) \t\n" + "lwc1 %[temp3], 4(%[tcos1]) \t\n" + "lwc1 %[temp4], 8(%[z1]) \t\n" + "lwc1 %[temp5], 4(%[z1]) \t\n" + "mul.s %[temp9], %[temp1], %[temp2] \t\n" + "mul.s %[temp10], %[temp1], %[temp3] \t\n" + "lwc1 %[temp6], 0(%[tsin1]) \t\n" + "lwc1 %[temp7], 0(%[tcos1]) \t\n" + "nmsub.s %[temp9], %[temp9], %[temp4], %[temp3] \t\n" + "madd.s %[temp10], %[temp10], %[temp4], %[temp2] \t\n" + "mul.s %[temp11], %[temp5], %[temp6] \t\n" + "mul.s %[temp12], %[temp5], %[temp7] \t\n" + "lwc1 %[temp8], 0(%[z1]) \t\n" + "lwc1 %[temp1], 4(%[z2]) \t\n" + "lwc1 %[temp2], 0(%[tsin2]) \t\n" + "lwc1 %[temp3], 0(%[tcos2]) \t\n" + "nmsub.s %[temp11], %[temp11], %[temp8], %[temp7] \t\n" + "madd.s %[temp12], %[temp12], %[temp8], %[temp6] \t\n" + "mul.s %[temp13], %[temp1], %[temp2] \t\n" + "mul.s %[temp14], %[temp1], %[temp3] \t\n" + "lwc1 %[temp4], 0(%[z2]) \t\n" + "lwc1 %[temp5], 12(%[z2]) \t\n" + "lwc1 %[temp6], 4(%[tsin2]) \t\n" + "lwc1 %[temp7], 4(%[tcos2]) \t\n" + "nmsub.s %[temp13], %[temp13], %[temp4], %[temp3] \t\n" + "madd.s %[temp14], %[temp14], %[temp4], %[temp2] \t\n" + "mul.s %[temp15], %[temp5], %[temp6] \t\n" + "mul.s %[temp16], %[temp5], %[temp7] \t\n" + "lwc1 %[temp8], 8(%[z2]) \t\n" + "nmsub.s %[temp15], %[temp15], %[temp8], %[temp7] \t\n" + "madd.s %[temp16], %[temp16], %[temp8], %[temp6] \t\n" + : [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), + [temp5]"=&f"(temp5), [temp6]"=&f"(temp6), + [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [temp10]"=&f"(temp10), + [temp11]"=&f"(temp11), [temp12]"=&f"(temp12), + [temp13]"=&f"(temp13), [temp14]"=&f"(temp14), + [temp15]"=&f"(temp15), [temp16]"=&f"(temp16) + : [z1]"r"(z1), [z2]"r"(z2), + [tsin1]"r"(tsin1), [tcos1]"r"(tcos1), + [tsin2]"r"(tsin2), [tcos2]"r"(tcos2) + : "memory" + ); + + z1[1].re = temp9; + z1[1].im = temp14; + z2[0].re = temp13; + z2[0].im = temp10; + + z1[0].re = temp11; + z1[0].im = temp16; + z2[1].re = temp15; + z2[1].im = temp12; + } +} + +/** + * Compute inverse MDCT of size N = 2^nbits + * @param output N samples + * @param input N/2 samples + */ +static void ff_imdct_calc_mips(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int k; + int n = 1 << s->mdct_bits; + int n2 = n >> 1; + int n4 = n >> 2; + + ff_imdct_half_mips(s, output+n4, input); + + for(k = 0; k < n4; k+=4) { + output[k] = -output[n2-k-1]; + output[k+1] = -output[n2-k-2]; + output[k+2] = -output[n2-k-3]; + output[k+3] = -output[n2-k-4]; + + output[n-k-1] = output[n2+k]; + output[n-k-2] = output[n2+k+1]; + output[n-k-3] = output[n2+k+2]; + output[n-k-4] = output[n2+k+3]; + } +} +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_fft_init_mips(FFTContext *s) +{ + int n=0; + + ff_fft_lut_init(fft_offsets_lut, 0, 1 << 16, &n); + ff_init_ff_cos_tabs(16); + +#if HAVE_INLINE_ASM + s->fft_calc = ff_fft_calc_mips; +#if CONFIG_MDCT + s->imdct_calc = ff_imdct_calc_mips; + s->imdct_half = ff_imdct_half_mips; +#endif +#endif +} diff --git a/ffmpeg/libavcodec/mips/fft_table.h b/ffmpeg/libavcodec/mips/fft_table.h new file mode 100644 index 0000000..dd52eaf --- /dev/null +++ b/ffmpeg/libavcodec/mips/fft_table.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Stanislav Ocovaj (socovaj@mips.com) + * + * 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 + */ + +/** + * @file + * definitions and LUT table for MIPS FFT + */ +#ifndef AVCODEC_MIPS_FFT_TABLE_H +#define AVCODEC_MIPS_FFT_TABLE_H + +#include "libavcodec/fft.h" + +#define MAX_LOG2_NFFT 16 //!< Specifies maxiumum allowed fft size +#define MAX_FFT_SIZE (1 << MAX_LOG2_NFFT) + +extern uint16_t fft_offsets_lut[]; +void ff_fft_lut_init(uint16_t *table, int off, int size, int *index); + +#endif /* AVCODEC_MIPS_FFT_TABLE_H */ diff --git a/ffmpeg/libavcodec/mips/fmtconvert_mips.c b/ffmpeg/libavcodec/mips/fmtconvert_mips.c new file mode 100644 index 0000000..8a0265f --- /dev/null +++ b/ffmpeg/libavcodec/mips/fmtconvert_mips.c @@ -0,0 +1,342 @@ +/* + * Format Conversion Utils for MIPS + * + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of is + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Zoran Lukic (zoranl@mips.com) + * Author: Nedeljko Babic (nbabic@mips.com) + * + * 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 "config.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/fmtconvert.h" + +#if HAVE_INLINE_ASM +#if HAVE_MIPSDSPR1 +static void float_to_int16_mips(int16_t *dst, const float *src, long len) +{ + const float *src_end = src + len; + int ret0, ret1, ret2, ret3, ret4, ret5, ret6, ret7; + float src0, src1, src2, src3, src4, src5, src6, src7; + + /* + * loop is 8 times unrolled in assembler in order to achieve better performance + */ + __asm__ volatile( + "beq %[len], $zero, fti16_end%= \n\t" + "fti16_lp%=: \n\t" + "lwc1 %[src0], 0(%[src]) \n\t" + "lwc1 %[src1], 4(%[src]) \n\t" + "lwc1 %[src2], 8(%[src]) \n\t" + "lwc1 %[src3], 12(%[src]) \n\t" + "cvt.w.s %[src0], %[src0] \n\t" + "cvt.w.s %[src1], %[src1] \n\t" + "cvt.w.s %[src2], %[src2] \n\t" + "cvt.w.s %[src3], %[src3] \n\t" + "mfc1 %[ret0], %[src0] \n\t" + "mfc1 %[ret1], %[src1] \n\t" + "mfc1 %[ret2], %[src2] \n\t" + "mfc1 %[ret3], %[src3] \n\t" + "lwc1 %[src4], 16(%[src]) \n\t" + "lwc1 %[src5], 20(%[src]) \n\t" + "lwc1 %[src6], 24(%[src]) \n\t" + "lwc1 %[src7], 28(%[src]) \n\t" + "cvt.w.s %[src4], %[src4] \n\t" + "cvt.w.s %[src5], %[src5] \n\t" + "cvt.w.s %[src6], %[src6] \n\t" + "cvt.w.s %[src7], %[src7] \n\t" + "addiu %[src], 32 \n\t" + "shll_s.w %[ret0], %[ret0], 16 \n\t" + "shll_s.w %[ret1], %[ret1], 16 \n\t" + "shll_s.w %[ret2], %[ret2], 16 \n\t" + "shll_s.w %[ret3], %[ret3], 16 \n\t" + "srl %[ret0], %[ret0], 16 \n\t" + "srl %[ret1], %[ret1], 16 \n\t" + "srl %[ret2], %[ret2], 16 \n\t" + "srl %[ret3], %[ret3], 16 \n\t" + "sh %[ret0], 0(%[dst]) \n\t" + "sh %[ret1], 2(%[dst]) \n\t" + "sh %[ret2], 4(%[dst]) \n\t" + "sh %[ret3], 6(%[dst]) \n\t" + "mfc1 %[ret4], %[src4] \n\t" + "mfc1 %[ret5], %[src5] \n\t" + "mfc1 %[ret6], %[src6] \n\t" + "mfc1 %[ret7], %[src7] \n\t" + "shll_s.w %[ret4], %[ret4], 16 \n\t" + "shll_s.w %[ret5], %[ret5], 16 \n\t" + "shll_s.w %[ret6], %[ret6], 16 \n\t" + "shll_s.w %[ret7], %[ret7], 16 \n\t" + "srl %[ret4], %[ret4], 16 \n\t" + "srl %[ret5], %[ret5], 16 \n\t" + "srl %[ret6], %[ret6], 16 \n\t" + "srl %[ret7], %[ret7], 16 \n\t" + "sh %[ret4], 8(%[dst]) \n\t" + "sh %[ret5], 10(%[dst]) \n\t" + "sh %[ret6], 12(%[dst]) \n\t" + "sh %[ret7], 14(%[dst]) \n\t" + "addiu %[dst], 16 \n\t" + "bne %[src], %[src_end], fti16_lp%= \n\t" + "fti16_end%=: \n\t" + : [ret0]"=&r"(ret0), [ret1]"=&r"(ret1), [ret2]"=&r"(ret2), [ret3]"=&r"(ret3), + [ret4]"=&r"(ret4), [ret5]"=&r"(ret5), [ret6]"=&r"(ret6), [ret7]"=&r"(ret7), + [src0]"=&f"(src0), [src1]"=&f"(src1), [src2]"=&f"(src2), [src3]"=&f"(src3), + [src4]"=&f"(src4), [src5]"=&f"(src5), [src6]"=&f"(src6), [src7]"=&f"(src7), + [src]"+r"(src), [dst]"+r"(dst) + : [src_end]"r"(src_end), [len]"r"(len) + : "memory" + ); +} + +static void float_to_int16_interleave_mips(int16_t *dst, const float **src, long len, + int channels) +{ + int c, ch2 = channels <<1; + int ret0, ret1, ret2, ret3, ret4, ret5, ret6, ret7; + float src0, src1, src2, src3, src4, src5, src6, src7; + int16_t *dst_ptr0, *dst_ptr1, *dst_ptr2, *dst_ptr3; + int16_t *dst_ptr4, *dst_ptr5, *dst_ptr6, *dst_ptr7; + const float *src_ptr, *src_ptr2, *src_end; + + if (channels == 2) { + src_ptr = &src[0][0]; + src_ptr2 = &src[1][0]; + src_end = src_ptr + len; + + __asm__ volatile ( + "fti16i2_lp%=: \n\t" + "lwc1 %[src0], 0(%[src_ptr]) \n\t" + "lwc1 %[src1], 0(%[src_ptr2]) \n\t" + "addiu %[src_ptr], 4 \n\t" + "cvt.w.s $f9, %[src0] \n\t" + "cvt.w.s $f10, %[src1] \n\t" + "mfc1 %[ret0], $f9 \n\t" + "mfc1 %[ret1], $f10 \n\t" + "shll_s.w %[ret0], %[ret0], 16 \n\t" + "shll_s.w %[ret1], %[ret1], 16 \n\t" + "addiu %[src_ptr2], 4 \n\t" + "srl %[ret0], %[ret0], 16 \n\t" + "srl %[ret1], %[ret1], 16 \n\t" + "sh %[ret0], 0(%[dst]) \n\t" + "sh %[ret1], 2(%[dst]) \n\t" + "addiu %[dst], 4 \n\t" + "bne %[src_ptr], %[src_end], fti16i2_lp%= \n\t" + : [ret0]"=&r"(ret0), [ret1]"=&r"(ret1), + [src0]"=&f"(src0), [src1]"=&f"(src1), + [src_ptr]"+r"(src_ptr), [src_ptr2]"+r"(src_ptr2), + [dst]"+r"(dst) + : [src_end]"r"(src_end) + : "memory" + ); + } else { + for (c = 0; c < channels; c++) { + src_ptr = &src[c][0]; + dst_ptr0 = &dst[c]; + src_end = src_ptr + len; + /* + * loop is 8 times unrolled in assembler in order to achieve better performance + */ + __asm__ volatile( + "fti16i_lp%=: \n\t" + "lwc1 %[src0], 0(%[src_ptr]) \n\t" + "lwc1 %[src1], 4(%[src_ptr]) \n\t" + "lwc1 %[src2], 8(%[src_ptr]) \n\t" + "lwc1 %[src3], 12(%[src_ptr]) \n\t" + "cvt.w.s %[src0], %[src0] \n\t" + "cvt.w.s %[src1], %[src1] \n\t" + "cvt.w.s %[src2], %[src2] \n\t" + "cvt.w.s %[src3], %[src3] \n\t" + "mfc1 %[ret0], %[src0] \n\t" + "mfc1 %[ret1], %[src1] \n\t" + "mfc1 %[ret2], %[src2] \n\t" + "mfc1 %[ret3], %[src3] \n\t" + "lwc1 %[src4], 16(%[src_ptr]) \n\t" + "lwc1 %[src5], 20(%[src_ptr]) \n\t" + "lwc1 %[src6], 24(%[src_ptr]) \n\t" + "lwc1 %[src7], 28(%[src_ptr]) \n\t" + "addu %[dst_ptr1], %[dst_ptr0], %[ch2] \n\t" + "addu %[dst_ptr2], %[dst_ptr1], %[ch2] \n\t" + "addu %[dst_ptr3], %[dst_ptr2], %[ch2] \n\t" + "addu %[dst_ptr4], %[dst_ptr3], %[ch2] \n\t" + "addu %[dst_ptr5], %[dst_ptr4], %[ch2] \n\t" + "addu %[dst_ptr6], %[dst_ptr5], %[ch2] \n\t" + "addu %[dst_ptr7], %[dst_ptr6], %[ch2] \n\t" + "addiu %[src_ptr], 32 \n\t" + "cvt.w.s %[src4], %[src4] \n\t" + "cvt.w.s %[src5], %[src5] \n\t" + "cvt.w.s %[src6], %[src6] \n\t" + "cvt.w.s %[src7], %[src7] \n\t" + "shll_s.w %[ret0], %[ret0], 16 \n\t" + "shll_s.w %[ret1], %[ret1], 16 \n\t" + "shll_s.w %[ret2], %[ret2], 16 \n\t" + "shll_s.w %[ret3], %[ret3], 16 \n\t" + "srl %[ret0], %[ret0], 16 \n\t" + "srl %[ret1], %[ret1], 16 \n\t" + "srl %[ret2], %[ret2], 16 \n\t" + "srl %[ret3], %[ret3], 16 \n\t" + "sh %[ret0], 0(%[dst_ptr0]) \n\t" + "sh %[ret1], 0(%[dst_ptr1]) \n\t" + "sh %[ret2], 0(%[dst_ptr2]) \n\t" + "sh %[ret3], 0(%[dst_ptr3]) \n\t" + "mfc1 %[ret4], %[src4] \n\t" + "mfc1 %[ret5], %[src5] \n\t" + "mfc1 %[ret6], %[src6] \n\t" + "mfc1 %[ret7], %[src7] \n\t" + "shll_s.w %[ret4], %[ret4], 16 \n\t" + "shll_s.w %[ret5], %[ret5], 16 \n\t" + "shll_s.w %[ret6], %[ret6], 16 \n\t" + "shll_s.w %[ret7], %[ret7], 16 \n\t" + "srl %[ret4], %[ret4], 16 \n\t" + "srl %[ret5], %[ret5], 16 \n\t" + "srl %[ret6], %[ret6], 16 \n\t" + "srl %[ret7], %[ret7], 16 \n\t" + "sh %[ret4], 0(%[dst_ptr4]) \n\t" + "sh %[ret5], 0(%[dst_ptr5]) \n\t" + "sh %[ret6], 0(%[dst_ptr6]) \n\t" + "sh %[ret7], 0(%[dst_ptr7]) \n\t" + "addu %[dst_ptr0], %[dst_ptr7], %[ch2] \n\t" + "bne %[src_ptr], %[src_end], fti16i_lp%= \n\t" + : [ret0]"=&r"(ret0), [ret1]"=&r"(ret1), [ret2]"=&r"(ret2), [ret3]"=&r"(ret3), + [ret4]"=&r"(ret4), [ret5]"=&r"(ret5), [ret6]"=&r"(ret6), [ret7]"=&r"(ret7), + [src0]"=&f"(src0), [src1]"=&f"(src1), [src2]"=&f"(src2), [src3]"=&f"(src3), + [src4]"=&f"(src4), [src5]"=&f"(src5), [src6]"=&f"(src6), [src7]"=&f"(src7), + [dst_ptr1]"=&r"(dst_ptr1), [dst_ptr2]"=&r"(dst_ptr2), [dst_ptr3]"=&r"(dst_ptr3), + [dst_ptr4]"=&r"(dst_ptr4), [dst_ptr5]"=&r"(dst_ptr5), [dst_ptr6]"=&r"(dst_ptr6), + [dst_ptr7]"=&r"(dst_ptr7), [dst_ptr0]"+r"(dst_ptr0), [src_ptr]"+r"(src_ptr) + : [ch2]"r"(ch2), [src_end]"r"(src_end) + : "memory" + ); + } + } +} +#endif /* HAVE_MIPSDSPR1 */ + +static void int32_to_float_fmul_scalar_mips(float *dst, const int *src, + float mul, int len) +{ + /* + * variables used in inline assembler + */ + float temp1, temp3, temp5, temp7, temp9, temp11, temp13, temp15; + + int rpom1, rpom2, rpom11, rpom21, rpom12, rpom22, rpom13, rpom23; + const int *src_end = src + len; + /* + * loop is 8 times unrolled in assembler in order to achieve better performance + */ + __asm__ volatile ( + "i32tf_lp%=: \n\t" + "lw %[rpom11], 0(%[src]) \n\t" + "lw %[rpom21], 4(%[src]) \n\t" + "lw %[rpom1], 8(%[src]) \n\t" + "lw %[rpom2], 12(%[src]) \n\t" + "mtc1 %[rpom11], %[temp1] \n\t" + "mtc1 %[rpom21], %[temp3] \n\t" + "mtc1 %[rpom1], %[temp5] \n\t" + "mtc1 %[rpom2], %[temp7] \n\t" + + "lw %[rpom13], 16(%[src]) \n\t" + "lw %[rpom23], 20(%[src]) \n\t" + "lw %[rpom12], 24(%[src]) \n\t" + "lw %[rpom22], 28(%[src]) \n\t" + "mtc1 %[rpom13], %[temp9] \n\t" + "mtc1 %[rpom23], %[temp11] \n\t" + "mtc1 %[rpom12], %[temp13] \n\t" + "mtc1 %[rpom22], %[temp15] \n\t" + + "addiu %[src], 32 \n\t" + "cvt.s.w %[temp1], %[temp1] \n\t" + "cvt.s.w %[temp3], %[temp3] \n\t" + "cvt.s.w %[temp5], %[temp5] \n\t" + "cvt.s.w %[temp7], %[temp7] \n\t" + + "cvt.s.w %[temp9], %[temp9] \n\t" + "cvt.s.w %[temp11], %[temp11] \n\t" + "cvt.s.w %[temp13], %[temp13] \n\t" + "cvt.s.w %[temp15], %[temp15] \n\t" + + "mul.s %[temp1], %[temp1], %[mul] \n\t" + "mul.s %[temp3], %[temp3], %[mul] \n\t" + "mul.s %[temp5], %[temp5], %[mul] \n\t" + "mul.s %[temp7], %[temp7], %[mul] \n\t" + + "mul.s %[temp9], %[temp9], %[mul] \n\t" + "mul.s %[temp11], %[temp11], %[mul] \n\t" + "mul.s %[temp13], %[temp13], %[mul] \n\t" + "mul.s %[temp15], %[temp15], %[mul] \n\t" + + "swc1 %[temp1], 0(%[dst]) \n\t" /*dst[i] = src[i] * mul; */ + "swc1 %[temp3], 4(%[dst]) \n\t" /*dst[i+1] = src[i+1] * mul;*/ + "swc1 %[temp5], 8(%[dst]) \n\t" /*dst[i+2] = src[i+2] * mul;*/ + "swc1 %[temp7], 12(%[dst]) \n\t" /*dst[i+3] = src[i+3] * mul;*/ + + "swc1 %[temp9], 16(%[dst]) \n\t" /*dst[i+4] = src[i+4] * mul;*/ + "swc1 %[temp11], 20(%[dst]) \n\t" /*dst[i+5] = src[i+5] * mul;*/ + "swc1 %[temp13], 24(%[dst]) \n\t" /*dst[i+6] = src[i+6] * mul;*/ + "swc1 %[temp15], 28(%[dst]) \n\t" /*dst[i+7] = src[i+7] * mul;*/ + "addiu %[dst], 32 \n\t" + "bne %[src], %[src_end], i32tf_lp%= \n\t" + : [temp1]"=&f"(temp1), [temp11]"=&f"(temp11), + [temp13]"=&f"(temp13), [temp15]"=&f"(temp15), + [temp3]"=&f"(temp3), [temp5]"=&f"(temp5), + [temp7]"=&f"(temp7), [temp9]"=&f"(temp9), + [rpom1]"=&r"(rpom1), [rpom2]"=&r"(rpom2), + [rpom11]"=&r"(rpom11), [rpom21]"=&r"(rpom21), + [rpom12]"=&r"(rpom12), [rpom22]"=&r"(rpom22), + [rpom13]"=&r"(rpom13), [rpom23]"=&r"(rpom23), + [dst]"+r"(dst), [src]"+r"(src) + : [mul]"f"(mul), [src_end]"r"(src_end) + : "memory" + ); +} +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_fmt_convert_init_mips(FmtConvertContext *c) +{ +#if HAVE_INLINE_ASM +#if HAVE_MIPSDSPR1 + c->float_to_int16_interleave = float_to_int16_interleave_mips; + c->float_to_int16 = float_to_int16_mips; +#endif + c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_mips; +#endif +} diff --git a/ffmpeg/libavcodec/mips/iirfilter_mips.c b/ffmpeg/libavcodec/mips/iirfilter_mips.c new file mode 100644 index 0000000..a5646cd --- /dev/null +++ b/ffmpeg/libavcodec/mips/iirfilter_mips.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Bojan Zivkovic (bojan@mips.com) + * + * IIR filter optimized for MIPS floating-point architecture + * + * 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 + */ + + /** + * @file + * Reference: libavcodec/iirfilter.c + */ + +#include "libavcodec/iirfilter.h" + +#if HAVE_INLINE_ASM +typedef struct FFIIRFilterCoeffs { + int order; + float gain; + int *cx; + float *cy; +} FFIIRFilterCoeffs; + +typedef struct FFIIRFilterState { + float x[1]; +} FFIIRFilterState; + +static void ff_iir_filter_flt_mips(const struct FFIIRFilterCoeffs *c, + struct FFIIRFilterState *s, int size, + const float *src, int sstep, float *dst, int dstep) +{ + if (c->order == 2) { + int i; + const float *src0 = src; + float *dst0 = dst; + for (i = 0; i < size; i++) { + float in = *src0 * c->gain + s->x[0] * c->cy[0] + s->x[1] * c->cy[1]; + *dst0 = s->x[0] + in + s->x[1] * c->cx[1]; + s->x[0] = s->x[1]; + s->x[1] = in; + src0 += sstep; + dst0 += dstep; + } + } else if (c->order == 4) { + int i; + const float *src0 = src; + float *dst0 = dst; + float four = 4.0; + float six = 6.0; + for (i = 0; i < size; i += 4) { + float in1, in2, in3, in4; + float res1, res2, res3, res4; + float *x = s->x; + float *cy = c->cy; + float gain = c->gain; + float src0_0 = src0[0 ]; + float src0_1 = src0[sstep ]; + float src0_2 = src0[2*sstep]; + float src0_3 = src0[3*sstep]; + + __asm__ volatile ( + "lwc1 $f0, 0(%[cy]) \n\t" + "lwc1 $f4, 0(%[x]) \n\t" + "lwc1 $f5, 4(%[x]) \n\t" + "lwc1 $f6, 8(%[x]) \n\t" + "lwc1 $f7, 12(%[x]) \n\t" + "mul.s %[in1], %[src0_0], %[gain] \n\t" + "mul.s %[in2], %[src0_1], %[gain] \n\t" + "mul.s %[in3], %[src0_2], %[gain] \n\t" + "mul.s %[in4], %[src0_3], %[gain] \n\t" + "lwc1 $f1, 4(%[cy]) \n\t" + "madd.s %[in1], %[in1], $f0, $f4 \n\t" + "madd.s %[in2], %[in2], $f0, $f5 \n\t" + "madd.s %[in3], %[in3], $f0, $f6 \n\t" + "madd.s %[in4], %[in4], $f0, $f7 \n\t" + "lwc1 $f2, 8(%[cy]) \n\t" + "madd.s %[in1], %[in1], $f1, $f5 \n\t" + "madd.s %[in2], %[in2], $f1, $f6 \n\t" + "madd.s %[in3], %[in3], $f1, $f7 \n\t" + "lwc1 $f3, 12(%[cy]) \n\t" + "add.s $f8, $f5, $f7 \n\t" + "madd.s %[in1], %[in1], $f2, $f6 \n\t" + "madd.s %[in2], %[in2], $f2, $f7 \n\t" + "mul.s $f9, $f6, %[six] \n\t" + "mul.s $f10, $f7, %[six] \n\t" + "madd.s %[in1], %[in1], $f3, $f7 \n\t" + "madd.s %[in2], %[in2], $f3, %[in1] \n\t" + "madd.s %[in3], %[in3], $f2, %[in1] \n\t" + "madd.s %[in4], %[in4], $f1, %[in1] \n\t" + "add.s %[res1], $f4, %[in1] \n\t" + "swc1 %[in1], 0(%[x]) \n\t" + "add.s $f0, $f6, %[in1] \n\t" + "madd.s %[in3], %[in3], $f3, %[in2] \n\t" + "madd.s %[in4], %[in4], $f2, %[in2] \n\t" + "add.s %[res2], $f5, %[in2] \n\t" + "madd.s %[res1], %[res1], $f8, %[four] \n\t" + "add.s $f8, $f7, %[in2] \n\t" + "swc1 %[in2], 4(%[x]) \n\t" + "madd.s %[in4], %[in4], $f3, %[in3] \n\t" + "add.s %[res3], $f6, %[in3] \n\t" + "add.s %[res1], %[res1], $f9 \n\t" + "madd.s %[res2], %[res2], $f0, %[four] \n\t" + "swc1 %[in3], 8(%[x]) \n\t" + "add.s %[res4], $f7, %[in4] \n\t" + "madd.s %[res3], %[res3], $f8, %[four] \n\t" + "swc1 %[in4], 12(%[x]) \n\t" + "add.s %[res2], %[res2], $f10 \n\t" + "add.s $f8, %[in1], %[in3] \n\t" + "madd.s %[res3], %[res3], %[in1], %[six] \n\t" + "madd.s %[res4], %[res4], $f8, %[four] \n\t" + "madd.s %[res4], %[res4], %[in2], %[six] \n\t" + + : [in1]"=&f"(in1), [in2]"=&f"(in2), + [in3]"=&f"(in3), [in4]"=&f"(in4), + [res1]"=&f"(res1), [res2]"=&f"(res2), + [res3]"=&f"(res3), [res4]"=&f"(res4) + : [src0_0]"f"(src0_0), [src0_1]"f"(src0_1), + [src0_2]"f"(src0_2), [src0_3]"f"(src0_3), + [gain]"f"(gain), [x]"r"(x), [cy]"r"(cy), + [four]"f"(four), [six]"f"(six) + : "$f0", "$f1", "$f2", "$f3", + "$f4", "$f5", "$f6", "$f7", + "$f8", "$f9", "$f10", + "memory" + ); + + dst0[0 ] = res1; + dst0[sstep ] = res2; + dst0[2*sstep] = res3; + dst0[3*sstep] = res4; + + src0 += 4*sstep; + dst0 += 4*dstep; + } + } else { + int i; + const float *src0 = src; + float *dst0 = dst; + for (i = 0; i < size; i++) { + int j; + float in, res; + in = *src0 * c->gain; + for(j = 0; j < c->order; j++) + in += c->cy[j] * s->x[j]; + res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1]; + for(j = 1; j < c->order >> 1; j++) + res += (s->x[j] + s->x[c->order - j]) * c->cx[j]; + for(j = 0; j < c->order - 1; j++) + s->x[j] = s->x[j + 1]; + *dst0 = res; + s->x[c->order - 1] = in; + src0 += sstep; + dst0 += dstep; + } + } +} +#endif /* HAVE_INLINE_ASM */ + +void ff_iir_filter_init_mips(FFIIRFilterContext *f) { +#if HAVE_INLINE_ASM + f->filter_flt = ff_iir_filter_flt_mips; +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/mips/lsp_mips.h b/ffmpeg/libavcodec/mips/lsp_mips.h new file mode 100644 index 0000000..c55ef03 --- /dev/null +++ b/ffmpeg/libavcodec/mips/lsp_mips.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nedeljko Babic (nbabic@mips.com) + * + * LSP routines for ACELP-based codecs optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/lsp.c + */ +#ifndef AVCODEC_LSP_MIPS_H +#define AVCODEC_LSP_MIPS_H + +#if HAVE_MIPSFPU && HAVE_INLINE_ASM +static av_always_inline void ff_lsp2polyf_mips(const double *lsp, double *f, int lp_half_order) +{ + int i, j = 0; + double * p_fi = f; + double * p_f = 0; + + f[0] = 1.0; + f[1] = -2 * lsp[0]; + lsp -= 2; + + for(i=2; i<=lp_half_order; i++) + { + double tmp, f_j_2, f_j_1, f_j; + double val = lsp[2*i]; + + __asm__ volatile( + "move %[p_f], %[p_fi] \n\t" + "add.d %[val], %[val], %[val] \n\t" + "addiu %[p_fi], 8 \n\t" + "ldc1 %[f_j_1], 0(%[p_f]) \n\t" + "ldc1 %[f_j], 8(%[p_f]) \n\t" + "neg.d %[val], %[val] \n\t" + "add.d %[tmp], %[f_j_1], %[f_j_1] \n\t" + "madd.d %[tmp], %[tmp], %[f_j], %[val] \n\t" + "addiu %[j], %[i], -2 \n\t" + "ldc1 %[f_j_2], -8(%[p_f]) \n\t" + "sdc1 %[tmp], 16(%[p_f]) \n\t" + "beqz %[j], ff_lsp2polyf_lp_j_end%= \n\t" + "ff_lsp2polyf_lp_j%=: \n\t" + "add.d %[tmp], %[f_j], %[f_j_2] \n\t" + "madd.d %[tmp], %[tmp], %[f_j_1], %[val] \n\t" + "mov.d %[f_j], %[f_j_1] \n\t" + "addiu %[j], -1 \n\t" + "mov.d %[f_j_1], %[f_j_2] \n\t" + "ldc1 %[f_j_2], -16(%[p_f]) \n\t" + "sdc1 %[tmp], 8(%[p_f]) \n\t" + "addiu %[p_f], -8 \n\t" + "bgtz %[j], ff_lsp2polyf_lp_j%= \n\t" + "ff_lsp2polyf_lp_j_end%=: \n\t" + + : [f_j_2]"=&f"(f_j_2), [f_j_1]"=&f"(f_j_1), [val]"+f"(val), + [tmp]"=&f"(tmp), [f_j]"=&f"(f_j), [p_f]"+r"(p_f), + [j]"+r"(j), [p_fi]"+r"(p_fi) + : [i]"r"(i) + : "memory" + ); + f[1] += val; + } +} +#define ff_lsp2polyf ff_lsp2polyf_mips +#endif /* HAVE_MIPSFPU && HAVE_INLINE_ASM */ +#endif /* AVCODEC_LSP_MIPS_H */ diff --git a/ffmpeg/libavcodec/mips/mathops.h b/ffmpeg/libavcodec/mips/mathops.h new file mode 100644 index 0000000..368290a --- /dev/null +++ b/ffmpeg/libavcodec/mips/mathops.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_MIPS_MATHOPS_H +#define AVCODEC_MIPS_MATHOPS_H + +#include +#include "config.h" +#include "libavutil/common.h" + +#if HAVE_INLINE_ASM + +#if HAVE_LOONGSON + +static inline av_const int64_t MAC64(int64_t d, int a, int b) +{ + int64_t m; + __asm__ ("dmult.g %1, %2, %3 \n\t" + "daddu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b)); + return d; +} +#define MAC64(d, a, b) ((d) = MAC64(d, a, b)) + +static inline av_const int64_t MLS64(int64_t d, int a, int b) +{ + int64_t m; + __asm__ ("dmult.g %1, %2, %3 \n\t" + "dsubu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b)); + return d; +} +#define MLS64(d, a, b) ((d) = MLS64(d, a, b)) + +#elif ARCH_MIPS64 + +static inline av_const int64_t MAC64(int64_t d, int a, int b) +{ + int64_t m; + __asm__ ("dmult %2, %3 \n\t" + "mflo %1 \n\t" + "daddu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b) + : "hi", "lo"); + return d; +} +#define MAC64(d, a, b) ((d) = MAC64(d, a, b)) + +static inline av_const int64_t MLS64(int64_t d, int a, int b) +{ + int64_t m; + __asm__ ("dmult %2, %3 \n\t" + "mflo %1 \n\t" + "dsubu %0, %0, %1 \n\t" + : "+r"(d), "=&r"(m) : "r"(a), "r"(b) + : "hi", "lo"); + return d; +} +#define MLS64(d, a, b) ((d) = MLS64(d, a, b)) + +#endif + +#endif /* HAVE_INLINE_ASM */ + +#endif /* AVCODEC_MIPS_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/mips/mpegaudiodsp_mips_fixed.c b/ffmpeg/libavcodec/mips/mpegaudiodsp_mips_fixed.c new file mode 100644 index 0000000..047a833 --- /dev/null +++ b/ffmpeg/libavcodec/mips/mpegaudiodsp_mips_fixed.c @@ -0,0 +1,907 @@ + /* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Bojan Zivkovic (bojan@mips.com) + * + * MPEG Audio decoder optimized for MIPS fixed-point architecture + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/mpegaudiodsp_template.c + */ + +#include + +#include "libavcodec/mpegaudiodsp.h" + +static void ff_mpadsp_apply_window_mips_fixed(int32_t *synth_buf, int32_t *window, + int *dither_state, int16_t *samples, int incr) +{ + register const int32_t *w, *w2, *p; + int j; + int16_t *samples2; + int w_asm, p_asm, w_asm1, p_asm1, w_asm2, p_asm2; + int w2_asm, w2_asm1, *p_temp1, *p_temp2; + int sum1 = 0; + int const min_asm = -32768, max_asm = 32767; + int temp1, temp2 = 0, temp3 = 0; + int64_t sum; + + /* copy to avoid wrap */ + memcpy(synth_buf + 512, synth_buf, 32 * sizeof(*synth_buf)); + samples2 = samples + 31 * incr; + w = window; + w2 = window + 31; + sum = *dither_state; + p = synth_buf + 16; + p_temp1 = synth_buf + 16; + p_temp2 = synth_buf + 48; + temp1 = sum; + + /** + * use of round_sample function from the original code is eliminated, + * changed with appropriate assembly instructions. + */ + __asm__ volatile ( + "mthi $zero \n\t" + "mtlo %[temp1] \n\t" + "lw %[w_asm], 0(%[w]) \n\t" + "lw %[p_asm], 0(%[p]) \n\t" + "lw %[w_asm1], 64*4(%[w]) \n\t" + "lw %[p_asm1], 64*4(%[p]) \n\t" + "lw %[w_asm2], 128*4(%[w]) \n\t" + "lw %[p_asm2], 128*4(%[p]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "madd %[w_asm2], %[p_asm2] \n\t" + "lw %[w_asm], 192*4(%[w]) \n\t" + "lw %[p_asm], 192*4(%[p]) \n\t" + "lw %[w_asm1], 256*4(%[w]) \n\t" + "lw %[p_asm1], 256*4(%[p]) \n\t" + "lw %[w_asm2], 320*4(%[w]) \n\t" + "lw %[p_asm2], 320*4(%[p]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "madd %[w_asm2], %[p_asm2] \n\t" + "lw %[w_asm], 384*4(%[w]) \n\t" + "lw %[p_asm], 384*4(%[p]) \n\t" + "lw %[w_asm1], 448*4(%[w]) \n\t" + "lw %[p_asm1], 448*4(%[p]) \n\t" + "lw %[w_asm2], 32*4(%[w]) \n\t" + "lw %[p_asm2], 32*4(%[p]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "msub %[w_asm2], %[p_asm2] \n\t" + "lw %[w_asm], 96*4(%[w]) \n\t" + "lw %[p_asm], 96*4(%[p]) \n\t" + "lw %[w_asm1], 160*4(%[w]) \n\t" + "lw %[p_asm1], 160*4(%[p]) \n\t" + "lw %[w_asm2], 224*4(%[w]) \n\t" + "lw %[p_asm2], 224*4(%[p]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub %[w_asm2], %[p_asm2] \n\t" + "lw %[w_asm], 288*4(%[w]) \n\t" + "lw %[p_asm], 288*4(%[p]) \n\t" + "lw %[w_asm1], 352*4(%[w]) \n\t" + "lw %[p_asm1], 352*4(%[p]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "lw %[w_asm], 480*4(%[w]) \n\t" + "lw %[p_asm], 480*4(%[p]) \n\t" + "lw %[w_asm2], 416*4(%[w]) \n\t" + "lw %[p_asm2], 416*4(%[p]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub %[w_asm2], %[p_asm2] \n\t" + + /*round_sample function from the original code is eliminated, + * changed with appropriate assembly instructions + * code example: + + "extr.w %[sum1],$ac0,24 \n\t" + "mflo %[temp3], $ac0 \n\t" + "and %[temp1], %[temp3], 0x00ffffff \n\t" + "slt %[temp2], %[sum1], %[min_asm] \n\t" + "movn %[sum1], %[min_asm],%[temp2] \n\t" + "slt %[temp2], %[max_asm],%[sum1] \n\t" + "movn %[sum1], %[max_asm],%[temp2] \n\t" + "sh %[sum1], 0(%[samples]) \n\t" + */ + + "extr.w %[sum1], $ac0, 24 \n\t" + "mflo %[temp3] \n\t" + "addi %[w], %[w], 4 \n\t" + "and %[temp1], %[temp3], 0x00ffffff \n\t" + "slt %[temp2], %[sum1], %[min_asm] \n\t" + "movn %[sum1], %[min_asm], %[temp2] \n\t" + "slt %[temp2], %[max_asm], %[sum1] \n\t" + "movn %[sum1], %[max_asm], %[temp2] \n\t" + "sh %[sum1], 0(%[samples]) \n\t" + + : [w_asm] "=&r" (w_asm), [p_asm] "=&r" (p_asm), [w_asm1] "=&r" (w_asm1), + [p_asm1] "=&r" (p_asm1), [temp1] "+r" (temp1), [temp2] "+r" (temp2), + [w_asm2] "=&r" (w_asm2), [p_asm2] "=&r" (p_asm2), + [sum1] "+r" (sum1), [w] "+r" (w), [temp3] "+r" (temp3) + : [p] "r" (p), [samples] "r" (samples), [min_asm] "r" (min_asm), + [max_asm] "r" (max_asm) + : "memory", "hi","lo" + ); + + samples += incr; + + /* we calculate two samples at the same time to avoid one memory + access per two sample */ + + for(j = 1; j < 16; j++) { + __asm__ volatile ( + "mthi $0, $ac1 \n\t" + "mtlo $0, $ac1 \n\t" + "mthi $0 \n\t" + "mtlo %[temp1] \n\t" + "addi %[p_temp1], %[p_temp1], 4 \n\t" + "lw %[w_asm], 0(%[w]) \n\t" + "lw %[p_asm], 0(%[p_temp1]) \n\t" + "lw %[w2_asm], 0(%[w2]) \n\t" + "lw %[w_asm1], 64*4(%[w]) \n\t" + "lw %[p_asm1], 64*4(%[p_temp1]) \n\t" + "lw %[w2_asm1], 64*4(%[w2]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "lw %[w_asm], 128*4(%[w]) \n\t" + "lw %[p_asm], 128*4(%[p_temp1]) \n\t" + "lw %[w2_asm], 128*4(%[w2]) \n\t" + "lw %[w_asm1], 192*4(%[w]) \n\t" + "lw %[p_asm1], 192*4(%[p_temp1]) \n\t" + "lw %[w2_asm1], 192*4(%[w2]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "lw %[w_asm], 256*4(%[w]) \n\t" + "lw %[p_asm], 256*4(%[p_temp1]) \n\t" + "lw %[w2_asm], 256*4(%[w2]) \n\t" + "lw %[w_asm1], 320*4(%[w]) \n\t" + "lw %[p_asm1], 320*4(%[p_temp1]) \n\t" + "lw %[w2_asm1], 320*4(%[w2]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "lw %[w_asm], 384*4(%[w]) \n\t" + "lw %[p_asm], 384*4(%[p_temp1]) \n\t" + "lw %[w2_asm], 384*4(%[w2]) \n\t" + "lw %[w_asm1], 448*4(%[w]) \n\t" + "lw %[p_asm1], 448*4(%[p_temp1]) \n\t" + "lw %[w2_asm1], 448*4(%[w2]) \n\t" + "madd %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "madd %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "addi %[p_temp2], %[p_temp2], -4 \n\t" + "lw %[w_asm], 32*4(%[w]) \n\t" + "lw %[p_asm], 0(%[p_temp2]) \n\t" + "lw %[w2_asm], 32*4(%[w2]) \n\t" + "lw %[w_asm1], 96*4(%[w]) \n\t" + "lw %[p_asm1], 64*4(%[p_temp2]) \n\t" + "lw %[w2_asm1], 96*4(%[w2]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "lw %[w_asm], 160*4(%[w]) \n\t" + "lw %[p_asm], 128*4(%[p_temp2]) \n\t" + "lw %[w2_asm], 160*4(%[w2]) \n\t" + "lw %[w_asm1], 224*4(%[w]) \n\t" + "lw %[p_asm1], 192*4(%[p_temp2]) \n\t" + "lw %[w2_asm1], 224*4(%[w2]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "lw %[w_asm], 288*4(%[w]) \n\t" + "lw %[p_asm], 256*4(%[p_temp2]) \n\t" + "lw %[w2_asm], 288*4(%[w2]) \n\t" + "lw %[w_asm1], 352*4(%[w]) \n\t" + "lw %[p_asm1], 320*4(%[p_temp2]) \n\t" + "lw %[w2_asm1], 352*4(%[w2]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "lw %[w_asm], 416*4(%[w]) \n\t" + "lw %[p_asm], 384*4(%[p_temp2]) \n\t" + "lw %[w2_asm], 416*4(%[w2]) \n\t" + "lw %[w_asm1], 480*4(%[w]) \n\t" + "lw %[p_asm1], 448*4(%[p_temp2]) \n\t" + "lw %[w2_asm1], 480*4(%[w2]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub $ac1, %[w2_asm], %[p_asm] \n\t" + "msub $ac1, %[w2_asm1], %[p_asm1] \n\t" + "addi %[w], %[w], 4 \n\t" + "addi %[w2], %[w2], -4 \n\t" + "mflo %[temp2] \n\t" + "extr.w %[sum1], $ac0, 24 \n\t" + "li %[temp3], 1 \n\t" + "and %[temp1], %[temp2], 0x00ffffff \n\t" + "madd $ac1, %[temp1], %[temp3] \n\t" + "slt %[temp2], %[sum1], %[min_asm] \n\t" + "movn %[sum1], %[min_asm], %[temp2] \n\t" + "slt %[temp2], %[max_asm], %[sum1] \n\t" + "movn %[sum1], %[max_asm], %[temp2] \n\t" + "sh %[sum1], 0(%[samples]) \n\t" + "mflo %[temp3], $ac1 \n\t" + "extr.w %[sum1], $ac1, 24 \n\t" + "and %[temp1], %[temp3], 0x00ffffff \n\t" + "slt %[temp2], %[sum1], %[min_asm] \n\t" + "movn %[sum1], %[min_asm], %[temp2] \n\t" + "slt %[temp2], %[max_asm], %[sum1] \n\t" + "movn %[sum1], %[max_asm], %[temp2] \n\t" + "sh %[sum1], 0(%[samples2]) \n\t" + + : [w_asm] "=&r" (w_asm), [p_asm] "=&r" (p_asm), [w_asm1] "=&r" (w_asm1), + [p_asm1] "=&r" (p_asm1), [w2_asm1] "=&r" (w2_asm1), + [w2_asm] "=&r" (w2_asm), [temp1] "+r" (temp1), [temp2] "+r" (temp2), + [p_temp1] "+r" (p_temp1), [p_temp2] "+r" (p_temp2), [sum1] "+r" (sum1), + [w] "+r" (w), [w2] "+r" (w2), [samples] "+r" (samples), + [samples2] "+r" (samples2), [temp3] "+r" (temp3) + : [min_asm] "r" (min_asm), [max_asm] "r" (max_asm) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo" + ); + + samples += incr; + samples2 -= incr; + } + + p = synth_buf + 32; + + __asm__ volatile ( + "mthi $0 \n\t" + "mtlo %[temp1] \n\t" + "lw %[w_asm], 32*4(%[w]) \n\t" + "lw %[p_asm], 0(%[p]) \n\t" + "lw %[w_asm1], 96*4(%[w]) \n\t" + "lw %[p_asm1], 64*4(%[p]) \n\t" + "lw %[w_asm2], 160*4(%[w]) \n\t" + "lw %[p_asm2], 128*4(%[p]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub %[w_asm2], %[p_asm2] \n\t" + "lw %[w_asm], 224*4(%[w]) \n\t" + "lw %[p_asm], 192*4(%[p]) \n\t" + "lw %[w_asm1], 288*4(%[w]) \n\t" + "lw %[p_asm1], 256*4(%[p]) \n\t" + "lw %[w_asm2], 352*4(%[w]) \n\t" + "lw %[p_asm2], 320*4(%[p]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "msub %[w_asm2], %[p_asm2] \n\t" + "lw %[w_asm], 416*4(%[w]) \n\t" + "lw %[p_asm], 384*4(%[p]) \n\t" + "lw %[w_asm1], 480*4(%[w]) \n\t" + "lw %[p_asm1], 448*4(%[p]) \n\t" + "msub %[w_asm], %[p_asm] \n\t" + "msub %[w_asm1], %[p_asm1] \n\t" + "extr.w %[sum1], $ac0, 24 \n\t" + "mflo %[temp2] \n\t" + "and %[temp1], %[temp2], 0x00ffffff \n\t" + "slt %[temp2], %[sum1], %[min_asm] \n\t" + "movn %[sum1], %[min_asm], %[temp2] \n\t" + "slt %[temp2], %[max_asm], %[sum1] \n\t" + "movn %[sum1], %[max_asm], %[temp2] \n\t" + "sh %[sum1], 0(%[samples]) \n\t" + + : [w_asm] "=&r" (w_asm), [p_asm] "=&r" (p_asm), [w_asm1] "=&r" (w_asm1), + [p_asm1] "=&r" (p_asm1), [temp1] "+r" (temp1), [temp2] "+r" (temp2), + [w_asm2] "=&r" (w_asm2), [p_asm2] "=&r" (p_asm2), [sum1] "+r" (sum1) + : [w] "r" (w), [p] "r" (p), [samples] "r" (samples), [min_asm] "r" (min_asm), + [max_asm] "r" (max_asm) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo" + ); + + *dither_state= temp1; +} + +static void imdct36_mips_fixed(int *out, int *buf, int *in, int *win) +{ + int j; + int t0, t1, t2, t3, s0, s1, s2, s3; + int tmp[18], *tmp1, *in1; + /* temporary variables */ + int temp_reg1, temp_reg2, temp_reg3, temp_reg4, temp_reg5, temp_reg6; + int t4, t5, t6, t8, t7; + + /* values defined in macros and tables are + * eliminated - they are directly loaded in appropriate variables + */ + int const C_1 = 4229717092; /* cos(pi*1/18)*2 */ + int const C_2 = 4035949074; /* cos(pi*2/18)*2 */ + int const C_3 = 575416510; /* -cos(pi*3/18)*2 */ + int const C_3A = 3719550786; /* cos(pi*3/18)*2 */ + int const C_4 = 1004831466; /* -cos(pi*4/18)*2 */ + int const C_5 = 1534215534; /* -cos(pi*5/18)*2 */ + int const C_7 = -1468965330; /* -cos(pi*7/18)*2 */ + int const C_8 = -745813244; /* -cos(pi*8/18)*2 */ + + /* + * instructions of the first two loops are reorganized and loops are unrolled, + * in order to eliminate unnecessary readings and writings in array + */ + + __asm__ volatile ( + "lw %[t1], 17*4(%[in]) \n\t" + "lw %[t2], 16*4(%[in]) \n\t" + "lw %[t3], 15*4(%[in]) \n\t" + "lw %[t4], 14*4(%[in]) \n\t" + "addu %[t1], %[t1], %[t2] \n\t" + "addu %[t2], %[t2], %[t3] \n\t" + "addu %[t3], %[t3], %[t4] \n\t" + "lw %[t5], 13*4(%[in]) \n\t" + "addu %[t1], %[t1], %[t3] \n\t" + "sw %[t2], 16*4(%[in]) \n\t" + "lw %[t6], 12*4(%[in]) \n\t" + "sw %[t1], 17*4(%[in]) \n\t" + "addu %[t4], %[t4], %[t5] \n\t" + "addu %[t5], %[t5], %[t6] \n\t" + "lw %[t7], 11*4(%[in]) \n\t" + "addu %[t3], %[t3], %[t5] \n\t" + "sw %[t4], 14*4(%[in]) \n\t" + "lw %[t8], 10*4(%[in]) \n\t" + "sw %[t3], 15*4(%[in]) \n\t" + "addu %[t6], %[t6], %[t7] \n\t" + "addu %[t7], %[t7], %[t8] \n\t" + "sw %[t6], 12*4(%[in]) \n\t" + "addu %[t5], %[t5], %[t7] \n\t" + "lw %[t1], 9*4(%[in]) \n\t" + "lw %[t2], 8*4(%[in]) \n\t" + "sw %[t5], 13*4(%[in]) \n\t" + "addu %[t8], %[t8], %[t1] \n\t" + "addu %[t1], %[t1], %[t2] \n\t" + "sw %[t8], 10*4(%[in]) \n\t" + "addu %[t7], %[t7], %[t1] \n\t" + "lw %[t3], 7*4(%[in]) \n\t" + "lw %[t4], 6*4(%[in]) \n\t" + "sw %[t7], 11*4(%[in]) \n\t" + "addu %[t2], %[t2], %[t3] \n\t" + "addu %[t3], %[t3], %[t4] \n\t" + "sw %[t2], 8*4(%[in]) \n\t" + "addu %[t1], %[t1], %[t3] \n\t" + "lw %[t5], 5*4(%[in]) \n\t" + "lw %[t6], 4*4(%[in]) \n\t" + "sw %[t1], 9*4(%[in]) \n\t" + "addu %[t4], %[t4], %[t5] \n\t" + "addu %[t5], %[t5], %[t6] \n\t" + "sw %[t4], 6*4(%[in]) \n\t" + "addu %[t3], %[t3], %[t5] \n\t" + "lw %[t7], 3*4(%[in]) \n\t" + "lw %[t8], 2*4(%[in]) \n\t" + "sw %[t3], 7*4(%[in]) \n\t" + "addu %[t6], %[t6], %[t7] \n\t" + "addu %[t7], %[t7], %[t8] \n\t" + "sw %[t6], 4*4(%[in]) \n\t" + "addu %[t5], %[t5], %[t7] \n\t" + "lw %[t1], 1*4(%[in]) \n\t" + "lw %[t2], 0*4(%[in]) \n\t" + "sw %[t5], 5*4(%[in]) \n\t" + "addu %[t8], %[t8], %[t1] \n\t" + "addu %[t1], %[t1], %[t2] \n\t" + "sw %[t8], 2*4(%[in]) \n\t" + "addu %[t7], %[t7], %[t1] \n\t" + "sw %[t7], 3*4(%[in]) \n\t" + "sw %[t1], 1*4(%[in]) \n\t" + + : [in] "+r" (in), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3), + [t4] "=&r" (t4), [t5] "=&r" (t5), [t6] "=&r" (t6), + [t7] "=&r" (t7), [t8] "=&r" (t8) + : + : "memory" + ); + + for(j = 0; j < 2; j++) { + + tmp1 = tmp + j; + in1 = in + j; + + /** + * Original constants are multiplied by two in advanced + * for assembly optimization (e.g. C_2 = 2 * C2). + * That can lead to overflow in operations where they are used. + * + * Example of the solution: + * + * in original code: + * t0 = ((int64_t)(in1[2*2] + in1[2*4]) * (int64_t)(2*C2))>>32 + * + * in assembly: + * C_2 = 2 * C2; + * . + * . + * "lw %[t7], 4*4(%[in1]) \n\t" + * "lw %[t8], 8*4(%[in1]) \n\t" + * "addu %[temp_reg2],%[t7], %[t8] \n\t" + * "multu %[C_2], %[temp_reg2] \n\t" + * "mfhi %[temp_reg1] \n\t" + * "sra %[temp_reg2],%[temp_reg2],31 \n\t" + * "move %[t0], $0 \n\t" + * "movn %[t0], %[C_2], %[temp_reg2] \n\t" + * "sub %[t0], %[temp_reg1],%[t0] \n\t" + */ + + __asm__ volatile ( + "lw %[t7], 4*4(%[in1]) \n\t" + "lw %[t8], 8*4(%[in1]) \n\t" + "lw %[t6], 16*4(%[in1]) \n\t" + "lw %[t4], 0*4(%[in1]) \n\t" + "addu %[temp_reg2], %[t7], %[t8] \n\t" + "addu %[t2], %[t6], %[t8] \n\t" + "multu %[C_2], %[temp_reg2] \n\t" + "lw %[t5], 12*4(%[in1]) \n\t" + "sub %[t2], %[t2], %[t7] \n\t" + "sub %[t1], %[t4], %[t5] \n\t" + "sra %[t3], %[t5], 1 \n\t" + "sra %[temp_reg1], %[t2], 1 \n\t" + "addu %[t3], %[t3], %[t4] \n\t" + "sub %[temp_reg1], %[t1], %[temp_reg1] \n\t" + "sra %[temp_reg2], %[temp_reg2], 31 \n\t" + "sw %[temp_reg1], 6*4(%[tmp1]) \n\t" + "move %[t0], $0 \n\t" + "movn %[t0], %[C_2], %[temp_reg2] \n\t" + "mfhi %[temp_reg1] \n\t" + "addu %[t1], %[t1], %[t2] \n\t" + "sw %[t1], 16*4(%[tmp1]) \n\t" + "sub %[temp_reg4], %[t8], %[t6] \n\t" + "add %[temp_reg2], %[t7], %[t6] \n\t" + "mult $ac1, %[C_8], %[temp_reg4] \n\t" + "multu $ac2, %[C_4], %[temp_reg2] \n\t" + "sub %[t0], %[temp_reg1], %[t0] \n\t" + "sra %[temp_reg1], %[temp_reg2], 31 \n\t" + "move %[t2], $0 \n\t" + "movn %[t2], %[C_4], %[temp_reg1] \n\t" + "mfhi %[t1], $ac1 \n\t" + "mfhi %[temp_reg1], $ac2 \n\t" + "lw %[t6], 10*4(%[in1]) \n\t" + "lw %[t8], 14*4(%[in1]) \n\t" + "lw %[t7], 2*4(%[in1]) \n\t" + "lw %[t4], 6*4(%[in1]) \n\t" + "sub %[temp_reg3], %[t3], %[t0] \n\t" + "add %[temp_reg4], %[t3], %[t0] \n\t" + "sub %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "add %[temp_reg4], %[temp_reg4], %[t1] \n\t" + "sub %[t2], %[temp_reg1], %[t2] \n\t" + "sw %[temp_reg4], 2*4(%[tmp1]) \n\t" + "sub %[temp_reg3], %[temp_reg3], %[t2] \n\t" + "add %[temp_reg1], %[t3], %[t2] \n\t" + "sw %[temp_reg3], 10*4(%[tmp1]) \n\t" + "sub %[temp_reg1], %[temp_reg1], %[t1] \n\t" + "addu %[temp_reg2], %[t6], %[t8] \n\t" + "sw %[temp_reg1], 14*4(%[tmp1]) \n\t" + "sub %[temp_reg2], %[temp_reg2], %[t7] \n\t" + "addu %[temp_reg3], %[t7], %[t6] \n\t" + "multu $ac3, %[C_3], %[temp_reg2] \n\t" + "multu %[C_1], %[temp_reg3] \n\t" + "sra %[temp_reg1], %[temp_reg2], 31 \n\t" + "move %[t1], $0 \n\t" + "sra %[temp_reg3], %[temp_reg3], 31 \n\t" + "movn %[t1], %[C_3], %[temp_reg1] \n\t" + "mfhi %[temp_reg1], $ac3 \n\t" + "mfhi %[temp_reg4] \n\t" + "move %[t2], $0 \n\t" + "movn %[t2], %[C_1], %[temp_reg3] \n\t" + "sub %[temp_reg3], %[t6], %[t8] \n\t" + "sub %[t2], %[temp_reg4], %[t2] \n\t" + "multu $ac1, %[C_7], %[temp_reg3] \n\t" + "sub %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "sra %[temp_reg4], %[temp_reg3], 31 \n\t" + "sub %[t1], %[temp_reg1], %[t1] \n\t" + "move %[t3], $0 \n\t" + "sw %[t1], 4*4(%[tmp1]) \n\t" + "movn %[t3], %[C_7], %[temp_reg4] \n\t" + "multu $ac2, %[C_3A], %[t4] \n\t" + "add %[temp_reg2], %[t7], %[t8] \n\t" + "move %[t1], $0 \n\t" + "mfhi %[temp_reg4], $ac1 \n\t" + "multu $ac3,%[C_5], %[temp_reg2] \n\t" + "move %[t0], $0 \n\t" + "sra %[temp_reg1], %[temp_reg2], 31 \n\t" + "movn %[t1],%[C_5], %[temp_reg1] \n\t" + "sub %[temp_reg4], %[temp_reg4], %[temp_reg3] \n\t" + "mfhi %[temp_reg1], $ac3 \n\t" + "sra %[temp_reg3], %[t4], 31 \n\t" + "movn %[t0], %[C_3A], %[temp_reg3] \n\t" + "mfhi %[temp_reg3], $ac2 \n\t" + "sub %[t3], %[temp_reg4], %[t3] \n\t" + "add %[temp_reg4], %[t3], %[t2] \n\t" + "sub %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "sub %[t1], %[temp_reg1], %[t1] \n\t" + "sub %[t0], %[temp_reg3], %[t0] \n\t" + "add %[temp_reg1], %[t2], %[t1] \n\t" + "add %[temp_reg4], %[temp_reg4], %[t0] \n\t" + "sub %[temp_reg2], %[t3], %[t1] \n\t" + "sw %[temp_reg4], 0*4(%[tmp1]) \n\t" + "sub %[temp_reg1], %[temp_reg1], %[t0] \n\t" + "sub %[temp_reg2], %[temp_reg2], %[t0] \n\t" + "sw %[temp_reg1], 12*4(%[tmp1]) \n\t" + "sw %[temp_reg2], 8*4(%[tmp1]) \n\t" + + : [t7] "=&r" (t7), [temp_reg1] "=&r" (temp_reg1), + [temp_reg2] "=&r" (temp_reg2), [temp_reg4] "=&r" (temp_reg4), + [temp_reg3] "=&r" (temp_reg3), [t8] "=&r" (t8), [t0] "=&r" (t0), + [t4] "=&r" (t4), [t5] "=&r" (t5), [t6] "=&r"(t6), [t2] "=&r" (t2), + [t3] "=&r" (t3), [t1] "=&r" (t1) + : [C_2] "r" (C_2), [in1] "r" (in1), [tmp1] "r" (tmp1), [C_8] "r" (C_8), + [C_4] "r" (C_4), [C_3] "r" (C_3), [C_1] "r" (C_1), [C_7] "r" (C_7), + [C_3A] "r" (C_3A), [C_5] "r" (C_5) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", + "$ac3hi", "$ac3lo" + ); + } + + /** + * loop is unrolled four times + * + * values defined in tables(icos36[] and icos36h[]) are not loaded from + * these tables - they are directly loaded in appropriate registers + * + */ + + __asm__ volatile ( + "lw %[t2], 1*4(%[tmp]) \n\t" + "lw %[t3], 3*4(%[tmp]) \n\t" + "lw %[t0], 0*4(%[tmp]) \n\t" + "lw %[t1], 2*4(%[tmp]) \n\t" + "addu %[temp_reg1], %[t3], %[t2] \n\t" + "li %[temp_reg2], 0x807D2B1E \n\t" + "move %[s1], $0 \n\t" + "multu %[temp_reg2], %[temp_reg1] \n\t" + "sra %[temp_reg1], %[temp_reg1], 31 \n\t" + "movn %[s1], %[temp_reg2], %[temp_reg1] \n\t" + "sub %[temp_reg3], %[t3], %[t2] \n\t" + "li %[temp_reg4], 0x2de5151 \n\t" + "mfhi %[temp_reg2] \n\t" + "addu %[s0], %[t1], %[t0] \n\t" + "lw %[temp_reg5], 9*4(%[win]) \n\t" + "mult $ac1, %[temp_reg4], %[temp_reg3] \n\t" + "lw %[temp_reg6], 4*9*4(%[buf]) \n\t" + "sub %[s2], %[t1], %[t0] \n\t" + "lw %[temp_reg3], 29*4(%[win]) \n\t" + "subu %[s1], %[temp_reg2], %[s1] \n\t" + "lw %[temp_reg4], 28*4(%[win]) \n\t" + "add %[t0], %[s0], %[s1] \n\t" + "extr.w %[s3], $ac1,23 \n\t" + "mult $ac2, %[t0], %[temp_reg3] \n\t" + "sub %[t1], %[s0], %[s1] \n\t" + "lw %[temp_reg1], 4*8*4(%[buf]) \n\t" + "mult %[t1], %[temp_reg5] \n\t" + "lw %[temp_reg2], 8*4(%[win]) \n\t" + "mfhi %[temp_reg3], $ac2 \n\t" + "mult $ac3, %[t0], %[temp_reg4] \n\t" + "add %[t0], %[s2], %[s3] \n\t" + "mfhi %[temp_reg5] \n\t" + "mult $ac1, %[t1], %[temp_reg2] \n\t" + "sub %[t1], %[s2], %[s3] \n\t" + "sw %[temp_reg3], 4*9*4(%[buf]) \n\t" + "mfhi %[temp_reg4], $ac3 \n\t" + "lw %[temp_reg3], 37*4(%[win]) \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "add %[temp_reg5], %[temp_reg5], %[temp_reg6] \n\t" + "lw %[temp_reg6], 17*4(%[win]) \n\t" + "sw %[temp_reg5], 32*9*4(%[out]) \n\t" + "sw %[temp_reg4], 4*8*4(%[buf]) \n\t" + "mult %[t1], %[temp_reg6] \n\t" + "add %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "lw %[temp_reg2], 0*4(%[win]) \n\t" + "lw %[temp_reg5], 4*17*4(%[buf]) \n\t" + "sw %[temp_reg1], 8*32*4(%[out]) \n\t" + "mfhi %[temp_reg6] \n\t" + "mult $ac1, %[t1], %[temp_reg2] \n\t" + "lw %[temp_reg4], 20*4(%[win]) \n\t" + "lw %[temp_reg1], 0(%[buf]) \n\t" + "mult $ac2, %[t0], %[temp_reg3] \n\t" + "mult %[t0], %[temp_reg4] \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "lw %[t0], 4*4(%[tmp]) \n\t" + "add %[temp_reg5], %[temp_reg5], %[temp_reg6] \n\t" + "mfhi %[temp_reg3], $ac2 \n\t" + "mfhi %[temp_reg4] \n\t" + "sw %[temp_reg5], 17*32*4(%[out]) \n\t" + "lw %[t1], 6*4(%[tmp]) \n\t" + "add %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "lw %[t2], 5*4(%[tmp]) \n\t" + "sw %[temp_reg1], 0*32*4(%[out]) \n\t" + "addu %[s0], %[t1], %[t0] \n\t" + "sw %[temp_reg3], 4*17*4(%[buf]) \n\t" + "lw %[t3], 7*4(%[tmp]) \n\t" + "sub %[s2], %[t1], %[t0] \n\t" + "sw %[temp_reg4], 0(%[buf]) \n\t" + "addu %[temp_reg5], %[t3], %[t2] \n\t" + "li %[temp_reg6], 0x8483EE0C \n\t" + "move %[s1], $0 \n\t" + "multu %[temp_reg6], %[temp_reg5] \n\t" + "sub %[temp_reg1], %[t3], %[t2] \n\t" + "li %[temp_reg2], 0xf746ea \n\t" + "sra %[temp_reg5], %[temp_reg5], 31 \n\t" + "mult $ac1, %[temp_reg2], %[temp_reg1] \n\t" + "movn %[s1], %[temp_reg6], %[temp_reg5] \n\t" + "mfhi %[temp_reg5] \n\t" + "lw %[temp_reg3], 10*4(%[win]) \n\t" + "lw %[temp_reg4], 4*10*4(%[buf]) \n\t" + "extr.w %[s3], $ac1, 23 \n\t" + "lw %[temp_reg1], 4*7*4(%[buf]) \n\t" + "lw %[temp_reg2], 7*4(%[win]) \n\t" + "lw %[temp_reg6], 30*4(%[win]) \n\t" + "subu %[s1], %[temp_reg5], %[s1] \n\t" + "sub %[t1], %[s0], %[s1] \n\t" + "add %[t0], %[s0], %[s1] \n\t" + "mult $ac2, %[t1], %[temp_reg3] \n\t" + "mult $ac3, %[t1], %[temp_reg2] \n\t" + "mult %[t0], %[temp_reg6] \n\t" + "lw %[temp_reg5], 27*4(%[win]) \n\t" + "mult $ac1, %[t0], %[temp_reg5] \n\t" + "mfhi %[temp_reg3], $ac2 \n\t" + "mfhi %[temp_reg2], $ac3 \n\t" + "mfhi %[temp_reg6] \n\t" + "add %[t0], %[s2], %[s3] \n\t" + "sub %[t1], %[s2], %[s3] \n\t" + "add %[temp_reg3], %[temp_reg3], %[temp_reg4] \n\t" + "lw %[temp_reg4], 16*4(%[win]) \n\t" + "mfhi %[temp_reg5], $ac1 \n\t" + "sw %[temp_reg3], 32*10*4(%[out]) \n\t" + "add %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "lw %[temp_reg3], 4*16*4(%[buf]) \n\t" + "sw %[temp_reg6], 4*10*4(%[buf]) \n\t" + "sw %[temp_reg1], 7*32*4(%[out]) \n\t" + "mult $ac2, %[t1], %[temp_reg4] \n\t" + "sw %[temp_reg5], 4*7*4(%[buf]) \n\t" + "lw %[temp_reg6], 1*4(%[win]) \n\t" + "lw %[temp_reg5], 4*1*4(%[buf]) \n\t" + "lw %[temp_reg1], 36*4(%[win]) \n\t" + "mult $ac3, %[t1], %[temp_reg6] \n\t" + "lw %[temp_reg2], 21*4(%[win]) \n\t" + "mfhi %[temp_reg4], $ac2 \n\t" + "mult %[t0], %[temp_reg1] \n\t" + "mult $ac1, %[t0],%[temp_reg2] \n\t" + "lw %[t0], 8*4(%[tmp]) \n\t" + "mfhi %[temp_reg6], $ac3 \n\t" + "lw %[t1], 10*4(%[tmp]) \n\t" + "lw %[t3], 11*4(%[tmp]) \n\t" + "mfhi %[temp_reg1] \n\t" + "add %[temp_reg3], %[temp_reg3], %[temp_reg4] \n\t" + "lw %[t2], 9*4(%[tmp]) \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "add %[temp_reg5], %[temp_reg5], %[temp_reg6] \n\t" + "sw %[temp_reg3], 16*32*4(%[out]) \n\t" + "sw %[temp_reg5], 1*32*4(%[out]) \n\t" + "sw %[temp_reg1], 4*16*4(%[buf]) \n\t" + "addu %[temp_reg3], %[t3], %[t2] \n\t" + "li %[temp_reg4], 0x8D3B7CD6 \n\t" + "sw %[temp_reg2], 4*1*4(%[buf]) \n\t" + "multu %[temp_reg4],%[temp_reg3] \n\t" + "sra %[temp_reg3], %[temp_reg3], 31 \n\t" + "move %[s1], $0 \n\t" + "movn %[s1], %[temp_reg4], %[temp_reg3] \n\t" + "addu %[s0], %[t1], %[t0] \n\t" + "mfhi %[temp_reg3] \n\t" + "sub %[s2], %[t1], %[t0] \n\t" + "sub %[temp_reg5], %[t3], %[t2] \n\t" + "li %[temp_reg6], 0x976fd9 \n\t" + "lw %[temp_reg2], 11*4(%[win]) \n\t" + "lw %[temp_reg1], 4*11*4(%[buf]) \n\t" + "mult $ac1, %[temp_reg6], %[temp_reg5] \n\t" + "subu %[s1], %[temp_reg3], %[s1] \n\t" + "lw %[temp_reg5], 31*4(%[win]) \n\t" + "sub %[t1], %[s0], %[s1] \n\t" + "add %[t0], %[s0], %[s1] \n\t" + "mult $ac2, %[t1], %[temp_reg2] \n\t" + "mult %[t0], %[temp_reg5] \n\t" + "lw %[temp_reg4], 6*4(%[win]) \n\t" + "extr.w %[s3], $ac1, 23 \n\t" + "lw %[temp_reg3], 4*6*4(%[buf]) \n\t" + "mfhi %[temp_reg2], $ac2 \n\t" + "lw %[temp_reg6], 26*4(%[win]) \n\t" + "mfhi %[temp_reg5] \n\t" + "mult $ac3, %[t1], %[temp_reg4] \n\t" + "mult $ac1, %[t0], %[temp_reg6] \n\t" + "add %[t0], %[s2], %[s3] \n\t" + "sub %[t1], %[s2], %[s3] \n\t" + "add %[temp_reg2], %[temp_reg2], %[temp_reg1] \n\t" + "mfhi %[temp_reg4], $ac3 \n\t" + "mfhi %[temp_reg6], $ac1 \n\t" + "sw %[temp_reg5], 4*11*4(%[buf]) \n\t" + "sw %[temp_reg2], 32*11*4(%[out]) \n\t" + "lw %[temp_reg1], 4*15*4(%[buf]) \n\t" + "add %[temp_reg3], %[temp_reg3], %[temp_reg4] \n\t" + "lw %[temp_reg2], 15*4(%[win]) \n\t" + "sw %[temp_reg3], 6*32*4(%[out]) \n\t" + "sw %[temp_reg6], 4*6*4(%[buf]) \n\t" + "mult %[t1], %[temp_reg2] \n\t" + "lw %[temp_reg3], 2*4(%[win]) \n\t" + "lw %[temp_reg4], 4*2*4(%[buf]) \n\t" + "lw %[temp_reg5], 35*4(%[win]) \n\t" + "mult $ac1, %[t1], %[temp_reg3] \n\t" + "mfhi %[temp_reg2] \n\t" + "lw %[temp_reg6], 22*4(%[win]) \n\t" + "mult $ac2, %[t0], %[temp_reg5] \n\t" + "lw %[t1], 14*4(%[tmp]) \n\t" + "mult $ac3, %[t0], %[temp_reg6] \n\t" + "lw %[t0], 12*4(%[tmp]) \n\t" + "mfhi %[temp_reg3], $ac1 \n\t" + "add %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "mfhi %[temp_reg5], $ac2 \n\t" + "sw %[temp_reg1], 15*32*4(%[out]) \n\t" + "mfhi %[temp_reg6], $ac3 \n\t" + "lw %[t2], 13*4(%[tmp]) \n\t" + "lw %[t3], 15*4(%[tmp]) \n\t" + "add %[temp_reg4], %[temp_reg4], %[temp_reg3] \n\t" + "sw %[temp_reg5], 4*15*4(%[buf]) \n\t" + "addu %[temp_reg1], %[t3], %[t2] \n\t" + "li %[temp_reg2], 0x9C42577C \n\t" + "move %[s1], $0 \n\t" + "multu %[temp_reg2], %[temp_reg1] \n\t" + "sw %[temp_reg4], 2*32*4(%[out]) \n\t" + "sra %[temp_reg1], %[temp_reg1], 31 \n\t" + "movn %[s1], %[temp_reg2], %[temp_reg1] \n\t" + "sub %[temp_reg3], %[t3], %[t2] \n\t" + "li %[temp_reg4], 0x6f94a2 \n\t" + "mfhi %[temp_reg1] \n\t" + "addu %[s0], %[t1], %[t0] \n\t" + "sw %[temp_reg6], 4*2*4(%[buf]) \n\t" + "mult $ac1, %[temp_reg4], %[temp_reg3] \n\t" + "sub %[s2], %[t1], %[t0] \n\t" + "lw %[temp_reg5], 12*4(%[win]) \n\t" + "lw %[temp_reg6], 4*12*4(%[buf]) \n\t" + "subu %[s1], %[temp_reg1], %[s1] \n\t" + "sub %[t1], %[s0], %[s1] \n\t" + "lw %[temp_reg3], 32*4(%[win]) \n\t" + "mult $ac2, %[t1], %[temp_reg5] \n\t" + "add %[t0], %[s0], %[s1] \n\t" + "extr.w %[s3], $ac1, 23 \n\t" + "lw %[temp_reg2], 5*4(%[win]) \n\t" + "mult %[t0], %[temp_reg3] \n\t" + "mfhi %[temp_reg5], $ac2 \n\t" + "lw %[temp_reg4], 25*4(%[win]) \n\t" + "lw %[temp_reg1], 4*5*4(%[buf]) \n\t" + "mult $ac3, %[t1], %[temp_reg2] \n\t" + "mult $ac1, %[t0], %[temp_reg4] \n\t" + "mfhi %[temp_reg3] \n\t" + "add %[t0], %[s2], %[s3] \n\t" + "add %[temp_reg5], %[temp_reg5], %[temp_reg6] \n\t" + "mfhi %[temp_reg2], $ac3 \n\t" + "mfhi %[temp_reg4], $ac1 \n\t" + "sub %[t1], %[s2], %[s3] \n\t" + "sw %[temp_reg5], 32*12*4(%[out]) \n\t" + "sw %[temp_reg3], 4*12*4(%[buf]) \n\t" + "lw %[temp_reg6], 14*4(%[win]) \n\t" + "lw %[temp_reg5], 4*14*4(%[buf]) \n\t" + "add %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "sw %[temp_reg4], 4*5*4(%[buf]) \n\t" + "sw %[temp_reg1], 5*32*4(%[out]) \n\t" + "mult %[t1], %[temp_reg6] \n\t" + "lw %[temp_reg4], 34*4(%[win]) \n\t" + "lw %[temp_reg2], 3*4(%[win]) \n\t" + "lw %[temp_reg1], 4*3*4(%[buf]) \n\t" + "mult $ac2, %[t0], %[temp_reg4] \n\t" + "mfhi %[temp_reg6] \n\t" + "mult $ac1, %[t1], %[temp_reg2] \n\t" + "lw %[temp_reg3], 23*4(%[win]) \n\t" + "lw %[s0], 16*4(%[tmp]) \n\t" + "mfhi %[temp_reg4], $ac2 \n\t" + "lw %[t1], 17*4(%[tmp]) \n\t" + "mult $ac3, %[t0], %[temp_reg3] \n\t" + "move %[s1], $0 \n\t" + "add %[temp_reg5], %[temp_reg5], %[temp_reg6] \n\t" + "mfhi %[temp_reg2], $ac1 \n\t" + "sw %[temp_reg5], 14*32*4(%[out]) \n\t" + "sw %[temp_reg4], 4*14*4(%[buf]) \n\t" + "mfhi %[temp_reg3], $ac3 \n\t" + "li %[temp_reg5], 0xB504F334 \n\t" + "add %[temp_reg1], %[temp_reg1], %[temp_reg2] \n\t" + "multu %[temp_reg5], %[t1] \n\t" + "lw %[temp_reg2], 4*13*4(%[buf]) \n\t" + "sw %[temp_reg1], 3*32*4(%[out]) \n\t" + "sra %[t1], %[t1], 31 \n\t" + "mfhi %[temp_reg6] \n\t" + "movn %[s1], %[temp_reg5], %[t1] \n\t" + "sw %[temp_reg3], 4*3*4(%[buf]) \n\t" + "lw %[temp_reg1], 13*4(%[win]) \n\t" + "lw %[temp_reg4], 4*4*4(%[buf]) \n\t" + "lw %[temp_reg3], 4*4(%[win]) \n\t" + "lw %[temp_reg5], 33*4(%[win]) \n\t" + "subu %[s1], %[temp_reg6], %[s1] \n\t" + "lw %[temp_reg6], 24*4(%[win]) \n\t" + "sub %[t1], %[s0], %[s1] \n\t" + "add %[t0], %[s0], %[s1] \n\t" + "mult $ac1, %[t1], %[temp_reg1] \n\t" + "mult $ac2, %[t1], %[temp_reg3] \n\t" + "mult $ac3, %[t0], %[temp_reg5] \n\t" + "mult %[t0], %[temp_reg6] \n\t" + "mfhi %[temp_reg1], $ac1 \n\t" + "mfhi %[temp_reg3], $ac2 \n\t" + "mfhi %[temp_reg5], $ac3 \n\t" + "mfhi %[temp_reg6] \n\t" + "add %[temp_reg2], %[temp_reg2], %[temp_reg1] \n\t" + "add %[temp_reg4], %[temp_reg4], %[temp_reg3] \n\t" + "sw %[temp_reg2], 13*32*4(%[out]) \n\t" + "sw %[temp_reg4], 4*32*4(%[out]) \n\t" + "sw %[temp_reg5], 4*13*4(%[buf]) \n\t" + "sw %[temp_reg6], 4*4*4(%[buf]) \n\t" + + : [t0] "=&r" (t0), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3), + [s0] "=&r" (s0), [s2] "=&r" (s2), [temp_reg1] "=&r" (temp_reg1), + [temp_reg2] "=&r" (temp_reg2), [s1] "=&r" (s1), [s3] "=&r" (s3), + [temp_reg3] "=&r" (temp_reg3), [temp_reg4] "=&r" (temp_reg4), + [temp_reg5] "=&r" (temp_reg5), [temp_reg6] "=&r" (temp_reg6), + [out] "+r" (out) + : [tmp] "r" (tmp), [win] "r" (win), [buf] "r" (buf) + : "memory", "hi", "lo", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", + "$ac3hi", "$ac3lo" + ); +} + +static void ff_imdct36_blocks_mips_fixed(int *out, int *buf, int *in, + int count, int switch_point, int block_type) +{ + int j; + for (j=0 ; j < count; j++) { + /* apply window & overlap with previous buffer */ + + /* select window */ + int win_idx = (switch_point && j < 2) ? 0 : block_type; + int *win = ff_mdct_win_fixed[win_idx + (4 & -(j & 1))]; + + imdct36_mips_fixed(out, buf, in, win); + + in += 18; + buf += ((j&3) != 3 ? 1 : (72-3)); + out++; + } +} + +void ff_mpadsp_init_mipsdspr1(MPADSPContext *s) +{ + s->apply_window_fixed = ff_mpadsp_apply_window_mips_fixed; + s->imdct36_blocks_fixed = ff_imdct36_blocks_mips_fixed; +} diff --git a/ffmpeg/libavcodec/mips/mpegaudiodsp_mips_float.c b/ffmpeg/libavcodec/mips/mpegaudiodsp_mips_float.c new file mode 100644 index 0000000..beb8e78 --- /dev/null +++ b/ffmpeg/libavcodec/mips/mpegaudiodsp_mips_float.c @@ -0,0 +1,1250 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Bojan Zivkovic (bojan@mips.com) + * + * MPEG Audio decoder optimized for MIPS floating-point architecture + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/mpegaudiodsp_template.c + * libavcodec/dct32.c + */ + +#include + +#include "libavcodec/mpegaudiodsp.h" + +static void ff_mpadsp_apply_window_mips_float(float *synth_buf, float *window, + int *dither_state, float *samples, int incr) +{ + register const float *w, *w2, *p; + int j; + float *samples2; + float sum, sum2; + /* temporary variables */ + int incr1 = incr << 2; + int t_sample; + float in1, in2, in3, in4, in5, in6, in7, in8; + float *p2; + + /* copy to avoid wrap */ + memcpy(synth_buf + 512, synth_buf, 32 * sizeof(*synth_buf)); + + /** + * instructions are scheduled to minimize pipeline stall. + * use of round_sample function from the original code is + * changed with appropriate assembly instructions. + */ + + __asm__ volatile ( + "lwc1 %[sum], 0(%[dither_state]) \t\n" + "sll %[t_sample], %[incr1], 5 \t\n" + "sub %[t_sample], %[t_sample], %[incr1] \n\t" + "li %[j], 4 \t\n" + "lwc1 %[in1], 0(%[window]) \t\n" + "lwc1 %[in2], 16*4(%[synth_buf]) \t\n" + "sw $zero, 0(%[dither_state]) \t\n" + "lwc1 %[in3], 64*4(%[window]) \t\n" + "lwc1 %[in4], 80*4(%[synth_buf]) \t\n" + "addu %[samples2], %[samples], %[t_sample] \t\n" + "madd.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in5], 128*4(%[window]) \t\n" + "lwc1 %[in6], 144*4(%[synth_buf]) \t\n" + "lwc1 %[in7], 192*4(%[window]) \t\n" + "madd.s %[sum], %[sum], %[in3], %[in4] \t\n" + "lwc1 %[in8], 208*4(%[synth_buf]) \t\n" + "lwc1 %[in1], 256*4(%[window]) \t\n" + "lwc1 %[in2], 272*4(%[synth_buf]) \t\n" + "madd.s %[sum], %[sum], %[in5], %[in6] \t\n" + "lwc1 %[in3], 320*4(%[window]) \t\n" + "lwc1 %[in4], 336*4(%[synth_buf]) \t\n" + "lwc1 %[in5], 384*4(%[window]) \t\n" + "madd.s %[sum], %[sum], %[in7], %[in8] \t\n" + "lwc1 %[in6], 400*4(%[synth_buf]) \t\n" + "lwc1 %[in7], 448*4(%[window]) \t\n" + "lwc1 %[in8], 464*4(%[synth_buf]) \t\n" + "madd.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in1], 32*4(%[window]) \t\n" + "lwc1 %[in2], 48*4(%[synth_buf]) \t\n" + "madd.s %[sum], %[sum], %[in3], %[in4] \t\n" + "lwc1 %[in3], 96*4(%[window]) \t\n" + "lwc1 %[in4], 112*4(%[synth_buf]) \t\n" + "madd.s %[sum], %[sum], %[in5], %[in6] \t\n" + "lwc1 %[in5], 160*4(%[window]) \t\n" + "lwc1 %[in6], 176*4(%[synth_buf]) \t\n" + "madd.s %[sum], %[sum], %[in7], %[in8] \t\n" + "lwc1 %[in7], 224*4(%[window]) \t\n" + "lwc1 %[in8], 240*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in1], 288*4(%[window]) \t\n" + "lwc1 %[in2], 304*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in3], %[in4] \t\n" + "lwc1 %[in3], 352*4(%[window]) \t\n" + "lwc1 %[in4], 368*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in5], %[in6] \t\n" + "lwc1 %[in5], 416*4(%[window]) \t\n" + "lwc1 %[in6], 432*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in7], %[in8] \t\n" + "lwc1 %[in7], 480*4(%[window]) \t\n" + "lwc1 %[in8], 496*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "addu %[w], %[window], 4 \t\n" + "nmsub.s %[sum], %[sum], %[in3], %[in4] \t\n" + "addu %[w2], %[window], 124 \t\n" + "addiu %[p], %[synth_buf], 68 \t\n" + "addiu %[p2], %[synth_buf], 188 \t\n" + "nmsub.s %[sum], %[sum], %[in5], %[in6] \t\n" + "nmsub.s %[sum], %[sum], %[in7], %[in8] \t\n" + "swc1 %[sum], 0(%[samples]) \t\n" + "addu %[samples], %[samples], %[incr1] \t\n" + + /* calculate two samples at the same time to avoid one memory + access per two sample */ + + "ff_mpadsp_apply_window_loop%=: \t\n" + "lwc1 %[in1], 0(%[w]) \t\n" + "lwc1 %[in2], 0(%[p]) \t\n" + "lwc1 %[in3], 0(%[w2]) \t\n" + "lwc1 %[in4], 64*4(%[w]) \t\n" + "lwc1 %[in5], 64*4(%[p]) \t\n" + "lwc1 %[in6], 64*4(%[w2]) \t\n" + "mul.s %[sum], %[in1], %[in2] \t\n" + "mul.s %[sum2], %[in2], %[in3] \t\n" + "lwc1 %[in1], 128*4(%[w]) \t\n" + "lwc1 %[in2], 128*4(%[p]) \t\n" + "madd.s %[sum], %[sum], %[in4], %[in5] \t\n" + "nmadd.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 128*4(%[w2]) \t\n" + "lwc1 %[in4], 192*4(%[w]) \t\n" + "madd.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in5], 192*4(%[p]) \t\n" + "lwc1 %[in6], 192*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "lwc1 %[in1], 256*4(%[w]) \t\n" + "lwc1 %[in2], 256*4(%[p]) \t\n" + "madd.s %[sum], %[sum], %[in4], %[in5] \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 256*4(%[w2]) \t\n" + "lwc1 %[in4], 320*4(%[w]) \t\n" + "madd.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in5], 320*4(%[p]) \t\n" + "lwc1 %[in6], 320*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "lwc1 %[in1], 384*4(%[w]) \t\n" + "lwc1 %[in2], 384*4(%[p]) \t\n" + "madd.s %[sum], %[sum], %[in4], %[in5] \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 384*4(%[w2]) \t\n" + "lwc1 %[in4], 448*4(%[w]) \t\n" + "madd.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in5], 448*4(%[p]) \t\n" + "lwc1 %[in6], 448*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "madd.s %[sum], %[sum], %[in4], %[in5] \t\n" + "lwc1 %[in1], 32*4(%[w]) \t\n" + "lwc1 %[in2], 0(%[p2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 32*4(%[w2]) \t\n" + "lwc1 %[in4], 96*4(%[w]) \t\n" + "lwc1 %[in5], 64*4(%[p2]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in6], 96*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "lwc1 %[in1], 160*4(%[w]) \t\n" + "nmsub.s %[sum], %[sum], %[in4], %[in5] \t\n" + "lwc1 %[in2], 128*4(%[p2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 160*4(%[w2]) \t\n" + "lwc1 %[in4], 224*4(%[w]) \t\n" + "lwc1 %[in5], 192*4(%[p2]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in6], 224*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "lwc1 %[in1], 288*4(%[w]) \t\n" + "nmsub.s %[sum], %[sum], %[in4], %[in5] \t\n" + "lwc1 %[in2], 256*4(%[p2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 288*4(%[w2]) \t\n" + "lwc1 %[in4], 352*4(%[w]) \t\n" + "lwc1 %[in5], 320*4(%[p2]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in6], 352*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "lwc1 %[in1], 416*4(%[w]) \t\n" + "nmsub.s %[sum], %[sum], %[in4], %[in5] \t\n" + "lwc1 %[in2], 384*4(%[p2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "lwc1 %[in3], 416*4(%[w2]) \t\n" + "lwc1 %[in4], 480*4(%[w]) \t\n" + "lwc1 %[in5], 448*4(%[p2]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in6], 480*4(%[w2]) \t\n" + "nmsub.s %[sum2], %[sum2], %[in2], %[in3] \t\n" + "addiu %[w], %[w], 4 \t\n" + "nmsub.s %[sum], %[sum], %[in4], %[in5] \t\n" + "addiu %[w2], %[w2], -4 \t\n" + "nmsub.s %[sum2], %[sum2], %[in5], %[in6] \t\n" + "addu %[j], %[j], 4 \t\n" + "addiu %[p], 4 \t\n" + "swc1 %[sum], 0(%[samples]) \t\n" + "addiu %[p2], -4 \t\n" + "swc1 %[sum2], 0(%[samples2]) \t\n" + "addu %[samples], %[samples], %[incr1] \t\n" + "subu %[samples2], %[samples2], %[incr1] \t\n" + "bne %[j], 64, ff_mpadsp_apply_window_loop%= \t\n" + + "lwc1 %[in1], 48*4(%[window]) \t\n" + "lwc1 %[in2], 32*4(%[synth_buf]) \t\n" + "lwc1 %[in3], 112*4(%[window]) \t\n" + "lwc1 %[in4], 96*4(%[synth_buf]) \t\n" + "lwc1 %[in5], 176*4(%[window]) \t\n" + "lwc1 %[in6], 160*4(%[synth_buf]) \t\n" + "mul.s %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in7], 240*4(%[window]) \t\n" + "lwc1 %[in8], 224*4(%[synth_buf]) \t\n" + "lwc1 %[in1], 304*4(%[window]) \t\n" + "nmadd.s %[sum], %[sum], %[in3], %[in4] \t\n" + "lwc1 %[in2], 288*4(%[synth_buf]) \t\n" + "lwc1 %[in3], 368*4(%[window]) \t\n" + "lwc1 %[in4], 352*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in5], %[in6] \t\n" + "nmsub.s %[sum], %[sum], %[in7], %[in8] \t\n" + "lwc1 %[in5], 432*4(%[window]) \t\n" + "lwc1 %[in6], 416*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in1], %[in2] \t\n" + "lwc1 %[in7], 496*4(%[window]) \t\n" + "lwc1 %[in8], 480*4(%[synth_buf]) \t\n" + "nmsub.s %[sum], %[sum], %[in3], %[in4] \t\n" + "nmsub.s %[sum], %[sum], %[in5], %[in6] \t\n" + "nmsub.s %[sum], %[sum], %[in7], %[in8] \t\n" + "swc1 %[sum], 0(%[samples]) \t\n" + + : [sum] "=&f" (sum), [sum2] "=&f" (sum2), + [w2] "=&r" (w2), [w] "=&r" (w), + [p] "=&r" (p), [p2] "=&r" (p2), [j] "=&r" (j), + [samples] "+r" (samples), [samples2] "=&r" (samples2), + [in1] "=&f" (in1), [in2] "=&f" (in2), + [in3] "=&f" (in3), [in4] "=&f" (in4), + [in5] "=&f" (in5), [in6] "=&f" (in6), + [in7] "=&f" (in7), [in8] "=&f" (in8), + [t_sample] "=&r" (t_sample) + : [synth_buf] "r" (synth_buf), [window] "r" (window), + [dither_state] "r" (dither_state), [incr1] "r" (incr1) + : "memory" + ); +} + +static void ff_dct32_mips_float(float *out, const float *tab) +{ + float val0 , val1 , val2 , val3 , val4 , val5 , val6 , val7, + val8 , val9 , val10, val11, val12, val13, val14, val15, + val16, val17, val18, val19, val20, val21, val22, val23, + val24, val25, val26, val27, val28, val29, val30, val31; + float fTmp1, fTmp2, fTmp3, fTmp4, fTmp5, fTmp6, fTmp7, fTmp8, + fTmp9, fTmp10, fTmp11; + + /** + * instructions are scheduled to minimize pipeline stall. + */ + __asm__ volatile ( + "lwc1 %[fTmp1], 0*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 31*4(%[tab]) \n\t" + "lwc1 %[fTmp3], 15*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 16*4(%[tab]) \n\t" + "li.s %[fTmp7], 0.50241928618815570551 \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp10], 0.50060299823519630134 \n\t" + "li.s %[fTmp11], 10.19000812354805681150 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "add.s %[val0], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val15], %[fTmp5], %[fTmp6] \n\t" + "lwc1 %[fTmp1], 7*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 24*4(%[tab]) \n\t" + "madd.s %[val16], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val31], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val15], %[val15], %[fTmp7] \n\t" + "lwc1 %[fTmp3], 8*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 23*4(%[tab]) \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val31], %[val31], %[fTmp7] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp7], 5.10114861868916385802 \n\t" + "li.s %[fTmp10], 0.67480834145500574602 \n\t" + "li.s %[fTmp11], 0.74453627100229844977 \n\t" + "add.s %[val7], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val8], %[fTmp5], %[fTmp6] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "li.s %[fTmp1], 0.50979557910415916894 \n\t" + "sub.s %[fTmp2], %[val0], %[val7] \n\t" + "mul.s %[val8], %[val8], %[fTmp7] \n\t" + "madd.s %[val23], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val24], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "add.s %[val0], %[val0], %[val7] \n\t" + "mul.s %[val7], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp2], %[val15], %[val8] \n\t" + "add.s %[val8], %[val15], %[val8] \n\t" + "mul.s %[val24], %[val24], %[fTmp7] \n\t" + "sub.s %[fTmp3], %[val16], %[val23] \n\t" + "add.s %[val16], %[val16], %[val23] \n\t" + "mul.s %[val15], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp4], %[val31], %[val24] \n\t" + "mul.s %[val23], %[fTmp1], %[fTmp3] \n\t" + "add.s %[val24], %[val31], %[val24] \n\t" + "mul.s %[val31], %[fTmp1], %[fTmp4] \n\t" + + : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), + [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), + [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), + [val0] "=f" (val0), [val7] "=f" (val7), + [val8] "=f" (val8), [val15] "=f" (val15), + [val16] "=f" (val16), [val23] "=f" (val23), + [val24] "=f" (val24), [val31] "=f" (val31) + : [tab] "r" (tab) + : "memory" + ); + + __asm__ volatile ( + "lwc1 %[fTmp1], 3*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 28*4(%[tab]) \n\t" + "lwc1 %[fTmp3], 12*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 19*4(%[tab]) \n\t" + "li.s %[fTmp7], 0.64682178335999012954 \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp10], 0.53104259108978417447 \n\t" + "li.s %[fTmp11], 1.48416461631416627724 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "add.s %[val3], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val12], %[fTmp5], %[fTmp6] \n\t" + "lwc1 %[fTmp1], 4*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 27*4(%[tab]) \n\t" + "madd.s %[val19], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val28], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val12], %[val12], %[fTmp7] \n\t" + "lwc1 %[fTmp3], 11*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 20*4(%[tab]) \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val28], %[val28], %[fTmp7] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "li.s %[fTmp7], 0.78815462345125022473 \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp10], 0.55310389603444452782 \n\t" + "li.s %[fTmp11], 1.16943993343288495515 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "add.s %[val4], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val11], %[fTmp5], %[fTmp6] \n\t" + "li.s %[fTmp1], 2.56291544774150617881 \n\t" + "madd.s %[val20], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val27], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val11], %[val11], %[fTmp7] \n\t" + "sub.s %[fTmp2], %[val3], %[val4] \n\t" + "add.s %[val3], %[val3], %[val4] \n\t" + "sub.s %[fTmp4], %[val19], %[val20] \n\t" + "mul.s %[val27], %[val27], %[fTmp7] \n\t" + "sub.s %[fTmp3], %[val12], %[val11] \n\t" + "mul.s %[val4], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val11], %[val12], %[val11] \n\t" + "add.s %[val19], %[val19], %[val20] \n\t" + "mul.s %[val20], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val12], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val28], %[val27] \n\t" + "add.s %[val27], %[val28], %[val27] \n\t" + "mul.s %[val28], %[fTmp1], %[fTmp2] \n\t" + + : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), + [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), + [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), + [val3] "=f" (val3), [val4] "=f" (val4), + [val11] "=f" (val11), [val12] "=f" (val12), + [val19] "=f" (val19), [val20] "=f" (val20), + [val27] "=f" (val27), [val28] "=f" (val28) + : [tab] "r" (tab) + : "memory" + ); + + __asm__ volatile ( + "li.s %[fTmp1], 0.54119610014619698439 \n\t" + "sub.s %[fTmp2], %[val0], %[val3] \n\t" + "add.s %[val0], %[val0], %[val3] \n\t" + "sub.s %[fTmp3], %[val7], %[val4] \n\t" + "add.s %[val4], %[val7], %[val4] \n\t" + "sub.s %[fTmp4], %[val8], %[val11] \n\t" + "mul.s %[val3], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val8], %[val8], %[val11] \n\t" + "mul.s %[val7], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val15], %[val12] \n\t" + "mul.s %[val11], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val12], %[val15], %[val12] \n\t" + "mul.s %[val15], %[fTmp1], %[fTmp2] \n\t" + + : [val0] "+f" (val0), [val3] "+f" (val3), + [val4] "+f" (val4), [val7] "+f" (val7), + [val8] "+f" (val8), [val11] "+f" (val11), + [val12] "+f" (val12), [val15] "+f" (val15), + [fTmp1] "=f" (fTmp1), [fTmp2] "=&f" (fTmp2), + [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4) + : + ); + + __asm__ volatile ( + "sub.s %[fTmp2], %[val16], %[val19] \n\t" + "add.s %[val16], %[val16], %[val19] \n\t" + "sub.s %[fTmp3], %[val23], %[val20] \n\t" + "add.s %[val20], %[val23], %[val20] \n\t" + "sub.s %[fTmp4], %[val24], %[val27] \n\t" + "mul.s %[val19], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val24], %[val24], %[val27] \n\t" + "mul.s %[val23], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val31], %[val28] \n\t" + "mul.s %[val27], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val28], %[val31], %[val28] \n\t" + "mul.s %[val31], %[fTmp1], %[fTmp2] \n\t" + + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val16] "+f" (val16), [val19] "+f" (val19), [val20] "+f" (val20), + [val23] "+f" (val23), [val24] "+f" (val24), [val27] "+f" (val27), + [val28] "+f" (val28), [val31] "+f" (val31) + : [fTmp1] "f" (fTmp1) + ); + + __asm__ volatile ( + "lwc1 %[fTmp1], 1*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 30*4(%[tab]) \n\t" + "lwc1 %[fTmp3], 14*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 17*4(%[tab]) \n\t" + "li.s %[fTmp7], 0.52249861493968888062 \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp10], 0.50547095989754365998 \n\t" + "li.s %[fTmp11], 3.40760841846871878570 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "add.s %[val1], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val14], %[fTmp5], %[fTmp6] \n\t" + "lwc1 %[fTmp1], 6*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 25*4(%[tab]) \n\t" + "madd.s %[val17], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val30], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val14], %[val14], %[fTmp7] \n\t" + "lwc1 %[fTmp3], 9*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 22*4(%[tab]) \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "mul.s %[val30], %[val30], %[fTmp7] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp7], 1.72244709823833392782 \n\t" + "li.s %[fTmp10], 0.62250412303566481615 \n\t" + "li.s %[fTmp11], 0.83934964541552703873 \n\t" + "add.s %[val6], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val9], %[fTmp5], %[fTmp6] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "li.s %[fTmp1], 0.60134488693504528054 \n\t" + "sub.s %[fTmp2], %[val1], %[val6] \n\t" + "add.s %[val1], %[val1], %[val6] \n\t" + "mul.s %[val9], %[val9], %[fTmp7] \n\t" + "madd.s %[val22], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val25], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val6], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp2], %[val14], %[val9] \n\t" + "add.s %[val9], %[val14], %[val9] \n\t" + "mul.s %[val25], %[val25], %[fTmp7] \n\t" + "sub.s %[fTmp3], %[val17], %[val22] \n\t" + "add.s %[val17], %[val17], %[val22] \n\t" + "mul.s %[val14], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp2], %[val30], %[val25] \n\t" + "mul.s %[val22], %[fTmp1], %[fTmp3] \n\t" + "add.s %[val25], %[val30], %[val25] \n\t" + "mul.s %[val30], %[fTmp1], %[fTmp2] \n\t" + + : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), + [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), + [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), + [val1] "=f" (val1), [val6] "=f" (val6), + [val9] "=f" (val9), [val14] "=f" (val14), + [val17] "=f" (val17), [val22] "=f" (val22), + [val25] "=f" (val25), [val30] "=f" (val30) + : [tab] "r" (tab) + : "memory" + ); + + __asm__ volatile ( + "lwc1 %[fTmp1], 2*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 29*4(%[tab]) \n\t" + "lwc1 %[fTmp3], 13*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 18*4(%[tab]) \n\t" + "li.s %[fTmp7], 0.56694403481635770368 \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp10], 0.51544730992262454697 \n\t" + "li.s %[fTmp11], 2.05778100995341155085 \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "add.s %[val2], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val13], %[fTmp5], %[fTmp6] \n\t" + "lwc1 %[fTmp1], 5*4(%[tab]) \n\t" + "lwc1 %[fTmp2], 26*4(%[tab]) \n\t" + "madd.s %[val18], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val29], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "mul.s %[val13], %[val13], %[fTmp7] \n\t" + "lwc1 %[fTmp3], 10*4(%[tab]) \n\t" + "lwc1 %[fTmp4], 21*4(%[tab]) \n\t" + "mul.s %[val29], %[val29], %[fTmp7] \n\t" + "add.s %[fTmp5], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp8], %[fTmp1], %[fTmp2] \n\t" + "add.s %[fTmp6], %[fTmp3], %[fTmp4] \n\t" + "sub.s %[fTmp9], %[fTmp3], %[fTmp4] \n\t" + "li.s %[fTmp7], 1.06067768599034747134 \n\t" + "li.s %[fTmp10], 0.58293496820613387367 \n\t" + "li.s %[fTmp11], 0.97256823786196069369 \n\t" + "add.s %[val5], %[fTmp5], %[fTmp6] \n\t" + "sub.s %[val10], %[fTmp5], %[fTmp6] \n\t" + "mul.s %[fTmp8], %[fTmp8], %[fTmp10] \n\t" + "li.s %[fTmp1], 0.89997622313641570463 \n\t" + "sub.s %[fTmp2], %[val2], %[val5] \n\t" + "mul.s %[val10], %[val10], %[fTmp7] \n\t" + "madd.s %[val21], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "nmsub.s %[val26], %[fTmp8], %[fTmp9], %[fTmp11] \n\t" + "add.s %[val2], %[val2], %[val5] \n\t" + "mul.s %[val5], %[fTmp1], %[fTmp2] \n\t" + "sub.s %[fTmp3], %[val13], %[val10] \n\t" + "add.s %[val10], %[val13], %[val10] \n\t" + "mul.s %[val26], %[val26], %[fTmp7] \n\t" + "sub.s %[fTmp4], %[val18], %[val21] \n\t" + "add.s %[val18], %[val18], %[val21] \n\t" + "mul.s %[val13], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val29], %[val26] \n\t" + "add.s %[val26], %[val29], %[val26] \n\t" + "mul.s %[val21], %[fTmp1], %[fTmp4] \n\t" + "mul.s %[val29], %[fTmp1], %[fTmp2] \n\t" + + : [fTmp1] "=&f" (fTmp1), [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), + [fTmp4] "=&f" (fTmp4), [fTmp5] "=&f" (fTmp5), [fTmp6] "=&f" (fTmp6), + [fTmp7] "=&f" (fTmp7), [fTmp8] "=&f" (fTmp8), [fTmp9] "=&f" (fTmp9), + [fTmp10] "=&f" (fTmp10), [fTmp11] "=&f" (fTmp11), + [val2] "=f" (val2), [val5] "=f" (val5), + [val10] "=f" (val10), [val13] "=f" (val13), + [val18] "=f" (val18), [val21] "=f" (val21), + [val26] "=f" (val26), [val29] "=f" (val29) + : [tab] "r" (tab) + : "memory" + ); + + __asm__ volatile ( + "li.s %[fTmp1], 1.30656296487637652785 \n\t" + "sub.s %[fTmp2], %[val1], %[val2] \n\t" + "add.s %[val1], %[val1], %[val2] \n\t" + "sub.s %[fTmp3], %[val6], %[val5] \n\t" + "add.s %[val5], %[val6], %[val5] \n\t" + "sub.s %[fTmp4], %[val9], %[val10] \n\t" + "mul.s %[val2], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val9], %[val9], %[val10] \n\t" + "mul.s %[val6], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val14], %[val13] \n\t" + "mul.s %[val10], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val13], %[val14], %[val13] \n\t" + "mul.s %[val14], %[fTmp1], %[fTmp2] \n\t" + + : [fTmp1] "=f" (fTmp1), [fTmp2] "=&f" (fTmp2), + [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val1] "+f" (val1), [val2] "+f" (val2), + [val5] "+f" (val5), [val6] "+f" (val6), + [val9] "+f" (val9), [val10] "+f" (val10), + [val13] "+f" (val13), [val14] "+f" (val14) + : + ); + + __asm__ volatile ( + "sub.s %[fTmp2], %[val17], %[val18] \n\t" + "add.s %[val17], %[val17], %[val18] \n\t" + "sub.s %[fTmp3], %[val22], %[val21] \n\t" + "add.s %[val21], %[val22], %[val21] \n\t" + "sub.s %[fTmp4], %[val25], %[val26] \n\t" + "mul.s %[val18], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val25], %[val25], %[val26] \n\t" + "mul.s %[val22], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val30], %[val29] \n\t" + "mul.s %[val26], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val29], %[val30], %[val29] \n\t" + "mul.s %[val30], %[fTmp1], %[fTmp2] \n\t" + + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val17] "+f" (val17), [val18] "+f" (val18), [val21] "+f" (val21), + [val22] "+f" (val22), [val25] "+f" (val25), [val26] "+f" (val26), + [val29] "+f" (val29), [val30] "+f" (val30) + : [fTmp1] "f" (fTmp1) + ); + + __asm__ volatile ( + "li.s %[fTmp1], 0.70710678118654752439 \n\t" + "sub.s %[fTmp2], %[val0], %[val1] \n\t" + "add.s %[val0], %[val0], %[val1] \n\t" + "sub.s %[fTmp3], %[val3], %[val2] \n\t" + "add.s %[val2], %[val3], %[val2] \n\t" + "sub.s %[fTmp4], %[val4], %[val5] \n\t" + "mul.s %[val1], %[fTmp1], %[fTmp2] \n\t" + "swc1 %[val0], 0(%[out]) \n\t" + "mul.s %[val3], %[fTmp3], %[fTmp1] \n\t" + "add.s %[val4], %[val4], %[val5] \n\t" + "mul.s %[val5], %[fTmp1], %[fTmp4] \n\t" + "swc1 %[val1], 16*4(%[out]) \n\t" + "sub.s %[fTmp2], %[val7], %[val6] \n\t" + "add.s %[val2], %[val2], %[val3] \n\t" + "swc1 %[val3], 24*4(%[out]) \n\t" + "add.s %[val6], %[val7], %[val6] \n\t" + "mul.s %[val7], %[fTmp1], %[fTmp2] \n\t" + "swc1 %[val2], 8*4(%[out]) \n\t" + "add.s %[val6], %[val6], %[val7] \n\t" + "swc1 %[val7], 28*4(%[out]) \n\t" + "add.s %[val4], %[val4], %[val6] \n\t" + "add.s %[val6], %[val6], %[val5] \n\t" + "add.s %[val5], %[val5], %[val7] \n\t" + "swc1 %[val4], 4*4(%[out]) \n\t" + "swc1 %[val5], 20*4(%[out]) \n\t" + "swc1 %[val6], 12*4(%[out]) \n\t" + + : [fTmp1] "=f" (fTmp1), [fTmp2] "=&f" (fTmp2), + [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val0] "+f" (val0), [val1] "+f" (val1), + [val2] "+f" (val2), [val3] "+f" (val3), + [val4] "+f" (val4), [val5] "+f" (val5), + [val6] "+f" (val6), [val7] "+f" (val7) + : [out] "r" (out) + ); + + __asm__ volatile ( + "sub.s %[fTmp2], %[val8], %[val9] \n\t" + "add.s %[val8], %[val8], %[val9] \n\t" + "sub.s %[fTmp3], %[val11], %[val10] \n\t" + "add.s %[val10], %[val11], %[val10] \n\t" + "sub.s %[fTmp4], %[val12], %[val13] \n\t" + "mul.s %[val9], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val12], %[val12], %[val13] \n\t" + "mul.s %[val11], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val15], %[val14] \n\t" + "mul.s %[val13], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val14], %[val15], %[val14] \n\t" + "add.s %[val10], %[val10], %[val11] \n\t" + "mul.s %[val15], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val14], %[val14], %[val15] \n\t" + "add.s %[val12], %[val12], %[val14] \n\t" + "add.s %[val14], %[val14], %[val13] \n\t" + "add.s %[val13], %[val13], %[val15] \n\t" + "add.s %[val8], %[val8], %[val12] \n\t" + "add.s %[val12], %[val12], %[val10] \n\t" + "add.s %[val10], %[val10], %[val14] \n\t" + "add.s %[val14], %[val14], %[val9] \n\t" + "add.s %[val9], %[val9], %[val13] \n\t" + "add.s %[val13], %[val13], %[val11] \n\t" + "add.s %[val11], %[val11], %[val15] \n\t" + "swc1 %[val8], 2*4(%[out]) \n\t" + "swc1 %[val9], 18*4(%[out]) \n\t" + "swc1 %[val10], 10*4(%[out]) \n\t" + "swc1 %[val11], 26*4(%[out]) \n\t" + "swc1 %[val12], 6*4(%[out]) \n\t" + "swc1 %[val13], 22*4(%[out]) \n\t" + "swc1 %[val14], 14*4(%[out]) \n\t" + "swc1 %[val15], 30*4(%[out]) \n\t" + + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val8] "+f" (val8), [val9] "+f" (val9), [val10] "+f" (val10), + [val11] "+f" (val11), [val12] "+f" (val12), [val13] "+f" (val13), + [val14] "+f" (val14), [val15] "+f" (val15) + : [fTmp1] "f" (fTmp1), [out] "r" (out) + ); + + __asm__ volatile ( + "sub.s %[fTmp2], %[val16], %[val17] \n\t" + "add.s %[val16], %[val16], %[val17] \n\t" + "sub.s %[fTmp3], %[val19], %[val18] \n\t" + "add.s %[val18], %[val19], %[val18] \n\t" + "sub.s %[fTmp4], %[val20], %[val21] \n\t" + "mul.s %[val17], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val20], %[val20], %[val21] \n\t" + "mul.s %[val19], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val23], %[val22] \n\t" + "mul.s %[val21], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val22], %[val23], %[val22] \n\t" + "add.s %[val18], %[val18], %[val19] \n\t" + "mul.s %[val23], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val22], %[val22], %[val23] \n\t" + "add.s %[val20], %[val20], %[val22] \n\t" + "add.s %[val22], %[val22], %[val21] \n\t" + "add.s %[val21], %[val21], %[val23] \n\t" + + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val16] "+f" (val16), [val17] "+f" (val17), [val18] "+f" (val18), + [val19] "+f" (val19), [val20] "+f" (val20), [val21] "+f" (val21), + [val22] "+f" (val22), [val23] "+f" (val23) + : [fTmp1] "f" (fTmp1) + ); + + __asm__ volatile ( + "sub.s %[fTmp2], %[val24], %[val25] \n\t" + "add.s %[val24], %[val24], %[val25] \n\t" + "sub.s %[fTmp3], %[val27], %[val26] \n\t" + "add.s %[val26], %[val27], %[val26] \n\t" + "sub.s %[fTmp4], %[val28], %[val29] \n\t" + "mul.s %[val25], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val28], %[val28], %[val29] \n\t" + "mul.s %[val27], %[fTmp1], %[fTmp3] \n\t" + "sub.s %[fTmp2], %[val31], %[val30] \n\t" + "mul.s %[val29], %[fTmp1], %[fTmp4] \n\t" + "add.s %[val30], %[val31], %[val30] \n\t" + "add.s %[val26], %[val26], %[val27] \n\t" + "mul.s %[val31], %[fTmp1], %[fTmp2] \n\t" + "add.s %[val30], %[val30], %[val31] \n\t" + "add.s %[val28], %[val28], %[val30] \n\t" + "add.s %[val30], %[val30], %[val29] \n\t" + "add.s %[val29], %[val29], %[val31] \n\t" + "add.s %[val24], %[val24], %[val28] \n\t" + "add.s %[val28], %[val28], %[val26] \n\t" + "add.s %[val26], %[val26], %[val30] \n\t" + "add.s %[val30], %[val30], %[val25] \n\t" + "add.s %[val25], %[val25], %[val29] \n\t" + "add.s %[val29], %[val29], %[val27] \n\t" + "add.s %[val27], %[val27], %[val31] \n\t" + + : [fTmp2] "=&f" (fTmp2), [fTmp3] "=&f" (fTmp3), [fTmp4] "=&f" (fTmp4), + [val24] "+f" (val24), [val25] "+f" (val25), [val26] "+f" (val26), + [val27] "+f" (val27), [val28] "+f" (val28), [val29] "+f" (val29), + [val30] "+f" (val30), [val31] "+f" (val31) + : [fTmp1] "f" (fTmp1) + ); + + out[ 1] = val16 + val24; + out[17] = val17 + val25; + out[ 9] = val18 + val26; + out[25] = val19 + val27; + out[ 5] = val20 + val28; + out[21] = val21 + val29; + out[13] = val22 + val30; + out[29] = val23 + val31; + out[ 3] = val24 + val20; + out[19] = val25 + val21; + out[11] = val26 + val22; + out[27] = val27 + val23; + out[ 7] = val28 + val18; + out[23] = val29 + val19; + out[15] = val30 + val17; + out[31] = val31; +} + +static void imdct36_mips_float(float *out, float *buf, float *in, float *win) +{ + float t0, t1, t2, t3, s0, s1, s2, s3; + float tmp[18]; + /* temporary variables */ + float in1, in2, in3, in4, in5, in6; + float out1, out2, out3, out4, out5; + float c1, c2, c3, c4, c5, c6, c7, c8, c9; + + /** + * all loops are unrolled totally, and instructions are scheduled to + * minimize pipeline stall. instructions of the first two loops are + * reorganized, in order to eliminate unnecessary readings and + * writings into array. values defined in macros and tables are + * eliminated - they are directly loaded in appropriate variables + */ + + /* loop 1 and 2 */ + __asm__ volatile ( + "lwc1 %[in1], 17*4(%[in]) \t\n" + "lwc1 %[in2], 16*4(%[in]) \t\n" + "lwc1 %[in3], 15*4(%[in]) \t\n" + "lwc1 %[in4], 14*4(%[in]) \t\n" + "lwc1 %[in5], 13*4(%[in]) \t\n" + "lwc1 %[in6], 12*4(%[in]) \t\n" + "add.s %[out1], %[in1], %[in2] \t\n" + "add.s %[out2], %[in2], %[in3] \t\n" + "add.s %[out3], %[in3], %[in4] \t\n" + "add.s %[out4], %[in4], %[in5] \t\n" + "add.s %[out5], %[in5], %[in6] \t\n" + "lwc1 %[in1], 11*4(%[in]) \t\n" + "swc1 %[out2], 16*4(%[in]) \t\n" + "add.s %[out1], %[out1], %[out3] \t\n" + "swc1 %[out4], 14*4(%[in]) \t\n" + "add.s %[out3], %[out3], %[out5] \t\n" + "lwc1 %[in2], 10*4(%[in]) \t\n" + "lwc1 %[in3], 9*4(%[in]) \t\n" + "swc1 %[out1], 17*4(%[in]) \t\n" + "lwc1 %[in4], 8*4(%[in]) \t\n" + "swc1 %[out3], 15*4(%[in]) \t\n" + "add.s %[out1], %[in6], %[in1] \t\n" + "add.s %[out2], %[in1], %[in2] \t\n" + "add.s %[out3], %[in2], %[in3] \t\n" + "add.s %[out4], %[in3], %[in4] \t\n" + "lwc1 %[in5], 7*4(%[in]) \t\n" + "swc1 %[out1], 12*4(%[in]) \t\n" + "add.s %[out5], %[out5], %[out2] \t\n" + "swc1 %[out3], 10*4(%[in]) \t\n" + "add.s %[out2], %[out2], %[out4] \t\n" + "lwc1 %[in6], 6*4(%[in]) \t\n" + "lwc1 %[in1], 5*4(%[in]) \t\n" + "swc1 %[out5], 13*4(%[in]) \t\n" + "lwc1 %[in2], 4*4(%[in]) \t\n" + "swc1 %[out2], 11*4(%[in]) \t\n" + "add.s %[out5], %[in4], %[in5] \t\n" + "add.s %[out1], %[in5], %[in6] \t\n" + "add.s %[out2], %[in6], %[in1] \t\n" + "add.s %[out3], %[in1], %[in2] \t\n" + "lwc1 %[in3], 3*4(%[in]) \t\n" + "swc1 %[out5], 8*4(%[in]) \t\n" + "add.s %[out4], %[out4], %[out1] \t\n" + "swc1 %[out2], 6*4(%[in]) \t\n" + "add.s %[out1], %[out1], %[out3] \t\n" + "lwc1 %[in4], 2*4(%[in]) \t\n" + "lwc1 %[in5], 1*4(%[in]) \t\n" + "swc1 %[out4], 9*4(%[in]) \t\n" + "lwc1 %[in6], 0(%[in]) \t\n" + "swc1 %[out1], 7*4(%[in]) \t\n" + "add.s %[out4], %[in2], %[in3] \t\n" + "add.s %[out5], %[in3], %[in4] \t\n" + "add.s %[out1], %[in4], %[in5] \t\n" + "add.s %[out2], %[in5], %[in6] \t\n" + "swc1 %[out4], 4*4(%[in]) \t\n" + "add.s %[out3], %[out3], %[out5] \t\n" + "swc1 %[out1], 2*4(%[in]) \t\n" + "add.s %[out5], %[out5], %[out2] \t\n" + "swc1 %[out2], 1*4(%[in]) \t\n" + "swc1 %[out3], 5*4(%[in]) \t\n" + "swc1 %[out5], 3*4(%[in]) \t\n" + + : [in1] "=&f" (in1), [in2] "=&f" (in2), + [in3] "=&f" (in3), [in4] "=&f" (in4), + [in5] "=&f" (in5), [in6] "=&f" (in6), + [out1] "=&f" (out1), [out2] "=&f" (out2), + [out3] "=&f" (out3), [out4] "=&f" (out4), + [out5] "=&f" (out5) + : [in] "r" (in) + : "memory" + ); + + /* loop 3 */ + __asm__ volatile ( + "li.s %[c1], 0.5 \t\n" + "lwc1 %[in1], 8*4(%[in]) \t\n" + "lwc1 %[in2], 16*4(%[in]) \t\n" + "lwc1 %[in3], 4*4(%[in]) \t\n" + "lwc1 %[in4], 0(%[in]) \t\n" + "lwc1 %[in5], 12*4(%[in]) \t\n" + "li.s %[c2], 0.93969262078590838405 \t\n" + "add.s %[t2], %[in1], %[in2] \t\n" + "add.s %[t0], %[in1], %[in3] \t\n" + "li.s %[c3], -0.76604444311897803520 \t\n" + "madd.s %[t3], %[in4], %[in5], %[c1] \t\n" + "sub.s %[t1], %[in4], %[in5] \t\n" + "sub.s %[t2], %[t2], %[in3] \t\n" + "mul.s %[t0], %[t0], %[c2] \t\n" + "li.s %[c4], -0.17364817766693034885 \t\n" + "li.s %[c5], -0.86602540378443864676 \t\n" + "li.s %[c6], 0.98480775301220805936 \t\n" + "nmsub.s %[out1], %[t1], %[t2], %[c1] \t\n" + "add.s %[out2], %[t1], %[t2] \t\n" + "add.s %[t2], %[in2], %[in3] \t\n" + "sub.s %[t1], %[in1], %[in2] \t\n" + "sub.s %[out3], %[t3], %[t0] \t\n" + "swc1 %[out1], 6*4(%[tmp]) \t\n" + "swc1 %[out2], 16*4(%[tmp]) \t\n" + "mul.s %[t2], %[t2], %[c3] \t\n" + "mul.s %[t1], %[t1], %[c4] \t\n" + "add.s %[out1], %[t3], %[t0] \t\n" + "lwc1 %[in1], 10*4(%[in]) \t\n" + "lwc1 %[in2], 14*4(%[in]) \t\n" + "sub.s %[out3], %[out3], %[t2] \t\n" + "add.s %[out2], %[t3], %[t2] \t\n" + "add.s %[out1], %[out1], %[t1] \t\n" + "lwc1 %[in3], 2*4(%[in]) \t\n" + "lwc1 %[in4], 6*4(%[in]) \t\n" + "swc1 %[out3], 10*4(%[tmp]) \t\n" + "sub.s %[out2], %[out2], %[t1] \t\n" + "swc1 %[out1], 2*4(%[tmp]) \t\n" + "add.s %[out1], %[in1], %[in2] \t\n" + "add.s %[t2], %[in1], %[in3] \t\n" + "sub.s %[t3], %[in1], %[in2] \t\n" + "swc1 %[out2], 14*4(%[tmp]) \t\n" + "li.s %[c7], -0.34202014332566873304 \t\n" + "sub.s %[out1], %[out1], %[in3] \t\n" + "mul.s %[t2], %[t2], %[c6] \t\n" + "mul.s %[t3], %[t3], %[c7] \t\n" + "li.s %[c8], 0.86602540378443864676 \t\n" + "mul.s %[t0], %[in4], %[c8] \t\n" + "mul.s %[out1], %[out1], %[c5] \t\n" + "add.s %[t1], %[in2], %[in3] \t\n" + "li.s %[c9], -0.64278760968653932632 \t\n" + "add.s %[out2], %[t2], %[t3] \t\n" + "lwc1 %[in1], 9*4(%[in]) \t\n" + "swc1 %[out1], 4*4(%[tmp]) \t\n" + "mul.s %[t1], %[t1], %[c9] \t\n" + "lwc1 %[in2], 17*4(%[in]) \t\n" + "add.s %[out2], %[out2], %[t0] \t\n" + "lwc1 %[in3], 5*4(%[in]) \t\n" + "lwc1 %[in4], 1*4(%[in]) \t\n" + "add.s %[out3], %[t2], %[t1] \t\n" + "sub.s %[out1], %[t3], %[t1] \t\n" + "swc1 %[out2], 0(%[tmp]) \t\n" + "lwc1 %[in5], 13*4(%[in]) \t\n" + "add.s %[t2], %[in1], %[in2] \t\n" + "sub.s %[out3], %[out3], %[t0] \t\n" + "sub.s %[out1], %[out1], %[t0] \t\n" + "add.s %[t0], %[in1], %[in3] \t\n" + "madd.s %[t3], %[in4], %[in5], %[c1] \t\n" + "sub.s %[t2], %[t2], %[in3] \t\n" + "swc1 %[out3], 12*4(%[tmp]) \t\n" + "swc1 %[out1], 8*4(%[tmp]) \t\n" + "sub.s %[t1], %[in4], %[in5] \t\n" + "mul.s %[t0], %[t0], %[c2] \t\n" + "nmsub.s %[out1], %[t1], %[t2], %[c1] \t\n" + "add.s %[out2], %[t1], %[t2] \t\n" + "add.s %[t2], %[in2], %[in3] \t\n" + "sub.s %[t1], %[in1], %[in2] \t\n" + "sub.s %[out3], %[t3], %[t0] \t\n" + "swc1 %[out1], 7*4(%[tmp]) \t\n" + "swc1 %[out2], 17*4(%[tmp]) \t\n" + "mul.s %[t2], %[t2], %[c3] \t\n" + "mul.s %[t1], %[t1], %[c4] \t\n" + "add.s %[out1], %[t3], %[t0] \t\n" + "lwc1 %[in1], 11*4(%[in]) \t\n" + "lwc1 %[in2], 15*4(%[in]) \t\n" + "sub.s %[out3], %[out3], %[t2] \t\n" + "add.s %[out2], %[t3], %[t2] \t\n" + "add.s %[out1], %[out1], %[t1] \t\n" + "lwc1 %[in3], 3*4(%[in]) \t\n" + "lwc1 %[in4], 7*4(%[in]) \t\n" + "swc1 %[out3], 11*4(%[tmp]) \t\n" + "sub.s %[out2], %[out2], %[t1] \t\n" + "swc1 %[out1], 3*4(%[tmp]) \t\n" + "add.s %[out3], %[in1], %[in2] \t\n" + "add.s %[t2], %[in1], %[in3] \t\n" + "sub.s %[t3], %[in1], %[in2] \t\n" + "swc1 %[out2], 15*4(%[tmp]) \t\n" + "mul.s %[t0], %[in4], %[c8] \t\n" + "sub.s %[out3], %[out3], %[in3] \t\n" + "mul.s %[t2], %[t2], %[c6] \t\n" + "mul.s %[t3], %[t3], %[c7] \t\n" + "add.s %[t1], %[in2], %[in3] \t\n" + "mul.s %[out3], %[out3], %[c5] \t\n" + "add.s %[out1], %[t2], %[t3] \t\n" + "mul.s %[t1], %[t1], %[c9] \t\n" + "swc1 %[out3], 5*4(%[tmp]) \t\n" + "add.s %[out1], %[out1], %[t0] \t\n" + "add.s %[out2], %[t2], %[t1] \t\n" + "sub.s %[out3], %[t3], %[t1] \t\n" + "swc1 %[out1], 1*4(%[tmp]) \t\n" + "sub.s %[out2], %[out2], %[t0] \t\n" + "sub.s %[out3], %[out3], %[t0] \t\n" + "swc1 %[out2], 13*4(%[tmp]) \t\n" + "swc1 %[out3], 9*4(%[tmp]) \t\n" + + : [t0] "=&f" (t0), [t1] "=&f" (t1), + [t2] "=&f" (t2), [t3] "=&f" (t3), + [in1] "=&f" (in1), [in2] "=&f" (in2), + [in3] "=&f" (in3), [in4] "=&f" (in4), + [in5] "=&f" (in5), + [out1] "=&f" (out1), [out2] "=&f" (out2), + [out3] "=&f" (out3), + [c1] "=&f" (c1), [c2] "=&f" (c2), + [c3] "=&f" (c3), [c4] "=&f" (c4), + [c5] "=&f" (c5), [c6] "=&f" (c6), + [c7] "=&f" (c7), [c8] "=&f" (c8), + [c9] "=&f" (c9) + : [in] "r" (in), [tmp] "r" (tmp) + : "memory" + ); + + /* loop 4 */ + __asm__ volatile ( + "lwc1 %[in1], 2*4(%[tmp]) \t\n" + "lwc1 %[in2], 0(%[tmp]) \t\n" + "lwc1 %[in3], 3*4(%[tmp]) \t\n" + "lwc1 %[in4], 1*4(%[tmp]) \t\n" + "li.s %[c1], 0.50190991877167369479 \t\n" + "li.s %[c2], 5.73685662283492756461 \t\n" + "add.s %[s0], %[in1], %[in2] \t\n" + "sub.s %[s2], %[in1], %[in2] \t\n" + "add.s %[s1], %[in3], %[in4] \t\n" + "sub.s %[s3], %[in3], %[in4] \t\n" + "lwc1 %[in1], 9*4(%[win]) \t\n" + "lwc1 %[in2], 4*9*4(%[buf]) \t\n" + "lwc1 %[in3], 8*4(%[win]) \t\n" + "mul.s %[s1], %[s1], %[c1] \t\n" + "mul.s %[s3], %[s3], %[c2] \t\n" + "lwc1 %[in4], 4*8*4(%[buf]) \t\n" + "lwc1 %[in5], 29*4(%[win]) \t\n" + "lwc1 %[in6], 28*4(%[win]) \t\n" + "add.s %[t0], %[s0], %[s1] \t\n" + "sub.s %[t1], %[s0], %[s1] \t\n" + "li.s %[c1], 0.51763809020504152469 \t\n" + "li.s %[c2], 1.93185165257813657349 \t\n" + "mul.s %[out3], %[in5], %[t0] \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out4], %[in6], %[t0] \t\n" + "add.s %[t0], %[s2], %[s3] \t\n" + "swc1 %[out3], 4*9*4(%[buf]) \t\n" + "swc1 %[out1], 288*4(%[out]) \t\n" + "swc1 %[out2], 256*4(%[out]) \t\n" + "swc1 %[out4], 4*8*4(%[buf]) \t\n" + "sub.s %[t1], %[s2], %[s3] \t\n" + "lwc1 %[in1], 17*4(%[win]) \t\n" + "lwc1 %[in2], 4*17*4(%[buf]) \t\n" + "lwc1 %[in3], 0(%[win]) \t\n" + "lwc1 %[in4], 0(%[buf]) \t\n" + "lwc1 %[in5], 37*4(%[win]) \t\n" + "lwc1 %[in6], 20*4(%[win]) \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "lwc1 %[in1], 6*4(%[tmp]) \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out3], %[t0], %[in5] \t\n" + "mul.s %[out4], %[t0], %[in6] \t\n" + "swc1 %[out1], 544*4(%[out]) \t\n" + "lwc1 %[in2], 4*4(%[tmp]) \t\n" + "swc1 %[out2], 0(%[out]) \t\n" + "swc1 %[out3], 4*17*4(%[buf]) \t\n" + "swc1 %[out4], 0(%[buf]) \t\n" + "lwc1 %[in3], 7*4(%[tmp]) \t\n" + "add.s %[s0], %[in1], %[in2] \t\n" + "sub.s %[s2], %[in1], %[in2] \t\n" + "lwc1 %[in4], 5*4(%[tmp]) \t\n" + "add.s %[s1], %[in3], %[in4] \t\n" + "sub.s %[s3], %[in3], %[in4] \t\n" + "lwc1 %[in1], 10*4(%[win]) \t\n" + "lwc1 %[in2], 4*10*4(%[buf]) \t\n" + "lwc1 %[in3], 7*4(%[win]) \t\n" + "mul.s %[s1], %[s1], %[c1] \t\n" + "mul.s %[s3], %[s3], %[c2] \t\n" + "add.s %[t0], %[s0], %[s1] \t\n" + "sub.s %[t1], %[s0], %[s1] \t\n" + "lwc1 %[in4], 4*7*4(%[buf]) \t\n" + "lwc1 %[in5], 30*4(%[win]) \t\n" + "lwc1 %[in6], 27*4(%[win]) \t\n" + "li.s %[c1], 0.55168895948124587824 \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out3], %[t0], %[in5] \t\n" + "mul.s %[out4], %[t0], %[in6] \t\n" + "add.s %[t0], %[s2], %[s3] \t\n" + "swc1 %[out1], 320*4(%[out]) \t\n" + "swc1 %[out2], 224*4(%[out]) \t\n" + "swc1 %[out3], 4*10*4(%[buf]) \t\n" + "swc1 %[out4], 4*7*4(%[buf]) \t\n" + "sub.s %[t1], %[s2], %[s3] \t\n" + "lwc1 %[in1], 16*4(%[win]) \t\n" + "lwc1 %[in2], 4*16*4(%[buf]) \t\n" + "lwc1 %[in3], 1*4(%[win]) \t\n" + "lwc1 %[in4], 4*1*4(%[buf]) \t\n" + "lwc1 %[in5], 36*4(%[win]) \t\n" + "lwc1 %[in6], 21*4(%[win]) \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "lwc1 %[in1], 10*4(%[tmp]) \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out3], %[in5], %[t0] \t\n" + "mul.s %[out4], %[in6], %[t0] \t\n" + "swc1 %[out1], 512*4(%[out]) \t\n" + "lwc1 %[in2], 8*4(%[tmp]) \t\n" + "swc1 %[out2], 32*4(%[out]) \t\n" + "swc1 %[out3], 4*16*4(%[buf]) \t\n" + "swc1 %[out4], 4*1*4(%[buf]) \t\n" + "li.s %[c2], 1.18310079157624925896 \t\n" + "add.s %[s0], %[in1], %[in2] \t\n" + "sub.s %[s2], %[in1], %[in2] \t\n" + "lwc1 %[in3], 11*4(%[tmp]) \t\n" + "lwc1 %[in4], 9*4(%[tmp]) \t\n" + "add.s %[s1], %[in3], %[in4] \t\n" + "sub.s %[s3], %[in3], %[in4] \t\n" + "lwc1 %[in1], 11*4(%[win]) \t\n" + "lwc1 %[in2], 4*11*4(%[buf]) \t\n" + "lwc1 %[in3], 6*4(%[win]) \t\n" + "mul.s %[s1], %[s1], %[c1] \t\n" + "mul.s %[s3], %[s3], %[c2] \t\n" + "lwc1 %[in4], 4*6*4(%[buf]) \t\n" + "lwc1 %[in5], 31*4(%[win]) \t\n" + "lwc1 %[in6], 26*4(%[win]) \t\n" + "add.s %[t0], %[s0], %[s1] \t\n" + "sub.s %[t1], %[s0], %[s1] \t\n" + "mul.s %[out3], %[t0], %[in5] \t\n" + "mul.s %[out4], %[t0], %[in6] \t\n" + "add.s %[t0], %[s2], %[s3] \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "swc1 %[out3], 4*11*4(%[buf]) \t\n" + "swc1 %[out4], 4*6*4(%[buf]) \t\n" + "sub.s %[t1], %[s2], %[s3] \t\n" + "swc1 %[out1], 352*4(%[out]) \t\n" + "swc1 %[out2], 192*4(%[out]) \t\n" + "lwc1 %[in1], 15*4(%[win]) \t\n" + "lwc1 %[in2], 4*15*4(%[buf]) \t\n" + "lwc1 %[in3], 2*4(%[win]) \t\n" + "lwc1 %[in4], 4*2*4(%[buf]) \t\n" + "lwc1 %[in5], 35*4(%[win]) \t\n" + "lwc1 %[in6], 22*4(%[win]) \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "lwc1 %[in1], 14*4(%[tmp]) \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out3], %[t0], %[in5] \t\n" + "mul.s %[out4], %[t0], %[in6] \t\n" + "swc1 %[out1], 480*4(%[out]) \t\n" + "lwc1 %[in2], 12*4(%[tmp]) \t\n" + "swc1 %[out2], 64*4(%[out]) \t\n" + "swc1 %[out3], 4*15*4(%[buf]) \t\n" + "swc1 %[out4], 4*2*4(%[buf]) \t\n" + "lwc1 %[in3], 15*4(%[tmp]) \t\n" + "add.s %[s0], %[in1], %[in2] \t\n" + "sub.s %[s2], %[in1], %[in2] \t\n" + "lwc1 %[in4], 13*4(%[tmp]) \t\n" + "li.s %[c1], 0.61038729438072803416 \t\n" + "li.s %[c2], 0.87172339781054900991 \t\n" + "add.s %[s1], %[in3], %[in4] \t\n" + "sub.s %[s3], %[in3], %[in4] \t\n" + "lwc1 %[in1], 12*4(%[win]) \t\n" + "lwc1 %[in2], 4*12*4(%[buf]) \t\n" + "lwc1 %[in3], 5*4(%[win]) \t\n" + "mul.s %[s1], %[s1], %[c1] \t\n" + "mul.s %[s3], %[s3], %[c2] \t\n" + "lwc1 %[in4], 4*5*4(%[buf]) \t\n" + "lwc1 %[in5], 32*4(%[win]) \t\n" + "lwc1 %[in6], 25*4(%[win]) \t\n" + "add.s %[t0], %[s0], %[s1] \t\n" + "sub.s %[t1], %[s0], %[s1] \t\n" + "lwc1 %[s0], 16*4(%[tmp]) \t\n" + "lwc1 %[s1], 17*4(%[tmp]) \t\n" + "li.s %[c1], 0.70710678118654752439 \t\n" + "mul.s %[out3], %[t0], %[in5] \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out4], %[t0], %[in6] \t\n" + "add.s %[t0], %[s2], %[s3] \t\n" + "swc1 %[out3], 4*12*4(%[buf]) \t\n" + "swc1 %[out1], 384*4(%[out]) \t\n" + "swc1 %[out2], 160*4(%[out]) \t\n" + "swc1 %[out4], 4*5*4(%[buf]) \t\n" + "sub.s %[t1], %[s2], %[s3] \t\n" + "lwc1 %[in1], 14*4(%[win]) \t\n" + "lwc1 %[in2], 4*14*4(%[buf]) \t\n" + "lwc1 %[in3], 3*4(%[win]) \t\n" + "lwc1 %[in4], 4*3*4(%[buf]) \t\n" + "lwc1 %[in5], 34*4(%[win]) \t\n" + "lwc1 %[in6], 23*4(%[win]) \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "mul.s %[s1], %[s1], %[c1] \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out3], %[in5], %[t0] \t\n" + "mul.s %[out4], %[in6], %[t0] \t\n" + "swc1 %[out1], 448*4(%[out]) \t\n" + "add.s %[t0], %[s0], %[s1] \t\n" + "swc1 %[out2], 96*4(%[out]) \t\n" + "swc1 %[out3], 4*14*4(%[buf]) \t\n" + "swc1 %[out4], 4*3*4(%[buf]) \t\n" + "sub.s %[t1], %[s0], %[s1] \t\n" + "lwc1 %[in1], 13*4(%[win]) \t\n" + "lwc1 %[in2], 4*13*4(%[buf]) \t\n" + "lwc1 %[in3], 4*4(%[win]) \t\n" + "lwc1 %[in4], 4*4*4(%[buf]) \t\n" + "lwc1 %[in5], 33*4(%[win]) \t\n" + "lwc1 %[in6], 24*4(%[win]) \t\n" + "madd.s %[out1], %[in2], %[in1], %[t1] \t\n" + "madd.s %[out2], %[in4], %[in3], %[t1] \t\n" + "mul.s %[out3], %[t0], %[in5] \t\n" + "mul.s %[out4], %[t0], %[in6] \t\n" + "swc1 %[out1], 416*4(%[out]) \t\n" + "swc1 %[out2], 128*4(%[out]) \t\n" + "swc1 %[out3], 4*13*4(%[buf]) \t\n" + "swc1 %[out4], 4*4*4(%[buf]) \t\n" + + : [c1] "=&f" (c1), [c2] "=&f" (c2), + [in1] "=&f" (in1), [in2] "=&f" (in2), + [in3] "=&f" (in3), [in4] "=&f" (in4), + [in5] "=&f" (in5), [in6] "=&f" (in6), + [out1] "=&f" (out1), [out2] "=&f" (out2), + [out3] "=&f" (out3), [out4] "=&f" (out4), + [t0] "=&f" (t0), [t1] "=&f" (t1), + [t2] "=&f" (t2), [t3] "=&f" (t3), + [s0] "=&f" (s0), [s1] "=&f" (s1), + [s2] "=&f" (s2), [s3] "=&f" (s3) + : [tmp] "r" (tmp), [win] "r" (win), + [buf] "r" (buf), [out] "r" (out) + : "memory" + ); +} + +static void ff_imdct36_blocks_mips_float(float *out, float *buf, float *in, + int count, int switch_point, int block_type) +{ + int j; + for (j=0 ; j < count; j++) { + /* apply window & overlap with previous buffer */ + + /* select window */ + int win_idx = (switch_point && j < 2) ? 0 : block_type; + float *win = ff_mdct_win_float[win_idx + (4 & -(j & 1))]; + + imdct36_mips_float(out, buf, in, win); + + in += 18; + buf += ((j&3) != 3 ? 1 : (72-3)); + out++; + } +} + +void ff_mpadsp_init_mipsfpu(MPADSPContext *s) +{ + s->apply_window_float = ff_mpadsp_apply_window_mips_float; + s->imdct36_blocks_float = ff_imdct36_blocks_mips_float; + s->dct32_float = ff_dct32_mips_float; +} diff --git a/ffmpeg/libavcodec/mips/sbrdsp_mips.c b/ffmpeg/libavcodec/mips/sbrdsp_mips.c new file mode 100644 index 0000000..d4460ba --- /dev/null +++ b/ffmpeg/libavcodec/mips/sbrdsp_mips.c @@ -0,0 +1,940 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Authors: Darko Laus (darko@mips.com) + * Djordje Pesut (djordje@mips.com) + * Mirjana Vulin (mvulin@mips.com) + * + * AAC Spectral Band Replication decoding functions optimized for MIPS + * + * 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 + */ + +/** + * @file + * Reference: libavcodec/sbrdsp.c + */ + +#include "config.h" +#include "libavcodec/sbrdsp.h" + +#if HAVE_INLINE_ASM +static void sbr_neg_odd_64_mips(float *x) +{ + int Temp1, Temp2, Temp3, Temp4, Temp5; + float *x1 = &x[1]; + float *x_end = x1 + 64; + + /* loop unrolled 4 times */ + __asm__ volatile ( + "lui %[Temp5], 0x8000 \n\t" + "1: \n\t" + "lw %[Temp1], 0(%[x1]) \n\t" + "lw %[Temp2], 8(%[x1]) \n\t" + "lw %[Temp3], 16(%[x1]) \n\t" + "lw %[Temp4], 24(%[x1]) \n\t" + "xor %[Temp1], %[Temp1], %[Temp5] \n\t" + "xor %[Temp2], %[Temp2], %[Temp5] \n\t" + "xor %[Temp3], %[Temp3], %[Temp5] \n\t" + "xor %[Temp4], %[Temp4], %[Temp5] \n\t" + "sw %[Temp1], 0(%[x1]) \n\t" + "sw %[Temp2], 8(%[x1]) \n\t" + "sw %[Temp3], 16(%[x1]) \n\t" + "sw %[Temp4], 24(%[x1]) \n\t" + "addiu %[x1], %[x1], 32 \n\t" + "bne %[x1], %[x_end], 1b \n\t" + + : [Temp1]"=&r"(Temp1), [Temp2]"=&r"(Temp2), + [Temp3]"=&r"(Temp3), [Temp4]"=&r"(Temp4), + [Temp5]"=&r"(Temp5), [x1]"+r"(x1) + : [x_end]"r"(x_end) + : "memory" + ); +} + +static void sbr_qmf_pre_shuffle_mips(float *z) +{ + int Temp1, Temp2, Temp3, Temp4, Temp5, Temp6; + float *z1 = &z[66]; + float *z2 = &z[59]; + float *z3 = &z[2]; + float *z4 = z1 + 60; + + /* loop unrolled 5 times */ + __asm__ volatile ( + "lui %[Temp6], 0x8000 \n\t" + "1: \n\t" + "lw %[Temp1], 0(%[z2]) \n\t" + "lw %[Temp2], 4(%[z2]) \n\t" + "lw %[Temp3], 8(%[z2]) \n\t" + "lw %[Temp4], 12(%[z2]) \n\t" + "lw %[Temp5], 16(%[z2]) \n\t" + "xor %[Temp1], %[Temp1], %[Temp6] \n\t" + "xor %[Temp2], %[Temp2], %[Temp6] \n\t" + "xor %[Temp3], %[Temp3], %[Temp6] \n\t" + "xor %[Temp4], %[Temp4], %[Temp6] \n\t" + "xor %[Temp5], %[Temp5], %[Temp6] \n\t" + "addiu %[z2], %[z2], -20 \n\t" + "sw %[Temp1], 32(%[z1]) \n\t" + "sw %[Temp2], 24(%[z1]) \n\t" + "sw %[Temp3], 16(%[z1]) \n\t" + "sw %[Temp4], 8(%[z1]) \n\t" + "sw %[Temp5], 0(%[z1]) \n\t" + "lw %[Temp1], 0(%[z3]) \n\t" + "lw %[Temp2], 4(%[z3]) \n\t" + "lw %[Temp3], 8(%[z3]) \n\t" + "lw %[Temp4], 12(%[z3]) \n\t" + "lw %[Temp5], 16(%[z3]) \n\t" + "sw %[Temp1], 4(%[z1]) \n\t" + "sw %[Temp2], 12(%[z1]) \n\t" + "sw %[Temp3], 20(%[z1]) \n\t" + "sw %[Temp4], 28(%[z1]) \n\t" + "sw %[Temp5], 36(%[z1]) \n\t" + "addiu %[z3], %[z3], 20 \n\t" + "addiu %[z1], %[z1], 40 \n\t" + "bne %[z1], %[z4], 1b \n\t" + "lw %[Temp1], 132(%[z]) \n\t" + "lw %[Temp2], 128(%[z]) \n\t" + "lw %[Temp3], 0(%[z]) \n\t" + "lw %[Temp4], 4(%[z]) \n\t" + "xor %[Temp1], %[Temp1], %[Temp6] \n\t" + "sw %[Temp1], 504(%[z]) \n\t" + "sw %[Temp2], 508(%[z]) \n\t" + "sw %[Temp3], 256(%[z]) \n\t" + "sw %[Temp4], 260(%[z]) \n\t" + + : [Temp1]"=&r"(Temp1), [Temp2]"=&r"(Temp2), + [Temp3]"=&r"(Temp3), [Temp4]"=&r"(Temp4), + [Temp5]"=&r"(Temp5), [Temp6]"=&r"(Temp6), + [z1]"+r"(z1), [z2]"+r"(z2), [z3]"+r"(z3) + : [z4]"r"(z4), [z]"r"(z) + : "memory" + ); +} + +static void sbr_qmf_post_shuffle_mips(float W[32][2], const float *z) +{ + int Temp1, Temp2, Temp3, Temp4, Temp5; + float *W_ptr = (float *)W; + float *z1 = (float *)z; + float *z2 = (float *)&z[60]; + float *z_end = z1 + 32; + + /* loop unrolled 4 times */ + __asm__ volatile ( + "lui %[Temp5], 0x8000 \n\t" + "1: \n\t" + "lw %[Temp1], 0(%[z2]) \n\t" + "lw %[Temp2], 4(%[z2]) \n\t" + "lw %[Temp3], 8(%[z2]) \n\t" + "lw %[Temp4], 12(%[z2]) \n\t" + "xor %[Temp1], %[Temp1], %[Temp5] \n\t" + "xor %[Temp2], %[Temp2], %[Temp5] \n\t" + "xor %[Temp3], %[Temp3], %[Temp5] \n\t" + "xor %[Temp4], %[Temp4], %[Temp5] \n\t" + "addiu %[z2], %[z2], -16 \n\t" + "sw %[Temp1], 24(%[W_ptr]) \n\t" + "sw %[Temp2], 16(%[W_ptr]) \n\t" + "sw %[Temp3], 8(%[W_ptr]) \n\t" + "sw %[Temp4], 0(%[W_ptr]) \n\t" + "lw %[Temp1], 0(%[z1]) \n\t" + "lw %[Temp2], 4(%[z1]) \n\t" + "lw %[Temp3], 8(%[z1]) \n\t" + "lw %[Temp4], 12(%[z1]) \n\t" + "sw %[Temp1], 4(%[W_ptr]) \n\t" + "sw %[Temp2], 12(%[W_ptr]) \n\t" + "sw %[Temp3], 20(%[W_ptr]) \n\t" + "sw %[Temp4], 28(%[W_ptr]) \n\t" + "addiu %[z1], %[z1], 16 \n\t" + "addiu %[W_ptr], %[W_ptr], 32 \n\t" + "bne %[z1], %[z_end], 1b \n\t" + + : [Temp1]"=&r"(Temp1), [Temp2]"=&r"(Temp2), + [Temp3]"=&r"(Temp3), [Temp4]"=&r"(Temp4), + [Temp5]"=&r"(Temp5), [z1]"+r"(z1), + [z2]"+r"(z2), [W_ptr]"+r"(W_ptr) + : [z_end]"r"(z_end) + : "memory" + ); +} + +#if HAVE_MIPSFPU +static void sbr_sum64x5_mips(float *z) +{ + int k; + float *z1; + float f1, f2, f3, f4, f5, f6, f7, f8; + for (k = 0; k < 64; k += 8) { + + z1 = &z[k]; + + /* loop unrolled 8 times */ + __asm__ volatile ( + "lwc1 $f0, 0(%[z1]) \n\t" + "lwc1 $f1, 256(%[z1]) \n\t" + "lwc1 $f2, 4(%[z1]) \n\t" + "lwc1 $f3, 260(%[z1]) \n\t" + "lwc1 $f4, 8(%[z1]) \n\t" + "add.s %[f1], $f0, $f1 \n\t" + "lwc1 $f5, 264(%[z1]) \n\t" + "add.s %[f2], $f2, $f3 \n\t" + "lwc1 $f6, 12(%[z1]) \n\t" + "lwc1 $f7, 268(%[z1]) \n\t" + "add.s %[f3], $f4, $f5 \n\t" + "lwc1 $f8, 16(%[z1]) \n\t" + "lwc1 $f9, 272(%[z1]) \n\t" + "add.s %[f4], $f6, $f7 \n\t" + "lwc1 $f10, 20(%[z1]) \n\t" + "lwc1 $f11, 276(%[z1]) \n\t" + "add.s %[f5], $f8, $f9 \n\t" + "lwc1 $f12, 24(%[z1]) \n\t" + "lwc1 $f13, 280(%[z1]) \n\t" + "add.s %[f6], $f10, $f11 \n\t" + "lwc1 $f14, 28(%[z1]) \n\t" + "lwc1 $f15, 284(%[z1]) \n\t" + "add.s %[f7], $f12, $f13 \n\t" + "lwc1 $f0, 512(%[z1]) \n\t" + "lwc1 $f1, 516(%[z1]) \n\t" + "add.s %[f8], $f14, $f15 \n\t" + "lwc1 $f2, 520(%[z1]) \n\t" + "add.s %[f1], %[f1], $f0 \n\t" + "add.s %[f2], %[f2], $f1 \n\t" + "lwc1 $f3, 524(%[z1]) \n\t" + "add.s %[f3], %[f3], $f2 \n\t" + "lwc1 $f4, 528(%[z1]) \n\t" + "lwc1 $f5, 532(%[z1]) \n\t" + "add.s %[f4], %[f4], $f3 \n\t" + "lwc1 $f6, 536(%[z1]) \n\t" + "add.s %[f5], %[f5], $f4 \n\t" + "add.s %[f6], %[f6], $f5 \n\t" + "lwc1 $f7, 540(%[z1]) \n\t" + "add.s %[f7], %[f7], $f6 \n\t" + "lwc1 $f0, 768(%[z1]) \n\t" + "lwc1 $f1, 772(%[z1]) \n\t" + "add.s %[f8], %[f8], $f7 \n\t" + "lwc1 $f2, 776(%[z1]) \n\t" + "add.s %[f1], %[f1], $f0 \n\t" + "add.s %[f2], %[f2], $f1 \n\t" + "lwc1 $f3, 780(%[z1]) \n\t" + "add.s %[f3], %[f3], $f2 \n\t" + "lwc1 $f4, 784(%[z1]) \n\t" + "lwc1 $f5, 788(%[z1]) \n\t" + "add.s %[f4], %[f4], $f3 \n\t" + "lwc1 $f6, 792(%[z1]) \n\t" + "add.s %[f5], %[f5], $f4 \n\t" + "add.s %[f6], %[f6], $f5 \n\t" + "lwc1 $f7, 796(%[z1]) \n\t" + "add.s %[f7], %[f7], $f6 \n\t" + "lwc1 $f0, 1024(%[z1]) \n\t" + "lwc1 $f1, 1028(%[z1]) \n\t" + "add.s %[f8], %[f8], $f7 \n\t" + "lwc1 $f2, 1032(%[z1]) \n\t" + "add.s %[f1], %[f1], $f0 \n\t" + "add.s %[f2], %[f2], $f1 \n\t" + "lwc1 $f3, 1036(%[z1]) \n\t" + "add.s %[f3], %[f3], $f2 \n\t" + "lwc1 $f4, 1040(%[z1]) \n\t" + "lwc1 $f5, 1044(%[z1]) \n\t" + "add.s %[f4], %[f4], $f3 \n\t" + "lwc1 $f6, 1048(%[z1]) \n\t" + "add.s %[f5], %[f5], $f4 \n\t" + "add.s %[f6], %[f6], $f5 \n\t" + "lwc1 $f7, 1052(%[z1]) \n\t" + "add.s %[f7], %[f7], $f6 \n\t" + "swc1 %[f1], 0(%[z1]) \n\t" + "swc1 %[f2], 4(%[z1]) \n\t" + "add.s %[f8], %[f8], $f7 \n\t" + "swc1 %[f3], 8(%[z1]) \n\t" + "swc1 %[f4], 12(%[z1]) \n\t" + "swc1 %[f5], 16(%[z1]) \n\t" + "swc1 %[f6], 20(%[z1]) \n\t" + "swc1 %[f7], 24(%[z1]) \n\t" + "swc1 %[f8], 28(%[z1]) \n\t" + + : [f1]"=&f"(f1), [f2]"=&f"(f2), [f3]"=&f"(f3), + [f4]"=&f"(f4), [f5]"=&f"(f5), [f6]"=&f"(f6), + [f7]"=&f"(f7), [f8]"=&f"(f8) + : [z1]"r"(z1) + : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", + "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", + "$f12", "$f13", "$f14", "$f15", + "memory" + ); + } +} + +static float sbr_sum_square_mips(float (*x)[2], int n) +{ + float sum0 = 0.0f, sum1 = 0.0f; + float *p_x; + float temp0, temp1, temp2, temp3; + float *loop_end; + p_x = &x[0][0]; + loop_end = p_x + (n >> 1)*4 - 4; + + __asm__ volatile ( + ".set push \n\t" + ".set noreorder \n\t" + "lwc1 %[temp0], 0(%[p_x]) \n\t" + "lwc1 %[temp1], 4(%[p_x]) \n\t" + "lwc1 %[temp2], 8(%[p_x]) \n\t" + "lwc1 %[temp3], 12(%[p_x]) \n\t" + "1: \n\t" + "addiu %[p_x], %[p_x], 16 \n\t" + "madd.s %[sum0], %[sum0], %[temp0], %[temp0] \n\t" + "lwc1 %[temp0], 0(%[p_x]) \n\t" + "madd.s %[sum1], %[sum1], %[temp1], %[temp1] \n\t" + "lwc1 %[temp1], 4(%[p_x]) \n\t" + "madd.s %[sum0], %[sum0], %[temp2], %[temp2] \n\t" + "lwc1 %[temp2], 8(%[p_x]) \n\t" + "madd.s %[sum1], %[sum1], %[temp3], %[temp3] \n\t" + "bne %[p_x], %[loop_end], 1b \n\t" + " lwc1 %[temp3], 12(%[p_x]) \n\t" + "madd.s %[sum0], %[sum0], %[temp0], %[temp0] \n\t" + "madd.s %[sum1], %[sum1], %[temp1], %[temp1] \n\t" + "madd.s %[sum0], %[sum0], %[temp2], %[temp2] \n\t" + "madd.s %[sum1], %[sum1], %[temp3], %[temp3] \n\t" + ".set pop \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [sum0]"+f"(sum0), [sum1]"+f"(sum1), + [p_x]"+r"(p_x) + : [loop_end]"r"(loop_end) + : "memory" + ); + return sum0 + sum1; +} + +static void sbr_qmf_deint_bfly_mips(float *v, const float *src0, const float *src1) +{ + int i; + float temp0, temp1, temp2, temp3, temp4, temp5; + float temp6, temp7, temp8, temp9, temp10, temp11; + float *v0 = v; + float *v1 = &v[127]; + float *psrc0 = (float*)src0; + float *psrc1 = (float*)&src1[63]; + + for (i = 0; i < 4; i++) { + + /* loop unrolled 16 times */ + __asm__ volatile( + "lwc1 %[temp0], 0(%[src0]) \n\t" + "lwc1 %[temp1], 0(%[src1]) \n\t" + "lwc1 %[temp3], 4(%[src0]) \n\t" + "lwc1 %[temp4], -4(%[src1]) \n\t" + "lwc1 %[temp6], 8(%[src0]) \n\t" + "lwc1 %[temp7], -8(%[src1]) \n\t" + "lwc1 %[temp9], 12(%[src0]) \n\t" + "lwc1 %[temp10], -12(%[src1]) \n\t" + "add.s %[temp2], %[temp0], %[temp1] \n\t" + "add.s %[temp5], %[temp3], %[temp4] \n\t" + "add.s %[temp8], %[temp6], %[temp7] \n\t" + "add.s %[temp11], %[temp9], %[temp10] \n\t" + "sub.s %[temp0], %[temp0], %[temp1] \n\t" + "sub.s %[temp3], %[temp3], %[temp4] \n\t" + "sub.s %[temp6], %[temp6], %[temp7] \n\t" + "sub.s %[temp9], %[temp9], %[temp10] \n\t" + "swc1 %[temp2], 0(%[v1]) \n\t" + "swc1 %[temp0], 0(%[v0]) \n\t" + "swc1 %[temp5], -4(%[v1]) \n\t" + "swc1 %[temp3], 4(%[v0]) \n\t" + "swc1 %[temp8], -8(%[v1]) \n\t" + "swc1 %[temp6], 8(%[v0]) \n\t" + "swc1 %[temp11], -12(%[v1]) \n\t" + "swc1 %[temp9], 12(%[v0]) \n\t" + "lwc1 %[temp0], 16(%[src0]) \n\t" + "lwc1 %[temp1], -16(%[src1]) \n\t" + "lwc1 %[temp3], 20(%[src0]) \n\t" + "lwc1 %[temp4], -20(%[src1]) \n\t" + "lwc1 %[temp6], 24(%[src0]) \n\t" + "lwc1 %[temp7], -24(%[src1]) \n\t" + "lwc1 %[temp9], 28(%[src0]) \n\t" + "lwc1 %[temp10], -28(%[src1]) \n\t" + "add.s %[temp2], %[temp0], %[temp1] \n\t" + "add.s %[temp5], %[temp3], %[temp4] \n\t" + "add.s %[temp8], %[temp6], %[temp7] \n\t" + "add.s %[temp11], %[temp9], %[temp10] \n\t" + "sub.s %[temp0], %[temp0], %[temp1] \n\t" + "sub.s %[temp3], %[temp3], %[temp4] \n\t" + "sub.s %[temp6], %[temp6], %[temp7] \n\t" + "sub.s %[temp9], %[temp9], %[temp10] \n\t" + "swc1 %[temp2], -16(%[v1]) \n\t" + "swc1 %[temp0], 16(%[v0]) \n\t" + "swc1 %[temp5], -20(%[v1]) \n\t" + "swc1 %[temp3], 20(%[v0]) \n\t" + "swc1 %[temp8], -24(%[v1]) \n\t" + "swc1 %[temp6], 24(%[v0]) \n\t" + "swc1 %[temp11], -28(%[v1]) \n\t" + "swc1 %[temp9], 28(%[v0]) \n\t" + "lwc1 %[temp0], 32(%[src0]) \n\t" + "lwc1 %[temp1], -32(%[src1]) \n\t" + "lwc1 %[temp3], 36(%[src0]) \n\t" + "lwc1 %[temp4], -36(%[src1]) \n\t" + "lwc1 %[temp6], 40(%[src0]) \n\t" + "lwc1 %[temp7], -40(%[src1]) \n\t" + "lwc1 %[temp9], 44(%[src0]) \n\t" + "lwc1 %[temp10], -44(%[src1]) \n\t" + "add.s %[temp2], %[temp0], %[temp1] \n\t" + "add.s %[temp5], %[temp3], %[temp4] \n\t" + "add.s %[temp8], %[temp6], %[temp7] \n\t" + "add.s %[temp11], %[temp9], %[temp10] \n\t" + "sub.s %[temp0], %[temp0], %[temp1] \n\t" + "sub.s %[temp3], %[temp3], %[temp4] \n\t" + "sub.s %[temp6], %[temp6], %[temp7] \n\t" + "sub.s %[temp9], %[temp9], %[temp10] \n\t" + "swc1 %[temp2], -32(%[v1]) \n\t" + "swc1 %[temp0], 32(%[v0]) \n\t" + "swc1 %[temp5], -36(%[v1]) \n\t" + "swc1 %[temp3], 36(%[v0]) \n\t" + "swc1 %[temp8], -40(%[v1]) \n\t" + "swc1 %[temp6], 40(%[v0]) \n\t" + "swc1 %[temp11], -44(%[v1]) \n\t" + "swc1 %[temp9], 44(%[v0]) \n\t" + "lwc1 %[temp0], 48(%[src0]) \n\t" + "lwc1 %[temp1], -48(%[src1]) \n\t" + "lwc1 %[temp3], 52(%[src0]) \n\t" + "lwc1 %[temp4], -52(%[src1]) \n\t" + "lwc1 %[temp6], 56(%[src0]) \n\t" + "lwc1 %[temp7], -56(%[src1]) \n\t" + "lwc1 %[temp9], 60(%[src0]) \n\t" + "lwc1 %[temp10], -60(%[src1]) \n\t" + "add.s %[temp2], %[temp0], %[temp1] \n\t" + "add.s %[temp5], %[temp3], %[temp4] \n\t" + "add.s %[temp8], %[temp6], %[temp7] \n\t" + "add.s %[temp11], %[temp9], %[temp10] \n\t" + "sub.s %[temp0], %[temp0], %[temp1] \n\t" + "sub.s %[temp3], %[temp3], %[temp4] \n\t" + "sub.s %[temp6], %[temp6], %[temp7] \n\t" + "sub.s %[temp9], %[temp9], %[temp10] \n\t" + "swc1 %[temp2], -48(%[v1]) \n\t" + "swc1 %[temp0], 48(%[v0]) \n\t" + "swc1 %[temp5], -52(%[v1]) \n\t" + "swc1 %[temp3], 52(%[v0]) \n\t" + "swc1 %[temp8], -56(%[v1]) \n\t" + "swc1 %[temp6], 56(%[v0]) \n\t" + "swc1 %[temp11], -60(%[v1]) \n\t" + "swc1 %[temp9], 60(%[v0]) \n\t" + "addiu %[src0], %[src0], 64 \n\t" + "addiu %[src1], %[src1], -64 \n\t" + "addiu %[v0], %[v0], 64 \n\t" + "addiu %[v1], %[v1], -64 \n\t" + + : [v0]"+r"(v0), [v1]"+r"(v1), [src0]"+r"(psrc0), [src1]"+r"(psrc1), + [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [temp10]"=&f"(temp10), [temp11]"=&f"(temp11) + : + :"memory" + ); + } +} + +static void sbr_autocorrelate_mips(const float x[40][2], float phi[3][2][2]) +{ + int i; + float real_sum_0 = 0.0f; + float real_sum_1 = 0.0f; + float real_sum_2 = 0.0f; + float imag_sum_1 = 0.0f; + float imag_sum_2 = 0.0f; + float *p_x, *p_phi; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6; + float temp7, temp_r, temp_r1, temp_r2, temp_r3, temp_r4; + p_x = (float*)&x[0][0]; + p_phi = &phi[0][0][0]; + + __asm__ volatile ( + "lwc1 %[temp0], 8(%[p_x]) \n\t" + "lwc1 %[temp1], 12(%[p_x]) \n\t" + "lwc1 %[temp2], 16(%[p_x]) \n\t" + "lwc1 %[temp3], 20(%[p_x]) \n\t" + "lwc1 %[temp4], 24(%[p_x]) \n\t" + "lwc1 %[temp5], 28(%[p_x]) \n\t" + "mul.s %[temp_r], %[temp1], %[temp1] \n\t" + "mul.s %[temp_r1], %[temp1], %[temp3] \n\t" + "mul.s %[temp_r2], %[temp1], %[temp2] \n\t" + "mul.s %[temp_r3], %[temp1], %[temp5] \n\t" + "mul.s %[temp_r4], %[temp1], %[temp4] \n\t" + "madd.s %[temp_r], %[temp_r], %[temp0], %[temp0] \n\t" + "madd.s %[temp_r1], %[temp_r1], %[temp0], %[temp2] \n\t" + "msub.s %[temp_r2], %[temp_r2], %[temp0], %[temp3] \n\t" + "madd.s %[temp_r3], %[temp_r3], %[temp0], %[temp4] \n\t" + "msub.s %[temp_r4], %[temp_r4], %[temp0], %[temp5] \n\t" + "add.s %[real_sum_0], %[real_sum_0], %[temp_r] \n\t" + "add.s %[real_sum_1], %[real_sum_1], %[temp_r1] \n\t" + "add.s %[imag_sum_1], %[imag_sum_1], %[temp_r2] \n\t" + "add.s %[real_sum_2], %[real_sum_2], %[temp_r3] \n\t" + "add.s %[imag_sum_2], %[imag_sum_2], %[temp_r4] \n\t" + "addiu %[p_x], %[p_x], 8 \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [real_sum_0]"+f"(real_sum_0), [real_sum_1]"+f"(real_sum_1), + [imag_sum_1]"+f"(imag_sum_1), [real_sum_2]"+f"(real_sum_2), + [temp_r]"=&f"(temp_r), [temp_r1]"=&f"(temp_r1), [temp_r2]"=&f"(temp_r2), + [temp_r3]"=&f"(temp_r3), [temp_r4]"=&f"(temp_r4), + [p_x]"+r"(p_x), [imag_sum_2]"+f"(imag_sum_2) + : + : "memory" + ); + + for (i = 0; i < 12; i++) { + __asm__ volatile ( + "lwc1 %[temp0], 8(%[p_x]) \n\t" + "lwc1 %[temp1], 12(%[p_x]) \n\t" + "lwc1 %[temp2], 16(%[p_x]) \n\t" + "lwc1 %[temp3], 20(%[p_x]) \n\t" + "lwc1 %[temp4], 24(%[p_x]) \n\t" + "lwc1 %[temp5], 28(%[p_x]) \n\t" + "mul.s %[temp_r], %[temp1], %[temp1] \n\t" + "mul.s %[temp_r1], %[temp1], %[temp3] \n\t" + "mul.s %[temp_r2], %[temp1], %[temp2] \n\t" + "mul.s %[temp_r3], %[temp1], %[temp5] \n\t" + "mul.s %[temp_r4], %[temp1], %[temp4] \n\t" + "madd.s %[temp_r], %[temp_r], %[temp0], %[temp0] \n\t" + "madd.s %[temp_r1], %[temp_r1], %[temp0], %[temp2] \n\t" + "msub.s %[temp_r2], %[temp_r2], %[temp0], %[temp3] \n\t" + "madd.s %[temp_r3], %[temp_r3], %[temp0], %[temp4] \n\t" + "msub.s %[temp_r4], %[temp_r4], %[temp0], %[temp5] \n\t" + "add.s %[real_sum_0], %[real_sum_0], %[temp_r] \n\t" + "add.s %[real_sum_1], %[real_sum_1], %[temp_r1] \n\t" + "add.s %[imag_sum_1], %[imag_sum_1], %[temp_r2] \n\t" + "add.s %[real_sum_2], %[real_sum_2], %[temp_r3] \n\t" + "add.s %[imag_sum_2], %[imag_sum_2], %[temp_r4] \n\t" + "lwc1 %[temp0], 32(%[p_x]) \n\t" + "lwc1 %[temp1], 36(%[p_x]) \n\t" + "mul.s %[temp_r], %[temp3], %[temp3] \n\t" + "mul.s %[temp_r1], %[temp3], %[temp5] \n\t" + "mul.s %[temp_r2], %[temp3], %[temp4] \n\t" + "mul.s %[temp_r3], %[temp3], %[temp1] \n\t" + "mul.s %[temp_r4], %[temp3], %[temp0] \n\t" + "madd.s %[temp_r], %[temp_r], %[temp2], %[temp2] \n\t" + "madd.s %[temp_r1], %[temp_r1], %[temp2], %[temp4] \n\t" + "msub.s %[temp_r2], %[temp_r2], %[temp2], %[temp5] \n\t" + "madd.s %[temp_r3], %[temp_r3], %[temp2], %[temp0] \n\t" + "msub.s %[temp_r4], %[temp_r4], %[temp2], %[temp1] \n\t" + "add.s %[real_sum_0], %[real_sum_0], %[temp_r] \n\t" + "add.s %[real_sum_1], %[real_sum_1], %[temp_r1] \n\t" + "add.s %[imag_sum_1], %[imag_sum_1], %[temp_r2] \n\t" + "add.s %[real_sum_2], %[real_sum_2], %[temp_r3] \n\t" + "add.s %[imag_sum_2], %[imag_sum_2], %[temp_r4] \n\t" + "lwc1 %[temp2], 40(%[p_x]) \n\t" + "lwc1 %[temp3], 44(%[p_x]) \n\t" + "mul.s %[temp_r], %[temp5], %[temp5] \n\t" + "mul.s %[temp_r1], %[temp5], %[temp1] \n\t" + "mul.s %[temp_r2], %[temp5], %[temp0] \n\t" + "mul.s %[temp_r3], %[temp5], %[temp3] \n\t" + "mul.s %[temp_r4], %[temp5], %[temp2] \n\t" + "madd.s %[temp_r], %[temp_r], %[temp4], %[temp4] \n\t" + "madd.s %[temp_r1], %[temp_r1], %[temp4], %[temp0] \n\t" + "msub.s %[temp_r2], %[temp_r2], %[temp4], %[temp1] \n\t" + "madd.s %[temp_r3], %[temp_r3], %[temp4], %[temp2] \n\t" + "msub.s %[temp_r4], %[temp_r4], %[temp4], %[temp3] \n\t" + "add.s %[real_sum_0], %[real_sum_0], %[temp_r] \n\t" + "add.s %[real_sum_1], %[real_sum_1], %[temp_r1] \n\t" + "add.s %[imag_sum_1], %[imag_sum_1], %[temp_r2] \n\t" + "add.s %[real_sum_2], %[real_sum_2], %[temp_r3] \n\t" + "add.s %[imag_sum_2], %[imag_sum_2], %[temp_r4] \n\t" + "addiu %[p_x], %[p_x], 24 \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [real_sum_0]"+f"(real_sum_0), [real_sum_1]"+f"(real_sum_1), + [imag_sum_1]"+f"(imag_sum_1), [real_sum_2]"+f"(real_sum_2), + [temp_r]"=&f"(temp_r), [temp_r1]"=&f"(temp_r1), + [temp_r2]"=&f"(temp_r2), [temp_r3]"=&f"(temp_r3), + [temp_r4]"=&f"(temp_r4), [p_x]"+r"(p_x), + [imag_sum_2]"+f"(imag_sum_2) + : + : "memory" + ); + } + __asm__ volatile ( + "lwc1 %[temp0], -296(%[p_x]) \n\t" + "lwc1 %[temp1], -292(%[p_x]) \n\t" + "lwc1 %[temp2], 8(%[p_x]) \n\t" + "lwc1 %[temp3], 12(%[p_x]) \n\t" + "lwc1 %[temp4], -288(%[p_x]) \n\t" + "lwc1 %[temp5], -284(%[p_x]) \n\t" + "lwc1 %[temp6], -280(%[p_x]) \n\t" + "lwc1 %[temp7], -276(%[p_x]) \n\t" + "madd.s %[temp_r], %[real_sum_0], %[temp0], %[temp0] \n\t" + "madd.s %[temp_r1], %[real_sum_0], %[temp2], %[temp2] \n\t" + "madd.s %[temp_r2], %[real_sum_1], %[temp0], %[temp4] \n\t" + "madd.s %[temp_r3], %[imag_sum_1], %[temp0], %[temp5] \n\t" + "madd.s %[temp_r], %[temp_r], %[temp1], %[temp1] \n\t" + "madd.s %[temp_r1], %[temp_r1], %[temp3], %[temp3] \n\t" + "madd.s %[temp_r2], %[temp_r2], %[temp1], %[temp5] \n\t" + "nmsub.s %[temp_r3], %[temp_r3], %[temp1], %[temp4] \n\t" + "lwc1 %[temp4], 16(%[p_x]) \n\t" + "lwc1 %[temp5], 20(%[p_x]) \n\t" + "swc1 %[temp_r], 40(%[p_phi]) \n\t" + "swc1 %[temp_r1], 16(%[p_phi]) \n\t" + "swc1 %[temp_r2], 24(%[p_phi]) \n\t" + "swc1 %[temp_r3], 28(%[p_phi]) \n\t" + "madd.s %[temp_r], %[real_sum_1], %[temp2], %[temp4] \n\t" + "madd.s %[temp_r1], %[imag_sum_1], %[temp2], %[temp5] \n\t" + "madd.s %[temp_r2], %[real_sum_2], %[temp0], %[temp6] \n\t" + "madd.s %[temp_r3], %[imag_sum_2], %[temp0], %[temp7] \n\t" + "madd.s %[temp_r], %[temp_r], %[temp3], %[temp5] \n\t" + "nmsub.s %[temp_r1], %[temp_r1], %[temp3], %[temp4] \n\t" + "madd.s %[temp_r2], %[temp_r2], %[temp1], %[temp7] \n\t" + "nmsub.s %[temp_r3], %[temp_r3], %[temp1], %[temp6] \n\t" + "swc1 %[temp_r], 0(%[p_phi]) \n\t" + "swc1 %[temp_r1], 4(%[p_phi]) \n\t" + "swc1 %[temp_r2], 8(%[p_phi]) \n\t" + "swc1 %[temp_r3], 12(%[p_phi]) \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp_r]"=&f"(temp_r), + [real_sum_0]"+f"(real_sum_0), [real_sum_1]"+f"(real_sum_1), + [real_sum_2]"+f"(real_sum_2), [imag_sum_1]"+f"(imag_sum_1), + [temp_r2]"=&f"(temp_r2), [temp_r3]"=&f"(temp_r3), + [temp_r1]"=&f"(temp_r1), [p_phi]"+r"(p_phi), + [imag_sum_2]"+f"(imag_sum_2) + : [p_x]"r"(p_x) + : "memory" + ); +} + +static void sbr_hf_gen_mips(float (*X_high)[2], const float (*X_low)[2], + const float alpha0[2], const float alpha1[2], + float bw, int start, int end) +{ + float alpha[4]; + int i; + float *p_x_low = (float*)&X_low[0][0] + 2*start; + float *p_x_high = &X_high[0][0] + 2*start; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6; + float temp7, temp8, temp9, temp10, temp11, temp12; + + alpha[0] = alpha1[0] * bw * bw; + alpha[1] = alpha1[1] * bw * bw; + alpha[2] = alpha0[0] * bw; + alpha[3] = alpha0[1] * bw; + + for (i = start; i < end; i++) { + __asm__ volatile ( + "lwc1 %[temp0], -16(%[p_x_low]) \n\t" + "lwc1 %[temp1], -12(%[p_x_low]) \n\t" + "lwc1 %[temp2], -8(%[p_x_low]) \n\t" + "lwc1 %[temp3], -4(%[p_x_low]) \n\t" + "lwc1 %[temp5], 0(%[p_x_low]) \n\t" + "lwc1 %[temp6], 4(%[p_x_low]) \n\t" + "lwc1 %[temp7], 0(%[alpha]) \n\t" + "lwc1 %[temp8], 4(%[alpha]) \n\t" + "lwc1 %[temp9], 8(%[alpha]) \n\t" + "lwc1 %[temp10], 12(%[alpha]) \n\t" + "addiu %[p_x_high], %[p_x_high], 8 \n\t" + "addiu %[p_x_low], %[p_x_low], 8 \n\t" + "mul.s %[temp11], %[temp1], %[temp8] \n\t" + "msub.s %[temp11], %[temp11], %[temp0], %[temp7] \n\t" + "madd.s %[temp11], %[temp11], %[temp2], %[temp9] \n\t" + "nmsub.s %[temp11], %[temp11], %[temp3], %[temp10] \n\t" + "add.s %[temp11], %[temp11], %[temp5] \n\t" + "swc1 %[temp11], -8(%[p_x_high]) \n\t" + "mul.s %[temp12], %[temp1], %[temp7] \n\t" + "madd.s %[temp12], %[temp12], %[temp0], %[temp8] \n\t" + "madd.s %[temp12], %[temp12], %[temp3], %[temp9] \n\t" + "madd.s %[temp12], %[temp12], %[temp2], %[temp10] \n\t" + "add.s %[temp12], %[temp12], %[temp6] \n\t" + "swc1 %[temp12], -4(%[p_x_high]) \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), + [temp9]"=&f"(temp9), [temp10]"=&f"(temp10), [temp11]"=&f"(temp11), + [temp12]"=&f"(temp12), [p_x_high]"+r"(p_x_high), + [p_x_low]"+r"(p_x_low) + : [alpha]"r"(alpha) + : "memory" + ); + } +} + +static void sbr_hf_g_filt_mips(float (*Y)[2], const float (*X_high)[40][2], + const float *g_filt, int m_max, intptr_t ixh) +{ + float *p_y, *p_x, *p_g; + float temp0, temp1, temp2; + int loop_end; + + p_g = (float*)&g_filt[0]; + p_y = &Y[0][0]; + p_x = (float*)&X_high[0][ixh][0]; + loop_end = (int)((int*)p_g + m_max); + + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "lwc1 %[temp0], 0(%[p_g]) \n\t" + "lwc1 %[temp1], 0(%[p_x]) \n\t" + "lwc1 %[temp2], 4(%[p_x]) \n\t" + "mul.s %[temp1], %[temp1], %[temp0] \n\t" + "mul.s %[temp2], %[temp2], %[temp0] \n\t" + "addiu %[p_g], %[p_g], 4 \n\t" + "addiu %[p_x], %[p_x], 320 \n\t" + "swc1 %[temp1], 0(%[p_y]) \n\t" + "swc1 %[temp2], 4(%[p_y]) \n\t" + "bne %[p_g], %[loop_end], 1b \n\t" + " addiu %[p_y], %[p_y], 8 \n\t" + ".set pop \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [p_x]"+r"(p_x), + [p_y]"+r"(p_y), [p_g]"+r"(p_g) + : [loop_end]"r"(loop_end) + : "memory" + ); +} + +static void sbr_hf_apply_noise_0_mips(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + int m; + + for (m = 0; m < m_max; m++){ + + float *Y1=&Y[m][0]; + float *ff_table; + float y0,y1, temp1, temp2, temp4, temp5; + int temp0, temp3; + const float *s_m1=&s_m[m]; + const float *q_filt1= &q_filt[m]; + + __asm__ volatile( + "lwc1 %[y0], 0(%[Y1]) \n\t" + "lwc1 %[temp1], 0(%[s_m1]) \n\t" + "addiu %[noise], %[noise], 1 \n\t" + "andi %[noise], %[noise], 0x1ff \n\t" + "sll %[temp0], %[noise], 3 \n\t" + "addu %[ff_table], %[ff_sbr_noise_table], %[temp0] \n\t" + "add.s %[y0], %[y0], %[temp1] \n\t" + "mfc1 %[temp3], %[temp1] \n\t" + "bne %[temp3], $0, 1f \n\t" + "lwc1 %[y1], 4(%[Y1]) \n\t" + "lwc1 %[temp2], 0(%[q_filt1]) \n\t" + "lwc1 %[temp4], 0(%[ff_table]) \n\t" + "lwc1 %[temp5], 4(%[ff_table]) \n\t" + "madd.s %[y0], %[y0], %[temp2], %[temp4] \n\t" + "madd.s %[y1], %[y1], %[temp2], %[temp5] \n\t" + "swc1 %[y1], 4(%[Y1]) \n\t" + "1: \n\t" + "swc1 %[y0], 0(%[Y1]) \n\t" + + : [ff_table]"=&r"(ff_table), [y0]"=&f"(y0), [y1]"=&f"(y1), + [temp0]"=&r"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5) + : [ff_sbr_noise_table]"r"(ff_sbr_noise_table), [noise]"r"(noise), + [Y1]"r"(Y1), [s_m1]"r"(s_m1), [q_filt1]"r"(q_filt1) + : "memory" + ); + } +} + +static void sbr_hf_apply_noise_1_mips(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + float y0,y1,temp1, temp2, temp4, temp5; + int temp0, temp3, m; + float phi_sign = 1 - 2 * (kx & 1); + + for (m = 0; m < m_max; m++) { + + float *ff_table; + float *Y1=&Y[m][0]; + const float *s_m1=&s_m[m]; + const float *q_filt1= &q_filt[m]; + + __asm__ volatile( + "lwc1 %[y1], 4(%[Y1]) \n\t" + "lwc1 %[temp1], 0(%[s_m1]) \n\t" + "lw %[temp3], 0(%[s_m1]) \n\t" + "addiu %[noise], %[noise], 1 \n\t" + "andi %[noise], %[noise], 0x1ff \n\t" + "sll %[temp0], %[noise], 3 \n\t" + "addu %[ff_table], %[ff_sbr_noise_table], %[temp0] \n\t" + "madd.s %[y1], %[y1], %[temp1], %[phi_sign] \n\t" + "bne %[temp3], $0, 1f \n\t" + "lwc1 %[y0], 0(%[Y1]) \n\t" + "lwc1 %[temp2], 0(%[q_filt1]) \n\t" + "lwc1 %[temp4], 0(%[ff_table]) \n\t" + "lwc1 %[temp5], 4(%[ff_table]) \n\t" + "madd.s %[y0], %[y0], %[temp2], %[temp4] \n\t" + "madd.s %[y1], %[y1], %[temp2], %[temp5] \n\t" + "swc1 %[y0], 0(%[Y1]) \n\t" + "1: \n\t" + "swc1 %[y1], 4(%[Y1]) \n\t" + + : [ff_table] "=&r" (ff_table), [y0] "=&f" (y0), [y1] "=&f" (y1), + [temp0] "=&r" (temp0), [temp1] "=&f" (temp1), [temp2] "=&f" (temp2), + [temp3] "=&r" (temp3), [temp4] "=&f" (temp4), [temp5] "=&f" (temp5) + : [ff_sbr_noise_table] "r" (ff_sbr_noise_table), [noise] "r" (noise), + [Y1] "r" (Y1), [s_m1] "r" (s_m1), [q_filt1] "r" (q_filt1), + [phi_sign] "f" (phi_sign) + : "memory" + ); + phi_sign = -phi_sign; + } +} + +static void sbr_hf_apply_noise_2_mips(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + int m; + float *ff_table; + float y0,y1, temp0, temp1, temp2, temp3, temp4, temp5; + + for (m = 0; m < m_max; m++) { + + float *Y1=&Y[m][0]; + const float *s_m1=&s_m[m]; + const float *q_filt1= &q_filt[m]; + + __asm__ volatile( + "lwc1 %[y0], 0(%[Y1]) \n\t" + "lwc1 %[temp1], 0(%[s_m1]) \n\t" + "addiu %[noise], %[noise], 1 \n\t" + "andi %[noise], %[noise], 0x1ff \n\t" + "sll %[temp0], %[noise], 3 \n\t" + "addu %[ff_table], %[ff_sbr_noise_table], %[temp0] \n\t" + "sub.s %[y0], %[y0], %[temp1] \n\t" + "mfc1 %[temp3], %[temp1] \n\t" + "bne %[temp3], $0, 1f \n\t" + "lwc1 %[y1], 4(%[Y1]) \n\t" + "lwc1 %[temp2], 0(%[q_filt1]) \n\t" + "lwc1 %[temp4], 0(%[ff_table]) \n\t" + "lwc1 %[temp5], 4(%[ff_table]) \n\t" + "madd.s %[y0], %[y0], %[temp2], %[temp4] \n\t" + "madd.s %[y1], %[y1], %[temp2], %[temp5] \n\t" + "swc1 %[y1], 4(%[Y1]) \n\t" + "1: \n\t" + "swc1 %[y0], 0(%[Y1]) \n\t" + + : [temp0]"=&r"(temp0), [ff_table]"=&r"(ff_table), [y0]"=&f"(y0), + [y1]"=&f"(y1), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5) + : [ff_sbr_noise_table]"r"(ff_sbr_noise_table), [noise]"r"(noise), + [Y1]"r"(Y1), [s_m1]"r"(s_m1), [q_filt1]"r"(q_filt1) + : "memory" + ); + } +} + +static void sbr_hf_apply_noise_3_mips(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + float phi_sign = 1 - 2 * (kx & 1); + int m; + + for (m = 0; m < m_max; m++) { + + float *Y1=&Y[m][0]; + float *ff_table; + float y0,y1, temp1, temp2, temp4, temp5; + int temp0, temp3; + const float *s_m1=&s_m[m]; + const float *q_filt1= &q_filt[m]; + + __asm__ volatile( + "lwc1 %[y1], 4(%[Y1]) \n\t" + "lwc1 %[temp1], 0(%[s_m1]) \n\t" + "addiu %[noise], %[noise], 1 \n\t" + "andi %[noise], %[noise], 0x1ff \n\t" + "sll %[temp0], %[noise], 3 \n\t" + "addu %[ff_table], %[ff_sbr_noise_table], %[temp0] \n\t" + "nmsub.s %[y1], %[y1], %[temp1], %[phi_sign] \n\t" + "mfc1 %[temp3], %[temp1] \n\t" + "bne %[temp3], $0, 1f \n\t" + "lwc1 %[y0], 0(%[Y1]) \n\t" + "lwc1 %[temp2], 0(%[q_filt1]) \n\t" + "lwc1 %[temp4], 0(%[ff_table]) \n\t" + "lwc1 %[temp5], 4(%[ff_table]) \n\t" + "madd.s %[y0], %[y0], %[temp2], %[temp4] \n\t" + "madd.s %[y1], %[y1], %[temp2], %[temp5] \n\t" + "swc1 %[y0], 0(%[Y1]) \n\t" + "1: \n\t" + "swc1 %[y1], 4(%[Y1]) \n\t" + + : [ff_table]"=&r"(ff_table), [y0]"=&f"(y0), [y1]"=&f"(y1), + [temp0]"=&r"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&r"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5) + : [ff_sbr_noise_table]"r"(ff_sbr_noise_table), [noise]"r"(noise), + [Y1]"r"(Y1), [s_m1]"r"(s_m1), [q_filt1]"r"(q_filt1), + [phi_sign]"f"(phi_sign) + : "memory" + ); + phi_sign = -phi_sign; + } +} +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ + +void ff_sbrdsp_init_mips(SBRDSPContext *s) +{ +#if HAVE_INLINE_ASM + s->neg_odd_64 = sbr_neg_odd_64_mips; + s->qmf_pre_shuffle = sbr_qmf_pre_shuffle_mips; + s->qmf_post_shuffle = sbr_qmf_post_shuffle_mips; +#if HAVE_MIPSFPU + s->sum64x5 = sbr_sum64x5_mips; + s->sum_square = sbr_sum_square_mips; + s->qmf_deint_bfly = sbr_qmf_deint_bfly_mips; + s->autocorrelate = sbr_autocorrelate_mips; + s->hf_gen = sbr_hf_gen_mips; + s->hf_g_filt = sbr_hf_g_filt_mips; + + s->hf_apply_noise[0] = sbr_hf_apply_noise_0_mips; + s->hf_apply_noise[1] = sbr_hf_apply_noise_1_mips; + s->hf_apply_noise[2] = sbr_hf_apply_noise_2_mips; + s->hf_apply_noise[3] = sbr_hf_apply_noise_3_mips; +#endif /* HAVE_MIPSFPU */ +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/mjpeg.c b/ffmpeg/libavcodec/mjpeg.c new file mode 100644 index 0000000..a5b1a80 --- /dev/null +++ b/ffmpeg/libavcodec/mjpeg.c @@ -0,0 +1,145 @@ +/* + * MJPEG encoder and decoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * MJPEG encoder and decoder. + */ + +#include "mjpeg.h" + + +#if 0 +/* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ +const unsigned char std_luminance_quant_tbl[64] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; +const unsigned char std_chrominance_quant_tbl[64] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; +#endif + +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +const uint8_t avpriv_mjpeg_bits_dc_luminance[17] = +{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +const uint8_t avpriv_mjpeg_val_dc[12] = +{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + +const uint8_t avpriv_mjpeg_bits_dc_chrominance[17] = +{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + +const uint8_t avpriv_mjpeg_bits_ac_luminance[17] = +{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; +const uint8_t avpriv_mjpeg_val_ac_luminance[] = +{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +const uint8_t avpriv_mjpeg_bits_ac_chrominance[17] = +{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + +const uint8_t avpriv_mjpeg_val_ac_chrominance[] = +{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +/* isn't this function nicer than the one in the libjpeg ? */ +void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, + const uint8_t *bits_table, + const uint8_t *val_table) +{ + int i, j, k,nb, code, sym; + + code = 0; + k = 0; + for(i=1;i<=16;i++) { + nb = bits_table[i]; + for(j=0;j 0xbf reserved */ +} JPEG_MARKER; + +static inline void put_marker(PutBitContext *p, int code) +{ + put_bits(p, 8, 0xff); + put_bits(p, 8, code); +} + +#define PREDICT(ret, topleft, top, left, predictor)\ + switch(predictor){\ + case 0: ret= 0; break;\ + case 1: ret= left; break;\ + case 2: ret= top; break;\ + case 3: ret= topleft; break;\ + case 4: ret= left + top - topleft; break;\ + case 5: ret= left + ((top - topleft)>>1); break;\ + case 6: ret= top + ((left - topleft)>>1); break;\ + default:\ + case 7: ret= (left + top)>>1; break;\ + } + +extern av_export const uint8_t avpriv_mjpeg_bits_dc_luminance[]; +extern av_export const uint8_t avpriv_mjpeg_val_dc[]; + +extern av_export const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; + +extern av_export const uint8_t avpriv_mjpeg_bits_ac_luminance[]; +extern av_export const uint8_t avpriv_mjpeg_val_ac_luminance[]; + +extern av_export const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; +extern av_export const uint8_t avpriv_mjpeg_val_ac_chrominance[]; + +void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, + const uint8_t *bits_table, + const uint8_t *val_table); + +#endif /* AVCODEC_MJPEG_H */ diff --git a/ffmpeg/libavcodec/mjpeg2jpeg_bsf.c b/ffmpeg/libavcodec/mjpeg2jpeg_bsf.c new file mode 100644 index 0000000..f367288 --- /dev/null +++ b/ffmpeg/libavcodec/mjpeg2jpeg_bsf.c @@ -0,0 +1,112 @@ +/* + * MJPEG/AVI1 to JPEG/JFIF bitstream format filter + * Copyright (c) 2010 Adrian Daerr and Nicolas George + * + * 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 + */ + +/* + * Adapted from mjpeg2jpeg.c, with original copyright: + * Paris 2010 Adrian Daerr, public domain + */ + +#include +#include "avcodec.h" +#include "mjpeg.h" + +static const uint8_t jpeg_header[] = { + 0xff, 0xd8, // SOI + 0xff, 0xe0, // APP0 + 0x00, 0x10, // APP0 header size (including + // this field, but excluding preceding) + 0x4a, 0x46, 0x49, 0x46, 0x00, // ID string 'JFIF\0' + 0x01, 0x01, // version + 0x00, // bits per type + 0x00, 0x00, // X density + 0x00, 0x00, // Y density + 0x00, // X thumbnail size + 0x00, // Y thumbnail size +}; + +static const int dht_segment_size = 420; +static const uint8_t dht_segment_head[] = { 0xFF, 0xC4, 0x01, 0xA2, 0x00 }; +static const uint8_t dht_segment_frag[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t *append(uint8_t *buf, const uint8_t *src, int size) +{ + memcpy(buf, src, size); + return buf + size; +} + +static uint8_t *append_dht_segment(uint8_t *buf) +{ + buf = append(buf, dht_segment_head, sizeof(dht_segment_head)); + buf = append(buf, avpriv_mjpeg_bits_dc_luminance + 1, 16); + buf = append(buf, dht_segment_frag, sizeof(dht_segment_frag)); + buf = append(buf, avpriv_mjpeg_val_dc, 12); + *(buf++) = 0x10; + buf = append(buf, avpriv_mjpeg_bits_ac_luminance + 1, 16); + buf = append(buf, avpriv_mjpeg_val_ac_luminance, 162); + *(buf++) = 0x11; + buf = append(buf, avpriv_mjpeg_bits_ac_chrominance + 1, 16); + buf = append(buf, avpriv_mjpeg_val_ac_chrominance, 162); + return buf; +} + +static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc, + AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int keyframe) +{ + int input_skip, output_size; + uint8_t *output, *out; + + if (buf_size < 12) { + av_log(avctx, AV_LOG_ERROR, "input is truncated\n"); + return AVERROR_INVALIDDATA; + } + if (memcmp("AVI1", buf + 6, 4)) { + av_log(avctx, AV_LOG_ERROR, "input is not MJPEG/AVI1\n"); + return AVERROR_INVALIDDATA; + } + input_skip = (buf[4] << 8) + buf[5] + 4; + if (buf_size < input_skip) { + av_log(avctx, AV_LOG_ERROR, "input is truncated\n"); + return AVERROR_INVALIDDATA; + } + output_size = buf_size - input_skip + + sizeof(jpeg_header) + dht_segment_size; + output = out = av_malloc(output_size); + if (!output) + return AVERROR(ENOMEM); + out = append(out, jpeg_header, sizeof(jpeg_header)); + out = append_dht_segment(out); + out = append(out, buf + input_skip, buf_size - input_skip); + *poutbuf = output; + *poutbuf_size = output_size; + return 1; +} + +AVBitStreamFilter ff_mjpeg2jpeg_bsf = { + .name = "mjpeg2jpeg", + .filter = mjpeg2jpeg_filter, +}; diff --git a/ffmpeg/libavcodec/mjpeg_parser.c b/ffmpeg/libavcodec/mjpeg_parser.c new file mode 100644 index 0000000..e548b00 --- /dev/null +++ b/ffmpeg/libavcodec/mjpeg_parser.c @@ -0,0 +1,134 @@ +/* + * MJPEG parser + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 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 + */ + +/** + * @file + * MJPEG parser. + */ + +#include "parser.h" + +typedef struct MJPEGParserContext{ + ParseContext pc; + int size; +}MJPEGParserContext; + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int find_frame_end(MJPEGParserContext *m, const uint8_t *buf, int buf_size){ + ParseContext *pc= &m->pc; + int vop_found, i; + uint32_t state; + + vop_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!vop_found){ + for(i=0; i=0xFFC00000 && state<=0xFFFEFFFF){ + if(state>=0xFFD80000 && state<=0xFFD8FFFF){ + i++; + vop_found=1; + break; + }else if(state<0xFFD00000 || state>0xFFD9FFFF){ + m->size= (state&0xFFFF)-1; + } + } + if(m->size>0){ + int size= FFMIN(buf_size-i, m->size); + i+=size; + m->size-=size; + state=0; + continue; + }else + i++; + } + } + + if(vop_found){ + /* EOF considered as end of frame */ + if (buf_size == 0) + return 0; + for(; i=0xFFC00000 && state<=0xFFFEFFFF){ + if(state>=0xFFD80000 && state<=0xFFD8FFFF){ + pc->frame_start_found=0; + pc->state=0; + return i-3; + } else if(state<0xFFD00000 || state>0xFFD9FFFF){ + m->size= (state&0xFFFF)-1; + } + } + if(m->size>0){ + int size= FFMIN(buf_size-i, m->size); + i+=size; + m->size-=size; + state=0; + continue; + }else + i++; + } + } + pc->frame_start_found= vop_found; + pc->state= state; + return END_NOT_FOUND; +} + +static int jpeg_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + MJPEGParserContext *m = s->priv_data; + ParseContext *pc = &m->pc; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= find_frame_end(m, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + + +AVCodecParser ff_mjpeg_parser = { + .codec_ids = { AV_CODEC_ID_MJPEG }, + .priv_data_size = sizeof(MJPEGParserContext), + .parser_parse = jpeg_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/mjpega_dump_header_bsf.c b/ffmpeg/libavcodec/mjpega_dump_header_bsf.c new file mode 100644 index 0000000..9de6ac3 --- /dev/null +++ b/ffmpeg/libavcodec/mjpega_dump_header_bsf.c @@ -0,0 +1,94 @@ +/* + * MJPEG A dump header bitstream filter + * Copyright (c) 2006 Baptiste Coudurier + * + * 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 + */ + +/** + * @file + * MJPEG A dump header bitstream filter + * modifies bitstream to be decoded by quicktime + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "mjpeg.h" + + +static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe) +{ + uint8_t *poutbufp; + unsigned dqt = 0, dht = 0, sof0 = 0; + int i; + + if (avctx->codec_id != AV_CODEC_ID_MJPEG) { + av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n"); + return 0; + } + + *poutbuf_size = 0; + *poutbuf = av_malloc(buf_size + 44 + FF_INPUT_BUFFER_PADDING_SIZE); + poutbufp = *poutbuf; + bytestream_put_byte(&poutbufp, 0xff); + bytestream_put_byte(&poutbufp, SOI); + bytestream_put_byte(&poutbufp, 0xff); + bytestream_put_byte(&poutbufp, APP1); + bytestream_put_be16(&poutbufp, 42); /* size */ + bytestream_put_be32(&poutbufp, 0); + bytestream_put_buffer(&poutbufp, "mjpg", 4); + bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */ + bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */ + bytestream_put_be32(&poutbufp, 0); /* next ptr */ + + for (i = 0; i < buf_size - 1; i++) { + if (buf[i] == 0xff) { + switch (buf[i + 1]) { + case DQT: dqt = i + 46; break; + case DHT: dht = i + 46; break; + case SOF0: sof0 = i + 46; break; + case SOS: + bytestream_put_be32(&poutbufp, dqt); /* quant off */ + bytestream_put_be32(&poutbufp, dht); /* huff off */ + bytestream_put_be32(&poutbufp, sof0); /* image off */ + bytestream_put_be32(&poutbufp, i + 46); /* scan off */ + bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */ + bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */ + *poutbuf_size = poutbufp - *poutbuf; + return 1; + case APP1: + if (i + 8 < buf_size && AV_RL32(buf + i + 8) == AV_RL32("mjpg")) { + av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n"); + memcpy(*poutbuf, buf, buf_size); + *poutbuf_size = buf_size; + return 1; + } + } + } + } + av_freep(poutbuf); + av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n"); + return 0; +} + +AVBitStreamFilter ff_mjpega_dump_header_bsf = { + "mjpegadump", + 0, + mjpega_dump_header, +}; diff --git a/ffmpeg/libavcodec/mjpegbdec.c b/ffmpeg/libavcodec/mjpegbdec.c new file mode 100644 index 0000000..4327c10 --- /dev/null +++ b/ffmpeg/libavcodec/mjpegbdec.c @@ -0,0 +1,167 @@ +/* + * Apple MJPEG-B decoder + * Copyright (c) 2002 Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * Apple MJPEG-B decoder. + */ + +#include "avcodec.h" +#include "mjpeg.h" +#include "mjpegdec.h" + +static uint32_t read_offs(AVCodecContext *avctx, GetBitContext *gb, uint32_t size, const char *err_msg){ + uint32_t offs= get_bits_long(gb, 32); + if(offs >= size){ + av_log(avctx, AV_LOG_WARNING, err_msg, offs, size); + return 0; + } + return offs; +} + +static int mjpegb_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MJpegDecodeContext *s = avctx->priv_data; + const uint8_t *buf_end, *buf_ptr; + GetBitContext hgb; /* for the header */ + uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs; + uint32_t field_size, sod_offs; + int ret; + + buf_ptr = buf; + buf_end = buf + buf_size; + s->got_picture = 0; + +read_header: + /* reset on every SOI */ + s->restart_interval = 0; + s->restart_count = 0; + s->mjpb_skiptosod = 0; + + if (buf_end - buf_ptr >= 1 << 28) + return AVERROR_INVALIDDATA; + + init_get_bits(&hgb, buf_ptr, /*buf_size*/(buf_end - buf_ptr)*8); + + skip_bits(&hgb, 32); /* reserved zeros */ + + if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g')) + { + av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n"); + return AVERROR_INVALIDDATA; + } + + field_size = get_bits_long(&hgb, 32); /* field size */ + av_log(avctx, AV_LOG_DEBUG, "field size: 0x%x\n", field_size); + skip_bits(&hgb, 32); /* padded field size */ + second_field_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "second_field_offs is %d and size is %d\n"); + av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs); + + dqt_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dqt is %d and size is %d\n"); + av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%x\n", dqt_offs); + if (dqt_offs) + { + init_get_bits(&s->gb, buf_ptr+dqt_offs, (buf_end - (buf_ptr+dqt_offs))*8); + s->start_code = DQT; + if (ff_mjpeg_decode_dqt(s) < 0 && + (avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; + } + + dht_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dht is %d and size is %d\n"); + av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%x\n", dht_offs); + if (dht_offs) + { + init_get_bits(&s->gb, buf_ptr+dht_offs, (buf_end - (buf_ptr+dht_offs))*8); + s->start_code = DHT; + ff_mjpeg_decode_dht(s); + } + + sof_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n"); + av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%x\n", sof_offs); + if (sof_offs) + { + init_get_bits(&s->gb, buf_ptr+sof_offs, (buf_end - (buf_ptr+sof_offs))*8); + s->start_code = SOF0; + if (ff_mjpeg_decode_sof(s) < 0) + return -1; + } + + sos_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sos is %d and size is %d\n"); + av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs); + sod_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n"); + av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%x\n", sod_offs); + if (sos_offs) + { + init_get_bits(&s->gb, buf_ptr + sos_offs, + 8 * FFMIN(field_size, buf_end - buf_ptr - sos_offs)); + s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16)); + s->start_code = SOS; + if (ff_mjpeg_decode_sos(s, NULL, NULL) < 0 && + (avctx->err_recognition & AV_EF_EXPLODE)) + return AVERROR_INVALIDDATA; + } + + if (s->interlaced) { + s->bottom_field ^= 1; + /* if not bottom field, do not output image yet */ + if (s->bottom_field != s->interlace_polarity && second_field_offs) + { + buf_ptr = buf + second_field_offs; + goto read_header; + } + } + + //XXX FIXME factorize, this looks very similar to the EOI code + + if(!s->got_picture) { + av_log(avctx, AV_LOG_WARNING, "no picture\n"); + return buf_size; + } + + if ((ret = av_frame_ref(data, s->picture_ptr)) < 0) + return ret; + *got_frame = 1; + + if (!s->lossless && avctx->debug & FF_DEBUG_QP) { + av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", + FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2])); + } + + return buf_size; +} + +AVCodec ff_mjpegb_decoder = { + .name = "mjpegb", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEGB, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = mjpegb_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"), +}; diff --git a/ffmpeg/libavcodec/mjpegdec.c b/ffmpeg/libavcodec/mjpegdec.c new file mode 100644 index 0000000..5880fec --- /dev/null +++ b/ffmpeg/libavcodec/mjpegdec.c @@ -0,0 +1,1935 @@ +/* + * MJPEG decoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * MJPEG decoder. + */ + +#include "libavutil/imgutils.h" +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "copy_block.h" +#include "internal.h" +#include "mjpeg.h" +#include "mjpegdec.h" +#include "jpeglsdec.h" + + +static int build_vlc(VLC *vlc, const uint8_t *bits_table, + const uint8_t *val_table, int nb_codes, + int use_static, int is_ac) +{ + uint8_t huff_size[256] = { 0 }; + uint16_t huff_code[256]; + uint16_t huff_sym[256]; + int i; + + av_assert0(nb_codes <= 256); + + ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table); + + for (i = 0; i < 256; i++) + huff_sym[i] = i + 16 * is_ac; + + if (is_ac) + huff_sym[0] = 16 * 256; + + return ff_init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1, + huff_code, 2, 2, huff_sym, 2, 2, use_static); +} + +static void build_basic_mjpeg_vlc(MJpegDecodeContext *s) +{ + build_vlc(&s->vlcs[0][0], avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc, 12, 0, 0); + build_vlc(&s->vlcs[0][1], avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc, 12, 0, 0); + build_vlc(&s->vlcs[1][0], avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance, 251, 0, 1); + build_vlc(&s->vlcs[1][1], avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance, 251, 0, 1); + build_vlc(&s->vlcs[2][0], avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance, 251, 0, 0); + build_vlc(&s->vlcs[2][1], avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance, 251, 0, 0); +} + +av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) +{ + MJpegDecodeContext *s = avctx->priv_data; + + if (!s->picture_ptr) + s->picture_ptr = &s->picture; + avcodec_get_frame_defaults(&s->picture); + + s->avctx = avctx; + ff_hpeldsp_init(&s->hdsp, avctx->flags); + ff_dsputil_init(&s->dsp, avctx); + ff_init_scantable(s->dsp.idct_permutation, &s->scantable, ff_zigzag_direct); + s->buffer_size = 0; + s->buffer = NULL; + s->start_code = -1; + s->first_picture = 1; + s->got_picture = 0; + s->org_height = avctx->coded_height; + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + + build_basic_mjpeg_vlc(s); + + if (s->extern_huff) { + av_log(avctx, AV_LOG_INFO, "using external huffman table\n"); + init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size * 8); + if (ff_mjpeg_decode_dht(s)) { + av_log(avctx, AV_LOG_ERROR, + "error using external huffman table, switching back to internal\n"); + build_basic_mjpeg_vlc(s); + } + } + if (avctx->field_order == AV_FIELD_BB) { /* quicktime icefloe 019 */ + s->interlace_polarity = 1; /* bottom field first */ + av_log(avctx, AV_LOG_DEBUG, "bottom field first\n"); + } + if (avctx->codec->id == AV_CODEC_ID_AMV) + s->flipped = 1; + + return 0; +} + + +/* quantize tables */ +int ff_mjpeg_decode_dqt(MJpegDecodeContext *s) +{ + int len, index, i, j; + + len = get_bits(&s->gb, 16) - 2; + + while (len >= 65) { + int pr = get_bits(&s->gb, 4); + if (pr > 1) { + av_log(s->avctx, AV_LOG_ERROR, "dqt: invalid precision\n"); + return AVERROR_INVALIDDATA; + } + index = get_bits(&s->gb, 4); + if (index >= 4) + return -1; + av_log(s->avctx, AV_LOG_DEBUG, "index=%d\n", index); + /* read quant table */ + for (i = 0; i < 64; i++) { + j = s->scantable.permutated[i]; + s->quant_matrixes[index][j] = get_bits(&s->gb, pr ? 16 : 8); + } + + // XXX FIXME finetune, and perhaps add dc too + s->qscale[index] = FFMAX(s->quant_matrixes[index][s->scantable.permutated[1]], + s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1; + av_log(s->avctx, AV_LOG_DEBUG, "qscale[%d]: %d\n", + index, s->qscale[index]); + len -= 65; + } + return 0; +} + +/* decode huffman tables and build VLC decoders */ +int ff_mjpeg_decode_dht(MJpegDecodeContext *s) +{ + int len, index, i, class, n, v, code_max; + uint8_t bits_table[17]; + uint8_t val_table[256]; + int ret = 0; + + len = get_bits(&s->gb, 16) - 2; + + while (len > 0) { + if (len < 17) + return AVERROR_INVALIDDATA; + class = get_bits(&s->gb, 4); + if (class >= 2) + return AVERROR_INVALIDDATA; + index = get_bits(&s->gb, 4); + if (index >= 4) + return AVERROR_INVALIDDATA; + n = 0; + for (i = 1; i <= 16; i++) { + bits_table[i] = get_bits(&s->gb, 8); + n += bits_table[i]; + } + len -= 17; + if (len < n || n > 256) + return AVERROR_INVALIDDATA; + + code_max = 0; + for (i = 0; i < n; i++) { + v = get_bits(&s->gb, 8); + if (v > code_max) + code_max = v; + val_table[i] = v; + } + len -= n; + + /* build VLC and flush previous vlc if present */ + ff_free_vlc(&s->vlcs[class][index]); + av_log(s->avctx, AV_LOG_DEBUG, "class=%d index=%d nb_codes=%d\n", + class, index, code_max + 1); + if ((ret = build_vlc(&s->vlcs[class][index], bits_table, val_table, + code_max + 1, 0, class > 0)) < 0) + return ret; + + if (class > 0) { + ff_free_vlc(&s->vlcs[2][index]); + if ((ret = build_vlc(&s->vlcs[2][index], bits_table, val_table, + code_max + 1, 0, 0)) < 0) + return ret; + } + } + return 0; +} + +int ff_mjpeg_decode_sof(MJpegDecodeContext *s) +{ + int len, nb_components, i, width, height, pix_fmt_id; + int h_count[MAX_COMPONENTS]; + int v_count[MAX_COMPONENTS]; + + s->cur_scan = 0; + s->upscale_h = s->upscale_v = 0; + + /* XXX: verify len field validity */ + len = get_bits(&s->gb, 16); + s->bits = get_bits(&s->gb, 8); + + if (s->pegasus_rct) + s->bits = 9; + if (s->bits == 9 && !s->pegasus_rct) + s->rct = 1; // FIXME ugly + + if (s->bits != 8 && !s->lossless) { + av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n"); + return -1; + } + + if(s->lossless && s->avctx->lowres){ + av_log(s->avctx, AV_LOG_ERROR, "lowres is not possible with lossless jpeg\n"); + return -1; + } + + height = get_bits(&s->gb, 16); + width = get_bits(&s->gb, 16); + + // HACK for odd_height.mov + if (s->interlaced && s->width == width && s->height == height + 1) + height= s->height; + + av_log(s->avctx, AV_LOG_DEBUG, "sof0: picture: %dx%d\n", width, height); + if (av_image_check_size(width, height, 0, s->avctx)) + return AVERROR_INVALIDDATA; + + nb_components = get_bits(&s->gb, 8); + if (nb_components <= 0 || + nb_components > MAX_COMPONENTS) + return -1; + if (s->interlaced && (s->bottom_field == !s->interlace_polarity)) { + if (nb_components != s->nb_components) { + av_log(s->avctx, AV_LOG_ERROR, "nb_components changing in interlaced picture\n"); + return AVERROR_INVALIDDATA; + } + } + if (s->ls && !(s->bits <= 8 || nb_components == 1)) { + avpriv_report_missing_feature(s->avctx, + "JPEG-LS that is not <= 8 " + "bits/component or 16-bit gray"); + return AVERROR_PATCHWELCOME; + } + s->nb_components = nb_components; + s->h_max = 1; + s->v_max = 1; + memset(h_count, 0, sizeof(h_count)); + memset(v_count, 0, sizeof(v_count)); + for (i = 0; i < nb_components; i++) { + /* component id */ + s->component_id[i] = get_bits(&s->gb, 8) - 1; + h_count[i] = get_bits(&s->gb, 4); + v_count[i] = get_bits(&s->gb, 4); + /* compute hmax and vmax (only used in interleaved case) */ + if (h_count[i] > s->h_max) + s->h_max = h_count[i]; + if (v_count[i] > s->v_max) + s->v_max = v_count[i]; + if (!h_count[i] || !v_count[i]) { + av_log(s->avctx, AV_LOG_ERROR, "h/v_count is 0\n"); + return -1; + } + s->quant_index[i] = get_bits(&s->gb, 8); + if (s->quant_index[i] >= 4) { + av_log(s->avctx, AV_LOG_ERROR, "quant_index is invalid\n"); + return AVERROR_INVALIDDATA; + } + av_log(s->avctx, AV_LOG_DEBUG, "component %d %d:%d id: %d quant:%d\n", + i, h_count[i], v_count[i], + s->component_id[i], s->quant_index[i]); + } + + if (s->ls && (s->h_max > 1 || s->v_max > 1)) { + avpriv_report_missing_feature(s->avctx, "Subsampling in JPEG-LS"); + return AVERROR_PATCHWELCOME; + } + + + /* if different size, realloc/alloc picture */ + if ( width != s->width || height != s->height + || memcmp(s->h_count, h_count, sizeof(h_count)) + || memcmp(s->v_count, v_count, sizeof(v_count))) { + + s->width = width; + s->height = height; + memcpy(s->h_count, h_count, sizeof(h_count)); + memcpy(s->v_count, v_count, sizeof(v_count)); + s->interlaced = 0; + s->got_picture = 0; + + /* test interlaced mode */ + if (s->first_picture && + s->org_height != 0 && + s->height < ((s->org_height * 3) / 4)) { + s->interlaced = 1; + s->bottom_field = s->interlace_polarity; + s->picture_ptr->interlaced_frame = 1; + s->picture_ptr->top_field_first = !s->interlace_polarity; + height *= 2; + } + + avcodec_set_dimensions(s->avctx, width, height); + + s->first_picture = 0; + } + + if (s->interlaced && (s->bottom_field == !s->interlace_polarity)) { + if (s->progressive) { + avpriv_request_sample(s->avctx, "progressively coded interlaced picture"); + return AVERROR_INVALIDDATA; + } + } else{ + if (s->v_max == 1 && s->h_max == 1 && s->lossless==1 && nb_components==3) + s->rgb = 1; + else if (!s->lossless) + s->rgb = 0; + /* XXX: not complete test ! */ + pix_fmt_id = (s->h_count[0] << 28) | (s->v_count[0] << 24) | + (s->h_count[1] << 20) | (s->v_count[1] << 16) | + (s->h_count[2] << 12) | (s->v_count[2] << 8) | + (s->h_count[3] << 4) | s->v_count[3]; + av_log(s->avctx, AV_LOG_DEBUG, "pix fmt id %x\n", pix_fmt_id); + /* NOTE we do not allocate pictures large enough for the possible + * padding of h/v_count being 4 */ + if (!(pix_fmt_id & 0xD0D0D0D0)) + pix_fmt_id -= (pix_fmt_id & 0xF0F0F0F0) >> 1; + if (!(pix_fmt_id & 0x0D0D0D0D)) + pix_fmt_id -= (pix_fmt_id & 0x0F0F0F0F) >> 1; + + switch (pix_fmt_id) { + case 0x11111100: + if (s->rgb) + s->avctx->pix_fmt = AV_PIX_FMT_BGR24; + else { + if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') { + s->avctx->pix_fmt = AV_PIX_FMT_GBR24P; + } else { + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + } + } + av_assert0(s->nb_components == 3); + break; + case 0x12121100: + case 0x22122100: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + s->upscale_v = 2; + s->upscale_h = (pix_fmt_id == 0x22122100); + s->chroma_height = s->height; + break; + case 0x21211100: + case 0x22211200: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + s->upscale_v = (pix_fmt_id == 0x22211200); + s->upscale_h = 2; + s->chroma_height = s->height; + break; + case 0x22221100: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + s->upscale_v = 2; + s->upscale_h = 2; + s->chroma_height = s->height / 2; + break; + case 0x11000000: + case 0x13000000: + case 0x14000000: + case 0x31000000: + case 0x33000000: + case 0x34000000: + case 0x41000000: + case 0x43000000: + case 0x44000000: + if(s->bits <= 8) + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + else + s->avctx->pix_fmt = AV_PIX_FMT_GRAY16; + break; + case 0x12111100: + case 0x22211100: + case 0x22112100: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + s->upscale_h = (pix_fmt_id == 0x22211100) * 2 + (pix_fmt_id == 0x22112100); + s->chroma_height = s->height / 2; + break; + case 0x21111100: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + break; + case 0x22121100: + case 0x22111200: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + s->upscale_v = (pix_fmt_id == 0x22121100) + 1; + break; + case 0x22111100: + s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUVJ420P; + s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id); + return AVERROR_PATCHWELCOME; + } + if ((s->upscale_h || s->upscale_v) && s->avctx->lowres) { + av_log(s->avctx, AV_LOG_ERROR, "lowres not supported for weird subsampling\n"); + return AVERROR_PATCHWELCOME; + } + if (s->ls) { + s->upscale_h = s->upscale_v = 0; + if (s->nb_components > 1) + s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + else if (s->bits <= 8) + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + else + s->avctx->pix_fmt = AV_PIX_FMT_GRAY16; + } + + av_frame_unref(s->picture_ptr); + if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0) + return -1; + s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; + s->picture_ptr->key_frame = 1; + s->got_picture = 1; + + for (i = 0; i < 3; i++) + s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced; + + av_dlog(s->avctx, "%d %d %d %d %d %d\n", + s->width, s->height, s->linesize[0], s->linesize[1], + s->interlaced, s->avctx->height); + + if (len != (8 + (3 * nb_components))) + av_log(s->avctx, AV_LOG_DEBUG, "decode_sof0: error, len(%d) mismatch\n", len); + } + + if (s->rgb && !s->lossless && !s->ls) { + av_log(s->avctx, AV_LOG_ERROR, "Unsupported coding and pixel format combination\n"); + return AVERROR_PATCHWELCOME; + } + + /* totally blank picture as progressive JPEG will only add details to it */ + if (s->progressive) { + int bw = (width + s->h_max * 8 - 1) / (s->h_max * 8); + int bh = (height + s->v_max * 8 - 1) / (s->v_max * 8); + for (i = 0; i < s->nb_components; i++) { + int size = bw * bh * s->h_count[i] * s->v_count[i]; + av_freep(&s->blocks[i]); + av_freep(&s->last_nnz[i]); + s->blocks[i] = av_malloc(size * sizeof(**s->blocks)); + s->last_nnz[i] = av_mallocz(size * sizeof(**s->last_nnz)); + s->block_stride[i] = bw * s->h_count[i]; + } + memset(s->coefs_finished, 0, sizeof(s->coefs_finished)); + } + return 0; +} + +static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index) +{ + int code; + code = get_vlc2(&s->gb, s->vlcs[0][dc_index].table, 9, 2); + if (code < 0) { + av_log(s->avctx, AV_LOG_WARNING, + "mjpeg_decode_dc: bad vlc: %d:%d (%p)\n", + 0, dc_index, &s->vlcs[0][dc_index]); + return 0xffff; + } + + if (code) + return get_xbits(&s->gb, code); + else + return 0; +} + +/* decode block and dequantize */ +static int decode_block(MJpegDecodeContext *s, int16_t *block, int component, + int dc_index, int ac_index, int16_t *quant_matrix) +{ + int code, i, j, level, val; + + /* DC coef */ + val = mjpeg_decode_dc(s, dc_index); + if (val == 0xffff) { + av_log(s->avctx, AV_LOG_ERROR, "error dc\n"); + return AVERROR_INVALIDDATA; + } + val = val * quant_matrix[0] + s->last_dc[component]; + s->last_dc[component] = val; + block[0] = val; + /* AC coefs */ + i = 0; + {OPEN_READER(re, &s->gb); + do { + UPDATE_CACHE(re, &s->gb); + GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2); + + i += ((unsigned)code) >> 4; + code &= 0xf; + if (code) { + if (code > MIN_CACHE_BITS - 16) + UPDATE_CACHE(re, &s->gb); + + { + int cache = GET_CACHE(re, &s->gb); + int sign = (~cache) >> 31; + level = (NEG_USR32(sign ^ cache,code) ^ sign) - sign; + } + + LAST_SKIP_BITS(re, &s->gb, code); + + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i); + return AVERROR_INVALIDDATA; + } + j = s->scantable.permutated[i]; + block[j] = level * quant_matrix[j]; + } + } while (i < 63); + CLOSE_READER(re, &s->gb);} + + return 0; +} + +static int decode_dc_progressive(MJpegDecodeContext *s, int16_t *block, + int component, int dc_index, + int16_t *quant_matrix, int Al) +{ + int val; + s->dsp.clear_block(block); + val = mjpeg_decode_dc(s, dc_index); + if (val == 0xffff) { + av_log(s->avctx, AV_LOG_ERROR, "error dc\n"); + return AVERROR_INVALIDDATA; + } + val = (val * quant_matrix[0] << Al) + s->last_dc[component]; + s->last_dc[component] = val; + block[0] = val; + return 0; +} + +/* decode block and dequantize - progressive JPEG version */ +static int decode_block_progressive(MJpegDecodeContext *s, int16_t *block, + uint8_t *last_nnz, int ac_index, + int16_t *quant_matrix, + int ss, int se, int Al, int *EOBRUN) +{ + int code, i, j, level, val, run; + + if (*EOBRUN) { + (*EOBRUN)--; + return 0; + } + + { + OPEN_READER(re, &s->gb); + for (i = ss; ; i++) { + UPDATE_CACHE(re, &s->gb); + GET_VLC(code, re, &s->gb, s->vlcs[2][ac_index].table, 9, 2); + + run = ((unsigned) code) >> 4; + code &= 0xF; + if (code) { + i += run; + if (code > MIN_CACHE_BITS - 16) + UPDATE_CACHE(re, &s->gb); + + { + int cache = GET_CACHE(re, &s->gb); + int sign = (~cache) >> 31; + level = (NEG_USR32(sign ^ cache,code) ^ sign) - sign; + } + + LAST_SKIP_BITS(re, &s->gb, code); + + if (i >= se) { + if (i == se) { + j = s->scantable.permutated[se]; + block[j] = level * quant_matrix[j] << Al; + break; + } + av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i); + return AVERROR_INVALIDDATA; + } + j = s->scantable.permutated[i]; + block[j] = level * quant_matrix[j] << Al; + } else { + if (run == 0xF) {// ZRL - skip 15 coefficients + i += 15; + if (i >= se) { + av_log(s->avctx, AV_LOG_ERROR, "ZRL overflow: %d\n", i); + return AVERROR_INVALIDDATA; + } + } else { + val = (1 << run); + if (run) { + UPDATE_CACHE(re, &s->gb); + val += NEG_USR32(GET_CACHE(re, &s->gb), run); + LAST_SKIP_BITS(re, &s->gb, run); + } + *EOBRUN = val - 1; + break; + } + } + } + CLOSE_READER(re, &s->gb); + } + + if (i > *last_nnz) + *last_nnz = i; + + return 0; +} + +#define REFINE_BIT(j) { \ + UPDATE_CACHE(re, &s->gb); \ + sign = block[j] >> 15; \ + block[j] += SHOW_UBITS(re, &s->gb, 1) * \ + ((quant_matrix[j] ^ sign) - sign) << Al; \ + LAST_SKIP_BITS(re, &s->gb, 1); \ +} + +#define ZERO_RUN \ +for (; ; i++) { \ + if (i > last) { \ + i += run; \ + if (i > se) { \ + av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i); \ + return -1; \ + } \ + break; \ + } \ + j = s->scantable.permutated[i]; \ + if (block[j]) \ + REFINE_BIT(j) \ + else if (run-- == 0) \ + break; \ +} + +/* decode block and dequantize - progressive JPEG refinement pass */ +static int decode_block_refinement(MJpegDecodeContext *s, int16_t *block, + uint8_t *last_nnz, + int ac_index, int16_t *quant_matrix, + int ss, int se, int Al, int *EOBRUN) +{ + int code, i = ss, j, sign, val, run; + int last = FFMIN(se, *last_nnz); + + OPEN_READER(re, &s->gb); + if (*EOBRUN) { + (*EOBRUN)--; + } else { + for (; ; i++) { + UPDATE_CACHE(re, &s->gb); + GET_VLC(code, re, &s->gb, s->vlcs[2][ac_index].table, 9, 2); + + if (code & 0xF) { + run = ((unsigned) code) >> 4; + UPDATE_CACHE(re, &s->gb); + val = SHOW_UBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + ZERO_RUN; + j = s->scantable.permutated[i]; + val--; + block[j] = ((quant_matrix[j]^val) - val) << Al; + if (i == se) { + if (i > *last_nnz) + *last_nnz = i; + CLOSE_READER(re, &s->gb); + return 0; + } + } else { + run = ((unsigned) code) >> 4; + if (run == 0xF) { + ZERO_RUN; + } else { + val = run; + run = (1 << run); + if (val) { + UPDATE_CACHE(re, &s->gb); + run += SHOW_UBITS(re, &s->gb, val); + LAST_SKIP_BITS(re, &s->gb, val); + } + *EOBRUN = run - 1; + break; + } + } + } + + if (i > *last_nnz) + *last_nnz = i; + } + + for (; i <= last; i++) { + j = s->scantable.permutated[i]; + if (block[j]) + REFINE_BIT(j) + } + CLOSE_READER(re, &s->gb); + + return 0; +} +#undef REFINE_BIT +#undef ZERO_RUN + +static void handle_rstn(MJpegDecodeContext *s, int nb_components) +{ + int i; + if (s->restart_interval) { + s->restart_count--; + if(s->restart_count == 0 && s->avctx->codec_id == AV_CODEC_ID_THP){ + align_get_bits(&s->gb); + for (i = 0; i < nb_components; i++) /* reset dc */ + s->last_dc[i] = 1024; + } + + i = 8 + ((-get_bits_count(&s->gb)) & 7); + /* skip RSTn */ + if (s->restart_count == 0) { + if( show_bits(&s->gb, i) == (1 << i) - 1 + || show_bits(&s->gb, i) == 0xFF) { + int pos = get_bits_count(&s->gb); + align_get_bits(&s->gb); + while (get_bits_left(&s->gb) >= 8 && show_bits(&s->gb, 8) == 0xFF) + skip_bits(&s->gb, 8); + if (get_bits_left(&s->gb) >= 8 && (get_bits(&s->gb, 8) & 0xF8) == 0xD0) { + for (i = 0; i < nb_components; i++) /* reset dc */ + s->last_dc[i] = 1024; + } else + skip_bits_long(&s->gb, pos - get_bits_count(&s->gb)); + } + } + } +} + +static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) +{ + int i, mb_x, mb_y; + uint16_t (*buffer)[4]; + int left[3], top[3], topleft[3]; + const int linesize = s->linesize[0]; + const int mask = (1 << s->bits) - 1; + int resync_mb_y = 0; + int resync_mb_x = 0; + + s->restart_count = s->restart_interval; + + av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, + (unsigned)s->mb_width * 4 * sizeof(s->ljpeg_buffer[0][0])); + buffer = s->ljpeg_buffer; + + for (i = 0; i < 3; i++) + buffer[0][i] = 1 << (s->bits - 1); + + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + uint8_t *ptr = s->picture.data[0] + (linesize * mb_y); + + if (s->interlaced && s->bottom_field) + ptr += linesize >> 1; + + for (i = 0; i < 3; i++) + top[i] = left[i] = topleft[i] = buffer[0][i]; + + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + int modified_predictor = predictor; + + if (s->restart_interval && !s->restart_count){ + s->restart_count = s->restart_interval; + resync_mb_x = mb_x; + resync_mb_y = mb_y; + for(i=0; i<3; i++) + top[i] = left[i]= topleft[i]= 1 << (s->bits - 1); + } + if (mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x || !mb_x) + modified_predictor = 1; + + for (i=0;idc_index[i]); + if(dc == 0xFFFF) + return -1; + + left[i] = buffer[mb_x][i] = + mask & (pred + (dc << point_transform)); + } + + if (s->restart_interval && !--s->restart_count) { + align_get_bits(&s->gb); + skip_bits(&s->gb, 16); /* skip RSTn */ + } + } + + if (s->rct) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + ptr[3*mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200) >> 2); + ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1]; + ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1]; + } + } else if (s->pegasus_rct) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + ptr[3*mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2]) >> 2); + ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1]; + ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1]; + } + } else { + for(i=0; icomp_index[i]; + for(mb_x = 0; mb_x < s->mb_width; mb_x++) { + ptr[3*mb_x+2-c] = buffer[mb_x][i]; + } + } + } + } + return 0; +} + +static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int nb_components, int predictor, + int point_transform) +{ + int i, mb_x, mb_y; + int bits= (s->bits+7)&~7; + int resync_mb_y = 0; + int resync_mb_x = 0; + + point_transform += bits - s->bits; + + av_assert0(nb_components>=1 && nb_components<=3); + + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + if (s->restart_interval && !s->restart_count){ + s->restart_count = s->restart_interval; + resync_mb_x = mb_x; + resync_mb_y = mb_y; + } + + if(!mb_x || mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x || s->interlaced){ + int toprow = mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x; + int leftcol = !mb_x || mb_y == resync_mb_y && mb_x == resync_mb_x; + for (i = 0; i < nb_components; i++) { + uint8_t *ptr; + uint16_t *ptr16; + int n, h, v, x, y, c, j, linesize; + n = s->nb_blocks[i]; + c = s->comp_index[i]; + h = s->h_scount[i]; + v = s->v_scount[i]; + x = 0; + y = 0; + linesize= s->linesize[c]; + + if(bits>8) linesize /= 2; + + for(j=0; jdc_index[i]); + if(dc == 0xFFFF) + return -1; + if(bits<=8){ + ptr = s->picture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + if(y==0 && toprow){ + if(x==0 && leftcol){ + pred= 1 << (bits - 1); + }else{ + pred= ptr[-1]; + } + }else{ + if(x==0 && leftcol){ + pred= ptr[-linesize]; + }else{ + PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); + } + } + + if (s->interlaced && s->bottom_field) + ptr += linesize >> 1; + pred &= (-1)<<(8-s->bits); + *ptr= pred + (dc << point_transform); + }else{ + ptr16 = (uint16_t*)(s->picture.data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap + if(y==0 && toprow){ + if(x==0 && leftcol){ + pred= 1 << (bits - 1); + }else{ + pred= ptr16[-1]; + } + }else{ + if(x==0 && leftcol){ + pred= ptr16[-linesize]; + }else{ + PREDICT(pred, ptr16[-linesize-1], ptr16[-linesize], ptr16[-1], predictor); + } + } + + if (s->interlaced && s->bottom_field) + ptr16 += linesize >> 1; + pred &= (-1)<<(16-s->bits); + *ptr16= pred + (dc << point_transform); + } + if (++x == h) { + x = 0; + y++; + } + } + } + } else { + for (i = 0; i < nb_components; i++) { + uint8_t *ptr; + uint16_t *ptr16; + int n, h, v, x, y, c, j, linesize, dc; + n = s->nb_blocks[i]; + c = s->comp_index[i]; + h = s->h_scount[i]; + v = s->v_scount[i]; + x = 0; + y = 0; + linesize = s->linesize[c]; + + if(bits>8) linesize /= 2; + + for (j = 0; j < n; j++) { + int pred; + + dc = mjpeg_decode_dc(s, s->dc_index[i]); + if(dc == 0xFFFF) + return -1; + if(bits<=8){ + ptr = s->picture.data[c] + + (linesize * (v * mb_y + y)) + + (h * mb_x + x); //FIXME optimize this crap + PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); + + pred &= (-1)<<(8-s->bits); + *ptr = pred + (dc << point_transform); + }else{ + ptr16 = (uint16_t*)(s->picture.data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap + PREDICT(pred, ptr16[-linesize-1], ptr16[-linesize], ptr16[-1], predictor); + + pred &= (-1)<<(16-s->bits); + *ptr16= pred + (dc << point_transform); + } + + if (++x == h) { + x = 0; + y++; + } + } + } + } + if (s->restart_interval && !--s->restart_count) { + align_get_bits(&s->gb); + skip_bits(&s->gb, 16); /* skip RSTn */ + } + } + } + return 0; +} + +static av_always_inline void mjpeg_copy_block(MJpegDecodeContext *s, + uint8_t *dst, const uint8_t *src, + int linesize, int lowres) +{ + switch (lowres) { + case 0: s->hdsp.put_pixels_tab[1][0](dst, src, linesize, 8); + break; + case 1: copy_block4(dst, src, linesize, linesize, 4); + break; + case 2: copy_block2(dst, src, linesize, linesize, 2); + break; + case 3: *dst = *src; + break; + } +} + +static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah, + int Al, const uint8_t *mb_bitmask, + const AVFrame *reference) +{ + int i, mb_x, mb_y; + uint8_t *data[MAX_COMPONENTS]; + const uint8_t *reference_data[MAX_COMPONENTS]; + int linesize[MAX_COMPONENTS]; + GetBitContext mb_bitmask_gb; + + if (mb_bitmask) + init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height); + + if (s->flipped && s->avctx->lowres) { + av_log(s->avctx, AV_LOG_ERROR, "Can not flip image with lowres\n"); + s->flipped = 0; + } + + for (i = 0; i < nb_components; i++) { + int c = s->comp_index[i]; + data[c] = s->picture_ptr->data[c]; + reference_data[c] = reference ? reference->data[c] : NULL; + linesize[c] = s->linesize[c]; + s->coefs_finished[c] |= 1; + if (s->flipped && !(s->avctx->flags & CODEC_FLAG_EMU_EDGE)) { + // picture should be flipped upside-down for this codec + int offset = (linesize[c] * (s->v_scount[i] * + (8 * s->mb_height - ((s->height / s->v_max) & 7)) - 1)); + data[c] += offset; + reference_data[c] += offset; + linesize[c] *= -1; + } + } + + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + for (mb_x = 0; mb_x < s->mb_width; mb_x++) { + const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb); + + if (s->restart_interval && !s->restart_count) + s->restart_count = s->restart_interval; + + if (get_bits_left(&s->gb) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "overread %d\n", + -get_bits_left(&s->gb)); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < nb_components; i++) { + uint8_t *ptr; + int n, h, v, x, y, c, j; + int block_offset; + n = s->nb_blocks[i]; + c = s->comp_index[i]; + h = s->h_scount[i]; + v = s->v_scount[i]; + x = 0; + y = 0; + for (j = 0; j < n; j++) { + block_offset = (((linesize[c] * (v * mb_y + y) * 8) + + (h * mb_x + x) * 8) >> s->avctx->lowres); + + if (s->interlaced && s->bottom_field) + block_offset += linesize[c] >> 1; + ptr = data[c] + block_offset; + if (!s->progressive) { + if (copy_mb) + mjpeg_copy_block(s, ptr, reference_data[c] + block_offset, + linesize[c], s->avctx->lowres); + + else { + s->dsp.clear_block(s->block); + if (decode_block(s, s->block, i, + s->dc_index[i], s->ac_index[i], + s->quant_matrixes[s->quant_index[c]]) < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "error y=%d x=%d\n", mb_y, mb_x); + return AVERROR_INVALIDDATA; + } + s->dsp.idct_put(ptr, linesize[c], s->block); + } + } else { + int block_idx = s->block_stride[c] * (v * mb_y + y) + + (h * mb_x + x); + int16_t *block = s->blocks[c][block_idx]; + if (Ah) + block[0] += get_bits1(&s->gb) * + s->quant_matrixes[s->quant_index[c]][0] << Al; + else if (decode_dc_progressive(s, block, i, s->dc_index[i], + s->quant_matrixes[s->quant_index[c]], + Al) < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "error y=%d x=%d\n", mb_y, mb_x); + return AVERROR_INVALIDDATA; + } + } + av_dlog(s->avctx, "mb: %d %d processed\n", mb_y, mb_x); + av_dlog(s->avctx, "%d %d %d %d %d %d %d %d \n", + mb_x, mb_y, x, y, c, s->bottom_field, + (v * mb_y + y) * 8, (h * mb_x + x) * 8); + if (++x == h) { + x = 0; + y++; + } + } + } + + handle_rstn(s, nb_components); + } + } + return 0; +} + +static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss, + int se, int Ah, int Al) +{ + int mb_x, mb_y; + int EOBRUN = 0; + int c = s->comp_index[0]; + uint8_t *data = s->picture.data[c]; + int linesize = s->linesize[c]; + int last_scan = 0; + int16_t *quant_matrix = s->quant_matrixes[s->quant_index[c]]; + + if (se > 63) { + av_log(s->avctx, AV_LOG_ERROR, "SE %d is too large\n", se); + return AVERROR_INVALIDDATA; + } + + if (!Al) { + s->coefs_finished[c] |= (1LL << (se + 1)) - (1LL << ss); + last_scan = !~s->coefs_finished[c]; + } + + if (s->interlaced && s->bottom_field) + data += linesize >> 1; + + s->restart_count = 0; + + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + uint8_t *ptr = data + (mb_y * linesize * 8 >> s->avctx->lowres); + int block_idx = mb_y * s->block_stride[c]; + int16_t (*block)[64] = &s->blocks[c][block_idx]; + uint8_t *last_nnz = &s->last_nnz[c][block_idx]; + for (mb_x = 0; mb_x < s->mb_width; mb_x++, block++, last_nnz++) { + int ret; + if (s->restart_interval && !s->restart_count) + s->restart_count = s->restart_interval; + + if (Ah) + ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0], + quant_matrix, ss, se, Al, &EOBRUN); + else + ret = decode_block_progressive(s, *block, last_nnz, s->ac_index[0], + quant_matrix, ss, se, Al, &EOBRUN); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "error y=%d x=%d\n", mb_y, mb_x); + return AVERROR_INVALIDDATA; + } + + if (last_scan) { + s->dsp.idct_put(ptr, linesize, *block); + ptr += 8 >> s->avctx->lowres; + } + handle_rstn(s, 0); + } + } + return 0; +} + +int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, + const AVFrame *reference) +{ + int len, nb_components, i, h, v, predictor, point_transform; + int index, id, ret; + const int block_size = s->lossless ? 1 : 8; + int ilv, prev_shift; + + if (!s->got_picture) { + av_log(s->avctx, AV_LOG_WARNING, + "Can not process SOS before SOF, skipping\n"); + return -1; + } + + av_assert0(s->picture_ptr->data[0]); + /* XXX: verify len field validity */ + len = get_bits(&s->gb, 16); + nb_components = get_bits(&s->gb, 8); + if (nb_components == 0 || nb_components > MAX_COMPONENTS) { + av_log(s->avctx, AV_LOG_ERROR, + "decode_sos: nb_components (%d) unsupported\n", nb_components); + return AVERROR_PATCHWELCOME; + } + if (len != 6 + 2 * nb_components) { + av_log(s->avctx, AV_LOG_ERROR, "decode_sos: invalid len (%d)\n", len); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < nb_components; i++) { + id = get_bits(&s->gb, 8) - 1; + av_log(s->avctx, AV_LOG_DEBUG, "component: %d\n", id); + /* find component index */ + for (index = 0; index < s->nb_components; index++) + if (id == s->component_id[index]) + break; + if (index == s->nb_components) { + av_log(s->avctx, AV_LOG_ERROR, + "decode_sos: index(%d) out of components\n", index); + return AVERROR_INVALIDDATA; + } + /* Metasoft MJPEG codec has Cb and Cr swapped */ + if (s->avctx->codec_tag == MKTAG('M', 'T', 'S', 'J') + && nb_components == 3 && s->nb_components == 3 && i) + index = 3 - i; + + if(nb_components == 3 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P) + index = (i+2)%3; + if(nb_components == 1 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P) + index = (index+2)%3; + + s->comp_index[i] = index; + + s->nb_blocks[i] = s->h_count[index] * s->v_count[index]; + s->h_scount[i] = s->h_count[index]; + s->v_scount[i] = s->v_count[index]; + + s->dc_index[i] = get_bits(&s->gb, 4); + s->ac_index[i] = get_bits(&s->gb, 4); + + if (s->dc_index[i] < 0 || s->ac_index[i] < 0 || + s->dc_index[i] >= 4 || s->ac_index[i] >= 4) + goto out_of_range; + if (!s->vlcs[0][s->dc_index[i]].table || !(s->progressive ? s->vlcs[2][s->ac_index[0]].table : s->vlcs[1][s->ac_index[i]].table)) + goto out_of_range; + } + + predictor = get_bits(&s->gb, 8); /* JPEG Ss / lossless JPEG predictor /JPEG-LS NEAR */ + ilv = get_bits(&s->gb, 8); /* JPEG Se / JPEG-LS ILV */ + if(s->avctx->codec_tag != AV_RL32("CJPG")){ + prev_shift = get_bits(&s->gb, 4); /* Ah */ + point_transform = get_bits(&s->gb, 4); /* Al */ + }else + prev_shift = point_transform = 0; + + if (nb_components > 1) { + /* interleaved stream */ + s->mb_width = (s->width + s->h_max * block_size - 1) / (s->h_max * block_size); + s->mb_height = (s->height + s->v_max * block_size - 1) / (s->v_max * block_size); + } else if (!s->ls) { /* skip this for JPEG-LS */ + h = s->h_max / s->h_scount[0]; + v = s->v_max / s->v_scount[0]; + s->mb_width = (s->width + h * block_size - 1) / (h * block_size); + s->mb_height = (s->height + v * block_size - 1) / (v * block_size); + s->nb_blocks[0] = 1; + s->h_scount[0] = 1; + s->v_scount[0] = 1; + } + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d skip:%d %s comp:%d\n", + s->lossless ? "lossless" : "sequential DCT", s->rgb ? "RGB" : "", + predictor, point_transform, ilv, s->bits, s->mjpb_skiptosod, + s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""), nb_components); + + + /* mjpeg-b can have padding bytes between sos and image data, skip them */ + for (i = s->mjpb_skiptosod; i > 0; i--) + skip_bits(&s->gb, 8); + +next_field: + for (i = 0; i < nb_components; i++) + s->last_dc[i] = 1024; + + if (s->lossless) { + av_assert0(s->picture_ptr == &s->picture); + if (CONFIG_JPEGLS_DECODER && s->ls) { +// for () { +// reset_ls_coding_parameters(s, 0); + + if ((ret = ff_jpegls_decode_picture(s, predictor, + point_transform, ilv)) < 0) + return ret; + } else { + if (s->rgb) { + if ((ret = ljpeg_decode_rgb_scan(s, nb_components, predictor, point_transform)) < 0) + return ret; + } else { + if ((ret = ljpeg_decode_yuv_scan(s, nb_components, predictor, point_transform)) < 0) + return ret; + } + } + } else { + if (s->progressive && predictor) { + av_assert0(s->picture_ptr == &s->picture); + if ((ret = mjpeg_decode_scan_progressive_ac(s, predictor, + ilv, prev_shift, + point_transform)) < 0) + return ret; + } else { + if ((ret = mjpeg_decode_scan(s, nb_components, + prev_shift, point_transform, + mb_bitmask, reference)) < 0) + return ret; + } + } + + if (s->interlaced && + get_bits_left(&s->gb) > 32 && + show_bits(&s->gb, 8) == 0xFF) { + GetBitContext bak = s->gb; + align_get_bits(&bak); + if (show_bits(&bak, 16) == 0xFFD1) { + av_log(s->avctx, AV_LOG_DEBUG, "AVRn interlaced picture marker found\n"); + s->gb = bak; + skip_bits(&s->gb, 16); + s->bottom_field ^= 1; + + goto next_field; + } + } + + emms_c(); + return 0; + out_of_range: + av_log(s->avctx, AV_LOG_ERROR, "decode_sos: ac/dc index out of range\n"); + return AVERROR_INVALIDDATA; +} + +static int mjpeg_decode_dri(MJpegDecodeContext *s) +{ + if (get_bits(&s->gb, 16) != 4) + return AVERROR_INVALIDDATA; + s->restart_interval = get_bits(&s->gb, 16); + s->restart_count = 0; + av_log(s->avctx, AV_LOG_DEBUG, "restart interval: %d\n", + s->restart_interval); + + return 0; +} + +static int mjpeg_decode_app(MJpegDecodeContext *s) +{ + int len, id, i; + + len = get_bits(&s->gb, 16); + if (len < 5) + return AVERROR_INVALIDDATA; + if (8 * len > get_bits_left(&s->gb)) + return AVERROR_INVALIDDATA; + + id = get_bits_long(&s->gb, 32); + len -= 6; + + if (s->avctx->debug & FF_DEBUG_STARTCODE) + av_log(s->avctx, AV_LOG_DEBUG, "APPx %8X\n", id); + + /* Buggy AVID, it puts EOI only at every 10th frame. */ + /* Also, this fourcc is used by non-avid files too, it holds some + information, but it's always present in AVID-created files. */ + if (id == AV_RB32("AVI1")) { + /* structure: + 4bytes AVI1 + 1bytes polarity + 1bytes always zero + 4bytes field_size + 4bytes field_size_less_padding + */ + s->buggy_avid = 1; + i = get_bits(&s->gb, 8); len--; + av_log(s->avctx, AV_LOG_DEBUG, "polarity %d\n", i); +#if 0 + skip_bits(&s->gb, 8); + skip_bits(&s->gb, 32); + skip_bits(&s->gb, 32); + len -= 10; +#endif + goto out; + } + +// len -= 2; + + if (id == AV_RB32("JFIF")) { + int t_w, t_h, v1, v2; + skip_bits(&s->gb, 8); /* the trailing zero-byte */ + v1 = get_bits(&s->gb, 8); + v2 = get_bits(&s->gb, 8); + skip_bits(&s->gb, 8); + + s->avctx->sample_aspect_ratio.num = get_bits(&s->gb, 16); + s->avctx->sample_aspect_ratio.den = get_bits(&s->gb, 16); + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, + "mjpeg: JFIF header found (version: %x.%x) SAR=%d/%d\n", + v1, v2, + s->avctx->sample_aspect_ratio.num, + s->avctx->sample_aspect_ratio.den); + + t_w = get_bits(&s->gb, 8); + t_h = get_bits(&s->gb, 8); + if (t_w && t_h) { + /* skip thumbnail */ + if (len -10 - (t_w * t_h * 3) > 0) + len -= t_w * t_h * 3; + } + len -= 10; + goto out; + } + + if (id == AV_RB32("Adob") && (get_bits(&s->gb, 8) == 'e')) { + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n"); + skip_bits(&s->gb, 16); /* version */ + skip_bits(&s->gb, 16); /* flags0 */ + skip_bits(&s->gb, 16); /* flags1 */ + skip_bits(&s->gb, 8); /* transform */ + len -= 7; + goto out; + } + + if (id == AV_RB32("LJIF")) { + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, + "Pegasus lossless jpeg header found\n"); + skip_bits(&s->gb, 16); /* version ? */ + skip_bits(&s->gb, 16); /* unknown always 0? */ + skip_bits(&s->gb, 16); /* unknown always 0? */ + skip_bits(&s->gb, 16); /* unknown always 0? */ + switch (get_bits(&s->gb, 8)) { + case 1: + s->rgb = 1; + s->pegasus_rct = 0; + break; + case 2: + s->rgb = 1; + s->pegasus_rct = 1; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace\n"); + } + len -= 9; + goto out; + } + + /* Apple MJPEG-A */ + if ((s->start_code == APP1) && (len > (0x28 - 8))) { + id = get_bits_long(&s->gb, 32); + len -= 4; + /* Apple MJPEG-A */ + if (id == AV_RB32("mjpg")) { +#if 0 + skip_bits(&s->gb, 32); /* field size */ + skip_bits(&s->gb, 32); /* pad field size */ + skip_bits(&s->gb, 32); /* next off */ + skip_bits(&s->gb, 32); /* quant off */ + skip_bits(&s->gb, 32); /* huff off */ + skip_bits(&s->gb, 32); /* image off */ + skip_bits(&s->gb, 32); /* scan off */ + skip_bits(&s->gb, 32); /* data off */ +#endif + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n"); + } + } + +out: + /* slow but needed for extreme adobe jpegs */ + if (len < 0) + av_log(s->avctx, AV_LOG_ERROR, + "mjpeg: error, decode_app parser read over the end\n"); + while (--len > 0) + skip_bits(&s->gb, 8); + + return 0; +} + +static int mjpeg_decode_com(MJpegDecodeContext *s) +{ + int len = get_bits(&s->gb, 16); + if (len >= 2 && 8 * len - 16 <= get_bits_left(&s->gb)) { + char *cbuf = av_malloc(len - 1); + if (cbuf) { + int i; + for (i = 0; i < len - 2; i++) + cbuf[i] = get_bits(&s->gb, 8); + if (i > 0 && cbuf[i - 1] == '\n') + cbuf[i - 1] = 0; + else + cbuf[i] = 0; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, "comment: '%s'\n", cbuf); + + /* buggy avid, it puts EOI only at every 10th frame */ + if (!strcmp(cbuf, "AVID")) { + s->buggy_avid = 1; + } else if (!strcmp(cbuf, "CS=ITU601")) + s->cs_itu601 = 1; + else if ((len > 31 && !strncmp(cbuf, "Intel(R) JPEG Library, version 1", 32)) || + (len > 19 && !strncmp(cbuf, "Metasoft MJPEG Codec", 20))) + s->flipped = 1; + + av_free(cbuf); + } + } + + return 0; +} + +/* return the 8 bit start code value and update the search + state. Return -1 if no start code found */ +static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end) +{ + const uint8_t *buf_ptr; + unsigned int v, v2; + int val; + int skipped = 0; + + buf_ptr = *pbuf_ptr; + while (buf_ptr < buf_end) { + v = *buf_ptr++; + v2 = *buf_ptr; + if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) { + val = *buf_ptr++; + goto found; + } + skipped++; + } + val = -1; +found: + av_dlog(NULL, "find_marker skipped %d bytes\n", skipped); + *pbuf_ptr = buf_ptr; + return val; +} + +int ff_mjpeg_find_marker(MJpegDecodeContext *s, + const uint8_t **buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, + int *unescaped_buf_size) +{ + int start_code; + start_code = find_marker(buf_ptr, buf_end); + + av_fast_padded_malloc(&s->buffer, &s->buffer_size, buf_end - *buf_ptr); + if (!s->buffer) + return AVERROR(ENOMEM); + + /* unescape buffer of SOS, use special treatment for JPEG-LS */ + if (start_code == SOS && !s->ls) { + const uint8_t *src = *buf_ptr; + uint8_t *dst = s->buffer; + + while (src < buf_end) { + uint8_t x = *(src++); + + *(dst++) = x; + if (s->avctx->codec_id != AV_CODEC_ID_THP) { + if (x == 0xff) { + while (src < buf_end && x == 0xff) + x = *(src++); + + if (x >= 0xd0 && x <= 0xd7) + *(dst++) = x; + else if (x) + break; + } + } + } + *unescaped_buf_ptr = s->buffer; + *unescaped_buf_size = dst - s->buffer; + memset(s->buffer + *unescaped_buf_size, 0, + FF_INPUT_BUFFER_PADDING_SIZE); + + av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n", + (buf_end - *buf_ptr) - (dst - s->buffer)); + } else if (start_code == SOS && s->ls) { + const uint8_t *src = *buf_ptr; + uint8_t *dst = s->buffer; + int bit_count = 0; + int t = 0, b = 0; + PutBitContext pb; + + s->cur_scan++; + + /* find marker */ + while (src + t < buf_end) { + uint8_t x = src[t++]; + if (x == 0xff) { + while ((src + t < buf_end) && x == 0xff) + x = src[t++]; + if (x & 0x80) { + t -= FFMIN(2, t); + break; + } + } + } + bit_count = t * 8; + init_put_bits(&pb, dst, t); + + /* unescape bitstream */ + while (b < t) { + uint8_t x = src[b++]; + put_bits(&pb, 8, x); + if (x == 0xFF) { + x = src[b++]; + put_bits(&pb, 7, x); + bit_count--; + } + } + flush_put_bits(&pb); + + *unescaped_buf_ptr = dst; + *unescaped_buf_size = (bit_count + 7) >> 3; + memset(s->buffer + *unescaped_buf_size, 0, + FF_INPUT_BUFFER_PADDING_SIZE); + } else { + *unescaped_buf_ptr = *buf_ptr; + *unescaped_buf_size = buf_end - *buf_ptr; + } + + return start_code; +} + +int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MJpegDecodeContext *s = avctx->priv_data; + const uint8_t *buf_end, *buf_ptr; + const uint8_t *unescaped_buf_ptr; + int unescaped_buf_size; + int start_code; + int i, index; + int ret = 0; + + buf_ptr = buf; + buf_end = buf + buf_size; + while (buf_ptr < buf_end) { + /* find start next marker */ + start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end, + &unescaped_buf_ptr, + &unescaped_buf_size); + /* EOF */ + if (start_code < 0) { + goto the_end; + } else if (unescaped_buf_size > (1U<<28)) { + av_log(avctx, AV_LOG_ERROR, "MJPEG packet 0x%x too big (0x%x/0x%x), corrupt data?\n", + start_code, unescaped_buf_size, buf_size); + return AVERROR_INVALIDDATA; + } else { + av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", + start_code, buf_end - buf_ptr); + + init_get_bits(&s->gb, unescaped_buf_ptr, unescaped_buf_size * 8); + + s->start_code = start_code; + if (s->avctx->debug & FF_DEBUG_STARTCODE) + av_log(avctx, AV_LOG_DEBUG, "startcode: %X\n", start_code); + + /* process markers */ + if (start_code >= 0xd0 && start_code <= 0xd7) + av_log(avctx, AV_LOG_DEBUG, + "restart marker: %d\n", start_code & 0x0f); + /* APP fields */ + else if (start_code >= APP0 && start_code <= APP15) + mjpeg_decode_app(s); + /* Comment */ + else if (start_code == COM) + mjpeg_decode_com(s); + + ret = -1; + switch (start_code) { + case SOI: + s->restart_interval = 0; + s->restart_count = 0; + /* nothing to do on SOI */ + break; + case DQT: + ff_mjpeg_decode_dqt(s); + break; + case DHT: + if ((ret = ff_mjpeg_decode_dht(s)) < 0) { + av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n"); + goto fail; + } + break; + case SOF0: + case SOF1: + s->lossless = 0; + s->ls = 0; + s->progressive = 0; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case SOF2: + s->lossless = 0; + s->ls = 0; + s->progressive = 1; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case SOF3: + s->lossless = 1; + s->ls = 0; + s->progressive = 0; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case SOF48: + s->lossless = 1; + s->ls = 1; + s->progressive = 0; + if ((ret = ff_mjpeg_decode_sof(s)) < 0) + goto fail; + break; + case LSE: + if (!CONFIG_JPEGLS_DECODER || + (ret = ff_jpegls_decode_lse(s)) < 0) + goto fail; + break; + case EOI: +eoi_parser: + s->cur_scan = 0; + if (!s->got_picture) { + av_log(avctx, AV_LOG_WARNING, + "Found EOI before any SOF, ignoring\n"); + break; + } + if (s->interlaced) { + s->bottom_field ^= 1; + /* if not bottom field, do not output image yet */ + if (s->bottom_field == !s->interlace_polarity) + break; + } + if ((ret = av_frame_ref(data, s->picture_ptr)) < 0) + return ret; + *got_frame = 1; + s->got_picture = 0; + + if (!s->lossless) { + int qp = FFMAX3(s->qscale[0], + s->qscale[1], + s->qscale[2]); + int qpw = (s->width + 15) / 16; + AVBufferRef *qp_table_buf = av_buffer_alloc(qpw); + if (qp_table_buf) { + memset(qp_table_buf->data, qp, qpw); + av_frame_set_qp_table(data, qp_table_buf, 0, FF_QSCALE_TYPE_MPEG1); + } + + if(avctx->debug & FF_DEBUG_QP) + av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp); + } + + goto the_end; + case SOS: + if ((ret = ff_mjpeg_decode_sos(s, NULL, NULL)) < 0 && + (avctx->err_recognition & AV_EF_EXPLODE)) + goto fail; + break; + case DRI: + mjpeg_decode_dri(s); + break; + case SOF5: + case SOF6: + case SOF7: + case SOF9: + case SOF10: + case SOF11: + case SOF13: + case SOF14: + case SOF15: + case JPG: + av_log(avctx, AV_LOG_ERROR, + "mjpeg: unsupported coding type (%x)\n", start_code); + break; + } + + /* eof process start code */ + buf_ptr += (get_bits_count(&s->gb) + 7) / 8; + av_log(avctx, AV_LOG_DEBUG, + "marker parser used %d bytes (%d bits)\n", + (get_bits_count(&s->gb) + 7) / 8, get_bits_count(&s->gb)); + } + } + if (s->got_picture) { + av_log(avctx, AV_LOG_WARNING, "EOI missing, emulating\n"); + goto eoi_parser; + } + av_log(avctx, AV_LOG_FATAL, "No JPEG data found in image\n"); + return AVERROR_INVALIDDATA; +fail: + s->got_picture = 0; + return ret; +the_end: + if (s->upscale_h) { + uint8_t *line = s->picture_ptr->data[s->upscale_h]; + av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P || + avctx->pix_fmt == AV_PIX_FMT_YUV444P || + avctx->pix_fmt == AV_PIX_FMT_YUVJ440P || + avctx->pix_fmt == AV_PIX_FMT_YUV440P); + for (i = 0; i < s->chroma_height; i++) { + for (index = s->width - 1; index; index--) + line[index] = (line[index / 2] + line[(index + 1) / 2]) >> 1; + line += s->linesize[s->upscale_h]; + } + } + if (s->upscale_v) { + uint8_t *dst = &((uint8_t *)s->picture_ptr->data[s->upscale_v])[(s->height - 1) * s->linesize[s->upscale_v]]; + av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P || + avctx->pix_fmt == AV_PIX_FMT_YUV444P || + avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || + avctx->pix_fmt == AV_PIX_FMT_YUV422P); + for (i = s->height - 1; i; i--) { + uint8_t *src1 = &((uint8_t *)s->picture_ptr->data[s->upscale_v])[i / 2 * s->linesize[s->upscale_v]]; + uint8_t *src2 = &((uint8_t *)s->picture_ptr->data[s->upscale_v])[(i + 1) / 2 * s->linesize[s->upscale_v]]; + if (src1 == src2) { + memcpy(dst, src1, s->width); + } else { + for (index = 0; index < s->width; index++) + dst[index] = (src1[index] + src2[index]) >> 1; + } + dst -= s->linesize[s->upscale_v]; + } + } + if (s->flipped && (s->avctx->flags & CODEC_FLAG_EMU_EDGE)) { + int hshift, vshift, j; + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift); + for (index=0; index<4; index++) { + uint8_t *dst = s->picture_ptr->data[index]; + int w = s->width; + int h = s->height; + if(index && index<3){ + w = -((-w) >> hshift); + h = -((-h) >> vshift); + } + if(dst){ + uint8_t *dst2 = dst + s->linesize[index]*(h-1); + for (i=0; ilinesize[index]; + dst2 -= s->linesize[index]; + } + } + } + } + + av_log(avctx, AV_LOG_DEBUG, "decode frame unused %td bytes\n", + buf_end - buf_ptr); +// return buf_end - buf_ptr; + return buf_ptr - buf; +} + +av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) +{ + MJpegDecodeContext *s = avctx->priv_data; + int i, j; + + if (s->picture_ptr) + av_frame_unref(s->picture_ptr); + + av_free(s->buffer); + av_freep(&s->ljpeg_buffer); + s->ljpeg_buffer_size = 0; + + for (i = 0; i < 3; i++) { + for (j = 0; j < 4; j++) + ff_free_vlc(&s->vlcs[i][j]); + } + for (i = 0; i < MAX_COMPONENTS; i++) { + av_freep(&s->blocks[i]); + av_freep(&s->last_nnz[i]); + } + return 0; +} + +static void decode_flush(AVCodecContext *avctx) +{ + MJpegDecodeContext *s = avctx->priv_data; + s->got_picture = 0; +} + +#if CONFIG_MJPEG_DECODER +#define OFFSET(x) offsetof(MJpegDecodeContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "extern_huff", "Use external huffman table.", + OFFSET(extern_huff), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD }, + { NULL }, +}; + +static const AVClass mjpegdec_class = { + .class_name = "MJPEG decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mjpeg_decoder = { + .name = "mjpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = ff_mjpeg_decode_frame, + .flush = decode_flush, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), + .priv_class = &mjpegdec_class, +}; +#endif +#if CONFIG_THP_DECODER +AVCodec ff_thp_decoder = { + .name = "thp", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_THP, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = ff_mjpeg_decode_frame, + .flush = decode_flush, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), +}; +#endif diff --git a/ffmpeg/libavcodec/mjpegdec.h b/ffmpeg/libavcodec/mjpegdec.h new file mode 100644 index 0000000..17665e4 --- /dev/null +++ b/ffmpeg/libavcodec/mjpegdec.h @@ -0,0 +1,135 @@ +/* + * MJPEG decoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 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 + */ + +/** + * @file + * MJPEG decoder. + */ + +#ifndef AVCODEC_MJPEGDEC_H +#define AVCODEC_MJPEGDEC_H + +#include "libavutil/log.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "hpeldsp.h" + +#define MAX_COMPONENTS 4 + +typedef struct MJpegDecodeContext { + AVClass *class; + AVCodecContext *avctx; + GetBitContext gb; + + int start_code; /* current start code */ + int buffer_size; + uint8_t *buffer; + + int16_t quant_matrixes[4][64]; + VLC vlcs[3][4]; + int qscale[4]; ///< quantizer scale calculated from quant_matrixes + + int org_height; /* size given at codec init */ + int first_picture; /* true if decoding first picture */ + int interlaced; /* true if interlaced */ + int bottom_field; /* true if bottom field */ + int lossless; + int ls; + int progressive; + int rgb; + int upscale_h; + int chroma_height; + int upscale_v; + int rct; /* standard rct */ + int pegasus_rct; /* pegasus reversible colorspace transform */ + int bits; /* bits per component */ + + int maxval; + int near; ///< near lossless bound (si 0 for lossless) + int t1,t2,t3; + int reset; ///< context halfing interval ?rename + + int width, height; + int mb_width, mb_height; + int nb_components; + int block_stride[MAX_COMPONENTS]; + int component_id[MAX_COMPONENTS]; + int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */ + int v_count[MAX_COMPONENTS]; + int comp_index[MAX_COMPONENTS]; + int dc_index[MAX_COMPONENTS]; + int ac_index[MAX_COMPONENTS]; + int nb_blocks[MAX_COMPONENTS]; + int h_scount[MAX_COMPONENTS]; + int v_scount[MAX_COMPONENTS]; + int h_max, v_max; /* maximum h and v counts */ + int quant_index[4]; /* quant table index for each component */ + int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */ + AVFrame picture; /* picture structure */ + AVFrame *picture_ptr; /* pointer to picture structure */ + int got_picture; ///< we found a SOF and picture is valid, too. + int linesize[MAX_COMPONENTS]; ///< linesize << interlaced + int8_t *qscale_table; + DECLARE_ALIGNED(16, int16_t, block)[64]; + int16_t (*blocks[MAX_COMPONENTS])[64]; ///< intermediate sums (progressive mode) + uint8_t *last_nnz[MAX_COMPONENTS]; + uint64_t coefs_finished[MAX_COMPONENTS]; ///< bitmask of which coefs have been completely decoded (progressive mode) + ScanTable scantable; + DSPContext dsp; + HpelDSPContext hdsp; + + int restart_interval; + int restart_count; + + int buggy_avid; + int cs_itu601; + int interlace_polarity; + + int mjpb_skiptosod; + + int cur_scan; /* current scan, used by JPEG-LS */ + int flipped; /* true if picture is flipped */ + + uint16_t (*ljpeg_buffer)[4]; + unsigned int ljpeg_buffer_size; + + int extern_huff; +} MJpegDecodeContext; + +int ff_mjpeg_decode_init(AVCodecContext *avctx); +int ff_mjpeg_decode_end(AVCodecContext *avctx); +int ff_mjpeg_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt); +int ff_mjpeg_decode_dqt(MJpegDecodeContext *s); +int ff_mjpeg_decode_dht(MJpegDecodeContext *s); +int ff_mjpeg_decode_sof(MJpegDecodeContext *s); +int ff_mjpeg_decode_sos(MJpegDecodeContext *s, + const uint8_t *mb_bitmask, const AVFrame *reference); +int ff_mjpeg_find_marker(MJpegDecodeContext *s, + const uint8_t **buf_ptr, const uint8_t *buf_end, + const uint8_t **unescaped_buf_ptr, int *unescaped_buf_size); + +#endif /* AVCODEC_MJPEGDEC_H */ diff --git a/ffmpeg/libavcodec/mjpegenc.c b/ffmpeg/libavcodec/mjpegenc.c new file mode 100644 index 0000000..80a4022 --- /dev/null +++ b/ffmpeg/libavcodec/mjpegenc.c @@ -0,0 +1,544 @@ +/* + * MJPEG encoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * MJPEG encoder. + */ + +#include "avcodec.h" +#include "mpegvideo.h" +#include "mjpeg.h" +#include "mjpegenc.h" + +/* use two quantizer tables (one for luminance and one for chrominance) */ +/* not yet working */ +#undef TWOMATRIXES + + +av_cold int ff_mjpeg_encode_init(MpegEncContext *s) +{ + MJpegContext *m; + + if (s->width > 65500 || s->height > 65500) { + av_log(s, AV_LOG_ERROR, "JPEG does not support resolutions above 65500x65500\n"); + return -1; + } + + m = av_malloc(sizeof(MJpegContext)); + if (!m) + return -1; + + s->min_qcoeff=-1023; + s->max_qcoeff= 1023; + + /* build all the huffman tables */ + ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, + m->huff_code_dc_luminance, + avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc); + ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, + m->huff_code_dc_chrominance, + avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, + m->huff_code_ac_luminance, + avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, + m->huff_code_ac_chrominance, + avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance); + + s->mjpeg_ctx = m; + return 0; +} + +void ff_mjpeg_encode_close(MpegEncContext *s) +{ + av_free(s->mjpeg_ctx); +} + +/* table_class: 0 = DC coef, 1 = AC coefs */ +static int put_huffman_table(MpegEncContext *s, int table_class, int table_id, + const uint8_t *bits_table, const uint8_t *value_table) +{ + PutBitContext *p = &s->pb; + int n, i; + + put_bits(p, 4, table_class); + put_bits(p, 4, table_id); + + n = 0; + for(i=1;i<=16;i++) { + n += bits_table[i]; + put_bits(p, 8, bits_table[i]); + } + + for(i=0;ipb; + int i, j, size; + uint8_t *ptr; + + /* quant matrixes */ + put_marker(p, DQT); +#ifdef TWOMATRIXES + put_bits(p, 16, 2 + 2 * (1 + 64)); +#else + put_bits(p, 16, 2 + 1 * (1 + 64)); +#endif + put_bits(p, 4, 0); /* 8 bit precision */ + put_bits(p, 4, 0); /* table 0 */ + for(i=0;i<64;i++) { + j = s->intra_scantable.permutated[i]; + put_bits(p, 8, s->intra_matrix[j]); + } +#ifdef TWOMATRIXES + put_bits(p, 4, 0); /* 8 bit precision */ + put_bits(p, 4, 1); /* table 1 */ + for(i=0;i<64;i++) { + j = s->intra_scantable.permutated[i]; + put_bits(p, 8, s->chroma_intra_matrix[j]); + } +#endif + + if(s->avctx->active_thread_type & FF_THREAD_SLICE){ + put_marker(p, DRI); + put_bits(p, 16, 4); + put_bits(p, 16, (s->width-1)/(8*s->mjpeg_hsample[0]) + 1); + } + + /* huffman table */ + put_marker(p, DHT); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + size = 2; + size += put_huffman_table(s, 0, 0, avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc); + size += put_huffman_table(s, 0, 1, avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc); + + size += put_huffman_table(s, 1, 0, avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance); + size += put_huffman_table(s, 1, 1, avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance); + AV_WB16(ptr, size); +} + +static void jpeg_put_comments(MpegEncContext *s) +{ + PutBitContext *p = &s->pb; + int size; + uint8_t *ptr; + + if (s->avctx->sample_aspect_ratio.num /* && !lossless */) + { + /* JFIF header */ + put_marker(p, APP0); + put_bits(p, 16, 16); + avpriv_put_string(p, "JFIF", 1); /* this puts the trailing zero-byte too */ + put_bits(p, 16, 0x0102); /* v 1.02 */ + put_bits(p, 8, 0); /* units type: 0 - aspect ratio */ + put_bits(p, 16, s->avctx->sample_aspect_ratio.num); + put_bits(p, 16, s->avctx->sample_aspect_ratio.den); + put_bits(p, 8, 0); /* thumbnail width */ + put_bits(p, 8, 0); /* thumbnail height */ + } + + /* comment */ + if(!(s->flags & CODEC_FLAG_BITEXACT)){ + put_marker(p, COM); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + avpriv_put_string(p, LIBAVCODEC_IDENT, 1); + size = strlen(LIBAVCODEC_IDENT)+3; + AV_WB16(ptr, size); + } + + if( s->avctx->pix_fmt == AV_PIX_FMT_YUV420P + ||s->avctx->pix_fmt == AV_PIX_FMT_YUV422P + ||s->avctx->pix_fmt == AV_PIX_FMT_YUV444P){ + put_marker(p, COM); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + avpriv_put_string(p, "CS=ITU601", 1); + size = strlen("CS=ITU601")+3; + AV_WB16(ptr, size); + } +} + +void ff_mjpeg_encode_picture_header(MpegEncContext *s) +{ + const int lossless= s->avctx->codec_id != AV_CODEC_ID_MJPEG; + int i; + + put_marker(&s->pb, SOI); + + // hack for AMV mjpeg format + if(s->avctx->codec_id == AV_CODEC_ID_AMV) goto end; + + jpeg_put_comments(s); + + jpeg_table_header(s); + + switch(s->avctx->codec_id){ + case AV_CODEC_ID_MJPEG: put_marker(&s->pb, SOF0 ); break; + case AV_CODEC_ID_LJPEG: put_marker(&s->pb, SOF3 ); break; + default: av_assert0(0); + } + + put_bits(&s->pb, 16, 17); + if(lossless && (s->avctx->pix_fmt == AV_PIX_FMT_BGR0 + || s->avctx->pix_fmt == AV_PIX_FMT_BGRA + || s->avctx->pix_fmt == AV_PIX_FMT_BGR24)) + put_bits(&s->pb, 8, 9); /* 9 bits/component RCT */ + else + put_bits(&s->pb, 8, 8); /* 8 bits/component */ + put_bits(&s->pb, 16, s->height); + put_bits(&s->pb, 16, s->width); + put_bits(&s->pb, 8, 3); /* 3 components */ + + /* Y component */ + put_bits(&s->pb, 8, 1); /* component number */ + put_bits(&s->pb, 4, s->mjpeg_hsample[0]); /* H factor */ + put_bits(&s->pb, 4, s->mjpeg_vsample[0]); /* V factor */ + put_bits(&s->pb, 8, 0); /* select matrix */ + + /* Cb component */ + put_bits(&s->pb, 8, 2); /* component number */ + put_bits(&s->pb, 4, s->mjpeg_hsample[1]); /* H factor */ + put_bits(&s->pb, 4, s->mjpeg_vsample[1]); /* V factor */ +#ifdef TWOMATRIXES + put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */ +#else + put_bits(&s->pb, 8, 0); /* select matrix */ +#endif + + /* Cr component */ + put_bits(&s->pb, 8, 3); /* component number */ + put_bits(&s->pb, 4, s->mjpeg_hsample[2]); /* H factor */ + put_bits(&s->pb, 4, s->mjpeg_vsample[2]); /* V factor */ +#ifdef TWOMATRIXES + put_bits(&s->pb, 8, lossless ? 0 : 1); /* select matrix */ +#else + put_bits(&s->pb, 8, 0); /* select matrix */ +#endif + + /* scan header */ + put_marker(&s->pb, SOS); + put_bits(&s->pb, 16, 12); /* length */ + put_bits(&s->pb, 8, 3); /* 3 components */ + + /* Y component */ + put_bits(&s->pb, 8, 1); /* index */ + put_bits(&s->pb, 4, 0); /* DC huffman table index */ + put_bits(&s->pb, 4, 0); /* AC huffman table index */ + + /* Cb component */ + put_bits(&s->pb, 8, 2); /* index */ + put_bits(&s->pb, 4, 1); /* DC huffman table index */ + put_bits(&s->pb, 4, lossless ? 0 : 1); /* AC huffman table index */ + + /* Cr component */ + put_bits(&s->pb, 8, 3); /* index */ + put_bits(&s->pb, 4, 1); /* DC huffman table index */ + put_bits(&s->pb, 4, lossless ? 0 : 1); /* AC huffman table index */ + + put_bits(&s->pb, 8, lossless ? s->avctx->prediction_method+1 : 0); /* Ss (not used) */ + + switch(s->avctx->codec_id){ + case AV_CODEC_ID_MJPEG: put_bits(&s->pb, 8, 63); break; /* Se (not used) */ + case AV_CODEC_ID_LJPEG: put_bits(&s->pb, 8, 0); break; /* not used */ + default: av_assert0(0); + } + + put_bits(&s->pb, 8, 0); /* Ah/Al (not used) */ + +end: + s->esc_pos = put_bits_count(&s->pb) >> 3; + for(i=1; islice_context_count; i++) + s->thread_context[i]->esc_pos = 0; +} + +static void escape_FF(MpegEncContext *s, int start) +{ + int size= put_bits_count(&s->pb) - start*8; + int i, ff_count; + uint8_t *buf= s->pb.buf + start; + int align= (-(size_t)(buf))&3; + + av_assert1((size&7) == 0); + size >>= 3; + + ff_count=0; + for(i=0; i>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + v= *(uint32_t*)(&buf[i+4]); + acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + v= *(uint32_t*)(&buf[i+8]); + acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + v= *(uint32_t*)(&buf[i+12]); + acc+=(((v & (v>>4))&0x0F0F0F0F)+0x01010101)&0x10101010; + + acc>>=4; + acc+= (acc>>16); + acc+= (acc>>8); + ff_count+= acc&0xFF; + } + for(; ipb); + skip_put_bytes(&s->pb, ff_count); + + for(i=size-1; ff_count; i--){ + int v= buf[i]; + + if(v==0xFF){ + buf[i+ff_count]= 0; + ff_count--; + } + + buf[i+ff_count]= v; + } +} + +void ff_mjpeg_encode_stuffing(MpegEncContext *s) +{ + int length, i; + PutBitContext *pbc = &s->pb; + int mb_y = s->mb_y - !s->mb_x; + length= (-put_bits_count(pbc))&7; + if(length) put_bits(pbc, length, (1<pb); + escape_FF(s, s->esc_pos); + + if((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height) + put_marker(pbc, RST0 + (mb_y&7)); + s->esc_pos = put_bits_count(pbc) >> 3; + + for(i=0; i<3; i++) + s->last_dc[i] = 128 << s->intra_dc_precision; +} + +void ff_mjpeg_encode_picture_trailer(MpegEncContext *s) +{ + + av_assert1((s->header_bits&7)==0); + + + put_marker(&s->pb, EOI); +} + +void ff_mjpeg_encode_dc(MpegEncContext *s, int val, + uint8_t *huff_size, uint16_t *huff_code) +{ + int mant, nbits; + + if (val == 0) { + put_bits(&s->pb, huff_size[0], huff_code[0]); + } else { + mant = val; + if (val < 0) { + val = -val; + mant--; + } + + nbits= av_log2_16bit(val) + 1; + + put_bits(&s->pb, huff_size[nbits], huff_code[nbits]); + + put_sbits(&s->pb, nbits, mant); + } +} + +static void encode_block(MpegEncContext *s, int16_t *block, int n) +{ + int mant, nbits, code, i, j; + int component, dc, run, last_index, val; + MJpegContext *m = s->mjpeg_ctx; + uint8_t *huff_size_ac; + uint16_t *huff_code_ac; + + /* DC coef */ + component = (n <= 3 ? 0 : (n&1) + 1); + dc = block[0]; /* overflow is impossible */ + val = dc - s->last_dc[component]; + if (n < 4) { + ff_mjpeg_encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance); + huff_size_ac = m->huff_size_ac_luminance; + huff_code_ac = m->huff_code_ac_luminance; + } else { + ff_mjpeg_encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); + huff_size_ac = m->huff_size_ac_chrominance; + huff_code_ac = m->huff_code_ac_chrominance; + } + s->last_dc[component] = dc; + + /* AC coefs */ + + run = 0; + last_index = s->block_last_index[n]; + for(i=1;i<=last_index;i++) { + j = s->intra_scantable.permutated[i]; + val = block[j]; + if (val == 0) { + run++; + } else { + while (run >= 16) { + put_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]); + run -= 16; + } + mant = val; + if (val < 0) { + val = -val; + mant--; + } + + nbits= av_log2(val) + 1; + code = (run << 4) | nbits; + + put_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]); + + put_sbits(&s->pb, nbits, mant); + run = 0; + } + } + + /* output EOB only if not already 64 values */ + if (last_index < 63 || run != 0) + put_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); +} + +void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]) +{ + int i; + if (s->chroma_format == CHROMA_444) { + encode_block(s, block[0], 0); + encode_block(s, block[2], 2); + encode_block(s, block[4], 4); + encode_block(s, block[8], 8); + encode_block(s, block[5], 5); + encode_block(s, block[9], 9); + + if (16*s->mb_x+8 < s->width) { + encode_block(s, block[1], 1); + encode_block(s, block[3], 3); + encode_block(s, block[6], 6); + encode_block(s, block[10], 10); + encode_block(s, block[7], 7); + encode_block(s, block[11], 11); + } + } else { + for(i=0;i<5;i++) { + encode_block(s, block[i], i); + } + if (s->chroma_format == CHROMA_420) { + encode_block(s, block[5], 5); + } else { + encode_block(s, block[6], 6); + encode_block(s, block[5], 5); + encode_block(s, block[7], 7); + } + } + + s->i_tex_bits += get_bits_diff(s); +} + +// maximum over s->mjpeg_vsample[i] +#define V_MAX 2 +static int amv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic_arg, int *got_packet) + +{ + MpegEncContext *s = avctx->priv_data; + AVFrame pic = *pic_arg; + int i; + + //CODEC_FLAG_EMU_EDGE have to be cleared + if(s->avctx->flags & CODEC_FLAG_EMU_EDGE) + return -1; + + //picture should be flipped upside-down + for(i=0; i < 3; i++) { + pic.data[i] += (pic.linesize[i] * (s->mjpeg_vsample[i] * (8 * s->mb_height -((s->height/V_MAX)&7)) - 1 )); + pic.linesize[i] *= -1; + } + return ff_MPV_encode_picture(avctx, pkt, &pic, got_packet); +} + +#if CONFIG_MJPEG_ENCODER +AVCodec ff_mjpeg_encoder = { + .name = "mjpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .capabilities = CODEC_CAP_SLICE_THREADS | CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), +}; +#endif +#if CONFIG_AMV_ENCODER +AVCodec ff_amv_encoder = { + .name = "amv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AMV, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = amv_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), +}; +#endif diff --git a/ffmpeg/libavcodec/mjpegenc.h b/ffmpeg/libavcodec/mjpegenc.h new file mode 100644 index 0000000..ce0c1cc --- /dev/null +++ b/ffmpeg/libavcodec/mjpegenc.h @@ -0,0 +1,61 @@ +/* + * MJPEG encoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-2004 Michael Niedermayer + * + * Support for external huffman table, various fixes (AVID workaround), + * aspecting, new decode_frame mechanism and apple mjpeg-b support + * by Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * MJPEG encoder. + */ + +#ifndef AVCODEC_MJPEGENC_H +#define AVCODEC_MJPEGENC_H + +#include + +#include "mpegvideo.h" + +typedef struct MJpegContext { + uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chrom, for easier addressing + uint16_t huff_code_dc_luminance[12]; + uint8_t huff_size_dc_chrominance[12]; + uint16_t huff_code_dc_chrominance[12]; + + uint8_t huff_size_ac_luminance[256]; + uint16_t huff_code_ac_luminance[256]; + uint8_t huff_size_ac_chrominance[256]; + uint16_t huff_code_ac_chrominance[256]; +} MJpegContext; + +int ff_mjpeg_encode_init(MpegEncContext *s); +void ff_mjpeg_encode_close(MpegEncContext *s); +void ff_mjpeg_encode_picture_header(MpegEncContext *s); +void ff_mjpeg_encode_picture_trailer(MpegEncContext *s); +void ff_mjpeg_encode_stuffing(MpegEncContext *s); +void ff_mjpeg_encode_dc(MpegEncContext *s, int val, + uint8_t *huff_size, uint16_t *huff_code); +void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[6][64]); + +#endif /* AVCODEC_MJPEGENC_H */ diff --git a/ffmpeg/libavcodec/mlp.c b/ffmpeg/libavcodec/mlp.c new file mode 100644 index 0000000..87f7c77 --- /dev/null +++ b/ffmpeg/libavcodec/mlp.c @@ -0,0 +1,115 @@ +/* + * MLP codec common code + * Copyright (c) 2007-2008 Ian Caulfield + * + * 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 "libavutil/crc.h" +#include "libavutil/intreadwrite.h" +#include "mlp.h" + +const uint8_t ff_mlp_huffman_tables[3][18][2] = { + { /* Huffman table 0, -7 - +10 */ + {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, + {0x04, 3}, {0x05, 3}, {0x06, 3}, {0x07, 3}, + {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, + }, { /* Huffman table 1, -7 - +8 */ + {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, + {0x02, 2}, {0x03, 2}, + {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, + }, { /* Huffman table 2, -7 - +7 */ + {0x01, 9}, {0x01, 8}, {0x01, 7}, {0x01, 6}, {0x01, 5}, {0x01, 4}, {0x01, 3}, + {0x01, 1}, + {0x03, 3}, {0x05, 4}, {0x09, 5}, {0x11, 6}, {0x21, 7}, {0x41, 8}, {0x81, 9}, + } +}; + +static int crc_init = 0; +#if CONFIG_SMALL +#define CRC_TABLE_SIZE 257 +#else +#define CRC_TABLE_SIZE 1024 +#endif +static AVCRC crc_63[CRC_TABLE_SIZE]; +static AVCRC crc_1D[CRC_TABLE_SIZE]; +static AVCRC crc_2D[CRC_TABLE_SIZE]; + +av_cold void ff_mlp_init_crc(void) +{ + if (!crc_init) { + av_crc_init(crc_63, 0, 8, 0x63, sizeof(crc_63)); + av_crc_init(crc_1D, 0, 8, 0x1D, sizeof(crc_1D)); + av_crc_init(crc_2D, 0, 16, 0x002D, sizeof(crc_2D)); + crc_init = 1; + } +} + +uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size) +{ + uint16_t crc; + + crc = av_crc(crc_2D, 0, buf, buf_size - 2); + crc ^= AV_RL16(buf + buf_size - 2); + return crc; +} + +uint8_t ff_mlp_checksum8(const uint8_t *buf, unsigned int buf_size) +{ + uint8_t checksum = av_crc(crc_63, 0x3c, buf, buf_size - 1); // crc_63[0xa2] == 0x3c + checksum ^= buf[buf_size-1]; + return checksum; +} + +uint8_t ff_mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size) +{ + int i; + int num_bytes = (bit_size + 2) / 8; + + int crc = crc_1D[buf[0] & 0x3f]; + crc = av_crc(crc_1D, crc, buf + 1, num_bytes - 2); + crc ^= buf[num_bytes - 1]; + + for (i = 0; i < ((bit_size + 2) & 7); i++) { + crc <<= 1; + if (crc & 0x100) + crc ^= 0x11D; + crc ^= (buf[num_bytes] >> (7 - i)) & 1; + } + + return crc; +} + +uint8_t ff_mlp_calculate_parity(const uint8_t *buf, unsigned int buf_size) +{ + uint32_t scratch = 0; + const uint8_t *buf_end = buf + buf_size; + + for (; ((intptr_t) buf & 3) && buf < buf_end; buf++) + scratch ^= *buf; + for (; buf < buf_end - 3; buf += 4) + scratch ^= *((const uint32_t*)buf); + + scratch = xor_32_to_8(scratch); + + for (; buf < buf_end; buf++) + scratch ^= *buf; + + return scratch; +} diff --git a/ffmpeg/libavcodec/mlp.h b/ffmpeg/libavcodec/mlp.h new file mode 100644 index 0000000..d8d1292 --- /dev/null +++ b/ffmpeg/libavcodec/mlp.h @@ -0,0 +1,127 @@ +/* + * MLP codec common header file + * Copyright (c) 2007-2008 Ian Caulfield + * + * 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 + */ + +#ifndef AVCODEC_MLP_H +#define AVCODEC_MLP_H + +#include + +#include "avcodec.h" + +/** Last possible matrix channel for each codec */ +#define MAX_MATRIX_CHANNEL_MLP 5 +#define MAX_MATRIX_CHANNEL_TRUEHD 7 +/** Maximum number of channels in a valid stream. + * MLP : 5.1 + 2 noise channels -> 8 channels + * TrueHD: 7.1 -> 8 channels + */ +#define MAX_CHANNELS 8 + +/** Maximum number of matrices used in decoding; most streams have one matrix + * per output channel, but some rematrix a channel (usually 0) more than once. + */ +#define MAX_MATRICES_MLP 6 +#define MAX_MATRICES_TRUEHD 8 +#define MAX_MATRICES 8 + +/** Maximum number of substreams that can be decoded. + * MLP's limit is 2. TrueHD supports at least up to 3. + */ +#define MAX_SUBSTREAMS 3 + +/** which multiple of 48000 the maximum sample rate is */ +#define MAX_RATEFACTOR 4 +/** maximum sample frequency seen in files */ +#define MAX_SAMPLERATE (MAX_RATEFACTOR * 48000) + +/** maximum number of audio samples within one access unit */ +#define MAX_BLOCKSIZE (40 * MAX_RATEFACTOR) +/** next power of two greater than MAX_BLOCKSIZE */ +#define MAX_BLOCKSIZE_POW2 (64 * MAX_RATEFACTOR) + +/** number of allowed filters */ +#define NUM_FILTERS 2 + +/** The maximum number of taps in IIR and FIR filters. */ +#define MAX_FIR_ORDER 8 +#define MAX_IIR_ORDER 4 + +/** Code that signals end of a stream. */ +#define END_OF_STREAM 0xd234d234 + +#define FIR 0 +#define IIR 1 + +/** filter data */ +typedef struct FilterParams { + uint8_t order; ///< number of taps in filter + uint8_t shift; ///< Right shift to apply to output of filter. + + int32_t state[MAX_FIR_ORDER]; +} FilterParams; + +/** sample data coding information */ +typedef struct ChannelParams { + FilterParams filter_params[NUM_FILTERS]; + int32_t coeff[NUM_FILTERS][MAX_FIR_ORDER]; + + int16_t huff_offset; ///< Offset to apply to residual values. + int32_t sign_huff_offset; ///< sign/rounding-corrected version of huff_offset + uint8_t codebook; ///< Which VLC codebook to use to read residuals. + uint8_t huff_lsbs; ///< Size of residual suffix not encoded using VLC. +} ChannelParams; + +/** Tables defining the Huffman codes. + * There are three entropy coding methods used in MLP (four if you count + * "none" as a method). These use the same sequences for codes starting with + * 00 or 01, but have different codes starting with 1. + */ +extern const uint8_t ff_mlp_huffman_tables[3][18][2]; + +/** MLP uses checksums that seem to be based on the standard CRC algorithm, but + * are not (in implementation terms, the table lookup and XOR are reversed). + * We can implement this behavior using a standard av_crc on all but the + * last element, then XOR that with the last element. + */ +uint8_t ff_mlp_checksum8 (const uint8_t *buf, unsigned int buf_size); +uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size); + +/** Calculate an 8-bit checksum over a restart header -- a non-multiple-of-8 + * number of bits, starting two bits into the first byte of buf. + */ +uint8_t ff_mlp_restart_checksum(const uint8_t *buf, unsigned int bit_size); + +/** XOR together all the bytes of a buffer. + * Does this belong in dspcontext? + */ +uint8_t ff_mlp_calculate_parity(const uint8_t *buf, unsigned int buf_size); + +void ff_mlp_init_crc(void); + +/** XOR four bytes into one. */ +static inline uint8_t xor_32_to_8(uint32_t value) +{ + value ^= value >> 16; + value ^= value >> 8; + return value; +} + +#endif /* AVCODEC_MLP_H */ diff --git a/ffmpeg/libavcodec/mlp_parser.c b/ffmpeg/libavcodec/mlp_parser.c new file mode 100644 index 0000000..2cc4b91 --- /dev/null +++ b/ffmpeg/libavcodec/mlp_parser.c @@ -0,0 +1,398 @@ +/* + * MLP parser + * Copyright (c) 2007 Ian Caulfield + * + * 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 + */ + +/** + * @file + * MLP parser + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/crc.h" +#include "get_bits.h" +#include "parser.h" +#include "mlp_parser.h" +#include "mlp.h" + +static const uint8_t mlp_quants[16] = { + 16, 20, 24, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint8_t mlp_channels[32] = { + 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4, + 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const uint64_t ff_mlp_layout[32] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_2_1|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint8_t thd_chancount[13] = { +// LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 + 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1 +}; + +static const uint64_t thd_layout[13] = { + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, // LR + AV_CH_FRONT_CENTER, // C + AV_CH_LOW_FREQUENCY, // LFE + AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRs + AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT, // LRvh + AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRc + AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, // LRrs + AV_CH_BACK_CENTER, // Cs + AV_CH_TOP_CENTER, // Ts + AV_CH_SURROUND_DIRECT_LEFT|AV_CH_SURROUND_DIRECT_RIGHT, // LRsd + AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT, // LRw + AV_CH_TOP_FRONT_CENTER, // Cvh + AV_CH_LOW_FREQUENCY_2, // LFE2 +}; + +static int mlp_samplerate(int in) +{ + if (in == 0xF) + return 0; + + return (in & 8 ? 44100 : 48000) << (in & 7) ; +} + +static int truehd_channels(int chanmap) +{ + int channels = 0, i; + + for (i = 0; i < 13; i++) + channels += thd_chancount[i] * ((chanmap >> i) & 1); + + return channels; +} + +uint64_t ff_truehd_layout(int chanmap) +{ + int i; + uint64_t layout = 0; + + for (i = 0; i < 13; i++) + layout |= thd_layout[i] * ((chanmap >> i) & 1); + + return layout; +} + +/** Read a major sync info header - contains high level information about + * the stream - sample rate, channel arrangement etc. Most of this + * information is not actually necessary for decoding, only for playback. + * gb must be a freshly initialized GetBitContext with no bits read. + */ + +int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) +{ + int ratebits, channel_arrangement; + uint16_t checksum; + + av_assert1(get_bits_count(gb) == 0); + + if (gb->size_in_bits < 28 << 3) { + av_log(log, AV_LOG_ERROR, "packet too short, unable to read major sync\n"); + return -1; + } + + checksum = ff_mlp_checksum16(gb->buffer, 26); + if (checksum != AV_RL16(gb->buffer+26)) { + av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n"); + return AVERROR_INVALIDDATA; + } + + if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */ + return AVERROR_INVALIDDATA; + + mh->stream_type = get_bits(gb, 8); + + if (mh->stream_type == 0xbb) { + mh->group1_bits = mlp_quants[get_bits(gb, 4)]; + mh->group2_bits = mlp_quants[get_bits(gb, 4)]; + + ratebits = get_bits(gb, 4); + mh->group1_samplerate = mlp_samplerate(ratebits); + mh->group2_samplerate = mlp_samplerate(get_bits(gb, 4)); + + skip_bits(gb, 11); + + mh->channel_arrangement= + channel_arrangement = get_bits(gb, 5); + mh->channels_mlp = mlp_channels[channel_arrangement]; + mh->channel_layout_mlp = ff_mlp_layout[channel_arrangement]; + } else if (mh->stream_type == 0xba) { + mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere? + mh->group2_bits = 0; + + ratebits = get_bits(gb, 4); + mh->group1_samplerate = mlp_samplerate(ratebits); + mh->group2_samplerate = 0; + + skip_bits(gb, 8); + + mh->channel_arrangement= + channel_arrangement = get_bits(gb, 5); + mh->channels_thd_stream1 = truehd_channels(channel_arrangement); + mh->channel_layout_thd_stream1 = ff_truehd_layout(channel_arrangement); + + skip_bits(gb, 2); + + channel_arrangement = get_bits(gb, 13); + mh->channels_thd_stream2 = truehd_channels(channel_arrangement); + mh->channel_layout_thd_stream2 = ff_truehd_layout(channel_arrangement); + } else + return AVERROR_INVALIDDATA; + + mh->access_unit_size = 40 << (ratebits & 7); + mh->access_unit_size_pow2 = 64 << (ratebits & 7); + + skip_bits_long(gb, 48); + + mh->is_vbr = get_bits1(gb); + + mh->peak_bitrate = (get_bits(gb, 15) * mh->group1_samplerate + 8) >> 4; + + mh->num_substreams = get_bits(gb, 4); + + skip_bits_long(gb, 4 + 11 * 8); + + return 0; +} + +typedef struct MLPParseContext +{ + ParseContext pc; + + int bytes_left; + + int in_sync; + + int num_substreams; +} MLPParseContext; + +static av_cold int mlp_init(AVCodecParserContext *s) +{ + ff_mlp_init_crc(); + return 0; +} + +static int mlp_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + MLPParseContext *mp = s->priv_data; + int sync_present; + uint8_t parity_bits; + int next; + int i, p = 0; + + *poutbuf_size = 0; + if (buf_size == 0) + return 0; + + if (!mp->in_sync) { + // Not in sync - find a major sync header + + for (i = 0; i < buf_size; i++) { + mp->pc.state = (mp->pc.state << 8) | buf[i]; + if ((mp->pc.state & 0xfffffffe) == 0xf8726fba && + // ignore if we do not have the data for the start of header + mp->pc.index + i >= 7) { + mp->in_sync = 1; + mp->bytes_left = 0; + break; + } + } + + if (!mp->in_sync) { + if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) + av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); + return buf_size; + } + + ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size); + + return i - 7; + } + + if (mp->bytes_left == 0) { + // Find length of this packet + + /* Copy overread bytes from last frame into buffer. */ + for(; mp->pc.overread>0; mp->pc.overread--) { + mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++]; + } + + if (mp->pc.index + buf_size < 2) { + if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) + av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); + return buf_size; + } + + mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8) + | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]); + mp->bytes_left = (mp->bytes_left & 0xfff) * 2; + if (mp->bytes_left <= 0) { // prevent infinite loop + goto lost_sync; + } + mp->bytes_left -= mp->pc.index; + } + + next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left; + + if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) { + mp->bytes_left -= buf_size; + return buf_size; + } + + mp->bytes_left = 0; + + sync_present = (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba; + + if (!sync_present) { + /* The first nibble of a frame is a parity check of the 4-byte + * access unit header and all the 2- or 4-byte substream headers. */ + // Only check when this isn't a sync frame - syncs have a checksum. + + parity_bits = 0; + for (i = -1; i < mp->num_substreams; i++) { + parity_bits ^= buf[p++]; + parity_bits ^= buf[p++]; + + if (i < 0 || buf[p-2] & 0x80) { + parity_bits ^= buf[p++]; + parity_bits ^= buf[p++]; + } + } + + if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) { + av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n"); + goto lost_sync; + } + } else { + GetBitContext gb; + MLPHeaderInfo mh; + + init_get_bits(&gb, buf + 4, (buf_size - 4) << 3); + if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0) + goto lost_sync; + + avctx->bits_per_raw_sample = mh.group1_bits; + if (avctx->bits_per_raw_sample > 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + else + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + avctx->sample_rate = mh.group1_samplerate; + s->duration = mh.access_unit_size; + + if(!avctx->channels || !avctx->channel_layout) { + if (mh.stream_type == 0xbb) { + /* MLP stream */ +#if FF_API_REQUEST_CHANNELS + if (avctx->request_channels > 0 && avctx->request_channels <= 2 && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else +#endif + if (avctx->request_channel_layout == AV_CH_LAYOUT_STEREO && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else { + avctx->channels = mh.channels_mlp; + avctx->channel_layout = mh.channel_layout_mlp; + } + } else { /* mh.stream_type == 0xba */ + /* TrueHD stream */ +#if FF_API_REQUEST_CHANNELS + if (avctx->request_channels > 0 && avctx->request_channels <= 2 && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else if (avctx->request_channels > 0 && + avctx->request_channels <= mh.channels_thd_stream1) { + avctx->channels = mh.channels_thd_stream1; + avctx->channel_layout = mh.channel_layout_thd_stream1; + } else +#endif + if (avctx->request_channel_layout == AV_CH_LAYOUT_STEREO && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else if (avctx->request_channel_layout == mh.channel_layout_thd_stream1 || + !mh.channels_thd_stream2) { + avctx->channels = mh.channels_thd_stream1; + avctx->channel_layout = mh.channel_layout_thd_stream1; + } else { + avctx->channels = mh.channels_thd_stream2; + avctx->channel_layout = mh.channel_layout_thd_stream2; + } + } + } + + if (!mh.is_vbr) /* Stream is CBR */ + avctx->bit_rate = mh.peak_bitrate; + + mp->num_substreams = mh.num_substreams; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; + +lost_sync: + mp->in_sync = 0; + return 1; +} + +AVCodecParser ff_mlp_parser = { + .codec_ids = { AV_CODEC_ID_MLP, AV_CODEC_ID_TRUEHD }, + .priv_data_size = sizeof(MLPParseContext), + .parser_init = mlp_init, + .parser_parse = mlp_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/mlp_parser.h b/ffmpeg/libavcodec/mlp_parser.h new file mode 100644 index 0000000..9967abb --- /dev/null +++ b/ffmpeg/libavcodec/mlp_parser.h @@ -0,0 +1,65 @@ +/* + * MLP parser prototypes + * Copyright (c) 2007 Ian Caulfield + * + * 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 + */ + +/** + * @file + * MLP parser prototypes + */ + +#ifndef AVCODEC_MLP_PARSER_H +#define AVCODEC_MLP_PARSER_H + +#include "get_bits.h" + +typedef struct MLPHeaderInfo +{ + int stream_type; ///< 0xBB for MLP, 0xBA for TrueHD + + int group1_bits; ///< The bit depth of the first substream + int group2_bits; ///< Bit depth of the second substream (MLP only) + + int group1_samplerate; ///< Sample rate of first substream + int group2_samplerate; ///< Sample rate of second substream (MLP only) + + int channel_arrangement; + int channels_mlp; ///< Channel count for MLP streams + int channels_thd_stream1; ///< Channel count for substream 1 of TrueHD streams ("6-channel presentation") + int channels_thd_stream2; ///< Channel count for substream 2 of TrueHD streams ("8-channel presentation") + uint64_t channel_layout_mlp; ///< Channel layout for MLP streams + uint64_t channel_layout_thd_stream1; ///< Channel layout for substream 1 of TrueHD streams ("6-channel presentation") + uint64_t channel_layout_thd_stream2; ///< Channel layout for substream 2 of TrueHD streams ("8-channel presentation") + + int access_unit_size; ///< Number of samples per coded frame + int access_unit_size_pow2; ///< Next power of two above number of samples per frame + + int is_vbr; ///< Stream is VBR instead of CBR + int peak_bitrate; ///< Peak bitrate for VBR, actual bitrate (==peak) for CBR + + int num_substreams; ///< Number of substreams within stream +} MLPHeaderInfo; + + +int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb); +uint64_t ff_truehd_layout(int chanmap); + +extern const uint64_t ff_mlp_layout[32]; + +#endif /* AVCODEC_MLP_PARSER_H */ diff --git a/ffmpeg/libavcodec/mlpdec.c b/ffmpeg/libavcodec/mlpdec.c new file mode 100644 index 0000000..a7c79a4 --- /dev/null +++ b/ffmpeg/libavcodec/mlpdec.c @@ -0,0 +1,1272 @@ +/* + * MLP decoder + * Copyright (c) 2007-2008 Ian Caulfield + * + * 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 + */ + +/** + * @file + * MLP decoder + */ + +#include + +#include "avcodec.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/channel_layout.h" +#include "get_bits.h" +#include "internal.h" +#include "libavutil/crc.h" +#include "parser.h" +#include "mlp_parser.h" +#include "mlpdsp.h" +#include "mlp.h" + +/** number of bits used for VLC lookup - longest Huffman code is 9 */ +#define VLC_BITS 9 + +typedef struct SubStream { + /// Set if a valid restart header has been read. Otherwise the substream cannot be decoded. + uint8_t restart_seen; + + //@{ + /** restart header data */ + /// The type of noise to be used in the rematrix stage. + uint16_t noise_type; + + /// The index of the first channel coded in this substream. + uint8_t min_channel; + /// The index of the last channel coded in this substream. + uint8_t max_channel; + /// The number of channels input into the rematrix stage. + uint8_t max_matrix_channel; + /// For each channel output by the matrix, the output channel to map it to + uint8_t ch_assign[MAX_CHANNELS]; + /// The channel layout for this substream + uint64_t ch_layout; + + /// Channel coding parameters for channels in the substream + ChannelParams channel_params[MAX_CHANNELS]; + + /// The left shift applied to random noise in 0x31ea substreams. + uint8_t noise_shift; + /// The current seed value for the pseudorandom noise generator(s). + uint32_t noisegen_seed; + + /// Set if the substream contains extra info to check the size of VLC blocks. + uint8_t data_check_present; + + /// Bitmask of which parameter sets are conveyed in a decoding parameter block. + uint8_t param_presence_flags; +#define PARAM_BLOCKSIZE (1 << 7) +#define PARAM_MATRIX (1 << 6) +#define PARAM_OUTSHIFT (1 << 5) +#define PARAM_QUANTSTEP (1 << 4) +#define PARAM_FIR (1 << 3) +#define PARAM_IIR (1 << 2) +#define PARAM_HUFFOFFSET (1 << 1) +#define PARAM_PRESENCE (1 << 0) + //@} + + //@{ + /** matrix data */ + + /// Number of matrices to be applied. + uint8_t num_primitive_matrices; + + /// matrix output channel + uint8_t matrix_out_ch[MAX_MATRICES]; + + /// Whether the LSBs of the matrix output are encoded in the bitstream. + uint8_t lsb_bypass[MAX_MATRICES]; + /// Matrix coefficients, stored as 2.14 fixed point. + int32_t matrix_coeff[MAX_MATRICES][MAX_CHANNELS]; + /// Left shift to apply to noise values in 0x31eb substreams. + uint8_t matrix_noise_shift[MAX_MATRICES]; + //@} + + /// Left shift to apply to Huffman-decoded residuals. + uint8_t quant_step_size[MAX_CHANNELS]; + + /// number of PCM samples in current audio block + uint16_t blocksize; + /// Number of PCM samples decoded so far in this frame. + uint16_t blockpos; + + /// Left shift to apply to decoded PCM values to get final 24-bit output. + int8_t output_shift[MAX_CHANNELS]; + + /// Running XOR of all output samples. + int32_t lossless_check_data; + +} SubStream; + +typedef struct MLPDecodeContext { + AVCodecContext *avctx; + + /// Current access unit being read has a major sync. + int is_major_sync_unit; + + /// Set if a valid major sync block has been read. Otherwise no decoding is possible. + uint8_t params_valid; + + /// Number of substreams contained within this stream. + uint8_t num_substreams; + + /// Index of the last substream to decode - further substreams are skipped. + uint8_t max_decoded_substream; + + /// Stream needs channel reordering to comply with FFmpeg's channel order + uint8_t needs_reordering; + + /// number of PCM samples contained in each frame + int access_unit_size; + /// next power of two above the number of samples in each frame + int access_unit_size_pow2; + + SubStream substream[MAX_SUBSTREAMS]; + + int matrix_changed; + int filter_changed[MAX_CHANNELS][NUM_FILTERS]; + + int8_t noise_buffer[MAX_BLOCKSIZE_POW2]; + int8_t bypassed_lsbs[MAX_BLOCKSIZE][MAX_CHANNELS]; + int32_t sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS]; + + MLPDSPContext dsp; +} MLPDecodeContext; + +static const uint64_t thd_channel_order[] = { + AV_CH_FRONT_LEFT, AV_CH_FRONT_RIGHT, // LR + AV_CH_FRONT_CENTER, // C + AV_CH_LOW_FREQUENCY, // LFE + AV_CH_SIDE_LEFT, AV_CH_SIDE_RIGHT, // LRs + AV_CH_TOP_FRONT_LEFT, AV_CH_TOP_FRONT_RIGHT, // LRvh + AV_CH_FRONT_LEFT_OF_CENTER, AV_CH_FRONT_RIGHT_OF_CENTER, // LRc + AV_CH_BACK_LEFT, AV_CH_BACK_RIGHT, // LRrs + AV_CH_BACK_CENTER, // Cs + AV_CH_TOP_CENTER, // Ts + AV_CH_SURROUND_DIRECT_LEFT, AV_CH_SURROUND_DIRECT_RIGHT, // LRsd + AV_CH_WIDE_LEFT, AV_CH_WIDE_RIGHT, // LRw + AV_CH_TOP_FRONT_CENTER, // Cvh + AV_CH_LOW_FREQUENCY_2, // LFE2 +}; + +static uint64_t thd_channel_layout_extract_channel(uint64_t channel_layout, + int index) +{ + int i; + + if (av_get_channel_layout_nb_channels(channel_layout) <= index) + return 0; + + for (i = 0; i < FF_ARRAY_ELEMS(thd_channel_order); i++) + if (channel_layout & thd_channel_order[i] && !index--) + return thd_channel_order[i]; + return 0; +} + +static VLC huff_vlc[3]; + +/** Initialize static data, constant between all invocations of the codec. */ + +static av_cold void init_static(void) +{ + if (!huff_vlc[0].bits) { + INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18, + &ff_mlp_huffman_tables[0][0][1], 2, 1, + &ff_mlp_huffman_tables[0][0][0], 2, 1, 512); + INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16, + &ff_mlp_huffman_tables[1][0][1], 2, 1, + &ff_mlp_huffman_tables[1][0][0], 2, 1, 512); + INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15, + &ff_mlp_huffman_tables[2][0][1], 2, 1, + &ff_mlp_huffman_tables[2][0][0], 2, 1, 512); + } + + ff_mlp_init_crc(); +} + +static inline int32_t calculate_sign_huff(MLPDecodeContext *m, + unsigned int substr, unsigned int ch) +{ + SubStream *s = &m->substream[substr]; + ChannelParams *cp = &s->channel_params[ch]; + int lsb_bits = cp->huff_lsbs - s->quant_step_size[ch]; + int sign_shift = lsb_bits + (cp->codebook ? 2 - cp->codebook : -1); + int32_t sign_huff_offset = cp->huff_offset; + + if (cp->codebook > 0) + sign_huff_offset -= 7 << lsb_bits; + + if (sign_shift >= 0) + sign_huff_offset -= 1 << sign_shift; + + return sign_huff_offset; +} + +/** Read a sample, consisting of either, both or neither of entropy-coded MSBs + * and plain LSBs. */ + +static inline int read_huff_channels(MLPDecodeContext *m, GetBitContext *gbp, + unsigned int substr, unsigned int pos) +{ + SubStream *s = &m->substream[substr]; + unsigned int mat, channel; + + for (mat = 0; mat < s->num_primitive_matrices; mat++) + if (s->lsb_bypass[mat]) + m->bypassed_lsbs[pos + s->blockpos][mat] = get_bits1(gbp); + + for (channel = s->min_channel; channel <= s->max_channel; channel++) { + ChannelParams *cp = &s->channel_params[channel]; + int codebook = cp->codebook; + int quant_step_size = s->quant_step_size[channel]; + int lsb_bits = cp->huff_lsbs - quant_step_size; + int result = 0; + + if (codebook > 0) + result = get_vlc2(gbp, huff_vlc[codebook-1].table, + VLC_BITS, (9 + VLC_BITS - 1) / VLC_BITS); + + if (result < 0) + return AVERROR_INVALIDDATA; + + if (lsb_bits > 0) + result = (result << lsb_bits) + get_bits(gbp, lsb_bits); + + result += cp->sign_huff_offset; + result <<= quant_step_size; + + m->sample_buffer[pos + s->blockpos][channel] = result; + } + + return 0; +} + +static av_cold int mlp_decode_init(AVCodecContext *avctx) +{ + MLPDecodeContext *m = avctx->priv_data; + int substr; + + init_static(); + m->avctx = avctx; + for (substr = 0; substr < MAX_SUBSTREAMS; substr++) + m->substream[substr].lossless_check_data = 0xffffffff; + ff_mlpdsp_init(&m->dsp); + + return 0; +} + +/** Read a major sync info header - contains high level information about + * the stream - sample rate, channel arrangement etc. Most of this + * information is not actually necessary for decoding, only for playback. + */ + +static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) +{ + MLPHeaderInfo mh; + int substr, ret; + + if ((ret = ff_mlp_read_major_sync(m->avctx, &mh, gb)) != 0) + return ret; + + if (mh.group1_bits == 0) { + av_log(m->avctx, AV_LOG_ERROR, "invalid/unknown bits per sample\n"); + return AVERROR_INVALIDDATA; + } + if (mh.group2_bits > mh.group1_bits) { + av_log(m->avctx, AV_LOG_ERROR, + "Channel group 2 cannot have more bits per sample than group 1.\n"); + return AVERROR_INVALIDDATA; + } + + if (mh.group2_samplerate && mh.group2_samplerate != mh.group1_samplerate) { + av_log(m->avctx, AV_LOG_ERROR, + "Channel groups with differing sample rates are not currently supported.\n"); + return AVERROR_INVALIDDATA; + } + + if (mh.group1_samplerate == 0) { + av_log(m->avctx, AV_LOG_ERROR, "invalid/unknown sampling rate\n"); + return AVERROR_INVALIDDATA; + } + if (mh.group1_samplerate > MAX_SAMPLERATE) { + av_log(m->avctx, AV_LOG_ERROR, + "Sampling rate %d is greater than the supported maximum (%d).\n", + mh.group1_samplerate, MAX_SAMPLERATE); + return AVERROR_INVALIDDATA; + } + if (mh.access_unit_size > MAX_BLOCKSIZE) { + av_log(m->avctx, AV_LOG_ERROR, + "Block size %d is greater than the supported maximum (%d).\n", + mh.access_unit_size, MAX_BLOCKSIZE); + return AVERROR_INVALIDDATA; + } + if (mh.access_unit_size_pow2 > MAX_BLOCKSIZE_POW2) { + av_log(m->avctx, AV_LOG_ERROR, + "Block size pow2 %d is greater than the supported maximum (%d).\n", + mh.access_unit_size_pow2, MAX_BLOCKSIZE_POW2); + return AVERROR_INVALIDDATA; + } + + if (mh.num_substreams == 0) + return AVERROR_INVALIDDATA; + if (m->avctx->codec_id == AV_CODEC_ID_MLP && mh.num_substreams > 2) { + av_log(m->avctx, AV_LOG_ERROR, "MLP only supports up to 2 substreams.\n"); + return AVERROR_INVALIDDATA; + } + if (mh.num_substreams > MAX_SUBSTREAMS) { + avpriv_request_sample(m->avctx, + "%d substreams (more than the " + "maximum supported by the decoder)", + mh.num_substreams); + return AVERROR_PATCHWELCOME; + } + + m->access_unit_size = mh.access_unit_size; + m->access_unit_size_pow2 = mh.access_unit_size_pow2; + + m->num_substreams = mh.num_substreams; + m->max_decoded_substream = m->num_substreams - 1; + + m->avctx->sample_rate = mh.group1_samplerate; + m->avctx->frame_size = mh.access_unit_size; + + m->avctx->bits_per_raw_sample = mh.group1_bits; + if (mh.group1_bits > 16) + m->avctx->sample_fmt = AV_SAMPLE_FMT_S32; + else + m->avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + m->params_valid = 1; + for (substr = 0; substr < MAX_SUBSTREAMS; substr++) + m->substream[substr].restart_seen = 0; + + /* Set the layout for each substream. When there's more than one, the first + * substream is Stereo. Subsequent substreams' layouts are indicated in the + * major sync. */ + if (m->avctx->codec_id == AV_CODEC_ID_MLP) { + if ((substr = (mh.num_substreams > 1))) + m->substream[0].ch_layout = AV_CH_LAYOUT_STEREO; + m->substream[substr].ch_layout = mh.channel_layout_mlp; + } else { + if ((substr = (mh.num_substreams > 1))) + m->substream[0].ch_layout = AV_CH_LAYOUT_STEREO; + if (mh.num_substreams > 2) + if (mh.channel_layout_thd_stream2) + m->substream[2].ch_layout = mh.channel_layout_thd_stream2; + else + m->substream[2].ch_layout = mh.channel_layout_thd_stream1; + m->substream[substr].ch_layout = mh.channel_layout_thd_stream1; + + if (m->avctx->channels<=2 && m->substream[substr].ch_layout == AV_CH_LAYOUT_MONO && m->max_decoded_substream == 1) { + av_log(m->avctx, AV_LOG_DEBUG, "Mono stream with 2 substreams, ignoring 2nd\n"); + m->max_decoded_substream = 0; + if (m->avctx->channels==2) + m->avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } + } + + m->needs_reordering = mh.channel_arrangement >= 18 && mh.channel_arrangement <= 20; + + return 0; +} + +/** Read a restart header from a block in a substream. This contains parameters + * required to decode the audio that do not change very often. Generally + * (always) present only in blocks following a major sync. */ + +static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, + const uint8_t *buf, unsigned int substr) +{ + SubStream *s = &m->substream[substr]; + unsigned int ch; + int sync_word, tmp; + uint8_t checksum; + uint8_t lossless_check; + int start_count = get_bits_count(gbp); + const int max_matrix_channel = m->avctx->codec_id == AV_CODEC_ID_MLP + ? MAX_MATRIX_CHANNEL_MLP + : MAX_MATRIX_CHANNEL_TRUEHD; + int max_channel, min_channel, matrix_channel; + + sync_word = get_bits(gbp, 13); + + if (sync_word != 0x31ea >> 1) { + av_log(m->avctx, AV_LOG_ERROR, + "restart header sync incorrect (got 0x%04x)\n", sync_word); + return AVERROR_INVALIDDATA; + } + + s->noise_type = get_bits1(gbp); + + if (m->avctx->codec_id == AV_CODEC_ID_MLP && s->noise_type) { + av_log(m->avctx, AV_LOG_ERROR, "MLP must have 0x31ea sync word.\n"); + return AVERROR_INVALIDDATA; + } + + skip_bits(gbp, 16); /* Output timestamp */ + + min_channel = get_bits(gbp, 4); + max_channel = get_bits(gbp, 4); + matrix_channel = get_bits(gbp, 4); + + if (matrix_channel > max_matrix_channel) { + av_log(m->avctx, AV_LOG_ERROR, + "Max matrix channel cannot be greater than %d.\n", + max_matrix_channel); + return AVERROR_INVALIDDATA; + } + + if (max_channel != matrix_channel) { + av_log(m->avctx, AV_LOG_ERROR, + "Max channel must be equal max matrix channel.\n"); + return AVERROR_INVALIDDATA; + } + + /* This should happen for TrueHD streams with >6 channels and MLP's noise + * type. It is not yet known if this is allowed. */ + if (max_channel > MAX_MATRIX_CHANNEL_MLP && !s->noise_type) { + avpriv_request_sample(m->avctx, + "%d channels (more than the " + "maximum supported by the decoder)", + max_channel + 2); + return AVERROR_PATCHWELCOME; + } + + if (min_channel > max_channel) { + av_log(m->avctx, AV_LOG_ERROR, + "Substream min channel cannot be greater than max channel.\n"); + return AVERROR_INVALIDDATA; + } + + s->min_channel = min_channel; + s->max_channel = max_channel; + s->max_matrix_channel = matrix_channel; + +#if FF_API_REQUEST_CHANNELS + if (m->avctx->request_channels > 0 && + m->avctx->request_channels <= s->max_channel + 1 && + m->max_decoded_substream > substr) { + av_log(m->avctx, AV_LOG_DEBUG, + "Extracting %d-channel downmix from substream %d. " + "Further substreams will be skipped.\n", + s->max_channel + 1, substr); + m->max_decoded_substream = substr; + } else +#endif + if (m->avctx->request_channel_layout == s->ch_layout && + m->max_decoded_substream > substr) { + av_log(m->avctx, AV_LOG_DEBUG, + "Extracting %d-channel downmix (0x%"PRIx64") from substream %d. " + "Further substreams will be skipped.\n", + s->max_channel + 1, s->ch_layout, substr); + m->max_decoded_substream = substr; + } + + s->noise_shift = get_bits(gbp, 4); + s->noisegen_seed = get_bits(gbp, 23); + + skip_bits(gbp, 19); + + s->data_check_present = get_bits1(gbp); + lossless_check = get_bits(gbp, 8); + if (substr == m->max_decoded_substream + && s->lossless_check_data != 0xffffffff) { + tmp = xor_32_to_8(s->lossless_check_data); + if (tmp != lossless_check) + av_log(m->avctx, AV_LOG_WARNING, + "Lossless check failed - expected %02x, calculated %02x.\n", + lossless_check, tmp); + } + + skip_bits(gbp, 16); + + memset(s->ch_assign, 0, sizeof(s->ch_assign)); + + for (ch = 0; ch <= s->max_matrix_channel; ch++) { + int ch_assign = get_bits(gbp, 6); + if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD) { + uint64_t channel = thd_channel_layout_extract_channel(s->ch_layout, + ch_assign); + ch_assign = av_get_channel_layout_channel_index(s->ch_layout, + channel); + } + if ((unsigned)ch_assign > s->max_matrix_channel) { + avpriv_request_sample(m->avctx, + "Assignment of matrix channel %d to invalid output channel %d", + ch, ch_assign); + return AVERROR_PATCHWELCOME; + } + s->ch_assign[ch_assign] = ch; + } + + checksum = ff_mlp_restart_checksum(buf, get_bits_count(gbp) - start_count); + + if (checksum != get_bits(gbp, 8)) + av_log(m->avctx, AV_LOG_ERROR, "restart header checksum error\n"); + + /* Set default decoding parameters. */ + s->param_presence_flags = 0xff; + s->num_primitive_matrices = 0; + s->blocksize = 8; + s->lossless_check_data = 0; + + memset(s->output_shift , 0, sizeof(s->output_shift )); + memset(s->quant_step_size, 0, sizeof(s->quant_step_size)); + + for (ch = s->min_channel; ch <= s->max_channel; ch++) { + ChannelParams *cp = &s->channel_params[ch]; + cp->filter_params[FIR].order = 0; + cp->filter_params[IIR].order = 0; + cp->filter_params[FIR].shift = 0; + cp->filter_params[IIR].shift = 0; + + /* Default audio coding is 24-bit raw PCM. */ + cp->huff_offset = 0; + cp->sign_huff_offset = (-1) << 23; + cp->codebook = 0; + cp->huff_lsbs = 24; + } + + if (substr == m->max_decoded_substream) { + m->avctx->channels = s->max_matrix_channel + 1; + m->avctx->channel_layout = s->ch_layout; + + if (m->avctx->codec_id == AV_CODEC_ID_MLP && m->needs_reordering) { + if (m->avctx->channel_layout == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) || + m->avctx->channel_layout == AV_CH_LAYOUT_5POINT0_BACK) { + int i = s->ch_assign[4]; + s->ch_assign[4] = s->ch_assign[3]; + s->ch_assign[3] = s->ch_assign[2]; + s->ch_assign[2] = i; + } else if (m->avctx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) { + FFSWAP(int, s->ch_assign[2], s->ch_assign[4]); + FFSWAP(int, s->ch_assign[3], s->ch_assign[5]); + } + } + + } + + return 0; +} + +/** Read parameters for one of the prediction filters. */ + +static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp, + unsigned int substr, unsigned int channel, + unsigned int filter) +{ + SubStream *s = &m->substream[substr]; + FilterParams *fp = &s->channel_params[channel].filter_params[filter]; + const int max_order = filter ? MAX_IIR_ORDER : MAX_FIR_ORDER; + const char fchar = filter ? 'I' : 'F'; + int i, order; + + // Filter is 0 for FIR, 1 for IIR. + av_assert0(filter < 2); + + if (m->filter_changed[channel][filter]++ > 1) { + av_log(m->avctx, AV_LOG_ERROR, "Filters may change only once per access unit.\n"); + return AVERROR_INVALIDDATA; + } + + order = get_bits(gbp, 4); + if (order > max_order) { + av_log(m->avctx, AV_LOG_ERROR, + "%cIR filter order %d is greater than maximum %d.\n", + fchar, order, max_order); + return AVERROR_INVALIDDATA; + } + fp->order = order; + + if (order > 0) { + int32_t *fcoeff = s->channel_params[channel].coeff[filter]; + int coeff_bits, coeff_shift; + + fp->shift = get_bits(gbp, 4); + + coeff_bits = get_bits(gbp, 5); + coeff_shift = get_bits(gbp, 3); + if (coeff_bits < 1 || coeff_bits > 16) { + av_log(m->avctx, AV_LOG_ERROR, + "%cIR filter coeff_bits must be between 1 and 16.\n", + fchar); + return AVERROR_INVALIDDATA; + } + if (coeff_bits + coeff_shift > 16) { + av_log(m->avctx, AV_LOG_ERROR, + "Sum of coeff_bits and coeff_shift for %cIR filter must be 16 or less.\n", + fchar); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < order; i++) + fcoeff[i] = get_sbits(gbp, coeff_bits) << coeff_shift; + + if (get_bits1(gbp)) { + int state_bits, state_shift; + + if (filter == FIR) { + av_log(m->avctx, AV_LOG_ERROR, + "FIR filter has state data specified.\n"); + return AVERROR_INVALIDDATA; + } + + state_bits = get_bits(gbp, 4); + state_shift = get_bits(gbp, 4); + + /* TODO: Check validity of state data. */ + + for (i = 0; i < order; i++) + fp->state[i] = get_sbits(gbp, state_bits) << state_shift; + } + } + + return 0; +} + +/** Read parameters for primitive matrices. */ + +static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitContext *gbp) +{ + SubStream *s = &m->substream[substr]; + unsigned int mat, ch; + const int max_primitive_matrices = m->avctx->codec_id == AV_CODEC_ID_MLP + ? MAX_MATRICES_MLP + : MAX_MATRICES_TRUEHD; + + if (m->matrix_changed++ > 1) { + av_log(m->avctx, AV_LOG_ERROR, "Matrices may change only once per access unit.\n"); + return AVERROR_INVALIDDATA; + } + + s->num_primitive_matrices = get_bits(gbp, 4); + + if (s->num_primitive_matrices > max_primitive_matrices) { + av_log(m->avctx, AV_LOG_ERROR, + "Number of primitive matrices cannot be greater than %d.\n", + max_primitive_matrices); + return AVERROR_INVALIDDATA; + } + + for (mat = 0; mat < s->num_primitive_matrices; mat++) { + int frac_bits, max_chan; + s->matrix_out_ch[mat] = get_bits(gbp, 4); + frac_bits = get_bits(gbp, 4); + s->lsb_bypass [mat] = get_bits1(gbp); + + if (s->matrix_out_ch[mat] > s->max_matrix_channel) { + av_log(m->avctx, AV_LOG_ERROR, + "Invalid channel %d specified as output from matrix.\n", + s->matrix_out_ch[mat]); + return AVERROR_INVALIDDATA; + } + if (frac_bits > 14) { + av_log(m->avctx, AV_LOG_ERROR, + "Too many fractional bits specified.\n"); + return AVERROR_INVALIDDATA; + } + + max_chan = s->max_matrix_channel; + if (!s->noise_type) + max_chan+=2; + + for (ch = 0; ch <= max_chan; ch++) { + int coeff_val = 0; + if (get_bits1(gbp)) + coeff_val = get_sbits(gbp, frac_bits + 2); + + s->matrix_coeff[mat][ch] = coeff_val << (14 - frac_bits); + } + + if (s->noise_type) + s->matrix_noise_shift[mat] = get_bits(gbp, 4); + else + s->matrix_noise_shift[mat] = 0; + } + + return 0; +} + +/** Read channel parameters. */ + +static int read_channel_params(MLPDecodeContext *m, unsigned int substr, + GetBitContext *gbp, unsigned int ch) +{ + SubStream *s = &m->substream[substr]; + ChannelParams *cp = &s->channel_params[ch]; + FilterParams *fir = &cp->filter_params[FIR]; + FilterParams *iir = &cp->filter_params[IIR]; + int ret; + + if (s->param_presence_flags & PARAM_FIR) + if (get_bits1(gbp)) + if ((ret = read_filter_params(m, gbp, substr, ch, FIR)) < 0) + return ret; + + if (s->param_presence_flags & PARAM_IIR) + if (get_bits1(gbp)) + if ((ret = read_filter_params(m, gbp, substr, ch, IIR)) < 0) + return ret; + + if (fir->order + iir->order > 8) { + av_log(m->avctx, AV_LOG_ERROR, "Total filter orders too high.\n"); + return AVERROR_INVALIDDATA; + } + + if (fir->order && iir->order && + fir->shift != iir->shift) { + av_log(m->avctx, AV_LOG_ERROR, + "FIR and IIR filters must use the same precision.\n"); + return AVERROR_INVALIDDATA; + } + /* The FIR and IIR filters must have the same precision. + * To simplify the filtering code, only the precision of the + * FIR filter is considered. If only the IIR filter is employed, + * the FIR filter precision is set to that of the IIR filter, so + * that the filtering code can use it. */ + if (!fir->order && iir->order) + fir->shift = iir->shift; + + if (s->param_presence_flags & PARAM_HUFFOFFSET) + if (get_bits1(gbp)) + cp->huff_offset = get_sbits(gbp, 15); + + cp->codebook = get_bits(gbp, 2); + cp->huff_lsbs = get_bits(gbp, 5); + + if (cp->huff_lsbs > 24) { + av_log(m->avctx, AV_LOG_ERROR, "Invalid huff_lsbs.\n"); + cp->huff_lsbs = 0; + return AVERROR_INVALIDDATA; + } + + cp->sign_huff_offset = calculate_sign_huff(m, substr, ch); + + return 0; +} + +/** Read decoding parameters that change more often than those in the restart + * header. */ + +static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, + unsigned int substr) +{ + SubStream *s = &m->substream[substr]; + unsigned int ch; + int ret; + + if (s->param_presence_flags & PARAM_PRESENCE) + if (get_bits1(gbp)) + s->param_presence_flags = get_bits(gbp, 8); + + if (s->param_presence_flags & PARAM_BLOCKSIZE) + if (get_bits1(gbp)) { + s->blocksize = get_bits(gbp, 9); + if (s->blocksize < 8 || s->blocksize > m->access_unit_size) { + av_log(m->avctx, AV_LOG_ERROR, "Invalid blocksize.\n"); + s->blocksize = 0; + return AVERROR_INVALIDDATA; + } + } + + if (s->param_presence_flags & PARAM_MATRIX) + if (get_bits1(gbp)) + if ((ret = read_matrix_params(m, substr, gbp)) < 0) + return ret; + + if (s->param_presence_flags & PARAM_OUTSHIFT) + if (get_bits1(gbp)) + for (ch = 0; ch <= s->max_matrix_channel; ch++) + s->output_shift[ch] = get_sbits(gbp, 4); + + if (s->param_presence_flags & PARAM_QUANTSTEP) + if (get_bits1(gbp)) + for (ch = 0; ch <= s->max_channel; ch++) { + ChannelParams *cp = &s->channel_params[ch]; + + s->quant_step_size[ch] = get_bits(gbp, 4); + + cp->sign_huff_offset = calculate_sign_huff(m, substr, ch); + } + + for (ch = s->min_channel; ch <= s->max_channel; ch++) + if (get_bits1(gbp)) + if ((ret = read_channel_params(m, substr, gbp, ch)) < 0) + return ret; + + return 0; +} + +#define MSB_MASK(bits) (-1u << bits) + +/** Generate PCM samples using the prediction filters and residual values + * read from the data stream, and update the filter state. */ + +static void filter_channel(MLPDecodeContext *m, unsigned int substr, + unsigned int channel) +{ + SubStream *s = &m->substream[substr]; + const int32_t *fircoeff = s->channel_params[channel].coeff[FIR]; + int32_t state_buffer[NUM_FILTERS][MAX_BLOCKSIZE + MAX_FIR_ORDER]; + int32_t *firbuf = state_buffer[FIR] + MAX_BLOCKSIZE; + int32_t *iirbuf = state_buffer[IIR] + MAX_BLOCKSIZE; + FilterParams *fir = &s->channel_params[channel].filter_params[FIR]; + FilterParams *iir = &s->channel_params[channel].filter_params[IIR]; + unsigned int filter_shift = fir->shift; + int32_t mask = MSB_MASK(s->quant_step_size[channel]); + + memcpy(firbuf, fir->state, MAX_FIR_ORDER * sizeof(int32_t)); + memcpy(iirbuf, iir->state, MAX_IIR_ORDER * sizeof(int32_t)); + + m->dsp.mlp_filter_channel(firbuf, fircoeff, + fir->order, iir->order, + filter_shift, mask, s->blocksize, + &m->sample_buffer[s->blockpos][channel]); + + memcpy(fir->state, firbuf - s->blocksize, MAX_FIR_ORDER * sizeof(int32_t)); + memcpy(iir->state, iirbuf - s->blocksize, MAX_IIR_ORDER * sizeof(int32_t)); +} + +/** Read a block of PCM residual data (or actual if no filtering active). */ + +static int read_block_data(MLPDecodeContext *m, GetBitContext *gbp, + unsigned int substr) +{ + SubStream *s = &m->substream[substr]; + unsigned int i, ch, expected_stream_pos = 0; + int ret; + + if (s->data_check_present) { + expected_stream_pos = get_bits_count(gbp); + expected_stream_pos += get_bits(gbp, 16); + avpriv_request_sample(m->avctx, + "Substreams with VLC block size check info"); + } + + if (s->blockpos + s->blocksize > m->access_unit_size) { + av_log(m->avctx, AV_LOG_ERROR, "too many audio samples in frame\n"); + return AVERROR_INVALIDDATA; + } + + memset(&m->bypassed_lsbs[s->blockpos][0], 0, + s->blocksize * sizeof(m->bypassed_lsbs[0])); + + for (i = 0; i < s->blocksize; i++) + if ((ret = read_huff_channels(m, gbp, substr, i)) < 0) + return ret; + + for (ch = s->min_channel; ch <= s->max_channel; ch++) + filter_channel(m, substr, ch); + + s->blockpos += s->blocksize; + + if (s->data_check_present) { + if (get_bits_count(gbp) != expected_stream_pos) + av_log(m->avctx, AV_LOG_ERROR, "block data length mismatch\n"); + skip_bits(gbp, 8); + } + + return 0; +} + +/** Data table used for TrueHD noise generation function. */ + +static const int8_t noise_table[256] = { + 30, 51, 22, 54, 3, 7, -4, 38, 14, 55, 46, 81, 22, 58, -3, 2, + 52, 31, -7, 51, 15, 44, 74, 30, 85, -17, 10, 33, 18, 80, 28, 62, + 10, 32, 23, 69, 72, 26, 35, 17, 73, 60, 8, 56, 2, 6, -2, -5, + 51, 4, 11, 50, 66, 76, 21, 44, 33, 47, 1, 26, 64, 48, 57, 40, + 38, 16, -10, -28, 92, 22, -18, 29, -10, 5, -13, 49, 19, 24, 70, 34, + 61, 48, 30, 14, -6, 25, 58, 33, 42, 60, 67, 17, 54, 17, 22, 30, + 67, 44, -9, 50, -11, 43, 40, 32, 59, 82, 13, 49, -14, 55, 60, 36, + 48, 49, 31, 47, 15, 12, 4, 65, 1, 23, 29, 39, 45, -2, 84, 69, + 0, 72, 37, 57, 27, 41, -15, -16, 35, 31, 14, 61, 24, 0, 27, 24, + 16, 41, 55, 34, 53, 9, 56, 12, 25, 29, 53, 5, 20, -20, -8, 20, + 13, 28, -3, 78, 38, 16, 11, 62, 46, 29, 21, 24, 46, 65, 43, -23, + 89, 18, 74, 21, 38, -12, 19, 12, -19, 8, 15, 33, 4, 57, 9, -8, + 36, 35, 26, 28, 7, 83, 63, 79, 75, 11, 3, 87, 37, 47, 34, 40, + 39, 19, 20, 42, 27, 34, 39, 77, 13, 42, 59, 64, 45, -1, 32, 37, + 45, -5, 53, -6, 7, 36, 50, 23, 6, 32, 9, -21, 18, 71, 27, 52, + -25, 31, 35, 42, -1, 68, 63, 52, 26, 43, 66, 37, 41, 25, 40, 70, +}; + +/** Noise generation functions. + * I'm not sure what these are for - they seem to be some kind of pseudorandom + * sequence generators, used to generate noise data which is used when the + * channels are rematrixed. I'm not sure if they provide a practical benefit + * to compression, or just obfuscate the decoder. Are they for some kind of + * dithering? */ + +/** Generate two channels of noise, used in the matrix when + * restart sync word == 0x31ea. */ + +static void generate_2_noise_channels(MLPDecodeContext *m, unsigned int substr) +{ + SubStream *s = &m->substream[substr]; + unsigned int i; + uint32_t seed = s->noisegen_seed; + unsigned int maxchan = s->max_matrix_channel; + + for (i = 0; i < s->blockpos; i++) { + uint16_t seed_shr7 = seed >> 7; + m->sample_buffer[i][maxchan+1] = ((int8_t)(seed >> 15)) << s->noise_shift; + m->sample_buffer[i][maxchan+2] = ((int8_t) seed_shr7) << s->noise_shift; + + seed = (seed << 16) ^ seed_shr7 ^ (seed_shr7 << 5); + } + + s->noisegen_seed = seed; +} + +/** Generate a block of noise, used when restart sync word == 0x31eb. */ + +static void fill_noise_buffer(MLPDecodeContext *m, unsigned int substr) +{ + SubStream *s = &m->substream[substr]; + unsigned int i; + uint32_t seed = s->noisegen_seed; + + for (i = 0; i < m->access_unit_size_pow2; i++) { + uint8_t seed_shr15 = seed >> 15; + m->noise_buffer[i] = noise_table[seed_shr15]; + seed = (seed << 8) ^ seed_shr15 ^ (seed_shr15 << 5); + } + + s->noisegen_seed = seed; +} + + +/** Apply the channel matrices in turn to reconstruct the original audio + * samples. */ + +static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) +{ + SubStream *s = &m->substream[substr]; + unsigned int mat, src_ch, i; + unsigned int maxchan; + + maxchan = s->max_matrix_channel; + if (!s->noise_type) { + generate_2_noise_channels(m, substr); + maxchan += 2; + } else { + fill_noise_buffer(m, substr); + } + + for (mat = 0; mat < s->num_primitive_matrices; mat++) { + int matrix_noise_shift = s->matrix_noise_shift[mat]; + unsigned int dest_ch = s->matrix_out_ch[mat]; + int32_t mask = MSB_MASK(s->quant_step_size[dest_ch]); + int32_t *coeffs = s->matrix_coeff[mat]; + int index = s->num_primitive_matrices - mat; + int index2 = 2 * index + 1; + + /* TODO: DSPContext? */ + + for (i = 0; i < s->blockpos; i++) { + int32_t bypassed_lsb = m->bypassed_lsbs[i][mat]; + int32_t *samples = m->sample_buffer[i]; + int64_t accum = 0; + + for (src_ch = 0; src_ch <= maxchan; src_ch++) + accum += (int64_t) samples[src_ch] * coeffs[src_ch]; + + if (matrix_noise_shift) { + index &= m->access_unit_size_pow2 - 1; + accum += m->noise_buffer[index] << (matrix_noise_shift + 7); + index += index2; + } + + samples[dest_ch] = ((accum >> 14) & mask) + bypassed_lsb; + } + } +} + +/** Write the audio data into the output buffer. */ + +static int output_data(MLPDecodeContext *m, unsigned int substr, + AVFrame *frame, int *got_frame_ptr) +{ + AVCodecContext *avctx = m->avctx; + SubStream *s = &m->substream[substr]; + unsigned int i, out_ch = 0; + int32_t *data_32; + int16_t *data_16; + int ret; + int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); + + if (m->avctx->channels != s->max_matrix_channel + 1) { + av_log(m->avctx, AV_LOG_ERROR, "channel count mismatch\n"); + return AVERROR_INVALIDDATA; + } + + if (!s->blockpos) { + av_log(avctx, AV_LOG_ERROR, "No samples to output.\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = s->blockpos; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + data_32 = (int32_t *)frame->data[0]; + data_16 = (int16_t *)frame->data[0]; + + for (i = 0; i < s->blockpos; i++) { + for (out_ch = 0; out_ch <= s->max_matrix_channel; out_ch++) { + int mat_ch = s->ch_assign[out_ch]; + int32_t sample = m->sample_buffer[i][mat_ch] + << s->output_shift[mat_ch]; + s->lossless_check_data ^= (sample & 0xffffff) << mat_ch; + if (is32) *data_32++ = sample << 8; + else *data_16++ = sample >> 8; + } + } + + *got_frame_ptr = 1; + + return 0; +} + +/** Read an access unit from the stream. + * @return negative on error, 0 if not enough data is present in the input stream, + * otherwise the number of bytes consumed. */ + +static int read_access_unit(AVCodecContext *avctx, void* data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MLPDecodeContext *m = avctx->priv_data; + GetBitContext gb; + unsigned int length, substr; + unsigned int substream_start; + unsigned int header_size = 4; + unsigned int substr_header_size = 0; + uint8_t substream_parity_present[MAX_SUBSTREAMS]; + uint16_t substream_data_len[MAX_SUBSTREAMS]; + uint8_t parity_bits; + int ret; + + if (buf_size < 4) + return 0; + + length = (AV_RB16(buf) & 0xfff) * 2; + + if (length < 4 || length > buf_size) + return AVERROR_INVALIDDATA; + + init_get_bits(&gb, (buf + 4), (length - 4) * 8); + + m->is_major_sync_unit = 0; + if (show_bits_long(&gb, 31) == (0xf8726fba >> 1)) { + if (read_major_sync(m, &gb) < 0) + goto error; + m->is_major_sync_unit = 1; + header_size += 28; + } + + if (!m->params_valid) { + av_log(m->avctx, AV_LOG_WARNING, + "Stream parameters not seen; skipping frame.\n"); + *got_frame_ptr = 0; + return length; + } + + substream_start = 0; + + for (substr = 0; substr < m->num_substreams; substr++) { + int extraword_present, checkdata_present, end, nonrestart_substr; + + extraword_present = get_bits1(&gb); + nonrestart_substr = get_bits1(&gb); + checkdata_present = get_bits1(&gb); + skip_bits1(&gb); + + end = get_bits(&gb, 12) * 2; + + substr_header_size += 2; + + if (extraword_present) { + if (m->avctx->codec_id == AV_CODEC_ID_MLP) { + av_log(m->avctx, AV_LOG_ERROR, "There must be no extraword for MLP.\n"); + goto error; + } + skip_bits(&gb, 16); + substr_header_size += 2; + } + + if (!(nonrestart_substr ^ m->is_major_sync_unit)) { + av_log(m->avctx, AV_LOG_ERROR, "Invalid nonrestart_substr.\n"); + goto error; + } + + if (end + header_size + substr_header_size > length) { + av_log(m->avctx, AV_LOG_ERROR, + "Indicated length of substream %d data goes off end of " + "packet.\n", substr); + end = length - header_size - substr_header_size; + } + + if (end < substream_start) { + av_log(avctx, AV_LOG_ERROR, + "Indicated end offset of substream %d data " + "is smaller than calculated start offset.\n", + substr); + goto error; + } + + if (substr > m->max_decoded_substream) + continue; + + substream_parity_present[substr] = checkdata_present; + substream_data_len[substr] = end - substream_start; + substream_start = end; + } + + parity_bits = ff_mlp_calculate_parity(buf, 4); + parity_bits ^= ff_mlp_calculate_parity(buf + header_size, substr_header_size); + + if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) { + av_log(avctx, AV_LOG_ERROR, "Parity check failed.\n"); + goto error; + } + + buf += header_size + substr_header_size; + + for (substr = 0; substr <= m->max_decoded_substream; substr++) { + SubStream *s = &m->substream[substr]; + init_get_bits(&gb, buf, substream_data_len[substr] * 8); + + m->matrix_changed = 0; + memset(m->filter_changed, 0, sizeof(m->filter_changed)); + + s->blockpos = 0; + do { + if (get_bits1(&gb)) { + if (get_bits1(&gb)) { + /* A restart header should be present. */ + if (read_restart_header(m, &gb, buf, substr) < 0) + goto next_substr; + s->restart_seen = 1; + } + + if (!s->restart_seen) + goto next_substr; + if (read_decoding_params(m, &gb, substr) < 0) + goto next_substr; + } + + if (!s->restart_seen) + goto next_substr; + + if ((ret = read_block_data(m, &gb, substr)) < 0) + return ret; + + if (get_bits_count(&gb) >= substream_data_len[substr] * 8) + goto substream_length_mismatch; + + } while (!get_bits1(&gb)); + + skip_bits(&gb, (-get_bits_count(&gb)) & 15); + + if (substream_data_len[substr] * 8 - get_bits_count(&gb) >= 32) { + int shorten_by; + + if (get_bits(&gb, 16) != 0xD234) + return AVERROR_INVALIDDATA; + + shorten_by = get_bits(&gb, 16); + if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD && shorten_by & 0x2000) + s->blockpos -= FFMIN(shorten_by & 0x1FFF, s->blockpos); + else if (m->avctx->codec_id == AV_CODEC_ID_MLP && shorten_by != 0xD234) + return AVERROR_INVALIDDATA; + + if (substr == m->max_decoded_substream) + av_log(m->avctx, AV_LOG_INFO, "End of stream indicated.\n"); + } + + if (substream_parity_present[substr]) { + uint8_t parity, checksum; + + if (substream_data_len[substr] * 8 - get_bits_count(&gb) != 16) + goto substream_length_mismatch; + + parity = ff_mlp_calculate_parity(buf, substream_data_len[substr] - 2); + checksum = ff_mlp_checksum8 (buf, substream_data_len[substr] - 2); + + if ((get_bits(&gb, 8) ^ parity) != 0xa9 ) + av_log(m->avctx, AV_LOG_ERROR, "Substream %d parity check failed.\n", substr); + if ( get_bits(&gb, 8) != checksum) + av_log(m->avctx, AV_LOG_ERROR, "Substream %d checksum failed.\n" , substr); + } + + if (substream_data_len[substr] * 8 != get_bits_count(&gb)) + goto substream_length_mismatch; + +next_substr: + if (!s->restart_seen) + av_log(m->avctx, AV_LOG_ERROR, + "No restart header present in substream %d.\n", substr); + + buf += substream_data_len[substr]; + } + + rematrix_channels(m, m->max_decoded_substream); + + if ((ret = output_data(m, m->max_decoded_substream, data, got_frame_ptr)) < 0) + return ret; + + return length; + +substream_length_mismatch: + av_log(m->avctx, AV_LOG_ERROR, "substream %d length mismatch\n", substr); + return AVERROR_INVALIDDATA; + +error: + m->params_valid = 0; + return AVERROR_INVALIDDATA; +} + +#if CONFIG_MLP_DECODER +AVCodec ff_mlp_decoder = { + .name = "mlp", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MLP, + .priv_data_size = sizeof(MLPDecodeContext), + .init = mlp_decode_init, + .decode = read_access_unit, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), +}; +#endif +#if CONFIG_TRUEHD_DECODER +AVCodec ff_truehd_decoder = { + .name = "truehd", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_TRUEHD, + .priv_data_size = sizeof(MLPDecodeContext), + .init = mlp_decode_init, + .decode = read_access_unit, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), +}; +#endif /* CONFIG_TRUEHD_DECODER */ diff --git a/ffmpeg/libavcodec/mlpdsp.c b/ffmpeg/libavcodec/mlpdsp.c new file mode 100644 index 0000000..9a376e2 --- /dev/null +++ b/ffmpeg/libavcodec/mlpdsp.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2007-2008 Ian Caulfield + * 2009 Ramiro Polla + * + * 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 "config.h" +#include "mlpdsp.h" +#include "mlp.h" + +static void ff_mlp_filter_channel(int32_t *state, const int32_t *coeff, + int firorder, int iirorder, + unsigned int filter_shift, int32_t mask, int blocksize, + int32_t *sample_buffer) +{ + int32_t *firbuf = state; + int32_t *iirbuf = state + MAX_BLOCKSIZE + MAX_FIR_ORDER; + const int32_t *fircoeff = coeff; + const int32_t *iircoeff = coeff + MAX_FIR_ORDER; + int i; + + for (i = 0; i < blocksize; i++) { + int32_t residual = *sample_buffer; + unsigned int order; + int64_t accum = 0; + int32_t result; + + for (order = 0; order < firorder; order++) + accum += (int64_t) firbuf[order] * fircoeff[order]; + for (order = 0; order < iirorder; order++) + accum += (int64_t) iirbuf[order] * iircoeff[order]; + + accum = accum >> filter_shift; + result = (accum + residual) & mask; + + *--firbuf = result; + *--iirbuf = result - accum; + + *sample_buffer = result; + sample_buffer += MAX_CHANNELS; + } +} + +void ff_mlpdsp_init(MLPDSPContext *c) +{ + c->mlp_filter_channel = ff_mlp_filter_channel; + if (ARCH_X86) + ff_mlpdsp_init_x86(c); +} diff --git a/ffmpeg/libavcodec/mlpdsp.h b/ffmpeg/libavcodec/mlpdsp.h new file mode 100644 index 0000000..84a8aa3 --- /dev/null +++ b/ffmpeg/libavcodec/mlpdsp.h @@ -0,0 +1,37 @@ +/* + * MLP codec common header file + * Copyright (c) 2007-2008 Ian Caulfield + * + * 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 + */ + +#ifndef AVCODEC_MLPDSP_H +#define AVCODEC_MLPDSP_H + +#include + +typedef struct MLPDSPContext { + void (*mlp_filter_channel)(int32_t *state, const int32_t *coeff, + int firorder, int iirorder, + unsigned int filter_shift, int32_t mask, + int blocksize, int32_t *sample_buffer); +} MLPDSPContext; + +void ff_mlpdsp_init(MLPDSPContext *c); +void ff_mlpdsp_init_x86(MLPDSPContext *c); + +#endif /* AVCODEC_MLPDSP_H */ diff --git a/ffmpeg/libavcodec/mmvideo.c b/ffmpeg/libavcodec/mmvideo.c new file mode 100644 index 0000000..bf47f65 --- /dev/null +++ b/ffmpeg/libavcodec/mmvideo.c @@ -0,0 +1,238 @@ +/* + * American Laser Games MM Video Decoder + * Copyright (c) 2006,2008 Peter Ross + * + * 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 + */ + +/** + * @file + * American Laser Games MM Video Decoder + * by Peter Ross (pross@xvid.org) + * + * The MM format was used by IBM-PC ports of ALG's "arcade shooter" games, + * including Mad Dog McCree and Crime Patrol. + * + * Technical details here: + * http://wiki.multimedia.cx/index.php?title=American_Laser_Games_MM + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define MM_PREAMBLE_SIZE 6 + +#define MM_TYPE_INTER 0x5 +#define MM_TYPE_INTRA 0x8 +#define MM_TYPE_INTRA_HH 0xc +#define MM_TYPE_INTER_HH 0xd +#define MM_TYPE_INTRA_HHV 0xe +#define MM_TYPE_INTER_HHV 0xf +#define MM_TYPE_PALETTE 0x31 + +typedef struct MmContext { + AVCodecContext *avctx; + AVFrame frame; + int palette[AVPALETTE_COUNT]; + GetByteContext gb; +} MmContext; + +static av_cold int mm_decode_init(AVCodecContext *avctx) +{ + MmContext *s = avctx->priv_data; + + s->avctx = avctx; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + +static int mm_decode_pal(MmContext *s) +{ + int i; + + bytestream2_skip(&s->gb, 4); + for (i = 0; i < 128; i++) { + s->palette[i] = 0xFFU << 24 | bytestream2_get_be24(&s->gb); + s->palette[i+128] = s->palette[i]<<2; + } + + return 0; +} + +/** + * @param half_horiz Half horizontal resolution (0 or 1) + * @param half_vert Half vertical resolution (0 or 1) + */ +static int mm_decode_intra(MmContext * s, int half_horiz, int half_vert) +{ + int x = 0, y = 0; + + while (bytestream2_get_bytes_left(&s->gb) > 0) { + int run_length, color; + + if (y >= s->avctx->height) + return 0; + + color = bytestream2_get_byte(&s->gb); + if (color & 0x80) { + run_length = 1; + }else{ + run_length = (color & 0x7f) + 2; + color = bytestream2_get_byte(&s->gb); + } + + if (half_horiz) + run_length *=2; + + if (color) { + memset(s->frame.data[0] + y*s->frame.linesize[0] + x, color, run_length); + if (half_vert) + memset(s->frame.data[0] + (y+1)*s->frame.linesize[0] + x, color, run_length); + } + x+= run_length; + + if (x >= s->avctx->width) { + x=0; + y += 1 + half_vert; + } + } + + return 0; +} + +/** + * @param half_horiz Half horizontal resolution (0 or 1) + * @param half_vert Half vertical resolution (0 or 1) + */ +static int mm_decode_inter(MmContext * s, int half_horiz, int half_vert) +{ + int data_off = bytestream2_get_le16(&s->gb), y = 0; + GetByteContext data_ptr; + + if (bytestream2_get_bytes_left(&s->gb) < data_off) + return AVERROR_INVALIDDATA; + + bytestream2_init(&data_ptr, s->gb.buffer + data_off, bytestream2_get_bytes_left(&s->gb) - data_off); + while (s->gb.buffer < data_ptr.buffer_start) { + int i, j; + int length = bytestream2_get_byte(&s->gb); + int x = bytestream2_get_byte(&s->gb) + ((length & 0x80) << 1); + length &= 0x7F; + + if (length==0) { + y += x; + continue; + } + + if (y + half_vert >= s->avctx->height) + return 0; + + for(i=0; igb); + for(j=0; j<8; j++) { + int replace = (replace_array >> (7-j)) & 1; + if (replace) { + int color = bytestream2_get_byte(&data_ptr); + s->frame.data[0][y*s->frame.linesize[0] + x] = color; + if (half_horiz) + s->frame.data[0][y*s->frame.linesize[0] + x + 1] = color; + if (half_vert) { + s->frame.data[0][(y+1)*s->frame.linesize[0] + x] = color; + if (half_horiz) + s->frame.data[0][(y+1)*s->frame.linesize[0] + x + 1] = color; + } + } + x += 1 + half_horiz; + } + } + + y += 1 + half_vert; + } + + return 0; +} + +static int mm_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MmContext *s = avctx->priv_data; + int type, res; + + if (buf_size < MM_PREAMBLE_SIZE) + return AVERROR_INVALIDDATA; + type = AV_RL16(&buf[0]); + buf += MM_PREAMBLE_SIZE; + buf_size -= MM_PREAMBLE_SIZE; + bytestream2_init(&s->gb, buf, buf_size); + + if ((res = ff_reget_buffer(avctx, &s->frame)) < 0) + return res; + + switch(type) { + case MM_TYPE_PALETTE : res = mm_decode_pal(s); return avpkt->size; + case MM_TYPE_INTRA : res = mm_decode_intra(s, 0, 0); break; + case MM_TYPE_INTRA_HH : res = mm_decode_intra(s, 1, 0); break; + case MM_TYPE_INTRA_HHV : res = mm_decode_intra(s, 1, 1); break; + case MM_TYPE_INTER : res = mm_decode_inter(s, 0, 0); break; + case MM_TYPE_INTER_HH : res = mm_decode_inter(s, 1, 0); break; + case MM_TYPE_INTER_HHV : res = mm_decode_inter(s, 1, 1); break; + default: + res = AVERROR_INVALIDDATA; + break; + } + if (res < 0) + return res; + + memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); + + if ((res = av_frame_ref(data, &s->frame)) < 0) + return res; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int mm_decode_end(AVCodecContext *avctx) +{ + MmContext *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_mmvideo_decoder = { + .name = "mmvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MMVIDEO, + .priv_data_size = sizeof(MmContext), + .init = mm_decode_init, + .close = mm_decode_end, + .decode = mm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"), +}; diff --git a/ffmpeg/libavcodec/motion-test.c b/ffmpeg/libavcodec/motion-test.c new file mode 100644 index 0000000..53cfedb --- /dev/null +++ b/ffmpeg/libavcodec/motion-test.c @@ -0,0 +1,151 @@ +/* + * (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * motion test. + */ + +#include +#include +#include + +#include "config.h" +#include "dsputil.h" +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "libavutil/mem.h" +#include "libavutil/time.h" + +#undef printf + +#define WIDTH 64 +#define HEIGHT 64 + +static uint8_t img1[WIDTH * HEIGHT]; +static uint8_t img2[WIDTH * HEIGHT]; + +static void fill_random(uint8_t *tab, int size) +{ + int i; + AVLFG prng; + + av_lfg_init(&prng, 1); + for(i=0;i 1) { + help(); + return 1; + } + + printf("ffmpeg motion test\n"); + + ctx = avcodec_alloc_context3(NULL); + ctx->flags |= CODEC_FLAG_BITEXACT; + memset(&cctx, 0, sizeof(cctx)); + ff_dsputil_init(&cctx, ctx); + for (c = 0; c < flags_size; c++) { + int x; + av_force_cpu_flags(flags[c]); + memset(&mmxctx, 0, sizeof(mmxctx)); + ff_dsputil_init(&mmxctx, ctx); + + for (x = 0; x < 2; x++) { + printf("%s for %dx%d pixels\n", c ? "mmx2" : "mmx", + x ? 8 : 16, x ? 8 : 16); + test_motion("mmx", mmxctx.pix_abs[x][0], cctx.pix_abs[x][0]); + test_motion("mmx_x2", mmxctx.pix_abs[x][1], cctx.pix_abs[x][1]); + test_motion("mmx_y2", mmxctx.pix_abs[x][2], cctx.pix_abs[x][2]); + test_motion("mmx_xy2", mmxctx.pix_abs[x][3], cctx.pix_abs[x][3]); + } + } + av_free(ctx); + + return 0; +} diff --git a/ffmpeg/libavcodec/motion_est.c b/ffmpeg/libavcodec/motion_est.c new file mode 100644 index 0000000..dc8e39b --- /dev/null +++ b/ffmpeg/libavcodec/motion_est.c @@ -0,0 +1,1759 @@ +/* + * Motion estimation + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * new motion estimation (X1/EPZS) 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 + */ + +/** + * @file + * Motion estimation. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "mathops.h" +#include "mpegvideo.h" + +#undef NDEBUG +#include + +#define P_LEFT P[1] +#define P_TOP P[2] +#define P_TOPRIGHT P[3] +#define P_MEDIAN P[4] +#define P_MV1 P[9] + +static int sad_hpel_motion_search(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int dmin, + int src_index, int ref_index, + int size, int h); + +static inline unsigned update_map_generation(MotionEstContext *c) +{ + c->map_generation+= 1<<(ME_MAP_MV_BITS*2); + if(c->map_generation==0){ + c->map_generation= 1<<(ME_MAP_MV_BITS*2); + memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE); + } + return c->map_generation; +} + +/* shape adaptive search stuff */ +typedef struct Minima{ + int height; + int x, y; + int checked; +}Minima; + +static int minima_cmp(const void *a, const void *b){ + const Minima *da = (const Minima *) a; + const Minima *db = (const Minima *) b; + + return da->height - db->height; +} + +#define FLAG_QPEL 1 //must be 1 +#define FLAG_CHROMA 2 +#define FLAG_DIRECT 4 + +static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){ + const int offset[3]= { + y*c-> stride + x, + ((y*c->uvstride + x)>>1), + ((y*c->uvstride + x)>>1), + }; + int i; + for(i=0; i<3; i++){ + c->src[0][i]= src [i] + offset[i]; + c->ref[0][i]= ref [i] + offset[i]; + } + if(ref_index){ + for(i=0; i<3; i++){ + c->ref[ref_index][i]= ref2[i] + offset[i]; + } + } +} + +static int get_flags(MotionEstContext *c, int direct, int chroma){ + return ((c->avctx->flags&CODEC_FLAG_QPEL) ? FLAG_QPEL : 0) + + (direct ? FLAG_DIRECT : 0) + + (chroma ? FLAG_CHROMA : 0); +} + +static av_always_inline int cmp_direct_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){ + MotionEstContext * const c= &s->me; + const int stride= c->stride; + const int hx= subx + (x<<(1+qpel)); + const int hy= suby + (y<<(1+qpel)); + uint8_t * const * const ref= c->ref[ref_index]; + uint8_t * const * const src= c->src[src_index]; + int d; + //FIXME check chroma 4mv, (no crashes ...) + av_assert2(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)); + if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){ + const int time_pp= s->pp_time; + const int time_pb= s->pb_time; + const int mask= 2*qpel+1; + if(s->mv_type==MV_TYPE_8X8){ + int i; + for(i=0; i<4; i++){ + int fx = c->direct_basis_mv[i][0] + hx; + int fy = c->direct_basis_mv[i][1] + hy; + int bx = hx ? fx - c->co_located_mv[i][0] : c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(qpel+4)); + int by = hy ? fy - c->co_located_mv[i][1] : c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(qpel+4)); + int fxy= (fx&mask) + ((fy&mask)<<(qpel+1)); + int bxy= (bx&mask) + ((by&mask)<<(qpel+1)); + + uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1); + if(qpel){ + c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride); + c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride); + }else{ + c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8); + c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8); + } + } + }else{ + int fx = c->direct_basis_mv[0][0] + hx; + int fy = c->direct_basis_mv[0][1] + hy; + int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp); + int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp); + int fxy= (fx&mask) + ((fy&mask)<<(qpel+1)); + int bxy= (bx&mask) + ((by&mask)<<(qpel+1)); + + if(qpel){ + c->qpel_put[1][fxy](c->temp , ref[0] + (fx>>2) + (fy>>2)*stride , stride); + c->qpel_put[1][fxy](c->temp + 8 , ref[0] + (fx>>2) + (fy>>2)*stride + 8 , stride); + c->qpel_put[1][fxy](c->temp + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8*stride, stride); + c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride); + c->qpel_avg[1][bxy](c->temp , ref[8] + (bx>>2) + (by>>2)*stride , stride); + c->qpel_avg[1][bxy](c->temp + 8 , ref[8] + (bx>>2) + (by>>2)*stride + 8 , stride); + c->qpel_avg[1][bxy](c->temp + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8*stride, stride); + c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride); + }else{ + av_assert2((fx>>1) + 16*s->mb_x >= -16); + av_assert2((fy>>1) + 16*s->mb_y >= -16); + av_assert2((fx>>1) + 16*s->mb_x <= s->width); + av_assert2((fy>>1) + 16*s->mb_y <= s->height); + av_assert2((bx>>1) + 16*s->mb_x >= -16); + av_assert2((by>>1) + 16*s->mb_y >= -16); + av_assert2((bx>>1) + 16*s->mb_x <= s->width); + av_assert2((by>>1) + 16*s->mb_y <= s->height); + + c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16); + c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16); + } + } + d = cmp_func(s, c->temp, src[0], stride, 16); + }else + d= 256*256*256*32; + return d; +} + +static av_always_inline int cmp_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel, int chroma){ + MotionEstContext * const c= &s->me; + const int stride= c->stride; + const int uvstride= c->uvstride; + const int dxy= subx + (suby<<(1+qpel)); //FIXME log2_subpel? + const int hx= subx + (x<<(1+qpel)); + const int hy= suby + (y<<(1+qpel)); + uint8_t * const * const ref= c->ref[ref_index]; + uint8_t * const * const src= c->src[src_index]; + int d; + //FIXME check chroma 4mv, (no crashes ...) + int uvdxy; /* no, it might not be used uninitialized */ + if(dxy){ + if(qpel){ + c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h) + if(chroma){ + int cx= hx/2; + int cy= hy/2; + cx= (cx>>1)|(cx&1); + cy= (cy>>1)|(cy&1); + uvdxy= (cx&1) + 2*(cy&1); + //FIXME x/y wrong, but mpeg4 qpel is sick anyway, we should drop as much of it as possible in favor for h264 + } + }else{ + c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h); + if(chroma) + uvdxy= dxy | (x&1) | (2*(y&1)); + } + d = cmp_func(s, c->temp, src[0], stride, h); + }else{ + d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h); + if(chroma) + uvdxy= (x&1) + 2*(y&1); + } + if(chroma){ + uint8_t * const uvtemp= c->temp + 16*stride; + c->hpel_put[size+1][uvdxy](uvtemp , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1); + c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1); + d += chroma_cmp_func(s, uvtemp , src[1], uvstride, h>>1); + d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1); + } + return d; +} + +static int cmp_simple(MpegEncContext *s, const int x, const int y, + int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func){ + return cmp_inline(s,x,y,0,0,0,16,ref_index,src_index, cmp_func, chroma_cmp_func, 0, 0); +} + +static int cmp_fpel_internal(MpegEncContext *s, const int x, const int y, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){ + if(flags&FLAG_DIRECT){ + return cmp_direct_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL); + }else{ + return cmp_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA); + } +} + +static int cmp_internal(MpegEncContext *s, const int x, const int y, const int subx, const int suby, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){ + if(flags&FLAG_DIRECT){ + return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL); + }else{ + return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL, flags&FLAG_CHROMA); + } +} + +/** @brief compares a block (either a full macroblock or a partition thereof) + against a proposed motion-compensated prediction of that block + */ +static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){ + if(av_builtin_constant_p(flags) && av_builtin_constant_p(h) && av_builtin_constant_p(size) + && av_builtin_constant_p(subx) && av_builtin_constant_p(suby) + && flags==0 && h==16 && size==0 && subx==0 && suby==0){ + return cmp_simple(s,x,y,ref_index,src_index, cmp_func, chroma_cmp_func); + }else if(av_builtin_constant_p(subx) && av_builtin_constant_p(suby) + && subx==0 && suby==0){ + return cmp_fpel_internal(s,x,y,size,h,ref_index,src_index, cmp_func, chroma_cmp_func,flags); + }else{ + return cmp_internal(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags); + } +} + +static int cmp_hpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){ + if(flags&FLAG_DIRECT){ + return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0); + }else{ + return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA); + } +} + +static int cmp_qpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby, + const int size, const int h, int ref_index, int src_index, + me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){ + if(flags&FLAG_DIRECT){ + return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1); + }else{ + return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1, flags&FLAG_CHROMA); + } +} + +#include "motion_est_template.c" + +static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){ + return 0; +} + +static void zero_hpel(uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h){ +} + +int ff_init_me(MpegEncContext *s){ + MotionEstContext * const c= &s->me; + int cache_size= FFMIN(ME_MAP_SIZE>>ME_MAP_SHIFT, 1<avctx->dia_size)&255, FFABS(s->avctx->pre_dia_size)&255); + + if(FFMIN(s->avctx->dia_size, s->avctx->pre_dia_size) < -FFMIN(ME_MAP_SIZE, MAX_SAB_SIZE)){ + av_log(s->avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n"); + return -1; + } + //special case of snow is needed because snow uses its own iterative ME code + if(s->me_method!=ME_ZERO && s->me_method!=ME_EPZS && s->me_method!=ME_X1 && s->avctx->codec_id != AV_CODEC_ID_SNOW){ + av_log(s->avctx, AV_LOG_ERROR, "me_method is only allowed to be set to zero and epzs; for hex,umh,full and others see dia_size\n"); + return -1; + } + + c->avctx= s->avctx; + + if(cache_size < 2*dia_size && !c->stride){ + av_log(s->avctx, AV_LOG_INFO, "ME_MAP size may be a little small for the selected diamond size\n"); + } + + ff_set_cmp(&s->dsp, s->dsp.me_pre_cmp, c->avctx->me_pre_cmp); + ff_set_cmp(&s->dsp, s->dsp.me_cmp, c->avctx->me_cmp); + ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, c->avctx->me_sub_cmp); + ff_set_cmp(&s->dsp, s->dsp.mb_cmp, c->avctx->mb_cmp); + + c->flags = get_flags(c, 0, c->avctx->me_cmp &FF_CMP_CHROMA); + c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA); + c->mb_flags = get_flags(c, 0, c->avctx->mb_cmp &FF_CMP_CHROMA); + +/*FIXME s->no_rounding b_type*/ + if(s->flags&CODEC_FLAG_QPEL){ + c->sub_motion_search= qpel_motion_search; + c->qpel_avg= s->dsp.avg_qpel_pixels_tab; + if(s->no_rounding) c->qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab; + else c->qpel_put= s->dsp.put_qpel_pixels_tab; + }else{ + if(c->avctx->me_sub_cmp&FF_CMP_CHROMA) + c->sub_motion_search= hpel_motion_search; + else if( c->avctx->me_sub_cmp == FF_CMP_SAD + && c->avctx-> me_cmp == FF_CMP_SAD + && c->avctx-> mb_cmp == FF_CMP_SAD) + c->sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles + else + c->sub_motion_search= hpel_motion_search; + } + c->hpel_avg= s->hdsp.avg_pixels_tab; + if(s->no_rounding) c->hpel_put= s->hdsp.put_no_rnd_pixels_tab; + else c->hpel_put= s->hdsp.put_pixels_tab; + + if(s->linesize){ + c->stride = s->linesize; + c->uvstride= s->uvlinesize; + }else{ + c->stride = 16*s->mb_width + 32; + c->uvstride= 8*s->mb_width + 16; + } + + /* 8x8 fullpel search would need a 4x4 chroma compare, which we do + * not have yet, and even if we had, the motion estimation code + * does not expect it. */ + if(s->codec_id != AV_CODEC_ID_SNOW){ + if((c->avctx->me_cmp&FF_CMP_CHROMA)/* && !s->dsp.me_cmp[2]*/){ + s->dsp.me_cmp[2]= zero_cmp; + } + if((c->avctx->me_sub_cmp&FF_CMP_CHROMA) && !s->dsp.me_sub_cmp[2]){ + s->dsp.me_sub_cmp[2]= zero_cmp; + } + c->hpel_put[2][0]= c->hpel_put[2][1]= + c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel; + } + + if(s->codec_id == AV_CODEC_ID_H261){ + c->sub_motion_search= no_sub_motion_search; + } + + return 0; +} + +#define CHECK_SAD_HALF_MV(suffix, x, y) \ +{\ + d= s->dsp.pix_abs[size][(x?1:0)+(y?2:0)](NULL, pix, ptr+((x)>>1), stride, h);\ + d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\ + COPY3_IF_LT(dminh, d, dx, x, dy, y)\ +} + +static int sad_hpel_motion_search(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int dmin, + int src_index, int ref_index, + int size, int h) +{ + MotionEstContext * const c= &s->me; + const int penalty_factor= c->sub_penalty_factor; + int mx, my, dminh; + uint8_t *pix, *ptr; + int stride= c->stride; + const int flags= c->sub_flags; + LOAD_COMMON + + av_assert2(flags == 0); + + if(c->skip){ + *mx_ptr = 0; + *my_ptr = 0; + return dmin; + } + + pix = c->src[src_index][0]; + + mx = *mx_ptr; + my = *my_ptr; + ptr = c->ref[ref_index][0] + (my * stride) + mx; + + dminh = dmin; + + if (mx > xmin && mx < xmax && + my > ymin && my < ymax) { + int dx=0, dy=0; + int d, pen_x, pen_y; + const int index= (my<mb_x + s->mb_y*s->mb_stride; + + s->p_mv_table[xy][0] = mx; + s->p_mv_table[xy][1] = my; + + /* has already been set to the 4 MV if 4MV is done */ + if(mv4){ + int mot_xy= s->block_index[0]; + + s->current_picture.motion_val[0][mot_xy ][0] = mx; + s->current_picture.motion_val[0][mot_xy ][1] = my; + s->current_picture.motion_val[0][mot_xy + 1][0] = mx; + s->current_picture.motion_val[0][mot_xy + 1][1] = my; + + mot_xy += s->b8_stride; + s->current_picture.motion_val[0][mot_xy ][0] = mx; + s->current_picture.motion_val[0][mot_xy ][1] = my; + s->current_picture.motion_val[0][mot_xy + 1][0] = mx; + s->current_picture.motion_val[0][mot_xy + 1][1] = my; + } +} + +/** + * get fullpel ME search limits. + */ +static inline void get_limits(MpegEncContext *s, int x, int y) +{ + MotionEstContext * const c= &s->me; + int range= c->avctx->me_range >> (1 + !!(c->flags&FLAG_QPEL)); + int max_range = MAX_MV >> (1 + !!(c->flags&FLAG_QPEL)); +/* + if(c->avctx->me_range) c->range= c->avctx->me_range >> 1; + else c->range= 16; +*/ + if (s->unrestricted_mv) { + c->xmin = - x - 16; + c->ymin = - y - 16; + c->xmax = - x + s->width; + c->ymax = - y + s->height; + } else if (s->out_format == FMT_H261){ + // Search range of H261 is different from other codec standards + c->xmin = (x > 15) ? - 15 : 0; + c->ymin = (y > 15) ? - 15 : 0; + c->xmax = (x < s->mb_width * 16 - 16) ? 15 : 0; + c->ymax = (y < s->mb_height * 16 - 16) ? 15 : 0; + } else { + c->xmin = - x; + c->ymin = - y; + c->xmax = - x + s->mb_width *16 - 16; + c->ymax = - y + s->mb_height*16 - 16; + } + if(!range || range > max_range) + range = max_range; + if(range){ + c->xmin = FFMAX(c->xmin,-range); + c->xmax = FFMIN(c->xmax, range); + c->ymin = FFMAX(c->ymin,-range); + c->ymax = FFMIN(c->ymax, range); + } +} + +static inline void init_mv4_ref(MotionEstContext *c){ + const int stride= c->stride; + + c->ref[1][0] = c->ref[0][0] + 8; + c->ref[2][0] = c->ref[0][0] + 8*stride; + c->ref[3][0] = c->ref[2][0] + 8; + c->src[1][0] = c->src[0][0] + 8; + c->src[2][0] = c->src[0][0] + 8*stride; + c->src[3][0] = c->src[2][0] + 8; +} + +static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift) +{ + MotionEstContext * const c= &s->me; + const int size= 1; + const int h=8; + int block; + int P[10][2]; + int dmin_sum=0, mx4_sum=0, my4_sum=0, i; + int same=1; + const int stride= c->stride; + uint8_t *mv_penalty= c->current_mv_penalty; + int saftey_cliping= s->unrestricted_mv && (s->width&15) && (s->height&15); + + init_mv4_ref(c); + + for(block=0; block<4; block++){ + int mx4, my4; + int pred_x4, pred_y4; + int dmin4; + static const int off[4]= {2, 1, 1, -1}; + const int mot_stride = s->b8_stride; + const int mot_xy = s->block_index[block]; + + if(saftey_cliping){ + c->xmax = - 16*s->mb_x + s->width - 8*(block &1); + c->ymax = - 16*s->mb_y + s->height - 8*(block>>1); + } + + P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0]; + P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1]; + + if(P_LEFT[0] > (c->xmax<xmax<first_slice_line && block<2) { + c->pred_x= pred_x4= P_LEFT[0]; + c->pred_y= pred_y4= P_LEFT[1]; + } else { + P_TOP[0] = s->current_picture.motion_val[0][mot_xy - mot_stride ][0]; + P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1]; + P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][0]; + P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][1]; + if(P_TOP[1] > (c->ymax<ymax<xmin<xmin< (c->xmax<xmax< (c->ymax<ymax<pred_x= pred_x4 = P_MEDIAN[0]; + c->pred_y= pred_y4 = P_MEDIAN[1]; + } + P_MV1[0]= mx; + P_MV1[1]= my; + if(saftey_cliping) + for(i=0; i<10; i++){ + if(P[i][0] > (c->xmax<xmax< (c->ymax<ymax<p_mv_table, (1<<16)>>shift); + + dmin4= c->sub_motion_search(s, &mx4, &my4, dmin4, block, block, size, h); + + if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){ + int dxy; + const int offset= ((block&1) + (block>>1)*stride)*8; + uint8_t *dest_y = c->scratchpad + offset; + if(s->quarter_sample){ + uint8_t *ref= c->ref[block][0] + (mx4>>2) + (my4>>2)*stride; + dxy = ((my4 & 3) << 2) | (mx4 & 3); + + if(s->no_rounding) + s->dsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y , ref , stride); + else + s->dsp.put_qpel_pixels_tab [1][dxy](dest_y , ref , stride); + }else{ + uint8_t *ref= c->ref[block][0] + (mx4>>1) + (my4>>1)*stride; + dxy = ((my4 & 1) << 1) | (mx4 & 1); + + if(s->no_rounding) + s->hdsp.put_no_rnd_pixels_tab[1][dxy](dest_y , ref , stride, h); + else + s->hdsp.put_pixels_tab [1][dxy](dest_y , ref , stride, h); + } + dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*c->mb_penalty_factor; + }else + dmin_sum+= dmin4; + + if(s->quarter_sample){ + mx4_sum+= mx4/2; + my4_sum+= my4/2; + }else{ + mx4_sum+= mx4; + my4_sum+= my4; + } + + s->current_picture.motion_val[0][s->block_index[block]][0] = mx4; + s->current_picture.motion_val[0][s->block_index[block]][1] = my4; + + if(mx4 != mx || my4 != my) same=0; + } + + if(same) + return INT_MAX; + + if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){ + dmin_sum += s->dsp.mb_cmp[0](s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*16*stride, c->scratchpad, stride, 16); + } + + if(c->avctx->mb_cmp&FF_CMP_CHROMA){ + int dxy; + int mx, my; + int offset; + + mx= ff_h263_round_chroma(mx4_sum); + my= ff_h263_round_chroma(my4_sum); + dxy = ((my & 1) << 1) | (mx & 1); + + offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize; + + if(s->no_rounding){ + s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad , s->last_picture.f.data[1] + offset, s->uvlinesize, 8); + s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8); + }else{ + s->hdsp.put_pixels_tab [1][dxy](c->scratchpad , s->last_picture.f.data[1] + offset, s->uvlinesize, 8); + s->hdsp.put_pixels_tab [1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8); + } + + dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad , s->uvlinesize, 8); + dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad+8, s->uvlinesize, 8); + } + + c->pred_x= mx; + c->pred_y= my; + + switch(c->avctx->mb_cmp&0xFF){ + /*case FF_CMP_SSE: + return dmin_sum+ 32*s->qscale*s->qscale;*/ + case FF_CMP_RD: + return dmin_sum; + default: + return dmin_sum+ 11*c->mb_penalty_factor; + } +} + +static inline void init_interlaced_ref(MpegEncContext *s, int ref_index){ + MotionEstContext * const c= &s->me; + + c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->linesize; + c->src[1][0] = c->src[0][0] + s->linesize; + if(c->flags & FLAG_CHROMA){ + c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->uvlinesize; + c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->uvlinesize; + c->src[1][1] = c->src[0][1] + s->uvlinesize; + c->src[1][2] = c->src[0][2] + s->uvlinesize; + } +} + +static int interlaced_search(MpegEncContext *s, int ref_index, + int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select) +{ + MotionEstContext * const c= &s->me; + const int size=0; + const int h=8; + int block; + int P[10][2]; + uint8_t * const mv_penalty= c->current_mv_penalty; + int same=1; + const int stride= 2*s->linesize; + int dmin_sum= 0; + const int mot_stride= s->mb_stride; + const int xy= s->mb_x + s->mb_y*mot_stride; + + c->ymin>>=1; + c->ymax>>=1; + c->stride<<=1; + c->uvstride<<=1; + init_interlaced_ref(s, ref_index); + + for(block=0; block<2; block++){ + int field_select; + int best_dmin= INT_MAX; + int best_field= -1; + + for(field_select=0; field_select<2; field_select++){ + int dmin, mx_i, my_i; + int16_t (*mv_table)[2]= mv_tables[block][field_select]; + + if(user_field_select){ + av_assert1(field_select==0 || field_select==1); + av_assert1(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1); + if(field_select_tables[block][xy] != field_select) + continue; + } + + P_LEFT[0] = mv_table[xy - 1][0]; + P_LEFT[1] = mv_table[xy - 1][1]; + if(P_LEFT[0] > (c->xmax<<1)) P_LEFT[0] = (c->xmax<<1); + + c->pred_x= P_LEFT[0]; + c->pred_y= P_LEFT[1]; + + if(!s->first_slice_line){ + P_TOP[0] = mv_table[xy - mot_stride][0]; + P_TOP[1] = mv_table[xy - mot_stride][1]; + P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0]; + P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1]; + if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1); + if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1); + if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1); + if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1); + + P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]); + P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]); + } + P_MV1[0]= mx; //FIXME not correct if block != field_select + P_MV1[1]= my / 2; + + dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1); + + dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h); + + mv_table[xy][0]= mx_i; + mv_table[xy][1]= my_i; + + if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){ + int dxy; + + //FIXME chroma ME + uint8_t *ref= c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride; + dxy = ((my_i & 1) << 1) | (mx_i & 1); + + if(s->no_rounding){ + s->hdsp.put_no_rnd_pixels_tab[size][dxy](c->scratchpad, ref , stride, h); + }else{ + s->hdsp.put_pixels_tab [size][dxy](c->scratchpad, ref , stride, h); + } + dmin= s->dsp.mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h); + dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor; + }else + dmin+= c->mb_penalty_factor; //field_select bits + + dmin += field_select != block; //slightly prefer same field + + if(dmin < best_dmin){ + best_dmin= dmin; + best_field= field_select; + } + } + { + int16_t (*mv_table)[2]= mv_tables[block][best_field]; + + if(mv_table[xy][0] != mx) same=0; //FIXME check if these checks work and are any good at all + if(mv_table[xy][1]&1) same=0; + if(mv_table[xy][1]*2 != my) same=0; + if(best_field != block) same=0; + } + + field_select_tables[block][xy]= best_field; + dmin_sum += best_dmin; + } + + c->ymin<<=1; + c->ymax<<=1; + c->stride>>=1; + c->uvstride>>=1; + + if(same) + return INT_MAX; + + switch(c->avctx->mb_cmp&0xFF){ + /*case FF_CMP_SSE: + return dmin_sum+ 32*s->qscale*s->qscale;*/ + case FF_CMP_RD: + return dmin_sum; + default: + return dmin_sum+ 11*c->mb_penalty_factor; + } +} + +static inline int get_penalty_factor(int lambda, int lambda2, int type){ + switch(type&0xFF){ + default: + case FF_CMP_SAD: + return lambda>>FF_LAMBDA_SHIFT; + case FF_CMP_DCT: + return (3*lambda)>>(FF_LAMBDA_SHIFT+1); + case FF_CMP_W53: + return (4*lambda)>>(FF_LAMBDA_SHIFT); + case FF_CMP_W97: + return (2*lambda)>>(FF_LAMBDA_SHIFT); + case FF_CMP_SATD: + case FF_CMP_DCT264: + return (2*lambda)>>FF_LAMBDA_SHIFT; + case FF_CMP_RD: + case FF_CMP_PSNR: + case FF_CMP_SSE: + case FF_CMP_NSSE: + return lambda2>>FF_LAMBDA_SHIFT; + case FF_CMP_BIT: + return 1; + } +} + +void ff_estimate_p_frame_motion(MpegEncContext * s, + int mb_x, int mb_y) +{ + MotionEstContext * const c= &s->me; + uint8_t *pix, *ppix; + int sum, mx, my, dmin; + int varc; ///< the variance of the block (sum of squared (p[y][x]-average)) + int vard; ///< sum of squared differences with the estimated motion vector + int P[10][2]; + const int shift= 1+s->quarter_sample; + int mb_type=0; + Picture * const pic= &s->current_picture; + + init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0); + + av_assert0(s->quarter_sample==0 || s->quarter_sample==1); + av_assert0(s->linesize == c->stride); + av_assert0(s->uvlinesize == c->uvstride); + + c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp); + c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp); + c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp); + c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV; + + get_limits(s, 16*mb_x, 16*mb_y); + c->skip=0; + + /* intra / predictive decision */ + pix = c->src[0][0]; + sum = s->dsp.pix_sum(pix, s->linesize); + varc = s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)sum*sum)>>8) + 500; + + pic->mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8; + pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8; + c->mb_var_sum_temp += (varc+128)>>8; + + switch(s->me_method) { + case ME_ZERO: + default: + mx = 0; + my = 0; + dmin = 0; + break; + case ME_X1: + case ME_EPZS: + { + const int mot_stride = s->b8_stride; + const int mot_xy = s->block_index[0]; + + P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0]; + P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1]; + + if(P_LEFT[0] > (c->xmax<xmax<first_slice_line) { + P_TOP[0] = s->current_picture.motion_val[0][mot_xy - mot_stride ][0]; + P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1]; + P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][0]; + P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][1]; + if(P_TOP[1] > (c->ymax<ymax<xmin<xmin< (c->ymax<ymax<out_format == FMT_H263){ + c->pred_x = P_MEDIAN[0]; + c->pred_y = P_MEDIAN[1]; + }else { /* mpeg1 at least */ + c->pred_x= P_LEFT[0]; + c->pred_y= P_LEFT[1]; + } + }else{ + c->pred_x= P_LEFT[0]; + c->pred_y= P_LEFT[1]; + } + + } + dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16); + + break; + } + + /* At this point (mx,my) are full-pell and the relative displacement */ + ppix = c->ref[0][0] + (my * s->linesize) + mx; + + vard = s->dsp.sse[0](NULL, pix, ppix, s->linesize, 16); + + pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8; + c->mc_mb_var_sum_temp += (vard+128)>>8; + + if(mb_type){ + int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100); + int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20; + c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score); + + if(mb_type == CANDIDATE_MB_TYPE_INTER){ + c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); + set_p_mv_tables(s, mx, my, 1); + }else{ + mx <<=shift; + my <<=shift; + } + if(mb_type == CANDIDATE_MB_TYPE_INTER4V){ + h263_mv4_search(s, mx, my, shift); + + set_p_mv_tables(s, mx, my, 0); + } + if(mb_type == CANDIDATE_MB_TYPE_INTER_I){ + interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 1); + } + }else if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){ + int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100); + int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20; + c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score); + + if (vard*2 + 200*256 > varc) + mb_type|= CANDIDATE_MB_TYPE_INTRA; + if (varc*2 + 200*256 > vard || s->qscale > 24){ +// if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){ + mb_type|= CANDIDATE_MB_TYPE_INTER; + c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); + if(s->flags&CODEC_FLAG_MV0) + if(mx || my) + mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference + }else{ + mx <<=shift; + my <<=shift; + } + if((s->flags&CODEC_FLAG_4MV) + && !c->skip && varc>50<<8 && vard>10<<8){ + if(h263_mv4_search(s, mx, my, shift) < INT_MAX) + mb_type|=CANDIDATE_MB_TYPE_INTER4V; + + set_p_mv_tables(s, mx, my, 0); + }else + set_p_mv_tables(s, mx, my, 1); + if((s->flags&CODEC_FLAG_INTERLACED_ME) + && !c->skip){ //FIXME varc/d checks + if(interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX) + mb_type |= CANDIDATE_MB_TYPE_INTER_I; + } + }else{ + int intra_score, i; + mb_type= CANDIDATE_MB_TYPE_INTER; + + dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); + if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip) + dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1); + + if((s->flags&CODEC_FLAG_4MV) + && !c->skip && varc>50<<8 && vard>10<<8){ + int dmin4= h263_mv4_search(s, mx, my, shift); + if(dmin4 < dmin){ + mb_type= CANDIDATE_MB_TYPE_INTER4V; + dmin=dmin4; + } + } + if((s->flags&CODEC_FLAG_INTERLACED_ME) + && !c->skip){ //FIXME varc/d checks + int dmin_i= interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0); + if(dmin_i < dmin){ + mb_type = CANDIDATE_MB_TYPE_INTER_I; + dmin= dmin_i; + } + } + + set_p_mv_tables(s, mx, my, mb_type!=CANDIDATE_MB_TYPE_INTER4V); + + /* get intra luma score */ + if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){ + intra_score= varc - 500; + }else{ + unsigned mean = (sum+128)>>8; + mean*= 0x01010101; + + for(i=0; i<16; i++){ + *(uint32_t*)(&c->scratchpad[i*s->linesize+ 0]) = mean; + *(uint32_t*)(&c->scratchpad[i*s->linesize+ 4]) = mean; + *(uint32_t*)(&c->scratchpad[i*s->linesize+ 8]) = mean; + *(uint32_t*)(&c->scratchpad[i*s->linesize+12]) = mean; + } + + intra_score= s->dsp.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16); + } + intra_score += c->mb_penalty_factor*16; + + if(intra_score < dmin){ + mb_type= CANDIDATE_MB_TYPE_INTRA; + s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup + }else + s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = 0; + + { + int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100); + int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20; + c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score); + } + } + + s->mb_type[mb_y*s->mb_stride + mb_x]= mb_type; +} + +int ff_pre_estimate_p_frame_motion(MpegEncContext * s, + int mb_x, int mb_y) +{ + MotionEstContext * const c= &s->me; + int mx, my, dmin; + int P[10][2]; + const int shift= 1+s->quarter_sample; + const int xy= mb_x + mb_y*s->mb_stride; + init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0); + + av_assert0(s->quarter_sample==0 || s->quarter_sample==1); + + c->pre_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp); + c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV; + + get_limits(s, 16*mb_x, 16*mb_y); + c->skip=0; + + P_LEFT[0] = s->p_mv_table[xy + 1][0]; + P_LEFT[1] = s->p_mv_table[xy + 1][1]; + + if(P_LEFT[0] < (c->xmin<xmin<first_slice_line) { + c->pred_x= P_LEFT[0]; + c->pred_y= P_LEFT[1]; + P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]= + P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME + } else { + P_TOP[0] = s->p_mv_table[xy + s->mb_stride ][0]; + P_TOP[1] = s->p_mv_table[xy + s->mb_stride ][1]; + P_TOPRIGHT[0] = s->p_mv_table[xy + s->mb_stride - 1][0]; + P_TOPRIGHT[1] = s->p_mv_table[xy + s->mb_stride - 1][1]; + if(P_TOP[1] < (c->ymin<ymin< (c->xmax<xmax<ymin<ymin<pred_x = P_MEDIAN[0]; + c->pred_y = P_MEDIAN[1]; + } + + dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16); + + s->p_mv_table[xy][0] = mx<p_mv_table[xy][1] = my<me; + int mx, my, dmin; + int P[10][2]; + const int shift= 1+s->quarter_sample; + const int mot_stride = s->mb_stride; + const int mot_xy = mb_y*mot_stride + mb_x; + uint8_t * const mv_penalty= c->mv_penalty[f_code] + MAX_MV; + int mv_scale; + + c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp); + c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp); + c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp); + c->current_mv_penalty= mv_penalty; + + get_limits(s, 16*mb_x, 16*mb_y); + + switch(s->me_method) { + case ME_ZERO: + default: + mx = 0; + my = 0; + dmin = 0; + break; + case ME_X1: + case ME_EPZS: + P_LEFT[0] = mv_table[mot_xy - 1][0]; + P_LEFT[1] = mv_table[mot_xy - 1][1]; + + if (P_LEFT[0] > (c->xmax << shift)) P_LEFT[0] = (c->xmax << shift); + + /* special case for first line */ + if (!s->first_slice_line) { + P_TOP[0] = mv_table[mot_xy - mot_stride ][0]; + P_TOP[1] = mv_table[mot_xy - mot_stride ][1]; + P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0]; + P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1]; + if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift); + if (P_TOPRIGHT[0] < (c->xmin << shift)) P_TOPRIGHT[0] = (c->xmin << shift); + if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift); + + P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]); + P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]); + } + c->pred_x = P_LEFT[0]; + c->pred_y = P_LEFT[1]; + + if(mv_table == s->b_forw_mv_table){ + mv_scale= (s->pb_time<<16) / (s->pp_time<pb_time - s->pp_time)<<16) / (s->pp_time<p_mv_table, mv_scale, 0, 16); + + break; + } + + dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16); + + if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip) + dmin= get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1); + +// s->mb_type[mb_y*s->mb_width + mb_x]= mb_type; + mv_table[mot_xy][0]= mx; + mv_table[mot_xy][1]= my; + + return dmin; +} + +static inline int check_bidir_mv(MpegEncContext * s, + int motion_fx, int motion_fy, + int motion_bx, int motion_by, + int pred_fx, int pred_fy, + int pred_bx, int pred_by, + int size, int h) +{ + //FIXME optimize? + //FIXME better f_code prediction (max mv & distance) + //FIXME pointers + MotionEstContext * const c= &s->me; + uint8_t * const mv_penalty_f= c->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame + uint8_t * const mv_penalty_b= c->mv_penalty[s->b_code] + MAX_MV; // f_code of the prev frame + int stride= c->stride; + uint8_t *dest_y = c->scratchpad; + uint8_t *ptr; + int dxy; + int src_x, src_y; + int fbmin; + uint8_t **src_data= c->src[0]; + uint8_t **ref_data= c->ref[0]; + uint8_t **ref2_data= c->ref[2]; + + if(s->quarter_sample){ + dxy = ((motion_fy & 3) << 2) | (motion_fx & 3); + src_x = motion_fx >> 2; + src_y = motion_fy >> 2; + + ptr = ref_data[0] + (src_y * stride) + src_x; + s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , stride); + + dxy = ((motion_by & 3) << 2) | (motion_bx & 3); + src_x = motion_bx >> 2; + src_y = motion_by >> 2; + + ptr = ref2_data[0] + (src_y * stride) + src_x; + s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y , ptr , stride); + }else{ + dxy = ((motion_fy & 1) << 1) | (motion_fx & 1); + src_x = motion_fx >> 1; + src_y = motion_fy >> 1; + + ptr = ref_data[0] + (src_y * stride) + src_x; + s->hdsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h); + + dxy = ((motion_by & 1) << 1) | (motion_bx & 1); + src_x = motion_bx >> 1; + src_y = motion_by >> 1; + + ptr = ref2_data[0] + (src_y * stride) + src_x; + s->hdsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h); + } + + fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor + +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor + + s->dsp.mb_cmp[size](s, src_data[0], dest_y, stride, h); //FIXME new_pic + + if(c->avctx->mb_cmp&FF_CMP_CHROMA){ + } + //FIXME CHROMA !!! + + return fbmin; +} + +/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/ +static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y) +{ + MotionEstContext * const c= &s->me; + const int mot_stride = s->mb_stride; + const int xy = mb_y *mot_stride + mb_x; + int fbmin; + int pred_fx= s->b_bidir_forw_mv_table[xy-1][0]; + int pred_fy= s->b_bidir_forw_mv_table[xy-1][1]; + int pred_bx= s->b_bidir_back_mv_table[xy-1][0]; + int pred_by= s->b_bidir_back_mv_table[xy-1][1]; + int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0]; + int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1]; + int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0]; + int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1]; + const int flags= c->sub_flags; + const int qpel= flags&FLAG_QPEL; + const int shift= 1+qpel; + const int xmin= c->xmin<ymin<xmax<ymax<avctx->bidir_refine){ + int end; + static const uint8_t limittab[5]={0,8,32,64,80}; + const int limit= limittab[s->avctx->bidir_refine]; + static const int8_t vect[][4]={ +{ 0, 0, 0, 1}, { 0, 0, 0,-1}, { 0, 0, 1, 0}, { 0, 0,-1, 0}, { 0, 1, 0, 0}, { 0,-1, 0, 0}, { 1, 0, 0, 0}, {-1, 0, 0, 0}, + +{ 0, 0, 1, 1}, { 0, 0,-1,-1}, { 0, 1, 1, 0}, { 0,-1,-1, 0}, { 1, 1, 0, 0}, {-1,-1, 0, 0}, { 1, 0, 0, 1}, {-1, 0, 0,-1}, +{ 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0}, +{ 0, 0,-1, 1}, { 0, 0, 1,-1}, { 0,-1, 1, 0}, { 0, 1,-1, 0}, {-1, 1, 0, 0}, { 1,-1, 0, 0}, { 1, 0, 0,-1}, {-1, 0, 0, 1}, +{ 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0}, + +{ 0, 1, 1, 1}, { 0,-1,-1,-1}, { 1, 1, 1, 0}, {-1,-1,-1, 0}, { 1, 1, 0, 1}, {-1,-1, 0,-1}, { 1, 0, 1, 1}, {-1, 0,-1,-1}, +{ 0,-1, 1, 1}, { 0, 1,-1,-1}, {-1, 1, 1, 0}, { 1,-1,-1, 0}, { 1, 1, 0,-1}, {-1,-1, 0, 1}, { 1, 0,-1, 1}, {-1, 0, 1,-1}, +{ 0, 1,-1, 1}, { 0,-1, 1,-1}, { 1,-1, 1, 0}, {-1, 1,-1, 0}, {-1, 1, 0, 1}, { 1,-1, 0,-1}, { 1, 0, 1,-1}, {-1, 0,-1, 1}, +{ 0, 1, 1,-1}, { 0,-1,-1, 1}, { 1, 1,-1, 0}, {-1,-1, 1, 0}, { 1,-1, 0, 1}, {-1, 1, 0,-1}, {-1, 0, 1, 1}, { 1, 0,-1,-1}, + +{ 1, 1, 1, 1}, {-1,-1,-1,-1}, +{ 1, 1, 1,-1}, {-1,-1,-1, 1}, { 1, 1,-1, 1}, {-1,-1, 1,-1}, { 1,-1, 1, 1}, {-1, 1,-1,-1}, {-1, 1, 1, 1}, { 1,-1,-1,-1}, +{ 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1}, + }; + static const uint8_t hash[]={ +HASH8( 0, 0, 0, 1), HASH8( 0, 0, 0,-1), HASH8( 0, 0, 1, 0), HASH8( 0, 0,-1, 0), HASH8( 0, 1, 0, 0), HASH8( 0,-1, 0, 0), HASH8( 1, 0, 0, 0), HASH8(-1, 0, 0, 0), + +HASH8( 0, 0, 1, 1), HASH8( 0, 0,-1,-1), HASH8( 0, 1, 1, 0), HASH8( 0,-1,-1, 0), HASH8( 1, 1, 0, 0), HASH8(-1,-1, 0, 0), HASH8( 1, 0, 0, 1), HASH8(-1, 0, 0,-1), +HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0), +HASH8( 0, 0,-1, 1), HASH8( 0, 0, 1,-1), HASH8( 0,-1, 1, 0), HASH8( 0, 1,-1, 0), HASH8(-1, 1, 0, 0), HASH8( 1,-1, 0, 0), HASH8( 1, 0, 0,-1), HASH8(-1, 0, 0, 1), +HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0), + +HASH8( 0, 1, 1, 1), HASH8( 0,-1,-1,-1), HASH8( 1, 1, 1, 0), HASH8(-1,-1,-1, 0), HASH8( 1, 1, 0, 1), HASH8(-1,-1, 0,-1), HASH8( 1, 0, 1, 1), HASH8(-1, 0,-1,-1), +HASH8( 0,-1, 1, 1), HASH8( 0, 1,-1,-1), HASH8(-1, 1, 1, 0), HASH8( 1,-1,-1, 0), HASH8( 1, 1, 0,-1), HASH8(-1,-1, 0, 1), HASH8( 1, 0,-1, 1), HASH8(-1, 0, 1,-1), +HASH8( 0, 1,-1, 1), HASH8( 0,-1, 1,-1), HASH8( 1,-1, 1, 0), HASH8(-1, 1,-1, 0), HASH8(-1, 1, 0, 1), HASH8( 1,-1, 0,-1), HASH8( 1, 0, 1,-1), HASH8(-1, 0,-1, 1), +HASH8( 0, 1, 1,-1), HASH8( 0,-1,-1, 1), HASH8( 1, 1,-1, 0), HASH8(-1,-1, 1, 0), HASH8( 1,-1, 0, 1), HASH8(-1, 1, 0,-1), HASH8(-1, 0, 1, 1), HASH8( 1, 0,-1,-1), + +HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1), +HASH8( 1, 1, 1,-1), HASH8(-1,-1,-1, 1), HASH8( 1, 1,-1, 1), HASH8(-1,-1, 1,-1), HASH8( 1,-1, 1, 1), HASH8(-1, 1,-1,-1), HASH8(-1, 1, 1, 1), HASH8( 1,-1,-1,-1), +HASH8( 1, 1,-1,-1), HASH8(-1,-1, 1, 1), HASH8( 1,-1,-1, 1), HASH8(-1, 1, 1,-1), HASH8( 1,-1, 1,-1), HASH8(-1, 1,-1, 1), +}; + +#define CHECK_BIDIR(fx,fy,bx,by)\ + if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\ + &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\ + &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\ + int score;\ + map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\ + score= check_bidir_mv(s, motion_fx+fx, motion_fy+fy, motion_bx+bx, motion_by+by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);\ + if(score < fbmin){\ + hashidx += HASH(fx,fy,bx,by);\ + fbmin= score;\ + motion_fx+=fx;\ + motion_fy+=fy;\ + motion_bx+=bx;\ + motion_by+=by;\ + end=0;\ + }\ + } +#define CHECK_BIDIR2(a,b,c,d)\ +CHECK_BIDIR(a,b,c,d)\ +CHECK_BIDIR(-(a),-(b),-(c),-(d)) + + do{ + int i; + int borderdist=0; + end=1; + + CHECK_BIDIR2(0,0,0,1) + CHECK_BIDIR2(0,0,1,0) + CHECK_BIDIR2(0,1,0,0) + CHECK_BIDIR2(1,0,0,0) + + for(i=8; ib_bidir_forw_mv_table[xy][0]= motion_fx; + s->b_bidir_forw_mv_table[xy][1]= motion_fy; + s->b_bidir_back_mv_table[xy][0]= motion_bx; + s->b_bidir_back_mv_table[xy][1]= motion_by; + + return fbmin; +} + +static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y) +{ + MotionEstContext * const c= &s->me; + int P[10][2]; + const int mot_stride = s->mb_stride; + const int mot_xy = mb_y*mot_stride + mb_x; + const int shift= 1+s->quarter_sample; + int dmin, i; + const int time_pp= s->pp_time; + const int time_pb= s->pb_time; + int mx, my, xmin, xmax, ymin, ymax; + int16_t (*mv_table)[2]= s->b_direct_mv_table; + + c->current_mv_penalty= c->mv_penalty[1] + MAX_MV; + ymin= xmin=(-32)>>shift; + ymax= xmax= 31>>shift; + + if (IS_8X8(s->next_picture.mb_type[mot_xy])) { + s->mv_type= MV_TYPE_8X8; + }else{ + s->mv_type= MV_TYPE_16X16; + } + + for(i=0; i<4; i++){ + int index= s->block_index[i]; + int min, max; + + c->co_located_mv[i][0] = s->next_picture.motion_val[0][index][0]; + c->co_located_mv[i][1] = s->next_picture.motion_val[0][index][1]; + c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3)); + c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3)); +// c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3); +// c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3); + + max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift; + min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift; + max+= 16*mb_x + 1; // +-1 is for the simpler rounding + min+= 16*mb_x - 1; + xmax= FFMIN(xmax, s->width - max); + xmin= FFMAX(xmin, - 16 - min); + + max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift; + min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift; + max+= 16*mb_y + 1; // +-1 is for the simpler rounding + min+= 16*mb_y - 1; + ymax= FFMIN(ymax, s->height - max); + ymin= FFMAX(ymin, - 16 - min); + + if(s->mv_type == MV_TYPE_16X16) break; + } + + av_assert2(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16); + + if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){ + s->b_direct_mv_table[mot_xy][0]= 0; + s->b_direct_mv_table[mot_xy][1]= 0; + + return 256*256*256*64; + } + + c->xmin= xmin; + c->ymin= ymin; + c->xmax= xmax; + c->ymax= ymax; + c->flags |= FLAG_DIRECT; + c->sub_flags |= FLAG_DIRECT; + c->pred_x=0; + c->pred_y=0; + + P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin<first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped + P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin<sub_flags&FLAG_QPEL) + dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); + else + dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16); + + if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip) + dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1); + + get_limits(s, 16*mb_x, 16*mb_y); //restore c->?min/max, maybe not needed + + mv_table[mot_xy][0]= mx; + mv_table[mot_xy][1]= my; + c->flags &= ~FLAG_DIRECT; + c->sub_flags &= ~FLAG_DIRECT; + + return dmin; +} + +void ff_estimate_b_frame_motion(MpegEncContext * s, + int mb_x, int mb_y) +{ + MotionEstContext * const c= &s->me; + const int penalty_factor= c->mb_penalty_factor; + int fmin, bmin, dmin, fbmin, bimin, fimin; + int type=0; + const int xy = mb_y*s->mb_stride + mb_x; + init_ref(c, s->new_picture.f.data, s->last_picture.f.data, + s->next_picture.f.data, 16 * mb_x, 16 * mb_y, 2); + + get_limits(s, 16*mb_x, 16*mb_y); + + c->skip=0; + + if (s->codec_id == AV_CODEC_ID_MPEG4 && s->next_picture.mbskip_table[xy]) { + int score= direct_search(s, mb_x, mb_y); //FIXME just check 0,0 + + score= ((unsigned)(score*score + 128*256))>>16; + c->mc_mb_var_sum_temp += score; + s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE + s->mb_type[mb_y*s->mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0; + + return; + } + + if (s->codec_id == AV_CODEC_ID_MPEG4) + dmin= direct_search(s, mb_x, mb_y); + else + dmin= INT_MAX; +//FIXME penalty stuff for non mpeg4 + c->skip=0; + fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) + 3*penalty_factor; + + c->skip=0; + bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) + 2*penalty_factor; + av_dlog(s, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]); + + c->skip=0; + fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor; + av_dlog(s, "%d %d %d %d\n", dmin, fmin, bmin, fbmin); + + if(s->flags & CODEC_FLAG_INTERLACED_ME){ +//FIXME mb type penalty + c->skip=0; + c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV; + fimin= interlaced_search(s, 0, + s->b_field_mv_table[0], s->b_field_select_table[0], + s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0); + c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV; + bimin= interlaced_search(s, 2, + s->b_field_mv_table[1], s->b_field_select_table[1], + s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0); + }else + fimin= bimin= INT_MAX; + + { + int score= fmin; + type = CANDIDATE_MB_TYPE_FORWARD; + + if (dmin <= score){ + score = dmin; + type = CANDIDATE_MB_TYPE_DIRECT; + } + if(bmin>16; + c->mc_mb_var_sum_temp += score; + s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE + } + + if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){ + type= CANDIDATE_MB_TYPE_FORWARD | CANDIDATE_MB_TYPE_BACKWARD | CANDIDATE_MB_TYPE_BIDIR | CANDIDATE_MB_TYPE_DIRECT; + if(fimin < INT_MAX) + type |= CANDIDATE_MB_TYPE_FORWARD_I; + if(bimin < INT_MAX) + type |= CANDIDATE_MB_TYPE_BACKWARD_I; + if(fimin < INT_MAX && bimin < INT_MAX){ + type |= CANDIDATE_MB_TYPE_BIDIR_I; + } + //FIXME something smarter + if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB + if(s->codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT && s->flags&CODEC_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy]) + type |= CANDIDATE_MB_TYPE_DIRECT0; + } + + s->mb_type[mb_y*s->mb_stride + mb_x]= type; +} + +/* find best f_code for ME which do unlimited searches */ +int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type) +{ + if(s->me_method>=ME_EPZS){ + int score[8]; + int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2); + uint8_t * fcode_tab= s->fcode_tab; + int best_fcode=-1; + int best_score=-10000000; + + if(s->msmpeg4_version) + range= FFMIN(range, 16); + else if(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) + range= FFMIN(range, 256); + + for(i=0; i<8; i++) score[i]= s->mb_num*(8-i); + + for(y=0; ymb_height; y++){ + int x; + int xy= y*s->mb_stride; + for(x=0; xmb_width; x++){ + if(s->mb_type[xy] & type){ + int mx= mv_table[xy][0]; + int my= mv_table[xy][1]; + int fcode= FFMAX(fcode_tab[mx + MAX_MV], + fcode_tab[my + MAX_MV]); + int j; + + if(mx >= range || mx < -range || + my >= range || my < -range) + continue; + + for(j=0; jpict_type==AV_PICTURE_TYPE_B || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy]) + score[j]-= 170; + } + } + xy++; + } + } + + for(i=1; i<8; i++){ + if(score[i] > best_score){ + best_score= score[i]; + best_fcode= i; + } + } + + return best_fcode; + }else{ + return 1; + } +} + +void ff_fix_long_p_mvs(MpegEncContext * s) +{ + MotionEstContext * const c= &s->me; + const int f_code= s->f_code; + int y, range; + av_assert0(s->pict_type==AV_PICTURE_TYPE_P); + + range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code); + + av_assert0(range <= 16 || !s->msmpeg4_version); + av_assert0(range <=256 || !(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)); + + if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range; + + if(s->flags&CODEC_FLAG_4MV){ + const int wrap= s->b8_stride; + + /* clip / convert to intra 8x8 type MVs */ + for(y=0; ymb_height; y++){ + int xy= y*2*wrap; + int i= y*s->mb_stride; + int x; + + for(x=0; xmb_width; x++){ + if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){ + int block; + for(block=0; block<4; block++){ + int off= (block& 1) + (block>>1)*wrap; + int mx = s->current_picture.motion_val[0][ xy + off ][0]; + int my = s->current_picture.motion_val[0][ xy + off ][1]; + + if( mx >=range || mx <-range + || my >=range || my <-range){ + s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V; + s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA; + s->current_picture.mb_type[i] = CANDIDATE_MB_TYPE_INTRA; + } + } + } + xy+=2; + i++; + } + } + } +} + +/** + * + * @param truncate 1 for truncation, 0 for using intra + */ +void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select, + int16_t (*mv_table)[2], int f_code, int type, int truncate) +{ + MotionEstContext * const c= &s->me; + int y, h_range, v_range; + + // RAL: 8 in MPEG-1, 16 in MPEG-4 + int range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code); + + if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range; + + h_range= range; + v_range= field_select_table ? range>>1 : range; + + /* clip / convert to intra 16x16 type MVs */ + for(y=0; ymb_height; y++){ + int x; + int xy= y*s->mb_stride; + for(x=0; xmb_width; x++){ + if (s->mb_type[xy] & type){ // RAL: "type" test added... + if(field_select_table==NULL || field_select_table[xy] == field_select){ + if( mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range + || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){ + + if(truncate){ + if (mv_table[xy][0] > h_range-1) mv_table[xy][0]= h_range-1; + else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range; + if (mv_table[xy][1] > v_range-1) mv_table[xy][1]= v_range-1; + else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range; + }else{ + s->mb_type[xy] &= ~type; + s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA; + mv_table[xy][0]= + mv_table[xy][1]= 0; + } + } + } + } + xy++; + } + } +} diff --git a/ffmpeg/libavcodec/motion_est_template.c b/ffmpeg/libavcodec/motion_est_template.c new file mode 100644 index 0000000..3123edc --- /dev/null +++ b/ffmpeg/libavcodec/motion_est_template.c @@ -0,0 +1,1103 @@ +/* + * Motion estimation + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * Motion estimation template. + */ + +//Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...) +#define LOAD_COMMON\ + uint32_t av_unused * const score_map= c->score_map;\ + const int av_unused xmin= c->xmin;\ + const int av_unused ymin= c->ymin;\ + const int av_unused xmax= c->xmax;\ + const int av_unused ymax= c->ymax;\ + uint8_t *mv_penalty= c->current_mv_penalty;\ + const int pred_x= c->pred_x;\ + const int pred_y= c->pred_y;\ + +#define CHECK_HALF_MV(dx, dy, x, y)\ +{\ + const int hx= 2*(x)+(dx);\ + const int hy= 2*(y)+(dy);\ + d= cmp_hpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\ + d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\ + COPY3_IF_LT(dmin, d, bx, hx, by, hy)\ +} + +static int hpel_motion_search(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int dmin, + int src_index, int ref_index, + int size, int h) +{ + MotionEstContext * const c= &s->me; + const int mx = *mx_ptr; + const int my = *my_ptr; + const int penalty_factor= c->sub_penalty_factor; + me_cmp_func cmp_sub, chroma_cmp_sub; + int bx=2*mx, by=2*my; + + LOAD_COMMON + int flags= c->sub_flags; + + //FIXME factorize + + cmp_sub= s->dsp.me_sub_cmp[size]; + chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; + + if(c->skip){ //FIXME move out of hpel? + *mx_ptr = 0; + *my_ptr = 0; + return dmin; + } + + if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ + dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); + if(mx || my || size>0) + dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; + } + + if (mx > xmin && mx < xmax && + my > ymin && my < ymax) { + int d= dmin; + const int index= (my<penalty_factor; + const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)] + + (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor; + const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)] + + (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor; + const int b= score_map[(index+(1<penalty_factor; + +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 + unsigned key; + unsigned map_generation= c->map_generation; + key= ((my-1)<map[(index-(1<map[(index+(1<map[(index+1)&(ME_MAP_SIZE-1)] == key); + key= ((my)<map[(index-1)&(ME_MAP_SIZE-1)] == key); +#endif + if(t<=b){ + CHECK_HALF_MV(0, 1, mx ,my-1) + if(l<=r){ + CHECK_HALF_MV(1, 1, mx-1, my-1) + if(t+r<=b+l){ + CHECK_HALF_MV(1, 1, mx , my-1) + }else{ + CHECK_HALF_MV(1, 1, mx-1, my ) + } + CHECK_HALF_MV(1, 0, mx-1, my ) + }else{ + CHECK_HALF_MV(1, 1, mx , my-1) + if(t+l<=b+r){ + CHECK_HALF_MV(1, 1, mx-1, my-1) + }else{ + CHECK_HALF_MV(1, 1, mx , my ) + } + CHECK_HALF_MV(1, 0, mx , my ) + } + }else{ + if(l<=r){ + if(t+l<=b+r){ + CHECK_HALF_MV(1, 1, mx-1, my-1) + }else{ + CHECK_HALF_MV(1, 1, mx , my ) + } + CHECK_HALF_MV(1, 0, mx-1, my) + CHECK_HALF_MV(1, 1, mx-1, my) + }else{ + if(t+r<=b+l){ + CHECK_HALF_MV(1, 1, mx , my-1) + }else{ + CHECK_HALF_MV(1, 1, mx-1, my) + } + CHECK_HALF_MV(1, 0, mx , my) + CHECK_HALF_MV(1, 1, mx , my) + } + CHECK_HALF_MV(0, 1, mx , my) + } + av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2); + } + + *mx_ptr = bx; + *my_ptr = by; + + return dmin; +} + +static int no_sub_motion_search(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int dmin, + int src_index, int ref_index, + int size, int h) +{ + (*mx_ptr)<<=1; + (*my_ptr)<<=1; + return dmin; +} + +static inline int get_mb_score(MpegEncContext *s, int mx, int my, + int src_index, int ref_index, int size, + int h, int add_rate) +{ +// const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp; + MotionEstContext * const c= &s->me; + const int penalty_factor= c->mb_penalty_factor; + const int flags= c->mb_flags; + const int qpel= flags & FLAG_QPEL; + const int mask= 1+2*qpel; + me_cmp_func cmp_sub, chroma_cmp_sub; + int d; + + LOAD_COMMON + + //FIXME factorize + + cmp_sub= s->dsp.mb_cmp[size]; + chroma_cmp_sub= s->dsp.mb_cmp[size+1]; + + d= cmp(s, mx>>(qpel+1), my>>(qpel+1), mx&mask, my&mask, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); + //FIXME check cbp before adding penalty for (0,0) vector + if(add_rate && (mx || my || size>0)) + d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor; + + return d; +} + +int ff_get_mb_score(MpegEncContext *s, int mx, int my, int src_index, + int ref_index, int size, int h, int add_rate) +{ + return get_mb_score(s, mx, my, src_index, ref_index, size, h, add_rate); +} + +#define CHECK_QUARTER_MV(dx, dy, x, y)\ +{\ + const int hx= 4*(x)+(dx);\ + const int hy= 4*(y)+(dy);\ + d= cmp_qpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ + d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\ + COPY3_IF_LT(dmin, d, bx, hx, by, hy)\ +} + +static int qpel_motion_search(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int dmin, + int src_index, int ref_index, + int size, int h) +{ + MotionEstContext * const c= &s->me; + const int mx = *mx_ptr; + const int my = *my_ptr; + const int penalty_factor= c->sub_penalty_factor; + const unsigned map_generation = c->map_generation; + const int subpel_quality= c->avctx->me_subpel_quality; + uint32_t *map= c->map; + me_cmp_func cmpf, chroma_cmpf; + me_cmp_func cmp_sub, chroma_cmp_sub; + + LOAD_COMMON + int flags= c->sub_flags; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME + //FIXME factorize + + cmp_sub= s->dsp.me_sub_cmp[size]; + chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; + + if(c->skip){ //FIXME somehow move up (benchmark) + *mx_ptr = 0; + *my_ptr = 0; + return dmin; + } + + if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ + dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); + if(mx || my || size>0) + dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor; + } + + if (mx > xmin && mx < xmax && + my > ymin && my < ymax) { + int bx=4*mx, by=4*my; + int d= dmin; + int i, nx, ny; + const int index= (my<me.dia_size>=2){ + const int tl= score_map[(index-(1<>10; + int i; + + if((nx&3)==0 && (ny&3)==0) continue; + + score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor; + +// if(nx&1) score-=1024*c->penalty_factor; +// if(ny&1) score-=1024*c->penalty_factor; + + for(i=0; i<8; i++){ + if(score < best[i]){ + memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); + memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); + best[i]= score; + best_pos[i][0]= nx + 4*mx; + best_pos[i][1]= ny + 4*my; + break; + } + } + } + } + }else{ + int tl; + //FIXME this could overflow (unlikely though) + const int cx = 4*(r - l); + const int cx2= r + l - 2*c; + const int cy = 4*(b - t); + const int cy2= b + t - 2*c; + int cxy; + + if(map[(index-(1<penalty_factor; + // if(ny&1) score-=32*c->penalty_factor; + + for(i=0; i<8; i++){ + if(score < best[i]){ + memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); + memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); + best[i]= score; + best_pos[i][0]= nx + 4*mx; + best_pos[i][1]= ny + 4*my; + break; + } + } + } + } + } + for(i=0; i>2, ny>>2) + } + + av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4); + + *mx_ptr = bx; + *my_ptr = by; + }else{ + *mx_ptr =4*mx; + *my_ptr =4*my; + } + + return dmin; +} + + +#define CHECK_MV(x,y)\ +{\ + const unsigned key = ((y)<= xmin);\ + av_assert2((x) <= xmax);\ + av_assert2((y) >= ymin);\ + av_assert2((y) <= ymax);\ + if(map[index]!=key){\ + d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ + map[index]= key;\ + score_map[index]= d;\ + d += (mv_penalty[((x)<mb_x, s->mb_y);\ +if( (x)>(xmax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\ +if( (y)<(ymin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\ +if( (y)>(ymax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\ + +#define LOAD_COMMON2\ + uint32_t *map= c->map;\ + const int qpel= flags&FLAG_QPEL;\ + const int shift= 1+qpel;\ + +static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, + int src_index, int ref_index, int const penalty_factor, + int size, int h, int flags) +{ + MotionEstContext * const c= &s->me; + me_cmp_func cmpf, chroma_cmpf; + int next_dir=-1; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + { /* ensure that the best point is in the MAP as h/qpel refinement needs it */ + const unsigned key = (best[1]<xmin) CHECK_MV_DIR(x-1, y , 0) + if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1) + if(dir!=0 && xme; + me_cmp_func cmpf, chroma_cmpf; + int dia_size; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + for(dia_size=1; dia_size<=4; dia_size++){ + int dir; + const int x= best[0]; + const int y= best[1]; + + if(dia_size&(dia_size-1)) continue; + + if( x + dia_size > xmax + || x - dia_size < xmin + || y + dia_size > ymax + || y - dia_size < ymin) + continue; + + for(dir= 0; dirme; + me_cmp_func cmpf, chroma_cmpf; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + int x,y,d; + const int dec= dia_size & (dia_size-1); + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){ + do{ + x= best[0]; + y= best[1]; + + CHECK_CLIPPED_MV(x -dia_size , y); + CHECK_CLIPPED_MV(x+ dia_size , y); + CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size); + CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size); + if(dia_size>1){ + CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size); + CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size); + } + }while(best[0] != x || best[1] != y); + } + + return dmin; +} + +static int l2s_dia_search(MpegEncContext * s, int *best, int dmin, + int src_index, int ref_index, int const penalty_factor, + int size, int h, int flags) +{ + MotionEstContext * const c= &s->me; + me_cmp_func cmpf, chroma_cmpf; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + int x,y,i,d; + int dia_size= c->dia_size&0xFF; + const int dec= dia_size & (dia_size-1); + static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1}, + { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}}; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){ + do{ + x= best[0]; + y= best[1]; + for(i=0; i<8; i++){ + CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size); + } + }while(best[0] != x || best[1] != y); + } + + x= best[0]; + y= best[1]; + CHECK_CLIPPED_MV(x+1, y); + CHECK_CLIPPED_MV(x, y+1); + CHECK_CLIPPED_MV(x-1, y); + CHECK_CLIPPED_MV(x, y-1); + + return dmin; +} + +static int umh_search(MpegEncContext * s, int *best, int dmin, + int src_index, int ref_index, int const penalty_factor, + int size, int h, int flags) +{ + MotionEstContext * const c= &s->me; + me_cmp_func cmpf, chroma_cmpf; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + int x,y,x2,y2, i, j, d; + const int dia_size= c->dia_size&0xFE; + static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2}, + { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2}, + {-2, 3}, { 0, 4}, { 2, 3}, + {-2,-3}, { 0,-4}, { 2,-3},}; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + x= best[0]; + y= best[1]; + for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){ + CHECK_MV(x2, y); + } + for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){ + CHECK_MV(x, y2); + } + + x= best[0]; + y= best[1]; + for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){ + for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){ + CHECK_MV(x2, y2); + } + } + +//FIXME prevent the CLIP stuff + + for(j=1; j<=dia_size/4; j++){ + for(i=0; i<16; i++){ + CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j); + } + } + + return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2); +} + +static int full_search(MpegEncContext * s, int *best, int dmin, + int src_index, int ref_index, int const penalty_factor, + int size, int h, int flags) +{ + MotionEstContext * const c= &s->me; + me_cmp_func cmpf, chroma_cmpf; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + int x,y, d; + const int dia_size= c->dia_size&0xFF; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){ + for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){ + CHECK_MV(x, y); + } + } + + x= best[0]; + y= best[1]; + d= dmin; + CHECK_CLIPPED_MV(x , y); + CHECK_CLIPPED_MV(x+1, y); + CHECK_CLIPPED_MV(x, y+1); + CHECK_CLIPPED_MV(x-1, y); + CHECK_CLIPPED_MV(x, y-1); + best[0]= x; + best[1]= y; + + return d; +} + +#define SAB_CHECK_MV(ax,ay)\ +{\ + const unsigned key = ((ay)<= minima[j].height) j++;\ +\ + memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\ +\ + minima[j].checked= 0;\ + minima[j].height= d;\ + minima[j].x= ax;\ + minima[j].y= ay;\ + \ + i=-1;\ + continue;\ + }\ + }\ +} + +#define MAX_SAB_SIZE ME_MAP_SIZE +static int sab_diamond_search(MpegEncContext * s, int *best, int dmin, + int src_index, int ref_index, int const penalty_factor, + int size, int h, int flags) +{ + MotionEstContext * const c= &s->me; + me_cmp_func cmpf, chroma_cmpf; + Minima minima[MAX_SAB_SIZE]; + const int minima_count= FFABS(c->dia_size); + int i, j; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + + av_assert1(minima_count <= MAX_SAB_SIZE); + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + /*Note j>=ME_MAP_MV_BITS; + minima[j].y= key & ((1< xmax || minima[j].x < xmin + || minima[j].y > ymax || minima[j].y < ymin) + continue; + + minima[j].checked=0; + if(minima[j].x || minima[j].y) + minima[j].height+= (mv_penalty[((minima[j].x)<= xmax || x <= xmin + || y >= ymax || y <= ymin) + continue; + + SAB_CHECK_MV(x-1, y) + SAB_CHECK_MV(x+1, y) + SAB_CHECK_MV(x , y-1) + SAB_CHECK_MV(x , y+1) + + minima[i].checked= 1; + } + + best[0]= minima[0].x; + best[1]= minima[0].y; + dmin= minima[0].height; + + if( best[0] < xmax && best[0] > xmin + && best[1] < ymax && best[1] > ymin){ + int d; + //ensure that the refernece samples for hpel refinement are in the map + CHECK_MV(best[0]-1, best[1]) + CHECK_MV(best[0]+1, best[1]) + CHECK_MV(best[0], best[1]-1) + CHECK_MV(best[0], best[1]+1) + } + return dmin; +} + +static int var_diamond_search(MpegEncContext * s, int *best, int dmin, + int src_index, int ref_index, int const penalty_factor, + int size, int h, int flags) +{ + MotionEstContext * const c= &s->me; + me_cmp_func cmpf, chroma_cmpf; + int dia_size; + LOAD_COMMON + LOAD_COMMON2 + unsigned map_generation = c->map_generation; + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + for(dia_size=1; dia_size<=c->dia_size; dia_size++){ + int dir, start, end; + const int x= best[0]; + const int y= best[1]; + + start= FFMAX(0, y + dia_size - ymax); + end = FFMIN(dia_size, xmax - x + 1); + for(dir= start; dirme; + if(c->dia_size==-1) + return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + else if(c->dia_size<-1) + return sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + else if(c->dia_size<2) + return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + else if(c->dia_size>1024) + return full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + else if(c->dia_size>768) + return umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + else if(c->dia_size>512) + return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF); + else if(c->dia_size>256) + return l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + else + return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); +} + +/** + @param P a list of candidate mvs to check before starting the + iterative search. If one of the candidates is close to the optimal mv, then + it takes fewer iterations. And it increases the chance that we find the + optimal mv. + */ +static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr, + int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], + int ref_mv_scale, int flags, int size, int h) +{ + MotionEstContext * const c= &s->me; + int best[2]={0, 0}; /**< x and y coordinates of the best motion vector. + i.e. the difference between the position of the + block currently being encoded and the position of + the block chosen to predict it from. */ + int d; ///< the score (cmp + penalty) of any given mv + int dmin; /**< the best value of d, i.e. the score + corresponding to the mv stored in best[]. */ + unsigned map_generation; + int penalty_factor; + const int ref_mv_stride= s->mb_stride; //pass as arg FIXME + const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME + me_cmp_func cmpf, chroma_cmpf; + + LOAD_COMMON + LOAD_COMMON2 + + if(c->pre_pass){ + penalty_factor= c->pre_penalty_factor; + cmpf= s->dsp.me_pre_cmp[size]; + chroma_cmpf= s->dsp.me_pre_cmp[size+1]; + }else{ + penalty_factor= c->penalty_factor; + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + } + + map_generation= update_map_generation(c); + + av_assert2(cmpf); + dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags); + map[0]= map_generation; + score_map[0]= dmin; + + //FIXME precalc first term below? + if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0) + dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor; + + /* first line */ + if (s->first_slice_line) { + CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) + }else{ + if(dmin<((h*h*s->avctx->mv0_threshold)>>8) + && ( P_LEFT[0] |P_LEFT[1] + |P_TOP[0] |P_TOP[1] + |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){ + *mx_ptr= 0; + *my_ptr= 0; + c->skip=1; + return dmin; + } + CHECK_MV( P_MEDIAN[0] >>shift , P_MEDIAN[1] >>shift) + CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1) + CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1) + CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) ) + CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) ) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) + CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift) + CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift) + CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) + } + if(dmin>h*h*4){ + if(c->pre_pass){ + CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16) + if(!s->first_slice_line) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) + }else{ + CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16) + if(s->mb_y+1end_mb_y) //FIXME replace at least with last_slice_line + CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) + } + } + + if(c->avctx->last_predictor_count){ + const int count= c->avctx->last_predictor_count; + const int xstart= FFMAX(0, s->mb_x - count); + const int ystart= FFMAX(0, s->mb_y - count); + const int xend= FFMIN(s->mb_width , s->mb_x + count + 1); + const int yend= FFMIN(s->mb_height, s->mb_y + count + 1); + int mb_y; + + for(mb_y=ystart; mb_y>16; + int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16; + + if(mx>xmax || mxymax || myme; +//FIXME convert other functions in the same way if faster + if(c->flags==0 && h==16 && size==0){ + return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16); +// case FLAG_QPEL: +// return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL); + }else{ + return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h); + } +} + +static int epzs_motion_search4(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int P[10][2], + int src_index, int ref_index, int16_t (*last_mv)[2], + int ref_mv_scale) +{ + MotionEstContext * const c= &s->me; + int best[2]={0, 0}; + int d, dmin; + unsigned map_generation; + const int penalty_factor= c->penalty_factor; + const int size=1; + const int h=8; + const int ref_mv_stride= s->mb_stride; + const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride; + me_cmp_func cmpf, chroma_cmpf; + LOAD_COMMON + int flags= c->flags; + LOAD_COMMON2 + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + map_generation= update_map_generation(c); + + dmin = 1000000; + + /* first line */ + if (s->first_slice_line) { + CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) + CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) + }else{ + CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) + //FIXME try some early stop + CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) + CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) + CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) + CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) + } + if(dmin>64*4){ + CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16) + if(s->mb_y+1end_mb_y) //FIXME replace at least with last_slice_line + CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) + } + + dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + + *mx_ptr= best[0]; + *my_ptr= best[1]; + + return dmin; +} + +//try to merge with above FIXME (needs PSNR test) +static int epzs_motion_search2(MpegEncContext * s, + int *mx_ptr, int *my_ptr, int P[10][2], + int src_index, int ref_index, int16_t (*last_mv)[2], + int ref_mv_scale) +{ + MotionEstContext * const c= &s->me; + int best[2]={0, 0}; + int d, dmin; + unsigned map_generation; + const int penalty_factor= c->penalty_factor; + const int size=0; //FIXME pass as arg + const int h=8; + const int ref_mv_stride= s->mb_stride; + const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride; + me_cmp_func cmpf, chroma_cmpf; + LOAD_COMMON + int flags= c->flags; + LOAD_COMMON2 + + cmpf= s->dsp.me_cmp[size]; + chroma_cmpf= s->dsp.me_cmp[size+1]; + + map_generation= update_map_generation(c); + + dmin = 1000000; + + /* first line */ + if (s->first_slice_line) { + CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) + CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) + }else{ + CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) + //FIXME try some early stop + CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) + CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) + CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) + CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) + CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) + } + if(dmin>64*4){ + CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16) + if(s->mb_y+1end_mb_y) //FIXME replace at least with last_slice_line + CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, + (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) + } + + dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); + + *mx_ptr= best[0]; + *my_ptr= best[1]; + + return dmin; +} diff --git a/ffmpeg/libavcodec/motionpixels.c b/ffmpeg/libavcodec/motionpixels.c new file mode 100644 index 0000000..00c1148 --- /dev/null +++ b/ffmpeg/libavcodec/motionpixels.c @@ -0,0 +1,343 @@ +/* + * Motion Pixels Video Decoder + * Copyright (c) 2008 Gregory Montoir (cyx@users.sourceforge.net) + * + * 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 "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "internal.h" + +#define MAX_HUFF_CODES 16 + +#include "motionpixels_tablegen.h" + +typedef struct HuffCode { + int code; + uint8_t size; + uint8_t delta; +} HuffCode; + +typedef struct MotionPixelsContext { + AVCodecContext *avctx; + AVFrame frame; + DSPContext dsp; + uint8_t *changes_map; + int offset_bits_len; + int codes_count, current_codes_count; + int max_codes_bits; + HuffCode codes[MAX_HUFF_CODES]; + VLC vlc; + YuvPixel *vpt, *hpt; + uint8_t gradient_scale[3]; + uint8_t *bswapbuf; + int bswapbuf_size; +} MotionPixelsContext; + +static av_cold int mp_decode_init(AVCodecContext *avctx) +{ + MotionPixelsContext *mp = avctx->priv_data; + int w4 = (avctx->width + 3) & ~3; + int h4 = (avctx->height + 3) & ~3; + + if(avctx->extradata_size < 2){ + av_log(avctx, AV_LOG_ERROR, "extradata too small\n"); + return AVERROR_INVALIDDATA; + } + + motionpixels_tableinit(); + mp->avctx = avctx; + ff_dsputil_init(&mp->dsp, avctx); + mp->changes_map = av_mallocz(avctx->width * h4); + mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1; + mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel)); + mp->hpt = av_mallocz(h4 * w4 / 16 * sizeof(YuvPixel)); + avctx->pix_fmt = AV_PIX_FMT_RGB555; + avcodec_get_frame_defaults(&mp->frame); + return 0; +} + +static void mp_read_changes_map(MotionPixelsContext *mp, GetBitContext *gb, int count, int bits_len, int read_color) +{ + uint16_t *pixels; + int offset, w, h, color = 0, x, y, i; + + while (count--) { + offset = get_bits_long(gb, mp->offset_bits_len); + w = get_bits(gb, bits_len) + 1; + h = get_bits(gb, bits_len) + 1; + if (read_color) + color = get_bits(gb, 15); + x = offset % mp->avctx->width; + y = offset / mp->avctx->width; + if (y >= mp->avctx->height) + continue; + w = FFMIN(w, mp->avctx->width - x); + h = FFMIN(h, mp->avctx->height - y); + pixels = (uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2]; + while (h--) { + mp->changes_map[offset] = w; + if (read_color) + for (i = 0; i < w; ++i) + pixels[i] = color; + offset += mp->avctx->width; + pixels += mp->frame.linesize[0] / 2; + } + } +} + +static int mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code) +{ + while (get_bits1(gb)) { + ++size; + if (size > mp->max_codes_bits) { + av_log(mp->avctx, AV_LOG_ERROR, "invalid code size %d/%d\n", size, mp->max_codes_bits); + return AVERROR_INVALIDDATA; + } + code <<= 1; + if (mp_get_code(mp, gb, size, code + 1) < 0) + return AVERROR_INVALIDDATA; + } + if (mp->current_codes_count >= MAX_HUFF_CODES) { + av_log(mp->avctx, AV_LOG_ERROR, "too many codes\n"); + return AVERROR_INVALIDDATA; + } + + mp->codes[mp->current_codes_count ].code = code; + mp->codes[mp->current_codes_count++].size = size; + return 0; +} + +static int mp_read_codes_table(MotionPixelsContext *mp, GetBitContext *gb) +{ + if (mp->codes_count == 1) { + mp->codes[0].delta = get_bits(gb, 4); + } else { + int i; + int ret; + + mp->max_codes_bits = get_bits(gb, 4); + for (i = 0; i < mp->codes_count; ++i) + mp->codes[i].delta = get_bits(gb, 4); + mp->current_codes_count = 0; + if ((ret = mp_get_code(mp, gb, 0, 0)) < 0) + return ret; + if (mp->current_codes_count < mp->codes_count) { + av_log(mp->avctx, AV_LOG_ERROR, "too few codes\n"); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + +static int mp_gradient(MotionPixelsContext *mp, int component, int v) +{ + int delta; + + delta = (v - 7) * mp->gradient_scale[component]; + mp->gradient_scale[component] = (v == 0 || v == 14) ? 2 : 1; + return delta; +} + +static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y) +{ + int color; + + color = *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2]; + return mp_rgb_yuv_table[color]; +} + +static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p) +{ + int color; + + color = mp_yuv_to_rgb(p->y, p->v, p->u, 1); + *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2] = color; +} + +static int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb) +{ + int i; + + i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1); + return mp->codes[i].delta; +} + +static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y) +{ + YuvPixel p; + const int y0 = y * mp->avctx->width; + int w, i, x = 0; + + p = mp->vpt[y]; + if (mp->changes_map[y0 + x] == 0) { + memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale)); + ++x; + } + while (x < mp->avctx->width) { + w = mp->changes_map[y0 + x]; + if (w != 0) { + if ((y & 3) == 0) { + if (mp->changes_map[y0 + x + mp->avctx->width] < w || + mp->changes_map[y0 + x + mp->avctx->width * 2] < w || + mp->changes_map[y0 + x + mp->avctx->width * 3] < w) { + for (i = (x + 3) & ~3; i < x + w; i += 4) { + mp->hpt[((y / 4) * mp->avctx->width + i) / 4] = mp_get_yuv_from_rgb(mp, i, y); + } + } + } + x += w; + memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale)); + p = mp_get_yuv_from_rgb(mp, x - 1, y); + } else { + p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb)); + p.y = av_clip(p.y, 0, 31); + if ((x & 3) == 0) { + if ((y & 3) == 0) { + p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb)); + p.v = av_clip(p.v, -32, 31); + p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb)); + p.u = av_clip(p.u, -32, 31); + mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p; + } else { + p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v; + p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u; + } + } + mp_set_rgb_from_yuv(mp, x, y, &p); + ++x; + } + } +} + +static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb) +{ + YuvPixel p; + int y, y0; + + av_assert1(mp->changes_map[0]); + + for (y = 0; y < mp->avctx->height; ++y) { + if (mp->changes_map[y * mp->avctx->width] != 0) { + memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale)); + p = mp_get_yuv_from_rgb(mp, 0, y); + } else { + p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb)); + p.y = av_clip(p.y, 0, 31); + if ((y & 3) == 0) { + p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb)); + p.v = av_clip(p.v, -32, 31); + p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb)); + p.u = av_clip(p.u, -32, 31); + } + mp->vpt[y] = p; + mp_set_rgb_from_yuv(mp, 0, y, &p); + } + } + for (y0 = 0; y0 < 2; ++y0) + for (y = y0; y < mp->avctx->height; y += 2) + mp_decode_line(mp, gb, y); +} + +static int mp_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MotionPixelsContext *mp = avctx->priv_data; + GetBitContext gb; + int i, count1, count2, sz, ret; + + if ((ret = ff_reget_buffer(avctx, &mp->frame)) < 0) + return ret; + + /* le32 bitstream msb first */ + av_fast_malloc(&mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!mp->bswapbuf) + return AVERROR(ENOMEM); + mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4); + if (buf_size & 3) + memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3); + memset(mp->bswapbuf + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + init_get_bits(&gb, mp->bswapbuf, buf_size * 8); + + memset(mp->changes_map, 0, avctx->width * avctx->height); + for (i = !(avctx->extradata[1] & 2); i < 2; ++i) { + count1 = get_bits(&gb, 12); + count2 = get_bits(&gb, 12); + mp_read_changes_map(mp, &gb, count1, 8, i); + mp_read_changes_map(mp, &gb, count2, 4, i); + } + + mp->codes_count = get_bits(&gb, 4); + if (mp->codes_count == 0) + goto end; + + if (mp->changes_map[0] == 0) { + *(uint16_t *)mp->frame.data[0] = get_bits(&gb, 15); + mp->changes_map[0] = 1; + } + if (mp_read_codes_table(mp, &gb) < 0) + goto end; + + sz = get_bits(&gb, 18); + if (avctx->extradata[0] != 5) + sz += get_bits(&gb, 18); + if (sz == 0) + goto end; + + if (mp->max_codes_bits <= 0) + goto end; + if (init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0)) + goto end; + mp_decode_frame_helper(mp, &gb); + ff_free_vlc(&mp->vlc); + +end: + if ((ret = av_frame_ref(data, &mp->frame)) < 0) + return ret; + *got_frame = 1; + return buf_size; +} + +static av_cold int mp_decode_end(AVCodecContext *avctx) +{ + MotionPixelsContext *mp = avctx->priv_data; + + av_freep(&mp->changes_map); + av_freep(&mp->vpt); + av_freep(&mp->hpt); + av_freep(&mp->bswapbuf); + av_frame_unref(&mp->frame); + + return 0; +} + +AVCodec ff_motionpixels_decoder = { + .name = "motionpixels", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MOTIONPIXELS, + .priv_data_size = sizeof(MotionPixelsContext), + .init = mp_decode_init, + .close = mp_decode_end, + .decode = mp_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Motion Pixels video"), +}; diff --git a/ffmpeg/libavcodec/motionpixels_tablegen.c b/ffmpeg/libavcodec/motionpixels_tablegen.c new file mode 100644 index 0000000..31e5cdf --- /dev/null +++ b/ffmpeg/libavcodec/motionpixels_tablegen.c @@ -0,0 +1,41 @@ +/* + * Generate a header file for hardcoded motionpixels RGB to YUV table + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#define MAX_NEG_CROP 0 +#define ff_cropTbl ((uint8_t *)NULL) +#include "motionpixels_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + motionpixels_tableinit(); + + write_fileheader(); + + printf("static const YuvPixel mp_rgb_yuv_table[1 << 15] = {\n"); + write_int8_t_2d_array(mp_rgb_yuv_table, 1 << 15, 3); + printf("};\n"); + + return 0; +} diff --git a/ffmpeg/libavcodec/motionpixels_tablegen.h b/ffmpeg/libavcodec/motionpixels_tablegen.h new file mode 100644 index 0000000..b9802e5 --- /dev/null +++ b/ffmpeg/libavcodec/motionpixels_tablegen.h @@ -0,0 +1,91 @@ +/* + * Header file for hardcoded motionpixels RGB to YUV table + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_MOTIONPIXELS_TABLEGEN_H +#define AVCODEC_MOTIONPIXELS_TABLEGEN_H + +#include + +typedef struct YuvPixel { + int8_t y, v, u; +} YuvPixel; + +static int mp_yuv_to_rgb(int y, int v, int u, int clip_rgb) { + const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int r, g, b; + + r = (1000 * y + 701 * v) / 1000; + g = (1000 * y - 357 * v - 172 * u) / 1000; + b = (1000 * y + 886 * u) / 1000; + if (clip_rgb) + return ((cm[r * 8] & 0xF8) << 7) | ((cm[g * 8] & 0xF8) << 2) | (cm[b * 8] >> 3); + if ((unsigned)r < 32 && (unsigned)g < 32 && (unsigned)b < 32) + return (r << 10) | (g << 5) | b; + return 1 << 15; +} + +#if CONFIG_HARDCODED_TABLES +#define motionpixels_tableinit() +#include "libavcodec/motionpixels_tables.h" +#else +static YuvPixel mp_rgb_yuv_table[1 << 15]; + +static void mp_set_zero_yuv(YuvPixel *p) +{ + int i, j; + + for (i = 0; i < 31; ++i) { + for (j = 31; j > i; --j) + if (!(p[j].u | p[j].v | p[j].y)) + p[j] = p[j - 1]; + for (j = 0; j < 31 - i; ++j) + if (!(p[j].u | p[j].v | p[j].y)) + p[j] = p[j + 1]; + } +} + +static void mp_build_rgb_yuv_table(YuvPixel *p) +{ + int y, v, u, i; + + for (y = 0; y <= 31; ++y) + for (v = -31; v <= 31; ++v) + for (u = -31; u <= 31; ++u) { + i = mp_yuv_to_rgb(y, v, u, 0); + if (i < (1 << 15) && !(p[i].u | p[i].v | p[i].y)) { + p[i].y = y; + p[i].v = v; + p[i].u = u; + } + } + for (i = 0; i < 1024; ++i) + mp_set_zero_yuv(p + i * 32); +} + +static void motionpixels_tableinit(void) +{ + if (!mp_rgb_yuv_table[0].u) + mp_build_rgb_yuv_table(mp_rgb_yuv_table); +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_MOTIONPIXELS_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/movsub_bsf.c b/ffmpeg/libavcodec/movsub_bsf.c new file mode 100644 index 0000000..a745190 --- /dev/null +++ b/ffmpeg/libavcodec/movsub_bsf.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008 Reimar Döffinger + * + * 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" + + +static int text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + if (buf_size > 0xffff) return 0; + *poutbuf_size = buf_size + 2; + *poutbuf = av_malloc(*poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE); + AV_WB16(*poutbuf, buf_size); + memcpy(*poutbuf + 2, buf, buf_size); + return 1; +} + +AVBitStreamFilter ff_text2movsub_bsf={ + "text2movsub", + 0, + text2movsub, +}; + +static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + if (buf_size < 2) return 0; + *poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf)); + *poutbuf = av_malloc(*poutbuf_size + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(*poutbuf, buf + 2, *poutbuf_size); + return 1; +} + +AVBitStreamFilter ff_mov2textsub_bsf={ + "mov2textsub", + 0, + mov2textsub, +}; diff --git a/ffmpeg/libavcodec/movtextdec.c b/ffmpeg/libavcodec/movtextdec.c new file mode 100644 index 0000000..05ff53a --- /dev/null +++ b/ffmpeg/libavcodec/movtextdec.c @@ -0,0 +1,116 @@ +/* + * 3GPP TS 26.245 Timed Text decoder + * Copyright (c) 2012 Philip Langdale + * + * 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 "avcodec.h" +#include "ass.h" +#include "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/bprint.h" +#include "libavutil/intreadwrite.h" + +static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end) +{ + while (text < text_end) { + switch (*text) { + case '\r': + break; + case '\n': + av_bprintf(buf, "\\N"); + break; + default: + av_bprint_chars(buf, *text, 1); + break; + } + text++; + } + + av_bprintf(buf, "\r\n"); + return 0; +} + +static int mov_text_init(AVCodecContext *avctx) { + /* + * TODO: Handle the default text style. + * NB: Most players ignore styles completely, with the result that + * it's very common to find files where the default style is broken + * and respecting it results in a worse experience than ignoring it. + */ + return ff_ass_subtitle_header_default(avctx); +} + +static int mov_text_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + int ts_start, ts_end; + AVBPrint buf; + const char *ptr = avpkt->data; + const char *end; + + if (!ptr || avpkt->size < 2) + return AVERROR_INVALIDDATA; + + /* + * A packet of size two with value zero is an empty subtitle + * used to mark the end of the previous non-empty subtitle. + * We can just drop them here as we have duration information + * already. If the value is non-zero, then it's technically a + * bad packet. + */ + if (avpkt->size == 2) + return AV_RB16(ptr) == 0 ? 0 : AVERROR_INVALIDDATA; + + /* + * The first two bytes of the packet are the length of the text string + * In complex cases, there are style descriptors appended to the string + * so we can't just assume the packet size is the string size. + */ + end = ptr + FFMIN(2 + AV_RB16(ptr), avpkt->size); + ptr += 2; + + ts_start = av_rescale_q(avpkt->pts, + avctx->time_base, + (AVRational){1,100}); + ts_end = av_rescale_q(avpkt->pts + avpkt->duration, + avctx->time_base, + (AVRational){1,100}); + + // Note that the spec recommends lines be no longer than 2048 characters. + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + text_to_ass(&buf, ptr, end); + + if (!av_bprint_is_complete(&buf)) + return AVERROR(ENOMEM); + + ff_ass_add_rect(sub, buf.str, ts_start, ts_end-ts_start, 0); + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +AVCodec ff_movtext_decoder = { + .name = "mov_text", + .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_MOV_TEXT, + .init = mov_text_init, + .decode = mov_text_decode_frame, +}; diff --git a/ffmpeg/libavcodec/movtextenc.c b/ffmpeg/libavcodec/movtextenc.c new file mode 100644 index 0000000..9b0a6c5 --- /dev/null +++ b/ffmpeg/libavcodec/movtextenc.c @@ -0,0 +1,165 @@ +/* + * 3GPP TS 26.245 Timed Text encoder + * Copyright (c) 2012 Philip Langdale + * + * 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 "avcodec.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "ass_split.h" +#include "ass.h" + +typedef struct { + ASSSplitContext *ass_ctx; + char buffer[2048]; + char *ptr; + char *end; +} MovTextContext; + + +static av_cold int mov_text_encode_init(AVCodecContext *avctx) +{ + /* + * For now, we'll use a fixed default style. When we add styling + * support, this will be generated from the ASS style. + */ + static uint8_t text_sample_entry[] = { + 0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags + 0x01, // int8_t horizontal-justification + 0xFF, // int8_t vertical-justification + 0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4] + // BoxRecord { + 0x00, 0x00, // int16_t top + 0x00, 0x00, // int16_t left + 0x00, 0x00, // int16_t bottom + 0x00, 0x00, // int16_t right + // }; + // StyleRecord { + 0x00, 0x00, // uint16_t startChar + 0x00, 0x00, // uint16_t endChar + 0x00, 0x01, // uint16_t font-ID + 0x00, // uint8_t face-style-flags + 0x12, // uint8_t font-size + 0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4] + // }; + // FontTableBox { + 0x00, 0x00, 0x00, 0x12, // uint32_t size + 'f', 't', 'a', 'b', // uint8_t name[4] + 0x00, 0x01, // uint16_t entry-count + // FontRecord { + 0x00, 0x01, // uint16_t font-ID + 0x05, // uint8_t font-name-length + 'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length] + // }; + // }; + }; + + MovTextContext *s = avctx->priv_data; + + avctx->extradata_size = sizeof text_sample_entry; + avctx->extradata = av_mallocz(avctx->extradata_size); + if (!avctx->extradata) + return AVERROR(ENOMEM); + + memcpy(avctx->extradata, text_sample_entry, avctx->extradata_size); + + s->ass_ctx = ff_ass_split(avctx->subtitle_header); + return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; +} + +static void mov_text_text_cb(void *priv, const char *text, int len) +{ + MovTextContext *s = priv; + av_assert0(s->end >= s->ptr); + av_strlcpy(s->ptr, text, FFMIN(s->end - s->ptr, len + 1)); + s->ptr += FFMIN(s->end - s->ptr, len); +} + +static void mov_text_new_line_cb(void *priv, int forced) +{ + MovTextContext *s = priv; + av_assert0(s->end >= s->ptr); + av_strlcpy(s->ptr, "\n", FFMIN(s->end - s->ptr, 2)); + if (s->end > s->ptr) + s->ptr++; +} + +static const ASSCodesCallbacks mov_text_callbacks = { + .text = mov_text_text_cb, + .new_line = mov_text_new_line_cb, +}; + +static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, + int bufsize, const AVSubtitle *sub) +{ + MovTextContext *s = avctx->priv_data; + ASSDialog *dialog; + int i, len, num; + + s->ptr = s->buffer; + s->end = s->ptr + sizeof(s->buffer); + + for (i = 0; i < sub->num_rects; i++) { + + if (sub->rects[i]->type != SUBTITLE_ASS) { + av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); + return AVERROR(ENOSYS); + } + + dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num); + for (; dialog && num--; dialog++) { + ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); + } + } + + if (s->ptr == s->buffer) + return 0; + + AV_WB16(buf, strlen(s->buffer)); + buf += 2; + + len = av_strlcpy(buf, s->buffer, bufsize - 2); + + if (len > bufsize-3) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); + return AVERROR(EINVAL); + } + + return len + 2; +} + +static int mov_text_encode_close(AVCodecContext *avctx) +{ + MovTextContext *s = avctx->priv_data; + ff_ass_split_free(s->ass_ctx); + return 0; +} + +AVCodec ff_movtext_encoder = { + .name = "mov_text", + .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_MOV_TEXT, + .priv_data_size = sizeof(MovTextContext), + .init = mov_text_encode_init, + .encode_sub = mov_text_encode_frame, + .close = mov_text_encode_close, +}; diff --git a/ffmpeg/libavcodec/mp3_header_compress_bsf.c b/ffmpeg/libavcodec/mp3_header_compress_bsf.c new file mode 100644 index 0000000..3c5e2fb --- /dev/null +++ b/ffmpeg/libavcodec/mp3_header_compress_bsf.c @@ -0,0 +1,88 @@ +/* + * copyright (c) 2006 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "mpegaudiodecheader.h" + + +static int mp3_header_compress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + uint32_t header, extraheader; + int mode_extension, header_size; + + if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ + av_log(avctx, AV_LOG_ERROR, "not standards compliant\n"); + return -1; + } + + header = AV_RB32(buf); + mode_extension= (header>>4)&3; + + if(ff_mpa_check_header(header) < 0 || (header&0x60000) != 0x20000){ +output_unchanged: + *poutbuf= (uint8_t *) buf; + *poutbuf_size= buf_size; + + av_log(avctx, AV_LOG_INFO, "cannot compress %08X\n", header); + return 0; + } + + if(avctx->extradata_size == 0){ + avctx->extradata_size=15; + avctx->extradata= av_malloc(avctx->extradata_size); + strcpy(avctx->extradata, "FFCMP3 0.0"); + memcpy(avctx->extradata+11, buf, 4); + } + if(avctx->extradata_size != 15){ + av_log(avctx, AV_LOG_ERROR, "Extradata invalid\n"); + return -1; + } + extraheader = AV_RB32(avctx->extradata+11); + if((extraheader&MP3_MASK) != (header&MP3_MASK)) + goto output_unchanged; + + header_size= (header&0x10000) ? 4 : 6; + + *poutbuf_size= buf_size - header_size; + *poutbuf= av_malloc(buf_size - header_size + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(*poutbuf, buf + header_size, buf_size - header_size + FF_INPUT_BUFFER_PADDING_SIZE); + + if(avctx->channels==2){ + if((header & (3<<19)) != 3<<19){ + (*poutbuf)[1] &= 0x3F; + (*poutbuf)[1] |= mode_extension<<6; + FFSWAP(int, (*poutbuf)[1], (*poutbuf)[2]); + }else{ + (*poutbuf)[1] &= 0x8F; + (*poutbuf)[1] |= mode_extension<<4; + } + } + + return 1; +} + +AVBitStreamFilter ff_mp3_header_compress_bsf={ + "mp3comp", + 0, + mp3_header_compress, +}; diff --git a/ffmpeg/libavcodec/mp3_header_decompress_bsf.c b/ffmpeg/libavcodec/mp3_header_decompress_bsf.c new file mode 100644 index 0000000..adf5a7f --- /dev/null +++ b/ffmpeg/libavcodec/mp3_header_decompress_bsf.c @@ -0,0 +1,98 @@ +/* + * copyright (c) 2006 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "mpegaudiodecheader.h" +#include "mpegaudiodata.h" + + +static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + uint32_t header; + int sample_rate= avctx->sample_rate; + int sample_rate_index=0; + int lsf, mpeg25, bitrate_index, frame_size; + + header = AV_RB32(buf); + if(ff_mpa_check_header(header) >= 0){ + *poutbuf= (uint8_t *) buf; + *poutbuf_size= buf_size; + + return 0; + } + + if(avctx->extradata_size != 15 || strcmp(avctx->extradata, "FFCMP3 0.0")){ + av_log(avctx, AV_LOG_ERROR, "Extradata invalid %d\n", avctx->extradata_size); + return -1; + } + + header= AV_RB32(avctx->extradata+11) & MP3_MASK; + + lsf = sample_rate < (24000+32000)/2; + mpeg25 = sample_rate < (12000+16000)/2; + sample_rate_index= (header>>10)&3; + sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off + + for(bitrate_index=2; bitrate_index<30; bitrate_index++){ + frame_size = avpriv_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; + frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); + if(frame_size == buf_size + 4) + break; + if(frame_size == buf_size + 6) + break; + } + if(bitrate_index == 30){ + av_log(avctx, AV_LOG_ERROR, "Could not find bitrate_index.\n"); + return -1; + } + + header |= (bitrate_index&1)<<9; + header |= (bitrate_index>>1)<<12; + header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0 + + *poutbuf_size= frame_size; + *poutbuf= av_malloc(frame_size + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(*poutbuf + frame_size - buf_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + + if(avctx->channels==2){ + uint8_t *p= *poutbuf + frame_size - buf_size; + if(lsf){ + FFSWAP(int, p[1], p[2]); + header |= (p[1] & 0xC0)>>2; + p[1] &= 0x3F; + }else{ + header |= p[1] & 0x30; + p[1] &= 0xCF; + } + } + + AV_WB32(*poutbuf, header); + + return 1; +} + +AVBitStreamFilter ff_mp3_header_decompress_bsf={ + "mp3decomp", + 0, + mp3_header_decompress, +}; diff --git a/ffmpeg/libavcodec/mpc.c b/ffmpeg/libavcodec/mpc.c new file mode 100644 index 0000000..3bd2d35 --- /dev/null +++ b/ffmpeg/libavcodec/mpc.c @@ -0,0 +1,99 @@ +/* + * Musepack decoder core + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Musepack decoder core + * MPEG Audio Layer 1/2 -like codec with frames of 1152 samples + * divided into 32 subbands. + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "mpegaudiodsp.h" +#include "mpegaudio.h" + +#include "mpc.h" +#include "mpcdata.h" + +void ff_mpc_init(void) +{ + ff_mpa_synth_init_fixed(ff_mpa_synth_window_fixed); +} + +/** + * Process decoded Musepack data and produce PCM + */ +static void mpc_synth(MPCContext *c, int16_t **out, int channels) +{ + int dither_state = 0; + int i, ch; + + for(ch = 0; ch < channels; ch++){ + for(i = 0; i < SAMPLES_PER_BAND; i++) { + ff_mpa_synth_filter_fixed(&c->mpadsp, + c->synth_buf[ch], &(c->synth_buf_offset[ch]), + ff_mpa_synth_window_fixed, &dither_state, + out[ch] + 32 * i, 1, + c->sb_samples[ch][i]); + } + } +} + +void ff_mpc_dequantize_and_synth(MPCContext * c, int maxband, int16_t **out, + int channels) +{ + int i, j, ch; + Band *bands = c->bands; + int off; + float mul; + + /* dequantize */ + memset(c->sb_samples, 0, sizeof(c->sb_samples)); + off = 0; + for(i = 0; i <= maxband; i++, off += SAMPLES_PER_BAND){ + for(ch = 0; ch < 2; ch++){ + if(bands[i].res[ch]){ + j = 0; + mul = (mpc_CC+1)[bands[i].res[ch]] * mpc_SCF[bands[i].scf_idx[ch][0] & 0xFF]; + for(; j < 12; j++) + c->sb_samples[ch][j][i] = mul * c->Q[ch][j + off]; + mul = (mpc_CC+1)[bands[i].res[ch]] * mpc_SCF[bands[i].scf_idx[ch][1] & 0xFF]; + for(; j < 24; j++) + c->sb_samples[ch][j][i] = mul * c->Q[ch][j + off]; + mul = (mpc_CC+1)[bands[i].res[ch]] * mpc_SCF[bands[i].scf_idx[ch][2] & 0xFF]; + for(; j < 36; j++) + c->sb_samples[ch][j][i] = mul * c->Q[ch][j + off]; + } + } + if(bands[i].msf){ + int t1, t2; + for(j = 0; j < SAMPLES_PER_BAND; j++){ + t1 = c->sb_samples[0][j][i]; + t2 = c->sb_samples[1][j][i]; + c->sb_samples[0][j][i] = t1 + t2; + c->sb_samples[1][j][i] = t1 - t2; + } + } + } + + mpc_synth(c, out, channels); +} diff --git a/ffmpeg/libavcodec/mpc.h b/ffmpeg/libavcodec/mpc.h new file mode 100644 index 0000000..295b4c7 --- /dev/null +++ b/ffmpeg/libavcodec/mpc.h @@ -0,0 +1,77 @@ +/* + * Musepack decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Musepack decoder + * MPEG Audio Layer 1/2 -like codec with frames of 1152 samples + * divided into 32 subbands. + */ + +#ifndef AVCODEC_MPC_H +#define AVCODEC_MPC_H + +#include "libavutil/lfg.h" +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "mpegaudio.h" +#include "mpegaudiodsp.h" + +#define BANDS 32 +#define SAMPLES_PER_BAND 36 +#define MPC_FRAME_SIZE (BANDS * SAMPLES_PER_BAND) + +/** Subband structure - hold all variables for each subband */ +typedef struct Band { + int msf; ///< mid-stereo flag + int res[2]; + int scfi[2]; + int scf_idx[2][3]; + int Q[2]; +}Band; + +typedef struct MPCContext { + DSPContext dsp; + MPADSPContext mpadsp; + GetBitContext gb; + int IS, MSS, gapless; + int lastframelen; + int maxbands, last_max_band; + int last_bits_used; + int oldDSCF[2][BANDS]; + Band bands[BANDS]; + int Q[2][MPC_FRAME_SIZE]; + int cur_frame, frames; + uint8_t *bits; + int buf_size; + AVLFG rnd; + int frames_to_skip; + /* for synthesis */ + DECLARE_ALIGNED(16, MPA_INT, synth_buf)[MPA_MAX_CHANNELS][512*2]; + int synth_buf_offset[MPA_MAX_CHANNELS]; + DECLARE_ALIGNED(16, int32_t, sb_samples)[MPA_MAX_CHANNELS][36][SBLIMIT]; +} MPCContext; + +void ff_mpc_init(void); +void ff_mpc_dequantize_and_synth(MPCContext *c, int maxband, int16_t **out, int channels); + +#endif /* AVCODEC_MPC_H */ diff --git a/ffmpeg/libavcodec/mpc7.c b/ffmpeg/libavcodec/mpc7.c new file mode 100644 index 0000000..85d4e09 --- /dev/null +++ b/ffmpeg/libavcodec/mpc7.c @@ -0,0 +1,343 @@ +/* + * Musepack SV7 decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * MPEG Audio Layer 1/2 -like codec with frames of 1152 samples + * divided into 32 subbands. + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/internal.h" +#include "libavutil/lfg.h" +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "internal.h" +#include "mpegaudiodsp.h" + +#include "mpc.h" +#include "mpc7data.h" + +static VLC scfi_vlc, dscf_vlc, hdr_vlc, quant_vlc[MPC7_QUANT_VLC_TABLES][2]; + +static const uint16_t quant_offsets[MPC7_QUANT_VLC_TABLES*2 + 1] = +{ + 0, 512, 1024, 1536, 2052, 2564, 3076, 3588, 4100, 4612, 5124, + 5636, 6164, 6676, 7224 +}; + + +static av_cold int mpc7_decode_init(AVCodecContext * avctx) +{ + int i, j; + MPCContext *c = avctx->priv_data; + GetBitContext gb; + LOCAL_ALIGNED_16(uint8_t, buf, [16]); + static int vlc_initialized = 0; + + static VLC_TYPE scfi_table[1 << MPC7_SCFI_BITS][2]; + static VLC_TYPE dscf_table[1 << MPC7_DSCF_BITS][2]; + static VLC_TYPE hdr_table[1 << MPC7_HDR_BITS][2]; + static VLC_TYPE quant_tables[7224][2]; + + /* Musepack SV7 is always stereo */ + if (avctx->channels != 2) { + avpriv_request_sample(avctx, "%d channels", avctx->channels); + return AVERROR_PATCHWELCOME; + } + + if(avctx->extradata_size < 16){ + av_log(avctx, AV_LOG_ERROR, "Too small extradata size (%i)!\n", avctx->extradata_size); + return -1; + } + memset(c->oldDSCF, 0, sizeof(c->oldDSCF)); + av_lfg_init(&c->rnd, 0xDEADBEEF); + ff_dsputil_init(&c->dsp, avctx); + ff_mpadsp_init(&c->mpadsp); + c->dsp.bswap_buf((uint32_t*)buf, (const uint32_t*)avctx->extradata, 4); + ff_mpc_init(); + init_get_bits(&gb, buf, 128); + + c->IS = get_bits1(&gb); + c->MSS = get_bits1(&gb); + c->maxbands = get_bits(&gb, 6); + if(c->maxbands >= BANDS){ + av_log(avctx, AV_LOG_ERROR, "Too many bands: %i\n", c->maxbands); + return -1; + } + skip_bits_long(&gb, 88); + c->gapless = get_bits1(&gb); + c->lastframelen = get_bits(&gb, 11); + av_log(avctx, AV_LOG_DEBUG, "IS: %d, MSS: %d, TG: %d, LFL: %d, bands: %d\n", + c->IS, c->MSS, c->gapless, c->lastframelen, c->maxbands); + c->frames_to_skip = 0; + + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + + if(vlc_initialized) return 0; + av_log(avctx, AV_LOG_DEBUG, "Initing VLC\n"); + scfi_vlc.table = scfi_table; + scfi_vlc.table_allocated = 1 << MPC7_SCFI_BITS; + if(init_vlc(&scfi_vlc, MPC7_SCFI_BITS, MPC7_SCFI_SIZE, + &mpc7_scfi[1], 2, 1, + &mpc7_scfi[0], 2, 1, INIT_VLC_USE_NEW_STATIC)){ + av_log(avctx, AV_LOG_ERROR, "Cannot init SCFI VLC\n"); + return -1; + } + dscf_vlc.table = dscf_table; + dscf_vlc.table_allocated = 1 << MPC7_DSCF_BITS; + if(init_vlc(&dscf_vlc, MPC7_DSCF_BITS, MPC7_DSCF_SIZE, + &mpc7_dscf[1], 2, 1, + &mpc7_dscf[0], 2, 1, INIT_VLC_USE_NEW_STATIC)){ + av_log(avctx, AV_LOG_ERROR, "Cannot init DSCF VLC\n"); + return -1; + } + hdr_vlc.table = hdr_table; + hdr_vlc.table_allocated = 1 << MPC7_HDR_BITS; + if(init_vlc(&hdr_vlc, MPC7_HDR_BITS, MPC7_HDR_SIZE, + &mpc7_hdr[1], 2, 1, + &mpc7_hdr[0], 2, 1, INIT_VLC_USE_NEW_STATIC)){ + av_log(avctx, AV_LOG_ERROR, "Cannot init HDR VLC\n"); + return -1; + } + for(i = 0; i < MPC7_QUANT_VLC_TABLES; i++){ + for(j = 0; j < 2; j++){ + quant_vlc[i][j].table = &quant_tables[quant_offsets[i*2 + j]]; + quant_vlc[i][j].table_allocated = quant_offsets[i*2 + j + 1] - quant_offsets[i*2 + j]; + if(init_vlc(&quant_vlc[i][j], 9, mpc7_quant_vlc_sizes[i], + &mpc7_quant_vlc[i][j][1], 4, 2, + &mpc7_quant_vlc[i][j][0], 4, 2, INIT_VLC_USE_NEW_STATIC)){ + av_log(avctx, AV_LOG_ERROR, "Cannot init QUANT VLC %i,%i\n",i,j); + return -1; + } + } + } + vlc_initialized = 1; + + return 0; +} + +/** + * Fill samples for given subband + */ +static inline void idx_to_quant(MPCContext *c, GetBitContext *gb, int idx, int *dst) +{ + int i, i1, t; + switch(idx){ + case -1: + for(i = 0; i < SAMPLES_PER_BAND; i++){ + *dst++ = (av_lfg_get(&c->rnd) & 0x3FC) - 510; + } + break; + case 1: + i1 = get_bits1(gb); + for(i = 0; i < SAMPLES_PER_BAND/3; i++){ + t = get_vlc2(gb, quant_vlc[0][i1].table, 9, 2); + *dst++ = mpc7_idx30[t]; + *dst++ = mpc7_idx31[t]; + *dst++ = mpc7_idx32[t]; + } + break; + case 2: + i1 = get_bits1(gb); + for(i = 0; i < SAMPLES_PER_BAND/2; i++){ + t = get_vlc2(gb, quant_vlc[1][i1].table, 9, 2); + *dst++ = mpc7_idx50[t]; + *dst++ = mpc7_idx51[t]; + } + break; + case 3: case 4: case 5: case 6: case 7: + i1 = get_bits1(gb); + for(i = 0; i < SAMPLES_PER_BAND; i++) + *dst++ = get_vlc2(gb, quant_vlc[idx-1][i1].table, 9, 2) - mpc7_quant_vlc_off[idx-1]; + break; + case 8: case 9: case 10: case 11: case 12: + case 13: case 14: case 15: case 16: case 17: + t = (1 << (idx - 2)) - 1; + for(i = 0; i < SAMPLES_PER_BAND; i++) + *dst++ = get_bits(gb, idx - 1) - t; + break; + default: // case 0 and -2..-17 + return; + } +} + +static int get_scale_idx(GetBitContext *gb, int ref) +{ + int t = get_vlc2(gb, dscf_vlc.table, MPC7_DSCF_BITS, 1) - 7; + if (t == 8) + return get_bits(gb, 6); + return ref + t; +} + +static int mpc7_decode_frame(AVCodecContext * avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size; + MPCContext *c = avctx->priv_data; + GetBitContext gb; + int i, ch; + int mb = -1; + Band *bands = c->bands; + int off, ret, last_frame, skip; + int bits_used, bits_avail; + + memset(bands, 0, sizeof(*bands) * (c->maxbands + 1)); + + buf_size = avpkt->size & ~3; + if (buf_size <= 0) { + av_log(avctx, AV_LOG_ERROR, "packet size is too small (%i bytes)\n", + avpkt->size); + return AVERROR_INVALIDDATA; + } + if (buf_size != avpkt->size) { + av_log(avctx, AV_LOG_WARNING, "packet size is not a multiple of 4. " + "extra bytes at the end will be skipped.\n"); + } + + skip = buf[0]; + last_frame = buf[1]; + buf += 4; + buf_size -= 4; + + /* get output buffer */ + frame->nb_samples = MPC_FRAME_SIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + av_fast_padded_malloc(&c->bits, &c->buf_size, buf_size); + if (!c->bits) + return AVERROR(ENOMEM); + c->dsp.bswap_buf((uint32_t *)c->bits, (const uint32_t *)buf, buf_size >> 2); + init_get_bits(&gb, c->bits, buf_size * 8); + skip_bits_long(&gb, skip); + + /* read subband indexes */ + for(i = 0; i <= c->maxbands; i++){ + for(ch = 0; ch < 2; ch++){ + int t = 4; + if(i) t = get_vlc2(&gb, hdr_vlc.table, MPC7_HDR_BITS, 1) - 5; + if(t == 4) bands[i].res[ch] = get_bits(&gb, 4); + else bands[i].res[ch] = bands[i-1].res[ch] + t; + if (bands[i].res[ch] < -1 || bands[i].res[ch] > 17) { + av_log(avctx, AV_LOG_ERROR, "subband index invalid\n"); + return AVERROR_INVALIDDATA; + } + } + + if(bands[i].res[0] || bands[i].res[1]){ + mb = i; + if(c->MSS) bands[i].msf = get_bits1(&gb); + } + } + /* get scale indexes coding method */ + for(i = 0; i <= mb; i++) + for(ch = 0; ch < 2; ch++) + if(bands[i].res[ch]) bands[i].scfi[ch] = get_vlc2(&gb, scfi_vlc.table, MPC7_SCFI_BITS, 1); + /* get scale indexes */ + for(i = 0; i <= mb; i++){ + for(ch = 0; ch < 2; ch++){ + if(bands[i].res[ch]){ + bands[i].scf_idx[ch][2] = c->oldDSCF[ch][i]; + bands[i].scf_idx[ch][0] = get_scale_idx(&gb, bands[i].scf_idx[ch][2]); + switch(bands[i].scfi[ch]){ + case 0: + bands[i].scf_idx[ch][1] = get_scale_idx(&gb, bands[i].scf_idx[ch][0]); + bands[i].scf_idx[ch][2] = get_scale_idx(&gb, bands[i].scf_idx[ch][1]); + break; + case 1: + bands[i].scf_idx[ch][1] = get_scale_idx(&gb, bands[i].scf_idx[ch][0]); + bands[i].scf_idx[ch][2] = bands[i].scf_idx[ch][1]; + break; + case 2: + bands[i].scf_idx[ch][1] = bands[i].scf_idx[ch][0]; + bands[i].scf_idx[ch][2] = get_scale_idx(&gb, bands[i].scf_idx[ch][1]); + break; + case 3: + bands[i].scf_idx[ch][2] = bands[i].scf_idx[ch][1] = bands[i].scf_idx[ch][0]; + break; + } + c->oldDSCF[ch][i] = bands[i].scf_idx[ch][2]; + } + } + } + /* get quantizers */ + memset(c->Q, 0, sizeof(c->Q)); + off = 0; + for(i = 0; i < BANDS; i++, off += SAMPLES_PER_BAND) + for(ch = 0; ch < 2; ch++) + idx_to_quant(c, &gb, bands[i].res[ch], c->Q[ch] + off); + + ff_mpc_dequantize_and_synth(c, mb, (int16_t **)frame->extended_data, 2); + if(last_frame) + frame->nb_samples = c->lastframelen; + + bits_used = get_bits_count(&gb); + bits_avail = buf_size * 8; + if (!last_frame && ((bits_avail < bits_used) || (bits_used + 32 <= bits_avail))) { + av_log(avctx, AV_LOG_ERROR, "Error decoding frame: used %i of %i bits\n", bits_used, bits_avail); + return -1; + } + if(c->frames_to_skip){ + c->frames_to_skip--; + *got_frame_ptr = 0; + return avpkt->size; + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +static void mpc7_decode_flush(AVCodecContext *avctx) +{ + MPCContext *c = avctx->priv_data; + + memset(c->oldDSCF, 0, sizeof(c->oldDSCF)); + c->frames_to_skip = 32; +} + +static av_cold int mpc7_decode_close(AVCodecContext *avctx) +{ + MPCContext *c = avctx->priv_data; + av_freep(&c->bits); + c->buf_size = 0; + return 0; +} + +AVCodec ff_mpc7_decoder = { + .name = "mpc7", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MUSEPACK7, + .priv_data_size = sizeof(MPCContext), + .init = mpc7_decode_init, + .close = mpc7_decode_close, + .decode = mpc7_decode_frame, + .flush = mpc7_decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Musepack SV7"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/mpc7data.h b/ffmpeg/libavcodec/mpc7data.h new file mode 100644 index 0000000..5609e8f --- /dev/null +++ b/ffmpeg/libavcodec/mpc7data.h @@ -0,0 +1,171 @@ +/* + * Musepack decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_MPC7DATA_H +#define AVCODEC_MPC7DATA_H + +#include + +static const int8_t mpc7_idx30[] = { -1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1,-1, 0, 1}; +static const int8_t mpc7_idx31[] = { -1,-1,-1, 0, 0, 0, 1, 1, 1,-1,-1,-1, 0, 0, 0, 1, 1, 1,-1,-1,-1, 0, 0, 0, 1, 1, 1}; +static const int8_t mpc7_idx32[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static const int8_t mpc7_idx50[] = { -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; +static const int8_t mpc7_idx51[] = { -2,-2,-2,-2,-2,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2}; + +#define MPC7_SCFI_SIZE 4 +#define MPC7_SCFI_BITS 3 +static const uint8_t mpc7_scfi[MPC7_SCFI_SIZE * 2] = { + 0x2, 3, 0x1, 1, 0x3, 3, 0x0, 2 +}; + +#define MPC7_DSCF_SIZE 16 +#define MPC7_DSCF_BITS 6 +static const uint8_t mpc7_dscf[MPC7_DSCF_SIZE * 2] = { + 0x20, 6, 0x04, 5, 0x11, 5, 0x1E, 5, 0x0D, 4, 0x00, 3, 0x03, 3, 0x09, 4, + 0x05, 3, 0x02, 3, 0x0E, 4, 0x03, 4, 0x1F, 5, 0x05, 5, 0x21, 6, 0x0C, 4 +}; + +#define MPC7_HDR_SIZE 10 +#define MPC7_HDR_BITS 9 +static const uint8_t mpc7_hdr[MPC7_HDR_SIZE * 2] = { + 0x5C, 8, 0x2F, 7, 0x0A, 5, 0x04, 4, 0x00, 2, + 0x01, 1, 0x03, 3, 0x16, 6, 0xBB, 9, 0xBA, 9 +}; + +#define MPC7_QUANT_VLC_TABLES 7 +static const uint8_t mpc7_quant_vlc_sizes[MPC7_QUANT_VLC_TABLES * 2] = { + 27, 25, 7, 9, 15, 31, 63 +}; + +static const uint8_t mpc7_quant_vlc_off[MPC7_QUANT_VLC_TABLES] = { + 0, 0, 3, 4, 7, 15, 31 +}; + +static const uint16_t mpc7_quant_vlc[MPC7_QUANT_VLC_TABLES][2][64 * 2] = { +{ + { + 0x0036, 6, 0x0009, 5, 0x0020, 6, 0x0005, 5, 0x000A, 4, 0x0007, 5, + 0x0034, 6, 0x0000, 5, 0x0023, 6, 0x000A, 5, 0x0006, 4, 0x0004, 5, + 0x000B, 4, 0x0007, 3, 0x000C, 4, 0x0003, 5, 0x0007, 4, 0x000B, 5, + 0x0022, 6, 0x0001, 5, 0x0035, 6, 0x0006, 5, 0x0009, 4, 0x0002, 5, + 0x0021, 6, 0x0008, 5, 0x0037, 6 + }, + { + 0x0067, 8, 0x003E, 7, 0x00E1, 9, 0x0037, 7, 0x0003, 4, 0x0034, 7, + 0x0065, 8, 0x003C, 7, 0x00E3, 9, 0x0018, 6, 0x0000, 4, 0x003D, 7, + 0x0004, 4, 0x0001, 1, 0x0005, 4, 0x003F, 7, 0x0001, 4, 0x003B, 7, + 0x00E2, 9, 0x0039, 7, 0x0064, 8, 0x0035, 7, 0x0002, 4, 0x0036, 7, + 0x00E0, 9, 0x003A, 7, 0x0066, 8 + } +}, +{ + { + 0x0059, 7, 0x002F, 6, 0x000F, 5, 0x0000, 5, 0x005B, 7, 0x0004, 5, + 0x0006, 4, 0x000D, 4, 0x0004, 4, 0x0005, 5, 0x0014, 5, 0x000C, 4, + 0x0004, 3, 0x000F, 4, 0x000E, 5, 0x0003, 5, 0x0003, 4, 0x000E, 4, + 0x0005, 4, 0x0001, 5, 0x005A, 7, 0x0002, 5, 0x0015, 5, 0x002E, 6, + 0x0058, 7 + }, + { + 0x0399, 10, 0x0071, 7, 0x0033, 6, 0x00E7, 8, 0x039A, 10, 0x0068, 7, + 0x001E, 5, 0x0000, 3, 0x001D, 5, 0x0069, 7, 0x0032, 6, 0x0001, 3, + 0x0002, 2, 0x0003, 3, 0x0031, 6, 0x006B, 7, 0x001B, 5, 0x0002, 3, + 0x001F, 5, 0x0070, 7, 0x0398, 10, 0x006A, 7, 0x0030, 6, 0x0072, 7, + 0x039B, 10 + } +}, +{ + { + 0x000C, 4, 0x0004, 3, 0x0000, 2, 0x0001, 2, 0x0007, 3, 0x0005, 3, 0x000D, 4 + }, + { + 0x0004, 5, 0x0003, 4, 0x0002, 2, 0x0003, 2, 0x0001, 2, 0x0000, 3, 0x0005, 5 + } +}, +{ + { + 0x0005, 4, 0x0000, 3, 0x0004, 3, 0x0006, 3, 0x0007, 3, 0x0005, 3, 0x0003, 3, 0x0001, 3, 0x0004, 4 + }, + { + 0x0009, 5, 0x000C, 4, 0x0003, 3, 0x0000, 2, 0x0002, 2, 0x0007, 3, 0x000D, 4, 0x0005, 4, 0x0008, 5 + } +}, +{ + { + 0x0039, 6, 0x0017, 5, 0x0008, 4, 0x000A, 4, 0x000D, 4, 0x0000, 3, + 0x0002, 3, 0x0003, 3, 0x0001, 3, 0x000F, 4, 0x000C, 4, 0x0009, 4, + 0x001D, 5, 0x0016, 5, 0x0038, 6, + }, + { + 0x00E5, 8, 0x0038, 6, 0x0007, 5, 0x0002, 4, 0x0000, 3, 0x0003, 3, + 0x0005, 3, 0x0006, 3, 0x0004, 3, 0x0002, 3, 0x000F, 4, 0x001D, 5, + 0x0006, 5, 0x0073, 7, 0x00E4, 8, + }, +}, +{ + { + 0x0041, 7, 0x0006, 6, 0x002C, 6, 0x002D, 6, 0x003B, 6, 0x000D, 5, + 0x0011, 5, 0x0013, 5, 0x0017, 5, 0x0015, 5, 0x001A, 5, 0x001E, 5, + 0x0000, 4, 0x0002, 4, 0x0005, 4, 0x0007, 4, 0x0003, 4, 0x0004, 4, + 0x001F, 5, 0x001C, 5, 0x0019, 5, 0x001B, 5, 0x0018, 5, 0x0014, 5, + 0x0012, 5, 0x000C, 5, 0x0002, 5, 0x003A, 6, 0x0021, 6, 0x0007, 6, + 0x0040, 7 + }, + { + 0x1948, 13, 0x194A, 13, 0x0328, 10, 0x0195, 9, 0x00CB, 8, 0x0066, 7, + 0x0031, 6, 0x0009, 5, 0x000F, 5, 0x001F, 5, 0x0002, 4, 0x0006, 4, + 0x0008, 4, 0x000B, 4, 0x000D, 4, 0x0000, 3, 0x000E, 4, 0x000A, 4, + 0x0009, 4, 0x0005, 4, 0x0003, 4, 0x001E, 5, 0x000E, 5, 0x0008, 5, + 0x0030, 6, 0x0067, 7, 0x00C9, 8, 0x00C8, 8, 0x0653, 11, 0x1949, 13, + 0x194B, 13 + } +}, +{ + { + 0x0067, 8, 0x0099, 8, 0x00B5, 8, 0x00E9, 8, 0x0040, 7, 0x0041, 7, + 0x004D, 7, 0x0051, 7, 0x005B, 7, 0x0071, 7, 0x0070, 7, 0x0018, 6, + 0x001D, 6, 0x0023, 6, 0x0025, 6, 0x0029, 6, 0x002C, 6, 0x002E, 6, + 0x0033, 6, 0x0031, 6, 0x0036, 6, 0x0037, 6, 0x0039, 6, 0x003C, 6, + 0x0000, 5, 0x0002, 5, 0x000A, 5, 0x0005, 5, 0x0009, 5, 0x0006, 5, + 0x000D, 5, 0x0007, 5, 0x000B, 5, 0x000F, 5, 0x0008, 5, 0x0004, 5, + 0x0003, 5, 0x0001, 5, 0x003F, 6, 0x003E, 6, 0x003D, 6, 0x0035, 6, + 0x003B, 6, 0x0034, 6, 0x0030, 6, 0x002F, 6, 0x002B, 6, 0x002A, 6, + 0x0027, 6, 0x0024, 6, 0x0021, 6, 0x001C, 6, 0x0075, 7, 0x0065, 7, + 0x0064, 7, 0x0050, 7, 0x0045, 7, 0x0044, 7, 0x0032, 7, 0x00E8, 8, + 0x00B4, 8, 0x0098, 8, 0x0066, 8 + }, + { + 0x37A4, 14, 0x37AD, 14, 0x37A6, 14, 0x37AE, 14, 0x0DEA, 12, 0x02F0, 10, + 0x02F1, 10, 0x00A0, 9, 0x00A2, 9, 0x01BC, 9, 0x007A, 8, 0x00DF, 8, + 0x003C, 7, 0x0049, 7, 0x006E, 7, 0x000E, 6, 0x0018, 6, 0x0019, 6, + 0x0022, 6, 0x0025, 6, 0x0036, 6, 0x0003, 5, 0x0009, 5, 0x000B, 5, + 0x0010, 5, 0x0013, 5, 0x0015, 5, 0x0018, 5, 0x001A, 5, 0x001D, 5, + 0x001F, 5, 0x0002, 4, 0x0000, 4, 0x001E, 5, 0x001C, 5, 0x0019, 5, + 0x0016, 5, 0x0014, 5, 0x000E, 5, 0x000D, 5, 0x0008, 5, 0x0006, 5, + 0x0002, 5, 0x002E, 6, 0x0023, 6, 0x001F, 6, 0x0015, 6, 0x000F, 6, + 0x005F, 7, 0x0048, 7, 0x0029, 7, 0x00BD, 8, 0x007B, 8, 0x0179, 9, + 0x00A1, 9, 0x037B, 10, 0x0147, 10, 0x0146, 10, 0x0DE8, 12, 0x37AF, 14, + 0x37A7, 14, 0x37AC, 14, 0x37A5, 14 + } +} +}; + +#endif /* AVCODEC_MPC7DATA_H */ diff --git a/ffmpeg/libavcodec/mpc8.c b/ffmpeg/libavcodec/mpc8.c new file mode 100644 index 0000000..4d6ca89 --- /dev/null +++ b/ffmpeg/libavcodec/mpc8.c @@ -0,0 +1,448 @@ +/* + * Musepack SV8 decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * MPEG Audio Layer 1/2 -like codec with frames of 1152 samples + * divided into 32 subbands. + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/lfg.h" +#include "avcodec.h" +#include "get_bits.h" +#include "dsputil.h" +#include "internal.h" +#include "mpegaudiodsp.h" + +#include "mpc.h" +#include "mpc8data.h" +#include "mpc8huff.h" + +static VLC band_vlc, scfi_vlc[2], dscf_vlc[2], res_vlc[2]; +static VLC q1_vlc, q2_vlc[2], q3_vlc[2], quant_vlc[4][2], q9up_vlc; + +static const int q3_offsets[2] = { MPC8_Q3_OFFSET, MPC8_Q4_OFFSET }; +static const int quant_offsets[6] = { MPC8_Q5_OFFSET, MPC8_Q6_OFFSET, MPC8_Q7_OFFSET, MPC8_Q8_OFFSET }; + +static inline int mpc8_dec_base(GetBitContext *gb, int k, int n) +{ + int len = mpc8_cnk_len[k-1][n-1] - 1; + int code = len ? get_bits_long(gb, len) : 0; + + if (code >= mpc8_cnk_lost[k-1][n-1]) + code = ((code << 1) | get_bits1(gb)) - mpc8_cnk_lost[k-1][n-1]; + + return code; +} + +static inline int mpc8_dec_enum(GetBitContext *gb, int k, int n) +{ + int bits = 0; + const uint32_t * C = mpc8_cnk[k-1]; + int code = mpc8_dec_base(gb, k, n); + + do { + n--; + if (code >= C[n]) { + bits |= 1 << n; + code -= C[n]; + C -= 32; + k--; + } + } while(k > 0); + + return bits; +} + +static inline int mpc8_get_mod_golomb(GetBitContext *gb, int m) +{ + if(mpc8_cnk_len[0][m] < 1) return 0; + return mpc8_dec_base(gb, 1, m+1); +} + +static int mpc8_get_mask(GetBitContext *gb, int size, int t) +{ + int mask = 0; + + if(t && t != size) + mask = mpc8_dec_enum(gb, FFMIN(t, size - t), size); + if((t << 1) > size) mask = ~mask; + + return mask; +} + +static const uint16_t vlc_offsets[13] = { + 0, 640, 1184, 1748, 2298, 2426, 2554, 3066, 3578, 4106, 4618, 5196, 5708 +}; + +static av_cold int mpc8_decode_init(AVCodecContext * avctx) +{ + int i; + MPCContext *c = avctx->priv_data; + GetBitContext gb; + static int vlc_initialized = 0; + int channels; + + static VLC_TYPE band_table[542][2]; + static VLC_TYPE q1_table[520][2]; + static VLC_TYPE q9up_table[524][2]; + static VLC_TYPE scfi0_table[1 << MPC8_SCFI0_BITS][2]; + static VLC_TYPE scfi1_table[1 << MPC8_SCFI1_BITS][2]; + static VLC_TYPE dscf0_table[560][2]; + static VLC_TYPE dscf1_table[598][2]; + static VLC_TYPE q3_0_table[512][2]; + static VLC_TYPE q3_1_table[516][2]; + static VLC_TYPE codes_table[5708][2]; + + if(avctx->extradata_size < 2){ + av_log(avctx, AV_LOG_ERROR, "Too small extradata size (%i)!\n", avctx->extradata_size); + return -1; + } + memset(c->oldDSCF, 0, sizeof(c->oldDSCF)); + av_lfg_init(&c->rnd, 0xDEADBEEF); + ff_dsputil_init(&c->dsp, avctx); + ff_mpadsp_init(&c->mpadsp); + + ff_mpc_init(); + + init_get_bits(&gb, avctx->extradata, 16); + + skip_bits(&gb, 3);//sample rate + c->maxbands = get_bits(&gb, 5) + 1; + if (c->maxbands >= BANDS) { + av_log(avctx,AV_LOG_ERROR, "maxbands %d too high\n", c->maxbands); + return AVERROR_INVALIDDATA; + } + channels = get_bits(&gb, 4) + 1; + if (channels > 2) { + avpriv_request_sample(avctx, "Multichannel MPC SV8"); + return AVERROR_PATCHWELCOME; + } + c->MSS = get_bits1(&gb); + c->frames = 1 << (get_bits(&gb, 3) * 2); + + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + avctx->channel_layout = (channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + avctx->channels = channels; + + if(vlc_initialized) return 0; + av_log(avctx, AV_LOG_DEBUG, "Initing VLC\n"); + + band_vlc.table = band_table; + band_vlc.table_allocated = 542; + init_vlc(&band_vlc, MPC8_BANDS_BITS, MPC8_BANDS_SIZE, + mpc8_bands_bits, 1, 1, + mpc8_bands_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + + q1_vlc.table = q1_table; + q1_vlc.table_allocated = 520; + init_vlc(&q1_vlc, MPC8_Q1_BITS, MPC8_Q1_SIZE, + mpc8_q1_bits, 1, 1, + mpc8_q1_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + q9up_vlc.table = q9up_table; + q9up_vlc.table_allocated = 524; + init_vlc(&q9up_vlc, MPC8_Q9UP_BITS, MPC8_Q9UP_SIZE, + mpc8_q9up_bits, 1, 1, + mpc8_q9up_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + + scfi_vlc[0].table = scfi0_table; + scfi_vlc[0].table_allocated = 1 << MPC8_SCFI0_BITS; + init_vlc(&scfi_vlc[0], MPC8_SCFI0_BITS, MPC8_SCFI0_SIZE, + mpc8_scfi0_bits, 1, 1, + mpc8_scfi0_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + scfi_vlc[1].table = scfi1_table; + scfi_vlc[1].table_allocated = 1 << MPC8_SCFI1_BITS; + init_vlc(&scfi_vlc[1], MPC8_SCFI1_BITS, MPC8_SCFI1_SIZE, + mpc8_scfi1_bits, 1, 1, + mpc8_scfi1_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + + dscf_vlc[0].table = dscf0_table; + dscf_vlc[0].table_allocated = 560; + init_vlc(&dscf_vlc[0], MPC8_DSCF0_BITS, MPC8_DSCF0_SIZE, + mpc8_dscf0_bits, 1, 1, + mpc8_dscf0_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + dscf_vlc[1].table = dscf1_table; + dscf_vlc[1].table_allocated = 598; + init_vlc(&dscf_vlc[1], MPC8_DSCF1_BITS, MPC8_DSCF1_SIZE, + mpc8_dscf1_bits, 1, 1, + mpc8_dscf1_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + + q3_vlc[0].table = q3_0_table; + q3_vlc[0].table_allocated = 512; + ff_init_vlc_sparse(&q3_vlc[0], MPC8_Q3_BITS, MPC8_Q3_SIZE, + mpc8_q3_bits, 1, 1, + mpc8_q3_codes, 1, 1, + mpc8_q3_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); + q3_vlc[1].table = q3_1_table; + q3_vlc[1].table_allocated = 516; + ff_init_vlc_sparse(&q3_vlc[1], MPC8_Q4_BITS, MPC8_Q4_SIZE, + mpc8_q4_bits, 1, 1, + mpc8_q4_codes, 1, 1, + mpc8_q4_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); + + for(i = 0; i < 2; i++){ + res_vlc[i].table = &codes_table[vlc_offsets[0+i]]; + res_vlc[i].table_allocated = vlc_offsets[1+i] - vlc_offsets[0+i]; + init_vlc(&res_vlc[i], MPC8_RES_BITS, MPC8_RES_SIZE, + &mpc8_res_bits[i], 1, 1, + &mpc8_res_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + + q2_vlc[i].table = &codes_table[vlc_offsets[2+i]]; + q2_vlc[i].table_allocated = vlc_offsets[3+i] - vlc_offsets[2+i]; + init_vlc(&q2_vlc[i], MPC8_Q2_BITS, MPC8_Q2_SIZE, + &mpc8_q2_bits[i], 1, 1, + &mpc8_q2_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + + quant_vlc[0][i].table = &codes_table[vlc_offsets[4+i]]; + quant_vlc[0][i].table_allocated = vlc_offsets[5+i] - vlc_offsets[4+i]; + init_vlc(&quant_vlc[0][i], MPC8_Q5_BITS, MPC8_Q5_SIZE, + &mpc8_q5_bits[i], 1, 1, + &mpc8_q5_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + quant_vlc[1][i].table = &codes_table[vlc_offsets[6+i]]; + quant_vlc[1][i].table_allocated = vlc_offsets[7+i] - vlc_offsets[6+i]; + init_vlc(&quant_vlc[1][i], MPC8_Q6_BITS, MPC8_Q6_SIZE, + &mpc8_q6_bits[i], 1, 1, + &mpc8_q6_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + quant_vlc[2][i].table = &codes_table[vlc_offsets[8+i]]; + quant_vlc[2][i].table_allocated = vlc_offsets[9+i] - vlc_offsets[8+i]; + init_vlc(&quant_vlc[2][i], MPC8_Q7_BITS, MPC8_Q7_SIZE, + &mpc8_q7_bits[i], 1, 1, + &mpc8_q7_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + quant_vlc[3][i].table = &codes_table[vlc_offsets[10+i]]; + quant_vlc[3][i].table_allocated = vlc_offsets[11+i] - vlc_offsets[10+i]; + init_vlc(&quant_vlc[3][i], MPC8_Q8_BITS, MPC8_Q8_SIZE, + &mpc8_q8_bits[i], 1, 1, + &mpc8_q8_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + vlc_initialized = 1; + + return 0; +} + +static int mpc8_decode_frame(AVCodecContext * avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MPCContext *c = avctx->priv_data; + GetBitContext gb2, *gb = &gb2; + int i, j, k, ch, cnt, res, t; + Band *bands = c->bands; + int off; + int maxband, keyframe; + int last[2]; + + /* get output buffer */ + frame->nb_samples = MPC_FRAME_SIZE; + if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + return res; + + keyframe = c->cur_frame == 0; + + if(keyframe){ + memset(c->Q, 0, sizeof(c->Q)); + c->last_bits_used = 0; + } + init_get_bits(gb, buf, buf_size * 8); + skip_bits(gb, c->last_bits_used & 7); + + if(keyframe) + maxband = mpc8_get_mod_golomb(gb, c->maxbands + 1); + else{ + maxband = c->last_max_band + get_vlc2(gb, band_vlc.table, MPC8_BANDS_BITS, 2); + if(maxband > 32) maxband -= 33; + } + + if(maxband > c->maxbands + 1) { + av_log(avctx, AV_LOG_ERROR, "maxband %d too large\n",maxband); + return AVERROR_INVALIDDATA; + } + c->last_max_band = maxband; + + /* read subband indexes */ + if(maxband){ + last[0] = last[1] = 0; + for(i = maxband - 1; i >= 0; i--){ + for(ch = 0; ch < 2; ch++){ + last[ch] = get_vlc2(gb, res_vlc[last[ch] > 2].table, MPC8_RES_BITS, 2) + last[ch]; + if(last[ch] > 15) last[ch] -= 17; + bands[i].res[ch] = last[ch]; + } + } + if(c->MSS){ + int mask; + + cnt = 0; + for(i = 0; i < maxband; i++) + if(bands[i].res[0] || bands[i].res[1]) + cnt++; + t = mpc8_get_mod_golomb(gb, cnt); + mask = mpc8_get_mask(gb, cnt, t); + for(i = maxband - 1; i >= 0; i--) + if(bands[i].res[0] || bands[i].res[1]){ + bands[i].msf = mask & 1; + mask >>= 1; + } + } + } + for(i = maxband; i < c->maxbands; i++) + bands[i].res[0] = bands[i].res[1] = 0; + + if(keyframe){ + for(i = 0; i < 32; i++) + c->oldDSCF[0][i] = c->oldDSCF[1][i] = 1; + } + + for(i = 0; i < maxband; i++){ + if(bands[i].res[0] || bands[i].res[1]){ + cnt = !!bands[i].res[0] + !!bands[i].res[1] - 1; + if(cnt >= 0){ + t = get_vlc2(gb, scfi_vlc[cnt].table, scfi_vlc[cnt].bits, 1); + if(bands[i].res[0]) bands[i].scfi[0] = t >> (2 * cnt); + if(bands[i].res[1]) bands[i].scfi[1] = t & 3; + } + } + } + + for(i = 0; i < maxband; i++){ + for(ch = 0; ch < 2; ch++){ + if(!bands[i].res[ch]) continue; + + if(c->oldDSCF[ch][i]){ + bands[i].scf_idx[ch][0] = get_bits(gb, 7) - 6; + c->oldDSCF[ch][i] = 0; + }else{ + t = get_vlc2(gb, dscf_vlc[1].table, MPC8_DSCF1_BITS, 2); + if(t == 64) + t += get_bits(gb, 6); + bands[i].scf_idx[ch][0] = ((bands[i].scf_idx[ch][2] + t - 25) & 0x7F) - 6; + } + for(j = 0; j < 2; j++){ + if((bands[i].scfi[ch] << j) & 2) + bands[i].scf_idx[ch][j + 1] = bands[i].scf_idx[ch][j]; + else{ + t = get_vlc2(gb, dscf_vlc[0].table, MPC8_DSCF0_BITS, 2); + if(t == 31) + t = 64 + get_bits(gb, 6); + bands[i].scf_idx[ch][j + 1] = ((bands[i].scf_idx[ch][j] + t - 25) & 0x7F) - 6; + } + } + } + } + + for(i = 0, off = 0; i < maxband; i++, off += SAMPLES_PER_BAND){ + for(ch = 0; ch < 2; ch++){ + res = bands[i].res[ch]; + switch(res){ + case -1: + for(j = 0; j < SAMPLES_PER_BAND; j++) + c->Q[ch][off + j] = (av_lfg_get(&c->rnd) & 0x3FC) - 510; + break; + case 0: + break; + case 1: + for(j = 0; j < SAMPLES_PER_BAND; j += SAMPLES_PER_BAND / 2){ + cnt = get_vlc2(gb, q1_vlc.table, MPC8_Q1_BITS, 2); + t = mpc8_get_mask(gb, 18, cnt); + for(k = 0; k < SAMPLES_PER_BAND / 2; k++, t <<= 1) + c->Q[ch][off + j + k] = (t & 0x20000) ? (get_bits1(gb) << 1) - 1 : 0; + } + break; + case 2: + cnt = 6;//2*mpc8_thres[res] + for(j = 0; j < SAMPLES_PER_BAND; j += 3){ + t = get_vlc2(gb, q2_vlc[cnt > 3].table, MPC8_Q2_BITS, 2); + c->Q[ch][off + j + 0] = mpc8_idx50[t]; + c->Q[ch][off + j + 1] = mpc8_idx51[t]; + c->Q[ch][off + j + 2] = mpc8_idx52[t]; + cnt = (cnt >> 1) + mpc8_huffq2[t]; + } + break; + case 3: + case 4: + for(j = 0; j < SAMPLES_PER_BAND; j += 2){ + t = get_vlc2(gb, q3_vlc[res - 3].table, MPC8_Q3_BITS, 2) + q3_offsets[res - 3]; + c->Q[ch][off + j + 1] = t >> 4; + c->Q[ch][off + j + 0] = (t & 8) ? (t & 0xF) - 16 : (t & 0xF); + } + break; + case 5: + case 6: + case 7: + case 8: + cnt = 2 * mpc8_thres[res]; + for(j = 0; j < SAMPLES_PER_BAND; j++){ + t = get_vlc2(gb, quant_vlc[res - 5][cnt > mpc8_thres[res]].table, quant_vlc[res - 5][cnt > mpc8_thres[res]].bits, 2) + quant_offsets[res - 5]; + c->Q[ch][off + j] = t; + cnt = (cnt >> 1) + FFABS(c->Q[ch][off + j]); + } + break; + default: + for(j = 0; j < SAMPLES_PER_BAND; j++){ + c->Q[ch][off + j] = get_vlc2(gb, q9up_vlc.table, MPC8_Q9UP_BITS, 2); + if(res != 9){ + c->Q[ch][off + j] <<= res - 9; + c->Q[ch][off + j] |= get_bits(gb, res - 9); + } + c->Q[ch][off + j] -= (1 << (res - 2)) - 1; + } + } + } + } + + ff_mpc_dequantize_and_synth(c, maxband - 1, + (int16_t **)frame->extended_data, + avctx->channels); + + c->cur_frame++; + + c->last_bits_used = get_bits_count(gb); + if(get_bits_left(gb) < 8) // we have only padding left + c->last_bits_used = buf_size << 3; + if(c->cur_frame >= c->frames) + c->cur_frame = 0; + + *got_frame_ptr = 1; + + return c->cur_frame ? c->last_bits_used >> 3 : buf_size; +} + +static av_cold void mpc8_decode_flush(AVCodecContext *avctx) +{ + MPCContext *c = avctx->priv_data; + c->cur_frame = 0; +} + +AVCodec ff_mpc8_decoder = { + .name = "mpc8", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MUSEPACK8, + .priv_data_size = sizeof(MPCContext), + .init = mpc8_decode_init, + .decode = mpc8_decode_frame, + .flush = mpc8_decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Musepack SV8"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/mpc8data.h b/ffmpeg/libavcodec/mpc8data.h new file mode 100644 index 0000000..22c2be4 --- /dev/null +++ b/ffmpeg/libavcodec/mpc8data.h @@ -0,0 +1,121 @@ +/* + * Musepack SV8 decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_MPC8DATA_H +#define AVCODEC_MPC8DATA_H + +#include + +static const int8_t mpc8_idx50[125] = { + -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, + -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, + -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, + -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, + -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2 +}; +static const int8_t mpc8_idx51[125] = { + -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 +}; +static const int8_t mpc8_idx52[125] = { + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 +}; + +static const unsigned int mpc8_thres[] = {0, 0, 3, 0, 0, 1, 3, 4, 8}; +static const int8_t mpc8_huffq2[5*5*5] = { + 6, 5, 4, 5, 6, 5, 4, 3, 4, 5, 4, 3, 2, 3, 4, 5, 4, 3, 4, 5, 6, 5, 4, 5, + 6, 5, 4, 3, 4, 5, 4, 3, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, 3, 4, 5, 4, 3, + 4, 5, 4, 3, 2, 3, 4, 3, 2, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, 2, 3, 4, 3, + 2, 3, 4, 5, 4, 3, 4, 5, 4, 3, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2, 3, 4, 5, + 4, 3, 4, 5, 6, 5, 4, 5, 6, 5, 4, 3, 4, 5, 4, 3, 2, 3, 4, 5, 4, 3, 4, 5, + 6, 5, 4, 5, 6 +}; + + +static const uint32_t mpc8_cnk[16][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, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465}, + {0, 0, 0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364, 455, 560, 680, 816, 969, 1140, 1330, 1540, 1771, 2024, 2300, 2600, 2925, 3276, 3654, 4060, 4495}, + {0, 0, 0, 0, 1, 5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315, 8855, 10626, 12650, 14950, 17550, 20475, 23751, 27405, 31465}, + {0, 0, 0, 0, 0, 1, 6, 21, 56, 126, 252, 462, 792, 1287, 2002, 3003, 4368, 6188, 8568, 11628, 15504, 20349, 26334, 33649, 42504, 53130, 65780, 80730, 98280, 118755, 142506, 169911}, + {0, 0, 0, 0, 0, 0, 1, 7, 28, 84, 210, 462, 924, 1716, 3003, 5005, 8008, 12376, 18564, 27132, 38760, 54264, 74613, 100947, 134596, 177100, 230230, 296010, 376740, 475020, 593775, 736281}, + {0, 0, 0, 0, 0, 0, 0, 1, 8, 36, 120, 330, 792, 1716, 3432, 6435, 11440, 19448, 31824, 50388, 77520, 116280, 170544, 245157, 346104, 480700, 657800, 888030, 1184040, 1560780, 2035800, 2629575}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 45, 165, 495, 1287, 3003, 6435, 12870, 24310, 43758, 75582, 125970, 203490, 319770, 490314, 735471, 1081575, 1562275, 2220075, 3108105, 4292145, 5852925, 7888725}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 55, 220, 715, 2002, 5005, 11440, 24310, 48620, 92378, 167960, 293930, 497420, 817190, 1307504, 2042975, 3124550, 4686825, 6906900, 10015005, 14307150, 20160075}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 66, 286, 1001, 3003, 8008, 19448, 43758, 92378, 184756, 352716, 646646, 1144066, 1961256, 3268760, 5311735, 8436285, 13123110, 20030010, 30045015, 44352165}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12, 78, 364, 1365, 4368, 12376, 31824, 75582, 167960, 352716, 705432, 1352078, 2496144, 4457400, 7726160, 13037895, 21474180, 34597290, 54627300, 84672315}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13, 91, 455, 1820, 6188, 18564, 50388, 125970, 293930, 646646, 1352078, 2704156, 5200300, 9657700, 17383860, 30421755, 51895935, 86493225, 141120525}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 105, 560, 2380, 8568, 27132, 77520, 203490, 497420, 1144066, 2496144, 5200300, 10400600, 20058300, 37442160, 67863915, 119759850, 206253075}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 15, 120, 680, 3060, 11628, 38760, 116280, 319770, 817190, 1961256, 4457400, 9657700, 20058300, 40116600, 77558760, 145422675, 265182525}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 136, 816, 3876, 15504, 54264, 170544, 490314, 1307504, 3268760, 7726160, 17383860, 37442160, 77558760, 155117520, 300540195}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 153, 969, 4845, 20349, 74613, 245157, 735471, 2042975, 5311735, 13037895, 30421755, 67863915, 145422675, 300540195} +}; + +static const uint8_t mpc8_cnk_len[16][33] = +{ + {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6}, + {0, 0, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0}, + {0, 0, 0, 2, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 0}, + {0, 0, 0, 0, 3, 4, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 0}, + {0, 0, 0, 0, 0, 3, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 0}, + {0, 0, 0, 0, 0, 0, 3, 5, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 0}, + {0, 0, 0, 0, 0, 0, 0, 3, 6, 7, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 22, 23, 23, 23, 24, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 8, 10, 11, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 21, 22, 23, 23, 24, 24, 25, 25, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, 24, 25, 25, 26, 26, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 9, 11, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 23, 24, 25, 26, 26, 27, 27, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 9, 11, 13, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 28, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 10, 12, 14, 15, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 27, 28, 29, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 10, 12, 14, 16, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 28, 29, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 10, 12, 14, 16, 18, 19, 21, 22, 23, 25, 26, 27, 28, 29, 30, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 10, 13, 15, 17, 18, 20, 21, 23, 24, 25, 27, 28, 29, 30, 0} + +}; + +static const uint32_t mpc8_cnk_lost[16][33] = +{ + {0, 0, 1, 0, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31}, + {0, 0, 1, 2, 6, 1, 11, 4, 28, 19, 9, 62, 50, 37, 23, 8, 120, 103, 85, 66, 46, 25, 3, 236, 212, 187, 161, 134, 106, 77, 47, 16, 0}, + {0, 0, 0, 0, 6, 12, 29, 8, 44, 8, 91, 36, 226, 148, 57, 464, 344, 208, 55, 908, 718, 508, 277, 24, 1796, 1496, 1171, 820, 442, 36, 3697, 3232, 0}, + {0, 0, 0, 0, 3, 1, 29, 58, 2, 46, 182, 17, 309, 23, 683, 228, 1716, 1036, 220, 3347, 2207, 877, 7529, 5758, 3734, 1434, 15218, 12293, 9017, 5363, 1303, 29576, 0}, + {0, 0, 0, 0, 0, 2, 11, 8, 2, 4, 50, 232, 761, 46, 1093, 3824, 2004, 7816, 4756, 880, 12419, 6434, 31887, 23032, 12406, 65292, 50342, 32792, 12317, 119638, 92233, 60768, 0}, + {0, 0, 0, 0, 0, 0, 1, 4, 44, 46, 50, 100, 332, 1093, 3187, 184, 4008, 14204, 5636, 26776, 11272, 56459, 30125, 127548, 85044, 31914, 228278, 147548, 49268, 454801, 312295, 142384, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 28, 8, 182, 232, 332, 664, 1757, 4944, 13320, 944, 15148, 53552, 14792, 91600, 16987, 178184, 43588, 390776, 160546, 913112, 536372, 61352, 1564729, 828448, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 7, 19, 91, 17, 761, 1093, 1757, 3514, 8458, 21778, 55490, 5102, 58654, 204518, 33974, 313105, 1015577, 534877, 1974229, 1086199, 4096463, 2535683, 499883, 6258916, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 9, 36, 309, 46, 3187, 4944, 8458, 16916, 38694, 94184, 230358, 26868, 231386, 789648, 54177, 1069754, 3701783, 1481708, 6762211, 2470066, 13394357, 5505632, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 62, 226, 23, 1093, 184, 13320, 21778, 38694, 77388, 171572, 401930, 953086, 135896, 925544, 3076873, 8340931, 3654106, 13524422, 3509417, 22756699, 2596624, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 50, 148, 683, 3824, 4008, 944, 55490, 94184, 171572, 343144, 745074, 1698160, 3931208, 662448, 3739321, 12080252, 32511574, 12481564, 49545413, 5193248, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 37, 57, 228, 2004, 14204, 15148, 5102, 230358, 401930, 745074, 1490148, 3188308, 7119516, 16170572, 3132677, 15212929, 47724503, 127314931, 42642616, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 23, 464, 1716, 7816, 5636, 53552, 58654, 26868, 953086, 1698160, 3188308, 6376616, 13496132, 29666704, 66353813, 14457878, 62182381, 189497312, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 344, 1036, 4756, 26776, 14792, 204518, 231386, 135896, 3931208, 7119516, 13496132, 26992264, 56658968, 123012781, 3252931, 65435312, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 208, 220, 880, 11272, 91600, 33974, 789648, 925544, 662448, 16170572, 29666704, 56658968, 113317936, 236330717, 508019104, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 103, 55, 3347, 12419, 56459, 16987, 313105, 54177, 3076873, 3739321, 3132677, 66353813, 123012781, 236330717, 0} +}; + +#endif /* AVCODEC_MPC8DATA_H */ diff --git a/ffmpeg/libavcodec/mpc8huff.h b/ffmpeg/libavcodec/mpc8huff.h new file mode 100644 index 0000000..8491037 --- /dev/null +++ b/ffmpeg/libavcodec/mpc8huff.h @@ -0,0 +1,578 @@ +/* + * Musepack SV8 decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_MPC8HUFF_H +#define AVCODEC_MPC8HUFF_H + +#include + +#define MPC8_BANDS_SIZE 33 +#define MPC8_BANDS_BITS 9 + +static const uint8_t mpc8_bands_codes[MPC8_BANDS_SIZE] = { + 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, + 0x05, 0x06, 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x01, 0x09, 0x0A, 0x0B, 0x07, + 0x08, 0x09, 0x06, 0x07, 0x05, 0x05, 0x03, 0x03, + 0x01, +}; +static const int8_t mpc8_bands_bits[MPC8_BANDS_SIZE] = { + 1, 3, 5, 6, 7, 8, 8, 9, + 10, 11, 12, 12, 12, 13, 12, 12, + 12, 12, 12, 13, 12, 12, 12, 11, + 11, 11, 10, 10, 9, 8, 6, 5, + 2, +}; + +#define MPC8_SCFI0_SIZE 4 +#define MPC8_SCFI0_BITS 3 + +static const uint8_t mpc8_scfi0_codes[MPC8_SCFI0_SIZE] = { + 0x00, 0x01, 0x01, 0x01, +}; +static const int8_t mpc8_scfi0_bits[MPC8_SCFI0_SIZE] = { + 3, 3, 1, 2, +}; + +#define MPC8_SCFI1_SIZE 16 +#define MPC8_SCFI1_BITS 7 + +static const uint8_t mpc8_scfi1_codes[MPC8_SCFI1_SIZE] = { + 0x01, 0x00, 0x02, 0x03, 0x01, 0x03, 0x04, 0x05, + 0x04, 0x06, 0x02, 0x02, 0x05, 0x07, 0x03, 0x03, + +}; +static const int8_t mpc8_scfi1_bits[MPC8_SCFI1_SIZE] = { + 6, 7, 6, 6, 7, 5, 5, 5, + 6, 5, 2, 3, 6, 5, 3, 2, + +}; + +#define MPC8_DSCF0_SIZE 64 +#define MPC8_DSCF0_BITS 9 + +static const uint8_t mpc8_dscf0_codes[MPC8_DSCF0_SIZE] = { + 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x07, 0x08, 0x09, 0x0A, 0x07, + 0x08, 0x09, 0x0A, 0x07, 0x08, 0x09, 0x0A, 0x06, + 0x07, 0x05, 0x04, 0x05, 0x06, 0x06, 0x07, 0x0A, + 0x08, 0x05, 0x06, 0x07, 0x09, 0x07, 0x08, 0x09, + 0x0B, 0x0B, 0x0C, 0x0D, 0x0B, 0x0C, 0x0D, 0x0B, + 0x0C, 0x0D, 0x07, 0x08, 0x09, 0x06, 0x07, 0x03, + 0x04, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, +}; +static const int8_t mpc8_dscf0_bits[MPC8_DSCF0_SIZE] = { + 12, 12, 12, 11, 11, 11, 10, 10, + 10, 10, 10, 9, 9, 9, 9, 8, + 8, 8, 8, 7, 7, 7, 7, 6, + 6, 5, 4, 4, 5, 4, 4, 10, + 4, 3, 3, 3, 4, 5, 6, 6, + 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, + 13, 13, 14, 14, 14, 14, 14, 14, + +}; + +#define MPC8_DSCF1_SIZE 65 +#define MPC8_DSCF1_BITS 9 + +static const uint8_t mpc8_dscf1_codes[MPC8_DSCF1_SIZE] = { + 0x00, 0x03, 0x04, 0x04, 0x05, 0x06, 0x05, 0x06, + 0x07, 0x08, 0x07, 0x08, 0x09, 0x0A, 0x07, 0x08, + 0x09, 0x0A, 0x07, 0x08, 0x09, 0x06, 0x07, 0x05, + 0x06, 0x04, 0x03, 0x03, 0x04, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x05, 0x04, 0x05, 0x05, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0B, 0x0C, 0x0D, 0x0B, 0x0C, + 0x0D, 0x09, 0x0A, 0x0B, 0x0C, 0x07, 0x08, 0x09, + 0x05, 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x0D, +}; +static const int8_t mpc8_dscf1_bits[MPC8_DSCF1_SIZE] = { + 15, 14, 14, 13, 13, 13, 12, 12, + 12, 12, 11, 11, 11, 11, 10, 10, + 10, 10, 9, 9, 9, 8, 8, 7, + 7, 6, 5, 4, 4, 3, 3, 3, + 3, 3, 4, 5, 5, 6, 7, 8, + 8, 9, 9, 10, 10, 10, 11, 11, + 11, 12, 12, 12, 12, 13, 13, 13, + 14, 14, 14, 15, 15, 15, 15, 15, + 12, +}; + +#define MPC8_RES_SIZE 17 +#define MPC8_RES_BITS 9 + +static const uint8_t mpc8_res_codes[2][MPC8_RES_SIZE] = { + { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, + 0x01, + }, + { + 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, + 0x03, + } +}; +static const int8_t mpc8_res_bits[2][MPC8_RES_SIZE] = { + { + 1, 2, 4, 5, 6, 7, 9, 10, + 11, 12, 13, 14, 15, 16, 16, 8, + 3, + }, + { + 2, 2, 3, 5, 7, 8, 10, 12, + 14, 14, 14, 14, 11, 9, 6, 4, + 2, + } +}; + +#define MPC8_Q1_SIZE 19 +#define MPC8_Q1_BITS 9 + +static const uint8_t mpc8_q1_codes[MPC8_Q1_SIZE] = { + 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x03, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x01, +}; +static const int8_t mpc8_q1_bits[MPC8_Q1_SIZE] = { + 6, 4, 4, 3, 3, 3, 3, 3, + 4, 4, 4, 5, 7, 8, 9, 10, + 11, 12, 12, +}; + +#define MPC8_Q9UP_SIZE 256 +#define MPC8_Q9UP_BITS 9 + +static const uint8_t mpc8_q9up_codes[MPC8_Q9UP_SIZE] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x26, 0x27, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x28, 0x26, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, + 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, + 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, + 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x3E, + 0x3F, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x6B, 0x7B, 0x6C, 0x6D, 0x6E, + 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, + 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, + 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, + 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0x27, 0x28, 0x29, + 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, + 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x4B, 0x06, 0x07, 0x08, 0x09, 0x00, 0x01, +}; +static const int8_t mpc8_q9up_bits[MPC8_Q9UP_SIZE] = { + 10, 10, 10, 10, 10, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 8, 9, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 6, + 6, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 10, 10, 10, 10, 11, 11, +}; + +#define MPC8_Q2_SIZE 125 +#define MPC8_Q2_BITS 9 + +static const uint8_t mpc8_q2_codes[2][MPC8_Q2_SIZE] = { +{ + 0x02, 0x03, 0x0F, 0x04, 0x00, 0x05, 0x0C, 0x12, + 0x0D, 0x06, 0x07, 0x13, 0x15, 0x14, 0x08, 0x09, + 0x0E, 0x15, 0x0F, 0x0A, 0x03, 0x0B, 0x10, 0x0C, + 0x01, 0x0D, 0x10, 0x16, 0x11, 0x0E, 0x12, 0x0F, + 0x10, 0x16, 0x13, 0x17, 0x11, 0x08, 0x12, 0x18, + 0x14, 0x13, 0x14, 0x17, 0x15, 0x0F, 0x16, 0x19, + 0x17, 0x10, 0x11, 0x1A, 0x18, 0x1B, 0x12, 0x1C, + 0x15, 0x09, 0x16, 0x1D, 0x19, 0x0A, 0x07, 0x0B, + 0x1A, 0x1E, 0x17, 0x0C, 0x18, 0x1F, 0x13, 0x20, + 0x1B, 0x21, 0x14, 0x11, 0x18, 0x22, 0x19, 0x12, + 0x1A, 0x19, 0x1A, 0x1B, 0x1B, 0x23, 0x1C, 0x0D, + 0x1D, 0x24, 0x1C, 0x1C, 0x1E, 0x1F, 0x1D, 0x13, + 0x1E, 0x25, 0x1F, 0x14, 0x02, 0x15, 0x15, 0x16, + 0x04, 0x17, 0x20, 0x26, 0x21, 0x18, 0x16, 0x27, + 0x1D, 0x28, 0x19, 0x1A, 0x22, 0x29, 0x23, 0x1B, + 0x03, 0x1C, 0x17, 0x1D, 0x05, +}, +{ + 0x02, 0x03, 0x0F, 0x04, 0x00, 0x05, 0x0C, 0x0D, + 0x0E, 0x06, 0x07, 0x0F, 0x1E, 0x10, 0x10, 0x08, + 0x11, 0x12, 0x13, 0x09, 0x03, 0x0A, 0x11, 0x0B, + 0x01, 0x0C, 0x14, 0x15, 0x16, 0x0D, 0x17, 0x12, + 0x0E, 0x13, 0x18, 0x19, 0x14, 0x0F, 0x10, 0x1A, + 0x1B, 0x15, 0x11, 0x16, 0x1C, 0x0E, 0x1D, 0x1E, + 0x1F, 0x0F, 0x12, 0x20, 0x1F, 0x21, 0x13, 0x22, + 0x12, 0x13, 0x14, 0x23, 0x20, 0x15, 0x0F, 0x16, + 0x21, 0x24, 0x17, 0x18, 0x19, 0x25, 0x14, 0x26, + 0x22, 0x27, 0x15, 0x10, 0x28, 0x29, 0x2A, 0x11, + 0x2B, 0x17, 0x1A, 0x18, 0x2C, 0x2D, 0x1B, 0x1C, + 0x19, 0x2E, 0x2F, 0x1A, 0x1D, 0x1B, 0x30, 0x12, + 0x31, 0x32, 0x33, 0x13, 0x02, 0x14, 0x15, 0x16, + 0x04, 0x17, 0x34, 0x35, 0x36, 0x18, 0x16, 0x37, + 0x23, 0x38, 0x19, 0x1A, 0x39, 0x3A, 0x3B, 0x1B, + 0x03, 0x1C, 0x17, 0x1D, 0x05, +} +}; +static const int8_t mpc8_q2_bits[2][MPC8_Q2_SIZE] = { +{ + 12, 11, 10, 11, 13, 11, 9, 8, + 9, 11, 11, 8, 7, 8, 11, 11, + 9, 8, 9, 11, 12, 11, 10, 11, + 13, 11, 9, 8, 9, 11, 9, 6, + 6, 7, 9, 8, 6, 4, 6, 8, + 9, 6, 6, 7, 9, 11, 9, 8, + 9, 11, 10, 8, 7, 8, 10, 8, + 6, 4, 6, 8, 7, 4, 3, 4, + 7, 8, 6, 4, 6, 8, 10, 8, + 7, 8, 10, 11, 9, 8, 9, 11, + 9, 6, 6, 6, 9, 8, 6, 4, + 6, 8, 9, 7, 6, 6, 9, 11, + 9, 8, 9, 11, 13, 11, 10, 11, + 12, 11, 9, 8, 9, 11, 10, 8, + 7, 8, 11, 11, 9, 8, 9, 11, + 13, 11, 10, 11, 12, +}, +{ + 11, 10, 9, 10, 12, 10, 8, 8, + 8, 10, 10, 8, 7, 8, 9, 10, + 8, 8, 8, 10, 11, 10, 9, 10, + 12, 10, 8, 8, 8, 10, 8, 6, + 5, 6, 8, 8, 6, 5, 5, 8, + 8, 6, 5, 6, 8, 10, 8, 8, + 8, 10, 9, 8, 7, 8, 9, 8, + 5, 5, 5, 8, 7, 5, 4, 5, + 7, 8, 5, 5, 5, 8, 9, 8, + 7, 8, 9, 10, 8, 8, 8, 10, + 8, 6, 5, 6, 8, 8, 5, 5, + 6, 8, 8, 6, 5, 6, 8, 10, + 8, 8, 8, 10, 12, 10, 10, 10, + 11, 10, 8, 8, 8, 10, 9, 8, + 7, 8, 10, 10, 8, 8, 8, 10, + 12, 10, 9, 10, 11, +} +}; + +#define MPC8_Q3_SIZE 49 +#define MPC8_Q3_BITS 9 +#define MPC8_Q3_OFFSET -48 + +static const uint8_t mpc8_q3_codes[MPC8_Q3_SIZE] = { + 0x07, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x0F, + 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x13, 0x12, 0x11, + 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, + 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, + 0x09, 0x08, 0x07, 0x06, 0x05, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, + 0x00, +}; +static const int8_t mpc8_q3_bits[MPC8_Q3_SIZE] = { + 3, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, +}; +static const int8_t mpc8_q3_syms[MPC8_Q3_SIZE] = { + 48, 65, 64, 49, 63, 32, 47, 80, + 79, 50, 62, 33, 16, 82, 81, 95, + 94, 66, 78, 34, 46, 17, 31, 30, + 97, 96, 111, 67, 77, 51, 61, 35, + 45, 18, 1, 0, 15, 98, 110, 83, + 93, 19, 29, 2, 14, 99, 109, 3, + 13, +}; + +#define MPC8_Q4_SIZE 81 +#define MPC8_Q4_BITS 9 +#define MPC8_Q4_OFFSET -64 + +static const uint8_t mpc8_q4_codes[MPC8_Q4_SIZE] = { + 0x0F, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x23, 0x22, 0x21, + 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, + 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, + 0x10, 0x0F, 0x0E, 0x0D, 0x19, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, + 0x0D, 0x0C, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, + 0x09, 0x08, 0x07, 0x06, 0x05, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, + 0x00, +}; +static const int8_t mpc8_q4_bits[MPC8_Q4_SIZE] = { + 4, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, + 10, +}; +static const int8_t mpc8_q4_syms[MPC8_Q4_SIZE] = { + 64, 96, 81, 80, 95, 66, 65, 79, + 78, 49, 48, 63, 32, 113, 112, 98, + 97, 111, 110, 83, 82, 94, 93, 67, + 77, 51, 50, 62, 61, 34, 33, 47, + 46, 17, 16, 31, 128, 114, 127, 126, + 99, 109, 68, 76, 35, 45, 18, 30, + 0, 15, 130, 129, 143, 142, 115, 125, + 100, 108, 84, 92, 52, 60, 36, 44, + 19, 29, 2, 1, 14, 131, 141, 116, + 124, 20, 28, 3, 13, 132, 140, 4, + 12, +}; + +#define MPC8_Q5_SIZE 15 +#define MPC8_Q5_BITS 7 +#define MPC8_Q5_OFFSET -7 + +static const uint8_t mpc8_q5_codes[2][MPC8_Q5_SIZE] = { +{ + 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, + 0x04, 0x05, 0x03, 0x03, 0x03, 0x02, 0x03, +}, +{ + 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x04, 0x05, 0x03, 0x02, 0x03, +} +}; +static const int8_t mpc8_q5_bits[2][MPC8_Q5_SIZE] = { +{ + 7, 7, 6, 5, 4, 3, 3, 2, + 3, 3, 4, 5, 6, 7, 7, +}, +{ + 6, 6, 5, 4, 4, 3, 3, 3, + 3, 3, 4, 4, 5, 6, 6, +} +}; + +#define MPC8_Q6_SIZE 31 +#define MPC8_Q6_BITS 9 +#define MPC8_Q6_OFFSET -15 + +static const uint8_t mpc8_q6_codes[2][MPC8_Q6_SIZE] = { +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x03, + 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x04, 0x03, + 0x05, 0x06, 0x07, 0x07, 0x06, 0x07, 0x08, 0x09, + 0x05, 0x06, 0x07, 0x04, 0x05, 0x06, 0x07, +}, +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x04, + 0x05, 0x06, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x07, 0x08, 0x09, + 0x06, 0x07, 0x05, 0x06, 0x07, 0x02, 0x03, +} +}; +static const int8_t mpc8_q6_bits[2][MPC8_Q6_SIZE] = { +{ + 9, 9, 9, 9, 8, 8, 7, 6, + 6, 6, 5, 5, 4, 4, 3, 2, + 3, 4, 4, 5, 6, 6, 6, 6, + 7, 8, 8, 9, 9, 9, 9, +}, +{ + 8, 8, 7, 7, 7, 6, 6, 5, + 5, 5, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 7, 7, 7, 8, 8, +} +}; + +#define MPC8_Q7_SIZE 63 +#define MPC8_Q7_BITS 9 +#define MPC8_Q7_OFFSET -31 + +static const uint8_t mpc8_q7_codes[2][MPC8_Q7_SIZE] = { +{ + 0x00, 0x01, 0x02, 0x08, 0x09, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x0A, 0x0B, 0x0C, 0x0D, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0A, 0x0B, 0x0C, 0x08, 0x09, 0x06, 0x04, 0x03, + 0x05, 0x07, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x0F, + 0x10, 0x11, 0x12, 0x0F, 0x13, 0x10, 0x11, 0x12, + 0x13, 0x0E, 0x0F, 0x10, 0x11, 0x08, 0x09, 0x0A, + 0x0B, 0x0C, 0x12, 0x13, 0x0D, 0x0E, 0x0F, +}, +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x09, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x0C, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x1E, 0x1F, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x09, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x02, 0x03, +} +}; +static const int8_t mpc8_q7_bits[2][MPC8_Q7_SIZE] = { +{ + 10, 10, 10, 9, 9, 10, 10, 10, + 10, 10, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, + 6, 6, 6, 5, 5, 4, 3, 2, + 3, 4, 5, 5, 6, 6, 6, 7, + 7, 7, 7, 8, 7, 8, 8, 8, + 8, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 9, 9, 10, 10, 10, +}, +{ + 9, 9, 8, 8, 8, 8, 8, 8, + 8, 7, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 9, 9, +} +}; + +#define MPC8_Q8_SIZE 127 +#define MPC8_Q8_BITS 9 +#define MPC8_Q8_OFFSET -63 + +static const uint8_t mpc8_q8_codes[2][MPC8_Q8_SIZE] = { +{ + 0x03, 0x04, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x1A, + 0x0F, 0x1B, 0x10, 0x00, 0x01, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x11, 0x0C, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1C, 0x1A, + 0x1B, 0x1C, 0x1D, 0x1E, 0x1D, 0x1E, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x19, 0x25, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F, 0x14, 0x15, 0x16, 0x17, + 0x0E, 0x0F, 0x10, 0x11, 0x0B, 0x07, 0x04, 0x03, + 0x05, 0x0C, 0x0D, 0x12, 0x13, 0x14, 0x15, 0x18, + 0x19, 0x1A, 0x1B, 0x20, 0x21, 0x22, 0x23, 0x24, + 0x25, 0x26, 0x27, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x2B, 0x2C, 0x2D, 0x2E, 0x1F, 0x20, 0x2F, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x0D, 0x0E, 0x2A, 0x0F, 0x10, 0x11, 0x12, 0x02, + 0x13, 0x03, 0x04, 0x05, 0x2B, 0x2C, 0x30, 0x31, + 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, +}, +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, + 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, + 0x2F, 0x30, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, + 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x31, 0x3F, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, + 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x16, + 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, + 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x04, 0x05, 0x06, 0x07, +} +}; +static const int8_t mpc8_q8_bits[2][MPC8_Q8_SIZE] = { +{ + 11, 11, 10, 10, 10, 10, 10, 9, + 10, 9, 10, 12, 12, 11, 11, 11, + 11, 11, 11, 11, 10, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 9, 10, + 10, 10, 10, 10, 9, 9, 9, 9, + 9, 9, 9, 9, 8, 9, 8, 8, + 8, 8, 8, 8, 7, 7, 7, 7, + 6, 6, 6, 6, 5, 4, 3, 2, + 3, 5, 5, 6, 6, 6, 6, 7, + 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 10, 10, 9, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 10, 11, 11, 11, 11, 12, + 11, 12, 12, 12, 10, 10, 9, 9, + 10, 10, 10, 10, 10, 10, 10, +}, +{ + 9, 9, 9, 9, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 7, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, +} +}; + +#endif /* AVCODEC_MPC8HUFF_H */ diff --git a/ffmpeg/libavcodec/mpcdata.h b/ffmpeg/libavcodec/mpcdata.h new file mode 100644 index 0000000..64fb4ab --- /dev/null +++ b/ffmpeg/libavcodec/mpcdata.h @@ -0,0 +1,100 @@ +/* + * Musepack decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_MPCDATA_H +#define AVCODEC_MPCDATA_H + +static const float mpc_CC[18+1] = { + 111.285962475327f, // 32768/2/255*sqrt(3) + 65536.0000 /* this value is never used */, + 21845.3333, 13107.2000, 9362.2857, 7281.7778, 4369.0667, 2114.0645, + 1040.2539, 516.0315, 257.0039, 128.2505, 64.0626, 32.0156, 16.0039, 8.0010, + 4.0002, 2.0001, 1.0000 +}; + +static const float mpc_SCF[256] = { + 307.330047607421875000, 255.999984741210937500, 213.243041992187500000, 177.627334594726562500, + 147.960128784179687500, 123.247924804687500000, 102.663139343261718750, 85.516410827636718750, + 71.233520507812500000, 59.336143493652343750, 49.425861358642578125, 41.170787811279296875, + 34.294471740722656250, 28.566631317138671875, 23.795452117919921875, 19.821151733398437500, + 16.510635375976562500, 13.753040313720703125, 11.456016540527343750, 9.542640686035156250, + 7.948835372924804688, 6.621226310729980469, 5.515353679656982422, 4.594182968139648438, + 3.826865673065185547, 3.187705039978027344, 2.655296564102172852, 2.211810588836669922, + 1.842395424842834473, 1.534679770469665527, 1.278358578681945801, 1.064847946166992188, + 0.886997759342193604, 0.738851964473724365, 0.615449428558349609, 0.512657463550567627, + 0.427033752202987671, 0.355710864067077637, 0.296300262212753296, 0.246812388300895691, + 0.205589950084686279, 0.171252459287643433, 0.142649993300437927, 0.118824683129787445, + 0.098978661000728607, 0.082447312772274017, 0.068677015602588654, 0.057206626981496811, + 0.047652013599872589, 0.039693206548690796, 0.033063672482967377, 0.027541399002075195, + 0.022941453382372856, 0.019109787419438362, 0.015918083488941193, 0.013259455561637878, + 0.011044870130717754, 0.009200163185596466, 0.007663558237254620, 0.006383595988154411, + 0.005317411851137877, 0.004429301247000694, 0.003689522389322519, 0.003073300700634718, + 0.002560000168159604, 0.002132430672645569, 0.001776273478753865, 0.001479601487517357, + 0.001232479466125369, 0.001026631565764546, 0.000855164253152907, 0.000712335284333676, + 0.000593361502978951, 0.000494258652906865, 0.000411707907915115, 0.000342944724252447, + 0.000285666319541633, 0.000237954518524930, 0.000198211506358348, 0.000165106350323185, + 0.000137530398205854, 0.000114560163638089, 0.000095426403277088, 0.000079488345363643, + 0.000066212254751008, 0.000055153526773211, 0.000045941822463647, 0.000038268648495432, + 0.000031877043511486, 0.000026552961571724, 0.000022118103515822, 0.000018423952496960, + 0.000015346795407822, 0.000012783583770215, 0.000010648477655195, 0.000008869976227288, + 0.000007388518497464, 0.000006154492893984, 0.000005126573796588, 0.000004270336830814, + 0.000003557107902452, 0.000002963002089018, 0.000002468123511790, 0.000002055899130937, + 0.000001712524181130, 0.000001426499579793, 0.000001188246528727, 0.000000989786371974, + 0.000000824472920158, 0.000000686770022185, 0.000000572066142013, 0.000000476520028769, + 0.000000396931966407, 0.000000330636652279, 0.000000275413924555, 0.000000229414467867, + 0.000000191097811353, 0.000000159180785886, 0.000000132594522029, 0.000000110448674207, + 0.000000092001613439, 0.000000076635565449, 0.000000063835940978, 0.000000053174105119, + 0.000000044293003043, 0.000000036895215771, 0.000000030733001921, 0.000000025599996789, + 0.000000021324305018, 3689522167600.270019531250000000, 3073300627835.926757812500000000, 2560000000000.002929687500000000, + 2132430501800.519042968750000000, 1776273376956.721923828125000000, 1479601378343.250244140625000000, 1232479339720.794189453125000000, + 1026631459710.774291992187500000, 855164155779.391845703125000000, 712335206965.024780273437500000, 593361454233.829101562500000000, + 494258618594.112609863281250000, 411707872682.763122558593750000, 342944697476.612365722656250000, 285666302081.983886718750000000, + 237954506209.446411132812500000, 198211502766.368713378906250000, 165106349338.563323974609375000, 137530396629.095306396484375000, + 114560161209.611633300781250000, 95426399240.062576293945312500, 79488345475.196502685546875000, 66212254855.064872741699218750, + 55153528064.816276550292968750, 45941822471.611343383789062500, 38268649822.956413269042968750, 31877045369.216873168945312500, + 26552962442.420688629150390625, 22118104306.789615631103515625, 18423953228.829509735107421875, 15346796808.164905548095703125, + 12783585007.291271209716796875, 10648479137.463939666748046875, 8869977230.669750213623046875, 7388519530.061036109924316406, + 6154493909.785535812377929688, 5126574428.270387649536132812, 4270337375.232155323028564453, 3557108465.595236301422119141, + 2963002574.315670013427734375, 2468123854.056322574615478516, 2055899448.676229715347290039, 1712524489.450022459030151367, + 1426499787.649837732315063477, 1188246741.404872417449951172, 989786560.561257958412170410, 824473067.192597866058349609, + 686770123.591610312461853027, 572066234.090648531913757324, 476520111.962911486625671387, 396932039.637152194976806641, + 330636714.243810534477233887, 275413990.026798009872436523, 229414528.498330980539321899, 191097866.455478429794311523, + 159180827.835415601730346680, 132594551.788319095969200134, 110448697.892960876226425171, 92001629.793398514389991760, + 76635578.744844585657119751, 63835955.327594503760337830, 53174116.504741288721561432, 44293010.914454914629459381, + 36895221.676002673804759979, 30733006.278359245508909225, 25600000.000000011175870895, 21324305.018005173653364182, + 17762733.769567202776670456, 14796013.783432489261031151, 12324793.397207930684089661, 10266314.597107734531164169, + 8551641.557793911546468735, 7123352.069650243036448956, 5933614.542338287457823753, 4942586.185941123403608799, + 4117078.726827629376202822, 3429446.974766122177243233, 2856663.020819837693125010, 2379545.062094463035464287, + 1982115.027663686312735081, 1651063.493385632522404194, 1375303.966290952404960990, 1145601.612096115713939071, + 954263.992400625254958868, 794883.454751964658498764, 662122.548550648498348892, 551535.280648162588477135, + 459418.224716113239992410, 382686.498229563992936164, 318770.453692168579436839, 265529.624424206791445613, + 221181.043067896069260314, 184239.532288295013131574, 153467.968081648985389620, 127835.850072912653558888, + 106484.791374639346031472, 88699.772306697457679547, 73885.195300610314006917, 61544.939097855312866159, + 51265.744282703839417081, 42703.373752321524079889, 35571.084655952341563534, 29630.025743156678800005, + 24681.238540563208516687, 20558.994486762283486314, 17125.244894500214286381, 14264.997876498367986642, + 11882.467414048716818797, 9897.865605612574654515, 8244.730671925974093028, 6867.701235916098994494, + 5720.662340906482313585, 4765.201119629112326948, 3969.320396371519564127, 3306.367142438103201130, + 2754.139900267978191550, 2294.145284983308101801, 1910.978664554782881169, 1591.808278354154936096, + 1325.945517883190177599, 1104.486978929608085309, 920.016297933984674273, 766.355787448445425980, + 638.359553275944676898, 531.741165047412550848, 442.930109144548907807, 368.952216760026544762, +}; + +#endif /* AVCODEC_MPCDATA_H */ diff --git a/ffmpeg/libavcodec/mpeg12.c b/ffmpeg/libavcodec/mpeg12.c new file mode 100644 index 0000000..ebabd73 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg12.c @@ -0,0 +1,2774 @@ +/* + * MPEG-1/2 decoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * MPEG-1/2 decoder + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +//#define DEBUG +#include "libavutil/avassert.h" +#include "libavutil/timecode.h" + +#include "internal.h" +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "error_resilience.h" +#include "mpeg12.h" +#include "mpeg12data.h" +#include "mpeg12decdata.h" +#include "bytestream.h" +#include "vdpau_internal.h" +#include "xvmc_internal.h" +#include "thread.h" + + +#define MV_VLC_BITS 9 +#define MBINCR_VLC_BITS 9 +#define MB_PAT_VLC_BITS 9 +#define MB_PTYPE_VLC_BITS 6 +#define MB_BTYPE_VLC_BITS 6 + +static VLC mv_vlc; + +/* as H.263, but only 17 codes */ +static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred) +{ + int code, sign, val, shift; + + code = get_vlc2(&s->gb, mv_vlc.table, MV_VLC_BITS, 2); + if (code == 0) { + return pred; + } + if (code < 0) { + return 0xffff; + } + + sign = get_bits1(&s->gb); + shift = fcode - 1; + val = code; + if (shift) { + val = (val - 1) << shift; + val |= get_bits(&s->gb, shift); + val++; + } + if (sign) + val = -val; + val += pred; + + /* modulo decoding */ + return sign_extend(val, 5 + shift); +} + +static inline int mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n) +{ + int level, dc, diff, i, j, run; + int component; + RLTable *rl = &ff_rl_mpeg1; + uint8_t * const scantable = s->intra_scantable.permutated; + const uint16_t *quant_matrix = s->intra_matrix; + const int qscale = s->qscale; + + /* DC coefficient */ + component = (n <= 3 ? 0 : n - 4 + 1); + diff = decode_dc(&s->gb, component); + if (diff >= 0xffff) + return -1; + dc = s->last_dc[component]; + dc += diff; + s->last_dc[component] = dc; + block[0] = dc * quant_matrix[0]; + av_dlog(s->avctx, "dc=%d diff=%d\n", dc, diff); + i = 0; + { + OPEN_READER(re, &s->gb); + /* now quantify & encode AC coefficients */ + for (;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level == 127) { + break; + } else if (level != 0) { + i += run; + j = scantable[i]; + level = (level * qscale * quant_matrix[j]) >> 4; + level = (level - 1) | 1; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6) + 1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 8); SKIP_BITS(re, &s->gb, 8); + if (level == -128) { + level = SHOW_UBITS(re, &s->gb, 8) - 256; LAST_SKIP_BITS(re, &s->gb, 8); + } else if (level == 0) { + level = SHOW_UBITS(re, &s->gb, 8) ; LAST_SKIP_BITS(re, &s->gb, 8); + } + i += run; + j = scantable[i]; + if (level < 0) { + level = -level; + level = (level * qscale * quant_matrix[j]) >> 4; + level = (level - 1) | 1; + level = -level; + } else { + level = (level * qscale * quant_matrix[j]) >> 4; + level = (level - 1) | 1; + } + } + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + block[j] = level; + } + CLOSE_READER(re, &s->gb); + } + s->block_last_index[n] = i; + return 0; +} + +int ff_mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n) +{ + return mpeg1_decode_block_intra(s, block, n); +} + +static inline int mpeg1_decode_block_inter(MpegEncContext *s, int16_t *block, int n) +{ + int level, i, j, run; + RLTable *rl = &ff_rl_mpeg1; + uint8_t * const scantable = s->intra_scantable.permutated; + const uint16_t *quant_matrix = s->inter_matrix; + const int qscale = s->qscale; + + { + OPEN_READER(re, &s->gb); + i = -1; + // special case for first coefficient, no need to add second VLC table + UPDATE_CACHE(re, &s->gb); + if (((int32_t)GET_CACHE(re, &s->gb)) < 0) { + level = (3 * qscale * quant_matrix[0]) >> 5; + level = (level - 1) | 1; + if (GET_CACHE(re, &s->gb) & 0x40000000) + level = -level; + block[0] = level; + i++; + SKIP_BITS(re, &s->gb, 2); + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + goto end; + } + /* now quantify & encode AC coefficients */ + for (;;) { + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level != 0) { + i += run; + j = scantable[i]; + level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; + level = (level - 1) | 1; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6) + 1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 8); SKIP_BITS(re, &s->gb, 8); + if (level == -128) { + level = SHOW_UBITS(re, &s->gb, 8) - 256; SKIP_BITS(re, &s->gb, 8); + } else if (level == 0) { + level = SHOW_UBITS(re, &s->gb, 8) ; SKIP_BITS(re, &s->gb, 8); + } + i += run; + j = scantable[i]; + if (level < 0) { + level = -level; + level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; + level = (level - 1) | 1; + level = -level; + } else { + level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; + level = (level - 1) | 1; + } + } + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + block[j] = level; + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + break; + UPDATE_CACHE(re, &s->gb); + } +end: + LAST_SKIP_BITS(re, &s->gb, 2); + CLOSE_READER(re, &s->gb); + } + s->block_last_index[n] = i; + return 0; +} + +/** + * Note: this function can read out of range and crash for corrupt streams. + * Changing this would eat up any speed benefits it has. + * Do not use "fast" flag if you need the code to be robust. + */ +static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, int16_t *block, int n) +{ + int level, i, j, run; + RLTable *rl = &ff_rl_mpeg1; + uint8_t * const scantable = s->intra_scantable.permutated; + const int qscale = s->qscale; + + { + OPEN_READER(re, &s->gb); + i = -1; + // special case for first coefficient, no need to add second VLC table + UPDATE_CACHE(re, &s->gb); + if (((int32_t)GET_CACHE(re, &s->gb)) < 0) { + level = (3 * qscale) >> 1; + level = (level - 1) | 1; + if (GET_CACHE(re, &s->gb) & 0x40000000) + level = -level; + block[0] = level; + i++; + SKIP_BITS(re, &s->gb, 2); + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + goto end; + } + + /* now quantify & encode AC coefficients */ + for (;;) { + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level != 0) { + i += run; + j = scantable[i]; + level = ((level * 2 + 1) * qscale) >> 1; + level = (level - 1) | 1; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6)+1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 8); SKIP_BITS(re, &s->gb, 8); + if (level == -128) { + level = SHOW_UBITS(re, &s->gb, 8) - 256; SKIP_BITS(re, &s->gb, 8); + } else if (level == 0) { + level = SHOW_UBITS(re, &s->gb, 8) ; SKIP_BITS(re, &s->gb, 8); + } + i += run; + j = scantable[i]; + if (level < 0) { + level = -level; + level = ((level * 2 + 1) * qscale) >> 1; + level = (level - 1) | 1; + level = -level; + } else { + level = ((level * 2 + 1) * qscale) >> 1; + level = (level - 1) | 1; + } + } + + block[j] = level; + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + break; + UPDATE_CACHE(re, &s->gb); + } +end: + LAST_SKIP_BITS(re, &s->gb, 2); + CLOSE_READER(re, &s->gb); + } + s->block_last_index[n] = i; + return 0; +} + + +static inline int mpeg2_decode_block_non_intra(MpegEncContext *s, int16_t *block, int n) +{ + int level, i, j, run; + RLTable *rl = &ff_rl_mpeg1; + uint8_t * const scantable = s->intra_scantable.permutated; + const uint16_t *quant_matrix; + const int qscale = s->qscale; + int mismatch; + + mismatch = 1; + + { + OPEN_READER(re, &s->gb); + i = -1; + if (n < 4) + quant_matrix = s->inter_matrix; + else + quant_matrix = s->chroma_inter_matrix; + + // special case for first coefficient, no need to add second VLC table + UPDATE_CACHE(re, &s->gb); + if (((int32_t)GET_CACHE(re, &s->gb)) < 0) { + level= (3 * qscale * quant_matrix[0]) >> 5; + if (GET_CACHE(re, &s->gb) & 0x40000000) + level = -level; + block[0] = level; + mismatch ^= level; + i++; + SKIP_BITS(re, &s->gb, 2); + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + goto end; + } + + /* now quantify & encode AC coefficients */ + for (;;) { + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level != 0) { + i += run; + j = scantable[i]; + level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6) + 1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); + + i += run; + j = scantable[i]; + if (level < 0) { + level = ((-level * 2 + 1) * qscale * quant_matrix[j]) >> 5; + level = -level; + } else { + level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5; + } + } + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + mismatch ^= level; + block[j] = level; + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + break; + UPDATE_CACHE(re, &s->gb); + } +end: + LAST_SKIP_BITS(re, &s->gb, 2); + CLOSE_READER(re, &s->gb); + } + block[63] ^= (mismatch & 1); + + s->block_last_index[n] = i; + return 0; +} + +/** + * Note: this function can read out of range and crash for corrupt streams. + * Changing this would eat up any speed benefits it has. + * Do not use "fast" flag if you need the code to be robust. + */ +static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, + int16_t *block, int n) +{ + int level, i, j, run; + RLTable *rl = &ff_rl_mpeg1; + uint8_t * const scantable = s->intra_scantable.permutated; + const int qscale = s->qscale; + OPEN_READER(re, &s->gb); + i = -1; + + // special case for first coefficient, no need to add second VLC table + UPDATE_CACHE(re, &s->gb); + if (((int32_t)GET_CACHE(re, &s->gb)) < 0) { + level = (3 * qscale) >> 1; + if (GET_CACHE(re, &s->gb) & 0x40000000) + level = -level; + block[0] = level; + i++; + SKIP_BITS(re, &s->gb, 2); + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + goto end; + } + + /* now quantify & encode AC coefficients */ + for (;;) { + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level != 0) { + i += run; + j = scantable[i]; + level = ((level * 2 + 1) * qscale) >> 1; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6) + 1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); + + i += run; + j = scantable[i]; + if (level < 0) { + level = ((-level * 2 + 1) * qscale) >> 1; + level = -level; + } else { + level = ((level * 2 + 1) * qscale) >> 1; + } + } + + block[j] = level; + if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF) + break; + UPDATE_CACHE(re, &s->gb); + } +end: + LAST_SKIP_BITS(re, &s->gb, 2); + CLOSE_READER(re, &s->gb); + s->block_last_index[n] = i; + return 0; +} + + +static inline int mpeg2_decode_block_intra(MpegEncContext *s, int16_t *block, int n) +{ + int level, dc, diff, i, j, run; + int component; + RLTable *rl; + uint8_t * const scantable = s->intra_scantable.permutated; + const uint16_t *quant_matrix; + const int qscale = s->qscale; + int mismatch; + + /* DC coefficient */ + if (n < 4) { + quant_matrix = s->intra_matrix; + component = 0; + } else { + quant_matrix = s->chroma_intra_matrix; + component = (n & 1) + 1; + } + diff = decode_dc(&s->gb, component); + if (diff >= 0xffff) + return -1; + dc = s->last_dc[component]; + dc += diff; + s->last_dc[component] = dc; + block[0] = dc << (3 - s->intra_dc_precision); + av_dlog(s->avctx, "dc=%d\n", block[0]); + mismatch = block[0] ^ 1; + i = 0; + if (s->intra_vlc_format) + rl = &ff_rl_mpeg2; + else + rl = &ff_rl_mpeg1; + + { + OPEN_READER(re, &s->gb); + /* now quantify & encode AC coefficients */ + for (;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level == 127) { + break; + } else if (level != 0) { + i += run; + j = scantable[i]; + level = (level * qscale * quant_matrix[j]) >> 4; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6) + 1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); + i += run; + j = scantable[i]; + if (level < 0) { + level = (-level * qscale * quant_matrix[j]) >> 4; + level = -level; + } else { + level = (level * qscale * quant_matrix[j]) >> 4; + } + } + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + mismatch ^= level; + block[j] = level; + } + CLOSE_READER(re, &s->gb); + } + block[63] ^= mismatch & 1; + + s->block_last_index[n] = i; + return 0; +} + +/** + * Note: this function can read out of range and crash for corrupt streams. + * Changing this would eat up any speed benefits it has. + * Do not use "fast" flag if you need the code to be robust. + */ +static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, int16_t *block, int n) +{ + int level, dc, diff, j, run; + int component; + RLTable *rl; + uint8_t * scantable = s->intra_scantable.permutated; + const uint16_t *quant_matrix; + const int qscale = s->qscale; + + /* DC coefficient */ + if (n < 4) { + quant_matrix = s->intra_matrix; + component = 0; + } else { + quant_matrix = s->chroma_intra_matrix; + component = (n & 1) + 1; + } + diff = decode_dc(&s->gb, component); + if (diff >= 0xffff) + return -1; + dc = s->last_dc[component]; + dc += diff; + s->last_dc[component] = dc; + block[0] = dc << (3 - s->intra_dc_precision); + if (s->intra_vlc_format) + rl = &ff_rl_mpeg2; + else + rl = &ff_rl_mpeg1; + + { + OPEN_READER(re, &s->gb); + /* now quantify & encode AC coefficients */ + for (;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); + + if (level == 127) { + break; + } else if (level != 0) { + scantable += run; + j = *scantable; + level = (level * qscale * quant_matrix[j]) >> 4; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } else { + /* escape */ + run = SHOW_UBITS(re, &s->gb, 6) + 1; LAST_SKIP_BITS(re, &s->gb, 6); + UPDATE_CACHE(re, &s->gb); + level = SHOW_SBITS(re, &s->gb, 12); SKIP_BITS(re, &s->gb, 12); + scantable += run; + j = *scantable; + if (level < 0) { + level = (-level * qscale * quant_matrix[j]) >> 4; + level = -level; + } else { + level = (level * qscale * quant_matrix[j]) >> 4; + } + } + + block[j] = level; + } + CLOSE_READER(re, &s->gb); + } + + s->block_last_index[n] = scantable - s->intra_scantable.permutated; + return 0; +} + +uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; + +#define INIT_2D_VLC_RL(rl, static_size)\ +{\ + static RL_VLC_ELEM rl_vlc_table[static_size];\ + INIT_VLC_STATIC(&rl.vlc, TEX_VLC_BITS, rl.n + 2,\ + &rl.table_vlc[0][1], 4, 2,\ + &rl.table_vlc[0][0], 4, 2, static_size);\ +\ + rl.rl_vlc[0] = rl_vlc_table;\ + init_2d_vlc_rl(&rl);\ +} + +static void init_2d_vlc_rl(RLTable *rl) +{ + int i; + + for (i = 0; i < rl->vlc.table_size; i++) { + int code = rl->vlc.table[i][0]; + int len = rl->vlc.table[i][1]; + int level, run; + + if (len == 0) { // illegal code + run = 65; + level = MAX_LEVEL; + } else if (len<0) { //more bits needed + run = 0; + level = code; + } else { + if (code == rl->n) { //esc + run = 65; + level = 0; + } else if (code == rl->n+1) { //eob + run = 0; + level = 127; + } else { + run = rl->table_run [code] + 1; + level = rl->table_level[code]; + } + } + rl->rl_vlc[0][i].len = len; + rl->rl_vlc[0][i].level = level; + rl->rl_vlc[0][i].run = run; + } +} + +void ff_mpeg12_common_init(MpegEncContext *s) +{ + + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg2_dc_scale_table[s->intra_dc_precision]; + +} + +void ff_mpeg1_clean_buffers(MpegEncContext *s) +{ + s->last_dc[0] = 1 << (7 + s->intra_dc_precision); + s->last_dc[1] = s->last_dc[0]; + s->last_dc[2] = s->last_dc[0]; + memset(s->last_mv, 0, sizeof(s->last_mv)); +} + + +/******************************************/ +/* decoding */ + +VLC ff_dc_lum_vlc; +VLC ff_dc_chroma_vlc; + +static VLC mbincr_vlc; +static VLC mb_ptype_vlc; +static VLC mb_btype_vlc; +static VLC mb_pat_vlc; + +av_cold void ff_mpeg12_init_vlcs(void) +{ + static int done = 0; + + if (!done) { + done = 1; + + INIT_VLC_STATIC(&ff_dc_lum_vlc, DC_VLC_BITS, 12, + ff_mpeg12_vlc_dc_lum_bits, 1, 1, + ff_mpeg12_vlc_dc_lum_code, 2, 2, 512); + INIT_VLC_STATIC(&ff_dc_chroma_vlc, DC_VLC_BITS, 12, + ff_mpeg12_vlc_dc_chroma_bits, 1, 1, + ff_mpeg12_vlc_dc_chroma_code, 2, 2, 514); + INIT_VLC_STATIC(&mv_vlc, MV_VLC_BITS, 17, + &ff_mpeg12_mbMotionVectorTable[0][1], 2, 1, + &ff_mpeg12_mbMotionVectorTable[0][0], 2, 1, 518); + INIT_VLC_STATIC(&mbincr_vlc, MBINCR_VLC_BITS, 36, + &ff_mpeg12_mbAddrIncrTable[0][1], 2, 1, + &ff_mpeg12_mbAddrIncrTable[0][0], 2, 1, 538); + INIT_VLC_STATIC(&mb_pat_vlc, MB_PAT_VLC_BITS, 64, + &ff_mpeg12_mbPatTable[0][1], 2, 1, + &ff_mpeg12_mbPatTable[0][0], 2, 1, 512); + + INIT_VLC_STATIC(&mb_ptype_vlc, MB_PTYPE_VLC_BITS, 7, + &table_mb_ptype[0][1], 2, 1, + &table_mb_ptype[0][0], 2, 1, 64); + INIT_VLC_STATIC(&mb_btype_vlc, MB_BTYPE_VLC_BITS, 11, + &table_mb_btype[0][1], 2, 1, + &table_mb_btype[0][0], 2, 1, 64); + ff_init_rl(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); + ff_init_rl(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); + + INIT_2D_VLC_RL(ff_rl_mpeg1, 680); + INIT_2D_VLC_RL(ff_rl_mpeg2, 674); + } +} + +static inline int get_dmv(MpegEncContext *s) +{ + if (get_bits1(&s->gb)) + return 1 - (get_bits1(&s->gb) << 1); + else + return 0; +} + +static inline int get_qscale(MpegEncContext *s) +{ + int qscale = get_bits(&s->gb, 5); + if (s->q_scale_type) { + return non_linear_qscale[qscale]; + } else { + return qscale << 1; + } +} + +static void exchange_uv(MpegEncContext *s) +{ + int16_t (*tmp)[64]; + + tmp = s->pblocks[4]; + s->pblocks[4] = s->pblocks[5]; + s->pblocks[5] = tmp; +} + +/* motion type (for MPEG-2) */ +#define MT_FIELD 1 +#define MT_FRAME 2 +#define MT_16X8 2 +#define MT_DMV 3 + +static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) +{ + int i, j, k, cbp, val, mb_type, motion_type; + const int mb_block_count = 4 + (1 << s->chroma_format); + + av_dlog(s->avctx, "decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y); + + av_assert2(s->mb_skipped == 0); + + if (s->mb_skip_run-- != 0) { + if (s->pict_type == AV_PICTURE_TYPE_P) { + s->mb_skipped = 1; + s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride] = MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16; + } else { + int mb_type; + + if (s->mb_x) + mb_type = s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride - 1]; + else + mb_type = s->current_picture.mb_type[s->mb_width + (s->mb_y - 1) * s->mb_stride - 1]; // FIXME not sure if this is allowed in MPEG at all + if (IS_INTRA(mb_type)) { + av_log(s->avctx, AV_LOG_ERROR, "skip with previntra\n"); + return -1; + } + s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride] = + mb_type | MB_TYPE_SKIP; + +// assert(s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride - 1] & (MB_TYPE_16x16 | MB_TYPE_16x8)); + + if ((s->mv[0][0][0] | s->mv[0][0][1] | s->mv[1][0][0] | s->mv[1][0][1]) == 0) + s->mb_skipped = 1; + } + + return 0; + } + + switch (s->pict_type) { + default: + case AV_PICTURE_TYPE_I: + if (get_bits1(&s->gb) == 0) { + if (get_bits1(&s->gb) == 0) { + av_log(s->avctx, AV_LOG_ERROR, "invalid mb type in I Frame at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + mb_type = MB_TYPE_QUANT | MB_TYPE_INTRA; + } else { + mb_type = MB_TYPE_INTRA; + } + break; + case AV_PICTURE_TYPE_P: + mb_type = get_vlc2(&s->gb, mb_ptype_vlc.table, MB_PTYPE_VLC_BITS, 1); + if (mb_type < 0) { + av_log(s->avctx, AV_LOG_ERROR, "invalid mb type in P Frame at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + mb_type = ptype2mb_type[mb_type]; + break; + case AV_PICTURE_TYPE_B: + mb_type = get_vlc2(&s->gb, mb_btype_vlc.table, MB_BTYPE_VLC_BITS, 1); + if (mb_type < 0) { + av_log(s->avctx, AV_LOG_ERROR, "invalid mb type in B Frame at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + mb_type = btype2mb_type[mb_type]; + break; + } + av_dlog(s->avctx, "mb_type=%x\n", mb_type); +// motion_type = 0; /* avoid warning */ + if (IS_INTRA(mb_type)) { + s->dsp.clear_blocks(s->block[0]); + + if (!s->chroma_y_shift) { + s->dsp.clear_blocks(s->block[6]); + } + + /* compute DCT type */ + if (s->picture_structure == PICT_FRAME && // FIXME add an interlaced_dct coded var? + !s->frame_pred_frame_dct) { + s->interlaced_dct = get_bits1(&s->gb); + } + + if (IS_QUANT(mb_type)) + s->qscale = get_qscale(s); + + if (s->concealment_motion_vectors) { + /* just parse them */ + if (s->picture_structure != PICT_FRAME) + skip_bits1(&s->gb); /* field select */ + + s->mv[0][0][0]= s->last_mv[0][0][0]= s->last_mv[0][1][0] = + mpeg_decode_motion(s, s->mpeg_f_code[0][0], s->last_mv[0][0][0]); + s->mv[0][0][1]= s->last_mv[0][0][1]= s->last_mv[0][1][1] = + mpeg_decode_motion(s, s->mpeg_f_code[0][1], s->last_mv[0][0][1]); + + skip_bits1(&s->gb); /* marker */ + } else + memset(s->last_mv, 0, sizeof(s->last_mv)); /* reset mv prediction */ + s->mb_intra = 1; + // if 1, we memcpy blocks in xvmcvideo + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) { + ff_xvmc_pack_pblocks(s, -1); // inter are always full blocks + if (s->swap_uv) { + exchange_uv(s); + } + } + + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (s->flags2 & CODEC_FLAG2_FAST) { + for (i = 0; i < 6; i++) { + mpeg2_fast_decode_block_intra(s, *s->pblocks[i], i); + } + } else { + for (i = 0; i < mb_block_count; i++) { + if (mpeg2_decode_block_intra(s, *s->pblocks[i], i) < 0) + return -1; + } + } + } else { + for (i = 0; i < 6; i++) { + if (mpeg1_decode_block_intra(s, *s->pblocks[i], i) < 0) + return -1; + } + } + } else { + if (mb_type & MB_TYPE_ZERO_MV) { + av_assert2(mb_type & MB_TYPE_CBP); + + s->mv_dir = MV_DIR_FORWARD; + if (s->picture_structure == PICT_FRAME) { + if (s->picture_structure == PICT_FRAME + && !s->frame_pred_frame_dct) + s->interlaced_dct = get_bits1(&s->gb); + s->mv_type = MV_TYPE_16X16; + } else { + s->mv_type = MV_TYPE_FIELD; + mb_type |= MB_TYPE_INTERLACED; + s->field_select[0][0] = s->picture_structure - 1; + } + + if (IS_QUANT(mb_type)) + s->qscale = get_qscale(s); + + s->last_mv[0][0][0] = 0; + s->last_mv[0][0][1] = 0; + s->last_mv[0][1][0] = 0; + s->last_mv[0][1][1] = 0; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + } else { + av_assert2(mb_type & MB_TYPE_L0L1); + // FIXME decide if MBs in field pictures are MB_TYPE_INTERLACED + /* get additional motion vector type */ + if (s->picture_structure == PICT_FRAME && s->frame_pred_frame_dct) + motion_type = MT_FRAME; + else { + motion_type = get_bits(&s->gb, 2); + if (s->picture_structure == PICT_FRAME && HAS_CBP(mb_type)) + s->interlaced_dct = get_bits1(&s->gb); + } + + if (IS_QUANT(mb_type)) + s->qscale = get_qscale(s); + + /* motion vectors */ + s->mv_dir = (mb_type >> 13) & 3; + av_dlog(s->avctx, "motion_type=%d\n", motion_type); + switch (motion_type) { + case MT_FRAME: /* or MT_16X8 */ + if (s->picture_structure == PICT_FRAME) { + mb_type |= MB_TYPE_16x16; + s->mv_type = MV_TYPE_16X16; + for (i = 0; i < 2; i++) { + if (USES_LIST(mb_type, i)) { + /* MT_FRAME */ + s->mv[i][0][0]= s->last_mv[i][0][0]= s->last_mv[i][1][0] = + mpeg_decode_motion(s, s->mpeg_f_code[i][0], s->last_mv[i][0][0]); + s->mv[i][0][1]= s->last_mv[i][0][1]= s->last_mv[i][1][1] = + mpeg_decode_motion(s, s->mpeg_f_code[i][1], s->last_mv[i][0][1]); + /* full_pel: only for MPEG-1 */ + if (s->full_pel[i]) { + s->mv[i][0][0] <<= 1; + s->mv[i][0][1] <<= 1; + } + } + } + } else { + mb_type |= MB_TYPE_16x8 | MB_TYPE_INTERLACED; + s->mv_type = MV_TYPE_16X8; + for (i = 0; i < 2; i++) { + if (USES_LIST(mb_type, i)) { + /* MT_16X8 */ + for (j = 0; j < 2; j++) { + s->field_select[i][j] = get_bits1(&s->gb); + for (k = 0; k < 2; k++) { + val = mpeg_decode_motion(s, s->mpeg_f_code[i][k], + s->last_mv[i][j][k]); + s->last_mv[i][j][k] = val; + s->mv[i][j][k] = val; + } + } + } + } + } + break; + case MT_FIELD: + s->mv_type = MV_TYPE_FIELD; + if (s->picture_structure == PICT_FRAME) { + mb_type |= MB_TYPE_16x8 | MB_TYPE_INTERLACED; + for (i = 0; i < 2; i++) { + if (USES_LIST(mb_type, i)) { + for (j = 0; j < 2; j++) { + s->field_select[i][j] = get_bits1(&s->gb); + val = mpeg_decode_motion(s, s->mpeg_f_code[i][0], + s->last_mv[i][j][0]); + s->last_mv[i][j][0] = val; + s->mv[i][j][0] = val; + av_dlog(s->avctx, "fmx=%d\n", val); + val = mpeg_decode_motion(s, s->mpeg_f_code[i][1], + s->last_mv[i][j][1] >> 1); + s->last_mv[i][j][1] = val << 1; + s->mv[i][j][1] = val; + av_dlog(s->avctx, "fmy=%d\n", val); + } + } + } + } else { + av_assert0(!s->progressive_sequence); + mb_type |= MB_TYPE_16x16 | MB_TYPE_INTERLACED; + for (i = 0; i < 2; i++) { + if (USES_LIST(mb_type, i)) { + s->field_select[i][0] = get_bits1(&s->gb); + for (k = 0; k < 2; k++) { + val = mpeg_decode_motion(s, s->mpeg_f_code[i][k], + s->last_mv[i][0][k]); + s->last_mv[i][0][k] = val; + s->last_mv[i][1][k] = val; + s->mv[i][0][k] = val; + } + } + } + } + break; + case MT_DMV: + if(s->progressive_sequence){ + av_log(s->avctx, AV_LOG_ERROR, "MT_DMV in progressive_sequence\n"); + return -1; + } + s->mv_type = MV_TYPE_DMV; + for (i = 0; i < 2; i++) { + if (USES_LIST(mb_type, i)) { + int dmx, dmy, mx, my, m; + const int my_shift = s->picture_structure == PICT_FRAME; + + mx = mpeg_decode_motion(s, s->mpeg_f_code[i][0], + s->last_mv[i][0][0]); + s->last_mv[i][0][0] = mx; + s->last_mv[i][1][0] = mx; + dmx = get_dmv(s); + my = mpeg_decode_motion(s, s->mpeg_f_code[i][1], + s->last_mv[i][0][1] >> my_shift); + dmy = get_dmv(s); + + + s->last_mv[i][0][1] = my << my_shift; + s->last_mv[i][1][1] = my << my_shift; + + s->mv[i][0][0] = mx; + s->mv[i][0][1] = my; + s->mv[i][1][0] = mx; // not used + s->mv[i][1][1] = my; // not used + + if (s->picture_structure == PICT_FRAME) { + mb_type |= MB_TYPE_16x16 | MB_TYPE_INTERLACED; + + // m = 1 + 2 * s->top_field_first; + m = s->top_field_first ? 1 : 3; + + /* top -> top pred */ + s->mv[i][2][0] = ((mx * m + (mx > 0)) >> 1) + dmx; + s->mv[i][2][1] = ((my * m + (my > 0)) >> 1) + dmy - 1; + m = 4 - m; + s->mv[i][3][0] = ((mx * m + (mx > 0)) >> 1) + dmx; + s->mv[i][3][1] = ((my * m + (my > 0)) >> 1) + dmy + 1; + } else { + mb_type |= MB_TYPE_16x16; + + s->mv[i][2][0] = ((mx + (mx > 0)) >> 1) + dmx; + s->mv[i][2][1] = ((my + (my > 0)) >> 1) + dmy; + if (s->picture_structure == PICT_TOP_FIELD) + s->mv[i][2][1]--; + else + s->mv[i][2][1]++; + } + } + } + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "00 motion_type at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + } + + s->mb_intra = 0; + if (HAS_CBP(mb_type)) { + s->dsp.clear_blocks(s->block[0]); + + cbp = get_vlc2(&s->gb, mb_pat_vlc.table, MB_PAT_VLC_BITS, 1); + if (mb_block_count > 6) { + cbp <<= mb_block_count - 6; + cbp |= get_bits(&s->gb, mb_block_count - 6); + s->dsp.clear_blocks(s->block[6]); + } + if (cbp <= 0) { + av_log(s->avctx, AV_LOG_ERROR, "invalid cbp %d at %d %d\n", cbp, s->mb_x, s->mb_y); + return -1; + } + + //if 1, we memcpy blocks in xvmcvideo + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) { + ff_xvmc_pack_pblocks(s, cbp); + if (s->swap_uv) { + exchange_uv(s); + } + } + + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (s->flags2 & CODEC_FLAG2_FAST) { + for (i = 0; i < 6; i++) { + if (cbp & 32) { + mpeg2_fast_decode_block_non_intra(s, *s->pblocks[i], i); + } else { + s->block_last_index[i] = -1; + } + cbp += cbp; + } + } else { + cbp <<= 12-mb_block_count; + + for (i = 0; i < mb_block_count; i++) { + if (cbp & (1 << 11)) { + if (mpeg2_decode_block_non_intra(s, *s->pblocks[i], i) < 0) + return -1; + } else { + s->block_last_index[i] = -1; + } + cbp += cbp; + } + } + } else { + if (s->flags2 & CODEC_FLAG2_FAST) { + for (i = 0; i < 6; i++) { + if (cbp & 32) { + mpeg1_fast_decode_block_inter(s, *s->pblocks[i], i); + } else { + s->block_last_index[i] = -1; + } + cbp += cbp; + } + } else { + for (i = 0; i < 6; i++) { + if (cbp & 32) { + if (mpeg1_decode_block_inter(s, *s->pblocks[i], i) < 0) + return -1; + } else { + s->block_last_index[i] = -1; + } + cbp += cbp; + } + } + } + } else { + for (i = 0; i < 12; i++) + s->block_last_index[i] = -1; + } + } + + s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride] = mb_type; + + return 0; +} + +static av_cold int mpeg_decode_init(AVCodecContext *avctx) +{ + Mpeg1Context *s = avctx->priv_data; + MpegEncContext *s2 = &s->mpeg_enc_ctx; + int i; + + /* we need some permutation to store matrices, + * until MPV_common_init() sets the real permutation. */ + for (i = 0; i < 64; i++) + s2->dsp.idct_permutation[i]=i; + + ff_MPV_decode_defaults(s2); + + s->mpeg_enc_ctx.avctx = avctx; + s->mpeg_enc_ctx.flags = avctx->flags; + s->mpeg_enc_ctx.flags2 = avctx->flags2; + ff_mpeg12_common_init(&s->mpeg_enc_ctx); + ff_mpeg12_init_vlcs(); + + s->mpeg_enc_ctx_allocated = 0; + s->mpeg_enc_ctx.picture_number = 0; + s->repeat_field = 0; + s->mpeg_enc_ctx.codec_id = avctx->codec->id; + avctx->color_range = AVCOL_RANGE_MPEG; + if (avctx->codec->id == AV_CODEC_ID_MPEG1VIDEO) + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + else + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + return 0; +} + +static int mpeg_decode_update_thread_context(AVCodecContext *avctx, const AVCodecContext *avctx_from) +{ + Mpeg1Context *ctx = avctx->priv_data, *ctx_from = avctx_from->priv_data; + MpegEncContext *s = &ctx->mpeg_enc_ctx, *s1 = &ctx_from->mpeg_enc_ctx; + int err; + + if (avctx == avctx_from || !ctx_from->mpeg_enc_ctx_allocated || !s1->context_initialized) + return 0; + + err = ff_mpeg_update_thread_context(avctx, avctx_from); + if (err) return err; + + if (!ctx->mpeg_enc_ctx_allocated) + memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext)); + + if (!(s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)) + s->picture_number++; + + return 0; +} + +static void quant_matrix_rebuild(uint16_t *matrix, const uint8_t *old_perm, + const uint8_t *new_perm) +{ + uint16_t temp_matrix[64]; + int i; + + memcpy(temp_matrix, matrix, 64 * sizeof(uint16_t)); + + for (i = 0; i < 64; i++) { + matrix[new_perm[i]] = temp_matrix[old_perm[i]]; + } +} + +static const enum AVPixelFormat mpeg1_hwaccel_pixfmt_list_420[] = { +#if CONFIG_MPEG_XVMC_DECODER + AV_PIX_FMT_XVMC_MPEG2_IDCT, + AV_PIX_FMT_XVMC_MPEG2_MC, +#endif +#if CONFIG_MPEG1_VDPAU_HWACCEL + AV_PIX_FMT_VDPAU_MPEG1, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = { +#if CONFIG_MPEG_XVMC_DECODER + AV_PIX_FMT_XVMC_MPEG2_IDCT, + AV_PIX_FMT_XVMC_MPEG2_MC, +#endif +#if CONFIG_MPEG2_VDPAU_HWACCEL + AV_PIX_FMT_VDPAU_MPEG2, +#endif +#if CONFIG_MPEG2_DXVA2_HWACCEL + AV_PIX_FMT_DXVA2_VLD, +#endif +#if CONFIG_MPEG2_VAAPI_HWACCEL + AV_PIX_FMT_VAAPI_VLD, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +static inline int uses_vdpau(AVCodecContext *avctx) { + return avctx->pix_fmt == AV_PIX_FMT_VDPAU_MPEG1 || avctx->pix_fmt == AV_PIX_FMT_VDPAU_MPEG2; +} + +static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + + if(s->chroma_format < 2) { + return avctx->get_format(avctx, + avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO ? + mpeg1_hwaccel_pixfmt_list_420 : + mpeg2_hwaccel_pixfmt_list_420); + } else if(s->chroma_format == 2) + return AV_PIX_FMT_YUV422P; + else + return AV_PIX_FMT_YUV444P; +} + +static void setup_hwaccel_for_pixfmt(AVCodecContext *avctx) +{ + if (avctx->pix_fmt != AV_PIX_FMT_XVMC_MPEG2_IDCT && avctx->pix_fmt != AV_PIX_FMT_XVMC_MPEG2_MC) { + avctx->xvmc_acceleration = 0; + } else if (!avctx->xvmc_acceleration) { + avctx->xvmc_acceleration = 2; + } + avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt); + // until then pix_fmt may be changed right after codec init + if (avctx->pix_fmt == AV_PIX_FMT_XVMC_MPEG2_IDCT || + avctx->hwaccel || uses_vdpau(avctx)) + if (avctx->idct_algo == FF_IDCT_AUTO) + avctx->idct_algo = FF_IDCT_SIMPLE; +} + +/* Call this function when we know all parameters. + * It may be called in different places for MPEG-1 and MPEG-2. */ +static int mpeg_decode_postinit(AVCodecContext *avctx) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + uint8_t old_permutation[64]; + + if ((s1->mpeg_enc_ctx_allocated == 0) || + avctx->coded_width != s->width || + avctx->coded_height != s->height || + s1->save_width != s->width || + s1->save_height != s->height || + s1->save_aspect_info != s->aspect_ratio_info || + s1->save_progressive_seq != s->progressive_sequence || + 0) + { + + if (s1->mpeg_enc_ctx_allocated) { + ParseContext pc = s->parse_context; + s->parse_context.buffer = 0; + ff_MPV_common_end(s); + s->parse_context = pc; + } + + if ((s->width == 0) || (s->height == 0)) + return -2; + + avcodec_set_dimensions(avctx, s->width, s->height); + if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->bit_rate) { + avctx->rc_max_rate = s->bit_rate; + } else if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && s->bit_rate && + (s->bit_rate != 0x3FFFF*400 || s->vbv_delay != 0xFFFF)) { + avctx->bit_rate = s->bit_rate; + } + s1->save_aspect_info = s->aspect_ratio_info; + s1->save_width = s->width; + s1->save_height = s->height; + s1->save_progressive_seq = s->progressive_sequence; + + /* low_delay may be forced, in this case we will have B-frames + * that behave like P-frames. */ + avctx->has_b_frames = !s->low_delay; + + if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { + //MPEG-1 fps + avctx->time_base.den = ff_mpeg12_frame_rate_tab[s->frame_rate_index].num; + avctx->time_base.num = ff_mpeg12_frame_rate_tab[s->frame_rate_index].den; + //MPEG-1 aspect + avctx->sample_aspect_ratio = av_d2q(1.0/ff_mpeg1_aspect[s->aspect_ratio_info], 255); + avctx->ticks_per_frame=1; + } else {//MPEG-2 + //MPEG-2 fps + av_reduce(&s->avctx->time_base.den, + &s->avctx->time_base.num, + ff_mpeg12_frame_rate_tab[s->frame_rate_index].num * s1->frame_rate_ext.num*2, + ff_mpeg12_frame_rate_tab[s->frame_rate_index].den * s1->frame_rate_ext.den, + 1 << 30); + avctx->ticks_per_frame = 2; + //MPEG-2 aspect + if (s->aspect_ratio_info > 1) { + AVRational dar = + av_mul_q(av_div_q(ff_mpeg2_aspect[s->aspect_ratio_info], + (AVRational) {s1->pan_scan.width, s1->pan_scan.height}), + (AVRational) {s->width, s->height}); + + // we ignore the spec here and guess a bit as reality does not match the spec, see for example + // res_change_ffmpeg_aspect.ts and sequence-display-aspect.mpg + // issue1613, 621, 562 + if ((s1->pan_scan.width == 0) || (s1->pan_scan.height == 0) || + (av_cmp_q(dar, (AVRational) {4, 3}) && av_cmp_q(dar, (AVRational) {16, 9}))) { + s->avctx->sample_aspect_ratio = + av_div_q(ff_mpeg2_aspect[s->aspect_ratio_info], + (AVRational) {s->width, s->height}); + } else { + s->avctx->sample_aspect_ratio = + av_div_q(ff_mpeg2_aspect[s->aspect_ratio_info], + (AVRational) {s1->pan_scan.width, s1->pan_scan.height}); +//issue1613 4/3 16/9 -> 16/9 +//res_change_ffmpeg_aspect.ts 4/3 225/44 ->4/3 +//widescreen-issue562.mpg 4/3 16/9 -> 16/9 +// s->avctx->sample_aspect_ratio = av_mul_q(s->avctx->sample_aspect_ratio, (AVRational) {s->width, s->height}); + av_dlog(avctx, "A %d/%d\n", + ff_mpeg2_aspect[s->aspect_ratio_info].num, ff_mpeg2_aspect[s->aspect_ratio_info].den); + av_dlog(avctx, "B %d/%d\n", s->avctx->sample_aspect_ratio.num, + s->avctx->sample_aspect_ratio.den); + } + } else { + s->avctx->sample_aspect_ratio = + ff_mpeg2_aspect[s->aspect_ratio_info]; + } + } // MPEG-2 + + avctx->pix_fmt = mpeg_get_pixelformat(avctx); + setup_hwaccel_for_pixfmt(avctx); + + /* Quantization matrices may need reordering + * if DCT permutation is changed. */ + memcpy(old_permutation, s->dsp.idct_permutation, 64 * sizeof(uint8_t)); + + if (ff_MPV_common_init(s) < 0) + return -2; + + quant_matrix_rebuild(s->intra_matrix, old_permutation, s->dsp.idct_permutation); + quant_matrix_rebuild(s->inter_matrix, old_permutation, s->dsp.idct_permutation); + quant_matrix_rebuild(s->chroma_intra_matrix, old_permutation, s->dsp.idct_permutation); + quant_matrix_rebuild(s->chroma_inter_matrix, old_permutation, s->dsp.idct_permutation); + + s1->mpeg_enc_ctx_allocated = 1; + } + return 0; +} + +static int mpeg1_decode_picture(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + int ref, f_code, vbv_delay; + + init_get_bits(&s->gb, buf, buf_size*8); + + ref = get_bits(&s->gb, 10); /* temporal ref */ + s->pict_type = get_bits(&s->gb, 3); + if (s->pict_type == 0 || s->pict_type > 3) + return -1; + + vbv_delay = get_bits(&s->gb, 16); + s->vbv_delay = vbv_delay; + if (s->pict_type == AV_PICTURE_TYPE_P || s->pict_type == AV_PICTURE_TYPE_B) { + s->full_pel[0] = get_bits1(&s->gb); + f_code = get_bits(&s->gb, 3); + if (f_code == 0 && (avctx->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT))) + return -1; + f_code += !f_code; + s->mpeg_f_code[0][0] = f_code; + s->mpeg_f_code[0][1] = f_code; + } + if (s->pict_type == AV_PICTURE_TYPE_B) { + s->full_pel[1] = get_bits1(&s->gb); + f_code = get_bits(&s->gb, 3); + if (f_code == 0 && (avctx->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT))) + return -1; + f_code += !f_code; + s->mpeg_f_code[1][0] = f_code; + s->mpeg_f_code[1][1] = f_code; + } + s->current_picture.f.pict_type = s->pict_type; + s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(avctx, AV_LOG_DEBUG, "vbv_delay %d, ref %d type:%d\n", vbv_delay, ref, s->pict_type); + + s->y_dc_scale = 8; + s->c_dc_scale = 8; + return 0; +} + +static void mpeg_decode_sequence_extension(Mpeg1Context *s1) +{ + MpegEncContext *s= &s1->mpeg_enc_ctx; + int horiz_size_ext, vert_size_ext; + int bit_rate_ext; + + skip_bits(&s->gb, 1); /* profile and level esc*/ + s->avctx->profile = get_bits(&s->gb, 3); + s->avctx->level = get_bits(&s->gb, 4); + s->progressive_sequence = get_bits1(&s->gb); /* progressive_sequence */ + s->chroma_format = get_bits(&s->gb, 2); /* chroma_format 1=420, 2=422, 3=444 */ + horiz_size_ext = get_bits(&s->gb, 2); + vert_size_ext = get_bits(&s->gb, 2); + s->width |= (horiz_size_ext << 12); + s->height |= (vert_size_ext << 12); + bit_rate_ext = get_bits(&s->gb, 12); /* XXX: handle it */ + s->bit_rate += (bit_rate_ext << 18) * 400; + skip_bits1(&s->gb); /* marker */ + s->avctx->rc_buffer_size += get_bits(&s->gb, 8) * 1024 * 16 << 10; + + s->low_delay = get_bits1(&s->gb); + if (s->flags & CODEC_FLAG_LOW_DELAY) + s->low_delay = 1; + + s1->frame_rate_ext.num = get_bits(&s->gb, 2) + 1; + s1->frame_rate_ext.den = get_bits(&s->gb, 5) + 1; + + av_dlog(s->avctx, "sequence extension\n"); + s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "profile: %d, level: %d vbv buffer: %d, bitrate:%d\n", + s->avctx->profile, s->avctx->level, s->avctx->rc_buffer_size, s->bit_rate); + +} + +static void mpeg_decode_sequence_display_extension(Mpeg1Context *s1) +{ + MpegEncContext *s = &s1->mpeg_enc_ctx; + int color_description, w, h; + + skip_bits(&s->gb, 3); /* video format */ + color_description = get_bits1(&s->gb); + if (color_description) { + s->avctx->color_primaries = get_bits(&s->gb, 8); + s->avctx->color_trc = get_bits(&s->gb, 8); + s->avctx->colorspace = get_bits(&s->gb, 8); + } + w = get_bits(&s->gb, 14); + skip_bits(&s->gb, 1); //marker + h = get_bits(&s->gb, 14); + // remaining 3 bits are zero padding + + s1->pan_scan.width = 16 * w; + s1->pan_scan.height = 16 * h; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "sde w:%d, h:%d\n", w, h); +} + +static void mpeg_decode_picture_display_extension(Mpeg1Context *s1) +{ + MpegEncContext *s = &s1->mpeg_enc_ctx; + int i, nofco; + + nofco = 1; + if (s->progressive_sequence) { + if (s->repeat_first_field) { + nofco++; + if (s->top_field_first) + nofco++; + } + } else { + if (s->picture_structure == PICT_FRAME) { + nofco++; + if (s->repeat_first_field) + nofco++; + } + } + for (i = 0; i < nofco; i++) { + s1->pan_scan.position[i][0] = get_sbits(&s->gb, 16); + skip_bits(&s->gb, 1); // marker + s1->pan_scan.position[i][1] = get_sbits(&s->gb, 16); + skip_bits(&s->gb, 1); // marker + } + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "pde (%d,%d) (%d,%d) (%d,%d)\n", + s1->pan_scan.position[0][0], s1->pan_scan.position[0][1], + s1->pan_scan.position[1][0], s1->pan_scan.position[1][1], + s1->pan_scan.position[2][0], s1->pan_scan.position[2][1]); +} + +static int load_matrix(MpegEncContext *s, uint16_t matrix0[64], uint16_t matrix1[64], int intra) +{ + int i; + + for (i = 0; i < 64; i++) { + int j = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + int v = get_bits(&s->gb, 8); + if (v == 0) { + av_log(s->avctx, AV_LOG_ERROR, "matrix damaged\n"); + return -1; + } + if (intra && i == 0 && v != 8) { + av_log(s->avctx, AV_LOG_DEBUG, "intra matrix specifies invalid DC quantizer %d, ignoring\n", v); + v = 8; // needed by pink.mpg / issue1046 + } + matrix0[j] = v; + if (matrix1) + matrix1[j] = v; + } + return 0; +} + +static void mpeg_decode_quant_matrix_extension(MpegEncContext *s) +{ + av_dlog(s->avctx, "matrix extension\n"); + + if (get_bits1(&s->gb)) load_matrix(s, s->chroma_intra_matrix, s->intra_matrix, 1); + if (get_bits1(&s->gb)) load_matrix(s, s->chroma_inter_matrix, s->inter_matrix, 0); + if (get_bits1(&s->gb)) load_matrix(s, s->chroma_intra_matrix, NULL , 1); + if (get_bits1(&s->gb)) load_matrix(s, s->chroma_inter_matrix, NULL , 0); +} + +static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) +{ + MpegEncContext *s = &s1->mpeg_enc_ctx; + + s->full_pel[0] = s->full_pel[1] = 0; + s->mpeg_f_code[0][0] = get_bits(&s->gb, 4); + s->mpeg_f_code[0][1] = get_bits(&s->gb, 4); + s->mpeg_f_code[1][0] = get_bits(&s->gb, 4); + s->mpeg_f_code[1][1] = get_bits(&s->gb, 4); + if (!s->pict_type && s1->mpeg_enc_ctx_allocated) { + av_log(s->avctx, AV_LOG_ERROR, "Missing picture start code, guessing missing values\n"); + if (s->mpeg_f_code[1][0] == 15 && s->mpeg_f_code[1][1] == 15) { + if (s->mpeg_f_code[0][0] == 15 && s->mpeg_f_code[0][1] == 15) + s->pict_type = AV_PICTURE_TYPE_I; + else + s->pict_type = AV_PICTURE_TYPE_P; + } else + s->pict_type = AV_PICTURE_TYPE_B; + s->current_picture.f.pict_type = s->pict_type; + s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + } + s->mpeg_f_code[0][0] += !s->mpeg_f_code[0][0]; + s->mpeg_f_code[0][1] += !s->mpeg_f_code[0][1]; + s->mpeg_f_code[1][0] += !s->mpeg_f_code[1][0]; + s->mpeg_f_code[1][1] += !s->mpeg_f_code[1][1]; + + s->intra_dc_precision = get_bits(&s->gb, 2); + s->picture_structure = get_bits(&s->gb, 2); + s->top_field_first = get_bits1(&s->gb); + s->frame_pred_frame_dct = get_bits1(&s->gb); + s->concealment_motion_vectors = get_bits1(&s->gb); + s->q_scale_type = get_bits1(&s->gb); + s->intra_vlc_format = get_bits1(&s->gb); + s->alternate_scan = get_bits1(&s->gb); + s->repeat_first_field = get_bits1(&s->gb); + s->chroma_420_type = get_bits1(&s->gb); + s->progressive_frame = get_bits1(&s->gb); + + + if (s->alternate_scan) { + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_alternate_vertical_scan); + } else { + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, ff_zigzag_direct); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); + } + + /* composite display not parsed */ + av_dlog(s->avctx, "intra_dc_precision=%d\n", s->intra_dc_precision); + av_dlog(s->avctx, "picture_structure=%d\n", s->picture_structure); + av_dlog(s->avctx, "top field first=%d\n", s->top_field_first); + av_dlog(s->avctx, "repeat first field=%d\n", s->repeat_first_field); + av_dlog(s->avctx, "conceal=%d\n", s->concealment_motion_vectors); + av_dlog(s->avctx, "intra_vlc_format=%d\n", s->intra_vlc_format); + av_dlog(s->avctx, "alternate_scan=%d\n", s->alternate_scan); + av_dlog(s->avctx, "frame_pred_frame_dct=%d\n", s->frame_pred_frame_dct); + av_dlog(s->avctx, "progressive_frame=%d\n", s->progressive_frame); +} + +static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) +{ + AVCodecContext *avctx = s->avctx; + Mpeg1Context *s1 = (Mpeg1Context*)s; + + /* start frame decoding */ + if (s->first_field || s->picture_structure == PICT_FRAME) { + AVFrameSideData *pan_scan; + + if (ff_MPV_frame_start(s, avctx) < 0) + return -1; + + ff_mpeg_er_frame_start(s); + + /* first check if we must repeat the frame */ + s->current_picture_ptr->f.repeat_pict = 0; + if (s->repeat_first_field) { + if (s->progressive_sequence) { + if (s->top_field_first) + s->current_picture_ptr->f.repeat_pict = 4; + else + s->current_picture_ptr->f.repeat_pict = 2; + } else if (s->progressive_frame) { + s->current_picture_ptr->f.repeat_pict = 1; + } + } + + pan_scan = av_frame_new_side_data(&s->current_picture_ptr->f, + AV_FRAME_DATA_PANSCAN, + sizeof(s1->pan_scan)); + if (!pan_scan) + return AVERROR(ENOMEM); + memcpy(pan_scan->data, &s1->pan_scan, sizeof(s1->pan_scan)); + + if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME)) + ff_thread_finish_setup(avctx); + } else { // second field + int i; + + if (!s->current_picture_ptr) { + av_log(s->avctx, AV_LOG_ERROR, "first field missing\n"); + return -1; + } + + if (s->avctx->hwaccel && + (s->avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) { + if (s->avctx->hwaccel->end_frame(s->avctx) < 0) + av_log(avctx, AV_LOG_ERROR, "hardware accelerator failed to decode first field\n"); + } + + for (i = 0; i < 4; i++) { + s->current_picture.f.data[i] = s->current_picture_ptr->f.data[i]; + if (s->picture_structure == PICT_BOTTOM_FIELD) { + s->current_picture.f.data[i] += s->current_picture_ptr->f.linesize[i]; + } + } + } + + if (avctx->hwaccel) { + if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0) + return -1; + } + +// MPV_frame_start will call this function too, +// but we need to call it on every field + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + if (ff_xvmc_field_start(s, avctx) < 0) + return -1; + + return 0; +} + +#define DECODE_SLICE_ERROR -1 +#define DECODE_SLICE_OK 0 + +/** + * Decode a slice. + * MpegEncContext.mb_y must be set to the MB row from the startcode. + * @return DECODE_SLICE_ERROR if the slice is damaged, + * DECODE_SLICE_OK if this slice is OK + */ +static int mpeg_decode_slice(MpegEncContext *s, int mb_y, + const uint8_t **buf, int buf_size) +{ + AVCodecContext *avctx = s->avctx; + const int lowres = s->avctx->lowres; + const int field_pic = s->picture_structure != PICT_FRAME; + + s->resync_mb_x = + s->resync_mb_y = -1; + + av_assert0(mb_y < s->mb_height); + + init_get_bits(&s->gb, *buf, buf_size * 8); + if(s->codec_id != AV_CODEC_ID_MPEG1VIDEO && s->mb_height > 2800/16) + skip_bits(&s->gb, 3); + + ff_mpeg1_clean_buffers(s); + s->interlaced_dct = 0; + + s->qscale = get_qscale(s); + + if (s->qscale == 0) { + av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n"); + return -1; + } + + /* extra slice info */ + while (get_bits1(&s->gb) != 0) { + skip_bits(&s->gb, 8); + } + + s->mb_x = 0; + + if (mb_y == 0 && s->codec_tag == AV_RL32("SLIF")) { + skip_bits1(&s->gb); + } else { + while (get_bits_left(&s->gb) > 0) { + int code = get_vlc2(&s->gb, mbincr_vlc.table, MBINCR_VLC_BITS, 2); + if (code < 0) { + av_log(s->avctx, AV_LOG_ERROR, "first mb_incr damaged\n"); + return -1; + } + if (code >= 33) { + if (code == 33) { + s->mb_x += 33; + } + /* otherwise, stuffing, nothing to do */ + } else { + s->mb_x += code; + break; + } + } + } + + if (s->mb_x >= (unsigned)s->mb_width) { + av_log(s->avctx, AV_LOG_ERROR, "initial skip overflow\n"); + return -1; + } + + if (avctx->hwaccel) { + const uint8_t *buf_end, *buf_start = *buf - 4; /* include start_code */ + int start_code = -1; + buf_end = avpriv_mpv_find_start_code(buf_start + 2, *buf + buf_size, &start_code); + if (buf_end < *buf + buf_size) + buf_end -= 4; + s->mb_y = mb_y; + if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_end - buf_start) < 0) + return DECODE_SLICE_ERROR; + *buf = buf_end; + return DECODE_SLICE_OK; + } + + s->resync_mb_x = s->mb_x; + s->resync_mb_y = s->mb_y = mb_y; + s->mb_skip_run = 0; + ff_init_block_index(s); + + if (s->mb_y == 0 && s->mb_x == 0 && (s->first_field || s->picture_structure == PICT_FRAME)) { + if (s->avctx->debug & FF_DEBUG_PICT_INFO) { + av_log(s->avctx, AV_LOG_DEBUG, "qp:%d fc:%2d%2d%2d%2d %s %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", + s->qscale, s->mpeg_f_code[0][0], s->mpeg_f_code[0][1], s->mpeg_f_code[1][0], s->mpeg_f_code[1][1], + s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + s->progressive_sequence ? "ps" :"", s->progressive_frame ? "pf" : "", s->alternate_scan ? "alt" :"", s->top_field_first ? "top" :"", + s->intra_dc_precision, s->picture_structure, s->frame_pred_frame_dct, s->concealment_motion_vectors, + s->q_scale_type, s->intra_vlc_format, s->repeat_first_field, s->chroma_420_type ? "420" :""); + } + } + + for (;;) { + // If 1, we memcpy blocks in xvmcvideo. + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) + ff_xvmc_init_block(s); // set s->block + + if (mpeg_decode_mb(s, s->block) < 0) + return -1; + + if (s->current_picture.motion_val[0] && !s->encoding) { // note motion_val is normally NULL unless we want to extract the MVs + const int wrap = s->b8_stride; + int xy = s->mb_x * 2 + s->mb_y * 2 * wrap; + int b8_xy = 4 * (s->mb_x + s->mb_y * s->mb_stride); + int motion_x, motion_y, dir, i; + + for (i = 0; i < 2; i++) { + for (dir = 0; dir < 2; dir++) { + if (s->mb_intra || (dir == 1 && s->pict_type != AV_PICTURE_TYPE_B)) { + motion_x = motion_y = 0; + } else if (s->mv_type == MV_TYPE_16X16 || (s->mv_type == MV_TYPE_FIELD && field_pic)) { + motion_x = s->mv[dir][0][0]; + motion_y = s->mv[dir][0][1]; + } else /*if ((s->mv_type == MV_TYPE_FIELD) || (s->mv_type == MV_TYPE_16X8))*/ { + motion_x = s->mv[dir][i][0]; + motion_y = s->mv[dir][i][1]; + } + + s->current_picture.motion_val[dir][xy ][0] = motion_x; + s->current_picture.motion_val[dir][xy ][1] = motion_y; + s->current_picture.motion_val[dir][xy + 1][0] = motion_x; + s->current_picture.motion_val[dir][xy + 1][1] = motion_y; + s->current_picture.ref_index [dir][b8_xy ] = + s->current_picture.ref_index [dir][b8_xy + 1] = s->field_select[dir][i]; + av_assert2(s->field_select[dir][i] == 0 || s->field_select[dir][i] == 1); + } + xy += wrap; + b8_xy +=2; + } + } + + s->dest[0] += 16 >> lowres; + s->dest[1] +=(16 >> lowres) >> s->chroma_x_shift; + s->dest[2] +=(16 >> lowres) >> s->chroma_x_shift; + + ff_MPV_decode_mb(s, s->block); + + if (++s->mb_x >= s->mb_width) { + const int mb_size = 16 >> s->avctx->lowres; + + ff_mpeg_draw_horiz_band(s, mb_size*(s->mb_y >> field_pic), mb_size); + ff_MPV_report_decode_progress(s); + + s->mb_x = 0; + s->mb_y += 1 << field_pic; + + if (s->mb_y >= s->mb_height) { + int left = get_bits_left(&s->gb); + int is_d10 = s->chroma_format == 2 && s->pict_type == AV_PICTURE_TYPE_I && avctx->profile == 0 && avctx->level == 5 + && s->intra_dc_precision == 2 && s->q_scale_type == 1 && s->alternate_scan == 0 + && s->progressive_frame == 0 /* vbv_delay == 0xBBB || 0xE10*/; + + if (left >= 32 && !is_d10) { + GetBitContext gb = s->gb; + align_get_bits(&gb); + if (show_bits(&gb, 24) == 0x060E2B) { + av_log(avctx, AV_LOG_DEBUG, "Invalid MXF data found in video stream\n"); + is_d10 = 1; + } + } + + if (left < 0 || (left && show_bits(&s->gb, FFMIN(left, 23)) && !is_d10) + || ((avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_AGGRESSIVE)) && left > 8)) { + av_log(avctx, AV_LOG_ERROR, "end mismatch left=%d %0X\n", left, show_bits(&s->gb, FFMIN(left, 23))); + return -1; + } else + goto eos; + } + + ff_init_block_index(s); + } + + /* skip mb handling */ + if (s->mb_skip_run == -1) { + /* read increment again */ + s->mb_skip_run = 0; + for (;;) { + int code = get_vlc2(&s->gb, mbincr_vlc.table, MBINCR_VLC_BITS, 2); + if (code < 0) { + av_log(s->avctx, AV_LOG_ERROR, "mb incr damaged\n"); + return -1; + } + if (code >= 33) { + if (code == 33) { + s->mb_skip_run += 33; + } else if (code == 35) { + if (s->mb_skip_run != 0 || show_bits(&s->gb, 15) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "slice mismatch\n"); + return -1; + } + goto eos; /* end of slice */ + } + /* otherwise, stuffing, nothing to do */ + } else { + s->mb_skip_run += code; + break; + } + } + if (s->mb_skip_run) { + int i; + if (s->pict_type == AV_PICTURE_TYPE_I) { + av_log(s->avctx, AV_LOG_ERROR, "skipped MB in I frame at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + /* skip mb */ + s->mb_intra = 0; + for (i = 0; i < 12; i++) + s->block_last_index[i] = -1; + if (s->picture_structure == PICT_FRAME) + s->mv_type = MV_TYPE_16X16; + else + s->mv_type = MV_TYPE_FIELD; + if (s->pict_type == AV_PICTURE_TYPE_P) { + /* if P type, zero motion vector is implied */ + s->mv_dir = MV_DIR_FORWARD; + s->mv[0][0][0] = s->mv[0][0][1] = 0; + s->last_mv[0][0][0] = s->last_mv[0][0][1] = 0; + s->last_mv[0][1][0] = s->last_mv[0][1][1] = 0; + s->field_select[0][0] = (s->picture_structure - 1) & 1; + } else { + /* if B type, reuse previous vectors and directions */ + s->mv[0][0][0] = s->last_mv[0][0][0]; + s->mv[0][0][1] = s->last_mv[0][0][1]; + s->mv[1][0][0] = s->last_mv[1][0][0]; + s->mv[1][0][1] = s->last_mv[1][0][1]; + } + } + } + } +eos: // end of slice + *buf += (get_bits_count(&s->gb)-1)/8; + av_dlog(s, "y %d %d %d %d\n", s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y); + return 0; +} + +static int slice_decode_thread(AVCodecContext *c, void *arg) +{ + MpegEncContext *s = *(void**)arg; + const uint8_t *buf = s->gb.buffer; + int mb_y = s->start_mb_y; + const int field_pic = s->picture_structure != PICT_FRAME; + + s->er.error_count = (3 * (s->end_mb_y - s->start_mb_y) * s->mb_width) >> field_pic; + + for (;;) { + uint32_t start_code; + int ret; + + ret = mpeg_decode_slice(s, mb_y, &buf, s->gb.buffer_end - buf); + emms_c(); + av_dlog(c, "ret:%d resync:%d/%d mb:%d/%d ts:%d/%d ec:%d\n", + ret, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, + s->start_mb_y, s->end_mb_y, s->er.error_count); + if (ret < 0) { + if (c->err_recognition & AV_EF_EXPLODE) + return ret; + if (s->resync_mb_x >= 0 && s->resync_mb_y >= 0) + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_AC_ERROR | ER_DC_ERROR | ER_MV_ERROR); + } else { + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_AC_END | ER_DC_END | ER_MV_END); + } + + if (s->mb_y == s->end_mb_y) + return 0; + + start_code = -1; + buf = avpriv_mpv_find_start_code(buf, s->gb.buffer_end, &start_code); + mb_y= start_code - SLICE_MIN_START_CODE; + if(s->codec_id != AV_CODEC_ID_MPEG1VIDEO && s->mb_height > 2800/16) + mb_y += (*buf&0xE0)<<2; + mb_y <<= field_pic; + if (s->picture_structure == PICT_BOTTOM_FIELD) + mb_y++; + if (mb_y < 0 || mb_y >= s->end_mb_y) + return -1; + } +} + +/** + * Handle slice ends. + * @return 1 if it seems to be the last slice + */ +static int slice_end(AVCodecContext *avctx, AVFrame *pict) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + + if (!s1->mpeg_enc_ctx_allocated || !s->current_picture_ptr) + return 0; + + if (s->avctx->hwaccel) { + if (s->avctx->hwaccel->end_frame(s->avctx) < 0) + av_log(avctx, AV_LOG_ERROR, "hardware accelerator failed to decode picture\n"); + } + + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + ff_xvmc_field_end(s); + + /* end of slice reached */ + if (/*s->mb_y << field_pic == s->mb_height &&*/ !s->first_field && !s->first_slice) { + /* end of image */ + + ff_er_frame_end(&s->er); + + ff_MPV_frame_end(s); + + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { + int ret = av_frame_ref(pict, &s->current_picture_ptr->f); + if (ret < 0) + return ret; + ff_print_debug_info(s, s->current_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG2); + } else { + if (avctx->active_thread_type & FF_THREAD_FRAME) + s->picture_number++; + /* latency of 1 frame for I- and P-frames */ + /* XXX: use another variable than picture_number */ + if (s->last_picture_ptr != NULL) { + int ret = av_frame_ref(pict, &s->last_picture_ptr->f); + if (ret < 0) + return ret; + ff_print_debug_info(s, s->last_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG2); + } + } + + return 1; + } else { + return 0; + } +} + +static int mpeg1_decode_sequence(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + int width, height; + int i, v, j; + + init_get_bits(&s->gb, buf, buf_size*8); + + width = get_bits(&s->gb, 12); + height = get_bits(&s->gb, 12); + if (width == 0 || height == 0) { + av_log(avctx, AV_LOG_WARNING, "Invalid horizontal or vertical size " + "value.\n"); + if (avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_COMPLIANT)) + return AVERROR_INVALIDDATA; + } + s->aspect_ratio_info = get_bits(&s->gb, 4); + if (s->aspect_ratio_info == 0) { + av_log(avctx, AV_LOG_ERROR, "aspect ratio has forbidden 0 value\n"); + if (avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_COMPLIANT)) + return -1; + } + s->frame_rate_index = get_bits(&s->gb, 4); + if (s->frame_rate_index == 0 || s->frame_rate_index > 13) + return -1; + s->bit_rate = get_bits(&s->gb, 18) * 400; + if (get_bits1(&s->gb) == 0) /* marker */ + return -1; + s->width = width; + s->height = height; + + s->avctx->rc_buffer_size = get_bits(&s->gb, 10) * 1024 * 16; + skip_bits(&s->gb, 1); + + /* get matrix */ + if (get_bits1(&s->gb)) { + load_matrix(s, s->chroma_intra_matrix, s->intra_matrix, 1); + } else { + for (i = 0; i < 64; i++) { + j = s->dsp.idct_permutation[i]; + v = ff_mpeg1_default_intra_matrix[i]; + s->intra_matrix[j] = v; + s->chroma_intra_matrix[j] = v; + } + } + if (get_bits1(&s->gb)) { + load_matrix(s, s->chroma_inter_matrix, s->inter_matrix, 0); + } else { + for (i = 0; i < 64; i++) { + int j = s->dsp.idct_permutation[i]; + v = ff_mpeg1_default_non_intra_matrix[i]; + s->inter_matrix[j] = v; + s->chroma_inter_matrix[j] = v; + } + } + + if (show_bits(&s->gb, 23) != 0) { + av_log(s->avctx, AV_LOG_ERROR, "sequence header damaged\n"); + return -1; + } + + /* we set MPEG-2 parameters so that it emulates MPEG-1 */ + s->progressive_sequence = 1; + s->progressive_frame = 1; + s->picture_structure = PICT_FRAME; + s->first_field = 0; + s->frame_pred_frame_dct = 1; + s->chroma_format = 1; + s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; + s->out_format = FMT_MPEG1; + s->swap_uv = 0; // AFAIK VCR2 does not have SEQ_HEADER + if (s->flags & CODEC_FLAG_LOW_DELAY) + s->low_delay = 1; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "vbv buffer: %d, bitrate:%d\n", + s->avctx->rc_buffer_size, s->bit_rate); + + return 0; +} + +static int vcr2_init_sequence(AVCodecContext *avctx) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + int i, v; + + /* start new MPEG-1 context decoding */ + s->out_format = FMT_MPEG1; + if (s1->mpeg_enc_ctx_allocated) { + ff_MPV_common_end(s); + } + s->width = avctx->coded_width; + s->height = avctx->coded_height; + avctx->has_b_frames = 0; // true? + s->low_delay = 1; + + avctx->pix_fmt = mpeg_get_pixelformat(avctx); + setup_hwaccel_for_pixfmt(avctx); + + if (ff_MPV_common_init(s) < 0) + return -1; + s1->mpeg_enc_ctx_allocated = 1; + + for (i = 0; i < 64; i++) { + int j = s->dsp.idct_permutation[i]; + v = ff_mpeg1_default_intra_matrix[i]; + s->intra_matrix[j] = v; + s->chroma_intra_matrix[j] = v; + + v = ff_mpeg1_default_non_intra_matrix[i]; + s->inter_matrix[j] = v; + s->chroma_inter_matrix[j] = v; + } + + s->progressive_sequence = 1; + s->progressive_frame = 1; + s->picture_structure = PICT_FRAME; + s->first_field = 0; + s->frame_pred_frame_dct = 1; + s->chroma_format = 1; + if (s->codec_tag == AV_RL32("BW10")) { + s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; + } else { + exchange_uv(s); // common init reset pblocks, so we swap them here + s->swap_uv = 1; // in case of xvmc we need to swap uv for each MB + s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; + } + s1->save_width = s->width; + s1->save_height = s->height; + s1->save_progressive_seq = s->progressive_sequence; + return 0; +} + + +static void mpeg_decode_user_data(AVCodecContext *avctx, + const uint8_t *p, int buf_size) +{ + Mpeg1Context *s = avctx->priv_data; + const uint8_t *buf_end = p + buf_size; + + if(buf_size > 29){ + int i; + for(i=0; i<20; i++) + if(!memcmp(p+i, "\0TMPGEXS\0", 9)){ + s->tmpgexs= 1; + } + +/* for(i=0; !(!p[i-2] && !p[i-1] && p[i]==1) && i= 5 && + p[0] == 'D' && p[1] == 'T' && p[2] == 'G' && p[3] == '1') { + int flags = p[4]; + p += 5; + if (flags & 0x80) { + /* skip event id */ + p += 2; + } + if (flags & 0x40) { + if (buf_end - p < 1) + return; + avctx->dtg_active_format = p[0] & 0x0f; + } + } +} + +static void mpeg_decode_gop(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + int broken_link; + int64_t tc; + + init_get_bits(&s->gb, buf, buf_size*8); + + tc = avctx->timecode_frame_start = get_bits(&s->gb, 25); + + s->closed_gop = get_bits1(&s->gb); + /*broken_link indicate that after editing the + reference frames of the first B-Frames after GOP I-Frame + are missing (open gop)*/ + broken_link = get_bits1(&s->gb); + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) { + char tcbuf[AV_TIMECODE_STR_SIZE]; + av_timecode_make_mpeg_tc_string(tcbuf, tc); + av_log(s->avctx, AV_LOG_DEBUG, + "GOP (%s) closed_gop=%d broken_link=%d\n", + tcbuf, s->closed_gop, broken_link); + } +} +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s) +{ + int i; + uint32_t state = pc->state; + + /* EOF considered as end of frame */ + if (buf_size == 0) + return 0; + +/* + 0 frame start -> 1/4 + 1 first_SEQEXT -> 0/2 + 2 first field start -> 3/0 + 3 second_SEQEXT -> 2/0 + 4 searching end +*/ + + for (i = 0; i < buf_size; i++) { + av_assert1(pc->frame_start_found >= 0 && pc->frame_start_found <= 4); + if (pc->frame_start_found & 1) { + if (state == EXT_START_CODE && (buf[i] & 0xF0) != 0x80) + pc->frame_start_found--; + else if (state == EXT_START_CODE + 2) { + if ((buf[i] & 3) == 3) + pc->frame_start_found = 0; + else + pc->frame_start_found = (pc->frame_start_found + 1) & 3; + } + state++; + } else { + i = avpriv_mpv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1; + if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) { + i++; + pc->frame_start_found = 4; + } + if (state == SEQ_END_CODE) { + pc->frame_start_found = 0; + pc->state=-1; + return i+1; + } + if (pc->frame_start_found == 2 && state == SEQ_START_CODE) + pc->frame_start_found = 0; + if (pc->frame_start_found < 4 && state == EXT_START_CODE) + pc->frame_start_found++; + if (pc->frame_start_found == 4 && (state & 0xFFFFFF00) == 0x100) { + if (state < SLICE_MIN_START_CODE || state > SLICE_MAX_START_CODE) { + pc->frame_start_found = 0; + pc->state = -1; + return i - 3; + } + } + if (pc->frame_start_found == 0 && s && state == PICTURE_START_CODE) { + ff_fetch_timestamp(s, i - 3, 1); + } + } + } + pc->state = state; + return END_NOT_FOUND; +} + +static int decode_chunks(AVCodecContext *avctx, + AVFrame *picture, int *got_output, + const uint8_t *buf, int buf_size) +{ + Mpeg1Context *s = avctx->priv_data; + MpegEncContext *s2 = &s->mpeg_enc_ctx; + const uint8_t *buf_ptr = buf; + const uint8_t *buf_end = buf + buf_size; + int ret, input_size; + int last_code = 0; + int picture_start_code_seen = 0; + + for (;;) { + /* find next start code */ + uint32_t start_code = -1; + buf_ptr = avpriv_mpv_find_start_code(buf_ptr, buf_end, &start_code); + if (start_code > 0x1ff) { + if (s2->pict_type != AV_PICTURE_TYPE_B || avctx->skip_frame <= AVDISCARD_DEFAULT) { + if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_SLICE)) { + int i; + av_assert0(avctx->thread_count > 1); + + avctx->execute(avctx, slice_decode_thread, &s2->thread_context[0], NULL, s->slice_count, sizeof(void*)); + for (i = 0; i < s->slice_count; i++) + s2->er.error_count += s2->thread_context[i]->er.error_count; + } + + if (CONFIG_VDPAU && uses_vdpau(avctx)) + ff_vdpau_mpeg_picture_complete(s2, buf, buf_size, s->slice_count); + + ret = slice_end(avctx, picture); + if (ret < 0) + return ret; + else if (ret) { + if (s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice + *got_output = 1; + } + } + s2->pict_type = 0; + return FFMAX(0, buf_ptr - buf - s2->parse_context.last_index); + } + + input_size = buf_end - buf_ptr; + + if (avctx->debug & FF_DEBUG_STARTCODE) { + av_log(avctx, AV_LOG_DEBUG, "%3X at %td left %d\n", start_code, buf_ptr-buf, input_size); + } + + /* prepare data for next start code */ + switch (start_code) { + case SEQ_START_CODE: + if (last_code == 0) { + mpeg1_decode_sequence(avctx, buf_ptr, input_size); + if(buf != avctx->extradata) + s->sync=1; + } else { + av_log(avctx, AV_LOG_ERROR, "ignoring SEQ_START_CODE after %X\n", last_code); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + break; + + case PICTURE_START_CODE: + if (picture_start_code_seen && s2->picture_structure == PICT_FRAME) { + /* If it's a frame picture, there can't be more than one picture header. + Yet, it does happen and we need to handle it. */ + av_log(avctx, AV_LOG_WARNING, "ignoring extra picture following a frame-picture\n"); + break; + } + picture_start_code_seen = 1; + + if (s2->width <= 0 || s2->height <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d.\n", + s2->width, s2->height); + return AVERROR_INVALIDDATA; + } + + if(s->tmpgexs){ + s2->intra_dc_precision= 3; + s2->intra_matrix[0]= 1; + } + if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_SLICE) && s->slice_count) { + int i; + + avctx->execute(avctx, slice_decode_thread, + s2->thread_context, NULL, + s->slice_count, sizeof(void*)); + for (i = 0; i < s->slice_count; i++) + s2->er.error_count += s2->thread_context[i]->er.error_count; + s->slice_count = 0; + } + if (last_code == 0 || last_code == SLICE_MIN_START_CODE) { + ret = mpeg_decode_postinit(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "mpeg_decode_postinit() failure\n"); + return ret; + } + + /* we have a complete image: we try to decompress it */ + if (mpeg1_decode_picture(avctx, buf_ptr, input_size) < 0) + s2->pict_type = 0; + s2->first_slice = 1; + last_code = PICTURE_START_CODE; + } else { + av_log(avctx, AV_LOG_ERROR, "ignoring pic after %X\n", last_code); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + break; + case EXT_START_CODE: + init_get_bits(&s2->gb, buf_ptr, input_size*8); + + switch (get_bits(&s2->gb, 4)) { + case 0x1: + if (last_code == 0) { + mpeg_decode_sequence_extension(s); + } else { + av_log(avctx, AV_LOG_ERROR, "ignoring seq ext after %X\n", last_code); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + break; + case 0x2: + mpeg_decode_sequence_display_extension(s); + break; + case 0x3: + mpeg_decode_quant_matrix_extension(s2); + break; + case 0x7: + mpeg_decode_picture_display_extension(s); + break; + case 0x8: + if (last_code == PICTURE_START_CODE) { + mpeg_decode_picture_coding_extension(s); + } else { + av_log(avctx, AV_LOG_ERROR, "ignoring pic cod ext after %X\n", last_code); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + break; + } + break; + case USER_START_CODE: + mpeg_decode_user_data(avctx, buf_ptr, input_size); + break; + case GOP_START_CODE: + if (last_code == 0) { + s2->first_field=0; + mpeg_decode_gop(avctx, buf_ptr, input_size); + s->sync=1; + } else { + av_log(avctx, AV_LOG_ERROR, "ignoring GOP_START_CODE after %X\n", last_code); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + break; + default: + if (start_code >= SLICE_MIN_START_CODE && + start_code <= SLICE_MAX_START_CODE && last_code == PICTURE_START_CODE) { + + if (s2->progressive_sequence && !s2->progressive_frame) { + s2->progressive_frame = 1; + av_log(s2->avctx, AV_LOG_ERROR, "interlaced frame in progressive sequence, ignoring\n"); + } + + if (s2->picture_structure == 0 || (s2->progressive_frame && s2->picture_structure != PICT_FRAME)) { + av_log(s2->avctx, AV_LOG_ERROR, "picture_structure %d invalid, ignoring\n", s2->picture_structure); + s2->picture_structure = PICT_FRAME; + } + + if (s2->progressive_sequence && !s2->frame_pred_frame_dct) { + av_log(s2->avctx, AV_LOG_WARNING, "invalid frame_pred_frame_dct\n"); + } + + if (s2->picture_structure == PICT_FRAME) { + s2->first_field = 0; + s2->v_edge_pos = 16 * s2->mb_height; + } else { + s2->first_field ^= 1; + s2->v_edge_pos = 8 * s2->mb_height; + memset(s2->mbskip_table, 0, s2->mb_stride * s2->mb_height); + } + } + if (start_code >= SLICE_MIN_START_CODE && + start_code <= SLICE_MAX_START_CODE && last_code != 0) { + const int field_pic = s2->picture_structure != PICT_FRAME; + int mb_y = start_code - SLICE_MIN_START_CODE; + last_code = SLICE_MIN_START_CODE; + if(s2->codec_id != AV_CODEC_ID_MPEG1VIDEO && s2->mb_height > 2800/16) + mb_y += (*buf_ptr&0xE0)<<2; + + mb_y <<= field_pic; + if (s2->picture_structure == PICT_BOTTOM_FIELD) + mb_y++; + + if (mb_y >= s2->mb_height) { + av_log(s2->avctx, AV_LOG_ERROR, "slice below image (%d >= %d)\n", mb_y, s2->mb_height); + return -1; + } + + if (s2->last_picture_ptr == NULL) { + /* Skip B-frames if we do not have reference frames and gop is not closed */ + if (s2->pict_type == AV_PICTURE_TYPE_B) { + if (!s2->closed_gop) + break; + } + } + if (s2->pict_type == AV_PICTURE_TYPE_I || (s2->flags2 & CODEC_FLAG2_SHOW_ALL)) + s->sync=1; + if (s2->next_picture_ptr == NULL) { + /* Skip P-frames if we do not have a reference frame or we have an invalid header. */ + if (s2->pict_type == AV_PICTURE_TYPE_P && !s->sync) break; + } + if ((avctx->skip_frame >= AVDISCARD_NONREF && s2->pict_type == AV_PICTURE_TYPE_B) || + (avctx->skip_frame >= AVDISCARD_NONKEY && s2->pict_type != AV_PICTURE_TYPE_I) || + avctx->skip_frame >= AVDISCARD_ALL) + break; + + if (!s->mpeg_enc_ctx_allocated) + break; + + if (s2->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (mb_y < avctx->skip_top || mb_y >= s2->mb_height - avctx->skip_bottom) + break; + } + + if (!s2->pict_type) { + av_log(avctx, AV_LOG_ERROR, "Missing picture start code\n"); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + break; + } + + if (s2->first_slice) { + s2->first_slice = 0; + if (mpeg_field_start(s2, buf, buf_size) < 0) + return -1; + } + if (!s2->current_picture_ptr) { + av_log(avctx, AV_LOG_ERROR, "current_picture not initialized\n"); + return AVERROR_INVALIDDATA; + } + + if (uses_vdpau(avctx)) { + s->slice_count++; + break; + } + + if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_SLICE)) { + int threshold = (s2->mb_height * s->slice_count + + s2->slice_context_count / 2) / + s2->slice_context_count; + av_assert0(avctx->thread_count > 1); + if (threshold <= mb_y) { + MpegEncContext *thread_context = s2->thread_context[s->slice_count]; + + thread_context->start_mb_y = mb_y; + thread_context->end_mb_y = s2->mb_height; + if (s->slice_count) { + s2->thread_context[s->slice_count-1]->end_mb_y = mb_y; + ret = ff_update_duplicate_context(thread_context, + s2); + if (ret < 0) + return ret; + } + init_get_bits(&thread_context->gb, buf_ptr, input_size*8); + s->slice_count++; + } + buf_ptr += 2; // FIXME add minimum number of bytes per slice + } else { + ret = mpeg_decode_slice(s2, mb_y, &buf_ptr, input_size); + emms_c(); + + if (ret < 0) { + if (avctx->err_recognition & AV_EF_EXPLODE) + return ret; + if (s2->resync_mb_x >= 0 && s2->resync_mb_y >= 0) + ff_er_add_slice(&s2->er, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x, s2->mb_y, ER_AC_ERROR | ER_DC_ERROR | ER_MV_ERROR); + } else { + ff_er_add_slice(&s2->er, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x-1, s2->mb_y, ER_AC_END | ER_DC_END | ER_MV_END); + } + } + } + break; + } + } +} + +static int mpeg_decode_frame(AVCodecContext *avctx, + void *data, int *got_output, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int ret; + int buf_size = avpkt->size; + Mpeg1Context *s = avctx->priv_data; + AVFrame *picture = data; + MpegEncContext *s2 = &s->mpeg_enc_ctx; + av_dlog(avctx, "fill_buffer\n"); + + if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == SEQ_END_CODE)) { + /* special case for last picture */ + if (s2->low_delay == 0 && s2->next_picture_ptr) { + int ret = av_frame_ref(picture, &s2->next_picture_ptr->f); + if (ret < 0) + return ret; + + s2->next_picture_ptr = NULL; + + *got_output = 1; + } + return buf_size; + } + + if (s2->flags & CODEC_FLAG_TRUNCATED) { + int next = ff_mpeg1_find_frame_end(&s2->parse_context, buf, buf_size, NULL); + + if (ff_combine_frame(&s2->parse_context, next, (const uint8_t **)&buf, &buf_size) < 0) + return buf_size; + } + + s2->codec_tag = avpriv_toupper4(avctx->codec_tag); + if (s->mpeg_enc_ctx_allocated == 0 && ( s2->codec_tag == AV_RL32("VCR2") + || s2->codec_tag == AV_RL32("BW10") + )) + vcr2_init_sequence(avctx); + + s->slice_count = 0; + + if (avctx->extradata && !s->extradata_decoded) { + ret = decode_chunks(avctx, picture, got_output, avctx->extradata, avctx->extradata_size); + if(*got_output) { + av_log(avctx, AV_LOG_ERROR, "picture in extradata\n"); + *got_output = 0; + } + s->extradata_decoded = 1; + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) { + s2->current_picture_ptr = NULL; + return ret; + } + } + + ret = decode_chunks(avctx, picture, got_output, buf, buf_size); + if (ret<0 || *got_output) + s2->current_picture_ptr = NULL; + + return ret; +} + + +static void flush(AVCodecContext *avctx) +{ + Mpeg1Context *s = avctx->priv_data; + + s->sync=0; + + ff_mpeg_flush(avctx); +} + +static int mpeg_decode_end(AVCodecContext *avctx) +{ + Mpeg1Context *s = avctx->priv_data; + + if (s->mpeg_enc_ctx_allocated) + ff_MPV_common_end(&s->mpeg_enc_ctx); + return 0; +} + +static const AVProfile mpeg2_video_profiles[] = { + { FF_PROFILE_MPEG2_422, "4:2:2" }, + { FF_PROFILE_MPEG2_HIGH, "High" }, + { FF_PROFILE_MPEG2_SS, "Spatially Scalable" }, + { FF_PROFILE_MPEG2_SNR_SCALABLE, "SNR Scalable" }, + { FF_PROFILE_MPEG2_MAIN, "Main" }, + { FF_PROFILE_MPEG2_SIMPLE, "Simple" }, + { FF_PROFILE_RESERVED, "Reserved" }, + { FF_PROFILE_RESERVED, "Reserved" }, + { FF_PROFILE_UNKNOWN }, +}; + + +AVCodec ff_mpeg1video_decoder = { + .name = "mpeg1video", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG1VIDEO, + .priv_data_size = sizeof(Mpeg1Context), + .init = mpeg_decode_init, + .close = mpeg_decode_end, + .decode = mpeg_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | + CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | + CODEC_CAP_SLICE_THREADS, + .flush = flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), + .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context) +}; + +AVCodec ff_mpeg2video_decoder = { + .name = "mpeg2video", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(Mpeg1Context), + .init = mpeg_decode_init, + .close = mpeg_decode_end, + .decode = mpeg_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | + CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | + CODEC_CAP_SLICE_THREADS, + .flush = flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), + .profiles = NULL_IF_CONFIG_SMALL(mpeg2_video_profiles), +}; + +//legacy decoder +AVCodec ff_mpegvideo_decoder = { + .name = "mpegvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(Mpeg1Context), + .init = mpeg_decode_init, + .close = mpeg_decode_end, + .decode = mpeg_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .flush = flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), +}; + +#if CONFIG_MPEG_XVMC_DECODER +static av_cold int mpeg_mc_decode_init(AVCodecContext *avctx) +{ + if (avctx->active_thread_type & FF_THREAD_SLICE) + return -1; + if (!(avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) + return -1; + if (!(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) { + av_dlog(avctx, "mpeg12.c: XvMC decoder will work better if SLICE_FLAG_ALLOW_FIELD is set\n"); + } + mpeg_decode_init(avctx); + + avctx->pix_fmt = AV_PIX_FMT_XVMC_MPEG2_IDCT; + avctx->xvmc_acceleration = 2; // 2 - the blocks are packed! + + return 0; +} + +AVCodec ff_mpeg_xvmc_decoder = { + .name = "mpegvideo_xvmc", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO_XVMC, + .priv_data_size = sizeof(Mpeg1Context), + .init = mpeg_mc_decode_init, + .close = mpeg_decode_end, + .decode = mpeg_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | + CODEC_CAP_TRUNCATED| CODEC_CAP_HWACCEL | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video XvMC (X-Video Motion Compensation)"), +}; + +#endif + +#if CONFIG_MPEG_VDPAU_DECODER +AVCodec ff_mpeg_vdpau_decoder = { + .name = "mpegvideo_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(Mpeg1Context), + .init = mpeg_decode_init, + .close = mpeg_decode_end, + .decode = mpeg_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | + CODEC_CAP_HWACCEL_VDPAU | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video (VDPAU acceleration)"), +}; +#endif + +#if CONFIG_MPEG1_VDPAU_DECODER +AVCodec ff_mpeg1_vdpau_decoder = { + .name = "mpeg1video_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG1VIDEO, + .priv_data_size = sizeof(Mpeg1Context), + .init = mpeg_decode_init, + .close = mpeg_decode_end, + .decode = mpeg_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | + CODEC_CAP_HWACCEL_VDPAU | CODEC_CAP_DELAY, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video (VDPAU acceleration)"), +}; +#endif diff --git a/ffmpeg/libavcodec/mpeg12.h b/ffmpeg/libavcodec/mpeg12.h new file mode 100644 index 0000000..1f36917 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg12.h @@ -0,0 +1,76 @@ +/* + * MPEG1/2 common code + * Copyright (c) 2007 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVCODEC_MPEG12_H +#define AVCODEC_MPEG12_H + +#include "mpegvideo.h" + +#define DC_VLC_BITS 9 +#define TEX_VLC_BITS 9 + +extern VLC ff_dc_lum_vlc; +extern VLC ff_dc_chroma_vlc; + +typedef struct Mpeg1Context { + MpegEncContext mpeg_enc_ctx; + int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ + int repeat_field; /* true if we must repeat the field */ + AVPanScan pan_scan; /**< some temporary storage for the panscan */ + int slice_count; + int swap_uv;//indicate VCR2 + int save_aspect_info; + int save_width, save_height, save_progressive_seq; + AVRational frame_rate_ext; ///< MPEG-2 specific framerate modificator + int sync; ///< Did we reach a sync point like a GOP/SEQ/KEYFrame? + int tmpgexs; + int extradata_decoded; +} Mpeg1Context; + +extern uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; + +void ff_mpeg12_common_init(MpegEncContext *s); +void ff_mpeg12_init_vlcs(void); + +static inline int decode_dc(GetBitContext *gb, int component) +{ + int code, diff; + + if (component == 0) { + code = get_vlc2(gb, ff_dc_lum_vlc.table, DC_VLC_BITS, 2); + } else { + code = get_vlc2(gb, ff_dc_chroma_vlc.table, DC_VLC_BITS, 2); + } + if (code < 0){ + av_log(NULL, AV_LOG_ERROR, "invalid dc code at\n"); + return 0xffff; + } + if (code == 0) { + diff = 0; + } else { + diff = get_xbits(gb, code); + } + return diff; +} + +extern int ff_mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n); + +#endif /* AVCODEC_MPEG12_H */ diff --git a/ffmpeg/libavcodec/mpeg12data.c b/ffmpeg/libavcodec/mpeg12data.c new file mode 100644 index 0000000..e8c4a5d --- /dev/null +++ b/ffmpeg/libavcodec/mpeg12data.c @@ -0,0 +1,432 @@ +/* + * MPEG1/2 tables + * copyright (c) 2000,2001 Fabrice Bellard + * copyright (c) 2002-2004 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 + */ + +/** + * @file + * MPEG1/2 tables. + */ + +#include "mpeg12data.h" + +const uint16_t ff_mpeg1_default_intra_matrix[256] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +const uint16_t ff_mpeg1_default_non_intra_matrix[64] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, +}; + +const uint16_t ff_mpeg12_vlc_dc_lum_code[12] = { + 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x1ff, +}; +const unsigned char ff_mpeg12_vlc_dc_lum_bits[12] = { + 3, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 9, +}; + +const uint16_t ff_mpeg12_vlc_dc_chroma_code[12] = { + 0x0, 0x1, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe, 0x3fe, 0x3ff, +}; +const unsigned char ff_mpeg12_vlc_dc_chroma_bits[12] = { + 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, +}; + +static const uint16_t mpeg1_vlc[113][2] = { + { 0x3, 2 }, { 0x4, 4 }, { 0x5, 5 }, { 0x6, 7 }, + { 0x26, 8 }, { 0x21, 8 }, { 0xa, 10 }, { 0x1d, 12 }, + { 0x18, 12 }, { 0x13, 12 }, { 0x10, 12 }, { 0x1a, 13 }, + { 0x19, 13 }, { 0x18, 13 }, { 0x17, 13 }, { 0x1f, 14 }, + { 0x1e, 14 }, { 0x1d, 14 }, { 0x1c, 14 }, { 0x1b, 14 }, + { 0x1a, 14 }, { 0x19, 14 }, { 0x18, 14 }, { 0x17, 14 }, + { 0x16, 14 }, { 0x15, 14 }, { 0x14, 14 }, { 0x13, 14 }, + { 0x12, 14 }, { 0x11, 14 }, { 0x10, 14 }, { 0x18, 15 }, + { 0x17, 15 }, { 0x16, 15 }, { 0x15, 15 }, { 0x14, 15 }, + { 0x13, 15 }, { 0x12, 15 }, { 0x11, 15 }, { 0x10, 15 }, + { 0x3, 3 }, { 0x6, 6 }, { 0x25, 8 }, { 0xc, 10 }, + { 0x1b, 12 }, { 0x16, 13 }, { 0x15, 13 }, { 0x1f, 15 }, + { 0x1e, 15 }, { 0x1d, 15 }, { 0x1c, 15 }, { 0x1b, 15 }, + { 0x1a, 15 }, { 0x19, 15 }, { 0x13, 16 }, { 0x12, 16 }, + { 0x11, 16 }, { 0x10, 16 }, { 0x5, 4 }, { 0x4, 7 }, + { 0xb, 10 }, { 0x14, 12 }, { 0x14, 13 }, { 0x7, 5 }, + { 0x24, 8 }, { 0x1c, 12 }, { 0x13, 13 }, { 0x6, 5 }, + { 0xf, 10 }, { 0x12, 12 }, { 0x7, 6 }, { 0x9, 10 }, + { 0x12, 13 }, { 0x5, 6 }, { 0x1e, 12 }, { 0x14, 16 }, + { 0x4, 6 }, { 0x15, 12 }, { 0x7, 7 }, { 0x11, 12 }, + { 0x5, 7 }, { 0x11, 13 }, { 0x27, 8 }, { 0x10, 13 }, + { 0x23, 8 }, { 0x1a, 16 }, { 0x22, 8 }, { 0x19, 16 }, + { 0x20, 8 }, { 0x18, 16 }, { 0xe, 10 }, { 0x17, 16 }, + { 0xd, 10 }, { 0x16, 16 }, { 0x8, 10 }, { 0x15, 16 }, + { 0x1f, 12 }, { 0x1a, 12 }, { 0x19, 12 }, { 0x17, 12 }, + { 0x16, 12 }, { 0x1f, 13 }, { 0x1e, 13 }, { 0x1d, 13 }, + { 0x1c, 13 }, { 0x1b, 13 }, { 0x1f, 16 }, { 0x1e, 16 }, + { 0x1d, 16 }, { 0x1c, 16 }, { 0x1b, 16 }, + { 0x1, 6 }, /* escape */ + { 0x2, 2 }, /* EOB */ +}; + +static const uint16_t mpeg2_vlc[113][2] = { + {0x02, 2}, {0x06, 3}, {0x07, 4}, {0x1c, 5}, + {0x1d, 5}, {0x05, 6}, {0x04, 6}, {0x7b, 7}, + {0x7c, 7}, {0x23, 8}, {0x22, 8}, {0xfa, 8}, + {0xfb, 8}, {0xfe, 8}, {0xff, 8}, {0x1f,14}, + {0x1e,14}, {0x1d,14}, {0x1c,14}, {0x1b,14}, + {0x1a,14}, {0x19,14}, {0x18,14}, {0x17,14}, + {0x16,14}, {0x15,14}, {0x14,14}, {0x13,14}, + {0x12,14}, {0x11,14}, {0x10,14}, {0x18,15}, + {0x17,15}, {0x16,15}, {0x15,15}, {0x14,15}, + {0x13,15}, {0x12,15}, {0x11,15}, {0x10,15}, + {0x02, 3}, {0x06, 5}, {0x79, 7}, {0x27, 8}, + {0x20, 8}, {0x16,13}, {0x15,13}, {0x1f,15}, + {0x1e,15}, {0x1d,15}, {0x1c,15}, {0x1b,15}, + {0x1a,15}, {0x19,15}, {0x13,16}, {0x12,16}, + {0x11,16}, {0x10,16}, {0x05, 5}, {0x07, 7}, + {0xfc, 8}, {0x0c,10}, {0x14,13}, {0x07, 5}, + {0x26, 8}, {0x1c,12}, {0x13,13}, {0x06, 6}, + {0xfd, 8}, {0x12,12}, {0x07, 6}, {0x04, 9}, + {0x12,13}, {0x06, 7}, {0x1e,12}, {0x14,16}, + {0x04, 7}, {0x15,12}, {0x05, 7}, {0x11,12}, + {0x78, 7}, {0x11,13}, {0x7a, 7}, {0x10,13}, + {0x21, 8}, {0x1a,16}, {0x25, 8}, {0x19,16}, + {0x24, 8}, {0x18,16}, {0x05, 9}, {0x17,16}, + {0x07, 9}, {0x16,16}, {0x0d,10}, {0x15,16}, + {0x1f,12}, {0x1a,12}, {0x19,12}, {0x17,12}, + {0x16,12}, {0x1f,13}, {0x1e,13}, {0x1d,13}, + {0x1c,13}, {0x1b,13}, {0x1f,16}, {0x1e,16}, + {0x1d,16}, {0x1c,16}, {0x1b,16}, + {0x01,6}, /* escape */ + {0x06,4}, /* EOB */ +}; + +static const int8_t mpeg1_level[111] = { + 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, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 1, 2, 3, 4, 5, 1, + 2, 3, 4, 1, 2, 3, 1, 2, + 3, 1, 2, 3, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, +}; + +static const int8_t mpeg1_run[111] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 4, 4, 4, 5, 5, + 5, 6, 6, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 11, 12, 12, + 13, 13, 14, 14, 15, 15, 16, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, +}; + +RLTable ff_rl_mpeg1 = { + 111, + 111, + mpeg1_vlc, + mpeg1_run, + mpeg1_level, +}; + +RLTable ff_rl_mpeg2 = { + 111, + 111, + mpeg2_vlc, + mpeg1_run, + mpeg1_level, +}; + +const uint8_t ff_mpeg12_mbAddrIncrTable[36][2] = { + {0x1, 1}, + {0x3, 3}, + {0x2, 3}, + {0x3, 4}, + {0x2, 4}, + {0x3, 5}, + {0x2, 5}, + {0x7, 7}, + {0x6, 7}, + {0xb, 8}, + {0xa, 8}, + {0x9, 8}, + {0x8, 8}, + {0x7, 8}, + {0x6, 8}, + {0x17, 10}, + {0x16, 10}, + {0x15, 10}, + {0x14, 10}, + {0x13, 10}, + {0x12, 10}, + {0x23, 11}, + {0x22, 11}, + {0x21, 11}, + {0x20, 11}, + {0x1f, 11}, + {0x1e, 11}, + {0x1d, 11}, + {0x1c, 11}, + {0x1b, 11}, + {0x1a, 11}, + {0x19, 11}, + {0x18, 11}, + {0x8, 11}, /* escape */ + {0xf, 11}, /* stuffing */ + {0x0, 8}, /* end (and 15 more 0 bits should follow) */ +}; + +const uint8_t ff_mpeg12_mbPatTable[64][2] = { + {0x1, 9}, + {0xb, 5}, + {0x9, 5}, + {0xd, 6}, + {0xd, 4}, + {0x17, 7}, + {0x13, 7}, + {0x1f, 8}, + {0xc, 4}, + {0x16, 7}, + {0x12, 7}, + {0x1e, 8}, + {0x13, 5}, + {0x1b, 8}, + {0x17, 8}, + {0x13, 8}, + {0xb, 4}, + {0x15, 7}, + {0x11, 7}, + {0x1d, 8}, + {0x11, 5}, + {0x19, 8}, + {0x15, 8}, + {0x11, 8}, + {0xf, 6}, + {0xf, 8}, + {0xd, 8}, + {0x3, 9}, + {0xf, 5}, + {0xb, 8}, + {0x7, 8}, + {0x7, 9}, + {0xa, 4}, + {0x14, 7}, + {0x10, 7}, + {0x1c, 8}, + {0xe, 6}, + {0xe, 8}, + {0xc, 8}, + {0x2, 9}, + {0x10, 5}, + {0x18, 8}, + {0x14, 8}, + {0x10, 8}, + {0xe, 5}, + {0xa, 8}, + {0x6, 8}, + {0x6, 9}, + {0x12, 5}, + {0x1a, 8}, + {0x16, 8}, + {0x12, 8}, + {0xd, 5}, + {0x9, 8}, + {0x5, 8}, + {0x5, 9}, + {0xc, 5}, + {0x8, 8}, + {0x4, 8}, + {0x4, 9}, + {0x7, 3}, + {0xa, 5}, + {0x8, 5}, + {0xc, 6} +}; + +const uint8_t ff_mpeg12_mbMotionVectorTable[17][2] = { +{ 0x1, 1 }, +{ 0x1, 2 }, +{ 0x1, 3 }, +{ 0x1, 4 }, +{ 0x3, 6 }, +{ 0x5, 7 }, +{ 0x4, 7 }, +{ 0x3, 7 }, +{ 0xb, 9 }, +{ 0xa, 9 }, +{ 0x9, 9 }, +{ 0x11, 10 }, +{ 0x10, 10 }, +{ 0xf, 10 }, +{ 0xe, 10 }, +{ 0xd, 10 }, +{ 0xc, 10 }, +}; + +const AVRational ff_mpeg12_frame_rate_tab[16] = { + { 0, 0}, + {24000, 1001}, + { 24, 1}, + { 25, 1}, + {30000, 1001}, + { 30, 1}, + { 50, 1}, + {60000, 1001}, + { 60, 1}, + // Xing's 15fps: (9) + { 15, 1}, + // libmpeg3's "Unofficial economy rates": (10-13) + { 5, 1}, + { 10, 1}, + { 12, 1}, + { 15, 1}, + { 0, 0}, +}; + +const AVRational ff_mpeg2_frame_rate_tab[] = { + { 1, 1}, + { 2, 1}, + { 3, 1}, + { 4, 1}, + { 5, 1}, + { 6, 1}, + { 8, 1}, + { 9, 1}, + { 10, 1}, + { 12, 1}, + { 15, 1}, + { 16, 1}, + { 18, 1}, + { 20, 1}, + { 24, 1}, + { 25, 1}, + { 30, 1}, + { 32, 1}, + { 36, 1}, + { 40, 1}, + { 45, 1}, + { 48, 1}, + { 50, 1}, + { 60, 1}, + { 72, 1}, + { 75, 1}, + { 80, 1}, + { 90, 1}, + { 96, 1}, + { 100, 1}, + { 120, 1}, + { 150, 1}, + { 180, 1}, + { 200, 1}, + { 240, 1}, + { 750, 1001}, + { 800, 1001}, + { 960, 1001}, + { 1000, 1001}, + { 1200, 1001}, + { 1250, 1001}, + { 1500, 1001}, + { 1600, 1001}, + { 1875, 1001}, + { 2000, 1001}, + { 2400, 1001}, + { 2500, 1001}, + { 3000, 1001}, + { 3750, 1001}, + { 4000, 1001}, + { 4800, 1001}, + { 5000, 1001}, + { 6000, 1001}, + { 7500, 1001}, + { 8000, 1001}, + { 10000, 1001}, + { 12000, 1001}, + { 15000, 1001}, + { 20000, 1001}, + { 24000, 1001}, + { 30000, 1001}, + { 60000, 1001}, + { 0, 0}, +}; + +const float ff_mpeg1_aspect[16]={ + 0.0000, + 1.0000, + 0.6735, + 0.7031, + + 0.7615, + 0.8055, + 0.8437, + 0.8935, + + 0.9157, + 0.9815, + 1.0255, + 1.0695, + + 1.0950, + 1.1575, + 1.2015, +}; + +const AVRational ff_mpeg2_aspect[16]={ + {0,1}, + {1,1}, + {4,3}, + {16,9}, + {221,100}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, + {0,1}, +}; diff --git a/ffmpeg/libavcodec/mpeg12data.h b/ffmpeg/libavcodec/mpeg12data.h new file mode 100644 index 0000000..65b9485 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg12data.h @@ -0,0 +1,57 @@ +/* + * MPEG1/2 tables + * copyright (c) 2000,2001 Fabrice Bellard + * copyright (c) 2002-2004 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 + */ + +/** + * @file + * MPEG1/2 tables. + */ + +#ifndef AVCODEC_MPEG12DATA_H +#define AVCODEC_MPEG12DATA_H + +#include +#include "libavutil/rational.h" +#include "rl.h" + +extern const uint16_t ff_mpeg1_default_intra_matrix[]; +extern const uint16_t ff_mpeg1_default_non_intra_matrix[64]; + +extern const uint16_t ff_mpeg12_vlc_dc_lum_code[12]; +extern const unsigned char ff_mpeg12_vlc_dc_lum_bits[12]; +extern const uint16_t ff_mpeg12_vlc_dc_chroma_code[12]; +extern const unsigned char ff_mpeg12_vlc_dc_chroma_bits[12]; + +extern RLTable ff_rl_mpeg1; +extern RLTable ff_rl_mpeg2; + +extern const uint8_t ff_mpeg12_mbAddrIncrTable[36][2]; +extern const uint8_t ff_mpeg12_mbPatTable[64][2]; + +extern const uint8_t ff_mpeg12_mbMotionVectorTable[17][2]; + +extern const AVRational ff_mpeg12_frame_rate_tab[]; +extern const AVRational ff_mpeg2_frame_rate_tab[]; + +extern const float ff_mpeg1_aspect[16]; +extern const AVRational ff_mpeg2_aspect[16]; + +#endif /* AVCODEC_MPEG12DATA_H */ diff --git a/ffmpeg/libavcodec/mpeg12decdata.h b/ffmpeg/libavcodec/mpeg12decdata.h new file mode 100644 index 0000000..66ca5c4 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg12decdata.h @@ -0,0 +1,93 @@ +/* + * MPEG1/2 decoder tables + * copyright (c) 2000,2001 Fabrice Bellard + * copyright (c) 2002-2004 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 + */ + +/** + * @file + * MPEG1/2 decoder tables. + */ + +#ifndef AVCODEC_MPEG12DECDATA_H +#define AVCODEC_MPEG12DECDATA_H + +#include +#include "mpegvideo.h" + + +#define MB_TYPE_ZERO_MV 0x20000000 +#define IS_ZERO_MV(a) ((a)&MB_TYPE_ZERO_MV) + +static const uint8_t table_mb_ptype[7][2] = { + { 3, 5 }, // 0x01 MB_INTRA + { 1, 2 }, // 0x02 MB_PAT + { 1, 3 }, // 0x08 MB_FOR + { 1, 1 }, // 0x0A MB_FOR|MB_PAT + { 1, 6 }, // 0x11 MB_QUANT|MB_INTRA + { 1, 5 }, // 0x12 MB_QUANT|MB_PAT + { 2, 5 }, // 0x1A MB_QUANT|MB_FOR|MB_PAT +}; + +static const uint32_t ptype2mb_type[7] = { + MB_TYPE_INTRA, + MB_TYPE_L0 | MB_TYPE_CBP | MB_TYPE_ZERO_MV | MB_TYPE_16x16, + MB_TYPE_L0, + MB_TYPE_L0 | MB_TYPE_CBP, + MB_TYPE_QUANT | MB_TYPE_INTRA, + MB_TYPE_QUANT | MB_TYPE_L0 | MB_TYPE_CBP | MB_TYPE_ZERO_MV | MB_TYPE_16x16, + MB_TYPE_QUANT | MB_TYPE_L0 | MB_TYPE_CBP, +}; + +static const uint8_t table_mb_btype[11][2] = { + { 3, 5 }, // 0x01 MB_INTRA + { 2, 3 }, // 0x04 MB_BACK + { 3, 3 }, // 0x06 MB_BACK|MB_PAT + { 2, 4 }, // 0x08 MB_FOR + { 3, 4 }, // 0x0A MB_FOR|MB_PAT + { 2, 2 }, // 0x0C MB_FOR|MB_BACK + { 3, 2 }, // 0x0E MB_FOR|MB_BACK|MB_PAT + { 1, 6 }, // 0x11 MB_QUANT|MB_INTRA + { 2, 6 }, // 0x16 MB_QUANT|MB_BACK|MB_PAT + { 3, 6 }, // 0x1A MB_QUANT|MB_FOR|MB_PAT + { 2, 5 }, // 0x1E MB_QUANT|MB_FOR|MB_BACK|MB_PAT +}; + +static const uint32_t btype2mb_type[11] = { + MB_TYPE_INTRA, + MB_TYPE_L1, + MB_TYPE_L1 | MB_TYPE_CBP, + MB_TYPE_L0, + MB_TYPE_L0 | MB_TYPE_CBP, + MB_TYPE_L0L1, + MB_TYPE_L0L1 | MB_TYPE_CBP, + MB_TYPE_QUANT | MB_TYPE_INTRA, + MB_TYPE_QUANT | MB_TYPE_L1 | MB_TYPE_CBP, + MB_TYPE_QUANT | MB_TYPE_L0 | MB_TYPE_CBP, + MB_TYPE_QUANT | MB_TYPE_L0L1 | MB_TYPE_CBP, +}; + +static const uint8_t non_linear_qscale[32] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8,10,12,14,16,18,20,22, + 24,28,32,36,40,44,48,52, + 56,64,72,80,88,96,104,112, +}; + +#endif /* AVCODEC_MPEG12DECDATA_H */ diff --git a/ffmpeg/libavcodec/mpeg12enc.c b/ffmpeg/libavcodec/mpeg12enc.c new file mode 100644 index 0000000..c8e7b45 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg12enc.c @@ -0,0 +1,1023 @@ +/* + * MPEG1/2 encoder + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * MPEG1/2 encoder + */ + +#include "avcodec.h" +#include "mathops.h" +#include "mpegvideo.h" + +#include "mpeg12.h" +#include "mpeg12data.h" +#include "bytestream.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/avassert.h" +#include "libavutil/timecode.h" + +static const uint8_t inv_non_linear_qscale[13] = { + 0, 2, 4, 6, 8, + 9,10,11,12,13,14,15,16, +}; + +static const uint8_t svcd_scan_offset_placeholder[14] = { + 0x10, 0x0E, + 0x00, 0x80, 0x81, + 0x00, 0x80, 0x81, + 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, +}; + +static void mpeg1_encode_block(MpegEncContext *s, + int16_t *block, + int component); +static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code); // RAL: f_code parameter added + +static uint8_t mv_penalty[MAX_FCODE+1][MAX_MV*2+1]; +static uint8_t fcode_tab[MAX_MV*2+1]; + +static uint8_t uni_mpeg1_ac_vlc_len [64*64*2]; +static uint8_t uni_mpeg2_ac_vlc_len [64*64*2]; + +/* simple include everything table for dc, first byte is bits number next 3 are code*/ +static uint32_t mpeg1_lum_dc_uni[512]; +static uint32_t mpeg1_chr_dc_uni[512]; + +static uint8_t mpeg1_index_run[2][64]; +static int8_t mpeg1_max_level[2][64]; + +static void init_uni_ac_vlc(RLTable *rl, uint8_t *uni_ac_vlc_len){ + int i; + + for(i=0; i<128; i++){ + int level= i-64; + int run; + if (!level) + continue; + for(run=0; run<64; run++){ + int len, code; + + int alevel= FFABS(level); + + if (alevel > rl->max_level[0][run]) + code= 111; /*rl->n*/ + else + code= rl->index_run[0][run] + alevel - 1; + + if (code < 111 /* rl->n */) { + /* length of vlc and sign */ + len= rl->table_vlc[code][1]+1; + } else { + len= rl->table_vlc[111/*rl->n*/][1]+6; + + if (alevel < 128) { + len += 8; + } else { + len += 16; + } + } + + uni_ac_vlc_len [UNI_AC_ENC_INDEX(run, i)]= len; + } + } +} + + +static int find_frame_rate_index(MpegEncContext *s){ + int i; + AVRational bestq= (AVRational){0, 0}; + AVRational ext; + AVRational target = av_inv_q(s->avctx->time_base); + + for(i=1;i<14;i++) { + if(s->avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL && i>=9) break; + + for (ext.num=1; ext.num <= 4; ext.num++) { + for (ext.den=1; ext.den <= 32; ext.den++) { + AVRational q = av_mul_q(ext, ff_mpeg12_frame_rate_tab[i]); + + if(s->codec_id != AV_CODEC_ID_MPEG2VIDEO && (ext.den!=1 || ext.num!=1)) + continue; + if(av_gcd(ext.den, ext.num) != 1) + continue; + + if( bestq.num==0 + || av_nearer_q(target, bestq, q) < 0 + || ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0){ + bestq = q; + s->frame_rate_index= i; + s->mpeg2_frame_rate_ext.num = ext.num; + s->mpeg2_frame_rate_ext.den = ext.den; + } + } + } + } + if(av_cmp_q(target, bestq)) + return -1; + else + return 0; +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + + if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && avctx->height > 2800) + avctx->thread_count = 1; + + if(ff_MPV_encode_init(avctx) < 0) + return -1; + + if(find_frame_rate_index(s) < 0){ + if(s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ + av_log(avctx, AV_LOG_ERROR, "MPEG1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num); + return -1; + }else{ + av_log(avctx, AV_LOG_INFO, "MPEG1/2 does not support %d/%d fps, there may be AV sync issues\n", avctx->time_base.den, avctx->time_base.num); + } + } + + if(avctx->profile == FF_PROFILE_UNKNOWN){ + if(avctx->level != FF_LEVEL_UNKNOWN){ + av_log(avctx, AV_LOG_ERROR, "Set profile and level\n"); + return -1; + } + avctx->profile = s->chroma_format == CHROMA_420 ? 4 : 0; /* Main or 4:2:2 */ + } + + if(avctx->level == FF_LEVEL_UNKNOWN){ + if(avctx->profile == 0){ /* 4:2:2 */ + if(avctx->width <= 720 && avctx->height <= 608) avctx->level = 5; /* Main */ + else avctx->level = 2; /* High */ + }else{ + if(avctx->profile != 1 && s->chroma_format != CHROMA_420){ + av_log(avctx, AV_LOG_ERROR, "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n"); + return -1; + } + if(avctx->width <= 720 && avctx->height <= 576) avctx->level = 8; /* Main */ + else if(avctx->width <= 1440) avctx->level = 6; /* High 1440 */ + else avctx->level = 4; /* High */ + } + } + + if ((avctx->width & 0xFFF) == 0 && (avctx->height & 0xFFF) == 1) { + av_log(avctx, AV_LOG_ERROR, "Width / Height is invalid for MPEG2\n"); + return AVERROR(EINVAL); + } + + if (s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { + if ((avctx->width & 0xFFF) == 0 || (avctx->height & 0xFFF) == 0) { + av_log(avctx, AV_LOG_ERROR, "Width or Height are not allowed to be multiplies of 4096\n" + "add '-strict %d' if you want to use them anyway.\n", FF_COMPLIANCE_UNOFFICIAL); + return AVERROR(EINVAL); + } + } + + s->drop_frame_timecode = s->drop_frame_timecode || !!(avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE); + if (s->drop_frame_timecode) + s->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; + if (s->drop_frame_timecode && s->frame_rate_index != 4) { + av_log(avctx, AV_LOG_ERROR, "Drop frame time code only allowed with 1001/30000 fps\n"); + return -1; + } + + if (s->tc_opt_str) { + AVRational rate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; + int ret = av_timecode_init_from_string(&s->tc, rate, s->tc_opt_str, s); + if (ret < 0) + return ret; + s->drop_frame_timecode = !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); + s->avctx->timecode_frame_start = s->tc.start; + } else { + s->avctx->timecode_frame_start = 0; // default is -1 + } + return 0; +} + +static void put_header(MpegEncContext *s, int header) +{ + avpriv_align_put_bits(&s->pb); + put_bits(&s->pb, 16, header>>16); + put_sbits(&s->pb, 16, header); +} + +/* put sequence header if needed */ +static void mpeg1_encode_sequence_header(MpegEncContext *s) +{ + unsigned int vbv_buffer_size; + unsigned int fps, v; + int i; + uint64_t time_code; + float best_aspect_error= 1E10; + float aspect_ratio= av_q2d(s->avctx->sample_aspect_ratio); + int constraint_parameter_flag; + + if(aspect_ratio==0.0) aspect_ratio= 1.0; //pixel aspect 1:1 (VGA) + + if (s->current_picture.f.key_frame) { + AVRational framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; + + /* mpeg1 header repeated every gop */ + put_header(s, SEQ_START_CODE); + + put_sbits(&s->pb, 12, s->width & 0xFFF); + put_sbits(&s->pb, 12, s->height & 0xFFF); + + for(i=1; i<15; i++){ + float error= aspect_ratio; + if(s->codec_id == AV_CODEC_ID_MPEG1VIDEO || i <=1) + error-= 1.0/ff_mpeg1_aspect[i]; + else + error-= av_q2d(ff_mpeg2_aspect[i])*s->height/s->width; + + error= FFABS(error); + + if(error < best_aspect_error){ + best_aspect_error= error; + s->aspect_ratio_info= i; + } + } + + put_bits(&s->pb, 4, s->aspect_ratio_info); + put_bits(&s->pb, 4, s->frame_rate_index); + + if(s->avctx->rc_max_rate){ + v = (s->avctx->rc_max_rate + 399) / 400; + if (v > 0x3ffff && s->codec_id == AV_CODEC_ID_MPEG1VIDEO) + v = 0x3ffff; + }else{ + v= 0x3FFFF; + } + + if(s->avctx->rc_buffer_size) + vbv_buffer_size = s->avctx->rc_buffer_size; + else + /* VBV calculation: Scaled so that a VCD has the proper VBV size of 40 kilobytes */ + vbv_buffer_size = (( 20 * s->bit_rate) / (1151929 / 2)) * 8 * 1024; + vbv_buffer_size= (vbv_buffer_size + 16383) / 16384; + + put_sbits(&s->pb, 18, v); + put_bits(&s->pb, 1, 1); /* marker */ + put_sbits(&s->pb, 10, vbv_buffer_size); + + constraint_parameter_flag= + s->width <= 768 && s->height <= 576 && + s->mb_width * s->mb_height <= 396 && + s->mb_width * s->mb_height * framerate.num <= framerate.den*396*25 && + framerate.num <= framerate.den*30 && + s->avctx->me_range && s->avctx->me_range < 128 && + vbv_buffer_size <= 20 && + v <= 1856000/400 && + s->codec_id == AV_CODEC_ID_MPEG1VIDEO; + + put_bits(&s->pb, 1, constraint_parameter_flag); + + ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix); + ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix); + + if(s->codec_id == AV_CODEC_ID_MPEG2VIDEO){ + put_header(s, EXT_START_CODE); + put_bits(&s->pb, 4, 1); //seq ext + + put_bits(&s->pb, 1, s->avctx->profile == 0); //escx 1 for 4:2:2 profile */ + + put_bits(&s->pb, 3, s->avctx->profile); //profile + put_bits(&s->pb, 4, s->avctx->level); //level + + put_bits(&s->pb, 1, s->progressive_sequence); + put_bits(&s->pb, 2, s->chroma_format); + put_bits(&s->pb, 2, s->width >>12); + put_bits(&s->pb, 2, s->height>>12); + put_bits(&s->pb, 12, v>>18); //bitrate ext + put_bits(&s->pb, 1, 1); //marker + put_bits(&s->pb, 8, vbv_buffer_size >>10); //vbv buffer ext + put_bits(&s->pb, 1, s->low_delay); + put_bits(&s->pb, 2, s->mpeg2_frame_rate_ext.num-1); // frame_rate_ext_n + put_bits(&s->pb, 5, s->mpeg2_frame_rate_ext.den-1); // frame_rate_ext_d + } + + put_header(s, GOP_START_CODE); + put_bits(&s->pb, 1, s->drop_frame_timecode); /* drop frame flag */ + /* time code : we must convert from the real frame rate to a + fake mpeg frame rate in case of low frame rate */ + fps = (framerate.num + framerate.den/2)/ framerate.den; + time_code = s->current_picture_ptr->f.coded_picture_number + s->avctx->timecode_frame_start; + + s->gop_picture_number = s->current_picture_ptr->f.coded_picture_number; + av_assert0(s->drop_frame_timecode == !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); + if (s->drop_frame_timecode) + time_code = av_timecode_adjust_ntsc_framenum2(time_code, fps); + put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24)); + put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60)); + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60)); + put_bits(&s->pb, 6, (uint32_t)((time_code % fps))); + put_bits(&s->pb, 1, !!(s->flags & CODEC_FLAG_CLOSED_GOP)); + put_bits(&s->pb, 1, 0); /* broken link */ + } +} + +static inline void encode_mb_skip_run(MpegEncContext *s, int run){ + while (run >= 33) { + put_bits(&s->pb, 11, 0x008); + run -= 33; + } + put_bits(&s->pb, ff_mpeg12_mbAddrIncrTable[run][1], + ff_mpeg12_mbAddrIncrTable[run][0]); +} + +static av_always_inline void put_qscale(MpegEncContext *s) +{ + if(s->q_scale_type){ + av_assert2(s->qscale>=1 && s->qscale <=12); + put_bits(&s->pb, 5, inv_non_linear_qscale[s->qscale]); + }else{ + put_bits(&s->pb, 5, s->qscale); + } +} + +void ff_mpeg1_encode_slice_header(MpegEncContext *s){ + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->height > 2800) { + put_header(s, SLICE_MIN_START_CODE + (s->mb_y & 127)); + put_bits(&s->pb, 3, s->mb_y >> 7); /* slice_vertical_position_extension */ + } else { + put_header(s, SLICE_MIN_START_CODE + s->mb_y); + } + put_qscale(s); + put_bits(&s->pb, 1, 0); /* slice extra information */ +} + +void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) +{ + mpeg1_encode_sequence_header(s); + + /* mpeg1 picture header */ + put_header(s, PICTURE_START_CODE); + /* temporal reference */ + + // RAL: s->picture_number instead of s->fake_picture_number + put_bits(&s->pb, 10, (s->picture_number - + s->gop_picture_number) & 0x3ff); + put_bits(&s->pb, 3, s->pict_type); + + s->vbv_delay_ptr= s->pb.buf + put_bits_count(&s->pb)/8; + put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */ + + // RAL: Forward f_code also needed for B frames + if (s->pict_type == AV_PICTURE_TYPE_P || s->pict_type == AV_PICTURE_TYPE_B) { + put_bits(&s->pb, 1, 0); /* half pel coordinates */ + if(s->codec_id == AV_CODEC_ID_MPEG1VIDEO) + put_bits(&s->pb, 3, s->f_code); /* forward_f_code */ + else + put_bits(&s->pb, 3, 7); /* forward_f_code */ + } + + // RAL: Backward f_code necessary for B frames + if (s->pict_type == AV_PICTURE_TYPE_B) { + put_bits(&s->pb, 1, 0); /* half pel coordinates */ + if(s->codec_id == AV_CODEC_ID_MPEG1VIDEO) + put_bits(&s->pb, 3, s->b_code); /* backward_f_code */ + else + put_bits(&s->pb, 3, 7); /* backward_f_code */ + } + + put_bits(&s->pb, 1, 0); /* extra bit picture */ + + s->frame_pred_frame_dct = 1; + if(s->codec_id == AV_CODEC_ID_MPEG2VIDEO){ + put_header(s, EXT_START_CODE); + put_bits(&s->pb, 4, 8); //pic ext + if (s->pict_type == AV_PICTURE_TYPE_P || s->pict_type == AV_PICTURE_TYPE_B) { + put_bits(&s->pb, 4, s->f_code); + put_bits(&s->pb, 4, s->f_code); + }else{ + put_bits(&s->pb, 8, 255); + } + if (s->pict_type == AV_PICTURE_TYPE_B) { + put_bits(&s->pb, 4, s->b_code); + put_bits(&s->pb, 4, s->b_code); + }else{ + put_bits(&s->pb, 8, 255); + } + put_bits(&s->pb, 2, s->intra_dc_precision); + + av_assert0(s->picture_structure == PICT_FRAME); + put_bits(&s->pb, 2, s->picture_structure); + if (s->progressive_sequence) { + put_bits(&s->pb, 1, 0); /* no repeat */ + } else { + put_bits(&s->pb, 1, s->current_picture_ptr->f.top_field_first); + } + /* XXX: optimize the generation of this flag with entropy + measures */ + s->frame_pred_frame_dct = s->progressive_sequence; + + put_bits(&s->pb, 1, s->frame_pred_frame_dct); + put_bits(&s->pb, 1, s->concealment_motion_vectors); + put_bits(&s->pb, 1, s->q_scale_type); + put_bits(&s->pb, 1, s->intra_vlc_format); + put_bits(&s->pb, 1, s->alternate_scan); + put_bits(&s->pb, 1, s->repeat_first_field); + s->progressive_frame = s->progressive_sequence; + put_bits(&s->pb, 1, s->chroma_format == CHROMA_420 ? s->progressive_frame : 0); /* chroma_420_type */ + put_bits(&s->pb, 1, s->progressive_frame); + put_bits(&s->pb, 1, 0); //composite_display_flag + } + if (s->scan_offset) { + int i; + + put_header(s, USER_START_CODE); + for(i=0; ipb, 8, svcd_scan_offset_placeholder[i]); + } + } + + s->mb_y=0; + ff_mpeg1_encode_slice_header(s); +} + +static inline void put_mb_modes(MpegEncContext *s, int n, int bits, + int has_mv, int field_motion) +{ + put_bits(&s->pb, n, bits); + if (!s->frame_pred_frame_dct) { + if (has_mv) + put_bits(&s->pb, 2, 2 - field_motion); /* motion_type: frame/field */ + put_bits(&s->pb, 1, s->interlaced_dct); + } +} + +static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y, + int mb_block_count) +{ + int i, cbp; + const int mb_x = s->mb_x; + const int mb_y = s->mb_y; + const int first_mb= mb_x == s->resync_mb_x && mb_y == s->resync_mb_y; + + /* compute cbp */ + cbp = 0; + for(i=0;iblock_last_index[i] >= 0) + cbp |= 1 << (mb_block_count - 1 - i); + } + + if (cbp == 0 && !first_mb && s->mv_type == MV_TYPE_16X16 && + (mb_x != s->mb_width - 1 || (mb_y != s->end_mb_y - 1 && s->codec_id == AV_CODEC_ID_MPEG1VIDEO)) && + ((s->pict_type == AV_PICTURE_TYPE_P && (motion_x | motion_y) == 0) || + (s->pict_type == AV_PICTURE_TYPE_B && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) ? ((s->mv[0][0][0] - s->last_mv[0][0][0])|(s->mv[0][0][1] - s->last_mv[0][0][1])) : 0) | + ((s->mv_dir & MV_DIR_BACKWARD) ? ((s->mv[1][0][0] - s->last_mv[1][0][0])|(s->mv[1][0][1] - s->last_mv[1][0][1])) : 0)) == 0))) { + s->mb_skip_run++; + s->qscale -= s->dquant; + s->skip_count++; + s->misc_bits++; + s->last_bits++; + if(s->pict_type == AV_PICTURE_TYPE_P){ + s->last_mv[0][1][0]= s->last_mv[0][0][0]= + s->last_mv[0][1][1]= s->last_mv[0][0][1]= 0; + } + } else { + if(first_mb){ + av_assert0(s->mb_skip_run == 0); + encode_mb_skip_run(s, s->mb_x); + }else{ + encode_mb_skip_run(s, s->mb_skip_run); + } + + if (s->pict_type == AV_PICTURE_TYPE_I) { + if(s->dquant && cbp){ + put_mb_modes(s, 2, 1, 0, 0); /* macroblock_type : macroblock_quant = 1 */ + put_qscale(s); + }else{ + put_mb_modes(s, 1, 1, 0, 0); /* macroblock_type : macroblock_quant = 0 */ + s->qscale -= s->dquant; + } + s->misc_bits+= get_bits_diff(s); + s->i_count++; + } else if (s->mb_intra) { + if(s->dquant && cbp){ + put_mb_modes(s, 6, 0x01, 0, 0); + put_qscale(s); + }else{ + put_mb_modes(s, 5, 0x03, 0, 0); + s->qscale -= s->dquant; + } + s->misc_bits+= get_bits_diff(s); + s->i_count++; + memset(s->last_mv, 0, sizeof(s->last_mv)); + } else if (s->pict_type == AV_PICTURE_TYPE_P) { + if(s->mv_type == MV_TYPE_16X16){ + if (cbp != 0) { + if ((motion_x|motion_y) == 0) { + if(s->dquant){ + put_mb_modes(s, 5, 1, 0, 0); /* macroblock_pattern & quant */ + put_qscale(s); + }else{ + put_mb_modes(s, 2, 1, 0, 0); /* macroblock_pattern only */ + } + s->misc_bits+= get_bits_diff(s); + } else { + if(s->dquant){ + put_mb_modes(s, 5, 2, 1, 0); /* motion + cbp */ + put_qscale(s); + }else{ + put_mb_modes(s, 1, 1, 1, 0); /* motion + cbp */ + } + s->misc_bits+= get_bits_diff(s); + mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); // RAL: f_code parameter added + mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); // RAL: f_code parameter added + s->mv_bits+= get_bits_diff(s); + } + } else { + put_bits(&s->pb, 3, 1); /* motion only */ + if (!s->frame_pred_frame_dct) + put_bits(&s->pb, 2, 2); /* motion_type: frame */ + s->misc_bits+= get_bits_diff(s); + mpeg1_encode_motion(s, motion_x - s->last_mv[0][0][0], s->f_code); // RAL: f_code parameter added + mpeg1_encode_motion(s, motion_y - s->last_mv[0][0][1], s->f_code); // RAL: f_code parameter added + s->qscale -= s->dquant; + s->mv_bits+= get_bits_diff(s); + } + s->last_mv[0][1][0]= s->last_mv[0][0][0]= motion_x; + s->last_mv[0][1][1]= s->last_mv[0][0][1]= motion_y; + }else{ + av_assert2(!s->frame_pred_frame_dct && s->mv_type == MV_TYPE_FIELD); + + if (cbp) { + if(s->dquant){ + put_mb_modes(s, 5, 2, 1, 1); /* motion + cbp */ + put_qscale(s); + }else{ + put_mb_modes(s, 1, 1, 1, 1); /* motion + cbp */ + } + } else { + put_bits(&s->pb, 3, 1); /* motion only */ + put_bits(&s->pb, 2, 1); /* motion_type: field */ + s->qscale -= s->dquant; + } + s->misc_bits+= get_bits_diff(s); + for(i=0; i<2; i++){ + put_bits(&s->pb, 1, s->field_select[0][i]); + mpeg1_encode_motion(s, s->mv[0][i][0] - s->last_mv[0][i][0] , s->f_code); + mpeg1_encode_motion(s, s->mv[0][i][1] - (s->last_mv[0][i][1]>>1), s->f_code); + s->last_mv[0][i][0]= s->mv[0][i][0]; + s->last_mv[0][i][1]= 2*s->mv[0][i][1]; + } + s->mv_bits+= get_bits_diff(s); + } + if(cbp) { + if (s->chroma_y_shift) { + put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); + } else { + put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp>>2][1], ff_mpeg12_mbPatTable[cbp>>2][0]); + put_sbits(&s->pb, 2, cbp); + } + } + s->f_count++; + } else{ + if(s->mv_type == MV_TYPE_16X16){ + if (cbp){ // With coded bloc pattern + if (s->dquant) { + if(s->mv_dir == MV_DIR_FORWARD) + put_mb_modes(s, 6, 3, 1, 0); + else + put_mb_modes(s, 8-s->mv_dir, 2, 1, 0); + put_qscale(s); + } else { + put_mb_modes(s, 5-s->mv_dir, 3, 1, 0); + } + }else{ // No coded bloc pattern + put_bits(&s->pb, 5-s->mv_dir, 2); + if (!s->frame_pred_frame_dct) + put_bits(&s->pb, 2, 2); /* motion_type: frame */ + s->qscale -= s->dquant; + } + s->misc_bits += get_bits_diff(s); + if (s->mv_dir&MV_DIR_FORWARD){ + mpeg1_encode_motion(s, s->mv[0][0][0] - s->last_mv[0][0][0], s->f_code); + mpeg1_encode_motion(s, s->mv[0][0][1] - s->last_mv[0][0][1], s->f_code); + s->last_mv[0][0][0]=s->last_mv[0][1][0]= s->mv[0][0][0]; + s->last_mv[0][0][1]=s->last_mv[0][1][1]= s->mv[0][0][1]; + s->f_count++; + } + if (s->mv_dir&MV_DIR_BACKWARD){ + mpeg1_encode_motion(s, s->mv[1][0][0] - s->last_mv[1][0][0], s->b_code); + mpeg1_encode_motion(s, s->mv[1][0][1] - s->last_mv[1][0][1], s->b_code); + s->last_mv[1][0][0]=s->last_mv[1][1][0]= s->mv[1][0][0]; + s->last_mv[1][0][1]=s->last_mv[1][1][1]= s->mv[1][0][1]; + s->b_count++; + } + }else{ + av_assert2(s->mv_type == MV_TYPE_FIELD); + av_assert2(!s->frame_pred_frame_dct); + if (cbp){ // With coded bloc pattern + if (s->dquant) { + if(s->mv_dir == MV_DIR_FORWARD) + put_mb_modes(s, 6, 3, 1, 1); + else + put_mb_modes(s, 8-s->mv_dir, 2, 1, 1); + put_qscale(s); + } else { + put_mb_modes(s, 5-s->mv_dir, 3, 1, 1); + } + }else{ // No coded bloc pattern + put_bits(&s->pb, 5-s->mv_dir, 2); + put_bits(&s->pb, 2, 1); /* motion_type: field */ + s->qscale -= s->dquant; + } + s->misc_bits += get_bits_diff(s); + if (s->mv_dir&MV_DIR_FORWARD){ + for(i=0; i<2; i++){ + put_bits(&s->pb, 1, s->field_select[0][i]); + mpeg1_encode_motion(s, s->mv[0][i][0] - s->last_mv[0][i][0] , s->f_code); + mpeg1_encode_motion(s, s->mv[0][i][1] - (s->last_mv[0][i][1]>>1), s->f_code); + s->last_mv[0][i][0]= s->mv[0][i][0]; + s->last_mv[0][i][1]= 2*s->mv[0][i][1]; + } + s->f_count++; + } + if (s->mv_dir&MV_DIR_BACKWARD){ + for(i=0; i<2; i++){ + put_bits(&s->pb, 1, s->field_select[1][i]); + mpeg1_encode_motion(s, s->mv[1][i][0] - s->last_mv[1][i][0] , s->b_code); + mpeg1_encode_motion(s, s->mv[1][i][1] - (s->last_mv[1][i][1]>>1), s->b_code); + s->last_mv[1][i][0]= s->mv[1][i][0]; + s->last_mv[1][i][1]= 2*s->mv[1][i][1]; + } + s->b_count++; + } + } + s->mv_bits += get_bits_diff(s); + if(cbp) { + if (s->chroma_y_shift) { + put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); + } else { + put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp>>2][1], ff_mpeg12_mbPatTable[cbp>>2][0]); + put_sbits(&s->pb, 2, cbp); + } + } + } + for(i=0;imb_skip_run = 0; + if(s->mb_intra) + s->i_tex_bits+= get_bits_diff(s); + else + s->p_tex_bits+= get_bits_diff(s); + } +} + +void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y) +{ + if (s->chroma_format == CHROMA_420) mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6); + else mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8); +} + +// RAL: Parameter added: f_or_b_code +static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code) +{ + if (val == 0) { + /* zero vector */ + put_bits(&s->pb, + ff_mpeg12_mbMotionVectorTable[0][1], + ff_mpeg12_mbMotionVectorTable[0][0]); + } else { + int code, sign, bits; + int bit_size = f_or_b_code - 1; + int range = 1 << bit_size; + /* modulo encoding */ + val = sign_extend(val, 5 + bit_size); + + if (val >= 0) { + val--; + code = (val >> bit_size) + 1; + bits = val & (range - 1); + sign = 0; + } else { + val = -val; + val--; + code = (val >> bit_size) + 1; + bits = val & (range - 1); + sign = 1; + } + + av_assert2(code > 0 && code <= 16); + + put_bits(&s->pb, + ff_mpeg12_mbMotionVectorTable[code][1], + ff_mpeg12_mbMotionVectorTable[code][0]); + + put_bits(&s->pb, 1, sign); + if (bit_size > 0) { + put_bits(&s->pb, bit_size, bits); + } + } +} + +void ff_mpeg1_encode_init(MpegEncContext *s) +{ + static int done=0; + + ff_mpeg12_common_init(s); + + if(!done){ + int f_code; + int mv; + int i; + + done=1; + ff_init_rl(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]); + ff_init_rl(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]); + + for(i=0; i<64; i++) + { + mpeg1_max_level[0][i]= ff_rl_mpeg1.max_level[0][i]; + mpeg1_index_run[0][i]= ff_rl_mpeg1.index_run[0][i]; + } + + init_uni_ac_vlc(&ff_rl_mpeg1, uni_mpeg1_ac_vlc_len); + if(s->intra_vlc_format) + init_uni_ac_vlc(&ff_rl_mpeg2, uni_mpeg2_ac_vlc_len); + + /* build unified dc encoding tables */ + for(i=-255; i<256; i++) + { + int adiff, index; + int bits, code; + int diff=i; + + adiff = FFABS(diff); + if(diff<0) diff--; + index = av_log2(2*adiff); + + bits= ff_mpeg12_vlc_dc_lum_bits[index] + index; + code= (ff_mpeg12_vlc_dc_lum_code[index]<> bit_size) + 1; + if(code<17){ + len= ff_mpeg12_mbMotionVectorTable[code][1] + 1 + bit_size; + }else{ + len= ff_mpeg12_mbMotionVectorTable[16][1] + 2 + bit_size; + } + } + + mv_penalty[f_code][mv+MAX_MV]= len; + } + } + + + for(f_code=MAX_FCODE; f_code>0; f_code--){ + for(mv=-(8<me.mv_penalty= mv_penalty; + s->fcode_tab= fcode_tab; + if(s->codec_id == AV_CODEC_ID_MPEG1VIDEO){ + s->min_qcoeff=-255; + s->max_qcoeff= 255; + }else{ + s->min_qcoeff=-2047; + s->max_qcoeff= 2047; + } + if (s->intra_vlc_format) { + s->intra_ac_vlc_length= + s->intra_ac_vlc_last_length= uni_mpeg2_ac_vlc_len; + } else { + s->intra_ac_vlc_length= + s->intra_ac_vlc_last_length= uni_mpeg1_ac_vlc_len; + } + s->inter_ac_vlc_length= + s->inter_ac_vlc_last_length= uni_mpeg1_ac_vlc_len; +} + +static inline void encode_dc(MpegEncContext *s, int diff, int component) +{ + if(((unsigned) (diff+255)) >= 511){ + int index; + + if(diff<0){ + index= av_log2_16bit(-2*diff); + diff--; + }else{ + index= av_log2_16bit(2*diff); + } + if (component == 0) { + put_bits( + &s->pb, + ff_mpeg12_vlc_dc_lum_bits[index] + index, + (ff_mpeg12_vlc_dc_lum_code[index]<pb, + ff_mpeg12_vlc_dc_chroma_bits[index] + index, + (ff_mpeg12_vlc_dc_chroma_code[index]<pb, + mpeg1_lum_dc_uni[diff+255]&0xFF, + mpeg1_lum_dc_uni[diff+255]>>8); + } else { + put_bits( + &s->pb, + mpeg1_chr_dc_uni[diff+255]&0xFF, + mpeg1_chr_dc_uni[diff+255]>>8); + } + } +} + +static void mpeg1_encode_block(MpegEncContext *s, + int16_t *block, + int n) +{ + int alevel, level, last_non_zero, dc, diff, i, j, run, last_index, sign; + int code, component; + const uint16_t (*table_vlc)[2] = ff_rl_mpeg1.table_vlc; + + last_index = s->block_last_index[n]; + + /* DC coef */ + if (s->mb_intra) { + component = (n <= 3 ? 0 : (n&1) + 1); + dc = block[0]; /* overflow is impossible */ + diff = dc - s->last_dc[component]; + encode_dc(s, diff, component); + s->last_dc[component] = dc; + i = 1; + if (s->intra_vlc_format) + table_vlc = ff_rl_mpeg2.table_vlc; + } else { + /* encode the first coefficient : needs to be done here because + it is handled slightly differently */ + level = block[0]; + if (abs(level) == 1) { + code = ((uint32_t)level >> 31); /* the sign bit */ + put_bits(&s->pb, 2, code | 0x02); + i = 1; + } else { + i = 0; + last_non_zero = -1; + goto next_coef; + } + } + + /* now quantify & encode AC coefs */ + last_non_zero = i - 1; + + for(;i<=last_index;i++) { + j = s->intra_scantable.permutated[i]; + level = block[j]; + next_coef: + /* encode using VLC */ + if (level != 0) { + run = i - last_non_zero - 1; + + alevel= level; + MASK_ABS(sign, alevel); + sign&=1; + + if (alevel <= mpeg1_max_level[0][run]){ + code= mpeg1_index_run[0][run] + alevel - 1; + /* store the vlc & sign at once */ + put_bits(&s->pb, table_vlc[code][1]+1, (table_vlc[code][0]<<1) + sign); + } else { + /* escape seems to be pretty rare <5% so I do not optimize it */ + put_bits(&s->pb, table_vlc[111][1], table_vlc[111][0]); + /* escape: only clip in this case */ + put_bits(&s->pb, 6, run); + if(s->codec_id == AV_CODEC_ID_MPEG1VIDEO){ + if (alevel < 128) { + put_sbits(&s->pb, 8, level); + } else { + if (level < 0) { + put_bits(&s->pb, 16, 0x8001 + level + 255); + } else { + put_sbits(&s->pb, 16, level); + } + } + }else{ + put_sbits(&s->pb, 12, level); + } + } + last_non_zero = i; + } + } + /* end of block */ + put_bits(&s->pb, table_vlc[112][1], table_vlc[112][0]); +} + +#define OFFSET(x) offsetof(MpegEncContext, x) +#define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM +#define COMMON_OPTS\ + { "gop_timecode", "MPEG GOP Timecode in hh:mm:ss[:;.]ff format", OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, VE },\ + { "intra_vlc", "Use MPEG-2 intra VLC table.", OFFSET(intra_vlc_format), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },\ + { "drop_frame_timecode", "Timecode is in drop frame format.", OFFSET(drop_frame_timecode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, \ + { "scan_offset", "Reserve space for SVCD scan offset user data.", OFFSET(scan_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + +static const AVOption mpeg1_options[] = { + COMMON_OPTS + FF_MPV_COMMON_OPTS + { NULL }, +}; + +static const AVOption mpeg2_options[] = { + COMMON_OPTS + { "non_linear_quant", "Use nonlinear quantizer.", OFFSET(q_scale_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + FF_MPV_COMMON_OPTS + { NULL }, +}; + +#define mpeg12_class(x)\ +static const AVClass mpeg## x ##_class = {\ + .class_name = "mpeg" #x "video encoder",\ + .item_name = av_default_item_name,\ + .option = mpeg## x ##_options,\ + .version = LIBAVUTIL_VERSION_INT,\ +}; + +mpeg12_class(1) +mpeg12_class(2) + +AVCodec ff_mpeg1video_encoder = { + .name = "mpeg1video", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG1VIDEO, + .priv_data_size = sizeof(MpegEncContext), + .init = encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .supported_framerates = ff_mpeg12_frame_rate_tab + 1, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE }, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), + .priv_class = &mpeg1_class, +}; + +AVCodec ff_mpeg2video_encoder = { + .name = "mpeg2video", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(MpegEncContext), + .init = encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .supported_framerates = ff_mpeg2_frame_rate_tab, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE + }, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), + .priv_class = &mpeg2_class, +}; diff --git a/ffmpeg/libavcodec/mpeg4audio.c b/ffmpeg/libavcodec/mpeg4audio.c new file mode 100644 index 0000000..68448e6 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4audio.c @@ -0,0 +1,190 @@ +/* + * MPEG-4 Audio common code + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * 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 "get_bits.h" +#include "put_bits.h" +#include "mpeg4audio.h" + +/** + * Parse MPEG-4 audio configuration for ALS object type. + * @param[in] gb bit reader context + * @param[in] c MPEG4AudioConfig structure to fill + * @return on success 0 is returned, otherwise a value < 0 + */ +static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c) +{ + if (get_bits_left(gb) < 112) + return -1; + + if (get_bits_long(gb, 32) != MKBETAG('A','L','S','\0')) + return -1; + + // override AudioSpecificConfig channel configuration and sample rate + // which are buggy in old ALS conformance files + c->sample_rate = get_bits_long(gb, 32); + + // skip number of samples + skip_bits_long(gb, 32); + + // read number of channels + c->chan_config = 0; + c->channels = get_bits(gb, 16) + 1; + + return 0; +} + +/* XXX: make sure to update the copies in the different encoders if you change + * this table */ +const int avpriv_mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; + +const uint8_t ff_mpeg4audio_channels[8] = { + 0, 1, 2, 3, 4, 5, 6, 8 +}; + +static inline int get_object_type(GetBitContext *gb) +{ + int object_type = get_bits(gb, 5); + if (object_type == AOT_ESCAPE) + object_type = 32 + get_bits(gb, 6); + return object_type; +} + +static inline int get_sample_rate(GetBitContext *gb, int *index) +{ + *index = get_bits(gb, 4); + return *index == 0x0f ? get_bits(gb, 24) : + avpriv_mpeg4audio_sample_rates[*index]; +} + +int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, + int bit_size, int sync_extension) +{ + GetBitContext gb; + int specific_config_bitindex; + + if (bit_size <= 0 || init_get_bits(&gb, buf, bit_size) < 0) + return AVERROR_INVALIDDATA; + c->object_type = get_object_type(&gb); + c->sample_rate = get_sample_rate(&gb, &c->sampling_index); + c->chan_config = get_bits(&gb, 4); + if (c->chan_config < FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) + c->channels = ff_mpeg4audio_channels[c->chan_config]; + c->sbr = -1; + c->ps = -1; + if (c->object_type == AOT_SBR || (c->object_type == AOT_PS && + // check for W6132 Annex YYYY draft MP3onMP4 + !(show_bits(&gb, 3) & 0x03 && !(show_bits(&gb, 9) & 0x3F)))) { + if (c->object_type == AOT_PS) + c->ps = 1; + c->ext_object_type = AOT_SBR; + c->sbr = 1; + c->ext_sample_rate = get_sample_rate(&gb, &c->ext_sampling_index); + c->object_type = get_object_type(&gb); + if (c->object_type == AOT_ER_BSAC) + c->ext_chan_config = get_bits(&gb, 4); + } else { + c->ext_object_type = AOT_NULL; + c->ext_sample_rate = 0; + } + specific_config_bitindex = get_bits_count(&gb); + + if (c->object_type == AOT_ALS) { + skip_bits(&gb, 5); + if (show_bits_long(&gb, 24) != MKBETAG('\0','A','L','S')) + skip_bits_long(&gb, 24); + + specific_config_bitindex = get_bits_count(&gb); + + if (parse_config_ALS(&gb, c)) + return -1; + } + + if (c->ext_object_type != AOT_SBR && sync_extension) { + while (get_bits_left(&gb) > 15) { + if (show_bits(&gb, 11) == 0x2b7) { // sync extension + get_bits(&gb, 11); + c->ext_object_type = get_object_type(&gb); + if (c->ext_object_type == AOT_SBR && (c->sbr = get_bits1(&gb)) == 1) { + c->ext_sample_rate = get_sample_rate(&gb, &c->ext_sampling_index); + if (c->ext_sample_rate == c->sample_rate) + c->sbr = -1; + } + if (get_bits_left(&gb) > 11 && get_bits(&gb, 11) == 0x548) + c->ps = get_bits1(&gb); + break; + } else + get_bits1(&gb); // skip 1 bit + } + } + + //PS requires SBR + if (!c->sbr) + c->ps = 0; + //Limit implicit PS to the HE-AACv2 Profile + if ((c->ps == -1 && c->object_type != AOT_AAC_LC) || c->channels & ~0x01) + c->ps = 0; + + return specific_config_bitindex; +} + +static av_always_inline unsigned int copy_bits(PutBitContext *pb, + GetBitContext *gb, + int bits) +{ + unsigned int el = get_bits(gb, bits); + put_bits(pb, bits, el); + return el; +} + +int avpriv_copy_pce_data(PutBitContext *pb, GetBitContext *gb) +{ + int five_bit_ch, four_bit_ch, comment_size, bits; + int offset = put_bits_count(pb); + + copy_bits(pb, gb, 10); //Tag, Object Type, Frequency + five_bit_ch = copy_bits(pb, gb, 4); //Front + five_bit_ch += copy_bits(pb, gb, 4); //Side + five_bit_ch += copy_bits(pb, gb, 4); //Back + four_bit_ch = copy_bits(pb, gb, 2); //LFE + four_bit_ch += copy_bits(pb, gb, 3); //Data + five_bit_ch += copy_bits(pb, gb, 4); //Coupling + if (copy_bits(pb, gb, 1)) //Mono Mixdown + copy_bits(pb, gb, 4); + if (copy_bits(pb, gb, 1)) //Stereo Mixdown + copy_bits(pb, gb, 4); + if (copy_bits(pb, gb, 1)) //Matrix Mixdown + copy_bits(pb, gb, 3); + for (bits = five_bit_ch*5+four_bit_ch*4; bits > 16; bits -= 16) + copy_bits(pb, gb, 16); + if (bits) + copy_bits(pb, gb, bits); + avpriv_align_put_bits(pb); + align_get_bits(gb); + comment_size = copy_bits(pb, gb, 8); + for (; comment_size > 0; comment_size--) + copy_bits(pb, gb, 8); + + return put_bits_count(pb) - offset; +} diff --git a/ffmpeg/libavcodec/mpeg4audio.h b/ffmpeg/libavcodec/mpeg4audio.h new file mode 100644 index 0000000..0f41045 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4audio.h @@ -0,0 +1,109 @@ +/* + * MPEG-4 Audio common header + * Copyright (c) 2008 Baptiste Coudurier + * + * 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 + */ + +#ifndef AVCODEC_MPEG4AUDIO_H +#define AVCODEC_MPEG4AUDIO_H + +#include +#include "get_bits.h" +#include "put_bits.h" + +typedef struct MPEG4AudioConfig { + int object_type; + int sampling_index; + int sample_rate; + int chan_config; + int sbr; ///< -1 implicit, 1 presence + int ext_object_type; + int ext_sampling_index; + int ext_sample_rate; + int ext_chan_config; + int channels; + int ps; ///< -1 implicit, 1 presence +} MPEG4AudioConfig; + +extern av_export const int avpriv_mpeg4audio_sample_rates[16]; +extern const uint8_t ff_mpeg4audio_channels[8]; + +/** + * Parse MPEG-4 systems extradata to retrieve audio configuration. + * @param[in] c MPEG4AudioConfig structure to fill. + * @param[in] buf Extradata from container. + * @param[in] bit_size Extradata size in bits. + * @param[in] sync_extension look for a sync extension after config if true. + * @return On error -1 is returned, on success AudioSpecificConfig bit index in extradata. + */ +int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, + int bit_size, int sync_extension); + +enum AudioObjectType { + AOT_NULL, + // Support? Name + AOT_AAC_MAIN, ///< Y Main + AOT_AAC_LC, ///< Y Low Complexity + AOT_AAC_SSR, ///< N (code in SoC repo) Scalable Sample Rate + AOT_AAC_LTP, ///< Y Long Term Prediction + AOT_SBR, ///< Y Spectral Band Replication + AOT_AAC_SCALABLE, ///< N Scalable + AOT_TWINVQ, ///< N Twin Vector Quantizer + AOT_CELP, ///< N Code Excited Linear Prediction + AOT_HVXC, ///< N Harmonic Vector eXcitation Coding + AOT_TTSI = 12, ///< N Text-To-Speech Interface + AOT_MAINSYNTH, ///< N Main Synthesis + AOT_WAVESYNTH, ///< N Wavetable Synthesis + AOT_MIDI, ///< N General MIDI + AOT_SAFX, ///< N Algorithmic Synthesis and Audio Effects + AOT_ER_AAC_LC, ///< N Error Resilient Low Complexity + AOT_ER_AAC_LTP = 19, ///< N Error Resilient Long Term Prediction + AOT_ER_AAC_SCALABLE, ///< N Error Resilient Scalable + AOT_ER_TWINVQ, ///< N Error Resilient Twin Vector Quantizer + AOT_ER_BSAC, ///< N Error Resilient Bit-Sliced Arithmetic Coding + AOT_ER_AAC_LD, ///< N Error Resilient Low Delay + AOT_ER_CELP, ///< N Error Resilient Code Excited Linear Prediction + AOT_ER_HVXC, ///< N Error Resilient Harmonic Vector eXcitation Coding + AOT_ER_HILN, ///< N Error Resilient Harmonic and Individual Lines plus Noise + AOT_ER_PARAM, ///< N Error Resilient Parametric + AOT_SSC, ///< N SinuSoidal Coding + AOT_PS, ///< N Parametric Stereo + AOT_SURROUND, ///< N MPEG Surround + AOT_ESCAPE, ///< Y Escape Value + AOT_L1, ///< Y Layer 1 + AOT_L2, ///< Y Layer 2 + AOT_L3, ///< Y Layer 3 + AOT_DST, ///< N Direct Stream Transfer + AOT_ALS, ///< Y Audio LosslesS + AOT_SLS, ///< N Scalable LosslesS + AOT_SLS_NON_CORE, ///< N Scalable LosslesS (non core) + AOT_ER_AAC_ELD, ///< N Error Resilient Enhanced Low Delay + AOT_SMR_SIMPLE, ///< N Symbolic Music Representation Simple + AOT_SMR_MAIN, ///< N Symbolic Music Representation Main + AOT_USAC_NOSBR, ///< N Unified Speech and Audio Coding (no SBR) + AOT_SAOC, ///< N Spatial Audio Object Coding + AOT_LD_SURROUND, ///< N Low Delay MPEG Surround + AOT_USAC, ///< N Unified Speech and Audio Coding +}; + +#define MAX_PCE_SIZE 304 /// + * + * 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 + */ + +/** + * @file + * mpeg4 tables. + */ + +#ifndef AVCODEC_MPEG4DATA_H +#define AVCODEC_MPEG4DATA_H + +#include +#include "mpegvideo.h" + +/* dc encoding for mpeg4 */ +const uint8_t ff_mpeg4_DCtab_lum[13][2] = +{ + {3,3}, {3,2}, {2,2}, {2,3}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, + {1,8}, {1,9}, {1,10}, {1,11}, +}; + +const uint8_t ff_mpeg4_DCtab_chrom[13][2] = +{ + {3,2}, {2,2}, {1,2}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, {1,8}, + {1,9}, {1,10}, {1,11}, {1,12}, +}; + +const uint16_t ff_mpeg4_intra_vlc[103][2] = { +{ 0x2, 2 }, +{ 0x6, 3 },{ 0xf, 4 },{ 0xd, 5 },{ 0xc, 5 }, +{ 0x15, 6 },{ 0x13, 6 },{ 0x12, 6 },{ 0x17, 7 }, +{ 0x1f, 8 },{ 0x1e, 8 },{ 0x1d, 8 },{ 0x25, 9 }, +{ 0x24, 9 },{ 0x23, 9 },{ 0x21, 9 },{ 0x21, 10 }, +{ 0x20, 10 },{ 0xf, 10 },{ 0xe, 10 },{ 0x7, 11 }, +{ 0x6, 11 },{ 0x20, 11 },{ 0x21, 11 },{ 0x50, 12 }, +{ 0x51, 12 },{ 0x52, 12 },{ 0xe, 4 },{ 0x14, 6 }, +{ 0x16, 7 },{ 0x1c, 8 },{ 0x20, 9 },{ 0x1f, 9 }, +{ 0xd, 10 },{ 0x22, 11 },{ 0x53, 12 },{ 0x55, 12 }, +{ 0xb, 5 },{ 0x15, 7 },{ 0x1e, 9 },{ 0xc, 10 }, +{ 0x56, 12 },{ 0x11, 6 },{ 0x1b, 8 },{ 0x1d, 9 }, +{ 0xb, 10 },{ 0x10, 6 },{ 0x22, 9 },{ 0xa, 10 }, +{ 0xd, 6 },{ 0x1c, 9 },{ 0x8, 10 },{ 0x12, 7 }, +{ 0x1b, 9 },{ 0x54, 12 },{ 0x14, 7 },{ 0x1a, 9 }, +{ 0x57, 12 },{ 0x19, 8 },{ 0x9, 10 },{ 0x18, 8 }, +{ 0x23, 11 },{ 0x17, 8 },{ 0x19, 9 },{ 0x18, 9 }, +{ 0x7, 10 },{ 0x58, 12 },{ 0x7, 4 },{ 0xc, 6 }, +{ 0x16, 8 },{ 0x17, 9 },{ 0x6, 10 },{ 0x5, 11 }, +{ 0x4, 11 },{ 0x59, 12 },{ 0xf, 6 },{ 0x16, 9 }, +{ 0x5, 10 },{ 0xe, 6 },{ 0x4, 10 },{ 0x11, 7 }, +{ 0x24, 11 },{ 0x10, 7 },{ 0x25, 11 },{ 0x13, 7 }, +{ 0x5a, 12 },{ 0x15, 8 },{ 0x5b, 12 },{ 0x14, 8 }, +{ 0x13, 8 },{ 0x1a, 8 },{ 0x15, 9 },{ 0x14, 9 }, +{ 0x13, 9 },{ 0x12, 9 },{ 0x11, 9 },{ 0x26, 11 }, +{ 0x27, 11 },{ 0x5c, 12 },{ 0x5d, 12 },{ 0x5e, 12 }, +{ 0x5f, 12 },{ 0x3, 7 }, +}; + +const int8_t ff_mpeg4_intra_level[102] = { + 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, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 1, 2, 3, + 4, 5, 1, 2, 3, 4, 1, 2, + 3, 1, 2, 3, 1, 2, 3, 1, + 2, 3, 1, 2, 1, 2, 1, 1, + 1, 1, 1, 1, 2, 3, 4, 5, + 6, 7, 8, 1, 2, 3, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +const int8_t ff_mpeg4_intra_run[102] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 4, 4, + 4, 5, 5, 5, 6, 6, 6, 7, + 7, 7, 8, 8, 9, 9, 10, 11, + 12, 13, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 2, 2, + 3, 3, 4, 4, 5, 5, 6, 6, + 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, +}; + +RLTable ff_mpeg4_rl_intra = { + 102, + 67, + ff_mpeg4_intra_vlc, + ff_mpeg4_intra_run, + ff_mpeg4_intra_level, +}; + +/* Note this is identical to the intra rvlc except that it is reordered. */ +static const uint16_t inter_rvlc[170][2]={ +{0x0006, 3},{0x0001, 4},{0x0004, 5},{0x001C, 7}, +{0x003C, 8},{0x003D, 8},{0x007C, 9},{0x00FC, 10}, +{0x00FD, 10},{0x01FC, 11},{0x01FD, 11},{0x03FC, 12}, +{0x07FC, 13},{0x07FD, 13},{0x0BFC, 13},{0x0BFD, 13}, +{0x0FFC, 14},{0x0FFD, 14},{0x1FFC, 15},{0x0007, 3}, +{0x000C, 6},{0x005C, 8},{0x007D, 9},{0x017C, 10}, +{0x02FC, 11},{0x03FD, 12},{0x0DFC, 13},{0x17FC, 14}, +{0x17FD, 14},{0x000A, 4},{0x001D, 7},{0x00BC, 9}, +{0x02FD, 11},{0x05FC, 12},{0x1BFC, 14},{0x1BFD, 14}, +{0x0005, 5},{0x005D, 8},{0x017D, 10},{0x05FD, 12}, +{0x0DFD, 13},{0x1DFC, 14},{0x1FFD, 15},{0x0008, 5}, +{0x006C, 8},{0x037C, 11},{0x0EFC, 13},{0x2FFC, 15}, +{0x0009, 5},{0x00BD, 9},{0x037D, 11},{0x0EFD, 13}, +{0x000D, 6},{0x01BC, 10},{0x06FC, 12},{0x1DFD, 14}, +{0x0014, 6},{0x01BD, 10},{0x06FD, 12},{0x2FFD, 15}, +{0x0015, 6},{0x01DC, 10},{0x0F7C, 13},{0x002C, 7}, +{0x01DD, 10},{0x1EFC, 14},{0x002D, 7},{0x03BC, 11}, +{0x0034, 7},{0x077C, 12},{0x006D, 8},{0x0F7D, 13}, +{0x0074, 8},{0x1EFD, 14},{0x0075, 8},{0x1F7C, 14}, +{0x00DC, 9},{0x1F7D, 14},{0x00DD, 9},{0x1FBC, 14}, +{0x00EC, 9},{0x37FC, 15},{0x01EC, 10},{0x01ED, 10}, +{0x01F4, 10},{0x03BD, 11},{0x03DC, 11},{0x03DD, 11}, +{0x03EC, 11},{0x03ED, 11},{0x03F4, 11},{0x077D, 12}, +{0x07BC, 12},{0x07BD, 12},{0x0FBC, 13},{0x0FBD, 13}, +{0x0FDC, 13},{0x0FDD, 13},{0x1FBD, 14},{0x1FDC, 14}, +{0x1FDD, 14},{0x37FD, 15},{0x3BFC, 15}, +{0x000B, 4},{0x0078, 8},{0x03F5, 11},{0x0FEC, 13}, +{0x1FEC, 14},{0x0012, 5},{0x00ED, 9},{0x07DC, 12}, +{0x1FED, 14},{0x3BFD, 15},{0x0013, 5},{0x03F8, 11}, +{0x3DFC, 15},{0x0018, 6},{0x07DD, 12},{0x0019, 6}, +{0x07EC, 12},{0x0022, 6},{0x0FED, 13},{0x0023, 6}, +{0x0FF4, 13},{0x0035, 7},{0x0FF5, 13},{0x0038, 7}, +{0x0FF8, 13},{0x0039, 7},{0x0FF9, 13},{0x0042, 7}, +{0x1FF4, 14},{0x0043, 7},{0x1FF5, 14},{0x0079, 8}, +{0x1FF8, 14},{0x0082, 8},{0x3DFD, 15},{0x0083, 8}, +{0x00F4, 9},{0x00F5, 9},{0x00F8, 9},{0x00F9, 9}, +{0x0102, 9},{0x0103, 9},{0x01F5, 10},{0x01F8, 10}, +{0x01F9, 10},{0x0202, 10},{0x0203, 10},{0x03F9, 11}, +{0x0402, 11},{0x0403, 11},{0x07ED, 12},{0x07F4, 12}, +{0x07F5, 12},{0x07F8, 12},{0x07F9, 12},{0x0802, 12}, +{0x0803, 12},{0x1002, 13},{0x1003, 13},{0x1FF9, 14}, +{0x2002, 14},{0x2003, 14},{0x3EFC, 15},{0x3EFD, 15}, +{0x3F7C, 15},{0x3F7D, 15},{0x0000, 4} +}; + +static const int8_t inter_rvlc_run[169]={ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 9, + 9, 9, 10, 10, 11, 11, 12, 12, +13, 13, 14, 14, 15, 15, 16, 16, +17, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, + 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 4, + 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, +12, 13, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, +27, 28, 29, 30, 31, 32, 33, 34, +35, 36, 37, 38, 39, 40, 41, 42, +43, 44, +}; + +static const int8_t inter_rvlc_level[169]={ + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 1, 2, 3, + 4, 5, 6, 7, 1, 2, 3, 4, + 5, 6, 7, 1, 2, 3, 4, 5, + 1, 2, 3, 4, 1, 2, 3, 4, + 1, 2, 3, 4, 1, 2, 3, 1, + 2, 3, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, + 1, 2, 3, 4, 5, 1, 2, 3, + 4, 5, 1, 2, 3, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, +}; + +RLTable ff_rvlc_rl_inter = { + 169, + 103, + inter_rvlc, + inter_rvlc_run, + inter_rvlc_level, +}; + +static const uint16_t intra_rvlc[170][2]={ +{0x0006, 3},{0x0007, 3},{0x000A, 4},{0x0009, 5}, +{0x0014, 6},{0x0015, 6},{0x0034, 7},{0x0074, 8}, +{0x0075, 8},{0x00DD, 9},{0x00EC, 9},{0x01EC, 10}, +{0x01ED, 10},{0x01F4, 10},{0x03EC, 11},{0x03ED, 11}, +{0x03F4, 11},{0x077D, 12},{0x07BC, 12},{0x0FBD, 13}, +{0x0FDC, 13},{0x07BD, 12},{0x0FDD, 13},{0x1FBD, 14}, +{0x1FDC, 14},{0x1FDD, 14},{0x1FFC, 15},{0x0001, 4}, +{0x0008, 5},{0x002D, 7},{0x006C, 8},{0x006D, 8}, +{0x00DC, 9},{0x01DD, 10},{0x03DC, 11},{0x03DD, 11}, +{0x077C, 12},{0x0FBC, 13},{0x1F7D, 14},{0x1FBC, 14}, +{0x0004, 5},{0x002C, 7},{0x00BC, 9},{0x01DC, 10}, +{0x03BC, 11},{0x03BD, 11},{0x0EFD, 13},{0x0F7C, 13}, +{0x0F7D, 13},{0x1EFD, 14},{0x1F7C, 14},{0x0005, 5}, +{0x005C, 8},{0x00BD, 9},{0x037D, 11},{0x06FC, 12}, +{0x0EFC, 13},{0x1DFD, 14},{0x1EFC, 14},{0x1FFD, 15}, +{0x000C, 6},{0x005D, 8},{0x01BD, 10},{0x03FD, 12}, +{0x06FD, 12},{0x1BFD, 14},{0x000D, 6},{0x007D, 9}, +{0x02FC, 11},{0x05FC, 12},{0x1BFC, 14},{0x1DFC, 14}, +{0x001C, 7},{0x017C, 10},{0x02FD, 11},{0x05FD, 12}, +{0x2FFC, 15},{0x001D, 7},{0x017D, 10},{0x037C, 11}, +{0x0DFD, 13},{0x2FFD, 15},{0x003C, 8},{0x01BC, 10}, +{0x0BFD, 13},{0x17FD, 14},{0x003D, 8},{0x01FD, 11}, +{0x0DFC, 13},{0x37FC, 15},{0x007C, 9},{0x03FC, 12}, +{0x00FC, 10},{0x0BFC, 13},{0x00FD, 10},{0x37FD, 15}, +{0x01FC, 11},{0x07FC, 13},{0x07FD, 13},{0x0FFC, 14}, +{0x0FFD, 14},{0x17FC, 14},{0x3BFC, 15}, +{0x000B, 4},{0x0078, 8},{0x03F5, 11},{0x0FEC, 13}, +{0x1FEC, 14},{0x0012, 5},{0x00ED, 9},{0x07DC, 12}, +{0x1FED, 14},{0x3BFD, 15},{0x0013, 5},{0x03F8, 11}, +{0x3DFC, 15},{0x0018, 6},{0x07DD, 12},{0x0019, 6}, +{0x07EC, 12},{0x0022, 6},{0x0FED, 13},{0x0023, 6}, +{0x0FF4, 13},{0x0035, 7},{0x0FF5, 13},{0x0038, 7}, +{0x0FF8, 13},{0x0039, 7},{0x0FF9, 13},{0x0042, 7}, +{0x1FF4, 14},{0x0043, 7},{0x1FF5, 14},{0x0079, 8}, +{0x1FF8, 14},{0x0082, 8},{0x3DFD, 15},{0x0083, 8}, +{0x00F4, 9},{0x00F5, 9},{0x00F8, 9},{0x00F9, 9}, +{0x0102, 9},{0x0103, 9},{0x01F5, 10},{0x01F8, 10}, +{0x01F9, 10},{0x0202, 10},{0x0203, 10},{0x03F9, 11}, +{0x0402, 11},{0x0403, 11},{0x07ED, 12},{0x07F4, 12}, +{0x07F5, 12},{0x07F8, 12},{0x07F9, 12},{0x0802, 12}, +{0x0803, 12},{0x1002, 13},{0x1003, 13},{0x1FF9, 14}, +{0x2002, 14},{0x2003, 14},{0x3EFC, 15},{0x3EFD, 15}, +{0x3F7C, 15},{0x3F7D, 15},{0x0000, 4} +}; + +static const int8_t intra_rvlc_run[169]={ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 11, 11, 12, 12, +13, 14, 15, 16, 17, 18, 19, + 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 4, + 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, +12, 13, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, +27, 28, 29, 30, 31, 32, 33, 34, +35, 36, 37, 38, 39, 40, 41, 42, +43, 44, +}; + +static const int8_t intra_rvlc_level[169]={ + 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, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 1, 2, 3, 4, + 5, 6, 1, 2, 3, 4, 5, 6, + 1, 2, 3, 4, 5, 1, 2, 3, + 4, 5, 1, 2, 3, 4, 1, 2, + 3, 4, 1, 2, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 1, 1, + 1, 2, 3, 4, 5, 1, 2, 3, + 4, 5, 1, 2, 3, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, +}; + +RLTable ff_rvlc_rl_intra = { + 169, + 103, + intra_rvlc, + intra_rvlc_run, + intra_rvlc_level, +}; + +const uint16_t ff_sprite_trajectory_tab[15][2] = { + {0x00, 2}, {0x02, 3}, {0x03, 3}, {0x04, 3}, {0x05, 3}, {0x06, 3}, + {0x0E, 4}, {0x1E, 5}, {0x3E, 6}, {0x7E, 7}, {0xFE, 8}, + {0x1FE, 9},{0x3FE, 10},{0x7FE, 11},{0xFFE, 12}, +}; + +const uint8_t ff_mb_type_b_tab[4][2] = { + {1, 1}, {1, 2}, {1, 3}, {1, 4}, +}; + +/* these matrixes will be permuted for the idct */ +const int16_t ff_mpeg4_default_intra_matrix[64] = { + 8, 17, 18, 19, 21, 23, 25, 27, + 17, 18, 19, 21, 23, 25, 27, 28, + 20, 21, 22, 23, 24, 26, 28, 30, + 21, 22, 23, 24, 26, 28, 30, 32, + 22, 23, 24, 26, 28, 30, 32, 35, + 23, 24, 26, 28, 30, 32, 35, 38, + 25, 26, 28, 30, 32, 35, 38, 41, + 27, 28, 30, 32, 35, 38, 41, 45, +}; + +const int16_t ff_mpeg4_default_non_intra_matrix[64] = { + 16, 17, 18, 19, 20, 21, 22, 23, + 17, 18, 19, 20, 21, 22, 23, 24, + 18, 19, 20, 21, 22, 23, 24, 25, + 19, 20, 21, 22, 23, 24, 26, 27, + 20, 21, 22, 23, 25, 26, 27, 28, + 21, 22, 23, 24, 26, 27, 28, 30, + 22, 23, 24, 26, 27, 28, 30, 31, + 23, 24, 25, 27, 28, 30, 31, 33, +}; + +const uint8_t ff_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 +}; +const uint8_t ff_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 +}; + +const uint16_t ff_mpeg4_resync_prefix[8]={ + 0x7F00, 0x7E00, 0x7C00, 0x7800, 0x7000, 0x6000, 0x4000, 0x0000 +}; + +const uint8_t ff_mpeg4_dc_threshold[8]={ + 99, 13, 15, 17, 19, 21, 23, 0 +}; + +#endif /* AVCODEC_MPEG4DATA_H */ diff --git a/ffmpeg/libavcodec/mpeg4video.c b/ffmpeg/libavcodec/mpeg4video.c new file mode 100644 index 0000000..9b86997 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4video.c @@ -0,0 +1,170 @@ +/* + * MPEG4 decoder / encoder common code. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 "mpegvideo.h" +#include "mpeg4video.h" +#include "mpeg4data.h" + +uint8_t ff_mpeg4_static_rl_table_store[3][2][2*MAX_RUN + MAX_LEVEL + 3]; + +int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s){ + switch(s->pict_type){ + case AV_PICTURE_TYPE_I: + return 16; + case AV_PICTURE_TYPE_P: + case AV_PICTURE_TYPE_S: + return s->f_code+15; + case AV_PICTURE_TYPE_B: + return FFMAX3(s->f_code, s->b_code, 2) + 15; + default: + return -1; + } +} + +void ff_mpeg4_clean_buffers(MpegEncContext *s) +{ + int c_wrap, c_xy, l_wrap, l_xy; + + l_wrap= s->b8_stride; + l_xy= (2*s->mb_y-1)*l_wrap + s->mb_x*2 - 1; + c_wrap= s->mb_stride; + c_xy= (s->mb_y-1)*c_wrap + s->mb_x - 1; + +#if 0 + /* clean DC */ + memsetw(s->dc_val[0] + l_xy, 1024, l_wrap*2+1); + memsetw(s->dc_val[1] + c_xy, 1024, c_wrap+1); + memsetw(s->dc_val[2] + c_xy, 1024, c_wrap+1); +#endif + + /* clean AC */ + memset(s->ac_val[0] + l_xy, 0, (l_wrap*2+1)*16*sizeof(int16_t)); + memset(s->ac_val[1] + c_xy, 0, (c_wrap +1)*16*sizeof(int16_t)); + memset(s->ac_val[2] + c_xy, 0, (c_wrap +1)*16*sizeof(int16_t)); + + /* clean MV */ + // we can't clear the MVs as they might be needed by a b frame +// memset(s->motion_val + l_xy, 0, (l_wrap*2+1)*2*sizeof(int16_t)); +// memset(s->motion_val, 0, 2*sizeof(int16_t)*(2 + s->mb_width*2)*(2 + s->mb_height*2)); + s->last_mv[0][0][0]= + s->last_mv[0][0][1]= + s->last_mv[1][0][0]= + s->last_mv[1][0][1]= 0; +} + +#define tab_size ((signed)FF_ARRAY_ELEMS(s->direct_scale_mv[0])) +#define tab_bias (tab_size/2) + +//used by mpeg4 and rv10 decoder +void ff_mpeg4_init_direct_mv(MpegEncContext *s){ + int i; + for(i=0; idirect_scale_mv[0][i] = (i-tab_bias)*s->pb_time/s->pp_time; + s->direct_scale_mv[1][i] = (i-tab_bias)*(s->pb_time-s->pp_time)/s->pp_time; + } +} + +static inline void ff_mpeg4_set_one_direct_mv(MpegEncContext *s, int mx, int my, int i){ + int xy= s->block_index[i]; + uint16_t time_pp= s->pp_time; + uint16_t time_pb= s->pb_time; + int p_mx, p_my; + + p_mx = s->next_picture.motion_val[0][xy][0]; + if((unsigned)(p_mx + tab_bias) < tab_size){ + s->mv[0][i][0] = s->direct_scale_mv[0][p_mx + tab_bias] + mx; + s->mv[1][i][0] = mx ? s->mv[0][i][0] - p_mx + : s->direct_scale_mv[1][p_mx + tab_bias]; + }else{ + s->mv[0][i][0] = p_mx*time_pb/time_pp + mx; + s->mv[1][i][0] = mx ? s->mv[0][i][0] - p_mx + : p_mx*(time_pb - time_pp)/time_pp; + } + p_my = s->next_picture.motion_val[0][xy][1]; + if((unsigned)(p_my + tab_bias) < tab_size){ + s->mv[0][i][1] = s->direct_scale_mv[0][p_my + tab_bias] + my; + s->mv[1][i][1] = my ? s->mv[0][i][1] - p_my + : s->direct_scale_mv[1][p_my + tab_bias]; + }else{ + s->mv[0][i][1] = p_my*time_pb/time_pp + my; + s->mv[1][i][1] = my ? s->mv[0][i][1] - p_my + : p_my*(time_pb - time_pp)/time_pp; + } +} + +#undef tab_size +#undef tab_bias + +/** + * + * @return the mb_type + */ +int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int my){ + const int mb_index= s->mb_x + s->mb_y*s->mb_stride; + const int colocated_mb_type = s->next_picture.mb_type[mb_index]; + uint16_t time_pp; + uint16_t time_pb; + int i; + + //FIXME avoid divides + // try special case with shifts for 1 and 3 B-frames? + + if(IS_8X8(colocated_mb_type)){ + s->mv_type = MV_TYPE_8X8; + for(i=0; i<4; i++){ + ff_mpeg4_set_one_direct_mv(s, mx, my, i); + } + return MB_TYPE_DIRECT2 | MB_TYPE_8x8 | MB_TYPE_L0L1; + } else if(IS_INTERLACED(colocated_mb_type)){ + s->mv_type = MV_TYPE_FIELD; + for(i=0; i<2; i++){ + int field_select = s->next_picture.ref_index[0][4 * mb_index + 2 * i]; + s->field_select[0][i]= field_select; + s->field_select[1][i]= i; + if(s->top_field_first){ + time_pp= s->pp_field_time - field_select + i; + time_pb= s->pb_field_time - field_select + i; + }else{ + time_pp= s->pp_field_time + field_select - i; + time_pb= s->pb_field_time + field_select - i; + } + s->mv[0][i][0] = s->p_field_mv_table[i][0][mb_index][0]*time_pb/time_pp + mx; + s->mv[0][i][1] = s->p_field_mv_table[i][0][mb_index][1]*time_pb/time_pp + my; + s->mv[1][i][0] = mx ? s->mv[0][i][0] - s->p_field_mv_table[i][0][mb_index][0] + : s->p_field_mv_table[i][0][mb_index][0]*(time_pb - time_pp)/time_pp; + s->mv[1][i][1] = my ? s->mv[0][i][1] - s->p_field_mv_table[i][0][mb_index][1] + : s->p_field_mv_table[i][0][mb_index][1]*(time_pb - time_pp)/time_pp; + } + return MB_TYPE_DIRECT2 | MB_TYPE_16x8 | MB_TYPE_L0L1 | MB_TYPE_INTERLACED; + }else{ + ff_mpeg4_set_one_direct_mv(s, mx, my, 0); + s->mv[0][1][0] = s->mv[0][2][0] = s->mv[0][3][0] = s->mv[0][0][0]; + s->mv[0][1][1] = s->mv[0][2][1] = s->mv[0][3][1] = s->mv[0][0][1]; + s->mv[1][1][0] = s->mv[1][2][0] = s->mv[1][3][0] = s->mv[1][0][0]; + s->mv[1][1][1] = s->mv[1][2][1] = s->mv[1][3][1] = s->mv[1][0][1]; + if((s->avctx->workaround_bugs & FF_BUG_DIRECT_BLOCKSIZE) || !s->quarter_sample) + s->mv_type= MV_TYPE_16X16; + else + s->mv_type= MV_TYPE_8X8; + return MB_TYPE_DIRECT2 | MB_TYPE_16x16 | MB_TYPE_L0L1; //Note see prev line + } +} diff --git a/ffmpeg/libavcodec/mpeg4video.h b/ffmpeg/libavcodec/mpeg4video.h new file mode 100644 index 0000000..400ce4d --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4video.h @@ -0,0 +1,200 @@ +/* + * MPEG4 encoder/decoder internal header. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 + */ + +#ifndef AVCODEC_MPEG4VIDEO_H +#define AVCODEC_MPEG4VIDEO_H + +#include +#include "get_bits.h" +#include "mpegvideo.h" +#include "rl.h" + +// shapes +#define RECT_SHAPE 0 +#define BIN_SHAPE 1 +#define BIN_ONLY_SHAPE 2 +#define GRAY_SHAPE 3 + +#define SIMPLE_VO_TYPE 1 +#define CORE_VO_TYPE 3 +#define MAIN_VO_TYPE 4 +#define NBIT_VO_TYPE 5 +#define ARTS_VO_TYPE 10 +#define ACE_VO_TYPE 12 +#define ADV_SIMPLE_VO_TYPE 17 + +// aspect_ratio_info +#define EXTENDED_PAR 15 + +//vol_sprite_usage / sprite_enable +#define STATIC_SPRITE 1 +#define GMC_SPRITE 2 + +#define MOTION_MARKER 0x1F001 +#define DC_MARKER 0x6B001 + +#define VOS_STARTCODE 0x1B0 +#define USER_DATA_STARTCODE 0x1B2 +#define GOP_STARTCODE 0x1B3 +#define VISUAL_OBJ_STARTCODE 0x1B5 +#define VOP_STARTCODE 0x1B6 + +/* dc encoding for mpeg4 */ +extern const uint8_t ff_mpeg4_DCtab_lum[13][2]; +extern const uint8_t ff_mpeg4_DCtab_chrom[13][2]; + +extern const uint16_t ff_mpeg4_intra_vlc[103][2]; +extern RLTable ff_mpeg4_rl_intra; + +/* Note this is identical to the intra rvlc except that it is reordered. */ +extern RLTable ff_rvlc_rl_inter; +extern RLTable ff_rvlc_rl_intra; + +extern const uint16_t ff_sprite_trajectory_tab[15][2]; +extern const uint8_t ff_mb_type_b_tab[4][2]; + +/* these matrixes will be permuted for the idct */ +extern const int16_t ff_mpeg4_default_intra_matrix[64]; +extern const int16_t ff_mpeg4_default_non_intra_matrix[64]; + +extern const uint8_t ff_mpeg4_y_dc_scale_table[32]; +extern const uint8_t ff_mpeg4_c_dc_scale_table[32]; +extern const uint16_t ff_mpeg4_resync_prefix[8]; + +extern const uint8_t ff_mpeg4_dc_threshold[8]; + +void ff_mpeg4_encode_mb(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y); +void ff_mpeg4_pred_ac(MpegEncContext * s, int16_t *block, int n, + int dir); +void ff_set_mpeg4_time(MpegEncContext * s); +void ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); + +int ff_mpeg4_decode_picture_header(MpegEncContext * s, GetBitContext *gb); +void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); +void ff_mpeg4_clean_buffers(MpegEncContext *s); +void ff_mpeg4_stuffing(PutBitContext * pbc); +void ff_mpeg4_init_partitions(MpegEncContext *s); +void ff_mpeg4_merge_partitions(MpegEncContext *s); +void ff_clean_mpeg4_qscales(MpegEncContext *s); +int ff_mpeg4_decode_partitions(MpegEncContext *s); +int ff_mpeg4_get_video_packet_prefix_length(MpegEncContext *s); +int ff_mpeg4_decode_video_packet_header(MpegEncContext *s); +void ff_mpeg4_init_direct_mv(MpegEncContext *s); +void ff_mpeg4videodec_static_init(void); + +/** + * + * @return the mb_type + */ +int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int my); + +extern uint8_t ff_mpeg4_static_rl_table_store[3][2][2*MAX_RUN + MAX_LEVEL + 3]; + + +#if 0 //3IV1 is quite rare and it slows things down a tiny bit +#define IS_3IV1 s->codec_tag == AV_RL32("3IV1") +#else +#define IS_3IV1 0 +#endif + + +/** + * Predict the dc. + * encoding quantized level -> quantized diff + * decoding quantized diff -> quantized level + * @param n block index (0-3 are luma, 4-5 are chroma) + * @param dir_ptr pointer to an integer where the prediction direction will be stored + */ +static inline int ff_mpeg4_pred_dc(MpegEncContext * s, int n, int level, int *dir_ptr, int encoding) +{ + int a, b, c, wrap, pred, scale, ret; + int16_t *dc_val; + + /* find prediction */ + if (n < 4) { + scale = s->y_dc_scale; + } else { + scale = s->c_dc_scale; + } + if(IS_3IV1) + scale= 8; + + wrap= s->block_wrap[n]; + dc_val = s->dc_val[0] + s->block_index[n]; + + /* B C + * A X + */ + a = dc_val[ - 1]; + b = dc_val[ - 1 - wrap]; + c = dc_val[ - wrap]; + + /* outside slice handling (we can't do that by memset as we need the dc for error resilience) */ + if(s->first_slice_line && n!=3){ + if(n!=2) b=c= 1024; + if(n!=1 && s->mb_x == s->resync_mb_x) b=a= 1024; + } + if(s->mb_x == s->resync_mb_x && s->mb_y == s->resync_mb_y+1){ + if(n==0 || n==4 || n==5) + b=1024; + } + + if (abs(a - b) < abs(b - c)) { + pred = c; + *dir_ptr = 1; /* top */ + } else { + pred = a; + *dir_ptr = 0; /* left */ + } + /* we assume pred is positive */ + pred = FASTDIV((pred + (scale >> 1)), scale); + + if(encoding){ + ret = level - pred; + }else{ + level += pred; + ret= level; + if(s->err_recognition&(AV_EF_BITSTREAM|AV_EF_AGGRESSIVE)){ + if(level<0){ + av_log(s->avctx, AV_LOG_ERROR, "dc<0 at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + if(level*scale > 2048 + scale){ + av_log(s->avctx, AV_LOG_ERROR, "dc overflow at %dx%d\n", s->mb_x, s->mb_y); + return -1; + } + } + } + level *=scale; + if(level&(~2047)){ + if(level<0) + level=0; + else if(!(s->workaround_bugs&FF_BUG_DC_CLIP)) + level=2047; + } + dc_val[0]= level; + + return ret; +} +#endif /* AVCODEC_MPEG4VIDEO_H */ diff --git a/ffmpeg/libavcodec/mpeg4video_parser.c b/ffmpeg/libavcodec/mpeg4video_parser.c new file mode 100644 index 0000000..3cbd69d --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4video_parser.c @@ -0,0 +1,154 @@ +/* + * MPEG4 Video frame extraction + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +#include "parser.h" +#include "mpegvideo.h" +#include "mpeg4video.h" +#include "mpeg4video_parser.h" + +struct Mp4vParseContext { + ParseContext pc; + struct MpegEncContext enc; + int first_picture; +}; + +int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size){ + int vop_found, i; + uint32_t state; + + vop_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!vop_found){ + for(i=0; iframe_start_found=0; + pc->state=-1; + return i-3; + } + } + } + pc->frame_start_found= vop_found; + pc->state= state; + return END_NOT_FOUND; +} + +/* XXX: make it use less memory */ +static int av_mpeg4_decode_header(AVCodecParserContext *s1, + AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + struct Mp4vParseContext *pc = s1->priv_data; + MpegEncContext *s = &pc->enc; + GetBitContext gb1, *gb = &gb1; + int ret; + + s->avctx = avctx; + s->current_picture_ptr = &s->current_picture; + + if (avctx->extradata_size && pc->first_picture){ + init_get_bits(gb, avctx->extradata, avctx->extradata_size*8); + ret = ff_mpeg4_decode_picture_header(s, gb); + } + + init_get_bits(gb, buf, 8 * buf_size); + ret = ff_mpeg4_decode_picture_header(s, gb); + if (s->width && (!avctx->width || !avctx->height || !avctx->coded_width || !avctx->coded_height)) { + avcodec_set_dimensions(avctx, s->width, s->height); + } + if((s1->flags & PARSER_FLAG_USE_CODEC_TS) && s->avctx->time_base.den>0 && ret>=0){ + av_assert1(s1->pts == AV_NOPTS_VALUE); + av_assert1(s1->dts == AV_NOPTS_VALUE); + + s1->pts = av_rescale_q(s->time, (AVRational){1, s->avctx->time_base.den}, (AVRational){1, 1200000}); + } + + s1->pict_type= s->pict_type; + pc->first_picture = 0; + return ret; +} + +static av_cold int mpeg4video_parse_init(AVCodecParserContext *s) +{ + struct Mp4vParseContext *pc = s->priv_data; + + ff_mpeg4videodec_static_init(); + + pc->first_picture = 1; + pc->enc.quant_precision=5; + pc->enc.slice_context_count = 1; + return 0; +} + +static int mpeg4video_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= ff_mpeg4_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + av_mpeg4_decode_header(s, avctx, buf, buf_size); + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + + +AVCodecParser ff_mpeg4video_parser = { + .codec_ids = { AV_CODEC_ID_MPEG4 }, + .priv_data_size = sizeof(struct Mp4vParseContext), + .parser_init = mpeg4video_parse_init, + .parser_parse = mpeg4video_parse, + .parser_close = ff_parse_close, + .split = ff_mpeg4video_split, +}; diff --git a/ffmpeg/libavcodec/mpeg4video_parser.h b/ffmpeg/libavcodec/mpeg4video_parser.h new file mode 100644 index 0000000..50f8b44 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4video_parser.h @@ -0,0 +1,34 @@ +/* + * MPEG4 video parser prototypes + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 + */ + +#ifndef AVCODEC_MPEG4VIDEO_PARSER_H +#define AVCODEC_MPEG4VIDEO_PARSER_H + +#include "parser.h" + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +int ff_mpeg4_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size); + +#endif /* AVCODEC_MPEG4VIDEO_PARSER_H */ diff --git a/ffmpeg/libavcodec/mpeg4videodec.c b/ffmpeg/libavcodec/mpeg4videodec.c new file mode 100644 index 0000000..be4aa37 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4videodec.c @@ -0,0 +1,2389 @@ +/* + * MPEG4 decoder. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 + */ + +#define UNCHECKED_BITSTREAM_READER 1 + +#include "libavutil/opt.h" +#include "error_resilience.h" +#include "internal.h" +#include "mpegvideo.h" +#include "mpeg4video.h" +#include "h263.h" +#include "thread.h" + +// The defines below define the number of bits that are read at once for +// reading vlc values. Changing these may improve speed and data cache needs +// be aware though that decreasing them may need the number of stages that is +// passed to get_vlc* to be increased. +#define SPRITE_TRAJ_VLC_BITS 6 +#define DC_VLC_BITS 9 +#define MB_TYPE_B_VLC_BITS 4 + + +static VLC dc_lum, dc_chrom; +static VLC sprite_trajectory; +static VLC mb_type_b_vlc; + +static const int mb_type_b_map[4]= { + MB_TYPE_DIRECT2 | MB_TYPE_L0L1, + MB_TYPE_L0L1 | MB_TYPE_16x16, + MB_TYPE_L1 | MB_TYPE_16x16, + MB_TYPE_L0 | MB_TYPE_16x16, +}; + +/** + * Predict the ac. + * @param n block index (0-3 are luma, 4-5 are chroma) + * @param dir the ac prediction direction + */ +void ff_mpeg4_pred_ac(MpegEncContext * s, int16_t *block, int n, + int dir) +{ + int i; + int16_t *ac_val, *ac_val1; + int8_t * const qscale_table = s->current_picture.qscale_table; + + /* find prediction */ + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val1 = ac_val; + if (s->ac_pred) { + if (dir == 0) { + const int xy= s->mb_x-1 + s->mb_y*s->mb_stride; + /* left prediction */ + ac_val -= 16; + + if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){ + /* same qscale */ + for(i=1;i<8;i++) { + block[s->dsp.idct_permutation[i<<3]] += ac_val[i]; + } + }else{ + /* different qscale, we must rescale */ + for(i=1;i<8;i++) { + block[s->dsp.idct_permutation[i<<3]] += ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale); + } + } + } else { + const int xy= s->mb_x + s->mb_y*s->mb_stride - s->mb_stride; + /* top prediction */ + ac_val -= 16 * s->block_wrap[n]; + + if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){ + /* same qscale */ + for(i=1;i<8;i++) { + block[s->dsp.idct_permutation[i]] += ac_val[i + 8]; + } + }else{ + /* different qscale, we must rescale */ + for(i=1;i<8;i++) { + block[s->dsp.idct_permutation[i]] += ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale); + } + } + } + } + /* left copy */ + for(i=1;i<8;i++) + ac_val1[i ] = block[s->dsp.idct_permutation[i<<3]]; + + /* top copy */ + for(i=1;i<8;i++) + ac_val1[8 + i] = block[s->dsp.idct_permutation[i ]]; + +} + +/** + * check if the next stuff is a resync marker or the end. + * @return 0 if not + */ +static inline int mpeg4_is_resync(MpegEncContext *s){ + int bits_count= get_bits_count(&s->gb); + int v= show_bits(&s->gb, 16); + + if(s->workaround_bugs&FF_BUG_NO_PADDING && !s->resync_marker){ + return 0; + } + + while(v<=0xFF){ + if(s->pict_type==AV_PICTURE_TYPE_B || (v>>(8-s->pict_type)!=1) || s->partitioned_frame) + break; + skip_bits(&s->gb, 8+s->pict_type); + bits_count+= 8+s->pict_type; + v= show_bits(&s->gb, 16); + } + + if(bits_count + 8 >= s->gb.size_in_bits){ + v>>=8; + v|= 0x7F >> (7-(bits_count&7)); + + if(v==0x7F) + return s->mb_num; + }else{ + if(v == ff_mpeg4_resync_prefix[bits_count&7]){ + int len, mb_num; + int mb_num_bits= av_log2(s->mb_num - 1) + 1; + GetBitContext gb= s->gb; + + skip_bits(&s->gb, 1); + align_get_bits(&s->gb); + + for(len=0; len<32; len++){ + if(get_bits1(&s->gb)) break; + } + + mb_num= get_bits(&s->gb, mb_num_bits); + if(!mb_num || mb_num > s->mb_num || get_bits_count(&s->gb)+6 > s->gb.size_in_bits) + mb_num= -1; + + s->gb= gb; + + if(len>=ff_mpeg4_get_video_packet_prefix_length(s)) + return mb_num; + } + } + return 0; +} + +static int mpeg4_decode_sprite_trajectory(MpegEncContext * s, GetBitContext *gb) +{ + int i; + int a= 2<sprite_warping_accuracy; + int rho= 3-s->sprite_warping_accuracy; + int r=16/a; + const int vop_ref[4][2]= {{0,0}, {s->width,0}, {0, s->height}, {s->width, s->height}}; // only true for rectangle shapes + int d[4][2]={{0,0}, {0,0}, {0,0}, {0,0}}; + int sprite_ref[4][2]; + int virtual_ref[2][2]; + int w2, h2, w3, h3; + int alpha=0, beta=0; + int w= s->width; + int h= s->height; + int min_ab; + + if(w<=0 || h<=0) + return -1; + + for(i=0; inum_sprite_warping_points; i++){ + int length; + int x=0, y=0; + + length= get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 3); + if(length){ + x= get_xbits(gb, length); + } + if(!(s->divx_version==500 && s->divx_build==413)) skip_bits1(gb); /* marker bit */ + + length= get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 3); + if(length){ + y=get_xbits(gb, length); + } + skip_bits1(gb); /* marker bit */ + s->sprite_traj[i][0]= d[i][0]= x; + s->sprite_traj[i][1]= d[i][1]= y; + } + for(; i<4; i++) + s->sprite_traj[i][0]= s->sprite_traj[i][1]= 0; + + while((1<divx_version==500 && s->divx_build==413){ + sprite_ref[0][0]= a*vop_ref[0][0] + d[0][0]; + sprite_ref[0][1]= a*vop_ref[0][1] + d[0][1]; + sprite_ref[1][0]= a*vop_ref[1][0] + d[0][0] + d[1][0]; + sprite_ref[1][1]= a*vop_ref[1][1] + d[0][1] + d[1][1]; + sprite_ref[2][0]= a*vop_ref[2][0] + d[0][0] + d[2][0]; + sprite_ref[2][1]= a*vop_ref[2][1] + d[0][1] + d[2][1]; + } else { + sprite_ref[0][0]= (a>>1)*(2*vop_ref[0][0] + d[0][0]); + sprite_ref[0][1]= (a>>1)*(2*vop_ref[0][1] + d[0][1]); + sprite_ref[1][0]= (a>>1)*(2*vop_ref[1][0] + d[0][0] + d[1][0]); + sprite_ref[1][1]= (a>>1)*(2*vop_ref[1][1] + d[0][1] + d[1][1]); + sprite_ref[2][0]= (a>>1)*(2*vop_ref[2][0] + d[0][0] + d[2][0]); + sprite_ref[2][1]= (a>>1)*(2*vop_ref[2][1] + d[0][1] + d[2][1]); + } +/* sprite_ref[3][0]= (a>>1)*(2*vop_ref[3][0] + d[0][0] + d[1][0] + d[2][0] + d[3][0]); + sprite_ref[3][1]= (a>>1)*(2*vop_ref[3][1] + d[0][1] + d[1][1] + d[2][1] + d[3][1]); */ + +// this is mostly identical to the mpeg4 std (and is totally unreadable because of that ...) +// perhaps it should be reordered to be more readable ... +// the idea behind this virtual_ref mess is to be able to use shifts later per pixel instead of divides +// so the distance between points is converted from w&h based to w2&h2 based which are of the 2^x form + virtual_ref[0][0]= 16*(vop_ref[0][0] + w2) + + ROUNDED_DIV(((w - w2)*(r*sprite_ref[0][0] - 16*vop_ref[0][0]) + w2*(r*sprite_ref[1][0] - 16*vop_ref[1][0])),w); + virtual_ref[0][1]= 16*vop_ref[0][1] + + ROUNDED_DIV(((w - w2)*(r*sprite_ref[0][1] - 16*vop_ref[0][1]) + w2*(r*sprite_ref[1][1] - 16*vop_ref[1][1])),w); + virtual_ref[1][0]= 16*vop_ref[0][0] + + ROUNDED_DIV(((h - h2)*(r*sprite_ref[0][0] - 16*vop_ref[0][0]) + h2*(r*sprite_ref[2][0] - 16*vop_ref[2][0])),h); + virtual_ref[1][1]= 16*(vop_ref[0][1] + h2) + + ROUNDED_DIV(((h - h2)*(r*sprite_ref[0][1] - 16*vop_ref[0][1]) + h2*(r*sprite_ref[2][1] - 16*vop_ref[2][1])),h); + + switch(s->num_sprite_warping_points) + { + case 0: + s->sprite_offset[0][0]= 0; + s->sprite_offset[0][1]= 0; + s->sprite_offset[1][0]= 0; + s->sprite_offset[1][1]= 0; + s->sprite_delta[0][0]= a; + s->sprite_delta[0][1]= 0; + s->sprite_delta[1][0]= 0; + s->sprite_delta[1][1]= a; + s->sprite_shift[0]= 0; + s->sprite_shift[1]= 0; + break; + case 1: //GMC only + s->sprite_offset[0][0]= sprite_ref[0][0] - a*vop_ref[0][0]; + s->sprite_offset[0][1]= sprite_ref[0][1] - a*vop_ref[0][1]; + s->sprite_offset[1][0]= ((sprite_ref[0][0]>>1)|(sprite_ref[0][0]&1)) - a*(vop_ref[0][0]/2); + s->sprite_offset[1][1]= ((sprite_ref[0][1]>>1)|(sprite_ref[0][1]&1)) - a*(vop_ref[0][1]/2); + s->sprite_delta[0][0]= a; + s->sprite_delta[0][1]= 0; + s->sprite_delta[1][0]= 0; + s->sprite_delta[1][1]= a; + s->sprite_shift[0]= 0; + s->sprite_shift[1]= 0; + break; + case 2: + s->sprite_offset[0][0]= (sprite_ref[0][0]<<(alpha+rho)) + + (-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][0]) + + ( r*sprite_ref[0][1] - virtual_ref[0][1])*(-vop_ref[0][1]) + + (1<<(alpha+rho-1)); + s->sprite_offset[0][1]= (sprite_ref[0][1]<<(alpha+rho)) + + (-r*sprite_ref[0][1] + virtual_ref[0][1])*(-vop_ref[0][0]) + + (-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][1]) + + (1<<(alpha+rho-1)); + s->sprite_offset[1][0]= ( (-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][0] + 1) + +( r*sprite_ref[0][1] - virtual_ref[0][1])*(-2*vop_ref[0][1] + 1) + +2*w2*r*sprite_ref[0][0] + - 16*w2 + + (1<<(alpha+rho+1))); + s->sprite_offset[1][1]= ( (-r*sprite_ref[0][1] + virtual_ref[0][1])*(-2*vop_ref[0][0] + 1) + +(-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][1] + 1) + +2*w2*r*sprite_ref[0][1] + - 16*w2 + + (1<<(alpha+rho+1))); + s->sprite_delta[0][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); + s->sprite_delta[0][1]= (+r*sprite_ref[0][1] - virtual_ref[0][1]); + s->sprite_delta[1][0]= (-r*sprite_ref[0][1] + virtual_ref[0][1]); + s->sprite_delta[1][1]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); + + s->sprite_shift[0]= alpha+rho; + s->sprite_shift[1]= alpha+rho+2; + break; + case 3: + min_ab= FFMIN(alpha, beta); + w3= w2>>min_ab; + h3= h2>>min_ab; + s->sprite_offset[0][0]= (sprite_ref[0][0]<<(alpha+beta+rho-min_ab)) + + (-r*sprite_ref[0][0] + virtual_ref[0][0])*h3*(-vop_ref[0][0]) + + (-r*sprite_ref[0][0] + virtual_ref[1][0])*w3*(-vop_ref[0][1]) + + (1<<(alpha+beta+rho-min_ab-1)); + s->sprite_offset[0][1]= (sprite_ref[0][1]<<(alpha+beta+rho-min_ab)) + + (-r*sprite_ref[0][1] + virtual_ref[0][1])*h3*(-vop_ref[0][0]) + + (-r*sprite_ref[0][1] + virtual_ref[1][1])*w3*(-vop_ref[0][1]) + + (1<<(alpha+beta+rho-min_ab-1)); + s->sprite_offset[1][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0])*h3*(-2*vop_ref[0][0] + 1) + + (-r*sprite_ref[0][0] + virtual_ref[1][0])*w3*(-2*vop_ref[0][1] + 1) + + 2*w2*h3*r*sprite_ref[0][0] + - 16*w2*h3 + + (1<<(alpha+beta+rho-min_ab+1)); + s->sprite_offset[1][1]= (-r*sprite_ref[0][1] + virtual_ref[0][1])*h3*(-2*vop_ref[0][0] + 1) + + (-r*sprite_ref[0][1] + virtual_ref[1][1])*w3*(-2*vop_ref[0][1] + 1) + + 2*w2*h3*r*sprite_ref[0][1] + - 16*w2*h3 + + (1<<(alpha+beta+rho-min_ab+1)); + s->sprite_delta[0][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0])*h3; + s->sprite_delta[0][1]= (-r*sprite_ref[0][0] + virtual_ref[1][0])*w3; + s->sprite_delta[1][0]= (-r*sprite_ref[0][1] + virtual_ref[0][1])*h3; + s->sprite_delta[1][1]= (-r*sprite_ref[0][1] + virtual_ref[1][1])*w3; + + s->sprite_shift[0]= alpha + beta + rho - min_ab; + s->sprite_shift[1]= alpha + beta + rho - min_ab + 2; + break; + } + /* try to simplify the situation */ + if( s->sprite_delta[0][0] == a<sprite_shift[0] + && s->sprite_delta[0][1] == 0 + && s->sprite_delta[1][0] == 0 + && s->sprite_delta[1][1] == a<sprite_shift[0]) + { + s->sprite_offset[0][0]>>=s->sprite_shift[0]; + s->sprite_offset[0][1]>>=s->sprite_shift[0]; + s->sprite_offset[1][0]>>=s->sprite_shift[1]; + s->sprite_offset[1][1]>>=s->sprite_shift[1]; + s->sprite_delta[0][0]= a; + s->sprite_delta[0][1]= 0; + s->sprite_delta[1][0]= 0; + s->sprite_delta[1][1]= a; + s->sprite_shift[0]= 0; + s->sprite_shift[1]= 0; + s->real_sprite_warping_points=1; + } + else{ + int shift_y= 16 - s->sprite_shift[0]; + int shift_c= 16 - s->sprite_shift[1]; + for(i=0; i<2; i++){ + s->sprite_offset[0][i]<<= shift_y; + s->sprite_offset[1][i]<<= shift_c; + s->sprite_delta[0][i]<<= shift_y; + s->sprite_delta[1][i]<<= shift_y; + s->sprite_shift[i]= 16; + } + s->real_sprite_warping_points= s->num_sprite_warping_points; + } + return 0; +} + +/** + * Decode the next video packet. + * @return <0 if something went wrong + */ +int ff_mpeg4_decode_video_packet_header(MpegEncContext *s) +{ + int mb_num_bits= av_log2(s->mb_num - 1) + 1; + int header_extension=0, mb_num, len; + + /* is there enough space left for a video packet + header */ + if( get_bits_count(&s->gb) > s->gb.size_in_bits-20) return -1; + + for(len=0; len<32; len++){ + if(get_bits1(&s->gb)) break; + } + + if(len!=ff_mpeg4_get_video_packet_prefix_length(s)){ + av_log(s->avctx, AV_LOG_ERROR, "marker does not match f_code\n"); + return -1; + } + + if(s->shape != RECT_SHAPE){ + header_extension= get_bits1(&s->gb); + //FIXME more stuff here + } + + mb_num= get_bits(&s->gb, mb_num_bits); + if(mb_num>=s->mb_num){ + av_log(s->avctx, AV_LOG_ERROR, "illegal mb_num in video packet (%d %d) \n", mb_num, s->mb_num); + return -1; + } + + s->mb_x= mb_num % s->mb_width; + s->mb_y= mb_num / s->mb_width; + + if(s->shape != BIN_ONLY_SHAPE){ + int qscale= get_bits(&s->gb, s->quant_precision); + if(qscale) + s->chroma_qscale=s->qscale= qscale; + } + + if(s->shape == RECT_SHAPE){ + header_extension= get_bits1(&s->gb); + } + if(header_extension){ + int time_incr=0; + + while (get_bits1(&s->gb) != 0) + time_incr++; + + check_marker(&s->gb, "before time_increment in video packed header"); + skip_bits(&s->gb, s->time_increment_bits); /* time_increment */ + check_marker(&s->gb, "before vop_coding_type in video packed header"); + + skip_bits(&s->gb, 2); /* vop coding type */ + //FIXME not rect stuff here + + if(s->shape != BIN_ONLY_SHAPE){ + skip_bits(&s->gb, 3); /* intra dc vlc threshold */ +//FIXME don't just ignore everything + if(s->pict_type == AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE){ + if(mpeg4_decode_sprite_trajectory(s, &s->gb) < 0) + return -1; + av_log(s->avctx, AV_LOG_ERROR, "untested\n"); + } + + //FIXME reduced res stuff here + + if (s->pict_type != AV_PICTURE_TYPE_I) { + int f_code = get_bits(&s->gb, 3); /* fcode_for */ + if(f_code==0){ + av_log(s->avctx, AV_LOG_ERROR, "Error, video packet header damaged (f_code=0)\n"); + } + } + if (s->pict_type == AV_PICTURE_TYPE_B) { + int b_code = get_bits(&s->gb, 3); + if(b_code==0){ + av_log(s->avctx, AV_LOG_ERROR, "Error, video packet header damaged (b_code=0)\n"); + } + } + } + } + //FIXME new-pred stuff + + return 0; +} + +/** + * Get the average motion vector for a GMC MB. + * @param n either 0 for the x component or 1 for y + * @return the average MV for a GMC MB + */ +static inline int get_amv(MpegEncContext *s, int n){ + int x, y, mb_v, sum, dx, dy, shift; + int len = 1 << (s->f_code + 4); + const int a= s->sprite_warping_accuracy; + + if(s->workaround_bugs & FF_BUG_AMV) + len >>= s->quarter_sample; + + if(s->real_sprite_warping_points==1){ + if(s->divx_version==500 && s->divx_build==413) + sum= s->sprite_offset[0][n] / (1<<(a - s->quarter_sample)); + else + sum= RSHIFT(s->sprite_offset[0][n]<quarter_sample, a); + }else{ + dx= s->sprite_delta[n][0]; + dy= s->sprite_delta[n][1]; + shift= s->sprite_shift[0]; + if(n) dy -= 1<<(shift + a + 1); + else dx -= 1<<(shift + a + 1); + mb_v= s->sprite_offset[0][n] + dx*s->mb_x*16 + dy*s->mb_y*16; + + sum=0; + for(y=0; y<16; y++){ + int v; + + v= mb_v + dy*y; + //XXX FIXME optimize + for(x=0; x<16; x++){ + sum+= v>>shift; + v+= dx; + } + } + sum= RSHIFT(sum, a+8-s->quarter_sample); + } + + if (sum < -len) sum= -len; + else if (sum >= len) sum= len-1; + + return sum; +} + +/** + * Decode the dc value. + * @param n block index (0-3 are luma, 4-5 are chroma) + * @param dir_ptr the prediction direction will be stored here + * @return the quantized dc + */ +static inline int mpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) +{ + int level, code; + + if (n < 4) + code = get_vlc2(&s->gb, dc_lum.table, DC_VLC_BITS, 1); + else + code = get_vlc2(&s->gb, dc_chrom.table, DC_VLC_BITS, 1); + if (code < 0 || code > 9 /* && s->nbit<9 */){ + av_log(s->avctx, AV_LOG_ERROR, "illegal dc vlc\n"); + return -1; + } + if (code == 0) { + level = 0; + } else { + if(IS_3IV1){ + if(code==1) + level= 2*get_bits1(&s->gb)-1; + else{ + if(get_bits1(&s->gb)) + level = get_bits(&s->gb, code-1) + (1<<(code-1)); + else + level = -get_bits(&s->gb, code-1) - (1<<(code-1)); + } + }else{ + level = get_xbits(&s->gb, code); + } + + if (code > 8){ + if(get_bits1(&s->gb)==0){ /* marker */ + if(s->err_recognition&(AV_EF_BITSTREAM|AV_EF_COMPLIANT)){ + av_log(s->avctx, AV_LOG_ERROR, "dc marker bit missing\n"); + return -1; + } + } + } + } + + return ff_mpeg4_pred_dc(s, n, level, dir_ptr, 0); +} + +/** + * Decode first partition. + * @return number of MBs decoded or <0 if an error occurred + */ +static int mpeg4_decode_partition_a(MpegEncContext *s){ + int mb_num; + static const int8_t quant_tab[4] = { -1, -2, 1, 2 }; + + /* decode first partition */ + mb_num=0; + s->first_slice_line=1; + for(; s->mb_ymb_height; s->mb_y++){ + ff_init_block_index(s); + for(; s->mb_xmb_width; s->mb_x++){ + const int xy= s->mb_x + s->mb_y*s->mb_stride; + int cbpc; + int dir=0; + + mb_num++; + ff_update_block_index(s); + if(s->mb_x == s->resync_mb_x && s->mb_y == s->resync_mb_y+1) + s->first_slice_line=0; + + if(s->pict_type==AV_PICTURE_TYPE_I){ + int i; + + do{ + if(show_bits_long(&s->gb, 19)==DC_MARKER){ + return mb_num-1; + } + + cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2); + if (cbpc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "cbpc corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + }while(cbpc == 8); + + s->cbp_table[xy]= cbpc & 3; + s->current_picture.mb_type[xy] = MB_TYPE_INTRA; + s->mb_intra = 1; + + if(cbpc & 4) { + ff_set_qscale(s, s->qscale + quant_tab[get_bits(&s->gb, 2)]); + } + s->current_picture.qscale_table[xy]= s->qscale; + + s->mbintra_table[xy]= 1; + for(i=0; i<6; i++){ + int dc_pred_dir; + int dc= mpeg4_decode_dc(s, i, &dc_pred_dir); + if(dc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "DC corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + dir<<=1; + if(dc_pred_dir) dir|=1; + } + s->pred_dir_table[xy]= dir; + }else{ /* P/S_TYPE */ + int mx, my, pred_x, pred_y, bits; + int16_t * const mot_val = s->current_picture.motion_val[0][s->block_index[0]]; + const int stride= s->b8_stride*2; + +try_again: + bits= show_bits(&s->gb, 17); + if(bits==MOTION_MARKER){ + return mb_num-1; + } + skip_bits1(&s->gb); + if(bits&0x10000){ + /* skip mb */ + if(s->pict_type==AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE){ + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_GMC | MB_TYPE_L0; + mx= get_amv(s, 0); + my= get_amv(s, 1); + }else{ + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + mx=my=0; + } + mot_val[0 ]= mot_val[2 ]= + mot_val[0+stride]= mot_val[2+stride]= mx; + mot_val[1 ]= mot_val[3 ]= + mot_val[1+stride]= mot_val[3+stride]= my; + + if(s->mbintra_table[xy]) + ff_clean_intra_table_entries(s); + continue; + } + + cbpc = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); + if (cbpc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "cbpc corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + if(cbpc == 20) + goto try_again; + + s->cbp_table[xy]= cbpc&(8+3); //8 is dquant + + s->mb_intra = ((cbpc & 4) != 0); + + if(s->mb_intra){ + s->current_picture.mb_type[xy] = MB_TYPE_INTRA; + s->mbintra_table[xy]= 1; + mot_val[0 ]= mot_val[2 ]= + mot_val[0+stride]= mot_val[2+stride]= 0; + mot_val[1 ]= mot_val[3 ]= + mot_val[1+stride]= mot_val[3+stride]= 0; + }else{ + if(s->mbintra_table[xy]) + ff_clean_intra_table_entries(s); + + if(s->pict_type==AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE && (cbpc & 16) == 0) + s->mcsel= get_bits1(&s->gb); + else s->mcsel= 0; + + if ((cbpc & 16) == 0) { + /* 16x16 motion prediction */ + + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + if(!s->mcsel){ + mx = ff_h263_decode_motion(s, pred_x, s->f_code); + if (mx >= 0xffff) + return -1; + + my = ff_h263_decode_motion(s, pred_y, s->f_code); + if (my >= 0xffff) + return -1; + s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_L0; + } else { + mx = get_amv(s, 0); + my = get_amv(s, 1); + s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_GMC | MB_TYPE_L0; + } + + mot_val[0 ]= mot_val[2 ] = + mot_val[0+stride]= mot_val[2+stride]= mx; + mot_val[1 ]= mot_val[3 ]= + mot_val[1+stride]= mot_val[3+stride]= my; + } else { + int i; + s->current_picture.mb_type[xy] = MB_TYPE_8x8 | MB_TYPE_L0; + for(i=0;i<4;i++) { + int16_t *mot_val= ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); + mx = ff_h263_decode_motion(s, pred_x, s->f_code); + if (mx >= 0xffff) + return -1; + + my = ff_h263_decode_motion(s, pred_y, s->f_code); + if (my >= 0xffff) + return -1; + mot_val[0] = mx; + mot_val[1] = my; + } + } + } + } + } + s->mb_x= 0; + } + + return mb_num; +} + +/** + * decode second partition. + * @return <0 if an error occurred + */ +static int mpeg4_decode_partition_b(MpegEncContext *s, int mb_count){ + int mb_num=0; + static const int8_t quant_tab[4] = { -1, -2, 1, 2 }; + + s->mb_x= s->resync_mb_x; + s->first_slice_line=1; + for(s->mb_y= s->resync_mb_y; mb_num < mb_count; s->mb_y++){ + ff_init_block_index(s); + for(; mb_num < mb_count && s->mb_xmb_width; s->mb_x++){ + const int xy= s->mb_x + s->mb_y*s->mb_stride; + + mb_num++; + ff_update_block_index(s); + if(s->mb_x == s->resync_mb_x && s->mb_y == s->resync_mb_y+1) + s->first_slice_line=0; + + if(s->pict_type==AV_PICTURE_TYPE_I){ + int ac_pred= get_bits1(&s->gb); + int cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + if(cbpy<0){ + av_log(s->avctx, AV_LOG_ERROR, "cbpy corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + s->cbp_table[xy]|= cbpy<<2; + s->current_picture.mb_type[xy] |= ac_pred*MB_TYPE_ACPRED; + }else{ /* P || S_TYPE */ + if (IS_INTRA(s->current_picture.mb_type[xy])) { + int dir=0,i; + int ac_pred = get_bits1(&s->gb); + int cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + + if(cbpy<0){ + av_log(s->avctx, AV_LOG_ERROR, "I cbpy corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + if(s->cbp_table[xy] & 8) { + ff_set_qscale(s, s->qscale + quant_tab[get_bits(&s->gb, 2)]); + } + s->current_picture.qscale_table[xy] = s->qscale; + + for(i=0; i<6; i++){ + int dc_pred_dir; + int dc= mpeg4_decode_dc(s, i, &dc_pred_dir); + if(dc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "DC corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + dir<<=1; + if(dc_pred_dir) dir|=1; + } + s->cbp_table[xy]&= 3; //remove dquant + s->cbp_table[xy]|= cbpy<<2; + s->current_picture.mb_type[xy] |= ac_pred*MB_TYPE_ACPRED; + s->pred_dir_table[xy]= dir; + } else if (IS_SKIP(s->current_picture.mb_type[xy])) { + s->current_picture.qscale_table[xy] = s->qscale; + s->cbp_table[xy]= 0; + }else{ + int cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + + if(cbpy<0){ + av_log(s->avctx, AV_LOG_ERROR, "P cbpy corrupted at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + if(s->cbp_table[xy] & 8) { + ff_set_qscale(s, s->qscale + quant_tab[get_bits(&s->gb, 2)]); + } + s->current_picture.qscale_table[xy] = s->qscale; + + s->cbp_table[xy]&= 3; //remove dquant + s->cbp_table[xy]|= (cbpy^0xf)<<2; + } + } + } + if(mb_num >= mb_count) return 0; + s->mb_x= 0; + } + return 0; +} + +/** + * Decode the first and second partition. + * @return <0 if error (and sets error type in the error_status_table) + */ +int ff_mpeg4_decode_partitions(MpegEncContext *s) +{ + int mb_num; + const int part_a_error= s->pict_type==AV_PICTURE_TYPE_I ? (ER_DC_ERROR|ER_MV_ERROR) : ER_MV_ERROR; + const int part_a_end = s->pict_type==AV_PICTURE_TYPE_I ? (ER_DC_END |ER_MV_END) : ER_MV_END; + + mb_num= mpeg4_decode_partition_a(s); + if(mb_num<0){ + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error); + return -1; + } + + if(s->resync_mb_x + s->resync_mb_y*s->mb_width + mb_num > s->mb_num){ + av_log(s->avctx, AV_LOG_ERROR, "slice below monitor ...\n"); + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, part_a_error); + return -1; + } + + s->mb_num_left= mb_num; + + if(s->pict_type==AV_PICTURE_TYPE_I){ + while(show_bits(&s->gb, 9) == 1) + skip_bits(&s->gb, 9); + if(get_bits_long(&s->gb, 19)!=DC_MARKER){ + av_log(s->avctx, AV_LOG_ERROR, "marker missing after first I partition at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + }else{ + while(show_bits(&s->gb, 10) == 1) + skip_bits(&s->gb, 10); + if(get_bits(&s->gb, 17)!=MOTION_MARKER){ + av_log(s->avctx, AV_LOG_ERROR, "marker missing after first P partition at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + } + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, part_a_end); + + if( mpeg4_decode_partition_b(s, mb_num) < 0){ + if(s->pict_type==AV_PICTURE_TYPE_P) + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_DC_ERROR); + return -1; + }else{ + if(s->pict_type==AV_PICTURE_TYPE_P) + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_DC_END); + } + + return 0; +} + +/** + * Decode a block. + * @return <0 if an error occurred + */ +static inline int mpeg4_decode_block(MpegEncContext * s, int16_t * block, + int n, int coded, int intra, int rvlc) +{ + int level, i, last, run; + int av_uninit(dc_pred_dir); + RLTable * rl; + RL_VLC_ELEM * rl_vlc; + const uint8_t * scan_table; + int qmul, qadd; + + //Note intra & rvlc should be optimized away if this is inlined + + if(intra) { + if(s->use_intra_dc_vlc){ + /* DC coef */ + if(s->partitioned_frame){ + level = s->dc_val[0][ s->block_index[n] ]; + if(n<4) level= FASTDIV((level + (s->y_dc_scale>>1)), s->y_dc_scale); + else level= FASTDIV((level + (s->c_dc_scale>>1)), s->c_dc_scale); + dc_pred_dir= (s->pred_dir_table[s->mb_x + s->mb_y*s->mb_stride]<ac_pred) { + if (dc_pred_dir == 0) + scan_table = s->intra_v_scantable.permutated; /* left */ + else + scan_table = s->intra_h_scantable.permutated; /* top */ + } else { + scan_table = s->intra_scantable.permutated; + } + qmul=1; + qadd=0; + } else { + i = -1; + if (!coded) { + s->block_last_index[n] = i; + return 0; + } + if(rvlc) rl = &ff_rvlc_rl_inter; + else rl = &ff_h263_rl_inter; + + scan_table = s->intra_scantable.permutated; + + if(s->mpeg_quant){ + qmul=1; + qadd=0; + if(rvlc){ + rl_vlc = ff_rvlc_rl_inter.rl_vlc[0]; + }else{ + rl_vlc = ff_h263_rl_inter.rl_vlc[0]; + } + }else{ + qmul = s->qscale << 1; + qadd = (s->qscale - 1) | 1; + if(rvlc){ + rl_vlc = ff_rvlc_rl_inter.rl_vlc[s->qscale]; + }else{ + rl_vlc = ff_h263_rl_inter.rl_vlc[s->qscale]; + } + } + } + { + OPEN_READER(re, &s->gb); + for(;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2, 0); + if (level==0) { + /* escape */ + if(rvlc){ + if(SHOW_UBITS(re, &s->gb, 1)==0){ + av_log(s->avctx, AV_LOG_ERROR, "1. marker bit missing in rvlc esc\n"); + return -1; + }; SKIP_CACHE(re, &s->gb, 1); + + last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); + run= SHOW_UBITS(re, &s->gb, 6); + SKIP_COUNTER(re, &s->gb, 1+1+6); + UPDATE_CACHE(re, &s->gb); + + if(SHOW_UBITS(re, &s->gb, 1)==0){ + av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in rvlc esc\n"); + return -1; + }; SKIP_CACHE(re, &s->gb, 1); + + level= SHOW_UBITS(re, &s->gb, 11); SKIP_CACHE(re, &s->gb, 11); + + if(SHOW_UBITS(re, &s->gb, 5)!=0x10){ + av_log(s->avctx, AV_LOG_ERROR, "reverse esc missing\n"); + return -1; + }; SKIP_CACHE(re, &s->gb, 5); + + level= level * qmul + qadd; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + SKIP_COUNTER(re, &s->gb, 1+11+5+1); + + i+= run + 1; + if(last) i+=192; + }else{ + int cache; + cache= GET_CACHE(re, &s->gb); + + if(IS_3IV1) + cache ^= 0xC0000000; + + if (cache&0x80000000) { + if (cache&0x40000000) { + /* third escape */ + SKIP_CACHE(re, &s->gb, 2); + last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); + run= SHOW_UBITS(re, &s->gb, 6); + SKIP_COUNTER(re, &s->gb, 2+1+6); + UPDATE_CACHE(re, &s->gb); + + if(IS_3IV1){ + level= SHOW_SBITS(re, &s->gb, 12); LAST_SKIP_BITS(re, &s->gb, 12); + }else{ + if(SHOW_UBITS(re, &s->gb, 1)==0){ + av_log(s->avctx, AV_LOG_ERROR, "1. marker bit missing in 3. esc\n"); + return -1; + }; SKIP_CACHE(re, &s->gb, 1); + + level= SHOW_SBITS(re, &s->gb, 12); SKIP_CACHE(re, &s->gb, 12); + + if(SHOW_UBITS(re, &s->gb, 1)==0){ + av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in 3. esc\n"); + return -1; + } + + SKIP_COUNTER(re, &s->gb, 1+12+1); + } + +#if 0 + if(s->error_recognition >= FF_ER_COMPLIANT){ + const int abs_level= FFABS(level); + if(abs_level<=MAX_LEVEL && run<=MAX_RUN){ + const int run1= run - rl->max_run[last][abs_level] - 1; + if(abs_level <= rl->max_level[last][run]){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, vlc encoding possible\n"); + return -1; + } + if(s->error_recognition > FF_ER_COMPLIANT){ + if(abs_level <= rl->max_level[last][run]*2){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 1 encoding possible\n"); + return -1; + } + if(run1 >= 0 && abs_level <= rl->max_level[last][run1]){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 2 encoding possible\n"); + return -1; + } + } + } + } +#endif + if (level>0) level= level * qmul + qadd; + else level= level * qmul - qadd; + + if((unsigned)(level + 2048) > 4095){ + if(s->err_recognition & (AV_EF_BITSTREAM|AV_EF_AGGRESSIVE)){ + if(level > 2560 || level<-2560){ + av_log(s->avctx, AV_LOG_ERROR, "|level| overflow in 3. esc, qp=%d\n", s->qscale); + return -1; + } + } + level= level<0 ? -2048 : 2047; + } + + i+= run + 1; + if(last) i+=192; + } else { + /* second escape */ + SKIP_BITS(re, &s->gb, 2); + GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2, 1); + i+= run + rl->max_run[run>>7][level/qmul] +1; //FIXME opt indexing + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } + } else { + /* first escape */ + SKIP_BITS(re, &s->gb, 1); + GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2, 1); + i+= run; + level = level + rl->max_level[run>>7][(run-1)&63] * qmul;//FIXME opt indexing + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } + } + } else { + i+= run; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); + } + if (i > 62){ + i-= 192; + if(i&(~63)){ + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + + block[scan_table[i]] = level; + break; + } + + block[scan_table[i]] = level; + } + CLOSE_READER(re, &s->gb); + } + not_coded: + if (intra) { + if(!s->use_intra_dc_vlc){ + block[0] = ff_mpeg4_pred_dc(s, n, block[0], &dc_pred_dir, 0); + + i -= i>>31; //if(i == -1) i=0; + } + + ff_mpeg4_pred_ac(s, block, n, dc_pred_dir); + if (s->ac_pred) { + i = 63; /* XXX: not optimal */ + } + } + s->block_last_index[n] = i; + return 0; +} + +/** + * decode partition C of one MB. + * @return <0 if an error occurred + */ +static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) +{ + int cbp, mb_type; + const int xy= s->mb_x + s->mb_y*s->mb_stride; + + mb_type = s->current_picture.mb_type[xy]; + cbp = s->cbp_table[xy]; + + s->use_intra_dc_vlc= s->qscale < s->intra_dc_threshold; + + if (s->current_picture.qscale_table[xy] != s->qscale) { + ff_set_qscale(s, s->current_picture.qscale_table[xy]); + } + + if (s->pict_type == AV_PICTURE_TYPE_P || s->pict_type==AV_PICTURE_TYPE_S) { + int i; + for(i=0; i<4; i++){ + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1]; + } + s->mb_intra = IS_INTRA(mb_type); + + if (IS_SKIP(mb_type)) { + /* skip mb */ + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + if(s->pict_type==AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE){ + s->mcsel=1; + s->mb_skipped = 0; + }else{ + s->mcsel=0; + s->mb_skipped = 1; + } + }else if(s->mb_intra){ + s->ac_pred = IS_ACPRED(s->current_picture.mb_type[xy]); + }else if(!s->mb_intra){ +// s->mcsel= 0; //FIXME do we need to init that + + s->mv_dir = MV_DIR_FORWARD; + if (IS_8X8(mb_type)) { + s->mv_type = MV_TYPE_8X8; + } else { + s->mv_type = MV_TYPE_16X16; + } + } + } else { /* I-Frame */ + s->mb_intra = 1; + s->ac_pred = IS_ACPRED(s->current_picture.mb_type[xy]); + } + + if (!IS_SKIP(mb_type)) { + int i; + s->dsp.clear_blocks(s->block[0]); + /* decode each block */ + for (i = 0; i < 6; i++) { + if(mpeg4_decode_block(s, block[i], i, cbp&32, s->mb_intra, s->rvlc) < 0){ + av_log(s->avctx, AV_LOG_ERROR, "texture corrupted at %d %d %d\n", s->mb_x, s->mb_y, s->mb_intra); + return -1; + } + cbp+=cbp; + } + } + + /* per-MB end of slice check */ + + if(--s->mb_num_left <= 0){ + if(mpeg4_is_resync(s)) + return SLICE_END; + else + return SLICE_NOEND; + }else{ + if(mpeg4_is_resync(s)){ + const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1; + if(s->cbp_table[xy+delta]) + return SLICE_END; + } + return SLICE_OK; + } +} + +static int mpeg4_decode_mb(MpegEncContext *s, + int16_t block[6][64]) +{ + int cbpc, cbpy, i, cbp, pred_x, pred_y, mx, my, dquant; + int16_t *mot_val; + static int8_t quant_tab[4] = { -1, -2, 1, 2 }; + const int xy= s->mb_x + s->mb_y * s->mb_stride; + + av_assert2(s->h263_pred); + + if (s->pict_type == AV_PICTURE_TYPE_P || s->pict_type==AV_PICTURE_TYPE_S) { + do{ + if (get_bits1(&s->gb)) { + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + if(s->pict_type==AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE){ + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_GMC | MB_TYPE_16x16 | MB_TYPE_L0; + s->mcsel=1; + s->mv[0][0][0]= get_amv(s, 0); + s->mv[0][0][1]= get_amv(s, 1); + + s->mb_skipped = 0; + }else{ + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + s->mcsel=0; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = 1; + } + goto end; + } + cbpc = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); + if (cbpc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "cbpc damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + }while(cbpc == 20); + + s->dsp.clear_blocks(s->block[0]); + dquant = cbpc & 8; + s->mb_intra = ((cbpc & 4) != 0); + if (s->mb_intra) goto intra; + + if(s->pict_type==AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE && (cbpc & 16) == 0) + s->mcsel= get_bits1(&s->gb); + else s->mcsel= 0; + cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1) ^ 0x0F; + + cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) { + ff_set_qscale(s, s->qscale + quant_tab[get_bits(&s->gb, 2)]); + } + if((!s->progressive_sequence) && (cbp || (s->workaround_bugs&FF_BUG_XVID_ILACE))) + s->interlaced_dct= get_bits1(&s->gb); + + s->mv_dir = MV_DIR_FORWARD; + if ((cbpc & 16) == 0) { + if(s->mcsel){ + s->current_picture.mb_type[xy] = MB_TYPE_GMC | MB_TYPE_16x16 | MB_TYPE_L0; + /* 16x16 global motion prediction */ + s->mv_type = MV_TYPE_16X16; + mx= get_amv(s, 0); + my= get_amv(s, 1); + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + }else if((!s->progressive_sequence) && get_bits1(&s->gb)){ + s->current_picture.mb_type[xy] = MB_TYPE_16x8 | MB_TYPE_L0 | MB_TYPE_INTERLACED; + /* 16x8 field motion prediction */ + s->mv_type= MV_TYPE_FIELD; + + s->field_select[0][0]= get_bits1(&s->gb); + s->field_select[0][1]= get_bits1(&s->gb); + + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + + for(i=0; i<2; i++){ + mx = ff_h263_decode_motion(s, pred_x, s->f_code); + if (mx >= 0xffff) + return -1; + + my = ff_h263_decode_motion(s, pred_y/2, s->f_code); + if (my >= 0xffff) + return -1; + + s->mv[0][i][0] = mx; + s->mv[0][i][1] = my; + } + }else{ + s->current_picture.mb_type[xy] = MB_TYPE_16x16 | MB_TYPE_L0; + /* 16x16 motion prediction */ + s->mv_type = MV_TYPE_16X16; + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + mx = ff_h263_decode_motion(s, pred_x, s->f_code); + + if (mx >= 0xffff) + return -1; + + my = ff_h263_decode_motion(s, pred_y, s->f_code); + + if (my >= 0xffff) + return -1; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + } + } else { + s->current_picture.mb_type[xy] = MB_TYPE_8x8 | MB_TYPE_L0; + s->mv_type = MV_TYPE_8X8; + for(i=0;i<4;i++) { + mot_val = ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); + mx = ff_h263_decode_motion(s, pred_x, s->f_code); + if (mx >= 0xffff) + return -1; + + my = ff_h263_decode_motion(s, pred_y, s->f_code); + if (my >= 0xffff) + return -1; + s->mv[0][i][0] = mx; + s->mv[0][i][1] = my; + mot_val[0] = mx; + mot_val[1] = my; + } + } + } else if(s->pict_type==AV_PICTURE_TYPE_B) { + int modb1; // first bit of modb + int modb2; // second bit of modb + int mb_type; + + s->mb_intra = 0; //B-frames never contain intra blocks + s->mcsel=0; // ... true gmc blocks + + if(s->mb_x==0){ + for(i=0; i<2; i++){ + s->last_mv[i][0][0]= + s->last_mv[i][0][1]= + s->last_mv[i][1][0]= + s->last_mv[i][1][1]= 0; + } + + ff_thread_await_progress(&s->next_picture_ptr->tf, s->mb_y, 0); + } + + /* if we skipped it in the future P Frame than skip it now too */ + s->mb_skipped = s->next_picture.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]; // Note, skiptab=0 if last was GMC + + if(s->mb_skipped){ + /* skip mb */ + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mv[1][0][0] = 0; + s->mv[1][0][1] = 0; + s->current_picture.mb_type[xy] = MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + goto end; + } + + modb1= get_bits1(&s->gb); + if(modb1){ + mb_type= MB_TYPE_DIRECT2 | MB_TYPE_SKIP | MB_TYPE_L0L1; //like MB_TYPE_B_DIRECT but no vectors coded + cbp=0; + }else{ + modb2= get_bits1(&s->gb); + mb_type= get_vlc2(&s->gb, mb_type_b_vlc.table, MB_TYPE_B_VLC_BITS, 1); + if(mb_type<0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal MB_type\n"); + return -1; + } + mb_type= mb_type_b_map[ mb_type ]; + if(modb2) cbp= 0; + else{ + s->dsp.clear_blocks(s->block[0]); + cbp= get_bits(&s->gb, 6); + } + + if ((!IS_DIRECT(mb_type)) && cbp) { + if(get_bits1(&s->gb)){ + ff_set_qscale(s, s->qscale + get_bits1(&s->gb)*4 - 2); + } + } + + if(!s->progressive_sequence){ + if(cbp) + s->interlaced_dct= get_bits1(&s->gb); + + if(!IS_DIRECT(mb_type) && get_bits1(&s->gb)){ + mb_type |= MB_TYPE_16x8 | MB_TYPE_INTERLACED; + mb_type &= ~MB_TYPE_16x16; + + if(USES_LIST(mb_type, 0)){ + s->field_select[0][0]= get_bits1(&s->gb); + s->field_select[0][1]= get_bits1(&s->gb); + } + if(USES_LIST(mb_type, 1)){ + s->field_select[1][0]= get_bits1(&s->gb); + s->field_select[1][1]= get_bits1(&s->gb); + } + } + } + + s->mv_dir = 0; + if((mb_type & (MB_TYPE_DIRECT2|MB_TYPE_INTERLACED)) == 0){ + s->mv_type= MV_TYPE_16X16; + + if(USES_LIST(mb_type, 0)){ + s->mv_dir = MV_DIR_FORWARD; + + mx = ff_h263_decode_motion(s, s->last_mv[0][0][0], s->f_code); + my = ff_h263_decode_motion(s, s->last_mv[0][0][1], s->f_code); + s->last_mv[0][1][0]= s->last_mv[0][0][0]= s->mv[0][0][0] = mx; + s->last_mv[0][1][1]= s->last_mv[0][0][1]= s->mv[0][0][1] = my; + } + + if(USES_LIST(mb_type, 1)){ + s->mv_dir |= MV_DIR_BACKWARD; + + mx = ff_h263_decode_motion(s, s->last_mv[1][0][0], s->b_code); + my = ff_h263_decode_motion(s, s->last_mv[1][0][1], s->b_code); + s->last_mv[1][1][0]= s->last_mv[1][0][0]= s->mv[1][0][0] = mx; + s->last_mv[1][1][1]= s->last_mv[1][0][1]= s->mv[1][0][1] = my; + } + }else if(!IS_DIRECT(mb_type)){ + s->mv_type= MV_TYPE_FIELD; + + if(USES_LIST(mb_type, 0)){ + s->mv_dir = MV_DIR_FORWARD; + + for(i=0; i<2; i++){ + mx = ff_h263_decode_motion(s, s->last_mv[0][i][0] , s->f_code); + my = ff_h263_decode_motion(s, s->last_mv[0][i][1]/2, s->f_code); + s->last_mv[0][i][0]= s->mv[0][i][0] = mx; + s->last_mv[0][i][1]= (s->mv[0][i][1] = my)*2; + } + } + + if(USES_LIST(mb_type, 1)){ + s->mv_dir |= MV_DIR_BACKWARD; + + for(i=0; i<2; i++){ + mx = ff_h263_decode_motion(s, s->last_mv[1][i][0] , s->b_code); + my = ff_h263_decode_motion(s, s->last_mv[1][i][1]/2, s->b_code); + s->last_mv[1][i][0]= s->mv[1][i][0] = mx; + s->last_mv[1][i][1]= (s->mv[1][i][1] = my)*2; + } + } + } + } + + if(IS_DIRECT(mb_type)){ + if(IS_SKIP(mb_type)) + mx=my=0; + else{ + mx = ff_h263_decode_motion(s, 0, 1); + my = ff_h263_decode_motion(s, 0, 1); + } + + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; + mb_type |= ff_mpeg4_set_direct_mv(s, mx, my); + } + s->current_picture.mb_type[xy] = mb_type; + } else { /* I-Frame */ + do{ + cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2); + if (cbpc < 0){ + av_log(s->avctx, AV_LOG_ERROR, "I cbpc damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + }while(cbpc == 8); + + dquant = cbpc & 4; + s->mb_intra = 1; +intra: + s->ac_pred = get_bits1(&s->gb); + if(s->ac_pred) + s->current_picture.mb_type[xy] = MB_TYPE_INTRA | MB_TYPE_ACPRED; + else + s->current_picture.mb_type[xy] = MB_TYPE_INTRA; + + cbpy = get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + if(cbpy<0){ + av_log(s->avctx, AV_LOG_ERROR, "I cbpy damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + cbp = (cbpc & 3) | (cbpy << 2); + + s->use_intra_dc_vlc= s->qscale < s->intra_dc_threshold; + + if (dquant) { + ff_set_qscale(s, s->qscale + quant_tab[get_bits(&s->gb, 2)]); + } + + if(!s->progressive_sequence) + s->interlaced_dct= get_bits1(&s->gb); + + s->dsp.clear_blocks(s->block[0]); + /* decode each block */ + for (i = 0; i < 6; i++) { + if (mpeg4_decode_block(s, block[i], i, cbp&32, 1, 0) < 0) + return -1; + cbp+=cbp; + } + goto end; + } + + /* decode each block */ + for (i = 0; i < 6; i++) { + if (mpeg4_decode_block(s, block[i], i, cbp&32, 0, 0) < 0) + return -1; + cbp+=cbp; + } +end: + + /* per-MB end of slice check */ + if(s->codec_id==AV_CODEC_ID_MPEG4){ + int next= mpeg4_is_resync(s); + if(next) { + if (s->mb_x + s->mb_y*s->mb_width + 1 > next && (s->avctx->err_recognition & AV_EF_AGGRESSIVE)) { + return -1; + } else if (s->mb_x + s->mb_y*s->mb_width + 1 >= next) + return SLICE_END; + + if(s->pict_type==AV_PICTURE_TYPE_B){ + const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1; + ff_thread_await_progress(&s->next_picture_ptr->tf, + (s->mb_x + delta >= s->mb_width) ? FFMIN(s->mb_y+1, s->mb_height-1) : s->mb_y, 0); + if (s->next_picture.mbskip_table[xy + delta]) + return SLICE_OK; + } + + return SLICE_END; + } + } + + return SLICE_OK; +} + + +static int mpeg4_decode_gop_header(MpegEncContext * s, GetBitContext *gb){ + int hours, minutes, seconds; + + if(!show_bits(gb, 23)){ + av_log(s->avctx, AV_LOG_WARNING, "GOP header invalid\n"); + return -1; + } + + hours= get_bits(gb, 5); + minutes= get_bits(gb, 6); + skip_bits1(gb); + seconds= get_bits(gb, 6); + + s->time_base= seconds + 60*(minutes + 60*hours); + + skip_bits1(gb); + skip_bits1(gb); + + return 0; +} + +static int mpeg4_decode_profile_level(MpegEncContext * s, GetBitContext *gb){ + + s->avctx->profile = get_bits(gb, 4); + s->avctx->level = get_bits(gb, 4); + + // for Simple profile, level 0 + if (s->avctx->profile == 0 && s->avctx->level == 8) { + s->avctx->level = 0; + } + + return 0; +} + +static int decode_vol_header(MpegEncContext *s, GetBitContext *gb){ + int width, height, vo_ver_id; + + /* vol header */ + skip_bits(gb, 1); /* random access */ + s->vo_type= get_bits(gb, 8); + if (get_bits1(gb) != 0) { /* is_ol_id */ + vo_ver_id = get_bits(gb, 4); /* vo_ver_id */ + skip_bits(gb, 3); /* vo_priority */ + } else { + vo_ver_id = 1; + } + s->aspect_ratio_info= get_bits(gb, 4); + if(s->aspect_ratio_info == FF_ASPECT_EXTENDED){ + s->avctx->sample_aspect_ratio.num= get_bits(gb, 8); // par_width + s->avctx->sample_aspect_ratio.den= get_bits(gb, 8); // par_height + }else{ + s->avctx->sample_aspect_ratio= ff_h263_pixel_aspect[s->aspect_ratio_info]; + } + + if ((s->vol_control_parameters=get_bits1(gb))) { /* vol control parameter */ + int chroma_format= get_bits(gb, 2); + if(chroma_format!=CHROMA_420){ + av_log(s->avctx, AV_LOG_ERROR, "illegal chroma format\n"); + } + s->low_delay= get_bits1(gb); + if(get_bits1(gb)){ /* vbv parameters */ + get_bits(gb, 15); /* first_half_bitrate */ + skip_bits1(gb); /* marker */ + get_bits(gb, 15); /* latter_half_bitrate */ + skip_bits1(gb); /* marker */ + get_bits(gb, 15); /* first_half_vbv_buffer_size */ + skip_bits1(gb); /* marker */ + get_bits(gb, 3); /* latter_half_vbv_buffer_size */ + get_bits(gb, 11); /* first_half_vbv_occupancy */ + skip_bits1(gb); /* marker */ + get_bits(gb, 15); /* latter_half_vbv_occupancy */ + skip_bits1(gb); /* marker */ + } + }else{ + // set low delay flag only once the smartest? low delay detection won't be overridden + if(s->picture_number==0) + s->low_delay=0; + } + + s->shape = get_bits(gb, 2); /* vol shape */ + if(s->shape != RECT_SHAPE) av_log(s->avctx, AV_LOG_ERROR, "only rectangular vol supported\n"); + if(s->shape == GRAY_SHAPE && vo_ver_id != 1){ + av_log(s->avctx, AV_LOG_ERROR, "Gray shape not supported\n"); + skip_bits(gb, 4); //video_object_layer_shape_extension + } + + check_marker(gb, "before time_increment_resolution"); + + s->avctx->time_base.den = get_bits(gb, 16); + if(!s->avctx->time_base.den){ + av_log(s->avctx, AV_LOG_ERROR, "time_base.den==0\n"); + s->avctx->time_base.num = 0; + return -1; + } + + s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1; + if (s->time_increment_bits < 1) + s->time_increment_bits = 1; + + check_marker(gb, "before fixed_vop_rate"); + + if (get_bits1(gb) != 0) { /* fixed_vop_rate */ + s->avctx->time_base.num = get_bits(gb, s->time_increment_bits); + }else + s->avctx->time_base.num = 1; + + s->t_frame=0; + + if (s->shape != BIN_ONLY_SHAPE) { + if (s->shape == RECT_SHAPE) { + skip_bits1(gb); /* marker */ + width = get_bits(gb, 13); + skip_bits1(gb); /* marker */ + height = get_bits(gb, 13); + skip_bits1(gb); /* marker */ + if(width && height && !(s->width && s->codec_tag == AV_RL32("MP4S"))){ /* they should be non zero but who knows ... */ + if (s->width && s->height && + (s->width != width || s->height != height)) + s->context_reinit = 1; + s->width = width; + s->height = height; + } + } + + s->progressive_sequence= + s->progressive_frame= get_bits1(gb)^1; + s->interlaced_dct=0; + if(!get_bits1(gb) && (s->avctx->debug & FF_DEBUG_PICT_INFO)) + av_log(s->avctx, AV_LOG_INFO, "MPEG4 OBMC not supported (very likely buggy encoder)\n"); /* OBMC Disable */ + if (vo_ver_id == 1) { + s->vol_sprite_usage = get_bits1(gb); /* vol_sprite_usage */ + } else { + s->vol_sprite_usage = get_bits(gb, 2); /* vol_sprite_usage */ + } + if(s->vol_sprite_usage==STATIC_SPRITE) av_log(s->avctx, AV_LOG_ERROR, "Static Sprites not supported\n"); + if(s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE){ + if(s->vol_sprite_usage==STATIC_SPRITE){ + s->sprite_width = get_bits(gb, 13); + skip_bits1(gb); /* marker */ + s->sprite_height= get_bits(gb, 13); + skip_bits1(gb); /* marker */ + s->sprite_left = get_bits(gb, 13); + skip_bits1(gb); /* marker */ + s->sprite_top = get_bits(gb, 13); + skip_bits1(gb); /* marker */ + } + s->num_sprite_warping_points= get_bits(gb, 6); + if(s->num_sprite_warping_points > 3){ + av_log(s->avctx, AV_LOG_ERROR, "%d sprite_warping_points\n", s->num_sprite_warping_points); + s->num_sprite_warping_points= 0; + return -1; + } + s->sprite_warping_accuracy = get_bits(gb, 2); + s->sprite_brightness_change= get_bits1(gb); + if(s->vol_sprite_usage==STATIC_SPRITE) + s->low_latency_sprite= get_bits1(gb); + } + // FIXME sadct disable bit if verid!=1 && shape not rect + + if (get_bits1(gb) == 1) { /* not_8_bit */ + s->quant_precision = get_bits(gb, 4); /* quant_precision */ + if(get_bits(gb, 4)!=8) av_log(s->avctx, AV_LOG_ERROR, "N-bit not supported\n"); /* bits_per_pixel */ + if(s->quant_precision!=5) av_log(s->avctx, AV_LOG_ERROR, "quant precision %d\n", s->quant_precision); + if(s->quant_precision<3 || s->quant_precision>9) { + s->quant_precision = 5; + } + } else { + s->quant_precision = 5; + } + + // FIXME a bunch of grayscale shape things + + if((s->mpeg_quant=get_bits1(gb))){ /* vol_quant_type */ + int i, v; + + /* load default matrixes */ + for(i=0; i<64; i++){ + int j= s->dsp.idct_permutation[i]; + v= ff_mpeg4_default_intra_matrix[i]; + s->intra_matrix[j]= v; + s->chroma_intra_matrix[j]= v; + + v= ff_mpeg4_default_non_intra_matrix[i]; + s->inter_matrix[j]= v; + s->chroma_inter_matrix[j]= v; + } + + /* load custom intra matrix */ + if(get_bits1(gb)){ + int last=0; + for(i=0; i<64; i++){ + int j; + v= get_bits(gb, 8); + if(v==0) break; + + last= v; + j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; + s->intra_matrix[j]= v; + s->chroma_intra_matrix[j]= v; + } + + /* replicate last value */ + for(; i<64; i++){ + int j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; + s->intra_matrix[j]= last; + s->chroma_intra_matrix[j]= last; + } + } + + /* load custom non intra matrix */ + if(get_bits1(gb)){ + int last=0; + for(i=0; i<64; i++){ + int j; + v= get_bits(gb, 8); + if(v==0) break; + + last= v; + j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; + s->inter_matrix[j]= v; + s->chroma_inter_matrix[j]= v; + } + + /* replicate last value */ + for(; i<64; i++){ + int j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; + s->inter_matrix[j]= last; + s->chroma_inter_matrix[j]= last; + } + } + + // FIXME a bunch of grayscale shape things + } + + if(vo_ver_id != 1) + s->quarter_sample= get_bits1(gb); + else s->quarter_sample=0; + + if(!get_bits1(gb)){ + int pos= get_bits_count(gb); + int estimation_method= get_bits(gb, 2); + if(estimation_method<2){ + if(!get_bits1(gb)){ + s->cplx_estimation_trash_i += 8*get_bits1(gb); //opaque + s->cplx_estimation_trash_i += 8*get_bits1(gb); //transparent + s->cplx_estimation_trash_i += 8*get_bits1(gb); //intra_cae + s->cplx_estimation_trash_i += 8*get_bits1(gb); //inter_cae + s->cplx_estimation_trash_i += 8*get_bits1(gb); //no_update + s->cplx_estimation_trash_i += 8*get_bits1(gb); //upampling + } + if(!get_bits1(gb)){ + s->cplx_estimation_trash_i += 8*get_bits1(gb); //intra_blocks + s->cplx_estimation_trash_p += 8*get_bits1(gb); //inter_blocks + s->cplx_estimation_trash_p += 8*get_bits1(gb); //inter4v_blocks + s->cplx_estimation_trash_i += 8*get_bits1(gb); //not coded blocks + } + if(!check_marker(gb, "in complexity estimation part 1")){ + skip_bits_long(gb, pos - get_bits_count(gb)); + goto no_cplx_est; + } + if(!get_bits1(gb)){ + s->cplx_estimation_trash_i += 8*get_bits1(gb); //dct_coeffs + s->cplx_estimation_trash_i += 8*get_bits1(gb); //dct_lines + s->cplx_estimation_trash_i += 8*get_bits1(gb); //vlc_syms + s->cplx_estimation_trash_i += 4*get_bits1(gb); //vlc_bits + } + if(!get_bits1(gb)){ + s->cplx_estimation_trash_p += 8*get_bits1(gb); //apm + s->cplx_estimation_trash_p += 8*get_bits1(gb); //npm + s->cplx_estimation_trash_b += 8*get_bits1(gb); //interpolate_mc_q + s->cplx_estimation_trash_p += 8*get_bits1(gb); //forwback_mc_q + s->cplx_estimation_trash_p += 8*get_bits1(gb); //halfpel2 + s->cplx_estimation_trash_p += 8*get_bits1(gb); //halfpel4 + } + if(!check_marker(gb, "in complexity estimation part 2")){ + skip_bits_long(gb, pos - get_bits_count(gb)); + goto no_cplx_est; + } + if(estimation_method==1){ + s->cplx_estimation_trash_i += 8*get_bits1(gb); //sadct + s->cplx_estimation_trash_p += 8*get_bits1(gb); //qpel + } + }else + av_log(s->avctx, AV_LOG_ERROR, "Invalid Complexity estimation method %d\n", estimation_method); + }else{ +no_cplx_est: + s->cplx_estimation_trash_i= + s->cplx_estimation_trash_p= + s->cplx_estimation_trash_b= 0; + } + + s->resync_marker= !get_bits1(gb); /* resync_marker_disabled */ + + s->data_partitioning= get_bits1(gb); + if(s->data_partitioning){ + s->rvlc= get_bits1(gb); + } + + if(vo_ver_id != 1) { + s->new_pred= get_bits1(gb); + if(s->new_pred){ + av_log(s->avctx, AV_LOG_ERROR, "new pred not supported\n"); + skip_bits(gb, 2); /* requested upstream message type */ + skip_bits1(gb); /* newpred segment type */ + } + s->reduced_res_vop= get_bits1(gb); + if(s->reduced_res_vop) av_log(s->avctx, AV_LOG_ERROR, "reduced resolution VOP not supported\n"); + } + else{ + s->new_pred=0; + s->reduced_res_vop= 0; + } + + s->scalability= get_bits1(gb); + + if (s->scalability) { + GetBitContext bak= *gb; + int h_sampling_factor_n; + int h_sampling_factor_m; + int v_sampling_factor_n; + int v_sampling_factor_m; + + s->hierachy_type= get_bits1(gb); + skip_bits(gb, 4); /* ref_layer_id */ + skip_bits1(gb); /* ref_layer_sampling_dir */ + h_sampling_factor_n= get_bits(gb, 5); + h_sampling_factor_m= get_bits(gb, 5); + v_sampling_factor_n= get_bits(gb, 5); + v_sampling_factor_m= get_bits(gb, 5); + s->enhancement_type= get_bits1(gb); + + if( h_sampling_factor_n==0 || h_sampling_factor_m==0 + || v_sampling_factor_n==0 || v_sampling_factor_m==0){ + /* illegal scalability header (VERY broken encoder), + * trying to workaround */ + s->scalability=0; + *gb= bak; + }else + av_log(s->avctx, AV_LOG_ERROR, "scalability not supported\n"); + + // bin shape stuff FIXME + } + } + + if(s->avctx->debug&FF_DEBUG_PICT_INFO) { + av_log(s->avctx, AV_LOG_DEBUG, "tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d, %s%s%s%s\n", + s->avctx->time_base.num, s->avctx->time_base.den, + s->time_increment_bits, + s->quant_precision, + s->progressive_sequence, + s->scalability ? "scalability " :"" , s->quarter_sample ? "qpel " : "", + s->data_partitioning ? "partition " : "", s->rvlc ? "rvlc " : "" + ); + } + + return 0; +} + +/** + * Decode the user data stuff in the header. + * Also initializes divx/xvid/lavc_version/build. + */ +static int decode_user_data(MpegEncContext *s, GetBitContext *gb){ + char buf[256]; + int i; + int e; + int ver = 0, build = 0, ver2 = 0, ver3 = 0; + char last; + + for(i=0; i<255 && get_bits_count(gb) < gb->size_in_bits; i++){ + if(show_bits(gb, 23) == 0) break; + buf[i]= get_bits(gb, 8); + } + buf[i]=0; + + /* divx detection */ + e=sscanf(buf, "DivX%dBuild%d%c", &ver, &build, &last); + if(e<2) + e=sscanf(buf, "DivX%db%d%c", &ver, &build, &last); + if(e>=2){ + s->divx_version= ver; + s->divx_build= build; + s->divx_packed= e==3 && last=='p'; + if(s->divx_packed && !s->showed_packed_warning) { + av_log(s->avctx, AV_LOG_WARNING, "Invalid and inefficient vfw-avi packed B frames detected\n"); + s->showed_packed_warning=1; + } + } + + /* libavcodec detection */ + e=sscanf(buf, "FFmpe%*[^b]b%d", &build)+3; + if(e!=4) + e=sscanf(buf, "FFmpeg v%d.%d.%d / libavcodec build: %d", &ver, &ver2, &ver3, &build); + if(e!=4){ + e=sscanf(buf, "Lavc%d.%d.%d", &ver, &ver2, &ver3)+1; + if (e>1) + build= (ver<<16) + (ver2<<8) + ver3; + } + if(e!=4){ + if(strcmp(buf, "ffmpeg")==0){ + s->lavc_build= 4600; + } + } + if(e==4){ + s->lavc_build= build; + } + + /* Xvid detection */ + e=sscanf(buf, "XviD%d", &build); + if(e==1){ + s->xvid_build= build; + } + + return 0; +} + +static int decode_vop_header(MpegEncContext *s, GetBitContext *gb){ + int time_incr, time_increment; + + s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* pict type: I = 0 , P = 1 */ + if(s->pict_type==AV_PICTURE_TYPE_B && s->low_delay && s->vol_control_parameters==0 && !(s->flags & CODEC_FLAG_LOW_DELAY)){ + av_log(s->avctx, AV_LOG_ERROR, "low_delay flag incorrectly, clearing it\n"); + s->low_delay=0; + } + + s->partitioned_frame= s->data_partitioning && s->pict_type!=AV_PICTURE_TYPE_B; + if(s->partitioned_frame) + s->decode_mb= mpeg4_decode_partitioned_mb; + else + s->decode_mb= mpeg4_decode_mb; + + time_incr=0; + while (get_bits1(gb) != 0) + time_incr++; + + check_marker(gb, "before time_increment"); + + if(s->time_increment_bits==0 || !(show_bits(gb, s->time_increment_bits+1)&1)){ + av_log(s->avctx, AV_LOG_ERROR, "hmm, seems the headers are not complete, trying to guess time_increment_bits\n"); + + for(s->time_increment_bits=1 ;s->time_increment_bits<16; s->time_increment_bits++){ + if ( s->pict_type == AV_PICTURE_TYPE_P + || (s->pict_type == AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE)) { + if((show_bits(gb, s->time_increment_bits+6)&0x37) == 0x30) break; + }else + if((show_bits(gb, s->time_increment_bits+5)&0x1F) == 0x18) break; + } + + av_log(s->avctx, AV_LOG_ERROR, "my guess is %d bits ;)\n",s->time_increment_bits); + if (s->avctx->time_base.den && 4*s->avctx->time_base.den < 1<time_increment_bits) { + s->avctx->time_base.den = 1<time_increment_bits; + } + } + + if(IS_3IV1) time_increment= get_bits1(gb); //FIXME investigate further + else time_increment= get_bits(gb, s->time_increment_bits); + + if(s->pict_type!=AV_PICTURE_TYPE_B){ + s->last_time_base= s->time_base; + s->time_base+= time_incr; + s->time= s->time_base*s->avctx->time_base.den + time_increment; + if(s->workaround_bugs&FF_BUG_UMP4){ + if(s->time < s->last_non_b_time){ + /* header is not mpeg-4-compatible, broken encoder, + * trying to workaround */ + s->time_base++; + s->time+= s->avctx->time_base.den; + } + } + s->pp_time= s->time - s->last_non_b_time; + s->last_non_b_time= s->time; + }else{ + s->time= (s->last_time_base + time_incr)*s->avctx->time_base.den + time_increment; + s->pb_time= s->pp_time - (s->last_non_b_time - s->time); + if(s->pp_time <=s->pb_time || s->pp_time <= s->pp_time - s->pb_time || s->pp_time<=0){ + /* messed up order, maybe after seeking? skipping current b-frame */ + return FRAME_SKIPPED; + } + ff_mpeg4_init_direct_mv(s); + + if(s->t_frame==0) s->t_frame= s->pb_time; + if(s->t_frame==0) s->t_frame=1; // 1/0 protection + s->pp_field_time= ( ROUNDED_DIV(s->last_non_b_time, s->t_frame) + - ROUNDED_DIV(s->last_non_b_time - s->pp_time, s->t_frame))*2; + s->pb_field_time= ( ROUNDED_DIV(s->time, s->t_frame) + - ROUNDED_DIV(s->last_non_b_time - s->pp_time, s->t_frame))*2; + if(!s->progressive_sequence){ + if(s->pp_field_time <= s->pb_field_time || s->pb_field_time <= 1) + return FRAME_SKIPPED; + } + } + + if(s->avctx->time_base.num) + s->current_picture_ptr->f.pts = ROUNDED_DIV(s->time, s->avctx->time_base.num); + else + s->current_picture_ptr->f.pts = AV_NOPTS_VALUE; + if(s->avctx->debug&FF_DEBUG_PTS) + av_log(s->avctx, AV_LOG_DEBUG, "MPEG4 PTS: %"PRId64"\n", + s->current_picture_ptr->f.pts); + + check_marker(gb, "before vop_coded"); + + /* vop coded */ + if (get_bits1(gb) != 1){ + if(s->avctx->debug&FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_ERROR, "vop not coded\n"); + return FRAME_SKIPPED; + } + if (s->shape != BIN_ONLY_SHAPE && ( s->pict_type == AV_PICTURE_TYPE_P + || (s->pict_type == AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE))) { + /* rounding type for motion estimation */ + s->no_rounding = get_bits1(gb); + } else { + s->no_rounding = 0; + } +//FIXME reduced res stuff + + if (s->shape != RECT_SHAPE) { + if (s->vol_sprite_usage != 1 || s->pict_type != AV_PICTURE_TYPE_I) { + skip_bits(gb, 13); /* width */ + skip_bits1(gb); /* marker */ + skip_bits(gb, 13); /* height */ + skip_bits1(gb); /* marker */ + skip_bits(gb, 13); /* hor_spat_ref */ + skip_bits1(gb); /* marker */ + skip_bits(gb, 13); /* ver_spat_ref */ + } + skip_bits1(gb); /* change_CR_disable */ + + if (get_bits1(gb) != 0) { + skip_bits(gb, 8); /* constant_alpha_value */ + } + } +//FIXME complexity estimation stuff + + if (s->shape != BIN_ONLY_SHAPE) { + skip_bits_long(gb, s->cplx_estimation_trash_i); + if(s->pict_type != AV_PICTURE_TYPE_I) + skip_bits_long(gb, s->cplx_estimation_trash_p); + if(s->pict_type == AV_PICTURE_TYPE_B) + skip_bits_long(gb, s->cplx_estimation_trash_b); + + if(get_bits_left(gb) < 3) { + av_log(s->avctx, AV_LOG_ERROR, "Header truncated\n"); + return -1; + } + s->intra_dc_threshold= ff_mpeg4_dc_threshold[ get_bits(gb, 3) ]; + if(!s->progressive_sequence){ + s->top_field_first= get_bits1(gb); + s->alternate_scan= get_bits1(gb); + }else + s->alternate_scan= 0; + } + + if(s->alternate_scan){ + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_alternate_vertical_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_alternate_vertical_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_vertical_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + } else{ + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_zigzag_direct); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_zigzag_direct); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + } + + if(s->pict_type == AV_PICTURE_TYPE_S && (s->vol_sprite_usage==STATIC_SPRITE || s->vol_sprite_usage==GMC_SPRITE)){ + if(mpeg4_decode_sprite_trajectory(s, gb) < 0) + return -1; + if(s->sprite_brightness_change) av_log(s->avctx, AV_LOG_ERROR, "sprite_brightness_change not supported\n"); + if(s->vol_sprite_usage==STATIC_SPRITE) av_log(s->avctx, AV_LOG_ERROR, "static sprite not supported\n"); + } + + if (s->shape != BIN_ONLY_SHAPE) { + s->chroma_qscale= s->qscale = get_bits(gb, s->quant_precision); + if(s->qscale==0){ + av_log(s->avctx, AV_LOG_ERROR, "Error, header damaged or not MPEG4 header (qscale=0)\n"); + return -1; // makes no sense to continue, as there is nothing left from the image then + } + + if (s->pict_type != AV_PICTURE_TYPE_I) { + s->f_code = get_bits(gb, 3); /* fcode_for */ + if(s->f_code==0){ + av_log(s->avctx, AV_LOG_ERROR, "Error, header damaged or not MPEG4 header (f_code=0)\n"); + s->f_code=1; + return -1; // makes no sense to continue, as the MV decoding will break very quickly + } + }else + s->f_code=1; + + if (s->pict_type == AV_PICTURE_TYPE_B) { + s->b_code = get_bits(gb, 3); + if(s->b_code==0){ + av_log(s->avctx, AV_LOG_ERROR, "Error, header damaged or not MPEG4 header (b_code=0)\n"); + s->b_code=1; + return -1; // makes no sense to continue, as the MV decoding will break very quickly + } + }else + s->b_code=1; + + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n", + s->qscale, s->f_code, s->b_code, + s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + gb->size_in_bits,s->progressive_sequence, s->alternate_scan, s->top_field_first, + s->quarter_sample ? "q" : "h", s->data_partitioning, s->resync_marker, s->num_sprite_warping_points, + s->sprite_warping_accuracy, 1-s->no_rounding, s->vo_type, s->vol_control_parameters ? " VOLC" : " ", s->intra_dc_threshold, + s->cplx_estimation_trash_i, s->cplx_estimation_trash_p, s->cplx_estimation_trash_b, + s->time, + time_increment + ); + } + + if(!s->scalability){ + if (s->shape!=RECT_SHAPE && s->pict_type!=AV_PICTURE_TYPE_I) { + skip_bits1(gb); // vop shape coding type + } + }else{ + if(s->enhancement_type){ + int load_backward_shape= get_bits1(gb); + if(load_backward_shape){ + av_log(s->avctx, AV_LOG_ERROR, "load backward shape isn't supported\n"); + } + } + skip_bits(gb, 2); //ref_select_code + } + } + /* detect buggy encoders which don't set the low_delay flag (divx4/xvid/opendivx)*/ + // note we cannot detect divx5 without b-frames easily (although it's buggy too) + if(s->vo_type==0 && s->vol_control_parameters==0 && s->divx_version==-1 && s->picture_number==0){ + av_log(s->avctx, AV_LOG_WARNING, "looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag\n"); + s->low_delay=1; + } + + s->picture_number++; // better than pic number==0 always ;) + + s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; //FIXME add short header support + s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table; + + if(s->workaround_bugs&FF_BUG_EDGE){ + s->h_edge_pos= s->width; + s->v_edge_pos= s->height; + } + return 0; +} + +/** + * Decode mpeg4 headers. + * @return <0 if no VOP found (or a damaged one) + * FRAME_SKIPPED if a not coded VOP is found + * 0 if a VOP is found + */ +int ff_mpeg4_decode_picture_header(MpegEncContext * s, GetBitContext *gb) +{ + unsigned startcode, v; + + /* search next start code */ + align_get_bits(gb); + + if(s->codec_tag == AV_RL32("WV1F") && show_bits(gb, 24) == 0x575630){ + skip_bits(gb, 24); + if(get_bits(gb, 8) == 0xF0) + goto end; + } + + startcode = 0xff; + for(;;) { + if(get_bits_count(gb) >= gb->size_in_bits){ + if(gb->size_in_bits==8 && (s->divx_version>=0 || s->xvid_build>=0) || s->codec_tag == AV_RL32("QMP4")){ + av_log(s->avctx, AV_LOG_VERBOSE, "frame skip %d\n", gb->size_in_bits); + return FRAME_SKIPPED; //divx bug + }else + return -1; //end of stream + } + + /* use the bits after the test */ + v = get_bits(gb, 8); + startcode = ((startcode << 8) | v) & 0xffffffff; + + if((startcode&0xFFFFFF00) != 0x100) + continue; //no startcode + + if(s->avctx->debug&FF_DEBUG_STARTCODE){ + av_log(s->avctx, AV_LOG_DEBUG, "startcode: %3X ", startcode); + if (startcode<=0x11F) av_log(s->avctx, AV_LOG_DEBUG, "Video Object Start"); + else if(startcode<=0x12F) av_log(s->avctx, AV_LOG_DEBUG, "Video Object Layer Start"); + else if(startcode<=0x13F) av_log(s->avctx, AV_LOG_DEBUG, "Reserved"); + else if(startcode<=0x15F) av_log(s->avctx, AV_LOG_DEBUG, "FGS bp start"); + else if(startcode<=0x1AF) av_log(s->avctx, AV_LOG_DEBUG, "Reserved"); + else if(startcode==0x1B0) av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Seq Start"); + else if(startcode==0x1B1) av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Seq End"); + else if(startcode==0x1B2) av_log(s->avctx, AV_LOG_DEBUG, "User Data"); + else if(startcode==0x1B3) av_log(s->avctx, AV_LOG_DEBUG, "Group of VOP start"); + else if(startcode==0x1B4) av_log(s->avctx, AV_LOG_DEBUG, "Video Session Error"); + else if(startcode==0x1B5) av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Start"); + else if(startcode==0x1B6) av_log(s->avctx, AV_LOG_DEBUG, "Video Object Plane start"); + else if(startcode==0x1B7) av_log(s->avctx, AV_LOG_DEBUG, "slice start"); + else if(startcode==0x1B8) av_log(s->avctx, AV_LOG_DEBUG, "extension start"); + else if(startcode==0x1B9) av_log(s->avctx, AV_LOG_DEBUG, "fgs start"); + else if(startcode==0x1BA) av_log(s->avctx, AV_LOG_DEBUG, "FBA Object start"); + else if(startcode==0x1BB) av_log(s->avctx, AV_LOG_DEBUG, "FBA Object Plane start"); + else if(startcode==0x1BC) av_log(s->avctx, AV_LOG_DEBUG, "Mesh Object start"); + else if(startcode==0x1BD) av_log(s->avctx, AV_LOG_DEBUG, "Mesh Object Plane start"); + else if(startcode==0x1BE) av_log(s->avctx, AV_LOG_DEBUG, "Still Texture Object start"); + else if(startcode==0x1BF) av_log(s->avctx, AV_LOG_DEBUG, "Texture Spatial Layer start"); + else if(startcode==0x1C0) av_log(s->avctx, AV_LOG_DEBUG, "Texture SNR Layer start"); + else if(startcode==0x1C1) av_log(s->avctx, AV_LOG_DEBUG, "Texture Tile start"); + else if(startcode==0x1C2) av_log(s->avctx, AV_LOG_DEBUG, "Texture Shape Layer start"); + else if(startcode==0x1C3) av_log(s->avctx, AV_LOG_DEBUG, "stuffing start"); + else if(startcode<=0x1C5) av_log(s->avctx, AV_LOG_DEBUG, "reserved"); + else if(startcode<=0x1FF) av_log(s->avctx, AV_LOG_DEBUG, "System start"); + av_log(s->avctx, AV_LOG_DEBUG, " at %d\n", get_bits_count(gb)); + } + + if(startcode >= 0x120 && startcode <= 0x12F){ + if(decode_vol_header(s, gb) < 0) + return -1; + } + else if(startcode == USER_DATA_STARTCODE){ + decode_user_data(s, gb); + } + else if(startcode == GOP_STARTCODE){ + mpeg4_decode_gop_header(s, gb); + } + else if(startcode == VOS_STARTCODE){ + mpeg4_decode_profile_level(s, gb); + } + else if(startcode == VOP_STARTCODE){ + break; + } + + align_get_bits(gb); + startcode = 0xff; + } +end: + if(s->flags& CODEC_FLAG_LOW_DELAY) + s->low_delay=1; + s->avctx->has_b_frames= !s->low_delay; + return decode_vop_header(s, gb); +} + +av_cold void ff_mpeg4videodec_static_init(void) { + static int done = 0; + + if (!done) { + ff_init_rl(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); + ff_init_rl(&ff_rvlc_rl_inter, ff_mpeg4_static_rl_table_store[1]); + ff_init_rl(&ff_rvlc_rl_intra, ff_mpeg4_static_rl_table_store[2]); + INIT_VLC_RL(ff_mpeg4_rl_intra, 554); + INIT_VLC_RL(ff_rvlc_rl_inter, 1072); + INIT_VLC_RL(ff_rvlc_rl_intra, 1072); + INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */, + &ff_mpeg4_DCtab_lum[0][1], 2, 1, + &ff_mpeg4_DCtab_lum[0][0], 2, 1, 512); + INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */, + &ff_mpeg4_DCtab_chrom[0][1], 2, 1, + &ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512); + INIT_VLC_STATIC(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15, + &ff_sprite_trajectory_tab[0][1], 4, 2, + &ff_sprite_trajectory_tab[0][0], 4, 2, 128); + INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4, + &ff_mb_type_b_tab[0][1], 2, 1, + &ff_mb_type_b_tab[0][0], 2, 1, 16); + done = 1; + } +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + int ret; + + s->divx_version= + s->divx_build= + s->xvid_build= + s->lavc_build= -1; + + if((ret=ff_h263_decode_init(avctx)) < 0) + return ret; + + ff_mpeg4videodec_static_init(); + + s->h263_pred = 1; + s->low_delay = 0; //default, might be overridden in the vol header during header parsing + s->decode_mb= mpeg4_decode_mb; + s->time_increment_bits = 4; /* default value for broken headers */ + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + + avctx->internal->allocate_progress = 1; + + return 0; +} + +static const AVProfile mpeg4_video_profiles[] = { + { FF_PROFILE_MPEG4_SIMPLE, "Simple Profile" }, + { FF_PROFILE_MPEG4_SIMPLE_SCALABLE, "Simple Scalable Profile" }, + { FF_PROFILE_MPEG4_CORE, "Core Profile" }, + { FF_PROFILE_MPEG4_MAIN, "Main Profile" }, + { FF_PROFILE_MPEG4_N_BIT, "N-bit Profile" }, + { FF_PROFILE_MPEG4_SCALABLE_TEXTURE, "Scalable Texture Profile" }, + { FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION, "Simple Face Animation Profile" }, + { FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE, "Basic Animated Texture Profile" }, + { FF_PROFILE_MPEG4_HYBRID, "Hybrid Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_REAL_TIME, "Advanced Real Time Simple Profile" }, + { FF_PROFILE_MPEG4_CORE_SCALABLE, "Code Scalable Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_CODING, "Advanced Coding Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_CORE, "Advanced Core Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE, "Advanced Scalable Texture Profile" }, + { FF_PROFILE_MPEG4_SIMPLE_STUDIO, "Simple Studio Profile" }, + { FF_PROFILE_MPEG4_ADVANCED_SIMPLE, "Advanced Simple Profile" }, + { FF_PROFILE_UNKNOWN }, +}; + +static const AVOption mpeg4_options[] = { + {"quarter_sample", "1/4 subpel MC", offsetof(MpegEncContext, quarter_sample), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0}, + {"divx_packed", "divx style packed b frames", offsetof(MpegEncContext, divx_packed), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0}, + {NULL} +}; + +static const AVClass mpeg4_class = { + "MPEG4 Video Decoder", + av_default_item_name, + mpeg4_options, + LIBAVUTIL_VERSION_INT, +}; + +static const AVClass mpeg4_vdpau_class = { + "MPEG4 Video VDPAU Decoder", + av_default_item_name, + mpeg4_options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mpeg4_decoder = { + .name = "mpeg4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .priv_data_size = sizeof(MpegEncContext), + .init = decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | + CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | + CODEC_CAP_FRAME_THREADS, + .flush = ff_mpeg_flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), + .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, + .profiles = NULL_IF_CONFIG_SMALL(mpeg4_video_profiles), + .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_mpeg_update_thread_context), + .priv_class = &mpeg4_class, +}; + + +#if CONFIG_MPEG4_VDPAU_DECODER +AVCodec ff_mpeg4_vdpau_decoder = { + .name = "mpeg4_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .priv_data_size = sizeof(MpegEncContext), + .init = decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY | + CODEC_CAP_HWACCEL_VDPAU, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 (VDPAU)"), + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU_MPEG4, + AV_PIX_FMT_NONE }, + .priv_class = &mpeg4_vdpau_class, +}; +#endif diff --git a/ffmpeg/libavcodec/mpeg4videoenc.c b/ffmpeg/libavcodec/mpeg4videoenc.c new file mode 100644 index 0000000..5662735 --- /dev/null +++ b/ffmpeg/libavcodec/mpeg4videoenc.c @@ -0,0 +1,1363 @@ +/* + * MPEG4 encoder. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 "libavutil/log.h" +#include "libavutil/opt.h" +#include "mpegvideo.h" +#include "h263.h" +#include "mpeg4video.h" + +//The uni_DCtab_* tables below contain unified bits+length tables to encode DC +//differences in mpeg4. Unified in the sense that the specification specifies +//this encoding in several steps. +static uint8_t uni_DCtab_lum_len[512]; +static uint8_t uni_DCtab_chrom_len[512]; +static uint16_t uni_DCtab_lum_bits[512]; +static uint16_t uni_DCtab_chrom_bits[512]; + +//unified encoding tables for run length encoding of coefficients +//unified in the sense that the specification specifies the encoding in several steps. +static uint32_t uni_mpeg4_intra_rl_bits[64*64*2*2]; +static uint8_t uni_mpeg4_intra_rl_len [64*64*2*2]; +static uint32_t uni_mpeg4_inter_rl_bits[64*64*2*2]; +static uint8_t uni_mpeg4_inter_rl_len [64*64*2*2]; +//#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128 + (run)*256 + (level)) +//#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128*64 + (run) + (level)*64) +#define UNI_MPEG4_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level)) + +/* mpeg4 +inter +max level: 24/6 +max run: 53/63 + +intra +max level: 53/16 +max run: 29/41 +*/ + + +/** + * Return the number of bits that encoding the 8x8 block in block would need. + * @param[in] block_last_index last index in scantable order that refers to a non zero element in block. + */ +static inline int get_block_rate(MpegEncContext * s, int16_t block[64], int block_last_index, uint8_t scantable[64]){ + int last=0; + int j; + int rate=0; + + for(j=1; j<=block_last_index; j++){ + const int index= scantable[j]; + int level= block[index]; + if(level){ + level+= 64; + if((level&(~127)) == 0){ + if(jintra_ac_vlc_length [UNI_AC_ENC_INDEX(j-last-1, level)]; + else rate+= s->intra_ac_vlc_last_length[UNI_AC_ENC_INDEX(j-last-1, level)]; + }else + rate += s->ac_esc_length; + + last= j; + } + } + + return rate; +} + + +/** + * Restore the ac coefficients in block that have been changed by decide_ac_pred(). + * This function also restores s->block_last_index. + * @param[in,out] block MB coefficients, these will be restored + * @param[in] dir ac prediction direction for each 8x8 block + * @param[out] st scantable for each 8x8 block + * @param[in] zigzag_last_index index referring to the last non zero coefficient in zigzag order + */ +static inline void restore_ac_coeffs(MpegEncContext * s, int16_t block[6][64], const int dir[6], uint8_t *st[6], const int zigzag_last_index[6]) +{ + int i, n; + memcpy(s->block_last_index, zigzag_last_index, sizeof(int)*6); + + for(n=0; n<6; n++){ + int16_t *ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + + st[n]= s->intra_scantable.permutated; + if(dir[n]){ + /* top prediction */ + for(i=1; i<8; i++){ + block[n][s->dsp.idct_permutation[i ]] = ac_val[i+8]; + } + }else{ + /* left prediction */ + for(i=1; i<8; i++){ + block[n][s->dsp.idct_permutation[i<<3]]= ac_val[i ]; + } + } + } +} + +/** + * Return the optimal value (0 or 1) for the ac_pred element for the given MB in mpeg4. + * This function will also update s->block_last_index and s->ac_val. + * @param[in,out] block MB coefficients, these will be updated if 1 is returned + * @param[in] dir ac prediction direction for each 8x8 block + * @param[out] st scantable for each 8x8 block + * @param[out] zigzag_last_index index referring to the last non zero coefficient in zigzag order + */ +static inline int decide_ac_pred(MpegEncContext * s, int16_t block[6][64], const int dir[6], uint8_t *st[6], int zigzag_last_index[6]) +{ + int score= 0; + int i, n; + int8_t * const qscale_table = s->current_picture.qscale_table; + + memcpy(zigzag_last_index, s->block_last_index, sizeof(int)*6); + + for(n=0; n<6; n++){ + int16_t *ac_val, *ac_val1; + + score -= get_block_rate(s, block[n], s->block_last_index[n], s->intra_scantable.permutated); + + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val1= ac_val; + if(dir[n]){ + const int xy= s->mb_x + s->mb_y*s->mb_stride - s->mb_stride; + /* top prediction */ + ac_val-= s->block_wrap[n]*16; + if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){ + /* same qscale */ + for(i=1; i<8; i++){ + const int level= block[n][s->dsp.idct_permutation[i ]]; + block[n][s->dsp.idct_permutation[i ]] = level - ac_val[i+8]; + ac_val1[i ]= block[n][s->dsp.idct_permutation[i<<3]]; + ac_val1[i+8]= level; + } + }else{ + /* different qscale, we must rescale */ + for(i=1; i<8; i++){ + const int level= block[n][s->dsp.idct_permutation[i ]]; + block[n][s->dsp.idct_permutation[i ]] = level - ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale); + ac_val1[i ]= block[n][s->dsp.idct_permutation[i<<3]]; + ac_val1[i+8]= level; + } + } + st[n]= s->intra_h_scantable.permutated; + }else{ + const int xy= s->mb_x-1 + s->mb_y*s->mb_stride; + /* left prediction */ + ac_val-= 16; + if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){ + /* same qscale */ + for(i=1; i<8; i++){ + const int level= block[n][s->dsp.idct_permutation[i<<3]]; + block[n][s->dsp.idct_permutation[i<<3]]= level - ac_val[i]; + ac_val1[i ]= level; + ac_val1[i+8]= block[n][s->dsp.idct_permutation[i ]]; + } + }else{ + /* different qscale, we must rescale */ + for(i=1; i<8; i++){ + const int level= block[n][s->dsp.idct_permutation[i<<3]]; + block[n][s->dsp.idct_permutation[i<<3]]= level - ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale); + ac_val1[i ]= level; + ac_val1[i+8]= block[n][s->dsp.idct_permutation[i ]]; + } + } + st[n]= s->intra_v_scantable.permutated; + } + + for(i=63; i>0; i--) //FIXME optimize + if(block[n][ st[n][i] ]) break; + s->block_last_index[n]= i; + + score += get_block_rate(s, block[n], s->block_last_index[n], st[n]); + } + + if(score < 0){ + return 1; + }else{ + restore_ac_coeffs(s, block, dir, st, zigzag_last_index); + return 0; + } +} + +/** + * modify mb_type & qscale so that encoding is actually possible in mpeg4 + */ +void ff_clean_mpeg4_qscales(MpegEncContext *s){ + int i; + int8_t * const qscale_table = s->current_picture.qscale_table; + + ff_clean_h263_qscales(s); + + if(s->pict_type== AV_PICTURE_TYPE_B){ + int odd=0; + /* ok, come on, this isn't funny anymore, there's more code for handling this mpeg4 mess than for the actual adaptive quantization */ + + for(i=0; imb_num; i++){ + int mb_xy= s->mb_index2xy[i]; + odd += qscale_table[mb_xy]&1; + } + + if(2*odd > s->mb_num) odd=1; + else odd=0; + + for(i=0; imb_num; i++){ + int mb_xy= s->mb_index2xy[i]; + if((qscale_table[mb_xy]&1) != odd) + qscale_table[mb_xy]++; + if(qscale_table[mb_xy] > 31) + qscale_table[mb_xy]= 31; + } + + for(i=1; imb_num; i++){ + int mb_xy= s->mb_index2xy[i]; + if(qscale_table[mb_xy] != qscale_table[s->mb_index2xy[i-1]] && (s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_DIRECT)){ + s->mb_type[mb_xy]|= CANDIDATE_MB_TYPE_BIDIR; + } + } + } +} + + +/** + * Encode the dc value. + * @param n block index (0-3 are luma, 4-5 are chroma) + */ +static inline void mpeg4_encode_dc(PutBitContext * s, int level, int n) +{ +#if 1 + /* DC will overflow if level is outside the [-255,255] range. */ + level+=256; + if (n < 4) { + /* luminance */ + put_bits(s, uni_DCtab_lum_len[level], uni_DCtab_lum_bits[level]); + } else { + /* chrominance */ + put_bits(s, uni_DCtab_chrom_len[level], uni_DCtab_chrom_bits[level]); + } +#else + int size, v; + /* find number of bits */ + size = 0; + v = abs(level); + while (v) { + v >>= 1; + size++; + } + + if (n < 4) { + /* luminance */ + put_bits(&s->pb, ff_mpeg4_DCtab_lum[size][1], ff_mpeg4_DCtab_lum[size][0]); + } else { + /* chrominance */ + put_bits(&s->pb, ff_mpeg4_DCtab_chrom[size][1], ff_mpeg4_DCtab_chrom[size][0]); + } + + /* encode remaining bits */ + if (size > 0) { + if (level < 0) + level = (-level) ^ ((1 << size) - 1); + put_bits(&s->pb, size, level); + if (size > 8) + put_bits(&s->pb, 1, 1); + } +#endif +} + +static inline int mpeg4_get_dc_length(int level, int n){ + if (n < 4) { + return uni_DCtab_lum_len[level + 256]; + } else { + return uni_DCtab_chrom_len[level + 256]; + } +} + +/** + * Encode an 8x8 block. + * @param n block index (0-3 are luma, 4-5 are chroma) + */ +static inline void mpeg4_encode_block(MpegEncContext * s, int16_t * block, int n, int intra_dc, + uint8_t *scan_table, PutBitContext *dc_pb, PutBitContext *ac_pb) +{ + int i, last_non_zero; + uint32_t *bits_tab; + uint8_t *len_tab; + const int last_index = s->block_last_index[n]; + + if (s->mb_intra) { //Note gcc (3.2.1 at least) will optimize this away + /* mpeg4 based DC predictor */ + mpeg4_encode_dc(dc_pb, intra_dc, n); + if(last_index<1) return; + i = 1; + bits_tab= uni_mpeg4_intra_rl_bits; + len_tab = uni_mpeg4_intra_rl_len; + } else { + if(last_index<0) return; + i = 0; + bits_tab= uni_mpeg4_inter_rl_bits; + len_tab = uni_mpeg4_inter_rl_len; + } + + /* AC coefs */ + last_non_zero = i - 1; + for (; i < last_index; i++) { + int level = block[ scan_table[i] ]; + if (level) { + int run = i - last_non_zero - 1; + level+=64; + if((level&(~127)) == 0){ + const int index= UNI_MPEG4_ENC_INDEX(0, run, level); + put_bits(ac_pb, len_tab[index], bits_tab[index]); + }else{ //ESC3 + put_bits(ac_pb, 7+2+1+6+1+12+1, (3<<23)+(3<<21)+(0<<20)+(run<<14)+(1<<13)+(((level-64)&0xfff)<<1)+1); + } + last_non_zero = i; + } + } + /*if(i<=last_index)*/{ + int level = block[ scan_table[i] ]; + int run = i - last_non_zero - 1; + level+=64; + if((level&(~127)) == 0){ + const int index= UNI_MPEG4_ENC_INDEX(1, run, level); + put_bits(ac_pb, len_tab[index], bits_tab[index]); + }else{ //ESC3 + put_bits(ac_pb, 7+2+1+6+1+12+1, (3<<23)+(3<<21)+(1<<20)+(run<<14)+(1<<13)+(((level-64)&0xfff)<<1)+1); + } + } +} + +static int mpeg4_get_block_length(MpegEncContext * s, int16_t * block, int n, int intra_dc, + uint8_t *scan_table) +{ + int i, last_non_zero; + uint8_t *len_tab; + const int last_index = s->block_last_index[n]; + int len=0; + + if (s->mb_intra) { //Note gcc (3.2.1 at least) will optimize this away + /* mpeg4 based DC predictor */ + len += mpeg4_get_dc_length(intra_dc, n); + if(last_index<1) return len; + i = 1; + len_tab = uni_mpeg4_intra_rl_len; + } else { + if(last_index<0) return 0; + i = 0; + len_tab = uni_mpeg4_inter_rl_len; + } + + /* AC coefs */ + last_non_zero = i - 1; + for (; i < last_index; i++) { + int level = block[ scan_table[i] ]; + if (level) { + int run = i - last_non_zero - 1; + level+=64; + if((level&(~127)) == 0){ + const int index= UNI_MPEG4_ENC_INDEX(0, run, level); + len += len_tab[index]; + }else{ //ESC3 + len += 7+2+1+6+1+12+1; + } + last_non_zero = i; + } + } + /*if(i<=last_index)*/{ + int level = block[ scan_table[i] ]; + int run = i - last_non_zero - 1; + level+=64; + if((level&(~127)) == 0){ + const int index= UNI_MPEG4_ENC_INDEX(1, run, level); + len += len_tab[index]; + }else{ //ESC3 + len += 7+2+1+6+1+12+1; + } + } + + return len; +} + +static inline void mpeg4_encode_blocks(MpegEncContext * s, int16_t block[6][64], int intra_dc[6], + uint8_t **scan_table, PutBitContext *dc_pb, PutBitContext *ac_pb){ + int i; + + if(scan_table){ + if(s->flags2 & CODEC_FLAG2_NO_OUTPUT){ + for (i = 0; i < 6; i++) { + skip_put_bits(&s->pb, mpeg4_get_block_length(s, block[i], i, intra_dc[i], scan_table[i])); + } + }else{ + /* encode each block */ + for (i = 0; i < 6; i++) { + mpeg4_encode_block(s, block[i], i, intra_dc[i], scan_table[i], dc_pb, ac_pb); + } + } + }else{ + if(s->flags2 & CODEC_FLAG2_NO_OUTPUT){ + for (i = 0; i < 6; i++) { + skip_put_bits(&s->pb, mpeg4_get_block_length(s, block[i], i, 0, s->intra_scantable.permutated)); + } + }else{ + /* encode each block */ + for (i = 0; i < 6; i++) { + mpeg4_encode_block(s, block[i], i, 0, s->intra_scantable.permutated, dc_pb, ac_pb); + } + } + } +} + +static inline int get_b_cbp(MpegEncContext * s, int16_t block[6][64], + int motion_x, int motion_y, int mb_type) +{ + int cbp = 0, i; + + if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) { + int score = 0; + const int lambda = s->lambda2 >> (FF_LAMBDA_SHIFT - 6); + + for (i = 0; i < 6; i++) + if (s->coded_score[i] < 0) { + score += s->coded_score[i]; + cbp |= 1 << (5 - i); + } + + if (cbp) { + int zero_score = -6; + if ((motion_x | motion_y | s->dquant | mb_type) == 0) + zero_score -= 4; //2*MV + mb_type + cbp bit + + zero_score *= lambda; + if (zero_score <= score) + cbp = 0; + } + + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0 && ((cbp >> (5 - i)) & 1) == 0) { + s->block_last_index[i] = -1; + s->dsp.clear_block(s->block[i]); + } + } + } else { + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + } + return cbp; +} + +//FIXME this is duplicated to h263.c +static const int dquant_code[5]= {1,0,9,2,3}; + +void ff_mpeg4_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y) +{ + int cbpc, cbpy, pred_x, pred_y; + PutBitContext * const pb2 = s->data_partitioning ? &s->pb2 : &s->pb; + PutBitContext * const tex_pb = s->data_partitioning && s->pict_type!=AV_PICTURE_TYPE_B ? &s->tex_pb : &s->pb; + PutBitContext * const dc_pb = s->data_partitioning && s->pict_type!=AV_PICTURE_TYPE_I ? &s->pb2 : &s->pb; + const int interleaved_stats= (s->flags&CODEC_FLAG_PASS1) && !s->data_partitioning ? 1 : 0; + + if (!s->mb_intra) { + int i, cbp; + + if(s->pict_type==AV_PICTURE_TYPE_B){ + static const int mb_type_table[8]= {-1, 3, 2, 1,-1,-1,-1, 0}; /* convert from mv_dir to type */ + int mb_type= mb_type_table[s->mv_dir]; + + if(s->mb_x==0){ + for(i=0; i<2; i++){ + s->last_mv[i][0][0]= + s->last_mv[i][0][1]= + s->last_mv[i][1][0]= + s->last_mv[i][1][1]= 0; + } + } + + av_assert2(s->dquant>=-2 && s->dquant<=2); + av_assert2((s->dquant&1)==0); + av_assert2(mb_type>=0); + + /* nothing to do if this MB was skipped in the next P Frame */ + if (s->next_picture.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]) { //FIXME avoid DCT & ... + s->skip_count++; + s->mv[0][0][0]= + s->mv[0][0][1]= + s->mv[1][0][0]= + s->mv[1][0][1]= 0; + s->mv_dir= MV_DIR_FORWARD; //doesn't matter + s->qscale -= s->dquant; +// s->mb_skipped=1; + + return; + } + + cbp= get_b_cbp(s, block, motion_x, motion_y, mb_type); + + if ((cbp | motion_x | motion_y | mb_type) ==0) { + /* direct MB with MV={0,0} */ + av_assert2(s->dquant==0); + + put_bits(&s->pb, 1, 1); /* mb not coded modb1=1 */ + + if(interleaved_stats){ + s->misc_bits++; + s->last_bits++; + } + s->skip_count++; + return; + } + + put_bits(&s->pb, 1, 0); /* mb coded modb1=0 */ + put_bits(&s->pb, 1, cbp ? 0 : 1); /* modb2 */ //FIXME merge + put_bits(&s->pb, mb_type+1, 1); // this table is so simple that we don't need it :) + if(cbp) put_bits(&s->pb, 6, cbp); + + if(cbp && mb_type){ + if(s->dquant) + put_bits(&s->pb, 2, (s->dquant>>2)+3); + else + put_bits(&s->pb, 1, 0); + }else + s->qscale -= s->dquant; + + if(!s->progressive_sequence){ + if(cbp) + put_bits(&s->pb, 1, s->interlaced_dct); + if(mb_type) // not direct mode + put_bits(&s->pb, 1, s->mv_type == MV_TYPE_FIELD); + } + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + if(mb_type == 0){ + av_assert2(s->mv_dir & MV_DIRECT); + ff_h263_encode_motion_vector(s, motion_x, motion_y, 1); + s->b_count++; + s->f_count++; + }else{ + av_assert2(mb_type > 0 && mb_type < 4); + if(s->mv_type != MV_TYPE_FIELD){ + if(s->mv_dir & MV_DIR_FORWARD){ + ff_h263_encode_motion_vector(s, s->mv[0][0][0] - s->last_mv[0][0][0], + s->mv[0][0][1] - s->last_mv[0][0][1], s->f_code); + s->last_mv[0][0][0]= s->last_mv[0][1][0]= s->mv[0][0][0]; + s->last_mv[0][0][1]= s->last_mv[0][1][1]= s->mv[0][0][1]; + s->f_count++; + } + if(s->mv_dir & MV_DIR_BACKWARD){ + ff_h263_encode_motion_vector(s, s->mv[1][0][0] - s->last_mv[1][0][0], + s->mv[1][0][1] - s->last_mv[1][0][1], s->b_code); + s->last_mv[1][0][0]= s->last_mv[1][1][0]= s->mv[1][0][0]; + s->last_mv[1][0][1]= s->last_mv[1][1][1]= s->mv[1][0][1]; + s->b_count++; + } + }else{ + if(s->mv_dir & MV_DIR_FORWARD){ + put_bits(&s->pb, 1, s->field_select[0][0]); + put_bits(&s->pb, 1, s->field_select[0][1]); + } + if(s->mv_dir & MV_DIR_BACKWARD){ + put_bits(&s->pb, 1, s->field_select[1][0]); + put_bits(&s->pb, 1, s->field_select[1][1]); + } + if(s->mv_dir & MV_DIR_FORWARD){ + for(i=0; i<2; i++){ + ff_h263_encode_motion_vector(s, s->mv[0][i][0] - s->last_mv[0][i][0] , + s->mv[0][i][1] - s->last_mv[0][i][1]/2, s->f_code); + s->last_mv[0][i][0]= s->mv[0][i][0]; + s->last_mv[0][i][1]= s->mv[0][i][1]*2; + } + s->f_count++; + } + if(s->mv_dir & MV_DIR_BACKWARD){ + for(i=0; i<2; i++){ + ff_h263_encode_motion_vector(s, s->mv[1][i][0] - s->last_mv[1][i][0] , + s->mv[1][i][1] - s->last_mv[1][i][1]/2, s->b_code); + s->last_mv[1][i][0]= s->mv[1][i][0]; + s->last_mv[1][i][1]= s->mv[1][i][1]*2; + } + s->b_count++; + } + } + } + + if(interleaved_stats){ + s->mv_bits+= get_bits_diff(s); + } + + mpeg4_encode_blocks(s, block, NULL, NULL, NULL, &s->pb); + + if(interleaved_stats){ + s->p_tex_bits+= get_bits_diff(s); + } + + }else{ /* s->pict_type==AV_PICTURE_TYPE_B */ + cbp= get_p_cbp(s, block, motion_x, motion_y); + + if ((cbp | motion_x | motion_y | s->dquant) == 0 && s->mv_type==MV_TYPE_16X16) { + /* check if the B frames can skip it too, as we must skip it if we skip here + why didn't they just compress the skip-mb bits instead of reusing them ?! */ + if(s->max_b_frames>0){ + int i; + int x,y, offset; + uint8_t *p_pic; + + x= s->mb_x*16; + y= s->mb_y*16; + + offset= x + y*s->linesize; + p_pic = s->new_picture.f.data[0] + offset; + + s->mb_skipped=1; + for(i=0; imax_b_frames; i++){ + uint8_t *b_pic; + int diff; + Picture *pic= s->reordered_input_picture[i+1]; + + if (pic == NULL || pic->f.pict_type != AV_PICTURE_TYPE_B) + break; + + b_pic = pic->f.data[0] + offset; + if (!pic->shared) + b_pic+= INPLACE_OFFSET; + + if(x+16 > s->width || y+16 > s->height){ + int x1,y1; + int xe= FFMIN(16, s->width - x); + int ye= FFMIN(16, s->height- y); + diff=0; + for(y1=0; y1linesize] - b_pic[x1+y1*s->linesize]); + } + } + diff= diff*256/(xe*ye); + }else{ + diff= s->dsp.sad[0](NULL, p_pic, b_pic, s->linesize, 16); + } + if(diff>s->qscale*70){ //FIXME check that 70 is optimal + s->mb_skipped=0; + break; + } + } + }else + s->mb_skipped=1; + + if(s->mb_skipped==1){ + /* skip macroblock */ + put_bits(&s->pb, 1, 1); + + if(interleaved_stats){ + s->misc_bits++; + s->last_bits++; + } + s->skip_count++; + + return; + } + } + + put_bits(&s->pb, 1, 0); /* mb coded */ + cbpc = cbp & 3; + cbpy = cbp >> 2; + cbpy ^= 0xf; + if(s->mv_type==MV_TYPE_16X16){ + if(s->dquant) cbpc+= 8; + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc], + ff_h263_inter_MCBPC_code[cbpc]); + + put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + if(s->dquant) + put_bits(pb2, 2, dquant_code[s->dquant+2]); + + if(!s->progressive_sequence){ + if(cbp) + put_bits(pb2, 1, s->interlaced_dct); + put_bits(pb2, 1, 0); + } + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + /* motion vectors: 16x16 mode */ + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + + ff_h263_encode_motion_vector(s, motion_x - pred_x, + motion_y - pred_y, s->f_code); + }else if(s->mv_type==MV_TYPE_FIELD){ + if(s->dquant) cbpc+= 8; + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc], + ff_h263_inter_MCBPC_code[cbpc]); + + put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + if(s->dquant) + put_bits(pb2, 2, dquant_code[s->dquant+2]); + + av_assert2(!s->progressive_sequence); + if(cbp) + put_bits(pb2, 1, s->interlaced_dct); + put_bits(pb2, 1, 1); + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + /* motion vectors: 16x8 interlaced mode */ + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + pred_y /=2; + + put_bits(&s->pb, 1, s->field_select[0][0]); + put_bits(&s->pb, 1, s->field_select[0][1]); + + ff_h263_encode_motion_vector(s, s->mv[0][0][0] - pred_x, + s->mv[0][0][1] - pred_y, s->f_code); + ff_h263_encode_motion_vector(s, s->mv[0][1][0] - pred_x, + s->mv[0][1][1] - pred_y, s->f_code); + }else{ + av_assert2(s->mv_type==MV_TYPE_8X8); + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc+16], + ff_h263_inter_MCBPC_code[cbpc+16]); + put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + + if(!s->progressive_sequence){ + if(cbp) + put_bits(pb2, 1, s->interlaced_dct); + } + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + for(i=0; i<4; i++){ + /* motion vectors: 8x8 mode*/ + ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y); + + ff_h263_encode_motion_vector(s, s->current_picture.motion_val[0][ s->block_index[i] ][0] - pred_x, + s->current_picture.motion_val[0][ s->block_index[i] ][1] - pred_y, s->f_code); + } + } + + if(interleaved_stats){ + s->mv_bits+= get_bits_diff(s); + } + + mpeg4_encode_blocks(s, block, NULL, NULL, NULL, tex_pb); + + if(interleaved_stats){ + s->p_tex_bits+= get_bits_diff(s); + } + s->f_count++; + } + } else { + int cbp; + int dc_diff[6]; //dc values with the dc prediction subtracted + int dir[6]; //prediction direction + int zigzag_last_index[6]; + uint8_t *scan_table[6]; + int i; + + for(i=0; i<6; i++){ + dc_diff[i]= ff_mpeg4_pred_dc(s, i, block[i][0], &dir[i], 1); + } + + if(s->flags & CODEC_FLAG_AC_PRED){ + s->ac_pred= decide_ac_pred(s, block, dir, scan_table, zigzag_last_index); + }else{ + for(i=0; i<6; i++) + scan_table[i]= s->intra_scantable.permutated; + } + + /* compute cbp */ + cbp = 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 1) + cbp |= 1 << (5 - i); + } + + cbpc = cbp & 3; + if (s->pict_type == AV_PICTURE_TYPE_I) { + if(s->dquant) cbpc+=4; + put_bits(&s->pb, + ff_h263_intra_MCBPC_bits[cbpc], + ff_h263_intra_MCBPC_code[cbpc]); + } else { + if(s->dquant) cbpc+=8; + put_bits(&s->pb, 1, 0); /* mb coded */ + put_bits(&s->pb, + ff_h263_inter_MCBPC_bits[cbpc + 4], + ff_h263_inter_MCBPC_code[cbpc + 4]); + } + put_bits(pb2, 1, s->ac_pred); + cbpy = cbp >> 2; + put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]); + if(s->dquant) + put_bits(dc_pb, 2, dquant_code[s->dquant+2]); + + if(!s->progressive_sequence){ + put_bits(dc_pb, 1, s->interlaced_dct); + } + + if(interleaved_stats){ + s->misc_bits+= get_bits_diff(s); + } + + mpeg4_encode_blocks(s, block, dc_diff, scan_table, dc_pb, tex_pb); + + if(interleaved_stats){ + s->i_tex_bits+= get_bits_diff(s); + } + s->i_count++; + + /* restore ac coeffs & last_index stuff if we messed them up with the prediction */ + if(s->ac_pred) + restore_ac_coeffs(s, block, dir, scan_table, zigzag_last_index); + } +} + +/** + * add mpeg4 stuffing bits (01...1) + */ +void ff_mpeg4_stuffing(PutBitContext * pbc) +{ + int length; + put_bits(pbc, 1, 0); + length= (-put_bits_count(pbc))&7; + if(length) put_bits(pbc, length, (1<pict_type==AV_PICTURE_TYPE_B){ + ff_mpeg4_init_direct_mv(s); + }else{ + s->last_time_base= s->time_base; + s->time_base= FFUDIV(s->time, s->avctx->time_base.den); + } +} + +static void mpeg4_encode_gop_header(MpegEncContext * s){ + int hours, minutes, seconds; + int64_t time; + + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, GOP_STARTCODE); + + time = s->current_picture_ptr->f.pts; + if(s->reordered_input_picture[1]) + time = FFMIN(time, s->reordered_input_picture[1]->f.pts); + time= time*s->avctx->time_base.num; + s->last_time_base= FFUDIV(time, s->avctx->time_base.den); + + seconds= FFUDIV(time, s->avctx->time_base.den); + minutes= FFUDIV(seconds, 60); seconds = FFUMOD(seconds, 60); + hours = FFUDIV(minutes, 60); minutes = FFUMOD(minutes, 60); + hours = FFUMOD(hours , 24); + + put_bits(&s->pb, 5, hours); + put_bits(&s->pb, 6, minutes); + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 6, seconds); + + put_bits(&s->pb, 1, !!(s->flags&CODEC_FLAG_CLOSED_GOP)); + put_bits(&s->pb, 1, 0); //broken link == NO + + ff_mpeg4_stuffing(&s->pb); +} + +static void mpeg4_encode_visual_object_header(MpegEncContext * s){ + int profile_and_level_indication; + int vo_ver_id; + + if(s->avctx->profile != FF_PROFILE_UNKNOWN){ + profile_and_level_indication = s->avctx->profile << 4; + }else if(s->max_b_frames || s->quarter_sample){ + profile_and_level_indication= 0xF0; // adv simple + }else{ + profile_and_level_indication= 0x00; // simple + } + + if(s->avctx->level != FF_LEVEL_UNKNOWN){ + profile_and_level_indication |= s->avctx->level; + }else{ + profile_and_level_indication |= 1; //level 1 + } + + if(profile_and_level_indication>>4 == 0xF){ + vo_ver_id= 5; + }else{ + vo_ver_id= 1; + } + + //FIXME levels + + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, VOS_STARTCODE); + + put_bits(&s->pb, 8, profile_and_level_indication); + + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, VISUAL_OBJ_STARTCODE); + + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 4, vo_ver_id); + put_bits(&s->pb, 3, 1); //priority + + put_bits(&s->pb, 4, 1); //visual obj type== video obj + + put_bits(&s->pb, 1, 0); //video signal type == no clue //FIXME + + ff_mpeg4_stuffing(&s->pb); +} + +static void mpeg4_encode_vol_header(MpegEncContext * s, int vo_number, int vol_number) +{ + int vo_ver_id; + + if (!CONFIG_MPEG4_ENCODER) return; + + if(s->max_b_frames || s->quarter_sample){ + vo_ver_id= 5; + s->vo_type= ADV_SIMPLE_VO_TYPE; + }else{ + vo_ver_id= 1; + s->vo_type= SIMPLE_VO_TYPE; + } + + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, 0x100 + vo_number); /* video obj */ + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, 0x120 + vol_number); /* video obj layer */ + + put_bits(&s->pb, 1, 0); /* random access vol */ + put_bits(&s->pb, 8, s->vo_type); /* video obj type indication */ + if(s->workaround_bugs & FF_BUG_MS) { + put_bits(&s->pb, 1, 0); /* is obj layer id= no */ + } else { + put_bits(&s->pb, 1, 1); /* is obj layer id= yes */ + put_bits(&s->pb, 4, vo_ver_id); /* is obj layer ver id */ + put_bits(&s->pb, 3, 1); /* is obj layer priority */ + } + + s->aspect_ratio_info= ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio); + + put_bits(&s->pb, 4, s->aspect_ratio_info);/* aspect ratio info */ + if (s->aspect_ratio_info == FF_ASPECT_EXTENDED){ + av_reduce(&s->avctx->sample_aspect_ratio.num, &s->avctx->sample_aspect_ratio.den, + s->avctx->sample_aspect_ratio.num, s->avctx->sample_aspect_ratio.den, 255); + put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.num); + put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.den); + } + + if(s->workaround_bugs & FF_BUG_MS) { // + put_bits(&s->pb, 1, 0); /* vol control parameters= no @@@ */ + } else { + put_bits(&s->pb, 1, 1); /* vol control parameters= yes */ + put_bits(&s->pb, 2, 1); /* chroma format YUV 420/YV12 */ + put_bits(&s->pb, 1, s->low_delay); + put_bits(&s->pb, 1, 0); /* vbv parameters= no */ + } + + put_bits(&s->pb, 2, RECT_SHAPE); /* vol shape= rectangle */ + put_bits(&s->pb, 1, 1); /* marker bit */ + + put_bits(&s->pb, 16, s->avctx->time_base.den); + if (s->time_increment_bits < 1) + s->time_increment_bits = 1; + put_bits(&s->pb, 1, 1); /* marker bit */ + put_bits(&s->pb, 1, 0); /* fixed vop rate=no */ + put_bits(&s->pb, 1, 1); /* marker bit */ + put_bits(&s->pb, 13, s->width); /* vol width */ + put_bits(&s->pb, 1, 1); /* marker bit */ + put_bits(&s->pb, 13, s->height); /* vol height */ + put_bits(&s->pb, 1, 1); /* marker bit */ + put_bits(&s->pb, 1, s->progressive_sequence ? 0 : 1); + put_bits(&s->pb, 1, 1); /* obmc disable */ + if (vo_ver_id == 1) { + put_bits(&s->pb, 1, s->vol_sprite_usage); /* sprite enable */ + }else{ + put_bits(&s->pb, 2, s->vol_sprite_usage); /* sprite enable */ + } + + put_bits(&s->pb, 1, 0); /* not 8 bit == false */ + put_bits(&s->pb, 1, s->mpeg_quant); /* quant type= (0=h263 style)*/ + + if(s->mpeg_quant){ + ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix); + ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix); + } + + if (vo_ver_id != 1) + put_bits(&s->pb, 1, s->quarter_sample); + put_bits(&s->pb, 1, 1); /* complexity estimation disable */ + s->resync_marker= s->rtp_mode; + put_bits(&s->pb, 1, s->resync_marker ? 0 : 1);/* resync marker disable */ + put_bits(&s->pb, 1, s->data_partitioning ? 1 : 0); + if(s->data_partitioning){ + put_bits(&s->pb, 1, 0); /* no rvlc */ + } + + if (vo_ver_id != 1){ + put_bits(&s->pb, 1, 0); /* newpred */ + put_bits(&s->pb, 1, 0); /* reduced res vop */ + } + put_bits(&s->pb, 1, 0); /* scalability */ + + ff_mpeg4_stuffing(&s->pb); + + /* user data */ + if(!(s->flags & CODEC_FLAG_BITEXACT)){ + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, 0x1B2); /* user_data */ + avpriv_put_string(&s->pb, LIBAVCODEC_IDENT, 0); + } +} + +/* write mpeg4 VOP header */ +void ff_mpeg4_encode_picture_header(MpegEncContext * s, int picture_number) +{ + int time_incr; + int time_div, time_mod; + + if(s->pict_type==AV_PICTURE_TYPE_I){ + if(!(s->flags&CODEC_FLAG_GLOBAL_HEADER)){ + if(s->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) //HACK, the reference sw is buggy + mpeg4_encode_visual_object_header(s); + if(s->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || picture_number==0) //HACK, the reference sw is buggy + mpeg4_encode_vol_header(s, 0, 0); + } + if(!(s->workaround_bugs & FF_BUG_MS)) + mpeg4_encode_gop_header(s); + } + + s->partitioned_frame= s->data_partitioning && s->pict_type!=AV_PICTURE_TYPE_B; + + put_bits(&s->pb, 16, 0); /* vop header */ + put_bits(&s->pb, 16, VOP_STARTCODE); /* vop header */ + put_bits(&s->pb, 2, s->pict_type - 1); /* pict type: I = 0 , P = 1 */ + + time_div= FFUDIV(s->time, s->avctx->time_base.den); + time_mod= FFUMOD(s->time, s->avctx->time_base.den); + time_incr= time_div - s->last_time_base; + av_assert0(time_incr >= 0); + while(time_incr--) + put_bits(&s->pb, 1, 1); + + put_bits(&s->pb, 1, 0); + + put_bits(&s->pb, 1, 1); /* marker */ + put_bits(&s->pb, s->time_increment_bits, time_mod); /* time increment */ + put_bits(&s->pb, 1, 1); /* marker */ + put_bits(&s->pb, 1, 1); /* vop coded */ + if ( s->pict_type == AV_PICTURE_TYPE_P + || (s->pict_type == AV_PICTURE_TYPE_S && s->vol_sprite_usage==GMC_SPRITE)) { + put_bits(&s->pb, 1, s->no_rounding); /* rounding type */ + } + put_bits(&s->pb, 3, 0); /* intra dc VLC threshold */ + if(!s->progressive_sequence){ + put_bits(&s->pb, 1, s->current_picture_ptr->f.top_field_first); + put_bits(&s->pb, 1, s->alternate_scan); + } + //FIXME sprite stuff + + put_bits(&s->pb, 5, s->qscale); + + if (s->pict_type != AV_PICTURE_TYPE_I) + put_bits(&s->pb, 3, s->f_code); /* fcode_for */ + if (s->pict_type == AV_PICTURE_TYPE_B) + put_bits(&s->pb, 3, s->b_code); /* fcode_back */ +} + + +static void init_uni_dc_tab(void) +{ + int level, uni_code, uni_len; + + for(level=-256; level<256; level++){ + int size, v, l; + /* find number of bits */ + size = 0; + v = abs(level); + while (v) { + v >>= 1; + size++; + } + + if (level < 0) + l= (-level) ^ ((1 << size) - 1); + else + l= level; + + /* luminance */ + uni_code= ff_mpeg4_DCtab_lum[size][0]; + uni_len = ff_mpeg4_DCtab_lum[size][1]; + + if (size > 0) { + uni_code<<=size; uni_code|=l; + uni_len+=size; + if (size > 8){ + uni_code<<=1; uni_code|=1; + uni_len++; + } + } + uni_DCtab_lum_bits[level+256]= uni_code; + uni_DCtab_lum_len [level+256]= uni_len; + + /* chrominance */ + uni_code= ff_mpeg4_DCtab_chrom[size][0]; + uni_len = ff_mpeg4_DCtab_chrom[size][1]; + + if (size > 0) { + uni_code<<=size; uni_code|=l; + uni_len+=size; + if (size > 8){ + uni_code<<=1; uni_code|=1; + uni_len++; + } + } + uni_DCtab_chrom_bits[level+256]= uni_code; + uni_DCtab_chrom_len [level+256]= uni_len; + + } +} + +static void init_uni_mpeg4_rl_tab(RLTable *rl, uint32_t *bits_tab, uint8_t *len_tab){ + int slevel, run, last; + + av_assert0(MAX_LEVEL >= 64); + av_assert0(MAX_RUN >= 63); + + for(slevel=-64; slevel<64; slevel++){ + if(slevel==0) continue; + for(run=0; run<64; run++){ + for(last=0; last<=1; last++){ + const int index= UNI_MPEG4_ENC_INDEX(last, run, slevel+64); + int level= slevel < 0 ? -slevel : slevel; + int sign= slevel < 0 ? 1 : 0; + int bits, len, code; + int level1, run1; + + len_tab[index]= 100; + + /* ESC0 */ + code= get_rl_index(rl, last, run, level); + bits= rl->table_vlc[code][0]; + len= rl->table_vlc[code][1]; + bits=bits*2+sign; len++; + + if(code!=rl->n && len < len_tab[index]){ + bits_tab[index]= bits; + len_tab [index]= len; + } + /* ESC1 */ + bits= rl->table_vlc[rl->n][0]; + len= rl->table_vlc[rl->n][1]; + bits=bits*2; len++; //esc1 + level1= level - rl->max_level[last][run]; + if(level1>0){ + code= get_rl_index(rl, last, run, level1); + bits<<= rl->table_vlc[code][1]; + len += rl->table_vlc[code][1]; + bits += rl->table_vlc[code][0]; + bits=bits*2+sign; len++; + + if(code!=rl->n && len < len_tab[index]){ + bits_tab[index]= bits; + len_tab [index]= len; + } + } + /* ESC2 */ + bits= rl->table_vlc[rl->n][0]; + len= rl->table_vlc[rl->n][1]; + bits=bits*4+2; len+=2; //esc2 + run1 = run - rl->max_run[last][level] - 1; + if(run1>=0){ + code= get_rl_index(rl, last, run1, level); + bits<<= rl->table_vlc[code][1]; + len += rl->table_vlc[code][1]; + bits += rl->table_vlc[code][0]; + bits=bits*2+sign; len++; + + if(code!=rl->n && len < len_tab[index]){ + bits_tab[index]= bits; + len_tab [index]= len; + } + } + /* ESC3 */ + bits= rl->table_vlc[rl->n][0]; + len = rl->table_vlc[rl->n][1]; + bits=bits*4+3; len+=2; //esc3 + bits=bits*2+last; len++; + bits=bits*64+run; len+=6; + bits=bits*2+1; len++; //marker + bits=bits*4096+(slevel&0xfff); len+=12; + bits=bits*2+1; len++; //marker + + if(len < len_tab[index]){ + bits_tab[index]= bits; + len_tab [index]= len; + } + } + } + } +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + int ret; + static int done = 0; + + if (avctx->width >= (1<<13) || avctx->height >= (1<<13)) { + av_log(avctx, AV_LOG_ERROR, "dimensions too large for MPEG-4\n"); + return AVERROR(EINVAL); + } + + if((ret=ff_MPV_encode_init(avctx)) < 0) + return ret; + + if (!done) { + done = 1; + + init_uni_dc_tab(); + + ff_init_rl(&ff_mpeg4_rl_intra, ff_mpeg4_static_rl_table_store[0]); + + init_uni_mpeg4_rl_tab(&ff_mpeg4_rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len); + init_uni_mpeg4_rl_tab(&ff_h263_rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len); + } + + s->min_qcoeff= -2048; + s->max_qcoeff= 2047; + s->intra_ac_vlc_length = uni_mpeg4_intra_rl_len; + s->intra_ac_vlc_last_length= uni_mpeg4_intra_rl_len + 128*64; + s->inter_ac_vlc_length = uni_mpeg4_inter_rl_len; + s->inter_ac_vlc_last_length= uni_mpeg4_inter_rl_len + 128*64; + s->luma_dc_vlc_length= uni_DCtab_lum_len; + s->ac_esc_length= 7+2+1+6+1+12+1; + s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; + s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table; + + if(s->flags & CODEC_FLAG_GLOBAL_HEADER){ + + s->avctx->extradata= av_malloc(1024); + init_put_bits(&s->pb, s->avctx->extradata, 1024); + + if(!(s->workaround_bugs & FF_BUG_MS)) + mpeg4_encode_visual_object_header(s); + mpeg4_encode_vol_header(s, 0, 0); + +// ff_mpeg4_stuffing(&s->pb); ? + flush_put_bits(&s->pb); + s->avctx->extradata_size= (put_bits_count(&s->pb)+7)>>3; + } + return 0; +} + +void ff_mpeg4_init_partitions(MpegEncContext *s) +{ + uint8_t *start= put_bits_ptr(&s->pb); + uint8_t *end= s->pb.buf_end; + int size= end - start; + int pb_size = (((intptr_t)start + size/3)&(~3)) - (intptr_t)start; + int tex_size= (size - 2*pb_size)&(~3); + + set_put_bits_buffer_size(&s->pb, pb_size); + init_put_bits(&s->tex_pb, start + pb_size , tex_size); + init_put_bits(&s->pb2 , start + pb_size + tex_size, pb_size); +} + +void ff_mpeg4_merge_partitions(MpegEncContext *s) +{ + const int pb2_len = put_bits_count(&s->pb2 ); + const int tex_pb_len= put_bits_count(&s->tex_pb); + const int bits= put_bits_count(&s->pb); + + if(s->pict_type==AV_PICTURE_TYPE_I){ + put_bits(&s->pb, 19, DC_MARKER); + s->misc_bits+=19 + pb2_len + bits - s->last_bits; + s->i_tex_bits+= tex_pb_len; + }else{ + put_bits(&s->pb, 17, MOTION_MARKER); + s->misc_bits+=17 + pb2_len; + s->mv_bits+= bits - s->last_bits; + s->p_tex_bits+= tex_pb_len; + } + + flush_put_bits(&s->pb2); + flush_put_bits(&s->tex_pb); + + set_put_bits_buffer_size(&s->pb, s->pb2.buf_end - s->pb.buf); + avpriv_copy_bits(&s->pb, s->pb2.buf , pb2_len); + avpriv_copy_bits(&s->pb, s->tex_pb.buf, tex_pb_len); + s->last_bits= put_bits_count(&s->pb); +} + + +void ff_mpeg4_encode_video_packet_header(MpegEncContext *s) +{ + int mb_num_bits= av_log2(s->mb_num - 1) + 1; + + put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(s), 0); + put_bits(&s->pb, 1, 1); + + put_bits(&s->pb, mb_num_bits, s->mb_x + s->mb_y*s->mb_width); + put_bits(&s->pb, s->quant_precision, s->qscale); + put_bits(&s->pb, 1, 0); /* no HEC */ +} + +#define OFFSET(x) offsetof(MpegEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "data_partitioning", "Use data partitioning.", OFFSET(data_partitioning), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + FF_MPV_COMMON_OPTS + { NULL }, +}; + +static const AVClass mpeg4enc_class = { + .class_name = "MPEG4 encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mpeg4_encoder = { + .name = "mpeg4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .priv_data_size = sizeof(MpegEncContext), + .init = encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), + .priv_class = &mpeg4enc_class, +}; diff --git a/ffmpeg/libavcodec/mpegaudio.c b/ffmpeg/libavcodec/mpegaudio.c new file mode 100644 index 0000000..cba5299 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudio.c @@ -0,0 +1,50 @@ +/* + * MPEG Audio common code + * Copyright (c) 2001, 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * MPEG Audio common code. + */ + +#include "mpegaudio.h" + + +/* bitrate is in kb/s */ +int ff_mpa_l2_select_table(int bitrate, int nb_channels, int freq, int lsf) +{ + int ch_bitrate, table; + + ch_bitrate = bitrate / nb_channels; + if (!lsf) { + if ((freq == 48000 && ch_bitrate >= 56) || + (ch_bitrate >= 56 && ch_bitrate <= 80)) + table = 0; + else if (freq != 48000 && ch_bitrate >= 96) + table = 1; + else if (freq != 32000 && ch_bitrate <= 48) + table = 2; + else + table = 3; + } else { + table = 4; + } + return table; +} diff --git a/ffmpeg/libavcodec/mpegaudio.h b/ffmpeg/libavcodec/mpegaudio.h new file mode 100644 index 0000000..b880b7a --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudio.h @@ -0,0 +1,77 @@ +/* + * copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * mpeg audio declarations for both encoder and decoder. + */ + +#ifndef AVCODEC_MPEGAUDIO_H +#define AVCODEC_MPEGAUDIO_H + +#ifndef CONFIG_FLOAT +# define CONFIG_FLOAT 0 +#endif + +#include + +/* max frame size, in samples */ +#define MPA_FRAME_SIZE 1152 + +/* max compressed frame size */ +#define MPA_MAX_CODED_FRAME_SIZE 1792 + +#define MPA_MAX_CHANNELS 2 + +#define SBLIMIT 32 /* number of subbands */ + +#define MPA_STEREO 0 +#define MPA_JSTEREO 1 +#define MPA_DUAL 2 +#define MPA_MONO 3 + +#ifndef FRAC_BITS +#define FRAC_BITS 23 /* fractional bits for sb_samples and dct */ +#define WFRAC_BITS 16 /* fractional bits for window */ +#endif + +#define IMDCT_SCALAR 1.759 + +#define FRAC_ONE (1 << FRAC_BITS) + +#define FIX(a) ((int)((a) * FRAC_ONE)) + +#if CONFIG_FLOAT +# define INTFLOAT float +typedef float MPA_INT; +typedef float OUT_INT; +#elif FRAC_BITS <= 15 +# define INTFLOAT int +typedef int16_t MPA_INT; +typedef int16_t OUT_INT; +#else +# define INTFLOAT int +typedef int32_t MPA_INT; +typedef int16_t OUT_INT; +#endif + +int ff_mpa_l2_select_table(int bitrate, int nb_channels, int freq, int lsf); + +#endif /* AVCODEC_MPEGAUDIO_H */ diff --git a/ffmpeg/libavcodec/mpegaudio_parser.c b/ffmpeg/libavcodec/mpegaudio_parser.c new file mode 100644 index 0000000..4081936 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudio_parser.c @@ -0,0 +1,114 @@ +/* + * MPEG Audio parser + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 "parser.h" +#include "mpegaudiodecheader.h" +#include "libavutil/common.h" + + +typedef struct MpegAudioParseContext { + ParseContext pc; + int frame_size; + uint32_t header; + int header_count; + int no_bitrate; +} MpegAudioParseContext; + +#define MPA_HEADER_SIZE 4 + +/* header + layer + bitrate + freq + lsf/mpeg25 */ +#define SAME_HEADER_MASK \ + (0xffe00000 | (3 << 17) | (3 << 10) | (3 << 19)) + +static int mpegaudio_parse(AVCodecParserContext *s1, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + MpegAudioParseContext *s = s1->priv_data; + ParseContext *pc = &s->pc; + uint32_t state= pc->state; + int i; + int next= END_NOT_FOUND; + + for(i=0; iframe_size){ + int inc= FFMIN(buf_size - i, s->frame_size); + i += inc; + s->frame_size -= inc; + state = 0; + + if(!s->frame_size){ + next= i; + break; + } + }else{ + while(i 4) + s->header_count = -2; + } else { + if((state&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header) + s->header_count= -3; + s->header= state; + s->header_count++; + s->frame_size = ret-4; + + if (s->header_count > 0) { + avctx->sample_rate= sr; + avctx->channels = channels; + s1->duration = frame_size; + if (s->no_bitrate || !avctx->bit_rate) { + s->no_bitrate = 1; + avctx->bit_rate += (bit_rate - avctx->bit_rate) / s->header_count; + } + } + break; + } + } + } + } + + pc->state= state; + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + + +AVCodecParser ff_mpegaudio_parser = { + .codec_ids = { AV_CODEC_ID_MP1, AV_CODEC_ID_MP2, AV_CODEC_ID_MP3 }, + .priv_data_size = sizeof(MpegAudioParseContext), + .parser_parse = mpegaudio_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/mpegaudio_tablegen.c b/ffmpeg/libavcodec/mpegaudio_tablegen.c new file mode 100644 index 0000000..90c9de4 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudio_tablegen.c @@ -0,0 +1,42 @@ +/* + * Generate a header file for hardcoded mpegaudiodec tables + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#include "mpegaudio_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + mpegaudio_tableinit(); + + write_fileheader(); + + WRITE_ARRAY("static const", int8_t, table_4_3_exp); + WRITE_ARRAY("static const", uint32_t, table_4_3_value); + WRITE_ARRAY("static const", uint32_t, exp_table_fixed); + WRITE_ARRAY("static const", float, exp_table_float); + WRITE_2D_ARRAY("static const", uint32_t, expval_table_fixed); + WRITE_2D_ARRAY("static const", float, expval_table_float); + + return 0; +} diff --git a/ffmpeg/libavcodec/mpegaudio_tablegen.h b/ffmpeg/libavcodec/mpegaudio_tablegen.h new file mode 100644 index 0000000..6c15d3c --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudio_tablegen.h @@ -0,0 +1,72 @@ +/* + * Header file for hardcoded mpegaudiodec tables + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_MPEGAUDIO_TABLEGEN_H +#define AVCODEC_MPEGAUDIO_TABLEGEN_H + +#include +#include + +#define TABLE_4_3_SIZE (8191 + 16)*4 +#if CONFIG_HARDCODED_TABLES +#define mpegaudio_tableinit() +#include "libavcodec/mpegaudio_tables.h" +#else +static int8_t table_4_3_exp[TABLE_4_3_SIZE]; +static uint32_t table_4_3_value[TABLE_4_3_SIZE]; +static uint32_t exp_table_fixed[512]; +static uint32_t expval_table_fixed[512][16]; +static float exp_table_float[512]; +static float expval_table_float[512][16]; + +#define FRAC_BITS 23 +#define IMDCT_SCALAR 1.759 + +static void mpegaudio_tableinit(void) +{ + int i, value, exponent; + for (i = 1; i < TABLE_4_3_SIZE; i++) { + double value = i / 4; + double f, fm; + int e, m; + f = value / IMDCT_SCALAR * cbrtf(value) * pow(2, (i & 3) * 0.25); + fm = frexp(f, &e); + m = (uint32_t)(fm * (1LL << 31) + 0.5); + e += FRAC_BITS - 31 + 5 - 100; + + /* normalized to FRAC_BITS */ + table_4_3_value[i] = m; + table_4_3_exp[i] = -e; + } + for (exponent = 0; exponent < 512; exponent++) { + for (value = 0; value < 16; value++) { + double f = (double)value * cbrtf(value) * pow(2, (exponent - 400) * 0.25 + FRAC_BITS + 5) / IMDCT_SCALAR; + expval_table_fixed[exponent][value] = llrint(f); + expval_table_float[exponent][value] = f; + } + exp_table_fixed[exponent] = expval_table_fixed[exponent][1]; + exp_table_float[exponent] = expval_table_float[exponent][1]; + } +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_MPEGAUDIO_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/mpegaudiodata.c b/ffmpeg/libavcodec/mpegaudiodata.c new file mode 100644 index 0000000..0569281 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodata.c @@ -0,0 +1,146 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * mpeg audio layer common tables. + */ + +#include "mpegaudiodata.h" + + +const uint16_t avpriv_mpa_bitrate_tab[2][3][15] = { + { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} + } +}; + +const uint16_t avpriv_mpa_freq_tab[3] = { 44100, 48000, 32000 }; + +/*******************************************************/ +/* layer 2 tables */ + +const int ff_mpa_sblimit_table[5] = { 27 , 30 , 8, 12 , 30 }; + +const int ff_mpa_quant_steps[17] = { + 3, 5, 7, 9, 15, + 31, 63, 127, 255, 511, + 1023, 2047, 4095, 8191, 16383, + 32767, 65535 +}; + +/* we use a negative value if grouped */ +const int ff_mpa_quant_bits[17] = { + -5, -7, 3, -10, 4, + 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, + 15, 16 +}; + +/* encoding tables which give the quantization index. Note how it is + possible to store them efficiently ! */ +static const unsigned char alloc_table_1[] = { + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, +}; + +static const unsigned char alloc_table_3[] = { + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, +}; + +static const unsigned char alloc_table_4[] = { + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, +}; + +const unsigned char * const ff_mpa_alloc_tables[5] = +{ alloc_table_1, alloc_table_1, alloc_table_3, alloc_table_3, alloc_table_4, }; diff --git a/ffmpeg/libavcodec/mpegaudiodata.h b/ffmpeg/libavcodec/mpegaudiodata.h new file mode 100644 index 0000000..29a2658 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodata.h @@ -0,0 +1,44 @@ +/* + * MPEG Audio common tables + * copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * mpeg audio layer common tables. + */ + +#ifndef AVCODEC_MPEGAUDIODATA_H +#define AVCODEC_MPEGAUDIODATA_H + +#include + +#include "libavutil/internal.h" + +#define MODE_EXT_MS_STEREO 2 +#define MODE_EXT_I_STEREO 1 + +extern av_export const uint16_t avpriv_mpa_bitrate_tab[2][3][15]; +extern av_export const uint16_t avpriv_mpa_freq_tab[3]; +extern const int ff_mpa_sblimit_table[5]; +extern const int ff_mpa_quant_steps[17]; +extern const int ff_mpa_quant_bits[17]; +extern const unsigned char * const ff_mpa_alloc_tables[5]; + +#endif /* AVCODEC_MPEGAUDIODATA_H */ diff --git a/ffmpeg/libavcodec/mpegaudiodec.c b/ffmpeg/libavcodec/mpegaudiodec.c new file mode 100644 index 0000000..4fffb6c --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodec.c @@ -0,0 +1,2076 @@ +/* + * MPEG Audio decoder + * Copyright (c) 2001, 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * MPEG Audio decoder + */ + +#include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "libavutil/libm.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" +#include "mpegaudiodsp.h" + +/* + * TODO: + * - test lsf / mpeg25 extensively. + */ + +#include "mpegaudio.h" +#include "mpegaudiodecheader.h" + +#define BACKSTEP_SIZE 512 +#define EXTRABYTES 24 +#define LAST_BUF_SIZE 2 * BACKSTEP_SIZE + EXTRABYTES + +/* layer 3 "granule" */ +typedef struct GranuleDef { + uint8_t scfsi; + int part2_3_length; + int big_values; + int global_gain; + int scalefac_compress; + uint8_t block_type; + uint8_t switch_point; + int table_select[3]; + int subblock_gain[3]; + uint8_t scalefac_scale; + uint8_t count1table_select; + int region_size[3]; /* number of huffman codes in each region */ + int preflag; + int short_start, long_end; /* long/short band indexes */ + uint8_t scale_factors[40]; + DECLARE_ALIGNED(16, INTFLOAT, sb_hybrid)[SBLIMIT * 18]; /* 576 samples */ +} GranuleDef; + +typedef struct MPADecodeContext { + MPA_DECODE_HEADER + uint8_t last_buf[LAST_BUF_SIZE]; + int last_buf_size; + /* next header (used in free format parsing) */ + uint32_t free_format_next_header; + GetBitContext gb; + GetBitContext in_gb; + DECLARE_ALIGNED(32, MPA_INT, synth_buf)[MPA_MAX_CHANNELS][512 * 2]; + int synth_buf_offset[MPA_MAX_CHANNELS]; + DECLARE_ALIGNED(32, INTFLOAT, sb_samples)[MPA_MAX_CHANNELS][36][SBLIMIT]; + INTFLOAT mdct_buf[MPA_MAX_CHANNELS][SBLIMIT * 18]; /* previous samples, for layer 3 MDCT */ + GranuleDef granules[2][2]; /* Used in Layer 3 */ + int adu_mode; ///< 0 for standard mp3, 1 for adu formatted mp3 + int dither_state; + int err_recognition; + AVCodecContext* avctx; + MPADSPContext mpadsp; + AVFloatDSPContext fdsp; + AVFrame *frame; +} MPADecodeContext; + +#if CONFIG_FLOAT +# define SHR(a,b) ((a)*(1.0f/(1<<(b)))) +# define FIXR_OLD(a) ((int)((a) * FRAC_ONE + 0.5)) +# define FIXR(x) ((float)(x)) +# define FIXHR(x) ((float)(x)) +# define MULH3(x, y, s) ((s)*(y)*(x)) +# define MULLx(x, y, s) ((y)*(x)) +# define RENAME(a) a ## _float +# define OUT_FMT AV_SAMPLE_FMT_FLT +# define OUT_FMT_P AV_SAMPLE_FMT_FLTP +#else +# define SHR(a,b) ((a)>>(b)) +/* WARNING: only correct for positive numbers */ +# define FIXR_OLD(a) ((int)((a) * FRAC_ONE + 0.5)) +# define FIXR(a) ((int)((a) * FRAC_ONE + 0.5)) +# define FIXHR(a) ((int)((a) * (1LL<<32) + 0.5)) +# define MULH3(x, y, s) MULH((s)*(x), y) +# define MULLx(x, y, s) MULL(x,y,s) +# define RENAME(a) a ## _fixed +# define OUT_FMT AV_SAMPLE_FMT_S16 +# define OUT_FMT_P AV_SAMPLE_FMT_S16P +#endif + +/****************/ + +#define HEADER_SIZE 4 + +#include "mpegaudiodata.h" +#include "mpegaudiodectab.h" + +/* vlc structure for decoding layer 3 huffman tables */ +static VLC huff_vlc[16]; +static VLC_TYPE huff_vlc_tables[ + 0 + 128 + 128 + 128 + 130 + 128 + 154 + 166 + + 142 + 204 + 190 + 170 + 542 + 460 + 662 + 414 + ][2]; +static const int huff_vlc_tables_sizes[16] = { + 0, 128, 128, 128, 130, 128, 154, 166, + 142, 204, 190, 170, 542, 460, 662, 414 +}; +static VLC huff_quad_vlc[2]; +static VLC_TYPE huff_quad_vlc_tables[128+16][2]; +static const int huff_quad_vlc_tables_sizes[2] = { 128, 16 }; +/* computed from band_size_long */ +static uint16_t band_index_long[9][23]; +#include "mpegaudio_tablegen.h" +/* intensity stereo coef table */ +static INTFLOAT is_table[2][16]; +static INTFLOAT is_table_lsf[2][2][16]; +static INTFLOAT csa_table[8][4]; + +static int16_t division_tab3[1<<6 ]; +static int16_t division_tab5[1<<8 ]; +static int16_t division_tab9[1<<11]; + +static int16_t * const division_tabs[4] = { + division_tab3, division_tab5, NULL, division_tab9 +}; + +/* lower 2 bits: modulo 3, higher bits: shift */ +static uint16_t scale_factor_modshift[64]; +/* [i][j]: 2^(-j/3) * FRAC_ONE * 2^(i+2) / (2^(i+2) - 1) */ +static int32_t scale_factor_mult[15][3]; +/* mult table for layer 2 group quantization */ + +#define SCALE_GEN(v) \ +{ FIXR_OLD(1.0 * (v)), FIXR_OLD(0.7937005259 * (v)), FIXR_OLD(0.6299605249 * (v)) } + +static const int32_t scale_factor_mult2[3][3] = { + SCALE_GEN(4.0 / 3.0), /* 3 steps */ + SCALE_GEN(4.0 / 5.0), /* 5 steps */ + SCALE_GEN(4.0 / 9.0), /* 9 steps */ +}; + +/** + * Convert region offsets to region sizes and truncate + * size to big_values. + */ +static void ff_region_offset2size(GranuleDef *g) +{ + int i, k, j = 0; + g->region_size[2] = 576 / 2; + for (i = 0; i < 3; i++) { + k = FFMIN(g->region_size[i], g->big_values); + g->region_size[i] = k - j; + j = k; + } +} + +static void ff_init_short_region(MPADecodeContext *s, GranuleDef *g) +{ + if (g->block_type == 2) { + if (s->sample_rate_index != 8) + g->region_size[0] = (36 / 2); + else + g->region_size[0] = (72 / 2); + } else { + if (s->sample_rate_index <= 2) + g->region_size[0] = (36 / 2); + else if (s->sample_rate_index != 8) + g->region_size[0] = (54 / 2); + else + g->region_size[0] = (108 / 2); + } + g->region_size[1] = (576 / 2); +} + +static void ff_init_long_region(MPADecodeContext *s, GranuleDef *g, int ra1, int ra2) +{ + int l; + g->region_size[0] = band_index_long[s->sample_rate_index][ra1 + 1] >> 1; + /* should not overflow */ + l = FFMIN(ra1 + ra2 + 2, 22); + g->region_size[1] = band_index_long[s->sample_rate_index][ l] >> 1; +} + +static void ff_compute_band_indexes(MPADecodeContext *s, GranuleDef *g) +{ + if (g->block_type == 2) { + if (g->switch_point) { + if(s->sample_rate_index == 8) + avpriv_request_sample(s->avctx, "switch point in 8khz"); + /* if switched mode, we handle the 36 first samples as + long blocks. For 8000Hz, we handle the 72 first + exponents as long blocks */ + if (s->sample_rate_index <= 2) + g->long_end = 8; + else + g->long_end = 6; + + g->short_start = 3; + } else { + g->long_end = 0; + g->short_start = 0; + } + } else { + g->short_start = 13; + g->long_end = 22; + } +} + +/* layer 1 unscaling */ +/* n = number of bits of the mantissa minus 1 */ +static inline int l1_unscale(int n, int mant, int scale_factor) +{ + int shift, mod; + int64_t val; + + shift = scale_factor_modshift[scale_factor]; + mod = shift & 3; + shift >>= 2; + val = MUL64(mant + (-1 << n) + 1, scale_factor_mult[n-1][mod]); + shift += n; + /* NOTE: at this point, 1 <= shift >= 21 + 15 */ + return (int)((val + (1LL << (shift - 1))) >> shift); +} + +static inline int l2_unscale_group(int steps, int mant, int scale_factor) +{ + int shift, mod, val; + + shift = scale_factor_modshift[scale_factor]; + mod = shift & 3; + shift >>= 2; + + val = (mant - (steps >> 1)) * scale_factor_mult2[steps >> 2][mod]; + /* NOTE: at this point, 0 <= shift <= 21 */ + if (shift > 0) + val = (val + (1 << (shift - 1))) >> shift; + return val; +} + +/* compute value^(4/3) * 2^(exponent/4). It normalized to FRAC_BITS */ +static inline int l3_unscale(int value, int exponent) +{ + unsigned int m; + int e; + + e = table_4_3_exp [4 * value + (exponent & 3)]; + m = table_4_3_value[4 * value + (exponent & 3)]; + e -= exponent >> 2; +#ifdef DEBUG + if(e < 1) + av_log(NULL, AV_LOG_WARNING, "l3_unscale: e is %d\n", e); +#endif + if (e > 31) + return 0; + m = (m + (1 << (e - 1))) >> e; + + return m; +} + +static av_cold void decode_init_static(void) +{ + int i, j, k; + int offset; + + /* scale factors table for layer 1/2 */ + for (i = 0; i < 64; i++) { + int shift, mod; + /* 1.0 (i = 3) is normalized to 2 ^ FRAC_BITS */ + shift = i / 3; + mod = i % 3; + scale_factor_modshift[i] = mod | (shift << 2); + } + + /* scale factor multiply for layer 1 */ + for (i = 0; i < 15; i++) { + int n, norm; + n = i + 2; + norm = ((INT64_C(1) << n) * FRAC_ONE) / ((1 << n) - 1); + scale_factor_mult[i][0] = MULLx(norm, FIXR(1.0 * 2.0), FRAC_BITS); + scale_factor_mult[i][1] = MULLx(norm, FIXR(0.7937005259 * 2.0), FRAC_BITS); + scale_factor_mult[i][2] = MULLx(norm, FIXR(0.6299605249 * 2.0), FRAC_BITS); + av_dlog(NULL, "%d: norm=%x s=%x %x %x\n", i, norm, + scale_factor_mult[i][0], + scale_factor_mult[i][1], + scale_factor_mult[i][2]); + } + + RENAME(ff_mpa_synth_init)(RENAME(ff_mpa_synth_window)); + + /* huffman decode tables */ + offset = 0; + for (i = 1; i < 16; i++) { + const HuffTable *h = &mpa_huff_tables[i]; + int xsize, x, y; + uint8_t tmp_bits [512] = { 0 }; + uint16_t tmp_codes[512] = { 0 }; + + xsize = h->xsize; + + j = 0; + for (x = 0; x < xsize; x++) { + for (y = 0; y < xsize; y++) { + tmp_bits [(x << 5) | y | ((x&&y)<<4)]= h->bits [j ]; + tmp_codes[(x << 5) | y | ((x&&y)<<4)]= h->codes[j++]; + } + } + + /* XXX: fail test */ + huff_vlc[i].table = huff_vlc_tables+offset; + huff_vlc[i].table_allocated = huff_vlc_tables_sizes[i]; + init_vlc(&huff_vlc[i], 7, 512, + tmp_bits, 1, 1, tmp_codes, 2, 2, + INIT_VLC_USE_NEW_STATIC); + offset += huff_vlc_tables_sizes[i]; + } + av_assert0(offset == FF_ARRAY_ELEMS(huff_vlc_tables)); + + offset = 0; + for (i = 0; i < 2; i++) { + huff_quad_vlc[i].table = huff_quad_vlc_tables+offset; + huff_quad_vlc[i].table_allocated = huff_quad_vlc_tables_sizes[i]; + init_vlc(&huff_quad_vlc[i], i == 0 ? 7 : 4, 16, + mpa_quad_bits[i], 1, 1, mpa_quad_codes[i], 1, 1, + INIT_VLC_USE_NEW_STATIC); + offset += huff_quad_vlc_tables_sizes[i]; + } + av_assert0(offset == FF_ARRAY_ELEMS(huff_quad_vlc_tables)); + + for (i = 0; i < 9; i++) { + k = 0; + for (j = 0; j < 22; j++) { + band_index_long[i][j] = k; + k += band_size_long[i][j]; + } + band_index_long[i][22] = k; + } + + /* compute n ^ (4/3) and store it in mantissa/exp format */ + + mpegaudio_tableinit(); + + for (i = 0; i < 4; i++) { + if (ff_mpa_quant_bits[i] < 0) { + for (j = 0; j < (1 << (-ff_mpa_quant_bits[i]+1)); j++) { + int val1, val2, val3, steps; + int val = j; + steps = ff_mpa_quant_steps[i]; + val1 = val % steps; + val /= steps; + val2 = val % steps; + val3 = val / steps; + division_tabs[i][j] = val1 + (val2 << 4) + (val3 << 8); + } + } + } + + + for (i = 0; i < 7; i++) { + float f; + INTFLOAT v; + if (i != 6) { + f = tan((double)i * M_PI / 12.0); + v = FIXR(f / (1.0 + f)); + } else { + v = FIXR(1.0); + } + is_table[0][ i] = v; + is_table[1][6 - i] = v; + } + /* invalid values */ + for (i = 7; i < 16; i++) + is_table[0][i] = is_table[1][i] = 0.0; + + for (i = 0; i < 16; i++) { + double f; + int e, k; + + for (j = 0; j < 2; j++) { + e = -(j + 1) * ((i + 1) >> 1); + f = exp2(e / 4.0); + k = i & 1; + is_table_lsf[j][k ^ 1][i] = FIXR(f); + is_table_lsf[j][k ][i] = FIXR(1.0); + av_dlog(NULL, "is_table_lsf %d %d: %f %f\n", + i, j, (float) is_table_lsf[j][0][i], + (float) is_table_lsf[j][1][i]); + } + } + + for (i = 0; i < 8; i++) { + float ci, cs, ca; + ci = ci_table[i]; + cs = 1.0 / sqrt(1.0 + ci * ci); + ca = cs * ci; +#if !CONFIG_FLOAT + csa_table[i][0] = FIXHR(cs/4); + csa_table[i][1] = FIXHR(ca/4); + csa_table[i][2] = FIXHR(ca/4) + FIXHR(cs/4); + csa_table[i][3] = FIXHR(ca/4) - FIXHR(cs/4); +#else + csa_table[i][0] = cs; + csa_table[i][1] = ca; + csa_table[i][2] = ca + cs; + csa_table[i][3] = ca - cs; +#endif + } +} + +static av_cold int decode_init(AVCodecContext * avctx) +{ + static int initialized_tables = 0; + MPADecodeContext *s = avctx->priv_data; + + if (!initialized_tables) { + decode_init_static(); + initialized_tables = 1; + } + + s->avctx = avctx; + + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_mpadsp_init(&s->mpadsp); + + if (avctx->request_sample_fmt == OUT_FMT && + avctx->codec_id != AV_CODEC_ID_MP3ON4) + avctx->sample_fmt = OUT_FMT; + else + avctx->sample_fmt = OUT_FMT_P; + s->err_recognition = avctx->err_recognition; + + if (avctx->codec_id == AV_CODEC_ID_MP3ADU) + s->adu_mode = 1; + + return 0; +} + +#define C3 FIXHR(0.86602540378443864676/2) +#define C4 FIXHR(0.70710678118654752439/2) //0.5 / cos(pi*(9)/36) +#define C5 FIXHR(0.51763809020504152469/2) //0.5 / cos(pi*(5)/36) +#define C6 FIXHR(1.93185165257813657349/4) //0.5 / cos(pi*(15)/36) + +/* 12 points IMDCT. We compute it "by hand" by factorizing obvious + cases. */ +static void imdct12(INTFLOAT *out, INTFLOAT *in) +{ + INTFLOAT in0, in1, in2, in3, in4, in5, t1, t2; + + in0 = in[0*3]; + in1 = in[1*3] + in[0*3]; + in2 = in[2*3] + in[1*3]; + in3 = in[3*3] + in[2*3]; + in4 = in[4*3] + in[3*3]; + in5 = in[5*3] + in[4*3]; + in5 += in3; + in3 += in1; + + in2 = MULH3(in2, C3, 2); + in3 = MULH3(in3, C3, 4); + + t1 = in0 - in4; + t2 = MULH3(in1 - in5, C4, 2); + + out[ 7] = + out[10] = t1 + t2; + out[ 1] = + out[ 4] = t1 - t2; + + in0 += SHR(in4, 1); + in4 = in0 + in2; + in5 += 2*in1; + in1 = MULH3(in5 + in3, C5, 1); + out[ 8] = + out[ 9] = in4 + in1; + out[ 2] = + out[ 3] = in4 - in1; + + in0 -= in2; + in5 = MULH3(in5 - in3, C6, 2); + out[ 0] = + out[ 5] = in0 - in5; + out[ 6] = + out[11] = in0 + in5; +} + +/* return the number of decoded frames */ +static int mp_decode_layer1(MPADecodeContext *s) +{ + int bound, i, v, n, ch, j, mant; + uint8_t allocation[MPA_MAX_CHANNELS][SBLIMIT]; + uint8_t scale_factors[MPA_MAX_CHANNELS][SBLIMIT]; + + if (s->mode == MPA_JSTEREO) + bound = (s->mode_ext + 1) * 4; + else + bound = SBLIMIT; + + /* allocation bits */ + for (i = 0; i < bound; i++) { + for (ch = 0; ch < s->nb_channels; ch++) { + allocation[ch][i] = get_bits(&s->gb, 4); + } + } + for (i = bound; i < SBLIMIT; i++) + allocation[0][i] = get_bits(&s->gb, 4); + + /* scale factors */ + for (i = 0; i < bound; i++) { + for (ch = 0; ch < s->nb_channels; ch++) { + if (allocation[ch][i]) + scale_factors[ch][i] = get_bits(&s->gb, 6); + } + } + for (i = bound; i < SBLIMIT; i++) { + if (allocation[0][i]) { + scale_factors[0][i] = get_bits(&s->gb, 6); + scale_factors[1][i] = get_bits(&s->gb, 6); + } + } + + /* compute samples */ + for (j = 0; j < 12; j++) { + for (i = 0; i < bound; i++) { + for (ch = 0; ch < s->nb_channels; ch++) { + n = allocation[ch][i]; + if (n) { + mant = get_bits(&s->gb, n + 1); + v = l1_unscale(n, mant, scale_factors[ch][i]); + } else { + v = 0; + } + s->sb_samples[ch][j][i] = v; + } + } + for (i = bound; i < SBLIMIT; i++) { + n = allocation[0][i]; + if (n) { + mant = get_bits(&s->gb, n + 1); + v = l1_unscale(n, mant, scale_factors[0][i]); + s->sb_samples[0][j][i] = v; + v = l1_unscale(n, mant, scale_factors[1][i]); + s->sb_samples[1][j][i] = v; + } else { + s->sb_samples[0][j][i] = 0; + s->sb_samples[1][j][i] = 0; + } + } + } + return 12; +} + +static int mp_decode_layer2(MPADecodeContext *s) +{ + int sblimit; /* number of used subbands */ + const unsigned char *alloc_table; + int table, bit_alloc_bits, i, j, ch, bound, v; + unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3], *sf; + int scale, qindex, bits, steps, k, l, m, b; + + /* select decoding table */ + table = ff_mpa_l2_select_table(s->bit_rate / 1000, s->nb_channels, + s->sample_rate, s->lsf); + sblimit = ff_mpa_sblimit_table[table]; + alloc_table = ff_mpa_alloc_tables[table]; + + if (s->mode == MPA_JSTEREO) + bound = (s->mode_ext + 1) * 4; + else + bound = sblimit; + + av_dlog(s->avctx, "bound=%d sblimit=%d\n", bound, sblimit); + + /* sanity check */ + if (bound > sblimit) + bound = sblimit; + + /* parse bit allocation */ + j = 0; + for (i = 0; i < bound; i++) { + bit_alloc_bits = alloc_table[j]; + for (ch = 0; ch < s->nb_channels; ch++) + bit_alloc[ch][i] = get_bits(&s->gb, bit_alloc_bits); + j += 1 << bit_alloc_bits; + } + for (i = bound; i < sblimit; i++) { + bit_alloc_bits = alloc_table[j]; + v = get_bits(&s->gb, bit_alloc_bits); + bit_alloc[0][i] = v; + bit_alloc[1][i] = v; + j += 1 << bit_alloc_bits; + } + + /* scale codes */ + for (i = 0; i < sblimit; i++) { + for (ch = 0; ch < s->nb_channels; ch++) { + if (bit_alloc[ch][i]) + scale_code[ch][i] = get_bits(&s->gb, 2); + } + } + + /* scale factors */ + for (i = 0; i < sblimit; i++) { + for (ch = 0; ch < s->nb_channels; ch++) { + if (bit_alloc[ch][i]) { + sf = scale_factors[ch][i]; + switch (scale_code[ch][i]) { + default: + case 0: + sf[0] = get_bits(&s->gb, 6); + sf[1] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + break; + case 2: + sf[0] = get_bits(&s->gb, 6); + sf[1] = sf[0]; + sf[2] = sf[0]; + break; + case 1: + sf[0] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + sf[1] = sf[0]; + break; + case 3: + sf[0] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + sf[1] = sf[2]; + break; + } + } + } + } + + /* samples */ + for (k = 0; k < 3; k++) { + for (l = 0; l < 12; l += 3) { + j = 0; + for (i = 0; i < bound; i++) { + bit_alloc_bits = alloc_table[j]; + for (ch = 0; ch < s->nb_channels; ch++) { + b = bit_alloc[ch][i]; + if (b) { + scale = scale_factors[ch][i][k]; + qindex = alloc_table[j+b]; + bits = ff_mpa_quant_bits[qindex]; + if (bits < 0) { + int v2; + /* 3 values at the same time */ + v = get_bits(&s->gb, -bits); + v2 = division_tabs[qindex][v]; + steps = ff_mpa_quant_steps[qindex]; + + s->sb_samples[ch][k * 12 + l + 0][i] = + l2_unscale_group(steps, v2 & 15, scale); + s->sb_samples[ch][k * 12 + l + 1][i] = + l2_unscale_group(steps, (v2 >> 4) & 15, scale); + s->sb_samples[ch][k * 12 + l + 2][i] = + l2_unscale_group(steps, v2 >> 8 , scale); + } else { + for (m = 0; m < 3; m++) { + v = get_bits(&s->gb, bits); + v = l1_unscale(bits - 1, v, scale); + s->sb_samples[ch][k * 12 + l + m][i] = v; + } + } + } else { + s->sb_samples[ch][k * 12 + l + 0][i] = 0; + s->sb_samples[ch][k * 12 + l + 1][i] = 0; + s->sb_samples[ch][k * 12 + l + 2][i] = 0; + } + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + /* XXX: find a way to avoid this duplication of code */ + for (i = bound; i < sblimit; i++) { + bit_alloc_bits = alloc_table[j]; + b = bit_alloc[0][i]; + if (b) { + int mant, scale0, scale1; + scale0 = scale_factors[0][i][k]; + scale1 = scale_factors[1][i][k]; + qindex = alloc_table[j+b]; + bits = ff_mpa_quant_bits[qindex]; + if (bits < 0) { + /* 3 values at the same time */ + v = get_bits(&s->gb, -bits); + steps = ff_mpa_quant_steps[qindex]; + mant = v % steps; + v = v / steps; + s->sb_samples[0][k * 12 + l + 0][i] = + l2_unscale_group(steps, mant, scale0); + s->sb_samples[1][k * 12 + l + 0][i] = + l2_unscale_group(steps, mant, scale1); + mant = v % steps; + v = v / steps; + s->sb_samples[0][k * 12 + l + 1][i] = + l2_unscale_group(steps, mant, scale0); + s->sb_samples[1][k * 12 + l + 1][i] = + l2_unscale_group(steps, mant, scale1); + s->sb_samples[0][k * 12 + l + 2][i] = + l2_unscale_group(steps, v, scale0); + s->sb_samples[1][k * 12 + l + 2][i] = + l2_unscale_group(steps, v, scale1); + } else { + for (m = 0; m < 3; m++) { + mant = get_bits(&s->gb, bits); + s->sb_samples[0][k * 12 + l + m][i] = + l1_unscale(bits - 1, mant, scale0); + s->sb_samples[1][k * 12 + l + m][i] = + l1_unscale(bits - 1, mant, scale1); + } + } + } else { + s->sb_samples[0][k * 12 + l + 0][i] = 0; + s->sb_samples[0][k * 12 + l + 1][i] = 0; + s->sb_samples[0][k * 12 + l + 2][i] = 0; + s->sb_samples[1][k * 12 + l + 0][i] = 0; + s->sb_samples[1][k * 12 + l + 1][i] = 0; + s->sb_samples[1][k * 12 + l + 2][i] = 0; + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + /* fill remaining samples to zero */ + for (i = sblimit; i < SBLIMIT; i++) { + for (ch = 0; ch < s->nb_channels; ch++) { + s->sb_samples[ch][k * 12 + l + 0][i] = 0; + s->sb_samples[ch][k * 12 + l + 1][i] = 0; + s->sb_samples[ch][k * 12 + l + 2][i] = 0; + } + } + } + } + return 3 * 12; +} + +#define SPLIT(dst,sf,n) \ + if (n == 3) { \ + int m = (sf * 171) >> 9; \ + dst = sf - 3 * m; \ + sf = m; \ + } else if (n == 4) { \ + dst = sf & 3; \ + sf >>= 2; \ + } else if (n == 5) { \ + int m = (sf * 205) >> 10; \ + dst = sf - 5 * m; \ + sf = m; \ + } else if (n == 6) { \ + int m = (sf * 171) >> 10; \ + dst = sf - 6 * m; \ + sf = m; \ + } else { \ + dst = 0; \ + } + +static av_always_inline void lsf_sf_expand(int *slen, int sf, int n1, int n2, + int n3) +{ + SPLIT(slen[3], sf, n3) + SPLIT(slen[2], sf, n2) + SPLIT(slen[1], sf, n1) + slen[0] = sf; +} + +static void exponents_from_scale_factors(MPADecodeContext *s, GranuleDef *g, + int16_t *exponents) +{ + const uint8_t *bstab, *pretab; + int len, i, j, k, l, v0, shift, gain, gains[3]; + int16_t *exp_ptr; + + exp_ptr = exponents; + gain = g->global_gain - 210; + shift = g->scalefac_scale + 1; + + bstab = band_size_long[s->sample_rate_index]; + pretab = mpa_pretab[g->preflag]; + for (i = 0; i < g->long_end; i++) { + v0 = gain - ((g->scale_factors[i] + pretab[i]) << shift) + 400; + len = bstab[i]; + for (j = len; j > 0; j--) + *exp_ptr++ = v0; + } + + if (g->short_start < 13) { + bstab = band_size_short[s->sample_rate_index]; + gains[0] = gain - (g->subblock_gain[0] << 3); + gains[1] = gain - (g->subblock_gain[1] << 3); + gains[2] = gain - (g->subblock_gain[2] << 3); + k = g->long_end; + for (i = g->short_start; i < 13; i++) { + len = bstab[i]; + for (l = 0; l < 3; l++) { + v0 = gains[l] - (g->scale_factors[k++] << shift) + 400; + for (j = len; j > 0; j--) + *exp_ptr++ = v0; + } + } + } +} + +/* handle n = 0 too */ +static inline int get_bitsz(GetBitContext *s, int n) +{ + return n ? get_bits(s, n) : 0; +} + + +static void switch_buffer(MPADecodeContext *s, int *pos, int *end_pos, + int *end_pos2) +{ + if (s->in_gb.buffer && *pos >= s->gb.size_in_bits) { + s->gb = s->in_gb; + s->in_gb.buffer = NULL; + av_assert2((get_bits_count(&s->gb) & 7) == 0); + skip_bits_long(&s->gb, *pos - *end_pos); + *end_pos2 = + *end_pos = *end_pos2 + get_bits_count(&s->gb) - *pos; + *pos = get_bits_count(&s->gb); + } +} + +/* Following is a optimized code for + INTFLOAT v = *src + if(get_bits1(&s->gb)) + v = -v; + *dst = v; +*/ +#if CONFIG_FLOAT +#define READ_FLIP_SIGN(dst,src) \ + v = AV_RN32A(src) ^ (get_bits1(&s->gb) << 31); \ + AV_WN32A(dst, v); +#else +#define READ_FLIP_SIGN(dst,src) \ + v = -get_bits1(&s->gb); \ + *(dst) = (*(src) ^ v) - v; +#endif + +static int huffman_decode(MPADecodeContext *s, GranuleDef *g, + int16_t *exponents, int end_pos2) +{ + int s_index; + int i; + int last_pos, bits_left; + VLC *vlc; + int end_pos = FFMIN(end_pos2, s->gb.size_in_bits); + + /* low frequencies (called big values) */ + s_index = 0; + for (i = 0; i < 3; i++) { + int j, k, l, linbits; + j = g->region_size[i]; + if (j == 0) + continue; + /* select vlc table */ + k = g->table_select[i]; + l = mpa_huff_data[k][0]; + linbits = mpa_huff_data[k][1]; + vlc = &huff_vlc[l]; + + if (!l) { + memset(&g->sb_hybrid[s_index], 0, sizeof(*g->sb_hybrid) * 2 * j); + s_index += 2 * j; + continue; + } + + /* read huffcode and compute each couple */ + for (; j > 0; j--) { + int exponent, x, y; + int v; + int pos = get_bits_count(&s->gb); + + if (pos >= end_pos){ + switch_buffer(s, &pos, &end_pos, &end_pos2); + if (pos >= end_pos) + break; + } + y = get_vlc2(&s->gb, vlc->table, 7, 3); + + if (!y) { + g->sb_hybrid[s_index ] = + g->sb_hybrid[s_index+1] = 0; + s_index += 2; + continue; + } + + exponent= exponents[s_index]; + + av_dlog(s->avctx, "region=%d n=%d x=%d y=%d exp=%d\n", + i, g->region_size[i] - j, x, y, exponent); + if (y & 16) { + x = y >> 5; + y = y & 0x0f; + if (x < 15) { + READ_FLIP_SIGN(g->sb_hybrid + s_index, RENAME(expval_table)[exponent] + x) + } else { + x += get_bitsz(&s->gb, linbits); + v = l3_unscale(x, exponent); + if (get_bits1(&s->gb)) + v = -v; + g->sb_hybrid[s_index] = v; + } + if (y < 15) { + READ_FLIP_SIGN(g->sb_hybrid + s_index + 1, RENAME(expval_table)[exponent] + y) + } else { + y += get_bitsz(&s->gb, linbits); + v = l3_unscale(y, exponent); + if (get_bits1(&s->gb)) + v = -v; + g->sb_hybrid[s_index+1] = v; + } + } else { + x = y >> 5; + y = y & 0x0f; + x += y; + if (x < 15) { + READ_FLIP_SIGN(g->sb_hybrid + s_index + !!y, RENAME(expval_table)[exponent] + x) + } else { + x += get_bitsz(&s->gb, linbits); + v = l3_unscale(x, exponent); + if (get_bits1(&s->gb)) + v = -v; + g->sb_hybrid[s_index+!!y] = v; + } + g->sb_hybrid[s_index + !y] = 0; + } + s_index += 2; + } + } + + /* high frequencies */ + vlc = &huff_quad_vlc[g->count1table_select]; + last_pos = 0; + while (s_index <= 572) { + int pos, code; + pos = get_bits_count(&s->gb); + if (pos >= end_pos) { + if (pos > end_pos2 && last_pos) { + /* some encoders generate an incorrect size for this + part. We must go back into the data */ + s_index -= 4; + skip_bits_long(&s->gb, last_pos - pos); + av_log(s->avctx, AV_LOG_INFO, "overread, skip %d enddists: %d %d\n", last_pos - pos, end_pos-pos, end_pos2-pos); + if(s->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT)) + s_index=0; + break; + } + switch_buffer(s, &pos, &end_pos, &end_pos2); + if (pos >= end_pos) + break; + } + last_pos = pos; + + code = get_vlc2(&s->gb, vlc->table, vlc->bits, 1); + av_dlog(s->avctx, "t=%d code=%d\n", g->count1table_select, code); + g->sb_hybrid[s_index+0] = + g->sb_hybrid[s_index+1] = + g->sb_hybrid[s_index+2] = + g->sb_hybrid[s_index+3] = 0; + while (code) { + static const int idxtab[16] = { 3,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0 }; + int v; + int pos = s_index + idxtab[code]; + code ^= 8 >> idxtab[code]; + READ_FLIP_SIGN(g->sb_hybrid + pos, RENAME(exp_table)+exponents[pos]) + } + s_index += 4; + } + /* skip extension bits */ + bits_left = end_pos2 - get_bits_count(&s->gb); + if (bits_left < 0 && (s->err_recognition & (AV_EF_BUFFER|AV_EF_COMPLIANT))) { + av_log(s->avctx, AV_LOG_ERROR, "bits_left=%d\n", bits_left); + s_index=0; + } else if (bits_left > 0 && (s->err_recognition & (AV_EF_BUFFER|AV_EF_AGGRESSIVE))) { + av_log(s->avctx, AV_LOG_ERROR, "bits_left=%d\n", bits_left); + s_index = 0; + } + memset(&g->sb_hybrid[s_index], 0, sizeof(*g->sb_hybrid) * (576 - s_index)); + skip_bits_long(&s->gb, bits_left); + + i = get_bits_count(&s->gb); + switch_buffer(s, &i, &end_pos, &end_pos2); + + return 0; +} + +/* Reorder short blocks from bitstream order to interleaved order. It + would be faster to do it in parsing, but the code would be far more + complicated */ +static void reorder_block(MPADecodeContext *s, GranuleDef *g) +{ + int i, j, len; + INTFLOAT *ptr, *dst, *ptr1; + INTFLOAT tmp[576]; + + if (g->block_type != 2) + return; + + if (g->switch_point) { + if (s->sample_rate_index != 8) + ptr = g->sb_hybrid + 36; + else + ptr = g->sb_hybrid + 72; + } else { + ptr = g->sb_hybrid; + } + + for (i = g->short_start; i < 13; i++) { + len = band_size_short[s->sample_rate_index][i]; + ptr1 = ptr; + dst = tmp; + for (j = len; j > 0; j--) { + *dst++ = ptr[0*len]; + *dst++ = ptr[1*len]; + *dst++ = ptr[2*len]; + ptr++; + } + ptr += 2 * len; + memcpy(ptr1, tmp, len * 3 * sizeof(*ptr1)); + } +} + +#define ISQRT2 FIXR(0.70710678118654752440) + +static void compute_stereo(MPADecodeContext *s, GranuleDef *g0, GranuleDef *g1) +{ + int i, j, k, l; + int sf_max, sf, len, non_zero_found; + INTFLOAT (*is_tab)[16], *tab0, *tab1, tmp0, tmp1, v1, v2; + int non_zero_found_short[3]; + + /* intensity stereo */ + if (s->mode_ext & MODE_EXT_I_STEREO) { + if (!s->lsf) { + is_tab = is_table; + sf_max = 7; + } else { + is_tab = is_table_lsf[g1->scalefac_compress & 1]; + sf_max = 16; + } + + tab0 = g0->sb_hybrid + 576; + tab1 = g1->sb_hybrid + 576; + + non_zero_found_short[0] = 0; + non_zero_found_short[1] = 0; + non_zero_found_short[2] = 0; + k = (13 - g1->short_start) * 3 + g1->long_end - 3; + for (i = 12; i >= g1->short_start; i--) { + /* for last band, use previous scale factor */ + if (i != 11) + k -= 3; + len = band_size_short[s->sample_rate_index][i]; + for (l = 2; l >= 0; l--) { + tab0 -= len; + tab1 -= len; + if (!non_zero_found_short[l]) { + /* test if non zero band. if so, stop doing i-stereo */ + for (j = 0; j < len; j++) { + if (tab1[j] != 0) { + non_zero_found_short[l] = 1; + goto found1; + } + } + sf = g1->scale_factors[k + l]; + if (sf >= sf_max) + goto found1; + + v1 = is_tab[0][sf]; + v2 = is_tab[1][sf]; + for (j = 0; j < len; j++) { + tmp0 = tab0[j]; + tab0[j] = MULLx(tmp0, v1, FRAC_BITS); + tab1[j] = MULLx(tmp0, v2, FRAC_BITS); + } + } else { +found1: + if (s->mode_ext & MODE_EXT_MS_STEREO) { + /* lower part of the spectrum : do ms stereo + if enabled */ + for (j = 0; j < len; j++) { + tmp0 = tab0[j]; + tmp1 = tab1[j]; + tab0[j] = MULLx(tmp0 + tmp1, ISQRT2, FRAC_BITS); + tab1[j] = MULLx(tmp0 - tmp1, ISQRT2, FRAC_BITS); + } + } + } + } + } + + non_zero_found = non_zero_found_short[0] | + non_zero_found_short[1] | + non_zero_found_short[2]; + + for (i = g1->long_end - 1;i >= 0;i--) { + len = band_size_long[s->sample_rate_index][i]; + tab0 -= len; + tab1 -= len; + /* test if non zero band. if so, stop doing i-stereo */ + if (!non_zero_found) { + for (j = 0; j < len; j++) { + if (tab1[j] != 0) { + non_zero_found = 1; + goto found2; + } + } + /* for last band, use previous scale factor */ + k = (i == 21) ? 20 : i; + sf = g1->scale_factors[k]; + if (sf >= sf_max) + goto found2; + v1 = is_tab[0][sf]; + v2 = is_tab[1][sf]; + for (j = 0; j < len; j++) { + tmp0 = tab0[j]; + tab0[j] = MULLx(tmp0, v1, FRAC_BITS); + tab1[j] = MULLx(tmp0, v2, FRAC_BITS); + } + } else { +found2: + if (s->mode_ext & MODE_EXT_MS_STEREO) { + /* lower part of the spectrum : do ms stereo + if enabled */ + for (j = 0; j < len; j++) { + tmp0 = tab0[j]; + tmp1 = tab1[j]; + tab0[j] = MULLx(tmp0 + tmp1, ISQRT2, FRAC_BITS); + tab1[j] = MULLx(tmp0 - tmp1, ISQRT2, FRAC_BITS); + } + } + } + } + } else if (s->mode_ext & MODE_EXT_MS_STEREO) { + /* ms stereo ONLY */ + /* NOTE: the 1/sqrt(2) normalization factor is included in the + global gain */ +#if CONFIG_FLOAT + s->fdsp.butterflies_float(g0->sb_hybrid, g1->sb_hybrid, 576); +#else + tab0 = g0->sb_hybrid; + tab1 = g1->sb_hybrid; + for (i = 0; i < 576; i++) { + tmp0 = tab0[i]; + tmp1 = tab1[i]; + tab0[i] = tmp0 + tmp1; + tab1[i] = tmp0 - tmp1; + } +#endif + } +} + +#if CONFIG_FLOAT +#if HAVE_MIPSFPU +# include "mips/compute_antialias_float.h" +#endif /* HAVE_MIPSFPU */ +#else +#if HAVE_MIPSDSPR1 +# include "mips/compute_antialias_fixed.h" +#endif /* HAVE_MIPSDSPR1 */ +#endif /* CONFIG_FLOAT */ + +#ifndef compute_antialias +#if CONFIG_FLOAT +#define AA(j) do { \ + float tmp0 = ptr[-1-j]; \ + float tmp1 = ptr[ j]; \ + ptr[-1-j] = tmp0 * csa_table[j][0] - tmp1 * csa_table[j][1]; \ + ptr[ j] = tmp0 * csa_table[j][1] + tmp1 * csa_table[j][0]; \ + } while (0) +#else +#define AA(j) do { \ + int tmp0 = ptr[-1-j]; \ + int tmp1 = ptr[ j]; \ + int tmp2 = MULH(tmp0 + tmp1, csa_table[j][0]); \ + ptr[-1-j] = 4 * (tmp2 - MULH(tmp1, csa_table[j][2])); \ + ptr[ j] = 4 * (tmp2 + MULH(tmp0, csa_table[j][3])); \ + } while (0) +#endif + +static void compute_antialias(MPADecodeContext *s, GranuleDef *g) +{ + INTFLOAT *ptr; + int n, i; + + /* we antialias only "long" bands */ + if (g->block_type == 2) { + if (!g->switch_point) + return; + /* XXX: check this for 8000Hz case */ + n = 1; + } else { + n = SBLIMIT - 1; + } + + ptr = g->sb_hybrid + 18; + for (i = n; i > 0; i--) { + AA(0); + AA(1); + AA(2); + AA(3); + AA(4); + AA(5); + AA(6); + AA(7); + + ptr += 18; + } +} +#endif /* compute_antialias */ + +static void compute_imdct(MPADecodeContext *s, GranuleDef *g, + INTFLOAT *sb_samples, INTFLOAT *mdct_buf) +{ + INTFLOAT *win, *out_ptr, *ptr, *buf, *ptr1; + INTFLOAT out2[12]; + int i, j, mdct_long_end, sblimit; + + /* find last non zero block */ + ptr = g->sb_hybrid + 576; + ptr1 = g->sb_hybrid + 2 * 18; + while (ptr >= ptr1) { + int32_t *p; + ptr -= 6; + p = (int32_t*)ptr; + if (p[0] | p[1] | p[2] | p[3] | p[4] | p[5]) + break; + } + sblimit = ((ptr - g->sb_hybrid) / 18) + 1; + + if (g->block_type == 2) { + /* XXX: check for 8000 Hz */ + if (g->switch_point) + mdct_long_end = 2; + else + mdct_long_end = 0; + } else { + mdct_long_end = sblimit; + } + + s->mpadsp.RENAME(imdct36_blocks)(sb_samples, mdct_buf, g->sb_hybrid, + mdct_long_end, g->switch_point, + g->block_type); + + buf = mdct_buf + 4*18*(mdct_long_end >> 2) + (mdct_long_end & 3); + ptr = g->sb_hybrid + 18 * mdct_long_end; + + for (j = mdct_long_end; j < sblimit; j++) { + /* select frequency inversion */ + win = RENAME(ff_mdct_win)[2 + (4 & -(j & 1))]; + out_ptr = sb_samples + j; + + for (i = 0; i < 6; i++) { + *out_ptr = buf[4*i]; + out_ptr += SBLIMIT; + } + imdct12(out2, ptr + 0); + for (i = 0; i < 6; i++) { + *out_ptr = MULH3(out2[i ], win[i ], 1) + buf[4*(i + 6*1)]; + buf[4*(i + 6*2)] = MULH3(out2[i + 6], win[i + 6], 1); + out_ptr += SBLIMIT; + } + imdct12(out2, ptr + 1); + for (i = 0; i < 6; i++) { + *out_ptr = MULH3(out2[i ], win[i ], 1) + buf[4*(i + 6*2)]; + buf[4*(i + 6*0)] = MULH3(out2[i + 6], win[i + 6], 1); + out_ptr += SBLIMIT; + } + imdct12(out2, ptr + 2); + for (i = 0; i < 6; i++) { + buf[4*(i + 6*0)] = MULH3(out2[i ], win[i ], 1) + buf[4*(i + 6*0)]; + buf[4*(i + 6*1)] = MULH3(out2[i + 6], win[i + 6], 1); + buf[4*(i + 6*2)] = 0; + } + ptr += 18; + buf += (j&3) != 3 ? 1 : (4*18-3); + } + /* zero bands */ + for (j = sblimit; j < SBLIMIT; j++) { + /* overlap */ + out_ptr = sb_samples + j; + for (i = 0; i < 18; i++) { + *out_ptr = buf[4*i]; + buf[4*i] = 0; + out_ptr += SBLIMIT; + } + buf += (j&3) != 3 ? 1 : (4*18-3); + } +} + +/* main layer3 decoding function */ +static int mp_decode_layer3(MPADecodeContext *s) +{ + int nb_granules, main_data_begin; + int gr, ch, blocksplit_flag, i, j, k, n, bits_pos; + GranuleDef *g; + int16_t exponents[576]; //FIXME try INTFLOAT + + /* read side info */ + if (s->lsf) { + main_data_begin = get_bits(&s->gb, 8); + skip_bits(&s->gb, s->nb_channels); + nb_granules = 1; + } else { + main_data_begin = get_bits(&s->gb, 9); + if (s->nb_channels == 2) + skip_bits(&s->gb, 3); + else + skip_bits(&s->gb, 5); + nb_granules = 2; + for (ch = 0; ch < s->nb_channels; ch++) { + s->granules[ch][0].scfsi = 0;/* all scale factors are transmitted */ + s->granules[ch][1].scfsi = get_bits(&s->gb, 4); + } + } + + for (gr = 0; gr < nb_granules; gr++) { + for (ch = 0; ch < s->nb_channels; ch++) { + av_dlog(s->avctx, "gr=%d ch=%d: side_info\n", gr, ch); + g = &s->granules[ch][gr]; + g->part2_3_length = get_bits(&s->gb, 12); + g->big_values = get_bits(&s->gb, 9); + if (g->big_values > 288) { + av_log(s->avctx, AV_LOG_ERROR, "big_values too big\n"); + return AVERROR_INVALIDDATA; + } + + g->global_gain = get_bits(&s->gb, 8); + /* if MS stereo only is selected, we precompute the + 1/sqrt(2) renormalization factor */ + if ((s->mode_ext & (MODE_EXT_MS_STEREO | MODE_EXT_I_STEREO)) == + MODE_EXT_MS_STEREO) + g->global_gain -= 2; + if (s->lsf) + g->scalefac_compress = get_bits(&s->gb, 9); + else + g->scalefac_compress = get_bits(&s->gb, 4); + blocksplit_flag = get_bits1(&s->gb); + if (blocksplit_flag) { + g->block_type = get_bits(&s->gb, 2); + if (g->block_type == 0) { + av_log(s->avctx, AV_LOG_ERROR, "invalid block type\n"); + return AVERROR_INVALIDDATA; + } + g->switch_point = get_bits1(&s->gb); + for (i = 0; i < 2; i++) + g->table_select[i] = get_bits(&s->gb, 5); + for (i = 0; i < 3; i++) + g->subblock_gain[i] = get_bits(&s->gb, 3); + ff_init_short_region(s, g); + } else { + int region_address1, region_address2; + g->block_type = 0; + g->switch_point = 0; + for (i = 0; i < 3; i++) + g->table_select[i] = get_bits(&s->gb, 5); + /* compute huffman coded region sizes */ + region_address1 = get_bits(&s->gb, 4); + region_address2 = get_bits(&s->gb, 3); + av_dlog(s->avctx, "region1=%d region2=%d\n", + region_address1, region_address2); + ff_init_long_region(s, g, region_address1, region_address2); + } + ff_region_offset2size(g); + ff_compute_band_indexes(s, g); + + g->preflag = 0; + if (!s->lsf) + g->preflag = get_bits1(&s->gb); + g->scalefac_scale = get_bits1(&s->gb); + g->count1table_select = get_bits1(&s->gb); + av_dlog(s->avctx, "block_type=%d switch_point=%d\n", + g->block_type, g->switch_point); + } + } + + if (!s->adu_mode) { + int skip; + const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3); + int extrasize = av_clip(get_bits_left(&s->gb) >> 3, 0, EXTRABYTES); + av_assert1((get_bits_count(&s->gb) & 7) == 0); + /* now we get bits from the main_data_begin offset */ + av_dlog(s->avctx, "seekback:%d, lastbuf:%d\n", + main_data_begin, s->last_buf_size); + + memcpy(s->last_buf + s->last_buf_size, ptr, extrasize); + s->in_gb = s->gb; + init_get_bits(&s->gb, s->last_buf, s->last_buf_size*8); +#if !UNCHECKED_BITSTREAM_READER + s->gb.size_in_bits_plus8 += FFMAX(extrasize, LAST_BUF_SIZE - s->last_buf_size) * 8; +#endif + s->last_buf_size <<= 3; + for (gr = 0; gr < nb_granules && (s->last_buf_size >> 3) < main_data_begin; gr++) { + for (ch = 0; ch < s->nb_channels; ch++) { + g = &s->granules[ch][gr]; + s->last_buf_size += g->part2_3_length; + memset(g->sb_hybrid, 0, sizeof(g->sb_hybrid)); + compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]); + } + } + skip = s->last_buf_size - 8 * main_data_begin; + if (skip >= s->gb.size_in_bits && s->in_gb.buffer) { + skip_bits_long(&s->in_gb, skip - s->gb.size_in_bits); + s->gb = s->in_gb; + s->in_gb.buffer = NULL; + } else { + skip_bits_long(&s->gb, skip); + } + } else { + gr = 0; + } + + for (; gr < nb_granules; gr++) { + for (ch = 0; ch < s->nb_channels; ch++) { + g = &s->granules[ch][gr]; + bits_pos = get_bits_count(&s->gb); + + if (!s->lsf) { + uint8_t *sc; + int slen, slen1, slen2; + + /* MPEG1 scale factors */ + slen1 = slen_table[0][g->scalefac_compress]; + slen2 = slen_table[1][g->scalefac_compress]; + av_dlog(s->avctx, "slen1=%d slen2=%d\n", slen1, slen2); + if (g->block_type == 2) { + n = g->switch_point ? 17 : 18; + j = 0; + if (slen1) { + for (i = 0; i < n; i++) + g->scale_factors[j++] = get_bits(&s->gb, slen1); + } else { + for (i = 0; i < n; i++) + g->scale_factors[j++] = 0; + } + if (slen2) { + for (i = 0; i < 18; i++) + g->scale_factors[j++] = get_bits(&s->gb, slen2); + for (i = 0; i < 3; i++) + g->scale_factors[j++] = 0; + } else { + for (i = 0; i < 21; i++) + g->scale_factors[j++] = 0; + } + } else { + sc = s->granules[ch][0].scale_factors; + j = 0; + for (k = 0; k < 4; k++) { + n = k == 0 ? 6 : 5; + if ((g->scfsi & (0x8 >> k)) == 0) { + slen = (k < 2) ? slen1 : slen2; + if (slen) { + for (i = 0; i < n; i++) + g->scale_factors[j++] = get_bits(&s->gb, slen); + } else { + for (i = 0; i < n; i++) + g->scale_factors[j++] = 0; + } + } else { + /* simply copy from last granule */ + for (i = 0; i < n; i++) { + g->scale_factors[j] = sc[j]; + j++; + } + } + } + g->scale_factors[j++] = 0; + } + } else { + int tindex, tindex2, slen[4], sl, sf; + + /* LSF scale factors */ + if (g->block_type == 2) + tindex = g->switch_point ? 2 : 1; + else + tindex = 0; + + sf = g->scalefac_compress; + if ((s->mode_ext & MODE_EXT_I_STEREO) && ch == 1) { + /* intensity stereo case */ + sf >>= 1; + if (sf < 180) { + lsf_sf_expand(slen, sf, 6, 6, 0); + tindex2 = 3; + } else if (sf < 244) { + lsf_sf_expand(slen, sf - 180, 4, 4, 0); + tindex2 = 4; + } else { + lsf_sf_expand(slen, sf - 244, 3, 0, 0); + tindex2 = 5; + } + } else { + /* normal case */ + if (sf < 400) { + lsf_sf_expand(slen, sf, 5, 4, 4); + tindex2 = 0; + } else if (sf < 500) { + lsf_sf_expand(slen, sf - 400, 5, 4, 0); + tindex2 = 1; + } else { + lsf_sf_expand(slen, sf - 500, 3, 0, 0); + tindex2 = 2; + g->preflag = 1; + } + } + + j = 0; + for (k = 0; k < 4; k++) { + n = lsf_nsf_table[tindex2][tindex][k]; + sl = slen[k]; + if (sl) { + for (i = 0; i < n; i++) + g->scale_factors[j++] = get_bits(&s->gb, sl); + } else { + for (i = 0; i < n; i++) + g->scale_factors[j++] = 0; + } + } + /* XXX: should compute exact size */ + for (; j < 40; j++) + g->scale_factors[j] = 0; + } + + exponents_from_scale_factors(s, g, exponents); + + /* read Huffman coded residue */ + huffman_decode(s, g, exponents, bits_pos + g->part2_3_length); + } /* ch */ + + if (s->mode == MPA_JSTEREO) + compute_stereo(s, &s->granules[0][gr], &s->granules[1][gr]); + + for (ch = 0; ch < s->nb_channels; ch++) { + g = &s->granules[ch][gr]; + + reorder_block(s, g); + compute_antialias(s, g); + compute_imdct(s, g, &s->sb_samples[ch][18 * gr][0], s->mdct_buf[ch]); + } + } /* gr */ + if (get_bits_count(&s->gb) < 0) + skip_bits_long(&s->gb, -get_bits_count(&s->gb)); + return nb_granules * 18; +} + +static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples, + const uint8_t *buf, int buf_size) +{ + int i, nb_frames, ch, ret; + OUT_INT *samples_ptr; + + init_get_bits(&s->gb, buf + HEADER_SIZE, (buf_size - HEADER_SIZE) * 8); + + /* skip error protection field */ + if (s->error_protection) + skip_bits(&s->gb, 16); + + switch(s->layer) { + case 1: + s->avctx->frame_size = 384; + nb_frames = mp_decode_layer1(s); + break; + case 2: + s->avctx->frame_size = 1152; + nb_frames = mp_decode_layer2(s); + break; + case 3: + s->avctx->frame_size = s->lsf ? 576 : 1152; + default: + nb_frames = mp_decode_layer3(s); + + s->last_buf_size=0; + if (s->in_gb.buffer) { + align_get_bits(&s->gb); + i = get_bits_left(&s->gb)>>3; + if (i >= 0 && i <= BACKSTEP_SIZE) { + memmove(s->last_buf, s->gb.buffer + (get_bits_count(&s->gb)>>3), i); + s->last_buf_size=i; + } else + av_log(s->avctx, AV_LOG_ERROR, "invalid old backstep %d\n", i); + s->gb = s->in_gb; + s->in_gb.buffer = NULL; + } + + align_get_bits(&s->gb); + av_assert1((get_bits_count(&s->gb) & 7) == 0); + i = get_bits_left(&s->gb) >> 3; + + if (i < 0 || i > BACKSTEP_SIZE || nb_frames < 0) { + if (i < 0) + av_log(s->avctx, AV_LOG_ERROR, "invalid new backstep %d\n", i); + i = FFMIN(BACKSTEP_SIZE, buf_size - HEADER_SIZE); + } + av_assert1(i <= buf_size - HEADER_SIZE && i >= 0); + memcpy(s->last_buf + s->last_buf_size, s->gb.buffer + buf_size - HEADER_SIZE - i, i); + s->last_buf_size += i; + } + + if(nb_frames < 0) + return nb_frames; + + /* get output buffer */ + if (!samples) { + av_assert0(s->frame != NULL); + s->frame->nb_samples = s->avctx->frame_size; + if ((ret = ff_get_buffer(s->avctx, s->frame, 0)) < 0) + return ret; + samples = (OUT_INT **)s->frame->extended_data; + } + + /* apply the synthesis filter */ + for (ch = 0; ch < s->nb_channels; ch++) { + int sample_stride; + if (s->avctx->sample_fmt == OUT_FMT_P) { + samples_ptr = samples[ch]; + sample_stride = 1; + } else { + samples_ptr = samples[0] + ch; + sample_stride = s->nb_channels; + } + for (i = 0; i < nb_frames; i++) { + RENAME(ff_mpa_synth_filter)(&s->mpadsp, s->synth_buf[ch], + &(s->synth_buf_offset[ch]), + RENAME(ff_mpa_synth_window), + &s->dither_state, samples_ptr, + sample_stride, s->sb_samples[ch][i]); + samples_ptr += 32 * sample_stride; + } + } + + return nb_frames * 32 * sizeof(OUT_INT) * s->nb_channels; +} + +static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MPADecodeContext *s = avctx->priv_data; + uint32_t header; + int ret; + + while(buf_size && !*buf){ + buf++; + buf_size--; + } + + if (buf_size < HEADER_SIZE) + return AVERROR_INVALIDDATA; + + header = AV_RB32(buf); + if (header>>8 == AV_RB32("TAG")>>8) { + av_log(avctx, AV_LOG_DEBUG, "discarding ID3 tag\n"); + return buf_size; + } + if (ff_mpa_check_header(header) < 0) { + av_log(avctx, AV_LOG_ERROR, "Header missing\n"); + return AVERROR_INVALIDDATA; + } + + if (avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header) == 1) { + /* free format: prepare to compute frame size */ + s->frame_size = -1; + return AVERROR_INVALIDDATA; + } + /* update codec info */ + avctx->channels = s->nb_channels; + avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + if (!avctx->bit_rate) + avctx->bit_rate = s->bit_rate; + + if (s->frame_size <= 0 || s->frame_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "incomplete frame\n"); + return AVERROR_INVALIDDATA; + } else if (s->frame_size < buf_size) { + av_log(avctx, AV_LOG_DEBUG, "incorrect frame size - multiple frames in buffer?\n"); + buf_size= s->frame_size; + } + + s->frame = data; + + ret = mp_decode_frame(s, NULL, buf, buf_size); + if (ret >= 0) { + s->frame->nb_samples = avctx->frame_size; + *got_frame_ptr = 1; + avctx->sample_rate = s->sample_rate; + //FIXME maybe move the other codec info stuff from above here too + } else { + av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n"); + /* Only return an error if the bad frame makes up the whole packet or + * the error is related to buffer management. + * If there is more data in the packet, just consume the bad frame + * instead of returning an error, which would discard the whole + * packet. */ + *got_frame_ptr = 0; + if (buf_size == avpkt->size || ret != AVERROR_INVALIDDATA) + return ret; + } + s->frame_size = 0; + return buf_size; +} + +static void mp_flush(MPADecodeContext *ctx) +{ + memset(ctx->synth_buf, 0, sizeof(ctx->synth_buf)); + ctx->last_buf_size = 0; +} + +static void flush(AVCodecContext *avctx) +{ + mp_flush(avctx->priv_data); +} + +#if CONFIG_MP3ADU_DECODER || CONFIG_MP3ADUFLOAT_DECODER +static int decode_frame_adu(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MPADecodeContext *s = avctx->priv_data; + uint32_t header; + int len, ret; + int av_unused out_size; + + len = buf_size; + + // Discard too short frames + if (buf_size < HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + + if (len > MPA_MAX_CODED_FRAME_SIZE) + len = MPA_MAX_CODED_FRAME_SIZE; + + // Get header and restore sync word + header = AV_RB32(buf) | 0xffe00000; + + if (ff_mpa_check_header(header) < 0) { // Bad header, discard frame + av_log(avctx, AV_LOG_ERROR, "Invalid frame header\n"); + return AVERROR_INVALIDDATA; + } + + avpriv_mpegaudio_decode_header((MPADecodeHeader *)s, header); + /* update codec info */ + avctx->sample_rate = s->sample_rate; + avctx->channels = s->nb_channels; + if (!avctx->bit_rate) + avctx->bit_rate = s->bit_rate; + + s->frame_size = len; + + s->frame = data; + + ret = mp_decode_frame(s, NULL, buf, buf_size); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error while decoding MPEG audio frame.\n"); + return ret; + } + + *got_frame_ptr = 1; + + return buf_size; +} +#endif /* CONFIG_MP3ADU_DECODER || CONFIG_MP3ADUFLOAT_DECODER */ + +#if CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER + +/** + * Context for MP3On4 decoder + */ +typedef struct MP3On4DecodeContext { + int frames; ///< number of mp3 frames per block (number of mp3 decoder instances) + int syncword; ///< syncword patch + const uint8_t *coff; ///< channel offsets in output buffer + MPADecodeContext *mp3decctx[5]; ///< MPADecodeContext for every decoder instance +} MP3On4DecodeContext; + +#include "mpeg4audio.h" + +/* Next 3 arrays are indexed by channel config number (passed via codecdata) */ + +/* number of mp3 decoder instances */ +static const uint8_t mp3Frames[8] = { 0, 1, 1, 2, 3, 3, 4, 5 }; + +/* offsets into output buffer, assume output order is FL FR C LFE BL BR SL SR */ +static const uint8_t chan_offset[8][5] = { + { 0 }, + { 0 }, // C + { 0 }, // FLR + { 2, 0 }, // C FLR + { 2, 0, 3 }, // C FLR BS + { 2, 0, 3 }, // C FLR BLRS + { 2, 0, 4, 3 }, // C FLR BLRS LFE + { 2, 0, 6, 4, 3 }, // C FLR BLRS BLR LFE +}; + +/* mp3on4 channel layouts */ +static const int16_t chan_layout[8] = { + 0, + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_7POINT1 +}; + +static av_cold int decode_close_mp3on4(AVCodecContext * avctx) +{ + MP3On4DecodeContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->frames; i++) + av_free(s->mp3decctx[i]); + + return 0; +} + + +static int decode_init_mp3on4(AVCodecContext * avctx) +{ + MP3On4DecodeContext *s = avctx->priv_data; + MPEG4AudioConfig cfg; + int i; + + if ((avctx->extradata_size < 2) || (avctx->extradata == NULL)) { + av_log(avctx, AV_LOG_ERROR, "Codec extradata missing or too short.\n"); + return AVERROR_INVALIDDATA; + } + + avpriv_mpeg4audio_get_config(&cfg, avctx->extradata, + avctx->extradata_size * 8, 1); + if (!cfg.chan_config || cfg.chan_config > 7) { + av_log(avctx, AV_LOG_ERROR, "Invalid channel config number.\n"); + return AVERROR_INVALIDDATA; + } + s->frames = mp3Frames[cfg.chan_config]; + s->coff = chan_offset[cfg.chan_config]; + avctx->channels = ff_mpeg4audio_channels[cfg.chan_config]; + avctx->channel_layout = chan_layout[cfg.chan_config]; + + if (cfg.sample_rate < 16000) + s->syncword = 0xffe00000; + else + s->syncword = 0xfff00000; + + /* Init the first mp3 decoder in standard way, so that all tables get builded + * We replace avctx->priv_data with the context of the first decoder so that + * decode_init() does not have to be changed. + * Other decoders will be initialized here copying data from the first context + */ + // Allocate zeroed memory for the first decoder context + s->mp3decctx[0] = av_mallocz(sizeof(MPADecodeContext)); + if (!s->mp3decctx[0]) + goto alloc_fail; + // Put decoder context in place to make init_decode() happy + avctx->priv_data = s->mp3decctx[0]; + decode_init(avctx); + // Restore mp3on4 context pointer + avctx->priv_data = s; + s->mp3decctx[0]->adu_mode = 1; // Set adu mode + + /* Create a separate codec/context for each frame (first is already ok). + * Each frame is 1 or 2 channels - up to 5 frames allowed + */ + for (i = 1; i < s->frames; i++) { + s->mp3decctx[i] = av_mallocz(sizeof(MPADecodeContext)); + if (!s->mp3decctx[i]) + goto alloc_fail; + s->mp3decctx[i]->adu_mode = 1; + s->mp3decctx[i]->avctx = avctx; + s->mp3decctx[i]->mpadsp = s->mp3decctx[0]->mpadsp; + } + + return 0; +alloc_fail: + decode_close_mp3on4(avctx); + return AVERROR(ENOMEM); +} + + +static void flush_mp3on4(AVCodecContext *avctx) +{ + int i; + MP3On4DecodeContext *s = avctx->priv_data; + + for (i = 0; i < s->frames; i++) + mp_flush(s->mp3decctx[i]); +} + + +static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MP3On4DecodeContext *s = avctx->priv_data; + MPADecodeContext *m; + int fsize, len = buf_size, out_size = 0; + uint32_t header; + OUT_INT **out_samples; + OUT_INT *outptr[2]; + int fr, ch, ret; + + /* get output buffer */ + frame->nb_samples = MPA_FRAME_SIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + out_samples = (OUT_INT **)frame->extended_data; + + // Discard too short frames + if (buf_size < HEADER_SIZE) + return AVERROR_INVALIDDATA; + + avctx->bit_rate = 0; + + ch = 0; + for (fr = 0; fr < s->frames; fr++) { + fsize = AV_RB16(buf) >> 4; + fsize = FFMIN3(fsize, len, MPA_MAX_CODED_FRAME_SIZE); + m = s->mp3decctx[fr]; + av_assert1(m); + + if (fsize < HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Frame size smaller than header size\n"); + return AVERROR_INVALIDDATA; + } + header = (AV_RB32(buf) & 0x000fffff) | s->syncword; // patch header + + if (ff_mpa_check_header(header) < 0) // Bad header, discard block + break; + + avpriv_mpegaudio_decode_header((MPADecodeHeader *)m, header); + + if (ch + m->nb_channels > avctx->channels || s->coff[fr] + m->nb_channels > avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "frame channel count exceeds codec " + "channel count\n"); + return AVERROR_INVALIDDATA; + } + ch += m->nb_channels; + + outptr[0] = out_samples[s->coff[fr]]; + if (m->nb_channels > 1) + outptr[1] = out_samples[s->coff[fr] + 1]; + + if ((ret = mp_decode_frame(m, outptr, buf, fsize)) < 0) + return ret; + + out_size += ret; + buf += fsize; + len -= fsize; + + avctx->bit_rate += m->bit_rate; + } + + /* update codec info */ + avctx->sample_rate = s->mp3decctx[0]->sample_rate; + + frame->nb_samples = out_size / (avctx->channels * sizeof(OUT_INT)); + *got_frame_ptr = 1; + + return buf_size; +} +#endif /* CONFIG_MP3ON4_DECODER || CONFIG_MP3ON4FLOAT_DECODER */ + +#if !CONFIG_FLOAT +#if CONFIG_MP1_DECODER +AVCodec ff_mp1_decoder = { + .name = "mp1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP1, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP2_DECODER +AVCodec ff_mp2_decoder = { + .name = "mp2", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP2, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP3_DECODER +AVCodec ff_mp3_decoder = { + .name = "mp3", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP3ADU_DECODER +AVCodec ff_mp3adu_decoder = { + .name = "mp3adu", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3ADU, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame_adu, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP3ON4_DECODER +AVCodec ff_mp3on4_decoder = { + .name = "mp3on4", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3ON4, + .priv_data_size = sizeof(MP3On4DecodeContext), + .init = decode_init_mp3on4, + .close = decode_close_mp3on4, + .decode = decode_frame_mp3on4, + .capabilities = CODEC_CAP_DR1, + .flush = flush_mp3on4, + .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#endif diff --git a/ffmpeg/libavcodec/mpegaudiodec_float.c b/ffmpeg/libavcodec/mpegaudiodec_float.c new file mode 100644 index 0000000..17a7757 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodec_float.c @@ -0,0 +1,104 @@ +/* + * Float MPEG Audio decoder + * Copyright (c) 2010 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 + */ + +#define CONFIG_FLOAT 1 +#include "mpegaudiodec.c" + +#if CONFIG_MP1FLOAT_DECODER +AVCodec ff_mp1float_decoder = { + .name = "mp1float", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP1, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP2FLOAT_DECODER +AVCodec ff_mp2float_decoder = { + .name = "mp2float", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP2, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP3FLOAT_DECODER +AVCodec ff_mp3float_decoder = { + .name = "mp3float", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP3ADUFLOAT_DECODER +AVCodec ff_mp3adufloat_decoder = { + .name = "mp3adufloat", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3ADU, + .priv_data_size = sizeof(MPADecodeContext), + .init = decode_init, + .decode = decode_frame_adu, + .capabilities = CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_MP3ON4FLOAT_DECODER +AVCodec ff_mp3on4float_decoder = { + .name = "mp3on4float", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP3ON4, + .priv_data_size = sizeof(MP3On4DecodeContext), + .init = decode_init_mp3on4, + .close = decode_close_mp3on4, + .decode = decode_frame_mp3on4, + .capabilities = CODEC_CAP_DR1, + .flush = flush_mp3on4, + .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; +#endif diff --git a/ffmpeg/libavcodec/mpegaudiodecheader.c b/ffmpeg/libavcodec/mpegaudiodecheader.c new file mode 100644 index 0000000..7841b30 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodecheader.c @@ -0,0 +1,146 @@ +/* + * MPEG Audio header decoder + * Copyright (c) 2001, 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * MPEG Audio header decoder. + */ + +//#define DEBUG +#include "avcodec.h" +#include "mpegaudio.h" +#include "mpegaudiodata.h" +#include "mpegaudiodecheader.h" + + +int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) +{ + int sample_rate, frame_size, mpeg25, padding; + int sample_rate_index, bitrate_index; + if (header & (1<<20)) { + s->lsf = (header & (1<<19)) ? 0 : 1; + mpeg25 = 0; + } else { + s->lsf = 1; + mpeg25 = 1; + } + + s->layer = 4 - ((header >> 17) & 3); + /* extract frequency */ + sample_rate_index = (header >> 10) & 3; + sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); + sample_rate_index += 3 * (s->lsf + mpeg25); + s->sample_rate_index = sample_rate_index; + s->error_protection = ((header >> 16) & 1) ^ 1; + s->sample_rate = sample_rate; + + bitrate_index = (header >> 12) & 0xf; + padding = (header >> 9) & 1; + //extension = (header >> 8) & 1; + s->mode = (header >> 6) & 3; + s->mode_ext = (header >> 4) & 3; + //copyright = (header >> 3) & 1; + //original = (header >> 2) & 1; + //emphasis = header & 3; + + if (s->mode == MPA_MONO) + s->nb_channels = 1; + else + s->nb_channels = 2; + + if (bitrate_index != 0) { + frame_size = avpriv_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; + s->bit_rate = frame_size * 1000; + switch(s->layer) { + case 1: + frame_size = (frame_size * 12000) / sample_rate; + frame_size = (frame_size + padding) * 4; + break; + case 2: + frame_size = (frame_size * 144000) / sample_rate; + frame_size += padding; + break; + default: + case 3: + frame_size = (frame_size * 144000) / (sample_rate << s->lsf); + frame_size += padding; + break; + } + s->frame_size = frame_size; + } else { + /* if no frame size computed, signal it */ + return 1; + } + +#if defined(DEBUG) + av_dlog(NULL, "layer%d, %d Hz, %d kbits/s, ", + s->layer, s->sample_rate, s->bit_rate); + if (s->nb_channels == 2) { + if (s->layer == 3) { + if (s->mode_ext & MODE_EXT_MS_STEREO) + av_dlog(NULL, "ms-"); + if (s->mode_ext & MODE_EXT_I_STEREO) + av_dlog(NULL, "i-"); + } + av_dlog(NULL, "stereo"); + } else { + av_dlog(NULL, "mono"); + } + av_dlog(NULL, "\n"); +#endif + return 0; +} + +int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bit_rate) +{ + MPADecodeHeader s1, *s = &s1; + + if (ff_mpa_check_header(head) != 0) + return -1; + + if (avpriv_mpegaudio_decode_header(s, head) != 0) { + return -1; + } + + switch(s->layer) { + case 1: + avctx->codec_id = AV_CODEC_ID_MP1; + *frame_size = 384; + break; + case 2: + avctx->codec_id = AV_CODEC_ID_MP2; + *frame_size = 1152; + break; + default: + case 3: + avctx->codec_id = AV_CODEC_ID_MP3; + if (s->lsf) + *frame_size = 576; + else + *frame_size = 1152; + break; + } + + *sample_rate = s->sample_rate; + *channels = s->nb_channels; + *bit_rate = s->bit_rate; + return s->frame_size; +} diff --git a/ffmpeg/libavcodec/mpegaudiodecheader.h b/ffmpeg/libavcodec/mpegaudiodecheader.h new file mode 100644 index 0000000..c434d00 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodecheader.h @@ -0,0 +1,76 @@ +/* + * MPEG Audio header decoder + * Copyright (c) 2001, 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * MPEG Audio header decoder. + */ + +#ifndef AVCODEC_MPEGAUDIODECHEADER_H +#define AVCODEC_MPEGAUDIODECHEADER_H + +#include "avcodec.h" + +#define MP3_MASK 0xFFFE0CCF + +#define MPA_DECODE_HEADER \ + int frame_size; \ + int error_protection; \ + int layer; \ + int sample_rate; \ + int sample_rate_index; /* between 0 and 8 */ \ + int bit_rate; \ + int nb_channels; \ + int mode; \ + int mode_ext; \ + int lsf; + +typedef struct MPADecodeHeader { + MPA_DECODE_HEADER +} MPADecodeHeader; + +/* header decoding. MUST check the header before because no + consistency check is done there. Return 1 if free format found and + that the frame size must be computed externally */ +int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header); + +/* useful helper to get mpeg audio stream infos. Return -1 if error in + header, otherwise the coded frame size in bytes */ +int avpriv_mpa_decode_header(AVCodecContext *avctx, uint32_t head, int *sample_rate, int *channels, int *frame_size, int *bitrate); + +/* fast header check for resync */ +static inline int ff_mpa_check_header(uint32_t header){ + /* header */ + if ((header & 0xffe00000) != 0xffe00000) + return -1; + /* layer check */ + if ((header & (3<<17)) == 0) + return -1; + /* bit rate */ + if ((header & (0xf<<12)) == 0xf<<12) + return -1; + /* frequency */ + if ((header & (3<<10)) == 3<<10) + return -1; + return 0; +} + +#endif /* AVCODEC_MPEGAUDIODECHEADER_H */ diff --git a/ffmpeg/libavcodec/mpegaudiodectab.h b/ffmpeg/libavcodec/mpegaudiodectab.h new file mode 100644 index 0000000..accd12b --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodectab.h @@ -0,0 +1,615 @@ +/* + * MPEG Audio decoder + * copyright (c) 2002 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * mpeg audio layer decoder tables. + */ + +#ifndef AVCODEC_MPEGAUDIODECTAB_H +#define AVCODEC_MPEGAUDIODECTAB_H + +#include +#include + +#include "mpegaudio.h" + +/*******************************************************/ +/* layer 3 tables */ + +/* layer 3 huffman tables */ +typedef struct HuffTable { + int xsize; + const uint8_t *bits; + const uint16_t *codes; +} HuffTable; + +/* layer3 scale factor size */ +static const uint8_t slen_table[2][16] = { + { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }, + { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }, +}; + +/* number of lsf scale factors for a given size */ +static const uint8_t lsf_nsf_table[6][3][4] = { + { { 6, 5, 5, 5 }, { 9, 9, 9, 9 }, { 6, 9, 9, 9 } }, + { { 6, 5, 7, 3 }, { 9, 9, 12, 6 }, { 6, 9, 12, 6 } }, + { { 11, 10, 0, 0 }, { 18, 18, 0, 0 }, { 15, 18, 0, 0 } }, + { { 7, 7, 7, 0 }, { 12, 12, 12, 0 }, { 6, 15, 12, 0 } }, + { { 6, 6, 6, 3 }, { 12, 9, 9, 6 }, { 6, 12, 9, 6 } }, + { { 8, 8, 5, 0 }, { 15, 12, 9, 0 }, { 6, 18, 9, 0 } }, +}; + +/* mpegaudio layer 3 huffman tables */ + +static const uint16_t mpa_huffcodes_1[4] = { + 0x0001, 0x0001, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_1[4] = { + 1, 3, 2, 3, +}; + +static const uint16_t mpa_huffcodes_2[9] = { + 0x0001, 0x0002, 0x0001, 0x0003, 0x0001, 0x0001, 0x0003, 0x0002, + 0x0000, +}; + +static const uint8_t mpa_huffbits_2[9] = { + 1, 3, 6, 3, 3, 5, 5, 5, + 6, +}; + +static const uint16_t mpa_huffcodes_3[9] = { + 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0002, + 0x0000, +}; + +static const uint8_t mpa_huffbits_3[9] = { + 2, 2, 6, 3, 2, 5, 5, 5, + 6, +}; + +static const uint16_t mpa_huffcodes_5[16] = { + 0x0001, 0x0002, 0x0006, 0x0005, 0x0003, 0x0001, 0x0004, 0x0004, + 0x0007, 0x0005, 0x0007, 0x0001, 0x0006, 0x0001, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_5[16] = { + 1, 3, 6, 7, 3, 3, 6, 7, + 6, 6, 7, 8, 7, 6, 7, 8, +}; + +static const uint16_t mpa_huffcodes_6[16] = { + 0x0007, 0x0003, 0x0005, 0x0001, 0x0006, 0x0002, 0x0003, 0x0002, + 0x0005, 0x0004, 0x0004, 0x0001, 0x0003, 0x0003, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_6[16] = { + 3, 3, 5, 7, 3, 2, 4, 5, + 4, 4, 5, 6, 6, 5, 6, 7, +}; + +static const uint16_t mpa_huffcodes_7[36] = { + 0x0001, 0x0002, 0x000a, 0x0013, 0x0010, 0x000a, 0x0003, 0x0003, + 0x0007, 0x000a, 0x0005, 0x0003, 0x000b, 0x0004, 0x000d, 0x0011, + 0x0008, 0x0004, 0x000c, 0x000b, 0x0012, 0x000f, 0x000b, 0x0002, + 0x0007, 0x0006, 0x0009, 0x000e, 0x0003, 0x0001, 0x0006, 0x0004, + 0x0005, 0x0003, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_7[36] = { + 1, 3, 6, 8, 8, 9, 3, 4, + 6, 7, 7, 8, 6, 5, 7, 8, + 8, 9, 7, 7, 8, 9, 9, 9, + 7, 7, 8, 9, 9, 10, 8, 8, + 9, 10, 10, 10, +}; + +static const uint16_t mpa_huffcodes_8[36] = { + 0x0003, 0x0004, 0x0006, 0x0012, 0x000c, 0x0005, 0x0005, 0x0001, + 0x0002, 0x0010, 0x0009, 0x0003, 0x0007, 0x0003, 0x0005, 0x000e, + 0x0007, 0x0003, 0x0013, 0x0011, 0x000f, 0x000d, 0x000a, 0x0004, + 0x000d, 0x0005, 0x0008, 0x000b, 0x0005, 0x0001, 0x000c, 0x0004, + 0x0004, 0x0001, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_8[36] = { + 2, 3, 6, 8, 8, 9, 3, 2, + 4, 8, 8, 8, 6, 4, 6, 8, + 8, 9, 8, 8, 8, 9, 9, 10, + 8, 7, 8, 9, 10, 10, 9, 8, + 9, 9, 11, 11, +}; + +static const uint16_t mpa_huffcodes_9[36] = { + 0x0007, 0x0005, 0x0009, 0x000e, 0x000f, 0x0007, 0x0006, 0x0004, + 0x0005, 0x0005, 0x0006, 0x0007, 0x0007, 0x0006, 0x0008, 0x0008, + 0x0008, 0x0005, 0x000f, 0x0006, 0x0009, 0x000a, 0x0005, 0x0001, + 0x000b, 0x0007, 0x0009, 0x0006, 0x0004, 0x0001, 0x000e, 0x0004, + 0x0006, 0x0002, 0x0006, 0x0000, +}; + +static const uint8_t mpa_huffbits_9[36] = { + 3, 3, 5, 6, 8, 9, 3, 3, + 4, 5, 6, 8, 4, 4, 5, 6, + 7, 8, 6, 5, 6, 7, 7, 8, + 7, 6, 7, 7, 8, 9, 8, 7, + 8, 8, 9, 9, +}; + +static const uint16_t mpa_huffcodes_10[64] = { + 0x0001, 0x0002, 0x000a, 0x0017, 0x0023, 0x001e, 0x000c, 0x0011, + 0x0003, 0x0003, 0x0008, 0x000c, 0x0012, 0x0015, 0x000c, 0x0007, + 0x000b, 0x0009, 0x000f, 0x0015, 0x0020, 0x0028, 0x0013, 0x0006, + 0x000e, 0x000d, 0x0016, 0x0022, 0x002e, 0x0017, 0x0012, 0x0007, + 0x0014, 0x0013, 0x0021, 0x002f, 0x001b, 0x0016, 0x0009, 0x0003, + 0x001f, 0x0016, 0x0029, 0x001a, 0x0015, 0x0014, 0x0005, 0x0003, + 0x000e, 0x000d, 0x000a, 0x000b, 0x0010, 0x0006, 0x0005, 0x0001, + 0x0009, 0x0008, 0x0007, 0x0008, 0x0004, 0x0004, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_10[64] = { + 1, 3, 6, 8, 9, 9, 9, 10, + 3, 4, 6, 7, 8, 9, 8, 8, + 6, 6, 7, 8, 9, 10, 9, 9, + 7, 7, 8, 9, 10, 10, 9, 10, + 8, 8, 9, 10, 10, 10, 10, 10, + 9, 9, 10, 10, 11, 11, 10, 11, + 8, 8, 9, 10, 10, 10, 11, 11, + 9, 8, 9, 10, 10, 11, 11, 11, +}; + +static const uint16_t mpa_huffcodes_11[64] = { + 0x0003, 0x0004, 0x000a, 0x0018, 0x0022, 0x0021, 0x0015, 0x000f, + 0x0005, 0x0003, 0x0004, 0x000a, 0x0020, 0x0011, 0x000b, 0x000a, + 0x000b, 0x0007, 0x000d, 0x0012, 0x001e, 0x001f, 0x0014, 0x0005, + 0x0019, 0x000b, 0x0013, 0x003b, 0x001b, 0x0012, 0x000c, 0x0005, + 0x0023, 0x0021, 0x001f, 0x003a, 0x001e, 0x0010, 0x0007, 0x0005, + 0x001c, 0x001a, 0x0020, 0x0013, 0x0011, 0x000f, 0x0008, 0x000e, + 0x000e, 0x000c, 0x0009, 0x000d, 0x000e, 0x0009, 0x0004, 0x0001, + 0x000b, 0x0004, 0x0006, 0x0006, 0x0006, 0x0003, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_11[64] = { + 2, 3, 5, 7, 8, 9, 8, 9, + 3, 3, 4, 6, 8, 8, 7, 8, + 5, 5, 6, 7, 8, 9, 8, 8, + 7, 6, 7, 9, 8, 10, 8, 9, + 8, 8, 8, 9, 9, 10, 9, 10, + 8, 8, 9, 10, 10, 11, 10, 11, + 8, 7, 7, 8, 9, 10, 10, 10, + 8, 7, 8, 9, 10, 10, 10, 10, +}; + +static const uint16_t mpa_huffcodes_12[64] = { + 0x0009, 0x0006, 0x0010, 0x0021, 0x0029, 0x0027, 0x0026, 0x001a, + 0x0007, 0x0005, 0x0006, 0x0009, 0x0017, 0x0010, 0x001a, 0x000b, + 0x0011, 0x0007, 0x000b, 0x000e, 0x0015, 0x001e, 0x000a, 0x0007, + 0x0011, 0x000a, 0x000f, 0x000c, 0x0012, 0x001c, 0x000e, 0x0005, + 0x0020, 0x000d, 0x0016, 0x0013, 0x0012, 0x0010, 0x0009, 0x0005, + 0x0028, 0x0011, 0x001f, 0x001d, 0x0011, 0x000d, 0x0004, 0x0002, + 0x001b, 0x000c, 0x000b, 0x000f, 0x000a, 0x0007, 0x0004, 0x0001, + 0x001b, 0x000c, 0x0008, 0x000c, 0x0006, 0x0003, 0x0001, 0x0000, +}; + +static const uint8_t mpa_huffbits_12[64] = { + 4, 3, 5, 7, 8, 9, 9, 9, + 3, 3, 4, 5, 7, 7, 8, 8, + 5, 4, 5, 6, 7, 8, 7, 8, + 6, 5, 6, 6, 7, 8, 8, 8, + 7, 6, 7, 7, 8, 8, 8, 9, + 8, 7, 8, 8, 8, 9, 8, 9, + 8, 7, 7, 8, 8, 9, 9, 10, + 9, 8, 8, 9, 9, 9, 9, 10, +}; + +static const uint16_t mpa_huffcodes_13[256] = { + 0x0001, 0x0005, 0x000e, 0x0015, 0x0022, 0x0033, 0x002e, 0x0047, + 0x002a, 0x0034, 0x0044, 0x0034, 0x0043, 0x002c, 0x002b, 0x0013, + 0x0003, 0x0004, 0x000c, 0x0013, 0x001f, 0x001a, 0x002c, 0x0021, + 0x001f, 0x0018, 0x0020, 0x0018, 0x001f, 0x0023, 0x0016, 0x000e, + 0x000f, 0x000d, 0x0017, 0x0024, 0x003b, 0x0031, 0x004d, 0x0041, + 0x001d, 0x0028, 0x001e, 0x0028, 0x001b, 0x0021, 0x002a, 0x0010, + 0x0016, 0x0014, 0x0025, 0x003d, 0x0038, 0x004f, 0x0049, 0x0040, + 0x002b, 0x004c, 0x0038, 0x0025, 0x001a, 0x001f, 0x0019, 0x000e, + 0x0023, 0x0010, 0x003c, 0x0039, 0x0061, 0x004b, 0x0072, 0x005b, + 0x0036, 0x0049, 0x0037, 0x0029, 0x0030, 0x0035, 0x0017, 0x0018, + 0x003a, 0x001b, 0x0032, 0x0060, 0x004c, 0x0046, 0x005d, 0x0054, + 0x004d, 0x003a, 0x004f, 0x001d, 0x004a, 0x0031, 0x0029, 0x0011, + 0x002f, 0x002d, 0x004e, 0x004a, 0x0073, 0x005e, 0x005a, 0x004f, + 0x0045, 0x0053, 0x0047, 0x0032, 0x003b, 0x0026, 0x0024, 0x000f, + 0x0048, 0x0022, 0x0038, 0x005f, 0x005c, 0x0055, 0x005b, 0x005a, + 0x0056, 0x0049, 0x004d, 0x0041, 0x0033, 0x002c, 0x002b, 0x002a, + 0x002b, 0x0014, 0x001e, 0x002c, 0x0037, 0x004e, 0x0048, 0x0057, + 0x004e, 0x003d, 0x002e, 0x0036, 0x0025, 0x001e, 0x0014, 0x0010, + 0x0035, 0x0019, 0x0029, 0x0025, 0x002c, 0x003b, 0x0036, 0x0051, + 0x0042, 0x004c, 0x0039, 0x0036, 0x0025, 0x0012, 0x0027, 0x000b, + 0x0023, 0x0021, 0x001f, 0x0039, 0x002a, 0x0052, 0x0048, 0x0050, + 0x002f, 0x003a, 0x0037, 0x0015, 0x0016, 0x001a, 0x0026, 0x0016, + 0x0035, 0x0019, 0x0017, 0x0026, 0x0046, 0x003c, 0x0033, 0x0024, + 0x0037, 0x001a, 0x0022, 0x0017, 0x001b, 0x000e, 0x0009, 0x0007, + 0x0022, 0x0020, 0x001c, 0x0027, 0x0031, 0x004b, 0x001e, 0x0034, + 0x0030, 0x0028, 0x0034, 0x001c, 0x0012, 0x0011, 0x0009, 0x0005, + 0x002d, 0x0015, 0x0022, 0x0040, 0x0038, 0x0032, 0x0031, 0x002d, + 0x001f, 0x0013, 0x000c, 0x000f, 0x000a, 0x0007, 0x0006, 0x0003, + 0x0030, 0x0017, 0x0014, 0x0027, 0x0024, 0x0023, 0x0035, 0x0015, + 0x0010, 0x0017, 0x000d, 0x000a, 0x0006, 0x0001, 0x0004, 0x0002, + 0x0010, 0x000f, 0x0011, 0x001b, 0x0019, 0x0014, 0x001d, 0x000b, + 0x0011, 0x000c, 0x0010, 0x0008, 0x0001, 0x0001, 0x0000, 0x0001, +}; + +static const uint8_t mpa_huffbits_13[256] = { + 1, 4, 6, 7, 8, 9, 9, 10, + 9, 10, 11, 11, 12, 12, 13, 13, + 3, 4, 6, 7, 8, 8, 9, 9, + 9, 9, 10, 10, 11, 12, 12, 12, + 6, 6, 7, 8, 9, 9, 10, 10, + 9, 10, 10, 11, 11, 12, 13, 13, + 7, 7, 8, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 11, 12, 13, 13, + 8, 7, 9, 9, 10, 10, 11, 11, + 10, 11, 11, 12, 12, 13, 13, 14, + 9, 8, 9, 10, 10, 10, 11, 11, + 11, 11, 12, 11, 13, 13, 14, 14, + 9, 9, 10, 10, 11, 11, 11, 11, + 11, 12, 12, 12, 13, 13, 14, 14, + 10, 9, 10, 11, 11, 11, 12, 12, + 12, 12, 13, 13, 13, 14, 16, 16, + 9, 8, 9, 10, 10, 11, 11, 12, + 12, 12, 12, 13, 13, 14, 15, 15, + 10, 9, 10, 10, 11, 11, 11, 13, + 12, 13, 13, 14, 14, 14, 16, 15, + 10, 10, 10, 11, 11, 12, 12, 13, + 12, 13, 14, 13, 14, 15, 16, 17, + 11, 10, 10, 11, 12, 12, 12, 12, + 13, 13, 13, 14, 15, 15, 15, 16, + 11, 11, 11, 12, 12, 13, 12, 13, + 14, 14, 15, 15, 15, 16, 16, 16, + 12, 11, 12, 13, 13, 13, 14, 14, + 14, 14, 14, 15, 16, 15, 16, 16, + 13, 12, 12, 13, 13, 13, 15, 14, + 14, 17, 15, 15, 15, 17, 16, 16, + 12, 12, 13, 14, 14, 14, 15, 14, + 15, 15, 16, 16, 19, 18, 19, 16, +}; + +static const uint16_t mpa_huffcodes_15[256] = { + 0x0007, 0x000c, 0x0012, 0x0035, 0x002f, 0x004c, 0x007c, 0x006c, + 0x0059, 0x007b, 0x006c, 0x0077, 0x006b, 0x0051, 0x007a, 0x003f, + 0x000d, 0x0005, 0x0010, 0x001b, 0x002e, 0x0024, 0x003d, 0x0033, + 0x002a, 0x0046, 0x0034, 0x0053, 0x0041, 0x0029, 0x003b, 0x0024, + 0x0013, 0x0011, 0x000f, 0x0018, 0x0029, 0x0022, 0x003b, 0x0030, + 0x0028, 0x0040, 0x0032, 0x004e, 0x003e, 0x0050, 0x0038, 0x0021, + 0x001d, 0x001c, 0x0019, 0x002b, 0x0027, 0x003f, 0x0037, 0x005d, + 0x004c, 0x003b, 0x005d, 0x0048, 0x0036, 0x004b, 0x0032, 0x001d, + 0x0034, 0x0016, 0x002a, 0x0028, 0x0043, 0x0039, 0x005f, 0x004f, + 0x0048, 0x0039, 0x0059, 0x0045, 0x0031, 0x0042, 0x002e, 0x001b, + 0x004d, 0x0025, 0x0023, 0x0042, 0x003a, 0x0034, 0x005b, 0x004a, + 0x003e, 0x0030, 0x004f, 0x003f, 0x005a, 0x003e, 0x0028, 0x0026, + 0x007d, 0x0020, 0x003c, 0x0038, 0x0032, 0x005c, 0x004e, 0x0041, + 0x0037, 0x0057, 0x0047, 0x0033, 0x0049, 0x0033, 0x0046, 0x001e, + 0x006d, 0x0035, 0x0031, 0x005e, 0x0058, 0x004b, 0x0042, 0x007a, + 0x005b, 0x0049, 0x0038, 0x002a, 0x0040, 0x002c, 0x0015, 0x0019, + 0x005a, 0x002b, 0x0029, 0x004d, 0x0049, 0x003f, 0x0038, 0x005c, + 0x004d, 0x0042, 0x002f, 0x0043, 0x0030, 0x0035, 0x0024, 0x0014, + 0x0047, 0x0022, 0x0043, 0x003c, 0x003a, 0x0031, 0x0058, 0x004c, + 0x0043, 0x006a, 0x0047, 0x0036, 0x0026, 0x0027, 0x0017, 0x000f, + 0x006d, 0x0035, 0x0033, 0x002f, 0x005a, 0x0052, 0x003a, 0x0039, + 0x0030, 0x0048, 0x0039, 0x0029, 0x0017, 0x001b, 0x003e, 0x0009, + 0x0056, 0x002a, 0x0028, 0x0025, 0x0046, 0x0040, 0x0034, 0x002b, + 0x0046, 0x0037, 0x002a, 0x0019, 0x001d, 0x0012, 0x000b, 0x000b, + 0x0076, 0x0044, 0x001e, 0x0037, 0x0032, 0x002e, 0x004a, 0x0041, + 0x0031, 0x0027, 0x0018, 0x0010, 0x0016, 0x000d, 0x000e, 0x0007, + 0x005b, 0x002c, 0x0027, 0x0026, 0x0022, 0x003f, 0x0034, 0x002d, + 0x001f, 0x0034, 0x001c, 0x0013, 0x000e, 0x0008, 0x0009, 0x0003, + 0x007b, 0x003c, 0x003a, 0x0035, 0x002f, 0x002b, 0x0020, 0x0016, + 0x0025, 0x0018, 0x0011, 0x000c, 0x000f, 0x000a, 0x0002, 0x0001, + 0x0047, 0x0025, 0x0022, 0x001e, 0x001c, 0x0014, 0x0011, 0x001a, + 0x0015, 0x0010, 0x000a, 0x0006, 0x0008, 0x0006, 0x0002, 0x0000, +}; + +static const uint8_t mpa_huffbits_15[256] = { + 3, 4, 5, 7, 7, 8, 9, 9, + 9, 10, 10, 11, 11, 11, 12, 13, + 4, 3, 5, 6, 7, 7, 8, 8, + 8, 9, 9, 10, 10, 10, 11, 11, + 5, 5, 5, 6, 7, 7, 8, 8, + 8, 9, 9, 10, 10, 11, 11, 11, + 6, 6, 6, 7, 7, 8, 8, 9, + 9, 9, 10, 10, 10, 11, 11, 11, + 7, 6, 7, 7, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 11, + 8, 7, 7, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 11, 11, 11, 12, + 9, 7, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 11, 11, 12, 12, + 9, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 11, 11, 11, 12, + 9, 8, 8, 9, 9, 9, 9, 10, + 10, 10, 10, 11, 11, 12, 12, 12, + 9, 8, 9, 9, 9, 9, 10, 10, + 10, 11, 11, 11, 11, 12, 12, 12, + 10, 9, 9, 9, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 12, 13, 12, + 10, 9, 9, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 12, 12, 12, 13, + 11, 10, 9, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 12, 12, 13, 13, + 11, 10, 10, 10, 10, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 13, 13, + 12, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 12, 13, + 12, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 13, 13, 13, 13, +}; + +static const uint16_t mpa_huffcodes_16[256] = { + 0x0001, 0x0005, 0x000e, 0x002c, 0x004a, 0x003f, 0x006e, 0x005d, + 0x00ac, 0x0095, 0x008a, 0x00f2, 0x00e1, 0x00c3, 0x0178, 0x0011, + 0x0003, 0x0004, 0x000c, 0x0014, 0x0023, 0x003e, 0x0035, 0x002f, + 0x0053, 0x004b, 0x0044, 0x0077, 0x00c9, 0x006b, 0x00cf, 0x0009, + 0x000f, 0x000d, 0x0017, 0x0026, 0x0043, 0x003a, 0x0067, 0x005a, + 0x00a1, 0x0048, 0x007f, 0x0075, 0x006e, 0x00d1, 0x00ce, 0x0010, + 0x002d, 0x0015, 0x0027, 0x0045, 0x0040, 0x0072, 0x0063, 0x0057, + 0x009e, 0x008c, 0x00fc, 0x00d4, 0x00c7, 0x0183, 0x016d, 0x001a, + 0x004b, 0x0024, 0x0044, 0x0041, 0x0073, 0x0065, 0x00b3, 0x00a4, + 0x009b, 0x0108, 0x00f6, 0x00e2, 0x018b, 0x017e, 0x016a, 0x0009, + 0x0042, 0x001e, 0x003b, 0x0038, 0x0066, 0x00b9, 0x00ad, 0x0109, + 0x008e, 0x00fd, 0x00e8, 0x0190, 0x0184, 0x017a, 0x01bd, 0x0010, + 0x006f, 0x0036, 0x0034, 0x0064, 0x00b8, 0x00b2, 0x00a0, 0x0085, + 0x0101, 0x00f4, 0x00e4, 0x00d9, 0x0181, 0x016e, 0x02cb, 0x000a, + 0x0062, 0x0030, 0x005b, 0x0058, 0x00a5, 0x009d, 0x0094, 0x0105, + 0x00f8, 0x0197, 0x018d, 0x0174, 0x017c, 0x0379, 0x0374, 0x0008, + 0x0055, 0x0054, 0x0051, 0x009f, 0x009c, 0x008f, 0x0104, 0x00f9, + 0x01ab, 0x0191, 0x0188, 0x017f, 0x02d7, 0x02c9, 0x02c4, 0x0007, + 0x009a, 0x004c, 0x0049, 0x008d, 0x0083, 0x0100, 0x00f5, 0x01aa, + 0x0196, 0x018a, 0x0180, 0x02df, 0x0167, 0x02c6, 0x0160, 0x000b, + 0x008b, 0x0081, 0x0043, 0x007d, 0x00f7, 0x00e9, 0x00e5, 0x00db, + 0x0189, 0x02e7, 0x02e1, 0x02d0, 0x0375, 0x0372, 0x01b7, 0x0004, + 0x00f3, 0x0078, 0x0076, 0x0073, 0x00e3, 0x00df, 0x018c, 0x02ea, + 0x02e6, 0x02e0, 0x02d1, 0x02c8, 0x02c2, 0x00df, 0x01b4, 0x0006, + 0x00ca, 0x00e0, 0x00de, 0x00da, 0x00d8, 0x0185, 0x0182, 0x017d, + 0x016c, 0x0378, 0x01bb, 0x02c3, 0x01b8, 0x01b5, 0x06c0, 0x0004, + 0x02eb, 0x00d3, 0x00d2, 0x00d0, 0x0172, 0x017b, 0x02de, 0x02d3, + 0x02ca, 0x06c7, 0x0373, 0x036d, 0x036c, 0x0d83, 0x0361, 0x0002, + 0x0179, 0x0171, 0x0066, 0x00bb, 0x02d6, 0x02d2, 0x0166, 0x02c7, + 0x02c5, 0x0362, 0x06c6, 0x0367, 0x0d82, 0x0366, 0x01b2, 0x0000, + 0x000c, 0x000a, 0x0007, 0x000b, 0x000a, 0x0011, 0x000b, 0x0009, + 0x000d, 0x000c, 0x000a, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, +}; + +static const uint8_t mpa_huffbits_16[256] = { + 1, 4, 6, 8, 9, 9, 10, 10, + 11, 11, 11, 12, 12, 12, 13, 9, + 3, 4, 6, 7, 8, 9, 9, 9, + 10, 10, 10, 11, 12, 11, 12, 8, + 6, 6, 7, 8, 9, 9, 10, 10, + 11, 10, 11, 11, 11, 12, 12, 9, + 8, 7, 8, 9, 9, 10, 10, 10, + 11, 11, 12, 12, 12, 13, 13, 10, + 9, 8, 9, 9, 10, 10, 11, 11, + 11, 12, 12, 12, 13, 13, 13, 9, + 9, 8, 9, 9, 10, 11, 11, 12, + 11, 12, 12, 13, 13, 13, 14, 10, + 10, 9, 9, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 14, 10, + 10, 9, 10, 10, 11, 11, 11, 12, + 12, 13, 13, 13, 13, 15, 15, 10, + 10, 10, 10, 11, 11, 11, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 10, + 11, 10, 10, 11, 11, 12, 12, 13, + 13, 13, 13, 14, 13, 14, 13, 11, + 11, 11, 10, 11, 12, 12, 12, 12, + 13, 14, 14, 14, 15, 15, 14, 10, + 12, 11, 11, 11, 12, 12, 13, 14, + 14, 14, 14, 14, 14, 13, 14, 11, + 12, 12, 12, 12, 12, 13, 13, 13, + 13, 15, 14, 14, 14, 14, 16, 11, + 14, 12, 12, 12, 13, 13, 14, 14, + 14, 16, 15, 15, 15, 17, 15, 11, + 13, 13, 11, 12, 14, 14, 13, 14, + 14, 15, 16, 15, 17, 15, 14, 11, + 9, 8, 8, 9, 9, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 8, +}; + +static const uint16_t mpa_huffcodes_24[256] = { + 0x000f, 0x000d, 0x002e, 0x0050, 0x0092, 0x0106, 0x00f8, 0x01b2, + 0x01aa, 0x029d, 0x028d, 0x0289, 0x026d, 0x0205, 0x0408, 0x0058, + 0x000e, 0x000c, 0x0015, 0x0026, 0x0047, 0x0082, 0x007a, 0x00d8, + 0x00d1, 0x00c6, 0x0147, 0x0159, 0x013f, 0x0129, 0x0117, 0x002a, + 0x002f, 0x0016, 0x0029, 0x004a, 0x0044, 0x0080, 0x0078, 0x00dd, + 0x00cf, 0x00c2, 0x00b6, 0x0154, 0x013b, 0x0127, 0x021d, 0x0012, + 0x0051, 0x0027, 0x004b, 0x0046, 0x0086, 0x007d, 0x0074, 0x00dc, + 0x00cc, 0x00be, 0x00b2, 0x0145, 0x0137, 0x0125, 0x010f, 0x0010, + 0x0093, 0x0048, 0x0045, 0x0087, 0x007f, 0x0076, 0x0070, 0x00d2, + 0x00c8, 0x00bc, 0x0160, 0x0143, 0x0132, 0x011d, 0x021c, 0x000e, + 0x0107, 0x0042, 0x0081, 0x007e, 0x0077, 0x0072, 0x00d6, 0x00ca, + 0x00c0, 0x00b4, 0x0155, 0x013d, 0x012d, 0x0119, 0x0106, 0x000c, + 0x00f9, 0x007b, 0x0079, 0x0075, 0x0071, 0x00d7, 0x00ce, 0x00c3, + 0x00b9, 0x015b, 0x014a, 0x0134, 0x0123, 0x0110, 0x0208, 0x000a, + 0x01b3, 0x0073, 0x006f, 0x006d, 0x00d3, 0x00cb, 0x00c4, 0x00bb, + 0x0161, 0x014c, 0x0139, 0x012a, 0x011b, 0x0213, 0x017d, 0x0011, + 0x01ab, 0x00d4, 0x00d0, 0x00cd, 0x00c9, 0x00c1, 0x00ba, 0x00b1, + 0x00a9, 0x0140, 0x012f, 0x011e, 0x010c, 0x0202, 0x0179, 0x0010, + 0x014f, 0x00c7, 0x00c5, 0x00bf, 0x00bd, 0x00b5, 0x00ae, 0x014d, + 0x0141, 0x0131, 0x0121, 0x0113, 0x0209, 0x017b, 0x0173, 0x000b, + 0x029c, 0x00b8, 0x00b7, 0x00b3, 0x00af, 0x0158, 0x014b, 0x013a, + 0x0130, 0x0122, 0x0115, 0x0212, 0x017f, 0x0175, 0x016e, 0x000a, + 0x028c, 0x015a, 0x00ab, 0x00a8, 0x00a4, 0x013e, 0x0135, 0x012b, + 0x011f, 0x0114, 0x0107, 0x0201, 0x0177, 0x0170, 0x016a, 0x0006, + 0x0288, 0x0142, 0x013c, 0x0138, 0x0133, 0x012e, 0x0124, 0x011c, + 0x010d, 0x0105, 0x0200, 0x0178, 0x0172, 0x016c, 0x0167, 0x0004, + 0x026c, 0x012c, 0x0128, 0x0126, 0x0120, 0x011a, 0x0111, 0x010a, + 0x0203, 0x017c, 0x0176, 0x0171, 0x016d, 0x0169, 0x0165, 0x0002, + 0x0409, 0x0118, 0x0116, 0x0112, 0x010b, 0x0108, 0x0103, 0x017e, + 0x017a, 0x0174, 0x016f, 0x016b, 0x0168, 0x0166, 0x0164, 0x0000, + 0x002b, 0x0014, 0x0013, 0x0011, 0x000f, 0x000d, 0x000b, 0x0009, + 0x0007, 0x0006, 0x0004, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, +}; + +static const uint8_t mpa_huffbits_24[256] = { + 4, 4, 6, 7, 8, 9, 9, 10, + 10, 11, 11, 11, 11, 11, 12, 9, + 4, 4, 5, 6, 7, 8, 8, 9, + 9, 9, 10, 10, 10, 10, 10, 8, + 6, 5, 6, 7, 7, 8, 8, 9, + 9, 9, 9, 10, 10, 10, 11, 7, + 7, 6, 7, 7, 8, 8, 8, 9, + 9, 9, 9, 10, 10, 10, 10, 7, + 8, 7, 7, 8, 8, 8, 8, 9, + 9, 9, 10, 10, 10, 10, 11, 7, + 9, 7, 8, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 7, + 9, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 11, 7, + 10, 8, 8, 8, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 11, 11, 8, + 10, 9, 9, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 11, 11, 8, + 10, 9, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 11, 11, 11, 8, + 11, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 8, + 11, 10, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 8, + 11, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 8, + 11, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 8, + 12, 10, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 8, + 8, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 4, +}; + +static const HuffTable mpa_huff_tables[16] = { +{ 1, NULL, NULL }, +{ 2, mpa_huffbits_1, mpa_huffcodes_1 }, +{ 3, mpa_huffbits_2, mpa_huffcodes_2 }, +{ 3, mpa_huffbits_3, mpa_huffcodes_3 }, +{ 4, mpa_huffbits_5, mpa_huffcodes_5 }, +{ 4, mpa_huffbits_6, mpa_huffcodes_6 }, +{ 6, mpa_huffbits_7, mpa_huffcodes_7 }, +{ 6, mpa_huffbits_8, mpa_huffcodes_8 }, +{ 6, mpa_huffbits_9, mpa_huffcodes_9 }, +{ 8, mpa_huffbits_10, mpa_huffcodes_10 }, +{ 8, mpa_huffbits_11, mpa_huffcodes_11 }, +{ 8, mpa_huffbits_12, mpa_huffcodes_12 }, +{ 16, mpa_huffbits_13, mpa_huffcodes_13 }, +{ 16, mpa_huffbits_15, mpa_huffcodes_15 }, +{ 16, mpa_huffbits_16, mpa_huffcodes_16 }, +{ 16, mpa_huffbits_24, mpa_huffcodes_24 }, +}; + +static const uint8_t mpa_huff_data[32][2] = { +{ 0, 0 }, +{ 1, 0 }, +{ 2, 0 }, +{ 3, 0 }, +{ 0, 0 }, +{ 4, 0 }, +{ 5, 0 }, +{ 6, 0 }, +{ 7, 0 }, +{ 8, 0 }, +{ 9, 0 }, +{ 10, 0 }, +{ 11, 0 }, +{ 12, 0 }, +{ 0, 0 }, +{ 13, 0 }, +{ 14, 1 }, +{ 14, 2 }, +{ 14, 3 }, +{ 14, 4 }, +{ 14, 6 }, +{ 14, 8 }, +{ 14, 10 }, +{ 14, 13 }, +{ 15, 4 }, +{ 15, 5 }, +{ 15, 6 }, +{ 15, 7 }, +{ 15, 8 }, +{ 15, 9 }, +{ 15, 11 }, +{ 15, 13 }, +}; + + +/* huffman tables for quadrules */ +static const uint8_t mpa_quad_codes[2][16] = { + { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1, }, + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, }, +}; + +static const uint8_t mpa_quad_bits[2][16] = { + { 1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6, }, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }, +}; + +/* band size tables */ +static const uint8_t band_size_long[9][22] = { +{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 8, 10, + 12, 16, 20, 24, 28, 34, 42, 50, 54, 76, 158, }, /* 44100 */ +{ 4, 4, 4, 4, 4, 4, 6, 6, 6, 8, 10, + 12, 16, 18, 22, 28, 34, 40, 46, 54, 54, 192, }, /* 48000 */ +{ 4, 4, 4, 4, 4, 4, 6, 6, 8, 10, 12, + 16, 20, 24, 30, 38, 46, 56, 68, 84, 102, 26, }, /* 32000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 22050 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 18, 22, 26, 32, 38, 46, 52, 64, 70, 76, 36, }, /* 24000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 16000 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 11025 */ +{ 6, 6, 6, 6, 6, 6, 8, 10, 12, 14, 16, + 20, 24, 28, 32, 38, 46, 52, 60, 68, 58, 54, }, /* 12000 */ +{ 12, 12, 12, 12, 12, 12, 16, 20, 24, 28, 32, + 40, 48, 56, 64, 76, 90, 2, 2, 2, 2, 2, }, /* 8000 */ +}; + +static const uint8_t band_size_short[9][13] = { +{ 4, 4, 4, 4, 6, 8, 10, 12, 14, 18, 22, 30, 56, }, /* 44100 */ +{ 4, 4, 4, 4, 6, 6, 10, 12, 14, 16, 20, 26, 66, }, /* 48000 */ +{ 4, 4, 4, 4, 6, 8, 12, 16, 20, 26, 34, 42, 12, }, /* 32000 */ +{ 4, 4, 4, 6, 6, 8, 10, 14, 18, 26, 32, 42, 18, }, /* 22050 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 32, 44, 12, }, /* 24000 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 16000 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 11025 */ +{ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18, }, /* 12000 */ +{ 8, 8, 8, 12, 16, 20, 24, 28, 36, 2, 2, 2, 26, }, /* 8000 */ +}; + +static const uint8_t mpa_pretab[2][22] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 }, +}; + +/* table for alias reduction (XXX: store it as integer !) */ +static const float ci_table[8] = { + -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037, +}; + +#endif /* AVCODEC_MPEGAUDIODECTAB_H */ diff --git a/ffmpeg/libavcodec/mpegaudiodsp.c b/ffmpeg/libavcodec/mpegaudiodsp.c new file mode 100644 index 0000000..aadc747 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodsp.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Mans Rullgard + * + * 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 "config.h" +#include "mpegaudiodsp.h" +#include "dct.h" +#include "dct32.h" + +void ff_mpadsp_init(MPADSPContext *s) +{ + DCTContext dct; + + ff_dct_init(&dct, 5, DCT_II); + ff_init_mpadsp_tabs_float(); + ff_init_mpadsp_tabs_fixed(); + + s->apply_window_float = ff_mpadsp_apply_window_float; + s->apply_window_fixed = ff_mpadsp_apply_window_fixed; + + s->dct32_float = dct.dct32; + s->dct32_fixed = ff_dct32_fixed; + + s->imdct36_blocks_float = ff_imdct36_blocks_float; + s->imdct36_blocks_fixed = ff_imdct36_blocks_fixed; + + if (ARCH_ARM) ff_mpadsp_init_arm(s); + if (ARCH_X86) ff_mpadsp_init_x86(s); + if (HAVE_ALTIVEC) ff_mpadsp_init_altivec(s); + if (HAVE_MIPSFPU) ff_mpadsp_init_mipsfpu(s); + if (HAVE_MIPSDSPR1) ff_mpadsp_init_mipsdspr1(s); +} diff --git a/ffmpeg/libavcodec/mpegaudiodsp.h b/ffmpeg/libavcodec/mpegaudiodsp.h new file mode 100644 index 0000000..623d2df --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodsp.h @@ -0,0 +1,89 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_MPEGAUDIODSP_H +#define AVCODEC_MPEGAUDIODSP_H + +#include +#include "libavutil/common.h" + +typedef struct MPADSPContext { + void (*apply_window_float)(float *synth_buf, float *window, + int *dither_state, float *samples, int incr); + void (*apply_window_fixed)(int32_t *synth_buf, int32_t *window, + int *dither_state, int16_t *samples, int incr); + void (*dct32_float)(float *dst, const float *src); + void (*dct32_fixed)(int *dst, const int *src); + + void (*imdct36_blocks_float)(float *out, float *buf, float *in, + int count, int switch_point, int block_type); + void (*imdct36_blocks_fixed)(int *out, int *buf, int *in, + int count, int switch_point, int block_type); +} MPADSPContext; + +void ff_mpadsp_init(MPADSPContext *s); + +extern int32_t ff_mpa_synth_window_fixed[]; +extern float ff_mpa_synth_window_float[]; + +extern const int32_t ff_mpa_enwindow[257]; + +void ff_mpa_synth_filter_fixed(MPADSPContext *s, + int32_t *synth_buf_ptr, int *synth_buf_offset, + int32_t *window, int *dither_state, + int16_t *samples, int incr, + int32_t *sb_samples); + +void ff_mpa_synth_filter_float(MPADSPContext *s, + float *synth_buf_ptr, int *synth_buf_offset, + float *window, int *dither_state, + float *samples, int incr, + float *sb_samples); + +void ff_mpadsp_init_arm(MPADSPContext *s); +void ff_mpadsp_init_x86(MPADSPContext *s); +void ff_mpadsp_init_altivec(MPADSPContext *s); +void ff_mpadsp_init_mipsfpu(MPADSPContext *s); +void ff_mpadsp_init_mipsdspr1(MPADSPContext *s); + +void ff_mpa_synth_init_float(float *window); +void ff_mpa_synth_init_fixed(int32_t *window); + +void ff_mpadsp_apply_window_float(float *synth_buf, float *window, + int *dither_state, float *samples, + int incr); +void ff_mpadsp_apply_window_fixed(int32_t *synth_buf, int32_t *window, + int *dither_state, int16_t *samples, + int incr); + +void ff_imdct36_blocks_float(float *out, float *buf, float *in, + int count, int switch_point, int block_type); + +void ff_imdct36_blocks_fixed(int *out, int *buf, int *in, + int count, int switch_point, int block_type); + +void ff_init_mpadsp_tabs_float(void); +void ff_init_mpadsp_tabs_fixed(void); + +/** For SSE implementation, MDCT_BUF_SIZE/2 should be 128-bit aligned */ +#define MDCT_BUF_SIZE FFALIGN(36, 2*4) + +extern int ff_mdct_win_fixed[8][MDCT_BUF_SIZE]; +extern float ff_mdct_win_float[8][MDCT_BUF_SIZE]; + +#endif /* AVCODEC_MPEGAUDIODSP_H */ diff --git a/ffmpeg/libavcodec/mpegaudiodsp_data.c b/ffmpeg/libavcodec/mpegaudiodsp_data.c new file mode 100644 index 0000000..4550de9 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodsp_data.c @@ -0,0 +1,56 @@ +/* + * 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 "mpegaudiodsp.h" + +/* half mpeg encoding window (full precision) */ +const int32_t ff_mpa_enwindow[257] = { + 0, -1, -1, -1, -1, -1, -1, -2, + -2, -2, -2, -3, -3, -4, -4, -5, + -5, -6, -7, -7, -8, -9, -10, -11, + -13, -14, -16, -17, -19, -21, -24, -26, + -29, -31, -35, -38, -41, -45, -49, -53, + -58, -63, -68, -73, -79, -85, -91, -97, + -104, -111, -117, -125, -132, -139, -147, -154, + -161, -169, -176, -183, -190, -196, -202, -208, + 213, 218, 222, 225, 227, 228, 228, 227, + 224, 221, 215, 208, 200, 189, 177, 163, + 146, 127, 106, 83, 57, 29, -2, -36, + -72, -111, -153, -197, -244, -294, -347, -401, + -459, -519, -581, -645, -711, -779, -848, -919, + -991, -1064, -1137, -1210, -1283, -1356, -1428, -1498, + -1567, -1634, -1698, -1759, -1817, -1870, -1919, -1962, + -2001, -2032, -2057, -2075, -2085, -2087, -2080, -2063, + 2037, 2000, 1952, 1893, 1822, 1739, 1644, 1535, + 1414, 1280, 1131, 970, 794, 605, 402, 185, + -45, -288, -545, -814, -1095, -1388, -1692, -2006, + -2330, -2663, -3004, -3351, -3705, -4063, -4425, -4788, + -5153, -5517, -5879, -6237, -6589, -6935, -7271, -7597, + -7910, -8209, -8491, -8755, -8998, -9219, -9416, -9585, + -9727, -9838, -9916, -9959, -9966, -9935, -9863, -9750, + -9592, -9389, -9139, -8840, -8492, -8092, -7640, -7134, + 6574, 5959, 5288, 4561, 3776, 2935, 2037, 1082, + 70, -998, -2122, -3300, -4533, -5818, -7154, -8540, + -9975,-11455,-12980,-14548,-16155,-17799,-19478,-21189, +-22929,-24694,-26482,-28289,-30112,-31947,-33791,-35640, +-37489,-39336,-41176,-43006,-44821,-46617,-48390,-50137, +-51853,-53534,-55178,-56778,-58333,-59838,-61289,-62684, +-64019,-65290,-66494,-67629,-68692,-69679,-70590,-71420, +-72169,-72835,-73415,-73908,-74313,-74630,-74856,-74992, + 75038, +}; diff --git a/ffmpeg/libavcodec/mpegaudiodsp_fixed.c b/ffmpeg/libavcodec/mpegaudiodsp_fixed.c new file mode 100644 index 0000000..3c49a56 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodsp_fixed.c @@ -0,0 +1,20 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define CONFIG_FLOAT 0 +#include "mpegaudiodsp_template.c" diff --git a/ffmpeg/libavcodec/mpegaudiodsp_float.c b/ffmpeg/libavcodec/mpegaudiodsp_float.c new file mode 100644 index 0000000..2d8d53e --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodsp_float.c @@ -0,0 +1,20 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define CONFIG_FLOAT 1 +#include "mpegaudiodsp_template.c" diff --git a/ffmpeg/libavcodec/mpegaudiodsp_template.c b/ffmpeg/libavcodec/mpegaudiodsp_template.c new file mode 100644 index 0000000..03a740a --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiodsp_template.c @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2001, 2002 Fabrice Bellard + * + * 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 "libavutil/mem.h" +#include "dct32.h" +#include "mathops.h" +#include "mpegaudiodsp.h" +#include "mpegaudio.h" + +#if CONFIG_FLOAT +#define RENAME(n) n##_float + +static inline float round_sample(float *sum) +{ + float sum1=*sum; + *sum = 0; + return sum1; +} + +#define MACS(rt, ra, rb) rt+=(ra)*(rb) +#define MULS(ra, rb) ((ra)*(rb)) +#define MULH3(x, y, s) ((s)*(y)*(x)) +#define MLSS(rt, ra, rb) rt-=(ra)*(rb) +#define MULLx(x, y, s) ((y)*(x)) +#define FIXHR(x) ((float)(x)) +#define FIXR(x) ((float)(x)) +#define SHR(a,b) ((a)*(1.0f/(1<<(b)))) + +#else + +#define RENAME(n) n##_fixed +#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15) + +static inline int round_sample(int64_t *sum) +{ + int sum1; + sum1 = (int)((*sum) >> OUT_SHIFT); + *sum &= (1<>(b)) +# define FIXR(a) ((int)((a) * FRAC_ONE + 0.5)) +# define FIXHR(a) ((int)((a) * (1LL<<32) + 0.5)) +#endif + +/** Window for MDCT. Actually only the elements in [0,17] and + [MDCT_BUF_SIZE/2, MDCT_BUF_SIZE/2 + 17] are actually used. The rest + is just to preserve alignment for SIMD implementations. +*/ +DECLARE_ALIGNED(16, INTFLOAT, RENAME(ff_mdct_win))[8][MDCT_BUF_SIZE]; + +DECLARE_ALIGNED(16, MPA_INT, RENAME(ff_mpa_synth_window))[512+256]; + +#define SUM8(op, sum, w, p) \ +{ \ + op(sum, (w)[0 * 64], (p)[0 * 64]); \ + op(sum, (w)[1 * 64], (p)[1 * 64]); \ + op(sum, (w)[2 * 64], (p)[2 * 64]); \ + op(sum, (w)[3 * 64], (p)[3 * 64]); \ + op(sum, (w)[4 * 64], (p)[4 * 64]); \ + op(sum, (w)[5 * 64], (p)[5 * 64]); \ + op(sum, (w)[6 * 64], (p)[6 * 64]); \ + op(sum, (w)[7 * 64], (p)[7 * 64]); \ +} + +#define SUM8P2(sum1, op1, sum2, op2, w1, w2, p) \ +{ \ + INTFLOAT tmp;\ + tmp = p[0 * 64];\ + op1(sum1, (w1)[0 * 64], tmp);\ + op2(sum2, (w2)[0 * 64], tmp);\ + tmp = p[1 * 64];\ + op1(sum1, (w1)[1 * 64], tmp);\ + op2(sum2, (w2)[1 * 64], tmp);\ + tmp = p[2 * 64];\ + op1(sum1, (w1)[2 * 64], tmp);\ + op2(sum2, (w2)[2 * 64], tmp);\ + tmp = p[3 * 64];\ + op1(sum1, (w1)[3 * 64], tmp);\ + op2(sum2, (w2)[3 * 64], tmp);\ + tmp = p[4 * 64];\ + op1(sum1, (w1)[4 * 64], tmp);\ + op2(sum2, (w2)[4 * 64], tmp);\ + tmp = p[5 * 64];\ + op1(sum1, (w1)[5 * 64], tmp);\ + op2(sum2, (w2)[5 * 64], tmp);\ + tmp = p[6 * 64];\ + op1(sum1, (w1)[6 * 64], tmp);\ + op2(sum2, (w2)[6 * 64], tmp);\ + tmp = p[7 * 64];\ + op1(sum1, (w1)[7 * 64], tmp);\ + op2(sum2, (w2)[7 * 64], tmp);\ +} + +void RENAME(ff_mpadsp_apply_window)(MPA_INT *synth_buf, MPA_INT *window, + int *dither_state, OUT_INT *samples, + int incr) +{ + register const MPA_INT *w, *w2, *p; + int j; + OUT_INT *samples2; +#if CONFIG_FLOAT + float sum, sum2; +#else + int64_t sum, sum2; +#endif + + /* copy to avoid wrap */ + memcpy(synth_buf + 512, synth_buf, 32 * sizeof(*synth_buf)); + + samples2 = samples + 31 * incr; + w = window; + w2 = window + 31; + + sum = *dither_state; + p = synth_buf + 16; + SUM8(MACS, sum, w, p); + p = synth_buf + 48; + SUM8(MLSS, sum, w + 32, p); + *samples = round_sample(&sum); + samples += incr; + w++; + + /* we calculate two samples at the same time to avoid one memory + access per two sample */ + for(j=1;j<16;j++) { + sum2 = 0; + p = synth_buf + 16 + j; + SUM8P2(sum, MACS, sum2, MLSS, w, w2, p); + p = synth_buf + 48 - j; + SUM8P2(sum, MLSS, sum2, MLSS, w + 32, w2 + 32, p); + + *samples = round_sample(&sum); + samples += incr; + sum += sum2; + *samples2 = round_sample(&sum); + samples2 -= incr; + w++; + w2--; + } + + p = synth_buf + 32; + SUM8(MLSS, sum, w + 32, p); + *samples = round_sample(&sum); + *dither_state= sum; +} + +/* 32 sub band synthesis filter. Input: 32 sub band samples, Output: + 32 samples. */ +void RENAME(ff_mpa_synth_filter)(MPADSPContext *s, MPA_INT *synth_buf_ptr, + int *synth_buf_offset, + MPA_INT *window, int *dither_state, + OUT_INT *samples, int incr, + MPA_INT *sb_samples) +{ + MPA_INT *synth_buf; + int offset; + + offset = *synth_buf_offset; + synth_buf = synth_buf_ptr + offset; + + s->RENAME(dct32)(synth_buf, sb_samples); + s->RENAME(apply_window)(synth_buf, window, dither_state, samples, incr); + + offset = (offset - 32) & 511; + *synth_buf_offset = offset; +} + +av_cold void RENAME(ff_mpa_synth_init)(MPA_INT *window) +{ + int i, j; + + /* max = 18760, max sum over all 16 coefs : 44736 */ + for(i=0;i<257;i++) { + INTFLOAT v; + v = ff_mpa_enwindow[i]; +#if CONFIG_FLOAT + v *= 1.0 / (1LL<<(16 + FRAC_BITS)); +#endif + window[i] = v; + if ((i & 63) != 0) + v = -v; + if (i != 0) + window[512 - i] = v; + } + + + // Needed for avoiding shuffles in ASM implementations + for(i=0; i < 8; i++) + for(j=0; j < 16; j++) + window[512+16*i+j] = window[64*i+32-j]; + + for(i=0; i < 8; i++) + for(j=0; j < 16; j++) + window[512+128+16*i+j] = window[64*i+48-j]; +} + +void RENAME(ff_init_mpadsp_tabs)(void) +{ + int i, j; + /* compute mdct windows */ + for (i = 0; i < 36; i++) { + for (j = 0; j < 4; j++) { + double d; + + if (j == 2 && i % 3 != 1) + continue; + + d = sin(M_PI * (i + 0.5) / 36.0); + if (j == 1) { + if (i >= 30) d = 0; + else if (i >= 24) d = sin(M_PI * (i - 18 + 0.5) / 12.0); + else if (i >= 18) d = 1; + } else if (j == 3) { + if (i < 6) d = 0; + else if (i < 12) d = sin(M_PI * (i - 6 + 0.5) / 12.0); + else if (i < 18) d = 1; + } + //merge last stage of imdct into the window coefficients + d *= 0.5 * IMDCT_SCALAR / cos(M_PI * (2 * i + 19) / 72); + + if (j == 2) + RENAME(ff_mdct_win)[j][i/3] = FIXHR((d / (1<<5))); + else { + int idx = i < 18 ? i : i + (MDCT_BUF_SIZE/2 - 18); + RENAME(ff_mdct_win)[j][idx] = FIXHR((d / (1<<5))); + } + } + } + + /* NOTE: we do frequency inversion adter the MDCT by changing + the sign of the right window coefs */ + for (j = 0; j < 4; j++) { + for (i = 0; i < MDCT_BUF_SIZE; i += 2) { + RENAME(ff_mdct_win)[j + 4][i ] = RENAME(ff_mdct_win)[j][i ]; + RENAME(ff_mdct_win)[j + 4][i + 1] = -RENAME(ff_mdct_win)[j][i + 1]; + } + } +} +/* cos(pi*i/18) */ +#define C1 FIXHR(0.98480775301220805936/2) +#define C2 FIXHR(0.93969262078590838405/2) +#define C3 FIXHR(0.86602540378443864676/2) +#define C4 FIXHR(0.76604444311897803520/2) +#define C5 FIXHR(0.64278760968653932632/2) +#define C6 FIXHR(0.5/2) +#define C7 FIXHR(0.34202014332566873304/2) +#define C8 FIXHR(0.17364817766693034885/2) + +/* 0.5 / cos(pi*(2*i+1)/36) */ +static const INTFLOAT icos36[9] = { + FIXR(0.50190991877167369479), + FIXR(0.51763809020504152469), //0 + FIXR(0.55168895948124587824), + FIXR(0.61038729438072803416), + FIXR(0.70710678118654752439), //1 + FIXR(0.87172339781054900991), + FIXR(1.18310079157624925896), + FIXR(1.93185165257813657349), //2 + FIXR(5.73685662283492756461), +}; + +/* 0.5 / cos(pi*(2*i+1)/36) */ +static const INTFLOAT icos36h[9] = { + FIXHR(0.50190991877167369479/2), + FIXHR(0.51763809020504152469/2), //0 + FIXHR(0.55168895948124587824/2), + FIXHR(0.61038729438072803416/2), + FIXHR(0.70710678118654752439/2), //1 + FIXHR(0.87172339781054900991/2), + FIXHR(1.18310079157624925896/4), + FIXHR(1.93185165257813657349/4), //2 +// FIXHR(5.73685662283492756461), +}; + +/* using Lee like decomposition followed by hand coded 9 points DCT */ +static void imdct36(INTFLOAT *out, INTFLOAT *buf, INTFLOAT *in, INTFLOAT *win) +{ + int i, j; + INTFLOAT t0, t1, t2, t3, s0, s1, s2, s3; + INTFLOAT tmp[18], *tmp1, *in1; + + for (i = 17; i >= 1; i--) + in[i] += in[i-1]; + for (i = 17; i >= 3; i -= 2) + in[i] += in[i-2]; + + for (j = 0; j < 2; j++) { + tmp1 = tmp + j; + in1 = in + j; + + t2 = in1[2*4] + in1[2*8] - in1[2*2]; + + t3 = in1[2*0] + SHR(in1[2*6],1); + t1 = in1[2*0] - in1[2*6]; + tmp1[ 6] = t1 - SHR(t2,1); + tmp1[16] = t1 + t2; + + t0 = MULH3(in1[2*2] + in1[2*4] , C2, 2); + t1 = MULH3(in1[2*4] - in1[2*8] , -2*C8, 1); + t2 = MULH3(in1[2*2] + in1[2*8] , -C4, 2); + + tmp1[10] = t3 - t0 - t2; + tmp1[ 2] = t3 + t0 + t1; + tmp1[14] = t3 + t2 - t1; + + tmp1[ 4] = MULH3(in1[2*5] + in1[2*7] - in1[2*1], -C3, 2); + t2 = MULH3(in1[2*1] + in1[2*5], C1, 2); + t3 = MULH3(in1[2*5] - in1[2*7], -2*C7, 1); + t0 = MULH3(in1[2*3], C3, 2); + + t1 = MULH3(in1[2*1] + in1[2*7], -C5, 2); + + tmp1[ 0] = t2 + t3 + t0; + tmp1[12] = t2 + t1 - t0; + tmp1[ 8] = t3 - t1 - t0; + } + + i = 0; + for (j = 0; j < 4; j++) { + t0 = tmp[i]; + t1 = tmp[i + 2]; + s0 = t1 + t0; + s2 = t1 - t0; + + t2 = tmp[i + 1]; + t3 = tmp[i + 3]; + s1 = MULH3(t3 + t2, icos36h[ j], 2); + s3 = MULLx(t3 - t2, icos36 [8 - j], FRAC_BITS); + + t0 = s0 + s1; + t1 = s0 - s1; + out[(9 + j) * SBLIMIT] = MULH3(t1, win[ 9 + j], 1) + buf[4*(9 + j)]; + out[(8 - j) * SBLIMIT] = MULH3(t1, win[ 8 - j], 1) + buf[4*(8 - j)]; + buf[4 * ( 9 + j )] = MULH3(t0, win[MDCT_BUF_SIZE/2 + 9 + j], 1); + buf[4 * ( 8 - j )] = MULH3(t0, win[MDCT_BUF_SIZE/2 + 8 - j], 1); + + t0 = s2 + s3; + t1 = s2 - s3; + out[(9 + 8 - j) * SBLIMIT] = MULH3(t1, win[ 9 + 8 - j], 1) + buf[4*(9 + 8 - j)]; + out[ j * SBLIMIT] = MULH3(t1, win[ j], 1) + buf[4*( j)]; + buf[4 * ( 9 + 8 - j )] = MULH3(t0, win[MDCT_BUF_SIZE/2 + 9 + 8 - j], 1); + buf[4 * ( j )] = MULH3(t0, win[MDCT_BUF_SIZE/2 + j], 1); + i += 4; + } + + s0 = tmp[16]; + s1 = MULH3(tmp[17], icos36h[4], 2); + t0 = s0 + s1; + t1 = s0 - s1; + out[(9 + 4) * SBLIMIT] = MULH3(t1, win[ 9 + 4], 1) + buf[4*(9 + 4)]; + out[(8 - 4) * SBLIMIT] = MULH3(t1, win[ 8 - 4], 1) + buf[4*(8 - 4)]; + buf[4 * ( 9 + 4 )] = MULH3(t0, win[MDCT_BUF_SIZE/2 + 9 + 4], 1); + buf[4 * ( 8 - 4 )] = MULH3(t0, win[MDCT_BUF_SIZE/2 + 8 - 4], 1); +} + +void RENAME(ff_imdct36_blocks)(INTFLOAT *out, INTFLOAT *buf, INTFLOAT *in, + int count, int switch_point, int block_type) +{ + int j; + for (j=0 ; j < count; j++) { + /* apply window & overlap with previous buffer */ + + /* select window */ + int win_idx = (switch_point && j < 2) ? 0 : block_type; + INTFLOAT *win = RENAME(ff_mdct_win)[win_idx + (4 & -(j & 1))]; + + imdct36(out, buf, in, win); + + in += 18; + buf += ((j&3) != 3 ? 1 : (72-3)); + out++; + } +} + diff --git a/ffmpeg/libavcodec/mpegaudioenc.c b/ffmpeg/libavcodec/mpegaudioenc.c new file mode 100644 index 0000000..3a109f0 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudioenc.c @@ -0,0 +1,788 @@ +/* + * The simplest mpeg audio layer 2 encoder + * Copyright (c) 2000, 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * The simplest mpeg audio layer 2 encoder. + */ + +#include "libavutil/channel_layout.h" + +#include "avcodec.h" +#include "internal.h" +#include "put_bits.h" + +#define FRAC_BITS 15 /* fractional bits for sb_samples and dct */ +#define WFRAC_BITS 14 /* fractional bits for window */ + +#include "mpegaudio.h" +#include "mpegaudiodsp.h" + +/* currently, cannot change these constants (need to modify + quantization stage) */ +#define MUL(a,b) (((int64_t)(a) * (int64_t)(b)) >> FRAC_BITS) + +#define SAMPLES_BUF_SIZE 4096 + +typedef struct MpegAudioContext { + PutBitContext pb; + int nb_channels; + int lsf; /* 1 if mpeg2 low bitrate selected */ + int bitrate_index; /* bit rate */ + int freq_index; + int frame_size; /* frame size, in bits, without padding */ + /* padding computation */ + int frame_frac, frame_frac_incr, do_padding; + short samples_buf[MPA_MAX_CHANNELS][SAMPLES_BUF_SIZE]; /* buffer for filter */ + int samples_offset[MPA_MAX_CHANNELS]; /* offset in samples_buf */ + int sb_samples[MPA_MAX_CHANNELS][3][12][SBLIMIT]; + unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3]; /* scale factors */ + /* code to group 3 scale factors */ + unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT]; + int sblimit; /* number of used subbands */ + const unsigned char *alloc_table; +} MpegAudioContext; + +/* define it to use floats in quantization (I don't like floats !) */ +#define USE_FLOATS + +#include "mpegaudiodata.h" +#include "mpegaudiotab.h" + +static av_cold int MPA_encode_init(AVCodecContext *avctx) +{ + MpegAudioContext *s = avctx->priv_data; + int freq = avctx->sample_rate; + int bitrate = avctx->bit_rate; + int channels = avctx->channels; + int i, v, table; + float a; + + if (channels <= 0 || channels > 2){ + av_log(avctx, AV_LOG_ERROR, "encoding %d channel(s) is not allowed in mp2\n", channels); + return AVERROR(EINVAL); + } + bitrate = bitrate / 1000; + s->nb_channels = channels; + avctx->frame_size = MPA_FRAME_SIZE; + avctx->delay = 512 - 32 + 1; + + /* encoding freq */ + s->lsf = 0; + for(i=0;i<3;i++) { + if (avpriv_mpa_freq_tab[i] == freq) + break; + if ((avpriv_mpa_freq_tab[i] / 2) == freq) { + s->lsf = 1; + break; + } + } + if (i == 3){ + av_log(avctx, AV_LOG_ERROR, "Sampling rate %d is not allowed in mp2\n", freq); + return AVERROR(EINVAL); + } + s->freq_index = i; + + /* encoding bitrate & frequency */ + for(i=0;i<15;i++) { + if (avpriv_mpa_bitrate_tab[s->lsf][1][i] == bitrate) + break; + } + if (i == 15){ + av_log(avctx, AV_LOG_ERROR, "bitrate %d is not allowed in mp2\n", bitrate); + return AVERROR(EINVAL); + } + s->bitrate_index = i; + + /* compute total header size & pad bit */ + + a = (float)(bitrate * 1000 * MPA_FRAME_SIZE) / (freq * 8.0); + s->frame_size = ((int)a) * 8; + + /* frame fractional size to compute padding */ + s->frame_frac = 0; + s->frame_frac_incr = (int)((a - floor(a)) * 65536.0); + + /* select the right allocation table */ + table = ff_mpa_l2_select_table(bitrate, s->nb_channels, freq, s->lsf); + + /* number of used subbands */ + s->sblimit = ff_mpa_sblimit_table[table]; + s->alloc_table = ff_mpa_alloc_tables[table]; + + av_dlog(avctx, "%d kb/s, %d Hz, frame_size=%d bits, table=%d, padincr=%x\n", + bitrate, freq, s->frame_size, table, s->frame_frac_incr); + + for(i=0;inb_channels;i++) + s->samples_offset[i] = 0; + + for(i=0;i<257;i++) { + int v; + v = ff_mpa_enwindow[i]; +#if WFRAC_BITS != 16 + v = (v + (1 << (16 - WFRAC_BITS - 1))) >> (16 - WFRAC_BITS); +#endif + filter_bank[i] = v; + if ((i & 63) != 0) + v = -v; + if (i != 0) + filter_bank[512 - i] = v; + } + + for(i=0;i<64;i++) { + v = (int)(exp2((3 - i) / 3.0) * (1 << 20)); + if (v <= 0) + v = 1; + scale_factor_table[i] = v; +#ifdef USE_FLOATS + scale_factor_inv_table[i] = exp2(-(3 - i) / 3.0) / (float)(1 << 20); +#else +#define P 15 + scale_factor_shift[i] = 21 - P - (i / 3); + scale_factor_mult[i] = (1 << P) * exp2((i % 3) / 3.0); +#endif + } + for(i=0;i<128;i++) { + v = i - 64; + if (v <= -3) + v = 0; + else if (v < 0) + v = 1; + else if (v == 0) + v = 2; + else if (v < 3) + v = 3; + else + v = 4; + scale_diff_table[i] = v; + } + + for(i=0;i<17;i++) { + v = ff_mpa_quant_bits[i]; + if (v < 0) + v = -v; + else + v = v * 3; + total_quant_bits[i] = 12 * v; + } + + return 0; +} + +/* 32 point floating point IDCT without 1/sqrt(2) coef zero scaling */ +static void idct32(int *out, int *tab) +{ + int i, j; + int *t, *t1, xr; + const int *xp = costab32; + + for(j=31;j>=3;j-=2) tab[j] += tab[j - 2]; + + t = tab + 30; + t1 = tab + 2; + do { + t[0] += t[-4]; + t[1] += t[1 - 4]; + t -= 4; + } while (t != t1); + + t = tab + 28; + t1 = tab + 4; + do { + t[0] += t[-8]; + t[1] += t[1-8]; + t[2] += t[2-8]; + t[3] += t[3-8]; + t -= 8; + } while (t != t1); + + t = tab; + t1 = tab + 32; + do { + t[ 3] = -t[ 3]; + t[ 6] = -t[ 6]; + + t[11] = -t[11]; + t[12] = -t[12]; + t[13] = -t[13]; + t[15] = -t[15]; + t += 16; + } while (t != t1); + + + t = tab; + t1 = tab + 8; + do { + int x1, x2, x3, x4; + + x3 = MUL(t[16], FIX(SQRT2*0.5)); + x4 = t[0] - x3; + x3 = t[0] + x3; + + x2 = MUL(-(t[24] + t[8]), FIX(SQRT2*0.5)); + x1 = MUL((t[8] - x2), xp[0]); + x2 = MUL((t[8] + x2), xp[1]); + + t[ 0] = x3 + x1; + t[ 8] = x4 - x2; + t[16] = x4 + x2; + t[24] = x3 - x1; + t++; + } while (t != t1); + + xp += 2; + t = tab; + t1 = tab + 4; + do { + xr = MUL(t[28],xp[0]); + t[28] = (t[0] - xr); + t[0] = (t[0] + xr); + + xr = MUL(t[4],xp[1]); + t[ 4] = (t[24] - xr); + t[24] = (t[24] + xr); + + xr = MUL(t[20],xp[2]); + t[20] = (t[8] - xr); + t[ 8] = (t[8] + xr); + + xr = MUL(t[12],xp[3]); + t[12] = (t[16] - xr); + t[16] = (t[16] + xr); + t++; + } while (t != t1); + xp += 4; + + for (i = 0; i < 4; i++) { + xr = MUL(tab[30-i*4],xp[0]); + tab[30-i*4] = (tab[i*4] - xr); + tab[ i*4] = (tab[i*4] + xr); + + xr = MUL(tab[ 2+i*4],xp[1]); + tab[ 2+i*4] = (tab[28-i*4] - xr); + tab[28-i*4] = (tab[28-i*4] + xr); + + xr = MUL(tab[31-i*4],xp[0]); + tab[31-i*4] = (tab[1+i*4] - xr); + tab[ 1+i*4] = (tab[1+i*4] + xr); + + xr = MUL(tab[ 3+i*4],xp[1]); + tab[ 3+i*4] = (tab[29-i*4] - xr); + tab[29-i*4] = (tab[29-i*4] + xr); + + xp += 2; + } + + t = tab + 30; + t1 = tab + 1; + do { + xr = MUL(t1[0], *xp); + t1[0] = (t[0] - xr); + t[0] = (t[0] + xr); + t -= 2; + t1 += 2; + xp++; + } while (t >= tab); + + for(i=0;i<32;i++) { + out[i] = tab[bitinv32[i]]; + } +} + +#define WSHIFT (WFRAC_BITS + 15 - FRAC_BITS) + +static void filter(MpegAudioContext *s, int ch, const short *samples, int incr) +{ + short *p, *q; + int sum, offset, i, j; + int tmp[64]; + int tmp1[32]; + int *out; + + offset = s->samples_offset[ch]; + out = &s->sb_samples[ch][0][0][0]; + for(j=0;j<36;j++) { + /* 32 samples at once */ + for(i=0;i<32;i++) { + s->samples_buf[ch][offset + (31 - i)] = samples[0]; + samples += incr; + } + + /* filter */ + p = s->samples_buf[ch] + offset; + q = filter_bank; + /* maxsum = 23169 */ + for(i=0;i<64;i++) { + sum = p[0*64] * q[0*64]; + sum += p[1*64] * q[1*64]; + sum += p[2*64] * q[2*64]; + sum += p[3*64] * q[3*64]; + sum += p[4*64] * q[4*64]; + sum += p[5*64] * q[5*64]; + sum += p[6*64] * q[6*64]; + sum += p[7*64] * q[7*64]; + tmp[i] = sum; + p++; + q++; + } + tmp1[0] = tmp[16] >> WSHIFT; + for( i=1; i<=16; i++ ) tmp1[i] = (tmp[i+16]+tmp[16-i]) >> WSHIFT; + for( i=17; i<=31; i++ ) tmp1[i] = (tmp[i+16]-tmp[80-i]) >> WSHIFT; + + idct32(out, tmp1); + + /* advance of 32 samples */ + offset -= 32; + out += 32; + /* handle the wrap around */ + if (offset < 0) { + memmove(s->samples_buf[ch] + SAMPLES_BUF_SIZE - (512 - 32), + s->samples_buf[ch], (512 - 32) * 2); + offset = SAMPLES_BUF_SIZE - 512; + } + } + s->samples_offset[ch] = offset; +} + +static void compute_scale_factors(unsigned char scale_code[SBLIMIT], + unsigned char scale_factors[SBLIMIT][3], + int sb_samples[3][12][SBLIMIT], + int sblimit) +{ + int *p, vmax, v, n, i, j, k, code; + int index, d1, d2; + unsigned char *sf = &scale_factors[0][0]; + + for(j=0;j vmax) + vmax = v; + } + /* compute the scale factor index using log 2 computations */ + if (vmax > 1) { + n = av_log2(vmax); + /* n is the position of the MSB of vmax. now + use at most 2 compares to find the index */ + index = (21 - n) * 3 - 3; + if (index >= 0) { + while (vmax <= scale_factor_table[index+1]) + index++; + } else { + index = 0; /* very unlikely case of overflow */ + } + } else { + index = 62; /* value 63 is not allowed */ + } + + av_dlog(NULL, "%2d:%d in=%x %x %d\n", + j, i, vmax, scale_factor_table[index], index); + /* store the scale factor */ + av_assert2(index >=0 && index <= 63); + sf[i] = index; + } + + /* compute the transmission factor : look if the scale factors + are close enough to each other */ + d1 = scale_diff_table[sf[0] - sf[1] + 64]; + d2 = scale_diff_table[sf[1] - sf[2] + 64]; + + /* handle the 25 cases */ + switch(d1 * 5 + d2) { + case 0*5+0: + case 0*5+4: + case 3*5+4: + case 4*5+0: + case 4*5+4: + code = 0; + break; + case 0*5+1: + case 0*5+2: + case 4*5+1: + case 4*5+2: + code = 3; + sf[2] = sf[1]; + break; + case 0*5+3: + case 4*5+3: + code = 3; + sf[1] = sf[2]; + break; + case 1*5+0: + case 1*5+4: + case 2*5+4: + code = 1; + sf[1] = sf[0]; + break; + case 1*5+1: + case 1*5+2: + case 2*5+0: + case 2*5+1: + case 2*5+2: + code = 2; + sf[1] = sf[2] = sf[0]; + break; + case 2*5+3: + case 3*5+3: + code = 2; + sf[0] = sf[1] = sf[2]; + break; + case 3*5+0: + case 3*5+1: + case 3*5+2: + code = 2; + sf[0] = sf[2] = sf[1]; + break; + case 1*5+3: + code = 2; + if (sf[0] > sf[2]) + sf[0] = sf[2]; + sf[1] = sf[2] = sf[0]; + break; + default: + av_assert2(0); //cannot happen + code = 0; /* kill warning */ + } + + av_dlog(NULL, "%d: %2d %2d %2d %d %d -> %d\n", j, + sf[0], sf[1], sf[2], d1, d2, code); + scale_code[j] = code; + sf += 3; + } +} + +/* The most important function : psycho acoustic module. In this + encoder there is basically none, so this is the worst you can do, + but also this is the simpler. */ +static void psycho_acoustic_model(MpegAudioContext *s, short smr[SBLIMIT]) +{ + int i; + + for(i=0;isblimit;i++) { + smr[i] = (int)(fixed_smr[i] * 10); + } +} + + +#define SB_NOTALLOCATED 0 +#define SB_ALLOCATED 1 +#define SB_NOMORE 2 + +/* Try to maximize the smr while using a number of bits inferior to + the frame size. I tried to make the code simpler, faster and + smaller than other encoders :-) */ +static void compute_bit_allocation(MpegAudioContext *s, + short smr1[MPA_MAX_CHANNELS][SBLIMIT], + unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT], + int *padding) +{ + int i, ch, b, max_smr, max_ch, max_sb, current_frame_size, max_frame_size; + int incr; + short smr[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char subband_status[MPA_MAX_CHANNELS][SBLIMIT]; + const unsigned char *alloc; + + memcpy(smr, smr1, s->nb_channels * sizeof(short) * SBLIMIT); + memset(subband_status, SB_NOTALLOCATED, s->nb_channels * SBLIMIT); + memset(bit_alloc, 0, s->nb_channels * SBLIMIT); + + /* compute frame size and padding */ + max_frame_size = s->frame_size; + s->frame_frac += s->frame_frac_incr; + if (s->frame_frac >= 65536) { + s->frame_frac -= 65536; + s->do_padding = 1; + max_frame_size += 8; + } else { + s->do_padding = 0; + } + + /* compute the header + bit alloc size */ + current_frame_size = 32; + alloc = s->alloc_table; + for(i=0;isblimit;i++) { + incr = alloc[0]; + current_frame_size += incr * s->nb_channels; + alloc += 1 << incr; + } + for(;;) { + /* look for the subband with the largest signal to mask ratio */ + max_sb = -1; + max_ch = -1; + max_smr = INT_MIN; + for(ch=0;chnb_channels;ch++) { + for(i=0;isblimit;i++) { + if (smr[ch][i] > max_smr && subband_status[ch][i] != SB_NOMORE) { + max_smr = smr[ch][i]; + max_sb = i; + max_ch = ch; + } + } + } + if (max_sb < 0) + break; + av_dlog(NULL, "current=%d max=%d max_sb=%d max_ch=%d alloc=%d\n", + current_frame_size, max_frame_size, max_sb, max_ch, + bit_alloc[max_ch][max_sb]); + + /* find alloc table entry (XXX: not optimal, should use + pointer table) */ + alloc = s->alloc_table; + for(i=0;iscale_code[max_ch][max_sb]] * 6; + incr += total_quant_bits[alloc[1]]; + } else { + /* increments bit allocation */ + b = bit_alloc[max_ch][max_sb]; + incr = total_quant_bits[alloc[b + 1]] - + total_quant_bits[alloc[b]]; + } + + if (current_frame_size + incr <= max_frame_size) { + /* can increase size */ + b = ++bit_alloc[max_ch][max_sb]; + current_frame_size += incr; + /* decrease smr by the resolution we added */ + smr[max_ch][max_sb] = smr1[max_ch][max_sb] - quant_snr[alloc[b]]; + /* max allocation size reached ? */ + if (b == ((1 << alloc[0]) - 1)) + subband_status[max_ch][max_sb] = SB_NOMORE; + else + subband_status[max_ch][max_sb] = SB_ALLOCATED; + } else { + /* cannot increase the size of this subband */ + subband_status[max_ch][max_sb] = SB_NOMORE; + } + } + *padding = max_frame_size - current_frame_size; + av_assert0(*padding >= 0); +} + +/* + * Output the mpeg audio layer 2 frame. Note how the code is small + * compared to other encoders :-) + */ +static void encode_frame(MpegAudioContext *s, + unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT], + int padding) +{ + int i, j, k, l, bit_alloc_bits, b, ch; + unsigned char *sf; + int q[3]; + PutBitContext *p = &s->pb; + + /* header */ + + put_bits(p, 12, 0xfff); + put_bits(p, 1, 1 - s->lsf); /* 1 = mpeg1 ID, 0 = mpeg2 lsf ID */ + put_bits(p, 2, 4-2); /* layer 2 */ + put_bits(p, 1, 1); /* no error protection */ + put_bits(p, 4, s->bitrate_index); + put_bits(p, 2, s->freq_index); + put_bits(p, 1, s->do_padding); /* use padding */ + put_bits(p, 1, 0); /* private_bit */ + put_bits(p, 2, s->nb_channels == 2 ? MPA_STEREO : MPA_MONO); + put_bits(p, 2, 0); /* mode_ext */ + put_bits(p, 1, 0); /* no copyright */ + put_bits(p, 1, 1); /* original */ + put_bits(p, 2, 0); /* no emphasis */ + + /* bit allocation */ + j = 0; + for(i=0;isblimit;i++) { + bit_alloc_bits = s->alloc_table[j]; + for(ch=0;chnb_channels;ch++) { + put_bits(p, bit_alloc_bits, bit_alloc[ch][i]); + } + j += 1 << bit_alloc_bits; + } + + /* scale codes */ + for(i=0;isblimit;i++) { + for(ch=0;chnb_channels;ch++) { + if (bit_alloc[ch][i]) + put_bits(p, 2, s->scale_code[ch][i]); + } + } + + /* scale factors */ + for(i=0;isblimit;i++) { + for(ch=0;chnb_channels;ch++) { + if (bit_alloc[ch][i]) { + sf = &s->scale_factors[ch][i][0]; + switch(s->scale_code[ch][i]) { + case 0: + put_bits(p, 6, sf[0]); + put_bits(p, 6, sf[1]); + put_bits(p, 6, sf[2]); + break; + case 3: + case 1: + put_bits(p, 6, sf[0]); + put_bits(p, 6, sf[2]); + break; + case 2: + put_bits(p, 6, sf[0]); + break; + } + } + } + } + + /* quantization & write sub band samples */ + + for(k=0;k<3;k++) { + for(l=0;l<12;l+=3) { + j = 0; + for(i=0;isblimit;i++) { + bit_alloc_bits = s->alloc_table[j]; + for(ch=0;chnb_channels;ch++) { + b = bit_alloc[ch][i]; + if (b) { + int qindex, steps, m, sample, bits; + /* we encode 3 sub band samples of the same sub band at a time */ + qindex = s->alloc_table[j+b]; + steps = ff_mpa_quant_steps[qindex]; + for(m=0;m<3;m++) { + sample = s->sb_samples[ch][k][l + m][i]; + /* divide by scale factor */ +#ifdef USE_FLOATS + { + float a; + a = (float)sample * scale_factor_inv_table[s->scale_factors[ch][i][k]]; + q[m] = (int)((a + 1.0) * steps * 0.5); + } +#else + { + int q1, e, shift, mult; + e = s->scale_factors[ch][i][k]; + shift = scale_factor_shift[e]; + mult = scale_factor_mult[e]; + + /* normalize to P bits */ + if (shift < 0) + q1 = sample << (-shift); + else + q1 = sample >> shift; + q1 = (q1 * mult) >> P; + q[m] = ((q1 + (1 << P)) * steps) >> (P + 1); + } +#endif + if (q[m] >= steps) + q[m] = steps - 1; + av_assert2(q[m] >= 0 && q[m] < steps); + } + bits = ff_mpa_quant_bits[qindex]; + if (bits < 0) { + /* group the 3 values to save bits */ + put_bits(p, -bits, + q[0] + steps * (q[1] + steps * q[2])); + } else { + put_bits(p, bits, q[0]); + put_bits(p, bits, q[1]); + put_bits(p, bits, q[2]); + } + } + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + } + } + + /* padding */ + for(i=0;ipriv_data; + const int16_t *samples = (const int16_t *)frame->data[0]; + short smr[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT]; + int padding, i, ret; + + for(i=0;inb_channels;i++) { + filter(s, i, samples + i, s->nb_channels); + } + + for(i=0;inb_channels;i++) { + compute_scale_factors(s->scale_code[i], s->scale_factors[i], + s->sb_samples[i], s->sblimit); + } + for(i=0;inb_channels;i++) { + psycho_acoustic_model(s, smr[i]); + } + compute_bit_allocation(s, smr, bit_alloc, &padding); + + if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE)) < 0) + return ret; + + init_put_bits(&s->pb, avpkt->data, avpkt->size); + + encode_frame(s, bit_alloc, padding); + + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + + avpkt->size = put_bits_count(&s->pb) / 8; + *got_packet_ptr = 1; + return 0; +} + +static const AVCodecDefault mp2_defaults[] = { + { "b", "128k" }, + { NULL }, +}; + +AVCodec ff_mp2_encoder = { + .name = "mp2", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_MP2, + .priv_data_size = sizeof(MpegAudioContext), + .init = MPA_encode_init, + .encode2 = MPA_encode_frame, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]){ + 44100, 48000, 32000, 22050, 24000, 16000, 0 + }, + .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + 0 }, + .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .defaults = mp2_defaults, +}; diff --git a/ffmpeg/libavcodec/mpegaudiotab.h b/ffmpeg/libavcodec/mpegaudiotab.h new file mode 100644 index 0000000..35129e6 --- /dev/null +++ b/ffmpeg/libavcodec/mpegaudiotab.h @@ -0,0 +1,118 @@ +/* + * mpeg audio layer 2 tables. Most of them come from the mpeg audio + * specification. + * + * Copyright (c) 2000, 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * mpeg audio layer 2 tables. + * Most of them come from the mpeg audio specification. + */ + +#ifndef AVCODEC_MPEGAUDIOTAB_H +#define AVCODEC_MPEGAUDIOTAB_H + +#include +#include "mpegaudio.h" + +#define SQRT2 1.41421356237309514547 + +static const int costab32[30] = { + FIX(0.54119610014619701222), + FIX(1.3065629648763763537), + + FIX(0.50979557910415917998), + FIX(2.5629154477415054814), + FIX(0.89997622313641556513), + FIX(0.60134488693504528634), + + FIX(0.5024192861881556782), + FIX(5.1011486186891552563), + FIX(0.78815462345125020249), + FIX(0.64682178335999007679), + FIX(0.56694403481635768927), + FIX(1.0606776859903470633), + FIX(1.7224470982383341955), + FIX(0.52249861493968885462), + + FIX(10.19000812354803287), + FIX(0.674808341455005678), + FIX(1.1694399334328846596), + FIX(0.53104259108978413284), + FIX(2.0577810099534108446), + FIX(0.58293496820613388554), + FIX(0.83934964541552681272), + FIX(0.50547095989754364798), + FIX(3.4076084184687189804), + FIX(0.62250412303566482475), + FIX(0.97256823786196078263), + FIX(0.51544730992262455249), + FIX(1.4841646163141661852), + FIX(0.5531038960344445421), + FIX(0.74453627100229857749), + FIX(0.5006029982351962726), +}; + +static const int bitinv32[32] = { + 0, 16, 8, 24, 4, 20, 12, 28, + 2, 18, 10, 26, 6, 22, 14, 30, + 1, 17, 9, 25, 5, 21, 13, 29, + 3, 19, 11, 27, 7, 23, 15, 31 +}; + + +static int16_t filter_bank[512]; + +static int scale_factor_table[64]; +#ifdef USE_FLOATS +static float scale_factor_inv_table[64]; +#else +static int8_t scale_factor_shift[64]; +static unsigned short scale_factor_mult[64]; +#endif +static unsigned char scale_diff_table[128]; + +/* total number of bits per allocation group */ +static unsigned short total_quant_bits[17]; + +/* signal to noise ratio of each quantification step (could be + computed from quant_steps[]). The values are dB multiplied by 10 +*/ +static const unsigned short quant_snr[17] = { + 70, 110, 160, 208, + 253, 316, 378, 439, + 499, 559, 620, 680, + 740, 800, 861, 920, + 980 +}; + +/* fixed psycho acoustic model. Values of SNR taken from the 'toolame' + project */ +static const float fixed_smr[SBLIMIT] = { + 30, 17, 16, 10, 3, 12, 8, 2.5, + 5, 5, 6, 6, 5, 6, 10, 6, + -4, -10, -21, -30, -42, -55, -68, -75, + -75, -75, -75, -75, -91, -107, -110, -108 +}; + +static const unsigned char nb_scale_factors[4] = { 3, 2, 1, 2 }; + +#endif /* AVCODEC_MPEGAUDIOTAB_H */ diff --git a/ffmpeg/libavcodec/mpegvideo.c b/ffmpeg/libavcodec/mpegvideo.c new file mode 100644 index 0000000..46f829c --- /dev/null +++ b/ffmpeg/libavcodec/mpegvideo.c @@ -0,0 +1,3365 @@ +/* + * The simplest mpeg encoder (well, it was the simplest!) + * 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 + */ + +/** + * @file + * The simplest mpeg encoder (well, it was the simplest!). + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "dsputil.h" +#include "h264chroma.h" +#include "internal.h" +#include "mathops.h" +#include "mpegvideo.h" +#include "mjpegenc.h" +#include "msmpeg4.h" +#include "xvmc_internal.h" +#include "thread.h" +#include + +//#undef NDEBUG +//#include + +static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, + int16_t *block, int n, int qscale); +static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, + int16_t *block, int n, int qscale); +static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, + int16_t *block, int n, int qscale); +static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, + int16_t *block, int n, int qscale); +static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, + int16_t *block, int n, int qscale); +static void dct_unquantize_h263_intra_c(MpegEncContext *s, + int16_t *block, int n, int qscale); +static void dct_unquantize_h263_inter_c(MpegEncContext *s, + int16_t *block, int n, int qscale); + + +//#define DEBUG + + +static const uint8_t ff_default_chroma_qscale_table[32] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 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 +}; + +const uint8_t ff_mpeg1_dc_scale_table[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static const uint8_t mpeg2_dc_scale_table1[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +static const uint8_t mpeg2_dc_scale_table2[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +}; + +static const uint8_t mpeg2_dc_scale_table3[128] = { +// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +const uint8_t *const ff_mpeg2_dc_scale_table[4] = { + ff_mpeg1_dc_scale_table, + mpeg2_dc_scale_table1, + mpeg2_dc_scale_table2, + mpeg2_dc_scale_table3, +}; + +const enum AVPixelFormat ff_pixfmt_list_420[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, + int (*mv)[2][4][2], + int mb_x, int mb_y, int mb_intra, int mb_skipped) +{ + MpegEncContext *s = opaque; + + s->mv_dir = mv_dir; + s->mv_type = mv_type; + s->mb_intra = mb_intra; + s->mb_skipped = mb_skipped; + s->mb_x = mb_x; + s->mb_y = mb_y; + memcpy(s->mv, mv, sizeof(*mv)); + + ff_init_block_index(s); + ff_update_block_index(s); + + s->dsp.clear_blocks(s->block[0]); + + s->dest[0] = s->current_picture.f.data[0] + (s->mb_y * 16 * s->linesize) + s->mb_x * 16; + s->dest[1] = s->current_picture.f.data[1] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); + s->dest[2] = s->current_picture.f.data[2] + (s->mb_y * (16 >> s->chroma_y_shift) * s->uvlinesize) + s->mb_x * (16 >> s->chroma_x_shift); + + assert(ref == 0); + ff_MPV_decode_mb(s, s->block); +} + +const uint8_t *avpriv_mpv_find_start_code(const uint8_t *av_restrict p, + const uint8_t *end, + uint32_t *av_restrict state) +{ + int i; + + assert(p <= end); + if (p >= end) + return end; + + for (i = 0; i < 3; i++) { + uint32_t tmp = *state << 8; + *state = tmp + *(p++); + if (tmp == 0x100 || p == end) + return p; + } + + while (p < end) { + if (p[-1] > 1 ) p += 3; + else if (p[-2] ) p += 2; + else if (p[-3]|(p[-1]-1)) p++; + else { + p++; + break; + } + } + + p = FFMIN(p, end) - 4; + *state = AV_RB32(p); + + return p + 4; +} + +/* init common dct for both encoder and decoder */ +av_cold int ff_dct_common_init(MpegEncContext *s) +{ + ff_dsputil_init(&s->dsp, s->avctx); + ff_h264chroma_init(&s->h264chroma, 8); //for lowres + ff_hpeldsp_init(&s->hdsp, s->avctx->flags); + ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample); + + 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 (s->flags & CODEC_FLAG_BITEXACT) + s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact; + s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; + +#if ARCH_X86 + ff_MPV_common_init_x86(s); +#elif ARCH_ALPHA + ff_MPV_common_init_axp(s); +#elif ARCH_ARM + ff_MPV_common_init_arm(s); +#elif HAVE_ALTIVEC + ff_MPV_common_init_altivec(s); +#elif ARCH_BFIN + ff_MPV_common_init_bfin(s); +#endif + + /* load & permutate scantables + * note: only wmv uses different ones + */ + if (s->alternate_scan) { + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_alternate_vertical_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_alternate_vertical_scan); + } else { + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_zigzag_direct); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_zigzag_direct); + } + ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); + + return 0; +} + +int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize) +{ + int alloc_size = FFALIGN(FFABS(linesize) + 64, 32); + + // edge emu needs blocksize + filter length - 1 + // (= 17x17 for halfpel / 21x21 for h264) + // VC1 computes luma and chroma simultaneously and needs 19X19 + 9x9 + // at uvlinesize. It supports only YUV420 so 24x24 is enough + // linesize * interlaced * MBsize + FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer, alloc_size * 4 * 24, + fail); + + FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad, alloc_size * 4 * 16 * 2, + fail) + s->me.temp = s->me.scratchpad; + s->rd_scratchpad = s->me.scratchpad; + s->b_scratchpad = s->me.scratchpad; + s->obmc_scratchpad = s->me.scratchpad + 16; + + return 0; +fail: + av_freep(&s->edge_emu_buffer); + return AVERROR(ENOMEM); +} + +/** + * Allocate a frame buffer + */ +static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) +{ + int r, ret; + + pic->tf.f = &pic->f; + if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && + s->codec_id != AV_CODEC_ID_VC1IMAGE && + s->codec_id != AV_CODEC_ID_MSS2) + r = ff_thread_get_buffer(s->avctx, &pic->tf, + pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); + else { + pic->f.width = s->avctx->width; + pic->f.height = s->avctx->height; + pic->f.format = s->avctx->pix_fmt; + r = avcodec_default_get_buffer2(s->avctx, &pic->f, 0); + } + + if (r < 0 || !pic->f.data[0]) { + av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %p)\n", + r, pic->f.data[0]); + return -1; + } + + if (s->avctx->hwaccel) { + assert(!pic->hwaccel_picture_private); + if (s->avctx->hwaccel->priv_data_size) { + pic->hwaccel_priv_buf = av_buffer_allocz(s->avctx->hwaccel->priv_data_size); + if (!pic->hwaccel_priv_buf) { + av_log(s->avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n"); + return -1; + } + pic->hwaccel_picture_private = pic->hwaccel_priv_buf->data; + } + } + + if (s->linesize && (s->linesize != pic->f.linesize[0] || + s->uvlinesize != pic->f.linesize[1])) { + av_log(s->avctx, AV_LOG_ERROR, + "get_buffer() failed (stride changed)\n"); + ff_mpeg_unref_picture(s, pic); + return -1; + } + + if (pic->f.linesize[1] != pic->f.linesize[2]) { + av_log(s->avctx, AV_LOG_ERROR, + "get_buffer() failed (uv stride mismatch)\n"); + ff_mpeg_unref_picture(s, pic); + return -1; + } + + if (!s->edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(s, pic->f.linesize[0])) < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "get_buffer() failed to allocate context scratch buffers.\n"); + ff_mpeg_unref_picture(s, pic); + return ret; + } + + return 0; +} + +static void free_picture_tables(Picture *pic) +{ + int i; + + av_buffer_unref(&pic->mb_var_buf); + av_buffer_unref(&pic->mc_mb_var_buf); + av_buffer_unref(&pic->mb_mean_buf); + av_buffer_unref(&pic->mbskip_table_buf); + av_buffer_unref(&pic->qscale_table_buf); + av_buffer_unref(&pic->mb_type_buf); + + for (i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } +} + +static int alloc_picture_tables(MpegEncContext *s, Picture *pic) +{ + const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1; + const int mb_array_size = s->mb_stride * s->mb_height; + const int b8_array_size = s->b8_stride * s->mb_height * 2; + int i; + + + pic->mbskip_table_buf = av_buffer_allocz(mb_array_size + 2); + pic->qscale_table_buf = av_buffer_allocz(big_mb_num + s->mb_stride); + pic->mb_type_buf = av_buffer_allocz((big_mb_num + s->mb_stride) * + sizeof(uint32_t)); + if (!pic->mbskip_table_buf || !pic->qscale_table_buf || !pic->mb_type_buf) + return AVERROR(ENOMEM); + + if (s->encoding) { + pic->mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); + pic->mc_mb_var_buf = av_buffer_allocz(mb_array_size * sizeof(int16_t)); + pic->mb_mean_buf = av_buffer_allocz(mb_array_size); + if (!pic->mb_var_buf || !pic->mc_mb_var_buf || !pic->mb_mean_buf) + return AVERROR(ENOMEM); + } + + if (s->out_format == FMT_H263 || s->encoding || + (s->avctx->debug & FF_DEBUG_MV) || s->avctx->debug_mv) { + int mv_size = 2 * (b8_array_size + 4) * sizeof(int16_t); + int ref_index_size = 4 * mb_array_size; + + for (i = 0; mv_size && i < 2; i++) { + pic->motion_val_buf[i] = av_buffer_allocz(mv_size); + pic->ref_index_buf[i] = av_buffer_allocz(ref_index_size); + if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) + return AVERROR(ENOMEM); + } + } + + return 0; +} + +static int make_tables_writable(Picture *pic) +{ + int ret, i; +#define MAKE_WRITABLE(table) \ +do {\ + if (pic->table &&\ + (ret = av_buffer_make_writable(&pic->table)) < 0)\ + return ret;\ +} while (0) + + MAKE_WRITABLE(mb_var_buf); + MAKE_WRITABLE(mc_mb_var_buf); + MAKE_WRITABLE(mb_mean_buf); + MAKE_WRITABLE(mbskip_table_buf); + MAKE_WRITABLE(qscale_table_buf); + MAKE_WRITABLE(mb_type_buf); + + for (i = 0; i < 2; i++) { + MAKE_WRITABLE(motion_val_buf[i]); + MAKE_WRITABLE(ref_index_buf[i]); + } + + return 0; +} + +/** + * Allocate a Picture. + * The pixels are allocated/set by calling get_buffer() if shared = 0 + */ +int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared) +{ + int i, ret; + + if (pic->qscale_table_buf) + if (pic->mbskip_table_buf->size < s->mb_stride * s->mb_height + 2 || + pic->qscale_table_buf->size < s->mb_stride * (s->mb_height + 1) + 1 + s->mb_stride) + free_picture_tables(pic); + + if (shared) { + assert(pic->f.data[0]); + pic->shared = 1; + } else { + assert(!pic->f.data[0]); + + if (alloc_frame_buffer(s, pic) < 0) + return -1; + + s->linesize = pic->f.linesize[0]; + s->uvlinesize = pic->f.linesize[1]; + } + + if (!pic->qscale_table_buf) + ret = alloc_picture_tables(s, pic); + else + ret = make_tables_writable(pic); + if (ret < 0) + goto fail; + + if (s->encoding) { + pic->mb_var = (uint16_t*)pic->mb_var_buf->data; + pic->mc_mb_var = (uint16_t*)pic->mc_mb_var_buf->data; + pic->mb_mean = pic->mb_mean_buf->data; + } + + pic->mbskip_table = pic->mbskip_table_buf->data; + pic->qscale_table = pic->qscale_table_buf->data + 2 * s->mb_stride + 1; + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * s->mb_stride + 1; + + if (pic->motion_val_buf[0]) { + for (i = 0; i < 2; i++) { + pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; + pic->ref_index[i] = pic->ref_index_buf[i]->data; + } + } + + return 0; +fail: + av_log(s->avctx, AV_LOG_ERROR, "Error allocating a picture.\n"); + ff_mpeg_unref_picture(s, pic); + free_picture_tables(pic); + return AVERROR(ENOMEM); +} + +/** + * Deallocate a picture. + */ +void ff_mpeg_unref_picture(MpegEncContext *s, Picture *pic) +{ + int off = offsetof(Picture, mb_mean) + sizeof(pic->mb_mean); + pic->period_since_free = 0; + + pic->tf.f = &pic->f; + /* WM Image / Screen codecs allocate internal buffers with different + * dimensions / colorspaces; ignore user-defined callbacks for these. */ + if (s->codec_id != AV_CODEC_ID_WMV3IMAGE && + s->codec_id != AV_CODEC_ID_VC1IMAGE && + s->codec_id != AV_CODEC_ID_MSS2) + ff_thread_release_buffer(s->avctx, &pic->tf); + else + av_frame_unref(&pic->f); + + av_buffer_unref(&pic->hwaccel_priv_buf); + + memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); +} + +static int update_picture_tables(Picture *dst, Picture *src) +{ + int i; + +#define UPDATE_TABLE(table)\ +do {\ + if (src->table &&\ + (!dst->table || dst->table->buffer != src->table->buffer)) {\ + av_buffer_unref(&dst->table);\ + dst->table = av_buffer_ref(src->table);\ + if (!dst->table) {\ + free_picture_tables(dst);\ + return AVERROR(ENOMEM);\ + }\ + }\ +} while (0) + + UPDATE_TABLE(mb_var_buf); + UPDATE_TABLE(mc_mb_var_buf); + UPDATE_TABLE(mb_mean_buf); + UPDATE_TABLE(mbskip_table_buf); + UPDATE_TABLE(qscale_table_buf); + UPDATE_TABLE(mb_type_buf); + for (i = 0; i < 2; i++) { + UPDATE_TABLE(motion_val_buf[i]); + UPDATE_TABLE(ref_index_buf[i]); + } + + dst->mb_var = src->mb_var; + dst->mc_mb_var = src->mc_mb_var; + dst->mb_mean = src->mb_mean; + dst->mbskip_table = src->mbskip_table; + dst->qscale_table = src->qscale_table; + dst->mb_type = src->mb_type; + for (i = 0; i < 2; i++) { + dst->motion_val[i] = src->motion_val[i]; + dst->ref_index[i] = src->ref_index[i]; + } + + return 0; +} + +int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src) +{ + int ret; + + av_assert0(!dst->f.buf[0]); + av_assert0(src->f.buf[0]); + + src->tf.f = &src->f; + dst->tf.f = &dst->f; + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + if (ret < 0) + goto fail; + + ret = update_picture_tables(dst, src); + if (ret < 0) + goto fail; + + if (src->hwaccel_picture_private) { + dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); + if (!dst->hwaccel_priv_buf) + goto fail; + dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; + } + + dst->field_picture = src->field_picture; + dst->mb_var_sum = src->mb_var_sum; + dst->mc_mb_var_sum = src->mc_mb_var_sum; + dst->b_frame_score = src->b_frame_score; + dst->needs_realloc = src->needs_realloc; + dst->reference = src->reference; + dst->shared = src->shared; + + return 0; +fail: + ff_mpeg_unref_picture(s, dst); + return ret; +} + +static int init_duplicate_context(MpegEncContext *s) +{ + int y_size = s->b8_stride * (2 * s->mb_height + 1); + int c_size = s->mb_stride * (s->mb_height + 1); + int yc_size = y_size + 2 * c_size; + int i; + + s->edge_emu_buffer = + s->me.scratchpad = + s->me.temp = + s->rd_scratchpad = + s->b_scratchpad = + s->obmc_scratchpad = NULL; + + if (s->encoding) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->me.map, + ME_MAP_SIZE * sizeof(uint32_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->me.score_map, + ME_MAP_SIZE * sizeof(uint32_t), fail) + if (s->avctx->noise_reduction) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_error_sum, + 2 * 64 * sizeof(int), fail) + } + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->blocks, 64 * 12 * 2 * sizeof(int16_t), fail) + s->block = s->blocks[0]; + + for (i = 0; i < 12; i++) { + s->pblocks[i] = &s->block[i]; + } + + if (s->out_format == FMT_H263) { + /* ac values */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_val_base, + yc_size * sizeof(int16_t) * 16, fail); + s->ac_val[0] = s->ac_val_base + s->b8_stride + 1; + s->ac_val[1] = s->ac_val_base + y_size + s->mb_stride + 1; + s->ac_val[2] = s->ac_val[1] + c_size; + } + + return 0; +fail: + return -1; // free() through ff_MPV_common_end() +} + +static void free_duplicate_context(MpegEncContext *s) +{ + if (s == NULL) + return; + + av_freep(&s->edge_emu_buffer); + av_freep(&s->me.scratchpad); + s->me.temp = + s->rd_scratchpad = + s->b_scratchpad = + s->obmc_scratchpad = NULL; + + av_freep(&s->dct_error_sum); + av_freep(&s->me.map); + av_freep(&s->me.score_map); + av_freep(&s->blocks); + av_freep(&s->ac_val_base); + s->block = NULL; +} + +static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) +{ +#define COPY(a) bak->a = src->a + COPY(edge_emu_buffer); + COPY(me.scratchpad); + COPY(me.temp); + COPY(rd_scratchpad); + COPY(b_scratchpad); + COPY(obmc_scratchpad); + COPY(me.map); + COPY(me.score_map); + COPY(blocks); + COPY(block); + COPY(start_mb_y); + COPY(end_mb_y); + COPY(me.map_generation); + COPY(pb); + COPY(dct_error_sum); + COPY(dct_count[0]); + COPY(dct_count[1]); + COPY(ac_val_base); + COPY(ac_val[0]); + COPY(ac_val[1]); + COPY(ac_val[2]); +#undef COPY +} + +int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) +{ + MpegEncContext bak; + int i, ret; + // FIXME copy only needed parts + // START_TIMER + backup_duplicate_context(&bak, dst); + memcpy(dst, src, sizeof(MpegEncContext)); + backup_duplicate_context(dst, &bak); + for (i = 0; i < 12; i++) { + dst->pblocks[i] = &dst->block[i]; + } + if (!dst->edge_emu_buffer && + (ret = ff_mpv_frame_size_alloc(dst, dst->linesize)) < 0) { + av_log(dst->avctx, AV_LOG_ERROR, "failed to allocate context " + "scratch buffers.\n"); + return ret; + } + // STOP_TIMER("update_duplicate_context") + // about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads + return 0; +} + +int ff_mpeg_update_thread_context(AVCodecContext *dst, + const AVCodecContext *src) +{ + int i, ret; + MpegEncContext *s = dst->priv_data, *s1 = src->priv_data; + + if (dst == src) + return 0; + + av_assert0(s != s1); + + // FIXME can parameters change on I-frames? + // in that case dst may need a reinit + if (!s->context_initialized) { + memcpy(s, s1, sizeof(MpegEncContext)); + + s->avctx = dst; + s->bitstream_buffer = NULL; + s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; + + if (s1->context_initialized){ +// s->picture_range_start += MAX_PICTURE_COUNT; +// s->picture_range_end += MAX_PICTURE_COUNT; + if((ret = ff_MPV_common_init(s)) < 0){ + memset(s, 0, sizeof(MpegEncContext)); + s->avctx = dst; + return ret; + } + } + } + + if (s->height != s1->height || s->width != s1->width || s->context_reinit) { + s->context_reinit = 0; + s->height = s1->height; + s->width = s1->width; + if ((ret = ff_MPV_common_frame_size_change(s)) < 0) + return ret; + } + + s->avctx->coded_height = s1->avctx->coded_height; + s->avctx->coded_width = s1->avctx->coded_width; + s->avctx->width = s1->avctx->width; + s->avctx->height = s1->avctx->height; + + s->coded_picture_number = s1->coded_picture_number; + s->picture_number = s1->picture_number; + s->input_picture_number = s1->input_picture_number; + + av_assert0(!s->picture || s->picture != s1->picture); + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + ff_mpeg_unref_picture(s, &s->picture[i]); + if (s1->picture[i].f.data[0] && + (ret = ff_mpeg_ref_picture(s, &s->picture[i], &s1->picture[i])) < 0) + return ret; + s->picture[i].period_since_free ++; + } + +#define UPDATE_PICTURE(pic)\ +do {\ + ff_mpeg_unref_picture(s, &s->pic);\ + if (s1->pic.f.data[0])\ + ret = ff_mpeg_ref_picture(s, &s->pic, &s1->pic);\ + else\ + ret = update_picture_tables(&s->pic, &s1->pic);\ + if (ret < 0)\ + return ret;\ +} while (0) + + UPDATE_PICTURE(current_picture); + UPDATE_PICTURE(last_picture); + UPDATE_PICTURE(next_picture); + + s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); + s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); + s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); + + // Error/bug resilience + s->next_p_frame_damaged = s1->next_p_frame_damaged; + s->workaround_bugs = s1->workaround_bugs; + s->padding_bug_score = s1->padding_bug_score; + + // MPEG4 timing info + memcpy(&s->time_increment_bits, &s1->time_increment_bits, + (char *) &s1->shape - (char *) &s1->time_increment_bits); + + // B-frame info + s->max_b_frames = s1->max_b_frames; + s->low_delay = s1->low_delay; + s->droppable = s1->droppable; + + // DivX handling (doesn't work) + s->divx_packed = s1->divx_packed; + + if (s1->bitstream_buffer) { + if (s1->bitstream_buffer_size + + FF_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) + av_fast_malloc(&s->bitstream_buffer, + &s->allocated_bitstream_buffer_size, + s1->allocated_bitstream_buffer_size); + s->bitstream_buffer_size = s1->bitstream_buffer_size; + memcpy(s->bitstream_buffer, s1->bitstream_buffer, + s1->bitstream_buffer_size); + memset(s->bitstream_buffer + s->bitstream_buffer_size, 0, + FF_INPUT_BUFFER_PADDING_SIZE); + } + + // linesize dependend scratch buffer allocation + if (!s->edge_emu_buffer) + if (s1->linesize) { + if (ff_mpv_frame_size_alloc(s, s1->linesize) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " + "scratch buffers.\n"); + return AVERROR(ENOMEM); + } + } else { + av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " + "be allocated due to unknown size.\n"); + } + + // MPEG2/interlacing info + memcpy(&s->progressive_sequence, &s1->progressive_sequence, + (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); + + if (!s1->first_field) { + s->last_pict_type = s1->pict_type; + if (s1->current_picture_ptr) + s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f.quality; + + if (s1->pict_type != AV_PICTURE_TYPE_B) { + s->last_non_b_pict_type = s1->pict_type; + } + } + + return 0; +} + +/** + * Set the given MpegEncContext to common defaults + * (same for encoding and decoding). + * The changed fields will not depend upon the + * prior state of the MpegEncContext. + */ +void ff_MPV_common_defaults(MpegEncContext *s) +{ + s->y_dc_scale_table = + s->c_dc_scale_table = ff_mpeg1_dc_scale_table; + s->chroma_qscale_table = ff_default_chroma_qscale_table; + s->progressive_frame = 1; + s->progressive_sequence = 1; + s->picture_structure = PICT_FRAME; + + s->coded_picture_number = 0; + s->picture_number = 0; + s->input_picture_number = 0; + + s->picture_in_gop_number = 0; + + s->f_code = 1; + s->b_code = 1; + + s->slice_context_count = 1; +} + +/** + * Set the given MpegEncContext to defaults for decoding. + * the changed fields will not depend upon + * the prior state of the MpegEncContext. + */ +void ff_MPV_decode_defaults(MpegEncContext *s) +{ + ff_MPV_common_defaults(s); +} + +static int init_er(MpegEncContext *s) +{ + ERContext *er = &s->er; + int mb_array_size = s->mb_height * s->mb_stride; + int i; + + er->avctx = s->avctx; + er->dsp = &s->dsp; + + er->mb_index2xy = s->mb_index2xy; + er->mb_num = s->mb_num; + er->mb_width = s->mb_width; + er->mb_height = s->mb_height; + er->mb_stride = s->mb_stride; + er->b8_stride = s->b8_stride; + + er->er_temp_buffer = av_malloc(s->mb_height * s->mb_stride); + er->error_status_table = av_mallocz(mb_array_size); + if (!er->er_temp_buffer || !er->error_status_table) + goto fail; + + er->mbskip_table = s->mbskip_table; + er->mbintra_table = s->mbintra_table; + + for (i = 0; i < FF_ARRAY_ELEMS(s->dc_val); i++) + er->dc_val[i] = s->dc_val[i]; + + er->decode_mb = mpeg_er_decode_mb; + er->opaque = s; + + return 0; +fail: + av_freep(&er->er_temp_buffer); + av_freep(&er->error_status_table); + return AVERROR(ENOMEM); +} + +/** + * Initialize and allocates MpegEncContext fields dependent on the resolution. + */ +static int init_context_frame(MpegEncContext *s) +{ + int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; + + s->mb_width = (s->width + 15) / 16; + s->mb_stride = s->mb_width + 1; + s->b8_stride = s->mb_width * 2 + 1; + s->b4_stride = s->mb_width * 4 + 1; + mb_array_size = s->mb_height * s->mb_stride; + mv_table_size = (s->mb_height + 2) * s->mb_stride + 1; + + /* set default edge pos, will be overriden + * in decode_header if needed */ + s->h_edge_pos = s->mb_width * 16; + s->v_edge_pos = s->mb_height * 16; + + s->mb_num = s->mb_width * s->mb_height; + + s->block_wrap[0] = + s->block_wrap[1] = + s->block_wrap[2] = + s->block_wrap[3] = s->b8_stride; + s->block_wrap[4] = + s->block_wrap[5] = s->mb_stride; + + y_size = s->b8_stride * (2 * s->mb_height + 1); + c_size = s->mb_stride * (s->mb_height + 1); + yc_size = y_size + 2 * c_size; + + FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), fail); // error ressilience code looks cleaner with this + for (y = 0; y < s->mb_height; y++) + for (x = 0; x < s->mb_width; x++) + s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride; + + s->mb_index2xy[s->mb_height * s->mb_width] = (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed? + + if (s->encoding) { + /* Allocate MV tables */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base, mv_table_size * 2 * sizeof(int16_t), fail) + s->p_mv_table = s->p_mv_table_base + s->mb_stride + 1; + s->b_forw_mv_table = s->b_forw_mv_table_base + s->mb_stride + 1; + s->b_back_mv_table = s->b_back_mv_table_base + s->mb_stride + 1; + s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base + s->mb_stride + 1; + s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base + s->mb_stride + 1; + s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; + + /* Allocate MB type table */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size * sizeof(uint16_t), fail) // needed for encoding + + FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * sizeof(int), fail) + + FF_ALLOC_OR_GOTO(s->avctx, s->cplx_tab, + mb_array_size * sizeof(float), fail); + FF_ALLOC_OR_GOTO(s->avctx, s->bits_tab, + mb_array_size * sizeof(float), fail); + + } + + if (s->codec_id == AV_CODEC_ID_MPEG4 || + (s->flags & CODEC_FLAG_INTERLACED_ME)) { + /* interlaced direct mode decoding tables */ + for (i = 0; i < 2; i++) { + int j, k; + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + FF_ALLOCZ_OR_GOTO(s->avctx, + s->b_field_mv_table_base[i][j][k], + mv_table_size * 2 * sizeof(int16_t), + fail); + s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + + s->mb_stride + 1; + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], mb_array_size * 2 * sizeof(uint8_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], mv_table_size * 2 * sizeof(int16_t), fail) + s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], mb_array_size * 2 * sizeof(uint8_t), fail) + } + } + if (s->out_format == FMT_H263) { + /* cbp values */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->coded_block_base, y_size, fail); + s->coded_block = s->coded_block_base + s->b8_stride + 1; + + /* cbp, ac_pred, pred_dir */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table , mb_array_size * sizeof(uint8_t), fail); + FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, mb_array_size * sizeof(uint8_t), fail); + } + + if (s->h263_pred || s->h263_plus || !s->encoding) { + /* dc values */ + // MN: we need these for error resilience of intra-frames + FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, yc_size * sizeof(int16_t), fail); + s->dc_val[0] = s->dc_val_base + s->b8_stride + 1; + s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1; + s->dc_val[2] = s->dc_val[1] + c_size; + for (i = 0; i < yc_size; i++) + s->dc_val_base[i] = 1024; + } + + /* which mb is a intra block */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail); + memset(s->mbintra_table, 1, mb_array_size); + + /* init macroblock skip table */ + FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail); + // Note the + 1 is for a quicker mpeg4 slice_end detection + + return init_er(s); +fail: + return AVERROR(ENOMEM); +} + +/** + * init common structure for both encoder and decoder. + * this assumes that some variables like width/height are already set + */ +av_cold int ff_MPV_common_init(MpegEncContext *s) +{ + int i; + int nb_slices = (HAVE_THREADS && + s->avctx->active_thread_type & FF_THREAD_SLICE) ? + s->avctx->thread_count : 1; + + if (s->encoding && s->avctx->slices) + nb_slices = s->avctx->slices; + + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) + s->mb_height = (s->height + 31) / 32 * 2; + else + s->mb_height = (s->height + 15) / 16; + + if (s->avctx->pix_fmt == AV_PIX_FMT_NONE) { + av_log(s->avctx, AV_LOG_ERROR, + "decoding to AV_PIX_FMT_NONE is not supported.\n"); + return -1; + } + + if (nb_slices > MAX_THREADS || (nb_slices > s->mb_height && s->mb_height)) { + int max_slices; + if (s->mb_height) + max_slices = FFMIN(MAX_THREADS, s->mb_height); + else + max_slices = MAX_THREADS; + av_log(s->avctx, AV_LOG_WARNING, "too many threads/slices (%d)," + " reducing to %d\n", nb_slices, max_slices); + nb_slices = max_slices; + } + + if ((s->width || s->height) && + av_image_check_size(s->width, s->height, 0, s->avctx)) + return -1; + + ff_dct_common_init(s); + + s->flags = s->avctx->flags; + s->flags2 = s->avctx->flags2; + + /* set chroma shifts */ + avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + + /* convert fourcc to upper case */ + s->codec_tag = avpriv_toupper4(s->avctx->codec_tag); + s->stream_codec_tag = avpriv_toupper4(s->avctx->stream_codec_tag); + + s->avctx->coded_frame = &s->current_picture.f; + + if (s->encoding) { + if (s->msmpeg4_version) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, + 2 * 2 * (MAX_LEVEL + 1) * + (MAX_RUN + 1) * 2 * sizeof(int), fail); + } + FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail); + + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix, 64 * 32 * sizeof(int), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix, 64 * 32 * sizeof(int), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix, 64 * 32 * sizeof(int), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_chroma_intra_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16, 64 * 32 * 2 * sizeof(uint16_t), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture *), fail) + FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture *), fail) + + if (s->avctx->noise_reduction) { + FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, 2 * 64 * sizeof(uint16_t), fail); + } + } + + FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, + MAX_PICTURE_COUNT * sizeof(Picture), fail); + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + avcodec_get_frame_defaults(&s->picture[i].f); + } + memset(&s->next_picture, 0, sizeof(s->next_picture)); + memset(&s->last_picture, 0, sizeof(s->last_picture)); + memset(&s->current_picture, 0, sizeof(s->current_picture)); + avcodec_get_frame_defaults(&s->next_picture.f); + avcodec_get_frame_defaults(&s->last_picture.f); + avcodec_get_frame_defaults(&s->current_picture.f); + + if (init_context_frame(s)) + goto fail; + + s->parse_context.state = -1; + + s->context_initialized = 1; + s->thread_context[0] = s; + +// if (s->width && s->height) { + if (nb_slices > 1) { + for (i = 1; i < nb_slices; i++) { + s->thread_context[i] = av_malloc(sizeof(MpegEncContext)); + memcpy(s->thread_context[i], s, sizeof(MpegEncContext)); + } + + for (i = 0; i < nb_slices; i++) { + if (init_duplicate_context(s->thread_context[i]) < 0) + goto fail; + s->thread_context[i]->start_mb_y = + (s->mb_height * (i) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; + } + } else { + if (init_duplicate_context(s) < 0) + goto fail; + s->start_mb_y = 0; + s->end_mb_y = s->mb_height; + } + s->slice_context_count = nb_slices; +// } + + return 0; + fail: + ff_MPV_common_end(s); + return -1; +} + +/** + * Frees and resets MpegEncContext fields depending on the resolution. + * Is used during resolution changes to avoid a full reinitialization of the + * codec. + */ +static int free_context_frame(MpegEncContext *s) +{ + int i, j, k; + + av_freep(&s->mb_type); + av_freep(&s->p_mv_table_base); + av_freep(&s->b_forw_mv_table_base); + av_freep(&s->b_back_mv_table_base); + av_freep(&s->b_bidir_forw_mv_table_base); + av_freep(&s->b_bidir_back_mv_table_base); + av_freep(&s->b_direct_mv_table_base); + s->p_mv_table = NULL; + s->b_forw_mv_table = NULL; + s->b_back_mv_table = NULL; + s->b_bidir_forw_mv_table = NULL; + s->b_bidir_back_mv_table = NULL; + s->b_direct_mv_table = NULL; + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + av_freep(&s->b_field_mv_table_base[i][j][k]); + s->b_field_mv_table[i][j][k] = NULL; + } + av_freep(&s->b_field_select_table[i][j]); + av_freep(&s->p_field_mv_table_base[i][j]); + s->p_field_mv_table[i][j] = NULL; + } + av_freep(&s->p_field_select_table[i]); + } + + av_freep(&s->dc_val_base); + av_freep(&s->coded_block_base); + av_freep(&s->mbintra_table); + av_freep(&s->cbp_table); + av_freep(&s->pred_dir_table); + + av_freep(&s->mbskip_table); + + av_freep(&s->er.error_status_table); + av_freep(&s->er.er_temp_buffer); + av_freep(&s->mb_index2xy); + av_freep(&s->lambda_table); + + av_freep(&s->cplx_tab); + av_freep(&s->bits_tab); + + s->linesize = s->uvlinesize = 0; + + return 0; +} + +int ff_MPV_common_frame_size_change(MpegEncContext *s) +{ + int i, err = 0; + + if (s->slice_context_count > 1) { + for (i = 0; i < s->slice_context_count; i++) { + free_duplicate_context(s->thread_context[i]); + } + for (i = 1; i < s->slice_context_count; i++) { + av_freep(&s->thread_context[i]); + } + } else + free_duplicate_context(s); + + if ((err = free_context_frame(s)) < 0) + return err; + + if (s->picture) + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + s->picture[i].needs_realloc = 1; + } + + s->last_picture_ptr = + s->next_picture_ptr = + s->current_picture_ptr = NULL; + + // init + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) + s->mb_height = (s->height + 31) / 32 * 2; + else + s->mb_height = (s->height + 15) / 16; + + if ((s->width || s->height) && + av_image_check_size(s->width, s->height, 0, s->avctx)) + return AVERROR_INVALIDDATA; + + if ((err = init_context_frame(s))) + goto fail; + + s->thread_context[0] = s; + + if (s->width && s->height) { + int nb_slices = s->slice_context_count; + if (nb_slices > 1) { + for (i = 1; i < nb_slices; i++) { + s->thread_context[i] = av_malloc(sizeof(MpegEncContext)); + memcpy(s->thread_context[i], s, sizeof(MpegEncContext)); + } + + for (i = 0; i < nb_slices; i++) { + if (init_duplicate_context(s->thread_context[i]) < 0) + goto fail; + s->thread_context[i]->start_mb_y = + (s->mb_height * (i) + nb_slices / 2) / nb_slices; + s->thread_context[i]->end_mb_y = + (s->mb_height * (i + 1) + nb_slices / 2) / nb_slices; + } + } else { + if (init_duplicate_context(s) < 0) + goto fail; + s->start_mb_y = 0; + s->end_mb_y = s->mb_height; + } + s->slice_context_count = nb_slices; + } + + return 0; + fail: + ff_MPV_common_end(s); + return err; +} + +/* init common structure for both encoder and decoder */ +void ff_MPV_common_end(MpegEncContext *s) +{ + int i; + + if (s->slice_context_count > 1) { + for (i = 0; i < s->slice_context_count; i++) { + free_duplicate_context(s->thread_context[i]); + } + for (i = 1; i < s->slice_context_count; i++) { + av_freep(&s->thread_context[i]); + } + s->slice_context_count = 1; + } else free_duplicate_context(s); + + av_freep(&s->parse_context.buffer); + s->parse_context.buffer_size = 0; + + av_freep(&s->bitstream_buffer); + s->allocated_bitstream_buffer_size = 0; + + av_freep(&s->avctx->stats_out); + av_freep(&s->ac_stats); + + if(s->q_chroma_intra_matrix != s->q_intra_matrix ) av_freep(&s->q_chroma_intra_matrix); + if(s->q_chroma_intra_matrix16 != s->q_intra_matrix16) av_freep(&s->q_chroma_intra_matrix16); + s->q_chroma_intra_matrix= NULL; + s->q_chroma_intra_matrix16= NULL; + av_freep(&s->q_intra_matrix); + av_freep(&s->q_inter_matrix); + av_freep(&s->q_intra_matrix16); + av_freep(&s->q_inter_matrix16); + av_freep(&s->input_picture); + av_freep(&s->reordered_input_picture); + av_freep(&s->dct_offset); + + if (s->picture) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + free_picture_tables(&s->picture[i]); + ff_mpeg_unref_picture(s, &s->picture[i]); + } + } + av_freep(&s->picture); + free_picture_tables(&s->last_picture); + ff_mpeg_unref_picture(s, &s->last_picture); + free_picture_tables(&s->current_picture); + ff_mpeg_unref_picture(s, &s->current_picture); + free_picture_tables(&s->next_picture); + ff_mpeg_unref_picture(s, &s->next_picture); + free_picture_tables(&s->new_picture); + ff_mpeg_unref_picture(s, &s->new_picture); + + free_context_frame(s); + + s->context_initialized = 0; + s->last_picture_ptr = + s->next_picture_ptr = + s->current_picture_ptr = NULL; + s->linesize = s->uvlinesize = 0; +} + +void ff_init_rl(RLTable *rl, + uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3]) +{ + int8_t max_level[MAX_RUN + 1], max_run[MAX_LEVEL + 1]; + uint8_t index_run[MAX_RUN + 1]; + int last, run, level, start, end, i; + + /* If table is static, we can quit if rl->max_level[0] is not NULL */ + if (static_store && rl->max_level[0]) + return; + + /* compute max_level[], max_run[] and index_run[] */ + for (last = 0; last < 2; last++) { + if (last == 0) { + start = 0; + end = rl->last; + } else { + start = rl->last; + end = rl->n; + } + + memset(max_level, 0, MAX_RUN + 1); + memset(max_run, 0, MAX_LEVEL + 1); + memset(index_run, rl->n, MAX_RUN + 1); + for (i = start; i < end; i++) { + run = rl->table_run[i]; + level = rl->table_level[i]; + if (index_run[run] == rl->n) + index_run[run] = i; + if (level > max_level[run]) + max_level[run] = level; + if (run > max_run[level]) + max_run[level] = run; + } + if (static_store) + rl->max_level[last] = static_store[last]; + else + rl->max_level[last] = av_malloc(MAX_RUN + 1); + memcpy(rl->max_level[last], max_level, MAX_RUN + 1); + if (static_store) + rl->max_run[last] = static_store[last] + MAX_RUN + 1; + else + rl->max_run[last] = av_malloc(MAX_LEVEL + 1); + memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); + if (static_store) + rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; + else + rl->index_run[last] = av_malloc(MAX_RUN + 1); + memcpy(rl->index_run[last], index_run, MAX_RUN + 1); + } +} + +void ff_init_vlc_rl(RLTable *rl) +{ + int i, q; + + for (q = 0; q < 32; q++) { + int qmul = q * 2; + int qadd = (q - 1) | 1; + + if (q == 0) { + qmul = 1; + qadd = 0; + } + for (i = 0; i < rl->vlc.table_size; i++) { + int code = rl->vlc.table[i][0]; + int len = rl->vlc.table[i][1]; + int level, run; + + if (len == 0) { // illegal code + run = 66; + level = MAX_LEVEL; + } else if (len < 0) { // more bits needed + run = 0; + level = code; + } else { + if (code == rl->n) { // esc + run = 66; + level = 0; + } else { + run = rl->table_run[code] + 1; + level = rl->table_level[code] * qmul + qadd; + if (code >= rl->last) run += 192; + } + } + rl->rl_vlc[q][i].len = len; + rl->rl_vlc[q][i].level = level; + rl->rl_vlc[q][i].run = run; + } + } +} + +void ff_release_unused_pictures(MpegEncContext*s, int remove_current) +{ + int i; + + /* release non reference frames */ + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference && + (remove_current || &s->picture[i] != s->current_picture_ptr)) { + ff_mpeg_unref_picture(s, &s->picture[i]); + } + } +} + +static inline int pic_is_unused(MpegEncContext *s, Picture *pic) +{ + if ( (s->avctx->active_thread_type & FF_THREAD_FRAME) + && pic->f.qscale_table //check if the frame has anything allocated + && pic->period_since_free < s->avctx->thread_count) + return 0; + if (pic == s->last_picture_ptr) + return 0; + if (pic->f.data[0] == NULL) + return 1; + if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) + return 1; + return 0; +} + +static int find_unused_picture(MpegEncContext *s, int shared) +{ + int i; + + if (shared) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (s->picture[i].f.data[0] == NULL && &s->picture[i] != s->last_picture_ptr) + return i; + } + } else { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (pic_is_unused(s, &s->picture[i])) + return i; + } + } + + av_log(s->avctx, AV_LOG_FATAL, + "Internal error, picture buffer overflow\n"); + /* We could return -1, but the codec would crash trying to draw into a + * non-existing frame anyway. This is safer than waiting for a random crash. + * Also the return of this is never useful, an encoder must only allocate + * as much as allowed in the specification. This has no relationship to how + * much libavcodec could allocate (and MAX_PICTURE_COUNT is always large + * enough for such valid streams). + * Plus, a decoder has to check stream validity and remove frames if too + * many reference frames are around. Waiting for "OOM" is not correct at + * all. Similarly, missing reference frames have to be replaced by + * interpolated/MC frames, anything else is a bug in the codec ... + */ + abort(); + return -1; +} + +int ff_find_unused_picture(MpegEncContext *s, int shared) +{ + int ret = find_unused_picture(s, shared); + + if (ret >= 0 && ret < MAX_PICTURE_COUNT) { + if (s->picture[ret].needs_realloc) { + s->picture[ret].needs_realloc = 0; + free_picture_tables(&s->picture[ret]); + ff_mpeg_unref_picture(s, &s->picture[ret]); + avcodec_get_frame_defaults(&s->picture[ret].f); + } + } + return ret; +} + +static void update_noise_reduction(MpegEncContext *s) +{ + int intra, i; + + for (intra = 0; intra < 2; intra++) { + if (s->dct_count[intra] > (1 << 16)) { + for (i = 0; i < 64; i++) { + s->dct_error_sum[intra][i] >>= 1; + } + s->dct_count[intra] >>= 1; + } + + for (i = 0; i < 64; i++) { + s->dct_offset[intra][i] = (s->avctx->noise_reduction * + s->dct_count[intra] + + s->dct_error_sum[intra][i] / 2) / + (s->dct_error_sum[intra][i] + 1); + } + } +} + +/** + * generic function for encode/decode called after coding/decoding + * the header and before a frame is coded/decoded. + */ +int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) +{ + int i, ret; + Picture *pic; + s->mb_skipped = 0; + + if (!ff_thread_can_start_frame(avctx)) { + av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + + /* mark & release old frames */ + if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && + s->last_picture_ptr != s->next_picture_ptr && + s->last_picture_ptr->f.data[0]) { + ff_mpeg_unref_picture(s, s->last_picture_ptr); + } + + /* release forgotten pictures */ + /* if (mpeg124/h263) */ + if (!s->encoding) { + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (&s->picture[i] != s->last_picture_ptr && + &s->picture[i] != s->next_picture_ptr && + s->picture[i].reference && !s->picture[i].needs_realloc) { + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) + av_log(avctx, AV_LOG_ERROR, + "releasing zombie picture\n"); + ff_mpeg_unref_picture(s, &s->picture[i]); + } + } + } + + if (!s->encoding) { + ff_release_unused_pictures(s, 1); + + if (s->current_picture_ptr && + s->current_picture_ptr->f.data[0] == NULL) { + // we already have a unused image + // (maybe it was set before reading the header) + pic = s->current_picture_ptr; + } else { + i = ff_find_unused_picture(s, 0); + if (i < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } + pic = &s->picture[i]; + } + + pic->reference = 0; + if (!s->droppable) { + if (s->pict_type != AV_PICTURE_TYPE_B) + pic->reference = 3; + } + + pic->f.coded_picture_number = s->coded_picture_number++; + + if (ff_alloc_picture(s, pic, 0) < 0) + return -1; + + s->current_picture_ptr = pic; + // FIXME use only the vars from current_pic + s->current_picture_ptr->f.top_field_first = s->top_field_first; + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || + s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (s->picture_structure != PICT_FRAME) + s->current_picture_ptr->f.top_field_first = + (s->picture_structure == PICT_TOP_FIELD) == s->first_field; + } + s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame && + !s->progressive_sequence; + s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; + } + + s->current_picture_ptr->f.pict_type = s->pict_type; + // if (s->flags && CODEC_FLAG_QSCALE) + // s->current_picture_ptr->quality = s->new_picture_ptr->quality; + s->current_picture_ptr->f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + ff_mpeg_unref_picture(s, &s->current_picture); + if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, + s->current_picture_ptr)) < 0) + return ret; + + if (s->pict_type != AV_PICTURE_TYPE_B) { + s->last_picture_ptr = s->next_picture_ptr; + if (!s->droppable) + s->next_picture_ptr = s->current_picture_ptr; + } + av_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", + s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, + s->last_picture_ptr ? s->last_picture_ptr->f.data[0] : NULL, + s->next_picture_ptr ? s->next_picture_ptr->f.data[0] : NULL, + s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL, + s->pict_type, s->droppable); + + if ((s->last_picture_ptr == NULL || + s->last_picture_ptr->f.data[0] == NULL) && + (s->pict_type != AV_PICTURE_TYPE_I || + s->picture_structure != PICT_FRAME)) { + int h_chroma_shift, v_chroma_shift; + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &h_chroma_shift, &v_chroma_shift); + if (s->pict_type != AV_PICTURE_TYPE_I) + av_log(avctx, AV_LOG_ERROR, + "warning: first frame is no keyframe\n"); + else if (s->picture_structure != PICT_FRAME) + av_log(avctx, AV_LOG_INFO, + "allocate dummy last picture for field based first keyframe\n"); + + /* Allocate a dummy frame */ + i = ff_find_unused_picture(s, 0); + if (i < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } + s->last_picture_ptr = &s->picture[i]; + s->last_picture_ptr->f.key_frame = 0; + if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0) { + s->last_picture_ptr = NULL; + return -1; + } + + memset(s->last_picture_ptr->f.data[0], 0x80, + avctx->height * s->last_picture_ptr->f.linesize[0]); + memset(s->last_picture_ptr->f.data[1], 0x80, + (avctx->height >> v_chroma_shift) * + s->last_picture_ptr->f.linesize[1]); + memset(s->last_picture_ptr->f.data[2], 0x80, + (avctx->height >> v_chroma_shift) * + s->last_picture_ptr->f.linesize[2]); + + if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){ + for(i=0; iheight; i++) + memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width); + } + + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); + } + if ((s->next_picture_ptr == NULL || + s->next_picture_ptr->f.data[0] == NULL) && + s->pict_type == AV_PICTURE_TYPE_B) { + /* Allocate a dummy frame */ + i = ff_find_unused_picture(s, 0); + if (i < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return i; + } + s->next_picture_ptr = &s->picture[i]; + s->next_picture_ptr->f.key_frame = 0; + if (ff_alloc_picture(s, s->next_picture_ptr, 0) < 0) { + s->next_picture_ptr = NULL; + return -1; + } + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 1); + } + +#if 0 // BUFREF-FIXME + memset(s->last_picture.f.data, 0, sizeof(s->last_picture.f.data)); + memset(s->next_picture.f.data, 0, sizeof(s->next_picture.f.data)); +#endif + if (s->last_picture_ptr) { + ff_mpeg_unref_picture(s, &s->last_picture); + if (s->last_picture_ptr->f.data[0] && + (ret = ff_mpeg_ref_picture(s, &s->last_picture, + s->last_picture_ptr)) < 0) + return ret; + } + if (s->next_picture_ptr) { + ff_mpeg_unref_picture(s, &s->next_picture); + if (s->next_picture_ptr->f.data[0] && + (ret = ff_mpeg_ref_picture(s, &s->next_picture, + s->next_picture_ptr)) < 0) + return ret; + } + + assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && + s->last_picture_ptr->f.data[0])); + + if (s->picture_structure!= PICT_FRAME) { + int i; + for (i = 0; i < 4; i++) { + if (s->picture_structure == PICT_BOTTOM_FIELD) { + s->current_picture.f.data[i] += + s->current_picture.f.linesize[i]; + } + s->current_picture.f.linesize[i] *= 2; + s->last_picture.f.linesize[i] *= 2; + s->next_picture.f.linesize[i] *= 2; + } + } + + s->err_recognition = avctx->err_recognition; + + /* set dequantizer, we can't do it during init as + * it might change for mpeg4 and we can't do it in the header + * decode as init is not called for mpeg4 there yet */ + if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; + s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; + } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { + s->dct_unquantize_intra = s->dct_unquantize_h263_intra; + s->dct_unquantize_inter = s->dct_unquantize_h263_inter; + } else { + s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra; + s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; + } + + if (s->dct_error_sum) { + assert(s->avctx->noise_reduction && s->encoding); + update_noise_reduction(s); + } + + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + return ff_xvmc_field_start(s, avctx); + + return 0; +} + +/* generic function for encode/decode called after a + * frame has been coded/decoded. */ +void ff_MPV_frame_end(MpegEncContext *s) +{ + int i; + /* redraw edges for the frame if decoding didn't complete */ + // just to make sure that all data is rendered. + if (CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) { + ff_xvmc_field_end(s); + } else if ((s->er.error_count || s->encoding || !(s->avctx->codec->capabilities&CODEC_CAP_DRAW_HORIZ_BAND)) && + !s->avctx->hwaccel && + !(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) && + s->unrestricted_mv && + s->current_picture.reference && + !s->intra_only && + !(s->flags & CODEC_FLAG_EMU_EDGE) && + !s->avctx->lowres + ) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); + int hshift = desc->log2_chroma_w; + int vshift = desc->log2_chroma_h; + s->dsp.draw_edges(s->current_picture.f.data[0], s->current_picture.f.linesize[0], + s->h_edge_pos, s->v_edge_pos, + EDGE_WIDTH, EDGE_WIDTH, + EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.f.data[1], s->current_picture.f.linesize[1], + s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.f.data[2], s->current_picture.f.linesize[2], + s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); + } + + emms_c(); + + s->last_pict_type = s->pict_type; + s->last_lambda_for [s->pict_type] = s->current_picture_ptr->f.quality; + if (s->pict_type!= AV_PICTURE_TYPE_B) { + s->last_non_b_pict_type = s->pict_type; + } +#if 0 + /* copy back current_picture variables */ + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (s->picture[i].f.data[0] == s->current_picture.f.data[0]) { + s->picture[i] = s->current_picture; + break; + } + } + assert(i < MAX_PICTURE_COUNT); +#endif + + if (s->encoding) { + /* release non-reference frames */ + for (i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference) + ff_mpeg_unref_picture(s, &s->picture[i]); + } + } + // clear copies, to avoid confusion +#if 0 + memset(&s->last_picture, 0, sizeof(Picture)); + memset(&s->next_picture, 0, sizeof(Picture)); + memset(&s->current_picture, 0, sizeof(Picture)); +#endif + s->avctx->coded_frame = &s->current_picture_ptr->f; + + if (s->current_picture.reference) + ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); +} + +/** + * Draw a line from (ex, ey) -> (sx, sy). + * @param w width of the image + * @param h height of the image + * @param stride stride/linesize of the image + * @param color color of the arrow + */ +static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, + int w, int h, int stride, int color) +{ + int x, y, fr, f; + + sx = av_clip(sx, 0, w - 1); + sy = av_clip(sy, 0, h - 1); + ex = av_clip(ex, 0, w - 1); + ey = av_clip(ey, 0, h - 1); + + buf[sy * stride + sx] += color; + + if (FFABS(ex - sx) > FFABS(ey - sy)) { + if (sx > ex) { + FFSWAP(int, sx, ex); + FFSWAP(int, sy, ey); + } + buf += sx + sy * stride; + ex -= sx; + f = ((ey - sy) << 16) / ex; + for (x = 0; x <= ex; x++) { + y = (x * f) >> 16; + fr = (x * f) & 0xFFFF; + buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; + if(fr) buf[(y + 1) * stride + x] += (color * fr ) >> 16; + } + } else { + if (sy > ey) { + FFSWAP(int, sx, ex); + FFSWAP(int, sy, ey); + } + buf += sx + sy * stride; + ey -= sy; + if (ey) + f = ((ex - sx) << 16) / ey; + else + f = 0; + for(y= 0; y <= ey; y++){ + x = (y*f) >> 16; + fr = (y*f) & 0xFFFF; + buf[y * stride + x] += (color * (0x10000 - fr)) >> 16; + if(fr) buf[y * stride + x + 1] += (color * fr ) >> 16; + } + } +} + +/** + * Draw an arrow from (ex, ey) -> (sx, sy). + * @param w width of the image + * @param h height of the image + * @param stride stride/linesize of the image + * @param color color of the arrow + */ +static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, + int ey, int w, int h, int stride, int color) +{ + int dx,dy; + + sx = av_clip(sx, -100, w + 100); + sy = av_clip(sy, -100, h + 100); + ex = av_clip(ex, -100, w + 100); + ey = av_clip(ey, -100, h + 100); + + dx = ex - sx; + dy = ey - sy; + + if (dx * dx + dy * dy > 3 * 3) { + int rx = dx + dy; + int ry = -dx + dy; + int length = ff_sqrt((rx * rx + ry * ry) << 8); + + // FIXME subpixel accuracy + rx = ROUNDED_DIV(rx * 3 << 4, length); + ry = ROUNDED_DIV(ry * 3 << 4, length); + + draw_line(buf, sx, sy, sx + rx, sy + ry, w, h, stride, color); + draw_line(buf, sx, sy, sx - ry, sy + rx, w, h, stride, color); + } + draw_line(buf, sx, sy, ex, ey, w, h, stride, color); +} + +/** + * Print debugging info for the given picture. + */ +void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint8_t *mbskip_table, + int *low_delay, + int mb_width, int mb_height, int mb_stride, int quarter_sample) +{ + if (avctx->hwaccel || !p || !p->mb_type + || (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)) + return; + + + if (avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) { + int x,y; + + av_log(avctx, AV_LOG_DEBUG, "New frame, type: %c\n", + av_get_picture_type_char(pict->pict_type)); + for (y = 0; y < mb_height; y++) { + for (x = 0; x < mb_width; x++) { + if (avctx->debug & FF_DEBUG_SKIP) { + int count = mbskip_table[x + y * mb_stride]; + if (count > 9) + count = 9; + av_log(avctx, AV_LOG_DEBUG, "%1d", count); + } + if (avctx->debug & FF_DEBUG_QP) { + av_log(avctx, AV_LOG_DEBUG, "%2d", + p->qscale_table[x + y * mb_stride]); + } + if (avctx->debug & FF_DEBUG_MB_TYPE) { + int mb_type = p->mb_type[x + y * mb_stride]; + // Type & MV direction + if (IS_PCM(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "P"); + else if (IS_INTRA(mb_type) && IS_ACPRED(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "A"); + else if (IS_INTRA4x4(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "i"); + else if (IS_INTRA16x16(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "I"); + else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "d"); + else if (IS_DIRECT(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "D"); + else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "g"); + else if (IS_GMC(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "G"); + else if (IS_SKIP(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "S"); + else if (!USES_LIST(mb_type, 1)) + av_log(avctx, AV_LOG_DEBUG, ">"); + else if (!USES_LIST(mb_type, 0)) + av_log(avctx, AV_LOG_DEBUG, "<"); + else { + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + av_log(avctx, AV_LOG_DEBUG, "X"); + } + + // segmentation + if (IS_8X8(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "+"); + else if (IS_16X8(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "-"); + else if (IS_8X16(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "|"); + else if (IS_INTRA(mb_type) || IS_16X16(mb_type)) + av_log(avctx, AV_LOG_DEBUG, " "); + else + av_log(avctx, AV_LOG_DEBUG, "?"); + + + if (IS_INTERLACED(mb_type)) + av_log(avctx, AV_LOG_DEBUG, "="); + else + av_log(avctx, AV_LOG_DEBUG, " "); + } + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + } + } + + if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || + (avctx->debug_mv)) { + const int shift = 1 + quarter_sample; + int mb_y; + uint8_t *ptr; + int i; + int h_chroma_shift, v_chroma_shift, block_height; + const int width = avctx->width; + const int height = avctx->height; + const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1; + const int mv_stride = (mb_width << mv_sample_log2) + + (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1); + + *low_delay = 0; // needed to see the vectors without trashing the buffers + + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift); + + av_frame_make_writable(pict); + + pict->opaque = NULL; + ptr = pict->data[0]; + block_height = 16 >> v_chroma_shift; + + for (mb_y = 0; mb_y < mb_height; mb_y++) { + int mb_x; + for (mb_x = 0; mb_x < mb_width; mb_x++) { + const int mb_index = mb_x + mb_y * mb_stride; + if ((avctx->debug_mv) && p->motion_val[0]) { + int type; + for (type = 0; type < 3; type++) { + int direction = 0; + switch (type) { + case 0: + if ((!(avctx->debug_mv & FF_DEBUG_VIS_MV_P_FOR)) || + (pict->pict_type!= AV_PICTURE_TYPE_P)) + continue; + direction = 0; + break; + case 1: + if ((!(avctx->debug_mv & FF_DEBUG_VIS_MV_B_FOR)) || + (pict->pict_type!= AV_PICTURE_TYPE_B)) + continue; + direction = 0; + break; + case 2: + if ((!(avctx->debug_mv & FF_DEBUG_VIS_MV_B_BACK)) || + (pict->pict_type!= AV_PICTURE_TYPE_B)) + continue; + direction = 1; + break; + } + if (!USES_LIST(p->mb_type[mb_index], direction)) + continue; + + if (IS_8X8(p->mb_type[mb_index])) { + int i; + for (i = 0; i < 4; i++) { + int sx = mb_x * 16 + 4 + 8 * (i & 1); + int sy = mb_y * 16 + 4 + 8 * (i >> 1); + int xy = (mb_x * 2 + (i & 1) + + (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); + int mx = (p->motion_val[direction][xy][0] >> shift) + sx; + int my = (p->motion_val[direction][xy][1] >> shift) + sy; + draw_arrow(ptr, sx, sy, mx, my, width, + height, pict->linesize[0], 100); + } + } else if (IS_16X8(p->mb_type[mb_index])) { + int i; + for (i = 0; i < 2; i++) { + int sx = mb_x * 16 + 8; + int sy = mb_y * 16 + 4 + 8 * i; + int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1); + int mx = (p->motion_val[direction][xy][0] >> shift); + int my = (p->motion_val[direction][xy][1] >> shift); + + if (IS_INTERLACED(p->mb_type[mb_index])) + my *= 2; + + draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, + height, pict->linesize[0], 100); + } + } else if (IS_8X16(p->mb_type[mb_index])) { + int i; + for (i = 0; i < 2; i++) { + int sx = mb_x * 16 + 4 + 8 * i; + int sy = mb_y * 16 + 8; + int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1); + int mx = p->motion_val[direction][xy][0] >> shift; + int my = p->motion_val[direction][xy][1] >> shift; + + if (IS_INTERLACED(p->mb_type[mb_index])) + my *= 2; + + draw_arrow(ptr, sx, sy, mx + sx, my + sy, width, + height, pict->linesize[0], 100); + } + } else { + int sx= mb_x * 16 + 8; + int sy= mb_y * 16 + 8; + int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2; + int mx= (p->motion_val[direction][xy][0]>>shift) + sx; + int my= (p->motion_val[direction][xy][1]>>shift) + sy; + draw_arrow(ptr, sx, sy, mx, my, width, height, pict->linesize[0], 100); + } + } + } + if ((avctx->debug & FF_DEBUG_VIS_QP)) { + uint64_t c = (p->qscale_table[mb_index] * 128 / 31) * + 0x0101010101010101ULL; + int y; + for (y = 0; y < block_height; y++) { + *(uint64_t *)(pict->data[1] + 8 * mb_x + + (block_height * mb_y + y) * + pict->linesize[1]) = c; + *(uint64_t *)(pict->data[2] + 8 * mb_x + + (block_height * mb_y + y) * + pict->linesize[2]) = c; + } + } + if ((avctx->debug & FF_DEBUG_VIS_MB_TYPE) && + p->motion_val[0]) { + int mb_type = p->mb_type[mb_index]; + uint64_t u,v; + int y; +#define COLOR(theta, r) \ + u = (int)(128 + r * cos(theta * 3.141592 / 180)); \ + v = (int)(128 + r * sin(theta * 3.141592 / 180)); + + + u = v = 128; + if (IS_PCM(mb_type)) { + COLOR(120, 48) + } else if ((IS_INTRA(mb_type) && IS_ACPRED(mb_type)) || + IS_INTRA16x16(mb_type)) { + COLOR(30, 48) + } else if (IS_INTRA4x4(mb_type)) { + COLOR(90, 48) + } else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type)) { + // COLOR(120, 48) + } else if (IS_DIRECT(mb_type)) { + COLOR(150, 48) + } else if (IS_GMC(mb_type) && IS_SKIP(mb_type)) { + COLOR(170, 48) + } else if (IS_GMC(mb_type)) { + COLOR(190, 48) + } else if (IS_SKIP(mb_type)) { + // COLOR(180, 48) + } else if (!USES_LIST(mb_type, 1)) { + COLOR(240, 48) + } else if (!USES_LIST(mb_type, 0)) { + COLOR(0, 48) + } else { + av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1)); + COLOR(300,48) + } + + u *= 0x0101010101010101ULL; + v *= 0x0101010101010101ULL; + for (y = 0; y < block_height; y++) { + *(uint64_t *)(pict->data[1] + 8 * mb_x + + (block_height * mb_y + y) * pict->linesize[1]) = u; + *(uint64_t *)(pict->data[2] + 8 * mb_x + + (block_height * mb_y + y) * pict->linesize[2]) = v; + } + + // segmentation + if (IS_8X8(mb_type) || IS_16X8(mb_type)) { + *(uint64_t *)(pict->data[0] + 16 * mb_x + 0 + + (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; + *(uint64_t *)(pict->data[0] + 16 * mb_x + 8 + + (16 * mb_y + 8) * pict->linesize[0]) ^= 0x8080808080808080ULL; + } + if (IS_8X8(mb_type) || IS_8X16(mb_type)) { + for (y = 0; y < 16; y++) + pict->data[0][16 * mb_x + 8 + (16 * mb_y + y) * + pict->linesize[0]] ^= 0x80; + } + if (IS_8X8(mb_type) && mv_sample_log2 >= 2) { + int dm = 1 << (mv_sample_log2 - 2); + for (i = 0; i < 4; i++) { + int sx = mb_x * 16 + 8 * (i & 1); + int sy = mb_y * 16 + 8 * (i >> 1); + int xy = (mb_x * 2 + (i & 1) + + (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1); + // FIXME bidir + int32_t *mv = (int32_t *) &p->motion_val[0][xy]; + if (mv[0] != mv[dm] || + mv[dm * mv_stride] != mv[dm * (mv_stride + 1)]) + for (y = 0; y < 8; y++) + pict->data[0][sx + 4 + (sy + y) * pict->linesize[0]] ^= 0x80; + if (mv[0] != mv[dm * mv_stride] || mv[dm] != mv[dm * (mv_stride + 1)]) + *(uint64_t *)(pict->data[0] + sx + (sy + 4) * + pict->linesize[0]) ^= 0x8080808080808080ULL; + } + } + + if (IS_INTERLACED(mb_type) && + avctx->codec->id == AV_CODEC_ID_H264) { + // hmm + } + } + mbskip_table[mb_index] = 0; + } + } + } +} + +void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) +{ + ff_print_debug_info2(s->avctx, p, pict, s->mbskip_table, &s->low_delay, + s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample); +} + +int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type) +{ + AVBufferRef *ref = av_buffer_ref(p->qscale_table_buf); + int offset = 2*s->mb_stride + 1; + if(!ref) + return AVERROR(ENOMEM); + av_assert0(ref->size >= offset + s->mb_stride * ((f->height+15)/16)); + ref->size -= offset; + ref->data += offset; + return av_frame_set_qp_table(f, ref, s->mb_stride, qp_type); +} + +static inline int hpel_motion_lowres(MpegEncContext *s, + uint8_t *dest, uint8_t *src, + int field_based, int field_select, + int src_x, int src_y, + int width, int height, int stride, + int h_edge_pos, int v_edge_pos, + int w, int h, h264_chroma_mc_func *pix_op, + int motion_x, int motion_y) +{ + const int lowres = s->avctx->lowres; + const int op_index = FFMIN(lowres, 2); + const int s_mask = (2 << lowres) - 1; + int emu = 0; + int sx, sy; + + if (s->quarter_sample) { + motion_x /= 2; + motion_y /= 2; + } + + sx = motion_x & s_mask; + sy = motion_y & s_mask; + src_x += motion_x >> lowres + 1; + src_y += motion_y >> lowres + 1; + + src += src_y * stride + src_x; + + if ((unsigned)src_x > FFMAX( h_edge_pos - (!!sx) - w, 0) || + (unsigned)src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1, + (h + 1) << field_based, src_x, + src_y << field_based, + h_edge_pos, + v_edge_pos); + src = s->edge_emu_buffer; + emu = 1; + } + + sx = (sx << 2) >> lowres; + sy = (sy << 2) >> lowres; + if (field_select) + src += s->linesize; + pix_op[op_index](dest, src, stride, h, sx, sy); + return emu; +} + +/* apply one mpeg motion vector to the three components */ +static av_always_inline void mpeg_motion_lowres(MpegEncContext *s, + uint8_t *dest_y, + uint8_t *dest_cb, + uint8_t *dest_cr, + int field_based, + int bottom_field, + int field_select, + uint8_t **ref_picture, + h264_chroma_mc_func *pix_op, + int motion_x, int motion_y, + int h, int mb_y) +{ + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy, + uvsx, uvsy; + const int lowres = s->avctx->lowres; + const int op_index = FFMIN(lowres-1+s->chroma_x_shift, 2); + const int block_s = 8>>lowres; + const int s_mask = (2 << lowres) - 1; + const int h_edge_pos = s->h_edge_pos >> lowres; + const int v_edge_pos = s->v_edge_pos >> lowres; + linesize = s->current_picture.f.linesize[0] << field_based; + uvlinesize = s->current_picture.f.linesize[1] << field_based; + + // FIXME obviously not perfect but qpel will not work in lowres anyway + if (s->quarter_sample) { + motion_x /= 2; + motion_y /= 2; + } + + if(field_based){ + motion_y += (bottom_field - field_select)*((1 << lowres)-1); + } + + sx = motion_x & s_mask; + sy = motion_y & s_mask; + src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1); + src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1); + + if (s->out_format == FMT_H263) { + uvsx = ((motion_x >> 1) & s_mask) | (sx & 1); + uvsy = ((motion_y >> 1) & s_mask) | (sy & 1); + uvsrc_x = src_x >> 1; + uvsrc_y = src_y >> 1; + } else if (s->out_format == FMT_H261) { + // even chroma mv's are full pel in H261 + mx = motion_x / 4; + my = motion_y / 4; + uvsx = (2 * mx) & s_mask; + uvsy = (2 * my) & s_mask; + uvsrc_x = s->mb_x * block_s + (mx >> lowres); + uvsrc_y = mb_y * block_s + (my >> lowres); + } else { + if(s->chroma_y_shift){ + mx = motion_x / 2; + my = motion_y / 2; + uvsx = mx & s_mask; + uvsy = my & s_mask; + uvsrc_x = s->mb_x * block_s + (mx >> lowres + 1); + uvsrc_y = (mb_y * block_s >> field_based) + (my >> lowres + 1); + } else { + if(s->chroma_x_shift){ + //Chroma422 + mx = motion_x / 2; + uvsx = mx & s_mask; + uvsy = motion_y & s_mask; + uvsrc_y = src_y; + uvsrc_x = s->mb_x*block_s + (mx >> (lowres+1)); + } else { + //Chroma444 + uvsx = motion_x & s_mask; + uvsy = motion_y & s_mask; + uvsrc_x = src_x; + uvsrc_y = src_y; + } + } + } + + ptr_y = ref_picture[0] + src_y * linesize + src_x; + ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; + ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; + + if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s, 0) || + (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, + linesize >> field_based, 17, 17 + field_based, + src_x, src_y << field_based, h_edge_pos, + v_edge_pos); + ptr_y = s->edge_emu_buffer; + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { + uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize; + s->vdsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9, + 9 + field_based, + uvsrc_x, uvsrc_y << field_based, + h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9, + 9 + field_based, + uvsrc_x, uvsrc_y << field_based, + h_edge_pos >> 1, v_edge_pos >> 1); + ptr_cb = uvbuf; + ptr_cr = uvbuf + 16; + } + } + + // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data + if (bottom_field) { + dest_y += s->linesize; + dest_cb += s->uvlinesize; + dest_cr += s->uvlinesize; + } + + if (field_select) { + ptr_y += s->linesize; + ptr_cb += s->uvlinesize; + ptr_cr += s->uvlinesize; + } + + sx = (sx << 2) >> lowres; + sy = (sy << 2) >> lowres; + pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy); + + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) { + uvsx = (uvsx << 2) >> lowres; + uvsy = (uvsy << 2) >> lowres; + if (h >> s->chroma_y_shift) { + pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy); + pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy); + } + } + // FIXME h261 lowres loop filter +} + +static inline void chroma_4mv_motion_lowres(MpegEncContext *s, + uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture, + h264_chroma_mc_func * pix_op, + int mx, int my) +{ + const int lowres = s->avctx->lowres; + const int op_index = FFMIN(lowres, 2); + const int block_s = 8 >> lowres; + const int s_mask = (2 << lowres) - 1; + const int h_edge_pos = s->h_edge_pos >> lowres + 1; + const int v_edge_pos = s->v_edge_pos >> lowres + 1; + int emu = 0, src_x, src_y, offset, sx, sy; + uint8_t *ptr; + + if (s->quarter_sample) { + mx /= 2; + my /= 2; + } + + /* In case of 8X8, we construct a single chroma motion vector + with a special rounding */ + mx = ff_h263_round_chroma(mx); + my = ff_h263_round_chroma(my); + + sx = mx & s_mask; + sy = my & s_mask; + src_x = s->mb_x * block_s + (mx >> lowres + 1); + src_y = s->mb_y * block_s + (my >> lowres + 1); + + offset = src_y * s->uvlinesize + src_x; + ptr = ref_picture[1] + offset; + if (s->flags & CODEC_FLAG_EMU_EDGE) { + if ((unsigned) src_x > FFMAX(h_edge_pos - (!!sx) - block_s, 0) || + (unsigned) src_y > FFMAX(v_edge_pos - (!!sy) - block_s, 0)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, + 9, 9, src_x, src_y, h_edge_pos, v_edge_pos); + ptr = s->edge_emu_buffer; + emu = 1; + } + } + sx = (sx << 2) >> lowres; + sy = (sy << 2) >> lowres; + pix_op[op_index](dest_cb, ptr, s->uvlinesize, block_s, sx, sy); + + ptr = ref_picture[2] + offset; + if (emu) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, + src_x, src_y, h_edge_pos, v_edge_pos); + ptr = s->edge_emu_buffer; + } + pix_op[op_index](dest_cr, ptr, s->uvlinesize, block_s, sx, sy); +} + +/** + * motion compensation of a single macroblock + * @param s context + * @param dest_y luma destination pointer + * @param dest_cb chroma cb/u destination pointer + * @param dest_cr chroma cr/v destination pointer + * @param dir direction (0->forward, 1->backward) + * @param ref_picture array[3] of pointers to the 3 planes of the reference picture + * @param pix_op halfpel motion compensation function (average or put normally) + * the motion vectors are taken from s->mv and the MV type from s->mv_type + */ +static inline void MPV_motion_lowres(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, + int dir, uint8_t **ref_picture, + h264_chroma_mc_func *pix_op) +{ + int mx, my; + int mb_x, mb_y, i; + const int lowres = s->avctx->lowres; + const int block_s = 8 >>lowres; + + mb_x = s->mb_x; + mb_y = s->mb_y; + + switch (s->mv_type) { + case MV_TYPE_16X16: + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, 0, + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], + 2 * block_s, mb_y); + break; + case MV_TYPE_8X8: + mx = 0; + my = 0; + for (i = 0; i < 4; i++) { + hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) * + s->linesize) * block_s, + ref_picture[0], 0, 0, + (2 * mb_x + (i & 1)) * block_s, + (2 * mb_y + (i >> 1)) * block_s, + s->width, s->height, s->linesize, + s->h_edge_pos >> lowres, s->v_edge_pos >> lowres, + block_s, block_s, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1]); + + mx += s->mv[dir][i][0]; + my += s->mv[dir][i][1]; + } + + if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) + chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture, + pix_op, mx, my); + break; + case MV_TYPE_FIELD: + if (s->picture_structure == PICT_FRAME) { + /* top field */ + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 1, 0, s->field_select[dir][0], + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], + block_s, mb_y); + /* bottom field */ + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 1, 1, s->field_select[dir][1], + ref_picture, pix_op, + s->mv[dir][1][0], s->mv[dir][1][1], + block_s, mb_y); + } else { + if (s->picture_structure != s->field_select[dir][0] + 1 && + s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) { + ref_picture = s->current_picture_ptr->f.data; + + } + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, s->field_select[dir][0], + ref_picture, pix_op, + s->mv[dir][0][0], + s->mv[dir][0][1], 2 * block_s, mb_y >> 1); + } + break; + case MV_TYPE_16X8: + for (i = 0; i < 2; i++) { + uint8_t **ref2picture; + + if (s->picture_structure == s->field_select[dir][i] + 1 || + s->pict_type == AV_PICTURE_TYPE_B || s->first_field) { + ref2picture = ref_picture; + } else { + ref2picture = s->current_picture_ptr->f.data; + } + + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, s->field_select[dir][i], + ref2picture, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1] + + 2 * block_s * i, block_s, mb_y >> 1); + + dest_y += 2 * block_s * s->linesize; + dest_cb += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize; + dest_cr += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize; + } + break; + case MV_TYPE_DMV: + if (s->picture_structure == PICT_FRAME) { + for (i = 0; i < 2; i++) { + int j; + for (j = 0; j < 2; j++) { + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 1, j, j ^ i, + ref_picture, pix_op, + s->mv[dir][2 * i + j][0], + s->mv[dir][2 * i + j][1], + block_s, mb_y); + } + pix_op = s->h264chroma.avg_h264_chroma_pixels_tab; + } + } else { + for (i = 0; i < 2; i++) { + mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr, + 0, 0, s->picture_structure != i + 1, + ref_picture, pix_op, + s->mv[dir][2 * i][0],s->mv[dir][2 * i][1], + 2 * block_s, mb_y >> 1); + + // after put we make avg of the same block + pix_op = s->h264chroma.avg_h264_chroma_pixels_tab; + + // opposite parity is always in the same + // frame if this is second field + if (!s->first_field) { + ref_picture = s->current_picture_ptr->f.data; + } + } + } + break; + default: + av_assert2(0); + } +} + +/** + * find the lowest MB row referenced in the MVs + */ +int ff_MPV_lowest_referenced_row(MpegEncContext *s, int dir) +{ + int my_max = INT_MIN, my_min = INT_MAX, qpel_shift = !s->quarter_sample; + int my, off, i, mvs; + + if (s->picture_structure != PICT_FRAME || s->mcsel) + goto unhandled; + + switch (s->mv_type) { + case MV_TYPE_16X16: + mvs = 1; + break; + case MV_TYPE_16X8: + mvs = 2; + break; + case MV_TYPE_8X8: + mvs = 4; + break; + default: + goto unhandled; + } + + for (i = 0; i < mvs; i++) { + my = s->mv[dir][i][1]<> 6; + + return FFMIN(FFMAX(s->mb_y + off, 0), s->mb_height-1); +unhandled: + return s->mb_height-1; +} + +/* put block[] to dest[] */ +static inline void put_dct(MpegEncContext *s, + int16_t *block, int i, uint8_t *dest, int line_size, int qscale) +{ + s->dct_unquantize_intra(s, block, i, qscale); + s->dsp.idct_put (dest, line_size, block); +} + +/* add block[] to dest[] */ +static inline void add_dct(MpegEncContext *s, + int16_t *block, int i, uint8_t *dest, int line_size) +{ + if (s->block_last_index[i] >= 0) { + s->dsp.idct_add (dest, line_size, block); + } +} + +static inline void add_dequant_dct(MpegEncContext *s, + int16_t *block, int i, uint8_t *dest, int line_size, int qscale) +{ + if (s->block_last_index[i] >= 0) { + s->dct_unquantize_inter(s, block, i, qscale); + + s->dsp.idct_add (dest, line_size, block); + } +} + +/** + * Clean dc, ac, coded_block for the current non-intra MB. + */ +void ff_clean_intra_table_entries(MpegEncContext *s) +{ + int wrap = s->b8_stride; + int xy = s->block_index[0]; + + s->dc_val[0][xy ] = + s->dc_val[0][xy + 1 ] = + s->dc_val[0][xy + wrap] = + s->dc_val[0][xy + 1 + wrap] = 1024; + /* ac pred */ + memset(s->ac_val[0][xy ], 0, 32 * sizeof(int16_t)); + memset(s->ac_val[0][xy + wrap], 0, 32 * sizeof(int16_t)); + if (s->msmpeg4_version>=3) { + s->coded_block[xy ] = + s->coded_block[xy + 1 ] = + s->coded_block[xy + wrap] = + s->coded_block[xy + 1 + wrap] = 0; + } + /* chroma */ + wrap = s->mb_stride; + xy = s->mb_x + s->mb_y * wrap; + s->dc_val[1][xy] = + s->dc_val[2][xy] = 1024; + /* ac pred */ + memset(s->ac_val[1][xy], 0, 16 * sizeof(int16_t)); + memset(s->ac_val[2][xy], 0, 16 * sizeof(int16_t)); + + s->mbintra_table[xy]= 0; +} + +/* generic function called after a macroblock has been parsed by the + decoder or after it has been encoded by the encoder. + + Important variables used: + s->mb_intra : true if intra macroblock + s->mv_dir : motion vector direction + s->mv_type : motion vector type + s->mv : motion vector + s->interlaced_dct : true if interlaced dct used (mpeg2) + */ +static av_always_inline +void MPV_decode_mb_internal(MpegEncContext *s, int16_t block[12][64], + int lowres_flag, int is_mpeg12) +{ + const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){ + ff_xvmc_decode_mb(s);//xvmc uses pblocks + return; + } + + if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { + /* print DCT coefficients */ + int i,j; + av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); + for(i=0; i<6; i++){ + for(j=0; j<64; j++){ + av_log(s->avctx, AV_LOG_DEBUG, "%5d", block[i][s->dsp.idct_permutation[j]]); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + } + + s->current_picture.qscale_table[mb_xy] = s->qscale; + + /* update DC predictors for P macroblocks */ + if (!s->mb_intra) { + if (!is_mpeg12 && (s->h263_pred || s->h263_aic)) { + if(s->mbintra_table[mb_xy]) + ff_clean_intra_table_entries(s); + } else { + s->last_dc[0] = + s->last_dc[1] = + s->last_dc[2] = 128 << s->intra_dc_precision; + } + } + else if (!is_mpeg12 && (s->h263_pred || s->h263_aic)) + s->mbintra_table[mb_xy]=1; + + if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==AV_PICTURE_TYPE_B) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { //FIXME precalc + uint8_t *dest_y, *dest_cb, *dest_cr; + int dct_linesize, dct_offset; + op_pixels_func (*op_pix)[4]; + qpel_mc_func (*op_qpix)[16]; + const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics + const int uvlinesize = s->current_picture.f.linesize[1]; + const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band || lowres_flag; + const int block_size= lowres_flag ? 8>>s->avctx->lowres : 8; + + /* avoid copy if macroblock skipped in last frame too */ + /* skip only during decoding as we might trash the buffers during encoding a bit */ + if(!s->encoding){ + uint8_t *mbskip_ptr = &s->mbskip_table[mb_xy]; + + if (s->mb_skipped) { + s->mb_skipped= 0; + av_assert2(s->pict_type!=AV_PICTURE_TYPE_I); + *mbskip_ptr = 1; + } else if(!s->current_picture.reference) { + *mbskip_ptr = 1; + } else{ + *mbskip_ptr = 0; /* not skipped */ + } + } + + dct_linesize = linesize << s->interlaced_dct; + dct_offset = s->interlaced_dct ? linesize : linesize * block_size; + + if(readable){ + dest_y= s->dest[0]; + dest_cb= s->dest[1]; + dest_cr= s->dest[2]; + }else{ + dest_y = s->b_scratchpad; + dest_cb= s->b_scratchpad+16*linesize; + dest_cr= s->b_scratchpad+32*linesize; + } + + if (!s->mb_intra) { + /* motion handling */ + /* decoding or more than one mb_type (MC was already done otherwise) */ + if(!s->encoding){ + + if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { + if (s->mv_dir & MV_DIR_FORWARD) { + ff_thread_await_progress(&s->last_picture_ptr->tf, + ff_MPV_lowest_referenced_row(s, 0), + 0); + } + if (s->mv_dir & MV_DIR_BACKWARD) { + ff_thread_await_progress(&s->next_picture_ptr->tf, + ff_MPV_lowest_referenced_row(s, 1), + 0); + } + } + + if(lowres_flag){ + h264_chroma_mc_func *op_pix = s->h264chroma.put_h264_chroma_pixels_tab; + + if (s->mv_dir & MV_DIR_FORWARD) { + MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix); + op_pix = s->h264chroma.avg_h264_chroma_pixels_tab; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix); + } + }else{ + op_qpix= s->me.qpel_put; + if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){ + op_pix = s->hdsp.put_pixels_tab; + }else{ + op_pix = s->hdsp.put_no_rnd_pixels_tab; + } + if (s->mv_dir & MV_DIR_FORWARD) { + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix); + op_pix = s->hdsp.avg_pixels_tab; + op_qpix= s->me.qpel_avg; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix); + } + } + } + + /* skip dequant / idct if we are really late ;) */ + if(s->avctx->skip_idct){ + if( (s->avctx->skip_idct >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B) + ||(s->avctx->skip_idct >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I) + || s->avctx->skip_idct >= AVDISCARD_ALL) + goto skip_idct; + } + + /* add dct residue */ + if(s->encoding || !( s->msmpeg4_version || s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO + || (s->codec_id==AV_CODEC_ID_MPEG4 && !s->mpeg_quant))){ + add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); + add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); + add_dequant_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); + add_dequant_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize, s->qscale); + + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if (s->chroma_y_shift){ + add_dequant_dct(s, block[4], 4, dest_cb, uvlinesize, s->chroma_qscale); + add_dequant_dct(s, block[5], 5, dest_cr, uvlinesize, s->chroma_qscale); + }else{ + dct_linesize >>= 1; + dct_offset >>=1; + add_dequant_dct(s, block[4], 4, dest_cb, dct_linesize, s->chroma_qscale); + add_dequant_dct(s, block[5], 5, dest_cr, dct_linesize, s->chroma_qscale); + add_dequant_dct(s, block[6], 6, dest_cb + dct_offset, dct_linesize, s->chroma_qscale); + add_dequant_dct(s, block[7], 7, dest_cr + dct_offset, dct_linesize, s->chroma_qscale); + } + } + } else if(is_mpeg12 || (s->codec_id != AV_CODEC_ID_WMV2)){ + add_dct(s, block[0], 0, dest_y , dct_linesize); + add_dct(s, block[1], 1, dest_y + block_size, dct_linesize); + add_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize); + add_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize); + + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if(s->chroma_y_shift){//Chroma420 + add_dct(s, block[4], 4, dest_cb, uvlinesize); + add_dct(s, block[5], 5, dest_cr, uvlinesize); + }else{ + //chroma422 + dct_linesize = uvlinesize << s->interlaced_dct; + dct_offset = s->interlaced_dct ? uvlinesize : uvlinesize*block_size; + + add_dct(s, block[4], 4, dest_cb, dct_linesize); + add_dct(s, block[5], 5, dest_cr, dct_linesize); + add_dct(s, block[6], 6, dest_cb+dct_offset, dct_linesize); + add_dct(s, block[7], 7, dest_cr+dct_offset, dct_linesize); + if(!s->chroma_x_shift){//Chroma444 + add_dct(s, block[8], 8, dest_cb+block_size, dct_linesize); + add_dct(s, block[9], 9, dest_cr+block_size, dct_linesize); + add_dct(s, block[10], 10, dest_cb+block_size+dct_offset, dct_linesize); + add_dct(s, block[11], 11, dest_cr+block_size+dct_offset, dct_linesize); + } + } + }//fi gray + } + else if (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) { + ff_wmv2_add_mb(s, block, dest_y, dest_cb, dest_cr); + } + } else { + /* dct only in intra block */ + if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ + put_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); + put_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); + put_dct(s, block[2], 2, dest_y + dct_offset , dct_linesize, s->qscale); + put_dct(s, block[3], 3, dest_y + dct_offset + block_size, dct_linesize, s->qscale); + + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if(s->chroma_y_shift){ + put_dct(s, block[4], 4, dest_cb, uvlinesize, s->chroma_qscale); + put_dct(s, block[5], 5, dest_cr, uvlinesize, s->chroma_qscale); + }else{ + dct_offset >>=1; + dct_linesize >>=1; + put_dct(s, block[4], 4, dest_cb, dct_linesize, s->chroma_qscale); + put_dct(s, block[5], 5, dest_cr, dct_linesize, s->chroma_qscale); + put_dct(s, block[6], 6, dest_cb + dct_offset, dct_linesize, s->chroma_qscale); + put_dct(s, block[7], 7, dest_cr + dct_offset, dct_linesize, s->chroma_qscale); + } + } + }else{ + s->dsp.idct_put(dest_y , dct_linesize, block[0]); + s->dsp.idct_put(dest_y + block_size, dct_linesize, block[1]); + s->dsp.idct_put(dest_y + dct_offset , dct_linesize, block[2]); + s->dsp.idct_put(dest_y + dct_offset + block_size, dct_linesize, block[3]); + + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + if(s->chroma_y_shift){ + s->dsp.idct_put(dest_cb, uvlinesize, block[4]); + s->dsp.idct_put(dest_cr, uvlinesize, block[5]); + }else{ + + dct_linesize = uvlinesize << s->interlaced_dct; + dct_offset = s->interlaced_dct? uvlinesize : uvlinesize*block_size; + + s->dsp.idct_put(dest_cb, dct_linesize, block[4]); + s->dsp.idct_put(dest_cr, dct_linesize, block[5]); + s->dsp.idct_put(dest_cb + dct_offset, dct_linesize, block[6]); + s->dsp.idct_put(dest_cr + dct_offset, dct_linesize, block[7]); + if(!s->chroma_x_shift){//Chroma444 + s->dsp.idct_put(dest_cb + block_size, dct_linesize, block[8]); + s->dsp.idct_put(dest_cr + block_size, dct_linesize, block[9]); + s->dsp.idct_put(dest_cb + block_size + dct_offset, dct_linesize, block[10]); + s->dsp.idct_put(dest_cr + block_size + dct_offset, dct_linesize, block[11]); + } + } + }//gray + } + } +skip_idct: + if(!readable){ + s->hdsp.put_pixels_tab[0][0](s->dest[0], dest_y , linesize,16); + s->hdsp.put_pixels_tab[s->chroma_x_shift][0](s->dest[1], dest_cb, uvlinesize,16 >> s->chroma_y_shift); + s->hdsp.put_pixels_tab[s->chroma_x_shift][0](s->dest[2], dest_cr, uvlinesize,16 >> s->chroma_y_shift); + } + } +} + +void ff_MPV_decode_mb(MpegEncContext *s, int16_t block[12][64]){ +#if !CONFIG_SMALL + if(s->out_format == FMT_MPEG1) { + if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1, 1); + else MPV_decode_mb_internal(s, block, 0, 1); + } else +#endif + if(s->avctx->lowres) MPV_decode_mb_internal(s, block, 1, 0); + else MPV_decode_mb_internal(s, block, 0, 0); +} + +/** + * @param h is the normal height, this will be reduced automatically if needed for the last row + */ +void ff_draw_horiz_band(AVCodecContext *avctx, DSPContext *dsp, Picture *cur, + Picture *last, int y, int h, int picture_structure, + int first_field, int draw_edges, int low_delay, + int v_edge_pos, int h_edge_pos) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + int hshift = desc->log2_chroma_w; + int vshift = desc->log2_chroma_h; + const int field_pic = picture_structure != PICT_FRAME; + if(field_pic){ + h <<= 1; + y <<= 1; + } + + if (!avctx->hwaccel && + !(avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) && + draw_edges && + cur->reference && + !(avctx->flags & CODEC_FLAG_EMU_EDGE)) { + int *linesize = cur->f.linesize; + int sides = 0, edge_h; + if (y==0) sides |= EDGE_TOP; + if (y + h >= v_edge_pos) + sides |= EDGE_BOTTOM; + + edge_h= FFMIN(h, v_edge_pos - y); + + dsp->draw_edges(cur->f.data[0] + y * linesize[0], + linesize[0], h_edge_pos, edge_h, + EDGE_WIDTH, EDGE_WIDTH, sides); + dsp->draw_edges(cur->f.data[1] + (y >> vshift) * linesize[1], + linesize[1], h_edge_pos >> hshift, edge_h >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, sides); + dsp->draw_edges(cur->f.data[2] + (y >> vshift) * linesize[2], + linesize[2], h_edge_pos >> hshift, edge_h >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, sides); + } + + h = FFMIN(h, avctx->height - y); + + if(field_pic && first_field && !(avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)) return; + + if (avctx->draw_horiz_band) { + AVFrame *src; + int offset[AV_NUM_DATA_POINTERS]; + int i; + + if(cur->f.pict_type == AV_PICTURE_TYPE_B || low_delay || + (avctx->slice_flags & SLICE_FLAG_CODED_ORDER)) + src = &cur->f; + else if (last) + src = &last->f; + else + return; + + if (cur->f.pict_type == AV_PICTURE_TYPE_B && + picture_structure == PICT_FRAME && + avctx->codec_id != AV_CODEC_ID_SVQ3) { + for (i = 0; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + }else{ + offset[0]= y * src->linesize[0]; + offset[1]= + offset[2]= (y >> vshift) * src->linesize[1]; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + } + + emms_c(); + + avctx->draw_horiz_band(avctx, src, offset, + y, picture_structure, h); + } +} + +void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) +{ + int draw_edges = s->unrestricted_mv && !s->intra_only; + ff_draw_horiz_band(s->avctx, &s->dsp, &s->current_picture, + &s->last_picture, y, h, s->picture_structure, + s->first_field, draw_edges, s->low_delay, + s->v_edge_pos, s->h_edge_pos); +} + +void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename + const int linesize = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics + const int uvlinesize = s->current_picture.f.linesize[1]; + const int mb_size= 4 - s->avctx->lowres; + + s->block_index[0]= s->b8_stride*(s->mb_y*2 ) - 2 + s->mb_x*2; + s->block_index[1]= s->b8_stride*(s->mb_y*2 ) - 1 + s->mb_x*2; + s->block_index[2]= s->b8_stride*(s->mb_y*2 + 1) - 2 + s->mb_x*2; + s->block_index[3]= s->b8_stride*(s->mb_y*2 + 1) - 1 + s->mb_x*2; + s->block_index[4]= s->mb_stride*(s->mb_y + 1) + s->b8_stride*s->mb_height*2 + s->mb_x - 1; + s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x - 1; + //block_index is not used by mpeg2, so it is not affected by chroma_format + + s->dest[0] = s->current_picture.f.data[0] + ((s->mb_x - 1) << mb_size); + s->dest[1] = s->current_picture.f.data[1] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift)); + s->dest[2] = s->current_picture.f.data[2] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift)); + + if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME)) + { + if(s->picture_structure==PICT_FRAME){ + s->dest[0] += s->mb_y * linesize << mb_size; + s->dest[1] += s->mb_y * uvlinesize << (mb_size - s->chroma_y_shift); + s->dest[2] += s->mb_y * uvlinesize << (mb_size - s->chroma_y_shift); + }else{ + s->dest[0] += (s->mb_y>>1) * linesize << mb_size; + s->dest[1] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); + s->dest[2] += (s->mb_y>>1) * uvlinesize << (mb_size - s->chroma_y_shift); + av_assert1((s->mb_y&1) == (s->picture_structure == PICT_BOTTOM_FIELD)); + } + } +} + +/** + * Permute an 8x8 block. + * @param block the block which will be permuted according to the given permutation vector + * @param permutation the permutation vector + * @param last the last non zero coefficient in scantable order, used to speed the permutation up + * @param scantable the used scantable, this is only used to speed the permutation up, the block is not + * (inverse) permutated to scantable order! + */ +void ff_block_permute(int16_t *block, uint8_t *permutation, const uint8_t *scantable, int last) +{ + int i; + int16_t temp[64]; + + if(last<=0) return; + //if(permutation[1]==1) return; //FIXME it is ok but not clean and might fail for some permutations + + for(i=0; i<=last; i++){ + const int j= scantable[i]; + temp[j]= block[j]; + block[j]=0; + } + + for(i=0; i<=last; i++){ + const int j= scantable[i]; + const int perm_j= permutation[j]; + block[perm_j]= temp[j]; + } +} + +void ff_mpeg_flush(AVCodecContext *avctx){ + int i; + MpegEncContext *s = avctx->priv_data; + + if(s==NULL || s->picture==NULL) + return; + + for (i = 0; i < MAX_PICTURE_COUNT; i++) + ff_mpeg_unref_picture(s, &s->picture[i]); + s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; + + s->mb_x= s->mb_y= 0; + s->closed_gop= 0; + + s->parse_context.state= -1; + s->parse_context.frame_start_found= 0; + s->parse_context.overread= 0; + s->parse_context.overread_index= 0; + s->parse_context.index= 0; + s->parse_context.last_index= 0; + s->bitstream_buffer_size=0; + s->pp_time=0; +} + +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 mpeg1 */ + 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->alternate_scan) nCoeffs= 63; + else 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]) >> 3; + level = -level; + } else { + level = (int)(level * qscale * quant_matrix[j]) >> 3; + } + 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->alternate_scan) nCoeffs= 63; + else 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]) >> 3; + level = -level; + } else { + level = (int)(level * qscale * quant_matrix[j]) >> 3; + } + 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->alternate_scan) nCoeffs= 63; + else 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; + } else { + level = (((level << 1) + 1) * qscale * + ((int) (quant_matrix[j]))) >> 4; + } + 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; + + assert(s->block_last_index[n]>=0); + + 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->inter_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; + + assert(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; + } + } +} + +/** + * set qscale and update qscale dependent variables. + */ +void ff_set_qscale(MpegEncContext * s, int qscale) +{ + if (qscale < 1) + qscale = 1; + else if (qscale > 31) + qscale = 31; + + s->qscale = qscale; + s->chroma_qscale= s->chroma_qscale_table[qscale]; + + s->y_dc_scale= s->y_dc_scale_table[ qscale ]; + s->c_dc_scale= s->c_dc_scale_table[ s->chroma_qscale ]; +} + +void ff_MPV_report_decode_progress(MpegEncContext *s) +{ + if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) + ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); +} + +#if CONFIG_ERROR_RESILIENCE +void ff_mpeg_er_frame_start(MpegEncContext *s) +{ + ERContext *er = &s->er; + + er->cur_pic = s->current_picture_ptr; + er->last_pic = s->last_picture_ptr; + er->next_pic = s->next_picture_ptr; + + er->pp_time = s->pp_time; + er->pb_time = s->pb_time; + er->quarter_sample = s->quarter_sample; + er->partitioned_frame = s->partitioned_frame; + + ff_er_frame_start(er); +} +#endif /* CONFIG_ERROR_RESILIENCE */ diff --git a/ffmpeg/libavcodec/mpegvideo.h b/ffmpeg/libavcodec/mpegvideo.h new file mode 100644 index 0000000..40fd295 --- /dev/null +++ b/ffmpeg/libavcodec/mpegvideo.h @@ -0,0 +1,968 @@ +/* + * Generic DCT based hybrid video encoder + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * mpegvideo header. + */ + +#ifndef AVCODEC_MPEGVIDEO_H +#define AVCODEC_MPEGVIDEO_H + +#include "avcodec.h" +#include "dsputil.h" +#include "error_resilience.h" +#include "get_bits.h" +#include "h264chroma.h" +#include "hpeldsp.h" +#include "put_bits.h" +#include "ratecontrol.h" +#include "parser.h" +#include "mpeg12data.h" +#include "rl.h" +#include "thread.h" +#include "videodsp.h" + +#include "libavutil/opt.h" +#include "libavutil/timecode.h" + +#define FRAME_SKIPPED 100 ///< return value for header parsers if frame is not coded + +enum OutputFormat { + FMT_MPEG1, + FMT_H261, + FMT_H263, + FMT_MJPEG, +}; + +#define MPEG_BUF_SIZE (16 * 1024) + +#define QMAT_SHIFT_MMX 16 +#define QMAT_SHIFT 21 + +#define MAX_FCODE 7 +#define MAX_MV 4096 + +#define MAX_THREADS 32 +#define MAX_PICTURE_COUNT 36 + +#define ME_MAP_SIZE 64 +#define ME_MAP_SHIFT 3 +#define ME_MAP_MV_BITS 11 + +#define MAX_MB_BYTES (30*16*16*3/8 + 120) + +#define INPLACE_OFFSET 16 + +/* Start codes. */ +#define SEQ_END_CODE 0x000001b7 +#define SEQ_START_CODE 0x000001b3 +#define GOP_START_CODE 0x000001b8 +#define PICTURE_START_CODE 0x00000100 +#define SLICE_MIN_START_CODE 0x00000101 +#define SLICE_MAX_START_CODE 0x000001af +#define EXT_START_CODE 0x000001b5 +#define USER_START_CODE 0x000001b2 + +/** + * Value of Picture.reference when Picture is not a reference picture, but + * is held for delayed output. + */ +#define DELAYED_PIC_REF 4 + +struct MpegEncContext; + +/** + * Picture. + */ +typedef struct Picture{ + struct AVFrame f; + ThreadFrame tf; + + AVBufferRef *qscale_table_buf; + int8_t *qscale_table; + + AVBufferRef *motion_val_buf[2]; + int16_t (*motion_val[2])[2]; + + AVBufferRef *mb_type_buf; + uint32_t *mb_type; + + AVBufferRef *mbskip_table_buf; + uint8_t *mbskip_table; + + AVBufferRef *ref_index_buf[2]; + int8_t *ref_index[2]; + + AVBufferRef *mb_var_buf; + uint16_t *mb_var; ///< Table for MB variances + + AVBufferRef *mc_mb_var_buf; + uint16_t *mc_mb_var; ///< Table for motion compensated MB variances + + AVBufferRef *mb_mean_buf; + uint8_t *mb_mean; ///< Table for MB luminance + + AVBufferRef *hwaccel_priv_buf; + /** + * hardware accelerator private data + */ + void *hwaccel_picture_private; + +#define MB_TYPE_INTRA MB_TYPE_INTRA4x4 //default mb_type if there is just one type +#define IS_INTRA4x4(a) ((a)&MB_TYPE_INTRA4x4) +#define IS_INTRA16x16(a) ((a)&MB_TYPE_INTRA16x16) +#define IS_PCM(a) ((a)&MB_TYPE_INTRA_PCM) +#define IS_INTRA(a) ((a)&7) +#define IS_INTER(a) ((a)&(MB_TYPE_16x16|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_8x8)) +#define IS_SKIP(a) ((a)&MB_TYPE_SKIP) +#define IS_INTRA_PCM(a) ((a)&MB_TYPE_INTRA_PCM) +#define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED) +#define IS_DIRECT(a) ((a)&MB_TYPE_DIRECT2) +#define IS_GMC(a) ((a)&MB_TYPE_GMC) +#define IS_16X16(a) ((a)&MB_TYPE_16x16) +#define IS_16X8(a) ((a)&MB_TYPE_16x8) +#define IS_8X16(a) ((a)&MB_TYPE_8x16) +#define IS_8X8(a) ((a)&MB_TYPE_8x8) +#define IS_SUB_8X8(a) ((a)&MB_TYPE_16x16) //note reused +#define IS_SUB_8X4(a) ((a)&MB_TYPE_16x8) //note reused +#define IS_SUB_4X8(a) ((a)&MB_TYPE_8x16) //note reused +#define IS_SUB_4X4(a) ((a)&MB_TYPE_8x8) //note reused +#define IS_ACPRED(a) ((a)&MB_TYPE_ACPRED) +#define IS_QUANT(a) ((a)&MB_TYPE_QUANT) +#define IS_DIR(a, part, list) ((a) & (MB_TYPE_P0L0<<((part)+2*(list)))) +#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list)))) ///< does this mb use listX, note does not work if subMBs +#define HAS_CBP(a) ((a)&MB_TYPE_CBP) + + int field_poc[2]; ///< h264 top/bottom POC + int poc; ///< h264 frame POC + int frame_num; ///< h264 frame_num (raw frame_num from slice header) + int mmco_reset; ///< h264 MMCO_RESET set this 1. Reordering code must not mix pictures before and after MMCO_RESET. + int pic_id; /**< h264 pic_num (short -> no wrap version of pic_num, + pic_num & max_pic_num; long -> long_pic_num) */ + int long_ref; ///< 1->long term reference 0->short term reference + int ref_poc[2][2][32]; ///< h264 POCs of the frames/fields used as reference (FIXME need per slice) + int ref_count[2][2]; ///< number of entries in ref_poc (FIXME need per slice) + int mbaff; ///< h264 1 -> MBAFF frame 0-> not MBAFF + int field_picture; ///< whether or not the picture was encoded in separate fields + int sync; ///< has been decoded after a keyframe + + int mb_var_sum; ///< sum of MB variance for current frame + int mc_mb_var_sum; ///< motion compensated MB variance for current frame + + int b_frame_score; /* */ + int needs_realloc; ///< Picture needs to be reallocated (eg due to a frame size change) + int period_since_free; ///< "cycles" since this Picture has been freed + + int reference; + int shared; +} Picture; + +/** + * Motion estimation context. + */ +typedef struct MotionEstContext{ + AVCodecContext *avctx; + int skip; ///< set if ME is skipped for the current MB + int co_located_mv[4][2]; ///< mv from last P-frame for direct mode ME + int direct_basis_mv[4][2]; + uint8_t *scratchpad; ///< data area for the ME algo, so that the ME does not need to malloc/free + uint8_t *best_mb; + uint8_t *temp_mb[2]; + uint8_t *temp; + int best_bits; + uint32_t *map; ///< map to avoid duplicate evaluations + uint32_t *score_map; ///< map to store the scores + unsigned map_generation; + int pre_penalty_factor; + int penalty_factor; /**< an estimate of the bits required to + code a given mv value, e.g. (1,0) takes + more bits than (0,0). We have to + estimate whether any reduction in + residual is worth the extra bits. */ + int sub_penalty_factor; + int mb_penalty_factor; + int flags; + int sub_flags; + int mb_flags; + int pre_pass; ///< = 1 for the pre pass + int dia_size; + int xmin; + int xmax; + int ymin; + int ymax; + int pred_x; + int pred_y; + uint8_t *src[4][4]; + uint8_t *ref[4][4]; + int stride; + int uvstride; + /* temp variables for picture complexity calculation */ + int mc_mb_var_sum_temp; + int mb_var_sum_temp; + int scene_change_score; +/* cmp, chroma_cmp;*/ + op_pixels_func (*hpel_put)[4]; + op_pixels_func (*hpel_avg)[4]; + qpel_mc_func (*qpel_put)[16]; + qpel_mc_func (*qpel_avg)[16]; + uint8_t (*mv_penalty)[MAX_MV*2+1]; ///< amount of bits needed to encode a MV + uint8_t *current_mv_penalty; + int (*sub_motion_search)(struct MpegEncContext * s, + int *mx_ptr, int *my_ptr, int dmin, + int src_index, int ref_index, + int size, int h); +}MotionEstContext; + +/** + * MpegEncContext. + */ +typedef struct MpegEncContext { + AVClass *class; + struct AVCodecContext *avctx; + /* the following parameters must be initialized before encoding */ + int width, height;///< picture size. must be a multiple of 16 + int gop_size; + int intra_only; ///< if true, only intra pictures are generated + int bit_rate; ///< wanted bit rate + enum OutputFormat out_format; ///< output format + int h263_pred; ///< use mpeg4/h263 ac/dc predictions + int pb_frame; ///< PB frame mode (0 = none, 1 = base, 2 = improved) + +/* the following codec id fields are deprecated in favor of codec_id */ + int h263_plus; ///< h263 plus headers + int h263_flv; ///< use flv h263 header + + enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ + int fixed_qscale; ///< fixed qscale if non zero + int encoding; ///< true if we are encoding (vs decoding) + int flags; ///< AVCodecContext.flags (HQ, MV4, ...) + int flags2; ///< AVCodecContext.flags2 + int max_b_frames; ///< max number of b-frames for encoding + int luma_elim_threshold; + int chroma_elim_threshold; + int strict_std_compliance; ///< strictly follow the std (MPEG4, ...) + int workaround_bugs; ///< workaround bugs in encoders which cannot be detected automatically + int codec_tag; ///< internal codec_tag upper case converted from avctx codec_tag + int stream_codec_tag; ///< internal stream_codec_tag upper case converted from avctx stream_codec_tag + /* the following fields are managed internally by the encoder */ + + /* sequence parameters */ + int context_initialized; + int input_picture_number; ///< used to set pic->display_picture_number, should not be used for/by anything else + int coded_picture_number; ///< used to set pic->coded_picture_number, should not be used for/by anything else + int picture_number; //FIXME remove, unclear definition + int picture_in_gop_number; ///< 0-> first pic in gop, ... + int mb_width, mb_height; ///< number of MBs horizontally & vertically + int mb_stride; ///< mb_width+1 used for some arrays to allow simple addressing of left & top MBs without sig11 + int b8_stride; ///< 2*mb_width+1 used for some 8x8 block arrays to allow simple addressing + int b4_stride; ///< 4*mb_width+1 used for some 4x4 block arrays to allow simple addressing + int h_edge_pos, v_edge_pos;///< horizontal / vertical position of the right/bottom edge (pixel replication) + int mb_num; ///< number of MBs of a picture + int linesize; ///< line size, in bytes, may be different from width + int uvlinesize; ///< line size, for chroma in bytes, may be different from width + Picture *picture; ///< main picture buffer + Picture **input_picture; ///< next pictures on display order for encoding + Picture **reordered_input_picture; ///< pointer to the next pictures in codedorder for encoding + + int y_dc_scale, c_dc_scale; + int ac_pred; + int block_last_index[12]; ///< last non zero coefficient in block + int h263_aic; ///< Advanded INTRA Coding (AIC) + + /* scantables */ + ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage + ScanTable intra_scantable; + ScanTable intra_h_scantable; + ScanTable intra_v_scantable; + + /* WARNING: changes above this line require updates to hardcoded + * offsets used in asm. */ + + int64_t user_specified_pts;///< last non zero pts from AVFrame which was passed into avcodec_encode_video() + /** + * pts difference between the first and second input frame, used for + * calculating dts of the first frame when there's a delay */ + int64_t dts_delta; + /** + * reordered pts to be used as dts for the next output frame when there's + * a delay */ + int64_t reordered_pts; + + /** bit output */ + PutBitContext pb; + + int start_mb_y; ///< start mb_y of this thread (so current thread should process start_mb_y <= row < end_mb_y) + int end_mb_y; ///< end mb_y of this thread (so current thread should process start_mb_y <= row < end_mb_y) + struct MpegEncContext *thread_context[MAX_THREADS]; + int slice_context_count; ///< number of used thread_contexts + + /** + * copy of the previous picture structure. + * note, linesize & data, might not match the previous picture (for field pictures) + */ + Picture last_picture; + + /** + * copy of the next picture structure. + * note, linesize & data, might not match the next picture (for field pictures) + */ + Picture next_picture; + + /** + * copy of the source picture structure for encoding. + * note, linesize & data, might not match the source picture (for field pictures) + */ + Picture new_picture; + + /** + * copy of the current picture structure. + * note, linesize & data, might not match the current picture (for field pictures) + */ + Picture current_picture; ///< buffer to store the decompressed current picture + + Picture *last_picture_ptr; ///< pointer to the previous picture. + Picture *next_picture_ptr; ///< pointer to the next picture (for bidir pred) + Picture *current_picture_ptr; ///< pointer to the current picture + int last_dc[3]; ///< last DC values for MPEG1 + int16_t *dc_val_base; + int16_t *dc_val[3]; ///< used for mpeg4 DC prediction, all 3 arrays must be continuous + const uint8_t *y_dc_scale_table; ///< qscale -> y_dc_scale table + const uint8_t *c_dc_scale_table; ///< qscale -> c_dc_scale table + const uint8_t *chroma_qscale_table; ///< qscale -> chroma_qscale (h263) + uint8_t *coded_block_base; + uint8_t *coded_block; ///< used for coded block pattern prediction (msmpeg4v3, wmv1) + int16_t (*ac_val_base)[16]; + int16_t (*ac_val[3])[16]; ///< used for for mpeg4 AC prediction, all 3 arrays must be continuous + int mb_skipped; ///< MUST BE SET only during DECODING + uint8_t *mbskip_table; /**< used to avoid copy if macroblock skipped (for black regions for example) + and used for b-frame encoding & decoding (contains skip table of next P Frame) */ + uint8_t *mbintra_table; ///< used to avoid setting {ac, dc, cbp}-pred stuff to zero on inter MB decoding + uint8_t *cbp_table; ///< used to store cbp, ac_pred for partitioned decoding + uint8_t *pred_dir_table; ///< used to store pred_dir for partitioned decoding + uint8_t *edge_emu_buffer; ///< temporary buffer for if MVs point to out-of-frame data + uint8_t *rd_scratchpad; ///< scratchpad for rate distortion mb decision + uint8_t *obmc_scratchpad; + uint8_t *b_scratchpad; ///< scratchpad used for writing into write only buffers + + int qscale; ///< QP + int chroma_qscale; ///< chroma QP + unsigned int lambda; ///< lagrange multipler used in rate distortion + unsigned int lambda2; ///< (lambda*lambda) >> FF_LAMBDA_SHIFT + int *lambda_table; + int adaptive_quant; ///< use adaptive quantization + int dquant; ///< qscale difference to prev qscale + int closed_gop; ///< MPEG1/2 GOP is closed + int pict_type; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... + int vbv_delay; + int last_pict_type; //FIXME removes + int last_non_b_pict_type; ///< used for mpeg4 gmc b-frames & ratecontrol + int droppable; + int frame_rate_index; + AVRational mpeg2_frame_rate_ext; + int last_lambda_for[5]; ///< last lambda for a specific pict type + int skipdct; ///< skip dct and code zero residual + + /* motion compensation */ + int unrestricted_mv; ///< mv can point outside of the coded picture + int h263_long_vectors; ///< use horrible h263v1 long vector mode + + DSPContext dsp; ///< pointers for accelerated dsp functions + H264ChromaContext h264chroma; + HpelDSPContext hdsp; + VideoDSPContext vdsp; + int f_code; ///< forward MV resolution + int b_code; ///< backward MV resolution for B Frames (mpeg4) + int16_t (*p_mv_table_base)[2]; + int16_t (*b_forw_mv_table_base)[2]; + int16_t (*b_back_mv_table_base)[2]; + int16_t (*b_bidir_forw_mv_table_base)[2]; + int16_t (*b_bidir_back_mv_table_base)[2]; + int16_t (*b_direct_mv_table_base)[2]; + int16_t (*p_field_mv_table_base[2][2])[2]; + int16_t (*b_field_mv_table_base[2][2][2])[2]; + int16_t (*p_mv_table)[2]; ///< MV table (1MV per MB) p-frame encoding + int16_t (*b_forw_mv_table)[2]; ///< MV table (1MV per MB) forward mode b-frame encoding + int16_t (*b_back_mv_table)[2]; ///< MV table (1MV per MB) backward mode b-frame encoding + int16_t (*b_bidir_forw_mv_table)[2]; ///< MV table (1MV per MB) bidir mode b-frame encoding + int16_t (*b_bidir_back_mv_table)[2]; ///< MV table (1MV per MB) bidir mode b-frame encoding + int16_t (*b_direct_mv_table)[2]; ///< MV table (1MV per MB) direct mode b-frame encoding + int16_t (*p_field_mv_table[2][2])[2]; ///< MV table (2MV per MB) interlaced p-frame encoding + int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced b-frame encoding + uint8_t (*p_field_select_table[2]); + uint8_t (*b_field_select_table[2][2]); + int me_method; ///< ME algorithm + int mv_dir; +#define MV_DIR_FORWARD 1 +#define MV_DIR_BACKWARD 2 +#define MV_DIRECT 4 ///< bidirectional mode where the difference equals the MV of the last P/S/I-Frame (mpeg4) + int mv_type; +#define MV_TYPE_16X16 0 ///< 1 vector for the whole mb +#define MV_TYPE_8X8 1 ///< 4 vectors (h263, mpeg4 4MV) +#define MV_TYPE_16X8 2 ///< 2 vectors, one per 16x8 block +#define MV_TYPE_FIELD 3 ///< 2 vectors, one per field +#define MV_TYPE_DMV 4 ///< 2 vectors, special mpeg2 Dual Prime Vectors + /**motion vectors for a macroblock + first coordinate : 0 = forward 1 = backward + second " : depend on type + third " : 0 = x, 1 = y + */ + int mv[2][4][2]; + int field_select[2][2]; + int last_mv[2][2][2]; ///< last MV, used for MV prediction in MPEG1 & B-frame MPEG4 + uint8_t *fcode_tab; ///< smallest fcode needed for each MV + int16_t direct_scale_mv[2][64]; ///< precomputed to avoid divisions in ff_mpeg4_set_direct_mv + + MotionEstContext me; + + int no_rounding; /**< apply no rounding to motion compensation (MPEG4, msmpeg4, ...) + for b-frames rounding mode is always 0 */ + + /* macroblock layer */ + int mb_x, mb_y; + int mb_skip_run; + int mb_intra; + uint16_t *mb_type; ///< Table for candidate MB types for encoding +#define CANDIDATE_MB_TYPE_INTRA 0x01 +#define CANDIDATE_MB_TYPE_INTER 0x02 +#define CANDIDATE_MB_TYPE_INTER4V 0x04 +#define CANDIDATE_MB_TYPE_SKIPPED 0x08 +//#define MB_TYPE_GMC 0x10 + +#define CANDIDATE_MB_TYPE_DIRECT 0x10 +#define CANDIDATE_MB_TYPE_FORWARD 0x20 +#define CANDIDATE_MB_TYPE_BACKWARD 0x40 +#define CANDIDATE_MB_TYPE_BIDIR 0x80 + +#define CANDIDATE_MB_TYPE_INTER_I 0x100 +#define CANDIDATE_MB_TYPE_FORWARD_I 0x200 +#define CANDIDATE_MB_TYPE_BACKWARD_I 0x400 +#define CANDIDATE_MB_TYPE_BIDIR_I 0x800 + +#define CANDIDATE_MB_TYPE_DIRECT0 0x1000 + + int block_index[6]; ///< index to current MB in block based arrays with edges + int block_wrap[6]; + uint8_t *dest[3]; + + int *mb_index2xy; ///< mb_index -> mb_x + mb_y*mb_stride + + /** matrix transmitted in the bitstream */ + uint16_t intra_matrix[64]; + uint16_t chroma_intra_matrix[64]; + uint16_t inter_matrix[64]; + uint16_t chroma_inter_matrix[64]; +#define QUANT_BIAS_SHIFT 8 + int intra_quant_bias; ///< bias for the quantizer + int inter_quant_bias; ///< bias for the quantizer + int min_qcoeff; ///< minimum encodable coefficient + int max_qcoeff; ///< maximum encodable coefficient + int ac_esc_length; ///< num of bits needed to encode the longest esc + uint8_t *intra_ac_vlc_length; + uint8_t *intra_ac_vlc_last_length; + uint8_t *inter_ac_vlc_length; + uint8_t *inter_ac_vlc_last_length; + uint8_t *luma_dc_vlc_length; +#define UNI_AC_ENC_INDEX(run,level) ((run)*128 + (level)) + + int coded_score[12]; + + /** precomputed matrix (combine qscale and DCT renorm) */ + int (*q_intra_matrix)[64]; + int (*q_chroma_intra_matrix)[64]; + int (*q_inter_matrix)[64]; + /** identical to the above but for MMX & these are not permutated, second 64 entries are bias*/ + uint16_t (*q_intra_matrix16)[2][64]; + uint16_t (*q_chroma_intra_matrix16)[2][64]; + uint16_t (*q_inter_matrix16)[2][64]; + + /* noise reduction */ + int (*dct_error_sum)[64]; + int dct_count[2]; + uint16_t (*dct_offset)[64]; + + void *opaque; ///< private data for the user + + /* bit rate control */ + int64_t total_bits; + int frame_bits; ///< bits used for the current frame + int stuffing_bits; ///< bits used for stuffing + int next_lambda; ///< next lambda used for retrying to encode a frame + RateControlContext rc_context; ///< contains stuff only accessed in ratecontrol.c + + /* statistics, used for 2-pass encoding */ + int mv_bits; + int header_bits; + int i_tex_bits; + int p_tex_bits; + int i_count; + int f_count; + int b_count; + int skip_count; + int misc_bits; ///< cbp, mb_type + int last_bits; ///< temp var used for calculating the above vars + + /* error concealment / resync */ + int resync_mb_x; ///< x position of last resync marker + int resync_mb_y; ///< y position of last resync marker + GetBitContext last_resync_gb; ///< used to search for the next resync marker + int mb_num_left; ///< number of MBs left in this video packet (for partitioned Slices only) + int next_p_frame_damaged; ///< set if the next p frame is damaged, to avoid showing trashed b frames + int err_recognition; + + ParseContext parse_context; + + /* H.263 specific */ + int gob_index; + int obmc; ///< overlapped block motion compensation + int showed_packed_warning; ///< flag for having shown the warning about divxs invalid b frames + int mb_info; ///< interval for outputting info about mb offsets as side data + int prev_mb_info, last_mb_info; + uint8_t *mb_info_ptr; + int mb_info_size; + + /* H.263+ specific */ + int umvplus; ///< == H263+ && unrestricted_mv + int h263_aic_dir; ///< AIC direction: 0 = left, 1 = top + int h263_slice_structured; + int alt_inter_vlc; ///< alternative inter vlc + int modified_quant; + int loop_filter; + int custom_pcf; + + /* mpeg4 specific */ + int time_increment_bits; ///< number of bits to represent the fractional part of time + int last_time_base; + int time_base; ///< time in seconds of last I,P,S Frame + int64_t time; ///< time of current frame + int64_t last_non_b_time; + uint16_t pp_time; ///< time distance between the last 2 p,s,i frames + uint16_t pb_time; ///< time distance between the last b and p,s,i frame + uint16_t pp_field_time; + uint16_t pb_field_time; ///< like above, just for interlaced + int shape; + int vol_sprite_usage; + int sprite_width; + int sprite_height; + int sprite_left; + int sprite_top; + int sprite_brightness_change; + int num_sprite_warping_points; + int real_sprite_warping_points; + uint16_t sprite_traj[4][2]; ///< sprite trajectory points + int sprite_offset[2][2]; ///< sprite offset[isChroma][isMVY] + int sprite_delta[2][2]; ///< sprite_delta [isY][isMVY] + int sprite_shift[2]; ///< sprite shift [isChroma] + int mcsel; + int quant_precision; + int quarter_sample; ///< 1->qpel, 0->half pel ME/MC + int scalability; + int hierachy_type; + int enhancement_type; + int new_pred; + int reduced_res_vop; + int aspect_ratio_info; //FIXME remove + int sprite_warping_accuracy; + int low_latency_sprite; + int data_partitioning; ///< data partitioning flag from header + int partitioned_frame; ///< is current frame partitioned + int rvlc; ///< reversible vlc + int resync_marker; ///< could this stream contain resync markers + int low_delay; ///< no reordering needed / has no b-frames + int vo_type; + int vol_control_parameters; ///< does the stream contain the low_delay flag, used to workaround buggy encoders + int intra_dc_threshold; ///< QP above whch the ac VLC should be used for intra dc + int use_intra_dc_vlc; + PutBitContext tex_pb; ///< used for data partitioned VOPs + PutBitContext pb2; ///< used for data partitioned VOPs + int mpeg_quant; + int t_frame; ///< time distance of first I -> B, used for interlaced b frames + int padding_bug_score; ///< used to detect the VERY common padding bug in MPEG4 + int cplx_estimation_trash_i; + int cplx_estimation_trash_p; + int cplx_estimation_trash_b; + + /* divx specific, used to workaround (many) bugs in divx5 */ + int divx_version; + int divx_build; + int divx_packed; + uint8_t *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them + int bitstream_buffer_size; + unsigned int allocated_bitstream_buffer_size; + + int xvid_build; + + /* lavc specific stuff, used to workaround bugs in libavcodec */ + int lavc_build; + + /* RV10 specific */ + int rv10_version; ///< RV10 version: 0 or 3 + int rv10_first_dc_coded[3]; + int orig_width, orig_height; + + /* MJPEG specific */ + struct MJpegContext *mjpeg_ctx; + int mjpeg_vsample[3]; ///< vertical sampling factors, default = {2, 1, 1} + int mjpeg_hsample[3]; ///< horizontal sampling factors, default = {2, 1, 1} + int esc_pos; + + /* MSMPEG4 specific */ + int mv_table_index; + int rl_table_index; + int rl_chroma_table_index; + int dc_table_index; + int use_skip_mb_code; + int slice_height; ///< in macroblocks + int first_slice_line; ///< used in mpeg4 too to handle resync markers + int flipflop_rounding; + int msmpeg4_version; ///< 0=not msmpeg4, 1=mp41, 2=mp42, 3=mp43/divx3 4=wmv1/7 5=wmv2/8 + int per_mb_rl_table; + int esc3_level_length; + int esc3_run_length; + /** [mb_intra][isChroma][level][run][last] */ + int (*ac_stats)[2][MAX_LEVEL+1][MAX_RUN+1][2]; + int inter_intra_pred; + int mspel; + + /* decompression specific */ + GetBitContext gb; + + /* Mpeg1 specific */ + int gop_picture_number; ///< index of the first picture of a GOP based on fake_pic_num & mpeg1 specific + int last_mv_dir; ///< last mv_dir, used for b frame encoding + int broken_link; ///< no_output_of_prior_pics_flag + uint8_t *vbv_delay_ptr; ///< pointer to vbv_delay in the bitstream + + /* MPEG-2-specific - I wished not to have to support this mess. */ + int progressive_sequence; + int mpeg_f_code[2][2]; + int picture_structure; +/* picture type */ +#define PICT_TOP_FIELD 1 +#define PICT_BOTTOM_FIELD 2 +#define PICT_FRAME 3 + + int intra_dc_precision; + int frame_pred_frame_dct; + int top_field_first; + int concealment_motion_vectors; + int q_scale_type; + int intra_vlc_format; + int alternate_scan; + int repeat_first_field; + int chroma_420_type; + int chroma_format; +#define CHROMA_420 1 +#define CHROMA_422 2 +#define CHROMA_444 3 + int chroma_x_shift;//depend on pix_format, that depend on chroma_format + int chroma_y_shift; + + int progressive_frame; + int full_pel[2]; + int interlaced_dct; + int first_slice; + int first_field; ///< is 1 for the first field of a field picture 0 otherwise + int drop_frame_timecode; ///< timecode is in drop frame format. + int scan_offset; ///< reserve space for SVCD scan offset user data. + + /* RTP specific */ + int rtp_mode; + + char *tc_opt_str; ///< timecode option string + AVTimecode tc; ///< timecode context + + uint8_t *ptr_lastgob; + int swap_uv; //vcr2 codec is an MPEG-2 variant with U and V swapped + int16_t (*pblocks[12])[64]; + + int16_t (*block)[64]; ///< points to one of the following blocks + int16_t (*blocks)[12][64]; // for HQ mode we need to keep the best block + int (*decode_mb)(struct MpegEncContext *s, int16_t block[6][64]); // used by some codecs to avoid a switch() +#define SLICE_OK 0 +#define SLICE_ERROR -1 +#define SLICE_END -2 ///= old_ctx->picture && \ + pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ + &new_ctx->picture[pic - old_ctx->picture] : NULL) + +/* mpegvideo_enc common options */ +#define FF_MPV_FLAG_SKIP_RD 0x0001 +#define FF_MPV_FLAG_STRICT_GOP 0x0002 +#define FF_MPV_FLAG_QP_RD 0x0004 +#define FF_MPV_FLAG_CBP_RD 0x0008 + +#define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) +#define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +#define FF_MPV_COMMON_OPTS \ +{ "mpv_flags", "Flags common for all mpegvideo-based encoders.", FF_MPV_OFFSET(mpv_flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "skip_rd", "RD optimal MB level residual skipping", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_SKIP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "strict_gop", "Strictly enforce gop size", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_STRICT_GOP }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "qp_rd", "Use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_QP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "cbp_rd", "use rate distortion optimization for CBP", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_CBP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "luma_elim_threshold", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\ + FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ +{ "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\ + FF_MPV_OFFSET(chroma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ +{ "quantizer_noise_shaping", NULL, FF_MPV_OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, + +extern const AVOption ff_mpv_generic_options[]; + +#define FF_MPV_GENERIC_CLASS(name) \ +static const AVClass name ## _class = {\ + .class_name = #name " encoder",\ + .item_name = av_default_item_name,\ + .option = ff_mpv_generic_options,\ + .version = LIBAVUTIL_VERSION_INT,\ +}; + +/** + * Set the given MpegEncContext to common defaults (same for encoding + * and decoding). The changed fields will not depend upon the prior + * state of the MpegEncContext. + */ +void ff_MPV_common_defaults(MpegEncContext *s); + +void ff_MPV_decode_defaults(MpegEncContext *s); +int ff_MPV_common_init(MpegEncContext *s); +int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize); +int ff_MPV_common_frame_size_change(MpegEncContext *s); +void ff_MPV_common_end(MpegEncContext *s); +void ff_MPV_decode_mb(MpegEncContext *s, int16_t block[12][64]); +int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx); +void ff_MPV_frame_end(MpegEncContext *s); +int ff_MPV_encode_init(AVCodecContext *avctx); +int ff_MPV_encode_end(AVCodecContext *avctx); +int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt, + AVFrame *frame, int *got_packet); +void ff_dct_encode_init_x86(MpegEncContext *s); +void ff_MPV_common_init_x86(MpegEncContext *s); +void ff_MPV_common_init_axp(MpegEncContext *s); +void ff_MPV_common_init_arm(MpegEncContext *s); +void ff_MPV_common_init_altivec(MpegEncContext *s); +void ff_MPV_common_init_bfin(MpegEncContext *s); +void ff_clean_intra_table_entries(MpegEncContext *s); +void ff_draw_horiz_band(AVCodecContext *avctx, DSPContext *dsp, Picture *cur, + Picture *last, int y, int h, int picture_structure, + int first_field, int draw_edges, int low_delay, + int v_edge_pos, int h_edge_pos); +void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h); +void ff_mpeg_flush(AVCodecContext *avctx); + +void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict); +void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, AVFrame *pict, uint8_t *mbskip_table, + int *low_delay, + int mb_width, int mb_height, int mb_stride, int quarter_sample); + +int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type); + +void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix); +void ff_release_unused_pictures(MpegEncContext *s, int remove_current); +int ff_find_unused_picture(MpegEncContext *s, int shared); +void ff_denoise_dct(MpegEncContext *s, int16_t *block); +int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src); +int ff_MPV_lowest_referenced_row(MpegEncContext *s, int dir); +void ff_MPV_report_decode_progress(MpegEncContext *s); +int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); +const uint8_t *avpriv_mpv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state); +void ff_set_qscale(MpegEncContext * s, int qscale); + +void ff_mpeg_er_frame_start(MpegEncContext *s); + +int ff_dct_common_init(MpegEncContext *s); +int ff_dct_encode_init(MpegEncContext *s); +void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], uint16_t (*qmat16)[2][64], + const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra); +int ff_dct_quantize_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow); + +void ff_init_block_index(MpegEncContext *s); + +void ff_MPV_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, int dir, + uint8_t **ref_picture, + op_pixels_func (*pix_op)[4], + qpel_mc_func (*qpix_op)[16]); + +/** + * Allocate a Picture. + * The pixels are allocated/set by calling get_buffer() if shared = 0. + */ +int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared); + +extern const enum AVPixelFormat ff_pixfmt_list_420[]; + +/** + * permute block according to permuatation. + * @param last last non zero element in scantable order + */ +void ff_block_permute(int16_t *block, uint8_t *permutation, const uint8_t *scantable, int last); + +static inline void ff_update_block_index(MpegEncContext *s){ + const int block_size= 8 >> s->avctx->lowres; + + s->block_index[0]+=2; + s->block_index[1]+=2; + s->block_index[2]+=2; + s->block_index[3]+=2; + s->block_index[4]++; + s->block_index[5]++; + s->dest[0]+= 2*block_size; + s->dest[1]+= block_size; + s->dest[2]+= block_size; +} + +static inline int get_bits_diff(MpegEncContext *s){ + const int bits= put_bits_count(&s->pb); + const int last= s->last_bits; + + s->last_bits = bits; + + return bits - last; +} + +static inline int ff_h263_round_chroma(int x){ + static const uint8_t h263_chroma_roundtab[16] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, + }; + return h263_chroma_roundtab[x & 0xf] + (x >> 3); +} + +/* motion_est.c */ +void ff_estimate_p_frame_motion(MpegEncContext * s, + int mb_x, int mb_y); +void ff_estimate_b_frame_motion(MpegEncContext * s, + int mb_x, int mb_y); +int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type); +void ff_fix_long_p_mvs(MpegEncContext * s); +void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select, + int16_t (*mv_table)[2], int f_code, int type, int truncate); +int ff_init_me(MpegEncContext *s); +int ff_pre_estimate_p_frame_motion(MpegEncContext * s, int mb_x, int mb_y); +int ff_epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr, + int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], + int ref_mv_scale, int size, int h); +int ff_get_mb_score(MpegEncContext * s, int mx, int my, int src_index, + int ref_index, int size, int h, int add_rate); + +/* mpeg12.c */ +extern const uint8_t ff_mpeg1_dc_scale_table[128]; +extern const uint8_t * const ff_mpeg2_dc_scale_table[4]; + +void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_mpeg1_encode_mb(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y); +void ff_mpeg1_encode_init(MpegEncContext *s); +void ff_mpeg1_encode_slice_header(MpegEncContext *s); +void ff_mpeg1_clean_buffers(MpegEncContext *s); +int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s); + +extern const uint8_t ff_aic_dc_scale_table[32]; +extern const uint8_t ff_h263_chroma_qscale_table[32]; +extern const uint8_t ff_h263_loop_filter_strength[32]; + +/* h261.c */ +void ff_h261_loop_filter(MpegEncContext *s); +void ff_h261_reorder_mb_index(MpegEncContext* s); +void ff_h261_encode_mb(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y); +void ff_h261_encode_picture_header(MpegEncContext * s, int picture_number); +void ff_h261_encode_init(MpegEncContext *s); +int ff_h261_get_picture_format(int width, int height); + + +/* rv10.c */ +void ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number); +int ff_rv_decode_dc(MpegEncContext *s, int n); +void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number); + + +/* msmpeg4.c */ +void ff_msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number); +void ff_msmpeg4_encode_ext_header(MpegEncContext * s); +void ff_msmpeg4_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y); +int ff_msmpeg4_decode_picture_header(MpegEncContext * s); +int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size); +int ff_msmpeg4_decode_init(AVCodecContext *avctx); +void ff_msmpeg4_encode_init(MpegEncContext *s); +int ff_wmv2_decode_picture_header(MpegEncContext * s); +int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s); +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr); +void ff_mspel_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture, op_pixels_func (*pix_op)[4], + int motion_x, int motion_y, int h); +int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number); +void ff_wmv2_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y); + +int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src); +void ff_mpeg_unref_picture(MpegEncContext *s, Picture *picture); + + +#endif /* AVCODEC_MPEGVIDEO_H */ diff --git a/ffmpeg/libavcodec/mpegvideo_enc.c b/ffmpeg/libavcodec/mpegvideo_enc.c new file mode 100644 index 0000000..dd66943 --- /dev/null +++ b/ffmpeg/libavcodec/mpegvideo_enc.c @@ -0,0 +1,4311 @@ +/* + * The simplest mpeg encoder (well, it was the simplest!) + * 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 + */ + +/** + * @file + * The simplest mpeg encoder (well, it was the simplest!). + */ + +#include "libavutil/internal.h" +#include "libavutil/intmath.h" +#include "libavutil/mathematics.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dct.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "h263.h" +#include "mathops.h" +#include "mjpegenc.h" +#include "msmpeg4.h" +#include "faandct.h" +#include "thread.h" +#include "aandcttab.h" +#include "flv.h" +#include "mpeg4video.h" +#include "internal.h" +#include "bytestream.h" +#include +#include "sp5x.h" + +//#undef NDEBUG +//#include + +static int encode_picture(MpegEncContext *s, int picture_number); +static int dct_quantize_refine(MpegEncContext *s, int16_t *block, int16_t *weight, int16_t *orig, int n, int qscale); +static int sse_mb(MpegEncContext *s); +static void denoise_dct_c(MpegEncContext *s, int16_t *block); +static int dct_quantize_trellis_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow); + +//#define DEBUG + +static uint8_t default_mv_penalty[MAX_FCODE + 1][MAX_MV * 2 + 1]; +static uint8_t default_fcode_tab[MAX_MV * 2 + 1]; + +const AVOption ff_mpv_generic_options[] = { + FF_MPV_COMMON_OPTS + { NULL }, +}; + +void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64], + uint16_t (*qmat16)[2][64], + const uint16_t *quant_matrix, + int bias, int qmin, int qmax, int intra) +{ + int qscale; + int shift = 0; + + for (qscale = qmin; qscale <= qmax; qscale++) { + int i; + if (dsp->fdct == ff_jpeg_fdct_islow_8 || + dsp->fdct == ff_jpeg_fdct_islow_10 || + dsp->fdct == ff_faandct) { + for (i = 0; i < 64; i++) { + const int j = dsp->idct_permutation[i]; + /* 16 <= qscale * quant_matrix[i] <= 7905 + * Assume x = ff_aanscales[i] * qscale * quant_matrix[i] + * 19952 <= x <= 249205026 + * (1 << 36) / 19952 >= (1 << 36) / (x) >= (1 << 36) / 249205026 + * 3444240 >= (1 << 36) / (x) >= 275 */ + + qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / + (qscale * quant_matrix[j])); + } + } else if (dsp->fdct == ff_fdct_ifast) { + for (i = 0; i < 64; i++) { + const int j = dsp->idct_permutation[i]; + /* 16 <= qscale * quant_matrix[i] <= 7905 + * Assume x = ff_aanscales[i] * qscale * quant_matrix[i] + * 19952 <= x <= 249205026 + * (1 << 36) / 19952 >= (1 << 36) / (x) >= (1 << 36) / 249205026 + * 3444240 >= (1 << 36) / (x) >= 275 */ + + qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 14)) / + (ff_aanscales[i] * (int64_t)qscale * quant_matrix[j])); + } + } else { + for (i = 0; i < 64; i++) { + const int j = dsp->idct_permutation[i]; + /* We can safely suppose that 16 <= quant_matrix[i] <= 255 + * Assume x = qscale * quant_matrix[i] + * So 16 <= x <= 7905 + * so (1 << 19) / 16 >= (1 << 19) / (x) >= (1 << 19) / 7905 + * so 32768 >= (1 << 19) / (x) >= 67 */ + qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / + (qscale * quant_matrix[j])); + //qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / + // (qscale * quant_matrix[i]); + qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / + (qscale * quant_matrix[j]); + + if (qmat16[qscale][0][i] == 0 || + qmat16[qscale][0][i] == 128 * 256) + qmat16[qscale][0][i] = 128 * 256 - 1; + qmat16[qscale][1][i] = + ROUNDED_DIV(bias << (16 - QUANT_BIAS_SHIFT), + qmat16[qscale][0][i]); + } + } + + for (i = intra; i < 64; i++) { + int64_t max = 8191; + if (dsp->fdct == ff_fdct_ifast) { + max = (8191LL * ff_aanscales[i]) >> 14; + } + while (((max * qmat[qscale][i]) >> shift) > INT_MAX) { + shift++; + } + } + } + if (shift) { + av_log(NULL, AV_LOG_INFO, + "Warning, QMAT_SHIFT is larger than %d, overflows possible\n", + QMAT_SHIFT - shift); + } +} + +static inline void update_qscale(MpegEncContext *s) +{ + s->qscale = (s->lambda * 139 + FF_LAMBDA_SCALE * 64) >> + (FF_LAMBDA_SHIFT + 7); + s->qscale = av_clip(s->qscale, s->avctx->qmin, s->avctx->qmax); + + s->lambda2 = (s->lambda * s->lambda + FF_LAMBDA_SCALE / 2) >> + FF_LAMBDA_SHIFT; +} + +void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix) +{ + int i; + + if (matrix) { + put_bits(pb, 1, 1); + for (i = 0; i < 64; i++) { + put_bits(pb, 8, matrix[ff_zigzag_direct[i]]); + } + } else + put_bits(pb, 1, 0); +} + +/** + * init s->current_picture.qscale_table from s->lambda_table + */ +void ff_init_qscale_tab(MpegEncContext *s) +{ + int8_t * const qscale_table = s->current_picture.qscale_table; + int i; + + for (i = 0; i < s->mb_num; i++) { + unsigned int lam = s->lambda_table[s->mb_index2xy[i]]; + int qp = (lam * 139 + FF_LAMBDA_SCALE * 64) >> (FF_LAMBDA_SHIFT + 7); + qscale_table[s->mb_index2xy[i]] = av_clip(qp, s->avctx->qmin, + s->avctx->qmax); + } +} + +static void copy_picture_attributes(MpegEncContext *s, AVFrame *dst, + const AVFrame *src) +{ + dst->pict_type = src->pict_type; + dst->quality = src->quality; + dst->coded_picture_number = src->coded_picture_number; + dst->display_picture_number = src->display_picture_number; + //dst->reference = src->reference; + dst->pts = src->pts; + dst->interlaced_frame = src->interlaced_frame; + dst->top_field_first = src->top_field_first; +} + +static void update_duplicate_context_after_me(MpegEncContext *dst, + MpegEncContext *src) +{ +#define COPY(a) dst->a= src->a + COPY(pict_type); + COPY(current_picture); + COPY(f_code); + COPY(b_code); + COPY(qscale); + COPY(lambda); + COPY(lambda2); + COPY(picture_in_gop_number); + COPY(gop_picture_number); + COPY(frame_pred_frame_dct); // FIXME don't set in encode_header + COPY(progressive_frame); // FIXME don't set in encode_header + COPY(partitioned_frame); // FIXME don't set in encode_header +#undef COPY +} + +/** + * Set the given MpegEncContext to defaults for encoding. + * the changed fields will not depend upon the prior state of the MpegEncContext. + */ +static void MPV_encode_defaults(MpegEncContext *s) +{ + int i; + ff_MPV_common_defaults(s); + + for (i = -16; i < 16; i++) { + default_fcode_tab[i + MAX_MV] = 1; + } + s->me.mv_penalty = default_mv_penalty; + s->fcode_tab = default_fcode_tab; +} + +av_cold int ff_dct_encode_init(MpegEncContext *s) { + if (ARCH_X86) + ff_dct_encode_init_x86(s); + + if (!s->dct_quantize) + s->dct_quantize = ff_dct_quantize_c; + if (!s->denoise_dct) + s->denoise_dct = denoise_dct_c; + s->fast_dct_quantize = s->dct_quantize; + if (s->avctx->trellis) + s->dct_quantize = dct_quantize_trellis_c; + + return 0; +} + +/* init video encoder */ +av_cold int ff_MPV_encode_init(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + int i; + int chroma_h_shift, chroma_v_shift; + + MPV_encode_defaults(s); + + switch (avctx->codec_id) { + case AV_CODEC_ID_MPEG2VIDEO: + if (avctx->pix_fmt != AV_PIX_FMT_YUV420P && + avctx->pix_fmt != AV_PIX_FMT_YUV422P) { + av_log(avctx, AV_LOG_ERROR, + "only YUV420 and YUV422 are supported\n"); + return -1; + } + break; + case AV_CODEC_ID_LJPEG: + if (avctx->pix_fmt != AV_PIX_FMT_YUVJ420P && + avctx->pix_fmt != AV_PIX_FMT_YUVJ422P && + avctx->pix_fmt != AV_PIX_FMT_YUVJ444P && + avctx->pix_fmt != AV_PIX_FMT_BGR0 && + avctx->pix_fmt != AV_PIX_FMT_BGRA && + avctx->pix_fmt != AV_PIX_FMT_BGR24 && + ((avctx->pix_fmt != AV_PIX_FMT_YUV420P && + avctx->pix_fmt != AV_PIX_FMT_YUV422P && + avctx->pix_fmt != AV_PIX_FMT_YUV444P) || + avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)) { + av_log(avctx, AV_LOG_ERROR, "colorspace not supported in LJPEG\n"); + return -1; + } + break; + case AV_CODEC_ID_MJPEG: + case AV_CODEC_ID_AMV: + if (avctx->pix_fmt != AV_PIX_FMT_YUVJ420P && + avctx->pix_fmt != AV_PIX_FMT_YUVJ422P && + avctx->pix_fmt != AV_PIX_FMT_YUVJ444P && + ((avctx->pix_fmt != AV_PIX_FMT_YUV420P && + avctx->pix_fmt != AV_PIX_FMT_YUV422P && + avctx->pix_fmt != AV_PIX_FMT_YUV444P) || + avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)) { + av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpeg\n"); + return -1; + } + break; + default: + if (avctx->pix_fmt != AV_PIX_FMT_YUV420P) { + av_log(avctx, AV_LOG_ERROR, "only YUV420 is supported\n"); + return -1; + } + } + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_YUVJ444P: + case AV_PIX_FMT_YUV444P: + s->chroma_format = CHROMA_444; + break; + case AV_PIX_FMT_YUVJ422P: + case AV_PIX_FMT_YUV422P: + s->chroma_format = CHROMA_422; + break; + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P: + default: + s->chroma_format = CHROMA_420; + break; + } + + s->bit_rate = avctx->bit_rate; + s->width = avctx->width; + s->height = avctx->height; + if (avctx->gop_size > 600 && + avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(avctx, AV_LOG_WARNING, + "keyframe interval too large!, reducing it from %d to %d\n", + avctx->gop_size, 600); + avctx->gop_size = 600; + } + s->gop_size = avctx->gop_size; + s->avctx = avctx; + s->flags = avctx->flags; + s->flags2 = avctx->flags2; + s->max_b_frames = avctx->max_b_frames; + s->codec_id = avctx->codec->id; + s->strict_std_compliance = avctx->strict_std_compliance; + s->quarter_sample = (avctx->flags & CODEC_FLAG_QPEL) != 0; + s->mpeg_quant = avctx->mpeg_quant; + s->rtp_mode = !!avctx->rtp_payload_size; + s->intra_dc_precision = avctx->intra_dc_precision; + s->user_specified_pts = AV_NOPTS_VALUE; + + if (s->gop_size <= 1) { + s->intra_only = 1; + s->gop_size = 12; + } else { + s->intra_only = 0; + } + + s->me_method = avctx->me_method; + + /* Fixed QSCALE */ + s->fixed_qscale = !!(avctx->flags & CODEC_FLAG_QSCALE); + + s->adaptive_quant = (s->avctx->lumi_masking || + s->avctx->dark_masking || + s->avctx->temporal_cplx_masking || + s->avctx->spatial_cplx_masking || + s->avctx->p_masking || + s->avctx->border_masking || + (s->mpv_flags & FF_MPV_FLAG_QP_RD)) && + !s->fixed_qscale; + + s->loop_filter = !!(s->flags & CODEC_FLAG_LOOP_FILTER); + + if (avctx->rc_max_rate && !avctx->rc_buffer_size) { + switch(avctx->codec_id) { + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + avctx->rc_buffer_size = FFMAX(avctx->rc_max_rate, 15000000) * 112L / 15000000 * 16384; + break; + case AV_CODEC_ID_MPEG4: + case AV_CODEC_ID_MSMPEG4V1: + case AV_CODEC_ID_MSMPEG4V2: + case AV_CODEC_ID_MSMPEG4V3: + if (avctx->rc_max_rate >= 15000000) { + avctx->rc_buffer_size = 320 + (avctx->rc_max_rate - 15000000L) * (760-320) / (38400000 - 15000000); + } else if(avctx->rc_max_rate >= 2000000) { + avctx->rc_buffer_size = 80 + (avctx->rc_max_rate - 2000000L) * (320- 80) / (15000000 - 2000000); + } else if(avctx->rc_max_rate >= 384000) { + avctx->rc_buffer_size = 40 + (avctx->rc_max_rate - 384000L) * ( 80- 40) / ( 2000000 - 384000); + } else + avctx->rc_buffer_size = 40; + avctx->rc_buffer_size *= 16384; + break; + } + if (avctx->rc_buffer_size) { + av_log(avctx, AV_LOG_INFO, "Automatically choosing VBV buffer size of %d kbyte\n", avctx->rc_buffer_size/8192); + } + } + + if ((!avctx->rc_max_rate) != (!avctx->rc_buffer_size)) { + av_log(avctx, AV_LOG_ERROR, "Either both buffer size and max rate or neither must be specified\n"); + if (avctx->rc_max_rate && !avctx->rc_buffer_size) + return -1; + } + + if (avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate) { + av_log(avctx, AV_LOG_INFO, + "Warning min_rate > 0 but min_rate != max_rate isn't recommended!\n"); + } + + if (avctx->rc_min_rate && avctx->rc_min_rate > avctx->bit_rate) { + av_log(avctx, AV_LOG_ERROR, "bitrate below min bitrate\n"); + return -1; + } + + if (avctx->rc_max_rate && avctx->rc_max_rate < avctx->bit_rate) { + av_log(avctx, AV_LOG_ERROR, "bitrate above max bitrate\n"); + return -1; + } + + if (avctx->rc_max_rate && + avctx->rc_max_rate == avctx->bit_rate && + avctx->rc_max_rate != avctx->rc_min_rate) { + av_log(avctx, AV_LOG_INFO, + "impossible bitrate constraints, this will fail\n"); + } + + if (avctx->rc_buffer_size && + avctx->bit_rate * (int64_t)avctx->time_base.num > + avctx->rc_buffer_size * (int64_t)avctx->time_base.den) { + av_log(avctx, AV_LOG_ERROR, "VBV buffer too small for bitrate\n"); + return -1; + } + + if (!s->fixed_qscale && + avctx->bit_rate * av_q2d(avctx->time_base) > + avctx->bit_rate_tolerance) { + av_log(avctx, AV_LOG_ERROR, + "bitrate tolerance too small for bitrate\n"); + return -1; + } + + if (s->avctx->rc_max_rate && + s->avctx->rc_min_rate == s->avctx->rc_max_rate && + (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || + s->codec_id == AV_CODEC_ID_MPEG2VIDEO) && + 90000LL * (avctx->rc_buffer_size - 1) > + s->avctx->rc_max_rate * 0xFFFFLL) { + av_log(avctx, AV_LOG_INFO, + "Warning vbv_delay will be set to 0xFFFF (=VBR) as the " + "specified vbv buffer is too large for the given bitrate!\n"); + } + + if ((s->flags & CODEC_FLAG_4MV) && s->codec_id != AV_CODEC_ID_MPEG4 && + s->codec_id != AV_CODEC_ID_H263 && s->codec_id != AV_CODEC_ID_H263P && + s->codec_id != AV_CODEC_ID_FLV1) { + av_log(avctx, AV_LOG_ERROR, "4MV not supported by codec\n"); + return -1; + } + + if (s->obmc && s->avctx->mb_decision != FF_MB_DECISION_SIMPLE) { + av_log(avctx, AV_LOG_ERROR, + "OBMC is only supported with simple mb decision\n"); + return -1; + } + + if (s->quarter_sample && s->codec_id != AV_CODEC_ID_MPEG4) { + av_log(avctx, AV_LOG_ERROR, "qpel not supported by codec\n"); + return -1; + } + + if (s->max_b_frames && + s->codec_id != AV_CODEC_ID_MPEG4 && + s->codec_id != AV_CODEC_ID_MPEG1VIDEO && + s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { + av_log(avctx, AV_LOG_ERROR, "b frames not supported by codec\n"); + return -1; + } + + if ((s->codec_id == AV_CODEC_ID_MPEG4 || + s->codec_id == AV_CODEC_ID_H263 || + s->codec_id == AV_CODEC_ID_H263P) && + (avctx->sample_aspect_ratio.num > 255 || + avctx->sample_aspect_ratio.den > 255)) { + av_log(avctx, AV_LOG_WARNING, + "Invalid pixel aspect ratio %i/%i, limit is 255/255 reducing\n", + avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); + av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den, + avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den, 255); + } + + if ((s->codec_id == AV_CODEC_ID_H263 || + s->codec_id == AV_CODEC_ID_H263P) && + (avctx->width > 2048 || + avctx->height > 1152 )) { + av_log(avctx, AV_LOG_ERROR, "H.263 does not support resolutions above 2048x1152\n"); + return -1; + } + if ((s->codec_id == AV_CODEC_ID_H263 || + s->codec_id == AV_CODEC_ID_H263P) && + ((avctx->width &3) || + (avctx->height&3) )) { + av_log(avctx, AV_LOG_ERROR, "w/h must be a multiple of 4\n"); + return -1; + } + + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO && + (avctx->width > 4095 || + avctx->height > 4095 )) { + av_log(avctx, AV_LOG_ERROR, "MPEG-1 does not support resolutions above 4095x4095\n"); + return -1; + } + + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && + (avctx->width > 16383 || + avctx->height > 16383 )) { + av_log(avctx, AV_LOG_ERROR, "MPEG-2 does not support resolutions above 16383x16383\n"); + return -1; + } + + if (s->codec_id == AV_CODEC_ID_RV10 && + (avctx->width &15 || + avctx->height&15 )) { + av_log(avctx, AV_LOG_ERROR, "width and height must be a multiple of 16\n"); + return AVERROR(EINVAL); + } + + if (s->codec_id == AV_CODEC_ID_RV20 && + (avctx->width &3 || + avctx->height&3 )) { + av_log(avctx, AV_LOG_ERROR, "width and height must be a multiple of 4\n"); + return AVERROR(EINVAL); + } + + if ((s->codec_id == AV_CODEC_ID_WMV1 || + s->codec_id == AV_CODEC_ID_WMV2) && + avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "width must be multiple of 2\n"); + return -1; + } + + if ((s->flags & (CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME)) && + s->codec_id != AV_CODEC_ID_MPEG4 && s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { + av_log(avctx, AV_LOG_ERROR, "interlacing not supported by codec\n"); + return -1; + } + + // FIXME mpeg2 uses that too + if (s->mpeg_quant && s->codec_id != AV_CODEC_ID_MPEG4) { + av_log(avctx, AV_LOG_ERROR, + "mpeg2 style quantization not supported by codec\n"); + return -1; + } + + if ((s->mpv_flags & FF_MPV_FLAG_CBP_RD) && !avctx->trellis) { + av_log(avctx, AV_LOG_ERROR, "CBP RD needs trellis quant\n"); + return -1; + } + + if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && + s->avctx->mb_decision != FF_MB_DECISION_RD) { + av_log(avctx, AV_LOG_ERROR, "QP RD needs mbd=2\n"); + return -1; + } + + if (s->avctx->scenechange_threshold < 1000000000 && + (s->flags & CODEC_FLAG_CLOSED_GOP)) { + av_log(avctx, AV_LOG_ERROR, + "closed gop with scene change detection are not supported yet, " + "set threshold to 1000000000\n"); + return -1; + } + + if (s->flags & CODEC_FLAG_LOW_DELAY) { + if (s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { + av_log(avctx, AV_LOG_ERROR, + "low delay forcing is only available for mpeg2\n"); + return -1; + } + if (s->max_b_frames != 0) { + av_log(avctx, AV_LOG_ERROR, + "b frames cannot be used with low delay\n"); + return -1; + } + } + + if (s->q_scale_type == 1) { + if (avctx->qmax > 12) { + av_log(avctx, AV_LOG_ERROR, + "non linear quant only supports qmax <= 12 currently\n"); + return -1; + } + } + + if (s->avctx->thread_count > 1 && + s->codec_id != AV_CODEC_ID_MPEG4 && + s->codec_id != AV_CODEC_ID_MPEG1VIDEO && + s->codec_id != AV_CODEC_ID_MPEG2VIDEO && + s->codec_id != AV_CODEC_ID_MJPEG && + (s->codec_id != AV_CODEC_ID_H263P)) { + av_log(avctx, AV_LOG_ERROR, + "multi threaded encoding not supported by codec\n"); + return -1; + } + + if (s->avctx->thread_count < 1) { + av_log(avctx, AV_LOG_ERROR, + "automatic thread number detection not supported by codec, " + "patch welcome\n"); + return -1; + } + + if (s->avctx->slices > 1 || s->avctx->thread_count > 1) + s->rtp_mode = 1; + + if (s->avctx->thread_count > 1 && s->codec_id == AV_CODEC_ID_H263P) + s->h263_slice_structured = 1; + + if (!avctx->time_base.den || !avctx->time_base.num) { + av_log(avctx, AV_LOG_ERROR, "framerate not set\n"); + return -1; + } + + i = (INT_MAX / 2 + 128) >> 8; + if (avctx->mb_threshold >= i) { + av_log(avctx, AV_LOG_ERROR, "mb_threshold too large, max is %d\n", + i - 1); + return -1; + } + + if (avctx->b_frame_strategy && (avctx->flags & CODEC_FLAG_PASS2)) { + av_log(avctx, AV_LOG_INFO, + "notice: b_frame_strategy only affects the first pass\n"); + avctx->b_frame_strategy = 0; + } + + i = av_gcd(avctx->time_base.den, avctx->time_base.num); + if (i > 1) { + av_log(avctx, AV_LOG_INFO, "removing common factors from framerate\n"); + avctx->time_base.den /= i; + avctx->time_base.num /= i; + //return -1; + } + + if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || s->codec_id == AV_CODEC_ID_MJPEG || s->codec_id==AV_CODEC_ID_AMV) { + // (a + x * 3 / 8) / x + s->intra_quant_bias = 3 << (QUANT_BIAS_SHIFT - 3); + s->inter_quant_bias = 0; + } else { + s->intra_quant_bias = 0; + // (a - x / 4) / x + s->inter_quant_bias = -(1 << (QUANT_BIAS_SHIFT - 2)); + } + + if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS) + s->intra_quant_bias = avctx->intra_quant_bias; + if (avctx->inter_quant_bias != FF_DEFAULT_QUANT_BIAS) + s->inter_quant_bias = avctx->inter_quant_bias; + + av_log(avctx, AV_LOG_DEBUG, "intra_quant_bias = %d inter_quant_bias = %d\n",s->intra_quant_bias,s->inter_quant_bias); + + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, &chroma_v_shift); + + if (avctx->codec_id == AV_CODEC_ID_MPEG4 && + s->avctx->time_base.den > (1 << 16) - 1) { + av_log(avctx, AV_LOG_ERROR, + "timebase %d/%d not supported by MPEG 4 standard, " + "the maximum admitted value for the timebase denominator " + "is %d\n", s->avctx->time_base.num, s->avctx->time_base.den, + (1 << 16) - 1); + return -1; + } + s->time_increment_bits = av_log2(s->avctx->time_base.den - 1) + 1; + + switch (avctx->codec->id) { + case AV_CODEC_ID_MPEG1VIDEO: + s->out_format = FMT_MPEG1; + s->low_delay = !!(s->flags & CODEC_FLAG_LOW_DELAY); + avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); + break; + case AV_CODEC_ID_MPEG2VIDEO: + s->out_format = FMT_MPEG1; + s->low_delay = !!(s->flags & CODEC_FLAG_LOW_DELAY); + avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); + s->rtp_mode = 1; + break; + case AV_CODEC_ID_LJPEG: + case AV_CODEC_ID_MJPEG: + case AV_CODEC_ID_AMV: + s->out_format = FMT_MJPEG; + s->intra_only = 1; /* force intra only for jpeg */ + if (avctx->codec->id == AV_CODEC_ID_LJPEG && + (avctx->pix_fmt == AV_PIX_FMT_BGR0 + || s->avctx->pix_fmt == AV_PIX_FMT_BGRA + || s->avctx->pix_fmt == AV_PIX_FMT_BGR24)) { + s->mjpeg_vsample[0] = s->mjpeg_hsample[0] = + s->mjpeg_vsample[1] = s->mjpeg_hsample[1] = + s->mjpeg_vsample[2] = s->mjpeg_hsample[2] = 1; + } else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P || avctx->pix_fmt == AV_PIX_FMT_YUVJ444P) { + s->mjpeg_vsample[0] = s->mjpeg_vsample[1] = s->mjpeg_vsample[2] = 2; + s->mjpeg_hsample[0] = s->mjpeg_hsample[1] = s->mjpeg_hsample[2] = 1; + } else { + s->mjpeg_vsample[0] = 2; + s->mjpeg_vsample[1] = 2 >> chroma_v_shift; + s->mjpeg_vsample[2] = 2 >> chroma_v_shift; + s->mjpeg_hsample[0] = 2; + s->mjpeg_hsample[1] = 2 >> chroma_h_shift; + s->mjpeg_hsample[2] = 2 >> chroma_h_shift; + } + if (!(CONFIG_MJPEG_ENCODER || CONFIG_LJPEG_ENCODER) || + ff_mjpeg_encode_init(s) < 0) + return -1; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_H261: + if (!CONFIG_H261_ENCODER) + return -1; + if (ff_h261_get_picture_format(s->width, s->height) < 0) { + av_log(avctx, AV_LOG_ERROR, + "The specified picture size of %dx%d is not valid for the " + "H.261 codec.\nValid sizes are 176x144, 352x288\n", + s->width, s->height); + return -1; + } + s->out_format = FMT_H261; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_H263: + if (!CONFIG_H263_ENCODER) + return -1; + if (ff_match_2uint16(ff_h263_format, FF_ARRAY_ELEMS(ff_h263_format), + s->width, s->height) == 8) { + av_log(avctx, AV_LOG_ERROR, + "The specified picture size of %dx%d is not valid for " + "the H.263 codec.\nValid sizes are 128x96, 176x144, " + "352x288, 704x576, and 1408x1152. " + "Try H.263+.\n", s->width, s->height); + return -1; + } + s->out_format = FMT_H263; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_H263P: + s->out_format = FMT_H263; + s->h263_plus = 1; + /* Fx */ + s->h263_aic = (avctx->flags & CODEC_FLAG_AC_PRED) ? 1 : 0; + s->modified_quant = s->h263_aic; + s->loop_filter = (avctx->flags & CODEC_FLAG_LOOP_FILTER) ? 1 : 0; + s->unrestricted_mv = s->obmc || s->loop_filter || s->umvplus; + + /* /Fx */ + /* These are just to be sure */ + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_FLV1: + s->out_format = FMT_H263; + s->h263_flv = 2; /* format = 1; 11-bit codes */ + s->unrestricted_mv = 1; + s->rtp_mode = 0; /* don't allow GOB */ + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_RV10: + s->out_format = FMT_H263; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_RV20: + s->out_format = FMT_H263; + avctx->delay = 0; + s->low_delay = 1; + s->modified_quant = 1; + s->h263_aic = 1; + s->h263_plus = 1; + s->loop_filter = 1; + s->unrestricted_mv = 0; + break; + case AV_CODEC_ID_MPEG4: + s->out_format = FMT_H263; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->low_delay = s->max_b_frames ? 0 : 1; + avctx->delay = s->low_delay ? 0 : (s->max_b_frames + 1); + break; + case AV_CODEC_ID_MSMPEG4V2: + s->out_format = FMT_H263; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->msmpeg4_version = 2; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_MSMPEG4V3: + s->out_format = FMT_H263; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->msmpeg4_version = 3; + s->flipflop_rounding = 1; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_WMV1: + s->out_format = FMT_H263; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->msmpeg4_version = 4; + s->flipflop_rounding = 1; + avctx->delay = 0; + s->low_delay = 1; + break; + case AV_CODEC_ID_WMV2: + s->out_format = FMT_H263; + s->h263_pred = 1; + s->unrestricted_mv = 1; + s->msmpeg4_version = 5; + s->flipflop_rounding = 1; + avctx->delay = 0; + s->low_delay = 1; + break; + default: + return -1; + } + + avctx->has_b_frames = !s->low_delay; + + s->encoding = 1; + + s->progressive_frame = + s->progressive_sequence = !(avctx->flags & (CODEC_FLAG_INTERLACED_DCT | + CODEC_FLAG_INTERLACED_ME) || + s->alternate_scan); + + /* init */ + if (ff_MPV_common_init(s) < 0) + return -1; + + ff_dct_encode_init(s); + + if ((CONFIG_H263P_ENCODER || CONFIG_RV20_ENCODER) && s->modified_quant) + s->chroma_qscale_table = ff_h263_chroma_qscale_table; + + s->quant_precision = 5; + + ff_set_cmp(&s->dsp, s->dsp.ildct_cmp, s->avctx->ildct_cmp); + ff_set_cmp(&s->dsp, s->dsp.frame_skip_cmp, s->avctx->frame_skip_cmp); + + if (CONFIG_H261_ENCODER && s->out_format == FMT_H261) + ff_h261_encode_init(s); + if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) + ff_h263_encode_init(s); + if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) + ff_msmpeg4_encode_init(s); + if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) + && s->out_format == FMT_MPEG1) + ff_mpeg1_encode_init(s); + + /* init q matrix */ + for (i = 0; i < 64; i++) { + int j = s->dsp.idct_permutation[i]; + if (CONFIG_MPEG4_ENCODER && s->codec_id == AV_CODEC_ID_MPEG4 && + s->mpeg_quant) { + s->intra_matrix[j] = ff_mpeg4_default_intra_matrix[i]; + s->inter_matrix[j] = ff_mpeg4_default_non_intra_matrix[i]; + } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { + s->intra_matrix[j] = + s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; + } else { + /* mpeg1/2 */ + s->intra_matrix[j] = ff_mpeg1_default_intra_matrix[i]; + s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i]; + } + if (s->avctx->intra_matrix) + s->intra_matrix[j] = s->avctx->intra_matrix[i]; + if (s->avctx->inter_matrix) + s->inter_matrix[j] = s->avctx->inter_matrix[i]; + } + + /* precompute matrix */ + /* for mjpeg, we do include qscale in the matrix */ + if (s->out_format != FMT_MJPEG) { + ff_convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + s->intra_matrix, s->intra_quant_bias, avctx->qmin, + 31, 1); + ff_convert_matrix(&s->dsp, s->q_inter_matrix, s->q_inter_matrix16, + s->inter_matrix, s->inter_quant_bias, avctx->qmin, + 31, 0); + } + + if (ff_rate_control_init(s) < 0) + return -1; + + return 0; +} + +av_cold int ff_MPV_encode_end(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + + ff_rate_control_uninit(s); + + ff_MPV_common_end(s); + if ((CONFIG_MJPEG_ENCODER || CONFIG_LJPEG_ENCODER) && + s->out_format == FMT_MJPEG) + ff_mjpeg_encode_close(s); + + av_freep(&avctx->extradata); + + return 0; +} + +static int get_sae(uint8_t *src, int ref, int stride) +{ + int x,y; + int acc = 0; + + for (y = 0; y < 16; y++) { + for (x = 0; x < 16; x++) { + acc += FFABS(src[x + y * stride] - ref); + } + } + + return acc; +} + +static int get_intra_count(MpegEncContext *s, uint8_t *src, + uint8_t *ref, int stride) +{ + int x, y, w, h; + int acc = 0; + + w = s->width & ~15; + h = s->height & ~15; + + for (y = 0; y < h; y += 16) { + for (x = 0; x < w; x += 16) { + int offset = x + y * stride; + int sad = s->dsp.sad[0](NULL, src + offset, ref + offset, stride, + 16); + int mean = (s->dsp.pix_sum(src + offset, stride) + 128) >> 8; + int sae = get_sae(src + offset, mean, stride); + + acc += sae + 500 < sad; + } + } + return acc; +} + + +static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg) +{ + Picture *pic = NULL; + int64_t pts; + int i, display_picture_number = 0, ret; + const int encoding_delay = s->max_b_frames ? s->max_b_frames : + (s->low_delay ? 0 : 1); + int direct = 1; + + if (pic_arg) { + pts = pic_arg->pts; + display_picture_number = s->input_picture_number++; + + if (pts != AV_NOPTS_VALUE) { + if (s->user_specified_pts != AV_NOPTS_VALUE) { + int64_t time = pts; + int64_t last = s->user_specified_pts; + + if (time <= last) { + av_log(s->avctx, AV_LOG_ERROR, + "Error, Invalid timestamp=%"PRId64", " + "last=%"PRId64"\n", pts, s->user_specified_pts); + return -1; + } + + if (!s->low_delay && display_picture_number == 1) + s->dts_delta = time - last; + } + s->user_specified_pts = pts; + } else { + if (s->user_specified_pts != AV_NOPTS_VALUE) { + s->user_specified_pts = + pts = s->user_specified_pts + 1; + av_log(s->avctx, AV_LOG_INFO, + "Warning: AVFrame.pts=? trying to guess (%"PRId64")\n", + pts); + } else { + pts = display_picture_number; + } + } + } + + if (pic_arg) { + if (!pic_arg->buf[0]) + direct = 0; + if (pic_arg->linesize[0] != s->linesize) + direct = 0; + if (pic_arg->linesize[1] != s->uvlinesize) + direct = 0; + if (pic_arg->linesize[2] != s->uvlinesize) + direct = 0; + + av_dlog(s->avctx, "%d %d %d %d\n", pic_arg->linesize[0], + pic_arg->linesize[1], s->linesize, s->uvlinesize); + + if (direct) { + i = ff_find_unused_picture(s, 1); + if (i < 0) + return i; + + pic = &s->picture[i]; + pic->reference = 3; + + if ((ret = av_frame_ref(&pic->f, pic_arg)) < 0) + return ret; + if (ff_alloc_picture(s, pic, 1) < 0) { + return -1; + } + } else { + i = ff_find_unused_picture(s, 0); + if (i < 0) + return i; + + pic = &s->picture[i]; + pic->reference = 3; + + if (ff_alloc_picture(s, pic, 0) < 0) { + return -1; + } + + if (pic->f.data[0] + INPLACE_OFFSET == pic_arg->data[0] && + pic->f.data[1] + INPLACE_OFFSET == pic_arg->data[1] && + pic->f.data[2] + INPLACE_OFFSET == pic_arg->data[2]) { + // empty + } else { + int h_chroma_shift, v_chroma_shift; + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &h_chroma_shift, + &v_chroma_shift); + + for (i = 0; i < 3; i++) { + int src_stride = pic_arg->linesize[i]; + int dst_stride = i ? s->uvlinesize : s->linesize; + int h_shift = i ? h_chroma_shift : 0; + int v_shift = i ? v_chroma_shift : 0; + int w = s->width >> h_shift; + int h = s->height >> v_shift; + uint8_t *src = pic_arg->data[i]; + uint8_t *dst = pic->f.data[i]; + + if (s->codec_id == AV_CODEC_ID_AMV && !(s->avctx->flags & CODEC_FLAG_EMU_EDGE)) { + h = ((s->height + 15)/16*16) >> v_shift; + } + + if (!s->avctx->rc_buffer_size) + dst += INPLACE_OFFSET; + + if (src_stride == dst_stride) + memcpy(dst, src, src_stride * h); + else { + int h2 = h; + uint8_t *dst2 = dst; + while (h2--) { + memcpy(dst2, src, w); + dst2 += dst_stride; + src += src_stride; + } + } + if ((s->width & 15) || (s->height & 15)) { + s->dsp.draw_edges(dst, dst_stride, + w, h, + 16>>h_shift, + 16>>v_shift, + EDGE_BOTTOM); + } + } + } + } + copy_picture_attributes(s, &pic->f, pic_arg); + pic->f.display_picture_number = display_picture_number; + pic->f.pts = pts; // we set this here to avoid modifiying pic_arg + } + + /* shift buffer entries */ + for (i = 1; i < MAX_PICTURE_COUNT /*s->encoding_delay + 1*/; i++) + s->input_picture[i - 1] = s->input_picture[i]; + + s->input_picture[encoding_delay] = (Picture*) pic; + + return 0; +} + +static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) +{ + int x, y, plane; + int score = 0; + int64_t score64 = 0; + + for (plane = 0; plane < 3; plane++) { + const int stride = p->f.linesize[plane]; + const int bw = plane ? 1 : 2; + for (y = 0; y < s->mb_height * bw; y++) { + for (x = 0; x < s->mb_width * bw; x++) { + int off = p->shared ? 0 : 16; + uint8_t *dptr = p->f.data[plane] + 8 * (x + y * stride) + off; + uint8_t *rptr = ref->f.data[plane] + 8 * (x + y * stride); + int v = s->dsp.frame_skip_cmp[1](s, dptr, rptr, stride, 8); + + switch (s->avctx->frame_skip_exp) { + case 0: score = FFMAX(score, v); break; + case 1: score += FFABS(v); break; + case 2: score += v * v; break; + case 3: score64 += FFABS(v * v * (int64_t)v); break; + case 4: score64 += v * v * (int64_t)(v * v); break; + } + } + } + } + + if (score) + score64 = score; + + if (score64 < s->avctx->frame_skip_threshold) + return 1; + if (score64 < ((s->avctx->frame_skip_factor * (int64_t)s->lambda) >> 8)) + return 1; + return 0; +} + +static int encode_frame(AVCodecContext *c, AVFrame *frame) +{ + AVPacket pkt = { 0 }; + int ret, got_output; + + av_init_packet(&pkt); + ret = avcodec_encode_video2(c, &pkt, frame, &got_output); + if (ret < 0) + return ret; + + ret = pkt.size; + av_free_packet(&pkt); + return ret; +} + +static int estimate_best_b_count(MpegEncContext *s) +{ + AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); + AVCodecContext *c = avcodec_alloc_context3(NULL); + AVFrame input[FF_MAX_B_FRAMES + 2]; + const int scale = s->avctx->brd_scale; + int i, j, out_size, p_lambda, b_lambda, lambda2; + int64_t best_rd = INT64_MAX; + int best_b_count = -1; + + av_assert0(scale >= 0 && scale <= 3); + + //emms_c(); + //s->next_picture_ptr->quality; + p_lambda = s->last_lambda_for[AV_PICTURE_TYPE_P]; + //p_lambda * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset; + b_lambda = s->last_lambda_for[AV_PICTURE_TYPE_B]; + if (!b_lambda) // FIXME we should do this somewhere else + b_lambda = p_lambda; + lambda2 = (b_lambda * b_lambda + (1 << FF_LAMBDA_SHIFT) / 2) >> + FF_LAMBDA_SHIFT; + + c->width = s->width >> scale; + c->height = s->height >> scale; + c->flags = CODEC_FLAG_QSCALE | CODEC_FLAG_PSNR | + CODEC_FLAG_INPUT_PRESERVED /*| CODEC_FLAG_EMU_EDGE*/; + c->flags |= s->avctx->flags & CODEC_FLAG_QPEL; + c->mb_decision = s->avctx->mb_decision; + c->me_cmp = s->avctx->me_cmp; + c->mb_cmp = s->avctx->mb_cmp; + c->me_sub_cmp = s->avctx->me_sub_cmp; + c->pix_fmt = AV_PIX_FMT_YUV420P; + c->time_base = s->avctx->time_base; + c->max_b_frames = s->max_b_frames; + + if (avcodec_open2(c, codec, NULL) < 0) + return -1; + + for (i = 0; i < s->max_b_frames + 2; i++) { + int ysize = c->width * c->height; + int csize = (c->width / 2) * (c->height / 2); + Picture pre_input, *pre_input_ptr = i ? s->input_picture[i - 1] : + s->next_picture_ptr; + + avcodec_get_frame_defaults(&input[i]); + input[i].data[0] = av_malloc(ysize + 2 * csize); + input[i].data[1] = input[i].data[0] + ysize; + input[i].data[2] = input[i].data[1] + csize; + input[i].linesize[0] = c->width; + input[i].linesize[1] = + input[i].linesize[2] = c->width / 2; + + if (pre_input_ptr && (!i || s->input_picture[i - 1])) { + pre_input = *pre_input_ptr; + + if (!pre_input.shared && i) { + pre_input.f.data[0] += INPLACE_OFFSET; + pre_input.f.data[1] += INPLACE_OFFSET; + pre_input.f.data[2] += INPLACE_OFFSET; + } + + s->dsp.shrink[scale](input[i].data[0], input[i].linesize[0], + pre_input.f.data[0], pre_input.f.linesize[0], + c->width, c->height); + s->dsp.shrink[scale](input[i].data[1], input[i].linesize[1], + pre_input.f.data[1], pre_input.f.linesize[1], + c->width >> 1, c->height >> 1); + s->dsp.shrink[scale](input[i].data[2], input[i].linesize[2], + pre_input.f.data[2], pre_input.f.linesize[2], + c->width >> 1, c->height >> 1); + } + } + + for (j = 0; j < s->max_b_frames + 1; j++) { + int64_t rd = 0; + + if (!s->input_picture[j]) + break; + + c->error[0] = c->error[1] = c->error[2] = 0; + + input[0].pict_type = AV_PICTURE_TYPE_I; + input[0].quality = 1 * FF_QP2LAMBDA; + + out_size = encode_frame(c, &input[0]); + + //rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT; + + for (i = 0; i < s->max_b_frames + 1; i++) { + int is_p = i % (j + 1) == j || i == s->max_b_frames; + + input[i + 1].pict_type = is_p ? + AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; + input[i + 1].quality = is_p ? p_lambda : b_lambda; + + out_size = encode_frame(c, &input[i + 1]); + + rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); + } + + /* get the delayed frames */ + while (out_size) { + out_size = encode_frame(c, NULL); + rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); + } + + rd += c->error[0] + c->error[1] + c->error[2]; + + if (rd < best_rd) { + best_rd = rd; + best_b_count = j; + } + } + + avcodec_close(c); + av_freep(&c); + + for (i = 0; i < s->max_b_frames + 2; i++) { + av_freep(&input[i].data[0]); + } + + return best_b_count; +} + +static int select_input_picture(MpegEncContext *s) +{ + int i, ret; + + for (i = 1; i < MAX_PICTURE_COUNT; i++) + s->reordered_input_picture[i - 1] = s->reordered_input_picture[i]; + s->reordered_input_picture[MAX_PICTURE_COUNT - 1] = NULL; + + /* set next picture type & ordering */ + if (s->reordered_input_picture[0] == NULL && s->input_picture[0]) { + if (/*s->picture_in_gop_number >= s->gop_size ||*/ + s->next_picture_ptr == NULL || s->intra_only) { + s->reordered_input_picture[0] = s->input_picture[0]; + s->reordered_input_picture[0]->f.pict_type = AV_PICTURE_TYPE_I; + s->reordered_input_picture[0]->f.coded_picture_number = + s->coded_picture_number++; + } else { + int b_frames; + + if (s->avctx->frame_skip_threshold || s->avctx->frame_skip_factor) { + if (s->picture_in_gop_number < s->gop_size && + skip_check(s, s->input_picture[0], s->next_picture_ptr)) { + // FIXME check that te gop check above is +-1 correct + av_frame_unref(&s->input_picture[0]->f); + + emms_c(); + ff_vbv_update(s, 0); + + goto no_output_pic; + } + } + + if (s->flags & CODEC_FLAG_PASS2) { + for (i = 0; i < s->max_b_frames + 1; i++) { + int pict_num = s->input_picture[0]->f.display_picture_number + i; + + if (pict_num >= s->rc_context.num_entries) + break; + if (!s->input_picture[i]) { + s->rc_context.entry[pict_num - 1].new_pict_type = AV_PICTURE_TYPE_P; + break; + } + + s->input_picture[i]->f.pict_type = + s->rc_context.entry[pict_num].new_pict_type; + } + } + + if (s->avctx->b_frame_strategy == 0) { + b_frames = s->max_b_frames; + while (b_frames && !s->input_picture[b_frames]) + b_frames--; + } else if (s->avctx->b_frame_strategy == 1) { + for (i = 1; i < s->max_b_frames + 1; i++) { + if (s->input_picture[i] && + s->input_picture[i]->b_frame_score == 0) { + s->input_picture[i]->b_frame_score = + get_intra_count(s, + s->input_picture[i ]->f.data[0], + s->input_picture[i - 1]->f.data[0], + s->linesize) + 1; + } + } + for (i = 0; i < s->max_b_frames + 1; i++) { + if (s->input_picture[i] == NULL || + s->input_picture[i]->b_frame_score - 1 > + s->mb_num / s->avctx->b_sensitivity) + break; + } + + b_frames = FFMAX(0, i - 1); + + /* reset scores */ + for (i = 0; i < b_frames + 1; i++) { + s->input_picture[i]->b_frame_score = 0; + } + } else if (s->avctx->b_frame_strategy == 2) { + b_frames = estimate_best_b_count(s); + } else { + av_log(s->avctx, AV_LOG_ERROR, "illegal b frame strategy\n"); + b_frames = 0; + } + + emms_c(); + + for (i = b_frames - 1; i >= 0; i--) { + int type = s->input_picture[i]->f.pict_type; + if (type && type != AV_PICTURE_TYPE_B) + b_frames = i; + } + if (s->input_picture[b_frames]->f.pict_type == AV_PICTURE_TYPE_B && + b_frames == s->max_b_frames) { + av_log(s->avctx, AV_LOG_ERROR, + "warning, too many b frames in a row\n"); + } + + if (s->picture_in_gop_number + b_frames >= s->gop_size) { + if ((s->mpv_flags & FF_MPV_FLAG_STRICT_GOP) && + s->gop_size > s->picture_in_gop_number) { + b_frames = s->gop_size - s->picture_in_gop_number - 1; + } else { + if (s->flags & CODEC_FLAG_CLOSED_GOP) + b_frames = 0; + s->input_picture[b_frames]->f.pict_type = AV_PICTURE_TYPE_I; + } + } + + if ((s->flags & CODEC_FLAG_CLOSED_GOP) && b_frames && + s->input_picture[b_frames]->f.pict_type == AV_PICTURE_TYPE_I) + b_frames--; + + s->reordered_input_picture[0] = s->input_picture[b_frames]; + if (s->reordered_input_picture[0]->f.pict_type != AV_PICTURE_TYPE_I) + s->reordered_input_picture[0]->f.pict_type = AV_PICTURE_TYPE_P; + s->reordered_input_picture[0]->f.coded_picture_number = + s->coded_picture_number++; + for (i = 0; i < b_frames; i++) { + s->reordered_input_picture[i + 1] = s->input_picture[i]; + s->reordered_input_picture[i + 1]->f.pict_type = + AV_PICTURE_TYPE_B; + s->reordered_input_picture[i + 1]->f.coded_picture_number = + s->coded_picture_number++; + } + } + } +no_output_pic: + if (s->reordered_input_picture[0]) { + s->reordered_input_picture[0]->reference = + s->reordered_input_picture[0]->f.pict_type != + AV_PICTURE_TYPE_B ? 3 : 0; + + ff_mpeg_unref_picture(s, &s->new_picture); + if ((ret = ff_mpeg_ref_picture(s, &s->new_picture, s->reordered_input_picture[0]))) + return ret; + + if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) { + // input is a shared pix, so we can't modifiy it -> alloc a new + // one & ensure that the shared one is reuseable + + Picture *pic; + int i = ff_find_unused_picture(s, 0); + if (i < 0) + return i; + pic = &s->picture[i]; + + pic->reference = s->reordered_input_picture[0]->reference; + if (ff_alloc_picture(s, pic, 0) < 0) { + return -1; + } + + copy_picture_attributes(s, &pic->f, + &s->reordered_input_picture[0]->f); + + /* mark us unused / free shared pic */ + av_frame_unref(&s->reordered_input_picture[0]->f); + s->reordered_input_picture[0]->shared = 0; + + s->current_picture_ptr = pic; + } else { + // input is not a shared pix -> reuse buffer for current_pix + s->current_picture_ptr = s->reordered_input_picture[0]; + for (i = 0; i < 4; i++) { + s->new_picture.f.data[i] += INPLACE_OFFSET; + } + } + ff_mpeg_unref_picture(s, &s->current_picture); + if ((ret = ff_mpeg_ref_picture(s, &s->current_picture, + s->current_picture_ptr)) < 0) + return ret; + + s->picture_number = s->new_picture.f.display_picture_number; + } else { + ff_mpeg_unref_picture(s, &s->new_picture); + } + return 0; +} + +int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt, + AVFrame *pic_arg, int *got_packet) +{ + MpegEncContext *s = avctx->priv_data; + int i, stuffing_count, ret; + int context_count = s->slice_context_count; + + s->picture_in_gop_number++; + + if (load_input_picture(s, pic_arg) < 0) + return -1; + + if (select_input_picture(s) < 0) { + return -1; + } + + /* output? */ + if (s->new_picture.f.data[0]) { + if ((ret = ff_alloc_packet2(avctx, pkt, s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000)) < 0) + return ret; + if (s->mb_info) { + s->mb_info_ptr = av_packet_new_side_data(pkt, + AV_PKT_DATA_H263_MB_INFO, + s->mb_width*s->mb_height*12); + s->prev_mb_info = s->last_mb_info = s->mb_info_size = 0; + } + + for (i = 0; i < context_count; i++) { + int start_y = s->thread_context[i]->start_mb_y; + int end_y = s->thread_context[i]-> end_mb_y; + int h = s->mb_height; + uint8_t *start = pkt->data + (size_t)(((int64_t) pkt->size) * start_y / h); + uint8_t *end = pkt->data + (size_t)(((int64_t) pkt->size) * end_y / h); + + init_put_bits(&s->thread_context[i]->pb, start, end - start); + } + + s->pict_type = s->new_picture.f.pict_type; + //emms_c(); + if (ff_MPV_frame_start(s, avctx) < 0) + return -1; +vbv_retry: + if (encode_picture(s, s->picture_number) < 0) + return -1; + + avctx->header_bits = s->header_bits; + avctx->mv_bits = s->mv_bits; + avctx->misc_bits = s->misc_bits; + avctx->i_tex_bits = s->i_tex_bits; + avctx->p_tex_bits = s->p_tex_bits; + avctx->i_count = s->i_count; + // FIXME f/b_count in avctx + avctx->p_count = s->mb_num - s->i_count - s->skip_count; + avctx->skip_count = s->skip_count; + + ff_MPV_frame_end(s); + + if (CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG) + ff_mjpeg_encode_picture_trailer(s); + + if (avctx->rc_buffer_size) { + RateControlContext *rcc = &s->rc_context; + int max_size = rcc->buffer_index * avctx->rc_max_available_vbv_use; + + if (put_bits_count(&s->pb) > max_size && + s->lambda < s->avctx->lmax) { + s->next_lambda = FFMAX(s->lambda + 1, s->lambda * + (s->qscale + 1) / s->qscale); + if (s->adaptive_quant) { + int i; + for (i = 0; i < s->mb_height * s->mb_stride; i++) + s->lambda_table[i] = + FFMAX(s->lambda_table[i] + 1, + s->lambda_table[i] * (s->qscale + 1) / + s->qscale); + } + s->mb_skipped = 0; // done in MPV_frame_start() + // done in encode_picture() so we must undo it + if (s->pict_type == AV_PICTURE_TYPE_P) { + if (s->flipflop_rounding || + s->codec_id == AV_CODEC_ID_H263P || + s->codec_id == AV_CODEC_ID_MPEG4) + s->no_rounding ^= 1; + } + if (s->pict_type != AV_PICTURE_TYPE_B) { + s->time_base = s->last_time_base; + s->last_non_b_time = s->time - s->pp_time; + } + for (i = 0; i < context_count; i++) { + PutBitContext *pb = &s->thread_context[i]->pb; + init_put_bits(pb, pb->buf, pb->buf_end - pb->buf); + } + goto vbv_retry; + } + + assert(s->avctx->rc_max_rate); + } + + if (s->flags & CODEC_FLAG_PASS1) + ff_write_pass1_stats(s); + + for (i = 0; i < 4; i++) { + s->current_picture_ptr->f.error[i] = s->current_picture.f.error[i]; + avctx->error[i] += s->current_picture_ptr->f.error[i]; + } + + if (s->flags & CODEC_FLAG_PASS1) + assert(avctx->header_bits + avctx->mv_bits + avctx->misc_bits + + avctx->i_tex_bits + avctx->p_tex_bits == + put_bits_count(&s->pb)); + flush_put_bits(&s->pb); + s->frame_bits = put_bits_count(&s->pb); + + stuffing_count = ff_vbv_update(s, s->frame_bits); + s->stuffing_bits = 8*stuffing_count; + if (stuffing_count) { + if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < + stuffing_count + 50) { + av_log(s->avctx, AV_LOG_ERROR, "stuffing too large\n"); + return -1; + } + + switch (s->codec_id) { + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + while (stuffing_count--) { + put_bits(&s->pb, 8, 0); + } + break; + case AV_CODEC_ID_MPEG4: + put_bits(&s->pb, 16, 0); + put_bits(&s->pb, 16, 0x1C3); + stuffing_count -= 4; + while (stuffing_count--) { + put_bits(&s->pb, 8, 0xFF); + } + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); + } + flush_put_bits(&s->pb); + s->frame_bits = put_bits_count(&s->pb); + } + + /* update mpeg1/2 vbv_delay for CBR */ + if (s->avctx->rc_max_rate && + s->avctx->rc_min_rate == s->avctx->rc_max_rate && + s->out_format == FMT_MPEG1 && + 90000LL * (avctx->rc_buffer_size - 1) <= + s->avctx->rc_max_rate * 0xFFFFLL) { + int vbv_delay, min_delay; + double inbits = s->avctx->rc_max_rate * + av_q2d(s->avctx->time_base); + int minbits = s->frame_bits - 8 * + (s->vbv_delay_ptr - s->pb.buf - 1); + double bits = s->rc_context.buffer_index + minbits - inbits; + + if (bits < 0) + av_log(s->avctx, AV_LOG_ERROR, + "Internal error, negative bits\n"); + + assert(s->repeat_first_field == 0); + + vbv_delay = bits * 90000 / s->avctx->rc_max_rate; + min_delay = (minbits * 90000LL + s->avctx->rc_max_rate - 1) / + s->avctx->rc_max_rate; + + vbv_delay = FFMAX(vbv_delay, min_delay); + + av_assert0(vbv_delay < 0xFFFF); + + s->vbv_delay_ptr[0] &= 0xF8; + s->vbv_delay_ptr[0] |= vbv_delay >> 13; + s->vbv_delay_ptr[1] = vbv_delay >> 5; + s->vbv_delay_ptr[2] &= 0x07; + s->vbv_delay_ptr[2] |= vbv_delay << 3; + avctx->vbv_delay = vbv_delay * 300; + } + s->total_bits += s->frame_bits; + avctx->frame_bits = s->frame_bits; + + pkt->pts = s->current_picture.f.pts; + if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) { + if (!s->current_picture.f.coded_picture_number) + pkt->dts = pkt->pts - s->dts_delta; + else + pkt->dts = s->reordered_pts; + s->reordered_pts = pkt->pts; + } else + pkt->dts = pkt->pts; + if (s->current_picture.f.key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + if (s->mb_info) + av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size); + } else { + s->frame_bits = 0; + } + assert((s->frame_bits & 7) == 0); + + pkt->size = s->frame_bits / 8; + *got_packet = !!pkt->size; + return 0; +} + +static inline void dct_single_coeff_elimination(MpegEncContext *s, + int n, int threshold) +{ + static const char tab[64] = { + 3, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + int score = 0; + int run = 0; + int i; + int16_t *block = s->block[n]; + const int last_index = s->block_last_index[n]; + int skip_dc; + + if (threshold < 0) { + skip_dc = 0; + threshold = -threshold; + } else + skip_dc = 1; + + /* Are all we could set to zero already zero? */ + if (last_index <= skip_dc - 1) + return; + + for (i = 0; i <= last_index; i++) { + const int j = s->intra_scantable.permutated[i]; + const int level = FFABS(block[j]); + if (level == 1) { + if (skip_dc && i == 0) + continue; + score += tab[run]; + run = 0; + } else if (level > 1) { + return; + } else { + run++; + } + } + if (score >= threshold) + return; + for (i = skip_dc; i <= last_index; i++) { + const int j = s->intra_scantable.permutated[i]; + block[j] = 0; + } + if (block[0]) + s->block_last_index[n] = 0; + else + s->block_last_index[n] = -1; +} + +static inline void clip_coeffs(MpegEncContext *s, int16_t *block, + int last_index) +{ + int i; + const int maxlevel = s->max_qcoeff; + const int minlevel = s->min_qcoeff; + int overflow = 0; + + if (s->mb_intra) { + i = 1; // skip clipping of intra dc + } else + i = 0; + + for (; i <= last_index; i++) { + const int j = s->intra_scantable.permutated[i]; + int level = block[j]; + + if (level > maxlevel) { + level = maxlevel; + overflow++; + } else if (level < minlevel) { + level = minlevel; + overflow++; + } + + block[j] = level; + } + + if (overflow && s->avctx->mb_decision == FF_MB_DECISION_SIMPLE) + av_log(s->avctx, AV_LOG_INFO, + "warning, clipping %d dct coefficients to %d..%d\n", + overflow, minlevel, maxlevel); +} + +static void get_visual_weight(int16_t *weight, uint8_t *ptr, int stride) +{ + int x, y; + // FIXME optimize + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) { + int x2, y2; + int sum = 0; + int sqr = 0; + int count = 0; + + for (y2 = FFMAX(y - 1, 0); y2 < FFMIN(8, y + 2); y2++) { + for (x2= FFMAX(x - 1, 0); x2 < FFMIN(8, x + 2); x2++) { + int v = ptr[x2 + y2 * stride]; + sum += v; + sqr += v * v; + count++; + } + } + weight[x + 8 * y]= (36 * ff_sqrt(count * sqr - sum * sum)) / count; + } + } +} + +static av_always_inline void encode_mb_internal(MpegEncContext *s, + int motion_x, int motion_y, + int mb_block_height, + int mb_block_width, + int mb_block_count) +{ + int16_t weight[12][64]; + int16_t orig[12][64]; + const int mb_x = s->mb_x; + const int mb_y = s->mb_y; + int i; + int skip_dct[12]; + int dct_offset = s->linesize * 8; // default for progressive frames + int uv_dct_offset = s->uvlinesize * 8; + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int wrap_y, wrap_c; + + for (i = 0; i < mb_block_count; i++) + skip_dct[i] = s->skipdct; + + if (s->adaptive_quant) { + const int last_qp = s->qscale; + const int mb_xy = mb_x + mb_y * s->mb_stride; + + s->lambda = s->lambda_table[mb_xy]; + update_qscale(s); + + if (!(s->mpv_flags & FF_MPV_FLAG_QP_RD)) { + s->qscale = s->current_picture_ptr->qscale_table[mb_xy]; + s->dquant = s->qscale - last_qp; + + if (s->out_format == FMT_H263) { + s->dquant = av_clip(s->dquant, -2, 2); + + if (s->codec_id == AV_CODEC_ID_MPEG4) { + if (!s->mb_intra) { + if (s->pict_type == AV_PICTURE_TYPE_B) { + if (s->dquant & 1 || s->mv_dir & MV_DIRECT) + s->dquant = 0; + } + if (s->mv_type == MV_TYPE_8X8) + s->dquant = 0; + } + } + } + } + ff_set_qscale(s, last_qp + s->dquant); + } else if (s->mpv_flags & FF_MPV_FLAG_QP_RD) + ff_set_qscale(s, s->qscale + s->dquant); + + wrap_y = s->linesize; + wrap_c = s->uvlinesize; + ptr_y = s->new_picture.f.data[0] + + (mb_y * 16 * wrap_y) + mb_x * 16; + ptr_cb = s->new_picture.f.data[1] + + (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width; + ptr_cr = s->new_picture.f.data[2] + + (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width; + + if((mb_x*16+16 > s->width || mb_y*16+16 > s->height) && s->codec_id != AV_CODEC_ID_AMV){ + uint8_t *ebuf = s->edge_emu_buffer + 32; + int cw = (s->width + s->chroma_x_shift) >> s->chroma_x_shift; + int ch = (s->height + s->chroma_y_shift) >> s->chroma_y_shift; + s->vdsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, 16, 16, mb_x * 16, + mb_y * 16, s->width, s->height); + ptr_y = ebuf; + s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, mb_block_width, + mb_block_height, mb_x * mb_block_width, mb_y * mb_block_height, + cw, ch); + ptr_cb = ebuf + 18 * wrap_y; + s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y + 16, ptr_cr, wrap_c, mb_block_width, + mb_block_height, mb_x * mb_block_width, mb_y * mb_block_height, + cw, ch); + ptr_cr = ebuf + 18 * wrap_y + 16; + } + + if (s->mb_intra) { + if (s->flags & CODEC_FLAG_INTERLACED_DCT) { + int progressive_score, interlaced_score; + + s->interlaced_dct = 0; + progressive_score = s->dsp.ildct_cmp[4](s, ptr_y, + NULL, wrap_y, 8) + + s->dsp.ildct_cmp[4](s, ptr_y + wrap_y * 8, + NULL, wrap_y, 8) - 400; + + if (progressive_score > 0) { + interlaced_score = s->dsp.ildct_cmp[4](s, ptr_y, + NULL, wrap_y * 2, 8) + + s->dsp.ildct_cmp[4](s, ptr_y + wrap_y, + NULL, wrap_y * 2, 8); + if (progressive_score > interlaced_score) { + s->interlaced_dct = 1; + + dct_offset = wrap_y; + uv_dct_offset = wrap_c; + wrap_y <<= 1; + if (s->chroma_format == CHROMA_422 || + s->chroma_format == CHROMA_444) + wrap_c <<= 1; + } + } + } + + s->dsp.get_pixels(s->block[0], ptr_y , wrap_y); + s->dsp.get_pixels(s->block[1], ptr_y + 8 , wrap_y); + s->dsp.get_pixels(s->block[2], ptr_y + dct_offset , wrap_y); + s->dsp.get_pixels(s->block[3], ptr_y + dct_offset + 8 , wrap_y); + + if (s->flags & CODEC_FLAG_GRAY) { + skip_dct[4] = 1; + skip_dct[5] = 1; + } else { + s->dsp.get_pixels(s->block[4], ptr_cb, wrap_c); + s->dsp.get_pixels(s->block[5], ptr_cr, wrap_c); + if (!s->chroma_y_shift && s->chroma_x_shift) { /* 422 */ + s->dsp.get_pixels(s->block[6], ptr_cb + uv_dct_offset, wrap_c); + s->dsp.get_pixels(s->block[7], ptr_cr + uv_dct_offset, wrap_c); + } else if (!s->chroma_y_shift && !s->chroma_x_shift) { /* 444 */ + s->dsp.get_pixels(s->block[6], ptr_cb + 8, wrap_c); + s->dsp.get_pixels(s->block[7], ptr_cr + 8, wrap_c); + s->dsp.get_pixels(s->block[8], ptr_cb + uv_dct_offset, wrap_c); + s->dsp.get_pixels(s->block[9], ptr_cr + uv_dct_offset, wrap_c); + s->dsp.get_pixels(s->block[10], ptr_cb + uv_dct_offset + 8, wrap_c); + s->dsp.get_pixels(s->block[11], ptr_cr + uv_dct_offset + 8, wrap_c); + } + } + } else { + op_pixels_func (*op_pix)[4]; + qpel_mc_func (*op_qpix)[16]; + uint8_t *dest_y, *dest_cb, *dest_cr; + + dest_y = s->dest[0]; + dest_cb = s->dest[1]; + dest_cr = s->dest[2]; + + if ((!s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { + op_pix = s->hdsp.put_pixels_tab; + op_qpix = s->dsp.put_qpel_pixels_tab; + } else { + op_pix = s->hdsp.put_no_rnd_pixels_tab; + op_qpix = s->dsp.put_no_rnd_qpel_pixels_tab; + } + + if (s->mv_dir & MV_DIR_FORWARD) { + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 0, + s->last_picture.f.data, + op_pix, op_qpix); + op_pix = s->hdsp.avg_pixels_tab; + op_qpix = s->dsp.avg_qpel_pixels_tab; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + ff_MPV_motion(s, dest_y, dest_cb, dest_cr, 1, + s->next_picture.f.data, + op_pix, op_qpix); + } + + if (s->flags & CODEC_FLAG_INTERLACED_DCT) { + int progressive_score, interlaced_score; + + s->interlaced_dct = 0; + progressive_score = s->dsp.ildct_cmp[0](s, dest_y, + ptr_y, wrap_y, + 8) + + s->dsp.ildct_cmp[0](s, dest_y + wrap_y * 8, + ptr_y + wrap_y * 8, wrap_y, + 8) - 400; + + if (s->avctx->ildct_cmp == FF_CMP_VSSE) + progressive_score -= 400; + + if (progressive_score > 0) { + interlaced_score = s->dsp.ildct_cmp[0](s, dest_y, + ptr_y, + wrap_y * 2, 8) + + s->dsp.ildct_cmp[0](s, dest_y + wrap_y, + ptr_y + wrap_y, + wrap_y * 2, 8); + + if (progressive_score > interlaced_score) { + s->interlaced_dct = 1; + + dct_offset = wrap_y; + uv_dct_offset = wrap_c; + wrap_y <<= 1; + if (s->chroma_format == CHROMA_422) + wrap_c <<= 1; + } + } + } + + s->dsp.diff_pixels(s->block[0], ptr_y, dest_y, wrap_y); + s->dsp.diff_pixels(s->block[1], ptr_y + 8, dest_y + 8, wrap_y); + s->dsp.diff_pixels(s->block[2], ptr_y + dct_offset, + dest_y + dct_offset, wrap_y); + s->dsp.diff_pixels(s->block[3], ptr_y + dct_offset + 8, + dest_y + dct_offset + 8, wrap_y); + + if (s->flags & CODEC_FLAG_GRAY) { + skip_dct[4] = 1; + skip_dct[5] = 1; + } else { + s->dsp.diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); + s->dsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); + if (!s->chroma_y_shift) { /* 422 */ + s->dsp.diff_pixels(s->block[6], ptr_cb + uv_dct_offset, + dest_cb + uv_dct_offset, wrap_c); + s->dsp.diff_pixels(s->block[7], ptr_cr + uv_dct_offset, + dest_cr + uv_dct_offset, wrap_c); + } + } + /* pre quantization */ + if (s->current_picture.mc_mb_var[s->mb_stride * mb_y + mb_x] < + 2 * s->qscale * s->qscale) { + // FIXME optimize + if (s->dsp.sad[1](NULL, ptr_y , dest_y, + wrap_y, 8) < 20 * s->qscale) + skip_dct[0] = 1; + if (s->dsp.sad[1](NULL, ptr_y + 8, + dest_y + 8, wrap_y, 8) < 20 * s->qscale) + skip_dct[1] = 1; + if (s->dsp.sad[1](NULL, ptr_y + dct_offset, + dest_y + dct_offset, wrap_y, 8) < 20 * s->qscale) + skip_dct[2] = 1; + if (s->dsp.sad[1](NULL, ptr_y + dct_offset + 8, + dest_y + dct_offset + 8, + wrap_y, 8) < 20 * s->qscale) + skip_dct[3] = 1; + if (s->dsp.sad[1](NULL, ptr_cb, dest_cb, + wrap_c, 8) < 20 * s->qscale) + skip_dct[4] = 1; + if (s->dsp.sad[1](NULL, ptr_cr, dest_cr, + wrap_c, 8) < 20 * s->qscale) + skip_dct[5] = 1; + if (!s->chroma_y_shift) { /* 422 */ + if (s->dsp.sad[1](NULL, ptr_cb + uv_dct_offset, + dest_cb + uv_dct_offset, + wrap_c, 8) < 20 * s->qscale) + skip_dct[6] = 1; + if (s->dsp.sad[1](NULL, ptr_cr + uv_dct_offset, + dest_cr + uv_dct_offset, + wrap_c, 8) < 20 * s->qscale) + skip_dct[7] = 1; + } + } + } + + if (s->quantizer_noise_shaping) { + if (!skip_dct[0]) + get_visual_weight(weight[0], ptr_y , wrap_y); + if (!skip_dct[1]) + get_visual_weight(weight[1], ptr_y + 8, wrap_y); + if (!skip_dct[2]) + get_visual_weight(weight[2], ptr_y + dct_offset , wrap_y); + if (!skip_dct[3]) + get_visual_weight(weight[3], ptr_y + dct_offset + 8, wrap_y); + if (!skip_dct[4]) + get_visual_weight(weight[4], ptr_cb , wrap_c); + if (!skip_dct[5]) + get_visual_weight(weight[5], ptr_cr , wrap_c); + if (!s->chroma_y_shift) { /* 422 */ + if (!skip_dct[6]) + get_visual_weight(weight[6], ptr_cb + uv_dct_offset, + wrap_c); + if (!skip_dct[7]) + get_visual_weight(weight[7], ptr_cr + uv_dct_offset, + wrap_c); + } + memcpy(orig[0], s->block[0], sizeof(int16_t) * 64 * mb_block_count); + } + + /* DCT & quantize */ + av_assert2(s->out_format != FMT_MJPEG || s->qscale == 8); + { + for (i = 0; i < mb_block_count; i++) { + if (!skip_dct[i]) { + int overflow; + s->block_last_index[i] = s->dct_quantize(s, s->block[i], i, s->qscale, &overflow); + // FIXME we could decide to change to quantizer instead of + // clipping + // JS: I don't think that would be a good idea it could lower + // quality instead of improve it. Just INTRADC clipping + // deserves changes in quantizer + if (overflow) + clip_coeffs(s, s->block[i], s->block_last_index[i]); + } else + s->block_last_index[i] = -1; + } + if (s->quantizer_noise_shaping) { + for (i = 0; i < mb_block_count; i++) { + if (!skip_dct[i]) { + s->block_last_index[i] = + dct_quantize_refine(s, s->block[i], weight[i], + orig[i], i, s->qscale); + } + } + } + + if (s->luma_elim_threshold && !s->mb_intra) + for (i = 0; i < 4; i++) + dct_single_coeff_elimination(s, i, s->luma_elim_threshold); + if (s->chroma_elim_threshold && !s->mb_intra) + for (i = 4; i < mb_block_count; i++) + dct_single_coeff_elimination(s, i, s->chroma_elim_threshold); + + if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) { + for (i = 0; i < mb_block_count; i++) { + if (s->block_last_index[i] == -1) + s->coded_score[i] = INT_MAX / 256; + } + } + } + + if ((s->flags & CODEC_FLAG_GRAY) && s->mb_intra) { + s->block_last_index[4] = + s->block_last_index[5] = 0; + s->block[4][0] = + s->block[5][0] = (1024 + s->c_dc_scale / 2) / s->c_dc_scale; + if (!s->chroma_y_shift) { /* 422 / 444 */ + for (i=6; i<12; i++) { + s->block_last_index[i] = 0; + s->block[i][0] = s->block[4][0]; + } + } + } + + // non c quantize code returns incorrect block_last_index FIXME + if (s->alternate_scan && s->dct_quantize != ff_dct_quantize_c) { + for (i = 0; i < mb_block_count; i++) { + int j; + if (s->block_last_index[i] > 0) { + for (j = 63; j > 0; j--) { + if (s->block[i][s->intra_scantable.permutated[j]]) + break; + } + s->block_last_index[i] = j; + } + } + } + + /* huffman encode */ + switch(s->codec_id){ //FIXME funct ptr could be slightly faster + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) + ff_mpeg1_encode_mb(s, s->block, motion_x, motion_y); + break; + case AV_CODEC_ID_MPEG4: + if (CONFIG_MPEG4_ENCODER) + ff_mpeg4_encode_mb(s, s->block, motion_x, motion_y); + break; + case AV_CODEC_ID_MSMPEG4V2: + case AV_CODEC_ID_MSMPEG4V3: + case AV_CODEC_ID_WMV1: + if (CONFIG_MSMPEG4_ENCODER) + ff_msmpeg4_encode_mb(s, s->block, motion_x, motion_y); + break; + case AV_CODEC_ID_WMV2: + if (CONFIG_WMV2_ENCODER) + ff_wmv2_encode_mb(s, s->block, motion_x, motion_y); + break; + case AV_CODEC_ID_H261: + if (CONFIG_H261_ENCODER) + ff_h261_encode_mb(s, s->block, motion_x, motion_y); + break; + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + case AV_CODEC_ID_FLV1: + case AV_CODEC_ID_RV10: + case AV_CODEC_ID_RV20: + if (CONFIG_H263_ENCODER) + ff_h263_encode_mb(s, s->block, motion_x, motion_y); + break; + case AV_CODEC_ID_MJPEG: + case AV_CODEC_ID_AMV: + if (CONFIG_MJPEG_ENCODER) + ff_mjpeg_encode_mb(s, s->block); + break; + default: + av_assert1(0); + } +} + +static av_always_inline void encode_mb(MpegEncContext *s, int motion_x, int motion_y) +{ + if (s->chroma_format == CHROMA_420) encode_mb_internal(s, motion_x, motion_y, 8, 8, 6); + else if (s->chroma_format == CHROMA_422) encode_mb_internal(s, motion_x, motion_y, 16, 8, 8); + else encode_mb_internal(s, motion_x, motion_y, 16, 16, 12); +} + +static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext *s, int type){ + int i; + + memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop? + + /* mpeg1 */ + d->mb_skip_run= s->mb_skip_run; + for(i=0; i<3; i++) + d->last_dc[i] = s->last_dc[i]; + + /* statistics */ + d->mv_bits= s->mv_bits; + d->i_tex_bits= s->i_tex_bits; + d->p_tex_bits= s->p_tex_bits; + d->i_count= s->i_count; + d->f_count= s->f_count; + d->b_count= s->b_count; + d->skip_count= s->skip_count; + d->misc_bits= s->misc_bits; + d->last_bits= 0; + + d->mb_skipped= 0; + d->qscale= s->qscale; + d->dquant= s->dquant; + + d->esc3_level_length= s->esc3_level_length; +} + +static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext *s, int type){ + int i; + + memcpy(d->mv, s->mv, 2*4*2*sizeof(int)); + memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop? + + /* mpeg1 */ + d->mb_skip_run= s->mb_skip_run; + for(i=0; i<3; i++) + d->last_dc[i] = s->last_dc[i]; + + /* statistics */ + d->mv_bits= s->mv_bits; + d->i_tex_bits= s->i_tex_bits; + d->p_tex_bits= s->p_tex_bits; + d->i_count= s->i_count; + d->f_count= s->f_count; + d->b_count= s->b_count; + d->skip_count= s->skip_count; + d->misc_bits= s->misc_bits; + + d->mb_intra= s->mb_intra; + d->mb_skipped= s->mb_skipped; + d->mv_type= s->mv_type; + d->mv_dir= s->mv_dir; + d->pb= s->pb; + if(s->data_partitioning){ + d->pb2= s->pb2; + d->tex_pb= s->tex_pb; + } + d->block= s->block; + for(i=0; i<8; i++) + d->block_last_index[i]= s->block_last_index[i]; + d->interlaced_dct= s->interlaced_dct; + d->qscale= s->qscale; + + d->esc3_level_length= s->esc3_level_length; +} + +static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegEncContext *best, int type, + PutBitContext pb[2], PutBitContext pb2[2], PutBitContext tex_pb[2], + int *dmin, int *next_block, int motion_x, int motion_y) +{ + int score; + uint8_t *dest_backup[3]; + + copy_context_before_encode(s, backup, type); + + s->block= s->blocks[*next_block]; + s->pb= pb[*next_block]; + if(s->data_partitioning){ + s->pb2 = pb2 [*next_block]; + s->tex_pb= tex_pb[*next_block]; + } + + if(*next_block){ + memcpy(dest_backup, s->dest, sizeof(s->dest)); + s->dest[0] = s->rd_scratchpad; + s->dest[1] = s->rd_scratchpad + 16*s->linesize; + s->dest[2] = s->rd_scratchpad + 16*s->linesize + 8; + assert(s->linesize >= 32); //FIXME + } + + encode_mb(s, motion_x, motion_y); + + score= put_bits_count(&s->pb); + if(s->data_partitioning){ + score+= put_bits_count(&s->pb2); + score+= put_bits_count(&s->tex_pb); + } + + if(s->avctx->mb_decision == FF_MB_DECISION_RD){ + ff_MPV_decode_mb(s, s->block); + + score *= s->lambda2; + score += sse_mb(s) << FF_LAMBDA_SHIFT; + } + + if(*next_block){ + memcpy(s->dest, dest_backup, sizeof(s->dest)); + } + + if(score<*dmin){ + *dmin= score; + *next_block^=1; + + copy_context_after_encode(best, s, type); + } +} + +static int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride){ + uint32_t *sq = ff_squareTbl + 256; + int acc=0; + int x,y; + + if(w==16 && h==16) + return s->dsp.sse[0](NULL, src1, src2, stride, 16); + else if(w==8 && h==8) + return s->dsp.sse[1](NULL, src1, src2, stride, 8); + + for(y=0; y=0); + + return acc; +} + +static int sse_mb(MpegEncContext *s){ + int w= 16; + int h= 16; + + if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; + if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; + + if(w==16 && h==16) + if(s->avctx->mb_cmp == FF_CMP_NSSE){ + return s->dsp.nsse[0](s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], s->linesize, 16) + +s->dsp.nsse[1](s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], s->uvlinesize, 8) + +s->dsp.nsse[1](s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], s->uvlinesize, 8); + }else{ + return s->dsp.sse[0](NULL, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], s->linesize, 16) + +s->dsp.sse[1](NULL, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], s->uvlinesize, 8) + +s->dsp.sse[1](NULL, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], s->uvlinesize, 8); + } + else + return sse(s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize) + +sse(s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], w>>1, h>>1, s->uvlinesize) + +sse(s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], w>>1, h>>1, s->uvlinesize); +} + +static int pre_estimate_motion_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= *(void**)arg; + + + s->me.pre_pass=1; + s->me.dia_size= s->avctx->pre_dia_size; + s->first_slice_line=1; + for(s->mb_y= s->end_mb_y-1; s->mb_y >= s->start_mb_y; s->mb_y--) { + for(s->mb_x=s->mb_width-1; s->mb_x >=0 ;s->mb_x--) { + ff_pre_estimate_p_frame_motion(s, s->mb_x, s->mb_y); + } + s->first_slice_line=0; + } + + s->me.pre_pass=0; + + return 0; +} + +static int estimate_motion_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= *(void**)arg; + + ff_check_alignment(); + + s->me.dia_size= s->avctx->dia_size; + s->first_slice_line=1; + for(s->mb_y= s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x=0; //for block init below + ff_init_block_index(s); + for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) { + s->block_index[0]+=2; + s->block_index[1]+=2; + s->block_index[2]+=2; + s->block_index[3]+=2; + + /* compute motion vector & mb_type and store in context */ + if(s->pict_type==AV_PICTURE_TYPE_B) + ff_estimate_b_frame_motion(s, s->mb_x, s->mb_y); + else + ff_estimate_p_frame_motion(s, s->mb_x, s->mb_y); + } + s->first_slice_line=0; + } + return 0; +} + +static int mb_var_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= *(void**)arg; + int mb_x, mb_y; + + ff_check_alignment(); + + for(mb_y=s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { + for(mb_x=0; mb_x < s->mb_width; mb_x++) { + int xx = mb_x * 16; + int yy = mb_y * 16; + uint8_t *pix = s->new_picture.f.data[0] + (yy * s->linesize) + xx; + int varc; + int sum = s->dsp.pix_sum(pix, s->linesize); + + varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)sum*sum)>>8) + 500 + 128)>>8; + + s->current_picture.mb_var [s->mb_stride * mb_y + mb_x] = varc; + s->current_picture.mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8; + s->me.mb_var_sum_temp += varc; + } + } + return 0; +} + +static void write_slice_end(MpegEncContext *s){ + if(CONFIG_MPEG4_ENCODER && s->codec_id==AV_CODEC_ID_MPEG4){ + if(s->partitioned_frame){ + ff_mpeg4_merge_partitions(s); + } + + ff_mpeg4_stuffing(&s->pb); + }else if(CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG){ + ff_mjpeg_encode_stuffing(s); + } + + avpriv_align_put_bits(&s->pb); + flush_put_bits(&s->pb); + + if((s->flags&CODEC_FLAG_PASS1) && !s->partitioned_frame) + s->misc_bits+= get_bits_diff(s); +} + +static void write_mb_info(MpegEncContext *s) +{ + uint8_t *ptr = s->mb_info_ptr + s->mb_info_size - 12; + int offset = put_bits_count(&s->pb); + int mba = s->mb_x + s->mb_width * (s->mb_y % s->gob_index); + int gobn = s->mb_y / s->gob_index; + int pred_x, pred_y; + if (CONFIG_H263_ENCODER) + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + bytestream_put_le32(&ptr, offset); + bytestream_put_byte(&ptr, s->qscale); + bytestream_put_byte(&ptr, gobn); + bytestream_put_le16(&ptr, mba); + bytestream_put_byte(&ptr, pred_x); /* hmv1 */ + bytestream_put_byte(&ptr, pred_y); /* vmv1 */ + /* 4MV not implemented */ + bytestream_put_byte(&ptr, 0); /* hmv2 */ + bytestream_put_byte(&ptr, 0); /* vmv2 */ +} + +static void update_mb_info(MpegEncContext *s, int startcode) +{ + if (!s->mb_info) + return; + if (put_bits_count(&s->pb) - s->prev_mb_info*8 >= s->mb_info*8) { + s->mb_info_size += 12; + s->prev_mb_info = s->last_mb_info; + } + if (startcode) { + s->prev_mb_info = put_bits_count(&s->pb)/8; + /* This might have incremented mb_info_size above, and we return without + * actually writing any info into that slot yet. But in that case, + * this will be called again at the start of the after writing the + * start code, actually writing the mb info. */ + return; + } + + s->last_mb_info = put_bits_count(&s->pb)/8; + if (!s->mb_info_size) + s->mb_info_size += 12; + write_mb_info(s); +} + +static int encode_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= *(void**)arg; + int mb_x, mb_y, pdif = 0; + int chr_h= 16>>s->chroma_y_shift; + int i, j; + MpegEncContext best_s, backup_s; + uint8_t bit_buf[2][MAX_MB_BYTES]; + uint8_t bit_buf2[2][MAX_MB_BYTES]; + uint8_t bit_buf_tex[2][MAX_MB_BYTES]; + PutBitContext pb[2], pb2[2], tex_pb[2]; + + ff_check_alignment(); + + for(i=0; i<2; i++){ + init_put_bits(&pb [i], bit_buf [i], MAX_MB_BYTES); + init_put_bits(&pb2 [i], bit_buf2 [i], MAX_MB_BYTES); + init_put_bits(&tex_pb[i], bit_buf_tex[i], MAX_MB_BYTES); + } + + s->last_bits= put_bits_count(&s->pb); + s->mv_bits=0; + s->misc_bits=0; + s->i_tex_bits=0; + s->p_tex_bits=0; + s->i_count=0; + s->f_count=0; + s->b_count=0; + s->skip_count=0; + + for(i=0; i<3; i++){ + /* init last dc values */ + /* note: quant matrix value (8) is implied here */ + s->last_dc[i] = 128 << s->intra_dc_precision; + + s->current_picture.f.error[i] = 0; + } + if(s->codec_id==AV_CODEC_ID_AMV){ + s->last_dc[0] = 128*8/13; + s->last_dc[1] = 128*8/14; + s->last_dc[2] = 128*8/14; + } + s->mb_skip_run = 0; + memset(s->last_mv, 0, sizeof(s->last_mv)); + + s->last_mv_dir = 0; + + switch(s->codec_id){ + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + case AV_CODEC_ID_FLV1: + if (CONFIG_H263_ENCODER) + s->gob_index = ff_h263_get_gob_height(s); + break; + case AV_CODEC_ID_MPEG4: + if(CONFIG_MPEG4_ENCODER && s->partitioned_frame) + ff_mpeg4_init_partitions(s); + break; + } + + s->resync_mb_x=0; + s->resync_mb_y=0; + s->first_slice_line = 1; + s->ptr_lastgob = s->pb.buf; + for(mb_y= s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { + s->mb_x=0; + s->mb_y= mb_y; + + ff_set_qscale(s, s->qscale); + ff_init_block_index(s); + + for(mb_x=0; mb_x < s->mb_width; mb_x++) { + int xy= mb_y*s->mb_stride + mb_x; // removed const, H261 needs to adjust this + int mb_type= s->mb_type[xy]; +// int d; + int dmin= INT_MAX; + int dir; + + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < MAX_MB_BYTES){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + if(s->data_partitioning){ + if( s->pb2 .buf_end - s->pb2 .buf - (put_bits_count(&s-> pb2)>>3) < MAX_MB_BYTES + || s->tex_pb.buf_end - s->tex_pb.buf - (put_bits_count(&s->tex_pb )>>3) < MAX_MB_BYTES){ + av_log(s->avctx, AV_LOG_ERROR, "encoded partitioned frame too large\n"); + return -1; + } + } + + s->mb_x = mb_x; + s->mb_y = mb_y; // moved into loop, can get changed by H.261 + ff_update_block_index(s); + + if(CONFIG_H261_ENCODER && s->codec_id == AV_CODEC_ID_H261){ + ff_h261_reorder_mb_index(s); + xy= s->mb_y*s->mb_stride + s->mb_x; + mb_type= s->mb_type[xy]; + } + + /* write gob / video packet header */ + if(s->rtp_mode){ + int current_packet_size, is_gob_start; + + current_packet_size= ((put_bits_count(&s->pb)+7)>>3) - (s->ptr_lastgob - s->pb.buf); + + is_gob_start= s->avctx->rtp_payload_size && current_packet_size >= s->avctx->rtp_payload_size && mb_y + mb_x>0; + + if(s->start_mb_y == mb_y && mb_y > 0 && mb_x==0) is_gob_start=1; + + switch(s->codec_id){ + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + if(!s->h263_slice_structured) + if(s->mb_x || s->mb_y%s->gob_index) is_gob_start=0; + break; + case AV_CODEC_ID_MPEG2VIDEO: + if(s->mb_x==0 && s->mb_y!=0) is_gob_start=1; + case AV_CODEC_ID_MPEG1VIDEO: + if(s->mb_skip_run) is_gob_start=0; + break; + case AV_CODEC_ID_MJPEG: + if(s->mb_x==0 && s->mb_y!=0) is_gob_start=1; + break; + } + + if(is_gob_start){ + if(s->start_mb_y != mb_y || mb_x!=0){ + write_slice_end(s); + if(CONFIG_MPEG4_ENCODER && s->codec_id==AV_CODEC_ID_MPEG4 && s->partitioned_frame){ + ff_mpeg4_init_partitions(s); + } + } + + av_assert2((put_bits_count(&s->pb)&7) == 0); + current_packet_size= put_bits_ptr(&s->pb) - s->ptr_lastgob; + + if(s->avctx->error_rate && s->resync_mb_x + s->resync_mb_y > 0){ + int r= put_bits_count(&s->pb)/8 + s->picture_number + 16 + s->mb_x + s->mb_y; + int d= 100 / s->avctx->error_rate; + if(r % d == 0){ + current_packet_size=0; + s->pb.buf_ptr= s->ptr_lastgob; + assert(put_bits_ptr(&s->pb) == s->ptr_lastgob); + } + } + + if (s->avctx->rtp_callback){ + int number_mb = (mb_y - s->resync_mb_y)*s->mb_width + mb_x - s->resync_mb_x; + s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, current_packet_size, number_mb); + } + update_mb_info(s, 1); + + switch(s->codec_id){ + case AV_CODEC_ID_MPEG4: + if (CONFIG_MPEG4_ENCODER) { + ff_mpeg4_encode_video_packet_header(s); + ff_mpeg4_clean_buffers(s); + } + break; + case AV_CODEC_ID_MPEG1VIDEO: + case AV_CODEC_ID_MPEG2VIDEO: + if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) { + ff_mpeg1_encode_slice_header(s); + ff_mpeg1_clean_buffers(s); + } + break; + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + if (CONFIG_H263_ENCODER) + ff_h263_encode_gob_header(s, mb_y); + break; + } + + if(s->flags&CODEC_FLAG_PASS1){ + int bits= put_bits_count(&s->pb); + s->misc_bits+= bits - s->last_bits; + s->last_bits= bits; + } + + s->ptr_lastgob += current_packet_size; + s->first_slice_line=1; + s->resync_mb_x=mb_x; + s->resync_mb_y=mb_y; + } + } + + if( (s->resync_mb_x == s->mb_x) + && s->resync_mb_y+1 == s->mb_y){ + s->first_slice_line=0; + } + + s->mb_skipped=0; + s->dquant=0; //only for QP_RD + + update_mb_info(s, 0); + + if (mb_type & (mb_type-1) || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) { // more than 1 MB type possible or FF_MPV_FLAG_QP_RD + int next_block=0; + int pb_bits_count, pb2_bits_count, tex_pb_bits_count; + + copy_context_before_encode(&backup_s, s, -1); + backup_s.pb= s->pb; + best_s.data_partitioning= s->data_partitioning; + best_s.partitioned_frame= s->partitioned_frame; + if(s->data_partitioning){ + backup_s.pb2= s->pb2; + backup_s.tex_pb= s->tex_pb; + } + + if(mb_type&CANDIDATE_MB_TYPE_INTER){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[0][0][0] = s->p_mv_table[xy][0]; + s->mv[0][0][1] = s->p_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); + } + if(mb_type&CANDIDATE_MB_TYPE_INTER_I){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(i=0; i<2; i++){ + j= s->field_select[0][i] = s->p_field_select_table[i][xy]; + s->mv[0][i][0] = s->p_field_mv_table[i][j][xy][0]; + s->mv[0][i][1] = s->p_field_mv_table[i][j][xy][1]; + } + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER_I, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&CANDIDATE_MB_TYPE_SKIPPED){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_SKIPPED, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); + } + if(mb_type&CANDIDATE_MB_TYPE_INTER4V){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_8X8; + s->mb_intra= 0; + for(i=0; i<4; i++){ + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1]; + } + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER4V, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&CANDIDATE_MB_TYPE_FORWARD){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[0][0][0] = s->b_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_forw_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_FORWARD, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); + } + if(mb_type&CANDIDATE_MB_TYPE_BACKWARD){ + s->mv_dir = MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[1][0][0] = s->b_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_back_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BACKWARD, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[1][0][0], s->mv[1][0][1]); + } + if(mb_type&CANDIDATE_MB_TYPE_BIDIR){ + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[0][0][0] = s->b_bidir_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1]; + s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BIDIR, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&CANDIDATE_MB_TYPE_FORWARD_I){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(i=0; i<2; i++){ + j= s->field_select[0][i] = s->b_field_select_table[0][i][xy]; + s->mv[0][i][0] = s->b_field_mv_table[0][i][j][xy][0]; + s->mv[0][i][1] = s->b_field_mv_table[0][i][j][xy][1]; + } + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_FORWARD_I, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&CANDIDATE_MB_TYPE_BACKWARD_I){ + s->mv_dir = MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(i=0; i<2; i++){ + j= s->field_select[1][i] = s->b_field_select_table[1][i][xy]; + s->mv[1][i][0] = s->b_field_mv_table[1][i][j][xy][0]; + s->mv[1][i][1] = s->b_field_mv_table[1][i][j][xy][1]; + } + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BACKWARD_I, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&CANDIDATE_MB_TYPE_BIDIR_I){ + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(dir=0; dir<2; dir++){ + for(i=0; i<2; i++){ + j= s->field_select[dir][i] = s->b_field_select_table[dir][i][xy]; + s->mv[dir][i][0] = s->b_field_mv_table[dir][i][j][xy][0]; + s->mv[dir][i][1] = s->b_field_mv_table[dir][i][j][xy][1]; + } + } + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BIDIR_I, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&CANDIDATE_MB_TYPE_INTRA){ + s->mv_dir = 0; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 1; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTRA, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + if(s->h263_pred || s->h263_aic){ + if(best_s.mb_intra) + s->mbintra_table[mb_x + mb_y*s->mb_stride]=1; + else + ff_clean_intra_table_entries(s); //old mode? + } + } + + if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && dmin < INT_MAX) { + if(best_s.mv_type==MV_TYPE_16X16){ //FIXME move 4mv after QPRD + const int last_qp= backup_s.qscale; + int qpi, qp, dc[6]; + int16_t ac[6][16]; + const int mvdir= (best_s.mv_dir&MV_DIR_BACKWARD) ? 1 : 0; + static const int dquant_tab[4]={-1,1,-2,2}; + int storecoefs = s->mb_intra && s->dc_val[0]; + + av_assert2(backup_s.dquant == 0); + + //FIXME intra + s->mv_dir= best_s.mv_dir; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= best_s.mb_intra; + s->mv[0][0][0] = best_s.mv[0][0][0]; + s->mv[0][0][1] = best_s.mv[0][0][1]; + s->mv[1][0][0] = best_s.mv[1][0][0]; + s->mv[1][0][1] = best_s.mv[1][0][1]; + + qpi = s->pict_type == AV_PICTURE_TYPE_B ? 2 : 0; + for(; qpi<4; qpi++){ + int dquant= dquant_tab[qpi]; + qp= last_qp + dquant; + if(qp < s->avctx->qmin || qp > s->avctx->qmax) + continue; + backup_s.dquant= dquant; + if(storecoefs){ + for(i=0; i<6; i++){ + dc[i]= s->dc_val[0][ s->block_index[i] ]; + memcpy(ac[i], s->ac_val[0][s->block_index[i]], sizeof(int16_t)*16); + } + } + + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER /* wrong but unused */, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[mvdir][0][0], s->mv[mvdir][0][1]); + if(best_s.qscale != qp){ + if(storecoefs){ + for(i=0; i<6; i++){ + s->dc_val[0][ s->block_index[i] ]= dc[i]; + memcpy(s->ac_val[0][s->block_index[i]], ac[i], sizeof(int16_t)*16); + } + } + } + } + } + } + if(CONFIG_MPEG4_ENCODER && mb_type&CANDIDATE_MB_TYPE_DIRECT){ + int mx= s->b_direct_mv_table[xy][0]; + int my= s->b_direct_mv_table[xy][1]; + + backup_s.dquant = 0; + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; + s->mb_intra= 0; + ff_mpeg4_set_direct_mv(s, mx, my); + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb, + &dmin, &next_block, mx, my); + } + if(CONFIG_MPEG4_ENCODER && mb_type&CANDIDATE_MB_TYPE_DIRECT0){ + backup_s.dquant = 0; + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; + s->mb_intra= 0; + ff_mpeg4_set_direct_mv(s, 0, 0); + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if (!best_s.mb_intra && s->mpv_flags & FF_MPV_FLAG_SKIP_RD) { + int coded=0; + for(i=0; i<6; i++) + coded |= s->block_last_index[i]; + if(coded){ + int mx,my; + memcpy(s->mv, best_s.mv, sizeof(s->mv)); + if(CONFIG_MPEG4_ENCODER && best_s.mv_dir & MV_DIRECT){ + mx=my=0; //FIXME find the one we actually used + ff_mpeg4_set_direct_mv(s, mx, my); + }else if(best_s.mv_dir&MV_DIR_BACKWARD){ + mx= s->mv[1][0][0]; + my= s->mv[1][0][1]; + }else{ + mx= s->mv[0][0][0]; + my= s->mv[0][0][1]; + } + + s->mv_dir= best_s.mv_dir; + s->mv_type = best_s.mv_type; + s->mb_intra= 0; +/* s->mv[0][0][0] = best_s.mv[0][0][0]; + s->mv[0][0][1] = best_s.mv[0][0][1]; + s->mv[1][0][0] = best_s.mv[1][0][0]; + s->mv[1][0][1] = best_s.mv[1][0][1];*/ + backup_s.dquant= 0; + s->skipdct=1; + encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER /* wrong but unused */, pb, pb2, tex_pb, + &dmin, &next_block, mx, my); + s->skipdct=0; + } + } + + s->current_picture.qscale_table[xy] = best_s.qscale; + + copy_context_after_encode(s, &best_s, -1); + + pb_bits_count= put_bits_count(&s->pb); + flush_put_bits(&s->pb); + avpriv_copy_bits(&backup_s.pb, bit_buf[next_block^1], pb_bits_count); + s->pb= backup_s.pb; + + if(s->data_partitioning){ + pb2_bits_count= put_bits_count(&s->pb2); + flush_put_bits(&s->pb2); + avpriv_copy_bits(&backup_s.pb2, bit_buf2[next_block^1], pb2_bits_count); + s->pb2= backup_s.pb2; + + tex_pb_bits_count= put_bits_count(&s->tex_pb); + flush_put_bits(&s->tex_pb); + avpriv_copy_bits(&backup_s.tex_pb, bit_buf_tex[next_block^1], tex_pb_bits_count); + s->tex_pb= backup_s.tex_pb; + } + s->last_bits= put_bits_count(&s->pb); + + if (CONFIG_H263_ENCODER && + s->out_format == FMT_H263 && s->pict_type!=AV_PICTURE_TYPE_B) + ff_h263_update_motion_val(s); + + if(next_block==0){ //FIXME 16 vs linesize16 + s->hdsp.put_pixels_tab[0][0](s->dest[0], s->rd_scratchpad , s->linesize ,16); + s->hdsp.put_pixels_tab[1][0](s->dest[1], s->rd_scratchpad + 16*s->linesize , s->uvlinesize, 8); + s->hdsp.put_pixels_tab[1][0](s->dest[2], s->rd_scratchpad + 16*s->linesize + 8, s->uvlinesize, 8); + } + + if(s->avctx->mb_decision == FF_MB_DECISION_BITS) + ff_MPV_decode_mb(s, s->block); + } else { + int motion_x = 0, motion_y = 0; + s->mv_type=MV_TYPE_16X16; + // only one MB-Type possible + + switch(mb_type){ + case CANDIDATE_MB_TYPE_INTRA: + s->mv_dir = 0; + s->mb_intra= 1; + motion_x= s->mv[0][0][0] = 0; + motion_y= s->mv[0][0][1] = 0; + break; + case CANDIDATE_MB_TYPE_INTER: + s->mv_dir = MV_DIR_FORWARD; + s->mb_intra= 0; + motion_x= s->mv[0][0][0] = s->p_mv_table[xy][0]; + motion_y= s->mv[0][0][1] = s->p_mv_table[xy][1]; + break; + case CANDIDATE_MB_TYPE_INTER_I: + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(i=0; i<2; i++){ + j= s->field_select[0][i] = s->p_field_select_table[i][xy]; + s->mv[0][i][0] = s->p_field_mv_table[i][j][xy][0]; + s->mv[0][i][1] = s->p_field_mv_table[i][j][xy][1]; + } + break; + case CANDIDATE_MB_TYPE_INTER4V: + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_8X8; + s->mb_intra= 0; + for(i=0; i<4; i++){ + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1]; + } + break; + case CANDIDATE_MB_TYPE_DIRECT: + if (CONFIG_MPEG4_ENCODER) { + s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD|MV_DIRECT; + s->mb_intra= 0; + motion_x=s->b_direct_mv_table[xy][0]; + motion_y=s->b_direct_mv_table[xy][1]; + ff_mpeg4_set_direct_mv(s, motion_x, motion_y); + } + break; + case CANDIDATE_MB_TYPE_DIRECT0: + if (CONFIG_MPEG4_ENCODER) { + s->mv_dir = MV_DIR_FORWARD|MV_DIR_BACKWARD|MV_DIRECT; + s->mb_intra= 0; + ff_mpeg4_set_direct_mv(s, 0, 0); + } + break; + case CANDIDATE_MB_TYPE_BIDIR: + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + s->mb_intra= 0; + s->mv[0][0][0] = s->b_bidir_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1]; + s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1]; + break; + case CANDIDATE_MB_TYPE_BACKWARD: + s->mv_dir = MV_DIR_BACKWARD; + s->mb_intra= 0; + motion_x= s->mv[1][0][0] = s->b_back_mv_table[xy][0]; + motion_y= s->mv[1][0][1] = s->b_back_mv_table[xy][1]; + break; + case CANDIDATE_MB_TYPE_FORWARD: + s->mv_dir = MV_DIR_FORWARD; + s->mb_intra= 0; + motion_x= s->mv[0][0][0] = s->b_forw_mv_table[xy][0]; + motion_y= s->mv[0][0][1] = s->b_forw_mv_table[xy][1]; + break; + case CANDIDATE_MB_TYPE_FORWARD_I: + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(i=0; i<2; i++){ + j= s->field_select[0][i] = s->b_field_select_table[0][i][xy]; + s->mv[0][i][0] = s->b_field_mv_table[0][i][j][xy][0]; + s->mv[0][i][1] = s->b_field_mv_table[0][i][j][xy][1]; + } + break; + case CANDIDATE_MB_TYPE_BACKWARD_I: + s->mv_dir = MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(i=0; i<2; i++){ + j= s->field_select[1][i] = s->b_field_select_table[1][i][xy]; + s->mv[1][i][0] = s->b_field_mv_table[1][i][j][xy][0]; + s->mv[1][i][1] = s->b_field_mv_table[1][i][j][xy][1]; + } + break; + case CANDIDATE_MB_TYPE_BIDIR_I: + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_FIELD; + s->mb_intra= 0; + for(dir=0; dir<2; dir++){ + for(i=0; i<2; i++){ + j= s->field_select[dir][i] = s->b_field_select_table[dir][i][xy]; + s->mv[dir][i][0] = s->b_field_mv_table[dir][i][j][xy][0]; + s->mv[dir][i][1] = s->b_field_mv_table[dir][i][j][xy][1]; + } + } + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "illegal MB type\n"); + } + + encode_mb(s, motion_x, motion_y); + + // RAL: Update last macroblock type + s->last_mv_dir = s->mv_dir; + + if (CONFIG_H263_ENCODER && + s->out_format == FMT_H263 && s->pict_type!=AV_PICTURE_TYPE_B) + ff_h263_update_motion_val(s); + + ff_MPV_decode_mb(s, s->block); + } + + /* clean the MV table in IPS frames for direct mode in B frames */ + if(s->mb_intra /* && I,P,S_TYPE */){ + s->p_mv_table[xy][0]=0; + s->p_mv_table[xy][1]=0; + } + + if(s->flags&CODEC_FLAG_PSNR){ + int w= 16; + int h= 16; + + if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; + if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; + + s->current_picture.f.error[0] += sse( + s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + s->dest[0], w, h, s->linesize); + s->current_picture.f.error[1] += sse( + s, s->new_picture.f.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, + s->dest[1], w>>1, h>>s->chroma_y_shift, s->uvlinesize); + s->current_picture.f.error[2] += sse( + s, s->new_picture.f.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, + s->dest[2], w>>1, h>>s->chroma_y_shift, s->uvlinesize); + } + if(s->loop_filter){ + if(CONFIG_H263_ENCODER && s->out_format == FMT_H263) + ff_h263_loop_filter(s); + } + av_dlog(s->avctx, "MB %d %d bits\n", + s->mb_x + s->mb_y * s->mb_stride, put_bits_count(&s->pb)); + } + } + + //not beautiful here but we must write it before flushing so it has to be here + if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == AV_PICTURE_TYPE_I) + ff_msmpeg4_encode_ext_header(s); + + write_slice_end(s); + + /* Send the last GOB if RTP */ + if (s->avctx->rtp_callback) { + int number_mb = (mb_y - s->resync_mb_y)*s->mb_width - s->resync_mb_x; + pdif = put_bits_ptr(&s->pb) - s->ptr_lastgob; + /* Call the RTP callback to send the last GOB */ + emms_c(); + s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, pdif, number_mb); + } + + return 0; +} + +#define MERGE(field) dst->field += src->field; src->field=0 +static void merge_context_after_me(MpegEncContext *dst, MpegEncContext *src){ + MERGE(me.scene_change_score); + MERGE(me.mc_mb_var_sum_temp); + MERGE(me.mb_var_sum_temp); +} + +static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src){ + int i; + + MERGE(dct_count[0]); //note, the other dct vars are not part of the context + MERGE(dct_count[1]); + MERGE(mv_bits); + MERGE(i_tex_bits); + MERGE(p_tex_bits); + MERGE(i_count); + MERGE(f_count); + MERGE(b_count); + MERGE(skip_count); + MERGE(misc_bits); + MERGE(er.error_count); + MERGE(padding_bug_score); + MERGE(current_picture.f.error[0]); + MERGE(current_picture.f.error[1]); + MERGE(current_picture.f.error[2]); + + if(dst->avctx->noise_reduction){ + for(i=0; i<64; i++){ + MERGE(dct_error_sum[0][i]); + MERGE(dct_error_sum[1][i]); + } + } + + assert(put_bits_count(&src->pb) % 8 ==0); + assert(put_bits_count(&dst->pb) % 8 ==0); + avpriv_copy_bits(&dst->pb, src->pb.buf, put_bits_count(&src->pb)); + flush_put_bits(&dst->pb); +} + +static int estimate_qp(MpegEncContext *s, int dry_run){ + if (s->next_lambda){ + s->current_picture_ptr->f.quality = + s->current_picture.f.quality = s->next_lambda; + if(!dry_run) s->next_lambda= 0; + } else if (!s->fixed_qscale) { + s->current_picture_ptr->f.quality = + s->current_picture.f.quality = ff_rate_estimate_qscale(s, dry_run); + if (s->current_picture.f.quality < 0) + return -1; + } + + if(s->adaptive_quant){ + switch(s->codec_id){ + case AV_CODEC_ID_MPEG4: + if (CONFIG_MPEG4_ENCODER) + ff_clean_mpeg4_qscales(s); + break; + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + case AV_CODEC_ID_FLV1: + if (CONFIG_H263_ENCODER) + ff_clean_h263_qscales(s); + break; + default: + ff_init_qscale_tab(s); + } + + s->lambda= s->lambda_table[0]; + //FIXME broken + }else + s->lambda = s->current_picture.f.quality; + update_qscale(s); + return 0; +} + +/* must be called before writing the header */ +static void set_frame_distances(MpegEncContext * s){ + assert(s->current_picture_ptr->f.pts != AV_NOPTS_VALUE); + s->time = s->current_picture_ptr->f.pts * s->avctx->time_base.num; + + if(s->pict_type==AV_PICTURE_TYPE_B){ + s->pb_time= s->pp_time - (s->last_non_b_time - s->time); + assert(s->pb_time > 0 && s->pb_time < s->pp_time); + }else{ + s->pp_time= s->time - s->last_non_b_time; + s->last_non_b_time= s->time; + assert(s->picture_number==0 || s->pp_time > 0); + } +} + +static int encode_picture(MpegEncContext *s, int picture_number) +{ + int i, ret; + int bits; + int context_count = s->slice_context_count; + + s->picture_number = picture_number; + + /* Reset the average MB variance */ + s->me.mb_var_sum_temp = + s->me.mc_mb_var_sum_temp = 0; + + /* we need to initialize some time vars before we can encode b-frames */ + // RAL: Condition added for MPEG1VIDEO + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->msmpeg4_version)) + set_frame_distances(s); + if(CONFIG_MPEG4_ENCODER && s->codec_id == AV_CODEC_ID_MPEG4) + ff_set_mpeg4_time(s); + + s->me.scene_change_score=0; + +// s->lambda= s->current_picture_ptr->quality; //FIXME qscale / ... stuff for ME rate distortion + + if(s->pict_type==AV_PICTURE_TYPE_I){ + if(s->msmpeg4_version >= 3) s->no_rounding=1; + else s->no_rounding=0; + }else if(s->pict_type!=AV_PICTURE_TYPE_B){ + if(s->flipflop_rounding || s->codec_id == AV_CODEC_ID_H263P || s->codec_id == AV_CODEC_ID_MPEG4) + s->no_rounding ^= 1; + } + + if(s->flags & CODEC_FLAG_PASS2){ + if (estimate_qp(s,1) < 0) + return -1; + ff_get_2pass_fcode(s); + }else if(!(s->flags & CODEC_FLAG_QSCALE)){ + if(s->pict_type==AV_PICTURE_TYPE_B) + s->lambda= s->last_lambda_for[s->pict_type]; + else + s->lambda= s->last_lambda_for[s->last_non_b_pict_type]; + update_qscale(s); + } + + if(s->codec_id != AV_CODEC_ID_AMV){ + if(s->q_chroma_intra_matrix != s->q_intra_matrix ) av_freep(&s->q_chroma_intra_matrix); + if(s->q_chroma_intra_matrix16 != s->q_intra_matrix16) av_freep(&s->q_chroma_intra_matrix16); + s->q_chroma_intra_matrix = s->q_intra_matrix; + s->q_chroma_intra_matrix16 = s->q_intra_matrix16; + } + + s->mb_intra=0; //for the rate distortion & bit compare functions + for(i=1; ithread_context[i], s); + if (ret < 0) + return ret; + } + + if(ff_init_me(s)<0) + return -1; + + /* Estimate motion for every MB */ + if(s->pict_type != AV_PICTURE_TYPE_I){ + s->lambda = (s->lambda * s->avctx->me_penalty_compensation + 128)>>8; + s->lambda2= (s->lambda2* (int64_t)s->avctx->me_penalty_compensation + 128)>>8; + if (s->pict_type != AV_PICTURE_TYPE_B) { + if((s->avctx->pre_me && s->last_non_b_pict_type==AV_PICTURE_TYPE_I) || s->avctx->pre_me==2){ + s->avctx->execute(s->avctx, pre_estimate_motion_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); + } + } + + s->avctx->execute(s->avctx, estimate_motion_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); + }else /* if(s->pict_type == AV_PICTURE_TYPE_I) */{ + /* I-Frame */ + for(i=0; imb_stride*s->mb_height; i++) + s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; + + if(!s->fixed_qscale){ + /* finding spatial complexity for I-frame rate control */ + s->avctx->execute(s->avctx, mb_var_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); + } + } + for(i=1; ithread_context[i]); + } + s->current_picture.mc_mb_var_sum= s->current_picture_ptr->mc_mb_var_sum= s->me.mc_mb_var_sum_temp; + s->current_picture. mb_var_sum= s->current_picture_ptr-> mb_var_sum= s->me. mb_var_sum_temp; + emms_c(); + + if(s->me.scene_change_score > s->avctx->scenechange_threshold && s->pict_type == AV_PICTURE_TYPE_P){ + s->pict_type= AV_PICTURE_TYPE_I; + for(i=0; imb_stride*s->mb_height; i++) + s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; + if(s->msmpeg4_version >= 3) + s->no_rounding=1; + av_dlog(s, "Scene change detected, encoding as I Frame %d %d\n", + s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); + } + + if(!s->umvplus){ + if(s->pict_type==AV_PICTURE_TYPE_P || s->pict_type==AV_PICTURE_TYPE_S) { + s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER); + + if(s->flags & CODEC_FLAG_INTERLACED_ME){ + int a,b; + a= ff_get_best_fcode(s, s->p_field_mv_table[0][0], CANDIDATE_MB_TYPE_INTER_I); //FIXME field_select + b= ff_get_best_fcode(s, s->p_field_mv_table[1][1], CANDIDATE_MB_TYPE_INTER_I); + s->f_code= FFMAX3(s->f_code, a, b); + } + + ff_fix_long_p_mvs(s); + ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, 0); + if(s->flags & CODEC_FLAG_INTERLACED_ME){ + int j; + for(i=0; i<2; i++){ + for(j=0; j<2; j++) + ff_fix_long_mvs(s, s->p_field_select_table[i], j, + s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, 0); + } + } + } + + if(s->pict_type==AV_PICTURE_TYPE_B){ + int a, b; + + a = ff_get_best_fcode(s, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); + b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, CANDIDATE_MB_TYPE_BIDIR); + s->f_code = FFMAX(a, b); + + a = ff_get_best_fcode(s, s->b_back_mv_table, CANDIDATE_MB_TYPE_BACKWARD); + b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, CANDIDATE_MB_TYPE_BIDIR); + s->b_code = FFMAX(a, b); + + ff_fix_long_mvs(s, NULL, 0, s->b_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_FORWARD, 1); + ff_fix_long_mvs(s, NULL, 0, s->b_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BACKWARD, 1); + ff_fix_long_mvs(s, NULL, 0, s->b_bidir_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_BIDIR, 1); + ff_fix_long_mvs(s, NULL, 0, s->b_bidir_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BIDIR, 1); + if(s->flags & CODEC_FLAG_INTERLACED_ME){ + int dir, j; + for(dir=0; dir<2; dir++){ + for(i=0; i<2; i++){ + for(j=0; j<2; j++){ + int type= dir ? (CANDIDATE_MB_TYPE_BACKWARD_I|CANDIDATE_MB_TYPE_BIDIR_I) + : (CANDIDATE_MB_TYPE_FORWARD_I |CANDIDATE_MB_TYPE_BIDIR_I); + ff_fix_long_mvs(s, s->b_field_select_table[dir][i], j, + s->b_field_mv_table[dir][i][j], dir ? s->b_code : s->f_code, type, 1); + } + } + } + } + } + } + + if (estimate_qp(s, 0) < 0) + return -1; + + if(s->qscale < 3 && s->max_qcoeff<=128 && s->pict_type==AV_PICTURE_TYPE_I && !(s->flags & CODEC_FLAG_QSCALE)) + s->qscale= 3; //reduce clipping problems + + if (s->out_format == FMT_MJPEG) { + /* for mjpeg, we do include qscale in the matrix */ + for(i=1;i<64;i++){ + int j= s->dsp.idct_permutation[i]; + + s->intra_matrix[j] = av_clip_uint8((ff_mpeg1_default_intra_matrix[i] * s->qscale) >> 3); + } + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg2_dc_scale_table[s->intra_dc_precision]; + s->intra_matrix[0] = ff_mpeg2_dc_scale_table[s->intra_dc_precision][8]; + ff_convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + s->intra_matrix, s->intra_quant_bias, 8, 8, 1); + s->qscale= 8; + } + if(s->codec_id == AV_CODEC_ID_AMV){ + static const uint8_t y[32]={13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; + static const uint8_t c[32]={14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; + for(i=1;i<64;i++){ + int j= s->dsp.idct_permutation[ff_zigzag_direct[i]]; + + s->intra_matrix[j] = sp5x_quant_table[5*2+0][i]; + s->chroma_intra_matrix[j] = sp5x_quant_table[5*2+1][i]; + } + s->y_dc_scale_table= y; + s->c_dc_scale_table= c; + s->intra_matrix[0] = 13; + s->chroma_intra_matrix[0] = 14; + ff_convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + s->intra_matrix, s->intra_quant_bias, 8, 8, 1); + ff_convert_matrix(&s->dsp, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, + s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); + s->qscale= 8; + } + + //FIXME var duplication + s->current_picture_ptr->f.key_frame = + s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; //FIXME pic_ptr + s->current_picture_ptr->f.pict_type = + s->current_picture.f.pict_type = s->pict_type; + + if (s->current_picture.f.key_frame) + s->picture_in_gop_number=0; + + s->mb_x = s->mb_y = 0; + s->last_bits= put_bits_count(&s->pb); + switch(s->out_format) { + case FMT_MJPEG: + if (CONFIG_MJPEG_ENCODER) + ff_mjpeg_encode_picture_header(s); + break; + case FMT_H261: + if (CONFIG_H261_ENCODER) + ff_h261_encode_picture_header(s, picture_number); + break; + case FMT_H263: + if (CONFIG_WMV2_ENCODER && s->codec_id == AV_CODEC_ID_WMV2) + ff_wmv2_encode_picture_header(s, picture_number); + else if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) + ff_msmpeg4_encode_picture_header(s, picture_number); + else if (CONFIG_MPEG4_ENCODER && s->h263_pred) + ff_mpeg4_encode_picture_header(s, picture_number); + else if (CONFIG_RV10_ENCODER && s->codec_id == AV_CODEC_ID_RV10) + ff_rv10_encode_picture_header(s, picture_number); + else if (CONFIG_RV20_ENCODER && s->codec_id == AV_CODEC_ID_RV20) + ff_rv20_encode_picture_header(s, picture_number); + else if (CONFIG_FLV_ENCODER && s->codec_id == AV_CODEC_ID_FLV1) + ff_flv_encode_picture_header(s, picture_number); + else if (CONFIG_H263_ENCODER) + ff_h263_encode_picture_header(s, picture_number); + break; + case FMT_MPEG1: + if (CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) + ff_mpeg1_encode_picture_header(s, picture_number); + break; + default: + av_assert0(0); + } + bits= put_bits_count(&s->pb); + s->header_bits= bits - s->last_bits; + + for(i=1; ithread_context[i], s); + } + s->avctx->execute(s->avctx, encode_thread, &s->thread_context[0], NULL, context_count, sizeof(void*)); + for(i=1; ithread_context[i]); + } + emms_c(); + return 0; +} + +static void denoise_dct_c(MpegEncContext *s, int16_t *block){ + const int intra= s->mb_intra; + int i; + + s->dct_count[intra]++; + + for(i=0; i<64; i++){ + int level= block[i]; + + if(level){ + if(level>0){ + s->dct_error_sum[intra][i] += level; + level -= s->dct_offset[intra][i]; + if(level<0) level=0; + }else{ + s->dct_error_sum[intra][i] -= level; + level += s->dct_offset[intra][i]; + if(level>0) level=0; + } + block[i]= level; + } + } +} + +static int dct_quantize_trellis_c(MpegEncContext *s, + int16_t *block, int n, + int qscale, int *overflow){ + const int *qmat; + const uint8_t *scantable= s->intra_scantable.scantable; + const uint8_t *perm_scantable= s->intra_scantable.permutated; + int max=0; + unsigned int threshold1, threshold2; + int bias=0; + int run_tab[65]; + int level_tab[65]; + int score_tab[65]; + int survivor[65]; + int survivor_count; + int last_run=0; + int last_level=0; + int last_score= 0; + int last_i; + int coeff[2][64]; + int coeff_count[64]; + int qmul, qadd, start_i, last_non_zero, i, dc; + const int esc_length= s->ac_esc_length; + uint8_t * length; + uint8_t * last_length; + const int lambda= s->lambda2 >> (FF_LAMBDA_SHIFT - 6); + + s->dsp.fdct (block); + + if(s->dct_error_sum) + s->denoise_dct(s, block); + qmul= qscale*16; + qadd= ((qscale-1)|1)*8; + + if (s->mb_intra) { + int q; + if (!s->h263_aic) { + if (n < 4) + q = s->y_dc_scale; + else + q = s->c_dc_scale; + q = q << 3; + } else{ + /* For AIC we skip quant/dequant of INTRADC */ + q = 1 << 3; + qadd=0; + } + + /* note: block[0] is assumed to be positive */ + block[0] = (block[0] + (q >> 1)) / q; + start_i = 1; + last_non_zero = 0; + qmat = n < 4 ? s->q_intra_matrix[qscale] : s->q_chroma_intra_matrix[qscale]; + if(s->mpeg_quant || s->out_format == FMT_MPEG1) + bias= 1<<(QMAT_SHIFT-1); + length = s->intra_ac_vlc_length; + last_length= s->intra_ac_vlc_last_length; + } else { + start_i = 0; + last_non_zero = -1; + qmat = s->q_inter_matrix[qscale]; + length = s->inter_ac_vlc_length; + last_length= s->inter_ac_vlc_last_length; + } + last_i= start_i; + + threshold1= (1<=start_i; i--) { + const int j = scantable[i]; + int level = block[j] * qmat[j]; + + if(((unsigned)(level+threshold1))>threshold2){ + last_non_zero = i; + break; + } + } + + for(i=start_i; i<=last_non_zero; i++) { + const int j = scantable[i]; + int level = block[j] * qmat[j]; + +// if( bias+level >= (1<<(QMAT_SHIFT - 3)) +// || bias-level >= (1<<(QMAT_SHIFT - 3))){ + if(((unsigned)(level+threshold1))>threshold2){ + if(level>0){ + level= (bias + level)>>QMAT_SHIFT; + coeff[0][i]= level; + coeff[1][i]= level-1; +// coeff[2][k]= level-2; + }else{ + level= (bias - level)>>QMAT_SHIFT; + coeff[0][i]= -level; + coeff[1][i]= -level+1; +// coeff[2][k]= -level+2; + } + coeff_count[i]= FFMIN(level, 2); + av_assert2(coeff_count[i]); + max |=level; + }else{ + coeff[0][i]= (level>>31)|1; + coeff_count[i]= 1; + } + } + + *overflow= s->max_qcoeff < max; //overflow might have happened + + if(last_non_zero < start_i){ + memset(block + start_i, 0, (64-start_i)*sizeof(int16_t)); + return last_non_zero; + } + + score_tab[start_i]= 0; + survivor[0]= start_i; + survivor_count= 1; + + for(i=start_i; i<=last_non_zero; i++){ + int level_index, j, zero_distortion; + int dct_coeff= FFABS(block[ scantable[i] ]); + int best_score=256*256*256*120; + + if (s->dsp.fdct == ff_fdct_ifast) + dct_coeff= (dct_coeff*ff_inv_aanscales[ scantable[i] ]) >> 12; + zero_distortion= dct_coeff*dct_coeff; + + for(level_index=0; level_index < coeff_count[i]; level_index++){ + int distortion; + int level= coeff[level_index][i]; + const int alevel= FFABS(level); + int unquant_coeff; + + av_assert2(level); + + if(s->out_format == FMT_H263){ + unquant_coeff= alevel*qmul + qadd; + }else{ //MPEG1 + j= s->dsp.idct_permutation[ scantable[i] ]; //FIXME optimize + if(s->mb_intra){ + unquant_coeff = (int)( alevel * qscale * s->intra_matrix[j]) >> 3; + unquant_coeff = (unquant_coeff - 1) | 1; + }else{ + unquant_coeff = ((( alevel << 1) + 1) * qscale * ((int) s->inter_matrix[j])) >> 4; + unquant_coeff = (unquant_coeff - 1) | 1; + } + unquant_coeff<<= 3; + } + + distortion= (unquant_coeff - dct_coeff) * (unquant_coeff - dct_coeff) - zero_distortion; + level+=64; + if((level&(~127)) == 0){ + for(j=survivor_count-1; j>=0; j--){ + int run= i - survivor[j]; + int score= distortion + length[UNI_AC_ENC_INDEX(run, level)]*lambda; + score += score_tab[i-run]; + + if(score < best_score){ + best_score= score; + run_tab[i+1]= run; + level_tab[i+1]= level-64; + } + } + + if(s->out_format == FMT_H263){ + for(j=survivor_count-1; j>=0; j--){ + int run= i - survivor[j]; + int score= distortion + last_length[UNI_AC_ENC_INDEX(run, level)]*lambda; + score += score_tab[i-run]; + if(score < last_score){ + last_score= score; + last_run= run; + last_level= level-64; + last_i= i+1; + } + } + } + }else{ + distortion += esc_length*lambda; + for(j=survivor_count-1; j>=0; j--){ + int run= i - survivor[j]; + int score= distortion + score_tab[i-run]; + + if(score < best_score){ + best_score= score; + run_tab[i+1]= run; + level_tab[i+1]= level-64; + } + } + + if(s->out_format == FMT_H263){ + for(j=survivor_count-1; j>=0; j--){ + int run= i - survivor[j]; + int score= distortion + score_tab[i-run]; + if(score < last_score){ + last_score= score; + last_run= run; + last_level= level-64; + last_i= i+1; + } + } + } + } + } + + score_tab[i+1]= best_score; + + //Note: there is a vlc code in mpeg4 which is 1 bit shorter then another one with a shorter run and the same level + if(last_non_zero <= 27){ + for(; survivor_count; survivor_count--){ + if(score_tab[ survivor[survivor_count-1] ] <= best_score) + break; + } + }else{ + for(; survivor_count; survivor_count--){ + if(score_tab[ survivor[survivor_count-1] ] <= best_score + lambda) + break; + } + } + + survivor[ survivor_count++ ]= i+1; + } + + if(s->out_format != FMT_H263){ + last_score= 256*256*256*120; + for(i= survivor[0]; i<=last_non_zero + 1; i++){ + int score= score_tab[i]; + if(i) score += lambda*2; //FIXME exacter? + + if(score < last_score){ + last_score= score; + last_i= i; + last_level= level_tab[i]; + last_run= run_tab[i]; + } + } + } + + s->coded_score[n] = last_score; + + dc= FFABS(block[0]); + last_non_zero= last_i - 1; + memset(block + start_i, 0, (64-start_i)*sizeof(int16_t)); + + if(last_non_zero < start_i) + return last_non_zero; + + if(last_non_zero == 0 && start_i == 0){ + int best_level= 0; + int best_score= dc * dc; + + for(i=0; iout_format == FMT_H263){ + unquant_coeff= (alevel*qmul + qadd)>>3; + }else{ //MPEG1 + unquant_coeff = ((( alevel << 1) + 1) * qscale * ((int) s->inter_matrix[0])) >> 4; + unquant_coeff = (unquant_coeff - 1) | 1; + } + unquant_coeff = (unquant_coeff + 4) >> 3; + unquant_coeff<<= 3 + 3; + + distortion= (unquant_coeff - dc) * (unquant_coeff - dc); + level+=64; + if((level&(~127)) == 0) score= distortion + last_length[UNI_AC_ENC_INDEX(0, level)]*lambda; + else score= distortion + esc_length*lambda; + + if(score < best_score){ + best_score= score; + best_level= level - 64; + } + } + block[0]= best_level; + s->coded_score[n] = best_score - dc*dc; + if(best_level == 0) return -1; + else return last_non_zero; + } + + i= last_i; + av_assert2(last_level); + + block[ perm_scantable[last_non_zero] ]= last_level; + i -= last_run + 1; + + for(; i>start_i; i -= run_tab[i] + 1){ + block[ perm_scantable[i-1] ]= level_tab[i]; + } + + return last_non_zero; +} + +//#define REFINE_STATS 1 +static int16_t basis[64][64]; + +static void build_basis(uint8_t *perm){ + int i, j, x, y; + emms_c(); + for(i=0; i<8; i++){ + for(j=0; j<8; j++){ + for(y=0; y<8; y++){ + for(x=0; x<8; x++){ + double s= 0.25*(1<intra_scantable.scantable; + const uint8_t *perm_scantable= s->intra_scantable.permutated; +// unsigned int threshold1, threshold2; +// int bias=0; + int run_tab[65]; + int prev_run=0; + int prev_level=0; + int qmul, qadd, start_i, last_non_zero, i, dc; + uint8_t * length; + uint8_t * last_length; + int lambda; + int rle_index, run, q = 1, sum; //q is only used when s->mb_intra is true +#ifdef REFINE_STATS +static int count=0; +static int after_last=0; +static int to_zero=0; +static int from_zero=0; +static int raise=0; +static int lower=0; +static int messed_sign=0; +#endif + + if(basis[0][0] == 0) + build_basis(s->dsp.idct_permutation); + + qmul= qscale*2; + qadd= (qscale-1)|1; + if (s->mb_intra) { + if (!s->h263_aic) { + if (n < 4) + q = s->y_dc_scale; + else + q = s->c_dc_scale; + } else{ + /* For AIC we skip quant/dequant of INTRADC */ + q = 1; + qadd=0; + } + q <<= RECON_SHIFT-3; + /* note: block[0] is assumed to be positive */ + dc= block[0]*q; +// block[0] = (block[0] + (q >> 1)) / q; + start_i = 1; +// if(s->mpeg_quant || s->out_format == FMT_MPEG1) +// bias= 1<<(QMAT_SHIFT-1); + length = s->intra_ac_vlc_length; + last_length= s->intra_ac_vlc_last_length; + } else { + dc= 0; + start_i = 0; + length = s->inter_ac_vlc_length; + last_length= s->inter_ac_vlc_last_length; + } + last_non_zero = s->block_last_index[n]; + +#ifdef REFINE_STATS +{START_TIMER +#endif + dc += (1<<(RECON_SHIFT-1)); + for(i=0; i<64; i++){ + rem[i]= dc - (orig[i]<0); + av_assert2(w<(1<<6)); + sum += w*w; + } + lambda= sum*(uint64_t)s->lambda2 >> (FF_LAMBDA_SHIFT - 6 + 6 + 6 + 6); +#ifdef REFINE_STATS +{START_TIMER +#endif + run=0; + rle_index=0; + for(i=start_i; i<=last_non_zero; i++){ + int j= perm_scantable[i]; + const int level= block[j]; + int coeff; + + if(level){ + if(level<0) coeff= qmul*level - qadd; + else coeff= qmul*level + qadd; + run_tab[rle_index++]=run; + run=0; + + s->dsp.add_8x8basis(rem, basis[j], coeff); + }else{ + run++; + } + } +#ifdef REFINE_STATS +if(last_non_zero>0){ +STOP_TIMER("init rem[]") +} +} + +{START_TIMER +#endif + for(;;){ + int best_score=s->dsp.try_8x8basis(rem, weight, basis[0], 0); + int best_coeff=0; + int best_change=0; + int run2, best_unquant_change=0, analyze_gradient; +#ifdef REFINE_STATS +{START_TIMER +#endif + analyze_gradient = last_non_zero > 2 || s->quantizer_noise_shaping >= 3; + + if(analyze_gradient){ +#ifdef REFINE_STATS +{START_TIMER +#endif + for(i=0; i<64; i++){ + int w= weight[i]; + + d1[i] = (rem[i]*w*w + (1<<(RECON_SHIFT+12-1)))>>(RECON_SHIFT+12); + } +#ifdef REFINE_STATS +STOP_TIMER("rem*w*w")} +{START_TIMER +#endif + s->dsp.fdct(d1); +#ifdef REFINE_STATS +STOP_TIMER("dct")} +#endif + } + + if(start_i){ + const int level= block[0]; + int change, old_coeff; + + av_assert2(s->mb_intra); + + old_coeff= q*level; + + for(change=-1; change<=1; change+=2){ + int new_level= level + change; + int score, new_coeff; + + new_coeff= q*new_level; + if(new_coeff >= 2048 || new_coeff < 0) + continue; + + score= s->dsp.try_8x8basis(rem, weight, basis[0], new_coeff - old_coeff); + if(scorequantizer_noise_shaping < 3 && i > last_non_zero + 1) + break; + + if(level){ + if(level<0) old_coeff= qmul*level - qadd; + else old_coeff= qmul*level + qadd; + run2= run_tab[rle_index++]; //FIXME ! maybe after last + }else{ + old_coeff=0; + run2--; + av_assert2(run2>=0 || i >= last_non_zero ); + } + + for(change=-1; change<=1; change+=2){ + int new_level= level + change; + int score, new_coeff, unquant_change; + + score=0; + if(s->quantizer_noise_shaping < 2 && FFABS(new_level) > FFABS(level)) + continue; + + if(new_level){ + if(new_level<0) new_coeff= qmul*new_level - qadd; + else new_coeff= qmul*new_level + qadd; + if(new_coeff >= 2048 || new_coeff <= -2048) + continue; + //FIXME check for overflow + + if(level){ + if(level < 63 && level > -63){ + if(i < last_non_zero) + score += length[UNI_AC_ENC_INDEX(run, new_level+64)] + - length[UNI_AC_ENC_INDEX(run, level+64)]; + else + score += last_length[UNI_AC_ENC_INDEX(run, new_level+64)] + - last_length[UNI_AC_ENC_INDEX(run, level+64)]; + } + }else{ + av_assert2(FFABS(new_level)==1); + + if(analyze_gradient){ + int g= d1[ scantable[i] ]; + if(g && (g^new_level) >= 0) + continue; + } + + if(i < last_non_zero){ + int next_i= i + run2 + 1; + int next_level= block[ perm_scantable[next_i] ] + 64; + + if(next_level&(~127)) + next_level= 0; + + if(next_i < last_non_zero) + score += length[UNI_AC_ENC_INDEX(run, 65)] + + length[UNI_AC_ENC_INDEX(run2, next_level)] + - length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)]; + else + score += length[UNI_AC_ENC_INDEX(run, 65)] + + last_length[UNI_AC_ENC_INDEX(run2, next_level)] + - last_length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)]; + }else{ + score += last_length[UNI_AC_ENC_INDEX(run, 65)]; + if(prev_level){ + score += length[UNI_AC_ENC_INDEX(prev_run, prev_level)] + - last_length[UNI_AC_ENC_INDEX(prev_run, prev_level)]; + } + } + } + }else{ + new_coeff=0; + av_assert2(FFABS(level)==1); + + if(i < last_non_zero){ + int next_i= i + run2 + 1; + int next_level= block[ perm_scantable[next_i] ] + 64; + + if(next_level&(~127)) + next_level= 0; + + if(next_i < last_non_zero) + score += length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)] + - length[UNI_AC_ENC_INDEX(run2, next_level)] + - length[UNI_AC_ENC_INDEX(run, 65)]; + else + score += last_length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)] + - last_length[UNI_AC_ENC_INDEX(run2, next_level)] + - length[UNI_AC_ENC_INDEX(run, 65)]; + }else{ + score += -last_length[UNI_AC_ENC_INDEX(run, 65)]; + if(prev_level){ + score += last_length[UNI_AC_ENC_INDEX(prev_run, prev_level)] + - length[UNI_AC_ENC_INDEX(prev_run, prev_level)]; + } + } + } + + score *= lambda; + + unquant_change= new_coeff - old_coeff; + av_assert2((score < 100*lambda && score > -100*lambda) || lambda==0); + + score+= s->dsp.try_8x8basis(rem, weight, basis[j], unquant_change); + if(score last_non_zero){ + last_non_zero= best_coeff; + av_assert2(block[j]); +#ifdef REFINE_STATS +after_last++; +#endif + }else{ +#ifdef REFINE_STATS +if(block[j]){ + if(block[j] - best_change){ + if(FFABS(block[j]) > FFABS(block[j] - best_change)){ + raise++; + }else{ + lower++; + } + }else{ + from_zero++; + } +}else{ + to_zero++; +} +#endif + for(; last_non_zero>=start_i; last_non_zero--){ + if(block[perm_scantable[last_non_zero]]) + break; + } + } +#ifdef REFINE_STATS +count++; +if(256*256*256*64 % count == 0){ + av_log(s->avctx, AV_LOG_DEBUG, "after_last:%d to_zero:%d from_zero:%d raise:%d lower:%d sign:%d xyp:%d/%d/%d\n", after_last, to_zero, from_zero, raise, lower, messed_sign, s->mb_x, s->mb_y, s->picture_number); +} +#endif + run=0; + rle_index=0; + for(i=start_i; i<=last_non_zero; i++){ + int j= perm_scantable[i]; + const int level= block[j]; + + if(level){ + run_tab[rle_index++]=run; + run=0; + }else{ + run++; + } + } + + s->dsp.add_8x8basis(rem, basis[j], best_unquant_change); + }else{ + break; + } + } +#ifdef REFINE_STATS +if(last_non_zero>0){ +STOP_TIMER("iterative search") +} +} +#endif + + return last_non_zero; +} + +int ff_dct_quantize_c(MpegEncContext *s, + int16_t *block, int n, + int qscale, int *overflow) +{ + int i, j, level, last_non_zero, q, start_i; + const int *qmat; + const uint8_t *scantable= s->intra_scantable.scantable; + int bias; + int max=0; + unsigned int threshold1, threshold2; + + s->dsp.fdct (block); + + if(s->dct_error_sum) + s->denoise_dct(s, block); + + if (s->mb_intra) { + if (!s->h263_aic) { + if (n < 4) + q = s->y_dc_scale; + else + q = s->c_dc_scale; + q = q << 3; + } else + /* For AIC we skip quant/dequant of INTRADC */ + q = 1 << 3; + + /* note: block[0] is assumed to be positive */ + block[0] = (block[0] + (q >> 1)) / q; + start_i = 1; + last_non_zero = 0; + qmat = n < 4 ? s->q_intra_matrix[qscale] : s->q_chroma_intra_matrix[qscale]; + bias= s->intra_quant_bias<<(QMAT_SHIFT - QUANT_BIAS_SHIFT); + } else { + start_i = 0; + last_non_zero = -1; + qmat = s->q_inter_matrix[qscale]; + bias= s->inter_quant_bias<<(QMAT_SHIFT - QUANT_BIAS_SHIFT); + } + threshold1= (1<=start_i;i--) { + j = scantable[i]; + level = block[j] * qmat[j]; + + if(((unsigned)(level+threshold1))>threshold2){ + last_non_zero = i; + break; + }else{ + block[j]=0; + } + } + for(i=start_i; i<=last_non_zero; i++) { + j = scantable[i]; + level = block[j] * qmat[j]; + +// if( bias+level >= (1<= (1<threshold2){ + if(level>0){ + level= (bias + level)>>QMAT_SHIFT; + block[j]= level; + }else{ + level= (bias - level)>>QMAT_SHIFT; + block[j]= -level; + } + max |=level; + }else{ + block[j]=0; + } + } + *overflow= s->max_qcoeff < max; //overflow might have happened + + /* we need this permutation so that we correct the IDCT, we only permute the !=0 elements */ + if (s->dsp.idct_permutation_type != FF_NO_IDCT_PERM) + ff_block_permute(block, s->dsp.idct_permutation, scantable, last_non_zero); + + return last_non_zero; +} + +#define OFFSET(x) offsetof(MpegEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption h263_options[] = { + { "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "structured_slices","Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "mb_info", "emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size", OFFSET(mb_info), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + FF_MPV_COMMON_OPTS + { NULL }, +}; + +static const AVClass h263_class = { + .class_name = "H.263 encoder", + .item_name = av_default_item_name, + .option = h263_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h263_encoder = { + .name = "h263", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts= (const enum AVPixelFormat[]){AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, + .long_name= NULL_IF_CONFIG_SMALL("H.263 / H.263-1996"), + .priv_class = &h263_class, +}; + +static const AVOption h263p_options[] = { + { "umv", "Use unlimited motion vectors.", OFFSET(umvplus), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "aiv", "Use alternative inter VLC.", OFFSET(alt_inter_vlc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "structured_slices", "Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + FF_MPV_COMMON_OPTS + { NULL }, +}; +static const AVClass h263p_class = { + .class_name = "H.263p encoder", + .item_name = av_default_item_name, + .option = h263p_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_h263p_encoder = { + .name = "h263p", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263P, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .capabilities = CODEC_CAP_SLICE_THREADS, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"), + .priv_class = &h263p_class, +}; + +FF_MPV_GENERIC_CLASS(msmpeg4v2) + +AVCodec ff_msmpeg4v2_encoder = { + .name = "msmpeg4v2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSMPEG4V2, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), + .priv_class = &msmpeg4v2_class, +}; + +FF_MPV_GENERIC_CLASS(msmpeg4v3) + +AVCodec ff_msmpeg4v3_encoder = { + .name = "msmpeg4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSMPEG4V3, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), + .priv_class = &msmpeg4v3_class, +}; + +FF_MPV_GENERIC_CLASS(wmv1) + +AVCodec ff_wmv1_encoder = { + .name = "wmv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV1, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), + .priv_class = &wmv1_class, +}; diff --git a/ffmpeg/libavcodec/mpegvideo_motion.c b/ffmpeg/libavcodec/mpegvideo_motion.c new file mode 100644 index 0000000..beb4d6c --- /dev/null +++ b/ffmpeg/libavcodec/mpegvideo_motion.c @@ -0,0 +1,894 @@ +/* + * 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 "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "mjpegenc.h" +#include "msmpeg4.h" +#include + +static void gmc1_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture) +{ + uint8_t *ptr; + int offset, src_x, src_y, linesize, uvlinesize; + int motion_x, motion_y; + int emu=0; + + motion_x= s->sprite_offset[0][0]; + motion_y= s->sprite_offset[0][1]; + src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy+1)); + src_y = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy+1)); + motion_x<<=(3-s->sprite_warping_accuracy); + motion_y<<=(3-s->sprite_warping_accuracy); + src_x = av_clip(src_x, -16, s->width); + if (src_x == s->width) + motion_x =0; + src_y = av_clip(src_y, -16, s->height); + if (src_y == s->height) + motion_y =0; + + linesize = s->linesize; + uvlinesize = s->uvlinesize; + + ptr = ref_picture[0] + (src_y * linesize) + src_x; + + if(s->flags&CODEC_FLAG_EMU_EDGE){ + if( (unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) + || (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, linesize, 17, 17, src_x, src_y, s->h_edge_pos, s->v_edge_pos); + ptr= s->edge_emu_buffer; + } + } + + if((motion_x|motion_y)&7){ + s->dsp.gmc1(dest_y , ptr , linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding); + s->dsp.gmc1(dest_y+8, ptr+8, linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding); + }else{ + int dxy; + + dxy= ((motion_x>>3)&1) | ((motion_y>>2)&2); + if (s->no_rounding){ + s->hdsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16); + }else{ + s->hdsp.put_pixels_tab [0][dxy](dest_y, ptr, linesize, 16); + } + } + + if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return; + + motion_x= s->sprite_offset[1][0]; + motion_y= s->sprite_offset[1][1]; + src_x = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy+1)); + src_y = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy+1)); + motion_x<<=(3-s->sprite_warping_accuracy); + motion_y<<=(3-s->sprite_warping_accuracy); + src_x = av_clip(src_x, -8, s->width>>1); + if (src_x == s->width>>1) + motion_x =0; + src_y = av_clip(src_y, -8, s->height>>1); + if (src_y == s->height>>1) + motion_y =0; + + offset = (src_y * uvlinesize) + src_x; + ptr = ref_picture[1] + offset; + if(s->flags&CODEC_FLAG_EMU_EDGE){ + if( (unsigned)src_x >= FFMAX((s->h_edge_pos>>1) - 9, 0) + || (unsigned)src_y >= FFMAX((s->v_edge_pos>>1) - 9, 0)){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr= s->edge_emu_buffer; + emu=1; + } + } + s->dsp.gmc1(dest_cb, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); + + ptr = ref_picture[2] + offset; + if(emu){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr= s->edge_emu_buffer; + } + s->dsp.gmc1(dest_cr, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); + + return; +} + +static void gmc_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture) +{ + uint8_t *ptr; + int linesize, uvlinesize; + const int a= s->sprite_warping_accuracy; + int ox, oy; + + linesize = s->linesize; + uvlinesize = s->uvlinesize; + + ptr = ref_picture[0]; + + ox= s->sprite_offset[0][0] + s->sprite_delta[0][0]*s->mb_x*16 + s->sprite_delta[0][1]*s->mb_y*16; + oy= s->sprite_offset[0][1] + s->sprite_delta[1][0]*s->mb_x*16 + s->sprite_delta[1][1]*s->mb_y*16; + + s->dsp.gmc(dest_y, ptr, linesize, 16, + ox, + oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos, s->v_edge_pos); + s->dsp.gmc(dest_y+8, ptr, linesize, 16, + ox + s->sprite_delta[0][0]*8, + oy + s->sprite_delta[1][0]*8, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos, s->v_edge_pos); + + if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return; + + ox= s->sprite_offset[1][0] + s->sprite_delta[0][0]*s->mb_x*8 + s->sprite_delta[0][1]*s->mb_y*8; + oy= s->sprite_offset[1][1] + s->sprite_delta[1][0]*s->mb_x*8 + s->sprite_delta[1][1]*s->mb_y*8; + + ptr = ref_picture[1]; + s->dsp.gmc(dest_cb, ptr, uvlinesize, 8, + ox, + oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos>>1, s->v_edge_pos>>1); + + ptr = ref_picture[2]; + s->dsp.gmc(dest_cr, ptr, uvlinesize, 8, + ox, + oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos>>1, s->v_edge_pos>>1); +} + +static inline int hpel_motion(MpegEncContext *s, + uint8_t *dest, uint8_t *src, + int src_x, int src_y, + op_pixels_func *pix_op, + int motion_x, int motion_y) +{ + int dxy = 0; + int emu=0; + + src_x += motion_x >> 1; + src_y += motion_y >> 1; + + /* WARNING: do no forget half pels */ + src_x = av_clip(src_x, -16, s->width); //FIXME unneeded for emu? + if (src_x != s->width) + dxy |= motion_x & 1; + src_y = av_clip(src_y, -16, s->height); + if (src_y != s->height) + dxy |= (motion_y & 1) << 1; + src += src_y * s->linesize + src_x; + + if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){ + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 8, 0) + || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&1) - 8, 0)){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, 9, 9, + src_x, src_y, s->h_edge_pos, s->v_edge_pos); + src= s->edge_emu_buffer; + emu=1; + } + } + pix_op[dxy](dest, src, s->linesize, 8); + return emu; +} + +static av_always_inline +void mpeg_motion_internal(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + int field_based, int bottom_field, int field_select, + uint8_t **ref_picture, op_pixels_func (*pix_op)[4], + int motion_x, int motion_y, int h, int is_mpeg12, int mb_y) +{ + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int dxy, uvdxy, mx, my, src_x, src_y, + uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize; + +#if 0 +if(s->quarter_sample) +{ + motion_x>>=1; + motion_y>>=1; +} +#endif + + v_edge_pos = s->v_edge_pos >> field_based; + linesize = s->current_picture.f.linesize[0] << field_based; + uvlinesize = s->current_picture.f.linesize[1] << field_based; + + dxy = ((motion_y & 1) << 1) | (motion_x & 1); + src_x = s->mb_x* 16 + (motion_x >> 1); + src_y =( mb_y<<(4-field_based)) + (motion_y >> 1); + + if (!is_mpeg12 && s->out_format == FMT_H263) { + if((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based){ + mx = (motion_x>>1)|(motion_x&1); + my = motion_y >>1; + uvdxy = ((my & 1) << 1) | (mx & 1); + uvsrc_x = s->mb_x* 8 + (mx >> 1); + uvsrc_y =( mb_y<<(3-field_based))+ (my >> 1); + }else{ + uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1); + uvsrc_x = src_x>>1; + uvsrc_y = src_y>>1; + } + }else if(!is_mpeg12 && s->out_format == FMT_H261){//even chroma mv's are full pel in H261 + mx = motion_x / 4; + my = motion_y / 4; + uvdxy = 0; + uvsrc_x = s->mb_x*8 + mx; + uvsrc_y = mb_y*8 + my; + } else { + if(s->chroma_y_shift){ + mx = motion_x / 2; + my = motion_y / 2; + uvdxy = ((my & 1) << 1) | (mx & 1); + uvsrc_x = s->mb_x* 8 + (mx >> 1); + uvsrc_y =( mb_y<<(3-field_based))+ (my >> 1); + } else { + if(s->chroma_x_shift){ + //Chroma422 + mx = motion_x / 2; + uvdxy = ((motion_y & 1) << 1) | (mx & 1); + uvsrc_x = s->mb_x* 8 + (mx >> 1); + uvsrc_y = src_y; + } else { + //Chroma444 + uvdxy = dxy; + uvsrc_x = src_x; + uvsrc_y = src_y; + } + } + } + + ptr_y = ref_picture[0] + src_y * linesize + src_x; + ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; + ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; + + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 16, 0) + || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&1) - h , 0)){ + if(is_mpeg12 || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || + s->codec_id == AV_CODEC_ID_MPEG1VIDEO){ + av_log(s->avctx,AV_LOG_DEBUG, + "MPEG motion vector out of boundary (%d %d)\n", src_x, src_y); + return; + } + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, + 17, 17+field_based, + src_x, src_y<h_edge_pos, s->v_edge_pos); + ptr_y = s->edge_emu_buffer; + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize; + s->vdsp.emulated_edge_mc(uvbuf , + ptr_cb, s->uvlinesize, + 9, 9+field_based, + uvsrc_x, uvsrc_y<h_edge_pos>>1, s->v_edge_pos>>1); + s->vdsp.emulated_edge_mc(uvbuf+16, + ptr_cr, s->uvlinesize, + 9, 9+field_based, + uvsrc_x, uvsrc_y<h_edge_pos>>1, s->v_edge_pos>>1); + ptr_cb= uvbuf; + ptr_cr= uvbuf+16; + } + } + + if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data + dest_y += s->linesize; + dest_cb+= s->uvlinesize; + dest_cr+= s->uvlinesize; + } + + if(field_select){ + ptr_y += s->linesize; + ptr_cb+= s->uvlinesize; + ptr_cr+= s->uvlinesize; + } + + pix_op[0][dxy](dest_y, ptr_y, linesize, h); + + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + pix_op[s->chroma_x_shift][uvdxy] + (dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift); + pix_op[s->chroma_x_shift][uvdxy] + (dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift); + } + if(!is_mpeg12 && (CONFIG_H261_ENCODER || CONFIG_H261_DECODER) && + s->out_format == FMT_H261){ + ff_h261_loop_filter(s); + } +} +/* apply one mpeg motion vector to the three components */ +static void mpeg_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + int field_select, uint8_t **ref_picture, + op_pixels_func (*pix_op)[4], + int motion_x, int motion_y, int h, int mb_y) +{ +#if !CONFIG_SMALL + if(s->out_format == FMT_MPEG1) + mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0, + field_select, ref_picture, pix_op, + motion_x, motion_y, h, 1, mb_y); + else +#endif + mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0, + field_select, ref_picture, pix_op, + motion_x, motion_y, h, 0, mb_y); +} + +static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y, + uint8_t *dest_cb, uint8_t *dest_cr, + int bottom_field, int field_select, + uint8_t **ref_picture, + op_pixels_func (*pix_op)[4], + int motion_x, int motion_y, int h, int mb_y) +{ +#if !CONFIG_SMALL + if(s->out_format == FMT_MPEG1) + mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1, + bottom_field, field_select, ref_picture, pix_op, + motion_x, motion_y, h, 1, mb_y); + else +#endif + mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1, + bottom_field, field_select, ref_picture, pix_op, + motion_x, motion_y, h, 0, mb_y); +} + +//FIXME move to dsputil, avg variant, 16x16 version +static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){ + int x; + uint8_t * const top = src[1]; + uint8_t * const left = src[2]; + uint8_t * const mid = src[0]; + uint8_t * const right = src[3]; + uint8_t * const bottom= src[4]; +#define OBMC_FILTER(x, t, l, m, r, b)\ + dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3 +#define OBMC_FILTER4(x, t, l, m, r, b)\ + OBMC_FILTER(x , t, l, m, r, b);\ + OBMC_FILTER(x+1 , t, l, m, r, b);\ + OBMC_FILTER(x +stride, t, l, m, r, b);\ + OBMC_FILTER(x+1+stride, t, l, m, r, b); + + x=0; + OBMC_FILTER (x , 2, 2, 4, 0, 0); + OBMC_FILTER (x+1, 2, 1, 5, 0, 0); + OBMC_FILTER4(x+2, 2, 1, 5, 0, 0); + OBMC_FILTER4(x+4, 2, 0, 5, 1, 0); + OBMC_FILTER (x+6, 2, 0, 5, 1, 0); + OBMC_FILTER (x+7, 2, 0, 4, 2, 0); + x+= stride; + OBMC_FILTER (x , 1, 2, 5, 0, 0); + OBMC_FILTER (x+1, 1, 2, 5, 0, 0); + OBMC_FILTER (x+6, 1, 0, 5, 2, 0); + OBMC_FILTER (x+7, 1, 0, 5, 2, 0); + x+= stride; + OBMC_FILTER4(x , 1, 2, 5, 0, 0); + OBMC_FILTER4(x+2, 1, 1, 6, 0, 0); + OBMC_FILTER4(x+4, 1, 0, 6, 1, 0); + OBMC_FILTER4(x+6, 1, 0, 5, 2, 0); + x+= 2*stride; + OBMC_FILTER4(x , 0, 2, 5, 0, 1); + OBMC_FILTER4(x+2, 0, 1, 6, 0, 1); + OBMC_FILTER4(x+4, 0, 0, 6, 1, 1); + OBMC_FILTER4(x+6, 0, 0, 5, 2, 1); + x+= 2*stride; + OBMC_FILTER (x , 0, 2, 5, 0, 1); + OBMC_FILTER (x+1, 0, 2, 5, 0, 1); + OBMC_FILTER4(x+2, 0, 1, 5, 0, 2); + OBMC_FILTER4(x+4, 0, 0, 5, 1, 2); + OBMC_FILTER (x+6, 0, 0, 5, 2, 1); + OBMC_FILTER (x+7, 0, 0, 5, 2, 1); + x+= stride; + OBMC_FILTER (x , 0, 2, 4, 0, 2); + OBMC_FILTER (x+1, 0, 1, 5, 0, 2); + OBMC_FILTER (x+6, 0, 0, 5, 1, 2); + OBMC_FILTER (x+7, 0, 0, 4, 2, 2); +} + +/* obmc for 1 8x8 luma block */ +static inline void obmc_motion(MpegEncContext *s, + uint8_t *dest, uint8_t *src, + int src_x, int src_y, + op_pixels_func *pix_op, + int16_t mv[5][2]/* mid top left right bottom*/) +#define MID 0 +{ + int i; + uint8_t *ptr[5]; + + av_assert2(s->quarter_sample==0); + + for(i=0; i<5; i++){ + if(i && mv[i][0]==mv[MID][0] && mv[i][1]==mv[MID][1]){ + ptr[i]= ptr[MID]; + }else{ + ptr[i]= s->obmc_scratchpad + 8*(i&1) + s->linesize*8*(i>>1); + hpel_motion(s, ptr[i], src, + src_x, src_y, + pix_op, + mv[i][0], mv[i][1]); + } + } + + put_obmc(dest, ptr, s->linesize); +} + +static inline void qpel_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + int field_based, int bottom_field, int field_select, + uint8_t **ref_picture, op_pixels_func (*pix_op)[4], + qpel_mc_func (*qpix_op)[16], + int motion_x, int motion_y, int h) +{ + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize; + + dxy = ((motion_y & 3) << 2) | (motion_x & 3); + src_x = s->mb_x * 16 + (motion_x >> 2); + src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2); + + v_edge_pos = s->v_edge_pos >> field_based; + linesize = s->linesize << field_based; + uvlinesize = s->uvlinesize << field_based; + + if(field_based){ + mx= motion_x/2; + my= motion_y>>1; + }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA2){ + static const int rtab[8]= {0,0,1,1,0,0,0,1}; + mx= (motion_x>>1) + rtab[motion_x&7]; + my= (motion_y>>1) + rtab[motion_y&7]; + }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA){ + mx= (motion_x>>1)|(motion_x&1); + my= (motion_y>>1)|(motion_y&1); + }else{ + mx= motion_x/2; + my= motion_y/2; + } + mx= (mx>>1)|(mx&1); + my= (my>>1)|(my&1); + + uvdxy= (mx&1) | ((my&1)<<1); + mx>>=1; + my>>=1; + + uvsrc_x = s->mb_x * 8 + mx; + uvsrc_y = s->mb_y * (8 >> field_based) + my; + + ptr_y = ref_picture[0] + src_y * linesize + src_x; + ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; + ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; + + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 16, 0) + || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&3) - h , 0)){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, + 17, 17+field_based, src_x, src_y<h_edge_pos, s->v_edge_pos); + ptr_y= s->edge_emu_buffer; + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize; + s->vdsp.emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize, + 9, 9 + field_based, + uvsrc_x, uvsrc_y<h_edge_pos>>1, s->v_edge_pos>>1); + s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, + 9, 9 + field_based, + uvsrc_x, uvsrc_y<h_edge_pos>>1, s->v_edge_pos>>1); + ptr_cb= uvbuf; + ptr_cr= uvbuf + 16; + } + } + + if(!field_based) + qpix_op[0][dxy](dest_y, ptr_y, linesize); + else{ + if(bottom_field){ + dest_y += s->linesize; + dest_cb+= s->uvlinesize; + dest_cr+= s->uvlinesize; + } + + if(field_select){ + ptr_y += s->linesize; + ptr_cb += s->uvlinesize; + ptr_cr += s->uvlinesize; + } + //damn interlaced mode + //FIXME boundary mirroring is not exactly correct here + qpix_op[1][dxy](dest_y , ptr_y , linesize); + qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize); + } + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){ + pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1); + pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1); + } +} + +/** + * h263 chroma 4mv motion compensation. + */ +static void chroma_4mv_motion(MpegEncContext *s, + uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture, + op_pixels_func *pix_op, + int mx, int my) +{ + int dxy, emu=0, src_x, src_y, offset; + uint8_t *ptr; + + /* In case of 8X8, we construct a single chroma motion vector + with a special rounding */ + mx= ff_h263_round_chroma(mx); + my= ff_h263_round_chroma(my); + + dxy = ((my & 1) << 1) | (mx & 1); + mx >>= 1; + my >>= 1; + + src_x = s->mb_x * 8 + mx; + src_y = s->mb_y * 8 + my; + src_x = av_clip(src_x, -8, (s->width >> 1)); + if (src_x == (s->width >> 1)) + dxy &= ~1; + src_y = av_clip(src_y, -8, (s->height >> 1)); + if (src_y == (s->height >> 1)) + dxy &= ~2; + + offset = src_y * s->uvlinesize + src_x; + ptr = ref_picture[1] + offset; + if(s->flags&CODEC_FLAG_EMU_EDGE){ + if( (unsigned)src_x > FFMAX((s->h_edge_pos>>1) - (dxy &1) - 8, 0) + || (unsigned)src_y > FFMAX((s->v_edge_pos>>1) - (dxy>>1) - 8, 0)){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, + 9, 9, src_x, src_y, + s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr= s->edge_emu_buffer; + emu=1; + } + } + pix_op[dxy](dest_cb, ptr, s->uvlinesize, 8); + + ptr = ref_picture[2] + offset; + if(emu){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, + 9, 9, src_x, src_y, + s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr= s->edge_emu_buffer; + } + pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8); +} + +static inline void prefetch_motion(MpegEncContext *s, uint8_t **pix, int dir){ + /* fetch pixels for estimated mv 4 macroblocks ahead + * optimized for 64byte cache lines */ + const int shift = s->quarter_sample ? 2 : 1; + const int mx= (s->mv[dir][0][0]>>shift) + 16*s->mb_x + 8; + const int my= (s->mv[dir][0][1]>>shift) + 16*s->mb_y; + int off= mx + (my + (s->mb_x&3)*4)*s->linesize + 64; + s->vdsp.prefetch(pix[0]+off, s->linesize, 4); + off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64; + s->vdsp.prefetch(pix[1]+off, pix[2]-pix[1], 2); +} + +/** + * motion compensation of a single macroblock + * @param s context + * @param dest_y luma destination pointer + * @param dest_cb chroma cb/u destination pointer + * @param dest_cr chroma cr/v destination pointer + * @param dir direction (0->forward, 1->backward) + * @param ref_picture array[3] of pointers to the 3 planes of the reference picture + * @param pix_op halfpel motion compensation function (average or put normally) + * @param qpix_op qpel motion compensation function (average or put normally) + * the motion vectors are taken from s->mv and the MV type from s->mv_type + */ +static av_always_inline void MPV_motion_internal(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, int dir, + uint8_t **ref_picture, + op_pixels_func (*pix_op)[4], + qpel_mc_func (*qpix_op)[16], int is_mpeg12) +{ + int dxy, mx, my, src_x, src_y, motion_x, motion_y; + int mb_x, mb_y, i; + uint8_t *ptr, *dest; + + mb_x = s->mb_x; + mb_y = s->mb_y; + + prefetch_motion(s, ref_picture, dir); + + if(!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B){ + LOCAL_ALIGNED_8(int16_t, mv_cache, [4], [4][2]); + Picture *cur_frame = &s->current_picture; + const int xy= s->mb_x + s->mb_y*s->mb_stride; + const int mot_stride= s->b8_stride; + const int mot_xy= mb_x*2 + mb_y*2*mot_stride; + + av_assert2(!s->mb_skipped); + + AV_COPY32(mv_cache[1][1], cur_frame->motion_val[0][mot_xy ]); + AV_COPY32(mv_cache[1][2], cur_frame->motion_val[0][mot_xy + 1]); + + AV_COPY32(mv_cache[2][1], cur_frame->motion_val[0][mot_xy + mot_stride ]); + AV_COPY32(mv_cache[2][2], cur_frame->motion_val[0][mot_xy + mot_stride + 1]); + + AV_COPY32(mv_cache[3][1], cur_frame->motion_val[0][mot_xy + mot_stride ]); + AV_COPY32(mv_cache[3][2], cur_frame->motion_val[0][mot_xy + mot_stride + 1]); + + if (mb_y == 0 || IS_INTRA(cur_frame->mb_type[xy - s->mb_stride])) { + AV_COPY32(mv_cache[0][1], mv_cache[1][1]); + AV_COPY32(mv_cache[0][2], mv_cache[1][2]); + }else{ + AV_COPY32(mv_cache[0][1], cur_frame->motion_val[0][mot_xy - mot_stride ]); + AV_COPY32(mv_cache[0][2], cur_frame->motion_val[0][mot_xy - mot_stride + 1]); + } + + if (mb_x == 0 || IS_INTRA(cur_frame->mb_type[xy - 1])) { + AV_COPY32(mv_cache[1][0], mv_cache[1][1]); + AV_COPY32(mv_cache[2][0], mv_cache[2][1]); + }else{ + AV_COPY32(mv_cache[1][0], cur_frame->motion_val[0][mot_xy - 1]); + AV_COPY32(mv_cache[2][0], cur_frame->motion_val[0][mot_xy - 1 + mot_stride]); + } + + if (mb_x + 1 >= s->mb_width || IS_INTRA(cur_frame->mb_type[xy + 1])) { + AV_COPY32(mv_cache[1][3], mv_cache[1][2]); + AV_COPY32(mv_cache[2][3], mv_cache[2][2]); + }else{ + AV_COPY32(mv_cache[1][3], cur_frame->motion_val[0][mot_xy + 2]); + AV_COPY32(mv_cache[2][3], cur_frame->motion_val[0][mot_xy + 2 + mot_stride]); + } + + mx = 0; + my = 0; + for(i=0;i<4;i++) { + const int x= (i&1)+1; + const int y= (i>>1)+1; + int16_t mv[5][2]= { + {mv_cache[y][x ][0], mv_cache[y][x ][1]}, + {mv_cache[y-1][x][0], mv_cache[y-1][x][1]}, + {mv_cache[y][x-1][0], mv_cache[y][x-1][1]}, + {mv_cache[y][x+1][0], mv_cache[y][x+1][1]}, + {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}}; + //FIXME cleanup + obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, + ref_picture[0], + mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8, + pix_op[1], + mv); + + mx += mv[0][0]; + my += mv[0][1]; + } + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)) + chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); + + return; + } + + switch(s->mv_type) { + case MV_TYPE_16X16: + if(s->mcsel){ + if(s->real_sprite_warping_points==1){ + gmc1_motion(s, dest_y, dest_cb, dest_cr, + ref_picture); + }else{ + gmc_motion(s, dest_y, dest_cb, dest_cr, + ref_picture); + } + }else if(!is_mpeg12 && s->quarter_sample){ + qpel_motion(s, dest_y, dest_cb, dest_cr, + 0, 0, 0, + ref_picture, pix_op, qpix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 16); + } else if (!is_mpeg12 && (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) && + s->mspel && s->codec_id == AV_CODEC_ID_WMV2) { + ff_mspel_motion(s, dest_y, dest_cb, dest_cr, + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 16); + }else + { + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y); + } + break; + case MV_TYPE_8X8: + if (!is_mpeg12) { + mx = 0; + my = 0; + if(s->quarter_sample){ + for(i=0;i<4;i++) { + motion_x = s->mv[dir][i][0]; + motion_y = s->mv[dir][i][1]; + + dxy = ((motion_y & 3) << 2) | (motion_x & 3); + src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8; + src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8; + + /* WARNING: do no forget half pels */ + src_x = av_clip(src_x, -16, s->width); + if (src_x == s->width) + dxy &= ~3; + src_y = av_clip(src_y, -16, s->height); + if (src_y == s->height) + dxy &= ~12; + + ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); + if(s->flags&CODEC_FLAG_EMU_EDGE){ + if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 8, 0) + || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&3) - 8, 0)){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, + s->linesize, 9, 9, + src_x, src_y, + s->h_edge_pos, s->v_edge_pos); + ptr= s->edge_emu_buffer; + } + } + dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; + qpix_op[1][dxy](dest, ptr, s->linesize); + + mx += s->mv[dir][i][0]/2; + my += s->mv[dir][i][1]/2; + } + }else{ + for(i=0;i<4;i++) { + hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, + ref_picture[0], + mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8, + pix_op[1], + s->mv[dir][i][0], s->mv[dir][i][1]); + + mx += s->mv[dir][i][0]; + my += s->mv[dir][i][1]; + } + } + + if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)) + chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); + } + break; + case MV_TYPE_FIELD: + if (s->picture_structure == PICT_FRAME) { + if(!is_mpeg12 && s->quarter_sample){ + for(i=0; i<2; i++){ + qpel_motion(s, dest_y, dest_cb, dest_cr, + 1, i, s->field_select[dir][i], + ref_picture, pix_op, qpix_op, + s->mv[dir][i][0], s->mv[dir][i][1], 8); + } + }else{ + /* top field */ + mpeg_motion_field(s, dest_y, dest_cb, dest_cr, + 0, s->field_select[dir][0], + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 8, mb_y); + /* bottom field */ + mpeg_motion_field(s, dest_y, dest_cb, dest_cr, + 1, s->field_select[dir][1], + ref_picture, pix_op, + s->mv[dir][1][0], s->mv[dir][1][1], 8, mb_y); + } + } else { + if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){ + ref_picture = s->current_picture_ptr->f.data; + } + + mpeg_motion(s, dest_y, dest_cb, dest_cr, + s->field_select[dir][0], + ref_picture, pix_op, + s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y>>1); + } + break; + case MV_TYPE_16X8: + for(i=0; i<2; i++){ + uint8_t ** ref2picture; + + if(s->picture_structure == s->field_select[dir][i] + 1 + || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){ + ref2picture= ref_picture; + }else{ + ref2picture = s->current_picture_ptr->f.data; + } + + mpeg_motion(s, dest_y, dest_cb, dest_cr, + s->field_select[dir][i], + ref2picture, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8, mb_y>>1); + + dest_y += 16*s->linesize; + dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize; + dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize; + } + break; + case MV_TYPE_DMV: + if(s->picture_structure == PICT_FRAME){ + for(i=0; i<2; i++){ + int j; + for(j=0; j<2; j++){ + mpeg_motion_field(s, dest_y, dest_cb, dest_cr, + j, j^i, ref_picture, pix_op, + s->mv[dir][2*i + j][0], + s->mv[dir][2*i + j][1], 8, mb_y); + } + pix_op = s->hdsp.avg_pixels_tab; + } + }else{ + for(i=0; i<2; i++){ + mpeg_motion(s, dest_y, dest_cb, dest_cr, + s->picture_structure != i+1, + ref_picture, pix_op, + s->mv[dir][2*i][0],s->mv[dir][2*i][1],16, mb_y>>1); + + // after put we make avg of the same block + pix_op=s->hdsp.avg_pixels_tab; + + //opposite parity is always in the same frame if this is second field + if(!s->first_field){ + ref_picture = s->current_picture_ptr->f.data; + } + } + } + break; + default: av_assert2(0); + } +} + +void ff_MPV_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, int dir, + uint8_t **ref_picture, + op_pixels_func (*pix_op)[4], + qpel_mc_func (*qpix_op)[16]) +{ +#if !CONFIG_SMALL + if(s->out_format == FMT_MPEG1) + MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir, + ref_picture, pix_op, qpix_op, 1); + else +#endif + MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir, + ref_picture, pix_op, qpix_op, 0); +} diff --git a/ffmpeg/libavcodec/mpegvideo_parser.c b/ffmpeg/libavcodec/mpegvideo_parser.c new file mode 100644 index 0000000..35a9160 --- /dev/null +++ b/ffmpeg/libavcodec/mpegvideo_parser.c @@ -0,0 +1,208 @@ +/* + * MPEG1 / MPEG2 video parser + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 "parser.h" +#include "mpegvideo.h" + +struct MpvParseContext { + ParseContext pc; + AVRational frame_rate; + int progressive_sequence; + int width, height; +}; + + +static void mpegvideo_extract_headers(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + struct MpvParseContext *pc = s->priv_data; + const uint8_t *buf_end = buf + buf_size; + uint32_t start_code; + int frame_rate_index, ext_type, bytes_left; + int frame_rate_ext_n, frame_rate_ext_d; + int top_field_first, repeat_first_field, progressive_frame; + int horiz_size_ext, vert_size_ext, bit_rate_ext; + int did_set_size=0; + int bit_rate = 0; + int vbv_delay = 0; +//FIXME replace the crap with get_bits() + s->repeat_pict = 0; + + while (buf < buf_end) { + start_code= -1; + buf= avpriv_mpv_find_start_code(buf, buf_end, &start_code); + bytes_left = buf_end - buf; + switch(start_code) { + case PICTURE_START_CODE: + if (bytes_left >= 2) { + s->pict_type = (buf[1] >> 3) & 7; + if (bytes_left >= 4) + vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); + } + break; + case SEQ_START_CODE: + if (bytes_left >= 7) { + pc->width = (buf[0] << 4) | (buf[1] >> 4); + pc->height = ((buf[1] & 0x0f) << 8) | buf[2]; + if(!avctx->width || !avctx->height || !avctx->coded_width || !avctx->coded_height){ + avcodec_set_dimensions(avctx, pc->width, pc->height); + did_set_size=1; + } + frame_rate_index = buf[3] & 0xf; + pc->frame_rate.den = avctx->time_base.den = ff_mpeg12_frame_rate_tab[frame_rate_index].num; + pc->frame_rate.num = avctx->time_base.num = ff_mpeg12_frame_rate_tab[frame_rate_index].den; + bit_rate = (buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6); + avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; + } + break; + case EXT_START_CODE: + if (bytes_left >= 1) { + ext_type = (buf[0] >> 4); + switch(ext_type) { + case 0x1: /* sequence extension */ + if (bytes_left >= 6) { + horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7); + vert_size_ext = (buf[2] >> 5) & 3; + bit_rate_ext = ((buf[2] & 0x1F)<<7) | (buf[3]>>1); + frame_rate_ext_n = (buf[5] >> 5) & 3; + frame_rate_ext_d = (buf[5] & 0x1f); + pc->progressive_sequence = buf[1] & (1 << 3); + avctx->has_b_frames= !(buf[5] >> 7); + + pc->width |=(horiz_size_ext << 12); + pc->height |=( vert_size_ext << 12); + bit_rate = (bit_rate&0x3FFFF) | (bit_rate_ext << 18); + if(did_set_size) + avcodec_set_dimensions(avctx, pc->width, pc->height); + avctx->time_base.den = pc->frame_rate.den * (frame_rate_ext_n + 1) * 2; + avctx->time_base.num = pc->frame_rate.num * (frame_rate_ext_d + 1); + avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; + } + break; + case 0x8: /* picture coding extension */ + if (bytes_left >= 5) { + top_field_first = buf[3] & (1 << 7); + repeat_first_field = buf[3] & (1 << 1); + progressive_frame = buf[4] & (1 << 7); + + /* check if we must repeat the frame */ + s->repeat_pict = 1; + if (repeat_first_field) { + if (pc->progressive_sequence) { + if (top_field_first) + s->repeat_pict = 5; + else + s->repeat_pict = 3; + } else if (progressive_frame) { + s->repeat_pict = 2; + } + } + } + break; + } + } + break; + case -1: + goto the_end; + default: + /* we stop parsing when we encounter a slice. It ensures + that this function takes a negligible amount of time */ + if (start_code >= SLICE_MIN_START_CODE && + start_code <= SLICE_MAX_START_CODE) + goto the_end; + break; + } + } + the_end: ; + if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && bit_rate) { + avctx->rc_max_rate = 400*bit_rate; + } else if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO && bit_rate && + (bit_rate != 0x3FFFF || vbv_delay != 0xFFFF)) { + avctx->bit_rate = 400*bit_rate; + } +} + +static int mpegvideo_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + struct MpvParseContext *pc1 = s->priv_data; + ParseContext *pc= &pc1->pc; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= ff_mpeg1_find_frame_end(pc, buf, buf_size, s); + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + + } + /* we have a full frame : we just parse the first few MPEG headers + to have the full timing information. The time take by this + function should be negligible for uncorrupted streams */ + mpegvideo_extract_headers(s, avctx, buf, buf_size); + av_dlog(NULL, "pict_type=%d frame_rate=%0.3f repeat_pict=%d\n", + s->pict_type, (double)avctx->time_base.den / avctx->time_base.num, s->repeat_pict); + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +static int mpegvideo_split(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + int i; + uint32_t state= -1; + int found=0; + + for(i=0; i= 0x100) + return i-3; + } + return 0; +} + +static int mpegvideo_parse_init(AVCodecParserContext *s) +{ + s->pict_type = AV_PICTURE_TYPE_NONE; // first frame might be partial + return 0; +} + +AVCodecParser ff_mpegvideo_parser = { + .codec_ids = { AV_CODEC_ID_MPEG1VIDEO, AV_CODEC_ID_MPEG2VIDEO }, + .priv_data_size = sizeof(struct MpvParseContext), + .parser_init = mpegvideo_parse_init, + .parser_parse = mpegvideo_parse, + .parser_close = ff_parse_close, + .split = mpegvideo_split, +}; diff --git a/ffmpeg/libavcodec/mpegvideo_xvmc.c b/ffmpeg/libavcodec/mpegvideo_xvmc.c new file mode 100644 index 0000000..6b0c6ac --- /dev/null +++ b/ffmpeg/libavcodec/mpegvideo_xvmc.c @@ -0,0 +1,331 @@ +/* + * XVideo Motion Compensation + * Copyright (c) 2003 Ivan Kalvachev + * + * 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 + +#include "avcodec.h" +#include "mpegvideo.h" + +#undef NDEBUG +#include + +#include "xvmc.h" +#include "xvmc_internal.h" + +/** + * Initialize the block field of the MpegEncContext pointer passed as + * parameter after making sure that the data is not corrupted. + * In order to implement something like direct rendering instead of decoding + * coefficients in s->blocks and then copying them, copy them directly + * into the data_blocks array provided by xvmc. + */ +void ff_xvmc_init_block(MpegEncContext *s) +{ + struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + assert(render && render->xvmc_id == AV_XVMC_ID); + + s->block = (int16_t (*)[64])(render->data_blocks + render->next_free_data_block_num * 64); +} + +/** + * Fill individual block pointers, so there are no gaps in the data_block array + * in case not all blocks in the macroblock are coded. + */ +void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp) +{ + int i, j = 0; + const int mb_block_count = 4 + (1 << s->chroma_format); + + cbp <<= 12-mb_block_count; + for (i = 0; i < mb_block_count; i++) { + if (cbp & (1 << 11)) + s->pblocks[i] = &s->block[j++]; + else + s->pblocks[i] = NULL; + cbp += cbp; + } +} + +/** + * Find and store the surfaces that are used as reference frames. + * This function should be called for every new field and/or frame. + * It should be safe to call the function a few times for the same field. + */ +int ff_xvmc_field_start(MpegEncContext *s, AVCodecContext *avctx) +{ + struct xvmc_pix_fmt *last, *next, *render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + const int mb_block_count = 4 + (1 << s->chroma_format); + + assert(avctx); + if (!render || render->xvmc_id != AV_XVMC_ID || + !render->data_blocks || !render->mv_blocks || + (unsigned int)render->allocated_mv_blocks > INT_MAX/(64*6) || + (unsigned int)render->allocated_data_blocks > INT_MAX/64 || + !render->p_surface) { + av_log(avctx, AV_LOG_ERROR, + "Render token doesn't look as expected.\n"); + return -1; // make sure that this is a render packet + } + + if (render->filled_mv_blocks_num) { + av_log(avctx, AV_LOG_ERROR, + "Rendering surface contains %i unprocessed blocks.\n", + render->filled_mv_blocks_num); + return -1; + } + if (render->allocated_mv_blocks < 1 || + render->allocated_data_blocks < render->allocated_mv_blocks*mb_block_count || + render->start_mv_blocks_num >= render->allocated_mv_blocks || + render->next_free_data_block_num > + render->allocated_data_blocks - + mb_block_count*(render->allocated_mv_blocks-render->start_mv_blocks_num)) { + av_log(avctx, AV_LOG_ERROR, + "Rendering surface doesn't provide enough block structures to work with.\n"); + return -1; + } + + render->picture_structure = s->picture_structure; + render->flags = s->first_field ? 0 : XVMC_SECOND_FIELD; + render->p_future_surface = NULL; + render->p_past_surface = NULL; + + switch(s->pict_type) { + case AV_PICTURE_TYPE_I: + return 0; // no prediction from other frames + case AV_PICTURE_TYPE_B: + next = (struct xvmc_pix_fmt*)s->next_picture.f.data[2]; + if (!next) + return -1; + if (next->xvmc_id != AV_XVMC_ID) + return -1; + render->p_future_surface = next->p_surface; + // no return here, going to set forward prediction + case AV_PICTURE_TYPE_P: + last = (struct xvmc_pix_fmt*)s->last_picture.f.data[2]; + if (!last) + last = render; // predict second field from the first + if (last->xvmc_id != AV_XVMC_ID) + return -1; + render->p_past_surface = last->p_surface; + return 0; + } + +return -1; +} + +/** + * Complete frame/field rendering by passing any remaining blocks. + * Normally ff_draw_horiz_band() is called for each slice, however, + * some leftover blocks, for example from error_resilience(), may remain. + * It should be safe to call the function a few times for the same field. + */ +void ff_xvmc_field_end(MpegEncContext *s) +{ + struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + assert(render); + + if (render->filled_mv_blocks_num > 0) + ff_mpeg_draw_horiz_band(s, 0, 0); +} + +/** + * Synthesize the data needed by XvMC to render one macroblock of data. + * Fill all relevant fields, if necessary do IDCT. + */ +void ff_xvmc_decode_mb(MpegEncContext *s) +{ + XvMCMacroBlock *mv_block; + struct xvmc_pix_fmt *render; + int i, cbp, blocks_per_mb; + + const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; + + + if (s->encoding) { + av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n"); + return; + } + + // from MPV_decode_mb(), update DC predictors for P macroblocks + if (!s->mb_intra) { + s->last_dc[0] = + s->last_dc[1] = + s->last_dc[2] = 128 << s->intra_dc_precision; + } + + // MC doesn't skip blocks + s->mb_skipped = 0; + + + // Do I need to export quant when I could not perform postprocessing? + // Anyway, it doesn't hurt. + s->current_picture.qscale_table[mb_xy] = s->qscale; + + // start of XVMC-specific code + render = (struct xvmc_pix_fmt*)s->current_picture.f.data[2]; + assert(render); + assert(render->xvmc_id == AV_XVMC_ID); + assert(render->mv_blocks); + + // take the next free macroblock + mv_block = &render->mv_blocks[render->start_mv_blocks_num + + render->filled_mv_blocks_num]; + + mv_block->x = s->mb_x; + mv_block->y = s->mb_y; + mv_block->dct_type = s->interlaced_dct; // XVMC_DCT_TYPE_FRAME/FIELD; + if (s->mb_intra) { + mv_block->macroblock_type = XVMC_MB_TYPE_INTRA; // no MC, all done + } else { + mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN; + + if (s->mv_dir & MV_DIR_FORWARD) { + mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD; + // PMV[n][dir][xy] = mv[dir][n][xy] + mv_block->PMV[0][0][0] = s->mv[0][0][0]; + mv_block->PMV[0][0][1] = s->mv[0][0][1]; + mv_block->PMV[1][0][0] = s->mv[0][1][0]; + mv_block->PMV[1][0][1] = s->mv[0][1][1]; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD; + mv_block->PMV[0][1][0] = s->mv[1][0][0]; + mv_block->PMV[0][1][1] = s->mv[1][0][1]; + mv_block->PMV[1][1][0] = s->mv[1][1][0]; + mv_block->PMV[1][1][1] = s->mv[1][1][1]; + } + + switch(s->mv_type) { + case MV_TYPE_16X16: + mv_block->motion_type = XVMC_PREDICTION_FRAME; + break; + case MV_TYPE_16X8: + mv_block->motion_type = XVMC_PREDICTION_16x8; + break; + case MV_TYPE_FIELD: + mv_block->motion_type = XVMC_PREDICTION_FIELD; + if (s->picture_structure == PICT_FRAME) { + mv_block->PMV[0][0][1] <<= 1; + mv_block->PMV[1][0][1] <<= 1; + mv_block->PMV[0][1][1] <<= 1; + mv_block->PMV[1][1][1] <<= 1; + } + break; + case MV_TYPE_DMV: + mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME; + if (s->picture_structure == PICT_FRAME) { + + mv_block->PMV[0][0][0] = s->mv[0][0][0]; // top from top + mv_block->PMV[0][0][1] = s->mv[0][0][1] << 1; + + mv_block->PMV[0][1][0] = s->mv[0][0][0]; // bottom from bottom + mv_block->PMV[0][1][1] = s->mv[0][0][1] << 1; + + mv_block->PMV[1][0][0] = s->mv[0][2][0]; // dmv00, top from bottom + mv_block->PMV[1][0][1] = s->mv[0][2][1] << 1; // dmv01 + + mv_block->PMV[1][1][0] = s->mv[0][3][0]; // dmv10, bottom from top + mv_block->PMV[1][1][1] = s->mv[0][3][1] << 1; // dmv11 + + } else { + mv_block->PMV[0][1][0] = s->mv[0][2][0]; // dmv00 + mv_block->PMV[0][1][1] = s->mv[0][2][1]; // dmv01 + } + break; + default: + assert(0); + } + + mv_block->motion_vertical_field_select = 0; + + // set correct field references + if (s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8) { + mv_block->motion_vertical_field_select |= s->field_select[0][0]; + mv_block->motion_vertical_field_select |= s->field_select[1][0] << 1; + mv_block->motion_vertical_field_select |= s->field_select[0][1] << 2; + mv_block->motion_vertical_field_select |= s->field_select[1][1] << 3; + } + } // !intra + // time to handle data blocks + mv_block->index = render->next_free_data_block_num; + + blocks_per_mb = 6; + if (s->chroma_format >= 2) { + blocks_per_mb = 4 + (1 << s->chroma_format); + } + + // calculate cbp + cbp = 0; + for (i = 0; i < blocks_per_mb; i++) { + cbp += cbp; + if (s->block_last_index[i] >= 0) + cbp++; + } + + if (s->flags & CODEC_FLAG_GRAY) { + if (s->mb_intra) { // intra frames are always full chroma blocks + for (i = 4; i < blocks_per_mb; i++) { + memset(s->pblocks[i], 0, sizeof(*s->pblocks[i])); // so we need to clear them + if (!render->unsigned_intra) + *s->pblocks[i][0] = 1 << 10; + } + } else { + cbp &= 0xf << (blocks_per_mb - 4); + blocks_per_mb = 4; // luminance blocks only + } + } + mv_block->coded_block_pattern = cbp; + if (cbp == 0) + mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN; + + for (i = 0; i < blocks_per_mb; i++) { + if (s->block_last_index[i] >= 0) { + // I do not have unsigned_intra MOCO to test, hope it is OK. + if (s->mb_intra && (render->idct || !render->unsigned_intra)) + *s->pblocks[i][0] -= 1 << 10; + if (!render->idct) { + s->dsp.idct(*s->pblocks[i]); + /* It is unclear if MC hardware requires pixel diff values to be + * in the range [-255;255]. TODO: Clipping if such hardware is + * ever found. As of now it would only be an unnecessary + * slowdown. */ + } + // copy blocks only if the codec doesn't support pblocks reordering + if (s->avctx->xvmc_acceleration == 1) { + memcpy(&render->data_blocks[render->next_free_data_block_num*64], + s->pblocks[i], sizeof(*s->pblocks[i])); + } + render->next_free_data_block_num++; + } + } + render->filled_mv_blocks_num++; + + assert(render->filled_mv_blocks_num <= render->allocated_mv_blocks); + assert(render->next_free_data_block_num <= render->allocated_data_blocks); + /* The above conditions should not be able to fail as long as this function + * is used and the following 'if ()' automatically calls a callback to free + * blocks. */ + + + if (render->filled_mv_blocks_num == render->allocated_mv_blocks) + ff_mpeg_draw_horiz_band(s, 0, 0); +} diff --git a/ffmpeg/libavcodec/mpl2dec.c b/ffmpeg/libavcodec/mpl2dec.c new file mode 100644 index 0000000..a777c7c --- /dev/null +++ b/ffmpeg/libavcodec/mpl2dec.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2012 Clément Bœsch + * + * 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 + */ + +/** + * @file + * MPL2 subtitles decoder + * + * @see http://web.archive.org/web/20090328040233/http://napisy.ussbrowarek.org/mpl2-eng.html + */ + +#include "avcodec.h" +#include "ass.h" +#include "libavutil/bprint.h" + +static int mpl2_event_to_ass(AVBPrint *buf, const char *p) +{ + if (*p == ' ') + p++; + + while (*p) { + int got_style = 0; + + while (*p && strchr("/\\_", *p)) { + if (*p == '/') av_bprintf(buf, "{\\i1}"); + else if (*p == '\\') av_bprintf(buf, "{\\b1}"); + else if (*p == '_') av_bprintf(buf, "{\\u1}"); + got_style = 1; + p++; + } + + while (*p && *p != '|') { + if (*p != '\r' && *p != '\n') + av_bprint_chars(buf, *p, 1); + p++; + } + + if (*p == '|') { + if (got_style) + av_bprintf(buf, "{\\r}"); + av_bprintf(buf, "\\N"); + p++; + } + } + + av_bprintf(buf, "\r\n"); + return 0; +} + +static int mpl2_decode_frame(AVCodecContext *avctx, void *data, + int *got_sub_ptr, AVPacket *avpkt) +{ + AVBPrint buf; + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + const int ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100}); + const int ts_duration = avpkt->duration != -1 ? + av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1; + + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + if (ptr && avpkt->size > 0 && *ptr && !mpl2_event_to_ass(&buf, ptr)) { + if (!av_bprint_is_complete(&buf)) { + av_bprint_finalize(&buf, NULL); + return AVERROR(ENOMEM); + } + ff_ass_add_rect(sub, buf.str, ts_start, ts_duration, 0); + } + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +AVCodec ff_mpl2_decoder = { + .name = "mpl2", + .long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_MPL2, + .decode = mpl2_decode_frame, + .init = ff_ass_subtitle_header_default, +}; diff --git a/ffmpeg/libavcodec/mqc.c b/ffmpeg/libavcodec/mqc.c new file mode 100644 index 0000000..700b957 --- /dev/null +++ b/ffmpeg/libavcodec/mqc.c @@ -0,0 +1,108 @@ +/* + * MQ-coder encoder and decoder common functions + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * MQ-coder ecoder and decoder common functions + * @file + * @author Kamil Nowosad + */ + +#include "mqc.h" + +typedef struct { + uint16_t qe; + uint8_t nmps; + uint8_t nlps; + uint8_t sw; +} MqcCxState; + +const static MqcCxState cx_states[47] = { + {0x5601, 1, 1, 1}, + {0x3401, 2, 6, 0}, + {0x1801, 3, 9, 0}, + {0x0AC1, 4, 12, 0}, + {0x0521, 5, 29, 0}, + {0x0221, 38, 33, 0}, + {0x5601, 7, 6, 1}, + {0x5401, 8, 14, 0}, + {0x4801, 9, 14, 0}, + {0x3801, 10, 14, 0}, + {0x3001, 11, 17, 0}, + {0x2401, 12, 18, 0}, + {0x1C01, 13, 20, 0}, + {0x1601, 29, 21, 0}, + {0x5601, 15, 14, 1}, + {0x5401, 16, 14, 0}, + {0x5101, 17, 15, 0}, + {0x4801, 18, 16, 0}, + {0x3801, 19, 17, 0}, + {0x3401, 20, 18, 0}, + {0x3001, 21, 19, 0}, + {0x2801, 22, 19, 0}, + {0x2401, 23, 20, 0}, + {0x2201, 24, 21, 0}, + {0x1C01, 25, 22, 0}, + {0x1801, 26, 23, 0}, + {0x1601, 27, 24, 0}, + {0x1401, 28, 25, 0}, + {0x1201, 29, 26, 0}, + {0x1101, 30, 27, 0}, + {0x0AC1, 31, 28, 0}, + {0x09C1, 32, 29, 0}, + {0x08A1, 33, 30, 0}, + {0x0521, 34, 31, 0}, + {0x0441, 35, 32, 0}, + {0x02A1, 36, 33, 0}, + {0x0221, 37, 34, 0}, + {0x0141, 38, 35, 0}, + {0x0111, 39, 36, 0}, + {0x0085, 40, 37, 0}, + {0x0049, 41, 38, 0}, + {0x0025, 42, 39, 0}, + {0x0015, 43, 40, 0}, + {0x0009, 44, 41, 0}, + {0x0005, 45, 42, 0}, + {0x0001, 45, 43, 0}, + {0x5601, 46, 46, 0} +}; + +uint16_t ff_mqc_qe [2*47]; +uint8_t ff_mqc_nlps[2*47]; +uint8_t ff_mqc_nmps[2*47]; + +void ff_mqc_init_contexts(MqcState *mqc) +{ + int i; + memset(mqc->cx_states, 0, sizeof(mqc->cx_states)); + mqc->cx_states[MQC_CX_UNI] = 2 * 46; + mqc->cx_states[MQC_CX_RL] = 2 * 3; + mqc->cx_states[0] = 2 * 4; + + for (i = 0; i < 47; i++){ + ff_mqc_qe[2*i ] = + ff_mqc_qe[2*i+1] = cx_states[i].qe; + + ff_mqc_nlps[2*i ] = 2*cx_states[i].nlps + cx_states[i].sw; + ff_mqc_nlps[2*i+1] = 2*cx_states[i].nlps + 1 - cx_states[i].sw; + ff_mqc_nmps[2*i ] = 2*cx_states[i].nmps; + ff_mqc_nmps[2*i+1] = 2*cx_states[i].nmps + 1; + } +} diff --git a/ffmpeg/libavcodec/mqc.h b/ffmpeg/libavcodec/mqc.h new file mode 100644 index 0000000..b28c13e --- /dev/null +++ b/ffmpeg/libavcodec/mqc.h @@ -0,0 +1,75 @@ +/* + * MQ-coder + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +#ifndef AVCODEC_MQC_H +#define AVCODEC_MQC_H + +/** + * MQ-coder + * @file + * @author Kamil Nowosad + */ + +#include "avcodec.h" + +#define MQC_CX_UNI 17 +#define MQC_CX_RL 18 + +extern uint16_t ff_mqc_qe[2*47]; +extern uint8_t ff_mqc_nlps[2*47]; +extern uint8_t ff_mqc_nmps[2*47]; + +typedef struct { + uint8_t *bp, *bpstart; + unsigned int a; + unsigned int c; + unsigned int ct; + uint8_t cx_states[19]; +} MqcState; + +/* encoder */ + +/** initialize the encoder */ +void ff_mqc_initenc(MqcState *mqc, uint8_t *bp); + +/** code bit d with context cx */ +void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d); + +/** number of encoded bytes */ +int ff_mqc_length(MqcState *mqc); + +/** flush the encoder [returns number of bytes encoded] */ +int ff_mqc_flush(MqcState *mqc); + +/* decoder */ + +/** initialize the decoder */ +void ff_mqc_initdec(MqcState *mqc, uint8_t *bp); + +/** returns decoded bit with context cx */ +int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate); + +/* common */ + +/** initialize the contexts */ +void ff_mqc_init_contexts(MqcState *mqc); + +#endif /* AVCODEC_MQC_H */ diff --git a/ffmpeg/libavcodec/mqcdec.c b/ffmpeg/libavcodec/mqcdec.c new file mode 100644 index 0000000..56e22f8 --- /dev/null +++ b/ffmpeg/libavcodec/mqcdec.c @@ -0,0 +1,93 @@ +/* + * MQ-coder decoder + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * MQ-coder decoder + * @file + * @author Kamil Nowosad + */ + +#include "mqc.h" + +static void bytein(MqcState *mqc) +{ + if (*mqc->bp == 0xff){ + if (*(mqc->bp+1) > 0x8f) + mqc->c++; + else{ + mqc->bp++; + mqc->c += 2 + 0xfe00 - (*mqc->bp << 9); + } + } else{ + mqc->bp++; + mqc->c += 1 + 0xff00 - (*mqc->bp << 8); + } +} + +static int exchange(MqcState *mqc, uint8_t *cxstate, int lps) +{ + int d; + if ((mqc->a < ff_mqc_qe[*cxstate]) ^ (!lps)){ + if (lps) + mqc->a = ff_mqc_qe[*cxstate]; + d = *cxstate & 1; + *cxstate = ff_mqc_nmps[*cxstate]; + } else{ + if (lps) + mqc->a = ff_mqc_qe[*cxstate]; + d = 1 - (*cxstate & 1); + *cxstate = ff_mqc_nlps[*cxstate]; + } + // renormd: + do{ + if (!(mqc->c & 0xff)){ + mqc->c -= 0x100; + bytein(mqc); + } + mqc->a += mqc->a; + mqc->c += mqc->c; + } while (!(mqc->a & 0x8000)); + return d; +} + +void ff_mqc_initdec(MqcState *mqc, uint8_t *bp) +{ + ff_mqc_init_contexts(mqc); + mqc->bp = bp; + mqc->c = (*mqc->bp ^ 0xff) << 16; + bytein(mqc); + mqc->c = mqc->c << 7; + mqc->a = 0x8000; +} + +int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate) +{ + mqc->a -= ff_mqc_qe[*cxstate]; + if ((mqc->c >> 16) < mqc->a){ + if (mqc->a & 0x8000) + return *cxstate & 1; + else + return exchange(mqc, cxstate, 0); + } else { + mqc->c -= mqc->a << 16; + return exchange(mqc, cxstate, 1); + } +} diff --git a/ffmpeg/libavcodec/mqcenc.c b/ffmpeg/libavcodec/mqcenc.c new file mode 100644 index 0000000..97d352b --- /dev/null +++ b/ffmpeg/libavcodec/mqcenc.c @@ -0,0 +1,119 @@ +/* + * MQ-coder encoder + * Copyright (c) 2007 Kamil Nowosad + * + * 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 + */ + +/** + * MQ-coder encoder + * @file + * @author Kamil Nowosad + */ + +#include "mqc.h" + +static void byteout(MqcState *mqc) +{ +retry: + if (*mqc->bp == 0xff){ + mqc->bp++; + *mqc->bp = mqc->c >> 20; + mqc->c &= 0xfffff; + mqc->ct = 7; + } else if ((mqc->c & 0x8000000)){ + (*mqc->bp)++; + mqc->c &= 0x7ffffff; + goto retry; + } else{ + mqc->bp++; + *mqc->bp = mqc->c >> 19; + mqc->c &= 0x7ffff; + mqc->ct = 8; + } +} + +static void renorme(MqcState *mqc) +{ + do{ + mqc->a += mqc->a; + mqc->c += mqc->c; + if (!--mqc->ct) + byteout(mqc); + } while (!(mqc->a & 0x8000)); +} + +static void setbits(MqcState *mqc) +{ + int tmp = mqc->c + mqc->a; + mqc->c |= 0xffff; + if (mqc->c >= tmp) + mqc->c -= 0x8000; +} + +void ff_mqc_initenc(MqcState *mqc, uint8_t *bp) +{ + ff_mqc_init_contexts(mqc); + mqc->a = 0x8000; + mqc->c = 0; + mqc->bp = bp-1; + mqc->bpstart = bp; + mqc->ct = 12 + (*mqc->bp == 0xff); +} + +void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d) +{ + int qe; + + qe = ff_mqc_qe[*cxstate]; + mqc->a -= qe; + if ((*cxstate & 1) == d){ + if (!(mqc->a & 0x8000)){ + if (mqc->a < qe) + mqc->a = qe; + else + mqc->c += qe; + *cxstate = ff_mqc_nmps[*cxstate]; + renorme(mqc); + } else + mqc->c += qe; + } else{ + if (mqc->a < qe) + mqc->c += qe; + else + mqc->a = qe; + *cxstate = ff_mqc_nlps[*cxstate]; + renorme(mqc); + } +} + +int ff_mqc_length(MqcState *mqc) +{ + return mqc->bp - mqc->bpstart; +} + +int ff_mqc_flush(MqcState *mqc) +{ + setbits(mqc); + mqc->c = mqc->c << mqc->ct; + byteout(mqc); + mqc->c = mqc->c << mqc->ct; + byteout(mqc); + if (*mqc->bp != 0xff) + mqc->bp++; + return mqc->bp - mqc->bpstart; +} diff --git a/ffmpeg/libavcodec/msgsmdec.c b/ffmpeg/libavcodec/msgsmdec.c new file mode 100644 index 0000000..90e83ae --- /dev/null +++ b/ffmpeg/libavcodec/msgsmdec.c @@ -0,0 +1,38 @@ +/* + * gsm 06.10 decoder, Microsoft variant + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "msgsmdec.h" +#include "gsm.h" +#include "gsmdec_template.c" + +int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, + const uint8_t *buf) +{ + int res; + GetBitContext gb; + init_get_bits(&gb, buf, GSM_MS_BLOCK_SIZE * 8); + res = gsm_decode_block(avctx, samples, &gb); + if (res < 0) + return res; + return gsm_decode_block(avctx, samples + GSM_FRAME_SIZE, &gb); +} diff --git a/ffmpeg/libavcodec/msgsmdec.h b/ffmpeg/libavcodec/msgsmdec.h new file mode 100644 index 0000000..3bfd1fd --- /dev/null +++ b/ffmpeg/libavcodec/msgsmdec.h @@ -0,0 +1,30 @@ +/* + * gsm 06.10 decoder, Microsoft variant + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_MSGSMDEC_H +#define AVCODEC_MSGSMDEC_H + +#include "avcodec.h" + +int ff_msgsm_decode_block(AVCodecContext *avctx, int16_t *samples, + const uint8_t *buf); + +#endif /* AVCODEC_MSGSMDEC_H */ diff --git a/ffmpeg/libavcodec/msmpeg4.c b/ffmpeg/libavcodec/msmpeg4.c new file mode 100644 index 0000000..395dffc --- /dev/null +++ b/ffmpeg/libavcodec/msmpeg4.c @@ -0,0 +1,1269 @@ +/* + * MSMPEG4 backend for encoder and decoder + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * msmpeg4v1 & v2 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 + */ + +/** + * @file + * MSMPEG4 backend for encoder and decoder + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "msmpeg4.h" +#include "libavutil/x86/asm.h" +#include "h263.h" +#include "mpeg4video.h" +#include "msmpeg4data.h" +#include "vc1data.h" +#include "libavutil/imgutils.h" + +/* + * You can also call this codec : MPEG4 with a twist ! + * + * TODO: + * - (encoding) select best mv table (two choices) + * - (encoding) select best vlc/dc table + */ +//#define DEBUG + +#define DC_VLC_BITS 9 +#define V2_INTRA_CBPC_VLC_BITS 3 +#define V2_MB_TYPE_VLC_BITS 7 +#define MV_VLC_BITS 9 +#define V2_MV_VLC_BITS 9 +#define TEX_VLC_BITS 9 + +#define DEFAULT_INTER_INDEX 3 + +/* This table is practically identical to the one from h263 + * except that it is inverted. */ +static av_cold void init_h263_dc_for_msmpeg4(void) +{ + int level, uni_code, uni_len; + + if(ff_v2_dc_chroma_table[255 + 256][1]) + return; + + for(level=-256; level<256; level++){ + int size, v, l; + /* find number of bits */ + size = 0; + v = abs(level); + while (v) { + v >>= 1; + size++; + } + + if (level < 0) + l= (-level) ^ ((1 << size) - 1); + else + l= level; + + /* luminance h263 */ + uni_code= ff_mpeg4_DCtab_lum[size][0]; + uni_len = ff_mpeg4_DCtab_lum[size][1]; + uni_code ^= (1< 0) { + uni_code<<=size; uni_code|=l; + uni_len+=size; + if (size > 8){ + uni_code<<=1; uni_code|=1; + uni_len++; + } + } + ff_v2_dc_lum_table[level + 256][0] = uni_code; + ff_v2_dc_lum_table[level + 256][1] = uni_len; + + /* chrominance h263 */ + uni_code= ff_mpeg4_DCtab_chrom[size][0]; + uni_len = ff_mpeg4_DCtab_chrom[size][1]; + uni_code ^= (1< 0) { + uni_code<<=size; uni_code|=l; + uni_len+=size; + if (size > 8){ + uni_code<<=1; uni_code|=1; + uni_len++; + } + } + ff_v2_dc_chroma_table[level + 256][0] = uni_code; + ff_v2_dc_chroma_table[level + 256][1] = uni_len; + + } +} + +av_cold void ff_msmpeg4_common_init(MpegEncContext *s) +{ + switch(s->msmpeg4_version){ + case 1: + case 2: + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + break; + case 3: + if(s->workaround_bugs){ + s->y_dc_scale_table= ff_old_ff_y_dc_scale_table; + s->c_dc_scale_table= ff_wmv1_c_dc_scale_table; + } else{ + s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; + s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table; + } + break; + case 4: + case 5: + s->y_dc_scale_table= ff_wmv1_y_dc_scale_table; + s->c_dc_scale_table= ff_wmv1_c_dc_scale_table; + break; +#if CONFIG_VC1_DECODER + case 6: + s->y_dc_scale_table= ff_wmv3_dc_scale_table; + s->c_dc_scale_table= ff_wmv3_dc_scale_table; + break; +#endif + + } + + + if(s->msmpeg4_version>=4){ + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable , ff_wmv1_scantable[1]); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_wmv1_scantable[2]); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_wmv1_scantable[3]); + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable , ff_wmv1_scantable[0]); + } + //Note the default tables are set in common_init in mpegvideo.c + + init_h263_dc_for_msmpeg4(); +} + +/* predict coded block */ +int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr) +{ + int xy, wrap, pred, a, b, c; + + xy = s->block_index[n]; + wrap = s->b8_stride; + + /* B C + * A X + */ + a = s->coded_block[xy - 1 ]; + b = s->coded_block[xy - 1 - wrap]; + c = s->coded_block[xy - wrap]; + + if (b == c) { + pred = a; + } else { + pred = c; + } + + /* store value */ + *coded_block_ptr = &s->coded_block[xy]; + + return pred; +} + +static inline int msmpeg4v1_pred_dc(MpegEncContext * s, int n, + int32_t **dc_val_ptr) +{ + int i; + + if (n < 4) { + i= 0; + } else { + i= n-3; + } + + *dc_val_ptr= &s->last_dc[i]; + return s->last_dc[i]; +} + +static int get_dc(uint8_t *src, int stride, int scale) +{ + int y; + int sum=0; + for(y=0; y<8; y++){ + int x; + for(x=0; x<8; x++){ + sum+=src[x + y*stride]; + } + } + return FASTDIV((sum + (scale>>1)), scale); +} + +/* dir = 0: left, dir = 1: top prediction */ +int ff_msmpeg4_pred_dc(MpegEncContext *s, int n, + int16_t **dc_val_ptr, int *dir_ptr) +{ + int a, b, c, wrap, pred, scale; + int16_t *dc_val; + + /* find prediction */ + if (n < 4) { + scale = s->y_dc_scale; + } else { + scale = s->c_dc_scale; + } + + wrap = s->block_wrap[n]; + dc_val= s->dc_val[0] + s->block_index[n]; + + /* B C + * A X + */ + a = dc_val[ - 1]; + b = dc_val[ - 1 - wrap]; + c = dc_val[ - wrap]; + + if(s->first_slice_line && (n&2)==0 && s->msmpeg4_version<4){ + b=c=1024; + } + + /* XXX: the following solution consumes divisions, but it does not + necessitate to modify mpegvideo.c. The problem comes from the + fact they decided to store the quantized DC (which would lead + to problems if Q could vary !) */ +#if ARCH_X86 && HAVE_7REGS && HAVE_EBX_AVAILABLE + __asm__ volatile( + "movl %3, %%eax \n\t" + "shrl $1, %%eax \n\t" + "addl %%eax, %2 \n\t" + "addl %%eax, %1 \n\t" + "addl %0, %%eax \n\t" + "mull %4 \n\t" + "movl %%edx, %0 \n\t" + "movl %1, %%eax \n\t" + "mull %4 \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%eax \n\t" + "mull %4 \n\t" + "movl %%edx, %2 \n\t" + : "+b" (a), "+c" (b), "+D" (c) + : "g" (scale), "S" (ff_inverse[scale]) + : "%eax", "%edx" + ); +#else + /* #elif ARCH_ALPHA */ + /* Divisions are extremely costly on Alpha; optimize the most + common case. But they are costly everywhere... + */ + if (scale == 8) { + a = (a + (8 >> 1)) / 8; + b = (b + (8 >> 1)) / 8; + c = (c + (8 >> 1)) / 8; + } else { + a = FASTDIV((a + (scale >> 1)), scale); + b = FASTDIV((b + (scale >> 1)), scale); + c = FASTDIV((c + (scale >> 1)), scale); + } +#endif + /* XXX: WARNING: they did not choose the same test as MPEG4. This + is very important ! */ + if(s->msmpeg4_version>3){ + if(s->inter_intra_pred){ + uint8_t *dest; + int wrap; + + if(n==1){ + pred=a; + *dir_ptr = 0; + }else if(n==2){ + pred=c; + *dir_ptr = 1; + }else if(n==3){ + if (abs(a - b) < abs(b - c)) { + pred = c; + *dir_ptr = 1; + } else { + pred = a; + *dir_ptr = 0; + } + }else{ + if(n<4){ + wrap= s->linesize; + dest= s->current_picture.f.data[0] + (((n >> 1) + 2*s->mb_y) * 8* wrap ) + ((n & 1) + 2*s->mb_x) * 8; + }else{ + wrap= s->uvlinesize; + dest= s->current_picture.f.data[n - 3] + (s->mb_y * 8 * wrap) + s->mb_x * 8; + } + if(s->mb_x==0) a= (1024 + (scale>>1))/scale; + else a= get_dc(dest-8, wrap, scale*8); + if(s->mb_y==0) c= (1024 + (scale>>1))/scale; + else c= get_dc(dest-8*wrap, wrap, scale*8); + + if (s->h263_aic_dir==0) { + pred= a; + *dir_ptr = 0; + }else if (s->h263_aic_dir==1) { + if(n==0){ + pred= c; + *dir_ptr = 1; + }else{ + pred= a; + *dir_ptr = 0; + } + }else if (s->h263_aic_dir==2) { + if(n==0){ + pred= a; + *dir_ptr = 0; + }else{ + pred= c; + *dir_ptr = 1; + } + } else { + pred= c; + *dir_ptr = 1; + } + } + }else{ + if (abs(a - b) < abs(b - c)) { + pred = c; + *dir_ptr = 1; + } else { + pred = a; + *dir_ptr = 0; + } + } + }else{ + if (abs(a - b) <= abs(b - c)) { + pred = c; + *dir_ptr = 1; + } else { + pred = a; + *dir_ptr = 0; + } + } + + /* update predictor */ + *dc_val_ptr = &dc_val[0]; + return pred; +} + +/****************************************/ +/* decoding stuff */ + +VLC ff_mb_non_intra_vlc[4]; +static VLC v2_dc_lum_vlc; +static VLC v2_dc_chroma_vlc; +static VLC v2_intra_cbpc_vlc; +static VLC v2_mb_type_vlc; +static VLC v2_mv_vlc; +VLC ff_inter_intra_vlc; + +/* This is identical to h263 except that its range is multiplied by 2. */ +static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code) +{ + int code, val, sign, shift; + + code = get_vlc2(&s->gb, v2_mv_vlc.table, V2_MV_VLC_BITS, 2); + av_dlog(s, "MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred); + if (code < 0) + return 0xffff; + + if (code == 0) + return pred; + sign = get_bits1(&s->gb); + shift = f_code - 1; + val = code; + if (shift) { + val = (val - 1) << shift; + val |= get_bits(&s->gb, shift); + val++; + } + if (sign) + val = -val; + + val += pred; + if (val <= -64) + val += 64; + else if (val >= 64) + val -= 64; + + return val; +} + +static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64]) +{ + int cbp, code, i; + uint32_t * const mb_type_ptr = &s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride]; + + if (s->pict_type == AV_PICTURE_TYPE_P) { + if (s->use_skip_mb_code) { + if (get_bits1(&s->gb)) { + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = 1; + *mb_type_ptr = MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16; + return 0; + } + } + + if(s->msmpeg4_version==2) + code = get_vlc2(&s->gb, v2_mb_type_vlc.table, V2_MB_TYPE_VLC_BITS, 1); + else + code = get_vlc2(&s->gb, ff_h263_inter_MCBPC_vlc.table, INTER_MCBPC_VLC_BITS, 2); + if(code<0 || code>7){ + av_log(s->avctx, AV_LOG_ERROR, "cbpc %d invalid at %d %d\n", code, s->mb_x, s->mb_y); + return -1; + } + + s->mb_intra = code >>2; + + cbp = code & 0x3; + } else { + s->mb_intra = 1; + if(s->msmpeg4_version==2) + cbp= get_vlc2(&s->gb, v2_intra_cbpc_vlc.table, V2_INTRA_CBPC_VLC_BITS, 1); + else + cbp= get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 1); + if(cbp<0 || cbp>3){ + av_log(s->avctx, AV_LOG_ERROR, "cbpc %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y); + return -1; + } + } + + if (!s->mb_intra) { + int mx, my, cbpy; + + cbpy= get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1); + if(cbpy<0){ + av_log(s->avctx, AV_LOG_ERROR, "cbpy %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y); + return -1; + } + + cbp|= cbpy<<2; + if(s->msmpeg4_version==1 || (cbp&3) != 3) cbp^= 0x3C; + + ff_h263_pred_motion(s, 0, 0, &mx, &my); + mx= msmpeg4v2_decode_motion(s, mx, 1); + my= msmpeg4v2_decode_motion(s, my, 1); + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + *mb_type_ptr = MB_TYPE_L0 | MB_TYPE_16x16; + } else { + if(s->msmpeg4_version==2){ + s->ac_pred = get_bits1(&s->gb); + cbp|= get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors + } else{ + s->ac_pred = 0; + cbp|= get_vlc2(&s->gb, ff_h263_cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors + if(s->pict_type==AV_PICTURE_TYPE_P) cbp^=0x3C; + } + *mb_type_ptr = MB_TYPE_INTRA; + } + + s->dsp.clear_blocks(s->block[0]); + for (i = 0; i < 6; i++) { + if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) + { + av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + return 0; +} + +static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) +{ + int cbp, code, i; + uint8_t *coded_val; + uint32_t * const mb_type_ptr = &s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride]; + + if (s->pict_type == AV_PICTURE_TYPE_P) { + if (s->use_skip_mb_code) { + if (get_bits1(&s->gb)) { + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = 1; + *mb_type_ptr = MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16; + + return 0; + } + } + + code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[DEFAULT_INTER_INDEX].table, MB_NON_INTRA_VLC_BITS, 3); + if (code < 0) + return -1; + //s->mb_intra = (code & 0x40) ? 0 : 1; + s->mb_intra = (~code & 0x40) >> 6; + + cbp = code & 0x3f; + } else { + s->mb_intra = 1; + code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + if (code < 0) + return -1; + /* predict coded block pattern */ + cbp = 0; + for(i=0;i<6;i++) { + int val = ((code >> (5 - i)) & 1); + if (i < 4) { + int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - i); + } + } + + if (!s->mb_intra) { + int mx, my; + if(s->per_mb_rl_table && cbp){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + ff_h263_pred_motion(s, 0, 0, &mx, &my); + if (ff_msmpeg4_decode_motion(s, &mx, &my) < 0) + return -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + *mb_type_ptr = MB_TYPE_L0 | MB_TYPE_16x16; + } else { + av_dlog(s, "I at %d %d %d %06X\n", s->mb_x, s->mb_y, + ((cbp & 3) ? 1 : 0) +((cbp & 0x3C)? 2 : 0), + show_bits(&s->gb, 24)); + s->ac_pred = get_bits1(&s->gb); + *mb_type_ptr = MB_TYPE_INTRA; + if(s->inter_intra_pred){ + s->h263_aic_dir= get_vlc2(&s->gb, ff_inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); + av_dlog(s, "%d%d %d %d/", + s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); + } + if(s->per_mb_rl_table && cbp){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + } + + s->dsp.clear_blocks(s->block[0]); + for (i = 0; i < 6; i++) { + if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) + { + av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + + return 0; +} + +/* init all vlc decoding tables */ +av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + static volatile int done = 0; + int i, ret; + MVTable *mv; + + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) + return ret; + + if (ff_h263_decode_init(avctx) < 0) + return -1; + + ff_msmpeg4_common_init(s); + + if (!done) { + for(i=0;ivlc, MV_VLC_BITS, mv->n + 1, + mv->table_mv_bits, 1, 1, + mv->table_mv_code, 2, 2, 3714); + mv = &ff_mv_tables[1]; + INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, mv->n + 1, + mv->table_mv_bits, 1, 1, + mv->table_mv_code, 2, 2, 2694); + + INIT_VLC_STATIC(&ff_msmp4_dc_luma_vlc[0], DC_VLC_BITS, 120, + &ff_table0_dc_lum[0][1], 8, 4, + &ff_table0_dc_lum[0][0], 8, 4, 1158); + INIT_VLC_STATIC(&ff_msmp4_dc_chroma_vlc[0], DC_VLC_BITS, 120, + &ff_table0_dc_chroma[0][1], 8, 4, + &ff_table0_dc_chroma[0][0], 8, 4, 1118); + INIT_VLC_STATIC(&ff_msmp4_dc_luma_vlc[1], DC_VLC_BITS, 120, + &ff_table1_dc_lum[0][1], 8, 4, + &ff_table1_dc_lum[0][0], 8, 4, 1476); + INIT_VLC_STATIC(&ff_msmp4_dc_chroma_vlc[1], DC_VLC_BITS, 120, + &ff_table1_dc_chroma[0][1], 8, 4, + &ff_table1_dc_chroma[0][0], 8, 4, 1216); + + INIT_VLC_STATIC(&v2_dc_lum_vlc, DC_VLC_BITS, 512, + &ff_v2_dc_lum_table[0][1], 8, 4, + &ff_v2_dc_lum_table[0][0], 8, 4, 1472); + INIT_VLC_STATIC(&v2_dc_chroma_vlc, DC_VLC_BITS, 512, + &ff_v2_dc_chroma_table[0][1], 8, 4, + &ff_v2_dc_chroma_table[0][0], 8, 4, 1506); + + INIT_VLC_STATIC(&v2_intra_cbpc_vlc, V2_INTRA_CBPC_VLC_BITS, 4, + &ff_v2_intra_cbpc[0][1], 2, 1, + &ff_v2_intra_cbpc[0][0], 2, 1, 8); + INIT_VLC_STATIC(&v2_mb_type_vlc, V2_MB_TYPE_VLC_BITS, 8, + &ff_v2_mb_type[0][1], 2, 1, + &ff_v2_mb_type[0][0], 2, 1, 128); + INIT_VLC_STATIC(&v2_mv_vlc, V2_MV_VLC_BITS, 33, + &ff_mvtab[0][1], 2, 1, + &ff_mvtab[0][0], 2, 1, 538); + + INIT_VLC_STATIC(&ff_mb_non_intra_vlc[0], MB_NON_INTRA_VLC_BITS, 128, + &ff_wmv2_inter_table[0][0][1], 8, 4, + &ff_wmv2_inter_table[0][0][0], 8, 4, 1636); + INIT_VLC_STATIC(&ff_mb_non_intra_vlc[1], MB_NON_INTRA_VLC_BITS, 128, + &ff_wmv2_inter_table[1][0][1], 8, 4, + &ff_wmv2_inter_table[1][0][0], 8, 4, 2648); + INIT_VLC_STATIC(&ff_mb_non_intra_vlc[2], MB_NON_INTRA_VLC_BITS, 128, + &ff_wmv2_inter_table[2][0][1], 8, 4, + &ff_wmv2_inter_table[2][0][0], 8, 4, 1532); + INIT_VLC_STATIC(&ff_mb_non_intra_vlc[3], MB_NON_INTRA_VLC_BITS, 128, + &ff_wmv2_inter_table[3][0][1], 8, 4, + &ff_wmv2_inter_table[3][0][0], 8, 4, 2488); + + INIT_VLC_STATIC(&ff_msmp4_mb_i_vlc, MB_INTRA_VLC_BITS, 64, + &ff_msmp4_mb_i_table[0][1], 4, 2, + &ff_msmp4_mb_i_table[0][0], 4, 2, 536); + + INIT_VLC_STATIC(&ff_inter_intra_vlc, INTER_INTRA_VLC_BITS, 4, + &ff_table_inter_intra[0][1], 2, 1, + &ff_table_inter_intra[0][0], 2, 1, 8); + done = 1; + } + + switch(s->msmpeg4_version){ + case 1: + case 2: + s->decode_mb= msmpeg4v12_decode_mb; + break; + case 3: + case 4: + s->decode_mb= msmpeg4v34_decode_mb; + break; + case 5: + if (CONFIG_WMV2_DECODER) + s->decode_mb= ff_wmv2_decode_mb; + case 6: + //FIXME + TODO VC1 decode mb + break; + } + + s->slice_height= s->mb_height; //to avoid 1/0 if the first frame is not a keyframe + + return 0; +} + +int ff_msmpeg4_decode_picture_header(MpegEncContext * s) +{ + int code; + + if(s->msmpeg4_version==1){ + int start_code = get_bits_long(&s->gb, 32); + if(start_code!=0x00000100){ + av_log(s->avctx, AV_LOG_ERROR, "invalid startcode\n"); + return -1; + } + + skip_bits(&s->gb, 5); // frame number */ + } + + s->pict_type = get_bits(&s->gb, 2) + 1; + if (s->pict_type != AV_PICTURE_TYPE_I && + s->pict_type != AV_PICTURE_TYPE_P){ + av_log(s->avctx, AV_LOG_ERROR, "invalid picture type\n"); + return -1; + } +#if 0 +{ + static int had_i=0; + if(s->pict_type == AV_PICTURE_TYPE_I) had_i=1; + if(!had_i) return -1; +} +#endif + s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + if(s->qscale==0){ + av_log(s->avctx, AV_LOG_ERROR, "invalid qscale\n"); + return -1; + } + + if (s->pict_type == AV_PICTURE_TYPE_I) { + code = get_bits(&s->gb, 5); + if(s->msmpeg4_version==1){ + if(code==0 || code>s->mb_height){ + av_log(s->avctx, AV_LOG_ERROR, "invalid slice height %d\n", code); + return -1; + } + + s->slice_height = code; + }else{ + /* 0x17: one slice, 0x18: two slices, ... */ + if (code < 0x17){ + av_log(s->avctx, AV_LOG_ERROR, "error, slice code was %X\n", code); + return -1; + } + + s->slice_height = s->mb_height / (code - 0x16); + } + + switch(s->msmpeg4_version){ + case 1: + case 2: + s->rl_chroma_table_index = 2; + s->rl_table_index = 2; + + s->dc_table_index = 0; //not used + break; + case 3: + s->rl_chroma_table_index = decode012(&s->gb); + s->rl_table_index = decode012(&s->gb); + + s->dc_table_index = get_bits1(&s->gb); + break; + case 4: + ff_msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8); + + if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + + if(!s->per_mb_rl_table){ + s->rl_chroma_table_index = decode012(&s->gb); + s->rl_table_index = decode012(&s->gb); + } + + s->dc_table_index = get_bits1(&s->gb); + s->inter_intra_pred= 0; + break; + } + s->no_rounding = 1; + if(s->avctx->debug&FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d slice:%d \n", + s->qscale, + s->rl_chroma_table_index, + s->rl_table_index, + s->dc_table_index, + s->per_mb_rl_table, + s->slice_height); + } else { + switch(s->msmpeg4_version){ + case 1: + case 2: + if(s->msmpeg4_version==1) + s->use_skip_mb_code = 1; + else + s->use_skip_mb_code = get_bits1(&s->gb); + s->rl_table_index = 2; + s->rl_chroma_table_index = s->rl_table_index; + s->dc_table_index = 0; //not used + s->mv_table_index = 0; + break; + case 3: + s->use_skip_mb_code = get_bits1(&s->gb); + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + + s->dc_table_index = get_bits1(&s->gb); + + s->mv_table_index = get_bits1(&s->gb); + break; + case 4: + s->use_skip_mb_code = get_bits1(&s->gb); + + if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + + if(!s->per_mb_rl_table){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + s->dc_table_index = get_bits1(&s->gb); + + s->mv_table_index = get_bits1(&s->gb); + s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + break; + } + + if(s->avctx->debug&FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_DEBUG, "skip:%d rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d \n", + s->use_skip_mb_code, + s->rl_table_index, + s->rl_chroma_table_index, + s->dc_table_index, + s->mv_table_index, + s->per_mb_rl_table, + s->qscale); + + if(s->flipflop_rounding){ + s->no_rounding ^= 1; + }else{ + s->no_rounding = 0; + } + } + av_dlog(s->avctx, "%d %d %d %d %d\n", s->pict_type, s->bit_rate, + s->inter_intra_pred, s->width, s->height); + + s->esc3_level_length= 0; + s->esc3_run_length= 0; + + return 0; +} + +int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size) +{ + int left= buf_size*8 - get_bits_count(&s->gb); + int length= s->msmpeg4_version>=3 ? 17 : 16; + /* the alt_bitstream reader could read over the end so we need to check it */ + if(left>=length && leftgb, 5); /* fps */ + s->bit_rate= get_bits(&s->gb, 11)*1024; + if(s->msmpeg4_version>=3) + s->flipflop_rounding= get_bits1(&s->gb); + else + s->flipflop_rounding= 0; + } + else if(leftflipflop_rounding= 0; + if(s->msmpeg4_version != 2) + av_log(s->avctx, AV_LOG_ERROR, "ext header missing, %d left\n", left); + } + else + { + av_log(s->avctx, AV_LOG_ERROR, "I frame too long, ignoring ext header\n"); + } + + return 0; +} + +static int msmpeg4_decode_dc(MpegEncContext * s, int n, int *dir_ptr) +{ + int level, pred; + + if(s->msmpeg4_version<=2){ + if (n < 4) { + level = get_vlc2(&s->gb, v2_dc_lum_vlc.table, DC_VLC_BITS, 3); + } else { + level = get_vlc2(&s->gb, v2_dc_chroma_vlc.table, DC_VLC_BITS, 3); + } + if (level < 0) + return -1; + level-=256; + }else{ //FIXME optimize use unified tables & index + if (n < 4) { + level = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + level = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (level < 0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal dc vlc\n"); + return -1; + } + + if (level == DC_MAX) { + level = get_bits(&s->gb, 8); + if (get_bits1(&s->gb)) + level = -level; + } else if (level != 0) { + if (get_bits1(&s->gb)) + level = -level; + } + } + + if(s->msmpeg4_version==1){ + int32_t *dc_val; + pred = msmpeg4v1_pred_dc(s, n, &dc_val); + level += pred; + + /* update predictor */ + *dc_val= level; + }else{ + int16_t *dc_val; + pred = ff_msmpeg4_pred_dc(s, n, &dc_val, dir_ptr); + level += pred; + + /* update predictor */ + if (n < 4) { + *dc_val = level * s->y_dc_scale; + } else { + *dc_val = level * s->c_dc_scale; + } + } + + return level; +} + +//#define ERROR_DETAILS +int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, + int n, int coded, const uint8_t *scan_table) +{ + int level, i, last, run, run_diff; + int av_uninit(dc_pred_dir); + RLTable *rl; + RL_VLC_ELEM *rl_vlc; + int qmul, qadd; + + if (s->mb_intra) { + qmul=1; + qadd=0; + + /* DC coef */ + level = msmpeg4_decode_dc(s, n, &dc_pred_dir); + + if (level < 0){ + av_log(s->avctx, AV_LOG_ERROR, "dc overflow- block: %d qscale: %d//\n", n, s->qscale); + if(s->inter_intra_pred) level=0; + else return -1; + } + if (n < 4) { + rl = &ff_rl_table[s->rl_table_index]; + if(level > 256*s->y_dc_scale){ + av_log(s->avctx, AV_LOG_ERROR, "dc overflow+ L qscale: %d//\n", s->qscale); + if(!s->inter_intra_pred) return -1; + } + } else { + rl = &ff_rl_table[3 + s->rl_chroma_table_index]; + if(level > 256*s->c_dc_scale){ + av_log(s->avctx, AV_LOG_ERROR, "dc overflow+ C qscale: %d//\n", s->qscale); + if(!s->inter_intra_pred) return -1; + } + } + block[0] = level; + + run_diff = s->msmpeg4_version >= 4; + i = 0; + if (!coded) { + goto not_coded; + } + if (s->ac_pred) { + if (dc_pred_dir == 0) + scan_table = s->intra_v_scantable.permutated; /* left */ + else + scan_table = s->intra_h_scantable.permutated; /* top */ + } else { + scan_table = s->intra_scantable.permutated; + } + rl_vlc= rl->rl_vlc[0]; + } else { + qmul = s->qscale << 1; + qadd = (s->qscale - 1) | 1; + i = -1; + rl = &ff_rl_table[3 + s->rl_table_index]; + + if(s->msmpeg4_version==2) + run_diff = 0; + else + run_diff = 1; + + if (!coded) { + s->block_last_index[n] = i; + return 0; + } + if(!scan_table) + scan_table = s->inter_scantable.permutated; + rl_vlc= rl->rl_vlc[s->qscale]; + } + { + OPEN_READER(re, &s->gb); + for(;;) { + UPDATE_CACHE(re, &s->gb); + GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2, 0); + if (level==0) { + int cache; + cache= GET_CACHE(re, &s->gb); + /* escape */ + if (s->msmpeg4_version==1 || (cache&0x80000000)==0) { + if (s->msmpeg4_version==1 || (cache&0x40000000)==0) { + /* third escape */ + if(s->msmpeg4_version!=1) LAST_SKIP_BITS(re, &s->gb, 2); + UPDATE_CACHE(re, &s->gb); + if(s->msmpeg4_version<=3){ + last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); + run= SHOW_UBITS(re, &s->gb, 6); SKIP_CACHE(re, &s->gb, 6); + level= SHOW_SBITS(re, &s->gb, 8); + SKIP_COUNTER(re, &s->gb, 1+6+8); + }else{ + int sign; + last= SHOW_UBITS(re, &s->gb, 1); SKIP_BITS(re, &s->gb, 1); + if(!s->esc3_level_length){ + int ll; + av_dlog(s->avctx, "ESC-3 %X at %d %d\n", + show_bits(&s->gb, 24), s->mb_x, s->mb_y); + if(s->qscale<8){ + ll= SHOW_UBITS(re, &s->gb, 3); SKIP_BITS(re, &s->gb, 3); + if(ll==0){ + ll= 8+SHOW_UBITS(re, &s->gb, 1); SKIP_BITS(re, &s->gb, 1); + } + }else{ + ll=2; + while(ll<8 && SHOW_UBITS(re, &s->gb, 1)==0){ + ll++; + SKIP_BITS(re, &s->gb, 1); + } + if(ll<8) SKIP_BITS(re, &s->gb, 1); + } + + s->esc3_level_length= ll; + s->esc3_run_length= SHOW_UBITS(re, &s->gb, 2) + 3; SKIP_BITS(re, &s->gb, 2); + UPDATE_CACHE(re, &s->gb); + } + run= SHOW_UBITS(re, &s->gb, s->esc3_run_length); + SKIP_BITS(re, &s->gb, s->esc3_run_length); + + sign= SHOW_UBITS(re, &s->gb, 1); + SKIP_BITS(re, &s->gb, 1); + + level= SHOW_UBITS(re, &s->gb, s->esc3_level_length); + SKIP_BITS(re, &s->gb, s->esc3_level_length); + if(sign) level= -level; + } + +#if 0 // waste of time / this will detect very few errors + { + const int abs_level= FFABS(level); + const int run1= run - rl->max_run[last][abs_level] - run_diff; + if(abs_level<=MAX_LEVEL && run<=MAX_RUN){ + if(abs_level <= rl->max_level[last][run]){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, vlc encoding possible\n"); + return DECODING_AC_LOST; + } + if(abs_level <= rl->max_level[last][run]*2){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 1 encoding possible\n"); + return DECODING_AC_LOST; + } + if(run1>=0 && abs_level <= rl->max_level[last][run1]){ + av_log(s->avctx, AV_LOG_ERROR, "illegal 3. esc, esc 2 encoding possible\n"); + return DECODING_AC_LOST; + } + } + } +#endif + //level = level * qmul + (level>0) * qadd - (level<=0) * qadd ; + if (level>0) level= level * qmul + qadd; + else level= level * qmul - qadd; +#if 0 // waste of time too :( + if(level>2048 || level<-2048){ + av_log(s->avctx, AV_LOG_ERROR, "|level| overflow in 3. esc\n"); + return DECODING_AC_LOST; + } +#endif + i+= run + 1; + if(last) i+=192; +#ifdef ERROR_DETAILS + if(run==66) + av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code in ESC3 level=%d\n", level); + else if((i>62 && i<192) || i>192+63) + av_log(s->avctx, AV_LOG_ERROR, "run overflow in ESC3 i=%d run=%d level=%d\n", i, run, level); +#endif + } else { + /* second escape */ + SKIP_BITS(re, &s->gb, 2); + GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2, 1); + i+= run + rl->max_run[run>>7][level/qmul] + run_diff; //FIXME opt indexing + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); +#ifdef ERROR_DETAILS + if(run==66) + av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code in ESC2 level=%d\n", level); + else if((i>62 && i<192) || i>192+63) + av_log(s->avctx, AV_LOG_ERROR, "run overflow in ESC2 i=%d run=%d level=%d\n", i, run, level); +#endif + } + } else { + /* first escape */ + SKIP_BITS(re, &s->gb, 1); + GET_RL_VLC(level, run, re, &s->gb, rl_vlc, TEX_VLC_BITS, 2, 1); + i+= run; + level = level + rl->max_level[run>>7][(run-1)&63] * qmul;//FIXME opt indexing + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); +#ifdef ERROR_DETAILS + if(run==66) + av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code in ESC1 level=%d\n", level); + else if((i>62 && i<192) || i>192+63) + av_log(s->avctx, AV_LOG_ERROR, "run overflow in ESC1 i=%d run=%d level=%d\n", i, run, level); +#endif + } + } else { + i+= run; + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); + LAST_SKIP_BITS(re, &s->gb, 1); +#ifdef ERROR_DETAILS + if(run==66) + av_log(s->avctx, AV_LOG_ERROR, "illegal vlc code level=%d\n", level); + else if((i>62 && i<192) || i>192+63) + av_log(s->avctx, AV_LOG_ERROR, "run overflow i=%d run=%d level=%d\n", i, run, level); +#endif + } + if (i > 62){ + i-= 192; + if(i&(~63)){ + const int left= get_bits_left(&s->gb); + if(((i+192 == 64 && level/qmul==-1) || !(s->err_recognition&(AV_EF_BITSTREAM|AV_EF_COMPLIANT))) && left>=0){ + av_log(s->avctx, AV_LOG_ERROR, "ignoring overflow at %d %d\n", s->mb_x, s->mb_y); + i = 63; + break; + }else{ + av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + } + + block[scan_table[i]] = level; + break; + } + + block[scan_table[i]] = level; + } + CLOSE_READER(re, &s->gb); + } + not_coded: + if (s->mb_intra) { + ff_mpeg4_pred_ac(s, block, n, dc_pred_dir); + if (s->ac_pred) { + i = 63; /* XXX: not optimal */ + } + } + if(s->msmpeg4_version>=4 && i>0) i=63; //FIXME/XXX optimize + s->block_last_index[n] = i; + + return 0; +} + +int ff_msmpeg4_decode_motion(MpegEncContext * s, + int *mx_ptr, int *my_ptr) +{ + MVTable *mv; + int code, mx, my; + + mv = &ff_mv_tables[s->mv_table_index]; + + code = get_vlc2(&s->gb, mv->vlc.table, MV_VLC_BITS, 2); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "illegal MV code at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + if (code == mv->n) { + mx = get_bits(&s->gb, 6); + my = get_bits(&s->gb, 6); + } else { + mx = mv->table_mvx[code]; + my = mv->table_mvy[code]; + } + + mx += *mx_ptr - 32; + my += *my_ptr - 32; + /* WARNING : they do not do exactly modulo encoding */ + if (mx <= -64) + mx += 64; + else if (mx >= 64) + mx -= 64; + + if (my <= -64) + my += 64; + else if (my >= 64) + my -= 64; + *mx_ptr = mx; + *my_ptr = my; + return 0; +} + +AVCodec ff_msmpeg4v1_decoder = { + .name = "msmpeg4v1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSMPEG4V1, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_msmpeg4_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 1"), + .pix_fmts = ff_pixfmt_list_420, +}; + +AVCodec ff_msmpeg4v2_decoder = { + .name = "msmpeg4v2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSMPEG4V2, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_msmpeg4_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), + .pix_fmts = ff_pixfmt_list_420, +}; + +AVCodec ff_msmpeg4v3_decoder = { + .name = "msmpeg4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSMPEG4V3, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_msmpeg4_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), + .pix_fmts = ff_pixfmt_list_420, +}; + +AVCodec ff_wmv1_decoder = { + .name = "wmv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV1, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_msmpeg4_decode_init, + .close = ff_h263_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), + .pix_fmts = ff_pixfmt_list_420, +}; diff --git a/ffmpeg/libavcodec/msmpeg4.h b/ffmpeg/libavcodec/msmpeg4.h new file mode 100644 index 0000000..a723888 --- /dev/null +++ b/ffmpeg/libavcodec/msmpeg4.h @@ -0,0 +1,68 @@ +/* + * MSMPEG4 backend for encoder and decoder + * copyright (c) 2007 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVCODEC_MSMPEG4_H +#define AVCODEC_MSMPEG4_H + +#include + +#include "config.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "msmpeg4data.h" +#include "put_bits.h" + +#define INTER_INTRA_VLC_BITS 3 +#define MB_NON_INTRA_VLC_BITS 9 +#define MB_INTRA_VLC_BITS 9 + +#define II_BITRATE 128*1024 +#define MBAC_BITRATE 50*1024 + +#define DC_MAX 119 + +extern VLC ff_mb_non_intra_vlc[4]; +extern VLC ff_inter_intra_vlc; + +void ff_msmpeg4_code012(PutBitContext *pb, int n); +void ff_msmpeg4_common_init(MpegEncContext *s); +void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n); +void ff_msmpeg4_handle_slices(MpegEncContext *s); +void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my); +int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, + uint8_t **coded_block_ptr); +int ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); +int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, + int n, int coded, const uint8_t *scan_table); +int ff_msmpeg4_pred_dc(MpegEncContext *s, int n, + int16_t **dc_val_ptr, int *dir_ptr); +int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]); + +#define CONFIG_MSMPEG4_DECODER (CONFIG_MSMPEG4V1_DECODER || \ + CONFIG_MSMPEG4V2_DECODER || \ + CONFIG_MSMPEG4V3_DECODER || \ + CONFIG_WMV2_DECODER || \ + CONFIG_VC1_DECODER) +#define CONFIG_MSMPEG4_ENCODER (CONFIG_MSMPEG4V2_ENCODER || \ + CONFIG_MSMPEG4V3_ENCODER || \ + CONFIG_WMV2_ENCODER) + +#endif /* AVCODEC_MSMPEG4_H */ diff --git a/ffmpeg/libavcodec/msmpeg4data.c b/ffmpeg/libavcodec/msmpeg4data.c new file mode 100644 index 0000000..50ba18c --- /dev/null +++ b/ffmpeg/libavcodec/msmpeg4data.c @@ -0,0 +1,2005 @@ +/* + * MSMPEG4 backend for encoder and decoder + * copyright (c) 2001 Fabrice Bellard + * copyright (c) 2002-2004 Michael Niedermayer + * + * msmpeg4v1 & v2 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 + */ + +/** + * @file + * MSMPEG4 data tables. + */ + +#include "msmpeg4data.h" + +uint32_t ff_v2_dc_lum_table[512][2]; +uint32_t ff_v2_dc_chroma_table[512][2]; +uint8_t ff_static_rl_table_store[NB_RL_TABLES][2][2 * MAX_RUN + MAX_LEVEL + 3]; + +VLC ff_msmp4_mb_i_vlc; +VLC ff_msmp4_dc_luma_vlc[2]; +VLC ff_msmp4_dc_chroma_vlc[2]; + +/* intra picture macroblock coded block pattern */ +const uint16_t ff_msmp4_mb_i_table[64][2] = { +{ 0x1, 1 },{ 0x17, 6 },{ 0x9, 5 },{ 0x5, 5 }, +{ 0x6, 5 },{ 0x47, 9 },{ 0x20, 7 },{ 0x10, 7 }, +{ 0x2, 5 },{ 0x7c, 9 },{ 0x3a, 7 },{ 0x1d, 7 }, +{ 0x2, 6 },{ 0xec, 9 },{ 0x77, 8 },{ 0x0, 8 }, +{ 0x3, 5 },{ 0xb7, 9 },{ 0x2c, 7 },{ 0x13, 7 }, +{ 0x1, 6 },{ 0x168, 10 },{ 0x46, 8 },{ 0x3f, 8 }, +{ 0x1e, 6 },{ 0x712, 13 },{ 0xb5, 9 },{ 0x42, 8 }, +{ 0x22, 7 },{ 0x1c5, 11 },{ 0x11e, 10 },{ 0x87, 9 }, +{ 0x6, 4 },{ 0x3, 9 },{ 0x1e, 7 },{ 0x1c, 6 }, +{ 0x12, 7 },{ 0x388, 12 },{ 0x44, 9 },{ 0x70, 9 }, +{ 0x1f, 6 },{ 0x23e, 11 },{ 0x39, 8 },{ 0x8e, 9 }, +{ 0x1, 7 },{ 0x1c6, 11 },{ 0xb6, 9 },{ 0x45, 9 }, +{ 0x14, 6 },{ 0x23f, 11 },{ 0x7d, 9 },{ 0x18, 9 }, +{ 0x7, 7 },{ 0x1c7, 11 },{ 0x86, 9 },{ 0x19, 9 }, +{ 0x15, 6 },{ 0x1db, 10 },{ 0x2, 9 },{ 0x46, 9 }, +{ 0xd, 8 },{ 0x713, 13 },{ 0x1da, 10 },{ 0x169, 10 }, +}; + +/* non intra picture macroblock coded block pattern + mb type */ +const uint32_t ff_table_mb_non_intra[128][2] = { +{ 0x40, 7 },{ 0x13c9, 13 },{ 0x9fd, 12 },{ 0x1fc, 15 }, +{ 0x9fc, 12 },{ 0xa83, 18 },{ 0x12d34, 17 },{ 0x83bc, 16 }, +{ 0x83a, 12 },{ 0x7f8, 17 },{ 0x3fd, 16 },{ 0x3ff, 16 }, +{ 0x79, 13 },{ 0xa82, 18 },{ 0x969d, 16 },{ 0x2a4, 16 }, +{ 0x978, 12 },{ 0x543, 17 },{ 0x41df, 15 },{ 0x7f9, 17 }, +{ 0x12f3, 13 },{ 0x25a6b, 18 },{ 0x25ef9, 18 },{ 0x3fa, 16 }, +{ 0x20ee, 14 },{ 0x969ab, 20 },{ 0x969c, 16 },{ 0x25ef8, 18 }, +{ 0x12d2, 13 },{ 0xa85, 18 },{ 0x969e, 16 },{ 0x4bc8, 15 }, +{ 0x3d, 12 },{ 0x12f7f, 17 },{ 0x2a2, 16 },{ 0x969f, 16 }, +{ 0x25ee, 14 },{ 0x12d355, 21 },{ 0x12f7d, 17 },{ 0x12f7e, 17 }, +{ 0x9e5, 12 },{ 0xa81, 18 },{ 0x4b4d4, 19 },{ 0x83bd, 16 }, +{ 0x78, 13 },{ 0x969b, 16 },{ 0x3fe, 16 },{ 0x2a5, 16 }, +{ 0x7e, 13 },{ 0xa80, 18 },{ 0x2a3, 16 },{ 0x3fb, 16 }, +{ 0x1076, 13 },{ 0xa84, 18 },{ 0x153, 15 },{ 0x4bc9, 15 }, +{ 0x55, 13 },{ 0x12d354, 21 },{ 0x4bde, 15 },{ 0x25e5, 14 }, +{ 0x25b, 10 },{ 0x4b4c, 15 },{ 0x96b, 12 },{ 0x96a, 12 }, +{ 0x1, 2 },{ 0x0, 7 },{ 0x26, 6 },{ 0x12b, 9 }, +{ 0x7, 3 },{ 0x20f, 10 },{ 0x4, 9 },{ 0x28, 12 }, +{ 0x6, 3 },{ 0x20a, 10 },{ 0x128, 9 },{ 0x2b, 12 }, +{ 0x11, 5 },{ 0x1b, 11 },{ 0x13a, 9 },{ 0x4ff, 11 }, +{ 0x3, 4 },{ 0x277, 10 },{ 0x106, 9 },{ 0x839, 12 }, +{ 0xb, 4 },{ 0x27b, 10 },{ 0x12c, 9 },{ 0x4bf, 11 }, +{ 0x9, 6 },{ 0x35, 12 },{ 0x27e, 10 },{ 0x13c8, 13 }, +{ 0x1, 6 },{ 0x4aa, 11 },{ 0x208, 10 },{ 0x29, 12 }, +{ 0x1, 4 },{ 0x254, 10 },{ 0x12e, 9 },{ 0x838, 12 }, +{ 0x24, 6 },{ 0x4f3, 11 },{ 0x276, 10 },{ 0x12f6, 13 }, +{ 0x1, 5 },{ 0x27a, 10 },{ 0x13e, 9 },{ 0x3e, 12 }, +{ 0x8, 6 },{ 0x413, 11 },{ 0xc, 10 },{ 0x4be, 11 }, +{ 0x14, 5 },{ 0x412, 11 },{ 0x253, 10 },{ 0x97a, 12 }, +{ 0x21, 6 },{ 0x4ab, 11 },{ 0x20b, 10 },{ 0x34, 12 }, +{ 0x15, 5 },{ 0x278, 10 },{ 0x252, 10 },{ 0x968, 12 }, +{ 0x5, 5 },{ 0xb, 10 },{ 0x9c, 8 },{ 0xe, 10 }, +}; + +/* dc table 0 */ + +const uint32_t ff_table0_dc_lum[120][2] = { +{ 0x1, 1 },{ 0x1, 2 },{ 0x1, 4 },{ 0x1, 5 }, +{ 0x5, 5 },{ 0x7, 5 },{ 0x8, 6 },{ 0xc, 6 }, +{ 0x0, 7 },{ 0x2, 7 },{ 0x12, 7 },{ 0x1a, 7 }, +{ 0x3, 8 },{ 0x7, 8 },{ 0x27, 8 },{ 0x37, 8 }, +{ 0x5, 9 },{ 0x4c, 9 },{ 0x6c, 9 },{ 0x6d, 9 }, +{ 0x8, 10 },{ 0x19, 10 },{ 0x9b, 10 },{ 0x1b, 10 }, +{ 0x9a, 10 },{ 0x13, 11 },{ 0x34, 11 },{ 0x35, 11 }, +{ 0x61, 12 },{ 0x48, 13 },{ 0xc4, 13 },{ 0x4a, 13 }, +{ 0xc6, 13 },{ 0xc7, 13 },{ 0x92, 14 },{ 0x18b, 14 }, +{ 0x93, 14 },{ 0x183, 14 },{ 0x182, 14 },{ 0x96, 14 }, +{ 0x97, 14 },{ 0x180, 14 },{ 0x314, 15 },{ 0x315, 15 }, +{ 0x605, 16 },{ 0x604, 16 },{ 0x606, 16 },{ 0xc0e, 17 }, +{ 0x303cd, 23 },{ 0x303c9, 23 },{ 0x303c8, 23 },{ 0x303ca, 23 }, +{ 0x303cb, 23 },{ 0x303cc, 23 },{ 0x303ce, 23 },{ 0x303cf, 23 }, +{ 0x303d0, 23 },{ 0x303d1, 23 },{ 0x303d2, 23 },{ 0x303d3, 23 }, +{ 0x303d4, 23 },{ 0x303d5, 23 },{ 0x303d6, 23 },{ 0x303d7, 23 }, +{ 0x303d8, 23 },{ 0x303d9, 23 },{ 0x303da, 23 },{ 0x303db, 23 }, +{ 0x303dc, 23 },{ 0x303dd, 23 },{ 0x303de, 23 },{ 0x303df, 23 }, +{ 0x303e0, 23 },{ 0x303e1, 23 },{ 0x303e2, 23 },{ 0x303e3, 23 }, +{ 0x303e4, 23 },{ 0x303e5, 23 },{ 0x303e6, 23 },{ 0x303e7, 23 }, +{ 0x303e8, 23 },{ 0x303e9, 23 },{ 0x303ea, 23 },{ 0x303eb, 23 }, +{ 0x303ec, 23 },{ 0x303ed, 23 },{ 0x303ee, 23 },{ 0x303ef, 23 }, +{ 0x303f0, 23 },{ 0x303f1, 23 },{ 0x303f2, 23 },{ 0x303f3, 23 }, +{ 0x303f4, 23 },{ 0x303f5, 23 },{ 0x303f6, 23 },{ 0x303f7, 23 }, +{ 0x303f8, 23 },{ 0x303f9, 23 },{ 0x303fa, 23 },{ 0x303fb, 23 }, +{ 0x303fc, 23 },{ 0x303fd, 23 },{ 0x303fe, 23 },{ 0x303ff, 23 }, +{ 0x60780, 24 },{ 0x60781, 24 },{ 0x60782, 24 },{ 0x60783, 24 }, +{ 0x60784, 24 },{ 0x60785, 24 },{ 0x60786, 24 },{ 0x60787, 24 }, +{ 0x60788, 24 },{ 0x60789, 24 },{ 0x6078a, 24 },{ 0x6078b, 24 }, +{ 0x6078c, 24 },{ 0x6078d, 24 },{ 0x6078e, 24 },{ 0x6078f, 24 }, +}; + +const uint32_t ff_table0_dc_chroma[120][2] = { +{ 0x0, 2 },{ 0x1, 2 },{ 0x5, 3 },{ 0x9, 4 }, +{ 0xd, 4 },{ 0x11, 5 },{ 0x1d, 5 },{ 0x1f, 5 }, +{ 0x21, 6 },{ 0x31, 6 },{ 0x38, 6 },{ 0x33, 6 }, +{ 0x39, 6 },{ 0x3d, 6 },{ 0x61, 7 },{ 0x79, 7 }, +{ 0x80, 8 },{ 0xc8, 8 },{ 0xca, 8 },{ 0xf0, 8 }, +{ 0x81, 8 },{ 0xc0, 8 },{ 0xc9, 8 },{ 0x107, 9 }, +{ 0x106, 9 },{ 0x196, 9 },{ 0x183, 9 },{ 0x1e3, 9 }, +{ 0x1e2, 9 },{ 0x20a, 10 },{ 0x20b, 10 },{ 0x609, 11 }, +{ 0x412, 11 },{ 0x413, 11 },{ 0x60b, 11 },{ 0x411, 11 }, +{ 0x60a, 11 },{ 0x65f, 11 },{ 0x410, 11 },{ 0x65d, 11 }, +{ 0x65e, 11 },{ 0xcb8, 12 },{ 0xc10, 12 },{ 0xcb9, 12 }, +{ 0x1823, 13 },{ 0x3045, 14 },{ 0x6089, 15 },{ 0xc110, 16 }, +{ 0x304448, 22 },{ 0x304449, 22 },{ 0x30444a, 22 },{ 0x30444b, 22 }, +{ 0x30444c, 22 },{ 0x30444d, 22 },{ 0x30444e, 22 },{ 0x30444f, 22 }, +{ 0x304450, 22 },{ 0x304451, 22 },{ 0x304452, 22 },{ 0x304453, 22 }, +{ 0x304454, 22 },{ 0x304455, 22 },{ 0x304456, 22 },{ 0x304457, 22 }, +{ 0x304458, 22 },{ 0x304459, 22 },{ 0x30445a, 22 },{ 0x30445b, 22 }, +{ 0x30445c, 22 },{ 0x30445d, 22 },{ 0x30445e, 22 },{ 0x30445f, 22 }, +{ 0x304460, 22 },{ 0x304461, 22 },{ 0x304462, 22 },{ 0x304463, 22 }, +{ 0x304464, 22 },{ 0x304465, 22 },{ 0x304466, 22 },{ 0x304467, 22 }, +{ 0x304468, 22 },{ 0x304469, 22 },{ 0x30446a, 22 },{ 0x30446b, 22 }, +{ 0x30446c, 22 },{ 0x30446d, 22 },{ 0x30446e, 22 },{ 0x30446f, 22 }, +{ 0x304470, 22 },{ 0x304471, 22 },{ 0x304472, 22 },{ 0x304473, 22 }, +{ 0x304474, 22 },{ 0x304475, 22 },{ 0x304476, 22 },{ 0x304477, 22 }, +{ 0x304478, 22 },{ 0x304479, 22 },{ 0x30447a, 22 },{ 0x30447b, 22 }, +{ 0x30447c, 22 },{ 0x30447d, 22 },{ 0x30447e, 22 },{ 0x30447f, 22 }, +{ 0x608880, 23 },{ 0x608881, 23 },{ 0x608882, 23 },{ 0x608883, 23 }, +{ 0x608884, 23 },{ 0x608885, 23 },{ 0x608886, 23 },{ 0x608887, 23 }, +{ 0x608888, 23 },{ 0x608889, 23 },{ 0x60888a, 23 },{ 0x60888b, 23 }, +{ 0x60888c, 23 },{ 0x60888d, 23 },{ 0x60888e, 23 },{ 0x60888f, 23 }, +}; + +/* dc table 1 */ + +const uint32_t ff_table1_dc_lum[120][2] = { +{ 0x2, 2 },{ 0x3, 2 },{ 0x3, 3 },{ 0x2, 4 }, +{ 0x5, 4 },{ 0x1, 5 },{ 0x3, 5 },{ 0x8, 5 }, +{ 0x0, 6 },{ 0x5, 6 },{ 0xd, 6 },{ 0xf, 6 }, +{ 0x13, 6 },{ 0x8, 7 },{ 0x18, 7 },{ 0x1c, 7 }, +{ 0x24, 7 },{ 0x4, 8 },{ 0x6, 8 },{ 0x12, 8 }, +{ 0x32, 8 },{ 0x3b, 8 },{ 0x4a, 8 },{ 0x4b, 8 }, +{ 0xb, 9 },{ 0x26, 9 },{ 0x27, 9 },{ 0x66, 9 }, +{ 0x74, 9 },{ 0x75, 9 },{ 0x14, 10 },{ 0x1c, 10 }, +{ 0x1f, 10 },{ 0x1d, 10 },{ 0x2b, 11 },{ 0x3d, 11 }, +{ 0x19d, 11 },{ 0x19f, 11 },{ 0x54, 12 },{ 0x339, 12 }, +{ 0x338, 12 },{ 0x33d, 12 },{ 0xab, 13 },{ 0xf1, 13 }, +{ 0x678, 13 },{ 0xf2, 13 },{ 0x1e0, 14 },{ 0x1e1, 14 }, +{ 0x154, 14 },{ 0xcf2, 14 },{ 0x3cc, 15 },{ 0x2ab, 15 }, +{ 0x19e7, 15 },{ 0x3ce, 15 },{ 0x19e6, 15 },{ 0x554, 16 }, +{ 0x79f, 16 },{ 0x555, 16 },{ 0xf3d, 17 },{ 0xf37, 17 }, +{ 0xf3c, 17 },{ 0xf35, 17 },{ 0x1e6d, 18 },{ 0x1e68, 18 }, +{ 0x3cd8, 19 },{ 0x3cd3, 19 },{ 0x3cd9, 19 },{ 0x79a4, 20 }, +{ 0xf34ba, 25 },{ 0xf34b4, 25 },{ 0xf34b5, 25 },{ 0xf34b6, 25 }, +{ 0xf34b7, 25 },{ 0xf34b8, 25 },{ 0xf34b9, 25 },{ 0xf34bb, 25 }, +{ 0xf34bc, 25 },{ 0xf34bd, 25 },{ 0xf34be, 25 },{ 0xf34bf, 25 }, +{ 0x1e6940, 26 },{ 0x1e6941, 26 },{ 0x1e6942, 26 },{ 0x1e6943, 26 }, +{ 0x1e6944, 26 },{ 0x1e6945, 26 },{ 0x1e6946, 26 },{ 0x1e6947, 26 }, +{ 0x1e6948, 26 },{ 0x1e6949, 26 },{ 0x1e694a, 26 },{ 0x1e694b, 26 }, +{ 0x1e694c, 26 },{ 0x1e694d, 26 },{ 0x1e694e, 26 },{ 0x1e694f, 26 }, +{ 0x1e6950, 26 },{ 0x1e6951, 26 },{ 0x1e6952, 26 },{ 0x1e6953, 26 }, +{ 0x1e6954, 26 },{ 0x1e6955, 26 },{ 0x1e6956, 26 },{ 0x1e6957, 26 }, +{ 0x1e6958, 26 },{ 0x1e6959, 26 },{ 0x1e695a, 26 },{ 0x1e695b, 26 }, +{ 0x1e695c, 26 },{ 0x1e695d, 26 },{ 0x1e695e, 26 },{ 0x1e695f, 26 }, +{ 0x1e6960, 26 },{ 0x1e6961, 26 },{ 0x1e6962, 26 },{ 0x1e6963, 26 }, +{ 0x1e6964, 26 },{ 0x1e6965, 26 },{ 0x1e6966, 26 },{ 0x1e6967, 26 }, +}; + +const uint32_t ff_table1_dc_chroma[120][2] = { +{ 0x0, 2 },{ 0x1, 2 },{ 0x4, 3 },{ 0x7, 3 }, +{ 0xb, 4 },{ 0xd, 4 },{ 0x15, 5 },{ 0x28, 6 }, +{ 0x30, 6 },{ 0x32, 6 },{ 0x52, 7 },{ 0x62, 7 }, +{ 0x66, 7 },{ 0xa6, 8 },{ 0xc6, 8 },{ 0xcf, 8 }, +{ 0x14f, 9 },{ 0x18e, 9 },{ 0x19c, 9 },{ 0x29d, 10 }, +{ 0x33a, 10 },{ 0x538, 11 },{ 0x63c, 11 },{ 0x63e, 11 }, +{ 0x63f, 11 },{ 0x676, 11 },{ 0xa73, 12 },{ 0xc7a, 12 }, +{ 0xcef, 12 },{ 0x14e5, 13 },{ 0x19dd, 13 },{ 0x29c8, 14 }, +{ 0x29c9, 14 },{ 0x63dd, 15 },{ 0x33b8, 14 },{ 0x33b9, 14 }, +{ 0xc7b6, 16 },{ 0x63d8, 15 },{ 0x63df, 15 },{ 0xc7b3, 16 }, +{ 0xc7b4, 16 },{ 0xc7b5, 16 },{ 0x63de, 15 },{ 0xc7b7, 16 }, +{ 0xc7b8, 16 },{ 0xc7b9, 16 },{ 0x18f65, 17 },{ 0x31ec8, 18 }, +{ 0xc7b248, 24 },{ 0xc7b249, 24 },{ 0xc7b24a, 24 },{ 0xc7b24b, 24 }, +{ 0xc7b24c, 24 },{ 0xc7b24d, 24 },{ 0xc7b24e, 24 },{ 0xc7b24f, 24 }, +{ 0xc7b250, 24 },{ 0xc7b251, 24 },{ 0xc7b252, 24 },{ 0xc7b253, 24 }, +{ 0xc7b254, 24 },{ 0xc7b255, 24 },{ 0xc7b256, 24 },{ 0xc7b257, 24 }, +{ 0xc7b258, 24 },{ 0xc7b259, 24 },{ 0xc7b25a, 24 },{ 0xc7b25b, 24 }, +{ 0xc7b25c, 24 },{ 0xc7b25d, 24 },{ 0xc7b25e, 24 },{ 0xc7b25f, 24 }, +{ 0xc7b260, 24 },{ 0xc7b261, 24 },{ 0xc7b262, 24 },{ 0xc7b263, 24 }, +{ 0xc7b264, 24 },{ 0xc7b265, 24 },{ 0xc7b266, 24 },{ 0xc7b267, 24 }, +{ 0xc7b268, 24 },{ 0xc7b269, 24 },{ 0xc7b26a, 24 },{ 0xc7b26b, 24 }, +{ 0xc7b26c, 24 },{ 0xc7b26d, 24 },{ 0xc7b26e, 24 },{ 0xc7b26f, 24 }, +{ 0xc7b270, 24 },{ 0xc7b271, 24 },{ 0xc7b272, 24 },{ 0xc7b273, 24 }, +{ 0xc7b274, 24 },{ 0xc7b275, 24 },{ 0xc7b276, 24 },{ 0xc7b277, 24 }, +{ 0xc7b278, 24 },{ 0xc7b279, 24 },{ 0xc7b27a, 24 },{ 0xc7b27b, 24 }, +{ 0xc7b27c, 24 },{ 0xc7b27d, 24 },{ 0xc7b27e, 24 },{ 0xc7b27f, 24 }, +{ 0x18f6480, 25 },{ 0x18f6481, 25 },{ 0x18f6482, 25 },{ 0x18f6483, 25 }, +{ 0x18f6484, 25 },{ 0x18f6485, 25 },{ 0x18f6486, 25 },{ 0x18f6487, 25 }, +{ 0x18f6488, 25 },{ 0x18f6489, 25 },{ 0x18f648a, 25 },{ 0x18f648b, 25 }, +{ 0x18f648c, 25 },{ 0x18f648d, 25 },{ 0x18f648e, 25 },{ 0x18f648f, 25 }, +}; + +/* vlc table 0, for intra luma */ + +static const uint16_t table0_vlc[133][2] = { +{ 0x1, 2 },{ 0x6, 3 },{ 0xf, 4 },{ 0x16, 5 }, +{ 0x20, 6 },{ 0x18, 7 },{ 0x8, 8 },{ 0x9a, 8 }, +{ 0x56, 9 },{ 0x13e, 9 },{ 0xf0, 10 },{ 0x3a5, 10 }, +{ 0x77, 11 },{ 0x1ef, 11 },{ 0x9a, 12 },{ 0x5d, 13 }, +{ 0x1, 4 },{ 0x11, 5 },{ 0x2, 7 },{ 0xb, 8 }, +{ 0x12, 9 },{ 0x1d6, 9 },{ 0x27e, 10 },{ 0x191, 11 }, +{ 0xea, 12 },{ 0x3dc, 12 },{ 0x13b, 13 },{ 0x4, 5 }, +{ 0x14, 7 },{ 0x9e, 8 },{ 0x9, 10 },{ 0x1ac, 11 }, +{ 0x1e2, 11 },{ 0x3ca, 12 },{ 0x5f, 13 },{ 0x17, 5 }, +{ 0x4e, 7 },{ 0x5e, 9 },{ 0xf3, 10 },{ 0x1ad, 11 }, +{ 0xec, 12 },{ 0x5f0, 13 },{ 0xe, 6 },{ 0xe1, 8 }, +{ 0x3a4, 10 },{ 0x9c, 12 },{ 0x13d, 13 },{ 0x3b, 6 }, +{ 0x1c, 9 },{ 0x14, 11 },{ 0x9be, 12 },{ 0x6, 7 }, +{ 0x7a, 9 },{ 0x190, 11 },{ 0x137, 13 },{ 0x1b, 7 }, +{ 0x8, 10 },{ 0x75c, 11 },{ 0x71, 7 },{ 0xd7, 10 }, +{ 0x9bf, 12 },{ 0x7, 8 },{ 0xaf, 10 },{ 0x4cc, 11 }, +{ 0x34, 8 },{ 0x265, 10 },{ 0x9f, 12 },{ 0xe0, 8 }, +{ 0x16, 11 },{ 0x327, 12 },{ 0x15, 9 },{ 0x17d, 11 }, +{ 0xebb, 12 },{ 0x14, 9 },{ 0xf6, 10 },{ 0x1e4, 11 }, +{ 0xcb, 10 },{ 0x99d, 12 },{ 0xca, 10 },{ 0x2fc, 12 }, +{ 0x17f, 11 },{ 0x4cd, 11 },{ 0x2fd, 12 },{ 0x4fe, 11 }, +{ 0x13a, 13 },{ 0xa, 4 },{ 0x42, 7 },{ 0x1d3, 9 }, +{ 0x4dd, 11 },{ 0x12, 5 },{ 0xe8, 8 },{ 0x4c, 11 }, +{ 0x136, 13 },{ 0x39, 6 },{ 0x264, 10 },{ 0xeba, 12 }, +{ 0x0, 7 },{ 0xae, 10 },{ 0x99c, 12 },{ 0x1f, 7 }, +{ 0x4de, 11 },{ 0x43, 7 },{ 0x4dc, 11 },{ 0x3, 8 }, +{ 0x3cb, 12 },{ 0x6, 8 },{ 0x99e, 12 },{ 0x2a, 8 }, +{ 0x5f1, 13 },{ 0xf, 8 },{ 0x9fe, 12 },{ 0x33, 8 }, +{ 0x9ff, 12 },{ 0x98, 8 },{ 0x99f, 12 },{ 0xea, 8 }, +{ 0x13c, 13 },{ 0x2e, 8 },{ 0x192, 11 },{ 0x136, 9 }, +{ 0x6a, 9 },{ 0x15, 11 },{ 0x3af, 10 },{ 0x1e3, 11 }, +{ 0x74, 11 },{ 0xeb, 12 },{ 0x2f9, 12 },{ 0x5c, 13 }, +{ 0xed, 12 },{ 0x3dd, 12 },{ 0x326, 12 },{ 0x5e, 13 }, +{ 0x16, 7 }, +}; + +static const int8_t table0_level[132] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 1, 2, 3, 4, 5, + 6, 7, 8, 1, 2, 3, 4, 5, + 6, 7, 1, 2, 3, 4, 5, 1, + 2, 3, 4, 1, 2, 3, 4, 1, + 2, 3, 1, 2, 3, 1, 2, 3, + 1, 2, 3, 1, 2, 3, 1, 2, + 3, 1, 2, 3, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 1, 2, 3, + 4, 1, 2, 3, 4, 1, 2, 3, + 1, 2, 3, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, +}; + +static const int8_t table0_run[132] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 6, 6, 6, 6, 7, + 7, 7, 8, 8, 8, 9, 9, 9, + 10, 10, 10, 11, 11, 11, 12, 12, + 12, 13, 13, 13, 14, 14, 15, 15, + 16, 17, 18, 19, 20, 0, 0, 0, + 0, 1, 1, 1, 1, 2, 2, 2, + 3, 3, 3, 4, 4, 5, 5, 6, + 6, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, +}; + +/* vlc table 1, for intra chroma and P macroblocks */ + +static const uint16_t table1_vlc[149][2] = { +{ 0x4, 3 },{ 0x14, 5 },{ 0x17, 7 },{ 0x7f, 8 }, +{ 0x154, 9 },{ 0x1f2, 10 },{ 0xbf, 11 },{ 0x65, 12 }, +{ 0xaaa, 12 },{ 0x630, 13 },{ 0x1597, 13 },{ 0x3b7, 14 }, +{ 0x2b22, 14 },{ 0xbe6, 15 },{ 0xb, 4 },{ 0x37, 7 }, +{ 0x62, 9 },{ 0x7, 11 },{ 0x166, 12 },{ 0xce, 13 }, +{ 0x1590, 13 },{ 0x5f6, 14 },{ 0xbe7, 15 },{ 0x7, 5 }, +{ 0x6d, 8 },{ 0x3, 11 },{ 0x31f, 12 },{ 0x5f2, 14 }, +{ 0x2, 6 },{ 0x61, 9 },{ 0x55, 12 },{ 0x1df, 14 }, +{ 0x1a, 6 },{ 0x1e, 10 },{ 0xac9, 12 },{ 0x2b23, 14 }, +{ 0x1e, 6 },{ 0x1f, 10 },{ 0xac3, 12 },{ 0x2b2b, 14 }, +{ 0x6, 7 },{ 0x4, 11 },{ 0x2f8, 13 },{ 0x19, 7 }, +{ 0x6, 11 },{ 0x63d, 13 },{ 0x57, 7 },{ 0x182, 11 }, +{ 0x2aa2, 14 },{ 0x4, 8 },{ 0x180, 11 },{ 0x59c, 14 }, +{ 0x7d, 8 },{ 0x164, 12 },{ 0x76d, 15 },{ 0x2, 9 }, +{ 0x18d, 11 },{ 0x1581, 13 },{ 0xad, 8 },{ 0x60, 12 }, +{ 0xc67, 14 },{ 0x1c, 9 },{ 0xee, 13 },{ 0x3, 9 }, +{ 0x2cf, 13 },{ 0xd9, 9 },{ 0x1580, 13 },{ 0x2, 11 }, +{ 0x183, 11 },{ 0x57, 12 },{ 0x61, 12 },{ 0x31, 11 }, +{ 0x66, 12 },{ 0x631, 13 },{ 0x632, 13 },{ 0xac, 13 }, +{ 0x31d, 12 },{ 0x76, 12 },{ 0x3a, 11 },{ 0x165, 12 }, +{ 0xc66, 14 },{ 0x3, 2 },{ 0x54, 7 },{ 0x2ab, 10 }, +{ 0x16, 13 },{ 0x5f7, 14 },{ 0x5, 4 },{ 0xf8, 9 }, +{ 0xaa9, 12 },{ 0x5f, 15 },{ 0x4, 4 },{ 0x1c, 10 }, +{ 0x1550, 13 },{ 0x4, 5 },{ 0x77, 11 },{ 0x76c, 15 }, +{ 0xe, 5 },{ 0xa, 12 },{ 0xc, 5 },{ 0x562, 11 }, +{ 0x4, 6 },{ 0x31c, 12 },{ 0x6, 6 },{ 0xc8, 13 }, +{ 0xd, 6 },{ 0x1da, 13 },{ 0x7, 6 },{ 0xc9, 13 }, +{ 0x1, 7 },{ 0x2e, 14 },{ 0x14, 7 },{ 0x1596, 13 }, +{ 0xa, 7 },{ 0xac2, 12 },{ 0x16, 7 },{ 0x15b, 14 }, +{ 0x15, 7 },{ 0x15a, 14 },{ 0xf, 8 },{ 0x5e, 15 }, +{ 0x7e, 8 },{ 0xab, 8 },{ 0x2d, 9 },{ 0xd8, 9 }, +{ 0xb, 9 },{ 0x14, 10 },{ 0x2b3, 10 },{ 0x1f3, 10 }, +{ 0x3a, 10 },{ 0x0, 10 },{ 0x58, 10 },{ 0x2e, 9 }, +{ 0x5e, 10 },{ 0x563, 11 },{ 0xec, 12 },{ 0x54, 12 }, +{ 0xac1, 12 },{ 0x1556, 13 },{ 0x2fa, 13 },{ 0x181, 11 }, +{ 0x1557, 13 },{ 0x59d, 14 },{ 0x2aa3, 14 },{ 0x2b2a, 14 }, +{ 0x1de, 14 },{ 0x63c, 13 },{ 0xcf, 13 },{ 0x1594, 13 }, +{ 0xd, 9 }, +}; + +static const int8_t table1_level[148] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 1, + 2, 3, 4, 5, 1, 2, 3, 4, + 1, 2, 3, 4, 1, 2, 3, 4, + 1, 2, 3, 1, 2, 3, 1, 2, + 3, 1, 2, 3, 1, 2, 3, 1, + 2, 3, 1, 2, 3, 1, 2, 1, + 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 3, 4, 5, 1, 2, + 3, 4, 1, 2, 3, 1, 2, 3, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, +}; + +static const int8_t table1_run[148] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 8, 8, + 8, 9, 9, 9, 10, 10, 10, 11, + 11, 11, 12, 12, 12, 13, 13, 14, + 14, 15, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 2, 2, 2, 3, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13, 14, 14, 15, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, +}; + +/* third vlc table */ + +static const uint16_t table2_vlc[186][2] = { +{ 0x1, 2 },{ 0x5, 3 },{ 0xd, 4 },{ 0x12, 5 }, +{ 0xe, 6 },{ 0x15, 7 },{ 0x13, 8 },{ 0x3f, 8 }, +{ 0x4b, 9 },{ 0x11f, 9 },{ 0xb8, 10 },{ 0x3e3, 10 }, +{ 0x172, 11 },{ 0x24d, 12 },{ 0x3da, 12 },{ 0x2dd, 13 }, +{ 0x1f55, 13 },{ 0x5b9, 14 },{ 0x3eae, 14 },{ 0x0, 4 }, +{ 0x10, 5 },{ 0x8, 7 },{ 0x20, 8 },{ 0x29, 9 }, +{ 0x1f4, 9 },{ 0x233, 10 },{ 0x1e0, 11 },{ 0x12a, 12 }, +{ 0x3dd, 12 },{ 0x50a, 13 },{ 0x1f29, 13 },{ 0xa42, 14 }, +{ 0x1272, 15 },{ 0x1737, 15 },{ 0x3, 5 },{ 0x11, 7 }, +{ 0xc4, 8 },{ 0x4b, 10 },{ 0xb4, 11 },{ 0x7d4, 11 }, +{ 0x345, 12 },{ 0x2d7, 13 },{ 0x7bf, 13 },{ 0x938, 14 }, +{ 0xbbb, 14 },{ 0x95e, 15 },{ 0x13, 5 },{ 0x78, 7 }, +{ 0x69, 9 },{ 0x232, 10 },{ 0x461, 11 },{ 0x3ec, 12 }, +{ 0x520, 13 },{ 0x1f2a, 13 },{ 0x3e50, 14 },{ 0x3e51, 14 }, +{ 0x1486, 15 },{ 0xc, 6 },{ 0x24, 9 },{ 0x94, 11 }, +{ 0x8c0, 12 },{ 0xf09, 14 },{ 0x1ef0, 15 },{ 0x3d, 6 }, +{ 0x53, 9 },{ 0x1a0, 11 },{ 0x2d6, 13 },{ 0xf08, 14 }, +{ 0x13, 7 },{ 0x7c, 9 },{ 0x7c1, 11 },{ 0x4ac, 14 }, +{ 0x1b, 7 },{ 0xa0, 10 },{ 0x344, 12 },{ 0xf79, 14 }, +{ 0x79, 7 },{ 0x3e1, 10 },{ 0x2d4, 13 },{ 0x2306, 14 }, +{ 0x21, 8 },{ 0x23c, 10 },{ 0xfae, 12 },{ 0x23de, 14 }, +{ 0x35, 8 },{ 0x175, 11 },{ 0x7b3, 13 },{ 0xc5, 8 }, +{ 0x174, 11 },{ 0x785, 13 },{ 0x48, 9 },{ 0x1a3, 11 }, +{ 0x49e, 13 },{ 0x2c, 9 },{ 0xfa, 10 },{ 0x7d6, 11 }, +{ 0x92, 10 },{ 0x5cc, 13 },{ 0x1ef1, 15 },{ 0xa3, 10 }, +{ 0x3ed, 12 },{ 0x93e, 14 },{ 0x1e2, 11 },{ 0x1273, 15 }, +{ 0x7c4, 11 },{ 0x1487, 15 },{ 0x291, 12 },{ 0x293, 12 }, +{ 0xf8a, 12 },{ 0x509, 13 },{ 0x508, 13 },{ 0x78d, 13 }, +{ 0x7be, 13 },{ 0x78c, 13 },{ 0x4ae, 14 },{ 0xbba, 14 }, +{ 0x2307, 14 },{ 0xb9a, 14 },{ 0x1736, 15 },{ 0xe, 4 }, +{ 0x45, 7 },{ 0x1f3, 9 },{ 0x47a, 11 },{ 0x5dc, 13 }, +{ 0x23df, 14 },{ 0x19, 5 },{ 0x28, 9 },{ 0x176, 11 }, +{ 0x49d, 13 },{ 0x23dd, 14 },{ 0x30, 6 },{ 0xa2, 10 }, +{ 0x2ef, 12 },{ 0x5b8, 14 },{ 0x3f, 6 },{ 0xa5, 10 }, +{ 0x3db, 12 },{ 0x93f, 14 },{ 0x44, 7 },{ 0x7cb, 11 }, +{ 0x95f, 15 },{ 0x63, 7 },{ 0x3c3, 12 },{ 0x15, 8 }, +{ 0x8f6, 12 },{ 0x17, 8 },{ 0x498, 13 },{ 0x2c, 8 }, +{ 0x7b2, 13 },{ 0x2f, 8 },{ 0x1f54, 13 },{ 0x8d, 8 }, +{ 0x7bd, 13 },{ 0x8e, 8 },{ 0x1182, 13 },{ 0xfb, 8 }, +{ 0x50b, 13 },{ 0x2d, 8 },{ 0x7c0, 11 },{ 0x79, 9 }, +{ 0x1f5f, 13 },{ 0x7a, 9 },{ 0x1f56, 13 },{ 0x231, 10 }, +{ 0x3e4, 10 },{ 0x1a1, 11 },{ 0x143, 11 },{ 0x1f7, 11 }, +{ 0x16f, 12 },{ 0x292, 12 },{ 0x2e7, 12 },{ 0x16c, 12 }, +{ 0x16d, 12 },{ 0x3dc, 12 },{ 0xf8b, 12 },{ 0x499, 13 }, +{ 0x3d8, 12 },{ 0x78e, 13 },{ 0x2d5, 13 },{ 0x1f5e, 13 }, +{ 0x1f2b, 13 },{ 0x78f, 13 },{ 0x4ad, 14 },{ 0x3eaf, 14 }, +{ 0x23dc, 14 },{ 0x4a, 9 }, +}; + +static const int8_t table2_level[185] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 1, 2, 3, 4, 5, 6, 1, + 2, 3, 4, 5, 1, 2, 3, 4, + 1, 2, 3, 4, 1, 2, 3, 4, + 1, 2, 3, 4, 1, 2, 3, 1, + 2, 3, 1, 2, 3, 1, 2, 3, + 1, 2, 3, 1, 2, 3, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 4, 5, 6, 1, 2, 3, + 4, 5, 1, 2, 3, 4, 1, 2, + 3, 4, 1, 2, 3, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, +}; + +static const int8_t table2_run[185] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 6, 6, 6, 6, + 7, 7, 7, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 10, 10, 10, 11, + 11, 11, 12, 12, 12, 13, 13, 13, + 14, 14, 14, 15, 15, 15, 16, 16, + 17, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 0, + 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 3, 4, 4, 4, 5, 5, 6, + 6, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, + 14, 15, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, +}; + +/* second non intra vlc table */ +static const uint16_t table4_vlc[169][2] = { +{ 0x0, 3 },{ 0x3, 4 },{ 0xb, 5 },{ 0x14, 6 }, +{ 0x3f, 6 },{ 0x5d, 7 },{ 0xa2, 8 },{ 0xac, 9 }, +{ 0x16e, 9 },{ 0x20a, 10 },{ 0x2e2, 10 },{ 0x432, 11 }, +{ 0x5c9, 11 },{ 0x827, 12 },{ 0xb54, 12 },{ 0x4e6, 13 }, +{ 0x105f, 13 },{ 0x172a, 13 },{ 0x20b2, 14 },{ 0x2d4e, 14 }, +{ 0x39f0, 14 },{ 0x4175, 15 },{ 0x5a9e, 15 },{ 0x4, 4 }, +{ 0x1e, 5 },{ 0x42, 7 },{ 0xb6, 8 },{ 0x173, 9 }, +{ 0x395, 10 },{ 0x72e, 11 },{ 0xb94, 12 },{ 0x16a4, 13 }, +{ 0x20b3, 14 },{ 0x2e45, 14 },{ 0x5, 5 },{ 0x40, 7 }, +{ 0x49, 9 },{ 0x28f, 10 },{ 0x5cb, 11 },{ 0x48a, 13 }, +{ 0x9dd, 14 },{ 0x73e2, 15 },{ 0x18, 5 },{ 0x25, 8 }, +{ 0x8a, 10 },{ 0x51b, 11 },{ 0xe5f, 12 },{ 0x9c9, 14 }, +{ 0x139c, 15 },{ 0x29, 6 },{ 0x4f, 9 },{ 0x412, 11 }, +{ 0x48d, 13 },{ 0x2e41, 14 },{ 0x38, 6 },{ 0x10e, 9 }, +{ 0x5a8, 11 },{ 0x105c, 13 },{ 0x39f2, 14 },{ 0x58, 7 }, +{ 0x21f, 10 },{ 0xe7e, 12 },{ 0x39ff, 14 },{ 0x23, 8 }, +{ 0x2e3, 10 },{ 0x4e5, 13 },{ 0x2e40, 14 },{ 0xa1, 8 }, +{ 0x5be, 11 },{ 0x9c8, 14 },{ 0x83, 8 },{ 0x13a, 11 }, +{ 0x1721, 13 },{ 0x44, 9 },{ 0x276, 12 },{ 0x39f6, 14 }, +{ 0x8b, 10 },{ 0x4ef, 13 },{ 0x5a9b, 15 },{ 0x208, 10 }, +{ 0x1cfe, 13 },{ 0x399, 10 },{ 0x1cb4, 13 },{ 0x39e, 10 }, +{ 0x39f3, 14 },{ 0x5ab, 11 },{ 0x73e3, 15 },{ 0x737, 11 }, +{ 0x5a9f, 15 },{ 0x82d, 12 },{ 0xe69, 12 },{ 0xe68, 12 }, +{ 0x433, 11 },{ 0xb7b, 12 },{ 0x2df8, 14 },{ 0x2e56, 14 }, +{ 0x2e57, 14 },{ 0x39f7, 14 },{ 0x51a5, 15 },{ 0x3, 3 }, +{ 0x2a, 6 },{ 0xe4, 8 },{ 0x28e, 10 },{ 0x735, 11 }, +{ 0x1058, 13 },{ 0x1cfa, 13 },{ 0x2df9, 14 },{ 0x4174, 15 }, +{ 0x9, 4 },{ 0x54, 8 },{ 0x398, 10 },{ 0x48b, 13 }, +{ 0x139d, 15 },{ 0xd, 4 },{ 0xad, 9 },{ 0x826, 12 }, +{ 0x2d4c, 14 },{ 0x11, 5 },{ 0x16b, 9 },{ 0xb7f, 12 }, +{ 0x51a4, 15 },{ 0x19, 5 },{ 0x21b, 10 },{ 0x16fd, 13 }, +{ 0x1d, 5 },{ 0x394, 10 },{ 0x28d3, 14 },{ 0x2b, 6 }, +{ 0x5bc, 11 },{ 0x5a9a, 15 },{ 0x2f, 6 },{ 0x247, 12 }, +{ 0x10, 7 },{ 0xa35, 12 },{ 0x3e, 6 },{ 0xb7a, 12 }, +{ 0x59, 7 },{ 0x105e, 13 },{ 0x26, 8 },{ 0x9cf, 14 }, +{ 0x55, 8 },{ 0x1cb5, 13 },{ 0x57, 8 },{ 0xe5b, 12 }, +{ 0xa0, 8 },{ 0x1468, 13 },{ 0x170, 9 },{ 0x90, 10 }, +{ 0x1ce, 9 },{ 0x21a, 10 },{ 0x218, 10 },{ 0x168, 9 }, +{ 0x21e, 10 },{ 0x244, 12 },{ 0x736, 11 },{ 0x138, 11 }, +{ 0x519, 11 },{ 0xe5e, 12 },{ 0x72c, 11 },{ 0xb55, 12 }, +{ 0x9dc, 14 },{ 0x20bb, 14 },{ 0x48c, 13 },{ 0x1723, 13 }, +{ 0x2e44, 14 },{ 0x16a5, 13 },{ 0x518, 11 },{ 0x39fe, 14 }, +{ 0x169, 9 }, +}; + +static const int8_t table4_level[168] = { + 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 1, 2, 3, 4, 5, 6, + 7, 8, 1, 2, 3, 4, 5, 6, + 7, 1, 2, 3, 4, 5, 1, 2, + 3, 4, 5, 1, 2, 3, 4, 1, + 2, 3, 4, 1, 2, 3, 1, 2, + 3, 1, 2, 3, 1, 2, 3, 1, + 2, 1, 2, 1, 2, 1, 2, 1, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 1, 2, 3, 4, + 5, 1, 2, 3, 4, 1, 2, 3, + 4, 1, 2, 3, 1, 2, 3, 1, + 2, 3, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +}; + +static const int8_t table4_run[168] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 7, + 7, 7, 7, 8, 8, 8, 9, 9, + 9, 10, 10, 10, 11, 11, 11, 12, + 12, 13, 13, 14, 14, 15, 15, 16, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 3, 3, 3, + 3, 4, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, + 14, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, +}; + +extern const uint16_t ff_inter_vlc[103][2]; +extern const int8_t ff_inter_level[102]; +extern const int8_t ff_inter_run[102]; + +extern const uint16_t ff_mpeg4_intra_vlc[103][2]; +extern const int8_t ff_mpeg4_intra_level[102]; +extern const int8_t ff_mpeg4_intra_run[102]; + +RLTable ff_rl_table[NB_RL_TABLES] = { + /* intra luminance tables */ + /* low motion */ + { + 132, + 85, + table0_vlc, + table0_run, + table0_level, + }, + /* high motion */ + { + 185, + 119, + table2_vlc, + table2_run, + table2_level, + }, + /* mid-rate */ + { + 102, + 67, + ff_mpeg4_intra_vlc, + ff_mpeg4_intra_run, + ff_mpeg4_intra_level, + }, + /* intra chrominance / non intra tables */ + /* low motion inter */ + { + 148, + 81, + table1_vlc, + table1_run, + table1_level, + }, + /* high motion inter */ + { + 168, + 99, + table4_vlc, + table4_run, + table4_level, + }, + /* mid rate inter */ + { + 102, + 58, + ff_inter_vlc, + ff_inter_run, + ff_inter_level, + }, +}; + +/* motion vector table 0 */ + +static const uint16_t table0_mv_code[1100] = { + 0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001, + 0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f, + 0x0014, 0x0020, 0x0022, 0x0025, 0x0027, 0x0029, 0x002d, 0x004b, + 0x004d, 0x0003, 0x0022, 0x0023, 0x0025, 0x0027, 0x0042, 0x0048, + 0x0049, 0x0050, 0x005c, 0x0091, 0x009f, 0x000e, 0x0043, 0x004c, + 0x0054, 0x0056, 0x008c, 0x0098, 0x009a, 0x009b, 0x00b1, 0x00b2, + 0x0120, 0x0121, 0x0126, 0x0133, 0x0139, 0x01a1, 0x01a4, 0x01a5, + 0x01a6, 0x01a7, 0x01ae, 0x01af, 0x000b, 0x0019, 0x0085, 0x0090, + 0x009b, 0x00aa, 0x00af, 0x010c, 0x010e, 0x011c, 0x011e, 0x0133, + 0x0144, 0x0160, 0x0174, 0x0175, 0x0177, 0x0178, 0x0249, 0x024b, + 0x0252, 0x0261, 0x0265, 0x0270, 0x0352, 0x0353, 0x0355, 0x0359, + 0x0010, 0x0011, 0x0013, 0x0034, 0x0035, 0x0036, 0x0037, 0x003d, + 0x003e, 0x0109, 0x0126, 0x0156, 0x021a, 0x021e, 0x023a, 0x023e, + 0x028e, 0x028f, 0x02cf, 0x0491, 0x0494, 0x049f, 0x04a0, 0x04a3, + 0x04a6, 0x04a7, 0x04ad, 0x04ae, 0x04c0, 0x04c4, 0x04c6, 0x04c8, + 0x04c9, 0x04f5, 0x04f6, 0x04f7, 0x0680, 0x0682, 0x0683, 0x0688, + 0x0689, 0x068d, 0x068e, 0x068f, 0x06a2, 0x06a3, 0x06a9, 0x06b0, + 0x06b1, 0x06b4, 0x06b5, 0x0024, 0x0060, 0x0063, 0x0078, 0x0079, + 0x0211, 0x0244, 0x0245, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b, + 0x026b, 0x02af, 0x02b8, 0x02bb, 0x0436, 0x0476, 0x0477, 0x047e, + 0x04c8, 0x04c9, 0x04ca, 0x0514, 0x0586, 0x0587, 0x0598, 0x059d, + 0x05d9, 0x05da, 0x0920, 0x0921, 0x093b, 0x093c, 0x093d, 0x0942, + 0x0943, 0x0944, 0x0945, 0x0959, 0x095e, 0x095f, 0x0982, 0x0983, + 0x098e, 0x098f, 0x09c4, 0x09e7, 0x09e8, 0x09e9, 0x0d02, 0x0d17, + 0x0d18, 0x0d19, 0x0d41, 0x0d42, 0x0d43, 0x0d50, 0x0d5f, 0x0d6d, + 0x0d6e, 0x0d6f, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x041e, 0x041f, 0x0420, 0x0421, + 0x048c, 0x048d, 0x04d3, 0x04d4, 0x04d5, 0x055c, 0x055d, 0x0572, + 0x0573, 0x0574, 0x0575, 0x08de, 0x08df, 0x08fe, 0x08ff, 0x0996, + 0x0a36, 0x0a37, 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b32, 0x0b33, + 0x0b34, 0x0b35, 0x0b36, 0x0b37, 0x0b38, 0x0b39, 0x0bb0, 0x0bf7, + 0x0bf8, 0x0bf9, 0x0bfa, 0x0bfb, 0x0bfc, 0x0bfd, 0x0bfe, 0x0bff, + 0x1254, 0x1255, 0x1256, 0x1257, 0x1270, 0x1271, 0x1272, 0x1273, + 0x1274, 0x1275, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af, 0x12b0, + 0x12b1, 0x1315, 0x1316, 0x1317, 0x13bf, 0x13c0, 0x13c1, 0x13c2, + 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9, 0x13ca, + 0x13cb, 0x13cc, 0x13cd, 0x1a06, 0x1a07, 0x1a28, 0x1a29, 0x1a2a, + 0x1a2b, 0x1a2c, 0x1a2d, 0x1a80, 0x1abb, 0x1abc, 0x1abd, 0x1ad8, + 0x1ad9, 0x0094, 0x0095, 0x0096, 0x0097, 0x00a0, 0x00a1, 0x00a2, + 0x00a3, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837, + 0x0838, 0x0839, 0x083a, 0x083b, 0x0939, 0x093a, 0x093b, 0x093c, + 0x093d, 0x093e, 0x093f, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4, + 0x09a5, 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, + 0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, + 0x11bb, 0x132f, 0x1454, 0x1455, 0x1456, 0x1457, 0x1458, 0x1459, + 0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f, 0x1460, 0x1461, + 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469, + 0x146a, 0x146b, 0x17de, 0x17df, 0x17e0, 0x17e1, 0x17e2, 0x17e3, + 0x17e4, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9, 0x17ea, 0x17eb, + 0x17ec, 0x17ed, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, + 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d, + 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, + 0x2628, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c, + 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, + 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, + 0x277d, 0x3503, 0x3544, 0x3545, 0x3546, 0x3547, 0x3560, 0x3561, + 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569, + 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571, + 0x3572, 0x3573, 0x3574, 0x3575, 0x03f0, 0x103d, 0x103e, 0x103f, + 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, + 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, + 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, + 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f, + 0x1060, 0x1061, 0x1270, 0x1271, 0x21b8, 0x21b9, 0x21ba, 0x21bb, + 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x21f0, 0x21f1, 0x21f2, 0x21f3, + 0x21f4, 0x21f5, 0x21f6, 0x21f7, 0x21f8, 0x21f9, 0x21fa, 0x21fb, + 0x21fc, 0x21fd, 0x21fe, 0x21ff, 0x2340, 0x2341, 0x2342, 0x2343, + 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b, + 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353, + 0x2354, 0x2355, 0x2356, 0x2357, 0x265c, 0x2f88, 0x2f89, 0x2f8a, + 0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f, 0x2f90, 0x2f91, 0x2f92, + 0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97, 0x2f98, 0x2f99, 0x2f9a, + 0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f, 0x2fa0, 0x2fa1, 0x2fa2, + 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9, 0x2faa, + 0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb2, + 0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7, 0x2fb8, 0x2fb9, 0x2fba, + 0x2fbb, 0x4c52, 0x4c53, 0x4e28, 0x4e29, 0x4e2a, 0x4e2b, 0x4e2c, + 0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34, + 0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c, + 0x4e3d, 0x4e3e, 0x4e3f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84, + 0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89, 0x4e8a, 0x4e8b, 0x4e8c, + 0x4e8d, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e92, 0x4e93, 0x4e94, + 0x4e95, 0x4e96, 0x4e97, 0x4e98, 0x4e99, 0x4e9a, 0x4e9b, 0x4e9c, + 0x4e9d, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea1, 0x4ea2, 0x4ea3, 0x4ea4, + 0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9, 0x4eaa, 0x4eab, 0x4eac, + 0x4ead, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb2, 0x4eb3, 0x4eb4, + 0x4eb5, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4eba, 0x4ebb, 0x4ebc, + 0x4ebd, 0x4ebe, 0x4ebf, 0x4ec0, 0x4ec1, 0x4ec2, 0x4ec3, 0x4ec4, + 0x4ec5, 0x4ec6, 0x4ec7, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x6a04, + 0x6a05, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, + 0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, + 0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, + 0x07f9, 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x07fe, 0x07ff, 0x2000, + 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, + 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2010, + 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, + 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, + 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028, + 0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f, 0x2030, + 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, + 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, + 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048, + 0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, + 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, + 0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f, 0x2060, + 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068, + 0x2069, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0x2070, + 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, + 0x2079, 0x4cba, 0x4cbb, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c, + 0x5d8d, 0x5d8e, 0x5d8f, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4, + 0x5db5, 0x5db6, 0x5db7, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc, + 0x5dbd, 0x5dbe, 0x5dbf, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44, + 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4c, + 0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54, + 0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c, + 0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64, + 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c, + 0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e72, 0x5e73, 0x5e74, + 0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c, + 0x5e7d, 0x5e7e, 0x5e7f, 0x5e80, 0x5e81, 0x5e82, 0x5e83, 0x5e84, + 0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89, 0x5e8a, 0x5e8b, 0x5e8c, + 0x5e8d, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e92, 0x5e93, 0x5e94, + 0x5e95, 0x5e96, 0x5e97, 0x5e98, 0x5e99, 0x5e9a, 0x5e9b, 0x5e9c, + 0x5e9d, 0x5e9e, 0x5e9f, 0x5ea0, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4, + 0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac, + 0x5ead, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb3, 0x5eb4, + 0x5eb5, 0x5eb6, 0x5eb7, 0x5eb8, 0x5eb9, 0x5eba, 0x5ebb, 0x5ebc, + 0x5ebd, 0x5ebe, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4, + 0x5ec5, 0x5ec6, 0x5ec7, 0x5ec8, 0x5ec9, 0x5eca, 0x5ecb, 0x5ecc, + 0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4, + 0x5ed5, 0x5ed6, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edb, 0x5edc, + 0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4, + 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9, 0x5eea, 0x5eeb, 0x5eec, + 0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef4, + 0x5ef5, 0x5ef6, 0x5ef7, 0x5ef8, 0x5ef9, 0x5efa, 0x5efb, 0x5efc, + 0x5efd, 0x5efe, 0x5eff, 0x5f00, 0x5f01, 0x5f02, 0x5f03, 0x5f04, + 0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09, 0x5f0a, 0x5f0b, 0x5f0c, + 0x5f0d, 0x5f0e, 0x5f0f, 0x0000, +}; + +static const uint8_t table0_mv_bits[1100] = { + 1, 4, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 8, +}; + +static const uint8_t table0_mvx[1099] = { + 32, 32, 31, 32, 33, 31, 33, 31, + 33, 32, 34, 32, 30, 32, 31, 34, + 35, 32, 34, 33, 29, 33, 30, 30, + 31, 31, 35, 29, 33, 35, 33, 34, + 31, 29, 30, 34, 30, 36, 28, 32, + 34, 37, 30, 27, 32, 25, 39, 32, + 34, 32, 35, 35, 35, 31, 35, 29, + 32, 29, 30, 29, 37, 27, 36, 38, + 37, 33, 32, 31, 29, 31, 28, 36, + 33, 30, 34, 33, 33, 28, 27, 25, + 31, 26, 39, 32, 32, 31, 33, 39, + 31, 38, 28, 36, 21, 23, 43, 36, + 34, 41, 30, 25, 28, 31, 30, 34, + 38, 35, 61, 34, 28, 30, 37, 37, + 35, 27, 36, 3, 59, 38, 37, 32, + 31, 29, 26, 33, 37, 33, 27, 27, + 35, 34, 34, 40, 42, 33, 32, 29, + 4, 5, 28, 24, 25, 35, 39, 38, + 32, 23, 27, 32, 30, 35, 26, 34, + 60, 36, 29, 22, 26, 41, 7, 30, + 38, 30, 36, 29, 30, 41, 26, 25, + 32, 34, 24, 39, 1, 25, 39, 32, + 28, 29, 32, 38, 26, 36, 28, 63, + 28, 39, 23, 21, 26, 35, 31, 35, + 57, 31, 29, 29, 28, 30, 27, 35, + 2, 38, 40, 34, 37, 29, 38, 43, + 26, 32, 33, 42, 24, 40, 28, 32, + 32, 32, 36, 32, 43, 25, 21, 31, + 30, 31, 41, 29, 33, 37, 26, 37, + 27, 59, 23, 33, 35, 31, 31, 37, + 38, 39, 32, 23, 32, 27, 37, 36, + 31, 40, 25, 27, 38, 31, 36, 28, + 31, 36, 25, 45, 3, 34, 38, 39, + 40, 38, 30, 32, 19, 24, 25, 26, + 45, 20, 24, 33, 33, 31, 41, 34, + 39, 47, 40, 58, 59, 41, 33, 3, + 17, 61, 42, 30, 26, 29, 36, 61, + 33, 37, 62, 28, 25, 38, 25, 38, + 17, 23, 34, 33, 21, 33, 49, 27, + 32, 23, 27, 22, 24, 22, 39, 43, + 27, 37, 6, 42, 47, 26, 30, 31, + 41, 39, 33, 22, 45, 36, 32, 45, + 19, 22, 30, 5, 5, 17, 29, 22, + 31, 31, 43, 37, 27, 32, 32, 32, + 33, 34, 43, 35, 29, 26, 22, 32, + 19, 32, 25, 31, 41, 49, 28, 34, + 28, 39, 34, 19, 37, 38, 29, 21, + 36, 42, 24, 48, 16, 28, 49, 22, + 34, 31, 38, 39, 44, 11, 35, 30, + 33, 33, 23, 28, 33, 46, 15, 13, + 24, 41, 24, 34, 34, 30, 26, 24, + 14, 60, 21, 29, 39, 23, 35, 37, + 63, 45, 33, 34, 47, 41, 22, 42, + 35, 35, 23, 32, 35, 43, 32, 7, + 31, 41, 20, 31, 16, 13, 63, 25, + 30, 32, 35, 30, 30, 31, 42, 47, + 39, 38, 40, 40, 51, 55, 56, 18, + 21, 39, 39, 33, 17, 41, 23, 24, + 43, 25, 31, 20, 19, 45, 1, 34, + 31, 22, 35, 15, 46, 46, 35, 31, + 28, 29, 29, 23, 41, 27, 14, 53, + 53, 27, 24, 32, 57, 32, 17, 42, + 37, 29, 33, 1, 25, 32, 32, 63, + 26, 40, 44, 36, 31, 39, 20, 20, + 44, 23, 33, 34, 35, 33, 33, 28, + 41, 23, 41, 41, 29, 25, 26, 49, + 29, 24, 37, 49, 50, 51, 51, 26, + 39, 25, 26, 15, 39, 18, 42, 17, + 4, 31, 32, 32, 60, 1, 42, 32, + 0, 12, 19, 35, 21, 41, 17, 26, + 20, 45, 46, 32, 37, 22, 47, 29, + 31, 27, 29, 30, 21, 33, 35, 18, + 25, 33, 50, 51, 42, 2, 15, 51, + 53, 33, 25, 29, 55, 37, 38, 33, + 38, 59, 38, 33, 39, 13, 32, 40, + 61, 61, 32, 9, 44, 3, 31, 29, + 25, 31, 27, 23, 9, 25, 9, 29, + 20, 30, 30, 42, 18, 28, 25, 28, + 28, 21, 29, 43, 29, 43, 26, 44, + 44, 21, 38, 21, 24, 45, 45, 35, + 39, 22, 35, 36, 34, 34, 45, 34, + 29, 31, 46, 25, 46, 16, 17, 31, + 20, 32, 47, 47, 47, 32, 49, 49, + 49, 31, 1, 27, 28, 39, 39, 21, + 36, 23, 51, 2, 40, 51, 32, 53, + 24, 30, 24, 30, 21, 40, 57, 57, + 31, 41, 58, 32, 12, 4, 32, 34, + 59, 31, 32, 13, 9, 35, 26, 35, + 37, 61, 37, 63, 26, 29, 41, 38, + 23, 20, 41, 26, 41, 42, 42, 42, + 26, 26, 26, 26, 1, 26, 37, 37, + 37, 23, 34, 42, 27, 43, 34, 27, + 31, 24, 33, 16, 3, 31, 24, 33, + 24, 4, 44, 44, 11, 44, 31, 13, + 13, 44, 45, 13, 25, 22, 38, 26, + 38, 38, 39, 32, 30, 39, 30, 22, + 32, 26, 30, 47, 47, 47, 19, 47, + 30, 31, 35, 8, 23, 47, 47, 27, + 35, 47, 31, 48, 35, 19, 36, 49, + 49, 33, 31, 39, 27, 39, 49, 49, + 50, 50, 50, 39, 31, 51, 51, 39, + 28, 33, 33, 21, 40, 31, 52, 53, + 40, 53, 9, 33, 31, 53, 54, 54, + 54, 55, 55, 34, 15, 56, 25, 56, + 21, 21, 40, 40, 25, 40, 58, 36, + 5, 41, 41, 12, 60, 41, 41, 37, + 22, 61, 18, 29, 29, 30, 61, 30, + 61, 62, 62, 30, 30, 63, 18, 13, + 30, 23, 19, 20, 20, 41, 13, 2, + 5, 5, 1, 5, 32, 6, 32, 35, + 20, 35, 27, 35, 35, 36, 36, 13, + 36, 41, 41, 41, 3, 30, 42, 27, + 20, 30, 27, 28, 30, 21, 33, 33, + 14, 24, 30, 42, 24, 33, 25, 42, + 43, 14, 43, 43, 14, 43, 7, 36, + 37, 37, 37, 37, 7, 14, 25, 43, + 43, 44, 15, 37, 7, 7, 3, 1, + 8, 15, 15, 8, 44, 44, 44, 45, + 45, 45, 45, 8, 8, 45, 21, 45, + 28, 28, 28, 21, 28, 28, 22, 37, + 46, 46, 37, 8, 29, 37, 29, 22, + 46, 37, 22, 29, 47, 47, 38, 38, + 16, 38, 38, 33, 38, 22, 47, 47, + 29, 25, 16, 0, 48, 1, 34, 48, + 48, 34, 25, 26, 26, 49, 49, 26, + 1, 49, 4, 26, 4, 49, 1, 9, + 49, 49, 49, 10, 49, 17, 38, 17, + 17, 50, 38, 50, 50, 22, 38, 51, + 38, 38, 51, 39, 39, 18, 22, 39, + 51, 22, 52, 52, 52, 39, 53, 53, + 10, 23, 18, 29, 10, 53, 29, 54, + 11, 54, 11, 11, 55, 1, 18, 55, + 55, 55, 55, 55, 55, 29, 34, 18, + 29, 56, 56, 34, 57, 34, 34, 29, + 29, 57, 57, 35, 35, 35, 35, 35, + 39, 35, 59, 59, 18, 59, 39, 30, + 18, 40, 60, 60, 61, 30, 18, 61, + 61, 19, 19, +}; + +static const uint8_t table0_mvy[1099] = { + 32, 31, 32, 33, 32, 31, 31, 33, + 33, 34, 32, 30, 32, 35, 34, 31, + 32, 29, 33, 30, 32, 34, 33, 31, + 30, 35, 31, 31, 29, 33, 35, 30, + 29, 33, 34, 34, 30, 32, 32, 36, + 29, 32, 35, 32, 28, 32, 32, 27, + 35, 37, 34, 29, 30, 36, 35, 34, + 25, 30, 29, 35, 33, 31, 31, 32, + 31, 28, 39, 28, 29, 37, 31, 33, + 27, 36, 28, 36, 37, 33, 33, 31, + 27, 32, 31, 38, 26, 25, 25, 33, + 39, 31, 34, 30, 32, 32, 32, 34, + 36, 32, 28, 33, 30, 38, 37, 27, + 33, 28, 32, 37, 35, 38, 29, 34, + 27, 29, 29, 32, 32, 34, 35, 3, + 26, 36, 31, 38, 30, 26, 35, 34, + 37, 26, 25, 32, 32, 39, 23, 37, + 32, 32, 29, 32, 29, 36, 29, 30, + 41, 31, 30, 21, 39, 25, 34, 38, + 32, 35, 39, 32, 33, 33, 32, 27, + 29, 25, 28, 27, 26, 31, 30, 35, + 24, 24, 31, 34, 32, 30, 35, 40, + 28, 38, 5, 35, 29, 36, 36, 32, + 38, 30, 33, 31, 35, 26, 23, 38, + 32, 41, 28, 25, 37, 40, 37, 39, + 32, 36, 33, 39, 25, 26, 28, 31, + 28, 42, 23, 31, 33, 31, 39, 1, + 59, 22, 27, 4, 33, 34, 33, 24, + 41, 3, 35, 41, 41, 28, 36, 36, + 28, 33, 35, 21, 23, 21, 22, 37, + 27, 27, 43, 29, 60, 39, 27, 25, + 59, 34, 27, 27, 26, 40, 37, 27, + 61, 26, 39, 33, 31, 22, 37, 25, + 30, 25, 24, 61, 31, 34, 25, 38, + 32, 32, 30, 3, 61, 43, 29, 23, + 28, 32, 28, 32, 31, 34, 5, 33, + 32, 33, 33, 42, 37, 23, 38, 31, + 40, 26, 32, 26, 37, 38, 36, 24, + 29, 30, 20, 22, 29, 24, 32, 41, + 2, 34, 25, 33, 29, 31, 39, 35, + 36, 24, 32, 30, 33, 27, 44, 60, + 30, 36, 19, 34, 31, 24, 16, 35, + 32, 38, 21, 33, 31, 31, 21, 35, + 5, 17, 29, 38, 38, 18, 58, 19, + 43, 41, 30, 41, 43, 39, 29, 7, + 29, 17, 28, 19, 28, 31, 25, 19, + 40, 26, 21, 33, 39, 23, 40, 30, + 39, 34, 35, 32, 32, 24, 33, 30, + 40, 47, 39, 37, 32, 33, 24, 23, + 45, 47, 27, 23, 42, 32, 32, 33, + 36, 37, 37, 17, 18, 22, 40, 38, + 32, 31, 35, 24, 17, 25, 17, 23, + 33, 34, 51, 42, 31, 36, 36, 29, + 21, 22, 37, 44, 43, 25, 47, 33, + 45, 27, 31, 58, 31, 32, 31, 38, + 43, 20, 47, 45, 54, 1, 26, 34, + 38, 14, 22, 24, 33, 34, 32, 32, + 37, 21, 23, 49, 35, 23, 28, 39, + 39, 23, 55, 33, 30, 30, 63, 16, + 42, 28, 13, 33, 33, 35, 19, 46, + 43, 17, 19, 36, 39, 24, 31, 32, + 33, 26, 28, 62, 33, 63, 33, 39, + 19, 49, 17, 31, 43, 13, 15, 29, + 25, 35, 33, 23, 49, 41, 28, 29, + 34, 38, 7, 61, 11, 50, 13, 41, + 19, 47, 25, 26, 15, 42, 41, 29, + 45, 27, 17, 35, 32, 29, 32, 24, + 13, 26, 26, 31, 24, 33, 28, 30, + 31, 11, 45, 46, 33, 33, 35, 57, + 32, 32, 35, 45, 34, 11, 37, 42, + 39, 37, 31, 49, 21, 27, 29, 47, + 53, 40, 51, 16, 26, 1, 40, 30, + 41, 44, 34, 25, 27, 31, 35, 35, + 31, 15, 49, 1, 35, 40, 5, 58, + 21, 29, 22, 59, 45, 31, 9, 26, + 9, 29, 11, 32, 30, 3, 13, 20, + 18, 20, 11, 3, 29, 40, 31, 53, + 30, 17, 20, 37, 31, 42, 47, 47, + 54, 38, 9, 34, 13, 37, 21, 25, + 27, 43, 42, 45, 40, 25, 27, 46, + 22, 25, 53, 20, 2, 14, 39, 15, + 22, 44, 34, 21, 38, 33, 27, 48, + 34, 52, 35, 47, 49, 54, 2, 13, + 23, 52, 29, 45, 22, 49, 54, 21, + 40, 42, 31, 30, 29, 34, 0, 25, + 23, 51, 24, 59, 28, 38, 29, 31, + 2, 13, 31, 8, 31, 33, 12, 45, + 41, 7, 14, 30, 25, 18, 43, 20, + 43, 35, 44, 1, 49, 42, 42, 18, + 41, 38, 41, 44, 53, 11, 20, 25, + 45, 46, 47, 48, 39, 52, 46, 49, + 63, 55, 44, 38, 13, 13, 57, 22, + 51, 16, 12, 28, 35, 57, 25, 20, + 26, 28, 28, 29, 32, 31, 62, 34, + 35, 35, 19, 49, 48, 39, 40, 18, + 43, 46, 11, 6, 48, 19, 49, 41, + 10, 23, 58, 17, 21, 23, 34, 30, + 60, 0, 44, 34, 26, 37, 46, 43, + 49, 59, 4, 34, 59, 37, 22, 25, + 28, 46, 6, 40, 59, 42, 36, 61, + 28, 30, 31, 43, 10, 22, 23, 47, + 20, 52, 55, 36, 25, 16, 1, 11, + 27, 29, 5, 63, 18, 41, 31, 34, + 38, 1, 5, 13, 28, 31, 17, 38, + 39, 41, 36, 37, 22, 39, 33, 43, + 43, 15, 17, 49, 30, 21, 22, 20, + 10, 17, 25, 54, 57, 3, 34, 8, + 36, 25, 31, 14, 15, 19, 29, 25, + 18, 39, 53, 22, 27, 20, 29, 33, + 41, 42, 35, 62, 50, 29, 53, 50, + 35, 55, 42, 61, 63, 4, 7, 42, + 21, 46, 47, 49, 27, 46, 17, 55, + 41, 50, 63, 4, 56, 18, 8, 10, + 18, 51, 63, 36, 55, 18, 5, 55, + 9, 29, 17, 21, 30, 27, 1, 59, + 7, 11, 12, 15, 5, 42, 24, 41, + 43, 7, 27, 22, 25, 31, 30, 37, + 22, 39, 53, 29, 36, 37, 48, 0, + 5, 13, 17, 31, 32, 26, 46, 28, + 44, 45, 46, 53, 49, 51, 3, 41, + 3, 22, 42, 33, 5, 45, 7, 22, + 40, 53, 24, 14, 25, 27, 10, 12, + 34, 16, 17, 53, 20, 26, 39, 45, + 18, 45, 35, 33, 31, 49, 4, 39, + 42, 11, 51, 5, 13, 26, 27, 17, + 52, 30, 0, 22, 12, 34, 62, 36, + 38, 41, 47, 30, 63, 38, 41, 43, + 59, 33, 45, 37, 38, 40, 47, 24, + 48, 49, 30, 1, 10, 22, 49, 15, + 39, 59, 31, 32, 33, 18, 13, 15, + 31, 21, 27, 44, 42, 39, 46, 17, + 26, 32, 30, 31, 0, 30, 34, 9, + 12, 13, 25, 31, 32, 55, 43, 35, + 61, 33, 35, 46, 25, 47, 48, 62, + 63, 38, 61, 1, 2, 5, 7, 9, + 46, 10, 34, 35, 36, 55, 51, 7, + 40, 23, 34, 37, 5, 13, 42, 18, + 25, 27, 28, +}; + +/* motion vector table 1 */ +static const uint16_t table1_mv_code[1100] = { + 0x0000, 0x0007, 0x0009, 0x000f, 0x000a, 0x0011, 0x001a, 0x001c, + 0x0011, 0x0031, 0x0025, 0x002d, 0x002f, 0x006f, 0x0075, 0x0041, + 0x004c, 0x004e, 0x005c, 0x0060, 0x0062, 0x0066, 0x0068, 0x0069, + 0x006b, 0x00a6, 0x00c1, 0x00cb, 0x00cc, 0x00ce, 0x00da, 0x00e8, + 0x00ee, 0x0087, 0x0090, 0x009e, 0x009f, 0x00ba, 0x00ca, 0x00d8, + 0x00db, 0x00df, 0x0104, 0x0109, 0x010c, 0x0143, 0x0145, 0x014a, + 0x0156, 0x015c, 0x01b3, 0x01d3, 0x01da, 0x0103, 0x0109, 0x010b, + 0x0122, 0x0127, 0x0134, 0x0161, 0x0164, 0x0176, 0x0184, 0x018d, + 0x018e, 0x018f, 0x0190, 0x0193, 0x0196, 0x019d, 0x019e, 0x019f, + 0x01a9, 0x01b2, 0x01b4, 0x01ba, 0x01bb, 0x01bc, 0x0201, 0x0202, + 0x0205, 0x0207, 0x020d, 0x0210, 0x0211, 0x0215, 0x021b, 0x021f, + 0x0281, 0x0285, 0x0290, 0x029c, 0x029d, 0x02a2, 0x02a7, 0x02a8, + 0x02aa, 0x02b0, 0x02b1, 0x02b4, 0x02bc, 0x02bf, 0x0320, 0x0326, + 0x0327, 0x0329, 0x032a, 0x0336, 0x0360, 0x0362, 0x0363, 0x0372, + 0x03b2, 0x03bc, 0x03bd, 0x0203, 0x0205, 0x021a, 0x0249, 0x024a, + 0x024c, 0x02c7, 0x02ca, 0x02ce, 0x02ef, 0x030d, 0x0322, 0x0325, + 0x0338, 0x0373, 0x037a, 0x0409, 0x0415, 0x0416, 0x0418, 0x0428, + 0x042d, 0x042f, 0x0434, 0x0508, 0x0509, 0x0510, 0x0511, 0x051c, + 0x051e, 0x0524, 0x0541, 0x0543, 0x0546, 0x0547, 0x054d, 0x0557, + 0x055f, 0x056a, 0x056c, 0x056d, 0x056f, 0x0576, 0x0577, 0x057a, + 0x057b, 0x057c, 0x057d, 0x0600, 0x0601, 0x0603, 0x0614, 0x0616, + 0x0617, 0x061c, 0x061f, 0x0642, 0x0648, 0x0649, 0x064a, 0x064b, + 0x0657, 0x0668, 0x0669, 0x066b, 0x066e, 0x067f, 0x06c2, 0x06c8, + 0x06cb, 0x06de, 0x06df, 0x06e2, 0x06e3, 0x06ef, 0x0748, 0x074b, + 0x076e, 0x076f, 0x077c, 0x0409, 0x0423, 0x0428, 0x0429, 0x042a, + 0x042b, 0x0432, 0x0433, 0x0496, 0x049a, 0x04d5, 0x04db, 0x0581, + 0x0582, 0x058b, 0x058c, 0x058d, 0x0598, 0x0599, 0x059a, 0x059e, + 0x05dd, 0x0619, 0x0632, 0x0633, 0x0648, 0x0672, 0x06a1, 0x06a2, + 0x06a3, 0x06af, 0x06e2, 0x06e3, 0x06e4, 0x0800, 0x0801, 0x0802, + 0x0803, 0x081a, 0x081b, 0x0829, 0x082f, 0x0832, 0x083e, 0x083f, + 0x0852, 0x0853, 0x0858, 0x086b, 0x0877, 0x0878, 0x0879, 0x087a, + 0x087b, 0x0a00, 0x0a01, 0x0a0d, 0x0a0e, 0x0a0f, 0x0a24, 0x0a37, + 0x0a3a, 0x0a3b, 0x0a3e, 0x0a46, 0x0a47, 0x0a4a, 0x0a4b, 0x0a5f, + 0x0a79, 0x0a7a, 0x0a7b, 0x0a80, 0x0a81, 0x0a84, 0x0a85, 0x0a99, + 0x0aa5, 0x0aa6, 0x0ab8, 0x0aba, 0x0abb, 0x0abc, 0x0abd, 0x0ac8, + 0x0ace, 0x0acf, 0x0ad7, 0x0adc, 0x0aeb, 0x0c04, 0x0c25, 0x0c26, + 0x0c27, 0x0c2a, 0x0c2b, 0x0c3a, 0x0c3b, 0x0c3c, 0x0c3d, 0x0ca0, + 0x0cad, 0x0cd4, 0x0cd5, 0x0cfc, 0x0cfd, 0x0d86, 0x0d92, 0x0d93, + 0x0d94, 0x0d95, 0x0db0, 0x0db8, 0x0db9, 0x0dba, 0x0dbb, 0x0dc0, + 0x0dc2, 0x0dc3, 0x0dda, 0x0ddb, 0x0ddc, 0x0ddd, 0x0e92, 0x0e93, + 0x0e94, 0x0e95, 0x0ec7, 0x0ecc, 0x0ece, 0x0ecf, 0x0ed8, 0x0ed9, + 0x0eda, 0x0edb, 0x0808, 0x0809, 0x080a, 0x0810, 0x0811, 0x0844, + 0x0845, 0x0861, 0x0862, 0x0863, 0x086c, 0x0922, 0x0923, 0x092e, + 0x092f, 0x0936, 0x0937, 0x09b1, 0x09b2, 0x09b3, 0x09b4, 0x09b5, + 0x09b8, 0x09b9, 0x09ba, 0x09bb, 0x09bc, 0x09bd, 0x09be, 0x09bf, + 0x0b00, 0x0b15, 0x0b2c, 0x0b2d, 0x0b2e, 0x0b2f, 0x0b36, 0x0bb9, + 0x0c28, 0x0c2a, 0x0c2b, 0x0c2c, 0x0c2d, 0x0c2e, 0x0c2f, 0x0c30, + 0x0c31, 0x0c38, 0x0c60, 0x0c61, 0x0c62, 0x0c63, 0x0c8d, 0x0c8e, + 0x0c8f, 0x0c92, 0x0cbe, 0x0cbf, 0x0ce6, 0x0ce7, 0x0d40, 0x0d41, + 0x0d57, 0x0d58, 0x0d59, 0x0d5a, 0x0d5b, 0x0d5c, 0x0d5d, 0x0d98, + 0x0d99, 0x0d9a, 0x0d9b, 0x0d9c, 0x0d9d, 0x0dad, 0x0dae, 0x0daf, + 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3, 0x0dca, 0x0dcb, 0x0dec, 0x0ded, + 0x0dee, 0x0def, 0x1018, 0x1022, 0x1023, 0x1030, 0x1031, 0x1032, + 0x1033, 0x1050, 0x1051, 0x105c, 0x1074, 0x1075, 0x1076, 0x1077, + 0x1078, 0x1079, 0x107a, 0x107b, 0x10b2, 0x10b3, 0x10b8, 0x10b9, + 0x10ba, 0x10bb, 0x10d4, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x1404, + 0x1405, 0x1406, 0x1407, 0x1410, 0x1411, 0x1412, 0x1413, 0x1414, + 0x1415, 0x1416, 0x1417, 0x1418, 0x1419, 0x1466, 0x1467, 0x1468, + 0x1469, 0x146a, 0x146b, 0x146c, 0x146d, 0x147e, 0x147f, 0x1488, + 0x1489, 0x148a, 0x148b, 0x14b6, 0x14b7, 0x14b8, 0x14b9, 0x14ba, + 0x14bb, 0x14bc, 0x14bd, 0x14f0, 0x14f1, 0x14f8, 0x14f9, 0x14fa, + 0x14fb, 0x14fc, 0x14fd, 0x14fe, 0x14ff, 0x152a, 0x152b, 0x152c, + 0x152d, 0x152e, 0x152f, 0x1530, 0x1531, 0x1548, 0x1549, 0x154e, + 0x154f, 0x1558, 0x1559, 0x155a, 0x155b, 0x1572, 0x159a, 0x159b, + 0x15ac, 0x15ba, 0x15bb, 0x15d0, 0x15d1, 0x15d2, 0x15d3, 0x15d4, + 0x15d5, 0x181d, 0x181e, 0x181f, 0x1840, 0x1841, 0x1842, 0x1843, + 0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x1861, 0x1862, + 0x1863, 0x1864, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869, 0x186a, + 0x186b, 0x186c, 0x186d, 0x186e, 0x191b, 0x191c, 0x191d, 0x191e, + 0x191f, 0x1942, 0x1943, 0x1944, 0x1945, 0x1946, 0x1947, 0x1958, + 0x1959, 0x19ed, 0x19ee, 0x19ef, 0x19f0, 0x19f1, 0x19f2, 0x19f3, + 0x19f4, 0x19f5, 0x19f6, 0x19f7, 0x1b0e, 0x1b0f, 0x1b62, 0x1b63, + 0x1b64, 0x1b65, 0x1b66, 0x1b67, 0x1b68, 0x1b69, 0x1b6a, 0x1b6b, + 0x1b6c, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b82, 0x1ba8, 0x1ba9, 0x1baa, + 0x1bab, 0x1bac, 0x1bad, 0x1bae, 0x1baf, 0x1bb0, 0x1bb1, 0x1bb2, + 0x1bb3, 0x1d80, 0x1d81, 0x1d82, 0x1d83, 0x1d84, 0x1d85, 0x1d86, + 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8d, 0x1007, + 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f, + 0x1016, 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, + 0x1087, 0x10c0, 0x123a, 0x123b, 0x123c, 0x123d, 0x123e, 0x123f, + 0x1240, 0x1241, 0x1242, 0x1243, 0x1350, 0x1352, 0x1353, 0x1358, + 0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, 0x1360, + 0x1361, 0x1602, 0x1603, 0x160c, 0x160d, 0x160e, 0x160f, 0x1620, + 0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627, 0x1628, + 0x1629, 0x166e, 0x166f, 0x167c, 0x167d, 0x167e, 0x167f, 0x1770, + 0x1771, 0x1852, 0x1853, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, + 0x1877, 0x1878, 0x1879, 0x187a, 0x187b, 0x187c, 0x187d, 0x187e, + 0x187f, 0x1918, 0x1919, 0x1926, 0x1927, 0x1970, 0x1971, 0x1972, + 0x1973, 0x1974, 0x1975, 0x1976, 0x1977, 0x1978, 0x1979, 0x197a, + 0x197b, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6, + 0x1aa7, 0x1aa8, 0x1aa9, 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b3c, + 0x1b3d, 0x1b3e, 0x1b3f, 0x1b50, 0x1b51, 0x1b52, 0x1b53, 0x1b54, + 0x1b55, 0x1b56, 0x1b57, 0x1b58, 0x1b59, 0x2032, 0x2033, 0x2034, + 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, 0x203c, + 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x20ba, + 0x20bb, 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20e0, 0x20e1, 0x20e2, + 0x20e3, 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x21aa, 0x21ab, 0x21c0, + 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, 0x21c8, + 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, 0x21d0, + 0x21d1, 0x21d2, 0x21d3, 0x2894, 0x2895, 0x2896, 0x2897, 0x2898, + 0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f, 0x28c0, + 0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7, 0x28c8, + 0x28c9, 0x28ca, 0x28cb, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, + 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c, + 0x293d, 0x293e, 0x293f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, + 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x2a40, + 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47, 0x2a48, + 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f, 0x2a50, + 0x2a51, 0x2a52, 0x2a53, 0x2ae6, 0x2ae7, 0x2b24, 0x2b25, 0x2b26, + 0x2b27, 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e, + 0x2b2f, 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b5a, 0x2b5b, 0x3014, + 0x3015, 0x3016, 0x3017, 0x3020, 0x3021, 0x3022, 0x3023, 0x3024, + 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c, + 0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034, + 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x30c0, 0x30c1, 0x30de, + 0x30df, 0x3218, 0x3219, 0x321a, 0x321b, 0x321c, 0x321d, 0x321e, + 0x321f, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226, + 0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e, + 0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3378, + 0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x337f, 0x33c0, + 0x33c1, 0x33c2, 0x33c3, 0x33c4, 0x33c5, 0x33c6, 0x33c7, 0x33c8, + 0x33c9, 0x33ca, 0x33cb, 0x33cc, 0x33cd, 0x33ce, 0x33cf, 0x33d0, + 0x33d1, 0x33d2, 0x33d3, 0x33d4, 0x33d5, 0x33d6, 0x33d7, 0x33d8, + 0x33d9, 0x3706, 0x3707, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734, + 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c, + 0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744, + 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c, + 0x374d, 0x374e, 0x374f, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3be8, + 0x3be9, 0x3bea, 0x3beb, 0x3bec, 0x3bed, 0x3bee, 0x3bef, 0x3bf0, + 0x3bf1, 0x3bf2, 0x3bf3, 0x3bf4, 0x3bf5, 0x3bf6, 0x3bf7, 0x3bf8, + 0x3bf9, 0x3bfa, 0x3bfb, 0x3bfc, 0x3bfd, 0x3bfe, 0x3bff, 0x2000, + 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, + 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x202e, 0x202f, 0x2182, + 0x2183, 0x21b4, 0x21b5, 0x21b6, 0x21b7, 0x21b8, 0x21b9, 0x21ba, + 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x2460, 0x2461, 0x2462, + 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a, + 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472, + 0x2473, 0x26a2, 0x26a3, 0x000b, +}; + +static const uint8_t table1_mv_bits[1100] = { + 2, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 4, +}; + +static const uint8_t table1_mvx[1099] = { + 32, 31, 32, 31, 33, 32, 33, 33, + 31, 34, 30, 32, 32, 34, 35, 32, + 34, 33, 29, 30, 30, 32, 31, 31, + 33, 35, 35, 33, 31, 29, 29, 33, + 34, 30, 31, 28, 36, 30, 34, 32, + 32, 37, 32, 32, 25, 27, 39, 32, + 32, 32, 38, 35, 36, 32, 37, 61, + 26, 32, 34, 35, 3, 35, 27, 28, + 29, 34, 28, 37, 31, 36, 32, 27, + 31, 30, 29, 39, 33, 29, 33, 35, + 25, 25, 29, 33, 31, 31, 31, 33, + 32, 30, 32, 32, 41, 39, 33, 36, + 32, 28, 34, 36, 38, 24, 60, 31, + 23, 28, 32, 33, 59, 32, 40, 30, + 5, 34, 32, 38, 32, 30, 43, 4, + 32, 32, 42, 31, 31, 32, 26, 38, + 26, 22, 21, 37, 61, 63, 37, 31, + 32, 33, 2, 1, 23, 33, 41, 27, + 35, 30, 38, 23, 33, 3, 28, 34, + 34, 27, 41, 29, 39, 35, 36, 29, + 32, 27, 30, 32, 24, 61, 37, 26, + 59, 25, 35, 27, 36, 37, 30, 31, + 34, 40, 3, 28, 34, 39, 32, 31, + 32, 30, 24, 28, 35, 36, 26, 32, + 31, 33, 29, 33, 39, 25, 30, 24, + 35, 59, 29, 34, 25, 30, 21, 35, + 43, 40, 32, 29, 5, 28, 31, 62, + 33, 33, 25, 31, 21, 31, 43, 31, + 34, 33, 20, 40, 39, 31, 31, 57, + 38, 32, 42, 33, 32, 31, 32, 29, + 30, 44, 5, 31, 22, 34, 36, 17, + 38, 58, 38, 35, 32, 60, 35, 24, + 32, 38, 16, 45, 42, 32, 31, 29, + 4, 30, 17, 40, 46, 48, 63, 32, + 42, 19, 41, 22, 28, 36, 45, 33, + 33, 32, 29, 7, 41, 42, 18, 33, + 33, 32, 22, 37, 1, 26, 22, 23, + 49, 28, 26, 27, 32, 33, 27, 23, + 28, 36, 15, 6, 34, 27, 31, 26, + 23, 2, 33, 32, 34, 41, 28, 32, + 41, 0, 36, 38, 34, 31, 47, 32, + 17, 31, 39, 33, 37, 51, 30, 47, + 32, 50, 32, 19, 63, 30, 25, 27, + 33, 62, 24, 31, 27, 30, 37, 31, + 45, 32, 39, 20, 46, 47, 35, 19, + 34, 1, 49, 21, 21, 14, 51, 26, + 23, 31, 36, 35, 58, 29, 29, 21, + 20, 42, 13, 28, 12, 40, 31, 33, + 39, 60, 32, 44, 33, 31, 28, 37, + 29, 32, 30, 49, 43, 28, 39, 25, + 32, 48, 2, 15, 20, 25, 31, 28, + 21, 24, 25, 15, 31, 17, 37, 43, + 18, 32, 33, 24, 33, 36, 13, 33, + 31, 39, 11, 31, 33, 32, 39, 37, + 32, 32, 29, 17, 44, 46, 36, 35, + 26, 37, 58, 32, 34, 38, 8, 38, + 38, 22, 29, 25, 16, 35, 32, 35, + 33, 43, 18, 46, 38, 50, 33, 18, + 53, 60, 13, 32, 36, 33, 51, 36, + 43, 45, 27, 42, 29, 24, 30, 25, + 31, 52, 31, 35, 38, 9, 22, 34, + 4, 17, 28, 55, 42, 25, 17, 20, + 47, 34, 33, 16, 40, 25, 16, 30, + 53, 29, 10, 11, 14, 26, 33, 4, + 35, 44, 26, 16, 31, 26, 34, 38, + 29, 31, 30, 24, 22, 61, 32, 9, + 45, 34, 31, 19, 9, 31, 46, 31, + 35, 54, 29, 57, 30, 50, 3, 31, + 63, 34, 47, 41, 51, 18, 31, 14, + 37, 38, 31, 24, 32, 31, 50, 33, + 31, 54, 27, 9, 33, 23, 19, 32, + 29, 29, 33, 28, 47, 49, 30, 47, + 33, 27, 25, 54, 44, 45, 50, 58, + 51, 48, 33, 59, 33, 34, 57, 13, + 26, 33, 13, 48, 30, 11, 7, 56, + 34, 55, 26, 0, 26, 35, 1, 51, + 33, 53, 31, 45, 12, 29, 29, 51, + 31, 48, 2, 6, 34, 30, 28, 33, + 60, 40, 27, 46, 31, 9, 35, 29, + 31, 39, 55, 46, 19, 37, 62, 34, + 30, 16, 19, 49, 41, 41, 39, 37, + 14, 5, 13, 35, 55, 30, 40, 40, + 42, 8, 20, 25, 45, 35, 33, 36, + 54, 38, 27, 37, 62, 40, 15, 59, + 49, 31, 29, 34, 34, 39, 24, 29, + 25, 29, 21, 29, 10, 61, 33, 49, + 35, 34, 3, 38, 39, 29, 7, 41, + 1, 35, 4, 23, 15, 23, 11, 37, + 28, 35, 30, 30, 24, 1, 43, 56, + 8, 34, 42, 24, 45, 30, 20, 23, + 8, 38, 22, 33, 17, 52, 34, 22, + 53, 43, 44, 1, 27, 31, 41, 43, + 41, 30, 31, 36, 30, 5, 55, 31, + 33, 30, 40, 23, 15, 29, 34, 34, + 59, 34, 30, 11, 13, 38, 5, 0, + 30, 42, 5, 30, 29, 34, 10, 44, + 30, 63, 35, 12, 3, 26, 15, 17, + 25, 34, 43, 39, 34, 56, 29, 23, + 30, 12, 30, 10, 35, 9, 24, 58, + 10, 12, 54, 33, 37, 20, 41, 35, + 29, 18, 61, 30, 40, 24, 39, 53, + 62, 26, 29, 33, 34, 53, 49, 21, + 27, 11, 63, 20, 26, 23, 7, 13, + 6, 47, 29, 30, 9, 51, 22, 34, + 21, 25, 33, 56, 57, 30, 38, 51, + 51, 38, 63, 28, 40, 35, 33, 18, + 33, 33, 24, 58, 58, 34, 49, 29, + 43, 4, 1, 4, 42, 35, 35, 30, + 17, 5, 56, 61, 25, 37, 36, 55, + 28, 35, 29, 50, 48, 52, 2, 42, + 34, 40, 46, 46, 43, 35, 29, 48, + 20, 29, 31, 41, 7, 30, 35, 19, + 14, 21, 8, 39, 39, 40, 46, 55, + 34, 6, 30, 34, 37, 25, 37, 33, + 22, 44, 52, 17, 35, 29, 36, 35, + 40, 37, 28, 30, 50, 14, 28, 55, + 6, 23, 19, 14, 30, 3, 30, 28, + 28, 61, 61, 47, 45, 48, 40, 40, + 34, 34, 25, 30, 29, 35, 4, 26, + 53, 50, 26, 41, 27, 59, 27, 38, + 39, 3, 50, 43, 47, 23, 33, 55, + 35, 21, 23, 35, 61, 33, 46, 52, + 35, 34, 24, 30, 43, 16, 37, 21, + 2, 24, 45, 34, 30, 55, 55, 1, + 29, 29, 26, 28, 25, 31, 36, 22, + 17, 30, 52, 2, 44, 44, 57, 26, + 62, 41, 39, 57, 26, 46, 49, 11, + 16, 19, 5, 59, 38, 39, 58, 38, + 25, 49, 50, 22, 28, 59, 9, 59, + 7, 28, 55, 17, 4, 35, 50, 21, + 29, 44, 47, 18, 24, 19, 25, 42, + 35, 3, 51, 35, 16, 35, 30, 63, + 57, 39, 39, 25, 35, 38, 9, 16, + 36, 45, 31, 60, 14, 34, 42, 24, + 0, 37, 18, 61, 57, 37, 28, 53, + 20, 46, 14, 47, 38, 38, 38, 9, + 34, 39, 43, 17, 39, 59, 5, 27, + 0, 12, 27, +}; + +static const uint8_t table1_mvy[1099] = { + 32, 32, 31, 31, 32, 33, 31, 33, + 33, 32, 32, 30, 34, 31, 32, 29, + 33, 30, 32, 33, 31, 35, 34, 30, + 34, 31, 33, 29, 29, 31, 33, 35, + 30, 30, 35, 32, 32, 34, 34, 28, + 25, 32, 36, 27, 32, 32, 32, 37, + 39, 3, 32, 30, 31, 26, 31, 32, + 32, 38, 29, 29, 32, 34, 31, 31, + 34, 35, 33, 33, 28, 33, 1, 33, + 27, 29, 30, 31, 28, 29, 37, 35, + 31, 33, 35, 27, 36, 37, 25, 25, + 61, 35, 4, 5, 32, 33, 36, 30, + 23, 30, 28, 34, 31, 32, 32, 39, + 32, 34, 21, 39, 32, 59, 32, 28, + 32, 36, 60, 33, 24, 36, 32, 32, + 41, 2, 32, 38, 26, 22, 33, 30, + 31, 32, 32, 30, 31, 32, 29, 3, + 40, 38, 32, 32, 33, 26, 31, 34, + 28, 38, 34, 31, 3, 31, 35, 38, + 27, 35, 33, 28, 29, 27, 29, 27, + 43, 29, 37, 63, 31, 33, 34, 30, + 31, 30, 37, 30, 35, 35, 26, 41, + 37, 31, 33, 28, 26, 30, 42, 24, + 7, 27, 33, 29, 36, 28, 34, 57, + 23, 41, 36, 23, 35, 34, 25, 30, + 25, 33, 25, 25, 29, 24, 33, 39, + 33, 33, 0, 37, 31, 36, 21, 32, + 61, 24, 35, 61, 31, 5, 31, 59, + 39, 21, 32, 30, 34, 22, 40, 32, + 29, 16, 31, 5, 62, 2, 20, 39, + 39, 32, 33, 1, 31, 24, 36, 32, + 36, 32, 28, 26, 6, 31, 38, 34, + 58, 35, 32, 33, 33, 17, 43, 26, + 31, 40, 31, 34, 32, 32, 31, 19, + 30, 32, 29, 33, 38, 38, 32, 59, + 40, 18, 38, 32, 35, 34, 32, 17, + 1, 15, 30, 28, 31, 28, 34, 29, + 32, 27, 35, 27, 49, 22, 37, 34, + 37, 26, 32, 32, 22, 28, 45, 29, + 30, 31, 43, 46, 41, 30, 26, 13, + 34, 32, 27, 38, 42, 42, 33, 47, + 33, 60, 27, 42, 25, 32, 22, 32, + 48, 32, 45, 33, 33, 41, 27, 25, + 19, 31, 35, 19, 36, 42, 27, 17, + 31, 44, 28, 33, 33, 31, 23, 31, + 40, 33, 31, 34, 30, 32, 33, 36, + 35, 47, 37, 41, 31, 23, 41, 29, + 30, 35, 32, 25, 32, 28, 58, 2, + 37, 33, 14, 33, 49, 20, 39, 36, + 21, 9, 23, 33, 35, 24, 39, 37, + 11, 33, 30, 31, 31, 28, 51, 40, + 35, 29, 25, 33, 46, 35, 37, 30, + 30, 8, 63, 28, 15, 40, 33, 45, + 49, 25, 32, 4, 47, 51, 36, 39, + 53, 10, 24, 29, 30, 31, 25, 40, + 38, 38, 33, 56, 23, 27, 32, 37, + 26, 29, 43, 36, 33, 24, 55, 43, + 9, 29, 34, 34, 24, 33, 18, 33, + 33, 30, 31, 50, 24, 60, 30, 39, + 34, 30, 39, 28, 22, 38, 2, 26, + 63, 32, 57, 21, 39, 33, 28, 18, + 30, 34, 22, 33, 29, 41, 30, 34, + 35, 21, 13, 34, 35, 39, 30, 46, + 32, 42, 32, 31, 33, 26, 11, 33, + 22, 31, 25, 31, 53, 27, 43, 25, + 40, 50, 21, 36, 38, 30, 12, 31, + 34, 20, 15, 29, 32, 62, 30, 13, + 17, 32, 19, 31, 20, 31, 30, 7, + 1, 17, 34, 37, 31, 31, 44, 34, + 26, 40, 16, 37, 52, 48, 30, 20, + 18, 33, 38, 29, 7, 25, 30, 54, + 45, 47, 46, 41, 29, 29, 16, 30, + 14, 26, 38, 34, 34, 29, 34, 30, + 29, 30, 57, 30, 4, 46, 33, 29, + 39, 44, 30, 31, 50, 33, 31, 32, + 19, 32, 40, 31, 37, 47, 1, 35, + 16, 31, 0, 35, 33, 1, 17, 34, + 9, 34, 33, 31, 49, 43, 42, 51, + 34, 29, 23, 29, 14, 30, 45, 49, + 11, 24, 31, 28, 35, 41, 30, 44, + 18, 29, 34, 35, 36, 25, 26, 21, + 31, 30, 34, 19, 34, 44, 36, 38, + 25, 31, 28, 23, 37, 3, 55, 41, + 30, 22, 41, 24, 33, 26, 35, 35, + 30, 55, 51, 47, 48, 38, 24, 15, + 21, 50, 25, 46, 30, 29, 10, 34, + 42, 45, 29, 42, 22, 3, 33, 27, + 34, 1, 34, 28, 34, 36, 35, 23, + 23, 13, 58, 3, 26, 63, 25, 31, + 34, 61, 38, 39, 25, 61, 29, 37, + 30, 41, 26, 48, 28, 33, 50, 35, + 30, 37, 29, 29, 40, 6, 39, 28, + 28, 19, 8, 22, 45, 34, 35, 10, + 58, 17, 37, 39, 30, 18, 54, 14, + 29, 16, 59, 30, 35, 23, 35, 30, + 47, 36, 29, 55, 20, 12, 31, 35, + 14, 29, 18, 34, 34, 24, 29, 26, + 22, 2, 27, 23, 8, 30, 55, 38, + 60, 31, 4, 34, 49, 34, 27, 34, + 33, 30, 31, 54, 42, 35, 38, 46, + 44, 26, 27, 9, 39, 25, 21, 29, + 28, 42, 13, 0, 5, 34, 37, 28, + 24, 29, 63, 26, 22, 27, 29, 25, + 33, 25, 61, 0, 35, 25, 36, 15, + 27, 40, 53, 33, 3, 10, 16, 37, + 38, 18, 30, 46, 27, 9, 6, 29, + 62, 8, 42, 28, 29, 3, 25, 16, + 26, 29, 35, 28, 27, 51, 61, 48, + 37, 9, 34, 7, 49, 45, 20, 29, + 21, 5, 5, 29, 28, 34, 29, 24, + 10, 24, 35, 36, 38, 55, 11, 36, + 38, 53, 54, 26, 30, 49, 20, 27, + 30, 39, 33, 41, 49, 22, 38, 38, + 4, 30, 8, 9, 3, 24, 22, 50, + 37, 36, 31, 27, 2, 9, 42, 63, + 25, 19, 44, 1, 28, 28, 48, 30, + 34, 41, 41, 38, 12, 27, 15, 0, + 16, 34, 35, 38, 28, 29, 40, 42, + 51, 52, 45, 54, 59, 59, 42, 44, + 37, 26, 46, 24, 15, 39, 22, 46, + 19, 35, 38, 17, 37, 23, 52, 55, + 50, 37, 26, 11, 37, 12, 24, 30, + 16, 13, 22, 13, 36, 35, 40, 41, + 34, 41, 26, 53, 51, 5, 21, 30, + 2, 63, 41, 20, 1, 56, 21, 24, + 25, 5, 28, 35, 26, 28, 30, 18, + 29, 23, 40, 34, 20, 42, 39, 34, + 28, 61, 38, 27, 62, 9, 36, 17, + 9, 49, 24, 25, 54, 34, 39, 37, + 3, 1, 25, 38, 38, 44, 35, 36, + 12, 60, 36, 38, 40, 25, 43, 39, + 53, 28, 39, 57, 46, 10, 52, 27, + 35, 42, 45, 59, 15, 60, 38, 24, + 23, 39, 12, 29, 24, 0, 20, 16, + 28, 43, 35, 28, 1, 49, 4, 21, + 42, 39, 29, 3, 44, 21, 53, 55, + 11, 5, 3, 39, 53, 28, 25, 19, + 34, 28, 21, +}; + +MVTable ff_mv_tables[2] = { + { + 1099, + table0_mv_code, + table0_mv_bits, + table0_mvx, + table0_mvy, + }, + { + 1099, + table1_mv_code, + table1_mv_bits, + table1_mvx, + table1_mvy, + } +}; + +const uint8_t ff_v2_mb_type[8][2] = { + {1, 1}, {0 , 2}, {3 , 3}, {9 , 5}, + {5, 4}, {0x21, 7}, {0x20, 7}, {0x11, 6}, +}; + +const uint8_t ff_v2_intra_cbpc[4][2] = { + {1, 1}, {0, 3}, {1, 3}, {1, 2}, +}; + +const uint8_t ff_wmv1_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, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21 +}; +const uint8_t ff_wmv1_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,19,20,20,21,21,22 +}; + +const uint8_t ff_old_ff_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,33,34,35,36,37,38,39 +}; + +const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64]={ + { + 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, + 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28, + 0x30, 0x38, 0x29, 0x21, 0x1A, 0x13, 0x0C, 0x05, + 0x06, 0x0D, 0x14, 0x1B, 0x22, 0x31, 0x39, 0x3A, + 0x32, 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, + 0x16, 0x1D, 0x24, 0x2B, 0x33, 0x3B, 0x3C, 0x34, + 0x2C, 0x25, 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x35, + 0x3D, 0x3E, 0x36, 0x2E, 0x27, 0x2F, 0x37, 0x3F, + }, + { + 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, + 0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28, + 0x21, 0x30, 0x1A, 0x13, 0x0C, 0x05, 0x06, 0x0D, + 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, 0x2A, + 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, 0x16, 0x1D, + 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x3B, 0x2C, 0x25, + 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3C, 0x35, + 0x3D, 0x2E, 0x27, 0x2F, 0x36, 0x3E, 0x37, 0x3F, + }, + { + 0x00, 0x01, 0x08, 0x02, 0x03, 0x09, 0x10, 0x18, + 0x11, 0x0A, 0x04, 0x05, 0x0B, 0x12, 0x19, 0x20, + 0x28, 0x30, 0x21, 0x1A, 0x13, 0x0C, 0x06, 0x07, + 0x0D, 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, + 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x0F, 0x16, 0x1D, + 0x24, 0x2B, 0x32, 0x3A, 0x33, 0x2C, 0x25, 0x1E, + 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3B, 0x3C, 0x35, + 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, + }, + { + 0x00, 0x08, 0x10, 0x01, 0x18, 0x20, 0x28, 0x09, + 0x02, 0x03, 0x0A, 0x11, 0x19, 0x30, 0x38, 0x29, + 0x21, 0x1A, 0x12, 0x0B, 0x04, 0x05, 0x0C, 0x13, + 0x1B, 0x22, 0x31, 0x39, 0x32, 0x2A, 0x23, 0x1C, + 0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1D, 0x24, + 0x2B, 0x33, 0x3A, 0x3B, 0x34, 0x2C, 0x25, 0x1E, + 0x16, 0x0F, 0x17, 0x1F, 0x26, 0x2D, 0x3C, 0x35, + 0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, + } +}; + +const uint8_t ff_table_inter_intra[4][2]={ + {0,1} /*Luma-Left Chroma-Left*/, + {2,2} /*Luma-Top Chroma-Left*/, + {6,3} /*luma-Left Chroma-Top */, + {7,3} /*luma-Top Chroma-Top */ +}; + +static const uint32_t table_mb_non_intra2[128][2] = { +{0x0000A7, 14}, {0x01B2B8, 18}, {0x01B28E, 18}, {0x036575, 19}, +{0x006CAC, 16}, {0x000A69, 18}, {0x002934, 20}, {0x00526B, 21}, +{0x006CA1, 16}, {0x01B2B9, 18}, {0x0029AD, 20}, {0x029353, 24}, +{0x006CA7, 16}, {0x006CAB, 16}, {0x01B2BB, 18}, {0x00029B, 16}, +{0x00D944, 17}, {0x000A6A, 18}, {0x0149A8, 23}, {0x03651F, 19}, +{0x006CAF, 16}, {0x000A4C, 18}, {0x03651E, 19}, {0x000A48, 18}, +{0x00299C, 20}, {0x00299F, 20}, {0x029352, 24}, {0x0029AC, 20}, +{0x000296, 16}, {0x00D946, 17}, {0x000A68, 18}, {0x000298, 16}, +{0x000527, 17}, {0x00D94D, 17}, {0x0014D7, 19}, {0x036574, 19}, +{0x000A5C, 18}, {0x01B299, 18}, {0x00299D, 20}, {0x00299E, 20}, +{0x000525, 17}, {0x000A66, 18}, {0x00A4D5, 22}, {0x00149B, 19}, +{0x000295, 16}, {0x006CAD, 16}, {0x000A49, 18}, {0x000521, 17}, +{0x006CAA, 16}, {0x00D945, 17}, {0x01B298, 18}, {0x00052F, 17}, +{0x003654, 15}, {0x006CA0, 16}, {0x000532, 17}, {0x000291, 16}, +{0x003652, 15}, {0x000520, 17}, {0x000A5D, 18}, {0x000294, 16}, +{0x00009B, 11}, {0x0006E2, 12}, {0x000028, 12}, {0x0001B0, 10}, +{0x000001, 3}, {0x000010, 8}, {0x00002F, 6}, {0x00004C, 10}, +{0x00000D, 4}, {0x000000, 10}, {0x000006, 9}, {0x000134, 12}, +{0x00000C, 4}, {0x000007, 10}, {0x000007, 9}, {0x0006E1, 12}, +{0x00000E, 5}, {0x0000DA, 9}, {0x000022, 9}, {0x000364, 11}, +{0x00000F, 4}, {0x000006, 10}, {0x00000F, 9}, {0x000135, 12}, +{0x000014, 5}, {0x0000DD, 9}, {0x000004, 9}, {0x000015, 11}, +{0x00001A, 6}, {0x0001B3, 10}, {0x000005, 10}, {0x0006E3, 12}, +{0x00000C, 5}, {0x0000B9, 8}, {0x000004, 8}, {0x0000DB, 9}, +{0x00000E, 4}, {0x00000B, 10}, {0x000023, 9}, {0x0006CB, 12}, +{0x000005, 6}, {0x0001B1, 10}, {0x000001, 10}, {0x0006E0, 12}, +{0x000011, 5}, {0x0000DF, 9}, {0x00000E, 9}, {0x000373, 11}, +{0x000003, 5}, {0x0000B8, 8}, {0x000006, 8}, {0x000175, 9}, +{0x000015, 5}, {0x000174, 9}, {0x000027, 9}, {0x000372, 11}, +{0x000010, 5}, {0x0000BB, 8}, {0x000005, 8}, {0x0000DE, 9}, +{0x00000F, 5}, {0x000001, 9}, {0x000012, 8}, {0x000004, 10}, +{0x000002, 3}, {0x000016, 5}, {0x000009, 4}, {0x000001, 5}, +}; + +static const uint32_t table_mb_non_intra3[128][2] = { +{0x0002A1, 10}, {0x005740, 15}, {0x01A0BF, 18}, {0x015D19, 17}, +{0x001514, 13}, {0x00461E, 15}, {0x015176, 17}, {0x015177, 17}, +{0x0011AD, 13}, {0x00682E, 16}, {0x0682F9, 20}, {0x03417D, 19}, +{0x001A36, 14}, {0x002A2D, 14}, {0x00D05E, 17}, {0x006824, 16}, +{0x001515, 13}, {0x00545C, 15}, {0x0230E9, 18}, {0x011AFA, 17}, +{0x0015D7, 13}, {0x005747, 15}, {0x008D79, 16}, {0x006825, 16}, +{0x002BA2, 14}, {0x00A8BA, 16}, {0x0235F6, 18}, {0x015D18, 17}, +{0x0011AE, 13}, {0x00346F, 15}, {0x008C3B, 16}, {0x00346E, 15}, +{0x000D1A, 13}, {0x00461F, 15}, {0x0682F8, 20}, {0x011875, 17}, +{0x002BA1, 14}, {0x008D61, 16}, {0x0235F7, 18}, {0x0230E8, 18}, +{0x001513, 13}, {0x008D7B, 16}, {0x011AF4, 17}, {0x011AF5, 17}, +{0x001185, 13}, {0x0046BF, 15}, {0x008D60, 16}, {0x008D7C, 16}, +{0x001512, 13}, {0x00461C, 15}, {0x00AE8D, 16}, {0x008D78, 16}, +{0x000D0E, 13}, {0x003413, 15}, {0x0046B1, 15}, {0x003416, 15}, +{0x000AEA, 12}, {0x002A2C, 14}, {0x005741, 15}, {0x002A2F, 14}, +{0x000158, 9}, {0x0008D2, 12}, {0x00054C, 11}, {0x000686, 12}, +{0x000000, 2}, {0x000069, 8}, {0x00006B, 8}, {0x00068C, 12}, +{0x000007, 3}, {0x00015E, 9}, {0x0002A3, 10}, {0x000AE9, 12}, +{0x000006, 3}, {0x000231, 10}, {0x0002B8, 10}, {0x001A08, 14}, +{0x000010, 5}, {0x0001A9, 10}, {0x000342, 11}, {0x000A88, 12}, +{0x000004, 4}, {0x0001A2, 10}, {0x0002A4, 10}, {0x001184, 13}, +{0x000012, 5}, {0x000232, 10}, {0x0002B2, 10}, {0x000680, 12}, +{0x00001B, 6}, {0x00046A, 11}, {0x00068E, 12}, {0x002359, 14}, +{0x000016, 5}, {0x00015F, 9}, {0x0002A0, 10}, {0x00054D, 11}, +{0x000005, 4}, {0x000233, 10}, {0x0002B9, 10}, {0x0015D6, 13}, +{0x000022, 6}, {0x000468, 11}, {0x000683, 12}, {0x001A0A, 14}, +{0x000013, 5}, {0x000236, 10}, {0x0002BB, 10}, {0x001186, 13}, +{0x000017, 5}, {0x0001AB, 10}, {0x0002A7, 10}, {0x0008D3, 12}, +{0x000014, 5}, {0x000237, 10}, {0x000460, 11}, {0x000D0F, 13}, +{0x000019, 6}, {0x0001AA, 10}, {0x0002B3, 10}, {0x000681, 12}, +{0x000018, 6}, {0x0001A8, 10}, {0x0002A5, 10}, {0x00068F, 12}, +{0x000007, 4}, {0x000055, 7}, {0x000047, 7}, {0x0000AD, 8}, +}; + +static const uint32_t table_mb_non_intra4[128][2] = { +{0x0000D4, 8}, {0x0021C5, 14}, {0x00F18A, 16}, {0x00D5BC, 16}, +{0x000879, 12}, {0x00354D, 14}, {0x010E3F, 17}, {0x010F54, 17}, +{0x000866, 12}, {0x00356E, 14}, {0x010F55, 17}, {0x010E3E, 17}, +{0x0010CE, 13}, {0x003C84, 14}, {0x00D5BD, 16}, {0x00F18B, 16}, +{0x000868, 12}, {0x00438C, 15}, {0x0087AB, 16}, {0x00790B, 15}, +{0x000F10, 12}, {0x00433D, 15}, {0x006AD3, 15}, {0x00790A, 15}, +{0x001AA7, 13}, {0x0043D4, 15}, {0x00871E, 16}, {0x006ADF, 15}, +{0x000D7C, 12}, {0x003C94, 14}, {0x00438D, 15}, {0x006AD2, 15}, +{0x0006BC, 11}, {0x0021E9, 14}, {0x006ADA, 15}, {0x006A99, 15}, +{0x0010F7, 13}, {0x004389, 15}, {0x006ADB, 15}, {0x0078C4, 15}, +{0x000D56, 12}, {0x0035F7, 14}, {0x00438E, 15}, {0x006A98, 15}, +{0x000D52, 12}, {0x003C95, 14}, {0x004388, 15}, {0x00433C, 15}, +{0x000D54, 12}, {0x001E4B, 13}, {0x003C63, 14}, {0x003C83, 14}, +{0x000861, 12}, {0x0021EB, 14}, {0x00356C, 14}, {0x0035F6, 14}, +{0x000863, 12}, {0x00219F, 14}, {0x003568, 14}, {0x003C82, 14}, +{0x0001AE, 9}, {0x0010C0, 13}, {0x000F11, 12}, {0x001AFA, 13}, +{0x000000, 1}, {0x0000F0, 8}, {0x0001AD, 9}, {0x0010C1, 13}, +{0x00000A, 4}, {0x0003C5, 10}, {0x000789, 11}, {0x001AB5, 13}, +{0x000009, 4}, {0x000435, 11}, {0x000793, 11}, {0x001E40, 13}, +{0x00001D, 5}, {0x0003CB, 10}, {0x000878, 12}, {0x001AAF, 13}, +{0x00000B, 4}, {0x0003C7, 10}, {0x000791, 11}, {0x001AAB, 13}, +{0x00001F, 5}, {0x000436, 11}, {0x0006BF, 11}, {0x000F19, 12}, +{0x00003D, 6}, {0x000D51, 12}, {0x0010C4, 13}, {0x0021E8, 14}, +{0x000036, 6}, {0x000437, 11}, {0x0006AF, 11}, {0x0010C5, 13}, +{0x00000C, 4}, {0x000432, 11}, {0x000794, 11}, {0x001E30, 13}, +{0x000042, 7}, {0x000870, 12}, {0x000F24, 12}, {0x001E43, 13}, +{0x000020, 6}, {0x00043E, 11}, {0x000795, 11}, {0x001AAA, 13}, +{0x000037, 6}, {0x0006AC, 11}, {0x0006AE, 11}, {0x0010F6, 13}, +{0x000034, 6}, {0x00043A, 11}, {0x000D50, 12}, {0x001AAE, 13}, +{0x000039, 6}, {0x00043F, 11}, {0x00078D, 11}, {0x0010D2, 13}, +{0x000038, 6}, {0x00043B, 11}, {0x0006BD, 11}, {0x0010D3, 13}, +{0x000011, 5}, {0x0001AC, 9}, {0x0000F3, 8}, {0x000439, 11}, +}; + +const uint32_t (* const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2]={ + table_mb_non_intra2, + table_mb_non_intra3, + table_mb_non_intra4, + ff_table_mb_non_intra, +}; + +const uint8_t ff_wmv2_scantableA[64]={ +0x00, 0x01, 0x02, 0x08, 0x03, 0x09, 0x0A, 0x10, +0x04, 0x0B, 0x11, 0x18, 0x12, 0x0C, 0x05, 0x13, +0x19, 0x0D, 0x14, 0x1A, 0x1B, 0x06, 0x15, 0x1C, +0x0E, 0x16, 0x1D, 0x07, 0x1E, 0x0F, 0x17, 0x1F, +}; + +const uint8_t ff_wmv2_scantableB[64]={ +0x00, 0x08, 0x01, 0x10, 0x09, 0x18, 0x11, 0x02, +0x20, 0x0A, 0x19, 0x28, 0x12, 0x30, 0x21, 0x1A, +0x38, 0x29, 0x22, 0x03, 0x31, 0x39, 0x0B, 0x2A, +0x13, 0x32, 0x1B, 0x3A, 0x23, 0x2B, 0x33, 0x3B, +}; diff --git a/ffmpeg/libavcodec/msmpeg4data.h b/ffmpeg/libavcodec/msmpeg4data.h new file mode 100644 index 0000000..24a10d9 --- /dev/null +++ b/ffmpeg/libavcodec/msmpeg4data.h @@ -0,0 +1,90 @@ +/* + * MSMPEG4 backend for encoder and decoder + * copyright (c) 2001 Fabrice Bellard + * copyright (c) 2002-2004 Michael Niedermayer + * + * msmpeg4v1 & v2 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 + */ + +/** + * @file + * MSMPEG4 data tables. + */ + +#ifndef AVCODEC_MSMPEG4DATA_H +#define AVCODEC_MSMPEG4DATA_H + +#include "libavutil/common.h" +#include "get_bits.h" +#include "rl.h" + +/* motion vector table */ +typedef struct MVTable { + int n; + const uint16_t *table_mv_code; + const uint8_t *table_mv_bits; + const uint8_t *table_mvx; + const uint8_t *table_mvy; + uint16_t *table_mv_index; /* encoding: convert mv to index in table_mv */ + VLC vlc; /* decoding: vlc */ +} MVTable; + +extern VLC ff_msmp4_mb_i_vlc; +extern VLC ff_msmp4_dc_luma_vlc[2]; +extern VLC ff_msmp4_dc_chroma_vlc[2]; + +/* intra picture macroblock coded block pattern */ +extern const uint16_t ff_msmp4_mb_i_table[64][2]; + +#define WMV1_SCANTABLE_COUNT 4 + +extern const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64]; + +#define NB_RL_TABLES 6 + +extern RLTable ff_rl_table[NB_RL_TABLES]; +extern uint8_t ff_static_rl_table_store[NB_RL_TABLES][2][2 * MAX_RUN + MAX_LEVEL + 3]; + +extern uint32_t ff_v2_dc_lum_table[512][2]; +extern uint32_t ff_v2_dc_chroma_table[512][2]; + +extern const uint8_t ff_wmv1_y_dc_scale_table[32]; +extern const uint8_t ff_wmv1_c_dc_scale_table[32]; +extern const uint8_t ff_old_ff_y_dc_scale_table[32]; + +extern MVTable ff_mv_tables[2]; + +extern const uint8_t ff_v2_mb_type[8][2]; +extern const uint8_t ff_v2_intra_cbpc[4][2]; + +extern const uint32_t ff_table_mb_non_intra[128][2]; +extern const uint8_t ff_table_inter_intra[4][2]; + +extern const uint32_t ff_table0_dc_lum[120][2]; +extern const uint32_t ff_table1_dc_lum[120][2]; +extern const uint32_t ff_table0_dc_chroma[120][2]; +extern const uint32_t ff_table1_dc_chroma[120][2]; + +#define WMV2_INTER_CBP_TABLE_COUNT 4 +extern const uint32_t (* const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2]; + +extern const uint8_t ff_wmv2_scantableA[64]; +extern const uint8_t ff_wmv2_scantableB[64]; + +#endif /* AVCODEC_MSMPEG4DATA_H */ diff --git a/ffmpeg/libavcodec/msmpeg4enc.c b/ffmpeg/libavcodec/msmpeg4enc.c new file mode 100644 index 0000000..82e6646 --- /dev/null +++ b/ffmpeg/libavcodec/msmpeg4enc.c @@ -0,0 +1,691 @@ +/* + * MSMPEG4 encoder backend + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * msmpeg4v1 & v2 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 + */ + +/** + * @file + * MSMPEG4 encoder backend + */ + +#include +#include + +#include "libavutil/avutil.h" +#include "libavutil/mem.h" +#include "mpegvideo.h" +#include "msmpeg4.h" +#include "h263.h" +#include "mpeg4video.h" +#include "msmpeg4.h" +#include "msmpeg4data.h" +#include "put_bits.h" +#include "rl.h" +#include "vc1data.h" + +static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2]; + +/* build the table which associate a (x,y) motion vector to a vlc */ +static void init_mv_table(MVTable *tab) +{ + int i, x, y; + + tab->table_mv_index = av_malloc(sizeof(uint16_t) * 4096); + /* mark all entries as not used */ + for(i=0;i<4096;i++) + tab->table_mv_index[i] = tab->n; + + for(i=0;in;i++) { + x = tab->table_mvx[i]; + y = tab->table_mvy[i]; + tab->table_mv_index[(x << 6) | y] = i; + } +} + +void ff_msmpeg4_code012(PutBitContext *pb, int n) +{ + if (n == 0) { + put_bits(pb, 1, 0); + } else { + put_bits(pb, 1, 1); + put_bits(pb, 1, (n >= 2)); + } +} + +static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run, int level, int intra){ + int size=0; + int code; + int run_diff= intra ? 0 : 1; + + code = get_rl_index(rl, last, run, level); + size+= rl->table_vlc[code][1]; + if (code == rl->n) { + int level1, run1; + + level1 = level - rl->max_level[last][run]; + if (level1 < 1) + goto esc2; + code = get_rl_index(rl, last, run, level1); + if (code == rl->n) { + esc2: + size++; + if (level > MAX_LEVEL) + goto esc3; + run1 = run - rl->max_run[last][level] - run_diff; + if (run1 < 0) + goto esc3; + code = get_rl_index(rl, last, run1, level); + if (code == rl->n) { + esc3: + /* third escape */ + size+=1+1+6+8; + } else { + /* second escape */ + size+= 1+1+ rl->table_vlc[code][1]; + } + } else { + /* first escape */ + size+= 1+1+ rl->table_vlc[code][1]; + } + } else { + size++; + } + return size; +} + +av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) +{ + static int init_done=0; + int i; + + ff_msmpeg4_common_init(s); + if(s->msmpeg4_version>=4){ + s->min_qcoeff= -255; + s->max_qcoeff= 255; + } + + if (!init_done) { + /* init various encoding tables */ + init_done = 1; + init_mv_table(&ff_mv_tables[0]); + init_mv_table(&ff_mv_tables[1]); + for(i=0;i0){// ;) + size++; + chroma_size++; + } + for(level=0; level<=MAX_LEVEL; level++){ + int run; + for(run=0; run<=MAX_RUN; run++){ + int last; + const int last_size= size + chroma_size; + for(last=0; last<2; last++){ + int inter_count = s->ac_stats[0][0][level][run][last] + s->ac_stats[0][1][level][run][last]; + int intra_luma_count = s->ac_stats[1][0][level][run][last]; + int intra_chroma_count= s->ac_stats[1][1][level][run][last]; + + if(s->pict_type==AV_PICTURE_TYPE_I){ + size += intra_luma_count *rl_length[i ][level][run][last]; + chroma_size+= intra_chroma_count*rl_length[i+3][level][run][last]; + }else{ + size+= intra_luma_count *rl_length[i ][level][run][last] + +intra_chroma_count*rl_length[i+3][level][run][last] + +inter_count *rl_length[i+3][level][run][last]; + } + } + if(last_size == size+chroma_size) break; + } + } + if(sizepict_type==AV_PICTURE_TYPE_P) chroma_best= best; + + memset(s->ac_stats, 0, sizeof(int)*(MAX_LEVEL+1)*(MAX_RUN+1)*2*2*2); + + s->rl_table_index = best; + s->rl_chroma_table_index= chroma_best; + + if(s->pict_type != s->last_non_b_pict_type){ + s->rl_table_index= 2; + if(s->pict_type==AV_PICTURE_TYPE_I) + s->rl_chroma_table_index= 1; + else + s->rl_chroma_table_index= 2; + } + +} + +/* write MSMPEG4 compatible frame header */ +void ff_msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number) +{ + find_best_tables(s); + + avpriv_align_put_bits(&s->pb); + put_bits(&s->pb, 2, s->pict_type - 1); + + put_bits(&s->pb, 5, s->qscale); + if(s->msmpeg4_version<=2){ + s->rl_table_index = 2; + s->rl_chroma_table_index = 2; + } + + s->dc_table_index = 1; + s->mv_table_index = 1; /* only if P frame */ + s->use_skip_mb_code = 1; /* only if P frame */ + s->per_mb_rl_table = 0; + if(s->msmpeg4_version==4) + s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE && s->pict_type==AV_PICTURE_TYPE_P); + av_dlog(s, "%d %d %d %d %d\n", s->pict_type, s->bit_rate, + s->inter_intra_pred, s->width, s->height); + + if (s->pict_type == AV_PICTURE_TYPE_I) { + s->slice_height= s->mb_height/1; + put_bits(&s->pb, 5, 0x16 + s->mb_height/s->slice_height); + + if(s->msmpeg4_version==4){ + ff_msmpeg4_encode_ext_header(s); + if(s->bit_rate>MBAC_BITRATE) + put_bits(&s->pb, 1, s->per_mb_rl_table); + } + + if(s->msmpeg4_version>2){ + if(!s->per_mb_rl_table){ + ff_msmpeg4_code012(&s->pb, s->rl_chroma_table_index); + ff_msmpeg4_code012(&s->pb, s->rl_table_index); + } + + put_bits(&s->pb, 1, s->dc_table_index); + } + } else { + put_bits(&s->pb, 1, s->use_skip_mb_code); + + if(s->msmpeg4_version==4 && s->bit_rate>MBAC_BITRATE) + put_bits(&s->pb, 1, s->per_mb_rl_table); + + if(s->msmpeg4_version>2){ + if(!s->per_mb_rl_table) + ff_msmpeg4_code012(&s->pb, s->rl_table_index); + + put_bits(&s->pb, 1, s->dc_table_index); + + put_bits(&s->pb, 1, s->mv_table_index); + } + } + + s->esc3_level_length= 0; + s->esc3_run_length= 0; +} + +void ff_msmpeg4_encode_ext_header(MpegEncContext * s) +{ + unsigned fps = s->avctx->time_base.den / s->avctx->time_base.num / FFMAX(s->avctx->ticks_per_frame, 1); + put_bits(&s->pb, 5, FFMIN(fps, 31)); //yes 29.97 -> 29 + + put_bits(&s->pb, 11, FFMIN(s->bit_rate/1024, 2047)); + + if(s->msmpeg4_version>=3) + put_bits(&s->pb, 1, s->flipflop_rounding); + else + av_assert0(s->flipflop_rounding==0); +} + +void ff_msmpeg4_encode_motion(MpegEncContext * s, + int mx, int my) +{ + int code; + MVTable *mv; + + /* modulo encoding */ + /* WARNING : you cannot reach all the MVs even with the modulo + encoding. This is a somewhat strange compromise they took !!! */ + if (mx <= -64) + mx += 64; + else if (mx >= 64) + mx -= 64; + if (my <= -64) + my += 64; + else if (my >= 64) + my -= 64; + + mx += 32; + my += 32; +#if 0 + if ((unsigned)mx >= 64 || + (unsigned)my >= 64) + av_log(s->avctx, AV_LOG_ERROR, "error mx=%d my=%d\n", mx, my); +#endif + mv = &ff_mv_tables[s->mv_table_index]; + + code = mv->table_mv_index[(mx << 6) | my]; + put_bits(&s->pb, + mv->table_mv_bits[code], + mv->table_mv_code[code]); + if (code == mv->n) { + /* escape : code literally */ + put_bits(&s->pb, 6, mx); + put_bits(&s->pb, 6, my); + } +} + +void ff_msmpeg4_handle_slices(MpegEncContext *s){ + if (s->mb_x == 0) { + if (s->slice_height && (s->mb_y % s->slice_height) == 0) { + if(s->msmpeg4_version < 4){ + ff_mpeg4_clean_buffers(s); + } + s->first_slice_line = 1; + } else { + s->first_slice_line = 0; + } + } +} + +static void msmpeg4v2_encode_motion(MpegEncContext * s, int val) +{ + int range, bit_size, sign, code, bits; + + if (val == 0) { + /* zero vector */ + code = 0; + put_bits(&s->pb, ff_mvtab[code][1], ff_mvtab[code][0]); + } else { + bit_size = s->f_code - 1; + range = 1 << bit_size; + if (val <= -64) + val += 64; + else if (val >= 64) + val -= 64; + + if (val >= 0) { + sign = 0; + } else { + val = -val; + sign = 1; + } + val--; + code = (val >> bit_size) + 1; + bits = val & (range - 1); + + put_bits(&s->pb, ff_mvtab[code][1] + 1, (ff_mvtab[code][0] << 1) | sign); + if (bit_size > 0) { + put_bits(&s->pb, bit_size, bits); + } + } +} + +void ff_msmpeg4_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y) +{ + int cbp, coded_cbp, i; + int pred_x, pred_y; + uint8_t *coded_block; + + ff_msmpeg4_handle_slices(s); + + if (!s->mb_intra) { + /* compute cbp */ + cbp = 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + if (s->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) { + /* skip macroblock */ + put_bits(&s->pb, 1, 1); + s->last_bits++; + s->misc_bits++; + s->skip_count++; + + return; + } + if (s->use_skip_mb_code) + put_bits(&s->pb, 1, 0); /* mb coded */ + + if(s->msmpeg4_version<=2){ + put_bits(&s->pb, + ff_v2_mb_type[cbp&3][1], + ff_v2_mb_type[cbp&3][0]); + if((cbp&3) != 3) coded_cbp= cbp ^ 0x3C; + else coded_cbp= cbp; + + put_bits(&s->pb, + ff_h263_cbpy_tab[coded_cbp>>2][1], + ff_h263_cbpy_tab[coded_cbp>>2][0]); + + s->misc_bits += get_bits_diff(s); + + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + msmpeg4v2_encode_motion(s, motion_x - pred_x); + msmpeg4v2_encode_motion(s, motion_y - pred_y); + }else{ + put_bits(&s->pb, + ff_table_mb_non_intra[cbp + 64][1], + ff_table_mb_non_intra[cbp + 64][0]); + + s->misc_bits += get_bits_diff(s); + + /* motion vector */ + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + ff_msmpeg4_encode_motion(s, motion_x - pred_x, + motion_y - pred_y); + } + + s->mv_bits += get_bits_diff(s); + + for (i = 0; i < 6; i++) { + ff_msmpeg4_encode_block(s, block[i], i); + } + s->p_tex_bits += get_bits_diff(s); + } else { + /* compute cbp */ + cbp = 0; + coded_cbp = 0; + for (i = 0; i < 6; i++) { + int val, pred; + val = (s->block_last_index[i] >= 1); + cbp |= val << (5 - i); + if (i < 4) { + /* predict value for close blocks only for luma */ + pred = ff_msmpeg4_coded_block_pred(s, i, &coded_block); + *coded_block = val; + val = val ^ pred; + } + coded_cbp |= val << (5 - i); + } + + if(s->msmpeg4_version<=2){ + if (s->pict_type == AV_PICTURE_TYPE_I) { + put_bits(&s->pb, + ff_v2_intra_cbpc[cbp&3][1], ff_v2_intra_cbpc[cbp&3][0]); + } else { + if (s->use_skip_mb_code) + put_bits(&s->pb, 1, 0); /* mb coded */ + put_bits(&s->pb, + ff_v2_mb_type[(cbp&3) + 4][1], + ff_v2_mb_type[(cbp&3) + 4][0]); + } + put_bits(&s->pb, 1, 0); /* no AC prediction yet */ + put_bits(&s->pb, + ff_h263_cbpy_tab[cbp>>2][1], + ff_h263_cbpy_tab[cbp>>2][0]); + }else{ + if (s->pict_type == AV_PICTURE_TYPE_I) { + put_bits(&s->pb, + ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[coded_cbp][0]); + } else { + if (s->use_skip_mb_code) + put_bits(&s->pb, 1, 0); /* mb coded */ + put_bits(&s->pb, + ff_table_mb_non_intra[cbp][1], + ff_table_mb_non_intra[cbp][0]); + } + put_bits(&s->pb, 1, 0); /* no AC prediction yet */ + if(s->inter_intra_pred){ + s->h263_aic_dir=0; + put_bits(&s->pb, ff_table_inter_intra[s->h263_aic_dir][1], ff_table_inter_intra[s->h263_aic_dir][0]); + } + } + s->misc_bits += get_bits_diff(s); + + for (i = 0; i < 6; i++) { + ff_msmpeg4_encode_block(s, block[i], i); + } + s->i_tex_bits += get_bits_diff(s); + s->i_count++; + } +} + +static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr) +{ + int sign, code; + int pred, av_uninit(extquant); + int extrabits = 0; + + int16_t *dc_val; + pred = ff_msmpeg4_pred_dc(s, n, &dc_val, dir_ptr); + + /* update predictor */ + if (n < 4) { + *dc_val = level * s->y_dc_scale; + } else { + *dc_val = level * s->c_dc_scale; + } + + /* do the prediction */ + level -= pred; + + if(s->msmpeg4_version<=2){ + if (n < 4) { + put_bits(&s->pb, + ff_v2_dc_lum_table[level + 256][1], + ff_v2_dc_lum_table[level + 256][0]); + }else{ + put_bits(&s->pb, + ff_v2_dc_chroma_table[level + 256][1], + ff_v2_dc_chroma_table[level + 256][0]); + } + }else{ + sign = 0; + if (level < 0) { + level = -level; + sign = 1; + } + code = level; + if (code > DC_MAX) + code = DC_MAX; + else if( s->msmpeg4_version>=6 ) { + if( s->qscale == 1 ) { + extquant = (level + 3) & 0x3; + code = ((level+3)>>2); + } else if( s->qscale == 2 ) { + extquant = (level + 1) & 0x1; + code = ((level+1)>>1); + } + } + + if (s->dc_table_index == 0) { + if (n < 4) { + put_bits(&s->pb, ff_table0_dc_lum[code][1], ff_table0_dc_lum[code][0]); + } else { + put_bits(&s->pb, ff_table0_dc_chroma[code][1], ff_table0_dc_chroma[code][0]); + } + } else { + if (n < 4) { + put_bits(&s->pb, ff_table1_dc_lum[code][1], ff_table1_dc_lum[code][0]); + } else { + put_bits(&s->pb, ff_table1_dc_chroma[code][1], ff_table1_dc_chroma[code][0]); + } + } + + if(s->msmpeg4_version>=6 && s->qscale<=2) + extrabits = 3 - s->qscale; + + if (code == DC_MAX) + put_bits(&s->pb, 8 + extrabits, level); + else if(extrabits > 0)//== VC1 && s->qscale<=2 + put_bits(&s->pb, extrabits, extquant); + + if (level != 0) { + put_bits(&s->pb, 1, sign); + } + } +} + +/* Encoding of a block. Very similar to MPEG4 except for a different + escape coding (same as H263) and more vlc tables. + */ +void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) +{ + int level, run, last, i, j, last_index; + int last_non_zero, sign, slevel; + int code, run_diff, dc_pred_dir; + const RLTable *rl; + const uint8_t *scantable; + + if (s->mb_intra) { + msmpeg4_encode_dc(s, block[0], n, &dc_pred_dir); + i = 1; + if (n < 4) { + rl = &ff_rl_table[s->rl_table_index]; + } else { + rl = &ff_rl_table[3 + s->rl_chroma_table_index]; + } + run_diff = s->msmpeg4_version>=4; + scantable= s->intra_scantable.permutated; + } else { + i = 0; + rl = &ff_rl_table[3 + s->rl_table_index]; + if(s->msmpeg4_version<=2) + run_diff = 0; + else + run_diff = 1; + scantable= s->inter_scantable.permutated; + } + + /* recalculate block_last_index for M$ wmv1 */ + if(s->msmpeg4_version>=4 && s->msmpeg4_version<6 && s->block_last_index[n]>0){ + for(last_index=63; last_index>=0; last_index--){ + if(block[scantable[last_index]]) break; + } + s->block_last_index[n]= last_index; + }else + last_index = s->block_last_index[n]; + /* AC coefs */ + last_non_zero = i - 1; + for (; i <= last_index; i++) { + j = scantable[i]; + level = block[j]; + if (level) { + run = i - last_non_zero - 1; + last = (i == last_index); + sign = 0; + slevel = level; + if (level < 0) { + sign = 1; + level = -level; + } + + if(level<=MAX_LEVEL && run<=MAX_RUN){ + s->ac_stats[s->mb_intra][n>3][level][run][last]++; + } + + s->ac_stats[s->mb_intra][n > 3][40][63][0]++; //esc3 like + + code = get_rl_index(rl, last, run, level); + put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); + if (code == rl->n) { + int level1, run1; + + level1 = level - rl->max_level[last][run]; + if (level1 < 1) + goto esc2; + code = get_rl_index(rl, last, run, level1); + if (code == rl->n) { + esc2: + put_bits(&s->pb, 1, 0); + if (level > MAX_LEVEL) + goto esc3; + run1 = run - rl->max_run[last][level] - run_diff; + if (run1 < 0) + goto esc3; + code = get_rl_index(rl, last, run1+1, level); + if (s->msmpeg4_version == 4 && code == rl->n) + goto esc3; + code = get_rl_index(rl, last, run1, level); + if (code == rl->n) { + esc3: + /* third escape */ + put_bits(&s->pb, 1, 0); + put_bits(&s->pb, 1, last); + if(s->msmpeg4_version>=4){ + if(s->esc3_level_length==0){ + s->esc3_level_length=8; + s->esc3_run_length= 6; + //ESCLVLSZ + ESCRUNSZ + if(s->qscale<8) + put_bits(&s->pb, 6 + (s->msmpeg4_version>=6), 3); + else + put_bits(&s->pb, 8, 3); + } + put_bits(&s->pb, s->esc3_run_length, run); + put_bits(&s->pb, 1, sign); + put_bits(&s->pb, s->esc3_level_length, level); + }else{ + put_bits(&s->pb, 6, run); + put_sbits(&s->pb, 8, slevel); + } + } else { + /* second escape */ + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); + put_bits(&s->pb, 1, sign); + } + } else { + /* first escape */ + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); + put_bits(&s->pb, 1, sign); + } + } else { + put_bits(&s->pb, 1, sign); + } + last_non_zero = i; + } + } +} diff --git a/ffmpeg/libavcodec/msrle.c b/ffmpeg/libavcodec/msrle.c new file mode 100644 index 0000000..674e586 --- /dev/null +++ b/ffmpeg/libavcodec/msrle.c @@ -0,0 +1,164 @@ +/* + * Microsoft RLE video decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * MS RLE video decoder by Mike Melanson (melanson@pcisys.net) + * For more information about the MS RLE format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * The MS RLE decoder outputs PAL8 colorspace data. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "msrledec.h" + +typedef struct MsrleContext { + AVCodecContext *avctx; + AVFrame frame; + + GetByteContext gb; + const unsigned char *buf; + int size; + + uint32_t pal[256]; +} MsrleContext; + +static av_cold int msrle_decode_init(AVCodecContext *avctx) +{ + MsrleContext *s = avctx->priv_data; + int i; + + s->avctx = avctx; + + switch (avctx->bits_per_coded_sample) { + case 1: + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + break; + case 4: + case 8: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + default: + av_log(avctx, AV_LOG_ERROR, "unsupported bits per sample\n"); + return AVERROR_INVALIDDATA; + } + + avcodec_get_frame_defaults(&s->frame); + + if (avctx->extradata_size >= 4) + for (i = 0; i < FFMIN(avctx->extradata_size, AVPALETTE_SIZE)/4; i++) + s->pal[i] = 0xFFU<<24 | AV_RL32(avctx->extradata+4*i); + + return 0; +} + +static int msrle_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MsrleContext *s = avctx->priv_data; + int istride = FFALIGN(avctx->width*avctx->bits_per_coded_sample, 32) / 8; + int ret; + + s->buf = buf; + s->size = buf_size; + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + if (avctx->bits_per_coded_sample > 1 && avctx->bits_per_coded_sample <= 8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { + s->frame.palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + /* make the palette available */ + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); + } + + /* FIXME how to correctly detect RLE ??? */ + if (avctx->height * istride == avpkt->size) { /* assume uncompressed */ + int linesize = (avctx->width * avctx->bits_per_coded_sample + 7) / 8; + uint8_t *ptr = s->frame.data[0]; + uint8_t *buf = avpkt->data + (avctx->height-1)*istride; + int i, j; + + for (i = 0; i < avctx->height; i++) { + if (avctx->bits_per_coded_sample == 4) { + for (j = 0; j < avctx->width - 1; j += 2) { + ptr[j+0] = buf[j>>1] >> 4; + ptr[j+1] = buf[j>>1] & 0xF; + } + if (avctx->width & 1) + ptr[j+0] = buf[j>>1] >> 4; + } else { + memcpy(ptr, buf, linesize); + } + buf -= istride; + ptr += s->frame.linesize[0]; + } + } else { + bytestream2_init(&s->gb, buf, buf_size); + ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, &s->gb); + } + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int msrle_decode_end(AVCodecContext *avctx) +{ + MsrleContext *s = avctx->priv_data; + + /* release the last frame */ + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_msrle_decoder = { + .name = "msrle", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSRLE, + .priv_data_size = sizeof(MsrleContext), + .init = msrle_decode_init, + .close = msrle_decode_end, + .decode = msrle_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Microsoft RLE"), +}; diff --git a/ffmpeg/libavcodec/msrledec.c b/ffmpeg/libavcodec/msrledec.c new file mode 100644 index 0000000..83d7d13 --- /dev/null +++ b/ffmpeg/libavcodec/msrledec.c @@ -0,0 +1,266 @@ +/* + * Microsoft RLE decoder + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * MS RLE decoder based on decoder by Mike Melanson and my own for TSCC + * For more information about the MS RLE format, visit: + * http://www.multimedia.cx/msrle.txt + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "msrledec.h" + +static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic, + GetByteContext *gb) +{ + unsigned char rle_code; + unsigned char extra_byte, odd_pixel; + unsigned char stream_byte; + unsigned int pixel_ptr = 0; + int row_dec = pic->linesize[0]; + int row_ptr = (avctx->height - 1) * row_dec; + int frame_size = row_dec * avctx->height; + int i; + + while (row_ptr >= 0) { + if (bytestream2_get_bytes_left(gb) <= 0) { + av_log(avctx, AV_LOG_ERROR, + "MS RLE: bytestream overrun, %d rows left\n", + row_ptr); + return AVERROR_INVALIDDATA; + } + rle_code = stream_byte = bytestream2_get_byteu(gb); + if (rle_code == 0) { + /* fetch the next byte to see how to handle escape code */ + stream_byte = bytestream2_get_byte(gb); + if (stream_byte == 0) { + /* line is done, goto the next one */ + row_ptr -= row_dec; + pixel_ptr = 0; + } else if (stream_byte == 1) { + /* decode is done */ + return 0; + } else if (stream_byte == 2) { + /* reposition frame decode coordinates */ + stream_byte = bytestream2_get_byte(gb); + pixel_ptr += stream_byte; + stream_byte = bytestream2_get_byte(gb); + row_ptr -= stream_byte * row_dec; + } else { + // copy pixels from encoded stream + odd_pixel = stream_byte & 1; + rle_code = (stream_byte + 1) / 2; + extra_byte = rle_code & 0x01; + if (row_ptr + pixel_ptr + stream_byte > frame_size || + bytestream2_get_bytes_left(gb) < rle_code) { + av_log(avctx, AV_LOG_ERROR, + "MS RLE: frame/stream ptr just went out of bounds (copy)\n"); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < rle_code; i++) { + if (pixel_ptr >= avctx->width) + break; + stream_byte = bytestream2_get_byteu(gb); + pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4; + pixel_ptr++; + if (i + 1 == rle_code && odd_pixel) + break; + if (pixel_ptr >= avctx->width) + break; + pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F; + pixel_ptr++; + } + + // if the RLE code is odd, skip a byte in the stream + if (extra_byte) + bytestream2_skip(gb, 1); + } + } else { + // decode a run of data + if (row_ptr + pixel_ptr + stream_byte > frame_size) { + av_log(avctx, AV_LOG_ERROR, + "MS RLE: frame ptr just went out of bounds (run)\n"); + return AVERROR_INVALIDDATA; + } + stream_byte = bytestream2_get_byte(gb); + for (i = 0; i < rle_code; i++) { + if (pixel_ptr >= avctx->width) + break; + if ((i & 1) == 0) + pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4; + else + pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F; + pixel_ptr++; + } + } + } + + /* one last sanity check on the way out */ + if (bytestream2_get_bytes_left(gb)) { + av_log(avctx, AV_LOG_ERROR, + "MS RLE: ended frame decode with %d bytes left over\n", + bytestream2_get_bytes_left(gb)); + return AVERROR_INVALIDDATA; + } + + return 0; +} + + +static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, + int depth, GetByteContext *gb) +{ + uint8_t *output, *output_end; + int p1, p2, line=avctx->height - 1, pos=0, i; + uint16_t pix16; + uint32_t pix32; + unsigned int width= FFABS(pic->linesize[0]) / (depth >> 3); + + output = pic->data[0] + (avctx->height - 1) * pic->linesize[0]; + output_end = output + FFABS(pic->linesize[0]); + + while (bytestream2_get_bytes_left(gb) > 0) { + p1 = bytestream2_get_byteu(gb); + if(p1 == 0) { //Escape code + p2 = bytestream2_get_byte(gb); + if(p2 == 0) { //End-of-line + if (--line < 0) { + if (bytestream2_get_be16(gb) == 1) { // end-of-picture + return 0; + } else { + av_log(avctx, AV_LOG_ERROR, + "Next line is beyond picture bounds (%d bytes left)\n", + bytestream2_get_bytes_left(gb)); + return AVERROR_INVALIDDATA; + } + } + output = pic->data[0] + line * pic->linesize[0]; + output_end = output + FFABS(pic->linesize[0]); + pos = 0; + continue; + } else if(p2 == 1) { //End-of-picture + return 0; + } else if(p2 == 2) { //Skip + p1 = bytestream2_get_byte(gb); + p2 = bytestream2_get_byte(gb); + line -= p2; + pos += p1; + if (line < 0 || pos >= width){ + av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n"); + return -1; + } + output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3); + output_end = pic->data[0] + line * pic->linesize[0] + FFABS(pic->linesize[0]); + continue; + } + // Copy data + if (output + p2 * (depth >> 3) > output_end) { + bytestream2_skip(gb, 2 * (depth >> 3)); + continue; + } else if (bytestream2_get_bytes_left(gb) < p2 * (depth >> 3)) { + av_log(avctx, AV_LOG_ERROR, "bytestream overrun\n"); + return AVERROR_INVALIDDATA; + } + + if ((depth == 8) || (depth == 24)) { + for(i = 0; i < p2 * (depth >> 3); i++) { + *output++ = bytestream2_get_byteu(gb); + } + // RLE8 copy is actually padded - and runs are not! + if(depth == 8 && (p2 & 1)) { + bytestream2_skip(gb, 1); + } + } else if (depth == 16) { + for(i = 0; i < p2; i++) { + *(uint16_t*)output = bytestream2_get_le16u(gb); + output += 2; + } + } else if (depth == 32) { + for(i = 0; i < p2; i++) { + *(uint32_t*)output = bytestream2_get_le32u(gb); + output += 4; + } + } + pos += p2; + } else { //run of pixels + uint8_t pix[3]; //original pixel + if (output + p1 * (depth >> 3) > output_end) + continue; + + switch(depth){ + case 8: + pix[0] = bytestream2_get_byte(gb); + for(i = 0; i < p1; i++) + *output++ = pix[0]; + break; + case 16: + pix16 = bytestream2_get_le16(gb); + for(i = 0; i < p1; i++) { + *(uint16_t*)output = pix16; + output += 2; + } + break; + case 24: + pix[0] = bytestream2_get_byte(gb); + pix[1] = bytestream2_get_byte(gb); + pix[2] = bytestream2_get_byte(gb); + for(i = 0; i < p1; i++) { + *output++ = pix[0]; + *output++ = pix[1]; + *output++ = pix[2]; + } + break; + case 32: + pix32 = bytestream2_get_le32(gb); + for(i = 0; i < p1; i++) { + *(uint32_t*)output = pix32; + output += 4; + } + break; + } + pos += p1; + } + } + + av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no end-of-picture code\n"); + return 0; +} + + +int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, + int depth, GetByteContext *gb) +{ + switch(depth){ + case 4: + return msrle_decode_pal4(avctx, pic, gb); + case 8: + case 16: + case 24: + case 32: + return msrle_decode_8_16_24_32(avctx, pic, depth, gb); + default: + av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth); + return -1; + } +} diff --git a/ffmpeg/libavcodec/msrledec.h b/ffmpeg/libavcodec/msrledec.h new file mode 100644 index 0000000..3f66636 --- /dev/null +++ b/ffmpeg/libavcodec/msrledec.h @@ -0,0 +1,39 @@ +/* + * Microsoft RLE decoder + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_MSRLEDEC_H +#define AVCODEC_MSRLEDEC_H + +#include "avcodec.h" +#include "bytestream.h" + +/** + * Decode stream in MS RLE format into frame. + * + * @param avctx codec context + * @param pic destination frame + * @param depth bit depth + * @param gb input bytestream context + */ +int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic, + int depth, GetByteContext *gb); + +#endif /* AVCODEC_MSRLEDEC_H */ diff --git a/ffmpeg/libavcodec/mss1.c b/ffmpeg/libavcodec/mss1.c new file mode 100644 index 0000000..bb1858d --- /dev/null +++ b/ffmpeg/libavcodec/mss1.c @@ -0,0 +1,224 @@ +/* + * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Microsoft Screen 1 (aka Windows Media Video V7 Screen) decoder + */ + +#include "avcodec.h" +#include "internal.h" +#include "mss12.h" + +typedef struct MSS1Context { + MSS12Context ctx; + AVFrame pic; + SliceContext sc; +} MSS1Context; + +static void arith_normalise(ArithCoder *c) +{ + for (;;) { + if (c->high >= 0x8000) { + if (c->low < 0x8000) { + if (c->low >= 0x4000 && c->high < 0xC000) { + c->value -= 0x4000; + c->low -= 0x4000; + c->high -= 0x4000; + } else { + return; + } + } else { + c->value -= 0x8000; + c->low -= 0x8000; + c->high -= 0x8000; + } + } + c->value <<= 1; + c->low <<= 1; + c->high <<= 1; + c->high |= 1; + c->value |= get_bits1(c->gbc.gb); + } +} + +ARITH_GET_BIT() + +static int arith_get_bits(ArithCoder *c, int bits) +{ + int range = c->high - c->low + 1; + int val = (((c->value - c->low + 1) << bits) - 1) / range; + int prob = range * val; + + c->high = ((prob + range) >> bits) + c->low - 1; + c->low += prob >> bits; + + arith_normalise(c); + + return val; +} + +static int arith_get_number(ArithCoder *c, int mod_val) +{ + int range = c->high - c->low + 1; + int val = ((c->value - c->low + 1) * mod_val - 1) / range; + int prob = range * val; + + c->high = (prob + range) / mod_val + c->low - 1; + c->low += prob / mod_val; + + arith_normalise(c); + + return val; +} + +static int arith_get_prob(ArithCoder *c, int16_t *probs) +{ + int range = c->high - c->low + 1; + int val = ((c->value - c->low + 1) * probs[0] - 1) / range; + int sym = 1; + + while (probs[sym] > val) + sym++; + + c->high = range * probs[sym - 1] / probs[0] + c->low - 1; + c->low += range * probs[sym] / probs[0]; + + return sym; +} + +ARITH_GET_MODEL_SYM() + +static void arith_init(ArithCoder *c, GetBitContext *gb) +{ + c->low = 0; + c->high = 0xFFFF; + c->value = get_bits(gb, 16); + c->gbc.gb = gb; + c->get_model_sym = arith_get_model_sym; + c->get_number = arith_get_number; +} + +static int decode_pal(MSS12Context *ctx, ArithCoder *acoder) +{ + int i, ncol, r, g, b; + uint32_t *pal = ctx->pal + 256 - ctx->free_colours; + + if (!ctx->free_colours) + return 0; + + ncol = arith_get_number(acoder, ctx->free_colours + 1); + for (i = 0; i < ncol; i++) { + r = arith_get_bits(acoder, 8); + g = arith_get_bits(acoder, 8); + b = arith_get_bits(acoder, 8); + *pal++ = (0xFFU << 24) | (r << 16) | (g << 8) | b; + } + + return !!ncol; +} + +static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MSS1Context *ctx = avctx->priv_data; + MSS12Context *c = &ctx->ctx; + GetBitContext gb; + ArithCoder acoder; + int pal_changed = 0; + int ret; + + init_get_bits(&gb, buf, buf_size * 8); + arith_init(&acoder, &gb); + + if ((ret = ff_reget_buffer(avctx, &ctx->pic)) < 0) + return ret; + + c->pal_pic = ctx->pic.data[0] + ctx->pic.linesize[0] * (avctx->height - 1); + c->pal_stride = -ctx->pic.linesize[0]; + c->keyframe = !arith_get_bit(&acoder); + if (c->keyframe) { + c->corrupted = 0; + ff_mss12_slicecontext_reset(&ctx->sc); + pal_changed = decode_pal(c, &acoder); + ctx->pic.key_frame = 1; + ctx->pic.pict_type = AV_PICTURE_TYPE_I; + } else { + if (c->corrupted) + return AVERROR_INVALIDDATA; + ctx->pic.key_frame = 0; + ctx->pic.pict_type = AV_PICTURE_TYPE_P; + } + c->corrupted = ff_mss12_decode_rect(&ctx->sc, &acoder, 0, 0, + avctx->width, avctx->height); + if (c->corrupted) + return AVERROR_INVALIDDATA; + memcpy(ctx->pic.data[1], c->pal, AVPALETTE_SIZE); + ctx->pic.palette_has_changed = pal_changed; + + if ((ret = av_frame_ref(data, &ctx->pic)) < 0) + return ret; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int mss1_decode_init(AVCodecContext *avctx) +{ + MSS1Context * const c = avctx->priv_data; + int ret; + + c->ctx.avctx = avctx; + + avcodec_get_frame_defaults(&c->pic); + + ret = ff_mss12_decode_init(&c->ctx, 0, &c->sc, NULL); + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + return ret; +} + +static av_cold int mss1_decode_end(AVCodecContext *avctx) +{ + MSS1Context * const ctx = avctx->priv_data; + + av_frame_unref(&ctx->pic); + ff_mss12_decode_end(&ctx->ctx); + + return 0; +} + +AVCodec ff_mss1_decoder = { + .name = "mss1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSS1, + .priv_data_size = sizeof(MSS1Context), + .init = mss1_decode_init, + .close = mss1_decode_end, + .decode = mss1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), +}; diff --git a/ffmpeg/libavcodec/mss12.c b/ffmpeg/libavcodec/mss12.c new file mode 100644 index 0000000..b522e4a --- /dev/null +++ b/ffmpeg/libavcodec/mss12.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Common functions for Microsoft Screen 1 and 2 + */ + +#include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "mss12.h" + +enum SplitMode { + SPLIT_VERT = 0, + SPLIT_HOR, + SPLIT_NONE +}; + +static const int sec_order_sizes[4] = { 1, 7, 6, 1 }; + +enum ContextDirection { + TOP_LEFT = 0, + TOP, + TOP_RIGHT, + LEFT +}; + +static int model_calc_threshold(Model *m) +{ + int thr; + + thr = 2 * m->weights[m->num_syms] - 1; + thr = ((thr >> 1) + 4 * m->cum_prob[0]) / thr; + + return FFMIN(thr, 0x3FFF); +} + +static void model_reset(Model *m) +{ + int i; + + for (i = 0; i <= m->num_syms; i++) { + m->weights[i] = 1; + m->cum_prob[i] = m->num_syms - i; + } + m->weights[0] = 0; + for (i = 0; i < m->num_syms; i++) + m->idx2sym[i + 1] = i; +} + +static av_cold void model_init(Model *m, int num_syms, int thr_weight) +{ + m->num_syms = num_syms; + m->thr_weight = thr_weight; + m->threshold = num_syms * thr_weight; +} + +static void model_rescale_weights(Model *m) +{ + int i; + int cum_prob; + + if (m->thr_weight == THRESH_ADAPTIVE) + m->threshold = model_calc_threshold(m); + while (m->cum_prob[0] > m->threshold) { + cum_prob = 0; + for (i = m->num_syms; i >= 0; i--) { + m->cum_prob[i] = cum_prob; + m->weights[i] = (m->weights[i] + 1) >> 1; + cum_prob += m->weights[i]; + } + } +} + +void ff_mss12_model_update(Model *m, int val) +{ + int i; + + if (m->weights[val] == m->weights[val - 1]) { + for (i = val; m->weights[i - 1] == m->weights[val]; i--); + if (i != val) { + int sym1, sym2; + + sym1 = m->idx2sym[val]; + sym2 = m->idx2sym[i]; + + m->idx2sym[val] = sym2; + m->idx2sym[i] = sym1; + + val = i; + } + } + m->weights[val]++; + for (i = val - 1; i >= 0; i--) + m->cum_prob[i]++; + model_rescale_weights(m); +} + +static void pixctx_reset(PixContext *ctx) +{ + int i, j; + + if (!ctx->special_initial_cache) + for (i = 0; i < ctx->cache_size; i++) + ctx->cache[i] = i; + else { + ctx->cache[0] = 1; + ctx->cache[1] = 2; + ctx->cache[2] = 4; + } + + model_reset(&ctx->cache_model); + model_reset(&ctx->full_model); + + for (i = 0; i < 15; i++) + for (j = 0; j < 4; j++) + model_reset(&ctx->sec_models[i][j]); +} + +static av_cold void pixctx_init(PixContext *ctx, int cache_size, + int full_model_syms, int special_initial_cache) +{ + int i, j, k, idx; + + ctx->cache_size = cache_size + 4; + ctx->num_syms = cache_size; + ctx->special_initial_cache = special_initial_cache; + + model_init(&ctx->cache_model, ctx->num_syms + 1, THRESH_LOW); + model_init(&ctx->full_model, full_model_syms, THRESH_HIGH); + + for (i = 0, idx = 0; i < 4; i++) + for (j = 0; j < sec_order_sizes[i]; j++, idx++) + for (k = 0; k < 4; k++) + model_init(&ctx->sec_models[idx][k], 2 + i, + i ? THRESH_LOW : THRESH_ADAPTIVE); +} + +static av_always_inline int decode_pixel(ArithCoder *acoder, PixContext *pctx, + uint8_t *ngb, int num_ngb, int any_ngb) +{ + int i, val, pix; + + val = acoder->get_model_sym(acoder, &pctx->cache_model); + if (val < pctx->num_syms) { + if (any_ngb) { + int idx, j; + + idx = 0; + for (i = 0; i < pctx->cache_size; i++) { + for (j = 0; j < num_ngb; j++) + if (pctx->cache[i] == ngb[j]) + break; + if (j == num_ngb) { + if (idx == val) + break; + idx++; + } + } + val = FFMIN(i, pctx->cache_size - 1); + } + pix = pctx->cache[val]; + } else { + pix = acoder->get_model_sym(acoder, &pctx->full_model); + for (i = 0; i < pctx->cache_size - 1; i++) + if (pctx->cache[i] == pix) + break; + val = i; + } + if (val) { + for (i = val; i > 0; i--) + pctx->cache[i] = pctx->cache[i - 1]; + pctx->cache[0] = pix; + } + + return pix; +} + +static int decode_pixel_in_context(ArithCoder *acoder, PixContext *pctx, + uint8_t *src, int stride, int x, int y, + int has_right) +{ + uint8_t neighbours[4]; + uint8_t ref_pix[4]; + int nlen; + int layer = 0, sub; + int pix; + int i, j; + + if (!y) { + memset(neighbours, src[-1], 4); + } else { + neighbours[TOP] = src[-stride]; + if (!x) { + neighbours[TOP_LEFT] = neighbours[LEFT] = neighbours[TOP]; + } else { + neighbours[TOP_LEFT] = src[-stride - 1]; + neighbours[ LEFT] = src[-1]; + } + if (has_right) + neighbours[TOP_RIGHT] = src[-stride + 1]; + else + neighbours[TOP_RIGHT] = neighbours[TOP]; + } + + sub = 0; + if (x >= 2 && src[-2] == neighbours[LEFT]) + sub = 1; + if (y >= 2 && src[-2 * stride] == neighbours[TOP]) + sub |= 2; + + nlen = 1; + ref_pix[0] = neighbours[0]; + for (i = 1; i < 4; i++) { + for (j = 0; j < nlen; j++) + if (ref_pix[j] == neighbours[i]) + break; + if (j == nlen) + ref_pix[nlen++] = neighbours[i]; + } + + switch (nlen) { + case 1: + layer = 0; + break; + case 2: + if (neighbours[TOP] == neighbours[TOP_LEFT]) { + if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) + layer = 1; + else if (neighbours[LEFT] == neighbours[TOP_LEFT]) + layer = 2; + else + layer = 3; + } else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) { + if (neighbours[LEFT] == neighbours[TOP_LEFT]) + layer = 4; + else + layer = 5; + } else if (neighbours[LEFT] == neighbours[TOP_LEFT]) { + layer = 6; + } else { + layer = 7; + } + break; + case 3: + if (neighbours[TOP] == neighbours[TOP_LEFT]) + layer = 8; + else if (neighbours[TOP_RIGHT] == neighbours[TOP_LEFT]) + layer = 9; + else if (neighbours[LEFT] == neighbours[TOP_LEFT]) + layer = 10; + else if (neighbours[TOP_RIGHT] == neighbours[TOP]) + layer = 11; + else if (neighbours[TOP] == neighbours[LEFT]) + layer = 12; + else + layer = 13; + break; + case 4: + layer = 14; + break; + } + + pix = acoder->get_model_sym(acoder, + &pctx->sec_models[layer][sub]); + if (pix < nlen) + return ref_pix[pix]; + else + return decode_pixel(acoder, pctx, ref_pix, nlen, 1); +} + +static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_pic, + int x, int y, int width, int height, int stride, + int rgb_stride, PixContext *pctx, const uint32_t *pal) +{ + int i, j, p; + uint8_t *rgb_dst = rgb_pic + x * 3 + y * rgb_stride; + + dst += x + y * stride; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + if (!i && !j) + p = decode_pixel(acoder, pctx, NULL, 0, 0); + else + p = decode_pixel_in_context(acoder, pctx, dst + i, stride, + i, j, width - i - 1); + dst[i] = p; + + if (rgb_pic) + AV_WB24(rgb_dst + i * 3, pal[p]); + } + dst += stride; + rgb_dst += rgb_stride; + } + + return 0; +} + +static void copy_rectangles(MSS12Context const *c, + int x, int y, int width, int height) +{ + int j; + + if (c->last_rgb_pic) + for (j = y; j < y + height; j++) { + memcpy(c->rgb_pic + j * c->rgb_stride + x * 3, + c->last_rgb_pic + j * c->rgb_stride + x * 3, + width * 3); + memcpy(c->pal_pic + j * c->pal_stride + x, + c->last_pal_pic + j * c->pal_stride + x, + width); + } +} + +static int motion_compensation(MSS12Context const *c, + int x, int y, int width, int height) +{ + if (x + c->mvX < 0 || x + c->mvX + width > c->avctx->width || + y + c->mvY < 0 || y + c->mvY + height > c->avctx->height || + !c->rgb_pic) + return -1; + else { + uint8_t *dst = c->pal_pic + x + y * c->pal_stride; + uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride; + uint8_t *src; + uint8_t *rgb_src; + int j; + x += c->mvX; + y += c->mvY; + if (c->last_rgb_pic) { + src = c->last_pal_pic + x + y * c->pal_stride; + rgb_src = c->last_rgb_pic + x * 3 + y * c->rgb_stride; + } else { + src = c->pal_pic + x + y * c->pal_stride; + rgb_src = c->rgb_pic + x * 3 + y * c->rgb_stride; + } + for (j = 0; j < height; j++) { + memmove(dst, src, width); + memmove(rgb_dst, rgb_src, width * 3); + dst += c->pal_stride; + src += c->pal_stride; + rgb_dst += c->rgb_stride; + rgb_src += c->rgb_stride; + } + } + return 0; +} + +static int decode_region_masked(MSS12Context const *c, ArithCoder *acoder, + uint8_t *dst, int stride, uint8_t *mask, + int mask_stride, int x, int y, + int width, int height, + PixContext *pctx) +{ + int i, j, p; + uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * c->rgb_stride; + + dst += x + y * stride; + mask += x + y * mask_stride; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + if (c->avctx->err_recognition & AV_EF_EXPLODE && + ( c->rgb_pic && mask[i] != 0x01 && mask[i] != 0x02 && mask[i] != 0x04 || + !c->rgb_pic && mask[i] != 0x80 && mask[i] != 0xFF)) + return -1; + + if (mask[i] == 0x02) { + copy_rectangles(c, x + i, y + j, 1, 1); + } else if (mask[i] == 0x04) { + if (motion_compensation(c, x + i, y + j, 1, 1)) + return -1; + } else if (mask[i] != 0x80) { + if (!i && !j) + p = decode_pixel(acoder, pctx, NULL, 0, 0); + else + p = decode_pixel_in_context(acoder, pctx, dst + i, stride, + i, j, width - i - 1); + dst[i] = p; + if (c->rgb_pic) + AV_WB24(rgb_dst + i * 3, c->pal[p]); + } + } + dst += stride; + mask += mask_stride; + rgb_dst += c->rgb_stride; + } + + return 0; +} + +static av_cold void slicecontext_init(SliceContext *sc, + int version, int full_model_syms) +{ + model_init(&sc->intra_region, 2, THRESH_ADAPTIVE); + model_init(&sc->inter_region, 2, THRESH_ADAPTIVE); + model_init(&sc->split_mode, 3, THRESH_HIGH); + model_init(&sc->edge_mode, 2, THRESH_HIGH); + model_init(&sc->pivot, 3, THRESH_LOW); + + pixctx_init(&sc->intra_pix_ctx, 8, full_model_syms, 0); + + pixctx_init(&sc->inter_pix_ctx, version ? 3 : 2, + full_model_syms, version ? 1 : 0); +} + +void ff_mss12_slicecontext_reset(SliceContext *sc) +{ + model_reset(&sc->intra_region); + model_reset(&sc->inter_region); + model_reset(&sc->split_mode); + model_reset(&sc->edge_mode); + model_reset(&sc->pivot); + pixctx_reset(&sc->intra_pix_ctx); + pixctx_reset(&sc->inter_pix_ctx); +} + +static int decode_pivot(SliceContext *sc, ArithCoder *acoder, int base) +{ + int val, inv; + + inv = acoder->get_model_sym(acoder, &sc->edge_mode); + val = acoder->get_model_sym(acoder, &sc->pivot) + 1; + + if (val > 2) { + if ((base + 1) / 2 - 2 <= 0) + return -1; + + val = acoder->get_number(acoder, (base + 1) / 2 - 2) + 3; + } + + if ((unsigned)val >= base) + return -1; + + return inv ? base - val : val; +} + +static int decode_region_intra(SliceContext *sc, ArithCoder *acoder, + int x, int y, int width, int height) +{ + MSS12Context const *c = sc->c; + int mode; + + mode = acoder->get_model_sym(acoder, &sc->intra_region); + + if (!mode) { + int i, j, pix, rgb_pix; + int stride = c->pal_stride; + int rgb_stride = c->rgb_stride; + uint8_t *dst = c->pal_pic + x + y * stride; + uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * rgb_stride; + + pix = decode_pixel(acoder, &sc->intra_pix_ctx, NULL, 0, 0); + rgb_pix = c->pal[pix]; + for (i = 0; i < height; i++, dst += stride, rgb_dst += rgb_stride) { + memset(dst, pix, width); + if (c->rgb_pic) + for (j = 0; j < width * 3; j += 3) + AV_WB24(rgb_dst + j, rgb_pix); + } + } else { + return decode_region(acoder, c->pal_pic, c->rgb_pic, + x, y, width, height, c->pal_stride, c->rgb_stride, + &sc->intra_pix_ctx, &c->pal[0]); + } + + return 0; +} + +static int decode_region_inter(SliceContext *sc, ArithCoder *acoder, + int x, int y, int width, int height) +{ + MSS12Context const *c = sc->c; + int mode; + + mode = acoder->get_model_sym(acoder, &sc->inter_region); + + if (!mode) { + mode = decode_pixel(acoder, &sc->inter_pix_ctx, NULL, 0, 0); + + if (c->avctx->err_recognition & AV_EF_EXPLODE && + ( c->rgb_pic && mode != 0x01 && mode != 0x02 && mode != 0x04 || + !c->rgb_pic && mode != 0x80 && mode != 0xFF)) + return -1; + + if (mode == 0x02) + copy_rectangles(c, x, y, width, height); + else if (mode == 0x04) + return motion_compensation(c, x, y, width, height); + else if (mode != 0x80) + return decode_region_intra(sc, acoder, x, y, width, height); + } else { + if (decode_region(acoder, c->mask, NULL, + x, y, width, height, c->mask_stride, 0, + &sc->inter_pix_ctx, &c->pal[0]) < 0) + return -1; + return decode_region_masked(c, acoder, c->pal_pic, + c->pal_stride, c->mask, + c->mask_stride, + x, y, width, height, + &sc->intra_pix_ctx); + } + + return 0; +} + +int ff_mss12_decode_rect(SliceContext *sc, ArithCoder *acoder, + int x, int y, int width, int height) +{ + int mode, pivot; + + mode = acoder->get_model_sym(acoder, &sc->split_mode); + + switch (mode) { + case SPLIT_VERT: + if ((pivot = decode_pivot(sc, acoder, height)) < 1) + return -1; + if (ff_mss12_decode_rect(sc, acoder, x, y, width, pivot)) + return -1; + if (ff_mss12_decode_rect(sc, acoder, x, y + pivot, width, height - pivot)) + return -1; + break; + case SPLIT_HOR: + if ((pivot = decode_pivot(sc, acoder, width)) < 1) + return -1; + if (ff_mss12_decode_rect(sc, acoder, x, y, pivot, height)) + return -1; + if (ff_mss12_decode_rect(sc, acoder, x + pivot, y, width - pivot, height)) + return -1; + break; + case SPLIT_NONE: + if (sc->c->keyframe) + return decode_region_intra(sc, acoder, x, y, width, height); + else + return decode_region_inter(sc, acoder, x, y, width, height); + default: + return -1; + } + + return 0; +} + +av_cold int ff_mss12_decode_init(MSS12Context *c, int version, + SliceContext* sc1, SliceContext *sc2) +{ + AVCodecContext *avctx = c->avctx; + int i; + + if (avctx->extradata_size < 52 + 256 * 3) { + av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + if (AV_RB32(avctx->extradata) < avctx->extradata_size) { + av_log(avctx, AV_LOG_ERROR, + "Insufficient extradata size: expected %d got %d\n", + AV_RB32(avctx->extradata), + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + avctx->coded_width = AV_RB32(avctx->extradata + 20); + avctx->coded_height = AV_RB32(avctx->extradata + 24); + if (avctx->coded_width > 4096 || avctx->coded_height > 4096) { + av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too large", + avctx->coded_width, avctx->coded_height); + return AVERROR_INVALIDDATA; + } + if (avctx->coded_width < 1 || avctx->coded_height < 1) { + av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too small", + avctx->coded_width, avctx->coded_height); + return AVERROR_INVALIDDATA; + } + + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n", + AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); + if (version != AV_RB32(avctx->extradata + 4) > 1) { + av_log(avctx, AV_LOG_ERROR, + "Header version doesn't match codec tag\n"); + return -1; + } + + c->free_colours = AV_RB32(avctx->extradata + 48); + if ((unsigned)c->free_colours > 256) { + av_log(avctx, AV_LOG_ERROR, + "Incorrect number of changeable palette entries: %d\n", + c->free_colours); + return AVERROR_INVALIDDATA; + } + av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours); + + av_log(avctx, AV_LOG_DEBUG, "Display dimensions %dx%d\n", + AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16)); + av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n", + avctx->coded_width, avctx->coded_height); + av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n", + av_int2float(AV_RB32(avctx->extradata + 28))); + av_log(avctx, AV_LOG_DEBUG, "Bitrate %d bps\n", + AV_RB32(avctx->extradata + 32)); + av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n", + av_int2float(AV_RB32(avctx->extradata + 36))); + av_log(avctx, AV_LOG_DEBUG, "Max. lag time %g ms\n", + av_int2float(AV_RB32(avctx->extradata + 40))); + av_log(avctx, AV_LOG_DEBUG, "Max. seek time %g ms\n", + av_int2float(AV_RB32(avctx->extradata + 44))); + + if (version) { + if (avctx->extradata_size < 60 + 256 * 3) { + av_log(avctx, AV_LOG_ERROR, + "Insufficient extradata size %d for v2\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + c->slice_split = AV_RB32(avctx->extradata + 52); + av_log(avctx, AV_LOG_DEBUG, "Slice split %d\n", c->slice_split); + + c->full_model_syms = AV_RB32(avctx->extradata + 56); + if (c->full_model_syms < 2 || c->full_model_syms > 256) { + av_log(avctx, AV_LOG_ERROR, + "Incorrect number of used colours %d\n", + c->full_model_syms); + return AVERROR_INVALIDDATA; + } + av_log(avctx, AV_LOG_DEBUG, "Used colours %d\n", + c->full_model_syms); + } else { + c->slice_split = 0; + c->full_model_syms = 256; + } + + for (i = 0; i < 256; i++) + c->pal[i] = 0xFFU << 24 | AV_RB24(avctx->extradata + 52 + + (version ? 8 : 0) + i * 3); + + c->mask_stride = FFALIGN(avctx->width, 16); + c->mask = av_malloc(c->mask_stride * avctx->height); + if (!c->mask) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate mask plane\n"); + return AVERROR(ENOMEM); + } + + sc1->c = c; + slicecontext_init(sc1, version, c->full_model_syms); + if (c->slice_split) { + sc2->c = c; + slicecontext_init(sc2, version, c->full_model_syms); + } + c->corrupted = 1; + + return 0; +} + +av_cold int ff_mss12_decode_end(MSS12Context *c) +{ + av_freep(&c->mask); + + return 0; +} diff --git a/ffmpeg/libavcodec/mss12.h b/ffmpeg/libavcodec/mss12.h new file mode 100644 index 0000000..a3f9a7c --- /dev/null +++ b/ffmpeg/libavcodec/mss12.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Common header for Microsoft Screen 1 and 2 + */ + +#ifndef AVCODEC_MSS12_H +#define AVCODEC_MSS12_H + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "get_bits.h" +#include "bytestream.h" + +#define MODEL_MIN_SYMS 2 +#define MODEL_MAX_SYMS 256 +#define THRESH_ADAPTIVE -1 +#define THRESH_LOW 15 +#define THRESH_HIGH 50 + +typedef struct Model { + int16_t cum_prob[MODEL_MAX_SYMS + 1]; + int16_t weights[MODEL_MAX_SYMS + 1]; + uint8_t idx2sym[MODEL_MAX_SYMS + 1]; + int num_syms; + int thr_weight, threshold; +} Model; + +typedef struct ArithCoder { + int low, high, value; + union { + GetBitContext *gb; + GetByteContext *gB; + } gbc; + int (*get_model_sym)(struct ArithCoder *c, Model *m); + int (*get_number) (struct ArithCoder *c, int n); +} ArithCoder; + +typedef struct PixContext { + int cache_size, num_syms; + uint8_t cache[12]; + Model cache_model, full_model; + Model sec_models[15][4]; + int special_initial_cache; +} PixContext; + +struct MSS12Context; + +typedef struct SliceContext { + struct MSS12Context *c; + Model intra_region, inter_region; + Model pivot, edge_mode, split_mode; + PixContext intra_pix_ctx, inter_pix_ctx; +} SliceContext; + +typedef struct MSS12Context { + AVCodecContext *avctx; + uint32_t pal[256]; + uint8_t *pal_pic; + uint8_t *last_pal_pic; + int pal_stride; + uint8_t *mask; + int mask_stride; + uint8_t *rgb_pic; + uint8_t *last_rgb_pic; + int rgb_stride; + int free_colours; + int keyframe; + int mvX, mvY; + int corrupted; + int slice_split; + int full_model_syms; +} MSS12Context; + +int ff_mss12_decode_rect(SliceContext *ctx, ArithCoder *acoder, + int x, int y, int width, int height); +void ff_mss12_model_update(Model *m, int val); +void ff_mss12_slicecontext_reset(SliceContext *sc); +int ff_mss12_decode_init(MSS12Context *c, int version, + SliceContext *sc1, SliceContext *sc2); +int ff_mss12_decode_end(MSS12Context *ctx); + +#define ARITH_GET_BIT(VERSION) \ +static int arith ## VERSION ## _get_bit(ArithCoder *c) \ +{ \ + int range = c->high - c->low + 1; \ + int bit = 2 * c->value - c->low >= c->high; \ + \ + if (bit) \ + c->low += range >> 1; \ + else \ + c->high = c->low + (range >> 1) - 1; \ + \ + arith ## VERSION ## _normalise(c); \ + \ + return bit; \ +} + +#define ARITH_GET_MODEL_SYM(VERSION) \ +static int arith ## VERSION ## _get_model_sym(ArithCoder *c, Model *m) \ +{ \ + int idx, val; \ + \ + idx = arith ## VERSION ## _get_prob(c, m->cum_prob); \ + \ + val = m->idx2sym[idx]; \ + ff_mss12_model_update(m, idx); \ + \ + arith ## VERSION ## _normalise(c); \ + \ + return val; \ +} + +#endif /* AVCODEC_MSS12_H */ diff --git a/ffmpeg/libavcodec/mss2.c b/ffmpeg/libavcodec/mss2.c new file mode 100644 index 0000000..fcdbbd2 --- /dev/null +++ b/ffmpeg/libavcodec/mss2.c @@ -0,0 +1,852 @@ +/* + * Microsoft Screen 2 (aka Windows Media Video V9 Screen) decoder + * + * 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 + */ + +/** + * @file + * Microsoft Screen 2 (aka Windows Media Video V9 Screen) decoder + */ + +#include "libavutil/avassert.h" +#include "error_resilience.h" +#include "internal.h" +#include "msmpeg4data.h" +#include "vc1.h" +#include "mss12.h" +#include "mss2dsp.h" + +typedef struct MSS2Context { + VC1Context v; + int split_position; + AVFrame last_pic; + MSS12Context c; + MSS2DSPContext dsp; + SliceContext sc[2]; +} MSS2Context; + +static void arith2_normalise(ArithCoder *c) +{ + while ((c->high >> 15) - (c->low >> 15) < 2) { + if ((c->low ^ c->high) & 0x10000) { + c->high ^= 0x8000; + c->value ^= 0x8000; + c->low ^= 0x8000; + } + c->high = c->high << 8 & 0xFFFFFF | 0xFF; + c->value = c->value << 8 & 0xFFFFFF | bytestream2_get_byte(c->gbc.gB); + c->low = c->low << 8 & 0xFFFFFF; + } +} + +ARITH_GET_BIT(2) + +/* L. Stuiver and A. Moffat: "Piecewise Integer Mapping for Arithmetic Coding." + * In Proc. 8th Data Compression Conference (DCC '98), pp. 3-12, Mar. 1998 */ + +static int arith2_get_scaled_value(int value, int n, int range) +{ + int split = (n << 1) - range; + + if (value > split) + return split + (value - split >> 1); + else + return value; +} + +static void arith2_rescale_interval(ArithCoder *c, int range, + int low, int high, int n) +{ + int split = (n << 1) - range; + + if (high > split) + c->high = split + (high - split << 1); + else + c->high = high; + + c->high += c->low - 1; + + if (low > split) + c->low += split + (low - split << 1); + else + c->low += low; +} + +static int arith2_get_number(ArithCoder *c, int n) +{ + int range = c->high - c->low + 1; + int scale = av_log2(range) - av_log2(n); + int val; + + if (n << scale > range) + scale--; + + n <<= scale; + + val = arith2_get_scaled_value(c->value - c->low, n, range) >> scale; + + arith2_rescale_interval(c, range, val << scale, (val + 1) << scale, n); + + arith2_normalise(c); + + return val; +} + +static int arith2_get_prob(ArithCoder *c, int16_t *probs) +{ + int range = c->high - c->low + 1, n = *probs; + int scale = av_log2(range) - av_log2(n); + int i = 0, val; + + if (n << scale > range) + scale--; + + n <<= scale; + + val = arith2_get_scaled_value(c->value - c->low, n, range) >> scale; + while (probs[++i] > val) ; + + arith2_rescale_interval(c, range, + probs[i] << scale, probs[i - 1] << scale, n); + + return i; +} + +ARITH_GET_MODEL_SYM(2) + +static int arith2_get_consumed_bytes(ArithCoder *c) +{ + int diff = (c->high >> 16) - (c->low >> 16); + int bp = bytestream2_tell(c->gbc.gB) - 3 << 3; + int bits = 1; + + while (!(diff & 0x80)) { + bits++; + diff <<= 1; + } + + return (bits + bp + 7 >> 3) + ((c->low >> 16) + 1 == c->high >> 16); +} + +static void arith2_init(ArithCoder *c, GetByteContext *gB) +{ + c->low = 0; + c->high = 0xFFFFFF; + c->value = bytestream2_get_be24(gB); + c->gbc.gB = gB; + c->get_model_sym = arith2_get_model_sym; + c->get_number = arith2_get_number; +} + +static int decode_pal_v2(MSS12Context *ctx, const uint8_t *buf, int buf_size) +{ + int i, ncol; + uint32_t *pal = ctx->pal + 256 - ctx->free_colours; + + if (!ctx->free_colours) + return 0; + + ncol = *buf++; + if (ncol > ctx->free_colours || buf_size < 2 + ncol * 3) + return AVERROR_INVALIDDATA; + for (i = 0; i < ncol; i++) + *pal++ = AV_RB24(buf + 3 * i); + + return 1 + ncol * 3; +} + +static int decode_555(GetByteContext *gB, uint16_t *dst, int stride, + int keyframe, int w, int h) +{ + int last_symbol = 0, repeat = 0, prev_avail = 0; + + if (!keyframe) { + int x, y, endx, endy, t; + +#define READ_PAIR(a, b) \ + a = bytestream2_get_byte(gB) << 4; \ + t = bytestream2_get_byte(gB); \ + a |= t >> 4; \ + b = (t & 0xF) << 8; \ + b |= bytestream2_get_byte(gB); \ + + READ_PAIR(x, endx) + READ_PAIR(y, endy) + + if (endx >= w || endy >= h || x > endx || y > endy) + return AVERROR_INVALIDDATA; + dst += x + stride * y; + w = endx - x + 1; + h = endy - y + 1; + if (y) + prev_avail = 1; + } + + do { + uint16_t *p = dst; + do { + if (repeat-- < 1) { + int b = bytestream2_get_byte(gB); + if (b < 128) + last_symbol = b << 8 | bytestream2_get_byte(gB); + else if (b > 129) { + repeat = 0; + while (b-- > 130) + repeat = (repeat << 8) + bytestream2_get_byte(gB) + 1; + if (last_symbol == -2) { + int skip = FFMIN((unsigned)repeat, dst + w - p); + repeat -= skip; + p += skip; + } + } else + last_symbol = 127 - b; + } + if (last_symbol >= 0) + *p = last_symbol; + else if (last_symbol == -1 && prev_avail) + *p = *(p - stride); + } while (++p < dst + w); + dst += stride; + prev_avail = 1; + } while (--h); + + return 0; +} + +static int decode_rle(GetBitContext *gb, uint8_t *pal_dst, int pal_stride, + uint8_t *rgb_dst, int rgb_stride, uint32_t *pal, + int keyframe, int kf_slipt, int slice, int w, int h) +{ + uint8_t bits[270] = { 0 }; + uint32_t codes[270]; + VLC vlc; + + int current_length = 0, read_codes = 0, next_code = 0, current_codes = 0; + int remaining_codes, surplus_codes, i; + + const int alphabet_size = 270 - keyframe; + + int last_symbol = 0, repeat = 0, prev_avail = 0; + + if (!keyframe) { + int x, y, clipw, cliph; + + x = get_bits(gb, 12); + y = get_bits(gb, 12); + clipw = get_bits(gb, 12) + 1; + cliph = get_bits(gb, 12) + 1; + + if (x + clipw > w || y + cliph > h) + return AVERROR_INVALIDDATA; + pal_dst += pal_stride * y + x; + rgb_dst += rgb_stride * y + x * 3; + w = clipw; + h = cliph; + if (y) + prev_avail = 1; + } else { + if (slice > 0) { + pal_dst += pal_stride * kf_slipt; + rgb_dst += rgb_stride * kf_slipt; + prev_avail = 1; + h -= kf_slipt; + } else + h = kf_slipt; + } + + /* read explicit codes */ + do { + while (current_codes--) { + int symbol = get_bits(gb, 8); + if (symbol >= 204 - keyframe) + symbol += 14 - keyframe; + else if (symbol > 189) + symbol = get_bits1(gb) + (symbol << 1) - 190; + if (bits[symbol]) + return AVERROR_INVALIDDATA; + bits[symbol] = current_length; + codes[symbol] = next_code++; + read_codes++; + } + current_length++; + next_code <<= 1; + remaining_codes = (1 << current_length) - next_code; + current_codes = get_bits(gb, av_ceil_log2(remaining_codes + 1)); + if (current_length > 22 || current_codes > remaining_codes) + return AVERROR_INVALIDDATA; + } while (current_codes != remaining_codes); + + remaining_codes = alphabet_size - read_codes; + + /* determine the minimum length to fit the rest of the alphabet */ + while ((surplus_codes = (2 << current_length) - + (next_code << 1) - remaining_codes) < 0) { + current_length++; + next_code <<= 1; + } + + /* add the rest of the symbols lexicographically */ + for (i = 0; i < alphabet_size; i++) + if (!bits[i]) { + if (surplus_codes-- == 0) { + current_length++; + next_code <<= 1; + } + bits[i] = current_length; + codes[i] = next_code++; + } + + if (next_code != 1 << current_length) + return AVERROR_INVALIDDATA; + + if (i = init_vlc(&vlc, 9, alphabet_size, bits, 1, 1, codes, 4, 4, 0)) + return i; + + /* frame decode */ + do { + uint8_t *pp = pal_dst; + uint8_t *rp = rgb_dst; + do { + if (repeat-- < 1) { + int b = get_vlc2(gb, vlc.table, 9, 3); + if (b < 256) + last_symbol = b; + else if (b < 268) { + b -= 256; + if (b == 11) + b = get_bits(gb, 4) + 10; + + if (!b) + repeat = 0; + else + repeat = get_bits(gb, b); + + repeat += (1 << b) - 1; + + if (last_symbol == -2) { + int skip = FFMIN(repeat, pal_dst + w - pp); + repeat -= skip; + pp += skip; + rp += skip * 3; + } + } else + last_symbol = 267 - b; + } + if (last_symbol >= 0) { + *pp = last_symbol; + AV_WB24(rp, pal[last_symbol]); + } else if (last_symbol == -1 && prev_avail) { + *pp = *(pp - pal_stride); + memcpy(rp, rp - rgb_stride, 3); + } + rp += 3; + } while (++pp < pal_dst + w); + pal_dst += pal_stride; + rgb_dst += rgb_stride; + prev_avail = 1; + } while (--h); + + ff_free_vlc(&vlc); + return 0; +} + +static int decode_wmv9(AVCodecContext *avctx, const uint8_t *buf, int buf_size, + int x, int y, int w, int h, int wmv9_mask) +{ + MSS2Context *ctx = avctx->priv_data; + MSS12Context *c = &ctx->c; + VC1Context *v = avctx->priv_data; + MpegEncContext *s = &v->s; + AVFrame *f; + int ret; + + ff_mpeg_flush(avctx); + + if (s->current_picture_ptr == NULL || s->current_picture_ptr->f.data[0]) { + int i = ff_find_unused_picture(s, 0); + if (i < 0) + return i; + s->current_picture_ptr = &s->picture[i]; + } + + init_get_bits(&s->gb, buf, buf_size * 8); + + s->loop_filter = avctx->skip_loop_filter < AVDISCARD_ALL; + + if (ff_vc1_parse_frame_header(v, &s->gb) == -1) { + av_log(v->s.avctx, AV_LOG_ERROR, "header error\n"); + return AVERROR_INVALIDDATA; + } + + if (s->pict_type != AV_PICTURE_TYPE_I) { + av_log(v->s.avctx, AV_LOG_ERROR, "expected I-frame\n"); + return AVERROR_INVALIDDATA; + } + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + if ((ret = ff_MPV_frame_start(s, avctx)) < 0) { + av_log(v->s.avctx, AV_LOG_ERROR, "ff_MPV_frame_start error\n"); + avctx->pix_fmt = AV_PIX_FMT_RGB24; + return ret; + } + + ff_mpeg_er_frame_start(s); + + v->bits = buf_size * 8; + + v->end_mb_x = (w + 15) >> 4; + s->end_mb_y = (h + 15) >> 4; + if (v->respic & 1) + v->end_mb_x = v->end_mb_x + 1 >> 1; + if (v->respic & 2) + s->end_mb_y = s->end_mb_y + 1 >> 1; + + ff_vc1_decode_blocks(v); + + ff_er_frame_end(&s->er); + + ff_MPV_frame_end(s); + + f = &s->current_picture.f; + + if (v->respic == 3) { + ctx->dsp.upsample_plane(f->data[0], f->linesize[0], w, h); + ctx->dsp.upsample_plane(f->data[1], f->linesize[1], w >> 1, h >> 1); + ctx->dsp.upsample_plane(f->data[2], f->linesize[2], w >> 1, h >> 1); + } else if (v->respic) + avpriv_request_sample(v->s.avctx, + "Asymmetric WMV9 rectangle subsampling"); + + av_assert0(f->linesize[1] == f->linesize[2]); + + if (wmv9_mask != -1) + ctx->dsp.mss2_blit_wmv9_masked(c->rgb_pic + y * c->rgb_stride + x * 3, + c->rgb_stride, wmv9_mask, + c->pal_pic + y * c->pal_stride + x, + c->pal_stride, + f->data[0], f->linesize[0], + f->data[1], f->data[2], f->linesize[1], + w, h); + else + ctx->dsp.mss2_blit_wmv9(c->rgb_pic + y * c->rgb_stride + x * 3, + c->rgb_stride, + f->data[0], f->linesize[0], + f->data[1], f->data[2], f->linesize[1], + w, h); + + avctx->pix_fmt = AV_PIX_FMT_RGB24; + + return 0; +} + +typedef struct Rectangle { + int coded, x, y, w, h; +} Rectangle; + +#define MAX_WMV9_RECTANGLES 20 +#define ARITH2_PADDING 2 + +static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MSS2Context *ctx = avctx->priv_data; + MSS12Context *c = &ctx->c; + AVFrame *frame = data; + GetBitContext gb; + GetByteContext gB; + ArithCoder acoder; + + int keyframe, has_wmv9, has_mv, is_rle, is_555, ret; + + Rectangle wmv9rects[MAX_WMV9_RECTANGLES], *r; + int used_rects = 0, i, implicit_rect = 0, av_uninit(wmv9_mask); + + av_assert0(FF_INPUT_BUFFER_PADDING_SIZE >= + ARITH2_PADDING + (MIN_CACHE_BITS + 7) / 8); + + init_get_bits(&gb, buf, buf_size * 8); + + if (keyframe = get_bits1(&gb)) + skip_bits(&gb, 7); + has_wmv9 = get_bits1(&gb); + has_mv = keyframe ? 0 : get_bits1(&gb); + is_rle = get_bits1(&gb); + is_555 = is_rle && get_bits1(&gb); + if (c->slice_split > 0) + ctx->split_position = c->slice_split; + else if (c->slice_split < 0) { + if (get_bits1(&gb)) { + if (get_bits1(&gb)) { + if (get_bits1(&gb)) + ctx->split_position = get_bits(&gb, 16); + else + ctx->split_position = get_bits(&gb, 12); + } else + ctx->split_position = get_bits(&gb, 8) << 4; + } else { + if (keyframe) + ctx->split_position = avctx->height / 2; + } + } else + ctx->split_position = avctx->height; + + if (c->slice_split && (ctx->split_position < 1 - is_555 || + ctx->split_position > avctx->height - 1)) + return AVERROR_INVALIDDATA; + + align_get_bits(&gb); + buf += get_bits_count(&gb) >> 3; + buf_size -= get_bits_count(&gb) >> 3; + + if (buf_size < 1) + return AVERROR_INVALIDDATA; + + if (is_555 && (has_wmv9 || has_mv || c->slice_split && ctx->split_position)) + return AVERROR_INVALIDDATA; + + avctx->pix_fmt = is_555 ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_RGB24; + if (ctx->last_pic.format != avctx->pix_fmt) + av_frame_unref(&ctx->last_pic); + + if (has_wmv9) { + bytestream2_init(&gB, buf, buf_size + ARITH2_PADDING); + arith2_init(&acoder, &gB); + + implicit_rect = !arith2_get_bit(&acoder); + + while (arith2_get_bit(&acoder)) { + if (used_rects == MAX_WMV9_RECTANGLES) + return AVERROR_INVALIDDATA; + r = &wmv9rects[used_rects]; + if (!used_rects) + r->x = arith2_get_number(&acoder, avctx->width); + else + r->x = arith2_get_number(&acoder, avctx->width - + wmv9rects[used_rects - 1].x) + + wmv9rects[used_rects - 1].x; + r->y = arith2_get_number(&acoder, avctx->height); + r->w = arith2_get_number(&acoder, avctx->width - r->x) + 1; + r->h = arith2_get_number(&acoder, avctx->height - r->y) + 1; + used_rects++; + } + + if (implicit_rect && used_rects) { + av_log(avctx, AV_LOG_ERROR, "implicit_rect && used_rects > 0\n"); + return AVERROR_INVALIDDATA; + } + + if (implicit_rect) { + wmv9rects[0].x = 0; + wmv9rects[0].y = 0; + wmv9rects[0].w = avctx->width; + wmv9rects[0].h = avctx->height; + + used_rects = 1; + } + for (i = 0; i < used_rects; i++) { + if (!implicit_rect && arith2_get_bit(&acoder)) { + av_log(avctx, AV_LOG_ERROR, "Unexpected grandchildren\n"); + return AVERROR_INVALIDDATA; + } + if (!i) { + wmv9_mask = arith2_get_bit(&acoder) - 1; + if (!wmv9_mask) + wmv9_mask = arith2_get_number(&acoder, 256); + } + wmv9rects[i].coded = arith2_get_number(&acoder, 2); + } + + buf += arith2_get_consumed_bytes(&acoder); + buf_size -= arith2_get_consumed_bytes(&acoder); + if (buf_size < 1) + return AVERROR_INVALIDDATA; + } + + c->mvX = c->mvY = 0; + if (keyframe && !is_555) { + if ((i = decode_pal_v2(c, buf, buf_size)) < 0) + return AVERROR_INVALIDDATA; + buf += i; + buf_size -= i; + } else if (has_mv) { + buf += 4; + buf_size -= 4; + if (buf_size < 1) + return AVERROR_INVALIDDATA; + c->mvX = AV_RB16(buf - 4) - avctx->width; + c->mvY = AV_RB16(buf - 2) - avctx->height; + } + + if (c->mvX < 0 || c->mvY < 0) { + FFSWAP(uint8_t *, c->pal_pic, c->last_pal_pic); + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if (ctx->last_pic.data[0]) { + av_assert0(frame->linesize[0] == ctx->last_pic.linesize[0]); + c->last_rgb_pic = ctx->last_pic.data[0] + + ctx->last_pic.linesize[0] * (avctx->height - 1); + } else { + av_log(avctx, AV_LOG_ERROR, "Missing keyframe\n"); + return AVERROR_INVALIDDATA; + } + } else { + if ((ret = ff_reget_buffer(avctx, &ctx->last_pic)) < 0) + return ret; + if ((ret = av_frame_ref(frame, &ctx->last_pic)) < 0) + return ret; + + c->last_rgb_pic = NULL; + } + c->rgb_pic = frame->data[0] + + frame->linesize[0] * (avctx->height - 1); + c->rgb_stride = -frame->linesize[0]; + + frame->key_frame = keyframe; + frame->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + + if (is_555) { + bytestream2_init(&gB, buf, buf_size); + + if (decode_555(&gB, (uint16_t *)c->rgb_pic, c->rgb_stride >> 1, + keyframe, avctx->width, avctx->height)) + return AVERROR_INVALIDDATA; + + buf_size -= bytestream2_tell(&gB); + } else { + if (keyframe) { + c->corrupted = 0; + ff_mss12_slicecontext_reset(&ctx->sc[0]); + if (c->slice_split) + ff_mss12_slicecontext_reset(&ctx->sc[1]); + } + if (is_rle) { + init_get_bits(&gb, buf, buf_size * 8); + if (ret = decode_rle(&gb, c->pal_pic, c->pal_stride, + c->rgb_pic, c->rgb_stride, c->pal, keyframe, + ctx->split_position, 0, + avctx->width, avctx->height)) + return ret; + align_get_bits(&gb); + + if (c->slice_split) + if (ret = decode_rle(&gb, c->pal_pic, c->pal_stride, + c->rgb_pic, c->rgb_stride, c->pal, keyframe, + ctx->split_position, 1, + avctx->width, avctx->height)) + return ret; + + align_get_bits(&gb); + buf += get_bits_count(&gb) >> 3; + buf_size -= get_bits_count(&gb) >> 3; + } else if (!implicit_rect || wmv9_mask != -1) { + if (c->corrupted) + return AVERROR_INVALIDDATA; + bytestream2_init(&gB, buf, buf_size + ARITH2_PADDING); + arith2_init(&acoder, &gB); + c->keyframe = keyframe; + if (c->corrupted = ff_mss12_decode_rect(&ctx->sc[0], &acoder, 0, 0, + avctx->width, + ctx->split_position)) + return AVERROR_INVALIDDATA; + + buf += arith2_get_consumed_bytes(&acoder); + buf_size -= arith2_get_consumed_bytes(&acoder); + if (c->slice_split) { + if (buf_size < 1) + return AVERROR_INVALIDDATA; + bytestream2_init(&gB, buf, buf_size + ARITH2_PADDING); + arith2_init(&acoder, &gB); + if (c->corrupted = ff_mss12_decode_rect(&ctx->sc[1], &acoder, 0, + ctx->split_position, + avctx->width, + avctx->height - ctx->split_position)) + return AVERROR_INVALIDDATA; + + buf += arith2_get_consumed_bytes(&acoder); + buf_size -= arith2_get_consumed_bytes(&acoder); + } + } else + memset(c->pal_pic, 0, c->pal_stride * avctx->height); + } + + if (has_wmv9) { + for (i = 0; i < used_rects; i++) { + int x = wmv9rects[i].x; + int y = wmv9rects[i].y; + int w = wmv9rects[i].w; + int h = wmv9rects[i].h; + if (wmv9rects[i].coded) { + int WMV9codedFrameSize; + if (buf_size < 4 || !(WMV9codedFrameSize = AV_RL24(buf))) + return AVERROR_INVALIDDATA; + if (ret = decode_wmv9(avctx, buf + 3, buf_size - 3, + x, y, w, h, wmv9_mask)) + return ret; + buf += WMV9codedFrameSize + 3; + buf_size -= WMV9codedFrameSize + 3; + } else { + uint8_t *dst = c->rgb_pic + y * c->rgb_stride + x * 3; + if (wmv9_mask != -1) { + ctx->dsp.mss2_gray_fill_masked(dst, c->rgb_stride, + wmv9_mask, + c->pal_pic + y * c->pal_stride + x, + c->pal_stride, + w, h); + } else { + do { + memset(dst, 0x80, w * 3); + dst += c->rgb_stride; + } while (--h); + } + } + } + } + + if (buf_size) + av_log(avctx, AV_LOG_WARNING, "buffer not fully consumed\n"); + + if (c->mvX < 0 || c->mvY < 0) { + av_frame_unref(&ctx->last_pic); + ret = av_frame_ref(&ctx->last_pic, frame); + if (ret < 0) + return ret; + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int wmv9_init(AVCodecContext *avctx) +{ + VC1Context *v = avctx->priv_data; + int ret; + + v->s.avctx = avctx; + avctx->flags |= CODEC_FLAG_EMU_EDGE; + v->s.flags |= CODEC_FLAG_EMU_EDGE; + + if ((ret = ff_vc1_init_common(v)) < 0) + return ret; + ff_vc1dsp_init(&v->vc1dsp); + + v->profile = PROFILE_MAIN; + + v->zz_8x4 = ff_wmv2_scantableA; + v->zz_4x8 = ff_wmv2_scantableB; + v->res_y411 = 0; + v->res_sprite = 0; + + v->frmrtq_postproc = 7; + v->bitrtq_postproc = 31; + + v->res_x8 = 0; + v->multires = 0; + v->res_fasttx = 1; + + v->fastuvmc = 0; + + v->extended_mv = 0; + + v->dquant = 1; + v->vstransform = 1; + + v->res_transtab = 0; + + v->overlap = 0; + + v->s.resync_marker = 0; + v->rangered = 0; + + v->s.max_b_frames = avctx->max_b_frames = 0; + v->quantizer_mode = 0; + + v->finterpflag = 0; + + v->res_rtm_flag = 1; + + ff_vc1_init_transposed_scantables(v); + + if ((ret = ff_msmpeg4_decode_init(avctx)) < 0 || + (ret = ff_vc1_decode_init_alloc_tables(v)) < 0) + return ret; + + /* error concealment */ + v->s.me.qpel_put = v->s.dsp.put_qpel_pixels_tab; + v->s.me.qpel_avg = v->s.dsp.avg_qpel_pixels_tab; + + return 0; +} + +static av_cold int mss2_decode_end(AVCodecContext *avctx) +{ + MSS2Context *const ctx = avctx->priv_data; + + av_frame_unref(&ctx->last_pic); + + ff_mss12_decode_end(&ctx->c); + av_freep(&ctx->c.pal_pic); + av_freep(&ctx->c.last_pal_pic); + ff_vc1_decode_end(avctx); + + return 0; +} + +static av_cold int mss2_decode_init(AVCodecContext *avctx) +{ + MSS2Context * const ctx = avctx->priv_data; + MSS12Context *c = &ctx->c; + int ret; + c->avctx = avctx; + if (ret = ff_mss12_decode_init(c, 1, &ctx->sc[0], &ctx->sc[1])) + return ret; + c->pal_stride = c->mask_stride; + c->pal_pic = av_mallocz(c->pal_stride * avctx->height); + c->last_pal_pic = av_mallocz(c->pal_stride * avctx->height); + if (!c->pal_pic || !c->last_pal_pic) { + mss2_decode_end(avctx); + return AVERROR(ENOMEM); + } + if (ret = wmv9_init(avctx)) { + mss2_decode_end(avctx); + return ret; + } + ff_mss2dsp_init(&ctx->dsp); + + avctx->pix_fmt = c->free_colours == 127 ? AV_PIX_FMT_RGB555 + : AV_PIX_FMT_RGB24; + + return 0; +} + +AVCodec ff_mss2_decoder = { + .name = "mss2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSS2, + .priv_data_size = sizeof(MSS2Context), + .init = mss2_decode_init, + .close = mss2_decode_end, + .decode = mss2_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MS Windows Media Video V9 Screen"), +}; diff --git a/ffmpeg/libavcodec/mss2dsp.c b/ffmpeg/libavcodec/mss2dsp.c new file mode 100644 index 0000000..c5fc1f8 --- /dev/null +++ b/ffmpeg/libavcodec/mss2dsp.c @@ -0,0 +1,156 @@ +/* + * Microsoft Screen 2 (aka Windows Media Video V9 Screen) decoder + * + * 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 + */ + +/** + * @file + * Microsoft Screen 2 (aka Windows Media Video V9 Screen) decoder DSP routines + */ + +#include "mss2dsp.h" +#include "libavutil/common.h" + +static av_always_inline void mss2_blit_wmv9_template(uint8_t *dst, + int dst_stride, + int gray, + int use_mask, + int maskcolor, + const uint8_t *mask, + int mask_stride, + const uint8_t *srcy, + int srcy_stride, + const uint8_t *srcu, + const uint8_t *srcv, + int srcuv_stride, + int w, int h) +{ + int i, j, k, r = -1; + while (++r < h) { + for (i = 0, j = 0, k = 0; i < w; j += (i & 1), i++, k += 3) { + if (!use_mask || mask[i] == maskcolor) { + if (gray) { + dst[k] = dst[k + 1] = dst[k + 2] = 0x80; + } else { + int y = srcy[i]; + int u = srcu[j] - 128; + int v = srcv[j] - 128; + dst[k] = av_clip_uint8(y + ( 91881 * v + 32768 >> 16)); + dst[k + 1] = av_clip_uint8(y + (-22554 * u - 46802 * v + 32768 >> 16)); + dst[k + 2] = av_clip_uint8(y + (116130 * u + 32768 >> 16)); + } + } + } + mask += mask_stride; + dst += dst_stride; + srcy += srcy_stride; + srcu += srcuv_stride * (r & 1); + srcv += srcuv_stride * (r & 1); + } +} + +static void mss2_blit_wmv9_c(uint8_t *dst, int dst_stride, + const uint8_t *srcy, int srcy_stride, + const uint8_t *srcu, const uint8_t *srcv, + int srcuv_stride, int w, int h) +{ + mss2_blit_wmv9_template(dst, dst_stride, 0, 0, + 0, NULL, 0, + srcy, srcy_stride, + srcu, srcv, srcuv_stride, + w, h); +} + +static void mss2_blit_wmv9_masked_c(uint8_t *dst, int dst_stride, + int maskcolor, const uint8_t *mask, + int mask_stride, + const uint8_t *srcy, int srcy_stride, + const uint8_t *srcu, const uint8_t *srcv, + int srcuv_stride, int w, int h) +{ + mss2_blit_wmv9_template(dst, dst_stride, 0, 1, + maskcolor, mask, mask_stride, + srcy, srcy_stride, + srcu, srcv, srcuv_stride, + w, h); +} + +static void mss2_gray_fill_masked_c(uint8_t *dst, int dst_stride, + int maskcolor, const uint8_t *mask, + int mask_stride, int w, int h) +{ + mss2_blit_wmv9_template(dst, dst_stride, 1, 1, + maskcolor, mask, mask_stride, + NULL, 0, + NULL, NULL, 0, + w, h); +} + +static void upsample_plane_c(uint8_t *plane, int plane_stride, int w, int h) +{ + uint8_t *src1, *src2, *dst1, *dst2, *p, a, b; + int i, j; + + if(!w || !h) + return; + + w += (w & 1); + h += (h & 1); + + j = h - 1; + + memcpy(plane + plane_stride * j, + plane + plane_stride * (j >> 1), + w); + + while ((j -= 2) > 0) { + dst1 = plane + plane_stride * (j + 1); + dst2 = plane + plane_stride * j; + src1 = plane + plane_stride * ((j + 1) >> 1); + src2 = plane + plane_stride * ( j >> 1); + + for (i = (w - 1) >> 1; i >= 0; i--) { + a = src1[i]; + b = src2[i]; + dst1[i] = (3 * a + b + 2) >> 2; + dst2[i] = (a + 3 * b + 2) >> 2; + } + } + + for (j = h - 1; j >= 0; j--) { + p = plane + plane_stride * j; + i = w - 1; + + p[i] = p[i >> 1]; + + while ((i -= 2) > 0) { + a = p[ i >> 1]; + b = p[(i + 1) >> 1]; + p[i] = (3 * a + b + 1) >> 2; + p[i + 1] = (a + 3 * b + 1) >> 2; + } + } +} + +av_cold void ff_mss2dsp_init(MSS2DSPContext* dsp) +{ + dsp->mss2_blit_wmv9 = mss2_blit_wmv9_c; + dsp->mss2_blit_wmv9_masked = mss2_blit_wmv9_masked_c; + dsp->mss2_gray_fill_masked = mss2_gray_fill_masked_c; + dsp->upsample_plane = upsample_plane_c; +} diff --git a/ffmpeg/libavcodec/mss2dsp.h b/ffmpeg/libavcodec/mss2dsp.h new file mode 100644 index 0000000..7368abb --- /dev/null +++ b/ffmpeg/libavcodec/mss2dsp.h @@ -0,0 +1,50 @@ +/* + * Microsoft Screen 2 (aka Windows Media Video V9 Screen) decoder + * + * 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 + */ + +/** + * @file + * Microsoft Screen 2 (aka Windows Media Video V9 Screen) decoder DSP routines + */ + +#ifndef AVCODEC_MSS2DSP_H +#define AVCODEC_MSS2DSP_H + +#include + +typedef struct MSS2DSPContext { + void (*mss2_blit_wmv9)(uint8_t *dst, int dst_stride, + const uint8_t *srcy, int srcy_stride, + const uint8_t *srcu, const uint8_t *srcv, + int srcuv_stride, int w, int h); + void (*mss2_blit_wmv9_masked)(uint8_t *dst, int dst_stride, + int maskcolor, const uint8_t *mask, + int mask_stride, + const uint8_t *srcy, int srcy_stride, + const uint8_t *srcu, const uint8_t *srcv, + int srcuv_stride, int w, int h); + void (*mss2_gray_fill_masked)(uint8_t *dst, int dst_stride, + int maskcolor, const uint8_t *mask, + int mask_stride, int w, int h); + void (*upsample_plane)(uint8_t *plane, int plane_stride, int w, int h); +} MSS2DSPContext; + +void ff_mss2dsp_init(MSS2DSPContext *dsp); + +#endif /* AVCODEC_MSS2DSP_H */ diff --git a/ffmpeg/libavcodec/mss3.c b/ffmpeg/libavcodec/mss3.c new file mode 100644 index 0000000..3cc484f --- /dev/null +++ b/ffmpeg/libavcodec/mss3.c @@ -0,0 +1,866 @@ +/* + * Microsoft Screen 3 (aka Microsoft ATC Screen) decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Microsoft Screen 3 (aka Microsoft ATC Screen) decoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "dsputil.h" +#include "internal.h" +#include "mss34dsp.h" + +#define HEADER_SIZE 27 + +#define MODEL2_SCALE 13 +#define MODEL_SCALE 15 +#define MODEL256_SEC_SCALE 9 + +typedef struct Model2 { + int upd_val, till_rescale; + unsigned zero_freq, zero_weight; + unsigned total_freq, total_weight; +} Model2; + +typedef struct Model { + int weights[16], freqs[16]; + int num_syms; + int tot_weight; + int upd_val, max_upd_val, till_rescale; +} Model; + +typedef struct Model256 { + int weights[256], freqs[256]; + int tot_weight; + int secondary[68]; + int sec_size; + int upd_val, max_upd_val, till_rescale; +} Model256; + +#define RAC_BOTTOM 0x01000000 +typedef struct RangeCoder { + const uint8_t *src, *src_end; + + uint32_t range, low; + int got_error; +} RangeCoder; + +enum BlockType { + FILL_BLOCK = 0, + IMAGE_BLOCK, + DCT_BLOCK, + HAAR_BLOCK, + SKIP_BLOCK +}; + +typedef struct BlockTypeContext { + int last_type; + Model bt_model[5]; +} BlockTypeContext; + +typedef struct FillBlockCoder { + int fill_val; + Model coef_model; +} FillBlockCoder; + +typedef struct ImageBlockCoder { + Model256 esc_model, vec_entry_model; + Model vec_size_model; + Model vq_model[125]; +} ImageBlockCoder; + +typedef struct DCTBlockCoder { + int *prev_dc; + int prev_dc_stride; + int prev_dc_height; + int quality; + uint16_t qmat[64]; + Model dc_model; + Model2 sign_model; + Model256 ac_model; +} DCTBlockCoder; + +typedef struct HaarBlockCoder { + int quality, scale; + Model256 coef_model; + Model coef_hi_model; +} HaarBlockCoder; + +typedef struct MSS3Context { + AVCodecContext *avctx; + AVFrame pic; + + int got_error; + RangeCoder coder; + BlockTypeContext btype[3]; + FillBlockCoder fill_coder[3]; + ImageBlockCoder image_coder[3]; + DCTBlockCoder dct_coder[3]; + HaarBlockCoder haar_coder[3]; + + int dctblock[64]; + int hblock[16 * 16]; +} MSS3Context; + + +static void model2_reset(Model2 *m) +{ + m->zero_weight = 1; + m->total_weight = 2; + m->zero_freq = 0x1000; + m->total_freq = 0x2000; + m->upd_val = 4; + m->till_rescale = 4; +} + +static void model2_update(Model2 *m, int bit) +{ + unsigned scale; + + if (!bit) + m->zero_weight++; + m->till_rescale--; + if (m->till_rescale) + return; + + m->total_weight += m->upd_val; + if (m->total_weight > 0x2000) { + m->total_weight = (m->total_weight + 1) >> 1; + m->zero_weight = (m->zero_weight + 1) >> 1; + if (m->total_weight == m->zero_weight) + m->total_weight = m->zero_weight + 1; + } + m->upd_val = m->upd_val * 5 >> 2; + if (m->upd_val > 64) + m->upd_val = 64; + scale = 0x80000000u / m->total_weight; + m->zero_freq = m->zero_weight * scale >> 18; + m->total_freq = m->total_weight * scale >> 18; + m->till_rescale = m->upd_val; +} + +static void model_update(Model *m, int val) +{ + int i, sum = 0; + unsigned scale; + + m->weights[val]++; + m->till_rescale--; + if (m->till_rescale) + return; + m->tot_weight += m->upd_val; + + if (m->tot_weight > 0x8000) { + m->tot_weight = 0; + for (i = 0; i < m->num_syms; i++) { + m->weights[i] = (m->weights[i] + 1) >> 1; + m->tot_weight += m->weights[i]; + } + } + scale = 0x80000000u / m->tot_weight; + for (i = 0; i < m->num_syms; i++) { + m->freqs[i] = sum * scale >> 16; + sum += m->weights[i]; + } + + m->upd_val = m->upd_val * 5 >> 2; + if (m->upd_val > m->max_upd_val) + m->upd_val = m->max_upd_val; + m->till_rescale = m->upd_val; +} + +static void model_reset(Model *m) +{ + int i; + + m->tot_weight = 0; + for (i = 0; i < m->num_syms - 1; i++) + m->weights[i] = 1; + m->weights[m->num_syms - 1] = 0; + + m->upd_val = m->num_syms; + m->till_rescale = 1; + model_update(m, m->num_syms - 1); + m->till_rescale = + m->upd_val = (m->num_syms + 6) >> 1; +} + +static av_cold void model_init(Model *m, int num_syms) +{ + m->num_syms = num_syms; + m->max_upd_val = 8 * num_syms + 48; + + model_reset(m); +} + +static void model256_update(Model256 *m, int val) +{ + int i, sum = 0; + unsigned scale; + int send, sidx = 1; + + m->weights[val]++; + m->till_rescale--; + if (m->till_rescale) + return; + m->tot_weight += m->upd_val; + + if (m->tot_weight > 0x8000) { + m->tot_weight = 0; + for (i = 0; i < 256; i++) { + m->weights[i] = (m->weights[i] + 1) >> 1; + m->tot_weight += m->weights[i]; + } + } + scale = 0x80000000u / m->tot_weight; + m->secondary[0] = 0; + for (i = 0; i < 256; i++) { + m->freqs[i] = sum * scale >> 16; + sum += m->weights[i]; + send = m->freqs[i] >> MODEL256_SEC_SCALE; + while (sidx <= send) + m->secondary[sidx++] = i - 1; + } + while (sidx < m->sec_size) + m->secondary[sidx++] = 255; + + m->upd_val = m->upd_val * 5 >> 2; + if (m->upd_val > m->max_upd_val) + m->upd_val = m->max_upd_val; + m->till_rescale = m->upd_val; +} + +static void model256_reset(Model256 *m) +{ + int i; + + for (i = 0; i < 255; i++) + m->weights[i] = 1; + m->weights[255] = 0; + + m->tot_weight = 0; + m->upd_val = 256; + m->till_rescale = 1; + model256_update(m, 255); + m->till_rescale = + m->upd_val = (256 + 6) >> 1; +} + +static av_cold void model256_init(Model256 *m) +{ + m->max_upd_val = 8 * 256 + 48; + m->sec_size = (1 << 6) + 2; + + model256_reset(m); +} + +static void rac_init(RangeCoder *c, const uint8_t *src, int size) +{ + int i; + + c->src = src; + c->src_end = src + size; + c->low = 0; + for (i = 0; i < FFMIN(size, 4); i++) + c->low = (c->low << 8) | *c->src++; + c->range = 0xFFFFFFFF; + c->got_error = 0; +} + +static void rac_normalise(RangeCoder *c) +{ + for (;;) { + c->range <<= 8; + c->low <<= 8; + if (c->src < c->src_end) { + c->low |= *c->src++; + } else if (!c->low) { + c->got_error = 1; + c->low = 1; + } + if (c->range >= RAC_BOTTOM) + return; + } +} + +static int rac_get_bit(RangeCoder *c) +{ + int bit; + + c->range >>= 1; + + bit = (c->range <= c->low); + if (bit) + c->low -= c->range; + + if (c->range < RAC_BOTTOM) + rac_normalise(c); + + return bit; +} + +static int rac_get_bits(RangeCoder *c, int nbits) +{ + int val; + + c->range >>= nbits; + val = c->low / c->range; + c->low -= c->range * val; + + if (c->range < RAC_BOTTOM) + rac_normalise(c); + + return val; +} + +static int rac_get_model2_sym(RangeCoder *c, Model2 *m) +{ + int bit, helper; + + helper = m->zero_freq * (c->range >> MODEL2_SCALE); + bit = (c->low >= helper); + if (bit) { + c->low -= helper; + c->range -= helper; + } else { + c->range = helper; + } + + if (c->range < RAC_BOTTOM) + rac_normalise(c); + + model2_update(m, bit); + + return bit; +} + +static int rac_get_model_sym(RangeCoder *c, Model *m) +{ + int prob, prob2, helper, val; + int end, end2; + + prob = 0; + prob2 = c->range; + c->range >>= MODEL_SCALE; + val = 0; + end = m->num_syms >> 1; + end2 = m->num_syms; + do { + helper = m->freqs[end] * c->range; + if (helper <= c->low) { + val = end; + prob = helper; + } else { + end2 = end; + prob2 = helper; + } + end = (end2 + val) >> 1; + } while (end != val); + c->low -= prob; + c->range = prob2 - prob; + if (c->range < RAC_BOTTOM) + rac_normalise(c); + + model_update(m, val); + + return val; +} + +static int rac_get_model256_sym(RangeCoder *c, Model256 *m) +{ + int prob, prob2, helper, val; + int start, end; + int ssym; + + prob2 = c->range; + c->range >>= MODEL_SCALE; + + helper = c->low / c->range; + ssym = helper >> MODEL256_SEC_SCALE; + val = m->secondary[ssym]; + + end = start = m->secondary[ssym + 1] + 1; + while (end > val + 1) { + ssym = (end + val) >> 1; + if (m->freqs[ssym] <= helper) { + end = start; + val = ssym; + } else { + end = (end + val) >> 1; + start = ssym; + } + } + prob = m->freqs[val] * c->range; + if (val != 255) + prob2 = m->freqs[val + 1] * c->range; + + c->low -= prob; + c->range = prob2 - prob; + if (c->range < RAC_BOTTOM) + rac_normalise(c); + + model256_update(m, val); + + return val; +} + +static int decode_block_type(RangeCoder *c, BlockTypeContext *bt) +{ + bt->last_type = rac_get_model_sym(c, &bt->bt_model[bt->last_type]); + + return bt->last_type; +} + +static int decode_coeff(RangeCoder *c, Model *m) +{ + int val, sign; + + val = rac_get_model_sym(c, m); + if (val) { + sign = rac_get_bit(c); + if (val > 1) { + val--; + val = (1 << val) + rac_get_bits(c, val); + } + if (!sign) + val = -val; + } + + return val; +} + +static void decode_fill_block(RangeCoder *c, FillBlockCoder *fc, + uint8_t *dst, int stride, int block_size) +{ + int i; + + fc->fill_val += decode_coeff(c, &fc->coef_model); + + for (i = 0; i < block_size; i++, dst += stride) + memset(dst, fc->fill_val, block_size); +} + +static void decode_image_block(RangeCoder *c, ImageBlockCoder *ic, + uint8_t *dst, int stride, int block_size) +{ + int i, j; + int vec_size; + int vec[4]; + int prev_line[16]; + int A, B, C; + + vec_size = rac_get_model_sym(c, &ic->vec_size_model) + 2; + for (i = 0; i < vec_size; i++) + vec[i] = rac_get_model256_sym(c, &ic->vec_entry_model); + for (; i < 4; i++) + vec[i] = 0; + memset(prev_line, 0, sizeof(prev_line)); + + for (j = 0; j < block_size; j++) { + A = 0; + B = 0; + for (i = 0; i < block_size; i++) { + C = B; + B = prev_line[i]; + A = rac_get_model_sym(c, &ic->vq_model[A + B * 5 + C * 25]); + + prev_line[i] = A; + if (A < 4) + dst[i] = vec[A]; + else + dst[i] = rac_get_model256_sym(c, &ic->esc_model); + } + dst += stride; + } +} + +static int decode_dct(RangeCoder *c, DCTBlockCoder *bc, int *block, + int bx, int by) +{ + int skip, val, sign, pos = 1, zz_pos, dc; + int blk_pos = bx + by * bc->prev_dc_stride; + + memset(block, 0, sizeof(*block) * 64); + + dc = decode_coeff(c, &bc->dc_model); + if (by) { + if (bx) { + int l, tl, t; + + l = bc->prev_dc[blk_pos - 1]; + tl = bc->prev_dc[blk_pos - 1 - bc->prev_dc_stride]; + t = bc->prev_dc[blk_pos - bc->prev_dc_stride]; + + if (FFABS(t - tl) <= FFABS(l - tl)) + dc += l; + else + dc += t; + } else { + dc += bc->prev_dc[blk_pos - bc->prev_dc_stride]; + } + } else if (bx) { + dc += bc->prev_dc[bx - 1]; + } + bc->prev_dc[blk_pos] = dc; + block[0] = dc * bc->qmat[0]; + + while (pos < 64) { + val = rac_get_model256_sym(c, &bc->ac_model); + if (!val) + return 0; + if (val == 0xF0) { + pos += 16; + continue; + } + skip = val >> 4; + val = val & 0xF; + if (!val) + return -1; + pos += skip; + if (pos >= 64) + return -1; + + sign = rac_get_model2_sym(c, &bc->sign_model); + if (val > 1) { + val--; + val = (1 << val) + rac_get_bits(c, val); + } + if (!sign) + val = -val; + + zz_pos = ff_zigzag_direct[pos]; + block[zz_pos] = val * bc->qmat[zz_pos]; + pos++; + } + + return pos == 64 ? 0 : -1; +} + +static void decode_dct_block(RangeCoder *c, DCTBlockCoder *bc, + uint8_t *dst, int stride, int block_size, + int *block, int mb_x, int mb_y) +{ + int i, j; + int bx, by; + int nblocks = block_size >> 3; + + bx = mb_x * nblocks; + by = mb_y * nblocks; + + for (j = 0; j < nblocks; j++) { + for (i = 0; i < nblocks; i++) { + if (decode_dct(c, bc, block, bx + i, by + j)) { + c->got_error = 1; + return; + } + ff_mss34_dct_put(dst + i * 8, stride, block); + } + dst += 8 * stride; + } +} + +static void decode_haar_block(RangeCoder *c, HaarBlockCoder *hc, + uint8_t *dst, int stride, int block_size, + int *block) +{ + const int hsize = block_size >> 1; + int A, B, C, D, t1, t2, t3, t4; + int i, j; + + for (j = 0; j < block_size; j++) { + for (i = 0; i < block_size; i++) { + if (i < hsize && j < hsize) + block[i] = rac_get_model256_sym(c, &hc->coef_model); + else + block[i] = decode_coeff(c, &hc->coef_hi_model); + block[i] *= hc->scale; + } + block += block_size; + } + block -= block_size * block_size; + + for (j = 0; j < hsize; j++) { + for (i = 0; i < hsize; i++) { + A = block[i]; + B = block[i + hsize]; + C = block[i + hsize * block_size]; + D = block[i + hsize * block_size + hsize]; + + t1 = A - B; + t2 = C - D; + t3 = A + B; + t4 = C + D; + dst[i * 2] = av_clip_uint8(t1 - t2); + dst[i * 2 + stride] = av_clip_uint8(t1 + t2); + dst[i * 2 + 1] = av_clip_uint8(t3 - t4); + dst[i * 2 + 1 + stride] = av_clip_uint8(t3 + t4); + } + block += block_size; + dst += stride * 2; + } +} + +static void reset_coders(MSS3Context *ctx, int quality) +{ + int i, j; + + for (i = 0; i < 3; i++) { + ctx->btype[i].last_type = SKIP_BLOCK; + for (j = 0; j < 5; j++) + model_reset(&ctx->btype[i].bt_model[j]); + ctx->fill_coder[i].fill_val = 0; + model_reset(&ctx->fill_coder[i].coef_model); + model256_reset(&ctx->image_coder[i].esc_model); + model256_reset(&ctx->image_coder[i].vec_entry_model); + model_reset(&ctx->image_coder[i].vec_size_model); + for (j = 0; j < 125; j++) + model_reset(&ctx->image_coder[i].vq_model[j]); + if (ctx->dct_coder[i].quality != quality) { + ctx->dct_coder[i].quality = quality; + ff_mss34_gen_quant_mat(ctx->dct_coder[i].qmat, quality, !i); + } + memset(ctx->dct_coder[i].prev_dc, 0, + sizeof(*ctx->dct_coder[i].prev_dc) * + ctx->dct_coder[i].prev_dc_stride * + ctx->dct_coder[i].prev_dc_height); + model_reset(&ctx->dct_coder[i].dc_model); + model2_reset(&ctx->dct_coder[i].sign_model); + model256_reset(&ctx->dct_coder[i].ac_model); + if (ctx->haar_coder[i].quality != quality) { + ctx->haar_coder[i].quality = quality; + ctx->haar_coder[i].scale = 17 - 7 * quality / 50; + } + model_reset(&ctx->haar_coder[i].coef_hi_model); + model256_reset(&ctx->haar_coder[i].coef_model); + } +} + +static av_cold void init_coders(MSS3Context *ctx) +{ + int i, j; + + for (i = 0; i < 3; i++) { + for (j = 0; j < 5; j++) + model_init(&ctx->btype[i].bt_model[j], 5); + model_init(&ctx->fill_coder[i].coef_model, 12); + model256_init(&ctx->image_coder[i].esc_model); + model256_init(&ctx->image_coder[i].vec_entry_model); + model_init(&ctx->image_coder[i].vec_size_model, 3); + for (j = 0; j < 125; j++) + model_init(&ctx->image_coder[i].vq_model[j], 5); + model_init(&ctx->dct_coder[i].dc_model, 12); + model256_init(&ctx->dct_coder[i].ac_model); + model_init(&ctx->haar_coder[i].coef_hi_model, 12); + model256_init(&ctx->haar_coder[i].coef_model); + } +} + +static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MSS3Context *c = avctx->priv_data; + RangeCoder *acoder = &c->coder; + GetByteContext gb; + uint8_t *dst[3]; + int dec_width, dec_height, dec_x, dec_y, quality, keyframe; + int x, y, i, mb_width, mb_height, blk_size, btype; + int ret; + + if (buf_size < HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, + "Frame should have at least %d bytes, got %d instead\n", + HEADER_SIZE, buf_size); + return AVERROR_INVALIDDATA; + } + + bytestream2_init(&gb, buf, buf_size); + keyframe = bytestream2_get_be32(&gb); + if (keyframe & ~0x301) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame type %X\n", keyframe); + return AVERROR_INVALIDDATA; + } + keyframe = !(keyframe & 1); + bytestream2_skip(&gb, 6); + dec_x = bytestream2_get_be16(&gb); + dec_y = bytestream2_get_be16(&gb); + dec_width = bytestream2_get_be16(&gb); + dec_height = bytestream2_get_be16(&gb); + + if (dec_x + dec_width > avctx->width || + dec_y + dec_height > avctx->height || + (dec_width | dec_height) & 0xF) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d +%d,%d\n", + dec_width, dec_height, dec_x, dec_y); + return AVERROR_INVALIDDATA; + } + bytestream2_skip(&gb, 4); + quality = bytestream2_get_byte(&gb); + if (quality < 1 || quality > 100) { + av_log(avctx, AV_LOG_ERROR, "Invalid quality setting %d\n", quality); + return AVERROR_INVALIDDATA; + } + bytestream2_skip(&gb, 4); + + if (keyframe && !bytestream2_get_bytes_left(&gb)) { + av_log(avctx, AV_LOG_ERROR, "Keyframe without data found\n"); + return AVERROR_INVALIDDATA; + } + if (!keyframe && c->got_error) + return buf_size; + c->got_error = 0; + + if ((ret = ff_reget_buffer(avctx, &c->pic)) < 0) + return ret; + c->pic.key_frame = keyframe; + c->pic.pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + if (!bytestream2_get_bytes_left(&gb)) { + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + *got_frame = 1; + + return buf_size; + } + + reset_coders(c, quality); + + rac_init(acoder, buf + HEADER_SIZE, buf_size - HEADER_SIZE); + + mb_width = dec_width >> 4; + mb_height = dec_height >> 4; + dst[0] = c->pic.data[0] + dec_x + dec_y * c->pic.linesize[0]; + dst[1] = c->pic.data[1] + dec_x / 2 + (dec_y / 2) * c->pic.linesize[1]; + dst[2] = c->pic.data[2] + dec_x / 2 + (dec_y / 2) * c->pic.linesize[2]; + for (y = 0; y < mb_height; y++) { + for (x = 0; x < mb_width; x++) { + for (i = 0; i < 3; i++) { + blk_size = 8 << !i; + + btype = decode_block_type(acoder, c->btype + i); + switch (btype) { + case FILL_BLOCK: + decode_fill_block(acoder, c->fill_coder + i, + dst[i] + x * blk_size, + c->pic.linesize[i], blk_size); + break; + case IMAGE_BLOCK: + decode_image_block(acoder, c->image_coder + i, + dst[i] + x * blk_size, + c->pic.linesize[i], blk_size); + break; + case DCT_BLOCK: + decode_dct_block(acoder, c->dct_coder + i, + dst[i] + x * blk_size, + c->pic.linesize[i], blk_size, + c->dctblock, x, y); + break; + case HAAR_BLOCK: + decode_haar_block(acoder, c->haar_coder + i, + dst[i] + x * blk_size, + c->pic.linesize[i], blk_size, + c->hblock); + break; + } + if (c->got_error || acoder->got_error) { + av_log(avctx, AV_LOG_ERROR, "Error decoding block %d,%d\n", + x, y); + c->got_error = 1; + return AVERROR_INVALIDDATA; + } + } + } + dst[0] += c->pic.linesize[0] * 16; + dst[1] += c->pic.linesize[1] * 8; + dst[2] += c->pic.linesize[2] * 8; + } + + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int mss3_decode_init(AVCodecContext *avctx) +{ + MSS3Context * const c = avctx->priv_data; + int i; + + c->avctx = avctx; + + if ((avctx->width & 0xF) || (avctx->height & 0xF)) { + av_log(avctx, AV_LOG_ERROR, + "Image dimensions should be a multiple of 16.\n"); + return AVERROR_INVALIDDATA; + } + + c->got_error = 0; + for (i = 0; i < 3; i++) { + int b_width = avctx->width >> (2 + !!i); + int b_height = avctx->height >> (2 + !!i); + c->dct_coder[i].prev_dc_stride = b_width; + c->dct_coder[i].prev_dc_height = b_height; + c->dct_coder[i].prev_dc = av_malloc(sizeof(*c->dct_coder[i].prev_dc) * + b_width * b_height); + if (!c->dct_coder[i].prev_dc) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate buffer\n"); + while (i >= 0) { + av_freep(&c->dct_coder[i].prev_dc); + i--; + } + return AVERROR(ENOMEM); + } + } + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + init_coders(c); + + return 0; +} + +static av_cold int mss3_decode_end(AVCodecContext *avctx) +{ + MSS3Context * const c = avctx->priv_data; + int i; + + av_frame_unref(&c->pic); + for (i = 0; i < 3; i++) + av_freep(&c->dct_coder[i].prev_dc); + + return 0; +} + +AVCodec ff_msa1_decoder = { + .name = "msa1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSA1, + .priv_data_size = sizeof(MSS3Context), + .init = mss3_decode_init, + .close = mss3_decode_end, + .decode = mss3_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MS ATC Screen"), +}; diff --git a/ffmpeg/libavcodec/mss34dsp.c b/ffmpeg/libavcodec/mss34dsp.c new file mode 100644 index 0000000..e4d4299 --- /dev/null +++ b/ffmpeg/libavcodec/mss34dsp.c @@ -0,0 +1,114 @@ +/* + * Common stuff for some Microsoft Screen codecs + * Copyright (C) 2012 Konstantin Shishkov + * + * 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 "libavutil/common.h" +#include "mss34dsp.h" + +static const uint8_t luma_quant[64] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static const uint8_t chroma_quant[64] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +void ff_mss34_gen_quant_mat(uint16_t *qmat, int quality, int luma) +{ + int i; + const uint8_t *qsrc = luma ? luma_quant : chroma_quant; + + if (quality >= 50) { + int scale = 200 - 2 * quality; + + for (i = 0; i < 64; i++) + qmat[i] = (qsrc[i] * scale + 50) / 100; + } else { + for (i = 0; i < 64; i++) + qmat[i] = (5000 * qsrc[i] / quality + 50) / 100; + } +} + +#define DCT_TEMPLATE(blk, step, SOP, shift) \ + const int t0 = -39409 * blk[7 * step] - 58980 * blk[1 * step]; \ + const int t1 = 39410 * blk[1 * step] - 58980 * blk[7 * step]; \ + const int t2 = -33410 * blk[5 * step] - 167963 * blk[3 * step]; \ + const int t3 = 33410 * blk[3 * step] - 167963 * blk[5 * step]; \ + const int t4 = blk[3 * step] + blk[7 * step]; \ + const int t5 = blk[1 * step] + blk[5 * step]; \ + const int t6 = 77062 * t4 + 51491 * t5; \ + const int t7 = 77062 * t5 - 51491 * t4; \ + const int t8 = 35470 * blk[2 * step] - 85623 * blk[6 * step]; \ + const int t9 = 35470 * blk[6 * step] + 85623 * blk[2 * step]; \ + const int tA = SOP(blk[0 * step] - blk[4 * step]); \ + const int tB = SOP(blk[0 * step] + blk[4 * step]); \ + \ + blk[0 * step] = ( t1 + t6 + t9 + tB) >> shift; \ + blk[1 * step] = ( t3 + t7 + t8 + tA) >> shift; \ + blk[2 * step] = ( t2 + t6 - t8 + tA) >> shift; \ + blk[3 * step] = ( t0 + t7 - t9 + tB) >> shift; \ + blk[4 * step] = (-(t0 + t7) - t9 + tB) >> shift; \ + blk[5 * step] = (-(t2 + t6) - t8 + tA) >> shift; \ + blk[6 * step] = (-(t3 + t7) + t8 + tA) >> shift; \ + blk[7 * step] = (-(t1 + t6) + t9 + tB) >> shift; \ + +#define SOP_ROW(a) ((a) << 16) + 0x2000 +#define SOP_COL(a) ((a + 32) << 16) + +void ff_mss34_dct_put(uint8_t *dst, int stride, int *block) +{ + int i, j; + int *ptr; + + ptr = block; + for (i = 0; i < 8; i++) { + DCT_TEMPLATE(ptr, 1, SOP_ROW, 13); + ptr += 8; + } + + ptr = block; + for (i = 0; i < 8; i++) { + DCT_TEMPLATE(ptr, 8, SOP_COL, 22); + ptr++; + } + + ptr = block; + for (j = 0; j < 8; j++) { + for (i = 0; i < 8; i++) + dst[i] = av_clip_uint8(ptr[i] + 128); + dst += stride; + ptr += 8; + } +} diff --git a/ffmpeg/libavcodec/mss34dsp.h b/ffmpeg/libavcodec/mss34dsp.h new file mode 100644 index 0000000..2f9827d --- /dev/null +++ b/ffmpeg/libavcodec/mss34dsp.h @@ -0,0 +1,45 @@ +/* + * Common stuff for some Microsoft Screen codecs + * Copyright (C) 2012 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_MSS34DSP_H +#define AVCODEC_MSS34DSP_H + +#include + +/** + * Generate quantisation matrix for given quality. + * + * @param qmat destination matrix + * @param quality quality setting (1-100) + * @param luma generate quantisation matrix for luma or chroma + */ +void ff_mss34_gen_quant_mat(uint16_t *qmat, int quality, int luma); + +/** + * Transform and output DCT block. + * + * @param dst output plane + * @param stride output plane stride + * @param block block to transform and output + */ +void ff_mss34_dct_put(uint8_t *dst, int stride, int *block); + +#endif /* AVCODEC_MSS34DSP_H */ diff --git a/ffmpeg/libavcodec/mss4.c b/ffmpeg/libavcodec/mss4.c new file mode 100644 index 0000000..391805f --- /dev/null +++ b/ffmpeg/libavcodec/mss4.c @@ -0,0 +1,677 @@ +/* + * Microsoft Screen 4 (aka Microsoft Expression Encoder Screen) decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Microsoft Screen 4 (aka Microsoft Titanium Screen 2, + * aka Microsoft Expression Encoder Screen) decoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "dsputil.h" +#include "get_bits.h" +#include "internal.h" +#include "mss34dsp.h" +#include "unary.h" + +#define HEADER_SIZE 8 + +enum FrameType { + INTRA_FRAME = 0, + INTER_FRAME, + SKIP_FRAME +}; + +enum BlockType { + SKIP_BLOCK = 0, + DCT_BLOCK, + IMAGE_BLOCK, +}; + +enum CachePos { + LEFT = 0, + TOP_LEFT, + TOP, +}; + +static const uint8_t mss4_dc_vlc_lens[2][16] = { + { 0, 1, 5, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 3, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0 } +}; + +static const uint8_t mss4_ac_vlc_lens[2][16] = { + { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125 }, + { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119 } +}; + +static const uint8_t mss4_ac_vlc_syms[2][162] = { + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, + 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, + 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, + 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, + 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, + 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, + 0xF9, 0xFA }, + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, + 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, + 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, + 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, + 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, + 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, + 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, + 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, + 0xF9, 0xFA } +}; + +static const uint8_t vec_len_syms[2][4] = { + { 4, 2, 3, 1 }, + { 4, 1, 2, 3 } +}; + +static const uint8_t mss4_vec_entry_vlc_lens[2][16] = { + { 0, 2, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 5, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const uint8_t mss4_vec_entry_vlc_syms[2][9] = { + { 0, 7, 6, 5, 8, 4, 3, 1, 2 }, + { 0, 2, 3, 4, 5, 6, 7, 1, 8 } +}; + +#define MAX_ENTRIES 162 + +typedef struct MSS4Context { + AVFrame pic; + + VLC dc_vlc[2], ac_vlc[2]; + VLC vec_entry_vlc[2]; + int block[64]; + uint8_t imgbuf[3][16 * 16]; + + int quality; + uint16_t quant_mat[2][64]; + + int *prev_dc[3]; + int dc_stride[3]; + int dc_cache[4][4]; + + int prev_vec[3][4]; +} MSS4Context; + +static av_cold int mss4_init_vlc(VLC *vlc, const uint8_t *lens, + const uint8_t *syms, int num_syms) +{ + uint8_t bits[MAX_ENTRIES]; + uint16_t codes[MAX_ENTRIES]; + int i, j; + int prefix = 0, max_bits = 0, idx = 0; + + for (i = 0; i < 16; i++) { + for (j = 0; j < lens[i]; j++) { + bits[idx] = i + 1; + codes[idx] = prefix++; + max_bits = i + 1; + idx++; + } + prefix <<= 1; + } + + return ff_init_vlc_sparse(vlc, FFMIN(max_bits, 9), num_syms, bits, 1, 1, + codes, 2, 2, syms, 1, 1, 0); +} + +static av_cold int mss4_init_vlcs(MSS4Context *ctx) +{ + int ret, i; + + for (i = 0; i < 2; i++) { + ret = mss4_init_vlc(&ctx->dc_vlc[i], mss4_dc_vlc_lens[i], NULL, 12); + if (ret) + return ret; + ret = mss4_init_vlc(&ctx->ac_vlc[i], mss4_ac_vlc_lens[i], + mss4_ac_vlc_syms[i], 162); + if (ret) + return ret; + ret = mss4_init_vlc(&ctx->vec_entry_vlc[i], mss4_vec_entry_vlc_lens[i], + mss4_vec_entry_vlc_syms[i], 9); + if (ret) + return ret; + } + return 0; +} + +static av_cold void mss4_free_vlcs(MSS4Context *ctx) +{ + int i; + + for (i = 0; i < 2; i++) { + ff_free_vlc(&ctx->dc_vlc[i]); + ff_free_vlc(&ctx->ac_vlc[i]); + ff_free_vlc(&ctx->vec_entry_vlc[i]); + } +} + +/* This function returns values in the range + * (-range + 1; -range/2] U [range/2; range - 1) + * i.e. + * nbits = 0 -> 0 + * nbits = 1 -> -1, 1 + * nbits = 2 -> -3, -2, 2, 3 + */ +static av_always_inline int get_coeff_bits(GetBitContext *gb, int nbits) +{ + int val; + + if (!nbits) + return 0; + + val = get_bits(gb, nbits); + if (val < (1 << (nbits - 1))) + val -= (1 << nbits) - 1; + + return val; +} + +static inline int get_coeff(GetBitContext *gb, VLC *vlc) +{ + int val = get_vlc2(gb, vlc->table, vlc->bits, 2); + + return get_coeff_bits(gb, val); +} + +static int mss4_decode_dct(GetBitContext *gb, VLC *dc_vlc, VLC *ac_vlc, + int *block, int *dc_cache, + int bx, int by, uint16_t *quant_mat) +{ + int skip, val, pos = 1, zz_pos, dc; + + memset(block, 0, sizeof(*block) * 64); + + dc = get_coeff(gb, dc_vlc); + // DC prediction is the same as in MSS3 + if (by) { + if (bx) { + int l, tl, t; + + l = dc_cache[LEFT]; + tl = dc_cache[TOP_LEFT]; + t = dc_cache[TOP]; + + if (FFABS(t - tl) <= FFABS(l - tl)) + dc += l; + else + dc += t; + } else { + dc += dc_cache[TOP]; + } + } else if (bx) { + dc += dc_cache[LEFT]; + } + dc_cache[LEFT] = dc; + block[0] = dc * quant_mat[0]; + + while (pos < 64) { + val = get_vlc2(gb, ac_vlc->table, 9, 2); + if (!val) + return 0; + if (val == -1) + return -1; + if (val == 0xF0) { + pos += 16; + continue; + } + skip = val >> 4; + val = get_coeff_bits(gb, val & 0xF); + pos += skip; + if (pos >= 64) + return -1; + + zz_pos = ff_zigzag_direct[pos]; + block[zz_pos] = val * quant_mat[zz_pos]; + pos++; + } + + return pos == 64 ? 0 : -1; +} + +static int mss4_decode_dct_block(MSS4Context *c, GetBitContext *gb, + uint8_t *dst[3], int mb_x, int mb_y) +{ + int i, j, k, ret; + uint8_t *out = dst[0]; + + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++) { + int xpos = mb_x * 2 + i; + c->dc_cache[j][TOP_LEFT] = c->dc_cache[j][TOP]; + c->dc_cache[j][TOP] = c->prev_dc[0][mb_x * 2 + i]; + ret = mss4_decode_dct(gb, c->dc_vlc, c->ac_vlc, c->block, + c->dc_cache[j], + xpos, mb_y * 2 + j, c->quant_mat[0]); + if (ret) + return ret; + c->prev_dc[0][mb_x * 2 + i] = c->dc_cache[j][LEFT]; + + ff_mss34_dct_put(out + xpos * 8, c->pic.linesize[0], + c->block); + } + out += 8 * c->pic.linesize[0]; + } + + for (i = 1; i < 3; i++) { + c->dc_cache[i + 1][TOP_LEFT] = c->dc_cache[i + 1][TOP]; + c->dc_cache[i + 1][TOP] = c->prev_dc[i][mb_x]; + ret = mss4_decode_dct(gb, c->dc_vlc + 1, c->ac_vlc + 1, + c->block, c->dc_cache[i + 1], mb_x, mb_y, + c->quant_mat[1]); + if (ret) + return ret; + c->prev_dc[i][mb_x] = c->dc_cache[i + 1][LEFT]; + + ff_mss34_dct_put(c->imgbuf[i], 8, c->block); + out = dst[i] + mb_x * 16; + // Since the DCT block is coded as YUV420 and the whole frame as YUV444, + // we need to scale chroma. + for (j = 0; j < 16; j++) { + for (k = 0; k < 8; k++) + AV_WN16A(out + k * 2, c->imgbuf[i][k + (j & ~1) * 4] * 0x101); + out += c->pic.linesize[i]; + } + } + + return 0; +} + +static void read_vec_pos(GetBitContext *gb, int *vec_pos, int *sel_flag, + int *sel_len, int *prev) +{ + int i, y_flag = 0; + + for (i = 2; i >= 0; i--) { + if (!sel_flag[i]) { + vec_pos[i] = 0; + continue; + } + if ((!i && !y_flag) || get_bits1(gb)) { + if (sel_len[i] > 0) { + int pval = prev[i]; + vec_pos[i] = get_bits(gb, sel_len[i]); + if (vec_pos[i] >= pval) + vec_pos[i]++; + } else { + vec_pos[i] = !prev[i]; + } + y_flag = 1; + } else { + vec_pos[i] = prev[i]; + } + } +} + +static int get_value_cached(GetBitContext *gb, int vec_pos, uint8_t *vec, + int vec_size, int component, int shift, int *prev) +{ + if (vec_pos < vec_size) + return vec[vec_pos]; + if (!get_bits1(gb)) + return prev[component]; + prev[component] = get_bits(gb, 8 - shift) << shift; + return prev[component]; +} + +#define MKVAL(vals) (vals[0] | (vals[1] << 3) | (vals[2] << 6)) + +/* Image mode - the hardest to comprehend MSS4 coding mode. + * + * In this mode all three 16x16 blocks are coded together with a method + * remotely similar to the methods employed in MSS1-MSS3. + * The idea is that every component has a vector of 1-4 most common symbols + * and an escape mode for reading new value from the bitstream. Decoding + * consists of retrieving pixel values from the vector or reading new ones + * from the bitstream; depending on flags read from the bitstream, these vector + * positions can be updated or reused from the state of the previous line + * or previous pixel. + */ +static int mss4_decode_image_block(MSS4Context *ctx, GetBitContext *gb, + uint8_t *picdst[3], int mb_x, int mb_y) +{ + uint8_t vec[3][4]; + int vec_len[3]; + int sel_len[3], sel_flag[3]; + int i, j, k, mode, split; + int prev_vec1 = 0, prev_split = 0; + int vals[3] = { 0 }; + int prev_pix[3] = { 0 }; + int prev_mode[16] = { 0 }; + uint8_t *dst[3]; + + const int val_shift = ctx->quality == 100 ? 0 : 2; + + for (i = 0; i < 3; i++) + dst[i] = ctx->imgbuf[i]; + + for (i = 0; i < 3; i++) { + vec_len[i] = vec_len_syms[!!i][get_unary(gb, 0, 3)]; + for (j = 0; j < vec_len[i]; j++) { + vec[i][j] = get_coeff(gb, &ctx->vec_entry_vlc[!!i]); + vec[i][j] += ctx->prev_vec[i][j]; + ctx->prev_vec[i][j] = vec[i][j]; + } + sel_flag[i] = vec_len[i] > 1; + sel_len[i] = vec_len[i] > 2 ? vec_len[i] - 2 : 0; + } + + for (j = 0; j < 16; j++) { + if (get_bits1(gb)) { + split = 0; + if (get_bits1(gb)) { + prev_mode[0] = 0; + vals[0] = vals[1] = vals[2] = 0; + mode = 2; + } else { + mode = get_bits1(gb); + if (mode) + split = get_bits(gb, 4); + } + for (i = 0; i < 16; i++) { + if (mode <= 1) { + vals[0] = prev_mode[i] & 7; + vals[1] = (prev_mode[i] >> 3) & 7; + vals[2] = prev_mode[i] >> 6; + if (mode == 1 && i == split) { + read_vec_pos(gb, vals, sel_flag, sel_len, vals); + } + } else if (mode == 2) { + if (get_bits1(gb)) + read_vec_pos(gb, vals, sel_flag, sel_len, vals); + } + for (k = 0; k < 3; k++) + *dst[k]++ = get_value_cached(gb, vals[k], vec[k], + vec_len[k], k, + val_shift, prev_pix); + prev_mode[i] = MKVAL(vals); + } + } else { + if (get_bits1(gb)) { + split = get_bits(gb, 4); + if (split >= prev_split) + split++; + prev_split = split; + } else { + split = prev_split; + } + if (split) { + vals[0] = prev_mode[0] & 7; + vals[1] = (prev_mode[0] >> 3) & 7; + vals[2] = prev_mode[0] >> 6; + for (i = 0; i < 3; i++) { + for (k = 0; k < split; k++) { + *dst[i]++ = get_value_cached(gb, vals[i], vec[i], + vec_len[i], i, val_shift, + prev_pix); + prev_mode[k] = MKVAL(vals); + } + } + } + + if (split != 16) { + vals[0] = prev_vec1 & 7; + vals[1] = (prev_vec1 >> 3) & 7; + vals[2] = prev_vec1 >> 6; + if (get_bits1(gb)) { + read_vec_pos(gb, vals, sel_flag, sel_len, vals); + prev_vec1 = MKVAL(vals); + } + for (i = 0; i < 3; i++) { + for (k = 0; k < 16 - split; k++) { + *dst[i]++ = get_value_cached(gb, vals[i], vec[i], + vec_len[i], i, val_shift, + prev_pix); + prev_mode[split + k] = MKVAL(vals); + } + } + } + } + } + + for (i = 0; i < 3; i++) + for (j = 0; j < 16; j++) + memcpy(picdst[i] + mb_x * 16 + j * ctx->pic.linesize[i], + ctx->imgbuf[i] + j * 16, 16); + + return 0; +} + +static inline void mss4_update_dc_cache(MSS4Context *c, int mb_x) +{ + int i; + + c->dc_cache[0][TOP] = c->prev_dc[0][mb_x * 2 + 1]; + c->dc_cache[0][LEFT] = 0; + c->dc_cache[1][TOP] = 0; + c->dc_cache[1][LEFT] = 0; + + for (i = 0; i < 2; i++) + c->prev_dc[0][mb_x * 2 + i] = 0; + + for (i = 1; i < 3; i++) { + c->dc_cache[i + 1][TOP] = c->prev_dc[i][mb_x]; + c->dc_cache[i + 1][LEFT] = 0; + c->prev_dc[i][mb_x] = 0; + } +} + +static int mss4_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MSS4Context *c = avctx->priv_data; + GetBitContext gb; + GetByteContext bc; + uint8_t *dst[3]; + int width, height, quality, frame_type; + int x, y, i, mb_width, mb_height, blk_type; + int ret; + + if (buf_size < HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, + "Frame should have at least %d bytes, got %d instead\n", + HEADER_SIZE, buf_size); + return AVERROR_INVALIDDATA; + } + + bytestream2_init(&bc, buf, buf_size); + width = bytestream2_get_be16(&bc); + height = bytestream2_get_be16(&bc); + bytestream2_skip(&bc, 2); + quality = bytestream2_get_byte(&bc); + frame_type = bytestream2_get_byte(&bc); + + if (width > avctx->width || + height != avctx->height) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d\n", + width, height); + return AVERROR_INVALIDDATA; + } + if (quality < 1 || quality > 100) { + av_log(avctx, AV_LOG_ERROR, "Invalid quality setting %d\n", quality); + return AVERROR_INVALIDDATA; + } + if ((frame_type & ~3) || frame_type == 3) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame type %d\n", frame_type); + return AVERROR_INVALIDDATA; + } + + if (frame_type != SKIP_FRAME && !bytestream2_get_bytes_left(&bc)) { + av_log(avctx, AV_LOG_ERROR, + "Empty frame found but it is not a skip frame.\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_reget_buffer(avctx, &c->pic)) < 0) + return ret; + c->pic.key_frame = (frame_type == INTRA_FRAME); + c->pic.pict_type = (frame_type == INTRA_FRAME) ? AV_PICTURE_TYPE_I + : AV_PICTURE_TYPE_P; + if (frame_type == SKIP_FRAME) { + *got_frame = 1; + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + return buf_size; + } + + if (c->quality != quality) { + c->quality = quality; + for (i = 0; i < 2; i++) + ff_mss34_gen_quant_mat(c->quant_mat[i], quality, !i); + } + + init_get_bits(&gb, buf + HEADER_SIZE, (buf_size - HEADER_SIZE) * 8); + + mb_width = FFALIGN(width, 16) >> 4; + mb_height = FFALIGN(height, 16) >> 4; + dst[0] = c->pic.data[0]; + dst[1] = c->pic.data[1]; + dst[2] = c->pic.data[2]; + + memset(c->prev_vec, 0, sizeof(c->prev_vec)); + for (y = 0; y < mb_height; y++) { + memset(c->dc_cache, 0, sizeof(c->dc_cache)); + for (x = 0; x < mb_width; x++) { + blk_type = decode012(&gb); + switch (blk_type) { + case DCT_BLOCK: + if (mss4_decode_dct_block(c, &gb, dst, x, y) < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error decoding DCT block %d,%d\n", + x, y); + return AVERROR_INVALIDDATA; + } + break; + case IMAGE_BLOCK: + if (mss4_decode_image_block(c, &gb, dst, x, y) < 0) { + av_log(avctx, AV_LOG_ERROR, + "Error decoding VQ block %d,%d\n", + x, y); + return AVERROR_INVALIDDATA; + } + break; + case SKIP_BLOCK: + if (frame_type == INTRA_FRAME) { + av_log(avctx, AV_LOG_ERROR, "Skip block in intra frame\n"); + return AVERROR_INVALIDDATA; + } + break; + } + if (blk_type != DCT_BLOCK) + mss4_update_dc_cache(c, x); + } + dst[0] += c->pic.linesize[0] * 16; + dst[1] += c->pic.linesize[1] * 16; + dst[2] += c->pic.linesize[2] * 16; + } + + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + *got_frame = 1; + + return buf_size; +} + +static av_cold int mss4_decode_init(AVCodecContext *avctx) +{ + MSS4Context * const c = avctx->priv_data; + int i; + + if (mss4_init_vlcs(c)) { + av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n"); + mss4_free_vlcs(c); + return AVERROR(ENOMEM); + } + for (i = 0; i < 3; i++) { + c->dc_stride[i] = FFALIGN(avctx->width, 16) >> (2 + !!i); + c->prev_dc[i] = av_malloc(sizeof(**c->prev_dc) * c->dc_stride[i]); + if (!c->prev_dc[i]) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate buffer\n"); + mss4_free_vlcs(c); + return AVERROR(ENOMEM); + } + } + + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + + return 0; +} + +static av_cold int mss4_decode_end(AVCodecContext *avctx) +{ + MSS4Context * const c = avctx->priv_data; + int i; + + av_frame_unref(&c->pic); + for (i = 0; i < 3; i++) + av_freep(&c->prev_dc[i]); + mss4_free_vlcs(c); + + return 0; +} + +AVCodec ff_mts2_decoder = { + .name = "mts2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MTS2, + .priv_data_size = sizeof(MSS4Context), + .init = mss4_decode_init, + .close = mss4_decode_end, + .decode = mss4_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("MS Expression Encoder Screen"), +}; diff --git a/ffmpeg/libavcodec/msvideo1.c b/ffmpeg/libavcodec/msvideo1.c new file mode 100644 index 0000000..c5a1daa --- /dev/null +++ b/ffmpeg/libavcodec/msvideo1.c @@ -0,0 +1,346 @@ +/* + * Microsoft Video-1 Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net) + * For more information about the MS Video-1 format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + */ + +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +#define PALETTE_COUNT 256 +#define CHECK_STREAM_PTR(n) \ + if ((stream_ptr + n) > s->size ) { \ + av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \ + stream_ptr + n, s->size); \ + return; \ + } + +typedef struct Msvideo1Context { + + AVCodecContext *avctx; + AVFrame frame; + + const unsigned char *buf; + int size; + + int mode_8bit; /* if it's not 8-bit, it's 16-bit */ + + uint32_t pal[256]; +} Msvideo1Context; + +static av_cold int msvideo1_decode_init(AVCodecContext *avctx) +{ + Msvideo1Context *s = avctx->priv_data; + + s->avctx = avctx; + + /* figure out the colorspace based on the presence of a palette */ + if (s->avctx->bits_per_coded_sample == 8) { + s->mode_8bit = 1; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else { + s->mode_8bit = 0; + avctx->pix_fmt = AV_PIX_FMT_RGB555; + } + + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + +static void msvideo1_decode_8bit(Msvideo1Context *s) +{ + int block_ptr, pixel_ptr; + int total_blocks; + int pixel_x, pixel_y; /* pixel width and height iterators */ + int block_x, block_y; /* block width and height iterators */ + int blocks_wide, blocks_high; /* width and height in 4x4 blocks */ + int block_inc; + int row_dec; + + /* decoding parameters */ + int stream_ptr; + unsigned char byte_a, byte_b; + unsigned short flags; + int skip_blocks; + unsigned char colors[8]; + unsigned char *pixels = s->frame.data[0]; + int stride = s->frame.linesize[0]; + + stream_ptr = 0; + skip_blocks = 0; + blocks_wide = s->avctx->width / 4; + blocks_high = s->avctx->height / 4; + total_blocks = blocks_wide * blocks_high; + block_inc = 4; + row_dec = stride + 4; + + for (block_y = blocks_high; block_y > 0; block_y--) { + block_ptr = ((block_y * 4) - 1) * stride; + for (block_x = blocks_wide; block_x > 0; block_x--) { + /* check if this block should be skipped */ + if (skip_blocks) { + block_ptr += block_inc; + skip_blocks--; + total_blocks--; + continue; + } + + pixel_ptr = block_ptr; + + /* get the next two bytes in the encoded data stream */ + CHECK_STREAM_PTR(2); + byte_a = s->buf[stream_ptr++]; + byte_b = s->buf[stream_ptr++]; + + /* check if the decode is finished */ + if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) + return; + else if ((byte_b & 0xFC) == 0x84) { + /* skip code, but don't count the current block */ + skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1; + } else if (byte_b < 0x80) { + /* 2-color encoding */ + flags = (byte_b << 8) | byte_a; + + CHECK_STREAM_PTR(2); + colors[0] = s->buf[stream_ptr++]; + colors[1] = s->buf[stream_ptr++]; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1]; + pixel_ptr -= row_dec; + } + } else if (byte_b >= 0x90) { + /* 8-color encoding */ + flags = (byte_b << 8) | byte_a; + + CHECK_STREAM_PTR(8); + memcpy(colors, &s->buf[stream_ptr], 8); + stream_ptr += 8; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + pixels[pixel_ptr++] = + colors[((pixel_y & 0x2) << 1) + + (pixel_x & 0x2) + ((flags & 0x1) ^ 1)]; + pixel_ptr -= row_dec; + } + } else { + /* 1-color encoding */ + colors[0] = byte_a; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) + pixels[pixel_ptr++] = colors[0]; + pixel_ptr -= row_dec; + } + } + + block_ptr += block_inc; + total_blocks--; + } + } + + /* make the palette available on the way out */ + if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8) + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); +} + +static void msvideo1_decode_16bit(Msvideo1Context *s) +{ + int block_ptr, pixel_ptr; + int total_blocks; + int pixel_x, pixel_y; /* pixel width and height iterators */ + int block_x, block_y; /* block width and height iterators */ + int blocks_wide, blocks_high; /* width and height in 4x4 blocks */ + int block_inc; + int row_dec; + + /* decoding parameters */ + int stream_ptr; + unsigned char byte_a, byte_b; + unsigned short flags; + int skip_blocks; + unsigned short colors[8]; + unsigned short *pixels = (unsigned short *)s->frame.data[0]; + int stride = s->frame.linesize[0] / 2; + + stream_ptr = 0; + skip_blocks = 0; + blocks_wide = s->avctx->width / 4; + blocks_high = s->avctx->height / 4; + total_blocks = blocks_wide * blocks_high; + block_inc = 4; + row_dec = stride + 4; + + for (block_y = blocks_high; block_y > 0; block_y--) { + block_ptr = ((block_y * 4) - 1) * stride; + for (block_x = blocks_wide; block_x > 0; block_x--) { + /* check if this block should be skipped */ + if (skip_blocks) { + block_ptr += block_inc; + skip_blocks--; + total_blocks--; + continue; + } + + pixel_ptr = block_ptr; + + /* get the next two bytes in the encoded data stream */ + CHECK_STREAM_PTR(2); + byte_a = s->buf[stream_ptr++]; + byte_b = s->buf[stream_ptr++]; + + /* check if the decode is finished */ + if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) { + return; + } else if ((byte_b & 0xFC) == 0x84) { + /* skip code, but don't count the current block */ + skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1; + } else if (byte_b < 0x80) { + /* 2- or 8-color encoding modes */ + flags = (byte_b << 8) | byte_a; + + CHECK_STREAM_PTR(4); + colors[0] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + colors[1] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + + if (colors[0] & 0x8000) { + /* 8-color encoding */ + CHECK_STREAM_PTR(12); + colors[2] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + colors[3] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + colors[4] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + colors[5] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + colors[6] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + colors[7] = AV_RL16(&s->buf[stream_ptr]); + stream_ptr += 2; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + pixels[pixel_ptr++] = + colors[((pixel_y & 0x2) << 1) + + (pixel_x & 0x2) + ((flags & 0x1) ^ 1)]; + pixel_ptr -= row_dec; + } + } else { + /* 2-color encoding */ + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1) + pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1]; + pixel_ptr -= row_dec; + } + } + } else { + /* otherwise, it's a 1-color block */ + colors[0] = (byte_b << 8) | byte_a; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) + pixels[pixel_ptr++] = colors[0]; + pixel_ptr -= row_dec; + } + } + + block_ptr += block_inc; + total_blocks--; + } + } +} + +static int msvideo1_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + Msvideo1Context *s = avctx->priv_data; + int ret; + + s->buf = buf; + s->size = buf_size; + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + if (s->mode_8bit) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { + memcpy(s->pal, pal, AVPALETTE_SIZE); + s->frame.palette_has_changed = 1; + } + } + + if (s->mode_8bit) + msvideo1_decode_8bit(s); + else + msvideo1_decode_16bit(s); + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int msvideo1_decode_end(AVCodecContext *avctx) +{ + Msvideo1Context *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_msvideo1_decoder = { + .name = "msvideo1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSVIDEO1, + .priv_data_size = sizeof(Msvideo1Context), + .init = msvideo1_decode_init, + .close = msvideo1_decode_end, + .decode = msvideo1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video 1"), +}; diff --git a/ffmpeg/libavcodec/msvideo1enc.c b/ffmpeg/libavcodec/msvideo1enc.c new file mode 100644 index 0000000..e0efb48 --- /dev/null +++ b/ffmpeg/libavcodec/msvideo1enc.c @@ -0,0 +1,311 @@ +/* + * Microsoft Video-1 Encoder + * Copyright (c) 2009 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Microsoft Video-1 encoder + */ + +#include "avcodec.h" +#include "internal.h" +#include "bytestream.h" +#include "libavutil/lfg.h" +#include "elbg.h" +#include "libavutil/imgutils.h" +/** + * Encoder context + */ +typedef struct Msvideo1EncContext { + AVCodecContext *avctx; + AVFrame pic; + AVLFG rnd; + uint8_t *prev; + + int block[16*3]; + int block2[16*3]; + int codebook[8*3]; + int codebook2[8*3]; + int output[16*3]; + int output2[16*3]; + int avg[3]; + int bestpos; + int keyint; +} Msvideo1EncContext; + +enum MSV1Mode{ + MODE_SKIP = 0, + MODE_FILL, + MODE_2COL, + MODE_8COL, +}; + +#define SKIP_PREFIX 0x8400 +#define SKIPS_MAX 0x0FFF +#define MKRGB555(in, off) ((in[off] << 10) | (in[off + 1] << 5) | (in[off + 2])) + +static const int remap[16] = { 0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15 }; + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + Msvideo1EncContext * const c = avctx->priv_data; + AVFrame * const p = &c->pic; + uint16_t *src; + uint8_t *prevptr; + uint8_t *dst, *buf; + int keyframe = 0; + int no_skips = 1; + int i, j, k, x, y, ret; + int skips = 0; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width*avctx->height*9 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + dst= buf= pkt->data; + + *p = *pict; + if(!c->prev) + c->prev = av_malloc(avctx->width * 3 * (avctx->height + 3)); + prevptr = c->prev + avctx->width * 3 * (FFALIGN(avctx->height, 4) - 1); + src = (uint16_t*)(p->data[0] + p->linesize[0]*(FFALIGN(avctx->height, 4) - 1)); + if(c->keyint >= avctx->keyint_min) + keyframe = 1; + + p->quality = 24; + + for(y = 0; y < avctx->height; y += 4){ + for(x = 0; x < avctx->width; x += 4){ + int bestmode = MODE_SKIP; + int bestscore = INT_MAX; + int flags = 0; + int score; + + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++){ + uint16_t val = src[x + i - j*p->linesize[0]/2]; + for(k = 0; k < 3; k++){ + c->block[(i + j*4)*3 + k] = + c->block2[remap[i + j*4]*3 + k] = (val >> (10-k*5)) & 0x1F; + } + } + } + if(!keyframe){ + bestscore = 0; + for(j = 0; j < 4; j++){ + for(i = 0; i < 4*3; i++){ + int t = prevptr[x*3 + i - j*3*avctx->width] - c->block[i + j*4*3]; + bestscore += t*t; + } + } + bestscore /= p->quality; + } + // try to find optimal value to fill whole 4x4 block + score = 0; + ff_init_elbg(c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd); + ff_do_elbg (c->block, 3, 16, c->avg, 1, 1, c->output, &c->rnd); + if(c->avg[0] == 1) // red component = 1 will be written as skip code + c->avg[0] = 0; + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++){ + for(k = 0; k < 3; k++){ + int t = c->avg[k] - c->block[(i+j*4)*3+k]; + score += t*t; + } + } + } + score /= p->quality; + score += 2; + if(score < bestscore){ + bestscore = score; + bestmode = MODE_FILL; + } + // search for optimal filling of 2-color block + score = 0; + ff_init_elbg(c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd); + ff_do_elbg (c->block, 3, 16, c->codebook, 2, 1, c->output, &c->rnd); + // last output value should be always 1, swap codebooks if needed + if(!c->output[15]){ + for(i = 0; i < 3; i++) + FFSWAP(uint8_t, c->codebook[i], c->codebook[i+3]); + for(i = 0; i < 16; i++) + c->output[i] ^= 1; + } + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++){ + for(k = 0; k < 3; k++){ + int t = c->codebook[c->output[i+j*4]*3 + k] - c->block[i*3+k+j*4*3]; + score += t*t; + } + } + } + score /= p->quality; + score += 6; + if(score < bestscore){ + bestscore = score; + bestmode = MODE_2COL; + } + // search for optimal filling of 2-color 2x2 subblocks + score = 0; + for(i = 0; i < 4; i++){ + ff_init_elbg(c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd); + ff_do_elbg (c->block2 + i*4*3, 3, 4, c->codebook2 + i*2*3, 2, 1, c->output2 + i*4, &c->rnd); + } + // last value should be always 1, swap codebooks if needed + if(!c->output2[15]){ + for(i = 0; i < 3; i++) + FFSWAP(uint8_t, c->codebook2[i+18], c->codebook2[i+21]); + for(i = 12; i < 16; i++) + c->output2[i] ^= 1; + } + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++){ + for(k = 0; k < 3; k++){ + int t = c->codebook2[(c->output2[remap[i+j*4]] + (i&2) + (j&2)*2)*3+k] - c->block[i*3+k + j*4*3]; + score += t*t; + } + } + } + score /= p->quality; + score += 18; + if(score < bestscore){ + bestscore = score; + bestmode = MODE_8COL; + } + + if(bestmode == MODE_SKIP){ + skips++; + no_skips = 0; + } + if((bestmode != MODE_SKIP && skips) || skips == SKIPS_MAX){ + bytestream_put_le16(&dst, skips | SKIP_PREFIX); + skips = 0; + } + + switch(bestmode){ + case MODE_FILL: + bytestream_put_le16(&dst, MKRGB555(c->avg,0) | 0x8000); + for(j = 0; j < 4; j++) + for(i = 0; i < 4; i++) + for(k = 0; k < 3; k++) + prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->avg[k]; + break; + case MODE_2COL: + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++){ + flags |= (c->output[i + j*4]^1) << (i + j*4); + for(k = 0; k < 3; k++) + prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->codebook[c->output[i + j*4]*3 + k]; + } + } + bytestream_put_le16(&dst, flags); + bytestream_put_le16(&dst, MKRGB555(c->codebook, 0)); + bytestream_put_le16(&dst, MKRGB555(c->codebook, 3)); + break; + case MODE_8COL: + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++){ + flags |= (c->output2[remap[i + j*4]]^1) << (i + j*4); + for(k = 0; k < 3; k++) + prevptr[x*3 + i*3 + k - j*3*avctx->width] = c->codebook2[(c->output2[remap[i+j*4]] + (i&2) + (j&2)*2)*3 + k]; + } + } + bytestream_put_le16(&dst, flags); + bytestream_put_le16(&dst, MKRGB555(c->codebook2, 0) | 0x8000); + for(i = 3; i < 24; i += 3) + bytestream_put_le16(&dst, MKRGB555(c->codebook2, i)); + break; + } + } + src -= p->linesize[0] << 1; + prevptr -= avctx->width * 3 * 4; + } + if(skips) + bytestream_put_le16(&dst, skips | SKIP_PREFIX); + //EOF + bytestream_put_byte(&dst, 0); + bytestream_put_byte(&dst, 0); + + if(no_skips) + keyframe = 1; + if(keyframe) + c->keyint = 0; + else + c->keyint++; + p->pict_type= keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + p->key_frame= keyframe; + if (keyframe) pkt->flags |= AV_PKT_FLAG_KEY; + pkt->size = dst - buf; + *got_packet = 1; + + return 0; +} + + +/** + * init encoder + */ +static av_cold int encode_init(AVCodecContext *avctx) +{ + Msvideo1EncContext * const c = avctx->priv_data; + + c->avctx = avctx; + if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) { + return -1; + } + if((avctx->width&3) || (avctx->height&3)){ + av_log(avctx, AV_LOG_ERROR, "width and height must be multiplies of 4\n"); + return -1; + } + + avcodec_get_frame_defaults(&c->pic); + avctx->coded_frame = (AVFrame*)&c->pic; + avctx->bits_per_coded_sample = 16; + + c->keyint = avctx->keyint_min; + av_lfg_init(&c->rnd, 1); + + return 0; +} + + + +/** + * Uninit encoder + */ +static av_cold int encode_end(AVCodecContext *avctx) +{ + Msvideo1EncContext * const c = avctx->priv_data; + + av_freep(&c->prev); + + return 0; +} + +AVCodec ff_msvideo1_encoder = { + .name = "msvideo1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSVIDEO1, + .priv_data_size = sizeof(Msvideo1EncContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"), +}; diff --git a/ffmpeg/libavcodec/mvcdec.c b/ffmpeg/libavcodec/mvcdec.c new file mode 100644 index 0000000..c4385fe --- /dev/null +++ b/ffmpeg/libavcodec/mvcdec.c @@ -0,0 +1,286 @@ +/* + * Silicon Graphics Motion Video Compressor 1 & 2 decoder + * Copyright (c) 2012 Peter Ross + * + * 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 + */ + +/** + * @file + * Silicon Graphics Motion Video Compressor 1 & 2 decoder + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct MvcContext { + AVFrame *frame; + int vflip; +} MvcContext; + +static av_cold int mvc_decode_init(AVCodecContext *avctx) +{ + MvcContext *s = avctx->priv_data; + int width = avctx->width; + int height = avctx->height; + + if (avctx->codec_id == AV_CODEC_ID_MVC1) { + width += 3; + height += 3; + } + width &= ~3; + height &= ~3; + if (width != avctx->width || height != avctx->height) + avcodec_set_dimensions(avctx, width, height); + + avctx->pix_fmt = (avctx->codec_id == AV_CODEC_ID_MVC1) ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_BGRA; + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + s->vflip = avctx->extradata_size >= 9 && !memcmp(avctx->extradata + avctx->extradata_size - 9, "BottomUp", 9); + return 0; +} + +static int decode_mvc1(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_start, int width, int height, int linesize) +{ + uint8_t *dst; + uint16_t v[8]; + int mask, x, y, i; + + x = y= 0; + while (bytestream2_get_bytes_left(gb) >= 6) { + mask = bytestream2_get_be16u(gb); + v[0] = bytestream2_get_be16u(gb); + v[1] = bytestream2_get_be16u(gb); + if ((v[0] & 0x8000)) { + if (bytestream2_get_bytes_left(gb) < 12) { + av_log(avctx, AV_LOG_WARNING, "buffer overflow\n"); + return AVERROR_INVALIDDATA; + } + for (i = 2; i < 8; i++) + v[i] = bytestream2_get_be16u(gb); + } else { + v[2] = v[4] = v[6] = v[0]; + v[3] = v[5] = v[7] = v[1]; + } + +#define PIX16(target, true, false) \ + i = (mask & target) ? true : false; \ + AV_WN16A(dst, (v[i] & 0x7C00) | (v[i] & 0x3E0) | (v[i] & 0x1F)); \ + dst += 2; + +#define ROW16(row, a1, a0, b1, b0) \ + dst = dst_start + (y + row) * linesize + x * 2; \ + PIX16(1 << (row * 4), a1, a0) \ + PIX16(1 << (row * 4 + 1), a1, a0) \ + PIX16(1 << (row * 4 + 2), b1, b0) \ + PIX16(1 << (row * 4 + 3), b1, b0) + + ROW16(0, 0, 1, 2, 3); + ROW16(1, 0, 1, 2, 3); + ROW16(2, 4, 5, 6, 7); + ROW16(3, 4, 5, 6, 7); + + x += 4; + if (x >= width) { + y += 4; + if (y >= height) { + break; + } + x = 0; + } + } + return 0; +} + +static void set_4x4_block(uint8_t *dst, int linesize, uint32_t pixel) +{ + int i, j; + for (j = 0; j < 4; j++) + for (i = 0; i < 4; i++) + AV_WN32A(dst + j * linesize + i * 4, pixel); +} + +#define PIX32(target, true, false) \ + AV_WN32A(dst, (mask & target) ? v[true] : v[false]); \ + dst += 4; + +#define ROW32(row, a1, a0, b1, b0) \ + dst = dst_start + (y + row) * linesize + x * 4; \ + PIX32(1 << (row * 4), a1, a0) \ + PIX32(1 << (row * 4 + 1), a1, a0) \ + PIX32(1 << (row * 4 + 2), b1, b0) \ + PIX32(1 << (row * 4 + 3), b1, b0) + +#define MVC2_BLOCK \ + ROW32(0, 1, 0, 3, 2); \ + ROW32(1, 1, 0, 3, 2); \ + ROW32(2, 5, 4, 7, 6); \ + ROW32(3, 5, 4, 7, 6); + +static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_start, int width, int height, int linesize, int vflip) +{ + uint8_t *dst; + uint32_t color[128], v[8]; + int w, h, nb_colors, i, x, y, p0, p1, mask; + + if (bytestream2_get_bytes_left(gb) < 6) + return AVERROR_INVALIDDATA; + + w = bytestream2_get_be16u(gb); + h = bytestream2_get_be16u(gb); + if ((w & ~3) != width || (h & ~3) != height) + av_log(avctx, AV_LOG_WARNING, "dimension mismatch\n"); + + if (bytestream2_get_byteu(gb)) { + avpriv_request_sample(avctx, "bitmap feature"); + return AVERROR_PATCHWELCOME; + } + + nb_colors = bytestream2_get_byteu(gb); + if (bytestream2_get_bytes_left(gb) < nb_colors * 3) + return AVERROR_INVALIDDATA; + for (i = 0; i < FFMIN(nb_colors, 128); i++) + color[i] = 0xFF000000 | bytestream2_get_be24u(gb); + if (nb_colors > 128) + bytestream2_skip(gb, (nb_colors - 128) * 3); + + if (vflip) { + dst_start += (height - 1) * linesize; + linesize = -linesize; + } + x = y = 0; + while (bytestream2_get_bytes_left(gb) >= 1) { + p0 = bytestream2_get_byteu(gb); + if ((p0 & 0x80)) { + if ((p0 & 0x40)) { + p0 &= 0x3F; + p0 = (p0 << 2) | (p0 >> 4); + set_4x4_block(dst_start + y * linesize + x * 4, linesize, 0xFF000000 | (p0 << 16) | (p0 << 8) | p0); + } else { + int g, r; + p0 &= 0x3F; + p0 = (p0 << 2) | (p0 >> 4); + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + g = bytestream2_get_byteu(gb); + r = bytestream2_get_byteu(gb); + set_4x4_block(dst_start + y * linesize + x * 4, linesize, 0xFF000000 | (r << 16) | (g << 8) | p0); + } + } else { + if (bytestream2_get_bytes_left(gb) < 1) + return AVERROR_INVALIDDATA; + p1 = bytestream2_get_byteu(gb); + if ((p1 & 0x80)) { + if ((p0 & 0x7F) == (p1 & 0x7F)) { + set_4x4_block(dst_start + y * linesize + x * 4, linesize, color[p0 & 0x7F]); + } else { + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + v[0] = v[2] = v[4] = v[6] = color[p0 & 0x7F]; + v[1] = v[3] = v[5] = v[7] = color[p1 & 0x7F]; + mask = bytestream2_get_le16u(gb); + MVC2_BLOCK + } + } else { + if (bytestream2_get_bytes_left(gb) < 8) + return AVERROR_INVALIDDATA; + v[0] = color[p0 & 0x7F]; + v[1] = color[p1 & 0x7F]; + for (i = 2; i < 8; i++) + v[i] = color[bytestream2_get_byteu(gb) & 0x7F]; + mask = bytestream2_get_le16u(gb); + MVC2_BLOCK + } + } + + x += 4; + if (x >= width) { + y += 4; + if (y >= height) + break; + x = 0; + } + } + return 0; +} + +static int mvc_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + MvcContext *s = avctx->priv_data; + GetByteContext gb; + int ret; + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + if (avctx->codec_id == AV_CODEC_ID_MVC1) + ret = decode_mvc1(avctx, &gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]); + else + ret = decode_mvc2(avctx, &gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0], s->vflip); + if (ret < 0) + return ret; + + *got_frame = 1; + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + return avpkt->size; +} + +static av_cold int mvc_decode_end(AVCodecContext *avctx) +{ + MvcContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +#if CONFIG_MVC1_DECODER +AVCodec ff_mvc1_decoder = { + .name = "mvc1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MVC1, + .priv_data_size = sizeof(MvcContext), + .init = mvc_decode_init, + .close = mvc_decode_end, + .decode = mvc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"), +}; +#endif + +#if CONFIG_MVC2_DECODER +AVCodec ff_mvc2_decoder = { + .name = "mvc2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MVC2, + .priv_data_size = sizeof(MvcContext), + .init = mvc_decode_init, + .close = mvc_decode_end, + .decode = mvc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"), +}; +#endif diff --git a/ffmpeg/libavcodec/mxpegdec.c b/ffmpeg/libavcodec/mxpegdec.c new file mode 100644 index 0000000..0069ca5 --- /dev/null +++ b/ffmpeg/libavcodec/mxpegdec.c @@ -0,0 +1,340 @@ +/* + * MxPEG decoder + * Copyright (c) 2011 Anatoly Nenashev + * + * 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 + */ + + +/** + * @file + * MxPEG decoder + */ + +#include "internal.h" +#include "mjpeg.h" +#include "mjpegdec.h" + +typedef struct MXpegDecodeContext { + MJpegDecodeContext jpg; + AVFrame picture[2]; /* pictures array */ + int picture_index; /* index of current picture */ + int got_sof_data; /* true if SOF data successfully parsed */ + int got_mxm_bitmask; /* true if MXM bitmask available */ + uint8_t *mxm_bitmask; /* bitmask buffer */ + unsigned bitmask_size; /* size of bitmask */ + int has_complete_frame; /* true if has complete frame */ + uint8_t *completion_bitmask; /* completion bitmask of macroblocks */ + unsigned mb_width, mb_height; /* size of picture in MB's from MXM header */ +} MXpegDecodeContext; + +static av_cold int mxpeg_decode_init(AVCodecContext *avctx) +{ + MXpegDecodeContext *s = avctx->priv_data; + + s->jpg.picture_ptr = &s->picture[0]; + return ff_mjpeg_decode_init(avctx); +} + +static int mxpeg_decode_app(MXpegDecodeContext *s, + const uint8_t *buf_ptr, int buf_size) +{ + int len; + if (buf_size < 2) + return 0; + len = AV_RB16(buf_ptr); + skip_bits(&s->jpg.gb, 8*FFMIN(len,buf_size)); + + return 0; +} + +static int mxpeg_decode_mxm(MXpegDecodeContext *s, + const uint8_t *buf_ptr, int buf_size) +{ + unsigned bitmask_size, mb_count; + int i; + + s->mb_width = AV_RL16(buf_ptr+4); + s->mb_height = AV_RL16(buf_ptr+6); + mb_count = s->mb_width * s->mb_height; + + bitmask_size = (mb_count + 7) >> 3; + if (bitmask_size > buf_size - 12) { + av_log(s->jpg.avctx, AV_LOG_ERROR, + "MXM bitmask is not complete\n"); + return AVERROR(EINVAL); + } + + if (s->bitmask_size != bitmask_size) { + s->bitmask_size = 0; + av_freep(&s->mxm_bitmask); + s->mxm_bitmask = av_malloc(bitmask_size); + if (!s->mxm_bitmask) { + av_log(s->jpg.avctx, AV_LOG_ERROR, + "MXM bitmask memory allocation error\n"); + return AVERROR(ENOMEM); + } + + av_freep(&s->completion_bitmask); + s->completion_bitmask = av_mallocz(bitmask_size); + if (!s->completion_bitmask) { + av_log(s->jpg.avctx, AV_LOG_ERROR, + "Completion bitmask memory allocation error\n"); + return AVERROR(ENOMEM); + } + + s->bitmask_size = bitmask_size; + } + + memcpy(s->mxm_bitmask, buf_ptr + 12, bitmask_size); + s->got_mxm_bitmask = 1; + + if (!s->has_complete_frame) { + uint8_t completion_check = 0xFF; + for (i = 0; i < bitmask_size; ++i) { + s->completion_bitmask[i] |= s->mxm_bitmask[i]; + completion_check &= s->completion_bitmask[i]; + } + s->has_complete_frame = !(completion_check ^ 0xFF); + } + + return 0; +} + +static int mxpeg_decode_com(MXpegDecodeContext *s, + const uint8_t *buf_ptr, int buf_size) +{ + int len, ret = 0; + if (buf_size < 2) + return 0; + len = AV_RB16(buf_ptr); + if (len > 14 && len <= buf_size && !strncmp(buf_ptr + 2, "MXM", 3)) { + ret = mxpeg_decode_mxm(s, buf_ptr + 2, len - 2); + } + skip_bits(&s->jpg.gb, 8*FFMIN(len,buf_size)); + + return ret; +} + +static int mxpeg_check_dimensions(MXpegDecodeContext *s, MJpegDecodeContext *jpg, + AVFrame *reference_ptr) +{ + if ((jpg->width + 0x0F)>>4 != s->mb_width || + (jpg->height + 0x0F)>>4 != s->mb_height) { + av_log(jpg->avctx, AV_LOG_ERROR, + "Picture dimensions stored in SOF and MXM mismatch\n"); + return AVERROR(EINVAL); + } + + if (reference_ptr->data[0]) { + int i; + for (i = 0; i < MAX_COMPONENTS; ++i) { + if ( (!reference_ptr->data[i] ^ !jpg->picture_ptr->data[i]) || + reference_ptr->linesize[i] != jpg->picture_ptr->linesize[i]) { + av_log(jpg->avctx, AV_LOG_ERROR, + "Dimensions of current and reference picture mismatch\n"); + return AVERROR(EINVAL); + } + } + } + + return 0; +} + +static int mxpeg_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MXpegDecodeContext *s = avctx->priv_data; + MJpegDecodeContext *jpg = &s->jpg; + const uint8_t *buf_end, *buf_ptr; + const uint8_t *unescaped_buf_ptr; + int unescaped_buf_size; + int start_code; + int ret; + + buf_ptr = buf; + buf_end = buf + buf_size; + jpg->got_picture = 0; + s->got_mxm_bitmask = 0; + while (buf_ptr < buf_end) { + start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, buf_end, + &unescaped_buf_ptr, &unescaped_buf_size); + if (start_code < 0) + goto the_end; + { + init_get_bits(&jpg->gb, unescaped_buf_ptr, unescaped_buf_size*8); + + if (start_code >= APP0 && start_code <= APP15) { + mxpeg_decode_app(s, unescaped_buf_ptr, unescaped_buf_size); + } + + switch (start_code) { + case SOI: + if (jpg->got_picture) //emulating EOI + goto the_end; + break; + case EOI: + goto the_end; + case DQT: + ret = ff_mjpeg_decode_dqt(jpg); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "quantization table decode error\n"); + return ret; + } + break; + case DHT: + ret = ff_mjpeg_decode_dht(jpg); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "huffman table decode error\n"); + return ret; + } + break; + case COM: + ret = mxpeg_decode_com(s, unescaped_buf_ptr, + unescaped_buf_size); + if (ret < 0) + return ret; + break; + case SOF0: + s->got_sof_data = 0; + ret = ff_mjpeg_decode_sof(jpg); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "SOF data decode error\n"); + return ret; + } + if (jpg->interlaced) { + av_log(avctx, AV_LOG_ERROR, + "Interlaced mode not supported in MxPEG\n"); + return AVERROR(EINVAL); + } + s->got_sof_data = 1; + break; + case SOS: + if (!s->got_sof_data) { + av_log(avctx, AV_LOG_WARNING, + "Can not process SOS without SOF data, skipping\n"); + break; + } + if (!jpg->got_picture) { + if (jpg->first_picture) { + av_log(avctx, AV_LOG_WARNING, + "First picture has no SOF, skipping\n"); + break; + } + if (!s->got_mxm_bitmask){ + av_log(avctx, AV_LOG_WARNING, + "Non-key frame has no MXM, skipping\n"); + break; + } + /* use stored SOF data to allocate current picture */ + av_frame_unref(jpg->picture_ptr); + if ((ret = ff_get_buffer(avctx, jpg->picture_ptr, + AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_P; + jpg->picture_ptr->key_frame = 0; + jpg->got_picture = 1; + } else { + jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_I; + jpg->picture_ptr->key_frame = 1; + } + + if (s->got_mxm_bitmask) { + AVFrame *reference_ptr = &s->picture[s->picture_index ^ 1]; + if (mxpeg_check_dimensions(s, jpg, reference_ptr) < 0) + break; + + /* allocate dummy reference picture if needed */ + if (!reference_ptr->data[0] && + (ret = ff_get_buffer(avctx, reference_ptr, + AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, reference_ptr); + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return ret; + } else { + ret = ff_mjpeg_decode_sos(jpg, NULL, NULL); + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return ret; + } + + break; + } + + buf_ptr += (get_bits_count(&jpg->gb)+7) >> 3; + } + + } + +the_end: + if (jpg->got_picture) { + int ret = av_frame_ref(data, jpg->picture_ptr); + if (ret < 0) + return ret; + *got_frame = 1; + + s->picture_index ^= 1; + jpg->picture_ptr = &s->picture[s->picture_index]; + + if (!s->has_complete_frame) { + if (!s->got_mxm_bitmask) + s->has_complete_frame = 1; + else + *got_frame = 0; + } + } + + return buf_ptr - buf; +} + +static av_cold int mxpeg_decode_end(AVCodecContext *avctx) +{ + MXpegDecodeContext *s = avctx->priv_data; + MJpegDecodeContext *jpg = &s->jpg; + int i; + + jpg->picture_ptr = NULL; + ff_mjpeg_decode_end(avctx); + + for (i = 0; i < 2; ++i) + av_frame_unref(&s->picture[i]); + + av_freep(&s->mxm_bitmask); + av_freep(&s->completion_bitmask); + + return 0; +} + +AVCodec ff_mxpeg_decoder = { + .name = "mxpeg", + .long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MXPEG, + .priv_data_size = sizeof(MXpegDecodeContext), + .init = mxpeg_decode_init, + .close = mxpeg_decode_end, + .decode = mxpeg_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, +}; diff --git a/ffmpeg/libavcodec/nellymoser.c b/ffmpeg/libavcodec/nellymoser.c new file mode 100644 index 0000000..0740c75 --- /dev/null +++ b/ffmpeg/libavcodec/nellymoser.c @@ -0,0 +1,224 @@ +/* + * Common code between Nellymoser encoder and decoder + * Copyright (c) 2007 a840bda5870ba11f19698ff6eb9581dfb0f95fa5, + * 539459aeb7d425140b62a3ec7dbf6dc8e408a306, and + * 520e17cd55896441042b14df2566a6eb610ed444 + * Copyright (c) 2007 Loic Minier + * Benjamin Larsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * The 3 alphanumeric copyright notices are md5summed they are from the original + * implementors. The original code is available from http://code.google.com/p/nelly2pcm/ + */ + +#include "nellymoser.h" +#include "avcodec.h" + +#define BITSTREAM_READER_LE +#include "get_bits.h" + +const float ff_nelly_dequantization_table[127] = { + 0.0000000000, + +-0.8472560048, 0.7224709988, + +-1.5247479677,-0.4531480074, 0.3753609955, 1.4717899561, + +-1.9822579622,-1.1929379702,-0.5829370022,-0.0693780035, 0.3909569979, 0.9069200158, 1.4862740040, 2.2215409279, + +-2.3887870312,-1.8067539930,-1.4105420113,-1.0773609877,-0.7995010018,-0.5558109879,-0.3334020078,-0.1324490011, + 0.0568020009, 0.2548770010, 0.4773550034, 0.7386850119, 1.0443060398, 1.3954459429, 1.8098750114, 2.3918759823, + +-2.3893830776,-1.9884680510,-1.7514040470,-1.5643119812,-1.3922129869,-1.2164649963,-1.0469499826,-0.8905100226, +-0.7645580173,-0.6454579830,-0.5259280205,-0.4059549868,-0.3029719889,-0.2096900046,-0.1239869967,-0.0479229987, + 0.0257730000, 0.1001340002, 0.1737180054, 0.2585540116, 0.3522900045, 0.4569880068, 0.5767750144, 0.7003160119, + 0.8425520062, 1.0093879700, 1.1821349859, 1.3534560204, 1.5320819616, 1.7332619429, 1.9722349644, 2.3978140354, + +-2.5756309032,-2.0573320389,-1.8984919786,-1.7727810144,-1.6662600040,-1.5742180347,-1.4993319511,-1.4316639900, +-1.3652280569,-1.3000990152,-1.2280930281,-1.1588579416,-1.0921250582,-1.0135740042,-0.9202849865,-0.8287050128, +-0.7374889851,-0.6447759867,-0.5590940118,-0.4857139885,-0.4110319912,-0.3459700048,-0.2851159871,-0.2341620028, +-0.1870580018,-0.1442500055,-0.1107169986,-0.0739680007,-0.0365610011,-0.0073290002, 0.0203610007, 0.0479039997, + 0.0751969963, 0.0980999991, 0.1220389977, 0.1458999962, 0.1694349945, 0.1970459968, 0.2252430022, 0.2556869984, + 0.2870100141, 0.3197099864, 0.3525829911, 0.3889069855, 0.4334920049, 0.4769459963, 0.5204820037, 0.5644530058, + 0.6122040153, 0.6685929894, 0.7341650128, 0.8032159805, 0.8784040213, 0.9566209912, 1.0397069454, 1.1293770075, + 1.2211159468, 1.3080279827, 1.4024800062, 1.5056819916, 1.6227730513, 1.7724959850, 1.9430880547, 2.2903931141 +}; + +const uint8_t ff_nelly_band_sizes_table[NELLY_BANDS] = { +2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 12, 14, 15 +}; + +const uint16_t ff_nelly_init_table[64] = { +3134, 5342, 6870, 7792, 8569, 9185, 9744, 10191, 10631, 11061, 11434, 11770, +12116, 12513, 12925, 13300, 13674, 14027, 14352, 14716, 15117, 15477, 15824, +16157, 16513, 16804, 17090, 17401, 17679, 17948, 18238, 18520, 18764, 19078, +19381, 19640, 19921, 20205, 20500, 20813, 21162, 21465, 21794, 22137, 22453, +22756, 23067, 23350, 23636, 23926, 24227, 24521, 24819, 25107, 25414, 25730, +26120, 26497, 26895, 27344, 27877, 28463, 29426, 31355 +}; + +const int16_t ff_nelly_delta_table[32] = { +-11725, -9420, -7910, -6801, -5948, -5233, -4599, -4039, -3507, -3030, -2596, +-2170, -1774, -1383, -1016, -660, -329, -1, 337, 696, 1085, 1512, 1962, 2433, +2968, 3569, 4314, 5279, 6622, 8154, 10076, 12975 +}; + +static inline int signed_shift(int i, int shift) { + if (shift > 0) + return i << shift; + return i >> -shift; +} + +static int sum_bits(short *buf, short shift, short off) +{ + int i, ret = 0; + + for (i = 0; i < NELLY_FILL_LEN; i++) { + int b = buf[i]-off; + b = ((b>>(shift-1))+1)>>1; + ret += av_clip(b, 0, NELLY_BIT_CAP); + } + + return ret; +} + +static int headroom(int *la) +{ + int l; + if (*la == 0) { + return 31; + } + l = 30 - av_log2(FFABS(*la)); + *la <<= l; + return l; +} + + +void ff_nelly_get_sample_bits(const float *buf, int *bits) +{ + int i, j; + short sbuf[128]; + int bitsum = 0, last_bitsum, small_bitsum, big_bitsum; + short shift, shift_saved; + int max, sum, last_off, tmp; + int big_off, small_off; + int off; + + max = 0; + for (i = 0; i < NELLY_FILL_LEN; i++) { + max = FFMAX(max, buf[i]); + } + shift = -16; + shift += headroom(&max); + + sum = 0; + for (i = 0; i < NELLY_FILL_LEN; i++) { + sbuf[i] = signed_shift(buf[i], shift); + sbuf[i] = (3*sbuf[i])>>2; + sum += sbuf[i]; + } + + shift += 11; + shift_saved = shift; + sum -= NELLY_DETAIL_BITS << shift; + shift += headroom(&sum); + small_off = (NELLY_BASE_OFF * (sum>>16)) >> 15; + shift = shift_saved - (NELLY_BASE_SHIFT+shift-31); + + small_off = signed_shift(small_off, shift); + + bitsum = sum_bits(sbuf, shift_saved, small_off); + + if (bitsum != NELLY_DETAIL_BITS) { + off = bitsum - NELLY_DETAIL_BITS; + + for(shift=0; FFABS(off) <= 16383; shift++) + off *= 2; + + off = (off * NELLY_BASE_OFF) >> 15; + shift = shift_saved-(NELLY_BASE_SHIFT+shift-15); + + off = signed_shift(off, shift); + + for (j = 1; j < 20; j++) { + last_off = small_off; + small_off += off; + last_bitsum = bitsum; + + bitsum = sum_bits(sbuf, shift_saved, small_off); + + if ((bitsum-NELLY_DETAIL_BITS) * (last_bitsum-NELLY_DETAIL_BITS) <= 0) + break; + } + + if (bitsum > NELLY_DETAIL_BITS) { + big_off = small_off; + small_off = last_off; + big_bitsum=bitsum; + small_bitsum=last_bitsum; + } else { + big_off = last_off; + big_bitsum=last_bitsum; + small_bitsum=bitsum; + } + + while (bitsum != NELLY_DETAIL_BITS && j <= 19) { + off = (big_off+small_off)>>1; + bitsum = sum_bits(sbuf, shift_saved, off); + if (bitsum > NELLY_DETAIL_BITS) { + big_off=off; + big_bitsum=bitsum; + } else { + small_off = off; + small_bitsum=bitsum; + } + j++; + } + + if (abs(big_bitsum-NELLY_DETAIL_BITS) >= + abs(small_bitsum-NELLY_DETAIL_BITS)) { + bitsum = small_bitsum; + } else { + small_off = big_off; + bitsum = big_bitsum; + } + } + + for (i = 0; i < NELLY_FILL_LEN; i++) { + tmp = sbuf[i]-small_off; + tmp = ((tmp>>(shift_saved-1))+1)>>1; + bits[i] = av_clip(tmp, 0, NELLY_BIT_CAP); + } + + if (bitsum > NELLY_DETAIL_BITS) { + tmp = i = 0; + while (tmp < NELLY_DETAIL_BITS) { + tmp += bits[i]; + i++; + } + + bits[i-1] -= tmp - NELLY_DETAIL_BITS; + for(; i < NELLY_FILL_LEN; i++) + bits[i] = 0; + } +} diff --git a/ffmpeg/libavcodec/nellymoser.h b/ffmpeg/libavcodec/nellymoser.h new file mode 100644 index 0000000..027fc7e --- /dev/null +++ b/ffmpeg/libavcodec/nellymoser.h @@ -0,0 +1,57 @@ +/* + * Common code between Nellymoser encoder and decoder + * Copyright (c) 2007 a840bda5870ba11f19698ff6eb9581dfb0f95fa5, + * 539459aeb7d425140b62a3ec7dbf6dc8e408a306, and + * 520e17cd55896441042b14df2566a6eb610ed444 + * Copyright (c) 2007 Loic Minier + * Benjamin Larsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * The 3 alphanumeric copyright notices are md5summed they are from the original + * implementors. The original code is available from http://code.google.com/p/nelly2pcm/ + */ + +#ifndef AVCODEC_NELLYMOSER_H +#define AVCODEC_NELLYMOSER_H + +#include "avcodec.h" + +#define NELLY_BANDS 23 +#define NELLY_BLOCK_LEN 64 +#define NELLY_HEADER_BITS 116 +#define NELLY_DETAIL_BITS 198 +#define NELLY_BUF_LEN 128 +#define NELLY_FILL_LEN 124 +#define NELLY_BIT_CAP 6 +#define NELLY_BASE_OFF 4228 +#define NELLY_BASE_SHIFT 19 +#define NELLY_SAMPLES (2 * NELLY_BUF_LEN) + +extern const float ff_nelly_dequantization_table[127]; +extern const uint8_t ff_nelly_band_sizes_table[NELLY_BANDS]; +extern const uint16_t ff_nelly_init_table[64]; +extern const int16_t ff_nelly_delta_table[32]; + +void ff_nelly_get_sample_bits(const float *buf, int *bits); + +#endif /* AVCODEC_NELLYMOSER_H */ diff --git a/ffmpeg/libavcodec/nellymoserdec.c b/ffmpeg/libavcodec/nellymoserdec.c new file mode 100644 index 0000000..42110a2 --- /dev/null +++ b/ffmpeg/libavcodec/nellymoserdec.c @@ -0,0 +1,209 @@ +/* + * NellyMoser audio decoder + * Copyright (c) 2007 a840bda5870ba11f19698ff6eb9581dfb0f95fa5, + * 539459aeb7d425140b62a3ec7dbf6dc8e408a306, and + * 520e17cd55896441042b14df2566a6eb610ed444 + * Copyright (c) 2007 Loic Minier + * Benjamin Larsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * The 3 alphanumeric copyright notices are md5summed they are from the original + * implementors. The original code is available from http://code.google.com/p/nelly2pcm/ + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "libavutil/lfg.h" +#include "libavutil/random_seed.h" +#include "avcodec.h" +#include "fft.h" +#include "fmtconvert.h" +#include "internal.h" +#include "nellymoser.h" +#include "sinewin.h" + +#define BITSTREAM_READER_LE +#include "get_bits.h" + + +typedef struct NellyMoserDecodeContext { + AVCodecContext* avctx; + AVLFG random_state; + GetBitContext gb; + float scale_bias; + AVFloatDSPContext fdsp; + FFTContext imdct_ctx; + DECLARE_ALIGNED(32, float, imdct_buf)[2][NELLY_BUF_LEN]; + float *imdct_out; + float *imdct_prev; +} NellyMoserDecodeContext; + +static void nelly_decode_block(NellyMoserDecodeContext *s, + const unsigned char block[NELLY_BLOCK_LEN], + float audio[NELLY_SAMPLES]) +{ + int i,j; + float buf[NELLY_FILL_LEN], pows[NELLY_FILL_LEN]; + float *aptr, *bptr, *pptr, val, pval; + int bits[NELLY_BUF_LEN]; + unsigned char v; + + init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8); + + bptr = buf; + pptr = pows; + val = ff_nelly_init_table[get_bits(&s->gb, 6)]; + for (i=0 ; i 0) + val += ff_nelly_delta_table[get_bits(&s->gb, 5)]; + pval = -pow(2, val/2048) * s->scale_bias; + for (j = 0; j < ff_nelly_band_sizes_table[i]; j++) { + *bptr++ = val; + *pptr++ = pval; + } + + } + + ff_nelly_get_sample_bits(buf, bits); + + for (i = 0; i < 2; i++) { + aptr = audio + i * NELLY_BUF_LEN; + + init_get_bits(&s->gb, block, NELLY_BLOCK_LEN * 8); + skip_bits_long(&s->gb, NELLY_HEADER_BITS + i*NELLY_DETAIL_BITS); + + for (j = 0; j < NELLY_FILL_LEN; j++) { + if (bits[j] <= 0) { + aptr[j] = M_SQRT1_2*pows[j]; + if (av_lfg_get(&s->random_state) & 1) + aptr[j] *= -1.0; + } else { + v = get_bits(&s->gb, bits[j]); + aptr[j] = ff_nelly_dequantization_table[(1<imdct_ctx.imdct_half(&s->imdct_ctx, s->imdct_out, aptr); + s->fdsp.vector_fmul_window(aptr, s->imdct_prev + NELLY_BUF_LEN / 2, + s->imdct_out, ff_sine_128, + NELLY_BUF_LEN / 2); + FFSWAP(float *, s->imdct_out, s->imdct_prev); + } +} + +static av_cold int decode_init(AVCodecContext * avctx) { + NellyMoserDecodeContext *s = avctx->priv_data; + + s->avctx = avctx; + s->imdct_out = s->imdct_buf[0]; + s->imdct_prev = s->imdct_buf[1]; + av_lfg_init(&s->random_state, 0); + ff_mdct_init(&s->imdct_ctx, 8, 1, 1.0); + + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + s->scale_bias = 1.0/(32768*8); + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + /* Generate overlap window */ + if (!ff_sine_128[127]) + ff_init_ff_sine_windows(7); + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + + return 0; +} + +static int decode_tag(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + const uint8_t *side=av_packet_get_side_data(avpkt, 'F', NULL); + int buf_size = avpkt->size; + NellyMoserDecodeContext *s = avctx->priv_data; + int blocks, i, ret; + float *samples_flt; + + blocks = buf_size / NELLY_BLOCK_LEN; + + if (blocks <= 0) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + if (buf_size % NELLY_BLOCK_LEN) { + av_log(avctx, AV_LOG_WARNING, "Leftover bytes: %d.\n", + buf_size % NELLY_BLOCK_LEN); + } + /* Normal numbers of blocks for sample rates: + * 8000 Hz - 1 + * 11025 Hz - 2 + * 16000 Hz - 3 + * 22050 Hz - 4 + * 44100 Hz - 8 + */ + if(side && blocks>1 && avctx->sample_rate%11025==0 && (1<<((side[0]>>2)&3)) == blocks) + avctx->sample_rate= 11025*(blocks/2); + + /* get output buffer */ + frame->nb_samples = NELLY_SAMPLES * blocks; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples_flt = (float *)frame->data[0]; + + for (i=0 ; ipriv_data; + + ff_mdct_end(&s->imdct_ctx); + + return 0; +} + +AVCodec ff_nellymoser_decoder = { + .name = "nellymoser", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_NELLYMOSER, + .priv_data_size = sizeof(NellyMoserDecodeContext), + .init = decode_init, + .close = decode_end, + .decode = decode_tag, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_PARAM_CHANGE, + .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/nellymoserenc.c b/ffmpeg/libavcodec/nellymoserenc.c new file mode 100644 index 0000000..b35820a --- /dev/null +++ b/ffmpeg/libavcodec/nellymoserenc.c @@ -0,0 +1,417 @@ +/* + * Nellymoser encoder + * This code is developed as part of Google Summer of Code 2008 Program. + * + * Copyright (c) 2008 Bartlomiej Wolowiec + * + * 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 + */ + +/** + * @file + * Nellymoser encoder + * by Bartlomiej Wolowiec + * + * Generic codec information: libavcodec/nellymoserdec.c + * + * Some information also from: http://samples.mplayerhq.hu/A-codecs/Nelly_Moser/ASAO/ASAO.zip + * (Copyright Joseph Artsimovich and UAB "DKD") + * + * for more information about nellymoser format, visit: + * http://wiki.multimedia.cx/index.php?title=Nellymoser + */ + +#include "libavutil/float_dsp.h" +#include "libavutil/mathematics.h" +#include "nellymoser.h" +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "fft.h" +#include "internal.h" +#include "sinewin.h" + +#define BITSTREAM_WRITER_LE +#include "put_bits.h" + +#define POW_TABLE_SIZE (1<<11) +#define POW_TABLE_OFFSET 3 +#define OPT_SIZE ((1<<15) + 3000) + +typedef struct NellyMoserEncodeContext { + AVCodecContext *avctx; + int last_frame; + AVFloatDSPContext fdsp; + FFTContext mdct_ctx; + AudioFrameQueue afq; + DECLARE_ALIGNED(32, float, mdct_out)[NELLY_SAMPLES]; + DECLARE_ALIGNED(32, float, in_buff)[NELLY_SAMPLES]; + DECLARE_ALIGNED(32, float, buf)[3 * NELLY_BUF_LEN]; ///< sample buffer + float (*opt )[OPT_SIZE]; + uint8_t (*path)[OPT_SIZE]; +} NellyMoserEncodeContext; + +static float pow_table[POW_TABLE_SIZE]; ///< -pow(2, -i / 2048.0 - 3.0); + +static const uint8_t sf_lut[96] = { + 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, + 5, 5, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 13, 13, 14, + 15, 15, 16, 17, 17, 18, 19, 19, 20, 21, 22, 22, 23, 24, 25, 26, + 27, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, + 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, + 54, 55, 55, 56, 57, 57, 58, 59, 59, 60, 60, 60, 61, 61, 61, 62, +}; + +static const uint8_t sf_delta_lut[78] = { + 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, + 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12, + 13, 13, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 22, 23, + 23, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 28, + 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, +}; + +static const uint8_t quant_lut[230] = { + 0, + + 0, 1, 2, + + 0, 1, 2, 3, 4, 5, 6, + + 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, + 12, 13, 13, 13, 14, + + 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, + 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 29, + 30, + + 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, + 21, 21, 22, 22, 23, 23, 24, 25, 26, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 44, 44, 45, 45, + 46, 47, 47, 48, 48, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52, + 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 57, + 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 61, + 61, 61, 61, 61, 62, +}; + +static const float quant_lut_mul[7] = { 0.0, 0.0, 2.0, 2.0, 5.0, 12.0, 36.6 }; +static const float quant_lut_add[7] = { 0.0, 0.0, 2.0, 7.0, 21.0, 56.0, 157.0 }; +static const uint8_t quant_lut_offset[8] = { 0, 0, 1, 4, 11, 32, 81, 230 }; + +static void apply_mdct(NellyMoserEncodeContext *s) +{ + float *in0 = s->buf; + float *in1 = s->buf + NELLY_BUF_LEN; + float *in2 = s->buf + 2 * NELLY_BUF_LEN; + + s->fdsp.vector_fmul (s->in_buff, in0, ff_sine_128, NELLY_BUF_LEN); + s->fdsp.vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in1, ff_sine_128, NELLY_BUF_LEN); + s->mdct_ctx.mdct_calc(&s->mdct_ctx, s->mdct_out, s->in_buff); + + s->fdsp.vector_fmul (s->in_buff, in1, ff_sine_128, NELLY_BUF_LEN); + s->fdsp.vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in2, ff_sine_128, NELLY_BUF_LEN); + s->mdct_ctx.mdct_calc(&s->mdct_ctx, s->mdct_out + NELLY_BUF_LEN, s->in_buff); +} + +static av_cold int encode_end(AVCodecContext *avctx) +{ + NellyMoserEncodeContext *s = avctx->priv_data; + + ff_mdct_end(&s->mdct_ctx); + + if (s->avctx->trellis) { + av_free(s->opt); + av_free(s->path); + } + ff_af_queue_close(&s->afq); + + return 0; +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + NellyMoserEncodeContext *s = avctx->priv_data; + int i, ret; + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "Nellymoser supports only 1 channel\n"); + return AVERROR(EINVAL); + } + + if (avctx->sample_rate != 8000 && avctx->sample_rate != 16000 && + avctx->sample_rate != 11025 && + avctx->sample_rate != 22050 && avctx->sample_rate != 44100 && + avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { + av_log(avctx, AV_LOG_ERROR, "Nellymoser works only with 8000, 16000, 11025, 22050 and 44100 sample rate\n"); + return AVERROR(EINVAL); + } + + avctx->frame_size = NELLY_SAMPLES; + avctx->delay = NELLY_BUF_LEN; + ff_af_queue_init(avctx, &s->afq); + s->avctx = avctx; + if ((ret = ff_mdct_init(&s->mdct_ctx, 8, 0, 32768.0)) < 0) + goto error; + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + /* Generate overlap window */ + ff_init_ff_sine_windows(7); + for (i = 0; i < POW_TABLE_SIZE; i++) + pow_table[i] = -pow(2, -i / 2048.0 - 3.0 + POW_TABLE_OFFSET); + + if (s->avctx->trellis) { + s->opt = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(float )); + s->path = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(uint8_t)); + if (!s->opt || !s->path) { + ret = AVERROR(ENOMEM); + goto error; + } + } + + return 0; +error: + encode_end(avctx); + return ret; +} + +#define find_best(val, table, LUT, LUT_add, LUT_size) \ + best_idx = \ + LUT[av_clip ((lrintf(val) >> 8) + LUT_add, 0, LUT_size - 1)]; \ + if (fabs(val - table[best_idx]) > fabs(val - table[best_idx + 1])) \ + best_idx++; + +static void get_exponent_greedy(NellyMoserEncodeContext *s, float *cand, int *idx_table) +{ + int band, best_idx, power_idx = 0; + float power_candidate; + + //base exponent + find_best(cand[0], ff_nelly_init_table, sf_lut, -20, 96); + idx_table[0] = best_idx; + power_idx = ff_nelly_init_table[best_idx]; + + for (band = 1; band < NELLY_BANDS; band++) { + power_candidate = cand[band] - power_idx; + find_best(power_candidate, ff_nelly_delta_table, sf_delta_lut, 37, 78); + idx_table[band] = best_idx; + power_idx += ff_nelly_delta_table[best_idx]; + } +} + +static inline float distance(float x, float y, int band) +{ + //return pow(fabs(x-y), 2.0); + float tmp = x - y; + return tmp * tmp; +} + +static void get_exponent_dynamic(NellyMoserEncodeContext *s, float *cand, int *idx_table) +{ + int i, j, band, best_idx; + float power_candidate, best_val; + + float (*opt )[OPT_SIZE] = s->opt ; + uint8_t(*path)[OPT_SIZE] = s->path; + + for (i = 0; i < NELLY_BANDS * OPT_SIZE; i++) { + opt[0][i] = INFINITY; + } + + for (i = 0; i < 64; i++) { + opt[0][ff_nelly_init_table[i]] = distance(cand[0], ff_nelly_init_table[i], 0); + path[0][ff_nelly_init_table[i]] = i; + } + + for (band = 1; band < NELLY_BANDS; band++) { + int q, c = 0; + float tmp; + int idx_min, idx_max, idx; + power_candidate = cand[band]; + for (q = 1000; !c && q < OPT_SIZE; q <<= 2) { + idx_min = FFMAX(0, cand[band] - q); + idx_max = FFMIN(OPT_SIZE, cand[band - 1] + q); + for (i = FFMAX(0, cand[band - 1] - q); i < FFMIN(OPT_SIZE, cand[band - 1] + q); i++) { + if ( isinf(opt[band - 1][i]) ) + continue; + for (j = 0; j < 32; j++) { + idx = i + ff_nelly_delta_table[j]; + if (idx > idx_max) + break; + if (idx >= idx_min) { + tmp = opt[band - 1][i] + distance(idx, power_candidate, band); + if (opt[band][idx] > tmp) { + opt[band][idx] = tmp; + path[band][idx] = j; + c = 1; + } + } + } + } + } + assert(c); //FIXME + } + + best_val = INFINITY; + best_idx = -1; + band = NELLY_BANDS - 1; + for (i = 0; i < OPT_SIZE; i++) { + if (best_val > opt[band][i]) { + best_val = opt[band][i]; + best_idx = i; + } + } + for (band = NELLY_BANDS - 1; band >= 0; band--) { + idx_table[band] = path[band][best_idx]; + if (band) { + best_idx -= ff_nelly_delta_table[path[band][best_idx]]; + } + } +} + +/** + * Encode NELLY_SAMPLES samples. It assumes, that samples contains 3 * NELLY_BUF_LEN values + * @param s encoder context + * @param output output buffer + * @param output_size size of output buffer + */ +static void encode_block(NellyMoserEncodeContext *s, unsigned char *output, int output_size) +{ + PutBitContext pb; + int i, j, band, block, best_idx, power_idx = 0; + float power_val, coeff, coeff_sum; + float pows[NELLY_FILL_LEN]; + int bits[NELLY_BUF_LEN], idx_table[NELLY_BANDS]; + float cand[NELLY_BANDS]; + + apply_mdct(s); + + init_put_bits(&pb, output, output_size * 8); + + i = 0; + for (band = 0; band < NELLY_BANDS; band++) { + coeff_sum = 0; + for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) { + coeff_sum += s->mdct_out[i ] * s->mdct_out[i ] + + s->mdct_out[i + NELLY_BUF_LEN] * s->mdct_out[i + NELLY_BUF_LEN]; + } + cand[band] = + log(FFMAX(1.0, coeff_sum / (ff_nelly_band_sizes_table[band] << 7))) * 1024.0 / M_LN2; + } + + if (s->avctx->trellis) { + get_exponent_dynamic(s, cand, idx_table); + } else { + get_exponent_greedy(s, cand, idx_table); + } + + i = 0; + for (band = 0; band < NELLY_BANDS; band++) { + if (band) { + power_idx += ff_nelly_delta_table[idx_table[band]]; + put_bits(&pb, 5, idx_table[band]); + } else { + power_idx = ff_nelly_init_table[idx_table[0]]; + put_bits(&pb, 6, idx_table[0]); + } + power_val = pow_table[power_idx & 0x7FF] / (1 << ((power_idx >> 11) + POW_TABLE_OFFSET)); + for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) { + s->mdct_out[i] *= power_val; + s->mdct_out[i + NELLY_BUF_LEN] *= power_val; + pows[i] = power_idx; + } + } + + ff_nelly_get_sample_bits(pows, bits); + + for (block = 0; block < 2; block++) { + for (i = 0; i < NELLY_FILL_LEN; i++) { + if (bits[i] > 0) { + const float *table = ff_nelly_dequantization_table + (1 << bits[i]) - 1; + coeff = s->mdct_out[block * NELLY_BUF_LEN + i]; + best_idx = + quant_lut[av_clip ( + coeff * quant_lut_mul[bits[i]] + quant_lut_add[bits[i]], + quant_lut_offset[bits[i]], + quant_lut_offset[bits[i]+1] - 1 + )]; + if (fabs(coeff - table[best_idx]) > fabs(coeff - table[best_idx + 1])) + best_idx++; + + put_bits(&pb, bits[i], best_idx); + } + } + if (!block) + put_bits(&pb, NELLY_HEADER_BITS + NELLY_DETAIL_BITS - put_bits_count(&pb), 0); + } + + flush_put_bits(&pb); + memset(put_bits_ptr(&pb), 0, output + output_size - put_bits_ptr(&pb)); +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + NellyMoserEncodeContext *s = avctx->priv_data; + int ret; + + if (s->last_frame) + return 0; + + memcpy(s->buf, s->buf + NELLY_SAMPLES, NELLY_BUF_LEN * sizeof(*s->buf)); + if (frame) { + memcpy(s->buf + NELLY_BUF_LEN, frame->data[0], + frame->nb_samples * sizeof(*s->buf)); + if (frame->nb_samples < NELLY_SAMPLES) { + memset(s->buf + NELLY_BUF_LEN + frame->nb_samples, 0, + (NELLY_SAMPLES - frame->nb_samples) * sizeof(*s->buf)); + if (frame->nb_samples >= NELLY_BUF_LEN) + s->last_frame = 1; + } + if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) + return ret; + } else { + memset(s->buf + NELLY_BUF_LEN, 0, NELLY_SAMPLES * sizeof(*s->buf)); + s->last_frame = 1; + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, NELLY_BLOCK_LEN)) < 0) + return ret; + encode_block(s, avpkt->data, avpkt->size); + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_nellymoser_encoder = { + .name = "nellymoser", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_NELLYMOSER, + .priv_data_size = sizeof(NellyMoserEncodeContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/noise_bsf.c b/ffmpeg/libavcodec/noise_bsf.c new file mode 100644 index 0000000..763af79 --- /dev/null +++ b/ffmpeg/libavcodec/noise_bsf.c @@ -0,0 +1,53 @@ +/* + * copyright (c) 2006 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 + +#include "avcodec.h" +#include "libavutil/mem.h" + + +static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + unsigned int *state= bsfc->priv_data; + int amount= args ? atoi(args) : (*state % 10001+1); + int i; + + if(amount <= 0) + return AVERROR(EINVAL); + + *poutbuf= av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + + memcpy(*poutbuf, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + for(i=0; i +#include +#include + +#include "libavutil/bswap.h" +#include "libavutil/common.h" +#include "libavutil/lzo.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" +#include "rtjpeg.h" + +typedef struct { + AVFrame pic; + int codec_frameheader; + int quality; + int width, height; + unsigned int decomp_size; + unsigned char *decomp_buf; + uint32_t lq[64], cq[64]; + RTJpegContext rtj; + DSPContext dsp; +} NuvContext; + +static const uint8_t fallback_lquant[] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static const uint8_t fallback_cquant[] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +/** + * @brief copy frame data from buffer to AVFrame, handling stride. + * @param f destination AVFrame + * @param src source buffer, does not use any line-stride + * @param width width of the video frame + * @param height height of the video frame + */ +static void copy_frame(AVFrame *f, const uint8_t *src, int width, int height) +{ + AVPicture pic; + avpicture_fill(&pic, src, AV_PIX_FMT_YUV420P, width, height); + av_picture_copy((AVPicture *)f, &pic, AV_PIX_FMT_YUV420P, width, height); +} + +/** + * @brief extract quantization tables from codec data into our context + */ +static int get_quant(AVCodecContext *avctx, NuvContext *c, const uint8_t *buf, + int size) +{ + int i; + if (size < 2 * 64 * 4) { + av_log(avctx, AV_LOG_ERROR, "insufficient rtjpeg quant data\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < 64; i++, buf += 4) + c->lq[i] = AV_RL32(buf); + for (i = 0; i < 64; i++, buf += 4) + c->cq[i] = AV_RL32(buf); + return 0; +} + +/** + * @brief set quantization tables from a quality value + */ +static void get_quant_quality(NuvContext *c, int quality) +{ + int i; + quality = FFMAX(quality, 1); + for (i = 0; i < 64; i++) { + c->lq[i] = (fallback_lquant[i] << 7) / quality; + c->cq[i] = (fallback_cquant[i] << 7) / quality; + } +} + +static int codec_reinit(AVCodecContext *avctx, int width, int height, + int quality) +{ + NuvContext *c = avctx->priv_data; + int ret; + + width = FFALIGN(width, 2); + height = FFALIGN(height, 2); + if (quality >= 0) + get_quant_quality(c, quality); + if (width != c->width || height != c->height) { + // also reserve space for a possible additional header + int buf_size = 24 + height * width * 3 / 2 + AV_LZO_OUTPUT_PADDING; + if (buf_size > INT_MAX/8) + return -1; + if ((ret = av_image_check_size(height, width, 0, avctx)) < 0) + return ret; + avctx->width = c->width = width; + avctx->height = c->height = height; + av_fast_malloc(&c->decomp_buf, &c->decomp_size, + buf_size); + if (!c->decomp_buf) { + av_log(avctx, AV_LOG_ERROR, + "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, + c->lq, c->cq); + return 1; + } else if (quality != c->quality) + ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, + c->lq, c->cq); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + NuvContext *c = avctx->priv_data; + AVFrame *picture = data; + int orig_size = buf_size; + int keyframe; + int size_change = 0; + int result, init_frame = !avctx->frame_number; + enum { + NUV_UNCOMPRESSED = '0', + NUV_RTJPEG = '1', + NUV_RTJPEG_IN_LZO = '2', + NUV_LZO = '3', + NUV_BLACK = 'N', + NUV_COPY_LAST = 'L' + } comptype; + + if (buf_size < 12) { + av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); + return AVERROR_INVALIDDATA; + } + + // codec data (rtjpeg quant tables) + if (buf[0] == 'D' && buf[1] == 'R') { + int ret; + // skip rest of the frameheader. + buf = &buf[12]; + buf_size -= 12; + ret = get_quant(avctx, c, buf, buf_size); + if (ret < 0) + return ret; + ff_rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, + c->cq); + return orig_size; + } + + if (buf_size < 12 || buf[0] != 'V') { + av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n"); + return AVERROR_INVALIDDATA; + } + comptype = buf[1]; + switch (comptype) { + case NUV_RTJPEG_IN_LZO: + case NUV_RTJPEG: + keyframe = !buf[2]; + break; + case NUV_COPY_LAST: + keyframe = 0; + break; + default: + keyframe = 1; + break; + } +retry: + // skip rest of the frameheader. + buf = &buf[12]; + buf_size -= 12; + if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) { + int outlen = c->decomp_size - AV_LZO_OUTPUT_PADDING, inlen = buf_size; + if (av_lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen)) + av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); + buf = c->decomp_buf; + buf_size = c->decomp_size - AV_LZO_OUTPUT_PADDING - outlen; + } + if (c->codec_frameheader) { + int w, h, q; + if (buf_size < RTJPEG_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Too small NUV video frame\n"); + return AVERROR_INVALIDDATA; + } + // There seem to exist two variants of this header: one starts with 'V' + // and 5 bytes unknown, the other matches current MythTV and is 4 bytes size, + // 1 byte header size (== 12), 1 byte version (== 0) + if (buf[0] != 'V' && AV_RL16(&buf[4]) != 0x000c) { + av_log(avctx, AV_LOG_ERROR, "Unknown secondary frame header (wrong codec_tag?)\n"); + return AVERROR_INVALIDDATA; + } + w = AV_RL16(&buf[6]); + h = AV_RL16(&buf[8]); + q = buf[10]; + if ((result = codec_reinit(avctx, w, h, q)) < 0) + return result; + if (result) { + buf = avpkt->data; + buf_size = avpkt->size; + size_change = 1; + goto retry; + } + buf = &buf[RTJPEG_HEADER_SIZE]; + buf_size -= RTJPEG_HEADER_SIZE; + } + + if (size_change || keyframe) { + av_frame_unref(&c->pic); + init_frame = 1; + } + + if ((result = ff_reget_buffer(avctx, &c->pic)) < 0) + return result; + if (init_frame) { + memset(c->pic.data[0], 0, avctx->height * c->pic.linesize[0]); + memset(c->pic.data[1], 0x80, avctx->height * c->pic.linesize[1] / 2); + memset(c->pic.data[2], 0x80, avctx->height * c->pic.linesize[2] / 2); + } + + c->pic.pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + c->pic.key_frame = keyframe; + // decompress/copy/whatever data + switch (comptype) { + case NUV_LZO: + case NUV_UNCOMPRESSED: { + int height = c->height; + if (buf_size < c->width * height * 3 / 2) { + av_log(avctx, AV_LOG_ERROR, "uncompressed frame too short\n"); + height = buf_size / c->width / 3 * 2; + } + if(height > 0) + copy_frame(&c->pic, buf, c->width, height); + break; + } + case NUV_RTJPEG_IN_LZO: + case NUV_RTJPEG: + ff_rtjpeg_decode_frame_yuv420(&c->rtj, &c->pic, buf, buf_size); + break; + case NUV_BLACK: + memset(c->pic.data[0], 0, c->width * c->height); + memset(c->pic.data[1], 128, c->width * c->height / 4); + memset(c->pic.data[2], 128, c->width * c->height / 4); + break; + case NUV_COPY_LAST: + /* nothing more to do here */ + break; + default: + av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); + return AVERROR_INVALIDDATA; + } + + if ((result = av_frame_ref(picture, &c->pic)) < 0) + return result; + + *got_frame = 1; + return orig_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + NuvContext *c = avctx->priv_data; + int ret; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + c->pic.data[0] = NULL; + c->decomp_buf = NULL; + c->quality = -1; + c->width = 0; + c->height = 0; + + c->codec_frameheader = avctx->codec_tag == MKTAG('R', 'J', 'P', 'G'); + + if (avctx->extradata_size) + get_quant(avctx, c, avctx->extradata, avctx->extradata_size); + + ff_dsputil_init(&c->dsp, avctx); + + if ((ret = codec_reinit(avctx, avctx->width, avctx->height, -1)) < 0) + return ret; + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + NuvContext *c = avctx->priv_data; + + av_freep(&c->decomp_buf); + av_frame_unref(&c->pic); + + return 0; +} + +AVCodec ff_nuv_decoder = { + .name = "nuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NUV, + .priv_data_size = sizeof(NuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"), +}; diff --git a/ffmpeg/libavcodec/old_codec_ids.h b/ffmpeg/libavcodec/old_codec_ids.h new file mode 100644 index 0000000..d8a8f74 --- /dev/null +++ b/ffmpeg/libavcodec/old_codec_ids.h @@ -0,0 +1,397 @@ +/* + * 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 + */ + +#ifndef AVCODEC_OLD_CODEC_IDS_H +#define AVCODEC_OLD_CODEC_IDS_H + +#include "libavutil/common.h" + +/* + * This header exists to prevent new codec IDs from being accidentally added to + * the deprecated list. + * Do not include it directly. It will be removed on next major bump + * + * Do not add new items to this list. Use the AVCodecID enum instead. + */ + + CODEC_ID_NONE = AV_CODEC_ID_NONE, + + /* video codecs */ + CODEC_ID_MPEG1VIDEO, + CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding + CODEC_ID_MPEG2VIDEO_XVMC, + CODEC_ID_H261, + CODEC_ID_H263, + CODEC_ID_RV10, + CODEC_ID_RV20, + CODEC_ID_MJPEG, + CODEC_ID_MJPEGB, + CODEC_ID_LJPEG, + CODEC_ID_SP5X, + CODEC_ID_JPEGLS, + CODEC_ID_MPEG4, + CODEC_ID_RAWVIDEO, + CODEC_ID_MSMPEG4V1, + CODEC_ID_MSMPEG4V2, + CODEC_ID_MSMPEG4V3, + CODEC_ID_WMV1, + CODEC_ID_WMV2, + CODEC_ID_H263P, + CODEC_ID_H263I, + CODEC_ID_FLV1, + CODEC_ID_SVQ1, + CODEC_ID_SVQ3, + CODEC_ID_DVVIDEO, + CODEC_ID_HUFFYUV, + CODEC_ID_CYUV, + CODEC_ID_H264, + CODEC_ID_INDEO3, + CODEC_ID_VP3, + CODEC_ID_THEORA, + CODEC_ID_ASV1, + CODEC_ID_ASV2, + CODEC_ID_FFV1, + CODEC_ID_4XM, + CODEC_ID_VCR1, + CODEC_ID_CLJR, + CODEC_ID_MDEC, + CODEC_ID_ROQ, + CODEC_ID_INTERPLAY_VIDEO, + CODEC_ID_XAN_WC3, + CODEC_ID_XAN_WC4, + CODEC_ID_RPZA, + CODEC_ID_CINEPAK, + CODEC_ID_WS_VQA, + CODEC_ID_MSRLE, + CODEC_ID_MSVIDEO1, + CODEC_ID_IDCIN, + CODEC_ID_8BPS, + CODEC_ID_SMC, + CODEC_ID_FLIC, + CODEC_ID_TRUEMOTION1, + CODEC_ID_VMDVIDEO, + CODEC_ID_MSZH, + CODEC_ID_ZLIB, + CODEC_ID_QTRLE, + CODEC_ID_TSCC, + CODEC_ID_ULTI, + CODEC_ID_QDRAW, + CODEC_ID_VIXL, + CODEC_ID_QPEG, + CODEC_ID_PNG, + CODEC_ID_PPM, + CODEC_ID_PBM, + CODEC_ID_PGM, + CODEC_ID_PGMYUV, + CODEC_ID_PAM, + CODEC_ID_FFVHUFF, + CODEC_ID_RV30, + CODEC_ID_RV40, + CODEC_ID_VC1, + CODEC_ID_WMV3, + CODEC_ID_LOCO, + CODEC_ID_WNV1, + CODEC_ID_AASC, + CODEC_ID_INDEO2, + CODEC_ID_FRAPS, + CODEC_ID_TRUEMOTION2, + CODEC_ID_BMP, + CODEC_ID_CSCD, + CODEC_ID_MMVIDEO, + CODEC_ID_ZMBV, + CODEC_ID_AVS, + CODEC_ID_SMACKVIDEO, + CODEC_ID_NUV, + CODEC_ID_KMVC, + CODEC_ID_FLASHSV, + CODEC_ID_CAVS, + CODEC_ID_JPEG2000, + CODEC_ID_VMNC, + CODEC_ID_VP5, + CODEC_ID_VP6, + CODEC_ID_VP6F, + CODEC_ID_TARGA, + CODEC_ID_DSICINVIDEO, + CODEC_ID_TIERTEXSEQVIDEO, + CODEC_ID_TIFF, + CODEC_ID_GIF, + CODEC_ID_DXA, + CODEC_ID_DNXHD, + CODEC_ID_THP, + CODEC_ID_SGI, + CODEC_ID_C93, + CODEC_ID_BETHSOFTVID, + CODEC_ID_PTX, + CODEC_ID_TXD, + CODEC_ID_VP6A, + CODEC_ID_AMV, + CODEC_ID_VB, + CODEC_ID_PCX, + CODEC_ID_SUNRAST, + CODEC_ID_INDEO4, + CODEC_ID_INDEO5, + CODEC_ID_MIMIC, + CODEC_ID_RL2, + CODEC_ID_ESCAPE124, + CODEC_ID_DIRAC, + CODEC_ID_BFI, + CODEC_ID_CMV, + CODEC_ID_MOTIONPIXELS, + CODEC_ID_TGV, + CODEC_ID_TGQ, + CODEC_ID_TQI, + CODEC_ID_AURA, + CODEC_ID_AURA2, + CODEC_ID_V210X, + CODEC_ID_TMV, + CODEC_ID_V210, + CODEC_ID_DPX, + CODEC_ID_MAD, + CODEC_ID_FRWU, + CODEC_ID_FLASHSV2, + CODEC_ID_CDGRAPHICS, + CODEC_ID_R210, + CODEC_ID_ANM, + CODEC_ID_BINKVIDEO, + CODEC_ID_IFF_ILBM, + CODEC_ID_IFF_BYTERUN1, + CODEC_ID_KGV1, + CODEC_ID_YOP, + CODEC_ID_VP8, + CODEC_ID_PICTOR, + CODEC_ID_ANSI, + CODEC_ID_A64_MULTI, + CODEC_ID_A64_MULTI5, + CODEC_ID_R10K, + CODEC_ID_MXPEG, + CODEC_ID_LAGARITH, + CODEC_ID_PRORES, + CODEC_ID_JV, + CODEC_ID_DFA, + CODEC_ID_WMV3IMAGE, + CODEC_ID_VC1IMAGE, + CODEC_ID_UTVIDEO, + CODEC_ID_BMV_VIDEO, + CODEC_ID_VBLE, + CODEC_ID_DXTORY, + CODEC_ID_V410, + CODEC_ID_XWD, + CODEC_ID_CDXL, + CODEC_ID_XBM, + CODEC_ID_ZEROCODEC, + CODEC_ID_MSS1, + CODEC_ID_MSA1, + CODEC_ID_TSCC2, + CODEC_ID_MTS2, + CODEC_ID_CLLC, + CODEC_ID_Y41P = MKBETAG('Y','4','1','P'), + CODEC_ID_ESCAPE130 = MKBETAG('E','1','3','0'), + CODEC_ID_EXR = MKBETAG('0','E','X','R'), + CODEC_ID_AVRP = MKBETAG('A','V','R','P'), + + CODEC_ID_G2M = MKBETAG( 0 ,'G','2','M'), + CODEC_ID_AVUI = MKBETAG('A','V','U','I'), + CODEC_ID_AYUV = MKBETAG('A','Y','U','V'), + CODEC_ID_V308 = MKBETAG('V','3','0','8'), + CODEC_ID_V408 = MKBETAG('V','4','0','8'), + CODEC_ID_YUV4 = MKBETAG('Y','U','V','4'), + CODEC_ID_SANM = MKBETAG('S','A','N','M'), + CODEC_ID_PAF_VIDEO = MKBETAG('P','A','F','V'), + CODEC_ID_SNOW = AV_CODEC_ID_SNOW, + + /* various PCM "codecs" */ + CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs + CODEC_ID_PCM_S16LE = 0x10000, + CODEC_ID_PCM_S16BE, + CODEC_ID_PCM_U16LE, + CODEC_ID_PCM_U16BE, + CODEC_ID_PCM_S8, + CODEC_ID_PCM_U8, + CODEC_ID_PCM_MULAW, + CODEC_ID_PCM_ALAW, + CODEC_ID_PCM_S32LE, + CODEC_ID_PCM_S32BE, + CODEC_ID_PCM_U32LE, + CODEC_ID_PCM_U32BE, + CODEC_ID_PCM_S24LE, + CODEC_ID_PCM_S24BE, + CODEC_ID_PCM_U24LE, + CODEC_ID_PCM_U24BE, + CODEC_ID_PCM_S24DAUD, + CODEC_ID_PCM_ZORK, + CODEC_ID_PCM_S16LE_PLANAR, + CODEC_ID_PCM_DVD, + CODEC_ID_PCM_F32BE, + CODEC_ID_PCM_F32LE, + CODEC_ID_PCM_F64BE, + CODEC_ID_PCM_F64LE, + CODEC_ID_PCM_BLURAY, + CODEC_ID_PCM_LXF, + CODEC_ID_S302M, + CODEC_ID_PCM_S8_PLANAR, + + /* various ADPCM codecs */ + CODEC_ID_ADPCM_IMA_QT = 0x11000, + CODEC_ID_ADPCM_IMA_WAV, + CODEC_ID_ADPCM_IMA_DK3, + CODEC_ID_ADPCM_IMA_DK4, + CODEC_ID_ADPCM_IMA_WS, + CODEC_ID_ADPCM_IMA_SMJPEG, + CODEC_ID_ADPCM_MS, + CODEC_ID_ADPCM_4XM, + CODEC_ID_ADPCM_XA, + CODEC_ID_ADPCM_ADX, + CODEC_ID_ADPCM_EA, + CODEC_ID_ADPCM_G726, + CODEC_ID_ADPCM_CT, + CODEC_ID_ADPCM_SWF, + CODEC_ID_ADPCM_YAMAHA, + CODEC_ID_ADPCM_SBPRO_4, + CODEC_ID_ADPCM_SBPRO_3, + CODEC_ID_ADPCM_SBPRO_2, + CODEC_ID_ADPCM_THP, + CODEC_ID_ADPCM_IMA_AMV, + CODEC_ID_ADPCM_EA_R1, + CODEC_ID_ADPCM_EA_R3, + CODEC_ID_ADPCM_EA_R2, + CODEC_ID_ADPCM_IMA_EA_SEAD, + CODEC_ID_ADPCM_IMA_EA_EACS, + CODEC_ID_ADPCM_EA_XAS, + CODEC_ID_ADPCM_EA_MAXIS_XA, + CODEC_ID_ADPCM_IMA_ISS, + CODEC_ID_ADPCM_G722, + CODEC_ID_ADPCM_IMA_APC, + CODEC_ID_VIMA = MKBETAG('V','I','M','A'), + + /* AMR */ + CODEC_ID_AMR_NB = 0x12000, + CODEC_ID_AMR_WB, + + /* RealAudio codecs*/ + CODEC_ID_RA_144 = 0x13000, + CODEC_ID_RA_288, + + /* various DPCM codecs */ + CODEC_ID_ROQ_DPCM = 0x14000, + CODEC_ID_INTERPLAY_DPCM, + CODEC_ID_XAN_DPCM, + CODEC_ID_SOL_DPCM, + + /* audio codecs */ + CODEC_ID_MP2 = 0x15000, + CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 + CODEC_ID_AAC, + CODEC_ID_AC3, + CODEC_ID_DTS, + CODEC_ID_VORBIS, + CODEC_ID_DVAUDIO, + CODEC_ID_WMAV1, + CODEC_ID_WMAV2, + CODEC_ID_MACE3, + CODEC_ID_MACE6, + CODEC_ID_VMDAUDIO, + CODEC_ID_FLAC, + CODEC_ID_MP3ADU, + CODEC_ID_MP3ON4, + CODEC_ID_SHORTEN, + CODEC_ID_ALAC, + CODEC_ID_WESTWOOD_SND1, + CODEC_ID_GSM, ///< as in Berlin toast format + CODEC_ID_QDM2, + CODEC_ID_COOK, + CODEC_ID_TRUESPEECH, + CODEC_ID_TTA, + CODEC_ID_SMACKAUDIO, + CODEC_ID_QCELP, + CODEC_ID_WAVPACK, + CODEC_ID_DSICINAUDIO, + CODEC_ID_IMC, + CODEC_ID_MUSEPACK7, + CODEC_ID_MLP, + CODEC_ID_GSM_MS, /* as found in WAV */ + CODEC_ID_ATRAC3, + CODEC_ID_VOXWARE, + CODEC_ID_APE, + CODEC_ID_NELLYMOSER, + CODEC_ID_MUSEPACK8, + CODEC_ID_SPEEX, + CODEC_ID_WMAVOICE, + CODEC_ID_WMAPRO, + CODEC_ID_WMALOSSLESS, + CODEC_ID_ATRAC3P, + CODEC_ID_EAC3, + CODEC_ID_SIPR, + CODEC_ID_MP1, + CODEC_ID_TWINVQ, + CODEC_ID_TRUEHD, + CODEC_ID_MP4ALS, + CODEC_ID_ATRAC1, + CODEC_ID_BINKAUDIO_RDFT, + CODEC_ID_BINKAUDIO_DCT, + CODEC_ID_AAC_LATM, + CODEC_ID_QDMC, + CODEC_ID_CELT, + CODEC_ID_G723_1, + CODEC_ID_G729, + CODEC_ID_8SVX_EXP, + CODEC_ID_8SVX_FIB, + CODEC_ID_BMV_AUDIO, + CODEC_ID_RALF, + CODEC_ID_IAC, + CODEC_ID_ILBC, + CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), + CODEC_ID_SONIC = MKBETAG('S','O','N','C'), + CODEC_ID_SONIC_LS = MKBETAG('S','O','N','L'), + CODEC_ID_PAF_AUDIO = MKBETAG('P','A','F','A'), + CODEC_ID_OPUS = MKBETAG('O','P','U','S'), + + /* subtitle codecs */ + CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. + CODEC_ID_DVD_SUBTITLE = 0x17000, + CODEC_ID_DVB_SUBTITLE, + CODEC_ID_TEXT, ///< raw UTF-8 text + CODEC_ID_XSUB, + CODEC_ID_SSA, + CODEC_ID_MOV_TEXT, + CODEC_ID_HDMV_PGS_SUBTITLE, + CODEC_ID_DVB_TELETEXT, + CODEC_ID_SRT, + CODEC_ID_MICRODVD = MKBETAG('m','D','V','D'), + CODEC_ID_EIA_608 = MKBETAG('c','6','0','8'), + CODEC_ID_JACOSUB = MKBETAG('J','S','U','B'), + CODEC_ID_SAMI = MKBETAG('S','A','M','I'), + CODEC_ID_REALTEXT = MKBETAG('R','T','X','T'), + CODEC_ID_SUBVIEWER = MKBETAG('S','u','b','V'), + + /* other specific kind of codecs (generally used for attachments) */ + CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. + CODEC_ID_TTF = 0x18000, + CODEC_ID_BINTEXT = MKBETAG('B','T','X','T'), + CODEC_ID_XBIN = MKBETAG('X','B','I','N'), + CODEC_ID_IDF = MKBETAG( 0 ,'I','D','F'), + CODEC_ID_OTF = MKBETAG( 0 ,'O','T','F'), + + CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it + + CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + * stream (only used by libavformat) */ + CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems + * stream (only used by libavformat) */ + CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. + +#endif /* AVCODEC_OLD_CODEC_IDS_H */ diff --git a/ffmpeg/libavcodec/options.c b/ffmpeg/libavcodec/options.c new file mode 100644 index 0000000..1d10128 --- /dev/null +++ b/ffmpeg/libavcodec/options.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * Options definition for AVCodecContext. + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/avassert.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include /* FLT_MIN, FLT_MAX */ +#include + +#include "options_table.h" + +static const char* context_to_name(void* ptr) { + AVCodecContext *avc= ptr; + + if(avc && avc->codec && avc->codec->name) + return avc->codec->name; + else + return "NULL"; +} + +static void *codec_child_next(void *obj, void *prev) +{ + AVCodecContext *s = obj; + if (!prev && s->codec && s->codec->priv_class && s->priv_data) + return s->priv_data; + return NULL; +} + +static const AVClass *codec_child_class_next(const AVClass *prev) +{ + AVCodec *c = NULL; + + /* find the codec that corresponds to prev */ + while (prev && (c = av_codec_next(c))) + if (c->priv_class == prev) + break; + + /* find next codec with priv options */ + while (c = av_codec_next(c)) + if (c->priv_class) + return c->priv_class; + return NULL; +} + +static AVClassCategory get_category(void *ptr) +{ + AVCodecContext* avctx = ptr; + if(avctx->codec && avctx->codec->decode) return AV_CLASS_CATEGORY_DECODER; + else return AV_CLASS_CATEGORY_ENCODER; +} + +static const AVClass av_codec_context_class = { + .class_name = "AVCodecContext", + .item_name = context_to_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = offsetof(AVCodecContext, log_level_offset), + .child_next = codec_child_next, + .child_class_next = codec_child_class_next, + .category = AV_CLASS_CATEGORY_ENCODER, + .get_category = get_category, +}; + +#if FF_API_ALLOC_CONTEXT +void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){ + AVCodec c= {0}; + c.type= codec_type; + avcodec_get_context_defaults3(s, &c); +} +#endif + +int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) +{ + int flags=0; + memset(s, 0, sizeof(AVCodecContext)); + + s->av_class = &av_codec_context_class; + + s->codec_type = codec ? codec->type : AVMEDIA_TYPE_UNKNOWN; + if(s->codec_type == AVMEDIA_TYPE_AUDIO) + flags= AV_OPT_FLAG_AUDIO_PARAM; + else if(s->codec_type == AVMEDIA_TYPE_VIDEO) + flags= AV_OPT_FLAG_VIDEO_PARAM; + else if(s->codec_type == AVMEDIA_TYPE_SUBTITLE) + flags= AV_OPT_FLAG_SUBTITLE_PARAM; + av_opt_set_defaults2(s, flags, flags); + + s->time_base = (AVRational){0,1}; + s->get_buffer2 = avcodec_default_get_buffer2; + s->get_format = avcodec_default_get_format; + s->execute = avcodec_default_execute; + s->execute2 = avcodec_default_execute2; + s->sample_aspect_ratio = (AVRational){0,1}; + s->pix_fmt = AV_PIX_FMT_NONE; + s->sample_fmt = AV_SAMPLE_FMT_NONE; + s->timecode_frame_start = -1; + + s->reordered_opaque = AV_NOPTS_VALUE; + if(codec && codec->priv_data_size){ + if(!s->priv_data){ + s->priv_data= av_mallocz(codec->priv_data_size); + if (!s->priv_data) { + return AVERROR(ENOMEM); + } + } + if(codec->priv_class){ + *(const AVClass**)s->priv_data = codec->priv_class; + av_opt_set_defaults(s->priv_data); + } + } + if (codec && codec->defaults) { + int ret; + const AVCodecDefault *d = codec->defaults; + while (d->key) { + ret = av_opt_set(s, d->key, d->value, 0); + av_assert0(ret >= 0); + d++; + } + } + return 0; +} + +AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) +{ + AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); + + if(avctx==NULL) return NULL; + + if(avcodec_get_context_defaults3(avctx, codec) < 0){ + av_free(avctx); + return NULL; + } + + return avctx; +} + +#if FF_API_ALLOC_CONTEXT +AVCodecContext *avcodec_alloc_context2(enum AVMediaType codec_type){ + AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); + + if(avctx==NULL) return NULL; + + avcodec_get_context_defaults2(avctx, codec_type); + + return avctx; +} + +void avcodec_get_context_defaults(AVCodecContext *s){ + avcodec_get_context_defaults2(s, AVMEDIA_TYPE_UNKNOWN); +} + +AVCodecContext *avcodec_alloc_context(void){ + return avcodec_alloc_context2(AVMEDIA_TYPE_UNKNOWN); +} +#endif + +int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) +{ + if (avcodec_is_open(dest)) { // check that the dest context is uninitialized + av_log(dest, AV_LOG_ERROR, + "Tried to copy AVCodecContext %p into already-initialized %p\n", + src, dest); + return AVERROR(EINVAL); + } + memcpy(dest, src, sizeof(*dest)); + + /* set values specific to opened codecs back to their default state */ + dest->priv_data = NULL; + dest->codec = NULL; + dest->slice_offset = NULL; + dest->hwaccel = NULL; + dest->thread_opaque = NULL; + dest->internal = NULL; + + /* reallocate values that should be allocated separately */ + dest->rc_eq = NULL; + dest->extradata = NULL; + dest->intra_matrix = NULL; + dest->inter_matrix = NULL; + dest->rc_override = NULL; + if (src->rc_eq) { + dest->rc_eq = av_strdup(src->rc_eq); + if (!dest->rc_eq) + return AVERROR(ENOMEM); + } + +#define alloc_and_copy_or_fail(obj, size, pad) \ + if (src->obj && size > 0) { \ + dest->obj = av_malloc(size + pad); \ + if (!dest->obj) \ + goto fail; \ + memcpy(dest->obj, src->obj, size); \ + if (pad) \ + memset(((uint8_t *) dest->obj) + size, 0, pad); \ + } + alloc_and_copy_or_fail(extradata, src->extradata_size, + FF_INPUT_BUFFER_PADDING_SIZE); + alloc_and_copy_or_fail(intra_matrix, 64 * sizeof(int16_t), 0); + alloc_and_copy_or_fail(inter_matrix, 64 * sizeof(int16_t), 0); + alloc_and_copy_or_fail(rc_override, src->rc_override_count * sizeof(*src->rc_override), 0); +#undef alloc_and_copy_or_fail + + return 0; + +fail: + av_freep(&dest->rc_override); + av_freep(&dest->intra_matrix); + av_freep(&dest->inter_matrix); + av_freep(&dest->extradata); + av_freep(&dest->rc_eq); + return AVERROR(ENOMEM); +} + +const AVClass *avcodec_get_class(void) +{ + return &av_codec_context_class; +} + +#define FOFFSET(x) offsetof(AVFrame,x) + +static const AVOption frame_options[]={ +{"best_effort_timestamp", "", FOFFSET(best_effort_timestamp), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, 0}, +{"pkt_pos", "", FOFFSET(pkt_pos), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0}, +{"pkt_size", "", FOFFSET(pkt_size), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0}, +{"sample_aspect_ratio", "", FOFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0}, +{"width", "", FOFFSET(width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"height", "", FOFFSET(height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"format", "", FOFFSET(format), AV_OPT_TYPE_INT, {.i64 = -1 }, 0, INT_MAX, 0}, +{"channel_layout", "", FOFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, 0}, +{"sample_rate", "", FOFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{NULL}, +}; + +static const AVClass av_frame_class = { + .class_name = "AVFrame", + .item_name = NULL, + .option = frame_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVClass *avcodec_get_frame_class(void) +{ + return &av_frame_class; +} + +#define SROFFSET(x) offsetof(AVSubtitleRect,x) + +static const AVOption subtitle_rect_options[]={ +{"x", "", SROFFSET(x), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"y", "", SROFFSET(y), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"w", "", SROFFSET(w), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"h", "", SROFFSET(h), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"type", "", SROFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, +{"flags", "", SROFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, 1, 0, "flags"}, +{"forced", "", SROFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, 1, 0}, +{NULL}, +}; + +static const AVClass av_subtitle_rect_class = { + .class_name = "AVSubtitleRect", + .item_name = NULL, + .option = subtitle_rect_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVClass *avcodec_get_subtitle_rect_class(void) +{ + return &av_subtitle_rect_class; +} diff --git a/ffmpeg/libavcodec/options_table.h b/ffmpeg/libavcodec/options_table.h new file mode 100644 index 0000000..d7e2683 --- /dev/null +++ b/ffmpeg/libavcodec/options_table.h @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +#ifndef AVCODEC_OPTIONS_TABLE_H +#define AVCODEC_OPTIONS_TABLE_H + +#include +#include + +#include "libavutil/opt.h" +#include "avcodec.h" +#include "version.h" +#include "config.h" + +#define OFFSET(x) offsetof(AVCodecContext,x) +#define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C +//these names are too long to be readable +#define V AV_OPT_FLAG_VIDEO_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM +#define S AV_OPT_FLAG_SUBTITLE_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +#define D AV_OPT_FLAG_DECODING_PARAM + +#define AV_CODEC_DEFAULT_BITRATE 200*1000 + +static const AVOption options[]={ +{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE }, 0, INT_MAX, A|V|E}, +{"ab", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.i64 = 128*1000 }, 0, INT_MAX, A|E}, +{"bt", "Set video bitrate tolerance (in bits/s). In 1-pass mode, bitrate tolerance specifies how far " + "ratecontrol is willing to deviate from the target average bitrate value. This is not related " + "to minimum/maximum bitrate. Lowering tolerance too much has an adverse effect on quality.", + OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E}, +{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"}, +{"mv4", "use four motion vectors per macroblock (MPEG-4)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"}, +{"qpel", "use 1/4-pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"}, +{"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, +{"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, +{"gmc", "use gmc", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GMC }, INT_MIN, INT_MAX, V|E, "flags"}, +{"mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_MV0 }, INT_MIN, INT_MAX, V|E, "flags"}, +{"input_preserved", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INPUT_PRESERVED }, INT_MIN, INT_MAX, 0, "flags"}, +{"pass1", "use internal 2-pass ratecontrol in first pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"}, +{"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"}, +{"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, +{"emu_edge", "do not draw edges", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_EMU_EDGE }, INT_MIN, INT_MAX, 0, "flags"}, +{"psnr", "error[?] variables will be set during encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_PSNR }, INT_MIN, INT_MAX, V|E, "flags"}, +{"truncated", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_TRUNCATED }, INT_MIN, INT_MAX, 0, "flags"}, +{"naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_NORMALIZE_AQP }, INT_MIN, INT_MAX, V|E, "flags"}, +{"ildct", "use interlaced DCT", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INTERLACED_DCT }, INT_MIN, INT_MAX, V|E, "flags"}, +{"low_delay", "force low delay", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOW_DELAY }, INT_MIN, INT_MAX, V|D|E, "flags"}, +{"global_header", "place global headers in extradata instead of every keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_GLOBAL_HEADER }, INT_MIN, INT_MAX, V|A|E, "flags"}, +{"bitexact", "use only bitexact functions (except (I)DCT)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_BITEXACT }, INT_MIN, INT_MAX, A|V|S|D|E, "flags"}, +{"aic", "H.263 advanced intra coding / MPEG-4 AC prediction", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_AC_PRED }, INT_MIN, INT_MAX, V|E, "flags"}, +{"ilme", "interlaced motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_INTERLACED_ME }, INT_MIN, INT_MAX, V|E, "flags"}, +{"cgop", "closed GOP", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_CLOSED_GOP }, INT_MIN, INT_MAX, V|E, "flags"}, +{"fast", "allow non-spec-compliant speedup tricks", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_FAST }, INT_MIN, INT_MAX, V|E, "flags2"}, +{"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"}, +{"ignorecrop", "ignore cropping information from sps", 1, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_IGNORE_CROP }, INT_MIN, INT_MAX, V|D, "flags2"}, +{"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"}, +{"chunks", "Frame data might be split into multiple chunks", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_CHUNKS }, INT_MIN, INT_MAX, V|D, "flags2"}, +{"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"}, +{"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"}, +{"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"full", "full motion estimation (slowest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"epzs", "EPZS motion estimation (default)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"esa", "esa motion estimation (alias for full)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"tesa", "tesa motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_TESA }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"dia", "diamond motion estimation (alias for EPZS)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"log", "log motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_LOG }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"phods", "phods motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_PHODS }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"x1", "X1 motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_X1 }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"hex", "hex motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_HEX }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"umh", "umh motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_UMH }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"iter", "iter motion estimation", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ITER }, INT_MIN, INT_MAX, V|E, "me_method" }, +{"extradata_size", NULL, OFFSET(extradata_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, INT_MIN, INT_MAX}, +{"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E}, +{"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|D|E}, +{"ac", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|D|E}, +{"cutoff", "set cutoff bandwidth", OFFSET(cutoff), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E}, +{"frame_size", NULL, OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E}, +{"frame_number", NULL, OFFSET(frame_number), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"delay", NULL, OFFSET(delay), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"qcomp", "video quantizer scale compression (VBR). Constant of ratecontrol equation. " + "Recommended range for default rc_eq: 0.0-1.0", + OFFSET(qcompress), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -FLT_MAX, FLT_MAX, V|E}, +{"qblur", "video quantizer scale blur (VBR)", OFFSET(qblur), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -1, FLT_MAX, V|E}, +{"qmin", "minimum video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.i64 = 2 }, -1, 69, V|E}, +{"qmax", "maximum video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 1024, V|E}, +{"qdiff", "maximum difference between the quantizer scales (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.i64 = 3 }, INT_MIN, INT_MAX, V|E}, +{"bf", "use 'frames' B frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, FF_MAX_B_FRAMES, V|E}, +{"b_qfactor", "QP factor between P- and B-frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E}, +{"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"b_strategy", "strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, +{"ps", "RTP payload size in bytes", OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"mv_bits", NULL, OFFSET(mv_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"header_bits", NULL, OFFSET(header_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"i_tex_bits", NULL, OFFSET(i_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"p_tex_bits", NULL, OFFSET(p_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"i_count", NULL, OFFSET(i_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"p_count", NULL, OFFSET(p_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"skip_count", NULL, OFFSET(skip_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"misc_bits", NULL, OFFSET(misc_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"frame_bits", NULL, OFFSET(frame_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"bug", "work around not autodetected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"}, +{"autodetect", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"}, +{"old_msmpeg4", "some old lavc-generated MSMPEG4v3 files (no autodetection)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_OLD_MSMPEG4 }, INT_MIN, INT_MAX, V|D, "bug"}, +{"xvid_ilace", "Xvid interlacing bug (autodetected if FOURCC == XVIX)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_XVID_ILACE }, INT_MIN, INT_MAX, V|D, "bug"}, +{"ump4", "(autodetected if FOURCC == UMP4)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_UMP4 }, INT_MIN, INT_MAX, V|D, "bug"}, +{"no_padding", "padding bug (autodetected)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_NO_PADDING }, INT_MIN, INT_MAX, V|D, "bug"}, +{"amv", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AMV }, INT_MIN, INT_MAX, V|D, "bug"}, +{"ac_vlc", "illegal VLC bug (autodetected per FOURCC)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AC_VLC }, INT_MIN, INT_MAX, V|D, "bug"}, +{"qpel_chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_QPEL_CHROMA }, INT_MIN, INT_MAX, V|D, "bug"}, +{"std_qpel", "old standard qpel (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_STD_QPEL }, INT_MIN, INT_MAX, V|D, "bug"}, +{"qpel_chroma2", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_QPEL_CHROMA2 }, INT_MIN, INT_MAX, V|D, "bug"}, +{"direct_blocksize", "direct-qpel-blocksize bug (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_DIRECT_BLOCKSIZE }, INT_MIN, INT_MAX, V|D, "bug"}, +{"edge", "edge padding bug (autodetected per FOURCC/version)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_EDGE }, INT_MIN, INT_MAX, V|D, "bug"}, +{"hpel_chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_HPEL_CHROMA }, INT_MIN, INT_MAX, V|D, "bug"}, +{"dc_clip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_DC_CLIP }, INT_MIN, INT_MAX, V|D, "bug"}, +{"ms", "work around various bugs in Microsoft's broken decoders", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_MS }, INT_MIN, INT_MAX, V|D, "bug"}, +{"trunc", "truncated frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_TRUNCATED}, INT_MIN, INT_MAX, V|D, "bug"}, +{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|D|E, "strict"}, +{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, V|D|E, "strict"}, +{"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, V|D|E, "strict"}, +{"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL }, INT_MIN, INT_MAX, V|D|E, "strict"}, +{"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, V|D|E, "strict"}, +{"experimental", "allow non-standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, V|D|E, "strict"}, +{"b_qoffset", "QP offset between P- and B-frames", OFFSET(b_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E}, +{"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"careful", "consider things that violate the spec and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, A|V|D, "err_detect"}, +{"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, 0, 99, V|E}, +{"rc_qmod_amp", "experimental quantizer modulation", OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +{"rc_qmod_freq", "experimental quantizer modulation", OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"rc_override_count", NULL, OFFSET(rc_override_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " + "defined in the section 'Expression Evaluation', the following functions are available: " + "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " + "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", + OFFSET(rc_eq), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, V|E}, +{"maxrate", "Set maximum bitrate tolerance (in bits/s). Requires bufsize to be set.", OFFSET(rc_max_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +{"minrate", "Set minimum bitrate tolerance (in bits/s). Most useful in setting up a CBR encode. It is of little use otherwise.", + OFFSET(rc_min_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +{"bufsize", "set ratecontrol buffer size (in bits)", OFFSET(rc_buffer_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|E}, +{"rc_buf_aggressivity", "currently useless", OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, V|E}, +{"i_qfactor", "QP factor between P- and I-frames", OFFSET(i_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = -0.8 }, -FLT_MAX, FLT_MAX, V|E}, +{"i_qoffset", "QP offset between P- and I-frames", OFFSET(i_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, -FLT_MAX, FLT_MAX, V|E}, +{"rc_init_cplx", "initial complexity for 1-pass encoding", OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +{"dct", "DCT algorithm", OFFSET(dct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E, "dct"}, +{"auto", "autoselect a good one (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_AUTO }, INT_MIN, INT_MAX, V|E, "dct"}, +{"fastint", "fast integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FASTINT }, INT_MIN, INT_MAX, V|E, "dct"}, +{"int", "accurate integer", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_INT }, INT_MIN, INT_MAX, V|E, "dct"}, +{"mmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_MMX }, INT_MIN, INT_MAX, V|E, "dct"}, +{"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_ALTIVEC }, INT_MIN, INT_MAX, V|E, "dct"}, +{"faan", "floating point AAN DCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DCT_FAAN }, INT_MIN, INT_MAX, V|E, "dct"}, +{"lumi_mask", "compresses bright areas stronger than medium ones", OFFSET(lumi_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E}, +{"tcplx_mask", "temporal complexity masking", OFFSET(temporal_cplx_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E}, +{"scplx_mask", "spatial complexity masking", OFFSET(spatial_cplx_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E}, +{"p_mask", "inter masking", OFFSET(p_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E}, +{"dark_mask", "compresses dark areas stronger than medium ones", OFFSET(dark_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, V|E}, +{"idct", "select IDCT implementation", OFFSET(idct_algo), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|E|D, "idct"}, +{"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_AUTO }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"int", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_INT }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLE }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simplemmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"arm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"altivec", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"sh4", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SH4 }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simplearm", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARM }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simplearmv5te", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simplearmv6", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simpleneon", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLENEON }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"simplealpha", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEALPHA }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"ipp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"xvidmmx", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVIDMMX }, INT_MIN, INT_MAX, V|E|D, "idct"}, +{"faani", "floating point AAN IDCT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"}, +{"slice_count", NULL, OFFSET(slice_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"ec", "set error concealment strategy", OFFSET(error_concealment), AV_OPT_TYPE_FLAGS, {.i64 = 3 }, INT_MIN, INT_MAX, V|D, "ec"}, +{"guess_mvs", "iterative motion vector (MV) search (slow)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_GUESS_MVS }, INT_MIN, INT_MAX, V|D, "ec"}, +{"deblock", "use strong deblock filter for damaged MBs", 0, AV_OPT_TYPE_CONST, {.i64 = FF_EC_DEBLOCK }, INT_MIN, INT_MAX, V|D, "ec"}, +{"bits_per_coded_sample", NULL, OFFSET(bits_per_coded_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"pred", "prediction method", OFFSET(prediction_method), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "pred"}, +{"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_LEFT }, INT_MIN, INT_MAX, V|E, "pred"}, +{"plane", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_PLANE }, INT_MIN, INT_MAX, V|E, "pred"}, +{"median", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_MEDIAN }, INT_MIN, INT_MAX, V|E, "pred"}, +{"aspect", "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E}, +{"debug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|A|S|E|D, "debug"}, +{"pict", "picture info", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PICT_INFO }, INT_MIN, INT_MAX, V|D, "debug"}, +{"rc", "rate control", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_RC }, INT_MIN, INT_MAX, V|E, "debug"}, +{"bitstream", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BITSTREAM }, INT_MIN, INT_MAX, V|D, "debug"}, +{"mb_type", "macroblock (MB) type", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, +{"qp", "per-block quantization parameter (QP)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_QP }, INT_MIN, INT_MAX, V|D, "debug"}, +{"mv", "motion vector", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MV }, INT_MIN, INT_MAX, V|D, "debug"}, +{"dct_coeff", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_DCT_COEFF }, INT_MIN, INT_MAX, V|D, "debug"}, +{"skip", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_SKIP }, INT_MIN, INT_MAX, V|D, "debug"}, +{"startcode", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_STARTCODE }, INT_MIN, INT_MAX, V|D, "debug"}, +{"pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PTS }, INT_MIN, INT_MAX, V|D, "debug"}, +{"er", "error recognition", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_ER }, INT_MIN, INT_MAX, V|D, "debug"}, +{"mmco", "memory management control operations (H.264)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_MMCO }, INT_MIN, INT_MAX, V|D, "debug"}, +{"bugs", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUGS }, INT_MIN, INT_MAX, V|D, "debug"}, +{"vis_qp", "visualize quantization parameter (QP), lower QP are tinted greener", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_QP }, INT_MIN, INT_MAX, V|D, "debug"}, +{"vis_mb_type", "visualize block types", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MB_TYPE }, INT_MIN, INT_MAX, V|D, "debug"}, +{"buffers", "picture buffer allocations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_BUFFERS }, INT_MIN, INT_MAX, V|D, "debug"}, +{"thread_ops", "threading operations", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_THREADS }, INT_MIN, INT_MAX, V|D, "debug"}, +{"vismv", "visualize motion vectors (MVs)", OFFSET(debug_mv), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, V|D, "debug_mv"}, +{"pf", "forward predicted MVs of P-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_P_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, +{"bf", "forward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_FOR }, INT_MIN, INT_MAX, V|D, "debug_mv"}, +{"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_VIS_MV_B_BACK }, INT_MIN, INT_MAX, V|D, "debug_mv"}, +{"cmp", "full-pel ME compare function", OFFSET(me_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"subcmp", "sub-pel ME compare function", OFFSET(me_sub_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"mbcmp", "macroblock compare function", OFFSET(mb_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"ildctcmp", "interlaced DCT compare function", OFFSET(ildct_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"dia_size", "diamond type & size for motion estimation", OFFSET(dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"last_pred", "amount of motion predictors from the previous frame", OFFSET(last_predictor_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"preme", "pre motion estimation", OFFSET(pre_me), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"precmp", "pre motion estimation compare function", OFFSET(me_pre_cmp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"sad", "sum of absolute differences, fast (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SAD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"sse", "sum of squared errors", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SSE }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"satd", "sum of absolute Hadamard transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SATD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"dct", "sum of absolute DCT transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"psnr", "sum of squared quantization errors (avoid, low quality)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_PSNR }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"bit", "number of bits needed for the block", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_BIT }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"rd", "rate distortion optimal, slow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_RD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"zero", "0", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_ZERO }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"vsad", "sum of absolute vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"vsse", "sum of squared vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSSE }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"nsse", "noise preserving sum of squared differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_NSSE }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +#if CONFIG_SNOW_ENCODER +{"w53", "5/3 wavelet, only used in snow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_W53 }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"w97", "9/7 wavelet, only used in snow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_W97 }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +#endif +{"dctmax", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"pre_dia_size", "diamond type & size for motion estimation pre-pass", OFFSET(pre_dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"subq", "sub-pel motion estimation quality", OFFSET(me_subpel_quality), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, +{"dtg_active_format", NULL, OFFSET(dtg_active_format), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"me_range", "limit motion vectors range (1023 for DivX player)", OFFSET(me_range), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, +{"pbias", "inter quant bias", OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E}, +{"global_quality", NULL, OFFSET(global_quality), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +{"coder", NULL, OFFSET(coder_type), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E, "coder"}, +{"vlc", "variable length coder / Huffman coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_VLC }, INT_MIN, INT_MAX, V|E, "coder"}, +{"ac", "arithmetic coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_AC }, INT_MIN, INT_MAX, V|E, "coder"}, +{"raw", "raw (no encoding)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_RAW }, INT_MIN, INT_MAX, V|E, "coder"}, +{"rle", "run-length coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_RLE }, INT_MIN, INT_MAX, V|E, "coder"}, +{"deflate", "deflate-based coder", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CODER_TYPE_DEFLATE }, INT_MIN, INT_MAX, V|E, "coder"}, +{"context", "context model", OFFSET(context_model), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"slice_flags", NULL, OFFSET(slice_flags), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"xvmc_acceleration", NULL, OFFSET(xvmc_acceleration), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"mbd", "macroblock decision algorithm (high quality mode)", OFFSET(mb_decision), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 2, V|E, "mbd"}, +{"simple", "use mbcmp (default)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_SIMPLE }, INT_MIN, INT_MAX, V|E, "mbd"}, +{"bits", "use fewest bits", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_BITS }, INT_MIN, INT_MAX, V|E, "mbd"}, +{"rd", "use best rate distortion", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MB_DECISION_RD }, INT_MIN, INT_MAX, V|E, "mbd"}, +{"stream_codec_tag", NULL, OFFSET(stream_codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"sc_threshold", "scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"lmin", "minimum Lagrange factor (VBR)", OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, V|E}, +{"lmax", "maximum Lagrange factor (VBR)", OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, V|E}, +{"nr", "noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"rc_init_occupancy", "number of bits which should be loaded into the rc buffer before decoding starts", OFFSET(rc_initial_buffer_occupancy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"flags2", NULL, OFFSET(flags2), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT}, 0, UINT_MAX, V|A|E|D, "flags2"}, +{"error", NULL, OFFSET(error_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"threads", NULL, OFFSET(thread_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, V|E|D, "threads"}, +{"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, V|E|D, "threads"}, +{"me_threshold", "motion estimation threshold", OFFSET(me_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"mb_threshold", "macroblock threshold", OFFSET(mb_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"dc", "intra_dc_precision", OFFSET(intra_dc_precision), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E}, +{"nssew", "nsse weight", OFFSET(nsse_weight), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E}, +{"skip_top", "number of macroblock rows at the top which are skipped", OFFSET(skip_top), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, +{"skip_bottom", "number of macroblock rows at the bottom which are skipped", OFFSET(skip_bottom), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|D}, +{"profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "profile"}, +{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "profile"}, +{"aac_main", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_MAIN }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_low", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LOW }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_ssr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_SSR }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_ltp", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LTP }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_he", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_HE }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_he_v2", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_HE_V2 }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_ld", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_LD }, INT_MIN, INT_MAX, A|E, "profile"}, +{"aac_eld", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_AAC_ELD }, INT_MIN, INT_MAX, A|E, "profile"}, +{"dts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS }, INT_MIN, INT_MAX, A|E, "profile"}, +{"dts_es", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_ES }, INT_MIN, INT_MAX, A|E, "profile"}, +{"dts_96_24", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_96_24 }, INT_MIN, INT_MAX, A|E, "profile"}, +{"dts_hd_hra", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_HRA }, INT_MIN, INT_MAX, A|E, "profile"}, +{"dts_hd_ma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_MA }, INT_MIN, INT_MAX, A|E, "profile"}, +{"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, +{"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"}, +{"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|A|D}, +{"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"}, +{"border_mask", "increase the quantizer for macroblocks close to borders", OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E}, +{"mblmin", "minimum macroblock Lagrange factor (VBR)", OFFSET(mb_lmin), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 2 }, 1, FF_LAMBDA_MAX, V|E}, +{"mblmax", "maximum macroblock Lagrange factor (VBR)", OFFSET(mb_lmax), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 31 }, 1, FF_LAMBDA_MAX, V|E}, +{"mepc", "motion estimation bitrate penalty compensation (1.0 = 256)", OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, V|E}, +{"skip_loop_filter", "skip loop filtering process for the selected frames", OFFSET(skip_loop_filter), AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"skip_idct" , "skip IDCT/dequantization for the selected frames", OFFSET(skip_idct), AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"skip_frame" , "skip decoding for the selected frames", OFFSET(skip_frame), AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"none" , "discard no frame", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONE }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"default" , "discard useless frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"noref" , "discard all non-reference frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONREF }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"bidir" , "discard all bidirectional frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_BIDIR }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"nokey" , "discard all frames except keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"all" , "discard all frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL }, INT_MIN, INT_MAX, V|D, "avdiscard"}, +{"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E}, +{"brd_scale", "downscale frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 10, V|E}, +{"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.i64 = 25 }, INT_MIN, INT_MAX, V|E}, +{"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.i64 = 1 }, INT_MIN, INT_MAX, V|E}, +{"chromaoffset", "chroma QP offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E}, +{"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +{"sc_factor", "multiplied by qscale for each frame and added to scene_change_score", OFFSET(scenechange_factor), AV_OPT_TYPE_INT, {.i64 = 6 }, 0, INT_MAX, V|E}, +{"mv0_threshold", NULL, OFFSET(mv0_threshold), AV_OPT_TYPE_INT, {.i64 = 256 }, 0, INT_MAX, V|E}, +{"b_sensitivity", "adjust sensitivity of b_frame_strategy 1", OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, V|E}, +{"compression_level", NULL, OFFSET(compression_level), AV_OPT_TYPE_INT, {.i64 = FF_COMPRESSION_DEFAULT }, INT_MIN, INT_MAX, V|A|E}, +{"min_prediction_order", NULL, OFFSET(min_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E}, +{"max_prediction_order", NULL, OFFSET(max_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E}, +{"timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, V|E}, +#if FF_API_REQUEST_CHANNELS +{"request_channels", "set desired number of audio channels", OFFSET(request_channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D}, +#endif +{"bits_per_raw_sample", NULL, OFFSET(bits_per_raw_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, +{"channel_layout", NULL, OFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT64_MAX, A|E|D, "channel_layout"}, +{"request_channel_layout", NULL, OFFSET(request_channel_layout), AV_OPT_TYPE_INT64, {.i64 = DEFAULT }, 0, INT64_MAX, A|D, "request_channel_layout"}, +{"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0.0, FLT_MAX, V|E}, +{"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use), AV_OPT_TYPE_FLOAT, {.dbl = 3 }, 0.0, FLT_MAX, V|E}, +{"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, INT_MAX, A|V|E|D}, +{"color_primaries", NULL, OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64 = AVCOL_PRI_UNSPECIFIED }, 1, AVCOL_PRI_NB-1, V|E|D}, +{"color_trc", NULL, OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64 = AVCOL_TRC_UNSPECIFIED }, 1, AVCOL_TRC_NB-1, V|E|D}, +{"colorspace", NULL, OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 1, AVCOL_SPC_NB-1, V|E|D}, +{"color_range", NULL, OFFSET(color_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, AVCOL_RANGE_NB-1, V|E|D}, +{"chroma_sample_location", NULL, OFFSET(chroma_sample_location), AV_OPT_TYPE_INT, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, 0, AVCHROMA_LOC_NB-1, V|E|D}, +{"log_level_offset", "set the log level offset", OFFSET(log_level_offset), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX }, +{"slices", "number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E}, +{"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.i64 = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|E|D, "thread_type"}, +{"slice", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_THREAD_SLICE }, INT_MIN, INT_MAX, V|E|D, "thread_type"}, +{"frame", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_THREAD_FRAME }, INT_MIN, INT_MAX, V|E|D, "thread_type"}, +{"audio_service_type", "audio service type", OFFSET(audio_service_type), AV_OPT_TYPE_INT, {.i64 = AV_AUDIO_SERVICE_TYPE_MAIN }, 0, AV_AUDIO_SERVICE_TYPE_NB-1, A|E, "audio_service_type"}, +{"ma", "Main Audio Service", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_MAIN }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"ef", "Effects", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EFFECTS }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"vi", "Visually Impaired", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"hi", "Hearing Impaired", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"di", "Dialogue", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_DIALOGUE }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"co", "Commentary", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_COMMENTARY }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"em", "Emergency", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EMERGENCY }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"vo", "Voice Over", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VOICE_OVER }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"ka", "Karaoke", 0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_KARAOKE }, INT_MIN, INT_MAX, A|E, "audio_service_type"}, +{"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64=AV_SAMPLE_FMT_NONE}, -1, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"}, +{"pkt_timebase", NULL, OFFSET(pkt_timebase), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0}, +{"sub_charenc", "set input text subtitles character encoding", OFFSET(sub_charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, S|D}, +{"sub_charenc_mode", "set input text subtitles character encoding mode", OFFSET(sub_charenc_mode), AV_OPT_TYPE_FLAGS, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, -1, INT_MAX, S|D, "sub_charenc_mode"}, +{"do_nothing", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_DO_NOTHING}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, +{"auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, +{"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"}, +{"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, A|V|D }, +{NULL}, +}; + +#undef A +#undef V +#undef S +#undef E +#undef D +#undef DEFAULT +#undef OFFSET + +#endif /* AVCODEC_OPTIONS_TABLE_H */ diff --git a/ffmpeg/libavcodec/os2threads.h b/ffmpeg/libavcodec/os2threads.h new file mode 100644 index 0000000..b816bff --- /dev/null +++ b/ffmpeg/libavcodec/os2threads.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2011 KO Myung-Hun + * + * 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 + */ + +/** + * @file + * os2threads to pthreads wrapper + */ + +#ifndef AVCODEC_OS2PTHREADS_H +#define AVCODEC_OS2PTHREADS_H + +#define INCL_DOS +#include + +#undef __STRICT_ANSI__ /* for _beginthread() */ +#include + +typedef TID pthread_t; +typedef void pthread_attr_t; + +typedef HMTX pthread_mutex_t; +typedef void pthread_mutexattr_t; + +typedef struct { + HEV event_sem; + int wait_count; +} pthread_cond_t; + +typedef void pthread_condattr_t; + +struct thread_arg { + void *(*start_routine)(void *); + void *arg; +}; + +static void thread_entry(void *arg) +{ + struct thread_arg *thread_arg = arg; + + thread_arg->start_routine(thread_arg->arg); + + av_free(thread_arg); +} + +static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) +{ + struct thread_arg *thread_arg; + + thread_arg = av_mallocz(sizeof(struct thread_arg)); + + thread_arg->start_routine = start_routine; + thread_arg->arg = arg; + + *thread = _beginthread(thread_entry, NULL, 256 * 1024, thread_arg); + + return 0; +} + +static av_always_inline int pthread_join(pthread_t thread, void **value_ptr) +{ + DosWaitThread((PTID)&thread, DCWW_WAIT); + + return 0; +} + +static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + DosCreateMutexSem(NULL, (PHMTX)mutex, 0, FALSE); + + return 0; +} + +static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex) +{ + DosCloseMutexSem(*(PHMTX)mutex); + + return 0; +} + +static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex) +{ + DosRequestMutexSem(*(PHMTX)mutex, SEM_INDEFINITE_WAIT); + + return 0; +} + +static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex) +{ + DosReleaseMutexSem(*(PHMTX)mutex); + + return 0; +} + +static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + DosCreateEventSem(NULL, &cond->event_sem, DCE_POSTONE, FALSE); + + cond->wait_count = 0; + + return 0; +} + +static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond) +{ + DosCloseEventSem(cond->event_sem); + + return 0; +} + +static av_always_inline int pthread_cond_signal(pthread_cond_t *cond) +{ + if (cond->wait_count > 0) { + DosPostEventSem(cond->event_sem); + + cond->wait_count--; + } + + return 0; +} + +static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond) +{ + while (cond->wait_count > 0) { + DosPostEventSem(cond->event_sem); + + cond->wait_count--; + } + + return 0; +} + +static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + cond->wait_count++; + + pthread_mutex_unlock(mutex); + + DosWaitEventSem(cond->event_sem, SEM_INDEFINITE_WAIT); + + pthread_mutex_lock(mutex); + + return 0; +} + +#endif /* AVCODEC_OS2PTHREADS_H */ diff --git a/ffmpeg/libavcodec/paf.c b/ffmpeg/libavcodec/paf.c new file mode 100644 index 0000000..7892314 --- /dev/null +++ b/ffmpeg/libavcodec/paf.c @@ -0,0 +1,446 @@ +/* + * Packed Animation File video and audio decoder + * Copyright (c) 2012 Paul B Mahol + * + * 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 "libavutil/intreadwrite.h" +#include "libavcodec/paf.h" +#include "bytestream.h" +#include "avcodec.h" +#include "copy_block.h" +#include "internal.h" + + +static const uint8_t block_sequences[16][8] = +{ + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 2, 0, 0, 0, 0, 0, 0, 0 }, + { 5, 7, 0, 0, 0, 0, 0, 0 }, + { 5, 0, 0, 0, 0, 0, 0, 0 }, + { 6, 0, 0, 0, 0, 0, 0, 0 }, + { 5, 7, 5, 7, 0, 0, 0, 0 }, + { 5, 7, 5, 0, 0, 0, 0, 0 }, + { 5, 7, 6, 0, 0, 0, 0, 0 }, + { 5, 5, 0, 0, 0, 0, 0, 0 }, + { 3, 0, 0, 0, 0, 0, 0, 0 }, + { 6, 6, 0, 0, 0, 0, 0, 0 }, + { 2, 4, 0, 0, 0, 0, 0, 0 }, + { 2, 4, 5, 7, 0, 0, 0, 0 }, + { 2, 4, 5, 0, 0, 0, 0, 0 }, + { 2, 4, 6, 0, 0, 0, 0, 0 }, + { 2, 4, 5, 7, 5, 7, 0, 0 } +}; + +typedef struct PAFVideoDecContext { + AVFrame pic; + GetByteContext gb; + + int current_frame; + uint8_t *frame[4]; + int frame_size; + int video_size; + + uint8_t *opcodes; +} PAFVideoDecContext; + +static av_cold int paf_vid_init(AVCodecContext *avctx) +{ + PAFVideoDecContext *c = avctx->priv_data; + int i; + + if (avctx->height & 3 || avctx->width & 3) { + av_log(avctx, AV_LOG_ERROR, "width and height must be multiplies of 4\n"); + return AVERROR_INVALIDDATA; + } + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + avcodec_get_frame_defaults(&c->pic); + c->frame_size = FFALIGN(avctx->height, 256) * avctx->width; + c->video_size = avctx->height * avctx->width; + for (i = 0; i < 4; i++) { + c->frame[i] = av_mallocz(c->frame_size); + if (!c->frame[i]) + return AVERROR(ENOMEM); + } + + return 0; +} + +static int get_video_page_offset(AVCodecContext *avctx, uint8_t a, uint8_t b) +{ + int x, y; + + x = b & 0x7F; + y = ((a & 0x3F) << 1) | (b >> 7 & 1); + + return y * 2 * avctx->width + x * 2; +} + +static void copy4h(AVCodecContext *avctx, uint8_t *dst) +{ + PAFVideoDecContext *c = avctx->priv_data; + int i; + + for (i = 0; i < 4; i++) { + bytestream2_get_buffer(&c->gb, dst, 4); + dst += avctx->width; + } +} + +static void copy_color_mask(AVCodecContext *avctx, uint8_t mask, uint8_t *dst, uint8_t color) +{ + int i; + + for (i = 0; i < 4; i++) { + if ((mask >> 4) & (1 << (3 - i))) + dst[i] = color; + if ((mask & 15) & (1 << (3 - i))) + dst[avctx->width + i] = color; + } +} + +static void copy_src_mask(AVCodecContext *avctx, uint8_t mask, uint8_t *dst, const uint8_t *src) +{ + int i; + + for (i = 0; i < 4; i++) { + if ((mask >> 4) & (1 << (3 - i))) + dst[i] = src[i]; + if ((mask & 15) & (1 << (3 - i))) + dst[avctx->width + i] = src[avctx->width + i]; + } +} + +static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt) +{ + PAFVideoDecContext *c = avctx->priv_data; + uint32_t opcode_size, offset; + uint8_t *dst, *dend, mask = 0, color = 0, a, b, p; + const uint8_t *src, *send, *opcodes; + int i, j, x = 0; + + i = bytestream2_get_byte(&c->gb); + if (i) { + if (code & 0x10) { + int align; + + align = bytestream2_tell(&c->gb) & 3; + if (align) + bytestream2_skip(&c->gb, 4 - align); + } + do { + a = bytestream2_get_byte(&c->gb); + b = bytestream2_get_byte(&c->gb); + p = (a & 0xC0) >> 6; + dst = c->frame[p] + get_video_page_offset(avctx, a, b); + dend = c->frame[p] + c->frame_size; + offset = (b & 0x7F) * 2; + j = bytestream2_get_le16(&c->gb) + offset; + + do { + offset++; + if (dst + 3 * avctx->width + 4 > dend) + return AVERROR_INVALIDDATA; + copy4h(avctx, dst); + if ((offset & 0x3F) == 0) + dst += avctx->width * 3; + dst += 4; + } while (offset < j); + } while (--i); + } + + dst = c->frame[c->current_frame]; + dend = c->frame[c->current_frame] + c->frame_size; + do { + a = bytestream2_get_byte(&c->gb); + b = bytestream2_get_byte(&c->gb); + p = (a & 0xC0) >> 6; + src = c->frame[p] + get_video_page_offset(avctx, a, b); + send = c->frame[p] + c->frame_size; + if ((src + 3 * avctx->width + 4 > send) || + (dst + 3 * avctx->width + 4 > dend)) + return AVERROR_INVALIDDATA; + copy_block4(dst, src, avctx->width, avctx->width, 4); + i++; + if ((i & 0x3F) == 0) + dst += avctx->width * 3; + dst += 4; + } while (i < c->video_size / 16); + + opcode_size = bytestream2_get_le16(&c->gb); + bytestream2_skip(&c->gb, 2); + + if (bytestream2_get_bytes_left(&c->gb) < opcode_size) + return AVERROR_INVALIDDATA; + + opcodes = pkt + bytestream2_tell(&c->gb); + bytestream2_skipu(&c->gb, opcode_size); + + dst = c->frame[c->current_frame]; + + for (i = 0; i < avctx->height; i += 4, dst += avctx->width * 3) { + for (j = 0; j < avctx->width; j += 4, dst += 4) { + int opcode, k = 0; + + if (x > opcode_size) + return AVERROR_INVALIDDATA; + if (j & 4) { + opcode = opcodes[x] & 15; + x++; + } else { + opcode = opcodes[x] >> 4; + } + + while (block_sequences[opcode][k]) { + + offset = avctx->width * 2; + code = block_sequences[opcode][k++]; + + switch (code) { + case 2: + offset = 0; + case 3: + color = bytestream2_get_byte(&c->gb); + case 4: + mask = bytestream2_get_byte(&c->gb); + copy_color_mask(avctx, mask, dst + offset, color); + break; + case 5: + offset = 0; + case 6: + a = bytestream2_get_byte(&c->gb); + b = bytestream2_get_byte(&c->gb); + p = (a & 0xC0) >> 6; + src = c->frame[p] + get_video_page_offset(avctx, a, b); + send = c->frame[p] + c->frame_size; + case 7: + if (src + offset + avctx->width + 4 > send) + return AVERROR_INVALIDDATA; + mask = bytestream2_get_byte(&c->gb); + copy_src_mask(avctx, mask, dst + offset, src + offset); + break; + } + } + } + } + + return 0; +} + +static int paf_vid_decode(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *pkt) +{ + PAFVideoDecContext *c = avctx->priv_data; + uint8_t code, *dst, *src, *end; + int i, frame, ret; + + if ((ret =ff_reget_buffer(avctx, &c->pic)) < 0) + return ret; + + bytestream2_init(&c->gb, pkt->data, pkt->size); + + code = bytestream2_get_byte(&c->gb); + if (code & 0x20) { + for (i = 0; i < 4; i++) + memset(c->frame[i], 0, c->frame_size); + + memset(c->pic.data[1], 0, AVPALETTE_SIZE); + c->current_frame = 0; + c->pic.key_frame = 1; + c->pic.pict_type = AV_PICTURE_TYPE_I; + } else { + c->pic.key_frame = 0; + c->pic.pict_type = AV_PICTURE_TYPE_P; + } + + if (code & 0x40) { + uint32_t *out = (uint32_t *)c->pic.data[1]; + int index, count; + + index = bytestream2_get_byte(&c->gb); + count = bytestream2_get_byte(&c->gb) + 1; + + if (index + count > 256) + return AVERROR_INVALIDDATA; + if (bytestream2_get_bytes_left(&c->gb) < 3*count) + return AVERROR_INVALIDDATA; + + out += index; + for (i = 0; i < count; i++) { + unsigned r, g, b; + + r = bytestream2_get_byteu(&c->gb); + r = r << 2 | r >> 4; + g = bytestream2_get_byteu(&c->gb); + g = g << 2 | g >> 4; + b = bytestream2_get_byteu(&c->gb); + b = b << 2 | b >> 4; + *out++ = 0xFFU << 24 | r << 16 | g << 8 | b; + } + c->pic.palette_has_changed = 1; + } + + switch (code & 0x0F) { + case 0: + if ((ret = decode_0(avctx, code, pkt->data)) < 0) + return ret; + break; + case 1: + dst = c->frame[c->current_frame]; + bytestream2_skip(&c->gb, 2); + if (bytestream2_get_bytes_left(&c->gb) < c->video_size) + return AVERROR_INVALIDDATA; + bytestream2_get_bufferu(&c->gb, dst, c->video_size); + break; + case 2: + frame = bytestream2_get_byte(&c->gb); + if (frame > 3) + return AVERROR_INVALIDDATA; + if (frame != c->current_frame) + memcpy(c->frame[c->current_frame], c->frame[frame], c->frame_size); + break; + case 4: + dst = c->frame[c->current_frame]; + end = dst + c->video_size; + + bytestream2_skip(&c->gb, 2); + + while (dst < end) { + int8_t code; + int count; + + if (bytestream2_get_bytes_left(&c->gb) < 2) + return AVERROR_INVALIDDATA; + + code = bytestream2_get_byteu(&c->gb); + count = FFABS(code) + 1; + + if (dst + count > end) + return AVERROR_INVALIDDATA; + if (code < 0) + memset(dst, bytestream2_get_byteu(&c->gb), count); + else + bytestream2_get_buffer(&c->gb, dst, count); + dst += count; + } + break; + default: + avpriv_request_sample(avctx, "unknown/invalid code"); + return AVERROR_INVALIDDATA; + } + + dst = c->pic.data[0]; + src = c->frame[c->current_frame]; + for (i = 0; i < avctx->height; i++) { + memcpy(dst, src, avctx->width); + dst += c->pic.linesize[0]; + src += avctx->width; + } + + c->current_frame = (c->current_frame + 1) & 3; + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + *got_frame = 1; + + return pkt->size; +} + +static av_cold int paf_vid_close(AVCodecContext *avctx) +{ + PAFVideoDecContext *c = avctx->priv_data; + int i; + + av_frame_unref(&c->pic); + + for (i = 0; i < 4; i++) + av_freep(&c->frame[i]); + + return 0; +} + +static av_cold int paf_aud_init(AVCodecContext *avctx) +{ + if (avctx->channels != 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } + + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int paf_aud_decode(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + AVFrame *frame = data; + uint8_t *buf = pkt->data; + int16_t *output_samples; + const uint8_t *t; + int frames, ret, i, j, k; + + frames = pkt->size / PAF_SOUND_FRAME_SIZE; + if (frames < 1) + return AVERROR_INVALIDDATA; + + frame->nb_samples = PAF_SOUND_SAMPLES * frames; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + output_samples = (int16_t *)frame->data[0]; + for (i = 0; i < frames; i++) { + t = buf + 256 * sizeof(uint16_t); + for (j = 0; j < PAF_SOUND_SAMPLES; j++) { + for (k = 0; k < 2; k++) { + *output_samples++ = AV_RL16(buf + *t * 2); + t++; + } + } + buf += PAF_SOUND_FRAME_SIZE; + } + + *got_frame_ptr = 1; + + return pkt->size; +} + +AVCodec ff_paf_video_decoder = { + .name = "paf_video", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PAF_VIDEO, + .priv_data_size = sizeof(PAFVideoDecContext), + .init = paf_vid_init, + .close = paf_vid_close, + .decode = paf_vid_decode, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), +}; + +AVCodec ff_paf_audio_decoder = { + .name = "paf_audio", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_PAF_AUDIO, + .init = paf_aud_init, + .decode = paf_aud_decode, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), +}; diff --git a/ffmpeg/libavcodec/paf.h b/ffmpeg/libavcodec/paf.h new file mode 100644 index 0000000..ce8245f --- /dev/null +++ b/ffmpeg/libavcodec/paf.h @@ -0,0 +1,28 @@ +/* + * Packed Animation File decoder/demuxer common code + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +#ifndef AVCODEC_PAF_H +#define AVCODEC_PAF_H + +#define PAF_SOUND_SAMPLES 2205 +#define PAF_SOUND_FRAME_SIZE ((256 + PAF_SOUND_SAMPLES) * 2) + +#endif /* AVCODEC_PAF_H */ diff --git a/ffmpeg/libavcodec/pamenc.c b/ffmpeg/libavcodec/pamenc.c new file mode 100644 index 0000000..3e47278 --- /dev/null +++ b/ffmpeg/libavcodec/pamenc.c @@ -0,0 +1,143 @@ +/* + * PAM image format + * Copyright (c) 2002, 2003 Fabrice Bellard + * + * 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 "avcodec.h" +#include "internal.h" +#include "pnm.h" + + +static int pam_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + PNMContext *s = avctx->priv_data; + AVFrame * const p = &s->picture; + int i, h, w, n, linesize, depth, maxval, ret; + const char *tuple_type; + uint8_t *ptr; + + h = avctx->height; + w = avctx->width; + switch (avctx->pix_fmt) { + case AV_PIX_FMT_MONOBLACK: + n = w; + depth = 1; + maxval = 1; + tuple_type = "BLACKANDWHITE"; + break; + case AV_PIX_FMT_GRAY8: + n = w; + depth = 1; + maxval = 255; + tuple_type = "GRAYSCALE"; + break; + case AV_PIX_FMT_GRAY16BE: + n = w * 2; + depth = 1; + maxval = 0xFFFF; + tuple_type = "GRAYSCALE"; + break; + case AV_PIX_FMT_GRAY8A: + n = w * 2; + depth = 2; + maxval = 255; + tuple_type = "GRAYSCALE_ALPHA"; + break; + case AV_PIX_FMT_RGB24: + n = w * 3; + depth = 3; + maxval = 255; + tuple_type = "RGB"; + break; + case AV_PIX_FMT_RGBA: + n = w * 4; + depth = 4; + maxval = 255; + tuple_type = "RGB_ALPHA"; + break; + case AV_PIX_FMT_RGB48BE: + n = w * 6; + depth = 3; + maxval = 0xFFFF; + tuple_type = "RGB"; + break; + case AV_PIX_FMT_RGBA64BE: + n = w * 8; + depth = 4; + maxval = 0xFFFF; + tuple_type = "RGB_ALPHA"; + break; + default: + return -1; + } + + if ((ret = ff_alloc_packet2(avctx, pkt, n*h + 200)) < 0) + return ret; + + *p = *pict; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + s->bytestream_start = + s->bytestream = pkt->data; + s->bytestream_end = pkt->data + pkt->size; + + snprintf(s->bytestream, s->bytestream_end - s->bytestream, + "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", + w, h, depth, maxval, tuple_type); + s->bytestream += strlen(s->bytestream); + + ptr = p->data[0]; + linesize = p->linesize[0]; + + if (avctx->pix_fmt == AV_PIX_FMT_MONOBLACK){ + int j; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) + *s->bytestream++ = ptr[j >> 3] >> (7 - j & 7) & 1; + ptr += linesize; + } + } else { + for (i = 0; i < h; i++) { + memcpy(s->bytestream, ptr, n); + s->bytestream += n; + ptr += linesize; + } + } + + pkt->size = s->bytestream - s->bytestream_start; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + + +AVCodec ff_pam_encoder = { + .name = "pam", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PAM, + .priv_data_size = sizeof(PNMContext), + .init = ff_pnm_init, + .encode2 = pam_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), +}; diff --git a/ffmpeg/libavcodec/parser.c b/ffmpeg/libavcodec/parser.c new file mode 100644 index 0000000..f7cb5cf --- /dev/null +++ b/ffmpeg/libavcodec/parser.c @@ -0,0 +1,300 @@ +/* + * Audio and Video frame extraction + * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003 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 "parser.h" +#include "libavutil/mem.h" + +static AVCodecParser *av_first_parser = NULL; + +AVCodecParser* av_parser_next(AVCodecParser *p){ + if(p) return p->next; + else return av_first_parser; +} + +void av_register_codec_parser(AVCodecParser *parser) +{ + parser->next = av_first_parser; + av_first_parser = parser; +} + +AVCodecParserContext *av_parser_init(int codec_id) +{ + AVCodecParserContext *s = NULL; + AVCodecParser *parser; + int ret; + + if(codec_id == AV_CODEC_ID_NONE) + return NULL; + + for(parser = av_first_parser; parser != NULL; parser = parser->next) { + if (parser->codec_ids[0] == codec_id || + parser->codec_ids[1] == codec_id || + parser->codec_ids[2] == codec_id || + parser->codec_ids[3] == codec_id || + parser->codec_ids[4] == codec_id) + goto found; + } + return NULL; + found: + s = av_mallocz(sizeof(AVCodecParserContext)); + if (!s) + goto err_out; + s->parser = parser; + s->priv_data = av_mallocz(parser->priv_data_size); + if (!s->priv_data) + goto err_out; + s->fetch_timestamp=1; + s->pict_type = AV_PICTURE_TYPE_I; + if (parser->parser_init) { + ret = parser->parser_init(s); + if (ret != 0) + goto err_out; + } + s->key_frame = -1; + s->convergence_duration = 0; + s->dts_sync_point = INT_MIN; + s->dts_ref_dts_delta = INT_MIN; + s->pts_dts_delta = INT_MIN; + return s; + +err_out: + if (s) + av_freep(&s->priv_data); + av_free(s); + return NULL; +} + +void ff_fetch_timestamp(AVCodecParserContext *s, int off, int remove){ + int i; + + s->dts= s->pts= AV_NOPTS_VALUE; + s->pos= -1; + s->offset= 0; + for(i = 0; i < AV_PARSER_PTS_NB; i++) { + if ( s->cur_offset + off >= s->cur_frame_offset[i] + && (s->frame_offset < s->cur_frame_offset[i] || + (!s->frame_offset && !s->next_frame_offset)) // first field/frame + // check disabled since MPEG-TS does not send complete PES packets + && /*s->next_frame_offset + off <*/ s->cur_frame_end[i]){ + s->dts= s->cur_frame_dts[i]; + s->pts= s->cur_frame_pts[i]; + s->pos= s->cur_frame_pos[i]; + s->offset = s->next_frame_offset - s->cur_frame_offset[i]; + if(remove) + s->cur_frame_offset[i]= INT64_MAX; + if(s->cur_offset + off < s->cur_frame_end[i]) + break; + } + } +} + +int av_parser_parse2(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, + int64_t pts, int64_t dts, + int64_t pos) +{ + int index, i; + uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]; + + if(!(s->flags & PARSER_FLAG_FETCHED_OFFSET)) { + s->next_frame_offset = + s->cur_offset = pos; + s->flags |= PARSER_FLAG_FETCHED_OFFSET; + } + + if (buf_size == 0) { + /* padding is always necessary even if EOF, so we add it here */ + memset(dummy_buf, 0, sizeof(dummy_buf)); + buf = dummy_buf; + } else if (s->cur_offset + buf_size != + s->cur_frame_end[s->cur_frame_start_index]) { /* skip remainder packets */ + /* add a new packet descriptor */ + i = (s->cur_frame_start_index + 1) & (AV_PARSER_PTS_NB - 1); + s->cur_frame_start_index = i; + s->cur_frame_offset[i] = s->cur_offset; + s->cur_frame_end[i] = s->cur_offset + buf_size; + s->cur_frame_pts[i] = pts; + s->cur_frame_dts[i] = dts; + s->cur_frame_pos[i] = pos; + } + + if (s->fetch_timestamp){ + s->fetch_timestamp=0; + s->last_pts = s->pts; + s->last_dts = s->dts; + s->last_pos = s->pos; + ff_fetch_timestamp(s, 0, 0); + } + + /* WARNING: the returned index can be negative */ + index = s->parser->parser_parse(s, avctx, (const uint8_t **)poutbuf, poutbuf_size, buf, buf_size); + /* update the file pointer */ + if (*poutbuf_size) { + /* fill the data for the current frame */ + s->frame_offset = s->next_frame_offset; + + /* offset of the next frame */ + s->next_frame_offset = s->cur_offset + index; + s->fetch_timestamp=1; + } + if (index < 0) + index = 0; + s->cur_offset += index; + return index; +} + +int av_parser_change(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + + if(s && s->parser->split){ + if((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) || (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)){ + int i= s->parser->split(avctx, buf, buf_size); + buf += i; + buf_size -= i; + } + } + + /* cast to avoid warning about discarding qualifiers */ + *poutbuf= (uint8_t *) buf; + *poutbuf_size= buf_size; + if(avctx->extradata){ + if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) + /*||(s->pict_type != AV_PICTURE_TYPE_I && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_NOKEY))*/ + /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){ + int size= buf_size + avctx->extradata_size; + *poutbuf_size= size; + *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + + memcpy(*poutbuf, avctx->extradata, avctx->extradata_size); + memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + return 1; + } + } + + return 0; +} + +void av_parser_close(AVCodecParserContext *s) +{ + if(s){ + if (s->parser->parser_close) + s->parser->parser_close(s); + av_free(s->priv_data); + av_free(s); + } +} + +/*****************************************************/ + +int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size) +{ + if(pc->overread){ + av_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", + pc->overread, pc->state, next, pc->index, pc->overread_index); + av_dlog(NULL, "%X %X %X %X\n", (*buf)[0], (*buf)[1], (*buf)[2], (*buf)[3]); + } + + /* Copy overread bytes from last frame into buffer. */ + for(; pc->overread>0; pc->overread--){ + pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; + } + + /* flush remaining if EOF */ + if(!*buf_size && next == END_NOT_FOUND){ + next= 0; + } + + pc->last_index= pc->index; + + /* copy into buffer end return */ + if(next == END_NOT_FOUND){ + void* new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); + + if(!new_buffer) + return AVERROR(ENOMEM); + pc->buffer = new_buffer; + memcpy(&pc->buffer[pc->index], *buf, *buf_size); + pc->index += *buf_size; + return -1; + } + + *buf_size= + pc->overread_index= pc->index + next; + + /* append to buffer */ + if(pc->index){ + void* new_buffer = av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); + + if(!new_buffer) + return AVERROR(ENOMEM); + pc->buffer = new_buffer; + if (next > -FF_INPUT_BUFFER_PADDING_SIZE) + memcpy(&pc->buffer[pc->index], *buf, + next + FF_INPUT_BUFFER_PADDING_SIZE); + pc->index = 0; + *buf= pc->buffer; + } + + /* store overread bytes */ + for(;next < 0; next++){ + pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; + pc->state64 = (pc->state64<<8) | pc->buffer[pc->last_index + next]; + pc->overread++; + } + + if(pc->overread){ + av_dlog(NULL, "overread %d, state:%X next:%d index:%d o_index:%d\n", + pc->overread, pc->state, next, pc->index, pc->overread_index); + av_dlog(NULL, "%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); + } + + return 0; +} + +void ff_parse_close(AVCodecParserContext *s) +{ + ParseContext *pc = s->priv_data; + + av_freep(&pc->buffer); +} + +/*************************/ + +int ff_mpeg4video_split(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + int i; + uint32_t state= -1; + + for(i=0; i> 4; + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_dlog(avctx, "pcm_bluray_parse_header: header = %02x%02x%02x%02x\n", + header[0], header[1], header[2], header[3]); + + /* get the sample depth and derive the sample format from it */ + avctx->bits_per_coded_sample = bits_per_samples[header[3] >> 6]; + if (!(avctx->bits_per_coded_sample == 16 || avctx->bits_per_coded_sample == 24)) { + av_log(avctx, AV_LOG_ERROR, "unsupported sample depth (%d)\n", avctx->bits_per_coded_sample); + return -1; + } + avctx->sample_fmt = avctx->bits_per_coded_sample == 16 ? AV_SAMPLE_FMT_S16 : + AV_SAMPLE_FMT_S32; + if (avctx->sample_fmt == AV_SAMPLE_FMT_S32) + avctx->bits_per_raw_sample = avctx->bits_per_coded_sample; + + /* get the sample rate. Not all values are used. */ + switch (header[2] & 0x0f) { + case 1: + avctx->sample_rate = 48000; + break; + case 4: + avctx->sample_rate = 96000; + break; + case 5: + avctx->sample_rate = 192000; + break; + default: + avctx->sample_rate = 0; + av_log(avctx, AV_LOG_ERROR, "reserved sample rate (%d)\n", + header[2] & 0x0f); + return -1; + } + + /* + * get the channel number (and mapping). Not all values are used. + * It must be noted that the number of channels in the MPEG stream can + * differ from the actual meaningful number, e.g. mono audio still has two + * channels, one being empty. + */ + avctx->channel_layout = channel_layouts[channel_layout]; + avctx->channels = channels[channel_layout]; + if (!avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "reserved channel configuration (%d)\n", + channel_layout); + return -1; + } + + avctx->bit_rate = FFALIGN(avctx->channels, 2) * avctx->sample_rate * + avctx->bits_per_coded_sample; + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_dlog(avctx, + "pcm_bluray_parse_header: %d channels, %d bits per sample, %d Hz, %d bit/s\n", + avctx->channels, avctx->bits_per_coded_sample, + avctx->sample_rate, avctx->bit_rate); + return 0; +} + +static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *src = avpkt->data; + int buf_size = avpkt->size; + GetByteContext gb; + int num_source_channels, channel, retval; + int sample_size, samples; + int16_t *dst16; + int32_t *dst32; + + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "PCM packet too small\n"); + return -1; + } + + if (pcm_bluray_parse_header(avctx, src)) + return -1; + src += 4; + buf_size -= 4; + + bytestream2_init(&gb, src, buf_size); + + /* There's always an even number of channels in the source */ + num_source_channels = FFALIGN(avctx->channels, 2); + sample_size = (num_source_channels * (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3; + samples = buf_size / sample_size; + + /* get output buffer */ + frame->nb_samples = samples; + if ((retval = ff_get_buffer(avctx, frame, 0)) < 0) + return retval; + dst16 = (int16_t *)frame->data[0]; + dst32 = (int32_t *)frame->data[0]; + + if (samples) { + switch (avctx->channel_layout) { + /* cases with same number of source and coded channels */ + case AV_CH_LAYOUT_STEREO: + case AV_CH_LAYOUT_4POINT0: + case AV_CH_LAYOUT_2_2: + samples *= num_source_channels; + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { +#if HAVE_BIGENDIAN + bytestream2_get_buffer(&gb, dst16, buf_size); +#else + do { + *dst16++ = bytestream2_get_be16u(&gb); + } while (--samples); +#endif + } else { + do { + *dst32++ = bytestream2_get_be24u(&gb) << 8; + } while (--samples); + } + break; + /* cases where number of source channels = coded channels + 1 */ + case AV_CH_LAYOUT_MONO: + case AV_CH_LAYOUT_SURROUND: + case AV_CH_LAYOUT_2_1: + case AV_CH_LAYOUT_5POINT0: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { +#if HAVE_BIGENDIAN + bytestream2_get_buffer(&gb, dst16, avctx->channels * 2); + dst16 += avctx->channels; +#else + channel = avctx->channels; + do { + *dst16++ = bytestream2_get_be16u(&gb); + } while (--channel); +#endif + bytestream2_skip(&gb, 2); + } while (--samples); + } else { + do { + channel = avctx->channels; + do { + *dst32++ = bytestream2_get_be24u(&gb) << 8; + } while (--channel); + bytestream2_skip(&gb, 3); + } while (--samples); + } + break; + /* remapping: L, R, C, LBack, RBack, LF */ + case AV_CH_LAYOUT_5POINT1: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { + dst16[0] = bytestream2_get_be16u(&gb); + dst16[1] = bytestream2_get_be16u(&gb); + dst16[2] = bytestream2_get_be16u(&gb); + dst16[4] = bytestream2_get_be16u(&gb); + dst16[5] = bytestream2_get_be16u(&gb); + dst16[3] = bytestream2_get_be16u(&gb); + dst16 += 6; + } while (--samples); + } else { + do { + dst32[0] = bytestream2_get_be24u(&gb) << 8; + dst32[1] = bytestream2_get_be24u(&gb) << 8; + dst32[2] = bytestream2_get_be24u(&gb) << 8; + dst32[4] = bytestream2_get_be24u(&gb) << 8; + dst32[5] = bytestream2_get_be24u(&gb) << 8; + dst32[3] = bytestream2_get_be24u(&gb) << 8; + dst32 += 6; + } while (--samples); + } + break; + /* remapping: L, R, C, LSide, LBack, RBack, RSide, */ + case AV_CH_LAYOUT_7POINT0: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { + dst16[0] = bytestream2_get_be16u(&gb); + dst16[1] = bytestream2_get_be16u(&gb); + dst16[2] = bytestream2_get_be16u(&gb); + dst16[5] = bytestream2_get_be16u(&gb); + dst16[3] = bytestream2_get_be16u(&gb); + dst16[4] = bytestream2_get_be16u(&gb); + dst16[6] = bytestream2_get_be16u(&gb); + dst16 += 7; + bytestream2_skip(&gb, 2); + } while (--samples); + } else { + do { + dst32[0] = bytestream2_get_be24u(&gb) << 8; + dst32[1] = bytestream2_get_be24u(&gb) << 8; + dst32[2] = bytestream2_get_be24u(&gb) << 8; + dst32[5] = bytestream2_get_be24u(&gb) << 8; + dst32[3] = bytestream2_get_be24u(&gb) << 8; + dst32[4] = bytestream2_get_be24u(&gb) << 8; + dst32[6] = bytestream2_get_be24u(&gb) << 8; + dst32 += 7; + bytestream2_skip(&gb, 3); + } while (--samples); + } + break; + /* remapping: L, R, C, LSide, LBack, RBack, RSide, LF */ + case AV_CH_LAYOUT_7POINT1: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { + dst16[0] = bytestream2_get_be16u(&gb); + dst16[1] = bytestream2_get_be16u(&gb); + dst16[2] = bytestream2_get_be16u(&gb); + dst16[6] = bytestream2_get_be16u(&gb); + dst16[4] = bytestream2_get_be16u(&gb); + dst16[5] = bytestream2_get_be16u(&gb); + dst16[7] = bytestream2_get_be16u(&gb); + dst16[3] = bytestream2_get_be16u(&gb); + dst16 += 8; + } while (--samples); + } else { + do { + dst32[0] = bytestream2_get_be24u(&gb) << 8; + dst32[1] = bytestream2_get_be24u(&gb) << 8; + dst32[2] = bytestream2_get_be24u(&gb) << 8; + dst32[6] = bytestream2_get_be24u(&gb) << 8; + dst32[4] = bytestream2_get_be24u(&gb) << 8; + dst32[5] = bytestream2_get_be24u(&gb) << 8; + dst32[7] = bytestream2_get_be24u(&gb) << 8; + dst32[3] = bytestream2_get_be24u(&gb) << 8; + dst32 += 8; + } while (--samples); + } + break; + } + } + + *got_frame_ptr = 1; + + retval = bytestream2_tell(&gb); + if (avctx->debug & FF_DEBUG_BITSTREAM) + av_dlog(avctx, "pcm_bluray_decode_frame: decoded %d -> %d bytes\n", + retval, buf_size); + return retval + 4; +} + +AVCodec ff_pcm_bluray_decoder = { + .name = "pcm_bluray", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_PCM_BLURAY, + .decode = pcm_bluray_decode_frame, + .capabilities = CODEC_CAP_DR1, + .sample_fmts = (const enum AVSampleFormat[]){ + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), +}; diff --git a/ffmpeg/libavcodec/pcm.c b/ffmpeg/libavcodec/pcm.c new file mode 100644 index 0000000..83482dd --- /dev/null +++ b/ffmpeg/libavcodec/pcm.c @@ -0,0 +1,625 @@ +/* + * PCM codecs + * Copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * PCM codecs + */ + +#include "libavutil/attributes.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" +#include "pcm_tablegen.h" + +static av_cold int pcm_encode_init(AVCodecContext *avctx) +{ + avctx->frame_size = 0; + switch (avctx->codec->id) { + case AV_CODEC_ID_PCM_ALAW: + pcm_alaw_tableinit(); + break; + case AV_CODEC_ID_PCM_MULAW: + pcm_ulaw_tableinit(); + break; + default: + break; + } + + avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id); + avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8; + avctx->bit_rate = avctx->block_align * avctx->sample_rate * 8; + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int pcm_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +/** + * Write PCM samples macro + * @param type Datatype of native machine format + * @param endian bytestream_put_xxx() suffix + * @param src Source pointer (variable name) + * @param dst Destination pointer (variable name) + * @param n Total number of samples (variable name) + * @param shift Bitshift (bits) + * @param offset Sample value offset + */ +#define ENCODE(type, endian, src, dst, n, shift, offset) \ + samples_ ## type = (const type *) src; \ + for (; n > 0; n--) { \ + register type v = (*samples_ ## type++ >> shift) + offset; \ + bytestream_put_ ## endian(&dst, v); \ + } + +#define ENCODE_PLANAR(type, endian, dst, n, shift, offset) \ + n /= avctx->channels; \ + for (c = 0; c < avctx->channels; c++) { \ + int i; \ + samples_ ## type = (const type *) frame->extended_data[c]; \ + for (i = n; i > 0; i--) { \ + register type v = (*samples_ ## type++ >> shift) + offset; \ + bytestream_put_ ## endian(&dst, v); \ + } \ + } + +static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + int n, c, sample_size, v, ret; + const short *samples; + unsigned char *dst; + const uint8_t *samples_uint8_t; + const int16_t *samples_int16_t; + const int32_t *samples_int32_t; + const int64_t *samples_int64_t; + const uint16_t *samples_uint16_t; + const uint32_t *samples_uint32_t; + + sample_size = av_get_bits_per_sample(avctx->codec->id) / 8; + n = frame->nb_samples * avctx->channels; + samples = (const short *)frame->data[0]; + + if ((ret = ff_alloc_packet2(avctx, avpkt, n * sample_size)) < 0) + return ret; + dst = avpkt->data; + + switch (avctx->codec->id) { + case AV_CODEC_ID_PCM_U32LE: + ENCODE(uint32_t, le32, samples, dst, n, 0, 0x80000000) + break; + case AV_CODEC_ID_PCM_U32BE: + ENCODE(uint32_t, be32, samples, dst, n, 0, 0x80000000) + break; + case AV_CODEC_ID_PCM_S24LE: + ENCODE(int32_t, le24, samples, dst, n, 8, 0) + break; + case AV_CODEC_ID_PCM_S24LE_PLANAR: + ENCODE_PLANAR(int32_t, le24, dst, n, 8, 0) + break; + case AV_CODEC_ID_PCM_S24BE: + ENCODE(int32_t, be24, samples, dst, n, 8, 0) + break; + case AV_CODEC_ID_PCM_U24LE: + ENCODE(uint32_t, le24, samples, dst, n, 8, 0x800000) + break; + case AV_CODEC_ID_PCM_U24BE: + ENCODE(uint32_t, be24, samples, dst, n, 8, 0x800000) + break; + case AV_CODEC_ID_PCM_S24DAUD: + for (; n > 0; n--) { + uint32_t tmp = ff_reverse[(*samples >> 8) & 0xff] + + (ff_reverse[*samples & 0xff] << 8); + tmp <<= 4; // sync flags would go here + bytestream_put_be24(&dst, tmp); + samples++; + } + break; + case AV_CODEC_ID_PCM_U16LE: + ENCODE(uint16_t, le16, samples, dst, n, 0, 0x8000) + break; + case AV_CODEC_ID_PCM_U16BE: + ENCODE(uint16_t, be16, samples, dst, n, 0, 0x8000) + break; + case AV_CODEC_ID_PCM_S8: + ENCODE(uint8_t, byte, samples, dst, n, 0, -128) + break; + case AV_CODEC_ID_PCM_S8_PLANAR: + ENCODE_PLANAR(uint8_t, byte, dst, n, 0, -128) + break; +#if HAVE_BIGENDIAN + case AV_CODEC_ID_PCM_F64LE: + ENCODE(int64_t, le64, samples, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_F32LE: + ENCODE(int32_t, le32, samples, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S32LE_PLANAR: + ENCODE_PLANAR(int32_t, le32, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16LE: + ENCODE(int16_t, le16, samples, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16LE_PLANAR: + ENCODE_PLANAR(int16_t, le16, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_F64BE: + case AV_CODEC_ID_PCM_F32BE: + case AV_CODEC_ID_PCM_S32BE: + case AV_CODEC_ID_PCM_S16BE: +#else + case AV_CODEC_ID_PCM_F64BE: + ENCODE(int64_t, be64, samples, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_F32BE: + case AV_CODEC_ID_PCM_S32BE: + ENCODE(int32_t, be32, samples, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16BE: + ENCODE(int16_t, be16, samples, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16BE_PLANAR: + ENCODE_PLANAR(int16_t, be16, dst, n, 0, 0) + break; + case AV_CODEC_ID_PCM_F64LE: + case AV_CODEC_ID_PCM_F32LE: + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_S16LE: +#endif /* HAVE_BIGENDIAN */ + case AV_CODEC_ID_PCM_U8: + memcpy(dst, samples, n * sample_size); + break; +#if HAVE_BIGENDIAN + case AV_CODEC_ID_PCM_S16BE_PLANAR: +#else + case AV_CODEC_ID_PCM_S16LE_PLANAR: + case AV_CODEC_ID_PCM_S32LE_PLANAR: +#endif /* HAVE_BIGENDIAN */ + n /= avctx->channels; + for (c = 0; c < avctx->channels; c++) { + const uint8_t *src = frame->extended_data[c]; + bytestream_put_buffer(&dst, src, n * sample_size); + } + break; + case AV_CODEC_ID_PCM_ALAW: + for (; n > 0; n--) { + v = *samples++; + *dst++ = linear_to_alaw[(v + 32768) >> 2]; + } + break; + case AV_CODEC_ID_PCM_MULAW: + for (; n > 0; n--) { + v = *samples++; + *dst++ = linear_to_ulaw[(v + 32768) >> 2]; + } + break; + default: + return -1; + } + + *got_packet_ptr = 1; + return 0; +} + +typedef struct PCMDecode { + short table[256]; +} PCMDecode; + +static av_cold int pcm_decode_init(AVCodecContext *avctx) +{ + PCMDecode *s = avctx->priv_data; + int i; + + if (avctx->channels <= 0) { + av_log(avctx, AV_LOG_ERROR, "PCM channels out of bounds\n"); + return AVERROR(EINVAL); + } + + switch (avctx->codec_id) { + case AV_CODEC_ID_PCM_ALAW: + for (i = 0; i < 256; i++) + s->table[i] = alaw2linear(i); + break; + case AV_CODEC_ID_PCM_MULAW: + for (i = 0; i < 256; i++) + s->table[i] = ulaw2linear(i); + break; + default: + break; + } + + avctx->sample_fmt = avctx->codec->sample_fmts[0]; + + if (avctx->sample_fmt == AV_SAMPLE_FMT_S32) + avctx->bits_per_raw_sample = av_get_bits_per_sample(avctx->codec_id); + + return 0; +} + +/** + * Read PCM samples macro + * @param size Data size of native machine format + * @param endian bytestream_get_xxx() endian suffix + * @param src Source pointer (variable name) + * @param dst Destination pointer (variable name) + * @param n Total number of samples (variable name) + * @param shift Bitshift (bits) + * @param offset Sample value offset + */ +#define DECODE(size, endian, src, dst, n, shift, offset) \ + for (; n > 0; n--) { \ + uint ## size ## _t v = bytestream_get_ ## endian(&src); \ + AV_WN ## size ## A(dst, (v - offset) << shift); \ + dst += size / 8; \ + } + +#define DECODE_PLANAR(size, endian, src, dst, n, shift, offset) \ + n /= avctx->channels; \ + for (c = 0; c < avctx->channels; c++) { \ + int i; \ + dst = frame->extended_data[c]; \ + for (i = n; i > 0; i--) { \ + uint ## size ## _t v = bytestream_get_ ## endian(&src); \ + AV_WN ## size ## A(dst, (v - offset) << shift); \ + dst += size / 8; \ + } \ + } + +static int pcm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *src = avpkt->data; + int buf_size = avpkt->size; + PCMDecode *s = avctx->priv_data; + AVFrame *frame = data; + int sample_size, c, n, ret, samples_per_block; + uint8_t *samples; + int32_t *dst_int32_t; + + sample_size = av_get_bits_per_sample(avctx->codec_id) / 8; + + /* av_get_bits_per_sample returns 0 for AV_CODEC_ID_PCM_DVD */ + samples_per_block = 1; + if (AV_CODEC_ID_PCM_DVD == avctx->codec_id) { + if (avctx->bits_per_coded_sample != 20 && + avctx->bits_per_coded_sample != 24) { + av_log(avctx, AV_LOG_ERROR, + "PCM DVD unsupported sample depth %i\n", + avctx->bits_per_coded_sample); + return AVERROR(EINVAL); + } + /* 2 samples are interleaved per block in PCM_DVD */ + samples_per_block = 2; + sample_size = avctx->bits_per_coded_sample * 2 / 8; + } else if (avctx->codec_id == AV_CODEC_ID_PCM_LXF) { + /* we process 40-bit blocks per channel for LXF */ + samples_per_block = 2; + sample_size = 5; + } + + if (sample_size == 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid sample_size\n"); + return AVERROR(EINVAL); + } + + if (avctx->channels == 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); + } + + if (avctx->codec_id != avctx->codec->id) { + av_log(avctx, AV_LOG_ERROR, "codec ids mismatch\n"); + return AVERROR(EINVAL); + } + + n = avctx->channels * sample_size; + + if (n && buf_size % n) { + if (buf_size < n) { + av_log(avctx, AV_LOG_ERROR, + "Invalid PCM packet, data has size %d but at least a size of %d was expected\n", + buf_size, n); + return AVERROR_INVALIDDATA; + } else + buf_size -= buf_size % n; + } + + n = buf_size / sample_size; + + /* get output buffer */ + frame->nb_samples = n * samples_per_block / avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = frame->data[0]; + + switch (avctx->codec_id) { + case AV_CODEC_ID_PCM_U32LE: + DECODE(32, le32, src, samples, n, 0, 0x80000000) + break; + case AV_CODEC_ID_PCM_U32BE: + DECODE(32, be32, src, samples, n, 0, 0x80000000) + break; + case AV_CODEC_ID_PCM_S24LE: + DECODE(32, le24, src, samples, n, 8, 0) + break; + case AV_CODEC_ID_PCM_S24LE_PLANAR: + DECODE_PLANAR(32, le24, src, samples, n, 8, 0); + break; + case AV_CODEC_ID_PCM_S24BE: + DECODE(32, be24, src, samples, n, 8, 0) + break; + case AV_CODEC_ID_PCM_U24LE: + DECODE(32, le24, src, samples, n, 8, 0x800000) + break; + case AV_CODEC_ID_PCM_U24BE: + DECODE(32, be24, src, samples, n, 8, 0x800000) + break; + case AV_CODEC_ID_PCM_S24DAUD: + for (; n > 0; n--) { + uint32_t v = bytestream_get_be24(&src); + v >>= 4; // sync flags are here + AV_WN16A(samples, ff_reverse[(v >> 8) & 0xff] + + (ff_reverse[v & 0xff] << 8)); + samples += 2; + } + break; + case AV_CODEC_ID_PCM_U16LE: + DECODE(16, le16, src, samples, n, 0, 0x8000) + break; + case AV_CODEC_ID_PCM_U16BE: + DECODE(16, be16, src, samples, n, 0, 0x8000) + break; + case AV_CODEC_ID_PCM_S8: + for (; n > 0; n--) + *samples++ = *src++ + 128; + break; + case AV_CODEC_ID_PCM_S8_PLANAR: + n /= avctx->channels; + for (c = 0; c < avctx->channels; c++) { + int i; + samples = frame->extended_data[c]; + for (i = n; i > 0; i--) + *samples++ = *src++ + 128; + } + break; +#if HAVE_BIGENDIAN + case AV_CODEC_ID_PCM_F64LE: + DECODE(64, le64, src, samples, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_F32LE: + DECODE(32, le32, src, samples, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S32LE_PLANAR: + DECODE_PLANAR(32, le32, src, samples, n, 0, 0); + break; + case AV_CODEC_ID_PCM_S16LE: + DECODE(16, le16, src, samples, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16LE_PLANAR: + DECODE_PLANAR(16, le16, src, samples, n, 0, 0); + break; + case AV_CODEC_ID_PCM_F64BE: + case AV_CODEC_ID_PCM_F32BE: + case AV_CODEC_ID_PCM_S32BE: + case AV_CODEC_ID_PCM_S16BE: +#else + case AV_CODEC_ID_PCM_F64BE: + DECODE(64, be64, src, samples, n, 0, 0) + break; + case AV_CODEC_ID_PCM_F32BE: + case AV_CODEC_ID_PCM_S32BE: + DECODE(32, be32, src, samples, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16BE: + DECODE(16, be16, src, samples, n, 0, 0) + break; + case AV_CODEC_ID_PCM_S16BE_PLANAR: + DECODE_PLANAR(16, be16, src, samples, n, 0, 0); + break; + case AV_CODEC_ID_PCM_F64LE: + case AV_CODEC_ID_PCM_F32LE: + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_S16LE: +#endif /* HAVE_BIGENDIAN */ + case AV_CODEC_ID_PCM_U8: + memcpy(samples, src, n * sample_size); + break; +#if HAVE_BIGENDIAN + case AV_CODEC_ID_PCM_S16BE_PLANAR: +#else + case AV_CODEC_ID_PCM_S16LE_PLANAR: + case AV_CODEC_ID_PCM_S32LE_PLANAR: +#endif /* HAVE_BIGENDIAN */ + n /= avctx->channels; + for (c = 0; c < avctx->channels; c++) { + samples = frame->extended_data[c]; + bytestream_get_buffer(&src, samples, n * sample_size); + } + break; + case AV_CODEC_ID_PCM_ZORK: + for (; n > 0; n--) { + int v = *src++; + if (v < 128) + v = 128 - v; + *samples++ = v; + } + break; + case AV_CODEC_ID_PCM_ALAW: + case AV_CODEC_ID_PCM_MULAW: + for (; n > 0; n--) { + AV_WN16A(samples, s->table[*src++]); + samples += 2; + } + break; + case AV_CODEC_ID_PCM_DVD: + { + const uint8_t *src8; + dst_int32_t = (int32_t *)frame->data[0]; + n /= avctx->channels; + switch (avctx->bits_per_coded_sample) { + case 20: + while (n--) { + c = avctx->channels; + src8 = src + 4 * c; + while (c--) { + *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8 & 0xf0) << 8); + *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8++ & 0x0f) << 12); + } + src = src8; + } + break; + case 24: + while (n--) { + c = avctx->channels; + src8 = src + 4 * c; + while (c--) { + *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8++) << 8); + *dst_int32_t++ = (bytestream_get_be16(&src) << 16) + ((*src8++) << 8); + } + src = src8; + } + break; + } + break; + } + case AV_CODEC_ID_PCM_LXF: + { + int i; + n /= avctx->channels; + for (c = 0; c < avctx->channels; c++) { + dst_int32_t = (int32_t *)frame->extended_data[c]; + for (i = 0; i < n; i++) { + // extract low 20 bits and expand to 32 bits + *dst_int32_t++ = (src[2] << 28) | + (src[1] << 20) | + (src[0] << 12) | + ((src[2] & 0x0F) << 8) | + src[1]; + // extract high 20 bits and expand to 32 bits + *dst_int32_t++ = (src[4] << 24) | + (src[3] << 16) | + ((src[2] & 0xF0) << 8) | + (src[4] << 4) | + (src[3] >> 4); + src += 5; + } + } + break; + } + default: + return -1; + } + + *got_frame_ptr = 1; + + return buf_size; +} + +#define PCM_ENCODER_0(id_, sample_fmt_, name_, long_name_) +#define PCM_ENCODER_1(id_, sample_fmt_, name_, long_name_) \ +AVCodec ff_ ## name_ ## _encoder = { \ + .name = #name_, \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = AV_CODEC_ID_ ## id_, \ + .init = pcm_encode_init, \ + .encode2 = pcm_encode_frame, \ + .close = pcm_encode_close, \ + .capabilities = CODEC_CAP_VARIABLE_FRAME_SIZE, \ + .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ + AV_SAMPLE_FMT_NONE }, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ +} + +#define PCM_ENCODER_2(cf, id, sample_fmt, name, long_name) \ + PCM_ENCODER_ ## cf(id, sample_fmt, name, long_name) +#define PCM_ENCODER_3(cf, id, sample_fmt, name, long_name) \ + PCM_ENCODER_2(cf, id, sample_fmt, name, long_name) +#define PCM_ENCODER(id, sample_fmt, name, long_name) \ + PCM_ENCODER_3(CONFIG_ ## id ## _ENCODER, id, sample_fmt, name, long_name) + +#define PCM_DECODER_0(id, sample_fmt, name, long_name) +#define PCM_DECODER_1(id_, sample_fmt_, name_, long_name_) \ +AVCodec ff_ ## name_ ## _decoder = { \ + .name = #name_, \ + .type = AVMEDIA_TYPE_AUDIO, \ + .id = AV_CODEC_ID_ ## id_, \ + .priv_data_size = sizeof(PCMDecode), \ + .init = pcm_decode_init, \ + .decode = pcm_decode_frame, \ + .capabilities = CODEC_CAP_DR1, \ + .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ + AV_SAMPLE_FMT_NONE }, \ + .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ +} + +#define PCM_DECODER_2(cf, id, sample_fmt, name, long_name) \ + PCM_DECODER_ ## cf(id, sample_fmt, name, long_name) +#define PCM_DECODER_3(cf, id, sample_fmt, name, long_name) \ + PCM_DECODER_2(cf, id, sample_fmt, name, long_name) +#define PCM_DECODER(id, sample_fmt, name, long_name) \ + PCM_DECODER_3(CONFIG_ ## id ## _DECODER, id, sample_fmt, name, long_name) + +#define PCM_CODEC(id, sample_fmt_, name, long_name_) \ + PCM_ENCODER(id, sample_fmt_, name, long_name_); \ + PCM_DECODER(id, sample_fmt_, name, long_name_) + +/* Note: Do not forget to add new entries to the Makefile as well. */ +PCM_CODEC (PCM_ALAW, AV_SAMPLE_FMT_S16, pcm_alaw, "PCM A-law / G.711 A-law"); +PCM_DECODER(PCM_DVD, AV_SAMPLE_FMT_S32, pcm_dvd, "PCM signed 20|24-bit big-endian"); +PCM_CODEC (PCM_F32BE, AV_SAMPLE_FMT_FLT, pcm_f32be, "PCM 32-bit floating point big-endian"); +PCM_CODEC (PCM_F32LE, AV_SAMPLE_FMT_FLT, pcm_f32le, "PCM 32-bit floating point little-endian"); +PCM_CODEC (PCM_F64BE, AV_SAMPLE_FMT_DBL, pcm_f64be, "PCM 64-bit floating point big-endian"); +PCM_CODEC (PCM_F64LE, AV_SAMPLE_FMT_DBL, pcm_f64le, "PCM 64-bit floating point little-endian"); +PCM_DECODER(PCM_LXF, AV_SAMPLE_FMT_S32P,pcm_lxf, "PCM signed 20-bit little-endian planar"); +PCM_CODEC (PCM_MULAW, AV_SAMPLE_FMT_S16, pcm_mulaw, "PCM mu-law / G.711 mu-law"); +PCM_CODEC (PCM_S8, AV_SAMPLE_FMT_U8, pcm_s8, "PCM signed 8-bit"); +PCM_CODEC (PCM_S8_PLANAR, AV_SAMPLE_FMT_U8P, pcm_s8_planar, "PCM signed 8-bit planar"); +PCM_CODEC (PCM_S16BE, AV_SAMPLE_FMT_S16, pcm_s16be, "PCM signed 16-bit big-endian"); +PCM_CODEC (PCM_S16BE_PLANAR, AV_SAMPLE_FMT_S16P,pcm_s16be_planar, "PCM signed 16-bit big-endian planar"); +PCM_CODEC (PCM_S16LE, AV_SAMPLE_FMT_S16, pcm_s16le, "PCM signed 16-bit little-endian"); +PCM_CODEC (PCM_S16LE_PLANAR, AV_SAMPLE_FMT_S16P,pcm_s16le_planar, "PCM signed 16-bit little-endian planar"); +PCM_CODEC (PCM_S24BE, AV_SAMPLE_FMT_S32, pcm_s24be, "PCM signed 24-bit big-endian"); +PCM_CODEC (PCM_S24DAUD, AV_SAMPLE_FMT_S16, pcm_s24daud, "PCM D-Cinema audio signed 24-bit"); +PCM_CODEC (PCM_S24LE, AV_SAMPLE_FMT_S32, pcm_s24le, "PCM signed 24-bit little-endian"); +PCM_CODEC (PCM_S24LE_PLANAR, AV_SAMPLE_FMT_S32P,pcm_s24le_planar, "PCM signed 24-bit little-endian planar"); +PCM_CODEC (PCM_S32BE, AV_SAMPLE_FMT_S32, pcm_s32be, "PCM signed 32-bit big-endian"); +PCM_CODEC (PCM_S32LE, AV_SAMPLE_FMT_S32, pcm_s32le, "PCM signed 32-bit little-endian"); +PCM_CODEC (PCM_S32LE_PLANAR, AV_SAMPLE_FMT_S32P,pcm_s32le_planar, "PCM signed 32-bit little-endian planar"); +PCM_CODEC (PCM_U8, AV_SAMPLE_FMT_U8, pcm_u8, "PCM unsigned 8-bit"); +PCM_CODEC (PCM_U16BE, AV_SAMPLE_FMT_S16, pcm_u16be, "PCM unsigned 16-bit big-endian"); +PCM_CODEC (PCM_U16LE, AV_SAMPLE_FMT_S16, pcm_u16le, "PCM unsigned 16-bit little-endian"); +PCM_CODEC (PCM_U24BE, AV_SAMPLE_FMT_S32, pcm_u24be, "PCM unsigned 24-bit big-endian"); +PCM_CODEC (PCM_U24LE, AV_SAMPLE_FMT_S32, pcm_u24le, "PCM unsigned 24-bit little-endian"); +PCM_CODEC (PCM_U32BE, AV_SAMPLE_FMT_S32, pcm_u32be, "PCM unsigned 32-bit big-endian"); +PCM_CODEC (PCM_U32LE, AV_SAMPLE_FMT_S32, pcm_u32le, "PCM unsigned 32-bit little-endian"); +PCM_DECODER(PCM_ZORK, AV_SAMPLE_FMT_U8, pcm_zork, "PCM Zork"); + diff --git a/ffmpeg/libavcodec/pcm_tablegen.c b/ffmpeg/libavcodec/pcm_tablegen.c new file mode 100644 index 0000000..bf8e7fb --- /dev/null +++ b/ffmpeg/libavcodec/pcm_tablegen.c @@ -0,0 +1,39 @@ +/* + * Generate a header file for hardcoded PCM tables + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#include "pcm_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + pcm_alaw_tableinit(); + pcm_ulaw_tableinit(); + + write_fileheader(); + + WRITE_ARRAY("static const", uint8_t, linear_to_alaw); + WRITE_ARRAY("static const", uint8_t, linear_to_ulaw); + + return 0; +} diff --git a/ffmpeg/libavcodec/pcm_tablegen.h b/ffmpeg/libavcodec/pcm_tablegen.h new file mode 100644 index 0000000..1387210 --- /dev/null +++ b/ffmpeg/libavcodec/pcm_tablegen.h @@ -0,0 +1,119 @@ +/* + * Header file for hardcoded PCM tables + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_PCM_TABLEGEN_H +#define AVCODEC_PCM_TABLEGEN_H + +#include +#include "libavutil/attributes.h" + +/* from g711.c by SUN microsystems (unrestricted use) */ + +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +#define BIAS (0x84) /* Bias for linear code. */ + +/* + * alaw2linear() - Convert an A-law value to 16-bit linear PCM + * + */ +static av_cold int alaw2linear(unsigned char a_val) +{ + int t; + int seg; + + a_val ^= 0x55; + + t = a_val & QUANT_MASK; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + if(seg) t= (t + t + 1 + 32) << (seg + 2); + else t= (t + t + 1 ) << 3; + + return (a_val & SIGN_BIT) ? t : -t; +} + +static av_cold int ulaw2linear(unsigned char u_val) +{ + int t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return (u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS); +} + +#if CONFIG_HARDCODED_TABLES +#define pcm_alaw_tableinit() +#define pcm_ulaw_tableinit() +#include "libavcodec/pcm_tables.h" +#else +/* 16384 entries per table */ +static uint8_t linear_to_alaw[16384]; +static uint8_t linear_to_ulaw[16384]; + +static av_cold void build_xlaw_table(uint8_t *linear_to_xlaw, + int (*xlaw2linear)(unsigned char), + int mask) +{ + int i, j, v, v1, v2; + + j = 0; + for(i=0;i<128;i++) { + if (i != 127) { + v1 = xlaw2linear(i ^ mask); + v2 = xlaw2linear((i + 1) ^ mask); + v = (v1 + v2 + 4) >> 3; + } else { + v = 8192; + } + for(;j 0) + linear_to_xlaw[8192 - j] = (i ^ (mask ^ 0x80)); + } + } + linear_to_xlaw[0] = linear_to_xlaw[1]; +} + +static void pcm_alaw_tableinit(void) +{ + build_xlaw_table(linear_to_alaw, alaw2linear, 0xd5); +} + +static void pcm_ulaw_tableinit(void) +{ + build_xlaw_table(linear_to_ulaw, ulaw2linear, 0xff); +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_PCM_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/pcx.c b/ffmpeg/libavcodec/pcx.c new file mode 100644 index 0000000..ba92332 --- /dev/null +++ b/ffmpeg/libavcodec/pcx.c @@ -0,0 +1,234 @@ +/* + * PC Paintbrush PCX (.pcx) image decoder + * Copyright (c) 2007, 2008 Ivo van Poorten + * + * This decoder does not support CGA palettes. I am unable to find samples + * and Netpbm cannot generate them. + * + * 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 "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" + +static void pcx_rle_decode(GetByteContext *gb, uint8_t *dst, + unsigned int bytes_per_scanline, int compressed) +{ + unsigned int i = 0; + unsigned char run, value; + + if (compressed) { + while (i= 0xc0) { + run = value & 0x3f; + value = bytestream2_get_byte(gb); + } + while (isize < 128) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + + if (bytestream2_get_byteu(&gb) != 0x0a || bytestream2_get_byteu(&gb) > 5) { + av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n"); + return AVERROR_INVALIDDATA; + } + + compressed = bytestream2_get_byteu(&gb); + bits_per_pixel = bytestream2_get_byteu(&gb); + xmin = bytestream2_get_le16u(&gb); + ymin = bytestream2_get_le16u(&gb); + xmax = bytestream2_get_le16u(&gb); + ymax = bytestream2_get_le16u(&gb); + avctx->sample_aspect_ratio.num = bytestream2_get_le16u(&gb); + avctx->sample_aspect_ratio.den = bytestream2_get_le16u(&gb); + + if (xmax < xmin || ymax < ymin) { + av_log(avctx, AV_LOG_ERROR, "invalid image dimensions\n"); + return AVERROR_INVALIDDATA; + } + + w = xmax - xmin + 1; + h = ymax - ymin + 1; + + bytestream2_skipu(&gb, 49); + nplanes = bytestream2_get_byteu(&gb); + bytes_per_line = bytestream2_get_le16u(&gb); + bytes_per_scanline = nplanes * bytes_per_line; + + if (bytes_per_scanline < (w * bits_per_pixel * nplanes + 7) / 8) { + av_log(avctx, AV_LOG_ERROR, "PCX data is corrupted\n"); + return AVERROR_INVALIDDATA; + } + + switch ((nplanes<<8) + bits_per_pixel) { + case 0x0308: + avctx->pix_fmt = AV_PIX_FMT_RGB24; + break; + case 0x0108: + case 0x0104: + case 0x0102: + case 0x0101: + case 0x0401: + case 0x0301: + case 0x0201: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid PCX file\n"); + return AVERROR_INVALIDDATA; + } + + bytestream2_skipu(&gb, 60); + + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) + return ret; + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + + ptr = p->data[0]; + stride = p->linesize[0]; + + scanline = av_malloc(bytes_per_scanline + FF_INPUT_BUFFER_PADDING_SIZE); + if (!scanline) + return AVERROR(ENOMEM); + + if (nplanes == 3 && bits_per_pixel == 8) { + for (y=0; ysize - 769; + + for (y=0; y> (x&7), v = 0; + for (i=nplanes - 1; i>=0; i--) { + v <<= 1; + v += !!(scanline[i*bytes_per_line + (x>>3)] & m); + } + ptr[x] = v; + } + ptr += stride; + } + } + + ret = bytestream2_tell(&gb); + if (nplanes == 1 && bits_per_pixel == 8) { + pcx_palette(&gb, (uint32_t *) p->data[1], 256); + ret += 256 * 3; + } else if (bits_per_pixel * nplanes == 1) { + AV_WN32A(p->data[1] , 0xFF000000); + AV_WN32A(p->data[1]+4, 0xFFFFFFFF); + } else if (bits_per_pixel < 8) { + bytestream2_seek(&gb, 16, SEEK_SET); + pcx_palette(&gb, (uint32_t *) p->data[1], 16); + } + + *got_frame = 1; + +end: + av_free(scanline); + return ret; +} + +AVCodec ff_pcx_decoder = { + .name = "pcx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PCX, + .decode = pcx_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), +}; diff --git a/ffmpeg/libavcodec/pcxenc.c b/ffmpeg/libavcodec/pcxenc.c new file mode 100644 index 0000000..7cb3af3 --- /dev/null +++ b/ffmpeg/libavcodec/pcxenc.c @@ -0,0 +1,230 @@ +/* + * PC Paintbrush PCX (.pcx) image encoder + * Copyright (c) 2009 Daniel Verkamp + * + * 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 + */ + +/** + * @file + * PCX image encoder + * @author Daniel Verkamp + * @see http://www.qzx.com/pc-gpe/pcx.txt + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "libavutil/imgutils.h" +#include "internal.h" + +typedef struct PCXContext { + AVFrame picture; +} PCXContext; + +static const uint32_t monoblack_pal[16] = { 0x000000, 0xFFFFFF }; + +static av_cold int pcx_encode_init(AVCodecContext *avctx) +{ + PCXContext *s = avctx->priv_data; + + avcodec_get_frame_defaults(&s->picture); + avctx->coded_frame = &s->picture; + + return 0; +} + +/** + * PCX run-length encoder + * @param dst output buffer + * @param dst_size size of output buffer + * @param src input buffer + * @param src_plane_size size of one plane of input buffer in bytes + * @param nplanes number of planes in input buffer + * @return number of bytes written to dst or -1 on error + * @bug will not work for nplanes != 1 && bpp != 8 + */ +static int pcx_rle_encode( uint8_t *dst, int dst_size, + const uint8_t *src, int src_plane_size, int nplanes) +{ + int p; + const uint8_t *dst_start = dst; + + // check worst-case upper bound on dst_size + if (dst_size < 2LL * src_plane_size * nplanes || src_plane_size <= 0) + return -1; + + for (p = 0; p < nplanes; p++) { + int count = 1; + const uint8_t *src_plane = src + p; + const uint8_t *src_plane_end = src_plane + src_plane_size * nplanes; + uint8_t prev = *src_plane; + src_plane += nplanes; + + for (; ; src_plane += nplanes) { + if (src_plane < src_plane_end && *src_plane == prev && count < 0x3F) { + // current byte is same as prev + ++count; + } else { + // output prev * count + if (count != 1 || prev >= 0xC0) + *dst++ = 0xC0 | count; + *dst++ = prev; + + if (src_plane == src_plane_end) + break; + + // start new run + count = 1; + prev = *src_plane; + } + } + } + + return dst - dst_start; +} + +static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + PCXContext *s = avctx->priv_data; + AVFrame *const pict = &s->picture; + const uint8_t *buf_end; + uint8_t *buf; + + int bpp, nplanes, i, y, line_bytes, written, ret, max_pkt_size, sw, sh; + const uint32_t *pal = NULL; + uint32_t palette256[256]; + const uint8_t *src; + + *pict = *frame; + pict->pict_type = AV_PICTURE_TYPE_I; + pict->key_frame = 1; + + if (avctx->width > 65535 || avctx->height > 65535) { + av_log(avctx, AV_LOG_ERROR, "image dimensions do not fit in 16 bits\n"); + return -1; + } + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGB24: + bpp = 8; + nplanes = 3; + break; + case AV_PIX_FMT_RGB8: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_GRAY8: + bpp = 8; + nplanes = 1; + avpriv_set_systematic_pal2(palette256, avctx->pix_fmt); + pal = palette256; + break; + case AV_PIX_FMT_PAL8: + bpp = 8; + nplanes = 1; + pal = (uint32_t *)pict->data[1]; + break; + case AV_PIX_FMT_MONOBLACK: + bpp = 1; + nplanes = 1; + pal = monoblack_pal; + break; + default: + av_log(avctx, AV_LOG_ERROR, "unsupported pixfmt\n"); + return -1; + } + + line_bytes = (avctx->width * bpp + 7) >> 3; + line_bytes = (line_bytes + 1) & ~1; + + max_pkt_size = 128 + avctx->height * 2 * line_bytes * nplanes + (pal ? 256*3 + 1 : 0); + if ((ret = ff_alloc_packet2(avctx, pkt, max_pkt_size)) < 0) + return ret; + buf = pkt->data; + buf_end = pkt->data + pkt->size; + + sw = avctx->sample_aspect_ratio.num; + sh = avctx->sample_aspect_ratio.den; + if (sw > 0xFFFFu || sh > 0xFFFFu) + av_reduce(&sw, &sh, sw, sh, 0xFFFFu); + + bytestream_put_byte(&buf, 10); // manufacturer + bytestream_put_byte(&buf, 5); // version + bytestream_put_byte(&buf, 1); // encoding + bytestream_put_byte(&buf, bpp); // bits per pixel per plane + bytestream_put_le16(&buf, 0); // x min + bytestream_put_le16(&buf, 0); // y min + bytestream_put_le16(&buf, avctx->width - 1); // x max + bytestream_put_le16(&buf, avctx->height - 1); // y max + bytestream_put_le16(&buf, sw); // horizontal DPI + bytestream_put_le16(&buf, sh); // vertical DPI + for (i = 0; i < 16; i++) + bytestream_put_be24(&buf, pal ? pal[i] : 0);// palette (<= 16 color only) + bytestream_put_byte(&buf, 0); // reserved + bytestream_put_byte(&buf, nplanes); // number of planes + bytestream_put_le16(&buf, line_bytes); // scanline plane size in bytes + + while (buf - pkt->data < 128) + *buf++= 0; + + src = pict->data[0]; + + for (y = 0; y < avctx->height; y++) { + if ((written = pcx_rle_encode(buf, buf_end - buf, + src, line_bytes, nplanes)) < 0) { + av_log(avctx, AV_LOG_ERROR, "buffer too small\n"); + return -1; + } + buf += written; + src += pict->linesize[0]; + } + + if (nplanes == 1 && bpp == 8) { + if (buf_end - buf < 257) { + av_log(avctx, AV_LOG_ERROR, "buffer too small\n"); + return -1; + } + bytestream_put_byte(&buf, 12); + for (i = 0; i < 256; i++) { + bytestream_put_be24(&buf, pal[i]); + } + } + + pkt->size = buf - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +AVCodec ff_pcx_encoder = { + .name = "pcx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PCX, + .priv_data_size = sizeof(PCXContext), + .init = pcx_encode_init, + .encode2 = pcx_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, + AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, + AV_PIX_FMT_MONOBLACK, + AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), +}; diff --git a/ffmpeg/libavcodec/pgssubdec.c b/ffmpeg/libavcodec/pgssubdec.c new file mode 100644 index 0000000..d0cff7b --- /dev/null +++ b/ffmpeg/libavcodec/pgssubdec.c @@ -0,0 +1,549 @@ +/* + * PGS subtitle decoder + * Copyright (c) 2009 Stephen Backway + * + * 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 + */ + +/** + * @file + * PGS subtitle decoder + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "bytestream.h" +#include "libavutil/colorspace.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +enum SegmentType { + PALETTE_SEGMENT = 0x14, + PICTURE_SEGMENT = 0x15, + PRESENTATION_SEGMENT = 0x16, + WINDOW_SEGMENT = 0x17, + DISPLAY_SEGMENT = 0x80, +}; + +typedef struct PGSSubPictureReference { + int x; + int y; + int picture_id; + int composition; +} PGSSubPictureReference; + +typedef struct PGSSubPresentation { + int id_number; + int object_count; + PGSSubPictureReference *objects; + int64_t pts; +} PGSSubPresentation; + +typedef struct PGSSubPicture { + int w; + int h; + uint8_t *rle; + unsigned int rle_buffer_size, rle_data_len; + unsigned int rle_remaining_len; +} PGSSubPicture; + +typedef struct PGSSubContext { + AVClass *class; + PGSSubPresentation presentation; + uint32_t clut[256]; + PGSSubPicture pictures[UINT16_MAX]; + int forced_subs_only; +} PGSSubContext; + +static av_cold int init_decoder(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + return 0; +} + +static av_cold int close_decoder(AVCodecContext *avctx) +{ + uint16_t picture; + + PGSSubContext *ctx = avctx->priv_data; + + av_freep(&ctx->presentation.objects); + ctx->presentation.object_count = 0; + + for (picture = 0; picture < UINT16_MAX; ++picture) { + av_freep(&ctx->pictures[picture].rle); + ctx->pictures[picture].rle_buffer_size = 0; + } + + return 0; +} + +/** + * Decode the RLE data. + * + * The subtitle is stored as an Run Length Encoded image. + * + * @param avctx contains the current codec context + * @param sub pointer to the processed subtitle data + * @param buf pointer to the RLE data to process + * @param buf_size size of the RLE data to process + */ +static int decode_rle(AVCodecContext *avctx, AVSubtitle *sub, int rect, + const uint8_t *buf, unsigned int buf_size) +{ + const uint8_t *rle_bitmap_end; + int pixel_count, line_count; + + rle_bitmap_end = buf + buf_size; + + sub->rects[rect]->pict.data[0] = av_malloc(sub->rects[rect]->w * sub->rects[rect]->h); + + if (!sub->rects[rect]->pict.data[0]) + return -1; + + pixel_count = 0; + line_count = 0; + + while (buf < rle_bitmap_end && line_count < sub->rects[rect]->h) { + uint8_t flags, color; + int run; + + color = bytestream_get_byte(&buf); + run = 1; + + if (color == 0x00) { + flags = bytestream_get_byte(&buf); + run = flags & 0x3f; + if (flags & 0x40) + run = (run << 8) + bytestream_get_byte(&buf); + color = flags & 0x80 ? bytestream_get_byte(&buf) : 0; + } + + if (run > 0 && pixel_count + run <= sub->rects[rect]->w * sub->rects[rect]->h) { + memset(sub->rects[rect]->pict.data[0] + pixel_count, color, run); + pixel_count += run; + } else if (!run) { + /* + * New Line. Check if correct pixels decoded, if not display warning + * and adjust bitmap pointer to correct new line position. + */ + if (pixel_count % sub->rects[rect]->w > 0) + av_log(avctx, AV_LOG_ERROR, "Decoded %d pixels, when line should be %d pixels\n", + pixel_count % sub->rects[rect]->w, sub->rects[rect]->w); + line_count++; + } + } + + if (pixel_count < sub->rects[rect]->w * sub->rects[rect]->h) { + av_log(avctx, AV_LOG_ERROR, "Insufficient RLE data for subtitle\n"); + return -1; + } + + av_dlog(avctx, "Pixel Count = %d, Area = %d\n", pixel_count, sub->rects[rect]->w * sub->rects[rect]->h); + + return 0; +} + +/** + * Parse the picture segment packet. + * + * The picture segment contains details on the sequence id, + * width, height and Run Length Encoded (RLE) bitmap data. + * + * @param avctx contains the current codec context + * @param buf pointer to the packet to process + * @param buf_size size of packet to process + * @todo TODO: Enable support for RLE data over multiple packets + */ +static int parse_picture_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + PGSSubContext *ctx = avctx->priv_data; + + uint8_t sequence_desc; + unsigned int rle_bitmap_len, width, height; + uint16_t picture_id; + + if (buf_size <= 4) + return -1; + buf_size -= 4; + + picture_id = bytestream_get_be16(&buf); + + /* skip 1 unknown byte: Version Number */ + buf++; + + /* Read the Sequence Description to determine if start of RLE data or appended to previous RLE */ + sequence_desc = bytestream_get_byte(&buf); + + if (!(sequence_desc & 0x80)) { + /* Additional RLE data */ + if (buf_size > ctx->pictures[picture_id].rle_remaining_len) + return -1; + + memcpy(ctx->pictures[picture_id].rle + ctx->pictures[picture_id].rle_data_len, buf, buf_size); + ctx->pictures[picture_id].rle_data_len += buf_size; + ctx->pictures[picture_id].rle_remaining_len -= buf_size; + + return 0; + } + + if (buf_size <= 7) + return -1; + buf_size -= 7; + + /* Decode rle bitmap length, stored size includes width/height data */ + rle_bitmap_len = bytestream_get_be24(&buf) - 2*2; + + /* Get bitmap dimensions from data */ + width = bytestream_get_be16(&buf); + height = bytestream_get_be16(&buf); + + /* Make sure the bitmap is not too large */ + if (avctx->width < width || avctx->height < height) { + av_log(avctx, AV_LOG_ERROR, "Bitmap dimensions larger than video.\n"); + return -1; + } + + if (buf_size > rle_bitmap_len) { + av_log(avctx, AV_LOG_ERROR, "too much RLE data\n"); + return AVERROR_INVALIDDATA; + } + + ctx->pictures[picture_id].w = width; + ctx->pictures[picture_id].h = height; + + av_fast_malloc(&ctx->pictures[picture_id].rle, &ctx->pictures[picture_id].rle_buffer_size, rle_bitmap_len); + + if (!ctx->pictures[picture_id].rle) + return -1; + + memcpy(ctx->pictures[picture_id].rle, buf, buf_size); + ctx->pictures[picture_id].rle_data_len = buf_size; + ctx->pictures[picture_id].rle_remaining_len = rle_bitmap_len - buf_size; + + return 0; +} + +/** + * Parse the palette segment packet. + * + * The palette segment contains details of the palette, + * a maximum of 256 colors can be defined. + * + * @param avctx contains the current codec context + * @param buf pointer to the packet to process + * @param buf_size size of packet to process + */ +static void parse_palette_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + PGSSubContext *ctx = avctx->priv_data; + + const uint8_t *buf_end = buf + buf_size; + const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int color_id; + int y, cb, cr, alpha; + int r, g, b, r_add, g_add, b_add; + + /* Skip two null bytes */ + buf += 2; + + while (buf < buf_end) { + color_id = bytestream_get_byte(&buf); + y = bytestream_get_byte(&buf); + cr = bytestream_get_byte(&buf); + cb = bytestream_get_byte(&buf); + alpha = bytestream_get_byte(&buf); + + YUV_TO_RGB1(cb, cr); + YUV_TO_RGB2(r, g, b, y); + + av_dlog(avctx, "Color %d := (%d,%d,%d,%d)\n", color_id, r, g, b, alpha); + + /* Store color in palette */ + ctx->clut[color_id] = RGBA(r,g,b,alpha); + } +} + +/** + * Parse the presentation segment packet. + * + * The presentation segment contains details on the video + * width, video height, x & y subtitle position. + * + * @param avctx contains the current codec context + * @param buf pointer to the packet to process + * @param buf_size size of packet to process + * @todo TODO: Implement cropping + */ +static void parse_presentation_segment(AVCodecContext *avctx, + const uint8_t *buf, int buf_size, + int64_t pts) +{ + PGSSubContext *ctx = avctx->priv_data; + + int w = bytestream_get_be16(&buf); + int h = bytestream_get_be16(&buf); + + uint16_t object_index; + + ctx->presentation.pts = pts; + + av_dlog(avctx, "Video Dimensions %dx%d\n", + w, h); + if (av_image_check_size(w, h, 0, avctx) >= 0) + avcodec_set_dimensions(avctx, w, h); + + /* Skip 1 bytes of unknown, frame rate? */ + buf++; + + ctx->presentation.id_number = bytestream_get_be16(&buf); + + /* + * Skip 3 bytes of unknown: + * state + * palette_update_flag (0x80), + * palette_id_to_use, + */ + buf += 3; + + ctx->presentation.object_count = bytestream_get_byte(&buf); + if (!ctx->presentation.object_count) + return; + + /* Verify that enough bytes are remaining for all of the objects. */ + buf_size -= 11; + if (buf_size < ctx->presentation.object_count * 8) { + ctx->presentation.object_count = 0; + return; + } + + av_freep(&ctx->presentation.objects); + ctx->presentation.objects = av_malloc(sizeof(PGSSubPictureReference) * ctx->presentation.object_count); + if (!ctx->presentation.objects) { + ctx->presentation.object_count = 0; + return; + } + + for (object_index = 0; object_index < ctx->presentation.object_count; ++object_index) { + PGSSubPictureReference *reference = &ctx->presentation.objects[object_index]; + reference->picture_id = bytestream_get_be16(&buf); + + /* Skip window_id_ref */ + buf++; + /* composition_flag (0x80 - object cropped, 0x40 - object forced) */ + reference->composition = bytestream_get_byte(&buf); + + reference->x = bytestream_get_be16(&buf); + reference->y = bytestream_get_be16(&buf); + + /* TODO If cropping, cropping_x, cropping_y, cropping_width, cropping_height (all 2 bytes).*/ + av_dlog(avctx, "Subtitle Placement ID=%d, x=%d, y=%d\n", reference->picture_id, reference->x, reference->y); + + if (reference->x > avctx->width || reference->y > avctx->height) { + av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", + reference->x, reference->y, avctx->width, avctx->height); + reference->x = 0; + reference->y = 0; + } + } +} + +/** + * Parse the display segment packet. + * + * The display segment controls the updating of the display. + * + * @param avctx contains the current codec context + * @param data pointer to the data pertaining the subtitle to display + * @param buf pointer to the packet to process + * @param buf_size size of packet to process + * @todo TODO: Fix start time, relies on correct PTS, currently too late + * + * @todo TODO: Fix end time, normally cleared by a second display + * @todo segment, which is currently ignored as it clears + * @todo the subtitle too early. + */ +static int display_end_segment(AVCodecContext *avctx, void *data, + const uint8_t *buf, int buf_size) +{ + AVSubtitle *sub = data; + PGSSubContext *ctx = avctx->priv_data; + int64_t pts; + + uint16_t rect; + + /* + * The end display time is a timeout value and is only reached + * if the next subtitle is later than timeout or subtitle has + * not been cleared by a subsequent empty display command. + */ + + pts = ctx->presentation.pts != AV_NOPTS_VALUE ? ctx->presentation.pts : sub->pts; + memset(sub, 0, sizeof(*sub)); + sub->pts = pts; + ctx->presentation.pts = AV_NOPTS_VALUE; + + // Blank if last object_count was 0. + if (!ctx->presentation.object_count) + return 1; + + sub->start_display_time = 0; + sub->end_display_time = 20000; + sub->format = 0; + + sub->num_rects = ctx->presentation.object_count; + sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects); + + for (rect = 0; rect < sub->num_rects; ++rect) { + uint16_t picture_id = ctx->presentation.objects[rect].picture_id; + sub->rects[rect] = av_mallocz(sizeof(*sub->rects[rect])); + sub->rects[rect]->x = ctx->presentation.objects[rect].x; + sub->rects[rect]->y = ctx->presentation.objects[rect].y; + sub->rects[rect]->w = ctx->pictures[picture_id].w; + sub->rects[rect]->h = ctx->pictures[picture_id].h; + sub->rects[rect]->type = SUBTITLE_BITMAP; + + /* Process bitmap */ + sub->rects[rect]->pict.linesize[0] = ctx->pictures[picture_id].w; + if (ctx->pictures[picture_id].rle) { + if (ctx->pictures[picture_id].rle_remaining_len) + av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", + ctx->pictures[picture_id].rle_data_len, ctx->pictures[picture_id].rle_remaining_len); + if (decode_rle(avctx, sub, rect, ctx->pictures[picture_id].rle, ctx->pictures[picture_id].rle_data_len) < 0) + return 0; + } + + /* Allocate memory for colors */ + sub->rects[rect]->nb_colors = 256; + sub->rects[rect]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + + /* Copy the forced flag */ + sub->rects[rect]->flags = (ctx->presentation.objects[rect].composition & 0x40) != 0 ? AV_SUBTITLE_FLAG_FORCED : 0; + + if (!ctx->forced_subs_only || ctx->presentation.objects[rect].composition & 0x40) + memcpy(sub->rects[rect]->pict.data[1], ctx->clut, sub->rects[rect]->nb_colors * sizeof(uint32_t)); + } + + return 1; +} + +static int decode(AVCodecContext *avctx, void *data, int *data_size, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVSubtitle *sub = data; + + const uint8_t *buf_end; + uint8_t segment_type; + int segment_length; + int i; + + av_dlog(avctx, "PGS sub packet:\n"); + + for (i = 0; i < buf_size; i++) { + av_dlog(avctx, "%02x ", buf[i]); + if (i % 16 == 15) + av_dlog(avctx, "\n"); + } + + if (i & 15) + av_dlog(avctx, "\n"); + + *data_size = 0; + + /* Ensure that we have received at a least a segment code and segment length */ + if (buf_size < 3) + return -1; + + buf_end = buf + buf_size; + + /* Step through buffer to identify segments */ + while (buf < buf_end) { + segment_type = bytestream_get_byte(&buf); + segment_length = bytestream_get_be16(&buf); + + av_dlog(avctx, "Segment Length %d, Segment Type %x\n", segment_length, segment_type); + + if (segment_type != DISPLAY_SEGMENT && segment_length > buf_end - buf) + break; + + switch (segment_type) { + case PALETTE_SEGMENT: + parse_palette_segment(avctx, buf, segment_length); + break; + case PICTURE_SEGMENT: + parse_picture_segment(avctx, buf, segment_length); + break; + case PRESENTATION_SEGMENT: + parse_presentation_segment(avctx, buf, segment_length, sub->pts); + break; + case WINDOW_SEGMENT: + /* + * Window Segment Structure (No new information provided): + * 2 bytes: Unknown, + * 2 bytes: X position of subtitle, + * 2 bytes: Y position of subtitle, + * 2 bytes: Width of subtitle, + * 2 bytes: Height of subtitle. + */ + break; + case DISPLAY_SEGMENT: + *data_size = display_end_segment(avctx, data, buf, segment_length); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown subtitle segment type 0x%x, length %d\n", + segment_type, segment_length); + break; + } + + buf += segment_length; + } + + return buf_size; +} + +#define OFFSET(x) offsetof(PGSSubContext, x) +#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + {"forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD}, + { NULL }, +}; + +static const AVClass pgsdec_class = { + .class_name = "PGS subtitle decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_pgssub_decoder = { + .name = "pgssub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_HDMV_PGS_SUBTITLE, + .priv_data_size = sizeof(PGSSubContext), + .init = init_decoder, + .close = close_decoder, + .decode = decode, + .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), + .priv_class = &pgsdec_class, +}; diff --git a/ffmpeg/libavcodec/pictordec.c b/ffmpeg/libavcodec/pictordec.c new file mode 100644 index 0000000..bf138b2 --- /dev/null +++ b/ffmpeg/libavcodec/pictordec.c @@ -0,0 +1,262 @@ +/* + * Pictor/PC Paint decoder + * Copyright (c) 2010 Peter Ross + * + * 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 + */ + +/** + * @file + * Pictor/PC Paint decoder + */ + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "cga_data.h" +#include "internal.h" + +typedef struct PicContext { + int width, height; + int nb_planes; + GetByteContext g; +} PicContext; + +static void picmemset_8bpp(PicContext *s, AVFrame *frame, int value, int run, + int *x, int *y) +{ + while (run > 0) { + uint8_t *d = frame->data[0] + *y * frame->linesize[0]; + if (*x + run >= s->width) { + int n = s->width - *x; + memset(d + *x, value, n); + run -= n; + *x = 0; + *y -= 1; + if (*y < 0) + break; + } else { + memset(d + *x, value, run); + *x += run; + break; + } + } +} + +static void picmemset(PicContext *s, AVFrame *frame, int value, int run, + int *x, int *y, int *plane, int bits_per_plane) +{ + uint8_t *d; + int shift = *plane * bits_per_plane; + int mask = ((1 << bits_per_plane) - 1) << shift; + value <<= shift; + + while (run > 0) { + int j; + for (j = 8-bits_per_plane; j >= 0; j -= bits_per_plane) { + d = frame->data[0] + *y * frame->linesize[0]; + d[*x] |= (value >> j) & mask; + *x += 1; + if (*x == s->width) { + *y -= 1; + *x = 0; + if (*y < 0) { + *y = s->height - 1; + *plane += 1; + value <<= bits_per_plane; + mask <<= bits_per_plane; + if (*plane >= s->nb_planes) + break; + } + } + } + run--; + } +} + +static const uint8_t cga_mode45_index[6][4] = { + [0] = { 0, 3, 5, 7 }, // mode4, palette#1, low intensity + [1] = { 0, 2, 4, 6 }, // mode4, palette#2, low intensity + [2] = { 0, 3, 4, 7 }, // mode5, low intensity + [3] = { 0, 11, 13, 15 }, // mode4, palette#1, high intensity + [4] = { 0, 10, 12, 14 }, // mode4, palette#2, high intensity + [5] = { 0, 11, 12, 15 }, // mode5, high intensity +}; + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + PicContext *s = avctx->priv_data; + AVFrame *frame = data; + uint32_t *palette; + int bits_per_plane, bpp, etype, esize, npal, pos_after_pal; + int i, x, y, plane, tmp, ret, val; + + bytestream2_init(&s->g, avpkt->data, avpkt->size); + + if (bytestream2_get_bytes_left(&s->g) < 11) + return AVERROR_INVALIDDATA; + + if (bytestream2_get_le16u(&s->g) != 0x1234) + return AVERROR_INVALIDDATA; + + s->width = bytestream2_get_le16u(&s->g); + s->height = bytestream2_get_le16u(&s->g); + bytestream2_skip(&s->g, 4); + tmp = bytestream2_get_byteu(&s->g); + bits_per_plane = tmp & 0xF; + s->nb_planes = (tmp >> 4) + 1; + bpp = bits_per_plane * s->nb_planes; + if (bits_per_plane > 8 || bpp < 1 || bpp > 32) { + avpriv_request_sample(avctx, "Unsupported bit depth"); + return AVERROR_PATCHWELCOME; + } + + if (bytestream2_peek_byte(&s->g) == 0xFF || bpp == 1 || bpp == 4 || bpp == 8) { + bytestream2_skip(&s->g, 2); + etype = bytestream2_get_le16(&s->g); + esize = bytestream2_get_le16(&s->g); + if (bytestream2_get_bytes_left(&s->g) < esize) + return AVERROR_INVALIDDATA; + } else { + etype = -1; + esize = 0; + } + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + if (s->width != avctx->width && s->height != avctx->height) { + if (av_image_check_size(s->width, s->height, 0, avctx) < 0) + return -1; + avcodec_set_dimensions(avctx, s->width, s->height); + } + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + memset(frame->data[0], 0, s->height * frame->linesize[0]); + frame->pict_type = AV_PICTURE_TYPE_I; + frame->palette_has_changed = 1; + + pos_after_pal = bytestream2_tell(&s->g) + esize; + palette = (uint32_t*)frame->data[1]; + if (etype == 1 && esize > 1 && bytestream2_peek_byte(&s->g) < 6) { + int idx = bytestream2_get_byte(&s->g); + npal = 4; + for (i = 0; i < npal; i++) + palette[i] = ff_cga_palette[ cga_mode45_index[idx][i] ]; + } else if (etype == 2) { + npal = FFMIN(esize, 16); + for (i = 0; i < npal; i++) { + int pal_idx = bytestream2_get_byte(&s->g); + palette[i] = ff_cga_palette[FFMIN(pal_idx, 15)]; + } + } else if (etype == 3) { + npal = FFMIN(esize, 16); + for (i = 0; i < npal; i++) { + int pal_idx = bytestream2_get_byte(&s->g); + palette[i] = ff_ega_palette[FFMIN(pal_idx, 63)]; + } + } else if (etype == 4 || etype == 5) { + npal = FFMIN(esize / 3, 256); + for (i = 0; i < npal; i++) { + palette[i] = bytestream2_get_be24(&s->g) << 2; + palette[i] |= 0xFFU << 24 | palette[i] >> 6 & 0x30303; + } + } else { + if (bpp == 1) { + npal = 2; + palette[0] = 0xFF000000; + palette[1] = 0xFFFFFFFF; + } else if (bpp == 2) { + npal = 4; + for (i = 0; i < npal; i++) + palette[i] = ff_cga_palette[ cga_mode45_index[0][i] ]; + } else { + npal = 16; + memcpy(palette, ff_cga_palette, npal * 4); + } + } + // fill remaining palette entries + memset(palette + npal, 0, AVPALETTE_SIZE - npal * 4); + // skip remaining palette bytes + bytestream2_seek(&s->g, pos_after_pal, SEEK_SET); + + val = 0; + y = s->height - 1; + if (bytestream2_get_le16(&s->g)) { + x = 0; + plane = 0; + while (y >= 0 && bytestream2_get_bytes_left(&s->g) >= 6) { + int stop_size, marker, t1, t2; + + t1 = bytestream2_get_bytes_left(&s->g); + t2 = bytestream2_get_le16(&s->g); + stop_size = t1 - FFMIN(t1, t2); + // ignore uncompressed block size + bytestream2_skip(&s->g, 2); + marker = bytestream2_get_byte(&s->g); + + while (plane < s->nb_planes && y >= 0 && + bytestream2_get_bytes_left(&s->g) > stop_size) { + int run = 1; + val = bytestream2_get_byte(&s->g); + if (val == marker) { + run = bytestream2_get_byte(&s->g); + if (run == 0) + run = bytestream2_get_le16(&s->g); + val = bytestream2_get_byte(&s->g); + } + if (!bytestream2_get_bytes_left(&s->g)) + break; + + if (bits_per_plane == 8) { + picmemset_8bpp(s, frame, val, run, &x, &y); + } else { + picmemset(s, frame, val, run, &x, &y, &plane, bits_per_plane); + } + } + } + + if (x < avctx->width && y >= 0) { + int run = (y + 1) * avctx->width - x; + if (bits_per_plane == 8) + picmemset_8bpp(s, frame, val, run, &x, &y); + else + picmemset(s, frame, val, run / (8 / bits_per_plane), &x, &y, &plane, bits_per_plane); + } + } else { + while (y >= 0 && bytestream2_get_bytes_left(&s->g) > 0) { + memcpy(frame->data[0] + y * frame->linesize[0], s->g.buffer, FFMIN(avctx->width, bytestream2_get_bytes_left(&s->g))); + bytestream2_skip(&s->g, avctx->width); + y--; + } + } + + *got_frame = 1; + return avpkt->size; +} + +AVCodec ff_pictor_decoder = { + .name = "pictor", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PICTOR, + .priv_data_size = sizeof(PicContext), + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"), +}; diff --git a/ffmpeg/libavcodec/png.c b/ffmpeg/libavcodec/png.c new file mode 100644 index 0000000..b398d91 --- /dev/null +++ b/ffmpeg/libavcodec/png.c @@ -0,0 +1,72 @@ +/* + * PNG image format + * Copyright (c) 2003 Fabrice Bellard + * + * 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 "avcodec.h" +#include "png.h" + +/* Mask to determine which y pixels are valid in a pass */ +const uint8_t ff_png_pass_ymask[NB_PASSES] = { + 0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, +}; + +/* minimum x value */ +static const uint8_t ff_png_pass_xmin[NB_PASSES] = { + 0, 4, 0, 2, 0, 1, 0 +}; + +/* x shift to get row width */ +static const uint8_t ff_png_pass_xshift[NB_PASSES] = { + 3, 3, 2, 2, 1, 1, 0 +}; + +void *ff_png_zalloc(void *opaque, unsigned int items, unsigned int size) +{ + return av_mallocz_array(items, size); +} + +void ff_png_zfree(void *opaque, void *ptr) +{ + av_free(ptr); +} + +int ff_png_get_nb_channels(int color_type) +{ + int channels; + channels = 1; + if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) == + PNG_COLOR_MASK_COLOR) + channels = 3; + if (color_type & PNG_COLOR_MASK_ALPHA) + channels++; + return channels; +} + +/* compute the row size of an interleaved pass */ +int ff_png_pass_row_size(int pass, int bits_per_pixel, int width) +{ + int shift, xmin, pass_width; + + xmin = ff_png_pass_xmin[pass]; + if (width <= xmin) + return 0; + shift = ff_png_pass_xshift[pass]; + pass_width = (width - xmin + (1 << shift) - 1) >> shift; + return (pass_width * bits_per_pixel + 7) >> 3; +} diff --git a/ffmpeg/libavcodec/png.h b/ffmpeg/libavcodec/png.h new file mode 100644 index 0000000..948c2f7 --- /dev/null +++ b/ffmpeg/libavcodec/png.h @@ -0,0 +1,69 @@ +/* + * PNG image format + * Copyright (c) 2003 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_PNG_H +#define AVCODEC_PNG_H + +#include + +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) + +#define PNG_FILTER_TYPE_LOCO 64 +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_MIXED 5 + +#define PNG_IHDR 0x0001 +#define PNG_IDAT 0x0002 +#define PNG_ALLIMAGE 0x0004 +#define PNG_PLTE 0x0008 + +#define NB_PASSES 7 + +#define PNGSIG 0x89504e470d0a1a0a +#define MNGSIG 0x8a4d4e470d0a1a0a + +/* Mask to determine which y pixels are valid in a pass */ +extern const uint8_t ff_png_pass_ymask[NB_PASSES]; + +void *ff_png_zalloc(void *opaque, unsigned int items, unsigned int size); + +void ff_png_zfree(void *opaque, void *ptr); + +int ff_png_get_nb_channels(int color_type); + +/* compute the row size of an interleaved pass */ +int ff_png_pass_row_size(int pass, int bits_per_pixel, int width); + +void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp); + +#endif /* AVCODEC_PNG_H */ diff --git a/ffmpeg/libavcodec/png_parser.c b/ffmpeg/libavcodec/png_parser.c new file mode 100644 index 0000000..6f153d9 --- /dev/null +++ b/ffmpeg/libavcodec/png_parser.c @@ -0,0 +1,120 @@ +/* + * PNG parser + * Copyright (c) 2009 Peter Holik + * + * 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 + */ + +/** + * @file + * PNG parser + */ + +#include "parser.h" +#include "png.h" + +typedef struct PNGParseContext +{ + ParseContext pc; + uint32_t index; + uint32_t chunk_length; + uint32_t remaining_size; +} PNGParseContext; + +static int png_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + PNGParseContext *ppc = s->priv_data; + int next = END_NOT_FOUND; + int i = 0; + + s->pict_type = AV_PICTURE_TYPE_NONE; + + *poutbuf_size = 0; + if (buf_size == 0) + return 0; + + if (!ppc->pc.frame_start_found) { + uint64_t state64 = ppc->pc.state64; + for (; i < buf_size; i++) { + state64 = (state64 << 8) | buf[i]; + if (state64 == PNGSIG || state64 == MNGSIG) { + i++; + ppc->pc.frame_start_found = 1; + break; + } + } + ppc->pc.state64 = state64; + } else + if (ppc->remaining_size) { + i = FFMIN(ppc->remaining_size, buf_size); + ppc->remaining_size -= i; + if (ppc->remaining_size) + goto flush; + if (ppc->index == -1) { + next = i; + goto flush; + } + } + + for (;ppc->pc.frame_start_found && i < buf_size; i++) { + ppc->pc.state = (ppc->pc.state<<8) | buf[i]; + if (ppc->index == 3) { + ppc->chunk_length = ppc->pc.state; + if (ppc->chunk_length > 0x7fffffff) { + ppc->index = ppc->pc.frame_start_found = 0; + goto flush; + } + ppc->chunk_length += 4; + } else if (ppc->index == 7) { + if (ppc->chunk_length >= buf_size - i) + ppc->remaining_size = ppc->chunk_length - buf_size + i + 1; + if (ppc->pc.state == MKBETAG('I', 'E', 'N', 'D')) { + if (ppc->remaining_size) + ppc->index = -1; + else + next = ppc->chunk_length + i + 1; + break; + } else { + ppc->index = 0; + if (ppc->remaining_size) + break; + else + i += ppc->chunk_length; + continue; + } + } + ppc->index++; + } +flush: + if (ff_combine_frame(&ppc->pc, next, &buf, &buf_size) < 0) + return buf_size; + + ppc->index = ppc->pc.frame_start_found = 0; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_png_parser = { + .codec_ids = { AV_CODEC_ID_PNG }, + .priv_data_size = sizeof(PNGParseContext), + .parser_parse = png_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/pngdec.c b/ffmpeg/libavcodec/pngdec.c new file mode 100644 index 0000000..086f3b4 --- /dev/null +++ b/ffmpeg/libavcodec/pngdec.c @@ -0,0 +1,902 @@ +/* + * PNG image format + * Copyright (c) 2003 Fabrice Bellard + * + * 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 + */ + +//#define DEBUG + +#include "libavutil/bprint.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "png.h" +#include "pngdsp.h" + +/* TODO: + * - add 16 bit depth support + */ + +#include + +//#define DEBUG + +typedef struct PNGDecContext { + PNGDSPContext dsp; + AVCodecContext *avctx; + + GetByteContext gb; + AVFrame *prev; + + int state; + int width, height; + int bit_depth; + int color_type; + int compression_type; + int interlace_type; + int filter_type; + int channels; + int bits_per_pixel; + int bpp; + + uint8_t *image_buf; + int image_linesize; + uint32_t palette[256]; + uint8_t *crow_buf; + uint8_t *last_row; + uint8_t *tmp_row; + int pass; + int crow_size; /* compressed row size (include filter type) */ + int row_size; /* decompressed row size */ + int pass_row_size; /* decompress row size of the current pass */ + int y; + z_stream zstream; +} PNGDecContext; + +/* Mask to determine which pixels are valid in a pass */ +static const uint8_t png_pass_mask[NB_PASSES] = { + 0x01, 0x01, 0x11, 0x11, 0x55, 0x55, 0xff, +}; + +/* Mask to determine which y pixels can be written in a pass */ +static const uint8_t png_pass_dsp_ymask[NB_PASSES] = { + 0xff, 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, +}; + +/* Mask to determine which pixels to overwrite while displaying */ +static const uint8_t png_pass_dsp_mask[NB_PASSES] = { + 0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff +}; + +/* NOTE: we try to construct a good looking image at each pass. width + is the original image width. We also do pixel format conversion at + this stage */ +static void png_put_interlaced_row(uint8_t *dst, int width, + int bits_per_pixel, int pass, + int color_type, const uint8_t *src) +{ + int x, mask, dsp_mask, j, src_x, b, bpp; + uint8_t *d; + const uint8_t *s; + + mask = png_pass_mask[pass]; + dsp_mask = png_pass_dsp_mask[pass]; + + switch (bits_per_pixel) { + case 1: + src_x = 0; + for (x = 0; x < width; x++) { + j = (x & 7); + if ((dsp_mask << j) & 0x80) { + b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1; + dst[x >> 3] &= 0xFF7F>>j; + dst[x >> 3] |= b << (7 - j); + } + if ((mask << j) & 0x80) + src_x++; + } + break; + case 2: + src_x = 0; + for (x = 0; x < width; x++) { + int j2 = 2 * (x & 3); + j = (x & 7); + if ((dsp_mask << j) & 0x80) { + b = (src[src_x >> 2] >> (6 - 2*(src_x & 3))) & 3; + dst[x >> 2] &= 0xFF3F>>j2; + dst[x >> 2] |= b << (6 - j2); + } + if ((mask << j) & 0x80) + src_x++; + } + break; + case 4: + src_x = 0; + for (x = 0; x < width; x++) { + int j2 = 4*(x&1); + j = (x & 7); + if ((dsp_mask << j) & 0x80) { + b = (src[src_x >> 1] >> (4 - 4*(src_x & 1))) & 15; + dst[x >> 1] &= 0xFF0F>>j2; + dst[x >> 1] |= b << (4 - j2); + } + if ((mask << j) & 0x80) + src_x++; + } + break; + default: + bpp = bits_per_pixel >> 3; + d = dst; + s = src; + for (x = 0; x < width; x++) { + j = x & 7; + if ((dsp_mask << j) & 0x80) { + memcpy(d, s, bpp); + } + d += bpp; + if ((mask << j) & 0x80) + s += bpp; + } + break; + } +} + +void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp) +{ + int i; + for (i = 0; i < w; i++) { + int a, b, c, p, pa, pb, pc; + + a = dst[i - bpp]; + b = top[i]; + c = top[i - bpp]; + + p = b - c; + pc = a - c; + + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); + + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + dst[i] = p + src[i]; + } +} + +#define UNROLL1(bpp, op) {\ + r = dst[0];\ + if(bpp >= 2) g = dst[1];\ + if(bpp >= 3) b = dst[2];\ + if(bpp >= 4) a = dst[3];\ + for(; i <= size - bpp; i+=bpp) {\ + dst[i+0] = r = op(r, src[i+0], last[i+0]);\ + if(bpp == 1) continue;\ + dst[i+1] = g = op(g, src[i+1], last[i+1]);\ + if(bpp == 2) continue;\ + dst[i+2] = b = op(b, src[i+2], last[i+2]);\ + if(bpp == 3) continue;\ + dst[i+3] = a = op(a, src[i+3], last[i+3]);\ + }\ +} + +#define UNROLL_FILTER(op)\ + if(bpp == 1) UNROLL1(1, op)\ + else if(bpp == 2) UNROLL1(2, op)\ + else if(bpp == 3) UNROLL1(3, op)\ + else if(bpp == 4) UNROLL1(4, op)\ + for (; i < size; i++) {\ + dst[i] = op(dst[i-bpp], src[i], last[i]);\ + }\ + +/* NOTE: 'dst' can be equal to 'last' */ +static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type, + uint8_t *src, uint8_t *last, int size, int bpp) +{ + int i, p, r, g, b, a; + + switch (filter_type) { + case PNG_FILTER_VALUE_NONE: + memcpy(dst, src, size); + break; + case PNG_FILTER_VALUE_SUB: + for (i = 0; i < bpp; i++) { + dst[i] = src[i]; + } + if (bpp == 4) { + p = *(int*)dst; + for (; i < size; i += bpp) { + int s = *(int*)(src + i); + p = ((s & 0x7f7f7f7f) + (p & 0x7f7f7f7f)) ^ ((s ^ p) & 0x80808080); + *(int*)(dst + i) = p; + } + } else { +#define OP_SUB(x,s,l) x+s + UNROLL_FILTER(OP_SUB); + } + break; + case PNG_FILTER_VALUE_UP: + dsp->add_bytes_l2(dst, src, last, size); + break; + case PNG_FILTER_VALUE_AVG: + for (i = 0; i < bpp; i++) { + p = (last[i] >> 1); + dst[i] = p + src[i]; + } +#define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff + UNROLL_FILTER(OP_AVG); + break; + case PNG_FILTER_VALUE_PAETH: + for (i = 0; i < bpp; i++) { + p = last[i]; + dst[i] = p + src[i]; + } + if (bpp > 2 && size > 4) { + // would write off the end of the array if we let it process the last pixel with bpp=3 + int w = bpp == 4 ? size : size - 3; + dsp->add_paeth_prediction(dst + i, src + i, last + i, w - i, bpp); + i = w; + } + ff_add_png_paeth_prediction(dst + i, src + i, last + i, size - i, bpp); + break; + } +} + +/* This used to be called "deloco" in FFmpeg + * and is actually an inverse reversible colorspace transformation */ +#define YUV2RGB(NAME, TYPE) \ +static void deloco_ ## NAME(TYPE *dst, int size, int alpha) \ +{ \ + int i; \ + for (i = 0; i < size; i += 3 + alpha) { \ + int g = dst [i+1]; \ + dst[i+0] += g; \ + dst[i+2] += g; \ + } \ +} + +YUV2RGB(rgb8, uint8_t) +YUV2RGB(rgb16, uint16_t) + +/* process exactly one decompressed row */ +static void png_handle_row(PNGDecContext *s) +{ + uint8_t *ptr, *last_row; + int got_line; + + if (!s->interlace_type) { + ptr = s->image_buf + s->image_linesize * s->y; + if (s->y == 0) + last_row = s->last_row; + else + last_row = ptr - s->image_linesize; + + png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1, + last_row, s->row_size, s->bpp); + /* loco lags by 1 row so that it doesn't interfere with top prediction */ + if (s->filter_type == PNG_FILTER_TYPE_LOCO && s->y > 0) { + if (s->bit_depth == 16) { + deloco_rgb16((uint16_t *)(ptr - s->image_linesize), s->row_size / 2, + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA); + } else { + deloco_rgb8(ptr - s->image_linesize, s->row_size, + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA); + } + } + s->y++; + if (s->y == s->height) { + s->state |= PNG_ALLIMAGE; + if (s->filter_type == PNG_FILTER_TYPE_LOCO) { + if (s->bit_depth == 16) { + deloco_rgb16((uint16_t *)ptr, s->row_size / 2, + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA); + } else { + deloco_rgb8(ptr, s->row_size, + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA); + } + } + } + } else { + got_line = 0; + for (;;) { + ptr = s->image_buf + s->image_linesize * s->y; + if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) { + /* if we already read one row, it is time to stop to + wait for the next one */ + if (got_line) + break; + png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1, + s->last_row, s->pass_row_size, s->bpp); + FFSWAP(uint8_t*, s->last_row, s->tmp_row); + got_line = 1; + } + if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) { + png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass, + s->color_type, s->last_row); + } + s->y++; + if (s->y == s->height) { + memset(s->last_row, 0, s->row_size); + for (;;) { + if (s->pass == NB_PASSES - 1) { + s->state |= PNG_ALLIMAGE; + goto the_end; + } else { + s->pass++; + s->y = 0; + s->pass_row_size = ff_png_pass_row_size(s->pass, + s->bits_per_pixel, + s->width); + s->crow_size = s->pass_row_size + 1; + if (s->pass_row_size != 0) + break; + /* skip pass if empty row */ + } + } + } + } + the_end: ; + } +} + +static int png_decode_idat(PNGDecContext *s, int length) +{ + int ret; + s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb)); + s->zstream.next_in = (unsigned char *)s->gb.buffer; + bytestream2_skip(&s->gb, length); + + /* decode one line if possible */ + while (s->zstream.avail_in > 0) { + ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + av_log(s->avctx, AV_LOG_ERROR, "inflate returned %d\n", ret); + return -1; + } + if (s->zstream.avail_out == 0) { + if (!(s->state & PNG_ALLIMAGE)) { + png_handle_row(s); + } + s->zstream.avail_out = s->crow_size; + s->zstream.next_out = s->crow_buf; + } + } + return 0; +} + +static int decode_zbuf(AVBPrint *bp, const uint8_t *data, + const uint8_t *data_end) +{ + z_stream zstream; + unsigned char *buf; + unsigned buf_size; + int ret; + + zstream.zalloc = ff_png_zalloc; + zstream.zfree = ff_png_zfree; + zstream.opaque = NULL; + if (inflateInit(&zstream) != Z_OK) + return AVERROR_EXTERNAL; + zstream.next_in = (unsigned char *)data; + zstream.avail_in = data_end - data; + av_bprint_init(bp, 0, -1); + + while (zstream.avail_in > 0) { + av_bprint_get_buffer(bp, 1, &buf, &buf_size); + if (!buf_size) { + ret = AVERROR(ENOMEM); + goto fail; + } + zstream.next_out = buf; + zstream.avail_out = buf_size; + ret = inflate(&zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) { + ret = AVERROR_EXTERNAL; + goto fail; + } + bp->len += zstream.next_out - buf; + if (ret == Z_STREAM_END) + break; + } + inflateEnd(&zstream); + bp->str[bp->len] = 0; + return 0; + +fail: + inflateEnd(&zstream); + av_bprint_finalize(bp, NULL); + return ret; +} + +static uint8_t *iso88591_to_utf8(const uint8_t *in, size_t size_in) +{ + size_t extra = 0, i; + uint8_t *out, *q; + + for (i = 0; i < size_in; i++) + extra += in[i] >= 0x80; + if (size_in == SIZE_MAX || extra > SIZE_MAX - size_in - 1) + return NULL; + q = out = av_malloc(size_in + extra + 1); + if (!out) + return NULL; + for (i = 0; i < size_in; i++) { + if (in[i] >= 0x80) { + *(q++) = 0xC0 | (in[i] >> 6); + *(q++) = 0x80 | (in[i] & 0x3F); + } else { + *(q++) = in[i]; + } + } + *(q++) = 0; + return out; +} + +static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed, + AVDictionary **dict) +{ + int ret, method; + const uint8_t *data = s->gb.buffer; + const uint8_t *data_end = data + length; + const uint8_t *keyword = data; + const uint8_t *keyword_end = memchr(keyword, 0, data_end - keyword); + uint8_t *kw_utf8 = NULL, *text, *txt_utf8 = NULL; + unsigned text_len; + AVBPrint bp; + + if (!keyword_end) + return AVERROR_INVALIDDATA; + data = keyword_end + 1; + + if (compressed) { + if (data == data_end) + return AVERROR_INVALIDDATA; + method = *(data++); + if (method) + return AVERROR_INVALIDDATA; + if ((ret = decode_zbuf(&bp, data, data_end)) < 0) + return ret; + text_len = bp.len; + av_bprint_finalize(&bp, (char **)&text); + if (!text) + return AVERROR(ENOMEM); + } else { + text = (uint8_t *)data; + text_len = data_end - text; + } + + kw_utf8 = iso88591_to_utf8(keyword, keyword_end - keyword); + txt_utf8 = iso88591_to_utf8(text, text_len); + if (text != data) + av_free(text); + if (!(kw_utf8 && txt_utf8)) { + av_free(kw_utf8); + av_free(txt_utf8); + return AVERROR(ENOMEM); + } + + av_dict_set(dict, kw_utf8, txt_utf8, + AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + PNGDecContext * const s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *p = data; + AVDictionary *metadata = NULL; + uint8_t *crow_buf_base = NULL; + uint32_t tag, length; + int64_t sig; + int ret; + + bytestream2_init(&s->gb, buf, buf_size); + + /* check signature */ + sig = bytestream2_get_be64(&s->gb); + if (sig != PNGSIG && + sig != MNGSIG) { + av_log(avctx, AV_LOG_ERROR, "Missing png signature\n"); + return -1; + } + + s->y = s->state = 0; + + /* init the zlib */ + s->zstream.zalloc = ff_png_zalloc; + s->zstream.zfree = ff_png_zfree; + s->zstream.opaque = NULL; + ret = inflateInit(&s->zstream); + if (ret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "inflateInit returned %d\n", ret); + return -1; + } + for (;;) { + if (bytestream2_get_bytes_left(&s->gb) <= 0) { + av_log(avctx, AV_LOG_ERROR, "No bytes left\n"); + goto fail; + } + + length = bytestream2_get_be32(&s->gb); + if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) { + av_log(avctx, AV_LOG_ERROR, "chunk too big\n"); + goto fail; + } + tag = bytestream2_get_le32(&s->gb); + if (avctx->debug & FF_DEBUG_STARTCODE) + av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n", + (tag & 0xff), + ((tag >> 8) & 0xff), + ((tag >> 16) & 0xff), + ((tag >> 24) & 0xff), length); + switch (tag) { + case MKTAG('I', 'H', 'D', 'R'): + if (length != 13) + goto fail; + s->width = bytestream2_get_be32(&s->gb); + s->height = bytestream2_get_be32(&s->gb); + if (av_image_check_size(s->width, s->height, 0, avctx)) { + s->width = s->height = 0; + av_log(avctx, AV_LOG_ERROR, "Invalid image size\n"); + goto fail; + } + s->bit_depth = bytestream2_get_byte(&s->gb); + s->color_type = bytestream2_get_byte(&s->gb); + s->compression_type = bytestream2_get_byte(&s->gb); + s->filter_type = bytestream2_get_byte(&s->gb); + s->interlace_type = bytestream2_get_byte(&s->gb); + bytestream2_skip(&s->gb, 4); /* crc */ + s->state |= PNG_IHDR; + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d " + "compression_type=%d filter_type=%d interlace_type=%d\n", + s->width, s->height, s->bit_depth, s->color_type, + s->compression_type, s->filter_type, s->interlace_type); + break; + case MKTAG('p', 'H', 'Y', 's'): + if (s->state & PNG_IDAT) { + av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n"); + goto fail; + } + avctx->sample_aspect_ratio.num = bytestream2_get_be32(&s->gb); + avctx->sample_aspect_ratio.den = bytestream2_get_be32(&s->gb); + if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.den < 0) + avctx->sample_aspect_ratio = (AVRational){ 0, 1 }; + bytestream2_skip(&s->gb, 1); /* unit specifier */ + bytestream2_skip(&s->gb, 4); /* crc */ + break; + case MKTAG('I', 'D', 'A', 'T'): + if (!(s->state & PNG_IHDR)) { + av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n"); + goto fail; + } + if (!(s->state & PNG_IDAT)) { + /* init image info */ + avctx->width = s->width; + avctx->height = s->height; + + s->channels = ff_png_get_nb_channels(s->color_type); + s->bits_per_pixel = s->bit_depth * s->channels; + s->bpp = (s->bits_per_pixel + 7) >> 3; + s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3; + + if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) && + s->color_type == PNG_COLOR_TYPE_RGB) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) && + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + avctx->pix_fmt = AV_PIX_FMT_RGBA; + } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) && + s->color_type == PNG_COLOR_TYPE_GRAY) { + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + } else if (s->bit_depth == 16 && + s->color_type == PNG_COLOR_TYPE_GRAY) { + avctx->pix_fmt = AV_PIX_FMT_GRAY16BE; + } else if (s->bit_depth == 16 && + s->color_type == PNG_COLOR_TYPE_RGB) { + avctx->pix_fmt = AV_PIX_FMT_RGB48BE; + } else if (s->bit_depth == 16 && + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + avctx->pix_fmt = AV_PIX_FMT_RGBA64BE; + } else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) && + s->color_type == PNG_COLOR_TYPE_PALETTE) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else if (s->bit_depth == 1) { + avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + } else if (s->bit_depth == 8 && + s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { + avctx->pix_fmt = AV_PIX_FMT_Y400A; + } else { + av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d " + "and color type %d\n", + s->bit_depth, s->color_type); + goto fail; + } + + if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) + goto fail; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + p->interlaced_frame = !!s->interlace_type; + + /* compute the compressed row size */ + if (!s->interlace_type) { + s->crow_size = s->row_size + 1; + } else { + s->pass = 0; + s->pass_row_size = ff_png_pass_row_size(s->pass, + s->bits_per_pixel, + s->width); + s->crow_size = s->pass_row_size + 1; + } + av_dlog(avctx, "row_size=%d crow_size =%d\n", + s->row_size, s->crow_size); + s->image_buf = p->data[0]; + s->image_linesize = p->linesize[0]; + /* copy the palette if needed */ + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) + memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t)); + /* empty row is used if differencing to the first row */ + s->last_row = av_mallocz(s->row_size); + if (!s->last_row) + goto fail; + if (s->interlace_type || + s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + s->tmp_row = av_malloc(s->row_size); + if (!s->tmp_row) + goto fail; + } + /* compressed row */ + crow_buf_base = av_malloc(s->row_size + 16); + if (!crow_buf_base) + goto fail; + + /* we want crow_buf+1 to be 16-byte aligned */ + s->crow_buf = crow_buf_base + 15; + s->zstream.avail_out = s->crow_size; + s->zstream.next_out = s->crow_buf; + } + s->state |= PNG_IDAT; + if (png_decode_idat(s, length) < 0) + goto fail; + bytestream2_skip(&s->gb, 4); /* crc */ + break; + case MKTAG('P', 'L', 'T', 'E'): + { + int n, i, r, g, b; + + if ((length % 3) != 0 || length > 256 * 3) + goto skip_tag; + /* read the palette */ + n = length / 3; + for (i = 0; i < n; i++) { + r = bytestream2_get_byte(&s->gb); + g = bytestream2_get_byte(&s->gb); + b = bytestream2_get_byte(&s->gb); + s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b; + } + for (; i < 256; i++) { + s->palette[i] = (0xFFU << 24); + } + s->state |= PNG_PLTE; + bytestream2_skip(&s->gb, 4); /* crc */ + } + break; + case MKTAG('t', 'R', 'N', 'S'): + { + int v, i; + + /* read the transparency. XXX: Only palette mode supported */ + if (s->color_type != PNG_COLOR_TYPE_PALETTE || + length > 256 || + !(s->state & PNG_PLTE)) + goto skip_tag; + for (i = 0; i < length; i++) { + v = bytestream2_get_byte(&s->gb); + s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24); + } + bytestream2_skip(&s->gb, 4); /* crc */ + } + break; + case MKTAG('t', 'E', 'X', 't'): + if (decode_text_chunk(s, length, 0, &metadata) < 0) + av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n"); + bytestream2_skip(&s->gb, length + 4); + break; + case MKTAG('z', 'T', 'X', 't'): + if (decode_text_chunk(s, length, 1, &metadata) < 0) + av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n"); + bytestream2_skip(&s->gb, length + 4); + break; + case MKTAG('I', 'E', 'N', 'D'): + if (!(s->state & PNG_ALLIMAGE)) + av_log(avctx, AV_LOG_ERROR, "IEND without all image\n"); + if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) { + goto fail; + } + bytestream2_skip(&s->gb, 4); /* crc */ + goto exit_loop; + default: + /* skip tag */ + skip_tag: + bytestream2_skip(&s->gb, length + 4); + break; + } + } + exit_loop: + + if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE){ + int i, j, k; + uint8_t *pd = p->data[0]; + for (j = 0; j < s->height; j++) { + i = s->width / 8; + for (k = 7; k >= 1; k--) + if ((s->width&7) >= k) + pd[8*i + k - 1] = (pd[i]>>8-k) & 1; + for (i--; i >= 0; i--) { + pd[8*i + 7]= pd[i] & 1; + pd[8*i + 6]= (pd[i]>>1) & 1; + pd[8*i + 5]= (pd[i]>>2) & 1; + pd[8*i + 4]= (pd[i]>>3) & 1; + pd[8*i + 3]= (pd[i]>>4) & 1; + pd[8*i + 2]= (pd[i]>>5) & 1; + pd[8*i + 1]= (pd[i]>>6) & 1; + pd[8*i + 0]= pd[i]>>7; + } + pd += s->image_linesize; + } + } + if (s->bits_per_pixel == 2){ + int i, j; + uint8_t *pd = p->data[0]; + for (j = 0; j < s->height; j++) { + i = s->width / 4; + if (s->color_type == PNG_COLOR_TYPE_PALETTE){ + if ((s->width&3) >= 3) pd[4*i + 2]= (pd[i] >> 2) & 3; + if ((s->width&3) >= 2) pd[4*i + 1]= (pd[i] >> 4) & 3; + if ((s->width&3) >= 1) pd[4*i + 0]= pd[i] >> 6; + for (i--; i >= 0; i--) { + pd[4*i + 3]= pd[i] & 3; + pd[4*i + 2]= (pd[i]>>2) & 3; + pd[4*i + 1]= (pd[i]>>4) & 3; + pd[4*i + 0]= pd[i]>>6; + } + } else { + if ((s->width&3) >= 3) pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55; + if ((s->width&3) >= 2) pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55; + if ((s->width&3) >= 1) pd[4*i + 0]= ( pd[i]>>6 )*0x55; + for (i--; i >= 0; i--) { + pd[4*i + 3]= ( pd[i] & 3)*0x55; + pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55; + pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55; + pd[4*i + 0]= ( pd[i]>>6 )*0x55; + } + } + pd += s->image_linesize; + } + } + if (s->bits_per_pixel == 4){ + int i, j; + uint8_t *pd = p->data[0]; + for (j = 0; j < s->height; j++) { + i = s->width/2; + if (s->color_type == PNG_COLOR_TYPE_PALETTE){ + if (s->width&1) pd[2*i+0]= pd[i]>>4; + for (i--; i >= 0; i--) { + pd[2*i + 1] = pd[i] & 15; + pd[2*i + 0] = pd[i] >> 4; + } + } else { + if (s->width & 1) pd[2*i + 0]= (pd[i] >> 4) * 0x11; + for (i--; i >= 0; i--) { + pd[2*i + 1] = (pd[i] & 15) * 0x11; + pd[2*i + 0] = (pd[i] >> 4) * 0x11; + } + } + pd += s->image_linesize; + } + } + + /* handle p-frames only if a predecessor frame is available */ + if (s->prev->data[0]) { + if ( !(avpkt->flags & AV_PKT_FLAG_KEY) + && s->prev->width == p->width + && s->prev->height== p->height + && s->prev->format== p->format + ) { + int i, j; + uint8_t *pd = p->data[0]; + uint8_t *pd_last = s->prev->data[0]; + + for (j = 0; j < s->height; j++) { + for (i = 0; i < s->width * s->bpp; i++) { + pd[i] += pd_last[i]; + } + pd += s->image_linesize; + pd_last += s->image_linesize; + } + } + } + + av_frame_set_metadata(p, metadata); + metadata = NULL; + + av_frame_unref(s->prev); + if ((ret = av_frame_ref(s->prev, p)) < 0) + goto fail; + + *got_frame = 1; + + ret = bytestream2_tell(&s->gb); + the_end: + inflateEnd(&s->zstream); + av_free(crow_buf_base); + s->crow_buf = NULL; + av_freep(&s->last_row); + av_freep(&s->tmp_row); + return ret; + fail: + av_dict_free(&metadata); + ret = -1; + goto the_end; +} + +static av_cold int png_dec_init(AVCodecContext *avctx) +{ + PNGDecContext *s = avctx->priv_data; + + s->prev = av_frame_alloc(); + if (!s->prev) + return AVERROR(ENOMEM); + + ff_pngdsp_init(&s->dsp); + + s->avctx = avctx; + + return 0; +} + +static av_cold int png_dec_end(AVCodecContext *avctx) +{ + PNGDecContext *s = avctx->priv_data; + + av_frame_free(&s->prev); + + return 0; +} + +AVCodec ff_png_decoder = { + .name = "png", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PNG, + .priv_data_size = sizeof(PNGDecContext), + .init = png_dec_init, + .close = png_dec_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/, + .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), +}; diff --git a/ffmpeg/libavcodec/pngdsp.c b/ffmpeg/libavcodec/pngdsp.c new file mode 100644 index 0000000..1ee8b57 --- /dev/null +++ b/ffmpeg/libavcodec/pngdsp.c @@ -0,0 +1,48 @@ +/* + * PNG image format + * Copyright (c) 2008 Loren Merrit + * + * 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 "libavutil/common.h" +#include "png.h" +#include "pngdsp.h" + +// 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size +#define pb_7f (~0UL/255 * 0x7f) +#define pb_80 (~0UL/255 * 0x80) + +static void add_bytes_l2_c(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w) +{ + long i; + for (i = 0; i <= w - sizeof(long); i += sizeof(long)) { + long a = *(long *)(src1 + i); + long b = *(long *)(src2 + i); + *(long *)(dst + i) = ((a & pb_7f) + (b & pb_7f)) ^ ((a ^ b) & pb_80); + } + for (; i < w; i++) + dst[i] = src1[i] + src2[i]; +} + +void ff_pngdsp_init(PNGDSPContext *dsp) +{ + dsp->add_bytes_l2 = add_bytes_l2_c; + dsp->add_paeth_prediction = ff_add_png_paeth_prediction; + + if (ARCH_X86) ff_pngdsp_init_x86(dsp); +} diff --git a/ffmpeg/libavcodec/pngdsp.h b/ffmpeg/libavcodec/pngdsp.h new file mode 100644 index 0000000..1475b0c --- /dev/null +++ b/ffmpeg/libavcodec/pngdsp.h @@ -0,0 +1,40 @@ +/* + * PNG image format + * Copyright (c) 2008 Loren Merrit + * + * 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 + */ + +#ifndef AVCODEC_PNGDSP_H +#define AVCODEC_PNGDSP_H + +#include + +typedef struct PNGDSPContext { + void (*add_bytes_l2)(uint8_t *dst /* align 16 */, + uint8_t *src1 /* align 16 */, + uint8_t *src2 /* align 16 */, int w); + + /* this might write to dst[w] */ + void (*add_paeth_prediction)(uint8_t *dst, uint8_t *src, + uint8_t *top, int w, int bpp); +} PNGDSPContext; + +void ff_pngdsp_init(PNGDSPContext *dsp); +void ff_pngdsp_init_x86(PNGDSPContext *dsp); + +#endif /* AVCDODEC_PNGDSP_H */ diff --git a/ffmpeg/libavcodec/pngenc.c b/ffmpeg/libavcodec/pngenc.c new file mode 100644 index 0000000..a401c78 --- /dev/null +++ b/ffmpeg/libavcodec/pngenc.c @@ -0,0 +1,480 @@ +/* + * PNG image format + * Copyright (c) 2003 Fabrice Bellard + * + * 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 "avcodec.h" +#include "internal.h" +#include "bytestream.h" +#include "dsputil.h" +#include "png.h" + +#include "libavutil/avassert.h" + +/* TODO: + * - add 2, 4 and 16 bit depth support + */ + +#include + +//#define DEBUG + +#define IOBUF_SIZE 4096 + +typedef struct PNGEncContext { + DSPContext dsp; + + uint8_t *bytestream; + uint8_t *bytestream_start; + uint8_t *bytestream_end; + AVFrame picture; + + int filter_type; + + z_stream zstream; + uint8_t buf[IOBUF_SIZE]; +} PNGEncContext; + +static void png_get_interlaced_row(uint8_t *dst, int row_size, + int bits_per_pixel, int pass, + const uint8_t *src, int width) +{ + int x, mask, dst_x, j, b, bpp; + uint8_t *d; + const uint8_t *s; + + mask = (int[]){0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}[pass]; + switch(bits_per_pixel) { + case 1: + memset(dst, 0, row_size); + dst_x = 0; + for(x = 0; x < width; x++) { + j = (x & 7); + if ((mask << j) & 0x80) { + b = (src[x >> 3] >> (7 - j)) & 1; + dst[dst_x >> 3] |= b << (7 - (dst_x & 7)); + dst_x++; + } + } + break; + default: + bpp = bits_per_pixel >> 3; + d = dst; + s = src; + for(x = 0; x < width; x++) { + j = x & 7; + if ((mask << j) & 0x80) { + memcpy(d, s, bpp); + d += bpp; + } + s += bpp; + } + break; + } +} + +static void sub_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp) +{ + int i; + for(i = 0; i < w; i++) { + int a, b, c, p, pa, pb, pc; + + a = src[i - bpp]; + b = top[i]; + c = top[i - bpp]; + + p = b - c; + pc = a - c; + + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); + + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + dst[i] = src[i] - p; + } +} + +static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type, + uint8_t *src, uint8_t *top, int size, int bpp) +{ + int i; + + switch(filter_type) { + case PNG_FILTER_VALUE_NONE: + memcpy(dst, src, size); + break; + case PNG_FILTER_VALUE_SUB: + dsp->diff_bytes(dst, src, src-bpp, size); + memcpy(dst, src, bpp); + break; + case PNG_FILTER_VALUE_UP: + dsp->diff_bytes(dst, src, top, size); + break; + case PNG_FILTER_VALUE_AVG: + for(i = 0; i < bpp; i++) + dst[i] = src[i] - (top[i] >> 1); + for(; i < size; i++) + dst[i] = src[i] - ((src[i-bpp] + top[i]) >> 1); + break; + case PNG_FILTER_VALUE_PAETH: + for(i = 0; i < bpp; i++) + dst[i] = src[i] - top[i]; + sub_png_paeth_prediction(dst+i, src+i, top+i, size-i, bpp); + break; + } +} + +static uint8_t *png_choose_filter(PNGEncContext *s, uint8_t *dst, + uint8_t *src, uint8_t *top, int size, int bpp) +{ + int pred = s->filter_type; + av_assert0(bpp || !pred); + if(!top && pred) + pred = PNG_FILTER_VALUE_SUB; + if(pred == PNG_FILTER_VALUE_MIXED) { + int i; + int cost, bcost = INT_MAX; + uint8_t *buf1 = dst, *buf2 = dst + size + 16; + for(pred=0; pred<5; pred++) { + png_filter_row(&s->dsp, buf1+1, pred, src, top, size, bpp); + buf1[0] = pred; + cost = 0; + for(i=0; i<=size; i++) + cost += abs((int8_t)buf1[i]); + if(cost < bcost) { + bcost = cost; + FFSWAP(uint8_t*, buf1, buf2); + } + } + return buf2; + } else { + png_filter_row(&s->dsp, dst+1, pred, src, top, size, bpp); + dst[0] = pred; + return dst; + } +} + +static void png_write_chunk(uint8_t **f, uint32_t tag, + const uint8_t *buf, int length) +{ + uint32_t crc; + uint8_t tagbuf[4]; + + bytestream_put_be32(f, length); + crc = crc32(0, Z_NULL, 0); + AV_WL32(tagbuf, tag); + crc = crc32(crc, tagbuf, 4); + bytestream_put_be32(f, av_bswap32(tag)); + if (length > 0) { + crc = crc32(crc, buf, length); + memcpy(*f, buf, length); + *f += length; + } + bytestream_put_be32(f, crc); +} + +/* XXX: do filtering */ +static int png_write_row(PNGEncContext *s, const uint8_t *data, int size) +{ + int ret; + + s->zstream.avail_in = size; + s->zstream.next_in = (uint8_t *)data; + while (s->zstream.avail_in > 0) { + ret = deflate(&s->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + return -1; + if (s->zstream.avail_out == 0) { + if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100) + png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE); + s->zstream.avail_out = IOBUF_SIZE; + s->zstream.next_out = s->buf; + } + } + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + PNGEncContext *s = avctx->priv_data; + AVFrame * const p= &s->picture; + int bit_depth, color_type, y, len, row_size, ret, is_progressive; + int bits_per_pixel, pass_row_size, enc_row_size; + int64_t max_packet_size; + int compression_level; + uint8_t *ptr, *top; + uint8_t *crow_base = NULL, *crow_buf, *crow; + uint8_t *progressive_buf = NULL; + uint8_t *top_buf = NULL; + + *p = *pict; + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT); + switch(avctx->pix_fmt) { + case AV_PIX_FMT_RGBA64BE: + bit_depth = 16; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case AV_PIX_FMT_RGB48BE: + bit_depth = 16; + color_type = PNG_COLOR_TYPE_RGB; + break; + case AV_PIX_FMT_RGBA: + bit_depth = 8; + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + case AV_PIX_FMT_RGB24: + bit_depth = 8; + color_type = PNG_COLOR_TYPE_RGB; + break; + case AV_PIX_FMT_GRAY16BE: + bit_depth = 16; + color_type = PNG_COLOR_TYPE_GRAY; + break; + case AV_PIX_FMT_GRAY8: + bit_depth = 8; + color_type = PNG_COLOR_TYPE_GRAY; + break; + case AV_PIX_FMT_GRAY8A: + bit_depth = 8; + color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + break; + case AV_PIX_FMT_MONOBLACK: + bit_depth = 1; + color_type = PNG_COLOR_TYPE_GRAY; + break; + case AV_PIX_FMT_PAL8: + bit_depth = 8; + color_type = PNG_COLOR_TYPE_PALETTE; + break; + default: + return -1; + } + bits_per_pixel = ff_png_get_nb_channels(color_type) * bit_depth; + row_size = (avctx->width * bits_per_pixel + 7) >> 3; + + s->zstream.zalloc = ff_png_zalloc; + s->zstream.zfree = ff_png_zfree; + s->zstream.opaque = NULL; + compression_level = avctx->compression_level == FF_COMPRESSION_DEFAULT ? + Z_DEFAULT_COMPRESSION : + av_clip(avctx->compression_level, 0, 9); + ret = deflateInit2(&s->zstream, compression_level, + Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + return -1; + + enc_row_size = deflateBound(&s->zstream, row_size); + max_packet_size = avctx->height * (int64_t)(enc_row_size + + ((enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) * 12) + + FF_MIN_BUFFER_SIZE; + if (max_packet_size > INT_MAX) + return AVERROR(ENOMEM); + if ((ret = ff_alloc_packet2(avctx, pkt, max_packet_size)) < 0) + return ret; + + s->bytestream_start = + s->bytestream = pkt->data; + s->bytestream_end = pkt->data + pkt->size; + + crow_base = av_malloc((row_size + 32) << (s->filter_type == PNG_FILTER_VALUE_MIXED)); + if (!crow_base) + goto fail; + crow_buf = crow_base + 15; // pixel data should be aligned, but there's a control byte before it + if (is_progressive) { + progressive_buf = av_malloc(row_size + 1); + if (!progressive_buf) + goto fail; + } + if (is_progressive) { + top_buf = av_malloc(row_size + 1); + if (!top_buf) + goto fail; + } + + /* write png header */ + AV_WB64(s->bytestream, PNGSIG); + s->bytestream += 8; + + AV_WB32(s->buf, avctx->width); + AV_WB32(s->buf + 4, avctx->height); + s->buf[8] = bit_depth; + s->buf[9] = color_type; + s->buf[10] = 0; /* compression type */ + s->buf[11] = 0; /* filter type */ + s->buf[12] = is_progressive; /* interlace type */ + + png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13); + + AV_WB32(s->buf, avctx->sample_aspect_ratio.num); + AV_WB32(s->buf + 4, avctx->sample_aspect_ratio.den); + s->buf[8] = 0; /* unit specifier is unknown */ + png_write_chunk(&s->bytestream, MKTAG('p', 'H', 'Y', 's'), s->buf, 9); + + /* put the palette if needed */ + if (color_type == PNG_COLOR_TYPE_PALETTE) { + int has_alpha, alpha, i; + unsigned int v; + uint32_t *palette; + uint8_t *alpha_ptr; + + palette = (uint32_t *)p->data[1]; + ptr = s->buf; + alpha_ptr = s->buf + 256 * 3; + has_alpha = 0; + for(i = 0; i < 256; i++) { + v = palette[i]; + alpha = v >> 24; + if (alpha != 0xff) + has_alpha = 1; + *alpha_ptr++ = alpha; + bytestream_put_be24(&ptr, v); + } + png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3); + if (has_alpha) { + png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256); + } + } + + /* now put each row */ + s->zstream.avail_out = IOBUF_SIZE; + s->zstream.next_out = s->buf; + if (is_progressive) { + int pass; + + for(pass = 0; pass < NB_PASSES; pass++) { + /* NOTE: a pass is completely omitted if no pixels would be + output */ + pass_row_size = ff_png_pass_row_size(pass, bits_per_pixel, avctx->width); + if (pass_row_size > 0) { + top = NULL; + for(y = 0; y < avctx->height; y++) { + if ((ff_png_pass_ymask[pass] << (y & 7)) & 0x80) { + ptr = p->data[0] + y * p->linesize[0]; + FFSWAP(uint8_t*, progressive_buf, top_buf); + png_get_interlaced_row(progressive_buf, pass_row_size, + bits_per_pixel, pass, + ptr, avctx->width); + crow = png_choose_filter(s, crow_buf, progressive_buf, top, pass_row_size, bits_per_pixel>>3); + png_write_row(s, crow, pass_row_size + 1); + top = progressive_buf; + } + } + } + } + } else { + top = NULL; + for(y = 0; y < avctx->height; y++) { + ptr = p->data[0] + y * p->linesize[0]; + crow = png_choose_filter(s, crow_buf, ptr, top, row_size, bits_per_pixel>>3); + png_write_row(s, crow, row_size + 1); + top = ptr; + } + } + /* compress last bytes */ + for(;;) { + ret = deflate(&s->zstream, Z_FINISH); + if (ret == Z_OK || ret == Z_STREAM_END) { + len = IOBUF_SIZE - s->zstream.avail_out; + if (len > 0 && s->bytestream_end - s->bytestream > len + 100) { + png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len); + } + s->zstream.avail_out = IOBUF_SIZE; + s->zstream.next_out = s->buf; + if (ret == Z_STREAM_END) + break; + } else { + goto fail; + } + } + png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0); + + pkt->size = s->bytestream - s->bytestream_start; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + ret = 0; + + the_end: + av_free(crow_base); + av_free(progressive_buf); + av_free(top_buf); + deflateEnd(&s->zstream); + return ret; + fail: + ret = -1; + goto the_end; +} + +static av_cold int png_enc_init(AVCodecContext *avctx){ + PNGEncContext *s = avctx->priv_data; + + switch(avctx->pix_fmt) { + case AV_PIX_FMT_RGBA: + avctx->bits_per_coded_sample = 32; + break; + case AV_PIX_FMT_RGB24: + avctx->bits_per_coded_sample = 24; + break; + case AV_PIX_FMT_GRAY8: + avctx->bits_per_coded_sample = 0x28; + break; + case AV_PIX_FMT_MONOBLACK: + avctx->bits_per_coded_sample = 1; + break; + case AV_PIX_FMT_PAL8: + avctx->bits_per_coded_sample = 8; + } + + avcodec_get_frame_defaults(&s->picture); + avctx->coded_frame= &s->picture; + ff_dsputil_init(&s->dsp, avctx); + + s->filter_type = av_clip(avctx->prediction_method, PNG_FILTER_VALUE_NONE, PNG_FILTER_VALUE_MIXED); + if(avctx->pix_fmt == AV_PIX_FMT_MONOBLACK) + s->filter_type = PNG_FILTER_VALUE_NONE; + + return 0; +} + +AVCodec ff_png_encoder = { + .name = "png", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PNG, + .priv_data_size = sizeof(PNGEncContext), + .init = png_enc_init, + .encode2 = encode_frame, + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, + AV_PIX_FMT_PAL8, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, + AV_PIX_FMT_GRAY16BE, + AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), +}; diff --git a/ffmpeg/libavcodec/pnm.c b/ffmpeg/libavcodec/pnm.c new file mode 100644 index 0000000..33b8896 --- /dev/null +++ b/ffmpeg/libavcodec/pnm.c @@ -0,0 +1,204 @@ +/* + * PNM image format + * Copyright (c) 2002, 2003 Fabrice Bellard + * + * 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 + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "pnm.h" + +static inline int pnm_space(int c) +{ + return c == ' ' || c == '\n' || c == '\r' || c == '\t'; +} + +static void pnm_get(PNMContext *sc, char *str, int buf_size) +{ + char *s; + int c; + + /* skip spaces and comments */ + while (sc->bytestream < sc->bytestream_end) { + c = *sc->bytestream++; + if (c == '#') { + while (c != '\n' && sc->bytestream < sc->bytestream_end) { + c = *sc->bytestream++; + } + } else if (!pnm_space(c)) { + break; + } + } + + s = str; + while (sc->bytestream < sc->bytestream_end && !pnm_space(c)) { + if ((s - str) < buf_size - 1) + *s++ = c; + c = *sc->bytestream++; + } + *s = '\0'; +} + +int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s) +{ + char buf1[32], tuple_type[32]; + int h, w, depth, maxval; + + pnm_get(s, buf1, sizeof(buf1)); + s->type= buf1[1]-'0'; + if(buf1[0] != 'P') + return AVERROR_INVALIDDATA; + + if (s->type==1 || s->type==4) { + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + } else if (s->type==2 || s->type==5) { + if (avctx->codec_id == AV_CODEC_ID_PGMYUV) + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + else + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + } else if (s->type==3 || s->type==6) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else if (s->type==7) { + w = -1; + h = -1; + maxval = -1; + depth = -1; + tuple_type[0] = '\0'; + for (;;) { + pnm_get(s, buf1, sizeof(buf1)); + if (!strcmp(buf1, "WIDTH")) { + pnm_get(s, buf1, sizeof(buf1)); + w = strtol(buf1, NULL, 10); + } else if (!strcmp(buf1, "HEIGHT")) { + pnm_get(s, buf1, sizeof(buf1)); + h = strtol(buf1, NULL, 10); + } else if (!strcmp(buf1, "DEPTH")) { + pnm_get(s, buf1, sizeof(buf1)); + depth = strtol(buf1, NULL, 10); + } else if (!strcmp(buf1, "MAXVAL")) { + pnm_get(s, buf1, sizeof(buf1)); + maxval = strtol(buf1, NULL, 10); + } else if (!strcmp(buf1, "TUPLTYPE") || + /* libavcodec used to write invalid files */ + !strcmp(buf1, "TUPLETYPE")) { + pnm_get(s, tuple_type, sizeof(tuple_type)); + } else if (!strcmp(buf1, "ENDHDR")) { + break; + } else { + return AVERROR_INVALIDDATA; + } + } + /* check that all tags are present */ + if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end) + return AVERROR_INVALIDDATA; + + avctx->width = w; + avctx->height = h; + s->maxval = maxval; + if (depth == 1) { + if (maxval == 1) { + avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + } else if (maxval == 255) { + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + } else { + avctx->pix_fmt = AV_PIX_FMT_GRAY16BE; + } + } else if (depth == 2) { + if (maxval == 255) + avctx->pix_fmt = AV_PIX_FMT_GRAY8A; + } else if (depth == 3) { + if (maxval < 256) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + } else { + avctx->pix_fmt = AV_PIX_FMT_RGB48BE; + } + } else if (depth == 4) { + if (maxval < 256) { + avctx->pix_fmt = AV_PIX_FMT_RGBA; + } else { + avctx->pix_fmt = AV_PIX_FMT_RGBA64BE; + } + } else { + return AVERROR_INVALIDDATA; + } + return 0; + } else { + return AVERROR_INVALIDDATA; + } + pnm_get(s, buf1, sizeof(buf1)); + w = atoi(buf1); + pnm_get(s, buf1, sizeof(buf1)); + h = atoi(buf1); + if(w <= 0 || h <= 0 || av_image_check_size(w, h, 0, avctx) || s->bytestream >= s->bytestream_end) + return AVERROR_INVALIDDATA; + + avctx->width = w; + avctx->height = h; + + if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && avctx->pix_fmt != AV_PIX_FMT_MONOBLACK) { + pnm_get(s, buf1, sizeof(buf1)); + s->maxval = atoi(buf1); + if (s->maxval <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid maxval: %d\n", s->maxval); + s->maxval = 255; + } + if (s->maxval >= 256) { + if (avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + avctx->pix_fmt = AV_PIX_FMT_GRAY16BE; + } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) { + avctx->pix_fmt = AV_PIX_FMT_RGB48BE; + } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P && s->maxval < 65536) { + if (s->maxval < 512) + avctx->pix_fmt = AV_PIX_FMT_YUV420P9BE; + else if (s->maxval < 1024) + avctx->pix_fmt = AV_PIX_FMT_YUV420P10BE; + else + avctx->pix_fmt = AV_PIX_FMT_YUV420P16; + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n"); + avctx->pix_fmt = AV_PIX_FMT_NONE; + return AVERROR_INVALIDDATA; + } + } + }else + s->maxval=1; + /* more check if YUV420 */ + if (av_pix_fmt_desc_get(avctx->pix_fmt)->flags & PIX_FMT_PLANAR) { + if ((avctx->width & 1) != 0) + return AVERROR_INVALIDDATA; + h = (avctx->height * 2); + if ((h % 3) != 0) + return AVERROR_INVALIDDATA; + h /= 3; + avctx->height = h; + } + return 0; +} + +av_cold int ff_pnm_init(AVCodecContext *avctx) +{ + PNMContext *s = avctx->priv_data; + + avcodec_get_frame_defaults(&s->picture); + avctx->coded_frame = &s->picture; + + return 0; +} diff --git a/ffmpeg/libavcodec/pnm.h b/ffmpeg/libavcodec/pnm.h new file mode 100644 index 0000000..92edf8d --- /dev/null +++ b/ffmpeg/libavcodec/pnm.h @@ -0,0 +1,39 @@ +/* + * PNM image format + * Copyright (c) 2002, 2003 Fabrice Bellard + * + * 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 + */ + +#ifndef AVCODEC_PNM_H +#define AVCODEC_PNM_H + +#include "avcodec.h" + +typedef struct PNMContext { + uint8_t *bytestream; + uint8_t *bytestream_start; + uint8_t *bytestream_end; + AVFrame picture; + int maxval; ///< maximum value of a pixel + int type; +} PNMContext; + +int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s); +int ff_pnm_init(AVCodecContext *avctx); + +#endif /* AVCODEC_PNM_H */ diff --git a/ffmpeg/libavcodec/pnm_parser.c b/ffmpeg/libavcodec/pnm_parser.c new file mode 100644 index 0000000..2a9e3e1 --- /dev/null +++ b/ffmpeg/libavcodec/pnm_parser.c @@ -0,0 +1,92 @@ +/* + * PNM image parser + * Copyright (c) 2002, 2003 Fabrice Bellard + * + * 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 "parser.h" //for ParseContext +#include "pnm.h" + + +static int pnm_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + PNMContext pnmctx; + int next; + + for (; pc->overread > 0; pc->overread--) { + pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; + } +retry: + if (pc->index) { + pnmctx.bytestream_start = + pnmctx.bytestream = pc->buffer; + pnmctx.bytestream_end = pc->buffer + pc->index; + } else { + pnmctx.bytestream_start = + pnmctx.bytestream = (uint8_t *) buf; /* casts avoid warnings */ + pnmctx.bytestream_end = (uint8_t *) buf + buf_size; + } + if (ff_pnm_decode_header(avctx, &pnmctx) < 0) { + if (pnmctx.bytestream < pnmctx.bytestream_end) { + if (pc->index) { + pc->index = 0; + } else { + buf++; + buf_size--; + } + goto retry; + } +#if 0 + if (pc->index && pc->index * 2 + FF_INPUT_BUFFER_PADDING_SIZE < pc->buffer_size && buf_size > pc->index) { + memcpy(pc->buffer + pc->index, buf, pc->index); + pc->index += pc->index; + buf += pc->index; + buf_size -= pc->index; + goto retry; + } +#endif + next = END_NOT_FOUND; + } else { + next = pnmctx.bytestream - pnmctx.bytestream_start + + avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + if (pnmctx.bytestream_start != buf) + next -= pc->index; + if (next > buf_size) + next = END_NOT_FOUND; + } + + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_pnm_parser = { + .codec_ids = { AV_CODEC_ID_PGM, AV_CODEC_ID_PGMYUV, AV_CODEC_ID_PPM, + AV_CODEC_ID_PBM, AV_CODEC_ID_PAM }, + .priv_data_size = sizeof(ParseContext), + .parser_parse = pnm_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/pnmdec.c b/ffmpeg/libavcodec/pnmdec.c new file mode 100644 index 0000000..d0c7295 --- /dev/null +++ b/ffmpeg/libavcodec/pnmdec.c @@ -0,0 +1,290 @@ +/* + * PNM image format + * Copyright (c) 2002, 2003 Fabrice Bellard + * + * 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 "avcodec.h" +#include "internal.h" +#include "put_bits.h" +#include "pnm.h" + + +static int pnm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + PNMContext * const s = avctx->priv_data; + AVFrame * const p = data; + int i, j, n, linesize, h, upgrade = 0, is_mono = 0; + unsigned char *ptr; + int components, sample_len, ret; + + s->bytestream_start = + s->bytestream = (uint8_t *)buf; + s->bytestream_end = (uint8_t *)buf + buf_size; + + if ((ret = ff_pnm_decode_header(avctx, s)) < 0) + return ret; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + switch (avctx->pix_fmt) { + default: + return AVERROR(EINVAL); + case AV_PIX_FMT_RGBA64BE: + n = avctx->width * 8; + components=4; + sample_len=16; + goto do_read; + case AV_PIX_FMT_RGB48BE: + n = avctx->width * 6; + components=3; + sample_len=16; + goto do_read; + case AV_PIX_FMT_RGBA: + n = avctx->width * 4; + components=4; + sample_len=8; + goto do_read; + case AV_PIX_FMT_RGB24: + n = avctx->width * 3; + components=3; + sample_len=8; + goto do_read; + case AV_PIX_FMT_GRAY8: + n = avctx->width; + components=1; + sample_len=8; + if (s->maxval < 255) + upgrade = 1; + goto do_read; + case AV_PIX_FMT_GRAY8A: + n = avctx->width * 2; + components=2; + sample_len=8; + goto do_read; + case AV_PIX_FMT_GRAY16BE: + case AV_PIX_FMT_GRAY16LE: + n = avctx->width * 2; + components=1; + sample_len=16; + if (s->maxval < 65535) + upgrade = 2; + goto do_read; + case AV_PIX_FMT_MONOWHITE: + case AV_PIX_FMT_MONOBLACK: + n = (avctx->width + 7) >> 3; + components=1; + sample_len=1; + is_mono = 1; + do_read: + ptr = p->data[0]; + linesize = p->linesize[0]; + if (s->bytestream + n * avctx->height > s->bytestream_end) + return AVERROR_INVALIDDATA; + if(s->type < 4 || (is_mono && s->type==7)){ + for (i=0; iheight; i++) { + PutBitContext pb; + init_put_bits(&pb, ptr, linesize); + for(j=0; jwidth * components; j++){ + unsigned int c=0; + int v=0; + if(s->type < 4) + while(s->bytestream < s->bytestream_end && (*s->bytestream < '0' || *s->bytestream > '9' )) + s->bytestream++; + if(s->bytestream >= s->bytestream_end) + return AVERROR_INVALIDDATA; + if (is_mono) { + /* read a single digit */ + v = (*s->bytestream++)&1; + } else { + /* read a sequence of digits */ + do { + v = 10*v + c; + c = (*s->bytestream++) - '0'; + } while (c <= 9); + } + put_bits(&pb, sample_len, (((1<maxval>>1))/s->maxval); + } + flush_put_bits(&pb); + ptr+= linesize; + } + }else{ + for (i = 0; i < avctx->height; i++) { + if (!upgrade) + memcpy(ptr, s->bytestream, n); + else if (upgrade == 1) { + unsigned int j, f = (255 * 128 + s->maxval / 2) / s->maxval; + for (j = 0; j < n; j++) + ptr[j] = (s->bytestream[j] * f + 64) >> 7; + } else if (upgrade == 2) { + unsigned int j, v, f = (65535 * 32768 + s->maxval / 2) / s->maxval; + for (j = 0; j < n / 2; j++) { + v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15; + } + } + s->bytestream += n; + ptr += linesize; + } + } + break; + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P9BE: + case AV_PIX_FMT_YUV420P10BE: + { + unsigned char *ptr1, *ptr2; + + n = avctx->width; + ptr = p->data[0]; + linesize = p->linesize[0]; + if (s->maxval >= 256) + n *= 2; + if (s->bytestream + n * avctx->height * 3 / 2 > s->bytestream_end) + return AVERROR_INVALIDDATA; + for (i = 0; i < avctx->height; i++) { + memcpy(ptr, s->bytestream, n); + s->bytestream += n; + ptr += linesize; + } + ptr1 = p->data[1]; + ptr2 = p->data[2]; + n >>= 1; + h = avctx->height >> 1; + for (i = 0; i < h; i++) { + memcpy(ptr1, s->bytestream, n); + s->bytestream += n; + memcpy(ptr2, s->bytestream, n); + s->bytestream += n; + ptr1 += p->linesize[1]; + ptr2 += p->linesize[2]; + } + } + break; + case AV_PIX_FMT_YUV420P16: + { + uint16_t *ptr1, *ptr2; + const int f = (65535 * 32768 + s->maxval / 2) / s->maxval; + unsigned int j, v; + + n = avctx->width * 2; + ptr = p->data[0]; + linesize = p->linesize[0]; + if (s->bytestream + n * avctx->height * 3 / 2 > s->bytestream_end) + return AVERROR_INVALIDDATA; + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < n / 2; j++) { + v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15; + } + s->bytestream += n; + ptr += linesize; + } + ptr1 = (uint16_t*)p->data[1]; + ptr2 = (uint16_t*)p->data[2]; + n >>= 1; + h = avctx->height >> 1; + for (i = 0; i < h; i++) { + for (j = 0; j < n / 2; j++) { + v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + ptr1[j] = (v * f + 16384) >> 15; + } + s->bytestream += n; + + for (j = 0; j < n / 2; j++) { + v = av_be2ne16(((uint16_t *)s->bytestream)[j]); + ptr2[j] = (v * f + 16384) >> 15; + } + s->bytestream += n; + + ptr1 += p->linesize[1] / 2; + ptr2 += p->linesize[2] / 2; + } + } + break; + } + *got_frame = 1; + + return s->bytestream - s->bytestream_start; +} + + +#if CONFIG_PGM_DECODER +AVCodec ff_pgm_decoder = { + .name = "pgm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PGM, + .priv_data_size = sizeof(PNMContext), + .decode = pnm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), +}; +#endif + +#if CONFIG_PGMYUV_DECODER +AVCodec ff_pgmyuv_decoder = { + .name = "pgmyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PGMYUV, + .priv_data_size = sizeof(PNMContext), + .decode = pnm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), +}; +#endif + +#if CONFIG_PPM_DECODER +AVCodec ff_ppm_decoder = { + .name = "ppm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PPM, + .priv_data_size = sizeof(PNMContext), + .decode = pnm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), +}; +#endif + +#if CONFIG_PBM_DECODER +AVCodec ff_pbm_decoder = { + .name = "pbm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PBM, + .priv_data_size = sizeof(PNMContext), + .decode = pnm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), +}; +#endif + +#if CONFIG_PAM_DECODER +AVCodec ff_pam_decoder = { + .name = "pam", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PAM, + .priv_data_size = sizeof(PNMContext), + .decode = pnm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), +}; +#endif diff --git a/ffmpeg/libavcodec/pnmenc.c b/ffmpeg/libavcodec/pnmenc.c new file mode 100644 index 0000000..8cd96be --- /dev/null +++ b/ffmpeg/libavcodec/pnmenc.c @@ -0,0 +1,186 @@ +/* + * PNM image format + * Copyright (c) 2002, 2003 Fabrice Bellard + * + * 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 "libavutil/pixdesc.h" +#include "avcodec.h" +#include "internal.h" +#include "pnm.h" + + +static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + PNMContext *s = avctx->priv_data; + AVFrame * const p = &s->picture; + int i, h, h1, c, n, linesize, ret; + uint8_t *ptr, *ptr1, *ptr2; + + if ((ret = ff_alloc_packet2(avctx, pkt, avpicture_get_size(avctx->pix_fmt, + avctx->width, + avctx->height) + 200)) < 0) + return ret; + + *p = *pict; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + s->bytestream_start = + s->bytestream = pkt->data; + s->bytestream_end = pkt->data + pkt->size; + + h = avctx->height; + h1 = h; + switch (avctx->pix_fmt) { + case AV_PIX_FMT_MONOWHITE: + c = '4'; + n = (avctx->width + 7) >> 3; + break; + case AV_PIX_FMT_GRAY8: + c = '5'; + n = avctx->width; + break; + case AV_PIX_FMT_GRAY16BE: + c = '5'; + n = avctx->width * 2; + break; + case AV_PIX_FMT_RGB24: + c = '6'; + n = avctx->width * 3; + break; + case AV_PIX_FMT_RGB48BE: + c = '6'; + n = avctx->width * 6; + break; + case AV_PIX_FMT_YUV420P: + if (avctx->width & 1 || avctx->height & 1) { + av_log(avctx, AV_LOG_ERROR, "pgmyuv needs even width and height\n"); + return AVERROR(EINVAL); + } + c = '5'; + n = avctx->width; + h1 = (h * 3) / 2; + break; + case AV_PIX_FMT_YUV420P16BE: + c = '5'; + n = avctx->width * 2; + h1 = (h * 3) / 2; + break; + default: + return -1; + } + snprintf(s->bytestream, s->bytestream_end - s->bytestream, + "P%c\n%d %d\n", c, avctx->width, h1); + s->bytestream += strlen(s->bytestream); + if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE) { + int maxdepth = (1 << (av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth_minus1 + 1)) - 1; + snprintf(s->bytestream, s->bytestream_end - s->bytestream, + "%d\n", maxdepth); + s->bytestream += strlen(s->bytestream); + } + + ptr = p->data[0]; + linesize = p->linesize[0]; + for (i = 0; i < h; i++) { + memcpy(s->bytestream, ptr, n); + s->bytestream += n; + ptr += linesize; + } + + if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P16BE) { + h >>= 1; + n >>= 1; + ptr1 = p->data[1]; + ptr2 = p->data[2]; + for (i = 0; i < h; i++) { + memcpy(s->bytestream, ptr1, n); + s->bytestream += n; + memcpy(s->bytestream, ptr2, n); + s->bytestream += n; + ptr1 += p->linesize[1]; + ptr2 += p->linesize[2]; + } + } + pkt->size = s->bytestream - s->bytestream_start; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + + +#if CONFIG_PGM_ENCODER +AVCodec ff_pgm_encoder = { + .name = "pgm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PGM, + .priv_data_size = sizeof(PNMContext), + .init = ff_pnm_init, + .encode2 = pnm_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), +}; +#endif + +#if CONFIG_PGMYUV_ENCODER +AVCodec ff_pgmyuv_encoder = { + .name = "pgmyuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PGMYUV, + .priv_data_size = sizeof(PNMContext), + .init = ff_pnm_init, + .encode2 = pnm_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), +}; +#endif + +#if CONFIG_PPM_ENCODER +AVCodec ff_ppm_encoder = { + .name = "ppm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PPM, + .priv_data_size = sizeof(PNMContext), + .init = ff_pnm_init, + .encode2 = pnm_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), +}; +#endif + +#if CONFIG_PBM_ENCODER +AVCodec ff_pbm_encoder = { + .name = "pbm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PBM, + .priv_data_size = sizeof(PNMContext), + .init = ff_pnm_init, + .encode2 = pnm_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), +}; +#endif diff --git a/ffmpeg/libavcodec/ppc/Makefile b/ffmpeg/libavcodec/ppc/Makefile new file mode 100644 index 0000000..febbb0a --- /dev/null +++ b/ffmpeg/libavcodec/ppc/Makefile @@ -0,0 +1,24 @@ +OBJS += ppc/dsputil_ppc.o \ + ppc/videodsp_ppc.o \ + +OBJS-$(CONFIG_H264CHROMA) += ppc/h264chroma_init.o +OBJS-$(CONFIG_H264QPEL) += ppc/h264_qpel.o +OBJS-$(CONFIG_HPELDSP) += ppc/hpeldsp_altivec.o +OBJS-$(CONFIG_VORBIS_DECODER) += ppc/vorbisdsp_altivec.o +OBJS-$(CONFIG_VP3DSP) += ppc/vp3dsp_altivec.o + +FFT-OBJS-$(HAVE_GNU_AS) += ppc/fft_altivec_s.o +ALTIVEC-OBJS-$(CONFIG_FFT) += ppc/fft_altivec.o \ + $(FFT-OBJS-yes) +ALTIVEC-OBJS-$(CONFIG_H264DSP) += ppc/h264_altivec.o +ALTIVEC-OBJS-$(CONFIG_MPEGAUDIODSP) += ppc/mpegaudiodec_altivec.o +ALTIVEC-OBJS-$(CONFIG_MPEGVIDEO) += ppc/mpegvideo_altivec.o +ALTIVEC-OBJS-$(CONFIG_VC1_DECODER) += ppc/vc1dsp_altivec.o +ALTIVEC-OBJS-$(CONFIG_VP8_DECODER) += ppc/vp8dsp_altivec.o + +ALTIVEC-OBJS += ppc/dsputil_altivec.o \ + ppc/fdct_altivec.o \ + ppc/fmtconvert_altivec.o \ + ppc/gmc_altivec.o \ + ppc/idct_altivec.o \ + ppc/int_altivec.o \ diff --git a/ffmpeg/libavcodec/ppc/asm.S b/ffmpeg/libavcodec/ppc/asm.S new file mode 100644 index 0000000..bbbf8a4 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/asm.S @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2009 Loren Merritt + * + * 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 "config.h" + +#define GLUE(a, b) a ## b +#define JOIN(a, b) GLUE(a, b) +#define X(s) JOIN(EXTERN_ASM, s) + +#if ARCH_PPC64 + +#define PTR .quad +#define lp ld +#define lpx ldx +#define stp std +#define stpu stdu +#define PS 8 +#define L(s) JOIN(., s) + +.macro extfunc name + .global X(\name) + .section .opd, "aw" +X(\name): + .quad L(\name), .TOC.@tocbase, 0 + .previous + .type X(\name), STT_FUNC +L(\name): +.endm + +.macro movrel rd, sym, gp + ld \rd, \sym@got(r2) +.endm + +.macro get_got rd +.endm + +#else /* ARCH_PPC64 */ + +#define PTR .int +#define lp lwz +#define lpx lwzx +#define stp stw +#define stpu stwu +#define PS 4 +#define L(s) s + +.macro extfunc name + .global X(\name) + .type X(\name), STT_FUNC +X(\name): +\name: +.endm + +.macro movrel rd, sym, gp +#if CONFIG_PIC + lwz \rd, \sym@got(\gp) +#else + lis \rd, \sym@ha + la \rd, \sym@l(\rd) +#endif +.endm + +.macro get_got rd +#if CONFIG_PIC + bcl 20, 31, .Lgot\@ +.Lgot\@: + mflr \rd + addis \rd, \rd, _GLOBAL_OFFSET_TABLE_ - .Lgot\@@ha + addi \rd, \rd, _GLOBAL_OFFSET_TABLE_ - .Lgot\@@l +#endif +.endm + +#endif /* ARCH_PPC64 */ + +#if HAVE_IBM_ASM + +.macro DEFINE_REG n + .equiv r\n, \n + .equiv f\n, \n + .equiv v\n, \n +.endm + +DEFINE_REG 0 +DEFINE_REG 1 +DEFINE_REG 2 +DEFINE_REG 3 +DEFINE_REG 4 +DEFINE_REG 5 +DEFINE_REG 6 +DEFINE_REG 7 +DEFINE_REG 8 +DEFINE_REG 9 +DEFINE_REG 10 +DEFINE_REG 11 +DEFINE_REG 12 +DEFINE_REG 13 +DEFINE_REG 14 +DEFINE_REG 15 +DEFINE_REG 16 +DEFINE_REG 17 +DEFINE_REG 18 +DEFINE_REG 19 +DEFINE_REG 20 +DEFINE_REG 21 +DEFINE_REG 22 +DEFINE_REG 23 +DEFINE_REG 24 +DEFINE_REG 25 +DEFINE_REG 26 +DEFINE_REG 27 +DEFINE_REG 28 +DEFINE_REG 29 +DEFINE_REG 30 +DEFINE_REG 31 + +#endif /* HAVE_IBM_ASM */ diff --git a/ffmpeg/libavcodec/ppc/dsputil_altivec.c b/ffmpeg/libavcodec/ppc/dsputil_altivec.c new file mode 100644 index 0000000..f36e394 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/dsputil_altivec.c @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * 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 "config.h" +#if HAVE_ALTIVEC_H +#include +#endif +#include "libavutil/attributes.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/dsputil.h" +#include "dsputil_altivec.h" + +static int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + vector unsigned char perm1 = vec_lvsl(0, pix2); + vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1)); + vector unsigned char pix2l, pix2r; + vector unsigned char pix1v, pix2v, pix2iv, avgv, t5; + vector unsigned int sad; + vector signed int sumdiffs; + + s = 0; + sad = (vector unsigned int)vec_splat_u32(0); + for (i = 0; i < h; i++) { + /* Read unaligned pixels into our vectors. The vectors are as follows: + pix1v: pix1[0]-pix1[15] + pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16] */ + pix1v = vec_ld( 0, pix1); + pix2l = vec_ld( 0, pix2); + pix2r = vec_ld(16, pix2); + pix2v = vec_perm(pix2l, pix2r, perm1); + pix2iv = vec_perm(pix2l, pix2r, perm2); + + /* Calculate the average vector */ + avgv = vec_avg(pix2v, pix2iv); + + /* Calculate a sum of abs differences vector */ + t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv)); + + /* Add each 4 pixel group together and put 4 results into sad */ + sad = vec_sum4s(t5, sad); + + pix1 += line_size; + pix2 += line_size; + } + /* Sum up the four partial sums, and put the result into s */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + + return s; +} + +static int sad16_y2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + vector unsigned char perm = vec_lvsl(0, pix2); + vector unsigned char pix2l, pix2r; + vector unsigned char pix1v, pix2v, pix3v, avgv, t5; + vector unsigned int sad; + vector signed int sumdiffs; + uint8_t *pix3 = pix2 + line_size; + + s = 0; + sad = (vector unsigned int)vec_splat_u32(0); + + /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one + iteration becomes pix2 in the next iteration. We can use this + fact to avoid a potentially expensive unaligned read, each + time around the loop. + Read unaligned pixels into our vectors. The vectors are as follows: + pix2v: pix2[0]-pix2[15] + Split the pixel vectors into shorts */ + pix2l = vec_ld( 0, pix2); + pix2r = vec_ld(15, pix2); + pix2v = vec_perm(pix2l, pix2r, perm); + + for (i = 0; i < h; i++) { + /* Read unaligned pixels into our vectors. The vectors are as follows: + pix1v: pix1[0]-pix1[15] + pix3v: pix3[0]-pix3[15] */ + pix1v = vec_ld(0, pix1); + + pix2l = vec_ld( 0, pix3); + pix2r = vec_ld(15, pix3); + pix3v = vec_perm(pix2l, pix2r, perm); + + /* Calculate the average vector */ + avgv = vec_avg(pix2v, pix3v); + + /* Calculate a sum of abs differences vector */ + t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv)); + + /* Add each 4 pixel group together and put 4 results into sad */ + sad = vec_sum4s(t5, sad); + + pix1 += line_size; + pix2v = pix3v; + pix3 += line_size; + + } + + /* Sum up the four partial sums, and put the result into s */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + return s; +} + +static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + uint8_t *pix3 = pix2 + line_size; + const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + const vector unsigned short two = (const vector unsigned short)vec_splat_u16(2); + vector unsigned char avgv, t5; + vector unsigned char perm1 = vec_lvsl(0, pix2); + vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1)); + vector unsigned char pix2l, pix2r; + vector unsigned char pix1v, pix2v, pix3v, pix2iv, pix3iv; + vector unsigned short pix2lv, pix2hv, pix2ilv, pix2ihv; + vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv; + vector unsigned short avghv, avglv; + vector unsigned short t1, t2, t3, t4; + vector unsigned int sad; + vector signed int sumdiffs; + + sad = (vector unsigned int)vec_splat_u32(0); + + s = 0; + + /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one + iteration becomes pix2 in the next iteration. We can use this + fact to avoid a potentially expensive unaligned read, as well + as some splitting, and vector addition each time around the loop. + Read unaligned pixels into our vectors. The vectors are as follows: + pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16] + Split the pixel vectors into shorts */ + pix2l = vec_ld( 0, pix2); + pix2r = vec_ld(16, pix2); + pix2v = vec_perm(pix2l, pix2r, perm1); + pix2iv = vec_perm(pix2l, pix2r, perm2); + + pix2hv = (vector unsigned short) vec_mergeh(zero, pix2v); + pix2lv = (vector unsigned short) vec_mergel(zero, pix2v); + pix2ihv = (vector unsigned short) vec_mergeh(zero, pix2iv); + pix2ilv = (vector unsigned short) vec_mergel(zero, pix2iv); + t1 = vec_add(pix2hv, pix2ihv); + t2 = vec_add(pix2lv, pix2ilv); + + for (i = 0; i < h; i++) { + /* Read unaligned pixels into our vectors. The vectors are as follows: + pix1v: pix1[0]-pix1[15] + pix3v: pix3[0]-pix3[15] pix3iv: pix3[1]-pix3[16] */ + pix1v = vec_ld(0, pix1); + + pix2l = vec_ld( 0, pix3); + pix2r = vec_ld(16, pix3); + pix3v = vec_perm(pix2l, pix2r, perm1); + pix3iv = vec_perm(pix2l, pix2r, perm2); + + /* Note that AltiVec does have vec_avg, but this works on vector pairs + and rounds up. We could do avg(avg(a,b),avg(c,d)), but the rounding + would mean that, for example, avg(3,0,0,1) = 2, when it should be 1. + Instead, we have to split the pixel vectors into vectors of shorts, + and do the averaging by hand. */ + + /* Split the pixel vectors into shorts */ + pix3hv = (vector unsigned short) vec_mergeh(zero, pix3v); + pix3lv = (vector unsigned short) vec_mergel(zero, pix3v); + pix3ihv = (vector unsigned short) vec_mergeh(zero, pix3iv); + pix3ilv = (vector unsigned short) vec_mergel(zero, pix3iv); + + /* Do the averaging on them */ + t3 = vec_add(pix3hv, pix3ihv); + t4 = vec_add(pix3lv, pix3ilv); + + avghv = vec_sr(vec_add(vec_add(t1, t3), two), two); + avglv = vec_sr(vec_add(vec_add(t2, t4), two), two); + + /* Pack the shorts back into a result */ + avgv = vec_pack(avghv, avglv); + + /* Calculate a sum of abs differences vector */ + t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv)); + + /* Add each 4 pixel group together and put 4 results into sad */ + sad = vec_sum4s(t5, sad); + + pix1 += line_size; + pix3 += line_size; + /* Transfer the calculated values for pix3 into pix2 */ + t1 = t3; + t2 = t4; + } + /* Sum up the four partial sums, and put the result into s */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + + return s; +} + +static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + vector unsigned char perm = vec_lvsl(0, pix2); + vector unsigned char t1, t2, t3,t4, t5; + vector unsigned int sad; + vector signed int sumdiffs; + + sad = (vector unsigned int)vec_splat_u32(0); + + + for (i = 0; i < h; i++) { + /* Read potentially unaligned pixels into t1 and t2 */ + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_ld(0, pix1); + t2 = vec_perm(pix2l, pix2r, perm); + + /* Calculate a sum of abs differences vector */ + t3 = vec_max(t1, t2); + t4 = vec_min(t1, t2); + t5 = vec_sub(t3, t4); + + /* Add each 4 pixel group together and put 4 results into sad */ + sad = vec_sum4s(t5, sad); + + pix1 += line_size; + pix2 += line_size; + } + + /* Sum up the four partial sums, and put the result into s */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + + return s; +} + +static int sad8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + const vector unsigned char permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; + vector unsigned char perm1 = vec_lvsl(0, pix1); + vector unsigned char perm2 = vec_lvsl(0, pix2); + vector unsigned char t1, t2, t3,t4, t5; + vector unsigned int sad; + vector signed int sumdiffs; + + sad = (vector unsigned int)vec_splat_u32(0); + + for (i = 0; i < h; i++) { + /* Read potentially unaligned pixels into t1 and t2 + Since we're reading 16 pixels, and actually only want 8, + mask out the last 8 pixels. The 0s don't change the sum. */ + vector unsigned char pix1l = vec_ld( 0, pix1); + vector unsigned char pix1r = vec_ld(15, pix1); + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear); + t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear); + + /* Calculate a sum of abs differences vector */ + t3 = vec_max(t1, t2); + t4 = vec_min(t1, t2); + t5 = vec_sub(t3, t4); + + /* Add each 4 pixel group together and put 4 results into sad */ + sad = vec_sum4s(t5, sad); + + pix1 += line_size; + pix2 += line_size; + } + + /* Sum up the four partial sums, and put the result into s */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + + return s; +} + +static int pix_norm1_altivec(uint8_t *pix, int line_size) +{ + int i; + int s; + const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + vector unsigned char perm = vec_lvsl(0, pix); + vector unsigned char pixv; + vector unsigned int sv; + vector signed int sum; + + sv = (vector unsigned int)vec_splat_u32(0); + + s = 0; + for (i = 0; i < 16; i++) { + /* Read in the potentially unaligned pixels */ + vector unsigned char pixl = vec_ld( 0, pix); + vector unsigned char pixr = vec_ld(15, pix); + pixv = vec_perm(pixl, pixr, perm); + + /* Square the values, and add them to our sum */ + sv = vec_msum(pixv, pixv, sv); + + pix += line_size; + } + /* Sum up the four partial sums, and put the result into s */ + sum = vec_sums((vector signed int) sv, (vector signed int) zero); + sum = vec_splat(sum, 3); + vec_ste(sum, 0, &s); + + return s; +} + +/** + * Sum of Squared Errors for a 8x8 block. + * AltiVec-enhanced. + * It's the sad8_altivec code above w/ squaring added. + */ +static int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + const vector unsigned char permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; + vector unsigned char perm1 = vec_lvsl(0, pix1); + vector unsigned char perm2 = vec_lvsl(0, pix2); + vector unsigned char t1, t2, t3,t4, t5; + vector unsigned int sum; + vector signed int sumsqr; + + sum = (vector unsigned int)vec_splat_u32(0); + + for (i = 0; i < h; i++) { + /* Read potentially unaligned pixels into t1 and t2 + Since we're reading 16 pixels, and actually only want 8, + mask out the last 8 pixels. The 0s don't change the sum. */ + vector unsigned char pix1l = vec_ld( 0, pix1); + vector unsigned char pix1r = vec_ld(15, pix1); + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear); + t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear); + + /* Since we want to use unsigned chars, we can take advantage + of the fact that abs(a-b)^2 = (a-b)^2. */ + + /* Calculate abs differences vector */ + t3 = vec_max(t1, t2); + t4 = vec_min(t1, t2); + t5 = vec_sub(t3, t4); + + /* Square the values and add them to our sum */ + sum = vec_msum(t5, t5, sum); + + pix1 += line_size; + pix2 += line_size; + } + + /* Sum up the four partial sums, and put the result into s */ + sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero); + sumsqr = vec_splat(sumsqr, 3); + vec_ste(sumsqr, 0, &s); + + return s; +} + +/** + * Sum of Squared Errors for a 16x16 block. + * AltiVec-enhanced. + * It's the sad16_altivec code above w/ squaring added. + */ +static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + int i; + int s; + const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + vector unsigned char perm = vec_lvsl(0, pix2); + vector unsigned char t1, t2, t3,t4, t5; + vector unsigned int sum; + vector signed int sumsqr; + + sum = (vector unsigned int)vec_splat_u32(0); + + for (i = 0; i < h; i++) { + /* Read potentially unaligned pixels into t1 and t2 */ + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_ld(0, pix1); + t2 = vec_perm(pix2l, pix2r, perm); + + /* Since we want to use unsigned chars, we can take advantage + of the fact that abs(a-b)^2 = (a-b)^2. */ + + /* Calculate abs differences vector */ + t3 = vec_max(t1, t2); + t4 = vec_min(t1, t2); + t5 = vec_sub(t3, t4); + + /* Square the values and add them to our sum */ + sum = vec_msum(t5, t5, sum); + + pix1 += line_size; + pix2 += line_size; + } + + /* Sum up the four partial sums, and put the result into s */ + sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero); + sumsqr = vec_splat(sumsqr, 3); + vec_ste(sumsqr, 0, &s); + + return s; +} + +static int pix_sum_altivec(uint8_t * pix, int line_size) +{ + const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); + vector unsigned char perm = vec_lvsl(0, pix); + vector unsigned char t1; + vector unsigned int sad; + vector signed int sumdiffs; + + int i; + int s; + + sad = (vector unsigned int)vec_splat_u32(0); + + for (i = 0; i < 16; i++) { + /* Read the potentially unaligned 16 pixels into t1 */ + vector unsigned char pixl = vec_ld( 0, pix); + vector unsigned char pixr = vec_ld(15, pix); + t1 = vec_perm(pixl, pixr, perm); + + /* Add each 4 pixel group together and put 4 results into sad */ + sad = vec_sum4s(t1, sad); + + pix += line_size; + } + + /* Sum up the four partial sums, and put the result into s */ + sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero); + sumdiffs = vec_splat(sumdiffs, 3); + vec_ste(sumdiffs, 0, &s); + + return s; +} + +static void get_pixels_altivec(int16_t *restrict block, const uint8_t *pixels, int line_size) +{ + int i; + vector unsigned char perm = vec_lvsl(0, pixels); + vector unsigned char bytes; + const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + vector signed short shorts; + + for (i = 0; i < 8; i++) { + // Read potentially unaligned pixels. + // We're reading 16 pixels, and actually only want 8, + // but we simply ignore the extras. + vector unsigned char pixl = vec_ld( 0, pixels); + vector unsigned char pixr = vec_ld(15, pixels); + bytes = vec_perm(pixl, pixr, perm); + + // convert the bytes into shorts + shorts = (vector signed short)vec_mergeh(zero, bytes); + + // save the data to the block, we assume the block is 16-byte aligned + vec_st(shorts, i*16, (vector signed short*)block); + + pixels += line_size; + } +} + +static void diff_pixels_altivec(int16_t *restrict block, const uint8_t *s1, + const uint8_t *s2, int stride) +{ + int i; + vector unsigned char perm1 = vec_lvsl(0, s1); + vector unsigned char perm2 = vec_lvsl(0, s2); + vector unsigned char bytes, pixl, pixr; + const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); + vector signed short shorts1, shorts2; + + for (i = 0; i < 4; i++) { + // Read potentially unaligned pixels + // We're reading 16 pixels, and actually only want 8, + // but we simply ignore the extras. + pixl = vec_ld( 0, s1); + pixr = vec_ld(15, s1); + bytes = vec_perm(pixl, pixr, perm1); + + // convert the bytes into shorts + shorts1 = (vector signed short)vec_mergeh(zero, bytes); + + // Do the same for the second block of pixels + pixl = vec_ld( 0, s2); + pixr = vec_ld(15, s2); + bytes = vec_perm(pixl, pixr, perm2); + + // convert the bytes into shorts + shorts2 = (vector signed short)vec_mergeh(zero, bytes); + + // Do the subtraction + shorts1 = vec_sub(shorts1, shorts2); + + // save the data to the block, we assume the block is 16-byte aligned + vec_st(shorts1, 0, (vector signed short*)block); + + s1 += stride; + s2 += stride; + block += 8; + + + // The code below is a copy of the code above... This is a manual + // unroll. + + // Read potentially unaligned pixels + // We're reading 16 pixels, and actually only want 8, + // but we simply ignore the extras. + pixl = vec_ld( 0, s1); + pixr = vec_ld(15, s1); + bytes = vec_perm(pixl, pixr, perm1); + + // convert the bytes into shorts + shorts1 = (vector signed short)vec_mergeh(zero, bytes); + + // Do the same for the second block of pixels + pixl = vec_ld( 0, s2); + pixr = vec_ld(15, s2); + bytes = vec_perm(pixl, pixr, perm2); + + // convert the bytes into shorts + shorts2 = (vector signed short)vec_mergeh(zero, bytes); + + // Do the subtraction + shorts1 = vec_sub(shorts1, shorts2); + + // save the data to the block, we assume the block is 16-byte aligned + vec_st(shorts1, 0, (vector signed short*)block); + + s1 += stride; + s2 += stride; + block += 8; + } +} + + +static void clear_block_altivec(int16_t *block) { + LOAD_ZERO; + vec_st(zero_s16v, 0, block); + vec_st(zero_s16v, 16, block); + vec_st(zero_s16v, 32, block); + vec_st(zero_s16v, 48, block); + vec_st(zero_s16v, 64, block); + vec_st(zero_s16v, 80, block); + vec_st(zero_s16v, 96, block); + vec_st(zero_s16v, 112, block); +} + + +static void add_bytes_altivec(uint8_t *dst, uint8_t *src, int w) { + register int i; + register vector unsigned char vdst, vsrc; + + /* dst and src are 16 bytes-aligned (guaranteed) */ + for (i = 0 ; (i + 15) < w ; i+=16) { + vdst = vec_ld(i, (unsigned char*)dst); + vsrc = vec_ld(i, (unsigned char*)src); + vdst = vec_add(vsrc, vdst); + vec_st(vdst, i, (unsigned char*)dst); + } + /* if w is not a multiple of 16 */ + for (; (i < w) ; i++) { + dst[i] = src[i]; + } +} + +static int hadamard8_diff8x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){ + int sum; + register const vector unsigned char vzero = + (const vector unsigned char)vec_splat_u8(0); + register vector signed short temp0, temp1, temp2, temp3, temp4, + temp5, temp6, temp7; + { + register const vector signed short vprod1 =(const vector signed short) + { 1,-1, 1,-1, 1,-1, 1,-1 }; + register const vector signed short vprod2 =(const vector signed short) + { 1, 1,-1,-1, 1, 1,-1,-1 }; + register const vector signed short vprod3 =(const vector signed short) + { 1, 1, 1, 1,-1,-1,-1,-1 }; + register const vector unsigned char perm1 = (const vector unsigned char) + {0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, + 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D}; + register const vector unsigned char perm2 = (const vector unsigned char) + {0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, + 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B}; + register const vector unsigned char perm3 = (const vector unsigned char) + {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + +#define ONEITERBUTTERFLY(i, res) \ + { \ + register vector unsigned char src1, src2, srcO; \ + register vector unsigned char dst1, dst2, dstO; \ + register vector signed short srcV, dstV; \ + register vector signed short but0, but1, but2, op1, op2, op3; \ + src1 = vec_ld(stride * i, src); \ + src2 = vec_ld((stride * i) + 15, src); \ + srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src)); \ + dst1 = vec_ld(stride * i, dst); \ + dst2 = vec_ld((stride * i) + 15, dst); \ + dstO = vec_perm(dst1, dst2, vec_lvsl(stride * i, dst)); \ + /* promote the unsigned chars to signed shorts */ \ + /* we're in the 8x8 function, we only care for the first 8 */ \ + srcV = (vector signed short)vec_mergeh((vector signed char)vzero, \ + (vector signed char)srcO); \ + dstV = (vector signed short)vec_mergeh((vector signed char)vzero, \ + (vector signed char)dstO); \ + /* subtractions inside the first butterfly */ \ + but0 = vec_sub(srcV, dstV); \ + op1 = vec_perm(but0, but0, perm1); \ + but1 = vec_mladd(but0, vprod1, op1); \ + op2 = vec_perm(but1, but1, perm2); \ + but2 = vec_mladd(but1, vprod2, op2); \ + op3 = vec_perm(but2, but2, perm3); \ + res = vec_mladd(but2, vprod3, op3); \ + } + ONEITERBUTTERFLY(0, temp0); + ONEITERBUTTERFLY(1, temp1); + ONEITERBUTTERFLY(2, temp2); + ONEITERBUTTERFLY(3, temp3); + ONEITERBUTTERFLY(4, temp4); + ONEITERBUTTERFLY(5, temp5); + ONEITERBUTTERFLY(6, temp6); + ONEITERBUTTERFLY(7, temp7); + } +#undef ONEITERBUTTERFLY + { + register vector signed int vsum; + register vector signed short line0 = vec_add(temp0, temp1); + register vector signed short line1 = vec_sub(temp0, temp1); + register vector signed short line2 = vec_add(temp2, temp3); + register vector signed short line3 = vec_sub(temp2, temp3); + register vector signed short line4 = vec_add(temp4, temp5); + register vector signed short line5 = vec_sub(temp4, temp5); + register vector signed short line6 = vec_add(temp6, temp7); + register vector signed short line7 = vec_sub(temp6, temp7); + + register vector signed short line0B = vec_add(line0, line2); + register vector signed short line2B = vec_sub(line0, line2); + register vector signed short line1B = vec_add(line1, line3); + register vector signed short line3B = vec_sub(line1, line3); + register vector signed short line4B = vec_add(line4, line6); + register vector signed short line6B = vec_sub(line4, line6); + register vector signed short line5B = vec_add(line5, line7); + register vector signed short line7B = vec_sub(line5, line7); + + register vector signed short line0C = vec_add(line0B, line4B); + register vector signed short line4C = vec_sub(line0B, line4B); + register vector signed short line1C = vec_add(line1B, line5B); + register vector signed short line5C = vec_sub(line1B, line5B); + register vector signed short line2C = vec_add(line2B, line6B); + register vector signed short line6C = vec_sub(line2B, line6B); + register vector signed short line3C = vec_add(line3B, line7B); + register vector signed short line7C = vec_sub(line3B, line7B); + + vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0)); + vsum = vec_sum4s(vec_abs(line1C), vsum); + vsum = vec_sum4s(vec_abs(line2C), vsum); + vsum = vec_sum4s(vec_abs(line3C), vsum); + vsum = vec_sum4s(vec_abs(line4C), vsum); + vsum = vec_sum4s(vec_abs(line5C), vsum); + vsum = vec_sum4s(vec_abs(line6C), vsum); + vsum = vec_sum4s(vec_abs(line7C), vsum); + vsum = vec_sums(vsum, (vector signed int)vzero); + vsum = vec_splat(vsum, 3); + vec_ste(vsum, 0, &sum); + } + return sum; +} + +/* +16x8 works with 16 elements; it allows to avoid replicating loads, and +give the compiler more rooms for scheduling. It's only used from +inside hadamard8_diff16_altivec. + +Unfortunately, it seems gcc-3.3 is a bit dumb, and the compiled code has a LOT +of spill code, it seems gcc (unlike xlc) cannot keep everything in registers +by itself. The following code include hand-made registers allocation. It's not +clean, but on a 7450 the resulting code is much faster (best case fall from +700+ cycles to 550). + +xlc doesn't add spill code, but it doesn't know how to schedule for the 7450, +and its code isn't much faster than gcc-3.3 on the 7450 (but uses 25% less +instructions...) + +On the 970, the hand-made RA is still a win (around 690 vs. around 780), but +xlc goes to around 660 on the regular C code... +*/ + +static int hadamard8_diff16x8_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h) { + int sum; + register vector signed short + temp0 __asm__ ("v0"), + temp1 __asm__ ("v1"), + temp2 __asm__ ("v2"), + temp3 __asm__ ("v3"), + temp4 __asm__ ("v4"), + temp5 __asm__ ("v5"), + temp6 __asm__ ("v6"), + temp7 __asm__ ("v7"); + register vector signed short + temp0S __asm__ ("v8"), + temp1S __asm__ ("v9"), + temp2S __asm__ ("v10"), + temp3S __asm__ ("v11"), + temp4S __asm__ ("v12"), + temp5S __asm__ ("v13"), + temp6S __asm__ ("v14"), + temp7S __asm__ ("v15"); + register const vector unsigned char vzero __asm__ ("v31") = + (const vector unsigned char)vec_splat_u8(0); + { + register const vector signed short vprod1 __asm__ ("v16") = + (const vector signed short){ 1,-1, 1,-1, 1,-1, 1,-1 }; + register const vector signed short vprod2 __asm__ ("v17") = + (const vector signed short){ 1, 1,-1,-1, 1, 1,-1,-1 }; + register const vector signed short vprod3 __asm__ ("v18") = + (const vector signed short){ 1, 1, 1, 1,-1,-1,-1,-1 }; + register const vector unsigned char perm1 __asm__ ("v19") = + (const vector unsigned char) + {0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, + 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D}; + register const vector unsigned char perm2 __asm__ ("v20") = + (const vector unsigned char) + {0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, + 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B}; + register const vector unsigned char perm3 __asm__ ("v21") = + (const vector unsigned char) + {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; + +#define ONEITERBUTTERFLY(i, res1, res2) \ + { \ + register vector unsigned char src1 __asm__ ("v22"), \ + src2 __asm__ ("v23"), \ + dst1 __asm__ ("v24"), \ + dst2 __asm__ ("v25"), \ + srcO __asm__ ("v22"), \ + dstO __asm__ ("v23"); \ + \ + register vector signed short srcV __asm__ ("v24"), \ + dstV __asm__ ("v25"), \ + srcW __asm__ ("v26"), \ + dstW __asm__ ("v27"), \ + but0 __asm__ ("v28"), \ + but0S __asm__ ("v29"), \ + op1 __asm__ ("v30"), \ + but1 __asm__ ("v22"), \ + op1S __asm__ ("v23"), \ + but1S __asm__ ("v24"), \ + op2 __asm__ ("v25"), \ + but2 __asm__ ("v26"), \ + op2S __asm__ ("v27"), \ + but2S __asm__ ("v28"), \ + op3 __asm__ ("v29"), \ + op3S __asm__ ("v30"); \ + \ + src1 = vec_ld(stride * i, src); \ + src2 = vec_ld((stride * i) + 16, src); \ + srcO = vec_perm(src1, src2, vec_lvsl(stride * i, src)); \ + dst1 = vec_ld(stride * i, dst); \ + dst2 = vec_ld((stride * i) + 16, dst); \ + dstO = vec_perm(dst1, dst2, vec_lvsl(stride * i, dst)); \ + /* promote the unsigned chars to signed shorts */ \ + srcV = (vector signed short)vec_mergeh((vector signed char)vzero, \ + (vector signed char)srcO); \ + dstV = (vector signed short)vec_mergeh((vector signed char)vzero, \ + (vector signed char)dstO); \ + srcW = (vector signed short)vec_mergel((vector signed char)vzero, \ + (vector signed char)srcO); \ + dstW = (vector signed short)vec_mergel((vector signed char)vzero, \ + (vector signed char)dstO); \ + /* subtractions inside the first butterfly */ \ + but0 = vec_sub(srcV, dstV); \ + but0S = vec_sub(srcW, dstW); \ + op1 = vec_perm(but0, but0, perm1); \ + but1 = vec_mladd(but0, vprod1, op1); \ + op1S = vec_perm(but0S, but0S, perm1); \ + but1S = vec_mladd(but0S, vprod1, op1S); \ + op2 = vec_perm(but1, but1, perm2); \ + but2 = vec_mladd(but1, vprod2, op2); \ + op2S = vec_perm(but1S, but1S, perm2); \ + but2S = vec_mladd(but1S, vprod2, op2S); \ + op3 = vec_perm(but2, but2, perm3); \ + res1 = vec_mladd(but2, vprod3, op3); \ + op3S = vec_perm(but2S, but2S, perm3); \ + res2 = vec_mladd(but2S, vprod3, op3S); \ + } + ONEITERBUTTERFLY(0, temp0, temp0S); + ONEITERBUTTERFLY(1, temp1, temp1S); + ONEITERBUTTERFLY(2, temp2, temp2S); + ONEITERBUTTERFLY(3, temp3, temp3S); + ONEITERBUTTERFLY(4, temp4, temp4S); + ONEITERBUTTERFLY(5, temp5, temp5S); + ONEITERBUTTERFLY(6, temp6, temp6S); + ONEITERBUTTERFLY(7, temp7, temp7S); + } +#undef ONEITERBUTTERFLY + { + register vector signed int vsum; + register vector signed short line0S, line1S, line2S, line3S, line4S, + line5S, line6S, line7S, line0BS,line2BS, + line1BS,line3BS,line4BS,line6BS,line5BS, + line7BS,line0CS,line4CS,line1CS,line5CS, + line2CS,line6CS,line3CS,line7CS; + + register vector signed short line0 = vec_add(temp0, temp1); + register vector signed short line1 = vec_sub(temp0, temp1); + register vector signed short line2 = vec_add(temp2, temp3); + register vector signed short line3 = vec_sub(temp2, temp3); + register vector signed short line4 = vec_add(temp4, temp5); + register vector signed short line5 = vec_sub(temp4, temp5); + register vector signed short line6 = vec_add(temp6, temp7); + register vector signed short line7 = vec_sub(temp6, temp7); + + register vector signed short line0B = vec_add(line0, line2); + register vector signed short line2B = vec_sub(line0, line2); + register vector signed short line1B = vec_add(line1, line3); + register vector signed short line3B = vec_sub(line1, line3); + register vector signed short line4B = vec_add(line4, line6); + register vector signed short line6B = vec_sub(line4, line6); + register vector signed short line5B = vec_add(line5, line7); + register vector signed short line7B = vec_sub(line5, line7); + + register vector signed short line0C = vec_add(line0B, line4B); + register vector signed short line4C = vec_sub(line0B, line4B); + register vector signed short line1C = vec_add(line1B, line5B); + register vector signed short line5C = vec_sub(line1B, line5B); + register vector signed short line2C = vec_add(line2B, line6B); + register vector signed short line6C = vec_sub(line2B, line6B); + register vector signed short line3C = vec_add(line3B, line7B); + register vector signed short line7C = vec_sub(line3B, line7B); + + vsum = vec_sum4s(vec_abs(line0C), vec_splat_s32(0)); + vsum = vec_sum4s(vec_abs(line1C), vsum); + vsum = vec_sum4s(vec_abs(line2C), vsum); + vsum = vec_sum4s(vec_abs(line3C), vsum); + vsum = vec_sum4s(vec_abs(line4C), vsum); + vsum = vec_sum4s(vec_abs(line5C), vsum); + vsum = vec_sum4s(vec_abs(line6C), vsum); + vsum = vec_sum4s(vec_abs(line7C), vsum); + + line0S = vec_add(temp0S, temp1S); + line1S = vec_sub(temp0S, temp1S); + line2S = vec_add(temp2S, temp3S); + line3S = vec_sub(temp2S, temp3S); + line4S = vec_add(temp4S, temp5S); + line5S = vec_sub(temp4S, temp5S); + line6S = vec_add(temp6S, temp7S); + line7S = vec_sub(temp6S, temp7S); + + line0BS = vec_add(line0S, line2S); + line2BS = vec_sub(line0S, line2S); + line1BS = vec_add(line1S, line3S); + line3BS = vec_sub(line1S, line3S); + line4BS = vec_add(line4S, line6S); + line6BS = vec_sub(line4S, line6S); + line5BS = vec_add(line5S, line7S); + line7BS = vec_sub(line5S, line7S); + + line0CS = vec_add(line0BS, line4BS); + line4CS = vec_sub(line0BS, line4BS); + line1CS = vec_add(line1BS, line5BS); + line5CS = vec_sub(line1BS, line5BS); + line2CS = vec_add(line2BS, line6BS); + line6CS = vec_sub(line2BS, line6BS); + line3CS = vec_add(line3BS, line7BS); + line7CS = vec_sub(line3BS, line7BS); + + vsum = vec_sum4s(vec_abs(line0CS), vsum); + vsum = vec_sum4s(vec_abs(line1CS), vsum); + vsum = vec_sum4s(vec_abs(line2CS), vsum); + vsum = vec_sum4s(vec_abs(line3CS), vsum); + vsum = vec_sum4s(vec_abs(line4CS), vsum); + vsum = vec_sum4s(vec_abs(line5CS), vsum); + vsum = vec_sum4s(vec_abs(line6CS), vsum); + vsum = vec_sum4s(vec_abs(line7CS), vsum); + vsum = vec_sums(vsum, (vector signed int)vzero); + vsum = vec_splat(vsum, 3); + vec_ste(vsum, 0, &sum); + } + return sum; +} + +static int hadamard8_diff16_altivec(/*MpegEncContext*/ void *s, uint8_t *dst, uint8_t *src, int stride, int h){ + int score; + score = hadamard8_diff16x8_altivec(s, dst, src, stride, 8); + if (h==16) { + dst += 8*stride; + src += 8*stride; + score += hadamard8_diff16x8_altivec(s, dst, src, stride, 8); + } + return score; +} + +av_cold void ff_dsputil_init_altivec(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + + c->pix_abs[0][1] = sad16_x2_altivec; + c->pix_abs[0][2] = sad16_y2_altivec; + c->pix_abs[0][3] = sad16_xy2_altivec; + c->pix_abs[0][0] = sad16_altivec; + c->pix_abs[1][0] = sad8_altivec; + c->sad[0]= sad16_altivec; + c->sad[1]= sad8_altivec; + c->pix_norm1 = pix_norm1_altivec; + c->sse[1]= sse8_altivec; + c->sse[0]= sse16_altivec; + c->pix_sum = pix_sum_altivec; + c->diff_pixels = diff_pixels_altivec; + c->add_bytes= add_bytes_altivec; + if (!high_bit_depth) { + c->get_pixels = get_pixels_altivec; + c->clear_block = clear_block_altivec; + } + + c->hadamard8_diff[0] = hadamard8_diff16_altivec; + c->hadamard8_diff[1] = hadamard8_diff8x8_altivec; +} diff --git a/ffmpeg/libavcodec/ppc/dsputil_altivec.h b/ffmpeg/libavcodec/ppc/dsputil_altivec.h new file mode 100644 index 0000000..0e769ab --- /dev/null +++ b/ffmpeg/libavcodec/ppc/dsputil_altivec.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * 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 + */ + +#ifndef AVCODEC_PPC_DSPUTIL_ALTIVEC_H +#define AVCODEC_PPC_DSPUTIL_ALTIVEC_H + +#include +#include "libavcodec/dsputil.h" + +void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); + +void ff_avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); + +void ff_fdct_altivec(int16_t *block); +void ff_gmc1_altivec(uint8_t *dst, uint8_t *src, int stride, int h, + int x16, int y16, int rounder); +void ff_idct_put_altivec(uint8_t *dest, int line_size, int16_t *block); +void ff_idct_add_altivec(uint8_t *dest, int line_size, int16_t *block); + +void ff_dsputil_init_altivec(DSPContext* c, AVCodecContext *avctx); +void ff_float_init_altivec(DSPContext* c, AVCodecContext *avctx); +void ff_int_init_altivec(DSPContext* c, AVCodecContext *avctx); + +#endif /* AVCODEC_PPC_DSPUTIL_ALTIVEC_H */ diff --git a/ffmpeg/libavcodec/ppc/dsputil_ppc.c b/ffmpeg/libavcodec/ppc/dsputil_ppc.c new file mode 100644 index 0000000..6112b0c --- /dev/null +++ b/ffmpeg/libavcodec/ppc/dsputil_ppc.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "dsputil_altivec.h" + +/* ***** WARNING ***** WARNING ***** WARNING ***** */ +/* +clear_blocks_dcbz32_ppc will not work properly on PowerPC processors with a +cache line size not equal to 32 bytes. +Fortunately all processor used by Apple up to at least the 7450 (aka second +generation G4) use 32 bytes cache line. +This is due to the use of the 'dcbz' instruction. It simply clear to zero a +single cache line, so you need to know the cache line size to use it ! +It's absurd, but it's fast... + +update 24/06/2003 : Apple released yesterday the G5, with a PPC970. cache line +size: 128 bytes. Oups. +The semantic of dcbz was changed, it always clear 32 bytes. so the function +below will work, but will be slow. So I fixed check_dcbz_effect to use dcbzl, +which is defined to clear a cache line (as dcbz before). So we still can +distinguish, and use dcbz (32 bytes) or dcbzl (one cache line) as required. + +see +and +*/ +static void clear_blocks_dcbz32_ppc(int16_t *blocks) +{ + register int misal = ((unsigned long)blocks & 0x00000010); + register int i = 0; + if (misal) { + ((unsigned long*)blocks)[0] = 0L; + ((unsigned long*)blocks)[1] = 0L; + ((unsigned long*)blocks)[2] = 0L; + ((unsigned long*)blocks)[3] = 0L; + i += 16; + } + for ( ; i < sizeof(int16_t)*6*64-31 ; i += 32) { + __asm__ volatile("dcbz %0,%1" : : "b" (blocks), "r" (i) : "memory"); + } + if (misal) { + ((unsigned long*)blocks)[188] = 0L; + ((unsigned long*)blocks)[189] = 0L; + ((unsigned long*)blocks)[190] = 0L; + ((unsigned long*)blocks)[191] = 0L; + i += 16; + } +} + +/* same as above, when dcbzl clear a whole 128B cache line + i.e. the PPC970 aka G5 */ +#if HAVE_DCBZL +static void clear_blocks_dcbz128_ppc(int16_t *blocks) +{ + register int misal = ((unsigned long)blocks & 0x0000007f); + register int i = 0; + if (misal) { + // we could probably also optimize this case, + // but there's not much point as the machines + // aren't available yet (2003-06-26) + memset(blocks, 0, sizeof(int16_t)*6*64); + } + else + for ( ; i < sizeof(int16_t)*6*64 ; i += 128) { + __asm__ volatile("dcbzl %0,%1" : : "b" (blocks), "r" (i) : "memory"); + } +} +#else +static void clear_blocks_dcbz128_ppc(int16_t *blocks) +{ + memset(blocks, 0, sizeof(int16_t)*6*64); +} +#endif + +#if HAVE_DCBZL +/* check dcbz report how many bytes are set to 0 by dcbz */ +/* update 24/06/2003 : replace dcbz by dcbzl to get + the intended effect (Apple "fixed" dcbz) + unfortunately this cannot be used unless the assembler + knows about dcbzl ... */ +static long check_dcbzl_effect(void) +{ + register char *fakedata = av_malloc(1024); + register char *fakedata_middle; + register long zero = 0; + register long i = 0; + long count = 0; + + if (!fakedata) { + return 0L; + } + + fakedata_middle = (fakedata + 512); + + memset(fakedata, 0xFF, 1024); + + /* below the constraint "b" seems to mean "Address base register" + in gcc-3.3 / RS/6000 speaks. seems to avoid using r0, so.... */ + __asm__ volatile("dcbzl %0, %1" : : "b" (fakedata_middle), "r" (zero)); + + for (i = 0; i < 1024 ; i ++) { + if (fakedata[i] == (char)0) + count++; + } + + av_free(fakedata); + + return count; +} +#else +static long check_dcbzl_effect(void) +{ + return 0; +} +#endif + +av_cold void ff_dsputil_init_ppc(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + int mm_flags = av_get_cpu_flags(); + + // Common optimizations whether AltiVec is available or not + if (!high_bit_depth) { + switch (check_dcbzl_effect()) { + case 32: + c->clear_blocks = clear_blocks_dcbz32_ppc; + break; + case 128: + c->clear_blocks = clear_blocks_dcbz128_ppc; + break; + default: + break; + } + } + +#if HAVE_ALTIVEC + if (mm_flags & AV_CPU_FLAG_ALTIVEC) { + ff_dsputil_init_altivec(c, avctx); + ff_int_init_altivec(c, avctx); + c->gmc1 = ff_gmc1_altivec; + +#if CONFIG_ENCODERS + if (avctx->bits_per_raw_sample <= 8 && + (avctx->dct_algo == FF_DCT_AUTO || + avctx->dct_algo == FF_DCT_ALTIVEC)) { + c->fdct = ff_fdct_altivec; + } +#endif //CONFIG_ENCODERS + + if (avctx->lowres == 0 && avctx->bits_per_raw_sample <= 8) { + if ((avctx->idct_algo == FF_IDCT_AUTO) || + (avctx->idct_algo == FF_IDCT_ALTIVEC)) { + c->idct_put = ff_idct_put_altivec; + c->idct_add = ff_idct_add_altivec; + c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; + } + } + + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/ffmpeg/libavcodec/ppc/fdct_altivec.c b/ffmpeg/libavcodec/ppc/fdct_altivec.c new file mode 100644 index 0000000..acab127 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/fdct_altivec.c @@ -0,0 +1,462 @@ +/* + * Copyright (C) 2003 James Klicman + * + * 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 "config.h" +#if HAVE_ALTIVEC_H +#include +#endif +#include "libavutil/common.h" +#include "dsputil_altivec.h" + +#define vs16(v) ((vector signed short)(v)) +#define vs32(v) ((vector signed int)(v)) +#define vu8(v) ((vector unsigned char)(v)) +#define vu16(v) ((vector unsigned short)(v)) +#define vu32(v) ((vector unsigned int)(v)) + + +#define C1 0.98078525066375732421875000 /* cos(1*PI/16) */ +#define C2 0.92387950420379638671875000 /* cos(2*PI/16) */ +#define C3 0.83146959543228149414062500 /* cos(3*PI/16) */ +#define C4 0.70710676908493041992187500 /* cos(4*PI/16) */ +#define C5 0.55557024478912353515625000 /* cos(5*PI/16) */ +#define C6 0.38268342614173889160156250 /* cos(6*PI/16) */ +#define C7 0.19509032368659973144531250 /* cos(7*PI/16) */ +#define SQRT_2 1.41421353816986083984375000 /* sqrt(2) */ + + +#define W0 -(2 * C2) +#define W1 (2 * C6) +#define W2 (SQRT_2 * C6) +#define W3 (SQRT_2 * C3) +#define W4 (SQRT_2 * (-C1 + C3 + C5 - C7)) +#define W5 (SQRT_2 * ( C1 + C3 - C5 + C7)) +#define W6 (SQRT_2 * ( C1 + C3 + C5 - C7)) +#define W7 (SQRT_2 * ( C1 + C3 - C5 - C7)) +#define W8 (SQRT_2 * ( C7 - C3)) +#define W9 (SQRT_2 * (-C1 - C3)) +#define WA (SQRT_2 * (-C3 - C5)) +#define WB (SQRT_2 * ( C5 - C3)) + + +static vector float fdctconsts[3] = { + { W0, W1, W2, W3 }, + { W4, W5, W6, W7 }, + { W8, W9, WA, WB } +}; + +#define LD_W0 vec_splat(cnsts0, 0) +#define LD_W1 vec_splat(cnsts0, 1) +#define LD_W2 vec_splat(cnsts0, 2) +#define LD_W3 vec_splat(cnsts0, 3) +#define LD_W4 vec_splat(cnsts1, 0) +#define LD_W5 vec_splat(cnsts1, 1) +#define LD_W6 vec_splat(cnsts1, 2) +#define LD_W7 vec_splat(cnsts1, 3) +#define LD_W8 vec_splat(cnsts2, 0) +#define LD_W9 vec_splat(cnsts2, 1) +#define LD_WA vec_splat(cnsts2, 2) +#define LD_WB vec_splat(cnsts2, 3) + + +#define FDCTROW(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ + x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ + x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ + x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ + x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ + x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ + x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ + x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ + x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ + \ + b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ + b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ + b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ + b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ + \ + b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ + b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ + b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ + cnst = LD_W2; \ + b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ + cnst = LD_W1; \ + b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ + cnst = LD_W0; \ + b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ + \ + x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ + x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ + x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ + x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ + x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ + cnst = LD_W3; \ + x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ + \ + cnst = LD_W8; \ + x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ + cnst = LD_W9; \ + x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ + cnst = LD_WA; \ + x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ + cnst = LD_WB; \ + x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ + \ + cnst = LD_W4; \ + b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ + cnst = LD_W5; \ + b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ + cnst = LD_W6; \ + b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ + cnst = LD_W7; \ + b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ + \ + b7 = vec_add(b7, x2); /* b7 = b7 + x2; */ \ + b5 = vec_add(b5, x3); /* b5 = b5 + x3; */ \ + b3 = vec_add(b3, x2); /* b3 = b3 + x2; */ \ + b1 = vec_add(b1, x3); /* b1 = b1 + x3; */ \ + /* }}} */ + +#define FDCTCOL(b0,b1,b2,b3,b4,b5,b6,b7) /* {{{ */ \ + x0 = vec_add(b0, b7); /* x0 = b0 + b7; */ \ + x7 = vec_sub(b0, b7); /* x7 = b0 - b7; */ \ + x1 = vec_add(b1, b6); /* x1 = b1 + b6; */ \ + x6 = vec_sub(b1, b6); /* x6 = b1 - b6; */ \ + x2 = vec_add(b2, b5); /* x2 = b2 + b5; */ \ + x5 = vec_sub(b2, b5); /* x5 = b2 - b5; */ \ + x3 = vec_add(b3, b4); /* x3 = b3 + b4; */ \ + x4 = vec_sub(b3, b4); /* x4 = b3 - b4; */ \ + \ + b7 = vec_add(x0, x3); /* b7 = x0 + x3; */ \ + b1 = vec_add(x1, x2); /* b1 = x1 + x2; */ \ + b0 = vec_add(b7, b1); /* b0 = b7 + b1; */ \ + b4 = vec_sub(b7, b1); /* b4 = b7 - b1; */ \ + \ + b2 = vec_sub(x0, x3); /* b2 = x0 - x3; */ \ + b6 = vec_sub(x1, x2); /* b6 = x1 - x2; */ \ + b5 = vec_add(b6, b2); /* b5 = b6 + b2; */ \ + cnst = LD_W2; \ + b5 = vec_madd(cnst, b5, mzero); /* b5 = b5 * W2; */ \ + cnst = LD_W1; \ + b2 = vec_madd(cnst, b2, b5); /* b2 = b5 + b2 * W1; */ \ + cnst = LD_W0; \ + b6 = vec_madd(cnst, b6, b5); /* b6 = b5 + b6 * W0; */ \ + \ + x0 = vec_add(x4, x7); /* x0 = x4 + x7; */ \ + x1 = vec_add(x5, x6); /* x1 = x5 + x6; */ \ + x2 = vec_add(x4, x6); /* x2 = x4 + x6; */ \ + x3 = vec_add(x5, x7); /* x3 = x5 + x7; */ \ + x8 = vec_add(x2, x3); /* x8 = x2 + x3; */ \ + cnst = LD_W3; \ + x8 = vec_madd(cnst, x8, mzero); /* x8 = x8 * W3; */ \ + \ + cnst = LD_W8; \ + x0 = vec_madd(cnst, x0, mzero); /* x0 *= W8; */ \ + cnst = LD_W9; \ + x1 = vec_madd(cnst, x1, mzero); /* x1 *= W9; */ \ + cnst = LD_WA; \ + x2 = vec_madd(cnst, x2, x8); /* x2 = x2 * WA + x8; */ \ + cnst = LD_WB; \ + x3 = vec_madd(cnst, x3, x8); /* x3 = x3 * WB + x8; */ \ + \ + cnst = LD_W4; \ + b7 = vec_madd(cnst, x4, x0); /* b7 = x4 * W4 + x0; */ \ + cnst = LD_W5; \ + b5 = vec_madd(cnst, x5, x1); /* b5 = x5 * W5 + x1; */ \ + cnst = LD_W6; \ + b3 = vec_madd(cnst, x6, x1); /* b3 = x6 * W6 + x1; */ \ + cnst = LD_W7; \ + b1 = vec_madd(cnst, x7, x0); /* b1 = x7 * W7 + x0; */ \ + \ + b7 = vec_add(b7, x2); /* b7 += x2; */ \ + b5 = vec_add(b5, x3); /* b5 += x3; */ \ + b3 = vec_add(b3, x2); /* b3 += x2; */ \ + b1 = vec_add(b1, x3); /* b1 += x3; */ \ + /* }}} */ + + + +/* two dimensional discrete cosine transform */ + +void ff_fdct_altivec(int16_t *block) +{ + vector signed short *bp; + vector float *cp; + vector float b00, b10, b20, b30, b40, b50, b60, b70; + vector float b01, b11, b21, b31, b41, b51, b61, b71; + vector float mzero, cnst, cnsts0, cnsts1, cnsts2; + vector float x0, x1, x2, x3, x4, x5, x6, x7, x8; + + /* setup constants {{{ */ + /* mzero = -0.0 */ + mzero = ((vector float)vec_splat_u32(-1)); + mzero = ((vector float)vec_sl(vu32(mzero), vu32(mzero))); + cp = fdctconsts; + cnsts0 = vec_ld(0, cp); cp++; + cnsts1 = vec_ld(0, cp); cp++; + cnsts2 = vec_ld(0, cp); + /* }}} */ + + + /* 8x8 matrix transpose (vector short[8]) {{{ */ +#define MERGE_S16(hl,a,b) vec_merge##hl(vs16(a), vs16(b)) + + bp = (vector signed short*)block; + b00 = ((vector float)vec_ld(0, bp)); + b40 = ((vector float)vec_ld(16*4, bp)); + b01 = ((vector float)MERGE_S16(h, b00, b40)); + b11 = ((vector float)MERGE_S16(l, b00, b40)); + bp++; + b10 = ((vector float)vec_ld(0, bp)); + b50 = ((vector float)vec_ld(16*4, bp)); + b21 = ((vector float)MERGE_S16(h, b10, b50)); + b31 = ((vector float)MERGE_S16(l, b10, b50)); + bp++; + b20 = ((vector float)vec_ld(0, bp)); + b60 = ((vector float)vec_ld(16*4, bp)); + b41 = ((vector float)MERGE_S16(h, b20, b60)); + b51 = ((vector float)MERGE_S16(l, b20, b60)); + bp++; + b30 = ((vector float)vec_ld(0, bp)); + b70 = ((vector float)vec_ld(16*4, bp)); + b61 = ((vector float)MERGE_S16(h, b30, b70)); + b71 = ((vector float)MERGE_S16(l, b30, b70)); + + x0 = ((vector float)MERGE_S16(h, b01, b41)); + x1 = ((vector float)MERGE_S16(l, b01, b41)); + x2 = ((vector float)MERGE_S16(h, b11, b51)); + x3 = ((vector float)MERGE_S16(l, b11, b51)); + x4 = ((vector float)MERGE_S16(h, b21, b61)); + x5 = ((vector float)MERGE_S16(l, b21, b61)); + x6 = ((vector float)MERGE_S16(h, b31, b71)); + x7 = ((vector float)MERGE_S16(l, b31, b71)); + + b00 = ((vector float)MERGE_S16(h, x0, x4)); + b10 = ((vector float)MERGE_S16(l, x0, x4)); + b20 = ((vector float)MERGE_S16(h, x1, x5)); + b30 = ((vector float)MERGE_S16(l, x1, x5)); + b40 = ((vector float)MERGE_S16(h, x2, x6)); + b50 = ((vector float)MERGE_S16(l, x2, x6)); + b60 = ((vector float)MERGE_S16(h, x3, x7)); + b70 = ((vector float)MERGE_S16(l, x3, x7)); + +#undef MERGE_S16 + /* }}} */ + + +/* Some of the initial calculations can be done as vector short before + * conversion to vector float. The following code section takes advantage + * of this. + */ + /* fdct rows {{{ */ + x0 = ((vector float)vec_add(vs16(b00), vs16(b70))); + x7 = ((vector float)vec_sub(vs16(b00), vs16(b70))); + x1 = ((vector float)vec_add(vs16(b10), vs16(b60))); + x6 = ((vector float)vec_sub(vs16(b10), vs16(b60))); + x2 = ((vector float)vec_add(vs16(b20), vs16(b50))); + x5 = ((vector float)vec_sub(vs16(b20), vs16(b50))); + x3 = ((vector float)vec_add(vs16(b30), vs16(b40))); + x4 = ((vector float)vec_sub(vs16(b30), vs16(b40))); + + b70 = ((vector float)vec_add(vs16(x0), vs16(x3))); + b10 = ((vector float)vec_add(vs16(x1), vs16(x2))); + + b00 = ((vector float)vec_add(vs16(b70), vs16(b10))); + b40 = ((vector float)vec_sub(vs16(b70), vs16(b10))); + +#define CTF0(n) \ + b##n##1 = ((vector float)vec_unpackl(vs16(b##n##0))); \ + b##n##0 = ((vector float)vec_unpackh(vs16(b##n##0))); \ + b##n##1 = vec_ctf(vs32(b##n##1), 0); \ + b##n##0 = vec_ctf(vs32(b##n##0), 0); + + CTF0(0); + CTF0(4); + + b20 = ((vector float)vec_sub(vs16(x0), vs16(x3))); + b60 = ((vector float)vec_sub(vs16(x1), vs16(x2))); + + CTF0(2); + CTF0(6); + +#undef CTF0 + + x0 = vec_add(b60, b20); + x1 = vec_add(b61, b21); + + cnst = LD_W2; + x0 = vec_madd(cnst, x0, mzero); + x1 = vec_madd(cnst, x1, mzero); + cnst = LD_W1; + b20 = vec_madd(cnst, b20, x0); + b21 = vec_madd(cnst, b21, x1); + cnst = LD_W0; + b60 = vec_madd(cnst, b60, x0); + b61 = vec_madd(cnst, b61, x1); + +#define CTFX(x,b) \ + b##0 = ((vector float)vec_unpackh(vs16(x))); \ + b##1 = ((vector float)vec_unpackl(vs16(x))); \ + b##0 = vec_ctf(vs32(b##0), 0); \ + b##1 = vec_ctf(vs32(b##1), 0); \ + + CTFX(x4, b7); + CTFX(x5, b5); + CTFX(x6, b3); + CTFX(x7, b1); + +#undef CTFX + + + x0 = vec_add(b70, b10); + x1 = vec_add(b50, b30); + x2 = vec_add(b70, b30); + x3 = vec_add(b50, b10); + x8 = vec_add(x2, x3); + cnst = LD_W3; + x8 = vec_madd(cnst, x8, mzero); + + cnst = LD_W8; + x0 = vec_madd(cnst, x0, mzero); + cnst = LD_W9; + x1 = vec_madd(cnst, x1, mzero); + cnst = LD_WA; + x2 = vec_madd(cnst, x2, x8); + cnst = LD_WB; + x3 = vec_madd(cnst, x3, x8); + + cnst = LD_W4; + b70 = vec_madd(cnst, b70, x0); + cnst = LD_W5; + b50 = vec_madd(cnst, b50, x1); + cnst = LD_W6; + b30 = vec_madd(cnst, b30, x1); + cnst = LD_W7; + b10 = vec_madd(cnst, b10, x0); + + b70 = vec_add(b70, x2); + b50 = vec_add(b50, x3); + b30 = vec_add(b30, x2); + b10 = vec_add(b10, x3); + + + x0 = vec_add(b71, b11); + x1 = vec_add(b51, b31); + x2 = vec_add(b71, b31); + x3 = vec_add(b51, b11); + x8 = vec_add(x2, x3); + cnst = LD_W3; + x8 = vec_madd(cnst, x8, mzero); + + cnst = LD_W8; + x0 = vec_madd(cnst, x0, mzero); + cnst = LD_W9; + x1 = vec_madd(cnst, x1, mzero); + cnst = LD_WA; + x2 = vec_madd(cnst, x2, x8); + cnst = LD_WB; + x3 = vec_madd(cnst, x3, x8); + + cnst = LD_W4; + b71 = vec_madd(cnst, b71, x0); + cnst = LD_W5; + b51 = vec_madd(cnst, b51, x1); + cnst = LD_W6; + b31 = vec_madd(cnst, b31, x1); + cnst = LD_W7; + b11 = vec_madd(cnst, b11, x0); + + b71 = vec_add(b71, x2); + b51 = vec_add(b51, x3); + b31 = vec_add(b31, x2); + b11 = vec_add(b11, x3); + /* }}} */ + + + /* 8x8 matrix transpose (vector float[8][2]) {{{ */ + x0 = vec_mergel(b00, b20); + x1 = vec_mergeh(b00, b20); + x2 = vec_mergel(b10, b30); + x3 = vec_mergeh(b10, b30); + + b00 = vec_mergeh(x1, x3); + b10 = vec_mergel(x1, x3); + b20 = vec_mergeh(x0, x2); + b30 = vec_mergel(x0, x2); + + x4 = vec_mergel(b41, b61); + x5 = vec_mergeh(b41, b61); + x6 = vec_mergel(b51, b71); + x7 = vec_mergeh(b51, b71); + + b41 = vec_mergeh(x5, x7); + b51 = vec_mergel(x5, x7); + b61 = vec_mergeh(x4, x6); + b71 = vec_mergel(x4, x6); + + x0 = vec_mergel(b01, b21); + x1 = vec_mergeh(b01, b21); + x2 = vec_mergel(b11, b31); + x3 = vec_mergeh(b11, b31); + + x4 = vec_mergel(b40, b60); + x5 = vec_mergeh(b40, b60); + x6 = vec_mergel(b50, b70); + x7 = vec_mergeh(b50, b70); + + b40 = vec_mergeh(x1, x3); + b50 = vec_mergel(x1, x3); + b60 = vec_mergeh(x0, x2); + b70 = vec_mergel(x0, x2); + + b01 = vec_mergeh(x5, x7); + b11 = vec_mergel(x5, x7); + b21 = vec_mergeh(x4, x6); + b31 = vec_mergel(x4, x6); + /* }}} */ + + + FDCTCOL(b00, b10, b20, b30, b40, b50, b60, b70); + FDCTCOL(b01, b11, b21, b31, b41, b51, b61, b71); + + + /* round, convert back to short {{{ */ +#define CTS(n) \ + b##n##0 = vec_round(b##n##0); \ + b##n##1 = vec_round(b##n##1); \ + b##n##0 = ((vector float)vec_cts(b##n##0, 0)); \ + b##n##1 = ((vector float)vec_cts(b##n##1, 0)); \ + b##n##0 = ((vector float)vec_pack(vs32(b##n##0), vs32(b##n##1))); \ + vec_st(vs16(b##n##0), 0, bp); + + bp = (vector signed short*)block; + CTS(0); bp++; + CTS(1); bp++; + CTS(2); bp++; + CTS(3); bp++; + CTS(4); bp++; + CTS(5); bp++; + CTS(6); bp++; + CTS(7); + +#undef CTS + /* }}} */ +} + +/* vim:set foldmethod=marker foldlevel=0: */ diff --git a/ffmpeg/libavcodec/ppc/fft_altivec.c b/ffmpeg/libavcodec/ppc/fft_altivec.c new file mode 100644 index 0000000..651ee26 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/fft_altivec.c @@ -0,0 +1,150 @@ +/* + * FFT/IFFT transforms + * AltiVec-enabled + * Copyright (c) 2009 Loren Merritt + * + * 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 "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/fft.h" + +/** + * Do a complex FFT with the parameters defined in ff_fft_init(). The + * input data must be permuted before with s->revtab table. No + * 1.0/sqrt(n) normalization is done. + * AltiVec-enabled + * This code assumes that the 'z' pointer is 16 bytes-aligned + * It also assumes all FFTComplex are 8 bytes-aligned pair of float + */ + +void ff_fft_calc_altivec(FFTContext *s, FFTComplex *z); +void ff_fft_calc_interleave_altivec(FFTContext *s, FFTComplex *z); + +#if HAVE_GNU_AS +static void ff_imdct_half_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int j, k; + int n = 1 << s->mdct_bits; + int n4 = n >> 2; + int n8 = n >> 3; + int n32 = n >> 5; + const uint16_t *revtabj = s->revtab; + const uint16_t *revtabk = s->revtab+n4; + const vec_f *tcos = (const vec_f*)(s->tcos+n8); + const vec_f *tsin = (const vec_f*)(s->tsin+n8); + const vec_f *pin = (const vec_f*)(input+n4); + vec_f *pout = (vec_f*)(output+n4); + + /* pre rotation */ + k = n32-1; + do { + vec_f cos,sin,cos0,sin0,cos1,sin1,re,im,r0,i0,r1,i1,a,b,c,d; +#define CMULA(p,o0,o1,o2,o3)\ + a = pin[ k*2+p]; /* { z[k].re, z[k].im, z[k+1].re, z[k+1].im } */\ + b = pin[-k*2-p-1]; /* { z[-k-2].re, z[-k-2].im, z[-k-1].re, z[-k-1].im } */\ + re = vec_perm(a, b, vcprm(0,2,s0,s2)); /* { z[k].re, z[k+1].re, z[-k-2].re, z[-k-1].re } */\ + im = vec_perm(a, b, vcprm(s3,s1,3,1)); /* { z[-k-1].im, z[-k-2].im, z[k+1].im, z[k].im } */\ + cos = vec_perm(cos0, cos1, vcprm(o0,o1,s##o2,s##o3)); /* { cos[k], cos[k+1], cos[-k-2], cos[-k-1] } */\ + sin = vec_perm(sin0, sin1, vcprm(o0,o1,s##o2,s##o3));\ + r##p = im*cos - re*sin;\ + i##p = re*cos + im*sin; +#define STORE2(v,dst)\ + j = dst;\ + vec_ste(v, 0, output+j*2);\ + vec_ste(v, 4, output+j*2); +#define STORE8(p)\ + a = vec_perm(r##p, i##p, vcprm(0,s0,0,s0));\ + b = vec_perm(r##p, i##p, vcprm(1,s1,1,s1));\ + c = vec_perm(r##p, i##p, vcprm(2,s2,2,s2));\ + d = vec_perm(r##p, i##p, vcprm(3,s3,3,s3));\ + STORE2(a, revtabk[ p*2-4]);\ + STORE2(b, revtabk[ p*2-3]);\ + STORE2(c, revtabj[-p*2+2]);\ + STORE2(d, revtabj[-p*2+3]); + + cos0 = tcos[k]; + sin0 = tsin[k]; + cos1 = tcos[-k-1]; + sin1 = tsin[-k-1]; + CMULA(0, 0,1,2,3); + CMULA(1, 2,3,0,1); + STORE8(0); + STORE8(1); + revtabj += 4; + revtabk -= 4; + k--; + } while(k >= 0); + + ff_fft_calc_altivec(s, (FFTComplex*)output); + + /* post rotation + reordering */ + j = -n32; + k = n32-1; + do { + vec_f cos,sin,re,im,a,b,c,d; +#define CMULB(d0,d1,o)\ + re = pout[o*2];\ + im = pout[o*2+1];\ + cos = tcos[o];\ + sin = tsin[o];\ + d0 = im*sin - re*cos;\ + d1 = re*sin + im*cos; + + CMULB(a,b,j); + CMULB(c,d,k); + pout[2*j] = vec_perm(a, d, vcprm(0,s3,1,s2)); + pout[2*j+1] = vec_perm(a, d, vcprm(2,s1,3,s0)); + pout[2*k] = vec_perm(c, b, vcprm(0,s3,1,s2)); + pout[2*k+1] = vec_perm(c, b, vcprm(2,s1,3,s0)); + j++; + k--; + } while(k >= 0); +} + +static void ff_imdct_calc_altivec(FFTContext *s, FFTSample *output, const FFTSample *input) +{ + int k; + int n = 1 << s->mdct_bits; + int n4 = n >> 2; + int n16 = n >> 4; + vec_u32 sign = {1U<<31,1U<<31,1U<<31,1U<<31}; + vec_u32 *p0 = (vec_u32*)(output+n4); + vec_u32 *p1 = (vec_u32*)(output+n4*3); + + ff_imdct_half_altivec(s, output+n4, input); + + for (k = 0; k < n16; k++) { + vec_u32 a = p0[k] ^ sign; + vec_u32 b = p1[-k-1]; + p0[-k-1] = vec_perm(a, a, vcprm(3,2,1,0)); + p1[k] = vec_perm(b, b, vcprm(3,2,1,0)); + } +} +#endif /* HAVE_GNU_AS */ + +av_cold void ff_fft_init_altivec(FFTContext *s) +{ +#if HAVE_GNU_AS + s->fft_calc = ff_fft_calc_interleave_altivec; + if (s->mdct_bits >= 5) { + s->imdct_calc = ff_imdct_calc_altivec; + s->imdct_half = ff_imdct_half_altivec; + } +#endif +} diff --git a/ffmpeg/libavcodec/ppc/fft_altivec_s.S b/ffmpeg/libavcodec/ppc/fft_altivec_s.S new file mode 100644 index 0000000..16ce838 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/fft_altivec_s.S @@ -0,0 +1,449 @@ +/* + * FFT transform with Altivec optimizations + * Copyright (c) 2009 Loren Merritt + * + * This algorithm (though not any of the implementation details) is + * based on libdjbfft by D. J. Bernstein. + * + * 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 + */ + +/* + * These functions are not individually interchangeable with the C versions. + * While C takes arrays of FFTComplex, Altivec leaves intermediate results + * in blocks as convenient to the vector size. + * i.e. {4x real, 4x imaginary, 4x real, ...} + * + * I ignore standard calling convention. + * Instead, the following registers are treated as global constants: + * v14: zero + * v15..v18: cosines + * v19..v29: permutations + * r9: 16 + * r12: ff_cos_tabs + * and the rest are free for local use. + */ + +#include "config.h" +#include "asm.S" + +.text + +.macro addi2 ra, imm // add 32-bit immediate +.if \imm & 0xffff + addi \ra, \ra, \imm@l +.endif +.if (\imm+0x8000)>>16 + addis \ra, \ra, \imm@ha +.endif +.endm + +.macro FFT4 a0, a1, a2, a3 // in:0-1 out:2-3 + vperm \a2,\a0,\a1,v20 // vcprm(0,1,s2,s1) // {r0,i0,r3,i2} + vperm \a3,\a0,\a1,v21 // vcprm(2,3,s0,s3) // {r1,i1,r2,i3} + vaddfp \a0,\a2,\a3 // {t1,t2,t6,t5} + vsubfp \a1,\a2,\a3 // {t3,t4,t8,t7} + vmrghw \a2,\a0,\a1 // vcprm(0,s0,1,s1) // {t1,t3,t2,t4} + vperm \a3,\a0,\a1,v22 // vcprm(2,s3,3,s2) // {t6,t7,t5,t8} + vaddfp \a0,\a2,\a3 // {r0,r1,i0,i1} + vsubfp \a1,\a2,\a3 // {r2,r3,i2,i3} + vperm \a2,\a0,\a1,v23 // vcprm(0,1,s0,s1) // {r0,r1,r2,r3} + vperm \a3,\a0,\a1,v24 // vcprm(2,3,s2,s3) // {i0,i1,i2,i3} +.endm + +.macro FFT4x2 a0, a1, b0, b1, a2, a3, b2, b3 + vperm \a2,\a0,\a1,v20 // vcprm(0,1,s2,s1) // {r0,i0,r3,i2} + vperm \a3,\a0,\a1,v21 // vcprm(2,3,s0,s3) // {r1,i1,r2,i3} + vperm \b2,\b0,\b1,v20 + vperm \b3,\b0,\b1,v21 + vaddfp \a0,\a2,\a3 // {t1,t2,t6,t5} + vsubfp \a1,\a2,\a3 // {t3,t4,t8,t7} + vaddfp \b0,\b2,\b3 + vsubfp \b1,\b2,\b3 + vmrghw \a2,\a0,\a1 // vcprm(0,s0,1,s1) // {t1,t3,t2,t4} + vperm \a3,\a0,\a1,v22 // vcprm(2,s3,3,s2) // {t6,t7,t5,t8} + vmrghw \b2,\b0,\b1 + vperm \b3,\b0,\b1,v22 + vaddfp \a0,\a2,\a3 // {r0,r1,i0,i1} + vsubfp \a1,\a2,\a3 // {r2,r3,i2,i3} + vaddfp \b0,\b2,\b3 + vsubfp \b1,\b2,\b3 + vperm \a2,\a0,\a1,v23 // vcprm(0,1,s0,s1) // {r0,r1,r2,r3} + vperm \a3,\a0,\a1,v24 // vcprm(2,3,s2,s3) // {i0,i1,i2,i3} + vperm \b2,\b0,\b1,v23 + vperm \b3,\b0,\b1,v24 +.endm + +.macro FFT8 a0, a1, b0, b1, a2, a3, b2, b3, b4 // in,out:a0-b1 + vmrghw \b2,\b0,\b1 // vcprm(0,s0,1,s1) // {r4,r6,i4,i6} + vmrglw \b3,\b0,\b1 // vcprm(2,s2,3,s3) // {r5,r7,i5,i7} + vperm \a2,\a0,\a1,v20 // FFT4 ... + vperm \a3,\a0,\a1,v21 + vaddfp \b0,\b2,\b3 // {t1,t3,t2,t4} + vsubfp \b1,\b2,\b3 // {r5,r7,i5,i7} + vperm \b4,\b1,\b1,v25 // vcprm(2,3,0,1) // {i5,i7,r5,r7} + vaddfp \a0,\a2,\a3 + vsubfp \a1,\a2,\a3 + vmaddfp \b1,\b1,v17,v14 // * {-1,1,1,-1}/sqrt(2) + vmaddfp \b1,\b4,v18,\b1 // * { 1,1,1,1 }/sqrt(2) // {t8,ta,t7,t9} + vmrghw \a2,\a0,\a1 + vperm \a3,\a0,\a1,v22 + vperm \b2,\b0,\b1,v26 // vcprm(1,2,s3,s0) // {t3,t2,t9,t8} + vperm \b3,\b0,\b1,v27 // vcprm(0,3,s2,s1) // {t1,t4,t7,ta} + vaddfp \a0,\a2,\a3 + vsubfp \a1,\a2,\a3 + vaddfp \b0,\b2,\b3 // {t1,t2,t9,ta} + vsubfp \b1,\b2,\b3 // {t6,t5,tc,tb} + vperm \a2,\a0,\a1,v23 + vperm \a3,\a0,\a1,v24 + vperm \b2,\b0,\b1,v28 // vcprm(0,2,s1,s3) // {t1,t9,t5,tb} + vperm \b3,\b0,\b1,v29 // vcprm(1,3,s0,s2) // {t2,ta,t6,tc} + vsubfp \b0,\a2,\b2 // {r4,r5,r6,r7} + vsubfp \b1,\a3,\b3 // {i4,i5,i6,i7} + vaddfp \a0,\a2,\b2 // {r0,r1,r2,r3} + vaddfp \a1,\a3,\b3 // {i0,i1,i2,i3} +.endm + +.macro BF d0,d1,s0,s1 + vsubfp \d1,\s0,\s1 + vaddfp \d0,\s0,\s1 +.endm + +.macro zip d0,d1,s0,s1 + vmrghw \d0,\s0,\s1 + vmrglw \d1,\s0,\s1 +.endm + +.macro def_fft4 interleave +fft4\interleave\()_altivec: + lvx v0, 0,r3 + lvx v1,r9,r3 + FFT4 v0,v1,v2,v3 +.ifnb \interleave + zip v0,v1,v2,v3 + stvx v0, 0,r3 + stvx v1,r9,r3 +.else + stvx v2, 0,r3 + stvx v3,r9,r3 +.endif + blr +.endm + +.macro def_fft8 interleave +fft8\interleave\()_altivec: + addi r4,r3,32 + lvx v0, 0,r3 + lvx v1,r9,r3 + lvx v2, 0,r4 + lvx v3,r9,r4 + FFT8 v0,v1,v2,v3,v4,v5,v6,v7,v8 +.ifnb \interleave + zip v4,v5,v0,v1 + zip v6,v7,v2,v3 + stvx v4, 0,r3 + stvx v5,r9,r3 + stvx v6, 0,r4 + stvx v7,r9,r4 +.else + stvx v0, 0,r3 + stvx v1,r9,r3 + stvx v2, 0,r4 + stvx v3,r9,r4 +.endif + blr +.endm + +.macro def_fft16 interleave +fft16\interleave\()_altivec: + addi r5,r3,64 + addi r6,r3,96 + addi r4,r3,32 + lvx v0, 0,r5 + lvx v1,r9,r5 + lvx v2, 0,r6 + lvx v3,r9,r6 + FFT4x2 v0,v1,v2,v3,v4,v5,v6,v7 + lvx v0, 0,r3 + lvx v1,r9,r3 + lvx v2, 0,r4 + lvx v3,r9,r4 + FFT8 v0,v1,v2,v3,v8,v9,v10,v11,v12 + vmaddfp v8,v4,v15,v14 // r2*wre + vmaddfp v9,v5,v15,v14 // i2*wre + vmaddfp v10,v6,v15,v14 // r3*wre + vmaddfp v11,v7,v15,v14 // i3*wre + vmaddfp v8,v5,v16,v8 // i2*wim + vnmsubfp v9,v4,v16,v9 // r2*wim + vnmsubfp v10,v7,v16,v10 // i3*wim + vmaddfp v11,v6,v16,v11 // r3*wim + BF v10,v12,v10,v8 + BF v11,v13,v9,v11 + BF v0,v4,v0,v10 + BF v3,v7,v3,v12 + BF v1,v5,v1,v11 + BF v2,v6,v2,v13 +.ifnb \interleave + zip v8, v9,v0,v1 + zip v10,v11,v2,v3 + zip v12,v13,v4,v5 + zip v14,v15,v6,v7 + stvx v8, 0,r3 + stvx v9,r9,r3 + stvx v10, 0,r4 + stvx v11,r9,r4 + stvx v12, 0,r5 + stvx v13,r9,r5 + stvx v14, 0,r6 + stvx v15,r9,r6 +.else + stvx v0, 0,r3 + stvx v4, 0,r5 + stvx v3,r9,r4 + stvx v7,r9,r6 + stvx v1,r9,r3 + stvx v5,r9,r5 + stvx v2, 0,r4 + stvx v6, 0,r6 +.endif + blr +.endm + +// void pass(float *z, float *wre, int n) +.macro PASS interleave, suffix +fft_pass\suffix\()_altivec: + mtctr r5 + slwi r0,r5,4 + slwi r7,r5,6 // o2 + slwi r5,r5,5 // o1 + add r10,r5,r7 // o3 + add r0,r4,r0 // wim + addi r6,r5,16 // o1+16 + addi r8,r7,16 // o2+16 + addi r11,r10,16 // o3+16 +1: + lvx v8, 0,r4 // wre + lvx v10, 0,r0 // wim + sub r0,r0,r9 + lvx v9, 0,r0 + vperm v9,v9,v10,v19 // vcprm(s0,3,2,1) => wim[0 .. -3] + lvx v4,r3,r7 // r2 = z[o2] + lvx v5,r3,r8 // i2 = z[o2+16] + lvx v6,r3,r10 // r3 = z[o3] + lvx v7,r3,r11 // i3 = z[o3+16] + vmaddfp v10,v4,v8,v14 // r2*wre + vmaddfp v11,v5,v8,v14 // i2*wre + vmaddfp v12,v6,v8,v14 // r3*wre + vmaddfp v13,v7,v8,v14 // i3*wre + lvx v0, 0,r3 // r0 = z[0] + lvx v3,r3,r6 // i1 = z[o1+16] + vmaddfp v10,v5,v9,v10 // i2*wim + vnmsubfp v11,v4,v9,v11 // r2*wim + vnmsubfp v12,v7,v9,v12 // i3*wim + vmaddfp v13,v6,v9,v13 // r3*wim + lvx v1,r3,r9 // i0 = z[16] + lvx v2,r3,r5 // r1 = z[o1] + BF v12,v8,v12,v10 + BF v13,v9,v11,v13 + BF v0,v4,v0,v12 + BF v3,v7,v3,v8 +.if !\interleave + stvx v0, 0,r3 + stvx v4,r3,r7 + stvx v3,r3,r6 + stvx v7,r3,r11 +.endif + BF v1,v5,v1,v13 + BF v2,v6,v2,v9 +.if !\interleave + stvx v1,r3,r9 + stvx v2,r3,r5 + stvx v5,r3,r8 + stvx v6,r3,r10 +.else + vmrghw v8,v0,v1 + vmrglw v9,v0,v1 + stvx v8, 0,r3 + stvx v9,r3,r9 + vmrghw v8,v2,v3 + vmrglw v9,v2,v3 + stvx v8,r3,r5 + stvx v9,r3,r6 + vmrghw v8,v4,v5 + vmrglw v9,v4,v5 + stvx v8,r3,r7 + stvx v9,r3,r8 + vmrghw v8,v6,v7 + vmrglw v9,v6,v7 + stvx v8,r3,r10 + stvx v9,r3,r11 +.endif + addi r3,r3,32 + addi r4,r4,16 + bdnz 1b + sub r3,r3,r5 + blr +.endm + +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +#define WORD_0 0x00,0x01,0x02,0x03 +#define WORD_1 0x04,0x05,0x06,0x07 +#define WORD_2 0x08,0x09,0x0a,0x0b +#define WORD_3 0x0c,0x0d,0x0e,0x0f +#define WORD_s0 0x10,0x11,0x12,0x13 +#define WORD_s1 0x14,0x15,0x16,0x17 +#define WORD_s2 0x18,0x19,0x1a,0x1b +#define WORD_s3 0x1c,0x1d,0x1e,0x1f + +#define vcprm(a, b, c, d) .byte WORD_##a, WORD_##b, WORD_##c, WORD_##d + + .rodata + .align 4 +fft_data: + .float 0, 0, 0, 0 + .float 1, 0.92387953, M_SQRT1_2, 0.38268343 + .float 0, 0.38268343, M_SQRT1_2, 0.92387953 + .float -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2,-M_SQRT1_2 + .float M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2 + vcprm(s0,3,2,1) + vcprm(0,1,s2,s1) + vcprm(2,3,s0,s3) + vcprm(2,s3,3,s2) + vcprm(0,1,s0,s1) + vcprm(2,3,s2,s3) + vcprm(2,3,0,1) + vcprm(1,2,s3,s0) + vcprm(0,3,s2,s1) + vcprm(0,2,s1,s3) + vcprm(1,3,s0,s2) + +.macro lvm b, r, regs:vararg + lvx \r, 0, \b + addi \b, \b, 16 + .ifnb \regs + lvm \b, \regs + .endif +.endm + +.macro stvm b, r, regs:vararg + stvx \r, 0, \b + addi \b, \b, 16 + .ifnb \regs + stvm \b, \regs + .endif +.endm + +.macro fft_calc interleave +extfunc ff_fft_calc\interleave\()_altivec + mflr r0 + stp r0, 2*PS(r1) + stpu r1, -(160+16*PS)(r1) + get_got r11 + addi r6, r1, 16*PS + stvm r6, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + mfvrsave r0 + stw r0, 15*PS(r1) + li r6, 0xfffffffc + mtvrsave r6 + + movrel r6, fft_data, r11 + lvm r6, v14, v15, v16, v17, v18, v19, v20, v21 + lvm r6, v22, v23, v24, v25, v26, v27, v28, v29 + + li r9, 16 + movrel r12, X(ff_cos_tabs), r11 + + movrel r6, fft_dispatch_tab\interleave\()_altivec, r11 + lwz r3, 0(r3) + subi r3, r3, 2 + slwi r3, r3, 2+ARCH_PPC64 + lpx r3, r3, r6 + mtctr r3 + mr r3, r4 + bctrl + + addi r6, r1, 16*PS + lvm r6, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 + lwz r6, 15*PS(r1) + mtvrsave r6 + lp r1, 0(r1) + lp r0, 2*PS(r1) + mtlr r0 + blr +.endm + +.macro DECL_FFT suffix, bits, n, n2, n4 +fft\n\suffix\()_altivec: + mflr r0 + stp r0,PS*(\bits-3)(r1) + bl fft\n2\()_altivec + addi2 r3,\n*4 + bl fft\n4\()_altivec + addi2 r3,\n*2 + bl fft\n4\()_altivec + addi2 r3,\n*-6 + lp r0,PS*(\bits-3)(r1) + lp r4,\bits*PS(r12) + mtlr r0 + li r5,\n/16 + b fft_pass\suffix\()_altivec +.endm + +.macro DECL_FFTS interleave, suffix + .text + def_fft4 \suffix + def_fft8 \suffix + def_fft16 \suffix + PASS \interleave, \suffix + DECL_FFT \suffix, 5, 32, 16, 8 + DECL_FFT \suffix, 6, 64, 32, 16 + DECL_FFT \suffix, 7, 128, 64, 32 + DECL_FFT \suffix, 8, 256, 128, 64 + DECL_FFT \suffix, 9, 512, 256, 128 + DECL_FFT \suffix,10, 1024, 512, 256 + DECL_FFT \suffix,11, 2048, 1024, 512 + DECL_FFT \suffix,12, 4096, 2048, 1024 + DECL_FFT \suffix,13, 8192, 4096, 2048 + DECL_FFT \suffix,14,16384, 8192, 4096 + DECL_FFT \suffix,15,32768,16384, 8192 + DECL_FFT \suffix,16,65536,32768,16384 + + fft_calc \suffix + + .rodata + .align 3 +fft_dispatch_tab\suffix\()_altivec: + PTR fft4\suffix\()_altivec + PTR fft8\suffix\()_altivec + PTR fft16\suffix\()_altivec + PTR fft32\suffix\()_altivec + PTR fft64\suffix\()_altivec + PTR fft128\suffix\()_altivec + PTR fft256\suffix\()_altivec + PTR fft512\suffix\()_altivec + PTR fft1024\suffix\()_altivec + PTR fft2048\suffix\()_altivec + PTR fft4096\suffix\()_altivec + PTR fft8192\suffix\()_altivec + PTR fft16384\suffix\()_altivec + PTR fft32768\suffix\()_altivec + PTR fft65536\suffix\()_altivec +.endm + +DECL_FFTS 0 +DECL_FFTS 1, _interleave diff --git a/ffmpeg/libavcodec/ppc/fmtconvert_altivec.c b/ffmpeg/libavcodec/ppc/fmtconvert_altivec.c new file mode 100644 index 0000000..b29c7d4 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/fmtconvert_altivec.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2006 Luca Barbato + * + * 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 "libavcodec/fmtconvert.h" + +#include "libavutil/ppc/util_altivec.h" +#include "libavutil/attributes.h" +#include "libavutil/mem.h" +#include "dsputil_altivec.h" + +static void int32_to_float_fmul_scalar_altivec(float *dst, const int *src, + float mul, int len) +{ + union { + vector float v; + float s[4]; + } mul_u; + int i; + vector float src1, src2, dst1, dst2, mul_v, zero; + + zero = (vector float)vec_splat_u32(0); + mul_u.s[0] = mul; + mul_v = vec_splat(mul_u.v, 0); + + for (i = 0; i < len; i += 8) { + src1 = vec_ctf(vec_ld(0, src+i), 0); + src2 = vec_ctf(vec_ld(16, src+i), 0); + dst1 = vec_madd(src1, mul_v, zero); + dst2 = vec_madd(src2, mul_v, zero); + vec_st(dst1, 0, dst+i); + vec_st(dst2, 16, dst+i); + } +} + + +static vector signed short float_to_int16_one_altivec(const float *src) +{ + vector float s0 = vec_ld(0, src); + vector float s1 = vec_ld(16, src); + vector signed int t0 = vec_cts(s0, 0); + vector signed int t1 = vec_cts(s1, 0); + return vec_packs(t0,t1); +} + +static void float_to_int16_altivec(int16_t *dst, const float *src, long len) +{ + int i; + vector signed short d0, d1, d; + vector unsigned char align; + if (((long)dst) & 15) { //FIXME + for (i = 0; i < len - 7; i += 8) { + d0 = vec_ld(0, dst+i); + d = float_to_int16_one_altivec(src + i); + d1 = vec_ld(15, dst+i); + d1 = vec_perm(d1, d0, vec_lvsl(0, dst + i)); + align = vec_lvsr(0, dst + i); + d0 = vec_perm(d1, d, align); + d1 = vec_perm(d, d1, align); + vec_st(d0, 0, dst + i); + vec_st(d1, 15, dst + i); + } + } else { + for (i = 0; i < len - 7; i += 8) { + d = float_to_int16_one_altivec(src + i); + vec_st(d, 0, dst + i); + } + } +} + +#define VSTE_INC(dst, v, elem, inc) do { \ + vector signed short s = vec_splat(v, elem); \ + vec_ste(s, 0, dst); \ + dst += inc; \ + } while (0) + +static void float_to_int16_stride_altivec(int16_t *dst, const float *src, + long len, int stride) +{ + int i; + vector signed short d; + + for (i = 0; i < len - 7; i += 8) { + d = float_to_int16_one_altivec(src + i); + VSTE_INC(dst, d, 0, stride); + VSTE_INC(dst, d, 1, stride); + VSTE_INC(dst, d, 2, stride); + VSTE_INC(dst, d, 3, stride); + VSTE_INC(dst, d, 4, stride); + VSTE_INC(dst, d, 5, stride); + VSTE_INC(dst, d, 6, stride); + VSTE_INC(dst, d, 7, stride); + } +} + +static void float_to_int16_interleave_altivec(int16_t *dst, const float **src, + long len, int channels) +{ + int i; + vector signed short d0, d1, d2, c0, c1, t0, t1; + vector unsigned char align; + + if (channels == 1) + float_to_int16_altivec(dst, src[0], len); + else { + if (channels == 2) { + if (((long)dst) & 15) { + for (i = 0; i < len - 7; i += 8) { + d0 = vec_ld(0, dst + i); + t0 = float_to_int16_one_altivec(src[0] + i); + d1 = vec_ld(31, dst + i); + t1 = float_to_int16_one_altivec(src[1] + i); + c0 = vec_mergeh(t0, t1); + c1 = vec_mergel(t0, t1); + d2 = vec_perm(d1, d0, vec_lvsl(0, dst + i)); + align = vec_lvsr(0, dst + i); + d0 = vec_perm(d2, c0, align); + d1 = vec_perm(c0, c1, align); + vec_st(d0, 0, dst + i); + d0 = vec_perm(c1, d2, align); + vec_st(d1, 15, dst + i); + vec_st(d0, 31, dst + i); + dst += 8; + } + } else { + for (i = 0; i < len - 7; i += 8) { + t0 = float_to_int16_one_altivec(src[0] + i); + t1 = float_to_int16_one_altivec(src[1] + i); + d0 = vec_mergeh(t0, t1); + d1 = vec_mergel(t0, t1); + vec_st(d0, 0, dst + i); + vec_st(d1, 16, dst + i); + dst += 8; + } + } + } else { + for (i = 0; i < channels; i++) + float_to_int16_stride_altivec(dst + i, src[i], len, channels); + } + } +} + +av_cold void ff_fmt_convert_init_altivec(FmtConvertContext *c, AVCodecContext *avctx) +{ + c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_altivec; + if (!(avctx->flags & CODEC_FLAG_BITEXACT)) { + c->float_to_int16 = float_to_int16_altivec; + c->float_to_int16_interleave = float_to_int16_interleave_altivec; + } +} diff --git a/ffmpeg/libavcodec/ppc/gmc_altivec.c b/ffmpeg/libavcodec/ppc/gmc_altivec.c new file mode 100644 index 0000000..4db761d --- /dev/null +++ b/ffmpeg/libavcodec/ppc/gmc_altivec.c @@ -0,0 +1,130 @@ +/* + * GMC (Global Motion Compensation) + * AltiVec-enabled + * Copyright (c) 2003 Romain Dolbeau + * + * 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 "libavutil/mem.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "dsputil_altivec.h" + +/* + altivec-enhanced gmc1. ATM this code assume stride is a multiple of 8, + to preserve proper dst alignment. +*/ +void ff_gmc1_altivec(uint8_t *dst /* align 8 */, uint8_t *src /* align1 */, int stride, int h, int x16, int y16, int rounder) +{ + const DECLARE_ALIGNED(16, unsigned short, rounder_a) = rounder; + const DECLARE_ALIGNED(16, unsigned short, ABCD)[8] = + { + (16-x16)*(16-y16), /* A */ + ( x16)*(16-y16), /* B */ + (16-x16)*( y16), /* C */ + ( x16)*( y16), /* D */ + 0, 0, 0, 0 /* padding */ + }; + register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0); + register const vector unsigned short vcsr8 = (const vector unsigned short)vec_splat_u16(8); + register vector unsigned char dstv, dstv2, src_0, src_1, srcvA, srcvB, srcvC, srcvD; + register vector unsigned short Av, Bv, Cv, Dv, rounderV, tempA, tempB, tempC, tempD; + int i; + unsigned long dst_odd = (unsigned long)dst & 0x0000000F; + unsigned long src_really_odd = (unsigned long)src & 0x0000000F; + + tempA = vec_ld(0, (const unsigned short*)ABCD); + Av = vec_splat(tempA, 0); + Bv = vec_splat(tempA, 1); + Cv = vec_splat(tempA, 2); + Dv = vec_splat(tempA, 3); + + rounderV = vec_splat((vec_u16)vec_lde(0, &rounder_a), 0); + + // we'll be able to pick-up our 9 char elements + // at src from those 32 bytes + // we load the first batch here, as inside the loop + // we can re-use 'src+stride' from one iteration + // as the 'src' of the next. + src_0 = vec_ld(0, src); + src_1 = vec_ld(16, src); + srcvA = vec_perm(src_0, src_1, vec_lvsl(0, src)); + + if (src_really_odd != 0x0000000F) { + // if src & 0xF == 0xF, then (src+1) is properly aligned + // on the second vector. + srcvB = vec_perm(src_0, src_1, vec_lvsl(1, src)); + } else { + srcvB = src_1; + } + srcvA = vec_mergeh(vczero, srcvA); + srcvB = vec_mergeh(vczero, srcvB); + + for(i=0; i + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/h264data.h" +#include "libavcodec/h264dsp.h" + +/**************************************************************************** + * IDCT transform: + ****************************************************************************/ + +#define VEC_1D_DCT(vb0,vb1,vb2,vb3,va0,va1,va2,va3) \ + /* 1st stage */ \ + vz0 = vec_add(vb0,vb2); /* temp[0] = Y[0] + Y[2] */ \ + vz1 = vec_sub(vb0,vb2); /* temp[1] = Y[0] - Y[2] */ \ + vz2 = vec_sra(vb1,vec_splat_u16(1)); \ + vz2 = vec_sub(vz2,vb3); /* temp[2] = Y[1].1/2 - Y[3] */ \ + vz3 = vec_sra(vb3,vec_splat_u16(1)); \ + vz3 = vec_add(vb1,vz3); /* temp[3] = Y[1] + Y[3].1/2 */ \ + /* 2nd stage: output */ \ + va0 = vec_add(vz0,vz3); /* x[0] = temp[0] + temp[3] */ \ + va1 = vec_add(vz1,vz2); /* x[1] = temp[1] + temp[2] */ \ + va2 = vec_sub(vz1,vz2); /* x[2] = temp[1] - temp[2] */ \ + va3 = vec_sub(vz0,vz3) /* x[3] = temp[0] - temp[3] */ + +#define VEC_TRANSPOSE_4(a0,a1,a2,a3,b0,b1,b2,b3) \ + b0 = vec_mergeh( a0, a0 ); \ + b1 = vec_mergeh( a1, a0 ); \ + b2 = vec_mergeh( a2, a0 ); \ + b3 = vec_mergeh( a3, a0 ); \ + a0 = vec_mergeh( b0, b2 ); \ + a1 = vec_mergel( b0, b2 ); \ + a2 = vec_mergeh( b1, b3 ); \ + a3 = vec_mergel( b1, b3 ); \ + b0 = vec_mergeh( a0, a2 ); \ + b1 = vec_mergel( a0, a2 ); \ + b2 = vec_mergeh( a1, a3 ); \ + b3 = vec_mergel( a1, a3 ) + +#define VEC_LOAD_U8_ADD_S16_STORE_U8(va) \ + vdst_orig = vec_ld(0, dst); \ + vdst = vec_perm(vdst_orig, zero_u8v, vdst_mask); \ + vdst_ss = (vec_s16) vec_mergeh(zero_u8v, vdst); \ + va = vec_add(va, vdst_ss); \ + va_u8 = vec_packsu(va, zero_s16v); \ + va_u32 = vec_splat((vec_u32)va_u8, 0); \ + vec_ste(va_u32, element, (uint32_t*)dst); + +static void ff_h264_idct_add_altivec(uint8_t *dst, int16_t *block, int stride) +{ + vec_s16 va0, va1, va2, va3; + vec_s16 vz0, vz1, vz2, vz3; + vec_s16 vtmp0, vtmp1, vtmp2, vtmp3; + vec_u8 va_u8; + vec_u32 va_u32; + vec_s16 vdst_ss; + const vec_u16 v6us = vec_splat_u16(6); + vec_u8 vdst, vdst_orig; + vec_u8 vdst_mask = vec_lvsl(0, dst); + int element = ((unsigned long)dst & 0xf) >> 2; + LOAD_ZERO; + + block[0] += 32; /* add 32 as a DC-level for rounding */ + + vtmp0 = vec_ld(0,block); + vtmp1 = vec_sld(vtmp0, vtmp0, 8); + vtmp2 = vec_ld(16,block); + vtmp3 = vec_sld(vtmp2, vtmp2, 8); + memset(block, 0, 16 * sizeof(int16_t)); + + VEC_1D_DCT(vtmp0,vtmp1,vtmp2,vtmp3,va0,va1,va2,va3); + VEC_TRANSPOSE_4(va0,va1,va2,va3,vtmp0,vtmp1,vtmp2,vtmp3); + VEC_1D_DCT(vtmp0,vtmp1,vtmp2,vtmp3,va0,va1,va2,va3); + + va0 = vec_sra(va0,v6us); + va1 = vec_sra(va1,v6us); + va2 = vec_sra(va2,v6us); + va3 = vec_sra(va3,v6us); + + VEC_LOAD_U8_ADD_S16_STORE_U8(va0); + dst += stride; + VEC_LOAD_U8_ADD_S16_STORE_U8(va1); + dst += stride; + VEC_LOAD_U8_ADD_S16_STORE_U8(va2); + dst += stride; + VEC_LOAD_U8_ADD_S16_STORE_U8(va3); +} + +#define IDCT8_1D_ALTIVEC(s0, s1, s2, s3, s4, s5, s6, s7, d0, d1, d2, d3, d4, d5, d6, d7) {\ + /* a0 = SRC(0) + SRC(4); */ \ + vec_s16 a0v = vec_add(s0, s4); \ + /* a2 = SRC(0) - SRC(4); */ \ + vec_s16 a2v = vec_sub(s0, s4); \ + /* a4 = (SRC(2)>>1) - SRC(6); */ \ + vec_s16 a4v = vec_sub(vec_sra(s2, onev), s6); \ + /* a6 = (SRC(6)>>1) + SRC(2); */ \ + vec_s16 a6v = vec_add(vec_sra(s6, onev), s2); \ + /* b0 = a0 + a6; */ \ + vec_s16 b0v = vec_add(a0v, a6v); \ + /* b2 = a2 + a4; */ \ + vec_s16 b2v = vec_add(a2v, a4v); \ + /* b4 = a2 - a4; */ \ + vec_s16 b4v = vec_sub(a2v, a4v); \ + /* b6 = a0 - a6; */ \ + vec_s16 b6v = vec_sub(a0v, a6v); \ + /* a1 = SRC(5) - SRC(3) - SRC(7) - (SRC(7)>>1); */ \ + /* a1 = (SRC(5)-SRC(3)) - (SRC(7) + (SRC(7)>>1)); */ \ + vec_s16 a1v = vec_sub( vec_sub(s5, s3), vec_add(s7, vec_sra(s7, onev)) ); \ + /* a3 = SRC(7) + SRC(1) - SRC(3) - (SRC(3)>>1); */ \ + /* a3 = (SRC(7)+SRC(1)) - (SRC(3) + (SRC(3)>>1)); */ \ + vec_s16 a3v = vec_sub( vec_add(s7, s1), vec_add(s3, vec_sra(s3, onev)) );\ + /* a5 = SRC(7) - SRC(1) + SRC(5) + (SRC(5)>>1); */ \ + /* a5 = (SRC(7)-SRC(1)) + SRC(5) + (SRC(5)>>1); */ \ + vec_s16 a5v = vec_add( vec_sub(s7, s1), vec_add(s5, vec_sra(s5, onev)) );\ + /* a7 = SRC(5)+SRC(3) + SRC(1) + (SRC(1)>>1); */ \ + vec_s16 a7v = vec_add( vec_add(s5, s3), vec_add(s1, vec_sra(s1, onev)) );\ + /* b1 = (a7>>2) + a1; */ \ + vec_s16 b1v = vec_add( vec_sra(a7v, twov), a1v); \ + /* b3 = a3 + (a5>>2); */ \ + vec_s16 b3v = vec_add(a3v, vec_sra(a5v, twov)); \ + /* b5 = (a3>>2) - a5; */ \ + vec_s16 b5v = vec_sub( vec_sra(a3v, twov), a5v); \ + /* b7 = a7 - (a1>>2); */ \ + vec_s16 b7v = vec_sub( a7v, vec_sra(a1v, twov)); \ + /* DST(0, b0 + b7); */ \ + d0 = vec_add(b0v, b7v); \ + /* DST(1, b2 + b5); */ \ + d1 = vec_add(b2v, b5v); \ + /* DST(2, b4 + b3); */ \ + d2 = vec_add(b4v, b3v); \ + /* DST(3, b6 + b1); */ \ + d3 = vec_add(b6v, b1v); \ + /* DST(4, b6 - b1); */ \ + d4 = vec_sub(b6v, b1v); \ + /* DST(5, b4 - b3); */ \ + d5 = vec_sub(b4v, b3v); \ + /* DST(6, b2 - b5); */ \ + d6 = vec_sub(b2v, b5v); \ + /* DST(7, b0 - b7); */ \ + d7 = vec_sub(b0v, b7v); \ +} + +#define ALTIVEC_STORE_SUM_CLIP(dest, idctv, perm_ldv, perm_stv, sel) { \ + /* unaligned load */ \ + vec_u8 hv = vec_ld( 0, dest ); \ + vec_u8 lv = vec_ld( 7, dest ); \ + vec_u8 dstv = vec_perm( hv, lv, (vec_u8)perm_ldv ); \ + vec_s16 idct_sh6 = vec_sra(idctv, sixv); \ + vec_u16 dst16 = (vec_u16)vec_mergeh(zero_u8v, dstv); \ + vec_s16 idstsum = vec_adds(idct_sh6, (vec_s16)dst16); \ + vec_u8 idstsum8 = vec_packsu(zero_s16v, idstsum); \ + vec_u8 edgehv; \ + /* unaligned store */ \ + vec_u8 bodyv = vec_perm( idstsum8, idstsum8, perm_stv );\ + vec_u8 edgelv = vec_perm( sel, zero_u8v, perm_stv ); \ + lv = vec_sel( lv, bodyv, edgelv ); \ + vec_st( lv, 7, dest ); \ + hv = vec_ld( 0, dest ); \ + edgehv = vec_perm( zero_u8v, sel, perm_stv ); \ + hv = vec_sel( hv, bodyv, edgehv ); \ + vec_st( hv, 0, dest ); \ + } + +static void ff_h264_idct8_add_altivec( uint8_t *dst, int16_t *dct, int stride ) { + vec_s16 s0, s1, s2, s3, s4, s5, s6, s7; + vec_s16 d0, d1, d2, d3, d4, d5, d6, d7; + vec_s16 idct0, idct1, idct2, idct3, idct4, idct5, idct6, idct7; + + vec_u8 perm_ldv = vec_lvsl(0, dst); + vec_u8 perm_stv = vec_lvsr(8, dst); + + const vec_u16 onev = vec_splat_u16(1); + const vec_u16 twov = vec_splat_u16(2); + const vec_u16 sixv = vec_splat_u16(6); + + const vec_u8 sel = (vec_u8) {0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1}; + LOAD_ZERO; + + dct[0] += 32; // rounding for the >>6 at the end + + s0 = vec_ld(0x00, (int16_t*)dct); + s1 = vec_ld(0x10, (int16_t*)dct); + s2 = vec_ld(0x20, (int16_t*)dct); + s3 = vec_ld(0x30, (int16_t*)dct); + s4 = vec_ld(0x40, (int16_t*)dct); + s5 = vec_ld(0x50, (int16_t*)dct); + s6 = vec_ld(0x60, (int16_t*)dct); + s7 = vec_ld(0x70, (int16_t*)dct); + memset(dct, 0, 64 * sizeof(int16_t)); + + IDCT8_1D_ALTIVEC(s0, s1, s2, s3, s4, s5, s6, s7, + d0, d1, d2, d3, d4, d5, d6, d7); + + TRANSPOSE8( d0, d1, d2, d3, d4, d5, d6, d7 ); + + IDCT8_1D_ALTIVEC(d0, d1, d2, d3, d4, d5, d6, d7, + idct0, idct1, idct2, idct3, idct4, idct5, idct6, idct7); + + ALTIVEC_STORE_SUM_CLIP(&dst[0*stride], idct0, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[1*stride], idct1, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[2*stride], idct2, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[3*stride], idct3, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[4*stride], idct4, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[5*stride], idct5, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[6*stride], idct6, perm_ldv, perm_stv, sel); + ALTIVEC_STORE_SUM_CLIP(&dst[7*stride], idct7, perm_ldv, perm_stv, sel); +} + +static av_always_inline void h264_idct_dc_add_internal(uint8_t *dst, int16_t *block, int stride, int size) +{ + vec_s16 dc16; + vec_u8 dcplus, dcminus, v0, v1, v2, v3, aligner; + LOAD_ZERO; + DECLARE_ALIGNED(16, int, dc); + int i; + + dc = (block[0] + 32) >> 6; + block[0] = 0; + dc16 = vec_splat((vec_s16) vec_lde(0, &dc), 1); + + if (size == 4) + dc16 = vec_sld(dc16, zero_s16v, 8); + dcplus = vec_packsu(dc16, zero_s16v); + dcminus = vec_packsu(vec_sub(zero_s16v, dc16), zero_s16v); + + aligner = vec_lvsr(0, dst); + dcplus = vec_perm(dcplus, dcplus, aligner); + dcminus = vec_perm(dcminus, dcminus, aligner); + + for (i = 0; i < size; i += 4) { + v0 = vec_ld(0, dst+0*stride); + v1 = vec_ld(0, dst+1*stride); + v2 = vec_ld(0, dst+2*stride); + v3 = vec_ld(0, dst+3*stride); + + v0 = vec_adds(v0, dcplus); + v1 = vec_adds(v1, dcplus); + v2 = vec_adds(v2, dcplus); + v3 = vec_adds(v3, dcplus); + + v0 = vec_subs(v0, dcminus); + v1 = vec_subs(v1, dcminus); + v2 = vec_subs(v2, dcminus); + v3 = vec_subs(v3, dcminus); + + vec_st(v0, 0, dst+0*stride); + vec_st(v1, 0, dst+1*stride); + vec_st(v2, 0, dst+2*stride); + vec_st(v3, 0, dst+3*stride); + + dst += 4*stride; + } +} + +static void h264_idct_dc_add_altivec(uint8_t *dst, int16_t *block, int stride) +{ + h264_idct_dc_add_internal(dst, block, stride, 4); +} + +static void ff_h264_idct8_dc_add_altivec(uint8_t *dst, int16_t *block, int stride) +{ + h264_idct_dc_add_internal(dst, block, stride, 8); +} + +static void ff_h264_idct_add16_altivec(uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i; + for(i=0; i<16; i++){ + int nnz = nnzc[ scan8[i] ]; + if(nnz){ + if(nnz==1 && block[i*16]) h264_idct_dc_add_altivec(dst + block_offset[i], block + i*16, stride); + else ff_h264_idct_add_altivec(dst + block_offset[i], block + i*16, stride); + } + } +} + +static void ff_h264_idct_add16intra_altivec(uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i; + for(i=0; i<16; i++){ + if(nnzc[ scan8[i] ]) ff_h264_idct_add_altivec(dst + block_offset[i], block + i*16, stride); + else if(block[i*16]) h264_idct_dc_add_altivec(dst + block_offset[i], block + i*16, stride); + } +} + +static void ff_h264_idct8_add4_altivec(uint8_t *dst, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i; + for(i=0; i<16; i+=4){ + int nnz = nnzc[ scan8[i] ]; + if(nnz){ + if(nnz==1 && block[i*16]) ff_h264_idct8_dc_add_altivec(dst + block_offset[i], block + i*16, stride); + else ff_h264_idct8_add_altivec (dst + block_offset[i], block + i*16, stride); + } + } +} + +static void ff_h264_idct_add8_altivec(uint8_t **dest, const int *block_offset, int16_t *block, int stride, const uint8_t nnzc[15*8]){ + int i, j; + for (j = 1; j < 3; j++) { + for(i = j * 16; i < j * 16 + 4; i++){ + if(nnzc[ scan8[i] ]) + ff_h264_idct_add_altivec(dest[j-1] + block_offset[i], block + i*16, stride); + else if(block[i*16]) + h264_idct_dc_add_altivec(dest[j-1] + block_offset[i], block + i*16, stride); + } + } +} + +#define transpose4x16(r0, r1, r2, r3) { \ + register vec_u8 r4; \ + register vec_u8 r5; \ + register vec_u8 r6; \ + register vec_u8 r7; \ + \ + r4 = vec_mergeh(r0, r2); /*0, 2 set 0*/ \ + r5 = vec_mergel(r0, r2); /*0, 2 set 1*/ \ + r6 = vec_mergeh(r1, r3); /*1, 3 set 0*/ \ + r7 = vec_mergel(r1, r3); /*1, 3 set 1*/ \ + \ + r0 = vec_mergeh(r4, r6); /*all set 0*/ \ + r1 = vec_mergel(r4, r6); /*all set 1*/ \ + r2 = vec_mergeh(r5, r7); /*all set 2*/ \ + r3 = vec_mergel(r5, r7); /*all set 3*/ \ +} + +static inline void write16x4(uint8_t *dst, int dst_stride, + register vec_u8 r0, register vec_u8 r1, + register vec_u8 r2, register vec_u8 r3) { + DECLARE_ALIGNED(16, unsigned char, result)[64]; + uint32_t *src_int = (uint32_t *)result, *dst_int = (uint32_t *)dst; + int int_dst_stride = dst_stride/4; + + vec_st(r0, 0, result); + vec_st(r1, 16, result); + vec_st(r2, 32, result); + vec_st(r3, 48, result); + /* FIXME: there has to be a better way!!!! */ + *dst_int = *src_int; + *(dst_int+ int_dst_stride) = *(src_int + 1); + *(dst_int+ 2*int_dst_stride) = *(src_int + 2); + *(dst_int+ 3*int_dst_stride) = *(src_int + 3); + *(dst_int+ 4*int_dst_stride) = *(src_int + 4); + *(dst_int+ 5*int_dst_stride) = *(src_int + 5); + *(dst_int+ 6*int_dst_stride) = *(src_int + 6); + *(dst_int+ 7*int_dst_stride) = *(src_int + 7); + *(dst_int+ 8*int_dst_stride) = *(src_int + 8); + *(dst_int+ 9*int_dst_stride) = *(src_int + 9); + *(dst_int+10*int_dst_stride) = *(src_int + 10); + *(dst_int+11*int_dst_stride) = *(src_int + 11); + *(dst_int+12*int_dst_stride) = *(src_int + 12); + *(dst_int+13*int_dst_stride) = *(src_int + 13); + *(dst_int+14*int_dst_stride) = *(src_int + 14); + *(dst_int+15*int_dst_stride) = *(src_int + 15); +} + +/** @brief performs a 6x16 transpose of data in src, and stores it to dst + @todo FIXME: see if we can't spare some vec_lvsl() by them factorizing + out of unaligned_load() */ +#define readAndTranspose16x6(src, src_stride, r8, r9, r10, r11, r12, r13) {\ + register vec_u8 r0 = unaligned_load(0, src); \ + register vec_u8 r1 = unaligned_load( src_stride, src); \ + register vec_u8 r2 = unaligned_load(2* src_stride, src); \ + register vec_u8 r3 = unaligned_load(3* src_stride, src); \ + register vec_u8 r4 = unaligned_load(4* src_stride, src); \ + register vec_u8 r5 = unaligned_load(5* src_stride, src); \ + register vec_u8 r6 = unaligned_load(6* src_stride, src); \ + register vec_u8 r7 = unaligned_load(7* src_stride, src); \ + register vec_u8 r14 = unaligned_load(14*src_stride, src); \ + register vec_u8 r15 = unaligned_load(15*src_stride, src); \ + \ + r8 = unaligned_load( 8*src_stride, src); \ + r9 = unaligned_load( 9*src_stride, src); \ + r10 = unaligned_load(10*src_stride, src); \ + r11 = unaligned_load(11*src_stride, src); \ + r12 = unaligned_load(12*src_stride, src); \ + r13 = unaligned_load(13*src_stride, src); \ + \ + /*Merge first pairs*/ \ + r0 = vec_mergeh(r0, r8); /*0, 8*/ \ + r1 = vec_mergeh(r1, r9); /*1, 9*/ \ + r2 = vec_mergeh(r2, r10); /*2,10*/ \ + r3 = vec_mergeh(r3, r11); /*3,11*/ \ + r4 = vec_mergeh(r4, r12); /*4,12*/ \ + r5 = vec_mergeh(r5, r13); /*5,13*/ \ + r6 = vec_mergeh(r6, r14); /*6,14*/ \ + r7 = vec_mergeh(r7, r15); /*7,15*/ \ + \ + /*Merge second pairs*/ \ + r8 = vec_mergeh(r0, r4); /*0,4, 8,12 set 0*/ \ + r9 = vec_mergel(r0, r4); /*0,4, 8,12 set 1*/ \ + r10 = vec_mergeh(r1, r5); /*1,5, 9,13 set 0*/ \ + r11 = vec_mergel(r1, r5); /*1,5, 9,13 set 1*/ \ + r12 = vec_mergeh(r2, r6); /*2,6,10,14 set 0*/ \ + r13 = vec_mergel(r2, r6); /*2,6,10,14 set 1*/ \ + r14 = vec_mergeh(r3, r7); /*3,7,11,15 set 0*/ \ + r15 = vec_mergel(r3, r7); /*3,7,11,15 set 1*/ \ + \ + /*Third merge*/ \ + r0 = vec_mergeh(r8, r12); /*0,2,4,6,8,10,12,14 set 0*/ \ + r1 = vec_mergel(r8, r12); /*0,2,4,6,8,10,12,14 set 1*/ \ + r2 = vec_mergeh(r9, r13); /*0,2,4,6,8,10,12,14 set 2*/ \ + r4 = vec_mergeh(r10, r14); /*1,3,5,7,9,11,13,15 set 0*/ \ + r5 = vec_mergel(r10, r14); /*1,3,5,7,9,11,13,15 set 1*/ \ + r6 = vec_mergeh(r11, r15); /*1,3,5,7,9,11,13,15 set 2*/ \ + /* Don't need to compute 3 and 7*/ \ + \ + /*Final merge*/ \ + r8 = vec_mergeh(r0, r4); /*all set 0*/ \ + r9 = vec_mergel(r0, r4); /*all set 1*/ \ + r10 = vec_mergeh(r1, r5); /*all set 2*/ \ + r11 = vec_mergel(r1, r5); /*all set 3*/ \ + r12 = vec_mergeh(r2, r6); /*all set 4*/ \ + r13 = vec_mergel(r2, r6); /*all set 5*/ \ + /* Don't need to compute 14 and 15*/ \ + \ +} + +// out: o = |x-y| < a +static inline vec_u8 diff_lt_altivec ( register vec_u8 x, + register vec_u8 y, + register vec_u8 a) { + + register vec_u8 diff = vec_subs(x, y); + register vec_u8 diffneg = vec_subs(y, x); + register vec_u8 o = vec_or(diff, diffneg); /* |x-y| */ + o = (vec_u8)vec_cmplt(o, a); + return o; +} + +static inline vec_u8 h264_deblock_mask ( register vec_u8 p0, + register vec_u8 p1, + register vec_u8 q0, + register vec_u8 q1, + register vec_u8 alpha, + register vec_u8 beta) { + + register vec_u8 mask; + register vec_u8 tempmask; + + mask = diff_lt_altivec(p0, q0, alpha); + tempmask = diff_lt_altivec(p1, p0, beta); + mask = vec_and(mask, tempmask); + tempmask = diff_lt_altivec(q1, q0, beta); + mask = vec_and(mask, tempmask); + + return mask; +} + +// out: newp1 = clip((p2 + ((p0 + q0 + 1) >> 1)) >> 1, p1-tc0, p1+tc0) +static inline vec_u8 h264_deblock_q1(register vec_u8 p0, + register vec_u8 p1, + register vec_u8 p2, + register vec_u8 q0, + register vec_u8 tc0) { + + register vec_u8 average = vec_avg(p0, q0); + register vec_u8 temp; + register vec_u8 uncliped; + register vec_u8 ones; + register vec_u8 max; + register vec_u8 min; + register vec_u8 newp1; + + temp = vec_xor(average, p2); + average = vec_avg(average, p2); /*avg(p2, avg(p0, q0)) */ + ones = vec_splat_u8(1); + temp = vec_and(temp, ones); /*(p2^avg(p0, q0)) & 1 */ + uncliped = vec_subs(average, temp); /*(p2+((p0+q0+1)>>1))>>1 */ + max = vec_adds(p1, tc0); + min = vec_subs(p1, tc0); + newp1 = vec_max(min, uncliped); + newp1 = vec_min(max, newp1); + return newp1; +} + +#define h264_deblock_p0_q0(p0, p1, q0, q1, tc0masked) { \ + \ + const vec_u8 A0v = vec_sl(vec_splat_u8(10), vec_splat_u8(4)); \ + \ + register vec_u8 pq0bit = vec_xor(p0,q0); \ + register vec_u8 q1minus; \ + register vec_u8 p0minus; \ + register vec_u8 stage1; \ + register vec_u8 stage2; \ + register vec_u8 vec160; \ + register vec_u8 delta; \ + register vec_u8 deltaneg; \ + \ + q1minus = vec_nor(q1, q1); /* 255 - q1 */ \ + stage1 = vec_avg(p1, q1minus); /* (p1 - q1 + 256)>>1 */ \ + stage2 = vec_sr(stage1, vec_splat_u8(1)); /* (p1 - q1 + 256)>>2 = 64 + (p1 - q1) >> 2 */ \ + p0minus = vec_nor(p0, p0); /* 255 - p0 */ \ + stage1 = vec_avg(q0, p0minus); /* (q0 - p0 + 256)>>1 */ \ + pq0bit = vec_and(pq0bit, vec_splat_u8(1)); \ + stage2 = vec_avg(stage2, pq0bit); /* 32 + ((q0 - p0)&1 + (p1 - q1) >> 2 + 1) >> 1 */ \ + stage2 = vec_adds(stage2, stage1); /* 160 + ((p0 - q0) + (p1 - q1) >> 2 + 1) >> 1 */ \ + vec160 = vec_ld(0, &A0v); \ + deltaneg = vec_subs(vec160, stage2); /* -d */ \ + delta = vec_subs(stage2, vec160); /* d */ \ + deltaneg = vec_min(tc0masked, deltaneg); \ + delta = vec_min(tc0masked, delta); \ + p0 = vec_subs(p0, deltaneg); \ + q0 = vec_subs(q0, delta); \ + p0 = vec_adds(p0, delta); \ + q0 = vec_adds(q0, deltaneg); \ +} + +#define h264_loop_filter_luma_altivec(p2, p1, p0, q0, q1, q2, alpha, beta, tc0) { \ + DECLARE_ALIGNED(16, unsigned char, temp)[16]; \ + register vec_u8 alphavec; \ + register vec_u8 betavec; \ + register vec_u8 mask; \ + register vec_u8 p1mask; \ + register vec_u8 q1mask; \ + register vector signed char tc0vec; \ + register vec_u8 finaltc0; \ + register vec_u8 tc0masked; \ + register vec_u8 newp1; \ + register vec_u8 newq1; \ + \ + temp[0] = alpha; \ + temp[1] = beta; \ + alphavec = vec_ld(0, temp); \ + betavec = vec_splat(alphavec, 0x1); \ + alphavec = vec_splat(alphavec, 0x0); \ + mask = h264_deblock_mask(p0, p1, q0, q1, alphavec, betavec); /*if in block */ \ + \ + AV_COPY32(temp, tc0); \ + tc0vec = vec_ld(0, (signed char*)temp); \ + tc0vec = vec_mergeh(tc0vec, tc0vec); \ + tc0vec = vec_mergeh(tc0vec, tc0vec); \ + mask = vec_and(mask, vec_cmpgt(tc0vec, vec_splat_s8(-1))); /* if tc0[i] >= 0 */ \ + finaltc0 = vec_and((vec_u8)tc0vec, mask); /* tc = tc0 */ \ + \ + p1mask = diff_lt_altivec(p2, p0, betavec); \ + p1mask = vec_and(p1mask, mask); /* if ( |p2 - p0| < beta) */ \ + tc0masked = vec_and(p1mask, (vec_u8)tc0vec); \ + finaltc0 = vec_sub(finaltc0, p1mask); /* tc++ */ \ + newp1 = h264_deblock_q1(p0, p1, p2, q0, tc0masked); \ + /*end if*/ \ + \ + q1mask = diff_lt_altivec(q2, q0, betavec); \ + q1mask = vec_and(q1mask, mask); /* if ( |q2 - q0| < beta ) */\ + tc0masked = vec_and(q1mask, (vec_u8)tc0vec); \ + finaltc0 = vec_sub(finaltc0, q1mask); /* tc++ */ \ + newq1 = h264_deblock_q1(p0, q1, q2, q0, tc0masked); \ + /*end if*/ \ + \ + h264_deblock_p0_q0(p0, p1, q0, q1, finaltc0); \ + p1 = newp1; \ + q1 = newq1; \ +} + +static void h264_v_loop_filter_luma_altivec(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) { + + if ((tc0[0] & tc0[1] & tc0[2] & tc0[3]) >= 0) { + register vec_u8 p2 = vec_ld(-3*stride, pix); + register vec_u8 p1 = vec_ld(-2*stride, pix); + register vec_u8 p0 = vec_ld(-1*stride, pix); + register vec_u8 q0 = vec_ld(0, pix); + register vec_u8 q1 = vec_ld(stride, pix); + register vec_u8 q2 = vec_ld(2*stride, pix); + h264_loop_filter_luma_altivec(p2, p1, p0, q0, q1, q2, alpha, beta, tc0); + vec_st(p1, -2*stride, pix); + vec_st(p0, -1*stride, pix); + vec_st(q0, 0, pix); + vec_st(q1, stride, pix); + } +} + +static void h264_h_loop_filter_luma_altivec(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) { + + register vec_u8 line0, line1, line2, line3, line4, line5; + if ((tc0[0] & tc0[1] & tc0[2] & tc0[3]) < 0) + return; + readAndTranspose16x6(pix-3, stride, line0, line1, line2, line3, line4, line5); + h264_loop_filter_luma_altivec(line0, line1, line2, line3, line4, line5, alpha, beta, tc0); + transpose4x16(line1, line2, line3, line4); + write16x4(pix-2, stride, line1, line2, line3, line4); +} + +static av_always_inline +void weight_h264_W_altivec(uint8_t *block, int stride, int height, + int log2_denom, int weight, int offset, int w) +{ + int y, aligned; + vec_u8 vblock; + vec_s16 vtemp, vweight, voffset, v0, v1; + vec_u16 vlog2_denom; + DECLARE_ALIGNED(16, int32_t, temp)[4]; + LOAD_ZERO; + + offset <<= log2_denom; + if(log2_denom) offset += 1<<(log2_denom-1); + temp[0] = log2_denom; + temp[1] = weight; + temp[2] = offset; + + vtemp = (vec_s16)vec_ld(0, temp); + vlog2_denom = (vec_u16)vec_splat(vtemp, 1); + vweight = vec_splat(vtemp, 3); + voffset = vec_splat(vtemp, 5); + aligned = !((unsigned long)block & 0xf); + + for (y = 0; y < height; y++) { + vblock = vec_ld(0, block); + + v0 = (vec_s16)vec_mergeh(zero_u8v, vblock); + v1 = (vec_s16)vec_mergel(zero_u8v, vblock); + + if (w == 16 || aligned) { + v0 = vec_mladd(v0, vweight, zero_s16v); + v0 = vec_adds(v0, voffset); + v0 = vec_sra(v0, vlog2_denom); + } + if (w == 16 || !aligned) { + v1 = vec_mladd(v1, vweight, zero_s16v); + v1 = vec_adds(v1, voffset); + v1 = vec_sra(v1, vlog2_denom); + } + vblock = vec_packsu(v0, v1); + vec_st(vblock, 0, block); + + block += stride; + } +} + +static av_always_inline +void biweight_h264_W_altivec(uint8_t *dst, uint8_t *src, int stride, int height, + int log2_denom, int weightd, int weights, int offset, int w) +{ + int y, dst_aligned, src_aligned; + vec_u8 vsrc, vdst; + vec_s16 vtemp, vweights, vweightd, voffset, v0, v1, v2, v3; + vec_u16 vlog2_denom; + DECLARE_ALIGNED(16, int32_t, temp)[4]; + LOAD_ZERO; + + offset = ((offset + 1) | 1) << log2_denom; + temp[0] = log2_denom+1; + temp[1] = weights; + temp[2] = weightd; + temp[3] = offset; + + vtemp = (vec_s16)vec_ld(0, temp); + vlog2_denom = (vec_u16)vec_splat(vtemp, 1); + vweights = vec_splat(vtemp, 3); + vweightd = vec_splat(vtemp, 5); + voffset = vec_splat(vtemp, 7); + dst_aligned = !((unsigned long)dst & 0xf); + src_aligned = !((unsigned long)src & 0xf); + + for (y = 0; y < height; y++) { + vdst = vec_ld(0, dst); + vsrc = vec_ld(0, src); + + v0 = (vec_s16)vec_mergeh(zero_u8v, vdst); + v1 = (vec_s16)vec_mergel(zero_u8v, vdst); + v2 = (vec_s16)vec_mergeh(zero_u8v, vsrc); + v3 = (vec_s16)vec_mergel(zero_u8v, vsrc); + + if (w == 8) { + if (src_aligned) + v3 = v2; + else + v2 = v3; + } + + if (w == 16 || dst_aligned) { + v0 = vec_mladd(v0, vweightd, zero_s16v); + v2 = vec_mladd(v2, vweights, zero_s16v); + + v0 = vec_adds(v0, voffset); + v0 = vec_adds(v0, v2); + v0 = vec_sra(v0, vlog2_denom); + } + if (w == 16 || !dst_aligned) { + v1 = vec_mladd(v1, vweightd, zero_s16v); + v3 = vec_mladd(v3, vweights, zero_s16v); + + v1 = vec_adds(v1, voffset); + v1 = vec_adds(v1, v3); + v1 = vec_sra(v1, vlog2_denom); + } + vdst = vec_packsu(v0, v1); + vec_st(vdst, 0, dst); + + dst += stride; + src += stride; + } +} + +#define H264_WEIGHT(W) \ +static void ff_weight_h264_pixels ## W ## _altivec(uint8_t *block, int stride, int height, \ + int log2_denom, int weight, int offset){ \ + weight_h264_W_altivec(block, stride, height, log2_denom, weight, offset, W); \ +}\ +static void ff_biweight_h264_pixels ## W ## _altivec(uint8_t *dst, uint8_t *src, int stride, int height, \ + int log2_denom, int weightd, int weights, int offset){ \ + biweight_h264_W_altivec(dst, src, stride, height, log2_denom, weightd, weights, offset, W); \ +} + +H264_WEIGHT(16) +H264_WEIGHT( 8) + +av_cold void ff_h264dsp_init_ppc(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) +{ + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { + if (bit_depth == 8) { + c->h264_idct_add = ff_h264_idct_add_altivec; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_altivec; + c->h264_idct_add16 = ff_h264_idct_add16_altivec; + c->h264_idct_add16intra = ff_h264_idct_add16intra_altivec; + c->h264_idct_dc_add= h264_idct_dc_add_altivec; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_altivec; + c->h264_idct8_add = ff_h264_idct8_add_altivec; + c->h264_idct8_add4 = ff_h264_idct8_add4_altivec; + c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_altivec; + c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_altivec; + + c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels16_altivec; + c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels8_altivec; + c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_altivec; + c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_altivec; + } + } +} diff --git a/ffmpeg/libavcodec/ppc/h264_qpel.c b/ffmpeg/libavcodec/ppc/h264_qpel.c new file mode 100644 index 0000000..429ae42 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/h264_qpel.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2004 Romain Dolbeau + * + * 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 "config.h" +#include "libavutil/attributes.h" +#include "libavcodec/h264qpel.h" + +#if HAVE_ALTIVEC +#include "libavutil/cpu.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "dsputil_altivec.h" + +#define PUT_OP_U8_ALTIVEC(d, s, dst) d = s +#define AVG_OP_U8_ALTIVEC(d, s, dst) d = vec_avg(dst, s) + +#define OP_U8_ALTIVEC PUT_OP_U8_ALTIVEC +#define PREFIX_h264_qpel16_h_lowpass_altivec put_h264_qpel16_h_lowpass_altivec +#define PREFIX_h264_qpel16_h_lowpass_num altivec_put_h264_qpel16_h_lowpass_num +#define PREFIX_h264_qpel16_v_lowpass_altivec put_h264_qpel16_v_lowpass_altivec +#define PREFIX_h264_qpel16_v_lowpass_num altivec_put_h264_qpel16_v_lowpass_num +#define PREFIX_h264_qpel16_hv_lowpass_altivec put_h264_qpel16_hv_lowpass_altivec +#define PREFIX_h264_qpel16_hv_lowpass_num altivec_put_h264_qpel16_hv_lowpass_num +#include "h264_qpel_template.c" +#undef OP_U8_ALTIVEC +#undef PREFIX_h264_qpel16_h_lowpass_altivec +#undef PREFIX_h264_qpel16_h_lowpass_num +#undef PREFIX_h264_qpel16_v_lowpass_altivec +#undef PREFIX_h264_qpel16_v_lowpass_num +#undef PREFIX_h264_qpel16_hv_lowpass_altivec +#undef PREFIX_h264_qpel16_hv_lowpass_num + +#define OP_U8_ALTIVEC AVG_OP_U8_ALTIVEC +#define PREFIX_h264_qpel16_h_lowpass_altivec avg_h264_qpel16_h_lowpass_altivec +#define PREFIX_h264_qpel16_h_lowpass_num altivec_avg_h264_qpel16_h_lowpass_num +#define PREFIX_h264_qpel16_v_lowpass_altivec avg_h264_qpel16_v_lowpass_altivec +#define PREFIX_h264_qpel16_v_lowpass_num altivec_avg_h264_qpel16_v_lowpass_num +#define PREFIX_h264_qpel16_hv_lowpass_altivec avg_h264_qpel16_hv_lowpass_altivec +#define PREFIX_h264_qpel16_hv_lowpass_num altivec_avg_h264_qpel16_hv_lowpass_num +#include "h264_qpel_template.c" +#undef OP_U8_ALTIVEC +#undef PREFIX_h264_qpel16_h_lowpass_altivec +#undef PREFIX_h264_qpel16_h_lowpass_num +#undef PREFIX_h264_qpel16_v_lowpass_altivec +#undef PREFIX_h264_qpel16_v_lowpass_num +#undef PREFIX_h264_qpel16_hv_lowpass_altivec +#undef PREFIX_h264_qpel16_hv_lowpass_num + +#define H264_MC(OPNAME, SIZE, CODETYPE) \ +static void OPNAME ## h264_qpel ## SIZE ## _mc00_ ## CODETYPE (uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + ff_ ## OPNAME ## pixels ## SIZE ## _ ## CODETYPE(dst, src, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc10_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{ \ + DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(half, src, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src, half, stride, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc20_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc30_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(half, src, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src+1, half, stride, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc01_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(half, src, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src, half, stride, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc02_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc03_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(half, src, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src+stride, half, stride, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc11_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src, SIZE, stride);\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc31_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src, SIZE, stride);\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src+1, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc13_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src + stride, SIZE, stride);\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc33_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src + stride, SIZE, stride);\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src+1, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc22_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\ + OPNAME ## h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(dst, tmp, src, stride, SIZE, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc21_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src, SIZE, stride);\ + put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfHV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc23_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\ + put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src + stride, SIZE, stride);\ + put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfHV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc12_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src, SIZE, stride);\ + put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfV, halfHV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\ + DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\ + put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src+1, SIZE, stride);\ + put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\ + OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfV, halfHV, stride, SIZE, SIZE);\ +}\ + +static inline void put_pixels16_l2_altivec( uint8_t * dst, const uint8_t * src1, + const uint8_t * src2, int dst_stride, + int src_stride1, int h) +{ + int i; + vec_u8 a, b, d, tmp1, tmp2, mask, mask_, edges, align; + + mask_ = vec_lvsl(0, src2); + + for (i = 0; i < h; i++) { + + tmp1 = vec_ld(i * src_stride1, src1); + mask = vec_lvsl(i * src_stride1, src1); + tmp2 = vec_ld(i * src_stride1 + 15, src1); + + a = vec_perm(tmp1, tmp2, mask); + + tmp1 = vec_ld(i * 16, src2); + tmp2 = vec_ld(i * 16 + 15, src2); + + b = vec_perm(tmp1, tmp2, mask_); + + tmp1 = vec_ld(0, dst); + mask = vec_lvsl(0, dst); + tmp2 = vec_ld(15, dst); + + d = vec_avg(a, b); + + edges = vec_perm(tmp2, tmp1, mask); + + align = vec_lvsr(0, dst); + + tmp2 = vec_perm(d, edges, align); + tmp1 = vec_perm(edges, d, align); + + vec_st(tmp2, 15, dst); + vec_st(tmp1, 0 , dst); + + dst += dst_stride; + } +} + +static inline void avg_pixels16_l2_altivec( uint8_t * dst, const uint8_t * src1, + const uint8_t * src2, int dst_stride, + int src_stride1, int h) +{ + int i; + vec_u8 a, b, d, tmp1, tmp2, mask, mask_, edges, align; + + mask_ = vec_lvsl(0, src2); + + for (i = 0; i < h; i++) { + + tmp1 = vec_ld(i * src_stride1, src1); + mask = vec_lvsl(i * src_stride1, src1); + tmp2 = vec_ld(i * src_stride1 + 15, src1); + + a = vec_perm(tmp1, tmp2, mask); + + tmp1 = vec_ld(i * 16, src2); + tmp2 = vec_ld(i * 16 + 15, src2); + + b = vec_perm(tmp1, tmp2, mask_); + + tmp1 = vec_ld(0, dst); + mask = vec_lvsl(0, dst); + tmp2 = vec_ld(15, dst); + + d = vec_avg(vec_perm(tmp1, tmp2, mask), vec_avg(a, b)); + + edges = vec_perm(tmp2, tmp1, mask); + + align = vec_lvsr(0, dst); + + tmp2 = vec_perm(d, edges, align); + tmp1 = vec_perm(edges, d, align); + + vec_st(tmp2, 15, dst); + vec_st(tmp1, 0 , dst); + + dst += dst_stride; + } +} + +/* Implemented but could be faster +#define put_pixels16_l2_altivec(d,s1,s2,ds,s1s,h) put_pixels16_l2(d,s1,s2,ds,s1s,16,h) +#define avg_pixels16_l2_altivec(d,s1,s2,ds,s1s,h) avg_pixels16_l2(d,s1,s2,ds,s1s,16,h) + */ + +H264_MC(put_, 16, altivec) +H264_MC(avg_, 16, altivec) +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth) +{ +#if HAVE_ALTIVEC + const int high_bit_depth = bit_depth > 8; + + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { + if (!high_bit_depth) { +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_altivec; \ + c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_altivec; \ + c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_altivec; \ + c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_altivec; \ + c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_altivec; \ + c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_altivec; \ + c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_altivec; \ + c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_altivec; \ + c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_altivec; \ + c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_altivec; \ + c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_altivec; \ + c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_altivec; \ + c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_altivec; \ + c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_altivec; \ + c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_altivec; \ + c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_altivec + + dspfunc(put_h264_qpel, 0, 16); + dspfunc(avg_h264_qpel, 0, 16); +#undef dspfunc + } + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/ffmpeg/libavcodec/ppc/h264_qpel_template.c b/ffmpeg/libavcodec/ppc/h264_qpel_template.c new file mode 100644 index 0000000..cfc4560 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/h264_qpel_template.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2004 Romain Dolbeau + * + * 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 "libavutil/mem.h" + +#ifdef DEBUG +#define ASSERT_ALIGNED(ptr) assert(((unsigned long)ptr&0x0000000F)); +#else +#define ASSERT_ALIGNED(ptr) ; +#endif + +/* this code assume stride % 16 == 0 */ +#ifdef PREFIX_h264_qpel16_h_lowpass_altivec +static void PREFIX_h264_qpel16_h_lowpass_altivec(uint8_t * dst, uint8_t * src, int dstStride, int srcStride) { + register int i; + + LOAD_ZERO; + const vec_u8 permM2 = vec_lvsl(-2, src); + const vec_u8 permM1 = vec_lvsl(-1, src); + const vec_u8 permP0 = vec_lvsl(+0, src); + const vec_u8 permP1 = vec_lvsl(+1, src); + const vec_u8 permP2 = vec_lvsl(+2, src); + const vec_u8 permP3 = vec_lvsl(+3, src); + const vec_s16 v5ss = vec_splat_s16(5); + const vec_u16 v5us = vec_splat_u16(5); + const vec_s16 v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2)); + const vec_s16 v16ss = vec_sl(vec_splat_s16(1),vec_splat_u16(4)); + + vec_u8 srcM2, srcM1, srcP0, srcP1, srcP2, srcP3; + + register int align = ((((unsigned long)src) - 2) % 16); + + vec_s16 srcP0A, srcP0B, srcP1A, srcP1B, + srcP2A, srcP2B, srcP3A, srcP3B, + srcM1A, srcM1B, srcM2A, srcM2B, + sum1A, sum1B, sum2A, sum2B, sum3A, sum3B, + pp1A, pp1B, pp2A, pp2B, pp3A, pp3B, + psumA, psumB, sumA, sumB; + + vec_u8 sum, fsum; + + for (i = 0 ; i < 16 ; i ++) { + vec_u8 srcR1 = vec_ld(-2, src); + vec_u8 srcR2 = vec_ld(14, src); + + switch (align) { + default: { + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = vec_perm(srcR1, srcR2, permP1); + srcP2 = vec_perm(srcR1, srcR2, permP2); + srcP3 = vec_perm(srcR1, srcR2, permP3); + } break; + case 11: { + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = vec_perm(srcR1, srcR2, permP1); + srcP2 = vec_perm(srcR1, srcR2, permP2); + srcP3 = srcR2; + } break; + case 12: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = vec_perm(srcR1, srcR2, permP1); + srcP2 = srcR2; + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + case 13: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = srcR2; + srcP2 = vec_perm(srcR2, srcR3, permP2); + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + case 14: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = srcR2; + srcP1 = vec_perm(srcR2, srcR3, permP1); + srcP2 = vec_perm(srcR2, srcR3, permP2); + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + case 15: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = srcR2; + srcP0 = vec_perm(srcR2, srcR3, permP0); + srcP1 = vec_perm(srcR2, srcR3, permP1); + srcP2 = vec_perm(srcR2, srcR3, permP2); + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + } + + srcP0A = (vec_s16) vec_mergeh(zero_u8v, srcP0); + srcP0B = (vec_s16) vec_mergel(zero_u8v, srcP0); + srcP1A = (vec_s16) vec_mergeh(zero_u8v, srcP1); + srcP1B = (vec_s16) vec_mergel(zero_u8v, srcP1); + + srcP2A = (vec_s16) vec_mergeh(zero_u8v, srcP2); + srcP2B = (vec_s16) vec_mergel(zero_u8v, srcP2); + srcP3A = (vec_s16) vec_mergeh(zero_u8v, srcP3); + srcP3B = (vec_s16) vec_mergel(zero_u8v, srcP3); + + srcM1A = (vec_s16) vec_mergeh(zero_u8v, srcM1); + srcM1B = (vec_s16) vec_mergel(zero_u8v, srcM1); + srcM2A = (vec_s16) vec_mergeh(zero_u8v, srcM2); + srcM2B = (vec_s16) vec_mergel(zero_u8v, srcM2); + + sum1A = vec_adds(srcP0A, srcP1A); + sum1B = vec_adds(srcP0B, srcP1B); + sum2A = vec_adds(srcM1A, srcP2A); + sum2B = vec_adds(srcM1B, srcP2B); + sum3A = vec_adds(srcM2A, srcP3A); + sum3B = vec_adds(srcM2B, srcP3B); + + pp1A = vec_mladd(sum1A, v20ss, v16ss); + pp1B = vec_mladd(sum1B, v20ss, v16ss); + + pp2A = vec_mladd(sum2A, v5ss, zero_s16v); + pp2B = vec_mladd(sum2B, v5ss, zero_s16v); + + pp3A = vec_add(sum3A, pp1A); + pp3B = vec_add(sum3B, pp1B); + + psumA = vec_sub(pp3A, pp2A); + psumB = vec_sub(pp3B, pp2B); + + sumA = vec_sra(psumA, v5us); + sumB = vec_sra(psumB, v5us); + + sum = vec_packsu(sumA, sumB); + + ASSERT_ALIGNED(dst); + + OP_U8_ALTIVEC(fsum, sum, vec_ld(0, dst)); + + vec_st(fsum, 0, dst); + + src += srcStride; + dst += dstStride; + } +} +#endif + +/* this code assume stride % 16 == 0 */ +#ifdef PREFIX_h264_qpel16_v_lowpass_altivec +static void PREFIX_h264_qpel16_v_lowpass_altivec(uint8_t * dst, uint8_t * src, int dstStride, int srcStride) { + register int i; + + LOAD_ZERO; + const vec_u8 perm = vec_lvsl(0, src); + const vec_s16 v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2)); + const vec_u16 v5us = vec_splat_u16(5); + const vec_s16 v5ss = vec_splat_s16(5); + const vec_s16 v16ss = vec_sl(vec_splat_s16(1),vec_splat_u16(4)); + + uint8_t *srcbis = src - (srcStride * 2); + + const vec_u8 srcM2a = vec_ld(0, srcbis); + const vec_u8 srcM2b = vec_ld(16, srcbis); + const vec_u8 srcM2 = vec_perm(srcM2a, srcM2b, perm); + //srcbis += srcStride; + const vec_u8 srcM1a = vec_ld(0, srcbis += srcStride); + const vec_u8 srcM1b = vec_ld(16, srcbis); + const vec_u8 srcM1 = vec_perm(srcM1a, srcM1b, perm); + //srcbis += srcStride; + const vec_u8 srcP0a = vec_ld(0, srcbis += srcStride); + const vec_u8 srcP0b = vec_ld(16, srcbis); + const vec_u8 srcP0 = vec_perm(srcP0a, srcP0b, perm); + //srcbis += srcStride; + const vec_u8 srcP1a = vec_ld(0, srcbis += srcStride); + const vec_u8 srcP1b = vec_ld(16, srcbis); + const vec_u8 srcP1 = vec_perm(srcP1a, srcP1b, perm); + //srcbis += srcStride; + const vec_u8 srcP2a = vec_ld(0, srcbis += srcStride); + const vec_u8 srcP2b = vec_ld(16, srcbis); + const vec_u8 srcP2 = vec_perm(srcP2a, srcP2b, perm); + //srcbis += srcStride; + + vec_s16 srcM2ssA = (vec_s16) vec_mergeh(zero_u8v, srcM2); + vec_s16 srcM2ssB = (vec_s16) vec_mergel(zero_u8v, srcM2); + vec_s16 srcM1ssA = (vec_s16) vec_mergeh(zero_u8v, srcM1); + vec_s16 srcM1ssB = (vec_s16) vec_mergel(zero_u8v, srcM1); + vec_s16 srcP0ssA = (vec_s16) vec_mergeh(zero_u8v, srcP0); + vec_s16 srcP0ssB = (vec_s16) vec_mergel(zero_u8v, srcP0); + vec_s16 srcP1ssA = (vec_s16) vec_mergeh(zero_u8v, srcP1); + vec_s16 srcP1ssB = (vec_s16) vec_mergel(zero_u8v, srcP1); + vec_s16 srcP2ssA = (vec_s16) vec_mergeh(zero_u8v, srcP2); + vec_s16 srcP2ssB = (vec_s16) vec_mergel(zero_u8v, srcP2); + + vec_s16 pp1A, pp1B, pp2A, pp2B, pp3A, pp3B, + psumA, psumB, sumA, sumB, + srcP3ssA, srcP3ssB, + sum1A, sum1B, sum2A, sum2B, sum3A, sum3B; + + vec_u8 sum, fsum, srcP3a, srcP3b, srcP3; + + for (i = 0 ; i < 16 ; i++) { + srcP3a = vec_ld(0, srcbis += srcStride); + srcP3b = vec_ld(16, srcbis); + srcP3 = vec_perm(srcP3a, srcP3b, perm); + srcP3ssA = (vec_s16) vec_mergeh(zero_u8v, srcP3); + srcP3ssB = (vec_s16) vec_mergel(zero_u8v, srcP3); + //srcbis += srcStride; + + sum1A = vec_adds(srcP0ssA, srcP1ssA); + sum1B = vec_adds(srcP0ssB, srcP1ssB); + sum2A = vec_adds(srcM1ssA, srcP2ssA); + sum2B = vec_adds(srcM1ssB, srcP2ssB); + sum3A = vec_adds(srcM2ssA, srcP3ssA); + sum3B = vec_adds(srcM2ssB, srcP3ssB); + + srcM2ssA = srcM1ssA; + srcM2ssB = srcM1ssB; + srcM1ssA = srcP0ssA; + srcM1ssB = srcP0ssB; + srcP0ssA = srcP1ssA; + srcP0ssB = srcP1ssB; + srcP1ssA = srcP2ssA; + srcP1ssB = srcP2ssB; + srcP2ssA = srcP3ssA; + srcP2ssB = srcP3ssB; + + pp1A = vec_mladd(sum1A, v20ss, v16ss); + pp1B = vec_mladd(sum1B, v20ss, v16ss); + + pp2A = vec_mladd(sum2A, v5ss, zero_s16v); + pp2B = vec_mladd(sum2B, v5ss, zero_s16v); + + pp3A = vec_add(sum3A, pp1A); + pp3B = vec_add(sum3B, pp1B); + + psumA = vec_sub(pp3A, pp2A); + psumB = vec_sub(pp3B, pp2B); + + sumA = vec_sra(psumA, v5us); + sumB = vec_sra(psumB, v5us); + + sum = vec_packsu(sumA, sumB); + + ASSERT_ALIGNED(dst); + + OP_U8_ALTIVEC(fsum, sum, vec_ld(0, dst)); + + vec_st(fsum, 0, dst); + + dst += dstStride; + } +} +#endif + +/* this code assume stride % 16 == 0 *and* tmp is properly aligned */ +#ifdef PREFIX_h264_qpel16_hv_lowpass_altivec +static void PREFIX_h264_qpel16_hv_lowpass_altivec(uint8_t * dst, int16_t * tmp, uint8_t * src, int dstStride, int tmpStride, int srcStride) { + register int i; + LOAD_ZERO; + const vec_u8 permM2 = vec_lvsl(-2, src); + const vec_u8 permM1 = vec_lvsl(-1, src); + const vec_u8 permP0 = vec_lvsl(+0, src); + const vec_u8 permP1 = vec_lvsl(+1, src); + const vec_u8 permP2 = vec_lvsl(+2, src); + const vec_u8 permP3 = vec_lvsl(+3, src); + const vec_s16 v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2)); + const vec_u32 v10ui = vec_splat_u32(10); + const vec_s16 v5ss = vec_splat_s16(5); + const vec_s16 v1ss = vec_splat_s16(1); + const vec_s32 v512si = vec_sl(vec_splat_s32(1),vec_splat_u32(9)); + const vec_u32 v16ui = vec_sl(vec_splat_u32(1),vec_splat_u32(4)); + + register int align = ((((unsigned long)src) - 2) % 16); + + vec_s16 srcP0A, srcP0B, srcP1A, srcP1B, + srcP2A, srcP2B, srcP3A, srcP3B, + srcM1A, srcM1B, srcM2A, srcM2B, + sum1A, sum1B, sum2A, sum2B, sum3A, sum3B, + pp1A, pp1B, pp2A, pp2B, psumA, psumB; + + const vec_u8 mperm = (const vec_u8) + {0x00, 0x08, 0x01, 0x09, 0x02, 0x0A, 0x03, 0x0B, + 0x04, 0x0C, 0x05, 0x0D, 0x06, 0x0E, 0x07, 0x0F}; + int16_t *tmpbis = tmp; + + vec_s16 tmpM1ssA, tmpM1ssB, tmpM2ssA, tmpM2ssB, + tmpP0ssA, tmpP0ssB, tmpP1ssA, tmpP1ssB, + tmpP2ssA, tmpP2ssB; + + vec_s32 pp1Ae, pp1Ao, pp1Be, pp1Bo, pp2Ae, pp2Ao, pp2Be, pp2Bo, + pp3Ae, pp3Ao, pp3Be, pp3Bo, pp1cAe, pp1cAo, pp1cBe, pp1cBo, + pp32Ae, pp32Ao, pp32Be, pp32Bo, sumAe, sumAo, sumBe, sumBo, + ssumAe, ssumAo, ssumBe, ssumBo; + vec_u8 fsum, sumv, sum; + vec_s16 ssume, ssumo; + + src -= (2 * srcStride); + for (i = 0 ; i < 21 ; i ++) { + vec_u8 srcM2, srcM1, srcP0, srcP1, srcP2, srcP3; + vec_u8 srcR1 = vec_ld(-2, src); + vec_u8 srcR2 = vec_ld(14, src); + + switch (align) { + default: { + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = vec_perm(srcR1, srcR2, permP1); + srcP2 = vec_perm(srcR1, srcR2, permP2); + srcP3 = vec_perm(srcR1, srcR2, permP3); + } break; + case 11: { + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = vec_perm(srcR1, srcR2, permP1); + srcP2 = vec_perm(srcR1, srcR2, permP2); + srcP3 = srcR2; + } break; + case 12: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = vec_perm(srcR1, srcR2, permP1); + srcP2 = srcR2; + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + case 13: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = vec_perm(srcR1, srcR2, permP0); + srcP1 = srcR2; + srcP2 = vec_perm(srcR2, srcR3, permP2); + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + case 14: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = vec_perm(srcR1, srcR2, permM1); + srcP0 = srcR2; + srcP1 = vec_perm(srcR2, srcR3, permP1); + srcP2 = vec_perm(srcR2, srcR3, permP2); + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + case 15: { + vec_u8 srcR3 = vec_ld(30, src); + srcM2 = vec_perm(srcR1, srcR2, permM2); + srcM1 = srcR2; + srcP0 = vec_perm(srcR2, srcR3, permP0); + srcP1 = vec_perm(srcR2, srcR3, permP1); + srcP2 = vec_perm(srcR2, srcR3, permP2); + srcP3 = vec_perm(srcR2, srcR3, permP3); + } break; + } + + srcP0A = (vec_s16) vec_mergeh(zero_u8v, srcP0); + srcP0B = (vec_s16) vec_mergel(zero_u8v, srcP0); + srcP1A = (vec_s16) vec_mergeh(zero_u8v, srcP1); + srcP1B = (vec_s16) vec_mergel(zero_u8v, srcP1); + + srcP2A = (vec_s16) vec_mergeh(zero_u8v, srcP2); + srcP2B = (vec_s16) vec_mergel(zero_u8v, srcP2); + srcP3A = (vec_s16) vec_mergeh(zero_u8v, srcP3); + srcP3B = (vec_s16) vec_mergel(zero_u8v, srcP3); + + srcM1A = (vec_s16) vec_mergeh(zero_u8v, srcM1); + srcM1B = (vec_s16) vec_mergel(zero_u8v, srcM1); + srcM2A = (vec_s16) vec_mergeh(zero_u8v, srcM2); + srcM2B = (vec_s16) vec_mergel(zero_u8v, srcM2); + + sum1A = vec_adds(srcP0A, srcP1A); + sum1B = vec_adds(srcP0B, srcP1B); + sum2A = vec_adds(srcM1A, srcP2A); + sum2B = vec_adds(srcM1B, srcP2B); + sum3A = vec_adds(srcM2A, srcP3A); + sum3B = vec_adds(srcM2B, srcP3B); + + pp1A = vec_mladd(sum1A, v20ss, sum3A); + pp1B = vec_mladd(sum1B, v20ss, sum3B); + + pp2A = vec_mladd(sum2A, v5ss, zero_s16v); + pp2B = vec_mladd(sum2B, v5ss, zero_s16v); + + psumA = vec_sub(pp1A, pp2A); + psumB = vec_sub(pp1B, pp2B); + + vec_st(psumA, 0, tmp); + vec_st(psumB, 16, tmp); + + src += srcStride; + tmp += tmpStride; /* int16_t*, and stride is 16, so it's OK here */ + } + + tmpM2ssA = vec_ld(0, tmpbis); + tmpM2ssB = vec_ld(16, tmpbis); + tmpbis += tmpStride; + tmpM1ssA = vec_ld(0, tmpbis); + tmpM1ssB = vec_ld(16, tmpbis); + tmpbis += tmpStride; + tmpP0ssA = vec_ld(0, tmpbis); + tmpP0ssB = vec_ld(16, tmpbis); + tmpbis += tmpStride; + tmpP1ssA = vec_ld(0, tmpbis); + tmpP1ssB = vec_ld(16, tmpbis); + tmpbis += tmpStride; + tmpP2ssA = vec_ld(0, tmpbis); + tmpP2ssB = vec_ld(16, tmpbis); + tmpbis += tmpStride; + + for (i = 0 ; i < 16 ; i++) { + const vec_s16 tmpP3ssA = vec_ld(0, tmpbis); + const vec_s16 tmpP3ssB = vec_ld(16, tmpbis); + + const vec_s16 sum1A = vec_adds(tmpP0ssA, tmpP1ssA); + const vec_s16 sum1B = vec_adds(tmpP0ssB, tmpP1ssB); + const vec_s16 sum2A = vec_adds(tmpM1ssA, tmpP2ssA); + const vec_s16 sum2B = vec_adds(tmpM1ssB, tmpP2ssB); + const vec_s16 sum3A = vec_adds(tmpM2ssA, tmpP3ssA); + const vec_s16 sum3B = vec_adds(tmpM2ssB, tmpP3ssB); + + tmpbis += tmpStride; + + tmpM2ssA = tmpM1ssA; + tmpM2ssB = tmpM1ssB; + tmpM1ssA = tmpP0ssA; + tmpM1ssB = tmpP0ssB; + tmpP0ssA = tmpP1ssA; + tmpP0ssB = tmpP1ssB; + tmpP1ssA = tmpP2ssA; + tmpP1ssB = tmpP2ssB; + tmpP2ssA = tmpP3ssA; + tmpP2ssB = tmpP3ssB; + + pp1Ae = vec_mule(sum1A, v20ss); + pp1Ao = vec_mulo(sum1A, v20ss); + pp1Be = vec_mule(sum1B, v20ss); + pp1Bo = vec_mulo(sum1B, v20ss); + + pp2Ae = vec_mule(sum2A, v5ss); + pp2Ao = vec_mulo(sum2A, v5ss); + pp2Be = vec_mule(sum2B, v5ss); + pp2Bo = vec_mulo(sum2B, v5ss); + + pp3Ae = vec_sra((vec_s32)sum3A, v16ui); + pp3Ao = vec_mulo(sum3A, v1ss); + pp3Be = vec_sra((vec_s32)sum3B, v16ui); + pp3Bo = vec_mulo(sum3B, v1ss); + + pp1cAe = vec_add(pp1Ae, v512si); + pp1cAo = vec_add(pp1Ao, v512si); + pp1cBe = vec_add(pp1Be, v512si); + pp1cBo = vec_add(pp1Bo, v512si); + + pp32Ae = vec_sub(pp3Ae, pp2Ae); + pp32Ao = vec_sub(pp3Ao, pp2Ao); + pp32Be = vec_sub(pp3Be, pp2Be); + pp32Bo = vec_sub(pp3Bo, pp2Bo); + + sumAe = vec_add(pp1cAe, pp32Ae); + sumAo = vec_add(pp1cAo, pp32Ao); + sumBe = vec_add(pp1cBe, pp32Be); + sumBo = vec_add(pp1cBo, pp32Bo); + + ssumAe = vec_sra(sumAe, v10ui); + ssumAo = vec_sra(sumAo, v10ui); + ssumBe = vec_sra(sumBe, v10ui); + ssumBo = vec_sra(sumBo, v10ui); + + ssume = vec_packs(ssumAe, ssumBe); + ssumo = vec_packs(ssumAo, ssumBo); + + sumv = vec_packsu(ssume, ssumo); + sum = vec_perm(sumv, sumv, mperm); + + ASSERT_ALIGNED(dst); + + OP_U8_ALTIVEC(fsum, sum, vec_ld(0, dst)); + + vec_st(fsum, 0, dst); + + dst += dstStride; + } +} +#endif diff --git a/ffmpeg/libavcodec/ppc/h264chroma_init.c b/ffmpeg/libavcodec/ppc/h264chroma_init.c new file mode 100644 index 0000000..f9e2a76 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/h264chroma_init.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2004 Romain Dolbeau + * + * 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 "config.h" +#include "libavutil/attributes.h" +#include "libavcodec/h264chroma.h" + +#if HAVE_ALTIVEC +#include "libavutil/cpu.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "dsputil_altivec.h" + +#define PUT_OP_U8_ALTIVEC(d, s, dst) d = s +#define AVG_OP_U8_ALTIVEC(d, s, dst) d = vec_avg(dst, s) + +#define OP_U8_ALTIVEC PUT_OP_U8_ALTIVEC +#define PREFIX_h264_chroma_mc8_altivec put_h264_chroma_mc8_altivec +#define PREFIX_h264_chroma_mc8_num altivec_put_h264_chroma_mc8_num +#include "h264chroma_template.c" +#undef OP_U8_ALTIVEC +#undef PREFIX_h264_chroma_mc8_altivec +#undef PREFIX_h264_chroma_mc8_num + +#define OP_U8_ALTIVEC AVG_OP_U8_ALTIVEC +#define PREFIX_h264_chroma_mc8_altivec avg_h264_chroma_mc8_altivec +#define PREFIX_h264_chroma_mc8_num altivec_avg_h264_chroma_mc8_num +#include "h264chroma_template.c" +#undef OP_U8_ALTIVEC +#undef PREFIX_h264_chroma_mc8_altivec +#undef PREFIX_h264_chroma_mc8_num +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_h264chroma_init_ppc(H264ChromaContext *c, int bit_depth) +{ +#if HAVE_ALTIVEC + const int high_bit_depth = bit_depth > 8; + + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { + if (!high_bit_depth) { + c->put_h264_chroma_pixels_tab[0] = put_h264_chroma_mc8_altivec; + c->avg_h264_chroma_pixels_tab[0] = avg_h264_chroma_mc8_altivec; + } + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/ffmpeg/libavcodec/ppc/h264chroma_template.c b/ffmpeg/libavcodec/ppc/h264chroma_template.c new file mode 100644 index 0000000..7436e11 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/h264chroma_template.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2004 Romain Dolbeau + * + * 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 "libavutil/mem.h" + +/* this code assume that stride % 16 == 0 */ + +#define CHROMA_MC8_ALTIVEC_CORE(BIAS1, BIAS2) \ + vsrc2ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc2uc);\ + vsrc3ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc3uc);\ +\ + psum = vec_mladd(vA, vsrc0ssH, BIAS1);\ + psum = vec_mladd(vB, vsrc1ssH, psum);\ + psum = vec_mladd(vC, vsrc2ssH, psum);\ + psum = vec_mladd(vD, vsrc3ssH, psum);\ + psum = BIAS2(psum);\ + psum = vec_sr(psum, v6us);\ +\ + vdst = vec_ld(0, dst);\ + ppsum = (vec_u8)vec_pack(psum, psum);\ + vfdst = vec_perm(vdst, ppsum, fperm);\ +\ + OP_U8_ALTIVEC(fsum, vfdst, vdst);\ +\ + vec_st(fsum, 0, dst);\ +\ + vsrc0ssH = vsrc2ssH;\ + vsrc1ssH = vsrc3ssH;\ +\ + dst += stride;\ + src += stride; + +#define CHROMA_MC8_ALTIVEC_CORE_SIMPLE \ +\ + vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc0uc);\ + vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc1uc);\ +\ + psum = vec_mladd(vA, vsrc0ssH, v32ss);\ + psum = vec_mladd(vE, vsrc1ssH, psum);\ + psum = vec_sr(psum, v6us);\ +\ + vdst = vec_ld(0, dst);\ + ppsum = (vec_u8)vec_pack(psum, psum);\ + vfdst = vec_perm(vdst, ppsum, fperm);\ +\ + OP_U8_ALTIVEC(fsum, vfdst, vdst);\ +\ + vec_st(fsum, 0, dst);\ +\ + dst += stride;\ + src += stride; + +#define noop(a) a +#define add28(a) vec_add(v28ss, a) + +#ifdef PREFIX_h264_chroma_mc8_altivec +static void PREFIX_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src, + int stride, int h, int x, int y) { + DECLARE_ALIGNED(16, signed int, ABCD)[4] = + {((8 - x) * (8 - y)), + (( x) * (8 - y)), + ((8 - x) * ( y)), + (( x) * ( y))}; + register int i; + vec_u8 fperm; + const vec_s32 vABCD = vec_ld(0, ABCD); + const vec_s16 vA = vec_splat((vec_s16)vABCD, 1); + const vec_s16 vB = vec_splat((vec_s16)vABCD, 3); + const vec_s16 vC = vec_splat((vec_s16)vABCD, 5); + const vec_s16 vD = vec_splat((vec_s16)vABCD, 7); + LOAD_ZERO; + const vec_s16 v32ss = vec_sl(vec_splat_s16(1),vec_splat_u16(5)); + const vec_u16 v6us = vec_splat_u16(6); + register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1; + register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0; + + vec_u8 vsrcAuc, av_uninit(vsrcBuc), vsrcperm0, vsrcperm1; + vec_u8 vsrc0uc, vsrc1uc; + vec_s16 vsrc0ssH, vsrc1ssH; + vec_u8 vsrcCuc, vsrc2uc, vsrc3uc; + vec_s16 vsrc2ssH, vsrc3ssH, psum; + vec_u8 vdst, ppsum, vfdst, fsum; + + if (((unsigned long)dst) % 16 == 0) { + fperm = (vec_u8){0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F}; + } else { + fperm = (vec_u8){0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F}; + } + + vsrcAuc = vec_ld(0, src); + + if (loadSecond) + vsrcBuc = vec_ld(16, src); + vsrcperm0 = vec_lvsl(0, src); + vsrcperm1 = vec_lvsl(1, src); + + vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0); + if (reallyBadAlign) + vsrc1uc = vsrcBuc; + else + vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1); + + vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc0uc); + vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc1uc); + + if (ABCD[3]) { + if (!loadSecond) {// -> !reallyBadAlign + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(stride + 0, src); + vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0); + vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1); + + CHROMA_MC8_ALTIVEC_CORE(v32ss, noop) + } + } else { + vec_u8 vsrcDuc; + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(stride + 0, src); + vsrcDuc = vec_ld(stride + 16, src); + vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0); + if (reallyBadAlign) + vsrc3uc = vsrcDuc; + else + vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1); + + CHROMA_MC8_ALTIVEC_CORE(v32ss, noop) + } + } + } else { + const vec_s16 vE = vec_add(vB, vC); + if (ABCD[2]) { // x == 0 B == 0 + if (!loadSecond) {// -> !reallyBadAlign + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(stride + 0, src); + vsrc1uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0); + CHROMA_MC8_ALTIVEC_CORE_SIMPLE + + vsrc0uc = vsrc1uc; + } + } else { + vec_u8 vsrcDuc; + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(stride + 0, src); + vsrcDuc = vec_ld(stride + 15, src); + vsrc1uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0); + CHROMA_MC8_ALTIVEC_CORE_SIMPLE + + vsrc0uc = vsrc1uc; + } + } + } else { // y == 0 C == 0 + if (!loadSecond) {// -> !reallyBadAlign + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(0, src); + vsrc0uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0); + vsrc1uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1); + + CHROMA_MC8_ALTIVEC_CORE_SIMPLE + } + } else { + vec_u8 vsrcDuc; + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(0, src); + vsrcDuc = vec_ld(15, src); + vsrc0uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0); + if (reallyBadAlign) + vsrc1uc = vsrcDuc; + else + vsrc1uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1); + + CHROMA_MC8_ALTIVEC_CORE_SIMPLE + } + } + } + } +} +#endif + +/* this code assume that stride % 16 == 0 */ +#ifdef PREFIX_no_rnd_vc1_chroma_mc8_altivec +static void PREFIX_no_rnd_vc1_chroma_mc8_altivec(uint8_t * dst, uint8_t * src, int stride, int h, int x, int y) { + DECLARE_ALIGNED(16, signed int, ABCD)[4] = + {((8 - x) * (8 - y)), + (( x) * (8 - y)), + ((8 - x) * ( y)), + (( x) * ( y))}; + register int i; + vec_u8 fperm; + const vec_s32 vABCD = vec_ld(0, ABCD); + const vec_s16 vA = vec_splat((vec_s16)vABCD, 1); + const vec_s16 vB = vec_splat((vec_s16)vABCD, 3); + const vec_s16 vC = vec_splat((vec_s16)vABCD, 5); + const vec_s16 vD = vec_splat((vec_s16)vABCD, 7); + LOAD_ZERO; + const vec_s16 v28ss = vec_sub(vec_sl(vec_splat_s16(1),vec_splat_u16(5)),vec_splat_s16(4)); + const vec_u16 v6us = vec_splat_u16(6); + register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1; + register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0; + + vec_u8 vsrcAuc, av_uninit(vsrcBuc), vsrcperm0, vsrcperm1; + vec_u8 vsrc0uc, vsrc1uc; + vec_s16 vsrc0ssH, vsrc1ssH; + vec_u8 vsrcCuc, vsrc2uc, vsrc3uc; + vec_s16 vsrc2ssH, vsrc3ssH, psum; + vec_u8 vdst, ppsum, vfdst, fsum; + + if (((unsigned long)dst) % 16 == 0) { + fperm = (vec_u8){0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, + 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F}; + } else { + fperm = (vec_u8){0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, + 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x1F}; + } + + vsrcAuc = vec_ld(0, src); + + if (loadSecond) + vsrcBuc = vec_ld(16, src); + vsrcperm0 = vec_lvsl(0, src); + vsrcperm1 = vec_lvsl(1, src); + + vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0); + if (reallyBadAlign) + vsrc1uc = vsrcBuc; + else + vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1); + + vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v, (vec_u8)vsrc0uc); + vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v, (vec_u8)vsrc1uc); + + if (!loadSecond) {// -> !reallyBadAlign + for (i = 0 ; i < h ; i++) { + + + vsrcCuc = vec_ld(stride + 0, src); + + vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0); + vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1); + + CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28) + } + } else { + vec_u8 vsrcDuc; + for (i = 0 ; i < h ; i++) { + vsrcCuc = vec_ld(stride + 0, src); + vsrcDuc = vec_ld(stride + 16, src); + + vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0); + if (reallyBadAlign) + vsrc3uc = vsrcDuc; + else + vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1); + + CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28) + } + } +} +#endif + +#undef noop +#undef add28 +#undef CHROMA_MC8_ALTIVEC_CORE diff --git a/ffmpeg/libavcodec/ppc/hpeldsp_altivec.c b/ffmpeg/libavcodec/ppc/hpeldsp_altivec.c new file mode 100644 index 0000000..4309d39 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/hpeldsp_altivec.c @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2002 Brian Foley + * Copyright (c) 2002 Dieter Shirley + * Copyright (c) 2003-2004 Romain Dolbeau + * + * 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 "config.h" +#include "libavutil/cpu.h" +#include "libavcodec/hpeldsp.h" + +#if HAVE_ALTIVEC +#if HAVE_ALTIVEC_H +#include +#endif +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "dsputil_altivec.h" + +/* next one assumes that ((line_size % 16) == 0) */ +void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + register vector unsigned char pixelsv1, pixelsv2; + register vector unsigned char pixelsv1B, pixelsv2B; + register vector unsigned char pixelsv1C, pixelsv2C; + register vector unsigned char pixelsv1D, pixelsv2D; + + register vector unsigned char perm = vec_lvsl(0, pixels); + int i; + register ptrdiff_t line_size_2 = line_size << 1; + register ptrdiff_t line_size_3 = line_size + line_size_2; + register ptrdiff_t line_size_4 = line_size << 2; + +// hand-unrolling the loop by 4 gains about 15% +// mininum execution time goes from 74 to 60 cycles +// it's faster than -funroll-loops, but using +// -funroll-loops w/ this is bad - 74 cycles again. +// all this is on a 7450, tuning for the 7450 + for (i = 0; i < h; i += 4) { + pixelsv1 = vec_ld( 0, pixels); + pixelsv2 = vec_ld(15, pixels); + pixelsv1B = vec_ld(line_size, pixels); + pixelsv2B = vec_ld(15 + line_size, pixels); + pixelsv1C = vec_ld(line_size_2, pixels); + pixelsv2C = vec_ld(15 + line_size_2, pixels); + pixelsv1D = vec_ld(line_size_3, pixels); + pixelsv2D = vec_ld(15 + line_size_3, pixels); + vec_st(vec_perm(pixelsv1, pixelsv2, perm), + 0, (unsigned char*)block); + vec_st(vec_perm(pixelsv1B, pixelsv2B, perm), + line_size, (unsigned char*)block); + vec_st(vec_perm(pixelsv1C, pixelsv2C, perm), + line_size_2, (unsigned char*)block); + vec_st(vec_perm(pixelsv1D, pixelsv2D, perm), + line_size_3, (unsigned char*)block); + pixels+=line_size_4; + block +=line_size_4; + } +} + +/* next one assumes that ((line_size % 16) == 0) */ +#define op_avg(a,b) a = ( ((a)|(b)) - ((((a)^(b))&0xFEFEFEFEUL)>>1) ) +void ff_avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv; + register vector unsigned char perm = vec_lvsl(0, pixels); + int i; + + for (i = 0; i < h; i++) { + pixelsv1 = vec_ld( 0, pixels); + pixelsv2 = vec_ld(16,pixels); + blockv = vec_ld(0, block); + pixelsv = vec_perm(pixelsv1, pixelsv2, perm); + blockv = vec_avg(blockv,pixelsv); + vec_st(blockv, 0, (unsigned char*)block); + pixels+=line_size; + block +=line_size; + } +} + +/* next one assumes that ((line_size % 8) == 0) */ +static void avg_pixels8_altivec(uint8_t * block, const uint8_t * pixels, ptrdiff_t line_size, int h) +{ + register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv; + int i; + + for (i = 0; i < h; i++) { + /* block is 8 bytes-aligned, so we're either in the + left block (16 bytes-aligned) or in the right block (not) */ + int rightside = ((unsigned long)block & 0x0000000F); + + blockv = vec_ld(0, block); + pixelsv1 = vec_ld( 0, pixels); + pixelsv2 = vec_ld(16, pixels); + pixelsv = vec_perm(pixelsv1, pixelsv2, vec_lvsl(0, pixels)); + + if (rightside) { + pixelsv = vec_perm(blockv, pixelsv, vcprm(0,1,s0,s1)); + } else { + pixelsv = vec_perm(blockv, pixelsv, vcprm(s0,s1,2,3)); + } + + blockv = vec_avg(blockv, pixelsv); + + vec_st(blockv, 0, block); + + pixels += line_size; + block += line_size; + } +} + +/* next one assumes that ((line_size % 8) == 0) */ +static void put_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + register int i; + register vector unsigned char pixelsv1, pixelsv2, pixelsavg; + register vector unsigned char blockv, temp1, temp2; + register vector unsigned short pixelssum1, pixelssum2, temp3; + register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0); + register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2); + + temp1 = vec_ld(0, pixels); + temp2 = vec_ld(16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels)); + if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels)); + } + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum1 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + pixelssum1 = vec_add(pixelssum1, vctwo); + + for (i = 0; i < h ; i++) { + int rightside = ((unsigned long)block & 0x0000000F); + blockv = vec_ld(0, block); + + temp1 = vec_ld(line_size, pixels); + temp2 = vec_ld(line_size + 16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels)); + if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels)); + } + + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum2 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + temp3 = vec_add(pixelssum1, pixelssum2); + temp3 = vec_sra(temp3, vctwo); + pixelssum1 = vec_add(pixelssum2, vctwo); + pixelsavg = vec_packsu(temp3, (vector unsigned short) vczero); + + if (rightside) { + blockv = vec_perm(blockv, pixelsavg, vcprm(0, 1, s0, s1)); + } else { + blockv = vec_perm(blockv, pixelsavg, vcprm(s0, s1, 2, 3)); + } + + vec_st(blockv, 0, block); + + block += line_size; + pixels += line_size; + } +} + +/* next one assumes that ((line_size % 8) == 0) */ +static void put_no_rnd_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + register int i; + register vector unsigned char pixelsv1, pixelsv2, pixelsavg; + register vector unsigned char blockv, temp1, temp2; + register vector unsigned short pixelssum1, pixelssum2, temp3; + register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0); + register const vector unsigned short vcone = (const vector unsigned short)vec_splat_u16(1); + register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2); + + temp1 = vec_ld(0, pixels); + temp2 = vec_ld(16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels)); + if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels)); + } + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum1 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + pixelssum1 = vec_add(pixelssum1, vcone); + + for (i = 0; i < h ; i++) { + int rightside = ((unsigned long)block & 0x0000000F); + blockv = vec_ld(0, block); + + temp1 = vec_ld(line_size, pixels); + temp2 = vec_ld(line_size + 16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels)); + if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels)); + } + + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum2 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + temp3 = vec_add(pixelssum1, pixelssum2); + temp3 = vec_sra(temp3, vctwo); + pixelssum1 = vec_add(pixelssum2, vcone); + pixelsavg = vec_packsu(temp3, (vector unsigned short) vczero); + + if (rightside) { + blockv = vec_perm(blockv, pixelsavg, vcprm(0, 1, s0, s1)); + } else { + blockv = vec_perm(blockv, pixelsavg, vcprm(s0, s1, 2, 3)); + } + + vec_st(blockv, 0, block); + + block += line_size; + pixels += line_size; + } +} + +/* next one assumes that ((line_size % 16) == 0) */ +static void put_pixels16_xy2_altivec(uint8_t * block, const uint8_t * pixels, ptrdiff_t line_size, int h) +{ + register int i; + register vector unsigned char pixelsv1, pixelsv2, pixelsv3, pixelsv4; + register vector unsigned char blockv, temp1, temp2; + register vector unsigned short temp3, temp4, + pixelssum1, pixelssum2, pixelssum3, pixelssum4; + register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0); + register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2); + + temp1 = vec_ld(0, pixels); + temp2 = vec_ld(16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels)); + if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels)); + } + pixelsv3 = vec_mergel(vczero, pixelsv1); + pixelsv4 = vec_mergel(vczero, pixelsv2); + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum3 = vec_add((vector unsigned short)pixelsv3, + (vector unsigned short)pixelsv4); + pixelssum3 = vec_add(pixelssum3, vctwo); + pixelssum1 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + pixelssum1 = vec_add(pixelssum1, vctwo); + + for (i = 0; i < h ; i++) { + blockv = vec_ld(0, block); + + temp1 = vec_ld(line_size, pixels); + temp2 = vec_ld(line_size + 16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels)); + if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels)); + } + + pixelsv3 = vec_mergel(vczero, pixelsv1); + pixelsv4 = vec_mergel(vczero, pixelsv2); + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + + pixelssum4 = vec_add((vector unsigned short)pixelsv3, + (vector unsigned short)pixelsv4); + pixelssum2 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + temp4 = vec_add(pixelssum3, pixelssum4); + temp4 = vec_sra(temp4, vctwo); + temp3 = vec_add(pixelssum1, pixelssum2); + temp3 = vec_sra(temp3, vctwo); + + pixelssum3 = vec_add(pixelssum4, vctwo); + pixelssum1 = vec_add(pixelssum2, vctwo); + + blockv = vec_packsu(temp3, temp4); + + vec_st(blockv, 0, block); + + block += line_size; + pixels += line_size; + } +} + +/* next one assumes that ((line_size % 16) == 0) */ +static void put_no_rnd_pixels16_xy2_altivec(uint8_t * block, const uint8_t * pixels, ptrdiff_t line_size, int h) +{ + register int i; + register vector unsigned char pixelsv1, pixelsv2, pixelsv3, pixelsv4; + register vector unsigned char blockv, temp1, temp2; + register vector unsigned short temp3, temp4, + pixelssum1, pixelssum2, pixelssum3, pixelssum4; + register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0); + register const vector unsigned short vcone = (const vector unsigned short)vec_splat_u16(1); + register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2); + + temp1 = vec_ld(0, pixels); + temp2 = vec_ld(16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels)); + if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels)); + } + pixelsv3 = vec_mergel(vczero, pixelsv1); + pixelsv4 = vec_mergel(vczero, pixelsv2); + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum3 = vec_add((vector unsigned short)pixelsv3, + (vector unsigned short)pixelsv4); + pixelssum3 = vec_add(pixelssum3, vcone); + pixelssum1 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + pixelssum1 = vec_add(pixelssum1, vcone); + + for (i = 0; i < h ; i++) { + blockv = vec_ld(0, block); + + temp1 = vec_ld(line_size, pixels); + temp2 = vec_ld(line_size + 16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels)); + if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels)); + } + + pixelsv3 = vec_mergel(vczero, pixelsv1); + pixelsv4 = vec_mergel(vczero, pixelsv2); + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + + pixelssum4 = vec_add((vector unsigned short)pixelsv3, + (vector unsigned short)pixelsv4); + pixelssum2 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + temp4 = vec_add(pixelssum3, pixelssum4); + temp4 = vec_sra(temp4, vctwo); + temp3 = vec_add(pixelssum1, pixelssum2); + temp3 = vec_sra(temp3, vctwo); + + pixelssum3 = vec_add(pixelssum4, vcone); + pixelssum1 = vec_add(pixelssum2, vcone); + + blockv = vec_packsu(temp3, temp4); + + vec_st(blockv, 0, block); + + block += line_size; + pixels += line_size; + } +} + +/* next one assumes that ((line_size % 8) == 0) */ +static void avg_pixels8_xy2_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + register int i; + register vector unsigned char pixelsv1, pixelsv2, pixelsavg; + register vector unsigned char blockv, temp1, temp2, blocktemp; + register vector unsigned short pixelssum1, pixelssum2, temp3; + + register const vector unsigned char vczero = (const vector unsigned char) + vec_splat_u8(0); + register const vector unsigned short vctwo = (const vector unsigned short) + vec_splat_u16(2); + + temp1 = vec_ld(0, pixels); + temp2 = vec_ld(16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels)); + if ((((unsigned long)pixels) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels)); + } + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum1 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + pixelssum1 = vec_add(pixelssum1, vctwo); + + for (i = 0; i < h ; i++) { + int rightside = ((unsigned long)block & 0x0000000F); + blockv = vec_ld(0, block); + + temp1 = vec_ld(line_size, pixels); + temp2 = vec_ld(line_size + 16, pixels); + pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels)); + if (((((unsigned long)pixels) + line_size) & 0x0000000F) == 0x0000000F) { + pixelsv2 = temp2; + } else { + pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels)); + } + + pixelsv1 = vec_mergeh(vczero, pixelsv1); + pixelsv2 = vec_mergeh(vczero, pixelsv2); + pixelssum2 = vec_add((vector unsigned short)pixelsv1, + (vector unsigned short)pixelsv2); + temp3 = vec_add(pixelssum1, pixelssum2); + temp3 = vec_sra(temp3, vctwo); + pixelssum1 = vec_add(pixelssum2, vctwo); + pixelsavg = vec_packsu(temp3, (vector unsigned short) vczero); + + if (rightside) { + blocktemp = vec_perm(blockv, pixelsavg, vcprm(0, 1, s0, s1)); + } else { + blocktemp = vec_perm(blockv, pixelsavg, vcprm(s0, s1, 2, 3)); + } + + blockv = vec_avg(blocktemp, blockv); + vec_st(blockv, 0, block); + + block += line_size; + pixels += line_size; + } +} +#endif /* HAVE_ALTIVEC */ + +void ff_hpeldsp_init_ppc(HpelDSPContext* c, int flags) +{ +#if HAVE_ALTIVEC + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_ALTIVEC) { + c->put_pixels_tab[0][0] = ff_put_pixels16_altivec; + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_altivec; + c->avg_pixels_tab[0][0] = ff_avg_pixels16_altivec; + c->avg_pixels_tab[1][0] = avg_pixels8_altivec; + c->avg_pixels_tab[1][3] = avg_pixels8_xy2_altivec; + c->put_pixels_tab[1][3] = put_pixels8_xy2_altivec; + c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_altivec; + c->put_pixels_tab[0][3] = put_pixels16_xy2_altivec; + c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_altivec; + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/ffmpeg/libavcodec/ppc/idct_altivec.c b/ffmpeg/libavcodec/ppc/idct_altivec.c new file mode 100644 index 0000000..c6f2cd8 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/idct_altivec.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2001 Michel Lespinasse + * + * 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 + */ + +/* + * NOTE: This code is based on GPL code from the libmpeg2 project. The + * author, Michel Lespinasses, has given explicit permission to release + * under LGPL as part of FFmpeg. + */ + +/* + * FFmpeg integration by Dieter Shirley + * + * This file is a direct copy of the AltiVec IDCT module from the libmpeg2 + * project. I've deleted all of the libmpeg2-specific code, renamed the + * functions and reordered the function parameters. The only change to the + * IDCT function itself was to factor out the partial transposition, and to + * perform a full transpose at the end of the function. + */ + + +#include /* malloc(), free() */ +#include +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif +#include "libavutil/ppc/types_altivec.h" +#include "dsputil_altivec.h" + +#define IDCT_HALF \ + /* 1st stage */ \ + t1 = vec_mradds (a1, vx7, vx1 ); \ + t8 = vec_mradds (a1, vx1, vec_subs (zero, vx7)); \ + t7 = vec_mradds (a2, vx5, vx3); \ + t3 = vec_mradds (ma2, vx3, vx5); \ + \ + /* 2nd stage */ \ + t5 = vec_adds (vx0, vx4); \ + t0 = vec_subs (vx0, vx4); \ + t2 = vec_mradds (a0, vx6, vx2); \ + t4 = vec_mradds (a0, vx2, vec_subs (zero, vx6)); \ + t6 = vec_adds (t8, t3); \ + t3 = vec_subs (t8, t3); \ + t8 = vec_subs (t1, t7); \ + t1 = vec_adds (t1, t7); \ + \ + /* 3rd stage */ \ + t7 = vec_adds (t5, t2); \ + t2 = vec_subs (t5, t2); \ + t5 = vec_adds (t0, t4); \ + t0 = vec_subs (t0, t4); \ + t4 = vec_subs (t8, t3); \ + t3 = vec_adds (t8, t3); \ + \ + /* 4th stage */ \ + vy0 = vec_adds (t7, t1); \ + vy7 = vec_subs (t7, t1); \ + vy1 = vec_mradds (c4, t3, t5); \ + vy6 = vec_mradds (mc4, t3, t5); \ + vy2 = vec_mradds (c4, t4, t0); \ + vy5 = vec_mradds (mc4, t4, t0); \ + vy3 = vec_adds (t2, t6); \ + vy4 = vec_subs (t2, t6); + + +#define IDCT \ + vec_s16 vx0, vx1, vx2, vx3, vx4, vx5, vx6, vx7; \ + vec_s16 vy0, vy1, vy2, vy3, vy4, vy5, vy6, vy7; \ + vec_s16 a0, a1, a2, ma2, c4, mc4, zero, bias; \ + vec_s16 t0, t1, t2, t3, t4, t5, t6, t7, t8; \ + vec_u16 shift; \ + \ + c4 = vec_splat (constants[0], 0); \ + a0 = vec_splat (constants[0], 1); \ + a1 = vec_splat (constants[0], 2); \ + a2 = vec_splat (constants[0], 3); \ + mc4 = vec_splat (constants[0], 4); \ + ma2 = vec_splat (constants[0], 5); \ + bias = (vec_s16)vec_splat ((vec_s32)constants[0], 3); \ + \ + zero = vec_splat_s16 (0); \ + shift = vec_splat_u16 (4); \ + \ + vx0 = vec_mradds (vec_sl (block[0], shift), constants[1], zero); \ + vx1 = vec_mradds (vec_sl (block[1], shift), constants[2], zero); \ + vx2 = vec_mradds (vec_sl (block[2], shift), constants[3], zero); \ + vx3 = vec_mradds (vec_sl (block[3], shift), constants[4], zero); \ + vx4 = vec_mradds (vec_sl (block[4], shift), constants[1], zero); \ + vx5 = vec_mradds (vec_sl (block[5], shift), constants[4], zero); \ + vx6 = vec_mradds (vec_sl (block[6], shift), constants[3], zero); \ + vx7 = vec_mradds (vec_sl (block[7], shift), constants[2], zero); \ + \ + IDCT_HALF \ + \ + vx0 = vec_mergeh (vy0, vy4); \ + vx1 = vec_mergel (vy0, vy4); \ + vx2 = vec_mergeh (vy1, vy5); \ + vx3 = vec_mergel (vy1, vy5); \ + vx4 = vec_mergeh (vy2, vy6); \ + vx5 = vec_mergel (vy2, vy6); \ + vx6 = vec_mergeh (vy3, vy7); \ + vx7 = vec_mergel (vy3, vy7); \ + \ + vy0 = vec_mergeh (vx0, vx4); \ + vy1 = vec_mergel (vx0, vx4); \ + vy2 = vec_mergeh (vx1, vx5); \ + vy3 = vec_mergel (vx1, vx5); \ + vy4 = vec_mergeh (vx2, vx6); \ + vy5 = vec_mergel (vx2, vx6); \ + vy6 = vec_mergeh (vx3, vx7); \ + vy7 = vec_mergel (vx3, vx7); \ + \ + vx0 = vec_adds (vec_mergeh (vy0, vy4), bias); \ + vx1 = vec_mergel (vy0, vy4); \ + vx2 = vec_mergeh (vy1, vy5); \ + vx3 = vec_mergel (vy1, vy5); \ + vx4 = vec_mergeh (vy2, vy6); \ + vx5 = vec_mergel (vy2, vy6); \ + vx6 = vec_mergeh (vy3, vy7); \ + vx7 = vec_mergel (vy3, vy7); \ + \ + IDCT_HALF \ + \ + shift = vec_splat_u16 (6); \ + vx0 = vec_sra (vy0, shift); \ + vx1 = vec_sra (vy1, shift); \ + vx2 = vec_sra (vy2, shift); \ + vx3 = vec_sra (vy3, shift); \ + vx4 = vec_sra (vy4, shift); \ + vx5 = vec_sra (vy5, shift); \ + vx6 = vec_sra (vy6, shift); \ + vx7 = vec_sra (vy7, shift); + + +static const vec_s16 constants[5] = { + {23170, 13573, 6518, 21895, -23170, -21895, 32, 31}, + {16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725}, + {22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521}, + {21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692}, + {19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722} +}; + +void ff_idct_put_altivec(uint8_t* dest, int stride, int16_t *blk) +{ + vec_s16 *block = (vec_s16*)blk; + vec_u8 tmp; + + IDCT + +#define COPY(dest,src) \ + tmp = vec_packsu (src, src); \ + vec_ste ((vec_u32)tmp, 0, (unsigned int *)dest); \ + vec_ste ((vec_u32)tmp, 4, (unsigned int *)dest); + + COPY (dest, vx0) dest += stride; + COPY (dest, vx1) dest += stride; + COPY (dest, vx2) dest += stride; + COPY (dest, vx3) dest += stride; + COPY (dest, vx4) dest += stride; + COPY (dest, vx5) dest += stride; + COPY (dest, vx6) dest += stride; + COPY (dest, vx7) +} + +void ff_idct_add_altivec(uint8_t* dest, int stride, int16_t *blk) +{ + vec_s16 *block = (vec_s16*)blk; + vec_u8 tmp; + vec_s16 tmp2, tmp3; + vec_u8 perm0; + vec_u8 perm1; + vec_u8 p0, p1, p; + + IDCT + + p0 = vec_lvsl (0, dest); + p1 = vec_lvsl (stride, dest); + p = vec_splat_u8 (-1); + perm0 = vec_mergeh (p, p0); + perm1 = vec_mergeh (p, p1); + +#define ADD(dest,src,perm) \ + /* *(uint64_t *)&tmp = *(uint64_t *)dest; */ \ + tmp = vec_ld (0, dest); \ + tmp2 = (vec_s16)vec_perm (tmp, (vec_u8)zero, perm); \ + tmp3 = vec_adds (tmp2, src); \ + tmp = vec_packsu (tmp3, tmp3); \ + vec_ste ((vec_u32)tmp, 0, (unsigned int *)dest); \ + vec_ste ((vec_u32)tmp, 4, (unsigned int *)dest); + + ADD (dest, vx0, perm0) dest += stride; + ADD (dest, vx1, perm1) dest += stride; + ADD (dest, vx2, perm0) dest += stride; + ADD (dest, vx3, perm1) dest += stride; + ADD (dest, vx4, perm0) dest += stride; + ADD (dest, vx5, perm1) dest += stride; + ADD (dest, vx6, perm0) dest += stride; + ADD (dest, vx7, perm1) +} diff --git a/ffmpeg/libavcodec/ppc/int_altivec.c b/ffmpeg/libavcodec/ppc/int_altivec.c new file mode 100644 index 0000000..4386b13 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/int_altivec.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2007 Luca Barbato + * + * 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 + */ + +/** + ** @file + ** integer misc ops. + **/ + +#include "config.h" +#if HAVE_ALTIVEC_H +#include +#endif + +#include "libavutil/attributes.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavcodec/dsputil.h" + +#include "dsputil_altivec.h" + +static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, + int size) { + int i, size16; + vector signed char vpix1; + vector signed short vpix2, vdiff, vpix1l,vpix1h; + union { vector signed int vscore; + int32_t score[4]; + } u; + u.vscore = vec_splat_s32(0); +// +//XXX lazy way, fix it later + +#define vec_unaligned_load(b) \ + vec_perm(vec_ld(0,b),vec_ld(15,b),vec_lvsl(0, b)); + + size16 = size >> 4; + while(size16) { +// score += (pix1[i]-pix2[i])*(pix1[i]-pix2[i]); + //load pix1 and the first batch of pix2 + + vpix1 = vec_unaligned_load(pix1); + vpix2 = vec_unaligned_load(pix2); + pix2 += 8; + //unpack + vpix1h = vec_unpackh(vpix1); + vdiff = vec_sub(vpix1h, vpix2); + vpix1l = vec_unpackl(vpix1); + // load another batch from pix2 + vpix2 = vec_unaligned_load(pix2); + u.vscore = vec_msum(vdiff, vdiff, u.vscore); + vdiff = vec_sub(vpix1l, vpix2); + u.vscore = vec_msum(vdiff, vdiff, u.vscore); + pix1 += 16; + pix2 += 8; + size16--; + } + u.vscore = vec_sums(u.vscore, vec_splat_s32(0)); + + size %= 16; + for (i = 0; i < size; i++) { + u.score[3] += (pix1[i]-pix2[i])*(pix1[i]-pix2[i]); + } + return u.score[3]; +} + +static int32_t scalarproduct_int16_altivec(const int16_t *v1, const int16_t *v2, + int order) +{ + int i; + LOAD_ZERO; + const vec_s16 *pv; + register vec_s16 vec1; + register vec_s32 res = vec_splat_s32(0), t; + int32_t ires; + + for(i = 0; i < order; i += 8){ + pv = (const vec_s16*)v1; + vec1 = vec_perm(pv[0], pv[1], vec_lvsl(0, v1)); + t = vec_msum(vec1, vec_ld(0, v2), zero_s32v); + res = vec_sums(t, res); + v1 += 8; + v2 += 8; + } + res = vec_splat(res, 3); + vec_ste(res, 0, &ires); + return ires; +} + +static int32_t scalarproduct_and_madd_int16_altivec(int16_t *v1, const int16_t *v2, const int16_t *v3, int order, int mul) +{ + LOAD_ZERO; + vec_s16 *pv1 = (vec_s16*)v1; + register vec_s16 muls = {mul,mul,mul,mul,mul,mul,mul,mul}; + register vec_s16 t0, t1, i0, i1, i4; + register vec_s16 i2 = vec_ld(0, v2), i3 = vec_ld(0, v3); + register vec_s32 res = zero_s32v; + register vec_u8 align = vec_lvsl(0, v2); + int32_t ires; + order >>= 4; + do { + i1 = vec_ld(16, v2); + t0 = vec_perm(i2, i1, align); + i2 = vec_ld(32, v2); + t1 = vec_perm(i1, i2, align); + i0 = pv1[0]; + i1 = pv1[1]; + res = vec_msum(t0, i0, res); + res = vec_msum(t1, i1, res); + i4 = vec_ld(16, v3); + t0 = vec_perm(i3, i4, align); + i3 = vec_ld(32, v3); + t1 = vec_perm(i4, i3, align); + pv1[0] = vec_mladd(t0, muls, i0); + pv1[1] = vec_mladd(t1, muls, i1); + pv1 += 2; + v2 += 8; + v3 += 8; + } while(--order); + res = vec_splat(vec_sums(res, zero_s32v), 3); + vec_ste(res, 0, &ires); + return ires; +} + +av_cold void ff_int_init_altivec(DSPContext *c, AVCodecContext *avctx) +{ + c->ssd_int8_vs_int16 = ssd_int8_vs_int16_altivec; + c->scalarproduct_int16 = scalarproduct_int16_altivec; + c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_altivec; +} diff --git a/ffmpeg/libavcodec/ppc/mathops.h b/ffmpeg/libavcodec/ppc/mathops.h new file mode 100644 index 0000000..dbd714f --- /dev/null +++ b/ffmpeg/libavcodec/ppc/mathops.h @@ -0,0 +1,79 @@ +/* + * simple math operations + * Copyright (c) 2001, 2002 Fabrice Bellard + * Copyright (c) 2006 Michael Niedermayer et al + * + * 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 + */ + +#ifndef AVCODEC_PPC_MATHOPS_H +#define AVCODEC_PPC_MATHOPS_H + +#include +#include "config.h" +#include "libavutil/common.h" + +#if HAVE_PPC4XX +/* signed 16x16 -> 32 multiply add accumulate */ +#define MAC16(rt, ra, rb) \ + __asm__ ("maclhw %0, %2, %3" : "=r" (rt) : "0" (rt), "r" (ra), "r" (rb)); + +/* signed 16x16 -> 32 multiply */ +#define MUL16(ra, rb) \ + ({ int __rt; \ + __asm__ ("mullhw %0, %1, %2" : "=r" (__rt) : "r" (ra), "r" (rb)); \ + __rt; }) +#endif + +#define MULH MULH +static inline av_const int MULH(int a, int b){ + int r; + __asm__ ("mulhw %0, %1, %2" : "=r"(r) : "r"(a), "r"(b)); + return r; +} + +#if !ARCH_PPC64 +static inline av_const int64_t MAC64(int64_t d, int a, int b) +{ + union { uint64_t x; unsigned hl[2]; } x = { d }; + int h, l; + __asm__ ("mullw %3, %4, %5 \n\t" + "mulhw %2, %4, %5 \n\t" + "addc %1, %1, %3 \n\t" + "adde %0, %0, %2 \n\t" + : "+r"(x.hl[0]), "+r"(x.hl[1]), "=&r"(h), "=&r"(l) + : "r"(a), "r"(b)); + return x.x; +} +#define MAC64(d, a, b) ((d) = MAC64(d, a, b)) + +static inline av_const int64_t MLS64(int64_t d, int a, int b) +{ + union { uint64_t x; unsigned hl[2]; } x = { d }; + int h, l; + __asm__ ("mullw %3, %4, %5 \n\t" + "mulhw %2, %4, %5 \n\t" + "subfc %1, %3, %1 \n\t" + "subfe %0, %2, %0 \n\t" + : "+r"(x.hl[0]), "+r"(x.hl[1]), "=&r"(h), "=&r"(l) + : "r"(a), "r"(b)); + return x.x; +} +#define MLS64(d, a, b) ((d) = MLS64(d, a, b)) +#endif + +#endif /* AVCODEC_PPC_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/ppc/mpegaudiodec_altivec.c b/ffmpeg/libavcodec/ppc/mpegaudiodec_altivec.c new file mode 100644 index 0000000..1152fd7 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/mpegaudiodec_altivec.c @@ -0,0 +1,130 @@ +/* + * Altivec optimized MP3 decoding functions + * Copyright (c) 2010 Vitor Sessak + * + * 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 "dsputil_altivec.h" +#include "libavutil/attributes.h" +#include "libavutil/internal.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/mpegaudiodsp.h" + +#define MACS(rt, ra, rb) rt+=(ra)*(rb) +#define MLSS(rt, ra, rb) rt-=(ra)*(rb) + +#define SUM8(op, sum, w, p) \ +{ \ + op(sum, (w)[0 * 64], (p)[0 * 64]); \ + op(sum, (w)[1 * 64], (p)[1 * 64]); \ + op(sum, (w)[2 * 64], (p)[2 * 64]); \ + op(sum, (w)[3 * 64], (p)[3 * 64]); \ + op(sum, (w)[4 * 64], (p)[4 * 64]); \ + op(sum, (w)[5 * 64], (p)[5 * 64]); \ + op(sum, (w)[6 * 64], (p)[6 * 64]); \ + op(sum, (w)[7 * 64], (p)[7 * 64]); \ +} + +static void apply_window(const float *buf, const float *win1, + const float *win2, float *sum1, float *sum2, int len) +{ + const vector float *win1a = (const vector float *) win1; + const vector float *win2a = (const vector float *) win2; + const vector float *bufa = (const vector float *) buf; + vector float *sum1a = (vector float *) sum1; + vector float *sum2a = (vector float *) sum2; + vector float av_uninit(v0), av_uninit(v4); + vector float v1, v2, v3; + + len = len >> 2; + +#define MULT(a, b) \ + { \ + v1 = vec_ld(a, win1a); \ + v2 = vec_ld(b, win2a); \ + v3 = vec_ld(a, bufa); \ + v0 = vec_madd(v3, v1, v0); \ + v4 = vec_madd(v2, v3, v4); \ + } + + while (len--) { + v0 = vec_xor(v0, v0); + v4 = vec_xor(v4, v4); + + MULT( 0, 0); + MULT( 256, 64); + MULT( 512, 128); + MULT( 768, 192); + MULT(1024, 256); + MULT(1280, 320); + MULT(1536, 384); + MULT(1792, 448); + + vec_st(v0, 0, sum1a); + vec_st(v4, 0, sum2a); + sum1a++; + sum2a++; + win1a++; + win2a++; + bufa++; + } +} + +static void apply_window_mp3(float *in, float *win, int *unused, float *out, + int incr) +{ + LOCAL_ALIGNED_16(float, suma, [17]); + LOCAL_ALIGNED_16(float, sumb, [17]); + LOCAL_ALIGNED_16(float, sumc, [17]); + LOCAL_ALIGNED_16(float, sumd, [17]); + + float sum; + int j; + float *out2 = out + 32 * incr; + + /* copy to avoid wrap */ + memcpy(in + 512, in, 32 * sizeof(*in)); + + apply_window(in + 16, win , win + 512, suma, sumc, 16); + apply_window(in + 32, win + 48, win + 640, sumb, sumd, 16); + + SUM8(MLSS, suma[0], win + 32, in + 48); + + sumc[ 0] = 0; + sumb[16] = 0; + sumd[16] = 0; + + out[0 ] = suma[ 0]; + out += incr; + out2 -= incr; + for(j=1;j<16;j++) { + *out = suma[ j] - sumd[16-j]; + *out2 = -sumb[16-j] - sumc[ j]; + out += incr; + out2 -= incr; + } + + sum = 0; + SUM8(MLSS, sum, win + 16 + 32, in + 32); + *out = sum; +} + +av_cold void ff_mpadsp_init_altivec(MPADSPContext *s) +{ + s->apply_window_float = apply_window_mp3; +} diff --git a/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c b/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c new file mode 100644 index 0000000..bf490b0 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/mpegvideo_altivec.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002 Dieter Shirley + * + * dct_unquantize_h263_altivec: + * Copyright (c) 2003 Romain Dolbeau + * + * 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 + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/mpegvideo.h" + +#include "dsputil_altivec.h" + +/* AltiVec version of dct_unquantize_h263 + this code assumes `block' is 16 bytes-aligned */ +static void dct_unquantize_h263_altivec(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + int i, level, qmul, qadd; + int nCoeffs; + + assert(s->block_last_index[n]>=0); + + qadd = (qscale - 1) | 1; + qmul = qscale << 1; + + if (s->mb_intra) { + if (!s->h263_aic) { + if (n < 4) + block[0] = block[0] * s->y_dc_scale; + else + block[0] = block[0] * s->c_dc_scale; + }else + qadd = 0; + i = 1; + nCoeffs= 63; //does not always use zigzag table + } else { + i = 0; + nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]; + } + + { + register const vector signed short vczero = (const vector signed short)vec_splat_s16(0); + DECLARE_ALIGNED(16, short, qmul8) = qmul; + DECLARE_ALIGNED(16, short, qadd8) = qadd; + register vector signed short blockv, qmulv, qaddv, nqaddv, temp1; + register vector bool short blockv_null, blockv_neg; + register short backup_0 = block[0]; + register int j = 0; + + qmulv = vec_splat((vec_s16)vec_lde(0, &qmul8), 0); + qaddv = vec_splat((vec_s16)vec_lde(0, &qadd8), 0); + nqaddv = vec_sub(vczero, qaddv); + + // vectorize all the 16 bytes-aligned blocks + // of 8 elements + for(; (j + 7) <= nCoeffs ; j+=8) { + blockv = vec_ld(j << 1, block); + blockv_neg = vec_cmplt(blockv, vczero); + blockv_null = vec_cmpeq(blockv, vczero); + // choose between +qadd or -qadd as the third operand + temp1 = vec_sel(qaddv, nqaddv, blockv_neg); + // multiply & add (block{i,i+7} * qmul [+-] qadd) + temp1 = vec_mladd(blockv, qmulv, temp1); + // put 0 where block[{i,i+7} used to have 0 + blockv = vec_sel(temp1, blockv, blockv_null); + vec_st(blockv, j << 1, block); + } + + // if nCoeffs isn't a multiple of 8, finish the job + // using good old scalar units. + // (we could do it using a truncated vector, + // but I'm not sure it's worth the hassle) + for(; j <= nCoeffs ; j++) { + level = block[j]; + if (level) { + if (level < 0) { + level = level * qmul - qadd; + } else { + level = level * qmul + qadd; + } + block[j] = level; + } + } + + if (i == 1) { + // cheat. this avoid special-casing the first iteration + block[0] = backup_0; + } + } +} + + +av_cold void ff_MPV_common_init_altivec(MpegEncContext *s) +{ + if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) return; + + if ((s->avctx->dct_algo == FF_DCT_AUTO) || + (s->avctx->dct_algo == FF_DCT_ALTIVEC)) { + s->dct_unquantize_h263_intra = dct_unquantize_h263_altivec; + s->dct_unquantize_h263_inter = dct_unquantize_h263_altivec; + } +} diff --git a/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c b/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c new file mode 100644 index 0000000..9c2ad70 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/vc1dsp_altivec.c @@ -0,0 +1,347 @@ +/* + * VC-1 and WMV3 decoder - DSP functions AltiVec-optimized + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 "libavutil/attributes.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/vc1dsp.h" + +// main steps of 8x8 transform +#define STEP8(s0, s1, s2, s3, s4, s5, s6, s7, vec_rnd) \ +do { \ + t0 = vec_sl(vec_add(s0, s4), vec_2); \ + t0 = vec_add(vec_sl(t0, vec_1), t0); \ + t0 = vec_add(t0, vec_rnd); \ + t1 = vec_sl(vec_sub(s0, s4), vec_2); \ + t1 = vec_add(vec_sl(t1, vec_1), t1); \ + t1 = vec_add(t1, vec_rnd); \ + t2 = vec_add(vec_sl(s6, vec_2), vec_sl(s6, vec_1)); \ + t2 = vec_add(t2, vec_sl(s2, vec_4)); \ + t3 = vec_add(vec_sl(s2, vec_2), vec_sl(s2, vec_1)); \ + t3 = vec_sub(t3, vec_sl(s6, vec_4)); \ + t4 = vec_add(t0, t2); \ + t5 = vec_add(t1, t3); \ + t6 = vec_sub(t1, t3); \ + t7 = vec_sub(t0, t2); \ +\ + t0 = vec_sl(vec_add(s1, s3), vec_4); \ + t0 = vec_add(t0, vec_sl(s5, vec_3)); \ + t0 = vec_add(t0, vec_sl(s7, vec_2)); \ + t0 = vec_add(t0, vec_sub(s5, s3)); \ +\ + t1 = vec_sl(vec_sub(s1, s5), vec_4); \ + t1 = vec_sub(t1, vec_sl(s7, vec_3)); \ + t1 = vec_sub(t1, vec_sl(s3, vec_2)); \ + t1 = vec_sub(t1, vec_add(s1, s7)); \ +\ + t2 = vec_sl(vec_sub(s7, s3), vec_4); \ + t2 = vec_add(t2, vec_sl(s1, vec_3)); \ + t2 = vec_add(t2, vec_sl(s5, vec_2)); \ + t2 = vec_add(t2, vec_sub(s1, s7)); \ +\ + t3 = vec_sl(vec_sub(s5, s7), vec_4); \ + t3 = vec_sub(t3, vec_sl(s3, vec_3)); \ + t3 = vec_add(t3, vec_sl(s1, vec_2)); \ + t3 = vec_sub(t3, vec_add(s3, s5)); \ +\ + s0 = vec_add(t4, t0); \ + s1 = vec_add(t5, t1); \ + s2 = vec_add(t6, t2); \ + s3 = vec_add(t7, t3); \ + s4 = vec_sub(t7, t3); \ + s5 = vec_sub(t6, t2); \ + s6 = vec_sub(t5, t1); \ + s7 = vec_sub(t4, t0); \ +}while(0) + +#define SHIFT_HOR8(s0, s1, s2, s3, s4, s5, s6, s7) \ +do { \ + s0 = vec_sra(s0, vec_3); \ + s1 = vec_sra(s1, vec_3); \ + s2 = vec_sra(s2, vec_3); \ + s3 = vec_sra(s3, vec_3); \ + s4 = vec_sra(s4, vec_3); \ + s5 = vec_sra(s5, vec_3); \ + s6 = vec_sra(s6, vec_3); \ + s7 = vec_sra(s7, vec_3); \ +}while(0) + +#define SHIFT_VERT8(s0, s1, s2, s3, s4, s5, s6, s7) \ +do { \ + s0 = vec_sra(s0, vec_7); \ + s1 = vec_sra(s1, vec_7); \ + s2 = vec_sra(s2, vec_7); \ + s3 = vec_sra(s3, vec_7); \ + s4 = vec_sra(vec_add(s4, vec_1s), vec_7); \ + s5 = vec_sra(vec_add(s5, vec_1s), vec_7); \ + s6 = vec_sra(vec_add(s6, vec_1s), vec_7); \ + s7 = vec_sra(vec_add(s7, vec_1s), vec_7); \ +}while(0) + +/* main steps of 4x4 transform */ +#define STEP4(s0, s1, s2, s3, vec_rnd) \ +do { \ + t1 = vec_add(vec_sl(s0, vec_4), s0); \ + t1 = vec_add(t1, vec_rnd); \ + t2 = vec_add(vec_sl(s2, vec_4), s2); \ + t0 = vec_add(t1, t2); \ + t1 = vec_sub(t1, t2); \ + t3 = vec_sl(vec_sub(s3, s1), vec_1); \ + t3 = vec_add(t3, vec_sl(t3, vec_2)); \ + t2 = vec_add(t3, vec_sl(s1, vec_5)); \ + t3 = vec_add(t3, vec_sl(s3, vec_3)); \ + t3 = vec_add(t3, vec_sl(s3, vec_2)); \ + s0 = vec_add(t0, t2); \ + s1 = vec_sub(t1, t3); \ + s2 = vec_add(t1, t3); \ + s3 = vec_sub(t0, t2); \ +}while (0) + +#define SHIFT_HOR4(s0, s1, s2, s3) \ + s0 = vec_sra(s0, vec_3); \ + s1 = vec_sra(s1, vec_3); \ + s2 = vec_sra(s2, vec_3); \ + s3 = vec_sra(s3, vec_3); + +#define SHIFT_VERT4(s0, s1, s2, s3) \ + s0 = vec_sra(s0, vec_7); \ + s1 = vec_sra(s1, vec_7); \ + s2 = vec_sra(s2, vec_7); \ + s3 = vec_sra(s3, vec_7); + +/** Do inverse transform on 8x8 block +*/ +static void vc1_inv_trans_8x8_altivec(int16_t block[64]) +{ + vector signed short src0, src1, src2, src3, src4, src5, src6, src7; + vector signed int s0, s1, s2, s3, s4, s5, s6, s7; + vector signed int s8, s9, sA, sB, sC, sD, sE, sF; + vector signed int t0, t1, t2, t3, t4, t5, t6, t7; + const vector signed int vec_64 = vec_sl(vec_splat_s32(4), vec_splat_u32(4)); + const vector unsigned int vec_7 = vec_splat_u32(7); + const vector unsigned int vec_4 = vec_splat_u32(4); + const vector signed int vec_4s = vec_splat_s32(4); + const vector unsigned int vec_3 = vec_splat_u32(3); + const vector unsigned int vec_2 = vec_splat_u32(2); + const vector signed int vec_1s = vec_splat_s32(1); + const vector unsigned int vec_1 = vec_splat_u32(1); + + src0 = vec_ld( 0, block); + src1 = vec_ld( 16, block); + src2 = vec_ld( 32, block); + src3 = vec_ld( 48, block); + src4 = vec_ld( 64, block); + src5 = vec_ld( 80, block); + src6 = vec_ld( 96, block); + src7 = vec_ld(112, block); + + s0 = vec_unpackl(src0); + s1 = vec_unpackl(src1); + s2 = vec_unpackl(src2); + s3 = vec_unpackl(src3); + s4 = vec_unpackl(src4); + s5 = vec_unpackl(src5); + s6 = vec_unpackl(src6); + s7 = vec_unpackl(src7); + s8 = vec_unpackh(src0); + s9 = vec_unpackh(src1); + sA = vec_unpackh(src2); + sB = vec_unpackh(src3); + sC = vec_unpackh(src4); + sD = vec_unpackh(src5); + sE = vec_unpackh(src6); + sF = vec_unpackh(src7); + STEP8(s0, s1, s2, s3, s4, s5, s6, s7, vec_4s); + SHIFT_HOR8(s0, s1, s2, s3, s4, s5, s6, s7); + STEP8(s8, s9, sA, sB, sC, sD, sE, sF, vec_4s); + SHIFT_HOR8(s8, s9, sA, sB, sC, sD, sE, sF); + src0 = vec_pack(s8, s0); + src1 = vec_pack(s9, s1); + src2 = vec_pack(sA, s2); + src3 = vec_pack(sB, s3); + src4 = vec_pack(sC, s4); + src5 = vec_pack(sD, s5); + src6 = vec_pack(sE, s6); + src7 = vec_pack(sF, s7); + TRANSPOSE8(src0, src1, src2, src3, src4, src5, src6, src7); + + s0 = vec_unpackl(src0); + s1 = vec_unpackl(src1); + s2 = vec_unpackl(src2); + s3 = vec_unpackl(src3); + s4 = vec_unpackl(src4); + s5 = vec_unpackl(src5); + s6 = vec_unpackl(src6); + s7 = vec_unpackl(src7); + s8 = vec_unpackh(src0); + s9 = vec_unpackh(src1); + sA = vec_unpackh(src2); + sB = vec_unpackh(src3); + sC = vec_unpackh(src4); + sD = vec_unpackh(src5); + sE = vec_unpackh(src6); + sF = vec_unpackh(src7); + STEP8(s0, s1, s2, s3, s4, s5, s6, s7, vec_64); + SHIFT_VERT8(s0, s1, s2, s3, s4, s5, s6, s7); + STEP8(s8, s9, sA, sB, sC, sD, sE, sF, vec_64); + SHIFT_VERT8(s8, s9, sA, sB, sC, sD, sE, sF); + src0 = vec_pack(s8, s0); + src1 = vec_pack(s9, s1); + src2 = vec_pack(sA, s2); + src3 = vec_pack(sB, s3); + src4 = vec_pack(sC, s4); + src5 = vec_pack(sD, s5); + src6 = vec_pack(sE, s6); + src7 = vec_pack(sF, s7); + + vec_st(src0, 0, block); + vec_st(src1, 16, block); + vec_st(src2, 32, block); + vec_st(src3, 48, block); + vec_st(src4, 64, block); + vec_st(src5, 80, block); + vec_st(src6, 96, block); + vec_st(src7,112, block); +} + +/** Do inverse transform on 8x4 part of block +*/ +static void vc1_inv_trans_8x4_altivec(uint8_t *dest, int stride, int16_t *block) +{ + vector signed short src0, src1, src2, src3, src4, src5, src6, src7; + vector signed int s0, s1, s2, s3, s4, s5, s6, s7; + vector signed int s8, s9, sA, sB, sC, sD, sE, sF; + vector signed int t0, t1, t2, t3, t4, t5, t6, t7; + const vector signed int vec_64 = vec_sl(vec_splat_s32(4), vec_splat_u32(4)); + const vector unsigned int vec_7 = vec_splat_u32(7); + const vector unsigned int vec_5 = vec_splat_u32(5); + const vector unsigned int vec_4 = vec_splat_u32(4); + const vector signed int vec_4s = vec_splat_s32(4); + const vector unsigned int vec_3 = vec_splat_u32(3); + const vector unsigned int vec_2 = vec_splat_u32(2); + const vector unsigned int vec_1 = vec_splat_u32(1); + vector unsigned char tmp; + vector signed short tmp2, tmp3; + vector unsigned char perm0, perm1, p0, p1, p; + + src0 = vec_ld( 0, block); + src1 = vec_ld( 16, block); + src2 = vec_ld( 32, block); + src3 = vec_ld( 48, block); + src4 = vec_ld( 64, block); + src5 = vec_ld( 80, block); + src6 = vec_ld( 96, block); + src7 = vec_ld(112, block); + + TRANSPOSE8(src0, src1, src2, src3, src4, src5, src6, src7); + s0 = vec_unpackl(src0); + s1 = vec_unpackl(src1); + s2 = vec_unpackl(src2); + s3 = vec_unpackl(src3); + s4 = vec_unpackl(src4); + s5 = vec_unpackl(src5); + s6 = vec_unpackl(src6); + s7 = vec_unpackl(src7); + s8 = vec_unpackh(src0); + s9 = vec_unpackh(src1); + sA = vec_unpackh(src2); + sB = vec_unpackh(src3); + sC = vec_unpackh(src4); + sD = vec_unpackh(src5); + sE = vec_unpackh(src6); + sF = vec_unpackh(src7); + STEP8(s0, s1, s2, s3, s4, s5, s6, s7, vec_4s); + SHIFT_HOR8(s0, s1, s2, s3, s4, s5, s6, s7); + STEP8(s8, s9, sA, sB, sC, sD, sE, sF, vec_4s); + SHIFT_HOR8(s8, s9, sA, sB, sC, sD, sE, sF); + src0 = vec_pack(s8, s0); + src1 = vec_pack(s9, s1); + src2 = vec_pack(sA, s2); + src3 = vec_pack(sB, s3); + src4 = vec_pack(sC, s4); + src5 = vec_pack(sD, s5); + src6 = vec_pack(sE, s6); + src7 = vec_pack(sF, s7); + TRANSPOSE8(src0, src1, src2, src3, src4, src5, src6, src7); + + s0 = vec_unpackh(src0); + s1 = vec_unpackh(src1); + s2 = vec_unpackh(src2); + s3 = vec_unpackh(src3); + s8 = vec_unpackl(src0); + s9 = vec_unpackl(src1); + sA = vec_unpackl(src2); + sB = vec_unpackl(src3); + STEP4(s0, s1, s2, s3, vec_64); + SHIFT_VERT4(s0, s1, s2, s3); + STEP4(s8, s9, sA, sB, vec_64); + SHIFT_VERT4(s8, s9, sA, sB); + src0 = vec_pack(s0, s8); + src1 = vec_pack(s1, s9); + src2 = vec_pack(s2, sA); + src3 = vec_pack(s3, sB); + + p0 = vec_lvsl (0, dest); + p1 = vec_lvsl (stride, dest); + p = vec_splat_u8 (-1); + perm0 = vec_mergeh (p, p0); + perm1 = vec_mergeh (p, p1); + +#define ADD(dest,src,perm) \ + /* *(uint64_t *)&tmp = *(uint64_t *)dest; */ \ + tmp = vec_ld (0, dest); \ + tmp2 = (vector signed short)vec_perm (tmp, vec_splat_u8(0), perm); \ + tmp3 = vec_adds (tmp2, src); \ + tmp = vec_packsu (tmp3, tmp3); \ + vec_ste ((vector unsigned int)tmp, 0, (unsigned int *)dest); \ + vec_ste ((vector unsigned int)tmp, 4, (unsigned int *)dest); + + ADD (dest, src0, perm0) dest += stride; + ADD (dest, src1, perm1) dest += stride; + ADD (dest, src2, perm0) dest += stride; + ADD (dest, src3, perm1) +} + +#define PUT_OP_U8_ALTIVEC(d, s, dst) d = s +#define AVG_OP_U8_ALTIVEC(d, s, dst) d = vec_avg(dst, s) + +#define OP_U8_ALTIVEC PUT_OP_U8_ALTIVEC +#define PREFIX_no_rnd_vc1_chroma_mc8_altivec put_no_rnd_vc1_chroma_mc8_altivec +#include "h264chroma_template.c" +#undef OP_U8_ALTIVEC +#undef PREFIX_no_rnd_vc1_chroma_mc8_altivec + +#define OP_U8_ALTIVEC AVG_OP_U8_ALTIVEC +#define PREFIX_no_rnd_vc1_chroma_mc8_altivec avg_no_rnd_vc1_chroma_mc8_altivec +#include "h264chroma_template.c" +#undef OP_U8_ALTIVEC +#undef PREFIX_no_rnd_vc1_chroma_mc8_altivec + +av_cold void ff_vc1dsp_init_altivec(VC1DSPContext *dsp) +{ + if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + return; + + dsp->vc1_inv_trans_8x8 = vc1_inv_trans_8x8_altivec; + dsp->vc1_inv_trans_8x4 = vc1_inv_trans_8x4_altivec; + dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = put_no_rnd_vc1_chroma_mc8_altivec; + dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = avg_no_rnd_vc1_chroma_mc8_altivec; +} diff --git a/ffmpeg/libavcodec/ppc/videodsp_ppc.c b/ffmpeg/libavcodec/ppc/videodsp_ppc.c new file mode 100644 index 0000000..9157022 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/videodsp_ppc.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003-2004 Romain Dolbeau + * + * 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 "libavutil/attributes.h" +#include "libavcodec/videodsp.h" + +static void prefetch_ppc(uint8_t *mem, ptrdiff_t stride, int h) +{ + register const uint8_t *p = mem; + do { + __asm__ volatile ("dcbt 0,%0" : : "r" (p)); + p += stride; + } while(--h); +} + +av_cold void ff_videodsp_init_ppc(VideoDSPContext *ctx, int bpc) +{ + ctx->prefetch = prefetch_ppc; +} diff --git a/ffmpeg/libavcodec/ppc/vorbisdsp_altivec.c b/ffmpeg/libavcodec/ppc/vorbisdsp_altivec.c new file mode 100644 index 0000000..08a2b26 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/vorbisdsp_altivec.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006 Luca Barbato + * + * 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 "config.h" +#if HAVE_ALTIVEC_H +#include +#endif +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavcodec/vorbisdsp.h" + +#if HAVE_ALTIVEC +static void vorbis_inverse_coupling_altivec(float *mag, float *ang, + intptr_t blocksize) +{ + int i; + vector float m, a; + vector bool int t0, t1; + const vector unsigned int v_31 = //XXX + vec_add(vec_add(vec_splat_u32(15),vec_splat_u32(15)),vec_splat_u32(1)); + for (i = 0; i < blocksize; i += 4) { + m = vec_ld(0, mag+i); + a = vec_ld(0, ang+i); + t0 = vec_cmple(m, (vector float)vec_splat_u32(0)); + t1 = vec_cmple(a, (vector float)vec_splat_u32(0)); + a = vec_xor(a, (vector float) vec_sl((vector unsigned int)t0, v_31)); + t0 = (vector bool int)vec_and(a, t1); + t1 = (vector bool int)vec_andc(a, t1); + a = vec_sub(m, (vector float)t1); + m = vec_add(m, (vector float)t0); + vec_stl(a, 0, ang+i); + vec_stl(m, 0, mag+i); + } +} +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_vorbisdsp_init_ppc(VorbisDSPContext *c) +{ +#if HAVE_ALTIVEC + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { + c->vorbis_inverse_coupling = vorbis_inverse_coupling_altivec; + } +#endif /* HAVE_ALTIVEC */ +} diff --git a/ffmpeg/libavcodec/ppc/vp3dsp_altivec.c b/ffmpeg/libavcodec/ppc/vp3dsp_altivec.c new file mode 100644 index 0000000..cc587b0 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/vp3dsp_altivec.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2009 David Conrad + * + * 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/cpu.h" +#include "libavcodec/vp3dsp.h" + +#if HAVE_ALTIVEC + +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "dsputil_altivec.h" + +static const vec_s16 constants = + {0, 64277, 60547, 54491, 46341, 36410, 25080, 12785}; +static const vec_u8 interleave_high = + {0, 1, 16, 17, 4, 5, 20, 21, 8, 9, 24, 25, 12, 13, 28, 29}; + +#define IDCT_START \ + vec_s16 A, B, C, D, Ad, Bd, Cd, Dd, E, F, G, H;\ + vec_s16 Ed, Gd, Add, Bdd, Fd, Hd;\ + vec_s16 eight = vec_splat_s16(8);\ + vec_u16 four = vec_splat_u16(4);\ +\ + vec_s16 C1 = vec_splat(constants, 1);\ + vec_s16 C2 = vec_splat(constants, 2);\ + vec_s16 C3 = vec_splat(constants, 3);\ + vec_s16 C4 = vec_splat(constants, 4);\ + vec_s16 C5 = vec_splat(constants, 5);\ + vec_s16 C6 = vec_splat(constants, 6);\ + vec_s16 C7 = vec_splat(constants, 7);\ +\ + vec_s16 b0 = vec_ld(0x00, block);\ + vec_s16 b1 = vec_ld(0x10, block);\ + vec_s16 b2 = vec_ld(0x20, block);\ + vec_s16 b3 = vec_ld(0x30, block);\ + vec_s16 b4 = vec_ld(0x40, block);\ + vec_s16 b5 = vec_ld(0x50, block);\ + vec_s16 b6 = vec_ld(0x60, block);\ + vec_s16 b7 = vec_ld(0x70, block); + +// these functions do (a*C)>>16 +// things are tricky because a is signed, but C unsigned. +// M15 is used if C fits in 15 bit unsigned (C6,C7) +// M16 is used if C requires 16 bits unsigned +static inline vec_s16 M15(vec_s16 a, vec_s16 C) +{ + return (vec_s16)vec_perm(vec_mule(a,C), vec_mulo(a,C), interleave_high); +} +static inline vec_s16 M16(vec_s16 a, vec_s16 C) +{ + return vec_add(a, M15(a, C)); +} + +#define IDCT_1D(ADD, SHIFT)\ + A = vec_add(M16(b1, C1), M15(b7, C7));\ + B = vec_sub(M15(b1, C7), M16(b7, C1));\ + C = vec_add(M16(b3, C3), M16(b5, C5));\ + D = vec_sub(M16(b5, C3), M16(b3, C5));\ +\ + Ad = M16(vec_sub(A, C), C4);\ + Bd = M16(vec_sub(B, D), C4);\ +\ + Cd = vec_add(A, C);\ + Dd = vec_add(B, D);\ +\ + E = ADD(M16(vec_add(b0, b4), C4));\ + F = ADD(M16(vec_sub(b0, b4), C4));\ +\ + G = vec_add(M16(b2, C2), M15(b6, C6));\ + H = vec_sub(M15(b2, C6), M16(b6, C2));\ +\ + Ed = vec_sub(E, G);\ + Gd = vec_add(E, G);\ +\ + Add = vec_add(F, Ad);\ + Bdd = vec_sub(Bd, H);\ +\ + Fd = vec_sub(F, Ad);\ + Hd = vec_add(Bd, H);\ +\ + b0 = SHIFT(vec_add(Gd, Cd));\ + b7 = SHIFT(vec_sub(Gd, Cd));\ +\ + b1 = SHIFT(vec_add(Add, Hd));\ + b2 = SHIFT(vec_sub(Add, Hd));\ +\ + b3 = SHIFT(vec_add(Ed, Dd));\ + b4 = SHIFT(vec_sub(Ed, Dd));\ +\ + b5 = SHIFT(vec_add(Fd, Bdd));\ + b6 = SHIFT(vec_sub(Fd, Bdd)); + +#define NOP(a) a +#define ADD8(a) vec_add(a, eight) +#define SHIFT4(a) vec_sra(a, four) + +static void vp3_idct_put_altivec(uint8_t *dst, int stride, int16_t block[64]) +{ + vec_u8 t; + IDCT_START + + // pixels are signed; so add 128*16 in addition to the normal 8 + vec_s16 v2048 = vec_sl(vec_splat_s16(1), vec_splat_u16(11)); + eight = vec_add(eight, v2048); + + IDCT_1D(NOP, NOP) + TRANSPOSE8(b0, b1, b2, b3, b4, b5, b6, b7); + IDCT_1D(ADD8, SHIFT4) + +#define PUT(a)\ + t = vec_packsu(a, a);\ + vec_ste((vec_u32)t, 0, (unsigned int *)dst);\ + vec_ste((vec_u32)t, 4, (unsigned int *)dst); + + PUT(b0) dst += stride; + PUT(b1) dst += stride; + PUT(b2) dst += stride; + PUT(b3) dst += stride; + PUT(b4) dst += stride; + PUT(b5) dst += stride; + PUT(b6) dst += stride; + PUT(b7) + memset(block, 0, sizeof(*block) * 64); +} + +static void vp3_idct_add_altivec(uint8_t *dst, int stride, int16_t block[64]) +{ + LOAD_ZERO; + vec_u8 t, vdst; + vec_s16 vdst_16; + vec_u8 vdst_mask = vec_mergeh(vec_splat_u8(-1), vec_lvsl(0, dst)); + + IDCT_START + + IDCT_1D(NOP, NOP) + TRANSPOSE8(b0, b1, b2, b3, b4, b5, b6, b7); + IDCT_1D(ADD8, SHIFT4) + +#define ADD(a)\ + vdst = vec_ld(0, dst);\ + vdst_16 = (vec_s16)vec_perm(vdst, zero_u8v, vdst_mask);\ + vdst_16 = vec_adds(a, vdst_16);\ + t = vec_packsu(vdst_16, vdst_16);\ + vec_ste((vec_u32)t, 0, (unsigned int *)dst);\ + vec_ste((vec_u32)t, 4, (unsigned int *)dst); + + ADD(b0) dst += stride; + ADD(b1) dst += stride; + ADD(b2) dst += stride; + ADD(b3) dst += stride; + ADD(b4) dst += stride; + ADD(b5) dst += stride; + ADD(b6) dst += stride; + ADD(b7) + memset(block, 0, sizeof(*block) * 64); +} + +#endif /* HAVE_ALTIVEC */ + +av_cold void ff_vp3dsp_init_ppc(VP3DSPContext *c, int flags) +{ +#if HAVE_ALTIVEC + if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) { + c->idct_put = vp3_idct_put_altivec; + c->idct_add = vp3_idct_add_altivec; + } +#endif +} diff --git a/ffmpeg/libavcodec/ppc/vp8dsp_altivec.c b/ffmpeg/libavcodec/ppc/vp8dsp_altivec.c new file mode 100644 index 0000000..14d8784 --- /dev/null +++ b/ffmpeg/libavcodec/ppc/vp8dsp_altivec.c @@ -0,0 +1,304 @@ +/* + * VP8 compatible video decoder + * + * Copyright (C) 2010 David Conrad + * + * 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 "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/ppc/types_altivec.h" +#include "libavutil/ppc/util_altivec.h" +#include "libavcodec/vp8dsp.h" +#include "dsputil_altivec.h" + +#define REPT4(...) { __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__ } + +// h subpel filter uses msum to multiply+add 4 pixel taps at once +static const vec_s8 h_subpel_filters_inner[7] = +{ + REPT4( -6, 123, 12, -1), + REPT4(-11, 108, 36, -8), + REPT4( -9, 93, 50, -6), + REPT4(-16, 77, 77, -16), + REPT4( -6, 50, 93, -9), + REPT4( -8, 36, 108, -11), + REPT4( -1, 12, 123, -6), +}; + +// for 6tap filters, these are the outer two taps +// The zeros mask off pixels 4-7 when filtering 0-3 +// and vice-versa +static const vec_s8 h_subpel_filters_outer[3] = +{ + REPT4(0, 0, 2, 1), + REPT4(0, 0, 3, 3), + REPT4(0, 0, 1, 2), +}; + +#define LOAD_H_SUBPEL_FILTER(i) \ + vec_s8 filter_inner = h_subpel_filters_inner[i]; \ + vec_s8 filter_outerh = h_subpel_filters_outer[(i)>>1]; \ + vec_s8 filter_outerl = vec_sld(filter_outerh, filter_outerh, 2) + +#define FILTER_H(dstv, off) \ + a = vec_ld((off)-is6tap-1, src); \ + b = vec_ld((off)-is6tap-1+15, src); \ +\ + pixh = vec_perm(a, b, permh##off); \ + pixl = vec_perm(a, b, perml##off); \ + filth = vec_msum(filter_inner, pixh, c64); \ + filtl = vec_msum(filter_inner, pixl, c64); \ +\ + if (is6tap) { \ + outer = vec_perm(a, b, perm_6tap##off); \ + filth = vec_msum(filter_outerh, outer, filth); \ + filtl = vec_msum(filter_outerl, outer, filtl); \ + } \ + if (w == 4) \ + filtl = filth; /* discard pixels 4-7 */ \ + dstv = vec_packs(filth, filtl); \ + dstv = vec_sra(dstv, c7) + +static av_always_inline +void put_vp8_epel_h_altivec_core(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int w, int is6tap) +{ + LOAD_H_SUBPEL_FILTER(mx-1); + vec_u8 align_vec0, align_vec8, permh0, permh8, filt; + vec_u8 perm_6tap0, perm_6tap8, perml0, perml8; + vec_u8 a, b, pixh, pixl, outer; + vec_s16 f16h, f16l; + vec_s32 filth, filtl; + + vec_u8 perm_inner6 = { 1,2,3,4, 2,3,4,5, 3,4,5,6, 4,5,6,7 }; + vec_u8 perm_inner4 = { 0,1,2,3, 1,2,3,4, 2,3,4,5, 3,4,5,6 }; + vec_u8 perm_inner = is6tap ? perm_inner6 : perm_inner4; + vec_u8 perm_outer = { 4,9, 0,5, 5,10, 1,6, 6,11, 2,7, 7,12, 3,8 }; + vec_s32 c64 = vec_sl(vec_splat_s32(1), vec_splat_u32(6)); + vec_u16 c7 = vec_splat_u16(7); + + align_vec0 = vec_lvsl( -is6tap-1, src); + align_vec8 = vec_lvsl(8-is6tap-1, src); + + permh0 = vec_perm(align_vec0, align_vec0, perm_inner); + permh8 = vec_perm(align_vec8, align_vec8, perm_inner); + perm_inner = vec_add(perm_inner, vec_splat_u8(4)); + perml0 = vec_perm(align_vec0, align_vec0, perm_inner); + perml8 = vec_perm(align_vec8, align_vec8, perm_inner); + perm_6tap0 = vec_perm(align_vec0, align_vec0, perm_outer); + perm_6tap8 = vec_perm(align_vec8, align_vec8, perm_outer); + + while (h --> 0) { + FILTER_H(f16h, 0); + + if (w == 16) { + FILTER_H(f16l, 8); + filt = vec_packsu(f16h, f16l); + vec_st(filt, 0, dst); + } else { + filt = vec_packsu(f16h, f16h); + vec_ste((vec_u32)filt, 0, (uint32_t*)dst); + if (w == 8) + vec_ste((vec_u32)filt, 4, (uint32_t*)dst); + } + src += src_stride; + dst += dst_stride; + } +} + +// v subpel filter does a simple vertical multiply + add +static const vec_u8 v_subpel_filters[7] = +{ + { 0, 6, 123, 12, 1, 0 }, + { 2, 11, 108, 36, 8, 1 }, + { 0, 9, 93, 50, 6, 0 }, + { 3, 16, 77, 77, 16, 3 }, + { 0, 6, 50, 93, 9, 0 }, + { 1, 8, 36, 108, 11, 2 }, + { 0, 1, 12, 123, 6, 0 }, +}; + +#define LOAD_V_SUBPEL_FILTER(i) \ + vec_u8 subpel_filter = v_subpel_filters[i]; \ + vec_u8 f0 = vec_splat(subpel_filter, 0); \ + vec_u8 f1 = vec_splat(subpel_filter, 1); \ + vec_u8 f2 = vec_splat(subpel_filter, 2); \ + vec_u8 f3 = vec_splat(subpel_filter, 3); \ + vec_u8 f4 = vec_splat(subpel_filter, 4); \ + vec_u8 f5 = vec_splat(subpel_filter, 5) + +#define FILTER_V(dstv, vec_mul) \ + s1f = (vec_s16)vec_mul(s1, f1); \ + s2f = (vec_s16)vec_mul(s2, f2); \ + s3f = (vec_s16)vec_mul(s3, f3); \ + s4f = (vec_s16)vec_mul(s4, f4); \ + s2f = vec_subs(s2f, s1f); \ + s3f = vec_subs(s3f, s4f); \ + if (is6tap) { \ + s0f = (vec_s16)vec_mul(s0, f0); \ + s5f = (vec_s16)vec_mul(s5, f5); \ + s2f = vec_adds(s2f, s0f); \ + s3f = vec_adds(s3f, s5f); \ + } \ + dstv = vec_adds(s2f, s3f); \ + dstv = vec_adds(dstv, c64); \ + dstv = vec_sra(dstv, c7) + +static av_always_inline +void put_vp8_epel_v_altivec_core(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int my, int w, int is6tap) +{ + LOAD_V_SUBPEL_FILTER(my-1); + vec_u8 s0, s1, s2, s3, s4, s5, filt, align_vech, perm_vec, align_vecl; + vec_s16 s0f, s1f, s2f, s3f, s4f, s5f, f16h, f16l; + vec_s16 c64 = vec_sl(vec_splat_s16(1), vec_splat_u16(6)); + vec_u16 c7 = vec_splat_u16(7); + + // we want pixels 0-7 to be in the even positions and 8-15 in the odd, + // so combine this permute with the alignment permute vector + align_vech = vec_lvsl(0, src); + align_vecl = vec_sld(align_vech, align_vech, 8); + if (w ==16) + perm_vec = vec_mergeh(align_vech, align_vecl); + else + perm_vec = vec_mergeh(align_vech, align_vech); + + if (is6tap) + s0 = load_with_perm_vec(-2*src_stride, src, perm_vec); + s1 = load_with_perm_vec(-1*src_stride, src, perm_vec); + s2 = load_with_perm_vec( 0*src_stride, src, perm_vec); + s3 = load_with_perm_vec( 1*src_stride, src, perm_vec); + if (is6tap) + s4 = load_with_perm_vec( 2*src_stride, src, perm_vec); + + src += (2+is6tap)*src_stride; + + while (h --> 0) { + if (is6tap) + s5 = load_with_perm_vec(0, src, perm_vec); + else + s4 = load_with_perm_vec(0, src, perm_vec); + + FILTER_V(f16h, vec_mule); + + if (w == 16) { + FILTER_V(f16l, vec_mulo); + filt = vec_packsu(f16h, f16l); + vec_st(filt, 0, dst); + } else { + filt = vec_packsu(f16h, f16h); + if (w == 4) + filt = (vec_u8)vec_splat((vec_u32)filt, 0); + else + vec_ste((vec_u32)filt, 4, (uint32_t*)dst); + vec_ste((vec_u32)filt, 0, (uint32_t*)dst); + } + + if (is6tap) + s0 = s1; + s1 = s2; + s2 = s3; + s3 = s4; + if (is6tap) + s4 = s5; + + dst += dst_stride; + src += src_stride; + } +} + +#define EPEL_FUNCS(WIDTH, TAPS) \ +static av_noinline \ +void put_vp8_epel ## WIDTH ## _h ## TAPS ## _altivec(uint8_t *dst, ptrdiff_t dst_stride, uint8_t *src, ptrdiff_t src_stride, int h, int mx, int my) \ +{ \ + put_vp8_epel_h_altivec_core(dst, dst_stride, src, src_stride, h, mx, WIDTH, TAPS == 6); \ +} \ +\ +static av_noinline \ +void put_vp8_epel ## WIDTH ## _v ## TAPS ## _altivec(uint8_t *dst, ptrdiff_t dst_stride, uint8_t *src, ptrdiff_t src_stride, int h, int mx, int my) \ +{ \ + put_vp8_epel_v_altivec_core(dst, dst_stride, src, src_stride, h, my, WIDTH, TAPS == 6); \ +} + +#define EPEL_HV(WIDTH, HTAPS, VTAPS) \ +static void put_vp8_epel ## WIDTH ## _h ## HTAPS ## v ## VTAPS ## _altivec(uint8_t *dst, ptrdiff_t stride, uint8_t *src, ptrdiff_t s, int h, int mx, int my) \ +{ \ + DECLARE_ALIGNED(16, uint8_t, tmp)[(2*WIDTH+5)*16]; \ + if (VTAPS == 6) { \ + put_vp8_epel ## WIDTH ## _h ## HTAPS ## _altivec(tmp, 16, src-2*stride, stride, h+5, mx, my); \ + put_vp8_epel ## WIDTH ## _v ## VTAPS ## _altivec(dst, stride, tmp+2*16, 16, h, mx, my); \ + } else { \ + put_vp8_epel ## WIDTH ## _h ## HTAPS ## _altivec(tmp, 16, src-stride, stride, h+4, mx, my); \ + put_vp8_epel ## WIDTH ## _v ## VTAPS ## _altivec(dst, stride, tmp+16, 16, h, mx, my); \ + } \ +} + +EPEL_FUNCS(16,6) +EPEL_FUNCS(8, 6) +EPEL_FUNCS(8, 4) +EPEL_FUNCS(4, 6) +EPEL_FUNCS(4, 4) + +EPEL_HV(16, 6,6) +EPEL_HV(8, 6,6) +EPEL_HV(8, 4,6) +EPEL_HV(8, 6,4) +EPEL_HV(8, 4,4) +EPEL_HV(4, 6,6) +EPEL_HV(4, 4,6) +EPEL_HV(4, 6,4) +EPEL_HV(4, 4,4) + +static void put_vp8_pixels16_altivec(uint8_t *dst, ptrdiff_t stride, uint8_t *src, ptrdiff_t s, int h, int mx, int my) +{ + ff_put_pixels16_altivec(dst, src, stride, h); +} + +av_cold void ff_vp8dsp_init_altivec(VP8DSPContext *c) +{ + if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) + return; + + c->put_vp8_epel_pixels_tab[0][0][0] = put_vp8_pixels16_altivec; + c->put_vp8_epel_pixels_tab[0][0][2] = put_vp8_epel16_h6_altivec; + c->put_vp8_epel_pixels_tab[0][2][0] = put_vp8_epel16_v6_altivec; + c->put_vp8_epel_pixels_tab[0][2][2] = put_vp8_epel16_h6v6_altivec; + + c->put_vp8_epel_pixels_tab[1][0][2] = put_vp8_epel8_h6_altivec; + c->put_vp8_epel_pixels_tab[1][2][0] = put_vp8_epel8_v6_altivec; + c->put_vp8_epel_pixels_tab[1][0][1] = put_vp8_epel8_h4_altivec; + c->put_vp8_epel_pixels_tab[1][1][0] = put_vp8_epel8_v4_altivec; + + c->put_vp8_epel_pixels_tab[1][2][2] = put_vp8_epel8_h6v6_altivec; + c->put_vp8_epel_pixels_tab[1][1][1] = put_vp8_epel8_h4v4_altivec; + c->put_vp8_epel_pixels_tab[1][1][2] = put_vp8_epel8_h6v4_altivec; + c->put_vp8_epel_pixels_tab[1][2][1] = put_vp8_epel8_h4v6_altivec; + + c->put_vp8_epel_pixels_tab[2][0][2] = put_vp8_epel4_h6_altivec; + c->put_vp8_epel_pixels_tab[2][2][0] = put_vp8_epel4_v6_altivec; + c->put_vp8_epel_pixels_tab[2][0][1] = put_vp8_epel4_h4_altivec; + c->put_vp8_epel_pixels_tab[2][1][0] = put_vp8_epel4_v4_altivec; + + c->put_vp8_epel_pixels_tab[2][2][2] = put_vp8_epel4_h6v6_altivec; + c->put_vp8_epel_pixels_tab[2][1][1] = put_vp8_epel4_h4v4_altivec; + c->put_vp8_epel_pixels_tab[2][1][2] = put_vp8_epel4_h6v4_altivec; + c->put_vp8_epel_pixels_tab[2][2][1] = put_vp8_epel4_h4v6_altivec; +} diff --git a/ffmpeg/libavcodec/proresdata.c b/ffmpeg/libavcodec/proresdata.c new file mode 100644 index 0000000..fcaf32a --- /dev/null +++ b/ffmpeg/libavcodec/proresdata.c @@ -0,0 +1,72 @@ +/* + * Apple ProRes compatible decoder + * + * Copyright (c) 2010-2011 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "proresdata.h" + +const uint8_t ff_prores_progressive_scan[64] = { + 0, 1, 8, 9, 2, 3, 10, 11, + 16, 17, 24, 25, 18, 19, 26, 27, + 4, 5, 12, 20, 13, 6, 7, 14, + 21, 28, 29, 22, 15, 23, 30, 31, + 32, 33, 40, 48, 41, 34, 35, 42, + 49, 56, 57, 50, 43, 36, 37, 44, + 51, 58, 59, 52, 45, 38, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +const uint8_t ff_prores_interlaced_scan[64] = { + 0, 8, 1, 9, 16, 24, 17, 25, + 2, 10, 3, 11, 18, 26, 19, 27, + 32, 40, 33, 34, 41, 48, 56, 49, + 42, 35, 43, 50, 57, 58, 51, 59, + 4, 12, 5, 6, 13, 20, 28, 21, + 14, 7, 15, 22, 29, 36, 44, 37, + 30, 23, 31, 38, 45, 52, 60, 53, + 46, 39, 47, 54, 61, 62, 55, 63 +}; + + +const uint8_t ff_prores_dc_codebook[4] = { + 0x04, // rice_order = 0, exp_golomb_order = 1, switch_bits = 0 + 0x28, // rice_order = 1, exp_golomb_order = 2, switch_bits = 0 + 0x4D, // rice_order = 2, exp_golomb_order = 3, switch_bits = 1 + 0x70 // rice_order = 3, exp_golomb_order = 4, switch_bits = 0 +}; + +const uint8_t ff_prores_ac_codebook[7] = { + 0x04, // rice_order = 0, exp_golomb_order = 1, switch_bits = 0 + 0x28, // rice_order = 1, exp_golomb_order = 2, switch_bits = 0 + 0x4C, // rice_order = 2, exp_golomb_order = 3, switch_bits = 0 + 0x05, // rice_order = 0, exp_golomb_order = 1, switch_bits = 1 + 0x29, // rice_order = 1, exp_golomb_order = 2, switch_bits = 1 + 0x06, // rice_order = 0, exp_golomb_order = 1, switch_bits = 2 + 0x0A, // rice_order = 0, exp_golomb_order = 2, switch_bits = 2 +}; + +/** + * Lookup tables for adaptive switching between codebooks + * according with previous run/level value. + */ +const uint8_t ff_prores_run_to_cb_index[16] = + { 5, 5, 3, 3, 0, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 2 }; + +const uint8_t ff_prores_lev_to_cb_index[10] = { 0, 6, 3, 5, 0, 1, 1, 1, 1, 2 }; diff --git a/ffmpeg/libavcodec/proresdata.h b/ffmpeg/libavcodec/proresdata.h new file mode 100644 index 0000000..ee8278d --- /dev/null +++ b/ffmpeg/libavcodec/proresdata.h @@ -0,0 +1,39 @@ +/* + * Apple ProRes compatible decoder + * + * Copyright (c) 2010-2011 Maxim Poliakovski + * + * 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 + */ + +#ifndef AVCODEC_PRORESDATA_H +#define AVCODEC_PRORESDATA_H + +#include + +#define FRAME_ID MKBETAG('i', 'c', 'p', 'f') + +extern const uint8_t ff_prores_progressive_scan[64]; +extern const uint8_t ff_prores_interlaced_scan[64]; + +#define FIRST_DC_CB 0xB8 // rice_order = 5, exp_golomb_order = 6, switch_bits = 0 +extern const uint8_t ff_prores_dc_codebook[4]; +extern const uint8_t ff_prores_ac_codebook[7]; +extern const uint8_t ff_prores_run_to_cb_index[16]; +extern const uint8_t ff_prores_lev_to_cb_index[10]; + +#endif /* AVCODEC_PRORESDATA_H */ diff --git a/ffmpeg/libavcodec/proresdec.h b/ffmpeg/libavcodec/proresdec.h new file mode 100644 index 0000000..f42c448 --- /dev/null +++ b/ffmpeg/libavcodec/proresdec.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2011 Maxim Poliakovski + * Copyright (c) 2010-2011 Elvis Presley + * + * 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 + */ + +#ifndef AVCODEC_PRORESDEC_H +#define AVCODEC_PRORESDEC_H + +#include "dsputil.h" +#include "proresdsp.h" + +typedef struct { + const uint8_t *data; + unsigned mb_x; + unsigned mb_y; + unsigned mb_count; + unsigned data_size; + int ret; +} SliceContext; + +typedef struct { + DSPContext dsp; + ProresDSPContext prodsp; + AVFrame *frame; + int frame_type; ///< 0 = progressive, 1 = tff, 2 = bff + uint8_t qmat_luma[64]; + uint8_t qmat_chroma[64]; + SliceContext *slices; + int slice_count; ///< number of slices in the current picture + unsigned mb_width; ///< width of the current picture in mb + unsigned mb_height; ///< height of the current picture in mb + uint8_t progressive_scan[64]; + uint8_t interlaced_scan[64]; + const uint8_t *scan; + int first_field; +} ProresContext; + +#endif /* AVCODEC_PRORESDEC_H */ diff --git a/ffmpeg/libavcodec/proresdec2.c b/ffmpeg/libavcodec/proresdec2.c new file mode 100644 index 0000000..b7aef36 --- /dev/null +++ b/ffmpeg/libavcodec/proresdec2.c @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2010-2011 Maxim Poliakovski + * Copyright (c) 2010-2011 Elvis Presley + * + * 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 + */ + +/** + * @file + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy), 'ap4h' (4444) + */ + +//#define DEBUG + +#define LONG_BITSTREAM_READER + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "simple_idct.h" +#include "proresdec.h" + +static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64]) +{ + int i; + for (i = 0; i < 64; i++) + dst[i] = permutation[src[i]]; +} + +static const uint8_t progressive_scan[64] = { + 0, 1, 8, 9, 2, 3, 10, 11, + 16, 17, 24, 25, 18, 19, 26, 27, + 4, 5, 12, 20, 13, 6, 7, 14, + 21, 28, 29, 22, 15, 23, 30, 31, + 32, 33, 40, 48, 41, 34, 35, 42, + 49, 56, 57, 50, 43, 36, 37, 44, + 51, 58, 59, 52, 45, 38, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static const uint8_t interlaced_scan[64] = { + 0, 8, 1, 9, 16, 24, 17, 25, + 2, 10, 3, 11, 18, 26, 19, 27, + 32, 40, 33, 34, 41, 48, 56, 49, + 42, 35, 43, 50, 57, 58, 51, 59, + 4, 12, 5, 6, 13, 20, 28, 21, + 14, 7, 15, 22, 29, 36, 44, 37, + 30, 23, 31, 38, 45, 52, 60, 53, + 46, 39, 47, 54, 61, 62, 55, 63, +}; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + uint8_t idct_permutation[64]; + + avctx->bits_per_raw_sample = 10; + + ff_dsputil_init(&ctx->dsp, avctx); + ff_proresdsp_init(&ctx->prodsp, avctx); + + ff_init_scantable_permutation(idct_permutation, + ctx->prodsp.idct_permutation_type); + + permute(ctx->progressive_scan, progressive_scan, idct_permutation); + permute(ctx->interlaced_scan, interlaced_scan, idct_permutation); + + return 0; +} + +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, + const int data_size, AVCodecContext *avctx) +{ + int hdr_size, width, height, flags; + int version; + const uint8_t *ptr; + + hdr_size = AV_RB16(buf); + av_dlog(avctx, "header size %d\n", hdr_size); + if (hdr_size > data_size) { + av_log(avctx, AV_LOG_ERROR, "error, wrong header size\n"); + return -1; + } + + version = AV_RB16(buf + 2); + av_dlog(avctx, "%.4s version %d\n", buf+4, version); + if (version > 1) { + av_log(avctx, AV_LOG_ERROR, "unsupported version: %d\n", version); + return -1; + } + + width = AV_RB16(buf + 8); + height = AV_RB16(buf + 10); + if (width != avctx->width || height != avctx->height) { + av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n", + avctx->width, avctx->height, width, height); + return -1; + } + + ctx->frame_type = (buf[12] >> 2) & 3; + + av_dlog(avctx, "frame type %d\n", ctx->frame_type); + + if (ctx->frame_type == 0) { + ctx->scan = ctx->progressive_scan; // permuted + } else { + ctx->scan = ctx->interlaced_scan; // permuted + ctx->frame->interlaced_frame = 1; + ctx->frame->top_field_first = ctx->frame_type == 1; + } + + avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + + ptr = buf + 20; + flags = buf[19]; + av_dlog(avctx, "flags %x\n", flags); + + if (flags & 2) { + if(buf + data_size - ptr < 64) { + av_log(avctx, AV_LOG_ERROR, "Header truncated\n"); + return -1; + } + permute(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr); + ptr += 64; + } else { + memset(ctx->qmat_luma, 4, 64); + } + + if (flags & 1) { + if(buf + data_size - ptr < 64) { + av_log(avctx, AV_LOG_ERROR, "Header truncated\n"); + return -1; + } + permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr); + } else { + memset(ctx->qmat_chroma, 4, 64); + } + + return hdr_size; +} + +static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, const int buf_size) +{ + ProresContext *ctx = avctx->priv_data; + int i, hdr_size, slice_count; + unsigned pic_data_size; + int log2_slice_mb_width, log2_slice_mb_height; + int slice_mb_count, mb_x, mb_y; + const uint8_t *data_ptr, *index_ptr; + + hdr_size = buf[0] >> 3; + if (hdr_size < 8 || hdr_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "error, wrong picture header size\n"); + return -1; + } + + pic_data_size = AV_RB32(buf + 1); + if (pic_data_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "error, wrong picture data size\n"); + return -1; + } + + log2_slice_mb_width = buf[7] >> 4; + log2_slice_mb_height = buf[7] & 0xF; + if (log2_slice_mb_width > 3 || log2_slice_mb_height) { + av_log(avctx, AV_LOG_ERROR, "unsupported slice resolution: %dx%d\n", + 1 << log2_slice_mb_width, 1 << log2_slice_mb_height); + return -1; + } + + ctx->mb_width = (avctx->width + 15) >> 4; + if (ctx->frame_type) + ctx->mb_height = (avctx->height + 31) >> 5; + else + ctx->mb_height = (avctx->height + 15) >> 4; + + slice_count = AV_RB16(buf + 5); + + if (ctx->slice_count != slice_count || !ctx->slices) { + av_freep(&ctx->slices); + ctx->slices = av_mallocz(slice_count * sizeof(*ctx->slices)); + if (!ctx->slices) + return AVERROR(ENOMEM); + ctx->slice_count = slice_count; + } + + if (!slice_count) + return AVERROR(EINVAL); + + if (hdr_size + slice_count*2 > buf_size) { + av_log(avctx, AV_LOG_ERROR, "error, wrong slice count\n"); + return -1; + } + + // parse slice information + index_ptr = buf + hdr_size; + data_ptr = index_ptr + slice_count*2; + + slice_mb_count = 1 << log2_slice_mb_width; + mb_x = 0; + mb_y = 0; + + for (i = 0; i < slice_count; i++) { + SliceContext *slice = &ctx->slices[i]; + + slice->data = data_ptr; + data_ptr += AV_RB16(index_ptr + i*2); + + while (ctx->mb_width - mb_x < slice_mb_count) + slice_mb_count >>= 1; + + slice->mb_x = mb_x; + slice->mb_y = mb_y; + slice->mb_count = slice_mb_count; + slice->data_size = data_ptr - slice->data; + + if (slice->data_size < 6) { + av_log(avctx, AV_LOG_ERROR, "error, wrong slice data size\n"); + return -1; + } + + mb_x += slice_mb_count; + if (mb_x == ctx->mb_width) { + slice_mb_count = 1 << log2_slice_mb_width; + mb_x = 0; + mb_y++; + } + if (data_ptr > buf + buf_size) { + av_log(avctx, AV_LOG_ERROR, "error, slice out of bounds\n"); + return -1; + } + } + + if (mb_x || mb_y != ctx->mb_height) { + av_log(avctx, AV_LOG_ERROR, "error wrong mb count y %d h %d\n", + mb_y, ctx->mb_height); + return -1; + } + + return pic_data_size; +} + +#define DECODE_CODEWORD(val, codebook) \ + do { \ + unsigned int rice_order, exp_order, switch_bits; \ + unsigned int q, buf, bits; \ + \ + UPDATE_CACHE(re, gb); \ + buf = GET_CACHE(re, gb); \ + \ + /* number of bits to switch between rice and exp golomb */ \ + switch_bits = codebook & 3; \ + rice_order = codebook >> 5; \ + exp_order = (codebook >> 2) & 7; \ + \ + q = 31 - av_log2(buf); \ + \ + if (q > switch_bits) { /* exp golomb */ \ + bits = exp_order - switch_bits + (q<<1); \ + val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) + \ + ((switch_bits + 1) << rice_order); \ + SKIP_BITS(re, gb, bits); \ + } else if (rice_order) { \ + SKIP_BITS(re, gb, q+1); \ + val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order); \ + SKIP_BITS(re, gb, rice_order); \ + } else { \ + val = q; \ + SKIP_BITS(re, gb, q+1); \ + } \ + } while (0) + +#define TOSIGNED(x) (((x) >> 1) ^ (-((x) & 1))) + +#define FIRST_DC_CB 0xB8 + +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70}; + +static av_always_inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out, + int blocks_per_slice) +{ + int16_t prev_dc; + int code, i, sign; + + OPEN_READER(re, gb); + + DECODE_CODEWORD(code, FIRST_DC_CB); + prev_dc = TOSIGNED(code); + out[0] = prev_dc; + + out += 64; // dc coeff for the next block + + code = 5; + sign = 0; + for (i = 1; i < blocks_per_slice; i++, out += 64) { + DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)]); + if(code) sign ^= -(code & 1); + else sign = 0; + prev_dc += (((code + 1) >> 1) ^ sign) - sign; + out[0] = prev_dc; + } + CLOSE_READER(re, gb); +} + +// adaptive codebook switching lut according to previous run/level values +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C }; +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C }; + +static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb, + int16_t *out, int blocks_per_slice) +{ + ProresContext *ctx = avctx->priv_data; + int block_mask, sign; + unsigned pos, run, level; + int max_coeffs, i, bits_left; + int log2_block_count = av_log2(blocks_per_slice); + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); \ + run = 4; + level = 2; + + max_coeffs = 64 << log2_block_count; + block_mask = blocks_per_slice - 1; + + for (pos = block_mask;;) { + bits_left = gb->size_in_bits - re_index; + if (!bits_left || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left))) + break; + + DECODE_CODEWORD(run, run_to_cb[FFMIN(run, 15)]); + pos += run + 1; + if (pos >= max_coeffs) { + av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs); + return; + } + + DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]); + level += 1; + + i = pos >> log2_block_count; + + sign = SHOW_SBITS(re, gb, 1); + SKIP_BITS(re, gb, 1); + out[((pos & block_mask) << 6) + ctx->scan[i]] = ((level ^ sign) - sign); + } + + CLOSE_READER(re, gb); +} + +static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice, + uint16_t *dst, int dst_stride, + const uint8_t *buf, unsigned buf_size, + const int16_t *qmat) +{ + ProresContext *ctx = avctx->priv_data; + LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]); + int16_t *block; + GetBitContext gb; + int i, blocks_per_slice = slice->mb_count<<2; + + for (i = 0; i < blocks_per_slice; i++) + ctx->dsp.clear_block(blocks+(i<<6)); + + init_get_bits(&gb, buf, buf_size << 3); + + decode_dc_coeffs(&gb, blocks, blocks_per_slice); + decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice); + + block = blocks; + for (i = 0; i < slice->mb_count; i++) { + ctx->prodsp.idct_put(dst, dst_stride, block+(0<<6), qmat); + ctx->prodsp.idct_put(dst +8, dst_stride, block+(1<<6), qmat); + ctx->prodsp.idct_put(dst+4*dst_stride , dst_stride, block+(2<<6), qmat); + ctx->prodsp.idct_put(dst+4*dst_stride+8, dst_stride, block+(3<<6), qmat); + block += 4*64; + dst += 16; + } +} + +static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice, + uint16_t *dst, int dst_stride, + const uint8_t *buf, unsigned buf_size, + const int16_t *qmat, int log2_blocks_per_mb) +{ + ProresContext *ctx = avctx->priv_data; + LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]); + int16_t *block; + GetBitContext gb; + int i, j, blocks_per_slice = slice->mb_count << log2_blocks_per_mb; + + for (i = 0; i < blocks_per_slice; i++) + ctx->dsp.clear_block(blocks+(i<<6)); + + init_get_bits(&gb, buf, buf_size << 3); + + decode_dc_coeffs(&gb, blocks, blocks_per_slice); + decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice); + + block = blocks; + for (i = 0; i < slice->mb_count; i++) { + for (j = 0; j < log2_blocks_per_mb; j++) { + ctx->prodsp.idct_put(dst, dst_stride, block+(0<<6), qmat); + ctx->prodsp.idct_put(dst+4*dst_stride, dst_stride, block+(1<<6), qmat); + block += 2*64; + dst += 8; + } + } +} + +static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) +{ + ProresContext *ctx = avctx->priv_data; + SliceContext *slice = &ctx->slices[jobnr]; + const uint8_t *buf = slice->data; + AVFrame *pic = ctx->frame; + int i, hdr_size, qscale, log2_chroma_blocks_per_mb; + int luma_stride, chroma_stride; + int y_data_size, u_data_size, v_data_size; + uint8_t *dest_y, *dest_u, *dest_v; + int16_t qmat_luma_scaled[64]; + int16_t qmat_chroma_scaled[64]; + int mb_x_shift; + + slice->ret = -1; + //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n", + // jobnr, slice->mb_count, slice->mb_x, slice->mb_y); + + // slice header + hdr_size = buf[0] >> 3; + qscale = av_clip(buf[1], 1, 224); + qscale = qscale > 128 ? qscale - 96 << 2: qscale; + y_data_size = AV_RB16(buf + 2); + u_data_size = AV_RB16(buf + 4); + v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size; + if (hdr_size > 7) v_data_size = AV_RB16(buf + 6); + + if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0 + || hdr_size+y_data_size+u_data_size+v_data_size > slice->data_size){ + av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n"); + return -1; + } + + buf += hdr_size; + + for (i = 0; i < 64; i++) { + qmat_luma_scaled [i] = ctx->qmat_luma [i] * qscale; + qmat_chroma_scaled[i] = ctx->qmat_chroma[i] * qscale; + } + + if (ctx->frame_type == 0) { + luma_stride = pic->linesize[0]; + chroma_stride = pic->linesize[1]; + } else { + luma_stride = pic->linesize[0] << 1; + chroma_stride = pic->linesize[1] << 1; + } + + if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10) { + mb_x_shift = 5; + log2_chroma_blocks_per_mb = 2; + } else { + mb_x_shift = 4; + log2_chroma_blocks_per_mb = 1; + } + + dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5); + dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); + dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift); + + if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) { + dest_y += pic->linesize[0]; + dest_u += pic->linesize[1]; + dest_v += pic->linesize[2]; + } + + decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride, + buf, y_data_size, qmat_luma_scaled); + + if (!(avctx->flags & CODEC_FLAG_GRAY)) { + decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride, + buf + y_data_size, u_data_size, + qmat_chroma_scaled, log2_chroma_blocks_per_mb); + decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride, + buf + y_data_size + u_data_size, v_data_size, + qmat_chroma_scaled, log2_chroma_blocks_per_mb); + } + + slice->ret = 0; + return 0; +} + +static int decode_picture(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + int i; + + avctx->execute2(avctx, decode_slice_thread, NULL, NULL, ctx->slice_count); + + for (i = 0; i < ctx->slice_count; i++) + if (ctx->slices[i].ret < 0) + return ctx->slices[i].ret; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + ProresContext *ctx = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int frame_hdr_size, pic_size; + + if (buf_size < 28 || AV_RL32(buf + 4) != AV_RL32("icpf")) { + av_log(avctx, AV_LOG_ERROR, "invalid frame header\n"); + return -1; + } + + ctx->frame = frame; + ctx->first_field = 1; + + buf += 8; + buf_size -= 8; + + frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx); + if (frame_hdr_size < 0) + return -1; + + buf += frame_hdr_size; + buf_size -= frame_hdr_size; + + if (ff_get_buffer(avctx, frame, 0) < 0) + return -1; + + decode_picture: + pic_size = decode_picture_header(avctx, buf, buf_size); + if (pic_size < 0) { + av_log(avctx, AV_LOG_ERROR, "error decoding picture header\n"); + return -1; + } + + if (decode_picture(avctx)) { + av_log(avctx, AV_LOG_ERROR, "error decoding picture\n"); + return -1; + } + + buf += pic_size; + buf_size -= pic_size; + + if (ctx->frame_type && buf_size > 0 && ctx->first_field) { + ctx->first_field = 0; + goto decode_picture; + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + + av_freep(&ctx->slices); + + return 0; +} + +AVCodec ff_prores_decoder = { + .name = "prores", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .priv_data_size = sizeof(ProresContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("ProRes"), + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, +}; diff --git a/ffmpeg/libavcodec/proresdec_lgpl.c b/ffmpeg/libavcodec/proresdec_lgpl.c new file mode 100644 index 0000000..59c9843 --- /dev/null +++ b/ffmpeg/libavcodec/proresdec_lgpl.c @@ -0,0 +1,668 @@ +/* + * Apple ProRes compatible decoder + * + * Copyright (c) 2010-2011 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * This is a decoder for Apple ProRes 422 SD/HQ/LT/Proxy and ProRes 4444. + * It is used for storing and editing high definition video data in Apple's Final Cut Pro. + * + * @see http://wiki.multimedia.cx/index.php?title=Apple_ProRes + */ + +#define LONG_BITSTREAM_READER // some ProRes vlc codes require up to 28 bits to be read at once + +#include + +#include "libavutil/intmath.h" +#include "avcodec.h" +#include "dsputil.h" +#include "internal.h" +#include "proresdata.h" +#include "proresdsp.h" +#include "get_bits.h" + +typedef struct { + const uint8_t *index; ///< pointers to the data of this slice + int slice_num; + int x_pos, y_pos; + int slice_width; + int prev_slice_sf; ///< scalefactor of the previous decoded slice + DECLARE_ALIGNED(16, int16_t, blocks)[8 * 4 * 64]; + DECLARE_ALIGNED(16, int16_t, qmat_luma_scaled)[64]; + DECLARE_ALIGNED(16, int16_t, qmat_chroma_scaled)[64]; +} ProresThreadData; + +typedef struct { + ProresDSPContext dsp; + AVFrame *frame; + ScanTable scantable; + int scantable_type; ///< -1 = uninitialized, 0 = progressive, 1/2 = interlaced + + int frame_type; ///< 0 = progressive, 1 = top-field first, 2 = bottom-field first + int pic_format; ///< 2 = 422, 3 = 444 + uint8_t qmat_luma[64]; ///< dequantization matrix for luma + uint8_t qmat_chroma[64]; ///< dequantization matrix for chroma + int qmat_changed; ///< 1 - global quantization matrices changed + int total_slices; ///< total number of slices in a picture + ProresThreadData *slice_data; + int pic_num; + int chroma_factor; + int mb_chroma_factor; + int num_chroma_blocks; ///< number of chrominance blocks in a macroblock + int num_x_slices; + int num_y_slices; + int slice_width_factor; + int slice_height_factor; + int num_x_mbs; + int num_y_mbs; + int alpha_info; +} ProresContext; + + +static av_cold int decode_init(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + + ctx->total_slices = 0; + ctx->slice_data = NULL; + + avctx->bits_per_raw_sample = PRORES_BITS_PER_SAMPLE; + ff_proresdsp_init(&ctx->dsp, avctx); + + ctx->scantable_type = -1; // set scantable type to uninitialized + memset(ctx->qmat_luma, 4, 64); + memset(ctx->qmat_chroma, 4, 64); + + return 0; +} + + +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, + const int data_size, AVCodecContext *avctx) +{ + int hdr_size, version, width, height, flags; + const uint8_t *ptr; + + hdr_size = AV_RB16(buf); + if (hdr_size > data_size) { + av_log(avctx, AV_LOG_ERROR, "frame data too small\n"); + return AVERROR_INVALIDDATA; + } + + version = AV_RB16(buf + 2); + if (version >= 2) { + av_log(avctx, AV_LOG_ERROR, + "unsupported header version: %d\n", version); + return AVERROR_INVALIDDATA; + } + + width = AV_RB16(buf + 8); + height = AV_RB16(buf + 10); + if (width != avctx->width || height != avctx->height) { + av_log(avctx, AV_LOG_ERROR, + "picture dimension changed: old: %d x %d, new: %d x %d\n", + avctx->width, avctx->height, width, height); + return AVERROR_INVALIDDATA; + } + + ctx->frame_type = (buf[12] >> 2) & 3; + if (ctx->frame_type > 2) { + av_log(avctx, AV_LOG_ERROR, + "unsupported frame type: %d\n", ctx->frame_type); + return AVERROR_INVALIDDATA; + } + + ctx->chroma_factor = (buf[12] >> 6) & 3; + ctx->mb_chroma_factor = ctx->chroma_factor + 2; + ctx->num_chroma_blocks = (1 << ctx->chroma_factor) >> 1; + switch (ctx->chroma_factor) { + case 2: + avctx->pix_fmt = AV_PIX_FMT_YUV422P10; + break; + case 3: + avctx->pix_fmt = AV_PIX_FMT_YUV444P10; + break; + default: + av_log(avctx, AV_LOG_ERROR, + "unsupported picture format: %d\n", ctx->pic_format); + return AVERROR_INVALIDDATA; + } + + if (ctx->scantable_type != ctx->frame_type) { + if (!ctx->frame_type) + ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, + ff_prores_progressive_scan); + else + ff_init_scantable(ctx->dsp.idct_permutation, &ctx->scantable, + ff_prores_interlaced_scan); + ctx->scantable_type = ctx->frame_type; + } + + if (ctx->frame_type) { /* if interlaced */ + ctx->frame->interlaced_frame = 1; + ctx->frame->top_field_first = ctx->frame_type & 1; + } else { + ctx->frame->interlaced_frame = 0; + } + + avctx->color_primaries = buf[14]; + avctx->color_trc = buf[15]; + avctx->colorspace = buf[16]; + + ctx->alpha_info = buf[17] & 0xf; + if (ctx->alpha_info) + avpriv_report_missing_feature(avctx, "Alpha channel"); + + ctx->qmat_changed = 0; + ptr = buf + 20; + flags = buf[19]; + if (flags & 2) { + if (ptr - buf > hdr_size - 64) { + av_log(avctx, AV_LOG_ERROR, "header data too small\n"); + return AVERROR_INVALIDDATA; + } + if (memcmp(ctx->qmat_luma, ptr, 64)) { + memcpy(ctx->qmat_luma, ptr, 64); + ctx->qmat_changed = 1; + } + ptr += 64; + } else { + memset(ctx->qmat_luma, 4, 64); + ctx->qmat_changed = 1; + } + + if (flags & 1) { + if (ptr - buf > hdr_size - 64) { + av_log(avctx, AV_LOG_ERROR, "header data too small\n"); + return -1; + } + if (memcmp(ctx->qmat_chroma, ptr, 64)) { + memcpy(ctx->qmat_chroma, ptr, 64); + ctx->qmat_changed = 1; + } + } else { + memset(ctx->qmat_chroma, 4, 64); + ctx->qmat_changed = 1; + } + + return hdr_size; +} + + +static int decode_picture_header(ProresContext *ctx, const uint8_t *buf, + const int data_size, AVCodecContext *avctx) +{ + int i, hdr_size, pic_data_size, num_slices; + int slice_width_factor, slice_height_factor; + int remainder, num_x_slices; + const uint8_t *data_ptr, *index_ptr; + + hdr_size = data_size > 0 ? buf[0] >> 3 : 0; + if (hdr_size < 8 || hdr_size > data_size) { + av_log(avctx, AV_LOG_ERROR, "picture header too small\n"); + return AVERROR_INVALIDDATA; + } + + pic_data_size = AV_RB32(buf + 1); + if (pic_data_size > data_size) { + av_log(avctx, AV_LOG_ERROR, "picture data too small\n"); + return AVERROR_INVALIDDATA; + } + + slice_width_factor = buf[7] >> 4; + slice_height_factor = buf[7] & 0xF; + if (slice_width_factor > 3 || slice_height_factor) { + av_log(avctx, AV_LOG_ERROR, + "unsupported slice dimension: %d x %d\n", + 1 << slice_width_factor, 1 << slice_height_factor); + return AVERROR_INVALIDDATA; + } + + ctx->slice_width_factor = slice_width_factor; + ctx->slice_height_factor = slice_height_factor; + + ctx->num_x_mbs = (avctx->width + 15) >> 4; + ctx->num_y_mbs = (avctx->height + + (1 << (4 + ctx->frame->interlaced_frame)) - 1) >> + (4 + ctx->frame->interlaced_frame); + + remainder = ctx->num_x_mbs & ((1 << slice_width_factor) - 1); + num_x_slices = (ctx->num_x_mbs >> slice_width_factor) + (remainder & 1) + + ((remainder >> 1) & 1) + ((remainder >> 2) & 1); + + num_slices = num_x_slices * ctx->num_y_mbs; + if (num_slices != AV_RB16(buf + 5)) { + av_log(avctx, AV_LOG_ERROR, "invalid number of slices\n"); + return AVERROR_INVALIDDATA; + } + + if (ctx->total_slices != num_slices) { + av_freep(&ctx->slice_data); + ctx->slice_data = av_malloc((num_slices + 1) * sizeof(ctx->slice_data[0])); + if (!ctx->slice_data) + return AVERROR(ENOMEM); + ctx->total_slices = num_slices; + } + + if (hdr_size + num_slices * 2 > data_size) { + av_log(avctx, AV_LOG_ERROR, "slice table too small\n"); + return AVERROR_INVALIDDATA; + } + + /* parse slice table allowing quick access to the slice data */ + index_ptr = buf + hdr_size; + data_ptr = index_ptr + num_slices * 2; + + for (i = 0; i < num_slices; i++) { + ctx->slice_data[i].index = data_ptr; + ctx->slice_data[i].prev_slice_sf = 0; + data_ptr += AV_RB16(index_ptr + i * 2); + } + ctx->slice_data[i].index = data_ptr; + ctx->slice_data[i].prev_slice_sf = 0; + + if (data_ptr > buf + data_size) { + av_log(avctx, AV_LOG_ERROR, "out of slice data\n"); + return -1; + } + + return pic_data_size; +} + + +/** + * Read an unsigned rice/exp golomb codeword. + */ +static inline int decode_vlc_codeword(GetBitContext *gb, unsigned codebook) +{ + unsigned int rice_order, exp_order, switch_bits; + unsigned int buf, code; + int log, prefix_len, len; + + OPEN_READER(re, gb); + UPDATE_CACHE(re, gb); + buf = GET_CACHE(re, gb); + + /* number of prefix bits to switch between Rice and expGolomb */ + switch_bits = (codebook & 3) + 1; + rice_order = codebook >> 5; /* rice code order */ + exp_order = (codebook >> 2) & 7; /* exp golomb code order */ + + log = 31 - av_log2(buf); /* count prefix bits (zeroes) */ + + if (log < switch_bits) { /* ok, we got a rice code */ + if (!rice_order) { + /* shortcut for faster decoding of rice codes without remainder */ + code = log; + LAST_SKIP_BITS(re, gb, log + 1); + } else { + prefix_len = log + 1; + code = (log << rice_order) + NEG_USR32(buf << prefix_len, rice_order); + LAST_SKIP_BITS(re, gb, prefix_len + rice_order); + } + } else { /* otherwise we got a exp golomb code */ + len = (log << 1) - switch_bits + exp_order + 1; + code = NEG_USR32(buf, len) - (1 << exp_order) + (switch_bits << rice_order); + LAST_SKIP_BITS(re, gb, len); + } + + CLOSE_READER(re, gb); + + return code; +} + +#define LSB2SIGN(x) (-((x) & 1)) +#define TOSIGNED(x) (((x) >> 1) ^ LSB2SIGN(x)) + +/** + * Decode DC coefficients for all blocks in a slice. + */ +static inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out, + int nblocks) +{ + int16_t prev_dc; + int i, sign; + int16_t delta; + unsigned int code; + + code = decode_vlc_codeword(gb, FIRST_DC_CB); + out[0] = prev_dc = TOSIGNED(code); + + out += 64; /* move to the DC coeff of the next block */ + delta = 3; + + for (i = 1; i < nblocks; i++, out += 64) { + code = decode_vlc_codeword(gb, ff_prores_dc_codebook[FFMIN(FFABS(delta), 3)]); + + sign = -(((delta >> 15) & 1) ^ (code & 1)); + delta = (((code + 1) >> 1) ^ sign) - sign; + prev_dc += delta; + out[0] = prev_dc; + } +} + + +/** + * Decode AC coefficients for all blocks in a slice. + */ +static inline void decode_ac_coeffs(GetBitContext *gb, int16_t *out, + int blocks_per_slice, + int plane_size_factor, + const uint8_t *scan) +{ + int pos, block_mask, run, level, sign, run_cb_index, lev_cb_index; + int max_coeffs, bits_left; + + /* set initial prediction values */ + run = 4; + level = 2; + + max_coeffs = blocks_per_slice << 6; + block_mask = blocks_per_slice - 1; + + for (pos = blocks_per_slice - 1; pos < max_coeffs;) { + run_cb_index = ff_prores_run_to_cb_index[FFMIN(run, 15)]; + lev_cb_index = ff_prores_lev_to_cb_index[FFMIN(level, 9)]; + + bits_left = get_bits_left(gb); + if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left))) + return; + + run = decode_vlc_codeword(gb, ff_prores_ac_codebook[run_cb_index]); + + bits_left = get_bits_left(gb); + if (bits_left <= 0 || (bits_left <= 8 && !show_bits(gb, bits_left))) + return; + + level = decode_vlc_codeword(gb, ff_prores_ac_codebook[lev_cb_index]) + 1; + + pos += run + 1; + if (pos >= max_coeffs) + break; + + sign = get_sbits(gb, 1); + out[((pos & block_mask) << 6) + scan[pos >> plane_size_factor]] = + (level ^ sign) - sign; + } +} + + +/** + * Decode a slice plane (luma or chroma). + */ +static void decode_slice_plane(ProresContext *ctx, ProresThreadData *td, + const uint8_t *buf, + int data_size, uint16_t *out_ptr, + int linesize, int mbs_per_slice, + int blocks_per_mb, int plane_size_factor, + const int16_t *qmat, int is_chroma) +{ + GetBitContext gb; + int16_t *block_ptr; + int mb_num, blocks_per_slice; + + blocks_per_slice = mbs_per_slice * blocks_per_mb; + + memset(td->blocks, 0, 8 * 4 * 64 * sizeof(*td->blocks)); + + init_get_bits(&gb, buf, data_size << 3); + + decode_dc_coeffs(&gb, td->blocks, blocks_per_slice); + + decode_ac_coeffs(&gb, td->blocks, blocks_per_slice, + plane_size_factor, ctx->scantable.permutated); + + /* inverse quantization, inverse transform and output */ + block_ptr = td->blocks; + + if (!is_chroma) { + for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) { + ctx->dsp.idct_put(out_ptr, linesize, block_ptr, qmat); + block_ptr += 64; + if (blocks_per_mb > 2) { + ctx->dsp.idct_put(out_ptr + 8, linesize, block_ptr, qmat); + block_ptr += 64; + } + ctx->dsp.idct_put(out_ptr + linesize * 4, linesize, block_ptr, qmat); + block_ptr += 64; + if (blocks_per_mb > 2) { + ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat); + block_ptr += 64; + } + } + } else { + for (mb_num = 0; mb_num < mbs_per_slice; mb_num++, out_ptr += blocks_per_mb * 4) { + ctx->dsp.idct_put(out_ptr, linesize, block_ptr, qmat); + block_ptr += 64; + ctx->dsp.idct_put(out_ptr + linesize * 4, linesize, block_ptr, qmat); + block_ptr += 64; + if (blocks_per_mb > 2) { + ctx->dsp.idct_put(out_ptr + 8, linesize, block_ptr, qmat); + block_ptr += 64; + ctx->dsp.idct_put(out_ptr + linesize * 4 + 8, linesize, block_ptr, qmat); + block_ptr += 64; + } + } + } +} + + +static int decode_slice(AVCodecContext *avctx, void *tdata) +{ + ProresThreadData *td = tdata; + ProresContext *ctx = avctx->priv_data; + int mb_x_pos = td->x_pos; + int mb_y_pos = td->y_pos; + int pic_num = ctx->pic_num; + int slice_num = td->slice_num; + int mbs_per_slice = td->slice_width; + const uint8_t *buf; + uint8_t *y_data, *u_data, *v_data; + AVFrame *pic = ctx->frame; + int i, sf, slice_width_factor; + int slice_data_size, hdr_size, y_data_size, u_data_size, v_data_size; + int y_linesize, u_linesize, v_linesize; + + buf = ctx->slice_data[slice_num].index; + slice_data_size = ctx->slice_data[slice_num + 1].index - buf; + + slice_width_factor = av_log2(mbs_per_slice); + + y_data = pic->data[0]; + u_data = pic->data[1]; + v_data = pic->data[2]; + y_linesize = pic->linesize[0]; + u_linesize = pic->linesize[1]; + v_linesize = pic->linesize[2]; + + if (pic->interlaced_frame) { + if (!(pic_num ^ pic->top_field_first)) { + y_data += y_linesize; + u_data += u_linesize; + v_data += v_linesize; + } + y_linesize <<= 1; + u_linesize <<= 1; + v_linesize <<= 1; + } + + if (slice_data_size < 6) { + av_log(avctx, AV_LOG_ERROR, "slice data too small\n"); + return AVERROR_INVALIDDATA; + } + + /* parse slice header */ + hdr_size = buf[0] >> 3; + y_data_size = AV_RB16(buf + 2); + u_data_size = AV_RB16(buf + 4); + v_data_size = hdr_size > 7 ? AV_RB16(buf + 6) : + slice_data_size - y_data_size - u_data_size - hdr_size; + + if (hdr_size + y_data_size + u_data_size + v_data_size > slice_data_size || + v_data_size < 0 || hdr_size < 6) { + av_log(avctx, AV_LOG_ERROR, "invalid data size\n"); + return AVERROR_INVALIDDATA; + } + + sf = av_clip(buf[1], 1, 224); + sf = sf > 128 ? (sf - 96) << 2 : sf; + + /* scale quantization matrixes according with slice's scale factor */ + /* TODO: this can be SIMD-optimized a lot */ + if (ctx->qmat_changed || sf != td->prev_slice_sf) { + td->prev_slice_sf = sf; + for (i = 0; i < 64; i++) { + td->qmat_luma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_luma[i] * sf; + td->qmat_chroma_scaled[ctx->dsp.idct_permutation[i]] = ctx->qmat_chroma[i] * sf; + } + } + + /* decode luma plane */ + decode_slice_plane(ctx, td, buf + hdr_size, y_data_size, + (uint16_t*) (y_data + (mb_y_pos << 4) * y_linesize + + (mb_x_pos << 5)), y_linesize, + mbs_per_slice, 4, slice_width_factor + 2, + td->qmat_luma_scaled, 0); + + /* decode U chroma plane */ + decode_slice_plane(ctx, td, buf + hdr_size + y_data_size, u_data_size, + (uint16_t*) (u_data + (mb_y_pos << 4) * u_linesize + + (mb_x_pos << ctx->mb_chroma_factor)), + u_linesize, mbs_per_slice, ctx->num_chroma_blocks, + slice_width_factor + ctx->chroma_factor - 1, + td->qmat_chroma_scaled, 1); + + /* decode V chroma plane */ + decode_slice_plane(ctx, td, buf + hdr_size + y_data_size + u_data_size, + v_data_size, + (uint16_t*) (v_data + (mb_y_pos << 4) * v_linesize + + (mb_x_pos << ctx->mb_chroma_factor)), + v_linesize, mbs_per_slice, ctx->num_chroma_blocks, + slice_width_factor + ctx->chroma_factor - 1, + td->qmat_chroma_scaled, 1); + + return 0; +} + + +static int decode_picture(ProresContext *ctx, int pic_num, + AVCodecContext *avctx) +{ + int slice_num, slice_width, x_pos, y_pos; + + slice_num = 0; + + ctx->pic_num = pic_num; + for (y_pos = 0; y_pos < ctx->num_y_mbs; y_pos++) { + slice_width = 1 << ctx->slice_width_factor; + + for (x_pos = 0; x_pos < ctx->num_x_mbs && slice_width; + x_pos += slice_width) { + while (ctx->num_x_mbs - x_pos < slice_width) + slice_width >>= 1; + + ctx->slice_data[slice_num].slice_num = slice_num; + ctx->slice_data[slice_num].x_pos = x_pos; + ctx->slice_data[slice_num].y_pos = y_pos; + ctx->slice_data[slice_num].slice_width = slice_width; + + slice_num++; + } + } + + return avctx->execute(avctx, decode_slice, + ctx->slice_data, NULL, slice_num, + sizeof(ctx->slice_data[0])); +} + + +#define MOVE_DATA_PTR(nbytes) buf += (nbytes); buf_size -= (nbytes) + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + ProresContext *ctx = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int frame_hdr_size, pic_num, pic_data_size; + + ctx->frame = data; + ctx->frame->pict_type = AV_PICTURE_TYPE_I; + ctx->frame->key_frame = 1; + + /* check frame atom container */ + if (buf_size < 28 || buf_size < AV_RB32(buf) || + AV_RB32(buf + 4) != FRAME_ID) { + av_log(avctx, AV_LOG_ERROR, "invalid frame\n"); + return AVERROR_INVALIDDATA; + } + + MOVE_DATA_PTR(8); + + frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx); + if (frame_hdr_size < 0) + return AVERROR_INVALIDDATA; + + MOVE_DATA_PTR(frame_hdr_size); + + if (ff_get_buffer(avctx, ctx->frame, 0) < 0) + return -1; + + for (pic_num = 0; ctx->frame->interlaced_frame - pic_num + 1; pic_num++) { + pic_data_size = decode_picture_header(ctx, buf, buf_size, avctx); + if (pic_data_size < 0) + return AVERROR_INVALIDDATA; + + if (decode_picture(ctx, pic_num, avctx)) + return -1; + + MOVE_DATA_PTR(pic_data_size); + } + + ctx->frame = NULL; + *got_frame = 1; + + return avpkt->size; +} + + +static av_cold int decode_close(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + + av_freep(&ctx->slice_data); + + return 0; +} + + +AVCodec ff_prores_lgpl_decoder = { + .name = "prores_lgpl", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .priv_data_size = sizeof(ProresContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)") +}; diff --git a/ffmpeg/libavcodec/proresdsp.c b/ffmpeg/libavcodec/proresdsp.c new file mode 100644 index 0000000..d73de46 --- /dev/null +++ b/ffmpeg/libavcodec/proresdsp.c @@ -0,0 +1,91 @@ +/* + * Apple ProRes compatible decoder + * + * Copyright (c) 2010-2011 Maxim Poliakovski + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dct.h" +#include "dsputil.h" +#include "proresdsp.h" +#include "simple_idct.h" +#include "libavutil/common.h" + +#define BIAS (1 << (PRORES_BITS_PER_SAMPLE - 1)) ///< bias value for converting signed pixels into unsigned ones +#define CLIP_MIN (1 << (PRORES_BITS_PER_SAMPLE - 8)) ///< minimum value for clipping resulting pixels +#define CLIP_MAX (1 << PRORES_BITS_PER_SAMPLE) - CLIP_MIN - 1 ///< maximum value for clipping resulting pixels + +#define CLIP_AND_BIAS(x) (av_clip((x) + BIAS, CLIP_MIN, CLIP_MAX)) + +#if CONFIG_PRORES_DECODER | CONFIG_PRORES_LGPL_DECODER +/** + * Add bias value, clamp and output pixels of a slice + */ +static void put_pixels(uint16_t *dst, int stride, const int16_t *in) +{ + int x, y, src_offset, dst_offset; + + for (y = 0, dst_offset = 0; y < 8; y++, dst_offset += stride) { + for (x = 0; x < 8; x++) { + src_offset = (y << 3) + x; + + dst[dst_offset + x] = CLIP_AND_BIAS(in[src_offset]); + } + } +} + +static void prores_idct_put_c(uint16_t *out, int linesize, int16_t *block, const int16_t *qmat) +{ + ff_prores_idct(block, qmat); + put_pixels(out, linesize >> 1, block); +} +#endif + +#if CONFIG_PRORES_KOSTYA_ENCODER +static void prores_fdct_c(const uint16_t *src, int linesize, int16_t *block) +{ + int x, y; + const uint16_t *tsrc = src; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + block[y * 8 + x] = tsrc[x]; + tsrc += linesize >> 1; + } + ff_jpeg_fdct_islow_10(block); +} +#endif + +void ff_proresdsp_init(ProresDSPContext *dsp, AVCodecContext *avctx) +{ +#if CONFIG_PRORES_DECODER | CONFIG_PRORES_LGPL_DECODER + dsp->idct_put = prores_idct_put_c; + dsp->idct_permutation_type = FF_NO_IDCT_PERM; + + if (ARCH_X86) ff_proresdsp_x86_init(dsp, avctx); + + ff_init_scantable_permutation(dsp->idct_permutation, + dsp->idct_permutation_type); +#endif +#if CONFIG_PRORES_KOSTYA_ENCODER + dsp->fdct = prores_fdct_c; + dsp->dct_permutation_type = FF_NO_IDCT_PERM; + ff_init_scantable_permutation(dsp->dct_permutation, + dsp->dct_permutation_type); +#endif +} diff --git a/ffmpeg/libavcodec/proresdsp.h b/ffmpeg/libavcodec/proresdsp.h new file mode 100644 index 0000000..706162a --- /dev/null +++ b/ffmpeg/libavcodec/proresdsp.h @@ -0,0 +1,44 @@ +/* + * Apple ProRes compatible decoder + * + * Copyright (c) 2010-2011 Maxim Poliakovski + * + * 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 + */ + +#ifndef AVCODEC_PRORESDSP_H +#define AVCODEC_PRORESDSP_H + +#include +#include "dsputil.h" + +#define PRORES_BITS_PER_SAMPLE 10 ///< output precision of prores decoder + +typedef struct ProresDSPContext { + int idct_permutation_type; + uint8_t idct_permutation[64]; + int dct_permutation_type; + uint8_t dct_permutation[64]; + void (* idct_put) (uint16_t *out, int linesize, int16_t *block, const int16_t *qmat); + void (* fdct) (const uint16_t *src, int linesize, int16_t *block); +} ProresDSPContext; + +void ff_proresdsp_init(ProresDSPContext *dsp, AVCodecContext *avctx); + +void ff_proresdsp_x86_init(ProresDSPContext *dsp, AVCodecContext *avctx); + +#endif /* AVCODEC_PRORESDSP_H */ diff --git a/ffmpeg/libavcodec/proresenc_anatoliy.c b/ffmpeg/libavcodec/proresenc_anatoliy.c new file mode 100644 index 0000000..7bf71a3 --- /dev/null +++ b/ffmpeg/libavcodec/proresenc_anatoliy.c @@ -0,0 +1,626 @@ +/* + * Apple ProRes encoder + * + * Copyright (c) 2011 Anatoliy Wasserman + * + * 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 + */ + +/** + * @file + * Apple ProRes encoder (Anatoliy Wasserman version) + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy) + */ + +#include "avcodec.h" +#include "dct.h" +#include "internal.h" +#include "put_bits.h" +#include "bytestream.h" +#include "dsputil.h" + +#define DEFAULT_SLICE_MB_WIDTH 8 + +#define FF_PROFILE_PRORES_PROXY 0 +#define FF_PROFILE_PRORES_LT 1 +#define FF_PROFILE_PRORES_STANDARD 2 +#define FF_PROFILE_PRORES_HQ 3 + +static const AVProfile profiles[] = { + { FF_PROFILE_PRORES_PROXY, "apco"}, + { FF_PROFILE_PRORES_LT, "apcs"}, + { FF_PROFILE_PRORES_STANDARD, "apcn"}, + { FF_PROFILE_PRORES_HQ, "apch"}, + { FF_PROFILE_UNKNOWN } +}; + +static const int qp_start_table[4] = { 4, 1, 1, 1 }; +static const int qp_end_table[4] = { 8, 9, 6, 6 }; +static const int bitrate_table[5] = { 1000, 2100, 3500, 5400 }; + +static const uint8_t progressive_scan[64] = { + 0, 1, 8, 9, 2, 3, 10, 11, + 16, 17, 24, 25, 18, 19, 26, 27, + 4, 5, 12, 20, 13, 6, 7, 14, + 21, 28, 29, 22, 15, 23, 30, 31, + 32, 33, 40, 48, 41, 34, 35, 42, + 49, 56, 57, 50, 43, 36, 37, 44, + 51, 58, 59, 52, 45, 38, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static const uint8_t QMAT_LUMA[4][64] = { + { + 4, 7, 9, 11, 13, 14, 15, 63, + 7, 7, 11, 12, 14, 15, 63, 63, + 9, 11, 13, 14, 15, 63, 63, 63, + 11, 11, 13, 14, 63, 63, 63, 63, + 11, 13, 14, 63, 63, 63, 63, 63, + 13, 14, 63, 63, 63, 63, 63, 63, + 13, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 + }, { + 4, 5, 6, 7, 9, 11, 13, 15, + 5, 5, 7, 8, 11, 13, 15, 17, + 6, 7, 9, 11, 13, 15, 15, 17, + 7, 7, 9, 11, 13, 15, 17, 19, + 7, 9, 11, 13, 14, 16, 19, 23, + 9, 11, 13, 14, 16, 19, 23, 29, + 9, 11, 13, 15, 17, 21, 28, 35, + 11, 13, 16, 17, 21, 28, 35, 41 + }, { + 4, 4, 5, 5, 6, 7, 7, 9, + 4, 4, 5, 6, 7, 7, 9, 9, + 5, 5, 6, 7, 7, 9, 9, 10, + 5, 5, 6, 7, 7, 9, 9, 10, + 5, 6, 7, 7, 8, 9, 10, 12, + 6, 7, 7, 8, 9, 10, 12, 15, + 6, 7, 7, 9, 10, 11, 14, 17, + 7, 7, 9, 10, 11, 14, 17, 21 + }, { + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 5, + 4, 4, 4, 4, 4, 4, 5, 5, + 4, 4, 4, 4, 4, 5, 5, 6, + 4, 4, 4, 4, 5, 5, 6, 7, + 4, 4, 4, 4, 5, 6, 7, 7 + } +}; + +static const uint8_t QMAT_CHROMA[4][64] = { + { + 4, 7, 9, 11, 13, 14, 63, 63, + 7, 7, 11, 12, 14, 63, 63, 63, + 9, 11, 13, 14, 63, 63, 63, 63, + 11, 11, 13, 14, 63, 63, 63, 63, + 11, 13, 14, 63, 63, 63, 63, 63, + 13, 14, 63, 63, 63, 63, 63, 63, + 13, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 + }, { + 4, 5, 6, 7, 9, 11, 13, 15, + 5, 5, 7, 8, 11, 13, 15, 17, + 6, 7, 9, 11, 13, 15, 15, 17, + 7, 7, 9, 11, 13, 15, 17, 19, + 7, 9, 11, 13, 14, 16, 19, 23, + 9, 11, 13, 14, 16, 19, 23, 29, + 9, 11, 13, 15, 17, 21, 28, 35, + 11, 13, 16, 17, 21, 28, 35, 41 + }, { + 4, 4, 5, 5, 6, 7, 7, 9, + 4, 4, 5, 6, 7, 7, 9, 9, + 5, 5, 6, 7, 7, 9, 9, 10, + 5, 5, 6, 7, 7, 9, 9, 10, + 5, 6, 7, 7, 8, 9, 10, 12, + 6, 7, 7, 8, 9, 10, 12, 15, + 6, 7, 7, 9, 10, 11, 14, 17, + 7, 7, 9, 10, 11, 14, 17, 21 + }, { + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 5, + 4, 4, 4, 4, 4, 4, 5, 5, + 4, 4, 4, 4, 4, 5, 5, 6, + 4, 4, 4, 4, 5, 5, 6, 7, + 4, 4, 4, 4, 5, 6, 7, 7 + } +}; + + +typedef struct { + uint8_t* fill_y; + uint8_t* fill_u; + uint8_t* fill_v; + + int qmat_luma[16][64]; + int qmat_chroma[16][64]; +} ProresContext; + +static void encode_codeword(PutBitContext *pb, int val, int codebook) +{ + unsigned int rice_order, exp_order, switch_bits, first_exp, exp, zeros, + mask; + + /* number of bits to switch between rice and exp golomb */ + switch_bits = codebook & 3; + rice_order = codebook >> 5; + exp_order = (codebook >> 2) & 7; + + first_exp = ((switch_bits + 1) << rice_order); + + if (val >= first_exp) { /* exp golomb */ + val -= first_exp; + val += (1 << exp_order); + exp = av_log2(val); + zeros = exp - exp_order + switch_bits + 1; + put_bits(pb, zeros, 0); + put_bits(pb, exp + 1, val); + } else if (rice_order) { + mask = (1 << rice_order) - 1; + put_bits(pb, (val >> rice_order), 0); + put_bits(pb, 1, 1); + put_bits(pb, rice_order, val & mask); + } else { + put_bits(pb, val, 0); + put_bits(pb, 1, 1); + } +} + +#define QSCALE(qmat,ind,val) ((val) / (qmat[ind])) +#define TO_GOLOMB(val) ((val << 1) ^ (val >> 31)) +#define DIFF_SIGN(val, sign) ((val >> 31) ^ sign) +#define IS_NEGATIVE(val) (((val >> 31) ^ -1) + 1) +#define TO_GOLOMB2(val,sign) (val==0 ? 0 : (val << 1) + sign) + +static av_always_inline int get_level(int val) +{ + int sign = (val >> 31); + return (val ^ sign) - sign; +} + +#define FIRST_DC_CB 0xB8 + +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70}; + +static void encode_dc_coeffs(PutBitContext *pb, int16_t *in, + int blocks_per_slice, int *qmat) +{ + int prev_dc, code; + int i, sign, idx; + int new_dc, delta, diff_sign, new_code; + + prev_dc = QSCALE(qmat, 0, in[0] - 16384); + code = TO_GOLOMB(prev_dc); + encode_codeword(pb, code, FIRST_DC_CB); + + code = 5; sign = 0; idx = 64; + for (i = 1; i < blocks_per_slice; i++, idx += 64) { + new_dc = QSCALE(qmat, 0, in[idx] - 16384); + delta = new_dc - prev_dc; + diff_sign = DIFF_SIGN(delta, sign); + new_code = TO_GOLOMB2(get_level(delta), diff_sign); + + encode_codeword(pb, new_code, dc_codebook[FFMIN(code, 6)]); + + code = new_code; + sign = delta >> 31; + prev_dc = new_dc; + } +} + +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, + 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C }; +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, + 0x28, 0x28, 0x28, 0x4C }; + +static void encode_ac_coeffs(AVCodecContext *avctx, PutBitContext *pb, + int16_t *in, int blocks_per_slice, int *qmat) +{ + int prev_run = 4; + int prev_level = 2; + + int run = 0, level, code, i, j; + for (i = 1; i < 64; i++) { + int indp = progressive_scan[i]; + for (j = 0; j < blocks_per_slice; j++) { + int val = QSCALE(qmat, indp, in[(j << 6) + indp]); + if (val) { + encode_codeword(pb, run, run_to_cb[FFMIN(prev_run, 15)]); + + prev_run = run; + run = 0; + level = get_level(val); + code = level - 1; + + encode_codeword(pb, code, lev_to_cb[FFMIN(prev_level, 9)]); + + prev_level = level; + + put_bits(pb, 1, IS_NEGATIVE(val)); + } else { + ++run; + } + } + } +} + +static void get(uint8_t *pixels, int stride, int16_t* block) +{ + int16_t *p = (int16_t*)pixels; + int i, j; + + stride >>= 1; + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + block[j] = p[j]; + } + p += stride; + block += 8; + } +} + +static void fdct_get(uint8_t *pixels, int stride, int16_t* block) +{ + get(pixels, stride, block); + ff_jpeg_fdct_islow_10(block); +} + +static int encode_slice_plane(AVCodecContext *avctx, int mb_count, + uint8_t *src, int src_stride, uint8_t *buf, unsigned buf_size, + int *qmat, int chroma) +{ + DECLARE_ALIGNED(16, int16_t, blocks)[DEFAULT_SLICE_MB_WIDTH << 8], *block; + int i, blocks_per_slice; + PutBitContext pb; + + block = blocks; + for (i = 0; i < mb_count; i++) { + fdct_get(src, src_stride, block + (0 << 6)); + fdct_get(src + 8 * src_stride, src_stride, block + ((2 - chroma) << 6)); + if (!chroma) { + fdct_get(src + 16, src_stride, block + (1 << 6)); + fdct_get(src + 16 + 8 * src_stride, src_stride, block + (3 << 6)); + } + + block += (256 >> chroma); + src += (32 >> chroma); + } + + blocks_per_slice = mb_count << (2 - chroma); + init_put_bits(&pb, buf, buf_size << 3); + + encode_dc_coeffs(&pb, blocks, blocks_per_slice, qmat); + encode_ac_coeffs(avctx, &pb, blocks, blocks_per_slice, qmat); + + flush_put_bits(&pb); + return put_bits_ptr(&pb) - pb.buf; +} + +static av_always_inline unsigned encode_slice_data(AVCodecContext *avctx, + uint8_t *dest_y, uint8_t *dest_u, uint8_t *dest_v, int luma_stride, + int chroma_stride, unsigned mb_count, uint8_t *buf, unsigned data_size, + unsigned* y_data_size, unsigned* u_data_size, unsigned* v_data_size, + int qp) +{ + ProresContext* ctx = avctx->priv_data; + + *y_data_size = encode_slice_plane(avctx, mb_count, dest_y, luma_stride, + buf, data_size, ctx->qmat_luma[qp - 1], 0); + + if (!(avctx->flags & CODEC_FLAG_GRAY)) { + *u_data_size = encode_slice_plane(avctx, mb_count, dest_u, + chroma_stride, buf + *y_data_size, data_size - *y_data_size, + ctx->qmat_chroma[qp - 1], 1); + + *v_data_size = encode_slice_plane(avctx, mb_count, dest_v, + chroma_stride, buf + *y_data_size + *u_data_size, + data_size - *y_data_size - *u_data_size, + ctx->qmat_chroma[qp - 1], 1); + } + + return *y_data_size + *u_data_size + *v_data_size; +} + +static void subimage_with_fill(uint16_t *src, unsigned x, unsigned y, + unsigned stride, unsigned width, unsigned height, uint16_t *dst, + unsigned dst_width, unsigned dst_height) +{ + + int box_width = FFMIN(width - x, dst_width); + int box_height = FFMIN(height - y, dst_height); + int i, j, src_stride = stride >> 1; + uint16_t last_pix, *last_line; + + src += y * src_stride + x; + for (i = 0; i < box_height; ++i) { + for (j = 0; j < box_width; ++j) { + dst[j] = src[j]; + } + last_pix = dst[j - 1]; + for (; j < dst_width; j++) + dst[j] = last_pix; + src += src_stride; + dst += dst_width; + } + last_line = dst - dst_width; + for (; i < dst_height; i++) { + for (j = 0; j < dst_width; ++j) { + dst[j] = last_line[j]; + } + dst += dst_width; + } +} + +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x, + int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size, + int unsafe, int *qp) +{ + int luma_stride, chroma_stride; + int hdr_size = 6, slice_size; + uint8_t *dest_y, *dest_u, *dest_v; + unsigned y_data_size = 0, u_data_size = 0, v_data_size = 0; + ProresContext* ctx = avctx->priv_data; + int tgt_bits = (mb_count * bitrate_table[avctx->profile]) >> 2; + int low_bytes = (tgt_bits - (tgt_bits >> 3)) >> 3; // 12% bitrate fluctuation + int high_bytes = (tgt_bits + (tgt_bits >> 3)) >> 3; + + luma_stride = pic->linesize[0]; + chroma_stride = pic->linesize[1]; + + dest_y = pic->data[0] + (mb_y << 4) * luma_stride + (mb_x << 5); + dest_u = pic->data[1] + (mb_y << 4) * chroma_stride + (mb_x << 4); + dest_v = pic->data[2] + (mb_y << 4) * chroma_stride + (mb_x << 4); + + if (unsafe) { + + subimage_with_fill((uint16_t *) pic->data[0], mb_x << 4, mb_y << 4, + luma_stride, avctx->width, avctx->height, + (uint16_t *) ctx->fill_y, mb_count << 4, 16); + subimage_with_fill((uint16_t *) pic->data[1], mb_x << 3, mb_y << 4, + chroma_stride, avctx->width >> 1, avctx->height, + (uint16_t *) ctx->fill_u, mb_count << 3, 16); + subimage_with_fill((uint16_t *) pic->data[2], mb_x << 3, mb_y << 4, + chroma_stride, avctx->width >> 1, avctx->height, + (uint16_t *) ctx->fill_v, mb_count << 3, 16); + + encode_slice_data(avctx, ctx->fill_y, ctx->fill_u, ctx->fill_v, + mb_count << 5, mb_count << 4, mb_count, buf + hdr_size, + data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size, + *qp); + } else { + slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v, + luma_stride, chroma_stride, mb_count, buf + hdr_size, + data_size - hdr_size, &y_data_size, &u_data_size, &v_data_size, + *qp); + + if (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]) { + do { + *qp += 1; + slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v, + luma_stride, chroma_stride, mb_count, buf + hdr_size, + data_size - hdr_size, &y_data_size, &u_data_size, + &v_data_size, *qp); + } while (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]); + } else if (slice_size < low_bytes && *qp + > qp_start_table[avctx->profile]) { + do { + *qp -= 1; + slice_size = encode_slice_data(avctx, dest_y, dest_u, dest_v, + luma_stride, chroma_stride, mb_count, buf + hdr_size, + data_size - hdr_size, &y_data_size, &u_data_size, + &v_data_size, *qp); + } while (slice_size < low_bytes && *qp > qp_start_table[avctx->profile]); + } + } + + buf[0] = hdr_size << 3; + buf[1] = *qp; + AV_WB16(buf + 2, y_data_size); + AV_WB16(buf + 4, u_data_size); + + return hdr_size + y_data_size + u_data_size + v_data_size; +} + +static int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic, + uint8_t *buf, const int buf_size) +{ + int mb_width = (avctx->width + 15) >> 4; + int mb_height = (avctx->height + 15) >> 4; + int hdr_size, sl_size, i; + int mb_y, sl_data_size, qp; + int unsafe_bot, unsafe_right; + uint8_t *sl_data, *sl_data_sizes; + int slice_per_line = 0, rem = mb_width; + + for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) { + slice_per_line += rem >> i; + rem &= (1 << i) - 1; + } + + qp = qp_start_table[avctx->profile]; + hdr_size = 8; sl_data_size = buf_size - hdr_size; + sl_data_sizes = buf + hdr_size; + sl_data = sl_data_sizes + (slice_per_line * mb_height * 2); + for (mb_y = 0; mb_y < mb_height; mb_y++) { + int mb_x = 0; + int slice_mb_count = DEFAULT_SLICE_MB_WIDTH; + while (mb_x < mb_width) { + while (mb_width - mb_x < slice_mb_count) + slice_mb_count >>= 1; + + unsafe_bot = (avctx->height & 0xf) && (mb_y == mb_height - 1); + unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == mb_width); + + sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count, + sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp); + + bytestream_put_be16(&sl_data_sizes, sl_size); + sl_data += sl_size; + sl_data_size -= sl_size; + mb_x += slice_mb_count; + } + } + + buf[0] = hdr_size << 3; + AV_WB32(buf + 1, sl_data - buf); + AV_WB16(buf + 5, slice_per_line * mb_height); + buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4; + + return sl_data - buf; +} + +static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + int header_size = 148; + uint8_t *buf; + int pic_size, ret; + int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + FF_MIN_BUFFER_SIZE; //FIXME choose tighter limit + + + if ((ret = ff_alloc_packet2(avctx, pkt, frame_size + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + buf = pkt->data; + pic_size = prores_encode_picture(avctx, pict, buf + header_size + 8, + pkt->size - header_size - 8); + + bytestream_put_be32(&buf, pic_size + 8 + header_size); + bytestream_put_buffer(&buf, "icpf", 4); + + bytestream_put_be16(&buf, header_size); + bytestream_put_be16(&buf, 0); + bytestream_put_buffer(&buf, "fmpg", 4); + bytestream_put_be16(&buf, avctx->width); + bytestream_put_be16(&buf, avctx->height); + *buf++ = 0x83; // {10}(422){00}{00}(frame){11} + *buf++ = 0; + *buf++ = 2; + *buf++ = 2; + *buf++ = 6; + *buf++ = 32; + *buf++ = 0; + *buf++ = 3; + + bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile], 64); + bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64); + + pkt->flags |= AV_PKT_FLAG_KEY; + pkt->size = pic_size + 8 + header_size; + *got_packet = 1; + + return 0; +} + +static void scale_mat(const uint8_t* src, int* dst, int scale) +{ + int i; + for (i = 0; i < 64; i++) + dst[i] = src[i] * scale; +} + +static av_cold int prores_encode_init(AVCodecContext *avctx) +{ + int i; + ProresContext* ctx = avctx->priv_data; + + if (avctx->pix_fmt != AV_PIX_FMT_YUV422P10) { + av_log(avctx, AV_LOG_ERROR, "need YUV422P10\n"); + return -1; + } + if (avctx->width & 0x1) { + av_log(avctx, AV_LOG_ERROR, + "frame width needs to be multiple of 2\n"); + return -1; + } + + if ((avctx->height & 0xf) || (avctx->width & 0xf)) { + ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8)); + if (!ctx->fill_y) + return AVERROR(ENOMEM); + ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9); + ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8); + } + + if (avctx->profile == FF_PROFILE_UNKNOWN) { + avctx->profile = FF_PROFILE_PRORES_STANDARD; + av_log(avctx, AV_LOG_INFO, + "encoding with ProRes standard (apcn) profile\n"); + + } else if (avctx->profile < FF_PROFILE_PRORES_PROXY + || avctx->profile > FF_PROFILE_PRORES_HQ) { + av_log( + avctx, + AV_LOG_ERROR, + "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch]\n", + avctx->profile); + return -1; + } + + avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name); + + for (i = 1; i <= 16; i++) { + scale_mat(QMAT_LUMA[avctx->profile] , ctx->qmat_luma[i - 1] , i); + scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i); + } + + avctx->coded_frame = avcodec_alloc_frame(); + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + return 0; +} + +static av_cold int prores_encode_close(AVCodecContext *avctx) +{ + ProresContext* ctx = avctx->priv_data; + av_freep(&avctx->coded_frame); + av_freep(&ctx->fill_y); + + return 0; +} + +AVCodec ff_prores_anatoliy_encoder = { + .name = "prores_anatoliy", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .priv_data_size = sizeof(ProresContext), + .init = prores_encode_init, + .close = prores_encode_close, + .encode2 = prores_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, + .profiles = profiles +}; + +AVCodec ff_prores_encoder = { + .name = "prores", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .priv_data_size = sizeof(ProresContext), + .init = prores_encode_init, + .close = prores_encode_close, + .encode2 = prores_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE}, + .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), + .capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY, + .profiles = profiles +}; diff --git a/ffmpeg/libavcodec/proresenc_kostya.c b/ffmpeg/libavcodec/proresenc_kostya.c new file mode 100644 index 0000000..8da13ac --- /dev/null +++ b/ffmpeg/libavcodec/proresenc_kostya.c @@ -0,0 +1,1077 @@ +/* + * Apple ProRes encoder + * + * Copyright (c) 2012 Konstantin Shishkov + * + * This encoder appears to be based on Anatoliy Wassermans considering + * similarities in the bugs. + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dsputil.h" +#include "put_bits.h" +#include "bytestream.h" +#include "internal.h" +#include "proresdsp.h" +#include "proresdata.h" + +#define CFACTOR_Y422 2 +#define CFACTOR_Y444 3 + +#define MAX_MBS_PER_SLICE 8 + +#define MAX_PLANES 3 // should be increased to 4 when there's AV_PIX_FMT_YUV444AP10 + +enum { + PRORES_PROFILE_PROXY = 0, + PRORES_PROFILE_LT, + PRORES_PROFILE_STANDARD, + PRORES_PROFILE_HQ, +}; + +enum { + QUANT_MAT_PROXY = 0, + QUANT_MAT_LT, + QUANT_MAT_STANDARD, + QUANT_MAT_HQ, + QUANT_MAT_DEFAULT, +}; + +static const uint8_t prores_quant_matrices[][64] = { + { // proxy + 4, 7, 9, 11, 13, 14, 15, 63, + 7, 7, 11, 12, 14, 15, 63, 63, + 9, 11, 13, 14, 15, 63, 63, 63, + 11, 11, 13, 14, 63, 63, 63, 63, + 11, 13, 14, 63, 63, 63, 63, 63, + 13, 14, 63, 63, 63, 63, 63, 63, + 13, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, + }, + { // LT + 4, 5, 6, 7, 9, 11, 13, 15, + 5, 5, 7, 8, 11, 13, 15, 17, + 6, 7, 9, 11, 13, 15, 15, 17, + 7, 7, 9, 11, 13, 15, 17, 19, + 7, 9, 11, 13, 14, 16, 19, 23, + 9, 11, 13, 14, 16, 19, 23, 29, + 9, 11, 13, 15, 17, 21, 28, 35, + 11, 13, 16, 17, 21, 28, 35, 41, + }, + { // standard + 4, 4, 5, 5, 6, 7, 7, 9, + 4, 4, 5, 6, 7, 7, 9, 9, + 5, 5, 6, 7, 7, 9, 9, 10, + 5, 5, 6, 7, 7, 9, 9, 10, + 5, 6, 7, 7, 8, 9, 10, 12, + 6, 7, 7, 8, 9, 10, 12, 15, + 6, 7, 7, 9, 10, 11, 14, 17, + 7, 7, 9, 10, 11, 14, 17, 21, + }, + { // high quality + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 5, + 4, 4, 4, 4, 4, 4, 5, 5, + 4, 4, 4, 4, 4, 5, 5, 6, + 4, 4, 4, 4, 5, 5, 6, 7, + 4, 4, 4, 4, 5, 6, 7, 7, + }, + { // codec default + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + }, +}; + +#define NUM_MB_LIMITS 4 +static const int prores_mb_limits[NUM_MB_LIMITS] = { + 1620, // up to 720x576 + 2700, // up to 960x720 + 6075, // up to 1440x1080 + 9216, // up to 2048x1152 +}; + +static const struct prores_profile { + const char *full_name; + uint32_t tag; + int min_quant; + int max_quant; + int br_tab[NUM_MB_LIMITS]; + int quant; +} prores_profile_info[4] = { + { + .full_name = "proxy", + .tag = MKTAG('a', 'p', 'c', 'o'), + .min_quant = 4, + .max_quant = 8, + .br_tab = { 300, 242, 220, 194 }, + .quant = QUANT_MAT_PROXY, + }, + { + .full_name = "LT", + .tag = MKTAG('a', 'p', 'c', 's'), + .min_quant = 1, + .max_quant = 9, + .br_tab = { 720, 560, 490, 440 }, + .quant = QUANT_MAT_LT, + }, + { + .full_name = "standard", + .tag = MKTAG('a', 'p', 'c', 'n'), + .min_quant = 1, + .max_quant = 6, + .br_tab = { 1050, 808, 710, 632 }, + .quant = QUANT_MAT_STANDARD, + }, + { + .full_name = "high quality", + .tag = MKTAG('a', 'p', 'c', 'h'), + .min_quant = 1, + .max_quant = 6, + .br_tab = { 1566, 1216, 1070, 950 }, + .quant = QUANT_MAT_HQ, + } +// for 4444 profile bitrate numbers are { 2350, 1828, 1600, 1425 } +}; + +#define TRELLIS_WIDTH 16 +#define SCORE_LIMIT INT_MAX / 2 + +struct TrellisNode { + int prev_node; + int quant; + int bits; + int score; +}; + +#define MAX_STORED_Q 16 + +typedef struct ProresThreadData { + DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; + DECLARE_ALIGNED(16, uint16_t, emu_buf)[16 * 16]; + int16_t custom_q[64]; + struct TrellisNode *nodes; +} ProresThreadData; + +typedef struct ProresContext { + AVClass *class; + DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; + DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16]; + int16_t quants[MAX_STORED_Q][64]; + int16_t custom_q[64]; + const uint8_t *quant_mat; + + ProresDSPContext dsp; + ScanTable scantable; + + int mb_width, mb_height; + int mbs_per_slice; + int num_chroma_blocks, chroma_factor; + int slices_width; + int slices_per_picture; + int pictures_per_frame; // 1 for progressive, 2 for interlaced + int cur_picture_idx; + int num_planes; + int bits_per_mb; + int force_quant; + + char *vendor; + int quant_sel; + + int frame_size_upper_bound; + + int profile; + const struct prores_profile *profile_info; + + int *slice_q; + + ProresThreadData *tdata; +} ProresContext; + +static void get_slice_data(ProresContext *ctx, const uint16_t *src, + int linesize, int x, int y, int w, int h, + int16_t *blocks, uint16_t *emu_buf, + int mbs_per_slice, int blocks_per_mb, int is_chroma) +{ + const uint16_t *esrc; + const int mb_width = 4 * blocks_per_mb; + int elinesize; + int i, j, k; + + for (i = 0; i < mbs_per_slice; i++, src += mb_width) { + if (x >= w) { + memset(blocks, 0, 64 * (mbs_per_slice - i) * blocks_per_mb + * sizeof(*blocks)); + return; + } + if (x + mb_width <= w && y + 16 <= h) { + esrc = src; + elinesize = linesize; + } else { + int bw, bh, pix; + + esrc = emu_buf; + elinesize = 16 * sizeof(*emu_buf); + + bw = FFMIN(w - x, mb_width); + bh = FFMIN(h - y, 16); + + for (j = 0; j < bh; j++) { + memcpy(emu_buf + j * 16, + (const uint8_t*)src + j * linesize, + bw * sizeof(*src)); + pix = emu_buf[j * 16 + bw - 1]; + for (k = bw; k < mb_width; k++) + emu_buf[j * 16 + k] = pix; + } + for (; j < 16; j++) + memcpy(emu_buf + j * 16, + emu_buf + (bh - 1) * 16, + mb_width * sizeof(*emu_buf)); + } + if (!is_chroma) { + ctx->dsp.fdct(esrc, elinesize, blocks); + blocks += 64; + if (blocks_per_mb > 2) { + ctx->dsp.fdct(esrc + 8, elinesize, blocks); + blocks += 64; + } + ctx->dsp.fdct(esrc + elinesize * 4, elinesize, blocks); + blocks += 64; + if (blocks_per_mb > 2) { + ctx->dsp.fdct(esrc + elinesize * 4 + 8, elinesize, blocks); + blocks += 64; + } + } else { + ctx->dsp.fdct(esrc, elinesize, blocks); + blocks += 64; + ctx->dsp.fdct(esrc + elinesize * 4, elinesize, blocks); + blocks += 64; + if (blocks_per_mb > 2) { + ctx->dsp.fdct(esrc + 8, elinesize, blocks); + blocks += 64; + ctx->dsp.fdct(esrc + elinesize * 4 + 8, elinesize, blocks); + blocks += 64; + } + } + + x += mb_width; + } +} + +/** + * Write an unsigned rice/exp golomb codeword. + */ +static inline void encode_vlc_codeword(PutBitContext *pb, unsigned codebook, int val) +{ + unsigned int rice_order, exp_order, switch_bits, switch_val; + int exponent; + + /* number of prefix bits to switch between Rice and expGolomb */ + switch_bits = (codebook & 3) + 1; + rice_order = codebook >> 5; /* rice code order */ + exp_order = (codebook >> 2) & 7; /* exp golomb code order */ + + switch_val = switch_bits << rice_order; + + if (val >= switch_val) { + val -= switch_val - (1 << exp_order); + exponent = av_log2(val); + + put_bits(pb, exponent - exp_order + switch_bits, 0); + put_bits(pb, exponent + 1, val); + } else { + exponent = val >> rice_order; + + if (exponent) + put_bits(pb, exponent, 0); + put_bits(pb, 1, 1); + if (rice_order) + put_sbits(pb, rice_order, val); + } +} + +#define GET_SIGN(x) ((x) >> 31) +#define MAKE_CODE(x) (((x) << 1) ^ GET_SIGN(x)) + +static void encode_dcs(PutBitContext *pb, int16_t *blocks, + int blocks_per_slice, int scale) +{ + int i; + int codebook = 3, code, dc, prev_dc, delta, sign, new_sign; + + prev_dc = (blocks[0] - 0x4000) / scale; + encode_vlc_codeword(pb, FIRST_DC_CB, MAKE_CODE(prev_dc)); + sign = 0; + codebook = 3; + blocks += 64; + + for (i = 1; i < blocks_per_slice; i++, blocks += 64) { + dc = (blocks[0] - 0x4000) / scale; + delta = dc - prev_dc; + new_sign = GET_SIGN(delta); + delta = (delta ^ sign) - sign; + code = MAKE_CODE(delta); + encode_vlc_codeword(pb, ff_prores_dc_codebook[codebook], code); + codebook = (code + (code & 1)) >> 1; + codebook = FFMIN(codebook, 3); + sign = new_sign; + prev_dc = dc; + } +} + +static void encode_acs(PutBitContext *pb, int16_t *blocks, + int blocks_per_slice, + int plane_size_factor, + const uint8_t *scan, const int16_t *qmat) +{ + int idx, i; + int run, level, run_cb, lev_cb; + int max_coeffs, abs_level; + + max_coeffs = blocks_per_slice << 6; + run_cb = ff_prores_run_to_cb_index[4]; + lev_cb = ff_prores_lev_to_cb_index[2]; + run = 0; + + for (i = 1; i < 64; i++) { + for (idx = scan[i]; idx < max_coeffs; idx += 64) { + level = blocks[idx] / qmat[scan[i]]; + if (level) { + abs_level = FFABS(level); + encode_vlc_codeword(pb, ff_prores_ac_codebook[run_cb], run); + encode_vlc_codeword(pb, ff_prores_ac_codebook[lev_cb], + abs_level - 1); + put_sbits(pb, 1, GET_SIGN(level)); + + run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)]; + lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)]; + run = 0; + } else { + run++; + } + } + } +} + +static int encode_slice_plane(ProresContext *ctx, PutBitContext *pb, + const uint16_t *src, int linesize, + int mbs_per_slice, int16_t *blocks, + int blocks_per_mb, int plane_size_factor, + const int16_t *qmat) +{ + int blocks_per_slice, saved_pos; + + saved_pos = put_bits_count(pb); + blocks_per_slice = mbs_per_slice * blocks_per_mb; + + encode_dcs(pb, blocks, blocks_per_slice, qmat[0]); + encode_acs(pb, blocks, blocks_per_slice, plane_size_factor, + ctx->scantable.permutated, qmat); + flush_put_bits(pb); + + return (put_bits_count(pb) - saved_pos) >> 3; +} + +static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, + PutBitContext *pb, + int sizes[4], int x, int y, int quant, + int mbs_per_slice) +{ + ProresContext *ctx = avctx->priv_data; + int i, xp, yp; + int total_size = 0; + const uint16_t *src; + int slice_width_factor = av_log2(mbs_per_slice); + int num_cblocks, pwidth, linesize, line_add; + int plane_factor, is_chroma; + uint16_t *qmat; + + if (ctx->pictures_per_frame == 1) + line_add = 0; + else + line_add = ctx->cur_picture_idx ^ !pic->top_field_first; + + if (ctx->force_quant) { + qmat = ctx->quants[0]; + } else if (quant < MAX_STORED_Q) { + qmat = ctx->quants[quant]; + } else { + qmat = ctx->custom_q; + for (i = 0; i < 64; i++) + qmat[i] = ctx->quant_mat[i] * quant; + } + + for (i = 0; i < ctx->num_planes; i++) { + is_chroma = (i == 1 || i == 2); + plane_factor = slice_width_factor + 2; + if (is_chroma) + plane_factor += ctx->chroma_factor - 3; + if (!is_chroma || ctx->chroma_factor == CFACTOR_Y444) { + xp = x << 4; + yp = y << 4; + num_cblocks = 4; + pwidth = avctx->width; + } else { + xp = x << 3; + yp = y << 4; + num_cblocks = 2; + pwidth = avctx->width >> 1; + } + + linesize = pic->linesize[i] * ctx->pictures_per_frame; + src = (const uint16_t*)(pic->data[i] + yp * linesize + + line_add * pic->linesize[i]) + xp; + + get_slice_data(ctx, src, linesize, xp, yp, + pwidth, avctx->height / ctx->pictures_per_frame, + ctx->blocks[0], ctx->emu_buf, + mbs_per_slice, num_cblocks, is_chroma); + sizes[i] = encode_slice_plane(ctx, pb, src, linesize, + mbs_per_slice, ctx->blocks[0], + num_cblocks, plane_factor, + qmat); + total_size += sizes[i]; + } + return total_size; +} + +static inline int estimate_vlc(unsigned codebook, int val) +{ + unsigned int rice_order, exp_order, switch_bits, switch_val; + int exponent; + + /* number of prefix bits to switch between Rice and expGolomb */ + switch_bits = (codebook & 3) + 1; + rice_order = codebook >> 5; /* rice code order */ + exp_order = (codebook >> 2) & 7; /* exp golomb code order */ + + switch_val = switch_bits << rice_order; + + if (val >= switch_val) { + val -= switch_val - (1 << exp_order); + exponent = av_log2(val); + + return exponent * 2 - exp_order + switch_bits + 1; + } else { + return (val >> rice_order) + rice_order + 1; + } +} + +static int estimate_dcs(int *error, int16_t *blocks, int blocks_per_slice, + int scale) +{ + int i; + int codebook = 3, code, dc, prev_dc, delta, sign, new_sign; + int bits; + + prev_dc = (blocks[0] - 0x4000) / scale; + bits = estimate_vlc(FIRST_DC_CB, MAKE_CODE(prev_dc)); + sign = 0; + codebook = 3; + blocks += 64; + *error += FFABS(blocks[0] - 0x4000) % scale; + + for (i = 1; i < blocks_per_slice; i++, blocks += 64) { + dc = (blocks[0] - 0x4000) / scale; + *error += FFABS(blocks[0] - 0x4000) % scale; + delta = dc - prev_dc; + new_sign = GET_SIGN(delta); + delta = (delta ^ sign) - sign; + code = MAKE_CODE(delta); + bits += estimate_vlc(ff_prores_dc_codebook[codebook], code); + codebook = (code + (code & 1)) >> 1; + codebook = FFMIN(codebook, 3); + sign = new_sign; + prev_dc = dc; + } + + return bits; +} + +static int estimate_acs(int *error, int16_t *blocks, int blocks_per_slice, + int plane_size_factor, + const uint8_t *scan, const int16_t *qmat) +{ + int idx, i; + int run, level, run_cb, lev_cb; + int max_coeffs, abs_level; + int bits = 0; + + max_coeffs = blocks_per_slice << 6; + run_cb = ff_prores_run_to_cb_index[4]; + lev_cb = ff_prores_lev_to_cb_index[2]; + run = 0; + + for (i = 1; i < 64; i++) { + for (idx = scan[i]; idx < max_coeffs; idx += 64) { + level = blocks[idx] / qmat[scan[i]]; + *error += FFABS(blocks[idx]) % qmat[scan[i]]; + if (level) { + abs_level = FFABS(level); + bits += estimate_vlc(ff_prores_ac_codebook[run_cb], run); + bits += estimate_vlc(ff_prores_ac_codebook[lev_cb], + abs_level - 1) + 1; + + run_cb = ff_prores_run_to_cb_index[FFMIN(run, 15)]; + lev_cb = ff_prores_lev_to_cb_index[FFMIN(abs_level, 9)]; + run = 0; + } else { + run++; + } + } + } + + return bits; +} + +static int estimate_slice_plane(ProresContext *ctx, int *error, int plane, + const uint16_t *src, int linesize, + int mbs_per_slice, + int blocks_per_mb, int plane_size_factor, + const int16_t *qmat, ProresThreadData *td) +{ + int blocks_per_slice; + int bits; + + blocks_per_slice = mbs_per_slice * blocks_per_mb; + + bits = estimate_dcs(error, td->blocks[plane], blocks_per_slice, qmat[0]); + bits += estimate_acs(error, td->blocks[plane], blocks_per_slice, + plane_size_factor, ctx->scantable.permutated, qmat); + + return FFALIGN(bits, 8); +} + +static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, + int trellis_node, int x, int y, int mbs_per_slice, + ProresThreadData *td) +{ + ProresContext *ctx = avctx->priv_data; + int i, q, pq, xp, yp; + const uint16_t *src; + int slice_width_factor = av_log2(mbs_per_slice); + int num_cblocks[MAX_PLANES], pwidth; + int plane_factor[MAX_PLANES], is_chroma[MAX_PLANES]; + const int min_quant = ctx->profile_info->min_quant; + const int max_quant = ctx->profile_info->max_quant; + int error, bits, bits_limit; + int mbs, prev, cur, new_score; + int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH]; + int overquant; + uint16_t *qmat; + int linesize[4], line_add; + + if (ctx->pictures_per_frame == 1) + line_add = 0; + else + line_add = ctx->cur_picture_idx ^ !pic->top_field_first; + mbs = x + mbs_per_slice; + + for (i = 0; i < ctx->num_planes; i++) { + is_chroma[i] = (i == 1 || i == 2); + plane_factor[i] = slice_width_factor + 2; + if (is_chroma[i]) + plane_factor[i] += ctx->chroma_factor - 3; + if (!is_chroma[i] || ctx->chroma_factor == CFACTOR_Y444) { + xp = x << 4; + yp = y << 4; + num_cblocks[i] = 4; + pwidth = avctx->width; + } else { + xp = x << 3; + yp = y << 4; + num_cblocks[i] = 2; + pwidth = avctx->width >> 1; + } + + linesize[i] = pic->linesize[i] * ctx->pictures_per_frame; + src = (const uint16_t*)(pic->data[i] + yp * linesize[i] + + line_add * pic->linesize[i]) + xp; + + get_slice_data(ctx, src, linesize[i], xp, yp, + pwidth, avctx->height / ctx->pictures_per_frame, + td->blocks[i], td->emu_buf, + mbs_per_slice, num_cblocks[i], is_chroma[i]); + } + + for (q = min_quant; q < max_quant + 2; q++) { + td->nodes[trellis_node + q].prev_node = -1; + td->nodes[trellis_node + q].quant = q; + } + + // todo: maybe perform coarser quantising to fit into frame size when needed + for (q = min_quant; q <= max_quant; q++) { + bits = 0; + error = 0; + for (i = 0; i < ctx->num_planes; i++) { + bits += estimate_slice_plane(ctx, &error, i, + src, linesize[i], + mbs_per_slice, + num_cblocks[i], plane_factor[i], + ctx->quants[q], td); + } + if (bits > 65000 * 8) { + error = SCORE_LIMIT; + break; + } + slice_bits[q] = bits; + slice_score[q] = error; + } + if (slice_bits[max_quant] <= ctx->bits_per_mb * mbs_per_slice) { + slice_bits[max_quant + 1] = slice_bits[max_quant]; + slice_score[max_quant + 1] = slice_score[max_quant] + 1; + overquant = max_quant; + } else { + for (q = max_quant + 1; q < 128; q++) { + bits = 0; + error = 0; + if (q < MAX_STORED_Q) { + qmat = ctx->quants[q]; + } else { + qmat = td->custom_q; + for (i = 0; i < 64; i++) + qmat[i] = ctx->quant_mat[i] * q; + } + for (i = 0; i < ctx->num_planes; i++) { + bits += estimate_slice_plane(ctx, &error, i, + src, linesize[i], + mbs_per_slice, + num_cblocks[i], plane_factor[i], + qmat, td); + } + if (bits <= ctx->bits_per_mb * mbs_per_slice) + break; + } + + slice_bits[max_quant + 1] = bits; + slice_score[max_quant + 1] = error; + overquant = q; + } + td->nodes[trellis_node + max_quant + 1].quant = overquant; + + bits_limit = mbs * ctx->bits_per_mb; + for (pq = min_quant; pq < max_quant + 2; pq++) { + prev = trellis_node - TRELLIS_WIDTH + pq; + + for (q = min_quant; q < max_quant + 2; q++) { + cur = trellis_node + q; + + bits = td->nodes[prev].bits + slice_bits[q]; + error = slice_score[q]; + if (bits > bits_limit) + error = SCORE_LIMIT; + + if (td->nodes[prev].score < SCORE_LIMIT && error < SCORE_LIMIT) + new_score = td->nodes[prev].score + error; + else + new_score = SCORE_LIMIT; + if (td->nodes[cur].prev_node == -1 || + td->nodes[cur].score >= new_score) { + + td->nodes[cur].bits = bits; + td->nodes[cur].score = new_score; + td->nodes[cur].prev_node = prev; + } + } + } + + error = td->nodes[trellis_node + min_quant].score; + pq = trellis_node + min_quant; + for (q = min_quant + 1; q < max_quant + 2; q++) { + if (td->nodes[trellis_node + q].score <= error) { + error = td->nodes[trellis_node + q].score; + pq = trellis_node + q; + } + } + + return pq; +} + +static int find_quant_thread(AVCodecContext *avctx, void *arg, + int jobnr, int threadnr) +{ + ProresContext *ctx = avctx->priv_data; + ProresThreadData *td = ctx->tdata + threadnr; + int mbs_per_slice = ctx->mbs_per_slice; + int x, y = jobnr, mb, q = 0; + + for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { + while (ctx->mb_width - x < mbs_per_slice) + mbs_per_slice >>= 1; + q = find_slice_quant(avctx, avctx->coded_frame, + (mb + 1) * TRELLIS_WIDTH, x, y, + mbs_per_slice, td); + } + + for (x = ctx->slices_width - 1; x >= 0; x--) { + ctx->slice_q[x + y * ctx->slices_width] = td->nodes[q].quant; + q = td->nodes[q].prev_node; + } + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + ProresContext *ctx = avctx->priv_data; + uint8_t *orig_buf, *buf, *slice_hdr, *slice_sizes, *tmp; + uint8_t *picture_size_pos; + PutBitContext pb; + int x, y, i, mb, q = 0; + int sizes[4] = { 0 }; + int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1); + int frame_size, picture_size, slice_size; + int pkt_size, ret; + uint8_t frame_flags; + + *avctx->coded_frame = *pic; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; + + pkt_size = ctx->frame_size_upper_bound + FF_MIN_BUFFER_SIZE; + + if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size)) < 0) + return ret; + + orig_buf = pkt->data; + + // frame atom + orig_buf += 4; // frame size + bytestream_put_be32 (&orig_buf, FRAME_ID); // frame container ID + buf = orig_buf; + + // frame header + tmp = buf; + buf += 2; // frame header size will be stored here + bytestream_put_be16 (&buf, 0); // version 1 + bytestream_put_buffer(&buf, ctx->vendor, 4); + bytestream_put_be16 (&buf, avctx->width); + bytestream_put_be16 (&buf, avctx->height); + + frame_flags = ctx->chroma_factor << 6; + if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) + frame_flags |= pic->top_field_first ? 0x04 : 0x08; + bytestream_put_byte (&buf, frame_flags); + + bytestream_put_byte (&buf, 0); // reserved + bytestream_put_byte (&buf, avctx->color_primaries); + bytestream_put_byte (&buf, avctx->color_trc); + bytestream_put_byte (&buf, avctx->colorspace); + bytestream_put_byte (&buf, 0x40); // source format and alpha information + bytestream_put_byte (&buf, 0); // reserved + if (ctx->quant_sel != QUANT_MAT_DEFAULT) { + bytestream_put_byte (&buf, 0x03); // matrix flags - both matrices are present + // luma quantisation matrix + for (i = 0; i < 64; i++) + bytestream_put_byte(&buf, ctx->quant_mat[i]); + // chroma quantisation matrix + for (i = 0; i < 64; i++) + bytestream_put_byte(&buf, ctx->quant_mat[i]); + } else { + bytestream_put_byte (&buf, 0x00); // matrix flags - default matrices are used + } + bytestream_put_be16 (&tmp, buf - orig_buf); // write back frame header size + + for (ctx->cur_picture_idx = 0; + ctx->cur_picture_idx < ctx->pictures_per_frame; + ctx->cur_picture_idx++) { + // picture header + picture_size_pos = buf + 1; + bytestream_put_byte (&buf, 0x40); // picture header size (in bits) + buf += 4; // picture data size will be stored here + bytestream_put_be16 (&buf, ctx->slices_per_picture); + bytestream_put_byte (&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs + + // seek table - will be filled during slice encoding + slice_sizes = buf; + buf += ctx->slices_per_picture * 2; + + // slices + if (!ctx->force_quant) { + ret = avctx->execute2(avctx, find_quant_thread, NULL, NULL, + ctx->mb_height); + if (ret) + return ret; + } + + for (y = 0; y < ctx->mb_height; y++) { + int mbs_per_slice = ctx->mbs_per_slice; + for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) { + q = ctx->force_quant ? ctx->force_quant + : ctx->slice_q[mb + y * ctx->slices_width]; + + while (ctx->mb_width - x < mbs_per_slice) + mbs_per_slice >>= 1; + + bytestream_put_byte(&buf, slice_hdr_size << 3); + slice_hdr = buf; + buf += slice_hdr_size - 1; + init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8); + encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice); + + bytestream_put_byte(&slice_hdr, q); + slice_size = slice_hdr_size + sizes[ctx->num_planes - 1]; + for (i = 0; i < ctx->num_planes - 1; i++) { + bytestream_put_be16(&slice_hdr, sizes[i]); + slice_size += sizes[i]; + } + bytestream_put_be16(&slice_sizes, slice_size); + buf += slice_size - slice_hdr_size; + } + } + + picture_size = buf - (picture_size_pos - 1); + bytestream_put_be32(&picture_size_pos, picture_size); + } + + orig_buf -= 8; + frame_size = buf - orig_buf; + bytestream_put_be32(&orig_buf, frame_size); + + pkt->size = frame_size; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int encode_close(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + int i; + + av_freep(&avctx->coded_frame); + + if (ctx->tdata) { + for (i = 0; i < avctx->thread_count; i++) + av_free(ctx->tdata[i].nodes); + } + av_freep(&ctx->tdata); + av_freep(&ctx->slice_q); + + return 0; +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + int mps; + int i, j; + int min_quant, max_quant; + int interlaced = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT); + + avctx->bits_per_raw_sample = 10; + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + + ff_proresdsp_init(&ctx->dsp, avctx); + ff_init_scantable(ctx->dsp.dct_permutation, &ctx->scantable, + interlaced ? ff_prores_interlaced_scan + : ff_prores_progressive_scan); + + mps = ctx->mbs_per_slice; + if (mps & (mps - 1)) { + av_log(avctx, AV_LOG_ERROR, + "there should be an integer power of two MBs per slice\n"); + return AVERROR(EINVAL); + } + + ctx->chroma_factor = avctx->pix_fmt == AV_PIX_FMT_YUV422P10 + ? CFACTOR_Y422 + : CFACTOR_Y444; + ctx->profile_info = prores_profile_info + ctx->profile; + ctx->num_planes = 3; + + ctx->mb_width = FFALIGN(avctx->width, 16) >> 4; + + if (interlaced) + ctx->mb_height = FFALIGN(avctx->height, 32) >> 5; + else + ctx->mb_height = FFALIGN(avctx->height, 16) >> 4; + + ctx->slices_width = ctx->mb_width / mps; + ctx->slices_width += av_popcount(ctx->mb_width - ctx->slices_width * mps); + ctx->slices_per_picture = ctx->mb_height * ctx->slices_width; + ctx->pictures_per_frame = 1 + interlaced; + + if (ctx->quant_sel == -1) + ctx->quant_mat = prores_quant_matrices[ctx->profile_info->quant]; + else + ctx->quant_mat = prores_quant_matrices[ctx->quant_sel]; + + if (strlen(ctx->vendor) != 4) { + av_log(avctx, AV_LOG_ERROR, "vendor ID should be 4 bytes\n"); + return AVERROR_INVALIDDATA; + } + + ctx->force_quant = avctx->global_quality / FF_QP2LAMBDA; + if (!ctx->force_quant) { + if (!ctx->bits_per_mb) { + for (i = 0; i < NUM_MB_LIMITS - 1; i++) + if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height * + ctx->pictures_per_frame) + break; + ctx->bits_per_mb = ctx->profile_info->br_tab[i]; + } else if (ctx->bits_per_mb < 128) { + av_log(avctx, AV_LOG_ERROR, "too few bits per MB, please set at least 128\n"); + return AVERROR_INVALIDDATA; + } + + min_quant = ctx->profile_info->min_quant; + max_quant = ctx->profile_info->max_quant; + for (i = min_quant; i < MAX_STORED_Q; i++) { + for (j = 0; j < 64; j++) + ctx->quants[i][j] = ctx->quant_mat[j] * i; + } + + ctx->slice_q = av_malloc(ctx->slices_per_picture * sizeof(*ctx->slice_q)); + if (!ctx->slice_q) { + encode_close(avctx); + return AVERROR(ENOMEM); + } + + ctx->tdata = av_mallocz(avctx->thread_count * sizeof(*ctx->tdata)); + if (!ctx->tdata) { + encode_close(avctx); + return AVERROR(ENOMEM); + } + + for (j = 0; j < avctx->thread_count; j++) { + ctx->tdata[j].nodes = av_malloc((ctx->slices_width + 1) + * TRELLIS_WIDTH + * sizeof(*ctx->tdata->nodes)); + if (!ctx->tdata[j].nodes) { + encode_close(avctx); + return AVERROR(ENOMEM); + } + for (i = min_quant; i < max_quant + 2; i++) { + ctx->tdata[j].nodes[i].prev_node = -1; + ctx->tdata[j].nodes[i].bits = 0; + ctx->tdata[j].nodes[i].score = 0; + } + } + } else { + int ls = 0; + + if (ctx->force_quant > 64) { + av_log(avctx, AV_LOG_ERROR, "too large quantiser, maximum is 64\n"); + return AVERROR_INVALIDDATA; + } + + for (j = 0; j < 64; j++) { + ctx->quants[0][j] = ctx->quant_mat[j] * ctx->force_quant; + ls += av_log2((1 << 11) / ctx->quants[0][j]) * 2 + 1; + } + + ctx->bits_per_mb = ls * 8; + if (ctx->chroma_factor == CFACTOR_Y444) + ctx->bits_per_mb += ls * 4; + if (ctx->num_planes == 4) + ctx->bits_per_mb += ls * 4; + } + + ctx->frame_size_upper_bound = ctx->pictures_per_frame * + ctx->slices_per_picture * + (2 + 2 * ctx->num_planes + + (mps * ctx->bits_per_mb) / 8) + + 200; + + avctx->codec_tag = ctx->profile_info->tag; + + av_log(avctx, AV_LOG_DEBUG, + "profile %d, %d slices, interlacing: %s, %d bits per MB\n", + ctx->profile, ctx->slices_per_picture * ctx->pictures_per_frame, + interlaced ? "yes" : "no", ctx->bits_per_mb); + av_log(avctx, AV_LOG_DEBUG, "frame size upper bound: %d\n", + ctx->frame_size_upper_bound); + + return 0; +} + +#define OFFSET(x) offsetof(ProresContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption options[] = { + { "mbs_per_slice", "macroblocks per slice", OFFSET(mbs_per_slice), + AV_OPT_TYPE_INT, { .i64 = 8 }, 1, MAX_MBS_PER_SLICE, VE }, + { "profile", NULL, OFFSET(profile), AV_OPT_TYPE_INT, + { .i64 = PRORES_PROFILE_STANDARD }, + PRORES_PROFILE_PROXY, PRORES_PROFILE_HQ, VE, "profile" }, + { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_PROXY }, + 0, 0, VE, "profile" }, + { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_LT }, + 0, 0, VE, "profile" }, + { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_STANDARD }, + 0, 0, VE, "profile" }, + { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_HQ }, + 0, 0, VE, "profile" }, + { "vendor", "vendor ID", OFFSET(vendor), + AV_OPT_TYPE_STRING, { .str = "Lavc" }, CHAR_MIN, CHAR_MAX, VE }, + { "bits_per_mb", "desired bits per macroblock", OFFSET(bits_per_mb), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8192, VE }, + { "quant_mat", "quantiser matrix", OFFSET(quant_sel), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, QUANT_MAT_DEFAULT, VE, "quant_mat" }, + { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, + 0, 0, VE, "quant_mat" }, + { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_PROXY }, + 0, 0, VE, "quant_mat" }, + { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_LT }, + 0, 0, VE, "quant_mat" }, + { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_STANDARD }, + 0, 0, VE, "quant_mat" }, + { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_HQ }, + 0, 0, VE, "quant_mat" }, + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_DEFAULT }, + 0, 0, VE, "quant_mat" }, + { NULL } +}; + +static const AVClass proresenc_class = { + .class_name = "ProRes encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_prores_kostya_encoder = { + .name = "prores_kostya", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .priv_data_size = sizeof(ProresContext), + .init = encode_init, + .close = encode_close, + .encode2 = encode_frame, + .capabilities = CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE + }, + .priv_class = &proresenc_class, +}; diff --git a/ffmpeg/libavcodec/psymodel.c b/ffmpeg/libavcodec/psymodel.c new file mode 100644 index 0000000..ea11636 --- /dev/null +++ b/ffmpeg/libavcodec/psymodel.c @@ -0,0 +1,147 @@ +/* + * audio encoder psychoacoustic model + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 "avcodec.h" +#include "psymodel.h" +#include "iirfilter.h" +#include "libavutil/mem.h" + +extern const FFPsyModel ff_aac_psy_model; + +av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens, + const uint8_t **bands, const int* num_bands, + int num_groups, const uint8_t *group_map) +{ + int i, j, k = 0; + + ctx->avctx = avctx; + ctx->ch = av_mallocz(sizeof(ctx->ch[0]) * avctx->channels * 2); + ctx->group = av_mallocz(sizeof(ctx->group[0]) * num_groups); + ctx->bands = av_malloc (sizeof(ctx->bands[0]) * num_lens); + ctx->num_bands = av_malloc (sizeof(ctx->num_bands[0]) * num_lens); + memcpy(ctx->bands, bands, sizeof(ctx->bands[0]) * num_lens); + memcpy(ctx->num_bands, num_bands, sizeof(ctx->num_bands[0]) * num_lens); + + /* assign channels to groups (with virtual channels for coupling) */ + for (i = 0; i < num_groups; i++) { + /* NOTE: Add 1 to handle the AAC chan_config without modification. + * This has the side effect of allowing an array of 0s to map + * to one channel per group. + */ + ctx->group[i].num_ch = group_map[i] + 1; + for (j = 0; j < ctx->group[i].num_ch * 2; j++) + ctx->group[i].ch[j] = &ctx->ch[k++]; + } + + switch (ctx->avctx->codec_id) { + case AV_CODEC_ID_AAC: + ctx->model = &ff_aac_psy_model; + break; + } + if (ctx->model->init) + return ctx->model->init(ctx); + return 0; +} + +FFPsyChannelGroup *ff_psy_find_group(FFPsyContext *ctx, int channel) +{ + int i = 0, ch = 0; + + while (ch <= channel) + ch += ctx->group[i++].num_ch; + + return &ctx->group[i-1]; +} + +av_cold void ff_psy_end(FFPsyContext *ctx) +{ + if (ctx->model->end) + ctx->model->end(ctx); + av_freep(&ctx->bands); + av_freep(&ctx->num_bands); + av_freep(&ctx->group); + av_freep(&ctx->ch); +} + +typedef struct FFPsyPreprocessContext{ + AVCodecContext *avctx; + float stereo_att; + struct FFIIRFilterCoeffs *fcoeffs; + struct FFIIRFilterState **fstate; + struct FFIIRFilterContext fiir; +}FFPsyPreprocessContext; + +#define FILT_ORDER 4 + +av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *avctx) +{ + FFPsyPreprocessContext *ctx; + int i; + float cutoff_coeff = 0; + ctx = av_mallocz(sizeof(FFPsyPreprocessContext)); + ctx->avctx = avctx; + + if (avctx->cutoff > 0) + cutoff_coeff = 2.0 * avctx->cutoff / avctx->sample_rate; + + if (!cutoff_coeff && avctx->codec_id == AV_CODEC_ID_AAC) + cutoff_coeff = 2.0 * AAC_CUTOFF(avctx) / avctx->sample_rate; + + if (cutoff_coeff && cutoff_coeff < 0.98) + ctx->fcoeffs = ff_iir_filter_init_coeffs(avctx, FF_FILTER_TYPE_BUTTERWORTH, + FF_FILTER_MODE_LOWPASS, FILT_ORDER, + cutoff_coeff, 0.0, 0.0); + if (ctx->fcoeffs) { + ctx->fstate = av_mallocz(sizeof(ctx->fstate[0]) * avctx->channels); + for (i = 0; i < avctx->channels; i++) + ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER); + } + + ff_iir_filter_init(&ctx->fiir); + + return ctx; +} + +void ff_psy_preprocess(struct FFPsyPreprocessContext *ctx, float **audio, int channels) +{ + int ch; + int frame_size = ctx->avctx->frame_size; + FFIIRFilterContext *iir = &ctx->fiir; + + if (ctx->fstate) { + for (ch = 0; ch < channels; ch++) + iir->filter_flt(ctx->fcoeffs, ctx->fstate[ch], frame_size, + &audio[ch][frame_size], 1, &audio[ch][frame_size], 1); + } +} + +av_cold void ff_psy_preprocess_end(struct FFPsyPreprocessContext *ctx) +{ + int i; + ff_iir_filter_free_coeffs(ctx->fcoeffs); + if (ctx->fstate) + for (i = 0; i < ctx->avctx->channels; i++) + ff_iir_filter_free_state(ctx->fstate[i]); + av_freep(&ctx->fstate); + av_free(ctx); +} diff --git a/ffmpeg/libavcodec/psymodel.h b/ffmpeg/libavcodec/psymodel.h new file mode 100644 index 0000000..d1a126a --- /dev/null +++ b/ffmpeg/libavcodec/psymodel.h @@ -0,0 +1,189 @@ +/* + * audio encoder psychoacoustic model + * Copyright (C) 2008 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_PSYMODEL_H +#define AVCODEC_PSYMODEL_H + +#include "avcodec.h" + +/** maximum possible number of bands */ +#define PSY_MAX_BANDS 128 +/** maximum number of channels */ +#define PSY_MAX_CHANS 20 + +#define AAC_CUTOFF(s) (s->bit_rate ? FFMIN3(4000 + s->bit_rate/8, 12000 + s->bit_rate/32, s->sample_rate / 2) : (s->sample_rate / 2)) + +/** + * single band psychoacoustic information + */ +typedef struct FFPsyBand { + int bits; + float energy; + float threshold; + float distortion; + float perceptual_weight; +} FFPsyBand; + +/** + * single channel psychoacoustic information + */ +typedef struct FFPsyChannel { + FFPsyBand psy_bands[PSY_MAX_BANDS]; ///< channel bands information + float entropy; ///< total PE for this channel +} FFPsyChannel; + +/** + * psychoacoustic information for an arbitrary group of channels + */ +typedef struct FFPsyChannelGroup { + FFPsyChannel *ch[PSY_MAX_CHANS]; ///< pointers to the individual channels in the group + uint8_t num_ch; ///< number of channels in this group + uint8_t coupling[PSY_MAX_BANDS]; ///< allow coupling for this band in the group +} FFPsyChannelGroup; + +/** + * windowing related information + */ +typedef struct FFPsyWindowInfo { + int window_type[3]; ///< window type (short/long/transitional, etc.) - current, previous and next + int window_shape; ///< window shape (sine/KBD/whatever) + int num_windows; ///< number of windows in a frame + int grouping[8]; ///< window grouping (for e.g. AAC) + int *window_sizes; ///< sequence of window sizes inside one frame (for eg. WMA) +} FFPsyWindowInfo; + +/** + * context used by psychoacoustic model + */ +typedef struct FFPsyContext { + AVCodecContext *avctx; ///< encoder context + const struct FFPsyModel *model; ///< encoder-specific model functions + + FFPsyChannel *ch; ///< single channel information + FFPsyChannelGroup *group; ///< channel group information + int num_groups; ///< number of channel groups + + uint8_t **bands; ///< scalefactor band sizes for possible frame sizes + int *num_bands; ///< number of scalefactor bands for possible frame sizes + int num_lens; ///< number of scalefactor band sets + + struct { + int size; ///< size of the bitresevoir in bits + int bits; ///< number of bits used in the bitresevoir + } bitres; + + void* model_priv_data; ///< psychoacoustic model implementation private data +} FFPsyContext; + +/** + * codec-specific psychoacoustic model implementation + */ +typedef struct FFPsyModel { + const char *name; + int (*init) (FFPsyContext *apc); + + /** + * Suggest window sequence for channel. + * + * @param ctx model context + * @param audio samples for the current frame + * @param la lookahead samples (NULL when unavailable) + * @param channel number of channel element to analyze + * @param prev_type previous window type + * + * @return suggested window information in a structure + */ + FFPsyWindowInfo (*window)(FFPsyContext *ctx, const float *audio, const float *la, int channel, int prev_type); + + /** + * Perform psychoacoustic analysis and set band info (threshold, energy) for a group of channels. + * + * @param ctx model context + * @param channel channel number of the first channel in the group to perform analysis on + * @param coeffs array of pointers to the transformed coefficients + * @param wi window information for the channels in the group + */ + void (*analyze)(FFPsyContext *ctx, int channel, const float **coeffs, const FFPsyWindowInfo *wi); + + void (*end) (FFPsyContext *apc); +} FFPsyModel; + +/** + * Initialize psychoacoustic model. + * + * @param ctx model context + * @param avctx codec context + * @param num_lens number of possible frame lengths + * @param bands scalefactor band lengths for all frame lengths + * @param num_bands number of scalefactor bands for all frame lengths + * @param num_groups number of channel groups + * @param group_map array with # of channels in group - 1, for each group + * + * @return zero if successful, a negative value if not + */ +int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens, + const uint8_t **bands, const int *num_bands, + int num_groups, const uint8_t *group_map); + +/** + * Determine what group a channel belongs to. + * + * @param ctx psymodel context + * @param channel channel to locate the group for + * + * @return pointer to the FFPsyChannelGroup this channel belongs to + */ +FFPsyChannelGroup *ff_psy_find_group(FFPsyContext *ctx, int channel); + +/** + * Cleanup model context at the end. + * + * @param ctx model context + */ +void ff_psy_end(FFPsyContext *ctx); + + +/************************************************************************** + * Audio preprocessing stuff. * + * This should be moved into some audio filter eventually. * + **************************************************************************/ +struct FFPsyPreprocessContext; + +/** + * psychoacoustic model audio preprocessing initialization + */ +struct FFPsyPreprocessContext *ff_psy_preprocess_init(AVCodecContext *avctx); + +/** + * Preprocess several channel in audio frame in order to compress it better. + * + * @param ctx preprocessing context + * @param audio samples to be filtered (in place) + * @param channels number of channel to preprocess + */ +void ff_psy_preprocess(struct FFPsyPreprocessContext *ctx, float **audio, int channels); + +/** + * Cleanup audio preprocessing module. + */ +void ff_psy_preprocess_end(struct FFPsyPreprocessContext *ctx); + +#endif /* AVCODEC_PSYMODEL_H */ diff --git a/ffmpeg/libavcodec/pthread.c b/ffmpeg/libavcodec/pthread.c new file mode 100644 index 0000000..9dbaec3 --- /dev/null +++ b/ffmpeg/libavcodec/pthread.c @@ -0,0 +1,1136 @@ +/* + * Copyright (c) 2004 Roman Shaposhnik + * Copyright (c) 2008 Alexander Strange (astrange@ithinksw.com) + * + * Many thanks to Steven M. Schultz for providing clever ideas and + * to Michael Niedermayer for writing initial + * implementation. + * + * 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 + */ + +/** + * @file + * Multithreading support functions + * @see doc/multithreading.txt + */ + +#include "config.h" + +#if HAVE_SCHED_GETAFFINITY +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#endif +#if HAVE_GETPROCESSAFFINITYMASK +#include +#endif +#if HAVE_SYSCTL +#if HAVE_SYS_PARAM_H +#include +#endif +#include +#include +#include +#endif +#if HAVE_SYSCONF +#include +#endif + +#include "avcodec.h" +#include "internal.h" +#include "thread.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" + +#if HAVE_PTHREADS +#include +#elif HAVE_W32THREADS +#include "w32pthreads.h" +#elif HAVE_OS2THREADS +#include "os2threads.h" +#endif + +typedef int (action_func)(AVCodecContext *c, void *arg); +typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); + +typedef struct ThreadContext { + pthread_t *workers; + action_func *func; + action_func2 *func2; + void *args; + int *rets; + int rets_count; + int job_count; + int job_size; + + pthread_cond_t last_job_cond; + pthread_cond_t current_job_cond; + pthread_mutex_t current_job_lock; + int current_job; + unsigned int current_execute; + int done; +} ThreadContext; + +/** + * Context used by codec threads and stored in their AVCodecContext thread_opaque. + */ +typedef struct PerThreadContext { + struct FrameThreadContext *parent; + + pthread_t thread; + int thread_init; + pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread. + pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change. + pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish. + + pthread_mutex_t mutex; ///< Mutex used to protect the contents of the PerThreadContext. + pthread_mutex_t progress_mutex; ///< Mutex used to protect frame progress values and progress_cond. + + AVCodecContext *avctx; ///< Context used to decode packets passed to this thread. + + AVPacket avpkt; ///< Input packet (for decoding) or output (for encoding). + uint8_t *buf; ///< backup storage for packet data when the input packet is not refcounted + int allocated_buf_size; ///< Size allocated for buf + + AVFrame frame; ///< Output frame (for decoding) or input (for encoding). + int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call. + int result; ///< The result of the last codec decode/encode() call. + + enum { + STATE_INPUT_READY, ///< Set when the thread is awaiting a packet. + STATE_SETTING_UP, ///< Set before the codec has called ff_thread_finish_setup(). + STATE_GET_BUFFER, /**< + * Set when the codec calls get_buffer(). + * State is returned to STATE_SETTING_UP afterwards. + */ + STATE_SETUP_FINISHED ///< Set after the codec has called ff_thread_finish_setup(). + } state; + + /** + * Array of frames passed to ff_thread_release_buffer(). + * Frames are released after all threads referencing them are finished. + */ + AVFrame *released_buffers; + int num_released_buffers; + int released_buffers_allocated; + + AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer() + int requested_flags; ///< flags passed to get_buffer() for requested_frame +} PerThreadContext; + +/** + * Context stored in the client AVCodecContext thread_opaque. + */ +typedef struct FrameThreadContext { + PerThreadContext *threads; ///< The contexts for each thread. + PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on. + + pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer(). + + int next_decoding; ///< The next context to submit a packet to. + int next_finished; ///< The next context to return output from. + + int delaying; /**< + * Set for the first N packets, where N is the number of threads. + * While it is set, ff_thread_en/decode_frame won't return any results. + */ + + int die; ///< Set when threads should exit. +} FrameThreadContext; + + +/* H264 slice threading seems to be buggy with more than 16 threads, + * limit the number of threads to 16 for automatic detection */ +#define MAX_AUTO_THREADS 16 + +int ff_get_logical_cpus(AVCodecContext *avctx) +{ + int ret, nb_cpus = 1; +#if HAVE_SCHED_GETAFFINITY && defined(CPU_COUNT) + cpu_set_t cpuset; + + CPU_ZERO(&cpuset); + + ret = sched_getaffinity(0, sizeof(cpuset), &cpuset); + if (!ret) { + nb_cpus = CPU_COUNT(&cpuset); + } +#elif HAVE_GETPROCESSAFFINITYMASK + DWORD_PTR proc_aff, sys_aff; + ret = GetProcessAffinityMask(GetCurrentProcess(), &proc_aff, &sys_aff); + if (ret) + nb_cpus = av_popcount64(proc_aff); +#elif HAVE_SYSCTL && defined(HW_NCPU) + int mib[2] = { CTL_HW, HW_NCPU }; + size_t len = sizeof(nb_cpus); + + ret = sysctl(mib, 2, &nb_cpus, &len, NULL, 0); + if (ret == -1) + nb_cpus = 0; +#elif HAVE_SYSCONF && defined(_SC_NPROC_ONLN) + nb_cpus = sysconf(_SC_NPROC_ONLN); +#elif HAVE_SYSCONF && defined(_SC_NPROCESSORS_ONLN) + nb_cpus = sysconf(_SC_NPROCESSORS_ONLN); +#endif + av_log(avctx, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus); + + if (avctx->height) + nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16); + + return nb_cpus; +} + + +static void* attribute_align_arg worker(void *v) +{ + AVCodecContext *avctx = v; + ThreadContext *c = avctx->thread_opaque; + int our_job = c->job_count; + int last_execute = 0; + int thread_count = avctx->thread_count; + int self_id; + + pthread_mutex_lock(&c->current_job_lock); + self_id = c->current_job++; + for (;;){ + while (our_job >= c->job_count) { + if (c->current_job == thread_count + c->job_count) + pthread_cond_signal(&c->last_job_cond); + + while (last_execute == c->current_execute && !c->done) + pthread_cond_wait(&c->current_job_cond, &c->current_job_lock); + last_execute = c->current_execute; + our_job = self_id; + + if (c->done) { + pthread_mutex_unlock(&c->current_job_lock); + return NULL; + } + } + pthread_mutex_unlock(&c->current_job_lock); + + c->rets[our_job%c->rets_count] = c->func ? c->func(avctx, (char*)c->args + our_job*c->job_size): + c->func2(avctx, c->args, our_job, self_id); + + pthread_mutex_lock(&c->current_job_lock); + our_job = c->current_job++; + } +} + +static av_always_inline void avcodec_thread_park_workers(ThreadContext *c, int thread_count) +{ + while (c->current_job != thread_count + c->job_count) + pthread_cond_wait(&c->last_job_cond, &c->current_job_lock); + pthread_mutex_unlock(&c->current_job_lock); +} + +static void thread_free(AVCodecContext *avctx) +{ + ThreadContext *c = avctx->thread_opaque; + int i; + + pthread_mutex_lock(&c->current_job_lock); + c->done = 1; + pthread_cond_broadcast(&c->current_job_cond); + pthread_mutex_unlock(&c->current_job_lock); + + for (i=0; ithread_count; i++) + pthread_join(c->workers[i], NULL); + + pthread_mutex_destroy(&c->current_job_lock); + pthread_cond_destroy(&c->current_job_cond); + pthread_cond_destroy(&c->last_job_cond); + av_free(c->workers); + av_freep(&avctx->thread_opaque); +} + +static int avcodec_thread_execute(AVCodecContext *avctx, action_func* func, void *arg, int *ret, int job_count, int job_size) +{ + ThreadContext *c= avctx->thread_opaque; + int dummy_ret; + + if (!(avctx->active_thread_type&FF_THREAD_SLICE) || avctx->thread_count <= 1) + return avcodec_default_execute(avctx, func, arg, ret, job_count, job_size); + + if (job_count <= 0) + return 0; + + pthread_mutex_lock(&c->current_job_lock); + + c->current_job = avctx->thread_count; + c->job_count = job_count; + c->job_size = job_size; + c->args = arg; + c->func = func; + if (ret) { + c->rets = ret; + c->rets_count = job_count; + } else { + c->rets = &dummy_ret; + c->rets_count = 1; + } + c->current_execute++; + pthread_cond_broadcast(&c->current_job_cond); + + avcodec_thread_park_workers(c, avctx->thread_count); + + return 0; +} + +static int avcodec_thread_execute2(AVCodecContext *avctx, action_func2* func2, void *arg, int *ret, int job_count) +{ + ThreadContext *c= avctx->thread_opaque; + c->func2 = func2; + return avcodec_thread_execute(avctx, NULL, arg, ret, job_count, 0); +} + +static int thread_init(AVCodecContext *avctx) +{ + int i; + ThreadContext *c; + int thread_count = avctx->thread_count; + + if (!thread_count) { + int nb_cpus = ff_get_logical_cpus(avctx); + // use number of cores + 1 as thread count if there is more than one + if (nb_cpus > 1) + thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); + else + thread_count = avctx->thread_count = 1; + } + + if (thread_count <= 1) { + avctx->active_thread_type = 0; + return 0; + } + + c = av_mallocz(sizeof(ThreadContext)); + if (!c) + return -1; + + c->workers = av_mallocz(sizeof(pthread_t)*thread_count); + if (!c->workers) { + av_free(c); + return -1; + } + + avctx->thread_opaque = c; + c->current_job = 0; + c->job_count = 0; + c->job_size = 0; + c->done = 0; + pthread_cond_init(&c->current_job_cond, NULL); + pthread_cond_init(&c->last_job_cond, NULL); + pthread_mutex_init(&c->current_job_lock, NULL); + pthread_mutex_lock(&c->current_job_lock); + for (i=0; iworkers[i], NULL, worker, avctx)) { + avctx->thread_count = i; + pthread_mutex_unlock(&c->current_job_lock); + ff_thread_free(avctx); + return -1; + } + } + + avcodec_thread_park_workers(c, thread_count); + + avctx->execute = avcodec_thread_execute; + avctx->execute2 = avcodec_thread_execute2; + return 0; +} + +/** + * Codec worker thread. + * + * Automatically calls ff_thread_finish_setup() if the codec does + * not provide an update_thread_context method, or if the codec returns + * before calling it. + */ +static attribute_align_arg void *frame_worker_thread(void *arg) +{ + PerThreadContext *p = arg; + FrameThreadContext *fctx = p->parent; + AVCodecContext *avctx = p->avctx; + const AVCodec *codec = avctx->codec; + + pthread_mutex_lock(&p->mutex); + while (1) { + while (p->state == STATE_INPUT_READY && !fctx->die) + pthread_cond_wait(&p->input_cond, &p->mutex); + + if (fctx->die) break; + + if (!codec->update_thread_context && (avctx->thread_safe_callbacks || ( +#if FF_API_GET_BUFFER + !avctx->get_buffer && +#endif + avctx->get_buffer2 == avcodec_default_get_buffer2))) + ff_thread_finish_setup(avctx); + + avcodec_get_frame_defaults(&p->frame); + p->got_frame = 0; + p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt); + + /* many decoders assign whole AVFrames, thus overwriting extended_data; + * make sure it's set correctly */ + p->frame.extended_data = p->frame.data; + + if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); + + pthread_mutex_lock(&p->progress_mutex); +#if 0 //BUFREF-FIXME + for (i = 0; i < MAX_BUFFERS; i++) + if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) { + p->progress[i][0] = INT_MAX; + p->progress[i][1] = INT_MAX; + } +#endif + p->state = STATE_INPUT_READY; + + pthread_cond_broadcast(&p->progress_cond); + pthread_cond_signal(&p->output_cond); + pthread_mutex_unlock(&p->progress_mutex); + } + pthread_mutex_unlock(&p->mutex); + + return NULL; +} + +/** + * Update the next thread's AVCodecContext with values from the reference thread's context. + * + * @param dst The destination context. + * @param src The source context. + * @param for_user 0 if the destination is a codec thread, 1 if the destination is the user's thread + */ +static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, int for_user) +{ + int err = 0; + + if (dst != src) { + dst->time_base = src->time_base; + dst->width = src->width; + dst->height = src->height; + dst->pix_fmt = src->pix_fmt; + + dst->coded_width = src->coded_width; + dst->coded_height = src->coded_height; + + dst->has_b_frames = src->has_b_frames; + dst->idct_algo = src->idct_algo; + + dst->bits_per_coded_sample = src->bits_per_coded_sample; + dst->sample_aspect_ratio = src->sample_aspect_ratio; + dst->dtg_active_format = src->dtg_active_format; + + dst->profile = src->profile; + dst->level = src->level; + + dst->bits_per_raw_sample = src->bits_per_raw_sample; + dst->ticks_per_frame = src->ticks_per_frame; + dst->color_primaries = src->color_primaries; + + dst->color_trc = src->color_trc; + dst->colorspace = src->colorspace; + dst->color_range = src->color_range; + dst->chroma_sample_location = src->chroma_sample_location; + } + + if (for_user) { + dst->delay = src->thread_count - 1; + dst->coded_frame = src->coded_frame; + } else { + if (dst->codec->update_thread_context) + err = dst->codec->update_thread_context(dst, src); + } + + return err; +} + +/** + * Update the next thread's AVCodecContext with values set by the user. + * + * @param dst The destination context. + * @param src The source context. + * @return 0 on success, negative error code on failure + */ +static int update_context_from_user(AVCodecContext *dst, AVCodecContext *src) +{ +#define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e - (char*)&dst->s); + dst->flags = src->flags; + + dst->draw_horiz_band= src->draw_horiz_band; + dst->get_buffer2 = src->get_buffer2; +#if FF_API_GET_BUFFER + dst->get_buffer = src->get_buffer; + dst->release_buffer = src->release_buffer; +#endif + + dst->opaque = src->opaque; + dst->debug = src->debug; + dst->debug_mv = src->debug_mv; + + dst->slice_flags = src->slice_flags; + dst->flags2 = src->flags2; + + copy_fields(skip_loop_filter, subtitle_header); + + dst->frame_number = src->frame_number; + dst->reordered_opaque = src->reordered_opaque; + dst->thread_safe_callbacks = src->thread_safe_callbacks; + + if (src->slice_count && src->slice_offset) { + if (dst->slice_count < src->slice_count) { + int *tmp = av_realloc(dst->slice_offset, src->slice_count * + sizeof(*dst->slice_offset)); + if (!tmp) { + av_free(dst->slice_offset); + return AVERROR(ENOMEM); + } + dst->slice_offset = tmp; + } + memcpy(dst->slice_offset, src->slice_offset, + src->slice_count * sizeof(*dst->slice_offset)); + } + dst->slice_count = src->slice_count; + return 0; +#undef copy_fields +} + +/// Releases the buffers that this decoding thread was the last user of. +static void release_delayed_buffers(PerThreadContext *p) +{ + FrameThreadContext *fctx = p->parent; + + while (p->num_released_buffers > 0) { + AVFrame *f; + + pthread_mutex_lock(&fctx->buffer_mutex); + + // fix extended data in case the caller screwed it up + av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO); + f = &p->released_buffers[--p->num_released_buffers]; + f->extended_data = f->data; + av_frame_unref(f); + + pthread_mutex_unlock(&fctx->buffer_mutex); + } +} + +static int submit_packet(PerThreadContext *p, AVPacket *avpkt) +{ + FrameThreadContext *fctx = p->parent; + PerThreadContext *prev_thread = fctx->prev_thread; + const AVCodec *codec = p->avctx->codec; + + if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; + + pthread_mutex_lock(&p->mutex); + + release_delayed_buffers(p); + + if (prev_thread) { + int err; + if (prev_thread->state == STATE_SETTING_UP) { + pthread_mutex_lock(&prev_thread->progress_mutex); + while (prev_thread->state == STATE_SETTING_UP) + pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); + pthread_mutex_unlock(&prev_thread->progress_mutex); + } + + err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); + if (err) { + pthread_mutex_unlock(&p->mutex); + return err; + } + } + + av_buffer_unref(&p->avpkt.buf); + p->avpkt = *avpkt; + if (avpkt->buf) + p->avpkt.buf = av_buffer_ref(avpkt->buf); + else { + av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + p->avpkt.data = p->buf; + memcpy(p->buf, avpkt->data, avpkt->size); + memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + } + + p->state = STATE_SETTING_UP; + pthread_cond_signal(&p->input_cond); + pthread_mutex_unlock(&p->mutex); + + /* + * If the client doesn't have a thread-safe get_buffer(), + * then decoding threads call back to the main thread, + * and it calls back to the client here. + */ + + if (!p->avctx->thread_safe_callbacks && ( +#if FF_API_GET_BUFFER + p->avctx->get_buffer || +#endif + p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { + while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { + pthread_mutex_lock(&p->progress_mutex); + while (p->state == STATE_SETTING_UP) + pthread_cond_wait(&p->progress_cond, &p->progress_mutex); + + if (p->state == STATE_GET_BUFFER) { + p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); + p->state = STATE_SETTING_UP; + pthread_cond_signal(&p->progress_cond); + } + pthread_mutex_unlock(&p->progress_mutex); + } + } + + fctx->prev_thread = p; + fctx->next_decoding++; + + return 0; +} + +int ff_thread_decode_frame(AVCodecContext *avctx, + AVFrame *picture, int *got_picture_ptr, + AVPacket *avpkt) +{ + FrameThreadContext *fctx = avctx->thread_opaque; + int finished = fctx->next_finished; + PerThreadContext *p; + int err; + + /* + * Submit a packet to the next decoding thread. + */ + + p = &fctx->threads[fctx->next_decoding]; + err = update_context_from_user(p->avctx, avctx); + if (err) return err; + err = submit_packet(p, avpkt); + if (err) return err; + + /* + * If we're still receiving the initial packets, don't return a frame. + */ + + if (fctx->delaying) { + if (fctx->next_decoding >= (avctx->thread_count-1)) fctx->delaying = 0; + + *got_picture_ptr=0; + if (avpkt->size) + return avpkt->size; + } + + /* + * Return the next available frame from the oldest thread. + * If we're at the end of the stream, then we have to skip threads that + * didn't output a frame, because we don't want to accidentally signal + * EOF (avpkt->size == 0 && *got_picture_ptr == 0). + */ + + do { + p = &fctx->threads[finished++]; + + if (p->state != STATE_INPUT_READY) { + pthread_mutex_lock(&p->progress_mutex); + while (p->state != STATE_INPUT_READY) + pthread_cond_wait(&p->output_cond, &p->progress_mutex); + pthread_mutex_unlock(&p->progress_mutex); + } + + av_frame_move_ref(picture, &p->frame); + *got_picture_ptr = p->got_frame; + picture->pkt_dts = p->avpkt.dts; + + /* + * A later call with avkpt->size == 0 may loop over all threads, + * including this one, searching for a frame to return before being + * stopped by the "finished != fctx->next_finished" condition. + * Make sure we don't mistakenly return the same frame again. + */ + p->got_frame = 0; + + if (finished >= avctx->thread_count) finished = 0; + } while (!avpkt->size && !*got_picture_ptr && finished != fctx->next_finished); + + update_context_from_thread(avctx, p->avctx, 1); + + if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0; + + fctx->next_finished = finished; + + /* return the size of the consumed packet if no error occurred */ + return (p->result >= 0) ? avpkt->size : p->result; +} + +void ff_thread_report_progress(ThreadFrame *f, int n, int field) +{ + PerThreadContext *p; + volatile int *progress = f->progress ? (int*)f->progress->data : NULL; + + if (!progress || progress[field] >= n) return; + + p = f->owner->thread_opaque; + + if (f->owner->debug&FF_DEBUG_THREADS) + av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field); + + pthread_mutex_lock(&p->progress_mutex); + progress[field] = n; + pthread_cond_broadcast(&p->progress_cond); + pthread_mutex_unlock(&p->progress_mutex); +} + +void ff_thread_await_progress(ThreadFrame *f, int n, int field) +{ + PerThreadContext *p; + volatile int *progress = f->progress ? (int*)f->progress->data : NULL; + + if (!progress || progress[field] >= n) return; + + p = f->owner->thread_opaque; + + if (f->owner->debug&FF_DEBUG_THREADS) + av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress); + + pthread_mutex_lock(&p->progress_mutex); + while (progress[field] < n) + pthread_cond_wait(&p->progress_cond, &p->progress_mutex); + pthread_mutex_unlock(&p->progress_mutex); +} + +void ff_thread_finish_setup(AVCodecContext *avctx) { + PerThreadContext *p = avctx->thread_opaque; + + if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return; + + if(p->state == STATE_SETUP_FINISHED){ + av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); + } + + pthread_mutex_lock(&p->progress_mutex); + p->state = STATE_SETUP_FINISHED; + pthread_cond_broadcast(&p->progress_cond); + pthread_mutex_unlock(&p->progress_mutex); +} + +/// Waits for all threads to finish. +static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count) +{ + int i; + + for (i = 0; i < thread_count; i++) { + PerThreadContext *p = &fctx->threads[i]; + + if (p->state != STATE_INPUT_READY) { + pthread_mutex_lock(&p->progress_mutex); + while (p->state != STATE_INPUT_READY) + pthread_cond_wait(&p->output_cond, &p->progress_mutex); + pthread_mutex_unlock(&p->progress_mutex); + } + p->got_frame = 0; + } +} + +static void frame_thread_free(AVCodecContext *avctx, int thread_count) +{ + FrameThreadContext *fctx = avctx->thread_opaque; + const AVCodec *codec = avctx->codec; + int i; + + park_frame_worker_threads(fctx, thread_count); + + if (fctx->prev_thread && fctx->prev_thread != fctx->threads) + if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { + av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); + fctx->prev_thread->avctx->internal->is_copy = fctx->threads->avctx->internal->is_copy; + fctx->threads->avctx->internal->is_copy = 1; + } + + fctx->die = 1; + + for (i = 0; i < thread_count; i++) { + PerThreadContext *p = &fctx->threads[i]; + + pthread_mutex_lock(&p->mutex); + pthread_cond_signal(&p->input_cond); + pthread_mutex_unlock(&p->mutex); + + if (p->thread_init) + pthread_join(p->thread, NULL); + p->thread_init=0; + + if (codec->close) + codec->close(p->avctx); + + avctx->codec = NULL; + + release_delayed_buffers(p); + av_frame_unref(&p->frame); + } + + for (i = 0; i < thread_count; i++) { + PerThreadContext *p = &fctx->threads[i]; + + pthread_mutex_destroy(&p->mutex); + pthread_mutex_destroy(&p->progress_mutex); + pthread_cond_destroy(&p->input_cond); + pthread_cond_destroy(&p->progress_cond); + pthread_cond_destroy(&p->output_cond); + av_buffer_unref(&p->avpkt.buf); + av_freep(&p->buf); + av_freep(&p->released_buffers); + + if (i) { + av_freep(&p->avctx->priv_data); + av_freep(&p->avctx->internal); + av_freep(&p->avctx->slice_offset); + } + + av_freep(&p->avctx); + } + + av_freep(&fctx->threads); + pthread_mutex_destroy(&fctx->buffer_mutex); + av_freep(&avctx->thread_opaque); +} + +static int frame_thread_init(AVCodecContext *avctx) +{ + int thread_count = avctx->thread_count; + const AVCodec *codec = avctx->codec; + AVCodecContext *src = avctx; + FrameThreadContext *fctx; + int i, err = 0; + + if (!thread_count) { + int nb_cpus = ff_get_logical_cpus(avctx); + if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv) + nb_cpus = 1; + // use number of cores + 1 as thread count if there is more than one + if (nb_cpus > 1) + thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS); + else + thread_count = avctx->thread_count = 1; + } + + if (thread_count <= 1) { + avctx->active_thread_type = 0; + return 0; + } + + avctx->thread_opaque = fctx = av_mallocz(sizeof(FrameThreadContext)); + + fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count); + pthread_mutex_init(&fctx->buffer_mutex, NULL); + fctx->delaying = 1; + + for (i = 0; i < thread_count; i++) { + AVCodecContext *copy = av_malloc(sizeof(AVCodecContext)); + PerThreadContext *p = &fctx->threads[i]; + + pthread_mutex_init(&p->mutex, NULL); + pthread_mutex_init(&p->progress_mutex, NULL); + pthread_cond_init(&p->input_cond, NULL); + pthread_cond_init(&p->progress_cond, NULL); + pthread_cond_init(&p->output_cond, NULL); + + p->parent = fctx; + p->avctx = copy; + + if (!copy) { + err = AVERROR(ENOMEM); + goto error; + } + + *copy = *src; + copy->thread_opaque = p; + copy->pkt = &p->avpkt; + + if (!i) { + src = copy; + + if (codec->init) + err = codec->init(copy); + + update_context_from_thread(avctx, copy, 1); + } else { + copy->priv_data = av_malloc(codec->priv_data_size); + if (!copy->priv_data) { + err = AVERROR(ENOMEM); + goto error; + } + memcpy(copy->priv_data, src->priv_data, codec->priv_data_size); + copy->internal = av_malloc(sizeof(AVCodecInternal)); + if (!copy->internal) { + err = AVERROR(ENOMEM); + goto error; + } + *copy->internal = *src->internal; + copy->internal->is_copy = 1; + + if (codec->init_thread_copy) + err = codec->init_thread_copy(copy); + } + + if (err) goto error; + + err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p)); + p->thread_init= !err; + if(!p->thread_init) + goto error; + } + + return 0; + +error: + frame_thread_free(avctx, i+1); + + return err; +} + +void ff_thread_flush(AVCodecContext *avctx) +{ + int i; + FrameThreadContext *fctx = avctx->thread_opaque; + + if (!avctx->thread_opaque) return; + + park_frame_worker_threads(fctx, avctx->thread_count); + if (fctx->prev_thread) { + if (fctx->prev_thread != &fctx->threads[0]) + update_context_from_thread(fctx->threads[0].avctx, fctx->prev_thread->avctx, 0); + if (avctx->codec->flush) + avctx->codec->flush(fctx->threads[0].avctx); + } + + fctx->next_decoding = fctx->next_finished = 0; + fctx->delaying = 1; + fctx->prev_thread = NULL; + for (i = 0; i < avctx->thread_count; i++) { + PerThreadContext *p = &fctx->threads[i]; + // Make sure decode flush calls with size=0 won't return old frames + p->got_frame = 0; + av_frame_unref(&p->frame); + + release_delayed_buffers(p); + } +} + +int ff_thread_can_start_frame(AVCodecContext *avctx) +{ + PerThreadContext *p = avctx->thread_opaque; + if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP && + (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks && ( +#if FF_API_GET_BUFFER + avctx->get_buffer || +#endif + avctx->get_buffer2 != avcodec_default_get_buffer2)))) { + return 0; + } + return 1; +} + +static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int flags) +{ + PerThreadContext *p = avctx->thread_opaque; + int err; + + f->owner = avctx; + + ff_init_buffer_info(avctx, f->f); + + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) + return ff_get_buffer(avctx, f->f, flags); + + if (p->state != STATE_SETTING_UP && + (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks && ( +#if FF_API_GET_BUFFER + avctx->get_buffer || +#endif + avctx->get_buffer2 != avcodec_default_get_buffer2)))) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n"); + return -1; + } + + if (avctx->internal->allocate_progress) { + int *progress; + f->progress = av_buffer_alloc(2 * sizeof(int)); + if (!f->progress) { + return AVERROR(ENOMEM); + } + progress = (int*)f->progress->data; + + progress[0] = progress[1] = -1; + } + + pthread_mutex_lock(&p->parent->buffer_mutex); + + if (avctx->thread_safe_callbacks || ( +#if FF_API_GET_BUFFER + !avctx->get_buffer && +#endif + avctx->get_buffer2 == avcodec_default_get_buffer2)) { + err = ff_get_buffer(avctx, f->f, flags); + } else { + pthread_mutex_lock(&p->progress_mutex); + p->requested_frame = f->f; + p->requested_flags = flags; + p->state = STATE_GET_BUFFER; + pthread_cond_broadcast(&p->progress_cond); + + while (p->state != STATE_SETTING_UP) + pthread_cond_wait(&p->progress_cond, &p->progress_mutex); + + err = p->result; + + pthread_mutex_unlock(&p->progress_mutex); + + if (!avctx->codec->update_thread_context) + ff_thread_finish_setup(avctx); + } + + if (err) + av_buffer_unref(&f->progress); + + pthread_mutex_unlock(&p->parent->buffer_mutex); + + return err; +} + +int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) +{ + int ret = thread_get_buffer_internal(avctx, f, flags); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "thread_get_buffer() failed\n"); + return ret; +} + +void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) +{ + PerThreadContext *p = avctx->thread_opaque; + FrameThreadContext *fctx; + AVFrame *dst, *tmp; + int can_direct_free = !(avctx->active_thread_type & FF_THREAD_FRAME) || + avctx->thread_safe_callbacks || + ( +#if FF_API_GET_BUFFER + !avctx->get_buffer && +#endif + avctx->get_buffer2 == avcodec_default_get_buffer2); + + if (!f->f->data[0]) + return; + + if (avctx->debug & FF_DEBUG_BUFFERS) + av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); + + av_buffer_unref(&f->progress); + f->owner = NULL; + + if (can_direct_free) { + av_frame_unref(f->f); + return; + } + + fctx = p->parent; + pthread_mutex_lock(&fctx->buffer_mutex); + + if (p->num_released_buffers + 1 >= INT_MAX / sizeof(*p->released_buffers)) + goto fail; + tmp = av_fast_realloc(p->released_buffers, &p->released_buffers_allocated, + (p->num_released_buffers + 1) * + sizeof(*p->released_buffers)); + if (!tmp) + goto fail; + p->released_buffers = tmp; + + dst = &p->released_buffers[p->num_released_buffers]; + av_frame_move_ref(dst, f->f); + + p->num_released_buffers++; + +fail: + pthread_mutex_unlock(&fctx->buffer_mutex); +} + +/** + * Set the threading algorithms used. + * + * Threading requires more than one thread. + * Frame threading requires entire frames to be passed to the codec, + * and introduces extra decoding delay, so is incompatible with low_delay. + * + * @param avctx The context. + */ +static void validate_thread_parameters(AVCodecContext *avctx) +{ + int frame_threading_supported = (avctx->codec->capabilities & CODEC_CAP_FRAME_THREADS) + && !(avctx->flags & CODEC_FLAG_TRUNCATED) + && !(avctx->flags & CODEC_FLAG_LOW_DELAY) + && !(avctx->flags2 & CODEC_FLAG2_CHUNKS); + if (avctx->thread_count == 1) { + avctx->active_thread_type = 0; + } else if (frame_threading_supported && (avctx->thread_type & FF_THREAD_FRAME)) { + avctx->active_thread_type = FF_THREAD_FRAME; + } else if (avctx->codec->capabilities & CODEC_CAP_SLICE_THREADS && + avctx->thread_type & FF_THREAD_SLICE) { + avctx->active_thread_type = FF_THREAD_SLICE; + } else if (!(avctx->codec->capabilities & CODEC_CAP_AUTO_THREADS)) { + avctx->thread_count = 1; + avctx->active_thread_type = 0; + } + + if (avctx->thread_count > MAX_AUTO_THREADS) + av_log(avctx, AV_LOG_WARNING, + "Application has requested %d threads. Using a thread count greater than %d is not recommended.\n", + avctx->thread_count, MAX_AUTO_THREADS); +} + +int ff_thread_init(AVCodecContext *avctx) +{ + if (avctx->thread_opaque) { + av_log(avctx, AV_LOG_ERROR, "avcodec_thread_init is ignored after avcodec_open\n"); + return -1; + } + +#if HAVE_W32THREADS + w32thread_init(); +#endif + + if (avctx->codec) { + validate_thread_parameters(avctx); + + if (avctx->active_thread_type&FF_THREAD_SLICE) + return thread_init(avctx); + else if (avctx->active_thread_type&FF_THREAD_FRAME) + return frame_thread_init(avctx); + } + + return 0; +} + +void ff_thread_free(AVCodecContext *avctx) +{ + if (avctx->active_thread_type&FF_THREAD_FRAME) + frame_thread_free(avctx, avctx->thread_count); + else + thread_free(avctx); +} diff --git a/ffmpeg/libavcodec/ptx.c b/ffmpeg/libavcodec/ptx.c new file mode 100644 index 0000000..37135c5 --- /dev/null +++ b/ffmpeg/libavcodec/ptx.c @@ -0,0 +1,93 @@ +/* + * V.Flash PTX (.ptx) image decoder + * Copyright (c) 2007 Ivo van Poorten + * + * 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" + +static int ptx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = avpkt->data + avpkt->size; + AVFrame * const p = data; + unsigned int offset, w, h, y, stride, bytes_per_pixel; + int ret; + uint8_t *ptr; + + if (buf_end - buf < 14) + return AVERROR_INVALIDDATA; + offset = AV_RL16(buf); + w = AV_RL16(buf+8); + h = AV_RL16(buf+10); + bytes_per_pixel = AV_RL16(buf+12) >> 3; + + if (bytes_per_pixel != 2) { + avpriv_request_sample(avctx, "Image format not RGB15"); + return AVERROR_PATCHWELCOME; + } + + avctx->pix_fmt = AV_PIX_FMT_BGR555LE; + + if (buf_end - buf < offset) + return AVERROR_INVALIDDATA; + if (offset != 0x2c) + avpriv_request_sample(avctx, "offset != 0x2c"); + + buf += offset; + + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) + return ret; + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + + ptr = p->data[0]; + stride = p->linesize[0]; + + for (y = 0; y < h && buf_end - buf >= w * bytes_per_pixel; y++) { + memcpy(ptr, buf, w*bytes_per_pixel); + ptr += stride; + buf += w*bytes_per_pixel; + } + + *got_frame = 1; + + if (y < h) { + av_log(avctx, AV_LOG_WARNING, "incomplete packet\n"); + return avpkt->size; + } + + return offset + w*h*bytes_per_pixel; +} + +AVCodec ff_ptx_decoder = { + .name = "ptx", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PTX, + .decode = ptx_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), +}; diff --git a/ffmpeg/libavcodec/put_bits.h b/ffmpeg/libavcodec/put_bits.h new file mode 100644 index 0000000..7320443 --- /dev/null +++ b/ffmpeg/libavcodec/put_bits.h @@ -0,0 +1,237 @@ +/* + * copyright (c) 2004 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 + */ + +/** + * @file + * bitstream writer API + */ + +#ifndef AVCODEC_PUT_BITS_H +#define AVCODEC_PUT_BITS_H + +#include +#include +#include + +#include "libavutil/bswap.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/avassert.h" +#include "mathops.h" +#include "config.h" + +typedef struct PutBitContext { + uint32_t bit_buf; + int bit_left; + uint8_t *buf, *buf_ptr, *buf_end; + int size_in_bits; +} PutBitContext; + +/** + * Initialize the PutBitContext s. + * + * @param buffer the buffer where to put bits + * @param buffer_size the size in bytes of buffer + */ +static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, + int buffer_size) +{ + if (buffer_size < 0) { + buffer_size = 0; + buffer = NULL; + } + + s->size_in_bits = 8 * buffer_size; + s->buf = buffer; + s->buf_end = s->buf + buffer_size; + s->buf_ptr = s->buf; + s->bit_left = 32; + s->bit_buf = 0; +} + +/** + * @return the total number of bits written to the bitstream. + */ +static inline int put_bits_count(PutBitContext *s) +{ + return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left; +} + +/** + * Pad the end of the output stream with zeros. + */ +static inline void flush_put_bits(PutBitContext *s) +{ +#ifndef BITSTREAM_WRITER_LE + if (s->bit_left < 32) + s->bit_buf <<= s->bit_left; +#endif + while (s->bit_left < 32) { + /* XXX: should test end of buffer */ +#ifdef BITSTREAM_WRITER_LE + *s->buf_ptr++ = s->bit_buf; + s->bit_buf >>= 8; +#else + *s->buf_ptr++ = s->bit_buf >> 24; + s->bit_buf <<= 8; +#endif + s->bit_left += 8; + } + s->bit_left = 32; + s->bit_buf = 0; +} + +#ifdef BITSTREAM_WRITER_LE +#define avpriv_align_put_bits align_put_bits_unsupported_here +#define avpriv_put_string ff_put_string_unsupported_here +#define avpriv_copy_bits avpriv_copy_bits_unsupported_here +#else +/** + * Pad the bitstream with zeros up to the next byte boundary. + */ +void avpriv_align_put_bits(PutBitContext *s); + +/** + * Put the string string in the bitstream. + * + * @param terminate_string 0-terminates the written string if value is 1 + */ +void avpriv_put_string(PutBitContext *pb, const char *string, + int terminate_string); + +/** + * Copy the content of src to the bitstream. + * + * @param length the number of bits of src to copy + */ +void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length); +#endif + +/** + * Write up to 31 bits into a bitstream. + * Use put_bits32 to write 32 bits. + */ +static inline void put_bits(PutBitContext *s, int n, unsigned int value) +{ + unsigned int bit_buf; + int bit_left; + + av_assert2(n <= 31 && value < (1U << n)); + + bit_buf = s->bit_buf; + bit_left = s->bit_left; + + /* XXX: optimize */ +#ifdef BITSTREAM_WRITER_LE + bit_buf |= value << (32 - bit_left); + if (n >= bit_left) { + av_assert2(s->buf_ptr+3buf_end); + AV_WL32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + bit_buf = (bit_left == 32) ? 0 : value >> bit_left; + bit_left += 32; + } + bit_left -= n; +#else + if (n < bit_left) { + bit_buf = (bit_buf << n) | value; + bit_left -= n; + } else { + bit_buf <<= bit_left; + bit_buf |= value >> (n - bit_left); + av_assert2(s->buf_ptr+3buf_end); + AV_WB32(s->buf_ptr, bit_buf); + s->buf_ptr += 4; + bit_left += 32 - n; + bit_buf = value; + } +#endif + + s->bit_buf = bit_buf; + s->bit_left = bit_left; +} + +static inline void put_sbits(PutBitContext *pb, int n, int32_t value) +{ + av_assert2(n >= 0 && n <= 31); + + put_bits(pb, n, value & ((1 << n) - 1)); +} + +/** + * Write exactly 32 bits into a bitstream. + */ +static void av_unused put_bits32(PutBitContext *s, uint32_t value) +{ + int lo = value & 0xffff; + int hi = value >> 16; +#ifdef BITSTREAM_WRITER_LE + put_bits(s, 16, lo); + put_bits(s, 16, hi); +#else + put_bits(s, 16, hi); + put_bits(s, 16, lo); +#endif +} + +/** + * Return the pointer to the byte where the bitstream writer will put + * the next bit. + */ +static inline uint8_t *put_bits_ptr(PutBitContext *s) +{ + return s->buf_ptr; +} + +/** + * Skip the given number of bytes. + * PutBitContext must be flushed & aligned to a byte boundary before calling this. + */ +static inline void skip_put_bytes(PutBitContext *s, int n) +{ + av_assert2((put_bits_count(s) & 7) == 0); + av_assert2(s->bit_left == 32); + s->buf_ptr += n; +} + +/** + * Skip the given number of bits. + * Must only be used if the actual values in the bitstream do not matter. + * If n is 0 the behavior is undefined. + */ +static inline void skip_put_bits(PutBitContext *s, int n) +{ + s->bit_left -= n; + s->buf_ptr -= 4 * (s->bit_left >> 5); + s->bit_left &= 31; +} + +/** + * Change the end of the buffer. + * + * @param size the new size in bytes of the buffer where to put bits + */ +static inline void set_put_bits_buffer_size(PutBitContext *s, int size) +{ + s->buf_end = s->buf + size; +} + +#endif /* AVCODEC_PUT_BITS_H */ diff --git a/ffmpeg/libavcodec/qcelpdata.h b/ffmpeg/libavcodec/qcelpdata.h new file mode 100644 index 0000000..7ddeed4 --- /dev/null +++ b/ffmpeg/libavcodec/qcelpdata.h @@ -0,0 +1,552 @@ +/* + * QCELP decoder + * Copyright (c) 2007 Reynaldo H. Verdejo Pinochet + * + * 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 + */ + +#ifndef AVCODEC_QCELPDATA_H +#define AVCODEC_QCELPDATA_H + +/** + * @file + * Data tables for the QCELP decoder + * @author Reynaldo H. Verdejo Pinochet + * @remark FFmpeg merging spearheaded by Kenan Gillet + * @remark Development mentored by Benjamin Larson + */ + +#include +#include +#include "libavutil/common.h" + +/** + * QCELP unpacked data frame + */ +typedef struct QCELPFrame { +/// @name QCELP excitation codebook parameters +/// @{ + uint8_t cbsign[16]; ///< sign of the codebook gain for each codebook subframe + uint8_t cbgain[16]; ///< unsigned codebook gain for each codebook subframe + uint8_t cindex[16]; ///< codebook index for each codebook subframe +/// @} + +/// @name QCELP pitch prediction parameters +/// @{ + uint8_t plag[4]; ///< pitch lag for each pitch subframe + uint8_t pfrac[4]; ///< fractional pitch lag for each pitch subframe + uint8_t pgain[4]; ///< pitch gain for each pitch subframe +/// @} + + /** + * line spectral pair frequencies (LSP) for RATE_OCTAVE, + * line spectral pair frequencies grouped into five vectors + * of dimension two (LSPV) for other rates + */ + uint8_t lspv[10]; + + /** + * reserved bits only present in bitrate 1, 1/4 and 1/8 packets + */ + uint8_t reserved; +} QCELPFrame; + +/** + * pre-calculated table for hammsinc function + * Only half of the table is needed because of symmetry. + * + * TIA/EIA/IS-733 2.4.5.2-2/3 + */ +static const float qcelp_hammsinc_table[4] = { -0.006822, 0.041249, -0.143459, 0.588863}; + +typedef struct QCELPBitmap { + uint8_t index; /**< index into the QCELPContext structure */ + uint8_t bitpos; /**< position of the lowest bit in the value's byte */ + uint8_t bitlen; /**< number of bits to read */ +} QCELPBitmap; + +#define QCELP_OF(variable, bit, len) {offsetof(QCELPFrame, variable), bit, len} + +/** + * bitmap unpacking tables for RATE_FULL + * + * TIA/EIA/IS-733 Table 2.4.7.1-1 + */ +static const QCELPBitmap qcelp_rate_full_bitmap[] = { + // start on bit + QCELP_OF(lspv [ 2], 0, 3), // 265 + QCELP_OF(lspv [ 1], 0, 7), // 262 + QCELP_OF(lspv [ 0], 0, 6), // 255 + QCELP_OF(lspv [ 4], 0, 6), // 249 + QCELP_OF(lspv [ 3], 0, 6), // 243 + QCELP_OF(lspv [ 2], 3, 4), // 237 + QCELP_OF(cbsign[ 0], 0, 1), // 233 + QCELP_OF(cbgain[ 0], 0, 4), // 232 + QCELP_OF(pfrac [ 0], 0, 1), // 228 + QCELP_OF(plag [ 0], 0, 7), // 227 + QCELP_OF(pgain [ 0], 0, 3), // 220 + QCELP_OF(cindex[ 1], 0, 4), // 217 + QCELP_OF(cbsign[ 1], 0, 1), // 213 + QCELP_OF(cbgain[ 1], 0, 4), // 212 + QCELP_OF(cindex[ 0], 0, 7), // 208 + QCELP_OF(cbgain[ 3], 0, 1), // 201 + QCELP_OF(cindex[ 2], 0, 7), // 200 + QCELP_OF(cbsign[ 2], 0, 1), // 193 + QCELP_OF(cbgain[ 2], 0, 4), // 192 + QCELP_OF(cindex[ 1], 4, 3), // 188 + QCELP_OF(plag [ 1], 0, 3), // 185 + QCELP_OF(pgain [ 1], 0, 3), // 182 + QCELP_OF(cindex[ 3], 0, 7), // 179 + QCELP_OF(cbsign[ 3], 0, 1), // 172 + QCELP_OF(cbgain[ 3], 1, 2), // 171 + QCELP_OF(cindex[ 4], 0, 6), // 169 + QCELP_OF(cbsign[ 4], 0, 1), // 163 + QCELP_OF(cbgain[ 4], 0, 4), // 162 + QCELP_OF(pfrac [ 1], 0, 1), // 158 + QCELP_OF(plag [ 1], 3, 4), // 157 + QCELP_OF(cbgain[ 6], 0, 3), // 153 + QCELP_OF(cindex[ 5], 0, 7), // 150 + QCELP_OF(cbsign[ 5], 0, 1), // 143 + QCELP_OF(cbgain[ 5], 0, 4), // 142 + QCELP_OF(cindex[ 4], 6, 1), // 138 + QCELP_OF(cindex[ 7], 0, 3), // 137 + QCELP_OF(cbsign[ 7], 0, 1), // 134 + QCELP_OF(cbgain[ 7], 0, 3), // 133 + QCELP_OF(cindex[ 6], 0, 7), // 130 + QCELP_OF(cbsign[ 6], 0, 1), // 123 + QCELP_OF(cbgain[ 6], 3, 1), // 122 + QCELP_OF(cbgain[ 8], 0, 1), // 121 + QCELP_OF(pfrac [ 2], 0, 1), // 120 + QCELP_OF(plag [ 2], 0, 7), // 119 + QCELP_OF(pgain [ 2], 0, 3), // 112 + QCELP_OF(cindex[ 7], 3, 4), // 109 + QCELP_OF(cbsign[ 9], 0, 1), // 105 + QCELP_OF(cbgain[ 9], 0, 4), // 104 + QCELP_OF(cindex[ 8], 0, 7), // 100 + QCELP_OF(cbsign[ 8], 0, 1), // 93 + QCELP_OF(cbgain[ 8], 1, 3), // 92 + QCELP_OF(cindex[10], 0, 4), // 89 + QCELP_OF(cbsign[10], 0, 1), // 85 + QCELP_OF(cbgain[10], 0, 4), // 84 + QCELP_OF(cindex[ 9], 0, 7), // 80 + QCELP_OF(pgain [ 3], 0, 2), // 73 + QCELP_OF(cindex[11], 0, 7), // 71 + QCELP_OF(cbsign[11], 0, 1), // 64 + QCELP_OF(cbgain[11], 0, 3), // 63 + QCELP_OF(cindex[10], 4, 3), // 60 + QCELP_OF(cindex[12], 0, 2), // 57 + QCELP_OF(cbsign[12], 0, 1), // 55 + QCELP_OF(cbgain[12], 0, 4), // 54 + QCELP_OF(pfrac [ 3], 0, 1), // 50 + QCELP_OF(plag [ 3], 0, 7), // 49 + QCELP_OF(pgain [ 3], 2, 1), // 42 + QCELP_OF(cindex[13], 0, 6), // 41 + QCELP_OF(cbsign[13], 0, 1), // 35 + QCELP_OF(cbgain[13], 0, 4), // 34 + QCELP_OF(cindex[12], 2, 5), // 30 + QCELP_OF(cbgain[15], 0, 3), // 25 + QCELP_OF(cindex[14], 0, 7), // 22 + QCELP_OF(cbsign[14], 0, 1), // 15 + QCELP_OF(cbgain[14], 0, 4), // 14 + QCELP_OF(cindex[13], 6, 1), // 10 + QCELP_OF(reserved, 0, 2), // 9 + QCELP_OF(cindex[15], 0, 7), // 7 + QCELP_OF(cbsign[15], 0, 1) // 0 +}; + +/** + * bitmap unpacking tables for RATE_HALF + * + * TIA/EIA/IS-733 Table 2.4.7.2-1 + */ +static const QCELPBitmap qcelp_rate_half_bitmap[] = { + // start on bit + QCELP_OF(lspv [2], 0, 3), // 123 + QCELP_OF(lspv [1], 0, 7), // 120 + QCELP_OF(lspv [0], 0, 6), // 113 + QCELP_OF(lspv [4], 0, 6), // 107 + QCELP_OF(lspv [3], 0, 6), // 101 + QCELP_OF(lspv [2], 3, 4), // 95 + QCELP_OF(cbsign[0], 0, 1), // 91 + QCELP_OF(cbgain[0], 0, 4), // 90 + QCELP_OF(pfrac [0], 0, 1), // 86 + QCELP_OF(plag [0], 0, 7), // 85 + QCELP_OF(pgain [0], 0, 3), // 78 + QCELP_OF(plag [1], 0, 6), // 75 + QCELP_OF(pgain [1], 0, 3), // 69 + QCELP_OF(cindex[0], 0, 7), // 66 + QCELP_OF(pgain [2], 0, 2), // 59 + QCELP_OF(cindex[1], 0, 7), // 57 + QCELP_OF(cbsign[1], 0, 1), // 50 + QCELP_OF(cbgain[1], 0, 4), // 49 + QCELP_OF(pfrac [1], 0, 1), // 45 + QCELP_OF(plag [1], 6, 1), // 44 + QCELP_OF(cindex[2], 0, 2), // 43 + QCELP_OF(cbsign[2], 0, 1), // 41 + QCELP_OF(cbgain[2], 0, 4), // 40 + QCELP_OF(pfrac [2], 0, 1), // 36 + QCELP_OF(plag [2], 0, 7), // 35 + QCELP_OF(pgain [2], 2, 1), // 28 + QCELP_OF(pfrac [3], 0, 1), // 27 + QCELP_OF(plag [3], 0, 7), // 26 + QCELP_OF(pgain [3], 0, 3), // 19 + QCELP_OF(cindex[2], 2, 5), // 16 + QCELP_OF(cindex[3], 0, 7), // 11 + QCELP_OF(cbsign[3], 0, 1), // 4 + QCELP_OF(cbgain[3], 0, 4) // 3 +}; + +/** + * bitmap unpacking tables for RATE_QUARTER + * + * TIA/EIA/IS-733 Table 2.4.7.3-1 + */ +static const QCELPBitmap qcelp_rate_quarter_bitmap[] = { + // start on bit + QCELP_OF(lspv [2], 0, 3), // 53 + QCELP_OF(lspv [1], 0, 7), // 50 + QCELP_OF(lspv [0], 0, 6), // 43 + QCELP_OF(lspv [4], 0, 6), // 37 + QCELP_OF(lspv [3], 0, 6), // 31 + QCELP_OF(lspv [2], 3, 4), // 25 + QCELP_OF(cbgain[3], 0, 4), // 21 + QCELP_OF(cbgain[2], 0, 4), // 17 + QCELP_OF(cbgain[1], 0, 4), // 13 + QCELP_OF(cbgain[0], 0, 4), // 9 + QCELP_OF(reserved, 0, 2), // 5 + QCELP_OF(cbgain[4], 0, 4) // 3 +}; + +/** + * bitmap unpacking tables for RATE_OCTAVE + * + * trick: CBSEED is written into QCELPContext.cbsign[15], + * which is not used for RATE_OCTAVE. + * CBSEED is only used to ensure the occurrence of random bit + * patterns in the 16 first bits that are used as the seed. + * + * TIA/EIA/IS-733 Table 2.4.7.4-1 + */ +static const QCELPBitmap qcelp_rate_octave_bitmap[] = { + // start on bit + QCELP_OF(cbsign[15], 3, 1), // 19 + QCELP_OF(lspv [0], 0, 1), // 18 + QCELP_OF(lspv [1], 0, 1), // 17 + QCELP_OF(lspv [2], 0, 1), // 16 + QCELP_OF(cbsign[15], 2, 1), // 15 + QCELP_OF(lspv [3], 0, 1), // 14 + QCELP_OF(lspv [4], 0, 1), // 13 + QCELP_OF(lspv [5], 0, 1), // 12 + QCELP_OF(cbsign[15], 1, 1), // 11 + QCELP_OF(lspv [6], 0, 1), // 10 + QCELP_OF(lspv [7], 0, 1), // 9 + QCELP_OF(lspv [8], 0, 1), // 8 + QCELP_OF(cbsign[15], 0, 1), // 7 + QCELP_OF(lspv [9], 0, 1), // 6 + QCELP_OF(cbgain [0], 0, 2), // 5 + QCELP_OF(reserved, 0, 4) // 3 +}; + +/** + * position of the bitmapping data for each packet type in + * the QCELPContext + */ +static const QCELPBitmap * const qcelp_unpacking_bitmaps_per_rate[5] = { + NULL, ///< for SILENCE rate + qcelp_rate_octave_bitmap, + qcelp_rate_quarter_bitmap, + qcelp_rate_half_bitmap, + qcelp_rate_full_bitmap, +}; + +static const uint16_t qcelp_unpacking_bitmaps_lengths[5] = { + 0, ///< for SILENCE rate + FF_ARRAY_ELEMS(qcelp_rate_octave_bitmap), + FF_ARRAY_ELEMS(qcelp_rate_quarter_bitmap), + FF_ARRAY_ELEMS(qcelp_rate_half_bitmap), + FF_ARRAY_ELEMS(qcelp_rate_full_bitmap), +}; + +typedef uint16_t qcelp_vector[2]; + +/** + * LSP vector quantization tables in x*10000 form + * + * TIA/EIA/IS-733 tables 2.4.3.2.6.3-1 through 2.4.3.2.6.3-5 + */ + +static const qcelp_vector qcelp_lspvq1[64]= { +{ 327, 118},{ 919, 111},{ 427, 440},{1327, 185}, +{ 469, 50},{1272, 91},{ 892, 59},{1771, 193}, +{ 222, 158},{1100, 127},{ 827, 55},{ 978, 791}, +{ 665, 47},{ 700,1401},{ 670, 859},{1913,1048}, +{ 471, 215},{1046, 125},{ 645, 298},{1599, 160}, +{ 593, 39},{1187, 462},{ 749, 341},{1520, 511}, +{ 290, 792},{ 909, 362},{ 753, 81},{1111,1058}, +{ 519, 253},{ 828, 839},{ 685, 541},{1421,1258}, +{ 386, 130},{ 962, 119},{ 542, 387},{1431, 185}, +{ 526, 51},{1175, 260},{ 831, 167},{1728, 510}, +{ 273, 437},{1172, 113},{ 771, 144},{1122, 751}, +{ 619, 119},{ 492,1276},{ 658, 695},{1882, 615}, +{ 415, 200},{1018, 88},{ 681, 339},{1436, 325}, +{ 555, 122},{1042, 485},{ 826, 345},{1374, 743}, +{ 383,1018},{1005, 358},{ 704, 86},{1301, 586}, +{ 597, 241},{ 832, 621},{ 555, 573},{1504, 839}}; + +static const qcelp_vector qcelp_lspvq2[128]= { +{ 255, 293},{ 904, 219},{ 151,1211},{1447, 498}, +{ 470, 253},{1559, 177},{1547, 994},{2394, 242}, +{ 91, 813},{ 857, 590},{ 934,1326},{1889, 282}, +{ 813, 472},{1057,1494},{ 450,3315},{2163,1895}, +{ 538, 532},{1399, 218},{ 146,1552},{1755, 626}, +{ 822, 202},{1299, 663},{ 706,1732},{2656, 401}, +{ 418, 745},{ 762,1038},{ 583,1748},{1746,1285}, +{ 527,1169},{1314, 830},{ 556,2116},{1073,2321}, +{ 297, 570},{ 981, 403},{ 468,1103},{1740, 243}, +{ 725, 179},{1255, 474},{1374,1362},{1922, 912}, +{ 285, 947},{ 930, 700},{ 593,1372},{1909, 576}, +{ 588, 916},{1110,1116},{ 224,2719},{1633,2220}, +{ 402, 520},{1061, 448},{ 402,1352},{1499, 775}, +{ 664, 589},{1081, 727},{ 801,2206},{2165,1157}, +{ 566, 802},{ 911,1116},{ 306,1703},{1792, 836}, +{ 655, 999},{1061,1038},{ 298,2089},{1110,1753}, +{ 361, 311},{ 970, 239},{ 265,1231},{1495, 573}, +{ 566, 262},{1569, 293},{1341,1144},{2271, 544}, +{ 214, 877},{ 847, 719},{ 794,1384},{2067, 274}, +{ 703, 688},{1099,1306},{ 391,2947},{2024,1670}, +{ 471, 525},{1245, 290},{ 264,1557},{1568, 807}, +{ 718, 399},{1193, 685},{ 883,1594},{2729, 764}, +{ 500, 754},{ 809,1108},{ 541,1648},{1523,1385}, +{ 614,1196},{1209, 847},{ 345,2242},{1442,1747}, +{ 199, 560},{1092, 194},{ 349,1253},{1653, 507}, +{ 625, 354},{1376, 431},{1187,1465},{2164, 872}, +{ 360, 974},{1008, 698},{ 704,1346},{2114, 452}, +{ 720, 816},{1240,1089},{ 439,2475},{1498,2040}, +{ 336, 718},{1213, 187},{ 451,1450},{1368, 885}, +{ 592, 578},{1131, 531},{ 861,1855},{1764,1500}, +{ 444, 970},{ 935, 903},{ 424,1687},{1633,1102}, +{ 793, 897},{1060, 897},{ 185,2011},{1205,1855}}; + +static const qcelp_vector qcelp_lspvq3[128]= { +{ 225, 283},{1296, 355},{ 543, 343},{2073, 274}, +{ 204,1099},{1562, 523},{1388, 161},{2784, 274}, +{ 112, 849},{1870, 175},{1189, 160},{1490,1088}, +{ 969,1115},{ 659,3322},{1158,1073},{3183,1363}, +{ 517, 223},{1740, 223},{ 704, 387},{2637, 234}, +{ 692,1005},{1287,1610},{ 952, 532},{2393, 646}, +{ 490, 552},{1619, 657},{ 845, 670},{1784,2280}, +{ 191,1775},{ 272,2868},{ 942, 952},{2628,1479}, +{ 278, 579},{1565, 218},{ 814, 180},{2379, 187}, +{ 276,1444},{1199,1223},{1200, 349},{3009, 307}, +{ 312, 844},{1898, 306},{ 863, 470},{1685,1241}, +{ 513,1727},{ 711,2233},{1085, 864},{3398, 527}, +{ 414, 440},{1356, 612},{ 964, 147},{2173, 738}, +{ 465,1292},{ 877,1749},{1104, 689},{2105,1311}, +{ 580, 864},{1895, 752},{ 652, 609},{1485,1699}, +{ 514,1400},{ 386,2131},{ 933, 798},{2473, 986}, +{ 334, 360},{1375, 398},{ 621, 276},{2183, 280}, +{ 311,1114},{1382, 807},{1284, 175},{2605, 636}, +{ 230, 816},{1739, 408},{1074, 176},{1619,1120}, +{ 784,1371},{ 448,3050},{1189, 880},{3039,1165}, +{ 424, 241},{1672, 186},{ 815, 333},{2432, 324}, +{ 584,1029},{1137,1546},{1015, 585},{2198, 995}, +{ 574, 581},{1746, 647},{ 733, 740},{1938,1737}, +{ 347,1710},{ 373,2429},{ 787,1061},{2439,1438}, +{ 185, 536},{1489, 178},{ 703, 216},{2178, 487}, +{ 154,1421},{1414, 994},{1103, 352},{3072, 473}, +{ 408, 819},{2055, 168},{ 998, 354},{1917,1140}, +{ 665,1799},{ 993,2213},{1234, 631},{3003, 762}, +{ 373, 620},{1518, 425},{ 913, 300},{1966, 836}, +{ 402,1185},{ 948,1385},{1121, 555},{1802,1509}, +{ 474, 886},{1888, 610},{ 739, 585},{1231,2379}, +{ 661,1335},{ 205,2211},{ 823, 822},{2480,1179}}; + +static const qcelp_vector qcelp_lspvq4[64]= { +{ 348, 311},{ 812,1145},{ 552, 461},{1826, 263}, +{ 601, 675},{1730, 172},{1523, 193},{2449, 277}, +{ 334, 668},{ 805,1441},{1319, 207},{1684, 910}, +{ 582,1318},{1403,1098},{ 979, 832},{2700,1359}, +{ 624, 228},{1292, 979},{ 800, 195},{2226, 285}, +{ 730, 862},{1537, 601},{1115, 509},{2720, 354}, +{ 218,1167},{1212,1538},{1074, 247},{1674,1710}, +{ 322,2142},{1263, 777},{ 981, 556},{2119,1710}, +{ 193, 596},{1035, 957},{ 694, 397},{1997, 253}, +{ 743, 603},{1584, 321},{1346, 346},{2221, 708}, +{ 451, 732},{1040,1415},{1184, 230},{1853, 919}, +{ 310,1661},{1625, 706},{ 856, 843},{2902, 702}, +{ 467, 348},{1108,1048},{ 859, 306},{1964, 463}, +{ 560,1013},{1425, 533},{1142, 634},{2391, 879}, +{ 397,1084},{1345,1700},{ 976, 248},{1887,1189}, +{ 644,2087},{1262, 603},{ 877, 550},{2203,1307}}; + +static const qcelp_vector qcelp_lspvq5[64]= { +{ 360, 222},{ 820,1097},{ 601, 319},{1656, 198}, +{ 604, 513},{1552, 141},{1391, 155},{2474, 261}, +{ 269, 785},{1463, 646},{1123, 191},{2015, 223}, +{ 785, 844},{1202,1011},{ 980, 807},{3014, 793}, +{ 570, 180},{1135,1382},{ 778, 256},{1901, 179}, +{ 807, 622},{1461, 458},{1231, 178},{2028, 821}, +{ 387, 927},{1496,1004},{ 888, 392},{2246, 341}, +{ 295,1462},{1156, 694},{1022, 473},{2226,1364}, +{ 210, 478},{1029,1020},{ 722, 181},{1730, 251}, +{ 730, 488},{1465, 293},{1303, 326},{2595, 387}, +{ 458, 584},{1569, 742},{1029, 173},{1910, 495}, +{ 605,1159},{1268, 719},{ 973, 646},{2872, 428}, +{ 443, 334},{ 835,1465},{ 912, 138},{1716, 442}, +{ 620, 778},{1316, 450},{1186, 335},{1446,1665}, +{ 486,1050},{1675,1019},{ 880, 278},{2214, 202}, +{ 539,1564},{1142, 533},{ 984, 391},{2130,1089}}; + +static const qcelp_vector * const qcelp_lspvq[5] = { + qcelp_lspvq1, + qcelp_lspvq2, + qcelp_lspvq3, + qcelp_lspvq4, + qcelp_lspvq5 +}; + +/** + * the final gain scalefactor before clipping into a usable output float + */ +#define QCELP_SCALE 8192. + +/** + * table for computing Ga (decoded linear codebook gain magnitude) + * + * @note The table could fit in int16_t in x*8 form, but it seems + * to be slower on x86 + * + * TIA/EIA/IS-733 2.4.6.2.1-3 + */ + +static const float qcelp_g12ga[61] = { + 1.000/QCELP_SCALE, 1.125/QCELP_SCALE, 1.250/QCELP_SCALE, 1.375/QCELP_SCALE, + 1.625/QCELP_SCALE, 1.750/QCELP_SCALE, 2.000/QCELP_SCALE, 2.250/QCELP_SCALE, + 2.500/QCELP_SCALE, 2.875/QCELP_SCALE, 3.125/QCELP_SCALE, 3.500/QCELP_SCALE, + 4.000/QCELP_SCALE, 4.500/QCELP_SCALE, 5.000/QCELP_SCALE, 5.625/QCELP_SCALE, + 6.250/QCELP_SCALE, 7.125/QCELP_SCALE, 8.000/QCELP_SCALE, 8.875/QCELP_SCALE, + 10.000/QCELP_SCALE, 11.250/QCELP_SCALE, 12.625/QCELP_SCALE, 14.125/QCELP_SCALE, + 15.875/QCELP_SCALE, 17.750/QCELP_SCALE, 20.000/QCELP_SCALE, 22.375/QCELP_SCALE, + 25.125/QCELP_SCALE, 28.125/QCELP_SCALE, 31.625/QCELP_SCALE, 35.500/QCELP_SCALE, + 39.750/QCELP_SCALE, 44.625/QCELP_SCALE, 50.125/QCELP_SCALE, 56.250/QCELP_SCALE, + 63.125/QCELP_SCALE, 70.750/QCELP_SCALE, 79.375/QCELP_SCALE, 89.125/QCELP_SCALE, + 100.000/QCELP_SCALE, 112.250/QCELP_SCALE, 125.875/QCELP_SCALE, 141.250/QCELP_SCALE, + 158.500/QCELP_SCALE, 177.875/QCELP_SCALE, 199.500/QCELP_SCALE, 223.875/QCELP_SCALE, + 251.250/QCELP_SCALE, 281.875/QCELP_SCALE, 316.250/QCELP_SCALE, 354.875/QCELP_SCALE, + 398.125/QCELP_SCALE, 446.625/QCELP_SCALE, 501.125/QCELP_SCALE, 562.375/QCELP_SCALE, + 631.000/QCELP_SCALE, 708.000/QCELP_SCALE, 794.375/QCELP_SCALE, 891.250/QCELP_SCALE, + 1000.000/QCELP_SCALE}; + +/** + * circular codebook for rate 1 frames in x*100 form + * + * TIA/EIA/IS-733 2.4.6.1-2 + */ +static const int16_t qcelp_rate_full_codebook[128] = { + 10, -65, -59, 12, 110, 34, -134, 157, + 104, -84, -34, -115, 23, -101, 3, 45, + -101, -16, -59, 28, -45, 134, -67, 22, + 61, -29, 226, -26, -55, -179, 157, -51, + -220, -93, -37, 60, 118, 74, -48, -95, + -181, 111, 36, -52, -215, 78, -112, 39, + -17, -47, -223, 19, 12, -98, -142, 130, + 54, -127, 21, -12, 39, -48, 12, 128, + 6, -167, 82, -102, -79, 55, -44, 48, + -20, -53, 8, -61, 11, -70, -157, -168, + 20, -56, -74, 78, 33, -63, -173, -2, + -75, -53, -146, 77, 66, -29, 9, -75, + 65, 119, -43, 76, 233, 98, 125, -156, + -27, 78, -9, 170, 176, 143, -148, -7, + 27, -136, 5, 27, 18, 139, 204, 7, + -184, -197, 52, -3, 78, -189, 8, -65 +}; +#define QCELP_RATE_FULL_CODEBOOK_RATIO .01 + +/** + * circular codebook for rate 1/2 frames in x*2 form + * + * TIA/EIA/IS-733 2.4.6.1-1 + */ +static const int8_t qcelp_rate_half_codebook[128] = { + 0, -4, 0, -3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, -3, -2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 4, 0, + 0, 3, 2, 0, 3, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, + -3, 3, 0, 0, -2, 0, 3, 0, + 0, 0, 0, 0, 0, 0, -5, 0, + 0, 0, 0, 3, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 6, -3, -4, 0, -3, -3, + 3, -3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; +#define QCELP_RATE_HALF_CODEBOOK_RATIO 0.5 + +/** + * sqrt(1.887) is the maximum of the pseudorandom + * white sequence used to generate the scaled codebook + * vector for bitrate 1/4. + * + * TIA/EIA/IS-733 2.4.8.1.2 + */ +#define QCELP_SQRT1887 1.373681186 + +/** + * table for impulse response of BPF used to filter + * the white excitation for bitrate 1/4 synthesis + * + * Only half the tables are needed because of symmetry. + * + * TIA/EIA/IS-733 2.4.8.1.2-1.1 + */ +static const double qcelp_rnd_fir_coefs[11] = { + -1.344519e-1, 1.735384e-2, -6.905826e-2, 2.434368e-2, + -8.210701e-2, 3.041388e-2, -9.251384e-2, 3.501983e-2, + -9.918777e-2, 3.749518e-2, 8.985137e-1 +}; + +/** + * This spread factor is used, for bitrate 1/8 and I_F_Q, + * to force the LSP frequencies to be at least 80 Hz apart. + * + * TIA/EIA/IS-733 2.4.3.3.2 + */ +#define QCELP_LSP_SPREAD_FACTOR 0.02 + +/** + * predictor coefficient for the conversion of LSP codes + * to LSP frequencies for 1/8 and I_F_Q + * + * TIA/EIA/IS-733 2.4.3.2.7-2 + */ +#define QCELP_LSP_OCTAVE_PREDICTOR 29.0/32 + +/** + * initial coefficient to perform bandwidth expansion on LPC + * + * @note: 0.9883 looks like an approximation of 253/256. + * + * TIA/EIA/IS-733 2.4.3.3.6 6 + */ +#define QCELP_BANDWIDTH_EXPANSION_COEFF 0.9883 + +#endif /* AVCODEC_QCELPDATA_H */ diff --git a/ffmpeg/libavcodec/qcelpdec.c b/ffmpeg/libavcodec/qcelpdec.c new file mode 100644 index 0000000..f8fe85d --- /dev/null +++ b/ffmpeg/libavcodec/qcelpdec.c @@ -0,0 +1,797 @@ +/* + * QCELP decoder + * Copyright (c) 2007 Reynaldo H. Verdejo Pinochet + * + * 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 + */ + +/** + * @file + * QCELP decoder + * @author Reynaldo H. Verdejo Pinochet + * @remark FFmpeg merging spearheaded by Kenan Gillet + * @remark Development mentored by Benjamin Larson + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "qcelpdata.h" +#include "celp_filters.h" +#include "acelp_filters.h" +#include "acelp_vectors.h" +#include "lsp.h" + +#undef NDEBUG +#include + +typedef enum { + I_F_Q = -1, /**< insufficient frame quality */ + SILENCE, + RATE_OCTAVE, + RATE_QUARTER, + RATE_HALF, + RATE_FULL +} qcelp_packet_rate; + +typedef struct { + GetBitContext gb; + qcelp_packet_rate bitrate; + QCELPFrame frame; /**< unpacked data frame */ + + uint8_t erasure_count; + uint8_t octave_count; /**< count the consecutive RATE_OCTAVE frames */ + float prev_lspf[10]; + float predictor_lspf[10];/**< LSP predictor for RATE_OCTAVE and I_F_Q */ + float pitch_synthesis_filter_mem[303]; + float pitch_pre_filter_mem[303]; + float rnd_fir_filter_mem[180]; + float formant_mem[170]; + float last_codebook_gain; + int prev_g1[2]; + int prev_bitrate; + float pitch_gain[4]; + uint8_t pitch_lag[4]; + uint16_t first16bits; + uint8_t warned_buf_mismatch_bitrate; + + /* postfilter */ + float postfilter_synth_mem[10]; + float postfilter_agc_mem; + float postfilter_tilt_mem; +} QCELPContext; + +/** + * Initialize the speech codec according to the specification. + * + * TIA/EIA/IS-733 2.4.9 + */ +static av_cold int qcelp_decode_init(AVCodecContext *avctx) +{ + QCELPContext *q = avctx->priv_data; + int i; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + for (i = 0; i < 10; i++) + q->prev_lspf[i] = (i + 1) / 11.; + + return 0; +} + +/** + * Decode the 10 quantized LSP frequencies from the LSPV/LSP + * transmission codes of any bitrate and check for badly received packets. + * + * @param q the context + * @param lspf line spectral pair frequencies + * + * @return 0 on success, -1 if the packet is badly received + * + * TIA/EIA/IS-733 2.4.3.2.6.2-2, 2.4.8.7.3 + */ +static int decode_lspf(QCELPContext *q, float *lspf) +{ + int i; + float tmp_lspf, smooth, erasure_coeff; + const float *predictors; + + if (q->bitrate == RATE_OCTAVE || q->bitrate == I_F_Q) { + predictors = q->prev_bitrate != RATE_OCTAVE && + q->prev_bitrate != I_F_Q ? q->prev_lspf + : q->predictor_lspf; + + if (q->bitrate == RATE_OCTAVE) { + q->octave_count++; + + for (i = 0; i < 10; i++) { + q->predictor_lspf[i] = + lspf[i] = (q->frame.lspv[i] ? QCELP_LSP_SPREAD_FACTOR + : -QCELP_LSP_SPREAD_FACTOR) + + predictors[i] * QCELP_LSP_OCTAVE_PREDICTOR + + (i + 1) * ((1 - QCELP_LSP_OCTAVE_PREDICTOR) / 11); + } + smooth = q->octave_count < 10 ? .875 : 0.1; + } else { + erasure_coeff = QCELP_LSP_OCTAVE_PREDICTOR; + + assert(q->bitrate == I_F_Q); + + if (q->erasure_count > 1) + erasure_coeff *= q->erasure_count < 4 ? 0.9 : 0.7; + + for (i = 0; i < 10; i++) { + q->predictor_lspf[i] = + lspf[i] = (i + 1) * (1 - erasure_coeff) / 11 + + erasure_coeff * predictors[i]; + } + smooth = 0.125; + } + + // Check the stability of the LSP frequencies. + lspf[0] = FFMAX(lspf[0], QCELP_LSP_SPREAD_FACTOR); + for (i = 1; i < 10; i++) + lspf[i] = FFMAX(lspf[i], lspf[i - 1] + QCELP_LSP_SPREAD_FACTOR); + + lspf[9] = FFMIN(lspf[9], 1.0 - QCELP_LSP_SPREAD_FACTOR); + for (i = 9; i > 0; i--) + lspf[i - 1] = FFMIN(lspf[i - 1], lspf[i] - QCELP_LSP_SPREAD_FACTOR); + + // Low-pass filter the LSP frequencies. + ff_weighted_vector_sumf(lspf, lspf, q->prev_lspf, smooth, 1.0 - smooth, 10); + } else { + q->octave_count = 0; + + tmp_lspf = 0.; + for (i = 0; i < 5; i++) { + lspf[2 * i + 0] = tmp_lspf += qcelp_lspvq[i][q->frame.lspv[i]][0] * 0.0001; + lspf[2 * i + 1] = tmp_lspf += qcelp_lspvq[i][q->frame.lspv[i]][1] * 0.0001; + } + + // Check for badly received packets. + if (q->bitrate == RATE_QUARTER) { + if (lspf[9] <= .70 || lspf[9] >= .97) + return -1; + for (i = 3; i < 10; i++) + if (fabs(lspf[i] - lspf[i - 2]) < .08) + return -1; + } else { + if (lspf[9] <= .66 || lspf[9] >= .985) + return -1; + for (i = 4; i < 10; i++) + if (fabs(lspf[i] - lspf[i - 4]) < .0931) + return -1; + } + } + return 0; +} + +/** + * Convert codebook transmission codes to GAIN and INDEX. + * + * @param q the context + * @param gain array holding the decoded gain + * + * TIA/EIA/IS-733 2.4.6.2 + */ +static void decode_gain_and_index(QCELPContext *q, float *gain) +{ + int i, subframes_count, g1[16]; + float slope; + + if (q->bitrate >= RATE_QUARTER) { + switch (q->bitrate) { + case RATE_FULL: subframes_count = 16; break; + case RATE_HALF: subframes_count = 4; break; + default: subframes_count = 5; + } + for (i = 0; i < subframes_count; i++) { + g1[i] = 4 * q->frame.cbgain[i]; + if (q->bitrate == RATE_FULL && !((i + 1) & 3)) { + g1[i] += av_clip((g1[i - 1] + g1[i - 2] + g1[i - 3]) / 3 - 6, 0, 32); + } + + gain[i] = qcelp_g12ga[g1[i]]; + + if (q->frame.cbsign[i]) { + gain[i] = -gain[i]; + q->frame.cindex[i] = (q->frame.cindex[i] - 89) & 127; + } + } + + q->prev_g1[0] = g1[i - 2]; + q->prev_g1[1] = g1[i - 1]; + q->last_codebook_gain = qcelp_g12ga[g1[i - 1]]; + + if (q->bitrate == RATE_QUARTER) { + // Provide smoothing of the unvoiced excitation energy. + gain[7] = gain[4]; + gain[6] = 0.4 * gain[3] + 0.6 * gain[4]; + gain[5] = gain[3]; + gain[4] = 0.8 * gain[2] + 0.2 * gain[3]; + gain[3] = 0.2 * gain[1] + 0.8 * gain[2]; + gain[2] = gain[1]; + gain[1] = 0.6 * gain[0] + 0.4 * gain[1]; + } + } else if (q->bitrate != SILENCE) { + if (q->bitrate == RATE_OCTAVE) { + g1[0] = 2 * q->frame.cbgain[0] + + av_clip((q->prev_g1[0] + q->prev_g1[1]) / 2 - 5, 0, 54); + subframes_count = 8; + } else { + assert(q->bitrate == I_F_Q); + + g1[0] = q->prev_g1[1]; + switch (q->erasure_count) { + case 1 : break; + case 2 : g1[0] -= 1; break; + case 3 : g1[0] -= 2; break; + default: g1[0] -= 6; + } + if (g1[0] < 0) + g1[0] = 0; + subframes_count = 4; + } + // This interpolation is done to produce smoother background noise. + slope = 0.5 * (qcelp_g12ga[g1[0]] - q->last_codebook_gain) / subframes_count; + for (i = 1; i <= subframes_count; i++) + gain[i - 1] = q->last_codebook_gain + slope * i; + + q->last_codebook_gain = gain[i - 2]; + q->prev_g1[0] = q->prev_g1[1]; + q->prev_g1[1] = g1[0]; + } +} + +/** + * If the received packet is Rate 1/4 a further sanity check is made of the + * codebook gain. + * + * @param cbgain the unpacked cbgain array + * @return -1 if the sanity check fails, 0 otherwise + * + * TIA/EIA/IS-733 2.4.8.7.3 + */ +static int codebook_sanity_check_for_rate_quarter(const uint8_t *cbgain) +{ + int i, diff, prev_diff = 0; + + for (i = 1; i < 5; i++) { + diff = cbgain[i] - cbgain[i-1]; + if (FFABS(diff) > 10) + return -1; + else if (FFABS(diff - prev_diff) > 12) + return -1; + prev_diff = diff; + } + return 0; +} + +/** + * Compute the scaled codebook vector Cdn From INDEX and GAIN + * for all rates. + * + * The specification lacks some information here. + * + * TIA/EIA/IS-733 has an omission on the codebook index determination + * formula for RATE_FULL and RATE_HALF frames at section 2.4.8.1.1. It says + * you have to subtract the decoded index parameter from the given scaled + * codebook vector index 'n' to get the desired circular codebook index, but + * it does not mention that you have to clamp 'n' to [0-9] in order to get + * RI-compliant results. + * + * The reason for this mistake seems to be the fact they forgot to mention you + * have to do these calculations per codebook subframe and adjust given + * equation values accordingly. + * + * @param q the context + * @param gain array holding the 4 pitch subframe gain values + * @param cdn_vector array for the generated scaled codebook vector + */ +static void compute_svector(QCELPContext *q, const float *gain, + float *cdn_vector) +{ + int i, j, k; + uint16_t cbseed, cindex; + float *rnd, tmp_gain, fir_filter_value; + + switch (q->bitrate) { + case RATE_FULL: + for (i = 0; i < 16; i++) { + tmp_gain = gain[i] * QCELP_RATE_FULL_CODEBOOK_RATIO; + cindex = -q->frame.cindex[i]; + for (j = 0; j < 10; j++) + *cdn_vector++ = tmp_gain * qcelp_rate_full_codebook[cindex++ & 127]; + } + break; + case RATE_HALF: + for (i = 0; i < 4; i++) { + tmp_gain = gain[i] * QCELP_RATE_HALF_CODEBOOK_RATIO; + cindex = -q->frame.cindex[i]; + for (j = 0; j < 40; j++) + *cdn_vector++ = tmp_gain * qcelp_rate_half_codebook[cindex++ & 127]; + } + break; + case RATE_QUARTER: + cbseed = (0x0003 & q->frame.lspv[4]) << 14 | + (0x003F & q->frame.lspv[3]) << 8 | + (0x0060 & q->frame.lspv[2]) << 1 | + (0x0007 & q->frame.lspv[1]) << 3 | + (0x0038 & q->frame.lspv[0]) >> 3; + rnd = q->rnd_fir_filter_mem + 20; + for (i = 0; i < 8; i++) { + tmp_gain = gain[i] * (QCELP_SQRT1887 / 32768.0); + for (k = 0; k < 20; k++) { + cbseed = 521 * cbseed + 259; + *rnd = (int16_t) cbseed; + + // FIR filter + fir_filter_value = 0.0; + for (j = 0; j < 10; j++) + fir_filter_value += qcelp_rnd_fir_coefs[j] * + (rnd[-j] + rnd[-20+j]); + + fir_filter_value += qcelp_rnd_fir_coefs[10] * rnd[-10]; + *cdn_vector++ = tmp_gain * fir_filter_value; + rnd++; + } + } + memcpy(q->rnd_fir_filter_mem, q->rnd_fir_filter_mem + 160, + 20 * sizeof(float)); + break; + case RATE_OCTAVE: + cbseed = q->first16bits; + for (i = 0; i < 8; i++) { + tmp_gain = gain[i] * (QCELP_SQRT1887 / 32768.0); + for (j = 0; j < 20; j++) { + cbseed = 521 * cbseed + 259; + *cdn_vector++ = tmp_gain * (int16_t) cbseed; + } + } + break; + case I_F_Q: + cbseed = -44; // random codebook index + for (i = 0; i < 4; i++) { + tmp_gain = gain[i] * QCELP_RATE_FULL_CODEBOOK_RATIO; + for (j = 0; j < 40; j++) + *cdn_vector++ = tmp_gain * qcelp_rate_full_codebook[cbseed++ & 127]; + } + break; + case SILENCE: + memset(cdn_vector, 0, 160 * sizeof(float)); + break; + } +} + +/** + * Apply generic gain control. + * + * @param v_out output vector + * @param v_in gain-controlled vector + * @param v_ref vector to control gain of + * + * TIA/EIA/IS-733 2.4.8.3, 2.4.8.6 + */ +static void apply_gain_ctrl(float *v_out, const float *v_ref, const float *v_in) +{ + int i; + + for (i = 0; i < 160; i += 40) { + float res = avpriv_scalarproduct_float_c(v_ref + i, v_ref + i, 40); + ff_scale_vector_to_given_sum_of_squares(v_out + i, v_in + i, res, 40); + } +} + +/** + * Apply filter in pitch-subframe steps. + * + * @param memory buffer for the previous state of the filter + * - must be able to contain 303 elements + * - the 143 first elements are from the previous state + * - the next 160 are for output + * @param v_in input filter vector + * @param gain per-subframe gain array, each element is between 0.0 and 2.0 + * @param lag per-subframe lag array, each element is + * - between 16 and 143 if its corresponding pfrac is 0, + * - between 16 and 139 otherwise + * @param pfrac per-subframe boolean array, 1 if the lag is fractional, 0 + * otherwise + * + * @return filter output vector + */ +static const float *do_pitchfilter(float memory[303], const float v_in[160], + const float gain[4], const uint8_t *lag, + const uint8_t pfrac[4]) +{ + int i, j; + float *v_lag, *v_out; + const float *v_len; + + v_out = memory + 143; // Output vector starts at memory[143]. + + for (i = 0; i < 4; i++) { + if (gain[i]) { + v_lag = memory + 143 + 40 * i - lag[i]; + for (v_len = v_in + 40; v_in < v_len; v_in++) { + if (pfrac[i]) { // If it is a fractional lag... + for (j = 0, *v_out = 0.; j < 4; j++) + *v_out += qcelp_hammsinc_table[j] * (v_lag[j - 4] + v_lag[3 - j]); + } else + *v_out = *v_lag; + + *v_out = *v_in + gain[i] * *v_out; + + v_lag++; + v_out++; + } + } else { + memcpy(v_out, v_in, 40 * sizeof(float)); + v_in += 40; + v_out += 40; + } + } + + memmove(memory, memory + 160, 143 * sizeof(float)); + return memory + 143; +} + +/** + * Apply pitch synthesis filter and pitch prefilter to the scaled codebook vector. + * TIA/EIA/IS-733 2.4.5.2, 2.4.8.7.2 + * + * @param q the context + * @param cdn_vector the scaled codebook vector + */ +static void apply_pitch_filters(QCELPContext *q, float *cdn_vector) +{ + int i; + const float *v_synthesis_filtered, *v_pre_filtered; + + if (q->bitrate >= RATE_HALF || q->bitrate == SILENCE || + (q->bitrate == I_F_Q && (q->prev_bitrate >= RATE_HALF))) { + + if (q->bitrate >= RATE_HALF) { + // Compute gain & lag for the whole frame. + for (i = 0; i < 4; i++) { + q->pitch_gain[i] = q->frame.plag[i] ? (q->frame.pgain[i] + 1) * 0.25 : 0.0; + + q->pitch_lag[i] = q->frame.plag[i] + 16; + } + } else { + float max_pitch_gain; + + if (q->bitrate == I_F_Q) { + if (q->erasure_count < 3) + max_pitch_gain = 0.9 - 0.3 * (q->erasure_count - 1); + else + max_pitch_gain = 0.0; + } else { + assert(q->bitrate == SILENCE); + max_pitch_gain = 1.0; + } + for (i = 0; i < 4; i++) + q->pitch_gain[i] = FFMIN(q->pitch_gain[i], max_pitch_gain); + + memset(q->frame.pfrac, 0, sizeof(q->frame.pfrac)); + } + + // pitch synthesis filter + v_synthesis_filtered = do_pitchfilter(q->pitch_synthesis_filter_mem, + cdn_vector, q->pitch_gain, + q->pitch_lag, q->frame.pfrac); + + // pitch prefilter update + for (i = 0; i < 4; i++) + q->pitch_gain[i] = 0.5 * FFMIN(q->pitch_gain[i], 1.0); + + v_pre_filtered = do_pitchfilter(q->pitch_pre_filter_mem, + v_synthesis_filtered, + q->pitch_gain, q->pitch_lag, + q->frame.pfrac); + + apply_gain_ctrl(cdn_vector, v_synthesis_filtered, v_pre_filtered); + } else { + memcpy(q->pitch_synthesis_filter_mem, cdn_vector + 17, 143 * sizeof(float)); + memcpy(q->pitch_pre_filter_mem, cdn_vector + 17, 143 * sizeof(float)); + memset(q->pitch_gain, 0, sizeof(q->pitch_gain)); + memset(q->pitch_lag, 0, sizeof(q->pitch_lag)); + } +} + +/** + * Reconstruct LPC coefficients from the line spectral pair frequencies + * and perform bandwidth expansion. + * + * @param lspf line spectral pair frequencies + * @param lpc linear predictive coding coefficients + * + * @note: bandwidth_expansion_coeff could be precalculated into a table + * but it seems to be slower on x86 + * + * TIA/EIA/IS-733 2.4.3.3.5 + */ +static void lspf2lpc(const float *lspf, float *lpc) +{ + double lsp[10]; + double bandwidth_expansion_coeff = QCELP_BANDWIDTH_EXPANSION_COEFF; + int i; + + for (i = 0; i < 10; i++) + lsp[i] = cos(M_PI * lspf[i]); + + ff_acelp_lspd2lpc(lsp, lpc, 5); + + for (i = 0; i < 10; i++) { + lpc[i] *= bandwidth_expansion_coeff; + bandwidth_expansion_coeff *= QCELP_BANDWIDTH_EXPANSION_COEFF; + } +} + +/** + * Interpolate LSP frequencies and compute LPC coefficients + * for a given bitrate & pitch subframe. + * + * TIA/EIA/IS-733 2.4.3.3.4, 2.4.8.7.2 + * + * @param q the context + * @param curr_lspf LSP frequencies vector of the current frame + * @param lpc float vector for the resulting LPC + * @param subframe_num frame number in decoded stream + */ +static void interpolate_lpc(QCELPContext *q, const float *curr_lspf, + float *lpc, const int subframe_num) +{ + float interpolated_lspf[10]; + float weight; + + if (q->bitrate >= RATE_QUARTER) + weight = 0.25 * (subframe_num + 1); + else if (q->bitrate == RATE_OCTAVE && !subframe_num) + weight = 0.625; + else + weight = 1.0; + + if (weight != 1.0) { + ff_weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf, + weight, 1.0 - weight, 10); + lspf2lpc(interpolated_lspf, lpc); + } else if (q->bitrate >= RATE_QUARTER || + (q->bitrate == I_F_Q && !subframe_num)) + lspf2lpc(curr_lspf, lpc); + else if (q->bitrate == SILENCE && !subframe_num) + lspf2lpc(q->prev_lspf, lpc); +} + +static qcelp_packet_rate buf_size2bitrate(const int buf_size) +{ + switch (buf_size) { + case 35: return RATE_FULL; + case 17: return RATE_HALF; + case 8: return RATE_QUARTER; + case 4: return RATE_OCTAVE; + case 1: return SILENCE; + } + + return I_F_Q; +} + +/** + * Determine the bitrate from the frame size and/or the first byte of the frame. + * + * @param avctx the AV codec context + * @param buf_size length of the buffer + * @param buf the bufffer + * + * @return the bitrate on success, + * I_F_Q if the bitrate cannot be satisfactorily determined + * + * TIA/EIA/IS-733 2.4.8.7.1 + */ +static qcelp_packet_rate determine_bitrate(AVCodecContext *avctx, + const int buf_size, + const uint8_t **buf) +{ + qcelp_packet_rate bitrate; + + if ((bitrate = buf_size2bitrate(buf_size)) >= 0) { + if (bitrate > **buf) { + QCELPContext *q = avctx->priv_data; + if (!q->warned_buf_mismatch_bitrate) { + av_log(avctx, AV_LOG_WARNING, + "Claimed bitrate and buffer size mismatch.\n"); + q->warned_buf_mismatch_bitrate = 1; + } + bitrate = **buf; + } else if (bitrate < **buf) { + av_log(avctx, AV_LOG_ERROR, + "Buffer is too small for the claimed bitrate.\n"); + return I_F_Q; + } + (*buf)++; + } else if ((bitrate = buf_size2bitrate(buf_size + 1)) >= 0) { + av_log(avctx, AV_LOG_WARNING, + "Bitrate byte is missing, guessing the bitrate from packet size.\n"); + } else + return I_F_Q; + + if (bitrate == SILENCE) { + // FIXME: Remove this warning when tested with samples. + avpriv_request_sample(avctx, "Blank frame handling"); + } + return bitrate; +} + +static void warn_insufficient_frame_quality(AVCodecContext *avctx, + const char *message) +{ + av_log(avctx, AV_LOG_WARNING, "Frame #%d, IFQ: %s\n", + avctx->frame_number, message); +} + +static void postfilter(QCELPContext *q, float *samples, float *lpc) +{ + static const float pow_0_775[10] = { + 0.775000, 0.600625, 0.465484, 0.360750, 0.279582, + 0.216676, 0.167924, 0.130141, 0.100859, 0.078166 + }, pow_0_625[10] = { + 0.625000, 0.390625, 0.244141, 0.152588, 0.095367, + 0.059605, 0.037253, 0.023283, 0.014552, 0.009095 + }; + float lpc_s[10], lpc_p[10], pole_out[170], zero_out[160]; + int n; + + for (n = 0; n < 10; n++) { + lpc_s[n] = lpc[n] * pow_0_625[n]; + lpc_p[n] = lpc[n] * pow_0_775[n]; + } + + ff_celp_lp_zero_synthesis_filterf(zero_out, lpc_s, + q->formant_mem + 10, 160, 10); + memcpy(pole_out, q->postfilter_synth_mem, sizeof(float) * 10); + ff_celp_lp_synthesis_filterf(pole_out + 10, lpc_p, zero_out, 160, 10); + memcpy(q->postfilter_synth_mem, pole_out + 160, sizeof(float) * 10); + + ff_tilt_compensation(&q->postfilter_tilt_mem, 0.3, pole_out + 10, 160); + + ff_adaptive_gain_control(samples, pole_out + 10, + avpriv_scalarproduct_float_c(q->formant_mem + 10, + q->formant_mem + 10, + 160), + 160, 0.9375, &q->postfilter_agc_mem); +} + +static int qcelp_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + QCELPContext *q = avctx->priv_data; + AVFrame *frame = data; + float *outbuffer; + int i, ret; + float quantized_lspf[10], lpc[10]; + float gain[16]; + float *formant_mem; + + /* get output buffer */ + frame->nb_samples = 160; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + outbuffer = (float *)frame->data[0]; + + if ((q->bitrate = determine_bitrate(avctx, buf_size, &buf)) == I_F_Q) { + warn_insufficient_frame_quality(avctx, "bitrate cannot be determined."); + goto erasure; + } + + if (q->bitrate == RATE_OCTAVE && + (q->first16bits = AV_RB16(buf)) == 0xFFFF) { + warn_insufficient_frame_quality(avctx, "Bitrate is 1/8 and first 16 bits are on."); + goto erasure; + } + + if (q->bitrate > SILENCE) { + const QCELPBitmap *bitmaps = qcelp_unpacking_bitmaps_per_rate[q->bitrate]; + const QCELPBitmap *bitmaps_end = qcelp_unpacking_bitmaps_per_rate[q->bitrate] + + qcelp_unpacking_bitmaps_lengths[q->bitrate]; + uint8_t *unpacked_data = (uint8_t *)&q->frame; + + init_get_bits(&q->gb, buf, 8 * buf_size); + + memset(&q->frame, 0, sizeof(QCELPFrame)); + + for (; bitmaps < bitmaps_end; bitmaps++) + unpacked_data[bitmaps->index] |= get_bits(&q->gb, bitmaps->bitlen) << bitmaps->bitpos; + + // Check for erasures/blanks on rates 1, 1/4 and 1/8. + if (q->frame.reserved) { + warn_insufficient_frame_quality(avctx, "Wrong data in reserved frame area."); + goto erasure; + } + if (q->bitrate == RATE_QUARTER && + codebook_sanity_check_for_rate_quarter(q->frame.cbgain)) { + warn_insufficient_frame_quality(avctx, "Codebook gain sanity check failed."); + goto erasure; + } + + if (q->bitrate >= RATE_HALF) { + for (i = 0; i < 4; i++) { + if (q->frame.pfrac[i] && q->frame.plag[i] >= 124) { + warn_insufficient_frame_quality(avctx, "Cannot initialize pitch filter."); + goto erasure; + } + } + } + } + + decode_gain_and_index(q, gain); + compute_svector(q, gain, outbuffer); + + if (decode_lspf(q, quantized_lspf) < 0) { + warn_insufficient_frame_quality(avctx, "Badly received packets in frame."); + goto erasure; + } + + apply_pitch_filters(q, outbuffer); + + if (q->bitrate == I_F_Q) { +erasure: + q->bitrate = I_F_Q; + q->erasure_count++; + decode_gain_and_index(q, gain); + compute_svector(q, gain, outbuffer); + decode_lspf(q, quantized_lspf); + apply_pitch_filters(q, outbuffer); + } else + q->erasure_count = 0; + + formant_mem = q->formant_mem + 10; + for (i = 0; i < 4; i++) { + interpolate_lpc(q, quantized_lspf, lpc, i); + ff_celp_lp_synthesis_filterf(formant_mem, lpc, outbuffer + i * 40, 40, 10); + formant_mem += 40; + } + + // postfilter, as per TIA/EIA/IS-733 2.4.8.6 + postfilter(q, outbuffer, lpc); + + memcpy(q->formant_mem, q->formant_mem + 160, 10 * sizeof(float)); + + memcpy(q->prev_lspf, quantized_lspf, sizeof(q->prev_lspf)); + q->prev_bitrate = q->bitrate; + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_qcelp_decoder = { + .name = "qcelp", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_QCELP, + .init = qcelp_decode_init, + .decode = qcelp_decode_frame, + .capabilities = CODEC_CAP_DR1, + .priv_data_size = sizeof(QCELPContext), + .long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"), +}; diff --git a/ffmpeg/libavcodec/qdm2.c b/ffmpeg/libavcodec/qdm2.c new file mode 100644 index 0000000..108c327 --- /dev/null +++ b/ffmpeg/libavcodec/qdm2.c @@ -0,0 +1,2014 @@ +/* + * QDM2 compatible decoder + * Copyright (c) 2003 Ewald Snel + * Copyright (c) 2005 Benjamin Larsson + * Copyright (c) 2005 Alex Beregszaszi + * Copyright (c) 2005 Roberto Togni + * + * 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 + */ + +/** + * @file + * QDM2 decoder + * @author Ewald Snel, Benjamin Larsson, Alex Beregszaszi, Roberto Togni + * + * The decoder is not perfect yet, there are still some distortions + * especially on files encoded with 16 or 8 subbands. + */ + +#include +#include +#include + +#define BITSTREAM_READER_LE +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "rdft.h" +#include "mpegaudiodsp.h" +#include "mpegaudio.h" + +#include "qdm2data.h" +#include "qdm2_tablegen.h" + +#undef NDEBUG +#include + + +#define QDM2_LIST_ADD(list, size, packet) \ +do { \ + if (size > 0) { \ + list[size - 1].next = &list[size]; \ + } \ + list[size].packet = packet; \ + list[size].next = NULL; \ + size++; \ +} while(0) + +// Result is 8, 16 or 30 +#define QDM2_SB_USED(sub_sampling) (((sub_sampling) >= 2) ? 30 : 8 << (sub_sampling)) + +#define FIX_NOISE_IDX(noise_idx) \ + if ((noise_idx) >= 3840) \ + (noise_idx) -= 3840; \ + +#define SB_DITHERING_NOISE(sb,noise_idx) (noise_table[(noise_idx)++] * sb_noise_attenuation[(sb)]) + +#define SAMPLES_NEEDED \ + av_log (NULL,AV_LOG_INFO,"This file triggers some untested code. Please contact the developers.\n"); + +#define SAMPLES_NEEDED_2(why) \ + av_log (NULL,AV_LOG_INFO,"This file triggers some missing code. Please contact the developers.\nPosition: %s\n",why); + +#define QDM2_MAX_FRAME_SIZE 512 + +typedef int8_t sb_int8_array[2][30][64]; + +/** + * Subpacket + */ +typedef struct { + int type; ///< subpacket type + unsigned int size; ///< subpacket size + const uint8_t *data; ///< pointer to subpacket data (points to input data buffer, it's not a private copy) +} QDM2SubPacket; + +/** + * A node in the subpacket list + */ +typedef struct QDM2SubPNode { + QDM2SubPacket *packet; ///< packet + struct QDM2SubPNode *next; ///< pointer to next packet in the list, NULL if leaf node +} QDM2SubPNode; + +typedef struct { + float re; + float im; +} QDM2Complex; + +typedef struct { + float level; + QDM2Complex *complex; + const float *table; + int phase; + int phase_shift; + int duration; + short time_index; + short cutoff; +} FFTTone; + +typedef struct { + int16_t sub_packet; + uint8_t channel; + int16_t offset; + int16_t exp; + uint8_t phase; +} FFTCoefficient; + +typedef struct { + DECLARE_ALIGNED(32, QDM2Complex, complex)[MPA_MAX_CHANNELS][256]; +} QDM2FFT; + +/** + * QDM2 decoder context + */ +typedef struct { + /// Parameters from codec header, do not change during playback + int nb_channels; ///< number of channels + int channels; ///< number of channels + int group_size; ///< size of frame group (16 frames per group) + int fft_size; ///< size of FFT, in complex numbers + int checksum_size; ///< size of data block, used also for checksum + + /// Parameters built from header parameters, do not change during playback + int group_order; ///< order of frame group + int fft_order; ///< order of FFT (actually fftorder+1) + int frame_size; ///< size of data frame + int frequency_range; + int sub_sampling; ///< subsampling: 0=25%, 1=50%, 2=100% */ + int coeff_per_sb_select; ///< selector for "num. of coeffs. per subband" tables. Can be 0, 1, 2 + int cm_table_select; ///< selector for "coding method" tables. Can be 0, 1 (from init: 0-4) + + /// Packets and packet lists + QDM2SubPacket sub_packets[16]; ///< the packets themselves + QDM2SubPNode sub_packet_list_A[16]; ///< list of all packets + QDM2SubPNode sub_packet_list_B[16]; ///< FFT packets B are on list + int sub_packets_B; ///< number of packets on 'B' list + QDM2SubPNode sub_packet_list_C[16]; ///< packets with errors? + QDM2SubPNode sub_packet_list_D[16]; ///< DCT packets + + /// FFT and tones + FFTTone fft_tones[1000]; + int fft_tone_start; + int fft_tone_end; + FFTCoefficient fft_coefs[1000]; + int fft_coefs_index; + int fft_coefs_min_index[5]; + int fft_coefs_max_index[5]; + int fft_level_exp[6]; + RDFTContext rdft_ctx; + QDM2FFT fft; + + /// I/O data + const uint8_t *compressed_data; + int compressed_size; + float output_buffer[QDM2_MAX_FRAME_SIZE * MPA_MAX_CHANNELS * 2]; + + /// Synthesis filter + MPADSPContext mpadsp; + DECLARE_ALIGNED(32, float, synth_buf)[MPA_MAX_CHANNELS][512*2]; + int synth_buf_offset[MPA_MAX_CHANNELS]; + DECLARE_ALIGNED(32, float, sb_samples)[MPA_MAX_CHANNELS][128][SBLIMIT]; + DECLARE_ALIGNED(32, float, samples)[MPA_MAX_CHANNELS * MPA_FRAME_SIZE]; + + /// Mixed temporary data used in decoding + float tone_level[MPA_MAX_CHANNELS][30][64]; + int8_t coding_method[MPA_MAX_CHANNELS][30][64]; + int8_t quantized_coeffs[MPA_MAX_CHANNELS][10][8]; + int8_t tone_level_idx_base[MPA_MAX_CHANNELS][30][8]; + int8_t tone_level_idx_hi1[MPA_MAX_CHANNELS][3][8][8]; + int8_t tone_level_idx_mid[MPA_MAX_CHANNELS][26][8]; + int8_t tone_level_idx_hi2[MPA_MAX_CHANNELS][26]; + int8_t tone_level_idx[MPA_MAX_CHANNELS][30][64]; + int8_t tone_level_idx_temp[MPA_MAX_CHANNELS][30][64]; + + // Flags + int has_errors; ///< packet has errors + int superblocktype_2_3; ///< select fft tables and some algorithm based on superblock type + int do_synth_filter; ///< used to perform or skip synthesis filter + + int sub_packet; + int noise_idx; ///< index for dithering noise table +} QDM2Context; + + +static VLC vlc_tab_level; +static VLC vlc_tab_diff; +static VLC vlc_tab_run; +static VLC fft_level_exp_alt_vlc; +static VLC fft_level_exp_vlc; +static VLC fft_stereo_exp_vlc; +static VLC fft_stereo_phase_vlc; +static VLC vlc_tab_tone_level_idx_hi1; +static VLC vlc_tab_tone_level_idx_mid; +static VLC vlc_tab_tone_level_idx_hi2; +static VLC vlc_tab_type30; +static VLC vlc_tab_type34; +static VLC vlc_tab_fft_tone_offset[5]; + +static const uint16_t qdm2_vlc_offs[] = { + 0,260,566,598,894,1166,1230,1294,1678,1950,2214,2278,2310,2570,2834,3124,3448,3838, +}; + +static av_cold void qdm2_init_vlc(void) +{ + static int vlcs_initialized = 0; + static VLC_TYPE qdm2_table[3838][2]; + + if (!vlcs_initialized) { + + vlc_tab_level.table = &qdm2_table[qdm2_vlc_offs[0]]; + vlc_tab_level.table_allocated = qdm2_vlc_offs[1] - qdm2_vlc_offs[0]; + init_vlc (&vlc_tab_level, 8, 24, + vlc_tab_level_huffbits, 1, 1, + vlc_tab_level_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_diff.table = &qdm2_table[qdm2_vlc_offs[1]]; + vlc_tab_diff.table_allocated = qdm2_vlc_offs[2] - qdm2_vlc_offs[1]; + init_vlc (&vlc_tab_diff, 8, 37, + vlc_tab_diff_huffbits, 1, 1, + vlc_tab_diff_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_run.table = &qdm2_table[qdm2_vlc_offs[2]]; + vlc_tab_run.table_allocated = qdm2_vlc_offs[3] - qdm2_vlc_offs[2]; + init_vlc (&vlc_tab_run, 5, 6, + vlc_tab_run_huffbits, 1, 1, + vlc_tab_run_huffcodes, 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + fft_level_exp_alt_vlc.table = &qdm2_table[qdm2_vlc_offs[3]]; + fft_level_exp_alt_vlc.table_allocated = qdm2_vlc_offs[4] - qdm2_vlc_offs[3]; + init_vlc (&fft_level_exp_alt_vlc, 8, 28, + fft_level_exp_alt_huffbits, 1, 1, + fft_level_exp_alt_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + + fft_level_exp_vlc.table = &qdm2_table[qdm2_vlc_offs[4]]; + fft_level_exp_vlc.table_allocated = qdm2_vlc_offs[5] - qdm2_vlc_offs[4]; + init_vlc (&fft_level_exp_vlc, 8, 20, + fft_level_exp_huffbits, 1, 1, + fft_level_exp_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + fft_stereo_exp_vlc.table = &qdm2_table[qdm2_vlc_offs[5]]; + fft_stereo_exp_vlc.table_allocated = qdm2_vlc_offs[6] - qdm2_vlc_offs[5]; + init_vlc (&fft_stereo_exp_vlc, 6, 7, + fft_stereo_exp_huffbits, 1, 1, + fft_stereo_exp_huffcodes, 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + fft_stereo_phase_vlc.table = &qdm2_table[qdm2_vlc_offs[6]]; + fft_stereo_phase_vlc.table_allocated = qdm2_vlc_offs[7] - qdm2_vlc_offs[6]; + init_vlc (&fft_stereo_phase_vlc, 6, 9, + fft_stereo_phase_huffbits, 1, 1, + fft_stereo_phase_huffcodes, 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_tone_level_idx_hi1.table = &qdm2_table[qdm2_vlc_offs[7]]; + vlc_tab_tone_level_idx_hi1.table_allocated = qdm2_vlc_offs[8] - qdm2_vlc_offs[7]; + init_vlc (&vlc_tab_tone_level_idx_hi1, 8, 20, + vlc_tab_tone_level_idx_hi1_huffbits, 1, 1, + vlc_tab_tone_level_idx_hi1_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_tone_level_idx_mid.table = &qdm2_table[qdm2_vlc_offs[8]]; + vlc_tab_tone_level_idx_mid.table_allocated = qdm2_vlc_offs[9] - qdm2_vlc_offs[8]; + init_vlc (&vlc_tab_tone_level_idx_mid, 8, 24, + vlc_tab_tone_level_idx_mid_huffbits, 1, 1, + vlc_tab_tone_level_idx_mid_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_tone_level_idx_hi2.table = &qdm2_table[qdm2_vlc_offs[9]]; + vlc_tab_tone_level_idx_hi2.table_allocated = qdm2_vlc_offs[10] - qdm2_vlc_offs[9]; + init_vlc (&vlc_tab_tone_level_idx_hi2, 8, 24, + vlc_tab_tone_level_idx_hi2_huffbits, 1, 1, + vlc_tab_tone_level_idx_hi2_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_type30.table = &qdm2_table[qdm2_vlc_offs[10]]; + vlc_tab_type30.table_allocated = qdm2_vlc_offs[11] - qdm2_vlc_offs[10]; + init_vlc (&vlc_tab_type30, 6, 9, + vlc_tab_type30_huffbits, 1, 1, + vlc_tab_type30_huffcodes, 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_type34.table = &qdm2_table[qdm2_vlc_offs[11]]; + vlc_tab_type34.table_allocated = qdm2_vlc_offs[12] - qdm2_vlc_offs[11]; + init_vlc (&vlc_tab_type34, 5, 10, + vlc_tab_type34_huffbits, 1, 1, + vlc_tab_type34_huffcodes, 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_fft_tone_offset[0].table = &qdm2_table[qdm2_vlc_offs[12]]; + vlc_tab_fft_tone_offset[0].table_allocated = qdm2_vlc_offs[13] - qdm2_vlc_offs[12]; + init_vlc (&vlc_tab_fft_tone_offset[0], 8, 23, + vlc_tab_fft_tone_offset_0_huffbits, 1, 1, + vlc_tab_fft_tone_offset_0_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_fft_tone_offset[1].table = &qdm2_table[qdm2_vlc_offs[13]]; + vlc_tab_fft_tone_offset[1].table_allocated = qdm2_vlc_offs[14] - qdm2_vlc_offs[13]; + init_vlc (&vlc_tab_fft_tone_offset[1], 8, 28, + vlc_tab_fft_tone_offset_1_huffbits, 1, 1, + vlc_tab_fft_tone_offset_1_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_fft_tone_offset[2].table = &qdm2_table[qdm2_vlc_offs[14]]; + vlc_tab_fft_tone_offset[2].table_allocated = qdm2_vlc_offs[15] - qdm2_vlc_offs[14]; + init_vlc (&vlc_tab_fft_tone_offset[2], 8, 32, + vlc_tab_fft_tone_offset_2_huffbits, 1, 1, + vlc_tab_fft_tone_offset_2_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_fft_tone_offset[3].table = &qdm2_table[qdm2_vlc_offs[15]]; + vlc_tab_fft_tone_offset[3].table_allocated = qdm2_vlc_offs[16] - qdm2_vlc_offs[15]; + init_vlc (&vlc_tab_fft_tone_offset[3], 8, 35, + vlc_tab_fft_tone_offset_3_huffbits, 1, 1, + vlc_tab_fft_tone_offset_3_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlc_tab_fft_tone_offset[4].table = &qdm2_table[qdm2_vlc_offs[16]]; + vlc_tab_fft_tone_offset[4].table_allocated = qdm2_vlc_offs[17] - qdm2_vlc_offs[16]; + init_vlc (&vlc_tab_fft_tone_offset[4], 8, 38, + vlc_tab_fft_tone_offset_4_huffbits, 1, 1, + vlc_tab_fft_tone_offset_4_huffcodes, 2, 2, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); + + vlcs_initialized=1; + } +} + +static int qdm2_get_vlc (GetBitContext *gb, VLC *vlc, int flag, int depth) +{ + int value; + + value = get_vlc2(gb, vlc->table, vlc->bits, depth); + + /* stage-2, 3 bits exponent escape sequence */ + if (value-- == 0) + value = get_bits (gb, get_bits (gb, 3) + 1); + + /* stage-3, optional */ + if (flag) { + int tmp; + + if (value >= 60) { + av_log(NULL, AV_LOG_ERROR, "value %d in qdm2_get_vlc too large\n", value); + return 0; + } + + tmp= vlc_stage3_values[value]; + + if ((value & ~3) > 0) + tmp += get_bits (gb, (value >> 2)); + value = tmp; + } + + return value; +} + + +static int qdm2_get_se_vlc (VLC *vlc, GetBitContext *gb, int depth) +{ + int value = qdm2_get_vlc (gb, vlc, 0, depth); + + return (value & 1) ? ((value + 1) >> 1) : -(value >> 1); +} + + +/** + * QDM2 checksum + * + * @param data pointer to data to be checksum'ed + * @param length data length + * @param value checksum value + * + * @return 0 if checksum is OK + */ +static uint16_t qdm2_packet_checksum (const uint8_t *data, int length, int value) { + int i; + + for (i=0; i < length; i++) + value -= data[i]; + + return (uint16_t)(value & 0xffff); +} + + +/** + * Fill a QDM2SubPacket structure with packet type, size, and data pointer. + * + * @param gb bitreader context + * @param sub_packet packet under analysis + */ +static void qdm2_decode_sub_packet_header (GetBitContext *gb, QDM2SubPacket *sub_packet) +{ + sub_packet->type = get_bits (gb, 8); + + if (sub_packet->type == 0) { + sub_packet->size = 0; + sub_packet->data = NULL; + } else { + sub_packet->size = get_bits (gb, 8); + + if (sub_packet->type & 0x80) { + sub_packet->size <<= 8; + sub_packet->size |= get_bits (gb, 8); + sub_packet->type &= 0x7f; + } + + if (sub_packet->type == 0x7f) + sub_packet->type |= (get_bits (gb, 8) << 8); + + sub_packet->data = &gb->buffer[get_bits_count(gb) / 8]; // FIXME: this depends on bitreader internal data + } + + av_log(NULL,AV_LOG_DEBUG,"Subpacket: type=%d size=%d start_offs=%x\n", + sub_packet->type, sub_packet->size, get_bits_count(gb) / 8); +} + + +/** + * Return node pointer to first packet of requested type in list. + * + * @param list list of subpackets to be scanned + * @param type type of searched subpacket + * @return node pointer for subpacket if found, else NULL + */ +static QDM2SubPNode* qdm2_search_subpacket_type_in_list (QDM2SubPNode *list, int type) +{ + while (list != NULL && list->packet != NULL) { + if (list->packet->type == type) + return list; + list = list->next; + } + return NULL; +} + + +/** + * Replace 8 elements with their average value. + * Called by qdm2_decode_superblock before starting subblock decoding. + * + * @param q context + */ +static void average_quantized_coeffs (QDM2Context *q) +{ + int i, j, n, ch, sum; + + n = coeff_per_sb_for_avg[q->coeff_per_sb_select][QDM2_SB_USED(q->sub_sampling) - 1] + 1; + + for (ch = 0; ch < q->nb_channels; ch++) + for (i = 0; i < n; i++) { + sum = 0; + + for (j = 0; j < 8; j++) + sum += q->quantized_coeffs[ch][i][j]; + + sum /= 8; + if (sum > 0) + sum--; + + for (j=0; j < 8; j++) + q->quantized_coeffs[ch][i][j] = sum; + } +} + + +/** + * Build subband samples with noise weighted by q->tone_level. + * Called by synthfilt_build_sb_samples. + * + * @param q context + * @param sb subband index + */ +static void build_sb_samples_from_noise (QDM2Context *q, int sb) +{ + int ch, j; + + FIX_NOISE_IDX(q->noise_idx); + + if (!q->nb_channels) + return; + + for (ch = 0; ch < q->nb_channels; ch++) + for (j = 0; j < 64; j++) { + q->sb_samples[ch][j * 2][sb] = SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j]; + q->sb_samples[ch][j * 2 + 1][sb] = SB_DITHERING_NOISE(sb,q->noise_idx) * q->tone_level[ch][sb][j]; + } +} + + +/** + * Called while processing data from subpackets 11 and 12. + * Used after making changes to coding_method array. + * + * @param sb subband index + * @param channels number of channels + * @param coding_method q->coding_method[0][0][0] + */ +static void fix_coding_method_array (int sb, int channels, sb_int8_array coding_method) +{ + int j,k; + int ch; + int run, case_val; + static const int switchtable[23] = {0,5,1,5,5,5,5,5,2,5,5,5,5,5,5,5,3,5,5,5,5,5,4}; + + for (ch = 0; ch < channels; ch++) { + for (j = 0; j < 64; ) { + if((coding_method[ch][sb][j] - 8) > 22) { + run = 1; + case_val = 8; + } else { + switch (switchtable[coding_method[ch][sb][j]-8]) { + case 0: run = 10; case_val = 10; break; + case 1: run = 1; case_val = 16; break; + case 2: run = 5; case_val = 24; break; + case 3: run = 3; case_val = 30; break; + case 4: run = 1; case_val = 30; break; + case 5: run = 1; case_val = 8; break; + default: run = 1; case_val = 8; break; + } + } + for (k = 0; k < run; k++) + if (j + k < 128) + if (coding_method[ch][sb + (j + k) / 64][(j + k) % 64] > coding_method[ch][sb][j]) + if (k > 0) { + SAMPLES_NEEDED + //not debugged, almost never used + memset(&coding_method[ch][sb][j + k], case_val, k * sizeof(int8_t)); + memset(&coding_method[ch][sb][j + k], case_val, 3 * sizeof(int8_t)); + } + j += run; + } + } +} + + +/** + * Related to synthesis filter + * Called by process_subpacket_10 + * + * @param q context + * @param flag 1 if called after getting data from subpacket 10, 0 if no subpacket 10 + */ +static void fill_tone_level_array (QDM2Context *q, int flag) +{ + int i, sb, ch, sb_used; + int tmp, tab; + + for (ch = 0; ch < q->nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (i = 0; i < 8; i++) { + if ((tab=coeff_per_sb_for_dequant[q->coeff_per_sb_select][sb]) < (last_coeff[q->coeff_per_sb_select] - 1)) + tmp = q->quantized_coeffs[ch][tab + 1][i] * dequant_table[q->coeff_per_sb_select][tab + 1][sb]+ + q->quantized_coeffs[ch][tab][i] * dequant_table[q->coeff_per_sb_select][tab][sb]; + else + tmp = q->quantized_coeffs[ch][tab][i] * dequant_table[q->coeff_per_sb_select][tab][sb]; + if(tmp < 0) + tmp += 0xff; + q->tone_level_idx_base[ch][sb][i] = (tmp / 256) & 0xff; + } + + sb_used = QDM2_SB_USED(q->sub_sampling); + + if ((q->superblocktype_2_3 != 0) && !flag) { + for (sb = 0; sb < sb_used; sb++) + for (ch = 0; ch < q->nb_channels; ch++) + for (i = 0; i < 64; i++) { + q->tone_level_idx[ch][sb][i] = q->tone_level_idx_base[ch][sb][i / 8]; + if (q->tone_level_idx[ch][sb][i] < 0) + q->tone_level[ch][sb][i] = 0; + else + q->tone_level[ch][sb][i] = fft_tone_level_table[0][q->tone_level_idx[ch][sb][i] & 0x3f]; + } + } else { + tab = q->superblocktype_2_3 ? 0 : 1; + for (sb = 0; sb < sb_used; sb++) { + if ((sb >= 4) && (sb <= 23)) { + for (ch = 0; ch < q->nb_channels; ch++) + for (i = 0; i < 64; i++) { + tmp = q->tone_level_idx_base[ch][sb][i / 8] - + q->tone_level_idx_hi1[ch][sb / 8][i / 8][i % 8] - + q->tone_level_idx_mid[ch][sb - 4][i / 8] - + q->tone_level_idx_hi2[ch][sb - 4]; + q->tone_level_idx[ch][sb][i] = tmp & 0xff; + if ((tmp < 0) || (!q->superblocktype_2_3 && !tmp)) + q->tone_level[ch][sb][i] = 0; + else + q->tone_level[ch][sb][i] = fft_tone_level_table[tab][tmp & 0x3f]; + } + } else { + if (sb > 4) { + for (ch = 0; ch < q->nb_channels; ch++) + for (i = 0; i < 64; i++) { + tmp = q->tone_level_idx_base[ch][sb][i / 8] - + q->tone_level_idx_hi1[ch][2][i / 8][i % 8] - + q->tone_level_idx_hi2[ch][sb - 4]; + q->tone_level_idx[ch][sb][i] = tmp & 0xff; + if ((tmp < 0) || (!q->superblocktype_2_3 && !tmp)) + q->tone_level[ch][sb][i] = 0; + else + q->tone_level[ch][sb][i] = fft_tone_level_table[tab][tmp & 0x3f]; + } + } else { + for (ch = 0; ch < q->nb_channels; ch++) + for (i = 0; i < 64; i++) { + tmp = q->tone_level_idx[ch][sb][i] = q->tone_level_idx_base[ch][sb][i / 8]; + if ((tmp < 0) || (!q->superblocktype_2_3 && !tmp)) + q->tone_level[ch][sb][i] = 0; + else + q->tone_level[ch][sb][i] = fft_tone_level_table[tab][tmp & 0x3f]; + } + } + } + } + } + + return; +} + + +/** + * Related to synthesis filter + * Called by process_subpacket_11 + * c is built with data from subpacket 11 + * Most of this function is used only if superblock_type_2_3 == 0, never seen it in samples + * + * @param tone_level_idx + * @param tone_level_idx_temp + * @param coding_method q->coding_method[0][0][0] + * @param nb_channels number of channels + * @param c coming from subpacket 11, passed as 8*c + * @param superblocktype_2_3 flag based on superblock packet type + * @param cm_table_select q->cm_table_select + */ +static void fill_coding_method_array (sb_int8_array tone_level_idx, sb_int8_array tone_level_idx_temp, + sb_int8_array coding_method, int nb_channels, + int c, int superblocktype_2_3, int cm_table_select) +{ + int ch, sb, j; + int tmp, acc, esp_40, comp; + int add1, add2, add3, add4; + int64_t multres; + + if (!superblocktype_2_3) { + /* This case is untested, no samples available */ + avpriv_request_sample(NULL, "!superblocktype_2_3"); + return; + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) { + for (j = 1; j < 63; j++) { // The loop only iterates to 63 so the code doesn't overflow the buffer + add1 = tone_level_idx[ch][sb][j] - 10; + if (add1 < 0) + add1 = 0; + add2 = add3 = add4 = 0; + if (sb > 1) { + add2 = tone_level_idx[ch][sb - 2][j] + tone_level_idx_offset_table[sb][0] - 6; + if (add2 < 0) + add2 = 0; + } + if (sb > 0) { + add3 = tone_level_idx[ch][sb - 1][j] + tone_level_idx_offset_table[sb][1] - 6; + if (add3 < 0) + add3 = 0; + } + if (sb < 29) { + add4 = tone_level_idx[ch][sb + 1][j] + tone_level_idx_offset_table[sb][3] - 6; + if (add4 < 0) + add4 = 0; + } + tmp = tone_level_idx[ch][sb][j + 1] * 2 - add4 - add3 - add2 - add1; + if (tmp < 0) + tmp = 0; + tone_level_idx_temp[ch][sb][j + 1] = tmp & 0xff; + } + tone_level_idx_temp[ch][sb][0] = tone_level_idx_temp[ch][sb][1]; + } + acc = 0; + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (j = 0; j < 64; j++) + acc += tone_level_idx_temp[ch][sb][j]; + + multres = 0x66666667LL * (acc * 10); + esp_40 = (multres >> 32) / 8 + ((multres & 0xffffffff) >> 31); + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (j = 0; j < 64; j++) { + comp = tone_level_idx_temp[ch][sb][j]* esp_40 * 10; + if (comp < 0) + comp += 0xff; + comp /= 256; // signed shift + switch(sb) { + case 0: + if (comp < 30) + comp = 30; + comp += 15; + break; + case 1: + if (comp < 24) + comp = 24; + comp += 10; + break; + case 2: + case 3: + case 4: + if (comp < 16) + comp = 16; + } + if (comp <= 5) + tmp = 0; + else if (comp <= 10) + tmp = 10; + else if (comp <= 16) + tmp = 16; + else if (comp <= 24) + tmp = -1; + else + tmp = 0; + coding_method[ch][sb][j] = ((tmp & 0xfffa) + 30 )& 0xff; + } + for (sb = 0; sb < 30; sb++) + fix_coding_method_array(sb, nb_channels, coding_method); + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (j = 0; j < 64; j++) + if (sb >= 10) { + if (coding_method[ch][sb][j] < 10) + coding_method[ch][sb][j] = 10; + } else { + if (sb >= 2) { + if (coding_method[ch][sb][j] < 16) + coding_method[ch][sb][j] = 16; + } else { + if (coding_method[ch][sb][j] < 30) + coding_method[ch][sb][j] = 30; + } + } + } else { // superblocktype_2_3 != 0 + for (ch = 0; ch < nb_channels; ch++) + for (sb = 0; sb < 30; sb++) + for (j = 0; j < 64; j++) + coding_method[ch][sb][j] = coding_method_table[cm_table_select][sb]; + } + + return; +} + + +/** + * + * Called by process_subpacket_11 to process more data from subpacket 11 with sb 0-8 + * Called by process_subpacket_12 to process data from subpacket 12 with sb 8-sb_used + * + * @param q context + * @param gb bitreader context + * @param length packet length in bits + * @param sb_min lower subband processed (sb_min included) + * @param sb_max higher subband processed (sb_max excluded) + */ +static int synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int length, int sb_min, int sb_max) +{ + int sb, j, k, n, ch, run, channels; + int joined_stereo, zero_encoding, chs; + int type34_first; + float type34_div = 0; + float type34_predictor; + float samples[10], sign_bits[16]; + + if (length == 0) { + // If no data use noise + for (sb=sb_min; sb < sb_max; sb++) + build_sb_samples_from_noise (q, sb); + + return 0; + } + + for (sb = sb_min; sb < sb_max; sb++) { + FIX_NOISE_IDX(q->noise_idx); + + channels = q->nb_channels; + + if (q->nb_channels <= 1 || sb < 12) + joined_stereo = 0; + else if (sb >= 24) + joined_stereo = 1; + else + joined_stereo = (get_bits_left(gb) >= 1) ? get_bits1 (gb) : 0; + + if (joined_stereo) { + if (get_bits_left(gb) >= 16) + for (j = 0; j < 16; j++) + sign_bits[j] = get_bits1 (gb); + + if (q->coding_method[0][sb][0] <= 0) { + av_log(NULL, AV_LOG_ERROR, "coding method invalid\n"); + return AVERROR_INVALIDDATA; + } + + for (j = 0; j < 64; j++) + if (q->coding_method[1][sb][j] > q->coding_method[0][sb][j]) + q->coding_method[0][sb][j] = q->coding_method[1][sb][j]; + + fix_coding_method_array(sb, q->nb_channels, q->coding_method); + channels = 1; + } + + for (ch = 0; ch < channels; ch++) { + zero_encoding = (get_bits_left(gb) >= 1) ? get_bits1(gb) : 0; + type34_predictor = 0.0; + type34_first = 1; + + for (j = 0; j < 128; ) { + switch (q->coding_method[ch][sb][j / 2]) { + case 8: + if (get_bits_left(gb) >= 10) { + if (zero_encoding) { + for (k = 0; k < 5; k++) { + if ((j + 2 * k) >= 128) + break; + samples[2 * k] = get_bits1(gb) ? dequant_1bit[joined_stereo][2 * get_bits1(gb)] : 0; + } + } else { + n = get_bits(gb, 8); + if (n >= 243) { + av_log(NULL, AV_LOG_ERROR, "Invalid 8bit codeword\n"); + return AVERROR_INVALIDDATA; + } + + for (k = 0; k < 5; k++) + samples[2 * k] = dequant_1bit[joined_stereo][random_dequant_index[n][k]]; + } + for (k = 0; k < 5; k++) + samples[2 * k + 1] = SB_DITHERING_NOISE(sb,q->noise_idx); + } else { + for (k = 0; k < 10; k++) + samples[k] = SB_DITHERING_NOISE(sb,q->noise_idx); + } + run = 10; + break; + + case 10: + if (get_bits_left(gb) >= 1) { + float f = 0.81; + + if (get_bits1(gb)) + f = -f; + f -= noise_samples[((sb + 1) * (j +5 * ch + 1)) & 127] * 9.0 / 40.0; + samples[0] = f; + } else { + samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); + } + run = 1; + break; + + case 16: + if (get_bits_left(gb) >= 10) { + if (zero_encoding) { + for (k = 0; k < 5; k++) { + if ((j + k) >= 128) + break; + samples[k] = (get_bits1(gb) == 0) ? 0 : dequant_1bit[joined_stereo][2 * get_bits1(gb)]; + } + } else { + n = get_bits (gb, 8); + if (n >= 243) { + av_log(NULL, AV_LOG_ERROR, "Invalid 8bit codeword\n"); + return AVERROR_INVALIDDATA; + } + + for (k = 0; k < 5; k++) + samples[k] = dequant_1bit[joined_stereo][random_dequant_index[n][k]]; + } + } else { + for (k = 0; k < 5; k++) + samples[k] = SB_DITHERING_NOISE(sb,q->noise_idx); + } + run = 5; + break; + + case 24: + if (get_bits_left(gb) >= 7) { + n = get_bits(gb, 7); + if (n >= 125) { + av_log(NULL, AV_LOG_ERROR, "Invalid 7bit codeword\n"); + return AVERROR_INVALIDDATA; + } + + for (k = 0; k < 3; k++) + samples[k] = (random_dequant_type24[n][k] - 2.0) * 0.5; + } else { + for (k = 0; k < 3; k++) + samples[k] = SB_DITHERING_NOISE(sb,q->noise_idx); + } + run = 3; + break; + + case 30: + if (get_bits_left(gb) >= 4) { + unsigned index = qdm2_get_vlc(gb, &vlc_tab_type30, 0, 1); + if (index >= FF_ARRAY_ELEMS(type30_dequant)) { + av_log(NULL, AV_LOG_ERROR, "index %d out of type30_dequant array\n", index); + return AVERROR_INVALIDDATA; + } + samples[0] = type30_dequant[index]; + } else + samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); + + run = 1; + break; + + case 34: + if (get_bits_left(gb) >= 7) { + if (type34_first) { + type34_div = (float)(1 << get_bits(gb, 2)); + samples[0] = ((float)get_bits(gb, 5) - 16.0) / 15.0; + type34_predictor = samples[0]; + type34_first = 0; + } else { + unsigned index = qdm2_get_vlc(gb, &vlc_tab_type34, 0, 1); + if (index >= FF_ARRAY_ELEMS(type34_delta)) { + av_log(NULL, AV_LOG_ERROR, "index %d out of type34_delta array\n", index); + return AVERROR_INVALIDDATA; + } + samples[0] = type34_delta[index] / type34_div + type34_predictor; + type34_predictor = samples[0]; + } + } else { + samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); + } + run = 1; + break; + + default: + samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx); + run = 1; + break; + } + + if (joined_stereo) { + float tmp[10][MPA_MAX_CHANNELS]; + for (k = 0; k < run; k++) { + tmp[k][0] = samples[k]; + if ((j + k) < 128) + tmp[k][1] = (sign_bits[(j + k) / 8]) ? -samples[k] : samples[k]; + } + for (chs = 0; chs < q->nb_channels; chs++) + for (k = 0; k < run; k++) + if ((j + k) < 128) + q->sb_samples[chs][j + k][sb] = q->tone_level[chs][sb][((j + k)/2)] * tmp[k][chs]; + } else { + for (k = 0; k < run; k++) + if ((j + k) < 128) + q->sb_samples[ch][j + k][sb] = q->tone_level[ch][sb][(j + k)/2] * samples[k]; + } + + j += run; + } // j loop + } // channel loop + } // subband loop + return 0; +} + + +/** + * Init the first element of a channel in quantized_coeffs with data from packet 10 (quantized_coeffs[ch][0]). + * This is similar to process_subpacket_9, but for a single channel and for element [0] + * same VLC tables as process_subpacket_9 are used. + * + * @param quantized_coeffs pointer to quantized_coeffs[ch][0] + * @param gb bitreader context + */ +static int init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext *gb) +{ + int i, k, run, level, diff; + + if (get_bits_left(gb) < 16) + return -1; + level = qdm2_get_vlc(gb, &vlc_tab_level, 0, 2); + + quantized_coeffs[0] = level; + + for (i = 0; i < 7; ) { + if (get_bits_left(gb) < 16) + return -1; + run = qdm2_get_vlc(gb, &vlc_tab_run, 0, 1) + 1; + + if (i + run >= 8) + return -1; + + if (get_bits_left(gb) < 16) + return -1; + diff = qdm2_get_se_vlc(&vlc_tab_diff, gb, 2); + + for (k = 1; k <= run; k++) + quantized_coeffs[i + k] = (level + ((k * diff) / run)); + + level += diff; + i += run; + } + return 0; +} + + +/** + * Related to synthesis filter, process data from packet 10 + * Init part of quantized_coeffs via function init_quantized_coeffs_elem0 + * Init tone_level_idx_hi1, tone_level_idx_hi2, tone_level_idx_mid with data from packet 10 + * + * @param q context + * @param gb bitreader context + */ +static void init_tone_level_dequantization (QDM2Context *q, GetBitContext *gb) +{ + int sb, j, k, n, ch; + + for (ch = 0; ch < q->nb_channels; ch++) { + init_quantized_coeffs_elem0(q->quantized_coeffs[ch][0], gb); + + if (get_bits_left(gb) < 16) { + memset(q->quantized_coeffs[ch][0], 0, 8); + break; + } + } + + n = q->sub_sampling + 1; + + for (sb = 0; sb < n; sb++) + for (ch = 0; ch < q->nb_channels; ch++) + for (j = 0; j < 8; j++) { + if (get_bits_left(gb) < 1) + break; + if (get_bits1(gb)) { + for (k=0; k < 8; k++) { + if (get_bits_left(gb) < 16) + break; + q->tone_level_idx_hi1[ch][sb][j][k] = qdm2_get_vlc(gb, &vlc_tab_tone_level_idx_hi1, 0, 2); + } + } else { + for (k=0; k < 8; k++) + q->tone_level_idx_hi1[ch][sb][j][k] = 0; + } + } + + n = QDM2_SB_USED(q->sub_sampling) - 4; + + for (sb = 0; sb < n; sb++) + for (ch = 0; ch < q->nb_channels; ch++) { + if (get_bits_left(gb) < 16) + break; + q->tone_level_idx_hi2[ch][sb] = qdm2_get_vlc(gb, &vlc_tab_tone_level_idx_hi2, 0, 2); + if (sb > 19) + q->tone_level_idx_hi2[ch][sb] -= 16; + else + for (j = 0; j < 8; j++) + q->tone_level_idx_mid[ch][sb][j] = -16; + } + + n = QDM2_SB_USED(q->sub_sampling) - 5; + + for (sb = 0; sb < n; sb++) + for (ch = 0; ch < q->nb_channels; ch++) + for (j = 0; j < 8; j++) { + if (get_bits_left(gb) < 16) + break; + q->tone_level_idx_mid[ch][sb][j] = qdm2_get_vlc(gb, &vlc_tab_tone_level_idx_mid, 0, 2) - 32; + } +} + +/** + * Process subpacket 9, init quantized_coeffs with data from it + * + * @param q context + * @param node pointer to node with packet + */ +static int process_subpacket_9 (QDM2Context *q, QDM2SubPNode *node) +{ + GetBitContext gb; + int i, j, k, n, ch, run, level, diff; + + init_get_bits(&gb, node->packet->data, node->packet->size*8); + + n = coeff_per_sb_for_avg[q->coeff_per_sb_select][QDM2_SB_USED(q->sub_sampling) - 1] + 1; // same as averagesomething function + + for (i = 1; i < n; i++) + for (ch=0; ch < q->nb_channels; ch++) { + level = qdm2_get_vlc(&gb, &vlc_tab_level, 0, 2); + q->quantized_coeffs[ch][i][0] = level; + + for (j = 0; j < (8 - 1); ) { + run = qdm2_get_vlc(&gb, &vlc_tab_run, 0, 1) + 1; + diff = qdm2_get_se_vlc(&vlc_tab_diff, &gb, 2); + + if (j + run >= 8) + return -1; + + for (k = 1; k <= run; k++) + q->quantized_coeffs[ch][i][j + k] = (level + ((k*diff) / run)); + + level += diff; + j += run; + } + } + + for (ch = 0; ch < q->nb_channels; ch++) + for (i = 0; i < 8; i++) + q->quantized_coeffs[ch][0][i] = 0; + + return 0; +} + + +/** + * Process subpacket 10 if not null, else + * + * @param q context + * @param node pointer to node with packet + */ +static void process_subpacket_10 (QDM2Context *q, QDM2SubPNode *node) +{ + GetBitContext gb; + + if (node) { + init_get_bits(&gb, node->packet->data, node->packet->size * 8); + init_tone_level_dequantization(q, &gb); + fill_tone_level_array(q, 1); + } else { + fill_tone_level_array(q, 0); + } +} + + +/** + * Process subpacket 11 + * + * @param q context + * @param node pointer to node with packet + */ +static void process_subpacket_11 (QDM2Context *q, QDM2SubPNode *node) +{ + GetBitContext gb; + int length = 0; + + if (node) { + length = node->packet->size * 8; + init_get_bits(&gb, node->packet->data, length); + } + + if (length >= 32) { + int c = get_bits (&gb, 13); + + if (c > 3) + fill_coding_method_array (q->tone_level_idx, q->tone_level_idx_temp, q->coding_method, + q->nb_channels, 8*c, q->superblocktype_2_3, q->cm_table_select); + } + + synthfilt_build_sb_samples(q, &gb, length, 0, 8); +} + + +/** + * Process subpacket 12 + * + * @param q context + * @param node pointer to node with packet + */ +static void process_subpacket_12 (QDM2Context *q, QDM2SubPNode *node) +{ + GetBitContext gb; + int length = 0; + + if (node) { + length = node->packet->size * 8; + init_get_bits(&gb, node->packet->data, length); + } + + synthfilt_build_sb_samples(q, &gb, length, 8, QDM2_SB_USED(q->sub_sampling)); +} + +/** + * Process new subpackets for synthesis filter + * + * @param q context + * @param list list with synthesis filter packets (list D) + */ +static void process_synthesis_subpackets (QDM2Context *q, QDM2SubPNode *list) +{ + QDM2SubPNode *nodes[4]; + + nodes[0] = qdm2_search_subpacket_type_in_list(list, 9); + if (nodes[0] != NULL) + process_subpacket_9(q, nodes[0]); + + nodes[1] = qdm2_search_subpacket_type_in_list(list, 10); + if (nodes[1] != NULL) + process_subpacket_10(q, nodes[1]); + else + process_subpacket_10(q, NULL); + + nodes[2] = qdm2_search_subpacket_type_in_list(list, 11); + if (nodes[0] != NULL && nodes[1] != NULL && nodes[2] != NULL) + process_subpacket_11(q, nodes[2]); + else + process_subpacket_11(q, NULL); + + nodes[3] = qdm2_search_subpacket_type_in_list(list, 12); + if (nodes[0] != NULL && nodes[1] != NULL && nodes[3] != NULL) + process_subpacket_12(q, nodes[3]); + else + process_subpacket_12(q, NULL); +} + + +/** + * Decode superblock, fill packet lists. + * + * @param q context + */ +static void qdm2_decode_super_block (QDM2Context *q) +{ + GetBitContext gb; + QDM2SubPacket header, *packet; + int i, packet_bytes, sub_packet_size, sub_packets_D; + unsigned int next_index = 0; + + memset(q->tone_level_idx_hi1, 0, sizeof(q->tone_level_idx_hi1)); + memset(q->tone_level_idx_mid, 0, sizeof(q->tone_level_idx_mid)); + memset(q->tone_level_idx_hi2, 0, sizeof(q->tone_level_idx_hi2)); + + q->sub_packets_B = 0; + sub_packets_D = 0; + + average_quantized_coeffs(q); // average elements in quantized_coeffs[max_ch][10][8] + + init_get_bits(&gb, q->compressed_data, q->compressed_size*8); + qdm2_decode_sub_packet_header(&gb, &header); + + if (header.type < 2 || header.type >= 8) { + q->has_errors = 1; + av_log(NULL,AV_LOG_ERROR,"bad superblock type\n"); + return; + } + + q->superblocktype_2_3 = (header.type == 2 || header.type == 3); + packet_bytes = (q->compressed_size - get_bits_count(&gb) / 8); + + init_get_bits(&gb, header.data, header.size*8); + + if (header.type == 2 || header.type == 4 || header.type == 5) { + int csum = 257 * get_bits(&gb, 8); + csum += 2 * get_bits(&gb, 8); + + csum = qdm2_packet_checksum(q->compressed_data, q->checksum_size, csum); + + if (csum != 0) { + q->has_errors = 1; + av_log(NULL,AV_LOG_ERROR,"bad packet checksum\n"); + return; + } + } + + q->sub_packet_list_B[0].packet = NULL; + q->sub_packet_list_D[0].packet = NULL; + + for (i = 0; i < 6; i++) + if (--q->fft_level_exp[i] < 0) + q->fft_level_exp[i] = 0; + + for (i = 0; packet_bytes > 0; i++) { + int j; + + if (i >= FF_ARRAY_ELEMS(q->sub_packet_list_A)) { + SAMPLES_NEEDED_2("too many packet bytes"); + return; + } + + q->sub_packet_list_A[i].next = NULL; + + if (i > 0) { + q->sub_packet_list_A[i - 1].next = &q->sub_packet_list_A[i]; + + /* seek to next block */ + init_get_bits(&gb, header.data, header.size*8); + skip_bits(&gb, next_index*8); + + if (next_index >= header.size) + break; + } + + /* decode subpacket */ + packet = &q->sub_packets[i]; + qdm2_decode_sub_packet_header(&gb, packet); + next_index = packet->size + get_bits_count(&gb) / 8; + sub_packet_size = ((packet->size > 0xff) ? 1 : 0) + packet->size + 2; + + if (packet->type == 0) + break; + + if (sub_packet_size > packet_bytes) { + if (packet->type != 10 && packet->type != 11 && packet->type != 12) + break; + packet->size += packet_bytes - sub_packet_size; + } + + packet_bytes -= sub_packet_size; + + /* add subpacket to 'all subpackets' list */ + q->sub_packet_list_A[i].packet = packet; + + /* add subpacket to related list */ + if (packet->type == 8) { + SAMPLES_NEEDED_2("packet type 8"); + return; + } else if (packet->type >= 9 && packet->type <= 12) { + /* packets for MPEG Audio like Synthesis Filter */ + QDM2_LIST_ADD(q->sub_packet_list_D, sub_packets_D, packet); + } else if (packet->type == 13) { + for (j = 0; j < 6; j++) + q->fft_level_exp[j] = get_bits(&gb, 6); + } else if (packet->type == 14) { + for (j = 0; j < 6; j++) + q->fft_level_exp[j] = qdm2_get_vlc(&gb, &fft_level_exp_vlc, 0, 2); + } else if (packet->type == 15) { + SAMPLES_NEEDED_2("packet type 15") + return; + } else if (packet->type >= 16 && packet->type < 48 && !fft_subpackets[packet->type - 16]) { + /* packets for FFT */ + QDM2_LIST_ADD(q->sub_packet_list_B, q->sub_packets_B, packet); + } + } // Packet bytes loop + +/* **************************************************************** */ + if (q->sub_packet_list_D[0].packet != NULL) { + process_synthesis_subpackets(q, q->sub_packet_list_D); + q->do_synth_filter = 1; + } else if (q->do_synth_filter) { + process_subpacket_10(q, NULL); + process_subpacket_11(q, NULL); + process_subpacket_12(q, NULL); + } +/* **************************************************************** */ +} + + +static void qdm2_fft_init_coefficient (QDM2Context *q, int sub_packet, + int offset, int duration, int channel, + int exp, int phase) +{ + if (q->fft_coefs_min_index[duration] < 0) + q->fft_coefs_min_index[duration] = q->fft_coefs_index; + + q->fft_coefs[q->fft_coefs_index].sub_packet = ((sub_packet >= 16) ? (sub_packet - 16) : sub_packet); + q->fft_coefs[q->fft_coefs_index].channel = channel; + q->fft_coefs[q->fft_coefs_index].offset = offset; + q->fft_coefs[q->fft_coefs_index].exp = exp; + q->fft_coefs[q->fft_coefs_index].phase = phase; + q->fft_coefs_index++; +} + + +static void qdm2_fft_decode_tones (QDM2Context *q, int duration, GetBitContext *gb, int b) +{ + int channel, stereo, phase, exp; + int local_int_4, local_int_8, stereo_phase, local_int_10; + int local_int_14, stereo_exp, local_int_20, local_int_28; + int n, offset; + + local_int_4 = 0; + local_int_28 = 0; + local_int_20 = 2; + local_int_8 = (4 - duration); + local_int_10 = 1 << (q->group_order - duration - 1); + offset = 1; + + while (get_bits_left(gb)>0) { + if (q->superblocktype_2_3) { + while ((n = qdm2_get_vlc(gb, &vlc_tab_fft_tone_offset[local_int_8], 1, 2)) < 2) { + if (get_bits_left(gb)<0) { + if(local_int_4 < q->group_size) + av_log(NULL, AV_LOG_ERROR, "overread in qdm2_fft_decode_tones()\n"); + return; + } + offset = 1; + if (n == 0) { + local_int_4 += local_int_10; + local_int_28 += (1 << local_int_8); + } else { + local_int_4 += 8*local_int_10; + local_int_28 += (8 << local_int_8); + } + } + offset += (n - 2); + } else { + offset += qdm2_get_vlc(gb, &vlc_tab_fft_tone_offset[local_int_8], 1, 2); + while (offset >= (local_int_10 - 1)) { + offset += (1 - (local_int_10 - 1)); + local_int_4 += local_int_10; + local_int_28 += (1 << local_int_8); + } + } + + if (local_int_4 >= q->group_size) + return; + + local_int_14 = (offset >> local_int_8); + if (local_int_14 >= FF_ARRAY_ELEMS(fft_level_index_table)) + return; + + if (q->nb_channels > 1) { + channel = get_bits1(gb); + stereo = get_bits1(gb); + } else { + channel = 0; + stereo = 0; + } + + exp = qdm2_get_vlc(gb, (b ? &fft_level_exp_vlc : &fft_level_exp_alt_vlc), 0, 2); + exp += q->fft_level_exp[fft_level_index_table[local_int_14]]; + exp = (exp < 0) ? 0 : exp; + + phase = get_bits(gb, 3); + stereo_exp = 0; + stereo_phase = 0; + + if (stereo) { + stereo_exp = (exp - qdm2_get_vlc(gb, &fft_stereo_exp_vlc, 0, 1)); + stereo_phase = (phase - qdm2_get_vlc(gb, &fft_stereo_phase_vlc, 0, 1)); + if (stereo_phase < 0) + stereo_phase += 8; + } + + if (q->frequency_range > (local_int_14 + 1)) { + int sub_packet = (local_int_20 + local_int_28); + + qdm2_fft_init_coefficient(q, sub_packet, offset, duration, channel, exp, phase); + if (stereo) + qdm2_fft_init_coefficient(q, sub_packet, offset, duration, (1 - channel), stereo_exp, stereo_phase); + } + + offset++; + } +} + + +static void qdm2_decode_fft_packets (QDM2Context *q) +{ + int i, j, min, max, value, type, unknown_flag; + GetBitContext gb; + + if (q->sub_packet_list_B[0].packet == NULL) + return; + + /* reset minimum indexes for FFT coefficients */ + q->fft_coefs_index = 0; + for (i=0; i < 5; i++) + q->fft_coefs_min_index[i] = -1; + + /* process subpackets ordered by type, largest type first */ + for (i = 0, max = 256; i < q->sub_packets_B; i++) { + QDM2SubPacket *packet= NULL; + + /* find subpacket with largest type less than max */ + for (j = 0, min = 0; j < q->sub_packets_B; j++) { + value = q->sub_packet_list_B[j].packet->type; + if (value > min && value < max) { + min = value; + packet = q->sub_packet_list_B[j].packet; + } + } + + max = min; + + /* check for errors (?) */ + if (!packet) + return; + + if (i == 0 && (packet->type < 16 || packet->type >= 48 || fft_subpackets[packet->type - 16])) + return; + + /* decode FFT tones */ + init_get_bits (&gb, packet->data, packet->size*8); + + if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16]) + unknown_flag = 1; + else + unknown_flag = 0; + + type = packet->type; + + if ((type >= 17 && type < 24) || (type >= 33 && type < 40)) { + int duration = q->sub_sampling + 5 - (type & 15); + + if (duration >= 0 && duration < 4) + qdm2_fft_decode_tones(q, duration, &gb, unknown_flag); + } else if (type == 31) { + for (j=0; j < 4; j++) + qdm2_fft_decode_tones(q, j, &gb, unknown_flag); + } else if (type == 46) { + for (j=0; j < 6; j++) + q->fft_level_exp[j] = get_bits(&gb, 6); + for (j=0; j < 4; j++) + qdm2_fft_decode_tones(q, j, &gb, unknown_flag); + } + } // Loop on B packets + + /* calculate maximum indexes for FFT coefficients */ + for (i = 0, j = -1; i < 5; i++) + if (q->fft_coefs_min_index[i] >= 0) { + if (j >= 0) + q->fft_coefs_max_index[j] = q->fft_coefs_min_index[i]; + j = i; + } + if (j >= 0) + q->fft_coefs_max_index[j] = q->fft_coefs_index; +} + + +static void qdm2_fft_generate_tone (QDM2Context *q, FFTTone *tone) +{ + float level, f[6]; + int i; + QDM2Complex c; + const double iscale = 2.0*M_PI / 512.0; + + tone->phase += tone->phase_shift; + + /* calculate current level (maximum amplitude) of tone */ + level = fft_tone_envelope_table[tone->duration][tone->time_index] * tone->level; + c.im = level * sin(tone->phase*iscale); + c.re = level * cos(tone->phase*iscale); + + /* generate FFT coefficients for tone */ + if (tone->duration >= 3 || tone->cutoff >= 3) { + tone->complex[0].im += c.im; + tone->complex[0].re += c.re; + tone->complex[1].im -= c.im; + tone->complex[1].re -= c.re; + } else { + f[1] = -tone->table[4]; + f[0] = tone->table[3] - tone->table[0]; + f[2] = 1.0 - tone->table[2] - tone->table[3]; + f[3] = tone->table[1] + tone->table[4] - 1.0; + f[4] = tone->table[0] - tone->table[1]; + f[5] = tone->table[2]; + for (i = 0; i < 2; i++) { + tone->complex[fft_cutoff_index_table[tone->cutoff][i]].re += c.re * f[i]; + tone->complex[fft_cutoff_index_table[tone->cutoff][i]].im += c.im *((tone->cutoff <= i) ? -f[i] : f[i]); + } + for (i = 0; i < 4; i++) { + tone->complex[i].re += c.re * f[i+2]; + tone->complex[i].im += c.im * f[i+2]; + } + } + + /* copy the tone if it has not yet died out */ + if (++tone->time_index < ((1 << (5 - tone->duration)) - 1)) { + memcpy(&q->fft_tones[q->fft_tone_end], tone, sizeof(FFTTone)); + q->fft_tone_end = (q->fft_tone_end + 1) % 1000; + } +} + + +static void qdm2_fft_tone_synthesizer (QDM2Context *q, int sub_packet) +{ + int i, j, ch; + const double iscale = 0.25 * M_PI; + + for (ch = 0; ch < q->channels; ch++) { + memset(q->fft.complex[ch], 0, q->fft_size * sizeof(QDM2Complex)); + } + + + /* apply FFT tones with duration 4 (1 FFT period) */ + if (q->fft_coefs_min_index[4] >= 0) + for (i = q->fft_coefs_min_index[4]; i < q->fft_coefs_max_index[4]; i++) { + float level; + QDM2Complex c; + + if (q->fft_coefs[i].sub_packet != sub_packet) + break; + + ch = (q->channels == 1) ? 0 : q->fft_coefs[i].channel; + level = (q->fft_coefs[i].exp < 0) ? 0.0 : fft_tone_level_table[q->superblocktype_2_3 ? 0 : 1][q->fft_coefs[i].exp & 63]; + + c.re = level * cos(q->fft_coefs[i].phase * iscale); + c.im = level * sin(q->fft_coefs[i].phase * iscale); + q->fft.complex[ch][q->fft_coefs[i].offset + 0].re += c.re; + q->fft.complex[ch][q->fft_coefs[i].offset + 0].im += c.im; + q->fft.complex[ch][q->fft_coefs[i].offset + 1].re -= c.re; + q->fft.complex[ch][q->fft_coefs[i].offset + 1].im -= c.im; + } + + /* generate existing FFT tones */ + for (i = q->fft_tone_end; i != q->fft_tone_start; ) { + qdm2_fft_generate_tone(q, &q->fft_tones[q->fft_tone_start]); + q->fft_tone_start = (q->fft_tone_start + 1) % 1000; + } + + /* create and generate new FFT tones with duration 0 (long) to 3 (short) */ + for (i = 0; i < 4; i++) + if (q->fft_coefs_min_index[i] >= 0) { + for (j = q->fft_coefs_min_index[i]; j < q->fft_coefs_max_index[i]; j++) { + int offset, four_i; + FFTTone tone; + + if (q->fft_coefs[j].sub_packet != sub_packet) + break; + + four_i = (4 - i); + offset = q->fft_coefs[j].offset >> four_i; + ch = (q->channels == 1) ? 0 : q->fft_coefs[j].channel; + + if (offset < q->frequency_range) { + if (offset < 2) + tone.cutoff = offset; + else + tone.cutoff = (offset >= 60) ? 3 : 2; + + tone.level = (q->fft_coefs[j].exp < 0) ? 0.0 : fft_tone_level_table[q->superblocktype_2_3 ? 0 : 1][q->fft_coefs[j].exp & 63]; + tone.complex = &q->fft.complex[ch][offset]; + tone.table = fft_tone_sample_table[i][q->fft_coefs[j].offset - (offset << four_i)]; + tone.phase = 64 * q->fft_coefs[j].phase - (offset << 8) - 128; + tone.phase_shift = (2 * q->fft_coefs[j].offset + 1) << (7 - four_i); + tone.duration = i; + tone.time_index = 0; + + qdm2_fft_generate_tone(q, &tone); + } + } + q->fft_coefs_min_index[i] = j; + } +} + + +static void qdm2_calculate_fft (QDM2Context *q, int channel, int sub_packet) +{ + const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.5f : 1.0f; + float *out = q->output_buffer + channel; + int i; + q->fft.complex[channel][0].re *= 2.0f; + q->fft.complex[channel][0].im = 0.0f; + q->rdft_ctx.rdft_calc(&q->rdft_ctx, (FFTSample *)q->fft.complex[channel]); + /* add samples to output buffer */ + for (i = 0; i < FFALIGN(q->fft_size, 8); i++) { + out[0] += q->fft.complex[channel][i].re * gain; + out[q->channels] += q->fft.complex[channel][i].im * gain; + out += 2 * q->channels; + } +} + + +/** + * @param q context + * @param index subpacket number + */ +static void qdm2_synthesis_filter (QDM2Context *q, int index) +{ + int i, k, ch, sb_used, sub_sampling, dither_state = 0; + + /* copy sb_samples */ + sb_used = QDM2_SB_USED(q->sub_sampling); + + for (ch = 0; ch < q->channels; ch++) + for (i = 0; i < 8; i++) + for (k=sb_used; k < SBLIMIT; k++) + q->sb_samples[ch][(8 * index) + i][k] = 0; + + for (ch = 0; ch < q->nb_channels; ch++) { + float *samples_ptr = q->samples + ch; + + for (i = 0; i < 8; i++) { + ff_mpa_synth_filter_float(&q->mpadsp, + q->synth_buf[ch], &(q->synth_buf_offset[ch]), + ff_mpa_synth_window_float, &dither_state, + samples_ptr, q->nb_channels, + q->sb_samples[ch][(8 * index) + i]); + samples_ptr += 32 * q->nb_channels; + } + } + + /* add samples to output buffer */ + sub_sampling = (4 >> q->sub_sampling); + + for (ch = 0; ch < q->channels; ch++) + for (i = 0; i < q->frame_size; i++) + q->output_buffer[q->channels * i + ch] += (1 << 23) * q->samples[q->nb_channels * sub_sampling * i + ch]; +} + + +/** + * Init static data (does not depend on specific file) + * + * @param q context + */ +static av_cold void qdm2_init(QDM2Context *q) { + static int initialized = 0; + + if (initialized != 0) + return; + initialized = 1; + + qdm2_init_vlc(); + ff_mpa_synth_init_float(ff_mpa_synth_window_float); + softclip_table_init(); + rnd_table_init(); + init_noise_samples(); + + av_log(NULL, AV_LOG_DEBUG, "init done\n"); +} + + +/** + * Init parameters from codec extradata + */ +static av_cold int qdm2_decode_init(AVCodecContext *avctx) +{ + QDM2Context *s = avctx->priv_data; + uint8_t *extradata; + int extradata_size; + int tmp_val, tmp, size; + + /* extradata parsing + + Structure: + wave { + frma (QDM2) + QDCA + QDCP + } + + 32 size (including this field) + 32 tag (=frma) + 32 type (=QDM2 or QDMC) + + 32 size (including this field, in bytes) + 32 tag (=QDCA) // maybe mandatory parameters + 32 unknown (=1) + 32 channels (=2) + 32 samplerate (=44100) + 32 bitrate (=96000) + 32 block size (=4096) + 32 frame size (=256) (for one channel) + 32 packet size (=1300) + + 32 size (including this field, in bytes) + 32 tag (=QDCP) // maybe some tuneable parameters + 32 float1 (=1.0) + 32 zero ? + 32 float2 (=1.0) + 32 float3 (=1.0) + 32 unknown (27) + 32 unknown (8) + 32 zero ? + */ + + if (!avctx->extradata || (avctx->extradata_size < 48)) { + av_log(avctx, AV_LOG_ERROR, "extradata missing or truncated\n"); + return -1; + } + + extradata = avctx->extradata; + extradata_size = avctx->extradata_size; + + while (extradata_size > 7) { + if (!memcmp(extradata, "frmaQDM", 7)) + break; + extradata++; + extradata_size--; + } + + if (extradata_size < 12) { + av_log(avctx, AV_LOG_ERROR, "not enough extradata (%i)\n", + extradata_size); + return -1; + } + + if (memcmp(extradata, "frmaQDM", 7)) { + av_log(avctx, AV_LOG_ERROR, "invalid headers, QDM? not found\n"); + return -1; + } + + if (extradata[7] == 'C') { +// s->is_qdmc = 1; + av_log(avctx, AV_LOG_ERROR, "stream is QDMC version 1, which is not supported\n"); + return -1; + } + + extradata += 8; + extradata_size -= 8; + + size = AV_RB32(extradata); + + if(size > extradata_size){ + av_log(avctx, AV_LOG_ERROR, "extradata size too small, %i < %i\n", + extradata_size, size); + return -1; + } + + extradata += 4; + av_log(avctx, AV_LOG_DEBUG, "size: %d\n", size); + if (AV_RB32(extradata) != MKBETAG('Q','D','C','A')) { + av_log(avctx, AV_LOG_ERROR, "invalid extradata, expecting QDCA\n"); + return -1; + } + + extradata += 8; + + avctx->channels = s->nb_channels = s->channels = AV_RB32(extradata); + extradata += 4; + if (s->channels <= 0 || s->channels > MPA_MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } + avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + + avctx->sample_rate = AV_RB32(extradata); + extradata += 4; + + avctx->bit_rate = AV_RB32(extradata); + extradata += 4; + + s->group_size = AV_RB32(extradata); + extradata += 4; + + s->fft_size = AV_RB32(extradata); + extradata += 4; + + s->checksum_size = AV_RB32(extradata); + if (s->checksum_size >= 1U << 28) { + av_log(avctx, AV_LOG_ERROR, "data block size too large (%u)\n", s->checksum_size); + return AVERROR_INVALIDDATA; + } + + s->fft_order = av_log2(s->fft_size) + 1; + + // something like max decodable tones + s->group_order = av_log2(s->group_size) + 1; + s->frame_size = s->group_size / 16; // 16 iterations per super block + + if (s->frame_size > QDM2_MAX_FRAME_SIZE) + return AVERROR_INVALIDDATA; + + s->sub_sampling = s->fft_order - 7; + s->frequency_range = 255 / (1 << (2 - s->sub_sampling)); + + switch ((s->sub_sampling * 2 + s->channels - 1)) { + case 0: tmp = 40; break; + case 1: tmp = 48; break; + case 2: tmp = 56; break; + case 3: tmp = 72; break; + case 4: tmp = 80; break; + case 5: tmp = 100;break; + default: tmp=s->sub_sampling; break; + } + tmp_val = 0; + if ((tmp * 1000) < avctx->bit_rate) tmp_val = 1; + if ((tmp * 1440) < avctx->bit_rate) tmp_val = 2; + if ((tmp * 1760) < avctx->bit_rate) tmp_val = 3; + if ((tmp * 2240) < avctx->bit_rate) tmp_val = 4; + s->cm_table_select = tmp_val; + + if (s->sub_sampling == 0) + tmp = 7999; + else + tmp = ((-(s->sub_sampling -1)) & 8000) + 20000; + /* + 0: 7999 -> 0 + 1: 20000 -> 2 + 2: 28000 -> 2 + */ + if (tmp < 8000) + s->coeff_per_sb_select = 0; + else if (tmp <= 16000) + s->coeff_per_sb_select = 1; + else + s->coeff_per_sb_select = 2; + + // Fail on unknown fft order + if ((s->fft_order < 7) || (s->fft_order > 9)) { + av_log(avctx, AV_LOG_ERROR, "Unknown FFT order (%d), contact the developers!\n", s->fft_order); + return -1; + } + + ff_rdft_init(&s->rdft_ctx, s->fft_order, IDFT_C2R); + ff_mpadsp_init(&s->mpadsp); + + qdm2_init(s); + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + + +static av_cold int qdm2_decode_close(AVCodecContext *avctx) +{ + QDM2Context *s = avctx->priv_data; + + ff_rdft_end(&s->rdft_ctx); + + return 0; +} + + +static int qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out) +{ + int ch, i; + const int frame_size = (q->frame_size * q->channels); + + if((unsigned)frame_size > FF_ARRAY_ELEMS(q->output_buffer)/2) + return -1; + + /* select input buffer */ + q->compressed_data = in; + q->compressed_size = q->checksum_size; + + /* copy old block, clear new block of output samples */ + memmove(q->output_buffer, &q->output_buffer[frame_size], frame_size * sizeof(float)); + memset(&q->output_buffer[frame_size], 0, frame_size * sizeof(float)); + + /* decode block of QDM2 compressed data */ + if (q->sub_packet == 0) { + q->has_errors = 0; // zero it for a new super block + av_log(NULL,AV_LOG_DEBUG,"Superblock follows\n"); + qdm2_decode_super_block(q); + } + + /* parse subpackets */ + if (!q->has_errors) { + if (q->sub_packet == 2) + qdm2_decode_fft_packets(q); + + qdm2_fft_tone_synthesizer(q, q->sub_packet); + } + + /* sound synthesis stage 1 (FFT) */ + for (ch = 0; ch < q->channels; ch++) { + qdm2_calculate_fft(q, ch, q->sub_packet); + + if (!q->has_errors && q->sub_packet_list_C[0].packet != NULL) { + SAMPLES_NEEDED_2("has errors, and C list is not empty") + return -1; + } + } + + /* sound synthesis stage 2 (MPEG audio like synthesis filter) */ + if (!q->has_errors && q->do_synth_filter) + qdm2_synthesis_filter(q, q->sub_packet); + + q->sub_packet = (q->sub_packet + 1) % 16; + + /* clip and convert output float[] to 16bit signed samples */ + for (i = 0; i < frame_size; i++) { + int value = (int)q->output_buffer[i]; + + if (value > SOFTCLIP_THRESHOLD) + value = (value > HARDCLIP_THRESHOLD) ? 32767 : softclip_table[ value - SOFTCLIP_THRESHOLD]; + else if (value < -SOFTCLIP_THRESHOLD) + value = (value < -HARDCLIP_THRESHOLD) ? -32767 : -softclip_table[-value - SOFTCLIP_THRESHOLD]; + + out[i] = value; + } + + return 0; +} + + +static int qdm2_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + QDM2Context *s = avctx->priv_data; + int16_t *out; + int i, ret; + + if(!buf) + return 0; + if(buf_size < s->checksum_size) + return -1; + + /* get output buffer */ + frame->nb_samples = 16 * s->frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + out = (int16_t *)frame->data[0]; + + for (i = 0; i < 16; i++) { + if (qdm2_decode(s, buf, out) < 0) + return -1; + out += s->channels * s->frame_size; + } + + *got_frame_ptr = 1; + + return s->checksum_size; +} + +AVCodec ff_qdm2_decoder = +{ + .name = "qdm2", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_QDM2, + .priv_data_size = sizeof(QDM2Context), + .init = qdm2_decode_init, + .close = qdm2_decode_close, + .decode = qdm2_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), +}; diff --git a/ffmpeg/libavcodec/qdm2_tablegen.c b/ffmpeg/libavcodec/qdm2_tablegen.c new file mode 100644 index 0000000..a7a9fb6 --- /dev/null +++ b/ffmpeg/libavcodec/qdm2_tablegen.c @@ -0,0 +1,44 @@ +/* + * Generate a header file for hardcoded QDM2 tables + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#include "qdm2_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + softclip_table_init(); + rnd_table_init(); + init_noise_samples(); + + write_fileheader(); + + WRITE_ARRAY("static const", uint16_t, softclip_table); + WRITE_ARRAY("static const", float, noise_table); + WRITE_ARRAY("static const", float, noise_samples); + + WRITE_2D_ARRAY("static const", uint8_t, random_dequant_index); + WRITE_2D_ARRAY("static const", uint8_t, random_dequant_type24); + + return 0; +} diff --git a/ffmpeg/libavcodec/qdm2_tablegen.h b/ffmpeg/libavcodec/qdm2_tablegen.h new file mode 100644 index 0000000..13ec9be --- /dev/null +++ b/ffmpeg/libavcodec/qdm2_tablegen.h @@ -0,0 +1,97 @@ +/* + * Header file for hardcoded QDM2 tables + * + * Copyright (c) 2010 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_QDM2_TABLEGEN_H +#define AVCODEC_QDM2_TABLEGEN_H + +#include +#include +#include "libavutil/attributes.h" + +#define SOFTCLIP_THRESHOLD 27600 +#define HARDCLIP_THRESHOLD 35716 + +#if CONFIG_HARDCODED_TABLES +#define softclip_table_init() +#define rnd_table_init() +#define init_noise_samples() +#include "libavcodec/qdm2_tables.h" +#else +static uint16_t softclip_table[HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1]; +static float noise_table[4096 + 20]; +static uint8_t random_dequant_index[256][5]; +static uint8_t random_dequant_type24[128][3]; +static float noise_samples[128]; + +static av_cold void softclip_table_init(void) { + int i; + double dfl = SOFTCLIP_THRESHOLD - 32767; + float delta = 1.0 / -dfl; + for (i = 0; i < HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1; i++) + softclip_table[i] = SOFTCLIP_THRESHOLD - ((int)(sin((float)i * delta) * dfl) & 0x0000FFFF); +} + + +// random generated table +static av_cold void rnd_table_init(void) { + int i,j; + uint32_t ldw; + uint64_t random_seed = 0; + float delta = 1.0 / 16384.0; + for(i = 0; i < 4096 ;i++) { + random_seed = random_seed * 214013 + 2531011; + noise_table[i] = (delta * (float)(((int32_t)random_seed >> 16) & 0x00007FFF)- 1.0) * 1.3; + } + + for (i = 0; i < 256 ;i++) { + random_seed = 81; + ldw = i; + for (j = 0; j < 5 ;j++) { + random_dequant_index[i][j] = ldw / random_seed; + ldw %= random_seed; + random_seed /= 3; + } + } + for (i = 0; i < 128 ;i++) { + random_seed = 25; + ldw = i; + for (j = 0; j < 3 ;j++) { + random_dequant_type24[i][j] = ldw / random_seed; + ldw %= random_seed; + random_seed /= 5; + } + } +} + + +static av_cold void init_noise_samples(void) { + int i; + unsigned random_seed = 0; + float delta = 1.0 / 16384.0; + for (i = 0; i < 128;i++) { + random_seed = random_seed * 214013 + 2531011; + noise_samples[i] = (delta * (float)((random_seed >> 16) & 0x00007fff) - 1.0); + } +} +#endif /* CONFIG_HARDCODED_TABLES */ + +#endif /* AVCODEC_QDM2_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/qdm2data.h b/ffmpeg/libavcodec/qdm2data.h new file mode 100644 index 0000000..355d613 --- /dev/null +++ b/ffmpeg/libavcodec/qdm2data.h @@ -0,0 +1,531 @@ +/* + * QDM2 compatible decoder + * Copyright (c) 2003 Ewald Snel + * Copyright (c) 2005 Benjamin Larsson + * Copyright (c) 2005 Alex Beregszaszi + * Copyright (c) 2005 Roberto Togni + * + * 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 + */ + + /** + * @file + * Various QDM2 tables. + */ + +#ifndef AVCODEC_QDM2DATA_H +#define AVCODEC_QDM2DATA_H + +#include + +/** VLC TABLES **/ + +/* values in this table range from -1..23; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_level_huffcodes[24] = { + 0x037c, 0x0004, 0x003c, 0x004c, 0x003a, 0x002c, 0x001c, 0x001a, + 0x0024, 0x0014, 0x0001, 0x0002, 0x0000, 0x0003, 0x0007, 0x0005, + 0x0006, 0x0008, 0x0009, 0x000a, 0x000c, 0x00fc, 0x007c, 0x017c +}; + +static const uint8_t vlc_tab_level_huffbits[24] = { + 10, 6, 7, 7, 6, 6, 6, 6, 6, 5, 4, 4, 4, 3, 3, 3, 3, 4, 4, 5, 7, 8, 9, 10 +}; + +/* values in this table range from -1..36; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_diff_huffcodes[37] = { + 0x1c57, 0x0004, 0x0000, 0x0001, 0x0003, 0x0002, 0x000f, 0x000e, + 0x0007, 0x0016, 0x0037, 0x0027, 0x0026, 0x0066, 0x0006, 0x0097, + 0x0046, 0x01c6, 0x0017, 0x0786, 0x0086, 0x0257, 0x00d7, 0x0357, + 0x00c6, 0x0386, 0x0186, 0x0000, 0x0157, 0x0c57, 0x0057, 0x0000, + 0x0b86, 0x0000, 0x1457, 0x0000, 0x0457 +}; + +static const uint8_t vlc_tab_diff_huffbits[37] = { + 13, 3, 3, 2, 3, 3, 4, 4, 6, 5, 6, 6, 7, 7, 8, 8, + 8, 9, 8, 11, 9, 10, 8, 10, 9, 12, 10, 0, 10, 13, 11, 0, + 12, 0, 13, 0, 13 +}; + +/* values in this table range from -1..5; adjust retrieved value by -1 */ +static const uint8_t vlc_tab_run_huffcodes[6] = { + 0x1f, 0x00, 0x01, 0x03, 0x07, 0x0f +}; + +static const uint8_t vlc_tab_run_huffbits[6] = { + 5, 1, 2, 3, 4, 5 +}; + +/* values in this table range from -1..19; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_tone_level_idx_hi1_huffcodes[20] = { + 0x5714, 0x000c, 0x0002, 0x0001, 0x0000, 0x0004, 0x0034, 0x0054, + 0x0094, 0x0014, 0x0114, 0x0214, 0x0314, 0x0614, 0x0e14, 0x0f14, + 0x2714, 0x0714, 0x1714, 0x3714 +}; + +static const uint8_t vlc_tab_tone_level_idx_hi1_huffbits[20] = { + 15, 4, 2, 1, 3, 5, 6, 7, 8, 10, 10, 11, 11, 12, 12, 12, 14, 14, 15, 14 +}; + +/* values in this table range from -1..23; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_tone_level_idx_mid_huffcodes[24] = { + 0x0fea, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x03ea, 0x00ea, 0x002a, 0x001a, + 0x0006, 0x0001, 0x0000, 0x0002, 0x000a, 0x006a, 0x01ea, 0x07ea +}; + +static const uint8_t vlc_tab_tone_level_idx_mid_huffbits[24] = { + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 7, 5, 3, 1, 2, 4, 6, 8, 10, 12 +}; + +/* values in this table range from -1..23; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_tone_level_idx_hi2_huffcodes[24] = { + 0x0664, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0064, 0x00e4, + 0x00a4, 0x0068, 0x0004, 0x0008, 0x0014, 0x0018, 0x0000, 0x0001, + 0x0002, 0x0003, 0x000c, 0x0028, 0x0024, 0x0164, 0x0000, 0x0264 +}; + +static const uint8_t vlc_tab_tone_level_idx_hi2_huffbits[24] = { + 11, 0, 0, 0, 0, 0, 10, 8, 8, 7, 6, 6, 5, 5, 4, 2, 2, 2, 4, 7, 8, 9, 0, 11 +}; + +/* values in this table range from -1..8; adjust retrieved value by -1 */ +static const uint8_t vlc_tab_type30_huffcodes[9] = { + 0x3c, 0x06, 0x00, 0x01, 0x03, 0x02, 0x04, 0x0c, 0x1c +}; + +static const uint8_t vlc_tab_type30_huffbits[9] = { + 6, 3, 3, 2, 2, 3, 4, 5, 6 +}; + +/* values in this table range from -1..9; adjust retrieved value by -1 */ +static const uint8_t vlc_tab_type34_huffcodes[10] = { + 0x18, 0x00, 0x01, 0x04, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08 +}; + +static const uint8_t vlc_tab_type34_huffbits[10] = { + 5, 4, 3, 3, 3, 3, 3, 3, 3, 5 +}; + +/* values in this table range from -1..22; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_fft_tone_offset_0_huffcodes[23] = { + 0x038e, 0x0001, 0x0000, 0x0022, 0x000a, 0x0006, 0x0012, 0x0002, + 0x001e, 0x003e, 0x0056, 0x0016, 0x000e, 0x0032, 0x0072, 0x0042, + 0x008e, 0x004e, 0x00f2, 0x002e, 0x0036, 0x00c2, 0x018e +}; + +static const uint8_t vlc_tab_fft_tone_offset_0_huffbits[23] = { + 10, 1, 2, 6, 4, 5, 6, 7, 6, 6, 7, 7, 8, 7, 8, 8, 9, 7, 8, 6, 6, 8, 10 +}; + +/* values in this table range from -1..27; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_fft_tone_offset_1_huffcodes[28] = { + 0x07a4, 0x0001, 0x0020, 0x0012, 0x001c, 0x0008, 0x0006, 0x0010, + 0x0000, 0x0014, 0x0004, 0x0032, 0x0070, 0x000c, 0x0002, 0x003a, + 0x001a, 0x002c, 0x002a, 0x0022, 0x0024, 0x000a, 0x0064, 0x0030, + 0x0062, 0x00a4, 0x01a4, 0x03a4 +}; + +static const uint8_t vlc_tab_fft_tone_offset_1_huffbits[28] = { + 11, 1, 6, 6, 5, 4, 3, 6, 6, 5, 6, 6, 7, 6, 6, 6, + 6, 6, 6, 7, 8, 6, 7, 7, 7, 9, 10, 11 +}; + +/* values in this table range from -1..31; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_fft_tone_offset_2_huffcodes[32] = { + 0x1760, 0x0001, 0x0000, 0x0082, 0x000c, 0x0006, 0x0003, 0x0007, + 0x0008, 0x0004, 0x0010, 0x0012, 0x0022, 0x001a, 0x0000, 0x0020, + 0x000a, 0x0040, 0x004a, 0x006a, 0x002a, 0x0042, 0x0002, 0x0060, + 0x00aa, 0x00e0, 0x00c2, 0x01c2, 0x0160, 0x0360, 0x0760, 0x0f60 +}; + +static const uint8_t vlc_tab_fft_tone_offset_2_huffbits[32] = { + 13, 2, 0, 8, 4, 3, 3, 3, 4, 4, 5, 5, 6, 5, 7, 7, + 7, 7, 7, 7, 8, 8, 8, 9, 8, 8, 9, 9, 10, 11, 13, 12 +}; + +/* values in this table range from -1..34; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_fft_tone_offset_3_huffcodes[35] = { + 0x33ea, 0x0005, 0x0000, 0x000c, 0x0000, 0x0006, 0x0003, 0x0008, + 0x0002, 0x0001, 0x0004, 0x0007, 0x001a, 0x000f, 0x001c, 0x002c, + 0x000a, 0x001d, 0x002d, 0x002a, 0x000d, 0x004c, 0x008c, 0x006a, + 0x00cd, 0x004d, 0x00ea, 0x020c, 0x030c, 0x010c, 0x01ea, 0x07ea, + 0x0bea, 0x03ea, 0x13ea +}; + +static const uint8_t vlc_tab_fft_tone_offset_3_huffbits[35] = { + 14, 4, 0, 10, 4, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6, + 6, 5, 6, 7, 7, 7, 8, 8, 8, 8, 9, 10, 10, 10, 10, 11, + 12, 13, 14 +}; + +/* values in this table range from -1..37; adjust retrieved value by -1 */ +static const uint16_t vlc_tab_fft_tone_offset_4_huffcodes[38] = { + 0x5282, 0x0016, 0x0000, 0x0136, 0x0004, 0x0000, 0x0007, 0x000a, + 0x000e, 0x0003, 0x0001, 0x000d, 0x0006, 0x0009, 0x0012, 0x0005, + 0x0025, 0x0022, 0x0015, 0x0002, 0x0076, 0x0035, 0x0042, 0x00c2, + 0x0182, 0x00b6, 0x0036, 0x03c2, 0x0482, 0x01c2, 0x0682, 0x0882, + 0x0a82, 0x0082, 0x0282, 0x1282, 0x3282, 0x2282 +}; + +static const uint8_t vlc_tab_fft_tone_offset_4_huffbits[38] = { + 15, 6, 0, 9, 3, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 6, + 6, 6, 6, 8, 7, 6, 8, 9, 9, 8, 9, 10, 11, 10, 11, 12, + 12, 12, 14, 15, 14, 14 +}; + +/** FFT TABLES **/ + +/* values in this table range from -1..27; adjust retrieved value by -1 */ +static const uint16_t fft_level_exp_alt_huffcodes[28] = { + 0x1ec6, 0x0006, 0x00c2, 0x0142, 0x0242, 0x0246, 0x00c6, 0x0046, + 0x0042, 0x0146, 0x00a2, 0x0062, 0x0026, 0x0016, 0x000e, 0x0005, + 0x0004, 0x0003, 0x0000, 0x0001, 0x000a, 0x0012, 0x0002, 0x0022, + 0x01c6, 0x02c6, 0x06c6, 0x0ec6 +}; + +static const uint8_t fft_level_exp_alt_huffbits[28] = { + 13, 7, 8, 9, 10, 10, 10, 10, 10, 9, 8, 7, 6, 5, 4, 3, + 3, 2, 3, 3, 4, 5, 7, 8, 9, 11, 12, 13 +}; + +/* values in this table range from -1..19; adjust retrieved value by -1 */ +static const uint16_t fft_level_exp_huffcodes[20] = { + 0x0f24, 0x0001, 0x0002, 0x0000, 0x0006, 0x0005, 0x0007, 0x000c, + 0x000b, 0x0014, 0x0013, 0x0004, 0x0003, 0x0023, 0x0064, 0x00a4, + 0x0024, 0x0124, 0x0324, 0x0724 +}; + +static const uint8_t fft_level_exp_huffbits[20] = { + 12, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 12 +}; + +/* values in this table range from -1..6; adjust retrieved value by -1 */ +static const uint8_t fft_stereo_exp_huffcodes[7] = { + 0x3e, 0x01, 0x00, 0x02, 0x06, 0x0e, 0x1e +}; + +static const uint8_t fft_stereo_exp_huffbits[7] = { + 6, 1, 2, 3, 4, 5, 6 +}; + +/* values in this table range from -1..8; adjust retrieved value by -1 */ +static const uint8_t fft_stereo_phase_huffcodes[9] = { + 0x35, 0x02, 0x00, 0x01, 0x0d, 0x15, 0x05, 0x09, 0x03 +}; + +static const uint8_t fft_stereo_phase_huffbits[9] = { + 6, 2, 2, 4, 4, 6, 5, 4, 2 +}; + +static const int fft_cutoff_index_table[4][2] = { + { 1, 2 }, {-1, 0 }, {-1,-2 }, { 0, 0 } +}; + +static const int16_t fft_level_index_table[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const uint8_t last_coeff[3] = { + 4, 7, 10 +}; + +static const uint8_t coeff_per_sb_for_avg[3][30] = { + { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + { 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }, + { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 } +}; + +static const uint32_t dequant_table[3][10][30] = { + { { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 256, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 51, 102, 154, 205, 256, 238, 219, 201, 183, 165, 146, 128, 110, 91, 73, 55, 37, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256, 228, 199, 171, 142, 114, 85, 57, 28 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 85, 171, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 85, 171, 256, 219, 183, 146, 110, 73, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 73, 110, 146, 183, 219, 256, 228, 199, 171, 142, 114, 85, 57, 28, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 57, 85, 114, 142, 171, 199, 228, 256, 213, 171, 128, 85, 43 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { { 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 85, 171, 256, 192, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 128, 192, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 102, 154, 205, 256, 213, 171, 128, 85, 43, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 85, 128, 171, 213, 256, 213, 171, 128, 85, 43 } } +}; + +static const uint8_t coeff_per_sb_for_dequant[3][30] = { + { 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + { 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 }, + { 0, 1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9 } +}; + +/* first index is subband, 2nd index is 0, 1 or 3 (2 is unused) */ +static const int8_t tone_level_idx_offset_table[30][4] = { + { -50, -50, 0, -50 }, + { -50, -50, 0, -50 }, + { -50, -9, 0, -19 }, + { -16, -6, 0, -12 }, + { -11, -4, 0, -8 }, + { -8, -3, 0, -6 }, + { -7, -3, 0, -5 }, + { -6, -2, 0, -4 }, + { -5, -2, 0, -3 }, + { -4, -1, 0, -3 }, + { -4, -1, 0, -2 }, + { -3, -1, 0, -2 }, + { -3, -1, 0, -2 }, + { -3, -1, 0, -2 }, + { -2, -1, 0, -1 }, + { -2, -1, 0, -1 }, + { -2, -1, 0, -1 }, + { -2, 0, 0, -1 }, + { -2, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, -1 }, + { -1, 0, 0, 0 }, + { -1, 0, 0, 0 }, + { -1, 0, 0, 0 }, + { -1, 0, 0, 0 } +}; + +/* all my samples have 1st index 0 or 1 */ +/* second index is subband, only indexes 0-29 seem to be used */ +static const int8_t coding_method_table[5][30] = { + { 34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 + }, + { 34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 + }, + { 34, 30, 30, 30, 24, 24, 16, 16, 16, 16, 16, 16, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 + }, + { 34, 34, 30, 30, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10, 10 + }, + { 34, 34, 30, 30, 30, 30, 30, 30, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 + }, +}; + +static const int vlc_stage3_values[60] = { + 0, 1, 2, 3, 4, 6, 8, 10, 12, 16, 20, 24, + 28, 36, 44, 52, 60, 76, 92, 108, 124, 156, 188, 220, + 252, 316, 380, 444, 508, 636, 764, 892, 1020, 1276, 1532, 1788, + 2044, 2556, 3068, 3580, 4092, 5116, 6140, 7164, 8188, 10236, 12284, 14332, + 16380, 20476, 24572, 28668, 32764, 40956, 49148, 57340, 65532, 81916, 98300,114684 +}; + +static const float fft_tone_sample_table[4][16][5] = { + { { .0100000000f,-.0037037037f,-.0020000000f,-.0069444444f,-.0018416207f }, + { .0416666667f, .0000000000f, .0000000000f,-.0208333333f,-.0123456791f }, + { .1250000000f, .0558035709f, .0330687836f,-.0164473690f,-.0097465888f }, + { .1562500000f, .0625000000f, .0370370370f,-.0062500000f,-.0037037037f }, + { .1996007860f, .0781250000f, .0462962948f, .0022727272f, .0013468013f }, + { .2000000000f, .0625000000f, .0370370373f, .0208333333f, .0074074073f }, + { .2127659619f, .0555555556f, .0329218097f, .0208333333f, .0123456791f }, + { .2173913121f, .0473484844f, .0280583613f, .0347222239f, .0205761325f }, + { .2173913121f, .0347222239f, .0205761325f, .0473484844f, .0280583613f }, + { .2127659619f, .0208333333f, .0123456791f, .0555555556f, .0329218097f }, + { .2000000000f, .0208333333f, .0074074073f, .0625000000f, .0370370370f }, + { .1996007860f, .0022727272f, .0013468013f, .0781250000f, .0462962948f }, + { .1562500000f,-.0062500000f,-.0037037037f, .0625000000f, .0370370370f }, + { .1250000000f,-.0164473690f,-.0097465888f, .0558035709f, .0330687836f }, + { .0416666667f,-.0208333333f,-.0123456791f, .0000000000f, .0000000000f }, + { .0100000000f,-.0069444444f,-.0018416207f,-.0037037037f,-.0020000000f } }, + + { { .0050000000f,-.0200000000f, .0125000000f,-.3030303030f, .0020000000f }, + { .1041666642f, .0400000000f,-.0250000000f, .0333333333f,-.0200000000f }, + { .1250000000f, .0100000000f, .0142857144f,-.0500000007f,-.0200000000f }, + { .1562500000f,-.0006250000f,-.00049382716f,-.000625000f,-.00049382716f }, + { .1562500000f,-.0006250000f,-.00049382716f,-.000625000f,-.00049382716f }, + { .1250000000f,-.0500000000f,-.0200000000f, .0100000000f, .0142857144f }, + { .1041666667f, .0333333333f,-.0200000000f, .0400000000f,-.0250000000f }, + { .0050000000f,-.3030303030f, .0020000001f,-.0200000000f, .0125000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } }, + + { { .1428571492f, .1250000000f,-.0285714287f,-.0357142873f, .0208333333f }, + { .1818181818f, .0588235296f, .0333333333f, .0212765951f, .0100000000f }, + { .1818181818f, .0212765951f, .0100000000f, .0588235296f, .0333333333f }, + { .1428571492f,-.0357142873f, .0208333333f, .1250000000f,-.0285714287f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } }, + + { { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f }, + { .0000000000f, .0000000000f, .0000000000f, .0000000000f, .0000000000f } } +}; + +static const float fft_tone_level_table[2][64] = { { +/* pow ~ (i > 46) ? 0 : (((((i & 1) ? 431 : 304) << (i >> 1))) / 1024.0); */ + 0.17677669f, 0.42677650f, 0.60355347f, 0.85355347f, + 1.20710683f, 1.68359375f, 2.37500000f, 3.36718750f, + 4.75000000f, 6.73437500f, 9.50000000f, 13.4687500f, + 19.0000000f, 26.9375000f, 38.0000000f, 53.8750000f, + 76.0000000f, 107.750000f, 152.000000f, 215.500000f, + 304.000000f, 431.000000f, 608.000000f, 862.000000f, + 1216.00000f, 1724.00000f, 2432.00000f, 3448.00000f, + 4864.00000f, 6896.00000f, 9728.00000f, 13792.0000f, + 19456.0000f, 27584.0000f, 38912.0000f, 55168.0000f, + 77824.0000f, 110336.000f, 155648.000f, 220672.000f, + 311296.000f, 441344.000f, 622592.000f, 882688.000f, + 1245184.00f, 1765376.00f, 2490368.00f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + }, { +/* pow = (i > 45) ? 0 : ((((i & 1) ? 431 : 304) << (i >> 1)) / 512.0); */ + 0.59375000f, 0.84179688f, 1.18750000f, 1.68359375f, + 2.37500000f, 3.36718750f, 4.75000000f, 6.73437500f, + 9.50000000f, 13.4687500f, 19.0000000f, 26.9375000f, + 38.0000000f, 53.8750000f, 76.0000000f, 107.750000f, + 152.000000f, 215.500000f, 304.000000f, 431.000000f, + 608.000000f, 862.000000f, 1216.00000f, 1724.00000f, + 2432.00000f, 3448.00000f, 4864.00000f, 6896.00000f, + 9728.00000f, 13792.0000f, 19456.0000f, 27584.0000f, + 38912.0000f, 55168.0000f, 77824.0000f, 110336.000f, + 155648.000f, 220672.000f, 311296.000f, 441344.000f, + 622592.000f, 882688.000f, 1245184.00f, 1765376.00f, + 2490368.00f, 3530752.00f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f, + 0.00000000f, 0.00000000f, 0.00000000f, 0.00000000f +} }; + +static const float fft_tone_envelope_table[4][31] = { + { .009607375f, .038060248f, .084265202f, .146446645f, .222214907f, .308658302f, + .402454883f, .500000060f, .597545207f, .691341758f, .777785182f, .853553414f, + .915734828f, .961939812f, .990392685f, 1.00000000f, .990392625f, .961939752f, + .915734768f, .853553295f, .777785063f, .691341639f, .597545087f, .500000000f, + .402454853f, .308658272f, .222214878f, .146446615f, .084265172f, .038060218f, + .009607345f }, + { .038060248f, .146446645f, .308658302f, .500000060f, .691341758f, .853553414f, + .961939812f, 1.00000000f, .961939752f, .853553295f, .691341639f, .500000000f, + .308658272f, .146446615f, .038060218f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f }, + { .146446645f, .500000060f, .853553414f, 1.00000000f, .853553295f, .500000000f, + .146446615f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f }, + { .500000060f, 1.00000000f, .500000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, .000000000f, + .000000000f } +}; + +static const float sb_noise_attenuation[32] = { + 0.0f, 0.0f, 0.3f, 0.4f, 0.5f, 0.7f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, +}; + +static const uint8_t fft_subpackets[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 +}; + +/* first index is joined_stereo, second index is 0 or 2 (1 is unused) */ +static const float dequant_1bit[2][3] = { + {-0.920000f, 0.000000f, 0.920000f }, + {-0.890000f, 0.000000f, 0.890000f } +}; + +static const float type30_dequant[8] = { + -1.0f,-0.625f,-0.291666656732559f,0.0f, + 0.25f,0.5f,0.75f,1.0f, +}; + +static const float type34_delta[10] = { // FIXME: covers 8 entries.. + -1.0f,-0.60947573184967f,-0.333333343267441f,-0.138071194291115f,0.0f, + 0.138071194291115f,0.333333343267441f,0.60947573184967f,1.0f,0.0f, +}; + +#endif /* AVCODEC_QDM2DATA_H */ diff --git a/ffmpeg/libavcodec/qdrw.c b/ffmpeg/libavcodec/qdrw.c new file mode 100644 index 0000000..6970099 --- /dev/null +++ b/ffmpeg/libavcodec/qdrw.c @@ -0,0 +1,151 @@ +/* + * QuickDraw (qdrw) codec + * Copyright (c) 2004 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Apple QuickDraw codec. + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = avpkt->data + avpkt->size; + int buf_size = avpkt->size; + AVFrame * const p = data; + uint8_t* outdata; + int colors; + int i, ret; + uint32_t *pal; + int r, g, b; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + outdata = p->data[0]; + + if (buf_end - buf < 0x68 + 4) + return AVERROR_INVALIDDATA; + buf += 0x68; /* jump to palette */ + colors = AV_RB32(buf); + buf += 4; + + if (colors < 0 || colors > 256) { + av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors); + return AVERROR_INVALIDDATA; + } + if (buf_end - buf < (colors + 1) * 8) + return AVERROR_INVALIDDATA; + + pal = (uint32_t*)p->data[1]; + for (i = 0; i <= colors; i++) { + unsigned int idx; + idx = AV_RB16(buf); /* color index */ + buf += 2; + + if (idx > 255) { + av_log(avctx, AV_LOG_ERROR, "Palette index out of range: %u\n", idx); + buf += 6; + continue; + } + r = *buf++; + buf++; + g = *buf++; + buf++; + b = *buf++; + buf++; + pal[idx] = 0xFFU << 24 | r << 16 | g << 8 | b; + } + p->palette_has_changed = 1; + + if (buf_end - buf < 18) + return AVERROR_INVALIDDATA; + buf += 18; /* skip unneeded data */ + for (i = 0; i < avctx->height; i++) { + int size, left, code, pix; + const uint8_t *next; + uint8_t *out; + int tsize = 0; + + /* decode line */ + out = outdata; + size = AV_RB16(buf); /* size of packed line */ + buf += 2; + if (buf_end - buf < size) + return AVERROR_INVALIDDATA; + + left = size; + next = buf + size; + while (left > 0) { + code = *buf++; + if (code & 0x80 ) { /* run */ + pix = *buf++; + if ((out + (257 - code)) > (outdata + p->linesize[0])) + break; + memset(out, pix, 257 - code); + out += 257 - code; + tsize += 257 - code; + left -= 2; + } else { /* copy */ + if ((out + code) > (outdata + p->linesize[0])) + break; + if (buf_end - buf < code + 1) + return AVERROR_INVALIDDATA; + memcpy(out, buf, code + 1); + out += code + 1; + buf += code + 1; + left -= 2 + code; + tsize += code + 1; + } + } + buf = next; + outdata += p->linesize[0]; + } + + *got_frame = 1; + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt= AV_PIX_FMT_PAL8; + + return 0; +} + +AVCodec ff_qdraw_decoder = { + .name = "qdraw", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_QDRAW, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"), +}; diff --git a/ffmpeg/libavcodec/qpeg.c b/ffmpeg/libavcodec/qpeg.c new file mode 100644 index 0000000..6015b7f --- /dev/null +++ b/ffmpeg/libavcodec/qpeg.c @@ -0,0 +1,352 @@ +/* + * QPEG codec + * Copyright (c) 2004 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * QPEG codec. + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct QpegContext{ + AVCodecContext *avctx; + AVFrame pic, ref; + uint32_t pal[256]; + GetByteContext buffer; +} QpegContext; + +static void qpeg_decode_intra(QpegContext *qctx, uint8_t *dst, + int stride, int width, int height) +{ + int i; + int code; + int c0, c1; + int run, copy; + int filled = 0; + int rows_to_go; + + rows_to_go = height; + height--; + dst = dst + height * stride; + + while ((bytestream2_get_bytes_left(&qctx->buffer) > 0) && (rows_to_go > 0)) { + code = bytestream2_get_byte(&qctx->buffer); + run = copy = 0; + if(code == 0xFC) /* end-of-picture code */ + break; + if(code >= 0xF8) { /* very long run */ + c0 = bytestream2_get_byte(&qctx->buffer); + c1 = bytestream2_get_byte(&qctx->buffer); + run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2; + } else if (code >= 0xF0) { /* long run */ + c0 = bytestream2_get_byte(&qctx->buffer); + run = ((code & 0xF) << 8) + c0 + 2; + } else if (code >= 0xE0) { /* short run */ + run = (code & 0x1F) + 2; + } else if (code >= 0xC0) { /* very long copy */ + c0 = bytestream2_get_byte(&qctx->buffer); + c1 = bytestream2_get_byte(&qctx->buffer); + copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1; + } else if (code >= 0x80) { /* long copy */ + c0 = bytestream2_get_byte(&qctx->buffer); + copy = ((code & 0x7F) << 8) + c0 + 1; + } else { /* short copy */ + copy = code + 1; + } + + /* perform actual run or copy */ + if(run) { + int p; + + p = bytestream2_get_byte(&qctx->buffer); + for(i = 0; i < run; i++) { + dst[filled++] = p; + if (filled >= width) { + filled = 0; + dst -= stride; + rows_to_go--; + if(rows_to_go <= 0) + break; + } + } + } else { + for(i = 0; i < copy; i++) { + dst[filled++] = bytestream2_get_byte(&qctx->buffer); + if (filled >= width) { + filled = 0; + dst -= stride; + rows_to_go--; + if(rows_to_go <= 0) + break; + } + } + } + } +} + +static const int qpeg_table_h[16] = + { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04}; +static const int qpeg_table_w[16] = + { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04}; + +/* Decodes delta frames */ +static void qpeg_decode_inter(QpegContext *qctx, uint8_t *dst, + int stride, int width, int height, + int delta, const uint8_t *ctable, + uint8_t *refdata) +{ + int i, j; + int code; + int filled = 0; + int orig_height; + + if(!refdata) + refdata= dst; + + /* copy prev frame */ + for(i = 0; i < height; i++) + memcpy(dst + (i * stride), refdata + (i * stride), width); + + orig_height = height; + height--; + dst = dst + height * stride; + + while ((bytestream2_get_bytes_left(&qctx->buffer) > 0) && (height >= 0)) { + code = bytestream2_get_byte(&qctx->buffer); + + if(delta) { + /* motion compensation */ + while(bytestream2_get_bytes_left(&qctx->buffer) > 0 && (code & 0xF0) == 0xF0) { + if(delta == 1) { + int me_idx; + int me_w, me_h, me_x, me_y; + uint8_t *me_plane; + int corr, val; + + /* get block size by index */ + me_idx = code & 0xF; + me_w = qpeg_table_w[me_idx]; + me_h = qpeg_table_h[me_idx]; + + /* extract motion vector */ + corr = bytestream2_get_byte(&qctx->buffer); + + val = corr >> 4; + if(val > 7) + val -= 16; + me_x = val; + + val = corr & 0xF; + if(val > 7) + val -= 16; + me_y = val; + + /* check motion vector */ + if ((me_x + filled < 0) || (me_x + me_w + filled > width) || + (height - me_y - me_h < 0) || (height - me_y > orig_height) || + (filled + me_w > width) || (height - me_h < 0)) + av_log(NULL, AV_LOG_ERROR, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n", + me_x, me_y, me_w, me_h, filled, height); + else { + /* do motion compensation */ + me_plane = refdata + (filled + me_x) + (height - me_y) * stride; + for(j = 0; j < me_h; j++) { + for(i = 0; i < me_w; i++) + dst[filled + i - (j * stride)] = me_plane[i - (j * stride)]; + } + } + } + code = bytestream2_get_byte(&qctx->buffer); + } + } + + if(code == 0xE0) /* end-of-picture code */ + break; + if(code > 0xE0) { /* run code: 0xE1..0xFF */ + int p; + + code &= 0x1F; + p = bytestream2_get_byte(&qctx->buffer); + for(i = 0; i <= code; i++) { + dst[filled++] = p; + if(filled >= width) { + filled = 0; + dst -= stride; + height--; + if(height < 0) + break; + } + } + } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */ + code &= 0x1F; + + if(code + 1 > bytestream2_get_bytes_left(&qctx->buffer)) + break; + + for(i = 0; i <= code; i++) { + dst[filled++] = bytestream2_get_byte(&qctx->buffer); + if(filled >= width) { + filled = 0; + dst -= stride; + height--; + if(height < 0) + break; + } + } + } else if(code >= 0x80) { /* skip code: 0x80..0xBF */ + int skip; + + code &= 0x3F; + /* codes 0x80 and 0x81 are actually escape codes, + skip value minus constant is in the next byte */ + if(!code) + skip = bytestream2_get_byte(&qctx->buffer) + 64; + else if(code == 1) + skip = bytestream2_get_byte(&qctx->buffer) + 320; + else + skip = code; + filled += skip; + while( filled >= width) { + filled -= width; + dst -= stride; + height--; + if(height < 0) + break; + } + } else { + /* zero code treated as one-pixel skip */ + if(code) { + dst[filled++] = ctable[code & 0x7F]; + } + else + filled++; + if(filled >= width) { + filled = 0; + dst -= stride; + height--; + } + } + } +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + uint8_t ctable[128]; + QpegContext * const a = avctx->priv_data; + AVFrame * p = &a->pic; + AVFrame * ref= &a->ref; + uint8_t* outdata; + int delta, ret; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (avpkt->size < 0x86) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + bytestream2_init(&a->buffer, avpkt->data, avpkt->size); + + av_frame_unref(ref); + av_frame_move_ref(ref, p); + + if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + outdata = a->pic.data[0]; + bytestream2_skip(&a->buffer, 4); + bytestream2_get_buffer(&a->buffer, ctable, 128); + bytestream2_skip(&a->buffer, 1); + + delta = bytestream2_get_byte(&a->buffer); + if(delta == 0x10) { + qpeg_decode_intra(a, outdata, a->pic.linesize[0], avctx->width, avctx->height); + } else { + qpeg_decode_inter(a, outdata, a->pic.linesize[0], avctx->width, avctx->height, delta, ctable, a->ref.data[0]); + } + + /* make the palette available on the way out */ + if (pal) { + a->pic.palette_has_changed = 1; + memcpy(a->pal, pal, AVPALETTE_SIZE); + } + memcpy(a->pic.data[1], a->pal, AVPALETTE_SIZE); + + if ((ret = av_frame_ref(data, &a->pic)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +static void decode_flush(AVCodecContext *avctx){ + QpegContext * const a = avctx->priv_data; + int i, pal_size; + const uint8_t *pal_src; + + pal_size = FFMIN(1024U, avctx->extradata_size); + pal_src = avctx->extradata + avctx->extradata_size - pal_size; + + for (i=0; ipal[i] = 0xFFU<<24 | AV_RL32(pal_src+4*i); +} + +static av_cold int decode_init(AVCodecContext *avctx){ + QpegContext * const a = avctx->priv_data; + + avcodec_get_frame_defaults(&a->pic); + avcodec_get_frame_defaults(&a->ref); + a->avctx = avctx; + avctx->pix_fmt= AV_PIX_FMT_PAL8; + + decode_flush(avctx); + + avcodec_get_frame_defaults(&a->pic); + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx){ + QpegContext * const a = avctx->priv_data; + AVFrame * const p = &a->pic; + AVFrame * const ref= &a->ref; + + av_frame_unref(p); + av_frame_unref(ref); + + return 0; +} + +AVCodec ff_qpeg_decoder = { + .name = "qpeg", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_QPEG, + .priv_data_size = sizeof(QpegContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .flush = decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), +}; diff --git a/ffmpeg/libavcodec/qtrle.c b/ffmpeg/libavcodec/qtrle.c new file mode 100644 index 0000000..c043249 --- /dev/null +++ b/ffmpeg/libavcodec/qtrle.c @@ -0,0 +1,526 @@ +/* + * Quicktime Animation (RLE) Video Decoder + * Copyright (C) 2004 the ffmpeg project + * + * 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 + */ + +/** + * @file + * QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net) + * For more information about the QT RLE format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * The QT RLE decoder has seven modes of operation: + * 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8 + * the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555 + * data. 24-bit data is RGB24 and 32-bit data is RGB32. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct QtrleContext { + AVCodecContext *avctx; + AVFrame frame; + + GetByteContext g; + uint32_t pal[256]; +} QtrleContext; + +#define CHECK_PIXEL_PTR(n) \ + if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \ + av_log (s->avctx, AV_LOG_ERROR, "Problem: pixel_ptr = %d, pixel_limit = %d\n",\ + pixel_ptr + n, pixel_limit); \ + return; \ + } \ + +static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change) +{ + int rle_code; + int pixel_ptr; + int row_inc = s->frame.linesize[0]; + unsigned char pi0, pi1; /* 2 8-pixel values */ + unsigned char *rgb = s->frame.data[0]; + int pixel_limit = s->frame.linesize[0] * s->avctx->height; + int skip; + /* skip & 0x80 appears to mean 'start a new line', which can be interpreted + * as 'go to next line' during the decoding of a frame but is 'go to first + * line' at the beginning. Since we always interpret it as 'go to next line' + * in the decoding loop (which makes code simpler/faster), the first line + * would not be counted, so we count one more. + * See: https://ffmpeg.org/trac/ffmpeg/ticket/226 + * In the following decoding loop, row_ptr will be the position of the + * current row. */ + + row_ptr -= row_inc; + pixel_ptr = row_ptr; + lines_to_change++; + while (lines_to_change) { + skip = bytestream2_get_byte(&s->g); + rle_code = (signed char)bytestream2_get_byte(&s->g); + if (rle_code == 0) + break; + if(skip & 0x80) { + lines_to_change--; + row_ptr += row_inc; + pixel_ptr = row_ptr + 2 * (skip & 0x7f); + } else + pixel_ptr += 2 * skip; + CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ + + if(rle_code == -1) + continue; + + if (rle_code < 0) { + /* decode the run length code */ + rle_code = -rle_code; + /* get the next 2 bytes from the stream, treat them as groups + * of 8 pixels, and output them rle_code times */ + + pi0 = bytestream2_get_byte(&s->g); + pi1 = bytestream2_get_byte(&s->g); + CHECK_PIXEL_PTR(rle_code * 2); + + while (rle_code--) { + rgb[pixel_ptr++] = pi0; + rgb[pixel_ptr++] = pi1; + } + } else { + /* copy the same pixel directly to output 2 times */ + rle_code *= 2; + CHECK_PIXEL_PTR(rle_code); + + while (rle_code--) + rgb[pixel_ptr++] = bytestream2_get_byte(&s->g); + } + } +} + +static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr, + int lines_to_change, int bpp) +{ + int rle_code, i; + int pixel_ptr; + int row_inc = s->frame.linesize[0]; + unsigned char pi[16]; /* 16 palette indices */ + unsigned char *rgb = s->frame.data[0]; + int pixel_limit = s->frame.linesize[0] * s->avctx->height; + int num_pixels = (bpp == 4) ? 8 : 16; + + while (lines_to_change--) { + pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1)); + CHECK_PIXEL_PTR(0); + + while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) { + if (rle_code == 0) { + /* there's another skip code in the stream */ + pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1)); + CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ + } else if (rle_code < 0) { + /* decode the run length code */ + rle_code = -rle_code; + /* get the next 4 bytes from the stream, treat them as palette + * indexes, and output them rle_code times */ + for (i = num_pixels-1; i >= 0; i--) { + pi[num_pixels-1-i] = (bytestream2_peek_byte(&s->g) >> ((i*bpp) & 0x07)) & ((1<g, ((i & ((num_pixels>>2)-1)) == 0)); + } + CHECK_PIXEL_PTR(rle_code * num_pixels); + while (rle_code--) { + for (i = 0; i < num_pixels; i++) + rgb[pixel_ptr++] = pi[i]; + } + } else { + /* copy the same pixel directly to output 4 times */ + rle_code *= 4; + CHECK_PIXEL_PTR(rle_code*(num_pixels>>2)); + while (rle_code--) { + if(bpp == 4) { + int x = bytestream2_get_byte(&s->g); + rgb[pixel_ptr++] = (x >> 4) & 0x0f; + rgb[pixel_ptr++] = x & 0x0f; + } else { + int x = bytestream2_get_byte(&s->g); + rgb[pixel_ptr++] = (x >> 6) & 0x03; + rgb[pixel_ptr++] = (x >> 4) & 0x03; + rgb[pixel_ptr++] = (x >> 2) & 0x03; + rgb[pixel_ptr++] = x & 0x03; + } + } + } + } + row_ptr += row_inc; + } +} + +static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change) +{ + int rle_code; + int pixel_ptr; + int row_inc = s->frame.linesize[0]; + unsigned char pi1, pi2, pi3, pi4; /* 4 palette indexes */ + unsigned char *rgb = s->frame.data[0]; + int pixel_limit = s->frame.linesize[0] * s->avctx->height; + + while (lines_to_change--) { + pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1)); + CHECK_PIXEL_PTR(0); + + while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) { + if (rle_code == 0) { + /* there's another skip code in the stream */ + pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1)); + CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ + } else if (rle_code < 0) { + /* decode the run length code */ + rle_code = -rle_code; + /* get the next 4 bytes from the stream, treat them as palette + * indexes, and output them rle_code times */ + pi1 = bytestream2_get_byte(&s->g); + pi2 = bytestream2_get_byte(&s->g); + pi3 = bytestream2_get_byte(&s->g); + pi4 = bytestream2_get_byte(&s->g); + + CHECK_PIXEL_PTR(rle_code * 4); + + while (rle_code--) { + rgb[pixel_ptr++] = pi1; + rgb[pixel_ptr++] = pi2; + rgb[pixel_ptr++] = pi3; + rgb[pixel_ptr++] = pi4; + } + } else { + /* copy the same pixel directly to output 4 times */ + rle_code *= 4; + CHECK_PIXEL_PTR(rle_code); + + while (rle_code--) { + rgb[pixel_ptr++] = bytestream2_get_byte(&s->g); + } + } + } + row_ptr += row_inc; + } +} + +static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change) +{ + int rle_code; + int pixel_ptr; + int row_inc = s->frame.linesize[0]; + unsigned short rgb16; + unsigned char *rgb = s->frame.data[0]; + int pixel_limit = s->frame.linesize[0] * s->avctx->height; + + while (lines_to_change--) { + pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2; + CHECK_PIXEL_PTR(0); + + while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) { + if (rle_code == 0) { + /* there's another skip code in the stream */ + pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2; + CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ + } else if (rle_code < 0) { + /* decode the run length code */ + rle_code = -rle_code; + rgb16 = bytestream2_get_be16(&s->g); + + CHECK_PIXEL_PTR(rle_code * 2); + + while (rle_code--) { + *(unsigned short *)(&rgb[pixel_ptr]) = rgb16; + pixel_ptr += 2; + } + } else { + CHECK_PIXEL_PTR(rle_code * 2); + + /* copy pixels directly to output */ + while (rle_code--) { + rgb16 = bytestream2_get_be16(&s->g); + *(unsigned short *)(&rgb[pixel_ptr]) = rgb16; + pixel_ptr += 2; + } + } + } + row_ptr += row_inc; + } +} + +static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change) +{ + int rle_code; + int pixel_ptr; + int row_inc = s->frame.linesize[0]; + unsigned char r, g, b; + unsigned char *rgb = s->frame.data[0]; + int pixel_limit = s->frame.linesize[0] * s->avctx->height; + + while (lines_to_change--) { + pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3; + CHECK_PIXEL_PTR(0); + + while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) { + if (rle_code == 0) { + /* there's another skip code in the stream */ + pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3; + CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ + } else if (rle_code < 0) { + /* decode the run length code */ + rle_code = -rle_code; + r = bytestream2_get_byte(&s->g); + g = bytestream2_get_byte(&s->g); + b = bytestream2_get_byte(&s->g); + + CHECK_PIXEL_PTR(rle_code * 3); + + while (rle_code--) { + rgb[pixel_ptr++] = r; + rgb[pixel_ptr++] = g; + rgb[pixel_ptr++] = b; + } + } else { + CHECK_PIXEL_PTR(rle_code * 3); + + /* copy pixels directly to output */ + while (rle_code--) { + rgb[pixel_ptr++] = bytestream2_get_byte(&s->g); + rgb[pixel_ptr++] = bytestream2_get_byte(&s->g); + rgb[pixel_ptr++] = bytestream2_get_byte(&s->g); + } + } + } + row_ptr += row_inc; + } +} + +static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change) +{ + int rle_code; + int pixel_ptr; + int row_inc = s->frame.linesize[0]; + unsigned int argb; + unsigned char *rgb = s->frame.data[0]; + int pixel_limit = s->frame.linesize[0] * s->avctx->height; + + while (lines_to_change--) { + pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4; + CHECK_PIXEL_PTR(0); + + while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) { + if (rle_code == 0) { + /* there's another skip code in the stream */ + pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4; + CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ + } else if (rle_code < 0) { + /* decode the run length code */ + rle_code = -rle_code; + argb = bytestream2_get_be32(&s->g); + + CHECK_PIXEL_PTR(rle_code * 4); + + while (rle_code--) { + AV_WN32A(rgb + pixel_ptr, argb); + pixel_ptr += 4; + } + } else { + CHECK_PIXEL_PTR(rle_code * 4); + + /* copy pixels directly to output */ + while (rle_code--) { + argb = bytestream2_get_be32(&s->g); + AV_WN32A(rgb + pixel_ptr, argb); + pixel_ptr += 4; + } + } + } + row_ptr += row_inc; + } +} + +static av_cold int qtrle_decode_init(AVCodecContext *avctx) +{ + QtrleContext *s = avctx->priv_data; + + s->avctx = avctx; + switch (avctx->bits_per_coded_sample) { + case 1: + case 33: + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + break; + + case 2: + case 4: + case 8: + case 34: + case 36: + case 40: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + + case 16: + avctx->pix_fmt = AV_PIX_FMT_RGB555; + break; + + case 24: + avctx->pix_fmt = AV_PIX_FMT_RGB24; + break; + + case 32: + avctx->pix_fmt = AV_PIX_FMT_RGB32; + break; + + default: + av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", + avctx->bits_per_coded_sample); + return AVERROR_INVALIDDATA; + } + + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + +static int qtrle_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + QtrleContext *s = avctx->priv_data; + int header, start_line; + int height, row_ptr; + int has_palette = 0; + int ret; + + bytestream2_init(&s->g, avpkt->data, avpkt->size); + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + /* check if this frame is even supposed to change */ + if (avpkt->size < 8) + goto done; + + /* start after the chunk size */ + bytestream2_seek(&s->g, 4, SEEK_SET); + + /* fetch the header */ + header = bytestream2_get_be16(&s->g); + + /* if a header is present, fetch additional decoding parameters */ + if (header & 0x0008) { + if (avpkt->size < 14) + goto done; + start_line = bytestream2_get_be16(&s->g); + bytestream2_skip(&s->g, 2); + height = bytestream2_get_be16(&s->g); + bytestream2_skip(&s->g, 2); + if (height > s->avctx->height - start_line) + goto done; + } else { + start_line = 0; + height = s->avctx->height; + } + row_ptr = s->frame.linesize[0] * start_line; + + switch (avctx->bits_per_coded_sample) { + case 1: + case 33: + qtrle_decode_1bpp(s, row_ptr, height); + break; + + case 2: + case 34: + qtrle_decode_2n4bpp(s, row_ptr, height, 2); + has_palette = 1; + break; + + case 4: + case 36: + qtrle_decode_2n4bpp(s, row_ptr, height, 4); + has_palette = 1; + break; + + case 8: + case 40: + qtrle_decode_8bpp(s, row_ptr, height); + has_palette = 1; + break; + + case 16: + qtrle_decode_16bpp(s, row_ptr, height); + break; + + case 24: + qtrle_decode_24bpp(s, row_ptr, height); + break; + + case 32: + qtrle_decode_32bpp(s, row_ptr, height); + break; + + default: + av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", + avctx->bits_per_coded_sample); + break; + } + + if(has_palette) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { + s->frame.palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + + /* make the palette available on the way out */ + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); + } + +done: + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return avpkt->size; +} + +static av_cold int qtrle_decode_end(AVCodecContext *avctx) +{ + QtrleContext *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_qtrle_decoder = { + .name = "qtrle", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_QTRLE, + .priv_data_size = sizeof(QtrleContext), + .init = qtrle_decode_init, + .close = qtrle_decode_end, + .decode = qtrle_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), +}; diff --git a/ffmpeg/libavcodec/qtrleenc.c b/ffmpeg/libavcodec/qtrleenc.c new file mode 100644 index 0000000..a25c45d --- /dev/null +++ b/ffmpeg/libavcodec/qtrleenc.c @@ -0,0 +1,402 @@ +/* + * Quicktime Animation (RLE) Video Encoder + * Copyright (C) 2007 Clemens Fruhwirth + * Copyright (C) 2007 Alexis Ballier + * + * This file is based on flashsvenc.c. + * + * 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 "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +/** Maximum RLE code for bulk copy */ +#define MAX_RLE_BULK 127 +/** Maximum RLE code for repeat */ +#define MAX_RLE_REPEAT 128 +/** Maximum RLE code for skip */ +#define MAX_RLE_SKIP 254 + +typedef struct QtrleEncContext { + AVCodecContext *avctx; + AVFrame frame; + int pixel_size; + AVPicture previous_frame; + unsigned int max_buf_size; + int logical_width; + /** + * This array will contain at ith position the value of the best RLE code + * if the line started at pixel i + * There can be 3 values : + * skip (0) : skip as much as possible pixels because they are equal to the + * previous frame ones + * repeat (<-1) : repeat that pixel -rle_code times, still as much as + * possible + * copy (>0) : copy the raw next rle_code pixels */ + signed char *rlecode_table; + /** + * This array will contain the length of the best rle encoding of the line + * starting at ith pixel */ + int *length_table; + /** + * Will contain at ith position the number of consecutive pixels equal to the previous + * frame starting from pixel i */ + uint8_t* skip_table; +} QtrleEncContext; + +static av_cold int qtrle_encode_init(AVCodecContext *avctx) +{ + QtrleEncContext *s = avctx->priv_data; + int ret; + + if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) { + return AVERROR(EINVAL); + } + s->avctx=avctx; + s->logical_width=avctx->width; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_GRAY8: + s->logical_width = avctx->width / 4; + s->pixel_size = 4; + break; + case AV_PIX_FMT_RGB555BE: + s->pixel_size = 2; + break; + case AV_PIX_FMT_RGB24: + s->pixel_size = 3; + break; + case AV_PIX_FMT_ARGB: + s->pixel_size = 4; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported colorspace.\n"); + break; + } + avctx->bits_per_coded_sample = avctx->pix_fmt == AV_PIX_FMT_GRAY8 ? 40 : s->pixel_size*8; + + s->rlecode_table = av_mallocz(s->logical_width); + s->skip_table = av_mallocz(s->logical_width); + s->length_table = av_mallocz((s->logical_width + 1)*sizeof(int)); + if (!s->skip_table || !s->length_table || !s->rlecode_table) { + av_log(avctx, AV_LOG_ERROR, "Error allocating memory.\n"); + return AVERROR(ENOMEM); + } + if ((ret = avpicture_alloc(&s->previous_frame, avctx->pix_fmt, avctx->width, avctx->height)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error allocating picture\n"); + return ret; + } + + s->max_buf_size = s->logical_width*s->avctx->height*s->pixel_size*2 /* image base material */ + + 15 /* header + footer */ + + s->avctx->height*2 /* skip code+rle end */ + + s->logical_width/MAX_RLE_BULK + 1 /* rle codes */; + avctx->coded_frame = &s->frame; + return 0; +} + +/** + * Compute the best RLE sequence for a line + */ +static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, uint8_t **buf) +{ + int width=s->logical_width; + int i; + signed char rlecode; + + /* This will be the number of pixels equal to the preivous frame one's + * starting from the ith pixel */ + unsigned int skipcount; + /* This will be the number of consecutive equal pixels in the current + * frame, starting from the ith one also */ + unsigned int av_uninit(repeatcount); + + /* The cost of the three different possibilities */ + int total_skip_cost; + int total_repeat_cost; + + int base_bulk_cost; + int lowest_bulk_cost; + int lowest_bulk_cost_index; + int sec_lowest_bulk_cost; + int sec_lowest_bulk_cost_index; + + uint8_t *this_line = p-> data[0] + line*p-> linesize[0] + + (width - 1)*s->pixel_size; + uint8_t *prev_line = s->previous_frame.data[0] + line*s->previous_frame.linesize[0] + + (width - 1)*s->pixel_size; + + s->length_table[width] = 0; + skipcount = 0; + + /* Initial values */ + lowest_bulk_cost = INT_MAX / 2; + lowest_bulk_cost_index = width; + sec_lowest_bulk_cost = INT_MAX / 2; + sec_lowest_bulk_cost_index = width; + + base_bulk_cost = 1 + s->pixel_size; + + for (i = width - 1; i >= 0; i--) { + + int prev_bulk_cost; + + /* If our lowest bulk cost index is too far away, replace it + * with the next lowest bulk cost */ + if (FFMIN(width, i + MAX_RLE_BULK) < lowest_bulk_cost_index) { + lowest_bulk_cost = sec_lowest_bulk_cost; + lowest_bulk_cost_index = sec_lowest_bulk_cost_index; + + sec_lowest_bulk_cost = INT_MAX / 2; + sec_lowest_bulk_cost_index = width; + } + + /* Deal with the first pixel's bulk cost */ + if (!i) { + base_bulk_cost++; + lowest_bulk_cost++; + sec_lowest_bulk_cost++; + } + + /* Look at the bulk cost of the previous loop and see if it is + * a new lower bulk cost */ + prev_bulk_cost = s->length_table[i + 1] + base_bulk_cost; + if (prev_bulk_cost <= sec_lowest_bulk_cost) { + /* If it's lower than the 2nd lowest, then it may be lower + * than the lowest */ + if (prev_bulk_cost <= lowest_bulk_cost) { + + /* If we have found a new lowest bulk cost, + * then the 2nd lowest bulk cost is now farther than the + * lowest bulk cost, and will never be used */ + sec_lowest_bulk_cost = INT_MAX / 2; + + lowest_bulk_cost = prev_bulk_cost; + lowest_bulk_cost_index = i + 1; + } else { + /* Then it must be the 2nd lowest bulk cost */ + sec_lowest_bulk_cost = prev_bulk_cost; + sec_lowest_bulk_cost_index = i + 1; + } + } + + if (!s->frame.key_frame && !memcmp(this_line, prev_line, s->pixel_size)) + skipcount = FFMIN(skipcount + 1, MAX_RLE_SKIP); + else + skipcount = 0; + + total_skip_cost = s->length_table[i + skipcount] + 2; + s->skip_table[i] = skipcount; + + + if (i < width - 1 && !memcmp(this_line, this_line + s->pixel_size, s->pixel_size)) + repeatcount = FFMIN(repeatcount + 1, MAX_RLE_REPEAT); + else + repeatcount = 1; + + total_repeat_cost = s->length_table[i + repeatcount] + 1 + s->pixel_size; + + /* skip code is free for the first pixel, it costs one byte for repeat and bulk copy + * so let's make it aware */ + if (i == 0) { + total_skip_cost--; + total_repeat_cost++; + } + + if (repeatcount > 1 && (skipcount == 0 || total_repeat_cost < total_skip_cost)) { + /* repeat is the best */ + s->length_table[i] = total_repeat_cost; + s->rlecode_table[i] = -repeatcount; + } + else if (skipcount > 0) { + /* skip is the best choice here */ + s->length_table[i] = total_skip_cost; + s->rlecode_table[i] = 0; + } + else { + /* We cannot do neither skip nor repeat + * thus we use the best bulk copy */ + + s->length_table[i] = lowest_bulk_cost; + s->rlecode_table[i] = lowest_bulk_cost_index - i; + + } + + /* These bulk costs increase every iteration */ + lowest_bulk_cost += s->pixel_size; + sec_lowest_bulk_cost += s->pixel_size; + + this_line -= s->pixel_size; + prev_line -= s->pixel_size; + } + + /* Good ! Now we have the best sequence for this line, let's output it */ + + /* We do a special case for the first pixel so that we avoid testing it in + * the whole loop */ + + i=0; + this_line = p-> data[0] + line*p->linesize[0]; + + if (s->rlecode_table[0] == 0) { + bytestream_put_byte(buf, s->skip_table[0] + 1); + i += s->skip_table[0]; + } + else bytestream_put_byte(buf, 1); + + + while (i < width) { + rlecode = s->rlecode_table[i]; + bytestream_put_byte(buf, rlecode); + if (rlecode == 0) { + /* Write a skip sequence */ + bytestream_put_byte(buf, s->skip_table[i] + 1); + i += s->skip_table[i]; + } + else if (rlecode > 0) { + /* bulk copy */ + if (s->avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + int j; + // QT grayscale colorspace has 0=white and 255=black, we will + // ignore the palette that is included in the AVFrame because + // AV_PIX_FMT_GRAY8 has defined color mapping + for (j = 0; j < rlecode*s->pixel_size; ++j) + bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff); + } else { + bytestream_put_buffer(buf, this_line + i*s->pixel_size, rlecode*s->pixel_size); + } + i += rlecode; + } + else { + /* repeat the bits */ + if (s->avctx->pix_fmt == AV_PIX_FMT_GRAY8) { + int j; + // QT grayscale colorspace has 0=white and 255=black, ... + for (j = 0; j < s->pixel_size; ++j) + bytestream_put_byte(buf, *(this_line + i*s->pixel_size + j) ^ 0xff); + } else { + bytestream_put_buffer(buf, this_line + i*s->pixel_size, s->pixel_size); + } + i -= rlecode; + } + } + bytestream_put_byte(buf, -1); // end RLE line +} + +/** Encode frame including header */ +static int encode_frame(QtrleEncContext *s, const AVFrame *p, uint8_t *buf) +{ + int i; + int start_line = 0; + int end_line = s->avctx->height; + uint8_t *orig_buf = buf; + + if (!s->frame.key_frame) { + unsigned line_size = s->logical_width * s->pixel_size; + for (start_line = 0; start_line < s->avctx->height; start_line++) + if (memcmp(p->data[0] + start_line*p->linesize[0], + s->previous_frame.data[0] + start_line*s->previous_frame.linesize[0], + line_size)) + break; + + for (end_line=s->avctx->height; end_line > start_line; end_line--) + if (memcmp(p->data[0] + (end_line - 1)*p->linesize[0], + s->previous_frame.data[0] + (end_line - 1)*s->previous_frame.linesize[0], + line_size)) + break; + } + + bytestream_put_be32(&buf, 0); // CHUNK SIZE, patched later + + if ((start_line == 0 && end_line == s->avctx->height) || start_line == s->avctx->height) + bytestream_put_be16(&buf, 0); // header + else { + bytestream_put_be16(&buf, 8); // header + bytestream_put_be16(&buf, start_line); // starting line + bytestream_put_be16(&buf, 0); // unknown + bytestream_put_be16(&buf, end_line - start_line); // lines to update + bytestream_put_be16(&buf, 0); // unknown + } + for (i = start_line; i < end_line; i++) + qtrle_encode_line(s, p, i, &buf); + + bytestream_put_byte(&buf, 0); // zero skip code = frame finished + AV_WB32(orig_buf, buf - orig_buf); // patch the chunk size + return buf - orig_buf; +} + +static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + QtrleEncContext * const s = avctx->priv_data; + AVFrame * const p = &s->frame; + int ret; + + *p = *pict; + + if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size)) < 0) + return ret; + + if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) { + /* I-Frame */ + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + } else { + /* P-Frame */ + p->pict_type = AV_PICTURE_TYPE_P; + p->key_frame = 0; + } + + pkt->size = encode_frame(s, pict, pkt->data); + + /* save the current frame */ + av_picture_copy(&s->previous_frame, (AVPicture *)p, avctx->pix_fmt, avctx->width, avctx->height); + + if (p->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int qtrle_encode_end(AVCodecContext *avctx) +{ + QtrleEncContext *s = avctx->priv_data; + + avpicture_free(&s->previous_frame); + av_free(s->rlecode_table); + av_free(s->length_table); + av_free(s->skip_table); + return 0; +} + +AVCodec ff_qtrle_encoder = { + .name = "qtrle", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_QTRLE, + .priv_data_size = sizeof(QtrleEncContext), + .init = qtrle_encode_init, + .encode2 = qtrle_encode_frame, + .close = qtrle_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB555BE, AV_PIX_FMT_ARGB, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), +}; diff --git a/ffmpeg/libavcodec/r210dec.c b/ffmpeg/libavcodec/r210dec.c new file mode 100644 index 0000000..198914c --- /dev/null +++ b/ffmpeg/libavcodec/r210dec.c @@ -0,0 +1,122 @@ +/* + * R210 decoder + * + * Copyright (c) 2009 Reimar Doeffinger + * + * 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 "avcodec.h" +#include "internal.h" +#include "libavutil/bswap.h" +#include "libavutil/common.h" + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_RGB48; + avctx->bits_per_raw_sample = 10; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + int h, w, ret; + AVFrame *pic = data; + const uint32_t *src = (const uint32_t *)avpkt->data; + int aligned_width = FFALIGN(avctx->width, + avctx->codec_id == AV_CODEC_ID_R10K ? 1 : 64); + uint8_t *dst_line; + + if (avpkt->size < 4 * aligned_width * avctx->height) { + av_log(avctx, AV_LOG_ERROR, "packet too small\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + dst_line = pic->data[0]; + + for (h = 0; h < avctx->height; h++) { + uint16_t *dst = (uint16_t *)dst_line; + for (w = 0; w < avctx->width; w++) { + uint32_t pixel; + uint16_t r, g, b; + if (avctx->codec_id==AV_CODEC_ID_AVRP) { + pixel = av_le2ne32(*src++); + } else { + pixel = av_be2ne32(*src++); + } + if (avctx->codec_id==AV_CODEC_ID_R210) { + b = pixel << 6; + g = (pixel >> 4) & 0xffc0; + r = (pixel >> 14) & 0xffc0; + } else { + b = pixel << 4; + g = (pixel >> 6) & 0xffc0; + r = (pixel >> 16) & 0xffc0; + } + *dst++ = r | (r >> 10); + *dst++ = g | (g >> 10); + *dst++ = b | (b >> 10); + } + src += aligned_width - avctx->width; + dst_line += pic->linesize[0]; + } + + *got_frame = 1; + + return avpkt->size; +} + +#if CONFIG_R210_DECODER +AVCodec ff_r210_decoder = { + .name = "r210", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_R210, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), +}; +#endif +#if CONFIG_R10K_DECODER +AVCodec ff_r10k_decoder = { + .name = "r10k", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_R10K, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), +}; +#endif +#if CONFIG_AVRP_DECODER +AVCodec ff_avrp_decoder = { + .name = "avrp", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVRP, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), +}; +#endif diff --git a/ffmpeg/libavcodec/r210enc.c b/ffmpeg/libavcodec/r210enc.c new file mode 100644 index 0000000..e19a27e --- /dev/null +++ b/ffmpeg/libavcodec/r210enc.c @@ -0,0 +1,123 @@ +/* + * R210 encoder + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "avcodec.h" +#include "internal.h" +#include "bytestream.h" + +static av_cold int encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + int i, j, ret; + int aligned_width = FFALIGN(avctx->width, + avctx->codec_id == AV_CODEC_ID_R10K ? 1 : 64); + int pad = (aligned_width - avctx->width) * 4; + uint8_t *src_line; + uint8_t *dst; + + if ((ret = ff_alloc_packet2(avctx, pkt, 4 * aligned_width * avctx->height)) < 0) + return ret; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + src_line = pic->data[0]; + dst = pkt->data; + + for (i = 0; i < avctx->height; i++) { + uint16_t *src = (uint16_t *)src_line; + for (j = 0; j < avctx->width; j++) { + uint32_t pixel; + uint16_t r = *src++ >> 6; + uint16_t g = *src++ >> 6; + uint16_t b = *src++ >> 4; + if (avctx->codec_id == AV_CODEC_ID_R210) + pixel = (r << 20) | (g << 10) | b >> 2; + else + pixel = (r << 22) | (g << 12) | b; + if (avctx->codec_id == AV_CODEC_ID_AVRP) + bytestream_put_le32(&dst, pixel); + else + bytestream_put_be32(&dst, pixel); + } + memset(dst, 0, pad); + dst += pad; + src_line += pic->linesize[0]; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +#if CONFIG_R210_ENCODER +AVCodec ff_r210_encoder = { + .name = "r210", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_R210, + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB48, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), +}; +#endif +#if CONFIG_R10K_ENCODER +AVCodec ff_r10k_encoder = { + .name = "r10k", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_R10K, + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB48, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), +}; +#endif +#if CONFIG_AVRP_ENCODER +AVCodec ff_avrp_encoder = { + .name = "avrp", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVRP, + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB48, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), +}; +#endif diff --git a/ffmpeg/libavcodec/ra144.c b/ffmpeg/libavcodec/ra144.c new file mode 100644 index 0000000..1ec1e10 --- /dev/null +++ b/ffmpeg/libavcodec/ra144.c @@ -0,0 +1,1728 @@ +/* + * Real Audio 1.0 (14.4K) + * Copyright (c) 2003 the ffmpeg project + * + * 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 "avcodec.h" +#include "celp_filters.h" +#include "mathops.h" +#include "ra144.h" + +const int16_t ff_gain_val_tab[256][3] = { + { 541, 956, 768}, { 877, 581, 568}, { 675,1574, 635}, {1248,1464, 668}, + {1246, 839, 1394}, {2560,1386, 991}, { 925, 687, 608}, {2208, 797, 1144}, + { 535, 832, 799}, { 762, 605, 1154}, { 832,1122, 1003}, {1180, 687, 1176}, + {1292, 901, 732}, {1656, 689, 896}, {1750,1248, 848}, {2284, 942, 1022}, + { 824,1472, 643}, { 517, 765, 512}, { 562,1816, 1522}, { 694,1826, 2700}, + { 704, 524, 672}, {1442, 757, 2232}, { 884, 551, 1266}, {2232,1007, 1692}, + { 932, 746, 777}, {1132, 822, 926}, {1226, 771, 611}, {2948,1342, 1008}, + {1302, 594, 1158}, {1602, 636, 1128}, {3408, 910, 1438}, {1996, 614, 575}, + { 665, 935, 628}, { 631,1192, 829}, { 644, 926, 1052}, { 879, 988, 1226}, + { 941,2768, 2772}, { 565,1344, 2304}, { 547, 628, 740}, { 639, 532, 1074}, + { 955,1208, 598}, {1124,1160, 900}, {1206, 899, 1242}, { 746, 533, 624}, + {1458,1028, 735}, {1706,1102, 692}, {1898,1018, 1004}, {2176, 988, 735}, + {1578, 782, 1642}, { 897, 516, 754}, {2068, 702, 1656}, {2344, 818, 1526}, + { 907, 652, 592}, {1056, 652, 642}, {2124,1416, 780}, {2664,1250, 727}, + {1894, 727, 1108}, {2196, 657, 981}, {4840, 920, 1704}, {4992,1238, 983}, + {2420, 909, 1094}, {2760, 935, 1032}, {2800, 612, 853}, {3068, 832, 574}, + { 523,1796, 923}, { 722,1916, 1382}, {1226,1542, 928}, { 758, 757, 584}, + { 512,1134, 577}, { 615,1276, 698}, { 574,2568, 2356}, { 993,2728, 3512}, + { 539, 890, 913}, { 694, 928, 1088}, { 805, 600, 1360}, {2160, 951, 3128}, + { 816, 950, 590}, { 955, 847, 811}, {1094, 883, 556}, {1304, 888, 604}, + { 863,1170, 855}, {1023, 997, 1032}, { 932,1228, 1280}, { 627, 564, 573}, + { 876, 900, 1448}, {1030, 857, 1792}, {1294, 953, 1758}, {1612, 854, 1714}, + {1090,1166, 631}, {1314,1202, 751}, {1480, 905, 795}, {1682,1016, 568}, + {1494,1178, 983}, { 878, 613, 526}, {1728,1446, 779}, {2136,1348, 774}, + { 950, 649, 939}, {1180, 703, 899}, {1236, 527, 1158}, {1450, 647, 972}, + {1282, 647, 707}, {1460, 663, 644}, {1614, 572, 578}, {3516,1222, 821}, + {2668, 729, 1682}, {3128, 585, 1502}, {3208, 733, 976}, {6800, 871, 1416}, + {3480, 743, 1408}, {3764, 899, 1170}, {3772, 632, 875}, {4092, 732, 638}, + {3112, 753, 2620}, {3372, 945, 1890}, {3768, 969, 2288}, {2016, 559, 854}, + {1736, 729, 787}, {1940, 686, 547}, {2140, 635, 674}, {4480,1272, 828}, + {3976, 592, 1666}, {4384, 621, 1388}, {4400, 801, 955}, {4656, 522, 646}, + {4848, 625, 1636}, {4984, 591, 874}, {5352, 535, 1001}, {11216,938, 1184}, + { 925,3280, 1476}, { 735,1580, 1088}, {1150,1576, 674}, { 655, 783, 528}, + { 527,2052, 1354}, { 782,1704, 1880}, { 578, 910, 1026}, { 692, 882, 1468}, + { 586, 683, 715}, { 739, 609, 717}, { 778, 773, 697}, { 922, 785, 813}, + { 766, 651, 984}, { 978, 596, 1030}, {1070, 757, 1080}, {1324, 687, 1178}, + {1108,2144, 979}, { 723, 982, 690}, { 936, 956, 527}, {1180,1002, 547}, + { 517,1306, 825}, { 832,1184, 974}, {1024, 957, 903}, {1262,1090, 906}, + {1028, 720, 649}, {1192, 679, 694}, {2468,1480, 979}, {2844,1370, 877}, + {1310, 835, 848}, {1508, 839, 698}, {1742,1030, 769}, {1910, 852, 573}, + {1280, 859, 1174}, {1584, 863, 1108}, {1686, 708, 1364}, {1942, 768, 1104}, + { 891, 536, 690}, {1016, 560, 663}, {2172, 870, 1348}, {2404, 999, 1170}, + {1890, 966, 889}, {2116, 912, 777}, {2296,1020, 714}, {4872,1844, 932}, + {2392, 778, 929}, {2604, 772, 744}, {2764, 957, 722}, {5832,1532, 984}, + {2188, 519, 1264}, {2332, 532, 922}, {5064, 995, 2412}, {2708, 571, 874}, + {2408, 545, 666}, {5016,1084, 875}, {5376, 983, 1196}, {5536, 979, 730}, + {5344, 634, 1744}, {5688, 706, 1348}, {5912, 977, 1190}, {6072, 905, 763}, + {6048, 582, 1526}, {11968,1013,1816}, {12864,937, 1900}, {12560,1086, 998}, + {1998, 684, 1884}, {2504, 633, 1992}, {1252, 567, 835}, {1478, 571, 973}, + {2620, 769, 1414}, {2808, 952, 1142}, {2908, 712, 1028}, {2976, 686, 741}, + {1462, 552, 714}, {3296, 991, 1452}, {1590, 615, 544}, {3480,1150, 824}, + {3212, 832, 923}, {3276, 839, 531}, {3548, 786, 852}, {3732, 764, 570}, + {5728, 906, 2616}, {6272, 804, 2252}, {3096, 535, 876}, {3228, 598, 649}, + {6536, 759, 1436}, {6648, 993, 846}, {6864, 567, 1210},{14016,1012, 1302}, + {3408, 548, 1098}, {7160,1008, 1742}, {7136,1000, 1182}, {7480,1032, 836}, + {7448, 612, 1552}, {7744, 614, 816}, {8384, 777, 1438}, {8784, 694, 786}, + { 882,1508, 1068}, { 597, 837, 766}, {1270, 954, 1408}, { 803, 550, 798}, + {1398,1308, 798}, {1848,1534, 738}, { 970, 675, 608}, {1264, 706, 684}, + {1716, 767, 1126}, {2108, 765, 1404}, {2236, 924, 1003}, {2472,1048, 611}, + { 999, 942, 963}, {1094, 857, 935}, {2936, 926, 1138}, {1934, 746, 551}, + {3336, 633, 1762}, {3764, 701, 1454}, {1890, 564, 636}, {4096,1126, 793}, + {3936, 556, 1140}, {3936, 540, 740}, {4216, 764, 874}, {8480,1328, 1014}, + {2184, 515, 1042}, {4432, 934, 1344}, {4784, 945, 1112}, {5016,1062, 733}, + {9216,1020, 2028}, {9968, 924, 1188}, {5424, 909, 1206}, {6512, 744, 1086} +}; + +const uint8_t ff_gain_exp_tab[256] = { + 15, 15, 15, 15, 15, 16, 14, 15, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 13, 14, 14, 13, 14, 13, 14, 13, 13, 13, 14, 13, 13, 14, 13, + 13, 13, 13, 13, 14, 13, 12, 12, 13, 13, 13, 12, 13, 13, 13, 13, + 13, 12, 13, 13, 12, 12, 13, 13, 13, 13, 14, 14, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 12, 13, 13, 12, 12, 12, 13, 12, 12, 12, 12, + 12, 12, 12, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 13, 13, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, + 13, 12, 12, 11, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 11, 11, 11, 11, + 12, 12, 12, 12, 11, 11, 12, 12, 12, 12, 12, 13, 12, 12, 12, 13, + 12, 12, 13, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 12, 12, 11, 11, 12, 12, 12, 12, 11, 12, 11, 12, 12, 12, 12, 12, + 13, 13, 12, 12, 13, 13, 13, 14, 12, 13, 13, 13, 13, 13, 13, 13, + 11, 10, 11, 10, 11, 11, 10, 10, 11, 11, 11, 11, 10, 9, 11, 10, + 12, 12, 11, 12, 12, 12, 12, 13, 11, 12, 12, 12, 13, 13, 12, 12 +}; + +const int8_t ff_cb1_vects[128][40]={ + { + 38, -4, 15, -4, 14, -13, 12, -11, -2, -6, + -6, -11, -45, -16, -11, -13, -7, 6, -12, 4, + -20, 3, -16, 12, -1, 12, 46, 24, 0, 33, + -3, 9, -12, -12, -8, -7, 17, -6, 0, -2, + }, { + 60, -16, 3, -22, 10, -32, 0, -28, -17, -18, + -3, -25, -37, -23, -10, 3, 2, 3, 0, 3, + -14, 0, -14, -1, 0, 2, 32, 9, -1, 25, + 7, 13, -5, 13, 8, 1, 2, 8, -10, 6, + }, { + 27, -12, 28, -2, 6, -7, 15, 9, -11, 1, + -13, -11, -40, 4, -29, -14, -19, -5, -23, -8, + -30, -13, -17, 0, -14, 12, 34, 20, -2, 25, + 2, -16, -4, -12, 15, 16, 29, 7, 24, 10, + }, { + 49, -24, 16, -20, 2, -26, 2, -7, -25, -10, + -11, -25, -32, -3, -27, 2, -8, -8, -11, -9, + -24, -17, -16, -14, -13, 2, 20, 5, -4, 17, + 14, -12, 3, 13, 33, 25, 14, 23, 15, 19, + }, { + 46, -6, 21, 8, -2, -16, -5, -8, -11, 4, + 8, 15, -24, 4, -2, -26, -3, -16, -16, -14, + -9, -2, -1, 4, 19, 7, 36, 17, 9, 13, + 0, 31, -5, -12, 7, -8, 11, -15, -13, -4, + }, { + 68, -18, 9, -9, -6, -35, -18, -25, -26, -7, + 10, 1, -16, -3, -1, -9, 6, -19, -4, -15, + -4, -6, 0, -8, 20, -2, 23, 2, 7, 5, + 12, 35, 1, 13, 24, 0, -3, 0, -22, 4, + }, { + 35, -14, 34, 10, -10, -10, -1, 12, -20, 12, + 0, 15, -18, 24, -20, -27, -14, -28, -27, -27, + -20, -19, -2, -8, 5, 7, 25, 13, 5, 5, + 6, 5, 2, -12, 31, 15, 23, -1, 12, 8, + }, { + 57, -26, 22, -7, -14, -28, -14, -3, -35, 0, + 3, 1, -11, 16, -18, -10, -4, -31, -15, -28, + -14, -23, -1, -21, 7, -2, 11, -1, 3, -1, + 18, 9, 10, 13, 49, 24, 8, 14, 2, 16, + }, { + 25, 15, 22, 11, 18, 4, 15, -22, 8, -2, + -17, -9, -48, -20, -30, -17, -16, 11, -1, 16, + 2, 10, -5, 26, -2, -4, 22, 0, 2, 10, + -6, 13, -14, 10, -23, 0, 10, -2, 1, 0, + }, { + 47, 3, 11, -6, 15, -13, 2, -38, -6, -13, + -15, -22, -40, -28, -28, 0, -5, 8, 10, 15, + 7, 7, -4, 13, -1, -14, 9, -14, 0, 2, + 4, 18, -7, 36, -6, 8, -3, 13, -7, 8, + }, { + 14, 7, 36, 13, 10, 10, 18, 0, 0, 5, + -25, -8, -43, 0, -48, -18, -27, 0, -12, 3, + -7, -6, -7, 13, -15, -5, 11, -3, 0, 2, + 0, -12, -6, 10, 0, 23, 22, 11, 26, 12, + }, { + 36, -5, 24, -4, 7, -7, 6, -17, -14, -5, + -22, -22, -35, -8, -46, -1, -17, -3, 0, 2, + -2, -10, -5, 0, -14, -15, -2, -18, -2, -4, + 11, -7, 1, 36, 18, 32, 7, 27, 17, 20, + }, { + 33, 13, 29, 24, 1, 1, -2, -18, 0, 9, + -3, 17, -27, 0, -21, -30, -12, -11, -5, -2, + 12, 4, 9, 19, 18, -9, 13, -6, 11, -8, + -2, 35, -8, 10, -7, -1, 4, -11, -10, -2, + }, { + 55, 1, 17, 6, -1, -16, -15, -35, -15, -2, + 0, 4, -19, -8, -20, -13, -1, -14, 7, -3, + 18, 0, 10, 5, 19, -19, 0, -21, 8, -16, + 9, 39, 0, 36, 10, 7, -9, 4, -20, 5, + }, { + 22, 5, 42, 26, -6, 8, 1, 2, -9, 17, + -10, 18, -21, 19, -39, -31, -23, -23, -16, -15, + 2, -12, 7, 6, 5, -9, 1, -10, 7, -16, + 4, 9, 0, 10, 17, 22, 16, 2, 14, 9, + }, { + 44, -6, 30, 8, -9, -10, -11, -14, -23, 5, + -8, 4, -14, 12, -37, -14, -12, -26, -4, -16, + 8, -16, 9, -7, 6, -19, -12, -25, 5, -24, + 15, 13, 8, 36, 34, 31, 1, 18, 4, 18, + }, { + -3, -5, -9, -7, 15, -1, 5, 13, 2, 12, + 5, 2, -21, -23, -2, -16, 0, 5, -6, 13, + -23, 3, -32, 10, -15, 8, 44, 28, 9, 37, + -2, 13, -9, -15, -12, -27, -7, -12, 0, -11, + }, { + 18, -17, -21, -25, 11, -19, -6, -3, -11, 0, + 7, -11, -13, -31, -1, 0, 9, 1, 5, 12, + -18, 0, -31, -2, -13, -1, 30, 14, 7, 29, + 9, 18, -1, 10, 4, -18, -22, 3, -10, -2, + }, { + -13, -13, 3, -5, 7, 4, 9, 34, -5, 20, + -2, 3, -16, -3, -20, -17, -11, -7, -17, 0, + -34, -13, -33, -2, -28, 8, 32, 24, 5, 29, + 3, -12, 0, -15, 11, -3, 3, 2, 24, 1, + }, { + 8, -25, -8, -23, 3, -13, -3, 17, -20, 8, + 0, -10, -8, -11, -18, 0, -1, -10, -5, 0, + -28, -17, -32, -15, -26, -1, 19, 9, 3, 21, + 15, -7, 6, 9, 29, 5, -10, 17, 15, 9, + }, { + 4, -6, -3, 5, -1, -4, -11, 16, -6, 23, + 19, 29, 0, -3, 6, -30, 3, -17, -10, -5, + -13, -2, -17, 3, 5, 3, 35, 21, 17, 17, + 2, 35, -2, -15, 3, -28, -13, -21, -13, -13, + }, { + 26, -19, -15, -12, -5, -22, -24, 0, -21, 12, + 21, 15, 8, -11, 7, -12, 14, -20, 2, -6, + -7, -6, -16, -9, 6, -5, 21, 7, 15, 10, + 13, 39, 5, 10, 20, -19, -28, -5, -22, -5, + }, { + -5, -15, 9, 7, -9, 2, -8, 37, -14, 31, + 11, 29, 5, 16, -11, -30, -7, -29, -21, -18, + -23, -19, -18, -9, -7, 3, 23, 17, 14, 9, + 8, 9, 6, -15, 27, -4, -2, -6, 12, -1, + }, { + 16, -27, -2, -10, -13, -16, -20, 20, -29, 20, + 14, 16, 13, 8, -9, -13, 2, -33, -9, -19, + -17, -23, -17, -22, -6, -6, 9, 2, 12, 2, + 20, 13, 13, 10, 45, 4, -16, 8, 2, 7, + }, { + -16, 14, -2, 8, 20, 17, 9, 2, 14, 16, + -6, 5, -24, -28, -21, -20, -8, 9, 4, 25, + -1, 11, -22, 24, -15, -8, 21, 5, 11, 14, + -5, 18, -11, 7, -27, -20, -14, -7, 1, -9, + }, { + 6, 2, -14, -9, 16, -1, -3, -14, 0, 5, + -3, -8, -16, -36, -19, -3, 1, 6, 17, 24, + 4, 7, -21, 11, -14, -18, 7, -9, 9, 7, + 6, 22, -3, 33, -10, -11, -28, 7, -7, 0, + }, { + -26, 6, 11, 10, 12, 23, 12, 23, 5, 24, + -13, 5, -19, -8, -38, -21, -20, -2, -6, 12, + -11, -5, -23, 11, -29, -9, 9, 0, 7, 6, + 1, -7, -2, 7, -3, 3, -2, 6, 27, 3, + }, { + -4, -6, 0, -7, 8, 4, 0, 6, -9, 13, + -11, -7, -11, -15, -37, -4, -9, -5, 5, 11, + -5, -9, -22, -1, -27, -18, -4, -14, 5, 0, + 12, -3, 4, 32, 14, 12, -17, 22, 17, 11, + }, { + -8, 12, 3, 21, 3, 14, -8, 5, 4, 28, + 7, 32, -2, -8, -12, -34, -4, -12, 1, 6, + 9, 4, -7, 17, 4, -13, 11, -1, 19, -4, + 0, 39, -4, 7, -11, -21, -20, -16, -10, -11, + }, { + 13, 0, -8, 3, 0, -4, -21, -11, -9, 16, + 10, 18, 5, -16, -10, -16, 5, -15, 13, 5, + 15, 1, -6, 4, 6, -23, -2, -16, 17, -12, + 10, 44, 3, 33, 6, -12, -34, -1, -20, -3, + }, { + -18, 4, 17, 23, -4, 20, -4, 26, -3, 36, + 0, 32, 2, 12, -29, -34, -16, -24, -10, -6, + 0, -12, -8, 4, -8, -13, 0, -6, 16, -12, + 5, 13, 3, 7, 13, 3, -8, -2, 14, 0, + }, { + 3, -7, 5, 5, -8, 2, -17, 9, -18, 24, + 2, 19, 10, 4, -28, -17, -5, -28, 2, -7, + 4, -15, -7, -8, -6, -23, -13, -21, 14, -20, + 17, 18, 11, 33, 30, 11, -23, 13, 5, 9, + }, { + 60, 10, 7, -1, 9, -8, 6, -13, 2, -15, + -1, -10, -13, -11, 15, 0, 6, 9, -1, 0, + -13, 1, -11, -3, -13, 21, 13, 26, -7, 31, + -10, -7, -16, -33, -31, -10, 22, -8, 1, -2, + }, { + 82, -1, -4, -19, 6, -27, -6, -29, -12, -26, + 1, -24, -5, -18, 17, 17, 17, 6, 10, 0, + -7, -2, -9, -16, -12, 11, 0, 11, -9, 23, + 0, -3, -8, -8, -13, -1, 8, 7, -7, 6, + }, { + 49, 2, 21, 0, 1, -2, 9, 8, -6, -6, + -8, -10, -8, 9, -2, 0, -4, -2, -13, -12, + -23, -15, -12, -16, -26, 21, 2, 21, -11, 23, + -4, -33, -7, -33, -6, 13, 34, 5, 27, 10, + }, { + 71, -10, 9, -17, -1, -20, -3, -8, -21, -18, + -6, -24, 0, 1, 0, 16, 6, -5, 0, -13, + -17, -19, -11, -29, -25, 11, -11, 6, -13, 15, + 7, -29, 0, -8, 11, 22, 20, 21, 17, 18, + }, { + 67, 8, 14, 11, -7, -11, -11, -9, -7, -3, + 13, 16, 8, 9, 24, -12, 10, -13, -5, -17, + -2, -4, 3, -10, 6, 17, 4, 19, 0, 11, + -6, 13, -9, -33, -14, -10, 16, -17, -10, -4, + }, { + 90, -3, 2, -6, -10, -29, -24, -26, -21, -15, + 15, 2, 16, 1, 25, 4, 21, -16, 6, -18, + 3, -8, 5, -24, 8, 7, -9, 4, -1, 3, + 5, 18, -1, -7, 2, -1, 2, -1, -19, 3, + }, { + 57, 0, 27, 13, -14, -5, -7, 11, -15, 4, + 5, 16, 13, 29, 6, -13, 0, -25, -16, -31, + -12, -22, 2, -23, -6, 16, -7, 14, -2, 3, + 0, -12, 0, -33, 9, 13, 28, -3, 14, 7, + }, { + 79, -11, 15, -4, -18, -23, -20, -5, -30, -7, + 7, 2, 21, 21, 8, 3, 10, -28, -4, -31, + -6, -25, 3, -37, -4, 7, -20, 0, -4, -4, + 11, -7, 6, -8, 27, 22, 14, 12, 5, 16, + }, { + 47, 30, 15, 14, 14, 9, 9, -23, 13, -10, + -12, -7, -16, -15, -3, -3, -1, 14, 9, 12, + 9, 8, 0, 10, -14, 4, -9, 2, -5, 8, + -13, -3, -18, -10, -45, -3, 16, -4, 4, 0, + }, { + 69, 17, 3, -3, 10, -8, -3, -40, -1, -21, + -10, -21, -8, -23, -1, 13, 8, 11, 21, 11, + 15, 4, 0, -2, -13, -5, -23, -12, -7, 0, + -1, 0, -10, 14, -28, 5, 1, 11, -5, 7, + }, { + 36, 21, 28, 16, 6, 16, 12, -2, 4, -2, + -20, -7, -11, 4, -20, -4, -12, 2, -1, 0, + 0, -8, -2, -2, -27, 4, -21, -2, -9, 0, + -6, -29, -9, -10, -21, 21, 28, 10, 29, 11, + }, { + 58, 9, 16, -1, 2, -2, 0, -19, -10, -13, + -17, -21, -3, -3, -19, 12, -2, 0, 10, -1, + 5, -12, 0, -15, -26, -5, -34, -16, -11, -7, + 4, -25, -2, 14, -3, 29, 13, 25, 20, 20, + }, { + 55, 28, 21, 27, -2, 7, -8, -20, 4, 1, + 1, 18, 5, 4, 5, -16, 2, -8, 5, -5, + 19, 2, 14, 3, 6, 0, -18, -4, 2, -11, + -8, 18, -11, -10, -29, -3, 10, -13, -8, -3, + }, { + 77, 16, 9, 9, -6, -11, -21, -37, -10, -10, + 4, 5, 13, -3, 7, 0, 13, -11, 17, -6, + 25, -1, 15, -9, 7, -9, -32, -19, 0, -18, + 2, 22, -3, 15, -12, 5, -4, 2, -17, 5, + }, { + 44, 20, 34, 29, -10, 13, -4, 0, -4, 9, + -5, 19, 10, 24, -11, -17, -8, -20, -5, -19, + 9, -14, 12, -9, -6, 0, -30, -9, 0, -19, + -2, -7, -2, -10, -5, 20, 21, 1, 17, 9, + }, { + 66, 8, 23, 11, -14, -5, -17, -16, -19, -2, + -3, 5, 18, 17, -10, 0, 1, -23, 6, -20, + 15, -18, 14, -22, -5, -10, -44, -23, -2, -26, + 9, -3, 4, 14, 12, 29, 7, 16, 7, 18, + }, { + 18, 9, -17, -4, 11, 3, 0, 11, 7, 4, + 10, 3, 10, -18, 24, -3, 14, 7, 4, 10, + -16, 1, -27, -4, -27, 17, 12, 30, 0, 35, + -9, -3, -12, -36, -35, -30, -2, -13, 2, -11, + }, { + 40, -2, -29, -22, 7, -14, -12, -5, -7, -7, + 12, -9, 18, -26, 26, 14, 24, 4, 16, 9, + -10, -2, -26, -18, -26, 7, -1, 15, -1, 27, + 2, 0, -4, -11, -17, -21, -16, 1, -7, -3, + }, { + 8, 1, -3, -2, 3, 10, 3, 32, -1, 12, + 2, 4, 15, 1, 7, -3, 2, -4, -6, -3, + -26, -15, -29, -17, -40, 17, 0, 26, -2, 27, + -2, -29, -4, -36, -10, -6, 9, 0, 27, 0, + }, { + 30, -11, -15, -20, 0, -8, -9, 15, -15, 0, + 5, -9, 23, -6, 8, 13, 13, -7, 5, -3, + -20, -19, -27, -31, -39, 7, -13, 11, -4, 19, + 8, -25, 3, -11, 7, 2, -4, 16, 18, 9, + }, { + 26, 7, -11, 8, -5, 1, -17, 14, -1, 15, + 24, 30, 32, 1, 33, -16, 18, -14, 0, -8, + -6, -4, -12, -12, -6, 13, 2, 23, 8, 15, + -4, 17, -5, -36, -18, -30, -8, -22, -10, -14, + }, { + 48, -4, -23, -9, -9, -17, -30, -2, -16, 3, + 26, 16, 40, -6, 35, 1, 28, -17, 12, -9, + 0, -8, -11, -25, -5, 3, -10, 8, 6, 7, + 6, 22, 1, -11, -1, -21, -22, -7, -19, -5, + }, { + 15, 0, 2, 10, -13, 7, -14, 35, -10, 23, + 16, 31, 37, 21, 16, -17, 6, -26, -10, -21, + -16, -21, -13, -25, -19, 13, -8, 19, 5, 7, + 1, -8, 2, -36, 5, -6, 3, -8, 15, -1, + }, { + 37, -12, -9, -7, -17, -11, -26, 18, -25, 12, + 19, 17, 45, 14, 17, 0, 17, -30, 1, -22, + -10, -25, -12, -38, -18, 3, -22, 4, 3, 0, + 13, -3, 10, -11, 23, 2, -10, 7, 5, 7, + }, { + 5, 29, -9, 11, 15, 22, 3, 0, 18, 8, + -1, 6, 7, -23, 6, -6, 5, 12, 15, 21, + 5, 8, -17, 9, -28, 0, -11, 6, 2, 12, + -11, 0, -14, -13, -49, -22, -8, -9, 4, -9, + }, { + 27, 16, -21, -6, 12, 3, -9, -16, 3, -2, + 1, -7, 15, -31, 7, 10, 16, 9, 27, 21, + 11, 5, -16, -3, -26, -9, -24, -7, 0, 4, + 0, 4, -6, 11, -32, -14, -23, 6, -5, -1, + }, { + -4, 20, 3, 13, 8, 28, 6, 21, 10, 16, + -8, 7, 12, -3, -11, -7, -5, 0, 4, 8, + -4, -8, -18, -3, -41, 0, -22, 2, 0, 4, + -5, -25, -6, -14, -25, 1, 2, 4, 29, 2, + }, { + 17, 8, -8, -4, 4, 10, -6, 5, -4, 5, + -6, -6, 20, -10, -9, 9, 4, -2, 16, 7, + 1, -12, -17, -16, -39, -9, -36, -12, -2, -3, + 6, -21, 1, 11, -7, 10, -11, 20, 20, 11, + }, { + 13, 27, -3, 24, -1, 19, -14, 3, 9, 20, + 12, 33, 29, -3, 15, -20, 9, -9, 11, 3, + 16, 2, -2, 2, -7, -3, -20, 0, 10, -7, + -7, 22, -7, -13, -33, -23, -14, -18, -7, -12, + }, { + 35, 15, -15, 6, -4, 1, -27, -12, -5, 8, + 15, 19, 37, -11, 16, -2, 20, -12, 23, 2, + 22, -1, -1, -11, -5, -13, -34, -14, 8, -14, + 4, 26, 0, 11, -16, -14, -29, -2, -17, -3, + }, { + 3, 19, 9, 26, -8, 26, -10, 24, 0, 28, + 5, 33, 34, 17, -2, -20, -1, -22, 0, -10, + 6, -14, -3, -10, -20, -4, -32, -4, 7, -15, + 0, -3, 0, -13, -9, 0, -3, -4, 17, 0, + }, { + 25, 7, -2, 8, -12, 7, -23, 8, -13, 16, + 7, 20, 42, 9, 0, -3, 9, -25, 12, -10, + 12, -18, -2, -24, -19, -13, -46, -19, 5, -22, + 10, 0, 8, 11, 8, 9, -17, 11, 7, 8, + }, { + -25, -7, 2, -8, 12, -7, 23, -8, 13, -16, + -7, -20, -42, -9, 0, 3, -9, 25, -12, 10, + -12, 18, 2, 24, 19, 13, 46, 19, -5, 22, + -10, 0, -8, -11, -8, -9, 17, -11, -7, -8, + }, { + -3, -19, -9, -26, 8, -26, 10, -24, 0, -28, + -5, -33, -34, -17, 2, 20, 1, 22, 0, 10, + -6, 14, 3, 10, 20, 4, 32, 4, -7, 15, + 0, 3, 0, 13, 9, 0, 3, 4, -17, 0, + }, { + -35, -15, 15, -6, 4, -1, 27, 12, 5, -8, + -15, -19, -37, 11, -16, 2, -20, 12, -23, -2, + -22, 1, 1, 11, 5, 13, 34, 14, -8, 14, + -4, -26, 0, -11, 16, 14, 29, 2, 17, 3, + }, { + -13, -27, 3, -24, 1, -19, 14, -3, -9, -20, + -12, -33, -29, 3, -15, 20, -9, 9, -11, -3, + -16, -2, 2, -2, 7, 3, 20, 0, -10, 7, + 7, -22, 7, 13, 33, 23, 14, 18, 7, 12, + }, { + -17, -8, 8, 4, -4, -10, 6, -5, 4, -5, + 6, 6, -20, 10, 9, -9, -4, 2, -16, -7, + -1, 12, 17, 16, 39, 9, 36, 12, 2, 3, + -6, 21, -1, -11, 7, -10, 11, -20, -20, -11, + }, { + 4, -20, -3, -13, -8, -28, -6, -21, -10, -16, + 8, -7, -12, 3, 11, 7, 5, 0, -4, -8, + 4, 8, 18, 3, 41, 0, 22, -2, 0, -4, + 5, 25, 6, 14, 25, -1, -2, -4, -29, -2, + }, { + -27, -16, 21, 6, -12, -3, 9, 16, -3, 2, + -1, 7, -15, 31, -7, -10, -16, -9, -27, -21, + -11, -5, 16, 3, 26, 9, 24, 7, 0, -4, + 0, -4, 6, -11, 32, 14, 23, -6, 5, 1, + }, { + -5, -29, 9, -11, -15, -22, -3, 0, -18, -8, + 1, -6, -7, 23, -6, 6, -5, -12, -15, -21, + -5, -8, 17, -9, 28, 0, 11, -6, -2, -12, + 11, 0, 14, 13, 49, 22, 8, 9, -4, 9, + }, { + -37, 12, 9, 7, 17, 11, 26, -18, 25, -12, + -19, -17, -45, -14, -17, 0, -17, 30, -1, 22, + 10, 25, 12, 38, 18, -3, 22, -4, -3, 0, + -13, 3, -10, 11, -23, -2, 10, -7, -5, -7, + }, { + -15, 0, -2, -10, 13, -7, 14, -35, 10, -23, + -16, -31, -37, -21, -16, 17, -6, 26, 10, 21, + 16, 21, 13, 25, 19, -13, 8, -19, -5, -7, + -1, 8, -2, 36, -5, 6, -3, 8, -15, 1, + }, { + -48, 4, 23, 9, 9, 17, 30, 2, 16, -3, + -26, -16, -40, 6, -35, -1, -28, 17, -12, 9, + 0, 8, 11, 25, 5, -3, 10, -8, -6, -7, + -6, -22, -1, 11, 1, 21, 22, 7, 19, 5, + }, { + -26, -7, 11, -8, 5, -1, 17, -14, 1, -15, + -24, -30, -32, -1, -33, 16, -18, 14, 0, 8, + 6, 4, 12, 12, 6, -13, -2, -23, -8, -15, + 4, -17, 5, 36, 18, 30, 8, 22, 10, 14, + }, { + -30, 11, 15, 20, 0, 8, 9, -15, 15, 0, + -5, 9, -23, 6, -8, -13, -13, 7, -5, 3, + 20, 19, 27, 31, 39, -7, 13, -11, 4, -19, + -8, 25, -3, 11, -7, -2, 4, -16, -18, -9, + }, { + -8, -1, 3, 2, -3, -10, -3, -32, 1, -12, + -2, -4, -15, -1, -7, 3, -2, 4, 6, 3, + 26, 15, 29, 17, 40, -17, 0, -26, 2, -27, + 2, 29, 4, 36, 10, 6, -9, 0, -27, 0, + }, { + -40, 2, 29, 22, -7, 14, 12, 5, 7, 7, + -12, 9, -18, 26, -26, -14, -24, -4, -16, -9, + 10, 2, 26, 18, 26, -7, 1, -15, 1, -27, + -2, 0, 4, 11, 17, 21, 16, -1, 7, 3, + }, { + -18, -9, 17, 4, -11, -3, 0, -11, -7, -4, + -10, -3, -10, 18, -24, 3, -14, -7, -4, -10, + 16, -1, 27, 4, 27, -17, -12, -30, 0, -35, + 9, 3, 12, 36, 35, 30, 2, 13, -2, 11, + }, { + -66, -8, -23, -11, 14, 5, 17, 16, 19, 2, + 3, -5, -18, -17, 10, 0, -1, 23, -6, 20, + -15, 18, -14, 22, 5, 10, 44, 23, 2, 26, + -9, 3, -4, -14, -12, -29, -7, -16, -7, -18, + }, { + -44, -20, -34, -29, 10, -13, 4, 0, 4, -9, + 5, -19, -10, -24, 11, 17, 8, 20, 5, 19, + -9, 14, -12, 9, 6, 0, 30, 9, 0, 19, + 2, 7, 2, 10, 5, -20, -21, -1, -17, -9, + }, { + -77, -16, -9, -9, 6, 11, 21, 37, 10, 10, + -4, -5, -13, 3, -7, 0, -13, 11, -17, 6, + -25, 1, -15, 9, -7, 9, 32, 19, 0, 18, + -2, -22, 3, -15, 12, -5, 4, -2, 17, -5, + }, { + -55, -28, -21, -27, 2, -7, 8, 20, -4, -1, + -1, -18, -5, -4, -5, 16, -2, 8, -5, 5, + -19, -2, -14, -3, -6, 0, 18, 4, -2, 11, + 8, -18, 11, 10, 29, 3, -10, 13, 8, 3, + }, { + -58, -9, -16, 1, -2, 2, 0, 19, 10, 13, + 17, 21, 3, 3, 19, -12, 2, 0, -10, 1, + -5, 12, 0, 15, 26, 5, 34, 16, 11, 7, + -4, 25, 2, -14, 3, -29, -13, -25, -20, -20, + }, { + -36, -21, -28, -16, -6, -16, -12, 2, -4, 2, + 20, 7, 11, -4, 20, 4, 12, -2, 1, 0, + 0, 8, 2, 2, 27, -4, 21, 2, 9, 0, + 6, 29, 9, 10, 21, -21, -28, -10, -29, -11, + }, { + -69, -17, -3, 3, -10, 8, 3, 40, 1, 21, + 10, 21, 8, 23, 1, -13, -8, -11, -21, -11, + -15, -4, 0, 2, 13, 5, 23, 12, 7, 0, + 1, 0, 10, -14, 28, -5, -1, -11, 5, -7, + }, { + -47, -30, -15, -14, -14, -9, -9, 23, -13, 10, + 12, 7, 16, 15, 3, 3, 1, -14, -9, -12, + -9, -8, 0, -10, 14, -4, 9, -2, 5, -8, + 13, 3, 18, 10, 45, 3, -16, 4, -4, 0, + }, { + -79, 11, -15, 4, 18, 23, 20, 5, 30, 7, + -7, -2, -21, -21, -8, -3, -10, 28, 4, 31, + 6, 25, -3, 37, 4, -7, 20, 0, 4, 4, + -11, 7, -6, 8, -27, -22, -14, -12, -5, -16, + }, { + -57, 0, -27, -13, 14, 5, 7, -11, 15, -4, + -5, -16, -13, -29, -6, 13, 0, 25, 16, 31, + 12, 22, -2, 23, 6, -16, 7, -14, 2, -3, + 0, 12, 0, 33, -9, -13, -28, 3, -14, -7, + }, { + -90, 3, -2, 6, 10, 29, 24, 26, 21, 15, + -15, -2, -16, -1, -25, -4, -21, 16, -6, 18, + -3, 8, -5, 24, -8, -7, 9, -4, 1, -3, + -5, -18, 1, 7, -2, 1, -2, 1, 19, -3, + }, { + -67, -8, -14, -11, 7, 11, 11, 9, 7, 3, + -13, -16, -8, -9, -24, 12, -10, 13, 5, 17, + 2, 4, -3, 10, -6, -17, -4, -19, 0, -11, + 6, -13, 9, 33, 14, 10, -16, 17, 10, 4, + }, { + -71, 10, -9, 17, 1, 20, 3, 8, 21, 18, + 6, 24, 0, -1, 0, -16, -6, 5, 0, 13, + 17, 19, 11, 29, 25, -11, 11, -6, 13, -15, + -7, 29, 0, 8, -11, -22, -20, -21, -17, -18, + }, { + -49, -2, -21, 0, -1, 2, -9, -8, 6, 6, + 8, 10, 8, -9, 2, 0, 4, 2, 13, 12, + 23, 15, 12, 16, 26, -21, -2, -21, 11, -23, + 4, 33, 7, 33, 6, -13, -34, -5, -27, -10, + }, { + -82, 1, 4, 19, -6, 27, 6, 29, 12, 26, + -1, 24, 5, 18, -17, -17, -17, -6, -10, 0, + 7, 2, 9, 16, 12, -11, 0, -11, 9, -23, + 0, 3, 8, 8, 13, 1, -8, -7, 7, -6, + }, { + -60, -10, -7, 1, -9, 8, -6, 13, -2, 15, + 1, 10, 13, 11, -15, 0, -6, -9, 1, 0, + 13, -1, 11, 3, 13, -21, -13, -26, 7, -31, + 10, 7, 16, 33, 31, 10, -22, 8, -1, 2, + }, { + -3, 7, -5, -5, 8, -2, 17, -9, 18, -24, + -2, -19, -10, -4, 28, 17, 5, 28, -2, 7, + -4, 15, 7, 8, 6, 23, 13, 21, -14, 20, + -17, -18, -11, -33, -30, -11, 23, -13, -5, -9, + }, { + 18, -4, -17, -23, 4, -20, 4, -26, 3, -36, + 0, -32, -2, -12, 29, 34, 16, 24, 10, 6, + 0, 12, 8, -4, 8, 13, 0, 6, -16, 12, + -5, -13, -3, -7, -13, -3, 8, 2, -14, 0, + }, { + -13, 0, 8, -3, 0, 4, 21, 11, 9, -16, + -10, -18, -5, 16, 10, 16, -5, 15, -13, -5, + -15, -1, 6, -4, -6, 23, 2, 16, -17, 12, + -10, -44, -3, -33, -6, 12, 34, 1, 20, 3, + }, { + 8, -12, -3, -21, -3, -14, 8, -5, -4, -28, + -7, -32, 2, 8, 12, 34, 4, 12, -1, -6, + -9, -4, 7, -17, -4, 13, -11, 1, -19, 4, + 0, -39, 4, -7, 11, 21, 20, 16, 10, 11, + }, { + 4, 6, 0, 7, -8, -4, 0, -6, 9, -13, + 11, 7, 11, 15, 37, 4, 9, 5, -5, -11, + 5, 9, 22, 1, 27, 18, 4, 14, -5, 0, + -12, 3, -4, -32, -14, -12, 17, -22, -17, -11, + }, { + 26, -6, -11, -10, -12, -23, -12, -23, -5, -24, + 13, -5, 19, 8, 38, 21, 20, 2, 6, -12, + 11, 5, 23, -11, 29, 9, -9, 0, -7, -6, + -1, 7, 2, -7, 3, -3, 2, -6, -27, -3, + }, { + -6, -2, 14, 9, -16, 1, 3, 14, 0, -5, + 3, 8, 16, 36, 19, 3, -1, -6, -17, -24, + -4, -7, 21, -11, 14, 18, -7, 9, -9, -7, + -6, -22, 3, -33, 10, 11, 28, -7, 7, 0, + }, { + 16, -14, 2, -8, -20, -17, -9, -2, -14, -16, + 6, -5, 24, 28, 21, 20, 8, -9, -4, -25, + 1, -11, 22, -24, 15, 8, -21, -5, -11, -14, + 5, -18, 11, -7, 27, 20, 14, 7, -1, 9, + }, { + -16, 27, 2, 10, 13, 16, 20, -20, 29, -20, + -14, -16, -13, -8, 9, 13, -2, 33, 9, 19, + 17, 23, 17, 22, 6, 6, -9, -2, -12, -2, + -20, -13, -13, -10, -45, -4, 16, -8, -2, -7, + }, { + 5, 15, -9, -7, 9, -2, 8, -37, 14, -31, + -11, -29, -5, -16, 11, 30, 7, 29, 21, 18, + 23, 19, 18, 9, 7, -3, -23, -17, -14, -9, + -8, -9, -6, 15, -27, 4, 2, 6, -12, 1, + }, { + -26, 19, 15, 12, 5, 22, 24, 0, 21, -12, + -21, -15, -8, 11, -7, 12, -14, 20, -2, 6, + 7, 6, 16, 9, -6, 5, -21, -7, -15, -10, + -13, -39, -5, -10, -20, 19, 28, 5, 22, 5, + }, { + -4, 6, 3, -5, 1, 4, 11, -16, 6, -23, + -19, -29, 0, 3, -6, 30, -3, 17, 10, 5, + 13, 2, 17, -3, -5, -3, -35, -21, -17, -17, + -2, -35, 2, 15, -3, 28, 13, 21, 13, 13, + }, { + -8, 25, 8, 23, -3, 13, 3, -17, 20, -8, + 0, 10, 8, 11, 18, 0, 1, 10, 5, 0, + 28, 17, 32, 15, 26, 1, -19, -9, -3, -21, + -15, 7, -6, -9, -29, -5, 10, -17, -15, -9, + }, { + 13, 13, -3, 5, -7, -4, -9, -34, 5, -20, + 2, -3, 16, 3, 20, 17, 11, 7, 17, 0, + 34, 13, 33, 2, 28, -8, -32, -24, -5, -29, + -3, 12, 0, 15, -11, 3, -3, -2, -24, -1, + }, { + -18, 17, 21, 25, -11, 19, 6, 3, 11, 0, + -7, 11, 13, 31, 1, 0, -9, -1, -5, -12, + 18, 0, 31, 2, 13, 1, -30, -14, -7, -29, + -9, -18, 1, -10, -4, 18, 22, -3, 10, 2, + }, { + 3, 5, 9, 7, -15, 1, -5, -13, -2, -12, + -5, -2, 21, 23, 2, 16, 0, -5, 6, -13, + 23, -3, 32, -10, 15, -8, -44, -28, -9, -37, + 2, -13, 9, 15, 12, 27, 7, 12, 0, 11, + }, { + -44, 6, -30, -8, 9, 10, 11, 14, 23, -5, + 8, -4, 14, -12, 37, 14, 12, 26, 4, 16, + -8, 16, -9, 7, -6, 19, 12, 25, -5, 24, + -15, -13, -8, -36, -34, -31, -1, -18, -4, -18, + }, { + -22, -5, -42, -26, 6, -8, -1, -2, 9, -17, + 10, -18, 21, -19, 39, 31, 23, 23, 16, 15, + -2, 12, -7, -6, -5, 9, -1, 10, -7, 16, + -4, -9, 0, -10, -17, -22, -16, -2, -14, -9, + }, { + -55, -1, -17, -6, 1, 16, 15, 35, 15, 2, + 0, -4, 19, 8, 20, 13, 1, 14, -7, 3, + -18, 0, -10, -5, -19, 19, 0, 21, -8, 16, + -9, -39, 0, -36, -10, -7, 9, -4, 20, -5, + }, { + -33, -13, -29, -24, -1, -1, 2, 18, 0, -9, + 3, -17, 27, 0, 21, 30, 12, 11, 5, 2, + -12, -4, -9, -19, -18, 9, -13, 6, -11, 8, + 2, -35, 8, -10, 7, 1, -4, 11, 10, 2, + }, { + -36, 5, -24, 4, -7, 7, -6, 17, 14, 5, + 22, 22, 35, 8, 46, 1, 17, 3, 0, -2, + 2, 10, 5, 0, 14, 15, 2, 18, 2, 4, + -11, 7, -1, -36, -18, -32, -7, -27, -17, -20, + }, { + -14, -7, -36, -13, -10, -10, -18, 0, 0, -5, + 25, 8, 43, 0, 48, 18, 27, 0, 12, -3, + 7, 6, 7, -13, 15, 5, -11, 3, 0, -2, + 0, 12, 6, -10, 0, -23, -22, -11, -26, -12, + }, { + -47, -3, -11, 6, -15, 13, -2, 38, 6, 13, + 15, 22, 40, 28, 28, 0, 5, -8, -10, -15, + -7, -7, 4, -13, 1, 14, -9, 14, 0, -2, + -4, -18, 7, -36, 6, -8, 3, -13, 7, -8, + }, { + -25, -15, -22, -11, -18, -4, -15, 22, -8, 2, + 17, 9, 48, 20, 30, 17, 16, -11, 1, -16, + -2, -10, 5, -26, 2, 4, -22, 0, -2, -10, + 6, -13, 14, -10, 23, 0, -10, 2, -1, 0, + }, { + -57, 26, -22, 7, 14, 28, 14, 3, 35, 0, + -3, -1, 11, -16, 18, 10, 4, 31, 15, 28, + 14, 23, 1, 21, -7, 2, -11, 1, -3, 1, + -18, -9, -10, -13, -49, -24, -8, -14, -2, -16, + }, { + -35, 14, -34, -10, 10, 10, 1, -12, 20, -12, + 0, -15, 18, -24, 20, 27, 14, 28, 27, 27, + 20, 19, 2, 8, -5, -7, -25, -13, -5, -5, + -6, -5, -2, 12, -31, -15, -23, 1, -12, -8, + }, { + -68, 18, -9, 9, 6, 35, 18, 25, 26, 7, + -10, -1, 16, 3, 1, 9, -6, 19, 4, 15, + 4, 6, 0, 8, -20, 2, -23, -2, -7, -5, + -12, -35, -1, -13, -24, 0, 3, 0, 22, -4, + }, { + -46, 6, -21, -8, 2, 16, 5, 8, 11, -4, + -8, -15, 24, -4, 2, 26, 3, 16, 16, 14, + 9, 2, 1, -4, -19, -7, -36, -17, -9, -13, + 0, -31, 5, 12, -7, 8, -11, 15, 13, 4, + }, { + -49, 24, -16, 20, -2, 26, -2, 7, 25, 10, + 11, 25, 32, 3, 27, -2, 8, 8, 11, 9, + 24, 17, 16, 14, 13, -2, -20, -5, 4, -17, + -14, 12, -3, -13, -33, -25, -14, -23, -15, -19, + }, { + -27, 12, -28, 2, -6, 7, -15, -9, 11, -1, + 13, 11, 40, -4, 29, 14, 19, 5, 23, 8, + 30, 13, 17, 0, 14, -12, -34, -20, 2, -25, + -2, 16, 4, 12, -15, -16, -29, -7, -24, -10, + }, { + -60, 16, -3, 22, -10, 32, 0, 28, 17, 18, + 3, 25, 37, 23, 10, -3, -2, -3, 0, -3, + 14, 0, 14, 1, 0, -2, -32, -9, 1, -25, + -7, -13, 5, -13, -8, -1, -2, -8, 10, -6, + }, { + -38, 4, -15, 4, -14, 13, -12, 11, 2, 6, + 6, 11, 45, 16, 11, 13, 7, -6, 12, -4, + 20, -3, 16, -12, 1, -12, -46, -24, 0, -33, + 3, -9, 12, 12, 8, 7, -17, 6, 0, 2 + } +}; + +const int8_t ff_cb2_vects[128][40]={ + { + 73, -32, -60, -15, -26, 59, 2, -33, 30, -10, + -3, -17, 8, 30, -1, -26, -4, -22, 10, 16, + -36, -5, -11, 56, 37, 6, -10, -5, -13, -3, + 6, -5, 11, 4, -19, -5, -16, 41, 24, 13, + }, { + 4, -11, -37, 23, -5, 46, -2, -29, -5, -39, + -21, -9, 0, 49, 12, -9, -16, -26, 22, 15, + -45, -20, -5, 40, 22, 17, -26, 31, -14, 2, + -14, 10, 30, 20, -27, -9, -39, 39, 18, 5, + }, { + 34, -25, -48, -28, -11, 34, -2, -41, 9, -7, + -17, 21, 20, 24, -17, -33, 0, -24, 10, 42, + 3, -5, 10, 42, 11, 8, -3, 3, 16, 9, + 22, -2, 0, -33, -10, 18, 7, 58, 10, 28, + }, { + -34, -4, -25, 10, 9, 21, -7, -36, -26, -36, + -35, 28, 12, 42, -3, -16, -12, -28, 21, 42, + -5, -21, 16, 26, -4, 19, -19, 39, 15, 15, + 1, 13, 19, -17, -17, 14, -15, 55, 4, 19, + }, { + 28, -20, -51, -14, -6, 7, 0, -26, 27, -4, + 18, -40, -6, 16, -1, -15, 0, -55, -5, -16, + -19, 14, -3, 49, 14, 1, -22, -30, -12, 0, + 24, 15, 9, -17, -45, -29, 4, 28, 51, 35, + }, { + -40, 0, -28, 24, 14, -5, -4, -21, -7, -33, + 0, -32, -15, 35, 12, 1, -11, -58, 5, -16, + -28, 0, 1, 33, 0, 11, -39, 5, -14, 6, + 3, 31, 28, -1, -53, -33, -19, 25, 46, 26, + }, { + -11, -14, -39, -27, 9, -17, -4, -33, 6, 0, + 4, -1, 5, 10, -17, -22, 5, -57, -5, 9, + 20, 13, 18, 35, -11, 3, -16, -22, 17, 13, + 40, 19, -1, -55, -35, -5, 27, 44, 37, 49, + }, { + -80, 6, -16, 11, 30, -30, -9, -28, -28, -29, + -13, 6, -2, 28, -3, -5, -7, -60, 5, 9, + 11, -1, 24, 19, -27, 13, -32, 13, 15, 19, + 19, 35, 17, -39, -43, -9, 4, 42, 32, 41, + }, { + 78, -21, -43, 4, -38, 17, 17, -5, 55, 24, + -15, -36, 14, 4, 24, -24, 12, 5, 17, 31, + -54, -5, -2, 27, 43, -12, 2, 9, -9, -15, + 22, -3, 28, 21, -20, 3, 20, 28, 9, -5, + }, { + 9, -1, -20, 43, -17, 3, 12, 0, 20, -4, + -33, -29, 6, 22, 38, -7, 0, 1, 29, 30, + -63, -21, 3, 11, 27, -1, -14, 45, -10, -9, + 1, 12, 47, 37, -28, 0, -2, 26, 4, -13, + }, { + 39, -14, -30, -8, -22, -8, 12, -12, 34, 27, + -29, 2, 26, -2, 8, -31, 16, 3, 17, 57, + -14, -6, 19, 13, 16, -10, 8, 17, 20, -2, + 38, 0, 17, -16, -11, 27, 44, 45, -4, 8, + }, { + -29, 5, -7, 30, -1, -21, 7, -7, 0, 0, + -47, 9, 18, 15, 22, -14, 4, 0, 28, 57, + -23, -21, 25, -2, 1, 0, -7, 53, 19, 3, + 17, 15, 36, 0, -19, 24, 21, 43, -9, 0, + }, { + 33, -10, -34, 5, -17, -35, 15, 1, 53, 30, + 6, -59, 0, -10, 24, -13, 17, -27, 1, -1, + -37, 13, 4, 20, 20, -18, -10, -16, -8, -11, + 39, 18, 26, 0, -46, -20, 41, 15, 37, 15, + }, { + -35, 10, -11, 44, 3, -48, 10, 6, 17, 2, + -11, -51, -8, 8, 38, 3, 4, -31, 12, -2, + -46, -1, 10, 4, 5, -7, -26, 19, -10, -5, + 18, 34, 45, 15, -54, -24, 18, 13, 31, 7, + }, { + -5, -3, -21, -7, -2, -60, 10, -5, 32, 34, + -7, -20, 11, -16, 8, -20, 21, -29, 1, 24, + 2, 13, 27, 6, -5, -15, -3, -8, 21, 1, + 55, 21, 15, -38, -37, 3, 65, 32, 23, 30, + }, { + -74, 17, 0, 31, 18, -73, 5, 0, -3, 5, + -25, -12, 3, 1, 22, -3, 9, -33, 12, 24, + -6, -2, 33, -9, -21, -5, -20, 27, 19, 7, + 34, 37, 34, -22, -44, 0, 41, 29, 17, 21, + }, { + 76, -35, -31, -28, -49, 43, -40, 0, 29, -14, + 8, 5, 10, 18, -26, -46, 0, 7, 6, 3, + -25, -7, -2, 40, 28, 14, 18, -3, -27, -28, + -8, -45, -13, 34, -13, -27, -15, 31, 12, 3, + }, { + 7, -15, -9, 9, -28, 29, -45, 5, -6, -43, + -9, 12, 2, 36, -12, -30, -11, 3, 17, 3, + -34, -22, 3, 24, 12, 24, 2, 32, -28, -22, + -29, -29, 5, 50, -21, -31, -38, 29, 7, -5, + }, { + 36, -29, -19, -41, -34, 18, -45, -6, 8, -10, + -5, 43, 23, 11, -42, -53, 5, 5, 6, 30, + 14, -8, 20, 26, 1, 16, 25, 4, 3, -15, + 7, -41, -23, -3, -4, -3, 8, 48, -1, 17, + }, { + -32, -8, 3, -2, -13, 4, -50, -1, -27, -39, + -23, 51, 15, 30, -27, -37, -7, 1, 17, 29, + 5, -23, 25, 10, -14, 26, 8, 41, 1, -9, + -13, -26, -5, 12, -12, -7, -14, 45, -6, 9, + }, { + 31, -24, -23, -27, -29, -9, -43, 8, 26, -7, + 30, -17, -4, 3, -26, -35, 5, -24, -10, -28, + -9, 12, 5, 33, 5, 8, 5, -29, -26, -24, + 9, -23, -14, 12, -39, -52, 5, 18, 39, 24, + }, { + -37, -3, 0, 10, -7, -22, -48, 12, -8, -36, + 12, -9, -12, 22, -12, -19, -6, -28, 0, -29, + -18, -3, 11, 17, -10, 18, -10, 7, -27, -18, + -11, -7, 3, 28, -47, -55, -18, 15, 34, 16, + }, { + -8, -17, -10, -40, -13, -34, -47, 0, 5, -4, + 16, 21, 8, -2, -42, -43, 10, -26, -10, -2, + 31, 11, 27, 19, -21, 10, 12, -20, 3, -11, + 25, -20, -25, -25, -29, -28, 28, 34, 25, 38, + }, { + -77, 2, 11, -1, 7, -47, -52, 5, -29, -33, + -1, 28, 0, 15, -28, -26, -2, -30, 0, -2, + 22, -4, 33, 3, -36, 21, -3, 15, 2, -5, + 4, -4, -6, -9, -37, -31, 5, 32, 20, 30, + }, { + 81, -25, -14, -8, -61, 0, -25, 28, 54, 20, + -3, -14, 17, -8, 0, -44, 16, 35, 13, 18, + -43, -7, 6, 11, 33, -4, 30, 11, -22, -40, + 6, -43, 3, 50, -14, -18, 22, 18, -1, -16, + }, { + 12, -4, 8, 29, -39, -12, -30, 33, 19, -8, + -21, -6, 8, 9, 13, -28, 4, 31, 24, 18, + -52, -23, 12, -4, 18, 5, 14, 47, -24, -34, + -14, -27, 22, 66, -22, -22, -1, 16, -6, -24, + }, { + 41, -18, -2, -21, -45, -24, -30, 21, 33, 24, + -17, 24, 29, -15, -16, -51, 21, 33, 13, 45, + -3, -8, 28, -2, 7, -2, 37, 19, 7, -27, + 22, -39, -7, 12, -5, 5, 45, 35, -15, -1, + }, { + -27, 1, 20, 17, -24, -38, -35, 26, -1, -4, + -35, 32, 21, 3, -2, -35, 8, 29, 24, 44, + -12, -24, 34, -18, -8, 7, 21, 55, 5, -21, + 2, -23, 11, 28, -13, 1, 22, 33, -21, -10, + }, { + 36, -13, -5, -7, -40, -51, -28, 36, 52, 27, + 18, -36, 2, -22, 0, -33, 21, 2, -3, -13, + -26, 11, 14, 4, 10, -10, 18, -14, -22, -36, + 24, -21, 1, 28, -40, -42, 42, 5, 25, 5, + }, { + -32, 6, 17, 31, -19, -65, -33, 41, 16, -1, + 0, -29, -6, -4, 13, -17, 9, -1, 8, -14, + -35, -3, 19, -11, -4, 0, 1, 21, -23, -30, + 3, -5, 20, 44, -48, -46, 19, 3, 20, -3, + }, { + -3, -7, 6, -20, -25, -77, -32, 29, 31, 30, + 4, 2, 14, -29, -16, -40, 26, 0, -3, 12, + 13, 10, 36, -9, -15, -8, 24, -6, 7, -22, + 40, -17, -8, -9, -31, -18, 66, 22, 11, 19, + }, { + -72, 13, 29, 18, -4, -90, -37, 34, -4, 1, + -13, 9, 6, -11, -2, -24, 13, -3, 7, 11, + 4, -4, 42, -25, -31, 1, 8, 29, 6, -17, + 19, -2, 10, 6, -38, -22, 42, 19, 6, 11, + }, { + 116, -20, -68, -30, -28, 83, 28, -18, 32, -22, + -13, -21, 5, 28, 5, -7, -24, -8, -22, 17, + -23, 30, -25, 45, 15, -9, -11, -18, 22, -10, + 4, -2, 19, -12, 23, 3, -43, 2, 12, -4, + }, { + 47, 0, -45, 7, -7, 69, 23, -13, -2, -51, + -32, -14, -3, 47, 19, 8, -37, -11, -10, 16, + -32, 15, -19, 29, 0, 1, -28, 18, 20, -4, + -16, 13, 38, 3, 15, 0, -66, 0, 7, -13, + }, { + 77, -13, -56, -43, -13, 57, 23, -26, 11, -19, + -27, 16, 17, 22, -10, -15, -19, -10, -22, 43, + 16, 30, -2, 31, -11, -6, -5, -9, 52, 2, + 20, 0, 8, -50, 33, 27, -19, 19, -1, 9, + }, { + 8, 6, -33, -4, 7, 44, 18, -21, -23, -48, + -46, 24, 9, 40, 3, 1, -32, -13, -11, 43, + 7, 14, 3, 15, -26, 3, -21, 26, 50, 8, + 0, 16, 27, -34, 25, 23, -43, 17, -6, 1, + }, { + 71, -9, -59, -29, -8, 30, 26, -11, 30, -16, + 8, -44, -9, 14, 5, 2, -19, -40, -38, -15, + -7, 50, -17, 38, -7, -14, -24, -43, 22, -6, + 22, 19, 17, -34, -2, -20, -23, -10, 39, 16, + }, { + 2, 11, -36, 9, 13, 17, 21, -6, -5, -45, + -10, -36, -18, 33, 19, 19, -31, -44, -27, -15, + -16, 34, -11, 22, -22, -4, -40, -7, 21, 0, + 1, 35, 36, -18, -10, -24, -46, -12, 34, 8, + }, { + 32, -2, -47, -42, 7, 5, 21, -18, 9, -12, + -5, -5, 2, 8, -10, -4, -14, -42, -38, 10, + 33, 49, 5, 24, -33, -12, -17, -35, 52, 6, + 38, 22, 7, -72, 7, 3, 0, 6, 25, 30, + }, { + -36, 18, -24, -3, 28, -7, 16, -13, -26, -41, + -24, 1, -5, 26, 3, 12, -27, -46, -27, 10, + 24, 34, 10, 8, -49, -2, -34, 0, 51, 12, + 17, 38, 25, -56, 0, 0, -22, 3, 20, 22, + }, { + 121, -9, -50, -10, -40, 40, 43, 9, 58, 12, + -25, -41, 11, 2, 31, -5, -8, 19, -15, 32, + -41, 30, -16, 16, 20, -28, 0, -3, 26, -22, + 19, 0, 36, 4, 22, 12, -6, -9, -1, -24, + }, { + 52, 10, -27, 27, -18, 26, 38, 14, 23, -16, + -44, -33, 3, 20, 45, 10, -20, 15, -3, 31, + -50, 14, -10, 0, 5, -17, -15, 32, 24, -16, + -1, 15, 55, 20, 14, 8, -29, -12, -7, -32, + }, { + 82, -3, -38, -23, -24, 15, 38, 2, 37, 15, + -39, -2, 23, -4, 15, -12, -3, 17, -15, 58, + -1, 29, 6, 2, -5, -26, 7, 4, 56, -9, + 35, 3, 25, -33, 32, 36, 17, 7, -15, -9, + }, { + 13, 17, -15, 15, -3, 1, 33, 7, 1, -12, + -58, 5, 15, 13, 29, 3, -16, 13, -4, 57, + -10, 13, 11, -13, -21, -15, -9, 40, 55, -3, + 14, 19, 44, -17, 24, 32, -5, 4, -21, -18, + }, { + 76, 1, -41, -9, -19, -12, 41, 17, 55, 18, + -3, -63, -3, -12, 30, 5, -3, -12, -31, 0, + -24, 49, -8, 9, -1, -33, -12, -29, 27, -18, + 37, 21, 34, -17, -3, -11, 14, -23, 25, -2, + }, { + 7, 22, -18, 29, 1, -25, 36, 21, 20, -9, + -22, -56, -11, 6, 45, 21, -15, -16, -20, -1, + -33, 34, -2, -6, -17, -23, -28, 6, 25, -12, + 16, 37, 53, -1, -11, -15, -8, -25, 20, -11, + }, { + 37, 8, -29, -22, -4, -37, 36, 9, 34, 22, + -17, -24, 8, -18, 15, -2, 1, -14, -31, 25, + 15, 48, 13, -4, -28, -31, -5, -21, 57, -4, + 53, 24, 23, -55, 6, 12, 37, -6, 11, 11, + }, { + -31, 28, -6, 16, 16, -50, 31, 14, 0, -6, + -36, -17, 0, 0, 29, 14, -11, -18, -20, 25, + 6, 33, 19, -20, -43, -21, -21, 14, 55, 0, + 32, 40, 42, -39, -1, 8, 14, -8, 6, 3, + }, { + 119, -24, -39, -44, -51, 66, -14, 15, 31, -26, + -1, 0, 7, 16, -19, -28, -19, 22, -26, 4, + -13, 28, -16, 29, 5, -1, 16, -16, 8, -35, + -10, -42, -4, 17, 29, -19, -42, -7, 0, -15, + }, { + 50, -3, -16, -5, -30, 53, -19, 20, -3, -55, + -19, 8, 0, 34, -5, -11, -32, 18, -15, 4, + -22, 13, -10, 13, -9, 8, 0, 19, 7, -29, + -31, -26, 13, 33, 21, -22, -65, -9, -4, -23, + }, { + 79, -17, -27, -56, -36, 41, -19, 8, 10, -22, + -15, 39, 20, 9, -35, -35, -15, 20, -26, 31, + 26, 27, 6, 15, -20, 0, 23, -8, 38, -22, + 5, -38, -15, -20, 39, 4, -18, 9, -13, -1, + }, { + 10, 3, -4, -18, -15, 27, -24, 13, -24, -51, + -34, 47, 12, 28, -21, -19, -27, 16, -15, 30, + 17, 12, 12, 0, -36, 10, 7, 27, 37, -16, + -15, -22, 3, -4, 31, 1, -42, 7, -18, -9, + }, { + 74, -12, -30, -42, -30, 14, -16, 23, 29, -19, + 20, -21, -7, 1, -19, -17, -14, -10, -43, -27, + 3, 48, -8, 22, -16, -7, 4, -42, 9, -31, + 6, -20, -6, -4, 3, -43, -22, -20, 28, 5, + }, { + 5, 7, -7, -4, -9, 0, -21, 28, -6, -48, + 2, -14, -15, 20, -5, 0, -27, -14, -32, -28, + -5, 32, -2, 6, -32, 3, -12, -5, 8, -25, + -14, -4, 12, 11, -4, -47, -45, -22, 22, -2, + }, { + 34, -6, -18, -55, -15, -11, -21, 16, 8, -16, + 6, 16, 5, -4, -35, -24, -10, -12, -43, -1, + 43, 47, 14, 8, -43, -5, 10, -34, 39, -18, + 22, -16, -17, -42, 13, -19, 1, -3, 14, 20, + }, { + -34, 14, 4, -17, 5, -24, -26, 20, -27, -45, + -12, 24, -2, 13, -21, -8, -22, -16, -32, -2, + 34, 31, 20, -7, -58, 5, -5, 2, 38, -12, + 2, -1, 1, -26, 5, -23, -21, -6, 8, 11, + }, { + 124, -13, -21, -23, -62, 23, 0, 43, 57, 8, + -13, -18, 14, -10, 6, -26, -3, 49, -19, 19, + -31, 27, -7, 0, 11, -20, 29, -1, 12, -47, + 4, -39, 11, 34, 28, -9, -5, -19, -13, -34, + }, { + 55, 6, 1, 14, -41, 10, -4, 48, 22, -20, + -31, -10, 5, 7, 20, -9, -16, 45, -8, 19, + -40, 12, -1, -15, -4, -10, 12, 34, 11, -41, + -16, -24, 30, 49, 20, -13, -28, -22, -18, -43, + }, { + 84, -6, -9, -36, -47, -1, -4, 36, 36, 12, + -27, 20, 26, -17, -9, -33, 1, 47, -19, 46, + 9, 27, 15, -13, -15, -18, 35, 6, 42, -33, + 20, -36, 1, -4, 38, 14, 18, -2, -27, -20, + }, { + 15, 13, 13, 1, -26, -14, -9, 41, 1, -16, + -46, 27, 18, 1, 4, -16, -11, 43, -8, 45, + 0, 11, 21, -29, -30, -8, 19, 42, 41, -28, + 0, -20, 20, 11, 30, 10, -4, -5, -32, -28, + }, { + 79, -2, -12, -22, -42, -28, -1, 51, 54, 15, + 8, -41, 0, -24, 6, -15, 1, 17, -36, -12, + -14, 47, 0, -6, -11, -26, 16, -27, 13, -43, + 22, -18, 10, 12, 2, -34, 15, -33, 13, -13, + }, { + 10, 18, 10, 15, -21, -41, -6, 56, 19, -13, + -9, -33, -9, -6, 20, 1, -11, 13, -24, -13, + -23, 32, 6, -22, -26, -15, 0, 8, 12, -37, + 1, -2, 28, 27, -5, -37, -7, -35, 8, -21, + }, { + 39, 4, 0, -35, -27, -53, -6, 44, 33, 18, + -5, -2, 11, -31, -9, -22, 6, 15, -36, 13, + 25, 46, 23, -20, -37, -24, 23, -19, 43, -29, + 38, -14, 0, -26, 12, -10, 38, -16, 0, 0, + }, { + -29, 25, 22, 2, -6, -67, -11, 49, -1, -10, + -24, 5, 3, -13, 4, -5, -6, 11, -25, 12, + 16, 31, 28, -36, -53, -13, 6, 16, 42, -24, + 17, 1, 18, -10, 4, -13, 15, -18, -5, -7, + }, { + 29, -25, -22, -2, 6, 67, 11, -49, 1, 10, + 24, -5, -3, 13, -4, 5, 6, -11, 25, -12, + -16, -31, -28, 36, 53, 13, -6, -16, -42, 24, + -17, -1, -18, 10, -4, 13, -15, 18, 5, 7, + }, { + -39, -4, 0, 35, 27, 53, 6, -44, -33, -18, + 5, 2, -11, 31, 9, 22, -6, -15, 36, -13, + -25, -46, -23, 20, 37, 24, -23, 19, -43, 29, + -38, 14, 0, 26, -12, 10, -38, 16, 0, 0, + }, { + -10, -18, -10, -15, 21, 41, 6, -56, -19, 13, + 9, 33, 9, 6, -20, -1, 11, -13, 24, 13, + 23, -32, -6, 22, 26, 15, 0, -8, -12, 37, + -1, 2, -28, -27, 5, 37, 7, 35, -8, 21, + }, { + -79, 2, 12, 22, 42, 28, 1, -51, -54, -15, + -8, 41, 0, 24, -6, 15, -1, -17, 36, 12, + 14, -47, 0, 6, 11, 26, -16, 27, -13, 43, + -22, 18, -10, -12, -2, 34, -15, 33, -13, 13, + }, { + -15, -13, -13, -1, 26, 14, 9, -41, -1, 16, + 46, -27, -18, -1, -4, 16, 11, -43, 8, -45, + 0, -11, -21, 29, 30, 8, -19, -42, -41, 28, + 0, 20, -20, -11, -30, -10, 4, 5, 32, 28, + }, { + -84, 6, 9, 36, 47, 1, 4, -36, -36, -12, + 27, -20, -26, 17, 9, 33, -1, -47, 19, -46, + -9, -27, -15, 13, 15, 18, -35, -6, -42, 33, + -20, 36, -1, 4, -38, -14, -18, 2, 27, 20, + }, { + -55, -6, -1, -14, 41, -10, 4, -48, -22, 20, + 31, 10, -5, -7, -20, 9, 16, -45, 8, -19, + 40, -12, 1, 15, 4, 10, -12, -34, -11, 41, + 16, 24, -30, -49, -20, 13, 28, 22, 18, 43, + }, { + -124, 13, 21, 23, 62, -23, 0, -43, -57, -8, + 13, 18, -14, 10, -6, 26, 3, -49, 19, -19, + 31, -27, 7, 0, -11, 20, -29, 1, -12, 47, + -4, 39, -11, -34, -28, 9, 5, 19, 13, 34, + }, { + 34, -14, -4, 17, -5, 24, 26, -20, 27, 45, + 12, -24, 2, -13, 21, 8, 22, 16, 32, 2, + -34, -31, -20, 7, 58, -5, 5, -2, -38, 12, + -2, 1, -1, 26, -5, 23, 21, 6, -8, -11, + }, { + -34, 6, 18, 55, 15, 11, 21, -16, -8, 16, + -6, -16, -5, 4, 35, 24, 10, 12, 43, 1, + -43, -47, -14, -8, 43, 5, -10, 34, -39, 18, + -22, 16, 17, 42, -13, 19, -1, 3, -14, -20, + }, { + -5, -7, 7, 4, 9, 0, 21, -28, 6, 48, + -2, 14, 15, -20, 5, 0, 27, 14, 32, 28, + 5, -32, 2, -6, 32, -3, 12, 5, -8, 25, + 14, 4, -12, -11, 4, 47, 45, 22, -22, 2, + }, { + -74, 12, 30, 42, 30, -14, 16, -23, -29, 19, + -20, 21, 7, -1, 19, 17, 14, 10, 43, 27, + -3, -48, 8, -22, 16, 7, -4, 42, -9, 31, + -6, 20, 6, 4, -3, 43, 22, 20, -28, -5, + }, { + -10, -3, 4, 18, 15, -27, 24, -13, 24, 51, + 34, -47, -12, -28, 21, 19, 27, -16, 15, -30, + -17, -12, -12, 0, 36, -10, -7, -27, -37, 16, + 15, 22, -3, 4, -31, -1, 42, -7, 18, 9, + }, { + -79, 17, 27, 56, 36, -41, 19, -8, -10, 22, + 15, -39, -20, -9, 35, 35, 15, -20, 26, -31, + -26, -27, -6, -15, 20, 0, -23, 8, -38, 22, + -5, 38, 15, 20, -39, -4, 18, -9, 13, 1, + }, { + -50, 3, 16, 5, 30, -53, 19, -20, 3, 55, + 19, -8, 0, -34, 5, 11, 32, -18, 15, -4, + 22, -13, 10, -13, 9, -8, 0, -19, -7, 29, + 31, 26, -13, -33, -21, 22, 65, 9, 4, 23, + }, { + -119, 24, 39, 44, 51, -66, 14, -15, -31, 26, + 1, 0, -7, -16, 19, 28, 19, -22, 26, -4, + 13, -28, 16, -29, -5, 1, -16, 16, -8, 35, + 10, 42, 4, -17, -29, 19, 42, 7, 0, 15, + }, { + 31, -28, 6, -16, -16, 50, -31, -14, 0, 6, + 36, 17, 0, 0, -29, -14, 11, 18, 20, -25, + -6, -33, -19, 20, 43, 21, 21, -14, -55, 0, + -32, -40, -42, 39, 1, -8, -14, 8, -6, -3, + }, { + -37, -8, 29, 22, 4, 37, -36, -9, -34, -22, + 17, 24, -8, 18, -15, 2, -1, 14, 31, -25, + -15, -48, -13, 4, 28, 31, 5, 21, -57, 4, + -53, -24, -23, 55, -6, -12, -37, 6, -11, -11, + }, { + -7, -22, 18, -29, -1, 25, -36, -21, -20, 9, + 22, 56, 11, -6, -45, -21, 15, 16, 20, 1, + 33, -34, 2, 6, 17, 23, 28, -6, -25, 12, + -16, -37, -53, 1, 11, 15, 8, 25, -20, 11, + }, { + -76, -1, 41, 9, 19, 12, -41, -17, -55, -18, + 3, 63, 3, 12, -30, -5, 3, 12, 31, 0, + 24, -49, 8, -9, 1, 33, 12, 29, -27, 18, + -37, -21, -34, 17, 3, 11, -14, 23, -25, 2, + }, { + -13, -17, 15, -15, 3, -1, -33, -7, -1, 12, + 58, -5, -15, -13, -29, -3, 16, -13, 4, -57, + 10, -13, -11, 13, 21, 15, 9, -40, -55, 3, + -14, -19, -44, 17, -24, -32, 5, -4, 21, 18, + }, { + -82, 3, 38, 23, 24, -15, -38, -2, -37, -15, + 39, 2, -23, 4, -15, 12, 3, -17, 15, -58, + 1, -29, -6, -2, 5, 26, -7, -4, -56, 9, + -35, -3, -25, 33, -32, -36, -17, -7, 15, 9, + }, { + -52, -10, 27, -27, 18, -26, -38, -14, -23, 16, + 44, 33, -3, -20, -45, -10, 20, -15, 3, -31, + 50, -14, 10, 0, -5, 17, 15, -32, -24, 16, + 1, -15, -55, -20, -14, -8, 29, 12, 7, 32, + }, { + -121, 9, 50, 10, 40, -40, -43, -9, -58, -12, + 25, 41, -11, -2, -31, 5, 8, -19, 15, -32, + 41, -30, 16, -16, -20, 28, 0, 3, -26, 22, + -19, 0, -36, -4, -22, -12, 6, 9, 1, 24, + }, { + 36, -18, 24, 3, -28, 7, -16, 13, 26, 41, + 24, -1, 5, -26, -3, -12, 27, 46, 27, -10, + -24, -34, -10, -8, 49, 2, 34, 0, -51, -12, + -17, -38, -25, 56, 0, 0, 22, -3, -20, -22, + }, { + -32, 2, 47, 42, -7, -5, -21, 18, -9, 12, + 5, 5, -2, -8, 10, 4, 14, 42, 38, -10, + -33, -49, -5, -24, 33, 12, 17, 35, -52, -6, + -38, -22, -7, 72, -7, -3, 0, -6, -25, -30, + }, { + -2, -11, 36, -9, -13, -17, -21, 6, 5, 45, + 10, 36, 18, -33, -19, -19, 31, 44, 27, 15, + 16, -34, 11, -22, 22, 4, 40, 7, -21, 0, + -1, -35, -36, 18, 10, 24, 46, 12, -34, -8, + }, { + -71, 9, 59, 29, 8, -30, -26, 11, -30, 16, + -8, 44, 9, -14, -5, -2, 19, 40, 38, 15, + 7, -50, 17, -38, 7, 14, 24, 43, -22, 6, + -22, -19, -17, 34, 2, 20, 23, 10, -39, -16, + }, { + -8, -6, 33, 4, -7, -44, -18, 21, 23, 48, + 46, -24, -9, -40, -3, -1, 32, 13, 11, -43, + -7, -14, -3, -15, 26, -3, 21, -26, -50, -8, + 0, -16, -27, 34, -25, -23, 43, -17, 6, -1, + }, { + -77, 13, 56, 43, 13, -57, -23, 26, -11, 19, + 27, -16, -17, -22, 10, 15, 19, 10, 22, -43, + -16, -30, 2, -31, 11, 6, 5, 9, -52, -2, + -20, 0, -8, 50, -33, -27, 19, -19, 1, -9, + }, { + -47, 0, 45, -7, 7, -69, -23, 13, 2, 51, + 32, 14, 3, -47, -19, -8, 37, 11, 10, -16, + 32, -15, 19, -29, 0, -1, 28, -18, -20, 4, + 16, -13, -38, -3, -15, 0, 66, 0, -7, 13, + }, { + -116, 20, 68, 30, 28, -83, -28, 18, -32, 22, + 13, 21, -5, -28, -5, 7, 24, 8, 22, -17, + 23, -30, 25, -45, -15, 9, 11, 18, -22, 10, + -4, 2, -19, 12, -23, -3, 43, -2, -12, 4, + }, { + 72, -13, -29, -18, 4, 90, 37, -34, 4, -1, + 13, -9, -6, 11, 2, 24, -13, 3, -7, -11, + -4, 4, -42, 25, 31, -1, -8, -29, -6, 17, + -19, 2, -10, -6, 38, 22, -42, -19, -6, -11, + }, { + 3, 7, -6, 20, 25, 77, 32, -29, -31, -30, + -4, -2, -14, 29, 16, 40, -26, 0, 3, -12, + -13, -10, -36, 9, 15, 8, -24, 6, -7, 22, + -40, 17, 8, 9, 31, 18, -66, -22, -11, -19, + }, { + 32, -6, -17, -31, 19, 65, 33, -41, -16, 1, + 0, 29, 6, 4, -13, 17, -9, 1, -8, 14, + 35, 3, -19, 11, 4, 0, -1, -21, 23, 30, + -3, 5, -20, -44, 48, 46, -19, -3, -20, 3, + }, { + -36, 13, 5, 7, 40, 51, 28, -36, -52, -27, + -18, 36, -2, 22, 0, 33, -21, -2, 3, 13, + 26, -11, -14, -4, -10, 10, -18, 14, 22, 36, + -24, 21, -1, -28, 40, 42, -42, -5, -25, -5, + }, { + 27, -1, -20, -17, 24, 38, 35, -26, 1, 4, + 35, -32, -21, -3, 2, 35, -8, -29, -24, -44, + 12, 24, -34, 18, 8, -7, -21, -55, -5, 21, + -2, 23, -11, -28, 13, -1, -22, -33, 21, 10, + }, { + -41, 18, 2, 21, 45, 24, 30, -21, -33, -24, + 17, -24, -29, 15, 16, 51, -21, -33, -13, -45, + 3, 8, -28, 2, -7, 2, -37, -19, -7, 27, + -22, 39, 7, -12, 5, -5, -45, -35, 15, 1, + }, { + -12, 4, -8, -29, 39, 12, 30, -33, -19, 8, + 21, 6, -8, -9, -13, 28, -4, -31, -24, -18, + 52, 23, -12, 4, -18, -5, -14, -47, 24, 34, + 14, 27, -22, -66, 22, 22, 1, -16, 6, 24, + }, { + -81, 25, 14, 8, 61, 0, 25, -28, -54, -20, + 3, 14, -17, 8, 0, 44, -16, -35, -13, -18, + 43, 7, -6, -11, -33, 4, -30, -11, 22, 40, + -6, 43, -3, -50, 14, 18, -22, -18, 1, 16, + }, { + 77, -2, -11, 1, -7, 47, 52, -5, 29, 33, + 1, -28, 0, -15, 28, 26, 2, 30, 0, 2, + -22, 4, -33, -3, 36, -21, 3, -15, -2, 5, + -4, 4, 6, 9, 37, 31, -5, -32, -20, -30, + }, { + 8, 17, 10, 40, 13, 34, 47, 0, -5, 4, + -16, -21, -8, 2, 42, 43, -10, 26, 10, 2, + -31, -11, -27, -19, 21, -10, -12, 20, -3, 11, + -25, 20, 25, 25, 29, 28, -28, -34, -25, -38, + }, { + 37, 3, 0, -10, 7, 22, 48, -12, 8, 36, + -12, 9, 12, -22, 12, 19, 6, 28, 0, 29, + 18, 3, -11, -17, 10, -18, 10, -7, 27, 18, + 11, 7, -3, -28, 47, 55, 18, -15, -34, -16, + }, { + -31, 24, 23, 27, 29, 9, 43, -8, -26, 7, + -30, 17, 4, -3, 26, 35, -5, 24, 10, 28, + 9, -12, -5, -33, -5, -8, -5, 29, 26, 24, + -9, 23, 14, -12, 39, 52, -5, -18, -39, -24, + }, { + 32, 8, -3, 2, 13, -4, 50, 1, 27, 39, + 23, -51, -15, -30, 27, 37, 7, -1, -17, -29, + -5, 23, -25, -10, 14, -26, -8, -41, -1, 9, + 13, 26, 5, -12, 12, 7, 14, -45, 6, -9, + }, { + -36, 29, 19, 41, 34, -18, 45, 6, -8, 10, + 5, -43, -23, -11, 42, 53, -5, -5, -6, -30, + -14, 8, -20, -26, -1, -16, -25, -4, -3, 15, + -7, 41, 23, 3, 4, 3, -8, -48, 1, -17, + }, { + -7, 15, 9, -9, 28, -29, 45, -5, 6, 43, + 9, -12, -2, -36, 12, 30, 11, -3, -17, -3, + 34, 22, -3, -24, -12, -24, -2, -32, 28, 22, + 29, 29, -5, -50, 21, 31, 38, -29, -7, 5, + }, { + -76, 35, 31, 28, 49, -43, 40, 0, -29, 14, + -8, -5, -10, -18, 26, 46, 0, -7, -6, -3, + 25, 7, 2, -40, -28, -14, -18, 3, 27, 28, + 8, 45, 13, -34, 13, 27, 15, -31, -12, -3, + }, { + 74, -17, 0, -31, -18, 73, -5, 0, 3, -5, + 25, 12, -3, -1, -22, 3, -9, 33, -12, -24, + 6, 2, -33, 9, 21, 5, 20, -27, -19, -7, + -34, -37, -34, 22, 44, 0, -41, -29, -17, -21, + }, { + 5, 3, 21, 7, 2, 60, -10, 5, -32, -34, + 7, 20, -11, 16, -8, 20, -21, 29, -1, -24, + -2, -13, -27, -6, 5, 15, 3, 8, -21, -1, + -55, -21, -15, 38, 37, -3, -65, -32, -23, -30, + }, { + 35, -10, 11, -44, -3, 48, -10, -6, -17, -2, + 11, 51, 8, -8, -38, -3, -4, 31, -12, 2, + 46, 1, -10, -4, -5, 7, 26, -19, 10, 5, + -18, -34, -45, -15, 54, 24, -18, -13, -31, -7, + }, { + -33, 10, 34, -5, 17, 35, -15, -1, -53, -30, + -6, 59, 0, 10, -24, 13, -17, 27, -1, 1, + 37, -13, -4, -20, -20, 18, 10, 16, 8, 11, + -39, -18, -26, 0, 46, 20, -41, -15, -37, -15, + }, { + 29, -5, 7, -30, 1, 21, -7, 7, 0, 0, + 47, -9, -18, -15, -22, 14, -4, 0, -28, -57, + 23, 21, -25, 2, -1, 0, 7, -53, -19, -3, + -17, -15, -36, 0, 19, -24, -21, -43, 9, 0, + }, { + -39, 14, 30, 8, 22, 8, -12, 12, -34, -27, + 29, -2, -26, 2, -8, 31, -16, -3, -17, -57, + 14, 6, -19, -13, -16, 10, -8, -17, -20, 2, + -38, 0, -17, 16, 11, -27, -44, -45, 4, -8, + }, { + -9, 1, 20, -43, 17, -3, -12, 0, -20, 4, + 33, 29, -6, -22, -38, 7, 0, -1, -29, -30, + 63, 21, -3, -11, -27, 1, 14, -45, 10, 9, + -1, -12, -47, -37, 28, 0, 2, -26, -4, 13, + }, { + -78, 21, 43, -4, 38, -17, -17, 5, -55, -24, + 15, 36, -14, -4, -24, 24, -12, -5, -17, -31, + 54, 5, 2, -27, -43, 12, -2, -9, 9, 15, + -22, 3, -28, -21, 20, -3, -20, -28, -9, 5, + }, { + 80, -6, 16, -11, -30, 30, 9, 28, 28, 29, + 13, -6, 2, -28, 3, 5, 7, 60, -5, -9, + -11, 1, -24, -19, 27, -13, 32, -13, -15, -19, + -19, -35, -17, 39, 43, 9, -4, -42, -32, -41, + }, { + 11, 14, 39, 27, -9, 17, 4, 33, -6, 0, + -4, 1, -5, -10, 17, 22, -5, 57, 5, -9, + -20, -13, -18, -35, 11, -3, 16, 22, -17, -13, + -40, -19, 1, 55, 35, 5, -27, -44, -37, -49, + }, { + 40, 0, 28, -24, -14, 5, 4, 21, 7, 33, + 0, 32, 15, -35, -12, -1, 11, 58, -5, 16, + 28, 0, -1, -33, 0, -11, 39, -5, 14, -6, + -3, -31, -28, 1, 53, 33, 19, -25, -46, -26, + }, { + -28, 20, 51, 14, 6, -7, 0, 26, -27, 4, + -18, 40, 6, -16, 1, 15, 0, 55, 5, 16, + 19, -14, 3, -49, -14, -1, 22, 30, 12, 0, + -24, -15, -9, 17, 45, 29, -4, -28, -51, -35, + }, { + 34, 4, 25, -10, -9, -21, 7, 36, 26, 36, + 35, -28, -12, -42, 3, 16, 12, 28, -21, -42, + 5, 21, -16, -26, 4, -19, 19, -39, -15, -15, + -1, -13, -19, 17, 17, -14, 15, -55, -4, -19, + }, { + -34, 25, 48, 28, 11, -34, 2, 41, -9, 7, + 17, -21, -20, -24, 17, 33, 0, 24, -10, -42, + -3, 5, -10, -42, -11, -8, 3, -3, -16, -9, + -22, 2, 0, 33, 10, -18, -7, -58, -10, -28, + }, { + -4, 11, 37, -23, 5, -46, 2, 29, 5, 39, + 21, 9, 0, -49, -12, 9, 16, 26, -22, -15, + 45, 20, 5, -40, -22, -17, 26, -31, 14, -2, + 14, -10, -30, -20, 27, 9, 39, -39, -18, -5, + }, { + -73, 32, 60, 15, 26, -59, -2, 33, -30, 10, + 3, 17, -8, -30, 1, 26, 4, 22, -10, -16, + 36, 5, 11, -56, -37, -6, 10, 5, 13, 3, + -6, 5, -11, -4, 19, 5, 16, -41, -24, -13 + } +}; + +const uint16_t ff_cb1_base[128]={ + 19657, 18474, 18365, 17520, 21048, 18231, 18584, 16671, + 20363, 19069, 19409, 18430, 21844, 18753, 19613, 17411, + 20389, 21772, 20129, 21702, 20978, 20472, 19627, 19387, + 21477, 23134, 21841, 23919, 22089, 21519, 21134, 20852, + 19675, 17821, 19044, 17477, 19986, 16955, 18446, 16086, + 21138, 18899, 20952, 18929, 21452, 17833, 20104, 17159, + 19770, 20056, 20336, 20866, 19329, 18217, 18908, 18004, + 21556, 21948, 23079, 23889, 20922, 19544, 20984, 19781, + 19781, 20984, 19544, 20922, 23889, 23079, 21948, 21556, + 18004, 18908, 18217, 19329, 20866, 20336, 20056, 19770, + 17159, 20104, 17833, 21452, 18929, 20952, 18899, 21138, + 16086, 18446, 16955, 19986, 17477, 19044, 17821, 19675, + 20852, 21134, 21519, 22089, 23919, 21841, 23134, 21477, + 19387, 19627, 20472, 20978, 21702, 20129, 21772, 20389, + 17411, 19613, 18753, 21844, 18430, 19409, 19069, 20363, + 16671, 18584, 18231, 21048, 17520, 18365, 18474, 19657, +}; + +const uint16_t ff_cb2_base[128]={ + 12174, 13380, 13879, 13832, 13170, 13227, 13204, 12053, + 12410, 13988, 14348, 14631, 13100, 13415, 13224, 12268, + 11982, 13825, 13499, 14210, 13877, 14788, 13811, 13109, + 11449, 13275, 12833, 13717, 12728, 13696, 12759, 12405, + 10230, 12185, 11628, 13161, 11762, 13458, 12312, 12818, + 10443, 12773, 12011, 14020, 11818, 13825, 12453, 13226, + 10446, 13162, 11881, 14300, 12859, 16288, 13490, 15053, + 10155, 12820, 11519, 13973, 12041, 15081, 12635, 14198, + 14198, 12635, 15081, 12041, 13973, 11519, 12820, 10155, + 15053, 13490, 16288, 12859, 14300, 11881, 13162, 10446, + 13226, 12453, 13825, 11818, 14020, 12011, 12773, 10443, + 12818, 12312, 13458, 11762, 13161, 11628, 12185, 10230, + 12405, 12759, 13696, 12728, 13717, 12833, 13275, 11449, + 13109, 13811, 14788, 13877, 14210, 13499, 13825, 11982, + 12268, 13224, 13415, 13100, 14631, 14348, 13988, 12410, + 12053, 13204, 13227, 13170, 13832, 13879, 13380, 12174, +}; + +const int16_t ff_energy_tab[32]={ + 0, 16, 20, 25, 32, 41, 51, 65, + 81, 103, 129, 163, 205, 259, 326, 410, + 516, 650, 819, 1031, 1298, 1634, 2057, 2590, + 3261, 4105, 5168, 6507, 8192, 10313, 12983, 16345 +}; + +static const int16_t lpc_refl_cb1[64]={ + -4041, -4018, -3998, -3977, -3954, -3930, -3906, -3879, + -3852, -3825, -3795, -3764, -3731, -3699, -3666, -3631, + -3594, -3555, -3513, -3468, -3420, -3372, -3321, -3268, + -3212, -3153, -3090, -3021, -2944, -2863, -2772, -2676, + -2565, -2445, -2328, -2202, -2072, -1941, -1808, -1660, + -1508, -1348, -1185, -994, -798, -600, -374, -110, + 152, 447, 720, 982, 1229, 1456, 1682, 1916, + 2130, 2353, 2595, 2853, 3118, 3363, 3588, 3814 +}; + +static const int16_t lpc_refl_cb2[32]={ + -3091, -2386, -1871, -1425, -1021, -649, -316, -20, + 267, 544, 810, 1065, 1305, 1534, 1756, 1970, + 2171, 2359, 2536, 2700, 2854, 2996, 3133, 3263, + 3386, 3499, 3603, 3701, 3789, 3870, 3947, 4020 +}; + +static const int16_t lpc_refl_cb3[32]={ + -3525, -3295, -3081, -2890, -2696, -2511, -2328, -2149, + -1979, -1817, -1658, -1498, -1341, -1188, -1032, -876, + -721, -561, -394, -228, -54, 119, 296, 484, + 683, 895, 1123, 1373, 1651, 1965, 2360, 2854 +}; + +static const int16_t lpc_refl_cb4[16]={ + -1845, -1057, -522, -77, 301, 647, 975, 1285, + 1582, 1873, 2163, 2452, 2735, 3017, 3299, 3569 +}; + +static const int16_t lpc_refl_cb5[16]={ + -2691, -2187, -1788, -1435, -1118, -837, -571, -316, + -59, 201, 470, 759, 1077, 1457, 1908, 2495 +}; + +static const int16_t lpc_refl_cb6[8]={ + -1372, -474, 133, 632, 1100, 1571, 2075, 2672 +}; + +static const int16_t lpc_refl_cb7[8]={ + -2389, -1787, -1231, -717, -239, 234, 770, 1474 +}; + +static const int16_t lpc_refl_cb8[8]={ + -1569, -864, -296, 200, 670, 1151, 1709, 2385 +}; + +static const int16_t lpc_refl_cb9[8]={ + -2200, -1608, -1062, -569, -120, 338, 863, 1621 +}; + +static const int16_t lpc_refl_cb10[4]={ + -617, 190, 802, 1483 +}; + +const int16_t * const ff_lpc_refl_cb[10]={ + lpc_refl_cb1, lpc_refl_cb2, lpc_refl_cb3, lpc_refl_cb4, lpc_refl_cb5, + lpc_refl_cb6, lpc_refl_cb7, lpc_refl_cb8, lpc_refl_cb9, lpc_refl_cb10 +}; + +static void ff_add_wav(int16_t *dest, int n, int skip_first, int *m, const int16_t *s1, + const int8_t *s2, const int8_t *s3) +{ + int i; + int v[3]; + + v[0] = 0; + for (i=!skip_first; i<3; i++) + v[i] = (ff_gain_val_tab[n][i] * m[i]) >> ff_gain_exp_tab[n]; + + if (v[0]) { + for (i=0; i < BLOCKSIZE; i++) + dest[i] = (s1[i]*v[0] + s2[i]*v[1] + s3[i]*v[2]) >> 12; + } else { + for (i=0; i < BLOCKSIZE; i++) + dest[i] = ( s2[i]*v[1] + s3[i]*v[2]) >> 12; + } +} + +/** + * Copy the last offset values of *source to *target. If those values are not + * enough to fill the target buffer, fill it with another copy of those values. + */ +void ff_copy_and_dup(int16_t *target, const int16_t *source, int offset) +{ + source += BUFFERSIZE - offset; + + memcpy(target, source, FFMIN(BLOCKSIZE, offset)*sizeof(*target)); + if (offset < BLOCKSIZE) + memcpy(target + offset, source, (BLOCKSIZE - offset)*sizeof(*target)); +} + +/** + * Evaluate the reflection coefficients from the filter coefficients. + * + * @return 1 if one of the reflection coefficients is greater than + * 4095, 0 if not. + */ +int ff_eval_refl(int *refl, const int16_t *coefs, AVCodecContext *avctx) +{ + int b, i, j; + int buffer1[LPC_ORDER]; + int buffer2[LPC_ORDER]; + int *bp1 = buffer1; + int *bp2 = buffer2; + + for (i=0; i < LPC_ORDER; i++) + buffer2[i] = coefs[i]; + + refl[LPC_ORDER-1] = bp2[LPC_ORDER-1]; + + if ((unsigned) bp2[LPC_ORDER-1] + 0x1000 > 0x1fff) { + av_log(avctx, AV_LOG_ERROR, "Overflow. Broken sample?\n"); + return 1; + } + + for (i = LPC_ORDER-2; i >= 0; i--) { + b = 0x1000-((bp2[i+1] * bp2[i+1]) >> 12); + + if (!b) + b = -2; + + b = 0x1000000 / b; + for (j=0; j <= i; j++) { +#if CONFIG_FTRAPV + int a = bp2[j] - ((refl[i+1] * bp2[i-j]) >> 12); + if((int)(a*(unsigned)b) != a*(int64_t)b) + return 1; +#endif + bp1[j] = ((bp2[j] - ((refl[i+1] * bp2[i-j]) >> 12)) * b) >> 12; + } + + if ((unsigned) bp1[i] + 0x1000 > 0x1fff) + return 1; + + refl[i] = bp1[i]; + + FFSWAP(int *, bp1, bp2); + } + return 0; +} + +/** + * Evaluate the LPC filter coefficients from the reflection coefficients. + * Does the inverse of the ff_eval_refl() function. + */ +void ff_eval_coefs(int *coefs, const int *refl) +{ + int buffer[LPC_ORDER]; + int *b1 = buffer; + int *b2 = coefs; + int i, j; + + for (i=0; i < LPC_ORDER; i++) { + b1[i] = refl[i] << 4; + + for (j=0; j < i; j++) + b1[j] = ((refl[i] * b2[i-j-1]) >> 12) + b2[j]; + + FFSWAP(int *, b1, b2); + } + + for (i=0; i < LPC_ORDER; i++) + coefs[i] >>= 4; +} + +void ff_int_to_int16(int16_t *out, const int *inp) +{ + int i; + + for (i = 0; i < LPC_ORDER; i++) + *out++ = *inp++; +} + +/** + * Evaluate sqrt(x << 24). x must fit in 20 bits. This value is evaluated in an + * odd way to make the output identical to the binary decoder. + */ +int ff_t_sqrt(unsigned int x) +{ + int s = 2; + while (x > 0xfff) { + s++; + x >>= 2; + } + + return ff_sqrt(x << 20) << s; +} + +unsigned int ff_rms(const int *data) +{ + int i; + unsigned int res = 0x10000; + int b = LPC_ORDER; + + for (i = 0; i < LPC_ORDER; i++) { + res = (((0x1000000 - data[i]*data[i]) >> 12) * res) >> 12; + + if (res == 0) + return 0; + + while (res <= 0x3fff) { + b++; + res <<= 2; + } + } + + return ff_t_sqrt(res) >> b; +} + +int ff_interp(RA144Context *ractx, int16_t *out, int a, int copyold, int energy) +{ + int work[LPC_ORDER]; + int b = NBLOCKS - a; + int i; + + // Interpolate block coefficients from the this frame's forth block and + // last frame's forth block. + for (i = 0; i < LPC_ORDER; i++) + out[i] = (a * ractx->lpc_coef[0][i] + b * ractx->lpc_coef[1][i])>> 2; + + if (ff_eval_refl(work, out, ractx->avctx)) { + // The interpolated coefficients are unstable, copy either new or old + // coefficients. + ff_int_to_int16(out, ractx->lpc_coef[copyold]); + return ff_rescale_rms(ractx->lpc_refl_rms[copyold], energy); + } else { + return ff_rescale_rms(ff_rms(work), energy); + } +} + +unsigned int ff_rescale_rms(unsigned int rms, unsigned int energy) +{ + return (rms * energy) >> 10; +} + +/** inverse root mean square */ +int ff_irms(const int16_t *data) +{ + unsigned int i, sum = 0; + + for (i=0; i < BLOCKSIZE; i++) + sum += data[i] * data[i]; + + if (sum == 0) + return 0; /* OOPS - division by zero */ + + return 0x20000000 / (ff_t_sqrt(sum) >> 8); +} + +void ff_subblock_synthesis(RA144Context *ractx, const uint16_t *lpc_coefs, + int cba_idx, int cb1_idx, int cb2_idx, + int gval, int gain) +{ + uint16_t buffer_a[BLOCKSIZE]; + uint16_t *block; + int m[3]; + + if (cba_idx) { + cba_idx += BLOCKSIZE/2 - 1; + ff_copy_and_dup(buffer_a, ractx->adapt_cb, cba_idx); + m[0] = (ff_irms(buffer_a) * gval) >> 12; + } else { + m[0] = 0; + } + m[1] = (ff_cb1_base[cb1_idx] * gval) >> 8; + m[2] = (ff_cb2_base[cb2_idx] * gval) >> 8; + memmove(ractx->adapt_cb, ractx->adapt_cb + BLOCKSIZE, + (BUFFERSIZE - BLOCKSIZE) * sizeof(*ractx->adapt_cb)); + + block = ractx->adapt_cb + BUFFERSIZE - BLOCKSIZE; + + ff_add_wav(block, gain, cba_idx, m, cba_idx? buffer_a: NULL, + ff_cb1_vects[cb1_idx], ff_cb2_vects[cb2_idx]); + + memcpy(ractx->curr_sblock, ractx->curr_sblock + BLOCKSIZE, + LPC_ORDER*sizeof(*ractx->curr_sblock)); + + if (ff_celp_lp_synthesis_filter(ractx->curr_sblock + LPC_ORDER, lpc_coefs, + block, BLOCKSIZE, LPC_ORDER, 1, 0, 0xfff)) + memset(ractx->curr_sblock, 0, (LPC_ORDER+BLOCKSIZE)*sizeof(*ractx->curr_sblock)); +} diff --git a/ffmpeg/libavcodec/ra144.h b/ffmpeg/libavcodec/ra144.h new file mode 100644 index 0000000..eb89398 --- /dev/null +++ b/ffmpeg/libavcodec/ra144.h @@ -0,0 +1,85 @@ +/* + * Real Audio 1.0 (14.4K) + * Copyright (c) 2003 the ffmpeg project + * + * 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 + */ + +#ifndef AVCODEC_RA144_H +#define AVCODEC_RA144_H + +#include +#include "lpc.h" +#include "audio_frame_queue.h" + +#define NBLOCKS 4 ///< number of subblocks within a block +#define BLOCKSIZE 40 ///< subblock size in 16-bit words +#define BUFFERSIZE 146 ///< the size of the adaptive codebook +#define FIXED_CB_SIZE 128 ///< size of fixed codebooks +#define FRAMESIZE 20 ///< size of encoded frame +#define LPC_ORDER 10 ///< order of LPC filter + +typedef struct RA144Context { + AVCodecContext *avctx; + LPCContext lpc_ctx; + AudioFrameQueue afq; + int last_frame; + + unsigned int old_energy; ///< previous frame energy + + unsigned int lpc_tables[2][10]; + + /** LPC coefficients: lpc_coef[0] is the coefficients of the current frame + * and lpc_coef[1] of the previous one. */ + unsigned int *lpc_coef[2]; + + unsigned int lpc_refl_rms[2]; + + int16_t curr_block[NBLOCKS * BLOCKSIZE]; + + /** The current subblock padded by the last 10 values of the previous one. */ + int16_t curr_sblock[50]; + + /** Adaptive codebook, its size is two units bigger to avoid a + * buffer overflow. */ + uint16_t adapt_cb[146+2]; +} RA144Context; + +void ff_copy_and_dup(int16_t *target, const int16_t *source, int offset); +int ff_eval_refl(int *refl, const int16_t *coefs, AVCodecContext *avctx); +void ff_eval_coefs(int *coefs, const int *refl); +void ff_int_to_int16(int16_t *out, const int *inp); +int ff_t_sqrt(unsigned int x); +unsigned int ff_rms(const int *data); +int ff_interp(RA144Context *ractx, int16_t *out, int a, int copyold, + int energy); +unsigned int ff_rescale_rms(unsigned int rms, unsigned int energy); +int ff_irms(const int16_t *data); +void ff_subblock_synthesis(RA144Context *ractx, const uint16_t *lpc_coefs, + int cba_idx, int cb1_idx, int cb2_idx, + int gval, int gain); + +extern const int16_t ff_gain_val_tab[256][3]; +extern const uint8_t ff_gain_exp_tab[256]; +extern const int8_t ff_cb1_vects[128][40]; +extern const int8_t ff_cb2_vects[128][40]; +extern const uint16_t ff_cb1_base[128]; +extern const uint16_t ff_cb2_base[128]; +extern const int16_t ff_energy_tab[32]; +extern const int16_t * const ff_lpc_refl_cb[10]; + +#endif /* AVCODEC_RA144_H */ diff --git a/ffmpeg/libavcodec/ra144dec.c b/ffmpeg/libavcodec/ra144dec.c new file mode 100644 index 0000000..5531fd2 --- /dev/null +++ b/ffmpeg/libavcodec/ra144dec.c @@ -0,0 +1,137 @@ +/* + * Real Audio 1.0 (14.4K) + * + * Copyright (c) 2008 Vitor Sessak + * Copyright (c) 2003 Nick Kurshev + * Based on public domain decoder at http://www.honeypot.net/audio + * + * 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 "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "ra144.h" + + +static av_cold int ra144_decode_init(AVCodecContext * avctx) +{ + RA144Context *ractx = avctx->priv_data; + + ractx->avctx = avctx; + + ractx->lpc_coef[0] = ractx->lpc_tables[0]; + ractx->lpc_coef[1] = ractx->lpc_tables[1]; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static void do_output_subblock(RA144Context *ractx, const uint16_t *lpc_coefs, + int gval, GetBitContext *gb) +{ + int cba_idx = get_bits(gb, 7); // index of the adaptive CB, 0 if none + int gain = get_bits(gb, 8); + int cb1_idx = get_bits(gb, 7); + int cb2_idx = get_bits(gb, 7); + + ff_subblock_synthesis(ractx, lpc_coefs, cba_idx, cb1_idx, cb2_idx, gval, + gain); +} + +/** Uncompress one block (20 bytes -> 160*2 bytes). */ +static int ra144_decode_frame(AVCodecContext * avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + static const uint8_t sizes[LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2}; + unsigned int refl_rms[NBLOCKS]; // RMS of the reflection coefficients + uint16_t block_coefs[NBLOCKS][LPC_ORDER]; // LPC coefficients of each sub-block + unsigned int lpc_refl[LPC_ORDER]; // LPC reflection coefficients of the frame + int i, j; + int ret; + int16_t *samples; + unsigned int energy; + + RA144Context *ractx = avctx->priv_data; + GetBitContext gb; + + if (buf_size < FRAMESIZE) { + av_log(avctx, AV_LOG_ERROR, + "Frame too small (%d bytes). Truncated file?\n", buf_size); + *got_frame_ptr = 0; + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = NBLOCKS * BLOCKSIZE; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + + init_get_bits(&gb, buf, FRAMESIZE * 8); + + for (i = 0; i < LPC_ORDER; i++) + lpc_refl[i] = ff_lpc_refl_cb[i][get_bits(&gb, sizes[i])]; + + ff_eval_coefs(ractx->lpc_coef[0], lpc_refl); + ractx->lpc_refl_rms[0] = ff_rms(lpc_refl); + + energy = ff_energy_tab[get_bits(&gb, 5)]; + + refl_rms[0] = ff_interp(ractx, block_coefs[0], 1, 1, ractx->old_energy); + refl_rms[1] = ff_interp(ractx, block_coefs[1], 2, + energy <= ractx->old_energy, + ff_t_sqrt(energy*ractx->old_energy) >> 12); + refl_rms[2] = ff_interp(ractx, block_coefs[2], 3, 0, energy); + refl_rms[3] = ff_rescale_rms(ractx->lpc_refl_rms[0], energy); + + ff_int_to_int16(block_coefs[3], ractx->lpc_coef[0]); + + for (i=0; i < NBLOCKS; i++) { + do_output_subblock(ractx, block_coefs[i], refl_rms[i], &gb); + + for (j=0; j < BLOCKSIZE; j++) + *samples++ = av_clip_int16(ractx->curr_sblock[j + 10] << 2); + } + + ractx->old_energy = energy; + ractx->lpc_refl_rms[1] = ractx->lpc_refl_rms[0]; + + FFSWAP(unsigned int *, ractx->lpc_coef[0], ractx->lpc_coef[1]); + + *got_frame_ptr = 1; + + return FRAMESIZE; +} + +AVCodec ff_ra_144_decoder = { + .name = "real_144", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_RA_144, + .priv_data_size = sizeof(RA144Context), + .init = ra144_decode_init, + .decode = ra144_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), +}; diff --git a/ffmpeg/libavcodec/ra144enc.c b/ffmpeg/libavcodec/ra144enc.c new file mode 100644 index 0000000..2eac343 --- /dev/null +++ b/ffmpeg/libavcodec/ra144enc.c @@ -0,0 +1,558 @@ +/* + * Real Audio 1.0 (14.4K) encoder + * Copyright (c) 2010 Francesco Lavra + * + * 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 + */ + +/** + * @file + * Real Audio 1.0 (14.4K) encoder + * @author Francesco Lavra + */ + +#include + +#include "avcodec.h" +#include "audio_frame_queue.h" +#include "internal.h" +#include "put_bits.h" +#include "celp_filters.h" +#include "ra144.h" + + +static av_cold int ra144_encode_close(AVCodecContext *avctx) +{ + RA144Context *ractx = avctx->priv_data; + ff_lpc_end(&ractx->lpc_ctx); + ff_af_queue_close(&ractx->afq); + return 0; +} + + +static av_cold int ra144_encode_init(AVCodecContext * avctx) +{ + RA144Context *ractx; + int ret; + + if (avctx->channels != 1) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", + avctx->channels); + return -1; + } + avctx->frame_size = NBLOCKS * BLOCKSIZE; + avctx->delay = avctx->frame_size; + avctx->bit_rate = 8000; + ractx = avctx->priv_data; + ractx->lpc_coef[0] = ractx->lpc_tables[0]; + ractx->lpc_coef[1] = ractx->lpc_tables[1]; + ractx->avctx = avctx; + ret = ff_lpc_init(&ractx->lpc_ctx, avctx->frame_size, LPC_ORDER, + FF_LPC_TYPE_LEVINSON); + if (ret < 0) + goto error; + + ff_af_queue_init(avctx, &ractx->afq); + + return 0; +error: + ra144_encode_close(avctx); + return ret; +} + + +/** + * Quantize a value by searching a sorted table for the element with the + * nearest value + * + * @param value value to quantize + * @param table array containing the quantization table + * @param size size of the quantization table + * @return index of the quantization table corresponding to the element with the + * nearest value + */ +static int quantize(int value, const int16_t *table, unsigned int size) +{ + unsigned int low = 0, high = size - 1; + + while (1) { + int index = (low + high) >> 1; + int error = table[index] - value; + + if (index == low) + return table[high] + error > value ? low : high; + if (error > 0) { + high = index; + } else { + low = index; + } + } +} + + +/** + * Orthogonalize a vector to another vector + * + * @param v vector to orthogonalize + * @param u vector against which orthogonalization is performed + */ +static void orthogonalize(float *v, const float *u) +{ + int i; + float num = 0, den = 0; + + for (i = 0; i < BLOCKSIZE; i++) { + num += v[i] * u[i]; + den += u[i] * u[i]; + } + num /= den; + for (i = 0; i < BLOCKSIZE; i++) + v[i] -= num * u[i]; +} + + +/** + * Calculate match score and gain of an LPC-filtered vector with respect to + * input data, possibly othogonalizing it to up to 2 other vectors + * + * @param work array used to calculate the filtered vector + * @param coefs coefficients of the LPC filter + * @param vect original vector + * @param ortho1 first vector against which orthogonalization is performed + * @param ortho2 second vector against which orthogonalization is performed + * @param data input data + * @param score pointer to variable where match score is returned + * @param gain pointer to variable where gain is returned + */ +static void get_match_score(float *work, const float *coefs, float *vect, + const float *ortho1, const float *ortho2, + const float *data, float *score, float *gain) +{ + float c, g; + int i; + + ff_celp_lp_synthesis_filterf(work, coefs, vect, BLOCKSIZE, LPC_ORDER); + if (ortho1) + orthogonalize(work, ortho1); + if (ortho2) + orthogonalize(work, ortho2); + c = g = 0; + for (i = 0; i < BLOCKSIZE; i++) { + g += work[i] * work[i]; + c += data[i] * work[i]; + } + if (c <= 0) { + *score = 0; + return; + } + *gain = c / g; + *score = *gain * c; +} + + +/** + * Create a vector from the adaptive codebook at a given lag value + * + * @param vect array where vector is stored + * @param cb adaptive codebook + * @param lag lag value + */ +static void create_adapt_vect(float *vect, const int16_t *cb, int lag) +{ + int i; + + cb += BUFFERSIZE - lag; + for (i = 0; i < FFMIN(BLOCKSIZE, lag); i++) + vect[i] = cb[i]; + if (lag < BLOCKSIZE) + for (i = 0; i < BLOCKSIZE - lag; i++) + vect[lag + i] = cb[i]; +} + + +/** + * Search the adaptive codebook for the best entry and gain and remove its + * contribution from input data + * + * @param adapt_cb array from which the adaptive codebook is extracted + * @param work array used to calculate LPC-filtered vectors + * @param coefs coefficients of the LPC filter + * @param data input data + * @return index of the best entry of the adaptive codebook + */ +static int adaptive_cb_search(const int16_t *adapt_cb, float *work, + const float *coefs, float *data) +{ + int i, av_uninit(best_vect); + float score, gain, best_score, av_uninit(best_gain); + float exc[BLOCKSIZE]; + + gain = best_score = 0; + for (i = BLOCKSIZE / 2; i <= BUFFERSIZE; i++) { + create_adapt_vect(exc, adapt_cb, i); + get_match_score(work, coefs, exc, NULL, NULL, data, &score, &gain); + if (score > best_score) { + best_score = score; + best_vect = i; + best_gain = gain; + } + } + if (!best_score) + return 0; + + /** + * Re-calculate the filtered vector from the vector with maximum match score + * and remove its contribution from input data. + */ + create_adapt_vect(exc, adapt_cb, best_vect); + ff_celp_lp_synthesis_filterf(work, coefs, exc, BLOCKSIZE, LPC_ORDER); + for (i = 0; i < BLOCKSIZE; i++) + data[i] -= best_gain * work[i]; + return best_vect - BLOCKSIZE / 2 + 1; +} + + +/** + * Find the best vector of a fixed codebook by applying an LPC filter to + * codebook entries, possibly othogonalizing them to up to 2 other vectors and + * matching the results with input data + * + * @param work array used to calculate the filtered vectors + * @param coefs coefficients of the LPC filter + * @param cb fixed codebook + * @param ortho1 first vector against which orthogonalization is performed + * @param ortho2 second vector against which orthogonalization is performed + * @param data input data + * @param idx pointer to variable where the index of the best codebook entry is + * returned + * @param gain pointer to variable where the gain of the best codebook entry is + * returned + */ +static void find_best_vect(float *work, const float *coefs, + const int8_t cb[][BLOCKSIZE], const float *ortho1, + const float *ortho2, float *data, int *idx, + float *gain) +{ + int i, j; + float g, score, best_score; + float vect[BLOCKSIZE]; + + *idx = *gain = best_score = 0; + for (i = 0; i < FIXED_CB_SIZE; i++) { + for (j = 0; j < BLOCKSIZE; j++) + vect[j] = cb[i][j]; + get_match_score(work, coefs, vect, ortho1, ortho2, data, &score, &g); + if (score > best_score) { + best_score = score; + *idx = i; + *gain = g; + } + } +} + + +/** + * Search the two fixed codebooks for the best entry and gain + * + * @param work array used to calculate LPC-filtered vectors + * @param coefs coefficients of the LPC filter + * @param data input data + * @param cba_idx index of the best entry of the adaptive codebook + * @param cb1_idx pointer to variable where the index of the best entry of the + * first fixed codebook is returned + * @param cb2_idx pointer to variable where the index of the best entry of the + * second fixed codebook is returned + */ +static void fixed_cb_search(float *work, const float *coefs, float *data, + int cba_idx, int *cb1_idx, int *cb2_idx) +{ + int i, ortho_cb1; + float gain; + float cba_vect[BLOCKSIZE], cb1_vect[BLOCKSIZE]; + float vect[BLOCKSIZE]; + + /** + * The filtered vector from the adaptive codebook can be retrieved from + * work, because this function is called just after adaptive_cb_search(). + */ + if (cba_idx) + memcpy(cba_vect, work, sizeof(cba_vect)); + + find_best_vect(work, coefs, ff_cb1_vects, cba_idx ? cba_vect : NULL, NULL, + data, cb1_idx, &gain); + + /** + * Re-calculate the filtered vector from the vector with maximum match score + * and remove its contribution from input data. + */ + if (gain) { + for (i = 0; i < BLOCKSIZE; i++) + vect[i] = ff_cb1_vects[*cb1_idx][i]; + ff_celp_lp_synthesis_filterf(work, coefs, vect, BLOCKSIZE, LPC_ORDER); + if (cba_idx) + orthogonalize(work, cba_vect); + for (i = 0; i < BLOCKSIZE; i++) + data[i] -= gain * work[i]; + memcpy(cb1_vect, work, sizeof(cb1_vect)); + ortho_cb1 = 1; + } else + ortho_cb1 = 0; + + find_best_vect(work, coefs, ff_cb2_vects, cba_idx ? cba_vect : NULL, + ortho_cb1 ? cb1_vect : NULL, data, cb2_idx, &gain); +} + + +/** + * Encode a subblock of the current frame + * + * @param ractx encoder context + * @param sblock_data input data of the subblock + * @param lpc_coefs coefficients of the LPC filter + * @param rms RMS of the reflection coefficients + * @param pb pointer to PutBitContext of the current frame + */ +static void ra144_encode_subblock(RA144Context *ractx, + const int16_t *sblock_data, + const int16_t *lpc_coefs, unsigned int rms, + PutBitContext *pb) +{ + float data[BLOCKSIZE] = { 0 }, work[LPC_ORDER + BLOCKSIZE]; + float coefs[LPC_ORDER]; + float zero[BLOCKSIZE], cba[BLOCKSIZE], cb1[BLOCKSIZE], cb2[BLOCKSIZE]; + int16_t cba_vect[BLOCKSIZE]; + int cba_idx, cb1_idx, cb2_idx, gain; + int i, n; + unsigned m[3]; + float g[3]; + float error, best_error; + + for (i = 0; i < LPC_ORDER; i++) { + work[i] = ractx->curr_sblock[BLOCKSIZE + i]; + coefs[i] = lpc_coefs[i] * (1/4096.0); + } + + /** + * Calculate the zero-input response of the LPC filter and subtract it from + * input data. + */ + ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, data, BLOCKSIZE, + LPC_ORDER); + for (i = 0; i < BLOCKSIZE; i++) { + zero[i] = work[LPC_ORDER + i]; + data[i] = sblock_data[i] - zero[i]; + } + + /** + * Codebook search is performed without taking into account the contribution + * of the previous subblock, since it has been just subtracted from input + * data. + */ + memset(work, 0, LPC_ORDER * sizeof(*work)); + + cba_idx = adaptive_cb_search(ractx->adapt_cb, work + LPC_ORDER, coefs, + data); + if (cba_idx) { + /** + * The filtered vector from the adaptive codebook can be retrieved from + * work, see implementation of adaptive_cb_search(). + */ + memcpy(cba, work + LPC_ORDER, sizeof(cba)); + + ff_copy_and_dup(cba_vect, ractx->adapt_cb, cba_idx + BLOCKSIZE / 2 - 1); + m[0] = (ff_irms(cba_vect) * rms) >> 12; + } + fixed_cb_search(work + LPC_ORDER, coefs, data, cba_idx, &cb1_idx, &cb2_idx); + for (i = 0; i < BLOCKSIZE; i++) { + cb1[i] = ff_cb1_vects[cb1_idx][i]; + cb2[i] = ff_cb2_vects[cb2_idx][i]; + } + ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, cb1, BLOCKSIZE, + LPC_ORDER); + memcpy(cb1, work + LPC_ORDER, sizeof(cb1)); + m[1] = (ff_cb1_base[cb1_idx] * rms) >> 8; + ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, cb2, BLOCKSIZE, + LPC_ORDER); + memcpy(cb2, work + LPC_ORDER, sizeof(cb2)); + m[2] = (ff_cb2_base[cb2_idx] * rms) >> 8; + best_error = FLT_MAX; + gain = 0; + for (n = 0; n < 256; n++) { + g[1] = ((ff_gain_val_tab[n][1] * m[1]) >> ff_gain_exp_tab[n]) * + (1/4096.0); + g[2] = ((ff_gain_val_tab[n][2] * m[2]) >> ff_gain_exp_tab[n]) * + (1/4096.0); + error = 0; + if (cba_idx) { + g[0] = ((ff_gain_val_tab[n][0] * m[0]) >> ff_gain_exp_tab[n]) * + (1/4096.0); + for (i = 0; i < BLOCKSIZE; i++) { + data[i] = zero[i] + g[0] * cba[i] + g[1] * cb1[i] + + g[2] * cb2[i]; + error += (data[i] - sblock_data[i]) * + (data[i] - sblock_data[i]); + } + } else { + for (i = 0; i < BLOCKSIZE; i++) { + data[i] = zero[i] + g[1] * cb1[i] + g[2] * cb2[i]; + error += (data[i] - sblock_data[i]) * + (data[i] - sblock_data[i]); + } + } + if (error < best_error) { + best_error = error; + gain = n; + } + } + put_bits(pb, 7, cba_idx); + put_bits(pb, 8, gain); + put_bits(pb, 7, cb1_idx); + put_bits(pb, 7, cb2_idx); + ff_subblock_synthesis(ractx, lpc_coefs, cba_idx, cb1_idx, cb2_idx, rms, + gain); +} + + +static int ra144_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + static const uint8_t sizes[LPC_ORDER] = {64, 32, 32, 16, 16, 8, 8, 8, 8, 4}; + static const uint8_t bit_sizes[LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2}; + RA144Context *ractx = avctx->priv_data; + PutBitContext pb; + int32_t lpc_data[NBLOCKS * BLOCKSIZE]; + int32_t lpc_coefs[LPC_ORDER][MAX_LPC_ORDER]; + int shift[LPC_ORDER]; + int16_t block_coefs[NBLOCKS][LPC_ORDER]; + int lpc_refl[LPC_ORDER]; /**< reflection coefficients of the frame */ + unsigned int refl_rms[NBLOCKS]; /**< RMS of the reflection coefficients */ + const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL; + int energy = 0; + int i, idx, ret; + + if (ractx->last_frame) + return 0; + + if ((ret = ff_alloc_packet2(avctx, avpkt, FRAMESIZE)) < 0) + return ret; + + /** + * Since the LPC coefficients are calculated on a frame centered over the + * fourth subframe, to encode a given frame, data from the next frame is + * needed. In each call to this function, the previous frame (whose data are + * saved in the encoder context) is encoded, and data from the current frame + * are saved in the encoder context to be used in the next function call. + */ + for (i = 0; i < (2 * BLOCKSIZE + BLOCKSIZE / 2); i++) { + lpc_data[i] = ractx->curr_block[BLOCKSIZE + BLOCKSIZE / 2 + i]; + energy += (lpc_data[i] * lpc_data[i]) >> 4; + } + if (frame) { + int j; + for (j = 0; j < frame->nb_samples && i < NBLOCKS * BLOCKSIZE; i++, j++) { + lpc_data[i] = samples[j] >> 2; + energy += (lpc_data[i] * lpc_data[i]) >> 4; + } + } + if (i < NBLOCKS * BLOCKSIZE) + memset(&lpc_data[i], 0, (NBLOCKS * BLOCKSIZE - i) * sizeof(*lpc_data)); + energy = ff_energy_tab[quantize(ff_t_sqrt(energy >> 5) >> 10, ff_energy_tab, + 32)]; + + ff_lpc_calc_coefs(&ractx->lpc_ctx, lpc_data, NBLOCKS * BLOCKSIZE, LPC_ORDER, + LPC_ORDER, 16, lpc_coefs, shift, FF_LPC_TYPE_LEVINSON, + 0, ORDER_METHOD_EST, 12, 0); + for (i = 0; i < LPC_ORDER; i++) + block_coefs[NBLOCKS - 1][i] = -(lpc_coefs[LPC_ORDER - 1][i] << + (12 - shift[LPC_ORDER - 1])); + + /** + * TODO: apply perceptual weighting of the input speech through bandwidth + * expansion of the LPC filter. + */ + + if (ff_eval_refl(lpc_refl, block_coefs[NBLOCKS - 1], avctx)) { + /** + * The filter is unstable: use the coefficients of the previous frame. + */ + ff_int_to_int16(block_coefs[NBLOCKS - 1], ractx->lpc_coef[1]); + if (ff_eval_refl(lpc_refl, block_coefs[NBLOCKS - 1], avctx)) { + /* the filter is still unstable. set reflection coeffs to zero. */ + memset(lpc_refl, 0, sizeof(lpc_refl)); + } + } + init_put_bits(&pb, avpkt->data, avpkt->size); + for (i = 0; i < LPC_ORDER; i++) { + idx = quantize(lpc_refl[i], ff_lpc_refl_cb[i], sizes[i]); + put_bits(&pb, bit_sizes[i], idx); + lpc_refl[i] = ff_lpc_refl_cb[i][idx]; + } + ractx->lpc_refl_rms[0] = ff_rms(lpc_refl); + ff_eval_coefs(ractx->lpc_coef[0], lpc_refl); + refl_rms[0] = ff_interp(ractx, block_coefs[0], 1, 1, ractx->old_energy); + refl_rms[1] = ff_interp(ractx, block_coefs[1], 2, + energy <= ractx->old_energy, + ff_t_sqrt(energy * ractx->old_energy) >> 12); + refl_rms[2] = ff_interp(ractx, block_coefs[2], 3, 0, energy); + refl_rms[3] = ff_rescale_rms(ractx->lpc_refl_rms[0], energy); + ff_int_to_int16(block_coefs[NBLOCKS - 1], ractx->lpc_coef[0]); + put_bits(&pb, 5, quantize(energy, ff_energy_tab, 32)); + for (i = 0; i < NBLOCKS; i++) + ra144_encode_subblock(ractx, ractx->curr_block + i * BLOCKSIZE, + block_coefs[i], refl_rms[i], &pb); + flush_put_bits(&pb); + ractx->old_energy = energy; + ractx->lpc_refl_rms[1] = ractx->lpc_refl_rms[0]; + FFSWAP(unsigned int *, ractx->lpc_coef[0], ractx->lpc_coef[1]); + + /* copy input samples to current block for processing in next call */ + i = 0; + if (frame) { + for (; i < frame->nb_samples; i++) + ractx->curr_block[i] = samples[i] >> 2; + + if ((ret = ff_af_queue_add(&ractx->afq, frame)) < 0) + return ret; + } else + ractx->last_frame = 1; + memset(&ractx->curr_block[i], 0, + (NBLOCKS * BLOCKSIZE - i) * sizeof(*ractx->curr_block)); + + /* Get the next frame pts/duration */ + ff_af_queue_remove(&ractx->afq, avctx->frame_size, &avpkt->pts, + &avpkt->duration); + + avpkt->size = FRAMESIZE; + *got_packet_ptr = 1; + return 0; +} + + +AVCodec ff_ra_144_encoder = { + .name = "real_144", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_RA_144, + .priv_data_size = sizeof(RA144Context), + .init = ra144_encode_init, + .encode2 = ra144_encode_frame, + .close = ra144_encode_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .supported_samplerates = (const int[]){ 8000, 0 }, + .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), +}; diff --git a/ffmpeg/libavcodec/ra288.c b/ffmpeg/libavcodec/ra288.c new file mode 100644 index 0000000..393ea0b --- /dev/null +++ b/ffmpeg/libavcodec/ra288.c @@ -0,0 +1,239 @@ +/* + * RealAudio 2.0 (28.8K) + * Copyright (c) 2003 the ffmpeg project + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "libavutil/internal.h" +#include "avcodec.h" +#include "internal.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "ra288.h" +#include "lpc.h" +#include "celp_filters.h" + +#define MAX_BACKWARD_FILTER_ORDER 36 +#define MAX_BACKWARD_FILTER_LEN 40 +#define MAX_BACKWARD_FILTER_NONREC 35 + +#define RA288_BLOCK_SIZE 5 +#define RA288_BLOCKS_PER_FRAME 32 + +typedef struct { + AVFloatDSPContext fdsp; + DECLARE_ALIGNED(32, float, sp_lpc)[FFALIGN(36, 16)]; ///< LPC coefficients for speech data (spec: A) + DECLARE_ALIGNED(32, float, gain_lpc)[FFALIGN(10, 16)]; ///< LPC coefficients for gain (spec: GB) + + /** speech data history (spec: SB). + * Its first 70 coefficients are updated only at backward filtering. + */ + float sp_hist[111]; + + /// speech part of the gain autocorrelation (spec: REXP) + float sp_rec[37]; + + /** log-gain history (spec: SBLG). + * Its first 28 coefficients are updated only at backward filtering. + */ + float gain_hist[38]; + + /// recursive part of the gain autocorrelation (spec: REXPLG) + float gain_rec[11]; +} RA288Context; + +static av_cold int ra288_decode_init(AVCodecContext *avctx) +{ + RA288Context *ractx = avctx->priv_data; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + if (avctx->block_align <= 0) { + av_log(avctx, AV_LOG_ERROR, "unsupported block align\n"); + return AVERROR_PATCHWELCOME; + } + + avpriv_float_dsp_init(&ractx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + return 0; +} + +static void convolve(float *tgt, const float *src, int len, int n) +{ + for (; n >= 0; n--) + tgt[n] = avpriv_scalarproduct_float_c(src, src - n, len); + +} + +static void decode(RA288Context *ractx, float gain, int cb_coef) +{ + int i; + double sumsum; + float sum, buffer[5]; + float *block = ractx->sp_hist + 70 + 36; // current block + float *gain_block = ractx->gain_hist + 28; + + memmove(ractx->sp_hist + 70, ractx->sp_hist + 75, 36*sizeof(*block)); + + /* block 46 of G.728 spec */ + sum = 32.; + for (i=0; i < 10; i++) + sum -= gain_block[9-i] * ractx->gain_lpc[i]; + + /* block 47 of G.728 spec */ + sum = av_clipf(sum, 0, 60); + + /* block 48 of G.728 spec */ + /* exp(sum * 0.1151292546497) == pow(10.0,sum/20) */ + sumsum = exp(sum * 0.1151292546497) * gain * (1.0/(1<<23)); + + for (i=0; i < 5; i++) + buffer[i] = codetable[cb_coef][i] * sumsum; + + sum = avpriv_scalarproduct_float_c(buffer, buffer, 5); + + sum = FFMAX(sum, 5. / (1<<24)); + + /* shift and store */ + memmove(gain_block, gain_block + 1, 9 * sizeof(*gain_block)); + + gain_block[9] = 10 * log10(sum) + (10*log10(((1<<24)/5.)) - 32); + + ff_celp_lp_synthesis_filterf(block, ractx->sp_lpc, buffer, 5, 36); +} + +/** + * Hybrid window filtering, see blocks 36 and 49 of the G.728 specification. + * + * @param order filter order + * @param n input length + * @param non_rec number of non-recursive samples + * @param out filter output + * @param hist pointer to the input history of the filter + * @param out pointer to the non-recursive part of the output + * @param out2 pointer to the recursive part of the output + * @param window pointer to the windowing function table + */ +static void do_hybrid_window(RA288Context *ractx, + int order, int n, int non_rec, float *out, + float *hist, float *out2, const float *window) +{ + int i; + float buffer1[MAX_BACKWARD_FILTER_ORDER + 1]; + float buffer2[MAX_BACKWARD_FILTER_ORDER + 1]; + LOCAL_ALIGNED(32, float, work, [FFALIGN(MAX_BACKWARD_FILTER_ORDER + + MAX_BACKWARD_FILTER_LEN + + MAX_BACKWARD_FILTER_NONREC, 16)]); + + av_assert2(order>=0); + + ractx->fdsp.vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 16)); + + convolve(buffer1, work + order , n , order); + convolve(buffer2, work + order + n, non_rec, order); + + for (i=0; i <= order; i++) { + out2[i] = out2[i] * 0.5625 + buffer1[i]; + out [i] = out2[i] + buffer2[i]; + } + + /* Multiply by the white noise correcting factor (WNCF). */ + *out *= 257./256.; +} + +/** + * Backward synthesis filter, find the LPC coefficients from past speech data. + */ +static void backward_filter(RA288Context *ractx, + float *hist, float *rec, const float *window, + float *lpc, const float *tab, + int order, int n, int non_rec, int move_size) +{ + float temp[MAX_BACKWARD_FILTER_ORDER+1]; + + do_hybrid_window(ractx, order, n, non_rec, temp, hist, rec, window); + + if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1)) + ractx->fdsp.vector_fmul(lpc, lpc, tab, FFALIGN(order, 16)); + + memmove(hist, hist + n, move_size*sizeof(*hist)); +} + +static int ra288_decode_frame(AVCodecContext * avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + float *out; + int i, ret; + RA288Context *ractx = avctx->priv_data; + GetBitContext gb; + + if (buf_size < avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, + "Error! Input buffer is too small [%d<%d]\n", + buf_size, avctx->block_align); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = RA288_BLOCK_SIZE * RA288_BLOCKS_PER_FRAME; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + out = (float *)frame->data[0]; + + init_get_bits(&gb, buf, avctx->block_align * 8); + + for (i=0; i < RA288_BLOCKS_PER_FRAME; i++) { + float gain = amptable[get_bits(&gb, 3)]; + int cb_coef = get_bits(&gb, 6 + (i&1)); + + decode(ractx, gain, cb_coef); + + memcpy(out, &ractx->sp_hist[70 + 36], RA288_BLOCK_SIZE * sizeof(*out)); + out += RA288_BLOCK_SIZE; + + if ((i & 7) == 3) { + backward_filter(ractx, ractx->sp_hist, ractx->sp_rec, syn_window, + ractx->sp_lpc, syn_bw_tab, 36, 40, 35, 70); + + backward_filter(ractx, ractx->gain_hist, ractx->gain_rec, gain_window, + ractx->gain_lpc, gain_bw_tab, 10, 8, 20, 28); + } + } + + *got_frame_ptr = 1; + + return avctx->block_align; +} + +AVCodec ff_ra_288_decoder = { + .name = "real_288", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_RA_288, + .priv_data_size = sizeof(RA288Context), + .init = ra288_decode_init, + .decode = ra288_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"), +}; diff --git a/ffmpeg/libavcodec/ra288.h b/ffmpeg/libavcodec/ra288.h new file mode 100644 index 0000000..7323eea --- /dev/null +++ b/ffmpeg/libavcodec/ra288.h @@ -0,0 +1,148 @@ +/* + * RealAudio 2.0 (28.8K) + * Copyright (c) 2003 the ffmpeg project + * + * 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 + */ + +#ifndef AVCODEC_RA288_H +#define AVCODEC_RA288_H + +#include +#include "libavutil/common.h" + +static const float amptable[8]={ + 0.515625, 0.90234375, 1.57910156, 2.76342773, + -0.515625, -0.90234375, -1.57910156, -2.76342773 +}; + +static const int16_t codetable[128][5]={ + { 668, -2950, -1254, -1790, -2553}, { -5032, -4577, -1045, 2908, 3318}, + { -2819, -2677, -948, -2825, -4450}, { -6679, -340, 1482, -1276, 1262}, + { -562, -6757, 1281, 179, -1274}, { -2512, -7130, -4925, 6913, 2411}, + { -2478, -156, 4683, -3873, 0}, { -8208, 2140, -478, -2785, 533}, + { 1889, 2759, 1381, -6955, -5913}, { 5082, -2460, -5778, 1797, 568}, + { -2208, -3309, -4523, -6236, -7505}, { -2719, 4358, -2988, -1149, 2664}, + { 1259, 995, 2711, -2464,-10390}, { 1722, -7569, -2742, 2171, -2329}, + { 1032, 747, -858, -7946,-12843}, { 3106, 4856, -4193, -2541, 1035}, + { 1862, -960, -6628, 410, 5882}, { -2493, -2628, -4000, -60, 7202}, + { -2672, 1446, 1536, -3831, 1233}, { -5302, 6912, 1589, -4187, 3665}, + { -3456, -8170, -7709, 1384, 4698}, { -4699, -6209,-11176, 8104, 16830}, + { 930, 7004, 1269, -8977, 2567}, { 4649, 11804, 3441, -5657, 1199}, + { 2542, -183, -8859, -7976, 3230}, { -2872, -2011, -9713, -8385, 12983}, + { 3086, 2140, -3680, -9643, -2896}, { -7609, 6515, -2283, -2522, 6332}, + { -3333, -5620, -9130,-11131, 5543}, { -407, -6721,-17466, -2889, 11568}, + { 3692, 6796, -262,-10846, -1856}, { 7275, 13404, -2989,-10595, 4936}, + { 244, -2219, 2656, 3776, -5412}, { -4043, -5934, 2131, 863, -2866}, + { -3302, 1743, -2006, -128, -2052}, { -6361, 3342, -1583, -21, 1142}, + { -3837, -1831, 6397, 2545, -2848}, { -9332, -6528, 5309, 1986, -2245}, + { -4490, 748, 1935, -3027, -493}, { -9255, 5366, 3193, -4493, 1784}, + { 4784, -370, 1866, 1057, -1889}, { 7342, -2690, -2577, 676, -611}, + { -502, 2235, -1850, -1777, -2049}, { 1011, 3880, -2465, 2209, -152}, + { 2592, 2829, 5588, 2839, -7306}, { -3049, -4918, 5955, 9201, -4447}, + { 697, 3908, 5798, -4451, -4644}, { -2121, 5444, -2570, 321, -1202}, + { 2846, -2086, 3532, 566, -708}, { -4279, 950, 4980, 3749, 452}, + { -2484, 3502, 1719, -170, 238}, { -3435, 263, 2114, -2005, 2361}, + { -7338, -1208, 9347, -1216, -4013}, {-13498, -439, 8028, -4232, 361}, + { -3729, 5433, 2004, -4727, -1259}, { -3986, 7743, 8429, -3691, -987}, + { 5198, -423, 1150, -1281, 816}, { 7409, 4109, -3949, 2690, 30}, + { 1246, 3055, -35, -1370, -246}, { -1489, 5635, -678, -2627, 3170}, + { 4830, -4585, 2008, -1062, 799}, { -129, 717, 4594, 14937, 10706}, + { 417, 2759, 1850, -5057, -1153}, { -3887, 7361, -5768, 4285, 666}, + { 1443, -938, 20, -2119, -1697}, { -3712, -3402, -2212, 110, 2136}, + { -2952, 12, -1568, -3500, -1855}, { -1315, -1731, 1160, -558, 1709}, + { 88, -4569, 194, -454, -2957}, { -2839, -1666, -273, 2084, -155}, + { -189, -2376, 1663, -1040, -2449}, { -2842, -1369, 636, -248, -2677}, + { 1517, 79, -3013, -3669, -973}, { 1913, -2493, -5312, -749, 1271}, + { -2903, -3324, -3756, -3690, -1829}, { -2913, -1547, -2760, -1406, 1124}, + { 1844, -1834, 456, 706, -4272}, { 467, -4256, -1909, 1521, 1134}, + { -127, -994, -637, -1491, -6494}, { 873, -2045, -3828, -2792, -578}, + { 2311, -1817, 2632, -3052, 1968}, { 641, 1194, 1893, 4107, 6342}, + { -45, 1198, 2160, -1449, 2203}, { -2004, 1713, 3518, 2652, 4251}, + { 2936, -3968, 1280, 131, -1476}, { 2827, 8, -1928, 2658, 3513}, + { 3199, -816, 2687, -1741, -1407}, { 2948, 4029, 394, -253, 1298}, + { 4286, 51, -4507, -32, -659}, { 3903, 5646, -5588, -2592, 5707}, + { -606, 1234, -1607, -5187, 664}, { -525, 3620, -2192, -2527, 1707}, + { 4297, -3251, -2283, 812, -2264}, { 5765, 528, -3287, 1352, 1672}, + { 2735, 1241, -1103, -3273, -3407}, { 4033, 1648, -2965, -1174, 1444}, + { 74, 918, 1999, 915, -1026}, { -2496, -1605, 2034, 2950, 229}, + { -2168, 2037, 15, -1264, -208}, { -3552, 1530, 581, 1491, 962}, + { -2613, -2338, 3621, -1488, -2185}, { -1747, 81, 5538, 1432, -2257}, + { -1019, 867, 214, -2284, -1510}, { -1684, 2816, -229, 2551, -1389}, + { 2707, 504, 479, 2783, -1009}, { 2517, -1487, -1596, 621, 1929}, + { -148, 2206, -4288, 1292, -1401}, { -527, 1243, -2731, 1909, 1280}, + { 2149, -1501, 3688, 610, -4591}, { 3306, -3369, 1875, 3636, -1217}, + { 2574, 2513, 1449, -3074, -4979}, { 814, 1826, -2497, 4234, -4077}, + { 1664, -220, 3418, 1002, 1115}, { 781, 1658, 3919, 6130, 3140}, + { 1148, 4065, 1516, 815, 199}, { 1191, 2489, 2561, 2421, 2443}, + { 770, -5915, 5515, -368, -3199}, { 1190, 1047, 3742, 6927, -2089}, + { 292, 3099, 4308, -758, -2455}, { 523, 3921, 4044, 1386, 85}, + { 4367, 1006, -1252, -1466, -1383}, { 3852, 1579, -77, 2064, 868}, + { 5109, 2919, -202, 359, -509}, { 3650, 3206, 2303, 1693, 1296}, + { 2905, -3907, 229, -1196, -2332}, { 5977, -3585, 805, 3825, -3138}, + { 3746, -606, 53, -269, -3301}, { 606, 2018, -1316, 4064, 398} +}; + +DECLARE_ALIGNED(32, static const float, syn_window)[FFALIGN(111, 16)]={ + 0.576690972, 0.580838025, 0.585013986, 0.589219987, 0.59345597, 0.597723007, + 0.602020264, 0.606384277, 0.610748291, 0.615142822, 0.619598389, 0.624084473, + 0.628570557, 0.633117676, 0.637695313, 0.642272949, 0.646911621, 0.651580811, + 0.656280518, 0.66104126, 0.665802002, 0.670593262, 0.675445557, 0.680328369, + 0.685241699, 0.690185547, 0.695159912, 0.700164795, 0.705230713, 0.710327148, + 0.715454102, 0.720611572, 0.725830078, 0.731048584, 0.736328125, 0.741638184, + 0.747009277, 0.752380371, 0.7578125, 0.763305664, 0.768798828, 0.774353027, + 0.779937744, 0.785583496, 0.791229248, 0.796936035, 0.802703857, 0.808502197, + 0.814331055, 0.820220947, 0.826141357, 0.832092285, 0.838104248, 0.844146729, + 0.850250244, 0.856384277, 0.862548828, 0.868774414, 0.875061035, 0.881378174, + 0.88772583, 0.894134521, 0.900604248, 0.907104492, 0.913635254, 0.920227051, + 0.926879883, 0.933563232, 0.940307617, 0.94708252, 0.953918457, 0.96081543, + 0.96774292, 0.974731445, 0.981781006, 0.988861084, 0.994842529, 0.998565674, + 0.999969482, 0.99911499, 0.996002197, 0.990600586, 0.982910156, 0.973022461, + 0.960876465, 0.946533203, 0.930053711, 0.911437988, 0.89074707, 0.868041992, + 0.843322754, 0.816680908, 0.788208008, 0.757904053, 0.725891113, 0.692199707, + 0.656921387, 0.620178223, 0.582000732, 0.542480469, 0.501739502, 0.459838867, + 0.416900635, 0.373016357, 0.328277588, 0.282775879, 0.236663818, 0.189971924, + 0.142852783, 0.0954284668,0.0477600098 +}; + +DECLARE_ALIGNED(32, static const float, gain_window)[FFALIGN(38, 16)]={ + 0.505699992, 0.524200022, 0.54339999, 0.563300014, 0.583953857, 0.60534668, + 0.627502441, 0.650482178, 0.674316406, 0.699005127, 0.724578857, 0.75112915, + 0.778625488, 0.807128906, 0.836669922, 0.86730957, 0.899078369, 0.932006836, + 0.961486816, 0.982757568, 0.995635986, 1, 0.995819092, 0.983154297, + 0.96206665, 0.932769775, 0.895507813, 0.850585938, 0.798400879, 0.739379883, + 0.674072266, 0.602996826, 0.526763916, 0.446014404, 0.361480713, 0.273834229, + 0.183868408, 0.0923461914 +}; + +/** synthesis bandwidth broadening table */ +DECLARE_ALIGNED(32, static const float, syn_bw_tab)[FFALIGN(36, 16)] = { + 0.98828125, 0.976699829, 0.965254128, 0.953942537, 0.942763507, 0.931715488, + 0.920796931, 0.910006344, 0.899342179, 0.888803005, 0.878387332, 0.868093729, + 0.857920766, 0.847867012, 0.837931097, 0.828111589, 0.818407178, 0.808816493, + 0.799338162, 0.789970934, 0.780713439, 0.771564424, 0.762522638, 0.753586829, + 0.744755745, 0.736028135, 0.727402806, 0.718878567, 0.710454226, 0.702128589, + 0.693900526, 0.685768902, 0.677732527, 0.669790328, 0.66194123, 0.654184103 +}; + +/** gain bandwidth broadening table */ +DECLARE_ALIGNED(32, static const float, gain_bw_tab)[FFALIGN(10, 16)] = { + 0.90625, 0.821289063, 0.74432373, 0.674499512, 0.61126709, + 0.553955078, 0.50201416, 0.454956055, 0.41229248, 0.373657227 +}; + +#endif /* AVCODEC_RA288_H */ diff --git a/ffmpeg/libavcodec/ralf.c b/ffmpeg/libavcodec/ralf.c new file mode 100644 index 0000000..d3f82d6 --- /dev/null +++ b/ffmpeg/libavcodec/ralf.c @@ -0,0 +1,535 @@ +/* + * RealAudio Lossless decoder + * + * Copyright (c) 2012 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * This is a decoder for Real Audio Lossless format. + * Dedicated to the mastermind behind it, Ralph Wiggum. + */ + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "golomb.h" +#include "internal.h" +#include "unary.h" +#include "ralfdata.h" + +#define FILTER_NONE 0 +#define FILTER_RAW 642 + +typedef struct VLCSet { + VLC filter_params; + VLC bias; + VLC coding_mode; + VLC filter_coeffs[10][11]; + VLC short_codes[15]; + VLC long_codes[125]; +} VLCSet; + +#define RALF_MAX_PKT_SIZE 8192 + +typedef struct RALFContext { + int version; + int max_frame_size; + VLCSet sets[3]; + int32_t channel_data[2][4096]; + + int filter_params; ///< combined filter parameters for the current channel data + int filter_length; ///< length of the filter for the current channel data + int filter_bits; ///< filter precision for the current channel data + int32_t filter[64]; + + int bias[2]; ///< a constant value added to channel data after filtering + + int num_blocks; ///< number of blocks inside the frame + int sample_offset; + int block_size[1 << 12]; ///< size of the blocks + int block_pts[1 << 12]; ///< block start time (in milliseconds) + + uint8_t pkt[16384]; + int has_pkt; +} RALFContext; + +#define MAX_ELEMS 644 // no RALF table uses more than that + +static int init_ralf_vlc(VLC *vlc, const uint8_t *data, int elems) +{ + uint8_t lens[MAX_ELEMS]; + uint16_t codes[MAX_ELEMS]; + int counts[17], prefixes[18]; + int i, cur_len; + int max_bits = 0; + int nb = 0; + + for (i = 0; i <= 16; i++) + counts[i] = 0; + for (i = 0; i < elems; i++) { + cur_len = (nb ? *data & 0xF : *data >> 4) + 1; + counts[cur_len]++; + max_bits = FFMAX(max_bits, cur_len); + lens[i] = cur_len; + data += nb; + nb ^= 1; + } + prefixes[1] = 0; + for (i = 1; i <= 16; i++) + prefixes[i + 1] = (prefixes[i] + counts[i]) << 1; + + for (i = 0; i < elems; i++) + codes[i] = prefixes[lens[i]]++; + + return ff_init_vlc_sparse(vlc, FFMIN(max_bits, 9), elems, + lens, 1, 1, codes, 2, 2, NULL, 0, 0, 0); +} + +static av_cold int decode_close(AVCodecContext *avctx) +{ + RALFContext *ctx = avctx->priv_data; + int i, j, k; + + for (i = 0; i < 3; i++) { + ff_free_vlc(&ctx->sets[i].filter_params); + ff_free_vlc(&ctx->sets[i].bias); + ff_free_vlc(&ctx->sets[i].coding_mode); + for (j = 0; j < 10; j++) + for (k = 0; k < 11; k++) + ff_free_vlc(&ctx->sets[i].filter_coeffs[j][k]); + for (j = 0; j < 15; j++) + ff_free_vlc(&ctx->sets[i].short_codes[j]); + for (j = 0; j < 125; j++) + ff_free_vlc(&ctx->sets[i].long_codes[j]); + } + + return 0; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + RALFContext *ctx = avctx->priv_data; + int i, j, k; + int ret; + + if (avctx->extradata_size < 24 || memcmp(avctx->extradata, "LSD:", 4)) { + av_log(avctx, AV_LOG_ERROR, "Extradata is not groovy, dude\n"); + return AVERROR_INVALIDDATA; + } + + ctx->version = AV_RB16(avctx->extradata + 4); + if (ctx->version != 0x103) { + avpriv_request_sample(avctx, "Unknown version %X", ctx->version); + return AVERROR_PATCHWELCOME; + } + + avctx->channels = AV_RB16(avctx->extradata + 8); + avctx->sample_rate = AV_RB32(avctx->extradata + 12); + if (avctx->channels < 1 || avctx->channels > 2 + || avctx->sample_rate < 8000 || avctx->sample_rate > 96000) { + av_log(avctx, AV_LOG_ERROR, "Invalid coding parameters %d Hz %d ch\n", + avctx->sample_rate, avctx->channels); + return AVERROR_INVALIDDATA; + } + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO + : AV_CH_LAYOUT_MONO; + + ctx->max_frame_size = AV_RB32(avctx->extradata + 16); + if (ctx->max_frame_size > (1 << 20) || !ctx->max_frame_size) { + av_log(avctx, AV_LOG_ERROR, "invalid frame size %d\n", + ctx->max_frame_size); + } + ctx->max_frame_size = FFMAX(ctx->max_frame_size, avctx->sample_rate); + + for (i = 0; i < 3; i++) { + ret = init_ralf_vlc(&ctx->sets[i].filter_params, filter_param_def[i], + FILTERPARAM_ELEMENTS); + if (ret < 0) { + decode_close(avctx); + return ret; + } + ret = init_ralf_vlc(&ctx->sets[i].bias, bias_def[i], BIAS_ELEMENTS); + if (ret < 0) { + decode_close(avctx); + return ret; + } + ret = init_ralf_vlc(&ctx->sets[i].coding_mode, coding_mode_def[i], + CODING_MODE_ELEMENTS); + if (ret < 0) { + decode_close(avctx); + return ret; + } + for (j = 0; j < 10; j++) { + for (k = 0; k < 11; k++) { + ret = init_ralf_vlc(&ctx->sets[i].filter_coeffs[j][k], + filter_coeffs_def[i][j][k], + FILTER_COEFFS_ELEMENTS); + if (ret < 0) { + decode_close(avctx); + return ret; + } + } + } + for (j = 0; j < 15; j++) { + ret = init_ralf_vlc(&ctx->sets[i].short_codes[j], + short_codes_def[i][j], SHORT_CODES_ELEMENTS); + if (ret < 0) { + decode_close(avctx); + return ret; + } + } + for (j = 0; j < 125; j++) { + ret = init_ralf_vlc(&ctx->sets[i].long_codes[j], + long_codes_def[i][j], LONG_CODES_ELEMENTS); + if (ret < 0) { + decode_close(avctx); + return ret; + } + } + } + + return 0; +} + +static inline int extend_code(GetBitContext *gb, int val, int range, int bits) +{ + if (val == 0) { + val = -range - get_ue_golomb(gb); + } else if (val == range * 2) { + val = range + get_ue_golomb(gb); + } else { + val -= range; + } + if (bits) + val = (val << bits) | get_bits(gb, bits); + return val; +} + +static int decode_channel(RALFContext *ctx, GetBitContext *gb, int ch, + int length, int mode, int bits) +{ + int i, t; + int code_params; + VLCSet *set = ctx->sets + mode; + VLC *code_vlc; int range, range2, add_bits; + int *dst = ctx->channel_data[ch]; + + ctx->filter_params = get_vlc2(gb, set->filter_params.table, 9, 2); + ctx->filter_bits = (ctx->filter_params - 2) >> 6; + ctx->filter_length = ctx->filter_params - (ctx->filter_bits << 6) - 1; + + if (ctx->filter_params == FILTER_RAW) { + for (i = 0; i < length; i++) + dst[i] = get_bits(gb, bits); + ctx->bias[ch] = 0; + return 0; + } + + ctx->bias[ch] = get_vlc2(gb, set->bias.table, 9, 2); + ctx->bias[ch] = extend_code(gb, ctx->bias[ch], 127, 4); + + if (ctx->filter_params == FILTER_NONE) { + memset(dst, 0, sizeof(*dst) * length); + return 0; + } + + if (ctx->filter_params > 1) { + int cmode = 0, coeff = 0; + VLC *vlc = set->filter_coeffs[ctx->filter_bits] + 5; + + add_bits = ctx->filter_bits; + + for (i = 0; i < ctx->filter_length; i++) { + t = get_vlc2(gb, vlc[cmode].table, vlc[cmode].bits, 2); + t = extend_code(gb, t, 21, add_bits); + if (!cmode) + coeff -= 12 << add_bits; + coeff = t - coeff; + ctx->filter[i] = coeff; + + cmode = coeff >> add_bits; + if (cmode < 0) { + cmode = -1 - av_log2(-cmode); + if (cmode < -5) + cmode = -5; + } else if (cmode > 0) { + cmode = 1 + av_log2(cmode); + if (cmode > 5) + cmode = 5; + } + } + } + + code_params = get_vlc2(gb, set->coding_mode.table, set->coding_mode.bits, 2); + if (code_params >= 15) { + add_bits = av_clip((code_params / 5 - 3) / 2, 0, 10); + if (add_bits > 9 && (code_params % 5) != 2) + add_bits--; + range = 10; + range2 = 21; + code_vlc = set->long_codes + code_params - 15; + } else { + add_bits = 0; + range = 6; + range2 = 13; + code_vlc = set->short_codes + code_params; + } + + for (i = 0; i < length; i += 2) { + int code1, code2; + + t = get_vlc2(gb, code_vlc->table, code_vlc->bits, 2); + code1 = t / range2; + code2 = t % range2; + dst[i] = extend_code(gb, code1, range, 0) << add_bits; + dst[i + 1] = extend_code(gb, code2, range, 0) << add_bits; + if (add_bits) { + dst[i] |= get_bits(gb, add_bits); + dst[i + 1] |= get_bits(gb, add_bits); + } + } + + return 0; +} + +static void apply_lpc(RALFContext *ctx, int ch, int length, int bits) +{ + int i, j, acc; + int *audio = ctx->channel_data[ch]; + int bias = 1 << (ctx->filter_bits - 1); + int max_clip = (1 << bits) - 1, min_clip = -max_clip - 1; + + for (i = 1; i < length; i++) { + int flen = FFMIN(ctx->filter_length, i); + + acc = 0; + for (j = 0; j < flen; j++) + acc += ctx->filter[j] * audio[i - j - 1]; + if (acc < 0) { + acc = (acc + bias - 1) >> ctx->filter_bits; + acc = FFMAX(acc, min_clip); + } else { + acc = (acc + bias) >> ctx->filter_bits; + acc = FFMIN(acc, max_clip); + } + audio[i] += acc; + } +} + +static int decode_block(AVCodecContext *avctx, GetBitContext *gb, + int16_t *dst0, int16_t *dst1) +{ + RALFContext *ctx = avctx->priv_data; + int len, ch, ret; + int dmode, mode[2], bits[2]; + int *ch0, *ch1; + int i, t, t2; + + len = 12 - get_unary(gb, 0, 6); + + if (len <= 7) len ^= 1; // codes for length = 6 and 7 are swapped + len = 1 << len; + + if (ctx->sample_offset + len > ctx->max_frame_size) { + av_log(avctx, AV_LOG_ERROR, + "Decoder's stomach is crying, it ate too many samples\n"); + return AVERROR_INVALIDDATA; + } + + if (avctx->channels > 1) + dmode = get_bits(gb, 2) + 1; + else + dmode = 0; + + mode[0] = (dmode == 4) ? 1 : 0; + mode[1] = (dmode >= 2) ? 2 : 0; + bits[0] = 16; + bits[1] = (mode[1] == 2) ? 17 : 16; + + for (ch = 0; ch < avctx->channels; ch++) { + if ((ret = decode_channel(ctx, gb, ch, len, mode[ch], bits[ch])) < 0) + return ret; + if (ctx->filter_params > 1 && ctx->filter_params != FILTER_RAW) { + ctx->filter_bits += 3; + apply_lpc(ctx, ch, len, bits[ch]); + } + if (get_bits_left(gb) < 0) + return AVERROR_INVALIDDATA; + } + ch0 = ctx->channel_data[0]; + ch1 = ctx->channel_data[1]; + switch (dmode) { + case 0: + for (i = 0; i < len; i++) + dst0[i] = ch0[i] + ctx->bias[0]; + break; + case 1: + for (i = 0; i < len; i++) { + dst0[i] = ch0[i] + ctx->bias[0]; + dst1[i] = ch1[i] + ctx->bias[1]; + } + break; + case 2: + for (i = 0; i < len; i++) { + ch0[i] += ctx->bias[0]; + dst0[i] = ch0[i]; + dst1[i] = ch0[i] - (ch1[i] + ctx->bias[1]); + } + break; + case 3: + for (i = 0; i < len; i++) { + t = ch0[i] + ctx->bias[0]; + t2 = ch1[i] + ctx->bias[1]; + dst0[i] = t + t2; + dst1[i] = t; + } + break; + case 4: + for (i = 0; i < len; i++) { + t = ch1[i] + ctx->bias[1]; + t2 = ((ch0[i] + ctx->bias[0]) << 1) | (t & 1); + dst0[i] = (t2 + t) / 2; + dst1[i] = (t2 - t) / 2; + } + break; + } + + ctx->sample_offset += len; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, + AVPacket *avpkt) +{ + RALFContext *ctx = avctx->priv_data; + AVFrame *frame = data; + int16_t *samples0; + int16_t *samples1; + int ret; + GetBitContext gb; + int table_size, table_bytes, i; + const uint8_t *src, *block_pointer; + int src_size; + int bytes_left; + + if (ctx->has_pkt) { + ctx->has_pkt = 0; + table_bytes = (AV_RB16(avpkt->data) + 7) >> 3; + if (table_bytes + 3 > avpkt->size || avpkt->size > RALF_MAX_PKT_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Wrong packet's breath smells of wrong data!\n"); + return AVERROR_INVALIDDATA; + } + if (memcmp(ctx->pkt, avpkt->data, 2 + table_bytes)) { + av_log(avctx, AV_LOG_ERROR, "Wrong packet tails are wrong!\n"); + return AVERROR_INVALIDDATA; + } + + src = ctx->pkt; + src_size = RALF_MAX_PKT_SIZE + avpkt->size; + memcpy(ctx->pkt + RALF_MAX_PKT_SIZE, avpkt->data + 2 + table_bytes, + avpkt->size - 2 - table_bytes); + } else { + if (avpkt->size == RALF_MAX_PKT_SIZE) { + memcpy(ctx->pkt, avpkt->data, avpkt->size); + ctx->has_pkt = 1; + *got_frame_ptr = 0; + + return avpkt->size; + } + src = avpkt->data; + src_size = avpkt->size; + } + + frame->nb_samples = ctx->max_frame_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples0 = (int16_t *)frame->data[0]; + samples1 = (int16_t *)frame->data[1]; + + if (src_size < 5) { + av_log(avctx, AV_LOG_ERROR, "too short packets are too short!\n"); + return AVERROR_INVALIDDATA; + } + table_size = AV_RB16(src); + table_bytes = (table_size + 7) >> 3; + if (src_size < table_bytes + 3) { + av_log(avctx, AV_LOG_ERROR, "short packets are short!\n"); + return AVERROR_INVALIDDATA; + } + init_get_bits(&gb, src + 2, table_size); + ctx->num_blocks = 0; + while (get_bits_left(&gb) > 0) { + ctx->block_size[ctx->num_blocks] = get_bits(&gb, 15); + if (get_bits1(&gb)) { + ctx->block_pts[ctx->num_blocks] = get_bits(&gb, 9); + } else { + ctx->block_pts[ctx->num_blocks] = 0; + } + ctx->num_blocks++; + } + + block_pointer = src + table_bytes + 2; + bytes_left = src_size - table_bytes - 2; + ctx->sample_offset = 0; + for (i = 0; i < ctx->num_blocks; i++) { + if (bytes_left < ctx->block_size[i]) { + av_log(avctx, AV_LOG_ERROR, "I'm pedaling backwards\n"); + break; + } + init_get_bits(&gb, block_pointer, ctx->block_size[i] * 8); + if (decode_block(avctx, &gb, samples0 + ctx->sample_offset, + samples1 + ctx->sample_offset) < 0) { + av_log(avctx, AV_LOG_ERROR, "Sir, I got carsick in your office. Not decoding the rest of packet.\n"); + break; + } + block_pointer += ctx->block_size[i]; + bytes_left -= ctx->block_size[i]; + } + + frame->nb_samples = ctx->sample_offset; + *got_frame_ptr = ctx->sample_offset > 0; + + return avpkt->size; +} + +static void decode_flush(AVCodecContext *avctx) +{ + RALFContext *ctx = avctx->priv_data; + + ctx->has_pkt = 0; +} + + +AVCodec ff_ralf_decoder = { + .name = "ralf", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_RALF, + .priv_data_size = sizeof(RALFContext), + .init = decode_init, + .close = decode_close, + .decode = decode_frame, + .flush = decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("RealAudio Lossless"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/ralfdata.h b/ffmpeg/libavcodec/ralfdata.h new file mode 100644 index 0000000..83eb970 --- /dev/null +++ b/ffmpeg/libavcodec/ralfdata.h @@ -0,0 +1,9920 @@ +/* + * RealAudio Lossless decoder + * + * Copyright (c) 2012 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_RALFDATA_H +#define AVCODEC_RALFDATA_H + +#include + +#define FILTERPARAM_ELEMENTS 643 +#define BIAS_ELEMENTS 255 +#define CODING_MODE_ELEMENTS 140 +#define FILTER_COEFFS_ELEMENTS 43 +#define SHORT_CODES_ELEMENTS 169 +#define LONG_CODES_ELEMENTS 441 + +static const uint8_t filter_param_def[3][324] = { + { + 0x48, 0x86, 0x66, 0x8A, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x54, 0x45, + 0x66, 0x88, 0xAA, 0xAB, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x65, 0x45, 0x55, 0x66, 0x77, 0x78, + 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xBC, 0xCB, 0xBF, 0xFF, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0x86, 0x55, 0x55, 0x55, 0x66, 0x67, 0x77, 0x88, 0x88, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0x9B, 0xBB, 0xCB, 0xBB, 0xCC, 0xCC, + 0xCF, 0xFF, 0xCC, 0xCF, 0xFC, 0xBC, 0xCC, 0xFB, 0xB9, 0xFC, 0xA8, 0x76, + 0x66, 0x56, 0x66, 0x67, 0x67, 0x77, 0x78, 0x88, 0x88, 0x89, 0x88, 0x89, + 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0xAA, 0xAA, 0xAA, 0xAA, 0x9A, 0xA9, + 0xAB, 0xA9, 0xA9, 0x98, 0x86, 0xFF, 0xCA, 0x88, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0x99, 0x98, 0x99, 0x99, 0x9A, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x88, 0x87, + 0x65, 0xFF, 0xFB, 0xAA, 0xA9, 0x88, 0x88, 0x89, 0x99, 0x98, 0x99, 0x9A, + 0xA9, 0x9A, 0xA9, 0xAA, 0xA9, 0x9A, 0xAA, 0xA9, 0xAA, 0xA9, 0x99, 0x99, + 0xA9, 0x9A, 0x99, 0x99, 0x99, 0x98, 0x88, 0x77, 0x64, 0xFF, 0xFF, 0xFC, + 0xBB, 0xBA, 0xB9, 0xAA, 0xAB, 0xAA, 0xAA, 0xBA, 0xAB, 0xAB, 0xAB, 0xCB, + 0xBA, 0xAB, 0xBB, 0xBB, 0xAA, 0xBA, 0xAA, 0xAA, 0xAA, 0xA9, 0xAA, 0x99, + 0x99, 0x99, 0x88, 0x87, 0x64, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCB, 0xBB, 0xBC, 0xBB, 0xCC, 0xFB, 0xCC, 0xCF, 0xCF, + 0xCC, 0xFC, 0xFC, 0xCF, 0xCB, 0xCC, 0xBB, 0xBB, 0xCB, 0xBB, 0xAA, 0x99, + 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xB8, 0xA0, 0x00, 0x00, + }, { + 0xFB, 0x95, 0x67, 0x8B, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x55, 0x56, + 0x77, 0x89, 0xBA, 0xBB, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x65, 0x55, 0x55, 0x56, 0x77, 0x78, + 0x89, 0x9A, 0xAA, 0xAA, 0xBC, 0xBC, 0xCB, 0xBC, 0xCF, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFB, 0x86, 0x55, 0x55, 0x55, 0x55, 0x56, 0x67, 0x77, 0x77, 0x88, + 0x89, 0x9A, 0x99, 0x99, 0xAA, 0xBB, 0xBB, 0xAB, 0xBF, 0xCB, 0xFA, 0xCC, + 0xFC, 0xEC, 0xEF, 0xFB, 0xBC, 0xFF, 0xBC, 0xBB, 0xA9, 0xFF, 0x98, 0x76, + 0x66, 0x66, 0x65, 0x66, 0x66, 0x76, 0x77, 0x77, 0x77, 0x88, 0x88, 0x88, + 0x89, 0x99, 0x99, 0x99, 0x99, 0xA9, 0x99, 0x99, 0x9A, 0x99, 0x99, 0xAA, + 0xAA, 0xA9, 0x99, 0x98, 0x76, 0xFF, 0xF9, 0x87, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0x89, 0x99, + 0x99, 0x99, 0x99, 0x89, 0x99, 0x99, 0x99, 0x98, 0x99, 0x98, 0x77, 0x77, + 0x65, 0xFF, 0xCA, 0xA9, 0x99, 0x89, 0x88, 0x88, 0x98, 0x89, 0x99, 0x98, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x99, 0xA9, 0x9A, 0xA9, 0x99, 0x99, + 0x99, 0x99, 0xA9, 0x99, 0x99, 0x98, 0x88, 0x77, 0x64, 0xFF, 0xCB, 0xA9, + 0xA9, 0xAA, 0xAA, 0xAA, 0x9A, 0xAB, 0xAA, 0x9A, 0xBB, 0xAB, 0xAB, 0xBB, + 0xAB, 0xBA, 0xBB, 0xBA, 0xAA, 0xBA, 0xBA, 0xAA, 0xAA, 0xA9, 0xA9, 0x99, + 0x99, 0x99, 0x88, 0x77, 0x64, 0xFF, 0xFF, 0xFF, 0xBC, 0xFB, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBA, 0xBA, 0xAB, 0xBF, 0xCB, 0xBB, 0xBB, 0xBC, 0xBF, 0xCC, + 0xCB, 0xCB, 0xCC, 0xBB, 0xBB, 0xFB, 0xCB, 0xBC, 0xCA, 0xBC, 0xAA, 0xA9, + 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0xFF, 0xFF, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xF0, 0x00, 0x00, + }, { + 0x9B, 0x65, 0x67, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB5, 0x54, 0x56, + 0x67, 0x88, 0xA9, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x65, 0x44, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x99, 0xA9, 0xAA, 0xBB, 0xBB, 0xAB, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0x76, 0x55, 0x54, 0x55, 0x55, 0x56, 0x67, 0x77, 0x77, 0x88, + 0x89, 0x99, 0x98, 0x99, 0x8A, 0x99, 0xBB, 0xAB, 0xBC, 0xAB, 0xBA, 0xAA, + 0xBB, 0xCB, 0xCC, 0xBB, 0xCC, 0xBB, 0xAC, 0xBA, 0x97, 0xFB, 0x97, 0x76, + 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x88, 0x88, 0x88, 0x88, + 0x99, 0x89, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9A, 0x98, 0x99, 0x99, + 0xA9, 0x99, 0x88, 0x87, 0x65, 0xFF, 0xCA, 0x98, 0x87, 0x77, 0x77, 0x87, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x88, 0x87, 0x77, + 0x64, 0xFF, 0xFC, 0xCA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAA, 0x9A, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0x99, 0x99, 0x99, 0x89, 0x88, 0x87, 0x64, 0xFF, 0xFF, 0xFB, + 0xFF, 0xBC, 0xFC, 0xBB, 0xCB, 0xBB, 0xCA, 0xCB, 0xBC, 0xCC, 0xBF, 0xBC, + 0xBB, 0xBB, 0xBE, 0xBC, 0xCB, 0xCC, 0xBB, 0xFC, 0xBC, 0xCC, 0xAB, 0xCB, + 0xAB, 0xBB, 0xAA, 0xA9, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xCF, 0xFB, + 0xCC, 0xFC, 0xCF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + } +}; + +static const uint8_t bias_def[3][128] = { + { + 0x4A, 0xAA, 0xAA, 0xAA, 0xBA, 0xBA, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x9A, 0xA9, 0xA9, + 0x99, 0xA9, 0x99, 0x99, 0xA9, 0xA9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x88, 0x98, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x77, 0x78, 0x77, 0x77, 0x77, 0x77, 0x66, 0x66, 0x66, 0x55, 0x55, 0x55, + 0x55, 0x54, 0x44, 0x32, 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x89, 0x88, 0x89, 0x89, 0x99, 0x99, 0x98, 0x99, 0x9A, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xA9, 0x9A, 0x99, 0x9A, 0xA9, 0xA9, 0xA9, + 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBA, 0x40, + }, { + 0x4C, 0xBC, 0xAC, 0xBC, 0xBA, 0xAB, 0xAB, 0xBB, 0xBA, 0xAA, 0xAB, 0xAA, + 0xBB, 0xAA, 0xBB, 0xAA, 0xAB, 0xBA, 0xBA, 0xAA, 0xBB, 0xAA, 0xA9, 0xAA, + 0xBB, 0xAA, 0xAA, 0x9A, 0x9A, 0xAA, 0xA9, 0xAA, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x89, 0x88, 0x88, 0x88, 0x88, + 0x87, 0x78, 0x77, 0x77, 0x77, 0x77, 0x67, 0x66, 0x66, 0x55, 0x44, 0x45, + 0x54, 0x44, 0x44, 0x33, 0x44, 0x45, 0x55, 0x56, 0x66, 0x66, 0x66, 0x67, + 0x77, 0x77, 0x77, 0x77, 0x87, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x99, 0x88, 0x99, 0x99, 0x89, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xA9, + 0xA9, 0xAA, 0x9A, 0xA9, 0xAA, 0x9A, 0xAA, 0x9A, 0xAA, 0xAB, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xBB, 0xBA, 0xAA, 0xAB, 0xAB, 0xAA, + 0xAB, 0xAB, 0xAC, 0xBB, 0xAA, 0xBB, 0xBB, 0x40, + }, { + 0x5B, 0xBB, 0xBC, 0xBB, 0xCB, 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xBB, 0xCB, + 0xBA, 0xCB, 0xBC, 0xBB, 0xAA, 0xBB, 0xAB, 0xBA, 0xBB, 0xBB, 0xAB, 0xBB, + 0xAA, 0xBA, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA9, 0x9A, + 0x9A, 0x99, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x89, 0x99, + 0x88, 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x66, 0x66, 0x55, + 0x54, 0x44, 0x43, 0x22, 0x34, 0x44, 0x55, 0x56, 0x66, 0x66, 0x67, 0x77, + 0x77, 0x77, 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x99, 0x89, 0x99, 0x99, + 0x99, 0x99, 0x99, 0x9A, 0x9A, 0xA9, 0xA9, 0x9A, 0x9A, 0xAA, 0x9A, 0xAA, + 0xAA, 0xAA, 0xBA, 0xAA, 0xAA, 0xAA, 0xBA, 0xAA, 0xAA, 0xAB, 0xBA, 0xBB, + 0xAA, 0xBB, 0xAB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBC, + 0xBB, 0xBC, 0xBB, 0xBB, 0xCC, 0xBC, 0xCB, 0x50, + } +}; + +static const uint8_t coding_mode_def[3][72] = { + { + 0xAA, 0x99, 0xAC, 0xB9, 0xBD, 0xAA, 0x7A, 0xA8, 0xA8, 0xA8, 0x79, 0x79, + 0x77, 0xA8, 0x97, 0x79, 0x89, 0x77, 0x87, 0x87, 0x68, 0x78, 0x66, 0x86, + 0x87, 0x67, 0x68, 0x66, 0x76, 0x76, 0x57, 0x67, 0x55, 0x75, 0x65, 0x56, + 0x56, 0x55, 0x65, 0x65, 0x56, 0x45, 0x55, 0x54, 0x55, 0x55, 0x45, 0x55, + 0x54, 0x55, 0x55, 0x45, 0x56, 0x64, 0x66, 0x76, 0x57, 0x67, 0x77, 0x77, + 0x98, 0x88, 0x9D, 0xBF, 0xBA, 0xEC, 0xFC, 0xBA, 0xEF, 0xFC, 0x00, 0x00, + }, { + 0xCF, 0x9B, 0xAF, 0xFF, 0xFF, 0xAB, 0x8A, 0x98, 0xB8, 0xF9, 0x78, 0x89, + 0x77, 0xF9, 0xF7, 0x79, 0x89, 0x77, 0x97, 0x97, 0x68, 0x68, 0x66, 0xA6, + 0x87, 0x77, 0x68, 0x66, 0x75, 0x76, 0x67, 0x56, 0x65, 0x75, 0x75, 0x56, + 0x56, 0x55, 0x65, 0x65, 0x56, 0x56, 0x55, 0x54, 0x55, 0x55, 0x45, 0x55, + 0x53, 0x55, 0x65, 0x35, 0x67, 0x64, 0x66, 0x66, 0x56, 0x78, 0x86, 0x88, + 0xA8, 0xFB, 0xAF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + }, { + 0xDC, 0xAD, 0xCC, 0xCA, 0xCF, 0xFE, 0xDF, 0xFF, 0xE9, 0xFF, 0x99, 0x79, + 0x97, 0x97, 0x97, 0x79, 0x79, 0x77, 0x97, 0x97, 0x79, 0x79, 0x77, 0x86, + 0x87, 0x68, 0x68, 0x76, 0x76, 0x76, 0x67, 0x57, 0x66, 0x65, 0x76, 0x66, + 0x56, 0x55, 0x64, 0x65, 0x55, 0x45, 0x55, 0x54, 0x55, 0x55, 0x35, 0x55, + 0x53, 0x55, 0x65, 0x35, 0x67, 0x64, 0x67, 0x87, 0x57, 0x8A, 0x86, 0x8B, + 0xBA, 0x9A, 0xCD, 0xAA, 0xAF, 0xFC, 0xFF, 0xFF, 0xDF, 0xFF, 0x00, 0x00, + } +}; + +static const uint8_t filter_coeffs_def[3][10][11][24] = { + { + { + { + 0x47, 0x88, 0x76, 0x52, 0x12, 0x35, 0x44, 0x43, 0x34, 0x45, 0x77, 0x67, + 0x66, 0x87, 0x87, 0x7D, 0x8A, 0x89, 0x9D, 0xDD, 0x9C, 0xC0, 0x00, 0x00, + }, + { + 0x7C, 0xCC, 0xC7, 0x65, 0xCC, 0x22, 0x23, 0x46, 0x32, 0x22, 0x46, 0x7B, + 0xB6, 0xBB, 0xBB, 0xBC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0xBB, 0xBB, 0xB4, 0x43, 0x25, 0x5B, 0x5A, 0xAB, 0x5B, 0x22, 0x22, 0x2B, + 0xBA, 0xAA, 0x46, 0x5B, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x31, 0x88, 0x88, 0x89, 0x88, 0x38, 0x88, 0x13, + 0x28, 0x88, 0x88, 0x28, 0x88, 0x88, 0x88, 0x88, 0x99, 0x90, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x88, 0x88, 0x88, 0x39, 0x98, 0x88, 0x88, 0x88, + 0x08, 0x88, 0x88, 0x81, 0x99, 0x88, 0x99, 0x99, 0x99, 0x20, 0x00, 0x00, + }, + { + 0xAA, 0xD9, 0x86, 0xCD, 0xDD, 0xDD, 0x98, 0x76, 0x43, 0x65, 0x35, 0x63, + 0x23, 0x44, 0x33, 0x24, 0x45, 0x44, 0x45, 0x59, 0xA8, 0x90, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x98, 0x88, 0x88, 0x89, 0x98, 0x08, 0x88, 0x88, + 0x28, 0x88, 0x88, 0x83, 0x19, 0x98, 0x88, 0x99, 0x99, 0x90, 0x00, 0x00, + }, + { + 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA5, 0xA4, 0x01, 0x4A, 0xAA, + 0x53, 0x4A, 0xA4, 0xAA, 0x5A, 0xAA, 0xAA, 0xAA, 0xAA, 0xB0, 0x00, 0x00, + }, + { + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x9A, 0xAA, 0xA3, 0x31, 0x31, + 0x34, 0x34, 0xA9, 0xA5, 0x44, 0x4A, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xED, 0xDE, 0xEE, 0xED, 0xDD, 0xDE, 0xE8, 0xEE, 0xE7, 0x64, + 0x47, 0x43, 0x30, 0x43, 0x43, 0x36, 0x7E, 0xEE, 0xEE, 0x90, 0x00, 0x00, + }, + { + 0x67, 0x87, 0x87, 0x66, 0x65, 0x55, 0x44, 0x45, 0x65, 0x54, 0x54, 0x32, + 0x34, 0x66, 0x63, 0x55, 0x44, 0x54, 0x34, 0x45, 0x56, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x56, 0x66, 0x65, 0x54, 0x33, 0x34, 0x33, 0x33, 0x33, 0x34, 0x44, 0x45, + 0x56, 0x66, 0x67, 0x77, 0x77, 0x77, 0x78, 0x89, 0x89, 0x60, 0x00, 0x00, + }, + { + 0x78, 0x89, 0x98, 0x65, 0x65, 0x32, 0x22, 0x32, 0x33, 0x33, 0x45, 0x77, + 0x77, 0x8B, 0x9A, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0x9D, 0xD8, 0x8D, 0x57, 0x56, 0x55, 0x44, 0x45, 0x22, 0x22, 0x23, 0x34, + 0x57, 0x78, 0x88, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0xDC, 0xCC, 0x8C, 0xCC, 0x87, 0x65, 0x55, 0x54, 0x23, 0x44, 0x21, 0x23, + 0x46, 0x56, 0x87, 0x7C, 0x8C, 0x8C, 0xCC, 0xCC, 0xCC, 0xD0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xCC, 0xCD, 0xDC, 0xC7, 0x64, 0x58, 0x31, 0x25, 0x33, 0x22, + 0x44, 0x56, 0x66, 0x6D, 0xDD, 0xDD, 0xDC, 0xDC, 0xDC, 0xD0, 0x00, 0x00, + }, + { + 0xB9, 0x99, 0xA6, 0x67, 0x78, 0x76, 0x78, 0x88, 0x66, 0x55, 0x44, 0x43, + 0x23, 0x33, 0x33, 0x33, 0x34, 0x45, 0x56, 0x66, 0x88, 0xB0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xDC, 0xCD, 0xDC, 0xCC, 0x77, 0xC5, 0x53, 0x12, 0x23, 0x33, + 0x33, 0x46, 0x65, 0x75, 0x8D, 0xDD, 0xDD, 0xDC, 0xDC, 0xD0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xCC, 0xCD, 0xDC, 0xCC, 0x8C, 0x85, 0x55, 0x33, 0x21, 0x23, + 0x33, 0x44, 0x56, 0x56, 0x56, 0x8D, 0xDD, 0xCC, 0xDC, 0xD0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xDD, 0xDE, 0xDD, 0xDD, 0xDD, 0x87, 0x75, 0x55, 0x43, 0x22, + 0x21, 0x25, 0x65, 0x55, 0x66, 0x77, 0xD8, 0x8D, 0xDD, 0x90, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xAA, 0x98, 0x77, 0x55, 0x43, + 0x33, 0x33, 0x21, 0x33, 0x34, 0x66, 0x89, 0xAF, 0xFF, 0xC0, 0x00, 0x00, + }, + { + 0x57, 0x77, 0x76, 0x66, 0x65, 0x55, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x33, 0x44, 0x43, 0x44, 0x44, 0x45, 0x56, 0x66, 0x77, 0x50, 0x00, 0x00, + }, + }, + { + { + 0x57, 0x76, 0x66, 0x65, 0x44, 0x44, 0x43, 0x33, 0x33, 0x33, 0x33, 0x34, + 0x45, 0x56, 0x67, 0x77, 0x77, 0x89, 0x88, 0x89, 0x99, 0x60, 0x00, 0x00, + }, + { + 0x8A, 0x99, 0x88, 0x77, 0x66, 0x44, 0x43, 0x32, 0x32, 0x22, 0x33, 0x45, + 0x67, 0x89, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFB, 0xBA, 0xA7, 0x78, 0x66, 0x65, 0x54, 0x22, 0x21, 0x23, 0x44, + 0x56, 0x8A, 0x9E, 0xAF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xAF, 0xFD, 0xDF, 0xAC, 0x98, 0x77, 0x66, 0x44, 0x31, 0x11, 0x35, + 0x67, 0x88, 0x8A, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xEE, 0xEF, 0xA8, 0x8E, 0x97, 0x66, 0x43, 0x22, 0x21, 0x23, + 0x45, 0x67, 0x97, 0x7F, 0xFF, 0xEE, 0xE9, 0xEE, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xAA, 0xA9, 0x97, 0x65, 0x45, 0x45, 0x67, 0x66, 0x55, 0x54, 0x44, 0x44, + 0x33, 0x33, 0x33, 0x33, 0x44, 0x45, 0x56, 0x68, 0x8B, 0xB0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xED, 0xDE, 0xED, 0xDD, 0xD8, 0x77, 0x65, 0x43, 0x11, 0x22, + 0x34, 0x66, 0x78, 0x87, 0xEE, 0xEE, 0xEE, 0x9D, 0xED, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xDC, 0xFF, 0xAE, 0xEA, 0x98, 0x76, 0x54, 0x31, 0x11, + 0x34, 0x56, 0x88, 0x99, 0x9B, 0xFF, 0xFF, 0xBF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xCF, 0xDF, 0xFF, 0xFD, 0x9A, 0x76, 0x65, 0x43, 0x21, + 0x12, 0x35, 0x56, 0x67, 0x89, 0x99, 0xAF, 0xAF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xEF, 0xDB, 0xBA, 0xAA, 0x99, 0x76, 0x55, 0x43, 0x22, + 0x22, 0x33, 0x33, 0x44, 0x55, 0x67, 0x8A, 0xFA, 0xFB, 0xA0, 0x00, 0x00, + }, + { + 0x57, 0x77, 0x77, 0x66, 0x65, 0x55, 0x54, 0x44, 0x44, 0x44, 0x43, 0x33, + 0x33, 0x34, 0x44, 0x44, 0x55, 0x55, 0x66, 0x77, 0x88, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x58, 0x77, 0x76, 0x66, 0x55, 0x54, 0x44, 0x33, 0x33, 0x23, 0x33, 0x33, + 0x45, 0x56, 0x66, 0x77, 0x88, 0x88, 0x88, 0x88, 0x99, 0x60, 0x00, 0x00, + }, + { + 0x9A, 0xA9, 0xA9, 0x88, 0x76, 0x55, 0x44, 0x33, 0x22, 0x22, 0x23, 0x45, + 0x56, 0x99, 0x9D, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFD, 0xBB, 0xAA, 0xBA, 0xA9, 0x87, 0x77, 0x54, 0x33, 0x21, 0x12, 0x45, + 0x68, 0x8A, 0xAA, 0xCB, 0xFF, 0xCF, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFE, 0xA9, 0x98, 0x87, 0x65, 0x41, 0x02, 0x45, + 0x77, 0x88, 0xAC, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xBF, 0xFC, 0xAB, 0xFB, 0xBA, 0xAB, 0xB8, 0x88, 0x76, 0x52, 0x01, 0x35, + 0x78, 0x99, 0xAB, 0xAA, 0xCF, 0xBB, 0xCF, 0xFC, 0xFC, 0xF0, 0x00, 0x00, + }, + { + 0xBA, 0xCA, 0x98, 0x75, 0x21, 0x35, 0x77, 0x77, 0x76, 0x65, 0x54, 0x44, + 0x44, 0x34, 0x44, 0x44, 0x45, 0x56, 0x78, 0x88, 0x9A, 0xC0, 0x00, 0x00, + }, + { + 0xDF, 0xCF, 0xCC, 0xFF, 0xAB, 0xC9, 0xB9, 0x98, 0x97, 0x75, 0x20, 0x13, + 0x56, 0x89, 0x89, 0xAA, 0xFC, 0xBC, 0xAF, 0xCC, 0xFF, 0xD0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xBB, 0xFB, 0xFF, 0xFB, 0xBA, 0xA8, 0x77, 0x54, 0x21, 0x11, + 0x45, 0x67, 0x88, 0x8A, 0xEF, 0xBB, 0xFF, 0xBB, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFB, 0xCB, 0xB9, 0x88, 0x65, 0x31, 0x12, + 0x23, 0x35, 0x67, 0x88, 0xAA, 0xAC, 0xFC, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFC, 0xEF, 0xFF, 0xBB, 0xAA, 0xA9, 0x76, 0x55, 0x32, 0x22, + 0x22, 0x33, 0x34, 0x56, 0x67, 0x68, 0x9A, 0xAA, 0xCD, 0xE0, 0x00, 0x00, + }, + { + 0x58, 0x77, 0x77, 0x66, 0x66, 0x55, 0x54, 0x44, 0x44, 0x43, 0x33, 0x33, + 0x33, 0x34, 0x44, 0x55, 0x55, 0x66, 0x67, 0x78, 0x88, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x57, 0x77, 0x76, 0x66, 0x55, 0x55, 0x54, 0x43, 0x33, 0x22, 0x33, 0x34, + 0x45, 0x55, 0x66, 0x67, 0x77, 0x77, 0x78, 0x88, 0x99, 0x50, 0x00, 0x00, + }, + { + 0xAC, 0x99, 0x98, 0x87, 0x76, 0x66, 0x54, 0x43, 0x32, 0x21, 0x23, 0x45, + 0x66, 0x89, 0x99, 0x99, 0xAA, 0xBF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xB9, 0xAA, 0x98, 0x77, 0x65, 0x42, 0x21, 0x12, 0x45, + 0x78, 0x8A, 0xBA, 0xAA, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFD, 0xBC, 0xBB, 0xB9, 0x98, 0x76, 0x32, 0x01, 0x46, + 0x79, 0xAB, 0xBB, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xAA, 0xAA, 0x99, 0x76, 0x42, 0x01, 0x36, + 0x79, 0x9A, 0xAB, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xCC, 0xDC, 0xB9, 0x75, 0x10, 0x47, 0x89, 0x99, 0x98, 0x87, 0x76, 0x66, + 0x55, 0x55, 0x55, 0x56, 0x66, 0x67, 0x78, 0x99, 0xBE, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFC, 0xCC, 0xFF, 0xFB, 0xAB, 0x87, 0x64, 0x10, 0x23, + 0x67, 0x99, 0x9A, 0xAD, 0xCE, 0xFF, 0xFC, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFD, 0xFA, 0xB9, 0x97, 0x65, 0x20, 0x13, + 0x56, 0x78, 0xAA, 0x9B, 0xFB, 0xFC, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xCF, 0xFC, 0xC9, 0xAC, 0x98, 0x87, 0x54, 0x31, 0x12, + 0x23, 0x45, 0x67, 0x78, 0x9A, 0xAA, 0xEB, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xCA, 0xFA, 0x99, 0x98, 0x88, 0x65, 0x44, 0x32, 0x22, + 0x22, 0x33, 0x45, 0x56, 0x67, 0x78, 0x99, 0xBB, 0xAB, 0xA0, 0x00, 0x00, + }, + { + 0x48, 0x77, 0x76, 0x66, 0x65, 0x55, 0x55, 0x44, 0x44, 0x43, 0x33, 0x33, + 0x33, 0x34, 0x45, 0x55, 0x55, 0x66, 0x67, 0x77, 0x78, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x68, 0x87, 0x77, 0x77, 0x66, 0x55, 0x54, 0x43, 0x33, 0x22, 0x23, 0x34, + 0x45, 0x55, 0x66, 0x78, 0x88, 0x98, 0x88, 0x88, 0x89, 0x60, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0xBA, 0x99, 0x87, 0x76, 0x54, 0x33, 0x21, 0x12, 0x46, + 0x67, 0x89, 0x9A, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFD, 0xCA, 0x98, 0x87, 0x76, 0x54, 0x21, 0x11, 0x45, + 0x78, 0x8A, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xAA, 0x99, 0x76, 0x32, 0x01, 0x46, + 0x78, 0x9A, 0xAB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0xE9, 0x89, 0x76, 0x52, 0x01, 0x35, + 0x68, 0x98, 0x9A, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xAD, 0xCB, 0xA9, 0x74, 0x10, 0x46, 0x89, 0x9A, 0xA9, 0x98, 0x77, 0x76, + 0x66, 0x55, 0x55, 0x56, 0x66, 0x66, 0x78, 0x88, 0x8A, 0xD0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xAA, 0xAA, 0x87, 0x63, 0x10, 0x24, + 0x67, 0x89, 0xAF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0x9A, 0x97, 0x64, 0x20, 0x13, + 0x67, 0x89, 0x9A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x87, 0x76, 0x43, 0x21, 0x12, + 0x34, 0x56, 0x67, 0x88, 0x89, 0xAE, 0xCF, 0xFD, 0xEF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xAA, 0x87, 0x66, 0x54, 0x31, 0x12, + 0x33, 0x44, 0x55, 0x67, 0x77, 0x89, 0xAB, 0xAB, 0xCF, 0xC0, 0x00, 0x00, + }, + { + 0x58, 0x87, 0x87, 0x77, 0x76, 0x66, 0x55, 0x55, 0x44, 0x43, 0x32, 0x22, + 0x33, 0x44, 0x55, 0x56, 0x67, 0x77, 0x78, 0x88, 0x88, 0x70, 0x00, 0x00, + }, + }, + { + { + 0x67, 0x76, 0x66, 0x76, 0x66, 0x55, 0x44, 0x44, 0x33, 0x22, 0x22, 0x34, + 0x56, 0x67, 0x77, 0x89, 0x88, 0x99, 0xAB, 0x9A, 0xAB, 0x70, 0x00, 0x00, + }, + { + 0x9B, 0xA9, 0x88, 0x88, 0x87, 0x77, 0x65, 0x54, 0x43, 0x21, 0x12, 0x45, + 0x67, 0x9A, 0x9A, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFC, 0xCB, 0xBA, 0xAA, 0x98, 0x87, 0x65, 0x31, 0x02, 0x56, + 0x89, 0xAB, 0xCB, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xAA, 0x9A, 0x98, 0x76, 0x42, 0x01, 0x36, + 0x79, 0xAF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x78, 0xA9, 0x98, 0x76, 0x52, 0x01, 0x35, + 0x78, 0x8E, 0xCB, 0xBF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0x8C, 0xBA, 0x99, 0x74, 0x10, 0x36, 0x89, 0x9A, 0xA9, 0x99, 0x88, 0x87, + 0x76, 0x66, 0x66, 0x66, 0x66, 0x56, 0x66, 0x78, 0x89, 0xC0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x8A, 0xA9, 0x88, 0x63, 0x10, 0x24, + 0x67, 0x8B, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x99, 0x76, 0x54, 0x10, 0x24, + 0x56, 0x78, 0x9A, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD9, 0x87, 0x54, 0x20, 0x22, + 0x45, 0x67, 0x77, 0x89, 0xAC, 0xAB, 0xFB, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xAB, 0x86, 0x54, 0x21, 0x12, + 0x34, 0x45, 0x66, 0x77, 0x67, 0x77, 0x88, 0x99, 0x9A, 0x90, 0x00, 0x00, + }, + { + 0x57, 0x77, 0x76, 0x66, 0x65, 0x55, 0x55, 0x55, 0x54, 0x43, 0x32, 0x23, + 0x33, 0x44, 0x55, 0x55, 0x66, 0x67, 0x88, 0x77, 0x77, 0x50, 0x00, 0x00, + }, + }, + { + { + 0x35, 0x44, 0x45, 0x55, 0x54, 0x44, 0x44, 0x43, 0x33, 0x33, 0x23, 0x44, + 0x68, 0x99, 0xAA, 0xAA, 0xCB, 0xAB, 0xAF, 0xFE, 0xEB, 0xE0, 0x00, 0x00, + }, + { + 0x77, 0x66, 0x67, 0x66, 0x66, 0x66, 0x54, 0x44, 0x33, 0x22, 0x12, 0x45, + 0x68, 0xAA, 0xBE, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xEA, 0x98, 0x88, 0x87, 0x77, 0x65, 0x55, 0x44, 0x32, 0x02, 0x46, + 0x78, 0x89, 0xAA, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0xAB, 0x99, 0x76, 0x65, 0x42, 0x01, 0x45, + 0x78, 0xAA, 0xAD, 0xAC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xEB, 0xBA, 0xA9, 0x86, 0x42, 0x01, 0x36, + 0x77, 0x8A, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0x98, 0x74, 0x10, 0x36, 0x77, 0x89, 0x99, 0x99, 0x88, 0x77, + 0x76, 0x66, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAA, 0xAB, 0xC0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xC9, 0x99, 0x99, 0x88, 0x64, 0x10, 0x24, + 0x55, 0x68, 0x89, 0xBB, 0xAD, 0xBF, 0xBF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x65, 0x65, 0x54, 0x20, 0x23, + 0x45, 0x56, 0x77, 0x77, 0x8E, 0xCB, 0xBE, 0xDF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x76, 0x53, 0x21, 0x13, + 0x34, 0x55, 0x45, 0x55, 0x67, 0x79, 0xAB, 0xFA, 0xFB, 0xA0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0x87, 0x54, 0x21, 0x23, + 0x33, 0x44, 0x55, 0x55, 0x44, 0x45, 0x57, 0x8A, 0xAA, 0x80, 0x00, 0x00, + }, + { + 0x79, 0x99, 0x99, 0x97, 0x77, 0x76, 0x54, 0x44, 0x44, 0x44, 0x32, 0x33, + 0x33, 0x33, 0x44, 0x45, 0x56, 0x67, 0x88, 0x77, 0x78, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x34, 0x54, 0x45, 0x55, 0x54, 0x44, 0x44, 0x33, 0x32, 0x43, 0x34, 0x44, + 0x56, 0x77, 0xBB, 0xB6, 0xCC, 0xCC, 0xCC, 0xC8, 0xCB, 0x70, 0x00, 0x00, + }, + { + 0x7E, 0x67, 0x55, 0x65, 0x44, 0x55, 0x44, 0x33, 0x22, 0x23, 0x23, 0x57, + 0x98, 0xDD, 0xDD, 0xDE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xEE, 0x97, 0x75, 0x54, 0x43, 0x33, 0x33, 0x32, 0x12, 0x58, + 0x88, 0xEE, 0xAE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x88, 0x87, 0x66, 0x53, 0x22, 0x02, 0x57, + 0x9D, 0xFF, 0xFF, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xA9, 0x78, 0x76, 0x42, 0x01, 0x36, + 0x99, 0x9A, 0xFF, 0xDF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xAB, 0xAA, 0xA8, 0x75, 0x10, 0x26, 0x79, 0x88, 0x77, 0x77, 0x66, 0x66, + 0x57, 0x78, 0x88, 0x89, 0x98, 0x9A, 0xBB, 0xBB, 0xDD, 0xC0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, 0xFE, 0xA8, 0x78, 0x76, 0x54, 0x20, 0x22, + 0x45, 0x6E, 0x8E, 0xEF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFA, 0xE7, 0x66, 0x64, 0x20, 0x23, + 0x34, 0x56, 0x78, 0x88, 0xAF, 0xFC, 0xFF, 0xFF, 0xAF, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xED, 0xDE, 0xED, 0x8D, 0xDD, 0xD9, 0xE6, 0x63, 0x21, 0x23, + 0x43, 0x34, 0x35, 0x55, 0x65, 0x47, 0xEE, 0xED, 0xED, 0xE0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xDC, 0xCD, 0xDD, 0xCC, 0xCC, 0xCD, 0xDD, 0x76, 0x43, 0x44, + 0x44, 0x43, 0x34, 0x33, 0x22, 0x33, 0x35, 0xD8, 0xCC, 0xD0, 0x00, 0x00, + }, + { + 0x6B, 0x77, 0xBB, 0xB6, 0x96, 0x55, 0x55, 0x54, 0x44, 0x44, 0x33, 0x43, + 0x33, 0x33, 0x45, 0x34, 0x44, 0x68, 0x57, 0x78, 0x86, 0x50, 0x00, 0x00, + }, + }, + { + { + 0x4A, 0xAA, 0xAA, 0x9A, 0x44, 0x44, 0x45, 0x23, 0x24, 0x22, 0xA3, 0x3A, + 0x44, 0x99, 0x99, 0x9A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0x45, 0x34, 0x94, 0x4A, 0x4A, 0x32, 0x23, 0x32, 0x24, 0x4A, 0xAA, + 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0xAA, 0xAA, 0xAA, 0x4A, 0xA4, 0x44, 0x21, 0x43, 0x32, 0x23, 0x5A, + 0xAA, 0xAA, 0x99, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x7D, 0x8D, 0x74, 0x21, 0x11, 0x35, 0x7D, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE9, 0x64, 0x32, 0x01, 0x57, + 0xE8, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xE9, 0x55, 0x10, 0x27, 0x98, 0x65, 0x48, 0xAE, 0x99, 0x88, + 0x77, 0x87, 0x79, 0x89, 0xEA, 0xEE, 0xAE, 0xEE, 0xEE, 0xE0, 0x00, 0x00, + }, + { + 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB6, 0x45, 0x11, 0x13, + 0x44, 0x3B, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xC0, 0x00, 0x00, + }, + { + 0xBB, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x5A, 0x31, 0x12, + 0x23, 0x34, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xB0, 0x00, 0x00, + }, + { + 0xBB, 0xBB, 0xBB, 0xAB, 0xBB, 0xBB, 0xAA, 0xAB, 0xBB, 0xBB, 0xB5, 0x55, + 0x64, 0x22, 0x24, 0x55, 0x32, 0x14, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xAA, 0xAA, 0xA9, 0x9A, 0xAA, 0xA9, 0x99, 0x9A, 0x4A, 0xAA, 0xA3, 0x33, + 0x32, 0x34, 0x35, 0x44, 0x42, 0x24, 0xA4, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0x9A, 0x99, 0x9A, 0xA9, 0x54, 0x94, 0x95, 0x44, 0x53, 0x34, 0x53, + 0x23, 0x34, 0x34, 0x45, 0x33, 0x4A, 0x99, 0x99, 0xA9, 0xA0, 0x00, 0x00, + }, + }, + }, + { + { + { + 0x57, 0xAB, 0x66, 0x52, 0x12, 0x44, 0x45, 0x43, 0x33, 0x45, 0x77, 0xA6, + 0x77, 0xA7, 0xA7, 0x65, 0x77, 0xBB, 0xB7, 0xBB, 0x7B, 0xB0, 0x00, 0x00, + }, + { + 0xBB, 0x5B, 0xBB, 0x5B, 0xBB, 0x21, 0x22, 0x45, 0x62, 0x26, 0x56, 0xBB, + 0xBB, 0xBA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xAA, 0x3A, 0x99, 0x93, 0x19, 0x99, 0x99, 0x99, 0x99, 0x24, 0x19, 0x33, + 0x99, 0x93, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xA0, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x66, 0x67, 0x76, 0x66, 0x66, 0x67, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x10, 0x77, 0x76, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x66, 0x67, 0x76, 0x66, 0x66, 0x67, 0x77, 0x66, 0x66, 0x66, + 0x61, 0x66, 0x66, 0x67, 0x07, 0x76, 0x77, 0x77, 0x77, 0x70, 0x00, 0x00, + }, + { + 0xDD, 0xDD, 0xD6, 0xCD, 0xDD, 0xD9, 0x88, 0xC9, 0x64, 0x76, 0x34, 0x42, + 0x12, 0x54, 0x53, 0x34, 0x54, 0x56, 0x66, 0x79, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0x88, 0x78, 0x77, 0x78, 0x77, 0x77, 0x77, 0x78, 0x87, 0x07, 0x77, 0x77, + 0x21, 0x77, 0x77, 0x78, 0x88, 0x87, 0x87, 0x88, 0x88, 0x80, 0x00, 0x00, + }, + { + 0xAA, 0x9A, 0x99, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x01, 0x99, 0x99, + 0x43, 0x99, 0x34, 0x99, 0x94, 0x99, 0x99, 0x99, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x88, 0x88, 0x88, 0x89, 0x88, 0x82, 0x88, 0x21, + 0x82, 0x82, 0x83, 0x88, 0x82, 0x88, 0x88, 0x88, 0x99, 0x90, 0x00, 0x00, + }, + { + 0xDD, 0xDD, 0xDD, 0xCD, 0xDD, 0xDD, 0xCC, 0xCD, 0xDD, 0xDD, 0xD6, 0x74, + 0x56, 0x64, 0x20, 0x54, 0x42, 0x38, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0x79, 0x87, 0x96, 0x76, 0x76, 0x55, 0x66, 0x44, 0x55, 0x44, 0x55, 0x32, + 0x24, 0x88, 0x62, 0x55, 0x45, 0x43, 0x47, 0x66, 0x76, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x57, 0x66, 0x65, 0x54, 0x43, 0x34, 0x33, 0x33, 0x33, 0x33, 0x44, 0x45, + 0x55, 0x66, 0x77, 0x77, 0x77, 0x77, 0x98, 0x88, 0x79, 0x60, 0x00, 0x00, + }, + { + 0x88, 0x98, 0x8D, 0x65, 0x66, 0x32, 0x33, 0x22, 0x23, 0x33, 0x45, 0x67, + 0x78, 0x68, 0x8D, 0xCD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0x8D, 0xCD, 0xDC, 0xC5, 0x56, 0x46, 0x45, 0x54, 0x22, 0x22, 0x22, 0x45, + 0x57, 0x6C, 0xCC, 0xCD, 0xDD, 0xDD, 0xDD, 0xDC, 0xCC, 0xD0, 0x00, 0x00, + }, + { + 0xCC, 0xCC, 0xCB, 0xBC, 0xCC, 0xC7, 0xB5, 0x54, 0x12, 0x33, 0x22, 0x25, + 0x56, 0xB6, 0x7B, 0xB7, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0xBB, 0xAB, 0xBA, 0xAB, 0xBB, 0xA5, 0xA5, 0x55, 0x21, 0x2B, 0x33, 0x23, + 0x44, 0x55, 0xA6, 0x5B, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xAC, 0xAB, 0xC6, 0x66, 0x87, 0x87, 0x77, 0x98, 0x66, 0x54, 0x43, 0x43, + 0x33, 0x32, 0x33, 0x33, 0x44, 0x45, 0x66, 0x68, 0x79, 0xA0, 0x00, 0x00, + }, + { + 0xBB, 0xBB, 0xBB, 0xAB, 0xBB, 0xBB, 0xBA, 0x4B, 0x43, 0x22, 0x22, 0x32, + 0x44, 0x34, 0xA5, 0xA6, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xBB, 0xAB, 0xAA, 0xAB, 0xBA, 0xAA, 0xA6, 0x65, 0x54, 0x43, 0x21, 0x23, + 0x34, 0x34, 0x55, 0x56, 0x6B, 0xBB, 0xB6, 0xBA, 0xBA, 0xB0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xDC, 0xCD, 0xDD, 0xCC, 0xCC, 0xC6, 0x66, 0x44, 0x43, 0x32, + 0x21, 0x25, 0x65, 0x46, 0x54, 0x8D, 0xDD, 0xDC, 0xD7, 0xC0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xEE, 0xEF, 0xEE, 0xEE, 0xEE, 0x9A, 0xF7, 0x66, 0x55, 0x43, + 0x33, 0x22, 0x22, 0x33, 0x34, 0x78, 0x98, 0xEE, 0xFE, 0x90, 0x00, 0x00, + }, + { + 0x57, 0x67, 0x66, 0x76, 0x65, 0x55, 0x44, 0x54, 0x44, 0x43, 0x43, 0x34, + 0x43, 0x44, 0x44, 0x44, 0x45, 0x45, 0x55, 0x67, 0x77, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x78, 0x88, 0x76, 0x66, 0x55, 0x54, 0x44, 0x33, 0x22, 0x23, 0x33, 0x44, + 0x55, 0x67, 0x67, 0x78, 0x98, 0x98, 0x99, 0x9A, 0xA9, 0x90, 0x00, 0x00, + }, + { + 0x99, 0xAA, 0xAB, 0x97, 0x65, 0x55, 0x44, 0x32, 0x22, 0x22, 0x33, 0x45, + 0x67, 0x89, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFC, 0xBB, 0xA8, 0x88, 0x77, 0x76, 0x54, 0x32, 0x11, 0x23, 0x46, + 0x77, 0x8A, 0xF8, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xED, 0xDE, 0xE9, 0xDD, 0x77, 0x65, 0x43, 0x21, 0x12, 0x34, + 0x57, 0x7D, 0x78, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE0, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xE7, 0x7D, 0x96, 0x54, 0x22, 0x11, 0x24, + 0x56, 0x87, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE0, 0x00, 0x00, + }, + { + 0xCB, 0xAA, 0x97, 0x65, 0x44, 0x45, 0x77, 0x76, 0x66, 0x55, 0x44, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x44, 0x55, 0x68, 0x99, 0x9A, 0xC0, 0x00, 0x00, + }, + { + 0xDD, 0xDD, 0xDD, 0x7D, 0xDD, 0xDC, 0xCC, 0x66, 0x66, 0x43, 0x11, 0x22, + 0x34, 0x56, 0x8C, 0xCD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xFE, 0xEF, 0xFF, 0xEE, 0xE9, 0x88, 0x76, 0x54, 0x31, 0x11, + 0x34, 0x57, 0x77, 0x8F, 0xAF, 0xFF, 0xFF, 0xFE, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xFE, 0xEE, 0xEE, 0xEA, 0xAE, 0xEE, 0xA9, 0xE9, 0x87, 0x65, 0x43, 0x11, + 0x22, 0x35, 0x56, 0x66, 0x88, 0x9A, 0xEE, 0xEA, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEA, 0xFF, 0xFB, 0xEA, 0x98, 0x76, 0x55, 0x43, 0x22, + 0x22, 0x33, 0x33, 0x44, 0x46, 0x78, 0xAA, 0xFF, 0xFB, 0xB0, 0x00, 0x00, + }, + { + 0x79, 0x99, 0x77, 0x77, 0x66, 0x55, 0x54, 0x44, 0x43, 0x43, 0x33, 0x33, + 0x33, 0x34, 0x44, 0x55, 0x55, 0x66, 0x66, 0x79, 0x99, 0x80, 0x00, 0x00, + }, + }, + { + { + 0x68, 0x87, 0x77, 0x66, 0x55, 0x55, 0x54, 0x43, 0x32, 0x22, 0x33, 0x34, + 0x45, 0x66, 0x77, 0x78, 0x88, 0x89, 0x98, 0x88, 0x88, 0x60, 0x00, 0x00, + }, + { + 0xAA, 0xAB, 0xAB, 0xA9, 0x88, 0x66, 0x65, 0x43, 0x22, 0x21, 0x23, 0x46, + 0x78, 0xA9, 0xBF, 0xEF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFD, 0xFF, 0xFF, 0xBC, 0x99, 0x98, 0x76, 0x65, 0x42, 0x21, 0x12, 0x46, + 0x67, 0x99, 0xFF, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFA, 0xB9, 0x87, 0x65, 0x31, 0x02, 0x56, + 0x79, 0x9A, 0xAF, 0xEA, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0x9B, 0xAE, 0xBE, 0x9B, 0xBB, 0xAB, 0xAA, 0x98, 0x76, 0x52, 0x01, 0x35, + 0x88, 0x99, 0x9A, 0xAC, 0xBA, 0xBB, 0xEA, 0xBA, 0xEA, 0xB0, 0x00, 0x00, + }, + { + 0xCC, 0xBC, 0xA7, 0x65, 0x21, 0x46, 0x88, 0x87, 0x77, 0x65, 0x44, 0x44, + 0x43, 0x33, 0x44, 0x45, 0x55, 0x56, 0x78, 0x9A, 0x9B, 0xC0, 0x00, 0x00, + }, + { + 0x9E, 0x9E, 0xA9, 0xAB, 0xAA, 0xA9, 0x9D, 0x99, 0x87, 0x65, 0x10, 0x23, + 0x68, 0x88, 0x98, 0x9A, 0xA9, 0xAA, 0xDA, 0xAD, 0xAA, 0x90, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, 0xFC, 0xBB, 0xA9, 0xA7, 0x65, 0x30, 0x12, + 0x56, 0x78, 0x9A, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xBA, 0x98, 0x76, 0x41, 0x11, + 0x24, 0x47, 0x77, 0x89, 0xBB, 0xED, 0xCF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xCF, 0xFF, 0xEF, 0xCF, 0xCE, 0x9B, 0xA9, 0x87, 0x65, 0x42, 0x11, + 0x23, 0x44, 0x55, 0x66, 0x67, 0x9A, 0xAB, 0xCF, 0xCC, 0xD0, 0x00, 0x00, + }, + { + 0x68, 0x78, 0x77, 0x76, 0x66, 0x55, 0x55, 0x54, 0x44, 0x33, 0x33, 0x32, + 0x33, 0x34, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 0x88, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x68, 0x77, 0x76, 0x66, 0x55, 0x55, 0x54, 0x44, 0x32, 0x22, 0x33, 0x34, + 0x55, 0x56, 0x66, 0x66, 0x67, 0x78, 0x88, 0x99, 0x99, 0x50, 0x00, 0x00, + }, + { + 0xCB, 0xCA, 0xAA, 0xA9, 0x97, 0x77, 0x66, 0x54, 0x32, 0x21, 0x13, 0x46, + 0x79, 0xAA, 0xAB, 0xBF, 0xCD, 0xFD, 0xCF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFC, 0xFF, 0xBB, 0xA9, 0xA8, 0x87, 0x65, 0x31, 0x02, 0x56, + 0x89, 0xAB, 0xBB, 0xBB, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFB, 0xFF, 0xCD, 0xCF, 0x99, 0x87, 0x65, 0x42, 0x01, 0x45, + 0x67, 0x9A, 0xBB, 0xAF, 0xBD, 0xBF, 0xFC, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xF9, 0xA8, 0x86, 0x42, 0x01, 0x36, + 0x78, 0x8A, 0xBF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0x00, 0x00, + }, + { + 0xCF, 0xDB, 0xBA, 0x85, 0x10, 0x47, 0x89, 0x99, 0x99, 0x87, 0x66, 0x65, + 0x55, 0x55, 0x55, 0x56, 0x66, 0x77, 0x89, 0xAC, 0xCE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xBF, 0xBB, 0xFF, 0x98, 0x63, 0x10, 0x24, + 0x59, 0x99, 0xBF, 0xFB, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xBB, 0xAF, 0x97, 0x65, 0x20, 0x13, + 0x56, 0x78, 0x99, 0xAB, 0xFD, 0xAF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xBB, 0xAA, 0x97, 0x65, 0x30, 0x13, + 0x44, 0x56, 0x88, 0x89, 0xA9, 0xBF, 0xFF, 0xCF, 0xFC, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFD, 0xFF, 0xFA, 0xBA, 0xBA, 0xB9, 0x87, 0x65, 0x32, 0x11, + 0x23, 0x45, 0x56, 0x67, 0x77, 0x9A, 0xBA, 0xBF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0x57, 0x78, 0x77, 0x66, 0x66, 0x55, 0x55, 0x44, 0x44, 0x43, 0x33, 0x23, + 0x33, 0x44, 0x45, 0x55, 0x56, 0x66, 0x66, 0x77, 0x78, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x68, 0x87, 0x87, 0x77, 0x66, 0x55, 0x54, 0x44, 0x32, 0x22, 0x23, 0x44, + 0x45, 0x56, 0x66, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x00, 0x00, + }, + { + 0x9A, 0xB9, 0xA9, 0xA8, 0x87, 0x76, 0x65, 0x54, 0x43, 0x21, 0x12, 0x45, + 0x68, 0x88, 0xAA, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFC, 0xCF, 0xBA, 0x98, 0x77, 0x65, 0x31, 0x02, 0x56, + 0x89, 0xAC, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x87, 0x76, 0x42, 0x01, 0x36, + 0x89, 0xAA, 0xBD, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xBF, 0xFF, 0xEF, 0xBF, 0xAC, 0x99, 0x87, 0x42, 0x01, 0x35, + 0x79, 0xAA, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xCD, 0xCC, 0xB9, 0x74, 0x10, 0x46, 0x8A, 0xA9, 0x99, 0x98, 0x77, 0x66, + 0x66, 0x55, 0x55, 0x55, 0x66, 0x67, 0x89, 0x9A, 0xAB, 0xD0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xDA, 0xA8, 0x53, 0x10, 0x24, + 0x68, 0x9A, 0xAE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFB, 0x98, 0x74, 0x10, 0x23, + 0x57, 0x89, 0xAB, 0xBC, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xBA, 0x98, 0x65, 0x20, 0x13, + 0x56, 0x78, 0x89, 0x9A, 0xAC, 0xEF, 0xFB, 0xFF, 0xDF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0x99, 0x86, 0x54, 0x21, 0x12, + 0x34, 0x45, 0x56, 0x67, 0x67, 0x99, 0xAB, 0xEB, 0xFF, 0xB0, 0x00, 0x00, + }, + { + 0x57, 0x87, 0x77, 0x77, 0x66, 0x66, 0x65, 0x55, 0x44, 0x43, 0x32, 0x22, + 0x33, 0x44, 0x55, 0x56, 0x67, 0x77, 0x77, 0x88, 0x99, 0x70, 0x00, 0x00, + }, + }, + { + { + 0x78, 0x88, 0x88, 0x77, 0x76, 0x65, 0x54, 0x44, 0x33, 0x32, 0x12, 0x34, + 0x46, 0x78, 0x99, 0x9A, 0xBA, 0xAC, 0xAB, 0xCB, 0xAA, 0x90, 0x00, 0x00, + }, + { + 0x9A, 0x98, 0x88, 0x98, 0x87, 0x77, 0x65, 0x54, 0x43, 0x21, 0x12, 0x45, + 0x67, 0x8B, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xBD, 0xA9, 0x99, 0x87, 0x77, 0x55, 0x41, 0x02, 0x46, + 0x79, 0xAB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFE, 0xFF, 0xFF, 0xDB, 0x9A, 0xBA, 0x98, 0x76, 0x42, 0x01, 0x36, + 0x79, 0xBB, 0xCB, 0xFC, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFA, 0x9A, 0xAA, 0x87, 0x42, 0x01, 0x35, + 0x78, 0xDA, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xBC, 0xCC, 0xA9, 0x74, 0x10, 0x36, 0x8A, 0xAA, 0xA9, 0x99, 0x88, 0x77, + 0x76, 0x66, 0x65, 0x66, 0x55, 0x66, 0x78, 0x88, 0xAB, 0xC0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xAA, 0x97, 0x63, 0x10, 0x24, + 0x67, 0x88, 0x9B, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFC, 0xBB, 0x97, 0x64, 0x10, 0x23, + 0x67, 0x88, 0xAA, 0xAB, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xBD, 0xA7, 0x64, 0x20, 0x14, + 0x55, 0x77, 0x78, 0x8A, 0xAA, 0xAB, 0xFD, 0xCC, 0xBF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x76, 0x54, 0x21, 0x12, + 0x34, 0x45, 0x56, 0x67, 0x77, 0x8A, 0xAA, 0x99, 0xBA, 0x90, 0x00, 0x00, + }, + { + 0x68, 0x88, 0x77, 0x66, 0x66, 0x55, 0x55, 0x55, 0x54, 0x43, 0x22, 0x23, + 0x34, 0x44, 0x44, 0x56, 0x77, 0x77, 0x78, 0x99, 0x99, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x45, 0x56, 0x66, 0x65, 0x55, 0x54, 0x44, 0x44, 0x44, 0x42, 0x12, 0x35, + 0x68, 0x8E, 0x9A, 0xBC, 0xEB, 0xBB, 0xEB, 0xBB, 0xBE, 0xB0, 0x00, 0x00, + }, + { + 0x87, 0x77, 0x76, 0x76, 0x66, 0x66, 0x55, 0x54, 0x43, 0x31, 0x12, 0x45, + 0x56, 0xA9, 0xEE, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xAF, 0x98, 0x97, 0x78, 0x75, 0x55, 0x44, 0x32, 0x02, 0x45, + 0x68, 0x8E, 0x9C, 0xEF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBA, 0x98, 0x77, 0x65, 0x42, 0x01, 0x45, + 0x69, 0x9C, 0x9B, 0xDF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xCA, 0xAA, 0xA8, 0x76, 0x52, 0x01, 0x35, + 0x67, 0x8A, 0xEA, 0xBF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xA9, 0xAB, 0x98, 0x74, 0x10, 0x36, 0x89, 0x99, 0x99, 0x88, 0x87, 0x87, + 0x76, 0x66, 0x66, 0x55, 0x56, 0x67, 0x79, 0x9B, 0x9B, 0xB0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x88, 0x87, 0x54, 0x10, 0x24, + 0x56, 0x77, 0x89, 0xBF, 0xFF, 0xEC, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xDC, 0xFF, 0xFB, 0xDB, 0xB9, 0x86, 0x53, 0x20, 0x23, + 0x44, 0x56, 0x88, 0x78, 0xAA, 0xFF, 0xAB, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xBF, 0xFA, 0x97, 0x64, 0x20, 0x23, + 0x44, 0x55, 0x56, 0x67, 0x77, 0x89, 0x9B, 0xB9, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xD9, 0x75, 0x43, 0x21, 0x23, + 0x34, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x78, 0x8A, 0x80, 0x00, 0x00, + }, + { + 0x79, 0x89, 0x98, 0x88, 0x77, 0x77, 0x54, 0x44, 0x44, 0x43, 0x22, 0x33, + 0x33, 0x44, 0x45, 0x45, 0x66, 0x68, 0x77, 0x98, 0x88, 0x60, 0x00, 0x00, + }, + }, + { + { + 0x25, 0x45, 0x57, 0x45, 0x45, 0x55, 0x43, 0x33, 0x33, 0x33, 0x34, 0x44, + 0x55, 0xBB, 0xBB, 0x6B, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0x86, 0x76, 0x75, 0x55, 0x55, 0x65, 0x74, 0x44, 0x33, 0x32, 0x12, 0x35, + 0x6C, 0xCC, 0xCC, 0xCD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xD0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xDD, 0x8E, 0x76, 0x55, 0x43, 0x44, 0x32, 0x32, 0x12, 0x46, + 0x87, 0x99, 0x9D, 0xDE, 0xEE, 0xEE, 0xDD, 0xDD, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, 0xA9, 0x96, 0x55, 0x43, 0x32, 0x02, 0x45, + 0x88, 0xEE, 0xE9, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xAF, 0x89, 0x66, 0x42, 0x01, 0x36, + 0xD9, 0x8A, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xAA, 0xEA, 0xF9, 0x74, 0x10, 0x35, 0x79, 0x98, 0x87, 0x66, 0x66, 0x55, + 0x56, 0x67, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xFC, 0xEE, 0xB0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xE9, 0x97, 0xF7, 0x65, 0x20, 0x13, + 0x56, 0x79, 0xEA, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xED, 0xDE, 0xEE, 0xED, 0xDD, 0xDE, 0x75, 0x63, 0x11, 0x22, + 0x34, 0x45, 0x67, 0x78, 0x9E, 0xEE, 0xEE, 0xEE, 0xEE, 0xE0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xDD, 0xDE, 0xED, 0xD8, 0xDD, 0xDE, 0x87, 0x54, 0x20, 0x23, + 0x46, 0x46, 0x56, 0x67, 0x76, 0x79, 0x8E, 0xED, 0xED, 0xE0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xDD, 0xDE, 0xDD, 0xDD, 0xDD, 0xD9, 0x98, 0x54, 0x32, 0x23, + 0x45, 0x44, 0x34, 0x43, 0x23, 0x66, 0x36, 0xD8, 0xDD, 0x90, 0x00, 0x00, + }, + { + 0x7B, 0x7B, 0xA7, 0x77, 0x6A, 0x57, 0x56, 0x55, 0x45, 0x43, 0x33, 0x33, + 0x33, 0x33, 0x44, 0x43, 0x35, 0xBB, 0xBA, 0xAA, 0xB7, 0x50, 0x00, 0x00, + }, + }, + { + { + 0x24, 0xA3, 0x44, 0x44, 0xAA, 0x49, 0x34, 0x43, 0x24, 0x42, 0x35, 0xA9, + 0x99, 0x49, 0x99, 0x9A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0x99, 0x39, 0x94, 0x94, 0x39, 0x43, 0x92, 0x33, 0x29, 0x22, 0x39, 0x99, + 0x99, 0x99, 0x88, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x90, 0x00, 0x00, + }, + { + 0x99, 0x99, 0x99, 0x99, 0x49, 0x49, 0x33, 0x34, 0x33, 0x21, 0x23, 0x99, + 0x99, 0x99, 0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x90, 0x00, 0x00, + }, + { + 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC6, 0x32, 0x21, 0x12, 0x45, + 0xC7, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xD0, 0x00, 0x00, + }, + { + 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD7, 0xDD, 0x75, 0x42, 0x01, 0x38, + 0xDD, 0x7D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xCC, 0x8C, 0x87, 0x64, 0x10, 0x37, 0x86, 0x66, 0x67, 0x69, 0x78, 0x77, + 0x76, 0x66, 0x66, 0x67, 0x68, 0x77, 0x88, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0xBB, 0xAB, 0xAA, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA4, 0x20, 0x22, + 0x44, 0xA5, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBA, 0xB0, 0x00, 0x00, + }, + { + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x4B, 0x33, 0x03, + 0x23, 0x46, 0x4B, 0x5B, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xBB, 0xBB, 0xBB, 0xAB, 0xBB, 0xBB, 0xAA, 0xAB, 0xBB, 0xBB, 0xB2, 0x43, + 0x44, 0x32, 0x13, 0x46, 0x34, 0x35, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA9, 0x9A, 0xAA, 0xAA, 0xA4, 0x23, + 0x32, 0xA5, 0x32, 0xA2, 0x24, 0xA3, 0xAA, 0x4A, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xA9, 0x59, 0x99, 0x99, 0x99, 0x54, 0x49, 0x45, 0x55, 0x45, 0x43, 0x39, + 0x52, 0x33, 0x43, 0x44, 0x25, 0x59, 0x59, 0x99, 0x59, 0xA0, 0x00, 0x00, + }, + }, + }, + { + { + { + 0x58, 0x76, 0x5B, 0x53, 0x21, 0x25, 0x54, 0x43, 0x33, 0x48, 0x88, 0x56, + 0x67, 0x6B, 0x87, 0xBC, 0x7C, 0x8C, 0xCC, 0xCC, 0x8C, 0xB0, 0x00, 0x00, + }, + { + 0xCC, 0xCC, 0x6C, 0x4C, 0xCC, 0x12, 0x12, 0x45, 0x53, 0x35, 0x7C, 0xCC, + 0xCC, 0xCC, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0xAA, 0xAA, 0xA4, 0xA1, 0x44, 0x55, 0xA9, 0x9A, 0xAA, 0xA2, 0x22, 0x24, + 0xA5, 0xA4, 0x49, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0x99, 0x88, 0x33, 0x88, 0x88, 0x88, 0x88, 0x28, 0x88, 0x88, 0x88, 0x21, + 0x33, 0x88, 0x83, 0x82, 0x88, 0x88, 0x88, 0x88, 0x89, 0x90, 0x00, 0x00, + }, + { + 0x66, 0x56, 0x55, 0x56, 0x65, 0x55, 0x55, 0x56, 0x06, 0x65, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x56, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x00, 0x00, + }, + { + 0xEE, 0x9D, 0xA6, 0x9D, 0xDA, 0xD9, 0x97, 0x55, 0x42, 0x64, 0x43, 0x32, + 0x24, 0x44, 0x33, 0x44, 0x66, 0x55, 0x58, 0x7D, 0xDD, 0xA0, 0x00, 0x00, + }, + { + 0x88, 0x78, 0x77, 0x78, 0x77, 0x77, 0x77, 0x78, 0x82, 0x07, 0x77, 0x77, + 0x72, 0x27, 0x77, 0x78, 0x87, 0x77, 0x87, 0x88, 0x88, 0x80, 0x00, 0x00, + }, + { + 0xBB, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x44, 0x01, 0x3A, 0xAA, + 0x4A, 0x4A, 0x45, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xB0, 0x00, 0x00, + }, + { + 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x89, 0x99, 0x92, 0x39, 0x21, + 0x49, 0x43, 0x33, 0x99, 0x34, 0x39, 0x99, 0x99, 0x99, 0x90, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xED, 0xDE, 0xEE, 0xED, 0xDD, 0xDE, 0xEE, 0xEE, 0x97, 0x75, + 0x55, 0x75, 0x20, 0x34, 0x63, 0x26, 0x8E, 0xEE, 0xEE, 0xE0, 0x00, 0x00, + }, + { + 0x69, 0xB8, 0x77, 0x8B, 0x85, 0x56, 0x55, 0x44, 0x65, 0x44, 0x33, 0x32, + 0x23, 0x67, 0xA4, 0x74, 0x45, 0x44, 0x45, 0x68, 0x86, 0x70, 0x00, 0x00, + }, + }, + { + { + 0x67, 0x76, 0x66, 0x54, 0x43, 0x43, 0x33, 0x33, 0x33, 0x33, 0x44, 0x44, + 0x55, 0x66, 0x67, 0x67, 0x77, 0x77, 0x89, 0x89, 0x99, 0x60, 0x00, 0x00, + }, + { + 0xA9, 0x99, 0x99, 0x66, 0x66, 0x43, 0x33, 0x22, 0x22, 0x33, 0x34, 0x57, + 0x78, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFE, 0xE9, 0xE9, 0x87, 0x65, 0x55, 0x44, 0x44, 0x32, 0x22, 0x22, 0x34, + 0x56, 0x79, 0x8E, 0xEA, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xDD, 0xD8, 0xDD, 0x75, 0x54, 0x54, 0x33, 0x44, 0x31, 0x13, + 0x45, 0x66, 0x88, 0x89, 0x8E, 0xDD, 0xDD, 0xDD, 0xED, 0xE0, 0x00, 0x00, + }, + { + 0xCC, 0xBC, 0xBB, 0xBC, 0xCB, 0x75, 0x65, 0x45, 0x32, 0x24, 0x43, 0x12, + 0x46, 0x54, 0x77, 0xBC, 0xCC, 0xCC, 0xCB, 0xCB, 0xCB, 0xC0, 0x00, 0x00, + }, + { + 0xA9, 0x8B, 0x97, 0x56, 0x88, 0x76, 0x77, 0x66, 0x55, 0x44, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x45, 0x56, 0x67, 0x8A, 0xCA, 0xC0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xCC, 0xCD, 0xDC, 0xCC, 0x68, 0x55, 0x53, 0x21, 0x23, 0x33, + 0x33, 0x45, 0x77, 0x67, 0xDD, 0xDD, 0xDD, 0xDC, 0xDC, 0xD0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xDD, 0xDE, 0xE9, 0x8D, 0xD8, 0x67, 0x44, 0x32, 0x22, 0x22, + 0x33, 0x44, 0x46, 0x87, 0xEE, 0xEE, 0xEE, 0xDD, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xEE, 0xEF, 0xFE, 0xEE, 0xE9, 0x78, 0x67, 0x54, 0x43, 0x22, + 0x12, 0x35, 0x53, 0x55, 0x56, 0x7A, 0xFE, 0xEE, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xFB, 0x87, 0x66, 0x54, 0x33, + 0x33, 0x22, 0x22, 0x33, 0x46, 0x67, 0x7A, 0xCF, 0xCF, 0xF0, 0x00, 0x00, + }, + { + 0x67, 0x77, 0x77, 0x66, 0x66, 0x55, 0x55, 0x44, 0x43, 0x44, 0x33, 0x34, + 0x43, 0x44, 0x43, 0x44, 0x44, 0x55, 0x66, 0x76, 0x88, 0x70, 0x00, 0x00, + }, + }, + { + { + 0x78, 0x77, 0x76, 0x66, 0x55, 0x44, 0x44, 0x33, 0x33, 0x22, 0x33, 0x34, + 0x45, 0x67, 0x78, 0x88, 0x88, 0x99, 0x89, 0xA9, 0xA9, 0x70, 0x00, 0x00, + }, + { + 0xA9, 0x9B, 0x99, 0x87, 0x77, 0x54, 0x44, 0x33, 0x22, 0x22, 0x23, 0x45, + 0x67, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFD, 0xAA, 0x98, 0x87, 0x77, 0x65, 0x32, 0x11, 0x23, 0x44, + 0x57, 0x9A, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x88, 0x77, 0x65, 0x54, 0x31, 0x11, 0x35, + 0x57, 0x88, 0x8F, 0xDF, 0xFC, 0x9F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xEE, 0xEF, 0xFE, 0x99, 0x87, 0x77, 0x54, 0x22, 0x11, 0x24, + 0x66, 0x77, 0x78, 0xEA, 0xF9, 0xFF, 0xEE, 0xEE, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xAB, 0xAA, 0x97, 0x65, 0x44, 0x45, 0x66, 0x65, 0x54, 0x44, 0x43, 0x33, + 0x33, 0x33, 0x33, 0x44, 0x55, 0x66, 0x78, 0x8B, 0xAB, 0xB0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xED, 0xDE, 0x98, 0x8D, 0xDD, 0x67, 0x66, 0x43, 0x11, 0x22, + 0x34, 0x57, 0x77, 0x8E, 0xEE, 0xEE, 0xEE, 0xED, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xBB, 0x98, 0x66, 0x54, 0x31, 0x11, + 0x34, 0x56, 0x98, 0xBF, 0xDC, 0xBF, 0xBF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xAA, 0x88, 0x66, 0x32, 0x11, + 0x23, 0x35, 0x66, 0x77, 0x99, 0xCE, 0xFE, 0xCD, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCA, 0xA9, 0x76, 0x54, 0x42, 0x22, + 0x22, 0x33, 0x34, 0x55, 0x56, 0x77, 0x9B, 0xBF, 0xFF, 0xC0, 0x00, 0x00, + }, + { + 0x69, 0x88, 0x77, 0x77, 0x76, 0x65, 0x55, 0x44, 0x43, 0x43, 0x33, 0x33, + 0x33, 0x34, 0x44, 0x44, 0x55, 0x67, 0x77, 0x88, 0x89, 0x70, 0x00, 0x00, + }, + }, + { + { + 0x79, 0x98, 0x87, 0x77, 0x66, 0x55, 0x44, 0x43, 0x33, 0x22, 0x23, 0x33, + 0x45, 0x66, 0x77, 0x88, 0x89, 0x99, 0x9A, 0xA9, 0x99, 0x70, 0x00, 0x00, + }, + { + 0xBB, 0xFB, 0xBA, 0xA9, 0x98, 0x76, 0x65, 0x44, 0x32, 0x21, 0x22, 0x35, + 0x79, 0xAE, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xCF, 0xFA, 0xAA, 0x99, 0x88, 0x77, 0x65, 0x33, 0x21, 0x12, 0x44, + 0x57, 0x89, 0xAB, 0xBE, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xBF, 0xDB, 0xA9, 0x99, 0x86, 0x65, 0x41, 0x02, 0x45, + 0x78, 0x89, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0xA9, 0x98, 0x76, 0x52, 0x01, 0x35, + 0x68, 0x89, 0x9E, 0xEF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, + }, + { + 0xDB, 0xCA, 0x98, 0x75, 0x21, 0x46, 0x77, 0x76, 0x66, 0x54, 0x44, 0x44, + 0x33, 0x34, 0x44, 0x45, 0x66, 0x77, 0x89, 0xAC, 0xCB, 0xD0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0x98, 0x77, 0x65, 0x10, 0x23, + 0x56, 0x89, 0xAA, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBB, 0xCA, 0x87, 0x65, 0x30, 0x12, + 0x56, 0x78, 0xA9, 0xBA, 0xFD, 0xCF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xED, 0xAA, 0xA9, 0x97, 0x64, 0x31, 0x12, + 0x23, 0x45, 0x56, 0x78, 0xA9, 0xAC, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xCB, 0xA8, 0x65, 0x54, 0x32, 0x12, + 0x23, 0x34, 0x45, 0x56, 0x77, 0x88, 0xAC, 0xDF, 0xDF, 0xE0, 0x00, 0x00, + }, + { + 0x68, 0x98, 0x88, 0x77, 0x77, 0x66, 0x55, 0x54, 0x44, 0x43, 0x32, 0x22, + 0x33, 0x44, 0x55, 0x56, 0x66, 0x77, 0x78, 0x89, 0x99, 0x70, 0x00, 0x00, + }, + }, + { + { + 0x8A, 0xA9, 0x88, 0x87, 0x66, 0x65, 0x54, 0x43, 0x33, 0x22, 0x23, 0x33, + 0x45, 0x55, 0x67, 0x78, 0x88, 0x88, 0x88, 0x99, 0x99, 0x60, 0x00, 0x00, + }, + { + 0xCF, 0xBF, 0xCA, 0xAA, 0x98, 0x87, 0x76, 0x54, 0x33, 0x21, 0x12, 0x45, + 0x78, 0x8A, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xBE, 0xBA, 0x99, 0x77, 0x65, 0x31, 0x02, 0x56, + 0x89, 0x9B, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBB, 0x97, 0x76, 0x32, 0x01, 0x46, + 0x88, 0x9B, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFC, 0xA8, 0x97, 0x42, 0x01, 0x35, + 0x78, 0x9A, 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xDC, 0xCB, 0xB9, 0x75, 0x10, 0x47, 0x89, 0x89, 0x88, 0x76, 0x66, 0x55, + 0x55, 0x55, 0x55, 0x66, 0x77, 0x78, 0x9A, 0xAC, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xCA, 0xA9, 0x87, 0x63, 0x10, 0x24, + 0x67, 0x8A, 0xCA, 0xFF, 0xFE, 0xCF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xAA, 0x98, 0x74, 0x20, 0x13, + 0x57, 0x8A, 0x9E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xA9, 0x87, 0x65, 0x30, 0x13, + 0x44, 0x56, 0x78, 0x9A, 0xBE, 0xEF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0x98, 0x65, 0x54, 0x31, 0x12, + 0x33, 0x44, 0x55, 0x67, 0x78, 0x9A, 0xAC, 0xFC, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0x68, 0x88, 0x87, 0x77, 0x77, 0x76, 0x55, 0x54, 0x44, 0x43, 0x32, 0x22, + 0x33, 0x44, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9A, 0xBB, 0x90, 0x00, 0x00, + }, + }, + { + { + 0x8A, 0x99, 0x88, 0x77, 0x76, 0x66, 0x55, 0x43, 0x33, 0x22, 0x22, 0x33, + 0x45, 0x67, 0x77, 0x88, 0x88, 0x99, 0xAA, 0x9A, 0xAA, 0x80, 0x00, 0x00, + }, + { + 0xBC, 0xAA, 0xAB, 0xA9, 0x98, 0x87, 0x66, 0x54, 0x33, 0x21, 0x12, 0x45, + 0x89, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xEF, 0xFC, 0xCC, 0xBA, 0x98, 0x87, 0x65, 0x31, 0x02, 0x56, + 0x79, 0xBB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFD, 0xBA, 0x98, 0x76, 0x42, 0x01, 0x36, + 0x78, 0x9A, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xBB, 0xA9, 0x87, 0x42, 0x01, 0x35, + 0x78, 0xAB, 0xFB, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xDD, 0xEC, 0xC9, 0x74, 0x10, 0x47, 0x89, 0x99, 0x99, 0x87, 0x76, 0x66, + 0x55, 0x55, 0x55, 0x56, 0x67, 0x78, 0x89, 0xBC, 0xCD, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0x98, 0x63, 0x10, 0x24, + 0x58, 0x9A, 0xBF, 0xEF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDB, 0x97, 0x74, 0x10, 0x23, + 0x57, 0x9A, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0xA8, 0x65, 0x20, 0x13, + 0x56, 0x77, 0x89, 0x9B, 0xCE, 0xCF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x9A, 0xAA, 0x76, 0x54, 0x21, 0x12, + 0x34, 0x45, 0x56, 0x66, 0x78, 0x99, 0xAF, 0xEC, 0xEF, 0xB0, 0x00, 0x00, + }, + { + 0x78, 0x88, 0x87, 0x77, 0x66, 0x66, 0x65, 0x55, 0x54, 0x43, 0x22, 0x22, + 0x33, 0x44, 0x55, 0x67, 0x77, 0x88, 0x98, 0x99, 0xAA, 0x80, 0x00, 0x00, + }, + }, + { + { + 0x67, 0x77, 0x86, 0x66, 0x66, 0x65, 0x54, 0x44, 0x33, 0x32, 0x12, 0x34, + 0x57, 0x99, 0xAC, 0x9A, 0xAC, 0xFB, 0xCF, 0xEE, 0xEB, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x66, 0x55, 0x43, 0x21, 0x12, 0x35, + 0x8A, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFA, 0xDA, 0x99, 0x98, 0x77, 0x76, 0x65, 0x53, 0x32, 0x02, 0x45, + 0x67, 0x9A, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xCF, 0xFB, 0xBB, 0xE9, 0x87, 0x76, 0x42, 0x01, 0x36, + 0x89, 0xBB, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xA9, 0x76, 0x52, 0x01, 0x35, + 0x67, 0x8A, 0x9A, 0xC9, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xEC, 0xCC, 0xA9, 0x74, 0x10, 0x37, 0x88, 0x89, 0x99, 0x88, 0x87, 0x76, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x78, 0xAA, 0xFE, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xBA, 0x87, 0x64, 0x10, 0x24, + 0x46, 0x77, 0xAB, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCF, 0xFF, 0x88, 0x64, 0x10, 0x24, + 0x46, 0x78, 0x88, 0xAA, 0xBF, 0xCC, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, 0xA7, 0x65, 0x20, 0x14, + 0x55, 0x57, 0x77, 0x88, 0x9A, 0xAA, 0xBB, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF9, 0x97, 0x76, 0x53, 0x21, 0x13, + 0x34, 0x45, 0x55, 0x66, 0x66, 0x77, 0x88, 0xAA, 0xDC, 0xA0, 0x00, 0x00, + }, + { + 0x9D, 0xAC, 0xBA, 0x98, 0x88, 0x77, 0x65, 0x54, 0x54, 0x43, 0x21, 0x23, + 0x34, 0x45, 0x55, 0x66, 0x67, 0x79, 0x99, 0x9D, 0xBB, 0x80, 0x00, 0x00, + }, + }, + { + { + 0x47, 0x7C, 0x65, 0x45, 0x45, 0x45, 0x45, 0x33, 0x43, 0x22, 0x23, 0x44, + 0x57, 0x77, 0xCC, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0x89, 0x88, 0x67, 0x68, 0x67, 0x76, 0x55, 0x55, 0x43, 0x21, 0x12, 0x46, + 0x8E, 0xEA, 0xEE, 0xEF, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xF0, 0x00, 0x00, + }, + { + 0xEE, 0xDE, 0xD9, 0xD8, 0x87, 0x66, 0x64, 0x55, 0x44, 0x42, 0x02, 0x45, + 0x67, 0x8D, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xED, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFA, 0xFF, 0xCF, 0xB7, 0x98, 0x66, 0x54, 0x42, 0x01, 0x57, + 0x89, 0xFA, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xAA, 0x88, 0x76, 0x42, 0x01, 0x36, + 0x78, 0xFF, 0xFF, 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xBC, 0xAA, 0xB8, 0x75, 0x10, 0x35, 0x78, 0x88, 0x87, 0x66, 0x66, 0x55, + 0x55, 0x66, 0x77, 0x77, 0x88, 0x99, 0x9A, 0xDB, 0xBB, 0xD0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFD, 0x99, 0x87, 0x65, 0x10, 0x23, + 0x56, 0x78, 0x9E, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xFE, 0xEF, 0xFF, 0xEE, 0xE9, 0xE8, 0x65, 0x54, 0x20, 0x23, + 0x34, 0x67, 0x7A, 0x99, 0x9F, 0xF9, 0xFF, 0xFE, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xEE, 0xEF, 0xFE, 0xEE, 0xE9, 0xEF, 0x87, 0x53, 0x20, 0x23, + 0x55, 0x55, 0x56, 0x68, 0x98, 0x8A, 0x9F, 0xFE, 0xFE, 0xF0, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x8A, 0x77, 0x54, 0x31, 0x23, + 0x44, 0x34, 0x44, 0x44, 0x43, 0x45, 0x57, 0xFA, 0xFB, 0xF0, 0x00, 0x00, + }, + { + 0x7C, 0xB7, 0x8B, 0x76, 0x76, 0x66, 0x55, 0x54, 0x44, 0x43, 0x33, 0x32, + 0x33, 0x44, 0x54, 0x44, 0x44, 0x57, 0x98, 0x87, 0xCB, 0x50, 0x00, 0x00, + }, + }, + { + { + 0x46, 0xAB, 0x6A, 0x6B, 0x65, 0x54, 0x54, 0x32, 0x22, 0x32, 0x43, 0x44, + 0xA4, 0x6A, 0xAA, 0xAB, 0xBB, 0xBB, 0xBB, 0xAA, 0xAA, 0xB0, 0x00, 0x00, + }, + { + 0x67, 0x66, 0x6B, 0x6C, 0x56, 0xB5, 0x55, 0x34, 0x32, 0x21, 0x23, 0x64, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCB, 0xC0, 0x00, 0x00, + }, + { + 0xCC, 0xCC, 0xCC, 0xBC, 0x76, 0x57, 0x55, 0x54, 0x43, 0x21, 0x12, 0x46, + 0x7C, 0xBB, 0xBB, 0xBC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x77, 0x43, 0x22, 0x02, 0x57, + 0x8D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0xDD, 0xCD, 0xCC, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0x65, 0x42, 0x01, 0x3C, + 0x7C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDC, 0xD0, 0x00, 0x00, + }, + { + 0xEE, 0x8E, 0xD9, 0x75, 0x10, 0x35, 0x77, 0x66, 0x68, 0x77, 0x66, 0x65, + 0x66, 0x65, 0x66, 0x68, 0x88, 0xEE, 0xAE, 0xED, 0xDD, 0xE0, 0x00, 0x00, + }, + { + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD8, 0xDD, 0x55, 0x20, 0x14, + 0x56, 0x4D, 0x7D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD0, 0x00, 0x00, + }, + { + 0xCC, 0xCC, 0xCC, 0xBC, 0xCC, 0xCC, 0xCB, 0xBC, 0xC7, 0x63, 0x20, 0x23, + 0x44, 0x55, 0x76, 0x7C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xC0, 0x00, 0x00, + }, + { + 0xBB, 0xBB, 0xBA, 0xAB, 0xBB, 0xBA, 0xAA, 0xAB, 0xB5, 0xB6, 0x31, 0x22, + 0x34, 0x43, 0x34, 0x54, 0x45, 0x4B, 0xBB, 0xBB, 0xBB, 0xB0, 0x00, 0x00, + }, + { + 0xCC, 0xBC, 0xCB, 0xBC, 0xCB, 0xBB, 0xBB, 0xB7, 0x66, 0x55, 0x42, 0x22, + 0x23, 0x34, 0x43, 0x35, 0x54, 0x55, 0x6C, 0xCB, 0xCB, 0xC0, 0x00, 0x00, + }, + { + 0xCB, 0xBB, 0x6B, 0xB7, 0xBB, 0x6B, 0x65, 0x55, 0x34, 0x33, 0x43, 0x32, + 0x23, 0x34, 0x55, 0x44, 0x46, 0xBB, 0xBB, 0xB6, 0xBB, 0xC0, 0x00, 0x00, + }, + }, + { + { + 0x88, 0x78, 0x71, 0x78, 0x77, 0x77, 0x77, 0x78, 0x27, 0x71, 0x77, 0x17, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x77, 0x88, 0x87, 0x88, 0x80, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x88, 0x82, 0x88, 0x83, 0x83, 0x12, 0x22, 0x38, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x90, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x88, 0x88, 0x38, 0x89, 0x22, 0x11, 0x28, 0x88, + 0x88, 0x88, 0x88, 0x89, 0x98, 0x88, 0x88, 0x98, 0x98, 0x90, 0x00, 0x00, + }, + { + 0xAA, 0x9A, 0x99, 0x9A, 0x39, 0x99, 0x99, 0x33, 0x99, 0x42, 0x02, 0x99, + 0x99, 0x99, 0x99, 0x9A, 0xA9, 0x99, 0x99, 0x99, 0xA9, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0x9A, 0x99, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0xA9, 0x92, 0x01, 0x34, + 0x99, 0x99, 0x99, 0x9A, 0xA9, 0x99, 0x9A, 0xA9, 0xA9, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0xAA, 0xAA, 0xAA, 0x30, 0x4A, 0xAA, 0x9A, 0xAA, 0xA4, 0x43, 0x43, + 0x35, 0x4A, 0x3A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0xAA, 0x9A, 0x99, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0x99, 0x93, 0x11, 0x13, + 0x34, 0x99, 0x99, 0x9A, 0x99, 0x99, 0x99, 0x99, 0xA9, 0xA0, 0x00, 0x00, + }, + { + 0x99, 0x89, 0x88, 0x89, 0x88, 0x88, 0x88, 0x89, 0x88, 0x88, 0x31, 0x12, + 0x88, 0x18, 0x88, 0x89, 0x98, 0x88, 0x89, 0x99, 0x98, 0x90, 0x00, 0x00, + }, + { + 0x88, 0x78, 0x77, 0x78, 0x77, 0x77, 0x77, 0x78, 0x77, 0x77, 0x71, 0x11, + 0x72, 0x77, 0x77, 0x78, 0x87, 0x77, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, + }, + { + 0xAA, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x39, 0x92, 0x21, + 0x19, 0x39, 0x99, 0x94, 0x93, 0x99, 0x99, 0x99, 0xAA, 0xA0, 0x00, 0x00, + }, + { + 0x88, 0x78, 0x77, 0x78, 0x77, 0x77, 0x77, 0x78, 0x77, 0x72, 0x77, 0x72, + 0x17, 0x27, 0x77, 0x78, 0x87, 0x71, 0x78, 0x87, 0x88, 0x80, 0x00, 0x00, + }, + }, + }, +}; + +static const uint8_t short_codes_def[3][15][88] = { + { + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xFC, 0xCD, 0xFF, 0xFF, 0xFF, 0xCC, 0xCB, 0xBC, + 0xDF, 0xFF, 0xFD, 0xDB, 0xC9, 0x69, 0xBC, 0xFF, 0xFC, 0xFF, 0xB9, 0x42, + 0x5A, 0xCD, 0xFF, 0xFD, 0xDC, 0x62, 0x03, 0x9B, 0xCF, 0xFF, 0xFD, 0xC9, + 0x53, 0x4A, 0xCC, 0xFF, 0xFF, 0xFF, 0xBA, 0x9A, 0xBC, 0xFF, 0xFF, 0xFC, + 0xDC, 0xBC, 0xBC, 0xFF, 0xFF, 0xFF, 0xFE, 0xCC, 0xCD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFC, 0xFC, 0xCC, 0xCF, 0xDF, 0xFF, 0xFF, 0xDB, 0xA9, 0x9B, + 0xCF, 0xDF, 0xFF, 0xCB, 0x97, 0x67, 0x9B, 0xFF, 0xFF, 0xDC, 0xA7, 0x42, + 0x47, 0xAD, 0xFF, 0xFF, 0xC9, 0x63, 0x03, 0x69, 0xBF, 0xFF, 0xFC, 0xA7, + 0x53, 0x47, 0xAC, 0xDF, 0xFD, 0xDC, 0x97, 0x77, 0x8C, 0xBD, 0xFF, 0xFF, + 0xCC, 0xAA, 0xAB, 0xCF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCC, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xDC, 0xFF, 0xDF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0xAF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0x56, 0x9F, 0xFF, 0xFF, 0xFF, 0xA6, 0x43, + 0x47, 0xEF, 0xFF, 0xFF, 0xF9, 0x53, 0x03, 0x6A, 0xFF, 0xFF, 0xFF, 0xA6, + 0x43, 0x46, 0xAF, 0xFF, 0xFF, 0xFF, 0x96, 0x56, 0x9F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xC9, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xDD, 0xFF, 0xFF, 0xFD, 0xFF, 0xFD, 0xFD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xDB, 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFA, 0x43, + 0x6B, 0xFF, 0xDF, 0xFF, 0xFD, 0xA3, 0x02, 0xAD, 0xFF, 0xFF, 0xFD, 0xFB, + 0x52, 0x3A, 0xDF, 0xFF, 0xFF, 0xFF, 0xCB, 0xAA, 0xCE, 0xFF, 0xDF, 0xFF, + 0xFE, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xCF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xCC, 0xCA, + 0xFF, 0xCF, 0xFB, 0xAA, 0xAA, 0xCF, 0xCB, 0xFC, 0xFF, 0xAA, 0xA9, 0x99, + 0xAC, 0xBF, 0xFC, 0xA9, 0x98, 0x88, 0x99, 0xAA, 0xCF, 0xCA, 0xA8, 0x53, + 0x58, 0x9F, 0xCC, 0xCC, 0xB9, 0x73, 0x02, 0x68, 0xAC, 0xCF, 0xCA, 0x98, + 0x53, 0x37, 0x9B, 0xAC, 0xFB, 0xAA, 0x97, 0x78, 0x8A, 0xFB, 0xFF, 0xFA, + 0xBB, 0x99, 0x9A, 0xAB, 0xFF, 0xFF, 0xEB, 0xBA, 0xAA, 0xAC, 0xCB, 0xFF, + 0xBF, 0xBC, 0xBC, 0xCF, 0xFF, 0xFF, 0xCF, 0xFC, 0xFC, 0xFF, 0xFF, 0xCF, + 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFD, 0xFC, 0xFF, + 0xFF, 0xFF, 0xFC, 0xAB, 0xBA, 0xFC, 0xFF, 0xFF, 0xFF, 0xA9, 0x77, 0x78, + 0xAF, 0xFF, 0xFF, 0xA8, 0x65, 0x45, 0x68, 0xFF, 0xFC, 0xFB, 0x74, 0x33, + 0x35, 0x7B, 0xFF, 0xFF, 0xB7, 0x43, 0x23, 0x46, 0xAF, 0xFF, 0xCB, 0x75, + 0x33, 0x35, 0x7A, 0xCC, 0xFF, 0xF8, 0x65, 0x45, 0x68, 0xAC, 0xCF, 0xCC, + 0xA8, 0x77, 0x78, 0xBF, 0xFF, 0xFF, 0xFF, 0xB9, 0x99, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0xFC, 0xFF, + 0xFF, 0xFC, 0xFB, 0x9A, 0x99, 0xBA, 0xFF, 0xFF, 0xFB, 0x97, 0x77, 0x77, + 0x9C, 0xCF, 0xFC, 0x98, 0x65, 0x45, 0x68, 0xAF, 0xFF, 0xC9, 0x75, 0x33, + 0x35, 0x79, 0xFF, 0xFB, 0x86, 0x43, 0x23, 0x47, 0x9F, 0xFF, 0xC9, 0x75, + 0x33, 0x35, 0x7B, 0xBF, 0xFF, 0xA8, 0x65, 0x45, 0x68, 0xAF, 0xFF, 0xFA, + 0xA8, 0x77, 0x78, 0x9B, 0xFF, 0xFF, 0xFF, 0xFB, 0x99, 0xBB, 0xFF, 0xFF, + 0xFF, 0xFE, 0xCE, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xBC, 0xEF, + 0xFF, 0xFF, 0xDB, 0x99, 0x89, 0xAC, 0xDF, 0xFF, 0xDB, 0x97, 0x66, 0x67, + 0x9C, 0xFF, 0xEC, 0x97, 0x65, 0x45, 0x67, 0xAC, 0xFF, 0xB9, 0x65, 0x33, + 0x35, 0x69, 0xBF, 0xFB, 0x86, 0x43, 0x33, 0x46, 0x9B, 0xEE, 0xB9, 0x65, + 0x33, 0x35, 0x69, 0xBE, 0xFD, 0xA7, 0x65, 0x45, 0x67, 0xAC, 0xDF, 0xDB, + 0x97, 0x66, 0x67, 0x9B, 0xDF, 0xFF, 0xDC, 0xA9, 0x89, 0x9B, 0xCF, 0xFF, + 0xFF, 0xDC, 0xBB, 0xBC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xEF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBB, 0xFF, + 0xFF, 0xFF, 0xFF, 0xAA, 0x99, 0xAB, 0xFF, 0xFF, 0xFA, 0x98, 0x76, 0x67, + 0xAC, 0xCF, 0xFA, 0xA7, 0x64, 0x45, 0x67, 0x9B, 0xFF, 0xF8, 0x74, 0x33, + 0x34, 0x68, 0xAF, 0xFB, 0x96, 0x43, 0x33, 0x46, 0x8B, 0xFF, 0xF9, 0x75, + 0x43, 0x35, 0x69, 0xBF, 0xCC, 0x98, 0x65, 0x45, 0x67, 0x9A, 0xBF, 0xFF, + 0x98, 0x66, 0x68, 0x8F, 0xFF, 0xFF, 0xFF, 0x98, 0x88, 0xAF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xBA, 0xBA, 0xBE, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, + 0xFF, 0xAA, 0xFF, 0xF9, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x88, 0x7F, + 0xAF, 0xFA, 0xFF, 0xF8, 0x75, 0x55, 0x79, 0xFF, 0xFF, 0xF9, 0x75, 0x32, + 0x34, 0x8A, 0xFF, 0xFF, 0xB8, 0x43, 0x22, 0x58, 0xFF, 0xFF, 0xCF, 0x95, + 0x33, 0x46, 0x7A, 0xFF, 0xFA, 0xFF, 0x75, 0x46, 0x79, 0xFA, 0xFF, 0xAF, + 0xF9, 0x89, 0x8A, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xAA, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFA, + 0x90, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBA, 0xAA, 0x99, 0xAA, 0xBD, 0xBB, 0xBA, 0x99, 0x88, 0x89, 0x9B, + 0xCC, 0xBA, 0x98, 0x77, 0x77, 0x78, 0x9A, 0xBA, 0x98, 0x76, 0x65, 0x66, + 0x78, 0xAB, 0xA8, 0x76, 0x55, 0x45, 0x56, 0x79, 0xA9, 0x87, 0x55, 0x44, + 0x44, 0x67, 0x8A, 0x98, 0x75, 0x44, 0x44, 0x45, 0x68, 0x9A, 0x87, 0x65, + 0x44, 0x45, 0x67, 0x8A, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xAB, 0x98, + 0x76, 0x55, 0x56, 0x78, 0x9A, 0xBA, 0x98, 0x77, 0x77, 0x78, 0x9A, 0xCD, + 0xCB, 0xA9, 0x88, 0x89, 0xAA, 0xBB, 0xDD, 0xCA, 0xA9, 0x9A, 0xAB, 0xCC, + 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCA, 0xAA, 0xAA, 0xAB, 0xCE, 0xDC, 0xCB, 0xA9, 0x88, 0x89, 0x9B, + 0xCD, 0xBB, 0x98, 0x87, 0x77, 0x78, 0xAB, 0xDA, 0xA8, 0x76, 0x65, 0x66, + 0x78, 0xAC, 0xA9, 0x76, 0x55, 0x44, 0x56, 0x79, 0xAA, 0x97, 0x65, 0x44, + 0x44, 0x67, 0x9A, 0xA8, 0x75, 0x44, 0x34, 0x45, 0x79, 0x9A, 0x87, 0x65, + 0x44, 0x45, 0x67, 0x9A, 0xB9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xAB, 0xA8, + 0x76, 0x65, 0x66, 0x78, 0xBB, 0xCB, 0xA8, 0x77, 0x77, 0x78, 0xAB, 0xBD, + 0xCB, 0xA9, 0x98, 0x99, 0xAA, 0xCD, 0xFD, 0xFB, 0xAA, 0xAB, 0xAB, 0xCC, + 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xCB, 0xAA, 0xAA, 0xAB, 0xCE, 0xED, 0xCB, 0xA9, 0x88, 0x89, 0xAB, + 0xCE, 0xCB, 0x98, 0x77, 0x77, 0x78, 0x9B, 0xCB, 0xA8, 0x76, 0x65, 0x56, + 0x78, 0xAB, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xBA, 0x87, 0x55, 0x44, + 0x45, 0x57, 0x8A, 0xA8, 0x75, 0x44, 0x34, 0x45, 0x78, 0xAA, 0x87, 0x65, + 0x44, 0x45, 0x67, 0x8A, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xAB, 0xA8, + 0x76, 0x65, 0x66, 0x78, 0xAB, 0xCB, 0x98, 0x77, 0x77, 0x78, 0x9B, 0xCD, + 0xCB, 0xA9, 0x88, 0x89, 0xAB, 0xCD, 0xED, 0xCB, 0xAA, 0xAA, 0xAB, 0xCD, + 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xCB, 0xB9, 0xAA, 0xBB, 0xFF, 0xDD, 0xCB, 0xA9, 0x89, 0x89, 0x9B, + 0xEF, 0xBB, 0xA8, 0x77, 0x77, 0x78, 0x9B, 0xFC, 0xA8, 0x76, 0x55, 0x56, + 0x78, 0xAB, 0xB9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xBB, 0x97, 0x65, 0x44, + 0x44, 0x57, 0x8A, 0xA8, 0x75, 0x44, 0x44, 0x45, 0x68, 0xAA, 0x87, 0x65, + 0x44, 0x45, 0x57, 0x9A, 0xB9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xBB, 0x98, + 0x76, 0x55, 0x66, 0x78, 0xAB, 0xFB, 0xA8, 0x77, 0x77, 0x78, 0xAB, 0xBD, + 0xFB, 0xA9, 0x88, 0x89, 0xAC, 0xCC, 0xBC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, + 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xAB, 0xA9, 0xAA, 0xAB, 0xCC, 0xDC, 0xBA, 0x98, 0x88, 0x88, 0x9A, + 0xBD, 0xBA, 0x98, 0x77, 0x77, 0x78, 0x9B, 0xCA, 0xA8, 0x76, 0x65, 0x56, + 0x78, 0xAB, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xBA, 0x87, 0x55, 0x44, + 0x45, 0x57, 0x89, 0x98, 0x75, 0x44, 0x44, 0x45, 0x68, 0x9A, 0x87, 0x55, + 0x44, 0x45, 0x57, 0x89, 0xA8, 0x76, 0x55, 0x55, 0x56, 0x79, 0xAB, 0xA8, + 0x76, 0x55, 0x56, 0x78, 0x9A, 0xCB, 0xA8, 0x77, 0x77, 0x78, 0x9B, 0xDC, + 0xCB, 0xA9, 0x88, 0x89, 0x9A, 0xBD, 0xCB, 0xCB, 0xA9, 0xA9, 0xAA, 0xBB, + 0xB0, 0x00, 0x00, 0x00, + }, + }, + { + { + 0xAF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0xAF, + 0xFF, 0xFF, 0xFF, 0xFB, 0x96, 0x56, 0x9F, 0xFF, 0xFF, 0xFF, 0xA6, 0x32, + 0x36, 0xAF, 0xFF, 0xFF, 0xF9, 0x63, 0x12, 0x6A, 0xFF, 0xFF, 0xFF, 0x96, + 0x33, 0x36, 0xBF, 0xFF, 0xFF, 0xFF, 0x96, 0x56, 0x9A, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDA, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x56, 0xFC, 0xCF, 0xFF, 0xFF, 0xF6, 0x32, + 0x39, 0xFF, 0xFF, 0xFF, 0xF8, 0x62, 0x12, 0x6F, 0xFF, 0xFF, 0xFF, 0xF6, + 0x43, 0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xA6, 0x58, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0x56, 0x9F, 0xFF, 0xFF, 0xFF, 0xB6, 0x43, + 0x36, 0xFF, 0xFF, 0xFF, 0xFB, 0x62, 0x12, 0x5B, 0xFF, 0xFF, 0xFF, 0xD6, + 0x42, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0x56, 0x9F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x43, + 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xA3, 0x11, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x61, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x53, + 0x5E, 0xFF, 0xFF, 0xFF, 0xFF, 0x93, 0x11, 0x8F, 0xFF, 0xFF, 0xFF, 0xFE, + 0x51, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0xCF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xAA, 0xAA, 0xAC, 0xDE, 0xCB, 0xBA, 0xA9, 0x98, 0x99, 0xAB, + 0xDE, 0xBA, 0x98, 0x77, 0x77, 0x78, 0xAB, 0xEA, 0xA8, 0x76, 0x65, 0x66, + 0x79, 0xAC, 0xA9, 0x86, 0x54, 0x44, 0x56, 0x79, 0xAA, 0x87, 0x65, 0x44, + 0x45, 0x57, 0x9A, 0xA9, 0x75, 0x44, 0x34, 0x45, 0x78, 0x9A, 0x87, 0x65, + 0x44, 0x45, 0x67, 0x9A, 0xB9, 0x86, 0x55, 0x45, 0x56, 0x89, 0xAC, 0xA8, + 0x76, 0x65, 0x66, 0x78, 0x9A, 0xCC, 0xA8, 0x87, 0x77, 0x89, 0x9B, 0xBF, + 0xDB, 0xA9, 0x98, 0x99, 0x9B, 0xBC, 0xDF, 0xCB, 0xAA, 0xB9, 0xAB, 0xBB, + 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCB, 0xAA, 0x9A, 0xAB, 0xCE, 0xCD, 0xCB, 0x99, 0x88, 0x89, 0x9B, + 0xCD, 0xCA, 0x98, 0x77, 0x67, 0x78, 0x9B, 0xCB, 0xA8, 0x76, 0x65, 0x56, + 0x78, 0xAB, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xAA, 0x87, 0x65, 0x44, + 0x45, 0x57, 0x8A, 0x98, 0x65, 0x44, 0x44, 0x45, 0x78, 0xAA, 0x87, 0x55, + 0x44, 0x45, 0x57, 0x8A, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xAB, 0xA8, + 0x76, 0x55, 0x66, 0x78, 0x9B, 0xCB, 0xA8, 0x77, 0x67, 0x78, 0x9B, 0xCD, + 0xDB, 0xA9, 0x88, 0x89, 0x9B, 0xCD, 0xDC, 0xDB, 0xAA, 0xA9, 0xAB, 0xBE, + 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBB, 0xAA, 0xAA, 0xAB, 0xCD, 0xDC, 0xCB, 0x99, 0x88, 0x89, 0xAB, + 0xCD, 0xBB, 0x98, 0x77, 0x77, 0x78, 0x9B, 0xCB, 0xA8, 0x76, 0x55, 0x56, + 0x78, 0xAB, 0xA9, 0x76, 0x55, 0x44, 0x56, 0x79, 0xAA, 0x87, 0x65, 0x44, + 0x45, 0x57, 0x8A, 0xA8, 0x75, 0x44, 0x44, 0x45, 0x68, 0xAA, 0x87, 0x55, + 0x44, 0x45, 0x67, 0x89, 0xA9, 0x76, 0x55, 0x45, 0x56, 0x79, 0xAB, 0xA8, + 0x76, 0x65, 0x66, 0x78, 0xAA, 0xCB, 0x98, 0x77, 0x77, 0x78, 0x9A, 0xBD, + 0xCB, 0xA9, 0x88, 0x89, 0xAB, 0xBB, 0xDD, 0xCB, 0xAA, 0x9A, 0xAA, 0xBB, + 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xEC, 0xBA, 0xAA, 0xBD, 0xEF, 0xDD, 0xCB, 0xA9, 0x99, 0x9A, 0xBD, + 0xCF, 0xDB, 0x98, 0x77, 0x77, 0x88, 0xAC, 0xDE, 0xA9, 0x76, 0x55, 0x66, + 0x79, 0x9F, 0xB9, 0x86, 0x55, 0x45, 0x56, 0x89, 0xBB, 0x97, 0x65, 0x44, + 0x45, 0x67, 0x9B, 0xB8, 0x75, 0x44, 0x34, 0x45, 0x79, 0xAA, 0x97, 0x64, + 0x44, 0x45, 0x57, 0x9B, 0xC9, 0x86, 0x55, 0x44, 0x56, 0x79, 0xBC, 0xA8, + 0x76, 0x55, 0x66, 0x79, 0xBF, 0xFC, 0xA8, 0x87, 0x77, 0x78, 0xAA, 0xFF, + 0xFC, 0xAA, 0x99, 0x99, 0xAC, 0xCF, 0xFF, 0xCB, 0xBA, 0xAB, 0xBC, 0xBE, + 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBB, 0xBB, 0x9B, 0xBB, 0xFE, 0xCD, 0xCC, 0xA9, 0x99, 0x99, 0xAC, + 0xED, 0xCC, 0xA8, 0x87, 0x77, 0x88, 0xAB, 0xCB, 0xA8, 0x76, 0x56, 0x66, + 0x79, 0xBC, 0xA9, 0x86, 0x55, 0x44, 0x56, 0x79, 0xCA, 0x97, 0x65, 0x44, + 0x44, 0x67, 0x8A, 0xA9, 0x75, 0x44, 0x34, 0x45, 0x79, 0xBB, 0x97, 0x64, + 0x44, 0x45, 0x67, 0x9A, 0xB9, 0x86, 0x54, 0x45, 0x56, 0x89, 0xBC, 0xA9, + 0x76, 0x66, 0x66, 0x79, 0xAC, 0xFC, 0xA8, 0x87, 0x77, 0x79, 0x9B, 0xDE, + 0xDC, 0xA9, 0x99, 0x9A, 0xAB, 0xBD, 0xBD, 0xDB, 0xBA, 0xAA, 0xBB, 0xCD, + 0xB0, 0x00, 0x00, 0x00, + }, + }, + { + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7F, 0xFC, 0xAF, 0xFF, 0xFF, 0xF6, 0x32, + 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x63, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCC, 0xCF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x99, 0xBB, + 0xFF, 0xFF, 0xFC, 0xBB, 0x86, 0x56, 0x9B, 0xFF, 0xFF, 0xFB, 0xA7, 0x42, + 0x36, 0xAF, 0xFF, 0xFF, 0xF9, 0x62, 0x13, 0x59, 0xFF, 0xFF, 0xFF, 0xA6, + 0x32, 0x47, 0xAF, 0xEF, 0xFF, 0xFF, 0x96, 0x57, 0x9A, 0xCC, 0xFF, 0xFF, + 0xFB, 0xAA, 0xAA, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x99, 0x9B, + 0xFF, 0xFF, 0xFF, 0xFA, 0x86, 0x56, 0x8B, 0xFF, 0xFF, 0xFF, 0xA6, 0x42, + 0x36, 0xAF, 0xFF, 0xFF, 0xF9, 0x52, 0x13, 0x58, 0xFF, 0xFF, 0xFF, 0xA5, + 0x33, 0x36, 0x9F, 0xFF, 0xFF, 0xFE, 0x86, 0x56, 0x8B, 0xFF, 0xFF, 0xFF, + 0xFE, 0xA8, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x7F, + 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x45, 0x68, 0xCF, 0xFF, 0xFF, 0xB5, 0x43, + 0x35, 0x8F, 0xFF, 0xFF, 0xF8, 0x43, 0x23, 0x57, 0xCF, 0xFF, 0xFF, 0xA5, + 0x32, 0x34, 0x8F, 0xFF, 0xFF, 0xFF, 0x64, 0x44, 0x6F, 0xFF, 0xFF, 0xFF, + 0xFF, 0x87, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xAF, 0xFF, 0xFF, 0xFF, 0xF3, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x52, 0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x8F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x88, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF8, 0x67, 0x87, + 0xFF, 0xFF, 0xFF, 0xF8, 0x76, 0x54, 0x77, 0xEF, 0xFF, 0xFF, 0x84, 0x33, + 0x35, 0x7F, 0xFF, 0xF8, 0x86, 0x53, 0x23, 0x57, 0xFF, 0xFF, 0xFF, 0x65, + 0x33, 0x35, 0x78, 0xFF, 0xFF, 0xF8, 0x55, 0x44, 0x58, 0xEE, 0xEE, 0xFE, + 0xFE, 0x67, 0x88, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFC, 0xCC, 0xFC, 0xFF, 0xFF, 0xFF, 0xBC, 0xA9, 0xA9, 0xCF, + 0xFF, 0xFC, 0xBA, 0x98, 0x77, 0x89, 0xBF, 0xFF, 0xB9, 0x87, 0x66, 0x67, + 0x8A, 0xCF, 0xBA, 0x87, 0x65, 0x44, 0x67, 0x9F, 0xFB, 0xA8, 0x65, 0x43, + 0x45, 0x69, 0xCF, 0xEA, 0x76, 0x43, 0x33, 0x46, 0x8F, 0xFC, 0xA8, 0x65, + 0x43, 0x34, 0x68, 0xAF, 0xF9, 0x97, 0x64, 0x44, 0x57, 0xAF, 0xFF, 0xFA, + 0x97, 0x66, 0x67, 0x9C, 0xFF, 0xFF, 0xFB, 0xA9, 0x99, 0x9B, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCB, 0xCC, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xDC, 0xCD, 0xCF, 0xFF, + 0xFF, 0xCC, 0xCB, 0xA9, 0x9A, 0xBC, 0xFF, 0xFD, 0xDB, 0xA8, 0x76, 0x78, + 0xAD, 0xFF, 0xDC, 0xA8, 0x65, 0x45, 0x68, 0xBF, 0xFE, 0xCA, 0x75, 0x33, + 0x35, 0x7A, 0xCF, 0xFC, 0xA6, 0x43, 0x23, 0x47, 0x9C, 0xFF, 0xC9, 0x75, + 0x33, 0x35, 0x79, 0xCE, 0xFD, 0xB8, 0x65, 0x45, 0x68, 0xAC, 0xDF, 0xFC, + 0xA8, 0x76, 0x78, 0xAB, 0xDF, 0xFF, 0xFD, 0xBA, 0x99, 0xAB, 0xCF, 0xFF, + 0xFF, 0xFD, 0xDD, 0xCD, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, + 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x9D, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xAF, 0x77, 0x8A, + 0xFF, 0xFF, 0xFF, 0xF9, 0x75, 0x45, 0x68, 0xFF, 0xFF, 0xFF, 0x84, 0x33, + 0x35, 0x9A, 0xFF, 0xFF, 0xF6, 0x43, 0x23, 0x47, 0xFF, 0xFF, 0xFF, 0x75, + 0x33, 0x35, 0x7A, 0xFF, 0xFF, 0xF8, 0x64, 0x45, 0x69, 0xFF, 0xFF, 0xFF, + 0x97, 0x86, 0x78, 0x9F, 0xFF, 0xFF, 0xAF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, + 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xDD, 0xDD, 0xDD, 0x5D, 0xDD, 0x4D, 0xDD, 0xDD, 0xD6, 0xDD, 0xD5, + 0xDD, 0xDD, 0x5D, 0xDD, 0x6D, 0xDD, 0xDD, 0xD5, 0xDD, 0xDD, 0xD6, 0xDD, + 0xDD, 0x6D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD6, 0xDD, 0xDD, 0xD6, + 0xD5, 0xDD, 0x5D, 0x6D, 0x55, 0xDD, 0x0D, 0x55, 0x65, 0xDD, 0x5D, 0xDD, + 0x66, 0xDD, 0xDD, 0xDD, 0xDD, 0xD5, 0xD5, 0x5D, 0x5D, 0xD6, 0xDD, 0xDD, + 0xDD, 0xDD, 0xD6, 0xD5, 0x6D, 0x6D, 0x6D, 0xD4, 0x6D, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x55, 0xD6, 0xDD, 0xDE, + 0xE0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0x9B, 0xA9, 0x9B, 0xAC, 0xCC, 0xFA, 0xBA, 0xBB, 0xA9, 0xAA, 0xBF, + 0xFF, 0xAA, 0xAA, 0x98, 0x88, 0x88, 0xAD, 0xF9, 0x99, 0x88, 0x76, 0x66, + 0x79, 0xAA, 0x99, 0x98, 0x75, 0x54, 0x56, 0x8F, 0xFA, 0xA9, 0x75, 0x43, + 0x34, 0x68, 0xAB, 0xBA, 0x86, 0x53, 0x33, 0x56, 0x8A, 0xBC, 0xB8, 0x64, + 0x33, 0x45, 0x79, 0xAC, 0xCB, 0x86, 0x54, 0x55, 0x67, 0x8A, 0xAC, 0xCA, + 0x76, 0x67, 0x78, 0x89, 0xBB, 0xFF, 0xB9, 0x78, 0x88, 0x9A, 0xBB, 0x9F, + 0xFD, 0xF9, 0xAB, 0x9A, 0xAB, 0xAA, 0xFF, 0xFC, 0xFA, 0xAB, 0x99, 0xAA, + 0x80, 0x00, 0x00, 0x00, + }, + { + 0xCC, 0xBC, 0xBB, 0xBC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xB4, 0xBB, + 0xBB, 0xBB, 0xBB, 0xB4, 0x44, 0xB4, 0x2B, 0xBC, 0xCC, 0xCB, 0xBB, 0x33, + 0x4B, 0xBB, 0xBB, 0xBB, 0xB4, 0xBB, 0x44, 0x3B, 0xBB, 0xBB, 0xBB, 0xBB, + 0xB3, 0xB4, 0xBB, 0xBB, 0xBB, 0xBB, 0xB4, 0x44, 0x3B, 0xBB, 0xBB, 0xBB, + 0xB4, 0xB3, 0xBB, 0xBC, 0xCC, 0xCC, 0xCC, 0xCB, 0xB4, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCB, 0xCC, 0xCC, + 0xC0, 0x00, 0x00, 0x00, + }, + { + 0x77, 0x67, 0x76, 0x67, 0x77, 0x66, 0x66, 0x67, 0x77, 0x77, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x67, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x70, 0x00, 0x00, 0x00, + }, + }, +}; + +static const uint8_t long_codes_def[3][125][224] = { + { + { + 0xBE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, + 0xFE, 0xED, 0xDD, 0xCC, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xED, 0xDC, + 0xCB, 0xCB, 0xBB, 0xCC, 0xDE, 0xEF, 0xFF, 0xFE, 0xED, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xDD, 0xFF, 0xFF, 0xFE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, + 0x99, 0xAB, 0xCD, 0xEF, 0xFE, 0xEC, 0xCB, 0xA9, 0x88, 0x87, 0x78, 0x89, + 0xAB, 0xCD, 0xFF, 0xFE, 0xCB, 0xA9, 0x87, 0x77, 0x66, 0x77, 0x89, 0xAB, + 0xDE, 0xFD, 0xDC, 0xAA, 0x87, 0x76, 0x65, 0x66, 0x67, 0x89, 0xBC, 0xEF, + 0xDD, 0xBA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xED, 0xDC, + 0xA9, 0x87, 0x65, 0x54, 0x45, 0x56, 0x79, 0xAC, 0xDD, 0xDD, 0xCA, 0x98, + 0x65, 0x54, 0x44, 0x55, 0x67, 0x9A, 0xBD, 0xDE, 0xEB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x66, 0x89, 0xAB, 0xDD, 0xED, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x56, 0x78, 0x9A, 0xCC, 0xDE, 0xFC, 0xBA, 0x87, 0x76, 0x65, 0x66, 0x77, + 0x89, 0xBB, 0xDD, 0xFE, 0xDB, 0xA9, 0x87, 0x76, 0x67, 0x77, 0x89, 0xAB, + 0xCD, 0xDF, 0xEF, 0xCB, 0xA9, 0x88, 0x87, 0x88, 0x89, 0xAB, 0xCC, 0xED, + 0xFF, 0xED, 0xCB, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xEF, 0xFF, + 0xFD, 0xDB, 0xBA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFD, 0xFF, 0xFF, 0xFD, + 0xDC, 0xCC, 0xBC, 0xCC, 0xDC, 0xDE, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDE, + 0xDD, 0xCD, 0xDD, 0xEE, 0xFF, 0xFE, 0xDF, 0xFF, 0xFF, 0xEF, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xFD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEF, 0xFF, 0xFF, 0xCF, 0xFE, + 0xDC, 0xDC, 0xCC, 0xBB, 0xCC, 0xCC, 0xDE, 0xEF, 0xFF, 0xEE, 0xDD, 0xCC, + 0xCB, 0xBA, 0xAA, 0xBB, 0xBC, 0xDD, 0xFF, 0xDC, 0xDD, 0xCB, 0xBA, 0xA9, + 0x99, 0x9A, 0x9A, 0xBC, 0xDF, 0xFF, 0xBD, 0xDB, 0xBA, 0x99, 0x88, 0x88, + 0x88, 0x9A, 0xBC, 0xEF, 0xDD, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x67, 0x78, 0x9A, + 0xCC, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x65, 0x66, 0x67, 0x88, 0xAB, 0xCC, + 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x67, 0x89, 0xBC, 0xCC, 0xCA, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xCC, 0xBB, 0xA9, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x67, 0x89, 0xAC, 0xBC, 0xCA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCC, 0xB9, 0x87, 0x66, 0x55, 0x55, + 0x56, 0x77, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x67, + 0x89, 0xAB, 0xBD, 0xDF, 0xCA, 0x98, 0x87, 0x76, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xCF, 0xDD, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x88, 0x9A, 0xBC, 0xDD, + 0xFF, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xDF, 0xFF, + 0xDC, 0xBA, 0xAA, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xEC, + 0xBB, 0xBA, 0xAA, 0xAB, 0xBB, 0xDC, 0xDF, 0xDF, 0xFF, 0xFD, 0xEE, 0xCC, + 0xBC, 0xBB, 0xCC, 0xDD, 0xCE, 0xFE, 0xCF, 0xFF, 0xDD, 0xDD, 0xCD, 0xDC, + 0xCB, 0xBD, 0xCD, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xDD, 0xEE, + 0xDD, 0xCD, 0xCC, 0xCC, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xDE, 0xDD, 0xCC, + 0xBB, 0xBB, 0xBA, 0xBB, 0xCD, 0xDE, 0xFF, 0xFD, 0xDD, 0xCC, 0xBA, 0xAA, + 0x99, 0x9A, 0xAA, 0xBC, 0xDE, 0xFF, 0xCD, 0xCB, 0xBA, 0x99, 0x98, 0x88, + 0x89, 0x9A, 0xBC, 0xDF, 0xED, 0xCC, 0xBA, 0x98, 0x88, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDE, 0xCC, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x67, 0x78, 0x9A, + 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x76, 0x65, 0x56, 0x67, 0x89, 0xAB, 0xCC, + 0xCC, 0xBA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x67, 0x89, 0xBC, 0xCC, 0xCA, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCC, 0xCC, 0xB9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x67, 0x89, 0xAC, 0xCC, 0xCB, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x66, 0x78, 0x9B, 0xCC, 0xCC, 0xBA, 0x87, 0x76, 0x55, 0x55, + 0x56, 0x78, 0x99, 0xBC, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xDD, 0xCB, 0x98, 0x87, 0x76, 0x66, 0x77, 0x89, 0x9B, + 0xBC, 0xCE, 0xED, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x89, 0x9A, 0xBC, 0xDC, + 0xEE, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xBC, 0xCD, 0xCF, 0xFE, + 0xDD, 0xBB, 0xAA, 0x99, 0x9A, 0xAA, 0xBC, 0xCC, 0xDC, 0xFF, 0xFE, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xDF, 0xFF, 0xFF, 0xED, 0xCC, + 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFD, 0xDF, 0xFF, 0xED, 0xDD, 0xDC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xDD, 0xFF, + 0xDF, 0xEC, 0xCC, 0xDC, 0xCD, 0xDD, 0xDF, 0xFF, 0xFF, 0xEE, 0xCC, 0xCC, + 0xBB, 0xBB, 0xBB, 0xAC, 0xCC, 0xEF, 0xEF, 0xFD, 0xDD, 0xCC, 0xBB, 0xAA, + 0x99, 0x9A, 0xAB, 0xBC, 0xDF, 0xFF, 0xDD, 0xCB, 0xBA, 0x99, 0x98, 0x88, + 0x89, 0x9A, 0xBC, 0xDD, 0xFC, 0xDB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xED, 0xBC, 0xBA, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x88, 0x9A, + 0xBD, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x65, 0x56, 0x67, 0x89, 0xAC, 0xCE, + 0xCC, 0xBA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x67, 0x8A, 0xBC, 0xDC, 0xDB, + 0xA9, 0x76, 0x65, 0x55, 0x55, 0x56, 0x78, 0xAA, 0xCC, 0xCC, 0xB9, 0x87, + 0x66, 0x55, 0x45, 0x55, 0x67, 0x89, 0xBC, 0xCC, 0xDB, 0xA8, 0x76, 0x65, + 0x55, 0x55, 0x66, 0x78, 0x9B, 0xCC, 0xCC, 0xBA, 0x97, 0x66, 0x55, 0x55, + 0x56, 0x78, 0x9A, 0xBC, 0xCF, 0xDC, 0xA9, 0x87, 0x66, 0x65, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xFD, 0xCB, 0xA8, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xBC, 0xCF, 0xFD, 0xCB, 0x99, 0x87, 0x77, 0x78, 0x89, 0xAA, 0xCC, 0xCC, + 0xFF, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x99, 0x9A, 0xBC, 0xDD, 0xCF, 0xFE, + 0xDD, 0xBB, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xBD, 0xDC, 0xFF, 0xFF, 0xDD, + 0xBC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xFE, 0xCF, 0xFF, 0xFD, 0xFD, 0xDD, + 0xDC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFE, 0xCF, 0xFF, 0xDD, 0xCD, 0xDD, 0xCC, + 0xCD, 0xCC, 0xCD, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xEE, 0xDD, 0xDD, 0xCD, 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xDE, 0xFF, + 0xFD, 0xED, 0xDD, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xDD, + 0xCC, 0xCB, 0xBB, 0xCC, 0xDE, 0xFF, 0xFF, 0xFE, 0xFD, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xFF, 0xFF, 0xDC, 0xBA, 0xA9, 0x99, 0x89, + 0x99, 0xAB, 0xCD, 0xFF, 0xFD, 0xDD, 0xCA, 0xA9, 0x88, 0x87, 0x78, 0x89, + 0xAB, 0xCD, 0xFF, 0xDE, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xDF, 0xFE, 0xDC, 0xA9, 0x87, 0x76, 0x65, 0x56, 0x67, 0x89, 0xAC, 0xEF, + 0xED, 0xCA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xED, 0xDB, + 0xA9, 0x76, 0x65, 0x54, 0x55, 0x56, 0x79, 0xAB, 0xCE, 0xDD, 0xBA, 0x87, + 0x66, 0x54, 0x44, 0x55, 0x67, 0x9A, 0xBD, 0xDD, 0xDB, 0xA9, 0x86, 0x65, + 0x54, 0x55, 0x66, 0x79, 0xAB, 0xCD, 0xDD, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x56, 0x78, 0x9A, 0xCD, 0xDF, 0xFC, 0xB9, 0x87, 0x66, 0x65, 0x66, 0x77, + 0x89, 0xBC, 0xDD, 0xFF, 0xDC, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDF, 0xFF, 0xCB, 0xA9, 0x88, 0x87, 0x78, 0x89, 0xAB, 0xBC, 0xED, + 0xFF, 0xFD, 0xCB, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xDF, 0xEF, 0xFF, + 0xED, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xCC, 0xCD, 0xED, 0xFF, 0xFF, 0xFD, + 0xDC, 0xCB, 0xBC, 0xCC, 0xCD, 0xDE, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xED, + 0xDE, 0xDD, 0xDE, 0xDD, 0xDF, 0xFF, 0xBF, 0xFF, 0xEF, 0xDF, 0xED, 0xDC, + 0xDD, 0xDD, 0xDE, 0xED, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xBC, 0xDC, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDD, 0xBC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCD, 0xDB, 0xCB, 0xAA, 0xA9, 0x98, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCC, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0xAB, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xAA, 0xA9, + 0x88, 0x76, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, + 0x66, 0x65, 0x55, 0x56, 0x67, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x99, 0xAA, 0xBA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xAB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xCB, + 0xBA, 0x99, 0x98, 0x88, 0x89, 0x99, 0x9A, 0xAB, 0xCB, 0xCC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBD, 0xDD, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0xBD, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0x9A, 0x9A, 0xAA, 0xAB, 0xBB, 0xCD, 0xBB, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xCA, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x77, + 0x88, 0x89, 0x9A, 0xAB, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x67, 0x78, 0x89, + 0xAA, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, + 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xA9, 0xA9, + 0x88, 0x76, 0x66, 0x65, 0x66, 0x66, 0x77, 0x89, 0xAA, 0xAA, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x67, 0x78, 0x9A, 0x99, 0xA9, 0x88, 0x76, 0x66, + 0x65, 0x66, 0x66, 0x78, 0x89, 0xA9, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xAA, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xAB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xAA, + 0xBB, 0xBA, 0x99, 0x88, 0x87, 0x78, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xCB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBA, 0xCC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBD, 0xDC, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDB, 0xBD, 0xCC, 0xBA, 0xAA, 0xA9, 0x99, + 0xAA, 0xAA, 0xAB, 0xBB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBB, 0xDC, + 0xBB, 0xAA, 0xAA, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0xDD, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x99, 0xAB, 0xBB, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x77, + 0x78, 0x88, 0x99, 0xAB, 0xBA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x76, 0x66, 0x67, 0x77, 0x89, + 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, + 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x78, 0x99, 0x99, 0x99, + 0x87, 0x76, 0x66, 0x66, 0x66, 0x66, 0x77, 0x89, 0x99, 0x99, 0x98, 0x77, + 0x66, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0x99, 0xA9, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x66, 0x77, 0x89, 0x99, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0x9A, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xA9, 0xAA, 0x99, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0x9A, 0xAA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xBA, + 0xBB, 0xAA, 0x98, 0x88, 0x87, 0x77, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xBB, + 0xA9, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xCC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBC, 0xDC, 0xBB, 0xBA, 0xAA, + 0x99, 0xAA, 0xAA, 0xBB, 0xBC, 0xCB, 0xBC, 0xCB, 0xBA, 0xAA, 0x99, 0x99, + 0x99, 0xAA, 0xAA, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xCD, 0xBB, 0xCC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xBC, 0xCB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x78, + 0x88, 0x88, 0x9A, 0xAB, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x66, 0x77, 0x78, 0x89, + 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, + 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0x99, 0xA9, + 0x88, 0x76, 0x66, 0x65, 0x66, 0x66, 0x77, 0x89, 0xA9, 0x9A, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x67, 0x88, 0x9A, 0x99, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x66, 0x66, 0x78, 0x89, 0xA9, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0x9A, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x99, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xBA, + 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x77, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xBB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xCD, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBD, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDB, 0xBC, 0xCB, 0xBA, 0xAA, 0x9A, 0x99, + 0x99, 0xAA, 0xAA, 0xBB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xCC, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xED, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xCB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x78, + 0x88, 0x89, 0x9A, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xBA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, + 0x88, 0x76, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, + 0x66, 0x65, 0x55, 0x66, 0x67, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, + 0x78, 0x99, 0xAA, 0xAB, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xAB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xBA, + 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x78, 0x88, 0x89, 0x9A, 0xBB, 0xBC, 0xCB, + 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xDD, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xCD, 0xED, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0xBD, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xEE, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, + 0xFE, 0xED, 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFE, 0xDD, + 0xCC, 0xCB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFE, 0xFE, 0xDC, 0xCB, 0xBA, + 0xAA, 0xAB, 0xBC, 0xDD, 0xFF, 0xFF, 0xEE, 0xDD, 0xBB, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDE, 0xFF, 0xFD, 0xDC, 0xBB, 0xA9, 0x88, 0x77, 0x88, 0x99, + 0xAC, 0xDF, 0xFF, 0xDD, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x78, 0x8A, 0xBC, + 0xEF, 0xFD, 0xDC, 0xB9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xFF, + 0xDD, 0xBA, 0x98, 0x76, 0x55, 0x45, 0x56, 0x78, 0xAB, 0xDE, 0xFD, 0xDB, + 0xA9, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xBC, 0xEF, 0xED, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0x9B, 0xCD, 0xEE, 0xDC, 0xA9, 0x86, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xDD, 0xEE, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xCE, 0xEF, 0xFD, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xCD, 0xEE, 0xFF, 0xDC, 0xBA, 0x88, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDF, 0xEF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0x9A, 0xBC, 0xCD, 0xEF, + 0xFF, 0xFE, 0xDC, 0xBA, 0xA9, 0x99, 0xAA, 0xBB, 0xCD, 0xEF, 0xEF, 0xFF, + 0xFE, 0xDC, 0xCB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFE, 0xFF, 0xFF, 0xFE, + 0xDD, 0xDC, 0xCC, 0xCD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEF, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFE, 0xED, + 0xDE, 0xEE, 0xEF, 0xEF, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAD, 0xCD, 0xCB, 0xBC, 0xCB, 0xCC, 0xCD, 0xDD, 0xDE, 0xEF, 0xBD, 0xDE, + 0xDD, 0xCC, 0xCC, 0xCC, 0xDC, 0xDD, 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xCB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xDD, 0xEF, 0xEF, 0xDD, 0xDC, 0xCC, 0xBB, 0xAA, + 0xA9, 0xAA, 0xBB, 0xCC, 0xFF, 0xFE, 0xCD, 0xCC, 0xAA, 0x99, 0x98, 0x88, + 0x99, 0xAB, 0xCE, 0xFE, 0xCC, 0xCB, 0xBA, 0x98, 0x88, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xFE, 0xCD, 0xBB, 0x99, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAC, + 0xDE, 0xDC, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x67, 0x8A, 0xBC, 0xFD, + 0xCC, 0xBA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xCB, + 0x99, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xCB, 0xA8, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xCD, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xCD, 0xEC, 0xB9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBB, 0xDC, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xCE, 0xFD, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCC, 0xDD, + 0xEF, 0xFD, 0xDB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDD, 0xDF, 0xFD, + 0xFD, 0xCC, 0xBB, 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xFC, 0xEF, 0xEF, 0xED, + 0xDD, 0xCC, 0xBC, 0xBC, 0xCC, 0xED, 0xEE, 0xDF, 0xFF, 0xFF, 0xFD, 0xED, + 0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xED, 0xBE, 0xDD, 0xDD, 0xDD, 0xDC, 0xDC, + 0xCD, 0xCC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xDD, 0xFE, + 0xDD, 0xCC, 0xCC, 0xCB, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xDE, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xFF, 0xFD, 0xDD, 0xCB, 0xAA, 0xA9, + 0x99, 0x99, 0xAB, 0xBC, 0xEF, 0xFF, 0xCD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDE, 0xEC, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xEE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xEC, 0xCA, 0x99, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDD, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x66, 0x78, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x67, 0x8A, 0xBC, 0xCC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x79, 0xAB, 0xCC, 0xCC, 0xB9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xDD, 0xCB, 0x99, 0x87, 0x76, 0x67, 0x77, 0x89, 0xAB, + 0xCD, 0xDE, 0xDD, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x89, 0xAA, 0xBC, 0xDD, + 0xEF, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x99, 0xAA, 0xBC, 0xDD, 0xDF, 0xFF, + 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xED, 0xFF, 0xFE, 0xDC, + 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEF, 0xEF, 0xFF, 0xFF, 0xED, 0xDC, + 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0xFE, 0xDF, 0xFF, 0xFE, 0xED, 0xDD, 0xDC, + 0xCD, 0xDD, 0xDD, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xEF, 0xCD, 0xFD, + 0xED, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBB, 0xBA, 0xAB, 0xBB, 0xCC, 0xDD, 0xFF, 0xFD, 0xDD, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xFE, 0xCD, 0xCB, 0xBA, 0x99, 0x88, 0x88, + 0x89, 0xAA, 0xBD, 0xEF, 0xDC, 0xDC, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0x9A, 0xCD, 0xFD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAC, 0xDD, + 0xCC, 0xB9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xCC, 0xCA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x79, 0xAB, 0xDD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x67, 0x8A, 0xBC, 0xCC, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x97, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xCD, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xDC, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xED, 0xBA, 0xA9, 0x88, 0x77, 0x88, 0x89, 0x9B, 0xBC, 0xDD, + 0xDE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xCE, 0xCF, 0xFE, + 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xED, 0xFF, 0xEE, 0xED, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCE, 0xEE, 0xDF, 0xFF, 0xFF, 0xED, 0xDD, + 0xDC, 0xCC, 0xCD, 0xDD, 0xFE, 0xFE, 0xBF, 0xFE, 0xDD, 0xDD, 0xCD, 0xCC, + 0xDD, 0xCC, 0xDD, 0xEE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xFF, 0xFE, 0xEE, 0xEE, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFF, 0xEE, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xED, + 0xCC, 0xCB, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, 0xCB, 0xBA, + 0xAA, 0xAB, 0xBC, 0xDF, 0xFF, 0xFF, 0xEE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDF, 0xFF, 0xFE, 0xED, 0xCB, 0xA9, 0x88, 0x77, 0x88, 0x9A, + 0xBC, 0xDF, 0xFF, 0xEE, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x78, 0x8A, 0xBC, + 0xEF, 0xFD, 0xDC, 0xB9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xFF, + 0xDD, 0xCA, 0x98, 0x76, 0x55, 0x45, 0x56, 0x78, 0xAB, 0xDF, 0xFE, 0xDC, + 0xA9, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xBC, 0xEF, 0xED, 0xCA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0x9B, 0xCE, 0xEE, 0xDC, 0xA9, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xEE, 0xEE, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xCE, 0xEF, 0xFD, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBD, 0xEF, 0xFF, 0xEC, 0xB9, 0x98, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x88, 0x9A, 0xBB, 0xDE, 0xFF, + 0xFF, 0xFE, 0xDC, 0xBA, 0xA9, 0x99, 0xAA, 0xBB, 0xCD, 0xFF, 0xFF, 0xFF, + 0xFE, 0xEC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xDC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEE, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDE, 0xBC, 0xDD, + 0xCB, 0xBB, 0xBA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDD, 0xED, 0xCC, 0xCB, 0xBA, + 0xAA, 0xA9, 0x99, 0xAA, 0xBB, 0xCC, 0xDE, 0xDB, 0xCB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xDC, 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xCD, 0xCB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x78, 0x9A, + 0xBC, 0xCA, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x89, 0x9A, 0xBB, + 0xAA, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBB, 0xAA, 0x99, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xBB, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x66, 0x65, 0x55, + 0x66, 0x78, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xBB, 0xAA, 0x98, 0x87, 0x77, 0x67, 0x77, 0x88, 0x9A, + 0xBB, 0xBC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x88, 0x9A, 0xAB, 0xCB, + 0xCC, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xBD, 0xDC, + 0xCB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xDE, 0xED, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCD, 0xEE, 0xDD, 0xCC, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xDC, 0xAE, 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xBC, 0xDC, 0xAB, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xED, 0xBB, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xDA, 0xBA, 0xAA, 0x99, 0x98, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCC, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x77, + 0x88, 0x89, 0xAA, 0xBC, 0xCA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x89, 0xAB, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xBA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x87, 0x66, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x66, 0x78, 0x99, 0xAA, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x67, 0x89, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0xAA, 0x99, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xBB, 0xA9, 0x88, 0x77, 0x76, 0x67, 0x77, 0x88, 0x99, + 0xAB, 0xAB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xBB, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xAC, 0xDB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xCC, 0xBB, + 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBC, 0xED, 0xDC, 0xBB, 0xBA, + 0xAA, 0xAA, 0xBA, 0xBB, 0xCC, 0xCC, 0xAC, 0xCC, 0xCB, 0xBB, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBB, 0xCC, + 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDC, 0xBB, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xCA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xAB, 0xBA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x66, 0x66, 0x78, 0x89, 0xA9, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0x99, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x98, 0x77, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x67, 0x77, 0x78, 0x89, + 0xAA, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xBB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBB, 0xCC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xBC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xBC, 0xCB, 0xBB, 0xAA, 0xAA, 0x99, + 0x9A, 0xAA, 0xAB, 0xBB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xAB, 0xDC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xEC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xCD, 0xCB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCC, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x78, + 0x88, 0x89, 0xAA, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x87, 0x66, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x66, 0x78, 0x99, 0xAA, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x67, 0x89, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0xAA, 0x99, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xAA, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBA, + 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x98, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xCB, 0xBA, + 0xAA, 0xAA, 0x99, 0x9A, 0xAA, 0xBB, 0xCD, 0xCD, 0xED, 0xDC, 0xBB, 0xBB, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xAC, 0xCC, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xCE, 0xAC, 0xDD, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xFE, 0xBC, 0xCB, 0xBA, + 0xAA, 0x99, 0x9A, 0xAA, 0xAB, 0xCC, 0xDE, 0xDB, 0xCB, 0xBA, 0xA9, 0x99, + 0x98, 0x99, 0x9A, 0xAB, 0xCC, 0xDD, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xCD, 0xCB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x78, 0x9A, + 0xBC, 0xCA, 0xAA, 0x98, 0x77, 0x66, 0x65, 0x66, 0x67, 0x88, 0x9A, 0xBB, + 0xAA, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x99, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xAA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xBB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBB, 0xBC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x88, 0x9A, 0xAB, 0xCB, + 0xCC, 0xCB, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xBD, 0xDC, + 0xCB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCE, 0xFE, 0xDC, 0xCC, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEC, 0xBE, 0xDC, 0xCC, 0xCB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDE, 0xDD, 0xDD, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, + 0xEE, 0xDD, 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xED, 0xDC, + 0xCC, 0xBC, 0xCC, 0xCD, 0xEE, 0xFF, 0xFF, 0xFD, 0xED, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAB, 0xBC, 0xDF, 0xFF, 0xFF, 0xDD, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xBC, 0xDF, 0xFF, 0xFD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xBC, 0xEF, 0xFF, 0xDD, 0xCB, 0x98, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBD, + 0xEF, 0xFD, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9B, 0xCD, 0xFF, + 0xDD, 0xBA, 0x97, 0x66, 0x54, 0x45, 0x56, 0x79, 0xAC, 0xDE, 0xFE, 0xDB, + 0xA9, 0x76, 0x55, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xFF, 0xDD, 0xCA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCE, 0xEE, 0xDC, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x8A, 0xBD, 0xEF, 0xEE, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x79, 0xAB, 0xDE, 0xEF, 0xED, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBD, 0xFE, 0xEF, 0xEC, 0xBA, 0x98, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDE, 0xEF, 0xFF, 0xDC, 0xBA, 0x99, 0x88, 0x89, 0x9A, 0xAB, 0xCD, 0xEE, + 0xFF, 0xFE, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xEF, 0xFF, + 0xFF, 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xDD, 0xCD, 0xCD, 0xDD, 0xDF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEE, 0xEE, + 0xEE, 0xEF, 0xEF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDD, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFF, 0xCE, 0xFE, + 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEE, 0xFF, 0xFF, 0xDF, 0xED, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDF, 0xFF, 0xFE, 0xED, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xCD, 0xDF, 0xFF, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xEF, 0xFD, 0xDB, 0xB9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xFE, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xFC, 0xCB, 0x98, 0x77, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAC, 0xDE, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x79, 0xAB, 0xCD, 0xDC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xBA, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCC, 0xDD, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x89, 0xBC, 0xDD, 0xED, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCE, 0xDE, 0xEC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x89, 0xAB, 0xCD, 0xEE, + 0xFF, 0xEC, 0xBB, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xCC, 0xDF, 0xEF, 0xFF, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBD, 0xDE, 0xFF, 0xFF, 0xFF, 0xED, + 0xCC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xDD, + 0xDC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xEF, 0xED, 0xDD, + 0xDD, 0xDF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xCE, 0xFE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xEE, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFF, 0xFD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFF, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDF, 0xED, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xEE, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x67, 0x89, 0x9B, + 0xCD, 0xEC, 0xBA, 0x98, 0x76, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDD, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x67, 0x78, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x67, 0x8A, 0xBC, 0xDC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x78, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCD, 0xDD, 0xCA, 0x98, 0x87, 0x77, 0x67, 0x77, 0x89, 0xAB, + 0xCD, 0xDE, 0xEC, 0xBA, 0x99, 0x88, 0x77, 0x78, 0x89, 0xAA, 0xBC, 0xDD, + 0xEE, 0xDC, 0xBA, 0xA9, 0x98, 0x89, 0x99, 0xAA, 0xBC, 0xDE, 0xEF, 0xFE, + 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFE, 0xFF, 0xFE, 0xED, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xED, 0xDC, + 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xDF, 0xFF, 0xEE, 0xDD, 0xDD, 0xCD, + 0xDD, 0xDE, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xDC, 0xCC, 0xBC, 0xCC, 0xCD, 0xDD, 0xDE, 0xEE, 0xBE, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xCD, 0xEE, 0xFF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xEF, 0xFF, 0xFD, 0xDD, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xFE, 0xCD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xCC, 0xEE, 0xEC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCE, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x55, 0x56, 0x77, 0x8A, 0xAC, 0xDD, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xCC, 0xBA, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x99, 0xAC, 0xDC, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xEC, 0xCA, 0xA9, 0x88, 0x88, 0x88, 0x89, 0xAB, 0xBC, 0xDD, + 0xDE, 0xDC, 0xCB, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xDE, 0xFE, + 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xDD, 0xEF, 0xEE, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xEF, 0xFF, 0xFE, 0xEE, 0xDD, + 0xCD, 0xCD, 0xCD, 0xDD, 0xFF, 0xFE, 0xCE, 0xED, 0xEE, 0xDD, 0xDD, 0xCC, + 0xDD, 0xCD, 0xDE, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xEE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, 0xEF, 0xFF, 0xBE, 0xFF, + 0xFE, 0xDD, 0xDC, 0xCD, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xEF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFD, 0xEE, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBC, 0xDE, 0xFF, 0xFF, 0xDD, 0xDC, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xDD, 0xFF, 0xFD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x99, + 0xAC, 0xDE, 0xFF, 0xDD, 0xCB, 0x98, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xDF, 0xED, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xEE, + 0xDC, 0xBA, 0x97, 0x66, 0x55, 0x45, 0x56, 0x78, 0xAB, 0xCE, 0xED, 0xDB, + 0xA8, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xBC, 0xDE, 0xDC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9B, 0xCE, 0xDD, 0xDB, 0xA9, 0x76, 0x65, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xDE, 0xDD, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xDD, 0xEE, 0xEC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBD, 0xEE, 0xEF, 0xDC, 0xB9, 0x98, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDE, 0xEE, 0xFE, 0xDB, 0xAA, 0x98, 0x88, 0x88, 0x9A, 0xAB, 0xCE, 0xFE, + 0xFF, 0xED, 0xDB, 0xBA, 0xAA, 0x99, 0xAA, 0xBB, 0xCD, 0xEF, 0xEF, 0xFF, + 0xFE, 0xDC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFE, 0xFF, 0xFF, 0xFE, + 0xED, 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, + 0xDE, 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0xEE, 0xED, 0xDE, + 0xED, 0xDE, 0xEE, 0xFE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0xBC, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFE, 0xCD, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEE, 0xEC, 0xCB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xED, 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xBB, 0xCD, 0xDB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDD, 0xBB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xA9, + 0x98, 0x76, 0x65, 0x44, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x77, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBB, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xCC, 0xCB, 0xBA, 0x99, 0x88, 0x87, 0x88, 0x88, 0x9A, 0xAB, 0xCC, + 0xDD, 0xCB, 0xBA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xCD, 0xED, + 0xCB, 0xBA, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xDF, 0xED, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDD, 0xDE, 0xFE, 0xED, 0xDC, 0xCB, + 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xFD, 0xAE, 0xDD, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xCC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBB, 0xCC, + 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDD, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBB, + 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xAA, 0x99, 0x99, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xCC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xCC, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDC, 0xAD, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xAB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xAB, 0xAA, 0xA9, + 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCA, 0xBA, 0x99, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xAA, 0xA9, 0x88, 0x87, 0x77, 0x77, + 0x78, 0x88, 0x9A, 0xAB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x88, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x88, 0x77, + 0x66, 0x66, 0x56, 0x66, 0x77, 0x88, 0x9A, 0x99, 0x98, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0x99, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x99, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x89, + 0xAA, 0xAA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xBB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xBC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCC, 0xBC, 0xCB, 0xBA, 0xAA, 0x99, 0x99, + 0x9A, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xBC, 0xAB, 0xDC, + 0xBB, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xBB, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xCA, 0xBB, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0xAA, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xAA, + 0x9A, 0x98, 0x87, 0x66, 0x66, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0xA9, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0xAA, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBB, + 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xAA, 0xA9, 0x99, 0x89, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCC, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xDD, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xAD, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCC, 0xBB, 0xBB, 0xAB, 0xAB, 0xBB, 0xBC, 0xCC, 0xDD, 0xAC, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBA, 0xBB, 0xBC, 0xCD, 0xDE, 0xFD, 0xCD, 0xCB, 0xBA, + 0xAA, 0xA9, 0xAA, 0xAA, 0xBC, 0xCD, 0xDE, 0xDB, 0xCC, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xED, 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xCD, 0xCB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBB, 0xDC, 0xBB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xAA, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xAA, + 0x98, 0x76, 0x65, 0x44, 0x55, 0x67, 0x88, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x77, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBB, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCB, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xCC, 0xCB, 0xBA, 0x98, 0x88, 0x87, 0x88, 0x89, 0x9A, 0xAC, 0xCC, + 0xCD, 0xCB, 0xBA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xCD, 0xDD, + 0xCB, 0xBA, 0xAA, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xDC, 0xDE, 0xDD, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xDD, 0xFE, 0xED, 0xDC, 0xCB, + 0xBB, 0xBB, 0xCC, 0xCC, 0xDD, 0xED, 0xBD, 0xED, 0xDC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xCC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFF, 0xFF, 0xEF, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFF, 0xFE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, + 0xDD, 0xDC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xCC, 0xBB, + 0xBB, 0xBC, 0xCE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xAA, 0x99, 0x9A, + 0xAB, 0xCD, 0xFF, 0xFF, 0xFF, 0xFE, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0xAB, + 0xCD, 0xFF, 0xFF, 0xEF, 0xDC, 0xA9, 0x87, 0x77, 0x77, 0x88, 0xAB, 0xCE, + 0xFF, 0xFE, 0xED, 0xBA, 0x87, 0x66, 0x55, 0x66, 0x79, 0xAC, 0xDF, 0xFF, + 0xFF, 0xCB, 0x98, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBC, 0xFF, 0xFF, 0xEC, + 0xB9, 0x86, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xDE, 0xFF, 0xFE, 0xDB, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xEF, 0xFF, 0xED, 0xBA, 0x87, 0x65, + 0x44, 0x55, 0x78, 0x9B, 0xCE, 0xFF, 0xFF, 0xDC, 0xA9, 0x86, 0x65, 0x55, + 0x67, 0x8A, 0xBC, 0xEF, 0xFF, 0xFE, 0xDB, 0xA8, 0x87, 0x66, 0x77, 0x89, + 0xAC, 0xDF, 0xFF, 0xFF, 0xED, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xFF, 0xFF, 0xFF, 0xED, 0xCB, 0xA9, 0x99, 0x9A, 0xAB, 0xCD, 0xEF, 0xFF, + 0xFF, 0xFF, 0xED, 0xCC, 0xBB, 0xBB, 0xBB, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xDD, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCC, 0xCC, 0xBC, 0xDC, 0xDD, 0xEE, 0xFF, 0xBD, 0xFD, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xFF, 0xED, 0xDC, 0xBB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xBC, 0xDD, 0xEE, 0xCC, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDF, 0xEC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0x9B, 0xCD, 0xFD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCB, 0x98, 0x77, 0x66, 0x55, 0x56, 0x67, 0x89, 0xBC, 0xDD, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xCC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xB9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDD, 0xDB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBB, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xEC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xCC, 0xEE, + 0xEE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xEE, 0xFE, + 0xDC, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xFE, 0xDD, + 0xCC, 0xBC, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xEF, 0xFF, 0xFE, 0xED, 0xDD, + 0xCD, 0xCC, 0xCE, 0xDE, 0xFE, 0xFE, 0xAF, 0xFE, 0xEE, 0xDD, 0xDD, 0xCD, + 0xDD, 0xDE, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xCE, 0xFE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xEE, 0xDC, 0xCB, + 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFD, 0xDC, 0xBB, 0xA9, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFF, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDE, 0xEC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDE, 0xCC, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xDC, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDD, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x67, 0x79, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x8A, 0xBC, 0xDC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x89, 0xAB, 0xDD, 0xDD, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x89, 0xAB, 0xCD, 0xEE, + 0xEE, 0xDC, 0xBA, 0xA9, 0x98, 0x89, 0x99, 0xAA, 0xBC, 0xDE, 0xEE, 0xFE, + 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFF, 0xFF, 0xFE, 0xDD, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xED, 0xDC, + 0xCC, 0xCD, 0xDD, 0xEE, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCD, 0xEE, 0xFF, 0xFF, 0xBF, 0xFE, + 0xED, 0xCC, 0xCC, 0xBB, 0xCC, 0xDD, 0xDF, 0xFF, 0xFF, 0xFE, 0xED, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xEF, 0xFF, 0xFD, 0xED, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xFF, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBD, 0xDF, 0xFD, 0xDB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0x9B, 0xCD, 0xFF, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xEC, 0xBB, 0x98, 0x77, 0x65, 0x55, 0x56, 0x67, 0x89, 0xBC, 0xDE, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x99, 0xBC, 0xDD, 0xDD, 0xCA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xEE, 0xEC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x89, 0xAB, 0xCD, 0xDD, + 0xFF, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xFF, 0xFF, + 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xFF, 0xFF, 0xFE, 0xED, + 0xCC, 0xCB, 0xBB, 0xBC, 0xCD, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, + 0xDC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xEE, 0xEE, 0xDD, 0xDE, 0xDE, 0xEE, 0xEE, 0xFE, 0xEF, 0xAF, 0xFF, + 0xFE, 0xED, 0xDD, 0xDD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFE, 0xDC, + 0xCC, 0xCB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFE, 0xFE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAB, 0xCC, 0xDE, 0xFF, 0xFF, 0xEE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDE, 0xFF, 0xFE, 0xEC, 0xBA, 0x99, 0x87, 0x77, 0x88, 0x9A, + 0xBC, 0xDF, 0xFF, 0xED, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBD, + 0xEF, 0xFD, 0xDC, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9B, 0xCD, 0xFF, + 0xDD, 0xBA, 0x98, 0x66, 0x54, 0x45, 0x56, 0x89, 0xAC, 0xDE, 0xED, 0xDB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBD, 0xEE, 0xED, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xDE, 0xFE, 0xDC, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBD, 0xEE, 0xED, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xDE, 0xEE, 0xED, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9B, 0xCD, 0xFE, 0xFF, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDF, 0xFF, 0xFE, 0xDC, 0xBA, 0x99, 0x98, 0x99, 0x9A, 0xBC, 0xDF, 0xFF, + 0xFF, 0xFE, 0xDC, 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFF, 0xFF, + 0xFE, 0xDD, 0xCC, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEE, 0xDD, 0xDC, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, + 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, + 0xEE, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCC, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDE, 0xBC, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDE, 0xFE, 0xCC, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xDE, 0xEB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xDD, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x9A, 0xAB, 0xCD, 0xDB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xCA, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x65, 0x44, 0x55, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0x98, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x77, 0x89, 0xAB, 0xBB, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBB, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x67, 0x77, + 0x89, 0xAA, 0xBB, 0xBB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xCC, 0xCB, 0xAA, 0x98, 0x88, 0x87, 0x88, 0x89, 0x9A, 0xBB, 0xCC, + 0xCD, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xCD, 0xDD, + 0xCB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDD, 0xDE, 0xDC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xDE, 0xFE, 0xED, 0xCC, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xED, 0xAE, 0xDD, 0xDC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xCC, 0xCD, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xAB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDD, 0xBB, 0xBA, 0xA9, + 0x99, 0x98, 0x89, 0x99, 0xAA, 0xBB, 0xCD, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCC, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBB, + 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xAA, 0xA9, 0x99, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xCD, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xAC, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xAB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xBB, 0xBA, 0xA9, + 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xCA, 0xBA, 0x99, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xAA, 0xA9, 0x88, 0x87, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xAB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0x99, 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x88, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x65, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x88, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xBA, + 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xBB, 0xCB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xCC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xCC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDC, 0xBC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xAB, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCD, 0xDC, 0xBC, 0xBB, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCC, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x56, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBB, + 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xAA, 0xA9, 0x99, 0x88, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xCC, 0xBA, + 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xCD, 0xCC, 0xDC, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0xAD, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDD, 0xAC, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xCC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDE, 0xEB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xDD, 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x78, + 0x88, 0x99, 0xAB, 0xCD, 0xCB, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCC, 0xAB, 0xA9, 0x87, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xCA, 0xA9, 0x98, 0x77, 0x66, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x77, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xBB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBC, 0xBC, 0xCB, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x89, 0x9A, 0xAB, 0xCC, + 0xCC, 0xCB, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xCD, 0xDC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDD, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xDE, 0xEE, 0xDD, 0xCC, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xED, 0xBE, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xCC, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, + 0xFF, 0xFE, 0xED, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, + 0xCC, 0xCC, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xCB, 0xBA, + 0xAA, 0xBB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xDD, 0xBB, 0xA9, 0x99, 0x99, + 0xAA, 0xBD, 0xEF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x88, 0x77, 0x88, 0x9A, + 0xCD, 0xFF, 0xFF, 0xFE, 0xDB, 0xA9, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xCD, + 0xFF, 0xFF, 0xDC, 0xB9, 0x87, 0x65, 0x55, 0x56, 0x78, 0xAB, 0xDF, 0xFF, + 0xFD, 0xCA, 0x98, 0x65, 0x54, 0x45, 0x56, 0x89, 0xBC, 0xEF, 0xFE, 0xDC, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xFF, 0xFE, 0xCA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAC, 0xDF, 0xFF, 0xEC, 0xB9, 0x87, 0x55, + 0x44, 0x55, 0x67, 0x9A, 0xCD, 0xFF, 0xFF, 0xDB, 0xA8, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xDF, 0xFF, 0xFD, 0xCB, 0x98, 0x76, 0x66, 0x67, 0x89, + 0xAB, 0xCF, 0xFF, 0xFF, 0xFD, 0xCA, 0x98, 0x87, 0x77, 0x89, 0x9A, 0xCD, + 0xFF, 0xFF, 0xFF, 0xEC, 0xBB, 0xA9, 0x99, 0x99, 0xAA, 0xBC, 0xDF, 0xFF, + 0xFF, 0xFF, 0xDD, 0xCB, 0xBA, 0xAA, 0xAB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xDC, 0xCC, 0xCC, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xDC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0xDE, 0xAF, 0xFE, + 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xEF, 0xDD, 0xCB, + 0xBB, 0xAA, 0xAB, 0xBB, 0xCD, 0xEE, 0xFF, 0xEE, 0xED, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCD, 0xEE, 0xFF, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xED, 0xDC, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCE, 0xEE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xDE, 0xEC, 0xCB, 0x98, 0x76, 0x65, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xDC, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xDD, 0xDB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xDE, 0xED, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEE, + 0xDE, 0xEC, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xEF, 0xEE, 0xFE, + 0xED, 0xCB, 0xBB, 0xAA, 0xAB, 0xBB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xED, + 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0xED, + 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xAF, 0xEE, 0xEE, 0xED, 0xDD, 0xDD, + 0xDD, 0xED, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCC, 0xCC, 0xBC, 0xCC, 0xDD, 0xDD, 0xEE, 0xBE, 0xFE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFF, 0xFE, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFF, 0xED, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xFE, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAB, 0xCC, 0xDE, 0xDC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x77, 0x8A, 0xBC, 0xDD, + 0xBC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCC, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xB9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDD, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDD, + 0xDE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xED, 0xEE, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFE, 0xEF, 0xFE, 0xDD, + 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xEE, 0xFF, 0xEE, 0xED, 0xDC, + 0xCC, 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xBE, 0xEE, 0xED, 0xDD, 0xDD, 0xCD, + 0xCD, 0xDD, 0xEE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xCC, 0xCC, 0xDC, 0xDD, 0xDE, 0xEF, 0xEF, 0xAE, 0xFE, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xDE, 0xEF, 0xFF, 0xFE, 0xEE, 0xDD, 0xDB, + 0xBB, 0xBA, 0xAB, 0xBC, 0xCD, 0xEE, 0xFF, 0xED, 0xED, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xBB, 0xCD, 0xEF, 0xFE, 0xDD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xED, 0xDB, 0xB9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xEE, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAC, + 0xDE, 0xDC, 0xCB, 0x98, 0x76, 0x65, 0x55, 0x56, 0x77, 0x9A, 0xBC, 0xED, + 0xCC, 0xB9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xBC, 0xDD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xDC, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCD, 0xDD, 0xDC, 0xB9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xDE, 0xDB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xDD, 0xEE, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEE, + 0xFF, 0xED, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xDE, 0xEE, 0xFF, + 0xDD, 0xCC, 0xBB, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xEE, 0xFF, 0xFE, 0xED, + 0xDC, 0xCB, 0xCC, 0xCC, 0xCD, 0xEE, 0xFF, 0xEE, 0xFF, 0xFF, 0xFE, 0xED, + 0xDD, 0xDD, 0xDE, 0xEE, 0xEF, 0xFF, 0xAE, 0xEE, 0xEE, 0xED, 0xED, 0xDD, + 0xDD, 0xDE, 0xEE, 0xFE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, + 0xFF, 0xFF, 0xED, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, + 0xCC, 0xCC, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCB, 0xBA, + 0xAA, 0xBB, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBB, 0xA9, 0x99, 0x99, + 0xAB, 0xBD, 0xFF, 0xFF, 0xFF, 0xFD, 0xCA, 0xA9, 0x87, 0x77, 0x88, 0x9A, + 0xBD, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xCD, + 0xFF, 0xFF, 0xFC, 0xB9, 0x87, 0x65, 0x55, 0x56, 0x78, 0xAB, 0xDF, 0xFF, + 0xFD, 0xCA, 0x97, 0x65, 0x54, 0x45, 0x56, 0x89, 0xAC, 0xFF, 0xFF, 0xDC, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xCF, 0xFF, 0xFD, 0xCA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAC, 0xDF, 0xFF, 0xFC, 0xB9, 0x86, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xCD, 0xFF, 0xFF, 0xDB, 0xA8, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xEF, 0xFF, 0xFF, 0xCA, 0x98, 0x76, 0x66, 0x67, 0x89, + 0xAB, 0xCF, 0xFF, 0xFF, 0xFD, 0xBA, 0x98, 0x87, 0x77, 0x89, 0x9B, 0xCD, + 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0xA9, 0x99, 0x99, 0xAB, 0xBC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xED, 0xCB, 0xBA, 0xAA, 0xAB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xDC, 0xCC, 0xCC, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCC, 0xBC, 0xBC, 0xCC, 0xDD, 0xDE, 0xEE, 0xAE, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xFF, 0xFE, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xEF, 0xED, 0xDC, 0xBB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xFE, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xDF, 0xEC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xEE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, 0x98, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBC, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xAC, 0xDD, 0xDD, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xBC, 0xED, + 0xEE, 0xDC, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xEE, 0xFE, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xEE, 0xEF, 0xFE, 0xDD, + 0xCC, 0xCB, 0xBB, 0xBC, 0xCD, 0xDD, 0xEF, 0xEE, 0xFF, 0xFE, 0xED, 0xDD, + 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFE, 0x9E, 0xED, 0xDD, 0xDD, 0xDC, 0xCC, + 0xDD, 0xDD, 0xDE, 0xEF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0x9C, 0xDC, + 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xED, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDD, 0xDB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xDC, 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x78, + 0x88, 0x99, 0xAB, 0xBC, 0xCA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCC, 0xAB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x67, 0x78, 0x9A, + 0xAC, 0xCA, 0xA9, 0x98, 0x76, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0xAA, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xBB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBC, 0xBB, 0xBB, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xCC, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBD, 0xDC, 0xCD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xCC, 0xEE, 0xDC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xED, 0x9D, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xCC, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0x9B, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xBB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBC, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBA, + 0xAB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xBC, 0xDC, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0x9C, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0x9B, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCD, 0xCA, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x99, 0xAA, 0xCC, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x9A, + 0xAC, 0xBA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBB, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xB9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x87, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xBA, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBA, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xBB, 0xBB, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xBB, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xCD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCC, 0xDC, 0xCC, 0xCB, 0xBB, + 0xBB, 0xAB, 0xBB, 0xCC, 0xCD, 0xDC, 0x9C, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0xEF, 0x9E, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAB, 0xBB, 0xCD, 0xEE, 0xFF, 0xFD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCD, 0xEF, 0xFF, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xEC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xEE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x78, 0x89, 0xAB, + 0xDE, 0xEC, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9B, 0xCD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0x98, 0x76, 0x65, + 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9B, 0xBD, 0xDD, 0xDB, 0xB9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDD, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xEE, 0xED, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xEE, 0xFE, + 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFE, 0xEF, 0xFE, 0xDD, + 0xDC, 0xCB, 0xBB, 0xCC, 0xCD, 0xEE, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0xDD, + 0xDC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xAE, 0xFE, 0xEE, 0xED, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEE, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xED, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, + 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xAA, 0xAB, + 0xBC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xBA, 0x99, 0x89, 0x9A, 0xBB, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xBC, 0xEF, + 0xFF, 0xFF, 0xFF, 0xCB, 0x98, 0x65, 0x55, 0x67, 0x8A, 0xBC, 0xFF, 0xFF, + 0xFF, 0xDC, 0xA9, 0x75, 0x44, 0x44, 0x67, 0x9B, 0xCF, 0xFF, 0xFF, 0xFE, + 0xCA, 0x87, 0x54, 0x33, 0x45, 0x79, 0xAC, 0xDF, 0xFF, 0xFF, 0xDC, 0xA9, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xCE, 0xFF, 0xFF, 0xFF, 0xCB, 0x97, 0x64, + 0x44, 0x45, 0x79, 0xAC, 0xDF, 0xFF, 0xFF, 0xFD, 0xBA, 0x87, 0x65, 0x55, + 0x68, 0x9B, 0xCD, 0xFF, 0xFF, 0xFF, 0xDC, 0xB9, 0x87, 0x77, 0x78, 0x9A, + 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x89, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, 0xBB, 0xAA, 0xAB, 0xBC, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, 0xCC, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xCD, 0x9E, 0xFE, + 0xDD, 0xDD, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFE, 0xFD, 0xDE, 0xED, 0xDC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xEC, 0xDD, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xED, 0xED, 0xCD, 0xCC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xBB, 0xCD, 0xDF, 0xDC, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x9A, + 0xBC, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xDE, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9B, 0xBD, 0xED, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x66, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xED, 0xCD, 0xCA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9B, 0xCC, 0xED, 0xCD, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x89, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDC, 0xCC, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xED, + 0xDE, 0xDD, 0xCC, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xEE, 0xDC, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFE, 0xDF, 0xEE, 0xDD, + 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xED, 0xFF, 0xEE, 0xED, 0xDD, + 0xDD, 0xDE, 0xEF, 0xEF, 0xFF, 0xEE, 0x9D, 0xDD, 0xCD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEE, 0xFE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xCD, 0xDD, 0xDE, 0xAE, 0xEE, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDD, 0xEF, 0xFE, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xEF, 0xED, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xEE, 0xCC, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDE, 0xDC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xCC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x56, 0x77, 0x9A, 0xBC, 0xDD, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x88, 0x76, 0x55, 0x55, + 0x67, 0x78, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCD, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDC, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDD, + 0xDD, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xDD, 0xED, + 0xDC, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFE, 0xDF, 0xEE, 0xDC, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xFE, 0xFE, 0xFE, 0xDD, 0xDD, + 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFE, 0xAE, 0xED, 0xDD, 0xDD, 0xCC, 0xCC, + 0xCD, 0xDD, 0xEE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDE, 0x9F, 0xFF, + 0xED, 0xDD, 0xDD, 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFE, 0xEF, 0xED, 0xDC, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCE, 0xEE, 0xFF, 0xED, 0xED, 0xDC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xEE, 0xFD, 0xDE, 0xDC, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xCD, 0xEF, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x9A, + 0xBB, 0xCD, 0xED, 0xCD, 0xCB, 0xA8, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xED, + 0xCD, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x66, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x76, 0x65, + 0x45, 0x56, 0x67, 0x9A, 0xBC, 0xDD, 0xDD, 0xCA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDD, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x88, + 0x9A, 0xBD, 0xDD, 0xDD, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xCE, 0xDE, 0xED, 0xCB, 0xAA, 0x99, 0x88, 0x89, 0x9A, 0xBC, 0xCD, 0xED, + 0xEF, 0xED, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xEE, 0xDE, 0xFE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xFE, 0xDF, 0xFE, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCC, 0xDE, 0xEE, 0xEF, 0xEE, 0xFF, 0xEF, 0xEE, 0xDE, + 0xDD, 0xDD, 0xDE, 0xEF, 0xFF, 0xFF, 0xAE, 0xDD, 0xDD, 0xED, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, + 0xCC, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xCB, 0xAA, 0xAB, + 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x99, 0x89, 0x9A, 0xBC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xBC, 0xDF, + 0xFF, 0xFF, 0xFF, 0xCB, 0x98, 0x66, 0x55, 0x67, 0x8A, 0xBD, 0xFF, 0xFF, + 0xFF, 0xFC, 0xA9, 0x76, 0x44, 0x45, 0x67, 0x9B, 0xCD, 0xFF, 0xFF, 0xFF, + 0xCA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAC, 0xFF, 0xFF, 0xFF, 0xFC, 0xA9, + 0x75, 0x43, 0x24, 0x57, 0x8A, 0xCE, 0xFF, 0xFF, 0xFF, 0xCB, 0x97, 0x65, + 0x44, 0x46, 0x79, 0xAC, 0xDF, 0xFF, 0xFF, 0xFD, 0xBA, 0x87, 0x65, 0x56, + 0x68, 0x9B, 0xCD, 0xFF, 0xFF, 0xFF, 0xDC, 0xB9, 0x87, 0x77, 0x78, 0x9A, + 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x99, 0x89, 0x9A, 0xBC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xAA, 0xAB, 0xBC, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDD, 0x9E, 0xFE, + 0xDD, 0xDC, 0xCC, 0xBC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFE, 0xDE, 0xDD, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xED, 0xED, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xEE, 0xDD, 0xCC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x99, 0x87, 0x76, 0x67, 0x78, 0x9A, 0xBC, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x34, 0x55, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x34, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x68, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x77, 0x88, + 0x9A, 0xBC, 0xDD, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xDE, 0xDD, 0xEC, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0x9A, 0xBB, 0xCD, 0xED, + 0xDE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xED, 0xEE, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xEE, 0xEF, 0xFE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xED, 0xFF, 0xEE, 0xED, 0xDD, + 0xCD, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0x8E, 0xDD, 0xDD, 0xCC, 0xCC, 0xCD, + 0xDD, 0xDD, 0xDE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x9B, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCC, 0xEC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAA, 0xBC, 0xCD, 0xBB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xAB, 0xBA, 0xA9, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0x9A, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBA, 0x9A, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x89, 0xAA, 0xBA, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBB, 0xBA, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xA9, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCC, 0xBC, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xCC, 0xDD, 0xDC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xCD, 0xEC, 0x8C, 0xBB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0x9B, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xAB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBA, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBA, + 0xAB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xBB, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDC, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0x8B, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xDC, 0xBC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCB, 0xBA, 0x99, 0x98, + 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x88, + 0x88, 0x9A, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xBA, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xBB, 0xCB, 0xAA, 0x98, 0x88, 0x87, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xAB, 0xCC, 0xCC, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xCD, 0xCC, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xDC, 0x8C, 0xBB, 0xBB, 0xBB, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xCD, 0xDD, 0x8E, 0xFE, + 0xED, 0xDD, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xFD, 0xDE, 0xED, 0xCC, + 0xCB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEE, 0xEF, 0xED, 0xDD, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xEE, 0xFD, 0xDD, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xBB, 0xCD, 0xEE, 0xEC, 0xDC, 0xBA, 0xA9, 0x88, 0x77, 0x88, 0x9A, + 0xBC, 0xCE, 0xED, 0xCD, 0xCB, 0xA9, 0x87, 0x76, 0x67, 0x78, 0x9A, 0xBC, + 0xDE, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xED, + 0xCC, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x34, 0x45, 0x68, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, + 0x65, 0x44, 0x34, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xDB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xDD, 0xDD, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCE, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x77, 0x89, + 0xAB, 0xCC, 0xDD, 0xDD, 0xDB, 0xAA, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xDE, 0xDD, 0xED, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xED, + 0xDE, 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEF, 0xED, 0xFF, + 0xED, 0xDC, 0xCB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEE, 0xFE, 0xDF, 0xFE, 0xDD, + 0xDC, 0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFD, 0xFF, 0xFE, 0xEE, 0xED, + 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0x9D, 0xDD, 0xDE, 0xDD, 0xDD, 0xCD, + 0xDD, 0xEE, 0xDE, 0xEF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFE, 0xEE, 0xDE, 0xDD, 0xDD, 0xDD, 0xED, 0xDD, 0xDD, 0x9F, 0xFF, + 0xFF, 0xFF, 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, + 0xDD, 0xDD, 0xCD, 0xDD, 0xDE, 0xEF, 0xFF, 0xEE, 0xFF, 0xED, 0xDC, 0xCB, + 0xBB, 0xCC, 0xCD, 0xEE, 0xFF, 0xFE, 0xEF, 0xED, 0xCC, 0xBA, 0xAA, 0xAA, + 0xBB, 0xCD, 0xEE, 0xFF, 0xFE, 0xEE, 0xDC, 0xBA, 0x98, 0x88, 0x99, 0xAB, + 0xCD, 0xDE, 0xFE, 0xEF, 0xDC, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xEE, 0xED, 0xCA, 0x98, 0x76, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xFF, + 0xEE, 0xCB, 0xA8, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBD, 0xDF, 0xEE, 0xED, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xDE, 0xFF, 0xDE, 0xCB, 0xA8, + 0x75, 0x43, 0x24, 0x57, 0x8A, 0xBD, 0xEF, 0xED, 0xED, 0xBA, 0x97, 0x65, + 0x44, 0x46, 0x78, 0xAB, 0xDD, 0xFE, 0xDF, 0xDC, 0xA9, 0x87, 0x65, 0x56, + 0x78, 0x9A, 0xCD, 0xEF, 0xEE, 0xED, 0xDB, 0xA9, 0x87, 0x77, 0x78, 0x9A, + 0xBC, 0xDF, 0xFE, 0xDF, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBB, 0xDD, + 0xFF, 0xFD, 0xFE, 0xDD, 0xCB, 0xAA, 0xAA, 0xAA, 0xBC, 0xDD, 0xFE, 0xFE, + 0xDF, 0xEE, 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFD, 0xFE, + 0xFE, 0xDD, 0xDC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xDF, 0xFE, 0xFF, + 0xEE, 0xED, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xED, 0xFE, 0xEF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0x9E, 0xFE, + 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xEE, 0xDE, 0xDD, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDD, 0xEF, 0xED, 0xDD, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xED, 0xCD, 0xCB, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x78, 0x99, 0xAB, + 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x66, 0x54, 0x45, 0x66, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x89, 0xBC, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x86, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xAA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xBD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, 0x88, 0x89, 0x9A, 0xBC, 0xCD, 0xEE, + 0xDD, 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xED, 0xEE, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFE, 0xDE, 0xEE, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xED, 0xFF, 0xEE, 0xEE, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0x9D, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xCD, 0xDD, 0xAE, 0xEE, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xDE, 0xED, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xDD, 0xDC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAA, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xCB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x56, 0x78, 0x89, 0xAB, 0xDC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBC, 0xAA, 0x88, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBC, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDC, 0xCC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCC, 0xDD, + 0xCD, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xDD, 0xED, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xDE, 0xDD, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xED, 0xFE, 0xED, 0xDD, 0xCC, + 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xFE, 0xAD, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xDE, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0x9E, 0xFE, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0xED, 0xDE, 0xED, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xDD, 0xED, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xED, 0xDD, 0xCC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCD, 0xDE, 0xDC, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0xA9, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCC, 0xBA, 0x98, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xBC, 0xDC, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0x9A, 0xBB, 0xCD, 0xED, + 0xDE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDE, 0xDD, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xED, 0xDF, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xDD, 0xEE, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEE, 0xEF, 0xFE, 0x9D, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xDD, 0xDE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFE, 0xFD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xEE, 0xDD, + 0xDD, 0xDD, 0xFE, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xFD, 0xCC, 0xBB, 0xBC, + 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xCB, 0xBA, 0xAA, 0xAB, 0xCD, + 0xDE, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xCD, 0xEF, + 0xFF, 0xFF, 0xFF, 0xEC, 0xA9, 0x86, 0x66, 0x78, 0x9B, 0xCE, 0xFF, 0xFF, + 0xFF, 0xED, 0xCA, 0x86, 0x54, 0x45, 0x78, 0xAC, 0xDE, 0xFF, 0xFF, 0xFF, + 0xCB, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xBD, 0xFF, 0xFF, 0xEF, 0xFE, 0xBA, + 0x86, 0x42, 0x24, 0x68, 0xAC, 0xDE, 0xFF, 0xFF, 0xFE, 0xDC, 0xA8, 0x75, + 0x44, 0x56, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xED, 0xCB, 0x98, 0x76, 0x66, + 0x79, 0xAC, 0xDF, 0xFF, 0xFF, 0xFF, 0xED, 0xCA, 0x98, 0x88, 0x89, 0xAB, + 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xBB, 0xAA, 0xAA, 0xAB, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xED, 0xDD, 0xDD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0xFE, 0xFF, 0xEF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCD, 0xDD, 0x9D, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xFE, 0xDE, 0xDD, 0xCC, + 0xBB, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xEE, 0xED, 0xDD, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAB, 0xCC, 0xDD, 0xED, 0xCD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xBC, 0xDE, 0xDC, 0xCB, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x78, 0x89, 0xAB, + 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xBB, 0xA9, 0x87, 0x66, 0x54, 0x55, 0x66, 0x78, 0x9A, 0xCD, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x45, 0x67, 0x89, 0xAB, 0xCC, 0xBC, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xCA, 0x98, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCC, 0xCA, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x9A, 0xBB, + 0xCD, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCD, 0xDD, + 0xDE, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xDE, 0xDD, 0xED, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDE, 0xFE, 0xDE, 0xED, 0xDC, + 0xCC, 0xCB, 0xBB, 0xCC, 0xDD, 0xDE, 0xEF, 0xED, 0xEF, 0xEE, 0xDD, 0xDD, + 0xDC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFE, 0x8D, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCD, 0xDE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0x9C, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x99, 0xAB, 0xBC, 0xDC, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xBB, 0xBB, 0xA9, 0x98, 0x88, 0x87, 0x88, 0x89, 0x9A, 0xBB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xCB, 0xDC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xDC, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDE, 0xCC, 0xED, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xED, 0x8C, 0xCC, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0x9B, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDB, 0xBB, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x89, 0xAA, 0xBB, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x67, 0x77, + 0x89, 0x9A, 0xBA, 0xAA, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xBA, 0xCB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xBB, 0xCC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0x9B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0x9C, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xBB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x78, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x99, 0x87, 0x76, 0x65, 0x56, + 0x67, 0x78, 0x99, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x89, 0xAA, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xBA, 0xBB, 0xA9, 0x98, 0x88, 0x87, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDB, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCC, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xCD, 0xDC, 0x8C, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCD, 0x8D, 0xEE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDD, 0xEE, 0xFD, 0xDD, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xEF, 0xDD, 0xDC, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAB, 0xBC, 0xDD, 0xED, 0xCC, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xBC, 0xDD, 0xDC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCC, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xCB, 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xBB, 0xA9, 0x87, 0x66, 0x54, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x45, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x54, 0x56, 0x67, 0x89, 0xAB, 0xCC, 0xBC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x88, 0x9B, 0xBD, 0xCC, 0xCB, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCD, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x9A, 0xAB, + 0xCD, 0xCC, 0xDC, 0xBB, 0xA9, 0x98, 0x88, 0x89, 0x99, 0xAB, 0xCD, 0xDD, + 0xDD, 0xCC, 0xBA, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDE, 0xDD, 0xED, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDE, 0xEE, 0xDE, 0xDD, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xED, 0xFF, 0xDE, 0xDD, 0xDC, + 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFE, 0x9D, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xDE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xFF, 0xFE, 0xEF, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xEE, 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFD, 0xDC, 0xCC, + 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFE, 0xFF, 0xFE, 0xDC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xEF, 0xFF, 0xEF, 0xDC, 0xBA, 0x98, 0x76, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xEE, 0xED, 0xCA, 0x98, 0x66, 0x55, 0x66, 0x89, 0xAB, 0xDE, 0xFF, + 0xEE, 0xDB, 0xA8, 0x76, 0x44, 0x45, 0x67, 0x8A, 0xCD, 0xFF, 0xFE, 0xFD, + 0xBA, 0x86, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xDE, 0xFF, 0xDE, 0xDB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xBD, 0xEF, 0xFE, 0xFD, 0xBA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDE, 0xFF, 0xEE, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x68, 0x9A, 0xCD, 0xFF, 0xFE, 0xFD, 0xCB, 0xA9, 0x87, 0x76, 0x77, 0x9A, + 0xBC, 0xEF, 0xFF, 0xEF, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFD, 0xFE, 0xDC, 0xCB, 0xAA, 0x9A, 0xAA, 0xBC, 0xDF, 0xFF, 0xFF, + 0xDF, 0xFE, 0xDD, 0xCC, 0xBB, 0xBB, 0xCD, 0xDD, 0xFF, 0xFF, 0xFD, 0xFF, + 0xFE, 0xED, 0xDC, 0xDC, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xEE, + 0xEF, 0xED, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xCD, 0xDE, 0xDD, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xDD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0x9E, 0xFE, + 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xFD, 0xEE, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xED, 0xED, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFD, 0xDE, 0xCC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCD, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xED, 0xCD, 0xCB, 0xA8, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCD, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAC, 0xCE, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x89, + 0xAB, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xEC, 0xDD, 0xCB, 0xAA, 0x99, 0x89, 0x99, 0xAA, 0xBC, 0xDE, 0xEE, + 0xDD, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xEF, 0xEC, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFE, 0xDF, 0xEE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xED, 0xFE, 0xFF, 0xFC, 0xFF, 0xFE, 0xED, 0xDD, + 0xDD, 0xDD, 0xEE, 0xFE, 0xFF, 0xFF, 0x9D, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xED, 0xDE, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xCD, 0xDD, 0xAE, 0xEE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xEE, 0xDE, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xED, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xCD, 0xDC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAA, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xDC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBC, 0xAA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xCD, 0xCC, 0xBA, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xED, 0xED, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xFE, 0xDE, 0xDD, 0xCC, + 0xCC, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xFF, 0xED, 0xFE, 0xED, 0xDD, 0xCC, + 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFF, 0xAD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xEE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0x9E, 0xFF, + 0xEE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEF, 0xFD, 0xEF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xDD, 0xED, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xCC, 0xDD, 0xED, 0xDE, 0xDC, 0xBA, 0xA9, 0x98, 0x89, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCD, 0xCB, 0xA8, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xCD, 0xDC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xBC, 0xDD, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xCD, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, 0x98, 0x99, 0x9A, 0xBB, 0xCD, 0xDD, + 0xDE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDD, 0xDD, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xED, 0xDE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEF, 0xDD, 0xFE, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEE, 0xEF, 0xFE, 0x9D, 0xDD, 0xDD, 0xDD, 0xDD, 0xCC, + 0xDD, 0xDD, 0xDE, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFE, 0xEE, 0xDD, 0xDD, 0xDC, 0xCC, 0xDD, 0xCD, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFE, 0xDE, 0xEE, 0xDF, 0xEF, 0xFF, 0xFE, 0xEF, 0xFF, 0xFF, + 0xDD, 0xDC, 0xCC, 0xDD, 0xDE, 0xEE, 0xFF, 0xDF, 0xFF, 0xEE, 0xDC, 0xCB, + 0xBB, 0xBC, 0xCD, 0xDD, 0xFF, 0xFE, 0xFF, 0xFD, 0xDC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCD, 0xEE, 0xFF, 0xEE, 0xEE, 0xCC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCC, 0xEF, 0xFF, 0xFF, 0xDC, 0xBA, 0x88, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xEF, 0xFE, 0xED, 0xCA, 0x97, 0x65, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xFE, + 0xEE, 0xDB, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xEE, 0xED, 0xFC, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0x9B, 0xDE, 0xFF, 0xDD, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xBC, 0xEF, 0xFD, 0xDC, 0xBA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDE, 0xFF, 0xDE, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x68, 0x9A, 0xCD, 0xEF, 0xFD, 0xED, 0xCB, 0xA9, 0x87, 0x77, 0x78, 0x9A, + 0xBC, 0xEF, 0xFF, 0xDE, 0xEC, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDD, + 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBC, 0xDD, 0xEF, 0xFF, + 0xEF, 0xFE, 0xDD, 0xCC, 0xBB, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFE, 0xFE, + 0xEE, 0xDD, 0xDC, 0xCC, 0xCD, 0xDF, 0xEF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xEE, 0xED, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDE, 0xED, 0xDE, 0xFF, + 0xEF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xDD, 0xDC, 0xCC, 0xCC, 0xCB, 0xCC, 0xCC, 0xCC, 0xCD, 0x8E, 0xFE, + 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xEE, 0xEF, 0xFD, 0xDE, 0xED, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xED, 0xED, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFD, 0xDD, 0xCC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCD, 0xEE, 0xDC, 0xDC, 0xBA, 0x98, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCC, 0xCA, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x98, 0x66, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x34, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x68, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xBC, 0xED, 0xCD, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0x9A, 0xBC, 0xCD, 0xEE, + 0xDE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xDF, 0xED, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFE, 0xDE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xED, 0xFE, 0xEE, 0xED, 0xDD, + 0xCD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0x7C, 0xCC, 0xCC, 0xCC, 0xDC, 0xCD, + 0xDD, 0xDE, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0x8C, 0xDD, + 0xCB, 0xBB, 0xBA, 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xDC, 0xCC, 0xCB, 0xBA, + 0xAA, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0xDD, 0xCB, 0xCB, 0xBA, 0xA9, 0x99, + 0x89, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xCC, 0xBB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xBA, 0xAA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xCB, + 0xAA, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xAB, 0xBA, 0xA9, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0x9A, 0xBB, 0xAA, 0x99, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x78, 0x99, 0xAB, 0xBA, 0xAA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x89, 0xAA, 0xBB, 0xAA, 0xA9, 0x88, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x9A, 0xAB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x89, 0xAB, 0xCB, 0xBB, 0xAA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xBB, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCC, + 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x89, 0x99, 0xAA, 0xBB, 0xCD, 0xCB, 0xCC, + 0xCB, 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xBD, 0xDC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDE, 0xCC, 0xDD, 0xDC, 0xCC, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCD, 0xDD, 0xED, 0x8C, 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0x9B, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xBC, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBA, 0xBB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAA, 0xBB, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xDC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xDC, 0x9B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBC, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0x8C, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xCD, 0xDC, 0xBD, 0xCB, 0xBA, + 0xAA, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCB, 0xCB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDB, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xBC, 0xBB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x88, + 0x9A, 0xBB, 0xCB, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xBA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBB, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xBB, 0xBA, 0xA9, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAA, 0xBB, 0xAA, 0x99, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x99, 0xAB, 0xBA, 0xAA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x89, 0x9A, 0xBB, 0xAB, 0xA9, 0x88, 0x76, 0x65, 0x56, + 0x67, 0x78, 0x9A, 0xAB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x89, 0xAB, 0xBB, 0xBB, 0xBA, 0x98, 0x88, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xBB, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xCB, 0xDC, + 0xBB, 0xAA, 0xAA, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDC, 0xCD, 0xCC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDD, 0xCC, 0xDD, 0xCC, 0xCC, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCC, 0xDE, 0xED, 0x8C, 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xEE, 0xED, 0xDC, 0xCC, 0xBC, 0xCC, 0xCC, 0xDC, 0xCD, 0x7E, 0xFF, + 0xEE, 0xDD, 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0xEF, 0xFD, 0xEF, 0xED, 0xDC, + 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xEE, 0xFF, 0xED, 0xEE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xFE, 0xDE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xAB, 0xCD, 0xEF, 0xED, 0xEC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x9A, + 0xBB, 0xDD, 0xED, 0xDD, 0xCB, 0x99, 0x87, 0x76, 0x67, 0x78, 0x9A, 0xBC, + 0xCE, 0xDD, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xCD, 0xED, + 0xCC, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x34, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x34, 0x56, 0x79, 0xAB, 0xCD, 0xEC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCE, 0xDD, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x77, 0x89, + 0xAB, 0xCD, 0xED, 0xDD, 0xCB, 0xAA, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xDF, 0xED, 0xED, 0xCB, 0xAA, 0x99, 0x89, 0x99, 0xAA, 0xBC, 0xDE, 0xEF, + 0xDE, 0xDD, 0xCC, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFE, 0xFD, 0xFE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xDF, 0xEF, 0xED, + 0xDD, 0xCC, 0xCC, 0xCD, 0xEE, 0xFE, 0xFF, 0xFD, 0xEF, 0xEE, 0xFE, 0xDD, + 0xDD, 0xED, 0xEE, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xED, 0xFE, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xED, 0xDD, 0xDD, 0xDD, 0xCC, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFE, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFE, 0xCD, 0xDC, 0xDD, 0xDD, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xDC, 0xCC, + 0xBC, 0xBC, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, 0xBB, 0xAA, 0xAA, + 0xBB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCC, 0xDE, 0xFF, 0xFF, 0xFD, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xAB, 0xDD, + 0xFF, 0xFF, 0xFE, 0xCB, 0x98, 0x65, 0x55, 0x67, 0x89, 0xAC, 0xDF, 0xFF, + 0xFF, 0xDB, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xCD, 0xFF, 0xFF, 0xFD, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCE, 0xFF, 0xEF, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xBD, 0xFF, 0xFE, 0xFD, 0xCA, 0x97, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDD, 0xFF, 0xEF, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xCE, 0xFF, 0xFE, 0xFF, 0xDB, 0xA9, 0x87, 0x76, 0x77, 0x9A, + 0xBC, 0xFF, 0xFF, 0xEF, 0xFC, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFE, 0xFE, 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xBC, 0xDE, 0xFF, 0xFF, + 0xDF, 0xFE, 0xDC, 0xDC, 0xBB, 0xBB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFD, 0xFF, + 0xFE, 0xED, 0xDD, 0xDC, 0xDE, 0xFE, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, + 0xEF, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xDC, 0xDC, 0xDE, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xEE, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xFE, 0xED, 0xFF, 0xFE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xDD, 0xEE, 0xDC, 0xCB, 0xBB, + 0xAB, 0xBB, 0xBC, 0xCD, 0xDE, 0xED, 0xDE, 0xDD, 0xCB, 0xAA, 0x99, 0x99, + 0xAA, 0xBC, 0xCD, 0xEE, 0xDD, 0xDD, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0x9A, + 0xBC, 0xDD, 0xED, 0xCD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDD, 0xDC, 0xBA, 0x87, 0x66, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xDD, + 0xCD, 0xCA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xAC, 0xDE, 0xDC, 0xDB, + 0xA9, 0x87, 0x54, 0x33, 0x45, 0x78, 0x9A, 0xCD, 0xDD, 0xCD, 0xCA, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xAC, 0xCE, 0xDC, 0xDC, 0xBA, 0x87, 0x65, + 0x44, 0x55, 0x78, 0x9A, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x8A, 0xBC, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x87, 0x76, 0x77, 0x89, + 0xAB, 0xCD, 0xEE, 0xCD, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xDF, 0xDC, 0xED, 0xCB, 0xBA, 0xA9, 0x99, 0x9A, 0xAB, 0xBC, 0xEF, 0xFE, + 0xCE, 0xDD, 0xCC, 0xBB, 0xAA, 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xED, 0xED, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xDE, 0xEE, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xFD, 0xEE, 0xEE, 0xEE, 0xEE, + 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xED, 0xEE, 0xEF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xED, 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xCC, 0xAE, 0xFE, + 0xED, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xED, 0xEE, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xDC, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xCD, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xBC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDC, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xCD, 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xEC, 0xDD, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xFE, 0xCE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFC, 0xEE, 0xDD, 0xDC, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0x9D, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xDD, 0xDE, 0xEE, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xED, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xEE, 0xDD, 0xDC, 0xCC, 0xCC, 0xDD, 0xDD, 0xEE, 0xED, 0xFF, 0xFD, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xDF, 0xFE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFD, 0xEF, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDE, 0xEC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xED, 0xDD, 0xCB, 0xA8, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDD, 0xDD, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xDD, + 0xDD, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xED, 0xCD, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xDE, 0xEC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0xAB, 0xCD, 0xEE, 0xDD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xEF, 0xED, 0xDD, 0xCB, 0xAA, 0x99, 0x98, 0x99, 0x9A, 0xBC, 0xDE, 0xFE, + 0xDD, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFD, 0xFE, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xFF, 0xDE, 0xDD, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFD, 0xFE, 0xED, 0xDD, 0xED, + 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xDC, 0xDD, 0xCD, 0xDD, 0xDE, + 0xDE, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDD, 0xDC, 0xDD, 0xCC, 0xCC, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFD, 0xDD, 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xDD, 0xCB, + 0xBB, 0xBC, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, 0xBA, 0xAA, 0xAA, + 0xBB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCC, 0xDF, 0xFF, 0xFF, 0xDC, 0xBA, 0x97, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xFF, 0xFD, 0xCB, 0x98, 0x65, 0x55, 0x67, 0x89, 0xBC, 0xDF, 0xFF, + 0xFF, 0xDC, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xFF, 0xFF, 0xFD, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xFF, 0xDC, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xCD, 0xFF, 0xFF, 0xFD, 0xCA, 0x97, 0x65, + 0x44, 0x45, 0x78, 0xAC, 0xDF, 0xFF, 0xEF, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x68, 0x9A, 0xCE, 0xFF, 0xFF, 0xFE, 0xCB, 0xA9, 0x87, 0x77, 0x78, 0x9A, + 0xBC, 0xDF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFD, 0xFF, 0xDD, 0xBB, 0xAA, 0xAA, 0xAA, 0xBC, 0xDE, 0xFF, 0xFF, + 0xDF, 0xFD, 0xDD, 0xCB, 0xBB, 0xBB, 0xCD, 0xDF, 0xFF, 0xFF, 0xFD, 0xFF, + 0xDF, 0xDD, 0xDC, 0xDC, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFE, + 0xEF, 0xEF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xCD, 0xDD, 0xED, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xEF, 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0xDD, 0x7F, 0xFF, + 0xFF, 0xFE, 0xED, 0xEE, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xDC, 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFF, 0xEF, 0xFF, 0xFD, 0xDC, 0xCB, + 0xBB, 0xBC, 0xCD, 0xCF, 0xFF, 0xFE, 0xFF, 0xFD, 0xDB, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCC, 0xDE, 0xFF, 0xFF, 0xFD, 0xDC, 0xAA, 0x99, 0x89, 0x99, 0xAB, + 0xBC, 0xDF, 0xFF, 0xFD, 0xDC, 0xBA, 0x98, 0x77, 0x78, 0x89, 0xAB, 0xCD, + 0xFF, 0xEF, 0xED, 0xCA, 0x98, 0x76, 0x56, 0x67, 0x89, 0xBC, 0xDE, 0xFE, + 0xDE, 0xCB, 0xA9, 0x76, 0x54, 0x45, 0x68, 0x9A, 0xBC, 0xEF, 0xEE, 0xED, + 0xBA, 0x87, 0x64, 0x23, 0x46, 0x78, 0xAB, 0xDD, 0xFE, 0xFE, 0xDB, 0xA9, + 0x76, 0x43, 0x24, 0x57, 0x8A, 0xBD, 0xDE, 0xED, 0xFD, 0xBA, 0x98, 0x65, + 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xFF, 0xDD, 0xDC, 0xB9, 0x87, 0x66, 0x56, + 0x78, 0x9A, 0xBD, 0xEF, 0xFD, 0xFD, 0xCB, 0xA9, 0x88, 0x77, 0x78, 0x9A, + 0xBC, 0xDE, 0xFF, 0xDE, 0xDC, 0xBB, 0xA9, 0x98, 0x89, 0x9A, 0xAC, 0xDE, + 0xFF, 0xFE, 0xFE, 0xDD, 0xCB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xFF, + 0xDF, 0xED, 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xDD, 0xFF, 0xFF, 0xFD, 0xFF, + 0xEF, 0xDD, 0xDC, 0xCC, 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xEE, + 0xEE, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xED, + 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCC, 0xCC, 0xDD, 0xDC, 0xCE, + 0xEF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCC, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBA, 0xBB, 0xBB, 0x8D, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEC, 0xCD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCC, 0xDC, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xDC, 0xBC, 0xBA, 0xA9, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xCD, 0xBB, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, + 0x9A, 0xBC, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x66, 0x67, 0x78, 0x89, 0x9A, + 0xBC, 0xBB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xCB, + 0xAB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xBA, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCB, 0xAB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xBA, 0xBA, 0x98, 0x77, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCB, 0xAB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0xA9, 0x87, 0x77, 0x66, 0x66, 0x78, + 0x89, 0xAB, 0xCC, 0xBB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xBC, 0xCB, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x89, 0xAA, 0xBC, 0xDC, + 0xBC, 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xDD, 0xDB, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xED, 0xCD, 0xCC, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEF, 0xEC, 0xDD, 0xDD, 0xCC, 0xCC, + 0xCB, 0xCC, 0xCD, 0xDE, 0xEE, 0xFE, 0x8C, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, + 0xCC, 0xCC, 0xDE, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0x9B, 0xCC, + 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xBC, 0xBB, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0x9A, 0xBB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBA, 0xBA, 0x99, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xBB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCC, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xDC, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCC, 0xBB, 0xBB, 0xAA, 0xAA, 0xAB, 0xAB, 0xBB, 0xBC, 0x8D, 0xED, + 0xCC, 0xCB, 0xBA, 0xBA, 0xBB, 0xBB, 0xCC, 0xCD, 0xDC, 0xCD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCC, 0xCB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xBC, 0xBB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, + 0x9A, 0xAB, 0xCB, 0xBB, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xBA, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xCB, + 0xAB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBA, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xBB, 0xAA, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xAB, 0xBA, 0xBA, 0x98, 0x77, 0x65, + 0x55, 0x56, 0x67, 0x89, 0xAB, 0xBB, 0xAB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x66, 0x66, 0x78, + 0x89, 0xAB, 0xCB, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAA, + 0xBC, 0xCB, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBC, 0xDC, + 0xBC, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xCB, 0xCC, + 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xBD, 0xCC, 0xCC, + 0xBB, 0xBA, 0xAB, 0xBB, 0xBC, 0xCD, 0xDE, 0xDC, 0xED, 0xCC, 0xCB, 0xBB, + 0xBB, 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0x8C, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xCC, 0xCD, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xEF, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7F, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDC, 0xDE, 0xDE, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFE, + 0xDD, 0xCC, 0xBC, 0xCC, 0xDE, 0xEE, 0xFF, 0xEF, 0xFE, 0xED, 0xCB, 0xBB, + 0xAB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFE, 0xEF, 0xED, 0xCB, 0xAA, 0x99, 0x9A, + 0xAB, 0xBC, 0xDE, 0xEF, 0xED, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0x9A, + 0xBC, 0xDE, 0xFD, 0xEE, 0xDB, 0xA9, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xEF, 0xED, 0xEC, 0xBA, 0x87, 0x66, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xEE, + 0xDE, 0xCB, 0x98, 0x76, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDF, 0xED, 0xDC, + 0xB9, 0x86, 0x54, 0x33, 0x45, 0x78, 0x9B, 0xCD, 0xED, 0xDD, 0xCB, 0x98, + 0x75, 0x43, 0x34, 0x57, 0x89, 0xBC, 0xDE, 0xFD, 0xDD, 0xBA, 0x87, 0x65, + 0x44, 0x46, 0x78, 0x9B, 0xCD, 0xEF, 0xEE, 0xCB, 0xA9, 0x87, 0x65, 0x56, + 0x67, 0x8A, 0xBC, 0xDF, 0xFE, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x89, + 0xAC, 0xCE, 0xEF, 0xDE, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xEF, 0xFD, 0xED, 0xDC, 0xBB, 0xA9, 0xA9, 0x9A, 0xBB, 0xCD, 0xEF, 0xFF, + 0xEF, 0xED, 0xCC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xED, 0xFF, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xDE, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDD, + 0xDD, 0xDD, 0xDE, 0xDE, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFE, 0xEE, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDE, 0xDC, 0xED, 0xDD, 0xDE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, 0xCC, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCB, + 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBB, 0xAA, 0xAB, 0xBC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x98, 0x89, 0xAB, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, 0x87, 0x66, 0x78, 0xAB, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDB, 0x97, 0x54, 0x45, 0x79, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFC, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, + 0x96, 0x42, 0x24, 0x68, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xA9, 0x75, + 0x43, 0x57, 0x9A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xA8, 0x76, 0x67, + 0x89, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x88, 0x9A, 0xBC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCB, 0xAA, 0xAB, 0xBD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBB, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xDC, 0xDD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xDF, 0xDD, 0xDD, 0xCC, 0xDB, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xFE, 0xFD, 0xDD, 0xCC, 0xCC, 0xDD, 0xDD, 0xDE, 0xFD, 0xFF, 0xFF, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBC, 0xDD, 0xDD, 0xFF, 0xDF, 0xFD, 0xDD, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAC, 0xCC, 0xFF, 0xFD, 0xFF, 0xDD, 0xCA, 0xA9, 0x99, 0x99, + 0x9A, 0xAB, 0xCD, 0xEF, 0xDF, 0xDD, 0xCB, 0xA9, 0x88, 0x88, 0x88, 0x99, + 0xAC, 0xCD, 0xFD, 0xDE, 0xCB, 0xA9, 0x87, 0x76, 0x77, 0x78, 0x9A, 0xBC, + 0xDF, 0xED, 0xEC, 0xA9, 0x87, 0x66, 0x55, 0x67, 0x78, 0x9B, 0xBE, 0xFF, + 0xDD, 0xCA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAC, 0xDF, 0xFD, 0xCB, + 0xA9, 0x86, 0x54, 0x34, 0x45, 0x78, 0x9A, 0xBD, 0xEF, 0xDC, 0xBA, 0x98, + 0x65, 0x43, 0x34, 0x56, 0x89, 0xAC, 0xDE, 0xFC, 0xDB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x78, 0x9A, 0xBD, 0xDF, 0xDD, 0xBB, 0xA8, 0x77, 0x65, 0x55, + 0x67, 0x8A, 0xAC, 0xDF, 0xFC, 0xDC, 0xBA, 0x98, 0x77, 0x76, 0x77, 0x89, + 0xAB, 0xCE, 0xEF, 0xCD, 0xCB, 0xAA, 0x98, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xDF, 0xFD, 0xED, 0xCB, 0xBA, 0xA9, 0x99, 0x9A, 0xAA, 0xCD, 0xFF, 0xFF, + 0xDE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xFF, 0xFD, 0xFD, + 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xDD, 0xFE, 0xFF, 0xFF, 0xCE, 0xED, 0xED, + 0xDC, 0xCC, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xEF, 0xEF, + 0xEF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDE, 0xEF, 0xDF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xAF, 0xFF, + 0xED, 0xDC, 0xCC, 0xBB, 0xBC, 0xCC, 0xCD, 0xDE, 0xED, 0xFF, 0xED, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xEF, 0xFD, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xDD, 0xEE, 0xDB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xCD, 0xDD, 0xDC, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCB, 0x98, 0x76, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAC, 0xCD, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xA9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xEC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xEE, 0xCC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x99, 0xAC, + 0xDE, 0xFC, 0xCC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x9A, 0xAB, 0xCE, 0xFF, + 0xDD, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xEF, 0xFD, 0xED, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xEF, 0xFF, 0xDE, 0xED, 0xDC, + 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFD, 0xFE, 0xED, 0xDD, 0xDC, + 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xAD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xEE, 0xEF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xDD, 0xDD, 0xDD, 0xDC, 0xCC, 0x8F, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDE, 0xED, 0xDD, 0xDD, 0xFF, 0xFD, 0xFF, 0xFF, 0xFD, + 0xCC, 0xCC, 0xCC, 0xCB, 0xCD, 0xDE, 0xEF, 0xDF, 0xFF, 0xEC, 0xDB, 0xBB, + 0xAA, 0xAB, 0xBB, 0xCC, 0xDF, 0xFD, 0xFF, 0xFD, 0xCB, 0xA9, 0x99, 0x99, + 0xAA, 0xBC, 0xDD, 0xEF, 0xDF, 0xED, 0xCB, 0xA9, 0x88, 0x88, 0x88, 0x9A, + 0xBC, 0xCC, 0xFD, 0xFE, 0xDB, 0xA9, 0x87, 0x76, 0x77, 0x78, 0x9A, 0xBC, + 0xDE, 0xDF, 0xFC, 0xBA, 0x87, 0x66, 0x55, 0x67, 0x78, 0x9B, 0xBD, 0xFE, + 0xEF, 0xCA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCE, 0xED, 0xDC, + 0xA9, 0x86, 0x54, 0x33, 0x45, 0x68, 0x9A, 0xBC, 0xED, 0xED, 0xBA, 0x98, + 0x75, 0x43, 0x34, 0x57, 0x89, 0xAC, 0xDD, 0xED, 0xDC, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xFF, 0xFF, 0xCB, 0xA9, 0x87, 0x65, 0x56, + 0x67, 0x89, 0xBC, 0xDF, 0xED, 0xDC, 0xBA, 0x98, 0x87, 0x76, 0x77, 0x89, + 0xAB, 0xCE, 0xFF, 0xCE, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x89, 0xAB, 0xDD, + 0xFF, 0xFF, 0xFD, 0xCB, 0xBA, 0xA9, 0x99, 0x9A, 0xAB, 0xCD, 0xDF, 0xFF, + 0xDF, 0xEE, 0xCC, 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDF, 0xFF, 0xFE, 0xFD, + 0xDD, 0xCC, 0xBB, 0xCC, 0xCC, 0xCD, 0xFF, 0xFF, 0xFF, 0xDD, 0xDE, 0xDD, + 0xDC, 0xCD, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFC, 0xFF, 0xED, 0xDD, 0xDD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xCD, 0xCD, 0xDD, 0xEE, 0xDE, + 0xFE, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDF, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xBB, 0xBC, 0xCD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0x99, 0x99, 0xAB, 0xCF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0x97, 0x77, 0x89, 0xBC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDC, 0x97, 0x54, 0x46, 0x8A, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xB9, 0x74, 0x12, 0x57, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, + 0x97, 0x42, 0x24, 0x79, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xB9, 0x86, + 0x44, 0x57, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xA9, 0x87, 0x77, + 0x8A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xAA, 0x99, 0x9A, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCC, 0xBB, 0xBB, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFD, 0xDC, 0xDD, 0xCD, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xCC, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xBB, 0xBC, + 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBA, 0xA9, 0xAA, 0xBC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xA9, 0x88, 0x88, 0x9A, 0xBD, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFB, 0xB9, 0x87, 0x66, 0x78, 0x9A, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFD, 0xCA, 0x87, 0x54, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xFF, 0xFF, + 0xDB, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, + 0x86, 0x42, 0x24, 0x68, 0xAB, 0xCD, 0xFF, 0xFF, 0xFF, 0xDB, 0xA8, 0x75, + 0x44, 0x56, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0x98, 0x76, 0x66, + 0x79, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFC, 0xBA, 0xAA, 0x9A, 0xAC, 0xCC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xCB, 0xBB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDF, 0xDC, 0xCC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xDC, 0xDC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCB, 0xCC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xA9, 0x9A, 0xBC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x98, 0x77, 0x89, 0xBF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFC, 0xA8, 0x54, 0x46, 0x8A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xCA, 0x74, 0x12, 0x47, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xA7, 0x42, 0x24, 0x7A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0x86, + 0x44, 0x58, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0x87, 0x78, + 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x99, 0xAB, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCC, 0xCB, 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0x9C, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDC, 0xCC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBB, 0xBB, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xBB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xBB, 0xBA, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xCC, + 0xBB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xBC, 0xCB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCC, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xDC, 0xCB, 0xBB, 0xBB, + 0xBA, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0x9C, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xCC, 0xDD, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xED, 0xEE, 0xED, 0xDD, 0xDC, 0xCD, 0xDC, 0x7F, 0xFF, + 0xFF, 0xFE, 0xED, 0xDD, 0xDD, 0xFD, 0xFF, 0xEE, 0xFD, 0xFF, 0xFF, 0xDE, + 0xDD, 0xCC, 0xCC, 0xDD, 0xDD, 0xFF, 0xFF, 0xEF, 0xFF, 0xDD, 0xDC, 0xCC, + 0xBB, 0xCC, 0xBD, 0xDD, 0xEF, 0xFE, 0xFF, 0xFD, 0xDC, 0xBB, 0xAA, 0xAA, + 0xBB, 0xCD, 0xDE, 0xEF, 0xDF, 0xFE, 0xDC, 0xBA, 0x99, 0x99, 0x99, 0xAB, + 0xCC, 0xDE, 0xFD, 0xFD, 0xEC, 0xCA, 0x98, 0x87, 0x78, 0x89, 0xAB, 0xCD, + 0xFF, 0xDE, 0xFD, 0xCA, 0x98, 0x76, 0x66, 0x78, 0x9A, 0xBC, 0xDD, 0xFE, + 0xDD, 0xCB, 0xA9, 0x86, 0x54, 0x45, 0x78, 0x9A, 0xCE, 0xDF, 0xEE, 0xDC, + 0xBA, 0x97, 0x64, 0x23, 0x46, 0x79, 0xAB, 0xDD, 0xFD, 0xEE, 0xDB, 0xA9, + 0x76, 0x42, 0x24, 0x67, 0x9A, 0xBC, 0xDE, 0xEF, 0xEE, 0xCA, 0x98, 0x75, + 0x44, 0x56, 0x89, 0xAB, 0xDE, 0xFE, 0xEE, 0xDC, 0xBA, 0x88, 0x76, 0x66, + 0x78, 0x9B, 0xCD, 0xEF, 0xDD, 0xFD, 0xCB, 0xA9, 0x98, 0x77, 0x88, 0x9A, + 0xBC, 0xDF, 0xFF, 0xDF, 0xDD, 0xCB, 0xA9, 0x99, 0x99, 0x9A, 0xBC, 0xDE, + 0xFF, 0xFD, 0xEE, 0xDD, 0xCB, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFF, 0xFF, + 0xDF, 0xFD, 0xDC, 0xCC, 0xBC, 0xCB, 0xCC, 0xCE, 0xFF, 0xFF, 0xFD, 0xEF, + 0xFE, 0xDD, 0xDC, 0xCD, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xCF, 0xEE, 0xDD, + 0xEE, 0xDE, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xDF, 0xFF, + 0xFE, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCD, 0xCC, 0xDD, 0xEE, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF, 0xDF, 0xDC, 0xCB, 0xCD, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, + 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xCC, 0xBC, + 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xAA, 0xBB, 0xBC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xA9, 0x98, 0x89, 0xAB, 0xCD, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, 0x87, 0x66, 0x78, 0xAB, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCB, 0x97, 0x54, 0x45, 0x79, 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFC, 0xB9, 0x64, 0x22, 0x46, 0x9A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, + 0x86, 0x42, 0x23, 0x68, 0xAC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDC, 0xA9, 0x75, + 0x44, 0x57, 0x9B, 0xCF, 0xDF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA8, 0x76, 0x67, + 0x8A, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xA9, 0x88, 0x9A, 0xBC, + 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCB, 0xBB, 0xAB, 0xBC, 0xCF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFD, 0xDF, 0xCC, 0xCC, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xDD, 0xDF, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFD, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCD, 0xDD, + 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, 0xBB, 0xBB, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCB, 0xA9, 0xAA, 0xBC, 0xDD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x97, 0x77, 0x89, 0xAC, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFC, 0xA8, 0x64, 0x46, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xB9, 0x74, 0x12, 0x47, 0x9B, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, + 0x97, 0x42, 0x24, 0x79, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xBA, 0x86, + 0x44, 0x58, 0x9C, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0xA9, 0x87, 0x78, + 0x9A, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xBA, 0x99, 0xAB, 0xBD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xCC, 0xBB, 0xBC, 0xCE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xDC, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xFF, 0xFF, 0xFF, 0xDF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xED, 0xCC, 0xED, 0xBB, 0xCB, 0xBB, 0xCC, 0xBC, 0xCC, 0x6D, 0xFF, + 0xED, 0xDC, 0xCC, 0xBD, 0xCC, 0xDC, 0xEE, 0xFF, 0xFC, 0xED, 0xDF, 0xCD, + 0xCC, 0xCB, 0xCC, 0xCD, 0xCD, 0xDE, 0xFF, 0xCF, 0xED, 0xEC, 0xCB, 0xBA, + 0xBB, 0xBB, 0xCC, 0xCC, 0xDD, 0xFC, 0xDD, 0xDC, 0xBA, 0xBA, 0xA9, 0x9A, + 0xAA, 0xBB, 0xCD, 0xEF, 0xDC, 0xDC, 0xCB, 0xA9, 0x98, 0x88, 0x99, 0x9B, + 0xBC, 0xCD, 0xFD, 0xBC, 0xCB, 0xAA, 0x98, 0x77, 0x77, 0x89, 0xAA, 0xBD, + 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x56, 0x67, 0x89, 0xAB, 0xCC, 0xDC, + 0xBC, 0xBB, 0xA8, 0x76, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xCE, 0xDC, 0xDB, + 0xB9, 0x87, 0x64, 0x23, 0x46, 0x78, 0xAB, 0xBC, 0xEC, 0xCC, 0xBA, 0x98, + 0x76, 0x43, 0x34, 0x57, 0x89, 0xBB, 0xCD, 0xDB, 0xCB, 0xBA, 0x97, 0x65, + 0x44, 0x56, 0x78, 0x9B, 0xBD, 0xDD, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x56, + 0x78, 0x9A, 0xBB, 0xDF, 0xEB, 0xDC, 0xBA, 0xA9, 0x87, 0x77, 0x78, 0x8A, + 0xBB, 0xCD, 0xFD, 0xCC, 0xDB, 0xBB, 0x99, 0x98, 0x88, 0x9A, 0xAA, 0xBC, + 0xDF, 0xDC, 0xDD, 0xBC, 0xBB, 0xAA, 0x99, 0xAA, 0xAB, 0xBC, 0xCE, 0xFE, + 0xDF, 0xFD, 0xCC, 0xBB, 0xAA, 0xBB, 0xBB, 0xCC, 0xDC, 0xFF, 0xEC, 0xFF, + 0xDC, 0xDC, 0xCC, 0xBB, 0xBC, 0xCD, 0xED, 0xED, 0xFE, 0xDE, 0xEE, 0xED, + 0xCD, 0xCC, 0xCC, 0xDD, 0xDD, 0xEF, 0xEF, 0xEC, 0xEF, 0xFE, 0xED, 0xED, + 0xDE, 0xED, 0xEE, 0xFE, 0xFF, 0xFF, 0x6C, 0xCC, 0xDD, 0xDD, 0xDD, 0xBC, + 0xCC, 0xED, 0xDD, 0xEF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xDD, 0xDD, 0xDE, 0xEF, 0xFF, 0xCF, 0xFF, + 0xFF, 0xDD, 0xDC, 0xCC, 0xCD, 0xDE, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, + 0xCB, 0xBA, 0xAA, 0xBB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0xA9, + 0x99, 0x9A, 0xAA, 0xBC, 0xEF, 0xFF, 0xFD, 0xDC, 0xBA, 0x98, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDF, 0xFF, 0xDD, 0xBA, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xBC, 0xFF, 0xFD, 0xCA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xED, 0xDB, 0xA8, 0x76, 0x65, 0x55, 0x56, 0x78, 0x89, 0xBC, 0xDF, + 0xDC, 0xB9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xED, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xEF, 0xDC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCD, 0xFD, 0xDA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDF, 0xDC, 0xB9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xDF, 0xFD, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBE, 0xEF, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDF, 0xFE, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x9A, 0xBC, 0xFE, 0xFF, + 0xFE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xBC, 0xDF, 0xFF, 0xFF, 0xFD, + 0xDC, 0xBB, 0xBB, 0xAA, 0xBB, 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, + 0xDC, 0xCC, 0xCD, 0xCE, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xDF, 0xDD, + 0xED, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFE, 0xFF, 0xFD, 0xEC, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFD, 0xDD, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, + 0xED, 0xCC, 0xCD, 0xFF, 0xED, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFD, 0xCC, 0xCB, 0xBB, + 0xBD, 0xFD, 0xEF, 0xFF, 0xDF, 0xEE, 0xFD, 0xCB, 0xBA, 0xA9, 0xAB, 0xBC, + 0xDD, 0xDF, 0xFF, 0xFF, 0xDC, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFF, 0xFE, 0xDC, 0xA9, 0x87, 0x66, 0x78, 0x9B, 0xCC, 0xDD, 0xFE, + 0xED, 0xDC, 0xBA, 0x97, 0x54, 0x45, 0x79, 0xAB, 0xDD, 0xFF, 0xFD, 0xDD, + 0xCB, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xBC, 0xDF, 0xFE, 0xDD, 0xDC, 0xBA, + 0x86, 0x42, 0x24, 0x68, 0xAB, 0xCD, 0xFF, 0xED, 0xDD, 0xCB, 0xA9, 0x75, + 0x44, 0x57, 0x8A, 0xBD, 0xDF, 0xFF, 0xDF, 0xDD, 0xCB, 0x98, 0x76, 0x67, + 0x89, 0xBC, 0xCD, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xDE, 0xFE, 0xDF, 0xFD, 0xED, 0xBB, 0xA9, 0xAA, 0xBC, 0xCD, 0xDF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xDC, 0xCA, 0xBB, 0xBC, 0xCD, 0xDF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xDC, 0xDD, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, + 0xFF, 0xEF, 0xDD, 0xDC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, + 0xDF, 0xDD, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xED, 0xFF, 0xFE, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0xDD, 0xDC, 0xCC, 0xFD, 0xFD, + 0xDD, 0xDF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xDF, 0xFD, 0xCD, 0xDC, 0xFD, 0xDD, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCD, 0xFF, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, + 0xCC, 0xCD, 0xDE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCB, 0xBB, 0xCB, + 0xCC, 0xCF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFD, 0xCB, 0xAA, 0xA9, 0xAA, 0xBC, + 0xCD, 0xFF, 0xFF, 0xFF, 0xDF, 0xBB, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFF, 0xFF, 0xDC, 0xA9, 0x87, 0x66, 0x78, 0x9A, 0xCC, 0xFF, 0xFD, + 0xFF, 0xDC, 0xBA, 0x87, 0x54, 0x45, 0x79, 0xAB, 0xDC, 0xDF, 0xFF, 0xFD, + 0xCA, 0x98, 0x64, 0x22, 0x46, 0x8A, 0xBD, 0xFF, 0xFF, 0xDF, 0xDC, 0xB9, + 0x86, 0x42, 0x24, 0x68, 0x9C, 0xCF, 0xDF, 0xFF, 0xFF, 0xCB, 0xA9, 0x75, + 0x44, 0x56, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xDD, 0xBB, 0x98, 0x76, 0x66, + 0x79, 0xAB, 0xDF, 0xFF, 0xFF, 0xFF, 0xCC, 0xBA, 0x99, 0x88, 0x89, 0xAB, + 0xDD, 0xFF, 0xFF, 0xEF, 0xFF, 0xCC, 0xBA, 0xAA, 0xAA, 0xAB, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xBB, 0xBC, 0xCD, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xDD, 0xDC, 0xDD, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xFF, 0xDD, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, + 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0xDD, 0xDF, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xBC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xA9, 0x9A, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x98, 0x77, 0x89, 0xAF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFB, 0xA8, 0x64, 0x46, 0x8A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xB9, 0x74, 0x12, 0x47, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, + 0x97, 0x42, 0x24, 0x79, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA, 0x86, + 0x44, 0x57, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x87, 0x78, + 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x99, 0xAA, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFB, 0xBB, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCD, 0xCC, 0xCF, 0xBB, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xBC, + 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x99, 0xAA, 0xBC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x98, 0x88, 0xAA, 0xBF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCD, 0xB9, 0x87, 0x66, 0x78, 0x9A, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCA, 0x87, 0x54, 0x45, 0x79, 0xAB, 0xDF, 0xFF, 0xFF, 0xFD, + 0xFB, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, + 0x86, 0x42, 0x24, 0x68, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xA8, 0x75, + 0x44, 0x56, 0x9B, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0x98, 0x76, 0x66, + 0x89, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x98, 0x88, 0x89, 0xBB, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFB, 0xCB, 0xAA, 0xAA, 0xBC, 0xDF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xCC, 0xAB, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0xCD, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0xBC, 0xCF, 0xFF, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xDC, 0xDB, 0xBA, 0xAA, 0xA9, 0xAA, 0xA9, 0xAB, 0xBB, 0xCC, 0xAF, 0xFD, + 0xBB, 0xBA, 0xA9, 0xAA, 0x9A, 0xAB, 0xBB, 0xCD, 0xDC, 0xCB, 0xBB, 0xAA, + 0x99, 0x99, 0x89, 0x9A, 0xAA, 0xBB, 0xCC, 0xCC, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xAB, 0xCB, 0xBB, 0xB9, 0x88, 0x87, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xBB, 0xCA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xCA, 0xAA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, + 0xAB, 0xBB, 0xAA, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xAA, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x77, 0x89, 0x9B, 0xAA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x66, 0x78, 0x99, 0xAB, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9C, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x9A, 0xBB, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0x9A, 0xBA, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x67, 0x77, + 0x88, 0x9B, 0xBC, 0xAA, 0x99, 0x98, 0x77, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xCA, 0xAA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x89, 0x99, 0xAB, 0xDD, + 0xCB, 0xCB, 0xA9, 0x89, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCB, 0xDC, + 0xBA, 0xA9, 0x99, 0x98, 0x99, 0x9A, 0xBA, 0xBC, 0xDC, 0xEC, 0xCC, 0xAB, + 0xBA, 0x9A, 0x9A, 0xAA, 0xAB, 0xBC, 0xEF, 0xEC, 0xEC, 0xCB, 0xBB, 0xBB, + 0xBA, 0xBB, 0xBB, 0xCC, 0xDC, 0xEE, 0xAC, 0xBC, 0xCB, 0xBA, 0xCA, 0xBA, + 0xBC, 0xBB, 0xDD, 0xDD, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xDF, 0xCC, 0xED, 0xBA, 0xBC, 0xCB, 0xBB, 0xBB, 0xCF, 0x6F, 0xFF, + 0xDC, 0xFF, 0xEF, 0xED, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xDF, 0xFF, 0xFD, + 0xFF, 0xDC, 0xDF, 0xFD, 0xFD, 0xFD, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDC, + 0xBB, 0xCB, 0xFC, 0xFF, 0xFF, 0xFC, 0xCF, 0xFC, 0xFF, 0xCB, 0xBB, 0xAB, + 0xCC, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0xCB, 0xBB, 0xA9, 0xA9, 0xAC, 0xBE, + 0xEE, 0xFE, 0xED, 0xCF, 0xFF, 0xDA, 0xA9, 0x88, 0x88, 0xAA, 0xCD, 0xCD, + 0xFF, 0xDC, 0xFF, 0xFB, 0xA9, 0x86, 0x66, 0x78, 0xAB, 0xCC, 0xFD, 0xFC, + 0xCF, 0xDD, 0xDA, 0x86, 0x54, 0x46, 0x79, 0xAD, 0xCF, 0xFF, 0xCC, 0xFF, + 0xCB, 0xA9, 0x64, 0x22, 0x47, 0x8A, 0xCB, 0xFF, 0xFF, 0xCF, 0xFD, 0xB9, + 0x86, 0x42, 0x24, 0x68, 0x9B, 0xCE, 0xFD, 0xCC, 0xFD, 0xBB, 0xA9, 0x76, + 0x44, 0x57, 0x8A, 0xBC, 0xEE, 0xDE, 0xED, 0xFF, 0xDB, 0xA8, 0x76, 0x66, + 0x78, 0xAC, 0xCD, 0xDF, 0xFD, 0xFF, 0xFB, 0xCB, 0xA9, 0x88, 0x89, 0x9B, + 0xCF, 0xCF, 0xFF, 0xDF, 0xFC, 0xDF, 0xCA, 0xA9, 0xAA, 0xAA, 0xCF, 0xDD, + 0xFF, 0xFC, 0xFF, 0xFD, 0xCC, 0xCC, 0xBB, 0xAB, 0xCC, 0xCF, 0xFF, 0xFC, + 0xCF, 0xDD, 0xFC, 0xFF, 0xCB, 0xCD, 0xFF, 0xDF, 0xFF, 0xFF, 0xFC, 0xFF, + 0xDF, 0xDF, 0xCF, 0xFC, 0xCF, 0xFF, 0xFF, 0xDF, 0xFD, 0xCF, 0xFF, 0xCF, + 0xFF, 0xFC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xFF, 0xFF, 0xFF, 0xCF, + 0xFD, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x6D, 0xCC, 0xCD, 0xBD, 0xDC, 0xFD, + 0xCD, 0xCF, 0xFF, 0xFF, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCB, 0xCC, + 0xCC, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xBA, 0xA9, 0xAA, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xA9, 0x88, 0x88, 0x9A, 0xBF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFB, 0xB9, 0x86, 0x66, 0x78, 0x9A, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xB9, 0x87, 0x54, 0x45, 0x78, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFB, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xBC, 0xFF, 0xFF, 0xFF, 0xFC, 0xCA, + 0x86, 0x42, 0x24, 0x68, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xA8, 0x75, + 0x44, 0x56, 0x8A, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x98, 0x76, 0x66, + 0x89, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x98, 0x88, 0x89, 0xAC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xCB, 0xAA, 0xA9, 0xBB, 0xCF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xBB, 0xCF, 0xEF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0x9F, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0x9C, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x65, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x94, 0x12, 0x58, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF8, 0x52, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, + 0x54, 0x78, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x87, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF9, 0x74, 0x57, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x85, 0x12, 0x59, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0x52, 0x14, 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, + 0x54, 0x67, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x89, + 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xF6, 0xF6, 0x6F, 0x68, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, + 0x66, 0xF6, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF6, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0xF6, 0x6F, + 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0x6F, 0x66, 0x66, 0xFF, 0x6F, 0xF6, + 0xFF, 0xFF, 0x6F, 0xCF, 0xFF, 0x6F, 0xFF, 0xF6, 0x6F, 0x6F, 0xFF, 0x6F, + 0xFF, 0xF6, 0x56, 0xF6, 0xF6, 0x56, 0xFF, 0xFF, 0x66, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x65, 0x56, 0x6F, 0xFF, 0xF6, 0xFF, 0x6F, 0xFF, 0xFF, + 0xF6, 0x66, 0xF6, 0xFF, 0x66, 0x6F, 0xFF, 0x6F, 0xFF, 0x6F, 0xF6, 0xFF, + 0x66, 0x6F, 0x56, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x6F, + 0x46, 0xF5, 0x6F, 0x6F, 0xFF, 0xF5, 0x6B, 0xAF, 0xFF, 0x5F, 0xFF, 0xFF, + 0x6F, 0x6F, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xF6, 0x66, 0xF5, 0xFF, + 0x5F, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xF5, 0x55, 0xF6, 0xF6, 0xFF, + 0xFF, 0x6F, 0xFF, 0xFF, 0x6F, 0xF6, 0xFF, 0xF6, 0xF6, 0xFF, 0xFF, 0xFF, + 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xF6, 0x6F, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xF6, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0x6F, + 0xF6, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0x6F, 0x6F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0x9F, 0x4F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xF9, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF8, 0x67, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF8, 0x97, 0x54, 0x47, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x8F, 0x74, 0x12, 0x57, 0x8F, 0xF9, 0xFF, 0xFF, 0x9F, 0xFF, 0x9F, + 0x98, 0x52, 0x24, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, + 0x54, 0x58, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xF8, + 0x9F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0x89, 0xFF, + 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xF9, 0x99, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xBA, 0xFF, 0xFF, 0xBF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0x77, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0x54, 0x45, 0x9A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x84, 0x22, 0x47, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA8, 0x42, 0x14, 0x7A, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x96, + 0x44, 0x59, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x97, 0x78, + 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFA, 0xBF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBF, 0xFB, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x76, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x6F, 0x67, 0x6F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xF7, 0x55, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF7, 0x55, 0x44, 0x46, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0xF5, 0x54, 0x44, 0x57, 0x66, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, + 0x75, 0x44, 0x34, 0x46, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x55, + 0x45, 0x45, 0x56, 0xFF, 0xFF, 0xFF, 0xFD, 0xCF, 0x6F, 0x7F, 0x75, 0x57, + 0x56, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x7F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7F, 0xF7, 0x7F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x7F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0x44, 0x45, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x73, 0x22, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0x42, 0x24, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x86, + 0x43, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x77, + 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF9, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x75, 0x67, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF9, 0x76, 0x43, 0x46, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF6, 0x63, 0x23, 0x58, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAF, 0x43, 0x23, 0x57, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x85, + 0x54, 0x45, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF7, 0x55, + 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xBF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xBF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xAF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x88, 0x9F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x87, 0x66, 0x78, 0xAF, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xBF, 0xA7, 0x54, 0x45, 0x6A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF7, 0x64, 0x22, 0x46, 0x89, 0xDF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, + 0x76, 0x42, 0x24, 0x68, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x75, + 0x44, 0x57, 0xA9, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0x97, 0x76, 0x67, + 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xBA, 0x98, 0x8A, 0xBB, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFA, 0xAF, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x9F, 0xFF, 0xCF, 0x99, 0xFF, 0x3F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x78, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x84, 0x22, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0x42, 0x14, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, + 0x44, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x88, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xEE, 0xEF, 0xFF, 0xFF, 0x3F, 0xFF, + 0xFE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, + 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF3, 0x12, 0x46, 0xFF, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0x52, 0x24, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0x44, 0x6E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFE, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0x83, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF4, 0x12, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0x42, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, + 0x44, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x8F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + }, + { + { + 0xBE, 0xDD, 0xEC, 0xDD, 0xDD, 0xDC, 0xDE, 0xEE, 0xFF, 0xFF, 0xCD, 0xFE, + 0xFD, 0xDD, 0xDC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFF, 0xFF, 0xDE, 0xFD, 0xCC, + 0xCC, 0xBB, 0xBB, 0xCC, 0xCD, 0xFF, 0xFF, 0xFD, 0xED, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xFF, 0xFF, 0xDF, 0xEC, 0xBB, 0xA9, 0x99, 0x99, + 0x99, 0xAB, 0xCD, 0xFF, 0xFD, 0xEC, 0xBB, 0xA9, 0x88, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xFE, 0xED, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xFC, 0xDC, 0xA9, 0x87, 0x76, 0x65, 0x66, 0x67, 0x89, 0xBC, 0xDF, + 0xDC, 0xCA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDD, 0xDB, + 0xA9, 0x87, 0x65, 0x54, 0x55, 0x56, 0x79, 0xAC, 0xDD, 0xDC, 0xBA, 0x97, + 0x65, 0x54, 0x44, 0x55, 0x67, 0x8A, 0xBD, 0xDE, 0xCB, 0xA9, 0x76, 0x65, + 0x54, 0x55, 0x66, 0x79, 0xAB, 0xCD, 0xED, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x56, 0x78, 0x9A, 0xBD, 0xDE, 0xDC, 0xB9, 0x87, 0x66, 0x65, 0x66, 0x77, + 0x89, 0xAC, 0xDC, 0xEF, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDF, 0xFE, 0xCB, 0xA9, 0x88, 0x77, 0x78, 0x89, 0xAB, 0xCC, 0xED, + 0xFF, 0xED, 0xCB, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xDF, 0xDF, 0xFF, + 0xED, 0xCC, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFD, 0xFF, 0xFF, 0xFE, + 0xDC, 0xCB, 0xBB, 0xBC, 0xCC, 0xEE, 0xEF, 0xEF, 0xFF, 0xFF, 0xFE, 0xEE, + 0xCC, 0xDD, 0xDD, 0xDF, 0xEF, 0xFF, 0xDF, 0xFF, 0xFE, 0xFF, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0xDE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAD, 0xCB, 0xBB, 0xBC, 0xCB, 0xFC, 0xDB, 0xCD, 0xFF, 0xFF, 0xCF, 0xFF, + 0xBD, 0xCC, 0xDC, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xCC, 0xDC, + 0xBB, 0xAB, 0xBA, 0xBC, 0xCD, 0xDD, 0xDD, 0xFB, 0xDD, 0xFB, 0xAB, 0xAA, + 0x9A, 0xAA, 0xAA, 0xBC, 0xFF, 0xFF, 0xCF, 0xFC, 0xCB, 0xBA, 0x99, 0x99, + 0x99, 0xAB, 0xBC, 0xCF, 0xFB, 0xDB, 0xBA, 0xA9, 0x98, 0x87, 0x78, 0x88, + 0xAA, 0xBC, 0xDF, 0xCF, 0xFB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, 0xAA, + 0xBF, 0xCF, 0xCC, 0xA9, 0x98, 0x76, 0x65, 0x56, 0x67, 0x89, 0xAB, 0xFC, + 0xCB, 0xDA, 0xA8, 0x76, 0x65, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xFB, + 0xA9, 0x87, 0x65, 0x44, 0x45, 0x56, 0x79, 0x9B, 0xCC, 0xBF, 0xBA, 0x97, + 0x75, 0x54, 0x44, 0x56, 0x68, 0x9A, 0xBE, 0xFB, 0xDB, 0xA9, 0x86, 0x65, + 0x44, 0x45, 0x67, 0x89, 0xAA, 0xCC, 0xDF, 0xBB, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xAC, 0xDC, 0xFC, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x8A, 0xAB, 0xBB, 0xFC, 0xBC, 0xB9, 0x87, 0x76, 0x77, 0x77, 0x89, 0xAB, + 0xDC, 0xBC, 0xFC, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xCB, 0xCB, + 0xFF, 0xFC, 0xCA, 0xAA, 0x99, 0x99, 0xA9, 0x9B, 0xBC, 0xCD, 0xDF, 0xFF, + 0xCF, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCF, 0xDD, 0xFF, 0xFF, 0xFD, + 0xCC, 0xCB, 0xBB, 0xCC, 0xBB, 0xDB, 0xFF, 0xCF, 0xFF, 0xFF, 0xDD, 0xFD, + 0xBF, 0xDC, 0xCB, 0xBF, 0xDF, 0xFC, 0xFF, 0xFF, 0xFE, 0xED, 0xFF, 0xCB, + 0xBC, 0xDC, 0xBC, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDF, 0xDD, 0xDD, 0xDC, 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xDF, 0xFF, + 0xFE, 0xDD, 0xDC, 0xCC, 0xCD, 0xDE, 0xEF, 0xFF, 0xFF, 0xEF, 0xFD, 0xDC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDF, 0xFF, 0xFD, 0xFE, 0xDC, 0xBB, 0xAA, + 0x9A, 0xAA, 0xAB, 0xCD, 0xEF, 0xFF, 0xDF, 0xDC, 0xBA, 0xA9, 0x98, 0x88, + 0x89, 0xAA, 0xBD, 0xDF, 0xFD, 0xEC, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xEF, 0xDD, 0xCB, 0x99, 0x87, 0x76, 0x66, 0x67, 0x88, 0xAB, + 0xCD, 0xFD, 0xDB, 0xA9, 0x87, 0x66, 0x65, 0x56, 0x67, 0x89, 0xAB, 0xED, + 0xDC, 0xBA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x77, 0x8A, 0xBD, 0xDD, 0xCB, + 0xA8, 0x76, 0x65, 0x55, 0x55, 0x66, 0x78, 0xAB, 0xCD, 0xDC, 0xB9, 0x87, + 0x65, 0x55, 0x44, 0x55, 0x67, 0x89, 0xBD, 0xDD, 0xCB, 0xA8, 0x76, 0x65, + 0x55, 0x55, 0x66, 0x78, 0x9B, 0xCD, 0xDC, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xDB, 0xA9, 0x87, 0x66, 0x65, 0x66, 0x67, + 0x89, 0xAB, 0xDD, 0xED, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0x9B, + 0xCC, 0xDE, 0xEC, 0xCB, 0xA9, 0x88, 0x77, 0x78, 0x89, 0x9A, 0xBC, 0xED, + 0xFF, 0xDD, 0xBA, 0xA9, 0x98, 0x88, 0x89, 0xAA, 0xBC, 0xDD, 0xDF, 0xFF, + 0xFD, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xED, 0xFF, 0xFE, 0xFD, + 0xCB, 0xBB, 0xBB, 0xBC, 0xBC, 0xDD, 0xEF, 0xEF, 0xFF, 0xFF, 0xFE, 0xDC, + 0xCC, 0xCC, 0xCC, 0xDE, 0xDF, 0xFE, 0xDF, 0xFF, 0xFF, 0xFE, 0xDD, 0xDC, + 0xCD, 0xDD, 0xDE, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xEE, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xED, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x4D, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xE3, 0xEE, 0xE4, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x3E, 0x4E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0x44, 0x44, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0x44, 0x4D, 0xDD, 0xD4, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD4, 0xD3, + 0x3D, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xE4, 0xE4, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x4E, 0xEE, 0x44, 0xEE, + 0xE4, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE4, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, 0xED, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x4E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xED, 0xED, 0xED, 0xEE, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xAD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0xFD, 0xFF, 0xFF, 0xFF, 0xDD, 0xFF, + 0xDF, 0xDD, 0xCC, 0xCC, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xEF, 0xDD, 0xDC, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDF, 0xFF, 0xFE, 0xFD, 0xEC, 0xBB, 0xAA, + 0x9A, 0xAA, 0xAB, 0xCD, 0xDF, 0xFF, 0xCD, 0xCD, 0xBA, 0xA9, 0x98, 0x88, + 0x99, 0x9A, 0xCD, 0xDF, 0xFD, 0xDC, 0xBA, 0xA9, 0x88, 0x77, 0x78, 0x89, + 0x9A, 0xBD, 0xFF, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0x9A, + 0xDF, 0xFC, 0xDB, 0xB9, 0x87, 0x66, 0x65, 0x66, 0x67, 0x89, 0xAC, 0xDD, + 0xDD, 0xBA, 0x98, 0x76, 0x55, 0x55, 0x56, 0x78, 0x8A, 0xCD, 0xED, 0xCB, + 0xA8, 0x76, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9B, 0xDE, 0xDC, 0xBA, 0x87, + 0x65, 0x55, 0x45, 0x55, 0x67, 0x8A, 0xBD, 0xCD, 0xCB, 0xA8, 0x76, 0x55, + 0x54, 0x55, 0x56, 0x78, 0xAB, 0xCD, 0xED, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x56, 0x78, 0x9A, 0xBC, 0xCD, 0xFB, 0xA9, 0x87, 0x66, 0x65, 0x66, 0x67, + 0x89, 0xAB, 0xCD, 0xFF, 0xDB, 0xA8, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xCC, 0xDF, 0xFD, 0xCA, 0x98, 0x88, 0x77, 0x77, 0x89, 0x9A, 0xBC, 0xED, + 0xFF, 0xFD, 0xCB, 0xA9, 0x98, 0x88, 0x99, 0xAA, 0xBC, 0xDD, 0xDF, 0xFF, + 0xDC, 0xCB, 0xAA, 0xAA, 0x9A, 0xAB, 0xBC, 0xCE, 0xED, 0xFF, 0xFF, 0xFD, + 0xCC, 0xBB, 0xBC, 0xBB, 0xCC, 0xDD, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDC, + 0xCC, 0xCD, 0xDC, 0xDF, 0xFF, 0xEF, 0xDF, 0xFF, 0xFE, 0xFC, 0xEC, 0xCD, + 0xCC, 0xDD, 0xCD, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBB, 0xBB, 0xBA, 0xAB, 0xBB, 0xCC, 0xCC, 0xEF, 0xBC, 0xDD, + 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xEE, 0xFE, 0xCC, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xEC, 0xCC, 0xBA, 0xAA, 0x99, + 0x98, 0x99, 0x9A, 0xAB, 0xBC, 0xDD, 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xDB, 0xBB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xCC, 0xBB, 0xAA, 0x98, 0x77, 0x76, 0x66, 0x77, 0x78, 0x9A, + 0xAC, 0xCB, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBB, 0xBA, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xAB, 0xBB, 0x99, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x67, 0x89, 0xAA, 0xAB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x77, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x67, + 0x88, 0x9A, 0xBB, 0xCC, 0xAA, 0x98, 0x77, 0x76, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xBC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBB, + 0xCC, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBD, 0xDD, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCF, 0xFE, 0xDD, 0xCC, 0xBB, + 0xBA, 0xBB, 0xBB, 0xBC, 0xCD, 0xDC, 0xCE, 0xDD, 0xDC, 0xCB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDD, 0xBC, 0xDC, + 0xCC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAB, 0xCB, 0xCD, 0xEE, 0xBD, 0xCC, 0xBB, + 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xDB, 0xCC, 0xAA, 0xA9, 0x99, + 0x88, 0x89, 0x99, 0x9A, 0xBC, 0xDC, 0xBC, 0xBA, 0x99, 0x98, 0x88, 0x77, + 0x88, 0x89, 0x9A, 0xBC, 0xCB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0xAB, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xBA, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xBA, + 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x89, 0xAA, 0xAA, 0xA9, + 0x88, 0x76, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x67, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAB, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, + 0x88, 0x9A, 0xAA, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xAB, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0xAB, 0xBB, + 0xCC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBC, 0xBC, 0xCB, + 0xBA, 0x99, 0x99, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xDD, 0xDC, 0xBA, + 0xA9, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCD, 0xBE, 0xEE, 0xCC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDB, 0xCD, 0xEC, 0xBB, 0xBB, 0xBA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xBC, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xBB, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xCA, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x77, + 0x88, 0x88, 0x9A, 0xAB, 0xBA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x77, 0x89, + 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, + 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0x99, 0xA9, + 0x88, 0x76, 0x66, 0x66, 0x66, 0x66, 0x77, 0x89, 0xA9, 0x9A, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x67, 0x78, 0x9A, 0x99, 0xA9, 0x87, 0x76, 0x66, + 0x65, 0x66, 0x66, 0x77, 0x89, 0xA9, 0xAA, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0x9A, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x99, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0x9A, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xAA, + 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x78, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xCB, + 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBA, 0xCD, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBD, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCB, 0xCC, 0xCB, 0xBA, 0xAA, 0x99, 0x99, + 0x99, 0xAA, 0xAA, 0xBB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xCC, 0xCB, + 0xBC, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xAC, 0xCD, 0xDE, 0xBD, 0xCB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xCA, 0xBC, 0xBA, 0x99, 0x98, + 0x88, 0x89, 0x89, 0x9A, 0xBB, 0xCC, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xCC, 0xAA, 0xA9, 0x88, 0x87, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xBA, 0xB9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, 0x78, 0x99, 0xAA, + 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xAA, 0xA9, + 0x87, 0x76, 0x66, 0x65, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, + 0x66, 0x65, 0x55, 0x66, 0x67, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, + 0x78, 0x9A, 0xBA, 0xAB, 0xA9, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAA, 0xBB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0xAB, 0xBA, + 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBD, 0xBB, + 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBB, 0xDD, 0xCB, 0xAB, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xBC, 0xBD, 0xDC, 0xBB, 0xBB, 0xAA, + 0xA9, 0xAA, 0xAA, 0xBB, 0xDC, 0xDC, 0xBE, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9C, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xCB, 0xEC, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xEE, 0xBD, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCE, 0xDB, 0xCB, 0xBA, 0xA9, 0x99, + 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xDC, 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, + 0x88, 0x99, 0xAA, 0xBC, 0xCB, 0xBB, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xBC, 0xAB, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xAA, 0x99, 0x87, 0x76, 0x66, 0x55, 0x66, 0x67, 0x89, 0x9A, 0xAA, 0xA9, + 0x88, 0x76, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAA, 0xAA, 0x98, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x67, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x66, 0x78, 0x99, 0xAA, 0xAB, 0x99, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x77, 0x89, 0x9A, 0xAB, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xBB, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xBB, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBB, + 0xCC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBC, 0xDC, + 0xBA, 0xA9, 0x99, 0x88, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xDC, 0xBB, + 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCD, 0xBD, 0xED, 0xCC, 0xBB, 0xBB, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0xBD, 0xDC, 0xCB, 0xBB, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBB, 0xBC, 0x90, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xED, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xEF, 0xBF, 0xFF, + 0xFD, 0xDD, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xED, 0xDC, + 0xCC, 0xCC, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFE, 0xDC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xCC, 0xEF, 0xFF, 0xFF, 0xDE, 0xDC, 0xBB, 0xAA, 0x99, 0x99, + 0xAA, 0xBC, 0xDF, 0xFF, 0xED, 0xEC, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x9A, + 0xBD, 0xEF, 0xFF, 0xDD, 0xCB, 0xA9, 0x88, 0x76, 0x67, 0x78, 0x9A, 0xCD, + 0xEF, 0xFD, 0xDC, 0xBA, 0x98, 0x76, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xEE, + 0xDE, 0xCB, 0x98, 0x76, 0x54, 0x44, 0x56, 0x79, 0xAC, 0xDE, 0xED, 0xDC, + 0xB9, 0x87, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xED, 0xDE, 0xCB, 0x98, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xDE, 0xDE, 0xFC, 0xB9, 0x87, 0x55, + 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xED, 0xEE, 0xDB, 0xA8, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xCE, 0xEF, 0xFD, 0xCA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9B, 0xBD, 0xED, 0xFF, 0xFD, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDF, 0xFE, 0xDC, 0xBA, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xED, + 0xFF, 0xFF, 0xEC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xFE, 0xEF, 0xFF, + 0xFF, 0xEC, 0xDC, 0xBB, 0xBB, 0xCC, 0xCC, 0xDE, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFE, 0xED, 0xDC, 0xCD, 0xDD, 0xDE, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEE, 0xFE, 0xDE, 0xEE, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xEE, 0xDD, 0xDE, + 0xFE, 0xDD, 0xDE, 0xEE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xDD, 0xDC, 0xCC, 0xBC, 0xCD, 0xDD, 0xDF, 0xFF, 0xFF, 0xCD, 0xDF, + 0xDC, 0xCB, 0xCB, 0xCB, 0xCC, 0xCD, 0xFF, 0xFF, 0xFF, 0xDE, 0xDC, 0xCC, + 0xBB, 0xBA, 0xAB, 0xBB, 0xCD, 0xFF, 0xFF, 0xFC, 0xDD, 0xBB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCD, 0xDF, 0xFF, 0xDC, 0xBB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAB, 0xBC, 0xDF, 0xFC, 0xCC, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAB, 0xBD, 0xFF, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xDD, 0xFC, 0xCA, 0x99, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xFF, + 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBE, 0xEC, 0xBA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xDD, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x78, 0xAB, 0xCC, 0xCC, 0xBA, 0x97, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDF, 0xDB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCD, 0xDD, 0xDB, 0xA8, 0x87, 0x77, 0x67, 0x77, 0x89, 0xAA, + 0xBD, 0xFF, 0xDD, 0xCA, 0xA9, 0x88, 0x77, 0x88, 0x89, 0x9A, 0xBC, 0xDC, + 0xFF, 0xFD, 0xCB, 0xAA, 0x99, 0x89, 0x99, 0xAA, 0xBC, 0xCF, 0xCF, 0xFF, + 0xFD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDC, 0xFF, 0xFF, 0xFF, 0xFD, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, + 0xCC, 0xCC, 0xDD, 0xCC, 0xFE, 0xDF, 0xDF, 0xFF, 0xFF, 0xDD, 0xCC, 0xCD, + 0xCC, 0xCF, 0xDD, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xDD, 0xED, 0xED, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, + 0xFF, 0xFE, 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xFE, 0xFE, 0xED, 0xCC, 0xBB, + 0xBB, 0xBB, 0xCD, 0xEF, 0xFF, 0xFF, 0xDE, 0xDD, 0xBB, 0xAA, 0x99, 0x99, + 0xAB, 0xCD, 0xED, 0xFF, 0xFE, 0xFD, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x9A, + 0xBD, 0xEF, 0xFF, 0xDF, 0xDC, 0xB9, 0x87, 0x76, 0x67, 0x78, 0x9A, 0xCE, + 0xFF, 0xFE, 0xDD, 0xBA, 0x97, 0x76, 0x55, 0x56, 0x78, 0x9B, 0xCE, 0xFF, + 0xED, 0xDB, 0xA8, 0x76, 0x54, 0x44, 0x56, 0x79, 0xAC, 0xEF, 0xEE, 0xEC, + 0xB9, 0x86, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xFE, 0xEE, 0xCB, 0x98, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAC, 0xEF, 0xFD, 0xEC, 0xB9, 0x87, 0x55, + 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xFD, 0xEF, 0xDB, 0xA8, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xDF, 0xEE, 0xFD, 0xCB, 0x98, 0x76, 0x66, 0x67, 0x78, + 0xAB, 0xCD, 0xEE, 0xFF, 0xFD, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDF, 0xEF, 0xFF, 0xED, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xEE, + 0xFF, 0xFF, 0xDC, 0xCB, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEE, 0xEF, 0xFF, + 0xFF, 0xED, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEF, 0xFE, 0xFF, 0xFF, 0xFF, + 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEE, 0xFE, 0xEF, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xEE, 0xED, 0xEE, + 0xED, 0xFE, 0xFE, 0xEE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBB, 0xBB, 0xBB, 0xAB, 0xBB, 0xCC, 0xCD, 0xDE, 0xBC, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDF, 0xFD, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEE, 0xEB, 0xCB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0xAA, 0xAB, 0xCD, 0xDD, 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xCD, 0xCB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xCC, 0xBB, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x65, 0x66, 0x77, 0x89, 0xAB, 0xBB, + 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, + 0x98, 0x76, 0x65, 0x54, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x77, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x89, 0xAB, 0xBB, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xBC, 0xCB, 0xBA, 0x99, 0x88, 0x87, 0x78, 0x88, 0x9A, 0xAB, 0xCB, + 0xCD, 0xCB, 0xBA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCD, 0xDD, + 0xCB, 0xBA, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xDE, 0xDD, 0xCB, + 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCE, 0xEE, 0xDD, 0xCC, 0xCB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEC, 0xBD, 0xDD, 0xCC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xAA, 0x99, 0xA9, 0xAA, 0xBB, 0xBD, 0xDC, 0xAB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xCA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x88, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x88, 0x9A, 0x99, 0xA9, 0x88, 0x76, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0x9A, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x89, + 0xAA, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xAA, + 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xCB, + 0xAA, 0xA9, 0x98, 0x88, 0x89, 0x99, 0x9A, 0xAB, 0xBB, 0xCC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBD, 0xDD, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDB, 0xBD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBB, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xAB, 0xCC, 0xDC, 0xAB, 0xAA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCA, 0xBA, 0x99, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x88, 0x88, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xAB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x66, 0x66, 0x66, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x67, 0x88, 0x9A, 0x99, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x9A, 0x98, 0x77, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x67, 0x77, 0x78, 0x89, + 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xAA, + 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xAB, 0xBB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBB, 0xBD, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCB, 0xCD, 0xCB, 0xBB, 0xAA, 0xAA, 0x99, + 0xAA, 0xAA, 0xAB, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xA9, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xAB, 0xCC, + 0xBB, 0xBB, 0xAA, 0xAA, 0xBA, 0xBC, 0xCD, 0xED, 0xEC, 0xBC, 0xBB, 0xBA, + 0xA9, 0xA9, 0xA9, 0xAA, 0xAB, 0xBC, 0xDE, 0xDB, 0xBB, 0xBA, 0x99, 0x99, + 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xCC, 0xBA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xCC, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x9A, + 0xBB, 0xBA, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x89, 0x9A, 0xBA, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xAA, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x99, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x67, 0x89, 0xAA, 0xBA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x89, 0xAA, 0xAB, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xAA, 0xBB, 0xA9, 0x98, 0x87, 0x77, 0x67, 0x77, 0x88, 0x9A, + 0xAB, 0xAC, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x78, 0x89, 0x99, 0xAA, 0xBA, + 0xCC, 0xCB, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xAC, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBB, 0xCB, 0xCE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xBE, 0xED, 0xDC, 0xCC, 0xBB, + 0xBB, 0xBB, 0xAA, 0xBC, 0xCC, 0xDB, 0xAD, 0xDD, 0xBB, 0xBB, 0xBB, 0xBA, + 0xAA, 0xBB, 0xBB, 0xBC, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCD, 0xAB, 0xCC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDE, 0xFD, 0xBC, 0xBB, 0xAA, + 0xAA, 0x9A, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xDB, 0xBB, 0xAA, 0x99, 0x99, + 0x89, 0x99, 0x9A, 0xAB, 0xCD, 0xDC, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xBB, 0xCC, 0xCA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xCA, 0xAA, 0x98, 0x77, 0x66, 0x65, 0x66, 0x67, 0x89, 0xAA, 0xCB, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xAA, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, + 0x66, 0x55, 0x45, 0x56, 0x67, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x89, 0xAB, 0xBB, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xBC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xBC, 0xCB, 0xBA, 0x99, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xCD, 0xCB, 0xAA, 0x99, 0x98, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xBD, 0xED, + 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xAA, 0xBC, 0xCB, 0xDE, 0xED, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCD, 0xBD, 0xFE, 0xED, 0xCC, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDB, 0xAD, 0xDD, 0xCC, 0xCC, 0xBB, 0xBB, + 0xAB, 0xBB, 0xBB, 0xBC, 0x90, 0x00, 0x00, 0x00, + }, + { + 0xAF, 0xDF, 0xDF, 0xFD, 0xDD, 0xCD, 0xDF, 0xFD, 0xFF, 0xDD, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xDF, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDF, 0xCC, 0xCD, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFF, 0xFD, 0xBA, 0x88, 0xAC, 0xDF, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCA, 0x74, 0x46, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFC, 0x85, 0x22, 0x47, 0xDF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xD8, 0x42, 0x13, 0x7B, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xA6, + 0x43, 0x58, 0xCF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xA8, 0x78, + 0xAB, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDB, 0xBC, 0xDF, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xDD, 0xFD, 0xDF, 0xDF, + 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDF, + 0xDD, 0xFD, 0xFF, 0xDD, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFD, 0xDD, 0xCD, 0xDE, 0xDD, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFF, 0xED, 0xDC, 0xCC, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xDD, + 0xBB, 0xBA, 0xBB, 0xBD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBA, 0xAA, + 0x99, 0xAA, 0xBB, 0xCE, 0xFF, 0xFF, 0xFF, 0xEC, 0xBA, 0x99, 0x88, 0x89, + 0x9A, 0xAB, 0xCE, 0xFF, 0xFE, 0xFC, 0xCA, 0x98, 0x87, 0x77, 0x78, 0x99, + 0xAB, 0xDD, 0xFF, 0xDD, 0xBB, 0x98, 0x77, 0x66, 0x66, 0x77, 0x99, 0xBC, + 0xDF, 0xED, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xFF, + 0xFC, 0xB9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0xAB, 0xCF, 0xFC, 0xDB, + 0xA8, 0x76, 0x55, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xED, 0xDC, 0xCA, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9B, 0xCE, 0xFE, 0xDB, 0xA9, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xDD, 0xDC, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xCF, 0xED, 0xFD, 0xBA, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBE, 0xEF, 0xDF, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xCF, 0xFE, 0xFF, 0xDC, 0xA9, 0x98, 0x88, 0x88, 0x9A, 0xBC, 0xDF, 0xEF, + 0xFF, 0xFE, 0xCB, 0xBA, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xFF, 0xFF, 0xFF, + 0xFD, 0xCD, 0xCB, 0xBB, 0xBB, 0xBC, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xED, 0xDC, 0xDC, 0xDD, 0xCF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xDF, 0xEF, + 0xDD, 0xEE, 0xFF, 0xDE, 0xFF, 0xFF, 0xBF, 0xFF, 0xFD, 0xFF, 0xFE, 0xED, + 0xFE, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xEE, 0xED, 0xDD, 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFF, 0xDE, 0xFF, + 0xED, 0xCC, 0xCC, 0xBC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0xEF, 0xED, 0xCC, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xFF, 0xFE, 0xFD, 0xCB, 0xAA, 0xA9, + 0x99, 0x99, 0xAB, 0xBC, 0xEF, 0xFF, 0xDD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xEF, 0xFD, 0xDB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0x9B, 0xCD, 0xEE, 0xDD, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCE, 0xEC, 0xCB, 0x98, 0x77, 0x66, 0x55, 0x56, 0x67, 0x89, 0xBC, 0xDE, + 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x77, 0x9A, 0xBD, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xDC, 0xB9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCD, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xED, 0xED, 0xCB, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDE, 0xEC, 0xBA, 0x99, 0x88, 0x87, 0x88, 0x89, 0xAB, 0xCD, 0xEF, + 0xFF, 0xDD, 0xBB, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xCC, 0xEF, 0xFF, 0xFF, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xED, + 0xCC, 0xBB, 0xBB, 0xBC, 0xDC, 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xEE, 0xED, + 0xDC, 0xDD, 0xED, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFE, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xCD, 0xDC, 0xCC, 0xCD, 0xDE, 0xDD, 0xFF, 0xFF, 0xFF, 0xDD, 0xFE, + 0xDC, 0xCC, 0xCB, 0xCC, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xDF, 0xDD, 0xCB, + 0xBB, 0xBA, 0xBB, 0xBC, 0xCD, 0xEF, 0xEF, 0xFD, 0xFC, 0xCB, 0xA9, 0xA9, + 0x99, 0x9A, 0xAB, 0xCD, 0xDF, 0xFE, 0xCE, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xFC, 0xCB, 0xAA, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCE, 0xFE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAC, + 0xDE, 0xEC, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x56, 0x77, 0x9A, 0xBC, 0xDD, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xEC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xB9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xDC, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCD, 0xDD, 0xDC, 0xB9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x99, 0xBB, 0xDF, 0xDE, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xED, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x89, 0xAA, 0xBD, 0xDD, + 0xFF, 0xED, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xEF, 0xFF, + 0xFD, 0xCC, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xEE, 0xFF, 0xFF, 0xED, + 0xDC, 0xCB, 0xBC, 0xCB, 0xCD, 0xCD, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDD, + 0xEC, 0xDC, 0xCC, 0xEF, 0xEF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFD, 0xED, 0xDD, + 0xDC, 0xDD, 0xDD, 0xDF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xEE, 0xED, 0xEF, 0xED, 0xEE, 0xFE, 0xEF, 0xFE, 0xFF, 0xAE, 0xFF, + 0xFE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xED, 0xCC, 0xCB, + 0xBB, 0xCC, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCB, 0xAA, 0xAA, 0xAA, + 0xBB, 0xCD, 0xEF, 0xFF, 0xFE, 0xFE, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xFF, 0xFF, 0xEE, 0xDC, 0xA9, 0x88, 0x77, 0x77, 0x89, 0xAB, 0xDE, + 0xFF, 0xFF, 0xFD, 0xBA, 0x97, 0x76, 0x55, 0x66, 0x89, 0xAC, 0xDF, 0xFE, + 0xEE, 0xDB, 0xA8, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBD, 0xFF, 0xEE, 0xED, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xDF, 0xFE, 0xFF, 0xDB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xEF, 0xEE, 0xFD, 0xCA, 0x87, 0x65, + 0x44, 0x45, 0x68, 0x9B, 0xCE, 0xFF, 0xFF, 0xEC, 0xB9, 0x86, 0x65, 0x55, + 0x67, 0x8A, 0xBD, 0xEF, 0xFF, 0xFF, 0xDC, 0xA9, 0x87, 0x66, 0x77, 0x89, + 0xAB, 0xCF, 0xFF, 0xFF, 0xFE, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xEF, 0xFF, 0xFF, 0xFE, 0xCB, 0xAA, 0x99, 0x9A, 0xAA, 0xBC, 0xDE, 0xFF, + 0xFF, 0xFF, 0xFE, 0xDC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xED, 0xDD, 0xCD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xEF, 0xEF, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAE, 0xDD, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xFE, 0xEE, 0xFF, 0xBD, 0xFF, + 0xEE, 0xED, 0xED, 0xEE, 0xEF, 0xFE, 0xFF, 0xFF, 0xFE, 0xEE, 0xED, 0xDD, + 0xCC, 0xCC, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xEE, 0xEE, 0xDC, 0xCB, 0xBB, + 0xBB, 0xBC, 0xDD, 0xEE, 0xFF, 0xFE, 0xDE, 0xDC, 0xBB, 0xAA, 0x99, 0xAA, + 0xBB, 0xCD, 0xEF, 0xFF, 0xED, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xEF, 0xFE, 0xDD, 0xDB, 0xA9, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCE, + 0xFF, 0xED, 0xDC, 0xBA, 0x97, 0x76, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xFE, + 0xDD, 0xCB, 0xA8, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBC, 0xEF, 0xDD, 0xDC, + 0xB9, 0x87, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xCD, 0xEE, 0xDE, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xDF, 0xDD, 0xED, 0xBA, 0x97, 0x65, + 0x44, 0x45, 0x78, 0x9A, 0xCD, 0xEE, 0xDE, 0xDC, 0xB9, 0x87, 0x65, 0x55, + 0x67, 0x89, 0xBC, 0xDE, 0xDD, 0xEE, 0xDB, 0xA9, 0x87, 0x66, 0x77, 0x89, + 0xAB, 0xCD, 0xFD, 0xDE, 0xED, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0x9A, 0xBC, + 0xDF, 0xDD, 0xFE, 0xED, 0xCB, 0xAA, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFE, + 0xDF, 0xFF, 0xED, 0xCC, 0xBB, 0xAB, 0xBB, 0xBC, 0xDE, 0xEF, 0xDD, 0xFF, + 0xFF, 0xEE, 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFE, 0xDF, 0xFF, 0xFF, + 0xEE, 0xED, 0xDD, 0xDD, 0xDD, 0xDE, 0xFE, 0xED, 0xFF, 0xFF, 0xFF, 0xEF, + 0xEE, 0xEE, 0xFE, 0xFF, 0xFF, 0xFE, 0x9D, 0xEE, 0xDD, 0xDE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xFE, 0xED, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xAB, 0xBA, 0xA9, + 0x99, 0x88, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x88, 0x89, 0x99, 0xAB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x55, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0x99, 0x99, 0x87, 0x76, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x89, + 0xAA, 0xAA, 0xA9, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xAB, 0xCB, + 0xA9, 0x99, 0x98, 0x88, 0x89, 0x99, 0xAA, 0xAB, 0xCB, 0xBC, 0xBA, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBC, 0xCC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0xAC, 0xBB, 0xBA, 0xAA, 0x99, 0x99, + 0xAA, 0xAA, 0xAB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xAB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xCC, 0xAB, 0xBA, 0xA9, + 0x99, 0x88, 0x89, 0x99, 0x9A, 0xAB, 0xBC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x99, 0xAB, 0xBB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x78, 0x89, 0x99, 0xAB, 0xA9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x56, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x88, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0x99, 0x98, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xA9, 0x99, 0x98, 0x77, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0x9A, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x89, + 0xAA, 0xAA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xBA, + 0xAB, 0xA9, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xAB, 0xBB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0xBC, 0xDC, 0xBB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xAC, 0xBB, 0xBA, 0xAA, 0xA9, 0x99, + 0xAA, 0xAA, 0xAB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xBD, 0xAB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0xDC, 0xBC, 0xBA, 0xA9, + 0x99, 0x89, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xBC, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xBC, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x65, 0x66, 0x66, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x67, 0x88, 0x9A, 0x99, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0x9A, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x89, + 0xAA, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0x9A, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xBB, 0xCB, + 0xAA, 0x99, 0x98, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xCB, 0xCC, 0xCB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBC, 0xDC, 0xBC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0xAD, 0xCB, 0xBA, 0xAA, 0xAA, 0x9A, + 0xAA, 0xAA, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCC, 0xCC, 0xBC, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xDD, 0x9C, 0xED, + 0xCD, 0xCC, 0xCB, 0xCC, 0xCC, 0xCD, 0xEE, 0xEF, 0xFD, 0xCD, 0xCC, 0xCB, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xDC, 0xCC, 0xBA, 0xAA, 0x99, + 0x9A, 0xAA, 0xBB, 0xBC, 0xDE, 0xFD, 0xCD, 0xBB, 0xA9, 0x98, 0x88, 0x89, + 0x9A, 0xAB, 0xCC, 0xEE, 0xDC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xBC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x89, 0xBB, + 0xCE, 0xDC, 0xCB, 0xA8, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xBC, 0xBA, 0x87, 0x66, 0x55, 0x45, 0x66, 0x78, 0x9A, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xAC, 0xCC, 0xCC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xCD, 0xCC, 0xAA, 0x98, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDC, 0xDD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xED, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xDC, + 0xDE, 0xDD, 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xDD, 0xEE, + 0xDD, 0xCC, 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDD, 0xDF, 0xFE, 0xEE, + 0xDC, 0xCC, 0xCB, 0xCC, 0xCC, 0xCD, 0xDE, 0xDE, 0xFF, 0xFF, 0xEE, 0xDD, + 0xDC, 0xCD, 0xDD, 0xDD, 0xED, 0xED, 0xAE, 0xDD, 0xDD, 0xCD, 0xCC, 0xCC, + 0xCC, 0xCD, 0xDD, 0xDD, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFE, 0xEE, 0xDD, 0xDD, 0xDD, 0xEE, 0xEF, 0xEF, 0xFF, 0xBF, 0xFF, + 0xFF, 0xDD, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, + 0xCC, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFE, 0xDC, 0xCB, 0xAA, + 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFF, 0xEF, 0xDC, 0xBB, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDE, 0xFF, 0xFE, 0xED, 0xBA, 0x99, 0x88, 0x77, 0x78, 0x9A, + 0xBC, 0xDF, 0xFF, 0xED, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xEF, 0xFD, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xCE, 0xFF, + 0xED, 0xBA, 0x97, 0x65, 0x55, 0x45, 0x56, 0x79, 0xAB, 0xDE, 0xFD, 0xCB, + 0xA9, 0x76, 0x55, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xEF, 0xDD, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xDE, 0xEE, 0xDC, 0xA9, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x9A, 0xBD, 0xEF, 0xEE, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xDF, 0xFE, 0xED, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9B, 0xCD, 0xEE, 0xFF, 0xDC, 0xBA, 0x98, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xEF, 0xFF, 0xFE, 0xDC, 0xBA, 0x99, 0x88, 0x89, 0xAA, 0xBC, 0xDE, 0xFF, + 0xFF, 0xFF, 0xDC, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDC, 0xCB, 0xBB, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xDD, 0xCD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xAF, 0xFA, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0x9F, 0xAA, 0xBA, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0x98, 0x89, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x76, 0x78, 0x78, 0x8F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF7, 0x64, 0x56, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xA9, 0x74, 0x22, 0x57, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x97, 0x52, 0x14, 0x69, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x86, + 0x44, 0x57, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x76, 0x77, + 0x89, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x89, 0x99, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xAF, 0xFA, 0xFF, 0xFF, + 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, + 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x79, 0xFA, 0xCF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xAF, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDD, 0xEE, 0xEE, 0xCD, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFD, 0xDC, 0xBB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFE, 0xCC, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDE, 0xEC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x88, 0xAB, + 0xCD, 0xDC, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDD, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xBB, 0xA9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x77, 0x9A, 0xBC, 0xDC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x99, 0xAC, 0xDD, 0xDD, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDC, 0xBA, 0x99, 0x88, 0x78, 0x88, 0x89, 0xAA, 0xBC, 0xDD, + 0xEE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xDE, 0xFE, + 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDD, 0xED, 0xFF, 0xFE, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xEF, 0xFF, 0xFF, 0xED, 0xDD, + 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFE, 0xCF, 0xFF, 0xEE, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDE, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xEF, 0xFF, 0xBF, 0xEF, + 0xED, 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, 0xCB, + 0xBB, 0xBA, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFD, 0xED, 0xCB, 0xBA, 0xA9, + 0x99, 0x9A, 0xBB, 0xCD, 0xEF, 0xFF, 0xDD, 0xCC, 0xBA, 0x99, 0x88, 0x88, + 0x89, 0xAB, 0xCD, 0xEF, 0xED, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAB, 0xDE, 0xFF, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAC, + 0xDE, 0xED, 0xCB, 0xA9, 0x77, 0x66, 0x55, 0x56, 0x67, 0x8A, 0xBC, 0xDE, + 0xDC, 0xBA, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCE, 0xED, 0xCB, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xDC, 0xB9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xEC, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDF, 0xDD, 0xBA, 0x97, 0x66, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xCD, 0xDD, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x9A, 0xBD, 0xDF, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x9A, 0xAC, + 0xDF, 0xDF, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xBB, 0xCD, 0xEE, + 0xFF, 0xFC, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xEF, 0xFF, 0xFE, + 0xEC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xED, 0xEF, 0xFF, 0xED, + 0xDD, 0xCB, 0xCB, 0xCC, 0xDD, 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xEE, 0xED, + 0xDD, 0xDE, 0xEE, 0xEE, 0xFF, 0xFE, 0xAE, 0xFF, 0xEE, 0xEE, 0xEE, 0xED, + 0xFD, 0xED, 0xFE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFE, 0xFF, 0xEE, 0xEF, 0xEF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, + 0xFF, 0xFE, 0xEE, 0xDD, 0xDF, 0xEF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFD, + 0xDD, 0xCB, 0xBC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCB, 0xBA, + 0xAA, 0xBB, 0xBC, 0xDF, 0xFF, 0xFF, 0xEF, 0xDD, 0xCB, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x88, 0x77, 0x88, 0x9A, + 0xBC, 0xDF, 0xFF, 0xFE, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBD, + 0xFF, 0xFE, 0xDC, 0xB9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9B, 0xDE, 0xFF, + 0xEE, 0xCA, 0x98, 0x65, 0x54, 0x45, 0x56, 0x79, 0xAC, 0xEF, 0xFF, 0xDC, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xCD, 0xFF, 0xED, 0xCA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAC, 0xDF, 0xFE, 0xEC, 0xA9, 0x86, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xCD, 0xFF, 0xEE, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xDF, 0xFF, 0xFD, 0xCA, 0x98, 0x76, 0x66, 0x67, 0x89, + 0xAB, 0xCE, 0xEF, 0xFF, 0xEC, 0xBA, 0x98, 0x87, 0x77, 0x89, 0x9B, 0xCD, + 0xEF, 0xFF, 0xFF, 0xEC, 0xBA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDF, 0xFF, + 0xFF, 0xFE, 0xDC, 0xBB, 0xAA, 0xAA, 0xAB, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDD, 0xCB, 0xCB, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0xAA, 0x99, 0xAA, 0xAA, 0xAB, 0xCC, 0xCD, 0xBB, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xEE, 0xBC, 0xBB, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xDA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCC, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBC, 0xCA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x67, 0x78, 0x99, + 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBB, + 0x9A, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xB9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAB, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xAA, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x9A, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAA, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBB, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBB, + 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBC, 0xCC, + 0xBB, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xA9, 0xAA, 0xAB, 0xBB, 0xCD, 0xCD, 0xDD, 0xDC, 0xCB, 0xBB, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xEC, 0xAE, 0xDD, 0xCC, 0xBB, 0xAA, 0xAA, + 0xAB, 0xBB, 0xBC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCB, 0x9B, 0xCB, + 0xBA, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xCA, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBC, 0xCC, 0xAB, 0xA9, 0x98, 0x88, 0x87, 0x77, + 0x88, 0x89, 0x9A, 0xBC, 0xBA, 0xAA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xB9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBB, + 0x9A, 0x98, 0x87, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x87, 0x76, 0x65, + 0x55, 0x66, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAA, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBB, + 0xBB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xCC, 0xBB, + 0xAA, 0xA9, 0x99, 0xAA, 0xAB, 0xBB, 0xDD, 0xBC, 0xDC, 0xCC, 0xCB, 0xBA, + 0xAA, 0xBA, 0xBB, 0xBC, 0xCC, 0xDC, 0x9C, 0xCC, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xAB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xAB, 0xBA, 0xA9, + 0x99, 0x98, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xAB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x55, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x88, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xAB, 0xBB, + 0xAA, 0x99, 0x99, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0xBC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xCB, 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCC, 0x9C, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xEC, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCE, 0xCB, 0xCB, 0xBA, 0x99, 0x98, + 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xDC, 0xBB, 0xBA, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xBC, 0xCB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xCB, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x78, 0x99, + 0xBC, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x89, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x87, 0x76, 0x65, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xBB, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xCB, 0xBB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xCC, + 0xBC, 0xBB, 0x99, 0x98, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCD, 0xCC, 0xDC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xDD, 0xDC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCC, 0xCD, 0xDD, 0xDE, 0xCD, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCD, 0xDD, 0xED, 0x9D, 0xCC, 0xCC, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAE, 0xDE, 0xDD, 0xED, 0xDC, 0xCC, 0xDC, 0xDD, 0xDD, 0xDD, 0x9E, 0xFF, + 0xFF, 0xFD, 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xEF, 0xFD, 0xEF, 0xEE, 0xED, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEF, 0xEE, 0xEF, 0xDE, 0xEF, 0xDD, 0xDC, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFD, 0xDF, 0xED, 0xCC, 0xBB, 0xBB, 0xBB, + 0xBC, 0xCD, 0xDD, 0xFF, 0xDE, 0xEE, 0xDC, 0xBA, 0x99, 0x99, 0x9A, 0xBC, + 0xCE, 0xFE, 0xFD, 0xDF, 0xDC, 0xBA, 0x98, 0x87, 0x88, 0x9A, 0xBC, 0xDE, + 0xFE, 0xDD, 0xEE, 0xCB, 0xA8, 0x76, 0x66, 0x67, 0x9A, 0xBC, 0xEE, 0xFD, + 0xDE, 0xDC, 0xA9, 0x86, 0x54, 0x45, 0x68, 0x9B, 0xCD, 0xEF, 0xED, 0xED, + 0xCB, 0x97, 0x64, 0x32, 0x46, 0x79, 0xBC, 0xDE, 0xFE, 0xDE, 0xEC, 0xB9, + 0x86, 0x42, 0x24, 0x57, 0x9A, 0xCD, 0xEF, 0xDD, 0xED, 0xCB, 0x98, 0x75, + 0x44, 0x56, 0x79, 0xAC, 0xDE, 0xEE, 0xDF, 0xED, 0xCA, 0x98, 0x76, 0x66, + 0x78, 0x9B, 0xCD, 0xFF, 0xED, 0xEF, 0xDC, 0xBA, 0x98, 0x77, 0x78, 0x9A, + 0xBC, 0xDE, 0xFE, 0xDF, 0xED, 0xDC, 0xBA, 0x99, 0x99, 0x9A, 0xBC, 0xDD, + 0xEF, 0xEE, 0xFF, 0xED, 0xCC, 0xBB, 0xAA, 0xBB, 0xBC, 0xDD, 0xEF, 0xFE, + 0xDF, 0xFE, 0xEE, 0xDC, 0xCC, 0xCC, 0xCC, 0xDE, 0xEF, 0xFF, 0xEE, 0xFE, + 0xFE, 0xEE, 0xEE, 0xDD, 0xDD, 0xED, 0xEE, 0xEE, 0xFE, 0xEE, 0xEF, 0xFF, + 0xEE, 0xEE, 0xDE, 0xEE, 0xFE, 0xFF, 0xFF, 0xEE, 0xFF, 0xFF, 0xFE, 0xEF, + 0xEF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0xDD, 0xDD, 0xEE, 0xDD, 0xDD, + 0xEE, 0xDE, 0xEE, 0xFE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0xFE, 0xEF, 0xFF, 0xEF, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEE, 0xDE, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xEC, 0xCC, + 0xCC, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEC, 0xBA, 0xAA, 0xAA, + 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xDE, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xAC, 0xDF, + 0xFF, 0xFF, 0xFE, 0xCB, 0x98, 0x66, 0x55, 0x66, 0x89, 0xBC, 0xDF, 0xFF, + 0xFF, 0xDC, 0xA8, 0x76, 0x44, 0x45, 0x67, 0x8A, 0xCD, 0xFF, 0xFF, 0xFD, + 0xCA, 0x86, 0x54, 0x33, 0x45, 0x68, 0xAC, 0xDF, 0xFF, 0xFF, 0xDC, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xBD, 0xEF, 0xFE, 0xFE, 0xCA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAC, 0xDF, 0xFF, 0xFF, 0xED, 0xB9, 0x86, 0x65, 0x55, + 0x67, 0x9B, 0xCE, 0xFF, 0xFF, 0xFF, 0xDB, 0xA9, 0x87, 0x66, 0x77, 0x8A, + 0xBD, 0xEF, 0xFF, 0xFF, 0xFF, 0xDB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, 0xBA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xDD, 0xCC, 0xBC, 0xCD, 0xDE, 0xEF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xED, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDE, 0xDD, 0xDD, 0xCC, 0xDD, 0xDD, 0xEE, 0xDE, 0xEF, 0xAE, 0xFE, + 0xEE, 0xDD, 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xDF, 0xDE, 0xDC, + 0xCC, 0xBB, 0xBB, 0xCC, 0xDD, 0xFE, 0xEF, 0xEE, 0xFD, 0xDC, 0xBA, 0xAA, + 0x9A, 0xAA, 0xBC, 0xDD, 0xEF, 0xFF, 0xDD, 0xDC, 0xBA, 0xA9, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xFF, 0xFC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAC, 0xDD, 0xFE, 0xDD, 0xCA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xBC, + 0xDE, 0xFC, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xEF, + 0xDD, 0xBA, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0xAB, 0xDE, 0xEC, 0xCB, + 0xA8, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xBD, 0xEF, 0xCC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9B, 0xCD, 0xDD, 0xDB, 0xA8, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xEE, 0xDD, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xCE, 0xED, 0xDC, 0xB9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xFE, 0xED, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xED, 0xEE, 0xCB, 0xAA, 0x98, 0x88, 0x89, 0x9A, 0xBC, 0xDD, 0xEE, + 0xEF, 0xED, 0xCC, 0xBA, 0xA9, 0x99, 0xAA, 0xBB, 0xCD, 0xEF, 0xED, 0xFE, + 0xED, 0xDC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEF, 0xFE, 0xFF, 0xFF, 0xED, + 0xDD, 0xDC, 0xCD, 0xCD, 0xDD, 0xEE, 0xFF, 0xEE, 0xFF, 0xFF, 0xFE, 0xEE, + 0xDE, 0xDD, 0xEE, 0xEF, 0xFF, 0xFF, 0x9F, 0xEE, 0xED, 0xFE, 0xEF, 0xEE, + 0xDF, 0xEE, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDC, 0xCC, 0xCB, 0xCC, 0xCC, 0xDD, 0xEE, 0xEE, 0xBE, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFF, 0xFD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xEE, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xDE, 0xEC, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xEE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xEC, 0xCA, 0x98, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xBC, 0xDD, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCC, 0xDC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xBA, 0x87, 0x66, 0x55, 0x55, + 0x67, 0x78, 0x9A, 0xCD, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCA, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDD, 0xEC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDD, + 0xDE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xEE, 0xEE, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xEF, 0xFE, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xEE, 0xFF, 0xFF, 0xED, 0xDD, + 0xDC, 0xCD, 0xDD, 0xDE, 0xEF, 0xFE, 0xBE, 0xFE, 0xEE, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEE, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDD, 0xDD, 0x9D, 0xFF, + 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEE, 0xEF, 0xFD, 0xEE, 0xDD, 0xCC, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEF, 0xDE, 0xED, 0xCB, 0xBA, 0xA9, + 0x99, 0x9A, 0xAB, 0xCD, 0xDE, 0xFE, 0xDD, 0xCB, 0xAA, 0x99, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xDC, 0xCB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xFD, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCE, 0xEC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x56, 0x77, 0x8A, 0xBD, 0xED, + 0xCC, 0xB9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xCB, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xBB, 0xDD, 0xCC, 0xB9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xDB, 0x98, 0x76, 0x55, + 0x45, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xBA, 0x97, 0x76, 0x55, 0x55, + 0x67, 0x88, 0xAA, 0xCD, 0xDC, 0xDB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x88, 0x9A, 0xAB, + 0xCD, 0xDE, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xDD, + 0xEE, 0xDC, 0xCB, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xEE, 0xDE, 0xFD, + 0xDD, 0xCB, 0xBA, 0xBA, 0xAB, 0xBB, 0xCC, 0xDD, 0xFD, 0xFF, 0xFE, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCC, 0xDC, 0xDD, 0xFE, 0xEF, 0xFF, 0xEF, 0xEE, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDF, 0xFF, 0xEF, 0xAD, 0xDD, 0xDD, 0xDE, 0xDC, 0xDD, + 0xDD, 0xDC, 0xDD, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xDD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, + 0xBC, 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0xAA, 0xAA, + 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x88, 0x76, 0x77, 0x89, 0xAC, 0xDF, + 0xFF, 0xFF, 0xFD, 0xCA, 0x98, 0x66, 0x55, 0x67, 0x89, 0xBC, 0xFF, 0xFF, + 0xFF, 0xFC, 0xA8, 0x76, 0x44, 0x45, 0x67, 0x8A, 0xCF, 0xFF, 0xFF, 0xFD, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x68, 0xAB, 0xDF, 0xFF, 0xFF, 0xDC, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xCA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xFF, 0xFC, 0xB9, 0x86, 0x65, 0x55, + 0x67, 0x9A, 0xCD, 0xFF, 0xFF, 0xFF, 0xDC, 0xA9, 0x87, 0x66, 0x77, 0x8A, + 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xDC, 0xA9, 0x88, 0x88, 0x99, 0xBC, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBA, 0xAA, 0xAA, 0xBC, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xEC, 0xCC, 0xBC, 0xCC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xCD, 0xCC, 0xCC, 0xDD, 0xDE, 0xDE, 0xEE, 0x9E, 0xFF, + 0xED, 0xDD, 0xDC, 0xCC, 0xCD, 0xDE, 0xFE, 0xFF, 0xFF, 0xDF, 0xED, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFF, 0xFE, 0xEE, 0xDC, 0xBA, 0xAA, + 0x9A, 0xAA, 0xBB, 0xCD, 0xDF, 0xFE, 0xDD, 0xDC, 0xBA, 0xA9, 0x98, 0x89, + 0x9A, 0xAB, 0xCD, 0xEF, 0xED, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xEE, 0xCC, 0xCB, 0xA8, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDE, 0xEC, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xED, + 0xCC, 0xBA, 0x98, 0x76, 0x54, 0x55, 0x66, 0x79, 0xAB, 0xCE, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x34, 0x45, 0x67, 0x8A, 0xBC, 0xED, 0xDC, 0xBA, 0x87, + 0x65, 0x54, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xDB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x67, 0x9A, 0xBC, 0xDD, 0xCD, 0xCA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDD, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xBC, 0xED, 0xDE, 0xDC, 0xA9, 0x98, 0x77, 0x77, 0x89, 0x9A, 0xBC, + 0xDD, 0xDD, 0xFD, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0x9A, 0xBC, 0xCD, 0xFE, + 0xEF, 0xED, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xED, 0xFF, + 0xED, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0xFE, 0xEF, 0xFF, 0xED, + 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDF, 0xFF, 0xED, 0xFF, 0xFF, 0xEE, 0xED, + 0xDD, 0xDD, 0xEE, 0xEF, 0xFF, 0xFE, 0x9E, 0xDD, 0xED, 0xDD, 0xDD, 0xDD, + 0xED, 0xDD, 0xDE, 0xEE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0x9B, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xED, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xCB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xDC, 0xAB, 0xAA, 0x99, 0x88, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xCC, 0xCA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xCB, 0xAA, 0x99, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x9A, + 0xAB, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x87, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAB, 0xBA, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xBB, 0xBB, 0xA9, 0x88, 0x87, 0x77, 0x78, 0x88, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xCC, 0xDC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xCD, 0xDC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xCC, 0xDD, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEC, 0x8D, 0xCC, 0xCB, 0xBB, 0xBA, 0xAA, + 0xBB, 0xBB, 0xBC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0x9B, 0xCC, + 0xBB, 0xAA, 0xAA, 0x99, 0xAA, 0xAA, 0xBB, 0xCD, 0xDC, 0xAB, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCC, 0xCA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBB, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x77, + 0x89, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBB, + 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xA9, 0x9A, 0xAA, 0xAB, 0xBB, 0xCC, 0xBC, 0xDC, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCC, 0xDC, 0x9C, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0xAA, 0x99, 0x9A, 0xAA, 0xAB, 0xBB, 0xCC, 0x8B, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xCB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCC, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x77, + 0x88, 0x89, 0x9A, 0xBC, 0xBA, 0xAA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xBB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x78, 0x9A, + 0xAB, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, 0x87, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x87, 0x66, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x67, 0x77, + 0x89, 0xAA, 0xBA, 0xAB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xAB, 0xBB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x88, 0x89, 0x9A, 0xAB, 0xBB, + 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xBB, 0xCC, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xCD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xCD, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBA, 0xBB, 0xBB, 0xBC, 0xCD, 0xDC, 0x9C, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xCC, 0xCC, 0xBB, 0xBB, 0xCC, 0xCC, 0xDD, 0xDD, 0x8D, 0xEE, + 0xDD, 0xCC, 0xCC, 0xCB, 0xCC, 0xDD, 0xEF, 0xEE, 0xFE, 0xDE, 0xDC, 0xCC, + 0xBB, 0xAB, 0xBB, 0xBB, 0xCC, 0xDD, 0xFF, 0xED, 0xDD, 0xCB, 0xBA, 0xA9, + 0x99, 0xAA, 0xAB, 0xBC, 0xDD, 0xFD, 0xCD, 0xCB, 0xAA, 0x99, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDE, 0xDC, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAA, 0xCD, 0xDD, 0xCC, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCE, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x8A, 0xBC, 0xDD, + 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9B, 0xBC, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xAC, 0xCC, 0xCB, 0xB9, 0x87, + 0x65, 0x54, 0x34, 0x56, 0x78, 0x9A, 0xCC, 0xCC, 0xCA, 0x98, 0x76, 0x55, + 0x54, 0x56, 0x67, 0x89, 0xAB, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0x9A, 0xCC, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x9A, 0xBB, + 0xCD, 0xDD, 0xEC, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xDD, + 0xDD, 0xEC, 0xBB, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDD, 0xDD, 0xFE, + 0xDC, 0xCB, 0xBB, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xED, 0xEF, 0xEE, 0xDD, + 0xCC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDD, 0xDE, 0xEE, 0xFF, 0xEE, 0xDE, 0xDD, + 0xCD, 0xDC, 0xDD, 0xED, 0xEF, 0xEE, 0x9E, 0xEE, 0xDD, 0xDD, 0xDC, 0xCC, + 0xCC, 0xCD, 0xDD, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, 0xCB, + 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xDC, 0xBA, 0xAA, 0xAA, + 0xBB, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xFF, 0xFF, 0xFF, 0xEC, 0xBA, 0x98, 0x76, 0x67, 0x89, 0xAB, 0xDD, + 0xFF, 0xFF, 0xED, 0xCA, 0x98, 0x66, 0x55, 0x66, 0x89, 0xBC, 0xDF, 0xFF, + 0xFF, 0xDB, 0xA8, 0x76, 0x54, 0x44, 0x67, 0x8A, 0xBC, 0xFF, 0xFF, 0xFD, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x68, 0xAB, 0xEF, 0xFF, 0xFF, 0xDB, 0xA8, + 0x65, 0x43, 0x34, 0x56, 0x8A, 0xBD, 0xEF, 0xFE, 0xFD, 0xCA, 0x87, 0x64, + 0x44, 0x56, 0x78, 0xAB, 0xDE, 0xFF, 0xEF, 0xDC, 0xB9, 0x86, 0x65, 0x56, + 0x67, 0x9A, 0xCD, 0xFF, 0xFE, 0xFF, 0xDC, 0xA9, 0x87, 0x66, 0x77, 0x8A, + 0xBC, 0xDF, 0xFF, 0xEF, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBB, 0xDE, + 0xFF, 0xFF, 0xFF, 0xED, 0xCB, 0xAA, 0xA9, 0xAA, 0xBB, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDC, 0xCB, 0xBB, 0xBC, 0xCE, 0xFF, 0xFF, 0xFD, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDD, 0xDF, 0xEE, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xED, 0xED, 0xDD, 0xCC, 0xCD, 0xDD, 0xDD, 0xED, 0xDE, 0x9E, 0xFF, + 0xFE, 0xDD, 0xDC, 0xCC, 0xDD, 0xDE, 0xEE, 0xFE, 0xFE, 0xFE, 0xED, 0xDD, + 0xCC, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0xEF, 0xED, 0xFE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xFF, 0xDE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xCD, 0xEF, 0xEC, 0xDC, 0xBB, 0xA9, 0x88, 0x77, 0x88, 0x9A, + 0xBC, 0xCE, 0xEE, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xEF, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xCD, 0xEE, + 0xDC, 0xBA, 0x98, 0x66, 0x54, 0x45, 0x56, 0x89, 0xAC, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xED, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xDD, 0xDD, 0xDB, 0xA9, 0x86, 0x55, + 0x44, 0x55, 0x67, 0x9A, 0xBD, 0xDD, 0xDE, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xDE, 0xED, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x89, + 0xAB, 0xCD, 0xEE, 0xDE, 0xDC, 0xAA, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xDE, 0xED, 0xED, 0xDB, 0xBA, 0x99, 0x99, 0x99, 0x9A, 0xBC, 0xDD, 0xEF, + 0xEE, 0xED, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xEF, 0xFD, 0xEF, + 0xDD, 0xDC, 0xCB, 0xBB, 0xBB, 0xCC, 0xDE, 0xEE, 0xFF, 0xDF, 0xFF, 0xED, + 0xDD, 0xCC, 0xDD, 0xCD, 0xDE, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xEE, 0xEE, + 0xDF, 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0x9D, 0xED, 0xDE, 0xDE, 0xDE, 0xED, + 0xEE, 0xEE, 0xFF, 0xEF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xED, 0xDC, 0xCC, 0xBC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xAE, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDE, 0xEF, 0xFE, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEF, 0xED, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xEE, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xDE, 0xEC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAA, 0xCC, 0xED, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xBA, 0x98, 0x87, 0x65, 0x55, 0x56, 0x77, 0x89, 0xBC, 0xDD, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xBA, 0x87, 0x76, 0x55, 0x55, + 0x67, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, + 0xCD, 0xDD, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDE, + 0xDE, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xEE, 0xEE, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFE, 0xDF, 0xED, 0xDD, + 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xED, 0xFF, 0xEE, 0xED, 0xDD, + 0xCD, 0xCD, 0xDD, 0xEE, 0xFF, 0xFF, 0xAE, 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEE, 0xEF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xED, 0xDD, 0xDC, 0xDC, 0xDC, 0xCC, 0xCD, 0xDD, 0xDD, 0x8E, 0xFE, + 0xEE, 0xDD, 0xDC, 0xCC, 0xCD, 0xDD, 0xEE, 0xEE, 0xFE, 0xEF, 0xEE, 0xDC, + 0xCC, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xEF, 0xDE, 0xFE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAB, 0xBC, 0xCD, 0xDD, 0xED, 0xDE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, + 0x9A, 0xBB, 0xCD, 0xDF, 0xDD, 0xEC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x9A, + 0xBB, 0xDD, 0xFD, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xDD, 0xEC, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xEC, + 0xCC, 0xBA, 0x98, 0x75, 0x54, 0x45, 0x56, 0x89, 0xAB, 0xCE, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xDC, 0xA9, 0x86, 0x55, + 0x44, 0x55, 0x78, 0x9A, 0xBC, 0xDD, 0xDD, 0xCA, 0x98, 0x76, 0x55, 0x56, + 0x67, 0x89, 0xAC, 0xDD, 0xDD, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x77, 0x89, + 0xAB, 0xBD, 0xED, 0xCD, 0xDC, 0xB9, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xDE, 0xED, 0xDE, 0xCB, 0xBA, 0x99, 0x98, 0x99, 0xAB, 0xBB, 0xCD, 0xEE, + 0xDE, 0xED, 0xDC, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEE, 0xDD, 0xEE, + 0xDC, 0xDC, 0xBC, 0xBC, 0xBB, 0xCC, 0xCD, 0xDD, 0xFD, 0xDF, 0xEE, 0xDE, + 0xDC, 0xCD, 0xCD, 0xDD, 0xDD, 0xDE, 0xEE, 0xED, 0xEF, 0xEF, 0xFF, 0xEE, + 0xED, 0xDE, 0xED, 0xDD, 0xFF, 0xFD, 0x9D, 0xDD, 0xDE, 0xCD, 0xDC, 0xDD, + 0xDD, 0xED, 0xDE, 0xEF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFD, 0xDF, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, + 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBB, 0xBB, + 0xCC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBB, 0xA9, 0x99, 0x9A, 0xBC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x98, 0x87, 0x78, 0x8A, 0xBC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCB, 0xA8, 0x76, 0x55, 0x67, 0x9A, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFD, 0xB9, 0x76, 0x54, 0x45, 0x68, 0x9B, 0xCF, 0xFF, 0xFF, 0xFF, + 0xCB, 0x97, 0x54, 0x23, 0x45, 0x79, 0xBC, 0xFF, 0xFF, 0xFF, 0xFC, 0xA9, + 0x75, 0x43, 0x24, 0x57, 0x9B, 0xCF, 0xFF, 0xFF, 0xFF, 0xDB, 0x98, 0x65, + 0x44, 0x56, 0x79, 0xBC, 0xFF, 0xFF, 0xFF, 0xFD, 0xCA, 0x87, 0x65, 0x56, + 0x78, 0xAB, 0xCF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x88, 0x77, 0x78, 0x9A, + 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x99, 0x99, 0xAA, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xBA, 0xBB, 0xCD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xFC, 0xCC, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDD, 0x9E, 0xEF, + 0xDD, 0xCC, 0xCB, 0xCC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFE, 0xDE, 0xED, 0xCC, + 0xCB, 0xBA, 0xBA, 0xBB, 0xCD, 0xCD, 0xEE, 0xEE, 0xED, 0xCC, 0xBA, 0xA9, + 0x99, 0x9A, 0xBB, 0xBD, 0xDD, 0xFE, 0xDE, 0xCB, 0xBA, 0x99, 0x88, 0x88, + 0x99, 0xAB, 0xBC, 0xDE, 0xDC, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xEE, 0xCD, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x78, 0x89, 0xBB, + 0xCE, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x87, 0x66, 0x54, 0x45, 0x56, 0x78, 0x9B, 0xCD, 0xCB, 0xCB, + 0x98, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xBC, 0xCD, 0xCC, 0xB9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0xA8, 0x76, 0x65, + 0x44, 0x56, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x88, + 0x9A, 0xBC, 0xDD, 0xCD, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDD, 0xDC, 0xEC, 0xBB, 0xA9, 0x98, 0x88, 0x99, 0x99, 0xBB, 0xCD, 0xDD, + 0xCE, 0xDC, 0xCB, 0xAA, 0xA9, 0x99, 0xAA, 0xBB, 0xBD, 0xDF, 0xDD, 0xEE, + 0xDD, 0xCB, 0xBB, 0xBA, 0xAB, 0xBC, 0xCD, 0xDE, 0xFE, 0xDE, 0xEE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xED, 0xFF, 0xEE, 0xDD, 0xDD, + 0xDC, 0xDE, 0xDD, 0xEE, 0xEF, 0xFD, 0x8D, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, + 0xDC, 0xDD, 0xDE, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0x8C, 0xDC, + 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xBC, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xCB, 0xCB, 0xBA, 0xA9, 0x98, + 0x88, 0x99, 0x99, 0xAB, 0xBC, 0xDC, 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xCC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xBA, 0xA9, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x77, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x66, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x89, 0xAB, 0xBB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xBB, 0xBB, 0xA9, 0x98, 0x88, 0x77, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xA9, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xCC, 0xCC, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xEC, 0xCD, 0xDC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDE, 0xCC, 0xED, 0xCC, 0xCC, 0xCB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xDD, 0x8C, 0xCB, 0xCB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xCB, 0xCC, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0x9B, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xAB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xBB, 0xA9, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBA, + 0xAB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xBB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xBB, 0xCC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x8B, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCC, 0xDB, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xBB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x9A, 0xAB, 0xBB, 0xDB, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xBA, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x65, 0x54, 0x55, 0x56, 0x78, 0x89, 0xAB, 0xAA, 0xAA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAB, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x67, 0x78, 0x99, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x89, 0xAA, 0xBA, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBB, 0xBA, 0xBB, 0xAA, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xCB, 0xBC, 0xCC, 0xBB, + 0xAB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xBC, 0xDC, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDC, 0x8B, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xDD, 0xCC, 0xCC, 0xCC, 0xBC, 0xCC, 0xCC, 0xCC, 0xDC, 0x8E, 0xEE, + 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFD, 0xEE, 0xED, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xDD, 0xED, 0xCC, 0xBA, 0xAA, + 0xA9, 0xAA, 0xAB, 0xCC, 0xDE, 0xFD, 0xCD, 0xDC, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x99, + 0xAB, 0xCD, 0xED, 0xCD, 0xBB, 0x99, 0x87, 0x66, 0x66, 0x78, 0x8A, 0xBB, + 0xCD, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xBC, 0xBA, 0x97, 0x66, 0x54, 0x45, 0x66, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0x98, 0x76, 0x54, 0x44, 0x45, 0x67, 0x89, 0xBC, 0xDD, 0xBC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0x9A, 0xCD, 0xCC, 0xCB, 0xA9, 0x86, 0x65, + 0x44, 0x56, 0x67, 0x9A, 0xAC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xA9, 0x98, 0x76, 0x66, 0x67, 0x88, + 0x9A, 0xBC, 0xDD, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDD, 0xCB, 0xA9, 0x99, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xDD, + 0xCD, 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xDD, 0xEE, + 0xDC, 0xCB, 0xBB, 0xBA, 0xBB, 0xBC, 0xCC, 0xDE, 0xEE, 0xEE, 0xFE, 0xDD, + 0xCC, 0xBC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xED, 0xFE, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xEE, 0xEF, 0xFD, 0x9D, 0xED, 0xCC, 0xDC, 0xCC, 0xDC, + 0xDD, 0xDD, 0xEE, 0xED, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xEE, 0xFE, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDC, + 0xDC, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, 0xBB, 0xBB, + 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDB, 0xAA, 0x9A, 0xAB, 0xCC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBD, 0xEF, + 0xFF, 0xFF, 0xFF, 0xDC, 0xA9, 0x87, 0x66, 0x78, 0x9B, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFD, 0xBA, 0x86, 0x54, 0x45, 0x78, 0xAC, 0xDE, 0xFF, 0xFF, 0xFF, + 0xDB, 0x98, 0x64, 0x22, 0x46, 0x89, 0xBC, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, + 0x86, 0x42, 0x24, 0x68, 0x9B, 0xDE, 0xFF, 0xFD, 0xFF, 0xCC, 0xA8, 0x75, + 0x44, 0x56, 0x8A, 0xBD, 0xFF, 0xFF, 0xFF, 0xED, 0xCB, 0x98, 0x76, 0x66, + 0x79, 0xAC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xCA, 0x98, 0x88, 0x89, 0xAB, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBB, 0xAA, 0x9A, 0xAB, 0xCD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, 0xCB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFF, + 0xEF, 0xFE, 0xFE, 0xDD, 0xDC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xEF, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xEF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDD, 0xDE, 0xDE, 0xDE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xCC, 0xDD, 0x9E, 0xEE, + 0xEE, 0xED, 0xDC, 0xCD, 0xCD, 0xDD, 0xDD, 0xEF, 0xED, 0xEE, 0xDD, 0xCC, + 0xCC, 0xBB, 0xCB, 0xCC, 0xDD, 0xDE, 0xEF, 0xDD, 0xEE, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAB, 0xBC, 0xCC, 0xDE, 0xEE, 0xDE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0xAA, 0xBC, 0xCC, 0xDE, 0xDC, 0xDC, 0xBA, 0x99, 0x88, 0x78, 0x88, 0x9A, + 0xBC, 0xCD, 0xDD, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x56, 0x78, 0xAB, 0xCD, 0xED, + 0xCD, 0xBA, 0x98, 0x65, 0x54, 0x45, 0x57, 0x89, 0xBB, 0xCD, 0xDC, 0xDB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x68, 0x9A, 0xBC, 0xDD, 0xDD, 0xBA, 0x98, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xDB, 0xA9, 0x87, 0x55, + 0x44, 0x55, 0x68, 0x9A, 0xCC, 0xED, 0xCC, 0xCB, 0xA8, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xDD, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x89, + 0xAB, 0xCD, 0xED, 0xCD, 0xCC, 0xBA, 0x98, 0x88, 0x78, 0x89, 0x9A, 0xCC, + 0xDE, 0xEC, 0xDC, 0xCB, 0xBA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xEE, + 0xDD, 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDE, 0xEE, 0xED, 0xED, + 0xDD, 0xDC, 0xCB, 0xBB, 0xBB, 0xBD, 0xCD, 0xFE, 0xEE, 0xCE, 0xEE, 0xDD, + 0xDD, 0xDC, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEC, 0xFE, 0xEE, 0xFE, 0xFD, + 0xDD, 0xDD, 0xEE, 0xEF, 0xEF, 0xFE, 0x8D, 0xDC, 0xDD, 0xDD, 0xCD, 0xDD, + 0xDD, 0xDD, 0xDE, 0xFE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDD, 0xAD, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xDE, 0xFD, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xDD, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xDD, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDC, 0xCC, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xCB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAC, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xBB, 0xB9, 0x88, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDC, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCC, 0xED, + 0xCD, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xDD, 0xDD, + 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFE, 0xDE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xED, 0xEE, 0xED, 0xDD, 0xCC, + 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xFF, 0xAD, 0xDD, 0xCD, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xDE, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCB, 0xCC, 0xCC, 0xCC, 0xDC, 0x9D, 0xFE, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDE, 0xED, 0xDE, 0xED, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xDD, 0xEC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xDC, 0xCD, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xBC, 0xDE, 0xCC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCC, 0xDC, 0xCC, 0xBA, 0xA8, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCC, 0xBA, 0x98, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x68, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0xAA, 0xBC, 0xDC, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x89, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDC, 0xBB, 0xAA, 0x99, 0x98, 0x99, 0x9A, 0xBB, 0xCD, 0xED, + 0xCD, 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEE, 0xDC, 0xED, + 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xED, 0xDE, 0xDD, 0xDC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xDD, 0xEE, 0xED, 0xDD, 0xDD, + 0xDC, 0xDD, 0xDD, 0xEE, 0xEF, 0xFE, 0x9D, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xDD, 0xDD, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFE, 0xEE, 0xDD, 0xDD, 0xDD, 0xDC, 0xDD, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFF, 0xEE, 0xED, 0xDF, 0xDE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xED, + 0xDC, 0xDD, 0xDC, 0xDD, 0xDE, 0xFF, 0xFF, 0xEE, 0xFF, 0xDD, 0xDC, 0xCB, + 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xFE, 0xFF, 0xED, 0xDC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCD, 0xDE, 0xFF, 0xED, 0xFE, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xEF, 0xFF, 0xDF, 0xDC, 0xBA, 0x98, 0x76, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xFE, 0xED, 0xCA, 0x98, 0x66, 0x55, 0x67, 0x89, 0xBC, 0xDE, 0xFE, + 0xED, 0xDB, 0xA8, 0x76, 0x44, 0x44, 0x67, 0x8A, 0xBD, 0xDF, 0xFD, 0xFC, + 0xBA, 0x86, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCE, 0xFE, 0xEE, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x89, 0xBC, 0xFF, 0xFE, 0xED, 0xBA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDE, 0xFF, 0xDF, 0xDC, 0xA9, 0x87, 0x65, 0x56, + 0x68, 0x9A, 0xCD, 0xEF, 0xFE, 0xEE, 0xCB, 0xA9, 0x87, 0x76, 0x78, 0x8A, + 0xBC, 0xDF, 0xFF, 0xDE, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xDE, + 0xFF, 0xFE, 0xEE, 0xDD, 0xCB, 0xAA, 0x99, 0xAA, 0xBC, 0xCE, 0xFF, 0xFF, + 0xEF, 0xFF, 0xDD, 0xCC, 0xBB, 0xBB, 0xCC, 0xDE, 0xEF, 0xFF, 0xFE, 0xFE, + 0xEF, 0xDD, 0xDC, 0xCD, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xEE, 0xED, 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0xDF, 0xFF, 0xFF, 0xFD, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0x9E, 0xFF, + 0xEE, 0xDE, 0xDC, 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFE, 0xFF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEE, 0xFF, 0xDD, 0xFE, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCD, 0xDD, 0xEE, 0xDE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xAB, 0xDE, 0xDE, 0xDD, 0xEC, 0xCA, 0x99, 0x88, 0x77, 0x88, 0x9A, + 0xBB, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xED, + 0xCC, 0xCA, 0x98, 0x65, 0x54, 0x45, 0x66, 0x89, 0xAB, 0xDD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBD, 0xDC, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xEC, 0xCB, 0xA9, 0x86, 0x65, + 0x44, 0x55, 0x68, 0x9A, 0xBD, 0xDD, 0xCD, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x89, + 0xAB, 0xCD, 0xFD, 0xCE, 0xCB, 0xBA, 0x98, 0x87, 0x77, 0x89, 0x9A, 0xBC, + 0xEE, 0xDC, 0xDD, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFE, + 0xDE, 0xDD, 0xCC, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xED, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCD, 0xDE, 0xEF, 0xFF, 0xDE, 0xEE, 0xDE, + 0xDD, 0xCC, 0xCD, 0xDE, 0xEE, 0xEF, 0xFF, 0xED, 0xFF, 0xFE, 0xEE, 0xDD, + 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0x8D, 0xCD, 0xCD, 0xDD, 0xDC, 0xCD, + 0xED, 0xEE, 0xEE, 0xFF, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x8B, 0xCC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xBC, 0xCB, 0xAA, + 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xBB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x88, + 0x89, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAB, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xAA, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xBA, 0xCB, 0xAA, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xCB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xBC, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xCC, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xED, 0x8C, 0xBB, 0xBB, 0xBB, 0xAB, 0xAB, + 0xBB, 0xBC, 0xCC, 0xCD, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0x8B, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xBB, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x88, + 0x88, 0x99, 0xAA, 0xBB, 0xAA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0x9A, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x88, 0x9A, 0xAA, 0x9A, 0x98, 0x87, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x99, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBA, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xBA, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xBB, 0xDC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xBB, 0xBB, 0xBC, 0xCD, 0xDC, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x8B, 0xCC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDB, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xCD, 0xBB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x99, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x9A, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xBB, 0xAB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xAA, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0xA8, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xBB, 0xA9, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0xDC, 0xBC, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCB, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCC, 0xDD, 0xDC, 0x8B, 0xBB, 0xBB, 0xBB, 0xAA, 0xAA, + 0xAB, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xEC, 0xCC, 0xCB, 0xCB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCD, 0x8D, 0xED, + 0xED, 0xDC, 0xCB, 0xBB, 0xBC, 0xCD, 0xCD, 0xEF, 0xFD, 0xDE, 0xED, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xCE, 0xEE, 0xDD, 0xDD, 0xCB, 0xBA, 0x99, + 0x99, 0x9A, 0xAA, 0xBC, 0xDE, 0xED, 0xDD, 0xCB, 0xBA, 0x99, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDD, 0xDC, 0xDB, 0xAA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xBC, 0xDC, 0xCD, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x78, 0x89, 0xAB, + 0xCD, 0xCB, 0xCA, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x99, 0xBC, 0xDC, + 0xBB, 0xA9, 0x87, 0x66, 0x54, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xCC, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xDB, 0xCB, 0x98, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCD, 0xDD, + 0xCD, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xDE, 0xEC, 0xED, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xED, 0xDE, 0xED, 0xDC, + 0xCC, 0xBC, 0xBC, 0xCC, 0xDD, 0xDE, 0xFF, 0xED, 0xFF, 0xDD, 0xDD, 0xDD, + 0xCD, 0xDD, 0xDD, 0xEE, 0xEF, 0xFE, 0x9D, 0xDD, 0xDD, 0xDD, 0xCC, 0xCC, + 0xCC, 0xDD, 0xEE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFE, 0xED, 0xDE, 0xDD, 0xDD, 0xDD, 0xDD, 0xCC, 0xDD, 0x9F, 0xFF, + 0xFF, 0xEE, 0xDE, 0xDD, 0xDD, 0xDE, 0xEE, 0xEF, 0xFD, 0xEF, 0xEF, 0xEE, + 0xDD, 0xCC, 0xCC, 0xCD, 0xCD, 0xEE, 0xFF, 0xDF, 0xFF, 0xED, 0xCC, 0xCB, + 0xBB, 0xBB, 0xCC, 0xDD, 0xDE, 0xFE, 0xDE, 0xDD, 0xCC, 0xAA, 0xAA, 0xAA, + 0xAB, 0xBC, 0xDD, 0xFF, 0xEE, 0xFD, 0xCB, 0xBA, 0x98, 0x88, 0x89, 0xAA, + 0xBC, 0xDF, 0xFF, 0xEE, 0xDC, 0xB9, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xEF, 0xEE, 0xEC, 0xBA, 0x97, 0x66, 0x55, 0x67, 0x89, 0xAB, 0xCE, 0xFE, + 0xDE, 0xCB, 0xA8, 0x76, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDE, 0xED, 0xEC, + 0xB9, 0x87, 0x54, 0x33, 0x45, 0x78, 0x9B, 0xCE, 0xEE, 0xDD, 0xCB, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xBC, 0xDF, 0xED, 0xEC, 0xCA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDE, 0xEE, 0xDD, 0xDB, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xCD, 0xFF, 0xED, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x8A, + 0xBC, 0xEF, 0xFF, 0xDF, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x9A, 0xBB, 0xCE, + 0xEF, 0xFD, 0xED, 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xFF, + 0xDF, 0xED, 0xDC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFD, 0xEE, + 0xDD, 0xDD, 0xCC, 0xCD, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xDF, 0xEF, 0xEF, + 0xDD, 0xEE, 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFE, 0xFE, + 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xDD, 0xDE, 0xDE, 0xED, 0xDD, + 0xEE, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0x9D, 0xFE, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEF, 0xED, 0xDE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEF, 0xDD, 0xDD, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xED, 0xCD, 0xDB, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xCC, 0xEE, 0xDC, 0xDC, 0xBA, 0x98, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xDD, 0xCC, 0xBA, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xAB, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xDD, + 0xCC, 0xBA, 0x98, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCE, 0xDB, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCE, 0xDC, 0xCC, 0xAA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9B, 0xBD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xEE, 0xDC, 0xDD, 0xCB, 0xAA, 0x99, 0x98, 0x99, 0xAA, 0xBC, 0xDE, 0xEE, + 0xCD, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xFF, 0xEC, 0xDD, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFE, 0xCF, 0xEE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEF, 0xFF, 0xED, 0xEE, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEE, 0xFE, 0xFF, 0xFE, 0x8C, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xEE, 0xEE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xDD, 0xCC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0x9E, 0xEE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xDE, 0xED, 0xDE, 0xDC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDE, 0xDD, 0xDD, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xED, 0xCD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDD, 0xDC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x89, 0xAB, + 0xCC, 0xCC, 0xCB, 0x99, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCB, 0xA9, 0x87, 0x65, 0x54, 0x55, 0x67, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x87, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAC, 0xDC, 0xBC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0x9B, 0xCD, 0xCB, 0xCB, 0xA9, 0x88, 0x77, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDC, 0xCC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDD, + 0xCD, 0xCC, 0xBB, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDE, 0xEC, 0xDD, + 0xCC, 0xBB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xEE, 0xDE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xEF, 0xED, 0xEE, 0xDD, 0xDD, 0xCC, + 0xCC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFE, 0xAD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xDE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x9D, 0xFF, + 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEE, 0xFD, 0xDE, 0xED, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xDD, 0xDD, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEC, 0xDD, 0xDC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCD, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xAC, + 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xCC, 0xDD, 0xCD, 0xCB, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDD, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xED, + 0xCD, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEE, 0xDC, 0xED, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFD, 0xCE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFF, 0xED, 0xEE, 0xEE, 0xDE, 0xDD, + 0xDD, 0xDE, 0xDE, 0xEE, 0xFF, 0xFE, 0x9D, 0xDC, 0xCD, 0xDD, 0xCC, 0xCD, + 0xDD, 0xDD, 0xDE, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFF, 0xEE, 0xDD, 0xCD, 0xCC, 0xDC, 0xCC, 0xDD, 0xCD, 0x8F, 0xFF, + 0xFF, 0xFE, 0xED, 0xEE, 0xDD, 0xDE, 0xEE, 0xFF, 0xFD, 0xEF, 0xFF, 0xEE, + 0xDD, 0xCC, 0xCD, 0xDD, 0xDE, 0xEE, 0xEF, 0xDE, 0xFE, 0xED, 0xDC, 0xCB, + 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xFE, 0xEE, 0xEE, 0xCC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCC, 0xCE, 0xEF, 0xED, 0xED, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAA, + 0xCD, 0xDE, 0xFE, 0xDE, 0xDC, 0xBA, 0x88, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xEF, 0xEE, 0xED, 0xCB, 0x98, 0x65, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xFE, + 0xEE, 0xDB, 0xA9, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xEF, 0xED, 0xEC, + 0xCA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCE, 0xFE, 0xDD, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xBD, 0xEF, 0xED, 0xDC, 0xBA, 0x97, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDE, 0xEE, 0xDE, 0xCB, 0xA9, 0x87, 0x65, 0x55, + 0x68, 0x9A, 0xCD, 0xEF, 0xFD, 0xED, 0xCB, 0xA9, 0x87, 0x76, 0x78, 0x9A, + 0xBC, 0xEE, 0xFF, 0xDF, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDE, + 0xEF, 0xED, 0xFE, 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xBC, 0xDE, 0xDE, 0xFE, + 0xDF, 0xED, 0xDC, 0xCC, 0xBB, 0xBB, 0xCC, 0xDE, 0xEE, 0xFF, 0xED, 0xEF, + 0xED, 0xDD, 0xCD, 0xDD, 0xDD, 0xEE, 0xFF, 0xFE, 0xFE, 0xDF, 0xFE, 0xDE, + 0xEE, 0xEE, 0xDE, 0xEE, 0xFF, 0xEF, 0xFE, 0xFE, 0xFF, 0xEE, 0xEE, 0xEF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, + 0xEE, 0xFE, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xCC, 0xBB, 0xBB, 0xCC, 0xCC, 0xBC, 0xBC, 0xCD, 0x8D, 0xEE, + 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xED, 0xDE, 0xED, 0xDC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xCD, 0xDF, 0xDC, 0xDC, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xED, 0xCD, 0xCC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCD, 0xCB, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xDC, + 0xCD, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xED, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCD, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAC, 0xCE, 0xCC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x89, + 0x9A, 0xBC, 0xED, 0xCC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x89, 0x9A, 0xBC, + 0xDF, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xED, + 0xCE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xDC, 0xED, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xDE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDF, 0xEF, 0xED, 0xFF, 0xEE, 0xED, 0xDC, + 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFE, 0x7C, 0xCD, 0xCC, 0xCC, 0xCC, 0xCD, + 0xDD, 0xDD, 0xED, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0x8B, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xBB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x98, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xA9, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0x98, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xBB, 0xA9, 0x98, 0x88, 0x87, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xAB, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xCB, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xBC, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCB, 0xDD, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xED, 0x8B, 0xBB, 0xBB, 0xBB, 0xBA, 0xAA, + 0xBB, 0xBB, 0xCC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0x8B, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xBB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAA, 0xBB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBA, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0xA9, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xBB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCB, 0xBC, 0xBB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xCC, 0xDC, 0x8B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x8C, 0xDC, + 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xCC, 0xBB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xCB, 0xBB, 0xAA, 0x99, 0x88, 0x87, 0x88, + 0x89, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0x98, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDB, 0xBD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xCB, 0xDC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xDC, 0x8C, 0xBB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xCD, 0xCB, 0xCB, 0xBB, 0xCB, 0xCB, 0xCC, 0xCC, 0x7D, 0xFF, + 0xDD, 0xCC, 0xCB, 0xBB, 0xCC, 0xCD, 0xDD, 0xDE, 0xED, 0xDD, 0xDC, 0xCC, + 0xBB, 0xAB, 0xAB, 0xBB, 0xCC, 0xDD, 0xEE, 0xDD, 0xDD, 0xCB, 0xBA, 0xA9, + 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xEC, 0xCD, 0xCB, 0xAA, 0x99, 0x88, 0x89, + 0x99, 0xAA, 0xBC, 0xDD, 0xDC, 0xDB, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x99, + 0xAB, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x89, 0xAB, + 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xBC, 0xB9, 0x87, 0x65, 0x54, 0x55, 0x67, 0x79, 0x9B, 0xBC, 0xCC, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x45, 0x67, 0x89, 0xAC, 0xCD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9B, 0xBD, 0xDB, 0xCA, 0xA8, 0x87, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xBB, 0xCD, 0xBB, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAA, 0xCD, 0xDC, 0xCB, 0xA9, 0x88, 0x77, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBB, 0xA9, 0x98, 0x77, 0x77, 0x88, 0x9A, 0xBB, + 0xDE, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x89, 0x9A, 0xBB, 0xDD, 0xED, + 0xDD, 0xDC, 0xBB, 0xAA, 0xA9, 0x99, 0xAA, 0xBC, 0xCD, 0xEF, 0xDC, 0xED, + 0xDC, 0xBB, 0xBB, 0xAA, 0xBB, 0xBC, 0xCC, 0xEE, 0xEE, 0xDE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEE, 0xEF, 0xFD, 0xFE, 0xDD, 0xDD, 0xDC, + 0xDD, 0xDD, 0xDE, 0xED, 0xFF, 0xFE, 0x8D, 0xCD, 0xCD, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xEE, 0xEF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xED, 0xDD, 0xDD, 0xDC, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xEE, 0xED, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xDC, + 0xCC, 0xCC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xCB, 0xBB, 0xAB, + 0xBC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xBB, 0xA9, 0x99, 0x9A, 0xAB, + 0xCD, 0xFF, 0xFF, 0xEF, 0xFD, 0xCA, 0x98, 0x77, 0x77, 0x89, 0xAC, 0xDF, + 0xFF, 0xFF, 0xFE, 0xDB, 0xA8, 0x76, 0x56, 0x67, 0x8A, 0xBD, 0xDF, 0xFF, + 0xFF, 0xFC, 0xB9, 0x76, 0x54, 0x45, 0x68, 0x9B, 0xCD, 0xFF, 0xFF, 0xFD, + 0xCB, 0x97, 0x54, 0x23, 0x46, 0x79, 0xAC, 0xEF, 0xFF, 0xFF, 0xEC, 0xA9, + 0x76, 0x43, 0x24, 0x57, 0x9B, 0xCD, 0xFF, 0xFF, 0xFD, 0xCB, 0x98, 0x65, + 0x44, 0x46, 0x79, 0xBC, 0xEF, 0xFF, 0xEF, 0xDD, 0xBA, 0x87, 0x66, 0x56, + 0x78, 0xAB, 0xDF, 0xFF, 0xFF, 0xFE, 0xDC, 0xA9, 0x88, 0x77, 0x78, 0x9A, + 0xCD, 0xFF, 0xFF, 0xDF, 0xFD, 0xCB, 0xAA, 0x99, 0x99, 0xAB, 0xBD, 0xDF, + 0xFF, 0xFD, 0xFF, 0xDD, 0xCB, 0xBB, 0xAA, 0xBB, 0xCC, 0xFE, 0xFF, 0xFF, + 0xEF, 0xFD, 0xED, 0xDC, 0xCC, 0xCC, 0xCD, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, + 0xEF, 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, + 0xEF, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCD, 0xDD, 0xDD, 0xFD, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xEE, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x9E, 0xFF, + 0xEE, 0xED, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFD, 0xEF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xDD, 0xED, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xFE, 0xDE, 0xDC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xDD, 0xCA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDD, 0xDC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xCD, 0xED, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xED, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xED, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAC, 0xDE, 0xEC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, + 0x9B, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xEF, 0xEC, 0xDC, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFE, + 0xCE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xEC, 0xED, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCD, 0xDE, 0xEF, 0xFF, 0xCF, 0xED, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEF, 0xFF, 0xFC, 0xFE, 0xFE, 0xDD, 0xDD, + 0xDE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xCD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xEE, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xED, 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xCC, 0x9E, 0xFE, + 0xED, 0xCC, 0xCB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xED, 0xEE, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xDD, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBB, 0xCD, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xCB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDC, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEE, + 0xCD, 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xEC, 0xDD, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFF, 0xCE, 0xDD, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFD, 0xEE, 0xDD, 0xCD, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xAD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xDD, 0xDE, 0xEF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xED, 0xEE, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x9F, 0xFF, + 0xFE, 0xED, 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xED, 0xEF, 0xEE, 0xDC, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xDE, 0xEE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xED, 0xDE, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xDD, 0xDD, 0xCB, 0xA8, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDD, 0xCC, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAC, 0xCD, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9B, 0xCD, 0xDD, 0xCD, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDF, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, 0x89, 0x99, 0xAA, 0xBC, 0xDD, 0xED, + 0xCD, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xEF, 0xED, 0xED, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0xFE, 0xCD, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFD, 0xFE, 0xEE, 0xED, 0xDD, + 0xDD, 0xEE, 0xDE, 0xFE, 0xFF, 0xFE, 0x9C, 0xCD, 0xCC, 0xCC, 0xCC, 0xDD, + 0xDD, 0xDE, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xFF, 0xFF, 0xEE, 0xDD, 0xDD, 0xDD, 0xCC, 0xCD, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xEE, 0xFE, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xEF, 0xDC, 0xDD, 0xDD, 0xFF, 0xEF, 0xFF, 0xDF, 0xFF, 0xFE, 0xDD, 0xCC, + 0xBB, 0xBC, 0xCD, 0xDD, 0xDF, 0xFE, 0xFF, 0xFF, 0xDC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCC, 0xDF, 0xFF, 0xEF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x99, 0xAB, + 0xCD, 0xDF, 0xFE, 0xFF, 0xFC, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xFF, 0xFD, 0xCB, 0x97, 0x65, 0x55, 0x67, 0x89, 0xBB, 0xDF, 0xFF, + 0xFF, 0xDC, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xFF, 0xFF, 0xFD, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xFE, 0xDB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xBD, 0xFF, 0xFF, 0xED, 0xBA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xFF, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9B, 0xCF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x87, 0x76, 0x78, 0x9A, + 0xBC, 0xDF, 0xFF, 0xEF, 0xEC, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFE, 0xFF, 0xCD, 0xCB, 0xAA, 0xAA, 0xAB, 0xBC, 0xDF, 0xFF, 0xFF, + 0xEF, 0xFF, 0xDD, 0xCB, 0xBB, 0xBB, 0xDC, 0xEE, 0xFF, 0xFF, 0xFD, 0xFE, + 0xEF, 0xDD, 0xDC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDC, 0xDD, 0xDE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xDE, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xDC, 0xCC, 0xCD, 0x8F, 0xFF, + 0xEE, 0xDC, 0xDC, 0xBC, 0xCD, 0xDE, 0xDD, 0xEF, 0xED, 0xEE, 0xEE, 0xDC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCD, 0xED, 0xEE, 0xED, 0xFE, 0xDC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xCC, 0xDD, 0xED, 0xDE, 0xCC, 0xBA, 0x99, 0x88, 0x89, + 0x99, 0xAB, 0xBC, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCE, 0xDD, 0xDD, 0xCA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x99, 0xAB, + 0xCE, 0xDD, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9B, 0xBD, 0xDD, + 0xCC, 0xBA, 0x87, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCE, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xCD, 0xCC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9B, 0xCD, 0xEC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x8A, 0xBC, 0xDD, 0xCD, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, + 0x9A, 0xBD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0x9A, 0xBC, 0xDD, 0xEE, + 0xCE, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xED, 0xEE, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEE, 0xFE, 0xDE, 0xEE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDF, 0xEE, 0xFF, 0xEC, 0xEF, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFE, 0x8D, 0xDD, 0xDC, 0xDC, 0xDD, 0xDD, + 0xDD, 0xDE, 0xEF, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xAA, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xAB, 0xBB, 0x8B, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDB, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xBB, 0xCB, 0xAA, 0x99, 0x88, + 0x88, 0x99, 0x99, 0xAA, 0xBC, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBB, 0xAA, 0xA9, 0x98, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xBA, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xA9, + 0x88, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x89, 0x9A, 0xAB, 0xCB, + 0xAC, 0xBA, 0xA9, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xCB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xBC, 0xCB, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xDB, 0xDC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCD, 0xDD, 0xEC, 0x8B, 0xBB, 0xBB, 0xBB, 0xAA, 0xAA, + 0xBB, 0xBB, 0xCC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0x9B, 0xCC, + 0xBB, 0xAA, 0xAA, 0x99, 0xAA, 0xAA, 0xBB, 0xBC, 0xCB, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x99, 0x9A, 0xBB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0x9A, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBB, + 0xAB, 0xAA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xBB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCB, 0xBC, 0xBB, 0xBA, + 0xAA, 0xA9, 0x9A, 0xAA, 0xAB, 0xBB, 0xCD, 0xCB, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x8C, 0xDD, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCC, 0xDC, 0xCD, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xCB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xCB, 0xBC, 0xAA, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAB, 0xBC, 0xBB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBC, 0xBB, 0xBB, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x89, 0x9A, 0xAB, 0xCC, + 0xBC, 0xBB, 0xA9, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xCB, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDC, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xDD, 0xCC, 0xDC, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xED, 0x8B, 0xBB, 0xBB, 0xBA, 0xAA, 0xBB, + 0xBB, 0xBC, 0xCC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xED, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7E, 0xFF, + 0xFE, 0xDD, 0xDC, 0xCD, 0xDD, 0xCE, 0xEE, 0xFF, 0xFD, 0xDF, 0xDD, 0xDC, + 0xDC, 0xCC, 0xBC, 0xCC, 0xCD, 0xDD, 0xFE, 0xDD, 0xEE, 0xDC, 0xBB, 0xBB, + 0xAA, 0xBB, 0xBB, 0xDD, 0xDE, 0xED, 0xDE, 0xDD, 0xBA, 0xA9, 0x99, 0x99, + 0xAA, 0xBB, 0xCD, 0xDD, 0xDD, 0xDC, 0xBB, 0xA9, 0x88, 0x88, 0x89, 0x9A, + 0xBC, 0xDE, 0xED, 0xCD, 0xCB, 0xA9, 0x87, 0x76, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDD, 0xDC, 0xBA, 0x87, 0x65, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xDC, + 0xDD, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xBC, 0xCE, 0xDC, 0xDB, + 0xA9, 0x86, 0x54, 0x33, 0x45, 0x78, 0x9A, 0xCD, 0xDD, 0xCD, 0xCA, 0x98, + 0x75, 0x43, 0x34, 0x57, 0x89, 0xAC, 0xCE, 0xCC, 0xDB, 0xB9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xFD, 0xCD, 0xCB, 0xA9, 0x87, 0x65, 0x56, + 0x67, 0x89, 0xBC, 0xDD, 0xDC, 0xDD, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xED, 0xCD, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xDF, 0xEC, 0xED, 0xDB, 0xBA, 0xA9, 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xDE, + 0xCF, 0xDD, 0xCB, 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xDF, 0xED, 0xFE, + 0xDD, 0xCC, 0xCB, 0xCB, 0xCC, 0xCD, 0xDE, 0xEE, 0xFD, 0xDF, 0xEF, 0xFD, + 0xDD, 0xDD, 0xDC, 0xED, 0xED, 0xEE, 0xFF, 0xFD, 0xFF, 0xFD, 0xEE, 0xED, + 0xDD, 0xDF, 0xEE, 0xFE, 0xFF, 0xFF, 0x8D, 0xDD, 0xDC, 0xCD, 0xDD, 0xCD, + 0xCD, 0xDD, 0xED, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFE, 0xCF, 0xCD, 0xCC, 0xCC, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, + 0xFF, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0xCC, 0xBB, + 0xCC, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xBA, 0xAA, 0xAB, 0xBC, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xA9, 0x87, 0x66, 0x78, 0x9B, 0xCD, 0xFF, 0xFF, + 0xFF, 0xDC, 0xBA, 0x86, 0x54, 0x45, 0x78, 0xAC, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFB, 0xA8, 0x64, 0x22, 0x46, 0x89, 0xBD, 0xFF, 0xFF, 0xDF, 0xDC, 0xB9, + 0x86, 0x42, 0x24, 0x68, 0x9B, 0xDD, 0xFF, 0xFF, 0xFF, 0xCC, 0xA8, 0x75, + 0x44, 0x56, 0x8A, 0xBF, 0xFF, 0xFF, 0xFF, 0xCF, 0xCA, 0x98, 0x76, 0x66, + 0x79, 0xAD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFD, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xDC, 0xFF, 0xFF, 0xDF, 0xFF, 0xDC, 0xCA, 0xAA, 0xAA, 0xAB, 0xCF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDB, 0xCC, 0xBB, 0xCC, 0xFD, 0xDF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFD, 0xDD, 0xDC, 0xCC, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xEE, 0xDD, 0xDC, 0xCC, 0xCD, 0xDC, 0xED, 0xDF, 0xFC, 0xFF, 0xEE, 0xDC, + 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xDF, 0xFD, 0xCC, 0xBB, 0xAB, + 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xED, 0xDD, 0xDC, 0xBB, 0xAA, 0x99, 0x99, + 0x9A, 0xBC, 0xCD, 0xDD, 0xDD, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0x9A, + 0xBB, 0xCD, 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDD, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xED, + 0xCC, 0xCA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAC, 0xDE, 0xDC, 0xCB, + 0xA9, 0x87, 0x54, 0x33, 0x45, 0x78, 0x9A, 0xBC, 0xDD, 0xDC, 0xBA, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x89, 0xBC, 0xDE, 0xDC, 0xCC, 0xBA, 0x98, 0x87, 0x76, 0x77, 0x89, + 0xAB, 0xCD, 0xEE, 0xCD, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x89, 0xAB, 0xCD, + 0xDE, 0xFC, 0xED, 0xBB, 0xBA, 0xA9, 0x99, 0x9A, 0xAB, 0xBD, 0xDF, 0xFE, + 0xCD, 0xED, 0xCB, 0xBB, 0xBA, 0xAA, 0xBB, 0xCC, 0xED, 0xFF, 0xEC, 0xEE, + 0xDC, 0xCC, 0xCC, 0xBC, 0xCC, 0xDD, 0xDF, 0xEF, 0xFF, 0xCD, 0xED, 0xDD, + 0xCD, 0xCD, 0xDC, 0xDD, 0xDF, 0xEF, 0xFF, 0xFC, 0xFF, 0xFD, 0xEE, 0xED, + 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDC, 0xCD, 0xCD, 0xDD, 0xED, + 0xEE, 0xFE, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xAF, 0xFF, + 0xFD, 0xDC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xFE, 0xFF, 0xED, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEF, 0xEE, 0xED, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xFE, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDD, 0xDD, 0xDB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCA, 0x98, 0x76, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xDD, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xEC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDE, 0xCC, 0xBA, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xDF, 0xED, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x9A, 0xAB, 0xCD, 0xFF, + 0xDD, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xFF, 0xFD, 0xED, + 0xCC, 0xBB, 0xBA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEF, 0xFF, 0xDF, 0xED, 0xDC, + 0xCC, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFF, 0xFD, 0xFF, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xAD, 0xDD, 0xDD, 0xDD, 0xDC, 0xDD, + 0xDE, 0xEF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xED, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0x9F, 0xFF, + 0xFE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFD, 0xFE, 0xEE, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xDE, 0xEE, 0xDE, 0xFF, 0xDC, 0xBB, 0xAA, + 0x99, 0xAA, 0xAB, 0xCC, 0xCE, 0xDD, 0xED, 0xEC, 0xBA, 0x99, 0x88, 0x88, + 0x9A, 0xAB, 0xBC, 0xEE, 0xCD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCC, 0xED, 0xDD, 0xCA, 0x98, 0x77, 0x66, 0x66, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xDC, 0xBA, 0x97, 0x65, 0x54, 0x55, 0x66, 0x78, 0xAB, 0xBD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xCC, 0xA9, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xCB, 0xA8, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBD, 0xDD, 0xDD, 0xCB, 0xA9, 0x88, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDF, 0xDD, 0xDC, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0x9A, 0xBC, 0xCE, 0xFE, + 0xDD, 0xDC, 0xBB, 0xBA, 0xA9, 0xAA, 0xAA, 0xBC, 0xDE, 0xDF, 0xFD, 0xFD, + 0xCC, 0xCB, 0xBB, 0xBA, 0xBB, 0xBC, 0xDD, 0xEF, 0xFF, 0xDF, 0xDD, 0xDC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFD, 0xEE, 0xDE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEF, 0xEF, 0xFF, 0xFF, 0x9C, 0xCC, 0xCC, 0xCD, 0xDC, 0xED, + 0xEE, 0xEF, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, 0xED, 0xDD, 0xCC, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFE, 0xFE, 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, + 0xFE, 0xDD, 0xDD, 0xDC, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, 0xCC, + 0xBB, 0xBB, 0xCD, 0xDF, 0xFF, 0xFD, 0xFF, 0xDE, 0xDC, 0xBB, 0xAA, 0xAA, + 0xAA, 0xCC, 0xCF, 0xFF, 0xDF, 0xFF, 0xCC, 0xBA, 0x98, 0x88, 0x99, 0xAB, + 0xCD, 0xFD, 0xFF, 0xED, 0xED, 0xBA, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xDD, 0xED, 0xCB, 0x97, 0x65, 0x55, 0x67, 0x89, 0xBC, 0xFF, 0xEF, + 0xEF, 0xDB, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xEF, 0xED, 0xEC, + 0xCA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xDF, 0xFE, 0xDE, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x89, 0xCD, 0xEF, 0xFD, 0xEC, 0xCA, 0x97, 0x65, + 0x44, 0x45, 0x79, 0xAB, 0xDE, 0xDF, 0xFE, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xCD, 0xFF, 0xFE, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x78, 0x9A, + 0xBC, 0xEF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xDE, + 0xFF, 0xFF, 0xDF, 0xCC, 0xBB, 0xAA, 0xA9, 0xAB, 0xBC, 0xDD, 0xFE, 0xFF, + 0xDF, 0xEE, 0xEC, 0xCC, 0xBB, 0xBC, 0xBD, 0xED, 0xFF, 0xFF, 0xFF, 0xEF, + 0xFD, 0xDD, 0xCC, 0xDC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xCF, 0xDE, 0xEF, + 0xDE, 0xFD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFD, 0xFF, 0xEE, + 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCB, 0xCD, 0xDE, 0xFF, 0xEE, + 0xDF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xED, 0xDB, 0xCC, 0xBA, 0xAB, 0xBB, 0xBB, 0xBB, 0xBB, 0x7F, 0xFD, + 0xCD, 0xCB, 0xBA, 0xBB, 0xBB, 0xBF, 0xDC, 0xDC, 0xFD, 0xDD, 0xDC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xED, 0xCF, 0xEC, 0xDC, 0xBA, 0xAA, 0x99, + 0x98, 0x99, 0xAA, 0xBB, 0xCD, 0xDF, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x88, + 0x99, 0x9A, 0xBC, 0xCE, 0xDC, 0xDB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xCD, 0xCF, 0xCC, 0xB9, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAA, + 0xCC, 0xDC, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAC, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDB, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAA, 0xCC, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xDB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xBB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBD, 0xCB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x89, 0xAC, 0xCF, 0xCC, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xCC, 0xDB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCC, 0xDD, + 0xDF, 0xCB, 0xAA, 0xA9, 0x98, 0x99, 0x9A, 0xAB, 0xBD, 0xDF, 0xFC, 0xEE, + 0xDB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBD, 0xDE, 0xFF, 0xCF, 0xDD, 0xDD, + 0xBC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xDD, 0xDD, 0xED, 0xCD, 0xCD, + 0xDC, 0xCC, 0xCE, 0xDF, 0xFF, 0xFF, 0x8D, 0xBB, 0xED, 0xCC, 0xCB, 0xCD, + 0xCF, 0xDD, 0xDF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCB, 0xBA, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xAA, 0xBB, 0x7C, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xDC, 0xCC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xCB, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBC, 0xDC, 0xBB, 0xAA, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xAB, 0xB9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAB, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xB9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xB9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xBA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAC, 0xBA, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x78, 0x88, 0x9A, 0xAB, 0xCC, + 0xBB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAB, 0xCD, 0xCB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCC, 0xDE, 0xBC, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xCE, 0xDB, 0xDE, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xED, 0x9C, 0xCB, 0xBB, 0xAB, 0xAA, 0xBA, + 0xBB, 0xBB, 0xCD, 0xDD, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0x9C, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0xDC, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBB, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xAB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBB, 0xBB, + 0xAA, 0x99, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xDC, 0xBC, 0xBB, 0xAA, + 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBC, 0xCD, 0xDB, 0xCD, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDD, 0x9C, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xCC, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCC, 0xCB, 0xBA, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xBB, 0xBB, 0x8C, 0xCD, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0xCC, 0xBA, 0xBA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xCC, 0xCC, 0xCB, 0xA9, 0x99, 0x88, + 0x88, 0x89, 0x99, 0x9A, 0xBB, 0xCB, 0xBB, 0xAA, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAA, 0xBC, 0xBB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xA9, 0x88, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x56, 0x67, 0x79, 0x9A, 0xBB, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBC, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x9A, 0xBB, 0xCB, + 0xAB, 0xBA, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xCB, 0xDB, + 0xAA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xDC, 0xBC, 0xBB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xDB, 0xCC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xCE, 0xDD, 0x7B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xCB, 0xCC, 0xCC, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xDC, 0xFE, 0xCD, 0xCC, 0xDD, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xFF, 0xDF, 0xFF, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDC, + 0xBD, 0xDF, 0xFD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDC, 0xCC, 0xBB, + 0xCC, 0xFF, 0xDF, 0xFF, 0xFD, 0xFF, 0xFD, 0xCB, 0xAA, 0xAA, 0xAC, 0xBB, + 0xBE, 0xDF, 0xFF, 0xEF, 0xDF, 0xDC, 0xA9, 0x98, 0x89, 0xAA, 0xCB, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCC, 0xA9, 0x86, 0x66, 0x78, 0xAB, 0xCD, 0xFF, 0xFD, + 0xFF, 0xFD, 0xBA, 0x86, 0x54, 0x45, 0x79, 0xAC, 0xCF, 0xDF, 0xFF, 0xFF, + 0xCC, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xBE, 0xDF, 0xFF, 0xFF, 0xFD, 0xCA, + 0x86, 0x42, 0x24, 0x68, 0xAB, 0xCF, 0xFF, 0xFF, 0xFF, 0xDC, 0xA9, 0x75, + 0x44, 0x56, 0x8A, 0xCD, 0xDF, 0xFE, 0xFF, 0xFD, 0xDB, 0x98, 0x76, 0x66, + 0x89, 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBA, 0x99, 0x88, 0x89, 0xBB, + 0xDD, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBA, 0xA9, 0x9A, 0xBC, 0xDD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xBC, 0xBB, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDC, 0xFD, 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xCD, 0xDF, 0xFD, 0xEE, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xDF, 0xFF, 0xFD, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, + 0xFF, 0xDF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xCC, 0xCF, + 0xDD, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xCF, 0xDD, 0xBB, 0xBA, 0xAC, 0xCB, + 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x99, 0x89, 0xAA, 0xAF, 0xFF, + 0xFF, 0xFF, 0xCF, 0xFC, 0xBA, 0x87, 0x66, 0x79, 0xAB, 0xDD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCB, 0x97, 0x54, 0x45, 0x79, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xB9, 0x64, 0x22, 0x46, 0x8A, 0xDD, 0xDD, 0xFF, 0xFF, 0xFD, 0xDC, + 0x96, 0x42, 0x23, 0x69, 0xBB, 0xCF, 0xFF, 0xFF, 0xFF, 0xFC, 0xB9, 0x75, + 0x44, 0x57, 0x9B, 0xBF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xA9, 0x76, 0x66, + 0x89, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0xA9, 0x88, 0x99, 0xAD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xAA, 0xAB, 0xCC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xDB, 0xBB, 0xBF, 0xCF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDD, 0xFD, 0xFD, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDC, 0xDC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xDF, 0xFD, 0xFF, 0xFA, 0xBD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x89, 0x99, 0x98, 0x88, 0x88, 0x88, 0x88, 0x98, 0x98, 0x9A, 0x6A, 0xCB, + 0x9A, 0xA9, 0x99, 0x99, 0xAA, 0x9A, 0xAB, 0xAA, 0xDA, 0x9A, 0xA9, 0x89, + 0x99, 0x89, 0x99, 0x89, 0x8A, 0x99, 0xAA, 0x9A, 0xAA, 0x99, 0x88, 0x88, + 0x88, 0x88, 0x89, 0xA9, 0xAA, 0xAA, 0x89, 0xA9, 0x98, 0x88, 0x88, 0x88, + 0x88, 0x89, 0x9A, 0xB9, 0xA9, 0xA9, 0x98, 0x78, 0x77, 0x77, 0x77, 0x88, + 0x89, 0x9A, 0xA9, 0x89, 0x98, 0x87, 0x76, 0x76, 0x77, 0x77, 0x88, 0x99, + 0x9A, 0xA8, 0x98, 0x88, 0x76, 0x66, 0x66, 0x77, 0x77, 0x88, 0x89, 0x98, + 0x89, 0x98, 0x87, 0x76, 0x66, 0x66, 0x67, 0x78, 0x88, 0x9B, 0xA8, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x66, 0x77, 0x88, 0x98, 0xA8, 0x89, 0x88, 0x87, + 0x76, 0x65, 0x56, 0x67, 0x77, 0x88, 0x99, 0x98, 0x99, 0x78, 0x77, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x8A, 0x99, 0x89, 0x98, 0x78, 0x77, 0x66, 0x66, + 0x67, 0x77, 0x88, 0xAB, 0x98, 0x99, 0x89, 0x87, 0x77, 0x76, 0x67, 0x77, + 0x88, 0x89, 0xA9, 0x9A, 0x9A, 0x98, 0x77, 0x77, 0x77, 0x77, 0x78, 0x89, + 0x9B, 0x98, 0xA9, 0x99, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x9A, 0xA9, + 0x8A, 0x99, 0x99, 0x89, 0x88, 0x88, 0x88, 0x99, 0x8A, 0xAA, 0xA9, 0xAB, + 0xAA, 0x98, 0x88, 0x89, 0x88, 0x89, 0x9A, 0xBA, 0xA9, 0xAC, 0xBA, 0xB9, + 0xAA, 0x99, 0x99, 0x9A, 0x99, 0xAA, 0xAD, 0xA9, 0xBA, 0xAB, 0xAB, 0xA9, + 0x9A, 0x9A, 0xBA, 0xAA, 0x9C, 0xBB, 0x8B, 0xA9, 0xA8, 0x99, 0x98, 0x88, + 0x99, 0x9A, 0xAA, 0xAB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xDD, 0xCC, 0xCC, 0xDC, 0xDD, 0xED, 0xEF, 0xDF, 0xFF, + 0xED, 0xDC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFE, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFF, 0xFD, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xFF, 0xFD, 0xCB, 0xA9, 0x98, 0x87, 0x88, + 0x89, 0x9A, 0xBC, 0xFF, 0xFE, 0xDC, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDF, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xEE, 0xBB, 0x98, 0x76, 0x65, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDF, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x45, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xA9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xEC, 0xCA, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDF, 0xDC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xDF, 0xFF, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xFF, + 0xFE, 0xCB, 0xBA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xFF, 0xFF, 0xFD, + 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xFF, 0xFF, 0xFF, 0xEF, 0xDD, + 0xCB, 0xBB, 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDD, + 0xDD, 0xDE, 0xDE, 0xFF, 0xFF, 0xFF, 0xCF, 0xFE, 0xFE, 0xFE, 0xEF, 0xDD, + 0xDF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0x99, 0xA9, 0x89, 0x89, 0x99, 0x98, 0x99, 0xBB, 0x6B, 0xAB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xBA, 0xAB, 0xBE, 0xFB, 0x9B, 0xAA, 0x99, + 0x99, 0x99, 0x99, 0xA9, 0xAC, 0x9B, 0xBA, 0xC9, 0xB9, 0xA9, 0x99, 0x88, + 0x89, 0x88, 0x89, 0xAA, 0xAA, 0xBA, 0x99, 0x99, 0x88, 0x88, 0x77, 0x87, + 0x88, 0x89, 0xAA, 0xAA, 0xA9, 0x9A, 0x88, 0x87, 0x77, 0x77, 0x78, 0x88, + 0x99, 0xAA, 0xA9, 0x9A, 0x99, 0x87, 0x76, 0x66, 0x67, 0x77, 0x88, 0x99, + 0xBB, 0xA9, 0x99, 0x88, 0x77, 0x66, 0x66, 0x66, 0x78, 0x88, 0x99, 0xB9, + 0x9A, 0x98, 0x87, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x77, 0x78, 0x8A, 0xA9, 0x99, 0x99, 0x87, + 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xA8, 0x99, 0x98, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x99, 0xA9, 0x99, 0x98, 0x98, 0x77, 0x66, 0x66, + 0x67, 0x78, 0x98, 0x9B, 0xA9, 0x99, 0x98, 0x87, 0x77, 0x66, 0x77, 0x77, + 0x89, 0x99, 0xCA, 0x9A, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0x99, 0xBA, 0x99, 0x88, 0x88, 0x87, 0x88, 0x88, 0x89, 0x9B, 0xB9, + 0xAB, 0xA9, 0xAA, 0x88, 0x88, 0x88, 0x88, 0x9A, 0xBA, 0xAB, 0xA9, 0xEA, + 0xAA, 0x9A, 0xA9, 0x9A, 0x89, 0x99, 0x9A, 0xAC, 0xAB, 0xAC, 0xDA, 0xBA, + 0xAA, 0x9A, 0x99, 0xAA, 0xAB, 0xBA, 0xCC, 0xAA, 0xFB, 0xDB, 0xBA, 0xAA, + 0xAA, 0xBA, 0xBB, 0xBB, 0xFC, 0xFB, 0x7A, 0x99, 0x99, 0x99, 0x99, 0x99, + 0x99, 0x9A, 0xAA, 0xAB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xA9, 0xAA, 0xBB, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x98, 0x77, 0x89, 0xAF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xA8, 0x54, 0x46, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDA, 0x74, 0x12, 0x47, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA7, 0x42, 0x24, 0x79, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x86, + 0x44, 0x57, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB9, 0x87, 0x77, + 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBA, 0x9A, 0xAB, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x8A, 0x98, 0x88, 0x87, 0x77, 0xF7, 0x6F, 0x88, 0x8F, 0xAA, 0x59, 0xFA, + 0xAF, 0xAF, 0x8A, 0x87, 0x8A, 0xA8, 0xFA, 0xA9, 0xF9, 0x9A, 0xAF, 0x98, + 0x9A, 0x79, 0x89, 0x78, 0x9A, 0xFA, 0xFF, 0xAC, 0x88, 0x8F, 0x87, 0x88, + 0xA8, 0x89, 0x9A, 0x87, 0xAF, 0xFA, 0x7A, 0xA9, 0x87, 0x78, 0x77, 0x98, + 0x78, 0x89, 0xAA, 0xFA, 0xA8, 0x98, 0x99, 0x87, 0x78, 0x87, 0x77, 0x87, + 0x87, 0xFA, 0xE8, 0x8B, 0x97, 0x76, 0x88, 0x77, 0x67, 0x77, 0x78, 0x78, + 0x8A, 0x87, 0xA9, 0x8F, 0x77, 0x77, 0x67, 0x97, 0x88, 0x78, 0x99, 0xA8, + 0x79, 0x89, 0x77, 0x76, 0x66, 0x76, 0x77, 0x77, 0x8F, 0x89, 0x98, 0xF9, + 0x88, 0x97, 0x66, 0x57, 0x67, 0x78, 0x77, 0xA9, 0x88, 0x78, 0x87, 0x87, + 0x66, 0x66, 0x66, 0x67, 0x68, 0x97, 0xF9, 0x88, 0xA8, 0x78, 0x87, 0x76, + 0x66, 0x77, 0x68, 0x77, 0x88, 0x89, 0x99, 0xA8, 0x78, 0x77, 0x77, 0x76, + 0x67, 0x76, 0x77, 0x89, 0xA9, 0x8A, 0x87, 0x87, 0x77, 0x68, 0x76, 0x76, + 0x88, 0x9A, 0x9A, 0xAA, 0xA7, 0x97, 0x87, 0x87, 0x87, 0x77, 0x99, 0x77, + 0x9A, 0x87, 0x9A, 0x99, 0x79, 0x79, 0x76, 0x87, 0x98, 0x99, 0xA8, 0x88, + 0x98, 0x9A, 0xA9, 0x99, 0x97, 0x98, 0x8A, 0x98, 0x9A, 0xFF, 0xA8, 0xFA, + 0x7F, 0x8A, 0x8F, 0x98, 0x8A, 0xA8, 0xFF, 0xF9, 0xA8, 0xAF, 0x99, 0x99, + 0x88, 0x99, 0xAA, 0x98, 0x9A, 0xAA, 0xAF, 0xAA, 0xFA, 0xF9, 0x9A, 0xFA, + 0xF9, 0x8A, 0xA8, 0x98, 0xAF, 0xA9, 0x9F, 0xFA, 0x89, 0x87, 0x78, 0x98, + 0x87, 0x8A, 0x87, 0x99, 0x90, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xBF, 0xFF, 0xFF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xBF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x88, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0x65, 0x57, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x84, 0x12, 0x58, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF8, 0x52, 0x14, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x96, + 0x54, 0x68, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xA8, 0x89, + 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFB, 0xFF, 0xFF, 0xFF, 0xBF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xEF, 0xFE, 0xEF, 0xFF, 0xFE, 0xEE, 0xE5, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, + 0xEE, 0xEE, 0x4E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0x5F, 0xFF, + 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, 0x5E, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0xE5, + 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0x55, 0xF5, 0x5F, 0xF5, 0xFF, 0x5F, 0x5F, + 0xFF, 0xFF, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF5, 0xFF, 0xF5, 0xFF, 0x5F, 0x4F, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xE3, 0xE5, 0xEE, 0x5E, 0xEE, 0xEE, 0xEE, 0xE5, 0x4E, + 0xEE, 0x5E, 0x5E, 0xE5, 0x5E, 0x5E, 0x55, 0xEE, 0xEE, 0x54, 0xEE, 0xE5, + 0x5E, 0xE5, 0xE6, 0x5E, 0xEE, 0xEE, 0xEE, 0xEF, 0xF5, 0xFF, 0xF5, 0xFF, + 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xF5, 0xFF, 0x5F, 0xFF, + 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0x5F, 0xF5, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0x5F, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x78, 0xF6, 0x66, 0x68, 0x76, 0x67, 0x67, 0x98, 0x78, 0x7F, 0x68, 0x98, + 0x9F, 0xF8, 0xF7, 0xFE, 0x8F, 0xFF, 0x9F, 0xFF, 0x9F, 0x88, 0x7F, 0x88, + 0x9F, 0x79, 0x9F, 0xFF, 0x8F, 0x9F, 0xF9, 0x96, 0x99, 0x97, 0x78, 0x67, + 0xF7, 0x98, 0xFF, 0x79, 0x99, 0xF8, 0x77, 0xF8, 0x89, 0x97, 0x78, 0x89, + 0xF7, 0x8F, 0xFF, 0xFF, 0x78, 0x99, 0x79, 0x97, 0x97, 0x77, 0x99, 0x7F, + 0x79, 0x99, 0x98, 0x77, 0x9F, 0x67, 0x67, 0x67, 0x78, 0x98, 0x9F, 0x99, + 0x89, 0xF6, 0x9F, 0x79, 0x78, 0x76, 0x66, 0xF8, 0x78, 0x89, 0x78, 0xF8, + 0x87, 0x88, 0x99, 0x87, 0x77, 0x69, 0x79, 0x78, 0xF7, 0x9F, 0x77, 0xF9, + 0x99, 0x76, 0x77, 0x77, 0x68, 0x87, 0x78, 0x9F, 0x97, 0x88, 0x78, 0x89, + 0x97, 0x76, 0x77, 0x77, 0x89, 0x8F, 0x8F, 0x67, 0x89, 0x98, 0x89, 0x78, + 0x77, 0x87, 0x78, 0x79, 0x78, 0x96, 0x68, 0x9F, 0xA8, 0x97, 0x78, 0x78, + 0x8F, 0x89, 0x79, 0x8F, 0x67, 0xFF, 0x8F, 0x99, 0x77, 0x66, 0x66, 0x76, + 0x86, 0xF8, 0xF6, 0x99, 0x9F, 0x7F, 0x89, 0x97, 0x79, 0x88, 0x6F, 0x88, + 0x89, 0x68, 0xFF, 0xFF, 0xF9, 0x98, 0x89, 0xF8, 0xFF, 0x98, 0x9F, 0xF7, + 0x78, 0x79, 0xF9, 0x77, 0x89, 0xF8, 0x97, 0x89, 0xF9, 0x98, 0x77, 0x9F, + 0x9F, 0x89, 0x9F, 0x99, 0x98, 0x9F, 0x99, 0x9F, 0x98, 0x89, 0x98, 0xFF, + 0x9F, 0xF8, 0xF9, 0x88, 0x9F, 0x7F, 0xF9, 0x67, 0xFF, 0x99, 0x98, 0xF9, + 0xFF, 0x89, 0x9F, 0xFF, 0x9F, 0xF9, 0x59, 0x77, 0x98, 0x68, 0x96, 0x77, + 0x68, 0x89, 0xF7, 0x6F, 0x60, 0x00, 0x00, 0x00, + }, + { + 0x68, 0x89, 0x78, 0x77, 0x67, 0x88, 0x88, 0xFF, 0x79, 0x99, 0x69, 0xF9, + 0xF9, 0x88, 0x87, 0x79, 0x8F, 0xF9, 0xF8, 0xF9, 0xF7, 0x8F, 0x98, 0x78, + 0x79, 0xF9, 0xF8, 0x88, 0x79, 0x7F, 0xF9, 0x97, 0xFF, 0x8F, 0x98, 0x78, + 0x77, 0x67, 0xF8, 0xF9, 0xFF, 0xF9, 0x78, 0xF8, 0x88, 0x87, 0x88, 0x77, + 0x98, 0xF7, 0x98, 0xFF, 0x98, 0x9F, 0xF8, 0x98, 0x87, 0x76, 0x79, 0x97, + 0x78, 0x89, 0x8C, 0x77, 0x88, 0x78, 0x77, 0x77, 0x88, 0x77, 0x78, 0x79, + 0x9F, 0x88, 0x79, 0x77, 0x77, 0x77, 0x67, 0x77, 0x77, 0x8F, 0x99, 0x97, + 0x87, 0x77, 0x78, 0x87, 0x78, 0x76, 0x77, 0x78, 0x9F, 0x99, 0xF7, 0x77, + 0x98, 0x76, 0x76, 0x77, 0x68, 0x7F, 0x78, 0xFF, 0xF9, 0x78, 0x88, 0x87, + 0x88, 0x76, 0x67, 0x88, 0x79, 0x78, 0xF9, 0x87, 0x89, 0x97, 0x77, 0x68, + 0x67, 0x77, 0x77, 0x77, 0x8E, 0x78, 0x78, 0x8A, 0x88, 0x77, 0x87, 0x77, + 0x67, 0x88, 0x88, 0x8F, 0x87, 0x89, 0x88, 0x77, 0x76, 0x77, 0x79, 0x77, + 0x77, 0x8F, 0x88, 0x79, 0xF8, 0x77, 0x78, 0x77, 0x88, 0x77, 0x78, 0x98, + 0x89, 0x89, 0xFF, 0xF8, 0x88, 0x99, 0x77, 0x98, 0x78, 0x87, 0x99, 0x99, + 0x98, 0xF8, 0x98, 0xFF, 0xFF, 0x79, 0x88, 0x77, 0x79, 0x8F, 0x88, 0xF8, + 0x88, 0xFF, 0x88, 0x78, 0x99, 0x9F, 0x88, 0xF9, 0xF8, 0x88, 0x99, 0xB9, + 0xF7, 0x88, 0x99, 0xF9, 0x99, 0x9F, 0xFF, 0x99, 0xFF, 0x8F, 0x98, 0x8F, + 0x89, 0x99, 0xF8, 0x99, 0x8F, 0xF9, 0x5F, 0x89, 0x77, 0x87, 0x99, 0x78, + 0x88, 0x77, 0xF8, 0x8F, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x5E, 0xDE, 0xE5, 0xDE, 0xEE, 0xED, 0xDD, 0xDE, 0xEE, 0xEE, 0x4E, 0xED, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, + 0xDD, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xDD, + 0x5D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD5, 0x45, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xE5, 0xEE, 0xEE, 0xE5, 0xEE, 0xEE, + 0x5E, 0xEE, 0xEE, 0xEE, 0xE5, 0xE5, 0xEE, 0xE5, 0x54, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0x45, 0xEE, 0xEE, 0x55, 0xEE, 0xEE, 0xE5, 0xED, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x5D, 0xDD, 0xDD, 0xDD, 0x55, 0xDD, 0xDD, + 0x55, 0x5D, 0x4D, 0xDD, 0xDD, 0x45, 0xDD, 0x5D, 0xDD, 0xDD, 0xDD, 0xDD, + 0x54, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0x5E, 0xEE, 0x5E, 0xEE, + 0xEE, 0x5E, 0xEE, 0xEE, 0xE5, 0xEE, 0xEE, 0xEE, 0x4E, 0xEE, 0x4E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x5E, 0xEE, 0xE4, 0xE5, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0xEE, 0xEE, 0xEE, 0x5E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x55, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, + 0xEE, 0xED, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0xED, 0xED, + 0xEE, 0xEE, 0xEE, 0x5E, 0xEE, 0xEE, 0xED, 0xED, 0xEE, 0xE5, 0xEE, 0xEE, + 0xED, 0xED, 0xED, 0xEE, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xF9, 0xF8, 0xF9, 0x4F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0x64, 0x68, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x85, 0x12, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x52, 0x14, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, + 0x54, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xF7, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x7F, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xF6, + 0xF6, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF7, 0xF6, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0x66, 0xF6, + 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x67, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFD, 0xBF, 0xF7, 0xF7, 0x6F, 0x66, 0x6F, 0x66, 0xF6, 0xFF, + 0xFF, 0xF6, 0xF6, 0xFF, 0x75, 0x76, 0xF5, 0x66, 0x66, 0x66, 0xFF, 0xFF, + 0xF6, 0xFF, 0xFF, 0xF5, 0x57, 0x66, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xF6, + 0xFF, 0x56, 0x56, 0x75, 0x77, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xF7, 0xF6, + 0xF6, 0xF6, 0x44, 0xF5, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, + 0x56, 0x75, 0x56, 0xF6, 0xFF, 0xFD, 0xC6, 0xAF, 0xF6, 0x6F, 0xFF, 0x55, + 0x57, 0x5F, 0x7F, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x65, 0x6F, 0xFF, 0x68, + 0x7F, 0xFF, 0xFF, 0x6F, 0xFF, 0xF6, 0xF6, 0x5F, 0x65, 0x6F, 0x6F, 0xFF, + 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF6, 0x6F, 0xFF, 0xFF, 0xFF, + 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xFF, 0xFF, + 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x7F, 0x7F, 0xFF, 0xFF, 0x7F, + 0xFF, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFD, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x12, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x61, 0x15, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + }, + { + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xEE, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xED, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x5E, 0xED, + 0xD5, 0x55, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xE5, 0xE5, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0xEE, 0xE5, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0x5E, 0x5E, 0xEE, 0x55, 0x54, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, + 0xDD, 0xDD, 0xD5, 0x5D, 0x44, 0x5D, 0xDD, 0xDD, 0xDD, 0xDD, 0x5D, 0xD5, + 0xD5, 0x5D, 0xDD, 0xD3, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x5D, + 0xD4, 0x35, 0x5D, 0xDD, 0xDD, 0xDD, 0xDD, 0xD5, 0x5E, 0xE4, 0x54, 0x53, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0xEE, 0xEE, 0x5E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, 0xEE, 0x5E, 0xEE, 0xE5, 0x5E, 0xEE, 0x5E, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0x5E, 0xEE, 0xE4, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xE5, 0xEE, 0xEE, 0xED, 0xEE, 0xED, 0xDD, 0xED, 0xED, 0xED, 0xED, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, 0xEE, 0xEE, 0xED, + 0xEE, 0xED, 0xED, 0xEE, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xCD, 0xCC, 0xCC, 0xDC, 0xDD, 0xFF, 0xFF, 0xFF, 0xDD, 0xEF, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xDF, 0xEF, 0xFF, 0xFF, 0xDF, 0xFD, 0xDC, + 0xBB, 0xBB, 0xAA, 0xBB, 0xCD, 0xDF, 0xFF, 0xFD, 0xED, 0xCC, 0xBB, 0xA9, + 0x99, 0x99, 0xAA, 0xBC, 0xDF, 0xFF, 0xCD, 0xCC, 0xBA, 0x99, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDF, 0xEC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xEE, 0xDD, 0xBA, 0xA8, 0x87, 0x76, 0x66, 0x67, 0x88, 0x9A, + 0xCD, 0xDD, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x67, 0x89, 0xAB, 0xCD, + 0xCC, 0xA9, 0x87, 0x76, 0x55, 0x55, 0x56, 0x77, 0x89, 0xBD, 0xDC, 0xCB, + 0x98, 0x76, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xCC, 0xA9, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x67, 0x89, 0xAD, 0xCD, 0xCA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x66, 0x78, 0x9A, 0xCC, 0xDC, 0xB9, 0x87, 0x66, 0x55, 0x55, + 0x56, 0x77, 0x8A, 0xBC, 0xDD, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x67, + 0x89, 0xAB, 0xCD, 0xEC, 0xCA, 0x98, 0x87, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xDE, 0xDC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x89, 0x9A, 0xBC, 0xDC, + 0xFE, 0xEC, 0xBA, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xBC, 0xCD, 0xDF, 0xFE, + 0xDC, 0xBB, 0xA9, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xEE, 0xFF, 0xFF, 0xDC, + 0xCB, 0xBA, 0xAB, 0xBB, 0xCC, 0xDD, 0xDE, 0xDF, 0xFF, 0xFF, 0xED, 0xCC, + 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xED, 0xDF, 0xFF, 0xDF, 0xDD, 0xDD, 0xDC, + 0xCC, 0xCD, 0xED, 0xCE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xEE, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xED, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x4E, + 0xEE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xD4, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0x4E, 0x4E, 0x4E, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x4E, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xE4, 0xE3, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0x4D, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0x44, 0x4D, 0x4D, 0xDD, 0xDD, 0xDD, 0xDD, 0x4E, 0xE4, 0xEE, 0x3E, 0x4E, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE3, 0xEE, 0xE5, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE4, 0xEE, 0xEE, 0xEE, 0x4E, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x4E, 0x3E, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE4, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0x4E, 0xEE, 0x4E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, 0xED, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x9C, 0xBB, 0xAA, 0xAA, 0xAA, 0x9A, 0xAA, 0xAB, 0xBC, 0xCD, 0xBB, 0xCC, + 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xAB, 0xCD, 0xDB, 0xCB, 0xAA, 0x99, 0x99, + 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCC, 0xAB, 0xAA, 0xA9, 0x98, 0x88, 0x88, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xBA, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, + 0x88, 0x76, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, + 0x66, 0x65, 0x55, 0x56, 0x67, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x66, 0x78, 0x99, 0xAA, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xAB, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xAB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xBB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xCC, + 0xBA, 0x99, 0x98, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xDD, 0xCC, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBD, 0xDD, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCB, 0xBC, 0xCB, 0xBA, 0xAA, 0xA9, 0x9A, + 0xAA, 0xAA, 0xBA, 0xBC, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCC, 0xBB, 0xCC, + 0xCA, 0xAA, 0xAA, 0x9A, 0xA9, 0xAA, 0xBB, 0xBD, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x98, 0x99, 0xA9, 0xAB, 0xBB, 0xCB, 0xBA, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x99, 0xAB, 0xBB, 0xAA, 0xA9, 0x98, 0x88, 0x88, 0x77, + 0x88, 0x88, 0x9A, 0xAB, 0xAA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x88, 0x99, 0xBA, 0x9A, 0x99, 0x88, 0x77, 0x76, 0x66, 0x77, 0x77, 0x89, + 0x9A, 0xA9, 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, 0x78, 0x89, 0xAA, + 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0x99, 0x99, + 0x88, 0x76, 0x66, 0x66, 0x66, 0x67, 0x77, 0x89, 0x99, 0x99, 0x98, 0x77, + 0x66, 0x66, 0x56, 0x66, 0x67, 0x78, 0x99, 0x99, 0xA9, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x66, 0x77, 0x89, 0xA9, 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x99, 0x99, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xA9, 0xAA, 0x99, 0x88, 0x77, 0x76, 0x67, 0x77, 0x78, 0x89, + 0x9A, 0x9A, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, 0x88, 0x9A, 0xB9, + 0xAB, 0xAA, 0x99, 0x88, 0x87, 0x77, 0x88, 0x89, 0x99, 0xAB, 0xAB, 0xCA, + 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x99, 0xAB, 0xBB, 0xBB, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xBC, 0xCC, 0xCB, 0xAA, 0x9A, + 0x99, 0x9A, 0x9A, 0xAB, 0xBC, 0xCC, 0xBC, 0xCA, 0xAA, 0xA9, 0x99, 0x99, + 0x99, 0x9A, 0xAA, 0xAB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBB, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0xCC, 0xBC, 0xBA, 0xAA, + 0x99, 0x99, 0x89, 0x99, 0x99, 0xAA, 0xBC, 0xBA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xAA, 0xA9, 0x98, 0x88, 0x87, 0x77, + 0x88, 0x88, 0x99, 0xAA, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, 0x77, 0x77, + 0x88, 0x99, 0xAA, 0x9A, 0x99, 0x88, 0x77, 0x77, 0x67, 0x77, 0x77, 0x89, + 0x9A, 0x99, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, 0x78, 0x89, 0xA9, + 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x78, 0x99, 0x99, 0x98, + 0x87, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x89, 0x99, 0x99, 0x88, 0x77, + 0x76, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0x99, 0x99, 0x87, 0x77, 0x66, + 0x66, 0x66, 0x67, 0x77, 0x89, 0x99, 0x99, 0x98, 0x77, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x99, 0x99, 0x99, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xA9, 0x9A, 0x98, 0x87, 0x77, 0x77, 0x67, 0x77, 0x78, 0x89, + 0x9A, 0x9A, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, 0x88, 0x99, 0xA9, + 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, 0x88, 0x88, 0x99, 0xAB, 0xAA, 0xBA, + 0xA9, 0x98, 0x88, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBA, 0xBB, 0xBA, 0xA9, + 0x99, 0x99, 0x89, 0x99, 0x99, 0xAA, 0xBB, 0xBC, 0xCB, 0xBB, 0xAA, 0xA9, + 0x99, 0x99, 0xAA, 0xAA, 0xBC, 0xCB, 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x99, + 0x99, 0x9A, 0xAA, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9C, 0xBA, 0xAA, 0x9A, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCB, 0xAB, 0xCC, + 0xBA, 0xAA, 0xA9, 0x99, 0xA9, 0xAA, 0xAA, 0xBC, 0xCC, 0xAC, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xBB, 0xCB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, + 0x78, 0x88, 0x99, 0xAA, 0xAA, 0xBA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xAA, 0x9A, 0x99, 0x88, 0x77, 0x76, 0x67, 0x77, 0x77, 0x88, + 0x9A, 0x99, 0x99, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x89, 0xA9, + 0x99, 0x98, 0x77, 0x76, 0x66, 0x66, 0x66, 0x67, 0x88, 0x89, 0x99, 0x98, + 0x87, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0xA9, 0x99, 0x98, 0x87, + 0x66, 0x66, 0x66, 0x66, 0x67, 0x78, 0x89, 0x99, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x77, 0x89, 0x99, 0x9A, 0x88, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0x99, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xA9, 0xAA, 0x99, 0x87, 0x77, 0x77, 0x67, 0x77, 0x77, 0x89, + 0x9A, 0xAA, 0xBA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x99, 0xAA, + 0xAB, 0xAA, 0x98, 0x88, 0x87, 0x77, 0x88, 0x89, 0x9A, 0xAB, 0xAA, 0xBA, + 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAA, 0xBB, 0xCC, 0xBA, 0xA9, + 0xA9, 0x99, 0x98, 0x99, 0x99, 0xAB, 0xAB, 0xAC, 0xCC, 0xBA, 0xAA, 0xA9, + 0x99, 0x9A, 0x9A, 0xBB, 0xBC, 0xCB, 0xBC, 0xBB, 0xAA, 0xA9, 0x99, 0x99, + 0x9A, 0x9A, 0xAA, 0xBB, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xCB, 0xDC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDD, 0xCC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xDB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBC, 0xCC, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x89, 0x9A, 0xAB, 0xBA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0xA9, + 0x88, 0x76, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x87, + 0x66, 0x65, 0x55, 0x66, 0x67, 0x88, 0x9A, 0xA9, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xB9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, + 0x78, 0x99, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0x9A, 0xAA, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xBA, + 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xAC, 0xCB, + 0xBA, 0x99, 0x98, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBB, 0xDC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xDD, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDB, 0xBD, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, + 0x9A, 0xAA, 0xBB, 0xBC, 0x90, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xDD, 0xCC, 0xCC, 0xCD, 0xDE, 0xED, 0xFF, 0xFF, 0xCF, 0xFF, + 0xEE, 0xDD, 0xDC, 0xCD, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFF, 0xFE, 0xDC, 0xBB, 0xAA, + 0xA9, 0xAA, 0xAB, 0xCD, 0xEF, 0xFF, 0xDD, 0xCC, 0xBA, 0x99, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xFD, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x78, 0x89, + 0xAB, 0xCE, 0xFE, 0xDD, 0xCA, 0x98, 0x87, 0x76, 0x66, 0x77, 0x89, 0xAB, + 0xDF, 0xFD, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x77, 0x9A, 0xBC, 0xEE, + 0xDC, 0xBA, 0x97, 0x76, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xED, 0xCB, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xDC, 0xB9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xDD, 0xCB, 0xA8, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xDD, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCD, 0xDE, 0xDC, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xFD, 0xDB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x99, 0xAC, + 0xCD, 0xDF, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEF, + 0xFF, 0xFD, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xEF, 0xDF, 0xFE, + 0xED, 0xCB, 0xBA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDE, 0xFF, 0xFF, 0xFF, 0xFD, + 0xDC, 0xBC, 0xCB, 0xCC, 0xCD, 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xEE, + 0xDD, 0xDE, 0xDE, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xEE, 0xED, 0xDD, + 0xEE, 0xDF, 0xEE, 0xFE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xCC, 0xCC, 0xCB, 0xCC, 0xCC, 0xEF, 0xFF, 0xDF, 0xCD, 0xFF, + 0xCD, 0xCC, 0xCC, 0xCC, 0xBD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDC, 0xBB, + 0xBB, 0xAB, 0xBA, 0xBC, 0xDC, 0xDF, 0xFF, 0xFD, 0xDC, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xBB, 0xBC, 0xFF, 0xFF, 0xCC, 0xDB, 0xA9, 0x99, 0x88, 0x88, + 0x89, 0xAB, 0xCC, 0xDF, 0xFC, 0xDC, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xFF, 0xBC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCF, 0xFC, 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xCF, + 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xFC, 0xBB, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0xA8, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xEC, 0xBA, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xCD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xDD, 0xDB, 0x99, 0x87, 0x77, 0x77, 0x77, 0x89, 0xAB, + 0xBC, 0xCF, 0xFD, 0xBB, 0xA9, 0x88, 0x88, 0x88, 0x89, 0x9B, 0xCC, 0xFC, + 0xFF, 0xDD, 0xBA, 0x9A, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xFD, 0xDF, 0xFD, + 0xFD, 0xCB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCF, 0xFD, 0xFF, 0xFF, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDD, 0xDF, 0xDF, 0xFF, 0xFF, 0xFD, 0xFD, + 0xCC, 0xCC, 0xFC, 0xCD, 0xFE, 0xFE, 0xDF, 0xFF, 0xFD, 0xDD, 0xFC, 0xDC, + 0xDD, 0xCC, 0xCE, 0xFD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xDD, 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFD, 0xFE, + 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0xFF, 0xFF, 0xFF, 0xEF, 0xDD, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xDF, 0xFF, 0xFD, 0xED, 0xCB, 0xAA, 0xA9, + 0x99, 0x99, 0xAA, 0xBC, 0xDF, 0xFF, 0xDD, 0xCB, 0xAA, 0x99, 0x88, 0x88, + 0x89, 0x9A, 0xBD, 0xEF, 0xFC, 0xDB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x88, + 0x9A, 0xBD, 0xFF, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xFC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDF, + 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x66, 0x78, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x67, 0x8A, 0xBD, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x79, 0xAB, 0xCD, 0xDC, 0xB9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDE, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAC, 0xCD, 0xFD, 0xCB, 0x98, 0x87, 0x76, 0x67, 0x77, 0x89, 0xAB, + 0xCD, 0xDF, 0xFD, 0xBA, 0x99, 0x88, 0x77, 0x78, 0x89, 0xAA, 0xBC, 0xDD, + 0xFF, 0xFD, 0xBA, 0xA9, 0x99, 0x89, 0x99, 0xAA, 0xBC, 0xDD, 0xEF, 0xFF, + 0xED, 0xCB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xFF, 0xFF, 0xFF, 0xED, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xEF, 0xFF, 0xFF, 0xFE, 0xDD, + 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFD, 0xED, 0xDD, + 0xDD, 0xDD, 0xED, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAE, 0xCD, 0xCC, 0xEC, 0xCD, 0xCC, 0xCD, 0xEF, 0xFF, 0xFF, 0xDD, 0xFD, + 0xDC, 0xDC, 0xCD, 0xCC, 0xDD, 0xED, 0xDF, 0xFF, 0xFF, 0xCF, 0xDF, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDF, 0xFF, 0xFD, 0xFD, 0xCB, 0xBB, 0xAA, + 0x99, 0xA9, 0xAB, 0xCD, 0xFF, 0xFF, 0xDE, 0xCB, 0xBA, 0x99, 0x88, 0x88, + 0x89, 0xAA, 0xCD, 0xFF, 0xFD, 0xDC, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x88, + 0x9A, 0xBD, 0xFD, 0xCC, 0xBA, 0x99, 0x87, 0x66, 0x66, 0x67, 0x88, 0xAC, + 0xCF, 0xEC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAC, 0xDD, + 0xDD, 0xBA, 0x97, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xCB, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x79, 0xAB, 0xDD, 0xDC, 0xB9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x77, 0x9A, 0xBC, 0xDD, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xBD, 0xDC, 0xB9, 0x97, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCD, 0xCD, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x99, 0xAC, 0xDC, 0xFE, 0xCA, 0x98, 0x87, 0x76, 0x67, 0x78, 0x99, 0xAC, + 0xCD, 0xCD, 0xED, 0xBA, 0x99, 0x88, 0x78, 0x88, 0x99, 0xAB, 0xCD, 0xDC, + 0xFF, 0xFC, 0xBA, 0xA9, 0x99, 0x89, 0x99, 0xAB, 0xBC, 0xDD, 0xCF, 0xFF, + 0xFD, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xCB, 0xCD, 0xDC, 0xFF, 0xFF, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xFF, 0xDF, 0xFF, 0xFF, 0xEE, 0xDE, + 0xDC, 0xCD, 0xDF, 0xEE, 0xFF, 0xFD, 0xDF, 0xFF, 0xEE, 0xDC, 0xDD, 0xCC, + 0xCC, 0xCC, 0xCC, 0xFD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAE, 0xED, 0xDE, 0xDD, 0xDD, 0xDE, 0xDF, 0xFF, 0xFF, 0xFF, 0xCD, 0xFE, + 0xFF, 0xEE, 0xDD, 0xDD, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xEE, 0xDC, + 0xCB, 0xCB, 0xBB, 0xCC, 0xDE, 0xEF, 0xFF, 0xFD, 0xFE, 0xDC, 0xCB, 0xAA, + 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xFF, 0xDF, 0xDC, 0xBB, 0xA9, 0x99, 0x99, + 0x9A, 0xAB, 0xDF, 0xFF, 0xFD, 0xDD, 0xBA, 0xA9, 0x88, 0x77, 0x78, 0x89, + 0xAB, 0xDE, 0xFF, 0xDD, 0xDB, 0xA9, 0x87, 0x76, 0x66, 0x77, 0x89, 0xBC, + 0xFE, 0xFD, 0xDB, 0xB9, 0x87, 0x66, 0x55, 0x56, 0x77, 0x9A, 0xBD, 0xFF, + 0xDD, 0xCA, 0x98, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCE, 0xFD, 0xEB, + 0xA9, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xBD, 0xFF, 0xDD, 0xBA, 0x97, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9B, 0xCD, 0xED, 0xDB, 0xA9, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xFD, 0xED, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xDF, 0xFD, 0xEC, 0xB9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xED, 0xDF, 0xFC, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x9A, 0xAC, + 0xDE, 0xEF, 0xFF, 0xCB, 0xA9, 0x88, 0x88, 0x88, 0x9A, 0xBB, 0xCE, 0xFE, + 0xFF, 0xFE, 0xCB, 0xBA, 0x99, 0x99, 0xAA, 0xAB, 0xCD, 0xEF, 0xEF, 0xFF, + 0xED, 0xDC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFE, + 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, + 0xDE, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xDD, 0xED, 0xCD, + 0xDD, 0xCC, 0xDD, 0xDE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xAC, 0xDC, + 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDD, 0xFE, 0xCC, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDE, 0xDB, 0xCB, 0xAA, 0xA9, 0x99, + 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xED, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xCC, 0xCB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xBC, 0xBA, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x98, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x66, 0x65, 0x56, + 0x66, 0x77, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xBB, 0xA9, 0x98, 0x77, 0x77, 0x67, 0x77, 0x88, 0x9A, + 0xBB, 0xBC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xCB, + 0xCC, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xBD, 0xDC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCC, 0xEE, 0xDC, 0xCB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCD, 0xFD, 0xDC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEC, 0xBD, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xCB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x8A, 0xA9, 0x99, 0x99, 0x98, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xAA, 0xBB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xDC, 0xAB, 0xBA, 0xA9, + 0x99, 0x99, 0x88, 0x99, 0x9A, 0xAA, 0xBC, 0xC9, 0xAA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x99, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x78, 0x88, 0x99, 0xAB, 0xB9, 0xA9, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, + 0x88, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x77, 0x76, 0x66, 0x77, 0x78, 0x89, + 0xAA, 0xA9, 0x99, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x78, 0x89, 0xA9, + 0x99, 0x98, 0x87, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0x99, 0x99, + 0x87, 0x76, 0x66, 0x66, 0x66, 0x67, 0x78, 0x89, 0x99, 0x89, 0x88, 0x77, + 0x66, 0x66, 0x66, 0x66, 0x77, 0x78, 0x9A, 0x99, 0x98, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0x99, 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x99, 0x99, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x78, 0x89, 0xA9, 0x9A, 0x99, 0x87, 0x77, 0x77, 0x67, 0x77, 0x78, 0x89, + 0x9A, 0x9A, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, 0x89, 0x9A, 0xBA, + 0xAB, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x88, 0x99, 0x99, 0xAB, 0xAB, 0xBB, + 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBA, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xAD, 0xDD, 0xBB, 0xAA, 0xA9, + 0xA9, 0x9A, 0xAA, 0xAB, 0xBB, 0xDB, 0xAC, 0xCB, 0xAA, 0xA9, 0x99, 0x99, + 0x99, 0x9A, 0xAA, 0xAB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBA, 0xCB, + 0xBB, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xAB, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xCA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0x9A, 0x99, 0x88, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x9A, 0x98, 0x87, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x66, 0x66, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x56, 0x66, 0x67, 0x78, 0x89, 0xAA, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x67, 0x77, 0x88, 0x89, + 0xAB, 0xAB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xAB, 0xCB, + 0xAA, 0x99, 0x98, 0x88, 0x89, 0x99, 0x9A, 0xAB, 0xBB, 0xCC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0xBD, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDB, 0xBC, 0xCB, 0xBB, 0xAA, 0xAA, 0x9A, + 0xAA, 0xAA, 0xAA, 0xBB, 0x90, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xAA, 0xBC, 0xBD, 0xBB, 0xCC, + 0xBB, 0xBA, 0xAA, 0xA9, 0xA9, 0xAA, 0xBB, 0xCD, 0xDD, 0xBC, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBD, 0xCB, 0xBB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xAB, 0xAA, 0x99, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xAB, 0xBA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0xAA, 0x99, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x9A, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x67, 0x88, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x77, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x88, 0x9A, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x76, 0x67, 0x77, 0x78, 0x99, + 0xAB, 0xAB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBB, + 0xBC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x89, 0xAA, 0xBB, 0xBC, 0xCC, + 0xAA, 0x99, 0x98, 0x88, 0x89, 0x99, 0x9A, 0xBB, 0xCB, 0xCD, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xBD, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDB, 0xAD, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDE, 0xBC, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xFD, 0xBC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCE, 0xDB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x99, 0xAB, 0xBC, 0xDD, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xCB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x89, 0xAB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x78, 0x9A, + 0xAB, 0xBA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xBB, + 0xAA, 0x99, 0x87, 0x66, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x65, 0x55, 0x55, 0x67, 0x78, 0x99, 0xBB, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x77, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xBB, 0xAA, 0x98, 0x77, 0x76, 0x67, 0x77, 0x88, 0x9A, + 0xAB, 0xBB, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBB, + 0xCC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xBC, 0xCC, + 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDC, 0xDD, 0xDC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCE, 0xFD, 0xDC, 0xCB, 0xBB, + 0xAB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDC, 0xBD, 0xDC, 0xCC, 0xBB, 0xBB, 0xAA, + 0xAB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xBE, 0xFF, + 0xED, 0xDD, 0xCD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xED, 0xDC, + 0xCC, 0xBC, 0xBC, 0xDD, 0xDE, 0xFF, 0xFF, 0xFD, 0xDD, 0xDC, 0xBB, 0xAA, + 0xAA, 0xBB, 0xCC, 0xDE, 0xFF, 0xFF, 0xDE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDE, 0xFF, 0xFD, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x9A, + 0xBC, 0xDF, 0xFF, 0xDD, 0xCB, 0xA9, 0x87, 0x76, 0x67, 0x78, 0x9A, 0xBD, + 0xFF, 0xFD, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9B, 0xCD, 0xFE, + 0xDD, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x56, 0x89, 0xAB, 0xEE, 0xFD, 0xDB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBD, 0xEE, 0xDD, 0xBA, 0x98, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xDE, 0xED, 0xEC, 0xA9, 0x87, 0x55, + 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xED, 0xED, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xCE, 0xEE, 0xFD, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBD, 0xEE, 0xFF, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xEF, 0xFE, 0xDC, 0xBA, 0x99, 0x88, 0x99, 0x9A, 0xBB, 0xCD, 0xFE, + 0xEF, 0xFE, 0xDC, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xEF, 0xFF, + 0xFE, 0xDC, 0xCC, 0xCB, 0xBB, 0xBC, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xDD, 0xCC, 0xCD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDE, 0xED, 0xEE, 0xEF, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0xEE, 0xEE, 0xDE, + 0xED, 0xDD, 0xEE, 0xFE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDF, 0xFE, 0xFF, 0xBC, 0xED, + 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xDE, 0xFF, 0xFF, 0xFF, 0xCD, 0xDC, 0xCC, + 0xBB, 0xAB, 0xAB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFC, 0xDC, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAB, 0xCC, 0xFF, 0xFE, 0xCD, 0xCB, 0xAA, 0x99, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xFC, 0xCB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x89, + 0xAB, 0xCE, 0xFE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xDE, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x56, 0x77, 0x8A, 0xBC, 0xDE, + 0xCC, 0xB9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xCD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xB9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCD, 0xDD, 0xCB, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xCD, 0xCC, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xCC, 0xCD, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xDD, 0xDE, 0xED, 0xBB, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCC, 0xDD, + 0xFF, 0xEC, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xDD, 0xDF, 0xFF, + 0xFE, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xED, 0xDD, 0xFF, 0xFF, 0xEE, + 0xCC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDD, 0xEE, 0xDF, 0xFF, 0xFF, 0xFE, 0xED, + 0xDC, 0xCD, 0xCD, 0xDD, 0xDE, 0xED, 0xCF, 0xFF, 0xFE, 0xEE, 0xDD, 0xDD, + 0xCD, 0xCC, 0xDD, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xDD, 0xED, + 0xDC, 0xCC, 0xCB, 0xBB, 0xCC, 0xCD, 0xEE, 0xFF, 0xFF, 0xDE, 0xDD, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xFF, 0xFD, 0xDC, 0xBB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xFF, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xEF, 0xFC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0x9B, 0xCD, 0xEE, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xEC, 0xCA, 0x98, 0x87, 0x66, 0x55, 0x56, 0x67, 0x89, 0xAC, 0xDE, + 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDD, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x99, 0xAB, 0xDD, 0xDD, 0xCA, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDE, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x89, 0xAA, 0xBC, 0xDD, + 0xEE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xDF, 0xFF, + 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xFD, 0xFF, 0xFF, 0xED, + 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xDF, 0xFF, 0xFE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCD, 0xDE, 0xEF, 0xFE, 0xCF, 0xFF, 0xFF, 0xDE, 0xDD, 0xDD, + 0xCD, 0xDD, 0xDE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCD, 0xDF, 0xEE, 0xFF, 0xFF, 0xCD, 0xDE, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDF, 0xFF, 0xFD, 0xDC, 0xCB, 0xBA, 0xA9, + 0x99, 0xAA, 0xAB, 0xCD, 0xFF, 0xFF, 0xCC, 0xBB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCF, 0xFF, 0xFC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCE, 0xFF, 0xCD, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xDD, 0xFC, 0xCB, 0x98, 0x87, 0x65, 0x55, 0x56, 0x77, 0x8A, 0xBD, 0xFF, + 0xCC, 0xB9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xED, 0xCB, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xB9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDD, 0xCB, 0xA8, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xED, 0xBA, 0x98, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xCD, 0xFC, 0xB9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x99, 0xAB, 0xFD, 0xFF, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDF, 0xFD, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x89, 0xAB, 0xCC, 0xDD, + 0xFF, 0xDE, 0xCC, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xCF, 0xFF, + 0xDD, 0xCB, 0xBB, 0xBA, 0xAA, 0xBB, 0xBC, 0xCD, 0xED, 0xFF, 0xFF, 0xDD, + 0xDD, 0xCC, 0xBB, 0xCC, 0xCC, 0xCD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFE, 0xED, + 0xDC, 0xCD, 0xED, 0xDE, 0xDF, 0xEE, 0xBF, 0xFF, 0xFF, 0xFE, 0xED, 0xDC, + 0xDD, 0xCC, 0xCC, 0xDD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDD, 0xDC, 0xCC, 0xDC, 0xCD, 0xDD, 0xDE, 0xFF, 0xEF, 0xBE, 0xEE, + 0xDD, 0xDC, 0xCC, 0xCD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFE, 0xDE, 0xDD, 0xCB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDE, 0xEF, 0xFF, 0xFD, 0xDD, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAB, 0xBC, 0xCE, 0xFF, 0xFE, 0xCD, 0xDB, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAC, 0xDD, 0xFF, 0xFD, 0xDC, 0xBA, 0x99, 0x87, 0x77, 0x78, 0x99, + 0xBC, 0xDE, 0xEE, 0xDC, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x78, 0x9A, 0xBC, + 0xDF, 0xFC, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xFE, + 0xCC, 0xBA, 0x98, 0x66, 0x55, 0x45, 0x56, 0x78, 0xAB, 0xCE, 0xDD, 0xCB, + 0xA8, 0x76, 0x55, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDE, 0xDD, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0x9B, 0xCD, 0xDD, 0xDB, 0xA9, 0x86, 0x55, + 0x44, 0x55, 0x67, 0x89, 0xBC, 0xDE, 0xDD, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDE, 0xFC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xFF, 0xDC, 0xAA, 0x98, 0x77, 0x77, 0x88, 0x99, 0xAB, + 0xCD, 0xDE, 0xFE, 0xDB, 0xBA, 0x98, 0x88, 0x89, 0x9A, 0xAB, 0xCD, 0xDE, + 0xEF, 0xEE, 0xCC, 0xBA, 0xA9, 0x99, 0x9A, 0xAB, 0xCC, 0xED, 0xEF, 0xFF, + 0xFD, 0xDC, 0xBB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFE, + 0xDD, 0xCD, 0xCC, 0xCC, 0xCC, 0xDE, 0xEF, 0xEF, 0xFF, 0xFF, 0xFE, 0xED, + 0xDD, 0xDD, 0xDD, 0xEE, 0xFF, 0xFE, 0xBF, 0xEE, 0xEE, 0xFE, 0xED, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0x9C, 0xCB, 0xBB, 0xBA, 0xBA, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xAC, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFE, 0xCD, 0xCB, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xEF, 0xDB, 0xCB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xED, 0xBC, 0xBA, 0xA9, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xBB, 0xCD, 0xDB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDC, 0xBB, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xBB, 0xBA, + 0x98, 0x76, 0x55, 0x54, 0x55, 0x67, 0x88, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x88, 0xAA, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xBB, 0xBA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCB, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xBC, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCC, + 0xCD, 0xCB, 0xAA, 0x99, 0x98, 0x89, 0x99, 0x9A, 0xBB, 0xCD, 0xCC, 0xDD, + 0xCB, 0xBA, 0xAA, 0xA9, 0x9A, 0xAA, 0xBC, 0xCC, 0xDC, 0xDE, 0xED, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xCD, 0xCD, 0xFE, 0xED, 0xDC, 0xCC, + 0xBB, 0xCB, 0xCC, 0xCD, 0xDD, 0xEC, 0xAD, 0xDD, 0xCC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xCB, 0xCC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xA9, 0xA9, 0x9A, 0xAA, 0xAB, 0xBB, 0xCC, 0xAB, 0xDC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xED, 0xBB, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xCA, 0xBB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xDC, 0xAB, 0xAA, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0x9A, 0x98, 0x87, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0xAA, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xAA, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBB, + 0xBC, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBC, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xCD, 0xCB, 0xBB, + 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xEC, 0xDC, 0xBB, 0xBB, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xAD, 0xCC, 0xCB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xAB, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDC, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x89, 0x99, 0x9A, 0xAB, 0xCC, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x88, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xBB, 0xCB, + 0xAA, 0x99, 0x98, 0x88, 0x89, 0x99, 0xAA, 0xAB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xBC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xAC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xAB, 0xCC, + 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xAB, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCD, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBC, 0xBA, 0xBA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x67, 0x88, 0x9A, 0xAA, + 0x9A, 0x98, 0x77, 0x66, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x67, 0x77, 0x89, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAB, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xAC, 0xBB, 0xCB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBD, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xCD, 0xCD, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDC, 0xAC, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xCC, 0x9B, 0xCC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDD, 0xED, 0xBC, 0xCB, 0xBA, + 0xAA, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDD, 0xCB, 0xCB, 0xAA, 0x99, 0x99, + 0x89, 0x99, 0x9A, 0xAB, 0xCC, 0xDC, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x9A, 0xAB, 0xCD, 0xCA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBB, 0xCC, 0xAB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xBC, 0xBA, 0xAA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xBB, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xAB, 0xBA, 0xA9, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0x99, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xBA, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAB, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBB, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xBC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xAB, 0xBB, 0xCB, 0xAA, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xCC, 0xCB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xBC, 0xDC, + 0xCB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xCE, 0xDC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCD, 0xED, 0xDD, 0xCC, 0xCB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEC, 0xAD, 0xCC, 0xCC, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xFE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xBF, 0xFF, + 0xFE, 0xFD, 0xDD, 0xDD, 0xDE, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xED, + 0xCC, 0xCB, 0xCC, 0xCC, 0xDE, 0xEF, 0xFF, 0xEE, 0xFF, 0xEC, 0xCB, 0xBA, + 0xAA, 0xAB, 0xBC, 0xDD, 0xFF, 0xFE, 0xEF, 0xED, 0xCB, 0xAA, 0x99, 0x99, + 0xAA, 0xBC, 0xDE, 0xFF, 0xEE, 0xFD, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0x9A, + 0xBC, 0xDE, 0xFF, 0xDE, 0xCB, 0xA9, 0x87, 0x76, 0x77, 0x78, 0x9A, 0xBD, + 0xEF, 0xED, 0xEC, 0xB9, 0x87, 0x66, 0x55, 0x66, 0x79, 0xAB, 0xCE, 0xFE, + 0xDD, 0xCA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAC, 0xDE, 0xED, 0xDB, + 0xA9, 0x86, 0x54, 0x43, 0x45, 0x68, 0x9A, 0xCD, 0xEE, 0xDD, 0xBA, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x79, 0xAB, 0xDE, 0xED, 0xDC, 0xB9, 0x87, 0x65, + 0x44, 0x55, 0x78, 0x9A, 0xCD, 0xEE, 0xDD, 0xCB, 0xA9, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xBC, 0xDF, 0xED, 0xED, 0xBA, 0x98, 0x77, 0x66, 0x77, 0x89, + 0xAB, 0xCD, 0xFE, 0xDE, 0xEC, 0xBA, 0x99, 0x88, 0x78, 0x89, 0xAB, 0xBD, + 0xEF, 0xED, 0xFE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0xAB, 0xBC, 0xDF, 0xFE, + 0xEF, 0xFE, 0xDC, 0xBB, 0xBA, 0xAA, 0xBB, 0xCD, 0xDE, 0xEF, 0xFD, 0xFE, + 0xEE, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xEF, 0xFF, 0xEE, + 0xEE, 0xDD, 0xDD, 0xDD, 0xEE, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xEE, + 0xFE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xAE, 0xEE, 0xEE, 0xEE, 0xDD, 0xDE, + 0xEF, 0xFE, 0xEE, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xDC, 0xDC, 0xCC, 0xCB, 0xCB, 0xCC, 0xCC, 0xDD, 0xCD, 0xAD, 0xED, + 0xDD, 0xCC, 0xCC, 0xCC, 0xBC, 0xCD, 0xCE, 0xEF, 0xFE, 0xEE, 0xDC, 0xCB, + 0xBB, 0xBA, 0xAB, 0xBB, 0xCC, 0xDE, 0xDF, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCD, 0xDE, 0xFD, 0xCD, 0xCB, 0xA9, 0x99, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xEF, 0xDC, 0xDB, 0xAA, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xDE, 0xDC, 0xCB, 0x98, 0x77, 0x65, 0x55, 0x56, 0x77, 0x89, 0xBC, 0xDD, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9B, 0xBC, 0xDB, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xDC, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xBA, 0x88, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDC, 0xCD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAC, + 0xCE, 0xDC, 0xDD, 0xCA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xDD, 0xDC, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAC, 0xCD, 0xEE, 0xDD, 0xEF, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xED, 0xFD, 0xEE, 0xEE, 0xDD, + 0xDC, 0xCB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xED, 0xFF, 0xED, 0xED, 0xDD, + 0xDC, 0xCD, 0xDD, 0xEE, 0xEF, 0xFE, 0xAD, 0xED, 0xDD, 0xDD, 0xCD, 0xDC, + 0xDD, 0xDE, 0xED, 0xED, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xCC, 0xCC, 0xBB, 0xBC, 0xCC, 0xCD, 0xDE, 0xEF, 0xCE, 0xFE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xFF, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCE, 0xFF, 0xED, 0xDC, 0xBB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFE, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x88, 0x9A, 0xBC, 0xDE, 0xEC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xDE, 0xCC, 0xB9, 0x98, 0x77, 0x66, 0x66, 0x67, 0x88, 0x9B, + 0xCD, 0xDC, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDD, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x67, 0x78, 0xAB, 0xCC, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x55, 0x56, 0x77, 0x8A, 0xBC, 0xCC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x89, 0xAC, 0xDD, 0xDD, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x89, 0xAB, 0xBD, 0xDD, + 0xDE, 0xDC, 0xBA, 0x99, 0x98, 0x89, 0x99, 0xAB, 0xBC, 0xDE, 0xED, 0xFD, + 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xFE, 0xEF, 0xEE, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFE, 0xFF, 0xEE, 0xDD, 0xDC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFF, 0xCF, 0xEE, 0xED, 0xDD, 0xDD, 0xCC, + 0xCD, 0xDD, 0xDF, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCC, 0xCC, 0xBB, 0xBB, 0xBC, 0xBC, 0xCC, 0xCC, 0xDD, 0xAC, 0xDD, + 0xDD, 0xCC, 0xCC, 0xBC, 0xBC, 0xCC, 0xDD, 0xDF, 0xFD, 0xDE, 0xEC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xDE, 0xCC, 0xDD, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAB, 0xCC, 0xDD, 0xED, 0xCD, 0xBB, 0xAA, 0x99, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDD, 0xDB, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCC, 0xED, 0xBC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x77, 0x89, 0xAB, + 0xCD, 0xCB, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xBC, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x45, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xB9, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xCA, 0xA8, 0x76, 0x65, + 0x44, 0x56, 0x67, 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x78, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCD, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x9A, 0xAB, + 0xCD, 0xCC, 0xDC, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDC, + 0xCD, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCD, 0xCC, 0xED, + 0xDC, 0xCB, 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xDD, 0xDE, 0xDD, 0xDD, + 0xCC, 0xBB, 0xBB, 0xCC, 0xCC, 0xCD, 0xDF, 0xDD, 0xFF, 0xED, 0xDD, 0xDC, + 0xCC, 0xCD, 0xDD, 0xEE, 0xEE, 0xFD, 0xAD, 0xDC, 0xDC, 0xCC, 0xCC, 0xBC, + 0xCC, 0xCC, 0xDC, 0xDE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAE, 0xED, 0xDD, 0xDD, 0xDD, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0x9E, 0xFF, + 0xFF, 0xED, 0xED, 0xDD, 0xEE, 0xEF, 0xFE, 0xFF, 0xFD, 0xDF, 0xEE, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xEF, 0xFE, 0xFF, 0xED, 0xFE, 0xDD, 0xCC, 0xCB, + 0xBC, 0xCC, 0xDE, 0xEE, 0xEE, 0xFE, 0xDF, 0xDD, 0xCB, 0xBA, 0xAA, 0xAB, + 0xBC, 0xDD, 0xDF, 0xEF, 0xED, 0xED, 0xDB, 0xBA, 0x99, 0x88, 0x99, 0xAB, + 0xCD, 0xEF, 0xFD, 0xDE, 0xDC, 0xBA, 0x98, 0x77, 0x77, 0x89, 0xAB, 0xDD, + 0xFF, 0xDD, 0xED, 0xBA, 0x98, 0x76, 0x55, 0x67, 0x89, 0xBC, 0xDD, 0xFE, + 0xDE, 0xCB, 0xA9, 0x76, 0x54, 0x45, 0x67, 0x9A, 0xCD, 0xEF, 0xED, 0xED, + 0xCA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCE, 0xED, 0xDE, 0xDB, 0xA8, + 0x75, 0x43, 0x24, 0x57, 0x8A, 0xBC, 0xDE, 0xED, 0xED, 0xCA, 0x97, 0x65, + 0x44, 0x46, 0x78, 0xAC, 0xCD, 0xED, 0xDE, 0xDD, 0xBA, 0x87, 0x65, 0x56, + 0x68, 0x9A, 0xBD, 0xEF, 0xDD, 0xFE, 0xDC, 0xA9, 0x87, 0x77, 0x78, 0x8A, + 0xBC, 0xDE, 0xEE, 0xEF, 0xFD, 0xDB, 0xAA, 0x98, 0x88, 0x9A, 0xAB, 0xCD, + 0xFF, 0xDD, 0xFE, 0xED, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xFE, + 0xDF, 0xFE, 0xED, 0xDC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xEE, 0xFF, + 0xFF, 0xFE, 0xDD, 0xCD, 0xDD, 0xDD, 0xEF, 0xEF, 0xFE, 0xFF, 0xFF, 0xFE, + 0xFE, 0xEE, 0xED, 0xEE, 0xEE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xEF, + 0xFE, 0xEF, 0xFE, 0xFF, 0xFF, 0xFE, 0xAD, 0xDD, 0xDD, 0xDD, 0xED, 0xDE, + 0xDE, 0xEE, 0xDD, 0xEE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xDC, 0xCB, 0xBB, 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xCD, 0xAD, 0xED, + 0xCC, 0xBB, 0xAA, 0xBA, 0xAB, 0xBC, 0xCD, 0xDF, 0xFD, 0xDD, 0xCC, 0xBB, + 0xAA, 0xA9, 0x9A, 0xAA, 0xBB, 0xCD, 0xEE, 0xDC, 0xDB, 0xBA, 0xA9, 0x99, + 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xDD, 0xBC, 0xBA, 0xA9, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xBB, 0xCD, 0xCB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBB, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xAC, 0xCA, 0xA9, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x88, 0x9A, 0xBB, 0xAB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x99, 0xAB, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x89, 0x9A, 0xBB, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xAC, 0xBB, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x89, 0xAB, 0xCC, 0xBC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xCC, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCC, + 0xCD, 0xCB, 0xAA, 0x99, 0x98, 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xCC, 0xDD, + 0xCB, 0xBA, 0xAA, 0x99, 0x9A, 0xAA, 0xBB, 0xCD, 0xDD, 0xCE, 0xDD, 0xCC, + 0xBB, 0xBA, 0xAA, 0xBB, 0xBC, 0xCD, 0xEE, 0xDD, 0xFD, 0xED, 0xCC, 0xCC, + 0xBC, 0xBC, 0xCC, 0xDD, 0xEE, 0xFE, 0x9D, 0xDD, 0xCC, 0xCC, 0xBB, 0xBB, + 0xBC, 0xCC, 0xDD, 0xEE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0x9B, 0xDC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0xBB, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCD, 0xCA, 0xBB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xDC, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x89, 0xAA, 0xBC, 0xBA, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xBB, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x9A, + 0xAB, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x45, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBA, 0xAB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xBB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xBB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xBC, 0xBB, 0xCC, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCC, 0xCC, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCC, 0xDD, 0xDC, 0xCB, 0xBB, + 0xAA, 0xAB, 0xBB, 0xBC, 0xCC, 0xDD, 0x9C, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xAB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xCC, 0xAB, 0xBA, 0xA9, + 0x99, 0x88, 0x89, 0x99, 0x9A, 0xAB, 0xBC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xAB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAA, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x77, 0x78, 0x99, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x98, + 0x87, 0x76, 0x66, 0x55, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x88, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x89, 0xAA, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xBB, + 0xAA, 0x99, 0x98, 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDC, 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0x9A, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xA9, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0x9B, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0xAA, 0xAA, 0xBB, 0xBC, 0xDC, 0xBC, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xBA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x9A, 0x98, 0x77, 0x66, 0x66, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x67, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x67, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBB, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xAA, + 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xBB, 0xCC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0x9C, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAD, 0xCC, 0xCC, 0xCC, 0xCB, 0xBB, 0xBC, 0xBC, 0xCC, 0xDC, 0x9D, 0xED, + 0xED, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xED, 0xDF, 0xDD, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDD, 0xEE, 0xDC, 0xDD, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEC, 0xCC, 0xCB, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xCC, 0xCC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x9A, + 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x88, 0x9A, 0xBB, + 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x66, 0x56, 0x67, 0x88, 0xAA, 0xBC, 0xDC, + 0xBC, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCB, 0xCB, + 0xA9, 0x87, 0x54, 0x33, 0x45, 0x78, 0x9A, 0xBC, 0xDC, 0xBC, 0xBA, 0x98, + 0x76, 0x43, 0x34, 0x56, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCC, 0xCD, 0xBA, 0x99, 0x87, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCC, 0xBA, 0x98, 0x87, 0x76, 0x77, 0x88, + 0x9A, 0xBC, 0xDC, 0xCD, 0xCC, 0xAA, 0x98, 0x88, 0x88, 0x88, 0x9A, 0xBB, + 0xCD, 0xDC, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xDC, + 0xCE, 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDE, 0xDD, 0xDD, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDD, 0xED, 0xDF, 0xEE, 0xDD, + 0xDC, 0xCB, 0xCC, 0xCC, 0xCC, 0xEE, 0xEF, 0xDD, 0xEE, 0xEE, 0xED, 0xDD, + 0xCD, 0xCD, 0xDE, 0xEE, 0xEE, 0xFE, 0x9D, 0xCD, 0xCD, 0xCC, 0xCC, 0xCC, + 0xCC, 0xDD, 0xDD, 0xDE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFF, 0xFE, 0xFF, 0xEE, 0xDE, 0xDE, 0xEF, 0xEE, 0xEE, 0xAF, 0xFF, + 0xFF, 0xFE, 0xEE, 0xED, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xDD, 0xCD, 0xCC, 0xDE, 0xEF, 0xFF, 0xFF, 0xEF, 0xFF, 0xEE, 0xDC, 0xBB, + 0xBB, 0xBB, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xBA, 0x99, 0x9A, + 0xAB, 0xCD, 0xFE, 0xFF, 0xFF, 0xFE, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0x9B, + 0xCD, 0xEF, 0xFE, 0xFF, 0xDC, 0xB9, 0x87, 0x76, 0x77, 0x78, 0xAB, 0xCD, + 0xEF, 0xFE, 0xED, 0xBA, 0x97, 0x66, 0x55, 0x67, 0x79, 0xAB, 0xDE, 0xFF, + 0xEF, 0xCB, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xBC, 0xEF, 0xFE, 0xEC, + 0xB9, 0x86, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xCE, 0xFF, 0xFE, 0xCB, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xEF, 0xFE, 0xED, 0xB9, 0x87, 0x65, + 0x44, 0x55, 0x78, 0x9B, 0xCE, 0xFF, 0xFF, 0xDB, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x8A, 0xBD, 0xFF, 0xFF, 0xED, 0xCB, 0x98, 0x87, 0x66, 0x77, 0x89, + 0xAC, 0xEF, 0xFF, 0xFF, 0xED, 0xCB, 0x99, 0x88, 0x88, 0x89, 0xAB, 0xCE, + 0xEF, 0xFE, 0xFF, 0xDD, 0xCB, 0xA9, 0x99, 0x9A, 0xAB, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xED, 0xCB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xEE, 0xDC, 0xCC, 0xCC, 0xDD, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xEE, 0xEE, 0xDE, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xEE, 0xFE, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDD, 0x9E, 0xEE, + 0xDD, 0xCC, 0xCC, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFE, 0xEF, 0xDD, 0xCC, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFF, 0xDD, 0xEC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xED, 0xDD, 0xCB, 0xAA, 0x98, 0x88, 0x88, + 0x89, 0xAB, 0xBC, 0xDF, 0xEC, 0xDB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xED, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCE, 0xEC, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x77, 0x8A, 0xBC, 0xDD, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xBA, 0x88, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xDC, 0xDB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x89, 0xBC, + 0xDE, 0xED, 0xED, 0xCA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xDD, + 0xDE, 0xDC, 0xCB, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xFD, 0xFE, + 0xDC, 0xBB, 0xBB, 0xAA, 0xAA, 0xBC, 0xCC, 0xDE, 0xFE, 0xDF, 0xEE, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xEE, 0xFF, 0xED, 0xFE, 0xFE, 0xED, 0xDD, + 0xCD, 0xDD, 0xDE, 0xFE, 0xFF, 0xFF, 0xAE, 0xEE, 0xED, 0xDD, 0xDD, 0xDD, + 0xDD, 0xEE, 0xFE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xDD, 0xDC, 0xCC, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xEE, 0xBE, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCD, 0xDE, 0xEF, 0xFE, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xEF, 0xED, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xEE, 0xDC, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDE, 0xEC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x67, 0x89, 0xAB, + 0xCD, 0xDC, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x56, 0x67, 0x89, 0xAB, 0xDD, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBC, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xCB, 0xA9, 0x87, + 0x65, 0x55, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xA9, 0x87, 0x66, 0x55, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x66, 0x66, 0x78, + 0x99, 0xAC, 0xDD, 0xDC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDD, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEE, + 0xDE, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xEE, 0xED, + 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFE, 0xDF, 0xEE, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xFE, 0xFF, 0xEE, 0xED, 0xDC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0xBF, 0xEE, 0xDD, 0xDD, 0xDC, 0xDD, + 0xDD, 0xDE, 0xEF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xEE, 0xDD, 0xDD, 0xCC, 0xDD, 0xCD, 0xDE, 0xEF, 0xFE, 0xAF, 0xFF, + 0xFD, 0xDC, 0xCC, 0xCC, 0xCC, 0xED, 0xEE, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, + 0xBB, 0xAA, 0xBB, 0xBB, 0xCD, 0xEE, 0xFF, 0xFE, 0xED, 0xCB, 0xAA, 0xA9, + 0x99, 0x9A, 0xAB, 0xCD, 0xEE, 0xFE, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xCD, 0xEF, 0xED, 0xDC, 0xAA, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCD, 0xFD, 0xDD, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCF, 0xEC, 0xCB, 0xA8, 0x77, 0x65, 0x55, 0x56, 0x77, 0x8A, 0xBC, 0xDE, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xCE, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xDC, 0xBA, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xDD, 0xDC, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDE, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x99, 0xBB, + 0xCD, 0xED, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEE, + 0xEE, 0xED, 0xCB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xEF, 0xED, 0xFF, + 0xDD, 0xCB, 0xBB, 0xAA, 0xAA, 0xBC, 0xCD, 0xDE, 0xFF, 0xEF, 0xFF, 0xFD, + 0xDC, 0xCB, 0xBC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0xDD, + 0xDD, 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xAE, 0xEE, 0xED, 0xED, 0xDD, 0xDD, + 0xDE, 0xEE, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xEE, 0xFE, 0xDE, 0xEE, 0xFF, 0xDE, 0xFF, 0x9F, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xDC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xCB, 0xBA, + 0xAA, 0xAB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xDF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x87, 0x77, 0x88, 0x9A, + 0xBD, 0xFF, 0xFF, 0xEF, 0xDB, 0xA9, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xCD, + 0xFF, 0xFF, 0xFC, 0xB9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9B, 0xCE, 0xFF, + 0xEE, 0xCA, 0x98, 0x65, 0x54, 0x45, 0x56, 0x89, 0xAC, 0xDF, 0xFE, 0xDC, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xCD, 0xFF, 0xED, 0xCA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAC, 0xDF, 0xFE, 0xDC, 0xA9, 0x86, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xCD, 0xFF, 0xEE, 0xCB, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAC, 0xFF, 0xFF, 0xFD, 0xCA, 0x98, 0x76, 0x66, 0x67, 0x88, + 0xAB, 0xCE, 0xFF, 0xFF, 0xFC, 0xBA, 0x98, 0x87, 0x77, 0x89, 0x9B, 0xCD, + 0xFF, 0xFE, 0xFF, 0xDC, 0xBA, 0x99, 0x98, 0x99, 0xAB, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xED, 0xCB, 0xBA, 0xAA, 0xAB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDD, 0xCC, 0xCC, 0xCC, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0xED, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xEE, 0xDE, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBE, 0xEE, 0xDD, 0xDD, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xED, 0x9F, 0xFF, + 0xFE, 0xDD, 0xDD, 0xCD, 0xDD, 0xEF, 0xEE, 0xFF, 0xFE, 0xEF, 0xED, 0xDC, + 0xCC, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xFF, 0xEE, 0xEE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAB, 0xBC, 0xDD, 0xEF, 0xFE, 0xDD, 0xCC, 0xCA, 0xA9, 0x99, 0x99, + 0x9A, 0xBC, 0xCD, 0xEF, 0xDE, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x9A, + 0xBC, 0xDE, 0xFE, 0xDE, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDE, 0xED, 0xDC, 0xA9, 0x87, 0x66, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xEE, + 0xDD, 0xBA, 0x98, 0x76, 0x54, 0x45, 0x67, 0x89, 0xAC, 0xDF, 0xED, 0xDB, + 0xA9, 0x87, 0x54, 0x33, 0x45, 0x78, 0x9A, 0xCC, 0xFD, 0xDC, 0xCA, 0x98, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xAB, 0xCE, 0xDD, 0xDC, 0xA9, 0x87, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xBD, 0xEE, 0xDD, 0xCA, 0xA9, 0x77, 0x65, 0x56, + 0x67, 0x89, 0xAC, 0xDE, 0xED, 0xED, 0xCA, 0x98, 0x77, 0x76, 0x77, 0x89, + 0xAB, 0xCD, 0xFE, 0xEE, 0xDC, 0xBA, 0x98, 0x88, 0x78, 0x89, 0x9A, 0xBC, + 0xDE, 0xED, 0xFE, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xEE, + 0xEF, 0xFD, 0xDC, 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xEE, 0xFF, + 0xED, 0xDC, 0xCC, 0xBB, 0xBB, 0xCD, 0xDD, 0xEF, 0xFF, 0xEF, 0xFF, 0xFE, + 0xED, 0xDD, 0xDC, 0xDD, 0xDE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0xEE, + 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0x9E, 0xDE, 0xDD, 0xDE, 0xDD, 0xCD, + 0xDD, 0xFE, 0xEF, 0xFF, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0x8B, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDC, 0xBC, 0xBB, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xCA, 0xBB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xBC, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAB, 0xCB, 0xAA, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xB9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x87, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBB, + 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCB, 0xBD, 0xCB, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCC, 0xDD, 0xCC, 0xBB, 0xBA, + 0xAA, 0xBB, 0xBB, 0xBB, 0xCC, 0xDC, 0x9C, 0xCC, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xAB, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xDC, 0xBB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xCA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x78, 0x89, 0x9A, 0xBB, 0xB9, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBB, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x67, 0x78, 0x89, + 0xAB, 0xA9, 0x99, 0x87, 0x77, 0x66, 0x66, 0x66, 0x67, 0x78, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x66, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x77, 0x66, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xAA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBA, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xAA, 0x99, 0x99, 0x88, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xBC, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDC, 0x9C, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xAA, 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBC, 0xCC, 0x9C, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xDD, 0xED, 0xBC, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xCB, 0xBB, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0xAA, 0xBC, 0xBA, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xBA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xAA, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBB, 0xAB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xAB, 0xBB, 0xBA, 0xA9, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xCB, + 0xBC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAB, 0xBC, 0xCC, 0xCD, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCC, 0xED, 0xCC, 0xBB, 0xBB, + 0xBB, 0xAB, 0xBB, 0xBC, 0xDC, 0xDD, 0x9C, 0xCB, 0xBB, 0xBB, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xDC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0x9D, 0xED, + 0xCC, 0xBB, 0xBA, 0xAB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFE, 0xDD, 0xCC, 0xBA, + 0xAA, 0xAA, 0x9A, 0xAA, 0xBC, 0xCD, 0xDF, 0xEC, 0xDC, 0xAA, 0x99, 0x99, + 0x89, 0x99, 0x9A, 0xBB, 0xCD, 0xDD, 0xCC, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xBB, 0xCD, 0xDB, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xBB, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9B, + 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x66, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xBB, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDB, 0xA9, + 0x88, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0x9B, 0xCC, 0xBB, 0xA9, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x77, 0x89, 0xAC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0xAA, 0xCC, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBB, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAA, + 0xBC, 0xDC, 0xDC, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xDD, + 0xCD, 0xCC, 0xBA, 0x99, 0x98, 0x89, 0x99, 0xAA, 0xBC, 0xCD, 0xCD, 0xED, + 0xCB, 0xBA, 0xAA, 0x99, 0x9A, 0xAA, 0xBC, 0xCD, 0xED, 0xDF, 0xED, 0xCC, + 0xBB, 0xBB, 0xAB, 0xBB, 0xBB, 0xCD, 0xDE, 0xED, 0xEE, 0xDD, 0xDC, 0xCC, + 0xBB, 0xCC, 0xCC, 0xDD, 0xEE, 0xEE, 0x9D, 0xCD, 0xCC, 0xCC, 0xCB, 0xBC, + 0xCC, 0xCC, 0xCD, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xFF, 0xFD, 0xDD, 0xDC, 0xED, 0xDD, 0xDD, 0x9F, 0xFF, + 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, + 0xED, 0xDD, 0xCD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCD, 0xBB, + 0xBB, 0xBC, 0xDD, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xDC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCD, 0xDE, 0xFF, 0xEF, 0xFD, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0xAB, + 0xCD, 0xEF, 0xFF, 0xFF, 0xED, 0xBA, 0x88, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xFF, 0xFD, 0xCA, 0x98, 0x66, 0x55, 0x67, 0x89, 0xAC, 0xDF, 0xFF, + 0xEF, 0xCB, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xFF, 0xFF, 0xFC, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x68, 0xAB, 0xDF, 0xFF, 0xFF, 0xDB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xBD, 0xEF, 0xFF, 0xFD, 0xBA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xFF, 0xEC, 0xA9, 0x87, 0x65, 0x55, + 0x68, 0x9A, 0xCD, 0xFF, 0xFF, 0xFF, 0xCC, 0xA9, 0x87, 0x76, 0x77, 0x8A, + 0xBC, 0xFF, 0xFF, 0xFF, 0xFE, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFF, 0xFF, 0xDE, 0xCB, 0xBA, 0xA9, 0xAA, 0xBC, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDC, 0xBB, 0xBB, 0xCC, 0xDE, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFE, 0xDD, 0xCC, 0xDC, 0xDF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xED, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDD, 0xFE, 0xED, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDC, 0x9D, 0xEE, + 0xEE, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xDD, 0xED, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xDD, 0xCB, 0xBA, 0x99, 0x99, 0x89, + 0x9A, 0xAB, 0xCD, 0xEE, 0xDC, 0xCC, 0xBA, 0x99, 0x88, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xDD, 0xCD, 0xBA, 0x99, 0x87, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x66, 0x54, 0x45, 0x66, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x8A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x88, + 0x9A, 0xBD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDD, 0xCB, 0xAA, 0x99, 0x98, 0x89, 0x9A, 0xBB, 0xCD, 0xEE, + 0xDE, 0xDD, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xDD, 0xDF, 0xED, 0xED, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xFF, 0xFE, 0xCE, 0xFF, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xFD, 0xFE, 0xFF, 0xDE, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEF, 0xFF, 0xFE, 0x9D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xEE, 0xEF, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xCC, 0xCC, 0xBB, 0xBC, 0xCC, 0xCC, 0xDD, 0xDD, 0xAE, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDE, 0xEF, 0xFE, 0xDE, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xED, 0xDD, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAB, 0xBC, 0xDE, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0xAA, 0xBC, 0xDE, 0xDC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAB, 0xCC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCA, 0x98, 0x77, 0x66, 0x55, 0x56, 0x77, 0x89, 0xBC, 0xDD, + 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCC, 0xBA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xB9, 0x87, 0x76, 0x55, 0x55, + 0x67, 0x78, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDD, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xDE, 0xDC, 0xBB, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xDE, 0xED, 0xED, + 0xDC, 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFE, 0xDF, 0xEE, 0xDD, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xED, 0xFF, 0xEE, 0xDD, 0xDD, + 0xCC, 0xDD, 0xDD, 0xEE, 0xFF, 0xFF, 0xAE, 0xDD, 0xDD, 0xDD, 0xDD, 0xCC, + 0xDD, 0xDD, 0xEE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0x9F, 0xFE, + 0xED, 0xDD, 0xCD, 0xDC, 0xCC, 0xDD, 0xDE, 0xEF, 0xFD, 0xEF, 0xDE, 0xCC, + 0xCB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xEF, 0xDD, 0xED, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xAB, 0xCD, 0xEF, 0xFD, 0xDD, 0xDB, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xCD, 0xEE, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x99, + 0xAB, 0xCD, 0xFD, 0xDD, 0xCB, 0x98, 0x77, 0x66, 0x66, 0x78, 0x9A, 0xBC, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x56, 0x78, 0x9A, 0xBD, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x55, 0x56, 0x79, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x55, 0x44, 0x55, 0x67, 0x8A, 0xBC, 0xED, 0xCC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x76, 0x55, + 0x44, 0x55, 0x67, 0x8A, 0xBC, 0xDC, 0xCD, 0xCA, 0x98, 0x76, 0x55, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x67, 0x88, + 0x9A, 0xCC, 0xDD, 0xDD, 0xCC, 0xAA, 0x98, 0x77, 0x77, 0x88, 0x9A, 0xBC, + 0xDD, 0xDC, 0xED, 0xCB, 0xA9, 0x99, 0x88, 0x89, 0x9A, 0xBC, 0xCE, 0xED, + 0xDF, 0xDC, 0xCB, 0xBA, 0xA9, 0xAA, 0xAA, 0xBC, 0xDD, 0xEF, 0xED, 0xEE, + 0xDD, 0xCC, 0xCC, 0xBB, 0xBB, 0xBC, 0xDD, 0xEE, 0xEE, 0xEF, 0xFE, 0xED, + 0xDC, 0xDC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xFE, 0xFF, 0xEE, 0xFD, 0xDD, + 0xDD, 0xDD, 0xED, 0xDF, 0xFF, 0xFF, 0x9D, 0xDD, 0xCD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDE, 0xDE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFE, 0xFE, 0xDE, 0xCD, 0xDD, 0xED, 0xDD, 0xDE, 0x8F, 0xFF, + 0xFF, 0xEF, 0xED, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xDD, 0xDC, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCC, 0xBB, + 0xBB, 0xBB, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xBA, 0xA9, 0x9A, + 0xAB, 0xCD, 0xEF, 0xFF, 0xFF, 0xFE, 0xDC, 0xA9, 0x88, 0x88, 0x89, 0xAA, + 0xCD, 0xFF, 0xFF, 0xEF, 0xEC, 0xB9, 0x87, 0x76, 0x77, 0x88, 0xAB, 0xCE, + 0xFF, 0xFF, 0xFD, 0xBA, 0x97, 0x66, 0x55, 0x66, 0x89, 0xAC, 0xDF, 0xFF, + 0xEE, 0xDB, 0xA8, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBD, 0xFF, 0xFD, 0xDD, + 0xB9, 0x86, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xCF, 0xFF, 0xEF, 0xCB, 0x98, + 0x65, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xFF, 0xFD, 0xED, 0xBA, 0x87, 0x65, + 0x44, 0x55, 0x78, 0x9B, 0xDD, 0xFE, 0xEF, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xBD, 0xFF, 0xFF, 0xFD, 0xCB, 0xA8, 0x87, 0x66, 0x77, 0x89, + 0xBC, 0xDF, 0xFF, 0xFF, 0xDD, 0xBB, 0xA9, 0x88, 0x88, 0x89, 0xAB, 0xCF, + 0xFF, 0xFF, 0xFF, 0xEC, 0xCB, 0xAA, 0xA9, 0x9A, 0xBB, 0xDD, 0xFF, 0xFF, + 0xFF, 0xFD, 0xED, 0xCB, 0xBB, 0xBB, 0xCC, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xED, 0xDC, 0xCD, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xEF, 0xEE, 0xED, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0xDE, 0xEF, 0xFE, 0xED, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0x9D, 0xED, + 0xDC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDF, 0xED, 0xDD, 0xDC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xDC, 0xCC, 0xBB, 0xA9, 0x99, + 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xDD, 0xCC, 0xBA, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xCD, 0xDB, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xBC, 0xCC, 0xBB, 0xAA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAA, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCB, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xAA, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBC, 0xBB, 0xBA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x89, 0xAB, 0xCC, 0xBC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xBC, 0xDC, 0xCB, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCC, + 0xCD, 0xCB, 0xBA, 0x99, 0x98, 0x99, 0x9A, 0xAB, 0xBB, 0xDD, 0xCC, 0xDC, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xCD, 0xDD, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBD, 0xDD, 0xEF, 0xDD, 0xED, 0xDD, 0xCC, 0xCC, + 0xBC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFD, 0x8D, 0xCC, 0xCC, 0xBB, 0xBB, 0xBB, + 0xCB, 0xCC, 0xDD, 0xDE, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xAB, 0xBB, 0x8B, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCD, 0xCA, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x78, + 0x99, 0xAB, 0xBB, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x9A, + 0xAB, 0xBA, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xBA, + 0x9A, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x65, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBA, 0xAB, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x88, 0x88, 0x9A, 0xAB, 0xCB, + 0xBB, 0xBA, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xBB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCC, 0xBC, 0xCB, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xCB, 0xDC, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDC, 0x8C, 0xBB, 0xBA, 0xAB, 0xAA, 0xAA, + 0xAB, 0xBB, 0xBB, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBB, 0x9B, 0xCB, + 0xBB, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xBB, 0xCC, 0xDC, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBA, 0xBA, 0xA9, 0x99, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xBB, 0xCB, 0xAA, 0xA9, 0x98, 0x88, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBA, 0x9A, 0x99, 0x87, 0x77, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x9A, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x87, 0x76, 0x66, + 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBA, 0xAA, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBB, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xA9, 0x99, 0xAA, 0xAB, 0xBB, 0xCC, 0xCB, 0xDC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0x9B, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0x8C, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCC, 0xDC, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xCB, 0xBB, 0xBA, 0x99, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xCB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x67, 0x88, 0x9A, + 0xBC, 0xBA, 0xA9, 0x88, 0x76, 0x66, 0x56, 0x66, 0x77, 0x88, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xBA, 0xAA, 0x98, 0x77, + 0x65, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xAA, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x99, 0x87, 0x76, 0x65, 0x66, + 0x67, 0x78, 0x99, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x66, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xBB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x78, 0x88, 0x9A, + 0xBB, 0xBB, 0xBB, 0xA9, 0x98, 0x88, 0x77, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xA9, 0x99, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCC, 0xCD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xCC, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCE, 0xEC, 0x9C, 0xCB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAB, 0xBB, 0xBC, 0xCC, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xBF, 0xDC, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCD, 0x7D, 0xFD, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xFD, 0xDE, 0xDC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xCE, 0xEE, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCC, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x99, 0x88, 0x88, + 0x99, 0xAB, 0xBC, 0xDE, 0xCC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAA, 0xBD, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x78, 0x89, 0xAB, + 0xCD, 0xCC, 0xCA, 0xA8, 0x77, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xBC, 0xA9, 0x87, 0x65, 0x54, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCC, 0xCA, 0x98, 0x76, 0x65, + 0x54, 0x56, 0x67, 0x89, 0xAC, 0xCC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x56, + 0x67, 0x88, 0x9A, 0xBD, 0xDC, 0xCB, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDC, 0xCD, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x99, 0xAB, + 0xCD, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xFD, + 0xDD, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDD, 0xED, 0xED, + 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xDF, 0xEE, 0xDC, + 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xED, 0xEE, 0xFD, 0xDD, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xEE, 0x8D, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDD, 0xDD, 0xEE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xEF, 0xFD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFE, 0xFD, 0xDE, 0xFE, 0xFE, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xEE, + 0xDC, 0xCD, 0xDC, 0xDD, 0xEE, 0xFF, 0xFF, 0xDF, 0xFF, 0xED, 0xDC, 0xCB, + 0xBB, 0xBC, 0xCD, 0xDE, 0xEF, 0xFE, 0xEF, 0xEE, 0xCC, 0xBA, 0xA9, 0x9A, + 0xAB, 0xCC, 0xDE, 0xFF, 0xEE, 0xFE, 0xDC, 0xBA, 0x98, 0x88, 0x89, 0x9B, + 0xCD, 0xDE, 0xFF, 0xDE, 0xDC, 0xBA, 0x97, 0x76, 0x77, 0x89, 0xAB, 0xCD, + 0xFF, 0xDD, 0xED, 0xBA, 0x97, 0x66, 0x55, 0x66, 0x89, 0xAC, 0xCD, 0xFE, + 0xDE, 0xDB, 0xA8, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBC, 0xEE, 0xED, 0xEC, + 0xB9, 0x86, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xCE, 0xFE, 0xDD, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x8A, 0xBC, 0xEF, 0xEE, 0xEC, 0xBA, 0x87, 0x65, + 0x44, 0x46, 0x78, 0xAB, 0xCD, 0xFE, 0xED, 0xDB, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xBD, 0xDF, 0xFD, 0xED, 0xCB, 0xA9, 0x87, 0x66, 0x77, 0x8A, + 0xBC, 0xDE, 0xFF, 0xDE, 0xDD, 0xBA, 0xA9, 0x88, 0x88, 0x99, 0xAB, 0xDD, + 0xEF, 0xFD, 0xFE, 0xDC, 0xCB, 0xAA, 0x99, 0xAA, 0xBC, 0xCD, 0xFF, 0xFF, + 0xDF, 0xFE, 0xDD, 0xCC, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFF, 0xED, 0xFF, + 0xEE, 0xDD, 0xDC, 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xFF, 0xDF, 0xFE, 0xEE, + 0xEE, 0xED, 0xEE, 0xDF, 0xFE, 0xFF, 0xFF, 0xFC, 0xFF, 0xEF, 0xEF, 0xFE, + 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDE, 0xFF, 0xEF, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xED, 0xDD, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0x9E, 0xFE, + 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xFD, 0xEF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xDF, 0xDD, 0xED, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xED, 0xDD, 0xDC, 0xBA, 0x99, 0x98, 0x89, + 0x9A, 0xAB, 0xCD, 0xDD, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCC, 0xCA, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xAC, + 0xDD, 0xDC, 0xCB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDD, 0xCC, 0xBA, 0x87, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, + 0x9B, 0xBC, 0xDD, 0xCC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDC, 0xEC, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0x9A, 0xBC, 0xDD, 0xFE, + 0xCE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCE, 0xEF, 0xFC, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFF, 0xDE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFF, 0xFD, 0xFE, 0xEE, 0xED, 0xED, + 0xDD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0x9D, 0xDD, 0xDC, 0xDC, 0xDD, 0xDD, + 0xDD, 0xEE, 0xEF, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xDD, 0xAE, 0xEE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEE, 0xED, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAA, 0xBC, 0xDD, 0xDC, 0xCB, 0xA9, 0x98, 0x77, 0x77, 0x78, 0x89, + 0xAB, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xCB, 0xCA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xAC, 0xDC, + 0xBB, 0xA9, 0x87, 0x65, 0x54, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xCD, 0xCC, 0xBA, 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xED, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xEE, 0xDE, 0xDD, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xFD, 0xEE, 0xED, 0xDD, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0x9D, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, + 0xCD, 0xDE, 0xEE, 0xEF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDE, 0xEE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDC, 0x9E, 0xFE, + 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xEF, 0xFD, 0xDF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xDE, 0xDE, 0xED, 0xCC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xED, 0xDE, 0xDC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xDD, 0xCD, 0xBA, 0xA8, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xDD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCD, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9B, 0xCC, 0xED, 0xCD, 0xCB, 0xAA, 0x98, 0x87, 0x78, 0x89, 0x9A, 0xBC, + 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, 0x88, 0x99, 0xAA, 0xBC, 0xCD, 0xED, + 0xDE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xDD, 0xDE, 0xEC, 0xDD, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xFE, 0xDE, 0xEE, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xFF, 0xFD, 0xEE, 0xEE, 0xDD, 0xDC, + 0xDD, 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0x9D, 0xDC, 0xDC, 0xCC, 0xCC, 0xCD, + 0xDD, 0xED, 0xEE, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xEF, 0xED, 0xDD, 0xCD, 0xDC, 0xCC, 0xCD, 0xDD, 0x8F, 0xFF, + 0xFF, 0xFF, 0xEE, 0xDD, 0xDE, 0xEF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, + 0xDD, 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFF, 0xDF, 0xFF, 0xED, 0xCC, 0xBB, + 0xBB, 0xBB, 0xCD, 0xDE, 0xFF, 0xFE, 0xEF, 0xFD, 0xCB, 0xAA, 0x99, 0x9A, + 0xAB, 0xBC, 0xDE, 0xFF, 0xEE, 0xFD, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0x9B, + 0xCC, 0xEE, 0xFD, 0xEF, 0xDB, 0xA9, 0x87, 0x76, 0x67, 0x88, 0x9B, 0xCD, + 0xFF, 0xFD, 0xDD, 0xBA, 0x97, 0x66, 0x55, 0x66, 0x89, 0xAB, 0xDE, 0xFF, + 0xDD, 0xCB, 0x98, 0x76, 0x54, 0x45, 0x67, 0x8A, 0xBC, 0xDF, 0xFE, 0xEC, + 0xA9, 0x86, 0x54, 0x33, 0x45, 0x68, 0x9B, 0xCD, 0xFE, 0xDD, 0xCB, 0x98, + 0x65, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xDF, 0xED, 0xDC, 0xBA, 0x87, 0x65, + 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xEE, 0xDE, 0xCB, 0xA9, 0x76, 0x65, 0x56, + 0x67, 0x8A, 0xBD, 0xDF, 0xFD, 0xFD, 0xCB, 0x98, 0x87, 0x66, 0x77, 0x89, + 0xAC, 0xEF, 0xFF, 0xDF, 0xDD, 0xBB, 0xA9, 0x88, 0x88, 0x99, 0xAB, 0xCE, + 0xFF, 0xFD, 0xEF, 0xDD, 0xCB, 0xAA, 0x99, 0x9A, 0xBB, 0xCD, 0xEF, 0xFF, + 0xEF, 0xFE, 0xDD, 0xCC, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFE, 0xFF, + 0xDE, 0xDD, 0xCC, 0xCC, 0xCC, 0xDE, 0xEF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, + 0xEE, 0xED, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xEF, 0xFF, 0xFF, 0xFF, 0x9D, 0xDD, 0xDD, 0xEE, 0xDD, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0x8D, 0xEE, + 0xCC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEF, 0xED, 0xCD, 0xDC, 0xCB, + 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDD, 0xCC, 0xDC, 0xBB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xCC, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xCD, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, + 0x9A, 0xBC, 0xDC, 0xBB, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xBC, 0xCB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xDC, + 0xBB, 0xA9, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xBB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xAB, 0xCC, 0xBC, 0xBA, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x99, 0xAB, + 0xCD, 0xCC, 0xCC, 0xBA, 0x99, 0x98, 0x88, 0x88, 0x99, 0xAB, 0xBC, 0xDC, + 0xCD, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xCC, 0xDD, 0xDC, 0xED, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xED, 0xCE, 0xED, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEE, 0xDC, 0xEE, 0xED, 0xDC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xFE, 0x7C, 0xCC, 0xCC, 0xCB, 0xCB, 0xBB, + 0xCC, 0xCC, 0xDE, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xAB, 0xBB, 0x8C, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xDC, 0xBC, 0xCB, 0xBA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xBB, 0xBB, 0xAA, 0x99, 0x99, + 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x88, 0x9A, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xAA, 0x98, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xA9, + 0x98, 0x76, 0x55, 0x45, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xAA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x89, 0xAA, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, 0x9A, + 0xBC, 0xBA, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBB, 0xCB, + 0xBC, 0xBA, 0xAA, 0x99, 0x98, 0x89, 0x99, 0x9A, 0xAB, 0xCC, 0xBB, 0xCB, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xBD, 0xCC, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDD, 0xCB, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xED, 0x8B, 0xBB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0x9B, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0x9B, 0xCB, + 0xBB, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xBB, 0xBC, 0xDB, 0xBB, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0xAA, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAA, 0xBB, 0xAA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x77, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAA, 0xBA, + 0xAB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xCB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0x99, 0xAA, 0xAA, 0xBB, 0xCC, 0xCB, 0xCC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCC, 0xDC, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xBB, 0x8B, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDB, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xBB, 0xBB, 0xAA, 0x99, 0x88, + 0x88, 0x89, 0x99, 0xAA, 0xBC, 0xCB, 0xAB, 0xAA, 0x98, 0x88, 0x87, 0x88, + 0x88, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAB, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x9A, + 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xBA, + 0x9A, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xA9, 0xA9, + 0x87, 0x76, 0x55, 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0x9A, 0x98, 0x87, + 0x66, 0x55, 0x55, 0x56, 0x77, 0x89, 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x99, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBA, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBB, 0xBA, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x88, 0x9A, 0xAB, 0xCB, + 0xAC, 0xBA, 0xA9, 0x99, 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xBB, 0xCB, + 0xBA, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCB, 0xBC, 0xCB, 0xBB, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xCB, 0xDD, 0xCC, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xDC, 0xDC, 0x8B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCC, 0xCC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0x7D, 0xFE, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xED, 0xDD, 0xDC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xDC, 0xDC, 0xCB, 0xA9, 0x99, + 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xED, 0xCD, 0xBA, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xAC, 0xCD, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xBC, 0xA9, 0x98, 0x77, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCC, 0xCB, 0xBA, 0x98, 0x77, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x54, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x67, 0x78, 0x9A, 0xBC, 0xCB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x78, + 0x99, 0xBB, 0xCC, 0xCC, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCC, 0xCC, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xBC, 0xDD, + 0xCC, 0xCC, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDE, 0xDC, 0xDD, + 0xCC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAB, 0xCC, 0xDE, 0xED, 0xDE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xDD, 0xEF, 0xED, 0xED, 0xEE, 0xEC, 0xCC, + 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFE, 0x8D, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFF, 0xFF, 0xED, 0xDC, 0xDD, 0xDD, 0xCD, 0xCC, 0xCC, 0x8F, 0xFF, + 0xFF, 0xEE, 0xEE, 0xED, 0xEE, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFE, + 0xDD, 0xDD, 0xCD, 0xCD, 0xEE, 0xEF, 0xEF, 0xEE, 0xFF, 0xED, 0xDD, 0xCB, + 0xBB, 0xBC, 0xCD, 0xDD, 0xEF, 0xFD, 0xEF, 0xDE, 0xDC, 0xBA, 0xAA, 0xAA, + 0xAB, 0xCD, 0xDE, 0xFF, 0xDE, 0xFE, 0xDC, 0xA9, 0x98, 0x88, 0x99, 0xAB, + 0xCC, 0xEF, 0xFD, 0xEF, 0xDC, 0xB9, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xEF, 0xEE, 0xDD, 0xCA, 0x98, 0x66, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xFE, + 0xED, 0xDB, 0xA8, 0x76, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xEF, 0xDD, 0xED, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCE, 0xFE, 0xDE, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xEF, 0xED, 0xED, 0xCA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xCE, 0xEE, 0xDD, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x68, 0x9A, 0xCD, 0xDF, 0xFD, 0xFD, 0xCB, 0xA9, 0x87, 0x76, 0x77, 0x89, + 0xBC, 0xDE, 0xEF, 0xCE, 0xDC, 0xCB, 0xA9, 0x98, 0x88, 0x99, 0xBB, 0xDD, + 0xFF, 0xED, 0xEF, 0xEC, 0xCB, 0xAA, 0xA9, 0xAA, 0xBB, 0xDD, 0xEF, 0xFF, + 0xCD, 0xED, 0xDC, 0xCC, 0xBB, 0xBB, 0xBC, 0xDD, 0xFF, 0xFF, 0xFC, 0xFE, + 0xDD, 0xDD, 0xDC, 0xCD, 0xCD, 0xDD, 0xFF, 0xFF, 0xFF, 0xCE, 0xDE, 0xED, + 0xDD, 0xEE, 0xDE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFC, 0xFE, 0xFE, 0xDE, 0xEE, + 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCC, 0xCC, 0xCD, 0xDD, 0xDE, + 0xEE, 0xDE, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x9E, 0xFE, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDE, 0xEE, 0xFD, 0xDF, 0xED, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xDD, 0xED, 0xDC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xED, 0xDD, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCD, 0xDE, 0xDC, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x99, + 0xAB, 0xCD, 0xED, 0xCC, 0xCB, 0x99, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x79, 0xAB, 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, 0x98, 0x99, 0x9A, 0xBC, 0xDE, 0xED, + 0xCD, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEF, 0xDC, 0xED, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xFE, 0xCE, 0xED, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFF, 0xEC, 0xFE, 0xEE, 0xED, 0xDD, + 0xDD, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0x8D, 0xDD, 0xDC, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEE, 0xEE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCD, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCC, 0xCC, 0xAE, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xED, 0xDE, 0xDC, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xDD, 0xDC, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xCD, 0xDD, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xCD, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xCB, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x66, 0x78, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x88, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xDC, 0xCC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xED, + 0xCD, 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCC, 0xDE, 0xDC, 0xDD, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xDE, 0xFE, 0xCE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xED, 0xEE, 0xDD, 0xDC, 0xCC, + 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xFE, 0xAD, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xDD, 0xEE, 0xEF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, 0x9E, 0xFF, + 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDE, 0xFD, 0xEE, 0xED, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xCD, 0xDD, 0xEE, 0xDD, 0xED, 0xCC, 0xBA, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xED, 0xDD, 0xCC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCD, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xDD, 0xCD, 0xCB, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBB, + 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCC, 0xBA, 0x98, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xCC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xCC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDB, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xCD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xDC, 0xDC, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xBC, 0xCD, 0xED, + 0xCE, 0xDC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBC, 0xCD, 0xEF, 0xEC, 0xED, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xFE, 0xCE, 0xED, 0xDD, + 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFD, 0xEE, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEF, 0xEF, 0xFF, 0x9C, 0xCD, 0xDC, 0xDC, 0xCC, 0xCD, + 0xDD, 0xDD, 0xEE, 0xFE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFE, 0xED, 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7E, 0xFF, + 0xFF, 0xFE, 0xEE, 0xDD, 0xDD, 0xDE, 0xEE, 0xEF, 0xFD, 0xDF, 0xFE, 0xFE, + 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEE, 0xEF, 0xDE, 0xFE, 0xEE, 0xCC, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCD, 0xEF, 0xFD, 0xEF, 0xED, 0xCB, 0xBA, 0xA9, 0x9A, + 0xAB, 0xBC, 0xDD, 0xEE, 0xDE, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x89, 0xAA, + 0xCC, 0xDE, 0xED, 0xDE, 0xDB, 0xB9, 0x87, 0x76, 0x77, 0x89, 0xAB, 0xCD, + 0xEF, 0xDE, 0xDC, 0xBA, 0x97, 0x66, 0x55, 0x67, 0x89, 0xAC, 0xCE, 0xFD, + 0xDD, 0xCB, 0xA8, 0x75, 0x54, 0x45, 0x67, 0x8A, 0xBD, 0xDF, 0xED, 0xEC, + 0xB9, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCD, 0xED, 0xDD, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x56, 0x89, 0xBC, 0xEF, 0xED, 0xDC, 0xBA, 0x87, 0x65, + 0x44, 0x46, 0x78, 0xAB, 0xCD, 0xED, 0xDD, 0xDB, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xBC, 0xEF, 0xDD, 0xED, 0xCB, 0xA9, 0x87, 0x76, 0x77, 0x89, + 0xBC, 0xDE, 0xFE, 0xDF, 0xDC, 0xCB, 0xA9, 0x88, 0x88, 0x99, 0xAB, 0xCD, + 0xFF, 0xED, 0xEE, 0xDD, 0xBB, 0xAA, 0x99, 0xAA, 0xAB, 0xCD, 0xEF, 0xFF, + 0xDE, 0xED, 0xCC, 0xCB, 0xBB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFF, 0xFE, 0xFF, + 0xED, 0xDD, 0xCC, 0xCC, 0xCD, 0xDE, 0xFE, 0xFF, 0xFF, 0xDF, 0xFE, 0xEE, + 0xDE, 0xDE, 0xDE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xEF, 0xEE, 0xFE, + 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xDD, 0xDC, 0xDE, 0xDE, 0xED, + 0xED, 0xFF, 0xEE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xEE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0x8E, 0xFF, + 0xED, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEF, 0xFE, 0xEF, 0xED, 0xCC, + 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEE, 0xEE, 0xDE, 0xED, 0xCB, 0xBA, 0xAA, + 0xA9, 0xAA, 0xAB, 0xCD, 0xDE, 0xFD, 0xED, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCC, 0xDF, 0xDC, 0xCC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xED, 0xDC, 0xBA, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xCE, 0xDC, 0xDB, 0xA9, 0x87, 0x66, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCC, 0xBA, 0x98, 0x66, 0x54, 0x55, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA8, 0x76, 0x54, 0x34, 0x55, 0x67, 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, + 0x65, 0x53, 0x34, 0x56, 0x78, 0x9A, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x54, 0x56, 0x67, 0x99, 0xBC, 0xDD, 0xCC, 0xCA, 0x98, 0x77, 0x65, 0x56, + 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x88, + 0x9A, 0xBD, 0xED, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xDE, 0xEC, 0xDD, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xEE, + 0xDE, 0xDC, 0xCB, 0xAA, 0xAA, 0x9A, 0xAA, 0xBB, 0xCE, 0xEF, 0xFD, 0xEE, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDE, 0xFF, 0xDE, 0xED, 0xDD, + 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFD, 0xFF, 0xFD, 0xED, 0xDD, + 0xDD, 0xDD, 0xDE, 0xEF, 0xFF, 0xFE, 0x7C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xDD, 0xDD, 0xEE, 0xFE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0x8B, 0xDC, + 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xEB, 0xBC, 0xBB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xBB, 0xCB, 0xAA, 0x99, 0x98, + 0x88, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xAB, 0xAA, 0x98, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xBC, 0xBA, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xAB, 0xAA, 0xA9, + 0x88, 0x76, 0x55, 0x45, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x98, 0x87, + 0x66, 0x55, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xAA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xBB, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBC, 0xBA, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xBB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xDC, 0xBD, 0xCC, 0xBB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xDD, 0xCB, 0xDC, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xEC, 0x8B, 0xBB, 0xBB, 0xBA, 0xAA, 0xAA, + 0xAB, 0xBB, 0xBC, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAB, 0xBA, 0xAA, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0x8B, 0xCB, + 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCB, 0xBB, 0xBA, 0xAA, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBB, 0xCC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x89, 0x99, 0xAA, 0xBB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x78, + 0x88, 0x99, 0xAA, 0xBB, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x88, 0x99, + 0xAB, 0xA9, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xBA, + 0x9A, 0x98, 0x77, 0x66, 0x55, 0x56, 0x66, 0x78, 0x89, 0xAA, 0xA9, 0xA9, + 0x87, 0x76, 0x65, 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x77, + 0x66, 0x55, 0x55, 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x78, 0x9A, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x78, 0x89, 0xAB, 0xA9, 0xA9, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xAA, 0xBA, 0xA9, 0x98, 0x88, 0x77, 0x78, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xBA, 0xA9, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xCB, + 0xBA, 0xA9, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBC, 0xCB, 0xBC, 0xCB, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xCB, 0xCC, 0xCB, 0xBB, 0xBA, + 0xAA, 0xAB, 0xBB, 0xBC, 0xCC, 0xDC, 0x8B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAB, 0xBB, 0xCC, 0xA0, 0x00, 0x00, 0x00, + }, + { + 0xAC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0x8C, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xBC, 0xCD, 0xDC, 0xBC, 0xCB, 0xBA, + 0xA9, 0x99, 0x9A, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCB, 0xAA, 0x99, 0x98, + 0x89, 0x99, 0x9A, 0xAB, 0xBC, 0xCB, 0xBB, 0xBA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xBC, 0xBB, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x88, + 0x9A, 0xAB, 0xCB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x56, 0x66, 0x77, 0x89, 0xAA, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x55, 0x45, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0x98, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xBA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAA, 0xCB, 0xAB, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xBB, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, + 0xBC, 0xBB, 0xAA, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xAB, 0xCC, 0xCB, 0xCC, + 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCD, 0xDD, 0xDC, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xED, 0x8C, 0xBB, 0xBB, 0xBB, 0xBB, 0xAB, + 0xBB, 0xBC, 0xCC, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xCE, 0xDC, 0xCC, 0xCB, 0xBB, 0xBB, 0xBB, 0xCC, 0xBC, 0xCC, 0x7D, 0xFE, + 0xDD, 0xCC, 0xCB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xFD, 0xDE, 0xDC, 0xCB, + 0xBB, 0xAA, 0xAA, 0xBB, 0xCC, 0xCD, 0xDE, 0xDD, 0xDD, 0xCB, 0xAA, 0x99, + 0x99, 0x9A, 0xAB, 0xCC, 0xDD, 0xFD, 0xCD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x99, 0xAB, 0xBC, 0xDD, 0xCC, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xBD, 0xDC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, 0x89, 0xAB, + 0xCD, 0xDB, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDC, + 0xCB, 0xA9, 0x87, 0x65, 0x54, 0x55, 0x67, 0x78, 0x9B, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xCB, 0x98, 0x77, 0x65, + 0x54, 0x55, 0x67, 0x89, 0xAC, 0xCC, 0xBC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0x9A, 0xBD, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x66, 0x67, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBB, 0xA9, 0x88, 0x77, 0x77, 0x88, 0x99, 0xBB, + 0xCD, 0xDC, 0xDC, 0xBA, 0xA9, 0x98, 0x88, 0x89, 0x99, 0xAB, 0xCD, 0xDD, + 0xDE, 0xDC, 0xBB, 0xAA, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDE, 0xFC, 0xDD, + 0xDC, 0xBB, 0xBA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDF, 0xEE, 0xDE, 0xDE, 0xDC, + 0xCC, 0xCB, 0xBC, 0xBC, 0xCD, 0xDE, 0xFF, 0xED, 0xFE, 0xED, 0xDD, 0xCC, + 0xCD, 0xCC, 0xDE, 0xDE, 0xFF, 0xFF, 0x8C, 0xCC, 0xDC, 0xCC, 0xCC, 0xCC, + 0xDD, 0xCD, 0xDE, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xEE, 0xED, 0xED, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xFF, 0xFF, 0xFE, 0xED, 0xED, 0xDD, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xEE, + 0xDD, 0xDC, 0xCD, 0xDD, 0xDD, 0xFF, 0xFF, 0xDE, 0xFF, 0xED, 0xDC, 0xCB, + 0xBB, 0xCC, 0xCC, 0xDD, 0xFF, 0xFD, 0xEF, 0xEE, 0xDC, 0xBB, 0xAA, 0xAA, + 0xBB, 0xCD, 0xDE, 0xFF, 0xEF, 0xFE, 0xDB, 0xBA, 0x98, 0x88, 0x99, 0xAB, + 0xCC, 0xDE, 0xFF, 0xEF, 0xDD, 0xB9, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCE, + 0xEF, 0xED, 0xED, 0xCA, 0x97, 0x66, 0x55, 0x67, 0x89, 0xAC, 0xDD, 0xFF, + 0xDD, 0xDB, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xBD, 0xFF, 0xED, 0xEC, + 0xBA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xDE, 0xFE, 0xDD, 0xCB, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xBD, 0xFE, 0xFD, 0xEC, 0xCA, 0x87, 0x65, + 0x44, 0x45, 0x78, 0xAC, 0xDF, 0xFF, 0xDE, 0xDC, 0xA9, 0x87, 0x65, 0x55, + 0x67, 0x9A, 0xCD, 0xFF, 0xFD, 0xFD, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x8A, + 0xBD, 0xEF, 0xFF, 0xCF, 0xDD, 0xCB, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xDE, + 0xFF, 0xED, 0xFD, 0xED, 0xCB, 0xAA, 0xAA, 0xAA, 0xBC, 0xDE, 0xEE, 0xFF, + 0xDE, 0xFD, 0xDD, 0xCB, 0xBB, 0xBB, 0xCC, 0xEE, 0xFF, 0xFF, 0xFD, 0xFE, + 0xEE, 0xDD, 0xDD, 0xCD, 0xDD, 0xEE, 0xFE, 0xFF, 0xFF, 0xDF, 0xEE, 0xEE, + 0xDD, 0xED, 0xDD, 0xEF, 0xEF, 0xFF, 0xFF, 0xFD, 0xEE, 0xEE, 0xEF, 0xEF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCC, 0xCC, 0xDD, 0xDD, 0xDE, + 0xFE, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xEF, 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xEF, 0xDD, 0xDC, 0xCC, 0xCC, 0xDD, 0xDE, 0xEE, 0xED, 0xEF, 0xED, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEE, 0xDE, 0xFE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xFD, 0xEE, 0xDC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCD, 0xDE, 0xDD, 0xDD, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xED, 0xDD, 0xCA, 0x98, 0x87, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xDE, 0xDC, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xEE, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCE, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xED, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xEE, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAC, 0xDE, 0xEC, 0xCC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, + 0x9B, 0xCD, 0xEE, 0xCD, 0xCB, 0xA9, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBD, + 0xEF, 0xFC, 0xDC, 0xCB, 0xAA, 0x99, 0x98, 0x99, 0x9A, 0xBC, 0xDF, 0xFF, + 0xCE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xFF, 0xFC, 0xED, + 0xDD, 0xCC, 0xBB, 0xBB, 0xBB, 0xCD, 0xDE, 0xEF, 0xFF, 0xCE, 0xED, 0xDD, + 0xDC, 0xCC, 0xCD, 0xDD, 0xDF, 0xFF, 0xFF, 0xFC, 0xFE, 0xEE, 0xEE, 0xEE, + 0xDD, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, + 0xEF, 0xEF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xEE, 0xDD, 0xCC, 0xCB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xAF, 0xFE, + 0xED, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xED, 0xEF, 0xDD, 0xCB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xDE, 0xDD, 0xED, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBB, 0xCD, 0xED, 0xDD, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xCD, 0xDC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x89, + 0x9A, 0xBC, 0xDC, 0xCC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCC, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, 0x66, 0x77, 0x89, 0xAB, 0xCC, + 0xBB, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xCC, 0xBB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBC, 0xCB, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xBB, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9A, 0xBD, 0xDB, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAB, + 0xCD, 0xEC, 0xCC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCD, 0xEE, + 0xCD, 0xCB, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xAB, 0xCD, 0xEF, 0xEC, 0xDD, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xCD, 0xDF, 0xFF, 0xCE, 0xDD, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFC, 0xEE, 0xDD, 0xDD, 0xCC, + 0xCC, 0xCD, 0xDD, 0xEF, 0xFF, 0xFF, 0xAD, 0xDD, 0xCC, 0xCC, 0xCC, 0xCD, + 0xDD, 0xEE, 0xEF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xDF, 0xFE, 0xED, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8F, 0xFF, + 0xFE, 0xDD, 0xDC, 0xCC, 0xDD, 0xDD, 0xDD, 0xEE, 0xEC, 0xEF, 0xEE, 0xDC, + 0xCB, 0xBB, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xDE, 0xEE, 0xDC, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xCC, 0xDD, 0xED, 0xEE, 0xDC, 0xBA, 0x99, 0x99, 0x99, + 0x9A, 0xAB, 0xCC, 0xDE, 0xDD, 0xEC, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xDD, 0xDD, 0xCB, 0xA8, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xBC, + 0xCD, 0xDD, 0xDC, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xCC, 0xDD, + 0xCC, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xDC, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x9A, 0xBC, 0xDD, 0xCC, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDC, 0xCB, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBC, 0xEE, 0xCC, 0xCA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xDE, 0xDD, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, + 0x9B, 0xCD, 0xEE, 0xCD, 0xCB, 0xAA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBC, + 0xEF, 0xEC, 0xDD, 0xCB, 0xAA, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xDE, 0xFE, + 0xCE, 0xDC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAB, 0xBC, 0xDE, 0xEF, 0xFC, 0xED, + 0xDC, 0xCC, 0xBB, 0xBB, 0xBB, 0xCC, 0xDE, 0xEF, 0xFF, 0xCE, 0xED, 0xDD, + 0xDC, 0xCC, 0xCC, 0xDD, 0xDE, 0xFF, 0xFF, 0xFD, 0xFE, 0xEE, 0xDD, 0xDD, + 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0x8C, 0xCC, 0xCC, 0xDC, 0xDD, 0xDD, + 0xDE, 0xEE, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xFF, 0xFD, 0xED, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFE, 0xDE, 0xDF, 0xDE, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xED, 0xDD, 0xCC, 0xCD, 0xEE, 0xEE, 0xFF, 0xDF, 0xFF, 0xFF, 0xED, 0xCC, + 0xBC, 0xBB, 0xCD, 0xDD, 0xEF, 0xFD, 0xFF, 0xFE, 0xEC, 0xBA, 0xAA, 0xAA, + 0xBB, 0xCC, 0xDF, 0xEF, 0xDF, 0xFF, 0xDC, 0xBA, 0x98, 0x88, 0x99, 0xAB, + 0xCC, 0xEF, 0xFF, 0xFF, 0xED, 0xBA, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xDD, + 0xEF, 0xDF, 0xFF, 0xCA, 0x97, 0x65, 0x55, 0x67, 0x89, 0xBC, 0xDF, 0xFE, + 0xEF, 0xDC, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x9A, 0xBD, 0xEF, 0xFE, 0xFD, + 0xCA, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCF, 0xFF, 0xDF, 0xDC, 0xA8, + 0x75, 0x43, 0x34, 0x57, 0x8A, 0xCD, 0xEF, 0xED, 0xFD, 0xCA, 0x97, 0x65, + 0x44, 0x45, 0x78, 0xAB, 0xDF, 0xFF, 0xEF, 0xDC, 0xB9, 0x87, 0x65, 0x55, + 0x68, 0x9B, 0xCF, 0xFF, 0xFD, 0xEE, 0xCB, 0xA9, 0x87, 0x76, 0x78, 0x9A, + 0xCD, 0xFF, 0xFF, 0xDF, 0xED, 0xCB, 0xA9, 0x98, 0x88, 0x9A, 0xBC, 0xDF, + 0xFF, 0xFD, 0xFD, 0xDC, 0xCB, 0xAA, 0xAA, 0xAA, 0xCD, 0xDF, 0xFF, 0xFF, + 0xDF, 0xFD, 0xDD, 0xCC, 0xCB, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFD, 0xFE, + 0xFE, 0xDD, 0xDC, 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFE, 0xEE, + 0xEE, 0xDE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xEF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8D, 0xCC, 0xCD, 0xDE, 0xEF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xFF, 0xDF, 0xDE, 0xDD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7F, 0xFF, + 0xEF, 0xFF, 0xFD, 0xEE, 0xFE, 0xDD, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xEE, + 0xDD, 0xDD, 0xDD, 0xCD, 0xDF, 0xFF, 0xFF, 0xDF, 0xFE, 0xED, 0xDC, 0xCB, + 0xBB, 0xBC, 0xCC, 0xDD, 0xFF, 0xFD, 0xFF, 0xFD, 0xDB, 0xBA, 0xAA, 0xAA, + 0xBB, 0xCC, 0xDD, 0xFF, 0xFF, 0xFE, 0xDB, 0xAA, 0x98, 0x89, 0x99, 0xAB, + 0xCC, 0xFF, 0xFF, 0xFE, 0xDC, 0xBA, 0x98, 0x77, 0x78, 0x89, 0xAC, 0xCC, + 0xFF, 0xFD, 0xFD, 0xCA, 0x98, 0x76, 0x66, 0x67, 0x89, 0xAC, 0xCD, 0xFE, + 0xDD, 0xCB, 0xA9, 0x76, 0x54, 0x45, 0x67, 0x9A, 0xCC, 0xDF, 0xDD, 0xED, + 0xBA, 0x97, 0x64, 0x23, 0x46, 0x78, 0xAB, 0xDD, 0xFF, 0xDD, 0xCB, 0xA9, + 0x76, 0x43, 0x24, 0x57, 0x9A, 0xCD, 0xFF, 0xFE, 0xDC, 0xCA, 0x98, 0x65, + 0x44, 0x56, 0x78, 0xAC, 0xDE, 0xFD, 0xDD, 0xDC, 0xAA, 0x87, 0x66, 0x56, + 0x78, 0x9A, 0xBD, 0xFF, 0xFE, 0xDD, 0xCB, 0xA9, 0x87, 0x77, 0x78, 0x99, + 0xBC, 0xEF, 0xFF, 0xDF, 0xED, 0xCB, 0xA9, 0x98, 0x89, 0x9A, 0xBC, 0xDD, + 0xFF, 0xFD, 0xFF, 0xEC, 0xCB, 0xBA, 0xAA, 0xAA, 0xAC, 0xDE, 0xEF, 0xFF, + 0xDF, 0xFE, 0xCC, 0xDC, 0xBB, 0xBB, 0xBC, 0xDD, 0xEF, 0xFF, 0xFE, 0xFF, + 0xDE, 0xED, 0xDD, 0xCC, 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFE, 0xFF, + 0xFF, 0xEC, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xED, 0xFE, + 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0xCB, 0xBC, 0xCD, 0xDC, 0xCF, + 0xDF, 0xEF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0x8D, 0xDC, + 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDC, 0xCD, 0xCB, 0xAA, + 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCB, 0xBA, 0x99, 0x99, + 0x89, 0x99, 0x9A, 0xAB, 0xBC, 0xDB, 0xBC, 0xAA, 0x99, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xCD, 0xBB, 0xBA, 0x99, 0x88, 0x77, 0x77, 0x78, 0x89, + 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x77, 0x89, 0x9A, + 0xBC, 0xBA, 0xBA, 0x98, 0x76, 0x66, 0x56, 0x66, 0x78, 0x89, 0xAB, 0xBB, + 0xAA, 0x99, 0x87, 0x66, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBB, 0xBA, 0xA9, + 0x98, 0x76, 0x55, 0x44, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0x99, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xBA, 0xA9, 0x98, 0x76, 0x65, + 0x55, 0x56, 0x67, 0x89, 0x9A, 0xBB, 0xAA, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x9A, 0xAB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCC, 0xAB, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xCA, 0xCB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBC, 0xCC, + 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x88, 0x99, 0x9A, 0xBB, 0xCD, 0xDB, 0xDC, + 0xCB, 0xAA, 0xAA, 0x99, 0x9A, 0xAA, 0xBB, 0xCD, 0xDD, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xDB, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBB, 0xCC, 0xCD, 0xDE, 0xED, 0x8C, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xDD, 0xDE, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0x9B, 0xCB, + 0xBA, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0xDB, 0xBC, 0xBA, 0xA9, + 0x99, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xBA, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x99, 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x78, + 0x89, 0xAA, 0xBA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x99, + 0xAB, 0xA9, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x56, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x9A, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x98, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0x9A, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBA, 0xBA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAA, 0xBB, + 0xAB, 0xAA, 0x99, 0x98, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xBA, 0xBB, + 0xAA, 0xA9, 0x99, 0x99, 0x99, 0x99, 0xAA, 0xBC, 0xCC, 0xBC, 0xBB, 0xAA, + 0xAA, 0x99, 0x99, 0xAA, 0xAA, 0xBB, 0xCD, 0xCB, 0xCC, 0xCB, 0xBB, 0xAA, + 0xAA, 0xAA, 0xBB, 0xBC, 0xCD, 0xDD, 0x9B, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xBC, 0xCD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBD, 0xCB, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBB, 0xBB, 0x8D, 0xDC, + 0xCB, 0xBB, 0xBA, 0xAA, 0xAB, 0xBB, 0xCC, 0xCD, 0xDB, 0xCC, 0xCB, 0xAA, + 0xAA, 0x99, 0x9A, 0xAA, 0xAB, 0xBB, 0xCD, 0xBC, 0xCB, 0xAA, 0x99, 0x98, + 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xDB, 0xBB, 0xBA, 0x98, 0x88, 0x88, 0x88, + 0x89, 0x9A, 0xAB, 0xBC, 0xBB, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x88, + 0x9A, 0xBB, 0xCB, 0xAB, 0xA9, 0x87, 0x76, 0x66, 0x67, 0x77, 0x89, 0x9A, + 0xBB, 0xBA, 0xB9, 0x98, 0x76, 0x66, 0x56, 0x66, 0x78, 0x89, 0xAB, 0xBB, + 0xAA, 0x99, 0x87, 0x65, 0x55, 0x55, 0x67, 0x78, 0x9A, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x55, 0x44, 0x56, 0x67, 0x89, 0x9A, 0xBB, 0xAA, 0x99, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAB, 0xBA, 0xAA, 0x98, 0x77, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0xAA, 0xA9, 0x88, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x99, 0xBB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCB, 0xAB, 0xAA, 0x98, 0x88, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBC, 0xCB, 0xBB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x89, 0x9A, 0xBC, 0xCC, + 0xBC, 0xBB, 0xAA, 0x99, 0x99, 0x88, 0x99, 0x9A, 0xAB, 0xCD, 0xCB, 0xCB, + 0xBB, 0xAA, 0xA9, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xDD, 0xBD, 0xDC, 0xBB, + 0xBB, 0xAA, 0xAA, 0xAB, 0xBB, 0xCC, 0xDE, 0xDB, 0xDD, 0xCC, 0xCB, 0xBB, + 0xBB, 0xBC, 0xCC, 0xCD, 0xDD, 0xED, 0x8B, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBC, 0xCD, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xFF, 0xDF, 0xDD, 0xCC, 0xCC, 0xDD, 0xCC, 0xCC, 0xCC, 0x7F, 0xFF, + 0xFF, 0xFD, 0xDE, 0xDD, 0xDE, 0xDE, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xED, + 0xCD, 0xCC, 0xCC, 0xDC, 0xDD, 0xEE, 0xFF, 0xDF, 0xFF, 0xDE, 0xCC, 0xBB, + 0xBB, 0xBB, 0xBC, 0xDD, 0xFE, 0xFE, 0xFF, 0xED, 0xCB, 0xAA, 0x99, 0xAA, + 0xAA, 0xBC, 0xCE, 0xEF, 0xEE, 0xED, 0xCB, 0xA9, 0x88, 0x88, 0x89, 0xAB, + 0xCC, 0xDE, 0xFF, 0xDF, 0xDB, 0xA9, 0x87, 0x77, 0x77, 0x89, 0xAB, 0xCD, + 0xDE, 0xED, 0xFC, 0xBA, 0x97, 0x66, 0x55, 0x67, 0x89, 0xAB, 0xCE, 0xED, + 0xDE, 0xCB, 0xA8, 0x75, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xDE, 0xED, 0xEC, + 0xB9, 0x87, 0x54, 0x33, 0x45, 0x78, 0xAB, 0xCE, 0xFF, 0xDE, 0xCB, 0x98, + 0x75, 0x43, 0x34, 0x57, 0x89, 0xBC, 0xDE, 0xFD, 0xDC, 0xBA, 0x97, 0x65, + 0x44, 0x46, 0x78, 0xAB, 0xCD, 0xFE, 0xDE, 0xCB, 0xA9, 0x87, 0x65, 0x56, + 0x67, 0x9A, 0xBC, 0xDF, 0xDD, 0xED, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x89, + 0xAC, 0xDF, 0xFF, 0xEF, 0xDC, 0xBB, 0xA9, 0x88, 0x88, 0x99, 0xAB, 0xCD, + 0xFF, 0xFF, 0xFD, 0xDC, 0xBB, 0xAA, 0x99, 0x9A, 0xAB, 0xCE, 0xDF, 0xFF, + 0xDF, 0xFD, 0xDC, 0xBB, 0xBB, 0xBB, 0xBC, 0xCD, 0xEF, 0xFF, 0xFD, 0xFF, + 0xDE, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xEE, 0xFF, 0xFF, 0xDF, 0xEF, 0xEE, + 0xED, 0xDD, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFE, 0xEF, 0xFE, 0xEE, + 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCC, 0xDD, 0xDD, 0xED, 0xDE, + 0xEE, 0xEF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xCC, 0xCB, 0xBB, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDD, 0xFD, 0xDF, 0xFF, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, + 0xCC, 0xCD, 0xFF, 0xFD, 0xFF, 0xFD, 0xFF, 0xFF, 0xFC, 0xDB, 0xBA, 0xBB, + 0xCB, 0xDD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xCB, 0xA9, 0x99, 0x9A, 0xBC, + 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x98, 0x77, 0x78, 0x9A, 0xBC, 0xDD, + 0xFD, 0xFF, 0xFF, 0xDD, 0xA8, 0x76, 0x55, 0x68, 0x9A, 0xBC, 0xFF, 0xFF, + 0xFF, 0xFC, 0xC9, 0x76, 0x54, 0x45, 0x68, 0xAB, 0xCC, 0xFF, 0xFF, 0xFD, + 0xCA, 0x97, 0x54, 0x23, 0x45, 0x79, 0xBC, 0xFF, 0xFF, 0xFF, 0xDC, 0xB9, + 0x76, 0x43, 0x24, 0x57, 0x9A, 0xCF, 0xFF, 0xFF, 0xFD, 0xDB, 0xA8, 0x65, + 0x44, 0x56, 0x79, 0xBD, 0xFF, 0xFF, 0xFF, 0xDC, 0xBA, 0x87, 0x65, 0x56, + 0x78, 0xAC, 0xDF, 0xFF, 0xFD, 0xFC, 0xFD, 0xBA, 0x88, 0x77, 0x78, 0x9A, + 0xCD, 0xFF, 0xFF, 0xDF, 0xFF, 0xDC, 0xBA, 0x99, 0x99, 0xAB, 0xCD, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFD, 0xDC, 0xBB, 0xBA, 0xBB, 0xDD, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFD, 0xFF, 0xDD, 0xDC, 0xCB, 0xDC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, + 0xDF, 0xDD, 0xFD, 0xFD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFD, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCB, 0xDD, 0xCF, 0xFF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEF, 0xEF, 0xFD, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x9F, 0xFF, + 0xFE, 0xDD, 0xDC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDF, 0xFD, 0xFF, 0xFF, 0xCC, + 0xCB, 0xBB, 0xBB, 0xBB, 0xBC, 0xDC, 0xEF, 0xEF, 0xFD, 0xDC, 0xBA, 0xAA, + 0x99, 0xAA, 0xAB, 0xCC, 0xDE, 0xFD, 0xFE, 0xDC, 0xBA, 0x99, 0x88, 0x89, + 0x9A, 0xAA, 0xCC, 0xDD, 0xED, 0xDC, 0xBA, 0x98, 0x87, 0x77, 0x78, 0x89, + 0xAB, 0xCD, 0xEE, 0xDD, 0xBA, 0x98, 0x77, 0x66, 0x66, 0x78, 0x89, 0xAC, + 0xCD, 0xDD, 0xCB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xED, + 0xDC, 0xBA, 0x87, 0x65, 0x54, 0x45, 0x66, 0x79, 0xAB, 0xCD, 0xEC, 0xCB, + 0xA8, 0x76, 0x54, 0x44, 0x55, 0x67, 0x89, 0xBD, 0xEE, 0xCC, 0xBA, 0x87, + 0x65, 0x54, 0x44, 0x56, 0x78, 0xAB, 0xDE, 0xEC, 0xCB, 0x98, 0x76, 0x65, + 0x54, 0x55, 0x67, 0x8A, 0xBC, 0xFE, 0xCC, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAB, 0xDF, 0xFC, 0xCB, 0xA9, 0x88, 0x76, 0x66, 0x67, 0x78, + 0x9A, 0xBE, 0xFF, 0xCC, 0xCB, 0xA9, 0x88, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xFF, 0xFC, 0xDD, 0xBB, 0xAA, 0x99, 0x88, 0x89, 0x9A, 0xBC, 0xDF, 0xFF, + 0xDD, 0xDC, 0xBB, 0xBA, 0xA9, 0x9A, 0xAA, 0xBC, 0xDE, 0xFF, 0xFC, 0xED, + 0xCC, 0xCC, 0xBB, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xFF, 0xDD, 0xDD, 0xED, + 0xDC, 0xDC, 0xDD, 0xDD, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFE, 0xDE, 0xDD, + 0xDD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xDD, 0xDD, 0xDF, 0xDE, 0xEE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFE, 0xDC, 0xCC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDE, 0xBF, 0xFF, + 0xFE, 0xDC, 0xCC, 0xBB, 0xBC, 0xCC, 0xDD, 0xEF, 0xFF, 0xFF, 0xFD, 0xCC, + 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xEF, 0xEF, 0xFD, 0xCB, 0xAA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDD, 0xFE, 0xFE, 0xCB, 0xA9, 0x98, 0x88, 0x88, + 0x89, 0x9A, 0xBC, 0xDF, 0xDD, 0xDC, 0xA9, 0x88, 0x77, 0x77, 0x77, 0x89, + 0x9A, 0xBC, 0xDD, 0xDC, 0xBA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xDC, 0xCB, 0x98, 0x76, 0x65, 0x55, 0x56, 0x77, 0x89, 0xAC, 0xDD, + 0xCC, 0xA9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCB, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xBD, 0xDC, 0xBA, 0x98, 0x76, 0x65, + 0x55, 0x55, 0x67, 0x89, 0xAC, 0xDE, 0xCC, 0xA9, 0x87, 0x76, 0x65, 0x55, + 0x66, 0x78, 0x9B, 0xCD, 0xEC, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xEF, 0xCC, 0xBA, 0x99, 0x87, 0x77, 0x77, 0x78, 0x89, 0xAC, + 0xDF, 0xFD, 0xDC, 0xBA, 0x99, 0x88, 0x88, 0x88, 0x99, 0xAB, 0xCE, 0xFF, + 0xDD, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0x9A, 0xBB, 0xCD, 0xFF, 0xFD, 0xED, + 0xCC, 0xBB, 0xAA, 0xAA, 0xAB, 0xBC, 0xDD, 0xFF, 0xFF, 0xDF, 0xED, 0xDC, + 0xCC, 0xBB, 0xBC, 0xCC, 0xDE, 0xFF, 0xFF, 0xFE, 0xFF, 0xEE, 0xDD, 0xDC, + 0xDD, 0xDD, 0xEF, 0xFF, 0xFF, 0xFF, 0xBE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, + 0xEF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFE, 0xDD, 0xFD, 0xEC, 0xDC, 0xCD, 0xCE, 0x9F, 0xFF, + 0xFF, 0xFD, 0xDD, 0xCC, 0xDC, 0xDD, 0xDE, 0xEF, 0xFD, 0xFF, 0xFF, 0xED, + 0xDC, 0xCB, 0xBB, 0xCC, 0xCC, 0xDD, 0xEF, 0xDF, 0xFE, 0xDD, 0xCB, 0xAA, + 0xAA, 0xAA, 0xBC, 0xCD, 0xDD, 0xFD, 0xFF, 0xDC, 0xBA, 0x99, 0x98, 0x99, + 0x9A, 0xAB, 0xCC, 0xDD, 0xDF, 0xED, 0xBA, 0x98, 0x87, 0x77, 0x88, 0x9A, + 0xAB, 0xCD, 0xFD, 0xED, 0xCB, 0x98, 0x77, 0x66, 0x67, 0x78, 0x9A, 0xAC, + 0xDD, 0xDD, 0xEB, 0xA9, 0x87, 0x65, 0x55, 0x66, 0x78, 0x9A, 0xBC, 0xDD, + 0xDD, 0xBA, 0x97, 0x65, 0x54, 0x45, 0x67, 0x89, 0xAB, 0xDE, 0xDD, 0xCB, + 0xA9, 0x76, 0x54, 0x44, 0x45, 0x67, 0x8A, 0xBC, 0xFD, 0xDD, 0xBA, 0x97, + 0x65, 0x44, 0x44, 0x56, 0x78, 0xAB, 0xCD, 0xDD, 0xDC, 0xA9, 0x87, 0x65, + 0x44, 0x55, 0x67, 0x9A, 0xBD, 0xEE, 0xDD, 0xBA, 0x98, 0x76, 0x65, 0x55, + 0x67, 0x89, 0xAC, 0xDD, 0xED, 0xDC, 0xBA, 0x98, 0x77, 0x66, 0x67, 0x78, + 0x9B, 0xCF, 0xFE, 0xDD, 0xDB, 0xAA, 0x98, 0x87, 0x77, 0x88, 0x9A, 0xBD, + 0xDF, 0xFD, 0xDD, 0xBB, 0xA9, 0x99, 0x89, 0x89, 0xAA, 0xBD, 0xEE, 0xFF, + 0xDE, 0xDC, 0xBB, 0xAA, 0xAA, 0xAA, 0xAB, 0xBD, 0xDF, 0xFF, 0xFD, 0xDD, + 0xDC, 0xCB, 0xBB, 0xBB, 0xBC, 0xCD, 0xDF, 0xFF, 0xFF, 0xDE, 0xDD, 0xDC, + 0xCC, 0xCC, 0xCC, 0xDD, 0xFE, 0xFF, 0xFF, 0xFC, 0xFF, 0xDF, 0xFE, 0xDE, + 0xDD, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9C, 0xCC, 0xDC, 0xDC, 0xDD, 0xDD, + 0xDD, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBB, 0xBB, 0xCB, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFD, 0xFF, + 0xCD, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBB, 0xCC, + 0xCC, 0xCD, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xCB, 0xAA, 0xA9, 0xAB, 0xBD, + 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xA9, 0x88, 0x88, 0x9A, 0xBC, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0xB9, 0x76, 0x66, 0x78, 0x9B, 0xCD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCA, 0x86, 0x54, 0x45, 0x79, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFB, 0xA8, 0x64, 0x22, 0x46, 0x8A, 0xCF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, + 0x86, 0x42, 0x24, 0x68, 0xAB, 0xDF, 0xFF, 0xFF, 0xFF, 0xDC, 0xB8, 0x75, + 0x44, 0x56, 0x8A, 0xCF, 0xFF, 0xFF, 0xDF, 0xFD, 0xCB, 0x98, 0x76, 0x67, + 0x89, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBA, 0xA9, 0x88, 0x89, 0xBB, + 0xCF, 0xFF, 0xFF, 0xDF, 0xFF, 0xCC, 0xBB, 0xAA, 0xAA, 0xBC, 0xDF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xCC, 0xCC, 0xBC, 0xCC, 0xCF, 0xFF, 0xFF, 0xFF, + 0xCF, 0xFD, 0xFF, 0xCC, 0xDD, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDD, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7B, 0xCD, 0xDC, 0xCD, 0xDF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xDF, 0xFD, 0xCB, 0xBF, 0xBC, 0xDC, 0xBA, 0xCB, 0xCB, 0x7F, 0xDF, + 0xDD, 0xDF, 0xCC, 0xBC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFC, 0xDD, 0xFF, 0xDD, + 0xDC, 0xFB, 0xDB, 0xCB, 0xCF, 0xDC, 0xFF, 0xBC, 0xFF, 0xFA, 0xFB, 0xFB, + 0xAB, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0xFD, 0xFC, 0xBB, 0xAA, 0xA9, 0x9A, + 0xBB, 0xCC, 0xCC, 0xFF, 0xCC, 0xFD, 0xCB, 0x9B, 0x89, 0x88, 0x99, 0xAB, + 0xAD, 0xCD, 0xFF, 0xFC, 0xBA, 0xAA, 0x97, 0x77, 0x78, 0x89, 0xAA, 0xBF, + 0xFF, 0xCB, 0xFC, 0xB9, 0x97, 0x76, 0x66, 0x77, 0x89, 0xAA, 0xFC, 0xFB, + 0xBC, 0xBB, 0xA9, 0x76, 0x54, 0x55, 0x67, 0x8A, 0xAC, 0xDC, 0xDD, 0xCC, + 0xB9, 0x97, 0x64, 0x23, 0x46, 0x78, 0x9C, 0xCB, 0xFC, 0xCF, 0xBB, 0xA8, + 0x76, 0x43, 0x24, 0x67, 0x99, 0xAC, 0xCF, 0xCF, 0xBC, 0xC9, 0x97, 0x65, + 0x44, 0x56, 0x78, 0x9A, 0xCD, 0xFF, 0xDC, 0xCA, 0xA9, 0x87, 0x66, 0x66, + 0x78, 0x9A, 0xBB, 0xFF, 0xFF, 0xFF, 0xCB, 0xA9, 0x87, 0x77, 0x77, 0x8A, + 0xBC, 0xBC, 0xFC, 0xFC, 0xCF, 0xCC, 0x99, 0x98, 0x88, 0x99, 0x9A, 0xCF, + 0xCF, 0xFF, 0xFF, 0xFC, 0xCB, 0xAA, 0x9A, 0xA9, 0xAA, 0xCF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xEC, 0xAA, 0xAB, 0xAC, 0xCC, 0xDF, 0xFF, 0xFC, 0xDF, + 0xCD, 0xCD, 0xBC, 0xCB, 0xCF, 0xFB, 0xDC, 0xFD, 0xFF, 0xDF, 0xFF, 0xDC, + 0xFD, 0xDC, 0xFC, 0xDF, 0xDD, 0xCF, 0xFF, 0xFA, 0xDC, 0xDF, 0xFD, 0xFD, + 0xCD, 0xDF, 0xDF, 0xDD, 0xDF, 0xFF, 0x6C, 0xBB, 0xCC, 0xCC, 0xDB, 0xFD, + 0xCF, 0xFF, 0xDD, 0xFF, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xCB, 0xAA, 0xAA, 0x99, 0x99, 0xA9, 0xAA, 0xAA, 0xAB, 0x8C, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, 0xAB, 0xCB, 0xCD, 0xDB, 0xBC, 0xCA, 0xBA, + 0x9A, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCE, 0xCB, 0xBB, 0xAA, 0x99, 0x98, + 0x88, 0x89, 0x9A, 0xAB, 0xBC, 0xCB, 0xBB, 0xA9, 0x98, 0x88, 0x88, 0x88, + 0x89, 0x99, 0xAB, 0xBC, 0xBA, 0xBA, 0x98, 0x87, 0x77, 0x77, 0x78, 0x89, + 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x87, 0x77, 0x66, 0x67, 0x77, 0x89, 0x9A, + 0xBC, 0xBA, 0xA9, 0x98, 0x76, 0x66, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xBB, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x56, 0x67, 0x78, 0x89, 0xAB, 0xBA, 0xA9, + 0x88, 0x76, 0x65, 0x44, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0x9A, 0x98, 0x87, + 0x66, 0x54, 0x45, 0x56, 0x78, 0x89, 0xAA, 0xB9, 0xA9, 0x88, 0x77, 0x65, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBB, 0x9A, 0xA9, 0x87, 0x76, 0x66, 0x56, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xBA, 0x99, 0x87, 0x76, 0x66, 0x66, 0x77, + 0x89, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x88, 0x77, 0x77, 0x77, 0x88, 0x9A, + 0xBC, 0xDA, 0xBB, 0xA9, 0x98, 0x88, 0x87, 0x88, 0x88, 0x9A, 0xAB, 0xCB, + 0xAC, 0xBA, 0xAA, 0x99, 0x98, 0x88, 0x89, 0x99, 0xAB, 0xCD, 0xCA, 0xCB, + 0xBA, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xAB, 0xCC, 0xDC, 0xBD, 0xCC, 0xBB, + 0xBA, 0xAA, 0xBA, 0xAA, 0xBB, 0xBE, 0xED, 0xCB, 0xCC, 0xDD, 0xCB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xCD, 0xFE, 0xFE, 0x8C, 0xBB, 0xBB, 0xAA, 0xAB, 0xBB, + 0xBB, 0xCC, 0xCD, 0xDD, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBB, 0xAA, 0xA9, 0x99, 0x99, 0x99, 0xAA, 0xAB, 0xBC, 0xAC, 0xCC, + 0xBA, 0xAA, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xBC, 0xDC, 0xBC, 0xBA, 0xA9, + 0x99, 0x98, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xBB, 0xBA, 0xA9, 0x98, 0x88, + 0x88, 0x88, 0x89, 0x9A, 0xAB, 0xCB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, + 0x88, 0x89, 0x9A, 0xBB, 0xBA, 0xA9, 0x98, 0x77, 0x77, 0x77, 0x77, 0x78, + 0x89, 0x9A, 0xBA, 0xAA, 0x98, 0x87, 0x76, 0x66, 0x66, 0x77, 0x78, 0x89, + 0xAB, 0xA9, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0x9A, 0xAA, + 0x99, 0x98, 0x77, 0x66, 0x65, 0x66, 0x66, 0x77, 0x89, 0x9A, 0xA9, 0x99, + 0x87, 0x76, 0x65, 0x55, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x88, 0x77, + 0x66, 0x65, 0x55, 0x66, 0x77, 0x88, 0x9A, 0xA9, 0x99, 0x87, 0x76, 0x66, + 0x65, 0x66, 0x67, 0x78, 0x99, 0xAA, 0x99, 0x98, 0x87, 0x76, 0x66, 0x66, + 0x66, 0x77, 0x89, 0xAA, 0xA9, 0xA9, 0x88, 0x77, 0x76, 0x66, 0x66, 0x77, + 0x88, 0x9A, 0xBA, 0xAA, 0x99, 0x88, 0x77, 0x77, 0x77, 0x77, 0x88, 0x99, + 0xAB, 0xBA, 0xAA, 0x99, 0x88, 0x87, 0x77, 0x77, 0x88, 0x99, 0xAB, 0xBB, + 0xAB, 0xAA, 0x99, 0x88, 0x88, 0x88, 0x88, 0x99, 0xAA, 0xBC, 0xCB, 0xBB, + 0xAA, 0x99, 0x99, 0x98, 0x99, 0x99, 0xAA, 0xBC, 0xDC, 0xBC, 0xBB, 0xBA, + 0xAA, 0x99, 0x99, 0x9A, 0xAB, 0xBC, 0xCD, 0xDC, 0xDC, 0xCB, 0xBA, 0xAA, + 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xED, 0xAC, 0xBB, 0xBA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xBB, 0xCC, 0xDE, 0xD0, 0x00, 0x00, 0x00, + }, + { + 0xBC, 0xBA, 0xBA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0x8C, 0xCC, + 0xBB, 0xBA, 0xAA, 0xAA, 0xBB, 0xBB, 0xCD, 0xDC, 0xDB, 0xBC, 0xBC, 0xA9, + 0x99, 0x99, 0x99, 0x9A, 0xAA, 0xBB, 0xCC, 0xAB, 0xCA, 0xAA, 0x98, 0x88, + 0x88, 0x89, 0x99, 0xAA, 0xCC, 0xBA, 0xBB, 0xA9, 0x98, 0x88, 0x78, 0x88, + 0x88, 0x99, 0xAA, 0xBB, 0xAA, 0xAA, 0x98, 0x87, 0x77, 0x77, 0x77, 0x88, + 0x99, 0xAA, 0xBA, 0xBA, 0x98, 0x87, 0x76, 0x66, 0x67, 0x77, 0x88, 0x9A, + 0xBA, 0xAA, 0xA9, 0x88, 0x76, 0x66, 0x66, 0x66, 0x77, 0x88, 0xAA, 0xAA, + 0xAA, 0x98, 0x87, 0x66, 0x55, 0x56, 0x67, 0x78, 0x99, 0xAA, 0xAA, 0xA9, + 0x88, 0x76, 0x65, 0x44, 0x56, 0x67, 0x88, 0x9A, 0xAA, 0x9A, 0x98, 0x87, + 0x66, 0x54, 0x45, 0x66, 0x78, 0x89, 0xAB, 0xAA, 0xB9, 0x98, 0x76, 0x66, + 0x55, 0x56, 0x67, 0x88, 0x9A, 0xBA, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x66, + 0x66, 0x78, 0x99, 0xAB, 0xBA, 0xAA, 0x98, 0x87, 0x77, 0x66, 0x66, 0x77, + 0x89, 0x9A, 0xBB, 0xAB, 0xA9, 0x98, 0x87, 0x77, 0x77, 0x77, 0x89, 0x9A, + 0xBB, 0xAB, 0xDA, 0xA9, 0x98, 0x88, 0x77, 0x88, 0x88, 0x9A, 0xAC, 0xBB, + 0xBC, 0xAB, 0xA9, 0x99, 0x98, 0x88, 0x89, 0x9A, 0xAA, 0xBD, 0xCB, 0xBB, + 0xBB, 0xA9, 0xA9, 0x99, 0x99, 0xAA, 0xAC, 0xBC, 0xCC, 0xBC, 0xCC, 0xBA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xBC, 0xCD, 0xCB, 0xCD, 0xBB, 0xCB, 0xBA, + 0xBB, 0xBB, 0xAC, 0xBB, 0xDD, 0xDD, 0x7A, 0xAA, 0xAA, 0xBA, 0xAA, 0xAA, + 0xAB, 0xBB, 0xBB, 0xCD, 0xB0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBF, 0xDF, 0xBB, 0xAB, 0xBF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xCC, 0xFD, 0xFF, 0xDF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xBB, 0xDF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xBF, + 0xCF, 0xBF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFD, 0xFF, 0xBB, 0xBA, 0xAB, 0xFC, + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, 0xCA, 0x99, 0x99, 0xAC, 0xDF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xCD, 0xBA, 0x87, 0x77, 0x89, 0x9B, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xCB, 0x97, 0x54, 0x46, 0x8A, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, + 0xCD, 0xA9, 0x64, 0x12, 0x57, 0x9B, 0xBF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBA, + 0x97, 0x52, 0x24, 0x79, 0xAB, 0xCF, 0xFF, 0xFF, 0xFF, 0xFC, 0xA9, 0x86, + 0x54, 0x57, 0x9B, 0xFD, 0xFF, 0xFD, 0xFF, 0xFC, 0xCC, 0xA9, 0x87, 0x77, + 0x8A, 0xAC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0x99, 0x99, 0x9A, 0xAF, + 0xCF, 0xFF, 0xFF, 0xDF, 0xFF, 0xBF, 0xAC, 0xBA, 0xAA, 0xCC, 0xBF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFF, 0xCB, 0xBC, 0xBB, 0xDF, 0xDD, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xDF, 0xFC, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xFD, 0xDF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFD, + 0xDF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0xCF, 0xDF, 0xDF, 0xFF, 0xCF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xAF, 0xFF, 0xBF, 0xAB, 0xFB, 0x9F, 0xBB, 0xAB, 0x6B, 0xFF, + 0xFB, 0xFF, 0xAF, 0xAA, 0xFB, 0xFA, 0xBB, 0xFF, 0xFF, 0xFF, 0xFB, 0xBF, + 0xB9, 0xFB, 0xBA, 0xBB, 0xBF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFA, 0xFB, 0xBB, + 0xAA, 0xFF, 0xFA, 0xBF, 0xBF, 0xFF, 0xBF, 0xFA, 0xAF, 0xBB, 0x99, 0x9A, + 0xA9, 0xBF, 0xFB, 0xFB, 0xAB, 0xFB, 0xBA, 0xA9, 0x98, 0x9A, 0x99, 0xAA, + 0xFB, 0xBB, 0xFF, 0xAF, 0xFA, 0xAA, 0x98, 0x78, 0x78, 0x89, 0xAF, 0xBF, + 0xAF, 0xFB, 0xBF, 0xBA, 0x99, 0x76, 0x66, 0x88, 0x99, 0xBF, 0xFF, 0xBF, + 0xFF, 0xFA, 0x98, 0x77, 0x54, 0x56, 0x79, 0x9B, 0xBF, 0xBB, 0xBB, 0xAF, + 0xAB, 0xA8, 0x64, 0x22, 0x57, 0x88, 0x9A, 0xFF, 0xAB, 0xAF, 0x99, 0xB8, + 0x77, 0x52, 0x25, 0x79, 0xA9, 0xAA, 0xFF, 0xFA, 0xBB, 0xBA, 0x98, 0x76, + 0x54, 0x66, 0x78, 0x99, 0xBF, 0xFB, 0x9F, 0xFA, 0x9A, 0x98, 0x76, 0x66, + 0x78, 0x8A, 0xFA, 0xAB, 0xAF, 0xFB, 0xBA, 0xB8, 0x98, 0x88, 0x78, 0x9A, + 0xAB, 0xFF, 0xFB, 0xAF, 0xBF, 0xBA, 0xAA, 0x99, 0xA9, 0x9F, 0x8A, 0xFA, + 0xFF, 0xAA, 0xFF, 0xBB, 0xAF, 0xA9, 0xA8, 0x89, 0xAB, 0xFA, 0xBB, 0xFF, + 0xFB, 0xFF, 0xFF, 0xFB, 0xA9, 0xAB, 0xAF, 0xBF, 0xBB, 0xBB, 0xBB, 0xFF, + 0xBF, 0xFB, 0xFF, 0xFA, 0xBF, 0xAF, 0xAF, 0xFB, 0xFF, 0xAF, 0xBF, 0xFF, + 0xFF, 0xBB, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFB, 0xFF, 0xFB, 0xFF, 0xFF, 0xFB, 0x6F, 0xAA, 0xAB, 0xAB, 0xBA, 0xFA, + 0xFA, 0xBB, 0xFF, 0xFB, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xDE, 0xFF, 0xFF, 0xFF, 0xDC, 0xCC, 0xCF, 0xCD, 0xCF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFD, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xDC, + 0xFC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xCC, 0xDC, 0xDD, + 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xEB, 0xBA, 0xBB, 0xBC, 0xDD, 0xFD, + 0xDF, 0xFC, 0xFF, 0xDD, 0xCB, 0x98, 0x78, 0x9A, 0xCC, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xFD, 0xB8, 0x54, 0x46, 0x9B, 0xCD, 0xDF, 0xFF, 0xFF, 0xFF, + 0xCD, 0xDA, 0x74, 0x22, 0x48, 0xAC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0xA7, 0x42, 0x14, 0x7A, 0xDF, 0xFF, 0xFF, 0xDD, 0xFF, 0xFD, 0xDA, 0x96, + 0x44, 0x58, 0xBC, 0xFD, 0xFF, 0xFF, 0xFF, 0xDF, 0xFC, 0xDA, 0x97, 0x78, + 0xAC, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xCA, 0xAA, 0xAB, 0xCF, + 0xFF, 0xFD, 0xFF, 0xDF, 0xFF, 0xFD, 0xFC, 0xDC, 0xBC, 0xCD, 0xDF, 0xDF, + 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, 0xDF, 0xCC, 0xFD, 0xFD, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xDF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDD, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xDF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6B, 0xDD, 0xCD, 0xDD, 0xFF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xDD, 0xDD, 0xCD, 0xDD, 0xDE, 0xDF, 0xFF, 0xCF, 0xFF, + 0xFF, 0xDC, 0xCC, 0xCB, 0xCC, 0xBD, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xDC, + 0xBB, 0xBA, 0xAA, 0xBB, 0xCC, 0xDF, 0xEF, 0xFF, 0xFD, 0xCC, 0xBA, 0x99, + 0x99, 0x99, 0xAA, 0xBC, 0xDF, 0xFF, 0xFE, 0xDC, 0xAA, 0x98, 0x88, 0x88, + 0x89, 0xAB, 0xBC, 0xDE, 0xFF, 0xDC, 0xB9, 0x98, 0x77, 0x77, 0x77, 0x89, + 0xAA, 0xCC, 0xFF, 0xFC, 0xCA, 0x98, 0x76, 0x66, 0x66, 0x77, 0x89, 0xAB, + 0xCD, 0xFE, 0xCB, 0xA8, 0x76, 0x65, 0x55, 0x56, 0x77, 0x99, 0xBC, 0xDE, + 0xDC, 0xB9, 0x87, 0x65, 0x55, 0x55, 0x66, 0x78, 0x9A, 0xCD, 0xDC, 0xCA, + 0x98, 0x76, 0x55, 0x44, 0x55, 0x67, 0x89, 0xAB, 0xDD, 0xCC, 0xA9, 0x87, + 0x65, 0x54, 0x45, 0x56, 0x78, 0x9A, 0xCD, 0xEC, 0xCA, 0x98, 0x76, 0x55, + 0x55, 0x55, 0x67, 0x89, 0xAB, 0xDF, 0xCC, 0xB9, 0x87, 0x76, 0x55, 0x55, + 0x66, 0x78, 0xAB, 0xCF, 0xFD, 0xCB, 0xA9, 0x87, 0x76, 0x66, 0x66, 0x78, + 0x9A, 0xBC, 0xFF, 0xDD, 0xCA, 0xA9, 0x87, 0x77, 0x77, 0x78, 0x9A, 0xBC, + 0xDF, 0xFD, 0xDC, 0xBA, 0xA9, 0x88, 0x88, 0x88, 0x9A, 0xAC, 0xDF, 0xFF, + 0xFF, 0xDC, 0xBA, 0xA9, 0x99, 0x99, 0xAA, 0xBB, 0xDF, 0xFF, 0xFF, 0xFF, + 0xDD, 0xCB, 0xBA, 0xAA, 0xAB, 0xBC, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDC, + 0xDC, 0xCC, 0xCC, 0xCD, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xDD, + 0xDD, 0xDE, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFE, 0xFE, 0xDD, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xCF, 0xFE, 0xFD, 0xDC, 0xCF, 0xFD, 0xED, 0xCC, 0xBC, 0xEC, 0x7F, 0xEF, + 0xFF, 0xEF, 0xEF, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xDF, 0xDD, 0xFF, + 0xDD, 0xFD, 0xEF, 0xEF, 0xEE, 0xEF, 0xFF, 0xCF, 0xEF, 0xFF, 0xDF, 0xEF, + 0xDF, 0xDE, 0xEF, 0xEF, 0xFF, 0xFD, 0xEE, 0xFD, 0xFD, 0xDD, 0xDD, 0xCC, + 0xDD, 0xEE, 0xFE, 0xFD, 0xED, 0xFF, 0xEE, 0xDC, 0xCC, 0xBC, 0xBC, 0xCE, + 0xED, 0xFF, 0xFE, 0xEF, 0xCD, 0xFF, 0xBB, 0xAA, 0xAA, 0xBC, 0xDD, 0xEE, + 0xFF, 0xFF, 0xFF, 0xFC, 0xCB, 0x98, 0x77, 0x89, 0xBC, 0xDE, 0xFF, 0xFD, + 0xDE, 0xDF, 0xDC, 0xA8, 0x54, 0x46, 0x8A, 0xCF, 0xEF, 0xEF, 0xDC, 0xFF, + 0xDC, 0xCA, 0x74, 0x12, 0x47, 0xAC, 0xED, 0xEE, 0xFE, 0xEE, 0xEF, 0xFB, + 0xA7, 0x42, 0x24, 0x7A, 0xBD, 0xEE, 0xEF, 0xDE, 0xED, 0xDE, 0xCA, 0x86, + 0x44, 0x68, 0xAD, 0xDD, 0xEE, 0xFD, 0xDE, 0xEE, 0xFC, 0xB9, 0x87, 0x78, + 0xAB, 0xCF, 0xDD, 0xFF, 0xFD, 0xFF, 0xFC, 0xCC, 0xBA, 0x9A, 0xAB, 0xBE, + 0xEF, 0xEF, 0xFD, 0xDF, 0xFF, 0xFD, 0xCC, 0xCC, 0xCC, 0xDC, 0xCD, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFE, 0xDE, 0xDD, 0xCC, 0xFD, 0xEF, 0xDF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xED, 0xDD, 0xDD, 0xEF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, + 0xFE, 0xFF, 0xED, 0xFE, 0xFE, 0xFF, 0xEF, 0xFF, 0xFF, 0xCE, 0xEF, 0xFF, + 0xFF, 0xFD, 0xDE, 0xFF, 0xEF, 0xFF, 0xFF, 0xFD, 0xFF, 0xEF, 0xFE, 0xEE, + 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0xDD, 0xCC, 0xCC, 0xCE, 0xCE, + 0xCE, 0xED, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x8F, 0xF8, 0xF8, 0xF9, 0xF8, 0x5F, 0xFF, + 0xF9, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, + 0xF8, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, + 0x88, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFE, 0x8F, 0x8F, + 0x8F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x78, 0xFF, 0xFF, + 0xF8, 0x8F, 0xFF, 0xFF, 0xFF, 0xF9, 0x8F, 0xF8, 0xF9, 0xF9, 0x8F, 0xFF, + 0x8F, 0x8F, 0xF8, 0x89, 0x8F, 0x68, 0x68, 0x88, 0x88, 0xF8, 0xFF, 0xFF, + 0xFF, 0xF8, 0x88, 0x78, 0x64, 0x56, 0xFF, 0x8F, 0xF8, 0xFF, 0xFF, 0xF8, + 0xFF, 0x88, 0x64, 0x22, 0x48, 0x88, 0x8F, 0xFF, 0xFF, 0xE9, 0x8F, 0xFF, + 0xF7, 0x52, 0x25, 0x78, 0x8F, 0xF8, 0xFF, 0xFF, 0x9F, 0xFF, 0xF8, 0x87, + 0x44, 0x58, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x8F, 0xF7, 0x76, + 0x88, 0xF9, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0x79, 0x88, 0xF9, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF8, 0xFF, 0xFF, 0x98, 0xFF, 0xFF, 0x8F, 0xF9, 0xFF, 0x8F, 0xFF, 0xFF, + 0x8F, 0xFF, 0xFF, 0xF8, 0xFF, 0x98, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x8F, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFF, 0x8F, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0x99, 0xFF, 0xCF, 0xF8, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x7F, 0x87, 0x87, 0x66, 0x68, 0x87, 0x77, 0x77, 0x68, 0xFF, 0x57, 0xFF, + 0x88, 0xFF, 0x88, 0x88, 0x8F, 0x88, 0xFF, 0xFF, 0xF8, 0x6F, 0xF7, 0x78, + 0xF8, 0x8F, 0x87, 0x78, 0x87, 0xFF, 0xF7, 0x87, 0xF7, 0xF8, 0x7F, 0xF8, + 0x88, 0x88, 0x87, 0x88, 0x8F, 0x87, 0xF8, 0x88, 0xF7, 0xF7, 0xFF, 0x8F, + 0x88, 0x7F, 0x8F, 0xF8, 0xF7, 0x8F, 0x8F, 0xF7, 0x77, 0xF7, 0x68, 0x8F, + 0x8F, 0xFF, 0xF7, 0x69, 0x8F, 0x88, 0x76, 0x78, 0x6F, 0x77, 0x6F, 0xFF, + 0x7F, 0x88, 0xF8, 0x8F, 0xF7, 0x87, 0x88, 0xF7, 0x7F, 0xF8, 0x8F, 0x77, + 0x68, 0x87, 0xF7, 0x86, 0x87, 0x67, 0x67, 0x7F, 0x78, 0xF8, 0x77, 0x77, + 0x88, 0x67, 0xF7, 0x76, 0x88, 0x78, 0x77, 0xFF, 0x8F, 0x7F, 0x88, 0x87, + 0x67, 0x67, 0x77, 0x77, 0x78, 0x8F, 0x7F, 0x77, 0x7F, 0x87, 0x76, 0x68, + 0x87, 0x77, 0x67, 0x7F, 0x7E, 0xE8, 0xCB, 0x88, 0x7F, 0xF7, 0x77, 0x87, + 0x6F, 0x8F, 0x87, 0x7F, 0x68, 0x88, 0xF7, 0x88, 0xF7, 0xF6, 0x87, 0xF8, + 0x87, 0xFF, 0xF7, 0x88, 0xF8, 0x8F, 0x8F, 0xF7, 0x88, 0x7F, 0xFF, 0x8F, + 0xFF, 0x77, 0xF8, 0x88, 0x78, 0x8F, 0xF7, 0x78, 0x77, 0x88, 0x8F, 0xF7, + 0x8F, 0xF8, 0xFF, 0xF8, 0x8F, 0x88, 0x78, 0x77, 0x7F, 0xF8, 0x78, 0xF8, + 0x88, 0x88, 0x7F, 0x8F, 0x7F, 0x8F, 0xA7, 0x78, 0x7F, 0xFF, 0xFF, 0x87, + 0x8F, 0x78, 0x87, 0x8F, 0x8F, 0x87, 0x8F, 0x77, 0xF8, 0xF7, 0x88, 0x8F, + 0x8F, 0xFF, 0xF8, 0x87, 0x7F, 0xF8, 0x8F, 0x87, 0x8F, 0x87, 0x78, 0x7F, + 0xF7, 0x77, 0x78, 0xF8, 0x70, 0x00, 0x00, 0x00, + }, + { + 0x57, 0x78, 0x66, 0x77, 0x66, 0x76, 0x77, 0x76, 0x87, 0x79, 0x68, 0xAD, + 0x98, 0x89, 0x98, 0xDA, 0xB9, 0x99, 0x99, 0x9D, 0x98, 0x79, 0xAA, 0x89, + 0x98, 0x88, 0x88, 0x98, 0xAA, 0x88, 0x9A, 0x87, 0x89, 0xA9, 0x99, 0x89, + 0x98, 0x98, 0x99, 0x89, 0xA9, 0x99, 0x7A, 0x88, 0x79, 0x98, 0x88, 0x87, + 0x87, 0x98, 0x88, 0x9A, 0x76, 0x98, 0x77, 0x88, 0x87, 0x97, 0x88, 0x98, + 0x98, 0x99, 0x88, 0x79, 0x89, 0x99, 0x78, 0x87, 0x88, 0x88, 0x89, 0xA9, + 0x98, 0x87, 0x99, 0x87, 0x78, 0x78, 0x87, 0x87, 0x87, 0x97, 0x99, 0x97, + 0x79, 0x98, 0x98, 0x78, 0x87, 0x98, 0x87, 0x78, 0x88, 0x9A, 0x76, 0x99, + 0x77, 0x78, 0x78, 0x77, 0x87, 0x78, 0x88, 0x99, 0xA7, 0x79, 0x88, 0x89, + 0x87, 0x77, 0x87, 0x88, 0x78, 0x88, 0x89, 0x77, 0x88, 0x97, 0x88, 0x87, + 0x87, 0x67, 0x88, 0x89, 0x89, 0x88, 0x79, 0x89, 0x88, 0x78, 0x87, 0x77, + 0x77, 0x78, 0x89, 0x8A, 0x76, 0x89, 0x97, 0x77, 0x97, 0x87, 0x77, 0x99, + 0x89, 0x99, 0x96, 0x6A, 0xA8, 0x88, 0x88, 0x88, 0x89, 0x87, 0x88, 0x88, + 0x99, 0x87, 0x9A, 0xA8, 0x88, 0x98, 0x78, 0x88, 0x88, 0x88, 0x99, 0x98, + 0x79, 0x99, 0x88, 0x88, 0x98, 0x88, 0x87, 0x88, 0x88, 0xA9, 0x78, 0xAA, + 0x98, 0x98, 0xA8, 0x88, 0x88, 0x88, 0x88, 0x88, 0xA7, 0x8A, 0x98, 0x89, + 0x8A, 0x88, 0x88, 0x9A, 0x89, 0x89, 0x99, 0x78, 0xA9, 0x99, 0xD8, 0x89, + 0x98, 0x8A, 0x89, 0x98, 0xAA, 0x87, 0x69, 0x88, 0x87, 0x87, 0x78, 0x77, + 0x67, 0x87, 0x77, 0x79, 0x50, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAB, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF5, 0x12, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x61, 0x15, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, + 0x65, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0xAF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xBB, 0xFF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFB, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA9, 0x99, 0xBF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x66, 0x88, 0xBF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFB, 0xB7, 0x53, 0x45, 0x7A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0x63, 0x22, 0x46, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x96, 0x42, 0x24, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA, 0x85, + 0x44, 0x57, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x86, 0x67, + 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF9, 0x99, 0xBF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xBB, 0xBF, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF6, 0x12, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF3, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, + 0xBC, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xE5, 0xEF, 0xFF, 0xFF, 0x3F, 0xFF, + 0xEE, 0xEE, 0xE5, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x5E, + 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xF4, 0x5F, 0x5F, 0xFF, 0xF5, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x55, 0x5F, 0x5F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x5F, 0x4F, 0xFF, 0x54, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEE, 0xEE, 0x4E, 0xE5, 0xE6, 0xEE, 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xE5, + 0xE5, 0xE5, 0xEE, 0x5E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x5E, + 0xEE, 0x44, 0xEE, 0xEE, 0xEE, 0xEE, 0x5E, 0xEF, 0xFF, 0xF5, 0x45, 0x3F, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0x4F, 0x4F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x5F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFE, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xAF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFA, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, + 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0x99, 0x9B, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x67, 0x7F, 0xAB, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xA7, 0x54, 0x45, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x64, 0x22, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xA6, 0x42, 0x23, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x75, + 0x43, 0x57, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x77, 0x67, + 0x9A, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xBA, 0xAA, 0xAF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x99, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0x65, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, + 0xFF, 0xFF, 0x94, 0x12, 0x59, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF9, 0x52, 0x14, 0x9D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, + 0x54, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, + 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFA, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x9F, 0xFF, 0xBF, 0xFB, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAF, 0xFF, 0xA9, 0xAA, 0xFF, 0x5F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, + 0xAF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFA, 0xFF, 0xAF, 0xFF, 0xAF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xA8, 0xA7, 0x67, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xD7, 0x53, 0x45, 0x7A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x64, 0x22, 0x47, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xF9, + 0x97, 0x42, 0x24, 0x68, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x76, + 0x44, 0x58, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x76, 0x67, + 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA9, 0xAF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0xAF, 0xFF, 0xFA, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFA, 0xFA, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xA9, 0xAF, 0xFF, 0xFA, 0x9F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x5F, 0xEF, 0x56, 0x6F, 0xF6, 0x66, 0xEE, 0xEF, 0x6F, 0xFF, 0x56, 0xE6, + 0xE6, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, 0xE6, 0xEE, + 0xEE, 0xEE, 0xE6, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xFF, 0xFF, 0x6F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEE, 0xEE, 0xE6, 0xEE, 0xEE, 0x6E, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x6E, 0x4E, 0x6E, 0xEE, 0xEE, 0xEE, + 0xE6, 0xEE, 0xEE, 0xEF, 0xF6, 0xF5, 0x6F, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xF4, 0x6F, 0x6F, 0xFF, 0xFF, 0xFF, 0xFE, + 0xEE, 0xE5, 0xE6, 0x66, 0x65, 0x6E, 0xE5, 0xEE, 0xE6, 0xEE, 0xEE, 0xEE, + 0xEE, 0xE5, 0x56, 0x45, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xE6, 0xE6, 0x65, 0x65, 0xEE, 0xEE, 0xEE, 0xE6, 0xEE, 0xEE, 0xE6, 0x66, + 0x6E, 0x6E, 0xEE, 0xEE, 0xE6, 0xEE, 0x6E, 0xEF, 0xF6, 0xF6, 0xFF, 0x56, + 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x6F, + 0x66, 0xF5, 0xF6, 0xFF, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xF5, 0xF6, 0xFF, 0x6F, 0xFE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE6, 0xEE, 0xEE, 0xFE, 0x6E, 0xFE, + 0xFF, 0xFE, 0xFF, 0x6E, 0xF6, 0xFE, 0xFF, 0x66, 0xFF, 0xFE, 0xFF, 0xFE, + 0xEF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x5F, 0xFF, 0xFE, 0xFF, 0xFF, 0x5F, 0xFF, 0x65, 0x6F, 0xF6, 0xFE, + 0x66, 0xFE, 0x66, 0x5E, 0x50, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xA8, 0xFF, 0xFF, 0xF7, 0xFF, 0x3F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x76, 0x77, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x86, 0x54, 0x45, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF9, 0x64, 0x22, 0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF6, 0x42, 0x24, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF5, + 0x44, 0x5B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xF6, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x7F, 0x8F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xEE, 0xED, 0xD5, 0xEE, 0xEE, 0x3E, 0xEE, + 0xEE, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xE4, 0x21, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xDD, + 0xDD, 0xD1, 0x1D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xED, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x75, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF4, 0x12, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x42, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x54, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFC, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x67, 0xAF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF6, 0x44, 0x45, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF6, 0x54, 0x22, 0x46, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF5, 0x42, 0x34, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x75, + 0x43, 0x4F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x56, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, + }, + { + 0xEE, 0xEE, 0xEE, 0xDE, 0xEE, 0xEE, 0xED, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0x53, 0x4E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xE5, 0x12, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, 0xDD, 0xDD, 0xDD, + 0xDD, 0xD2, 0x24, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xD3, 0x3D, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x3E, 0xE5, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xED, 0xE0, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + { + 0x88, 0x88, 0x88, 0x78, 0x88, 0x88, 0x87, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x80, 0x00, 0x00, 0x00, + }, + }, +}; + +#endif /* AVCODEC_RALFDATA_H */ diff --git a/ffmpeg/libavcodec/rangecoder.c b/ffmpeg/libavcodec/rangecoder.c new file mode 100644 index 0000000..7d2d14d --- /dev/null +++ b/ffmpeg/libavcodec/rangecoder.c @@ -0,0 +1,157 @@ +/* + * Range coder + * Copyright (c) 2004 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 + */ + +/** + * @file + * Range coder. + * based upon + * "Range encoding: an algorithm for removing redundancy from a digitised + * message. + * G. N. N. Martin Presented in March 1979 to the Video & + * Data Recording Conference, + * IBM UK Scientific Center held in Southampton July 24-27 1979." + * + */ + +#include + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "rangecoder.h" +#include "bytestream.h" + +void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size) +{ + c->bytestream_start = + c->bytestream = buf; + c->bytestream_end = buf + buf_size; + c->low = 0; + c->range = 0xFF00; + c->outstanding_count = 0; + c->outstanding_byte = -1; +} + +void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, int buf_size) +{ + /* cast to avoid compiler warning */ + ff_init_range_encoder(c, (uint8_t *)buf, buf_size); + + c->low = bytestream_get_be16((const uint8_t **)&c->bytestream); +} + +void ff_build_rac_states(RangeCoder *c, int factor, int max_p) +{ + const int64_t one = 1LL << 32; + int64_t p; + int last_p8, p8, i; + + memset(c->zero_state, 0, sizeof(c->zero_state)); + memset(c->one_state, 0, sizeof(c->one_state)); + + last_p8 = 0; + p = one / 2; + for (i = 0; i < 128; i++) { + p8 = (256 * p + one / 2) >> 32; // FIXME: try without the one + if (p8 <= last_p8) + p8 = last_p8 + 1; + if (last_p8 && last_p8 < 256 && p8 <= max_p) + c->one_state[last_p8] = p8; + + p += ((one - p) * factor + one / 2) >> 32; + last_p8 = p8; + } + + for (i = 256 - max_p; i <= max_p; i++) { + if (c->one_state[i]) + continue; + + p = (i * one + 128) >> 8; + p += ((one - p) * factor + one / 2) >> 32; + p8 = (256 * p + one / 2) >> 32; // FIXME: try without the one + if (p8 <= i) + p8 = i + 1; + if (p8 > max_p) + p8 = max_p; + c->one_state[i] = p8; + } + + for (i = 1; i < 255; i++) + c->zero_state[i] = 256 - c->one_state[256 - i]; +} + +/* Return the number of bytes written. */ +int ff_rac_terminate(RangeCoder *c) +{ + c->range = 0xFF; + c->low += 0xFF; + renorm_encoder(c); + c->range = 0xFF; + renorm_encoder(c); + + av_assert1(c->low == 0); + av_assert1(c->range >= 0x100); + + return c->bytestream - c->bytestream_start; +} + +#ifdef TEST +#define SIZE 10240 + +#include "libavutil/lfg.h" +#include "libavutil/log.h" + +int main(void) +{ + RangeCoder c; + uint8_t b[9 * SIZE]; + uint8_t r[9 * SIZE]; + int i; + uint8_t state[10]; + AVLFG prng; + + av_lfg_init(&prng, 1); + + ff_init_range_encoder(&c, b, SIZE); + ff_build_rac_states(&c, 0.05 * (1LL << 32), 128 + 64 + 32 + 16); + + memset(state, 128, sizeof(state)); + + for (i = 0; i < SIZE; i++) + r[i] = av_lfg_get(&prng) % 7; + + for (i = 0; i < SIZE; i++) + put_rac(&c, state, r[i] & 1); + + ff_rac_terminate(&c); + + ff_init_range_decoder(&c, b, SIZE); + + memset(state, 128, sizeof(state)); + + for (i = 0; i < SIZE; i++) + if ((r[i] & 1) != get_rac(&c, state)) { + av_log(NULL, AV_LOG_ERROR, "rac failure at %d\n", i); + return 1; + } + + return 0; +} +#endif /* TEST */ diff --git a/ffmpeg/libavcodec/rangecoder.h b/ffmpeg/libavcodec/rangecoder.h new file mode 100644 index 0000000..88e555f --- /dev/null +++ b/ffmpeg/libavcodec/rangecoder.h @@ -0,0 +1,147 @@ +/* + * Range coder + * Copyright (c) 2004 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 + */ + +/** + * @file + * Range coder. + */ + +#ifndef AVCODEC_RANGECODER_H +#define AVCODEC_RANGECODER_H + +#include + +#include "libavutil/common.h" +#include "libavutil/avassert.h" + +typedef struct RangeCoder { + int low; + int range; + int outstanding_count; + int outstanding_byte; + uint8_t zero_state[256]; + uint8_t one_state[256]; + uint8_t *bytestream_start; + uint8_t *bytestream; + uint8_t *bytestream_end; +} RangeCoder; + +void ff_init_range_encoder(RangeCoder *c, uint8_t *buf, int buf_size); +void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf, int buf_size); +int ff_rac_terminate(RangeCoder *c); +void ff_build_rac_states(RangeCoder *c, int factor, int max_p); + +static inline void renorm_encoder(RangeCoder *c) +{ + // FIXME: optimize + while (c->range < 0x100) { + if (c->outstanding_byte < 0) { + c->outstanding_byte = c->low >> 8; + } else if (c->low <= 0xFF00) { + *c->bytestream++ = c->outstanding_byte; + for (; c->outstanding_count; c->outstanding_count--) + *c->bytestream++ = 0xFF; + c->outstanding_byte = c->low >> 8; + } else if (c->low >= 0x10000) { + *c->bytestream++ = c->outstanding_byte + 1; + for (; c->outstanding_count; c->outstanding_count--) + *c->bytestream++ = 0x00; + c->outstanding_byte = (c->low >> 8) & 0xFF; + } else { + c->outstanding_count++; + } + + c->low = (c->low & 0xFF) << 8; + c->range <<= 8; + } +} + +static inline int get_rac_count(RangeCoder *c) +{ + int x = c->bytestream - c->bytestream_start + c->outstanding_count; + if (c->outstanding_byte >= 0) + x++; + return 8 * x - av_log2(c->range); +} + +static inline void put_rac(RangeCoder *c, uint8_t *const state, int bit) +{ + int range1 = (c->range * (*state)) >> 8; + + av_assert2(*state); + av_assert2(range1 < c->range); + av_assert2(range1 > 0); + if (!bit) { + c->range -= range1; + *state = c->zero_state[*state]; + } else { + c->low += c->range - range1; + c->range = range1; + *state = c->one_state[*state]; + } + + renorm_encoder(c); +} + +static inline void refill(RangeCoder *c) +{ + if (c->range < 0x100) { + c->range <<= 8; + c->low <<= 8; + if (c->bytestream < c->bytestream_end) + c->low += c->bytestream[0]; + c->bytestream++; + } +} + +static inline int get_rac(RangeCoder *c, uint8_t *const state) +{ + int range1 = (c->range * (*state)) >> 8; + int av_unused one_mask; + + c->range -= range1; +#if 1 + if (c->low < c->range) { + *state = c->zero_state[*state]; + refill(c); + return 0; + } else { + c->low -= c->range; + *state = c->one_state[*state]; + c->range = range1; + refill(c); + return 1; + } +#else + one_mask = (c->range - c->low - 1) >> 31; + + c->low -= c->range & one_mask; + c->range += (range1 - c->range) & one_mask; + + *state = c->zero_state[(*state) + (256 & one_mask)]; + + refill(c); + + return one_mask & 1; +#endif +} + +#endif /* AVCODEC_RANGECODER_H */ diff --git a/ffmpeg/libavcodec/ratecontrol.c b/ffmpeg/libavcodec/ratecontrol.c new file mode 100644 index 0000000..5860423 --- /dev/null +++ b/ffmpeg/libavcodec/ratecontrol.c @@ -0,0 +1,1062 @@ +/* + * Rate control for video encoders + * + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * Rate control for video encoders. + */ + +#include "avcodec.h" +#include "ratecontrol.h" +#include "mpegvideo.h" +#include "libavutil/eval.h" + +#undef NDEBUG // Always check asserts, the speed effect is far too small to disable them. +#include + +#ifndef M_E +#define M_E 2.718281828 +#endif + +static int init_pass2(MpegEncContext *s); +static double get_qscale(MpegEncContext *s, RateControlEntry *rce, + double rate_factor, int frame_num); + +void ff_write_pass1_stats(MpegEncContext *s) +{ + snprintf(s->avctx->stats_out, 256, + "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d " + "fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d;\n", + s->current_picture_ptr->f.display_picture_number, + s->current_picture_ptr->f.coded_picture_number, + s->pict_type, + s->current_picture.f.quality, + s->i_tex_bits, + s->p_tex_bits, + s->mv_bits, + s->misc_bits, + s->f_code, + s->b_code, + s->current_picture.mc_mb_var_sum, + s->current_picture.mb_var_sum, + s->i_count, s->skip_count, + s->header_bits); +} + +static double get_fps(AVCodecContext *avctx) +{ + return 1.0 / av_q2d(avctx->time_base) / FFMAX(avctx->ticks_per_frame, 1); +} + +static inline double qp2bits(RateControlEntry *rce, double qp) +{ + if (qp <= 0.0) { + av_log(NULL, AV_LOG_ERROR, "qp<=0.0\n"); + } + return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits + 1) / qp; +} + +static inline double bits2qp(RateControlEntry *rce, double bits) +{ + if (bits < 0.9) { + av_log(NULL, AV_LOG_ERROR, "bits<0.9\n"); + } + return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits + 1) / bits; +} + +int ff_rate_control_init(MpegEncContext *s) +{ + RateControlContext *rcc = &s->rc_context; + int i, res; + static const char * const const_names[] = { + "PI", + "E", + "iTex", + "pTex", + "tex", + "mv", + "fCode", + "iCount", + "mcVar", + "var", + "isI", + "isP", + "isB", + "avgQP", + "qComp", +#if 0 + "lastIQP", + "lastPQP", + "lastBQP", + "nextNonBQP", +#endif + "avgIITex", + "avgPITex", + "avgPPTex", + "avgBPTex", + "avgTex", + NULL + }; + static double (* const func1[])(void *, double) = { + (void *)bits2qp, + (void *)qp2bits, + NULL + }; + static const char * const func1_names[] = { + "bits2qp", + "qp2bits", + NULL + }; + emms_c(); + + if (!s->avctx->rc_max_available_vbv_use && s->avctx->rc_buffer_size) { + if (s->avctx->rc_max_rate) { + s->avctx->rc_max_available_vbv_use = av_clipf(s->avctx->rc_max_rate/(s->avctx->rc_buffer_size*get_fps(s->avctx)), 1.0/3, 1.0); + } else + s->avctx->rc_max_available_vbv_use = 1.0; + } + + res = av_expr_parse(&rcc->rc_eq_eval, + s->avctx->rc_eq ? s->avctx->rc_eq : "tex^qComp", + const_names, func1_names, func1, + NULL, NULL, 0, s->avctx); + if (res < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error parsing rc_eq \"%s\"\n", s->avctx->rc_eq); + return res; + } + + for (i = 0; i < 5; i++) { + rcc->pred[i].coeff = FF_QP2LAMBDA * 7.0; + rcc->pred[i].count = 1.0; + rcc->pred[i].decay = 0.4; + + rcc->i_cplx_sum [i] = + rcc->p_cplx_sum [i] = + rcc->mv_bits_sum[i] = + rcc->qscale_sum [i] = + rcc->frame_count[i] = 1; // 1 is better because of 1/0 and such + + rcc->last_qscale_for[i] = FF_QP2LAMBDA * 5; + } + rcc->buffer_index = s->avctx->rc_initial_buffer_occupancy; + if (!rcc->buffer_index) + rcc->buffer_index = s->avctx->rc_buffer_size * 3 / 4; + + if (s->flags & CODEC_FLAG_PASS2) { + int i; + char *p; + + /* find number of pics */ + p = s->avctx->stats_in; + for (i = -1; p; i++) + p = strchr(p + 1, ';'); + i += s->max_b_frames; + if (i <= 0 || i >= INT_MAX / sizeof(RateControlEntry)) + return -1; + rcc->entry = av_mallocz(i * sizeof(RateControlEntry)); + rcc->num_entries = i; + + /* init all to skipped p frames + * (with b frames we might have a not encoded frame at the end FIXME) */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + + rce->pict_type = rce->new_pict_type = AV_PICTURE_TYPE_P; + rce->qscale = rce->new_qscale = FF_QP2LAMBDA * 2; + rce->misc_bits = s->mb_num + 10; + rce->mb_var_sum = s->mb_num * 100; + } + + /* read stats */ + p = s->avctx->stats_in; + for (i = 0; i < rcc->num_entries - s->max_b_frames; i++) { + RateControlEntry *rce; + int picture_number; + int e; + char *next; + + next = strchr(p, ';'); + if (next) { + (*next) = 0; // sscanf in unbelievably slow on looong strings // FIXME copy / do not write + next++; + } + e = sscanf(p, " in:%d ", &picture_number); + + assert(picture_number >= 0); + assert(picture_number < rcc->num_entries); + rce = &rcc->entry[picture_number]; + + e += sscanf(p, " in:%*d out:%*d type:%d q:%f itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d skipcount:%d hbits:%d", + &rce->pict_type, &rce->qscale, &rce->i_tex_bits, &rce->p_tex_bits, + &rce->mv_bits, &rce->misc_bits, + &rce->f_code, &rce->b_code, + &rce->mc_mb_var_sum, &rce->mb_var_sum, + &rce->i_count, &rce->skip_count, &rce->header_bits); + if (e != 14) { + av_log(s->avctx, AV_LOG_ERROR, + "statistics are damaged at line %d, parser out=%d\n", + i, e); + return -1; + } + + p = next; + } + + if (init_pass2(s) < 0) + return -1; + + // FIXME maybe move to end + if ((s->flags & CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) { +#if CONFIG_LIBXVID + return ff_xvid_rate_control_init(s); +#else + av_log(s->avctx, AV_LOG_ERROR, + "Xvid ratecontrol requires libavcodec compiled with Xvid support.\n"); + return -1; +#endif + } + } + + if (!(s->flags & CODEC_FLAG_PASS2)) { + rcc->short_term_qsum = 0.001; + rcc->short_term_qcount = 0.001; + + rcc->pass1_rc_eq_output_sum = 0.001; + rcc->pass1_wanted_bits = 0.001; + + if (s->avctx->qblur > 1.0) { + av_log(s->avctx, AV_LOG_ERROR, "qblur too large\n"); + return -1; + } + /* init stuff with the user specified complexity */ + if (s->avctx->rc_initial_cplx) { + for (i = 0; i < 60 * 30; i++) { + double bits = s->avctx->rc_initial_cplx * (i / 10000.0 + 1.0) * s->mb_num; + RateControlEntry rce; + + if (i % ((s->gop_size + 3) / 4) == 0) + rce.pict_type = AV_PICTURE_TYPE_I; + else if (i % (s->max_b_frames + 1)) + rce.pict_type = AV_PICTURE_TYPE_B; + else + rce.pict_type = AV_PICTURE_TYPE_P; + + rce.new_pict_type = rce.pict_type; + rce.mc_mb_var_sum = bits * s->mb_num / 100000; + rce.mb_var_sum = s->mb_num; + + rce.qscale = FF_QP2LAMBDA * 2; + rce.f_code = 2; + rce.b_code = 1; + rce.misc_bits = 1; + + if (s->pict_type == AV_PICTURE_TYPE_I) { + rce.i_count = s->mb_num; + rce.i_tex_bits = bits; + rce.p_tex_bits = 0; + rce.mv_bits = 0; + } else { + rce.i_count = 0; // FIXME we do know this approx + rce.i_tex_bits = 0; + rce.p_tex_bits = bits * 0.9; + rce.mv_bits = bits * 0.1; + } + rcc->i_cplx_sum[rce.pict_type] += rce.i_tex_bits * rce.qscale; + rcc->p_cplx_sum[rce.pict_type] += rce.p_tex_bits * rce.qscale; + rcc->mv_bits_sum[rce.pict_type] += rce.mv_bits; + rcc->frame_count[rce.pict_type]++; + + get_qscale(s, &rce, rcc->pass1_wanted_bits / rcc->pass1_rc_eq_output_sum, i); + + // FIXME misbehaves a little for variable fps + rcc->pass1_wanted_bits += s->bit_rate / get_fps(s->avctx); + } + } + } + + return 0; +} + +void ff_rate_control_uninit(MpegEncContext *s) +{ + RateControlContext *rcc = &s->rc_context; + emms_c(); + + av_expr_free(rcc->rc_eq_eval); + av_freep(&rcc->entry); + +#if CONFIG_LIBXVID + if ((s->flags & CODEC_FLAG_PASS2) && s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) + ff_xvid_rate_control_uninit(s); +#endif +} + +int ff_vbv_update(MpegEncContext *s, int frame_size) +{ + RateControlContext *rcc = &s->rc_context; + const double fps = get_fps(s->avctx); + const int buffer_size = s->avctx->rc_buffer_size; + const double min_rate = s->avctx->rc_min_rate / fps; + const double max_rate = s->avctx->rc_max_rate / fps; + + av_dlog(s, "%d %f %d %f %f\n", + buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate); + + if (buffer_size) { + int left; + + rcc->buffer_index -= frame_size; + if (rcc->buffer_index < 0) { + av_log(s->avctx, AV_LOG_ERROR, "rc buffer underflow\n"); + rcc->buffer_index = 0; + } + + left = buffer_size - rcc->buffer_index - 1; + rcc->buffer_index += av_clip(left, min_rate, max_rate); + + if (rcc->buffer_index > buffer_size) { + int stuffing = ceil((rcc->buffer_index - buffer_size) / 8); + + if (stuffing < 4 && s->codec_id == AV_CODEC_ID_MPEG4) + stuffing = 4; + rcc->buffer_index -= 8 * stuffing; + + if (s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing); + + return stuffing; + } + } + return 0; +} + +/** + * Modify the bitrate curve from pass1 for one frame. + */ +static double get_qscale(MpegEncContext *s, RateControlEntry *rce, + double rate_factor, int frame_num) +{ + RateControlContext *rcc = &s->rc_context; + AVCodecContext *a = s->avctx; + const int pict_type = rce->new_pict_type; + const double mb_num = s->mb_num; + double q, bits; + int i; + + double const_values[] = { + M_PI, + M_E, + rce->i_tex_bits * rce->qscale, + rce->p_tex_bits * rce->qscale, + (rce->i_tex_bits + rce->p_tex_bits) * (double)rce->qscale, + rce->mv_bits / mb_num, + rce->pict_type == AV_PICTURE_TYPE_B ? (rce->f_code + rce->b_code) * 0.5 : rce->f_code, + rce->i_count / mb_num, + rce->mc_mb_var_sum / mb_num, + rce->mb_var_sum / mb_num, + rce->pict_type == AV_PICTURE_TYPE_I, + rce->pict_type == AV_PICTURE_TYPE_P, + rce->pict_type == AV_PICTURE_TYPE_B, + rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type], + a->qcompress, +#if 0 + rcc->last_qscale_for[AV_PICTURE_TYPE_I], + rcc->last_qscale_for[AV_PICTURE_TYPE_P], + rcc->last_qscale_for[AV_PICTURE_TYPE_B], + rcc->next_non_b_qscale, +#endif + rcc->i_cplx_sum[AV_PICTURE_TYPE_I] / (double)rcc->frame_count[AV_PICTURE_TYPE_I], + rcc->i_cplx_sum[AV_PICTURE_TYPE_P] / (double)rcc->frame_count[AV_PICTURE_TYPE_P], + rcc->p_cplx_sum[AV_PICTURE_TYPE_P] / (double)rcc->frame_count[AV_PICTURE_TYPE_P], + rcc->p_cplx_sum[AV_PICTURE_TYPE_B] / (double)rcc->frame_count[AV_PICTURE_TYPE_B], + (rcc->i_cplx_sum[pict_type] + rcc->p_cplx_sum[pict_type]) / (double)rcc->frame_count[pict_type], + 0 + }; + + bits = av_expr_eval(rcc->rc_eq_eval, const_values, rce); + if (isnan(bits)) { + av_log(s->avctx, AV_LOG_ERROR, "Error evaluating rc_eq \"%s\"\n", s->avctx->rc_eq); + return -1; + } + + rcc->pass1_rc_eq_output_sum += bits; + bits *= rate_factor; + if (bits < 0.0) + bits = 0.0; + bits += 1.0; // avoid 1/0 issues + + /* user override */ + for (i = 0; i < s->avctx->rc_override_count; i++) { + RcOverride *rco = s->avctx->rc_override; + if (rco[i].start_frame > frame_num) + continue; + if (rco[i].end_frame < frame_num) + continue; + + if (rco[i].qscale) + bits = qp2bits(rce, rco[i].qscale); // FIXME move at end to really force it? + else + bits *= rco[i].quality_factor; + } + + q = bits2qp(rce, bits); + + /* I/B difference */ + if (pict_type == AV_PICTURE_TYPE_I && s->avctx->i_quant_factor < 0.0) + q = -q * s->avctx->i_quant_factor + s->avctx->i_quant_offset; + else if (pict_type == AV_PICTURE_TYPE_B && s->avctx->b_quant_factor < 0.0) + q = -q * s->avctx->b_quant_factor + s->avctx->b_quant_offset; + if (q < 1) + q = 1; + + return q; +} + +static double get_diff_limited_q(MpegEncContext *s, RateControlEntry *rce, double q) +{ + RateControlContext *rcc = &s->rc_context; + AVCodecContext *a = s->avctx; + const int pict_type = rce->new_pict_type; + const double last_p_q = rcc->last_qscale_for[AV_PICTURE_TYPE_P]; + const double last_non_b_q = rcc->last_qscale_for[rcc->last_non_b_pict_type]; + + if (pict_type == AV_PICTURE_TYPE_I && + (a->i_quant_factor > 0.0 || rcc->last_non_b_pict_type == AV_PICTURE_TYPE_P)) + q = last_p_q * FFABS(a->i_quant_factor) + a->i_quant_offset; + else if (pict_type == AV_PICTURE_TYPE_B && + a->b_quant_factor > 0.0) + q = last_non_b_q * a->b_quant_factor + a->b_quant_offset; + if (q < 1) + q = 1; + + /* last qscale / qdiff stuff */ + if (rcc->last_non_b_pict_type == pict_type || pict_type != AV_PICTURE_TYPE_I) { + double last_q = rcc->last_qscale_for[pict_type]; + const int maxdiff = FF_QP2LAMBDA * a->max_qdiff; + + if (q > last_q + maxdiff) + q = last_q + maxdiff; + else if (q < last_q - maxdiff) + q = last_q - maxdiff; + } + + rcc->last_qscale_for[pict_type] = q; // Note we cannot do that after blurring + + if (pict_type != AV_PICTURE_TYPE_B) + rcc->last_non_b_pict_type = pict_type; + + return q; +} + +/** + * Get the qmin & qmax for pict_type. + */ +static void get_qminmax(int *qmin_ret, int *qmax_ret, MpegEncContext *s, int pict_type) +{ + int qmin = s->avctx->lmin; + int qmax = s->avctx->lmax; + + assert(qmin <= qmax); + + switch (pict_type) { + case AV_PICTURE_TYPE_B: + qmin = (int)(qmin * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset + 0.5); + qmax = (int)(qmax * FFABS(s->avctx->b_quant_factor) + s->avctx->b_quant_offset + 0.5); + break; + case AV_PICTURE_TYPE_I: + qmin = (int)(qmin * FFABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset + 0.5); + qmax = (int)(qmax * FFABS(s->avctx->i_quant_factor) + s->avctx->i_quant_offset + 0.5); + break; + } + + qmin = av_clip(qmin, 1, FF_LAMBDA_MAX); + qmax = av_clip(qmax, 1, FF_LAMBDA_MAX); + + if (qmax < qmin) + qmax = qmin; + + *qmin_ret = qmin; + *qmax_ret = qmax; +} + +static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, + double q, int frame_num) +{ + RateControlContext *rcc = &s->rc_context; + const double buffer_size = s->avctx->rc_buffer_size; + const double fps = get_fps(s->avctx); + const double min_rate = s->avctx->rc_min_rate / fps; + const double max_rate = s->avctx->rc_max_rate / fps; + const int pict_type = rce->new_pict_type; + int qmin, qmax; + + get_qminmax(&qmin, &qmax, s, pict_type); + + /* modulation */ + if (s->avctx->rc_qmod_freq && + frame_num % s->avctx->rc_qmod_freq == 0 && + pict_type == AV_PICTURE_TYPE_P) + q *= s->avctx->rc_qmod_amp; + + /* buffer overflow/underflow protection */ + if (buffer_size) { + double expected_size = rcc->buffer_index; + double q_limit; + + if (min_rate) { + double d = 2 * (buffer_size - expected_size) / buffer_size; + if (d > 1.0) + d = 1.0; + else if (d < 0.0001) + d = 0.0001; + q *= pow(d, 1.0 / s->avctx->rc_buffer_aggressivity); + + q_limit = bits2qp(rce, + FFMAX((min_rate - buffer_size + rcc->buffer_index) * + s->avctx->rc_min_vbv_overflow_use, 1)); + + if (q > q_limit) { + if (s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, + "limiting QP %f -> %f\n", q, q_limit); + q = q_limit; + } + } + + if (max_rate) { + double d = 2 * expected_size / buffer_size; + if (d > 1.0) + d = 1.0; + else if (d < 0.0001) + d = 0.0001; + q /= pow(d, 1.0 / s->avctx->rc_buffer_aggressivity); + + q_limit = bits2qp(rce, + FFMAX(rcc->buffer_index * + s->avctx->rc_max_available_vbv_use, + 1)); + if (q < q_limit) { + if (s->avctx->debug & FF_DEBUG_RC) + av_log(s->avctx, AV_LOG_DEBUG, + "limiting QP %f -> %f\n", q, q_limit); + q = q_limit; + } + } + } + av_dlog(s, "q:%f max:%f min:%f size:%f index:%f agr:%f\n", + q, max_rate, min_rate, buffer_size, rcc->buffer_index, + s->avctx->rc_buffer_aggressivity); + if (s->avctx->rc_qsquish == 0.0 || qmin == qmax) { + if (q < qmin) + q = qmin; + else if (q > qmax) + q = qmax; + } else { + double min2 = log(qmin); + double max2 = log(qmax); + + q = log(q); + q = (q - min2) / (max2 - min2) - 0.5; + q *= -4.0; + q = 1.0 / (1.0 + exp(q)); + q = q * (max2 - min2) + min2; + + q = exp(q); + } + + return q; +} + +// ---------------------------------- +// 1 Pass Code + +static double predict_size(Predictor *p, double q, double var) +{ + return p->coeff * var / (q * p->count); +} + +static void update_predictor(Predictor *p, double q, double var, double size) +{ + double new_coeff = size * q / (var + 1); + if (var < 10) + return; + + p->count *= p->decay; + p->coeff *= p->decay; + p->count++; + p->coeff += new_coeff; +} + +static void adaptive_quantization(MpegEncContext *s, double q) +{ + int i; + const float lumi_masking = s->avctx->lumi_masking / (128.0 * 128.0); + const float dark_masking = s->avctx->dark_masking / (128.0 * 128.0); + const float temp_cplx_masking = s->avctx->temporal_cplx_masking; + const float spatial_cplx_masking = s->avctx->spatial_cplx_masking; + const float p_masking = s->avctx->p_masking; + const float border_masking = s->avctx->border_masking; + float bits_sum = 0.0; + float cplx_sum = 0.0; + float *cplx_tab = s->cplx_tab; + float *bits_tab = s->bits_tab; + const int qmin = s->avctx->mb_lmin; + const int qmax = s->avctx->mb_lmax; + Picture *const pic = &s->current_picture; + const int mb_width = s->mb_width; + const int mb_height = s->mb_height; + + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + float temp_cplx = sqrt(pic->mc_mb_var[mb_xy]); // FIXME merge in pow() + float spat_cplx = sqrt(pic->mb_var[mb_xy]); + const int lumi = pic->mb_mean[mb_xy]; + float bits, cplx, factor; + int mb_x = mb_xy % s->mb_stride; + int mb_y = mb_xy / s->mb_stride; + int mb_distance; + float mb_factor = 0.0; + if (spat_cplx < 4) + spat_cplx = 4; // FIXME finetune + if (temp_cplx < 4) + temp_cplx = 4; // FIXME finetune + + if ((s->mb_type[mb_xy] & CANDIDATE_MB_TYPE_INTRA)) { // FIXME hq mode + cplx = spat_cplx; + factor = 1.0 + p_masking; + } else { + cplx = temp_cplx; + factor = pow(temp_cplx, -temp_cplx_masking); + } + factor *= pow(spat_cplx, -spatial_cplx_masking); + + if (lumi > 127) + factor *= (1.0 - (lumi - 128) * (lumi - 128) * lumi_masking); + else + factor *= (1.0 - (lumi - 128) * (lumi - 128) * dark_masking); + + if (mb_x < mb_width / 5) { + mb_distance = mb_width / 5 - mb_x; + mb_factor = (float)mb_distance / (float)(mb_width / 5); + } else if (mb_x > 4 * mb_width / 5) { + mb_distance = mb_x - 4 * mb_width / 5; + mb_factor = (float)mb_distance / (float)(mb_width / 5); + } + if (mb_y < mb_height / 5) { + mb_distance = mb_height / 5 - mb_y; + mb_factor = FFMAX(mb_factor, + (float)mb_distance / (float)(mb_height / 5)); + } else if (mb_y > 4 * mb_height / 5) { + mb_distance = mb_y - 4 * mb_height / 5; + mb_factor = FFMAX(mb_factor, + (float)mb_distance / (float)(mb_height / 5)); + } + + factor *= 1.0 - border_masking * mb_factor; + + if (factor < 0.00001) + factor = 0.00001; + + bits = cplx * factor; + cplx_sum += cplx; + bits_sum += bits; + cplx_tab[i] = cplx; + bits_tab[i] = bits; + } + + /* handle qmin/qmax clipping */ + if (s->flags & CODEC_FLAG_NORMALIZE_AQP) { + float factor = bits_sum / cplx_sum; + for (i = 0; i < s->mb_num; i++) { + float newq = q * cplx_tab[i] / bits_tab[i]; + newq *= factor; + + if (newq > qmax) { + bits_sum -= bits_tab[i]; + cplx_sum -= cplx_tab[i] * q / qmax; + } else if (newq < qmin) { + bits_sum -= bits_tab[i]; + cplx_sum -= cplx_tab[i] * q / qmin; + } + } + if (bits_sum < 0.001) + bits_sum = 0.001; + if (cplx_sum < 0.001) + cplx_sum = 0.001; + } + + for (i = 0; i < s->mb_num; i++) { + const int mb_xy = s->mb_index2xy[i]; + float newq = q * cplx_tab[i] / bits_tab[i]; + int intq; + + if (s->flags & CODEC_FLAG_NORMALIZE_AQP) { + newq *= bits_sum / cplx_sum; + } + + intq = (int)(newq + 0.5); + + if (intq > qmax) + intq = qmax; + else if (intq < qmin) + intq = qmin; + s->lambda_table[mb_xy] = intq; + } +} + +void ff_get_2pass_fcode(MpegEncContext *s) +{ + RateControlContext *rcc = &s->rc_context; + RateControlEntry *rce = &rcc->entry[s->picture_number]; + + s->f_code = rce->f_code; + s->b_code = rce->b_code; +} + +// FIXME rd or at least approx for dquant + +float ff_rate_estimate_qscale(MpegEncContext *s, int dry_run) +{ + float q; + int qmin, qmax; + float br_compensation; + double diff; + double short_term_q; + double fps; + int picture_number = s->picture_number; + int64_t wanted_bits; + RateControlContext *rcc = &s->rc_context; + AVCodecContext *a = s->avctx; + RateControlEntry local_rce, *rce; + double bits; + double rate_factor; + int var; + const int pict_type = s->pict_type; + Picture * const pic = &s->current_picture; + emms_c(); + +#if CONFIG_LIBXVID + if ((s->flags & CODEC_FLAG_PASS2) && + s->avctx->rc_strategy == FF_RC_STRATEGY_XVID) + return ff_xvid_rate_estimate_qscale(s, dry_run); +#endif + + get_qminmax(&qmin, &qmax, s, pict_type); + + fps = get_fps(s->avctx); + /* update predictors */ + if (picture_number > 2 && !dry_run) { + const int last_var = s->last_pict_type == AV_PICTURE_TYPE_I ? rcc->last_mb_var_sum + : rcc->last_mc_mb_var_sum; + av_assert1(s->frame_bits >= s->stuffing_bits); + update_predictor(&rcc->pred[s->last_pict_type], + rcc->last_qscale, + sqrt(last_var), + s->frame_bits - s->stuffing_bits); + } + + if (s->flags & CODEC_FLAG_PASS2) { + assert(picture_number >= 0); + if (picture_number >= rcc->num_entries) { + av_log(s, AV_LOG_ERROR, "Input is longer than 2-pass log file\n"); + return -1; + } + rce = &rcc->entry[picture_number]; + wanted_bits = rce->expected_bits; + } else { + Picture *dts_pic; + rce = &local_rce; + + /* FIXME add a dts field to AVFrame and ensure it is set and use it + * here instead of reordering but the reordering is simpler for now + * until H.264 B-pyramid must be handled. */ + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) + dts_pic = s->current_picture_ptr; + else + dts_pic = s->last_picture_ptr; + + if (!dts_pic || dts_pic->f.pts == AV_NOPTS_VALUE) + wanted_bits = (uint64_t)(s->bit_rate * (double)picture_number / fps); + else + wanted_bits = (uint64_t)(s->bit_rate * (double)dts_pic->f.pts / fps); + } + + diff = s->total_bits - wanted_bits; + br_compensation = (a->bit_rate_tolerance - diff) / a->bit_rate_tolerance; + if (br_compensation <= 0.0) + br_compensation = 0.001; + + var = pict_type == AV_PICTURE_TYPE_I ? pic->mb_var_sum : pic->mc_mb_var_sum; + + short_term_q = 0; /* avoid warning */ + if (s->flags & CODEC_FLAG_PASS2) { + if (pict_type != AV_PICTURE_TYPE_I) + assert(pict_type == rce->new_pict_type); + + q = rce->new_qscale / br_compensation; + av_dlog(s, "%f %f %f last:%d var:%d type:%d//\n", q, rce->new_qscale, + br_compensation, s->frame_bits, var, pict_type); + } else { + rce->pict_type = + rce->new_pict_type = pict_type; + rce->mc_mb_var_sum = pic->mc_mb_var_sum; + rce->mb_var_sum = pic->mb_var_sum; + rce->qscale = FF_QP2LAMBDA * 2; + rce->f_code = s->f_code; + rce->b_code = s->b_code; + rce->misc_bits = 1; + + bits = predict_size(&rcc->pred[pict_type], rce->qscale, sqrt(var)); + if (pict_type == AV_PICTURE_TYPE_I) { + rce->i_count = s->mb_num; + rce->i_tex_bits = bits; + rce->p_tex_bits = 0; + rce->mv_bits = 0; + } else { + rce->i_count = 0; // FIXME we do know this approx + rce->i_tex_bits = 0; + rce->p_tex_bits = bits * 0.9; + rce->mv_bits = bits * 0.1; + } + rcc->i_cplx_sum[pict_type] += rce->i_tex_bits * rce->qscale; + rcc->p_cplx_sum[pict_type] += rce->p_tex_bits * rce->qscale; + rcc->mv_bits_sum[pict_type] += rce->mv_bits; + rcc->frame_count[pict_type]++; + + bits = rce->i_tex_bits + rce->p_tex_bits; + rate_factor = rcc->pass1_wanted_bits / + rcc->pass1_rc_eq_output_sum * br_compensation; + + q = get_qscale(s, rce, rate_factor, picture_number); + if (q < 0) + return -1; + + assert(q > 0.0); + q = get_diff_limited_q(s, rce, q); + assert(q > 0.0); + + // FIXME type dependent blur like in 2-pass + if (pict_type == AV_PICTURE_TYPE_P || s->intra_only) { + rcc->short_term_qsum *= a->qblur; + rcc->short_term_qcount *= a->qblur; + + rcc->short_term_qsum += q; + rcc->short_term_qcount++; + q = short_term_q = rcc->short_term_qsum / rcc->short_term_qcount; + } + assert(q > 0.0); + + q = modify_qscale(s, rce, q, picture_number); + + rcc->pass1_wanted_bits += s->bit_rate / fps; + + assert(q > 0.0); + } + + if (s->avctx->debug & FF_DEBUG_RC) { + av_log(s->avctx, AV_LOG_DEBUG, + "%c qp:%d<%2.1f<%d %d want:%d total:%d comp:%f st_q:%2.2f " + "size:%d var:%d/%d br:%d fps:%d\n", + av_get_picture_type_char(pict_type), + qmin, q, qmax, picture_number, + (int)wanted_bits / 1000, (int)s->total_bits / 1000, + br_compensation, short_term_q, s->frame_bits, + pic->mb_var_sum, pic->mc_mb_var_sum, + s->bit_rate / 1000, (int)fps); + } + + if (q < qmin) + q = qmin; + else if (q > qmax) + q = qmax; + + if (s->adaptive_quant) + adaptive_quantization(s, q); + else + q = (int)(q + 0.5); + + if (!dry_run) { + rcc->last_qscale = q; + rcc->last_mc_mb_var_sum = pic->mc_mb_var_sum; + rcc->last_mb_var_sum = pic->mb_var_sum; + } + return q; +} + +// ---------------------------------------------- +// 2-Pass code + +static int init_pass2(MpegEncContext *s) +{ + RateControlContext *rcc = &s->rc_context; + AVCodecContext *a = s->avctx; + int i, toobig; + double fps = get_fps(s->avctx); + double complexity[5] = { 0 }; // approximate bits at quant=1 + uint64_t const_bits[5] = { 0 }; // quantizer independent bits + uint64_t all_const_bits; + uint64_t all_available_bits = (uint64_t)(s->bit_rate * + (double)rcc->num_entries / fps); + double rate_factor = 0; + double step; + const int filter_size = (int)(a->qblur * 4) | 1; + double expected_bits; + double *qscale, *blurred_qscale, qscale_sum; + + /* find complexity & const_bits & decide the pict_types */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + + rce->new_pict_type = rce->pict_type; + rcc->i_cplx_sum[rce->pict_type] += rce->i_tex_bits * rce->qscale; + rcc->p_cplx_sum[rce->pict_type] += rce->p_tex_bits * rce->qscale; + rcc->mv_bits_sum[rce->pict_type] += rce->mv_bits; + rcc->frame_count[rce->pict_type]++; + + complexity[rce->new_pict_type] += (rce->i_tex_bits + rce->p_tex_bits) * + (double)rce->qscale; + const_bits[rce->new_pict_type] += rce->mv_bits + rce->misc_bits; + } + + all_const_bits = const_bits[AV_PICTURE_TYPE_I] + + const_bits[AV_PICTURE_TYPE_P] + + const_bits[AV_PICTURE_TYPE_B]; + + if (all_available_bits < all_const_bits) { + av_log(s->avctx, AV_LOG_ERROR, "requested bitrate is too low\n"); + return -1; + } + + qscale = av_malloc(sizeof(double) * rcc->num_entries); + blurred_qscale = av_malloc(sizeof(double) * rcc->num_entries); + toobig = 0; + + for (step = 256 * 256; step > 0.0000001; step *= 0.5) { + expected_bits = 0; + rate_factor += step; + + rcc->buffer_index = s->avctx->rc_buffer_size / 2; + + /* find qscale */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + + qscale[i] = get_qscale(s, &rcc->entry[i], rate_factor, i); + rcc->last_qscale_for[rce->pict_type] = qscale[i]; + } + assert(filter_size % 2 == 1); + + /* fixed I/B QP relative to P mode */ + for (i = FFMAX(0, rcc->num_entries - 300); i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + + qscale[i] = get_diff_limited_q(s, rce, qscale[i]); + } + + for (i = rcc->num_entries - 1; i >= 0; i--) { + RateControlEntry *rce = &rcc->entry[i]; + + qscale[i] = get_diff_limited_q(s, rce, qscale[i]); + } + + /* smooth curve */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + const int pict_type = rce->new_pict_type; + int j; + double q = 0.0, sum = 0.0; + + for (j = 0; j < filter_size; j++) { + int index = i + j - filter_size / 2; + double d = index - i; + double coeff = a->qblur == 0 ? 1.0 : exp(-d * d / (a->qblur * a->qblur)); + + if (index < 0 || index >= rcc->num_entries) + continue; + if (pict_type != rcc->entry[index].new_pict_type) + continue; + q += qscale[index] * coeff; + sum += coeff; + } + blurred_qscale[i] = q / sum; + } + + /* find expected bits */ + for (i = 0; i < rcc->num_entries; i++) { + RateControlEntry *rce = &rcc->entry[i]; + double bits; + + rce->new_qscale = modify_qscale(s, rce, blurred_qscale[i], i); + + bits = qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits; + bits += 8 * ff_vbv_update(s, bits); + + rce->expected_bits = expected_bits; + expected_bits += bits; + } + + av_dlog(s->avctx, + "expected_bits: %f all_available_bits: %d rate_factor: %f\n", + expected_bits, (int)all_available_bits, rate_factor); + if (expected_bits > all_available_bits) { + rate_factor -= step; + ++toobig; + } + } + av_free(qscale); + av_free(blurred_qscale); + + /* check bitrate calculations and print info */ + qscale_sum = 0.0; + for (i = 0; i < rcc->num_entries; i++) { + av_dlog(s, "[lavc rc] entry[%d].new_qscale = %.3f qp = %.3f\n", + i, + rcc->entry[i].new_qscale, + rcc->entry[i].new_qscale / FF_QP2LAMBDA); + qscale_sum += av_clip(rcc->entry[i].new_qscale / FF_QP2LAMBDA, + s->avctx->qmin, s->avctx->qmax); + } + assert(toobig <= 40); + av_log(s->avctx, AV_LOG_DEBUG, + "[lavc rc] requested bitrate: %d bps expected bitrate: %d bps\n", + s->bit_rate, + (int)(expected_bits / ((double)all_available_bits / s->bit_rate))); + av_log(s->avctx, AV_LOG_DEBUG, + "[lavc rc] estimated target average qp: %.3f\n", + (float)qscale_sum / rcc->num_entries); + if (toobig == 0) { + av_log(s->avctx, AV_LOG_INFO, + "[lavc rc] Using all of requested bitrate is not " + "necessary for this video with these parameters.\n"); + } else if (toobig == 40) { + av_log(s->avctx, AV_LOG_ERROR, + "[lavc rc] Error: bitrate too low for this video " + "with these parameters.\n"); + return -1; + } else if (fabs(expected_bits / all_available_bits - 1.0) > 0.01) { + av_log(s->avctx, AV_LOG_ERROR, + "[lavc rc] Error: 2pass curve failed to converge\n"); + return -1; + } + + return 0; +} diff --git a/ffmpeg/libavcodec/ratecontrol.h b/ffmpeg/libavcodec/ratecontrol.h new file mode 100644 index 0000000..959b6a2 --- /dev/null +++ b/ffmpeg/libavcodec/ratecontrol.h @@ -0,0 +1,103 @@ +/* + * Ratecontrol + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +#ifndef AVCODEC_RATECONTROL_H +#define AVCODEC_RATECONTROL_H + +/** + * @file + * ratecontrol header. + */ + +#include +#include +#include "libavutil/eval.h" + +typedef struct Predictor{ + double coeff; + double count; + double decay; +} Predictor; + +typedef struct RateControlEntry{ + int pict_type; + float qscale; + int mv_bits; + int i_tex_bits; + int p_tex_bits; + int misc_bits; + int header_bits; + uint64_t expected_bits; + int new_pict_type; + float new_qscale; + int mc_mb_var_sum; + int mb_var_sum; + int i_count; + int skip_count; + int f_code; + int b_code; +}RateControlEntry; + +/** + * rate control context. + */ +typedef struct RateControlContext{ + int num_entries; ///< number of RateControlEntries + RateControlEntry *entry; + double buffer_index; ///< amount of bits in the video/audio buffer + Predictor pred[5]; + double short_term_qsum; ///< sum of recent qscales + double short_term_qcount; ///< count of recent qscales + double pass1_rc_eq_output_sum;///< sum of the output of the rc equation, this is used for normalization + double pass1_wanted_bits; ///< bits which should have been outputed by the pass1 code (including complexity init) + double last_qscale; + double last_qscale_for[5]; ///< last qscale for a specific pict type, used for max_diff & ipb factor stuff + int last_mc_mb_var_sum; + int last_mb_var_sum; + uint64_t i_cplx_sum[5]; + uint64_t p_cplx_sum[5]; + uint64_t mv_bits_sum[5]; + uint64_t qscale_sum[5]; + int frame_count[5]; + int last_non_b_pict_type; + + void *non_lavc_opaque; ///< context for non lavc rc code (for example xvid) + float dry_run_qscale; ///< for xvid rc + int last_picture_number; ///< for xvid rc + AVExpr * rc_eq_eval; +}RateControlContext; + +struct MpegEncContext; + +/* rate control */ +int ff_rate_control_init(struct MpegEncContext *s); +float ff_rate_estimate_qscale(struct MpegEncContext *s, int dry_run); +void ff_write_pass1_stats(struct MpegEncContext *s); +void ff_rate_control_uninit(struct MpegEncContext *s); +int ff_vbv_update(struct MpegEncContext *s, int frame_size); +void ff_get_2pass_fcode(struct MpegEncContext *s); + +int ff_xvid_rate_control_init(struct MpegEncContext *s); +void ff_xvid_rate_control_uninit(struct MpegEncContext *s); +float ff_xvid_rate_estimate_qscale(struct MpegEncContext *s, int dry_run); + +#endif /* AVCODEC_RATECONTROL_H */ diff --git a/ffmpeg/libavcodec/raw.c b/ffmpeg/libavcodec/raw.c new file mode 100644 index 0000000..e23dbea --- /dev/null +++ b/ffmpeg/libavcodec/raw.c @@ -0,0 +1,208 @@ +/* + * Raw Video Codec + * Copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Raw Video Codec + */ + +#include "avcodec.h" +#include "raw.h" +#include "libavutil/common.h" + +const PixelFormatTag ff_raw_pix_fmt_tags[] = { + { AV_PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ + { AV_PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') }, + { AV_PIX_FMT_YUV420P, MKTAG('Y', 'V', '1', '2') }, + { AV_PIX_FMT_YUV410P, MKTAG('Y', 'U', 'V', '9') }, + { AV_PIX_FMT_YUV410P, MKTAG('Y', 'V', 'U', '9') }, + { AV_PIX_FMT_YUV411P, MKTAG('Y', '4', '1', 'B') }, + { AV_PIX_FMT_YUV422P, MKTAG('Y', '4', '2', 'B') }, + { AV_PIX_FMT_YUV422P, MKTAG('P', '4', '2', '2') }, + { AV_PIX_FMT_YUV422P, MKTAG('Y', 'V', '1', '6') }, + /* yuvjXXX formats are deprecated hacks specific to libav*, + they are identical to yuvXXX */ + { AV_PIX_FMT_YUVJ420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ + { AV_PIX_FMT_YUVJ420P, MKTAG('I', 'Y', 'U', 'V') }, + { AV_PIX_FMT_YUVJ420P, MKTAG('Y', 'V', '1', '2') }, + { AV_PIX_FMT_YUVJ422P, MKTAG('Y', '4', '2', 'B') }, + { AV_PIX_FMT_YUVJ422P, MKTAG('P', '4', '2', '2') }, + { AV_PIX_FMT_GRAY8, MKTAG('Y', '8', '0', '0') }, + { AV_PIX_FMT_GRAY8, MKTAG('Y', '8', ' ', ' ') }, + + { AV_PIX_FMT_YUYV422, MKTAG('Y', 'U', 'Y', '2') }, /* Packed formats */ + { AV_PIX_FMT_YUYV422, MKTAG('Y', '4', '2', '2') }, + { AV_PIX_FMT_YUYV422, MKTAG('V', '4', '2', '2') }, + { AV_PIX_FMT_YUYV422, MKTAG('V', 'Y', 'U', 'Y') }, + { AV_PIX_FMT_YUYV422, MKTAG('Y', 'U', 'N', 'V') }, + { AV_PIX_FMT_UYVY422, MKTAG('U', 'Y', 'V', 'Y') }, + { AV_PIX_FMT_UYVY422, MKTAG('H', 'D', 'Y', 'C') }, + { AV_PIX_FMT_UYVY422, MKTAG('U', 'Y', 'N', 'V') }, + { AV_PIX_FMT_UYVY422, MKTAG('U', 'Y', 'N', 'Y') }, + { AV_PIX_FMT_UYVY422, MKTAG('u', 'y', 'v', '1') }, + { AV_PIX_FMT_UYVY422, MKTAG('2', 'V', 'u', '1') }, + { AV_PIX_FMT_UYVY422, MKTAG('A', 'V', 'R', 'n') }, /* Avid AVI Codec 1:1 */ + { AV_PIX_FMT_UYVY422, MKTAG('A', 'V', '1', 'x') }, /* Avid 1:1x */ + { AV_PIX_FMT_UYVY422, MKTAG('A', 'V', 'u', 'p') }, + { AV_PIX_FMT_UYVY422, MKTAG('V', 'D', 'T', 'Z') }, /* SoftLab-NSK VideoTizer */ + { AV_PIX_FMT_UYVY422, MKTAG('a', 'u', 'v', '2') }, + { AV_PIX_FMT_UYVY422, MKTAG('c', 'y', 'u', 'v') }, /* CYUV is also Creative YUV */ + { AV_PIX_FMT_UYYVYY411, MKTAG('Y', '4', '1', '1') }, + { AV_PIX_FMT_GRAY8, MKTAG('G', 'R', 'E', 'Y') }, + { AV_PIX_FMT_NV12, MKTAG('N', 'V', '1', '2') }, + { AV_PIX_FMT_NV21, MKTAG('N', 'V', '2', '1') }, + + /* nut */ + { AV_PIX_FMT_RGB555LE, MKTAG('R', 'G', 'B', 15) }, + { AV_PIX_FMT_BGR555LE, MKTAG('B', 'G', 'R', 15) }, + { AV_PIX_FMT_RGB565LE, MKTAG('R', 'G', 'B', 16) }, + { AV_PIX_FMT_BGR565LE, MKTAG('B', 'G', 'R', 16) }, + { AV_PIX_FMT_RGB555BE, MKTAG(15 , 'B', 'G', 'R') }, + { AV_PIX_FMT_BGR555BE, MKTAG(15 , 'R', 'G', 'B') }, + { AV_PIX_FMT_RGB565BE, MKTAG(16 , 'B', 'G', 'R') }, + { AV_PIX_FMT_BGR565BE, MKTAG(16 , 'R', 'G', 'B') }, + { AV_PIX_FMT_RGB444LE, MKTAG('R', 'G', 'B', 12) }, + { AV_PIX_FMT_BGR444LE, MKTAG('B', 'G', 'R', 12) }, + { AV_PIX_FMT_RGB444BE, MKTAG(12 , 'B', 'G', 'R') }, + { AV_PIX_FMT_BGR444BE, MKTAG(12 , 'R', 'G', 'B') }, + { AV_PIX_FMT_RGBA64LE, MKTAG('R', 'B', 'A', 64 ) }, + { AV_PIX_FMT_BGRA64LE, MKTAG('B', 'R', 'A', 64 ) }, + { AV_PIX_FMT_RGBA64BE, MKTAG(64 , 'R', 'B', 'A') }, + { AV_PIX_FMT_BGRA64BE, MKTAG(64 , 'B', 'R', 'A') }, + { AV_PIX_FMT_RGBA, MKTAG('R', 'G', 'B', 'A') }, + { AV_PIX_FMT_RGB0, MKTAG('R', 'G', 'B', 0 ) }, + { AV_PIX_FMT_BGRA, MKTAG('B', 'G', 'R', 'A') }, + { AV_PIX_FMT_BGR0, MKTAG('B', 'G', 'R', 0 ) }, + { AV_PIX_FMT_ABGR, MKTAG('A', 'B', 'G', 'R') }, + { AV_PIX_FMT_0BGR, MKTAG( 0 , 'B', 'G', 'R') }, + { AV_PIX_FMT_ARGB, MKTAG('A', 'R', 'G', 'B') }, + { AV_PIX_FMT_0RGB, MKTAG( 0 , 'R', 'G', 'B') }, + { AV_PIX_FMT_RGB24, MKTAG('R', 'G', 'B', 24 ) }, + { AV_PIX_FMT_BGR24, MKTAG('B', 'G', 'R', 24 ) }, + { AV_PIX_FMT_YUV411P, MKTAG('4', '1', '1', 'P') }, + { AV_PIX_FMT_YUV422P, MKTAG('4', '2', '2', 'P') }, + { AV_PIX_FMT_YUVJ422P, MKTAG('4', '2', '2', 'P') }, + { AV_PIX_FMT_YUV440P, MKTAG('4', '4', '0', 'P') }, + { AV_PIX_FMT_YUVJ440P, MKTAG('4', '4', '0', 'P') }, + { AV_PIX_FMT_YUV444P, MKTAG('4', '4', '4', 'P') }, + { AV_PIX_FMT_YUVJ444P, MKTAG('4', '4', '4', 'P') }, + { AV_PIX_FMT_MONOWHITE,MKTAG('B', '1', 'W', '0') }, + { AV_PIX_FMT_MONOBLACK,MKTAG('B', '0', 'W', '1') }, + { AV_PIX_FMT_BGR8, MKTAG('B', 'G', 'R', 8 ) }, + { AV_PIX_FMT_RGB8, MKTAG('R', 'G', 'B', 8 ) }, + { AV_PIX_FMT_BGR4, MKTAG('B', 'G', 'R', 4 ) }, + { AV_PIX_FMT_RGB4, MKTAG('R', 'G', 'B', 4 ) }, + { AV_PIX_FMT_RGB4_BYTE,MKTAG('B', '4', 'B', 'Y') }, + { AV_PIX_FMT_BGR4_BYTE,MKTAG('R', '4', 'B', 'Y') }, + { AV_PIX_FMT_RGB48LE, MKTAG('R', 'G', 'B', 48 ) }, + { AV_PIX_FMT_RGB48BE, MKTAG( 48, 'R', 'G', 'B') }, + { AV_PIX_FMT_BGR48LE, MKTAG('B', 'G', 'R', 48 ) }, + { AV_PIX_FMT_BGR48BE, MKTAG( 48, 'B', 'G', 'R') }, + { AV_PIX_FMT_GRAY16LE, MKTAG('Y', '1', 0 , 16 ) }, + { AV_PIX_FMT_GRAY16BE, MKTAG(16 , 0 , '1', 'Y') }, + { AV_PIX_FMT_YUV420P10LE, MKTAG('Y', '3', 11 , 10 ) }, + { AV_PIX_FMT_YUV420P10BE, MKTAG(10 , 11 , '3', 'Y') }, + { AV_PIX_FMT_YUV422P10LE, MKTAG('Y', '3', 10 , 10 ) }, + { AV_PIX_FMT_YUV422P10BE, MKTAG(10 , 10 , '3', 'Y') }, + { AV_PIX_FMT_YUV444P10LE, MKTAG('Y', '3', 0 , 10 ) }, + { AV_PIX_FMT_YUV444P10BE, MKTAG(10 , 0 , '3', 'Y') }, + { AV_PIX_FMT_YUV420P12LE, MKTAG('Y', '3', 11 , 12 ) }, + { AV_PIX_FMT_YUV420P12BE, MKTAG(12 , 11 , '3', 'Y') }, + { AV_PIX_FMT_YUV422P12LE, MKTAG('Y', '3', 10 , 12 ) }, + { AV_PIX_FMT_YUV422P12BE, MKTAG(12 , 10 , '3', 'Y') }, + { AV_PIX_FMT_YUV444P12LE, MKTAG('Y', '3', 0 , 12 ) }, + { AV_PIX_FMT_YUV444P12BE, MKTAG(12 , 0 , '3', 'Y') }, + { AV_PIX_FMT_YUV420P14LE, MKTAG('Y', '3', 11 , 14 ) }, + { AV_PIX_FMT_YUV420P14BE, MKTAG(14 , 11 , '3', 'Y') }, + { AV_PIX_FMT_YUV422P14LE, MKTAG('Y', '3', 10 , 14 ) }, + { AV_PIX_FMT_YUV422P14BE, MKTAG(14 , 10 , '3', 'Y') }, + { AV_PIX_FMT_YUV444P14LE, MKTAG('Y', '3', 0 , 14 ) }, + { AV_PIX_FMT_YUV444P14BE, MKTAG(14 , 0 , '3', 'Y') }, + { AV_PIX_FMT_YUV420P16LE, MKTAG('Y', '3', 11 , 16 ) }, + { AV_PIX_FMT_YUV420P16BE, MKTAG(16 , 11 , '3', 'Y') }, + { AV_PIX_FMT_YUV422P16LE, MKTAG('Y', '3', 10 , 16 ) }, + { AV_PIX_FMT_YUV422P16BE, MKTAG(16 , 10 , '3', 'Y') }, + { AV_PIX_FMT_YUV444P16LE, MKTAG('Y', '3', 0 , 16 ) }, + { AV_PIX_FMT_YUV444P16BE, MKTAG(16 , 0 , '3', 'Y') }, + { AV_PIX_FMT_YUVA420P, MKTAG('Y', '4', 11 , 8 ) }, + { AV_PIX_FMT_YUVA422P, MKTAG('Y', '4', 10 , 8 ) }, + { AV_PIX_FMT_YUVA444P, MKTAG('Y', '4', 0 , 8 ) }, + { AV_PIX_FMT_GRAY8A, MKTAG('Y', '2', 0 , 8 ) }, + + { AV_PIX_FMT_YUVA420P9LE, MKTAG('Y', '4', 11 , 9 ) }, + { AV_PIX_FMT_YUVA420P9BE, MKTAG( 9 , 11 , '4', 'Y') }, + { AV_PIX_FMT_YUVA422P9LE, MKTAG('Y', '4', 10 , 9 ) }, + { AV_PIX_FMT_YUVA422P9BE, MKTAG( 9 , 10 , '4', 'Y') }, + { AV_PIX_FMT_YUVA444P9LE, MKTAG('Y', '4', 0 , 9 ) }, + { AV_PIX_FMT_YUVA444P9BE, MKTAG( 9 , 0 , '4', 'Y') }, + { AV_PIX_FMT_YUVA420P10LE, MKTAG('Y', '4', 11 , 10 ) }, + { AV_PIX_FMT_YUVA420P10BE, MKTAG(10 , 11 , '4', 'Y') }, + { AV_PIX_FMT_YUVA422P10LE, MKTAG('Y', '4', 10 , 10 ) }, + { AV_PIX_FMT_YUVA422P10BE, MKTAG(10 , 10 , '4', 'Y') }, + { AV_PIX_FMT_YUVA444P10LE, MKTAG('Y', '4', 0 , 10 ) }, + { AV_PIX_FMT_YUVA444P10BE, MKTAG(10 , 0 , '4', 'Y') }, + { AV_PIX_FMT_YUVA420P16LE, MKTAG('Y', '4', 11 , 16 ) }, + { AV_PIX_FMT_YUVA420P16BE, MKTAG(16 , 11 , '4', 'Y') }, + { AV_PIX_FMT_YUVA422P16LE, MKTAG('Y', '4', 10 , 16 ) }, + { AV_PIX_FMT_YUVA422P16BE, MKTAG(16 , 10 , '4', 'Y') }, + { AV_PIX_FMT_YUVA444P16LE, MKTAG('Y', '4', 0 , 16 ) }, + { AV_PIX_FMT_YUVA444P16BE, MKTAG(16 , 0 , '4', 'Y') }, + + /* quicktime */ + { AV_PIX_FMT_YUV420P, MKTAG('R', '4', '2', '0') }, /* Radius DV YUV PAL */ + { AV_PIX_FMT_YUV411P, MKTAG('R', '4', '1', '1') }, /* Radius DV YUV NTSC */ + { AV_PIX_FMT_UYVY422, MKTAG('2', 'v', 'u', 'y') }, + { AV_PIX_FMT_UYVY422, MKTAG('2', 'V', 'u', 'y') }, + { AV_PIX_FMT_UYVY422, MKTAG('A', 'V', 'U', 'I') }, /* FIXME merge both fields */ + { AV_PIX_FMT_UYVY422, MKTAG('b', 'x', 'y', 'v') }, + { AV_PIX_FMT_YUYV422, MKTAG('y', 'u', 'v', '2') }, + { AV_PIX_FMT_YUYV422, MKTAG('y', 'u', 'v', 's') }, + { AV_PIX_FMT_YUYV422, MKTAG('D', 'V', 'O', 'O') }, /* Digital Voodoo SD 8 Bit */ + { AV_PIX_FMT_RGB555LE,MKTAG('L', '5', '5', '5') }, + { AV_PIX_FMT_RGB565LE,MKTAG('L', '5', '6', '5') }, + { AV_PIX_FMT_RGB565BE,MKTAG('B', '5', '6', '5') }, + { AV_PIX_FMT_BGR24, MKTAG('2', '4', 'B', 'G') }, + { AV_PIX_FMT_BGR24, MKTAG('b', 'x', 'b', 'g') }, + { AV_PIX_FMT_BGRA, MKTAG('B', 'G', 'R', 'A') }, + { AV_PIX_FMT_RGBA, MKTAG('R', 'G', 'B', 'A') }, + { AV_PIX_FMT_RGB24, MKTAG('b', 'x', 'r', 'g') }, + { AV_PIX_FMT_ABGR, MKTAG('A', 'B', 'G', 'R') }, + { AV_PIX_FMT_GRAY16BE,MKTAG('b', '1', '6', 'g') }, + { AV_PIX_FMT_RGB48BE, MKTAG('b', '4', '8', 'r') }, + + /* special */ + { AV_PIX_FMT_RGB565LE,MKTAG( 3 , 0 , 0 , 0 ) }, /* flipped RGB565LE */ + { AV_PIX_FMT_YUV444P, MKTAG('Y', 'V', '2', '4') }, /* YUV444P, swapped UV */ + { AV_PIX_FMT_YUYV422, MKTAG('Y', 'V', 'Y', 'U') }, /* YUYV, swapped UV */ + + { AV_PIX_FMT_NONE, 0 }, +}; + +unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) +{ + const PixelFormatTag *tags = ff_raw_pix_fmt_tags; + while (tags->pix_fmt >= 0) { + if (tags->pix_fmt == fmt) + return tags->fourcc; + tags++; + } + return 0; +} diff --git a/ffmpeg/libavcodec/raw.h b/ffmpeg/libavcodec/raw.h new file mode 100644 index 0000000..3e59f28 --- /dev/null +++ b/ffmpeg/libavcodec/raw.h @@ -0,0 +1,44 @@ +/* + * Raw Video Codec + * Copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Raw Video Codec + */ + +#ifndef AVCODEC_RAW_H +#define AVCODEC_RAW_H + +#include "avcodec.h" +#include "libavutil/internal.h" + +typedef struct PixelFormatTag { + enum AVPixelFormat pix_fmt; + unsigned int fourcc; +} PixelFormatTag; + +extern av_export const PixelFormatTag ff_raw_pix_fmt_tags[]; +#if LIBAVCODEC_VERSION_MAJOR < 55 +enum AVPixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); +#endif +enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); + +#endif /* AVCODEC_RAW_H */ diff --git a/ffmpeg/libavcodec/rawdec.c b/ffmpeg/libavcodec/rawdec.c new file mode 100644 index 0000000..00730dc --- /dev/null +++ b/ffmpeg/libavcodec/rawdec.c @@ -0,0 +1,348 @@ +/* + * Raw Video Decoder + * Copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Raw Video Decoder + */ + +#include "avcodec.h" +#include "raw.h" +#include "libavutil/avassert.h" +#include "libavutil/buffer.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +typedef struct RawVideoContext { + AVClass *av_class; + AVBufferRef *palette; + int frame_size; /* size of the frame in bytes */ + int flip; + int is_2_4_bpp; // 2 or 4 bpp raw in avi/mov + int is_yuv2; + int tff; +} RawVideoContext; + +static const AVOption options[]={ +{"top", "top field first", offsetof(RawVideoContext, tff), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_VIDEO_PARAM}, +{NULL} +}; + +static const AVClass class = { + .class_name = "rawdec", + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const PixelFormatTag pix_fmt_bps_avi[] = { + { AV_PIX_FMT_MONOWHITE, 1 }, + { AV_PIX_FMT_PAL8, 2 }, + { AV_PIX_FMT_PAL8, 4 }, + { AV_PIX_FMT_PAL8, 8 }, + { AV_PIX_FMT_RGB444LE, 12 }, + { AV_PIX_FMT_RGB555LE, 15 }, + { AV_PIX_FMT_RGB555LE, 16 }, + { AV_PIX_FMT_BGR24, 24 }, + { AV_PIX_FMT_BGRA, 32 }, + { AV_PIX_FMT_NONE, 0 }, +}; + +static const PixelFormatTag pix_fmt_bps_mov[] = { + { AV_PIX_FMT_MONOWHITE, 1 }, + { AV_PIX_FMT_PAL8, 2 }, + { AV_PIX_FMT_PAL8, 4 }, + { AV_PIX_FMT_PAL8, 8 }, + // FIXME swscale does not support 16 bit in .mov, sample 16bit.mov + // http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html + { AV_PIX_FMT_RGB555BE, 16 }, + { AV_PIX_FMT_RGB24, 24 }, + { AV_PIX_FMT_ARGB, 32 }, + { AV_PIX_FMT_MONOWHITE,33 }, + { AV_PIX_FMT_NONE, 0 }, +}; + +enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, + unsigned int fourcc) +{ + while (tags->pix_fmt >= 0) { + if (tags->fourcc == fourcc) + return tags->pix_fmt; + tags++; + } + return AV_PIX_FMT_NONE; +} + +#if LIBAVCODEC_VERSION_MAJOR < 55 +enum AVPixelFormat ff_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc) +{ + return avpriv_find_pix_fmt(tags, fourcc); +} +#endif + +static av_cold int raw_init_decoder(AVCodecContext *avctx) +{ + RawVideoContext *context = avctx->priv_data; + const AVPixFmtDescriptor *desc; + + if ( avctx->codec_tag == MKTAG('r','a','w',' ') + || avctx->codec_tag == MKTAG('N','O','1','6')) + avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_mov, + avctx->bits_per_coded_sample); + else if (avctx->codec_tag == MKTAG('W', 'R', 'A', 'W')) + avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_avi, + avctx->bits_per_coded_sample); + else if (avctx->codec_tag) + avctx->pix_fmt = avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, avctx->codec_tag); + else if (avctx->pix_fmt == AV_PIX_FMT_NONE && avctx->bits_per_coded_sample) + avctx->pix_fmt = avpriv_find_pix_fmt(pix_fmt_bps_avi, + avctx->bits_per_coded_sample); + + desc = av_pix_fmt_desc_get(avctx->pix_fmt); + if (!desc) { + av_log(avctx, AV_LOG_ERROR, "Invalid pixel format.\n"); + return AVERROR(EINVAL); + } + + if (desc->flags & (PIX_FMT_PAL | PIX_FMT_PSEUDOPAL)) { + context->palette = av_buffer_alloc(AVPALETTE_SIZE); + if (!context->palette) + return AVERROR(ENOMEM); + if (desc->flags & PIX_FMT_PSEUDOPAL) + avpriv_set_systematic_pal2((uint32_t*)context->palette->data, avctx->pix_fmt); + else + memset(context->palette->data, 0, AVPALETTE_SIZE); + } + + context->frame_size = avpicture_get_size(avctx->pix_fmt, avctx->width, + avctx->height); + if ((avctx->bits_per_coded_sample == 4 || avctx->bits_per_coded_sample == 2) && + avctx->pix_fmt == AV_PIX_FMT_PAL8 && + (!avctx->codec_tag || avctx->codec_tag == MKTAG('r','a','w',' '))) + context->is_2_4_bpp = 1; + + if ((avctx->extradata_size >= 9 && + !memcmp(avctx->extradata + avctx->extradata_size - 9, "BottomUp", 9)) || + avctx->codec_tag == MKTAG('c','y','u','v') || + avctx->codec_tag == MKTAG(3, 0, 0, 0) || + avctx->codec_tag == MKTAG('W','R','A','W')) + context->flip = 1; + + if (avctx->codec_tag == AV_RL32("yuv2") && + avctx->pix_fmt == AV_PIX_FMT_YUYV422) + context->is_yuv2 = 1; + + return 0; +} + +static void flip(AVCodecContext *avctx, AVPicture *picture) +{ + picture->data[0] += picture->linesize[0] * (avctx->height - 1); + picture->linesize[0] *= -1; +} + +static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + RawVideoContext *context = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int linesize_align = 4; + int res, len; + int need_copy = !avpkt->buf || context->is_2_4_bpp || context->is_yuv2; + + AVFrame *frame = data; + AVPicture *picture = data; + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + frame->reordered_opaque = avctx->reordered_opaque; + frame->pkt_pts = avctx->pkt->pts; + av_frame_set_pkt_pos (frame, avctx->pkt->pos); + av_frame_set_pkt_duration(frame, avctx->pkt->duration); + + if (context->tff >= 0) { + frame->interlaced_frame = 1; + frame->top_field_first = context->tff; + } + + if ((res = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) + return res; + + if (need_copy) + frame->buf[0] = av_buffer_alloc(context->frame_size); + else + frame->buf[0] = av_buffer_ref(avpkt->buf); + if (!frame->buf[0]) + return AVERROR(ENOMEM); + + //2bpp and 4bpp raw in avi and mov (yes this is ugly ...) + if (context->is_2_4_bpp) { + int i; + uint8_t *dst = frame->buf[0]->data; + buf_size = context->frame_size - AVPALETTE_SIZE; + if (avctx->bits_per_coded_sample == 4) { + for (i = 0; 2 * i + 1 < buf_size && isize; i++) { + dst[2 * i + 0] = buf[i] >> 4; + dst[2 * i + 1] = buf[i] & 15; + } + linesize_align = 8; + } else { + av_assert0(avctx->bits_per_coded_sample == 2); + for (i = 0; 4 * i + 3 < buf_size && isize; i++) { + dst[4 * i + 0] = buf[i] >> 6; + dst[4 * i + 1] = buf[i] >> 4 & 3; + dst[4 * i + 2] = buf[i] >> 2 & 3; + dst[4 * i + 3] = buf[i] & 3; + } + linesize_align = 16; + } + buf = dst; + } else if (need_copy) { + memcpy(frame->buf[0]->data, buf, FFMIN(buf_size, context->frame_size)); + buf = frame->buf[0]->data; + } + + if (avctx->codec_tag == MKTAG('A', 'V', '1', 'x') || + avctx->codec_tag == MKTAG('A', 'V', 'u', 'p')) + buf += buf_size - context->frame_size; + + len = context->frame_size - (avctx->pix_fmt==AV_PIX_FMT_PAL8 ? AVPALETTE_SIZE : 0); + if (buf_size < len) { + av_log(avctx, AV_LOG_ERROR, "Invalid buffer size, packet size %d < expected frame_size %d\n", buf_size, len); + return AVERROR(EINVAL); + } + + if ((res = avpicture_fill(picture, buf, avctx->pix_fmt, + avctx->width, avctx->height)) < 0) + return res; + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, + NULL); + + if (pal) { + av_buffer_unref(&context->palette); + context->palette = av_buffer_alloc(AVPALETTE_SIZE); + if (!context->palette) + return AVERROR(ENOMEM); + memcpy(context->palette->data, pal, AVPALETTE_SIZE); + frame->palette_has_changed = 1; + } + } + + if ((avctx->pix_fmt==AV_PIX_FMT_BGR24 || + avctx->pix_fmt==AV_PIX_FMT_GRAY8 || + avctx->pix_fmt==AV_PIX_FMT_RGB555LE || + avctx->pix_fmt==AV_PIX_FMT_RGB555BE || + avctx->pix_fmt==AV_PIX_FMT_RGB565LE || + avctx->pix_fmt==AV_PIX_FMT_MONOWHITE || + avctx->pix_fmt==AV_PIX_FMT_PAL8) && + FFALIGN(frame->linesize[0], linesize_align) * avctx->height <= buf_size) + frame->linesize[0] = FFALIGN(frame->linesize[0], linesize_align); + + if (avctx->pix_fmt == AV_PIX_FMT_NV12 && avctx->codec_tag == MKTAG('N', 'V', '1', '2') && + FFALIGN(frame->linesize[0], linesize_align) * avctx->height + + FFALIGN(frame->linesize[1], linesize_align) * ((avctx->height + 1) / 2) <= buf_size) { + int la0 = FFALIGN(frame->linesize[0], linesize_align); + frame->data[1] += (la0 - frame->linesize[0]) * avctx->height; + frame->linesize[0] = la0; + frame->linesize[1] = FFALIGN(frame->linesize[1], linesize_align); + } + + if ((avctx->pix_fmt == AV_PIX_FMT_PAL8 && buf_size < context->frame_size) || + (desc->flags & PIX_FMT_PSEUDOPAL)) { + frame->buf[1] = av_buffer_ref(context->palette); + if (!frame->buf[1]) + return AVERROR(ENOMEM); + frame->data[1] = frame->buf[1]->data; + } + + if (avctx->pix_fmt == AV_PIX_FMT_BGR24 && + ((frame->linesize[0] + 3) & ~3) * avctx->height <= buf_size) + frame->linesize[0] = (frame->linesize[0] + 3) & ~3; + + if (context->flip) + flip(avctx, picture); + + if (avctx->codec_tag == MKTAG('Y', 'V', '1', '2') || + avctx->codec_tag == MKTAG('Y', 'V', '1', '6') || + avctx->codec_tag == MKTAG('Y', 'V', '2', '4') || + avctx->codec_tag == MKTAG('Y', 'V', 'U', '9')) + FFSWAP(uint8_t *, picture->data[1], picture->data[2]); + + if (avctx->codec_tag == AV_RL32("I420") && (avctx->width+1)*(avctx->height+1) * 3/2 == buf_size) { + picture->data[1] = picture->data[1] + (avctx->width+1)*(avctx->height+1) -avctx->width*avctx->height; + picture->data[2] = picture->data[2] + ((avctx->width+1)*(avctx->height+1) -avctx->width*avctx->height)*5/4; + } + + if (avctx->codec_tag == AV_RL32("yuv2") && + avctx->pix_fmt == AV_PIX_FMT_YUYV422) { + int x, y; + uint8_t *line = picture->data[0]; + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) + line[2 * x + 1] ^= 0x80; + line += picture->linesize[0]; + } + } + if (avctx->codec_tag == AV_RL32("YVYU") && + avctx->pix_fmt == AV_PIX_FMT_YUYV422) { + int x, y; + uint8_t *line = picture->data[0]; + for(y = 0; y < avctx->height; y++) { + for(x = 0; x < avctx->width - 1; x += 2) + FFSWAP(uint8_t, line[2*x + 1], line[2*x + 3]); + line += picture->linesize[0]; + } + } + + if (avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ + frame->interlaced_frame = 1; + if (avctx->field_order == AV_FIELD_TT || avctx->field_order == AV_FIELD_TB) + frame->top_field_first = 1; + } + + *got_frame = 1; + return buf_size; +} + +static av_cold int raw_close_decoder(AVCodecContext *avctx) +{ + RawVideoContext *context = avctx->priv_data; + + av_buffer_unref(&context->palette); + return 0; +} + +AVCodec ff_rawvideo_decoder = { + .name = "rawvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RAWVIDEO, + .priv_data_size = sizeof(RawVideoContext), + .init = raw_init_decoder, + .close = raw_close_decoder, + .decode = raw_decode, + .long_name = NULL_IF_CONFIG_SMALL("raw video"), + .priv_class = &class, +}; diff --git a/ffmpeg/libavcodec/rawenc.c b/ffmpeg/libavcodec/rawenc.c new file mode 100644 index 0000000..c6da6b8 --- /dev/null +++ b/ffmpeg/libavcodec/rawenc.c @@ -0,0 +1,80 @@ +/* + * Raw Video Encoder + * Copyright (c) 2001 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * Raw Video Encoder + */ + +#include "avcodec.h" +#include "raw.h" +#include "internal.h" +#include "libavutil/pixdesc.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/internal.h" + +static av_cold int raw_init_encoder(AVCodecContext *avctx) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + + avctx->coded_frame = avctx->priv_data; + avcodec_get_frame_defaults(avctx->coded_frame); + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc); + if(!avctx->codec_tag) + avctx->codec_tag = avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt); + return 0; +} + +static int raw_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + int ret = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + + if (ret < 0) + return ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, ret)) < 0) + return ret; + if ((ret = avpicture_layout((const AVPicture *)frame, avctx->pix_fmt, avctx->width, + avctx->height, pkt->data, pkt->size)) < 0) + return ret; + + if(avctx->codec_tag == AV_RL32("yuv2") && ret > 0 && + avctx->pix_fmt == AV_PIX_FMT_YUYV422) { + int x; + for(x = 1; x < avctx->height*avctx->width*2; x += 2) + pkt->data[x] ^= 0x80; + } + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +AVCodec ff_rawvideo_encoder = { + .name = "rawvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RAWVIDEO, + .priv_data_size = sizeof(AVFrame), + .init = raw_init_encoder, + .encode2 = raw_encode, + .long_name = NULL_IF_CONFIG_SMALL("raw video"), +}; diff --git a/ffmpeg/libavcodec/rdft.c b/ffmpeg/libavcodec/rdft.c new file mode 100644 index 0000000..ebddd8b --- /dev/null +++ b/ffmpeg/libavcodec/rdft.c @@ -0,0 +1,133 @@ +/* + * (I)RDFT transforms + * Copyright (c) 2009 Alex Converse + * + * 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 +#include "libavutil/mathematics.h" +#include "rdft.h" + +/** + * @file + * (Inverse) Real Discrete Fourier Transforms. + */ + +/* sin(2*pi*x/n) for 0<=xnbits; + const float k1 = 0.5; + const float k2 = 0.5 - s->inverse; + const FFTSample *tcos = s->tcos; + const FFTSample *tsin = s->tsin; + + if (!s->inverse) { + s->fft.fft_permute(&s->fft, (FFTComplex*)data); + s->fft.fft_calc(&s->fft, (FFTComplex*)data); + } + /* i=0 is a special case because of packing, the DC term is real, so we + are going to throw the N/2 term (also real) in with it. */ + ev.re = data[0]; + data[0] = ev.re+data[1]; + data[1] = ev.re-data[1]; + for (i = 1; i < (n>>2); i++) { + i1 = 2*i; + i2 = n-i1; + /* Separate even and odd FFTs */ + ev.re = k1*(data[i1 ]+data[i2 ]); + od.im = -k2*(data[i1 ]-data[i2 ]); + ev.im = k1*(data[i1+1]-data[i2+1]); + od.re = k2*(data[i1+1]+data[i2+1]); + /* Apply twiddle factors to the odd FFT and add to the even FFT */ + data[i1 ] = ev.re + od.re*tcos[i] - od.im*tsin[i]; + data[i1+1] = ev.im + od.im*tcos[i] + od.re*tsin[i]; + data[i2 ] = ev.re - od.re*tcos[i] + od.im*tsin[i]; + data[i2+1] = -ev.im + od.im*tcos[i] + od.re*tsin[i]; + } + data[2*i+1]=s->sign_convention*data[2*i+1]; + if (s->inverse) { + data[0] *= k1; + data[1] *= k1; + s->fft.fft_permute(&s->fft, (FFTComplex*)data); + s->fft.fft_calc(&s->fft, (FFTComplex*)data); + } +} + +av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans) +{ + int n = 1 << nbits; + int i; + const double theta = (trans == DFT_R2C || trans == DFT_C2R ? -1 : 1)*2*M_PI/n; + + s->nbits = nbits; + s->inverse = trans == IDFT_C2R || trans == DFT_C2R; + s->sign_convention = trans == IDFT_R2C || trans == DFT_C2R ? 1 : -1; + + if (nbits < 4 || nbits > 16) + return -1; + + if (ff_fft_init(&s->fft, nbits-1, trans == IDFT_C2R || trans == IDFT_R2C) < 0) + return -1; + + ff_init_ff_cos_tabs(nbits); + s->tcos = ff_cos_tabs[nbits]; + s->tsin = ff_sin_tabs[nbits]+(trans == DFT_R2C || trans == DFT_C2R)*(n>>2); +#if !CONFIG_HARDCODED_TABLES + for (i = 0; i < (n>>2); i++) { + s->tsin[i] = sin(i*theta); + } +#endif + s->rdft_calc = ff_rdft_calc_c; + + if (ARCH_ARM) ff_rdft_init_arm(s); + + return 0; +} + +av_cold void ff_rdft_end(RDFTContext *s) +{ + ff_fft_end(&s->fft); +} diff --git a/ffmpeg/libavcodec/rdft.h b/ffmpeg/libavcodec/rdft.h new file mode 100644 index 0000000..5fb0323 --- /dev/null +++ b/ffmpeg/libavcodec/rdft.h @@ -0,0 +1,74 @@ +/* + * (I)RDFT transforms + * Copyright (c) 2009 Alex Converse + * + * 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 + */ + +#ifndef AVCODEC_RDFT_H +#define AVCODEC_RDFT_H + +#include "config.h" +#include "fft.h" + +#if CONFIG_HARDCODED_TABLES +# define SINTABLE_CONST const +#else +# define SINTABLE_CONST +#endif + +#define SINTABLE(size) \ + SINTABLE_CONST DECLARE_ALIGNED(16, FFTSample, ff_sin_##size)[size/2] + +extern SINTABLE(16); +extern SINTABLE(32); +extern SINTABLE(64); +extern SINTABLE(128); +extern SINTABLE(256); +extern SINTABLE(512); +extern SINTABLE(1024); +extern SINTABLE(2048); +extern SINTABLE(4096); +extern SINTABLE(8192); +extern SINTABLE(16384); +extern SINTABLE(32768); +extern SINTABLE(65536); + +struct RDFTContext { + int nbits; + int inverse; + int sign_convention; + + /* pre/post rotation tables */ + const FFTSample *tcos; + SINTABLE_CONST FFTSample *tsin; + FFTContext fft; + void (*rdft_calc)(struct RDFTContext *s, FFTSample *z); +}; + +/** + * Set up a real FFT. + * @param nbits log2 of the length of the input array + * @param trans the type of transform + */ +int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans); +void ff_rdft_end(RDFTContext *s); + +void ff_rdft_init_arm(RDFTContext *s); + + +#endif /* AVCODEC_RDFT_H */ diff --git a/ffmpeg/libavcodec/realtextdec.c b/ffmpeg/libavcodec/realtextdec.c new file mode 100644 index 0000000..4578897 --- /dev/null +++ b/ffmpeg/libavcodec/realtextdec.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012 Clément Bœsch + * + * 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 + */ + +/** + * @file + * RealText subtitle decoder + * @see http://service.real.com/help/library/guides/ProductionGuide/prodguide/htmfiles/realtext.htm + */ + +#include "avcodec.h" +#include "ass.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" + +static int rt_event_to_ass(AVBPrint *buf, const char *p) +{ + int prev_chr_is_space = 1; + + while (*p) { + if (*p != '<') { + if (!av_isspace(*p)) + av_bprint_chars(buf, *p, 1); + else if (!prev_chr_is_space) + av_bprint_chars(buf, ' ', 1); + prev_chr_is_space = av_isspace(*p); + } else { + const char *end = strchr(p, '>'); + if (!end) + break; + if (!av_strncasecmp(p, "
", 5) || + !av_strncasecmp(p, "
", 4)) { + av_bprintf(buf, "\\N"); + } + p = end; + } + p++; + } + av_bprintf(buf, "\r\n"); + return 0; +} + +static int realtext_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + AVBPrint buf; + + av_bprint_init(&buf, 0, 4096); + // note: no need to rescale pts & duration since they are in the same + // timebase as ASS (1/100) + if (ptr && avpkt->size > 0 && !rt_event_to_ass(&buf, ptr)) + ff_ass_add_rect(sub, buf.str, avpkt->pts, avpkt->duration, 0); + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +AVCodec ff_realtext_decoder = { + .name = "realtext", + .long_name = NULL_IF_CONFIG_SMALL("RealText subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_REALTEXT, + .decode = realtext_decode_frame, + .init = ff_ass_subtitle_header_default, +}; diff --git a/ffmpeg/libavcodec/rectangle.h b/ffmpeg/libavcodec/rectangle.h new file mode 100644 index 0000000..594a760 --- /dev/null +++ b/ffmpeg/libavcodec/rectangle.h @@ -0,0 +1,124 @@ +/* + * rectangle filling function + * Copyright (c) 2003 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 + */ + +/** + * @file + * useful rectangle filling function + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_RECTANGLE_H +#define AVCODEC_RECTANGLE_H + +#include "config.h" +#include "libavutil/common.h" +#include "libavutil/avassert.h" + +/** + * fill a rectangle. + * @param h height of the rectangle, should be a constant + * @param w width of the rectangle, should be a constant + * @param size the size of val (1, 2 or 4), should be a constant + */ +static av_always_inline void fill_rectangle(void *vp, int w, int h, int stride, uint32_t val, int size){ + uint8_t *p= (uint8_t*)vp; + av_assert2(size==1 || size==2 || size==4); + av_assert2(w<=4); + + w *= size; + stride *= size; + + av_assert2((((long)vp)&(FFMIN(w, 8<<(HAVE_NEON|ARCH_PPC|HAVE_MMX))-1)) == 0); + av_assert2((stride&(w-1))==0); + if(w==2){ + const uint16_t v= size==4 ? val : val*0x0101; + *(uint16_t*)(p + 0*stride)= v; + if(h==1) return; + *(uint16_t*)(p + 1*stride)= v; + if(h==2) return; + *(uint16_t*)(p + 2*stride)= v; + *(uint16_t*)(p + 3*stride)= v; + }else if(w==4){ + const uint32_t v= size==4 ? val : size==2 ? val*0x00010001 : val*0x01010101; + *(uint32_t*)(p + 0*stride)= v; + if(h==1) return; + *(uint32_t*)(p + 1*stride)= v; + if(h==2) return; + *(uint32_t*)(p + 2*stride)= v; + *(uint32_t*)(p + 3*stride)= v; + }else if(w==8){ + //gcc can't optimize 64bit math on x86_32 +#if HAVE_FAST_64BIT + const uint64_t v= size==2 ? val*0x0001000100010001ULL : val*0x0100000001ULL; + *(uint64_t*)(p + 0*stride)= v; + if(h==1) return; + *(uint64_t*)(p + 1*stride)= v; + if(h==2) return; + *(uint64_t*)(p + 2*stride)= v; + *(uint64_t*)(p + 3*stride)= v; + }else if(w==16){ + const uint64_t v= val*0x0100000001ULL; + *(uint64_t*)(p + 0+0*stride)= v; + *(uint64_t*)(p + 8+0*stride)= v; + *(uint64_t*)(p + 0+1*stride)= v; + *(uint64_t*)(p + 8+1*stride)= v; + if(h==2) return; + *(uint64_t*)(p + 0+2*stride)= v; + *(uint64_t*)(p + 8+2*stride)= v; + *(uint64_t*)(p + 0+3*stride)= v; + *(uint64_t*)(p + 8+3*stride)= v; +#else + const uint32_t v= size==2 ? val*0x00010001 : val; + *(uint32_t*)(p + 0+0*stride)= v; + *(uint32_t*)(p + 4+0*stride)= v; + if(h==1) return; + *(uint32_t*)(p + 0+1*stride)= v; + *(uint32_t*)(p + 4+1*stride)= v; + if(h==2) return; + *(uint32_t*)(p + 0+2*stride)= v; + *(uint32_t*)(p + 4+2*stride)= v; + *(uint32_t*)(p + 0+3*stride)= v; + *(uint32_t*)(p + 4+3*stride)= v; + }else if(w==16){ + *(uint32_t*)(p + 0+0*stride)= val; + *(uint32_t*)(p + 4+0*stride)= val; + *(uint32_t*)(p + 8+0*stride)= val; + *(uint32_t*)(p +12+0*stride)= val; + *(uint32_t*)(p + 0+1*stride)= val; + *(uint32_t*)(p + 4+1*stride)= val; + *(uint32_t*)(p + 8+1*stride)= val; + *(uint32_t*)(p +12+1*stride)= val; + if(h==2) return; + *(uint32_t*)(p + 0+2*stride)= val; + *(uint32_t*)(p + 4+2*stride)= val; + *(uint32_t*)(p + 8+2*stride)= val; + *(uint32_t*)(p +12+2*stride)= val; + *(uint32_t*)(p + 0+3*stride)= val; + *(uint32_t*)(p + 4+3*stride)= val; + *(uint32_t*)(p + 8+3*stride)= val; + *(uint32_t*)(p +12+3*stride)= val; +#endif + }else + av_assert2(0); + av_assert2(h==4); +} + +#endif /* AVCODEC_RECTANGLE_H */ diff --git a/ffmpeg/libavcodec/remove_extradata_bsf.c b/ffmpeg/libavcodec/remove_extradata_bsf.c new file mode 100644 index 0000000..f0d9b45 --- /dev/null +++ b/ffmpeg/libavcodec/remove_extradata_bsf.c @@ -0,0 +1,55 @@ +/* + * copyright (c) 2006 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 "avcodec.h" + + +static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size, int keyframe){ + int cmd= args ? *args : 0; + AVCodecParserContext *s; + + if(!bsfc->parser){ + bsfc->parser= av_parser_init(avctx->codec_id); + } + s= bsfc->parser; + + if(s && s->parser->split){ + if( (((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) || (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) && cmd=='a') + ||(!keyframe && cmd=='k') + ||(cmd=='e' || !cmd) + ){ + int i= s->parser->split(avctx, buf, buf_size); + buf += i; + buf_size -= i; + } + } + *poutbuf= (uint8_t *) buf; + *poutbuf_size= buf_size; + + return 0; +} + +AVBitStreamFilter ff_remove_extradata_bsf={ + "remove_extra", + 0, + remove_extradata, +}; diff --git a/ffmpeg/libavcodec/resample.c b/ffmpeg/libavcodec/resample.c new file mode 100644 index 0000000..f950288 --- /dev/null +++ b/ffmpeg/libavcodec/resample.c @@ -0,0 +1,435 @@ +/* + * samplerate conversion for both audio and video + * Copyright (c) 2000 Fabrice Bellard + * + * 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 + */ + +/** + * @file + * samplerate conversion for both audio and video + */ + +#include + +#include "avcodec.h" +#include "audioconvert.h" +#include "libavutil/opt.h" +#include "libavutil/mem.h" +#include "libavutil/samplefmt.h" + +#if FF_API_AVCODEC_RESAMPLE + +#define MAX_CHANNELS 8 + +struct AVResampleContext; + +static const char *context_to_name(void *ptr) +{ + return "audioresample"; +} + +static const AVOption options[] = {{NULL}}; +static const AVClass audioresample_context_class = { + "ReSampleContext", context_to_name, options, LIBAVUTIL_VERSION_INT +}; + +struct ReSampleContext { + struct AVResampleContext *resample_context; + short *temp[MAX_CHANNELS]; + int temp_len; + float ratio; + /* channel convert */ + int input_channels, output_channels, filter_channels; + AVAudioConvert *convert_ctx[2]; + enum AVSampleFormat sample_fmt[2]; ///< input and output sample format + unsigned sample_size[2]; ///< size of one sample in sample_fmt + short *buffer[2]; ///< buffers used for conversion to S16 + unsigned buffer_size[2]; ///< sizes of allocated buffers +}; + +/* n1: number of samples */ +static void stereo_to_mono(short *output, short *input, int n1) +{ + short *p, *q; + int n = n1; + + p = input; + q = output; + while (n >= 4) { + q[0] = (p[0] + p[1]) >> 1; + q[1] = (p[2] + p[3]) >> 1; + q[2] = (p[4] + p[5]) >> 1; + q[3] = (p[6] + p[7]) >> 1; + q += 4; + p += 8; + n -= 4; + } + while (n > 0) { + q[0] = (p[0] + p[1]) >> 1; + q++; + p += 2; + n--; + } +} + +/* n1: number of samples */ +static void mono_to_stereo(short *output, short *input, int n1) +{ + short *p, *q; + int n = n1; + int v; + + p = input; + q = output; + while (n >= 4) { + v = p[0]; q[0] = v; q[1] = v; + v = p[1]; q[2] = v; q[3] = v; + v = p[2]; q[4] = v; q[5] = v; + v = p[3]; q[6] = v; q[7] = v; + q += 8; + p += 4; + n -= 4; + } + while (n > 0) { + v = p[0]; q[0] = v; q[1] = v; + q += 2; + p += 1; + n--; + } +} + +/* +5.1 to stereo input: [fl, fr, c, lfe, rl, rr] +- Left = front_left + rear_gain * rear_left + center_gain * center +- Right = front_right + rear_gain * rear_right + center_gain * center +Where rear_gain is usually around 0.5-1.0 and + center_gain is almost always 0.7 (-3 dB) +*/ +static void surround_to_stereo(short **output, short *input, int channels, int samples) +{ + int i; + short l, r; + + for (i = 0; i < samples; i++) { + int fl,fr,c,rl,rr; + fl = input[0]; + fr = input[1]; + c = input[2]; + // lfe = input[3]; + rl = input[4]; + rr = input[5]; + + l = av_clip_int16(fl + (0.5 * rl) + (0.7 * c)); + r = av_clip_int16(fr + (0.5 * rr) + (0.7 * c)); + + /* output l & r. */ + *output[0]++ = l; + *output[1]++ = r; + + /* increment input. */ + input += channels; + } +} + +static void deinterleave(short **output, short *input, int channels, int samples) +{ + int i, j; + + for (i = 0; i < samples; i++) { + for (j = 0; j < channels; j++) { + *output[j]++ = *input++; + } + } +} + +static void interleave(short *output, short **input, int channels, int samples) +{ + int i, j; + + for (i = 0; i < samples; i++) { + for (j = 0; j < channels; j++) { + *output++ = *input[j]++; + } + } +} + +static void ac3_5p1_mux(short *output, short *input1, short *input2, int n) +{ + int i; + short l, r; + + for (i = 0; i < n; i++) { + l = *input1++; + r = *input2++; + *output++ = l; /* left */ + *output++ = (l / 2) + (r / 2); /* center */ + *output++ = r; /* right */ + *output++ = 0; /* left surround */ + *output++ = 0; /* right surroud */ + *output++ = 0; /* low freq */ + } +} + +#define SUPPORT_RESAMPLE(ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8) \ + ch8<<7 | ch7<<6 | ch6<<5 | ch5<<4 | ch4<<3 | ch3<<2 | ch2<<1 | ch1<<0 + +static const uint8_t supported_resampling[MAX_CHANNELS] = { + // output ch: 1 2 3 4 5 6 7 8 + SUPPORT_RESAMPLE(1, 1, 0, 0, 0, 0, 0, 0), // 1 input channel + SUPPORT_RESAMPLE(1, 1, 0, 0, 0, 1, 0, 0), // 2 input channels + SUPPORT_RESAMPLE(0, 0, 1, 0, 0, 0, 0, 0), // 3 input channels + SUPPORT_RESAMPLE(0, 0, 0, 1, 0, 0, 0, 0), // 4 input channels + SUPPORT_RESAMPLE(0, 0, 0, 0, 1, 0, 0, 0), // 5 input channels + SUPPORT_RESAMPLE(0, 1, 0, 0, 0, 1, 0, 0), // 6 input channels + SUPPORT_RESAMPLE(0, 0, 0, 0, 0, 0, 1, 0), // 7 input channels + SUPPORT_RESAMPLE(0, 0, 0, 0, 0, 0, 0, 1), // 8 input channels +}; + +ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, + int output_rate, int input_rate, + enum AVSampleFormat sample_fmt_out, + enum AVSampleFormat sample_fmt_in, + int filter_length, int log2_phase_count, + int linear, double cutoff) +{ + ReSampleContext *s; + + if (input_channels > MAX_CHANNELS) { + av_log(NULL, AV_LOG_ERROR, + "Resampling with input channels greater than %d is unsupported.\n", + MAX_CHANNELS); + return NULL; + } + if (!(supported_resampling[input_channels-1] & (1<<(output_channels-1)))) { + int i; + av_log(NULL, AV_LOG_ERROR, "Unsupported audio resampling. Allowed " + "output channels for %d input channel%s", input_channels, + input_channels > 1 ? "s:" : ":"); + for (i = 0; i < MAX_CHANNELS; i++) + if (supported_resampling[input_channels-1] & (1<ratio = (float)output_rate / (float)input_rate; + + s->input_channels = input_channels; + s->output_channels = output_channels; + + s->filter_channels = s->input_channels; + if (s->output_channels < s->filter_channels) + s->filter_channels = s->output_channels; + + s->sample_fmt[0] = sample_fmt_in; + s->sample_fmt[1] = sample_fmt_out; + s->sample_size[0] = av_get_bytes_per_sample(s->sample_fmt[0]); + s->sample_size[1] = av_get_bytes_per_sample(s->sample_fmt[1]); + + if (s->sample_fmt[0] != AV_SAMPLE_FMT_S16) { + if (!(s->convert_ctx[0] = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, + s->sample_fmt[0], 1, NULL, 0))) { + av_log(s, AV_LOG_ERROR, + "Cannot convert %s sample format to s16 sample format\n", + av_get_sample_fmt_name(s->sample_fmt[0])); + av_free(s); + return NULL; + } + } + + if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) { + if (!(s->convert_ctx[1] = av_audio_convert_alloc(s->sample_fmt[1], 1, + AV_SAMPLE_FMT_S16, 1, NULL, 0))) { + av_log(s, AV_LOG_ERROR, + "Cannot convert s16 sample format to %s sample format\n", + av_get_sample_fmt_name(s->sample_fmt[1])); + av_audio_convert_free(s->convert_ctx[0]); + av_free(s); + return NULL; + } + } + + s->resample_context = av_resample_init(output_rate, input_rate, + filter_length, log2_phase_count, + linear, cutoff); + + *(const AVClass**)s->resample_context = &audioresample_context_class; + + return s; +} + +/* resample audio. 'nb_samples' is the number of input samples */ +/* XXX: optimize it ! */ +int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) +{ + int i, nb_samples1; + short *bufin[MAX_CHANNELS]; + short *bufout[MAX_CHANNELS]; + short *buftmp2[MAX_CHANNELS], *buftmp3[MAX_CHANNELS]; + short *output_bak = NULL; + int lenout; + + if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { + /* nothing to do */ + memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); + return nb_samples; + } + + if (s->sample_fmt[0] != AV_SAMPLE_FMT_S16) { + int istride[1] = { s->sample_size[0] }; + int ostride[1] = { 2 }; + const void *ibuf[1] = { input }; + void *obuf[1]; + unsigned input_size = nb_samples * s->input_channels * 2; + + if (!s->buffer_size[0] || s->buffer_size[0] < input_size) { + av_free(s->buffer[0]); + s->buffer_size[0] = input_size; + s->buffer[0] = av_malloc(s->buffer_size[0]); + if (!s->buffer[0]) { + av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); + return 0; + } + } + + obuf[0] = s->buffer[0]; + + if (av_audio_convert(s->convert_ctx[0], obuf, ostride, + ibuf, istride, nb_samples * s->input_channels) < 0) { + av_log(s->resample_context, AV_LOG_ERROR, + "Audio sample format conversion failed\n"); + return 0; + } + + input = s->buffer[0]; + } + + lenout= 2*s->output_channels*nb_samples * s->ratio + 16; + + if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) { + int out_size = lenout * av_get_bytes_per_sample(s->sample_fmt[1]) * + s->output_channels; + output_bak = output; + + if (!s->buffer_size[1] || s->buffer_size[1] < out_size) { + av_free(s->buffer[1]); + s->buffer_size[1] = out_size; + s->buffer[1] = av_malloc(s->buffer_size[1]); + if (!s->buffer[1]) { + av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); + return 0; + } + } + + output = s->buffer[1]; + } + + /* XXX: move those malloc to resample init code */ + for (i = 0; i < s->filter_channels; i++) { + bufin[i] = av_malloc((nb_samples + s->temp_len) * sizeof(short)); + memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short)); + buftmp2[i] = bufin[i] + s->temp_len; + bufout[i] = av_malloc(lenout * sizeof(short)); + } + + if (s->input_channels == 2 && s->output_channels == 1) { + buftmp3[0] = output; + stereo_to_mono(buftmp2[0], input, nb_samples); + } else if (s->output_channels >= 2 && s->input_channels == 1) { + buftmp3[0] = bufout[0]; + memcpy(buftmp2[0], input, nb_samples * sizeof(short)); + } else if (s->input_channels == 6 && s->output_channels ==2) { + buftmp3[0] = bufout[0]; + buftmp3[1] = bufout[1]; + surround_to_stereo(buftmp2, input, s->input_channels, nb_samples); + } else if (s->output_channels >= s->input_channels && s->input_channels >= 2) { + for (i = 0; i < s->input_channels; i++) { + buftmp3[i] = bufout[i]; + } + deinterleave(buftmp2, input, s->input_channels, nb_samples); + } else { + buftmp3[0] = output; + memcpy(buftmp2[0], input, nb_samples * sizeof(short)); + } + + nb_samples += s->temp_len; + + /* resample each channel */ + nb_samples1 = 0; /* avoid warning */ + for (i = 0; i < s->filter_channels; i++) { + int consumed; + int is_last = i + 1 == s->filter_channels; + + nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], + &consumed, nb_samples, lenout, is_last); + s->temp_len = nb_samples - consumed; + s->temp[i] = av_realloc(s->temp[i], s->temp_len * sizeof(short)); + memcpy(s->temp[i], bufin[i] + consumed, s->temp_len * sizeof(short)); + } + + if (s->output_channels == 2 && s->input_channels == 1) { + mono_to_stereo(output, buftmp3[0], nb_samples1); + } else if (s->output_channels == 6 && s->input_channels == 2) { + ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); + } else if ((s->output_channels == s->input_channels && s->input_channels >= 2) || + (s->output_channels == 2 && s->input_channels == 6)) { + interleave(output, buftmp3, s->output_channels, nb_samples1); + } + + if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) { + int istride[1] = { 2 }; + int ostride[1] = { s->sample_size[1] }; + const void *ibuf[1] = { output }; + void *obuf[1] = { output_bak }; + + if (av_audio_convert(s->convert_ctx[1], obuf, ostride, + ibuf, istride, nb_samples1 * s->output_channels) < 0) { + av_log(s->resample_context, AV_LOG_ERROR, + "Audio sample format conversion failed\n"); + return 0; + } + } + + for (i = 0; i < s->filter_channels; i++) { + av_free(bufin[i]); + av_free(bufout[i]); + } + + return nb_samples1; +} + +void audio_resample_close(ReSampleContext *s) +{ + int i; + av_resample_close(s->resample_context); + for (i = 0; i < s->filter_channels; i++) + av_freep(&s->temp[i]); + av_freep(&s->buffer[0]); + av_freep(&s->buffer[1]); + av_audio_convert_free(s->convert_ctx[0]); + av_audio_convert_free(s->convert_ctx[1]); + av_free(s); +} + +#endif diff --git a/ffmpeg/libavcodec/resample2.c b/ffmpeg/libavcodec/resample2.c new file mode 100644 index 0000000..9b63b53 --- /dev/null +++ b/ffmpeg/libavcodec/resample2.c @@ -0,0 +1,319 @@ +/* + * audio resampling + * Copyright (c) 2004 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 + */ + +/** + * @file + * audio resampling + * @author Michael Niedermayer + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "libavutil/common.h" + +#if FF_API_AVCODEC_RESAMPLE + +#ifndef CONFIG_RESAMPLE_HP +#define FILTER_SHIFT 15 + +#define FELEM int16_t +#define FELEM2 int32_t +#define FELEML int64_t +#define FELEM_MAX INT16_MAX +#define FELEM_MIN INT16_MIN +#define WINDOW_TYPE 9 +#elif !defined(CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE) +#define FILTER_SHIFT 30 + +#define FELEM int32_t +#define FELEM2 int64_t +#define FELEML int64_t +#define FELEM_MAX INT32_MAX +#define FELEM_MIN INT32_MIN +#define WINDOW_TYPE 12 +#else +#define FILTER_SHIFT 0 + +#define FELEM double +#define FELEM2 double +#define FELEML double +#define WINDOW_TYPE 24 +#endif + + +typedef struct AVResampleContext{ + const AVClass *av_class; + FELEM *filter_bank; + int filter_length; + int ideal_dst_incr; + int dst_incr; + int index; + int frac; + int src_incr; + int compensation_distance; + int phase_shift; + int phase_mask; + int linear; +}AVResampleContext; + +/** + * 0th order modified bessel function of the first kind. + */ +static double bessel(double x){ + double v=1; + double lastv=0; + double t=1; + int i; + + x= x*x/4; + for(i=1; v != lastv; i++){ + lastv=v; + t *= x/(i*i); + v += t; + } + return v; +} + +/** + * Build a polyphase filterbank. + * @param factor resampling factor + * @param scale wanted sum of coefficients for each filter + * @param type 0->cubic, 1->blackman nuttall windowed sinc, 2..16->kaiser windowed sinc beta=2..16 + * @return 0 on success, negative on error + */ +static int build_filter(FELEM *filter, double factor, int tap_count, int phase_count, int scale, int type){ + int ph, i; + double x, y, w; + double *tab = av_malloc(tap_count * sizeof(*tab)); + const int center= (tap_count-1)/2; + + if (!tab) + return AVERROR(ENOMEM); + + /* if upsampling, only need to interpolate, no filter */ + if (factor > 1.0) + factor = 1.0; + + for(ph=0;phphase_shift= phase_shift; + c->phase_mask= phase_count-1; + c->linear= linear; + + c->filter_length= FFMAX((int)ceil(filter_size/factor), 1); + c->filter_bank= av_mallocz(c->filter_length*(phase_count+1)*sizeof(FELEM)); + if (!c->filter_bank) + goto error; + if (build_filter(c->filter_bank, factor, c->filter_length, phase_count, 1<filter_bank[c->filter_length*phase_count+1], c->filter_bank, (c->filter_length-1)*sizeof(FELEM)); + c->filter_bank[c->filter_length*phase_count]= c->filter_bank[c->filter_length - 1]; + + if(!av_reduce(&c->src_incr, &c->dst_incr, out_rate, in_rate * (int64_t)phase_count, INT32_MAX/2)) + goto error; + c->ideal_dst_incr= c->dst_incr; + + c->index= -phase_count*((c->filter_length-1)/2); + + return c; +error: + av_free(c->filter_bank); + av_free(c); + return NULL; +} + +void av_resample_close(AVResampleContext *c){ + av_freep(&c->filter_bank); + av_freep(&c); +} + +void av_resample_compensate(AVResampleContext *c, int sample_delta, int compensation_distance){ +// sample_delta += (c->ideal_dst_incr - c->dst_incr)*(int64_t)c->compensation_distance / c->ideal_dst_incr; + c->compensation_distance= compensation_distance; + c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance; +} + +int av_resample(AVResampleContext *c, short *dst, short *src, int *consumed, int src_size, int dst_size, int update_ctx){ + int dst_index, i; + int index= c->index; + int frac= c->frac; + int dst_incr_frac= c->dst_incr % c->src_incr; + int dst_incr= c->dst_incr / c->src_incr; + int compensation_distance= c->compensation_distance; + + if(compensation_distance == 0 && c->filter_length == 1 && c->phase_shift==0){ + int64_t index2= ((int64_t)index)<<32; + int64_t incr= (1LL<<32) * c->dst_incr / c->src_incr; + dst_size= FFMIN(dst_size, (src_size-1-index) * (int64_t)c->src_incr / c->dst_incr); + + for(dst_index=0; dst_index < dst_size; dst_index++){ + dst[dst_index] = src[index2>>32]; + index2 += incr; + } + index += dst_index * dst_incr; + index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr; + frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; + }else{ + for(dst_index=0; dst_index < dst_size; dst_index++){ + FELEM *filter= c->filter_bank + c->filter_length*(index & c->phase_mask); + int sample_index= index >> c->phase_shift; + FELEM2 val=0; + + if(sample_index < 0){ + for(i=0; ifilter_length; i++) + val += src[FFABS(sample_index + i) % src_size] * filter[i]; + }else if(sample_index + c->filter_length > src_size){ + break; + }else if(c->linear){ + FELEM2 v2=0; + for(i=0; ifilter_length; i++){ + val += src[sample_index + i] * (FELEM2)filter[i]; + v2 += src[sample_index + i] * (FELEM2)filter[i + c->filter_length]; + } + val+=(v2-val)*(FELEML)frac / c->src_incr; + }else{ + for(i=0; ifilter_length; i++){ + val += src[sample_index + i] * (FELEM2)filter[i]; + } + } + +#ifdef CONFIG_RESAMPLE_AUDIOPHILE_KIDDY_MODE + dst[dst_index] = av_clip_int16(lrintf(val)); +#else + val = (val + (1<<(FILTER_SHIFT-1)))>>FILTER_SHIFT; + dst[dst_index] = (unsigned)(val + 32768) > 65535 ? (val>>31) ^ 32767 : val; +#endif + + frac += dst_incr_frac; + index += dst_incr; + if(frac >= c->src_incr){ + frac -= c->src_incr; + index++; + } + + if(dst_index + 1 == compensation_distance){ + compensation_distance= 0; + dst_incr_frac= c->ideal_dst_incr % c->src_incr; + dst_incr= c->ideal_dst_incr / c->src_incr; + } + } + } + *consumed= FFMAX(index, 0) >> c->phase_shift; + if(index>=0) index &= c->phase_mask; + + if(compensation_distance){ + compensation_distance -= dst_index; + av_assert2(compensation_distance > 0); + } + if(update_ctx){ + c->frac= frac; + c->index= index; + c->dst_incr= dst_incr_frac + c->src_incr*dst_incr; + c->compensation_distance= compensation_distance; + } + + return dst_index; +} + +#endif diff --git a/ffmpeg/libavcodec/rl.h b/ffmpeg/libavcodec/rl.h new file mode 100644 index 0000000..c80283d --- /dev/null +++ b/ffmpeg/libavcodec/rl.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000-2002 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * rl header. + */ + +#ifndef AVCODEC_RL_H +#define AVCODEC_RL_H + +#include +#include "get_bits.h" + +/* run length table */ +#define MAX_RUN 64 +#define MAX_LEVEL 64 + +/** RLTable. */ +typedef struct RLTable { + int n; ///< number of entries of table_vlc minus 1 + int last; ///< number of values for last = 0 + const uint16_t (*table_vlc)[2]; + const int8_t *table_run; + const int8_t *table_level; + uint8_t *index_run[2]; ///< encoding only + int8_t *max_level[2]; ///< encoding & decoding + int8_t *max_run[2]; ///< encoding & decoding + VLC vlc; ///< decoding only deprecated FIXME remove + RL_VLC_ELEM *rl_vlc[32]; ///< decoding only +} RLTable; + +/** + * + * @param static_store static uint8_t array[2][2*MAX_RUN + MAX_LEVEL + 3] which will hold + * the level and run tables, if this is NULL av_malloc() will be used + */ +void ff_init_rl(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3]); +void ff_init_vlc_rl(RLTable *rl); + +#define INIT_VLC_RL(rl, static_size)\ +{\ + int q;\ + static RL_VLC_ELEM rl_vlc_table[32][static_size];\ + INIT_VLC_STATIC(&rl.vlc, 9, rl.n + 1,\ + &rl.table_vlc[0][1], 4, 2,\ + &rl.table_vlc[0][0], 4, 2, static_size);\ +\ + if(!rl.rl_vlc[0]){\ + for(q=0; q<32; q++)\ + rl.rl_vlc[q]= rl_vlc_table[q];\ +\ + ff_init_vlc_rl(&rl);\ + }\ +} + +static inline int get_rl_index(const RLTable *rl, int last, int run, int level) +{ + int index; + index = rl->index_run[last][run]; + if (index >= rl->n) + return rl->n; + if (level > rl->max_level[last][run]) + return rl->n; + return index + level - 1; +} + +#endif /* AVCODEC_RL_H */ diff --git a/ffmpeg/libavcodec/rl2.c b/ffmpeg/libavcodec/rl2.c new file mode 100644 index 0000000..c8853de --- /dev/null +++ b/ffmpeg/libavcodec/rl2.c @@ -0,0 +1,226 @@ +/* + * RL2 Video Decoder + * Copyright (C) 2008 Sascha Sommer (saschasommer@freenet.de) + * + * 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 + */ + +/** + * @file + * RL2 Video Decoder + * @author Sascha Sommer (saschasommer@freenet.de) + * @see http://wiki.multimedia.cx/index.php?title=RL2 + */ + +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "avcodec.h" +#include "internal.h" + + +#define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr count, palette + +typedef struct Rl2Context { + AVCodecContext *avctx; + + uint16_t video_base; ///< initial drawing offset + uint32_t clr_count; ///< number of used colors (currently unused) + uint8_t *back_frame; ///< background frame + uint32_t palette[AVPALETTE_COUNT]; +} Rl2Context; + +/** + * Run Length Decode a single 320x200 frame + * @param s rl2 context + * @param in input buffer + * @param size input buffer size + * @param out output buffer + * @param stride stride of the output buffer + * @param video_base offset of the rle data inside the frame + */ +static void rl2_rle_decode(Rl2Context *s, const uint8_t *in, int size, + uint8_t *out, int stride, int video_base) +{ + int base_x = video_base % s->avctx->width; + int base_y = video_base / s->avctx->width; + int stride_adj = stride - s->avctx->width; + int i; + const uint8_t *back_frame = s->back_frame; + const uint8_t *in_end = in + size; + const uint8_t *out_end = out + stride * s->avctx->height; + uint8_t *line_end; + + /** copy start of the background frame */ + for (i = 0; i <= base_y; i++) { + if (s->back_frame) + memcpy(out, back_frame, s->avctx->width); + out += stride; + back_frame += s->avctx->width; + } + back_frame += base_x - s->avctx->width; + line_end = out - stride_adj; + out += base_x - stride; + + /** decode the variable part of the frame */ + while (in < in_end) { + uint8_t val = *in++; + int len = 1; + if (val >= 0x80) { + if (in >= in_end) + break; + len = *in++; + if (!len) + break; + } + + if (len >= out_end - out) + break; + + if (s->back_frame) + val |= 0x80; + else + val &= ~0x80; + + while (len--) { + *out++ = (val == 0x80) ? *back_frame : val; + back_frame++; + if (out == line_end) { + out += stride_adj; + line_end += stride; + if (len >= out_end - out) + break; + } + } + } + + /** copy the rest from the background frame */ + if (s->back_frame) { + while (out < out_end) { + memcpy(out, back_frame, line_end - out); + back_frame += line_end - out; + out = line_end + stride_adj; + line_end += stride; + } + } +} + + +/** + * Initialize the decoder + * @param avctx decoder context + * @return 0 success, -1 on error + */ +static av_cold int rl2_decode_init(AVCodecContext *avctx) +{ + Rl2Context *s = avctx->priv_data; + int back_size; + int i; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + /** parse extra data */ + if (!avctx->extradata || avctx->extradata_size < EXTRADATA1_SIZE) { + av_log(avctx, AV_LOG_ERROR, "invalid extradata size\n"); + return AVERROR(EINVAL); + } + + /** get frame_offset */ + s->video_base = AV_RL16(&avctx->extradata[0]); + s->clr_count = AV_RL32(&avctx->extradata[2]); + + if (s->video_base >= avctx->width * avctx->height) { + av_log(avctx, AV_LOG_ERROR, "invalid video_base\n"); + return AVERROR_INVALIDDATA; + } + + /** initialize palette */ + for (i = 0; i < AVPALETTE_COUNT; i++) + s->palette[i] = 0xFFU << 24 | AV_RB24(&avctx->extradata[6 + i * 3]); + + /** decode background frame if present */ + back_size = avctx->extradata_size - EXTRADATA1_SIZE; + + if (back_size > 0) { + uint8_t *back_frame = av_mallocz(avctx->width*avctx->height); + if (!back_frame) + return AVERROR(ENOMEM); + rl2_rle_decode(s, avctx->extradata + EXTRADATA1_SIZE, back_size, + back_frame, avctx->width, 0); + s->back_frame = back_frame; + } + return 0; +} + + +static int rl2_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int ret, buf_size = avpkt->size; + Rl2Context *s = avctx->priv_data; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + /** run length decode */ + rl2_rle_decode(s, buf, buf_size, frame->data[0], frame->linesize[0], + s->video_base); + + /** make the palette available on the way out */ + memcpy(frame->data[1], s->palette, AVPALETTE_SIZE); + + *got_frame = 1; + + /** report that the buffer was completely consumed */ + return buf_size; +} + + +/** + * Uninit decoder + * @param avctx decoder context + * @return 0 success, -1 on error + */ +static av_cold int rl2_decode_end(AVCodecContext *avctx) +{ + Rl2Context *s = avctx->priv_data; + + av_free(s->back_frame); + + return 0; +} + + +AVCodec ff_rl2_decoder = { + .name = "rl2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RL2, + .priv_data_size = sizeof(Rl2Context), + .init = rl2_decode_init, + .close = rl2_decode_end, + .decode = rl2_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), +}; diff --git a/ffmpeg/libavcodec/rle.c b/ffmpeg/libavcodec/rle.c new file mode 100644 index 0000000..d2ec68c --- /dev/null +++ b/ffmpeg/libavcodec/rle.c @@ -0,0 +1,85 @@ +/* + * RLE encoder + * Copyright (c) 2007 Bobby Bingham + * + * 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 "avcodec.h" +#include "rle.h" +#include "libavutil/common.h" + +/** + * Count up to 127 consecutive pixels which are either all the same or + * all differ from the previous and next pixels. + * @param start Pointer to the first pixel + * @param len Maximum number of pixels + * @param bpp Bytes per pixel + * @param same 1 if searching for identical pixel values. 0 for differing + * @return Number of matching consecutive pixels found + */ +static int count_pixels(const uint8_t *start, int len, int bpp, int same) +{ + const uint8_t *pos; + int count = 1; + + for(pos = start + bpp; count < FFMIN(127, len); pos += bpp, count ++) { + if(same != !memcmp(pos-bpp, pos, bpp)) { + if(!same) { + /* if bpp == 1, then 0 1 1 0 is more efficiently encoded as a single + * raw block of pixels. for larger bpp, RLE is as good or better */ + if(bpp == 1 && count + 1 < FFMIN(127, len) && *pos != *(pos+1)) + continue; + + /* if RLE can encode the next block better than as a raw block, + * back up and leave _all_ the identical pixels for RLE */ + count --; + } + break; + } + } + + return count; +} + +int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *ptr , int bpp, int w, + int add_rep, int xor_rep, int add_raw, int xor_raw) +{ + int count, x; + uint8_t *out = outbuf; + + for(x = 0; x < w; x += count) { + /* see if we can encode the next set of pixels with RLE */ + if((count = count_pixels(ptr, w-x, bpp, 1)) > 1) { + if(out + bpp + 1 > outbuf + out_size) return -1; + *out++ = (count ^ xor_rep) + add_rep; + memcpy(out, ptr, bpp); + out += bpp; + } else { + /* fall back on uncompressed */ + count = count_pixels(ptr, w-x, bpp, 0); + if(out + bpp*count >= outbuf + out_size) return -1; + *out++ = (count ^ xor_raw) + add_raw; + + memcpy(out, ptr, bpp * count); + out += bpp * count; + } + + ptr += count * bpp; + } + + return out - outbuf; +} diff --git a/ffmpeg/libavcodec/rle.h b/ffmpeg/libavcodec/rle.h new file mode 100644 index 0000000..2485132 --- /dev/null +++ b/ffmpeg/libavcodec/rle.h @@ -0,0 +1,39 @@ +/* + * RLE encoder + * + * 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 + */ + +#ifndef AVCODEC_RLE_H +#define AVCODEC_RLE_H + +#include + +/** + * RLE compress the row, with maximum size of out_size. Value before repeated bytes is (count ^ xor_rep) + add_rep. + * Value before raw bytes is (count ^ xor_raw) + add_raw. + * @param outbuf Output buffer + * @param out_size Maximum output size + * @param inbuf Input buffer + * @param bpp Bytes per pixel + * @param w Image width + * @return Size of output in bytes, or -1 if larger than out_size + */ +int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *inbuf, int bpp, int w, + int add_rep, int xor_rep, int add_raw, int xor_raw); + +#endif /* AVCODEC_RLE_H */ diff --git a/ffmpeg/libavcodec/rnd_avg.h b/ffmpeg/libavcodec/rnd_avg.h new file mode 100644 index 0000000..50ab59a --- /dev/null +++ b/ffmpeg/libavcodec/rnd_avg.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2003 BERO + * Copyright (c) 2011 Oskar Arvidsson + * + * 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 + */ + +#ifndef AVCODEC_RND_AVG_H +#define AVCODEC_RND_AVG_H + +#include +#include + +#define CALL_2X_PIXELS(a, b, n)\ +static void a(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){\ + b(block , pixels , line_size, h);\ + b(block+n, pixels+n, line_size, h);\ +} + +#define BYTE_VEC32(c) ((c)*0x01010101UL) +#define BYTE_VEC64(c) ((c)*0x0001000100010001UL) + +static inline uint32_t rnd_avg32(uint32_t a, uint32_t b) +{ + return (a | b) - (((a ^ b) & ~BYTE_VEC32(0x01)) >> 1); +} + +static inline uint32_t no_rnd_avg32(uint32_t a, uint32_t b) +{ + return (a & b) + (((a ^ b) & ~BYTE_VEC32(0x01)) >> 1); +} + +static inline uint64_t rnd_avg64(uint64_t a, uint64_t b) +{ + return (a | b) - (((a ^ b) & ~BYTE_VEC64(0x01)) >> 1); +} + +static inline uint64_t no_rnd_avg64(uint64_t a, uint64_t b) +{ + return (a & b) + (((a ^ b) & ~BYTE_VEC64(0x01)) >> 1); +} + +#endif /* AVCODEC_RND_AVG_H */ diff --git a/ffmpeg/libavcodec/roqaudioenc.c b/ffmpeg/libavcodec/roqaudioenc.c new file mode 100644 index 0000000..b68e3f8 --- /dev/null +++ b/ffmpeg/libavcodec/roqaudioenc.c @@ -0,0 +1,206 @@ +/* + * RoQ audio encoder + * + * Copyright (c) 2005 Eric Lasota + * Based on RoQ specs (c)2001 Tim Ferguson + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "mathops.h" + +#define ROQ_FRAME_SIZE 735 +#define ROQ_HEADER_SIZE 8 + +#define MAX_DPCM (127*127) + + +typedef struct +{ + short lastSample[2]; + int input_frames; + int buffered_samples; + int16_t *frame_buffer; + int64_t first_pts; +} ROQDPCMContext; + + +static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx) +{ + ROQDPCMContext *context = avctx->priv_data; + + av_freep(&context->frame_buffer); + + return 0; +} + +static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx) +{ + ROQDPCMContext *context = avctx->priv_data; + int ret; + + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n"); + return AVERROR(EINVAL); + } + if (avctx->sample_rate != 22050) { + av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n"); + return AVERROR(EINVAL); + } + + avctx->frame_size = ROQ_FRAME_SIZE; + avctx->bit_rate = (ROQ_HEADER_SIZE + ROQ_FRAME_SIZE * avctx->channels) * + (22050 / ROQ_FRAME_SIZE) * 8; + + context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * avctx->channels * + sizeof(*context->frame_buffer)); + if (!context->frame_buffer) { + ret = AVERROR(ENOMEM); + goto error; + } + + context->lastSample[0] = context->lastSample[1] = 0; + + return 0; +error: + roq_dpcm_encode_close(avctx); + return ret; +} + +static unsigned char dpcm_predict(short *previous, short current) +{ + int diff; + int negative; + int result; + int predicted; + + diff = current - *previous; + + negative = diff<0; + diff = FFABS(diff); + + if (diff >= MAX_DPCM) + result = 127; + else { + result = ff_sqrt(diff); + result += diff > result*result+result; + } + + /* See if this overflows */ + retry: + diff = result*result; + if (negative) + diff = -diff; + predicted = *previous + diff; + + /* If it overflows, back off a step */ + if (predicted > 32767 || predicted < -32768) { + result--; + goto retry; + } + + /* Add the sign bit */ + result |= negative << 7; //if (negative) result |= 128; + + *previous = predicted; + + return result; +} + +static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + int i, stereo, data_size, ret; + const int16_t *in = frame ? (const int16_t *)frame->data[0] : NULL; + uint8_t *out; + ROQDPCMContext *context = avctx->priv_data; + + stereo = (avctx->channels == 2); + + if (!in && context->input_frames >= 8) + return 0; + + if (in && context->input_frames < 8) { + memcpy(&context->frame_buffer[context->buffered_samples * avctx->channels], + in, avctx->frame_size * avctx->channels * sizeof(*in)); + context->buffered_samples += avctx->frame_size; + if (context->input_frames == 0) + context->first_pts = frame->pts; + if (context->input_frames < 7) { + context->input_frames++; + return 0; + } + } + if (context->input_frames < 8) { + in = context->frame_buffer; + } + + if (stereo) { + context->lastSample[0] &= 0xFF00; + context->lastSample[1] &= 0xFF00; + } + + if (context->input_frames == 7) + data_size = avctx->channels * context->buffered_samples; + else + data_size = avctx->channels * avctx->frame_size; + + if ((ret = ff_alloc_packet2(avctx, avpkt, ROQ_HEADER_SIZE + data_size)) < 0) + return ret; + out = avpkt->data; + + bytestream_put_byte(&out, stereo ? 0x21 : 0x20); + bytestream_put_byte(&out, 0x10); + bytestream_put_le32(&out, data_size); + + if (stereo) { + bytestream_put_byte(&out, (context->lastSample[1])>>8); + bytestream_put_byte(&out, (context->lastSample[0])>>8); + } else + bytestream_put_le16(&out, context->lastSample[0]); + + /* Write the actual samples */ + for (i = 0; i < data_size; i++) + *out++ = dpcm_predict(&context->lastSample[i & 1], *in++); + + avpkt->pts = context->input_frames <= 7 ? context->first_pts : frame->pts; + avpkt->duration = data_size / avctx->channels; + + context->input_frames++; + if (!in) + context->input_frames = FFMAX(context->input_frames, 8); + + *got_packet_ptr = 1; + return 0; +} + +AVCodec ff_roq_dpcm_encoder = { + .name = "roq_dpcm", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ROQ_DPCM, + .priv_data_size = sizeof(ROQDPCMContext), + .init = roq_dpcm_encode_init, + .encode2 = roq_dpcm_encode_frame, + .close = roq_dpcm_encode_close, + .capabilities = CODEC_CAP_DELAY, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"), +}; diff --git a/ffmpeg/libavcodec/roqvideo.c b/ffmpeg/libavcodec/roqvideo.c new file mode 100644 index 0000000..eb8fc25 --- /dev/null +++ b/ffmpeg/libavcodec/roqvideo.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2003 Mike Melanson + * Copyright (C) 2003 Dr. Tim Ferguson + * + * 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 + */ + +/** + * @file + * id RoQ Video common functions based on work by Dr. Tim Ferguson + */ + +#include "avcodec.h" +#include "roqvideo.h" + +static inline void block_copy(unsigned char *out, unsigned char *in, + int outstride, int instride, int sz) +{ + int rows = sz; + while(rows--) { + memcpy(out, in, sz); + out += outstride; + in += instride; + } +} + +void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) +{ + unsigned char *bptr; + int boffs,stride; + + stride = ri->current_frame->linesize[0]; + boffs = y*stride + x; + + bptr = ri->current_frame->data[0] + boffs; + bptr[0 ] = cell->y[0]; + bptr[1 ] = cell->y[1]; + bptr[stride ] = cell->y[2]; + bptr[stride+1] = cell->y[3]; + + stride = ri->current_frame->linesize[1]; + boffs = y*stride + x; + + bptr = ri->current_frame->data[1] + boffs; + bptr[0 ] = + bptr[1 ] = + bptr[stride ] = + bptr[stride+1] = cell->u; + + bptr = ri->current_frame->data[2] + boffs; + bptr[0 ] = + bptr[1 ] = + bptr[stride ] = + bptr[stride+1] = cell->v; +} + +void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell) +{ + unsigned char *bptr; + int boffs,stride; + + stride = ri->current_frame->linesize[0]; + boffs = y*stride + x; + + bptr = ri->current_frame->data[0] + boffs; + bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = cell->y[0]; + bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = cell->y[1]; + bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = cell->y[2]; + bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->y[3]; + + stride = ri->current_frame->linesize[1]; + boffs = y*stride + x; + + bptr = ri->current_frame->data[1] + boffs; + bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = + bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = + bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = + bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->u; + + bptr = ri->current_frame->data[2] + boffs; + bptr[ 0] = bptr[ 1] = bptr[stride ] = bptr[stride +1] = + bptr[ 2] = bptr[ 3] = bptr[stride +2] = bptr[stride +3] = + bptr[stride*2 ] = bptr[stride*2+1] = bptr[stride*3 ] = bptr[stride*3+1] = + bptr[stride*2+2] = bptr[stride*2+3] = bptr[stride*3+2] = bptr[stride*3+3] = cell->v; +} + + +static inline void apply_motion_generic(RoqContext *ri, int x, int y, int deltax, + int deltay, int sz) +{ + int mx, my, cp; + + mx = x + deltax; + my = y + deltay; + + /* check MV against frame boundaries */ + if ((mx < 0) || (mx > ri->width - sz) || + (my < 0) || (my > ri->height - sz)) { + av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)\n", + mx, my, ri->width, ri->height); + return; + } + + if (ri->last_frame->data[0] == NULL) { + av_log(ri->avctx, AV_LOG_ERROR, "Invalid decode type. Invalid header?\n"); + return; + } + + for(cp = 0; cp < 3; cp++) { + int outstride = ri->current_frame->linesize[cp]; + int instride = ri->last_frame ->linesize[cp]; + block_copy(ri->current_frame->data[cp] + y*outstride + x, + ri->last_frame->data[cp] + my*instride + mx, + outstride, instride, sz); + } +} + + +void ff_apply_motion_4x4(RoqContext *ri, int x, int y, + int deltax, int deltay) +{ + apply_motion_generic(ri, x, y, deltax, deltay, 4); +} + +void ff_apply_motion_8x8(RoqContext *ri, int x, int y, + int deltax, int deltay) +{ + apply_motion_generic(ri, x, y, deltax, deltay, 8); +} diff --git a/ffmpeg/libavcodec/roqvideo.h b/ffmpeg/libavcodec/roqvideo.h new file mode 100644 index 0000000..3834897 --- /dev/null +++ b/ffmpeg/libavcodec/roqvideo.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2003 Mike Melanson + * Copyright (C) 2003 Dr. Tim Ferguson + * + * 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 + */ + +#ifndef AVCODEC_ROQVIDEO_H +#define AVCODEC_ROQVIDEO_H + +#include "libavutil/lfg.h" +#include "avcodec.h" +#include "bytestream.h" + +typedef struct roq_cell { + unsigned char y[4]; + unsigned char u, v; +} roq_cell; + +typedef struct roq_qcell { + int idx[4]; +} roq_qcell; + +typedef struct motion_vect { + int d[2]; +} motion_vect; + +struct RoqTempData; + +typedef struct RoqContext { + + AVCodecContext *avctx; + AVFrame frames[2]; + AVFrame *last_frame; + AVFrame *current_frame; + int first_frame; + + roq_cell cb2x2[256]; + roq_qcell cb4x4[256]; + + GetByteContext gb; + int width, height; + + /* Encoder only data */ + AVLFG randctx; + uint64_t lambda; + + motion_vect *this_motion4; + motion_vect *last_motion4; + + motion_vect *this_motion8; + motion_vect *last_motion8; + + unsigned int framesSinceKeyframe; + + const AVFrame *frame_to_enc; + uint8_t *out_buf; + struct RoqTempData *tmpData; +} RoqContext; + +#define RoQ_INFO 0x1001 +#define RoQ_QUAD_CODEBOOK 0x1002 +#define RoQ_QUAD_VQ 0x1011 +#define RoQ_SOUND_MONO 0x1020 +#define RoQ_SOUND_STEREO 0x1021 + +#define RoQ_ID_MOT 0x00 +#define RoQ_ID_FCC 0x01 +#define RoQ_ID_SLD 0x02 +#define RoQ_ID_CCC 0x03 + +void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell); +void ff_apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell); + +void ff_apply_motion_4x4(RoqContext *ri, int x, int y, int deltax, int deltay); + +void ff_apply_motion_8x8(RoqContext *ri, int x, int y, int deltax, int deltay); + +#endif /* AVCODEC_ROQVIDEO_H */ diff --git a/ffmpeg/libavcodec/roqvideodec.c b/ffmpeg/libavcodec/roqvideodec.c new file mode 100644 index 0000000..85fdab7 --- /dev/null +++ b/ffmpeg/libavcodec/roqvideodec.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * id RoQ Video Decoder by Dr. Tim Ferguson + * For more information about the id RoQ format, visit: + * http://www.csse.monash.edu.au/~timf/ + */ + +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "roqvideo.h" + +static void roqvideo_decode_frame(RoqContext *ri) +{ + unsigned int chunk_id = 0, chunk_arg = 0; + unsigned long chunk_size = 0; + int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; + int vqid, xpos, ypos, xp, yp, x, y, mx, my; + int frame_stats[2][4] = {{0},{0}}; + roq_qcell *qcell; + int64_t chunk_start; + + while (bytestream2_get_bytes_left(&ri->gb) >= 8) { + chunk_id = bytestream2_get_le16(&ri->gb); + chunk_size = bytestream2_get_le32(&ri->gb); + chunk_arg = bytestream2_get_le16(&ri->gb); + + if(chunk_id == RoQ_QUAD_VQ) + break; + if(chunk_id == RoQ_QUAD_CODEBOOK) { + if((nv1 = chunk_arg >> 8) == 0) + nv1 = 256; + if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) + nv2 = 256; + for(i = 0; i < nv1; i++) { + ri->cb2x2[i].y[0] = bytestream2_get_byte(&ri->gb); + ri->cb2x2[i].y[1] = bytestream2_get_byte(&ri->gb); + ri->cb2x2[i].y[2] = bytestream2_get_byte(&ri->gb); + ri->cb2x2[i].y[3] = bytestream2_get_byte(&ri->gb); + ri->cb2x2[i].u = bytestream2_get_byte(&ri->gb); + ri->cb2x2[i].v = bytestream2_get_byte(&ri->gb); + } + for(i = 0; i < nv2; i++) + for(j = 0; j < 4; j++) + ri->cb4x4[i].idx[j] = bytestream2_get_byte(&ri->gb); + } + } + + chunk_start = bytestream2_tell(&ri->gb); + xpos = ypos = 0; + + if (chunk_size > bytestream2_get_bytes_left(&ri->gb)) { + av_log(ri->avctx, AV_LOG_ERROR, "Chunk does not fit in input buffer\n"); + chunk_size = bytestream2_get_bytes_left(&ri->gb); + } + + while (bytestream2_tell(&ri->gb) < chunk_start + chunk_size) { + for (yp = ypos; yp < ypos + 16; yp += 8) + for (xp = xpos; xp < xpos + 16; xp += 8) { + if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) { + av_log(ri->avctx, AV_LOG_ERROR, "Input buffer too small\n"); + return; + } + if (vqflg_pos < 0) { + vqflg = bytestream2_get_le16(&ri->gb); + vqflg_pos = 7; + } + vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; + frame_stats[0][vqid]++; + vqflg_pos--; + + switch(vqid) { + case RoQ_ID_MOT: + break; + case RoQ_ID_FCC: { + int byte = bytestream2_get_byte(&ri->gb); + mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8)); + my = 8 - (byte & 0xf) - ((signed char) chunk_arg); + ff_apply_motion_8x8(ri, xp, yp, mx, my); + break; + } + case RoQ_ID_SLD: + qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb); + ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]); + ff_apply_vector_4x4(ri, xp + 4, yp, ri->cb2x2 + qcell->idx[1]); + ff_apply_vector_4x4(ri, xp, yp + 4, ri->cb2x2 + qcell->idx[2]); + ff_apply_vector_4x4(ri, xp + 4, yp + 4, ri->cb2x2 + qcell->idx[3]); + break; + case RoQ_ID_CCC: + for (k = 0; k < 4; k++) { + x = xp; y = yp; + if(k & 0x01) x += 4; + if(k & 0x02) y += 4; + + if (bytestream2_tell(&ri->gb) >= chunk_start + chunk_size) { + av_log(ri->avctx, AV_LOG_ERROR, "Input buffer too small\n"); + return; + } + if (vqflg_pos < 0) { + vqflg = bytestream2_get_le16(&ri->gb); + vqflg_pos = 7; + } + vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; + frame_stats[1][vqid]++; + vqflg_pos--; + switch(vqid) { + case RoQ_ID_MOT: + break; + case RoQ_ID_FCC: { + int byte = bytestream2_get_byte(&ri->gb); + mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8)); + my = 8 - (byte & 0xf) - ((signed char) chunk_arg); + ff_apply_motion_4x4(ri, x, y, mx, my); + break; + } + case RoQ_ID_SLD: + qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb); + ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]); + ff_apply_vector_2x2(ri, x + 2, y, ri->cb2x2 + qcell->idx[1]); + ff_apply_vector_2x2(ri, x, y + 2, ri->cb2x2 + qcell->idx[2]); + ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + qcell->idx[3]); + break; + case RoQ_ID_CCC: + ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); + ff_apply_vector_2x2(ri, x + 2, y, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); + ff_apply_vector_2x2(ri, x, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); + ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb)); + break; + } + } + break; + default: + av_assert2(0); + } + } + + xpos += 16; + if (xpos >= ri->width) { + xpos -= ri->width; + ypos += 16; + } + if(ypos >= ri->height) + break; + } +} + + +static av_cold int roq_decode_init(AVCodecContext *avctx) +{ + RoqContext *s = avctx->priv_data; + + s->avctx = avctx; + + if (avctx->width % 16 || avctx->height % 16) { + av_log(avctx, AV_LOG_ERROR, + "Dimensions must be a multiple of 16\n"); + return AVERROR_PATCHWELCOME; + } + + s->width = avctx->width; + s->height = avctx->height; + + s->last_frame = av_frame_alloc(); + s->current_frame = av_frame_alloc(); + if (!s->current_frame || !s->last_frame) { + av_frame_free(&s->current_frame); + av_frame_free(&s->last_frame); + return AVERROR(ENOMEM); + } + + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + + return 0; +} + +static int roq_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + RoqContext *s = avctx->priv_data; + int copy= !s->current_frame->data[0]; + int ret; + + if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0) + return ret; + + if(copy) + av_picture_copy((AVPicture*)s->current_frame, (AVPicture*)s->last_frame, + avctx->pix_fmt, avctx->width, avctx->height); + + bytestream2_init(&s->gb, buf, buf_size); + roqvideo_decode_frame(s); + + if ((ret = av_frame_ref(data, s->current_frame)) < 0) + return ret; + *got_frame = 1; + + /* shuffle frames */ + FFSWAP(AVFrame *, s->current_frame, s->last_frame); + + return buf_size; +} + +static av_cold int roq_decode_end(AVCodecContext *avctx) +{ + RoqContext *s = avctx->priv_data; + + av_frame_free(&s->current_frame); + av_frame_free(&s->last_frame); + + return 0; +} + +AVCodec ff_roq_decoder = { + .name = "roqvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ROQ, + .priv_data_size = sizeof(RoqContext), + .init = roq_decode_init, + .close = roq_decode_end, + .decode = roq_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), +}; diff --git a/ffmpeg/libavcodec/roqvideoenc.c b/ffmpeg/libavcodec/roqvideoenc.c new file mode 100644 index 0000000..a652c47 --- /dev/null +++ b/ffmpeg/libavcodec/roqvideoenc.c @@ -0,0 +1,1087 @@ +/* + * RoQ Video Encoder. + * + * Copyright (C) 2007 Vitor Sessak + * Copyright (C) 2004-2007 Eric Lasota + * Based on RoQ specs (C) 2001 Tim Ferguson + * + * 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 + */ + +/** + * @file + * id RoQ encoder by Vitor. Based on the Switchblade3 library and the + * Switchblade3 FFmpeg glue by Eric Lasota. + */ + +/* + * COSTS: + * Level 1: + * SKIP - 2 bits + * MOTION - 2 + 8 bits + * CODEBOOK - 2 + 8 bits + * SUBDIVIDE - 2 + combined subcel cost + * + * Level 2: + * SKIP - 2 bits + * MOTION - 2 + 8 bits + * CODEBOOK - 2 + 8 bits + * SUBDIVIDE - 2 + 4*8 bits + * + * Maximum cost: 138 bits per cel + * + * Proper evaluation requires LCD fraction comparison, which requires + * Squared Error (SE) loss * savings increase + * + * Maximum savings increase: 136 bits + * Maximum SE loss without overflow: 31580641 + * Components in 8x8 supercel: 192 + * Maximum SE precision per component: 164482 + * >65025, so no truncation is needed (phew) + */ + +#include + +#include "roqvideo.h" +#include "bytestream.h" +#include "elbg.h" +#include "internal.h" +#include "mathops.h" + +#define CHROMA_BIAS 1 + +/** + * Maximum number of generated 4x4 codebooks. Can't be 256 to workaround a + * Quake 3 bug. + */ +#define MAX_CBS_4x4 255 + +#define MAX_CBS_2x2 256 ///< Maximum number of 2x2 codebooks. + +/* The cast is useful when multiplying it by INT_MAX */ +#define ROQ_LAMBDA_SCALE ((uint64_t) FF_LAMBDA_SCALE) + +/* Macroblock support functions */ +static void unpack_roq_cell(roq_cell *cell, uint8_t u[4*3]) +{ + memcpy(u , cell->y, 4); + memset(u+4, cell->u, 4); + memset(u+8, cell->v, 4); +} + +static void unpack_roq_qcell(uint8_t cb2[], roq_qcell *qcell, uint8_t u[4*4*3]) +{ + int i,cp; + static const int offsets[4] = {0, 2, 8, 10}; + + for (cp=0; cp<3; cp++) + for (i=0; i<4; i++) { + u[4*4*cp + offsets[i] ] = cb2[qcell->idx[i]*2*2*3 + 4*cp ]; + u[4*4*cp + offsets[i]+1] = cb2[qcell->idx[i]*2*2*3 + 4*cp+1]; + u[4*4*cp + offsets[i]+4] = cb2[qcell->idx[i]*2*2*3 + 4*cp+2]; + u[4*4*cp + offsets[i]+5] = cb2[qcell->idx[i]*2*2*3 + 4*cp+3]; + } +} + + +static void enlarge_roq_mb4(uint8_t base[3*16], uint8_t u[3*64]) +{ + int x,y,cp; + + for(cp=0; cp<3; cp++) + for(y=0; y<8; y++) + for(x=0; x<8; x++) + *u++ = base[(y/2)*4 + (x/2) + 16*cp]; +} + +static inline int square(int x) +{ + return x*x; +} + +static inline int eval_sse(const uint8_t *a, const uint8_t *b, int count) +{ + int diff=0; + + while(count--) + diff += square(*b++ - *a++); + + return diff; +} + +// FIXME Could use DSPContext.sse, but it is not so speed critical (used +// just for motion estimation). +static int block_sse(uint8_t * const *buf1, uint8_t * const *buf2, int x1, int y1, + int x2, int y2, const int *stride1, const int *stride2, int size) +{ + int i, k; + int sse=0; + + for (k=0; k<3; k++) { + int bias = (k ? CHROMA_BIAS : 4); + for (i=0; i 7) + return INT_MAX; + + if (my < -7 || my > 7) + return INT_MAX; + + mx += x; + my += y; + + if ((unsigned) mx > enc->width-size || (unsigned) my > enc->height-size) + return INT_MAX; + + return block_sse(enc->frame_to_enc->data, enc->last_frame->data, x, y, + mx, my, + enc->frame_to_enc->linesize, enc->last_frame->linesize, + size); +} + +/** + * @return distortion between two macroblocks + */ +static inline int squared_diff_macroblock(uint8_t a[], uint8_t b[], int size) +{ + int cp, sdiff=0; + + for(cp=0;cp<3;cp++) { + int bias = (cp ? CHROMA_BIAS : 4); + sdiff += bias*eval_sse(a, b, size*size); + a += size*size; + b += size*size; + } + + return sdiff; +} + +typedef struct +{ + int eval_dist[4]; + int best_bit_use; + int best_coding; + + int subCels[4]; + motion_vect motion; + int cbEntry; +} SubcelEvaluation; + +typedef struct +{ + int eval_dist[4]; + int best_coding; + + SubcelEvaluation subCels[4]; + + motion_vect motion; + int cbEntry; + + int sourceX, sourceY; +} CelEvaluation; + +typedef struct +{ + int numCB4; + int numCB2; + int usedCB2[MAX_CBS_2x2]; + int usedCB4[MAX_CBS_4x4]; + uint8_t unpacked_cb2[MAX_CBS_2x2*2*2*3]; + uint8_t unpacked_cb4[MAX_CBS_4x4*4*4*3]; + uint8_t unpacked_cb4_enlarged[MAX_CBS_4x4*8*8*3]; +} RoqCodebooks; + +/** + * Temporary vars + */ +typedef struct RoqTempData +{ + CelEvaluation *cel_evals; + + int f2i4[MAX_CBS_4x4]; + int i2f4[MAX_CBS_4x4]; + int f2i2[MAX_CBS_2x2]; + int i2f2[MAX_CBS_2x2]; + + int mainChunkSize; + + int numCB4; + int numCB2; + + RoqCodebooks codebooks; + + int *closest_cb2; + int used_option[4]; +} RoqTempdata; + +/** + * Initialize cel evaluators and set their source coordinates + */ +static void create_cel_evals(RoqContext *enc, RoqTempdata *tempData) +{ + int n=0, x, y, i; + + tempData->cel_evals = av_malloc(enc->width*enc->height/64 * sizeof(CelEvaluation)); + + /* Map to the ROQ quadtree order */ + for (y=0; yheight; y+=16) + for (x=0; xwidth; x+=16) + for(i=0; i<4; i++) { + tempData->cel_evals[n ].sourceX = x + (i&1)*8; + tempData->cel_evals[n++].sourceY = y + (i&2)*4; + } +} + +/** + * Get macroblocks from parts of the image + */ +static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim) +{ + int i, j, cp; + + for (cp=0; cp<3; cp++) { + int stride = frame->linesize[cp]; + for (i=0; idata[cp][(y+i)*stride + x + j]; + } +} + +/** + * Find the codebook with the lowest distortion from an image + */ +static int index_mb(uint8_t cluster[], uint8_t cb[], int numCB, + int *outIndex, int dim) +{ + int i, lDiff = INT_MAX, pick=0; + + /* Diff against the others */ + for (i=0; iwidth/blocksize)*enc->height/blocksize; + + if (blocksize == 4) { + last_motion = enc->last_motion4; + this_motion = enc->this_motion4; + } else { + last_motion = enc->last_motion8; + this_motion = enc->this_motion8; + } + + for (i=0; iheight; i+=blocksize) + for (j=0; jwidth; j+=blocksize) { + lowestdiff = eval_motion_dist(enc, j, i, (motion_vect) {{0,0}}, + blocksize); + bestpick.d[0] = 0; + bestpick.d[1] = 0; + + if (blocksize == 4) + EVAL_MOTION(enc->this_motion8[(i/8)*(enc->width/8) + j/8]); + + offset = (i/blocksize)*enc->width/blocksize + j/blocksize; + if (offset < max && offset >= 0) + EVAL_MOTION(last_motion[offset]); + + offset++; + if (offset < max && offset >= 0) + EVAL_MOTION(last_motion[offset]); + + offset = (i/blocksize + 1)*enc->width/blocksize + j/blocksize; + if (offset < max && offset >= 0) + EVAL_MOTION(last_motion[offset]); + + off[0]= (i/blocksize)*enc->width/blocksize + j/blocksize - 1; + off[1]= off[0] - enc->width/blocksize + 1; + off[2]= off[1] + 1; + + if (i) { + + for(k=0; k<2; k++) + vect.d[k]= mid_pred(this_motion[off[0]].d[k], + this_motion[off[1]].d[k], + this_motion[off[2]].d[k]); + + EVAL_MOTION(vect); + for(k=0; k<3; k++) + EVAL_MOTION(this_motion[off[k]]); + } else if(j) + EVAL_MOTION(this_motion[off[0]]); + + vect = bestpick; + + oldbest = -1; + while (oldbest != lowestdiff) { + oldbest = lowestdiff; + for (k=0; k<8; k++) { + vect2 = vect; + vect2.d[0] += offsets[k].d[0]; + vect2.d[1] += offsets[k].d[1]; + EVAL_MOTION(vect2); + } + vect = bestpick; + } + offset = (i/blocksize)*enc->width/blocksize + j/blocksize; + this_motion[offset] = bestpick; + } +} + +/** + * Get distortion for all options available to a subcel + */ +static void gather_data_for_subcel(SubcelEvaluation *subcel, int x, + int y, RoqContext *enc, RoqTempdata *tempData) +{ + uint8_t mb4[4*4*3]; + uint8_t mb2[2*2*3]; + int cluster_index; + int i, best_dist; + + static const int bitsUsed[4] = {2, 10, 10, 34}; + + if (enc->framesSinceKeyframe >= 1) { + subcel->motion = enc->this_motion4[y*enc->width/16 + x/4]; + + subcel->eval_dist[RoQ_ID_FCC] = + eval_motion_dist(enc, x, y, + enc->this_motion4[y*enc->width/16 + x/4], 4); + } else + subcel->eval_dist[RoQ_ID_FCC] = INT_MAX; + + if (enc->framesSinceKeyframe >= 2) + subcel->eval_dist[RoQ_ID_MOT] = block_sse(enc->frame_to_enc->data, + enc->current_frame->data, x, + y, x, y, + enc->frame_to_enc->linesize, + enc->current_frame->linesize, + 4); + else + subcel->eval_dist[RoQ_ID_MOT] = INT_MAX; + + cluster_index = y*enc->width/16 + x/4; + + get_frame_mb(enc->frame_to_enc, x, y, mb4, 4); + + subcel->eval_dist[RoQ_ID_SLD] = index_mb(mb4, + tempData->codebooks.unpacked_cb4, + tempData->codebooks.numCB4, + &subcel->cbEntry, 4); + + subcel->eval_dist[RoQ_ID_CCC] = 0; + + for(i=0;i<4;i++) { + subcel->subCels[i] = tempData->closest_cb2[cluster_index*4+i]; + + get_frame_mb(enc->frame_to_enc, x+2*(i&1), + y+(i&2), mb2, 2); + + subcel->eval_dist[RoQ_ID_CCC] += + squared_diff_macroblock(tempData->codebooks.unpacked_cb2 + subcel->subCels[i]*2*2*3, mb2, 2); + } + + best_dist = INT_MAX; + for (i=0; i<4; i++) + if (ROQ_LAMBDA_SCALE*subcel->eval_dist[i] + enc->lambda*bitsUsed[i] < + best_dist) { + subcel->best_coding = i; + subcel->best_bit_use = bitsUsed[i]; + best_dist = ROQ_LAMBDA_SCALE*subcel->eval_dist[i] + + enc->lambda*bitsUsed[i]; + } +} + +/** + * Get distortion for all options available to a cel + */ +static void gather_data_for_cel(CelEvaluation *cel, RoqContext *enc, + RoqTempdata *tempData) +{ + uint8_t mb8[8*8*3]; + int index = cel->sourceY*enc->width/64 + cel->sourceX/8; + int i, j, best_dist, divide_bit_use; + + int bitsUsed[4] = {2, 10, 10, 0}; + + if (enc->framesSinceKeyframe >= 1) { + cel->motion = enc->this_motion8[index]; + + cel->eval_dist[RoQ_ID_FCC] = + eval_motion_dist(enc, cel->sourceX, cel->sourceY, + enc->this_motion8[index], 8); + } else + cel->eval_dist[RoQ_ID_FCC] = INT_MAX; + + if (enc->framesSinceKeyframe >= 2) + cel->eval_dist[RoQ_ID_MOT] = block_sse(enc->frame_to_enc->data, + enc->current_frame->data, + cel->sourceX, cel->sourceY, + cel->sourceX, cel->sourceY, + enc->frame_to_enc->linesize, + enc->current_frame->linesize,8); + else + cel->eval_dist[RoQ_ID_MOT] = INT_MAX; + + get_frame_mb(enc->frame_to_enc, cel->sourceX, cel->sourceY, mb8, 8); + + cel->eval_dist[RoQ_ID_SLD] = + index_mb(mb8, tempData->codebooks.unpacked_cb4_enlarged, + tempData->codebooks.numCB4, &cel->cbEntry, 8); + + gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc, tempData); + gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc, tempData); + gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc, tempData); + gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc, tempData); + + cel->eval_dist[RoQ_ID_CCC] = 0; + divide_bit_use = 0; + for (i=0; i<4; i++) { + cel->eval_dist[RoQ_ID_CCC] += + cel->subCels[i].eval_dist[cel->subCels[i].best_coding]; + divide_bit_use += cel->subCels[i].best_bit_use; + } + + best_dist = INT_MAX; + bitsUsed[3] = 2 + divide_bit_use; + + for (i=0; i<4; i++) + if (ROQ_LAMBDA_SCALE*cel->eval_dist[i] + enc->lambda*bitsUsed[i] < + best_dist) { + cel->best_coding = i; + best_dist = ROQ_LAMBDA_SCALE*cel->eval_dist[i] + + enc->lambda*bitsUsed[i]; + } + + tempData->used_option[cel->best_coding]++; + tempData->mainChunkSize += bitsUsed[cel->best_coding]; + + if (cel->best_coding == RoQ_ID_SLD) + tempData->codebooks.usedCB4[cel->cbEntry]++; + + if (cel->best_coding == RoQ_ID_CCC) + for (i=0; i<4; i++) { + if (cel->subCels[i].best_coding == RoQ_ID_SLD) + tempData->codebooks.usedCB4[cel->subCels[i].cbEntry]++; + else if (cel->subCels[i].best_coding == RoQ_ID_CCC) + for (j=0; j<4; j++) + tempData->codebooks.usedCB2[cel->subCels[i].subCels[j]]++; + } +} + +static void remap_codebooks(RoqContext *enc, RoqTempdata *tempData) +{ + int i, j, idx=0; + + /* Make remaps for the final codebook usage */ + for (i=0; icodebooks.usedCB4[i]) { + tempData->i2f4[i] = idx; + tempData->f2i4[idx] = i; + for (j=0; j<4; j++) + tempData->codebooks.usedCB2[enc->cb4x4[i].idx[j]]++; + idx++; + } + } + + tempData->numCB4 = idx; + + idx = 0; + for (i=0; icodebooks.usedCB2[i]) { + tempData->i2f2[i] = idx; + tempData->f2i2[idx] = i; + idx++; + } + } + tempData->numCB2 = idx; + +} + +/** + * Write codebook chunk + */ +static void write_codebooks(RoqContext *enc, RoqTempdata *tempData) +{ + int i, j; + uint8_t **outp= &enc->out_buf; + + if (tempData->numCB2) { + bytestream_put_le16(outp, RoQ_QUAD_CODEBOOK); + bytestream_put_le32(outp, tempData->numCB2*6 + tempData->numCB4*4); + bytestream_put_byte(outp, tempData->numCB4); + bytestream_put_byte(outp, tempData->numCB2); + + for (i=0; inumCB2; i++) { + bytestream_put_buffer(outp, enc->cb2x2[tempData->f2i2[i]].y, 4); + bytestream_put_byte(outp, enc->cb2x2[tempData->f2i2[i]].u); + bytestream_put_byte(outp, enc->cb2x2[tempData->f2i2[i]].v); + } + + for (i=0; inumCB4; i++) + for (j=0; j<4; j++) + bytestream_put_byte(outp, tempData->i2f2[enc->cb4x4[tempData->f2i4[i]].idx[j]]); + + } +} + +static inline uint8_t motion_arg(motion_vect mot) +{ + uint8_t ax = 8 - ((uint8_t) mot.d[0]); + uint8_t ay = 8 - ((uint8_t) mot.d[1]); + return ((ax&15)<<4) | (ay&15); +} + +typedef struct +{ + int typeSpool; + int typeSpoolLength; + uint8_t argumentSpool[64]; + uint8_t *args; + uint8_t **pout; +} CodingSpool; + +/* NOTE: Typecodes must be spooled AFTER arguments!! */ +static void write_typecode(CodingSpool *s, uint8_t type) +{ + s->typeSpool |= (type & 3) << (14 - s->typeSpoolLength); + s->typeSpoolLength += 2; + if (s->typeSpoolLength == 16) { + bytestream_put_le16(s->pout, s->typeSpool); + bytestream_put_buffer(s->pout, s->argumentSpool, + s->args - s->argumentSpool); + s->typeSpoolLength = 0; + s->typeSpool = 0; + s->args = s->argumentSpool; + } +} + +static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData, int w, int h, int numBlocks) +{ + int i, j, k; + int x, y; + int subX, subY; + int dist=0; + + roq_qcell *qcell; + CelEvaluation *eval; + + CodingSpool spool; + + spool.typeSpool=0; + spool.typeSpoolLength=0; + spool.args = spool.argumentSpool; + spool.pout = &enc->out_buf; + + if (tempData->used_option[RoQ_ID_CCC]%2) + tempData->mainChunkSize+=8; //FIXME + + /* Write the video chunk header */ + bytestream_put_le16(&enc->out_buf, RoQ_QUAD_VQ); + bytestream_put_le32(&enc->out_buf, tempData->mainChunkSize/8); + bytestream_put_byte(&enc->out_buf, 0x0); + bytestream_put_byte(&enc->out_buf, 0x0); + + for (i=0; icel_evals + i; + + x = eval->sourceX; + y = eval->sourceY; + dist += eval->eval_dist[eval->best_coding]; + + switch (eval->best_coding) { + case RoQ_ID_MOT: + write_typecode(&spool, RoQ_ID_MOT); + break; + + case RoQ_ID_FCC: + bytestream_put_byte(&spool.args, motion_arg(eval->motion)); + + write_typecode(&spool, RoQ_ID_FCC); + ff_apply_motion_8x8(enc, x, y, + eval->motion.d[0], eval->motion.d[1]); + break; + + case RoQ_ID_SLD: + bytestream_put_byte(&spool.args, tempData->i2f4[eval->cbEntry]); + write_typecode(&spool, RoQ_ID_SLD); + + qcell = enc->cb4x4 + eval->cbEntry; + ff_apply_vector_4x4(enc, x , y , enc->cb2x2 + qcell->idx[0]); + ff_apply_vector_4x4(enc, x+4, y , enc->cb2x2 + qcell->idx[1]); + ff_apply_vector_4x4(enc, x , y+4, enc->cb2x2 + qcell->idx[2]); + ff_apply_vector_4x4(enc, x+4, y+4, enc->cb2x2 + qcell->idx[3]); + break; + + case RoQ_ID_CCC: + write_typecode(&spool, RoQ_ID_CCC); + + for (j=0; j<4; j++) { + subX = x + 4*(j&1); + subY = y + 2*(j&2); + + switch(eval->subCels[j].best_coding) { + case RoQ_ID_MOT: + break; + + case RoQ_ID_FCC: + bytestream_put_byte(&spool.args, + motion_arg(eval->subCels[j].motion)); + + ff_apply_motion_4x4(enc, subX, subY, + eval->subCels[j].motion.d[0], + eval->subCels[j].motion.d[1]); + break; + + case RoQ_ID_SLD: + bytestream_put_byte(&spool.args, + tempData->i2f4[eval->subCels[j].cbEntry]); + + qcell = enc->cb4x4 + eval->subCels[j].cbEntry; + + ff_apply_vector_2x2(enc, subX , subY , + enc->cb2x2 + qcell->idx[0]); + ff_apply_vector_2x2(enc, subX+2, subY , + enc->cb2x2 + qcell->idx[1]); + ff_apply_vector_2x2(enc, subX , subY+2, + enc->cb2x2 + qcell->idx[2]); + ff_apply_vector_2x2(enc, subX+2, subY+2, + enc->cb2x2 + qcell->idx[3]); + break; + + case RoQ_ID_CCC: + for (k=0; k<4; k++) { + int cb_idx = eval->subCels[j].subCels[k]; + bytestream_put_byte(&spool.args, + tempData->i2f2[cb_idx]); + + ff_apply_vector_2x2(enc, subX + 2*(k&1), subY + (k&2), + enc->cb2x2 + cb_idx); + } + break; + } + write_typecode(&spool, eval->subCels[j].best_coding); + } + break; + } + } + + /* Flush the remainder of the argument/type spool */ + while (spool.typeSpoolLength) + write_typecode(&spool, 0x0); + +#if 0 + uint8_t *fdata[3] = {enc->frame_to_enc->data[0], + enc->frame_to_enc->data[1], + enc->frame_to_enc->data[2]}; + uint8_t *cdata[3] = {enc->current_frame->data[0], + enc->current_frame->data[1], + enc->current_frame->data[2]}; + av_log(enc->avctx, AV_LOG_ERROR, "Expected distortion: %i Actual: %i\n", + dist, + block_sse(fdata, cdata, 0, 0, 0, 0, + enc->frame_to_enc->linesize, + enc->current_frame->linesize, + enc->width)); //WARNING: Square dimensions implied... +#endif +} + + +/** + * Create a single YUV cell from a 2x2 section of the image + */ +static inline void frame_block_to_cell(uint8_t *block, uint8_t * const *data, + int top, int left, const int *stride) +{ + int i, j, u=0, v=0; + + for (i=0; i<2; i++) + for (j=0; j<2; j++) { + int x = (top+i)*stride[0] + left + j; + *block++ = data[0][x]; + x = (top+i)*stride[1] + left + j; + u += data[1][x]; + v += data[2][x]; + } + + *block++ = (u+2)/4; + *block++ = (v+2)/4; +} + +/** + * Create YUV clusters for the entire image + */ +static void create_clusters(const AVFrame *frame, int w, int h, uint8_t *yuvClusters) +{ + int i, j, k, l; + + for (i=0; idata, + i+2*k, j+2*l, frame->linesize); + yuvClusters += 24; + } +} + +static void generate_codebook(RoqContext *enc, RoqTempdata *tempdata, + int *points, int inputCount, roq_cell *results, + int size, int cbsize) +{ + int i, j, k; + int c_size = size*size/4; + int *buf; + int *codebook = av_malloc(6*c_size*cbsize*sizeof(int)); + int *closest_cb; + + if (size == 4) + closest_cb = av_malloc(6*c_size*inputCount*sizeof(int)); + else + closest_cb = tempdata->closest_cb2; + + ff_init_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); + ff_do_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); + + if (size == 4) + av_free(closest_cb); + + buf = codebook; + for (i=0; iy[j] = *buf++; + + results->u = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS; + results->v = (*buf++ + CHROMA_BIAS/2)/CHROMA_BIAS; + results++; + } + + av_free(codebook); +} + +static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) +{ + int i,j; + RoqCodebooks *codebooks = &tempData->codebooks; + int max = enc->width*enc->height/16; + uint8_t mb2[3*4]; + roq_cell *results4 = av_malloc(sizeof(roq_cell)*MAX_CBS_4x4*4); + uint8_t *yuvClusters=av_malloc(sizeof(int)*max*6*4); + int *points = av_malloc(max*6*4*sizeof(int)); + int bias; + + /* Subsample YUV data */ + create_clusters(enc->frame_to_enc, enc->width, enc->height, yuvClusters); + + /* Cast to integer and apply chroma bias */ + for (i=0; inumCB4 = MAX_CBS_4x4; + + tempData->closest_cb2 = av_malloc(max*4*sizeof(int)); + + /* Create 2x2 codebooks */ + generate_codebook(enc, tempData, points, max*4, enc->cb2x2, 2, MAX_CBS_2x2); + + codebooks->numCB2 = MAX_CBS_2x2; + + /* Unpack 2x2 codebook clusters */ + for (i=0; inumCB2; i++) + unpack_roq_cell(enc->cb2x2 + i, codebooks->unpacked_cb2 + i*2*2*3); + + /* Index all 4x4 entries to the 2x2 entries, unpack, and enlarge */ + for (i=0; inumCB4; i++) { + for (j=0; j<4; j++) { + unpack_roq_cell(&results4[4*i + j], mb2); + index_mb(mb2, codebooks->unpacked_cb2, codebooks->numCB2, + &enc->cb4x4[i].idx[j], 2); + } + unpack_roq_qcell(codebooks->unpacked_cb2, enc->cb4x4 + i, + codebooks->unpacked_cb4 + i*4*4*3); + enlarge_roq_mb4(codebooks->unpacked_cb4 + i*4*4*3, + codebooks->unpacked_cb4_enlarged + i*8*8*3); + } + + av_free(yuvClusters); + av_free(points); + av_free(results4); +} + +static void roq_encode_video(RoqContext *enc) +{ + RoqTempdata *tempData = enc->tmpData; + int i; + + memset(tempData, 0, sizeof(*tempData)); + + create_cel_evals(enc, tempData); + + generate_new_codebooks(enc, tempData); + + if (enc->framesSinceKeyframe >= 1) { + motion_search(enc, 8); + motion_search(enc, 4); + } + + retry_encode: + for (i=0; iwidth*enc->height/64; i++) + gather_data_for_cel(tempData->cel_evals + i, enc, tempData); + + /* Quake 3 can't handle chunks bigger than 65535 bytes */ + if (tempData->mainChunkSize/8 > 65535) { + av_log(enc->avctx, AV_LOG_ERROR, + "Warning, generated a frame too big (%d > 65535), " + "try using a smaller qscale value.\n", + tempData->mainChunkSize/8); + enc->lambda *= 1.5; + tempData->mainChunkSize = 0; + memset(tempData->used_option, 0, sizeof(tempData->used_option)); + memset(tempData->codebooks.usedCB4, 0, + sizeof(tempData->codebooks.usedCB4)); + memset(tempData->codebooks.usedCB2, 0, + sizeof(tempData->codebooks.usedCB2)); + + goto retry_encode; + } + + remap_codebooks(enc, tempData); + + write_codebooks(enc, tempData); + + reconstruct_and_encode_image(enc, tempData, enc->width, enc->height, + enc->width*enc->height/64); + + enc->avctx->coded_frame = enc->current_frame; + + /* Rotate frame history */ + FFSWAP(AVFrame *, enc->current_frame, enc->last_frame); + FFSWAP(motion_vect *, enc->last_motion4, enc->this_motion4); + FFSWAP(motion_vect *, enc->last_motion8, enc->this_motion8); + + av_free(tempData->cel_evals); + av_free(tempData->closest_cb2); + + enc->framesSinceKeyframe++; +} + +static int roq_encode_end(AVCodecContext *avctx) +{ + RoqContext *enc = avctx->priv_data; + + av_frame_free(&enc->current_frame); + av_frame_free(&enc->last_frame); + + av_free(enc->tmpData); + av_free(enc->this_motion4); + av_free(enc->last_motion4); + av_free(enc->this_motion8); + av_free(enc->last_motion8); + + return 0; +} + +static int roq_encode_init(AVCodecContext *avctx) +{ + RoqContext *enc = avctx->priv_data; + + av_lfg_init(&enc->randctx, 1); + + enc->framesSinceKeyframe = 0; + if ((avctx->width & 0xf) || (avctx->height & 0xf)) { + av_log(avctx, AV_LOG_ERROR, "Dimensions must be divisible by 16\n"); + return -1; + } + + if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1))) + av_log(avctx, AV_LOG_ERROR, "Warning: dimensions not power of two\n"); + + enc->width = avctx->width; + enc->height = avctx->height; + + enc->framesSinceKeyframe = 0; + enc->first_frame = 1; + + enc->last_frame = av_frame_alloc(); + enc->current_frame = av_frame_alloc(); + if (!enc->last_frame || !enc->current_frame) { + roq_encode_end(avctx); + return AVERROR(ENOMEM); + } + + enc->tmpData = av_malloc(sizeof(RoqTempdata)); + + enc->this_motion4 = + av_mallocz((enc->width*enc->height/16)*sizeof(motion_vect)); + + enc->last_motion4 = + av_malloc ((enc->width*enc->height/16)*sizeof(motion_vect)); + + enc->this_motion8 = + av_mallocz((enc->width*enc->height/64)*sizeof(motion_vect)); + + enc->last_motion8 = + av_malloc ((enc->width*enc->height/64)*sizeof(motion_vect)); + + return 0; +} + +static void roq_write_video_info_chunk(RoqContext *enc) +{ + /* ROQ info chunk */ + bytestream_put_le16(&enc->out_buf, RoQ_INFO); + + /* Size: 8 bytes */ + bytestream_put_le32(&enc->out_buf, 8); + + /* Unused argument */ + bytestream_put_byte(&enc->out_buf, 0x00); + bytestream_put_byte(&enc->out_buf, 0x00); + + /* Width */ + bytestream_put_le16(&enc->out_buf, enc->width); + + /* Height */ + bytestream_put_le16(&enc->out_buf, enc->height); + + /* Unused in Quake 3, mimics the output of the real encoder */ + bytestream_put_byte(&enc->out_buf, 0x08); + bytestream_put_byte(&enc->out_buf, 0x00); + bytestream_put_byte(&enc->out_buf, 0x04); + bytestream_put_byte(&enc->out_buf, 0x00); +} + +static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + RoqContext *enc = avctx->priv_data; + int size, ret; + + enc->avctx = avctx; + + enc->frame_to_enc = frame; + + if (frame->quality) + enc->lambda = frame->quality - 1; + else + enc->lambda = 2*ROQ_LAMBDA_SCALE; + + /* 138 bits max per 8x8 block + + * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */ + size = ((enc->width * enc->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8; + if ((ret = ff_alloc_packet2(avctx, pkt, size)) < 0) + return ret; + enc->out_buf = pkt->data; + + /* Check for I frame */ + if (enc->framesSinceKeyframe == avctx->gop_size) + enc->framesSinceKeyframe = 0; + + if (enc->first_frame) { + /* Alloc memory for the reconstruction data (we must know the stride + for that) */ + if ((ret = ff_get_buffer(avctx, enc->current_frame, 0)) < 0 || + (ret = ff_get_buffer(avctx, enc->last_frame, 0)) < 0) + return ret; + + /* Before the first video frame, write a "video info" chunk */ + roq_write_video_info_chunk(enc); + + enc->first_frame = 0; + } + + /* Encode the actual frame */ + roq_encode_video(enc); + + pkt->size = enc->out_buf - pkt->data; + if (enc->framesSinceKeyframe == 1) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +AVCodec ff_roq_encoder = { + .name = "roqvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ROQ, + .priv_data_size = sizeof(RoqContext), + .init = roq_encode_init, + .encode2 = roq_encode_frame, + .close = roq_encode_end, + .supported_framerates = (const AVRational[]){ {30,1}, {0,0} }, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), +}; diff --git a/ffmpeg/libavcodec/rpza.c b/ffmpeg/libavcodec/rpza.c new file mode 100644 index 0000000..2aa0091 --- /dev/null +++ b/ffmpeg/libavcodec/rpza.c @@ -0,0 +1,292 @@ +/* + * Quicktime Video (RPZA) Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * QT RPZA Video Decoder by Roberto Togni + * For more information about the RPZA format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * The RPZA decoder outputs RGB555 colorspace data. + * + * Note that this decoder reads big endian RGB555 pixel values from the + * bytestream, arranges them in the host's endian order, and outputs + * them to the final rendered map in the same host endian order. This is + * intended behavior as the libavcodec documentation states that RGB555 + * pixels shall be stored in native CPU endianness. + */ + +#include +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct RpzaContext { + + AVCodecContext *avctx; + AVFrame frame; + + const unsigned char *buf; + int size; + +} RpzaContext; + +#define ADVANCE_BLOCK() \ +{ \ + pixel_ptr += 4; \ + if (pixel_ptr >= width) \ + { \ + pixel_ptr = 0; \ + row_ptr += stride * 4; \ + } \ + total_blocks--; \ + if (total_blocks < 0) \ + { \ + av_log(s->avctx, AV_LOG_ERROR, "warning: block counter just went negative (this should not happen)\n"); \ + return; \ + } \ +} + +static void rpza_decode_stream(RpzaContext *s) +{ + int width = s->avctx->width; + int stride = s->frame.linesize[0] / 2; + int row_inc = stride - 4; + int stream_ptr = 0; + int chunk_size; + unsigned char opcode; + int n_blocks; + unsigned short colorA = 0, colorB; + unsigned short color4[4]; + unsigned char index, idx; + unsigned short ta, tb; + unsigned short *pixels = (unsigned short *)s->frame.data[0]; + + int row_ptr = 0; + int pixel_ptr = 0; + int block_ptr; + int pixel_x, pixel_y; + int total_blocks; + + /* First byte is always 0xe1. Warn if it's different */ + if (s->buf[stream_ptr] != 0xe1) + av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0xe1\n", + s->buf[stream_ptr]); + + /* Get chunk size, ingnoring first byte */ + chunk_size = AV_RB32(&s->buf[stream_ptr]) & 0x00FFFFFF; + stream_ptr += 4; + + /* If length mismatch use size from MOV file and try to decode anyway */ + if (chunk_size != s->size) + av_log(s->avctx, AV_LOG_ERROR, "MOV chunk size != encoded chunk size; using MOV chunk size\n"); + + chunk_size = s->size; + + /* Number of 4x4 blocks in frame. */ + total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4); + + /* Process chunk data */ + while (stream_ptr < chunk_size) { + opcode = s->buf[stream_ptr++]; /* Get opcode */ + + n_blocks = (opcode & 0x1f) + 1; /* Extract block counter from opcode */ + + /* If opcode MSbit is 0, we need more data to decide what to do */ + if ((opcode & 0x80) == 0) { + colorA = (opcode << 8) | (s->buf[stream_ptr++]); + opcode = 0; + if ((s->buf[stream_ptr] & 0x80) != 0) { + /* Must behave as opcode 110xxxxx, using colorA computed + * above. Use fake opcode 0x20 to enter switch block at + * the right place */ + opcode = 0x20; + n_blocks = 1; + } + } + + switch (opcode & 0xe0) { + + /* Skip blocks */ + case 0x80: + while (n_blocks--) { + ADVANCE_BLOCK(); + } + break; + + /* Fill blocks with one color */ + case 0xa0: + colorA = AV_RB16 (&s->buf[stream_ptr]); + stream_ptr += 2; + while (n_blocks--) { + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++){ + pixels[block_ptr] = colorA; + block_ptr++; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* Fill blocks with 4 colors */ + case 0xc0: + colorA = AV_RB16 (&s->buf[stream_ptr]); + stream_ptr += 2; + case 0x20: + colorB = AV_RB16 (&s->buf[stream_ptr]); + stream_ptr += 2; + + /* sort out the colors */ + color4[0] = colorB; + color4[1] = 0; + color4[2] = 0; + color4[3] = colorA; + + /* red components */ + ta = (colorA >> 10) & 0x1F; + tb = (colorB >> 10) & 0x1F; + color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10; + color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10; + + /* green components */ + ta = (colorA >> 5) & 0x1F; + tb = (colorB >> 5) & 0x1F; + color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5; + color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5; + + /* blue components */ + ta = colorA & 0x1F; + tb = colorB & 0x1F; + color4[1] |= ((11 * ta + 21 * tb) >> 5); + color4[2] |= ((21 * ta + 11 * tb) >> 5); + + if (s->size - stream_ptr < n_blocks * 4) + return; + while (n_blocks--) { + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + index = s->buf[stream_ptr++]; + for (pixel_x = 0; pixel_x < 4; pixel_x++){ + idx = (index >> (2 * (3 - pixel_x))) & 0x03; + pixels[block_ptr] = color4[idx]; + block_ptr++; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* Fill block with 16 colors */ + case 0x00: + if (s->size - stream_ptr < 16) + return; + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++){ + /* We already have color of upper left pixel */ + if ((pixel_y != 0) || (pixel_x !=0)) { + colorA = AV_RB16 (&s->buf[stream_ptr]); + stream_ptr += 2; + } + pixels[block_ptr] = colorA; + block_ptr++; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + break; + + /* Unknown opcode */ + default: + av_log(s->avctx, AV_LOG_ERROR, "Unknown opcode %d in rpza chunk." + " Skip remaining %d bytes of chunk data.\n", opcode, + chunk_size - stream_ptr); + return; + } /* Opcode switch */ + } +} + +static av_cold int rpza_decode_init(AVCodecContext *avctx) +{ + RpzaContext *s = avctx->priv_data; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_RGB555; + + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + +static int rpza_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + RpzaContext *s = avctx->priv_data; + int ret; + + s->buf = buf; + s->size = buf_size; + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + rpza_decode_stream(s); + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int rpza_decode_end(AVCodecContext *avctx) +{ + RpzaContext *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_rpza_decoder = { + .name = "rpza", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RPZA, + .priv_data_size = sizeof(RpzaContext), + .init = rpza_decode_init, + .close = rpza_decode_end, + .decode = rpza_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), +}; diff --git a/ffmpeg/libavcodec/rtjpeg.c b/ffmpeg/libavcodec/rtjpeg.c new file mode 100644 index 0000000..fe781ce --- /dev/null +++ b/ffmpeg/libavcodec/rtjpeg.c @@ -0,0 +1,173 @@ +/* + * RTJpeg decoding functions + * Copyright (c) 2006 Reimar Doeffinger + * + * 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 "libavutil/common.h" +#include "get_bits.h" +#include "rtjpeg.h" + +#define PUT_COEFF(c) \ + i = scan[coeff--]; \ + block[i] = (c) * quant[i]; + +/// aligns the bitstream to the given power of two +#define ALIGN(a) \ + n = (-get_bits_count(gb)) & (a - 1); \ + if (n) {skip_bits(gb, n);} + +/** + * @brief read one block from stream + * @param gb contains stream data + * @param block where data is written to + * @param scan array containing the mapping stream address -> block position + * @param quant quantization factors + * @return 0 means the block is not coded, < 0 means an error occurred. + * + * Note: GetBitContext is used to make the code simpler, since all data is + * aligned this could be done faster in a different way, e.g. as it is done + * in MPlayer libmpcodecs/native/rtjpegn.c. + */ +static inline int get_block(GetBitContext *gb, int16_t *block, const uint8_t *scan, + const uint32_t *quant) { + int coeff, i, n; + int8_t ac; + uint8_t dc = get_bits(gb, 8); + + // block not coded + if (dc == 255) + return 0; + + // number of non-zero coefficients + coeff = get_bits(gb, 6); + if (get_bits_left(gb) < (coeff << 1)) + return -1; + + // normally we would only need to clear the (63 - coeff) last values, + // but since we do not know where they are we just clear the whole block + memset(block, 0, 64 * sizeof(int16_t)); + + // 2 bits per coefficient + while (coeff) { + ac = get_sbits(gb, 2); + if (ac == -2) + break; // continue with more bits + PUT_COEFF(ac); + } + + // 4 bits per coefficient + ALIGN(4); + if (get_bits_left(gb) < (coeff << 2)) + return -1; + while (coeff) { + ac = get_sbits(gb, 4); + if (ac == -8) + break; // continue with more bits + PUT_COEFF(ac); + } + + // 8 bits per coefficient + ALIGN(8); + if (get_bits_left(gb) < (coeff << 3)) + return -1; + while (coeff) { + ac = get_sbits(gb, 8); + PUT_COEFF(ac); + } + + PUT_COEFF(dc); + return 1; +} + +/** + * @brief decode one rtjpeg YUV420 frame + * @param c context, must be initialized via ff_rtjpeg_decode_init + * @param f AVFrame to place decoded frame into. If parts of the frame + * are not coded they are left unchanged, so consider initializing it + * @param buf buffer containing input data + * @param buf_size length of input data in bytes + * @return number of bytes consumed from the input buffer + */ +int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, + const uint8_t *buf, int buf_size) { + GetBitContext gb; + int w = c->w / 16, h = c->h / 16; + int x, y; + uint8_t *y1 = f->data[0], *y2 = f->data[0] + 8 * f->linesize[0]; + uint8_t *u = f->data[1], *v = f->data[2]; + init_get_bits(&gb, buf, buf_size * 8); + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { +#define BLOCK(quant, dst, stride) do { \ + int res = get_block(&gb, block, c->scan, quant); \ + if (res < 0) \ + return res; \ + if (res > 0) \ + c->dsp->idct_put(dst, stride, block); \ +} while (0) + int16_t *block = c->block; + BLOCK(c->lquant, y1, f->linesize[0]); + y1 += 8; + BLOCK(c->lquant, y1, f->linesize[0]); + y1 += 8; + BLOCK(c->lquant, y2, f->linesize[0]); + y2 += 8; + BLOCK(c->lquant, y2, f->linesize[0]); + y2 += 8; + BLOCK(c->cquant, u, f->linesize[1]); + u += 8; + BLOCK(c->cquant, v, f->linesize[2]); + v += 8; + } + y1 += 2 * 8 * (f->linesize[0] - w); + y2 += 2 * 8 * (f->linesize[0] - w); + u += 8 * (f->linesize[1] - w); + v += 8 * (f->linesize[2] - w); + } + return get_bits_count(&gb) / 8; +} + +/** + * @brief initialize an RTJpegContext, may be called multiple times + * @param c context to initialize + * @param dsp specifies the idct to use for decoding + * @param width width of image, will be rounded down to the nearest multiple + * of 16 for decoding + * @param height height of image, will be rounded down to the nearest multiple + * of 16 for decoding + * @param lquant luma quantization table to use + * @param cquant chroma quantization table to use + */ +void ff_rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, + int width, int height, + const uint32_t *lquant, const uint32_t *cquant) { + int i; + c->dsp = dsp; + for (i = 0; i < 64; i++) { + int z = ff_zigzag_direct[i]; + int p = c->dsp->idct_permutation[i]; + z = ((z << 3) | (z >> 3)) & 63; // rtjpeg uses a transposed variant + + // permute the scan and quantization tables for the chosen idct + c->scan[i] = c->dsp->idct_permutation[z]; + c->lquant[p] = lquant[i]; + c->cquant[p] = cquant[i]; + } + c->w = width; + c->h = height; +} diff --git a/ffmpeg/libavcodec/rtjpeg.h b/ffmpeg/libavcodec/rtjpeg.h new file mode 100644 index 0000000..294b06c --- /dev/null +++ b/ffmpeg/libavcodec/rtjpeg.h @@ -0,0 +1,47 @@ +/* + * RTJpeg decoding functions + * copyright (c) 2006 Reimar Doeffinger + * + * 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 + */ + +#ifndef AVCODEC_RTJPEG_H +#define AVCODEC_RTJPEG_H + +#include +#include "dsputil.h" +#include "libavutil/mem.h" + +#define RTJPEG_FILE_VERSION 0 +#define RTJPEG_HEADER_SIZE 12 + +typedef struct RTJpegContext { + int w, h; + DSPContext *dsp; + uint8_t scan[64]; + uint32_t lquant[64]; + uint32_t cquant[64]; + DECLARE_ALIGNED(16, int16_t, block)[64]; +} RTJpegContext; + +void ff_rtjpeg_decode_init(RTJpegContext *c, DSPContext *dsp, + int width, int height, + const uint32_t *lquant, const uint32_t *cquant); + +int ff_rtjpeg_decode_frame_yuv420(RTJpegContext *c, AVFrame *f, + const uint8_t *buf, int buf_size); +#endif /* AVCODEC_RTJPEG_H */ diff --git a/ffmpeg/libavcodec/rv10.c b/ffmpeg/libavcodec/rv10.c new file mode 100644 index 0000000..b5772b2 --- /dev/null +++ b/ffmpeg/libavcodec/rv10.c @@ -0,0 +1,789 @@ +/* + * RV10/RV20 decoder + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * RV10/RV20 decoder + */ + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "error_resilience.h" +#include "mpegvideo.h" +#include "mpeg4video.h" +#include "h263.h" + +//#define DEBUG + +#define RV_GET_MAJOR_VER(x) ((x) >> 28) +#define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF) +#define RV_GET_MICRO_VER(x) (((x) >> 12) & 0xFF) + +#define DC_VLC_BITS 14 //FIXME find a better solution + +typedef struct RVDecContext { + MpegEncContext m; + int sub_id; +} RVDecContext; + +static const uint16_t rv_lum_code[256] = +{ + 0x3e7f, 0x0f00, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 0x0f06, + 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, + 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, + 0x0f17, 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, + 0x0f1f, 0x0f20, 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, + 0x0f27, 0x0f28, 0x0f29, 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, + 0x0f2f, 0x0f30, 0x0f31, 0x0f32, 0x0f33, 0x0f34, 0x0f35, 0x0f36, + 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b, 0x0f3c, 0x0f3d, 0x0f3e, + 0x0f3f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, + 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x038c, 0x038d, 0x038e, + 0x038f, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, + 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, + 0x039f, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, + 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, + 0x00cf, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, + 0x0057, 0x0020, 0x0021, 0x0022, 0x0023, 0x000c, 0x000d, 0x0004, + 0x0000, 0x0005, 0x000e, 0x000f, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, + 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44, 0x0f45, 0x0f46, 0x0f47, + 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d, 0x0f4e, 0x0f4f, + 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56, 0x0f57, + 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f, + 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, + 0x0f68, 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, + 0x0f70, 0x0f71, 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, + 0x0f78, 0x0f79, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, +}; + +static const uint8_t rv_lum_bits[256] = +{ + 14, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 7, 7, 7, 7, 7, 7, 7, + 7, 6, 6, 6, 6, 5, 5, 4, + 2, 4, 5, 5, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, +}; + +static const uint16_t rv_chrom_code[256] = +{ + 0xfe7f, 0x3f00, 0x3f01, 0x3f02, 0x3f03, 0x3f04, 0x3f05, 0x3f06, + 0x3f07, 0x3f08, 0x3f09, 0x3f0a, 0x3f0b, 0x3f0c, 0x3f0d, 0x3f0e, + 0x3f0f, 0x3f10, 0x3f11, 0x3f12, 0x3f13, 0x3f14, 0x3f15, 0x3f16, + 0x3f17, 0x3f18, 0x3f19, 0x3f1a, 0x3f1b, 0x3f1c, 0x3f1d, 0x3f1e, + 0x3f1f, 0x3f20, 0x3f21, 0x3f22, 0x3f23, 0x3f24, 0x3f25, 0x3f26, + 0x3f27, 0x3f28, 0x3f29, 0x3f2a, 0x3f2b, 0x3f2c, 0x3f2d, 0x3f2e, + 0x3f2f, 0x3f30, 0x3f31, 0x3f32, 0x3f33, 0x3f34, 0x3f35, 0x3f36, + 0x3f37, 0x3f38, 0x3f39, 0x3f3a, 0x3f3b, 0x3f3c, 0x3f3d, 0x3f3e, + 0x3f3f, 0x0f80, 0x0f81, 0x0f82, 0x0f83, 0x0f84, 0x0f85, 0x0f86, + 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c, 0x0f8d, 0x0f8e, + 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95, 0x0f96, + 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e, + 0x0f9f, 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, + 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, + 0x03cf, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, + 0x00e7, 0x0030, 0x0031, 0x0032, 0x0033, 0x0008, 0x0009, 0x0002, + 0x0000, 0x0003, 0x000a, 0x000b, 0x0034, 0x0035, 0x0036, 0x0037, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x03d0, 0x03d1, 0x03d2, 0x03d3, 0x03d4, 0x03d5, 0x03d6, 0x03d7, + 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df, + 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7, + 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, + 0x0fb0, 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, + 0x0fb8, 0x0fb9, 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, + 0x3f40, 0x3f41, 0x3f42, 0x3f43, 0x3f44, 0x3f45, 0x3f46, 0x3f47, + 0x3f48, 0x3f49, 0x3f4a, 0x3f4b, 0x3f4c, 0x3f4d, 0x3f4e, 0x3f4f, + 0x3f50, 0x3f51, 0x3f52, 0x3f53, 0x3f54, 0x3f55, 0x3f56, 0x3f57, + 0x3f58, 0x3f59, 0x3f5a, 0x3f5b, 0x3f5c, 0x3f5d, 0x3f5e, 0x3f5f, + 0x3f60, 0x3f61, 0x3f62, 0x3f63, 0x3f64, 0x3f65, 0x3f66, 0x3f67, + 0x3f68, 0x3f69, 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6d, 0x3f6e, 0x3f6f, + 0x3f70, 0x3f71, 0x3f72, 0x3f73, 0x3f74, 0x3f75, 0x3f76, 0x3f77, + 0x3f78, 0x3f79, 0x3f7a, 0x3f7b, 0x3f7c, 0x3f7d, 0x3f7e, 0x3f7f, +}; + +static const uint8_t rv_chrom_bits[256] = +{ + 16, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 8, 8, 8, 8, 8, 8, 8, + 8, 6, 6, 6, 6, 4, 4, 3, + 2, 3, 4, 4, 6, 6, 6, 6, + 8, 8, 8, 8, 8, 8, 8, 8, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, +}; + +static VLC rv_dc_lum, rv_dc_chrom; + +int ff_rv_decode_dc(MpegEncContext *s, int n) +{ + int code; + + if (n < 4) { + code = get_vlc2(&s->gb, rv_dc_lum.table, DC_VLC_BITS, 2); + if (code < 0) { + /* XXX: I don't understand why they use LONGER codes than + necessary. The following code would be completely useless + if they had thought about it !!! */ + code = get_bits(&s->gb, 7); + if (code == 0x7c) { + code = (int8_t)(get_bits(&s->gb, 7) + 1); + } else if (code == 0x7d) { + code = -128 + get_bits(&s->gb, 7); + } else if (code == 0x7e) { + if (get_bits1(&s->gb) == 0) + code = (int8_t)(get_bits(&s->gb, 8) + 1); + else + code = (int8_t)(get_bits(&s->gb, 8)); + } else if (code == 0x7f) { + skip_bits(&s->gb, 11); + code = 1; + } + } else { + code -= 128; + } + } else { + code = get_vlc2(&s->gb, rv_dc_chrom.table, DC_VLC_BITS, 2); + /* same remark */ + if (code < 0) { + code = get_bits(&s->gb, 9); + if (code == 0x1fc) { + code = (int8_t)(get_bits(&s->gb, 7) + 1); + } else if (code == 0x1fd) { + code = -128 + get_bits(&s->gb, 7); + } else if (code == 0x1fe) { + skip_bits(&s->gb, 9); + code = 1; + } else { + av_log(s->avctx, AV_LOG_ERROR, "chroma dc error\n"); + return 0xffff; + } + } else { + code -= 128; + } + } + return -code; +} + +/* read RV 1.0 compatible frame header */ +static int rv10_decode_picture_header(MpegEncContext *s) +{ + int mb_count, pb_frame, marker, mb_xy; + + marker = get_bits1(&s->gb); + + if (get_bits1(&s->gb)) + s->pict_type = AV_PICTURE_TYPE_P; + else + s->pict_type = AV_PICTURE_TYPE_I; + if(!marker) av_log(s->avctx, AV_LOG_ERROR, "marker missing\n"); + pb_frame = get_bits1(&s->gb); + + av_dlog(s->avctx, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame); + + if (pb_frame){ + av_log(s->avctx, AV_LOG_ERROR, "pb frame not supported\n"); + return -1; + } + + s->qscale = get_bits(&s->gb, 5); + if(s->qscale==0){ + av_log(s->avctx, AV_LOG_ERROR, "error, qscale:0\n"); + return -1; + } + + if (s->pict_type == AV_PICTURE_TYPE_I) { + if (s->rv10_version == 3) { + /* specific MPEG like DC coding not used */ + s->last_dc[0] = get_bits(&s->gb, 8); + s->last_dc[1] = get_bits(&s->gb, 8); + s->last_dc[2] = get_bits(&s->gb, 8); + av_dlog(s->avctx, "DC:%d %d %d\n", s->last_dc[0], + s->last_dc[1], s->last_dc[2]); + } + } + /* if multiple packets per frame are sent, the position at which + to display the macroblocks is coded here */ + + mb_xy= s->mb_x + s->mb_y*s->mb_width; + if(show_bits(&s->gb, 12)==0 || (mb_xy && mb_xy < s->mb_num)){ + s->mb_x = get_bits(&s->gb, 6); /* mb_x */ + s->mb_y = get_bits(&s->gb, 6); /* mb_y */ + mb_count = get_bits(&s->gb, 12); + } else { + s->mb_x = 0; + s->mb_y = 0; + mb_count = s->mb_width * s->mb_height; + } + skip_bits(&s->gb, 3); /* ignored */ + s->f_code = 1; + s->unrestricted_mv = 1; + + return mb_count; +} + +static int rv20_decode_picture_header(RVDecContext *rv) +{ + MpegEncContext *s = &rv->m; + int seq, mb_pos, i; + int rpr_bits; + +#if 0 + GetBitContext gb= s->gb; + for(i=0; i<64; i++){ + av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&gb)); + if(i%4==3) av_log(s->avctx, AV_LOG_DEBUG, " "); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); +#endif +#if 0 + av_log(s->avctx, AV_LOG_DEBUG, "%3dx%03d/%02Xx%02X ", s->width, s->height, s->width/4, s->height/4); + for(i=0; iavctx->extradata_size; i++){ + av_log(s->avctx, AV_LOG_DEBUG, "%02X ", ((uint8_t*)s->avctx->extradata)[i]); + if(i%4==3) av_log(s->avctx, AV_LOG_DEBUG, " "); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); +#endif + + i= get_bits(&s->gb, 2); + switch(i){ + case 0: s->pict_type= AV_PICTURE_TYPE_I; break; + case 1: s->pict_type= AV_PICTURE_TYPE_I; break; //hmm ... + case 2: s->pict_type= AV_PICTURE_TYPE_P; break; + case 3: s->pict_type= AV_PICTURE_TYPE_B; break; + default: + av_log(s->avctx, AV_LOG_ERROR, "unknown frame type\n"); + return -1; + } + + if(s->low_delay && s->pict_type==AV_PICTURE_TYPE_B){ + av_log(s->avctx, AV_LOG_ERROR, "low delay B\n"); + return -1; + } + if(s->last_picture_ptr==NULL && s->pict_type==AV_PICTURE_TYPE_B){ + av_log(s->avctx, AV_LOG_ERROR, "early B pix\n"); + return -1; + } + + if (get_bits1(&s->gb)){ + av_log(s->avctx, AV_LOG_ERROR, "reserved bit set\n"); + return -1; + } + + s->qscale = get_bits(&s->gb, 5); + if(s->qscale==0){ + av_log(s->avctx, AV_LOG_ERROR, "error, qscale:0\n"); + return -1; + } + + if(RV_GET_MINOR_VER(rv->sub_id) >= 2) + s->loop_filter = get_bits1(&s->gb) && !s->avctx->lowres; + + if(RV_GET_MINOR_VER(rv->sub_id) <= 1) + seq = get_bits(&s->gb, 8) << 7; + else + seq = get_bits(&s->gb, 13) << 2; + + rpr_bits = s->avctx->extradata[1] & 7; + if(rpr_bits){ + int f, new_w, new_h; + rpr_bits = FFMIN((rpr_bits >> 1) + 1, 3); + + f = get_bits(&s->gb, rpr_bits); + + if(f){ + new_w= 4*((uint8_t*)s->avctx->extradata)[6+2*f]; + new_h= 4*((uint8_t*)s->avctx->extradata)[7+2*f]; + }else{ + new_w= s->orig_width ; + new_h= s->orig_height; + } + if(new_w != s->width || new_h != s->height){ + AVRational old_aspect = s->avctx->sample_aspect_ratio; + av_log(s->avctx, AV_LOG_DEBUG, "attempting to change resolution to %dx%d\n", new_w, new_h); + if (av_image_check_size(new_w, new_h, 0, s->avctx) < 0) + return -1; + ff_MPV_common_end(s); + + // attempt to keep aspect during typical resolution switches + if (!old_aspect.num) + old_aspect = (AVRational){1, 1}; + if (2 * new_w * s->height == new_h * s->width) + s->avctx->sample_aspect_ratio = av_mul_q(old_aspect, (AVRational){2, 1}); + if (new_w * s->height == 2 * new_h * s->width) + s->avctx->sample_aspect_ratio = av_mul_q(old_aspect, (AVRational){1, 2}); + avcodec_set_dimensions(s->avctx, new_w, new_h); + s->width = new_w; + s->height = new_h; + if (ff_MPV_common_init(s) < 0) + return -1; + } + + if(s->avctx->debug & FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "F %d/%d\n", f, rpr_bits); + } + } + if (av_image_check_size(s->width, s->height, 0, s->avctx) < 0) + return AVERROR_INVALIDDATA; + + mb_pos = ff_h263_decode_mba(s); + + seq |= s->time &~0x7FFF; + if(seq - s->time > 0x4000) seq -= 0x8000; + if(seq - s->time < -0x4000) seq += 0x8000; + if(seq != s->time){ + if(s->pict_type!=AV_PICTURE_TYPE_B){ + s->time= seq; + s->pp_time= s->time - s->last_non_b_time; + s->last_non_b_time= s->time; + }else{ + s->time= seq; + s->pb_time= s->pp_time - (s->last_non_b_time - s->time); + } + } + if (s->pict_type==AV_PICTURE_TYPE_B) { + if(s->pp_time <=s->pb_time || s->pp_time <= s->pp_time - s->pb_time || s->pp_time<=0){ + av_log(s->avctx, AV_LOG_DEBUG, "messed up order, possible from seeking? skipping current b frame\n"); +#define ERROR_SKIP_FRAME -123 + return ERROR_SKIP_FRAME; + } + ff_mpeg4_init_direct_mv(s); + } + + s->no_rounding= get_bits1(&s->gb); + + if(RV_GET_MINOR_VER(rv->sub_id) <= 1 && s->pict_type == AV_PICTURE_TYPE_B) + skip_bits(&s->gb, 5); // binary decoder reads 3+2 bits here but they don't seem to be used + + s->f_code = 1; + s->unrestricted_mv = 1; + s->h263_aic= s->pict_type == AV_PICTURE_TYPE_I; +// s->alt_inter_vlc=1; +// s->obmc=1; +// s->umvplus=1; + s->modified_quant=1; + if(!s->avctx->lowres) + s->loop_filter=1; + + if(s->avctx->debug & FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_INFO, "num:%5d x:%2d y:%2d type:%d qscale:%2d rnd:%d\n", + seq, s->mb_x, s->mb_y, s->pict_type, s->qscale, s->no_rounding); + } + + av_assert0(s->pict_type != AV_PICTURE_TYPE_B || !s->low_delay); + + return s->mb_width*s->mb_height - mb_pos; +} + +static av_cold int rv10_decode_init(AVCodecContext *avctx) +{ + RVDecContext *rv = avctx->priv_data; + MpegEncContext *s = &rv->m; + static int done=0; + int major_ver, minor_ver, micro_ver; + + if (avctx->extradata_size < 8) { + av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n"); + return -1; + } + + ff_MPV_decode_defaults(s); + + s->avctx= avctx; + s->out_format = FMT_H263; + s->codec_id= avctx->codec_id; + + s->orig_width = s->width = avctx->coded_width; + s->orig_height= s->height = avctx->coded_height; + + s->h263_long_vectors= ((uint8_t*)avctx->extradata)[3] & 1; + rv->sub_id = AV_RB32((uint8_t*)avctx->extradata + 4); + + major_ver = RV_GET_MAJOR_VER(rv->sub_id); + minor_ver = RV_GET_MINOR_VER(rv->sub_id); + micro_ver = RV_GET_MICRO_VER(rv->sub_id); + + s->low_delay = 1; + switch (major_ver) { + case 1: + s->rv10_version = micro_ver ? 3 : 1; + s->obmc = micro_ver == 2; + break; + case 2: + if (minor_ver >= 2) { + s->low_delay = 0; + s->avctx->has_b_frames = 1; + } + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", rv->sub_id); + avpriv_request_sample(avctx, "RV1/2 version"); + return AVERROR_PATCHWELCOME; + } + + if(avctx->debug & FF_DEBUG_PICT_INFO){ + av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", rv->sub_id, ((uint32_t*)avctx->extradata)[0]); + } + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + if (ff_MPV_common_init(s) < 0) + return -1; + + ff_h263_decode_init_vlc(); + + /* init rv vlc */ + if (!done) { + INIT_VLC_STATIC(&rv_dc_lum, DC_VLC_BITS, 256, + rv_lum_bits, 1, 1, + rv_lum_code, 2, 2, 16384); + INIT_VLC_STATIC(&rv_dc_chrom, DC_VLC_BITS, 256, + rv_chrom_bits, 1, 1, + rv_chrom_code, 2, 2, 16388); + done = 1; + } + + return 0; +} + +static av_cold int rv10_decode_end(AVCodecContext *avctx) +{ + MpegEncContext *s = avctx->priv_data; + + ff_MPV_common_end(s); + return 0; +} + +static int rv10_decode_packet(AVCodecContext *avctx, + const uint8_t *buf, int buf_size, int buf_size2) +{ + RVDecContext *rv = avctx->priv_data; + MpegEncContext *s = &rv->m; + int mb_count, mb_pos, left, start_mb_x, active_bits_size; + + active_bits_size = buf_size * 8; + init_get_bits(&s->gb, buf, FFMAX(buf_size, buf_size2) * 8); + if(s->codec_id ==AV_CODEC_ID_RV10) + mb_count = rv10_decode_picture_header(s); + else + mb_count = rv20_decode_picture_header(rv); + if (mb_count < 0) { + if (mb_count != ERROR_SKIP_FRAME) + av_log(s->avctx, AV_LOG_ERROR, "HEADER ERROR\n"); + return -1; + } + + if (s->mb_x >= s->mb_width || + s->mb_y >= s->mb_height) { + av_log(s->avctx, AV_LOG_ERROR, "POS ERROR %d %d\n", s->mb_x, s->mb_y); + return -1; + } + mb_pos = s->mb_y * s->mb_width + s->mb_x; + left = s->mb_width * s->mb_height - mb_pos; + if (mb_count > left) { + av_log(s->avctx, AV_LOG_ERROR, "COUNT ERROR\n"); + return -1; + } + + if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr==NULL) { + if(s->current_picture_ptr){ //FIXME write parser so we always have complete frames? + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); + s->mb_x= s->mb_y = s->resync_mb_x = s->resync_mb_y= 0; + } + if(ff_MPV_frame_start(s, avctx) < 0) + return -1; + ff_mpeg_er_frame_start(s); + } else { + if (s->current_picture_ptr->f.pict_type != s->pict_type) { + av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n"); + return -1; + } + } + + + av_dlog(avctx, "qscale=%d\n", s->qscale); + + /* default quantization values */ + if(s->codec_id== AV_CODEC_ID_RV10){ + if(s->mb_y==0) s->first_slice_line=1; + }else{ + s->first_slice_line=1; + s->resync_mb_x= s->mb_x; + } + start_mb_x= s->mb_x; + s->resync_mb_y= s->mb_y; + if(s->h263_aic){ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_aic_dc_scale_table; + }else{ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } + + if(s->modified_quant) + s->chroma_qscale_table= ff_h263_chroma_qscale_table; + + ff_set_qscale(s, s->qscale); + + s->rv10_first_dc_coded[0] = 0; + s->rv10_first_dc_coded[1] = 0; + s->rv10_first_dc_coded[2] = 0; + s->block_wrap[0]= + s->block_wrap[1]= + s->block_wrap[2]= + s->block_wrap[3]= s->b8_stride; + s->block_wrap[4]= + s->block_wrap[5]= s->mb_stride; + ff_init_block_index(s); + /* decode each macroblock */ + + for(s->mb_num_left= mb_count; s->mb_num_left>0; s->mb_num_left--) { + int ret; + ff_update_block_index(s); + av_dlog(avctx, "**mb x=%d y=%d\n", s->mb_x, s->mb_y); + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + ret=ff_h263_decode_mb(s, s->block); + + // Repeat the slice end check from ff_h263_decode_mb with our active + // bitstream size + if (ret != SLICE_ERROR) { + int v = show_bits(&s->gb, 16); + + if (get_bits_count(&s->gb) + 16 > active_bits_size) + v >>= get_bits_count(&s->gb) + 16 - active_bits_size; + + if (!v) + ret = SLICE_END; + } + if (ret != SLICE_ERROR && active_bits_size < get_bits_count(&s->gb) && + 8 * buf_size2 >= get_bits_count(&s->gb)) { + active_bits_size = buf_size2 * 8; + av_log(avctx, AV_LOG_DEBUG, "update size from %d to %d\n", + 8 * buf_size, active_bits_size); + ret= SLICE_OK; + } + + if (ret == SLICE_ERROR || active_bits_size < get_bits_count(&s->gb)) { + av_log(s->avctx, AV_LOG_ERROR, "ERROR at MB %d %d\n", s->mb_x, s->mb_y); + return -1; + } + if(s->pict_type != AV_PICTURE_TYPE_B) + ff_h263_update_motion_val(s); + ff_MPV_decode_mb(s, s->block); + if(s->loop_filter) + ff_h263_loop_filter(s); + + if (++s->mb_x == s->mb_width) { + s->mb_x = 0; + s->mb_y++; + ff_init_block_index(s); + } + if(s->mb_x == s->resync_mb_x) + s->first_slice_line=0; + if(ret == SLICE_END) break; + } + + ff_er_add_slice(&s->er, start_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END); + + return active_bits_size; +} + +static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) +{ + if(avctx->slice_count) return avctx->slice_offset[n]; + else return AV_RL32(buf + n*8); +} + +static int rv10_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + MpegEncContext *s = avctx->priv_data; + int i, ret; + AVFrame *pict = data; + int slice_count; + const uint8_t *slices_hdr = NULL; + + av_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); + s->flags = avctx->flags; + s->flags2 = avctx->flags2; + + /* no supplementary picture */ + if (buf_size == 0) { + return 0; + } + + if(!avctx->slice_count){ + slice_count = (*buf++) + 1; + buf_size--; + + if (!slice_count || buf_size <= 8 * slice_count) { + av_log(avctx, AV_LOG_ERROR, "Invalid slice count: %d.\n", slice_count); + return AVERROR_INVALIDDATA; + } + + slices_hdr = buf + 4; + buf += 8 * slice_count; + buf_size -= 8 * slice_count; + }else + slice_count = avctx->slice_count; + + for(i=0; i= buf_size) + return AVERROR_INVALIDDATA; + + if(i+1 == slice_count) + size= buf_size - offset; + else + size= get_slice_offset(avctx, slices_hdr, i+1) - offset; + + if(i+2 >= slice_count) + size2= buf_size - offset; + else + size2= get_slice_offset(avctx, slices_hdr, i+2) - offset; + + if (size <= 0 || size2 <= 0 || + offset + FFMAX(size, size2) > buf_size) + return AVERROR_INVALIDDATA; + + if(rv10_decode_packet(avctx, buf+offset, size, size2) > 8*size) + i++; + } + + if(s->current_picture_ptr != NULL && s->mb_y>=s->mb_height){ + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); + + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { + if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->current_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); + } else if (s->last_picture_ptr != NULL) { + if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->last_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict,s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); + } + + if(s->last_picture_ptr || s->low_delay){ + *got_frame = 1; + } + s->current_picture_ptr= NULL; // so we can detect if frame_end was not called (find some nicer solution...) + } + + return avpkt->size; +} + +AVCodec ff_rv10_decoder = { + .name = "rv10", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV10, + .priv_data_size = sizeof(RVDecContext), + .init = rv10_decode_init, + .close = rv10_decode_end, + .decode = rv10_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .pix_fmts = ff_pixfmt_list_420, +}; + +AVCodec ff_rv20_decoder = { + .name = "rv20", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV20, + .priv_data_size = sizeof(RVDecContext), + .init = rv10_decode_init, + .close = rv10_decode_end, + .decode = rv10_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .flush = ff_mpeg_flush, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), + .pix_fmts = ff_pixfmt_list_420, +}; diff --git a/ffmpeg/libavcodec/rv10enc.c b/ffmpeg/libavcodec/rv10enc.c new file mode 100644 index 0000000..c4c5c53 --- /dev/null +++ b/ffmpeg/libavcodec/rv10enc.c @@ -0,0 +1,72 @@ +/* + * RV10 encoder + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * RV10 encoder + */ + +#include "mpegvideo.h" +#include "put_bits.h" + +void ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) +{ + int full_frame= 0; + + avpriv_align_put_bits(&s->pb); + + put_bits(&s->pb, 1, 1); /* marker */ + + put_bits(&s->pb, 1, (s->pict_type == AV_PICTURE_TYPE_P)); + + put_bits(&s->pb, 1, 0); /* not PB frame */ + + put_bits(&s->pb, 5, s->qscale); + + if (s->pict_type == AV_PICTURE_TYPE_I) { + /* specific MPEG like DC coding not used */ + } + /* if multiple packets per frame are sent, the position at which + to display the macroblocks is coded here */ + if(!full_frame){ + put_bits(&s->pb, 6, 0); /* mb_x */ + put_bits(&s->pb, 6, 0); /* mb_y */ + put_bits(&s->pb, 12, s->mb_width * s->mb_height); + } + + put_bits(&s->pb, 3, 0); /* ignored */ +} + +FF_MPV_GENERIC_CLASS(rv10) + +AVCodec ff_rv10_encoder = { + .name = "rv10", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV10, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .priv_class = &rv10_class, +}; diff --git a/ffmpeg/libavcodec/rv20enc.c b/ffmpeg/libavcodec/rv20enc.c new file mode 100644 index 0000000..295699a --- /dev/null +++ b/ffmpeg/libavcodec/rv20enc.c @@ -0,0 +1,73 @@ +/* + * RV20 encoder + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * RV20 encoder + */ + +#include "mpegvideo.h" +#include "h263.h" +#include "put_bits.h" + +void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ + put_bits(&s->pb, 2, s->pict_type); //I 0 vs. 1 ? + put_bits(&s->pb, 1, 0); /* unknown bit */ + put_bits(&s->pb, 5, s->qscale); + + put_sbits(&s->pb, 8, picture_number); //FIXME wrong, but correct is not known + s->mb_x= s->mb_y= 0; + ff_h263_encode_mba(s); + + put_bits(&s->pb, 1, s->no_rounding); + + av_assert0(s->f_code == 1); + av_assert0(s->unrestricted_mv == 0); + av_assert0(s->alt_inter_vlc == 0); + av_assert0(s->umvplus == 0); + av_assert0(s->modified_quant==1); + av_assert0(s->loop_filter==1); + + s->h263_aic= s->pict_type == AV_PICTURE_TYPE_I; + if(s->h263_aic){ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_aic_dc_scale_table; + }else{ + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + } +} + +FF_MPV_GENERIC_CLASS(rv20) + +AVCodec ff_rv20_encoder = { + .name = "rv20", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV20, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_MPV_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), + .priv_class = &rv20_class, +}; diff --git a/ffmpeg/libavcodec/rv30.c b/ffmpeg/libavcodec/rv30.c new file mode 100644 index 0000000..a99980e --- /dev/null +++ b/ffmpeg/libavcodec/rv30.c @@ -0,0 +1,288 @@ +/* + * RV30 decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV30 decoder + */ + +#include "avcodec.h" +#include "mpegvideo.h" +#include "golomb.h" + +#include "rv34.h" +#include "rv30data.h" + + +static int rv30_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceInfo *si) +{ + int mb_bits; + int w = r->s.width, h = r->s.height; + int mb_size; + int rpr; + + memset(si, 0, sizeof(SliceInfo)); + if(get_bits(gb, 3)) + return -1; + si->type = get_bits(gb, 2); + if(si->type == 1) si->type = 0; + if(get_bits1(gb)) + return -1; + si->quant = get_bits(gb, 5); + skip_bits1(gb); + si->pts = get_bits(gb, 13); + rpr = get_bits(gb, r->rpr); + if (r->s.avctx->extradata_size < 8 + rpr*2) { + av_log(r->s.avctx, AV_LOG_WARNING, + "Extradata does not contain selected resolution\n"); + rpr = 0; + } + if(rpr){ + w = r->s.avctx->extradata[6 + rpr*2] << 2; + h = r->s.avctx->extradata[7 + rpr*2] << 2; + } + si->width = w; + si->height = h; + mb_size = ((w + 15) >> 4) * ((h + 15) >> 4); + mb_bits = ff_rv34_get_start_offset(gb, mb_size); + si->start = get_bits(gb, mb_bits); + skip_bits1(gb); + return 0; +} + +/** + * Decode 4x4 intra types array. + */ +static int rv30_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t *dst) +{ + int i, j, k; + + for(i = 0; i < 4; i++, dst += r->intra_types_stride - 4){ + for(j = 0; j < 4; j+= 2){ + unsigned code = svq3_get_ue_golomb(gb) << 1; + if (code > 80U*2U) { + av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction code\n"); + return -1; + } + for(k = 0; k < 2; k++){ + int A = dst[-r->intra_types_stride] + 1; + int B = dst[-1] + 1; + *dst++ = rv30_itype_from_context[A * 90 + B * 9 + rv30_itype_code[code + k]]; + if(dst[-1] == 9){ + av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction mode\n"); + return -1; + } + } + } + } + return 0; +} + +/** + * Decode macroblock information. + */ +static int rv30_decode_mb_info(RV34DecContext *r) +{ + static const int rv30_p_types[6] = { RV34_MB_SKIP, RV34_MB_P_16x16, RV34_MB_P_8x8, -1, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 }; + static const int rv30_b_types[6] = { RV34_MB_SKIP, RV34_MB_B_DIRECT, RV34_MB_B_FORWARD, RV34_MB_B_BACKWARD, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 }; + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + unsigned code = svq3_get_ue_golomb(gb); + + if (code > 11) { + av_log(s->avctx, AV_LOG_ERROR, "Incorrect MB type code\n"); + return -1; + } + if(code > 5){ + av_log(s->avctx, AV_LOG_ERROR, "dquant needed\n"); + code -= 6; + } + if(s->pict_type != AV_PICTURE_TYPE_B) + return rv30_p_types[code]; + else + return rv30_b_types[code]; +} + +static inline void rv30_weak_loop_filter(uint8_t *src, const int step, + const int stride, const int lim) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int i, diff; + + for(i = 0; i < 4; i++){ + diff = ((src[-2*step] - src[1*step]) - (src[-1*step] - src[0*step])*4) >> 3; + diff = av_clip(diff, -lim, lim); + src[-1*step] = cm[src[-1*step] + diff]; + src[ 0*step] = cm[src[ 0*step] - diff]; + src += stride; + } +} + +static void rv30_loop_filter(RV34DecContext *r, int row) +{ + MpegEncContext *s = &r->s; + int mb_pos, mb_x; + int i, j, k; + uint8_t *Y, *C; + int loc_lim, cur_lim, left_lim = 0, top_lim = 0; + + mb_pos = row * s->mb_stride; + for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ + int mbtype = s->current_picture_ptr->mb_type[mb_pos]; + if(IS_INTRA(mbtype) || IS_SEPARATE_DC(mbtype)) + r->deblock_coefs[mb_pos] = 0xFFFF; + if(IS_INTRA(mbtype)) + r->cbp_chroma[mb_pos] = 0xFF; + } + + /* all vertical edges are filtered first + * and horizontal edges are filtered on the next iteration + */ + mb_pos = row * s->mb_stride; + for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ + cur_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos]]; + if(mb_x) + left_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos - 1]]; + for(j = 0; j < 16; j += 4){ + Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize + 4 * !mb_x; + for(i = !mb_x; i < 4; i++, Y += 4){ + int ij = i + j; + loc_lim = 0; + if(r->deblock_coefs[mb_pos] & (1 << ij)) + loc_lim = cur_lim; + else if(!i && r->deblock_coefs[mb_pos - 1] & (1 << (ij + 3))) + loc_lim = left_lim; + else if( i && r->deblock_coefs[mb_pos] & (1 << (ij - 1))) + loc_lim = cur_lim; + if(loc_lim) + rv30_weak_loop_filter(Y, 1, s->linesize, loc_lim); + } + } + for(k = 0; k < 2; k++){ + int cur_cbp, left_cbp = 0; + cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF; + if(mb_x) + left_cbp = (r->cbp_chroma[mb_pos - 1] >> (k*4)) & 0xF; + for(j = 0; j < 8; j += 4){ + C = s->current_picture_ptr->f.data[k + 1] + mb_x*8 + (row*8 + j) * s->uvlinesize + 4 * !mb_x; + for(i = !mb_x; i < 2; i++, C += 4){ + int ij = i + (j >> 1); + loc_lim = 0; + if (cur_cbp & (1 << ij)) + loc_lim = cur_lim; + else if(!i && left_cbp & (1 << (ij + 1))) + loc_lim = left_lim; + else if( i && cur_cbp & (1 << (ij - 1))) + loc_lim = cur_lim; + if(loc_lim) + rv30_weak_loop_filter(C, 1, s->uvlinesize, loc_lim); + } + } + } + } + mb_pos = row * s->mb_stride; + for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ + cur_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos]]; + if(row) + top_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos - s->mb_stride]]; + for(j = 4*!row; j < 16; j += 4){ + Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize; + for(i = 0; i < 4; i++, Y += 4){ + int ij = i + j; + loc_lim = 0; + if(r->deblock_coefs[mb_pos] & (1 << ij)) + loc_lim = cur_lim; + else if(!j && r->deblock_coefs[mb_pos - s->mb_stride] & (1 << (ij + 12))) + loc_lim = top_lim; + else if( j && r->deblock_coefs[mb_pos] & (1 << (ij - 4))) + loc_lim = cur_lim; + if(loc_lim) + rv30_weak_loop_filter(Y, s->linesize, 1, loc_lim); + } + } + for(k = 0; k < 2; k++){ + int cur_cbp, top_cbp = 0; + cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF; + if(row) + top_cbp = (r->cbp_chroma[mb_pos - s->mb_stride] >> (k*4)) & 0xF; + for(j = 4*!row; j < 8; j += 4){ + C = s->current_picture_ptr->f.data[k+1] + mb_x*8 + (row*8 + j) * s->uvlinesize; + for(i = 0; i < 2; i++, C += 4){ + int ij = i + (j >> 1); + loc_lim = 0; + if (r->cbp_chroma[mb_pos] & (1 << ij)) + loc_lim = cur_lim; + else if(!j && top_cbp & (1 << (ij + 2))) + loc_lim = top_lim; + else if( j && cur_cbp & (1 << (ij - 2))) + loc_lim = cur_lim; + if(loc_lim) + rv30_weak_loop_filter(C, s->uvlinesize, 1, loc_lim); + } + } + } + } +} + +/** + * Initialize decoder. + */ +static av_cold int rv30_decode_init(AVCodecContext *avctx) +{ + RV34DecContext *r = avctx->priv_data; + + r->rv30 = 1; + ff_rv34_decode_init(avctx); + if(avctx->extradata_size < 2){ + av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n"); + return -1; + } + r->rpr = (avctx->extradata[1] & 7) >> 1; + r->rpr = FFMIN(r->rpr + 1, 3); + if(avctx->extradata_size - 8 < (r->rpr - 1) * 2){ + av_log(avctx, AV_LOG_ERROR, "Insufficient extradata - need at least %d bytes, got %d\n", + 6 + r->rpr * 2, avctx->extradata_size); + } + r->parse_slice_header = rv30_parse_slice_header; + r->decode_intra_types = rv30_decode_intra_types; + r->decode_mb_info = rv30_decode_mb_info; + r->loop_filter = rv30_loop_filter; + r->luma_dc_quant_i = rv30_luma_dc_quant; + r->luma_dc_quant_p = rv30_luma_dc_quant; + return 0; +} + +AVCodec ff_rv30_decoder = { + .name = "rv30", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV30, + .priv_data_size = sizeof(RV34DecContext), + .init = rv30_decode_init, + .close = ff_rv34_decode_end, + .decode = ff_rv34_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | + CODEC_CAP_FRAME_THREADS, + .flush = ff_mpeg_flush, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 3.0"), + .pix_fmts = ff_pixfmt_list_420, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), +}; diff --git a/ffmpeg/libavcodec/rv30data.h b/ffmpeg/libavcodec/rv30data.h new file mode 100644 index 0000000..9cc48a6 --- /dev/null +++ b/ffmpeg/libavcodec/rv30data.h @@ -0,0 +1,181 @@ +/* + * RealVideo 3 decoder + * copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * miscellaneous RV30 tables + */ + +#ifndef AVCODEC_RV30DATA_H +#define AVCODEC_RV30DATA_H + +#include + +/** DC quantizer mapping for RV30 */ +static const uint8_t rv30_luma_dc_quant[32] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 22, 22, 23, 23, 23, 24, 24, 25, 25 +}; + +/** + * This table is used for storing the differences + * between the predicted and the real intra type. + */ +static const uint8_t rv30_itype_code[9*9*2] = { + 0, 0, 0, 1, 1, 0, 1, 1, 0, 2, 2, 0, 0, 3, 3, 0, 1, 2, + 2, 1, 0, 4, 4, 0, 3, 1, 1, 3, 0, 5, 5, 0, 2, 2, 1, 4, + 4, 1, 0, 6, 3, 2, 1, 5, 2, 3, 5, 1, 6, 0, 0, 7, 4, 2, + 2, 4, 3, 3, 6, 1, 1, 6, 7, 0, 0, 8, 5, 2, 4, 3, 2, 5, + 3, 4, 1, 7, 4, 4, 7, 1, 8, 0, 6, 2, 3, 5, 5, 3, 2, 6, + 1, 8, 2, 7, 7, 2, 8, 1, 5, 4, 4, 5, 3, 6, 6, 3, 8, 2, + 4, 6, 5, 5, 6, 4, 2, 8, 7, 3, 3, 7, 6, 5, 5, 6, 7, 4, + 4, 7, 8, 3, 3, 8, 7, 5, 8, 4, 5, 7, 4, 8, 6, 6, 7, 6, + 5, 8, 8, 5, 6, 7, 8, 6, 7, 7, 6, 8, 8, 7, 7, 8, 8, 8, +}; + +/** + * This table is used for retrieving the current intra type + * based on its neighbors and adjustment provided by + * code read and decoded before. + * + * This is really a three-dimensional matrix with dimensions + * [-1..9][-1..9][0..9]. The first and second coordinates are + * detemined by the top and left neighbors (-1 if unavailable). + */ +static const uint8_t rv30_itype_from_context[900] = { + 0, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 2, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 0, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, + + 0, 1, 9, 9, 9, 9, 9, 9, 9, + 0, 2, 1, 6, 4, 8, 5, 7, 3, + 1, 0, 2, 6, 5, 4, 3, 8, 7, + 2, 8, 0, 1, 7, 4, 3, 6, 5, + 2, 0, 1, 3, 8, 5, 4, 7, 6, + 2, 0, 1, 4, 6, 7, 8, 3, 5, + 0, 1, 5, 2, 6, 3, 8, 4, 7, + 0, 1, 6, 2, 4, 7, 5, 8, 3, + 2, 7, 0, 1, 4, 8, 6, 3, 5, + 2, 8, 0, 1, 7, 3, 4, 5, 6, + + 1, 0, 9, 9, 9, 9, 9, 9, 9, + 1, 2, 5, 6, 3, 0, 4, 8, 7, + 1, 6, 2, 5, 3, 0, 4, 8, 7, + 2, 1, 7, 6, 8, 3, 5, 0, 4, + 1, 2, 5, 3, 6, 8, 4, 7, 0, + 1, 6, 2, 0, 4, 5, 8, 7, 3, + 1, 5, 2, 6, 3, 8, 4, 0, 7, + 1, 6, 0, 2, 4, 5, 7, 3, 8, + 2, 1, 7, 6, 0, 8, 5, 4, 3, + 1, 2, 7, 8, 3, 4, 5, 6, 0, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 2, 1, 8, 7, 6, 5, 4, 3, + 1, 2, 0, 6, 5, 7, 4, 8, 3, + 2, 8, 7, 1, 0, 6, 4, 3, 5, + 2, 0, 8, 1, 3, 7, 5, 4, 6, + 2, 0, 4, 1, 7, 8, 6, 3, 5, + 2, 0, 1, 5, 8, 4, 6, 7, 3, + 2, 0, 6, 1, 4, 7, 8, 5, 3, + 2, 7, 8, 1, 0, 5, 4, 6, 3, + 2, 8, 7, 1, 0, 4, 3, 6, 5, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 0, 2, 1, 3, 5, 8, 6, 4, 7, + 1, 0, 2, 5, 3, 6, 4, 8, 7, + 2, 8, 1, 0, 3, 5, 7, 6, 4, + 3, 2, 5, 8, 1, 4, 6, 7, 0, + 4, 2, 0, 6, 1, 5, 8, 3, 7, + 5, 3, 1, 2, 8, 6, 4, 0, 7, + 1, 6, 0, 2, 4, 5, 8, 3, 7, + 2, 7, 0, 1, 5, 4, 8, 6, 3, + 2, 8, 3, 5, 1, 0, 7, 6, 4, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 0, 6, 1, 4, 7, 5, 8, 3, + 1, 6, 2, 0, 4, 5, 3, 7, 8, + 2, 8, 7, 6, 4, 0, 1, 5, 3, + 4, 2, 1, 0, 6, 8, 3, 5, 7, + 4, 2, 6, 0, 1, 5, 7, 8, 3, + 1, 2, 5, 0, 6, 3, 4, 7, 8, + 6, 4, 0, 1, 2, 7, 5, 3, 8, + 2, 7, 4, 6, 0, 1, 8, 5, 3, + 2, 8, 7, 4, 6, 1, 3, 5, 0, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 5, 1, 2, 3, 6, 8, 0, 4, 7, + 1, 5, 6, 3, 2, 0, 4, 8, 7, + 2, 1, 5, 3, 6, 8, 7, 4, 0, + 5, 3, 1, 2, 6, 8, 4, 7, 0, + 1, 6, 2, 4, 5, 8, 0, 3, 7, + 5, 1, 3, 6, 2, 0, 8, 4, 7, + 1, 6, 5, 2, 0, 4, 3, 7, 8, + 2, 7, 1, 6, 5, 0, 8, 3, 4, + 2, 5, 1, 3, 6, 8, 4, 0, 7, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 1, 6, 2, 0, 5, 4, 3, 7, 8, + 1, 6, 5, 4, 2, 3, 0, 7, 8, + 2, 1, 6, 7, 4, 8, 5, 3, 0, + 2, 1, 6, 5, 8, 4, 3, 0, 7, + 6, 4, 1, 2, 0, 5, 7, 8, 3, + 1, 6, 5, 2, 3, 0, 4, 8, 7, + 6, 1, 4, 0, 2, 7, 5, 3, 8, + 2, 7, 4, 6, 1, 5, 0, 8, 3, + 2, 1, 6, 8, 4, 7, 3, 5, 0, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 0, 4, 7, 6, 1, 8, 5, 3, + 6, 1, 2, 0, 4, 7, 5, 8, 3, + 2, 7, 8, 0, 1, 6, 4, 3, 5, + 2, 4, 0, 8, 3, 1, 7, 6, 5, + 4, 2, 7, 0, 6, 1, 8, 5, 3, + 2, 1, 0, 8, 5, 6, 7, 4, 3, + 2, 6, 4, 1, 7, 0, 5, 8, 3, + 2, 7, 4, 0, 8, 6, 1, 5, 3, + 2, 8, 7, 4, 1, 0, 3, 6, 5, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, + 2, 0, 8, 1, 3, 4, 6, 5, 7, + 1, 2, 0, 6, 8, 5, 7, 3, 4, + 2, 8, 7, 1, 0, 3, 6, 5, 4, + 8, 3, 2, 5, 1, 0, 4, 7, 6, + 2, 0, 4, 8, 5, 1, 7, 6, 3, + 2, 1, 0, 8, 5, 3, 6, 4, 7, + 2, 1, 6, 0, 8, 4, 5, 7, 3, + 2, 7, 8, 4, 0, 6, 1, 5, 3, + 2, 8, 3, 0, 7, 4, 1, 6, 5, +}; + +/** + * Loop filter limits are taken from this table. + */ +static const uint8_t rv30_loop_filt_lim[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5 +}; +#endif /* AVCODEC_RV30DATA_H */ diff --git a/ffmpeg/libavcodec/rv30dsp.c b/ffmpeg/libavcodec/rv30dsp.c new file mode 100644 index 0000000..362b2a5 --- /dev/null +++ b/ffmpeg/libavcodec/rv30dsp.c @@ -0,0 +1,314 @@ +/* + * RV30 decoder motion compensation functions + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV30 decoder motion compensation functions + */ + +#include "avcodec.h" +#include "h264chroma.h" +#include "h264qpel.h" +#include "rv34dsp.h" + +#define RV30_LOWPASS(OPNAME, OP) \ +static av_unused void OPNAME ## rv30_tpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ + const int h = 8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i = 0; i < h; i++)\ + {\ + OP(dst[0], (-(src[-1]+src[2]) + src[0]*C1 + src[1]*C2 + 8)>>4);\ + OP(dst[1], (-(src[ 0]+src[3]) + src[1]*C1 + src[2]*C2 + 8)>>4);\ + OP(dst[2], (-(src[ 1]+src[4]) + src[2]*C1 + src[3]*C2 + 8)>>4);\ + OP(dst[3], (-(src[ 2]+src[5]) + src[3]*C1 + src[4]*C2 + 8)>>4);\ + OP(dst[4], (-(src[ 3]+src[6]) + src[4]*C1 + src[5]*C2 + 8)>>4);\ + OP(dst[5], (-(src[ 4]+src[7]) + src[5]*C1 + src[6]*C2 + 8)>>4);\ + OP(dst[6], (-(src[ 5]+src[8]) + src[6]*C1 + src[7]*C2 + 8)>>4);\ + OP(dst[7], (-(src[ 6]+src[9]) + src[7]*C1 + src[8]*C2 + 8)>>4);\ + dst += dstStride;\ + src += srcStride;\ + }\ +}\ +\ +static void OPNAME ## rv30_tpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ + const int w = 8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i = 0; i < w; i++)\ + {\ + const int srcA = src[-1*srcStride];\ + const int src0 = src[0 *srcStride];\ + const int src1 = src[1 *srcStride];\ + const int src2 = src[2 *srcStride];\ + const int src3 = src[3 *srcStride];\ + const int src4 = src[4 *srcStride];\ + const int src5 = src[5 *srcStride];\ + const int src6 = src[6 *srcStride];\ + const int src7 = src[7 *srcStride];\ + const int src8 = src[8 *srcStride];\ + const int src9 = src[9 *srcStride];\ + OP(dst[0*dstStride], (-(srcA+src2) + src0*C1 + src1*C2 + 8)>>4);\ + OP(dst[1*dstStride], (-(src0+src3) + src1*C1 + src2*C2 + 8)>>4);\ + OP(dst[2*dstStride], (-(src1+src4) + src2*C1 + src3*C2 + 8)>>4);\ + OP(dst[3*dstStride], (-(src2+src5) + src3*C1 + src4*C2 + 8)>>4);\ + OP(dst[4*dstStride], (-(src3+src6) + src4*C1 + src5*C2 + 8)>>4);\ + OP(dst[5*dstStride], (-(src4+src7) + src5*C1 + src6*C2 + 8)>>4);\ + OP(dst[6*dstStride], (-(src5+src8) + src6*C1 + src7*C2 + 8)>>4);\ + OP(dst[7*dstStride], (-(src6+src9) + src7*C1 + src8*C2 + 8)>>4);\ + dst++;\ + src++;\ + }\ +}\ +\ +static void OPNAME ## rv30_tpel8_hv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + const int w = 8;\ + const int h = 8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i, j;\ + for(j = 0; j < h; j++){\ + for(i = 0; i < w; i++){\ + OP(dst[i], (\ + src[srcStride*-1+i-1] -12*src[srcStride*-1+i] -6*src[srcStride*-1+i+1] +src[srcStride*-1+i+2]+\ + -12*src[srcStride* 0+i-1] +144*src[srcStride* 0+i] +72*src[srcStride* 0+i+1] -12*src[srcStride* 0+i+2] +\ + -6*src[srcStride* 1+i-1] +72*src[srcStride* 1+i] +36*src[srcStride* 1+i+1] -6*src[srcStride* 1+i+2] +\ + src[srcStride* 2+i-1] -12*src[srcStride* 2+i] -6*src[srcStride* 2+i+1] +src[srcStride* 2+i+2] +\ + 128)>>8);\ + }\ + src += srcStride;\ + dst += dstStride;\ + }\ +}\ +\ +static void OPNAME ## rv30_tpel8_hhv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + const int w = 8;\ + const int h = 8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i, j;\ + for(j = 0; j < h; j++){\ + for(i = 0; i < w; i++){\ + OP(dst[i], (\ + src[srcStride*-1+i-1] -12*src[srcStride*-1+i+1] -6*src[srcStride*-1+i] +src[srcStride*-1+i+2]+\ + -12*src[srcStride* 0+i-1] +144*src[srcStride* 0+i+1] +72*src[srcStride* 0+i] -12*src[srcStride* 0+i+2]+\ + -6*src[srcStride* 1+i-1] +72*src[srcStride* 1+i+1] +36*src[srcStride* 1+i] -6*src[srcStride* 1+i+2]+\ + src[srcStride* 2+i-1] -12*src[srcStride* 2+i+1] -6*src[srcStride* 2+i] +src[srcStride* 2+i+2]+\ + 128)>>8);\ + }\ + src += srcStride;\ + dst += dstStride;\ + }\ +}\ +\ +static void OPNAME ## rv30_tpel8_hvv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + const int w = 8;\ + const int h = 8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i, j;\ + for(j = 0; j < h; j++){\ + for(i = 0; i < w; i++){\ + OP(dst[i], (\ + src[srcStride*-1+i-1] -12*src[srcStride*-1+i] -6*src[srcStride*-1+i+1] +src[srcStride*-1+i+2]+\ + -6*src[srcStride* 0+i-1] +72*src[srcStride* 0+i] +36*src[srcStride* 0+i+1] -6*src[srcStride* 0+i+2]+\ + -12*src[srcStride* 1+i-1] +144*src[srcStride* 1+i] +72*src[srcStride* 1+i+1] -12*src[srcStride* 1+i+2]+\ + src[srcStride* 2+i-1] -12*src[srcStride* 2+i] -6*src[srcStride* 2+i+1] +src[srcStride* 2+i+2]+\ + 128)>>8);\ + }\ + src += srcStride;\ + dst += dstStride;\ + }\ +}\ +\ +static void OPNAME ## rv30_tpel8_hhvv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + const int w = 8;\ + const int h = 8;\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i, j;\ + for(j = 0; j < h; j++){\ + for(i = 0; i < w; i++){\ + OP(dst[i], (\ + 36*src[i+srcStride*0] +54*src[i+1+srcStride*0] +6*src[i+2+srcStride*0]+\ + 54*src[i+srcStride*1] +81*src[i+1+srcStride*1] +9*src[i+2+srcStride*1]+\ + 6*src[i+srcStride*2] + 9*src[i+1+srcStride*2] + src[i+2+srcStride*2]+\ + 128)>>8);\ + }\ + src += srcStride;\ + dst += dstStride;\ + }\ +}\ +\ +static void OPNAME ## rv30_tpel16_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ + OPNAME ## rv30_tpel8_v_lowpass(dst , src , dstStride, srcStride, C1, C2);\ + OPNAME ## rv30_tpel8_v_lowpass(dst+8, src+8, dstStride, srcStride, C1, C2);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv30_tpel8_v_lowpass(dst , src , dstStride, srcStride, C1, C2);\ + OPNAME ## rv30_tpel8_v_lowpass(dst+8, src+8, dstStride, srcStride, C1, C2);\ +}\ +\ +static void OPNAME ## rv30_tpel16_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, const int C1, const int C2){\ + OPNAME ## rv30_tpel8_h_lowpass(dst , src , dstStride, srcStride, C1, C2);\ + OPNAME ## rv30_tpel8_h_lowpass(dst+8, src+8, dstStride, srcStride, C1, C2);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv30_tpel8_h_lowpass(dst , src , dstStride, srcStride, C1, C2);\ + OPNAME ## rv30_tpel8_h_lowpass(dst+8, src+8, dstStride, srcStride, C1, C2);\ +}\ +\ +static void OPNAME ## rv30_tpel16_hv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## rv30_tpel8_hv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hv_lowpass(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv30_tpel8_hv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hv_lowpass(dst+8, src+8, dstStride, srcStride);\ +}\ +\ +static void OPNAME ## rv30_tpel16_hhv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## rv30_tpel8_hhv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hhv_lowpass(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv30_tpel8_hhv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hhv_lowpass(dst+8, src+8, dstStride, srcStride);\ +}\ +\ +static void OPNAME ## rv30_tpel16_hvv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## rv30_tpel8_hvv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hvv_lowpass(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv30_tpel8_hvv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hvv_lowpass(dst+8, src+8, dstStride, srcStride);\ +}\ +\ +static void OPNAME ## rv30_tpel16_hhvv_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## rv30_tpel8_hhvv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hhvv_lowpass(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv30_tpel8_hhvv_lowpass(dst , src , dstStride, srcStride);\ + OPNAME ## rv30_tpel8_hhvv_lowpass(dst+8, src+8, dstStride, srcStride);\ +}\ +\ + +#define RV30_MC(OPNAME, SIZE) \ +static void OPNAME ## rv30_tpel ## SIZE ## _mc10_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _h_lowpass(dst, src, stride, stride, 12, 6);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc20_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _h_lowpass(dst, src, stride, stride, 6, 12);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc01_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _v_lowpass(dst, src, stride, stride, 12, 6);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc02_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _v_lowpass(dst, src, stride, stride, 6, 12);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc11_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _hv_lowpass(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc12_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _hvv_lowpass(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc21_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _hhv_lowpass(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## rv30_tpel ## SIZE ## _mc22_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv30_tpel ## SIZE ## _hhvv_lowpass(dst, src, stride, stride);\ +}\ +\ + +#define op_avg(a, b) a = (((a)+cm[b]+1)>>1) +#define op_put(a, b) a = cm[b] + +RV30_LOWPASS(put_ , op_put) +RV30_LOWPASS(avg_ , op_avg) +RV30_MC(put_, 8) +RV30_MC(put_, 16) +RV30_MC(avg_, 8) +RV30_MC(avg_, 16) + +av_cold void ff_rv30dsp_init(RV34DSPContext *c) +{ + H264ChromaContext h264chroma; + H264QpelContext qpel; + + ff_rv34dsp_init(c); + ff_h264chroma_init(&h264chroma, 8); + ff_h264qpel_init(&qpel, 8); + + c->put_pixels_tab[0][ 0] = qpel.put_h264_qpel_pixels_tab[0][0]; + c->put_pixels_tab[0][ 1] = put_rv30_tpel16_mc10_c; + c->put_pixels_tab[0][ 2] = put_rv30_tpel16_mc20_c; + c->put_pixels_tab[0][ 4] = put_rv30_tpel16_mc01_c; + c->put_pixels_tab[0][ 5] = put_rv30_tpel16_mc11_c; + c->put_pixels_tab[0][ 6] = put_rv30_tpel16_mc21_c; + c->put_pixels_tab[0][ 8] = put_rv30_tpel16_mc02_c; + c->put_pixels_tab[0][ 9] = put_rv30_tpel16_mc12_c; + c->put_pixels_tab[0][10] = put_rv30_tpel16_mc22_c; + c->avg_pixels_tab[0][ 0] = qpel.avg_h264_qpel_pixels_tab[0][0]; + c->avg_pixels_tab[0][ 1] = avg_rv30_tpel16_mc10_c; + c->avg_pixels_tab[0][ 2] = avg_rv30_tpel16_mc20_c; + c->avg_pixels_tab[0][ 4] = avg_rv30_tpel16_mc01_c; + c->avg_pixels_tab[0][ 5] = avg_rv30_tpel16_mc11_c; + c->avg_pixels_tab[0][ 6] = avg_rv30_tpel16_mc21_c; + c->avg_pixels_tab[0][ 8] = avg_rv30_tpel16_mc02_c; + c->avg_pixels_tab[0][ 9] = avg_rv30_tpel16_mc12_c; + c->avg_pixels_tab[0][10] = avg_rv30_tpel16_mc22_c; + c->put_pixels_tab[1][ 0] = qpel.put_h264_qpel_pixels_tab[1][0]; + c->put_pixels_tab[1][ 1] = put_rv30_tpel8_mc10_c; + c->put_pixels_tab[1][ 2] = put_rv30_tpel8_mc20_c; + c->put_pixels_tab[1][ 4] = put_rv30_tpel8_mc01_c; + c->put_pixels_tab[1][ 5] = put_rv30_tpel8_mc11_c; + c->put_pixels_tab[1][ 6] = put_rv30_tpel8_mc21_c; + c->put_pixels_tab[1][ 8] = put_rv30_tpel8_mc02_c; + c->put_pixels_tab[1][ 9] = put_rv30_tpel8_mc12_c; + c->put_pixels_tab[1][10] = put_rv30_tpel8_mc22_c; + c->avg_pixels_tab[1][ 0] = qpel.avg_h264_qpel_pixels_tab[1][0]; + c->avg_pixels_tab[1][ 1] = avg_rv30_tpel8_mc10_c; + c->avg_pixels_tab[1][ 2] = avg_rv30_tpel8_mc20_c; + c->avg_pixels_tab[1][ 4] = avg_rv30_tpel8_mc01_c; + c->avg_pixels_tab[1][ 5] = avg_rv30_tpel8_mc11_c; + c->avg_pixels_tab[1][ 6] = avg_rv30_tpel8_mc21_c; + c->avg_pixels_tab[1][ 8] = avg_rv30_tpel8_mc02_c; + c->avg_pixels_tab[1][ 9] = avg_rv30_tpel8_mc12_c; + c->avg_pixels_tab[1][10] = avg_rv30_tpel8_mc22_c; + + c->put_chroma_pixels_tab[0] = h264chroma.put_h264_chroma_pixels_tab[0]; + c->put_chroma_pixels_tab[1] = h264chroma.put_h264_chroma_pixels_tab[1]; + c->avg_chroma_pixels_tab[0] = h264chroma.avg_h264_chroma_pixels_tab[0]; + c->avg_chroma_pixels_tab[1] = h264chroma.avg_h264_chroma_pixels_tab[1]; +} diff --git a/ffmpeg/libavcodec/rv34.c b/ffmpeg/libavcodec/rv34.c new file mode 100644 index 0000000..35f9dea --- /dev/null +++ b/ffmpeg/libavcodec/rv34.c @@ -0,0 +1,1821 @@ +/* + * RV30/40 decoder common data + * Copyright (c) 2007 Mike Melanson, Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV30/40 decoder common data + */ + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" + +#include "avcodec.h" +#include "error_resilience.h" +#include "mpegvideo.h" +#include "golomb.h" +#include "internal.h" +#include "mathops.h" +#include "rectangle.h" +#include "thread.h" + +#include "rv34vlc.h" +#include "rv34data.h" +#include "rv34.h" + +//#define DEBUG + +static inline void ZERO8x2(void* dst, int stride) +{ + fill_rectangle(dst, 1, 2, stride, 0, 4); + fill_rectangle(((uint8_t*)(dst))+4, 1, 2, stride, 0, 4); +} + +/** translation of RV30/40 macroblock types to lavc ones */ +static const int rv34_mb_type_to_lavc[12] = { + MB_TYPE_INTRA, + MB_TYPE_INTRA16x16 | MB_TYPE_SEPARATE_DC, + MB_TYPE_16x16 | MB_TYPE_L0, + MB_TYPE_8x8 | MB_TYPE_L0, + MB_TYPE_16x16 | MB_TYPE_L0, + MB_TYPE_16x16 | MB_TYPE_L1, + MB_TYPE_SKIP, + MB_TYPE_DIRECT2 | MB_TYPE_16x16, + MB_TYPE_16x8 | MB_TYPE_L0, + MB_TYPE_8x16 | MB_TYPE_L0, + MB_TYPE_16x16 | MB_TYPE_L0L1, + MB_TYPE_16x16 | MB_TYPE_L0 | MB_TYPE_SEPARATE_DC +}; + + +static RV34VLC intra_vlcs[NUM_INTRA_TABLES], inter_vlcs[NUM_INTER_TABLES]; + +static int rv34_decode_mv(RV34DecContext *r, int block_type); + +/** + * @name RV30/40 VLC generating functions + * @{ + */ + +static const int table_offs[] = { + 0, 1818, 3622, 4144, 4698, 5234, 5804, 5868, 5900, 5932, + 5996, 6252, 6316, 6348, 6380, 7674, 8944, 10274, 11668, 12250, + 14060, 15846, 16372, 16962, 17512, 18148, 18180, 18212, 18244, 18308, + 18564, 18628, 18660, 18692, 20036, 21314, 22648, 23968, 24614, 26384, + 28190, 28736, 29366, 29938, 30608, 30640, 30672, 30704, 30768, 31024, + 31088, 31120, 31184, 32570, 33898, 35236, 36644, 37286, 39020, 40802, + 41368, 42052, 42692, 43348, 43380, 43412, 43444, 43476, 43604, 43668, + 43700, 43732, 45100, 46430, 47778, 49160, 49802, 51550, 53340, 53972, + 54648, 55348, 55994, 56122, 56154, 56186, 56218, 56346, 56410, 56442, + 56474, 57878, 59290, 60636, 62036, 62682, 64460, 64524, 64588, 64716, + 64844, 66076, 67466, 67978, 68542, 69064, 69648, 70296, 72010, 72074, + 72138, 72202, 72330, 73572, 74936, 75454, 76030, 76566, 77176, 77822, + 79582, 79646, 79678, 79742, 79870, 81180, 82536, 83064, 83672, 84242, + 84934, 85576, 87384, 87448, 87480, 87544, 87672, 88982, 90340, 90902, + 91598, 92182, 92846, 93488, 95246, 95278, 95310, 95374, 95502, 96878, + 98266, 98848, 99542, 100234, 100884, 101524, 103320, 103352, 103384, 103416, + 103480, 104874, 106222, 106910, 107584, 108258, 108902, 109544, 111366, 111398, + 111430, 111462, 111494, 112878, 114320, 114988, 115660, 116310, 116950, 117592 +}; + +static VLC_TYPE table_data[117592][2]; + +/** + * Generate VLC from codeword lengths. + * @param bits codeword lengths (zeroes are accepted) + * @param size length of input data + * @param vlc output VLC + * @param insyms symbols for input codes (NULL for default ones) + * @param num VLC table number (for static initialization) + */ +static void rv34_gen_vlc(const uint8_t *bits, int size, VLC *vlc, const uint8_t *insyms, + const int num) +{ + int i; + int counts[17] = {0}, codes[17]; + uint16_t cw[MAX_VLC_SIZE], syms[MAX_VLC_SIZE]; + uint8_t bits2[MAX_VLC_SIZE]; + int maxbits = 0, realsize = 0; + + for(i = 0; i < size; i++){ + if(bits[i]){ + bits2[realsize] = bits[i]; + syms[realsize] = insyms ? insyms[i] : i; + realsize++; + maxbits = FFMAX(maxbits, bits[i]); + counts[bits[i]]++; + } + } + + codes[0] = 0; + for(i = 0; i < 16; i++) + codes[i+1] = (codes[i] + counts[i]) << 1; + for(i = 0; i < realsize; i++) + cw[i] = codes[bits2[i]]++; + + vlc->table = &table_data[table_offs[num]]; + vlc->table_allocated = table_offs[num + 1] - table_offs[num]; + ff_init_vlc_sparse(vlc, FFMIN(maxbits, 9), realsize, + bits2, 1, 1, + cw, 2, 2, + syms, 2, 2, INIT_VLC_USE_NEW_STATIC); +} + +/** + * Initialize all tables. + */ +static av_cold void rv34_init_tables(void) +{ + int i, j, k; + + for(i = 0; i < NUM_INTRA_TABLES; i++){ + for(j = 0; j < 2; j++){ + rv34_gen_vlc(rv34_table_intra_cbppat [i][j], CBPPAT_VLC_SIZE, &intra_vlcs[i].cbppattern[j], NULL, 19*i + 0 + j); + rv34_gen_vlc(rv34_table_intra_secondpat[i][j], OTHERBLK_VLC_SIZE, &intra_vlcs[i].second_pattern[j], NULL, 19*i + 2 + j); + rv34_gen_vlc(rv34_table_intra_thirdpat [i][j], OTHERBLK_VLC_SIZE, &intra_vlcs[i].third_pattern[j], NULL, 19*i + 4 + j); + for(k = 0; k < 4; k++){ + rv34_gen_vlc(rv34_table_intra_cbp[i][j+k*2], CBP_VLC_SIZE, &intra_vlcs[i].cbp[j][k], rv34_cbp_code, 19*i + 6 + j*4 + k); + } + } + for(j = 0; j < 4; j++){ + rv34_gen_vlc(rv34_table_intra_firstpat[i][j], FIRSTBLK_VLC_SIZE, &intra_vlcs[i].first_pattern[j], NULL, 19*i + 14 + j); + } + rv34_gen_vlc(rv34_intra_coeff[i], COEFF_VLC_SIZE, &intra_vlcs[i].coefficient, NULL, 19*i + 18); + } + + for(i = 0; i < NUM_INTER_TABLES; i++){ + rv34_gen_vlc(rv34_inter_cbppat[i], CBPPAT_VLC_SIZE, &inter_vlcs[i].cbppattern[0], NULL, i*12 + 95); + for(j = 0; j < 4; j++){ + rv34_gen_vlc(rv34_inter_cbp[i][j], CBP_VLC_SIZE, &inter_vlcs[i].cbp[0][j], rv34_cbp_code, i*12 + 96 + j); + } + for(j = 0; j < 2; j++){ + rv34_gen_vlc(rv34_table_inter_firstpat [i][j], FIRSTBLK_VLC_SIZE, &inter_vlcs[i].first_pattern[j], NULL, i*12 + 100 + j); + rv34_gen_vlc(rv34_table_inter_secondpat[i][j], OTHERBLK_VLC_SIZE, &inter_vlcs[i].second_pattern[j], NULL, i*12 + 102 + j); + rv34_gen_vlc(rv34_table_inter_thirdpat [i][j], OTHERBLK_VLC_SIZE, &inter_vlcs[i].third_pattern[j], NULL, i*12 + 104 + j); + } + rv34_gen_vlc(rv34_inter_coeff[i], COEFF_VLC_SIZE, &inter_vlcs[i].coefficient, NULL, i*12 + 106); + } +} + +/** @} */ // vlc group + +/** + * @name RV30/40 4x4 block decoding functions + * @{ + */ + +/** + * Decode coded block pattern. + */ +static int rv34_decode_cbp(GetBitContext *gb, RV34VLC *vlc, int table) +{ + int pattern, code, cbp=0; + int ones; + static const int cbp_masks[3] = {0x100000, 0x010000, 0x110000}; + static const int shifts[4] = { 0, 2, 8, 10 }; + const int *curshift = shifts; + int i, t, mask; + + code = get_vlc2(gb, vlc->cbppattern[table].table, 9, 2); + pattern = code & 0xF; + code >>= 4; + + ones = rv34_count_ones[pattern]; + + for(mask = 8; mask; mask >>= 1, curshift++){ + if(pattern & mask) + cbp |= get_vlc2(gb, vlc->cbp[table][ones].table, vlc->cbp[table][ones].bits, 1) << curshift[0]; + } + + for(i = 0; i < 4; i++){ + t = (modulo_three_table[code] >> (6 - 2*i)) & 3; + if(t == 1) + cbp |= cbp_masks[get_bits1(gb)] << i; + if(t == 2) + cbp |= cbp_masks[2] << i; + } + return cbp; +} + +/** + * Get one coefficient value from the bitstream and store it. + */ +static inline void decode_coeff(int16_t *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q) +{ + if(coef){ + if(coef == esc){ + coef = get_vlc2(gb, vlc->table, 9, 2); + if(coef > 23){ + coef -= 23; + coef = 22 + ((1 << coef) | get_bits(gb, coef)); + } + coef += esc; + } + if(get_bits1(gb)) + coef = -coef; + *dst = (coef*q + 8) >> 4; + } +} + +/** + * Decode 2x2 subblock of coefficients. + */ +static inline void decode_subblock(int16_t *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc, int q) +{ + int flags = modulo_three_table[code]; + + decode_coeff( dst+0*4+0, (flags >> 6) , 3, gb, vlc, q); + if(is_block2){ + decode_coeff(dst+1*4+0, (flags >> 4) & 3, 2, gb, vlc, q); + decode_coeff(dst+0*4+1, (flags >> 2) & 3, 2, gb, vlc, q); + }else{ + decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q); + decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q); + } + decode_coeff( dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q); +} + +/** + * Decode a single coefficient. + */ +static inline void decode_subblock1(int16_t *dst, int code, GetBitContext *gb, VLC *vlc, int q) +{ + int coeff = modulo_three_table[code] >> 6; + decode_coeff(dst, coeff, 3, gb, vlc, q); +} + +static inline void decode_subblock3(int16_t *dst, int code, GetBitContext *gb, VLC *vlc, + int q_dc, int q_ac1, int q_ac2) +{ + int flags = modulo_three_table[code]; + + decode_coeff(dst+0*4+0, (flags >> 6) , 3, gb, vlc, q_dc); + decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q_ac1); + decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q_ac1); + decode_coeff(dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q_ac2); +} + +/** + * Decode coefficients for 4x4 block. + * + * This is done by filling 2x2 subblocks with decoded coefficients + * in this order (the same for subblocks and subblock coefficients): + * o--o + * / + * / + * o--o + */ + +static int rv34_decode_block(int16_t *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc, int q_dc, int q_ac1, int q_ac2) +{ + int code, pattern, has_ac = 1; + + code = get_vlc2(gb, rvlc->first_pattern[fc].table, 9, 2); + + pattern = code & 0x7; + + code >>= 3; + + if (modulo_three_table[code] & 0x3F) { + decode_subblock3(dst, code, gb, &rvlc->coefficient, q_dc, q_ac1, q_ac2); + } else { + decode_subblock1(dst, code, gb, &rvlc->coefficient, q_dc); + if (!pattern) + return 0; + has_ac = 0; + } + + if(pattern & 4){ + code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); + decode_subblock(dst + 4*0+2, code, 0, gb, &rvlc->coefficient, q_ac2); + } + if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block + code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); + decode_subblock(dst + 4*2+0, code, 1, gb, &rvlc->coefficient, q_ac2); + } + if(pattern & 1){ + code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2); + decode_subblock(dst + 4*2+2, code, 0, gb, &rvlc->coefficient, q_ac2); + } + return has_ac | pattern; +} + +/** + * @name RV30/40 bitstream parsing + * @{ + */ + +/** + * Decode starting slice position. + * @todo Maybe replace with ff_h263_decode_mba() ? + */ +int ff_rv34_get_start_offset(GetBitContext *gb, int mb_size) +{ + int i; + for(i = 0; i < 5; i++) + if(rv34_mb_max_sizes[i] >= mb_size - 1) + break; + return rv34_mb_bits_sizes[i]; +} + +/** + * Select VLC set for decoding from current quantizer, modifier and frame type. + */ +static inline RV34VLC* choose_vlc_set(int quant, int mod, int type) +{ + if(mod == 2 && quant < 19) quant += 10; + else if(mod && quant < 26) quant += 5; + return type ? &inter_vlcs[rv34_quant_to_vlc_set[1][av_clip(quant, 0, 30)]] + : &intra_vlcs[rv34_quant_to_vlc_set[0][av_clip(quant, 0, 30)]]; +} + +/** + * Decode intra macroblock header and return CBP in case of success, -1 otherwise. + */ +static int rv34_decode_intra_mb_header(RV34DecContext *r, int8_t *intra_types) +{ + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int t; + + r->is16 = get_bits1(gb); + if(r->is16){ + s->current_picture_ptr->mb_type[mb_pos] = MB_TYPE_INTRA16x16; + r->block_type = RV34_MB_TYPE_INTRA16x16; + t = get_bits(gb, 2); + fill_rectangle(intra_types, 4, 4, r->intra_types_stride, t, sizeof(intra_types[0])); + r->luma_vlc = 2; + }else{ + if(!r->rv30){ + if(!get_bits1(gb)) + av_log(s->avctx, AV_LOG_ERROR, "Need DQUANT\n"); + } + s->current_picture_ptr->mb_type[mb_pos] = MB_TYPE_INTRA; + r->block_type = RV34_MB_TYPE_INTRA; + if(r->decode_intra_types(r, gb, intra_types) < 0) + return -1; + r->luma_vlc = 1; + } + + r->chroma_vlc = 0; + r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0); + + return rv34_decode_cbp(gb, r->cur_vlcs, r->is16); +} + +/** + * Decode inter macroblock header and return CBP in case of success, -1 otherwise. + */ +static int rv34_decode_inter_mb_header(RV34DecContext *r, int8_t *intra_types) +{ + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int i, t; + + r->block_type = r->decode_mb_info(r); + if(r->block_type == -1) + return -1; + s->current_picture_ptr->mb_type[mb_pos] = rv34_mb_type_to_lavc[r->block_type]; + r->mb_type[mb_pos] = r->block_type; + if(r->block_type == RV34_MB_SKIP){ + if(s->pict_type == AV_PICTURE_TYPE_P) + r->mb_type[mb_pos] = RV34_MB_P_16x16; + if(s->pict_type == AV_PICTURE_TYPE_B) + r->mb_type[mb_pos] = RV34_MB_B_DIRECT; + } + r->is16 = !!IS_INTRA16x16(s->current_picture_ptr->mb_type[mb_pos]); + rv34_decode_mv(r, r->block_type); + if(r->block_type == RV34_MB_SKIP){ + fill_rectangle(intra_types, 4, 4, r->intra_types_stride, 0, sizeof(intra_types[0])); + return 0; + } + r->chroma_vlc = 1; + r->luma_vlc = 0; + + if(IS_INTRA(s->current_picture_ptr->mb_type[mb_pos])){ + if(r->is16){ + t = get_bits(gb, 2); + fill_rectangle(intra_types, 4, 4, r->intra_types_stride, t, sizeof(intra_types[0])); + r->luma_vlc = 2; + }else{ + if(r->decode_intra_types(r, gb, intra_types) < 0) + return -1; + r->luma_vlc = 1; + } + r->chroma_vlc = 0; + r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0); + }else{ + for(i = 0; i < 16; i++) + intra_types[(i & 3) + (i>>2) * r->intra_types_stride] = 0; + r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); + if(r->mb_type[mb_pos] == RV34_MB_P_MIX16x16){ + r->is16 = 1; + r->chroma_vlc = 1; + r->luma_vlc = 2; + r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0); + } + } + + return rv34_decode_cbp(gb, r->cur_vlcs, r->is16); +} + +/** @} */ //bitstream functions + +/** + * @name motion vector related code (prediction, reconstruction, motion compensation) + * @{ + */ + +/** macroblock partition width in 8x8 blocks */ +static const uint8_t part_sizes_w[RV34_MB_TYPES] = { 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2 }; + +/** macroblock partition height in 8x8 blocks */ +static const uint8_t part_sizes_h[RV34_MB_TYPES] = { 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2 }; + +/** availability index for subblocks */ +static const uint8_t avail_indexes[4] = { 6, 7, 10, 11 }; + +/** + * motion vector prediction + * + * Motion prediction performed for the block by using median prediction of + * motion vectors from the left, top and right top blocks but in corner cases + * some other vectors may be used instead. + */ +static void rv34_pred_mv(RV34DecContext *r, int block_type, int subblock_no, int dmv_no) +{ + MpegEncContext *s = &r->s; + int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; + int A[2] = {0}, B[2], C[2]; + int i, j; + int mx, my; + int* avail = r->avail_cache + avail_indexes[subblock_no]; + int c_off = part_sizes_w[block_type]; + + mv_pos += (subblock_no & 1) + (subblock_no >> 1)*s->b8_stride; + if(subblock_no == 3) + c_off = -1; + + if(avail[-1]){ + A[0] = s->current_picture_ptr->motion_val[0][mv_pos-1][0]; + A[1] = s->current_picture_ptr->motion_val[0][mv_pos-1][1]; + } + if(avail[-4]){ + B[0] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride][0]; + B[1] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride][1]; + }else{ + B[0] = A[0]; + B[1] = A[1]; + } + if(!avail[c_off-4]){ + if(avail[-4] && (avail[-1] || r->rv30)){ + C[0] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride-1][0]; + C[1] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride-1][1]; + }else{ + C[0] = A[0]; + C[1] = A[1]; + } + }else{ + C[0] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride+c_off][0]; + C[1] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride+c_off][1]; + } + mx = mid_pred(A[0], B[0], C[0]); + my = mid_pred(A[1], B[1], C[1]); + mx += r->dmv[dmv_no][0]; + my += r->dmv[dmv_no][1]; + for(j = 0; j < part_sizes_h[block_type]; j++){ + for(i = 0; i < part_sizes_w[block_type]; i++){ + s->current_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][0] = mx; + s->current_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][1] = my; + } + } +} + +#define GET_PTS_DIFF(a, b) ((a - b + 8192) & 0x1FFF) + +/** + * Calculate motion vector component that should be added for direct blocks. + */ +static int calc_add_mv(RV34DecContext *r, int dir, int val) +{ + int mul = dir ? -r->mv_weight2 : r->mv_weight1; + + return (val * mul + 0x2000) >> 14; +} + +/** + * Predict motion vector for B-frame macroblock. + */ +static inline void rv34_pred_b_vector(int A[2], int B[2], int C[2], + int A_avail, int B_avail, int C_avail, + int *mx, int *my) +{ + if(A_avail + B_avail + C_avail != 3){ + *mx = A[0] + B[0] + C[0]; + *my = A[1] + B[1] + C[1]; + if(A_avail + B_avail + C_avail == 2){ + *mx /= 2; + *my /= 2; + } + }else{ + *mx = mid_pred(A[0], B[0], C[0]); + *my = mid_pred(A[1], B[1], C[1]); + } +} + +/** + * motion vector prediction for B-frames + */ +static void rv34_pred_mv_b(RV34DecContext *r, int block_type, int dir) +{ + MpegEncContext *s = &r->s; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; + int A[2] = { 0 }, B[2] = { 0 }, C[2] = { 0 }; + int has_A = 0, has_B = 0, has_C = 0; + int mx, my; + int i, j; + Picture *cur_pic = s->current_picture_ptr; + const int mask = dir ? MB_TYPE_L1 : MB_TYPE_L0; + int type = cur_pic->mb_type[mb_pos]; + + if((r->avail_cache[6-1] & type) & mask){ + A[0] = cur_pic->motion_val[dir][mv_pos - 1][0]; + A[1] = cur_pic->motion_val[dir][mv_pos - 1][1]; + has_A = 1; + } + if((r->avail_cache[6-4] & type) & mask){ + B[0] = cur_pic->motion_val[dir][mv_pos - s->b8_stride][0]; + B[1] = cur_pic->motion_val[dir][mv_pos - s->b8_stride][1]; + has_B = 1; + } + if(r->avail_cache[6-4] && (r->avail_cache[6-2] & type) & mask){ + C[0] = cur_pic->motion_val[dir][mv_pos - s->b8_stride + 2][0]; + C[1] = cur_pic->motion_val[dir][mv_pos - s->b8_stride + 2][1]; + has_C = 1; + }else if((s->mb_x+1) == s->mb_width && (r->avail_cache[6-5] & type) & mask){ + C[0] = cur_pic->motion_val[dir][mv_pos - s->b8_stride - 1][0]; + C[1] = cur_pic->motion_val[dir][mv_pos - s->b8_stride - 1][1]; + has_C = 1; + } + + rv34_pred_b_vector(A, B, C, has_A, has_B, has_C, &mx, &my); + + mx += r->dmv[dir][0]; + my += r->dmv[dir][1]; + + for(j = 0; j < 2; j++){ + for(i = 0; i < 2; i++){ + cur_pic->motion_val[dir][mv_pos + i + j*s->b8_stride][0] = mx; + cur_pic->motion_val[dir][mv_pos + i + j*s->b8_stride][1] = my; + } + } + if(block_type == RV34_MB_B_BACKWARD || block_type == RV34_MB_B_FORWARD){ + ZERO8x2(cur_pic->motion_val[!dir][mv_pos], s->b8_stride); + } +} + +/** + * motion vector prediction - RV3 version + */ +static void rv34_pred_mv_rv3(RV34DecContext *r, int block_type, int dir) +{ + MpegEncContext *s = &r->s; + int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; + int A[2] = {0}, B[2], C[2]; + int i, j, k; + int mx, my; + int* avail = r->avail_cache + avail_indexes[0]; + + if(avail[-1]){ + A[0] = s->current_picture_ptr->motion_val[0][mv_pos - 1][0]; + A[1] = s->current_picture_ptr->motion_val[0][mv_pos - 1][1]; + } + if(avail[-4]){ + B[0] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride][0]; + B[1] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride][1]; + }else{ + B[0] = A[0]; + B[1] = A[1]; + } + if(!avail[-4 + 2]){ + if(avail[-4] && (avail[-1])){ + C[0] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride - 1][0]; + C[1] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride - 1][1]; + }else{ + C[0] = A[0]; + C[1] = A[1]; + } + }else{ + C[0] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride + 2][0]; + C[1] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride + 2][1]; + } + mx = mid_pred(A[0], B[0], C[0]); + my = mid_pred(A[1], B[1], C[1]); + mx += r->dmv[0][0]; + my += r->dmv[0][1]; + for(j = 0; j < 2; j++){ + for(i = 0; i < 2; i++){ + for(k = 0; k < 2; k++){ + s->current_picture_ptr->motion_val[k][mv_pos + i + j*s->b8_stride][0] = mx; + s->current_picture_ptr->motion_val[k][mv_pos + i + j*s->b8_stride][1] = my; + } + } + } +} + +static const int chroma_coeffs[3] = { 0, 3, 5 }; + +/** + * generic motion compensation function + * + * @param r decoder context + * @param block_type type of the current block + * @param xoff horizontal offset from the start of the current block + * @param yoff vertical offset from the start of the current block + * @param mv_off offset to the motion vector information + * @param width width of the current partition in 8x8 blocks + * @param height height of the current partition in 8x8 blocks + * @param dir motion compensation direction (i.e. from the last or the next reference frame) + * @param thirdpel motion vectors are specified in 1/3 of pixel + * @param qpel_mc a set of functions used to perform luma motion compensation + * @param chroma_mc a set of functions used to perform chroma motion compensation + */ +static inline void rv34_mc(RV34DecContext *r, const int block_type, + const int xoff, const int yoff, int mv_off, + const int width, const int height, int dir, + const int thirdpel, int weighted, + qpel_mc_func (*qpel_mc)[16], + h264_chroma_mc_func (*chroma_mc)) +{ + MpegEncContext *s = &r->s; + uint8_t *Y, *U, *V, *srcY, *srcU, *srcV; + int dxy, mx, my, umx, umy, lx, ly, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; + int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride + mv_off; + int is16x16 = 1; + + if(thirdpel){ + int chroma_mx, chroma_my; + mx = (s->current_picture_ptr->motion_val[dir][mv_pos][0] + (3 << 24)) / 3 - (1 << 24); + my = (s->current_picture_ptr->motion_val[dir][mv_pos][1] + (3 << 24)) / 3 - (1 << 24); + lx = (s->current_picture_ptr->motion_val[dir][mv_pos][0] + (3 << 24)) % 3; + ly = (s->current_picture_ptr->motion_val[dir][mv_pos][1] + (3 << 24)) % 3; + chroma_mx = s->current_picture_ptr->motion_val[dir][mv_pos][0] / 2; + chroma_my = s->current_picture_ptr->motion_val[dir][mv_pos][1] / 2; + umx = (chroma_mx + (3 << 24)) / 3 - (1 << 24); + umy = (chroma_my + (3 << 24)) / 3 - (1 << 24); + uvmx = chroma_coeffs[(chroma_mx + (3 << 24)) % 3]; + uvmy = chroma_coeffs[(chroma_my + (3 << 24)) % 3]; + }else{ + int cx, cy; + mx = s->current_picture_ptr->motion_val[dir][mv_pos][0] >> 2; + my = s->current_picture_ptr->motion_val[dir][mv_pos][1] >> 2; + lx = s->current_picture_ptr->motion_val[dir][mv_pos][0] & 3; + ly = s->current_picture_ptr->motion_val[dir][mv_pos][1] & 3; + cx = s->current_picture_ptr->motion_val[dir][mv_pos][0] / 2; + cy = s->current_picture_ptr->motion_val[dir][mv_pos][1] / 2; + umx = cx >> 2; + umy = cy >> 2; + uvmx = (cx & 3) << 1; + uvmy = (cy & 3) << 1; + //due to some flaw RV40 uses the same MC compensation routine for H2V2 and H3V3 + if(uvmx == 6 && uvmy == 6) + uvmx = uvmy = 4; + } + + if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) { + /* wait for the referenced mb row to be finished */ + int mb_row = s->mb_y + ((yoff + my + 5 + 8 * height) >> 4); + ThreadFrame *f = dir ? &s->next_picture_ptr->tf : &s->last_picture_ptr->tf; + ff_thread_await_progress(f, mb_row, 0); + } + + dxy = ly*4 + lx; + srcY = dir ? s->next_picture_ptr->f.data[0] : s->last_picture_ptr->f.data[0]; + srcU = dir ? s->next_picture_ptr->f.data[1] : s->last_picture_ptr->f.data[1]; + srcV = dir ? s->next_picture_ptr->f.data[2] : s->last_picture_ptr->f.data[2]; + src_x = s->mb_x * 16 + xoff + mx; + src_y = s->mb_y * 16 + yoff + my; + uvsrc_x = s->mb_x * 8 + (xoff >> 1) + umx; + uvsrc_y = s->mb_y * 8 + (yoff >> 1) + umy; + srcY += src_y * s->linesize + src_x; + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + if(s->h_edge_pos - (width << 3) < 6 || s->v_edge_pos - (height << 3) < 6 || + (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 || + (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4) { + uint8_t *uvbuf = s->edge_emu_buffer + 22 * s->linesize; + + srcY -= 2 + 2*s->linesize; + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize, (width<<3)+6, (height<<3)+6, + src_x - 2, src_y - 2, s->h_edge_pos, s->v_edge_pos); + srcY = s->edge_emu_buffer + 2 + 2*s->linesize; + s->vdsp.emulated_edge_mc(uvbuf , srcU, s->uvlinesize, (width<<2)+1, (height<<2)+1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, s->uvlinesize, (width<<2)+1, (height<<2)+1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, s->v_edge_pos >> 1); + srcU = uvbuf; + srcV = uvbuf + 16; + } + if(!weighted){ + Y = s->dest[0] + xoff + yoff *s->linesize; + U = s->dest[1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + V = s->dest[2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + }else{ + Y = r->tmp_b_block_y [dir] + xoff + yoff *s->linesize; + U = r->tmp_b_block_uv[dir*2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + V = r->tmp_b_block_uv[dir*2+1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + } + + if(block_type == RV34_MB_P_16x8){ + qpel_mc[1][dxy](Y, srcY, s->linesize); + Y += 8; + srcY += 8; + }else if(block_type == RV34_MB_P_8x16){ + qpel_mc[1][dxy](Y, srcY, s->linesize); + Y += 8 * s->linesize; + srcY += 8 * s->linesize; + } + is16x16 = (block_type != RV34_MB_P_8x8) && (block_type != RV34_MB_P_16x8) && (block_type != RV34_MB_P_8x16); + qpel_mc[!is16x16][dxy](Y, srcY, s->linesize); + chroma_mc[2-width] (U, srcU, s->uvlinesize, height*4, uvmx, uvmy); + chroma_mc[2-width] (V, srcV, s->uvlinesize, height*4, uvmx, uvmy); +} + +static void rv34_mc_1mv(RV34DecContext *r, const int block_type, + const int xoff, const int yoff, int mv_off, + const int width, const int height, int dir) +{ + rv34_mc(r, block_type, xoff, yoff, mv_off, width, height, dir, r->rv30, 0, + r->rdsp.put_pixels_tab, + r->rdsp.put_chroma_pixels_tab); +} + +static void rv4_weight(RV34DecContext *r) +{ + r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][0](r->s.dest[0], + r->tmp_b_block_y[0], + r->tmp_b_block_y[1], + r->weight1, + r->weight2, + r->s.linesize); + r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][1](r->s.dest[1], + r->tmp_b_block_uv[0], + r->tmp_b_block_uv[2], + r->weight1, + r->weight2, + r->s.uvlinesize); + r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][1](r->s.dest[2], + r->tmp_b_block_uv[1], + r->tmp_b_block_uv[3], + r->weight1, + r->weight2, + r->s.uvlinesize); +} + +static void rv34_mc_2mv(RV34DecContext *r, const int block_type) +{ + int weighted = !r->rv30 && block_type != RV34_MB_B_BIDIR && r->weight1 != 8192; + + rv34_mc(r, block_type, 0, 0, 0, 2, 2, 0, r->rv30, weighted, + r->rdsp.put_pixels_tab, + r->rdsp.put_chroma_pixels_tab); + if(!weighted){ + rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, 0, + r->rdsp.avg_pixels_tab, + r->rdsp.avg_chroma_pixels_tab); + }else{ + rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, 1, + r->rdsp.put_pixels_tab, + r->rdsp.put_chroma_pixels_tab); + rv4_weight(r); + } +} + +static void rv34_mc_2mv_skip(RV34DecContext *r) +{ + int i, j; + int weighted = !r->rv30 && r->weight1 != 8192; + + for(j = 0; j < 2; j++) + for(i = 0; i < 2; i++){ + rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 0, r->rv30, + weighted, + r->rdsp.put_pixels_tab, + r->rdsp.put_chroma_pixels_tab); + rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 1, r->rv30, + weighted, + weighted ? r->rdsp.put_pixels_tab : r->rdsp.avg_pixels_tab, + weighted ? r->rdsp.put_chroma_pixels_tab : r->rdsp.avg_chroma_pixels_tab); + } + if(weighted) + rv4_weight(r); +} + +/** number of motion vectors in each macroblock type */ +static const int num_mvs[RV34_MB_TYPES] = { 0, 0, 1, 4, 1, 1, 0, 0, 2, 2, 2, 1 }; + +/** + * Decode motion vector differences + * and perform motion vector reconstruction and motion compensation. + */ +static int rv34_decode_mv(RV34DecContext *r, int block_type) +{ + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + int i, j, k, l; + int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; + int next_bt; + + memset(r->dmv, 0, sizeof(r->dmv)); + for(i = 0; i < num_mvs[block_type]; i++){ + r->dmv[i][0] = svq3_get_se_golomb(gb); + r->dmv[i][1] = svq3_get_se_golomb(gb); + } + switch(block_type){ + case RV34_MB_TYPE_INTRA: + case RV34_MB_TYPE_INTRA16x16: + ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); + return 0; + case RV34_MB_SKIP: + if(s->pict_type == AV_PICTURE_TYPE_P){ + ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); + rv34_mc_1mv (r, block_type, 0, 0, 0, 2, 2, 0); + break; + } + case RV34_MB_B_DIRECT: + //surprisingly, it uses motion scheme from next reference frame + /* wait for the current mb row to be finished */ + if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) + ff_thread_await_progress(&s->next_picture_ptr->tf, FFMAX(0, s->mb_y-1), 0); + + next_bt = s->next_picture_ptr->mb_type[s->mb_x + s->mb_y * s->mb_stride]; + if(IS_INTRA(next_bt) || IS_SKIP(next_bt)){ + ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); + ZERO8x2(s->current_picture_ptr->motion_val[1][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); + }else + for(j = 0; j < 2; j++) + for(i = 0; i < 2; i++) + for(k = 0; k < 2; k++) + for(l = 0; l < 2; l++) + s->current_picture_ptr->motion_val[l][mv_pos + i + j*s->b8_stride][k] = calc_add_mv(r, l, s->next_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][k]); + if(!(IS_16X8(next_bt) || IS_8X16(next_bt) || IS_8X8(next_bt))) //we can use whole macroblock MC + rv34_mc_2mv(r, block_type); + else + rv34_mc_2mv_skip(r); + ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); + break; + case RV34_MB_P_16x16: + case RV34_MB_P_MIX16x16: + rv34_pred_mv(r, block_type, 0, 0); + rv34_mc_1mv (r, block_type, 0, 0, 0, 2, 2, 0); + break; + case RV34_MB_B_FORWARD: + case RV34_MB_B_BACKWARD: + r->dmv[1][0] = r->dmv[0][0]; + r->dmv[1][1] = r->dmv[0][1]; + if(r->rv30) + rv34_pred_mv_rv3(r, block_type, block_type == RV34_MB_B_BACKWARD); + else + rv34_pred_mv_b (r, block_type, block_type == RV34_MB_B_BACKWARD); + rv34_mc_1mv (r, block_type, 0, 0, 0, 2, 2, block_type == RV34_MB_B_BACKWARD); + break; + case RV34_MB_P_16x8: + case RV34_MB_P_8x16: + rv34_pred_mv(r, block_type, 0, 0); + rv34_pred_mv(r, block_type, 1 + (block_type == RV34_MB_P_16x8), 1); + if(block_type == RV34_MB_P_16x8){ + rv34_mc_1mv(r, block_type, 0, 0, 0, 2, 1, 0); + rv34_mc_1mv(r, block_type, 0, 8, s->b8_stride, 2, 1, 0); + } + if(block_type == RV34_MB_P_8x16){ + rv34_mc_1mv(r, block_type, 0, 0, 0, 1, 2, 0); + rv34_mc_1mv(r, block_type, 8, 0, 1, 1, 2, 0); + } + break; + case RV34_MB_B_BIDIR: + rv34_pred_mv_b (r, block_type, 0); + rv34_pred_mv_b (r, block_type, 1); + rv34_mc_2mv (r, block_type); + break; + case RV34_MB_P_8x8: + for(i=0;i< 4;i++){ + rv34_pred_mv(r, block_type, i, i); + rv34_mc_1mv (r, block_type, (i&1)<<3, (i&2)<<2, (i&1)+(i>>1)*s->b8_stride, 1, 1, 0); + } + break; + } + + return 0; +} +/** @} */ // mv group + +/** + * @name Macroblock reconstruction functions + * @{ + */ +/** mapping of RV30/40 intra prediction types to standard H.264 types */ +static const int ittrans[9] = { + DC_PRED, VERT_PRED, HOR_PRED, DIAG_DOWN_RIGHT_PRED, DIAG_DOWN_LEFT_PRED, + VERT_RIGHT_PRED, VERT_LEFT_PRED, HOR_UP_PRED, HOR_DOWN_PRED, +}; + +/** mapping of RV30/40 intra 16x16 prediction types to standard H.264 types */ +static const int ittrans16[4] = { + DC_PRED8x8, VERT_PRED8x8, HOR_PRED8x8, PLANE_PRED8x8, +}; + +/** + * Perform 4x4 intra prediction. + */ +static void rv34_pred_4x4_block(RV34DecContext *r, uint8_t *dst, int stride, int itype, int up, int left, int down, int right) +{ + uint8_t *prev = dst - stride + 4; + uint32_t topleft; + + if(!up && !left) + itype = DC_128_PRED; + else if(!up){ + if(itype == VERT_PRED) itype = HOR_PRED; + if(itype == DC_PRED) itype = LEFT_DC_PRED; + }else if(!left){ + if(itype == HOR_PRED) itype = VERT_PRED; + if(itype == DC_PRED) itype = TOP_DC_PRED; + if(itype == DIAG_DOWN_LEFT_PRED) itype = DIAG_DOWN_LEFT_PRED_RV40_NODOWN; + } + if(!down){ + if(itype == DIAG_DOWN_LEFT_PRED) itype = DIAG_DOWN_LEFT_PRED_RV40_NODOWN; + if(itype == HOR_UP_PRED) itype = HOR_UP_PRED_RV40_NODOWN; + if(itype == VERT_LEFT_PRED) itype = VERT_LEFT_PRED_RV40_NODOWN; + } + if(!right && up){ + topleft = dst[-stride + 3] * 0x01010101u; + prev = (uint8_t*)&topleft; + } + r->h.pred4x4[itype](dst, prev, stride); +} + +static inline int adjust_pred16(int itype, int up, int left) +{ + if(!up && !left) + itype = DC_128_PRED8x8; + else if(!up){ + if(itype == PLANE_PRED8x8)itype = HOR_PRED8x8; + if(itype == VERT_PRED8x8) itype = HOR_PRED8x8; + if(itype == DC_PRED8x8) itype = LEFT_DC_PRED8x8; + }else if(!left){ + if(itype == PLANE_PRED8x8)itype = VERT_PRED8x8; + if(itype == HOR_PRED8x8) itype = VERT_PRED8x8; + if(itype == DC_PRED8x8) itype = TOP_DC_PRED8x8; + } + return itype; +} + +static inline void rv34_process_block(RV34DecContext *r, + uint8_t *pdst, int stride, + int fc, int sc, int q_dc, int q_ac) +{ + MpegEncContext *s = &r->s; + int16_t *ptr = s->block[0]; + int has_ac = rv34_decode_block(ptr, &s->gb, r->cur_vlcs, + fc, sc, q_dc, q_ac, q_ac); + if(has_ac){ + r->rdsp.rv34_idct_add(pdst, stride, ptr); + }else{ + r->rdsp.rv34_idct_dc_add(pdst, stride, ptr[0]); + ptr[0] = 0; + } +} + +static void rv34_output_i16x16(RV34DecContext *r, int8_t *intra_types, int cbp) +{ + LOCAL_ALIGNED_16(int16_t, block16, [16]); + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + int q_dc = rv34_qscale_tab[ r->luma_dc_quant_i[s->qscale] ], + q_ac = rv34_qscale_tab[s->qscale]; + uint8_t *dst = s->dest[0]; + int16_t *ptr = s->block[0]; + int i, j, itype, has_ac; + + memset(block16, 0, 16 * sizeof(*block16)); + + has_ac = rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac); + if(has_ac) + r->rdsp.rv34_inv_transform(block16); + else + r->rdsp.rv34_inv_transform_dc(block16); + + itype = ittrans16[intra_types[0]]; + itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]); + r->h.pred16x16[itype](dst, s->linesize); + + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++, cbp >>= 1){ + int dc = block16[i + j*4]; + + if(cbp & 1){ + has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac); + }else + has_ac = 0; + + if(has_ac){ + ptr[0] = dc; + r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr); + }else + r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc); + } + + dst += 4*s->linesize; + } + + itype = ittrans16[intra_types[0]]; + if(itype == PLANE_PRED8x8) itype = DC_PRED8x8; + itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]); + + q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; + q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; + + for(j = 1; j < 3; j++){ + dst = s->dest[j]; + r->h.pred8x8[itype](dst, s->uvlinesize); + for(i = 0; i < 4; i++, cbp >>= 1){ + uint8_t *pdst; + if(!(cbp & 1)) continue; + pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize; + + rv34_process_block(r, pdst, s->uvlinesize, + r->chroma_vlc, 1, q_dc, q_ac); + } + } +} + +static void rv34_output_intra(RV34DecContext *r, int8_t *intra_types, int cbp) +{ + MpegEncContext *s = &r->s; + uint8_t *dst = s->dest[0]; + int avail[6*8] = {0}; + int i, j, k; + int idx, q_ac, q_dc; + + // Set neighbour information. + if(r->avail_cache[1]) + avail[0] = 1; + if(r->avail_cache[2]) + avail[1] = avail[2] = 1; + if(r->avail_cache[3]) + avail[3] = avail[4] = 1; + if(r->avail_cache[4]) + avail[5] = 1; + if(r->avail_cache[5]) + avail[8] = avail[16] = 1; + if(r->avail_cache[9]) + avail[24] = avail[32] = 1; + + q_ac = rv34_qscale_tab[s->qscale]; + for(j = 0; j < 4; j++){ + idx = 9 + j*8; + for(i = 0; i < 4; i++, cbp >>= 1, dst += 4, idx++){ + rv34_pred_4x4_block(r, dst, s->linesize, ittrans[intra_types[i]], avail[idx-8], avail[idx-1], avail[idx+7], avail[idx-7]); + avail[idx] = 1; + if(!(cbp & 1)) continue; + + rv34_process_block(r, dst, s->linesize, + r->luma_vlc, 0, q_ac, q_ac); + } + dst += s->linesize * 4 - 4*4; + intra_types += r->intra_types_stride; + } + + intra_types -= r->intra_types_stride * 4; + + q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; + q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; + + for(k = 0; k < 2; k++){ + dst = s->dest[1+k]; + fill_rectangle(r->avail_cache + 6, 2, 2, 4, 0, 4); + + for(j = 0; j < 2; j++){ + int* acache = r->avail_cache + 6 + j*4; + for(i = 0; i < 2; i++, cbp >>= 1, acache++){ + int itype = ittrans[intra_types[i*2+j*2*r->intra_types_stride]]; + rv34_pred_4x4_block(r, dst+4*i, s->uvlinesize, itype, acache[-4], acache[-1], !i && !j, acache[-3]); + acache[0] = 1; + + if(!(cbp&1)) continue; + + rv34_process_block(r, dst + 4*i, s->uvlinesize, + r->chroma_vlc, 1, q_dc, q_ac); + } + + dst += 4*s->uvlinesize; + } + } +} + +static int is_mv_diff_gt_3(int16_t (*motion_val)[2], int step) +{ + int d; + d = motion_val[0][0] - motion_val[-step][0]; + if(d < -3 || d > 3) + return 1; + d = motion_val[0][1] - motion_val[-step][1]; + if(d < -3 || d > 3) + return 1; + return 0; +} + +static int rv34_set_deblock_coef(RV34DecContext *r) +{ + MpegEncContext *s = &r->s; + int hmvmask = 0, vmvmask = 0, i, j; + int midx = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; + int16_t (*motion_val)[2] = &s->current_picture_ptr->motion_val[0][midx]; + for(j = 0; j < 16; j += 8){ + for(i = 0; i < 2; i++){ + if(is_mv_diff_gt_3(motion_val + i, 1)) + vmvmask |= 0x11 << (j + i*2); + if((j || s->mb_y) && is_mv_diff_gt_3(motion_val + i, s->b8_stride)) + hmvmask |= 0x03 << (j + i*2); + } + motion_val += s->b8_stride; + } + if(s->first_slice_line) + hmvmask &= ~0x000F; + if(!s->mb_x) + vmvmask &= ~0x1111; + if(r->rv30){ //RV30 marks both subblocks on the edge for filtering + vmvmask |= (vmvmask & 0x4444) >> 1; + hmvmask |= (hmvmask & 0x0F00) >> 4; + if(s->mb_x) + r->deblock_coefs[s->mb_x - 1 + s->mb_y*s->mb_stride] |= (vmvmask & 0x1111) << 3; + if(!s->first_slice_line) + r->deblock_coefs[s->mb_x + (s->mb_y - 1)*s->mb_stride] |= (hmvmask & 0xF) << 12; + } + return hmvmask | vmvmask; +} + +static int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types) +{ + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + uint8_t *dst = s->dest[0]; + int16_t *ptr = s->block[0]; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp, cbp2; + int q_dc, q_ac, has_ac; + int i, j; + int dist; + + // Calculate which neighbours are available. Maybe it's worth optimizing too. + memset(r->avail_cache, 0, sizeof(r->avail_cache)); + fill_rectangle(r->avail_cache + 6, 2, 2, 4, 1, 4); + dist = (s->mb_x - s->resync_mb_x) + (s->mb_y - s->resync_mb_y) * s->mb_width; + if(s->mb_x && dist) + r->avail_cache[5] = + r->avail_cache[9] = s->current_picture_ptr->mb_type[mb_pos - 1]; + if(dist >= s->mb_width) + r->avail_cache[2] = + r->avail_cache[3] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride]; + if(((s->mb_x+1) < s->mb_width) && dist >= s->mb_width - 1) + r->avail_cache[4] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride + 1]; + if(s->mb_x && dist > s->mb_width) + r->avail_cache[1] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride - 1]; + + s->qscale = r->si.quant; + cbp = cbp2 = rv34_decode_inter_mb_header(r, intra_types); + r->cbp_luma [mb_pos] = cbp; + r->cbp_chroma[mb_pos] = cbp >> 16; + r->deblock_coefs[mb_pos] = rv34_set_deblock_coef(r) | r->cbp_luma[mb_pos]; + s->current_picture_ptr->qscale_table[mb_pos] = s->qscale; + + if(cbp == -1) + return -1; + + if (IS_INTRA(s->current_picture_ptr->mb_type[mb_pos])){ + if(r->is16) rv34_output_i16x16(r, intra_types, cbp); + else rv34_output_intra(r, intra_types, cbp); + return 0; + } + + if(r->is16){ + // Only for RV34_MB_P_MIX16x16 + LOCAL_ALIGNED_16(int16_t, block16, [16]); + memset(block16, 0, 16 * sizeof(*block16)); + q_dc = rv34_qscale_tab[ r->luma_dc_quant_p[s->qscale] ]; + q_ac = rv34_qscale_tab[s->qscale]; + if (rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac)) + r->rdsp.rv34_inv_transform(block16); + else + r->rdsp.rv34_inv_transform_dc(block16); + + q_ac = rv34_qscale_tab[s->qscale]; + + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++, cbp >>= 1){ + int dc = block16[i + j*4]; + + if(cbp & 1){ + has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac); + }else + has_ac = 0; + + if(has_ac){ + ptr[0] = dc; + r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr); + }else + r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc); + } + + dst += 4*s->linesize; + } + + r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); + }else{ + q_ac = rv34_qscale_tab[s->qscale]; + + for(j = 0; j < 4; j++){ + for(i = 0; i < 4; i++, cbp >>= 1){ + if(!(cbp & 1)) continue; + + rv34_process_block(r, dst + 4*i, s->linesize, + r->luma_vlc, 0, q_ac, q_ac); + } + dst += 4*s->linesize; + } + } + + q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; + q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; + + for(j = 1; j < 3; j++){ + dst = s->dest[j]; + for(i = 0; i < 4; i++, cbp >>= 1){ + uint8_t *pdst; + if(!(cbp & 1)) continue; + pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize; + + rv34_process_block(r, pdst, s->uvlinesize, + r->chroma_vlc, 1, q_dc, q_ac); + } + } + + return 0; +} + +static int rv34_decode_intra_macroblock(RV34DecContext *r, int8_t *intra_types) +{ + MpegEncContext *s = &r->s; + int cbp, dist; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + // Calculate which neighbours are available. Maybe it's worth optimizing too. + memset(r->avail_cache, 0, sizeof(r->avail_cache)); + fill_rectangle(r->avail_cache + 6, 2, 2, 4, 1, 4); + dist = (s->mb_x - s->resync_mb_x) + (s->mb_y - s->resync_mb_y) * s->mb_width; + if(s->mb_x && dist) + r->avail_cache[5] = + r->avail_cache[9] = s->current_picture_ptr->mb_type[mb_pos - 1]; + if(dist >= s->mb_width) + r->avail_cache[2] = + r->avail_cache[3] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride]; + if(((s->mb_x+1) < s->mb_width) && dist >= s->mb_width - 1) + r->avail_cache[4] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride + 1]; + if(s->mb_x && dist > s->mb_width) + r->avail_cache[1] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride - 1]; + + s->qscale = r->si.quant; + cbp = rv34_decode_intra_mb_header(r, intra_types); + r->cbp_luma [mb_pos] = cbp; + r->cbp_chroma[mb_pos] = cbp >> 16; + r->deblock_coefs[mb_pos] = 0xFFFF; + s->current_picture_ptr->qscale_table[mb_pos] = s->qscale; + + if(cbp == -1) + return -1; + + if(r->is16){ + rv34_output_i16x16(r, intra_types, cbp); + return 0; + } + + rv34_output_intra(r, intra_types, cbp); + return 0; +} + +static int check_slice_end(RV34DecContext *r, MpegEncContext *s) +{ + int bits; + if(s->mb_y >= s->mb_height) + return 1; + if(!s->mb_num_left) + return 1; + if(r->s.mb_skip_run > 1) + return 0; + bits = get_bits_left(&s->gb); + if(bits <= 0 || (bits < 8 && !show_bits(&s->gb, bits))) + return 1; + return 0; +} + + +static void rv34_decoder_free(RV34DecContext *r) +{ + av_freep(&r->intra_types_hist); + r->intra_types = NULL; + av_freep(&r->tmp_b_block_base); + av_freep(&r->mb_type); + av_freep(&r->cbp_luma); + av_freep(&r->cbp_chroma); + av_freep(&r->deblock_coefs); +} + + +static int rv34_decoder_alloc(RV34DecContext *r) +{ + r->intra_types_stride = r->s.mb_width * 4 + 4; + + r->cbp_chroma = av_malloc(r->s.mb_stride * r->s.mb_height * + sizeof(*r->cbp_chroma)); + r->cbp_luma = av_malloc(r->s.mb_stride * r->s.mb_height * + sizeof(*r->cbp_luma)); + r->deblock_coefs = av_malloc(r->s.mb_stride * r->s.mb_height * + sizeof(*r->deblock_coefs)); + r->intra_types_hist = av_malloc(r->intra_types_stride * 4 * 2 * + sizeof(*r->intra_types_hist)); + r->mb_type = av_mallocz(r->s.mb_stride * r->s.mb_height * + sizeof(*r->mb_type)); + + if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs && + r->intra_types_hist && r->mb_type)) { + rv34_decoder_free(r); + return AVERROR(ENOMEM); + } + + r->intra_types = r->intra_types_hist + r->intra_types_stride * 4; + + return 0; +} + + +static int rv34_decoder_realloc(RV34DecContext *r) +{ + rv34_decoder_free(r); + return rv34_decoder_alloc(r); +} + + +static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int buf_size) +{ + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + int mb_pos, slice_type; + int res; + + init_get_bits(&r->s.gb, buf, buf_size*8); + res = r->parse_slice_header(r, gb, &r->si); + if(res < 0){ + av_log(s->avctx, AV_LOG_ERROR, "Incorrect or unknown slice header\n"); + return -1; + } + + slice_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I; + if (slice_type != s->pict_type) { + av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n"); + return AVERROR_INVALIDDATA; + } + if (s->width != r->si.width || s->height != r->si.height) { + av_log(s->avctx, AV_LOG_ERROR, "Size mismatch\n"); + return AVERROR_INVALIDDATA; + } + + r->si.end = end; + s->qscale = r->si.quant; + s->mb_num_left = r->si.end - r->si.start; + r->s.mb_skip_run = 0; + + mb_pos = s->mb_x + s->mb_y * s->mb_width; + if(r->si.start != mb_pos){ + av_log(s->avctx, AV_LOG_ERROR, "Slice indicates MB offset %d, got %d\n", r->si.start, mb_pos); + s->mb_x = r->si.start % s->mb_width; + s->mb_y = r->si.start / s->mb_width; + } + memset(r->intra_types_hist, -1, r->intra_types_stride * 4 * 2 * sizeof(*r->intra_types_hist)); + s->first_slice_line = 1; + s->resync_mb_x = s->mb_x; + s->resync_mb_y = s->mb_y; + + ff_init_block_index(s); + while(!check_slice_end(r, s)) { + ff_update_block_index(s); + + if(r->si.type) + res = rv34_decode_inter_macroblock(r, r->intra_types + s->mb_x * 4 + 4); + else + res = rv34_decode_intra_macroblock(r, r->intra_types + s->mb_x * 4 + 4); + if(res < 0){ + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_ERROR); + return -1; + } + if (++s->mb_x == s->mb_width) { + s->mb_x = 0; + s->mb_y++; + ff_init_block_index(s); + + memmove(r->intra_types_hist, r->intra_types, r->intra_types_stride * 4 * sizeof(*r->intra_types_hist)); + memset(r->intra_types, -1, r->intra_types_stride * 4 * sizeof(*r->intra_types_hist)); + + if(r->loop_filter && s->mb_y >= 2) + r->loop_filter(r, s->mb_y - 2); + + if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) + ff_thread_report_progress(&s->current_picture_ptr->tf, + s->mb_y - 2, 0); + + } + if(s->mb_x == s->resync_mb_x) + s->first_slice_line=0; + s->mb_num_left--; + } + ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END); + + return s->mb_y == s->mb_height; +} + +/** @} */ // recons group end + +/** + * Initialize decoder. + */ +av_cold int ff_rv34_decode_init(AVCodecContext *avctx) +{ + RV34DecContext *r = avctx->priv_data; + MpegEncContext *s = &r->s; + int ret; + + ff_MPV_decode_defaults(s); + s->avctx = avctx; + s->out_format = FMT_H263; + s->codec_id = avctx->codec_id; + + s->width = avctx->width; + s->height = avctx->height; + + r->s.avctx = avctx; + avctx->flags |= CODEC_FLAG_EMU_EDGE; + r->s.flags |= CODEC_FLAG_EMU_EDGE; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->has_b_frames = 1; + s->low_delay = 0; + + if ((ret = ff_MPV_common_init(s)) < 0) + return ret; + + ff_h264_pred_init(&r->h, AV_CODEC_ID_RV40, 8, 1); + +#if CONFIG_RV30_DECODER + if (avctx->codec_id == AV_CODEC_ID_RV30) + ff_rv30dsp_init(&r->rdsp); +#endif +#if CONFIG_RV40_DECODER + if (avctx->codec_id == AV_CODEC_ID_RV40) + ff_rv40dsp_init(&r->rdsp); +#endif + + if ((ret = rv34_decoder_alloc(r)) < 0) + return ret; + + if(!intra_vlcs[0].cbppattern[0].bits) + rv34_init_tables(); + + avctx->internal->allocate_progress = 1; + + return 0; +} + +int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx) +{ + int err; + RV34DecContext *r = avctx->priv_data; + + r->s.avctx = avctx; + + if (avctx->internal->is_copy) { + r->tmp_b_block_base = NULL; + if ((err = ff_MPV_common_init(&r->s)) < 0) + return err; + if ((err = rv34_decoder_alloc(r)) < 0) + return err; + } + + return 0; +} + +int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + RV34DecContext *r = dst->priv_data, *r1 = src->priv_data; + MpegEncContext * const s = &r->s, * const s1 = &r1->s; + int err; + + if (dst == src || !s1->context_initialized) + return 0; + + if (s->height != s1->height || s->width != s1->width) { + s->height = s1->height; + s->width = s1->width; + if ((err = ff_MPV_common_frame_size_change(s)) < 0) + return err; + if ((err = rv34_decoder_realloc(r)) < 0) + return err; + } + + if ((err = ff_mpeg_update_thread_context(dst, src))) + return err; + + r->cur_pts = r1->cur_pts; + r->last_pts = r1->last_pts; + r->next_pts = r1->next_pts; + + memset(&r->si, 0, sizeof(r->si)); + + return 0; +} + +static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) +{ + if(avctx->slice_count) return avctx->slice_offset[n]; + else return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8); +} + +static int finish_frame(AVCodecContext *avctx, AVFrame *pict) +{ + RV34DecContext *r = avctx->priv_data; + MpegEncContext *s = &r->s; + int got_picture = 0, ret; + + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); + s->mb_num_left = 0; + + if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) + ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); + + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { + if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->current_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); + got_picture = 1; + } else if (s->last_picture_ptr != NULL) { + if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + return ret; + ff_print_debug_info(s, s->last_picture_ptr, pict); + ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); + got_picture = 1; + } + + return got_picture; +} + +static AVRational update_sar(int old_w, int old_h, AVRational sar, int new_w, int new_h) +{ + // attempt to keep aspect during typical resolution switches + if (!sar.num) + sar = (AVRational){1, 1}; + + sar = av_mul_q(sar, (AVRational){new_h * old_w, new_w * old_h}); + return sar; +} + +int ff_rv34_decode_frame(AVCodecContext *avctx, + void *data, int *got_picture_ptr, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + RV34DecContext *r = avctx->priv_data; + MpegEncContext *s = &r->s; + AVFrame *pict = data; + SliceInfo si; + int i, ret; + int slice_count; + const uint8_t *slices_hdr = NULL; + int last = 0; + + /* no supplementary picture */ + if (buf_size == 0) { + /* special case for last picture */ + if (s->low_delay==0 && s->next_picture_ptr) { + if ((ret = av_frame_ref(pict, &s->next_picture_ptr->f)) < 0) + return ret; + s->next_picture_ptr = NULL; + + *got_picture_ptr = 1; + } + return 0; + } + + if(!avctx->slice_count){ + slice_count = (*buf++) + 1; + slices_hdr = buf + 4; + buf += 8 * slice_count; + buf_size -= 1 + 8 * slice_count; + }else + slice_count = avctx->slice_count; + + //parse first slice header to check whether this frame can be decoded + if(get_slice_offset(avctx, slices_hdr, 0) < 0 || + get_slice_offset(avctx, slices_hdr, 0) > buf_size){ + av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); + return AVERROR_INVALIDDATA; + } + init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, 0), (buf_size-get_slice_offset(avctx, slices_hdr, 0))*8); + if(r->parse_slice_header(r, &r->s.gb, &si) < 0 || si.start){ + av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n"); + return AVERROR_INVALIDDATA; + } + if ((!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) && + si.type == AV_PICTURE_TYPE_B) { + av_log(avctx, AV_LOG_ERROR, "Invalid decoder state: B-frame without " + "reference data.\n"); + return AVERROR_INVALIDDATA; + } + if( (avctx->skip_frame >= AVDISCARD_NONREF && si.type==AV_PICTURE_TYPE_B) + || (avctx->skip_frame >= AVDISCARD_NONKEY && si.type!=AV_PICTURE_TYPE_I) + || avctx->skip_frame >= AVDISCARD_ALL) + return avpkt->size; + + /* first slice */ + if (si.start == 0) { + if (s->mb_num_left > 0) { + av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n", + s->mb_num_left); + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); + } + + if (s->width != si.width || s->height != si.height) { + int err; + + av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n", + si.width, si.height); + + if (av_image_check_size(si.width, si.height, 0, s->avctx)) + return AVERROR_INVALIDDATA; + + s->avctx->sample_aspect_ratio = update_sar( + s->width, s->height, s->avctx->sample_aspect_ratio, + si.width, si.height); + s->width = si.width; + s->height = si.height; + avcodec_set_dimensions(s->avctx, s->width, s->height); + if ((err = ff_MPV_common_frame_size_change(s)) < 0) + return err; + if ((err = rv34_decoder_realloc(r)) < 0) + return err; + } + s->pict_type = si.type ? si.type : AV_PICTURE_TYPE_I; + if (ff_MPV_frame_start(s, s->avctx) < 0) + return -1; + ff_mpeg_er_frame_start(s); + if (!r->tmp_b_block_base) { + int i; + + r->tmp_b_block_base = av_malloc(s->linesize * 48); + for (i = 0; i < 2; i++) + r->tmp_b_block_y[i] = r->tmp_b_block_base + + i * 16 * s->linesize; + for (i = 0; i < 4; i++) + r->tmp_b_block_uv[i] = r->tmp_b_block_base + 32 * s->linesize + + (i >> 1) * 8 * s->uvlinesize + + (i & 1) * 16; + } + r->cur_pts = si.pts; + if (s->pict_type != AV_PICTURE_TYPE_B) { + r->last_pts = r->next_pts; + r->next_pts = r->cur_pts; + } else { + int refdist = GET_PTS_DIFF(r->next_pts, r->last_pts); + int dist0 = GET_PTS_DIFF(r->cur_pts, r->last_pts); + int dist1 = GET_PTS_DIFF(r->next_pts, r->cur_pts); + + if(!refdist){ + r->mv_weight1 = r->mv_weight2 = r->weight1 = r->weight2 = 8192; + r->scaled_weight = 0; + }else{ + r->mv_weight1 = (dist0 << 14) / refdist; + r->mv_weight2 = (dist1 << 14) / refdist; + if((r->mv_weight1|r->mv_weight2) & 511){ + r->weight1 = r->mv_weight1; + r->weight2 = r->mv_weight2; + r->scaled_weight = 0; + }else{ + r->weight1 = r->mv_weight1 >> 9; + r->weight2 = r->mv_weight2 >> 9; + r->scaled_weight = 1; + } + } + } + s->mb_x = s->mb_y = 0; + ff_thread_finish_setup(s->avctx); + } else if (HAVE_THREADS && + (s->avctx->active_thread_type & FF_THREAD_FRAME)) { + av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames in frame " + "multithreading mode (start MB is %d).\n", si.start); + return AVERROR_INVALIDDATA; + } + + for(i = 0; i < slice_count; i++){ + int offset = get_slice_offset(avctx, slices_hdr, i); + int size; + if(i+1 == slice_count) + size = buf_size - offset; + else + size = get_slice_offset(avctx, slices_hdr, i+1) - offset; + + if(offset < 0 || offset > buf_size){ + av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); + break; + } + + r->si.end = s->mb_width * s->mb_height; + s->mb_num_left = r->s.mb_x + r->s.mb_y*r->s.mb_width - r->si.start; + + if(i+1 < slice_count){ + if (get_slice_offset(avctx, slices_hdr, i+1) < 0 || + get_slice_offset(avctx, slices_hdr, i+1) > buf_size) { + av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); + break; + } + init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, i+1), (buf_size-get_slice_offset(avctx, slices_hdr, i+1))*8); + if(r->parse_slice_header(r, &r->s.gb, &si) < 0){ + if(i+2 < slice_count) + size = get_slice_offset(avctx, slices_hdr, i+2) - offset; + else + size = buf_size - offset; + }else + r->si.end = si.start; + } + if (size < 0 || size > buf_size - offset) { + av_log(avctx, AV_LOG_ERROR, "Slice size is invalid\n"); + break; + } + last = rv34_decode_slice(r, r->si.end, buf + offset, size); + if(last) + break; + } + + if (s->current_picture_ptr) { + if (last) { + if(r->loop_filter) + r->loop_filter(r, s->mb_height - 1); + + ret = finish_frame(avctx, pict); + if (ret < 0) + return ret; + *got_picture_ptr = ret; + } else if (HAVE_THREADS && + (s->avctx->active_thread_type & FF_THREAD_FRAME)) { + av_log(avctx, AV_LOG_INFO, "marking unfished frame as finished\n"); + /* always mark the current frame as finished, frame-mt supports + * only complete frames */ + ff_er_frame_end(&s->er); + ff_MPV_frame_end(s); + s->mb_num_left = 0; + ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); + return AVERROR_INVALIDDATA; + } + } + + return avpkt->size; +} + +av_cold int ff_rv34_decode_end(AVCodecContext *avctx) +{ + RV34DecContext *r = avctx->priv_data; + + ff_MPV_common_end(&r->s); + rv34_decoder_free(r); + + return 0; +} diff --git a/ffmpeg/libavcodec/rv34.h b/ffmpeg/libavcodec/rv34.h new file mode 100644 index 0000000..475f17a --- /dev/null +++ b/ffmpeg/libavcodec/rv34.h @@ -0,0 +1,140 @@ +/* + * RV30/40 decoder common data declarations + * Copyright (c) 2007 Mike Melanson, Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV30 and RV40 decoder common data declarations + */ + +#ifndef AVCODEC_RV34_H +#define AVCODEC_RV34_H + +#include "avcodec.h" +#include "mpegvideo.h" + +#include "h264pred.h" +#include "rv34dsp.h" + +#define MB_TYPE_SEPARATE_DC 0x01000000 +#define IS_SEPARATE_DC(a) ((a) & MB_TYPE_SEPARATE_DC) + +/** + * RV30 and RV40 Macroblock types + */ +enum RV40BlockTypes{ + RV34_MB_TYPE_INTRA, ///< Intra macroblock + RV34_MB_TYPE_INTRA16x16, ///< Intra macroblock with DCs in a separate 4x4 block + RV34_MB_P_16x16, ///< P-frame macroblock, one motion frame + RV34_MB_P_8x8, ///< P-frame macroblock, 8x8 motion compensation partitions + RV34_MB_B_FORWARD, ///< B-frame macroblock, forward prediction + RV34_MB_B_BACKWARD, ///< B-frame macroblock, backward prediction + RV34_MB_SKIP, ///< Skipped block + RV34_MB_B_DIRECT, ///< Bidirectionally predicted B-frame macroblock, no motion vectors + RV34_MB_P_16x8, ///< P-frame macroblock, 16x8 motion compensation partitions + RV34_MB_P_8x16, ///< P-frame macroblock, 8x16 motion compensation partitions + RV34_MB_B_BIDIR, ///< Bidirectionally predicted B-frame macroblock, two motion vectors + RV34_MB_P_MIX16x16, ///< P-frame macroblock with DCs in a separate 4x4 block, one motion vector + RV34_MB_TYPES +}; + +/** + * VLC tables used by the decoder + * + * Intra frame VLC sets do not contain some of those tables. + */ +typedef struct RV34VLC{ + VLC cbppattern[2]; ///< VLCs used for pattern of coded block patterns decoding + VLC cbp[2][4]; ///< VLCs used for coded block patterns decoding + VLC first_pattern[4]; ///< VLCs used for decoding coefficients in the first subblock + VLC second_pattern[2]; ///< VLCs used for decoding coefficients in the subblocks 2 and 3 + VLC third_pattern[2]; ///< VLCs used for decoding coefficients in the last subblock + VLC coefficient; ///< VLCs used for decoding big coefficients +}RV34VLC; + +/** essential slice information */ +typedef struct SliceInfo{ + int type; ///< slice type (intra, inter) + int quant; ///< quantizer used for this slice + int vlc_set; ///< VLCs used for this slice + int start, end; ///< start and end macroblocks of the slice + int width; ///< coded width + int height; ///< coded height + int pts; ///< frame timestamp +}SliceInfo; + +/** decoder context */ +typedef struct RV34DecContext{ + MpegEncContext s; + RV34DSPContext rdsp; + int8_t *intra_types_hist;///< old block types, used for prediction + int8_t *intra_types; ///< block types + int intra_types_stride;///< block types array stride + const uint8_t *luma_dc_quant_i;///< luma subblock DC quantizer for intraframes + const uint8_t *luma_dc_quant_p;///< luma subblock DC quantizer for interframes + + RV34VLC *cur_vlcs; ///< VLC set used for current frame decoding + H264PredContext h; ///< functions for 4x4 and 16x16 intra block prediction + SliceInfo si; ///< current slice information + + int *mb_type; ///< internal macroblock types + int block_type; ///< current block type + int luma_vlc; ///< which VLC set will be used for decoding of luma blocks + int chroma_vlc; ///< which VLC set will be used for decoding of chroma blocks + int is16; ///< current block has additional 16x16 specific features or not + int dmv[4][2]; ///< differential motion vectors for the current macroblock + + int rv30; ///< indicates which RV variasnt is currently decoded + int rpr; ///< one field size in RV30 slice header + + int cur_pts, last_pts, next_pts; + int scaled_weight; + int weight1, weight2; ///< B frame distance fractions (0.14) used in motion compensation + int mv_weight1, mv_weight2; + + uint16_t *cbp_luma; ///< CBP values for luma subblocks + uint8_t *cbp_chroma; ///< CBP values for chroma subblocks + uint16_t *deblock_coefs; ///< deblock coefficients for each macroblock + + /** 8x8 block available flags (for MV prediction) */ + DECLARE_ALIGNED(8, uint32_t, avail_cache)[3*4]; + + /** temporary blocks for RV4 weighted MC */ + uint8_t *tmp_b_block_y[2]; + uint8_t *tmp_b_block_uv[4]; + uint8_t *tmp_b_block_base; + + int (*parse_slice_header)(struct RV34DecContext *r, GetBitContext *gb, SliceInfo *si); + int (*decode_mb_info)(struct RV34DecContext *r); + int (*decode_intra_types)(struct RV34DecContext *r, GetBitContext *gb, int8_t *dst); + void (*loop_filter)(struct RV34DecContext *r, int row); +}RV34DecContext; + +/** + * common decoding functions + */ +int ff_rv34_get_start_offset(GetBitContext *gb, int blocks); +int ff_rv34_decode_init(AVCodecContext *avctx); +int ff_rv34_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt); +int ff_rv34_decode_end(AVCodecContext *avctx); +int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx); +int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); + +#endif /* AVCODEC_RV34_H */ diff --git a/ffmpeg/libavcodec/rv34_parser.c b/ffmpeg/libavcodec/rv34_parser.c new file mode 100644 index 0000000..8af7443 --- /dev/null +++ b/ffmpeg/libavcodec/rv34_parser.c @@ -0,0 +1,93 @@ +/* + * RV30/40 parser + * Copyright (c) 2011 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * RV30/40 parser + */ + +#include "parser.h" +#include "libavutil/intreadwrite.h" + +typedef struct { + ParseContext pc; + int64_t key_dts; + int key_pts; +} RV34ParseContext; + +static const int rv_to_av_frame_type[4] = { + AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, +}; + +static int rv34_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + RV34ParseContext *pc = s->priv_data; + int type, pts, hdr; + + if (buf_size < 13 + *buf * 8) { + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; + } + + hdr = AV_RB32(buf + 9 + *buf * 8); + if (avctx->codec_id == AV_CODEC_ID_RV30) { + type = (hdr >> 27) & 3; + pts = (hdr >> 7) & 0x1FFF; + } else { + type = (hdr >> 29) & 3; + pts = (hdr >> 6) & 0x1FFF; + } + + if (type != 3 && s->pts != AV_NOPTS_VALUE) { + pc->key_dts = s->pts; + pc->key_pts = pts; + } else { + if (type != 3) + s->pts = pc->key_dts + ((pts - pc->key_pts) & 0x1FFF); + else + s->pts = pc->key_dts - ((pc->key_pts - pts) & 0x1FFF); + } + s->pict_type = rv_to_av_frame_type[type]; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +#if CONFIG_RV30_PARSER +AVCodecParser ff_rv30_parser = { + .codec_ids = { AV_CODEC_ID_RV30 }, + .priv_data_size = sizeof(RV34ParseContext), + .parser_parse = rv34_parse, +}; +#endif + +#if CONFIG_RV40_PARSER +AVCodecParser ff_rv40_parser = { + .codec_ids = { AV_CODEC_ID_RV40 }, + .priv_data_size = sizeof(RV34ParseContext), + .parser_parse = rv34_parse, +}; +#endif diff --git a/ffmpeg/libavcodec/rv34data.h b/ffmpeg/libavcodec/rv34data.h new file mode 100644 index 0000000..4b2701f --- /dev/null +++ b/ffmpeg/libavcodec/rv34data.h @@ -0,0 +1,126 @@ +/* + * RealVideo 4 decoder + * copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * miscellaneous RV30/40 tables + */ + +#ifndef AVCODEC_RV34DATA_H +#define AVCODEC_RV34DATA_H + +#include + +/** + * number of ones in nibble minus one + */ +static const uint8_t rv34_count_ones[16] = { + 0, 0, 0, 1, 0, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 3 +}; + +/** + * values used to reconstruct coded block pattern + */ +static const uint8_t rv34_cbp_code[16] = { + 0x00, 0x20, 0x10, 0x30, 0x02, 0x22, 0x12, 0x32, + 0x01, 0x21, 0x11, 0x31, 0x03, 0x23, 0x13, 0x33 +}; + +/** + * precalculated results of division by three and modulo three for values 0-107 + * + * A lot of four-tuples in RV40 are represented as c0*27+c1*9+c2*3+c3. + * This table allows conversion from a value back to a vector. + */ +static const uint8_t modulo_three_table[108] = { + 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, + 0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A, + 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2A, + + 0x40, 0x41, 0x42, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, + 0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5A, + 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x68, 0x69, 0x6A, + + 0x80, 0x81, 0x82, 0x84, 0x85, 0x86, 0x88, 0x89, 0x8A, + 0x90, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98, 0x99, 0x9A, + 0xA0, 0xA1, 0xA2, 0xA4, 0xA5, 0xA6, 0xA8, 0xA9, 0xAA, + + 0xC0, 0xC1, 0xC2, 0xC4, 0xC5, 0xC6, 0xC8, 0xC9, 0xCA, + 0xD0, 0xD1, 0xD2, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, + 0xE0, 0xE1, 0xE2, 0xE4, 0xE5, 0xE6, 0xE8, 0xE9, 0xEA, +}; + +/** + * quantizer values used for AC and DC coefficients in chroma blocks + */ +static const uint8_t rv34_chroma_quant[2][32] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25 }, + { 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23 } +}; + +/** + * This table is used for dequantizing. + */ +static const uint16_t rv34_qscale_tab[32] = { + 60, 67, 76, 85, 96, 108, 121, 136, + 152, 171, 192, 216, 242, 272, 305, 341, + 383, 432, 481, 544, 606, 683, 767, 854, + 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211 +}; + +/** + * tables used to translate a quantizer value into a VLC set for decoding + * The first table is used for intraframes. + */ +static const uint8_t rv34_quant_to_vlc_set[2][31] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, + 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6 }, +}; + +/** + * table for obtaining the quantizer difference + * @todo Use with ff_modified_quant_tab from h263data.h. + */ +static const uint8_t rv34_dquant_tab[2][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, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9,10,11,12,13,14,15,16,17,18,18,19,20,21,22,23,24,25,26,27,28 +},{ + 0, 2, 3, 4, 5, 6, 7, 8, 9,10,11,13,14,15,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,31,31,26 +} +}; + +/** + * maximum number of macroblocks for each of the possible slice offset sizes + * @todo This is the same as ff_mba_max, maybe use it instead. + */ +static const uint16_t rv34_mb_max_sizes[6] = { 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF }; +/** + * bits needed to code the slice offset for the given size + * @todo This is the same as ff_mba_length, maybe use it instead. + */ +static const uint8_t rv34_mb_bits_sizes[6] = { 6, 7, 9, 11, 13, 14 }; + +#endif /* AVCODEC_RV34DATA_H */ diff --git a/ffmpeg/libavcodec/rv34dsp.c b/ffmpeg/libavcodec/rv34dsp.c new file mode 100644 index 0000000..7234ee8 --- /dev/null +++ b/ffmpeg/libavcodec/rv34dsp.c @@ -0,0 +1,143 @@ +/* + * RV30/40 decoder common dsp functions + * Copyright (c) 2007 Mike Melanson, Konstantin Shishkov + * Copyright (c) 2011 Janne Grunau + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * RV30/40 decoder common dsp functions + */ + +#include "rv34dsp.h" +#include "libavutil/common.h" + +/** + * @name RV30/40 inverse transform functions + * @{ + */ + +static av_always_inline void rv34_row_transform(int temp[16], int16_t *block) +{ + int i; + + for(i = 0; i < 4; i++){ + const int z0 = 13*(block[i+4*0] + block[i+4*2]); + const int z1 = 13*(block[i+4*0] - block[i+4*2]); + const int z2 = 7* block[i+4*1] - 17*block[i+4*3]; + const int z3 = 17* block[i+4*1] + 7*block[i+4*3]; + + temp[4*i+0] = z0 + z3; + temp[4*i+1] = z1 + z2; + temp[4*i+2] = z1 - z2; + temp[4*i+3] = z0 - z3; + } +} + +/** + * Real Video 3.0/4.0 inverse transform + sample reconstruction + * Code is almost the same as in SVQ3, only scaling is different. + */ +static void rv34_idct_add_c(uint8_t *dst, ptrdiff_t stride, int16_t *block){ + int temp[16]; + int i; + + rv34_row_transform(temp, block); + memset(block, 0, 16*sizeof(int16_t)); + + for(i = 0; i < 4; i++){ + const int z0 = 13*(temp[4*0+i] + temp[4*2+i]) + 0x200; + const int z1 = 13*(temp[4*0+i] - temp[4*2+i]) + 0x200; + const int z2 = 7* temp[4*1+i] - 17*temp[4*3+i]; + const int z3 = 17* temp[4*1+i] + 7*temp[4*3+i]; + + dst[0] = av_clip_uint8( dst[0] + ( (z0 + z3) >> 10 ) ); + dst[1] = av_clip_uint8( dst[1] + ( (z1 + z2) >> 10 ) ); + dst[2] = av_clip_uint8( dst[2] + ( (z1 - z2) >> 10 ) ); + dst[3] = av_clip_uint8( dst[3] + ( (z0 - z3) >> 10 ) ); + + dst += stride; + } +} + +/** + * RealVideo 3.0/4.0 inverse transform for DC block + * + * Code is almost the same as rv34_inv_transform() + * but final coefficients are multiplied by 1.5 and have no rounding. + */ +static void rv34_inv_transform_noround_c(int16_t *block){ + int temp[16]; + int i; + + rv34_row_transform(temp, block); + + for(i = 0; i < 4; i++){ + const int z0 = 39*(temp[4*0+i] + temp[4*2+i]); + const int z1 = 39*(temp[4*0+i] - temp[4*2+i]); + const int z2 = 21* temp[4*1+i] - 51*temp[4*3+i]; + const int z3 = 51* temp[4*1+i] + 21*temp[4*3+i]; + + block[i*4+0] = (z0 + z3) >> 11; + block[i*4+1] = (z1 + z2) >> 11; + block[i*4+2] = (z1 - z2) >> 11; + block[i*4+3] = (z0 - z3) >> 11; + } +} + +static void rv34_idct_dc_add_c(uint8_t *dst, ptrdiff_t stride, int dc) +{ + int i, j; + + dc = (13*13*dc + 0x200) >> 10; + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + dst[j] = av_clip_uint8( dst[j] + dc ); + + dst += stride; + } +} + +static void rv34_inv_transform_dc_noround_c(int16_t *block) +{ + int16_t dc = (13 * 13 * 3 * block[0]) >> 11; + int i, j; + + for (i = 0; i < 4; i++, block += 4) + for (j = 0; j < 4; j++) + block[j] = dc; +} + +/** @} */ // transform + + +av_cold void ff_rv34dsp_init(RV34DSPContext *c) +{ + c->rv34_inv_transform = rv34_inv_transform_noround_c; + c->rv34_inv_transform_dc = rv34_inv_transform_dc_noround_c; + + c->rv34_idct_add = rv34_idct_add_c; + c->rv34_idct_dc_add = rv34_idct_dc_add_c; + + if (ARCH_ARM) + ff_rv34dsp_init_arm(c); + if (ARCH_X86) + ff_rv34dsp_init_x86(c); +} diff --git a/ffmpeg/libavcodec/rv34dsp.h b/ffmpeg/libavcodec/rv34dsp.h new file mode 100644 index 0000000..c5d4e39 --- /dev/null +++ b/ffmpeg/libavcodec/rv34dsp.h @@ -0,0 +1,87 @@ +/* + * RV30/40 decoder motion compensation functions + * Copyright (c) 2008 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * RV30/40 decoder motion compensation functions + */ + +#ifndef AVCODEC_RV34DSP_H +#define AVCODEC_RV34DSP_H + +#include "dsputil.h" +#include "h264chroma.h" + +typedef void (*rv40_weight_func)(uint8_t *dst/*align width (8 or 16)*/, + uint8_t *src1/*align width (8 or 16)*/, + uint8_t *src2/*align width (8 or 16)*/, + int w1, int w2, ptrdiff_t stride); + +typedef void (*rv34_inv_transform_func)(int16_t *block); + +typedef void (*rv34_idct_add_func)(uint8_t *dst, ptrdiff_t stride, int16_t *block); +typedef void (*rv34_idct_dc_add_func)(uint8_t *dst, ptrdiff_t stride, + int dc); + +typedef void (*rv40_weak_loop_filter_func)(uint8_t *src, ptrdiff_t stride, + int filter_p1, int filter_q1, + int alpha, int beta, + int lims, int lim_q1, int lim_p1); + +typedef void (*rv40_strong_loop_filter_func)(uint8_t *src, ptrdiff_t stride, + int alpha, int lims, + int dmode, int chroma); + +typedef int (*rv40_loop_filter_strength_func)(uint8_t *src, ptrdiff_t stride, + int beta, int beta2, int edge, + int *p1, int *q1); + +typedef struct RV34DSPContext { + qpel_mc_func put_pixels_tab[4][16]; + qpel_mc_func avg_pixels_tab[4][16]; + h264_chroma_mc_func put_chroma_pixels_tab[3]; + h264_chroma_mc_func avg_chroma_pixels_tab[3]; + /** + * Biweight functions, first dimension is transform size (16/8), + * second is whether the weight is prescaled by 1/512 to skip + * the intermediate shifting. + */ + rv40_weight_func rv40_weight_pixels_tab[2][2]; + rv34_inv_transform_func rv34_inv_transform; + rv34_inv_transform_func rv34_inv_transform_dc; + rv34_idct_add_func rv34_idct_add; + rv34_idct_dc_add_func rv34_idct_dc_add; + rv40_weak_loop_filter_func rv40_weak_loop_filter[2]; + rv40_strong_loop_filter_func rv40_strong_loop_filter[2]; + rv40_loop_filter_strength_func rv40_loop_filter_strength[2]; +} RV34DSPContext; + +void ff_rv30dsp_init(RV34DSPContext *c); +void ff_rv34dsp_init(RV34DSPContext *c); +void ff_rv40dsp_init(RV34DSPContext *c); + +void ff_rv34dsp_init_arm(RV34DSPContext *c); +void ff_rv34dsp_init_x86(RV34DSPContext *c); + +void ff_rv40dsp_init_x86(RV34DSPContext *c); +void ff_rv40dsp_init_arm(RV34DSPContext *c); + +#endif /* AVCODEC_RV34DSP_H */ diff --git a/ffmpeg/libavcodec/rv34vlc.h b/ffmpeg/libavcodec/rv34vlc.h new file mode 100644 index 0000000..aa29357 --- /dev/null +++ b/ffmpeg/libavcodec/rv34vlc.h @@ -0,0 +1,4055 @@ +/* + * RealVideo 3/4 decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV30/40 VLC tables + */ + +#ifndef AVCODEC_RV34VLC_H +#define AVCODEC_RV34VLC_H + +#include + +#define NUM_INTRA_TABLES 5 +#define NUM_INTER_TABLES 7 + +#define CBPPAT_VLC_SIZE 1296 +#define CBP_VLC_SIZE 16 +#define FIRSTBLK_VLC_SIZE 864 +#define OTHERBLK_VLC_SIZE 108 +#define COEFF_VLC_SIZE 32 +#define MAX_VLC_SIZE 1296 + +static const uint8_t rv34_table_intra_cbppat[NUM_INTRA_TABLES][2][CBPPAT_VLC_SIZE] = { + { + { + 8, 10, 10, 10, 10, 10, 11, 10, 10, 11, 10, 10, 10, 10, 10, 6, + 12, 12, 13, 12, 13, 12, 13, 11, 13, 13, 13, 12, 13, 12, 12, 8, + 14, 13, 16, 13, 15, 13, 16, 12, 16, 16, 16, 14, 16, 13, 14, 10, + 12, 13, 12, 12, 13, 13, 13, 12, 13, 13, 12, 12, 13, 12, 12, 8, + 13, 14, 14, 12, 14, 14, 14, 12, 14, 15, 14, 12, 14, 13, 13, 8, + 16, 16, 16, 12, 16, 16, 16, 13, 16, 16, 16, 13, 16, 14, 14, 9, + 14, 16, 13, 13, 16, 16, 16, 14, 15, 16, 14, 13, 15, 15, 14, 10, + 16, 16, 14, 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 15, 14, 10, + 16, 16, 16, 11, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 15, 9, + 12, 13, 13, 13, 12, 12, 14, 12, 12, 14, 13, 12, 12, 12, 12, 8, + 14, 14, 16, 14, 13, 12, 14, 12, 14, 15, 14, 13, 13, 12, 13, 8, + 16, 16, 16, 15, 16, 13, 16, 13, 16, 16, 16, 15, 16, 13, 15, 10, + 14, 16, 14, 14, 14, 14, 15, 13, 14, 16, 14, 13, 13, 13, 13, 9, + 16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 14, 13, 14, 13, 13, 8, + 16, 16, 16, 14, 16, 14, 16, 13, 16, 16, 16, 14, 16, 14, 14, 9, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 14, 10, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 16, 14, 16, 15, 14, 9, + 16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 16, 13, 16, 15, 15, 8, + 14, 16, 16, 16, 14, 14, 16, 14, 16, 16, 16, 15, 13, 13, 14, 10, + 16, 16, 16, 16, 15, 13, 16, 13, 16, 16, 16, 16, 16, 13, 14, 10, + 16, 16, 16, 16, 16, 11, 16, 12, 16, 16, 16, 16, 16, 12, 16, 9, + 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 14, 14, 10, + 16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 16, 15, 16, 13, 14, 9, + 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16, 13, 14, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 11, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14, 9, + 16, 16, 16, 14, 16, 15, 16, 11, 16, 16, 16, 14, 16, 14, 14, 8, + 12, 13, 13, 13, 13, 13, 14, 12, 12, 13, 12, 12, 12, 12, 12, 8, + 14, 14, 16, 14, 15, 14, 16, 13, 14, 15, 14, 13, 14, 13, 13, 9, + 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 16, 14, 16, 14, 16, 10, + 14, 15, 14, 14, 15, 14, 15, 13, 14, 14, 13, 12, 13, 13, 13, 9, + 15, 16, 15, 14, 16, 16, 16, 13, 15, 16, 14, 12, 14, 13, 13, 8, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 16, 13, 16, 14, 14, 9, + 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 13, 13, 16, 16, 14, 10, + 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 15, 13, 16, 14, 14, 9, + 16, 16, 16, 12, 16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 15, 8, + 13, 14, 14, 14, 14, 14, 16, 13, 13, 14, 14, 13, 12, 12, 12, 8, + 16, 16, 16, 14, 15, 14, 16, 13, 15, 16, 14, 13, 13, 12, 13, 8, + 16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 14, 16, 13, 14, 9, + 15, 16, 16, 15, 16, 15, 16, 13, 14, 16, 14, 13, 13, 13, 12, 8, + 16, 16, 16, 14, 16, 14, 15, 12, 15, 15, 14, 12, 13, 12, 12, 7, + 16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 16, 13, 16, 13, 13, 7, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 14, 14, 16, 14, 13, 9, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 14, 12, 16, 13, 12, 7, + 16, 16, 16, 12, 16, 16, 16, 11, 16, 16, 15, 12, 16, 13, 13, 6, + 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 13, 13, 14, 10, + 16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 14, 13, 14, 9, + 16, 16, 16, 16, 16, 13, 16, 13, 16, 16, 16, 16, 16, 12, 14, 8, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 14, 13, 13, 9, + 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 13, 14, 12, 12, 7, + 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 13, 14, 12, 13, 6, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14, 9, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 13, 15, 13, 12, 7, + 16, 16, 16, 13, 16, 14, 16, 11, 16, 16, 16, 12, 16, 12, 12, 5, + 14, 16, 15, 16, 16, 16, 16, 15, 14, 15, 14, 14, 13, 14, 13, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, 16, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, 14, 15, 14, 13, 10, + 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14, 13, 16, 14, 14, 9, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 15, 9, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 13, 16, 16, 13, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 16, 16, 13, 9, + 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 15, 12, 16, 16, 14, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 15, 14, 13, 13, 13, 9, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 14, 13, 13, 9, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 15, 9, + 16, 16, 16, 16, 16, 16, 16, 15, 15, 16, 14, 14, 14, 13, 13, 9, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 14, 12, 13, 12, 12, 7, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 13, 16, 13, 13, 7, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 16, 14, 13, 9, + 16, 16, 16, 15, 16, 16, 16, 13, 16, 16, 13, 12, 14, 13, 12, 6, + 16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 14, 10, 15, 12, 12, 5, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 13, 13, 9, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 13, 12, 13, 8, + 16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 15, 12, 14, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 13, 13, 13, 8, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 15, 13, 12, 11, 12, 6, + 16, 16, 16, 15, 16, 14, 16, 12, 16, 16, 16, 12, 13, 10, 12, 5, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 13, 14, 12, 8, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 13, 12, 13, 12, 10, 5, + 16, 16, 16, 13, 16, 13, 16, 10, 16, 16, 13, 10, 13, 10, 10, 1, + }, + { + 2, 7, 7, 8, 7, 8, 9, 8, 7, 9, 8, 8, 8, 8, 9, 7, + 6, 9, 10, 10, 10, 10, 11, 10, 10, 11, 11, 11, 10, 11, 11, 9, + 9, 11, 12, 12, 12, 13, 14, 13, 13, 14, 14, 13, 13, 13, 14, 11, + 6, 10, 9, 10, 10, 11, 11, 11, 10, 11, 10, 11, 11, 11, 11, 9, + 6, 9, 10, 10, 10, 11, 12, 11, 10, 12, 11, 11, 11, 11, 11, 8, + 9, 11, 12, 12, 12, 13, 13, 13, 12, 14, 14, 13, 13, 13, 13, 10, + 9, 13, 11, 13, 13, 14, 14, 13, 13, 14, 13, 13, 14, 14, 14, 12, + 9, 12, 12, 12, 12, 14, 14, 13, 13, 14, 13, 13, 13, 14, 13, 11, + 8, 12, 12, 11, 12, 14, 14, 12, 13, 14, 14, 13, 13, 13, 14, 11, + 6, 10, 10, 11, 9, 10, 12, 11, 10, 12, 11, 11, 10, 11, 11, 9, + 7, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, 11, 11, 11, 9, + 9, 12, 13, 13, 12, 12, 14, 13, 13, 14, 14, 13, 14, 13, 14, 11, + 8, 11, 11, 12, 11, 12, 12, 12, 11, 13, 12, 12, 12, 12, 12, 10, + 7, 10, 10, 11, 10, 11, 12, 11, 10, 12, 11, 11, 11, 11, 11, 8, + 9, 11, 12, 12, 12, 12, 13, 12, 12, 13, 13, 12, 13, 12, 13, 10, + 10, 13, 13, 14, 14, 14, 15, 14, 14, 15, 14, 15, 14, 14, 14, 12, + 9, 12, 12, 13, 12, 13, 14, 13, 12, 13, 13, 12, 13, 13, 13, 10, + 9, 12, 12, 12, 12, 13, 14, 12, 12, 14, 13, 12, 13, 13, 13, 10, + 9, 12, 13, 13, 11, 13, 14, 13, 13, 14, 14, 14, 12, 13, 13, 11, + 10, 12, 13, 13, 12, 12, 14, 13, 13, 14, 14, 14, 13, 13, 14, 11, + 10, 13, 14, 14, 13, 12, 15, 13, 14, 14, 14, 14, 15, 13, 14, 11, + 11, 14, 14, 14, 13, 14, 15, 14, 14, 15, 15, 14, 13, 14, 14, 12, + 10, 13, 12, 13, 12, 12, 14, 13, 13, 14, 13, 13, 13, 13, 13, 10, + 10, 12, 13, 13, 13, 12, 14, 12, 13, 14, 14, 13, 13, 13, 13, 10, + 13, 15, 16, 16, 15, 15, 16, 16, 15, 16, 15, 16, 16, 16, 16, 14, + 11, 14, 14, 14, 14, 14, 15, 14, 14, 15, 15, 14, 14, 14, 15, 11, + 10, 13, 13, 13, 13, 13, 14, 12, 13, 14, 14, 13, 13, 13, 13, 10, + 6, 10, 10, 11, 10, 11, 12, 11, 10, 12, 10, 11, 10, 11, 11, 9, + 8, 11, 11, 12, 11, 12, 13, 12, 11, 12, 12, 12, 12, 12, 12, 10, + 11, 13, 14, 14, 13, 14, 15, 14, 13, 15, 15, 14, 14, 14, 15, 12, + 7, 11, 10, 12, 11, 12, 12, 12, 11, 12, 11, 12, 11, 12, 12, 10, + 7, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, 11, 11, 11, 9, + 10, 12, 13, 13, 12, 13, 14, 13, 13, 14, 13, 13, 13, 13, 13, 10, + 10, 13, 12, 14, 13, 14, 14, 14, 13, 14, 12, 14, 15, 14, 14, 11, + 10, 12, 12, 12, 12, 13, 14, 13, 13, 14, 13, 12, 13, 13, 13, 10, + 9, 12, 13, 13, 13, 14, 14, 13, 13, 14, 14, 13, 13, 13, 13, 10, + 7, 10, 10, 11, 10, 11, 12, 11, 10, 12, 12, 11, 9, 11, 11, 9, + 7, 10, 11, 11, 10, 11, 12, 11, 10, 12, 12, 11, 11, 11, 11, 9, + 10, 12, 13, 13, 13, 13, 15, 13, 13, 14, 13, 13, 13, 13, 13, 10, + 8, 11, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 11, 12, 11, 9, + 6, 9, 9, 10, 9, 10, 10, 10, 9, 11, 10, 10, 9, 10, 10, 7, + 8, 10, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 11, 11, 11, 8, + 10, 13, 13, 13, 13, 14, 14, 13, 13, 14, 13, 13, 13, 13, 13, 11, + 8, 11, 11, 11, 11, 12, 12, 11, 11, 12, 11, 11, 11, 11, 11, 8, + 8, 11, 11, 11, 11, 12, 12, 10, 11, 12, 12, 11, 11, 11, 11, 8, + 10, 13, 13, 13, 12, 13, 14, 13, 12, 14, 14, 14, 10, 13, 13, 11, + 10, 12, 12, 13, 12, 13, 14, 12, 12, 13, 13, 13, 12, 12, 13, 10, + 11, 13, 14, 14, 13, 13, 14, 13, 13, 15, 14, 13, 13, 13, 13, 10, + 10, 12, 13, 13, 12, 13, 14, 13, 13, 14, 14, 13, 12, 13, 13, 11, + 8, 11, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 11, 11, 11, 8, + 9, 11, 12, 12, 11, 11, 12, 11, 12, 12, 12, 11, 12, 11, 11, 8, + 12, 15, 14, 14, 14, 15, 15, 14, 14, 15, 15, 14, 14, 14, 15, 12, + 10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 13, 12, 12, 12, 12, 9, + 9, 11, 11, 11, 11, 11, 12, 10, 11, 12, 12, 11, 11, 11, 11, 7, + 10, 13, 13, 13, 13, 14, 15, 14, 13, 14, 14, 14, 12, 14, 15, 12, + 11, 14, 14, 14, 14, 15, 15, 14, 14, 15, 15, 15, 14, 15, 15, 12, + 13, 16, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 14, + 10, 13, 13, 14, 13, 15, 14, 14, 13, 15, 13, 14, 14, 14, 14, 12, + 10, 13, 13, 13, 13, 13, 14, 13, 13, 14, 13, 13, 13, 13, 14, 11, + 12, 14, 14, 14, 14, 15, 15, 14, 14, 15, 15, 14, 15, 14, 14, 12, + 11, 14, 14, 15, 14, 15, 15, 14, 14, 15, 12, 14, 15, 16, 15, 12, + 11, 13, 13, 14, 13, 14, 14, 14, 14, 14, 13, 13, 14, 14, 14, 11, + 11, 14, 14, 14, 14, 15, 15, 14, 14, 16, 14, 13, 14, 14, 14, 11, + 10, 13, 13, 13, 12, 14, 14, 14, 12, 15, 14, 14, 11, 13, 13, 12, + 10, 12, 13, 14, 12, 13, 14, 13, 13, 14, 14, 13, 12, 13, 13, 11, + 12, 14, 14, 15, 14, 15, 16, 15, 15, 15, 15, 15, 14, 14, 15, 12, + 10, 13, 13, 13, 12, 13, 14, 13, 13, 14, 13, 13, 12, 13, 13, 11, + 9, 11, 11, 12, 11, 12, 12, 11, 11, 12, 12, 11, 11, 11, 11, 9, + 10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 13, 12, 13, 12, 12, 9, + 11, 13, 13, 15, 14, 14, 15, 14, 14, 15, 14, 14, 14, 14, 14, 11, + 10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 11, 11, 12, 12, 12, 8, + 9, 12, 12, 11, 12, 12, 13, 11, 12, 12, 12, 11, 12, 11, 11, 8, + 10, 13, 13, 14, 12, 14, 15, 14, 13, 15, 15, 14, 10, 13, 13, 11, + 11, 13, 14, 13, 13, 14, 14, 13, 13, 14, 14, 14, 11, 13, 13, 11, + 12, 14, 14, 14, 14, 14, 15, 14, 15, 16, 15, 14, 13, 13, 14, 11, + 11, 14, 13, 14, 13, 14, 15, 14, 13, 15, 14, 14, 11, 13, 13, 11, + 9, 12, 12, 12, 11, 12, 13, 11, 12, 13, 12, 11, 10, 11, 11, 8, + 10, 12, 12, 12, 12, 12, 13, 11, 12, 12, 12, 11, 11, 11, 11, 8, + 12, 15, 14, 15, 14, 15, 16, 15, 15, 15, 15, 14, 14, 14, 14, 12, + 10, 12, 12, 12, 12, 12, 13, 11, 12, 13, 12, 11, 11, 11, 11, 8, + 8, 10, 10, 10, 10, 10, 11, 9, 10, 11, 10, 9, 10, 9, 9, 5, + }, + }, + { + { + 12, 12, 11, 9, 11, 10, 11, 9, 11, 11, 10, 9, 9, 8, 9, 5, + 14, 13, 14, 11, 14, 11, 13, 10, 14, 13, 12, 10, 12, 10, 11, 6, + 16, 13, 16, 12, 16, 12, 16, 11, 16, 14, 16, 12, 15, 12, 13, 8, + 14, 14, 12, 11, 14, 12, 13, 10, 13, 13, 11, 10, 12, 11, 10, 6, + 16, 15, 14, 11, 16, 13, 14, 10, 15, 14, 13, 10, 13, 11, 11, 7, + 16, 16, 16, 11, 16, 14, 16, 11, 16, 16, 15, 12, 15, 13, 13, 8, + 16, 16, 13, 12, 16, 16, 15, 12, 16, 16, 12, 11, 15, 13, 12, 8, + 16, 16, 14, 11, 16, 16, 16, 11, 16, 16, 14, 11, 15, 14, 13, 8, + 16, 16, 15, 10, 16, 16, 16, 10, 16, 16, 15, 11, 16, 14, 14, 8, + 14, 14, 14, 12, 13, 11, 13, 10, 13, 13, 12, 11, 11, 10, 10, 6, + 16, 15, 16, 13, 13, 11, 14, 11, 15, 14, 13, 11, 12, 10, 11, 7, + 16, 15, 16, 14, 16, 11, 16, 11, 16, 16, 16, 13, 16, 12, 13, 8, + 16, 16, 14, 13, 15, 13, 14, 11, 14, 15, 13, 11, 13, 11, 11, 7, + 16, 16, 15, 13, 15, 13, 14, 11, 16, 15, 14, 11, 13, 11, 11, 7, + 16, 16, 16, 13, 16, 13, 16, 11, 16, 16, 16, 12, 16, 12, 13, 8, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 14, 13, 15, 14, 13, 9, + 16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 14, 12, 15, 13, 13, 8, + 16, 16, 16, 12, 16, 16, 16, 11, 16, 16, 15, 12, 16, 13, 13, 7, + 16, 16, 16, 16, 13, 12, 16, 12, 16, 16, 14, 13, 12, 11, 12, 8, + 16, 16, 16, 15, 14, 11, 16, 11, 16, 16, 16, 13, 14, 11, 13, 8, + 16, 16, 16, 16, 15, 10, 16, 11, 16, 16, 16, 14, 15, 11, 13, 8, + 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 14, 14, 14, 12, 13, 9, + 16, 16, 16, 15, 16, 13, 16, 12, 16, 16, 16, 13, 14, 12, 13, 8, + 16, 16, 16, 14, 16, 12, 16, 11, 16, 16, 16, 13, 15, 12, 13, 7, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 16, 14, 13, 9, + 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 14, 16, 13, 13, 8, + 16, 16, 16, 14, 16, 14, 16, 10, 16, 16, 16, 13, 16, 13, 13, 7, + 14, 14, 13, 12, 13, 12, 13, 11, 12, 13, 11, 10, 11, 10, 10, 6, + 16, 16, 15, 13, 16, 13, 15, 11, 14, 14, 13, 11, 13, 11, 11, 7, + 16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 16, 13, 16, 13, 14, 9, + 16, 16, 13, 13, 15, 14, 14, 11, 13, 14, 11, 11, 12, 11, 11, 7, + 16, 16, 15, 12, 16, 14, 15, 11, 14, 14, 12, 11, 13, 11, 11, 7, + 16, 16, 16, 13, 16, 14, 16, 12, 16, 16, 14, 12, 16, 13, 13, 8, + 16, 16, 14, 14, 16, 16, 16, 13, 16, 16, 12, 11, 15, 13, 12, 8, + 16, 16, 15, 13, 16, 16, 16, 12, 16, 16, 13, 11, 16, 13, 12, 8, + 16, 16, 16, 11, 16, 16, 16, 11, 16, 16, 14, 11, 16, 14, 13, 7, + 16, 16, 15, 13, 14, 13, 14, 11, 14, 14, 12, 11, 11, 10, 11, 7, + 16, 16, 16, 13, 14, 12, 15, 11, 15, 14, 13, 11, 12, 11, 11, 7, + 16, 16, 16, 14, 16, 13, 16, 12, 16, 16, 16, 13, 14, 12, 13, 8, + 16, 16, 15, 13, 15, 14, 14, 12, 14, 14, 12, 11, 12, 11, 11, 7, + 16, 16, 14, 12, 15, 13, 14, 11, 15, 14, 13, 11, 12, 11, 11, 6, + 16, 16, 16, 13, 16, 13, 16, 11, 16, 15, 14, 11, 14, 11, 12, 6, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 13, 12, 14, 13, 12, 8, + 16, 16, 15, 13, 16, 14, 15, 11, 16, 16, 13, 11, 14, 12, 11, 6, + 16, 16, 16, 12, 16, 14, 15, 11, 16, 16, 13, 10, 14, 12, 12, 6, + 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 14, 13, 12, 11, 12, 8, + 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 15, 13, 13, 11, 12, 8, + 16, 16, 16, 15, 16, 12, 16, 12, 16, 16, 16, 14, 14, 11, 13, 7, + 16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 14, 13, 13, 12, 12, 8, + 16, 16, 16, 14, 15, 13, 15, 11, 16, 15, 14, 12, 13, 11, 11, 6, + 16, 16, 16, 14, 16, 12, 15, 11, 16, 16, 15, 12, 14, 11, 12, 6, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 15, 13, 14, 13, 12, 8, + 16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 14, 12, 13, 12, 11, 6, + 16, 16, 16, 13, 16, 13, 15, 10, 16, 16, 14, 11, 14, 11, 11, 5, + 16, 16, 15, 14, 16, 16, 16, 13, 14, 14, 12, 12, 12, 12, 12, 8, + 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, 13, 14, 13, 13, 9, + 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 16, 13, 15, 9, + 16, 16, 14, 15, 16, 16, 16, 14, 14, 16, 12, 12, 13, 13, 12, 8, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 15, 13, 12, 14, 12, 12, 8, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 14, 12, 16, 13, 13, 8, + 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 11, 11, 15, 14, 12, 8, + 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 12, 11, 15, 13, 12, 8, + 16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 13, 10, 16, 13, 12, 7, + 16, 16, 16, 16, 16, 15, 16, 13, 14, 16, 13, 13, 12, 12, 12, 8, + 16, 16, 16, 15, 16, 14, 16, 13, 16, 16, 14, 13, 13, 12, 12, 8, + 16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 16, 13, 15, 12, 14, 8, + 16, 16, 16, 15, 16, 16, 16, 13, 14, 16, 13, 12, 12, 12, 11, 8, + 16, 16, 16, 14, 16, 14, 16, 12, 14, 14, 13, 11, 13, 11, 11, 6, + 16, 16, 16, 14, 16, 14, 16, 12, 16, 15, 14, 11, 14, 11, 12, 6, + 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 12, 12, 14, 13, 11, 8, + 16, 16, 15, 14, 16, 16, 16, 12, 16, 15, 12, 11, 13, 12, 11, 6, + 16, 16, 16, 13, 16, 14, 16, 11, 16, 14, 13, 10, 14, 11, 11, 5, + 16, 16, 16, 16, 16, 16, 16, 14, 14, 16, 15, 13, 11, 11, 11, 8, + 16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 16, 13, 12, 11, 12, 7, + 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 13, 13, 11, 13, 7, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 14, 13, 12, 12, 11, 7, + 16, 16, 16, 15, 16, 14, 15, 12, 16, 14, 13, 12, 12, 11, 11, 6, + 16, 16, 16, 14, 16, 13, 15, 11, 16, 14, 14, 11, 13, 10, 11, 5, + 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 13, 12, 12, 12, 11, 7, + 16, 16, 16, 14, 16, 14, 15, 12, 16, 15, 12, 11, 12, 11, 10, 5, + 16, 16, 16, 13, 16, 13, 14, 10, 16, 14, 12, 9, 12, 10, 9, 3, + }, + { + 2, 6, 6, 7, 6, 7, 8, 7, 7, 8, 7, 8, 7, 8, 8, 5, + 5, 8, 9, 9, 9, 9, 12, 10, 10, 11, 10, 10, 10, 11, 11, 8, + 9, 10, 13, 12, 13, 12, 15, 13, 13, 14, 13, 14, 13, 13, 14, 11, + 5, 10, 9, 10, 10, 10, 12, 10, 10, 12, 10, 11, 11, 11, 11, 8, + 6, 9, 10, 9, 10, 11, 12, 10, 10, 12, 11, 11, 10, 11, 11, 8, + 9, 11, 12, 11, 12, 13, 14, 12, 13, 14, 14, 12, 13, 13, 13, 11, + 10, 13, 11, 12, 14, 14, 15, 13, 13, 15, 12, 13, 14, 14, 14, 12, + 9, 12, 12, 12, 13, 13, 15, 13, 13, 14, 13, 13, 14, 13, 15, 11, + 8, 11, 12, 10, 12, 13, 14, 12, 13, 14, 14, 13, 13, 13, 14, 11, + 5, 9, 10, 10, 9, 10, 12, 11, 10, 12, 11, 11, 9, 11, 11, 9, + 6, 10, 10, 11, 10, 10, 12, 11, 11, 12, 11, 11, 11, 11, 11, 9, + 9, 11, 13, 13, 12, 11, 14, 12, 13, 15, 13, 13, 14, 13, 14, 11, + 8, 11, 11, 12, 11, 12, 13, 12, 12, 13, 12, 13, 12, 12, 12, 10, + 7, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, 11, 11, 12, 9, + 9, 12, 12, 12, 12, 12, 14, 12, 13, 14, 13, 13, 13, 13, 13, 11, + 11, 14, 13, 15, 15, 16, 16, 15, 15, 16, 15, 15, 16, 16, 15, 13, + 10, 12, 13, 13, 13, 14, 15, 13, 13, 14, 13, 13, 14, 14, 14, 11, + 9, 12, 12, 12, 13, 13, 14, 12, 13, 14, 14, 13, 13, 13, 14, 11, + 9, 13, 13, 13, 11, 12, 15, 13, 13, 15, 14, 14, 11, 13, 14, 11, + 10, 13, 13, 13, 12, 12, 15, 13, 13, 15, 14, 14, 13, 13, 14, 11, + 10, 12, 13, 13, 12, 11, 14, 12, 13, 15, 13, 13, 13, 13, 14, 11, + 11, 14, 15, 15, 13, 14, 16, 14, 14, 16, 16, 14, 14, 15, 15, 13, + 10, 13, 13, 13, 12, 13, 14, 13, 13, 14, 14, 14, 13, 13, 14, 11, + 10, 12, 13, 13, 13, 12, 14, 13, 13, 14, 14, 13, 13, 13, 13, 11, + 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 12, 15, 15, 15, 14, 15, 16, 14, 15, 16, 16, 15, 16, 15, 15, 13, + 10, 12, 12, 12, 13, 13, 14, 12, 13, 14, 13, 13, 13, 13, 13, 11, + 6, 10, 10, 11, 10, 11, 12, 11, 10, 12, 11, 11, 10, 11, 11, 9, + 8, 11, 12, 12, 12, 12, 13, 12, 12, 13, 12, 13, 12, 13, 13, 10, + 11, 13, 15, 14, 15, 14, 16, 14, 15, 16, 16, 14, 15, 15, 15, 13, + 7, 11, 10, 12, 11, 11, 13, 11, 11, 13, 10, 11, 12, 12, 12, 10, + 7, 11, 11, 11, 11, 11, 13, 11, 11, 13, 11, 12, 12, 12, 12, 9, + 10, 12, 13, 13, 13, 13, 15, 13, 14, 15, 14, 14, 14, 14, 15, 11, + 10, 13, 12, 14, 14, 14, 15, 13, 13, 15, 12, 13, 15, 15, 14, 12, + 10, 13, 12, 12, 13, 13, 15, 14, 13, 15, 13, 13, 14, 14, 14, 11, + 10, 13, 13, 12, 13, 14, 15, 13, 13, 15, 13, 13, 14, 14, 14, 11, + 7, 10, 11, 11, 10, 11, 12, 11, 10, 12, 12, 12, 9, 11, 12, 9, + 7, 11, 11, 11, 11, 11, 13, 11, 11, 13, 12, 12, 11, 12, 12, 9, + 10, 12, 14, 13, 13, 13, 16, 13, 14, 16, 14, 14, 13, 13, 14, 11, + 8, 11, 11, 12, 11, 12, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10, + 6, 9, 9, 10, 9, 10, 11, 10, 10, 11, 10, 10, 10, 10, 10, 8, + 8, 11, 11, 11, 12, 11, 13, 11, 12, 13, 12, 12, 12, 12, 12, 10, + 11, 14, 13, 14, 14, 14, 16, 14, 14, 16, 14, 14, 15, 15, 14, 12, + 9, 12, 11, 12, 12, 12, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10, + 8, 11, 11, 11, 11, 11, 13, 11, 12, 12, 12, 12, 12, 12, 12, 9, + 10, 13, 14, 13, 11, 13, 14, 14, 13, 15, 15, 14, 10, 13, 14, 11, + 10, 13, 13, 13, 12, 13, 14, 13, 13, 14, 14, 14, 13, 13, 13, 11, + 10, 13, 14, 13, 13, 12, 15, 13, 14, 15, 14, 14, 14, 13, 14, 12, + 11, 14, 14, 14, 13, 13, 15, 14, 14, 15, 14, 15, 13, 14, 14, 12, + 9, 11, 12, 12, 11, 11, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10, + 9, 11, 12, 12, 12, 11, 13, 11, 12, 13, 12, 12, 12, 12, 12, 10, + 13, 15, 15, 16, 15, 16, 16, 15, 16, 16, 16, 15, 15, 15, 16, 14, + 10, 13, 13, 13, 13, 13, 14, 13, 13, 14, 13, 13, 13, 13, 13, 11, + 8, 11, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 12, 11, 12, 9, + 11, 14, 14, 15, 14, 15, 15, 14, 13, 15, 14, 15, 12, 14, 15, 13, + 12, 15, 15, 15, 15, 15, 16, 15, 15, 16, 16, 16, 15, 16, 15, 13, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 11, 14, 13, 15, 14, 14, 16, 14, 14, 16, 13, 14, 15, 14, 15, 12, + 11, 14, 13, 14, 14, 14, 16, 15, 14, 16, 14, 14, 15, 15, 15, 12, + 13, 15, 15, 15, 15, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 13, + 11, 14, 13, 14, 14, 14, 15, 14, 14, 16, 12, 14, 16, 16, 14, 12, + 11, 14, 14, 14, 14, 15, 16, 15, 14, 16, 13, 14, 16, 15, 14, 12, + 12, 14, 14, 14, 14, 14, 16, 14, 15, 16, 14, 14, 14, 15, 15, 12, + 11, 14, 14, 14, 13, 14, 16, 15, 13, 16, 15, 15, 11, 14, 14, 12, + 11, 14, 14, 15, 14, 14, 16, 14, 14, 15, 14, 14, 13, 15, 15, 12, + 13, 15, 16, 15, 15, 15, 16, 15, 16, 16, 16, 16, 15, 15, 16, 13, + 11, 14, 14, 14, 14, 14, 15, 14, 14, 16, 14, 14, 14, 15, 14, 12, + 9, 12, 12, 12, 12, 12, 13, 12, 12, 13, 12, 13, 12, 12, 12, 10, + 11, 13, 13, 13, 13, 13, 14, 13, 13, 14, 13, 14, 13, 13, 14, 11, + 12, 15, 14, 15, 15, 15, 16, 15, 14, 16, 14, 14, 16, 16, 14, 13, + 10, 12, 12, 12, 12, 12, 14, 12, 13, 13, 12, 12, 13, 13, 13, 10, + 10, 12, 12, 12, 12, 12, 14, 12, 12, 13, 12, 12, 12, 12, 12, 10, + 10, 14, 14, 14, 12, 14, 16, 14, 13, 16, 16, 16, 10, 13, 14, 12, + 11, 14, 14, 14, 13, 14, 16, 14, 14, 16, 15, 14, 12, 13, 14, 12, + 12, 14, 14, 14, 14, 14, 16, 14, 14, 16, 15, 15, 14, 14, 15, 12, + 12, 14, 15, 15, 14, 15, 16, 14, 15, 15, 15, 15, 13, 15, 14, 12, + 9, 12, 12, 12, 12, 13, 13, 12, 12, 13, 13, 12, 11, 12, 12, 10, + 10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10, + 13, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 15, 16, 15, 13, + 10, 12, 12, 13, 12, 13, 13, 12, 13, 14, 13, 13, 12, 13, 13, 10, + 7, 10, 10, 10, 10, 10, 11, 10, 10, 11, 10, 10, 10, 10, 10, 7, + }, + }, + { + { + 10, 10, 9, 8, 9, 8, 9, 7, 9, 9, 8, 7, 8, 7, 7, 4, + 13, 11, 12, 9, 12, 9, 12, 9, 12, 11, 11, 9, 10, 9, 9, 6, + 15, 12, 15, 11, 14, 10, 14, 10, 14, 13, 13, 11, 13, 11, 12, 7, + 13, 12, 11, 9, 12, 11, 12, 9, 12, 12, 10, 9, 10, 10, 9, 6, + 14, 13, 12, 10, 13, 12, 13, 9, 13, 12, 11, 10, 12, 11, 10, 6, + 16, 14, 14, 10, 15, 13, 14, 10, 15, 15, 14, 11, 14, 12, 12, 8, + 15, 14, 12, 11, 15, 14, 13, 11, 14, 14, 11, 10, 13, 12, 11, 8, + 15, 16, 13, 11, 16, 14, 14, 11, 15, 15, 12, 10, 14, 13, 12, 8, + 16, 15, 14, 10, 16, 14, 14, 10, 16, 15, 14, 10, 14, 13, 12, 7, + 13, 12, 12, 11, 11, 9, 12, 9, 12, 12, 11, 10, 10, 9, 9, 6, + 13, 13, 14, 12, 12, 10, 12, 10, 14, 13, 12, 11, 11, 10, 10, 7, + 16, 14, 16, 13, 14, 11, 15, 10, 16, 15, 14, 12, 14, 11, 12, 8, + 14, 14, 13, 12, 13, 12, 13, 10, 13, 13, 12, 11, 11, 10, 10, 7, + 15, 14, 14, 12, 14, 12, 13, 10, 14, 13, 12, 11, 12, 11, 11, 7, + 16, 15, 16, 13, 15, 13, 15, 10, 16, 15, 14, 12, 14, 12, 12, 7, + 15, 16, 14, 13, 16, 14, 14, 12, 15, 15, 12, 12, 13, 12, 12, 8, + 16, 16, 14, 13, 16, 14, 14, 11, 15, 15, 14, 11, 14, 12, 12, 8, + 16, 16, 15, 12, 16, 14, 15, 10, 16, 16, 13, 12, 14, 13, 12, 7, + 14, 14, 14, 13, 13, 11, 13, 11, 14, 14, 13, 12, 11, 10, 11, 8, + 16, 15, 16, 13, 13, 11, 14, 11, 15, 14, 14, 13, 12, 11, 12, 8, + 15, 15, 16, 14, 14, 10, 14, 10, 16, 15, 15, 13, 14, 10, 12, 8, + 16, 16, 16, 14, 15, 13, 14, 12, 15, 15, 13, 13, 13, 12, 12, 8, + 16, 16, 16, 14, 15, 13, 14, 11, 16, 16, 14, 13, 13, 12, 12, 8, + 16, 16, 16, 14, 16, 12, 15, 11, 16, 15, 15, 13, 14, 12, 12, 8, + 16, 16, 16, 16, 16, 15, 15, 13, 16, 16, 14, 13, 14, 13, 12, 9, + 16, 16, 16, 14, 16, 15, 15, 11, 16, 16, 14, 13, 15, 13, 12, 8, + 16, 16, 16, 14, 16, 14, 14, 10, 16, 16, 15, 13, 14, 12, 12, 7, + 12, 12, 12, 11, 12, 11, 12, 10, 11, 11, 10, 9, 9, 9, 9, 6, + 14, 13, 14, 12, 13, 12, 13, 10, 13, 13, 12, 10, 12, 10, 11, 7, + 16, 14, 16, 13, 15, 13, 16, 12, 15, 14, 14, 12, 14, 12, 13, 8, + 14, 14, 13, 11, 14, 12, 13, 11, 12, 12, 10, 10, 11, 10, 10, 7, + 14, 14, 13, 12, 14, 12, 13, 11, 13, 13, 12, 10, 12, 11, 10, 7, + 16, 15, 15, 12, 16, 14, 15, 11, 16, 14, 13, 11, 14, 12, 12, 8, + 16, 16, 13, 13, 16, 15, 14, 12, 14, 14, 11, 11, 13, 12, 11, 8, + 16, 16, 14, 12, 16, 14, 14, 12, 15, 14, 12, 11, 14, 12, 12, 8, + 16, 15, 14, 11, 16, 15, 15, 11, 16, 15, 13, 11, 14, 13, 12, 8, + 14, 13, 13, 12, 13, 11, 13, 10, 12, 13, 11, 10, 10, 10, 10, 7, + 15, 14, 14, 13, 13, 12, 13, 11, 14, 13, 12, 11, 12, 10, 11, 7, + 16, 15, 16, 14, 15, 12, 15, 11, 16, 14, 14, 12, 14, 11, 12, 8, + 14, 15, 13, 12, 14, 13, 13, 11, 13, 13, 11, 11, 11, 10, 10, 7, + 14, 14, 14, 12, 14, 13, 13, 10, 14, 13, 12, 10, 12, 10, 10, 6, + 16, 15, 15, 13, 16, 13, 15, 11, 15, 14, 13, 11, 13, 11, 11, 7, + 16, 16, 14, 13, 16, 15, 14, 12, 15, 15, 12, 11, 13, 12, 11, 8, + 16, 16, 14, 13, 16, 14, 14, 11, 15, 14, 12, 11, 13, 12, 11, 7, + 16, 16, 15, 12, 16, 14, 14, 11, 15, 15, 13, 11, 14, 12, 11, 6, + 16, 15, 15, 14, 14, 12, 14, 12, 13, 14, 13, 12, 11, 11, 11, 8, + 16, 16, 16, 14, 14, 12, 15, 12, 15, 14, 14, 12, 12, 11, 12, 8, + 16, 16, 16, 15, 14, 12, 15, 12, 16, 15, 14, 13, 13, 11, 12, 8, + 16, 16, 16, 15, 15, 14, 15, 12, 14, 14, 13, 12, 12, 11, 11, 8, + 16, 16, 15, 14, 14, 12, 14, 11, 14, 14, 13, 12, 12, 11, 11, 7, + 16, 16, 16, 14, 15, 12, 14, 11, 15, 15, 14, 12, 13, 11, 12, 7, + 16, 16, 16, 16, 16, 15, 16, 13, 15, 15, 14, 12, 13, 12, 11, 8, + 16, 16, 16, 14, 15, 14, 14, 12, 16, 15, 13, 12, 13, 12, 11, 7, + 16, 16, 16, 13, 16, 13, 14, 10, 16, 15, 14, 11, 13, 11, 11, 6, + 14, 15, 13, 13, 14, 13, 14, 12, 12, 13, 11, 11, 11, 11, 10, 8, + 16, 16, 15, 13, 16, 14, 16, 13, 14, 14, 13, 12, 13, 12, 12, 8, + 16, 16, 16, 14, 16, 14, 16, 13, 16, 14, 15, 13, 15, 13, 13, 9, + 15, 15, 14, 14, 15, 14, 14, 12, 13, 14, 11, 11, 12, 12, 11, 8, + 15, 16, 15, 13, 15, 14, 14, 12, 14, 14, 12, 11, 13, 12, 12, 8, + 16, 16, 16, 13, 16, 15, 15, 13, 16, 15, 14, 11, 15, 12, 13, 8, + 16, 16, 14, 13, 16, 15, 15, 13, 14, 14, 10, 11, 14, 12, 11, 8, + 16, 16, 15, 13, 16, 16, 15, 13, 15, 14, 12, 11, 14, 13, 12, 8, + 16, 16, 15, 13, 16, 15, 16, 12, 16, 14, 13, 10, 15, 13, 12, 7, + 15, 15, 15, 14, 14, 14, 15, 12, 13, 14, 12, 12, 11, 11, 11, 8, + 16, 15, 16, 14, 15, 13, 15, 12, 14, 14, 13, 12, 12, 11, 12, 8, + 16, 16, 16, 15, 16, 14, 16, 13, 16, 15, 14, 12, 14, 11, 13, 8, + 16, 16, 15, 14, 16, 14, 15, 13, 14, 14, 12, 11, 12, 11, 11, 8, + 15, 16, 15, 14, 15, 14, 14, 12, 14, 13, 12, 11, 12, 11, 11, 7, + 16, 16, 16, 14, 16, 13, 16, 12, 15, 14, 13, 11, 13, 11, 12, 7, + 16, 16, 15, 14, 16, 15, 15, 13, 14, 15, 11, 11, 13, 12, 11, 8, + 16, 16, 15, 13, 16, 14, 15, 12, 15, 14, 12, 11, 13, 11, 11, 7, + 16, 16, 15, 13, 16, 14, 16, 12, 15, 14, 13, 10, 13, 11, 11, 6, + 16, 16, 16, 14, 14, 14, 15, 13, 14, 14, 14, 12, 11, 11, 11, 8, + 16, 16, 16, 14, 15, 14, 16, 13, 15, 14, 14, 13, 12, 11, 11, 7, + 16, 16, 16, 16, 15, 13, 16, 12, 15, 15, 14, 12, 13, 10, 12, 7, + 16, 16, 16, 14, 15, 15, 14, 13, 14, 14, 13, 12, 12, 11, 11, 8, + 16, 15, 16, 14, 16, 13, 15, 12, 14, 14, 13, 12, 12, 10, 10, 6, + 16, 15, 16, 14, 16, 13, 16, 11, 16, 14, 13, 11, 13, 10, 11, 6, + 16, 16, 16, 15, 16, 16, 15, 13, 14, 16, 12, 12, 12, 12, 10, 7, + 16, 16, 16, 14, 16, 14, 14, 12, 15, 15, 12, 11, 12, 11, 10, 6, + 16, 16, 16, 13, 16, 13, 15, 10, 15, 14, 13, 10, 13, 10, 10, 4, + }, + { + 1, 6, 6, 7, 6, 7, 9, 8, 7, 9, 7, 8, 7, 8, 8, 6, + 6, 9, 10, 10, 10, 10, 12, 11, 10, 12, 11, 11, 11, 11, 12, 9, + 9, 10, 13, 11, 13, 12, 14, 13, 14, 14, 14, 14, 14, 14, 14, 12, + 6, 10, 9, 10, 10, 11, 13, 11, 11, 13, 10, 12, 11, 12, 12, 9, + 6, 10, 10, 10, 10, 11, 13, 11, 11, 13, 12, 12, 11, 12, 12, 9, + 9, 11, 13, 12, 13, 14, 15, 13, 14, 16, 14, 14, 14, 14, 15, 12, + 10, 13, 11, 13, 14, 14, 16, 14, 14, 15, 13, 14, 15, 15, 16, 12, + 9, 13, 12, 12, 14, 14, 16, 14, 14, 15, 14, 14, 15, 15, 15, 12, + 8, 11, 12, 11, 13, 14, 15, 13, 13, 15, 14, 14, 13, 15, 15, 11, + 6, 10, 10, 11, 9, 10, 13, 11, 10, 13, 11, 12, 10, 12, 12, 9, + 6, 10, 10, 11, 11, 10, 13, 11, 11, 13, 11, 12, 12, 12, 13, 10, + 9, 12, 13, 13, 13, 12, 16, 13, 14, 15, 14, 14, 15, 14, 15, 12, + 8, 12, 12, 13, 12, 13, 15, 14, 13, 15, 13, 14, 13, 13, 14, 11, + 7, 11, 11, 12, 11, 12, 13, 12, 12, 13, 12, 13, 12, 13, 13, 10, + 9, 12, 13, 13, 13, 13, 16, 13, 13, 15, 14, 14, 14, 15, 15, 12, + 11, 15, 14, 15, 15, 16, 16, 16, 15, 16, 15, 16, 16, 16, 16, 14, + 10, 13, 13, 14, 14, 14, 16, 15, 14, 16, 15, 15, 15, 15, 16, 13, + 9, 12, 13, 13, 13, 14, 16, 14, 13, 15, 14, 14, 14, 16, 15, 12, + 10, 13, 14, 14, 11, 13, 16, 14, 14, 16, 15, 15, 12, 14, 15, 12, + 10, 13, 14, 14, 12, 12, 16, 15, 14, 16, 15, 15, 14, 14, 16, 12, + 9, 12, 13, 14, 13, 11, 16, 13, 14, 15, 13, 14, 14, 14, 15, 12, + 11, 15, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 13, 14, 14, 13, 14, 16, 15, 14, 16, 16, 16, 14, 15, 16, 13, + 10, 13, 13, 14, 13, 13, 16, 13, 13, 14, 14, 15, 15, 14, 15, 13, + 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 12, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 12, 13, 14, 13, 13, 14, 13, 13, 14, 13, 14, 14, 14, 15, 12, + 6, 10, 11, 11, 10, 11, 13, 12, 11, 13, 11, 12, 11, 12, 12, 10, + 8, 12, 13, 13, 12, 13, 14, 14, 13, 15, 14, 14, 14, 14, 15, 12, + 12, 14, 16, 15, 15, 15, 16, 15, 16, 16, 16, 16, 16, 16, 16, 14, + 7, 11, 11, 12, 12, 12, 14, 13, 12, 14, 11, 12, 13, 13, 13, 11, + 8, 11, 12, 12, 12, 12, 14, 13, 12, 14, 12, 13, 13, 14, 14, 11, + 11, 13, 14, 14, 14, 14, 16, 15, 15, 16, 15, 15, 16, 16, 16, 13, + 10, 14, 12, 14, 14, 15, 16, 15, 13, 16, 12, 14, 16, 16, 15, 13, + 10, 13, 13, 14, 14, 15, 16, 15, 14, 16, 14, 15, 15, 16, 16, 12, + 10, 13, 14, 13, 14, 14, 16, 15, 14, 16, 15, 15, 14, 16, 16, 13, + 7, 11, 11, 11, 10, 12, 14, 13, 11, 14, 13, 13, 10, 12, 13, 10, + 8, 11, 12, 12, 11, 12, 14, 13, 12, 15, 13, 13, 12, 13, 14, 11, + 11, 13, 14, 14, 14, 14, 16, 15, 14, 16, 15, 16, 16, 16, 16, 14, + 8, 12, 12, 13, 12, 13, 15, 14, 12, 15, 13, 13, 13, 14, 14, 11, + 6, 10, 10, 11, 10, 11, 13, 12, 11, 13, 11, 12, 11, 12, 12, 9, + 9, 12, 13, 13, 13, 13, 14, 13, 13, 15, 14, 14, 14, 14, 14, 12, + 11, 15, 14, 15, 14, 15, 16, 16, 16, 16, 15, 16, 16, 16, 16, 14, + 9, 13, 12, 13, 13, 13, 15, 14, 13, 14, 13, 14, 14, 15, 14, 12, + 9, 12, 12, 12, 12, 13, 14, 13, 13, 14, 13, 13, 13, 13, 14, 11, + 10, 13, 15, 14, 12, 14, 16, 14, 14, 16, 15, 15, 12, 14, 16, 12, + 10, 14, 14, 14, 13, 14, 16, 15, 14, 16, 16, 16, 13, 14, 16, 13, + 11, 13, 14, 14, 14, 13, 16, 14, 14, 16, 15, 15, 15, 15, 16, 13, + 11, 15, 15, 15, 14, 15, 16, 16, 15, 16, 16, 16, 14, 16, 16, 13, + 9, 13, 13, 13, 12, 13, 15, 14, 13, 15, 14, 14, 13, 14, 15, 11, + 9, 12, 12, 13, 12, 12, 14, 13, 13, 14, 13, 14, 14, 14, 14, 11, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 11, 14, 14, 15, 15, 14, 16, 16, 14, 16, 14, 15, 15, 16, 16, 12, + 9, 12, 12, 13, 12, 12, 14, 12, 12, 14, 13, 13, 13, 13, 14, 11, + 11, 14, 14, 16, 14, 16, 16, 16, 13, 16, 14, 16, 14, 16, 16, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 15, 14, 16, 14, 15, 16, 16, 15, 16, 14, 15, 16, 16, 16, 13, + 11, 15, 14, 16, 15, 16, 16, 16, 15, 16, 15, 16, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 11, 14, 13, 14, 15, 14, 16, 15, 14, 16, 12, 14, 16, 16, 15, 13, + 11, 14, 14, 16, 14, 15, 16, 16, 15, 16, 14, 15, 16, 16, 16, 14, + 12, 14, 14, 15, 14, 16, 16, 15, 14, 16, 15, 15, 15, 16, 16, 13, + 11, 14, 15, 15, 13, 15, 16, 16, 14, 16, 16, 16, 12, 15, 15, 13, + 11, 15, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 11, 15, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 10, 13, 13, 14, 14, 14, 16, 15, 14, 16, 14, 15, 14, 14, 15, 12, + 12, 15, 14, 16, 14, 15, 16, 15, 15, 16, 15, 15, 16, 15, 16, 13, + 12, 16, 14, 16, 15, 16, 16, 16, 16, 16, 14, 15, 16, 16, 16, 14, + 10, 13, 13, 14, 14, 13, 16, 14, 13, 16, 13, 14, 15, 15, 15, 12, + 10, 13, 13, 14, 13, 13, 16, 14, 14, 15, 14, 14, 14, 14, 15, 12, + 10, 14, 15, 14, 13, 15, 16, 15, 14, 16, 16, 16, 11, 14, 16, 12, + 11, 14, 14, 16, 14, 15, 16, 15, 15, 16, 16, 16, 13, 15, 16, 13, + 12, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 15, 16, 13, + 12, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 13, + 10, 13, 14, 14, 13, 14, 16, 14, 13, 16, 15, 14, 12, 14, 16, 11, + 10, 13, 13, 14, 13, 14, 16, 14, 14, 15, 14, 14, 13, 14, 14, 11, + 13, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 11, 13, 14, 15, 14, 14, 16, 15, 14, 16, 14, 15, 14, 15, 16, 12, + 8, 11, 11, 11, 11, 12, 13, 12, 11, 13, 11, 12, 11, 12, 12, 9, + }, + }, + { + { + 8, 8, 8, 7, 8, 7, 8, 6, 8, 8, 7, 6, 7, 6, 6, 4, + 11, 10, 11, 9, 11, 9, 11, 8, 11, 10, 10, 9, 10, 8, 9, 6, + 13, 11, 13, 10, 12, 10, 13, 9, 13, 12, 13, 10, 12, 10, 11, 7, + 11, 11, 10, 9, 11, 10, 11, 9, 10, 11, 9, 8, 10, 9, 9, 6, + 12, 12, 11, 9, 12, 11, 12, 9, 12, 12, 11, 9, 11, 10, 10, 7, + 14, 13, 13, 10, 15, 12, 13, 10, 15, 13, 13, 10, 13, 12, 12, 8, + 13, 13, 11, 10, 14, 13, 12, 10, 13, 13, 10, 10, 12, 11, 10, 8, + 15, 14, 13, 10, 14, 13, 13, 10, 14, 13, 12, 10, 13, 12, 11, 8, + 14, 14, 13, 10, 16, 13, 13, 10, 15, 14, 13, 10, 13, 12, 12, 8, + 11, 11, 11, 10, 10, 9, 10, 9, 10, 10, 10, 9, 9, 8, 9, 6, + 12, 12, 12, 11, 11, 9, 12, 9, 12, 12, 11, 10, 11, 9, 10, 7, + 14, 13, 14, 12, 13, 10, 13, 10, 15, 13, 14, 12, 12, 10, 12, 8, + 13, 13, 12, 11, 12, 11, 12, 10, 12, 12, 11, 10, 11, 10, 10, 7, + 14, 13, 13, 11, 13, 12, 12, 10, 13, 13, 12, 11, 12, 10, 10, 7, + 16, 15, 15, 12, 14, 12, 13, 10, 15, 14, 13, 12, 13, 12, 12, 8, + 15, 15, 13, 13, 14, 14, 14, 12, 14, 14, 12, 11, 13, 12, 11, 8, + 15, 16, 14, 12, 15, 14, 13, 11, 15, 15, 13, 12, 13, 12, 11, 8, + 16, 15, 15, 12, 16, 14, 14, 10, 15, 15, 14, 12, 14, 12, 12, 8, + 13, 13, 13, 13, 11, 10, 12, 10, 12, 13, 12, 11, 10, 10, 10, 8, + 14, 13, 14, 13, 12, 10, 13, 10, 14, 14, 13, 12, 12, 10, 11, 8, + 15, 14, 16, 14, 13, 10, 14, 10, 16, 14, 14, 13, 13, 10, 12, 8, + 15, 15, 14, 14, 14, 13, 13, 12, 14, 14, 13, 12, 12, 11, 11, 9, + 15, 15, 15, 14, 14, 12, 14, 11, 15, 14, 13, 13, 13, 11, 11, 8, + 16, 15, 16, 14, 15, 12, 14, 11, 16, 16, 15, 13, 14, 12, 12, 8, + 16, 16, 16, 14, 15, 14, 14, 12, 15, 15, 14, 13, 13, 12, 11, 9, + 16, 16, 15, 15, 16, 14, 14, 11, 16, 16, 14, 13, 14, 12, 12, 8, + 16, 16, 16, 13, 15, 13, 14, 10, 16, 16, 15, 13, 14, 12, 12, 8, + 11, 11, 11, 10, 11, 10, 11, 9, 10, 10, 9, 8, 9, 9, 9, 6, + 12, 12, 13, 11, 12, 11, 12, 10, 12, 12, 11, 10, 11, 10, 10, 7, + 15, 13, 15, 12, 14, 13, 14, 11, 14, 13, 13, 11, 13, 11, 12, 8, + 12, 13, 12, 11, 13, 11, 12, 10, 11, 12, 10, 9, 11, 10, 10, 7, + 14, 13, 13, 11, 14, 12, 13, 11, 12, 12, 11, 10, 12, 11, 10, 7, + 15, 14, 15, 12, 15, 13, 15, 11, 15, 14, 13, 11, 13, 12, 12, 8, + 14, 14, 13, 12, 15, 14, 13, 12, 13, 13, 11, 10, 13, 12, 11, 8, + 16, 15, 13, 12, 15, 14, 14, 12, 14, 14, 12, 11, 14, 12, 11, 8, + 16, 15, 14, 12, 16, 15, 15, 11, 15, 14, 13, 11, 14, 13, 12, 8, + 12, 12, 12, 11, 12, 11, 12, 10, 11, 11, 11, 10, 10, 9, 9, 7, + 13, 13, 14, 12, 13, 11, 13, 11, 13, 12, 12, 11, 11, 10, 10, 7, + 15, 14, 16, 13, 14, 12, 14, 11, 14, 14, 14, 12, 13, 11, 12, 8, + 13, 13, 13, 12, 13, 12, 13, 11, 12, 12, 11, 10, 11, 10, 10, 7, + 14, 14, 13, 12, 13, 12, 13, 10, 13, 13, 11, 10, 12, 10, 10, 7, + 16, 15, 15, 13, 15, 12, 14, 11, 15, 14, 13, 11, 13, 11, 11, 7, + 15, 16, 14, 13, 15, 14, 14, 12, 14, 14, 12, 11, 13, 12, 11, 8, + 16, 15, 14, 13, 15, 14, 14, 11, 14, 14, 12, 11, 13, 12, 11, 7, + 16, 15, 15, 12, 16, 14, 14, 11, 15, 14, 13, 11, 14, 12, 11, 7, + 14, 15, 14, 14, 13, 12, 13, 12, 13, 13, 12, 12, 11, 10, 11, 8, + 15, 15, 15, 14, 13, 12, 14, 12, 14, 14, 13, 12, 12, 11, 11, 8, + 16, 15, 16, 14, 14, 12, 15, 12, 16, 14, 14, 13, 13, 11, 12, 8, + 15, 15, 15, 14, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11, 8, + 15, 15, 15, 14, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11, 7, + 16, 15, 16, 14, 15, 12, 15, 11, 15, 14, 14, 12, 13, 11, 12, 7, + 16, 16, 16, 15, 16, 15, 14, 13, 15, 15, 13, 12, 13, 12, 11, 9, + 16, 16, 16, 14, 15, 14, 14, 12, 15, 15, 13, 12, 14, 12, 11, 8, + 16, 16, 16, 14, 16, 14, 14, 11, 15, 15, 14, 12, 14, 12, 11, 7, + 13, 13, 13, 12, 13, 12, 13, 11, 11, 12, 11, 10, 10, 10, 10, 8, + 15, 14, 14, 13, 14, 13, 14, 12, 13, 13, 12, 11, 13, 11, 11, 8, + 16, 15, 16, 14, 16, 14, 16, 13, 15, 14, 14, 12, 14, 12, 13, 9, + 14, 15, 13, 13, 14, 13, 14, 12, 12, 13, 11, 11, 12, 11, 11, 8, + 15, 15, 14, 13, 15, 14, 14, 12, 13, 13, 12, 11, 13, 12, 11, 8, + 16, 16, 16, 13, 16, 15, 16, 13, 15, 14, 14, 12, 14, 13, 13, 9, + 14, 15, 13, 13, 16, 15, 15, 13, 13, 14, 11, 11, 13, 12, 11, 9, + 16, 16, 14, 13, 16, 15, 16, 13, 14, 14, 12, 11, 14, 13, 12, 8, + 16, 16, 15, 12, 16, 15, 15, 12, 15, 14, 13, 11, 14, 13, 12, 8, + 14, 14, 14, 13, 14, 13, 14, 12, 12, 13, 12, 11, 11, 11, 11, 8, + 15, 15, 15, 14, 14, 13, 15, 12, 14, 13, 13, 12, 12, 11, 11, 8, + 16, 16, 16, 15, 15, 14, 16, 13, 15, 14, 14, 12, 14, 12, 12, 9, + 15, 15, 14, 14, 14, 14, 14, 13, 13, 14, 12, 11, 12, 11, 11, 8, + 15, 15, 15, 13, 15, 14, 14, 12, 13, 13, 12, 11, 12, 11, 11, 7, + 16, 15, 16, 14, 16, 14, 15, 12, 15, 14, 14, 12, 13, 12, 12, 8, + 16, 16, 15, 14, 16, 15, 15, 13, 14, 14, 12, 11, 13, 12, 11, 8, + 16, 16, 15, 13, 16, 14, 14, 12, 14, 15, 12, 11, 13, 12, 11, 7, + 16, 16, 16, 13, 16, 15, 15, 12, 15, 14, 13, 11, 14, 12, 11, 7, + 15, 15, 15, 14, 13, 13, 14, 13, 13, 14, 13, 12, 11, 11, 11, 8, + 16, 16, 16, 14, 15, 13, 15, 12, 14, 14, 14, 13, 12, 11, 12, 8, + 16, 16, 16, 14, 15, 13, 15, 12, 15, 14, 14, 12, 13, 11, 12, 8, + 15, 16, 16, 14, 15, 14, 15, 13, 14, 14, 12, 12, 11, 11, 11, 8, + 16, 15, 15, 14, 15, 14, 14, 12, 14, 14, 13, 12, 12, 11, 11, 7, + 16, 16, 16, 13, 15, 13, 15, 12, 15, 14, 14, 12, 13, 11, 11, 7, + 16, 16, 16, 15, 15, 16, 15, 13, 14, 14, 12, 12, 12, 12, 11, 8, + 16, 16, 16, 14, 16, 14, 14, 12, 15, 15, 13, 11, 12, 11, 10, 7, + 16, 16, 15, 13, 16, 14, 14, 11, 15, 14, 13, 10, 13, 11, 10, 5, + }, + { + 1, 6, 6, 7, 6, 7, 9, 7, 6, 9, 7, 8, 7, 8, 8, 5, + 5, 8, 10, 10, 10, 10, 12, 11, 11, 12, 11, 11, 11, 12, 12, 9, + 9, 10, 12, 11, 13, 12, 15, 13, 14, 15, 15, 14, 14, 15, 15, 12, + 6, 10, 9, 10, 10, 11, 13, 12, 11, 13, 11, 12, 12, 12, 12, 10, + 6, 10, 10, 10, 11, 11, 13, 11, 11, 13, 12, 12, 11, 12, 12, 10, + 9, 12, 13, 12, 13, 13, 16, 13, 14, 16, 15, 14, 14, 15, 16, 12, + 9, 13, 11, 13, 14, 14, 16, 15, 14, 16, 13, 15, 15, 15, 15, 12, + 9, 13, 12, 13, 14, 15, 16, 15, 14, 16, 15, 15, 15, 15, 16, 12, + 8, 12, 12, 11, 13, 14, 15, 13, 13, 15, 14, 14, 14, 14, 14, 12, + 6, 10, 10, 11, 9, 10, 13, 11, 11, 13, 12, 12, 10, 12, 12, 9, + 6, 10, 11, 11, 11, 10, 13, 12, 11, 13, 12, 12, 12, 12, 13, 10, + 9, 12, 13, 13, 13, 12, 16, 13, 14, 16, 14, 15, 16, 14, 15, 12, + 8, 12, 13, 13, 13, 13, 16, 14, 13, 16, 13, 14, 14, 14, 14, 12, + 7, 11, 11, 12, 11, 12, 14, 13, 12, 14, 13, 13, 12, 13, 13, 11, + 9, 12, 13, 13, 13, 13, 15, 14, 14, 16, 16, 15, 15, 15, 16, 12, + 11, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 14, 14, 15, 15, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13, + 9, 13, 13, 13, 14, 14, 16, 14, 14, 16, 15, 14, 14, 16, 16, 13, + 9, 13, 14, 14, 11, 13, 16, 14, 13, 16, 15, 16, 13, 14, 15, 12, + 10, 13, 14, 15, 13, 12, 16, 14, 14, 16, 15, 15, 14, 14, 16, 13, + 9, 12, 13, 14, 12, 11, 15, 13, 13, 15, 13, 14, 15, 14, 16, 12, + 11, 15, 16, 16, 14, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 13, + 11, 14, 14, 15, 13, 14, 16, 15, 15, 16, 16, 16, 16, 16, 16, 13, + 10, 12, 13, 14, 13, 13, 16, 14, 14, 14, 14, 16, 15, 14, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 9, 12, 13, 14, 13, 13, 16, 13, 13, 15, 15, 16, 15, 15, 16, 12, + 6, 11, 11, 12, 10, 12, 13, 12, 11, 13, 11, 12, 11, 12, 13, 10, + 9, 12, 13, 13, 13, 13, 16, 14, 14, 15, 14, 14, 14, 14, 14, 12, + 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 7, 11, 11, 12, 12, 12, 14, 13, 12, 14, 11, 13, 13, 13, 13, 11, + 8, 12, 12, 13, 12, 13, 14, 13, 13, 14, 13, 13, 13, 14, 14, 11, + 11, 14, 14, 15, 16, 15, 16, 16, 15, 16, 16, 16, 16, 16, 16, 13, + 10, 14, 12, 14, 15, 15, 16, 16, 14, 16, 12, 15, 16, 16, 16, 13, + 11, 14, 13, 15, 15, 15, 16, 16, 14, 16, 14, 14, 16, 16, 16, 13, + 11, 14, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 13, + 7, 11, 12, 11, 10, 12, 14, 13, 12, 14, 13, 13, 10, 12, 13, 10, + 8, 12, 12, 13, 12, 12, 15, 13, 13, 14, 13, 13, 13, 13, 14, 11, + 11, 13, 15, 16, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 9, 12, 13, 13, 13, 13, 15, 14, 13, 15, 13, 14, 13, 14, 14, 12, + 7, 11, 11, 11, 11, 11, 13, 12, 11, 13, 11, 12, 11, 12, 12, 10, + 9, 12, 13, 13, 13, 13, 16, 13, 14, 16, 15, 14, 14, 14, 16, 12, + 12, 14, 14, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 14, + 10, 13, 13, 14, 14, 14, 16, 15, 14, 16, 14, 14, 16, 15, 15, 12, + 9, 12, 13, 13, 13, 15, 16, 14, 13, 16, 14, 13, 13, 14, 14, 11, + 10, 14, 15, 14, 12, 14, 16, 15, 13, 16, 16, 16, 12, 14, 16, 12, + 11, 14, 14, 14, 14, 14, 16, 15, 15, 16, 16, 16, 14, 15, 16, 13, + 11, 14, 14, 16, 14, 13, 16, 15, 14, 16, 15, 16, 15, 15, 16, 13, + 12, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14, + 10, 13, 14, 14, 13, 14, 16, 14, 13, 16, 15, 15, 13, 14, 14, 12, + 9, 12, 13, 14, 13, 12, 16, 14, 13, 16, 14, 14, 14, 14, 15, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 9, 12, 13, 13, 13, 13, 14, 13, 12, 15, 14, 14, 14, 14, 14, 11, + 11, 14, 14, 16, 14, 16, 16, 16, 13, 16, 14, 16, 14, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 14, 14, 16, 16, 15, 16, 16, 15, 16, 14, 16, 16, 16, 16, 14, + 12, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 14, 12, 15, 15, 15, 16, 16, 14, 16, 12, 14, 16, 16, 15, 14, + 12, 15, 14, 16, 16, 16, 16, 16, 15, 16, 14, 16, 16, 16, 16, 14, + 12, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, + 11, 15, 15, 16, 14, 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 11, 15, 14, 16, 14, 14, 16, 15, 14, 16, 15, 16, 15, 16, 16, 12, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 12, 16, 15, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 14, + 10, 14, 13, 14, 15, 14, 16, 15, 14, 16, 13, 16, 16, 16, 15, 13, + 10, 14, 14, 14, 13, 14, 16, 15, 15, 16, 14, 14, 14, 16, 16, 12, + 10, 14, 15, 14, 13, 16, 16, 15, 13, 16, 16, 16, 12, 14, 16, 12, + 11, 16, 16, 16, 14, 15, 16, 16, 16, 16, 16, 16, 14, 16, 16, 13, + 12, 15, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14, + 11, 14, 14, 14, 14, 15, 16, 14, 14, 16, 16, 16, 13, 15, 15, 12, + 10, 14, 13, 14, 14, 14, 16, 15, 14, 16, 15, 15, 14, 14, 16, 12, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 12, 14, 14, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 13, + 8, 11, 11, 12, 12, 12, 13, 12, 11, 13, 12, 12, 12, 13, 12, 10, + }, + }, + { + { + 5, 6, 6, 6, 6, 6, 7, 6, 6, 7, 6, 6, 6, 6, 6, 4, + 9, 9, 9, 8, 9, 8, 10, 8, 10, 10, 9, 9, 9, 8, 9, 6, + 11, 10, 12, 10, 11, 10, 12, 9, 12, 11, 11, 10, 11, 10, 11, 8, + 9, 10, 9, 8, 10, 10, 10, 9, 9, 10, 8, 8, 9, 9, 8, 7, + 10, 11, 10, 9, 11, 11, 11, 9, 11, 11, 10, 9, 10, 10, 10, 7, + 13, 12, 12, 10, 13, 12, 13, 10, 13, 12, 12, 11, 13, 12, 11, 9, + 11, 12, 10, 10, 12, 12, 11, 10, 11, 12, 10, 10, 11, 11, 10, 8, + 12, 12, 11, 10, 13, 13, 13, 10, 13, 13, 12, 11, 13, 12, 11, 9, + 12, 12, 12, 10, 13, 13, 13, 10, 13, 13, 12, 10, 13, 12, 12, 9, + 9, 9, 10, 10, 9, 8, 10, 9, 9, 10, 9, 9, 8, 8, 9, 6, + 10, 11, 11, 11, 10, 9, 11, 9, 11, 11, 11, 10, 10, 9, 10, 7, + 12, 12, 13, 12, 12, 10, 13, 10, 13, 13, 13, 12, 12, 11, 11, 9, + 11, 12, 11, 11, 11, 11, 11, 10, 11, 12, 10, 10, 10, 10, 10, 8, + 12, 12, 12, 11, 12, 11, 11, 10, 12, 12, 11, 11, 11, 11, 10, 8, + 14, 13, 13, 12, 13, 12, 13, 10, 14, 14, 13, 12, 13, 12, 12, 9, + 13, 14, 13, 12, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 11, 9, + 14, 14, 13, 12, 13, 13, 13, 11, 14, 14, 13, 12, 13, 12, 12, 9, + 14, 15, 14, 12, 15, 13, 13, 11, 15, 14, 14, 12, 14, 13, 12, 9, + 11, 11, 12, 12, 10, 10, 12, 11, 11, 12, 11, 11, 10, 10, 10, 8, + 12, 12, 14, 13, 11, 10, 12, 11, 13, 13, 13, 12, 12, 10, 11, 9, + 13, 13, 14, 14, 12, 10, 13, 11, 14, 14, 14, 13, 12, 11, 12, 9, + 13, 13, 13, 13, 12, 13, 13, 12, 13, 14, 12, 12, 12, 12, 11, 9, + 13, 14, 14, 13, 13, 12, 13, 11, 14, 14, 13, 12, 13, 12, 12, 9, + 14, 14, 14, 14, 14, 12, 13, 11, 15, 15, 15, 13, 14, 12, 12, 9, + 14, 15, 15, 13, 14, 14, 13, 12, 13, 14, 13, 13, 12, 12, 11, 10, + 16, 16, 15, 14, 15, 14, 13, 11, 15, 15, 14, 13, 13, 13, 12, 9, + 15, 15, 15, 13, 14, 13, 13, 11, 15, 15, 15, 13, 14, 13, 12, 9, + 8, 9, 9, 9, 9, 9, 10, 9, 8, 10, 9, 9, 8, 8, 9, 7, + 11, 11, 11, 11, 11, 11, 12, 10, 11, 11, 11, 10, 10, 10, 10, 8, + 13, 13, 14, 12, 13, 12, 14, 11, 13, 13, 13, 12, 13, 11, 12, 9, + 10, 11, 10, 11, 11, 11, 12, 10, 10, 11, 10, 10, 10, 10, 10, 8, + 12, 12, 12, 11, 12, 12, 12, 11, 11, 12, 11, 10, 11, 11, 10, 8, + 14, 13, 14, 12, 14, 13, 14, 12, 14, 13, 13, 11, 13, 12, 12, 9, + 12, 13, 12, 12, 13, 13, 13, 12, 12, 13, 11, 11, 12, 12, 11, 9, + 13, 14, 13, 12, 14, 14, 14, 12, 14, 13, 12, 11, 13, 12, 12, 9, + 14, 14, 13, 12, 15, 14, 15, 12, 14, 14, 13, 11, 13, 13, 12, 9, + 10, 11, 11, 11, 10, 10, 12, 10, 10, 11, 10, 10, 9, 9, 10, 7, + 12, 12, 13, 12, 12, 11, 12, 11, 12, 12, 12, 11, 11, 10, 10, 8, + 14, 13, 14, 13, 14, 12, 13, 12, 14, 13, 14, 12, 13, 11, 12, 9, + 12, 13, 12, 12, 12, 12, 12, 11, 11, 12, 11, 10, 10, 10, 10, 8, + 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 10, 11, 10, 10, 7, + 14, 14, 14, 12, 14, 12, 14, 11, 14, 13, 13, 11, 13, 11, 11, 8, + 13, 15, 13, 13, 14, 14, 14, 12, 13, 14, 12, 12, 12, 12, 11, 9, + 14, 15, 13, 12, 14, 13, 13, 11, 13, 13, 12, 11, 13, 12, 11, 8, + 15, 15, 15, 12, 15, 14, 14, 11, 14, 14, 13, 11, 13, 12, 12, 8, + 12, 13, 13, 13, 12, 12, 13, 12, 12, 13, 12, 12, 11, 11, 11, 9, + 13, 14, 15, 14, 13, 12, 14, 12, 13, 13, 14, 12, 12, 11, 12, 9, + 14, 14, 15, 14, 14, 12, 14, 12, 14, 14, 14, 13, 13, 11, 12, 9, + 13, 14, 14, 14, 13, 13, 14, 13, 13, 13, 12, 12, 12, 12, 11, 9, + 14, 14, 14, 13, 13, 13, 13, 12, 13, 14, 13, 12, 12, 11, 11, 8, + 15, 14, 15, 14, 14, 13, 14, 11, 15, 14, 14, 12, 13, 11, 12, 8, + 14, 15, 14, 14, 15, 14, 14, 13, 14, 15, 13, 13, 12, 12, 11, 10, + 16, 15, 14, 14, 14, 14, 13, 12, 14, 14, 13, 12, 13, 12, 11, 9, + 15, 15, 15, 14, 16, 14, 14, 11, 15, 15, 14, 12, 13, 12, 11, 8, + 11, 12, 11, 12, 12, 12, 12, 11, 10, 11, 10, 10, 10, 10, 10, 8, + 13, 13, 13, 13, 13, 13, 14, 12, 12, 12, 12, 12, 12, 11, 12, 9, + 14, 14, 14, 13, 15, 13, 15, 13, 14, 14, 14, 12, 14, 12, 13, 10, + 12, 13, 12, 13, 13, 13, 13, 12, 11, 12, 11, 11, 12, 11, 11, 9, + 14, 14, 13, 13, 14, 14, 14, 12, 12, 13, 12, 11, 13, 12, 12, 9, + 14, 14, 15, 13, 15, 15, 15, 13, 15, 13, 13, 12, 14, 12, 13, 10, + 13, 15, 12, 13, 14, 14, 14, 13, 12, 13, 11, 11, 13, 12, 11, 10, + 14, 15, 14, 13, 15, 14, 15, 13, 14, 14, 12, 11, 13, 13, 12, 9, + 14, 15, 14, 13, 15, 14, 15, 13, 14, 14, 13, 11, 14, 13, 12, 9, + 12, 13, 13, 13, 12, 13, 13, 12, 11, 12, 12, 11, 11, 11, 11, 9, + 13, 14, 14, 13, 14, 13, 14, 12, 13, 13, 13, 12, 12, 11, 11, 9, + 15, 15, 16, 14, 15, 14, 14, 13, 15, 14, 14, 13, 13, 12, 13, 10, + 13, 14, 14, 13, 13, 14, 14, 13, 12, 13, 12, 12, 11, 11, 11, 9, + 14, 14, 14, 13, 14, 13, 14, 12, 13, 13, 12, 11, 12, 11, 11, 8, + 15, 15, 15, 13, 15, 14, 14, 12, 14, 13, 13, 12, 13, 12, 12, 9, + 14, 15, 14, 14, 15, 15, 14, 13, 13, 14, 12, 12, 13, 12, 12, 9, + 15, 15, 14, 13, 15, 14, 14, 13, 14, 14, 12, 11, 13, 12, 11, 8, + 15, 16, 14, 13, 15, 15, 15, 12, 14, 14, 13, 11, 14, 12, 12, 8, + 12, 14, 13, 13, 13, 13, 14, 12, 12, 13, 12, 12, 10, 11, 11, 9, + 14, 15, 15, 14, 13, 13, 15, 13, 13, 14, 14, 12, 12, 11, 12, 9, + 15, 15, 16, 14, 14, 13, 15, 13, 14, 14, 14, 13, 13, 11, 12, 9, + 14, 15, 14, 14, 14, 14, 14, 13, 13, 14, 13, 12, 12, 12, 11, 9, + 14, 15, 15, 14, 14, 14, 14, 12, 13, 14, 13, 12, 12, 11, 11, 8, + 15, 15, 15, 14, 14, 13, 15, 12, 15, 14, 14, 12, 13, 11, 11, 8, + 14, 16, 14, 14, 14, 15, 14, 13, 13, 14, 12, 12, 12, 12, 11, 9, + 15, 15, 15, 14, 15, 14, 14, 12, 14, 14, 13, 12, 12, 11, 11, 8, + 15, 15, 14, 13, 15, 13, 14, 12, 14, 14, 13, 11, 13, 11, 11, 7, + }, + { + 1, 5, 6, 7, 6, 7, 9, 8, 6, 9, 8, 8, 7, 8, 8, 6, + 5, 8, 10, 10, 10, 11, 13, 12, 11, 13, 12, 12, 12, 12, 13, 10, + 8, 10, 13, 12, 13, 13, 16, 14, 14, 16, 16, 14, 16, 16, 16, 12, + 5, 10, 9, 11, 11, 12, 13, 12, 11, 13, 11, 12, 12, 12, 13, 10, + 6, 10, 11, 11, 11, 12, 14, 12, 11, 13, 13, 13, 12, 13, 13, 11, + 8, 12, 13, 12, 14, 14, 16, 14, 14, 16, 16, 16, 16, 16, 16, 13, + 9, 13, 11, 14, 14, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13, + 9, 13, 13, 13, 14, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 14, + 8, 12, 13, 12, 13, 14, 16, 14, 14, 16, 16, 16, 14, 16, 16, 13, + 5, 10, 11, 12, 9, 11, 13, 12, 11, 13, 13, 13, 11, 12, 13, 10, + 6, 10, 11, 12, 11, 11, 14, 13, 12, 14, 12, 13, 13, 13, 13, 11, + 9, 12, 14, 15, 13, 13, 16, 16, 14, 16, 16, 16, 16, 16, 16, 13, + 8, 13, 13, 14, 13, 14, 16, 16, 14, 16, 14, 16, 14, 16, 14, 13, + 7, 11, 12, 13, 12, 12, 14, 13, 12, 14, 13, 14, 13, 14, 14, 12, + 9, 13, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 15, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 9, 13, 14, 14, 14, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14, + 9, 13, 14, 15, 11, 13, 16, 14, 14, 16, 16, 16, 13, 14, 16, 13, + 9, 13, 14, 16, 13, 13, 16, 16, 14, 16, 16, 16, 16, 15, 16, 14, + 8, 12, 13, 16, 13, 12, 16, 14, 13, 16, 14, 16, 16, 16, 16, 13, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 14, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 9, 13, 16, 16, 14, 14, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 13, 14, 15, 14, 14, 16, 14, 13, 16, 16, 16, 14, 16, 16, 14, + 6, 11, 11, 12, 11, 12, 14, 13, 11, 14, 12, 13, 12, 13, 13, 11, + 9, 13, 13, 14, 13, 14, 16, 16, 14, 16, 16, 16, 15, 16, 16, 13, + 11, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 7, 11, 11, 13, 12, 13, 16, 14, 12, 16, 12, 14, 14, 14, 14, 12, + 8, 12, 12, 13, 12, 14, 16, 14, 13, 16, 14, 14, 14, 14, 14, 12, + 11, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 14, 13, 16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 16, + 10, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 7, 11, 12, 12, 11, 13, 16, 14, 12, 15, 14, 14, 11, 13, 13, 12, + 8, 12, 12, 13, 13, 13, 16, 14, 13, 16, 13, 15, 13, 14, 14, 12, + 11, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 8, 12, 13, 14, 13, 14, 16, 16, 14, 16, 14, 16, 14, 16, 15, 13, + 6, 11, 11, 12, 11, 12, 13, 13, 11, 13, 12, 13, 12, 13, 13, 11, + 9, 13, 14, 14, 14, 14, 16, 14, 14, 16, 16, 16, 16, 16, 14, 13, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 14, 13, 14, 14, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13, + 9, 13, 14, 13, 13, 16, 16, 14, 13, 16, 16, 16, 13, 16, 14, 13, + 10, 14, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 13, 14, 16, 14, + 11, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 14, 16, 16, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 14, 14, 14, 14, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 13, + 9, 13, 13, 16, 14, 14, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 13, 14, 14, 13, 16, 16, 14, 13, 16, 14, 16, 14, 14, 16, 12, + 10, 14, 14, 16, 16, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 14, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 14, 13, 16, 16, 16, 16, 16, 14, 16, 12, 16, 16, 16, 16, 14, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 14, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 11, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 15, 14, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 14, + 10, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 10, 14, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 14, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 15, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 13, + 10, 15, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 8, 12, 12, 13, 12, 14, 14, 14, 12, 16, 13, 14, 12, 14, 14, 11, + }, + }, +}; + + +static const uint8_t rv34_table_intra_cbp[NUM_INTRA_TABLES][8][CBP_VLC_SIZE] = { + { + { 0, 3, 3, 4, 3, 5, 5, 5, 2, 5, 4, 6, 4, 6, 6, 6, }, + { 0, 2, 3, 4, 2, 5, 6, 7, 3, 6, 5, 7, 4, 7, 8, 8, }, + { 0, 3, 4, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 3, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 6, 3, 5, 6, 5, }, + { 0, 4, 4, 4, 4, 5, 5, 4, 4, 5, 4, 5, 4, 4, 4, 2, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 6, 6, 5, 6, 5, 6, 4, 6, 6, 5, 4, 4, 4, 4, 1, }, + { 0, 4, 4, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 2, }, + }, + { + { 0, 4, 3, 4, 3, 4, 5, 4, 3, 5, 4, 5, 3, 5, 5, 5, }, + { 0, 2, 3, 4, 2, 5, 6, 7, 3, 6, 5, 7, 4, 7, 8, 8, }, + { 0, 4, 4, 4, 4, 4, 5, 4, 4, 5, 4, 4, 3, 4, 4, 3, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 6, 3, 5, 6, 5, }, + { 0, 4, 4, 4, 4, 4, 5, 4, 4, 5, 5, 5, 4, 4, 4, 2, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 5, 6, 5, 5, 5, 6, 4, 6, 6, 5, 4, 5, 4, 4, 1, }, + { 0, 4, 4, 4, 4, 4, 5, 4, 4, 5, 5, 4, 4, 4, 5, 2, }, + }, + { + { 0, 3, 3, 4, 3, 4, 4, 5, 3, 5, 4, 5, 4, 5, 5, 5, }, + { 0, 2, 3, 4, 2, 4, 6, 7, 3, 6, 5, 7, 5, 7, 8, 8, }, + { 0, 4, 4, 4, 4, 4, 5, 4, 3, 5, 4, 4, 4, 4, 4, 3, }, + { 0, 3, 3, 4, 3, 3, 6, 6, 3, 6, 4, 6, 3, 6, 6, 5, }, + { 0, 4, 4, 4, 3, 4, 5, 4, 4, 5, 4, 4, 4, 4, 4, 3, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 5, 5, 5, 5, 5, 6, 4, 5, 6, 5, 5, 5, 4, 4, 1, }, + { 0, 4, 4, 4, 4, 4, 6, 4, 4, 6, 5, 4, 4, 4, 4, 2, }, + }, + { + { 0, 3, 3, 4, 3, 4, 4, 5, 3, 5, 4, 5, 4, 5, 5, 5, }, + { 0, 2, 3, 4, 2, 4, 7, 6, 3, 7, 5, 7, 5, 7, 7, 7, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 3, 3, 3, 3, 4, 6, 6, 3, 6, 4, 6, 3, 6, 6, 5, }, + { 0, 3, 4, 4, 3, 4, 5, 4, 4, 5, 4, 5, 4, 5, 4, 3, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 4, 5, 4, 4, 4, 5, 4, 4, 5, 5, 4, 4, 4, 4, 2, }, + { 0, 4, 4, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 2, }, + }, + { + { 0, 3, 3, 4, 3, 4, 5, 6, 2, 5, 4, 7, 4, 6, 6, 7, }, + { 0, 2, 3, 4, 2, 4, 6, 7, 3, 7, 5, 7, 5, 7, 7, 7, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 2, 3, 4, 3, 4, 6, 5, 3, 6, 4, 6, 4, 6, 6, 6, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, }, + { 0, 4, 4, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 2, }, + { 0, 3, 4, 4, 4, 4, 5, 4, 4, 5, 4, 4, 4, 4, 4, 3, }, + }, +}; + + +static const uint8_t rv34_table_intra_firstpat[NUM_INTRA_TABLES][4][FIRSTBLK_VLC_SIZE] = { + { + { + 0, 10, 5, 10, 7, 12, 9, 11, 8, 13, 9, 12, 10, 13, 11, 12, + 16, 16, 14, 15, 15, 16, 13, 14, 5, 12, 6, 11, 9, 13, 10, 11, + 9, 14, 9, 12, 11, 14, 11, 12, 16, 16, 14, 15, 15, 16, 13, 13, + 10, 15, 9, 12, 12, 16, 11, 12, 12, 16, 10, 13, 13, 16, 11, 12, + 16, 16, 13, 14, 15, 16, 13, 12, 6, 12, 8, 11, 8, 12, 10, 11, + 9, 14, 10, 12, 10, 13, 11, 12, 15, 16, 14, 15, 14, 16, 13, 13, + 8, 13, 9, 12, 10, 13, 10, 12, 10, 14, 9, 12, 11, 14, 10, 12, + 15, 16, 13, 15, 14, 16, 13, 13, 11, 16, 10, 13, 13, 16, 11, 12, + 12, 16, 11, 13, 13, 16, 11, 12, 16, 16, 13, 14, 15, 16, 12, 12, + 10, 16, 12, 14, 10, 14, 11, 12, 12, 16, 13, 14, 11, 14, 12, 12, + 16, 16, 15, 16, 14, 15, 13, 13, 11, 16, 12, 14, 11, 14, 11, 12, + 12, 16, 12, 14, 11, 14, 11, 12, 16, 16, 14, 15, 13, 15, 13, 12, + 14, 16, 13, 14, 13, 16, 12, 12, 14, 16, 13, 14, 13, 16, 12, 12, + 16, 16, 14, 14, 14, 15, 12, 11, 2, 10, 6, 10, 7, 12, 9, 11, + 8, 12, 9, 11, 10, 13, 10, 11, 15, 16, 14, 15, 14, 16, 13, 13, + 5, 12, 6, 11, 9, 13, 10, 11, 9, 13, 9, 11, 10, 13, 10, 11, + 15, 16, 13, 14, 14, 16, 13, 13, 9, 15, 8, 12, 12, 15, 11, 11, + 11, 16, 10, 12, 13, 15, 11, 11, 15, 16, 13, 14, 15, 16, 12, 12, + 6, 12, 8, 11, 8, 12, 9, 11, 9, 14, 9, 12, 10, 13, 10, 11, + 15, 16, 14, 15, 14, 16, 13, 13, 7, 13, 8, 11, 9, 13, 10, 11, + 9, 14, 9, 12, 10, 13, 10, 11, 14, 16, 13, 14, 13, 16, 12, 12, + 11, 16, 10, 12, 12, 15, 11, 11, 11, 16, 10, 12, 12, 15, 11, 11, + 15, 16, 12, 13, 14, 16, 12, 11, 9, 15, 11, 13, 9, 13, 11, 12, + 11, 16, 12, 14, 10, 14, 11, 12, 16, 16, 14, 15, 13, 15, 12, 12, + 11, 16, 11, 14, 10, 14, 11, 12, 11, 16, 12, 13, 11, 14, 11, 11, + 15, 16, 14, 15, 13, 14, 12, 12, 13, 16, 12, 14, 13, 15, 11, 11, + 13, 16, 12, 14, 13, 15, 11, 11, 16, 16, 13, 14, 13, 15, 11, 10, + 5, 12, 7, 11, 8, 13, 10, 11, 9, 13, 9, 12, 10, 14, 11, 12, + 16, 16, 14, 15, 14, 16, 13, 13, 7, 13, 7, 11, 9, 13, 10, 11, + 9, 14, 9, 12, 11, 14, 11, 12, 16, 16, 14, 14, 14, 16, 13, 13, + 9, 15, 8, 12, 12, 15, 11, 12, 11, 16, 10, 12, 13, 16, 11, 12, + 16, 16, 13, 14, 15, 16, 12, 12, 7, 13, 8, 12, 9, 13, 10, 11, + 10, 14, 10, 12, 10, 14, 11, 12, 16, 16, 14, 15, 14, 16, 13, 13, + 8, 14, 9, 12, 10, 13, 10, 11, 9, 14, 9, 12, 10, 14, 10, 11, + 15, 16, 13, 14, 14, 16, 12, 12, 11, 16, 10, 12, 12, 15, 11, 12, + 11, 16, 10, 12, 12, 15, 11, 11, 15, 16, 12, 14, 14, 16, 12, 11, + 10, 16, 11, 13, 9, 14, 11, 12, 12, 16, 12, 14, 11, 14, 11, 12, + 16, 16, 14, 16, 14, 15, 13, 12, 11, 16, 11, 14, 10, 14, 11, 12, + 11, 16, 12, 14, 11, 14, 11, 11, 15, 16, 14, 15, 13, 15, 12, 12, + 13, 16, 12, 14, 13, 15, 11, 11, 13, 16, 12, 14, 12, 14, 11, 11, + 15, 16, 12, 13, 13, 14, 11, 10, 6, 13, 8, 11, 9, 13, 10, 11, + 10, 14, 10, 12, 10, 13, 10, 11, 15, 16, 13, 13, 13, 14, 12, 11, + 7, 13, 8, 11, 9, 13, 9, 11, 10, 14, 9, 11, 10, 13, 10, 11, + 15, 16, 13, 13, 13, 14, 11, 11, 9, 14, 8, 11, 10, 13, 9, 10, + 11, 15, 9, 11, 11, 13, 9, 10, 15, 16, 12, 13, 13, 14, 10, 9, + 7, 13, 8, 11, 9, 13, 9, 11, 10, 14, 10, 12, 10, 13, 10, 11, + 15, 16, 13, 13, 13, 14, 11, 11, 8, 13, 8, 11, 9, 13, 9, 10, + 9, 14, 9, 11, 10, 13, 9, 10, 14, 16, 12, 13, 13, 14, 11, 10, + 9, 14, 8, 11, 10, 13, 9, 9, 10, 14, 8, 11, 10, 13, 9, 9, + 14, 16, 11, 12, 12, 14, 10, 9, 9, 14, 9, 12, 8, 12, 9, 10, + 11, 15, 10, 12, 10, 13, 9, 10, 15, 16, 13, 13, 12, 13, 11, 10, + 9, 14, 9, 12, 9, 12, 9, 10, 10, 14, 10, 12, 9, 12, 9, 9, + 14, 16, 12, 13, 11, 13, 10, 9, 10, 14, 9, 11, 10, 12, 8, 8, + 10, 14, 9, 11, 10, 12, 8, 8, 12, 14, 9, 10, 10, 11, 8, 7, + }, + { + 0, 9, 6, 9, 6, 10, 8, 9, 7, 11, 8, 11, 9, 11, 9, 10, + 14, 16, 13, 14, 13, 14, 12, 11, 5, 11, 7, 10, 8, 10, 8, 9, + 8, 12, 8, 11, 9, 12, 9, 10, 14, 16, 12, 13, 13, 14, 11, 11, + 10, 14, 9, 11, 11, 13, 10, 10, 11, 15, 9, 11, 12, 13, 10, 10, + 15, 16, 12, 12, 13, 14, 11, 9, 6, 11, 7, 10, 7, 10, 8, 9, + 8, 12, 9, 11, 9, 11, 9, 10, 14, 16, 13, 13, 13, 14, 11, 11, + 7, 12, 8, 11, 8, 11, 9, 9, 9, 13, 9, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 12, 14, 11, 10, 11, 14, 10, 12, 11, 13, 10, 10, + 12, 15, 10, 12, 12, 13, 10, 10, 15, 16, 12, 12, 13, 14, 10, 9, + 10, 14, 11, 13, 9, 12, 10, 10, 11, 15, 12, 13, 10, 12, 10, 10, + 14, 16, 13, 14, 12, 13, 11, 10, 11, 14, 11, 13, 10, 12, 10, 10, + 12, 15, 11, 13, 10, 12, 10, 10, 15, 16, 13, 13, 12, 13, 11, 9, + 13, 16, 12, 13, 12, 13, 10, 9, 14, 16, 12, 13, 12, 13, 10, 9, + 16, 16, 12, 12, 13, 13, 10, 7, 4, 10, 6, 9, 7, 10, 8, 9, + 8, 12, 9, 11, 9, 11, 9, 9, 14, 16, 13, 13, 13, 14, 11, 11, + 6, 11, 7, 10, 8, 11, 8, 9, 9, 12, 9, 11, 9, 12, 9, 9, + 14, 16, 12, 13, 13, 14, 11, 10, 10, 14, 9, 11, 11, 13, 9, 9, + 11, 14, 9, 11, 11, 13, 10, 9, 14, 16, 11, 12, 13, 14, 10, 9, + 6, 11, 8, 10, 7, 10, 8, 9, 9, 12, 9, 11, 9, 11, 9, 9, + 14, 16, 13, 13, 12, 13, 11, 10, 8, 12, 8, 10, 8, 11, 9, 9, + 9, 12, 9, 11, 9, 11, 9, 9, 14, 16, 12, 13, 12, 13, 11, 10, + 11, 14, 10, 11, 11, 13, 9, 9, 11, 14, 10, 11, 11, 13, 9, 9, + 14, 16, 11, 12, 13, 14, 10, 8, 10, 14, 11, 12, 9, 12, 10, 10, + 11, 14, 11, 13, 10, 12, 10, 10, 14, 16, 13, 14, 12, 13, 11, 9, + 11, 14, 11, 12, 10, 12, 10, 10, 11, 14, 11, 12, 10, 12, 10, 9, + 14, 16, 13, 13, 11, 12, 10, 9, 13, 16, 12, 13, 12, 13, 10, 9, + 13, 16, 11, 12, 11, 13, 10, 8, 15, 16, 12, 12, 12, 12, 9, 7, + 8, 12, 8, 11, 9, 12, 9, 10, 10, 14, 10, 12, 11, 13, 10, 10, + 16, 16, 14, 14, 14, 14, 12, 11, 8, 13, 8, 11, 9, 12, 10, 10, + 11, 14, 10, 12, 11, 13, 10, 10, 16, 16, 13, 14, 14, 14, 12, 11, + 11, 14, 9, 12, 11, 13, 10, 10, 12, 15, 10, 12, 12, 14, 10, 10, + 15, 16, 12, 12, 14, 14, 11, 9, 9, 13, 9, 11, 9, 12, 10, 10, + 11, 14, 10, 12, 10, 12, 10, 10, 15, 16, 14, 14, 13, 14, 12, 11, + 9, 13, 9, 11, 10, 12, 10, 10, 10, 14, 10, 12, 10, 12, 10, 10, + 15, 16, 13, 13, 13, 14, 11, 10, 11, 15, 10, 12, 11, 13, 10, 10, + 11, 15, 10, 12, 12, 13, 10, 9, 15, 16, 11, 12, 13, 14, 10, 9, + 11, 15, 11, 13, 10, 12, 10, 10, 12, 16, 12, 13, 11, 13, 10, 10, + 16, 16, 14, 14, 12, 13, 11, 9, 11, 15, 11, 13, 10, 13, 10, 10, + 12, 15, 12, 13, 10, 12, 10, 10, 14, 16, 13, 13, 12, 13, 10, 9, + 13, 16, 12, 13, 12, 13, 10, 9, 13, 16, 11, 12, 11, 13, 10, 9, + 14, 16, 11, 12, 12, 12, 9, 7, 10, 15, 10, 12, 11, 13, 10, 10, + 12, 16, 12, 13, 12, 13, 11, 10, 16, 16, 14, 14, 14, 15, 12, 10, + 10, 14, 10, 12, 10, 13, 10, 10, 12, 15, 11, 12, 11, 13, 10, 10, + 16, 16, 14, 13, 14, 14, 11, 9, 11, 14, 10, 11, 11, 12, 9, 9, + 12, 15, 10, 11, 11, 13, 9, 8, 16, 16, 12, 12, 13, 13, 10, 7, + 10, 15, 10, 12, 10, 13, 10, 10, 12, 15, 11, 12, 11, 13, 10, 10, + 16, 16, 14, 13, 14, 14, 11, 9, 10, 14, 10, 12, 10, 12, 10, 10, + 12, 15, 11, 12, 11, 13, 10, 10, 16, 16, 13, 13, 13, 14, 11, 9, + 11, 14, 10, 11, 10, 12, 9, 8, 11, 14, 9, 11, 11, 12, 9, 8, + 14, 16, 10, 11, 12, 13, 9, 7, 11, 15, 11, 12, 10, 12, 10, 9, + 13, 16, 11, 12, 11, 12, 10, 9, 16, 16, 13, 13, 12, 13, 10, 7, + 11, 15, 10, 12, 10, 12, 9, 8, 12, 15, 11, 12, 10, 12, 9, 8, + 14, 16, 12, 12, 11, 12, 9, 7, 11, 14, 10, 11, 10, 12, 8, 7, + 11, 14, 9, 10, 10, 11, 8, 6, 12, 15, 9, 9, 9, 10, 7, 4, + }, + { + 0, 6, 3, 7, 3, 7, 6, 7, 5, 9, 6, 9, 7, 9, 8, 8, + 16, 16, 16, 16, 16, 16, 16, 11, 3, 8, 5, 8, 6, 8, 7, 7, + 7, 11, 7, 10, 8, 10, 8, 9, 16, 16, 16, 16, 16, 16, 14, 10, + 8, 16, 7, 11, 10, 16, 9, 9, 11, 16, 9, 14, 16, 16, 10, 9, + 16, 16, 16, 16, 16, 16, 16, 10, 3, 8, 5, 8, 5, 8, 7, 7, + 7, 11, 8, 10, 8, 10, 8, 9, 16, 16, 16, 16, 16, 16, 16, 11, + 6, 10, 7, 9, 7, 10, 8, 8, 8, 11, 8, 10, 8, 11, 8, 8, + 16, 16, 16, 16, 16, 16, 11, 10, 10, 16, 9, 13, 11, 16, 10, 9, + 11, 16, 9, 11, 16, 16, 10, 9, 16, 16, 11, 16, 16, 16, 11, 9, + 9, 16, 10, 11, 8, 11, 9, 9, 11, 16, 12, 16, 10, 16, 10, 10, + 16, 16, 16, 16, 16, 16, 16, 10, 10, 16, 11, 16, 10, 16, 10, 10, + 11, 16, 11, 16, 10, 16, 10, 9, 16, 16, 16, 16, 16, 16, 11, 9, + 16, 16, 16, 16, 16, 16, 11, 9, 16, 16, 16, 16, 16, 16, 11, 9, + 16, 16, 11, 16, 16, 16, 9, 7, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 2, 8, 5, 9, 6, 9, 8, 8, 8, 12, 9, 11, 9, 11, 10, 10, + 16, 16, 14, 16, 14, 16, 14, 12, 5, 10, 6, 9, 8, 10, 8, 9, + 9, 12, 9, 11, 10, 12, 10, 10, 16, 16, 14, 15, 15, 16, 13, 12, + 10, 13, 9, 12, 11, 12, 10, 10, 12, 15, 11, 12, 12, 13, 11, 10, + 16, 16, 15, 14, 15, 16, 13, 12, 6, 10, 8, 10, 7, 10, 8, 9, + 9, 13, 10, 11, 10, 12, 10, 10, 16, 16, 14, 16, 14, 16, 13, 12, + 7, 11, 8, 11, 9, 11, 9, 9, 10, 13, 10, 11, 10, 12, 10, 9, + 16, 16, 14, 14, 14, 15, 12, 11, 11, 14, 11, 12, 11, 13, 10, 10, + 12, 15, 11, 13, 12, 13, 11, 10, 16, 16, 14, 16, 15, 15, 13, 11, + 10, 13, 11, 12, 10, 12, 10, 10, 12, 15, 12, 13, 11, 13, 11, 11, + 16, 16, 15, 16, 14, 15, 13, 11, 11, 14, 11, 13, 11, 12, 11, 10, + 12, 16, 12, 13, 12, 13, 11, 10, 16, 16, 15, 16, 13, 15, 12, 11, + 13, 15, 12, 13, 13, 14, 11, 11, 14, 16, 13, 13, 13, 14, 11, 11, + 16, 16, 15, 14, 15, 15, 12, 10, 3, 8, 6, 9, 7, 9, 8, 8, + 8, 12, 9, 11, 9, 11, 9, 9, 16, 16, 15, 15, 15, 16, 13, 12, + 6, 10, 7, 9, 8, 10, 8, 8, 9, 12, 9, 11, 10, 12, 10, 9, + 16, 16, 14, 14, 14, 15, 13, 11, 10, 13, 9, 11, 11, 12, 10, 10, + 12, 14, 11, 12, 12, 13, 11, 10, 16, 16, 14, 14, 15, 15, 13, 11, + 6, 10, 8, 10, 7, 10, 8, 9, 10, 12, 10, 11, 10, 11, 10, 9, + 16, 16, 14, 15, 14, 15, 13, 11, 8, 11, 8, 10, 9, 11, 9, 9, + 9, 13, 9, 11, 10, 11, 9, 9, 16, 16, 13, 14, 14, 14, 12, 10, + 11, 14, 10, 12, 11, 12, 10, 10, 12, 14, 11, 12, 12, 13, 10, 10, + 16, 16, 13, 14, 15, 15, 12, 10, 10, 13, 11, 12, 10, 12, 10, 10, + 12, 14, 12, 13, 11, 13, 11, 10, 16, 16, 15, 14, 14, 14, 12, 11, + 11, 14, 11, 12, 10, 12, 10, 10, 12, 15, 12, 12, 11, 13, 10, 10, + 16, 16, 14, 15, 13, 14, 12, 10, 13, 15, 12, 13, 12, 13, 11, 10, + 13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 14, 13, 15, 11, 9, + 6, 10, 8, 10, 8, 11, 9, 10, 11, 13, 11, 12, 11, 13, 11, 10, + 16, 16, 16, 16, 16, 16, 13, 12, 8, 11, 9, 11, 9, 11, 10, 10, + 11, 14, 11, 12, 11, 12, 11, 10, 16, 16, 15, 15, 16, 16, 13, 12, + 11, 14, 10, 12, 12, 13, 11, 10, 13, 16, 12, 13, 13, 14, 11, 11, + 16, 16, 15, 16, 16, 16, 13, 12, 8, 12, 9, 11, 9, 11, 10, 10, + 11, 14, 11, 12, 11, 12, 11, 10, 16, 16, 16, 16, 16, 16, 13, 12, + 9, 12, 10, 11, 10, 12, 10, 10, 11, 14, 11, 12, 11, 13, 10, 10, + 16, 16, 15, 14, 15, 15, 13, 11, 12, 14, 11, 13, 12, 13, 11, 10, + 12, 15, 11, 12, 13, 13, 11, 10, 16, 16, 14, 15, 16, 15, 13, 11, + 11, 15, 12, 13, 11, 13, 11, 10, 13, 16, 13, 14, 12, 14, 11, 11, + 16, 16, 16, 16, 15, 15, 13, 12, 12, 14, 12, 13, 11, 13, 11, 10, + 13, 15, 12, 13, 11, 13, 11, 10, 16, 16, 15, 15, 13, 15, 13, 11, + 13, 16, 13, 13, 13, 13, 12, 11, 13, 16, 13, 13, 13, 13, 11, 10, + 16, 16, 13, 15, 14, 14, 12, 9, 9, 13, 10, 12, 11, 13, 11, 11, + 13, 16, 13, 14, 13, 14, 12, 11, 16, 16, 16, 16, 16, 16, 14, 12, + 10, 14, 11, 13, 11, 13, 11, 10, 13, 16, 13, 13, 13, 14, 12, 11, + 16, 16, 16, 16, 16, 16, 14, 12, 11, 15, 11, 13, 12, 13, 11, 10, + 14, 16, 12, 13, 13, 14, 12, 10, 16, 16, 15, 16, 16, 16, 13, 11, + 10, 14, 11, 12, 11, 13, 11, 10, 13, 16, 12, 13, 12, 14, 12, 11, + 16, 16, 16, 16, 16, 16, 14, 12, 11, 14, 11, 12, 11, 13, 11, 10, + 13, 15, 12, 13, 12, 13, 11, 10, 16, 16, 15, 15, 16, 16, 13, 11, + 12, 15, 12, 13, 12, 13, 11, 10, 13, 16, 12, 13, 13, 13, 11, 10, + 16, 16, 14, 14, 16, 15, 13, 10, 12, 15, 12, 13, 12, 13, 11, 10, + 14, 16, 13, 14, 13, 14, 12, 11, 16, 16, 16, 16, 15, 16, 13, 11, + 12, 16, 12, 13, 12, 13, 11, 10, 13, 16, 13, 13, 12, 14, 11, 10, + 16, 16, 15, 16, 14, 15, 13, 10, 12, 15, 12, 14, 12, 13, 11, 10, + 13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 14, 13, 14, 11, 8, + }, + }, + { + { + 0, 11, 5, 11, 7, 13, 10, 12, 7, 13, 9, 13, 10, 14, 12, 13, + 16, 16, 15, 16, 16, 16, 15, 15, 4, 13, 6, 12, 10, 14, 11, 12, + 8, 14, 9, 13, 11, 15, 12, 13, 16, 16, 15, 16, 15, 16, 15, 14, + 9, 16, 9, 13, 13, 16, 12, 13, 12, 16, 10, 14, 14, 16, 13, 13, + 16, 16, 14, 16, 16, 16, 14, 14, 5, 13, 8, 13, 8, 13, 11, 12, + 9, 14, 10, 13, 10, 14, 12, 13, 16, 16, 15, 16, 15, 16, 14, 15, + 7, 14, 9, 13, 10, 14, 11, 13, 9, 15, 10, 13, 11, 14, 12, 13, + 16, 16, 14, 16, 15, 16, 14, 14, 11, 16, 11, 14, 13, 16, 12, 13, + 12, 16, 11, 14, 14, 16, 12, 13, 16, 16, 14, 15, 16, 16, 14, 13, + 10, 16, 12, 15, 10, 15, 12, 14, 12, 16, 13, 16, 11, 15, 13, 14, + 16, 16, 16, 16, 14, 16, 14, 14, 11, 16, 12, 15, 11, 16, 12, 13, + 12, 16, 13, 15, 12, 16, 12, 13, 16, 16, 16, 16, 14, 16, 14, 14, + 14, 16, 13, 15, 14, 16, 13, 13, 14, 16, 14, 15, 14, 16, 13, 13, + 16, 16, 15, 16, 15, 16, 13, 13, 2, 12, 6, 11, 7, 13, 10, 12, + 7, 13, 9, 12, 10, 14, 11, 12, 16, 16, 15, 16, 15, 16, 14, 15, + 5, 13, 6, 12, 9, 13, 10, 12, 8, 14, 9, 13, 11, 14, 11, 13, + 16, 16, 14, 16, 15, 16, 14, 14, 9, 16, 8, 13, 12, 16, 11, 13, + 11, 16, 10, 13, 13, 16, 12, 13, 16, 16, 13, 15, 16, 16, 13, 13, + 5, 13, 8, 12, 7, 13, 10, 12, 8, 14, 10, 13, 10, 14, 11, 13, + 16, 16, 14, 16, 15, 16, 14, 14, 7, 14, 8, 12, 9, 14, 11, 12, + 8, 14, 9, 13, 10, 14, 11, 12, 15, 16, 14, 15, 14, 16, 13, 14, + 11, 16, 10, 13, 13, 16, 12, 13, 11, 16, 10, 13, 13, 16, 12, 13, + 16, 16, 13, 15, 15, 16, 13, 13, 9, 16, 12, 15, 9, 14, 11, 13, + 11, 16, 13, 15, 11, 14, 12, 13, 16, 16, 15, 16, 14, 16, 14, 14, + 11, 16, 12, 14, 11, 15, 12, 13, 11, 16, 12, 14, 11, 15, 12, 13, + 16, 16, 15, 16, 14, 16, 13, 13, 13, 16, 13, 15, 13, 16, 12, 13, + 14, 16, 13, 15, 13, 16, 12, 12, 16, 16, 14, 15, 14, 16, 12, 12, + 4, 13, 7, 12, 8, 14, 11, 12, 9, 14, 10, 13, 11, 14, 12, 13, + 16, 16, 15, 16, 16, 16, 15, 15, 6, 14, 7, 12, 10, 14, 11, 12, + 9, 15, 10, 13, 11, 15, 12, 13, 16, 16, 15, 16, 16, 16, 14, 14, + 9, 16, 8, 13, 12, 16, 11, 13, 12, 16, 10, 14, 13, 16, 12, 13, + 16, 16, 14, 16, 16, 16, 14, 14, 6, 14, 8, 13, 8, 14, 11, 13, + 9, 15, 10, 13, 11, 14, 12, 13, 16, 16, 15, 16, 16, 16, 14, 14, + 7, 15, 9, 13, 10, 14, 11, 13, 9, 15, 10, 13, 11, 14, 11, 13, + 16, 16, 14, 16, 15, 16, 14, 14, 10, 16, 10, 13, 12, 16, 12, 13, + 11, 16, 10, 13, 13, 16, 12, 13, 16, 16, 13, 14, 15, 16, 13, 13, + 9, 16, 12, 14, 9, 14, 11, 13, 12, 16, 12, 15, 11, 15, 12, 13, + 16, 16, 16, 16, 15, 16, 14, 14, 10, 16, 12, 15, 11, 15, 12, 13, + 11, 16, 12, 14, 11, 15, 12, 13, 16, 16, 14, 16, 13, 16, 13, 13, + 13, 16, 13, 15, 13, 16, 12, 13, 13, 16, 12, 14, 13, 16, 12, 12, + 15, 16, 13, 14, 13, 16, 12, 12, 6, 14, 8, 13, 9, 14, 10, 12, + 10, 15, 10, 12, 11, 14, 11, 12, 16, 16, 14, 14, 14, 16, 13, 13, + 7, 15, 8, 13, 9, 14, 10, 12, 10, 15, 10, 13, 11, 14, 11, 12, + 16, 16, 14, 14, 14, 16, 13, 12, 9, 16, 8, 12, 11, 14, 10, 11, + 11, 16, 10, 13, 11, 14, 10, 11, 16, 16, 13, 14, 14, 16, 12, 11, + 7, 14, 9, 13, 9, 14, 10, 12, 10, 16, 10, 13, 11, 14, 11, 12, + 16, 16, 14, 14, 14, 15, 13, 12, 7, 14, 9, 13, 9, 14, 10, 12, + 9, 14, 10, 12, 10, 14, 11, 12, 15, 16, 13, 14, 14, 15, 12, 12, + 9, 15, 9, 12, 11, 14, 10, 11, 10, 15, 9, 12, 11, 14, 10, 11, + 14, 16, 11, 13, 13, 15, 11, 11, 9, 16, 10, 13, 9, 14, 10, 11, + 11, 16, 11, 13, 10, 14, 10, 11, 16, 16, 14, 15, 13, 15, 12, 12, + 9, 16, 10, 13, 9, 13, 10, 11, 10, 15, 10, 13, 10, 13, 10, 11, + 14, 16, 13, 14, 12, 14, 11, 11, 11, 16, 10, 13, 11, 13, 9, 10, + 11, 14, 10, 12, 10, 13, 9, 9, 13, 15, 10, 11, 11, 12, 9, 8, + }, + { + 0, 10, 5, 10, 6, 11, 8, 10, 7, 12, 8, 11, 9, 12, 9, 10, + 14, 16, 13, 13, 13, 14, 12, 11, 5, 12, 6, 10, 8, 12, 9, 10, + 8, 13, 8, 11, 9, 12, 9, 10, 14, 16, 12, 13, 13, 14, 11, 11, + 9, 15, 8, 12, 11, 14, 10, 10, 11, 16, 9, 12, 12, 14, 10, 10, + 14, 16, 11, 12, 13, 14, 11, 10, 5, 12, 8, 11, 7, 11, 9, 10, + 8, 13, 9, 11, 9, 12, 9, 10, 14, 16, 12, 13, 13, 14, 11, 11, + 7, 13, 8, 11, 9, 12, 9, 10, 9, 13, 9, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 12, 13, 11, 10, 11, 15, 10, 12, 12, 14, 10, 10, + 12, 16, 10, 12, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 10, 9, + 10, 15, 11, 13, 9, 13, 10, 10, 11, 15, 12, 13, 10, 12, 10, 10, + 14, 16, 13, 14, 12, 13, 11, 10, 11, 16, 11, 13, 10, 13, 10, 10, + 11, 16, 11, 13, 10, 13, 10, 10, 14, 16, 13, 14, 12, 13, 11, 9, + 13, 16, 12, 13, 12, 14, 11, 10, 14, 16, 12, 13, 12, 14, 10, 9, + 16, 16, 12, 13, 13, 13, 10, 8, 3, 11, 6, 10, 7, 11, 9, 10, + 8, 12, 8, 11, 9, 12, 9, 10, 14, 16, 13, 13, 13, 14, 11, 11, + 5, 12, 6, 10, 8, 12, 9, 10, 8, 13, 8, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 13, 14, 11, 10, 9, 14, 8, 11, 11, 14, 10, 10, + 11, 15, 9, 11, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 11, 9, + 6, 12, 8, 11, 7, 11, 9, 10, 8, 13, 9, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 13, 13, 11, 10, 7, 13, 8, 11, 8, 12, 9, 10, + 9, 13, 9, 11, 9, 12, 9, 9, 14, 16, 12, 13, 12, 13, 11, 10, + 10, 15, 9, 12, 11, 14, 10, 10, 11, 15, 9, 11, 11, 13, 10, 9, + 14, 16, 11, 12, 13, 14, 10, 9, 9, 15, 11, 13, 9, 12, 10, 10, + 11, 15, 11, 13, 9, 12, 10, 10, 14, 16, 13, 14, 12, 13, 11, 10, + 10, 15, 11, 13, 10, 13, 10, 10, 11, 15, 11, 13, 10, 12, 10, 10, + 14, 16, 12, 13, 11, 12, 10, 9, 13, 16, 12, 13, 12, 14, 10, 9, + 13, 16, 11, 12, 12, 13, 10, 9, 14, 16, 11, 12, 12, 13, 9, 8, + 7, 13, 8, 12, 9, 13, 10, 11, 10, 14, 10, 12, 11, 13, 11, 11, + 16, 16, 13, 14, 14, 14, 12, 11, 8, 14, 8, 12, 9, 13, 10, 10, + 10, 14, 10, 12, 11, 13, 10, 10, 16, 16, 13, 13, 14, 14, 12, 11, + 10, 15, 9, 12, 11, 14, 10, 10, 12, 16, 10, 12, 12, 14, 10, 10, + 16, 16, 12, 13, 14, 15, 11, 10, 8, 14, 9, 12, 9, 13, 10, 11, + 10, 15, 10, 12, 10, 13, 10, 11, 16, 16, 13, 14, 14, 14, 12, 11, + 8, 14, 9, 12, 9, 13, 10, 10, 10, 14, 10, 12, 10, 13, 10, 10, + 15, 16, 13, 13, 13, 14, 11, 10, 10, 15, 10, 12, 12, 14, 10, 10, + 11, 16, 9, 12, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 10, 9, + 11, 16, 11, 13, 10, 13, 10, 10, 12, 16, 12, 13, 10, 13, 11, 10, + 15, 16, 14, 14, 12, 13, 11, 10, 11, 16, 11, 13, 10, 13, 10, 10, + 11, 16, 12, 13, 10, 12, 10, 10, 14, 16, 13, 14, 11, 13, 11, 9, + 13, 16, 12, 13, 12, 14, 10, 10, 12, 16, 11, 12, 12, 13, 10, 9, + 14, 16, 11, 12, 11, 12, 9, 8, 10, 16, 10, 13, 11, 14, 11, 11, + 12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 14, 13, 14, 14, 12, 10, + 10, 15, 10, 13, 10, 13, 10, 11, 12, 16, 11, 13, 11, 13, 11, 10, + 16, 16, 14, 13, 14, 14, 12, 10, 11, 15, 9, 12, 11, 13, 10, 9, + 12, 16, 10, 12, 12, 13, 10, 9, 16, 16, 12, 12, 13, 14, 10, 8, + 10, 16, 10, 13, 10, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 10, + 16, 16, 14, 13, 14, 14, 12, 10, 9, 15, 9, 12, 10, 13, 10, 10, + 11, 16, 10, 12, 11, 13, 10, 10, 16, 16, 13, 13, 13, 14, 11, 9, + 10, 15, 9, 11, 11, 13, 9, 9, 11, 15, 9, 11, 11, 13, 9, 8, + 14, 16, 10, 11, 13, 13, 10, 8, 11, 16, 11, 13, 10, 13, 10, 9, + 13, 16, 11, 13, 11, 13, 10, 9, 16, 16, 13, 13, 13, 13, 10, 8, + 11, 16, 10, 12, 10, 13, 10, 9, 11, 16, 11, 12, 10, 12, 9, 9, + 15, 16, 12, 13, 11, 12, 10, 8, 11, 16, 10, 12, 11, 12, 9, 8, + 11, 15, 9, 11, 10, 12, 9, 7, 13, 15, 9, 9, 10, 10, 7, 5, + }, + { + 0, 7, 3, 8, 4, 9, 7, 8, 5, 10, 7, 10, 8, 11, 8, 9, + 16, 16, 16, 16, 16, 16, 11, 10, 2, 10, 4, 9, 7, 10, 7, 8, + 7, 16, 7, 10, 9, 16, 8, 9, 16, 16, 16, 16, 16, 16, 11, 10, + 8, 16, 7, 10, 10, 16, 9, 8, 10, 16, 9, 11, 16, 16, 9, 9, + 16, 16, 16, 16, 16, 16, 11, 9, 3, 10, 6, 9, 6, 11, 8, 8, + 7, 16, 8, 10, 9, 16, 9, 9, 16, 16, 16, 16, 16, 16, 11, 10, + 5, 16, 7, 10, 8, 11, 8, 8, 8, 16, 8, 10, 9, 16, 8, 8, + 16, 16, 11, 16, 16, 16, 10, 9, 9, 16, 9, 11, 11, 16, 9, 9, + 11, 16, 9, 11, 11, 16, 9, 8, 16, 16, 10, 16, 16, 16, 10, 9, + 8, 16, 10, 16, 8, 16, 10, 9, 12, 16, 11, 16, 10, 16, 10, 9, + 16, 16, 16, 16, 16, 16, 12, 10, 10, 16, 11, 16, 10, 16, 10, 9, + 11, 16, 11, 16, 10, 16, 10, 9, 16, 16, 16, 16, 16, 16, 11, 9, + 16, 16, 16, 16, 16, 16, 10, 9, 16, 16, 11, 16, 16, 16, 10, 9, + 16, 16, 10, 11, 11, 16, 9, 7, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 2, 9, 6, 9, 6, 10, 8, 9, 8, 12, 9, 11, 9, 12, 10, 10, + 16, 16, 14, 14, 15, 15, 13, 12, 5, 11, 7, 10, 8, 11, 9, 9, + 9, 13, 9, 11, 10, 12, 10, 10, 15, 16, 14, 14, 14, 16, 12, 11, + 10, 14, 9, 11, 11, 13, 10, 10, 12, 15, 10, 12, 12, 13, 11, 10, + 16, 16, 14, 15, 14, 15, 12, 11, 5, 11, 8, 10, 7, 11, 9, 9, + 9, 13, 9, 12, 9, 12, 10, 10, 15, 16, 13, 14, 13, 16, 12, 11, + 7, 12, 8, 11, 9, 11, 9, 10, 9, 13, 9, 11, 10, 12, 9, 9, + 16, 16, 13, 14, 13, 14, 11, 11, 10, 14, 10, 12, 11, 13, 10, 10, + 11, 16, 11, 12, 12, 13, 10, 10, 16, 16, 13, 14, 13, 14, 12, 11, + 10, 14, 11, 13, 10, 13, 10, 11, 12, 16, 12, 13, 10, 12, 11, 11, + 16, 16, 14, 15, 13, 14, 12, 11, 11, 15, 11, 13, 11, 13, 10, 10, + 12, 15, 12, 13, 11, 13, 11, 10, 15, 16, 14, 15, 13, 15, 12, 11, + 12, 16, 12, 13, 12, 14, 11, 11, 13, 16, 12, 13, 12, 14, 11, 10, + 16, 16, 13, 14, 13, 14, 11, 10, 3, 10, 6, 9, 7, 10, 8, 9, + 9, 12, 9, 11, 10, 12, 9, 10, 15, 16, 14, 14, 14, 14, 12, 11, + 6, 11, 7, 10, 8, 10, 9, 9, 9, 13, 9, 11, 10, 12, 9, 9, + 15, 16, 13, 14, 14, 15, 12, 11, 10, 14, 9, 11, 11, 12, 10, 10, + 12, 14, 10, 12, 11, 13, 10, 10, 15, 16, 13, 14, 14, 16, 12, 11, + 6, 11, 8, 10, 7, 11, 9, 9, 9, 13, 9, 11, 9, 12, 9, 9, + 15, 16, 14, 14, 13, 14, 12, 11, 7, 11, 8, 11, 8, 11, 9, 9, + 9, 12, 9, 11, 9, 12, 9, 9, 15, 16, 13, 13, 13, 14, 11, 10, + 10, 13, 10, 12, 11, 13, 10, 10, 11, 15, 10, 12, 11, 13, 10, 10, + 14, 16, 12, 13, 13, 14, 11, 10, 10, 14, 11, 12, 9, 12, 10, 10, + 11, 15, 11, 13, 10, 13, 10, 10, 15, 16, 14, 14, 13, 14, 12, 11, + 10, 14, 10, 12, 10, 12, 10, 10, 11, 15, 11, 12, 10, 12, 10, 10, + 15, 16, 13, 14, 12, 14, 11, 10, 12, 16, 11, 13, 12, 14, 11, 10, + 12, 16, 12, 13, 11, 13, 10, 10, 15, 16, 12, 14, 12, 14, 11, 9, + 7, 12, 9, 11, 9, 12, 10, 10, 11, 14, 11, 12, 11, 13, 11, 11, + 16, 16, 15, 16, 15, 16, 13, 12, 8, 12, 9, 11, 9, 12, 10, 10, + 11, 14, 11, 12, 11, 13, 10, 10, 16, 16, 14, 15, 15, 16, 13, 12, + 11, 14, 10, 12, 11, 13, 10, 10, 12, 16, 11, 13, 12, 14, 11, 10, + 16, 16, 14, 15, 14, 16, 12, 11, 8, 13, 9, 11, 9, 12, 10, 10, + 11, 14, 11, 12, 11, 13, 10, 10, 16, 16, 15, 15, 14, 15, 13, 12, + 9, 13, 9, 12, 9, 12, 10, 10, 11, 14, 10, 12, 10, 12, 10, 10, + 16, 16, 14, 15, 14, 14, 12, 11, 11, 15, 11, 12, 11, 13, 11, 10, + 12, 16, 11, 12, 12, 13, 11, 10, 16, 16, 13, 15, 14, 15, 11, 11, + 11, 16, 11, 13, 10, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11, + 16, 16, 14, 15, 14, 15, 13, 11, 11, 16, 11, 13, 11, 13, 11, 10, + 12, 16, 12, 13, 10, 13, 11, 10, 16, 16, 14, 14, 12, 14, 12, 10, + 12, 16, 12, 14, 12, 14, 11, 11, 13, 16, 12, 14, 12, 14, 11, 10, + 15, 16, 12, 14, 12, 14, 11, 9, 9, 14, 11, 13, 11, 13, 11, 11, + 13, 16, 12, 14, 13, 14, 12, 11, 16, 16, 16, 16, 16, 16, 14, 12, + 9, 14, 10, 12, 10, 13, 11, 11, 12, 16, 12, 13, 13, 14, 11, 11, + 16, 16, 16, 16, 16, 14, 13, 12, 10, 15, 11, 13, 11, 14, 11, 10, + 13, 16, 12, 13, 12, 15, 11, 10, 16, 16, 14, 16, 15, 16, 13, 11, + 10, 14, 10, 13, 11, 14, 11, 11, 13, 16, 12, 13, 12, 14, 11, 11, + 16, 16, 16, 16, 15, 16, 13, 12, 10, 14, 10, 12, 10, 13, 10, 11, + 12, 15, 12, 13, 12, 13, 11, 10, 16, 16, 14, 14, 15, 15, 13, 11, + 11, 16, 11, 13, 11, 14, 11, 10, 12, 16, 11, 13, 12, 14, 11, 10, + 16, 16, 13, 14, 14, 15, 12, 10, 11, 16, 12, 13, 11, 14, 11, 10, + 13, 16, 13, 14, 12, 14, 11, 11, 16, 16, 15, 16, 15, 15, 12, 11, + 11, 16, 12, 13, 11, 14, 11, 10, 13, 16, 12, 13, 11, 14, 11, 10, + 16, 16, 14, 15, 13, 14, 12, 10, 12, 16, 12, 14, 12, 14, 10, 10, + 12, 16, 11, 13, 11, 14, 10, 10, 14, 16, 11, 13, 12, 13, 10, 8, + }, + }, + { + { + 0, 12, 6, 13, 7, 14, 11, 14, 8, 14, 10, 14, 11, 15, 13, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 5, 14, 7, 13, 10, 16, 12, 14, + 9, 16, 10, 14, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 9, 14, 14, 16, 13, 16, 12, 16, 11, 16, 16, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 5, 14, 9, 14, 8, 14, 12, 14, + 9, 16, 11, 14, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 14, 11, 16, 12, 14, 10, 16, 11, 15, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 14, 16, 14, 16, + 13, 16, 12, 16, 15, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 13, 16, 11, 16, 14, 16, 13, 16, 14, 16, 13, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 14, 16, 13, 16, 14, 16, + 13, 16, 14, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 16, 16, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 12, 6, 12, 8, 14, 11, 13, + 8, 14, 10, 13, 11, 14, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 14, 7, 13, 10, 14, 11, 14, 9, 16, 10, 14, 12, 16, 13, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 9, 14, 13, 16, 13, 14, + 12, 16, 11, 15, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 14, 9, 13, 8, 14, 12, 14, 9, 16, 11, 14, 11, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 15, 9, 14, 10, 16, 12, 14, + 9, 16, 10, 14, 11, 16, 12, 14, 16, 16, 16, 16, 16, 16, 15, 16, + 11, 16, 11, 15, 14, 16, 13, 15, 12, 16, 11, 15, 14, 16, 13, 14, + 16, 16, 14, 16, 16, 16, 14, 16, 10, 16, 13, 16, 10, 16, 13, 16, + 12, 16, 14, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 13, 16, 12, 16, 13, 16, 12, 16, 13, 16, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 15, 16, 14, 16, 14, 16, 16, 16, 14, 16, + 15, 16, 14, 16, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, 14, 14, + 4, 14, 8, 13, 9, 16, 12, 14, 9, 16, 11, 14, 11, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 15, 8, 13, 10, 16, 12, 14, + 10, 16, 11, 14, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 9, 14, 13, 16, 13, 15, 12, 16, 11, 16, 14, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 9, 14, 9, 16, 12, 14, + 10, 16, 11, 15, 12, 16, 13, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 14, 11, 16, 12, 14, 10, 16, 11, 14, 12, 16, 13, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 15, 14, 16, 13, 15, + 12, 16, 11, 15, 14, 16, 13, 14, 16, 16, 14, 16, 16, 16, 14, 16, + 10, 16, 13, 16, 10, 16, 13, 15, 13, 16, 14, 16, 12, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 12, 16, 13, 16, + 12, 16, 13, 16, 11, 16, 13, 16, 16, 16, 16, 16, 15, 16, 15, 16, + 14, 16, 14, 16, 15, 16, 14, 16, 14, 16, 14, 16, 14, 16, 14, 14, + 16, 16, 14, 16, 15, 16, 14, 14, 6, 16, 9, 14, 10, 16, 12, 14, + 10, 16, 11, 13, 12, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 14, + 7, 16, 9, 14, 10, 16, 12, 13, 11, 16, 11, 14, 12, 16, 12, 14, + 16, 16, 16, 16, 16, 16, 14, 14, 9, 16, 9, 14, 12, 16, 11, 13, + 12, 16, 11, 14, 12, 16, 12, 13, 16, 16, 14, 16, 16, 16, 13, 14, + 7, 16, 10, 14, 10, 16, 12, 14, 11, 16, 11, 14, 11, 16, 12, 14, + 16, 16, 16, 16, 16, 16, 14, 14, 8, 16, 10, 14, 10, 16, 11, 13, + 10, 16, 11, 13, 11, 16, 12, 13, 16, 16, 14, 16, 16, 16, 14, 14, + 10, 16, 9, 13, 12, 16, 11, 13, 11, 16, 10, 13, 12, 16, 11, 12, + 16, 16, 13, 15, 15, 16, 13, 13, 9, 16, 11, 14, 9, 16, 11, 13, + 12, 16, 12, 16, 12, 16, 12, 13, 16, 16, 16, 16, 15, 16, 14, 14, + 10, 16, 11, 14, 10, 16, 11, 13, 11, 16, 12, 14, 10, 15, 11, 13, + 16, 16, 15, 16, 13, 16, 13, 13, 12, 16, 11, 13, 12, 16, 11, 12, + 12, 16, 11, 13, 11, 14, 11, 11, 13, 16, 12, 13, 12, 14, 11, 11, + }, + { + 0, 10, 5, 10, 6, 11, 8, 10, 7, 12, 8, 11, 8, 12, 9, 10, + 14, 16, 13, 13, 13, 14, 12, 11, 4, 12, 6, 10, 8, 12, 9, 10, + 8, 13, 8, 11, 9, 12, 9, 10, 14, 16, 12, 13, 13, 14, 11, 11, + 9, 15, 8, 12, 12, 14, 10, 11, 11, 16, 9, 12, 12, 14, 10, 10, + 14, 16, 11, 13, 13, 15, 11, 11, 4, 12, 8, 11, 6, 11, 9, 10, + 8, 13, 9, 11, 8, 12, 9, 10, 14, 16, 12, 13, 13, 14, 11, 11, + 7, 13, 8, 11, 9, 12, 9, 10, 8, 13, 9, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 12, 13, 11, 10, 11, 16, 10, 12, 12, 14, 10, 11, + 11, 16, 10, 12, 12, 14, 10, 10, 15, 16, 11, 13, 13, 14, 11, 10, + 10, 16, 11, 13, 9, 13, 10, 11, 11, 15, 12, 13, 10, 12, 10, 11, + 15, 16, 13, 14, 12, 13, 11, 11, 11, 16, 11, 13, 10, 13, 10, 11, + 12, 16, 11, 13, 10, 13, 10, 10, 15, 16, 13, 14, 12, 13, 11, 10, + 13, 16, 12, 13, 13, 14, 11, 11, 14, 16, 12, 13, 12, 14, 11, 10, + 16, 16, 13, 13, 13, 14, 11, 9, 3, 11, 6, 10, 6, 11, 9, 10, + 8, 12, 8, 11, 9, 12, 9, 10, 14, 16, 13, 13, 13, 13, 12, 11, + 5, 12, 6, 10, 8, 12, 9, 10, 8, 13, 8, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 13, 14, 11, 11, 9, 15, 8, 11, 11, 14, 10, 10, + 11, 15, 9, 11, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 11, 10, + 5, 12, 8, 11, 7, 11, 9, 10, 8, 13, 9, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 13, 13, 11, 11, 7, 13, 8, 11, 8, 12, 9, 10, + 8, 13, 8, 11, 9, 12, 9, 9, 13, 16, 11, 13, 12, 13, 11, 10, + 10, 15, 9, 12, 11, 14, 10, 10, 11, 15, 9, 11, 11, 13, 10, 10, + 14, 16, 11, 12, 13, 14, 10, 10, 9, 16, 11, 13, 9, 12, 10, 10, + 11, 16, 11, 13, 9, 12, 10, 10, 15, 16, 13, 14, 12, 13, 11, 10, + 11, 16, 11, 13, 10, 13, 10, 10, 11, 15, 11, 13, 9, 12, 10, 10, + 14, 16, 12, 13, 11, 13, 10, 10, 13, 16, 12, 13, 12, 14, 11, 10, + 13, 16, 11, 13, 12, 13, 10, 10, 14, 16, 11, 12, 12, 13, 10, 9, + 7, 14, 8, 12, 9, 13, 10, 11, 10, 14, 10, 12, 11, 13, 11, 11, + 16, 16, 14, 14, 14, 14, 12, 12, 7, 14, 8, 12, 9, 13, 10, 11, + 10, 14, 10, 12, 11, 13, 10, 11, 16, 16, 13, 13, 14, 14, 12, 11, + 10, 15, 9, 12, 12, 14, 10, 10, 12, 16, 9, 12, 12, 14, 10, 10, + 16, 16, 12, 13, 14, 15, 12, 11, 8, 14, 9, 12, 9, 13, 10, 11, + 10, 15, 10, 12, 10, 13, 10, 11, 16, 16, 14, 14, 14, 14, 12, 11, + 8, 14, 9, 12, 9, 13, 10, 11, 10, 14, 10, 12, 10, 13, 10, 10, + 15, 16, 13, 13, 13, 14, 12, 11, 10, 15, 10, 12, 12, 14, 10, 10, + 11, 16, 9, 12, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 11, 10, + 11, 16, 11, 14, 9, 13, 10, 11, 12, 16, 12, 14, 10, 13, 11, 11, + 16, 16, 14, 15, 13, 14, 12, 11, 11, 16, 12, 14, 10, 13, 11, 11, + 11, 16, 11, 13, 10, 13, 10, 10, 15, 16, 13, 14, 12, 13, 11, 10, + 13, 16, 12, 14, 13, 14, 11, 10, 12, 16, 11, 13, 12, 13, 10, 10, + 14, 16, 11, 12, 11, 13, 10, 9, 10, 16, 10, 13, 11, 14, 11, 11, + 12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 14, 13, 14, 15, 12, 11, + 10, 16, 10, 13, 10, 14, 11, 11, 12, 16, 11, 13, 11, 14, 11, 11, + 16, 16, 14, 13, 14, 14, 12, 11, 11, 15, 9, 12, 11, 14, 10, 10, + 13, 16, 10, 12, 12, 14, 10, 10, 16, 16, 13, 13, 14, 14, 11, 10, + 10, 16, 10, 13, 11, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11, + 16, 16, 14, 14, 14, 14, 12, 11, 9, 16, 10, 13, 10, 14, 11, 11, + 11, 15, 11, 12, 11, 13, 11, 11, 16, 16, 13, 13, 14, 14, 12, 10, + 10, 15, 9, 12, 11, 14, 10, 10, 11, 16, 9, 11, 11, 13, 10, 9, + 15, 16, 11, 12, 13, 14, 10, 9, 11, 16, 11, 13, 10, 13, 10, 10, + 13, 16, 12, 13, 11, 13, 10, 10, 16, 16, 14, 14, 13, 13, 11, 10, + 11, 16, 11, 13, 10, 13, 10, 10, 12, 16, 11, 13, 10, 13, 10, 10, + 15, 16, 13, 13, 12, 13, 11, 9, 11, 16, 11, 12, 11, 13, 10, 9, + 11, 15, 10, 11, 11, 12, 9, 8, 13, 15, 10, 10, 10, 11, 8, 7, + }, + { + 0, 9, 3, 8, 5, 9, 7, 8, 5, 11, 6, 9, 8, 11, 8, 9, + 16, 16, 16, 16, 16, 16, 11, 10, 2, 10, 4, 9, 7, 10, 7, 8, + 7, 16, 7, 10, 9, 11, 8, 9, 16, 16, 11, 16, 16, 16, 11, 10, + 7, 16, 7, 10, 10, 16, 8, 9, 10, 16, 8, 10, 11, 16, 9, 9, + 16, 16, 16, 16, 16, 16, 11, 10, 3, 11, 6, 9, 6, 11, 8, 8, + 7, 16, 8, 10, 8, 11, 8, 9, 16, 16, 15, 16, 16, 16, 11, 10, + 5, 11, 7, 9, 8, 11, 8, 8, 7, 16, 7, 10, 8, 11, 8, 8, + 16, 16, 11, 16, 16, 16, 10, 9, 9, 16, 8, 11, 11, 16, 9, 9, + 10, 16, 8, 11, 11, 16, 9, 9, 16, 16, 10, 16, 16, 16, 10, 9, + 8, 16, 10, 11, 8, 16, 9, 9, 11, 16, 11, 16, 10, 16, 10, 9, + 16, 16, 16, 16, 16, 16, 11, 10, 9, 16, 10, 16, 10, 16, 9, 9, + 10, 16, 10, 16, 9, 16, 9, 9, 16, 16, 16, 16, 15, 16, 10, 9, + 16, 16, 11, 16, 16, 16, 10, 10, 13, 16, 11, 16, 11, 16, 10, 9, + 16, 16, 10, 11, 11, 16, 9, 8, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 1, 10, 6, 10, 7, 11, 9, 10, 8, 12, 9, 12, 9, 12, 10, 10, + 16, 16, 14, 16, 14, 15, 13, 12, 5, 12, 7, 10, 9, 11, 9, 10, + 9, 13, 9, 12, 10, 13, 10, 10, 16, 16, 14, 15, 14, 14, 13, 12, + 10, 15, 10, 12, 12, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11, + 16, 16, 14, 16, 15, 16, 13, 12, 6, 12, 8, 11, 8, 11, 10, 10, + 9, 13, 10, 12, 10, 12, 10, 10, 15, 16, 13, 15, 13, 14, 12, 12, + 7, 13, 9, 11, 9, 12, 10, 10, 9, 14, 10, 12, 10, 13, 10, 10, + 15, 16, 13, 15, 13, 14, 12, 11, 11, 15, 11, 13, 12, 14, 11, 11, + 12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 13, 15, 14, 16, 12, 11, + 10, 16, 12, 14, 10, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11, + 16, 16, 15, 16, 14, 16, 13, 12, 11, 16, 12, 14, 11, 14, 11, 11, + 12, 16, 12, 14, 11, 14, 11, 11, 16, 16, 14, 15, 13, 15, 12, 12, + 13, 16, 13, 15, 13, 15, 12, 12, 13, 16, 12, 15, 12, 15, 11, 11, + 16, 16, 13, 16, 13, 15, 12, 11, 4, 11, 7, 10, 7, 11, 9, 10, + 9, 13, 9, 12, 10, 12, 10, 10, 15, 16, 14, 15, 14, 15, 13, 12, + 6, 12, 7, 11, 9, 11, 9, 10, 9, 13, 9, 12, 10, 12, 10, 10, + 15, 16, 14, 15, 14, 15, 12, 12, 10, 15, 9, 12, 12, 13, 11, 11, + 12, 15, 11, 13, 12, 14, 11, 11, 16, 16, 13, 15, 14, 16, 12, 12, + 6, 12, 8, 11, 8, 11, 9, 10, 9, 14, 10, 12, 10, 12, 10, 10, + 14, 16, 13, 14, 13, 14, 12, 12, 8, 13, 9, 11, 9, 12, 10, 10, + 9, 13, 9, 12, 9, 12, 9, 10, 14, 16, 13, 14, 13, 14, 12, 11, + 11, 15, 11, 13, 11, 14, 11, 11, 12, 16, 10, 13, 12, 13, 11, 10, + 15, 16, 12, 15, 13, 16, 12, 11, 10, 15, 11, 13, 10, 13, 11, 11, + 12, 16, 12, 14, 11, 13, 11, 11, 16, 16, 14, 15, 13, 16, 13, 12, + 11, 16, 11, 14, 11, 13, 11, 11, 12, 16, 12, 14, 10, 13, 11, 11, + 15, 16, 13, 16, 12, 14, 12, 11, 12, 16, 12, 14, 12, 15, 11, 11, + 13, 16, 12, 14, 12, 14, 11, 11, 15, 16, 13, 15, 13, 15, 11, 10, + 7, 13, 9, 12, 10, 13, 11, 11, 11, 15, 12, 13, 12, 13, 11, 11, + 16, 16, 15, 16, 16, 16, 14, 13, 8, 13, 9, 12, 10, 13, 11, 11, + 12, 15, 11, 13, 12, 13, 11, 11, 16, 16, 14, 15, 15, 16, 13, 12, + 11, 16, 11, 13, 12, 14, 11, 11, 13, 16, 12, 14, 13, 15, 12, 11, + 16, 16, 14, 16, 15, 16, 13, 12, 9, 15, 10, 13, 10, 13, 11, 11, + 12, 15, 11, 13, 11, 13, 11, 11, 16, 16, 14, 16, 16, 16, 13, 12, + 9, 14, 10, 13, 10, 13, 11, 11, 11, 14, 11, 13, 11, 13, 11, 11, + 16, 16, 14, 16, 14, 16, 12, 12, 11, 16, 11, 14, 12, 14, 12, 11, + 12, 16, 11, 13, 13, 14, 11, 11, 16, 16, 13, 15, 14, 16, 12, 11, + 12, 16, 12, 14, 11, 14, 11, 11, 13, 16, 13, 14, 12, 15, 12, 11, + 16, 16, 16, 16, 14, 16, 13, 12, 12, 16, 12, 14, 11, 14, 12, 11, + 12, 16, 12, 15, 11, 14, 11, 11, 16, 16, 14, 16, 13, 15, 12, 12, + 13, 16, 13, 16, 13, 16, 12, 12, 13, 16, 12, 15, 12, 16, 11, 11, + 14, 16, 12, 15, 12, 15, 11, 10, 9, 16, 11, 14, 12, 14, 12, 12, + 13, 16, 13, 15, 14, 16, 12, 12, 16, 16, 16, 16, 16, 16, 14, 13, + 10, 16, 11, 14, 12, 14, 12, 12, 13, 16, 13, 14, 13, 16, 12, 12, + 16, 16, 15, 16, 16, 16, 13, 12, 11, 16, 11, 14, 12, 15, 12, 11, + 13, 16, 12, 14, 13, 16, 12, 11, 16, 16, 14, 16, 16, 16, 13, 12, + 11, 16, 11, 14, 12, 14, 12, 12, 13, 16, 12, 15, 13, 16, 12, 12, + 16, 16, 16, 16, 16, 16, 14, 13, 10, 16, 11, 14, 11, 15, 11, 11, + 13, 16, 12, 14, 12, 14, 12, 11, 16, 16, 14, 16, 16, 16, 13, 12, + 11, 16, 11, 15, 12, 15, 12, 11, 13, 16, 11, 14, 13, 15, 12, 11, + 16, 16, 13, 16, 14, 16, 12, 11, 12, 16, 12, 15, 11, 15, 12, 11, + 14, 16, 13, 15, 12, 16, 12, 11, 16, 16, 15, 16, 14, 16, 13, 12, + 11, 16, 12, 15, 11, 15, 11, 11, 13, 16, 13, 16, 11, 15, 11, 11, + 16, 16, 14, 16, 13, 15, 12, 11, 12, 16, 12, 15, 12, 16, 11, 11, + 12, 16, 11, 15, 12, 14, 11, 11, 13, 16, 12, 13, 11, 13, 10, 9, + }, + }, + { + { + 0, 13, 6, 13, 8, 14, 12, 16, 8, 16, 11, 16, 12, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 16, 7, 14, 11, 16, 13, 16, + 9, 16, 11, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 10, 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 5, 16, 10, 16, 8, 16, 13, 16, + 10, 16, 12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 16, 11, 16, 13, 16, 10, 16, 12, 16, 12, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 16, 16, 16, 16, + 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 11, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, + 14, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 13, 7, 13, 8, 16, 12, 16, + 8, 16, 10, 16, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 16, 7, 14, 10, 16, 12, 16, 9, 16, 10, 16, 12, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 9, 16, 14, 16, 14, 16, + 13, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 9, 16, 8, 16, 12, 16, 9, 16, 11, 16, 11, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 16, 10, 16, 11, 16, 13, 16, + 9, 16, 11, 16, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 12, 16, 16, 16, 14, 16, 13, 16, 12, 16, 16, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 13, 16, 11, 16, 14, 16, + 13, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 14, 16, 13, 16, 14, 16, 13, 16, 14, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 16, 8, 16, 9, 16, 13, 16, 10, 16, 11, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 8, 16, 11, 16, 13, 16, + 10, 16, 11, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 9, 16, 13, 16, 13, 16, 13, 16, 12, 16, 16, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 10, 16, 10, 16, 13, 16, + 10, 16, 12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 16, 11, 16, 13, 16, 10, 16, 11, 16, 12, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 16, 16, 14, 16, + 12, 16, 11, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 13, 16, 10, 16, 13, 16, 13, 16, 16, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 12, 16, 14, 16, + 12, 16, 15, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 10, 16, 10, 16, 13, 16, + 11, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 9, 16, 11, 16, 12, 16, 11, 16, 11, 16, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 9, 16, 12, 16, 12, 16, + 13, 16, 11, 16, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 16, 10, 16, 12, 16, 11, 16, 12, 16, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 10, 16, 11, 16, 12, 16, + 10, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 10, 14, 12, 16, 12, 16, 11, 16, 10, 14, 13, 16, 12, 14, + 16, 16, 14, 16, 16, 16, 14, 16, 9, 16, 12, 16, 10, 16, 12, 16, + 13, 16, 13, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 11, 16, 12, 16, 11, 16, 12, 16, 11, 16, 12, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 12, 16, 13, 16, 12, 13, + 12, 16, 12, 16, 12, 16, 12, 13, 16, 16, 13, 14, 13, 16, 13, 13, + }, + { + 0, 10, 5, 10, 5, 10, 8, 10, 6, 11, 8, 11, 8, 11, 9, 10, + 14, 16, 13, 14, 13, 14, 12, 12, 4, 12, 5, 10, 8, 12, 9, 10, + 7, 12, 8, 11, 9, 12, 9, 10, 14, 16, 12, 13, 13, 14, 12, 12, + 9, 16, 8, 12, 12, 14, 10, 11, 11, 16, 9, 12, 12, 14, 11, 11, + 14, 16, 12, 13, 14, 15, 12, 12, 4, 12, 7, 11, 6, 11, 9, 10, + 8, 12, 9, 11, 8, 11, 9, 10, 14, 16, 12, 14, 13, 14, 12, 12, + 7, 13, 8, 11, 8, 12, 9, 10, 8, 13, 8, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 12, 13, 11, 11, 11, 16, 10, 12, 12, 14, 11, 11, + 12, 16, 10, 12, 12, 14, 11, 11, 16, 16, 12, 13, 14, 15, 12, 11, + 10, 16, 11, 14, 9, 13, 10, 11, 11, 16, 12, 14, 10, 13, 11, 11, + 15, 16, 13, 14, 13, 14, 12, 12, 11, 16, 12, 14, 10, 13, 11, 11, + 12, 16, 12, 14, 11, 13, 11, 11, 15, 16, 13, 14, 13, 14, 12, 11, + 14, 16, 13, 14, 13, 15, 12, 12, 14, 16, 12, 14, 13, 15, 11, 11, + 16, 16, 13, 14, 14, 15, 12, 11, 3, 11, 5, 10, 6, 11, 9, 10, + 7, 12, 8, 11, 9, 11, 9, 10, 14, 16, 13, 13, 13, 14, 12, 12, + 5, 12, 6, 10, 8, 12, 9, 10, 8, 13, 8, 11, 9, 12, 9, 10, + 14, 16, 12, 13, 13, 14, 12, 12, 9, 16, 8, 11, 11, 14, 10, 11, + 11, 16, 9, 12, 12, 14, 10, 11, 15, 16, 12, 13, 14, 15, 12, 11, + 5, 12, 7, 11, 6, 11, 9, 10, 8, 13, 9, 11, 8, 11, 9, 10, + 14, 16, 12, 14, 13, 13, 12, 12, 7, 13, 8, 11, 8, 12, 9, 10, + 8, 12, 8, 11, 9, 12, 9, 10, 13, 16, 12, 13, 12, 13, 11, 11, + 10, 16, 9, 12, 12, 14, 10, 11, 11, 15, 9, 12, 12, 14, 10, 11, + 14, 16, 11, 13, 13, 14, 11, 11, 9, 16, 11, 14, 8, 13, 10, 11, + 11, 16, 12, 13, 10, 13, 10, 11, 16, 16, 13, 15, 13, 14, 12, 12, + 11, 16, 11, 14, 10, 13, 10, 11, 11, 16, 11, 13, 10, 13, 10, 11, + 14, 16, 13, 14, 12, 13, 11, 11, 14, 16, 12, 14, 13, 15, 11, 11, + 13, 16, 12, 13, 12, 14, 11, 11, 14, 16, 12, 13, 12, 13, 11, 10, + 6, 14, 8, 12, 9, 13, 10, 11, 10, 14, 10, 12, 11, 13, 11, 12, + 16, 16, 14, 14, 14, 14, 13, 12, 7, 14, 8, 12, 9, 13, 10, 11, + 10, 14, 10, 12, 11, 13, 11, 11, 16, 16, 13, 14, 14, 15, 13, 12, + 10, 16, 8, 12, 12, 14, 10, 11, 12, 16, 10, 12, 13, 15, 11, 11, + 16, 16, 13, 14, 15, 16, 12, 12, 8, 15, 9, 13, 9, 13, 10, 11, + 10, 15, 10, 13, 10, 13, 11, 11, 16, 16, 14, 14, 14, 14, 13, 12, + 8, 15, 9, 12, 10, 13, 10, 11, 10, 14, 10, 12, 10, 13, 10, 11, + 16, 16, 13, 14, 13, 14, 12, 12, 10, 16, 10, 13, 12, 15, 11, 11, + 11, 16, 9, 12, 12, 14, 11, 11, 14, 16, 11, 13, 14, 16, 12, 11, + 10, 16, 12, 14, 9, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11, + 16, 16, 15, 16, 14, 14, 13, 12, 11, 16, 12, 14, 11, 14, 11, 11, + 11, 16, 12, 14, 10, 13, 11, 11, 15, 16, 13, 15, 12, 14, 12, 11, + 14, 16, 13, 14, 13, 16, 12, 12, 12, 16, 12, 13, 12, 14, 11, 11, + 14, 16, 11, 12, 12, 13, 10, 10, 9, 16, 10, 14, 11, 15, 12, 12, + 12, 16, 11, 13, 12, 15, 12, 12, 16, 16, 14, 13, 15, 15, 13, 12, + 10, 16, 10, 14, 11, 15, 11, 12, 12, 16, 11, 13, 12, 14, 12, 12, + 16, 16, 14, 13, 15, 14, 13, 12, 11, 16, 9, 12, 12, 14, 11, 11, + 13, 16, 11, 13, 13, 15, 11, 11, 16, 16, 14, 14, 16, 16, 12, 12, + 10, 16, 10, 14, 11, 14, 11, 12, 12, 16, 11, 13, 12, 14, 12, 12, + 16, 16, 14, 14, 15, 15, 13, 12, 10, 16, 10, 13, 11, 14, 11, 12, + 11, 16, 11, 13, 11, 14, 11, 12, 16, 16, 14, 14, 14, 14, 13, 12, + 11, 16, 10, 12, 12, 15, 11, 11, 12, 16, 9, 12, 12, 14, 10, 11, + 16, 16, 12, 13, 14, 15, 11, 11, 11, 16, 12, 14, 10, 14, 11, 11, + 13, 16, 12, 14, 12, 14, 11, 11, 16, 16, 15, 15, 14, 15, 12, 12, + 11, 16, 12, 14, 11, 14, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11, + 16, 16, 14, 14, 13, 14, 12, 11, 12, 16, 11, 13, 12, 14, 10, 10, + 12, 15, 11, 12, 12, 13, 10, 10, 14, 15, 11, 11, 12, 12, 10, 9, + }, + { + 0, 8, 3, 8, 5, 9, 7, 8, 5, 10, 6, 10, 8, 11, 8, 9, + 16, 16, 15, 16, 16, 16, 11, 11, 2, 10, 4, 9, 7, 10, 7, 8, + 7, 16, 7, 10, 9, 11, 8, 9, 16, 16, 15, 16, 16, 16, 11, 11, + 7, 16, 6, 11, 10, 16, 9, 10, 10, 16, 9, 11, 11, 16, 9, 10, + 16, 16, 16, 16, 16, 16, 16, 11, 3, 10, 6, 9, 5, 10, 7, 9, + 7, 16, 8, 10, 8, 11, 8, 9, 16, 16, 16, 16, 16, 16, 11, 11, + 5, 11, 7, 10, 8, 11, 8, 9, 7, 14, 7, 10, 8, 11, 8, 9, + 16, 16, 11, 16, 16, 16, 10, 11, 9, 16, 9, 11, 11, 16, 9, 10, + 10, 16, 8, 11, 11, 16, 9, 10, 16, 16, 11, 16, 16, 16, 11, 10, + 8, 16, 9, 16, 7, 16, 9, 10, 11, 16, 11, 16, 10, 16, 10, 10, + 16, 16, 16, 16, 16, 16, 16, 11, 9, 16, 10, 16, 9, 16, 9, 10, + 10, 16, 10, 16, 9, 16, 9, 10, 16, 16, 16, 16, 11, 16, 11, 11, + 16, 16, 16, 16, 16, 16, 10, 10, 11, 16, 11, 16, 11, 16, 10, 10, + 16, 16, 11, 16, 11, 16, 10, 9, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 1, 10, 6, 10, 7, 11, 9, 10, 8, 12, 9, 12, 9, 12, 10, 10, + 15, 16, 14, 15, 14, 16, 13, 12, 5, 12, 7, 11, 8, 11, 9, 10, + 9, 13, 9, 12, 10, 12, 10, 10, 16, 16, 14, 15, 13, 16, 13, 12, + 10, 15, 10, 13, 12, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11, + 16, 16, 14, 16, 14, 16, 13, 12, 5, 12, 8, 11, 7, 11, 9, 10, + 9, 13, 10, 12, 9, 12, 10, 10, 14, 16, 14, 15, 13, 14, 13, 12, + 7, 13, 9, 12, 9, 12, 10, 10, 9, 13, 9, 12, 9, 12, 10, 10, + 14, 16, 13, 14, 13, 15, 12, 12, 11, 16, 11, 13, 12, 14, 11, 11, + 12, 16, 11, 14, 12, 14, 11, 11, 16, 16, 14, 16, 14, 16, 13, 12, + 10, 16, 11, 14, 10, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11, + 15, 16, 15, 16, 14, 16, 13, 12, 11, 16, 12, 14, 11, 14, 11, 12, + 12, 16, 12, 14, 11, 14, 11, 11, 15, 16, 14, 16, 13, 16, 13, 12, + 13, 16, 13, 16, 13, 16, 12, 12, 13, 16, 13, 16, 13, 16, 12, 12, + 16, 16, 14, 15, 14, 16, 13, 12, 4, 11, 7, 10, 7, 11, 9, 10, + 9, 13, 9, 11, 9, 12, 10, 10, 15, 16, 14, 15, 14, 15, 13, 12, + 6, 12, 7, 11, 8, 11, 9, 10, 9, 13, 9, 12, 10, 12, 10, 10, + 15, 16, 13, 14, 14, 15, 12, 12, 10, 14, 10, 12, 12, 13, 11, 11, + 12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 14, 15, 15, 16, 13, 12, + 6, 12, 8, 11, 8, 11, 9, 10, 9, 13, 10, 12, 9, 12, 10, 10, + 16, 16, 14, 15, 13, 14, 12, 12, 8, 13, 9, 11, 9, 12, 9, 10, + 9, 13, 9, 12, 9, 12, 9, 10, 14, 16, 13, 14, 13, 14, 12, 11, + 11, 15, 11, 13, 12, 14, 11, 11, 11, 16, 10, 13, 12, 14, 11, 11, + 15, 16, 13, 15, 14, 16, 12, 11, 10, 16, 12, 13, 10, 13, 11, 11, + 11, 16, 12, 14, 10, 13, 11, 11, 16, 16, 14, 16, 13, 16, 13, 12, + 11, 16, 12, 14, 10, 14, 11, 11, 11, 16, 12, 14, 10, 13, 11, 11, + 16, 16, 14, 16, 12, 15, 12, 11, 13, 16, 13, 15, 13, 15, 12, 12, + 13, 16, 12, 15, 12, 15, 12, 11, 15, 16, 13, 16, 13, 16, 12, 11, + 8, 14, 9, 12, 10, 13, 11, 11, 11, 16, 11, 13, 11, 13, 11, 11, + 16, 16, 16, 16, 16, 16, 14, 13, 9, 14, 10, 12, 10, 13, 11, 11, + 11, 16, 11, 13, 12, 13, 11, 11, 16, 16, 15, 16, 15, 16, 14, 12, + 11, 16, 11, 13, 12, 14, 12, 11, 13, 16, 12, 14, 13, 14, 12, 11, + 16, 16, 15, 16, 16, 16, 14, 13, 9, 14, 10, 13, 10, 13, 11, 11, + 11, 16, 11, 13, 11, 13, 11, 11, 16, 16, 15, 16, 14, 15, 14, 13, + 9, 14, 10, 13, 10, 13, 11, 11, 11, 15, 11, 13, 11, 13, 11, 11, + 16, 16, 14, 16, 14, 16, 13, 12, 12, 16, 12, 14, 13, 14, 12, 11, + 12, 16, 11, 14, 12, 15, 12, 11, 16, 16, 13, 16, 15, 16, 13, 11, + 11, 16, 12, 14, 11, 14, 12, 11, 13, 16, 13, 15, 12, 14, 12, 12, + 16, 16, 16, 16, 14, 16, 14, 13, 12, 16, 13, 15, 11, 14, 12, 12, + 12, 16, 13, 14, 11, 15, 12, 11, 16, 16, 15, 16, 13, 15, 13, 12, + 13, 16, 13, 15, 13, 16, 12, 12, 13, 16, 13, 15, 13, 15, 12, 12, + 15, 16, 13, 16, 13, 15, 11, 10, 10, 16, 12, 14, 12, 15, 12, 12, + 14, 16, 13, 15, 13, 16, 13, 12, 16, 16, 16, 16, 16, 16, 15, 13, + 10, 16, 12, 14, 12, 15, 12, 12, 13, 16, 13, 15, 13, 15, 13, 12, + 16, 16, 16, 16, 16, 16, 14, 13, 11, 16, 12, 15, 13, 16, 12, 12, + 14, 16, 13, 16, 13, 16, 12, 12, 16, 16, 15, 16, 15, 16, 14, 12, + 11, 16, 12, 14, 12, 16, 12, 12, 14, 16, 13, 15, 13, 15, 13, 12, + 16, 16, 16, 16, 16, 16, 15, 13, 11, 16, 12, 14, 12, 15, 12, 12, + 13, 16, 12, 14, 12, 15, 12, 12, 16, 16, 16, 16, 16, 16, 14, 12, + 12, 16, 12, 15, 13, 16, 12, 12, 13, 16, 12, 15, 13, 15, 12, 11, + 16, 16, 14, 16, 15, 16, 13, 12, 12, 16, 13, 16, 12, 16, 12, 12, + 15, 16, 14, 16, 13, 16, 12, 12, 16, 16, 16, 16, 16, 16, 14, 13, + 12, 16, 13, 15, 12, 16, 12, 12, 13, 16, 13, 15, 12, 15, 12, 12, + 16, 16, 15, 16, 14, 16, 13, 12, 13, 16, 13, 16, 12, 16, 12, 12, + 13, 16, 12, 16, 12, 15, 12, 12, 14, 16, 12, 14, 12, 14, 11, 10, + }, + }, + { + { + 0, 16, 6, 16, 8, 16, 16, 16, 9, 16, 11, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 16, 7, 16, 11, 16, 16, 16, + 10, 16, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 10, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 5, 16, 10, 16, 9, 16, 16, 16, + 10, 16, 13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 11, 16, 12, 16, 16, 16, 10, 16, 12, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 7, 16, 8, 16, 13, 16, + 9, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 16, 7, 16, 11, 16, 13, 16, 9, 16, 11, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 9, 16, 16, 16, 16, 16, + 13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 16, 10, 16, 8, 16, 16, 16, 10, 16, 12, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 16, 10, 16, 11, 16, 16, 16, + 9, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 12, 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 16, 16, 11, 16, 16, 16, + 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 4, 16, 8, 16, 10, 16, 16, 16, 10, 16, 11, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 8, 16, 11, 16, 16, 16, + 10, 16, 12, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 9, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 10, 16, 10, 16, 16, 16, + 11, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 11, 16, 11, 16, 16, 16, 10, 16, 12, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 12, 16, 16, 16, 16, 16, + 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 12, 16, 16, 16, + 12, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 10, 16, 11, 16, 16, 16, + 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 9, 16, 11, 16, 13, 16, 11, 16, 12, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 9, 16, 13, 16, 12, 16, + 13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 16, 10, 16, 14, 16, 12, 16, 12, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 11, 16, 11, 16, 13, 16, + 10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 10, 16, 13, 16, 12, 16, 12, 16, 11, 16, 16, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 12, 16, 10, 16, 13, 16, + 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 13, 16, 11, 16, 13, 16, 12, 16, 13, 16, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 13, 16, 16, 16, 12, 16, + 13, 16, 12, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 0, 10, 4, 10, 5, 11, 9, 11, 6, 11, 8, 11, 8, 12, 10, 12, + 15, 16, 13, 15, 14, 15, 13, 14, 4, 12, 5, 11, 8, 12, 9, 11, + 7, 13, 8, 12, 9, 13, 10, 12, 15, 16, 13, 15, 14, 16, 13, 14, + 10, 16, 9, 13, 12, 16, 11, 13, 11, 16, 10, 14, 13, 16, 12, 13, + 16, 16, 14, 16, 15, 16, 14, 15, 4, 12, 7, 12, 6, 12, 9, 11, + 8, 13, 9, 12, 9, 12, 10, 12, 15, 16, 13, 15, 14, 15, 13, 14, + 7, 13, 8, 12, 9, 13, 10, 12, 8, 13, 9, 12, 9, 13, 10, 12, + 14, 16, 13, 15, 13, 15, 13, 14, 12, 16, 11, 14, 13, 16, 12, 13, + 12, 16, 11, 14, 13, 16, 12, 13, 16, 16, 14, 16, 15, 16, 14, 15, + 10, 16, 12, 16, 10, 14, 12, 13, 12, 16, 13, 16, 11, 14, 12, 13, + 16, 16, 16, 16, 15, 16, 14, 15, 12, 16, 13, 16, 11, 15, 12, 13, + 13, 16, 13, 16, 12, 15, 12, 14, 16, 16, 16, 16, 14, 16, 13, 14, + 16, 16, 14, 16, 14, 16, 13, 15, 16, 16, 14, 16, 14, 16, 13, 15, + 16, 16, 16, 16, 16, 16, 14, 16, 2, 11, 5, 11, 6, 11, 9, 11, + 7, 12, 8, 11, 9, 12, 10, 12, 15, 16, 14, 14, 14, 14, 13, 14, + 4, 13, 6, 11, 8, 12, 9, 11, 8, 13, 8, 12, 10, 13, 10, 12, + 15, 16, 13, 15, 14, 15, 13, 14, 9, 16, 8, 13, 12, 15, 11, 12, + 11, 16, 10, 14, 13, 16, 12, 13, 16, 16, 14, 16, 16, 16, 14, 15, + 5, 13, 8, 12, 7, 12, 9, 11, 8, 13, 9, 12, 9, 12, 10, 12, + 16, 16, 14, 15, 14, 15, 13, 13, 7, 13, 8, 12, 9, 13, 10, 12, + 8, 13, 8, 12, 9, 13, 10, 12, 14, 16, 13, 14, 13, 15, 12, 13, + 11, 16, 10, 14, 13, 16, 12, 13, 11, 16, 10, 13, 12, 15, 11, 13, + 14, 16, 12, 14, 14, 16, 13, 14, 10, 16, 12, 15, 9, 14, 11, 13, + 12, 16, 12, 16, 11, 14, 12, 13, 16, 16, 15, 16, 16, 16, 14, 15, + 11, 16, 12, 15, 11, 15, 12, 13, 12, 16, 12, 15, 11, 14, 12, 13, + 16, 16, 14, 16, 13, 15, 13, 14, 15, 16, 14, 16, 14, 16, 13, 14, + 14, 16, 13, 16, 14, 16, 13, 14, 16, 16, 14, 16, 14, 16, 13, 14, + 7, 15, 8, 13, 9, 14, 11, 13, 10, 14, 10, 13, 11, 14, 12, 13, + 16, 16, 15, 16, 15, 16, 15, 14, 7, 16, 8, 13, 10, 14, 11, 13, + 11, 15, 10, 13, 12, 14, 12, 13, 16, 16, 16, 16, 16, 16, 15, 15, + 10, 16, 9, 13, 13, 16, 12, 13, 13, 16, 11, 14, 14, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 15, 16, 8, 16, 10, 14, 9, 14, 11, 13, + 11, 16, 11, 14, 11, 14, 12, 13, 16, 16, 16, 16, 16, 16, 14, 15, + 8, 16, 10, 14, 10, 14, 11, 13, 10, 15, 10, 14, 11, 14, 12, 13, + 16, 16, 14, 16, 15, 16, 14, 14, 11, 16, 10, 14, 13, 16, 12, 13, + 11, 16, 10, 13, 13, 16, 12, 13, 16, 16, 13, 16, 16, 16, 14, 14, + 11, 16, 12, 16, 10, 15, 12, 13, 14, 16, 14, 16, 12, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 11, 16, 12, 14, + 12, 16, 13, 16, 11, 14, 12, 13, 16, 16, 16, 16, 14, 16, 14, 14, + 15, 16, 14, 16, 16, 16, 13, 14, 13, 16, 13, 15, 14, 16, 13, 14, + 14, 16, 13, 14, 14, 15, 13, 14, 9, 16, 11, 16, 12, 16, 13, 14, + 12, 16, 12, 15, 13, 16, 13, 14, 16, 16, 16, 15, 16, 16, 15, 15, + 10, 16, 10, 16, 12, 16, 12, 14, 12, 16, 12, 14, 13, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 15, 15, 11, 16, 10, 14, 14, 16, 12, 13, + 14, 16, 12, 16, 14, 16, 13, 14, 16, 16, 16, 16, 16, 16, 16, 15, + 10, 16, 12, 16, 11, 16, 12, 14, 13, 16, 12, 15, 13, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 16, 15, 10, 16, 11, 16, 12, 16, 12, 14, + 12, 16, 12, 15, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 14, + 11, 16, 10, 14, 14, 16, 12, 13, 13, 16, 11, 14, 14, 16, 12, 13, + 16, 16, 15, 16, 16, 16, 14, 14, 12, 16, 13, 16, 11, 16, 12, 14, + 15, 16, 14, 16, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 16, + 12, 16, 13, 16, 12, 16, 12, 14, 13, 16, 13, 16, 12, 16, 12, 13, + 16, 16, 16, 16, 16, 16, 14, 15, 13, 16, 13, 16, 14, 16, 12, 13, + 13, 16, 13, 14, 14, 16, 12, 13, 16, 16, 14, 14, 14, 15, 13, 13, + }, + { + 0, 9, 3, 9, 5, 9, 7, 9, 5, 10, 7, 11, 8, 11, 9, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 2, 11, 4, 10, 7, 11, 8, 10, + 7, 16, 7, 11, 9, 16, 9, 11, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 7, 16, 11, 16, 10, 11, 11, 16, 10, 16, 16, 16, 11, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 2, 11, 6, 10, 6, 10, 8, 10, + 7, 16, 8, 16, 8, 11, 9, 11, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 13, 7, 11, 8, 11, 9, 11, 6, 12, 8, 12, 8, 12, 9, 11, + 16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 10, 16, 12, 16, 10, 13, + 10, 16, 9, 16, 11, 16, 11, 12, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 16, 8, 16, 10, 12, 11, 16, 12, 16, 10, 16, 11, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 11, 16, 10, 16, 11, 16, + 11, 16, 12, 16, 10, 16, 11, 12, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 1, 10, 5, 10, 6, 10, 9, 10, 7, 12, 9, 12, 9, 12, 10, 10, + 16, 16, 15, 16, 14, 16, 13, 13, 5, 12, 7, 11, 8, 11, 9, 10, + 8, 13, 9, 12, 10, 12, 10, 11, 16, 16, 16, 16, 14, 16, 13, 12, + 10, 16, 10, 13, 12, 14, 12, 12, 12, 16, 11, 14, 13, 15, 12, 12, + 16, 16, 16, 15, 16, 16, 14, 13, 5, 12, 8, 11, 7, 11, 9, 10, + 8, 13, 10, 12, 9, 12, 10, 10, 15, 16, 14, 15, 14, 14, 13, 13, + 7, 13, 9, 12, 9, 12, 10, 10, 9, 13, 10, 13, 10, 13, 10, 10, + 14, 16, 14, 15, 14, 16, 13, 12, 11, 16, 12, 14, 12, 15, 12, 12, + 12, 16, 12, 15, 13, 16, 12, 12, 16, 16, 15, 16, 16, 16, 14, 13, + 10, 16, 12, 14, 10, 14, 12, 12, 12, 16, 13, 14, 11, 14, 12, 12, + 16, 16, 16, 16, 14, 16, 14, 13, 11, 16, 12, 14, 11, 14, 12, 12, + 12, 16, 13, 16, 11, 15, 12, 12, 16, 16, 16, 16, 14, 16, 14, 13, + 13, 16, 14, 16, 14, 16, 13, 13, 13, 16, 13, 16, 13, 16, 13, 12, + 16, 16, 16, 16, 16, 16, 13, 13, 4, 11, 7, 10, 7, 11, 9, 10, + 8, 12, 9, 12, 9, 12, 10, 11, 15, 16, 14, 15, 14, 16, 13, 13, + 6, 12, 7, 11, 8, 11, 9, 10, 9, 13, 9, 12, 10, 12, 10, 10, + 16, 16, 15, 16, 15, 16, 13, 12, 10, 16, 10, 13, 12, 14, 12, 11, + 12, 16, 11, 14, 13, 14, 12, 12, 16, 16, 16, 14, 16, 16, 14, 13, + 6, 12, 8, 11, 7, 11, 9, 10, 9, 14, 10, 12, 9, 12, 10, 10, + 15, 16, 14, 16, 14, 16, 14, 13, 7, 13, 9, 12, 9, 12, 10, 10, + 9, 13, 9, 12, 9, 12, 10, 10, 14, 16, 13, 14, 14, 16, 12, 11, + 11, 16, 11, 14, 12, 14, 12, 12, 12, 16, 11, 14, 12, 14, 12, 11, + 16, 16, 13, 16, 14, 16, 13, 12, 10, 16, 12, 14, 10, 14, 11, 11, + 12, 16, 13, 14, 11, 14, 12, 12, 16, 16, 16, 16, 14, 16, 13, 13, + 11, 16, 12, 16, 11, 14, 12, 12, 12, 16, 12, 14, 11, 14, 12, 11, + 16, 16, 15, 16, 13, 15, 13, 12, 13, 16, 14, 16, 13, 16, 13, 12, + 13, 16, 13, 16, 13, 16, 13, 12, 16, 16, 14, 16, 14, 16, 12, 11, + 8, 13, 10, 12, 10, 13, 11, 11, 11, 14, 12, 14, 12, 14, 12, 12, + 16, 16, 16, 16, 16, 16, 14, 13, 9, 14, 10, 13, 10, 13, 11, 11, + 12, 16, 12, 13, 12, 13, 12, 11, 16, 16, 16, 16, 16, 16, 15, 14, + 12, 16, 11, 14, 13, 15, 12, 12, 13, 16, 12, 15, 14, 15, 13, 12, + 16, 16, 16, 16, 16, 16, 15, 13, 9, 14, 11, 13, 10, 13, 11, 11, + 11, 16, 12, 14, 12, 14, 12, 12, 16, 16, 16, 16, 16, 16, 16, 13, + 10, 15, 11, 13, 11, 14, 12, 11, 11, 16, 12, 14, 11, 14, 12, 11, + 16, 16, 16, 16, 16, 16, 14, 12, 12, 16, 12, 14, 13, 15, 13, 12, + 12, 16, 12, 14, 13, 15, 12, 12, 16, 16, 14, 16, 16, 16, 14, 12, + 12, 16, 13, 16, 11, 14, 12, 12, 14, 16, 14, 16, 12, 16, 13, 12, + 16, 16, 16, 16, 16, 16, 16, 13, 12, 16, 13, 16, 12, 16, 13, 12, + 12, 16, 13, 16, 12, 16, 12, 12, 16, 16, 16, 16, 14, 16, 14, 12, + 14, 16, 14, 16, 14, 16, 14, 13, 13, 16, 13, 16, 13, 16, 13, 12, + 16, 16, 13, 16, 13, 16, 12, 11, 9, 16, 12, 15, 13, 16, 13, 12, + 13, 16, 14, 16, 14, 16, 14, 13, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 16, 12, 15, 12, 15, 13, 12, 13, 16, 14, 16, 13, 16, 13, 12, + 16, 16, 16, 16, 16, 16, 16, 13, 12, 16, 12, 16, 13, 16, 13, 12, + 14, 16, 13, 16, 14, 16, 13, 12, 16, 16, 16, 16, 16, 16, 16, 13, + 11, 16, 12, 15, 12, 16, 13, 12, 14, 16, 14, 16, 13, 16, 13, 13, + 16, 16, 16, 16, 16, 16, 15, 13, 11, 16, 12, 16, 12, 16, 13, 12, + 13, 16, 13, 15, 13, 16, 13, 12, 16, 16, 16, 16, 16, 16, 15, 13, + 12, 16, 12, 16, 13, 16, 13, 12, 13, 16, 12, 16, 13, 16, 13, 12, + 16, 16, 14, 16, 16, 16, 14, 12, 12, 16, 14, 16, 11, 16, 13, 12, + 14, 16, 14, 16, 13, 16, 13, 12, 16, 16, 16, 16, 16, 16, 16, 13, + 12, 16, 13, 16, 12, 16, 13, 12, 13, 16, 13, 16, 12, 16, 13, 12, + 16, 16, 16, 16, 14, 16, 14, 12, 13, 16, 13, 16, 13, 16, 13, 13, + 13, 16, 12, 16, 12, 16, 12, 12, 14, 16, 13, 15, 13, 16, 12, 11, + }, + }, +}; + + +static const uint8_t rv34_table_intra_secondpat[NUM_INTRA_TABLES][2][OTHERBLK_VLC_SIZE] = { + { + { + 0, 5, 10, 3, 6, 10, 7, 8, 9, 4, 6, 10, 6, 7, 9, 8, + 8, 9, 8, 8, 9, 8, 9, 9, 9, 9, 8, 3, 6, 10, 4, 6, + 10, 7, 7, 9, 5, 7, 10, 6, 7, 9, 7, 7, 8, 7, 8, 9, + 8, 8, 9, 8, 8, 7, 6, 8, 10, 6, 8, 10, 7, 8, 9, 7, + 8, 10, 7, 8, 10, 8, 8, 8, 8, 9, 9, 8, 8, 9, 9, 8, + 7, 7, 8, 9, 7, 8, 9, 7, 7, 7, 8, 8, 9, 7, 8, 9, + 7, 7, 7, 8, 8, 8, 7, 7, 7, 7, 6, 5, + }, + { + 0, 5, 11, 3, 6, 11, 8, 9, 11, 3, 6, 10, 6, 7, 11, 9, + 9, 11, 7, 9, 11, 9, 9, 11, 10, 10, 11, 2, 6, 10, 4, 7, + 10, 7, 9, 11, 4, 7, 11, 6, 7, 10, 9, 9, 11, 7, 9, 11, + 8, 9, 10, 10, 10, 10, 5, 8, 11, 6, 8, 11, 8, 9, 11, 6, + 8, 11, 7, 8, 11, 9, 9, 11, 8, 10, 11, 9, 9, 11, 10, 10, + 10, 8, 9, 11, 8, 9, 11, 9, 9, 10, 8, 9, 11, 8, 9, 11, + 9, 9, 10, 8, 9, 10, 9, 9, 10, 9, 9, 8, + }, + }, + { + { + 0, 5, 10, 4, 6, 10, 7, 8, 10, 4, 6, 10, 6, 7, 9, 8, + 8, 9, 8, 8, 9, 8, 9, 9, 9, 9, 9, 2, 6, 10, 4, 6, + 10, 7, 7, 9, 5, 7, 10, 6, 7, 9, 7, 7, 9, 7, 8, 9, + 8, 8, 9, 9, 8, 8, 6, 8, 10, 6, 8, 10, 7, 8, 9, 6, + 8, 10, 7, 8, 10, 8, 8, 9, 8, 9, 10, 8, 8, 9, 9, 9, + 8, 8, 8, 10, 7, 8, 9, 7, 8, 8, 7, 8, 10, 7, 8, 9, + 7, 7, 8, 8, 8, 9, 8, 8, 8, 7, 7, 6, + }, + { + 0, 5, 12, 4, 7, 12, 8, 10, 13, 4, 7, 12, 6, 8, 12, 10, + 10, 12, 8, 9, 12, 10, 10, 12, 12, 12, 12, 1, 6, 12, 4, 7, + 12, 8, 9, 12, 4, 7, 12, 6, 8, 11, 9, 10, 12, 8, 9, 12, + 9, 10, 11, 11, 11, 12, 6, 8, 12, 7, 9, 12, 9, 10, 13, 6, + 9, 12, 8, 9, 12, 10, 10, 12, 9, 10, 12, 10, 10, 12, 12, 12, + 12, 8, 10, 12, 9, 10, 12, 10, 10, 12, 8, 10, 12, 9, 10, 12, + 10, 10, 11, 9, 10, 12, 10, 10, 11, 11, 10, 10, + }, + }, + { + { + 0, 5, 10, 3, 6, 10, 7, 8, 11, 4, 6, 10, 6, 7, 10, 8, + 9, 10, 8, 8, 10, 9, 9, 10, 10, 10, 10, 2, 6, 10, 4, 6, + 10, 7, 8, 10, 4, 7, 10, 6, 7, 10, 8, 8, 10, 7, 8, 10, + 8, 8, 9, 10, 9, 9, 5, 8, 11, 6, 8, 10, 7, 9, 10, 6, + 8, 11, 7, 8, 10, 8, 8, 10, 8, 9, 11, 9, 9, 10, 10, 9, + 9, 8, 9, 10, 8, 9, 10, 8, 9, 10, 8, 9, 10, 8, 8, 10, + 8, 8, 9, 8, 9, 10, 8, 8, 9, 9, 8, 8, + }, + { + 0, 6, 13, 4, 7, 14, 9, 11, 14, 3, 7, 13, 7, 8, 13, 11, + 11, 14, 8, 10, 13, 10, 11, 13, 13, 13, 14, 1, 6, 12, 4, 8, + 13, 9, 10, 15, 4, 8, 13, 7, 8, 12, 11, 11, 14, 8, 10, 13, + 10, 10, 13, 13, 13, 14, 5, 9, 13, 7, 9, 13, 10, 11, 14, 6, + 10, 14, 8, 10, 14, 11, 11, 14, 9, 11, 14, 11, 11, 13, 13, 13, + 14, 9, 10, 14, 9, 11, 13, 11, 12, 14, 9, 11, 13, 9, 11, 14, + 11, 12, 13, 10, 12, 15, 11, 11, 13, 13, 12, 13, + }, + }, + { + { + 0, 5, 11, 3, 6, 11, 7, 9, 12, 3, 6, 11, 6, 7, 11, 9, + 9, 11, 8, 9, 11, 9, 9, 11, 11, 11, 12, 2, 6, 11, 4, 6, + 11, 7, 9, 11, 4, 7, 11, 5, 7, 10, 9, 9, 11, 7, 8, 11, + 9, 9, 10, 11, 11, 11, 5, 8, 11, 6, 8, 11, 8, 9, 12, 6, + 8, 11, 7, 8, 11, 9, 9, 11, 8, 9, 12, 9, 9, 11, 11, 11, + 11, 8, 10, 12, 8, 10, 11, 9, 10, 12, 8, 10, 12, 8, 9, 12, + 10, 10, 12, 9, 10, 12, 9, 9, 11, 11, 10, 11, + }, + { + 0, 6, 13, 3, 8, 14, 10, 12, 16, 3, 8, 15, 7, 9, 15, 12, + 13, 15, 9, 11, 15, 11, 12, 16, 14, 16, 16, 1, 7, 13, 4, 8, + 14, 9, 11, 15, 4, 8, 14, 7, 9, 14, 12, 13, 15, 8, 10, 14, + 11, 11, 14, 16, 14, 16, 6, 9, 14, 7, 10, 14, 11, 13, 15, 7, + 10, 14, 9, 10, 13, 12, 12, 15, 10, 11, 14, 11, 11, 14, 14, 14, + 16, 9, 11, 14, 10, 11, 14, 13, 14, 15, 9, 12, 14, 10, 12, 16, + 13, 14, 16, 10, 13, 16, 12, 12, 14, 15, 14, 15, + }, + }, + { + { + 0, 6, 12, 3, 7, 12, 9, 11, 13, 4, 7, 12, 6, 8, 12, 10, + 11, 13, 8, 10, 13, 10, 11, 13, 13, 13, 14, 1, 6, 12, 4, 7, + 12, 9, 10, 14, 4, 7, 12, 6, 7, 12, 10, 11, 13, 8, 9, 13, + 10, 10, 12, 13, 13, 14, 6, 9, 13, 7, 9, 13, 10, 12, 14, 7, + 9, 13, 8, 10, 13, 11, 11, 14, 9, 11, 13, 11, 11, 14, 13, 13, + 14, 10, 12, 14, 10, 12, 14, 12, 13, 15, 10, 12, 14, 10, 12, 14, + 12, 13, 15, 11, 13, 15, 12, 12, 15, 14, 14, 14, + }, + { + 0, 6, 16, 3, 8, 16, 10, 13, 16, 3, 8, 16, 7, 9, 16, 13, + 16, 16, 8, 10, 16, 11, 13, 16, 16, 16, 16, 1, 7, 14, 4, 8, + 16, 10, 12, 16, 4, 8, 13, 7, 9, 16, 13, 14, 16, 8, 10, 16, + 11, 11, 14, 16, 16, 16, 6, 9, 14, 8, 10, 14, 12, 16, 16, 6, + 10, 13, 9, 11, 16, 13, 14, 16, 9, 12, 16, 12, 11, 16, 16, 16, + 16, 10, 12, 16, 11, 12, 16, 16, 14, 16, 9, 12, 16, 11, 12, 16, + 16, 15, 16, 10, 13, 16, 12, 13, 16, 16, 16, 16, + }, + }, +}; + +static const uint8_t rv34_table_intra_thirdpat[NUM_INTRA_TABLES][2][OTHERBLK_VLC_SIZE] = { + { + { + 0, 5, 10, 3, 6, 10, 7, 8, 10, 4, 7, 10, 6, 7, 10, 8, + 8, 10, 8, 9, 10, 9, 9, 10, 9, 9, 9, 2, 6, 10, 4, 7, + 10, 7, 8, 9, 5, 7, 10, 6, 7, 10, 8, 8, 9, 8, 9, 10, + 8, 8, 9, 9, 9, 8, 6, 8, 11, 6, 8, 10, 7, 8, 10, 6, + 8, 11, 7, 8, 10, 8, 8, 9, 8, 9, 10, 9, 9, 10, 9, 9, + 9, 7, 8, 10, 7, 8, 10, 7, 8, 8, 7, 8, 10, 7, 8, 9, + 7, 8, 8, 8, 8, 9, 8, 8, 8, 7, 7, 7, + }, + { + 0, 4, 10, 3, 6, 10, 7, 8, 11, 3, 6, 10, 5, 7, 10, 9, + 9, 11, 9, 10, 11, 9, 10, 11, 11, 11, 11, 2, 6, 10, 4, 6, + 10, 7, 8, 10, 4, 7, 10, 6, 7, 10, 8, 9, 10, 8, 9, 11, + 9, 9, 11, 10, 10, 11, 6, 8, 11, 6, 8, 11, 8, 9, 11, 7, + 9, 11, 7, 8, 11, 9, 9, 11, 9, 10, 12, 10, 10, 12, 11, 11, + 11, 8, 9, 11, 8, 9, 11, 9, 9, 11, 9, 10, 11, 9, 10, 11, + 9, 10, 11, 10, 11, 12, 10, 10, 12, 10, 10, 10, + }, + }, + { + { + 0, 5, 10, 3, 6, 10, 7, 8, 10, 4, 7, 10, 6, 7, 10, 8, + 9, 10, 8, 9, 11, 8, 9, 10, 10, 10, 10, 2, 6, 10, 4, 6, + 10, 7, 8, 10, 4, 7, 10, 5, 7, 10, 8, 8, 10, 8, 9, 10, + 8, 9, 10, 9, 9, 9, 5, 7, 11, 6, 8, 11, 7, 8, 11, 6, + 8, 11, 7, 8, 10, 8, 9, 10, 8, 9, 11, 9, 9, 10, 10, 9, + 10, 7, 8, 10, 7, 8, 10, 8, 9, 10, 8, 9, 10, 8, 9, 10, + 8, 8, 10, 9, 9, 10, 9, 9, 10, 9, 9, 9, + }, + { + 0, 5, 11, 3, 6, 11, 8, 9, 12, 4, 7, 12, 6, 7, 12, 9, + 10, 13, 10, 11, 13, 10, 11, 14, 12, 13, 14, 1, 6, 11, 4, 7, + 11, 8, 9, 12, 5, 7, 11, 6, 8, 12, 9, 10, 13, 10, 11, 14, + 10, 11, 13, 12, 12, 14, 6, 8, 12, 7, 9, 13, 9, 10, 14, 7, + 10, 13, 8, 10, 12, 11, 11, 13, 11, 13, 14, 11, 12, 14, 13, 13, + 15, 9, 10, 12, 9, 11, 14, 10, 11, 14, 11, 11, 13, 10, 11, 13, + 11, 12, 14, 12, 14, 15, 13, 13, 14, 13, 13, 14, + }, + }, + { + { + 0, 5, 11, 3, 6, 11, 7, 9, 11, 4, 6, 11, 5, 7, 10, 9, + 9, 11, 8, 9, 11, 9, 10, 11, 11, 11, 11, 2, 6, 10, 3, 6, + 10, 7, 9, 11, 4, 7, 10, 5, 7, 10, 8, 9, 11, 8, 9, 11, + 9, 9, 11, 11, 11, 11, 5, 8, 11, 6, 8, 11, 8, 10, 12, 6, + 8, 11, 7, 8, 11, 9, 10, 11, 9, 10, 12, 9, 10, 11, 11, 11, + 11, 8, 9, 11, 8, 10, 12, 9, 11, 12, 8, 10, 12, 9, 10, 12, + 10, 11, 12, 10, 11, 12, 10, 10, 11, 11, 11, 11, + }, + { + 0, 5, 13, 2, 7, 16, 9, 11, 16, 4, 8, 16, 7, 9, 16, 12, + 12, 16, 12, 16, 16, 12, 16, 16, 16, 16, 16, 1, 6, 13, 4, 8, + 16, 9, 11, 16, 6, 9, 16, 7, 10, 16, 13, 13, 16, 13, 15, 16, + 12, 16, 16, 16, 16, 16, 7, 9, 16, 8, 11, 15, 11, 13, 16, 10, + 12, 16, 10, 12, 16, 16, 13, 16, 16, 16, 16, 14, 16, 16, 16, 16, + 16, 12, 12, 16, 12, 16, 16, 16, 16, 16, 13, 14, 16, 12, 13, 16, + 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 6, 11, 3, 7, 11, 8, 10, 12, 4, 7, 11, 6, 8, 11, 10, + 11, 12, 9, 10, 12, 10, 10, 12, 12, 12, 13, 1, 6, 11, 4, 7, + 11, 8, 10, 12, 4, 7, 11, 6, 8, 11, 10, 10, 12, 9, 10, 12, + 10, 10, 12, 13, 13, 13, 6, 8, 12, 7, 10, 12, 10, 12, 13, 7, + 9, 12, 8, 10, 12, 11, 11, 13, 11, 12, 14, 11, 11, 13, 13, 13, + 13, 9, 11, 13, 10, 12, 14, 12, 13, 15, 10, 12, 14, 11, 12, 14, + 13, 13, 14, 12, 13, 15, 13, 13, 14, 14, 14, 14, + }, + { + 0, 5, 16, 2, 6, 16, 10, 14, 16, 4, 8, 16, 7, 9, 16, 11, + 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 1, 6, 12, 4, 8, + 12, 12, 12, 16, 6, 8, 16, 8, 10, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 12, 16, 16, 7, 10, 16, 8, 11, 14, 16, 16, 16, 10, + 12, 16, 10, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 5, 11, 3, 6, 11, 10, 10, 12, 3, 7, 11, 6, 8, 11, 11, + 11, 12, 10, 10, 12, 11, 11, 13, 14, 13, 14, 1, 6, 11, 4, 7, + 11, 10, 11, 13, 5, 7, 11, 7, 8, 11, 11, 11, 13, 10, 11, 13, + 11, 11, 12, 13, 13, 14, 7, 10, 12, 9, 11, 13, 12, 13, 14, 9, + 10, 13, 9, 10, 13, 12, 11, 13, 12, 13, 16, 12, 13, 13, 14, 14, + 14, 11, 14, 16, 12, 14, 15, 14, 13, 16, 13, 13, 15, 13, 14, 16, + 14, 13, 16, 13, 13, 16, 13, 14, 15, 15, 14, 15, + }, + { + 0, 4, 16, 2, 7, 16, 10, 16, 16, 4, 10, 16, 7, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 6, 13, 4, 11, + 16, 16, 16, 16, 6, 10, 16, 8, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 8, 16, 16, 10, 16, 16, 16, 16, 16, 10, + 16, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, +}; + + +static const uint8_t rv34_intra_coeff[NUM_INTRA_TABLES][COEFF_VLC_SIZE] = { +{ + 1, 3, 3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 11, 11, 11, 10, 10, 10, 12, 13, 14, 15, 15, +}, +{ + 1, 2, 3, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 10, 11, + 11, 11, 12, 12, 13, 13, 13, 13, 13, 13, 13, 14, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 6, 8, 8, 9, 9, 10, 10, 11, 12, 12, 12, + 13, 13, 14, 14, 14, 14, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 6, 8, 8, 9, 9, 10, 10, 11, 12, 12, 12, + 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 7, 7, 8, 8, 9, 10, 10, 12, 11, 13, 12, + 15, 13, 14, 13, 12, 15, 14, 13, 12, 12, 10, 11, 16, 16, 16, 16, +} +}; + + +static const uint8_t rv34_inter_cbppat[NUM_INTER_TABLES][CBPPAT_VLC_SIZE] = { +{ + 7, 9, 9, 8, 9, 8, 9, 8, 9, 9, 8, 8, 8, 8, 8, 4, + 7, 10, 11, 10, 11, 10, 12, 10, 12, 11, 11, 10, 11, 10, 10, 7, + 10, 11, 15, 12, 15, 12, 15, 12, 15, 14, 14, 12, 14, 12, 14, 9, + 7, 11, 10, 10, 12, 11, 11, 10, 11, 12, 10, 10, 11, 10, 10, 7, + 8, 12, 12, 11, 13, 12, 12, 10, 13, 13, 12, 10, 12, 11, 11, 7, + 11, 13, 15, 11, 15, 13, 15, 12, 16, 14, 14, 12, 15, 13, 13, 9, + 10, 15, 11, 12, 15, 14, 14, 12, 15, 15, 12, 12, 14, 14, 12, 9, + 11, 15, 13, 12, 16, 15, 14, 12, 15, 15, 13, 12, 15, 14, 13, 9, + 13, 15, 14, 10, 16, 15, 16, 11, 16, 16, 15, 12, 16, 15, 15, 9, + 7, 11, 11, 11, 11, 10, 11, 10, 11, 12, 11, 10, 10, 10, 10, 7, + 9, 12, 13, 12, 12, 11, 13, 10, 13, 13, 12, 11, 12, 10, 11, 7, + 12, 13, 16, 14, 15, 12, 16, 12, 16, 15, 15, 13, 15, 12, 14, 9, + 9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11, 7, + 9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 13, 11, 12, 11, 11, 7, + 12, 14, 15, 13, 16, 13, 15, 11, 16, 14, 15, 12, 15, 12, 13, 8, + 12, 16, 14, 14, 16, 15, 15, 13, 16, 15, 14, 13, 15, 14, 13, 9, + 12, 15, 14, 13, 15, 14, 15, 12, 16, 15, 14, 12, 14, 13, 13, 8, + 13, 16, 16, 12, 16, 14, 16, 11, 16, 16, 15, 12, 16, 14, 14, 8, + 10, 15, 15, 15, 12, 12, 14, 12, 14, 15, 15, 14, 12, 12, 13, 9, + 11, 15, 16, 14, 13, 12, 15, 12, 16, 15, 15, 14, 14, 12, 13, 9, + 14, 15, 16, 16, 15, 11, 16, 12, 16, 16, 16, 15, 16, 12, 15, 9, + 12, 16, 16, 15, 14, 14, 14, 13, 16, 16, 15, 14, 14, 13, 13, 9, + 12, 15, 15, 14, 14, 13, 15, 12, 16, 15, 14, 13, 14, 13, 13, 8, + 13, 16, 16, 15, 16, 12, 16, 11, 16, 16, 16, 14, 16, 13, 14, 8, + 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 16, 15, 16, 15, 14, 11, + 13, 16, 16, 15, 16, 15, 15, 12, 16, 16, 16, 14, 15, 14, 14, 9, + 14, 16, 16, 13, 16, 14, 16, 10, 16, 16, 16, 13, 16, 14, 14, 8, + 7, 12, 11, 11, 11, 11, 12, 10, 11, 11, 10, 10, 10, 10, 10, 7, + 9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11, 8, + 12, 14, 16, 14, 16, 14, 16, 13, 16, 14, 15, 13, 15, 13, 14, 9, + 9, 13, 12, 12, 13, 12, 13, 11, 12, 13, 11, 10, 12, 11, 11, 7, + 9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11, 7, + 12, 14, 16, 13, 16, 14, 15, 12, 15, 15, 14, 12, 15, 13, 13, 8, + 11, 15, 13, 14, 15, 15, 14, 13, 15, 15, 12, 12, 14, 14, 12, 9, + 11, 15, 14, 13, 15, 14, 14, 12, 15, 14, 13, 11, 14, 13, 12, 8, + 13, 16, 15, 12, 16, 15, 16, 12, 16, 16, 14, 11, 15, 14, 14, 8, + 8, 13, 13, 12, 12, 12, 13, 11, 12, 13, 12, 11, 11, 10, 10, 7, + 9, 13, 14, 12, 13, 12, 13, 11, 13, 13, 13, 11, 12, 11, 11, 7, + 12, 14, 16, 14, 15, 13, 15, 12, 15, 15, 15, 13, 14, 12, 13, 8, + 9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11, 7, + 9, 13, 12, 12, 13, 12, 12, 10, 13, 13, 12, 10, 12, 10, 10, 6, + 11, 14, 14, 12, 14, 12, 14, 11, 14, 14, 13, 11, 13, 11, 12, 7, + 12, 16, 14, 14, 15, 15, 14, 13, 15, 15, 13, 12, 14, 13, 12, 8, + 11, 14, 13, 12, 14, 13, 13, 11, 14, 14, 13, 11, 13, 12, 11, 7, + 11, 14, 14, 12, 15, 13, 14, 11, 15, 14, 13, 11, 14, 12, 12, 6, + 11, 16, 15, 15, 13, 14, 15, 13, 14, 15, 15, 13, 12, 12, 12, 9, + 12, 15, 15, 14, 14, 13, 15, 12, 15, 15, 14, 13, 13, 11, 12, 8, + 13, 16, 16, 15, 16, 13, 16, 13, 16, 16, 15, 14, 14, 12, 14, 8, + 11, 16, 15, 14, 14, 14, 14, 13, 15, 15, 14, 13, 13, 12, 12, 8, + 11, 14, 14, 13, 13, 12, 14, 11, 14, 14, 13, 12, 12, 11, 11, 7, + 12, 14, 15, 13, 14, 12, 14, 11, 15, 14, 14, 12, 13, 11, 12, 7, + 13, 16, 16, 16, 16, 15, 16, 14, 16, 16, 15, 14, 15, 14, 13, 9, + 12, 15, 14, 13, 15, 13, 14, 12, 15, 15, 13, 12, 13, 12, 12, 7, + 11, 15, 14, 12, 14, 13, 14, 10, 15, 14, 13, 11, 13, 11, 11, 5, + 10, 15, 15, 15, 15, 14, 15, 13, 12, 14, 12, 12, 12, 13, 12, 9, + 12, 16, 16, 15, 16, 15, 16, 14, 14, 15, 14, 13, 14, 13, 13, 9, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 15, 11, + 11, 15, 15, 14, 15, 15, 15, 14, 14, 15, 12, 12, 13, 13, 12, 9, + 12, 15, 15, 14, 16, 14, 15, 13, 14, 14, 13, 12, 14, 13, 12, 8, + 13, 16, 16, 15, 16, 16, 16, 14, 16, 16, 15, 12, 16, 14, 14, 9, + 13, 16, 14, 16, 16, 16, 16, 15, 15, 16, 11, 12, 16, 15, 12, 9, + 13, 16, 15, 14, 16, 15, 16, 14, 15, 16, 12, 11, 15, 14, 13, 8, + 13, 16, 16, 13, 16, 16, 16, 13, 16, 16, 13, 11, 16, 14, 14, 8, + 11, 15, 15, 15, 14, 14, 15, 13, 13, 15, 14, 13, 12, 12, 12, 9, + 11, 15, 16, 14, 15, 14, 15, 13, 14, 14, 14, 13, 13, 12, 13, 8, + 13, 16, 16, 16, 16, 15, 16, 14, 16, 16, 16, 13, 15, 12, 14, 9, + 11, 16, 15, 14, 14, 14, 15, 13, 14, 14, 13, 12, 13, 12, 11, 8, + 11, 14, 14, 13, 14, 13, 14, 12, 13, 13, 12, 11, 12, 11, 11, 7, + 12, 15, 15, 13, 15, 14, 15, 12, 15, 14, 14, 11, 13, 12, 12, 7, + 13, 16, 15, 15, 16, 16, 16, 14, 15, 16, 12, 12, 14, 14, 12, 8, + 11, 15, 14, 13, 15, 13, 14, 12, 14, 14, 12, 11, 13, 12, 11, 6, + 11, 14, 14, 12, 15, 13, 14, 11, 15, 14, 12, 10, 13, 11, 11, 5, + 12, 16, 16, 16, 15, 15, 16, 15, 14, 16, 15, 15, 10, 12, 12, 9, + 13, 16, 16, 16, 15, 14, 16, 13, 15, 15, 15, 14, 12, 11, 13, 8, + 14, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 14, 14, 11, 14, 8, + 13, 16, 16, 15, 15, 15, 15, 14, 15, 16, 14, 13, 12, 12, 11, 8, + 11, 15, 15, 13, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11, 6, + 11, 15, 15, 13, 15, 12, 14, 11, 14, 14, 13, 11, 12, 10, 11, 5, + 13, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, 14, 14, 13, 11, 8, + 11, 14, 14, 13, 14, 13, 14, 11, 14, 14, 12, 11, 12, 11, 10, 5, + 10, 13, 13, 11, 13, 12, 13, 9, 13, 13, 12, 9, 12, 10, 10, 3, +}, +{ + 5, 7, 7, 7, 7, 7, 8, 7, 7, 8, 7, 7, 7, 7, 7, 4, + 7, 9, 11, 9, 11, 9, 11, 9, 11, 10, 10, 9, 10, 9, 10, 6, + 11, 11, 14, 11, 14, 11, 14, 11, 15, 13, 14, 12, 14, 12, 13, 9, + 6, 11, 10, 9, 11, 10, 11, 9, 11, 11, 9, 9, 10, 10, 9, 6, + 8, 11, 11, 10, 12, 11, 12, 10, 12, 12, 11, 10, 12, 11, 11, 7, + 11, 13, 14, 11, 15, 13, 15, 11, 15, 14, 14, 12, 14, 13, 13, 9, + 10, 14, 11, 11, 15, 14, 13, 12, 14, 14, 11, 11, 14, 13, 12, 9, + 11, 14, 13, 11, 15, 14, 14, 11, 15, 15, 13, 11, 14, 14, 13, 9, + 12, 14, 14, 10, 16, 15, 16, 11, 16, 16, 15, 11, 16, 15, 14, 9, + 6, 10, 11, 10, 10, 9, 11, 9, 10, 11, 10, 10, 9, 9, 9, 6, + 9, 12, 12, 11, 12, 10, 12, 10, 12, 12, 12, 11, 11, 10, 11, 7, + 12, 13, 15, 13, 14, 11, 15, 11, 15, 15, 14, 13, 14, 12, 14, 9, + 9, 12, 12, 11, 12, 11, 12, 11, 12, 13, 11, 11, 12, 11, 11, 7, + 9, 12, 12, 11, 13, 11, 12, 10, 13, 13, 12, 11, 12, 11, 11, 7, + 12, 14, 15, 12, 15, 12, 14, 11, 15, 15, 14, 12, 14, 13, 13, 8, + 12, 15, 14, 13, 15, 14, 14, 13, 16, 16, 14, 13, 15, 14, 13, 9, + 12, 15, 14, 13, 15, 14, 14, 12, 15, 15, 13, 12, 14, 13, 13, 9, + 13, 15, 15, 12, 16, 14, 15, 11, 16, 16, 15, 12, 15, 14, 14, 9, + 10, 14, 14, 14, 12, 11, 13, 12, 14, 15, 14, 13, 12, 11, 12, 9, + 12, 14, 15, 14, 13, 11, 14, 12, 15, 15, 15, 14, 13, 11, 13, 9, + 13, 15, 16, 15, 14, 11, 16, 11, 16, 16, 16, 14, 15, 12, 15, 9, + 12, 15, 15, 14, 14, 14, 14, 13, 15, 15, 14, 14, 14, 13, 13, 9, + 12, 15, 15, 14, 14, 13, 14, 12, 15, 15, 14, 13, 14, 13, 13, 9, + 13, 15, 16, 14, 15, 13, 16, 11, 16, 16, 15, 14, 15, 13, 14, 9, + 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 16, 16, 16, 16, 14, 11, + 14, 16, 16, 14, 16, 15, 15, 12, 16, 16, 16, 14, 15, 14, 14, 9, + 14, 16, 16, 14, 16, 14, 16, 11, 16, 16, 16, 14, 16, 14, 14, 9, + 6, 11, 10, 10, 10, 10, 11, 10, 10, 11, 9, 9, 9, 9, 9, 6, + 9, 12, 12, 11, 13, 11, 13, 11, 12, 12, 11, 11, 12, 11, 11, 7, + 12, 14, 16, 13, 16, 14, 16, 13, 15, 14, 15, 12, 15, 13, 14, 9, + 8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 11, 10, 7, + 9, 12, 12, 11, 13, 12, 13, 11, 13, 12, 11, 10, 12, 11, 11, 7, + 12, 14, 15, 12, 15, 14, 15, 12, 15, 14, 14, 12, 14, 13, 13, 9, + 11, 15, 13, 13, 15, 14, 14, 13, 14, 15, 11, 11, 14, 14, 12, 9, + 11, 14, 13, 12, 15, 14, 14, 12, 14, 14, 12, 11, 14, 13, 12, 8, + 13, 15, 15, 12, 16, 15, 15, 12, 15, 15, 14, 11, 15, 14, 14, 8, + 8, 12, 12, 11, 11, 11, 12, 11, 11, 12, 11, 11, 10, 10, 10, 7, + 9, 13, 13, 12, 13, 11, 13, 11, 12, 13, 12, 11, 11, 10, 11, 7, + 12, 14, 15, 14, 15, 13, 15, 12, 15, 14, 14, 13, 14, 12, 13, 9, + 9, 13, 12, 12, 12, 12, 12, 11, 12, 13, 11, 11, 11, 11, 10, 7, + 9, 12, 12, 11, 12, 11, 12, 10, 12, 12, 11, 10, 11, 10, 10, 7, + 11, 13, 14, 12, 14, 12, 14, 11, 14, 13, 13, 11, 13, 11, 12, 7, + 12, 15, 14, 13, 15, 14, 14, 13, 15, 15, 13, 12, 13, 13, 12, 9, + 11, 14, 13, 12, 14, 13, 13, 11, 14, 14, 12, 11, 13, 12, 11, 7, + 11, 14, 14, 12, 14, 13, 14, 11, 14, 14, 13, 11, 13, 12, 12, 7, + 11, 15, 15, 14, 13, 13, 14, 13, 14, 15, 14, 13, 11, 11, 12, 9, + 12, 15, 15, 14, 14, 12, 14, 12, 14, 14, 14, 13, 12, 11, 12, 8, + 13, 16, 16, 15, 15, 12, 16, 13, 16, 15, 15, 14, 14, 12, 14, 9, + 12, 15, 15, 14, 14, 14, 14, 13, 15, 15, 14, 13, 12, 12, 12, 9, + 11, 14, 14, 13, 13, 12, 13, 11, 14, 13, 13, 12, 12, 11, 11, 7, + 12, 14, 15, 13, 14, 12, 14, 11, 15, 14, 13, 12, 13, 11, 12, 7, + 13, 16, 16, 15, 16, 15, 15, 14, 16, 16, 15, 14, 14, 14, 12, 9, + 12, 15, 14, 13, 14, 13, 14, 12, 15, 14, 13, 12, 13, 12, 12, 8, + 12, 14, 14, 13, 15, 13, 14, 11, 14, 14, 13, 12, 13, 12, 12, 6, + 10, 14, 14, 13, 14, 14, 14, 13, 12, 13, 12, 12, 12, 12, 11, 9, + 12, 15, 15, 14, 15, 14, 16, 14, 14, 14, 13, 12, 14, 13, 13, 9, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 16, 11, + 11, 15, 14, 14, 15, 14, 14, 14, 13, 14, 11, 12, 13, 13, 12, 9, + 12, 15, 14, 14, 15, 14, 15, 13, 14, 14, 13, 12, 14, 13, 13, 9, + 13, 16, 16, 14, 16, 15, 16, 14, 16, 15, 15, 12, 16, 14, 14, 9, + 13, 16, 14, 15, 16, 16, 16, 14, 14, 16, 11, 12, 15, 14, 12, 9, + 13, 16, 15, 14, 16, 15, 16, 14, 15, 15, 12, 11, 15, 14, 13, 9, + 14, 16, 16, 13, 16, 16, 16, 14, 16, 15, 13, 11, 16, 14, 14, 9, + 11, 15, 15, 14, 14, 14, 14, 13, 13, 14, 13, 13, 11, 11, 11, 9, + 12, 15, 15, 14, 15, 14, 15, 13, 14, 14, 13, 13, 13, 12, 12, 9, + 13, 16, 16, 16, 16, 14, 16, 14, 16, 15, 16, 14, 15, 12, 14, 9, + 11, 15, 14, 14, 15, 14, 14, 13, 14, 14, 12, 12, 12, 12, 11, 8, + 11, 14, 14, 13, 14, 13, 13, 12, 13, 13, 12, 11, 12, 11, 11, 7, + 12, 14, 15, 13, 15, 13, 14, 13, 14, 14, 13, 12, 13, 12, 12, 8, + 13, 16, 15, 15, 16, 15, 15, 14, 15, 16, 12, 12, 14, 14, 11, 9, + 12, 15, 14, 13, 15, 13, 14, 12, 14, 14, 12, 11, 13, 12, 11, 7, + 12, 14, 14, 13, 15, 13, 14, 12, 15, 14, 13, 10, 13, 12, 12, 6, + 12, 16, 16, 15, 14, 14, 15, 14, 13, 15, 14, 14, 10, 11, 11, 9, + 13, 16, 16, 15, 15, 14, 15, 14, 15, 15, 15, 14, 12, 11, 12, 8, + 14, 16, 16, 16, 16, 14, 16, 14, 16, 15, 15, 14, 14, 11, 14, 8, + 12, 16, 16, 15, 15, 14, 15, 14, 14, 16, 14, 14, 12, 12, 11, 8, + 11, 14, 14, 13, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11, 7, + 12, 14, 15, 13, 14, 13, 14, 12, 14, 14, 13, 12, 13, 11, 12, 6, + 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 14, 13, 13, 13, 11, 8, + 12, 15, 15, 13, 15, 13, 14, 12, 14, 14, 13, 12, 13, 12, 10, 6, + 11, 14, 13, 12, 14, 12, 13, 10, 14, 13, 12, 10, 12, 10, 10, 4, +}, +{ + 4, 6, 6, 6, 6, 6, 7, 6, 6, 7, 6, 6, 6, 6, 6, 3, + 6, 9, 10, 9, 10, 9, 11, 9, 10, 10, 10, 9, 10, 9, 10, 6, + 10, 11, 14, 11, 14, 11, 14, 11, 14, 13, 14, 11, 14, 11, 13, 9, + 6, 10, 9, 9, 10, 10, 10, 9, 10, 11, 9, 9, 10, 10, 9, 6, + 8, 11, 11, 9, 12, 11, 12, 10, 12, 12, 11, 10, 12, 11, 11, 7, + 11, 13, 14, 11, 15, 13, 15, 11, 15, 14, 14, 11, 15, 13, 14, 9, + 10, 13, 11, 11, 14, 14, 13, 11, 14, 14, 11, 11, 13, 13, 11, 9, + 11, 14, 12, 11, 15, 14, 14, 11, 15, 15, 13, 11, 14, 14, 13, 9, + 12, 14, 13, 10, 16, 15, 16, 11, 16, 16, 14, 11, 16, 14, 14, 9, + 6, 10, 10, 10, 9, 9, 10, 9, 10, 11, 10, 10, 9, 9, 9, 6, + 8, 11, 12, 11, 11, 10, 12, 10, 12, 12, 12, 11, 11, 10, 11, 7, + 11, 13, 15, 13, 14, 11, 15, 11, 15, 14, 14, 13, 14, 12, 14, 9, + 8, 12, 12, 12, 12, 12, 12, 11, 12, 13, 11, 11, 11, 11, 11, 8, + 9, 12, 12, 11, 12, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11, 8, + 11, 14, 15, 13, 14, 13, 15, 11, 15, 15, 14, 13, 15, 13, 14, 9, + 12, 16, 14, 14, 15, 15, 14, 12, 15, 16, 14, 13, 14, 14, 13, 10, + 11, 15, 14, 13, 15, 14, 15, 12, 15, 16, 14, 13, 15, 14, 13, 9, + 13, 15, 15, 12, 16, 15, 16, 12, 16, 16, 15, 13, 15, 14, 14, 9, + 10, 14, 14, 14, 11, 11, 13, 11, 14, 14, 14, 13, 11, 11, 11, 9, + 11, 14, 15, 14, 13, 11, 14, 12, 15, 15, 15, 14, 13, 11, 13, 9, + 13, 14, 16, 15, 14, 11, 16, 12, 16, 16, 16, 14, 15, 12, 15, 10, + 12, 16, 15, 15, 14, 14, 14, 12, 16, 16, 14, 14, 14, 13, 13, 10, + 12, 15, 15, 14, 14, 13, 14, 12, 15, 16, 14, 14, 14, 13, 13, 9, + 13, 16, 16, 14, 16, 13, 16, 12, 16, 16, 16, 14, 16, 13, 15, 10, + 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 16, 16, 16, 16, 14, 11, + 13, 16, 16, 15, 16, 16, 16, 13, 16, 16, 16, 15, 16, 15, 14, 10, + 14, 16, 16, 14, 16, 14, 16, 12, 16, 16, 16, 15, 16, 15, 15, 10, + 6, 10, 10, 10, 10, 10, 11, 10, 9, 10, 9, 9, 9, 9, 9, 6, + 9, 12, 12, 11, 12, 11, 13, 11, 12, 12, 11, 10, 12, 11, 11, 8, + 12, 14, 15, 14, 15, 14, 16, 13, 15, 14, 14, 12, 15, 13, 14, 10, + 8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 11, 10, 7, + 9, 12, 12, 11, 13, 12, 13, 11, 12, 13, 11, 10, 12, 12, 11, 8, + 11, 14, 14, 13, 15, 14, 15, 13, 15, 14, 14, 12, 15, 13, 14, 9, + 11, 15, 12, 13, 15, 15, 14, 13, 14, 15, 11, 11, 14, 14, 12, 9, + 11, 14, 13, 13, 15, 14, 15, 13, 15, 15, 13, 11, 15, 14, 13, 9, + 13, 15, 15, 12, 16, 15, 16, 13, 16, 15, 14, 11, 16, 15, 14, 9, + 8, 12, 12, 11, 11, 11, 12, 11, 11, 12, 11, 11, 9, 10, 10, 7, + 9, 12, 13, 12, 12, 11, 13, 11, 12, 13, 12, 12, 11, 11, 11, 8, + 12, 14, 15, 14, 15, 13, 16, 13, 15, 14, 15, 13, 14, 12, 14, 9, + 9, 13, 12, 12, 12, 12, 13, 12, 12, 13, 11, 11, 11, 11, 10, 8, + 9, 12, 12, 12, 12, 12, 13, 11, 12, 13, 11, 11, 12, 11, 11, 7, + 11, 13, 14, 13, 14, 13, 15, 12, 14, 14, 14, 12, 14, 12, 13, 8, + 12, 15, 14, 14, 15, 15, 14, 13, 15, 16, 13, 13, 14, 14, 12, 9, + 11, 14, 13, 13, 14, 14, 14, 12, 14, 15, 13, 12, 14, 13, 12, 8, + 11, 14, 14, 13, 15, 14, 15, 12, 15, 15, 14, 12, 14, 13, 13, 8, + 11, 14, 14, 14, 13, 13, 14, 13, 13, 14, 14, 13, 11, 11, 11, 9, + 11, 15, 15, 14, 14, 13, 15, 13, 14, 15, 14, 14, 13, 11, 13, 9, + 13, 16, 16, 16, 15, 13, 16, 13, 16, 16, 16, 15, 15, 12, 15, 10, + 11, 15, 15, 15, 14, 14, 14, 13, 15, 15, 14, 14, 13, 13, 12, 9, + 11, 14, 14, 13, 13, 13, 14, 12, 14, 14, 13, 13, 13, 12, 12, 8, + 12, 15, 15, 14, 15, 13, 15, 12, 15, 15, 14, 13, 14, 12, 13, 8, + 13, 16, 16, 16, 16, 16, 16, 14, 16, 16, 15, 15, 15, 15, 13, 10, + 12, 15, 15, 14, 15, 14, 15, 13, 15, 16, 14, 13, 14, 14, 13, 9, + 12, 15, 15, 14, 15, 14, 15, 12, 15, 15, 14, 13, 14, 13, 13, 8, + 10, 14, 13, 13, 14, 13, 14, 13, 11, 13, 11, 11, 11, 11, 11, 9, + 12, 15, 16, 14, 15, 14, 16, 14, 14, 14, 14, 13, 14, 13, 13, 10, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 13, 16, 14, 16, 11, + 11, 15, 14, 14, 15, 14, 15, 14, 13, 14, 11, 12, 13, 13, 11, 9, + 12, 15, 15, 14, 15, 15, 16, 14, 14, 14, 13, 12, 14, 13, 13, 9, + 13, 16, 16, 15, 16, 16, 16, 15, 16, 15, 15, 12, 16, 14, 15, 10, + 12, 16, 14, 15, 16, 16, 16, 14, 14, 16, 11, 12, 14, 15, 12, 9, + 13, 16, 15, 14, 16, 16, 16, 14, 15, 16, 13, 12, 15, 15, 13, 9, + 14, 16, 16, 14, 16, 16, 16, 15, 16, 16, 14, 12, 16, 15, 15, 10, + 11, 14, 14, 14, 14, 14, 14, 13, 12, 14, 13, 13, 11, 11, 11, 9, + 11, 15, 15, 14, 14, 14, 16, 14, 14, 14, 14, 13, 13, 12, 13, 9, + 13, 16, 16, 16, 16, 15, 16, 15, 16, 15, 16, 14, 15, 13, 15, 10, + 11, 15, 15, 14, 14, 14, 15, 14, 14, 15, 13, 13, 12, 13, 11, 9, + 11, 14, 14, 13, 14, 14, 14, 13, 13, 14, 13, 12, 13, 12, 12, 8, + 12, 15, 15, 14, 16, 14, 16, 14, 15, 15, 15, 13, 14, 13, 14, 9, + 13, 16, 15, 16, 16, 16, 16, 15, 15, 16, 13, 13, 14, 14, 12, 9, + 12, 15, 14, 14, 15, 15, 15, 13, 14, 15, 13, 12, 14, 13, 12, 8, + 12, 15, 14, 14, 15, 15, 15, 13, 15, 15, 14, 12, 14, 13, 13, 8, + 12, 16, 15, 15, 13, 14, 15, 14, 13, 15, 14, 14, 10, 11, 11, 9, + 12, 16, 16, 15, 15, 14, 16, 14, 15, 15, 15, 14, 13, 12, 13, 9, + 14, 16, 16, 16, 16, 14, 16, 15, 16, 15, 16, 15, 14, 12, 15, 10, + 12, 16, 15, 15, 15, 15, 15, 14, 15, 16, 14, 14, 12, 13, 11, 9, + 11, 15, 15, 14, 14, 14, 15, 13, 14, 15, 14, 13, 13, 12, 12, 8, + 12, 15, 15, 14, 15, 14, 15, 13, 15, 15, 14, 13, 14, 12, 13, 8, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14, 14, 14, 14, 11, 9, + 12, 15, 15, 14, 15, 15, 15, 13, 15, 15, 14, 13, 14, 13, 12, 8, + 11, 14, 14, 13, 14, 13, 14, 12, 13, 14, 13, 12, 13, 12, 12, 7, +}, +{ + 2, 6, 6, 5, 6, 6, 7, 6, 6, 7, 6, 6, 6, 6, 6, 3, + 6, 9, 10, 9, 10, 9, 11, 9, 10, 10, 10, 9, 10, 9, 10, 7, + 10, 11, 14, 11, 14, 11, 14, 11, 14, 13, 14, 12, 14, 12, 13, 9, + 6, 10, 9, 9, 10, 10, 10, 9, 10, 11, 9, 9, 10, 10, 9, 7, + 8, 11, 11, 9, 12, 11, 12, 10, 12, 12, 11, 10, 12, 11, 11, 8, + 11, 13, 14, 11, 16, 13, 15, 12, 16, 14, 14, 12, 15, 13, 14, 10, + 10, 13, 11, 11, 14, 14, 13, 11, 13, 14, 11, 11, 13, 13, 11, 9, + 11, 13, 13, 11, 15, 14, 14, 12, 15, 15, 13, 12, 15, 14, 13, 10, + 12, 14, 14, 11, 16, 15, 16, 12, 16, 16, 15, 12, 16, 15, 15, 10, + 6, 10, 10, 10, 9, 9, 10, 9, 10, 11, 10, 10, 9, 9, 9, 7, + 8, 11, 12, 11, 11, 10, 12, 10, 12, 12, 12, 11, 11, 10, 11, 8, + 12, 13, 16, 13, 14, 11, 16, 12, 16, 15, 15, 13, 14, 12, 14, 10, + 9, 13, 12, 12, 12, 12, 12, 11, 13, 13, 12, 12, 12, 12, 11, 8, + 10, 13, 13, 12, 13, 12, 13, 11, 14, 14, 13, 12, 13, 12, 12, 9, + 12, 14, 16, 13, 15, 13, 15, 12, 16, 16, 16, 13, 16, 14, 14, 10, + 12, 16, 14, 14, 16, 15, 14, 13, 16, 16, 14, 14, 15, 15, 13, 11, + 12, 16, 15, 14, 16, 15, 15, 12, 16, 16, 15, 14, 16, 15, 14, 10, + 14, 16, 16, 14, 16, 15, 16, 13, 16, 16, 16, 14, 16, 16, 15, 11, + 10, 14, 14, 13, 11, 11, 13, 12, 14, 14, 13, 13, 11, 11, 12, 9, + 12, 14, 16, 14, 13, 11, 14, 12, 16, 15, 15, 14, 14, 12, 13, 10, + 13, 14, 16, 15, 14, 11, 16, 12, 16, 16, 16, 15, 16, 13, 15, 11, + 12, 16, 15, 15, 14, 14, 14, 13, 16, 16, 15, 15, 14, 14, 13, 11, + 13, 16, 16, 15, 14, 14, 15, 13, 16, 16, 16, 15, 15, 14, 14, 11, + 14, 16, 16, 15, 16, 14, 16, 13, 16, 16, 16, 15, 16, 14, 15, 11, + 15, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14, 12, + 15, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 15, 12, + 15, 16, 16, 15, 16, 15, 16, 13, 16, 16, 16, 16, 16, 16, 16, 11, + 6, 10, 10, 10, 10, 10, 11, 10, 9, 10, 9, 9, 9, 9, 9, 7, + 9, 12, 13, 12, 13, 12, 14, 12, 12, 12, 12, 11, 12, 11, 11, 8, + 12, 14, 16, 14, 16, 14, 16, 14, 15, 14, 15, 13, 16, 13, 14, 11, + 8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 11, 10, 8, + 10, 13, 13, 12, 14, 13, 14, 12, 13, 13, 12, 11, 13, 12, 12, 9, + 12, 15, 15, 13, 16, 15, 16, 14, 16, 15, 15, 12, 16, 14, 15, 10, + 11, 15, 13, 13, 16, 15, 14, 13, 14, 15, 11, 12, 14, 14, 12, 10, + 12, 16, 14, 13, 16, 16, 16, 14, 16, 15, 13, 12, 15, 15, 14, 10, + 14, 16, 16, 14, 16, 16, 16, 14, 16, 16, 15, 13, 16, 16, 15, 11, + 8, 12, 12, 12, 11, 11, 12, 11, 11, 12, 11, 11, 9, 10, 10, 8, + 10, 13, 14, 13, 13, 12, 14, 12, 13, 13, 13, 12, 12, 11, 12, 9, + 13, 15, 16, 15, 16, 14, 16, 14, 16, 15, 16, 14, 15, 13, 15, 11, + 10, 13, 13, 13, 13, 13, 13, 12, 13, 14, 12, 12, 12, 12, 11, 9, + 10, 13, 13, 13, 13, 13, 14, 12, 13, 14, 13, 12, 12, 12, 12, 9, + 12, 15, 15, 14, 16, 14, 16, 13, 16, 15, 15, 13, 15, 13, 14, 10, + 13, 16, 15, 15, 16, 16, 15, 14, 16, 16, 13, 14, 15, 15, 12, 10, + 12, 16, 14, 14, 16, 16, 15, 13, 16, 16, 14, 13, 15, 14, 13, 10, + 13, 16, 16, 14, 16, 15, 16, 13, 16, 16, 16, 13, 16, 15, 15, 10, + 11, 15, 15, 14, 13, 13, 14, 13, 13, 15, 14, 14, 11, 12, 12, 10, + 12, 15, 16, 15, 14, 13, 16, 14, 16, 15, 16, 14, 13, 12, 13, 10, + 14, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 16, 13, 16, 11, + 12, 16, 16, 16, 15, 15, 15, 14, 15, 16, 14, 14, 13, 14, 12, 10, + 12, 16, 16, 15, 15, 14, 16, 13, 16, 16, 15, 14, 14, 13, 13, 10, + 13, 16, 16, 15, 16, 14, 16, 13, 16, 16, 16, 15, 16, 14, 15, 10, + 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 13, 12, + 14, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 16, 15, 14, 11, + 14, 16, 16, 15, 16, 16, 16, 13, 16, 16, 16, 15, 16, 15, 14, 10, + 10, 14, 13, 13, 13, 13, 14, 13, 11, 13, 11, 11, 11, 11, 11, 9, + 12, 15, 16, 15, 16, 15, 16, 14, 14, 14, 14, 13, 14, 13, 14, 11, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, 16, 12, + 11, 15, 14, 14, 15, 15, 15, 14, 13, 14, 11, 12, 13, 13, 12, 10, + 13, 16, 15, 15, 16, 16, 16, 15, 15, 15, 13, 12, 15, 14, 13, 10, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 12, + 13, 16, 14, 15, 16, 16, 16, 15, 14, 16, 11, 12, 15, 15, 12, 10, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 16, 16, 14, 11, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 11, + 11, 15, 15, 14, 13, 14, 14, 14, 13, 14, 13, 13, 11, 12, 11, 10, + 12, 16, 16, 16, 16, 15, 16, 15, 15, 15, 15, 14, 13, 12, 14, 10, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 14, 16, 12, + 12, 16, 15, 15, 16, 16, 16, 14, 14, 15, 13, 13, 13, 13, 12, 10, + 12, 16, 16, 15, 15, 15, 16, 14, 14, 15, 14, 13, 14, 13, 13, 10, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 15, 11, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 15, 15, 12, 11, + 13, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, 13, 16, 14, 13, 10, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 15, 10, + 12, 16, 16, 15, 14, 15, 16, 14, 13, 15, 14, 14, 11, 12, 12, 10, + 13, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 15, 13, 12, 14, 11, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 11, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 15, 15, 13, 14, 12, 11, + 13, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 14, 13, 13, 10, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 15, 14, 14, 10, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 15, 16, 13, 11, + 14, 16, 16, 16, 16, 16, 16, 14, 16, 16, 15, 14, 15, 14, 13, 10, + 12, 15, 15, 14, 15, 14, 16, 14, 14, 16, 15, 13, 14, 13, 13, 9, +}, +{ + 2, 5, 5, 5, 5, 5, 6, 6, 5, 6, 5, 6, 5, 6, 6, 4, + 6, 8, 10, 8, 10, 9, 11, 9, 10, 10, 10, 9, 10, 9, 10, 8, + 10, 11, 13, 11, 13, 11, 14, 11, 14, 13, 13, 12, 13, 12, 13, 10, + 6, 10, 8, 9, 10, 10, 10, 9, 10, 11, 9, 9, 10, 10, 9, 7, + 8, 11, 11, 10, 12, 11, 12, 10, 12, 12, 11, 10, 12, 12, 11, 9, + 11, 13, 14, 11, 15, 14, 15, 12, 16, 14, 14, 12, 15, 14, 14, 11, + 10, 13, 11, 11, 14, 13, 13, 12, 13, 14, 11, 11, 13, 13, 12, 10, + 11, 14, 13, 11, 16, 14, 14, 12, 15, 15, 14, 12, 15, 14, 14, 11, + 12, 14, 14, 11, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 15, 12, + 6, 10, 10, 10, 8, 9, 10, 9, 10, 11, 10, 10, 9, 9, 9, 8, + 8, 11, 12, 12, 11, 10, 12, 11, 12, 12, 12, 12, 12, 11, 12, 9, + 11, 13, 16, 14, 14, 12, 15, 12, 16, 15, 16, 14, 14, 13, 14, 11, + 9, 13, 12, 12, 12, 12, 12, 11, 13, 13, 12, 12, 12, 12, 11, 10, + 10, 13, 13, 12, 13, 12, 13, 11, 14, 14, 13, 13, 13, 13, 12, 10, + 13, 14, 16, 14, 15, 14, 16, 13, 16, 16, 16, 14, 16, 14, 15, 12, + 12, 16, 14, 14, 16, 15, 14, 13, 16, 16, 14, 14, 15, 15, 13, 12, + 13, 16, 15, 14, 16, 16, 15, 13, 16, 16, 15, 14, 16, 16, 14, 12, + 14, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 12, + 10, 13, 14, 13, 11, 11, 13, 12, 13, 14, 13, 13, 11, 12, 12, 10, + 11, 14, 15, 15, 13, 12, 14, 13, 16, 16, 16, 15, 14, 13, 14, 11, + 12, 14, 16, 16, 14, 12, 16, 13, 16, 16, 16, 16, 15, 13, 16, 12, + 12, 16, 15, 16, 14, 15, 14, 14, 16, 16, 15, 16, 14, 14, 13, 12, + 13, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16, 14, 15, 12, + 14, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 16, 15, 16, 13, + 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 15, 13, + 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 13, + 15, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 13, + 6, 10, 10, 10, 10, 10, 10, 10, 8, 10, 9, 9, 8, 9, 9, 7, + 9, 12, 13, 12, 13, 12, 13, 12, 12, 12, 12, 11, 12, 11, 12, 10, + 12, 14, 16, 14, 16, 14, 16, 14, 16, 15, 15, 14, 16, 14, 15, 12, + 8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 12, 10, 9, + 10, 13, 13, 12, 14, 13, 14, 12, 13, 13, 12, 11, 13, 13, 12, 10, + 13, 15, 16, 14, 16, 16, 16, 14, 16, 15, 15, 13, 16, 15, 15, 12, + 11, 15, 13, 13, 15, 15, 15, 14, 14, 14, 11, 12, 14, 14, 12, 11, + 13, 16, 14, 14, 16, 16, 16, 14, 16, 15, 13, 13, 16, 14, 14, 11, + 14, 16, 16, 14, 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 16, 12, + 8, 12, 12, 12, 11, 11, 12, 12, 11, 12, 11, 11, 9, 10, 10, 9, + 10, 13, 14, 13, 13, 12, 14, 13, 13, 13, 13, 13, 12, 11, 12, 10, + 13, 15, 16, 15, 16, 14, 16, 14, 16, 16, 16, 15, 16, 13, 15, 12, + 10, 14, 13, 13, 13, 13, 13, 13, 13, 14, 12, 12, 12, 12, 11, 10, + 10, 13, 13, 13, 13, 13, 14, 12, 13, 14, 13, 12, 13, 12, 12, 10, + 13, 16, 16, 14, 16, 15, 16, 14, 16, 16, 15, 14, 16, 14, 15, 11, + 13, 16, 15, 16, 16, 16, 15, 14, 16, 16, 14, 14, 15, 15, 13, 12, + 13, 16, 15, 14, 16, 16, 16, 14, 16, 16, 14, 14, 15, 15, 14, 11, + 14, 16, 16, 15, 16, 16, 16, 14, 16, 16, 16, 15, 16, 16, 15, 12, + 11, 14, 15, 14, 13, 13, 14, 14, 13, 15, 14, 14, 11, 12, 12, 11, + 13, 16, 16, 16, 14, 14, 16, 14, 16, 16, 16, 15, 14, 13, 14, 12, + 14, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13, + 13, 16, 16, 16, 15, 16, 15, 15, 16, 16, 15, 16, 14, 14, 13, 12, + 13, 16, 16, 15, 15, 14, 16, 14, 16, 16, 16, 15, 14, 14, 14, 11, + 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 15, 16, 12, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 13, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, + 9, 13, 13, 13, 13, 13, 14, 13, 10, 12, 11, 12, 11, 12, 11, 10, + 12, 15, 16, 15, 16, 16, 16, 16, 14, 14, 14, 13, 14, 13, 14, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, + 11, 15, 14, 14, 15, 14, 15, 14, 13, 14, 11, 12, 13, 13, 12, 11, + 13, 16, 16, 15, 16, 16, 16, 15, 15, 15, 14, 13, 16, 15, 14, 12, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 13, + 12, 16, 14, 15, 16, 16, 16, 16, 14, 16, 11, 13, 15, 16, 13, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 16, 16, 15, 12, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 13, + 11, 15, 14, 14, 13, 14, 15, 14, 12, 14, 13, 13, 11, 12, 12, 11, + 13, 16, 16, 16, 16, 15, 16, 16, 15, 15, 15, 15, 14, 13, 14, 12, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 15, 14, 16, 13, 14, 13, 14, 13, 11, + 13, 16, 16, 16, 16, 16, 16, 15, 15, 16, 15, 14, 14, 14, 14, 11, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 15, 16, 16, 13, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 16, 16, 15, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, + 11, 16, 16, 15, 13, 15, 16, 15, 13, 15, 15, 15, 11, 12, 12, 11, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 15, 12, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 14, 14, 13, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 12, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 14, 13, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 12, + 12, 14, 14, 14, 14, 15, 16, 14, 14, 16, 15, 14, 14, 15, 14, 11, +}, +{ + 1, 5, 5, 6, 5, 6, 7, 7, 5, 7, 6, 7, 5, 6, 6, 6, + 6, 9, 10, 9, 10, 9, 11, 10, 11, 11, 11, 10, 11, 10, 11, 9, + 10, 11, 14, 12, 14, 12, 16, 12, 16, 13, 16, 13, 14, 13, 16, 12, + 6, 10, 9, 9, 10, 11, 11, 10, 10, 11, 9, 10, 10, 11, 10, 9, + 8, 11, 11, 10, 13, 12, 13, 12, 13, 13, 12, 12, 13, 13, 13, 11, + 11, 13, 16, 12, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 13, + 10, 14, 11, 12, 14, 14, 13, 13, 13, 16, 12, 13, 14, 16, 13, 12, + 11, 14, 13, 12, 16, 16, 16, 14, 16, 16, 14, 14, 16, 16, 16, 13, + 12, 14, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 6, 10, 10, 11, 9, 9, 11, 10, 10, 11, 11, 11, 9, 10, 10, 9, + 9, 12, 13, 12, 12, 11, 13, 12, 13, 13, 13, 13, 12, 12, 13, 11, + 12, 13, 16, 16, 16, 13, 16, 14, 16, 16, 16, 16, 16, 14, 16, 13, + 9, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, 13, 12, 11, + 10, 14, 14, 13, 14, 13, 14, 13, 16, 16, 14, 15, 14, 14, 14, 12, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 14, 14, 16, 11, 12, 14, 13, 14, 16, 16, 16, 12, 13, 13, 12, + 12, 16, 16, 16, 13, 13, 16, 14, 16, 16, 16, 16, 16, 14, 16, 13, + 13, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 6, 10, 10, 10, 10, 11, 11, 11, 9, 11, 9, 10, 9, 10, 10, 9, + 9, 13, 13, 13, 13, 13, 14, 13, 12, 13, 13, 12, 13, 12, 13, 11, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 8, 13, 12, 12, 13, 13, 13, 13, 11, 13, 10, 12, 12, 13, 12, 11, + 10, 14, 13, 13, 16, 16, 16, 14, 14, 14, 13, 13, 14, 14, 14, 12, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 11, 16, 13, 16, 16, 16, 16, 16, 14, 16, 12, 13, 16, 16, 14, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 13, 13, 13, 11, 12, 13, 13, 11, 13, 12, 13, 10, 12, 12, 11, + 10, 14, 16, 16, 14, 13, 16, 14, 14, 16, 16, 14, 13, 13, 14, 12, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 16, 14, 16, 14, 14, 14, 14, 13, 16, 13, 14, 13, 14, 12, 12, + 10, 14, 14, 14, 14, 16, 16, 14, 14, 16, 14, 14, 14, 14, 14, 12, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 12, 14, 14, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 14, 13, 14, 13, 14, 16, 16, 11, 13, 12, 13, 11, 13, 12, 12, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 14, 16, 16, 16, 16, 16, 13, 16, 12, 13, 14, 16, 13, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 14, 16, 12, 16, 16, 16, 14, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 14, 16, 16, 16, 13, 16, 14, 16, 12, 13, 13, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 12, 16, 14, 14, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, +}, +{ + 1, 5, 5, 6, 5, 6, 7, 8, 5, 7, 6, 8, 6, 7, 7, 7, + 5, 9, 10, 10, 10, 10, 12, 11, 10, 11, 11, 11, 10, 11, 12, 10, + 9, 11, 13, 12, 13, 12, 16, 14, 16, 14, 16, 16, 16, 13, 16, 13, + 5, 10, 9, 10, 10, 11, 11, 11, 10, 11, 9, 11, 10, 11, 11, 10, + 8, 11, 11, 11, 12, 13, 13, 13, 12, 13, 12, 12, 13, 13, 13, 12, + 11, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 14, 11, 12, 14, 16, 13, 14, 13, 16, 12, 14, 16, 16, 13, 13, + 11, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 14, 14, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 10, 11, 11, 9, 10, 11, 11, 10, 12, 11, 12, 9, 11, 11, 11, + 8, 12, 13, 13, 11, 11, 14, 13, 13, 14, 13, 16, 12, 12, 13, 12, + 11, 13, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 13, 12, 13, 12, 13, 13, 14, 13, 16, 13, 16, 13, 16, 13, 13, + 10, 14, 13, 14, 13, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 14, 16, 16, 11, 12, 14, 16, 13, 16, 16, 16, 12, 14, 13, 13, + 11, 16, 16, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 14, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 10, 10, 11, 10, 11, 12, 12, 8, 11, 10, 11, 9, 11, 11, 11, + 9, 12, 13, 13, 13, 13, 16, 16, 12, 13, 13, 13, 13, 13, 16, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 13, 11, 13, 12, 13, 13, 14, 11, 13, 10, 13, 12, 14, 12, 12, + 10, 14, 13, 14, 16, 16, 16, 16, 13, 16, 13, 14, 16, 16, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 13, 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 13, 13, 13, 11, 13, 14, 16, 11, 13, 13, 14, 10, 12, 12, 12, + 10, 14, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, 13, 13, 16, 14, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 14, 16, 13, 16, 16, 16, 13, 16, 13, 16, 13, 16, 13, 14, + 10, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 13, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 14, 13, 16, 13, 16, 16, 16, 10, 14, 12, 14, 11, 13, 13, 13, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 16, 16, 16, 16, 13, 16, 13, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14, +} +}; + + +static const uint8_t rv34_inter_cbp[NUM_INTER_TABLES][4][CBP_VLC_SIZE] = { +{ + { 0, 6, 6, 3, 6, 4, 5, 3, 6, 5, 4, 3, 3, 4, 4, 3 }, + { 0, 6, 6, 4, 6, 4, 5, 3, 6, 5, 4, 3, 4, 4, 4, 2 }, + { 0, 7, 7, 4, 7, 5, 5, 4, 7, 5, 5, 4, 5, 4, 4, 1 }, + { 0, 7, 7, 5, 7, 5, 6, 4, 7, 6, 5, 3, 5, 4, 4, 1 } +}, +{ + { 0, 6, 6, 3, 6, 3, 5, 4, 6, 5, 3, 4, 3, 4, 4, 3 }, + { 0, 6, 6, 4, 6, 4, 4, 4, 6, 4, 4, 3, 4, 4, 4, 2 }, + { 0, 6, 6, 4, 6, 4, 5, 4, 6, 5, 4, 3, 4, 4, 3, 2 }, + { 0, 7, 7, 5, 7, 5, 6, 4, 7, 6, 5, 3, 5, 4, 4, 1 } +}, +{ + { 0, 6, 6, 3, 6, 3, 5, 4, 6, 5, 3, 4, 3, 4, 4, 3 }, + { 0, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2 }, + { 0, 6, 6, 4, 6, 4, 5, 3, 6, 5, 4, 3, 4, 4, 4, 2 }, + { 0, 7, 7, 5, 7, 5, 6, 4, 7, 6, 5, 3, 5, 4, 4, 1 } +}, +{ + { 0, 6, 6, 3, 6, 3, 5, 4, 6, 5, 3, 4, 3, 4, 4, 3 }, + { 0, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2 }, + { 0, 6, 6, 4, 6, 4, 5, 3, 6, 5, 4, 3, 4, 4, 4, 2 }, + { 0, 7, 7, 4, 7, 5, 6, 4, 7, 6, 5, 4, 4, 4, 4, 1 } +}, +{ + { 0, 5, 5, 3, 5, 3, 5, 4, 5, 5, 3, 4, 3, 4, 4, 4 }, + { 0, 5, 5, 3, 5, 4, 5, 4, 5, 5, 3, 4, 3, 4, 4, 3 }, + { 0, 6, 6, 4, 6, 4, 5, 4, 6, 5, 4, 3, 4, 4, 3, 2 }, + { 0, 7, 7, 4, 7, 5, 6, 4, 7, 6, 5, 4, 4, 4, 4, 1 } +}, +{ + { 0, 5, 5, 3, 5, 3, 5, 4, 5, 5, 3, 4, 3, 4, 4, 4 }, + { 0, 5, 5, 3, 5, 4, 5, 4, 5, 5, 3, 4, 3, 4, 4, 3 }, + { 0, 5, 5, 3, 5, 4, 4, 4, 5, 4, 4, 4, 3, 4, 4, 3 }, + { 0, 6, 6, 4, 6, 4, 5, 4, 6, 5, 4, 3, 4, 4, 3, 2 } +}, +{ + { 0, 4, 4, 3, 4, 3, 5, 5, 4, 5, 3, 5, 3, 5, 4, 5 }, + { 0, 4, 4, 3, 4, 4, 5, 4, 4, 5, 3, 5, 3, 5, 4, 4 }, + { 0, 4, 4, 3, 4, 4, 5, 4, 4, 5, 4, 4, 3, 4, 4, 4 }, + { 0, 4, 4, 3, 5, 4, 5, 4, 5, 5, 4, 4, 3, 4, 4, 3 } +} +}; + + +static const uint8_t rv34_table_inter_firstpat[NUM_INTER_TABLES][2][FIRSTBLK_VLC_SIZE] = { + { + { + 0, 7, 5, 7, 5, 7, 6, 6, 7, 10, 7, 9, 8, 9, 8, 7, + 12, 14, 11, 12, 12, 12, 11, 9, 6, 9, 6, 8, 7, 9, 7, 7, + 8, 11, 8, 9, 9, 10, 9, 8, 13, 15, 12, 12, 12, 13, 11, 9, + 10, 13, 9, 10, 11, 12, 9, 8, 12, 14, 10, 11, 12, 13, 10, 9, + 16, 16, 12, 12, 14, 13, 11, 9, 6, 9, 7, 9, 7, 9, 8, 7, + 9, 11, 9, 10, 9, 10, 9, 8, 14, 16, 12, 12, 13, 13, 11, 9, + 8, 11, 8, 10, 9, 10, 9, 8, 10, 13, 10, 11, 10, 11, 9, 8, + 14, 16, 12, 12, 13, 13, 11, 9, 12, 14, 10, 11, 12, 13, 10, 9, + 13, 16, 11, 12, 13, 13, 10, 9, 16, 16, 13, 12, 14, 14, 11, 9, + 11, 13, 11, 12, 10, 11, 10, 9, 13, 14, 12, 12, 11, 12, 10, 9, + 16, 16, 13, 13, 13, 13, 11, 9, 12, 15, 12, 12, 11, 12, 10, 9, + 13, 16, 13, 13, 12, 12, 11, 9, 16, 16, 14, 13, 13, 13, 11, 9, + 14, 16, 13, 13, 13, 14, 11, 9, 16, 16, 13, 13, 14, 14, 11, 9, + 16, 16, 13, 13, 14, 13, 11, 8, 4, 9, 6, 8, 6, 9, 7, 7, + 8, 11, 8, 9, 9, 10, 8, 8, 13, 15, 12, 12, 13, 13, 11, 9, + 7, 10, 7, 9, 8, 10, 8, 8, 9, 12, 9, 10, 10, 11, 9, 8, + 14, 16, 12, 12, 13, 13, 11, 9, 11, 13, 9, 10, 11, 12, 9, 8, + 12, 14, 10, 11, 12, 13, 10, 9, 16, 16, 13, 12, 14, 14, 11, 9, + 7, 10, 8, 9, 8, 10, 8, 8, 10, 12, 10, 11, 10, 11, 9, 8, + 14, 16, 13, 13, 13, 13, 11, 9, 9, 12, 9, 10, 9, 11, 9, 8, + 11, 13, 10, 11, 10, 11, 10, 9, 15, 16, 13, 13, 13, 13, 11, 9, + 12, 14, 11, 11, 12, 13, 10, 9, 13, 16, 11, 12, 13, 13, 10, 9, + 16, 16, 12, 12, 14, 13, 11, 8, 11, 14, 11, 12, 10, 11, 10, 9, + 13, 15, 12, 13, 11, 12, 10, 9, 16, 16, 14, 13, 13, 13, 11, 9, + 12, 15, 12, 13, 11, 12, 10, 9, 13, 16, 13, 13, 12, 12, 11, 9, + 16, 16, 14, 13, 13, 13, 11, 9, 15, 16, 13, 13, 13, 13, 11, 9, + 16, 16, 13, 13, 13, 13, 11, 9, 16, 16, 13, 12, 13, 13, 10, 7, + 8, 11, 8, 10, 9, 11, 9, 9, 10, 13, 10, 11, 11, 12, 10, 9, + 15, 16, 13, 13, 14, 14, 12, 10, 9, 12, 9, 11, 10, 11, 9, 9, + 12, 14, 11, 11, 11, 12, 10, 9, 16, 16, 13, 13, 14, 14, 12, 10, + 12, 14, 10, 11, 12, 13, 10, 9, 14, 16, 11, 12, 13, 14, 10, 9, + 16, 16, 13, 13, 15, 14, 11, 9, 9, 12, 10, 11, 9, 11, 10, 9, + 12, 14, 11, 12, 11, 12, 10, 9, 16, 16, 14, 13, 14, 14, 12, 10, + 11, 14, 10, 12, 11, 12, 10, 9, 12, 15, 11, 12, 12, 13, 11, 10, + 16, 16, 14, 13, 14, 14, 12, 10, 13, 16, 11, 12, 13, 14, 11, 9, + 14, 16, 12, 12, 13, 14, 11, 9, 16, 16, 13, 13, 14, 14, 11, 9, + 12, 15, 12, 13, 10, 12, 10, 9, 14, 16, 13, 13, 11, 12, 11, 10, + 16, 16, 14, 14, 14, 13, 12, 9, 13, 16, 13, 13, 12, 13, 11, 10, + 14, 16, 13, 13, 12, 13, 11, 10, 16, 16, 14, 14, 13, 13, 12, 9, + 15, 16, 13, 13, 13, 14, 11, 9, 16, 16, 13, 13, 13, 14, 11, 9, + 16, 16, 13, 12, 13, 13, 10, 8, 10, 13, 10, 11, 10, 12, 10, 9, + 12, 14, 11, 12, 12, 13, 11, 10, 16, 16, 13, 13, 14, 14, 12, 9, + 11, 14, 10, 11, 11, 12, 10, 9, 13, 16, 11, 12, 12, 13, 11, 10, + 16, 16, 14, 13, 14, 14, 12, 9, 12, 15, 10, 11, 12, 13, 9, 8, + 14, 16, 11, 11, 13, 14, 10, 8, 16, 16, 12, 12, 14, 14, 10, 8, + 11, 14, 11, 12, 11, 12, 10, 9, 13, 16, 12, 13, 12, 13, 11, 10, + 16, 16, 14, 13, 14, 14, 12, 9, 12, 15, 11, 12, 11, 13, 10, 10, + 13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 14, 13, 14, 14, 12, 9, + 13, 16, 11, 11, 13, 13, 10, 8, 14, 16, 11, 12, 13, 14, 10, 8, + 16, 16, 12, 12, 14, 14, 10, 8, 12, 15, 12, 13, 10, 11, 10, 9, + 14, 16, 13, 13, 11, 12, 10, 9, 16, 16, 14, 13, 13, 13, 11, 8, + 13, 16, 12, 13, 11, 12, 10, 9, 14, 16, 13, 13, 12, 12, 10, 9, + 16, 16, 14, 13, 13, 12, 10, 8, 14, 16, 12, 12, 12, 13, 10, 8, + 14, 16, 12, 12, 12, 13, 10, 7, 16, 16, 11, 11, 12, 11, 8, 5, + }, + { + 0, 7, 4, 8, 5, 8, 7, 8, 6, 10, 7, 10, 8, 10, 9, 9, + 13, 16, 12, 13, 13, 14, 12, 12, 4, 10, 6, 9, 8, 11, 8, 9, + 8, 12, 8, 11, 10, 12, 10, 10, 14, 16, 12, 13, 14, 15, 12, 12, + 9, 14, 9, 11, 12, 14, 11, 11, 11, 15, 10, 12, 13, 14, 11, 11, + 15, 16, 13, 14, 15, 16, 13, 12, 5, 10, 7, 10, 7, 10, 9, 9, + 8, 12, 9, 11, 10, 11, 10, 10, 14, 16, 13, 14, 14, 14, 12, 12, + 8, 12, 8, 11, 10, 12, 10, 10, 10, 14, 10, 12, 11, 13, 10, 11, + 15, 16, 13, 14, 14, 15, 13, 12, 11, 16, 10, 12, 13, 15, 11, 11, + 13, 16, 11, 13, 14, 15, 12, 12, 16, 16, 14, 14, 16, 16, 13, 12, + 11, 15, 11, 13, 11, 13, 11, 11, 13, 16, 12, 14, 12, 13, 12, 12, + 16, 16, 14, 15, 15, 15, 13, 12, 12, 16, 12, 14, 12, 14, 12, 12, + 14, 16, 13, 14, 13, 14, 12, 12, 16, 16, 14, 16, 16, 16, 13, 12, + 14, 16, 13, 14, 15, 16, 13, 12, 16, 16, 14, 15, 16, 16, 13, 12, + 16, 16, 15, 16, 16, 16, 13, 12, 2, 9, 5, 8, 6, 9, 8, 9, + 7, 11, 8, 10, 9, 11, 9, 10, 13, 16, 12, 13, 14, 14, 12, 12, + 5, 11, 6, 10, 9, 11, 9, 9, 9, 13, 9, 11, 10, 12, 10, 10, + 14, 16, 12, 14, 14, 15, 12, 12, 9, 14, 9, 11, 12, 14, 10, 11, + 11, 16, 10, 12, 13, 14, 11, 11, 16, 16, 13, 14, 15, 16, 13, 12, + 6, 11, 7, 10, 8, 11, 9, 9, 9, 13, 9, 11, 10, 12, 10, 10, + 14, 16, 13, 14, 14, 14, 12, 12, 8, 13, 8, 11, 10, 12, 10, 10, + 10, 13, 10, 12, 11, 13, 10, 11, 14, 16, 13, 14, 14, 15, 12, 12, + 11, 15, 10, 12, 13, 15, 11, 11, 12, 16, 11, 13, 13, 15, 12, 11, + 16, 16, 13, 14, 15, 16, 13, 12, 11, 15, 11, 13, 10, 13, 11, 11, + 13, 16, 12, 14, 12, 13, 12, 11, 16, 16, 14, 15, 15, 15, 13, 12, + 12, 16, 12, 13, 12, 14, 12, 12, 13, 16, 12, 14, 13, 14, 12, 12, + 16, 16, 14, 15, 15, 15, 13, 12, 14, 16, 13, 14, 15, 16, 12, 12, + 16, 16, 13, 14, 15, 16, 12, 12, 16, 16, 14, 15, 16, 16, 13, 12, + 6, 12, 7, 10, 9, 12, 9, 10, 9, 13, 9, 12, 11, 13, 11, 11, + 14, 16, 13, 14, 15, 15, 13, 12, 8, 13, 8, 11, 10, 13, 10, 10, + 10, 14, 10, 12, 12, 14, 11, 11, 15, 16, 13, 14, 16, 16, 13, 12, + 10, 15, 9, 12, 12, 15, 11, 11, 12, 16, 11, 13, 14, 16, 12, 12, + 16, 16, 14, 14, 16, 16, 13, 12, 8, 13, 9, 11, 10, 12, 10, 11, + 11, 14, 11, 12, 11, 13, 11, 11, 16, 16, 14, 15, 15, 16, 13, 12, + 10, 14, 10, 12, 11, 13, 11, 11, 11, 15, 11, 13, 12, 14, 11, 11, + 15, 16, 13, 14, 15, 16, 13, 12, 12, 16, 11, 13, 13, 16, 12, 12, + 13, 16, 11, 13, 14, 16, 12, 12, 16, 16, 13, 14, 16, 16, 13, 12, + 12, 16, 12, 14, 11, 13, 11, 11, 13, 16, 13, 14, 12, 14, 12, 12, + 16, 16, 15, 16, 16, 16, 14, 13, 13, 16, 12, 14, 12, 14, 12, 12, + 14, 16, 13, 14, 13, 14, 12, 12, 16, 16, 14, 16, 14, 16, 13, 12, + 15, 16, 13, 15, 15, 16, 13, 12, 15, 16, 13, 15, 14, 16, 13, 12, + 16, 16, 14, 15, 15, 16, 13, 11, 8, 13, 8, 11, 10, 13, 10, 11, + 11, 15, 10, 12, 12, 14, 11, 11, 15, 16, 13, 14, 15, 15, 13, 12, + 9, 14, 9, 12, 11, 14, 10, 11, 11, 16, 10, 12, 13, 14, 11, 11, + 16, 16, 13, 14, 15, 16, 13, 12, 11, 15, 9, 12, 12, 14, 10, 10, + 12, 16, 11, 12, 14, 15, 11, 11, 16, 16, 13, 14, 16, 16, 12, 11, + 9, 14, 10, 12, 11, 13, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11, + 16, 16, 14, 14, 15, 15, 13, 12, 10, 15, 10, 12, 12, 14, 11, 11, + 12, 16, 11, 13, 13, 14, 11, 11, 16, 16, 14, 14, 15, 16, 13, 12, + 12, 16, 10, 12, 13, 15, 11, 11, 13, 16, 11, 13, 14, 15, 11, 11, + 16, 16, 13, 13, 15, 16, 12, 11, 12, 16, 11, 13, 10, 13, 11, 11, + 14, 16, 13, 14, 12, 14, 11, 11, 16, 16, 15, 16, 14, 15, 13, 11, + 13, 16, 12, 14, 12, 14, 11, 11, 13, 16, 12, 14, 12, 14, 11, 11, + 16, 16, 14, 15, 14, 14, 12, 11, 14, 16, 12, 13, 13, 15, 11, 11, + 14, 16, 12, 13, 13, 14, 11, 11, 15, 16, 12, 13, 13, 13, 10, 9, + }, + }, + { + { + 0, 7, 4, 7, 5, 7, 6, 6, 6, 10, 7, 8, 8, 9, 8, 7, + 13, 14, 11, 12, 12, 12, 11, 9, 5, 9, 6, 8, 7, 9, 7, 7, + 8, 11, 8, 9, 9, 10, 9, 8, 13, 16, 12, 12, 12, 13, 11, 9, + 10, 13, 8, 10, 11, 12, 9, 9, 12, 14, 10, 11, 12, 13, 10, 9, + 15, 16, 12, 12, 14, 14, 11, 9, 6, 10, 7, 9, 7, 9, 8, 7, + 8, 11, 9, 10, 9, 10, 9, 8, 14, 16, 12, 12, 13, 12, 11, 9, + 8, 11, 8, 10, 9, 10, 9, 8, 10, 13, 10, 11, 10, 11, 9, 9, + 14, 16, 12, 12, 13, 13, 11, 9, 12, 15, 10, 11, 12, 13, 10, 9, + 13, 16, 11, 12, 13, 13, 10, 9, 16, 16, 12, 13, 14, 14, 11, 9, + 10, 14, 11, 12, 9, 11, 10, 9, 12, 15, 12, 13, 11, 12, 11, 9, + 16, 16, 13, 13, 13, 13, 11, 9, 12, 15, 12, 13, 11, 12, 11, 9, + 13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 13, 13, 13, 11, 9, + 14, 16, 13, 13, 13, 14, 11, 10, 16, 16, 13, 13, 13, 14, 11, 10, + 16, 16, 13, 13, 14, 14, 11, 9, 4, 9, 6, 8, 6, 9, 7, 7, + 8, 11, 8, 9, 9, 10, 9, 8, 13, 15, 12, 12, 13, 13, 11, 9, + 6, 10, 7, 9, 8, 10, 8, 8, 9, 12, 9, 10, 10, 11, 9, 8, + 14, 16, 12, 12, 13, 13, 11, 10, 10, 13, 8, 10, 11, 12, 9, 9, + 12, 15, 10, 11, 12, 13, 10, 9, 16, 16, 12, 12, 14, 14, 11, 9, + 7, 11, 8, 9, 7, 10, 8, 8, 9, 12, 10, 11, 9, 11, 9, 9, + 14, 16, 12, 13, 13, 13, 11, 10, 9, 12, 9, 10, 9, 11, 9, 9, + 10, 13, 10, 11, 10, 11, 10, 9, 14, 16, 12, 13, 13, 13, 11, 9, + 12, 15, 10, 11, 12, 13, 10, 9, 13, 16, 11, 12, 13, 13, 10, 9, + 16, 16, 12, 12, 14, 14, 11, 9, 10, 14, 11, 12, 9, 11, 10, 9, + 12, 16, 12, 13, 11, 12, 11, 9, 16, 16, 14, 14, 13, 13, 11, 9, + 12, 16, 12, 13, 11, 12, 10, 10, 13, 16, 12, 13, 11, 12, 11, 10, + 16, 16, 13, 13, 13, 13, 11, 9, 14, 16, 13, 13, 13, 14, 11, 9, + 15, 16, 13, 13, 13, 14, 11, 9, 16, 16, 13, 13, 13, 13, 10, 8, + 7, 11, 8, 10, 9, 11, 9, 9, 10, 13, 10, 11, 11, 12, 10, 10, + 15, 16, 13, 13, 14, 14, 12, 10, 9, 13, 9, 11, 10, 12, 10, 9, + 11, 14, 10, 12, 12, 13, 10, 10, 16, 16, 13, 13, 14, 14, 12, 10, + 11, 15, 9, 11, 12, 13, 10, 9, 13, 16, 11, 12, 13, 14, 11, 10, + 16, 16, 13, 13, 15, 15, 11, 10, 9, 13, 10, 11, 9, 11, 10, 9, + 11, 14, 11, 12, 11, 12, 11, 10, 16, 16, 14, 14, 14, 14, 12, 10, + 10, 14, 10, 12, 11, 12, 10, 10, 12, 15, 11, 12, 12, 13, 11, 10, + 16, 16, 13, 13, 14, 14, 12, 10, 13, 16, 11, 12, 13, 14, 11, 10, + 13, 16, 11, 12, 13, 14, 11, 10, 16, 16, 12, 13, 14, 14, 11, 9, + 11, 15, 12, 13, 10, 12, 10, 10, 13, 16, 13, 14, 11, 13, 11, 10, + 16, 16, 14, 14, 14, 14, 12, 10, 13, 16, 13, 13, 11, 13, 11, 10, + 14, 16, 13, 14, 12, 13, 11, 10, 16, 16, 14, 14, 13, 13, 12, 10, + 15, 16, 13, 14, 14, 14, 11, 10, 15, 16, 13, 13, 13, 14, 11, 10, + 16, 16, 12, 13, 13, 13, 10, 8, 9, 13, 10, 11, 10, 12, 10, 10, + 12, 15, 11, 12, 12, 13, 11, 10, 16, 16, 14, 13, 14, 14, 12, 10, + 10, 14, 10, 12, 11, 13, 10, 10, 13, 16, 11, 12, 12, 14, 11, 10, + 16, 16, 13, 13, 14, 14, 12, 10, 12, 16, 9, 11, 12, 14, 10, 9, + 13, 16, 10, 12, 13, 14, 10, 9, 16, 16, 12, 12, 14, 14, 11, 9, + 10, 14, 11, 12, 10, 12, 10, 10, 13, 16, 12, 13, 12, 13, 11, 10, + 16, 16, 14, 14, 14, 14, 12, 10, 11, 16, 11, 12, 11, 13, 11, 10, + 13, 16, 12, 13, 12, 14, 11, 10, 16, 16, 14, 14, 14, 14, 12, 10, + 13, 16, 11, 12, 13, 14, 10, 9, 14, 16, 11, 12, 13, 14, 10, 9, + 16, 16, 12, 12, 14, 14, 10, 8, 12, 16, 12, 13, 10, 12, 10, 9, + 14, 16, 13, 13, 11, 12, 11, 9, 16, 16, 14, 14, 13, 13, 11, 9, + 13, 16, 12, 13, 11, 12, 10, 9, 14, 16, 13, 13, 11, 13, 11, 9, + 16, 16, 14, 14, 13, 13, 11, 9, 14, 16, 12, 13, 12, 13, 10, 8, + 14, 16, 12, 12, 12, 13, 10, 8, 15, 16, 11, 11, 11, 12, 9, 6, + }, + { + 0, 7, 4, 7, 5, 8, 7, 8, 5, 10, 7, 10, 8, 10, 9, 10, + 13, 16, 12, 14, 14, 14, 13, 12, 4, 10, 6, 9, 8, 11, 9, 9, + 8, 12, 8, 11, 10, 12, 10, 10, 14, 16, 13, 14, 14, 15, 13, 12, + 9, 14, 9, 12, 12, 14, 11, 11, 12, 16, 11, 13, 13, 15, 12, 12, + 15, 16, 14, 15, 15, 16, 13, 13, 5, 10, 7, 10, 7, 10, 9, 9, + 8, 12, 9, 11, 9, 11, 10, 10, 14, 16, 13, 14, 14, 15, 13, 12, + 7, 12, 8, 11, 10, 12, 10, 10, 10, 13, 10, 12, 11, 13, 11, 11, + 15, 16, 13, 15, 14, 16, 13, 13, 11, 16, 11, 13, 13, 16, 12, 12, + 13, 16, 12, 14, 14, 16, 12, 12, 16, 16, 14, 16, 16, 16, 14, 13, + 11, 15, 12, 14, 11, 13, 11, 12, 13, 16, 12, 14, 12, 14, 12, 12, + 16, 16, 14, 16, 14, 16, 13, 13, 13, 16, 12, 14, 12, 14, 12, 12, + 14, 16, 13, 15, 13, 15, 13, 13, 16, 16, 15, 16, 16, 16, 14, 13, + 15, 16, 13, 16, 15, 16, 13, 13, 16, 16, 14, 16, 16, 16, 14, 13, + 16, 16, 16, 16, 16, 16, 14, 13, 2, 9, 5, 8, 6, 9, 8, 9, + 7, 11, 8, 10, 9, 11, 9, 10, 14, 16, 13, 14, 14, 15, 13, 12, + 5, 11, 6, 10, 9, 11, 9, 10, 8, 13, 9, 11, 11, 12, 10, 11, + 14, 16, 13, 14, 14, 16, 13, 13, 9, 15, 9, 12, 12, 14, 11, 11, + 12, 16, 11, 13, 13, 15, 12, 12, 16, 16, 14, 15, 16, 16, 14, 13, + 6, 11, 7, 10, 8, 11, 9, 10, 9, 13, 9, 12, 10, 12, 10, 11, + 14, 16, 13, 14, 14, 15, 13, 13, 8, 12, 8, 11, 10, 12, 10, 11, + 9, 13, 10, 12, 11, 13, 11, 11, 14, 16, 13, 14, 14, 16, 13, 13, + 12, 16, 11, 13, 13, 15, 12, 12, 13, 16, 11, 13, 14, 16, 12, 12, + 16, 16, 14, 15, 16, 16, 13, 13, 11, 15, 11, 14, 10, 13, 11, 12, + 13, 16, 13, 15, 12, 14, 12, 12, 16, 16, 15, 16, 15, 16, 14, 13, + 12, 16, 12, 14, 12, 14, 12, 12, 13, 16, 13, 15, 13, 14, 12, 13, + 16, 16, 15, 16, 15, 16, 13, 13, 15, 16, 13, 16, 15, 16, 13, 13, + 16, 16, 14, 16, 16, 16, 13, 13, 16, 16, 15, 16, 16, 16, 14, 13, + 5, 12, 7, 10, 9, 12, 10, 10, 9, 13, 9, 12, 11, 13, 11, 11, + 15, 16, 13, 14, 15, 15, 13, 13, 7, 13, 8, 11, 10, 13, 10, 11, + 10, 14, 10, 12, 12, 14, 11, 12, 16, 16, 14, 15, 16, 16, 14, 13, + 10, 16, 9, 12, 13, 15, 11, 12, 13, 16, 11, 13, 14, 16, 12, 12, + 16, 16, 14, 16, 16, 16, 14, 13, 8, 13, 9, 12, 9, 12, 10, 11, + 11, 15, 11, 13, 11, 13, 11, 12, 16, 16, 14, 16, 16, 16, 14, 13, + 9, 14, 10, 12, 11, 13, 11, 12, 11, 15, 11, 13, 12, 14, 12, 12, + 16, 16, 14, 16, 15, 16, 14, 13, 12, 16, 11, 14, 14, 16, 12, 12, + 13, 16, 12, 14, 14, 16, 13, 13, 16, 16, 13, 15, 16, 16, 14, 13, + 11, 16, 12, 14, 10, 13, 12, 12, 13, 16, 13, 15, 12, 14, 12, 13, + 16, 16, 16, 16, 16, 16, 14, 14, 13, 16, 13, 15, 12, 15, 12, 13, + 13, 16, 13, 15, 12, 15, 13, 13, 16, 16, 15, 16, 14, 16, 14, 13, + 16, 16, 14, 16, 16, 16, 14, 13, 15, 16, 14, 16, 15, 16, 14, 13, + 16, 16, 14, 16, 15, 16, 13, 12, 8, 14, 9, 12, 10, 14, 11, 12, + 11, 16, 10, 13, 12, 14, 12, 12, 16, 16, 14, 15, 15, 16, 14, 13, + 9, 15, 9, 12, 12, 14, 11, 12, 12, 16, 11, 13, 13, 15, 12, 12, + 16, 16, 14, 15, 16, 16, 14, 13, 11, 16, 9, 12, 13, 15, 11, 11, + 13, 16, 11, 13, 14, 16, 12, 12, 16, 16, 14, 14, 16, 16, 13, 12, + 9, 15, 10, 13, 11, 14, 11, 12, 12, 16, 11, 14, 12, 14, 12, 12, + 16, 16, 14, 16, 16, 16, 14, 13, 10, 16, 10, 13, 12, 15, 12, 12, + 12, 16, 12, 14, 13, 15, 12, 12, 16, 16, 14, 16, 16, 16, 14, 13, + 12, 16, 11, 13, 13, 16, 12, 12, 13, 16, 11, 13, 14, 16, 12, 12, + 16, 16, 13, 14, 16, 16, 13, 12, 11, 16, 12, 14, 10, 13, 11, 12, + 13, 16, 13, 15, 12, 14, 12, 12, 16, 16, 16, 16, 15, 16, 13, 12, + 12, 16, 12, 15, 12, 14, 12, 12, 13, 16, 13, 15, 12, 14, 12, 12, + 16, 16, 15, 16, 14, 15, 13, 12, 14, 16, 13, 14, 13, 16, 12, 12, + 13, 16, 12, 14, 13, 15, 12, 12, 14, 16, 12, 13, 13, 14, 11, 10, + }, + }, + { + { + 0, 7, 4, 7, 5, 7, 6, 6, 6, 10, 7, 8, 8, 9, 8, 8, + 13, 14, 11, 12, 12, 12, 11, 10, 5, 9, 6, 8, 7, 9, 7, 7, + 8, 11, 8, 9, 9, 10, 9, 8, 13, 16, 12, 12, 13, 13, 11, 10, + 10, 14, 8, 10, 11, 13, 9, 9, 12, 15, 10, 11, 12, 13, 10, 10, + 16, 16, 12, 13, 14, 14, 11, 10, 5, 10, 7, 9, 6, 9, 8, 8, + 8, 11, 9, 10, 9, 10, 9, 8, 14, 16, 12, 12, 13, 13, 11, 10, + 8, 12, 8, 10, 9, 10, 9, 9, 10, 13, 9, 11, 10, 11, 9, 9, + 14, 16, 12, 13, 13, 13, 11, 10, 12, 16, 10, 12, 12, 13, 10, 10, + 13, 16, 11, 12, 13, 14, 11, 10, 16, 16, 12, 13, 14, 14, 11, 10, + 10, 14, 11, 13, 9, 11, 10, 10, 12, 16, 12, 13, 11, 12, 11, 10, + 16, 16, 13, 14, 13, 13, 12, 10, 12, 16, 12, 13, 11, 13, 11, 10, + 13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 14, 13, 14, 12, 10, + 14, 16, 13, 14, 13, 14, 12, 11, 16, 16, 13, 14, 14, 15, 12, 11, + 16, 16, 13, 14, 14, 14, 11, 10, 3, 9, 5, 8, 6, 9, 7, 7, + 8, 11, 8, 10, 9, 10, 9, 8, 14, 15, 12, 12, 13, 13, 11, 10, + 6, 11, 6, 9, 8, 10, 8, 8, 9, 12, 9, 10, 10, 11, 9, 9, + 14, 16, 12, 13, 13, 13, 11, 10, 10, 14, 8, 11, 12, 13, 9, 9, + 12, 16, 10, 11, 12, 13, 10, 10, 16, 16, 12, 13, 14, 14, 11, 10, + 6, 11, 8, 10, 7, 10, 8, 8, 9, 12, 10, 11, 9, 11, 9, 9, + 14, 16, 12, 13, 13, 13, 12, 10, 9, 12, 9, 11, 9, 11, 9, 9, + 10, 13, 10, 11, 10, 12, 10, 9, 14, 16, 12, 13, 13, 13, 11, 10, + 12, 16, 10, 12, 12, 14, 10, 10, 13, 16, 10, 12, 13, 14, 11, 10, + 16, 16, 12, 13, 14, 14, 11, 10, 10, 15, 11, 13, 9, 11, 10, 10, + 12, 16, 12, 13, 11, 12, 11, 10, 16, 16, 14, 14, 13, 14, 12, 10, + 12, 16, 12, 13, 11, 13, 11, 10, 13, 16, 12, 13, 11, 13, 11, 10, + 16, 16, 13, 14, 13, 13, 12, 10, 14, 16, 13, 14, 14, 14, 11, 11, + 15, 16, 13, 14, 13, 14, 11, 10, 16, 16, 13, 13, 13, 14, 11, 9, + 7, 12, 8, 11, 9, 11, 9, 10, 10, 14, 10, 12, 11, 12, 11, 10, + 16, 16, 13, 13, 14, 14, 12, 11, 9, 13, 9, 11, 10, 12, 10, 10, + 11, 15, 10, 12, 12, 13, 11, 10, 16, 16, 13, 14, 14, 14, 12, 11, + 11, 16, 9, 11, 12, 14, 10, 10, 13, 16, 10, 12, 13, 14, 11, 10, + 16, 16, 13, 14, 16, 16, 12, 11, 9, 13, 10, 12, 9, 12, 10, 10, + 11, 15, 11, 13, 11, 13, 11, 11, 16, 16, 14, 14, 14, 14, 13, 11, + 10, 14, 10, 12, 11, 13, 11, 10, 12, 16, 11, 13, 12, 13, 11, 11, + 16, 16, 13, 14, 14, 14, 12, 11, 13, 16, 11, 13, 13, 14, 11, 11, + 13, 16, 11, 13, 13, 14, 11, 11, 16, 16, 12, 13, 14, 15, 12, 10, + 11, 16, 12, 14, 10, 12, 11, 10, 13, 16, 13, 14, 11, 13, 11, 11, + 16, 16, 15, 16, 14, 14, 13, 11, 13, 16, 13, 14, 12, 13, 11, 11, + 13, 16, 13, 14, 12, 13, 11, 11, 16, 16, 14, 14, 13, 14, 12, 11, + 15, 16, 13, 14, 14, 16, 12, 11, 14, 16, 13, 14, 13, 14, 12, 11, + 16, 16, 12, 13, 13, 14, 11, 9, 9, 14, 10, 12, 10, 13, 11, 11, + 12, 16, 12, 13, 12, 14, 12, 11, 16, 16, 14, 14, 14, 14, 13, 11, + 10, 16, 10, 13, 12, 14, 11, 11, 13, 16, 12, 13, 13, 14, 12, 11, + 16, 16, 14, 14, 15, 15, 13, 11, 12, 16, 9, 12, 13, 14, 10, 10, + 14, 16, 11, 12, 13, 15, 11, 10, 16, 16, 13, 13, 15, 16, 11, 10, + 10, 16, 11, 13, 11, 13, 11, 11, 13, 16, 12, 14, 12, 14, 12, 11, + 16, 16, 14, 14, 14, 14, 13, 11, 11, 16, 11, 13, 12, 14, 11, 11, + 13, 16, 12, 14, 13, 14, 12, 11, 16, 16, 14, 14, 14, 15, 13, 11, + 13, 16, 11, 13, 13, 14, 11, 10, 14, 16, 11, 13, 13, 14, 11, 10, + 16, 16, 12, 13, 14, 15, 11, 9, 12, 16, 12, 14, 10, 13, 11, 10, + 14, 16, 13, 14, 11, 13, 11, 10, 16, 16, 14, 15, 13, 14, 12, 10, + 13, 16, 13, 14, 11, 13, 11, 10, 14, 16, 13, 14, 12, 13, 11, 10, + 16, 16, 14, 14, 13, 13, 11, 10, 14, 16, 12, 13, 13, 14, 11, 9, + 14, 16, 12, 13, 12, 13, 10, 9, 14, 16, 11, 11, 12, 12, 9, 7, + }, + { + 0, 7, 3, 8, 5, 8, 7, 9, 5, 10, 7, 10, 8, 11, 10, 10, + 14, 16, 14, 15, 14, 16, 14, 14, 4, 10, 6, 10, 8, 11, 9, 10, + 8, 12, 9, 11, 10, 12, 11, 11, 15, 16, 14, 16, 15, 16, 14, 14, + 10, 16, 10, 13, 13, 16, 12, 13, 13, 16, 12, 14, 14, 16, 13, 13, + 16, 16, 16, 16, 16, 16, 14, 15, 4, 10, 7, 10, 7, 10, 9, 10, + 8, 12, 9, 12, 10, 12, 11, 12, 14, 16, 14, 16, 15, 16, 14, 14, + 8, 12, 9, 12, 10, 13, 11, 12, 10, 14, 11, 13, 11, 14, 12, 13, + 16, 16, 14, 16, 16, 16, 14, 15, 12, 16, 12, 14, 14, 16, 13, 14, + 14, 16, 13, 16, 16, 16, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 12, 16, 11, 14, 13, 13, 13, 16, 13, 16, 13, 15, 13, 14, + 16, 16, 16, 16, 16, 16, 15, 16, 13, 16, 13, 16, 13, 16, 13, 14, + 14, 16, 14, 16, 14, 16, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 2, 9, 5, 9, 6, 10, 8, 10, + 7, 11, 8, 11, 9, 12, 10, 11, 14, 16, 14, 16, 15, 16, 14, 14, + 5, 11, 6, 10, 9, 12, 10, 11, 9, 13, 9, 12, 11, 13, 11, 12, + 16, 16, 14, 16, 16, 16, 14, 14, 10, 16, 9, 13, 13, 16, 12, 13, + 13, 16, 12, 14, 14, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 14, + 5, 11, 8, 11, 7, 11, 10, 11, 9, 13, 10, 13, 10, 13, 11, 12, + 16, 16, 14, 16, 16, 16, 14, 14, 8, 13, 9, 12, 10, 13, 11, 12, + 10, 14, 10, 13, 11, 14, 12, 12, 16, 16, 14, 16, 15, 16, 14, 14, + 12, 16, 12, 14, 14, 16, 13, 14, 14, 16, 12, 16, 15, 16, 13, 14, + 16, 16, 15, 16, 16, 16, 15, 15, 11, 16, 12, 16, 10, 14, 12, 13, + 13, 16, 14, 16, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 15, 16, + 13, 16, 13, 16, 13, 16, 13, 14, 14, 16, 14, 16, 13, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, + 5, 13, 7, 12, 9, 13, 11, 12, 10, 14, 10, 13, 11, 13, 12, 13, + 16, 16, 16, 16, 16, 16, 16, 15, 7, 14, 8, 12, 11, 14, 11, 12, + 11, 16, 11, 13, 13, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 10, 14, 14, 16, 12, 13, 13, 16, 12, 15, 16, 16, 14, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 14, 10, 13, 9, 13, 11, 12, + 11, 16, 12, 14, 12, 14, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 11, 14, 12, 14, 12, 13, 11, 16, 12, 14, 12, 15, 13, 13, + 16, 16, 15, 16, 16, 16, 15, 16, 13, 16, 12, 16, 15, 16, 14, 14, + 13, 16, 12, 16, 16, 16, 14, 14, 16, 16, 14, 16, 16, 16, 14, 16, + 11, 16, 13, 16, 10, 14, 12, 13, 14, 16, 14, 16, 13, 16, 14, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 14, 16, 13, 16, 14, 15, + 13, 16, 14, 16, 13, 16, 14, 15, 16, 16, 16, 16, 15, 16, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 16, + 16, 16, 15, 16, 16, 16, 14, 14, 8, 16, 10, 14, 11, 16, 12, 13, + 12, 16, 12, 14, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 16, 14, + 10, 16, 10, 14, 12, 16, 12, 13, 13, 16, 12, 15, 14, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 16, 15, 11, 16, 10, 13, 13, 16, 12, 13, + 14, 16, 12, 14, 15, 16, 13, 13, 16, 16, 16, 16, 16, 16, 15, 14, + 10, 16, 11, 14, 11, 16, 12, 13, 13, 16, 13, 16, 13, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 16, 15, 11, 16, 12, 14, 13, 16, 13, 14, + 13, 16, 13, 16, 14, 16, 13, 14, 16, 16, 16, 16, 16, 16, 16, 15, + 13, 16, 12, 14, 14, 16, 13, 13, 13, 16, 12, 15, 14, 16, 13, 13, + 16, 16, 14, 16, 16, 16, 14, 13, 11, 16, 12, 16, 11, 15, 12, 13, + 14, 16, 14, 16, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 14, + 12, 16, 13, 16, 12, 16, 13, 14, 13, 16, 14, 16, 13, 16, 13, 14, + 16, 16, 16, 16, 14, 16, 14, 14, 14, 16, 13, 16, 14, 16, 13, 13, + 13, 16, 13, 16, 14, 16, 13, 13, 15, 16, 13, 14, 13, 15, 12, 12, + }, + }, + { + { + 0, 7, 4, 6, 4, 7, 6, 7, 6, 9, 7, 8, 7, 9, 8, 8, + 13, 14, 12, 12, 12, 13, 11, 11, 5, 9, 5, 8, 7, 9, 7, 8, + 8, 11, 8, 10, 9, 10, 9, 9, 13, 15, 12, 13, 12, 13, 11, 11, + 9, 14, 8, 11, 11, 13, 10, 10, 11, 15, 10, 12, 12, 13, 10, 11, + 14, 16, 12, 13, 14, 14, 12, 11, 5, 9, 7, 9, 6, 9, 8, 8, + 8, 11, 8, 10, 8, 10, 9, 9, 13, 16, 12, 13, 13, 13, 11, 11, + 7, 11, 8, 10, 9, 11, 9, 9, 9, 13, 9, 11, 10, 11, 10, 10, + 14, 16, 12, 13, 13, 13, 12, 11, 11, 16, 10, 12, 12, 14, 11, 11, + 13, 16, 11, 13, 13, 14, 11, 11, 16, 16, 13, 14, 14, 15, 12, 11, + 10, 15, 11, 13, 9, 12, 10, 10, 12, 16, 12, 13, 11, 12, 11, 11, + 15, 16, 13, 14, 13, 14, 12, 11, 12, 16, 12, 14, 11, 13, 11, 11, + 13, 16, 12, 14, 12, 13, 12, 11, 16, 16, 13, 14, 14, 14, 12, 11, + 14, 16, 13, 14, 14, 15, 12, 12, 16, 16, 13, 14, 14, 16, 12, 12, + 16, 16, 14, 14, 14, 15, 12, 11, 3, 9, 5, 8, 6, 9, 7, 8, + 7, 11, 8, 10, 9, 10, 9, 9, 13, 14, 12, 13, 13, 13, 12, 11, + 6, 11, 6, 9, 8, 10, 8, 9, 9, 12, 8, 10, 10, 11, 9, 10, + 14, 16, 12, 13, 13, 14, 12, 11, 9, 14, 8, 11, 11, 13, 10, 10, + 12, 16, 10, 12, 12, 14, 11, 11, 16, 16, 12, 13, 14, 15, 12, 11, + 6, 11, 8, 10, 7, 10, 8, 9, 9, 12, 9, 11, 9, 11, 10, 10, + 14, 16, 13, 13, 13, 14, 12, 11, 8, 12, 9, 11, 9, 11, 9, 10, + 10, 13, 9, 11, 10, 12, 10, 10, 14, 16, 12, 13, 13, 14, 12, 11, + 12, 16, 10, 12, 12, 14, 11, 11, 12, 16, 10, 12, 13, 14, 11, 11, + 15, 16, 12, 13, 14, 14, 11, 11, 10, 15, 11, 13, 9, 12, 10, 10, + 12, 16, 12, 14, 11, 13, 11, 11, 16, 16, 14, 14, 14, 14, 12, 11, + 12, 16, 12, 14, 11, 13, 11, 11, 13, 16, 12, 14, 11, 13, 11, 11, + 16, 16, 13, 14, 13, 14, 12, 11, 14, 16, 13, 14, 14, 15, 12, 11, + 14, 16, 13, 14, 13, 15, 12, 11, 16, 16, 13, 14, 13, 14, 11, 10, + 6, 13, 8, 11, 9, 12, 10, 10, 10, 14, 10, 12, 11, 13, 11, 11, + 16, 16, 13, 14, 14, 14, 13, 12, 8, 14, 8, 12, 10, 13, 10, 11, + 11, 15, 10, 12, 12, 13, 11, 11, 16, 16, 14, 14, 15, 16, 13, 12, + 11, 16, 9, 12, 12, 14, 11, 11, 13, 16, 11, 13, 13, 16, 11, 11, + 16, 16, 13, 14, 16, 16, 13, 12, 8, 14, 10, 12, 9, 12, 10, 11, + 11, 15, 11, 13, 11, 13, 11, 11, 16, 16, 14, 15, 14, 15, 13, 12, + 10, 15, 10, 13, 11, 13, 11, 11, 11, 15, 11, 13, 12, 13, 11, 11, + 16, 16, 13, 15, 14, 15, 13, 12, 12, 16, 11, 13, 13, 15, 11, 11, + 13, 16, 11, 13, 13, 15, 11, 11, 16, 16, 12, 14, 14, 16, 12, 11, + 11, 16, 12, 14, 10, 13, 11, 11, 13, 16, 13, 15, 12, 14, 12, 12, + 16, 16, 15, 16, 14, 15, 13, 12, 12, 16, 13, 14, 12, 14, 12, 12, + 13, 16, 13, 14, 12, 14, 12, 12, 16, 16, 14, 15, 13, 14, 12, 12, + 15, 16, 13, 15, 14, 16, 12, 12, 14, 16, 13, 14, 13, 15, 12, 12, + 15, 16, 12, 13, 13, 14, 11, 10, 9, 15, 10, 13, 11, 14, 11, 12, + 12, 16, 12, 14, 12, 14, 12, 12, 16, 16, 14, 14, 14, 15, 13, 12, + 10, 16, 10, 13, 12, 14, 12, 12, 13, 16, 12, 14, 13, 15, 12, 12, + 16, 16, 14, 14, 15, 16, 13, 12, 11, 16, 9, 12, 13, 15, 11, 11, + 14, 16, 11, 13, 14, 16, 11, 11, 16, 16, 13, 14, 16, 16, 12, 11, + 10, 16, 11, 14, 11, 14, 12, 12, 13, 16, 13, 14, 12, 14, 12, 12, + 16, 16, 14, 15, 15, 15, 13, 12, 11, 16, 12, 14, 12, 15, 12, 12, + 13, 16, 12, 14, 13, 15, 12, 12, 16, 16, 14, 15, 15, 16, 13, 12, + 12, 16, 11, 13, 13, 15, 11, 11, 13, 16, 11, 13, 13, 15, 11, 11, + 16, 16, 12, 13, 14, 16, 12, 10, 11, 16, 12, 14, 10, 13, 11, 11, + 14, 16, 13, 14, 12, 14, 11, 11, 16, 16, 15, 16, 14, 14, 12, 11, + 12, 16, 13, 14, 11, 14, 11, 11, 13, 16, 13, 14, 12, 14, 11, 11, + 16, 16, 14, 15, 13, 14, 12, 11, 14, 16, 12, 14, 13, 14, 11, 10, + 13, 16, 12, 13, 12, 14, 11, 10, 14, 16, 11, 12, 12, 12, 10, 8, + }, + { + 0, 8, 4, 9, 5, 9, 8, 10, 6, 11, 8, 11, 9, 12, 11, 12, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 11, 6, 11, 9, 12, 10, 12, + 9, 13, 10, 13, 11, 16, 12, 13, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 11, 16, 16, 16, 14, 16, 14, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 11, 8, 12, 7, 12, 10, 12, + 8, 13, 10, 13, 10, 13, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 13, 10, 14, 11, 16, 12, 14, 11, 16, 12, 16, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 14, 16, 12, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 10, 5, 10, 7, 11, 9, 11, + 8, 12, 9, 12, 10, 13, 12, 13, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 12, 7, 12, 10, 13, 11, 12, 9, 16, 10, 13, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 10, 16, 16, 16, 14, 16, + 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 6, 12, 9, 13, 8, 12, 11, 13, 10, 16, 11, 16, 11, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 10, 14, 11, 16, 12, 16, + 10, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 14, 16, 11, 16, 14, 16, + 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 6, 16, 9, 13, 10, 16, 12, 14, 11, 16, 12, 16, 12, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 9, 14, 12, 16, 13, 16, + 12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 10, 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 11, 16, 10, 16, 12, 16, + 12, 16, 13, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 13, 16, 14, 16, 11, 16, 13, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16, + 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 11, 16, 14, 16, 16, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 11, 16, 12, 16, 13, 16, + 13, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 11, 16, 13, 16, 14, 16, 14, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 10, 16, 16, 16, 13, 16, + 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 12, 16, 13, 16, 13, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 14, 16, 16, 16, + 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 12, 16, 16, 16, 14, 16, 14, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 11, 16, 13, 16, + 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 15, + }, + }, + { + { + 0, 7, 3, 7, 4, 7, 6, 7, 6, 9, 7, 9, 7, 9, 8, 9, + 13, 14, 12, 13, 13, 13, 12, 12, 4, 9, 5, 9, 7, 9, 8, 9, + 7, 11, 8, 10, 9, 11, 9, 10, 13, 16, 12, 14, 13, 14, 12, 12, + 9, 14, 8, 12, 12, 14, 10, 11, 11, 16, 10, 13, 13, 14, 11, 12, + 15, 16, 13, 14, 14, 16, 12, 12, 5, 10, 7, 9, 6, 9, 8, 9, + 8, 11, 8, 11, 8, 10, 9, 10, 14, 16, 12, 14, 13, 14, 12, 12, + 7, 12, 8, 11, 9, 11, 9, 10, 9, 13, 9, 12, 10, 12, 10, 11, + 14, 16, 12, 14, 13, 14, 12, 12, 12, 16, 11, 13, 13, 15, 11, 12, + 13, 16, 11, 14, 13, 15, 12, 12, 15, 16, 13, 15, 14, 16, 13, 13, + 10, 15, 12, 14, 9, 13, 11, 12, 12, 16, 12, 14, 11, 13, 12, 12, + 15, 16, 13, 15, 14, 15, 13, 13, 12, 16, 12, 14, 12, 14, 12, 12, + 13, 16, 13, 14, 12, 14, 12, 12, 16, 16, 14, 15, 14, 16, 13, 13, + 15, 16, 13, 15, 14, 16, 12, 13, 16, 16, 14, 16, 14, 16, 13, 13, + 16, 16, 14, 16, 15, 16, 13, 13, 3, 9, 5, 9, 6, 9, 8, 9, + 7, 11, 8, 10, 9, 11, 9, 10, 14, 15, 13, 14, 13, 14, 12, 12, + 5, 11, 6, 10, 8, 11, 9, 10, 9, 12, 9, 11, 10, 12, 10, 11, + 14, 16, 13, 14, 14, 15, 13, 13, 9, 15, 8, 12, 12, 14, 10, 11, + 12, 16, 10, 13, 13, 15, 11, 12, 15, 16, 13, 14, 14, 16, 13, 13, + 6, 11, 8, 11, 7, 10, 9, 10, 9, 13, 10, 12, 9, 12, 10, 11, + 14, 16, 13, 14, 14, 14, 13, 13, 8, 13, 9, 12, 9, 12, 10, 11, + 9, 13, 9, 12, 10, 12, 10, 11, 14, 16, 12, 14, 13, 14, 12, 12, + 12, 16, 11, 13, 13, 15, 11, 12, 12, 16, 11, 13, 13, 15, 11, 12, + 14, 16, 12, 14, 14, 15, 12, 12, 10, 15, 11, 14, 9, 13, 11, 12, + 12, 16, 12, 14, 11, 14, 12, 12, 16, 16, 14, 16, 14, 15, 13, 13, + 12, 16, 12, 14, 11, 14, 12, 12, 12, 16, 13, 14, 11, 14, 12, 12, + 15, 16, 14, 15, 13, 15, 12, 13, 14, 16, 13, 15, 14, 16, 13, 13, + 14, 16, 13, 15, 14, 16, 12, 13, 15, 16, 13, 15, 13, 15, 12, 12, + 6, 13, 8, 12, 9, 12, 10, 11, 10, 14, 11, 13, 11, 13, 12, 12, + 15, 16, 14, 15, 15, 15, 14, 13, 8, 14, 9, 12, 11, 13, 11, 12, + 11, 15, 11, 13, 12, 14, 12, 12, 16, 16, 14, 15, 15, 16, 14, 14, + 10, 16, 9, 13, 12, 15, 11, 12, 13, 16, 11, 14, 13, 16, 12, 12, + 16, 16, 14, 15, 16, 16, 13, 13, 8, 14, 10, 13, 9, 13, 11, 12, + 11, 15, 12, 14, 11, 14, 12, 12, 16, 16, 15, 16, 15, 16, 14, 14, + 10, 15, 10, 13, 11, 14, 11, 12, 11, 15, 11, 14, 12, 14, 12, 12, + 15, 16, 14, 15, 14, 16, 13, 13, 12, 16, 11, 14, 13, 16, 12, 12, + 12, 16, 11, 14, 13, 15, 12, 12, 15, 16, 12, 14, 15, 16, 13, 13, + 11, 16, 12, 14, 10, 14, 11, 12, 13, 16, 13, 16, 12, 14, 12, 13, + 16, 16, 16, 16, 15, 16, 14, 13, 12, 16, 13, 15, 12, 14, 12, 13, + 13, 16, 13, 15, 12, 14, 12, 13, 16, 16, 14, 16, 13, 15, 13, 13, + 15, 16, 14, 16, 14, 16, 13, 13, 14, 16, 13, 15, 13, 16, 13, 13, + 14, 16, 12, 14, 13, 14, 12, 12, 9, 16, 11, 14, 11, 15, 12, 13, + 13, 16, 12, 14, 12, 15, 13, 13, 16, 16, 14, 15, 15, 15, 14, 13, + 11, 16, 11, 14, 12, 16, 12, 13, 13, 16, 12, 14, 13, 16, 13, 13, + 16, 16, 14, 15, 16, 16, 14, 13, 11, 16, 10, 13, 13, 16, 11, 12, + 14, 16, 11, 14, 14, 16, 12, 12, 16, 16, 14, 14, 16, 16, 13, 12, + 11, 16, 12, 14, 11, 15, 12, 13, 13, 16, 13, 15, 13, 16, 13, 13, + 16, 16, 15, 16, 15, 16, 14, 13, 11, 16, 12, 15, 12, 16, 12, 13, + 13, 16, 13, 15, 13, 16, 13, 13, 16, 16, 15, 16, 15, 16, 14, 13, + 12, 16, 11, 14, 13, 16, 12, 12, 13, 16, 11, 14, 13, 16, 12, 12, + 16, 16, 13, 14, 15, 16, 12, 12, 11, 16, 12, 14, 10, 14, 11, 12, + 14, 16, 13, 15, 12, 15, 12, 12, 16, 16, 16, 16, 14, 15, 13, 12, + 12, 16, 13, 15, 12, 14, 12, 12, 13, 16, 13, 15, 12, 14, 12, 12, + 16, 16, 14, 16, 14, 15, 12, 12, 14, 16, 13, 15, 13, 16, 11, 12, + 13, 16, 12, 14, 13, 15, 11, 11, 14, 16, 12, 13, 12, 13, 11, 10, + }, + { + 0, 8, 4, 9, 5, 10, 9, 11, 5, 11, 9, 12, 9, 13, 12, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 11, 6, 12, 9, 13, 11, 13, + 9, 16, 10, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 12, 8, 13, 7, 12, 11, 16, + 8, 16, 11, 16, 11, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 10, 16, 11, 16, 13, 16, 11, 16, 12, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 10, 6, 11, 7, 12, 10, 13, + 7, 12, 10, 13, 10, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 13, 7, 12, 10, 16, 12, 16, 10, 16, 11, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 16, 16, 16, 16, + 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 13, 9, 16, 8, 16, 12, 16, 9, 16, 12, 16, 11, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 11, 16, 12, 16, 13, 16, + 10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 6, 16, 9, 16, 10, 16, 13, 16, 11, 16, 12, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 9, 16, 12, 16, 13, 16, + 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 10, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 11, 16, 11, 16, 13, 16, + 12, 16, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 13, 16, 16, 16, 11, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 16, 11, 16, 12, 16, 16, 16, + 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 11, 16, 13, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 10, 16, 16, 16, 16, 16, + 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 11, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 7, 4, 8, 4, 8, 7, 8, 6, 10, 7, 10, 8, 10, 9, 10, + 13, 16, 13, 15, 13, 15, 13, 14, 4, 10, 5, 10, 7, 10, 9, 10, + 7, 12, 8, 11, 9, 12, 10, 11, 13, 16, 13, 15, 13, 16, 13, 14, + 9, 16, 9, 13, 12, 16, 11, 13, 11, 16, 11, 14, 13, 16, 12, 14, + 15, 16, 14, 16, 15, 16, 14, 14, 4, 10, 7, 10, 6, 10, 9, 10, + 8, 12, 9, 12, 9, 11, 10, 12, 13, 16, 13, 16, 14, 16, 13, 14, + 7, 12, 8, 12, 9, 12, 10, 12, 9, 13, 10, 13, 10, 13, 11, 12, + 14, 16, 13, 16, 14, 16, 13, 14, 12, 16, 11, 14, 13, 16, 12, 14, + 13, 16, 12, 16, 14, 16, 13, 14, 16, 16, 14, 16, 15, 16, 14, 14, + 10, 16, 12, 15, 10, 14, 12, 13, 12, 16, 13, 16, 12, 14, 13, 14, + 15, 16, 14, 16, 14, 16, 14, 14, 12, 16, 13, 16, 12, 16, 13, 14, + 13, 16, 13, 16, 13, 16, 13, 14, 16, 16, 14, 16, 15, 16, 14, 15, + 15, 16, 14, 16, 15, 16, 13, 15, 16, 16, 14, 16, 15, 16, 14, 15, + 16, 16, 16, 16, 16, 16, 15, 15, 2, 9, 5, 10, 6, 10, 8, 10, + 7, 11, 8, 11, 9, 11, 10, 11, 14, 16, 13, 15, 14, 15, 14, 14, + 5, 11, 6, 11, 8, 12, 9, 11, 8, 13, 9, 12, 10, 13, 11, 12, + 14, 16, 13, 15, 14, 16, 14, 14, 9, 16, 8, 13, 12, 16, 11, 13, + 12, 16, 11, 14, 13, 16, 12, 13, 16, 16, 14, 16, 15, 16, 14, 15, + 5, 12, 8, 11, 7, 11, 9, 11, 9, 13, 10, 13, 10, 13, 11, 12, + 14, 16, 14, 16, 14, 16, 14, 15, 8, 13, 9, 13, 10, 13, 11, 12, + 9, 13, 10, 13, 10, 13, 11, 13, 13, 16, 13, 15, 13, 16, 13, 14, + 12, 16, 11, 14, 13, 16, 12, 14, 12, 16, 11, 14, 13, 16, 12, 14, + 14, 16, 13, 16, 14, 16, 13, 14, 10, 16, 12, 15, 9, 14, 11, 13, + 12, 16, 13, 16, 12, 15, 12, 14, 16, 16, 15, 16, 15, 16, 14, 14, + 12, 16, 13, 16, 12, 16, 12, 14, 12, 16, 13, 16, 12, 15, 13, 14, + 15, 16, 14, 16, 14, 16, 14, 14, 15, 16, 14, 16, 14, 16, 14, 15, + 14, 16, 13, 16, 14, 16, 13, 14, 16, 16, 14, 16, 14, 16, 13, 14, + 6, 14, 9, 13, 9, 14, 11, 12, 10, 14, 11, 13, 11, 14, 12, 13, + 16, 16, 15, 16, 15, 16, 14, 15, 8, 15, 9, 13, 11, 14, 11, 13, + 11, 16, 11, 14, 12, 15, 12, 14, 16, 16, 15, 16, 16, 16, 15, 16, + 10, 16, 9, 14, 12, 16, 12, 13, 13, 16, 11, 15, 14, 16, 13, 14, + 16, 16, 15, 16, 16, 16, 15, 16, 8, 15, 10, 13, 10, 14, 11, 13, + 11, 16, 12, 14, 12, 14, 12, 14, 16, 16, 16, 16, 16, 16, 15, 16, + 10, 16, 11, 14, 11, 15, 12, 13, 11, 16, 11, 14, 12, 15, 12, 14, + 16, 16, 14, 16, 15, 16, 14, 15, 12, 16, 11, 15, 13, 16, 13, 14, + 12, 16, 11, 14, 13, 16, 13, 14, 15, 16, 13, 16, 16, 16, 14, 15, + 10, 16, 12, 15, 10, 15, 12, 13, 13, 16, 13, 16, 12, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 15, 15, 12, 16, 13, 16, 12, 16, 13, 14, + 12, 16, 13, 16, 12, 16, 13, 14, 16, 16, 15, 16, 14, 16, 14, 15, + 15, 16, 14, 16, 15, 16, 14, 15, 14, 16, 13, 16, 14, 16, 13, 14, + 14, 16, 13, 15, 14, 16, 13, 14, 9, 16, 11, 16, 11, 16, 12, 14, + 13, 16, 12, 16, 13, 16, 13, 14, 16, 16, 15, 16, 16, 16, 15, 15, + 11, 16, 11, 16, 12, 16, 13, 14, 13, 16, 12, 16, 13, 16, 13, 14, + 16, 16, 15, 16, 16, 16, 15, 15, 11, 16, 10, 15, 13, 16, 12, 13, + 14, 16, 12, 16, 14, 16, 13, 14, 16, 16, 15, 16, 16, 16, 14, 14, + 11, 16, 12, 16, 11, 16, 13, 14, 13, 16, 13, 16, 13, 16, 13, 14, + 16, 16, 16, 16, 16, 16, 15, 15, 11, 16, 12, 16, 12, 16, 13, 14, + 13, 16, 13, 16, 13, 16, 13, 14, 16, 16, 15, 16, 16, 16, 15, 14, + 12, 16, 12, 15, 13, 16, 12, 14, 13, 16, 12, 16, 14, 16, 13, 14, + 16, 16, 14, 16, 16, 16, 14, 14, 11, 16, 12, 16, 11, 16, 12, 14, + 14, 16, 14, 16, 12, 16, 13, 14, 16, 16, 16, 16, 16, 16, 15, 14, + 12, 16, 13, 16, 12, 16, 12, 14, 13, 16, 13, 16, 12, 16, 13, 14, + 16, 16, 16, 16, 15, 16, 14, 14, 14, 16, 13, 16, 14, 16, 12, 14, + 13, 16, 13, 16, 13, 16, 12, 13, 15, 16, 13, 14, 14, 15, 13, 13, + }, + { + 0, 8, 4, 10, 5, 11, 10, 16, 5, 12, 9, 16, 10, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 12, 7, 12, 9, 16, 12, 16, + 9, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 12, 9, 16, 8, 16, 12, 16, + 8, 16, 11, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 8, 16, 11, 16, 12, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 11, 6, 12, 7, 16, 11, 16, + 7, 16, 10, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 7, 16, 10, 16, 12, 16, 9, 16, 11, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 10, 16, 8, 16, 12, 16, 9, 16, 12, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 11, 16, 12, 16, 16, 16, + 10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 9, 16, 10, 16, 16, 16, 11, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 9, 16, 12, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 11, 16, 11, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 11, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 10, 16, 12, 16, 16, 16, + 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 9, 16, 16, 16, 16, 16, + 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 11, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 8, 4, 10, 5, 9, 8, 10, 6, 11, 8, 12, 8, 11, 10, 13, + 14, 16, 14, 16, 14, 16, 16, 16, 3, 11, 5, 11, 8, 12, 10, 12, + 7, 12, 9, 13, 10, 13, 11, 13, 14, 16, 14, 16, 16, 16, 16, 16, + 9, 16, 9, 16, 12, 16, 12, 16, 11, 16, 11, 16, 14, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 11, 7, 12, 6, 11, 10, 12, + 8, 13, 9, 13, 9, 13, 11, 14, 13, 16, 14, 16, 14, 16, 16, 16, + 7, 13, 9, 13, 9, 13, 11, 13, 9, 14, 10, 16, 11, 16, 12, 16, + 15, 16, 14, 16, 16, 16, 16, 16, 12, 16, 12, 16, 14, 16, 13, 16, + 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 10, 16, 13, 16, 12, 16, 13, 16, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 13, 16, 14, 16, + 13, 16, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 2, 10, 5, 11, 6, 11, 9, 11, + 7, 12, 9, 13, 9, 13, 11, 13, 14, 16, 16, 16, 16, 16, 16, 16, + 4, 12, 6, 12, 8, 13, 10, 13, 8, 13, 9, 13, 11, 16, 12, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 8, 16, 12, 16, 12, 16, + 12, 16, 11, 16, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 12, 8, 13, 7, 13, 10, 13, 8, 14, 10, 14, 10, 14, 12, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 14, 9, 16, 10, 16, 11, 14, + 8, 14, 10, 16, 11, 16, 12, 16, 13, 16, 14, 16, 16, 16, 16, 16, + 11, 16, 11, 16, 13, 16, 13, 16, 12, 16, 12, 16, 14, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 12, 16, 10, 16, 12, 16, + 12, 16, 13, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 13, 16, 12, 16, 14, 16, 12, 16, 13, 16, 12, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 6, 16, 8, 16, 9, 16, 11, 13, 10, 16, 11, 16, 11, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 16, 9, 16, 10, 16, 12, 16, + 11, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 9, 16, 12, 16, 13, 16, 13, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 7, 16, 10, 16, 9, 16, 12, 16, + 11, 16, 12, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 11, 16, 11, 16, 12, 16, 11, 16, 12, 16, 13, 16, 13, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 14, 16, 14, 16, + 12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 10, 16, 13, 16, 13, 16, 14, 16, 13, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 12, 16, 14, 16, + 12, 16, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 11, 16, 11, 16, 13, 16, + 12, 16, 13, 16, 13, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 11, 16, 13, 16, 13, 16, 13, 16, 13, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 14, 16, 13, 16, + 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 12, 16, 12, 16, 13, 16, 13, 16, 13, 16, 13, 16, 14, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 12, 16, 13, 16, 14, 16, + 13, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 12, 16, 14, 16, 14, 16, 14, 16, 14, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 11, 16, 14, 16, + 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 14, 16, 13, 16, 14, 16, 16, 16, 16, 16, 14, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 0, 10, 4, 12, 5, 16, 11, 16, 6, 16, 10, 16, 11, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 3, 16, 7, 16, 10, 16, 16, 16, + 9, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 4, 16, 10, 16, 9, 16, 16, 16, + 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 12, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 6, 16, 8, 16, 16, 16, + 8, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 8, 16, 11, 16, 16, 16, 10, 16, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 11, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 11, 16, 9, 16, 16, 16, 10, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 9, 16, 12, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 5, 16, 9, 16, 11, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 10, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 11, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 12, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 6, 16, 11, 16, 15, 16, 16, 16, + 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 9, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 9, 16, 16, 16, 16, 16, + 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, +}; + +static const uint8_t rv34_table_inter_secondpat[NUM_INTER_TABLES][2][OTHERBLK_VLC_SIZE] = { + { + { + 0, 4, 8, 3, 6, 8, 6, 7, 8, 4, 6, 8, 6, 7, 8, 7, + 8, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 3, 6, 8, 4, 6, + 9, 7, 7, 8, 5, 7, 9, 6, 7, 9, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 7, 6, 8, 9, 7, 8, 9, 7, 8, 9, 7, + 8, 9, 7, 8, 9, 8, 8, 9, 8, 8, 9, 8, 9, 9, 8, 8, + 8, 8, 9, 9, 8, 9, 9, 7, 8, 8, 8, 9, 9, 8, 9, 9, + 8, 8, 8, 7, 8, 8, 8, 8, 8, 7, 7, 6, + }, + { + 0, 4, 9, 3, 6, 9, 7, 8, 10, 3, 6, 9, 5, 7, 10, 9, + 9, 10, 7, 8, 10, 8, 9, 10, 10, 10, 10, 2, 6, 9, 4, 7, + 10, 8, 9, 10, 4, 7, 10, 6, 7, 10, 9, 9, 10, 7, 8, 10, + 8, 9, 10, 10, 10, 10, 6, 8, 10, 7, 9, 11, 9, 10, 11, 7, + 9, 11, 8, 9, 11, 10, 10, 11, 8, 9, 11, 9, 10, 11, 11, 11, + 10, 8, 10, 11, 9, 10, 11, 9, 10, 11, 8, 10, 11, 9, 10, 11, + 10, 10, 11, 8, 10, 11, 9, 10, 10, 10, 10, 9, + }, + }, + { + { + 0, 4, 8, 3, 6, 8, 6, 7, 9, 4, 6, 8, 5, 7, 8, 8, + 8, 9, 7, 7, 8, 8, 8, 8, 8, 9, 8, 3, 6, 8, 4, 6, + 9, 7, 7, 9, 5, 6, 9, 6, 7, 9, 8, 8, 9, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 6, 8, 9, 7, 8, 10, 7, 8, 9, 7, + 8, 10, 7, 8, 10, 8, 8, 9, 7, 8, 9, 8, 9, 9, 9, 9, + 8, 7, 9, 10, 8, 9, 10, 8, 8, 8, 8, 9, 10, 8, 9, 9, + 8, 8, 8, 7, 8, 8, 8, 8, 8, 8, 7, 6, + }, + { + 0, 4, 9, 3, 6, 10, 8, 9, 11, 3, 5, 9, 5, 7, 10, 9, + 10, 11, 7, 8, 10, 9, 9, 11, 11, 11, 12, 2, 5, 10, 4, 7, + 10, 8, 9, 11, 4, 6, 10, 6, 7, 10, 9, 10, 11, 7, 9, 10, + 9, 9, 11, 11, 11, 11, 6, 8, 11, 7, 9, 11, 9, 10, 12, 7, + 9, 11, 8, 9, 12, 10, 10, 12, 8, 10, 11, 10, 10, 11, 12, 11, + 11, 8, 10, 12, 9, 11, 12, 10, 11, 12, 9, 10, 12, 10, 11, 12, + 11, 11, 12, 9, 10, 12, 10, 10, 11, 11, 11, 10, + }, + }, + { + { + 0, 4, 8, 3, 6, 9, 7, 8, 9, 4, 6, 8, 5, 7, 9, 8, + 9, 9, 7, 8, 9, 8, 8, 9, 9, 9, 9, 2, 6, 9, 4, 6, + 9, 7, 8, 10, 5, 7, 9, 6, 7, 9, 8, 8, 9, 7, 8, 9, + 8, 8, 9, 9, 9, 9, 6, 8, 10, 7, 8, 10, 8, 9, 10, 6, + 8, 10, 8, 8, 10, 9, 9, 10, 8, 9, 10, 9, 9, 10, 10, 10, + 9, 8, 9, 10, 8, 9, 10, 8, 9, 10, 8, 9, 10, 9, 9, 10, + 9, 9, 9, 8, 9, 9, 8, 9, 9, 9, 9, 8, + }, + { + 0, 4, 10, 3, 6, 10, 8, 10, 12, 2, 6, 10, 6, 8, 11, 10, + 11, 12, 7, 9, 11, 9, 10, 12, 12, 13, 13, 2, 6, 10, 4, 7, + 11, 9, 10, 13, 4, 7, 11, 7, 8, 11, 10, 11, 12, 8, 9, 12, + 10, 10, 12, 12, 12, 13, 6, 9, 12, 8, 10, 13, 10, 12, 14, 7, + 10, 13, 9, 10, 13, 11, 11, 13, 9, 11, 13, 11, 11, 13, 13, 13, + 13, 9, 11, 13, 10, 12, 14, 11, 12, 14, 9, 11, 14, 11, 12, 14, + 12, 12, 14, 9, 12, 13, 11, 12, 13, 13, 12, 12, + }, + }, + { + { + 0, 4, 9, 3, 6, 9, 7, 8, 10, 3, 6, 9, 6, 7, 9, 9, + 9, 10, 7, 8, 9, 8, 9, 10, 10, 10, 11, 2, 6, 9, 4, 7, + 10, 7, 9, 10, 4, 7, 10, 6, 7, 10, 9, 9, 10, 7, 8, 10, + 8, 9, 10, 10, 10, 10, 6, 8, 11, 7, 9, 11, 8, 10, 11, 6, + 9, 11, 8, 9, 11, 9, 9, 11, 8, 9, 11, 9, 10, 11, 11, 10, + 10, 8, 10, 11, 9, 10, 11, 9, 10, 11, 8, 10, 11, 9, 10, 11, + 10, 10, 11, 8, 10, 11, 9, 10, 11, 10, 10, 10, + }, + { + 0, 4, 12, 3, 7, 12, 10, 11, 14, 3, 6, 12, 7, 9, 13, 12, + 13, 14, 8, 11, 13, 11, 12, 14, 14, 14, 14, 1, 7, 12, 5, 8, + 13, 10, 12, 14, 4, 8, 13, 8, 9, 13, 12, 13, 14, 9, 11, 14, + 11, 12, 14, 14, 14, 14, 7, 10, 14, 9, 11, 14, 11, 13, 16, 8, + 11, 14, 10, 12, 14, 13, 13, 16, 10, 12, 15, 12, 13, 15, 15, 15, + 15, 10, 13, 15, 12, 13, 14, 13, 15, 15, 10, 13, 15, 12, 13, 15, + 13, 14, 15, 10, 13, 14, 12, 13, 14, 14, 14, 14, + }, + }, + { + { + 0, 4, 9, 3, 6, 10, 7, 9, 11, 3, 5, 9, 5, 7, 10, 9, + 10, 12, 7, 8, 10, 9, 10, 11, 11, 12, 12, 2, 6, 10, 4, 7, + 10, 7, 9, 12, 4, 7, 10, 6, 7, 11, 9, 10, 12, 7, 9, 11, + 9, 9, 11, 11, 11, 12, 5, 8, 11, 7, 9, 12, 9, 10, 13, 6, + 9, 12, 8, 9, 12, 10, 10, 12, 8, 10, 12, 10, 10, 12, 12, 12, + 12, 8, 10, 12, 9, 11, 13, 10, 11, 13, 9, 11, 13, 10, 11, 13, + 11, 11, 13, 9, 11, 12, 10, 11, 12, 11, 11, 12, + }, + { + 0, 4, 12, 3, 7, 13, 10, 12, 15, 3, 7, 13, 7, 9, 14, 12, + 12, 13, 8, 11, 14, 11, 13, 15, 15, 14, 14, 1, 6, 13, 5, 8, + 13, 10, 13, 15, 4, 8, 13, 8, 9, 14, 13, 13, 15, 8, 11, 14, + 12, 12, 15, 15, 14, 14, 7, 10, 13, 9, 11, 13, 12, 14, 16, 8, + 11, 14, 10, 12, 15, 13, 13, 16, 10, 12, 15, 12, 13, 15, 15, 14, + 15, 11, 12, 14, 12, 14, 14, 13, 15, 15, 10, 12, 14, 12, 13, 15, + 14, 15, 15, 10, 13, 13, 12, 13, 15, 14, 14, 15, + }, + }, + { + { + 0, 5, 10, 3, 7, 11, 9, 11, 14, 3, 7, 11, 7, 8, 12, 11, + 12, 14, 7, 9, 12, 10, 11, 14, 13, 14, 16, 1, 7, 11, 5, 8, + 12, 9, 11, 15, 4, 8, 12, 7, 9, 13, 11, 12, 15, 8, 10, 13, + 10, 11, 14, 14, 14, 16, 6, 9, 13, 8, 11, 14, 10, 13, 16, 7, + 10, 14, 9, 11, 15, 12, 13, 16, 9, 11, 15, 12, 12, 15, 14, 14, + 16, 10, 12, 14, 11, 13, 15, 12, 14, 16, 10, 12, 15, 11, 13, 16, + 13, 14, 16, 10, 13, 16, 12, 13, 15, 14, 15, 16, + }, + { + 0, 5, 16, 3, 8, 14, 11, 13, 14, 2, 8, 14, 8, 10, 16, 13, + 13, 14, 9, 13, 16, 12, 13, 16, 16, 14, 16, 1, 7, 14, 6, 10, + 14, 12, 16, 16, 5, 9, 14, 9, 11, 16, 15, 16, 16, 10, 12, 16, + 13, 13, 16, 16, 14, 16, 8, 11, 14, 11, 13, 14, 14, 14, 16, 8, + 12, 14, 11, 13, 16, 16, 16, 16, 10, 12, 15, 13, 14, 16, 16, 16, + 16, 11, 14, 14, 14, 15, 16, 16, 15, 16, 10, 13, 16, 13, 14, 14, + 16, 16, 16, 10, 13, 16, 13, 14, 16, 16, 16, 16, + }, + }, + { + { + 0, 5, 11, 3, 7, 13, 9, 12, 16, 3, 7, 12, 6, 9, 14, 11, + 13, 16, 7, 10, 16, 11, 12, 16, 16, 16, 16, 1, 6, 12, 5, 9, + 16, 9, 13, 16, 4, 8, 16, 7, 10, 16, 12, 15, 16, 7, 11, 16, + 11, 12, 16, 16, 16, 16, 6, 10, 15, 8, 11, 16, 11, 14, 16, 7, + 11, 16, 10, 12, 16, 13, 16, 16, 9, 13, 16, 13, 14, 16, 16, 16, + 16, 10, 12, 16, 12, 16, 16, 16, 16, 16, 11, 13, 16, 13, 16, 16, + 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 0, 5, 16, 3, 8, 16, 12, 12, 16, 2, 8, 16, 8, 10, 16, 13, + 13, 16, 9, 13, 16, 12, 13, 16, 16, 16, 16, 1, 8, 16, 6, 10, + 16, 12, 16, 16, 5, 9, 16, 9, 11, 16, 13, 16, 16, 9, 12, 14, + 12, 12, 16, 16, 16, 16, 8, 11, 13, 11, 12, 16, 14, 16, 16, 8, + 12, 16, 11, 13, 16, 16, 15, 16, 9, 13, 14, 12, 13, 16, 16, 16, + 16, 10, 12, 13, 14, 13, 16, 16, 16, 16, 9, 13, 16, 13, 12, 16, + 16, 16, 16, 10, 12, 16, 14, 15, 16, 16, 16, 16, + }, + }, +}; + +static const uint8_t rv34_table_inter_thirdpat[NUM_INTER_TABLES][2][OTHERBLK_VLC_SIZE] = { + { + { + 0, 5, 8, 3, 6, 9, 6, 7, 9, 4, 6, 9, 6, 7, 9, 8, + 8, 9, 7, 8, 9, 8, 9, 9, 9, 9, 9, 2, 6, 9, 4, 7, + 9, 7, 8, 9, 5, 7, 9, 6, 7, 9, 8, 8, 9, 7, 8, 9, + 8, 9, 9, 9, 9, 8, 5, 8, 10, 6, 8, 10, 8, 9, 9, 7, + 8, 10, 7, 9, 10, 8, 9, 9, 8, 9, 10, 9, 9, 10, 9, 9, + 9, 7, 9, 10, 8, 9, 10, 8, 8, 9, 8, 9, 10, 8, 9, 10, + 8, 8, 9, 8, 9, 9, 8, 9, 9, 8, 8, 7, + }, + { + 0, 4, 9, 2, 6, 10, 7, 8, 10, 3, 6, 10, 6, 7, 10, 9, + 9, 10, 8, 9, 11, 9, 10, 11, 10, 11, 11, 2, 6, 10, 4, 7, + 10, 8, 9, 10, 5, 7, 10, 7, 8, 10, 9, 9, 10, 9, 10, 11, + 10, 10, 11, 11, 11, 11, 6, 9, 11, 7, 9, 11, 9, 10, 12, 8, + 9, 11, 8, 10, 11, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, + 11, 9, 11, 12, 10, 11, 12, 10, 11, 12, 10, 11, 12, 10, 11, 12, + 11, 11, 12, 11, 12, 12, 11, 12, 12, 12, 11, 11, + }, + }, + { + { + 0, 4, 9, 3, 6, 9, 6, 8, 9, 4, 6, 9, 5, 7, 9, 8, + 8, 9, 7, 8, 10, 8, 9, 10, 9, 9, 9, 2, 6, 9, 4, 7, + 9, 7, 8, 9, 5, 7, 9, 6, 7, 10, 8, 9, 9, 7, 9, 10, + 8, 9, 10, 9, 9, 9, 5, 8, 10, 6, 8, 10, 8, 9, 10, 7, + 8, 10, 7, 9, 11, 9, 9, 10, 8, 9, 10, 9, 10, 10, 10, 10, + 9, 7, 9, 10, 8, 9, 11, 8, 9, 10, 8, 9, 11, 8, 9, 11, + 9, 9, 10, 9, 9, 10, 9, 9, 10, 9, 9, 8, + }, + { + 0, 4, 9, 2, 5, 10, 7, 8, 11, 3, 6, 10, 6, 7, 10, 9, + 10, 11, 8, 9, 11, 9, 10, 11, 11, 11, 12, 2, 6, 10, 4, 7, + 10, 8, 9, 11, 5, 7, 10, 6, 8, 10, 9, 10, 11, 9, 10, 12, + 10, 10, 12, 11, 12, 12, 6, 9, 11, 8, 9, 12, 9, 11, 13, 8, + 10, 12, 9, 10, 12, 11, 11, 12, 10, 12, 13, 11, 12, 13, 13, 12, + 13, 10, 11, 13, 10, 12, 13, 11, 12, 13, 11, 12, 13, 11, 12, 13, + 12, 12, 13, 12, 13, 14, 13, 13, 14, 13, 13, 13, + }, + }, + { + { + 0, 4, 9, 3, 6, 9, 7, 8, 10, 3, 6, 9, 5, 7, 10, 8, + 9, 10, 7, 9, 10, 8, 9, 10, 10, 10, 10, 2, 6, 9, 4, 7, + 10, 7, 9, 10, 4, 7, 10, 6, 8, 10, 8, 9, 10, 8, 9, 10, + 9, 9, 10, 10, 10, 10, 5, 8, 11, 7, 9, 11, 8, 10, 11, 7, + 9, 11, 8, 9, 11, 9, 10, 11, 9, 10, 11, 10, 10, 11, 11, 11, + 11, 8, 10, 11, 9, 10, 11, 9, 10, 11, 9, 10, 12, 9, 10, 12, + 10, 11, 11, 9, 10, 11, 10, 11, 11, 10, 10, 10, + }, + { + 0, 4, 10, 3, 6, 11, 8, 10, 12, 3, 6, 11, 6, 8, 11, 10, + 11, 13, 9, 10, 13, 11, 12, 14, 13, 13, 14, 1, 6, 10, 5, 8, + 12, 9, 10, 13, 5, 8, 11, 7, 9, 12, 11, 11, 13, 10, 12, 13, + 11, 12, 14, 14, 13, 15, 7, 10, 12, 9, 11, 14, 11, 12, 15, 9, + 11, 13, 10, 11, 14, 12, 12, 14, 12, 14, 16, 13, 13, 16, 14, 14, + 16, 12, 13, 15, 12, 14, 15, 13, 14, 16, 13, 14, 16, 14, 14, 16, + 14, 15, 16, 14, 16, 16, 15, 16, 16, 15, 15, 16, + }, + }, + { + { + 0, 4, 9, 2, 6, 9, 7, 9, 11, 3, 6, 10, 6, 7, 10, 9, + 10, 11, 7, 9, 10, 9, 10, 11, 11, 11, 12, 2, 6, 10, 4, 7, + 10, 8, 9, 11, 5, 7, 10, 7, 8, 10, 9, 10, 11, 8, 9, 11, + 9, 10, 11, 11, 12, 11, 6, 9, 11, 7, 10, 12, 9, 11, 12, 7, + 10, 12, 9, 10, 12, 11, 11, 12, 9, 11, 12, 10, 11, 12, 12, 12, + 12, 9, 11, 12, 9, 11, 13, 11, 12, 13, 9, 11, 13, 10, 12, 13, + 11, 12, 13, 11, 12, 13, 11, 12, 13, 12, 13, 12, + }, + { + 0, 4, 11, 2, 6, 12, 9, 11, 16, 4, 7, 12, 7, 9, 15, 11, + 12, 16, 10, 11, 16, 11, 13, 16, 16, 16, 16, 1, 6, 11, 5, 8, + 16, 9, 12, 16, 6, 9, 15, 8, 10, 16, 12, 13, 16, 12, 14, 16, + 12, 16, 16, 16, 16, 16, 8, 11, 14, 10, 12, 16, 12, 16, 16, 10, + 13, 16, 12, 16, 16, 13, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, + 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 5, 9, 3, 6, 10, 8, 10, 12, 3, 6, 10, 6, 8, 10, 10, + 11, 12, 8, 9, 11, 10, 10, 12, 13, 13, 13, 1, 6, 10, 5, 8, + 11, 9, 11, 13, 5, 8, 11, 7, 9, 11, 11, 11, 13, 8, 9, 11, + 10, 10, 12, 13, 13, 14, 6, 9, 12, 8, 11, 13, 11, 13, 15, 8, + 10, 13, 10, 11, 13, 12, 13, 15, 10, 12, 13, 12, 12, 13, 14, 14, + 14, 9, 12, 14, 11, 13, 15, 13, 15, 16, 11, 13, 15, 12, 14, 15, + 14, 15, 16, 13, 14, 15, 14, 14, 15, 15, 16, 16, + }, + { + 0, 4, 16, 2, 7, 16, 10, 13, 16, 3, 8, 16, 7, 10, 16, 16, + 16, 16, 12, 16, 16, 15, 16, 16, 16, 16, 16, 1, 7, 16, 6, 9, + 16, 10, 16, 16, 7, 12, 16, 9, 13, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 9, 16, 16, 11, 13, 16, 16, 16, 16, 12, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 4, 9, 3, 6, 11, 9, 12, 16, 3, 6, 10, 6, 8, 11, 12, + 13, 16, 8, 9, 12, 10, 11, 13, 16, 16, 16, 1, 6, 10, 5, 8, + 12, 10, 13, 16, 5, 8, 11, 8, 9, 13, 13, 14, 16, 9, 10, 14, + 11, 12, 15, 16, 16, 16, 6, 10, 13, 9, 12, 16, 14, 16, 16, 9, + 12, 14, 11, 13, 16, 16, 16, 16, 12, 14, 16, 14, 16, 16, 16, 16, + 16, 11, 16, 16, 13, 16, 16, 16, 16, 16, 12, 16, 16, 13, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 0, 4, 16, 2, 8, 16, 10, 16, 16, 3, 9, 16, 8, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 7, 16, 5, 10, + 16, 16, 16, 16, 7, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 10, 15, 16, 10, 16, 16, 16, 16, 16, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, + { + { + 0, 3, 9, 3, 7, 11, 11, 15, 16, 3, 6, 11, 7, 9, 12, 16, + 16, 16, 8, 10, 16, 11, 16, 16, 16, 16, 16, 1, 6, 11, 6, 9, + 15, 16, 16, 16, 5, 8, 16, 9, 11, 16, 16, 16, 16, 10, 16, 16, + 16, 16, 16, 16, 16, 16, 7, 11, 16, 11, 16, 16, 16, 16, 16, 11, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + { + 0, 4, 16, 2, 8, 16, 16, 16, 16, 3, 12, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 7, 16, 5, 12, + 16, 16, 16, 16, 6, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }, + }, +}; + + +static const uint8_t rv34_inter_coeff[NUM_INTER_TABLES][COEFF_VLC_SIZE] = { +{ + 1, 2, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 8, 9, 9, 10, + 10, 10, 10, 11, 11, 11, 11, 12, 11, 11, 11, 13, 14, 15, 16, 16, +}, +{ + 1, 2, 3, 5, 5, 6, 6, 7, 7, 8, 9, 9, 9, 10, 10, 10, + 11, 11, 12, 12, 12, 12, 13, 13, 12, 12, 13, 14, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, + 12, 12, 13, 13, 13, 14, 14, 15, 14, 14, 16, 16, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 6, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, + 13, 13, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 11, 11, 13, 12, 12, 13, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, +}, +{ + 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 10, 11, 14, 13, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, +} +}; + +#endif /* AVCODEC_RV34VLC_H */ diff --git a/ffmpeg/libavcodec/rv40.c b/ffmpeg/libavcodec/rv40.c new file mode 100644 index 0000000..d6dfc5e --- /dev/null +++ b/ffmpeg/libavcodec/rv40.c @@ -0,0 +1,579 @@ +/* + * RV40 decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV40 decoder + */ + +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "mpegvideo.h" +#include "golomb.h" + +#include "rv34.h" +#include "rv40vlc2.h" +#include "rv40data.h" + +static VLC aic_top_vlc; +static VLC aic_mode1_vlc[AIC_MODE1_NUM], aic_mode2_vlc[AIC_MODE2_NUM]; +static VLC ptype_vlc[NUM_PTYPE_VLCS], btype_vlc[NUM_BTYPE_VLCS]; + +static const int16_t mode2_offs[] = { + 0, 614, 1222, 1794, 2410, 3014, 3586, 4202, 4792, 5382, 5966, 6542, + 7138, 7716, 8292, 8864, 9444, 10030, 10642, 11212, 11814 +}; + +/** + * Initialize all tables. + */ +static av_cold void rv40_init_tables(void) +{ + int i; + static VLC_TYPE aic_table[1 << AIC_TOP_BITS][2]; + static VLC_TYPE aic_mode1_table[AIC_MODE1_NUM << AIC_MODE1_BITS][2]; + static VLC_TYPE aic_mode2_table[11814][2]; + static VLC_TYPE ptype_table[NUM_PTYPE_VLCS << PTYPE_VLC_BITS][2]; + static VLC_TYPE btype_table[NUM_BTYPE_VLCS << BTYPE_VLC_BITS][2]; + + aic_top_vlc.table = aic_table; + aic_top_vlc.table_allocated = 1 << AIC_TOP_BITS; + init_vlc(&aic_top_vlc, AIC_TOP_BITS, AIC_TOP_SIZE, + rv40_aic_top_vlc_bits, 1, 1, + rv40_aic_top_vlc_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); + for(i = 0; i < AIC_MODE1_NUM; i++){ + // Every tenth VLC table is empty + if((i % 10) == 9) continue; + aic_mode1_vlc[i].table = &aic_mode1_table[i << AIC_MODE1_BITS]; + aic_mode1_vlc[i].table_allocated = 1 << AIC_MODE1_BITS; + init_vlc(&aic_mode1_vlc[i], AIC_MODE1_BITS, AIC_MODE1_SIZE, + aic_mode1_vlc_bits[i], 1, 1, + aic_mode1_vlc_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + for(i = 0; i < AIC_MODE2_NUM; i++){ + aic_mode2_vlc[i].table = &aic_mode2_table[mode2_offs[i]]; + aic_mode2_vlc[i].table_allocated = mode2_offs[i + 1] - mode2_offs[i]; + init_vlc(&aic_mode2_vlc[i], AIC_MODE2_BITS, AIC_MODE2_SIZE, + aic_mode2_vlc_bits[i], 1, 1, + aic_mode2_vlc_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + for(i = 0; i < NUM_PTYPE_VLCS; i++){ + ptype_vlc[i].table = &ptype_table[i << PTYPE_VLC_BITS]; + ptype_vlc[i].table_allocated = 1 << PTYPE_VLC_BITS; + ff_init_vlc_sparse(&ptype_vlc[i], PTYPE_VLC_BITS, PTYPE_VLC_SIZE, + ptype_vlc_bits[i], 1, 1, + ptype_vlc_codes[i], 1, 1, + ptype_vlc_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); + } + for(i = 0; i < NUM_BTYPE_VLCS; i++){ + btype_vlc[i].table = &btype_table[i << BTYPE_VLC_BITS]; + btype_vlc[i].table_allocated = 1 << BTYPE_VLC_BITS; + ff_init_vlc_sparse(&btype_vlc[i], BTYPE_VLC_BITS, BTYPE_VLC_SIZE, + btype_vlc_bits[i], 1, 1, + btype_vlc_codes[i], 1, 1, + btype_vlc_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); + } +} + +/** + * Get stored dimension from bitstream. + * + * If the width/height is the standard one then it's coded as a 3-bit index. + * Otherwise it is coded as escaped 8-bit portions. + */ +static int get_dimension(GetBitContext *gb, const int *dim) +{ + int t = get_bits(gb, 3); + int val = dim[t]; + if(val < 0) + val = dim[get_bits1(gb) - val]; + if(!val){ + do{ + t = get_bits(gb, 8); + val += t << 2; + }while(t == 0xFF); + } + return val; +} + +/** + * Get encoded picture size - usually this is called from rv40_parse_slice_header. + */ +static void rv40_parse_picture_size(GetBitContext *gb, int *w, int *h) +{ + *w = get_dimension(gb, rv40_standard_widths); + *h = get_dimension(gb, rv40_standard_heights); +} + +static int rv40_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceInfo *si) +{ + int mb_bits; + int w = r->s.width, h = r->s.height; + int mb_size; + + memset(si, 0, sizeof(SliceInfo)); + if(get_bits1(gb)) + return -1; + si->type = get_bits(gb, 2); + if(si->type == 1) si->type = 0; + si->quant = get_bits(gb, 5); + if(get_bits(gb, 2)) + return -1; + si->vlc_set = get_bits(gb, 2); + skip_bits1(gb); + si->pts = get_bits(gb, 13); + if(!si->type || !get_bits1(gb)) + rv40_parse_picture_size(gb, &w, &h); + if(av_image_check_size(w, h, 0, r->s.avctx) < 0) + return -1; + si->width = w; + si->height = h; + mb_size = ((w + 15) >> 4) * ((h + 15) >> 4); + mb_bits = ff_rv34_get_start_offset(gb, mb_size); + si->start = get_bits(gb, mb_bits); + + return 0; +} + +/** + * Decode 4x4 intra types array. + */ +static int rv40_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t *dst) +{ + MpegEncContext *s = &r->s; + int i, j, k, v; + int A, B, C; + int pattern; + int8_t *ptr; + + for(i = 0; i < 4; i++, dst += r->intra_types_stride){ + if(!i && s->first_slice_line){ + pattern = get_vlc2(gb, aic_top_vlc.table, AIC_TOP_BITS, 1); + dst[0] = (pattern >> 2) & 2; + dst[1] = (pattern >> 1) & 2; + dst[2] = pattern & 2; + dst[3] = (pattern << 1) & 2; + continue; + } + ptr = dst; + for(j = 0; j < 4; j++){ + /* Coefficients are read using VLC chosen by the prediction pattern + * The first one (used for retrieving a pair of coefficients) is + * constructed from the top, top right and left coefficients + * The second one (used for retrieving only one coefficient) is + * top + 10 * left. + */ + A = ptr[-r->intra_types_stride + 1]; // it won't be used for the last coefficient in a row + B = ptr[-r->intra_types_stride]; + C = ptr[-1]; + pattern = A + (B << 4) + (C << 8); + for(k = 0; k < MODE2_PATTERNS_NUM; k++) + if(pattern == rv40_aic_table_index[k]) + break; + if(j < 3 && k < MODE2_PATTERNS_NUM){ //pattern is found, decoding 2 coefficients + v = get_vlc2(gb, aic_mode2_vlc[k].table, AIC_MODE2_BITS, 2); + *ptr++ = v/9; + *ptr++ = v%9; + j++; + }else{ + if(B != -1 && C != -1) + v = get_vlc2(gb, aic_mode1_vlc[B + C*10].table, AIC_MODE1_BITS, 1); + else{ // tricky decoding + v = 0; + switch(C){ + case -1: // code 0 -> 1, 1 -> 0 + if(B < 2) + v = get_bits1(gb) ^ 1; + break; + case 0: + case 2: // code 0 -> 2, 1 -> 0 + v = (get_bits1(gb) ^ 1) << 1; + break; + } + } + *ptr++ = v; + } + } + } + return 0; +} + +/** + * Decode macroblock information. + */ +static int rv40_decode_mb_info(RV34DecContext *r) +{ + MpegEncContext *s = &r->s; + GetBitContext *gb = &s->gb; + int q, i; + int prev_type = 0; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + if(!r->s.mb_skip_run) { + r->s.mb_skip_run = svq3_get_ue_golomb(gb) + 1; + if(r->s.mb_skip_run > (unsigned)s->mb_num) + return -1; + } + + if(--r->s.mb_skip_run) + return RV34_MB_SKIP; + + if(r->avail_cache[6-4]){ + int blocks[RV34_MB_TYPES] = {0}; + int count = 0; + if(r->avail_cache[6-1]) + blocks[r->mb_type[mb_pos - 1]]++; + blocks[r->mb_type[mb_pos - s->mb_stride]]++; + if(r->avail_cache[6-2]) + blocks[r->mb_type[mb_pos - s->mb_stride + 1]]++; + if(r->avail_cache[6-5]) + blocks[r->mb_type[mb_pos - s->mb_stride - 1]]++; + for(i = 0; i < RV34_MB_TYPES; i++){ + if(blocks[i] > count){ + count = blocks[i]; + prev_type = i; + if(count>1) + break; + } + } + } else if (r->avail_cache[6-1]) + prev_type = r->mb_type[mb_pos - 1]; + + if(s->pict_type == AV_PICTURE_TYPE_P){ + prev_type = block_num_to_ptype_vlc_num[prev_type]; + q = get_vlc2(gb, ptype_vlc[prev_type].table, PTYPE_VLC_BITS, 1); + if(q < PBTYPE_ESCAPE) + return q; + q = get_vlc2(gb, ptype_vlc[prev_type].table, PTYPE_VLC_BITS, 1); + av_log(s->avctx, AV_LOG_ERROR, "Dquant for P-frame\n"); + }else{ + prev_type = block_num_to_btype_vlc_num[prev_type]; + q = get_vlc2(gb, btype_vlc[prev_type].table, BTYPE_VLC_BITS, 1); + if(q < PBTYPE_ESCAPE) + return q; + q = get_vlc2(gb, btype_vlc[prev_type].table, BTYPE_VLC_BITS, 1); + av_log(s->avctx, AV_LOG_ERROR, "Dquant for B-frame\n"); + } + return 0; +} + +enum RV40BlockPos{ + POS_CUR, + POS_TOP, + POS_LEFT, + POS_BOTTOM, +}; + +#define MASK_CUR 0x0001 +#define MASK_RIGHT 0x0008 +#define MASK_BOTTOM 0x0010 +#define MASK_TOP 0x1000 +#define MASK_Y_TOP_ROW 0x000F +#define MASK_Y_LAST_ROW 0xF000 +#define MASK_Y_LEFT_COL 0x1111 +#define MASK_Y_RIGHT_COL 0x8888 +#define MASK_C_TOP_ROW 0x0003 +#define MASK_C_LAST_ROW 0x000C +#define MASK_C_LEFT_COL 0x0005 +#define MASK_C_RIGHT_COL 0x000A + +static const int neighbour_offs_x[4] = { 0, 0, -1, 0 }; +static const int neighbour_offs_y[4] = { 0, -1, 0, 1 }; + +static void rv40_adaptive_loop_filter(RV34DSPContext *rdsp, + uint8_t *src, int stride, int dmode, + int lim_q1, int lim_p1, + int alpha, int beta, int beta2, + int chroma, int edge, int dir) +{ + int filter_p1, filter_q1; + int strong; + int lims; + + strong = rdsp->rv40_loop_filter_strength[dir](src, stride, beta, beta2, + edge, &filter_p1, &filter_q1); + + lims = filter_p1 + filter_q1 + ((lim_q1 + lim_p1) >> 1) + 1; + + if (strong) { + rdsp->rv40_strong_loop_filter[dir](src, stride, alpha, + lims, dmode, chroma); + } else if (filter_p1 & filter_q1) { + rdsp->rv40_weak_loop_filter[dir](src, stride, 1, 1, alpha, beta, + lims, lim_q1, lim_p1); + } else if (filter_p1 | filter_q1) { + rdsp->rv40_weak_loop_filter[dir](src, stride, filter_p1, filter_q1, + alpha, beta, lims >> 1, lim_q1 >> 1, + lim_p1 >> 1); + } +} + +/** + * RV40 loop filtering function + */ +static void rv40_loop_filter(RV34DecContext *r, int row) +{ + MpegEncContext *s = &r->s; + int mb_pos, mb_x; + int i, j, k; + uint8_t *Y, *C; + int alpha, beta, betaY, betaC; + int q; + int mbtype[4]; ///< current macroblock and its neighbours types + /** + * flags indicating that macroblock can be filtered with strong filter + * it is set only for intra coded MB and MB with DCs coded separately + */ + int mb_strong[4]; + int clip[4]; ///< MB filter clipping value calculated from filtering strength + /** + * coded block patterns for luma part of current macroblock and its neighbours + * Format: + * LSB corresponds to the top left block, + * each nibble represents one row of subblocks. + */ + int cbp[4]; + /** + * coded block patterns for chroma part of current macroblock and its neighbours + * Format is the same as for luma with two subblocks in a row. + */ + int uvcbp[4][2]; + /** + * This mask represents the pattern of luma subblocks that should be filtered + * in addition to the coded ones because because they lie at the edge of + * 8x8 block with different enough motion vectors + */ + unsigned mvmasks[4]; + + mb_pos = row * s->mb_stride; + for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ + int mbtype = s->current_picture_ptr->mb_type[mb_pos]; + if(IS_INTRA(mbtype) || IS_SEPARATE_DC(mbtype)) + r->cbp_luma [mb_pos] = r->deblock_coefs[mb_pos] = 0xFFFF; + if(IS_INTRA(mbtype)) + r->cbp_chroma[mb_pos] = 0xFF; + } + mb_pos = row * s->mb_stride; + for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ + int y_h_deblock, y_v_deblock; + int c_v_deblock[2], c_h_deblock[2]; + int clip_left; + int avail[4]; + unsigned y_to_deblock; + int c_to_deblock[2]; + + q = s->current_picture_ptr->qscale_table[mb_pos]; + alpha = rv40_alpha_tab[q]; + beta = rv40_beta_tab [q]; + betaY = betaC = beta * 3; + if(s->width * s->height <= 176*144) + betaY += beta; + + avail[0] = 1; + avail[1] = row; + avail[2] = mb_x; + avail[3] = row < s->mb_height - 1; + for(i = 0; i < 4; i++){ + if(avail[i]){ + int pos = mb_pos + neighbour_offs_x[i] + neighbour_offs_y[i]*s->mb_stride; + mvmasks[i] = r->deblock_coefs[pos]; + mbtype [i] = s->current_picture_ptr->mb_type[pos]; + cbp [i] = r->cbp_luma[pos]; + uvcbp[i][0] = r->cbp_chroma[pos] & 0xF; + uvcbp[i][1] = r->cbp_chroma[pos] >> 4; + }else{ + mvmasks[i] = 0; + mbtype [i] = mbtype[0]; + cbp [i] = 0; + uvcbp[i][0] = uvcbp[i][1] = 0; + } + mb_strong[i] = IS_INTRA(mbtype[i]) || IS_SEPARATE_DC(mbtype[i]); + clip[i] = rv40_filter_clip_tbl[mb_strong[i] + 1][q]; + } + y_to_deblock = mvmasks[POS_CUR] + | (mvmasks[POS_BOTTOM] << 16); + /* This pattern contains bits signalling that horizontal edges of + * the current block can be filtered. + * That happens when either of adjacent subblocks is coded or lies on + * the edge of 8x8 blocks with motion vectors differing by more than + * 3/4 pel in any component (any edge orientation for some reason). + */ + y_h_deblock = y_to_deblock + | ((cbp[POS_CUR] << 4) & ~MASK_Y_TOP_ROW) + | ((cbp[POS_TOP] & MASK_Y_LAST_ROW) >> 12); + /* This pattern contains bits signalling that vertical edges of + * the current block can be filtered. + * That happens when either of adjacent subblocks is coded or lies on + * the edge of 8x8 blocks with motion vectors differing by more than + * 3/4 pel in any component (any edge orientation for some reason). + */ + y_v_deblock = y_to_deblock + | ((cbp[POS_CUR] << 1) & ~MASK_Y_LEFT_COL) + | ((cbp[POS_LEFT] & MASK_Y_RIGHT_COL) >> 3); + if(!mb_x) + y_v_deblock &= ~MASK_Y_LEFT_COL; + if(!row) + y_h_deblock &= ~MASK_Y_TOP_ROW; + if(row == s->mb_height - 1 || (mb_strong[POS_CUR] | mb_strong[POS_BOTTOM])) + y_h_deblock &= ~(MASK_Y_TOP_ROW << 16); + /* Calculating chroma patterns is similar and easier since there is + * no motion vector pattern for them. + */ + for(i = 0; i < 2; i++){ + c_to_deblock[i] = (uvcbp[POS_BOTTOM][i] << 4) | uvcbp[POS_CUR][i]; + c_v_deblock[i] = c_to_deblock[i] + | ((uvcbp[POS_CUR] [i] << 1) & ~MASK_C_LEFT_COL) + | ((uvcbp[POS_LEFT][i] & MASK_C_RIGHT_COL) >> 1); + c_h_deblock[i] = c_to_deblock[i] + | ((uvcbp[POS_TOP][i] & MASK_C_LAST_ROW) >> 2) + | (uvcbp[POS_CUR][i] << 2); + if(!mb_x) + c_v_deblock[i] &= ~MASK_C_LEFT_COL; + if(!row) + c_h_deblock[i] &= ~MASK_C_TOP_ROW; + if(row == s->mb_height - 1 || (mb_strong[POS_CUR] | mb_strong[POS_BOTTOM])) + c_h_deblock[i] &= ~(MASK_C_TOP_ROW << 4); + } + + for(j = 0; j < 16; j += 4){ + Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize; + for(i = 0; i < 4; i++, Y += 4){ + int ij = i + j; + int clip_cur = y_to_deblock & (MASK_CUR << ij) ? clip[POS_CUR] : 0; + int dither = j ? ij : i*4; + + // if bottom block is coded then we can filter its top edge + // (or bottom edge of this block, which is the same) + if(y_h_deblock & (MASK_BOTTOM << ij)){ + rv40_adaptive_loop_filter(&r->rdsp, Y+4*s->linesize, + s->linesize, dither, + y_to_deblock & (MASK_BOTTOM << ij) ? clip[POS_CUR] : 0, + clip_cur, alpha, beta, betaY, + 0, 0, 0); + } + // filter left block edge in ordinary mode (with low filtering strength) + if(y_v_deblock & (MASK_CUR << ij) && (i || !(mb_strong[POS_CUR] | mb_strong[POS_LEFT]))){ + if(!i) + clip_left = mvmasks[POS_LEFT] & (MASK_RIGHT << j) ? clip[POS_LEFT] : 0; + else + clip_left = y_to_deblock & (MASK_CUR << (ij-1)) ? clip[POS_CUR] : 0; + rv40_adaptive_loop_filter(&r->rdsp, Y, s->linesize, dither, + clip_cur, + clip_left, + alpha, beta, betaY, 0, 0, 1); + } + // filter top edge of the current macroblock when filtering strength is high + if(!j && y_h_deblock & (MASK_CUR << i) && (mb_strong[POS_CUR] | mb_strong[POS_TOP])){ + rv40_adaptive_loop_filter(&r->rdsp, Y, s->linesize, dither, + clip_cur, + mvmasks[POS_TOP] & (MASK_TOP << i) ? clip[POS_TOP] : 0, + alpha, beta, betaY, 0, 1, 0); + } + // filter left block edge in edge mode (with high filtering strength) + if(y_v_deblock & (MASK_CUR << ij) && !i && (mb_strong[POS_CUR] | mb_strong[POS_LEFT])){ + clip_left = mvmasks[POS_LEFT] & (MASK_RIGHT << j) ? clip[POS_LEFT] : 0; + rv40_adaptive_loop_filter(&r->rdsp, Y, s->linesize, dither, + clip_cur, + clip_left, + alpha, beta, betaY, 0, 1, 1); + } + } + } + for(k = 0; k < 2; k++){ + for(j = 0; j < 2; j++){ + C = s->current_picture_ptr->f.data[k + 1] + mb_x*8 + (row*8 + j*4) * s->uvlinesize; + for(i = 0; i < 2; i++, C += 4){ + int ij = i + j*2; + int clip_cur = c_to_deblock[k] & (MASK_CUR << ij) ? clip[POS_CUR] : 0; + if(c_h_deblock[k] & (MASK_CUR << (ij+2))){ + int clip_bot = c_to_deblock[k] & (MASK_CUR << (ij+2)) ? clip[POS_CUR] : 0; + rv40_adaptive_loop_filter(&r->rdsp, C+4*s->uvlinesize, s->uvlinesize, i*8, + clip_bot, + clip_cur, + alpha, beta, betaC, 1, 0, 0); + } + if((c_v_deblock[k] & (MASK_CUR << ij)) && (i || !(mb_strong[POS_CUR] | mb_strong[POS_LEFT]))){ + if(!i) + clip_left = uvcbp[POS_LEFT][k] & (MASK_CUR << (2*j+1)) ? clip[POS_LEFT] : 0; + else + clip_left = c_to_deblock[k] & (MASK_CUR << (ij-1)) ? clip[POS_CUR] : 0; + rv40_adaptive_loop_filter(&r->rdsp, C, s->uvlinesize, j*8, + clip_cur, + clip_left, + alpha, beta, betaC, 1, 0, 1); + } + if(!j && c_h_deblock[k] & (MASK_CUR << ij) && (mb_strong[POS_CUR] | mb_strong[POS_TOP])){ + int clip_top = uvcbp[POS_TOP][k] & (MASK_CUR << (ij+2)) ? clip[POS_TOP] : 0; + rv40_adaptive_loop_filter(&r->rdsp, C, s->uvlinesize, i*8, + clip_cur, + clip_top, + alpha, beta, betaC, 1, 1, 0); + } + if(c_v_deblock[k] & (MASK_CUR << ij) && !i && (mb_strong[POS_CUR] | mb_strong[POS_LEFT])){ + clip_left = uvcbp[POS_LEFT][k] & (MASK_CUR << (2*j+1)) ? clip[POS_LEFT] : 0; + rv40_adaptive_loop_filter(&r->rdsp, C, s->uvlinesize, j*8, + clip_cur, + clip_left, + alpha, beta, betaC, 1, 1, 1); + } + } + } + } + } +} + +/** + * Initialize decoder. + */ +static av_cold int rv40_decode_init(AVCodecContext *avctx) +{ + RV34DecContext *r = avctx->priv_data; + + r->rv30 = 0; + ff_rv34_decode_init(avctx); + if(!aic_top_vlc.bits) + rv40_init_tables(); + r->parse_slice_header = rv40_parse_slice_header; + r->decode_intra_types = rv40_decode_intra_types; + r->decode_mb_info = rv40_decode_mb_info; + r->loop_filter = rv40_loop_filter; + r->luma_dc_quant_i = rv40_luma_dc_quant[0]; + r->luma_dc_quant_p = rv40_luma_dc_quant[1]; + return 0; +} + +AVCodec ff_rv40_decoder = { + .name = "rv40", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_RV40, + .priv_data_size = sizeof(RV34DecContext), + .init = rv40_decode_init, + .close = ff_rv34_decode_end, + .decode = ff_rv34_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | + CODEC_CAP_FRAME_THREADS, + .flush = ff_mpeg_flush, + .long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"), + .pix_fmts = ff_pixfmt_list_420, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), +}; diff --git a/ffmpeg/libavcodec/rv40data.h b/ffmpeg/libavcodec/rv40data.h new file mode 100644 index 0000000..36f9f91 --- /dev/null +++ b/ffmpeg/libavcodec/rv40data.h @@ -0,0 +1,101 @@ +/* + * RealVideo 4 decoder + * copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * miscellaneous RV40 tables + */ + +#ifndef AVCODEC_RV40DATA_H +#define AVCODEC_RV40DATA_H + +#include + +/** + * standard widths and heights coded in RV40 + */ +//@{ +static const int rv40_standard_widths[] = { 160, 172, 240, 320, 352, 640, 704, 0}; +static const int rv40_standard_heights[] = { 120, 132, 144, 240, 288, 480, -8, -10, 180, 360, 576, 0}; +//@} + +#define MODE2_PATTERNS_NUM 20 +/** + * intra types table + * + * These values are actually coded 3-tuples + * used for detecting standard block configurations. + */ +static const uint16_t rv40_aic_table_index[MODE2_PATTERNS_NUM] = { + 0x000, 0x100, 0x200, + 0x011, 0x111, 0x211, 0x511, 0x611, + 0x022, 0x122, 0x222, 0x722, + 0x272, 0x227, + 0x822, 0x282, 0x228, + 0x112, 0x116, 0x221 +}; + +/** + * luma quantizer values + * The second table is used for inter blocks. + */ +static const uint8_t rv40_luma_dc_quant[2][32] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 22, 22, 22, 22 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 20, 21, 21, 22, 23, 23, 23, 24, 24, 24, 24 } +}; + +/** + * @name Coefficients used by the RV40 loop filter + * @{ + */ + +/** alpha parameter for RV40 loop filter - almost the same as in JVT-A003r1 */ +static const uint8_t rv40_alpha_tab[32] = { + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 122, 96, 75, 59, 47, 37, + 29, 23, 18, 15, 13, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1 +}; +/** beta parameter for RV40 loop filter - almost the same as in JVT-A003r1 */ +static const uint8_t rv40_beta_tab[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 4, 4, 4, 6, 6, + 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 13, 14, 15, 16, 17 +}; +/** clip table for RV40 loop filter - the same as in JVT-A003r1 */ +static const uint8_t rv40_filter_clip_tbl[3][32] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5 + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 7, 8, 9 + } +}; +/** @} */ // end loopfilter group + +#endif /* AVCODEC_RV40DATA_H */ diff --git a/ffmpeg/libavcodec/rv40dsp.c b/ffmpeg/libavcodec/rv40dsp.c new file mode 100644 index 0000000..fda8947 --- /dev/null +++ b/ffmpeg/libavcodec/rv40dsp.c @@ -0,0 +1,626 @@ +/* + * RV40 decoder motion compensation functions + * Copyright (c) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV40 decoder motion compensation functions + */ + +#include "avcodec.h" +#include "h264qpel.h" +#include "rv34dsp.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" + +#define RV40_LOWPASS(OPNAME, OP) \ +static av_unused void OPNAME ## rv40_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,\ + const int h, const int C1, const int C2, const int SHIFT){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i = 0; i < h; i++)\ + {\ + OP(dst[0], (src[-2] + src[ 3] - 5*(src[-1]+src[2]) + src[0]*C1 + src[1]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[1], (src[-1] + src[ 4] - 5*(src[ 0]+src[3]) + src[1]*C1 + src[2]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[2], (src[ 0] + src[ 5] - 5*(src[ 1]+src[4]) + src[2]*C1 + src[3]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[3], (src[ 1] + src[ 6] - 5*(src[ 2]+src[5]) + src[3]*C1 + src[4]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[4], (src[ 2] + src[ 7] - 5*(src[ 3]+src[6]) + src[4]*C1 + src[5]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[5], (src[ 3] + src[ 8] - 5*(src[ 4]+src[7]) + src[5]*C1 + src[6]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[6], (src[ 4] + src[ 9] - 5*(src[ 5]+src[8]) + src[6]*C1 + src[7]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[7], (src[ 5] + src[10] - 5*(src[ 6]+src[9]) + src[7]*C1 + src[8]*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + dst += dstStride;\ + src += srcStride;\ + }\ +}\ +\ +static void OPNAME ## rv40_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,\ + const int w, const int C1, const int C2, const int SHIFT){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int i;\ + for(i = 0; i < w; i++)\ + {\ + const int srcB = src[-2*srcStride];\ + const int srcA = src[-1*srcStride];\ + const int src0 = src[0 *srcStride];\ + const int src1 = src[1 *srcStride];\ + const int src2 = src[2 *srcStride];\ + const int src3 = src[3 *srcStride];\ + const int src4 = src[4 *srcStride];\ + const int src5 = src[5 *srcStride];\ + const int src6 = src[6 *srcStride];\ + const int src7 = src[7 *srcStride];\ + const int src8 = src[8 *srcStride];\ + const int src9 = src[9 *srcStride];\ + const int src10 = src[10*srcStride];\ + OP(dst[0*dstStride], (srcB + src3 - 5*(srcA+src2) + src0*C1 + src1*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[1*dstStride], (srcA + src4 - 5*(src0+src3) + src1*C1 + src2*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[2*dstStride], (src0 + src5 - 5*(src1+src4) + src2*C1 + src3*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[3*dstStride], (src1 + src6 - 5*(src2+src5) + src3*C1 + src4*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[4*dstStride], (src2 + src7 - 5*(src3+src6) + src4*C1 + src5*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[5*dstStride], (src3 + src8 - 5*(src4+src7) + src5*C1 + src6*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[6*dstStride], (src4 + src9 - 5*(src5+src8) + src6*C1 + src7*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + OP(dst[7*dstStride], (src5 + src10 - 5*(src6+src9) + src7*C1 + src8*C2 + (1<<(SHIFT-1))) >> SHIFT);\ + dst++;\ + src++;\ + }\ +}\ +\ +static void OPNAME ## rv40_qpel16_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,\ + const int w, const int C1, const int C2, const int SHIFT){\ + OPNAME ## rv40_qpel8_v_lowpass(dst , src , dstStride, srcStride, 8, C1, C2, SHIFT);\ + OPNAME ## rv40_qpel8_v_lowpass(dst+8, src+8, dstStride, srcStride, 8, C1, C2, SHIFT);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv40_qpel8_v_lowpass(dst , src , dstStride, srcStride, w-8, C1, C2, SHIFT);\ + OPNAME ## rv40_qpel8_v_lowpass(dst+8, src+8, dstStride, srcStride, w-8, C1, C2, SHIFT);\ +}\ +\ +static void OPNAME ## rv40_qpel16_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride,\ + const int h, const int C1, const int C2, const int SHIFT){\ + OPNAME ## rv40_qpel8_h_lowpass(dst , src , dstStride, srcStride, 8, C1, C2, SHIFT);\ + OPNAME ## rv40_qpel8_h_lowpass(dst+8, src+8, dstStride, srcStride, 8, C1, C2, SHIFT);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## rv40_qpel8_h_lowpass(dst , src , dstStride, srcStride, h-8, C1, C2, SHIFT);\ + OPNAME ## rv40_qpel8_h_lowpass(dst+8, src+8, dstStride, srcStride, h-8, C1, C2, SHIFT);\ +}\ +\ + +#define RV40_MC(OPNAME, SIZE) \ +static void OPNAME ## rv40_qpel ## SIZE ## _mc10_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv40_qpel ## SIZE ## _h_lowpass(dst, src, stride, stride, SIZE, 52, 20, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc30_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv40_qpel ## SIZE ## _h_lowpass(dst, src, stride, stride, SIZE, 20, 52, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc01_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, src, stride, stride, SIZE, 52, 20, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc11_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 52, 20, 6);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 52, 20, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc21_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 20, 20, 5);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 52, 20, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc31_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 20, 52, 6);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 52, 20, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc12_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 52, 20, 6);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 20, 20, 5);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc22_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 20, 20, 5);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 20, 20, 5);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc32_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 20, 52, 6);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 20, 20, 5);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc03_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, src, stride, stride, SIZE, 20, 52, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc13_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 52, 20, 6);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 20, 52, 6);\ +}\ +\ +static void OPNAME ## rv40_qpel ## SIZE ## _mc23_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + uint8_t full[SIZE*(SIZE+5)];\ + uint8_t * const full_mid = full + SIZE*2;\ + put_rv40_qpel ## SIZE ## _h_lowpass(full, src - 2*stride, SIZE, stride, SIZE+5, 20, 20, 5);\ + OPNAME ## rv40_qpel ## SIZE ## _v_lowpass(dst, full_mid, stride, SIZE, SIZE, 20, 52, 6);\ +}\ +\ + +#define op_avg(a, b) a = (((a)+cm[b]+1)>>1) +#define op_put(a, b) a = cm[b] + +RV40_LOWPASS(put_ , op_put) +RV40_LOWPASS(avg_ , op_avg) + +#undef op_avg +#undef op_put + +RV40_MC(put_, 8) +RV40_MC(put_, 16) +RV40_MC(avg_, 8) +RV40_MC(avg_, 16) + +static const int rv40_bias[4][4] = { + { 0, 16, 32, 16 }, + { 32, 28, 32, 28 }, + { 0, 32, 16, 32 }, + { 32, 28, 32, 28 } +}; + +#define RV40_CHROMA_MC(OPNAME, OP)\ +static void OPNAME ## rv40_chroma_mc4_c(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){\ + const int A = (8-x) * (8-y);\ + const int B = ( x) * (8-y);\ + const int C = (8-x) * ( y);\ + const int D = ( x) * ( y);\ + int i;\ + int bias = rv40_bias[y>>1][x>>1];\ + \ + av_assert2(x<8 && y<8 && x>=0 && y>=0);\ +\ + if(D){\ + for(i = 0; i < h; i++){\ + OP(dst[0], (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1] + bias));\ + OP(dst[1], (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + bias));\ + OP(dst[2], (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + bias));\ + OP(dst[3], (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + bias));\ + dst += stride;\ + src += stride;\ + }\ + }else{\ + const int E = B + C;\ + const int step = C ? stride : 1;\ + for(i = 0; i < h; i++){\ + OP(dst[0], (A*src[0] + E*src[step+0] + bias));\ + OP(dst[1], (A*src[1] + E*src[step+1] + bias));\ + OP(dst[2], (A*src[2] + E*src[step+2] + bias));\ + OP(dst[3], (A*src[3] + E*src[step+3] + bias));\ + dst += stride;\ + src += stride;\ + }\ + }\ +}\ +\ +static void OPNAME ## rv40_chroma_mc8_c(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){\ + const int A = (8-x) * (8-y);\ + const int B = ( x) * (8-y);\ + const int C = (8-x) * ( y);\ + const int D = ( x) * ( y);\ + int i;\ + int bias = rv40_bias[y>>1][x>>1];\ + \ + av_assert2(x<8 && y<8 && x>=0 && y>=0);\ +\ + if(D){\ + for(i = 0; i < h; i++){\ + OP(dst[0], (A*src[0] + B*src[1] + C*src[stride+0] + D*src[stride+1] + bias));\ + OP(dst[1], (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + bias));\ + OP(dst[2], (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + bias));\ + OP(dst[3], (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + bias));\ + OP(dst[4], (A*src[4] + B*src[5] + C*src[stride+4] + D*src[stride+5] + bias));\ + OP(dst[5], (A*src[5] + B*src[6] + C*src[stride+5] + D*src[stride+6] + bias));\ + OP(dst[6], (A*src[6] + B*src[7] + C*src[stride+6] + D*src[stride+7] + bias));\ + OP(dst[7], (A*src[7] + B*src[8] + C*src[stride+7] + D*src[stride+8] + bias));\ + dst += stride;\ + src += stride;\ + }\ + }else{\ + const int E = B + C;\ + const int step = C ? stride : 1;\ + for(i = 0; i < h; i++){\ + OP(dst[0], (A*src[0] + E*src[step+0] + bias));\ + OP(dst[1], (A*src[1] + E*src[step+1] + bias));\ + OP(dst[2], (A*src[2] + E*src[step+2] + bias));\ + OP(dst[3], (A*src[3] + E*src[step+3] + bias));\ + OP(dst[4], (A*src[4] + E*src[step+4] + bias));\ + OP(dst[5], (A*src[5] + E*src[step+5] + bias));\ + OP(dst[6], (A*src[6] + E*src[step+6] + bias));\ + OP(dst[7], (A*src[7] + E*src[step+7] + bias));\ + dst += stride;\ + src += stride;\ + }\ + }\ +} + +#define op_avg(a, b) a = (((a)+((b)>>6)+1)>>1) +#define op_put(a, b) a = ((b)>>6) + +RV40_CHROMA_MC(put_, op_put) +RV40_CHROMA_MC(avg_, op_avg) + +#define RV40_WEIGHT_FUNC(size) \ +static void rv40_weight_func_rnd_ ## size (uint8_t *dst, uint8_t *src1, uint8_t *src2, int w1, int w2, ptrdiff_t stride)\ +{\ + int i, j;\ +\ + for (j = 0; j < size; j++) {\ + for (i = 0; i < size; i++)\ + dst[i] = (((w2 * src1[i]) >> 9) + ((w1 * src2[i]) >> 9) + 0x10) >> 5;\ + src1 += stride;\ + src2 += stride;\ + dst += stride;\ + }\ +}\ +static void rv40_weight_func_nornd_ ## size (uint8_t *dst, uint8_t *src1, uint8_t *src2, int w1, int w2, ptrdiff_t stride)\ +{\ + int i, j;\ +\ + for (j = 0; j < size; j++) {\ + for (i = 0; i < size; i++)\ + dst[i] = (w2 * src1[i] + w1 * src2[i] + 0x10) >> 5;\ + src1 += stride;\ + src2 += stride;\ + dst += stride;\ + }\ +} + +RV40_WEIGHT_FUNC(16) +RV40_WEIGHT_FUNC(8) + +/** + * dither values for deblocking filter - left/top values + */ +static const uint8_t rv40_dither_l[16] = { + 0x40, 0x50, 0x20, 0x60, 0x30, 0x50, 0x40, 0x30, + 0x50, 0x40, 0x50, 0x30, 0x60, 0x20, 0x50, 0x40 +}; + +/** + * dither values for deblocking filter - right/bottom values + */ +static const uint8_t rv40_dither_r[16] = { + 0x40, 0x30, 0x60, 0x20, 0x50, 0x30, 0x30, 0x40, + 0x40, 0x40, 0x50, 0x30, 0x20, 0x60, 0x30, 0x40 +}; + +#define CLIP_SYMM(a, b) av_clip(a, -(b), b) +/** + * weaker deblocking very similar to the one described in 4.4.2 of JVT-A003r1 + */ +static av_always_inline void rv40_weak_loop_filter(uint8_t *src, + const int step, + const ptrdiff_t stride, + const int filter_p1, + const int filter_q1, + const int alpha, + const int beta, + const int lim_p0q0, + const int lim_q1, + const int lim_p1) +{ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + int i, t, u, diff; + + for (i = 0; i < 4; i++, src += stride) { + int diff_p1p0 = src[-2*step] - src[-1*step]; + int diff_q1q0 = src[ 1*step] - src[ 0*step]; + int diff_p1p2 = src[-2*step] - src[-3*step]; + int diff_q1q2 = src[ 1*step] - src[ 2*step]; + + t = src[0*step] - src[-1*step]; + if (!t) + continue; + + u = (alpha * FFABS(t)) >> 7; + if (u > 3 - (filter_p1 && filter_q1)) + continue; + + t <<= 2; + if (filter_p1 && filter_q1) + t += src[-2*step] - src[1*step]; + + diff = CLIP_SYMM((t + 4) >> 3, lim_p0q0); + src[-1*step] = cm[src[-1*step] + diff]; + src[ 0*step] = cm[src[ 0*step] - diff]; + + if (filter_p1 && FFABS(diff_p1p2) <= beta) { + t = (diff_p1p0 + diff_p1p2 - diff) >> 1; + src[-2*step] = cm[src[-2*step] - CLIP_SYMM(t, lim_p1)]; + } + + if (filter_q1 && FFABS(diff_q1q2) <= beta) { + t = (diff_q1q0 + diff_q1q2 + diff) >> 1; + src[ 1*step] = cm[src[ 1*step] - CLIP_SYMM(t, lim_q1)]; + } + } +} + +static void rv40_h_weak_loop_filter(uint8_t *src, const ptrdiff_t stride, + const int filter_p1, const int filter_q1, + const int alpha, const int beta, + const int lim_p0q0, const int lim_q1, + const int lim_p1) +{ + rv40_weak_loop_filter(src, stride, 1, filter_p1, filter_q1, + alpha, beta, lim_p0q0, lim_q1, lim_p1); +} + +static void rv40_v_weak_loop_filter(uint8_t *src, const ptrdiff_t stride, + const int filter_p1, const int filter_q1, + const int alpha, const int beta, + const int lim_p0q0, const int lim_q1, + const int lim_p1) +{ + rv40_weak_loop_filter(src, 1, stride, filter_p1, filter_q1, + alpha, beta, lim_p0q0, lim_q1, lim_p1); +} + +static av_always_inline void rv40_strong_loop_filter(uint8_t *src, + const int step, + const ptrdiff_t stride, + const int alpha, + const int lims, + const int dmode, + const int chroma) +{ + int i; + + for(i = 0; i < 4; i++, src += stride){ + int sflag, p0, q0, p1, q1; + int t = src[0*step] - src[-1*step]; + + if (!t) + continue; + + sflag = (alpha * FFABS(t)) >> 7; + if (sflag > 1) + continue; + + p0 = (25*src[-3*step] + 26*src[-2*step] + 26*src[-1*step] + + 26*src[ 0*step] + 25*src[ 1*step] + + rv40_dither_l[dmode + i]) >> 7; + + q0 = (25*src[-2*step] + 26*src[-1*step] + 26*src[ 0*step] + + 26*src[ 1*step] + 25*src[ 2*step] + + rv40_dither_r[dmode + i]) >> 7; + + if (sflag) { + p0 = av_clip(p0, src[-1*step] - lims, src[-1*step] + lims); + q0 = av_clip(q0, src[ 0*step] - lims, src[ 0*step] + lims); + } + + p1 = (25*src[-4*step] + 26*src[-3*step] + 26*src[-2*step] + 26*p0 + + 25*src[ 0*step] + rv40_dither_l[dmode + i]) >> 7; + q1 = (25*src[-1*step] + 26*q0 + 26*src[ 1*step] + 26*src[ 2*step] + + 25*src[ 3*step] + rv40_dither_r[dmode + i]) >> 7; + + if (sflag) { + p1 = av_clip(p1, src[-2*step] - lims, src[-2*step] + lims); + q1 = av_clip(q1, src[ 1*step] - lims, src[ 1*step] + lims); + } + + src[-2*step] = p1; + src[-1*step] = p0; + src[ 0*step] = q0; + src[ 1*step] = q1; + + if(!chroma){ + src[-3*step] = (25*src[-1*step] + 26*src[-2*step] + + 51*src[-3*step] + 26*src[-4*step] + 64) >> 7; + src[ 2*step] = (25*src[ 0*step] + 26*src[ 1*step] + + 51*src[ 2*step] + 26*src[ 3*step] + 64) >> 7; + } + } +} + +static void rv40_h_strong_loop_filter(uint8_t *src, const ptrdiff_t stride, + const int alpha, const int lims, + const int dmode, const int chroma) +{ + rv40_strong_loop_filter(src, stride, 1, alpha, lims, dmode, chroma); +} + +static void rv40_v_strong_loop_filter(uint8_t *src, const ptrdiff_t stride, + const int alpha, const int lims, + const int dmode, const int chroma) +{ + rv40_strong_loop_filter(src, 1, stride, alpha, lims, dmode, chroma); +} + +static av_always_inline int rv40_loop_filter_strength(uint8_t *src, + int step, ptrdiff_t stride, + int beta, int beta2, + int edge, + int *p1, int *q1) +{ + int sum_p1p0 = 0, sum_q1q0 = 0, sum_p1p2 = 0, sum_q1q2 = 0; + int strong0 = 0, strong1 = 0; + uint8_t *ptr; + int i; + + for (i = 0, ptr = src; i < 4; i++, ptr += stride) { + sum_p1p0 += ptr[-2*step] - ptr[-1*step]; + sum_q1q0 += ptr[ 1*step] - ptr[ 0*step]; + } + + *p1 = FFABS(sum_p1p0) < (beta << 2); + *q1 = FFABS(sum_q1q0) < (beta << 2); + + if(!*p1 && !*q1) + return 0; + + if (!edge) + return 0; + + for (i = 0, ptr = src; i < 4; i++, ptr += stride) { + sum_p1p2 += ptr[-2*step] - ptr[-3*step]; + sum_q1q2 += ptr[ 1*step] - ptr[ 2*step]; + } + + strong0 = *p1 && (FFABS(sum_p1p2) < beta2); + strong1 = *q1 && (FFABS(sum_q1q2) < beta2); + + return strong0 && strong1; +} + +static int rv40_h_loop_filter_strength(uint8_t *src, ptrdiff_t stride, + int beta, int beta2, int edge, + int *p1, int *q1) +{ + return rv40_loop_filter_strength(src, stride, 1, beta, beta2, edge, p1, q1); +} + +static int rv40_v_loop_filter_strength(uint8_t *src, ptrdiff_t stride, + int beta, int beta2, int edge, + int *p1, int *q1) +{ + return rv40_loop_filter_strength(src, 1, stride, beta, beta2, edge, p1, q1); +} + +av_cold void ff_rv40dsp_init(RV34DSPContext *c) +{ + H264QpelContext qpel; + + ff_rv34dsp_init(c); + ff_h264qpel_init(&qpel, 8); + + c->put_pixels_tab[0][ 0] = qpel.put_h264_qpel_pixels_tab[0][0]; + c->put_pixels_tab[0][ 1] = put_rv40_qpel16_mc10_c; + c->put_pixels_tab[0][ 2] = qpel.put_h264_qpel_pixels_tab[0][2]; + c->put_pixels_tab[0][ 3] = put_rv40_qpel16_mc30_c; + c->put_pixels_tab[0][ 4] = put_rv40_qpel16_mc01_c; + c->put_pixels_tab[0][ 5] = put_rv40_qpel16_mc11_c; + c->put_pixels_tab[0][ 6] = put_rv40_qpel16_mc21_c; + c->put_pixels_tab[0][ 7] = put_rv40_qpel16_mc31_c; + c->put_pixels_tab[0][ 8] = qpel.put_h264_qpel_pixels_tab[0][8]; + c->put_pixels_tab[0][ 9] = put_rv40_qpel16_mc12_c; + c->put_pixels_tab[0][10] = put_rv40_qpel16_mc22_c; + c->put_pixels_tab[0][11] = put_rv40_qpel16_mc32_c; + c->put_pixels_tab[0][12] = put_rv40_qpel16_mc03_c; + c->put_pixels_tab[0][13] = put_rv40_qpel16_mc13_c; + c->put_pixels_tab[0][14] = put_rv40_qpel16_mc23_c; + c->put_pixels_tab[0][15] = ff_put_rv40_qpel16_mc33_c; + c->avg_pixels_tab[0][ 0] = qpel.avg_h264_qpel_pixels_tab[0][0]; + c->avg_pixels_tab[0][ 1] = avg_rv40_qpel16_mc10_c; + c->avg_pixels_tab[0][ 2] = qpel.avg_h264_qpel_pixels_tab[0][2]; + c->avg_pixels_tab[0][ 3] = avg_rv40_qpel16_mc30_c; + c->avg_pixels_tab[0][ 4] = avg_rv40_qpel16_mc01_c; + c->avg_pixels_tab[0][ 5] = avg_rv40_qpel16_mc11_c; + c->avg_pixels_tab[0][ 6] = avg_rv40_qpel16_mc21_c; + c->avg_pixels_tab[0][ 7] = avg_rv40_qpel16_mc31_c; + c->avg_pixels_tab[0][ 8] = qpel.avg_h264_qpel_pixels_tab[0][8]; + c->avg_pixels_tab[0][ 9] = avg_rv40_qpel16_mc12_c; + c->avg_pixels_tab[0][10] = avg_rv40_qpel16_mc22_c; + c->avg_pixels_tab[0][11] = avg_rv40_qpel16_mc32_c; + c->avg_pixels_tab[0][12] = avg_rv40_qpel16_mc03_c; + c->avg_pixels_tab[0][13] = avg_rv40_qpel16_mc13_c; + c->avg_pixels_tab[0][14] = avg_rv40_qpel16_mc23_c; + c->avg_pixels_tab[0][15] = ff_avg_rv40_qpel16_mc33_c; + c->put_pixels_tab[1][ 0] = qpel.put_h264_qpel_pixels_tab[1][0]; + c->put_pixels_tab[1][ 1] = put_rv40_qpel8_mc10_c; + c->put_pixels_tab[1][ 2] = qpel.put_h264_qpel_pixels_tab[1][2]; + c->put_pixels_tab[1][ 3] = put_rv40_qpel8_mc30_c; + c->put_pixels_tab[1][ 4] = put_rv40_qpel8_mc01_c; + c->put_pixels_tab[1][ 5] = put_rv40_qpel8_mc11_c; + c->put_pixels_tab[1][ 6] = put_rv40_qpel8_mc21_c; + c->put_pixels_tab[1][ 7] = put_rv40_qpel8_mc31_c; + c->put_pixels_tab[1][ 8] = qpel.put_h264_qpel_pixels_tab[1][8]; + c->put_pixels_tab[1][ 9] = put_rv40_qpel8_mc12_c; + c->put_pixels_tab[1][10] = put_rv40_qpel8_mc22_c; + c->put_pixels_tab[1][11] = put_rv40_qpel8_mc32_c; + c->put_pixels_tab[1][12] = put_rv40_qpel8_mc03_c; + c->put_pixels_tab[1][13] = put_rv40_qpel8_mc13_c; + c->put_pixels_tab[1][14] = put_rv40_qpel8_mc23_c; + c->put_pixels_tab[1][15] = ff_put_rv40_qpel8_mc33_c; + c->avg_pixels_tab[1][ 0] = qpel.avg_h264_qpel_pixels_tab[1][0]; + c->avg_pixels_tab[1][ 1] = avg_rv40_qpel8_mc10_c; + c->avg_pixels_tab[1][ 2] = qpel.avg_h264_qpel_pixels_tab[1][2]; + c->avg_pixels_tab[1][ 3] = avg_rv40_qpel8_mc30_c; + c->avg_pixels_tab[1][ 4] = avg_rv40_qpel8_mc01_c; + c->avg_pixels_tab[1][ 5] = avg_rv40_qpel8_mc11_c; + c->avg_pixels_tab[1][ 6] = avg_rv40_qpel8_mc21_c; + c->avg_pixels_tab[1][ 7] = avg_rv40_qpel8_mc31_c; + c->avg_pixels_tab[1][ 8] = qpel.avg_h264_qpel_pixels_tab[1][8]; + c->avg_pixels_tab[1][ 9] = avg_rv40_qpel8_mc12_c; + c->avg_pixels_tab[1][10] = avg_rv40_qpel8_mc22_c; + c->avg_pixels_tab[1][11] = avg_rv40_qpel8_mc32_c; + c->avg_pixels_tab[1][12] = avg_rv40_qpel8_mc03_c; + c->avg_pixels_tab[1][13] = avg_rv40_qpel8_mc13_c; + c->avg_pixels_tab[1][14] = avg_rv40_qpel8_mc23_c; + c->avg_pixels_tab[1][15] = ff_avg_rv40_qpel8_mc33_c; + + c->put_chroma_pixels_tab[0] = put_rv40_chroma_mc8_c; + c->put_chroma_pixels_tab[1] = put_rv40_chroma_mc4_c; + c->avg_chroma_pixels_tab[0] = avg_rv40_chroma_mc8_c; + c->avg_chroma_pixels_tab[1] = avg_rv40_chroma_mc4_c; + + c->rv40_weight_pixels_tab[0][0] = rv40_weight_func_rnd_16; + c->rv40_weight_pixels_tab[0][1] = rv40_weight_func_rnd_8; + c->rv40_weight_pixels_tab[1][0] = rv40_weight_func_nornd_16; + c->rv40_weight_pixels_tab[1][1] = rv40_weight_func_nornd_8; + + c->rv40_weak_loop_filter[0] = rv40_h_weak_loop_filter; + c->rv40_weak_loop_filter[1] = rv40_v_weak_loop_filter; + c->rv40_strong_loop_filter[0] = rv40_h_strong_loop_filter; + c->rv40_strong_loop_filter[1] = rv40_v_strong_loop_filter; + c->rv40_loop_filter_strength[0] = rv40_h_loop_filter_strength; + c->rv40_loop_filter_strength[1] = rv40_v_loop_filter_strength; + + if (ARCH_X86) + ff_rv40dsp_init_x86(c); + if (ARCH_ARM) + ff_rv40dsp_init_arm(c); +} diff --git a/ffmpeg/libavcodec/rv40vlc2.h b/ffmpeg/libavcodec/rv40vlc2.h new file mode 100644 index 0000000..15119a1 --- /dev/null +++ b/ffmpeg/libavcodec/rv40vlc2.h @@ -0,0 +1,706 @@ +/* + * RealVideo 4 decoder + * copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV40 VLC tables used for macroblock information decoding + */ + +#ifndef AVCODEC_RV40VLC2_H +#define AVCODEC_RV40VLC2_H + +#include + +/** + * codes used for the first four block types + */ +//@{ +#define AIC_TOP_BITS 8 +#define AIC_TOP_SIZE 16 +static const uint8_t rv40_aic_top_vlc_codes[AIC_TOP_SIZE] = { + 0x01, 0x05, 0x01, 0x00, 0x03, 0x3D, 0x1D, 0x02, + 0x04, 0x3C, 0x3F, 0x1C, 0x0D, 0x3E, 0x0C, 0x01 +}; + +static const uint8_t rv40_aic_top_vlc_bits[AIC_TOP_SIZE] = { + 1, 4, 5, 5, 5, 7, 6, 5, 4, 7, 7, 6, 5, 7, 5, 3 +}; +//@} + +/** + * codes used for determining a pair of block types + */ +//@{ +#define AIC_MODE2_NUM 20 +#define AIC_MODE2_SIZE 81 +#define AIC_MODE2_BITS 9 + +static const uint16_t aic_mode2_vlc_codes[AIC_MODE2_NUM][AIC_MODE2_SIZE] = { +{ 0x0001, 0x0001, 0x0005, 0x01F5, 0x0011, 0x0049, 0x0000, 0x0048, 0x004B, + 0x0035, 0x0003, 0x0034, 0x03C9, 0x01F4, 0x00C9, 0x004A, 0x0FD9, 0x03C8, + 0x0010, 0x0037, 0x0001, 0x00C8, 0x0075, 0x01F7, 0x00CB, 0x0074, 0x0002, + 0x01F6, 0x00CA, 0x01F1, 0x01F0, 0x1F81, 0x07F9, 0x1F80, 0x1F83, 0x07F8, + 0x0077, 0x00F5, 0x0036, 0x07FB, 0x0076, 0x1F82, 0x00F4, 0x00F7, 0x07FA, + 0x0071, 0x00F6, 0x03CB, 0x03CA, 0x0FD8, 0x00F1, 0x03F5, 0x1F8D, 0x07E5, + 0x0013, 0x0031, 0x00F0, 0x0FDB, 0x00F3, 0x07E4, 0x0030, 0x01F3, 0x07E7, + 0x03F4, 0x07E6, 0x0070, 0x3F19, 0x01F2, 0x3F18, 0x0FDA, 0x0033, 0x07E1, + 0x01FD, 0x01FC, 0x0073, 0x01FF, 0x0FC5, 0x0FC4, 0x0FC7, 0x03F7, 0x0072, }, +{ 0x0005, 0x0005, 0x0005, 0x0079, 0x0005, 0x000D, 0x001D, 0x0078, 0x0069, + 0x0004, 0x0001, 0x0007, 0x0068, 0x001C, 0x001F, 0x0004, 0x006B, 0x000C, + 0x0004, 0x001E, 0x0006, 0x006A, 0x0015, 0x000F, 0x0014, 0x0017, 0x0007, + 0x0016, 0x000E, 0x0011, 0x0009, 0x00D1, 0x00D0, 0x0181, 0x00D3, 0x007B, + 0x0010, 0x0013, 0x0004, 0x00D2, 0x0007, 0x0319, 0x0008, 0x007A, 0x00DD, + 0x0019, 0x0006, 0x000B, 0x0065, 0x00DC, 0x0012, 0x0064, 0x0180, 0x00DF, + 0x0006, 0x0018, 0x0001, 0x00DE, 0x001D, 0x00D9, 0x001B, 0x0067, 0x000A, + 0x00D8, 0x00DB, 0x001C, 0x0318, 0x00DA, 0x0635, 0x0183, 0x0000, 0x00C5, + 0x0066, 0x0061, 0x0035, 0x00C4, 0x0182, 0x0634, 0x031B, 0x00C7, 0x001F, }, +{ 0x0005, 0x0001, 0x001D, 0x01C1, 0x0035, 0x00F1, 0x006D, 0x00F0, 0x0049, + 0x0000, 0x0004, 0x0003, 0x00F3, 0x0048, 0x0034, 0x006C, 0x01C0, 0x01C3, + 0x0007, 0x0006, 0x0001, 0x006F, 0x0002, 0x004B, 0x006E, 0x001C, 0x0005, + 0x0069, 0x0068, 0x006B, 0x0037, 0x01C2, 0x00F2, 0x0395, 0x01CD, 0x00FD, + 0x006A, 0x0036, 0x0015, 0x01CC, 0x0014, 0x0394, 0x004A, 0x00FC, 0x00FF, + 0x0017, 0x0031, 0x00FE, 0x01CF, 0x0397, 0x00F9, 0x01CE, 0x0725, 0x0396, + 0x0016, 0x0030, 0x0075, 0x0724, 0x00F8, 0x0727, 0x0033, 0x0391, 0x0390, + 0x0011, 0x0032, 0x001F, 0x00FB, 0x0074, 0x0726, 0x00FA, 0x001E, 0x0077, + 0x0019, 0x0018, 0x0004, 0x0010, 0x003D, 0x0076, 0x0071, 0x0013, 0x0001, }, +{ 0x000D, 0x0019, 0x0011, 0x0015, 0x0061, 0x0019, 0x0014, 0x01AD, 0x0060, + 0x0018, 0x0001, 0x0005, 0x001B, 0x0010, 0x0019, 0x0005, 0x0017, 0x0018, + 0x0016, 0x0004, 0x0004, 0x0013, 0x000C, 0x0012, 0x001A, 0x0018, 0x0005, + 0x000F, 0x001B, 0x0004, 0x001D, 0x0011, 0x001C, 0x0010, 0x000E, 0x001B, + 0x0013, 0x001F, 0x001A, 0x0029, 0x0005, 0x0063, 0x001E, 0x0009, 0x0062, + 0x0008, 0x0007, 0x0007, 0x0019, 0x0004, 0x001A, 0x0018, 0x006D, 0x0007, + 0x001B, 0x0007, 0x001A, 0x006C, 0x0006, 0x0012, 0x0005, 0x006F, 0x000B, + 0x006E, 0x0069, 0x001D, 0x0359, 0x0028, 0x002B, 0x002A, 0x001C, 0x00D5, + 0x0358, 0x001F, 0x0001, 0x001E, 0x0068, 0x00D4, 0x00D7, 0x0019, 0x0000, }, +{ 0x00B9, 0x0061, 0x0060, 0x00B8, 0x02B5, 0x01AD, 0x00BB, 0x0AF5, 0x0151, + 0x0001, 0x0001, 0x0005, 0x0000, 0x0003, 0x0005, 0x0004, 0x0063, 0x0025, + 0x00BA, 0x0004, 0x0007, 0x0062, 0x00A5, 0x0024, 0x006D, 0x0002, 0x006C, + 0x02B4, 0x000D, 0x006F, 0x0027, 0x00A4, 0x0026, 0x01AC, 0x0150, 0x01AF, + 0x01AE, 0x0021, 0x006E, 0x02B7, 0x0020, 0x0153, 0x0023, 0x00A7, 0x0152, + 0x00A6, 0x0006, 0x000C, 0x0022, 0x01A9, 0x0019, 0x002D, 0x02B6, 0x01A8, + 0x000F, 0x0007, 0x000E, 0x00A1, 0x0069, 0x002C, 0x0001, 0x01AB, 0x00A0, + 0x02B1, 0x00A3, 0x002F, 0x0AF4, 0x02B0, 0x0AF7, 0x02B3, 0x0068, 0x015D, + 0x0AF6, 0x01AA, 0x0055, 0x015C, 0x02B2, 0x0579, 0x0578, 0x015F, 0x00A2, }, +{ 0x0905, 0x013D, 0x013C, 0x0904, 0x121D, 0x049D, 0x049C, 0x243D, 0x0907, + 0x00ED, 0x0001, 0x0015, 0x0041, 0x013F, 0x0031, 0x0014, 0x025D, 0x025C, + 0x013E, 0x000D, 0x0000, 0x0040, 0x0139, 0x0043, 0x0030, 0x0017, 0x0033, + 0x0906, 0x0032, 0x0042, 0x00EC, 0x025F, 0x00EF, 0x025E, 0x049F, 0x0138, + 0x0901, 0x013B, 0x0259, 0x121C, 0x049E, 0x0900, 0x0258, 0x243C, 0x121F, + 0x0903, 0x003D, 0x00EE, 0x025B, 0x025A, 0x004D, 0x013A, 0x0902, 0x0245, + 0x00E9, 0x0016, 0x00E8, 0x0499, 0x0125, 0x0244, 0x004C, 0x0498, 0x090D, + 0x00EB, 0x003C, 0x0011, 0x049B, 0x049A, 0x0485, 0x00EA, 0x003F, 0x0124, + 0x090C, 0x003E, 0x0039, 0x0095, 0x0247, 0x0246, 0x0484, 0x0094, 0x0038, }, +{ 0x0F09, 0x00CD, 0x01FD, 0x0791, 0x1E6D, 0x0790, 0x03D9, 0x3CD1, 0x3CD0, + 0x0075, 0x0001, 0x0001, 0x0035, 0x00CC, 0x0011, 0x0000, 0x03D8, 0x01FC, + 0x03DB, 0x0010, 0x0003, 0x00CF, 0x03DA, 0x00CE, 0x0074, 0x0034, 0x0077, + 0x0793, 0x0013, 0x0076, 0x0071, 0x03C5, 0x0070, 0x01FF, 0x0792, 0x01FE, + 0x01F9, 0x0037, 0x00C9, 0x0F08, 0x01F8, 0x03C4, 0x00C8, 0x0F0B, 0x079D, + 0x03C7, 0x0001, 0x0012, 0x0073, 0x00CB, 0x0005, 0x0036, 0x03C6, 0x0072, + 0x007D, 0x0002, 0x00CA, 0x079C, 0x01FB, 0x00F5, 0x0031, 0x079F, 0x0F0A, + 0x0F35, 0x079E, 0x01FA, 0x1E6C, 0x1E6F, 0x3CD3, 0x0799, 0x03C1, 0x1E6E, + 0x3CD2, 0x0030, 0x00F4, 0x007C, 0x03C0, 0x03C3, 0x0798, 0x01E5, 0x00F7, }, +{ 0x01A5, 0x0001, 0x001D, 0x0021, 0x00A1, 0x000D, 0x0061, 0x06B9, 0x00A0, + 0x0060, 0x0001, 0x0005, 0x000C, 0x0020, 0x001C, 0x0004, 0x01A4, 0x01A7, + 0x00A3, 0x001F, 0x001E, 0x0023, 0x0022, 0x002D, 0x002C, 0x0063, 0x0062, + 0x1A81, 0x01A6, 0x01A1, 0x06B8, 0x06BB, 0x00A2, 0x06BA, 0x0D59, 0x06A5, + 0x01A0, 0x000F, 0x006D, 0x06A4, 0x002F, 0x00AD, 0x006C, 0x06A7, 0x00AC, + 0x0D58, 0x000E, 0x01A3, 0x00AF, 0x00AE, 0x006F, 0x01A2, 0x0D5B, 0x00A9, + 0x0019, 0x0001, 0x0009, 0x00A8, 0x006E, 0x002E, 0x0000, 0x01AD, 0x00AB, + 0x00AA, 0x0355, 0x0029, 0x1A80, 0x1A83, 0x1A82, 0x0354, 0x01AC, 0x0D5A, + 0x1A8D, 0x01AF, 0x0357, 0x0D45, 0x0D44, 0x0D47, 0x1A8C, 0x06A6, 0x06A1, }, +{ 0x0001, 0x0011, 0x0005, 0x0775, 0x00F9, 0x00F8, 0x0031, 0x0030, 0x0049, + 0x00FB, 0x0010, 0x0033, 0x0EC9, 0x038D, 0x038C, 0x00FA, 0x038F, 0x0774, + 0x0048, 0x0032, 0x0000, 0x01D5, 0x00E5, 0x038E, 0x00E4, 0x0013, 0x000D, + 0x0389, 0x0777, 0x0388, 0x038B, 0x1DF9, 0x0EC8, 0x3BC9, 0x1DF8, 0x038A, + 0x03B5, 0x0776, 0x00E7, 0x3BC8, 0x01D4, 0x3BCB, 0x0ECB, 0x0771, 0x0ECA, + 0x01D7, 0x03B4, 0x01D6, 0x1DFB, 0x0EF5, 0x0770, 0x0EF4, 0x3BCA, 0x0773, + 0x00E6, 0x03B7, 0x004B, 0x1DFA, 0x03B6, 0x0EF7, 0x00E1, 0x0EF6, 0x0EF1, + 0x03B1, 0x01D1, 0x003D, 0x0EF0, 0x0772, 0x077D, 0x077C, 0x003C, 0x01D0, + 0x03B0, 0x01D3, 0x003F, 0x03B3, 0x01D2, 0x0EF3, 0x077F, 0x00E0, 0x004A, }, +{ 0x0015, 0x0049, 0x0014, 0x07D1, 0x03FD, 0x03FC, 0x01C1, 0x01C0, 0x00F1, + 0x0017, 0x0001, 0x0001, 0x01C3, 0x0048, 0x004B, 0x0016, 0x0031, 0x01C2, + 0x004A, 0x0011, 0x0000, 0x01CD, 0x00F0, 0x01CC, 0x0075, 0x0010, 0x000D, + 0x03FF, 0x01CF, 0x01CE, 0x07D0, 0x0F81, 0x07D3, 0x1F1D, 0x0F80, 0x07D2, + 0x01C9, 0x03FE, 0x0074, 0x07DD, 0x00F3, 0x1F1C, 0x07DC, 0x03F9, 0x07DF, + 0x00F2, 0x00FD, 0x0077, 0x07DE, 0x07D9, 0x01C8, 0x07D8, 0x0F83, 0x03F8, + 0x0030, 0x0076, 0x0013, 0x0F82, 0x00FC, 0x03FB, 0x0033, 0x03FA, 0x03E5, + 0x03E4, 0x01CB, 0x0032, 0x1F1F, 0x03E7, 0x07DB, 0x07DA, 0x003D, 0x01CA, + 0x07C5, 0x03E6, 0x0071, 0x0F8D, 0x07C4, 0x1F1E, 0x0F8C, 0x03E1, 0x01F5, }, +{ 0x0019, 0x0065, 0x0018, 0x0351, 0x0350, 0x0353, 0x0021, 0x0020, 0x0064, + 0x001D, 0x0005, 0x0005, 0x01A5, 0x0023, 0x0067, 0x0005, 0x0066, 0x0022, + 0x001B, 0x0004, 0x0001, 0x0004, 0x001C, 0x0061, 0x001A, 0x0005, 0x0004, + 0x0007, 0x002D, 0x0006, 0x002C, 0x01A4, 0x002F, 0x0352, 0x035D, 0x0060, + 0x0001, 0x002E, 0x001F, 0x035C, 0x0000, 0x06B1, 0x01A7, 0x0029, 0x01A6, + 0x0028, 0x0063, 0x0062, 0x035F, 0x01A1, 0x002B, 0x06B0, 0x06B3, 0x01A0, + 0x0003, 0x006D, 0x001E, 0x035E, 0x006C, 0x06B2, 0x0002, 0x01A3, 0x01A2, + 0x000D, 0x0005, 0x0007, 0x01AD, 0x006F, 0x002A, 0x006E, 0x0004, 0x0004, + 0x000C, 0x0007, 0x0006, 0x000F, 0x000E, 0x00D5, 0x0009, 0x0006, 0x0007, }, +{ 0x0065, 0x0181, 0x0064, 0x36C9, 0x06D5, 0x0DB5, 0x0379, 0x0180, 0x0183, + 0x00D5, 0x001D, 0x001C, 0x0DB4, 0x0182, 0x0378, 0x00D4, 0x00D7, 0x06D4, + 0x0067, 0x001F, 0x0001, 0x00D6, 0x00D1, 0x018D, 0x0066, 0x0001, 0x0000, + 0x037B, 0x06D7, 0x037A, 0x0DB7, 0x36C8, 0x06D6, 0x0DB6, 0x1B79, 0x0DB1, + 0x018C, 0x0365, 0x00D0, 0x1B78, 0x00D3, 0x1B7B, 0x0364, 0x06D1, 0x06D0, + 0x018F, 0x018E, 0x00D2, 0x36CB, 0x0367, 0x0366, 0x06D3, 0x0DB0, 0x06D2, + 0x0361, 0x06DD, 0x0189, 0x36CA, 0x0360, 0x36F5, 0x0188, 0x0DB3, 0x36F4, + 0x0009, 0x0008, 0x0005, 0x06DC, 0x00DD, 0x018B, 0x00DC, 0x0004, 0x000B, + 0x018A, 0x0061, 0x0003, 0x0363, 0x00DF, 0x06DF, 0x0362, 0x000A, 0x001E, }, +{ 0x001D, 0x0061, 0x000D, 0x0D55, 0x06B9, 0x06B8, 0x01A5, 0x0021, 0x0020, + 0x0023, 0x000C, 0x0060, 0x0D54, 0x00AD, 0x00AC, 0x0022, 0x00AF, 0x06BB, + 0x000F, 0x001C, 0x0001, 0x002D, 0x0063, 0x01A4, 0x000E, 0x0001, 0x0005, + 0x01A7, 0x06BA, 0x01A6, 0x06A5, 0x0D57, 0x0D56, 0x1ABD, 0x0D51, 0x00AE, + 0x002C, 0x00A9, 0x002F, 0x0D50, 0x01A1, 0x1ABC, 0x06A4, 0x06A7, 0x06A6, + 0x00A8, 0x06A1, 0x01A0, 0x1ABF, 0x0D53, 0x06A0, 0x0D52, 0x1ABE, 0x06A3, + 0x0062, 0x002E, 0x0009, 0x0D5D, 0x01A3, 0x0D5C, 0x006D, 0x00AB, 0x06A2, + 0x006C, 0x001F, 0x0001, 0x06AD, 0x0029, 0x01A2, 0x0028, 0x0004, 0x001E, + 0x01AD, 0x006F, 0x0000, 0x01AC, 0x01AF, 0x06AC, 0x00AA, 0x006E, 0x0019, }, +{ 0x0019, 0x007D, 0x0018, 0x01B5, 0x000D, 0x01B4, 0x007C, 0x007F, 0x01B7, + 0x000C, 0x001B, 0x001A, 0x01B6, 0x000F, 0x00D5, 0x0019, 0x007E, 0x00D4, + 0x0018, 0x001B, 0x0001, 0x000E, 0x0011, 0x0009, 0x0005, 0x0005, 0x0005, + 0x00D7, 0x01B1, 0x0008, 0x01B0, 0x0079, 0x06FD, 0x0371, 0x0370, 0x00D6, + 0x0078, 0x01B3, 0x0010, 0x0373, 0x0013, 0x06FC, 0x007B, 0x007A, 0x00D1, + 0x00D0, 0x00D3, 0x0065, 0x0372, 0x06FF, 0x0064, 0x06FE, 0x037D, 0x00D2, + 0x00DD, 0x0067, 0x0004, 0x037C, 0x0012, 0x01B2, 0x0007, 0x0066, 0x01BD, + 0x0006, 0x0061, 0x0004, 0x01BC, 0x001A, 0x0060, 0x001D, 0x0004, 0x001C, + 0x0063, 0x0001, 0x0007, 0x000B, 0x0000, 0x0062, 0x000A, 0x0005, 0x0007, }, +{ 0x0069, 0x0045, 0x0068, 0x04BD, 0x0255, 0x04BC, 0x00E5, 0x00E4, 0x0031, + 0x0030, 0x0019, 0x0001, 0x0121, 0x00E7, 0x00E6, 0x0033, 0x00E1, 0x00E0, + 0x006B, 0x0018, 0x0001, 0x0044, 0x0032, 0x0047, 0x006A, 0x001B, 0x0005, + 0x003D, 0x0046, 0x0015, 0x0041, 0x0120, 0x0123, 0x04BF, 0x0122, 0x0040, + 0x003C, 0x00E3, 0x0014, 0x0254, 0x0043, 0x0975, 0x012D, 0x00E2, 0x00ED, + 0x0042, 0x00EC, 0x004D, 0x0257, 0x0256, 0x0251, 0x04BE, 0x0974, 0x0250, + 0x00EF, 0x00EE, 0x004C, 0x04B9, 0x012C, 0x04B8, 0x004F, 0x04BB, 0x0253, + 0x003F, 0x0017, 0x0001, 0x0252, 0x00E9, 0x00E8, 0x00EB, 0x0000, 0x0003, + 0x0016, 0x0002, 0x0004, 0x004E, 0x003E, 0x00EA, 0x0049, 0x000D, 0x0007, }, +{ 0x000D, 0x01BD, 0x000C, 0x0D31, 0x0D30, 0x0D33, 0x0359, 0x0358, 0x002D, + 0x0065, 0x001D, 0x001C, 0x0D32, 0x035B, 0x035A, 0x002C, 0x01BC, 0x0345, + 0x000F, 0x001F, 0x0001, 0x002F, 0x0064, 0x01BF, 0x0067, 0x0001, 0x0005, + 0x0066, 0x002E, 0x0061, 0x0029, 0x0695, 0x0694, 0x0697, 0x0696, 0x0060, + 0x01BE, 0x0D3D, 0x0028, 0x1A49, 0x0344, 0x1A48, 0x1A4B, 0x0D3C, 0x0691, + 0x002B, 0x01B9, 0x002A, 0x0D3F, 0x0690, 0x0347, 0x0D3E, 0x1A4A, 0x0346, + 0x00D5, 0x0341, 0x0063, 0x0D39, 0x0340, 0x0D38, 0x01B8, 0x0D3B, 0x0D3A, + 0x00D4, 0x0062, 0x0000, 0x0693, 0x01BB, 0x0343, 0x0342, 0x001E, 0x000E, + 0x006D, 0x0009, 0x0001, 0x006C, 0x00D7, 0x034D, 0x01BA, 0x0008, 0x0004, }, +{ 0x0075, 0x00CD, 0x0035, 0x03C1, 0x03C0, 0x07F9, 0x03C3, 0x1F8D, 0x00CC, + 0x0074, 0x0011, 0x0010, 0x03C2, 0x0FD9, 0x01F1, 0x00CF, 0x03CD, 0x00CE, + 0x0034, 0x0001, 0x0001, 0x0037, 0x00C9, 0x00C8, 0x0036, 0x0000, 0x0001, + 0x0FD8, 0x03CC, 0x00CB, 0x01F0, 0x07F8, 0x03CF, 0x07FB, 0x07FA, 0x00CA, + 0x01F3, 0x03CE, 0x00F5, 0x0FDB, 0x00F4, 0x07E5, 0x07E4, 0x07E7, 0x01F2, + 0x07E6, 0x03C9, 0x01FD, 0x0FDA, 0x1F8C, 0x07E1, 0x1F8F, 0x1F8E, 0x03C8, + 0x03CB, 0x0077, 0x0076, 0x0FC5, 0x03CA, 0x07E0, 0x00F7, 0x0FC4, 0x03F5, + 0x00F6, 0x01FC, 0x0003, 0x03F4, 0x0071, 0x03F7, 0x00F1, 0x0013, 0x0031, + 0x0030, 0x0070, 0x0005, 0x0012, 0x0073, 0x01FF, 0x0072, 0x007D, 0x0002, }, +{ 0x0061, 0x0055, 0x0060, 0x02C9, 0x02C8, 0x02CB, 0x0171, 0x00B5, 0x0054, + 0x0001, 0x0001, 0x0001, 0x0057, 0x0001, 0x0063, 0x001D, 0x0062, 0x0039, + 0x006D, 0x0000, 0x0005, 0x0038, 0x0056, 0x00B4, 0x006C, 0x0003, 0x001C, + 0x006F, 0x003B, 0x0002, 0x003A, 0x0170, 0x00B7, 0x0173, 0x0051, 0x006E, + 0x0025, 0x0050, 0x0069, 0x02CA, 0x0024, 0x0027, 0x0172, 0x00B6, 0x00B1, + 0x000D, 0x000C, 0x001F, 0x017D, 0x0026, 0x0068, 0x0053, 0x017C, 0x006B, + 0x001E, 0x000F, 0x0004, 0x017F, 0x006A, 0x02F5, 0x0019, 0x0021, 0x0052, + 0x02F4, 0x02F7, 0x0020, 0x0BCD, 0x05E5, 0x05E4, 0x0BCC, 0x0023, 0x00B0, + 0x02F6, 0x00B3, 0x0022, 0x02F1, 0x02F0, 0x0BCF, 0x0BCE, 0x017E, 0x005D, }, +{ 0x00BD, 0x0025, 0x01A1, 0x0159, 0x0299, 0x00BC, 0x0024, 0x0505, 0x0504, + 0x01A0, 0x0001, 0x001D, 0x006D, 0x001C, 0x0001, 0x0005, 0x0027, 0x01A3, + 0x0158, 0x001F, 0x001E, 0x01A2, 0x0026, 0x0021, 0x000D, 0x0020, 0x0023, + 0x0298, 0x006C, 0x0022, 0x00BF, 0x00BE, 0x01AD, 0x002D, 0x029B, 0x00B9, + 0x01AC, 0x00B8, 0x01AF, 0x029A, 0x006F, 0x015B, 0x006E, 0x0285, 0x0284, + 0x01AE, 0x0019, 0x002C, 0x01A9, 0x01A8, 0x000C, 0x000F, 0x015A, 0x00BB, + 0x000E, 0x0000, 0x0069, 0x01AB, 0x0018, 0x01AA, 0x0004, 0x0055, 0x00BA, + 0x0507, 0x0145, 0x0054, 0x0506, 0x00A5, 0x0501, 0x00A4, 0x0057, 0x0500, + 0x0A05, 0x0144, 0x00A7, 0x0287, 0x0286, 0x0503, 0x0147, 0x0A04, 0x0146, }, +{ 0x0759, 0x0041, 0x00E5, 0x03BD, 0x0E9D, 0x012D, 0x012C, 0x3A1D, 0x03BC, + 0x012F, 0x000D, 0x0040, 0x00E4, 0x03BF, 0x0043, 0x0042, 0x0758, 0x03BE, + 0x00E7, 0x0001, 0x0000, 0x003D, 0x00E6, 0x0015, 0x0014, 0x0017, 0x003C, + 0x743D, 0x012E, 0x03B9, 0x03B8, 0x0E9C, 0x03BB, 0x075B, 0x3A1C, 0x0E9F, + 0x0129, 0x00E1, 0x0128, 0x0E9E, 0x012B, 0x075A, 0x00E0, 0x0E99, 0x0745, + 0x3A1F, 0x03BA, 0x0744, 0x0E98, 0x1D0D, 0x03A5, 0x0E9B, 0x743C, 0x0E9A, + 0x012A, 0x004D, 0x00E3, 0x0E85, 0x01D5, 0x0E84, 0x004C, 0x0747, 0x1D0C, + 0x01D4, 0x003F, 0x0016, 0x0746, 0x03A4, 0x0741, 0x004F, 0x003E, 0x01D7, + 0x0740, 0x000C, 0x0011, 0x004E, 0x00E2, 0x00ED, 0x00EC, 0x0049, 0x0048, }, +}; + +static const uint8_t aic_mode2_vlc_bits[AIC_MODE2_NUM][AIC_MODE2_SIZE] = { +{ 1, 5, 4, 10, 6, 8, 5, 8, 8, + 7, 5, 7, 11, 10, 9, 8, 13, 11, + 6, 7, 3, 9, 8, 10, 9, 8, 5, + 10, 9, 10, 10, 14, 12, 14, 14, 12, + 8, 9, 7, 12, 8, 14, 9, 9, 12, + 8, 9, 11, 11, 13, 9, 11, 14, 12, + 6, 7, 9, 13, 9, 12, 7, 10, 12, + 11, 12, 8, 15, 10, 15, 13, 7, 12, + 10, 10, 8, 10, 13, 13, 13, 11, 8, }, +{ 4, 6, 5, 11, 8, 10, 7, 11, 9, + 4, 1, 4, 9, 7, 7, 5, 9, 10, + 6, 7, 4, 9, 9, 10, 9, 9, 6, + 9, 10, 9, 10, 12, 12, 13, 12, 11, + 9, 9, 8, 12, 8, 14, 10, 11, 12, + 7, 8, 10, 11, 12, 9, 11, 13, 12, + 6, 7, 8, 12, 9, 12, 7, 11, 10, + 12, 12, 9, 14, 12, 15, 13, 8, 12, + 11, 11, 10, 12, 13, 15, 14, 12, 9, }, +{ 5, 7, 6, 12, 9, 11, 8, 11, 10, + 7, 5, 7, 11, 10, 9, 8, 12, 12, + 5, 5, 1, 8, 7, 10, 8, 6, 4, + 8, 8, 8, 9, 12, 11, 13, 12, 11, + 8, 9, 8, 12, 8, 13, 10, 11, 11, + 8, 9, 11, 12, 13, 11, 12, 14, 13, + 8, 9, 10, 14, 11, 14, 9, 13, 13, + 8, 9, 6, 11, 10, 14, 11, 6, 10, + 6, 6, 4, 8, 9, 10, 10, 8, 5, }, +{ 11, 7, 8, 10, 12, 9, 10, 14, 12, + 7, 1, 5, 7, 8, 6, 4, 10, 9, + 10, 5, 4, 8, 11, 8, 7, 6, 7, + 11, 6, 7, 8, 10, 8, 10, 11, 9, + 10, 8, 9, 13, 9, 12, 8, 11, 12, + 11, 4, 7, 8, 9, 6, 8, 12, 9, + 8, 5, 8, 12, 9, 10, 6, 12, 11, + 12, 12, 10, 15, 13, 13, 13, 10, 13, + 15, 10, 9, 10, 12, 13, 13, 10, 9, }, +{ 11, 8, 8, 11, 13, 10, 11, 15, 12, + 7, 1, 4, 7, 7, 5, 4, 8, 9, + 11, 5, 5, 8, 11, 9, 8, 7, 8, + 13, 7, 8, 9, 11, 9, 10, 12, 10, + 10, 9, 8, 13, 9, 12, 9, 11, 12, + 11, 5, 7, 9, 10, 6, 9, 13, 10, + 7, 4, 7, 11, 8, 9, 5, 10, 11, + 13, 11, 9, 15, 13, 15, 13, 8, 12, + 15, 10, 10, 12, 13, 14, 14, 12, 11, }, +{ 12, 9, 9, 12, 13, 11, 11, 14, 12, + 8, 2, 5, 7, 9, 6, 5, 10, 10, + 9, 4, 2, 7, 9, 7, 6, 5, 6, + 12, 6, 7, 8, 10, 8, 10, 11, 9, + 12, 9, 10, 13, 11, 12, 10, 14, 13, + 12, 6, 8, 10, 10, 7, 9, 12, 10, + 8, 5, 8, 11, 9, 10, 7, 11, 12, + 8, 6, 5, 11, 11, 11, 8, 6, 9, + 12, 6, 6, 8, 10, 10, 11, 8, 6, }, +{ 13, 9, 10, 12, 14, 12, 11, 15, 15, + 8, 1, 5, 7, 9, 6, 5, 11, 10, + 11, 6, 5, 9, 11, 9, 8, 7, 8, + 12, 6, 8, 8, 11, 8, 10, 12, 10, + 10, 7, 9, 13, 10, 11, 9, 13, 12, + 11, 3, 6, 8, 9, 4, 7, 11, 8, + 8, 5, 9, 12, 10, 9, 7, 12, 13, + 13, 12, 10, 14, 14, 15, 12, 11, 14, + 15, 7, 9, 8, 11, 11, 12, 10, 9, }, +{ 10, 5, 6, 9, 11, 7, 8, 12, 11, + 8, 1, 4, 7, 9, 6, 4, 10, 10, + 11, 6, 6, 9, 9, 9, 9, 8, 8, + 14, 10, 10, 12, 12, 11, 12, 13, 12, + 10, 7, 8, 12, 9, 11, 8, 12, 11, + 13, 7, 10, 11, 11, 8, 10, 13, 11, + 6, 3, 7, 11, 8, 9, 5, 10, 11, + 11, 11, 9, 14, 14, 14, 11, 10, 13, + 14, 10, 11, 13, 13, 13, 14, 12, 12, }, +{ 2, 5, 3, 11, 8, 8, 6, 6, 7, + 8, 5, 6, 12, 10, 10, 8, 10, 11, + 7, 6, 2, 9, 8, 10, 8, 5, 4, + 10, 11, 10, 10, 13, 12, 14, 13, 10, + 10, 11, 8, 14, 9, 14, 12, 11, 12, + 9, 10, 9, 13, 12, 11, 12, 14, 11, + 8, 10, 7, 13, 10, 12, 8, 12, 12, + 10, 9, 6, 12, 11, 11, 11, 6, 9, + 10, 9, 6, 10, 9, 12, 11, 8, 7, }, +{ 6, 8, 6, 12, 11, 11, 10, 10, 9, + 6, 1, 3, 10, 8, 8, 6, 7, 10, + 8, 6, 3, 10, 9, 10, 8, 6, 5, + 11, 10, 10, 12, 13, 12, 14, 13, 12, + 10, 11, 8, 12, 9, 14, 12, 11, 12, + 9, 9, 8, 12, 12, 10, 12, 13, 11, + 7, 8, 6, 13, 9, 11, 7, 11, 11, + 11, 10, 7, 14, 11, 12, 12, 7, 10, + 12, 11, 8, 13, 12, 14, 13, 11, 10, }, +{ 7, 10, 7, 13, 13, 13, 11, 11, 10, + 8, 5, 6, 12, 11, 10, 9, 10, 11, + 7, 5, 1, 9, 8, 10, 7, 4, 4, + 9, 11, 9, 11, 12, 11, 13, 13, 10, + 9, 11, 8, 13, 9, 14, 12, 11, 12, + 11, 10, 10, 13, 12, 11, 14, 14, 12, + 9, 10, 8, 13, 10, 14, 9, 12, 12, + 9, 7, 4, 12, 10, 11, 10, 6, 7, + 9, 7, 4, 9, 9, 11, 9, 7, 5, }, +{ 7, 9, 7, 14, 11, 12, 10, 9, 9, + 8, 5, 5, 12, 9, 10, 8, 8, 11, + 7, 5, 2, 8, 8, 9, 7, 4, 4, + 10, 11, 10, 12, 14, 11, 12, 13, 12, + 9, 10, 8, 13, 8, 13, 10, 11, 11, + 9, 9, 8, 14, 10, 10, 11, 12, 11, + 10, 11, 9, 14, 10, 14, 9, 12, 14, + 6, 6, 3, 11, 8, 9, 8, 3, 6, + 9, 7, 4, 10, 8, 11, 10, 6, 5, }, +{ 6, 8, 7, 13, 12, 12, 10, 9, 9, + 9, 7, 8, 13, 11, 11, 9, 11, 12, + 7, 6, 1, 9, 8, 10, 7, 5, 4, + 10, 12, 10, 12, 13, 13, 14, 13, 11, + 9, 11, 9, 13, 10, 14, 12, 12, 12, + 11, 12, 10, 14, 13, 12, 13, 14, 12, + 8, 9, 7, 13, 10, 13, 8, 11, 12, + 8, 6, 3, 12, 9, 10, 9, 4, 6, + 10, 8, 5, 10, 10, 12, 11, 8, 6, }, +{ 7, 10, 7, 12, 9, 12, 10, 10, 12, + 9, 7, 7, 12, 9, 11, 6, 10, 11, + 6, 6, 1, 9, 8, 9, 7, 4, 5, + 11, 12, 9, 12, 10, 14, 13, 13, 11, + 10, 12, 8, 13, 8, 14, 10, 10, 11, + 11, 11, 10, 13, 14, 10, 14, 13, 11, + 11, 10, 7, 13, 8, 12, 7, 10, 12, + 7, 10, 4, 12, 6, 10, 8, 5, 8, + 10, 7, 4, 9, 7, 10, 9, 6, 5, }, +{ 7, 9, 7, 13, 12, 13, 10, 10, 8, + 8, 5, 6, 11, 10, 10, 8, 10, 10, + 7, 5, 2, 9, 8, 9, 7, 5, 3, + 8, 9, 7, 9, 11, 11, 13, 11, 9, + 8, 10, 7, 12, 9, 14, 11, 10, 10, + 9, 10, 9, 12, 12, 12, 13, 14, 12, + 10, 10, 9, 13, 11, 13, 9, 13, 12, + 8, 7, 4, 12, 10, 10, 10, 6, 6, + 7, 6, 3, 9, 8, 10, 9, 6, 3, }, +{ 7, 10, 7, 13, 13, 13, 11, 11, 9, + 8, 6, 6, 13, 11, 11, 9, 10, 11, + 7, 6, 1, 9, 8, 10, 8, 5, 4, + 8, 9, 8, 9, 12, 12, 12, 12, 8, + 10, 13, 9, 14, 11, 14, 14, 13, 12, + 9, 10, 9, 13, 12, 11, 13, 14, 11, + 9, 11, 8, 13, 11, 13, 10, 13, 13, + 9, 8, 5, 12, 10, 11, 11, 6, 7, + 8, 7, 3, 8, 9, 11, 10, 7, 4, }, +{ 8, 9, 7, 11, 11, 12, 11, 14, 9, + 8, 6, 6, 11, 13, 10, 9, 11, 9, + 7, 5, 1, 7, 9, 9, 7, 5, 3, + 13, 11, 9, 10, 12, 11, 12, 12, 9, + 10, 11, 9, 13, 9, 12, 12, 12, 10, + 12, 11, 10, 13, 14, 12, 14, 14, 11, + 11, 8, 8, 13, 11, 12, 9, 13, 11, + 9, 10, 5, 11, 8, 11, 9, 6, 7, + 7, 8, 4, 6, 8, 10, 8, 8, 5, }, +{ 8, 10, 8, 13, 13, 13, 12, 11, 10, + 5, 1, 3, 10, 7, 8, 6, 8, 9, + 8, 7, 4, 9, 10, 11, 8, 7, 6, + 8, 9, 7, 9, 12, 11, 12, 10, 8, + 9, 10, 8, 13, 9, 9, 12, 11, 11, + 7, 7, 6, 12, 9, 8, 10, 12, 8, + 6, 7, 4, 12, 8, 13, 6, 9, 10, + 13, 13, 9, 15, 14, 14, 15, 9, 11, + 13, 11, 9, 13, 13, 15, 15, 12, 10, }, +{ 10, 8, 9, 11, 12, 10, 8, 13, 13, + 9, 2, 5, 7, 5, 4, 3, 8, 9, + 11, 5, 5, 9, 8, 8, 6, 8, 8, + 12, 7, 8, 10, 10, 9, 8, 12, 10, + 9, 10, 9, 12, 7, 11, 7, 12, 12, + 9, 5, 8, 9, 9, 6, 6, 11, 10, + 6, 4, 7, 9, 5, 9, 3, 9, 10, + 13, 11, 9, 13, 10, 13, 10, 9, 13, + 14, 11, 10, 12, 12, 13, 11, 14, 11, }, +{ 11, 7, 8, 10, 12, 9, 9, 14, 10, + 9, 4, 7, 8, 10, 7, 7, 11, 10, + 8, 2, 2, 6, 8, 5, 5, 5, 6, + 15, 9, 10, 10, 12, 10, 11, 14, 12, + 9, 8, 9, 12, 9, 11, 8, 12, 11, + 14, 10, 11, 12, 13, 10, 12, 15, 12, + 9, 7, 8, 12, 9, 12, 7, 11, 13, + 9, 6, 5, 11, 10, 11, 7, 6, 9, + 11, 4, 5, 7, 8, 8, 8, 7, 7, }, +}; +//@} + +/** + * Codes used for determining block type + */ +//@{ +#define AIC_MODE1_NUM 90 +#define AIC_MODE1_SIZE 9 +#define AIC_MODE1_BITS 7 + +static const uint8_t aic_mode1_vlc_codes[AIC_MODE1_NUM][AIC_MODE1_SIZE] = { + { 0x01, 0x01, 0x01, 0x11, 0x00, 0x09, 0x03, 0x10, 0x05,}, + { 0x09, 0x01, 0x01, 0x05, 0x11, 0x00, 0x03, 0x21, 0x20,}, + { 0x01, 0x01, 0x01, 0x11, 0x09, 0x10, 0x05, 0x00, 0x03,}, + { 0x01, 0x01, 0x00, 0x03, 0x21, 0x05, 0x09, 0x20, 0x11,}, + { 0x01, 0x09, 0x00, 0x29, 0x08, 0x15, 0x03, 0x0B, 0x28,}, + { 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02,}, + { 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x01, 0x09, 0x08,}, + { 0x01, 0x01, 0x01, 0x09, 0x01, 0x08, 0x00, 0x03, 0x05,}, + { 0x01, 0x01, 0x01, 0x00, 0x05, 0x11, 0x09, 0x10, 0x03,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x01, 0x01, 0x05, 0x01, 0x00, 0x03, 0x09, 0x08,}, + { 0x09, 0x01, 0x01, 0x05, 0x11, 0x00, 0x03, 0x21, 0x20,}, + { 0x01, 0x01, 0x01, 0x0D, 0x05, 0x04, 0x00, 0x07, 0x0C,}, + { 0x01, 0x01, 0x00, 0x05, 0x11, 0x03, 0x09, 0x21, 0x20,}, + { 0x05, 0x01, 0x01, 0x11, 0x00, 0x09, 0x03, 0x21, 0x20,}, + { 0x09, 0x01, 0x01, 0x00, 0x05, 0x01, 0x03, 0x11, 0x10,}, + { 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x02,}, + { 0x01, 0x01, 0x01, 0x09, 0x00, 0x05, 0x01, 0x03, 0x08,}, + { 0x01, 0x01, 0x01, 0x09, 0x11, 0x05, 0x00, 0x10, 0x03,}, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x00, 0x01, 0x09, 0x08, 0x15, 0x14, 0x0B, 0x03,}, + { 0x0D, 0x01, 0x01, 0x05, 0x0C, 0x04, 0x01, 0x00, 0x07,}, + { 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x03, 0x01, 0x01,}, + { 0x05, 0x01, 0x01, 0x04, 0x19, 0x07, 0x18, 0x0D, 0x00,}, + { 0x11, 0x09, 0x01, 0x21, 0x05, 0x20, 0x01, 0x00, 0x03,}, + { 0x41, 0x01, 0x00, 0x05, 0x40, 0x03, 0x09, 0x21, 0x11,}, + { 0x29, 0x01, 0x00, 0x28, 0x09, 0x15, 0x03, 0x08, 0x0B,}, + { 0x01, 0x00, 0x01, 0x11, 0x09, 0x10, 0x05, 0x01, 0x03,}, + { 0x05, 0x01, 0x01, 0x04, 0x0D, 0x0C, 0x07, 0x00, 0x01,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x00, 0x03, 0x05, 0x11, 0x10, 0x25, 0x24, 0x13,}, + { 0x21, 0x01, 0x01, 0x00, 0x11, 0x03, 0x05, 0x20, 0x09,}, + { 0x01, 0x01, 0x01, 0x00, 0x09, 0x11, 0x10, 0x05, 0x03,}, + { 0x21, 0x05, 0x01, 0x01, 0x09, 0x00, 0x11, 0x20, 0x03,}, + { 0x05, 0x01, 0x00, 0x04, 0x01, 0x19, 0x07, 0x18, 0x0D,}, + { 0x11, 0x01, 0x00, 0x01, 0x09, 0x01, 0x03, 0x10, 0x05,}, + { 0x1D, 0x01, 0x05, 0x0D, 0x0C, 0x04, 0x00, 0x1C, 0x0F,}, + { 0x05, 0x19, 0x01, 0x04, 0x00, 0x18, 0x1B, 0x1A, 0x07,}, + { 0x09, 0x01, 0x00, 0x01, 0x05, 0x03, 0x11, 0x10, 0x01,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x00, 0x03, 0x41, 0x05, 0x40, 0x09, 0x11, 0x21,}, + { 0x05, 0x01, 0x01, 0x19, 0x04, 0x07, 0x00, 0x18, 0x0D,}, + { 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x03,}, + { 0x01, 0x05, 0x00, 0x0D, 0x01, 0x04, 0x07, 0x19, 0x18,}, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, + { 0x31, 0x01, 0x05, 0x19, 0x04, 0x07, 0x00, 0x30, 0x0D,}, + { 0x01, 0x00, 0x03, 0x11, 0x01, 0x05, 0x01, 0x09, 0x10,}, + { 0x01, 0x05, 0x01, 0x11, 0x01, 0x10, 0x00, 0x03, 0x09,}, + { 0x01, 0x09, 0x00, 0x29, 0x03, 0x08, 0x28, 0x15, 0x0B,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x01, 0x00, 0x09, 0x15, 0x03, 0x08, 0x14, 0x0B,}, + { 0x11, 0x01, 0x01, 0x00, 0x09, 0x01, 0x03, 0x10, 0x05,}, + { 0x01, 0x00, 0x03, 0x25, 0x11, 0x05, 0x10, 0x24, 0x13,}, + { 0x11, 0x01, 0x00, 0x01, 0x09, 0x01, 0x05, 0x10, 0x03,}, + { 0x05, 0x01, 0x00, 0x0D, 0x0C, 0x04, 0x0F, 0x1D, 0x1C,}, + { 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02,}, + { 0x21, 0x01, 0x05, 0x09, 0x11, 0x00, 0x03, 0x41, 0x40,}, + { 0x05, 0x01, 0x00, 0x1D, 0x1C, 0x0D, 0x0C, 0x0F, 0x04,}, + { 0x05, 0x01, 0x00, 0x0D, 0x31, 0x04, 0x19, 0x30, 0x07,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x01, 0x00, 0x21, 0x05, 0x11, 0x03, 0x09, 0x20,}, + { 0x01, 0x01, 0x00, 0x11, 0x03, 0x05, 0x01, 0x09, 0x10,}, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, + { 0x05, 0x01, 0x04, 0x19, 0x07, 0x0D, 0x00, 0x31, 0x30,}, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, + { 0x05, 0x01, 0x01, 0x11, 0x09, 0x00, 0x03, 0x21, 0x20,}, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02,}, + { 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x01, 0x01, 0x02,}, + { 0x09, 0x01, 0x00, 0x29, 0x08, 0x15, 0x03, 0x28, 0x0B,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x00, 0x01, 0x03,}, + { 0x09, 0x01, 0x00, 0x29, 0x28, 0x15, 0x08, 0x03, 0x0B,}, + { 0x01, 0x00, 0x01, 0x11, 0x05, 0x10, 0x09, 0x01, 0x03,}, + { 0x05, 0x04, 0x01, 0x1D, 0x0D, 0x0C, 0x1C, 0x00, 0x0F,}, + { 0x09, 0x11, 0x01, 0x41, 0x00, 0x40, 0x05, 0x03, 0x21,}, + { 0x0D, 0x05, 0x01, 0x1D, 0x1C, 0x0C, 0x04, 0x00, 0x0F,}, + { 0x41, 0x09, 0x01, 0x40, 0x00, 0x11, 0x05, 0x03, 0x21,}, + { 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x00, 0x01, 0x03,}, + { 0x05, 0x04, 0x01, 0x0D, 0x01, 0x0C, 0x07, 0x01, 0x00,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + + { 0x05, 0x04, 0x01, 0x07, 0x19, 0x31, 0x30, 0x0D, 0x00,}, + { 0x21, 0x01, 0x01, 0x00, 0x11, 0x09, 0x20, 0x05, 0x03,}, + { 0x05, 0x01, 0x01, 0x04, 0x07, 0x0D, 0x0C, 0x00, 0x01,}, + { 0x21, 0x09, 0x01, 0x00, 0x20, 0x05, 0x23, 0x22, 0x03,}, + { 0x31, 0x0D, 0x01, 0x19, 0x05, 0x30, 0x04, 0x07, 0x00,}, + { 0x31, 0x05, 0x01, 0x04, 0x19, 0x00, 0x0D, 0x30, 0x07,}, + { 0x31, 0x01, 0x00, 0x0D, 0x05, 0x19, 0x04, 0x30, 0x07,}, + { 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x01,}, + { 0x01, 0x00, 0x01, 0x01, 0x05, 0x09, 0x08, 0x03, 0x01,}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, +}; + +static const uint8_t aic_mode1_vlc_bits[AIC_MODE1_NUM][AIC_MODE1_SIZE] = { + { 1, 4, 2, 7, 4, 6, 4, 7, 5,}, + { 5, 1, 3, 4, 6, 3, 3, 7, 7,}, + { 1, 4, 2, 7, 6, 7, 5, 4, 4,}, + { 1, 3, 3, 3, 7, 4, 5, 7, 6,}, + { 2, 4, 2, 6, 4, 5, 2, 4, 6,}, + { 7, 2, 3, 4, 7, 1, 5, 7, 7,}, + { 5, 1, 3, 6, 5, 5, 2, 7, 7,}, + { 2, 5, 1, 7, 3, 7, 5, 5, 6,}, + { 2, 4, 1, 4, 5, 7, 6, 7, 4,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 2, 1, 3, 6, 5, 5, 5, 7, 7,}, + { 5, 1, 3, 4, 6, 3, 3, 7, 7,}, + { 4, 1, 2, 6, 5, 5, 4, 5, 6,}, + { 3, 1, 3, 4, 6, 3, 5, 7, 7,}, + { 4, 1, 3, 6, 3, 5, 3, 7, 7,}, + { 6, 1, 4, 4, 5, 2, 4, 7, 7,}, + { 7, 1, 5, 7, 4, 3, 2, 7, 7,}, + { 5, 3, 2, 7, 5, 6, 1, 5, 7,}, + { 4, 1, 2, 6, 7, 5, 4, 7, 4,}, + { 1, 0, 1, 0, 0, 0, 0, 0, 0,}, + + { 3, 3, 1, 5, 5, 6, 6, 5, 3,}, + { 6, 2, 1, 5, 6, 5, 4, 4, 5,}, + { 6, 4, 1, 7, 6, 7, 6, 3, 2,}, + { 4, 3, 1, 4, 6, 4, 6, 5, 3,}, + { 6, 5, 1, 7, 4, 7, 3, 3, 3,}, + { 7, 2, 2, 3, 7, 2, 4, 6, 5,}, + { 6, 2, 2, 6, 4, 5, 2, 4, 4,}, + { 4, 4, 1, 7, 6, 7, 5, 2, 4,}, + { 5, 4, 1, 5, 6, 6, 5, 4, 2,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 2, 2, 2, 3, 5, 5, 6, 6, 5,}, + { 7, 1, 3, 3, 6, 3, 4, 7, 5,}, + { 2, 4, 1, 4, 6, 7, 7, 5, 4,}, + { 7, 4, 3, 1, 5, 3, 6, 7, 3,}, + { 4, 3, 3, 4, 1, 6, 4, 6, 5,}, + { 7, 4, 4, 2, 6, 1, 4, 7, 5,}, + { 5, 2, 3, 4, 4, 3, 2, 5, 4,}, + { 3, 5, 2, 3, 2, 5, 5, 5, 3,}, + { 6, 4, 4, 2, 5, 4, 7, 7, 1,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 2, 2, 2, 7, 3, 7, 4, 5, 6,}, + { 4, 1, 3, 6, 4, 4, 3, 6, 5,}, + { 2, 4, 1, 7, 3, 7, 6, 6, 6,}, + { 3, 4, 3, 5, 1, 4, 4, 6, 6,}, + { 4, 5, 2, 7, 1, 7, 3, 7, 7,}, + { 6, 2, 3, 5, 3, 3, 2, 6, 4,}, + { 4, 4, 4, 7, 2, 5, 1, 6, 7,}, + { 4, 5, 2, 7, 1, 7, 4, 4, 6,}, + { 2, 4, 2, 6, 2, 4, 6, 5, 4,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 1, 3, 3, 5, 6, 3, 5, 6, 5,}, + { 7, 1, 4, 4, 6, 2, 4, 7, 5,}, + { 2, 2, 2, 6, 5, 3, 5, 6, 5,}, + { 7, 4, 4, 2, 6, 1, 5, 7, 4,}, + { 3, 2, 2, 4, 4, 3, 4, 5, 5,}, + { 7, 2, 5, 3, 7, 1, 4, 7, 7,}, + { 6, 2, 3, 4, 5, 2, 2, 7, 7,}, + { 3, 2, 2, 5, 5, 4, 4, 4, 3,}, + { 3, 2, 2, 4, 6, 3, 5, 6, 3,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 1, 3, 3, 7, 4, 6, 3, 5, 7,}, + { 4, 1, 4, 7, 4, 5, 2, 6, 7,}, + { 2, 4, 1, 7, 5, 7, 3, 7, 7,}, + { 3, 2, 3, 5, 3, 4, 2, 6, 6,}, + { 3, 5, 4, 7, 2, 7, 1, 7, 7,}, + { 4, 1, 3, 6, 5, 3, 3, 7, 7,}, + { 4, 2, 5, 7, 3, 7, 1, 7, 7,}, + { 7, 4, 1, 7, 3, 7, 2, 5, 7,}, + { 4, 2, 2, 6, 4, 5, 2, 6, 4,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 3, 4, 1, 7, 6, 7, 6, 2, 6,}, + { 4, 2, 2, 6, 6, 5, 4, 2, 4,}, + { 4, 4, 1, 7, 5, 7, 6, 2, 4,}, + { 3, 3, 2, 5, 4, 4, 5, 2, 4,}, + { 4, 5, 2, 7, 2, 7, 3, 2, 6,}, + { 4, 3, 2, 5, 5, 4, 3, 2, 4,}, + { 7, 4, 2, 7, 2, 5, 3, 2, 6,}, + { 4, 6, 2, 7, 3, 7, 6, 1, 6,}, + { 5, 5, 1, 6, 4, 6, 5, 2, 4,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + + { 3, 3, 2, 3, 5, 6, 6, 4, 2,}, + { 7, 1, 3, 3, 6, 5, 7, 4, 3,}, + { 5, 4, 1, 5, 5, 6, 6, 4, 2,}, + { 6, 4, 2, 2, 6, 3, 6, 6, 2,}, + { 6, 4, 2, 5, 3, 6, 3, 3, 2,}, + { 6, 3, 2, 3, 5, 2, 4, 6, 3,}, + { 6, 2, 2, 4, 3, 5, 3, 6, 3,}, + { 7, 5, 1, 7, 4, 7, 7, 3, 2,}, + { 5, 5, 2, 3, 6, 7, 7, 5, 1,}, + { 0, 0, 0, 0, 0, 0, 0, 0, 0,}, +}; + +//@} + +#define PBTYPE_ESCAPE 0xFF + +/** tables used for P-frame macroblock type decoding */ +//@{ +#define NUM_PTYPE_VLCS 7 +#define PTYPE_VLC_SIZE 8 +#define PTYPE_VLC_BITS 7 + +static const uint8_t ptype_vlc_codes[NUM_PTYPE_VLCS][PTYPE_VLC_SIZE] = { + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x0D, 0x05, 0x01, 0x04, 0x01, 0x00, 0x07, 0x0C }, + { 0x09, 0x11, 0x01, 0x00, 0x05, 0x03, 0x21, 0x20 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 } +}; + +static const uint8_t ptype_vlc_bits[NUM_PTYPE_VLCS][PTYPE_VLC_SIZE] = { + { 1, 2, 3, 6, 5, 4, 7, 7 }, + { 3, 1, 2, 7, 6, 5, 4, 7 }, + { 5, 4, 1, 4, 3, 3, 4, 5 }, + { 4, 5, 2, 2, 3, 2, 6, 6 }, + { 5, 6, 1, 4, 2, 3, 7, 7 }, + { 5, 6, 1, 4, 3, 2, 7, 7 }, + { 6, 3, 2, 7, 5, 4, 1, 7 } +}; + +static const uint8_t ptype_vlc_syms[PTYPE_VLC_SIZE] = { + 0, 1, 2, 3, 8, 9, 11, PBTYPE_ESCAPE +}; + +/** reverse of ptype_vlc_syms */ +static const uint8_t block_num_to_ptype_vlc_num[12] = { + 0, 1, 2, 3, 0, 0, 2, 0, 4, 5, 0, 6 +}; +//@} + +/** tables used for P-frame macroblock type decoding */ +//@{ +#define NUM_BTYPE_VLCS 6 +#define BTYPE_VLC_SIZE 7 +#define BTYPE_VLC_BITS 6 + +static const uint8_t btype_vlc_codes[NUM_BTYPE_VLCS][BTYPE_VLC_SIZE] = { + { 0x01, 0x05, 0x00, 0x03, 0x11, 0x09, 0x10 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x09, 0x01, 0x00, 0x01, 0x05, 0x03, 0x08 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 } +}; + +static const uint8_t btype_vlc_bits[NUM_BTYPE_VLCS][PTYPE_VLC_SIZE] = { + { 2, 3, 2, 2, 5, 4, 5 }, + { 4, 1, 3, 2, 6, 5, 6 }, + { 6, 4, 1, 2, 5, 3, 6 }, + { 5, 3, 3, 1, 4, 3, 5 }, + { 6, 5, 3, 2, 4, 1, 6 }, + { 6, 5, 3, 1, 4, 2, 6 } +}; + +static const uint8_t btype_vlc_syms[BTYPE_VLC_SIZE] = { + 0, 1, 4, 5, 10, 7, PBTYPE_ESCAPE +}; + +/** reverse of btype_vlc_syms */ +static const uint8_t block_num_to_btype_vlc_num[12] = { + 0, 1, 0, 0, 2, 3, 0, 5, 0, 0, 4, 0 +}; +//@} +#endif /* AVCODEC_RV40VLC2_H */ diff --git a/ffmpeg/libavcodec/s302m.c b/ffmpeg/libavcodec/s302m.c new file mode 100644 index 0000000..5f73148 --- /dev/null +++ b/ffmpeg/libavcodec/s302m.c @@ -0,0 +1,161 @@ +/* + * SMPTE 302M decoder + * Copyright (c) 2008 Laurent Aimar + * Copyright (c) 2009 Baptiste Coudurier + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "avcodec.h" +#include "internal.h" +#include "mathops.h" + +#define AES3_HEADER_LEN 4 + +static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, + int buf_size) +{ + uint32_t h; + int frame_size, channels, bits; + + if (buf_size <= AES3_HEADER_LEN) { + av_log(avctx, AV_LOG_ERROR, "frame is too short\n"); + return AVERROR_INVALIDDATA; + } + + /* + * AES3 header : + * size: 16 + * number channels 2 + * channel_id 8 + * bits per samples 2 + * alignments 4 + */ + + h = AV_RB32(buf); + frame_size = (h >> 16) & 0xffff; + channels = ((h >> 14) & 0x0003) * 2 + 2; + bits = ((h >> 4) & 0x0003) * 4 + 16; + + if (AES3_HEADER_LEN + frame_size != buf_size || bits > 24) { + av_log(avctx, AV_LOG_ERROR, "frame has invalid header\n"); + return AVERROR_INVALIDDATA; + } + + /* Set output properties */ + avctx->bits_per_coded_sample = bits; + if (bits > 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + else + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + avctx->channels = channels; + switch(channels) { + case 2: + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + break; + case 4: + avctx->channel_layout = AV_CH_LAYOUT_QUAD; + break; + case 6: + avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; + break; + case 8: + avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK | AV_CH_LAYOUT_STEREO_DOWNMIX; + } + avctx->sample_rate = 48000; + avctx->bit_rate = 48000 * avctx->channels * (avctx->bits_per_coded_sample + 4) + + 32 * (48000 / (buf_size * 8 / + (avctx->channels * + (avctx->bits_per_coded_sample + 4)))); + + return frame_size; +} + +static int s302m_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int block_size, ret; + + int frame_size = s302m_parse_frame_header(avctx, buf, buf_size); + if (frame_size < 0) + return frame_size; + + buf_size -= AES3_HEADER_LEN; + buf += AES3_HEADER_LEN; + + /* get output buffer */ + block_size = (avctx->bits_per_coded_sample + 4) / 4; + frame->nb_samples = 2 * (buf_size / block_size) / avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + buf_size = (frame->nb_samples * avctx->channels / 2) * block_size; + + if (avctx->bits_per_coded_sample == 24) { + uint32_t *o = (uint32_t *)frame->data[0]; + for (; buf_size > 6; buf_size -= 7) { + *o++ = (ff_reverse[buf[2]] << 24) | + (ff_reverse[buf[1]] << 16) | + (ff_reverse[buf[0]] << 8); + *o++ = (ff_reverse[buf[6] & 0xf0] << 28) | + (ff_reverse[buf[5]] << 20) | + (ff_reverse[buf[4]] << 12) | + (ff_reverse[buf[3] & 0x0f] << 4); + buf += 7; + } + } else if (avctx->bits_per_coded_sample == 20) { + uint32_t *o = (uint32_t *)frame->data[0]; + for (; buf_size > 5; buf_size -= 6) { + *o++ = (ff_reverse[buf[2] & 0xf0] << 28) | + (ff_reverse[buf[1]] << 20) | + (ff_reverse[buf[0]] << 12); + *o++ = (ff_reverse[buf[5] & 0xf0] << 28) | + (ff_reverse[buf[4]] << 20) | + (ff_reverse[buf[3]] << 12); + buf += 6; + } + } else { + uint16_t *o = (uint16_t *)frame->data[0]; + for (; buf_size > 4; buf_size -= 5) { + *o++ = (ff_reverse[buf[1]] << 8) | + ff_reverse[buf[0]]; + *o++ = (ff_reverse[buf[4] & 0xf0] << 12) | + (ff_reverse[buf[3]] << 4) | + (ff_reverse[buf[2]] >> 4); + buf += 5; + } + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + +AVCodec ff_s302m_decoder = { + .name = "s302m", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_S302M, + .decode = s302m_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), +}; diff --git a/ffmpeg/libavcodec/s3tc.c b/ffmpeg/libavcodec/s3tc.c new file mode 100644 index 0000000..4e791c8 --- /dev/null +++ b/ffmpeg/libavcodec/s3tc.c @@ -0,0 +1,97 @@ +/* + * S3 Texture Compression (S3TC) decoding functions + * Copyright (c) 2007 by Ivo van Poorten + * + * see also: http://wiki.multimedia.cx/index.php?title=S3TC + * + * 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 "libavcodec/bytestream.h" +#include "avcodec.h" +#include "s3tc.h" + +static inline void dxt1_decode_pixels(GetByteContext *gb, uint32_t *d, + unsigned int qstride, unsigned int flag, + uint64_t alpha) { + unsigned int x, y, c0, c1, a = (!flag * 255u) << 24; + unsigned int rb0, rb1, rb2, rb3, g0, g1, g2, g3; + uint32_t colors[4], pixels; + + c0 = bytestream2_get_le16(gb); + c1 = bytestream2_get_le16(gb); + + rb0 = (c0<<3 | c0<<8) & 0xf800f8; + rb1 = (c1<<3 | c1<<8) & 0xf800f8; + rb0 += (rb0>>5) & 0x070007; + rb1 += (rb1>>5) & 0x070007; + g0 = (c0 <<5) & 0x00fc00; + g1 = (c1 <<5) & 0x00fc00; + g0 += (g0 >>6) & 0x000300; + g1 += (g1 >>6) & 0x000300; + + colors[0] = rb0 + g0 + a; + colors[1] = rb1 + g1 + a; + + if (c0 > c1 || flag) { + rb2 = (((2*rb0+rb1) * 21) >> 6) & 0xff00ff; + rb3 = (((2*rb1+rb0) * 21) >> 6) & 0xff00ff; + g2 = (((2*g0 +g1 ) * 21) >> 6) & 0x00ff00; + g3 = (((2*g1 +g0 ) * 21) >> 6) & 0x00ff00; + colors[3] = rb3 + g3 + a; + } else { + rb2 = ((rb0+rb1) >> 1) & 0xff00ff; + g2 = ((g0 +g1 ) >> 1) & 0x00ff00; + colors[3] = 0; + } + + colors[2] = rb2 + g2 + a; + + pixels = bytestream2_get_le32(gb); + for (y=0; y<4; y++) { + for (x=0; x<4; x++) { + a = (alpha & 0x0f) << 28; + a += a >> 4; + d[x] = a + colors[pixels&3]; + pixels >>= 2; + alpha >>= 4; + } + d += qstride; + } +} + +void ff_decode_dxt1(GetByteContext *gb, uint8_t *dst, + const unsigned int w, const unsigned int h, + const unsigned int stride) { + unsigned int bx, by, qstride = stride/4; + uint32_t *d = (uint32_t *) dst; + + for (by=0; by < h/4; by++, d += stride-w) + for (bx = 0; bx < w / 4; bx++, d += 4) + dxt1_decode_pixels(gb, d, qstride, 0, 0LL); +} + +void ff_decode_dxt3(GetByteContext *gb, uint8_t *dst, + const unsigned int w, const unsigned int h, + const unsigned int stride) { + unsigned int bx, by, qstride = stride/4; + uint32_t *d = (uint32_t *) dst; + + for (by=0; by < h/4; by++, d += stride-w) + for (bx = 0; bx < w / 4; bx++, d += 4) + dxt1_decode_pixels(gb, d, qstride, 1, bytestream2_get_le64(gb)); +} diff --git a/ffmpeg/libavcodec/s3tc.h b/ffmpeg/libavcodec/s3tc.h new file mode 100644 index 0000000..2d77b3a --- /dev/null +++ b/ffmpeg/libavcodec/s3tc.h @@ -0,0 +1,55 @@ +/* + * S3 Texture Compression (S3TC) decoding functions + * Copyright (c) 2007 by Ivo van Poorten + * + * 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 + */ + +#ifndef AVCODEC_S3TC_H +#define AVCODEC_S3TC_H + +#include + +#include "bytestream.h" + +#define FF_S3TC_DXT1 0x31545844 +#define FF_S3TC_DXT3 0x33545844 + +/** + * Decode DXT1 encoded data to RGB32 + * @param gb GetByteContext + * @param dst destination buffer + * @param w width of output image + * @param h height of output image + * @param stride line size of output image + */ +void ff_decode_dxt1(GetByteContext *gb, uint8_t *dst, + const unsigned int w, const unsigned int h, + const unsigned int stride); +/** + * Decode DXT3 encoded data to RGB32 + * @param gb GetByteContext + * @param dst destination buffer + * @param w width of output image + * @param h height of output image + * @param stride line size of output image + */ +void ff_decode_dxt3(GetByteContext *gb, uint8_t *dst, + const unsigned int w, const unsigned int h, + const unsigned int stride); + +#endif /* AVCODEC_S3TC_H */ diff --git a/ffmpeg/libavcodec/samidec.c b/ffmpeg/libavcodec/samidec.c new file mode 100644 index 0000000..39ac608 --- /dev/null +++ b/ffmpeg/libavcodec/samidec.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2012 Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * SAMI subtitle decoder + * @see http://msdn.microsoft.com/en-us/library/ms971327.aspx + */ + +#include "ass.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" + +typedef struct { + AVBPrint source; + AVBPrint content; + AVBPrint full; +} SAMIContext; + +static int sami_paragraph_to_ass(AVCodecContext *avctx, const char *src) +{ + SAMIContext *sami = avctx->priv_data; + int ret = 0; + char *tag = NULL; + char *dupsrc = av_strdup(src); + char *p = dupsrc; + + av_bprint_clear(&sami->content); + for (;;) { + char *saveptr = NULL; + int prev_chr_is_space = 0; + AVBPrint *dst = &sami->content; + + /* parse & extract paragraph tag */ + p = av_stristr(p, " + p++; + continue; + } + if (dst->len) // add a separator with the previous paragraph if there was one + av_bprintf(dst, "\\N"); + tag = av_strtok(p, ">", &saveptr); + if (!tag || !saveptr) + break; + p = saveptr; + + /* check if the current paragraph is the "source" (speaker name) */ + if (av_stristr(tag, "ID=Source") || av_stristr(tag, "ID=\"Source\"")) { + dst = &sami->source; + av_bprint_clear(dst); + } + + /* if empty event -> skip subtitle */ + while (av_isspace(*p)) + p++; + if (!strncmp(p, " ", 6)) { + ret = -1; + goto end; + } + + /* extract the text, stripping most of the tags */ + while (*p) { + if (*p == '<') { + if (!av_strncasecmp(p, "' || av_isspace(p[2]))) + break; + if (!av_strncasecmp(p, "') + p++; + } + if (!av_isspace(*p)) + av_bprint_chars(dst, *p, 1); + else if (!prev_chr_is_space) + av_bprint_chars(dst, ' ', 1); + prev_chr_is_space = av_isspace(*p); + p++; + } + } + + av_bprint_clear(&sami->full); + if (sami->source.len) + av_bprintf(&sami->full, "{\\i1}%s{\\i0}\\N", sami->source.str); + av_bprintf(&sami->full, "%s\r\n", sami->content.str); + +end: + av_free(dupsrc); + return ret; +} + +static int sami_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + SAMIContext *sami = avctx->priv_data; + + if (ptr && avpkt->size > 0 && !sami_paragraph_to_ass(avctx, ptr)) { + int ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100}); + int ts_duration = avpkt->duration != -1 ? + av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1; + ff_ass_add_rect(sub, sami->full.str, ts_start, ts_duration, 0); + } + *got_sub_ptr = sub->num_rects > 0; + return avpkt->size; +} + +static av_cold int sami_init(AVCodecContext *avctx) +{ + SAMIContext *sami = avctx->priv_data; + av_bprint_init(&sami->source, 0, 2048); + av_bprint_init(&sami->content, 0, 2048); + av_bprint_init(&sami->full, 0, 2048); + return ff_ass_subtitle_header_default(avctx); +} + +static av_cold int sami_close(AVCodecContext *avctx) +{ + SAMIContext *sami = avctx->priv_data; + av_bprint_finalize(&sami->source, NULL); + av_bprint_finalize(&sami->content, NULL); + av_bprint_finalize(&sami->full, NULL); + return 0; +} + +AVCodec ff_sami_decoder = { + .name = "sami", + .long_name = NULL_IF_CONFIG_SMALL("SAMI subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SAMI, + .priv_data_size = sizeof(SAMIContext), + .init = sami_init, + .close = sami_close, + .decode = sami_decode_frame, +}; diff --git a/ffmpeg/libavcodec/sanm.c b/ffmpeg/libavcodec/sanm.c new file mode 100644 index 0000000..f217ef3 --- /dev/null +++ b/ffmpeg/libavcodec/sanm.c @@ -0,0 +1,1300 @@ +/* + * LucasArts Smush video decoder + * Copyright (c) 2006 Cyril Zorin + * Copyright (c) 2011 Konstantin Shishkov + * + * 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 + */ + +// #define DEBUG 1 + +#include "avcodec.h" +#include "copy_block.h" +#include "bytestream.h" +#include "internal.h" +#include "libavutil/bswap.h" +#include "libavutil/imgutils.h" +#include "sanm_data.h" +#include "libavutil/avassert.h" + +#define NGLYPHS 256 + +typedef struct { + AVCodecContext *avctx; + GetByteContext gb; + + int version, subversion; + uint32_t pal[256]; + int16_t delta_pal[768]; + + int pitch; + int width, height; + int aligned_width, aligned_height; + int prev_seq; + + AVFrame *frame; + uint16_t *frm0, *frm1, *frm2; + uint8_t *stored_frame; + uint32_t frm0_size, frm1_size, frm2_size; + uint32_t stored_frame_size; + + uint8_t *rle_buf; + unsigned int rle_buf_size; + + int rotate_code; + + long npixels, buf_size; + + uint16_t codebook[256]; + uint16_t small_codebook[4]; + + int8_t p4x4glyphs[NGLYPHS][16]; + int8_t p8x8glyphs[NGLYPHS][64]; +} SANMVideoContext; + +typedef struct { + int seq_num, codec, rotate_code, rle_output_size; + + uint16_t bg_color; + uint32_t width, height; +} SANMFrameHeader; + +enum GlyphEdge { + LEFT_EDGE, + TOP_EDGE, + RIGHT_EDGE, + BOTTOM_EDGE, + NO_EDGE +}; + +enum GlyphDir { + DIR_LEFT, + DIR_UP, + DIR_RIGHT, + DIR_DOWN, + NO_DIR +}; + +/** + * Return enum GlyphEdge of box where point (x, y) lies. + * + * @param x x point coordinate + * @param y y point coordinate + * @param edge_size box width/height. + */ +static enum GlyphEdge which_edge(int x, int y, int edge_size) +{ + const int edge_max = edge_size - 1; + + if (!y) { + return BOTTOM_EDGE; + } else if (y == edge_max) { + return TOP_EDGE; + } else if (!x) { + return LEFT_EDGE; + } else if (x == edge_max) { + return RIGHT_EDGE; + } else { + return NO_EDGE; + } +} + +static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1) +{ + if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) || + (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) || + (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) || + (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE)) { + return DIR_UP; + } else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) || + (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE)) { + return DIR_DOWN; + } else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) || + (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE)) { + return DIR_LEFT; + } else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) || + (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) || + (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) || + (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE)) { + return DIR_RIGHT; + } + + return NO_DIR; +} + +/** + * Interpolate two points. + */ +static void interp_point(int8_t *points, int x0, int y0, int x1, int y1, + int pos, int npoints) +{ + if (npoints) { + points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints; + points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints; + } else { + points[0] = x0; + points[1] = y0; + } +} + +/** + * Construct glyphs by iterating through vectors coordinates. + * + * @param pglyphs pointer to table where glyphs are stored + * @param xvec pointer to x component of vectors coordinates + * @param yvec pointer to y component of vectors coordinates + * @param side_length glyph width/height. + */ +static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec, + const int side_length) +{ + const int glyph_size = side_length * side_length; + int8_t *pglyph = pglyphs; + + int i, j; + for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) { + int x0 = xvec[i]; + int y0 = yvec[i]; + enum GlyphEdge edge0 = which_edge(x0, y0, side_length); + + for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) { + int x1 = xvec[j]; + int y1 = yvec[j]; + enum GlyphEdge edge1 = which_edge(x1, y1, side_length); + enum GlyphDir dir = which_direction(edge0, edge1); + int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0)); + int ipoint; + + for (ipoint = 0; ipoint <= npoints; ipoint++) { + int8_t point[2]; + int irow, icol; + + interp_point(point, x0, y0, x1, y1, ipoint, npoints); + + switch (dir) { + case DIR_UP: + for (irow = point[1]; irow >= 0; irow--) + pglyph[point[0] + irow * side_length] = 1; + break; + + case DIR_DOWN: + for (irow = point[1]; irow < side_length; irow++) + pglyph[point[0] + irow * side_length] = 1; + break; + + case DIR_LEFT: + for (icol = point[0]; icol >= 0; icol--) + pglyph[icol + point[1] * side_length] = 1; + break; + + case DIR_RIGHT: + for (icol = point[0]; icol < side_length; icol++) + pglyph[icol + point[1] * side_length] = 1; + break; + } + } + } + } +} + +static void init_sizes(SANMVideoContext *ctx, int width, int height) +{ + ctx->width = width; + ctx->height = height; + ctx->npixels = width * height; + + ctx->aligned_width = FFALIGN(width, 8); + ctx->aligned_height = FFALIGN(height, 8); + + ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]); + ctx->pitch = width; +} + +static void destroy_buffers(SANMVideoContext *ctx) +{ + av_freep(&ctx->frm0); + av_freep(&ctx->frm1); + av_freep(&ctx->frm2); + av_freep(&ctx->stored_frame); + av_freep(&ctx->rle_buf); + ctx->frm0_size = + ctx->frm1_size = + ctx->frm2_size = 0; +} + +static av_cold int init_buffers(SANMVideoContext *ctx) +{ + av_fast_padded_malloc(&ctx->frm0, &ctx->frm0_size, ctx->buf_size); + av_fast_padded_malloc(&ctx->frm1, &ctx->frm1_size, ctx->buf_size); + av_fast_padded_malloc(&ctx->frm2, &ctx->frm2_size, ctx->buf_size); + if (!ctx->version) + av_fast_padded_malloc(&ctx->stored_frame, &ctx->stored_frame_size, ctx->buf_size); + + if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || (!ctx->stored_frame && !ctx->version)) { + destroy_buffers(ctx); + return AVERROR(ENOMEM); + } + + return 0; +} + +static void rotate_bufs(SANMVideoContext *ctx, int rotate_code) +{ + av_dlog(ctx->avctx, "rotate %d\n", rotate_code); + if (rotate_code == 2) + FFSWAP(uint16_t*, ctx->frm1, ctx->frm2); + FFSWAP(uint16_t*, ctx->frm2, ctx->frm0); +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + SANMVideoContext *ctx = avctx->priv_data; + + ctx->avctx = avctx; + ctx->version = !avctx->extradata_size; + + avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8; + + init_sizes(ctx, avctx->width, avctx->height); + if (init_buffers(ctx)) { + av_log(avctx, AV_LOG_ERROR, "error allocating buffers\n"); + return AVERROR(ENOMEM); + } + + make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4); + make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8); + + if (!ctx->version) { + int i; + + if (avctx->extradata_size < 1026) { + av_log(avctx, AV_LOG_ERROR, "not enough extradata\n"); + return AVERROR_INVALIDDATA; + } + + ctx->subversion = AV_RL16(avctx->extradata); + for (i = 0; i < 256; i++) + ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4); + } + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + SANMVideoContext *ctx = avctx->priv_data; + + destroy_buffers(ctx); + + return 0; +} + +static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size) +{ + int opcode, color, run_len, left = out_size; + + while (left > 0) { + opcode = bytestream2_get_byte(&ctx->gb); + run_len = (opcode >> 1) + 1; + if (run_len > left || bytestream2_get_bytes_left(&ctx->gb) <= 0) + return AVERROR_INVALIDDATA; + + if (opcode & 1) { + color = bytestream2_get_byte(&ctx->gb); + memset(dst, color, run_len); + } else { + if (bytestream2_get_bytes_left(&ctx->gb) < run_len) + return AVERROR_INVALIDDATA; + bytestream2_get_bufferu(&ctx->gb, dst, run_len); + } + + dst += run_len; + left -= run_len; + } + + return 0; +} + +static int old_codec1(SANMVideoContext *ctx, int top, + int left, int width, int height) +{ + uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * ctx->pitch; + int i, j, len, flag, code, val, pos, end; + + for (i = 0; i < height; i++) { + pos = 0; + + if (bytestream2_get_bytes_left(&ctx->gb) < 2) + return AVERROR_INVALIDDATA; + + len = bytestream2_get_le16u(&ctx->gb); + end = bytestream2_tell(&ctx->gb) + len; + + while (bytestream2_tell(&ctx->gb) < end) { + if (bytestream2_get_bytes_left(&ctx->gb) < 2) + return AVERROR_INVALIDDATA; + + code = bytestream2_get_byteu(&ctx->gb); + flag = code & 1; + code = (code >> 1) + 1; + if (pos + code > width) + return AVERROR_INVALIDDATA; + if (flag) { + val = bytestream2_get_byteu(&ctx->gb); + if (val) + memset(dst + pos, val, code); + pos += code; + } else { + if (bytestream2_get_bytes_left(&ctx->gb) < code) + return AVERROR_INVALIDDATA; + for (j = 0; j < code; j++) { + val = bytestream2_get_byteu(&ctx->gb); + if (val) + dst[pos] = val; + pos++; + } + } + } + dst += ctx->pitch; + } + ctx->rotate_code = 0; + + return 0; +} + +static inline void codec37_mv(uint8_t *dst, const uint8_t *src, + int height, int stride, int x, int y) +{ + int pos, i, j; + + pos = x + y * stride; + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) { + if ((pos + i) < 0 || (pos + i) >= height * stride) + dst[i] = 0; + else + dst[i] = src[i]; + } + dst += stride; + src += stride; + pos += stride; + } +} + +static int old_codec37(SANMVideoContext *ctx, int top, + int left, int width, int height) +{ + int stride = ctx->pitch; + int i, j, k, t; + int skip_run = 0; + int compr, mvoff, seq, flags; + uint32_t decoded_size; + uint8_t *dst, *prev; + + compr = bytestream2_get_byte(&ctx->gb); + mvoff = bytestream2_get_byte(&ctx->gb); + seq = bytestream2_get_le16(&ctx->gb); + decoded_size = bytestream2_get_le32(&ctx->gb); + bytestream2_skip(&ctx->gb, 4); + flags = bytestream2_get_byte(&ctx->gb); + bytestream2_skip(&ctx->gb, 3); + + if (decoded_size > ctx->height * stride - left - top * stride) { + decoded_size = ctx->height * stride - left - top * stride; + av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n"); + } + + ctx->rotate_code = 0; + + if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) + rotate_bufs(ctx, 1); + + dst = ((uint8_t*)ctx->frm0) + left + top * stride; + prev = ((uint8_t*)ctx->frm2) + left + top * stride; + + if (mvoff > 2) { + av_log(ctx->avctx, AV_LOG_ERROR, "invalid motion base value %d\n", mvoff); + return AVERROR_INVALIDDATA; + } + av_dlog(ctx->avctx, "compression %d\n", compr); + switch (compr) { + case 0: + for (i = 0; i < height; i++) { + bytestream2_get_buffer(&ctx->gb, dst, width); + dst += stride; + } + memset(ctx->frm1, 0, ctx->height * stride); + memset(ctx->frm2, 0, ctx->height * stride); + break; + case 2: + if (rle_decode(ctx, dst, decoded_size)) + return AVERROR_INVALIDDATA; + memset(ctx->frm1, 0, ctx->frm1_size); + memset(ctx->frm2, 0, ctx->frm2_size); + break; + case 3: + case 4: + if (flags & 4) { + for (j = 0; j < height; j += 4) { + for (i = 0; i < width; i += 4) { + int code; + if (skip_run) { + skip_run--; + copy_block4(dst + i, prev + i, stride, stride, 4); + continue; + } + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + code = bytestream2_get_byteu(&ctx->gb); + switch (code) { + case 0xFF: + if (bytestream2_get_bytes_left(&ctx->gb) < 16) + return AVERROR_INVALIDDATA; + for (k = 0; k < 4; k++) + bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4); + break; + case 0xFE: + if (bytestream2_get_bytes_left(&ctx->gb) < 4) + return AVERROR_INVALIDDATA; + for (k = 0; k < 4; k++) + memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4); + break; + case 0xFD: + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + t = bytestream2_get_byteu(&ctx->gb); + for (k = 0; k < 4; k++) + memset(dst + i + k * stride, t, 4); + break; + default: + if (compr == 4 && !code) { + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + skip_run = bytestream2_get_byteu(&ctx->gb) + 1; + i -= 4; + } else { + int mx, my; + + mx = c37_mv[(mvoff * 255 + code) * 2 ]; + my = c37_mv[(mvoff * 255 + code) * 2 + 1]; + codec37_mv(dst + i, prev + i + mx + my * stride, + ctx->height, stride, i + mx, j + my); + } + } + } + dst += stride * 4; + prev += stride * 4; + } + } else { + for (j = 0; j < height; j += 4) { + for (i = 0; i < width; i += 4) { + int code; + if (skip_run) { + skip_run--; + copy_block4(dst + i, prev + i, stride, stride, 4); + continue; + } + code = bytestream2_get_byte(&ctx->gb); + if (code == 0xFF) { + if (bytestream2_get_bytes_left(&ctx->gb) < 16) + return AVERROR_INVALIDDATA; + for (k = 0; k < 4; k++) + bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4); + } else if (compr == 4 && !code) { + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + skip_run = bytestream2_get_byteu(&ctx->gb) + 1; + i -= 4; + } else { + int mx, my; + + mx = c37_mv[(mvoff * 255 + code) * 2]; + my = c37_mv[(mvoff * 255 + code) * 2 + 1]; + codec37_mv(dst + i, prev + i + mx + my * stride, + ctx->height, stride, i + mx, j + my); + } + } + dst += stride * 4; + prev += stride * 4; + } + } + break; + default: + av_log(ctx->avctx, AV_LOG_ERROR, + "subcodec 37 compression %d not implemented\n", compr); + return AVERROR_PATCHWELCOME; + } + + return 0; +} + +static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, + uint8_t *prev2, int stride, int tbl, int size) +{ + int code, k, t; + uint8_t colors[2]; + int8_t *pglyph; + + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + + code = bytestream2_get_byteu(&ctx->gb); + if (code >= 0xF8) { + switch (code) { + case 0xFF: + if (size == 2) { + if (bytestream2_get_bytes_left(&ctx->gb) < 4) + return AVERROR_INVALIDDATA; + dst[0] = bytestream2_get_byteu(&ctx->gb); + dst[1] = bytestream2_get_byteu(&ctx->gb); + dst[0+stride] = bytestream2_get_byteu(&ctx->gb); + dst[1+stride] = bytestream2_get_byteu(&ctx->gb); + } else { + size >>= 1; + if (process_block(ctx, dst, prev1, prev2, stride, tbl, size)) + return AVERROR_INVALIDDATA; + if (process_block(ctx, dst + size, prev1 + size, prev2 + size, + stride, tbl, size)) + return AVERROR_INVALIDDATA; + dst += size * stride; + prev1 += size * stride; + prev2 += size * stride; + if (process_block(ctx, dst, prev1, prev2, stride, tbl, size)) + return AVERROR_INVALIDDATA; + if (process_block(ctx, dst + size, prev1 + size, prev2 + size, + stride, tbl, size)) + return AVERROR_INVALIDDATA; + } + break; + case 0xFE: + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + + t = bytestream2_get_byteu(&ctx->gb); + for (k = 0; k < size; k++) + memset(dst + k * stride, t, size); + break; + case 0xFD: + if (bytestream2_get_bytes_left(&ctx->gb) < 3) + return AVERROR_INVALIDDATA; + + code = bytestream2_get_byteu(&ctx->gb); + pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code]; + bytestream2_get_bufferu(&ctx->gb, colors, 2); + + for (k = 0; k < size; k++) + for (t = 0; t < size; t++) + dst[t + k * stride] = colors[!*pglyph++]; + break; + case 0xFC: + for (k = 0; k < size; k++) + memcpy(dst + k * stride, prev1 + k * stride, size); + break; + default: + k = bytestream2_tell(&ctx->gb); + bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET); + t = bytestream2_get_byte(&ctx->gb); + bytestream2_seek(&ctx->gb, k, SEEK_SET); + for (k = 0; k < size; k++) + memset(dst + k * stride, t, size); + } + } else { + int mx = motion_vectors[code][0]; + int my = motion_vectors[code][1]; + int index = prev2 - (const uint8_t*)ctx->frm2; + + av_assert2(index >= 0 && index < (ctx->buf_size>>1)); + + if (index < - mx - my*stride || + (ctx->buf_size>>1) - index < mx + size + (my + size - 1)*stride) { + av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid \n"); + return AVERROR_INVALIDDATA; + } + + for (k = 0; k < size; k++) + memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size); + } + + return 0; +} + +static int old_codec47(SANMVideoContext *ctx, int top, + int left, int width, int height) +{ + int i, j, seq, compr, new_rot, tbl_pos, skip; + int stride = ctx->pitch; + uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * stride; + uint8_t *prev1 = (uint8_t*)ctx->frm1; + uint8_t *prev2 = (uint8_t*)ctx->frm2; + uint32_t decoded_size; + + tbl_pos = bytestream2_tell(&ctx->gb); + seq = bytestream2_get_le16(&ctx->gb); + compr = bytestream2_get_byte(&ctx->gb); + new_rot = bytestream2_get_byte(&ctx->gb); + skip = bytestream2_get_byte(&ctx->gb); + bytestream2_skip(&ctx->gb, 9); + decoded_size = bytestream2_get_le32(&ctx->gb); + bytestream2_skip(&ctx->gb, 8); + + if (decoded_size > ctx->height * stride - left - top * stride) { + decoded_size = ctx->height * stride - left - top * stride; + av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n"); + } + + if (skip & 1) + bytestream2_skip(&ctx->gb, 0x8080); + if (!seq) { + ctx->prev_seq = -1; + memset(prev1, 0, ctx->height * stride); + memset(prev2, 0, ctx->height * stride); + } + av_dlog(ctx->avctx, "compression %d\n", compr); + switch (compr) { + case 0: + if (bytestream2_get_bytes_left(&ctx->gb) < width * height) + return AVERROR_INVALIDDATA; + for (j = 0; j < height; j++) { + bytestream2_get_bufferu(&ctx->gb, dst, width); + dst += stride; + } + break; + case 1: + if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1)) + return AVERROR_INVALIDDATA; + for (j = 0; j < height; j += 2) { + for (i = 0; i < width; i += 2) { + dst[i] = dst[i + 1] = + dst[stride + i] = dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb); + } + dst += stride * 2; + } + break; + case 2: + if (seq == ctx->prev_seq + 1) { + for (j = 0; j < height; j += 8) { + for (i = 0; i < width; i += 8) { + if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride, + tbl_pos + 8, 8)) + return AVERROR_INVALIDDATA; + } + dst += stride * 8; + prev1 += stride * 8; + prev2 += stride * 8; + } + } + break; + case 3: + memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height); + break; + case 4: + memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height); + break; + case 5: + if (rle_decode(ctx, dst, decoded_size)) + return AVERROR_INVALIDDATA; + break; + default: + av_log(ctx->avctx, AV_LOG_ERROR, + "subcodec 47 compression %d not implemented\n", compr); + return AVERROR_PATCHWELCOME; + } + if (seq == ctx->prev_seq + 1) + ctx->rotate_code = new_rot; + else + ctx->rotate_code = 0; + ctx->prev_seq = seq; + + return 0; +} + +static int process_frame_obj(SANMVideoContext *ctx) +{ + uint16_t codec, top, left, w, h; + + codec = bytestream2_get_le16u(&ctx->gb); + left = bytestream2_get_le16u(&ctx->gb); + top = bytestream2_get_le16u(&ctx->gb); + w = bytestream2_get_le16u(&ctx->gb); + h = bytestream2_get_le16u(&ctx->gb); + + if (ctx->width < left + w || ctx->height < top + h) { + if (av_image_check_size(FFMAX(left + w, ctx->width), + FFMAX(top + h, ctx->height), 0, ctx->avctx) < 0) + return AVERROR_INVALIDDATA; + avcodec_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width), + FFMAX(top + h, ctx->height)); + init_sizes(ctx, FFMAX(left + w, ctx->width), + FFMAX(top + h, ctx->height)); + if (init_buffers(ctx)) { + av_log(ctx->avctx, AV_LOG_ERROR, "error resizing buffers\n"); + return AVERROR(ENOMEM); + } + } + bytestream2_skip(&ctx->gb, 4); + + av_dlog(ctx->avctx, "subcodec %d\n", codec); + switch (codec) { + case 1: + case 3: + return old_codec1(ctx, top, left, w, h); + break; + case 37: + return old_codec37(ctx, top, left, w, h); + break; + case 47: + return old_codec47(ctx, top, left, w, h); + break; + default: + avpriv_request_sample(ctx->avctx, "unknown subcodec %d", codec); + return AVERROR_PATCHWELCOME; + } +} + +static int decode_0(SANMVideoContext *ctx) +{ + uint16_t *frm = ctx->frm0; + int x, y; + + if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) { + av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for raw frame\n"); + return AVERROR_INVALIDDATA; + } + for (y = 0; y < ctx->height; y++) { + for (x = 0; x < ctx->width; x++) + frm[x] = bytestream2_get_le16u(&ctx->gb); + frm += ctx->pitch; + } + return 0; +} + +static int decode_nop(SANMVideoContext *ctx) +{ + avpriv_request_sample(ctx->avctx, "unknown/unsupported compression type"); + return AVERROR_PATCHWELCOME; +} + +static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, int pitch) +{ + uint8_t *dst = (uint8_t *)pdest; + uint8_t *src = (uint8_t *)psrc; + int stride = pitch * 2; + + switch (block_size) { + case 2: + copy_block4(dst, src, stride, stride, 2); + break; + case 4: + copy_block8(dst, src, stride, stride, 4); + break; + case 8: + copy_block16(dst, src, stride, stride, 8); + break; + } +} + +static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitch) +{ + int x, y; + + pitch -= block_size; + for (y = 0; y < block_size; y++, pdest += pitch) + for (x = 0; x < block_size; x++) + *pdest++ = color; +} + +static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color, + uint16_t bg_color, int block_size, int pitch) +{ + int8_t *pglyph; + uint16_t colors[2] = { fg_color, bg_color }; + int x, y; + + if (index >= NGLYPHS) { + av_log(ctx->avctx, AV_LOG_ERROR, "ignoring nonexistent glyph #%u\n", index); + return AVERROR_INVALIDDATA; + } + + pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index]; + pitch -= block_size; + + for (y = 0; y < block_size; y++, dst += pitch) + for (x = 0; x < block_size; x++) + *dst++ = colors[*pglyph++]; + return 0; +} + +static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch) +{ + uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch; + + if (block_size == 2) { + uint32_t indices; + + if (bytestream2_get_bytes_left(&ctx->gb) < 4) + return AVERROR_INVALIDDATA; + + indices = bytestream2_get_le32u(&ctx->gb); + dst[0] = ctx->codebook[indices & 0xFF]; indices >>= 8; + dst[1] = ctx->codebook[indices & 0xFF]; indices >>= 8; + dst[pitch] = ctx->codebook[indices & 0xFF]; indices >>= 8; + dst[pitch + 1] = ctx->codebook[indices & 0xFF]; + } else { + uint16_t fgcolor, bgcolor; + int glyph; + + if (bytestream2_get_bytes_left(&ctx->gb) < 3) + return AVERROR_INVALIDDATA; + + glyph = bytestream2_get_byteu(&ctx->gb); + bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)]; + fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)]; + + draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch); + } + return 0; +} + +static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch) +{ + uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch; + + if (block_size == 2) { + if (bytestream2_get_bytes_left(&ctx->gb) < 8) + return AVERROR_INVALIDDATA; + + dst[0] = bytestream2_get_le16u(&ctx->gb); + dst[1] = bytestream2_get_le16u(&ctx->gb); + dst[pitch] = bytestream2_get_le16u(&ctx->gb); + dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb); + } else { + uint16_t fgcolor, bgcolor; + int glyph; + + if (bytestream2_get_bytes_left(&ctx->gb) < 5) + return AVERROR_INVALIDDATA; + + glyph = bytestream2_get_byteu(&ctx->gb); + bgcolor = bytestream2_get_le16u(&ctx->gb); + fgcolor = bytestream2_get_le16u(&ctx->gb); + + draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch); + } + return 0; +} + +static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my, + int block_size) +{ + int start_pos = cx + mx + (cy + my) * ctx->pitch; + int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1); + + int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1); + + if (!good) { + av_log(ctx->avctx, AV_LOG_ERROR, "ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n", + cx + mx, cy + my, cx, cy, block_size); + } + + return good; +} + +static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size) +{ + int16_t mx, my, index; + int opcode; + + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + + opcode = bytestream2_get_byteu(&ctx->gb); + + av_dlog(ctx->avctx, "opcode 0x%0X cx %d cy %d blk %d\n", opcode, cx, cy, blk_size); + switch (opcode) { + default: + mx = motion_vectors[opcode][0]; + my = motion_vectors[opcode][1]; + + if (good_mvec(ctx, cx, cy, mx, my, blk_size)) { + copy_block(ctx->frm0 + cx + ctx->pitch * cy, + ctx->frm2 + cx + mx + ctx->pitch * (cy + my), + blk_size, ctx->pitch); + } + break; + case 0xF5: + if (bytestream2_get_bytes_left(&ctx->gb) < 2) + return AVERROR_INVALIDDATA; + index = bytestream2_get_le16u(&ctx->gb); + + mx = index % ctx->width; + my = index / ctx->width; + + if (good_mvec(ctx, cx, cy, mx, my, blk_size)) { + copy_block(ctx->frm0 + cx + ctx->pitch * cy, + ctx->frm2 + cx + mx + ctx->pitch * (cy + my), + blk_size, ctx->pitch); + } + break; + case 0xF6: + copy_block(ctx->frm0 + cx + ctx->pitch * cy, + ctx->frm1 + cx + ctx->pitch * cy, + blk_size, ctx->pitch); + break; + case 0xF7: + opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch); + break; + + case 0xF8: + opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch); + break; + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + fill_block(ctx->frm0 + cx + cy * ctx->pitch, + ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch); + break; + case 0xFD: + if (bytestream2_get_bytes_left(&ctx->gb) < 1) + return AVERROR_INVALIDDATA; + fill_block(ctx->frm0 + cx + cy * ctx->pitch, + ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch); + break; + case 0xFE: + if (bytestream2_get_bytes_left(&ctx->gb) < 2) + return AVERROR_INVALIDDATA; + fill_block(ctx->frm0 + cx + cy * ctx->pitch, + bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch); + break; + case 0xFF: + if (blk_size == 2) { + opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch); + } else { + blk_size >>= 1; + if (codec2subblock(ctx, cx , cy , blk_size)) + return AVERROR_INVALIDDATA; + if (codec2subblock(ctx, cx + blk_size, cy , blk_size)) + return AVERROR_INVALIDDATA; + if (codec2subblock(ctx, cx , cy + blk_size, blk_size)) + return AVERROR_INVALIDDATA; + if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size)) + return AVERROR_INVALIDDATA; + } + break; + } + return 0; +} + +static int decode_2(SANMVideoContext *ctx) +{ + int cx, cy, ret; + + for (cy = 0; cy < ctx->aligned_height; cy += 8) { + for (cx = 0; cx < ctx->aligned_width; cx += 8) { + if (ret = codec2subblock(ctx, cx, cy, 8)) + return ret; + } + } + + return 0; +} + +static int decode_3(SANMVideoContext *ctx) +{ + memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size); + return 0; +} + +static int decode_4(SANMVideoContext *ctx) +{ + memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size); + return 0; +} + +static int decode_5(SANMVideoContext *ctx) +{ +#if HAVE_BIGENDIAN + uint16_t *frm; + int npixels; +#endif + uint8_t *dst = (uint8_t*)ctx->frm0; + + if (rle_decode(ctx, dst, ctx->buf_size)) + return AVERROR_INVALIDDATA; + +#if HAVE_BIGENDIAN + npixels = ctx->npixels; + frm = ctx->frm0; + while (npixels--) + *frm++ = av_bswap16(*frm); +#endif + + return 0; +} + +static int decode_6(SANMVideoContext *ctx) +{ + int npixels = ctx->npixels; + uint16_t *frm = ctx->frm0; + + if (bytestream2_get_bytes_left(&ctx->gb) < npixels) { + av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for frame\n"); + return AVERROR_INVALIDDATA; + } + while (npixels--) + *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)]; + + return 0; +} + +static int decode_8(SANMVideoContext *ctx) +{ + uint16_t *pdest = ctx->frm0; + uint8_t *rsrc; + long npixels = ctx->npixels; + + av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels); + if (!ctx->rle_buf) { + av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed\n"); + return AVERROR(ENOMEM); + } + rsrc = ctx->rle_buf; + + if (rle_decode(ctx, rsrc, npixels)) + return AVERROR_INVALIDDATA; + + while (npixels--) + *pdest++ = ctx->codebook[*rsrc++]; + + return 0; +} + +typedef int (*frm_decoder)(SANMVideoContext *ctx); + +static const frm_decoder v1_decoders[] = { + decode_0, decode_nop, decode_2, decode_3, decode_4, decode_5, + decode_6, decode_nop, decode_8 +}; + +static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr) +{ + int i, ret; + + if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) { + av_log(ctx->avctx, AV_LOG_ERROR, "too short input frame (%d bytes)\n", + ret); + return AVERROR_INVALIDDATA; + } + bytestream2_skip(&ctx->gb, 8); // skip pad + + hdr->width = bytestream2_get_le32u(&ctx->gb); + hdr->height = bytestream2_get_le32u(&ctx->gb); + + if (hdr->width != ctx->width || hdr->height != ctx->height) { + av_log(ctx->avctx, AV_LOG_ERROR, "variable size frames are not implemented\n"); + return AVERROR_PATCHWELCOME; + } + + hdr->seq_num = bytestream2_get_le16u(&ctx->gb); + hdr->codec = bytestream2_get_byteu(&ctx->gb); + hdr->rotate_code = bytestream2_get_byteu(&ctx->gb); + + bytestream2_skip(&ctx->gb, 4); // skip pad + + for (i = 0; i < 4; i++) + ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb); + hdr->bg_color = bytestream2_get_le16u(&ctx->gb); + + bytestream2_skip(&ctx->gb, 2); // skip pad + + hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb); + for (i = 0; i < 256; i++) + ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb); + + bytestream2_skip(&ctx->gb, 8); // skip pad + + av_dlog(ctx->avctx, "subcodec %d\n", hdr->codec); + return 0; +} + +static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color) +{ + while (buf_size--) + *pbuf++ = color; +} + +static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr) +{ + uint8_t *dst; + const uint8_t *src = (uint8_t*) ctx->frm0; + int ret, dstpitch, height = ctx->height; + int srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1); + + if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0) + return ret; + + dst = ctx->frame->data[0]; + dstpitch = ctx->frame->linesize[0]; + + while (height--) { + memcpy(dst, src, srcpitch); + src += srcpitch; + dst += dstpitch; + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + SANMVideoContext *ctx = avctx->priv_data; + int i, ret; + + ctx->frame = data; + bytestream2_init(&ctx->gb, pkt->data, pkt->size); + + if (!ctx->version) { + int to_store = 0; + + while (bytestream2_get_bytes_left(&ctx->gb) >= 8) { + uint32_t sig, size; + int pos; + + sig = bytestream2_get_be32u(&ctx->gb); + size = bytestream2_get_be32u(&ctx->gb); + pos = bytestream2_tell(&ctx->gb); + + if (bytestream2_get_bytes_left(&ctx->gb) < size) { + av_log(avctx, AV_LOG_ERROR, "incorrect chunk size %d\n", size); + break; + } + switch (sig) { + case MKBETAG('N', 'P', 'A', 'L'): + if (size != 256 * 3) { + av_log(avctx, AV_LOG_ERROR, "incorrect palette block size %d\n", + size); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < 256; i++) + ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb); + break; + case MKBETAG('F', 'O', 'B', 'J'): + if (size < 16) + return AVERROR_INVALIDDATA; + if (ret = process_frame_obj(ctx)) + return ret; + break; + case MKBETAG('X', 'P', 'A', 'L'): + if (size == 6 || size == 4) { + uint8_t tmp[3]; + int j; + + for (i = 0; i < 256; i++) { + for (j = 0; j < 3; j++) { + int t = (ctx->pal[i] >> (16 - j * 8)) & 0xFF; + tmp[j] = av_clip_uint8((t * 129 + ctx->delta_pal[i * 3 + j]) >> 7); + } + ctx->pal[i] = 0xFFU << 24 | AV_RB24(tmp); + } + } else { + if (size < 768 * 2 + 4) { + av_log(avctx, AV_LOG_ERROR, "incorrect palette change block size %d\n", + size); + return AVERROR_INVALIDDATA; + } + bytestream2_skipu(&ctx->gb, 4); + for (i = 0; i < 768; i++) + ctx->delta_pal[i] = bytestream2_get_le16u(&ctx->gb); + if (size >= 768 * 5 + 4) { + for (i = 0; i < 256; i++) + ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb); + } else { + memset(ctx->pal, 0, sizeof(ctx->pal)); + } + } + break; + case MKBETAG('S', 'T', 'O', 'R'): + to_store = 1; + break; + case MKBETAG('F', 'T', 'C', 'H'): + memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size); + break; + default: + bytestream2_skip(&ctx->gb, size); + av_log(avctx, AV_LOG_DEBUG, "unknown/unsupported chunk %x\n", sig); + break; + } + + bytestream2_seek(&ctx->gb, pos + size, SEEK_SET); + if (size & 1) + bytestream2_skip(&ctx->gb, 1); + } + if (to_store) + memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size); + if ((ret = copy_output(ctx, NULL))) + return ret; + memcpy(ctx->frame->data[1], ctx->pal, 1024); + } else { + SANMFrameHeader header; + + if ((ret = read_frame_header(ctx, &header))) + return ret; + + ctx->rotate_code = header.rotate_code; + if ((ctx->frame->key_frame = !header.seq_num)) { + ctx->frame->pict_type = AV_PICTURE_TYPE_I; + fill_frame(ctx->frm1, ctx->npixels, header.bg_color); + fill_frame(ctx->frm2, ctx->npixels, header.bg_color); + } else { + ctx->frame->pict_type = AV_PICTURE_TYPE_P; + } + + if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) { + if ((ret = v1_decoders[header.codec](ctx))) { + av_log(avctx, AV_LOG_ERROR, + "subcodec %d: error decoding frame\n", header.codec); + return ret; + } + } else { + avpriv_request_sample(avctx, "subcodec %d", + header.codec); + return AVERROR_PATCHWELCOME; + } + + if ((ret = copy_output(ctx, &header))) + return ret; + } + if (ctx->rotate_code) + rotate_bufs(ctx, ctx->rotate_code); + + *got_frame_ptr = 1; + + return pkt->size; +} + +AVCodec ff_sanm_decoder = { + .name = "sanm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SANM, + .priv_data_size = sizeof(SANMVideoContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"), +}; diff --git a/ffmpeg/libavcodec/sanm_data.h b/ffmpeg/libavcodec/sanm_data.h new file mode 100644 index 0000000..8fccf38 --- /dev/null +++ b/ffmpeg/libavcodec/sanm_data.h @@ -0,0 +1,248 @@ +/* + * LucasArts Smush video decoder + * Copyright (c) 2006 Cyril Zorin + * + * 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 + */ + +#ifndef AVCODEC_SANM_DATA_H +#define AVCODEC_SANM_DATA_H + +#include + +#define GLYPH_COORD_VECT_SIZE 16 + +static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE] = + { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1 }; +static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE] = + { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2 }; +static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE] = + { 0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0 }; +static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE] = + { 0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1 }; + +static const int8_t motion_vectors[256][2] = +{ + { 0, 0}, { -1, -43}, { 6, -43}, { -9, -42}, { 13, -41}, + {-16, -40}, { 19, -39}, {-23, -36}, { 26, -34}, { -2, -33}, + { 4, -33}, {-29, -32}, { -9, -32}, { 11, -31}, {-16, -29}, + { 32, -29}, { 18, -28}, {-34, -26}, {-22, -25}, { -1, -25}, + { 3, -25}, { -7, -24}, { 8, -24}, { 24, -23}, { 36, -23}, + {-12, -22}, { 13, -21}, {-38, -20}, { 0, -20}, {-27, -19}, + { -4, -19}, { 4, -19}, {-17, -18}, { -8, -17}, { 8, -17}, + { 18, -17}, { 28, -17}, { 39, -17}, {-12, -15}, { 12, -15}, + {-21, -14}, { -1, -14}, { 1, -14}, {-41, -13}, { -5, -13}, + { 5, -13}, { 21, -13}, {-31, -12}, {-15, -11}, { -8, -11}, + { 8, -11}, { 15, -11}, { -2, -10}, { 1, -10}, { 31, -10}, + {-23, -9}, {-11, -9}, { -5, -9}, { 4, -9}, { 11, -9}, + { 42, -9}, { 6, -8}, { 24, -8}, {-18, -7}, { -7, -7}, + { -3, -7}, { -1, -7}, { 2, -7}, { 18, -7}, {-43, -6}, + {-13, -6}, { -4, -6}, { 4, -6}, { 8, -6}, {-33, -5}, + { -9, -5}, { -2, -5}, { 0, -5}, { 2, -5}, { 5, -5}, + { 13, -5}, {-25, -4}, { -6, -4}, { -3, -4}, { 3, -4}, + { 9, -4}, {-19, -3}, { -7, -3}, { -4, -3}, { -2, -3}, + { -1, -3}, { 0, -3}, { 1, -3}, { 2, -3}, { 4, -3}, + { 6, -3}, { 33, -3}, {-14, -2}, {-10, -2}, { -5, -2}, + { -3, -2}, { -2, -2}, { -1, -2}, { 0, -2}, { 1, -2}, + { 2, -2}, { 3, -2}, { 5, -2}, { 7, -2}, { 14, -2}, + { 19, -2}, { 25, -2}, { 43, -2}, { -7, -1}, { -3, -1}, + { -2, -1}, { -1, -1}, { 0, -1}, { 1, -1}, { 2, -1}, + { 3, -1}, { 10, -1}, { -5, 0}, { -3, 0}, { -2, 0}, + { -1, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 5, 0}, + { 7, 0}, {-10, 1}, { -7, 1}, { -3, 1}, { -2, 1}, + { -1, 1}, { 0, 1}, { 1, 1}, { 2, 1}, { 3, 1}, + {-43, 2}, {-25, 2}, {-19, 2}, {-14, 2}, { -5, 2}, + { -3, 2}, { -2, 2}, { -1, 2}, { 0, 2}, { 1, 2}, + { 2, 2}, { 3, 2}, { 5, 2}, { 7, 2}, { 10, 2}, + { 14, 2}, {-33, 3}, { -6, 3}, { -4, 3}, { -2, 3}, + { -1, 3}, { 0, 3}, { 1, 3}, { 2, 3}, { 4, 3}, + { 19, 3}, { -9, 4}, { -3, 4}, { 3, 4}, { 7, 4}, + { 25, 4}, {-13, 5}, { -5, 5}, { -2, 5}, { 0, 5}, + { 2, 5}, { 5, 5}, { 9, 5}, { 33, 5}, { -8, 6}, + { -4, 6}, { 4, 6}, { 13, 6}, { 43, 6}, {-18, 7}, + { -2, 7}, { 0, 7}, { 2, 7}, { 7, 7}, { 18, 7}, + {-24, 8}, { -6, 8}, {-42, 9}, {-11, 9}, { -4, 9}, + { 5, 9}, { 11, 9}, { 23, 9}, {-31, 10}, { -1, 10}, + { 2, 10}, {-15, 11}, { -8, 11}, { 8, 11}, { 15, 11}, + { 31, 12}, {-21, 13}, { -5, 13}, { 5, 13}, { 41, 13}, + { -1, 14}, { 1, 14}, { 21, 14}, {-12, 15}, { 12, 15}, + {-39, 17}, {-28, 17}, {-18, 17}, { -8, 17}, { 8, 17}, + { 17, 18}, { -4, 19}, { 0, 19}, { 4, 19}, { 27, 19}, + { 38, 20}, {-13, 21}, { 12, 22}, {-36, 23}, {-24, 23}, + { -8, 24}, { 7, 24}, { -3, 25}, { 1, 25}, { 22, 25}, + { 34, 26}, {-18, 28}, {-32, 29}, { 16, 29}, {-11, 31}, + { 9, 32}, { 29, 32}, { -4, 33}, { 2, 33}, {-26, 34}, + { 23, 36}, {-19, 39}, { 16, 40}, {-13, 41}, { 9, 42}, + { -6, 43}, { 1, 43}, { 0, 0}, { 0, 0}, { 0, 0}, +}; + +static const int8_t c37_mv[] = { + 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, + 8, 0, 13, 0, 21, 0, -1, 0, -2, 0, + -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, + -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, + 5, 1, 8, 1, 13, 1, 21, 1, -1, 1, + -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, + -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, + 3, 2, 5, 2, 8, 2, 13, 2, 21, 2, + -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, + -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, + 2, 3, 3, 3, 5, 3, 8, 3, 13, 3, + 21, 3, -1, 3, -2, 3, -3, 3, -5, 3, + -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, + 1, 5, 2, 5, 3, 5, 5, 5, 8, 5, + 13, 5, 21, 5, -1, 5, -2, 5, -3, 5, + -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, + 0, 8, 1, 8, 2, 8, 3, 8, 5, 8, + 8, 8, 13, 8, 21, 8, -1, 8, -2, 8, + -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, + -21, 8, 0, 13, 1, 13, 2, 13, 3, 13, + 5, 13, 8, 13, 13, 13, 21, 13, -1, 13, + -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, + -17, 13, -21, 13, 0, 21, 1, 21, 2, 21, + 3, 21, 5, 21, 8, 21, 13, 21, 21, 21, + -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, + -13, 21, -17, 21, -21, 21, 0, -1, 1, -1, + 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, + 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, + -8, -1, -13, -1, -17, -1, -21, -1, 0, -2, + 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, + 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, + -5, -2, -8, -2, -13, -2, -17, -2, -21, -2, + 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, + 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, + -3, -3, -5, -3, -8, -3, -13, -3, -17, -3, + -21, -3, 0, -5, 1, -5, 2, -5, 3, -5, + 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, + -2, -5, -3, -5, -5, -5, -8, -5, -13, -5, + -17, -5, -21, -5, 0, -8, 1, -8, 2, -8, + 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, + -1, -8, -2, -8, -3, -8, -5, -8, -8, -8, + -13, -8, -17, -8, -21, -8, 0, -13, 1, -13, + 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, + 21, -13, -1, -13, -2, -13, -3, -13, -5, -13, + -8, -13, -13, -13, -17, -13, -21, -13, 0, -17, + 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, + 13, -17, 21, -17, -1, -17, -2, -17, -3, -17, + -5, -17, -8, -17, -13, -17, -17, -17, -21, -17, + 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, + 8, -21, 13, -21, 21, -21, -1, -21, -2, -21, + -3, -21, -5, -21, -8, -21, -13, -21, -17, -21, + 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, + 0, -23, -6, -22, 6, -22, -13, -19, 12, -19, + 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, + -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, + 19, -13, -19, -12, -8, -11, -2, -11, 0, -11, + 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, + 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, + -29, -8, -11, -8, -8, -8, -3, -8, 3, -8, + 8, -8, 11, -8, 29, -8, -5, -7, -2, -7, + 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, + -6, -6, -3, -6, -1, -6, 1, -6, 3, -6, + 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, + -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, + 7, -5, 17, -5, -13, -4, -10, -4, -5, -4, + -3, -4, -1, -4, 0, -4, 1, -4, 3, -4, + 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, + -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, + 1, -3, 2, -3, 4, -3, 6, -3, 8, -3, + -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, + -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, + 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, + -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, + 1, -1, 2, -1, 3, -1, 4, -1, 6, -1, + 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, + -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, + -2, 0, -1, 0, 0, -31, 1, 0, 2, 0, + 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, + 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, + -6, 1, -4, 1, -3, 1, -2, 1, -1, 1, + 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, + 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, + -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, + 2, 2, 3, 2, 5, 2, 7, 2, 11, 2, + -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, + 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, + 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, + -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, + 5, 4, 10, 4, 13, 4, -17, 5, -7, 5, + -4, 5, -2, 5, 0, 5, 2, 5, 4, 5, + 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, + -3, 6, -1, 6, 1, 6, 3, 6, 6, 6, + 9, 6, 22, 6, -5, 7, -2, 7, 0, 7, + 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, + -3, 8, 3, 8, 8, 8, 11, 8, 29, 8, + -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, + -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, + 0, 11, 2, 11, 8, 11, 19, 12, -19, 13, + -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, + -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, + -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, + -17, 25, 18, 25, -8, 29, 8, 29, 0, 31, + 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, + 0, -18, -5, -17, 5, -17, -10, -15, 10, -15, + 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, + -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, + -15, -10, -4, -10, 4, -10, 15, -10, -6, -9, + -1, -9, 1, -9, 6, -9, -11, -8, -8, -8, + -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, + -5, -7, -2, -7, 0, -7, 2, -7, 5, -7, + -22, -6, -9, -6, -6, -6, -3, -6, -1, -6, + 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, + -17, -5, -7, -5, -4, -5, -2, -5, -1, -5, + 0, -5, 1, -5, 2, -5, 4, -5, 7, -5, + 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, + -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, + 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, + -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, + 0, -3, 1, -3, 2, -3, 3, -3, 4, -3, + 6, -3, 8, -3, -11, -2, -7, -2, -5, -2, + -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, + 1, -2, 2, -2, 3, -2, 4, -2, 5, -2, + 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, + -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, + 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, + 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, + -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, + -2, 0, -1, 0, 0, -23, 1, 0, 2, 0, + 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, + 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, + -5, 1, -4, 1, -3, 1, -2, 1, -1, 1, + 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, + 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, + -5, 2, -4, 2, -3, 2, -2, 2, -1, 2, + 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, + 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, + -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, + 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, + 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, + -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, + 3, 4, 5, 4, 10, 4, 13, 4, -17, 5, + -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, + 1, 5, 2, 5, 4, 5, 7, 5, 17, 5, + -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, + 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, + -5, 7, -2, 7, 0, 7, 2, 7, 5, 7, + -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, + 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, + 6, 9, -15, 10, -4, 10, 4, 10, 15, 10, + -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, + 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, + -10, 15, 10, 15, -5, 17, 5, 17, 0, 18, + -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, +}; +#endif /* AVCODEC_SANM_DATA_H */ diff --git a/ffmpeg/libavcodec/sbr.h b/ffmpeg/libavcodec/sbr.h new file mode 100644 index 0000000..e28fccd --- /dev/null +++ b/ffmpeg/libavcodec/sbr.h @@ -0,0 +1,213 @@ +/* + * Spectral Band Replication definitions and structures + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * Copyright (c) 2010 Alex Converse + * + * 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 + */ + +/** + * @file + * Spectral Band Replication definitions and structures + * @author Robert Swain ( rob opendot cl ) + */ + +#ifndef AVCODEC_SBR_H +#define AVCODEC_SBR_H + +#include +#include "fft.h" +#include "aacps.h" +#include "sbrdsp.h" + +typedef struct AACContext AACContext; + +/** + * Spectral Band Replication header - spectrum parameters that invoke a reset if they differ from the previous header. + */ +typedef struct SpectrumParameters { + uint8_t bs_start_freq; + uint8_t bs_stop_freq; + uint8_t bs_xover_band; + + /** + * @name Variables associated with bs_header_extra_1 + * @{ + */ + uint8_t bs_freq_scale; + uint8_t bs_alter_scale; + uint8_t bs_noise_bands; + /** @} */ +} SpectrumParameters; + +#define SBR_SYNTHESIS_BUF_SIZE ((1280-128)*2) + +/** + * Spectral Band Replication per channel data + */ +typedef struct SBRData { + /** + * @name Main bitstream data variables + * @{ + */ + unsigned bs_frame_class; + unsigned bs_add_harmonic_flag; + unsigned bs_num_env; + uint8_t bs_freq_res[7]; + unsigned bs_num_noise; + uint8_t bs_df_env[5]; + uint8_t bs_df_noise[2]; + uint8_t bs_invf_mode[2][5]; + uint8_t bs_add_harmonic[48]; + unsigned bs_amp_res; + /** @} */ + + /** + * @name State variables + * @{ + */ + DECLARE_ALIGNED(32, float, synthesis_filterbank_samples)[SBR_SYNTHESIS_BUF_SIZE]; + DECLARE_ALIGNED(32, float, analysis_filterbank_samples) [1312]; + int synthesis_filterbank_samples_offset; + ///l_APrev and l_A + int e_a[2]; + ///Chirp factors + float bw_array[5]; + ///QMF values of the original signal + float W[2][32][32][2]; + ///QMF output of the HF adjustor + int Ypos; + DECLARE_ALIGNED(16, float, Y)[2][38][64][2]; + DECLARE_ALIGNED(16, float, g_temp)[42][48]; + float q_temp[42][48]; + uint8_t s_indexmapped[8][48]; + ///Envelope scalefactors + float env_facs[6][48]; + ///Noise scalefactors + float noise_facs[3][5]; + ///Envelope time borders + uint8_t t_env[8]; + ///Envelope time border of the last envelope of the previous frame + uint8_t t_env_num_env_old; + ///Noise time borders + uint8_t t_q[3]; + unsigned f_indexnoise; + unsigned f_indexsine; + /** @} */ +} SBRData; + +typedef struct SpectralBandReplication SpectralBandReplication; + +/** + * aacsbr functions pointers + */ +typedef struct AACSBRContext { + int (*sbr_lf_gen)(AACContext *ac, SpectralBandReplication *sbr, + float X_low[32][40][2], const float W[2][32][32][2], + int buf_idx); + void (*sbr_hf_assemble)(float Y1[38][64][2], + const float X_high[64][40][2], + SpectralBandReplication *sbr, SBRData *ch_data, + const int e_a[2]); + int (*sbr_x_gen)(SpectralBandReplication *sbr, float X[2][38][64], + const float Y0[38][64][2], const float Y1[38][64][2], + const float X_low[32][40][2], int ch); + void (*sbr_hf_inverse_filter)(SBRDSPContext *dsp, + float (*alpha0)[2], float (*alpha1)[2], + const float X_low[32][40][2], int k0); +} AACSBRContext; + +/** + * Spectral Band Replication + */ +struct SpectralBandReplication { + int sample_rate; + int start; + int reset; + SpectrumParameters spectrum_params; + int bs_amp_res_header; + /** + * @name Variables associated with bs_header_extra_2 + * @{ + */ + unsigned bs_limiter_bands; + unsigned bs_limiter_gains; + unsigned bs_interpol_freq; + unsigned bs_smoothing_mode; + /** @} */ + unsigned bs_coupling; + unsigned k[5]; ///< k0, k1, k2 + ///kx', and kx respectively, kx is the first QMF subband where SBR is used. + ///kx' is its value from the previous frame + unsigned kx[2]; + ///M' and M respectively, M is the number of QMF subbands that use SBR. + unsigned m[2]; + unsigned kx_and_m_pushed; + ///The number of frequency bands in f_master + unsigned n_master; + SBRData data[2]; + PSContext ps; + ///N_Low and N_High respectively, the number of frequency bands for low and high resolution + unsigned n[2]; + ///Number of noise floor bands + unsigned n_q; + ///Number of limiter bands + unsigned n_lim; + ///The master QMF frequency grouping + uint16_t f_master[49]; + ///Frequency borders for low resolution SBR + uint16_t f_tablelow[25]; + ///Frequency borders for high resolution SBR + uint16_t f_tablehigh[49]; + ///Frequency borders for noise floors + uint16_t f_tablenoise[6]; + ///Frequency borders for the limiter + uint16_t f_tablelim[30]; + unsigned num_patches; + uint8_t patch_num_subbands[6]; + uint8_t patch_start_subband[6]; + ///QMF low frequency input to the HF generator + DECLARE_ALIGNED(16, float, X_low)[32][40][2]; + ///QMF output of the HF generator + DECLARE_ALIGNED(16, float, X_high)[64][40][2]; + ///QMF values of the reconstructed signal + DECLARE_ALIGNED(16, float, X)[2][2][38][64]; + ///Zeroth coefficient used to filter the subband signals + DECLARE_ALIGNED(16, float, alpha0)[64][2]; + ///First coefficient used to filter the subband signals + DECLARE_ALIGNED(16, float, alpha1)[64][2]; + ///Dequantized envelope scalefactors, remapped + float e_origmapped[7][48]; + ///Dequantized noise scalefactors, remapped + float q_mapped[7][48]; + ///Sinusoidal presence, remapped + uint8_t s_mapped[7][48]; + ///Estimated envelope + float e_curr[7][48]; + ///Amplitude adjusted noise scalefactors + float q_m[7][48]; + ///Sinusoidal levels + float s_m[7][48]; + float gain[7][48]; + DECLARE_ALIGNED(32, float, qmf_filter_scratch)[5][64]; + FFTContext mdct_ana; + FFTContext mdct; + SBRDSPContext dsp; + AACSBRContext c; +}; + +#endif /* AVCODEC_SBR_H */ diff --git a/ffmpeg/libavcodec/sbrdsp.c b/ffmpeg/libavcodec/sbrdsp.c new file mode 100644 index 0000000..6fede79 --- /dev/null +++ b/ffmpeg/libavcodec/sbrdsp.c @@ -0,0 +1,250 @@ +/* + * AAC Spectral Band Replication decoding functions + * Copyright (c) 2008-2009 Robert Swain ( rob opendot cl ) + * Copyright (c) 2009-2010 Alex Converse + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "sbrdsp.h" + +static void sbr_sum64x5_c(float *z) +{ + int k; + for (k = 0; k < 64; k++) { + float f = z[k] + z[k + 64] + z[k + 128] + z[k + 192] + z[k + 256]; + z[k] = f; + } +} + +static float sbr_sum_square_c(float (*x)[2], int n) +{ + float sum0 = 0.0f, sum1 = 0.0f; + int i; + + for (i = 0; i < n; i += 2) + { + sum0 += x[i + 0][0] * x[i + 0][0]; + sum1 += x[i + 0][1] * x[i + 0][1]; + sum0 += x[i + 1][0] * x[i + 1][0]; + sum1 += x[i + 1][1] * x[i + 1][1]; + } + + return sum0 + sum1; +} + +static void sbr_neg_odd_64_c(float *x) +{ + int i; + for (i = 1; i < 64; i += 2) + x[i] = -x[i]; +} + +static void sbr_qmf_pre_shuffle_c(float *z) +{ + int k; + z[64] = z[0]; + z[65] = z[1]; + for (k = 1; k < 32; k++) { + z[64+2*k ] = -z[64 - k]; + z[64+2*k+1] = z[ k + 1]; + } +} + +static void sbr_qmf_post_shuffle_c(float W[32][2], const float *z) +{ + int k; + for (k = 0; k < 32; k++) { + W[k][0] = -z[63-k]; + W[k][1] = z[k]; + } +} + +static void sbr_qmf_deint_neg_c(float *v, const float *src) +{ + int i; + for (i = 0; i < 32; i++) { + v[ i] = src[63 - 2*i ]; + v[63 - i] = -src[63 - 2*i - 1]; + } +} + +static void sbr_qmf_deint_bfly_c(float *v, const float *src0, const float *src1) +{ + int i; + for (i = 0; i < 64; i++) { + v[ i] = src0[i] - src1[63 - i]; + v[127 - i] = src0[i] + src1[63 - i]; + } +} + +static av_always_inline void autocorrelate(const float x[40][2], + float phi[3][2][2], int lag) +{ + int i; + float real_sum = 0.0f; + float imag_sum = 0.0f; + if (lag) { + for (i = 1; i < 38; i++) { + real_sum += x[i][0] * x[i+lag][0] + x[i][1] * x[i+lag][1]; + imag_sum += x[i][0] * x[i+lag][1] - x[i][1] * x[i+lag][0]; + } + phi[2-lag][1][0] = real_sum + x[ 0][0] * x[lag][0] + x[ 0][1] * x[lag][1]; + phi[2-lag][1][1] = imag_sum + x[ 0][0] * x[lag][1] - x[ 0][1] * x[lag][0]; + if (lag == 1) { + phi[0][0][0] = real_sum + x[38][0] * x[39][0] + x[38][1] * x[39][1]; + phi[0][0][1] = imag_sum + x[38][0] * x[39][1] - x[38][1] * x[39][0]; + } + } else { + for (i = 1; i < 38; i++) { + real_sum += x[i][0] * x[i][0] + x[i][1] * x[i][1]; + } + phi[2][1][0] = real_sum + x[ 0][0] * x[ 0][0] + x[ 0][1] * x[ 0][1]; + phi[1][0][0] = real_sum + x[38][0] * x[38][0] + x[38][1] * x[38][1]; + } +} + +static void sbr_autocorrelate_c(const float x[40][2], float phi[3][2][2]) +{ + autocorrelate(x, phi, 0); + autocorrelate(x, phi, 1); + autocorrelate(x, phi, 2); +} + +static void sbr_hf_gen_c(float (*X_high)[2], const float (*X_low)[2], + const float alpha0[2], const float alpha1[2], + float bw, int start, int end) +{ + float alpha[4]; + int i; + + alpha[0] = alpha1[0] * bw * bw; + alpha[1] = alpha1[1] * bw * bw; + alpha[2] = alpha0[0] * bw; + alpha[3] = alpha0[1] * bw; + + for (i = start; i < end; i++) { + X_high[i][0] = + X_low[i - 2][0] * alpha[0] - + X_low[i - 2][1] * alpha[1] + + X_low[i - 1][0] * alpha[2] - + X_low[i - 1][1] * alpha[3] + + X_low[i][0]; + X_high[i][1] = + X_low[i - 2][1] * alpha[0] + + X_low[i - 2][0] * alpha[1] + + X_low[i - 1][1] * alpha[2] + + X_low[i - 1][0] * alpha[3] + + X_low[i][1]; + } +} + +static void sbr_hf_g_filt_c(float (*Y)[2], const float (*X_high)[40][2], + const float *g_filt, int m_max, intptr_t ixh) +{ + int m; + + for (m = 0; m < m_max; m++) { + Y[m][0] = X_high[m][ixh][0] * g_filt[m]; + Y[m][1] = X_high[m][ixh][1] * g_filt[m]; + } +} + +static av_always_inline void sbr_hf_apply_noise(float (*Y)[2], + const float *s_m, + const float *q_filt, + int noise, + float phi_sign0, + float phi_sign1, + int m_max) +{ + int m; + + for (m = 0; m < m_max; m++) { + float y0 = Y[m][0]; + float y1 = Y[m][1]; + noise = (noise + 1) & 0x1ff; + if (s_m[m]) { + y0 += s_m[m] * phi_sign0; + y1 += s_m[m] * phi_sign1; + } else { + y0 += q_filt[m] * ff_sbr_noise_table[noise][0]; + y1 += q_filt[m] * ff_sbr_noise_table[noise][1]; + } + Y[m][0] = y0; + Y[m][1] = y1; + phi_sign1 = -phi_sign1; + } +} + +static void sbr_hf_apply_noise_0(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + sbr_hf_apply_noise(Y, s_m, q_filt, noise, 1.0, 0.0, m_max); +} + +static void sbr_hf_apply_noise_1(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + float phi_sign = 1 - 2 * (kx & 1); + sbr_hf_apply_noise(Y, s_m, q_filt, noise, 0.0, phi_sign, m_max); +} + +static void sbr_hf_apply_noise_2(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + sbr_hf_apply_noise(Y, s_m, q_filt, noise, -1.0, 0.0, m_max); +} + +static void sbr_hf_apply_noise_3(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max) +{ + float phi_sign = 1 - 2 * (kx & 1); + sbr_hf_apply_noise(Y, s_m, q_filt, noise, 0.0, -phi_sign, m_max); +} + +av_cold void ff_sbrdsp_init(SBRDSPContext *s) +{ + s->sum64x5 = sbr_sum64x5_c; + s->sum_square = sbr_sum_square_c; + s->neg_odd_64 = sbr_neg_odd_64_c; + s->qmf_pre_shuffle = sbr_qmf_pre_shuffle_c; + s->qmf_post_shuffle = sbr_qmf_post_shuffle_c; + s->qmf_deint_neg = sbr_qmf_deint_neg_c; + s->qmf_deint_bfly = sbr_qmf_deint_bfly_c; + s->autocorrelate = sbr_autocorrelate_c; + s->hf_gen = sbr_hf_gen_c; + s->hf_g_filt = sbr_hf_g_filt_c; + + s->hf_apply_noise[0] = sbr_hf_apply_noise_0; + s->hf_apply_noise[1] = sbr_hf_apply_noise_1; + s->hf_apply_noise[2] = sbr_hf_apply_noise_2; + s->hf_apply_noise[3] = sbr_hf_apply_noise_3; + + if (ARCH_ARM) + ff_sbrdsp_init_arm(s); + if (ARCH_X86) + ff_sbrdsp_init_x86(s); + if (ARCH_MIPS) + ff_sbrdsp_init_mips(s); +} diff --git a/ffmpeg/libavcodec/sbrdsp.h b/ffmpeg/libavcodec/sbrdsp.h new file mode 100644 index 0000000..3831135 --- /dev/null +++ b/ffmpeg/libavcodec/sbrdsp.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012 Mans Rullgard + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_SBRDSP_H +#define AVCODEC_SBRDSP_H + +#include + +typedef struct SBRDSPContext { + void (*sum64x5)(float *z); + float (*sum_square)(float (*x)[2], int n); + void (*neg_odd_64)(float *x); + void (*qmf_pre_shuffle)(float *z); + void (*qmf_post_shuffle)(float W[32][2], const float *z); + void (*qmf_deint_neg)(float *v, const float *src); + void (*qmf_deint_bfly)(float *v, const float *src0, const float *src1); + void (*autocorrelate)(const float x[40][2], float phi[3][2][2]); + void (*hf_gen)(float (*X_high)[2], const float (*X_low)[2], + const float alpha0[2], const float alpha1[2], + float bw, int start, int end); + void (*hf_g_filt)(float (*Y)[2], const float (*X_high)[40][2], + const float *g_filt, int m_max, intptr_t ixh); + void (*hf_apply_noise[4])(float (*Y)[2], const float *s_m, + const float *q_filt, int noise, + int kx, int m_max); +} SBRDSPContext; + +extern const float ff_sbr_noise_table[][2]; + +void ff_sbrdsp_init(SBRDSPContext *s); +void ff_sbrdsp_init_arm(SBRDSPContext *s); +void ff_sbrdsp_init_x86(SBRDSPContext *s); +void ff_sbrdsp_init_mips(SBRDSPContext *s); + +#endif /* AVCODEC_SBRDSP_H */ diff --git a/ffmpeg/libavcodec/sgi.h b/ffmpeg/libavcodec/sgi.h new file mode 100644 index 0000000..be17f2e --- /dev/null +++ b/ffmpeg/libavcodec/sgi.h @@ -0,0 +1,36 @@ + /* + * SGI image encoder + * Xiaohui Sun + * + * 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 + */ + +#ifndef AVCODEC_SGI_H +#define AVCODEC_SGI_H + +/** + * SGI image file signature + */ +#define SGI_MAGIC 474 + +#define SGI_HEADER_SIZE 512 + +#define SGI_GRAYSCALE 1 +#define SGI_RGB 3 +#define SGI_RGBA 4 + +#endif /* AVCODEC_SGI_H */ diff --git a/ffmpeg/libavcodec/sgidec.c b/ffmpeg/libavcodec/sgidec.c new file mode 100644 index 0000000..e7f453b --- /dev/null +++ b/ffmpeg/libavcodec/sgidec.c @@ -0,0 +1,243 @@ +/* + * SGI image decoder + * Todd Kirby + * + * 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 "libavutil/imgutils.h" +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "sgi.h" + +typedef struct SgiState { + unsigned int width; + unsigned int height; + unsigned int depth; + unsigned int bytes_per_channel; + int linesize; + GetByteContext g; +} SgiState; + +/** + * Expand an RLE row into a channel. + * @param s the current image state + * @param out_buf Points to one line after the output buffer. + * @param out_end end of line in output buffer + * @param pixelstride pixel stride of input buffer + * @return size of output in bytes, -1 if buffer overflows + */ +static int expand_rle_row(SgiState *s, uint8_t *out_buf, + uint8_t *out_end, int pixelstride) +{ + unsigned char pixel, count; + unsigned char *orig = out_buf; + + while (out_buf < out_end) { + if (bytestream2_get_bytes_left(&s->g) < 1) + return AVERROR_INVALIDDATA; + pixel = bytestream2_get_byteu(&s->g); + if (!(count = (pixel & 0x7f))) { + break; + } + + /* Check for buffer overflow. */ + if(out_buf + pixelstride * (count-1) >= out_end) return -1; + + if (pixel & 0x80) { + while (count--) { + *out_buf = bytestream2_get_byte(&s->g); + out_buf += pixelstride; + } + } else { + pixel = bytestream2_get_byte(&s->g); + + while (count--) { + *out_buf = pixel; + out_buf += pixelstride; + } + } + } + return (out_buf - orig) / pixelstride; +} + +/** + * Read a run length encoded SGI image. + * @param out_buf output buffer + * @param s the current image state + * @return 0 if no error, else return error number. + */ +static int read_rle_sgi(uint8_t *out_buf, SgiState *s) +{ + uint8_t *dest_row; + unsigned int len = s->height * s->depth * 4; + GetByteContext g_table = s->g; + unsigned int y, z; + unsigned int start_offset; + + /* size of RLE offset and length tables */ + if (len * 2 > bytestream2_get_bytes_left(&s->g)) { + return AVERROR_INVALIDDATA; + } + + for (z = 0; z < s->depth; z++) { + dest_row = out_buf; + for (y = 0; y < s->height; y++) { + dest_row -= s->linesize; + start_offset = bytestream2_get_be32(&g_table); + bytestream2_seek(&s->g, start_offset, SEEK_SET); + if (expand_rle_row(s, dest_row + z, dest_row + s->width*s->depth, + s->depth) != s->width) { + return AVERROR_INVALIDDATA; + } + } + } + return 0; +} + +/** + * Read an uncompressed SGI image. + * @param out_buf output buffer + * @param s the current image state + * @return 0 if read success, otherwise return -1. + */ +static int read_uncompressed_sgi(unsigned char* out_buf, SgiState *s) +{ + int x, y, z; + unsigned int offset = s->height * s->width * s->bytes_per_channel; + GetByteContext gp[4]; + uint8_t *out_end; + + /* Test buffer size. */ + if (offset * s->depth > bytestream2_get_bytes_left(&s->g)) + return AVERROR_INVALIDDATA; + + /* Create a reader for each plane */ + for (z = 0; z < s->depth; z++) { + gp[z] = s->g; + bytestream2_skip(&gp[z], z * offset); + } + + for (y = s->height - 1; y >= 0; y--) { + out_end = out_buf + (y * s->linesize); + if (s->bytes_per_channel == 1) { + for (x = s->width; x > 0; x--) + for (z = 0; z < s->depth; z++) + *out_end++ = bytestream2_get_byteu(&gp[z]); + } else { + uint16_t *out16 = (uint16_t *)out_end; + for (x = s->width; x > 0; x--) + for (z = 0; z < s->depth; z++) + *out16++ = bytestream2_get_ne16u(&gp[z]); + } + } + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + SgiState *s = avctx->priv_data; + AVFrame *p = data; + unsigned int dimension, rle; + int ret = 0; + uint8_t *out_buf, *out_end; + + bytestream2_init(&s->g, avpkt->data, avpkt->size); + if (bytestream2_get_bytes_left(&s->g) < SGI_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", avpkt->size); + return AVERROR_INVALIDDATA; + } + + /* Test for SGI magic. */ + if (bytestream2_get_be16u(&s->g) != SGI_MAGIC) { + av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); + return AVERROR_INVALIDDATA; + } + + rle = bytestream2_get_byteu(&s->g); + s->bytes_per_channel = bytestream2_get_byteu(&s->g); + dimension = bytestream2_get_be16u(&s->g); + s->width = bytestream2_get_be16u(&s->g); + s->height = bytestream2_get_be16u(&s->g); + s->depth = bytestream2_get_be16u(&s->g); + + if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) { + av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); + return -1; + } + + /* Check for supported image dimensions. */ + if (dimension != 2 && dimension != 3) { + av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n"); + return -1; + } + + if (s->depth == SGI_GRAYSCALE) { + avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_GRAY16BE : AV_PIX_FMT_GRAY8; + } else if (s->depth == SGI_RGB) { + avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_RGB48BE : AV_PIX_FMT_RGB24; + } else if (s->depth == SGI_RGBA) { + avctx->pix_fmt = s->bytes_per_channel == 2 ? AV_PIX_FMT_RGBA64BE : AV_PIX_FMT_RGBA; + } else { + av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); + return -1; + } + + if (av_image_check_size(s->width, s->height, 0, avctx)) + return -1; + avcodec_set_dimensions(avctx, s->width, s->height); + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + out_buf = p->data[0]; + + out_end = out_buf + p->linesize[0] * s->height; + + s->linesize = p->linesize[0]; + + /* Skip header. */ + bytestream2_seek(&s->g, SGI_HEADER_SIZE, SEEK_SET); + if (rle) { + ret = read_rle_sgi(out_end, s); + } else { + ret = read_uncompressed_sgi(out_buf, s); + } + + if (ret == 0) { + *got_frame = 1; + return avpkt->size; + } else { + return ret; + } +} + +AVCodec ff_sgi_decoder = { + .name = "sgi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SGI, + .priv_data_size = sizeof(SgiState), + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/sgienc.c b/ffmpeg/libavcodec/sgienc.c new file mode 100644 index 0000000..d03ef52 --- /dev/null +++ b/ffmpeg/libavcodec/sgienc.c @@ -0,0 +1,228 @@ +/* + * SGI image encoder + * Todd Kirby + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "sgi.h" +#include "rle.h" + +#define SGI_SINGLE_CHAN 2 +#define SGI_MULTI_CHAN 3 + +typedef struct SgiContext { + AVFrame picture; +} SgiContext; + +static av_cold int encode_init(AVCodecContext *avctx) +{ + SgiContext *s = avctx->priv_data; + + if (avctx->width > 65535 || avctx->height > 65535) { + av_log(avctx, AV_LOG_ERROR, "SGI does not support resolutions above 65535x65535\n"); + return -1; + } + + avcodec_get_frame_defaults(&s->picture); + avctx->coded_frame = &s->picture; + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + SgiContext *s = avctx->priv_data; + AVFrame * const p = &s->picture; + uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf; + int x, y, z, length, tablesize, ret; + unsigned int width, height, depth, dimension, bytes_per_channel, pixmax, put_be; + unsigned char *end_buf; + + *p = *frame; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + width = avctx->width; + height = avctx->height; + bytes_per_channel = 1; + pixmax = 0xFF; + put_be = HAVE_BIGENDIAN; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_GRAY8: + dimension = SGI_SINGLE_CHAN; + depth = SGI_GRAYSCALE; + break; + case AV_PIX_FMT_RGB24: + dimension = SGI_MULTI_CHAN; + depth = SGI_RGB; + break; + case AV_PIX_FMT_RGBA: + dimension = SGI_MULTI_CHAN; + depth = SGI_RGBA; + break; + case AV_PIX_FMT_GRAY16LE: + put_be = !HAVE_BIGENDIAN; + case AV_PIX_FMT_GRAY16BE: + avctx->coder_type = FF_CODER_TYPE_RAW; + bytes_per_channel = 2; + pixmax = 0xFFFF; + dimension = SGI_SINGLE_CHAN; + depth = SGI_GRAYSCALE; + break; + case AV_PIX_FMT_RGB48LE: + put_be = !HAVE_BIGENDIAN; + case AV_PIX_FMT_RGB48BE: + avctx->coder_type = FF_CODER_TYPE_RAW; + bytes_per_channel = 2; + pixmax = 0xFFFF; + dimension = SGI_MULTI_CHAN; + depth = SGI_RGB; + break; + case AV_PIX_FMT_RGBA64LE: + put_be = !HAVE_BIGENDIAN; + case AV_PIX_FMT_RGBA64BE: + avctx->coder_type = FF_CODER_TYPE_RAW; + bytes_per_channel = 2; + pixmax = 0xFFFF; + dimension = SGI_MULTI_CHAN; + depth = SGI_RGBA; + break; + default: + return AVERROR_INVALIDDATA; + } + + tablesize = depth * height * 4; + length = SGI_HEADER_SIZE; + if (avctx->coder_type == FF_CODER_TYPE_RAW) + length += depth * height * width; + else // assume ff_rl_encode() produces at most 2x size of input + length += tablesize * 2 + depth * height * (2 * width + 1); + + if ((ret = ff_alloc_packet2(avctx, pkt, bytes_per_channel * length)) < 0) + return ret; + buf = pkt->data; + end_buf = pkt->data + pkt->size; + + /* Encode header. */ + bytestream_put_be16(&buf, SGI_MAGIC); + bytestream_put_byte(&buf, avctx->coder_type != FF_CODER_TYPE_RAW); /* RLE 1 - VERBATIM 0*/ + bytestream_put_byte(&buf, bytes_per_channel); + bytestream_put_be16(&buf, dimension); + bytestream_put_be16(&buf, width); + bytestream_put_be16(&buf, height); + bytestream_put_be16(&buf, depth); + + bytestream_put_be32(&buf, 0L); /* pixmin */ + bytestream_put_be32(&buf, pixmax); + bytestream_put_be32(&buf, 0L); /* dummy */ + + /* name */ + memset(buf, 0, SGI_HEADER_SIZE); + buf += 80; + + /* colormap */ + bytestream_put_be32(&buf, 0L); + + /* The rest of the 512 byte header is unused. */ + buf += 404; + offsettab = buf; + + if (avctx->coder_type != FF_CODER_TYPE_RAW) { + /* Skip RLE offset table. */ + buf += tablesize; + lengthtab = buf; + + /* Skip RLE length table. */ + buf += tablesize; + + /* Make an intermediate consecutive buffer. */ + if (!(encode_buf = av_malloc(width))) + return -1; + + for (z = 0; z < depth; z++) { + in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; + + for (y = 0; y < height; y++) { + bytestream_put_be32(&offsettab, buf - pkt->data); + + for (x = 0; x < width; x++) + encode_buf[x] = in_buf[depth * x]; + + if ((length = ff_rle_encode(buf, end_buf - buf - 1, encode_buf, 1, width, 0, 0, 0x80, 0)) < 1) { + av_free(encode_buf); + return -1; + } + + buf += length; + bytestream_put_byte(&buf, 0); + bytestream_put_be32(&lengthtab, length + 1); + in_buf -= p->linesize[0]; + } + } + + av_free(encode_buf); + } else { + for (z = 0; z < depth; z++) { + in_buf = p->data[0] + p->linesize[0] * (height - 1) + z * bytes_per_channel; + + for (y = 0; y < height; y++) { + for (x = 0; x < width * depth; x += depth) + if (bytes_per_channel == 1) { + bytestream_put_byte(&buf, in_buf[x]); + } else { + if (put_be) { + bytestream_put_be16(&buf, ((uint16_t *)in_buf)[x]); + } else { + bytestream_put_le16(&buf, ((uint16_t *)in_buf)[x]); + } + } + + in_buf -= p->linesize[0]; + } + } + } + + /* total length */ + pkt->size = buf - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +AVCodec ff_sgi_encoder = { + .name = "sgi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SGI, + .priv_data_size = sizeof(SgiContext), + .init = encode_init, + .encode2 = encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE, + AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_RGBA64BE, + AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("SGI image"), +}; diff --git a/ffmpeg/libavcodec/sgirledec.c b/ffmpeg/libavcodec/sgirledec.c new file mode 100644 index 0000000..9d6cdba --- /dev/null +++ b/ffmpeg/libavcodec/sgirledec.c @@ -0,0 +1,151 @@ +/* + * SGI RLE 8-bit decoder + * Copyright (c) 2012 Peter Ross + * + * 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 + */ + +/** + * @file + * SGI RLE 8-bit decoder + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +typedef struct SGIRLEContext { + AVFrame *frame; +} SGIRLEContext; + +static av_cold int sgirle_decode_init(AVCodecContext *avctx) +{ + SGIRLEContext *s = avctx->priv_data; + avctx->pix_fmt = AV_PIX_FMT_BGR8; + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + return 0; +} + +/** + * Convert SGI RGB332 pixel into PIX_FMT_BGR8 + * SGI RGB332 is packed RGB 3:3:2, 8bpp, (msb)3R 2B 3G(lsb) + */ +#define RGB332_TO_BGR8(x) (((x << 3) & 0xC0) | ((x << 3) & 0x38) | ((x >> 5) & 7)) + +static av_always_inline void memcpy_rgb332_to_bgr8(uint8_t *dst, const uint8_t *src, int size) +{ + int i; + for (i = 0; i < size; i++) + dst[i] = RGB332_TO_BGR8(src[i]); +} + +/** + * @param[out] dst Destination buffer + * @param[in] src Source buffer + * @param src_size Source buffer size (bytes) + * @param width Width of destination buffer (pixels) + * @param height Height of destination buffer (pixels) + * @param linesize Line size of destination buffer (bytes) + * @return <0 on error + */ +static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize) +{ + const uint8_t *src_end = src + src_size; + int x = 0, y = 0; + +#define INC_XY(n) \ + x += n; \ + if (x >= width) { \ + y++; \ + if (y >= height) \ + return 0; \ + x = 0; \ + } + + while (src_end - src >= 2) { + uint8_t v = *src++; + if (v > 0 && v < 0xC0) { + do { + int length = FFMIN(v, width - x); + memset(dst + y*linesize + x, RGB332_TO_BGR8(*src), length); + INC_XY(length); + v -= length; + } while (v > 0); + src++; + } else if (v >= 0xC1) { + v -= 0xC0; + do { + int length = FFMIN3(v, width - x, src_end - src); + if (src_end - src < length) + break; + memcpy_rgb332_to_bgr8(dst + y*linesize + x, src, length); + INC_XY(length); + src += length; + v -= length; + } while (v > 0); + } else { + avpriv_request_sample(avctx, "opcode %d", v); + return AVERROR_PATCHWELCOME; + } + } + return 0; +} + +static int sgirle_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + SGIRLEContext *s = avctx->priv_data; + int ret; + + if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) + return ret; + + ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size, avctx->width, avctx->height, s->frame->linesize[0]); + if (ret < 0) + return ret; + + *got_frame = 1; + if ((ret = av_frame_ref(data, s->frame)) < 0) + return ret; + + return avpkt->size; +} + +static av_cold int sgirle_decode_end(AVCodecContext *avctx) +{ + SGIRLEContext *s = avctx->priv_data; + + av_frame_free(&s->frame); + + return 0; +} + +AVCodec ff_sgirle_decoder = { + .name = "sgirle", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SGIRLE, + .priv_data_size = sizeof(SGIRLEContext), + .init = sgirle_decode_init, + .close = sgirle_decode_end, + .decode = sgirle_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"), +}; diff --git a/ffmpeg/libavcodec/sh4/Makefile b/ffmpeg/libavcodec/sh4/Makefile new file mode 100644 index 0000000..a24b298 --- /dev/null +++ b/ffmpeg/libavcodec/sh4/Makefile @@ -0,0 +1,7 @@ +OBJS += sh4/dsputil_align.o \ + sh4/dsputil_sh4.o \ + sh4/idct_sh4.o \ + +OBJS-$(CONFIG_H264CHROMA) += sh4/h264chroma_init.o \ + +OBJS-$(CONFIG_HPELDSP) += sh4/hpeldsp.o diff --git a/ffmpeg/libavcodec/sh4/dsputil_align.c b/ffmpeg/libavcodec/sh4/dsputil_align.c new file mode 100644 index 0000000..d6bd479 --- /dev/null +++ b/ffmpeg/libavcodec/sh4/dsputil_align.c @@ -0,0 +1,312 @@ +/* + * aligned/packed access motion + * + * Copyright (c) 2001-2003 BERO + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/rnd_avg.h" +#include "dsputil_sh4.h" + + +#define LP(p) *(uint32_t*)(p) +#define LPC(p) *(const uint32_t*)(p) + + +#define UNPACK(ph,pl,tt0,tt1) do { \ + uint32_t t0,t1; t0=tt0;t1=tt1; \ + ph = ( (t0 & ~BYTE_VEC32(0x03))>>2) + ( (t1 & ~BYTE_VEC32(0x03))>>2); \ + pl = (t0 & BYTE_VEC32(0x03)) + (t1 & BYTE_VEC32(0x03)); } while(0) + +#define rnd_PACK(ph,pl,nph,npl) ph + nph + (((pl + npl + BYTE_VEC32(0x02))>>2) & BYTE_VEC32(0x03)) +#define no_rnd_PACK(ph,pl,nph,npl) ph + nph + (((pl + npl + BYTE_VEC32(0x01))>>2) & BYTE_VEC32(0x03)) + +/* little-endian */ +#define MERGE1(a,b,ofs) (ofs==0)?a:( ((a)>>(8*ofs))|((b)<<(32-8*ofs)) ) +#define MERGE2(a,b,ofs) (ofs==3)?b:( ((a)>>(8*(ofs+1)))|((b)<<(32-8*(ofs+1))) ) +/* big +#define MERGE1(a,b,ofs) (ofs==0)?a:( ((a)<<(8*ofs))|((b)>>(32-8*ofs)) ) +#define MERGE2(a,b,ofs) (ofs==3)?b:( ((a)<<(8+8*ofs))|((b)>>(32-8-8*ofs)) ) +*/ + + +#define put(d,s) d = s +#define avg(d,s) d = rnd_avg32(s,d) + +#define OP_C4(ofs) \ + ref-=ofs; \ + do { \ + OP(LP(dest),MERGE1(LPC(ref),LPC(ref+4),ofs)); \ + ref+=stride; \ + dest+=stride; \ + } while(--height) + +#define OP_C40() \ + do { \ + OP(LP(dest),LPC(ref)); \ + ref+=stride; \ + dest+=stride; \ + } while(--height) + +#define OP_C(ofs,sz,avg2) \ +{ \ + ref-=ofs; \ + do { \ + uint32_t t0,t1; \ + t0 = LPC(ref+0); \ + t1 = LPC(ref+4); \ + OP(LP(dest+0), MERGE1(t0,t1,ofs)); \ + t0 = LPC(ref+8); \ + OP(LP(dest+4), MERGE1(t1,t0,ofs)); \ +if (sz==16) { \ + t1 = LPC(ref+12); \ + OP(LP(dest+8), MERGE1(t0,t1,ofs)); \ + t0 = LPC(ref+16); \ + OP(LP(dest+12), MERGE1(t1,t0,ofs)); \ +} \ + ref+=stride; \ + dest+= stride; \ + } while(--height); \ +} + +/* aligned */ +#define OP_C0(sz,avg2) \ +{ \ + do { \ + OP(LP(dest+0), LPC(ref+0)); \ + OP(LP(dest+4), LPC(ref+4)); \ +if (sz==16) { \ + OP(LP(dest+8), LPC(ref+8)); \ + OP(LP(dest+12), LPC(ref+12)); \ +} \ + ref+=stride; \ + dest+= stride; \ + } while(--height); \ +} + +#define OP_X(ofs,sz,avg2) \ +{ \ + ref-=ofs; \ + do { \ + uint32_t t0,t1; \ + t0 = LPC(ref+0); \ + t1 = LPC(ref+4); \ + OP(LP(dest+0), avg2(MERGE1(t0,t1,ofs),MERGE2(t0,t1,ofs))); \ + t0 = LPC(ref+8); \ + OP(LP(dest+4), avg2(MERGE1(t1,t0,ofs),MERGE2(t1,t0,ofs))); \ +if (sz==16) { \ + t1 = LPC(ref+12); \ + OP(LP(dest+8), avg2(MERGE1(t0,t1,ofs),MERGE2(t0,t1,ofs))); \ + t0 = LPC(ref+16); \ + OP(LP(dest+12), avg2(MERGE1(t1,t0,ofs),MERGE2(t1,t0,ofs))); \ +} \ + ref+=stride; \ + dest+= stride; \ + } while(--height); \ +} + +/* aligned */ +#define OP_Y0(sz,avg2) \ +{ \ + uint32_t t0,t1,t2,t3,t; \ +\ + t0 = LPC(ref+0); \ + t1 = LPC(ref+4); \ +if (sz==16) { \ + t2 = LPC(ref+8); \ + t3 = LPC(ref+12); \ +} \ + do { \ + ref += stride; \ +\ + t = LPC(ref+0); \ + OP(LP(dest+0), avg2(t0,t)); t0 = t; \ + t = LPC(ref+4); \ + OP(LP(dest+4), avg2(t1,t)); t1 = t; \ +if (sz==16) { \ + t = LPC(ref+8); \ + OP(LP(dest+8), avg2(t2,t)); t2 = t; \ + t = LPC(ref+12); \ + OP(LP(dest+12), avg2(t3,t)); t3 = t; \ +} \ + dest+= stride; \ + } while(--height); \ +} + +#define OP_Y(ofs,sz,avg2) \ +{ \ + uint32_t t0,t1,t2,t3,t,w0,w1; \ +\ + ref-=ofs; \ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + t0 = MERGE1(w0,w1,ofs); \ + w0 = LPC(ref+8); \ + t1 = MERGE1(w1,w0,ofs); \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + t2 = MERGE1(w0,w1,ofs); \ + w0 = LPC(ref+16); \ + t3 = MERGE1(w1,w0,ofs); \ +} \ + do { \ + ref += stride; \ +\ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + t = MERGE1(w0,w1,ofs); \ + OP(LP(dest+0), avg2(t0,t)); t0 = t; \ + w0 = LPC(ref+8); \ + t = MERGE1(w1,w0,ofs); \ + OP(LP(dest+4), avg2(t1,t)); t1 = t; \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + t = MERGE1(w0,w1,ofs); \ + OP(LP(dest+8), avg2(t2,t)); t2 = t; \ + w0 = LPC(ref+16); \ + t = MERGE1(w1,w0,ofs); \ + OP(LP(dest+12), avg2(t3,t)); t3 = t; \ +} \ + dest+=stride; \ + } while(--height); \ +} + +#define OP_X0(sz,avg2) OP_X(0,sz,avg2) +#define OP_XY0(sz,PACK) OP_XY(0,sz,PACK) +#define OP_XY(ofs,sz,PACK) \ +{ \ + uint32_t t2,t3,w0,w1; \ + uint32_t a0,a1,a2,a3,a4,a5,a6,a7; \ +\ + ref -= ofs; \ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + UNPACK(a0,a1,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + w0 = LPC(ref+8); \ + UNPACK(a2,a3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + UNPACK(a4,a5,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + w0 = LPC(ref+16); \ + UNPACK(a6,a7,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ +} \ + do { \ + ref+=stride; \ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + UNPACK(t2,t3,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + OP(LP(dest+0),PACK(a0,a1,t2,t3)); \ + a0 = t2; a1 = t3; \ + w0 = LPC(ref+8); \ + UNPACK(t2,t3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ + OP(LP(dest+4),PACK(a2,a3,t2,t3)); \ + a2 = t2; a3 = t3; \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + UNPACK(t2,t3,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + OP(LP(dest+8),PACK(a4,a5,t2,t3)); \ + a4 = t2; a5 = t3; \ + w0 = LPC(ref+16); \ + UNPACK(t2,t3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ + OP(LP(dest+12),PACK(a6,a7,t2,t3)); \ + a6 = t2; a7 = t3; \ +} \ + dest+=stride; \ + } while(--height); \ +} + +#define DEFFUNC(op,rnd,xy,sz,OP_N,avgfunc) \ +static void op##_##rnd##_pixels##sz##_##xy (uint8_t * dest, const uint8_t * ref, \ + const ptrdiff_t stride, int height) \ +{ \ + switch((int)ref&3) { \ + case 0:OP_N##0(sz,rnd##_##avgfunc); return; \ + case 1:OP_N(1,sz,rnd##_##avgfunc); return; \ + case 2:OP_N(2,sz,rnd##_##avgfunc); return; \ + case 3:OP_N(3,sz,rnd##_##avgfunc); return; \ + } \ +} + +#define put_pixels8_c ff_put_rnd_pixels8_o +#define put_pixels16_c ff_put_rnd_pixels16_o +#define avg_pixels8_c ff_avg_rnd_pixels8_o +#define avg_pixels16_c ff_avg_rnd_pixels16_o +#define put_no_rnd_pixels8_c ff_put_rnd_pixels8_o +#define put_no_rnd_pixels16_c ff_put_rnd_pixels16_o +#define avg_no_rnd_pixels16_c ff_avg_rnd_pixels16_o + +#if CONFIG_H264QPEL + +#include "qpel.c" + +#endif + +av_cold void ff_dsputil_init_align(DSPContext *c, AVCodecContext *avctx) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + +#if CONFIG_H264QPEL + +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_sh4; \ + c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_sh4; \ + c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_sh4; \ + c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_sh4; \ + c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_sh4; \ + c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_sh4; \ + c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_sh4; \ + c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_sh4; \ + c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_sh4; \ + c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_sh4; \ + c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_sh4; \ + c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_sh4; \ + c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_sh4; \ + c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_sh4; \ + c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_sh4; \ + c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_sh4 + + dspfunc(put_qpel, 0, 16); + dspfunc(put_no_rnd_qpel, 0, 16); + + dspfunc(avg_qpel, 0, 16); + /* dspfunc(avg_no_rnd_qpel, 0, 16); */ + + dspfunc(put_qpel, 1, 8); + dspfunc(put_no_rnd_qpel, 1, 8); + + dspfunc(avg_qpel, 1, 8); + /* dspfunc(avg_no_rnd_qpel, 1, 8); */ + +#undef dspfunc + + c->put_mspel_pixels_tab[0]= put_mspel8_mc00_sh4; + c->put_mspel_pixels_tab[1]= put_mspel8_mc10_sh4; + c->put_mspel_pixels_tab[2]= put_mspel8_mc20_sh4; + c->put_mspel_pixels_tab[3]= put_mspel8_mc30_sh4; + c->put_mspel_pixels_tab[4]= put_mspel8_mc02_sh4; + c->put_mspel_pixels_tab[5]= put_mspel8_mc12_sh4; + c->put_mspel_pixels_tab[6]= put_mspel8_mc22_sh4; + c->put_mspel_pixels_tab[7]= put_mspel8_mc32_sh4; + + c->gmc1 = gmc1_c; + +#endif +} diff --git a/ffmpeg/libavcodec/sh4/dsputil_sh4.c b/ffmpeg/libavcodec/sh4/dsputil_sh4.c new file mode 100644 index 0000000..6e19fa0 --- /dev/null +++ b/ffmpeg/libavcodec/sh4/dsputil_sh4.c @@ -0,0 +1,108 @@ +/* + * sh4 dsputil + * + * Copyright (c) 2003 BERO + * + * 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 "libavutil/attributes.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "dsputil_sh4.h" +#include "sh4.h" + +static void memzero_align8(void *dst,size_t size) +{ + int fpscr; + fp_single_enter(fpscr); + dst = (char *)dst + size; + size /= 32; + __asm__ volatile ( + " fldi0 fr0\n" + " fldi0 fr1\n" + " fschg\n" // double + "1: \n" \ + " dt %1\n" + " fmov dr0,@-%0\n" + " fmov dr0,@-%0\n" + " fmov dr0,@-%0\n" + " bf.s 1b\n" + " fmov dr0,@-%0\n" + " fschg" //back to single + : "+r"(dst),"+r"(size) :: "memory" ); + fp_single_leave(fpscr); +} + +static void clear_blocks_sh4(int16_t *blocks) +{ + memzero_align8(blocks,sizeof(int16_t)*6*64); +} + +static void idct_put(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + ff_idct_sh4(block); + for(i=0;i<8;i++) { + dest[0] = cm[block[0]]; + dest[1] = cm[block[1]]; + dest[2] = cm[block[2]]; + dest[3] = cm[block[3]]; + dest[4] = cm[block[4]]; + dest[5] = cm[block[5]]; + dest[6] = cm[block[6]]; + dest[7] = cm[block[7]]; + dest+=line_size; + block+=8; + } +} +static void idct_add(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + ff_idct_sh4(block); + for(i=0;i<8;i++) { + dest[0] = cm[dest[0]+block[0]]; + dest[1] = cm[dest[1]+block[1]]; + dest[2] = cm[dest[2]+block[2]]; + dest[3] = cm[dest[3]+block[3]]; + dest[4] = cm[dest[4]+block[4]]; + dest[5] = cm[dest[5]+block[5]]; + dest[6] = cm[dest[6]+block[6]]; + dest[7] = cm[dest[7]+block[7]]; + dest+=line_size; + block+=8; + } +} + +av_cold void ff_dsputil_init_sh4(DSPContext *c, AVCodecContext *avctx) +{ + const int idct_algo= avctx->idct_algo; + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + ff_dsputil_init_align(c,avctx); + + if (!high_bit_depth) + c->clear_blocks = clear_blocks_sh4; + if (avctx->bits_per_raw_sample <= 8 && + (idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SH4)) { + c->idct_put = idct_put; + c->idct_add = idct_add; + c->idct = ff_idct_sh4; + c->idct_permutation_type= FF_NO_IDCT_PERM; + } +} diff --git a/ffmpeg/libavcodec/sh4/dsputil_sh4.h b/ffmpeg/libavcodec/sh4/dsputil_sh4.h new file mode 100644 index 0000000..bd97a5b --- /dev/null +++ b/ffmpeg/libavcodec/sh4/dsputil_sh4.h @@ -0,0 +1,34 @@ +/* + * 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 + */ + +#ifndef AVCODEC_SH4_DSPUTIL_SH4_H +#define AVCODEC_SH4_DSPUTIL_SH4_H + +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/hpeldsp.h" + +void ff_idct_sh4(int16_t *block); +void ff_dsputil_init_align(DSPContext* c, AVCodecContext *avctx); + +void ff_put_rnd_pixels8_o (uint8_t * dest, const uint8_t * ref, const int stride, int height); +void ff_put_rnd_pixels16_o(uint8_t * dest, const uint8_t * ref, const int stride, int height); +void ff_avg_rnd_pixels8_o (uint8_t * dest, const uint8_t * ref, const int stride, int height); +void ff_avg_rnd_pixels16_o(uint8_t * dest, const uint8_t * ref, const int stride, int height); + +#endif /* AVCODEC_SH4_DSPUTIL_SH4_H */ diff --git a/ffmpeg/libavcodec/sh4/h264chroma_init.c b/ffmpeg/libavcodec/sh4/h264chroma_init.c new file mode 100644 index 0000000..d15f0ae --- /dev/null +++ b/ffmpeg/libavcodec/sh4/h264chroma_init.c @@ -0,0 +1,132 @@ +/* + * aligned/packed access motion + * + * Copyright (c) 2001-2003 BERO + * + * 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 + +#include "libavutil/attributes.h" +#include "libavcodec/h264chroma.h" + +#define H264_CHROMA_MC(OPNAME, OP)\ +static void OPNAME ## h264_chroma_mc2_sh4(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){\ + const int A=(8-x)*(8-y);\ + const int B=( x)*(8-y);\ + const int C=(8-x)*( y);\ + const int D=( x)*( y);\ + \ + assert(x<8 && y<8 && x>=0 && y>=0);\ +\ + do {\ + int t0,t1,t2,t3; \ + uint8_t *s0 = src; \ + uint8_t *s1 = src+stride; \ + t0 = *s0++; t2 = *s1++; \ + t1 = *s0++; t3 = *s1++; \ + OP(dst[0], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[1], (A*t1 + B*t0 + C*t3 + D*t2));\ + dst+= stride;\ + src+= stride;\ + }while(--h);\ +}\ +\ +static void OPNAME ## h264_chroma_mc4_sh4(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){\ + const int A=(8-x)*(8-y);\ + const int B=( x)*(8-y);\ + const int C=(8-x)*( y);\ + const int D=( x)*( y);\ + \ + assert(x<8 && y<8 && x>=0 && y>=0);\ +\ + do {\ + int t0,t1,t2,t3; \ + uint8_t *s0 = src; \ + uint8_t *s1 = src+stride; \ + t0 = *s0++; t2 = *s1++; \ + t1 = *s0++; t3 = *s1++; \ + OP(dst[0], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[1], (A*t1 + B*t0 + C*t3 + D*t2));\ + t1 = *s0++; t3 = *s1++; \ + OP(dst[2], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[3], (A*t1 + B*t0 + C*t3 + D*t2));\ + dst+= stride;\ + src+= stride;\ + }while(--h);\ +}\ +\ +static void OPNAME ## h264_chroma_mc8_sh4(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){\ + const int A=(8-x)*(8-y);\ + const int B=( x)*(8-y);\ + const int C=(8-x)*( y);\ + const int D=( x)*( y);\ + \ + assert(x<8 && y<8 && x>=0 && y>=0);\ +\ + do {\ + int t0,t1,t2,t3; \ + uint8_t *s0 = src; \ + uint8_t *s1 = src+stride; \ + t0 = *s0++; t2 = *s1++; \ + t1 = *s0++; t3 = *s1++; \ + OP(dst[0], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[1], (A*t1 + B*t0 + C*t3 + D*t2));\ + t1 = *s0++; t3 = *s1++; \ + OP(dst[2], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[3], (A*t1 + B*t0 + C*t3 + D*t2));\ + t1 = *s0++; t3 = *s1++; \ + OP(dst[4], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[5], (A*t1 + B*t0 + C*t3 + D*t2));\ + t1 = *s0++; t3 = *s1++; \ + OP(dst[6], (A*t0 + B*t1 + C*t2 + D*t3));\ + t0 = *s0++; t2 = *s1++; \ + OP(dst[7], (A*t1 + B*t0 + C*t3 + D*t2));\ + dst+= stride;\ + src+= stride;\ + }while(--h);\ +} + +#define op_avg(a, b) a = (((a)+(((b) + 32)>>6)+1)>>1) +#define op_put(a, b) a = (((b) + 32)>>6) + +H264_CHROMA_MC(put_ , op_put) +H264_CHROMA_MC(avg_ , op_avg) +#undef op_avg +#undef op_put + +av_cold void ff_h264chroma_init_sh4(H264ChromaContext *c, int bit_depth) +{ + const int high_bit_depth = bit_depth > 8; + + if (!high_bit_depth) { + c->put_h264_chroma_pixels_tab[0]= put_h264_chroma_mc8_sh4; + c->put_h264_chroma_pixels_tab[1]= put_h264_chroma_mc4_sh4; + c->put_h264_chroma_pixels_tab[2]= put_h264_chroma_mc2_sh4; + c->avg_h264_chroma_pixels_tab[0]= avg_h264_chroma_mc8_sh4; + c->avg_h264_chroma_pixels_tab[1]= avg_h264_chroma_mc4_sh4; + c->avg_h264_chroma_pixels_tab[2]= avg_h264_chroma_mc2_sh4; + } +} diff --git a/ffmpeg/libavcodec/sh4/hpeldsp.c b/ffmpeg/libavcodec/sh4/hpeldsp.c new file mode 100644 index 0000000..b524003 --- /dev/null +++ b/ffmpeg/libavcodec/sh4/hpeldsp.c @@ -0,0 +1,347 @@ +/* + * aligned/packed access motion + * + * Copyright (c) 2001-2003 BERO + * + * 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 "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/bit_depth_template.c" // for BYTE_VEC32 +#include "dsputil_sh4.h" + + +#define LP(p) *(uint32_t*)(p) +#define LPC(p) *(const uint32_t*)(p) + + +#define UNPACK(ph,pl,tt0,tt1) do { \ + uint32_t t0,t1; t0=tt0;t1=tt1; \ + ph = ( (t0 & ~BYTE_VEC32(0x03))>>2) + ( (t1 & ~BYTE_VEC32(0x03))>>2); \ + pl = (t0 & BYTE_VEC32(0x03)) + (t1 & BYTE_VEC32(0x03)); } while(0) + +#define rnd_PACK(ph,pl,nph,npl) ph + nph + (((pl + npl + BYTE_VEC32(0x02))>>2) & BYTE_VEC32(0x03)) +#define no_rnd_PACK(ph,pl,nph,npl) ph + nph + (((pl + npl + BYTE_VEC32(0x01))>>2) & BYTE_VEC32(0x03)) + +/* little-endian */ +#define MERGE1(a,b,ofs) (ofs==0)?a:( ((a)>>(8*ofs))|((b)<<(32-8*ofs)) ) +#define MERGE2(a,b,ofs) (ofs==3)?b:( ((a)>>(8*(ofs+1)))|((b)<<(32-8*(ofs+1))) ) +/* big +#define MERGE1(a,b,ofs) (ofs==0)?a:( ((a)<<(8*ofs))|((b)>>(32-8*ofs)) ) +#define MERGE2(a,b,ofs) (ofs==3)?b:( ((a)<<(8+8*ofs))|((b)>>(32-8-8*ofs)) ) +*/ + + +#define put(d,s) d = s +#define avg(d,s) d = rnd_avg32(s,d) + +#define OP_C4(ofs) \ + ref-=ofs; \ + do { \ + OP(LP(dest),MERGE1(LPC(ref),LPC(ref+4),ofs)); \ + ref+=stride; \ + dest+=stride; \ + } while(--height) + +#define OP_C40() \ + do { \ + OP(LP(dest),LPC(ref)); \ + ref+=stride; \ + dest+=stride; \ + } while(--height) + + +#define OP put + +static void put_pixels4_c(uint8_t *dest,const uint8_t *ref, const int stride,int height) +{ + switch((int)ref&3){ + case 0: OP_C40(); return; + case 1: OP_C4(1); return; + case 2: OP_C4(2); return; + case 3: OP_C4(3); return; + } +} + +#undef OP +#define OP avg + +static void avg_pixels4_c(uint8_t *dest,const uint8_t *ref, const int stride,int height) +{ + switch((int)ref&3){ + case 0: OP_C40(); return; + case 1: OP_C4(1); return; + case 2: OP_C4(2); return; + case 3: OP_C4(3); return; + } +} + +#undef OP + +#define OP_C(ofs,sz,avg2) \ +{ \ + ref-=ofs; \ + do { \ + uint32_t t0,t1; \ + t0 = LPC(ref+0); \ + t1 = LPC(ref+4); \ + OP(LP(dest+0), MERGE1(t0,t1,ofs)); \ + t0 = LPC(ref+8); \ + OP(LP(dest+4), MERGE1(t1,t0,ofs)); \ +if (sz==16) { \ + t1 = LPC(ref+12); \ + OP(LP(dest+8), MERGE1(t0,t1,ofs)); \ + t0 = LPC(ref+16); \ + OP(LP(dest+12), MERGE1(t1,t0,ofs)); \ +} \ + ref+=stride; \ + dest+= stride; \ + } while(--height); \ +} + +/* aligned */ +#define OP_C0(sz,avg2) \ +{ \ + do { \ + OP(LP(dest+0), LPC(ref+0)); \ + OP(LP(dest+4), LPC(ref+4)); \ +if (sz==16) { \ + OP(LP(dest+8), LPC(ref+8)); \ + OP(LP(dest+12), LPC(ref+12)); \ +} \ + ref+=stride; \ + dest+= stride; \ + } while(--height); \ +} + +#define OP_X(ofs,sz,avg2) \ +{ \ + ref-=ofs; \ + do { \ + uint32_t t0,t1; \ + t0 = LPC(ref+0); \ + t1 = LPC(ref+4); \ + OP(LP(dest+0), avg2(MERGE1(t0,t1,ofs),MERGE2(t0,t1,ofs))); \ + t0 = LPC(ref+8); \ + OP(LP(dest+4), avg2(MERGE1(t1,t0,ofs),MERGE2(t1,t0,ofs))); \ +if (sz==16) { \ + t1 = LPC(ref+12); \ + OP(LP(dest+8), avg2(MERGE1(t0,t1,ofs),MERGE2(t0,t1,ofs))); \ + t0 = LPC(ref+16); \ + OP(LP(dest+12), avg2(MERGE1(t1,t0,ofs),MERGE2(t1,t0,ofs))); \ +} \ + ref+=stride; \ + dest+= stride; \ + } while(--height); \ +} + +/* aligned */ +#define OP_Y0(sz,avg2) \ +{ \ + uint32_t t0,t1,t2,t3,t; \ +\ + t0 = LPC(ref+0); \ + t1 = LPC(ref+4); \ +if (sz==16) { \ + t2 = LPC(ref+8); \ + t3 = LPC(ref+12); \ +} \ + do { \ + ref += stride; \ +\ + t = LPC(ref+0); \ + OP(LP(dest+0), avg2(t0,t)); t0 = t; \ + t = LPC(ref+4); \ + OP(LP(dest+4), avg2(t1,t)); t1 = t; \ +if (sz==16) { \ + t = LPC(ref+8); \ + OP(LP(dest+8), avg2(t2,t)); t2 = t; \ + t = LPC(ref+12); \ + OP(LP(dest+12), avg2(t3,t)); t3 = t; \ +} \ + dest+= stride; \ + } while(--height); \ +} + +#define OP_Y(ofs,sz,avg2) \ +{ \ + uint32_t t0,t1,t2,t3,t,w0,w1; \ +\ + ref-=ofs; \ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + t0 = MERGE1(w0,w1,ofs); \ + w0 = LPC(ref+8); \ + t1 = MERGE1(w1,w0,ofs); \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + t2 = MERGE1(w0,w1,ofs); \ + w0 = LPC(ref+16); \ + t3 = MERGE1(w1,w0,ofs); \ +} \ + do { \ + ref += stride; \ +\ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + t = MERGE1(w0,w1,ofs); \ + OP(LP(dest+0), avg2(t0,t)); t0 = t; \ + w0 = LPC(ref+8); \ + t = MERGE1(w1,w0,ofs); \ + OP(LP(dest+4), avg2(t1,t)); t1 = t; \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + t = MERGE1(w0,w1,ofs); \ + OP(LP(dest+8), avg2(t2,t)); t2 = t; \ + w0 = LPC(ref+16); \ + t = MERGE1(w1,w0,ofs); \ + OP(LP(dest+12), avg2(t3,t)); t3 = t; \ +} \ + dest+=stride; \ + } while(--height); \ +} + +#define OP_X0(sz,avg2) OP_X(0,sz,avg2) +#define OP_XY0(sz,PACK) OP_XY(0,sz,PACK) +#define OP_XY(ofs,sz,PACK) \ +{ \ + uint32_t t2,t3,w0,w1; \ + uint32_t a0,a1,a2,a3,a4,a5,a6,a7; \ +\ + ref -= ofs; \ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + UNPACK(a0,a1,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + w0 = LPC(ref+8); \ + UNPACK(a2,a3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + UNPACK(a4,a5,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + w0 = LPC(ref+16); \ + UNPACK(a6,a7,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ +} \ + do { \ + ref+=stride; \ + w0 = LPC(ref+0); \ + w1 = LPC(ref+4); \ + UNPACK(t2,t3,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + OP(LP(dest+0),PACK(a0,a1,t2,t3)); \ + a0 = t2; a1 = t3; \ + w0 = LPC(ref+8); \ + UNPACK(t2,t3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ + OP(LP(dest+4),PACK(a2,a3,t2,t3)); \ + a2 = t2; a3 = t3; \ +if (sz==16) { \ + w1 = LPC(ref+12); \ + UNPACK(t2,t3,MERGE1(w0,w1,ofs),MERGE2(w0,w1,ofs)); \ + OP(LP(dest+8),PACK(a4,a5,t2,t3)); \ + a4 = t2; a5 = t3; \ + w0 = LPC(ref+16); \ + UNPACK(t2,t3,MERGE1(w1,w0,ofs),MERGE2(w1,w0,ofs)); \ + OP(LP(dest+12),PACK(a6,a7,t2,t3)); \ + a6 = t2; a7 = t3; \ +} \ + dest+=stride; \ + } while(--height); \ +} + +#define DEFFUNC(prefix, op,rnd,xy,sz,OP_N,avgfunc) \ +prefix void op##_##rnd##_pixels##sz##_##xy (uint8_t * dest, const uint8_t * ref, \ + const int stride, int height) \ +{ \ + switch((int)ref&3) { \ + case 0:OP_N##0(sz,rnd##_##avgfunc); return; \ + case 1:OP_N(1,sz,rnd##_##avgfunc); return; \ + case 2:OP_N(2,sz,rnd##_##avgfunc); return; \ + case 3:OP_N(3,sz,rnd##_##avgfunc); return; \ + } \ +} + +#define OP put + +DEFFUNC( ,ff_put,rnd,o,8,OP_C,avg32) +DEFFUNC(static,put, rnd,x,8,OP_X,avg32) +DEFFUNC(static,put,no_rnd,x,8,OP_X,avg32) +DEFFUNC(static,put, rnd,y,8,OP_Y,avg32) +DEFFUNC(static,put,no_rnd,y,8,OP_Y,avg32) +DEFFUNC(static,put, rnd,xy,8,OP_XY,PACK) +DEFFUNC(static,put,no_rnd,xy,8,OP_XY,PACK) +DEFFUNC( ,ff_put,rnd,o,16,OP_C,avg32) +DEFFUNC(static,put, rnd,x,16,OP_X,avg32) +DEFFUNC(static,put,no_rnd,x,16,OP_X,avg32) +DEFFUNC(static,put, rnd,y,16,OP_Y,avg32) +DEFFUNC(static,put,no_rnd,y,16,OP_Y,avg32) +DEFFUNC(static,put, rnd,xy,16,OP_XY,PACK) +DEFFUNC(static,put,no_rnd,xy,16,OP_XY,PACK) + +#undef OP +#define OP avg + +DEFFUNC( ,ff_avg,rnd,o,8,OP_C,avg32) +DEFFUNC(static,avg, rnd,x,8,OP_X,avg32) +DEFFUNC(static,avg, rnd,y,8,OP_Y,avg32) +DEFFUNC(static,avg, rnd,xy,8,OP_XY,PACK) +DEFFUNC( ,ff_avg,rnd,o,16,OP_C,avg32) +DEFFUNC(static,avg, rnd,x,16,OP_X,avg32) +DEFFUNC(static,avg,no_rnd,x,16,OP_X,avg32) +DEFFUNC(static,avg, rnd,y,16,OP_Y,avg32) +DEFFUNC(static,avg,no_rnd,y,16,OP_Y,avg32) +DEFFUNC(static,avg, rnd,xy,16,OP_XY,PACK) +DEFFUNC(static,avg,no_rnd,xy,16,OP_XY,PACK) + +#undef OP + +#define ff_put_no_rnd_pixels8_o ff_put_rnd_pixels8_o +#define ff_put_no_rnd_pixels16_o ff_put_rnd_pixels16_o +#define ff_avg_no_rnd_pixels16_o ff_avg_rnd_pixels16_o + +void ff_hpeldsp_init_sh4(HpelDSPContext* c, int flags) +{ + c->put_pixels_tab[0][0] = ff_put_rnd_pixels16_o; + c->put_pixels_tab[0][1] = put_rnd_pixels16_x; + c->put_pixels_tab[0][2] = put_rnd_pixels16_y; + c->put_pixels_tab[0][3] = put_rnd_pixels16_xy; + c->put_pixels_tab[1][0] = ff_put_rnd_pixels8_o; + c->put_pixels_tab[1][1] = put_rnd_pixels8_x; + c->put_pixels_tab[1][2] = put_rnd_pixels8_y; + c->put_pixels_tab[1][3] = put_rnd_pixels8_xy; + + c->put_no_rnd_pixels_tab[0][0] = ff_put_no_rnd_pixels16_o; + c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x; + c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y; + c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy; + c->put_no_rnd_pixels_tab[1][0] = ff_put_no_rnd_pixels8_o; + c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x; + c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y; + c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy; + + c->avg_pixels_tab[0][0] = ff_avg_rnd_pixels16_o; + c->avg_pixels_tab[0][1] = avg_rnd_pixels16_x; + c->avg_pixels_tab[0][2] = avg_rnd_pixels16_y; + c->avg_pixels_tab[0][3] = avg_rnd_pixels16_xy; + c->avg_pixels_tab[1][0] = ff_avg_rnd_pixels8_o; + c->avg_pixels_tab[1][1] = avg_rnd_pixels8_x; + c->avg_pixels_tab[1][2] = avg_rnd_pixels8_y; + c->avg_pixels_tab[1][3] = avg_rnd_pixels8_xy; + + c->avg_no_rnd_pixels_tab[0] = ff_avg_no_rnd_pixels16_o; + c->avg_no_rnd_pixels_tab[1] = avg_no_rnd_pixels16_x; + c->avg_no_rnd_pixels_tab[2] = avg_no_rnd_pixels16_y; + c->avg_no_rnd_pixels_tab[3] = avg_no_rnd_pixels16_xy; +} diff --git a/ffmpeg/libavcodec/sh4/idct_sh4.c b/ffmpeg/libavcodec/sh4/idct_sh4.c new file mode 100644 index 0000000..d4e8711 --- /dev/null +++ b/ffmpeg/libavcodec/sh4/idct_sh4.c @@ -0,0 +1,210 @@ +/* + * idct for sh4 + * + * Copyright (c) 2001-2003 BERO + * + * 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 "dsputil_sh4.h" +#include "sh4.h" + +#define c1 1.38703984532214752434 /* sqrt(2)*cos(1*pi/16) */ +#define c2 1.30656296487637657577 /* sqrt(2)*cos(2*pi/16) */ +#define c3 1.17587560241935884520 /* sqrt(2)*cos(3*pi/16) */ +#define c4 1.00000000000000000000 /* sqrt(2)*cos(4*pi/16) */ +#define c5 0.78569495838710234903 /* sqrt(2)*cos(5*pi/16) */ +#define c6 0.54119610014619712324 /* sqrt(2)*cos(6*pi/16) */ +#define c7 0.27589937928294311353 /* sqrt(2)*cos(7*pi/16) */ + +static const float even_table[] __attribute__ ((aligned(8))) = { + c4, c4, c4, c4, + c2, c6,-c6,-c2, + c4,-c4,-c4, c4, + c6,-c2, c2,-c6 +}; + +static const float odd_table[] __attribute__ ((aligned(8))) = { + c1, c3, c5, c7, + c3,-c7,-c1,-c5, + c5,-c1, c7, c3, + c7,-c5, c3,-c1 +}; + +#undef c1 +#undef c2 +#undef c3 +#undef c4 +#undef c5 +#undef c6 +#undef c7 + +#define load_matrix(table) \ + do { \ + const float *t = table; \ + __asm__ volatile( \ + " fschg\n" \ + " fmov @%0+,xd0\n" \ + " fmov @%0+,xd2\n" \ + " fmov @%0+,xd4\n" \ + " fmov @%0+,xd6\n" \ + " fmov @%0+,xd8\n" \ + " fmov @%0+,xd10\n" \ + " fmov @%0+,xd12\n" \ + " fmov @%0+,xd14\n" \ + " fschg\n" \ + : "+r"(t) \ + ); \ + } while (0) + +#define ftrv() \ + __asm__ volatile("ftrv xmtrx,fv0" \ + : "+f"(fr0),"+f"(fr1),"+f"(fr2),"+f"(fr3)); + +#define DEFREG \ + register float fr0 __asm__("fr0"); \ + register float fr1 __asm__("fr1"); \ + register float fr2 __asm__("fr2"); \ + register float fr3 __asm__("fr3") + +#define DESCALE(x,n) (x)*(1.0f/(1<<(n))) + +/* this code work worse on gcc cvs. 3.2.3 work fine */ + + +//optimized + +void ff_idct_sh4(int16_t *block) +{ + DEFREG; + + int i; + float tblock[8*8],*fblock; + int ofs1,ofs2,ofs3; + int fpscr; + + fp_single_enter(fpscr); + + /* row */ + + /* even part */ + load_matrix(even_table); + + fblock = tblock+4; + i = 8; + do { + fr0 = block[0]; + fr1 = block[2]; + fr2 = block[4]; + fr3 = block[6]; + block+=8; + ftrv(); + *--fblock = fr3; + *--fblock = fr2; + *--fblock = fr1; + *--fblock = fr0; + fblock+=8+4; + } while(--i); + block-=8*8; + fblock-=8*8+4; + + load_matrix(odd_table); + + i = 8; + + do { + float t0,t1,t2,t3; + fr0 = block[1]; + fr1 = block[3]; + fr2 = block[5]; + fr3 = block[7]; + block+=8; + ftrv(); + t0 = *fblock++; + t1 = *fblock++; + t2 = *fblock++; + t3 = *fblock++; + fblock+=4; + *--fblock = t0 - fr0; + *--fblock = t1 - fr1; + *--fblock = t2 - fr2; + *--fblock = t3 - fr3; + *--fblock = t3 + fr3; + *--fblock = t2 + fr2; + *--fblock = t1 + fr1; + *--fblock = t0 + fr0; + fblock+=8; + } while(--i); + block-=8*8; + fblock-=8*8; + + /* col */ + + /* even part */ + load_matrix(even_table); + + ofs1 = sizeof(float)*2*8; + ofs2 = sizeof(float)*4*8; + ofs3 = sizeof(float)*6*8; + + i = 8; + +#define OA(fblock,ofs) *(float*)((char*)fblock + ofs) + + do { + fr0 = OA(fblock, 0); + fr1 = OA(fblock,ofs1); + fr2 = OA(fblock,ofs2); + fr3 = OA(fblock,ofs3); + ftrv(); + OA(fblock,0 ) = fr0; + OA(fblock,ofs1) = fr1; + OA(fblock,ofs2) = fr2; + OA(fblock,ofs3) = fr3; + fblock++; + } while(--i); + fblock-=8; + + load_matrix(odd_table); + + i=8; + do { + float t0,t1,t2,t3; + t0 = OA(fblock, 0); /* [8*0] */ + t1 = OA(fblock,ofs1); /* [8*2] */ + t2 = OA(fblock,ofs2); /* [8*4] */ + t3 = OA(fblock,ofs3); /* [8*6] */ + fblock+=8; + fr0 = OA(fblock, 0); /* [8*1] */ + fr1 = OA(fblock,ofs1); /* [8*3] */ + fr2 = OA(fblock,ofs2); /* [8*5] */ + fr3 = OA(fblock,ofs3); /* [8*7] */ + fblock+=-8+1; + ftrv(); + block[8*0] = DESCALE(t0 + fr0,3); + block[8*7] = DESCALE(t0 - fr0,3); + block[8*1] = DESCALE(t1 + fr1,3); + block[8*6] = DESCALE(t1 - fr1,3); + block[8*2] = DESCALE(t2 + fr2,3); + block[8*5] = DESCALE(t2 - fr2,3); + block[8*3] = DESCALE(t3 + fr3,3); + block[8*4] = DESCALE(t3 - fr3,3); + block++; + } while(--i); + + fp_single_leave(fpscr); +} diff --git a/ffmpeg/libavcodec/sh4/qpel.c b/ffmpeg/libavcodec/sh4/qpel.c new file mode 100644 index 0000000..1a5a4cd --- /dev/null +++ b/ffmpeg/libavcodec/sh4/qpel.c @@ -0,0 +1,862 @@ +/* + * This is optimized for sh, which have post increment addressing (*p++). + * Some CPU may be index (p[n]) faster than post increment (*p++). + * + * copyright (c) 2001-2003 BERO + * + * 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 "libavutil/common.h" +#include "libavcodec/copy_block.h" +#include "libavcodec/rnd_avg.h" + +#define PIXOP2(OPNAME, OP) \ +\ +static inline void OPNAME ## _pixels4_l2_aligned(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),rnd_avg32(LPC(src1 ),LPC(src2 )) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _pixels4_l2_aligned2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),rnd_avg32(AV_RN32(src1 ),LPC(src2 )) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _no_rnd_pixels16_l2_aligned2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),no_rnd_avg32(AV_RN32(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),no_rnd_avg32(AV_RN32(src1+4),LPC(src2+4)) ); \ + OP(LP(dst+8),no_rnd_avg32(AV_RN32(src1+8),LPC(src2+8)) ); \ + OP(LP(dst+12),no_rnd_avg32(AV_RN32(src1+12),LPC(src2+12)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _pixels16_l2_aligned2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),rnd_avg32(AV_RN32(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),rnd_avg32(AV_RN32(src1+4),LPC(src2+4)) ); \ + OP(LP(dst+8),rnd_avg32(AV_RN32(src1+8),LPC(src2+8)) ); \ + OP(LP(dst+12),rnd_avg32(AV_RN32(src1+12),LPC(src2+12)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _no_rnd_pixels8_l2_aligned2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do { /* onlye src2 aligned */\ + OP(LP(dst ),no_rnd_avg32(AV_RN32(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),no_rnd_avg32(AV_RN32(src1+4),LPC(src2+4)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _pixels8_l2_aligned2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),rnd_avg32(AV_RN32(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),rnd_avg32(AV_RN32(src1+4),LPC(src2+4)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _no_rnd_pixels8_l2_aligned(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),no_rnd_avg32(LPC(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),no_rnd_avg32(LPC(src1+4),LPC(src2+4)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _pixels8_l2_aligned(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),rnd_avg32(LPC(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),rnd_avg32(LPC(src1+4),LPC(src2+4)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _no_rnd_pixels16_l2_aligned(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),no_rnd_avg32(LPC(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),no_rnd_avg32(LPC(src1+4),LPC(src2+4)) ); \ + OP(LP(dst+8),no_rnd_avg32(LPC(src1+8),LPC(src2+8)) ); \ + OP(LP(dst+12),no_rnd_avg32(LPC(src1+12),LPC(src2+12)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _pixels16_l2_aligned(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{\ + do {\ + OP(LP(dst ),rnd_avg32(LPC(src1 ),LPC(src2 )) ); \ + OP(LP(dst+4),rnd_avg32(LPC(src1+4),LPC(src2+4)) ); \ + OP(LP(dst+8),rnd_avg32(LPC(src1+8),LPC(src2+8)) ); \ + OP(LP(dst+12),rnd_avg32(LPC(src1+12),LPC(src2+12)) ); \ + src1+=src_stride1; \ + src2+=src_stride2; \ + dst+=dst_stride; \ + } while(--h); \ +}\ +\ +static inline void OPNAME ## _no_rnd_pixels16_l2_aligned1(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{ OPNAME ## _no_rnd_pixels16_l2_aligned2(dst,src2,src1,dst_stride,src_stride2,src_stride1,h); } \ +\ +static inline void OPNAME ## _pixels16_l2_aligned1(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{ OPNAME ## _pixels16_l2_aligned2(dst,src2,src1,dst_stride,src_stride2,src_stride1,h); } \ +\ +static inline void OPNAME ## _no_rnd_pixels8_l2_aligned1(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{ OPNAME ## _no_rnd_pixels8_l2_aligned2(dst,src2,src1,dst_stride,src_stride2,src_stride1,h); } \ +\ +static inline void OPNAME ## _pixels8_l2_aligned1(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2, int h) \ +{ OPNAME ## _pixels8_l2_aligned2(dst,src2,src1,dst_stride,src_stride2,src_stride1,h); } \ +\ +static inline void OPNAME ## _pixels8_l4_aligned(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,LPC(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+4),rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _no_rnd_pixels8_l4_aligned(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,LPC(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+4),no_rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _pixels8_l4_aligned0(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; /* src1 only not aligned */\ + UNPACK(a0,a1,AV_RN32(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+4),rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _no_rnd_pixels8_l4_aligned0(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,AV_RN32(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+4),no_rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _pixels16_l4_aligned(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,LPC(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+8),LPC(src2+8)); \ + UNPACK(a2,a3,LPC(src3+8),LPC(src4+8)); \ + OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+12),LPC(src2+12)); \ + UNPACK(a2,a3,LPC(src3+12),LPC(src4+12)); \ + OP(LP(dst+12),rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _no_rnd_pixels16_l4_aligned(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,LPC(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+4),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+8),LPC(src2+8)); \ + UNPACK(a2,a3,LPC(src3+8),LPC(src4+8)); \ + OP(LP(dst+8),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,LPC(src1+12),LPC(src2+12)); \ + UNPACK(a2,a3,LPC(src3+12),LPC(src4+12)); \ + OP(LP(dst+12),no_rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _pixels16_l4_aligned0(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { /* src1 is unaligned */\ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,AV_RN32(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+8),LPC(src2+8)); \ + UNPACK(a2,a3,LPC(src3+8),LPC(src4+8)); \ + OP(LP(dst+8),rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+12),LPC(src2+12)); \ + UNPACK(a2,a3,LPC(src3+12),LPC(src4+12)); \ + OP(LP(dst+12),rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ +static inline void OPNAME ## _no_rnd_pixels16_l4_aligned0(uint8_t *dst, const uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *src4,int dst_stride, int src_stride1, int src_stride2,int src_stride3,int src_stride4, int h){\ + do { \ + uint32_t a0,a1,a2,a3; \ + UNPACK(a0,a1,AV_RN32(src1),LPC(src2)); \ + UNPACK(a2,a3,LPC(src3),LPC(src4)); \ + OP(LP(dst),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+4),LPC(src2+4)); \ + UNPACK(a2,a3,LPC(src3+4),LPC(src4+4)); \ + OP(LP(dst+4),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+8),LPC(src2+8)); \ + UNPACK(a2,a3,LPC(src3+8),LPC(src4+8)); \ + OP(LP(dst+8),no_rnd_PACK(a0,a1,a2,a3)); \ + UNPACK(a0,a1,AV_RN32(src1+12),LPC(src2+12)); \ + UNPACK(a2,a3,LPC(src3+12),LPC(src4+12)); \ + OP(LP(dst+12),no_rnd_PACK(a0,a1,a2,a3)); \ + src1+=src_stride1;\ + src2+=src_stride2;\ + src3+=src_stride3;\ + src4+=src_stride4;\ + dst+=dst_stride;\ + } while(--h); \ +} \ +\ + +#define op_avg(a, b) a = rnd_avg32(a,b) +#define op_put(a, b) a = b + +PIXOP2(avg, op_avg) +PIXOP2(put, op_put) +#undef op_avg +#undef op_put + +#define avg2(a,b) ((a+b+1)>>1) +#define avg4(a,b,c,d) ((a+b+c+d+2)>>2) + + +static void gmc1_c(uint8_t *dst, uint8_t *src, int stride, int h, int x16, int y16, int rounder) +{ + const int A=(16-x16)*(16-y16); + const int B=( x16)*(16-y16); + const int C=(16-x16)*( y16); + const int D=( x16)*( y16); + + do { + int t0,t1,t2,t3; + uint8_t *s0 = src; + uint8_t *s1 = src+stride; + t0 = *s0++; t2 = *s1++; + t1 = *s0++; t3 = *s1++; + dst[0]= (A*t0 + B*t1 + C*t2 + D*t3 + rounder)>>8; + t0 = *s0++; t2 = *s1++; + dst[1]= (A*t1 + B*t0 + C*t3 + D*t2 + rounder)>>8; + t1 = *s0++; t3 = *s1++; + dst[2]= (A*t0 + B*t1 + C*t2 + D*t3 + rounder)>>8; + t0 = *s0++; t2 = *s1++; + dst[3]= (A*t1 + B*t0 + C*t3 + D*t2 + rounder)>>8; + t1 = *s0++; t3 = *s1++; + dst[4]= (A*t0 + B*t1 + C*t2 + D*t3 + rounder)>>8; + t0 = *s0++; t2 = *s1++; + dst[5]= (A*t1 + B*t0 + C*t3 + D*t2 + rounder)>>8; + t1 = *s0++; t3 = *s1++; + dst[6]= (A*t0 + B*t1 + C*t2 + D*t3 + rounder)>>8; + t0 = *s0++; t2 = *s1++; + dst[7]= (A*t1 + B*t0 + C*t3 + D*t2 + rounder)>>8; + dst+= stride; + src+= stride; + }while(--h); +} + +#define QPEL_MC(r, OPNAME, RND, OP) \ +static void OPNAME ## mpeg4_qpel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + do {\ + uint8_t *s = src; \ + int src0,src1,src2,src3,src4,src5,src6,src7,src8;\ + src0= *s++;\ + src1= *s++;\ + src2= *s++;\ + src3= *s++;\ + src4= *s++;\ + OP(dst[0], (src0+src1)*20 - (src0+src2)*6 + (src1+src3)*3 - (src2+src4));\ + src5= *s++;\ + OP(dst[1], (src1+src2)*20 - (src0+src3)*6 + (src0+src4)*3 - (src1+src5));\ + src6= *s++;\ + OP(dst[2], (src2+src3)*20 - (src1+src4)*6 + (src0+src5)*3 - (src0+src6));\ + src7= *s++;\ + OP(dst[3], (src3+src4)*20 - (src2+src5)*6 + (src1+src6)*3 - (src0+src7));\ + src8= *s++;\ + OP(dst[4], (src4+src5)*20 - (src3+src6)*6 + (src2+src7)*3 - (src1+src8));\ + OP(dst[5], (src5+src6)*20 - (src4+src7)*6 + (src3+src8)*3 - (src2+src8));\ + OP(dst[6], (src6+src7)*20 - (src5+src8)*6 + (src4+src8)*3 - (src3+src7));\ + OP(dst[7], (src7+src8)*20 - (src6+src8)*6 + (src5+src7)*3 - (src4+src6));\ + dst+=dstStride;\ + src+=srcStride;\ + }while(--h);\ +}\ +\ +static void OPNAME ## mpeg4_qpel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int w=8;\ + do{\ + uint8_t *s = src, *d=dst;\ + int src0,src1,src2,src3,src4,src5,src6,src7,src8;\ + src0 = *s; s+=srcStride; \ + src1 = *s; s+=srcStride; \ + src2 = *s; s+=srcStride; \ + src3 = *s; s+=srcStride; \ + src4 = *s; s+=srcStride; \ + OP(*d, (src0+src1)*20 - (src0+src2)*6 + (src1+src3)*3 - (src2+src4));d+=dstStride;\ + src5 = *s; s+=srcStride; \ + OP(*d, (src1+src2)*20 - (src0+src3)*6 + (src0+src4)*3 - (src1+src5));d+=dstStride;\ + src6 = *s; s+=srcStride; \ + OP(*d, (src2+src3)*20 - (src1+src4)*6 + (src0+src5)*3 - (src0+src6));d+=dstStride;\ + src7 = *s; s+=srcStride; \ + OP(*d, (src3+src4)*20 - (src2+src5)*6 + (src1+src6)*3 - (src0+src7));d+=dstStride;\ + src8 = *s; \ + OP(*d, (src4+src5)*20 - (src3+src6)*6 + (src2+src7)*3 - (src1+src8));d+=dstStride;\ + OP(*d, (src5+src6)*20 - (src4+src7)*6 + (src3+src8)*3 - (src2+src8));d+=dstStride;\ + OP(*d, (src6+src7)*20 - (src5+src8)*6 + (src4+src8)*3 - (src3+src7));d+=dstStride;\ + OP(*d, (src7+src8)*20 - (src6+src8)*6 + (src5+src7)*3 - (src4+src6));\ + dst++;\ + src++;\ + }while(--w);\ +}\ +\ +static void OPNAME ## mpeg4_qpel16_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + do {\ + uint8_t *s = src;\ + int src0,src1,src2,src3,src4,src5,src6,src7,src8;\ + int src9,src10,src11,src12,src13,src14,src15,src16;\ + src0= *s++;\ + src1= *s++;\ + src2= *s++;\ + src3= *s++;\ + src4= *s++;\ + OP(dst[ 0], (src0 +src1 )*20 - (src0 +src2 )*6 + (src1 +src3 )*3 - (src2 +src4 ));\ + src5= *s++;\ + OP(dst[ 1], (src1 +src2 )*20 - (src0 +src3 )*6 + (src0 +src4 )*3 - (src1 +src5 ));\ + src6= *s++;\ + OP(dst[ 2], (src2 +src3 )*20 - (src1 +src4 )*6 + (src0 +src5 )*3 - (src0 +src6 ));\ + src7= *s++;\ + OP(dst[ 3], (src3 +src4 )*20 - (src2 +src5 )*6 + (src1 +src6 )*3 - (src0 +src7 ));\ + src8= *s++;\ + OP(dst[ 4], (src4 +src5 )*20 - (src3 +src6 )*6 + (src2 +src7 )*3 - (src1 +src8 ));\ + src9= *s++;\ + OP(dst[ 5], (src5 +src6 )*20 - (src4 +src7 )*6 + (src3 +src8 )*3 - (src2 +src9 ));\ + src10= *s++;\ + OP(dst[ 6], (src6 +src7 )*20 - (src5 +src8 )*6 + (src4 +src9 )*3 - (src3 +src10));\ + src11= *s++;\ + OP(dst[ 7], (src7 +src8 )*20 - (src6 +src9 )*6 + (src5 +src10)*3 - (src4 +src11));\ + src12= *s++;\ + OP(dst[ 8], (src8 +src9 )*20 - (src7 +src10)*6 + (src6 +src11)*3 - (src5 +src12));\ + src13= *s++;\ + OP(dst[ 9], (src9 +src10)*20 - (src8 +src11)*6 + (src7 +src12)*3 - (src6 +src13));\ + src14= *s++;\ + OP(dst[10], (src10+src11)*20 - (src9 +src12)*6 + (src8 +src13)*3 - (src7 +src14));\ + src15= *s++;\ + OP(dst[11], (src11+src12)*20 - (src10+src13)*6 + (src9 +src14)*3 - (src8 +src15));\ + src16= *s++;\ + OP(dst[12], (src12+src13)*20 - (src11+src14)*6 + (src10+src15)*3 - (src9 +src16));\ + OP(dst[13], (src13+src14)*20 - (src12+src15)*6 + (src11+src16)*3 - (src10+src16));\ + OP(dst[14], (src14+src15)*20 - (src13+src16)*6 + (src12+src16)*3 - (src11+src15));\ + OP(dst[15], (src15+src16)*20 - (src14+src16)*6 + (src13+src15)*3 - (src12+src14));\ + dst+=dstStride;\ + src+=srcStride;\ + }while(--h);\ +}\ +\ +static void OPNAME ## mpeg4_qpel16_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;\ + int w=16;\ + do {\ + uint8_t *s = src, *d=dst;\ + int src0,src1,src2,src3,src4,src5,src6,src7,src8;\ + int src9,src10,src11,src12,src13,src14,src15,src16;\ + src0 = *s; s+=srcStride; \ + src1 = *s; s+=srcStride; \ + src2 = *s; s+=srcStride; \ + src3 = *s; s+=srcStride; \ + src4 = *s; s+=srcStride; \ + OP(*d, (src0 +src1 )*20 - (src0 +src2 )*6 + (src1 +src3 )*3 - (src2 +src4 ));d+=dstStride;\ + src5 = *s; s+=srcStride; \ + OP(*d, (src1 +src2 )*20 - (src0 +src3 )*6 + (src0 +src4 )*3 - (src1 +src5 ));d+=dstStride;\ + src6 = *s; s+=srcStride; \ + OP(*d, (src2 +src3 )*20 - (src1 +src4 )*6 + (src0 +src5 )*3 - (src0 +src6 ));d+=dstStride;\ + src7 = *s; s+=srcStride; \ + OP(*d, (src3 +src4 )*20 - (src2 +src5 )*6 + (src1 +src6 )*3 - (src0 +src7 ));d+=dstStride;\ + src8 = *s; s+=srcStride; \ + OP(*d, (src4 +src5 )*20 - (src3 +src6 )*6 + (src2 +src7 )*3 - (src1 +src8 ));d+=dstStride;\ + src9 = *s; s+=srcStride; \ + OP(*d, (src5 +src6 )*20 - (src4 +src7 )*6 + (src3 +src8 )*3 - (src2 +src9 ));d+=dstStride;\ + src10 = *s; s+=srcStride; \ + OP(*d, (src6 +src7 )*20 - (src5 +src8 )*6 + (src4 +src9 )*3 - (src3 +src10));d+=dstStride;\ + src11 = *s; s+=srcStride; \ + OP(*d, (src7 +src8 )*20 - (src6 +src9 )*6 + (src5 +src10)*3 - (src4 +src11));d+=dstStride;\ + src12 = *s; s+=srcStride; \ + OP(*d, (src8 +src9 )*20 - (src7 +src10)*6 + (src6 +src11)*3 - (src5 +src12));d+=dstStride;\ + src13 = *s; s+=srcStride; \ + OP(*d, (src9 +src10)*20 - (src8 +src11)*6 + (src7 +src12)*3 - (src6 +src13));d+=dstStride;\ + src14 = *s; s+=srcStride; \ + OP(*d, (src10+src11)*20 - (src9 +src12)*6 + (src8 +src13)*3 - (src7 +src14));d+=dstStride;\ + src15 = *s; s+=srcStride; \ + OP(*d, (src11+src12)*20 - (src10+src13)*6 + (src9 +src14)*3 - (src8 +src15));d+=dstStride;\ + src16 = *s; \ + OP(*d, (src12+src13)*20 - (src11+src14)*6 + (src10+src15)*3 - (src9 +src16));d+=dstStride;\ + OP(*d, (src13+src14)*20 - (src12+src15)*6 + (src11+src16)*3 - (src10+src16));d+=dstStride;\ + OP(*d, (src14+src15)*20 - (src13+src16)*6 + (src12+src16)*3 - (src11+src15));d+=dstStride;\ + OP(*d, (src15+src16)*20 - (src14+src16)*6 + (src13+src15)*3 - (src12+src14));\ + dst++;\ + src++;\ + }while(--w);\ +}\ +\ +static void OPNAME ## qpel8_mc00_sh4 (uint8_t *dst, uint8_t *src, int stride){\ + OPNAME ## pixels8_c(dst, src, stride, 8);\ +}\ +\ +static void OPNAME ## qpel8_mc10_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t half[64];\ + put ## RND ## mpeg4_qpel8_h_lowpass(half, src, 8, stride, 8);\ + OPNAME ## pixels8_l2_aligned2(dst, src, half, stride, stride, 8, 8);\ +}\ +\ +static void OPNAME ## qpel8_mc20_sh4(uint8_t *dst, uint8_t *src, int stride){\ + OPNAME ## mpeg4_qpel8_h_lowpass(dst, src, stride, stride, 8);\ +}\ +\ +static void OPNAME ## qpel8_mc30_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t half[64];\ + put ## RND ## mpeg4_qpel8_h_lowpass(half, src, 8, stride, 8);\ + OPNAME ## pixels8_l2_aligned2(dst, src+1, half, stride, stride, 8, 8);\ +}\ +\ +static void OPNAME ## qpel8_mc01_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t half[64];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(half, full, 8, 16);\ + OPNAME ## pixels8_l2_aligned(dst, full, half, stride, 16, 8, 8);\ +}\ +\ +static void OPNAME ## qpel8_mc02_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + copy_block9(full, src, 16, stride, 9);\ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, full, stride, 16);\ +}\ +\ +static void OPNAME ## qpel8_mc03_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t half[64];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(half, full, 8, 16);\ + OPNAME ## pixels8_l2_aligned(dst, full+16, half, stride, 16, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc11_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t halfH[72];\ + uint8_t halfHV[64];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\ + put ## RND ## pixels8_l2_aligned(halfH, halfH, full, 8, 8, 16, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\ + OPNAME ## pixels8_l2_aligned(dst, halfH, halfHV, stride, 8, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc31_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t halfH[72];\ + uint8_t halfHV[64];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\ + put ## RND ## pixels8_l2_aligned1(halfH, halfH, full+1, 8, 8, 16, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\ + OPNAME ## pixels8_l2_aligned(dst, halfH, halfHV, stride, 8, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc13_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t halfH[72];\ + uint8_t halfHV[64];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\ + put ## RND ## pixels8_l2_aligned(halfH, halfH, full, 8, 8, 16, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\ + OPNAME ## pixels8_l2_aligned(dst, halfH+8, halfHV, stride, 8, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc33_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t halfH[72];\ + uint8_t halfHV[64];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\ + put ## RND ## pixels8_l2_aligned1(halfH, halfH, full+1, 8, 8, 16, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\ + OPNAME ## pixels8_l2_aligned(dst, halfH+8, halfHV, stride, 8, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc21_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t halfH[72];\ + uint8_t halfHV[64];\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\ + OPNAME ## pixels8_l2_aligned(dst, halfH, halfHV, stride, 8, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc23_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t halfH[72];\ + uint8_t halfHV[64];\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9);\ + put ## RND ## mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);\ + OPNAME ## pixels8_l2_aligned(dst, halfH+8, halfHV, stride, 8, 8, 8);\ +}\ +static void OPNAME ## qpel8_mc12_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t halfH[72];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\ + put ## RND ## pixels8_l2_aligned(halfH, halfH, full, 8, 8, 16, 9);\ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);\ +}\ +static void OPNAME ## qpel8_mc32_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[16*9];\ + uint8_t halfH[72];\ + copy_block9(full, src, 16, stride, 9);\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);\ + put ## RND ## pixels8_l2_aligned1(halfH, halfH, full+1, 8, 8, 16, 9);\ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);\ +}\ +static void OPNAME ## qpel8_mc22_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t halfH[72];\ + put ## RND ## mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9);\ + OPNAME ## mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);\ +}\ +static void OPNAME ## qpel16_mc00_sh4 (uint8_t *dst, uint8_t *src, int stride){\ + OPNAME ## pixels16_c(dst, src, stride, 16);\ +}\ +\ +static void OPNAME ## qpel16_mc10_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t half[256];\ + put ## RND ## mpeg4_qpel16_h_lowpass(half, src, 16, stride, 16);\ + OPNAME ## pixels16_l2_aligned2(dst, src, half, stride, stride, 16, 16);\ +}\ +\ +static void OPNAME ## qpel16_mc20_sh4(uint8_t *dst, uint8_t *src, int stride){\ + OPNAME ## mpeg4_qpel16_h_lowpass(dst, src, stride, stride, 16);\ +}\ +\ +static void OPNAME ## qpel16_mc30_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t half[256];\ + put ## RND ## mpeg4_qpel16_h_lowpass(half, src, 16, stride, 16);\ + OPNAME ## pixels16_l2_aligned2(dst, src+1, half, stride, stride, 16, 16);\ +}\ +\ +static void OPNAME ## qpel16_mc01_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t half[256];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(half, full, 16, 24);\ + OPNAME ## pixels16_l2_aligned(dst, full, half, stride, 24, 16, 16);\ +}\ +\ +static void OPNAME ## qpel16_mc02_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + copy_block17(full, src, 24, stride, 17);\ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, full, stride, 24);\ +}\ +\ +static void OPNAME ## qpel16_mc03_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t half[256];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(half, full, 16, 24);\ + OPNAME ## pixels16_l2_aligned(dst, full+24, half, stride, 24, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc11_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t halfH[272];\ + uint8_t halfHV[256];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\ + put ## RND ## pixels16_l2_aligned(halfH, halfH, full, 16, 16, 24, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\ + OPNAME ## pixels16_l2_aligned(dst, halfH, halfHV, stride, 16, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc31_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t halfH[272];\ + uint8_t halfHV[256];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\ + put ## RND ## pixels16_l2_aligned1(halfH, halfH, full+1, 16, 16, 24, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\ + OPNAME ## pixels16_l2_aligned(dst, halfH, halfHV, stride, 16, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc13_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t halfH[272];\ + uint8_t halfHV[256];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\ + put ## RND ## pixels16_l2_aligned(halfH, halfH, full, 16, 16, 24, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\ + OPNAME ## pixels16_l2_aligned(dst, halfH+16, halfHV, stride, 16, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc33_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t halfH[272];\ + uint8_t halfHV[256];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\ + put ## RND ## pixels16_l2_aligned1(halfH, halfH, full+1, 16, 16, 24, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\ + OPNAME ## pixels16_l2_aligned(dst, halfH+16, halfHV, stride, 16, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc21_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t halfH[272];\ + uint8_t halfHV[256];\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\ + OPNAME ## pixels16_l2_aligned(dst, halfH, halfHV, stride, 16, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc23_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t halfH[272];\ + uint8_t halfHV[256];\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17);\ + put ## RND ## mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);\ + OPNAME ## pixels16_l2_aligned(dst, halfH+16, halfHV, stride, 16, 16, 16);\ +}\ +static void OPNAME ## qpel16_mc12_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t halfH[272];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\ + put ## RND ## pixels16_l2_aligned(halfH, halfH, full, 16, 16, 24, 17);\ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);\ +}\ +static void OPNAME ## qpel16_mc32_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t full[24*17];\ + uint8_t halfH[272];\ + copy_block17(full, src, 24, stride, 17);\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);\ + put ## RND ## pixels16_l2_aligned1(halfH, halfH, full+1, 16, 16, 24, 17);\ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);\ +}\ +static void OPNAME ## qpel16_mc22_sh4(uint8_t *dst, uint8_t *src, int stride){\ + uint8_t halfH[272];\ + put ## RND ## mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17);\ + OPNAME ## mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);\ +} + +#define op_avg(a, b) a = (((a)+cm[((b) + 16)>>5]+1)>>1) +#define op_avg_no_rnd(a, b) a = (((a)+cm[((b) + 15)>>5])>>1) +#define op_put(a, b) a = cm[((b) + 16)>>5] +#define op_put_no_rnd(a, b) a = cm[((b) + 15)>>5] + +QPEL_MC(0, put_ , _ , op_put) +QPEL_MC(1, put_no_rnd_, _no_rnd_, op_put_no_rnd) +QPEL_MC(0, avg_ , _ , op_avg) +//QPEL_MC(1, avg_no_rnd , _ , op_avg) +#undef op_avg +#undef op_avg_no_rnd +#undef op_put +#undef op_put_no_rnd + +static void wmv2_mspel8_h_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + do{ + int src_1,src0,src1,src2,src3,src4,src5,src6,src7,src8,src9; + uint8_t *s = src; + src_1 = s[-1]; + src0 = *s++; + src1 = *s++; + src2 = *s++; + dst[0]= cm[(9*(src0 + src1) - (src_1 + src2) + 8)>>4]; + src3 = *s++; + dst[1]= cm[(9*(src1 + src2) - (src0 + src3) + 8)>>4]; + src4 = *s++; + dst[2]= cm[(9*(src2 + src3) - (src1 + src4) + 8)>>4]; + src5 = *s++; + dst[3]= cm[(9*(src3 + src4) - (src2 + src5) + 8)>>4]; + src6 = *s++; + dst[4]= cm[(9*(src4 + src5) - (src3 + src6) + 8)>>4]; + src7 = *s++; + dst[5]= cm[(9*(src5 + src6) - (src4 + src7) + 8)>>4]; + src8 = *s++; + dst[6]= cm[(9*(src6 + src7) - (src5 + src8) + 8)>>4]; + src9 = *s++; + dst[7]= cm[(9*(src7 + src8) - (src6 + src9) + 8)>>4]; + dst+=dstStride; + src+=srcStride; + }while(--h); +} + +static void wmv2_mspel8_v_lowpass(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int w){ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + do{ + int src_1,src0,src1,src2,src3,src4,src5,src6,src7,src8,src9; + uint8_t *s = src,*d = dst; + src_1 = *(s-srcStride); + src0 = *s; s+=srcStride; + src1 = *s; s+=srcStride; + src2 = *s; s+=srcStride; + *d= cm[(9*(src0 + src1) - (src_1 + src2) + 8)>>4]; d+=dstStride; + src3 = *s; s+=srcStride; + *d= cm[(9*(src1 + src2) - (src0 + src3) + 8)>>4]; d+=dstStride; + src4 = *s; s+=srcStride; + *d= cm[(9*(src2 + src3) - (src1 + src4) + 8)>>4]; d+=dstStride; + src5 = *s; s+=srcStride; + *d= cm[(9*(src3 + src4) - (src2 + src5) + 8)>>4]; d+=dstStride; + src6 = *s; s+=srcStride; + *d= cm[(9*(src4 + src5) - (src3 + src6) + 8)>>4]; d+=dstStride; + src7 = *s; s+=srcStride; + *d= cm[(9*(src5 + src6) - (src4 + src7) + 8)>>4]; d+=dstStride; + src8 = *s; s+=srcStride; + *d= cm[(9*(src6 + src7) - (src5 + src8) + 8)>>4]; d+=dstStride; + src9 = *s; + *d= cm[(9*(src7 + src8) - (src6 + src9) + 8)>>4]; d+=dstStride; + src++; + dst++; + }while(--w); +} + +static void put_mspel8_mc00_sh4 (uint8_t *dst, uint8_t *src, int stride){ + put_pixels8_c(dst, src, stride, 8); +} + +static void put_mspel8_mc10_sh4(uint8_t *dst, uint8_t *src, int stride){ + uint8_t half[64]; + wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); + put_pixels8_l2_aligned2(dst, src, half, stride, stride, 8, 8); +} + +static void put_mspel8_mc20_sh4(uint8_t *dst, uint8_t *src, int stride){ + wmv2_mspel8_h_lowpass(dst, src, stride, stride, 8); +} + +static void put_mspel8_mc30_sh4(uint8_t *dst, uint8_t *src, int stride){ + uint8_t half[64]; + wmv2_mspel8_h_lowpass(half, src, 8, stride, 8); + put_pixels8_l2_aligned2(dst, src+1, half, stride, stride, 8, 8); +} + +static void put_mspel8_mc02_sh4(uint8_t *dst, uint8_t *src, int stride){ + wmv2_mspel8_v_lowpass(dst, src, stride, stride, 8); +} + +static void put_mspel8_mc12_sh4(uint8_t *dst, uint8_t *src, int stride){ + uint8_t halfH[88]; + uint8_t halfV[64]; + uint8_t halfHV[64]; + wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(halfV, src, 8, stride, 8); + wmv2_mspel8_v_lowpass(halfHV, halfH+8, 8, 8, 8); + put_pixels8_l2_aligned(dst, halfV, halfHV, stride, 8, 8, 8); +} +static void put_mspel8_mc32_sh4(uint8_t *dst, uint8_t *src, int stride){ + uint8_t halfH[88]; + uint8_t halfV[64]; + uint8_t halfHV[64]; + wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(halfV, src+1, 8, stride, 8); + wmv2_mspel8_v_lowpass(halfHV, halfH+8, 8, 8, 8); + put_pixels8_l2_aligned(dst, halfV, halfHV, stride, 8, 8, 8); +} +static void put_mspel8_mc22_sh4(uint8_t *dst, uint8_t *src, int stride){ + uint8_t halfH[88]; + wmv2_mspel8_h_lowpass(halfH, src-stride, 8, stride, 11); + wmv2_mspel8_v_lowpass(dst, halfH+8, stride, 8, 8); +} diff --git a/ffmpeg/libavcodec/sh4/sh4.h b/ffmpeg/libavcodec/sh4/sh4.h new file mode 100644 index 0000000..5d46540 --- /dev/null +++ b/ffmpeg/libavcodec/sh4/sh4.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2008 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_SH4_SH4_H +#define AVCODEC_SH4_SH4_H + +#ifdef __SH4__ +# define fp_single_enter(fpscr) \ + do { \ + __asm__ volatile ("sts fpscr, %0 \n\t" \ + "and %1, %0 \n\t" \ + "lds %0, fpscr \n\t" \ + : "=&r"(fpscr) : "r"(~(1<<19))); \ + } while (0) + +# define fp_single_leave(fpscr) \ + do { \ + __asm__ volatile ("or %1, %0 \n\t" \ + "lds %0, fpscr \n\t" \ + : "+r"(fpscr) : "r"(1<<19)); \ + } while (0) +#else +# define fp_single_enter(fpscr) ((void)fpscr) +# define fp_single_leave(fpscr) +#endif + +#endif /* AVCODEC_SH4_SH4_H */ diff --git a/ffmpeg/libavcodec/shorten.c b/ffmpeg/libavcodec/shorten.c new file mode 100644 index 0000000..1d3b6eb --- /dev/null +++ b/ffmpeg/libavcodec/shorten.c @@ -0,0 +1,671 @@ +/* + * Shorten decoder + * Copyright (c) 2005 Jeff Muizelaar + * + * 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 + */ + +/** + * @file + * Shorten decoder + * @author Jeff Muizelaar + * + */ + +#include +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "golomb.h" +#include "internal.h" + +#define MAX_CHANNELS 8 +#define MAX_BLOCKSIZE 65535 + +#define OUT_BUFFER_SIZE 16384 + +#define ULONGSIZE 2 + +#define WAVE_FORMAT_PCM 0x0001 + +#define DEFAULT_BLOCK_SIZE 256 + +#define TYPESIZE 4 +#define CHANSIZE 0 +#define LPCQSIZE 2 +#define ENERGYSIZE 3 +#define BITSHIFTSIZE 2 + +#define TYPE_S8 1 +#define TYPE_U8 2 +#define TYPE_S16HL 3 +#define TYPE_U16HL 4 +#define TYPE_S16LH 5 +#define TYPE_U16LH 6 + +#define NWRAP 3 +#define NSKIPSIZE 1 + +#define LPCQUANT 5 +#define V2LPCQOFFSET (1 << LPCQUANT) + +#define FNSIZE 2 +#define FN_DIFF0 0 +#define FN_DIFF1 1 +#define FN_DIFF2 2 +#define FN_DIFF3 3 +#define FN_QUIT 4 +#define FN_BLOCKSIZE 5 +#define FN_BITSHIFT 6 +#define FN_QLPC 7 +#define FN_ZERO 8 +#define FN_VERBATIM 9 + +/** indicates if the FN_* command is audio or non-audio */ +static const uint8_t is_audio_command[10] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0 }; + +#define VERBATIM_CKSIZE_SIZE 5 +#define VERBATIM_BYTE_SIZE 8 +#define CANONICAL_HEADER_SIZE 44 + +typedef struct ShortenContext { + AVCodecContext *avctx; + GetBitContext gb; + + int min_framesize, max_framesize; + unsigned channels; + + int32_t *decoded[MAX_CHANNELS]; + int32_t *decoded_base[MAX_CHANNELS]; + int32_t *offset[MAX_CHANNELS]; + int *coeffs; + uint8_t *bitstream; + int bitstream_size; + int bitstream_index; + unsigned int allocated_bitstream_size; + int header_size; + uint8_t header[OUT_BUFFER_SIZE]; + int version; + int cur_chan; + int bitshift; + int nmean; + int internal_ftype; + int nwrap; + int blocksize; + int bitindex; + int32_t lpcqoffset; + int got_header; + int got_quit_command; +} ShortenContext; + +static av_cold int shorten_decode_init(AVCodecContext *avctx) +{ + ShortenContext *s = avctx->priv_data; + s->avctx = avctx; + + return 0; +} + +static int allocate_buffers(ShortenContext *s) +{ + int i, chan; + int *coeffs; + void *tmp_ptr; + + for (chan = 0; chan < s->channels; chan++) { + if (FFMAX(1, s->nmean) >= UINT_MAX / sizeof(int32_t)) { + av_log(s->avctx, AV_LOG_ERROR, "nmean too large\n"); + return AVERROR_INVALIDDATA; + } + if (s->blocksize + s->nwrap >= UINT_MAX / sizeof(int32_t) || + s->blocksize + s->nwrap <= (unsigned)s->nwrap) { + av_log(s->avctx, AV_LOG_ERROR, + "s->blocksize + s->nwrap too large\n"); + return AVERROR_INVALIDDATA; + } + + tmp_ptr = + av_realloc(s->offset[chan], sizeof(int32_t) * FFMAX(1, s->nmean)); + if (!tmp_ptr) + return AVERROR(ENOMEM); + s->offset[chan] = tmp_ptr; + + tmp_ptr = av_realloc(s->decoded_base[chan], (s->blocksize + s->nwrap) * + sizeof(s->decoded_base[0][0])); + if (!tmp_ptr) + return AVERROR(ENOMEM); + s->decoded_base[chan] = tmp_ptr; + for (i = 0; i < s->nwrap; i++) + s->decoded_base[chan][i] = 0; + s->decoded[chan] = s->decoded_base[chan] + s->nwrap; + } + + coeffs = av_realloc(s->coeffs, s->nwrap * sizeof(*s->coeffs)); + if (!coeffs) + return AVERROR(ENOMEM); + s->coeffs = coeffs; + + return 0; +} + +static inline unsigned int get_uint(ShortenContext *s, int k) +{ + if (s->version != 0) + k = get_ur_golomb_shorten(&s->gb, ULONGSIZE); + return get_ur_golomb_shorten(&s->gb, k); +} + +static void fix_bitshift(ShortenContext *s, int32_t *buffer) +{ + int i; + + if (s->bitshift != 0) + for (i = 0; i < s->blocksize; i++) + buffer[i] <<= s->bitshift; +} + +static int init_offset(ShortenContext *s) +{ + int32_t mean = 0; + int chan, i; + int nblock = FFMAX(1, s->nmean); + /* initialise offset */ + switch (s->internal_ftype) { + case TYPE_U8: + s->avctx->sample_fmt = AV_SAMPLE_FMT_U8P; + mean = 0x80; + break; + case TYPE_S16HL: + case TYPE_S16LH: + s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "unknown audio type\n"); + return AVERROR_PATCHWELCOME; + } + + for (chan = 0; chan < s->channels; chan++) + for (i = 0; i < nblock; i++) + s->offset[chan][i] = mean; + return 0; +} + +static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header, + int header_size) +{ + int len, bps; + short wave_format; + const uint8_t *end= header + header_size; + + if (bytestream_get_le32(&header) != MKTAG('R', 'I', 'F', 'F')) { + av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n"); + return AVERROR_INVALIDDATA; + } + + header += 4; /* chunk size */ + + if (bytestream_get_le32(&header) != MKTAG('W', 'A', 'V', 'E')) { + av_log(avctx, AV_LOG_ERROR, "missing WAVE tag\n"); + return AVERROR_INVALIDDATA; + } + + while (bytestream_get_le32(&header) != MKTAG('f', 'm', 't', ' ')) { + len = bytestream_get_le32(&header); + if (len<0 || end - header - 8 < len) + return AVERROR_INVALIDDATA; + header += len; + } + len = bytestream_get_le32(&header); + + if (len < 16) { + av_log(avctx, AV_LOG_ERROR, "fmt chunk was too short\n"); + return AVERROR_INVALIDDATA; + } + + wave_format = bytestream_get_le16(&header); + + switch (wave_format) { + case WAVE_FORMAT_PCM: + break; + default: + av_log(avctx, AV_LOG_ERROR, "unsupported wave format\n"); + return AVERROR(ENOSYS); + } + + header += 2; // skip channels (already got from shorten header) + avctx->sample_rate = bytestream_get_le32(&header); + header += 4; // skip bit rate (represents original uncompressed bit rate) + header += 2; // skip block align (not needed) + bps = bytestream_get_le16(&header); + avctx->bits_per_coded_sample = bps; + + if (bps != 16 && bps != 8) { + av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample: %d\n", bps); + return AVERROR(ENOSYS); + } + + len -= 16; + if (len > 0) + av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len); + + return 0; +} + +static const int fixed_coeffs[3][3] = { + { 1, 0, 0 }, + { 2, -1, 0 }, + { 3, -3, 1 } +}; + +static int decode_subframe_lpc(ShortenContext *s, int command, int channel, + int residual_size, int32_t coffset) +{ + int pred_order, sum, qshift, init_sum, i, j; + const int *coeffs; + + if (command == FN_QLPC) { + /* read/validate prediction order */ + pred_order = get_ur_golomb_shorten(&s->gb, LPCQSIZE); + if (pred_order > s->nwrap) { + av_log(s->avctx, AV_LOG_ERROR, "invalid pred_order %d\n", + pred_order); + return AVERROR(EINVAL); + } + /* read LPC coefficients */ + for (i = 0; i < pred_order; i++) + s->coeffs[i] = get_sr_golomb_shorten(&s->gb, LPCQUANT); + coeffs = s->coeffs; + + qshift = LPCQUANT; + } else { + /* fixed LPC coeffs */ + pred_order = command; + coeffs = fixed_coeffs[pred_order - 1]; + qshift = 0; + } + + /* subtract offset from previous samples to use in prediction */ + if (command == FN_QLPC && coffset) + for (i = -pred_order; i < 0; i++) + s->decoded[channel][i] -= coffset; + + /* decode residual and do LPC prediction */ + init_sum = pred_order ? (command == FN_QLPC ? s->lpcqoffset : 0) : coffset; + for (i = 0; i < s->blocksize; i++) { + sum = init_sum; + for (j = 0; j < pred_order; j++) + sum += coeffs[j] * s->decoded[channel][i - j - 1]; + s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + + (sum >> qshift); + } + + /* add offset to current samples */ + if (command == FN_QLPC && coffset) + for (i = 0; i < s->blocksize; i++) + s->decoded[channel][i] += coffset; + + return 0; +} + +static int read_header(ShortenContext *s) +{ + int i, ret; + int maxnlpc = 0; + /* shorten signature */ + if (get_bits_long(&s->gb, 32) != AV_RB32("ajkg")) { + av_log(s->avctx, AV_LOG_ERROR, "missing shorten magic 'ajkg'\n"); + return AVERROR_INVALIDDATA; + } + + s->lpcqoffset = 0; + s->blocksize = DEFAULT_BLOCK_SIZE; + s->nmean = -1; + s->version = get_bits(&s->gb, 8); + s->internal_ftype = get_uint(s, TYPESIZE); + + s->channels = get_uint(s, CHANSIZE); + if (!s->channels) { + av_log(s->avctx, AV_LOG_ERROR, "No channels reported\n"); + return AVERROR_INVALIDDATA; + } + if (s->channels > MAX_CHANNELS) { + av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels); + s->channels = 0; + return AVERROR_INVALIDDATA; + } + s->avctx->channels = s->channels; + + /* get blocksize if version > 0 */ + if (s->version > 0) { + int skip_bytes; + unsigned blocksize; + + blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE)); + if (!blocksize || blocksize > MAX_BLOCKSIZE) { + av_log(s->avctx, AV_LOG_ERROR, + "invalid or unsupported block size: %d\n", + blocksize); + return AVERROR(EINVAL); + } + s->blocksize = blocksize; + + maxnlpc = get_uint(s, LPCQSIZE); + s->nmean = get_uint(s, 0); + + skip_bytes = get_uint(s, NSKIPSIZE); + for (i = 0; i < skip_bytes; i++) + skip_bits(&s->gb, 8); + } + s->nwrap = FFMAX(NWRAP, maxnlpc); + + if ((ret = allocate_buffers(s)) < 0) + return ret; + + if ((ret = init_offset(s)) < 0) + return ret; + + if (s->version > 1) + s->lpcqoffset = V2LPCQOFFSET; + + if (get_ur_golomb_shorten(&s->gb, FNSIZE) != FN_VERBATIM) { + av_log(s->avctx, AV_LOG_ERROR, + "missing verbatim section at beginning of stream\n"); + return AVERROR_INVALIDDATA; + } + + s->header_size = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE); + if (s->header_size >= OUT_BUFFER_SIZE || + s->header_size < CANONICAL_HEADER_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, "header is wrong size: %d\n", + s->header_size); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < s->header_size; i++) + s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); + + if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0) + return ret; + + s->cur_chan = 0; + s->bitshift = 0; + + s->got_header = 1; + + return 0; +} + +static int shorten_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ShortenContext *s = avctx->priv_data; + int i, input_buf_size = 0; + int ret; + + /* allocate internal bitstream buffer */ + if (s->max_framesize == 0) { + void *tmp_ptr; + s->max_framesize = 8192; // should hopefully be enough for the first header + tmp_ptr = av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, + s->max_framesize); + if (!tmp_ptr) { + av_log(avctx, AV_LOG_ERROR, "error allocating bitstream buffer\n"); + return AVERROR(ENOMEM); + } + s->bitstream = tmp_ptr; + } + + /* append current packet data to bitstream buffer */ + if (1 && s->max_framesize) { //FIXME truncated + buf_size = FFMIN(buf_size, s->max_framesize - s->bitstream_size); + input_buf_size = buf_size; + + if (s->bitstream_index + s->bitstream_size + buf_size > + s->allocated_bitstream_size) { + memmove(s->bitstream, &s->bitstream[s->bitstream_index], + s->bitstream_size); + s->bitstream_index = 0; + } + if (buf) + memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, + buf_size); + buf = &s->bitstream[s->bitstream_index]; + buf_size += s->bitstream_size; + s->bitstream_size = buf_size; + + /* do not decode until buffer has at least max_framesize bytes or + * the end of the file has been reached */ + if (buf_size < s->max_framesize && avpkt->data) { + *got_frame_ptr = 0; + return input_buf_size; + } + } + /* init and position bitstream reader */ + init_get_bits(&s->gb, buf, buf_size * 8); + skip_bits(&s->gb, s->bitindex); + + /* process header or next subblock */ + if (!s->got_header) { + if ((ret = read_header(s)) < 0) + return ret; + *got_frame_ptr = 0; + goto finish_frame; + } + + /* if quit command was read previously, don't decode anything */ + if (s->got_quit_command) { + *got_frame_ptr = 0; + return avpkt->size; + } + + s->cur_chan = 0; + while (s->cur_chan < s->channels) { + unsigned cmd; + int len; + + if (get_bits_left(&s->gb) < 3 + FNSIZE) { + *got_frame_ptr = 0; + break; + } + + cmd = get_ur_golomb_shorten(&s->gb, FNSIZE); + + if (cmd > FN_VERBATIM) { + av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd); + *got_frame_ptr = 0; + break; + } + + if (!is_audio_command[cmd]) { + /* process non-audio command */ + switch (cmd) { + case FN_VERBATIM: + len = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE); + while (len--) + get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); + break; + case FN_BITSHIFT: + s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE); + break; + case FN_BLOCKSIZE: { + unsigned blocksize = get_uint(s, av_log2(s->blocksize)); + if (blocksize > s->blocksize) { + av_log(avctx, AV_LOG_ERROR, + "Increasing block size is not supported\n"); + return AVERROR_PATCHWELCOME; + } + if (!blocksize || blocksize > MAX_BLOCKSIZE) { + av_log(avctx, AV_LOG_ERROR, "invalid or unsupported " + "block size: %d\n", blocksize); + return AVERROR(EINVAL); + } + s->blocksize = blocksize; + break; + } + case FN_QUIT: + s->got_quit_command = 1; + break; + } + if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) { + *got_frame_ptr = 0; + break; + } + } else { + /* process audio command */ + int residual_size = 0; + int channel = s->cur_chan; + int32_t coffset; + + /* get Rice code for residual decoding */ + if (cmd != FN_ZERO) { + residual_size = get_ur_golomb_shorten(&s->gb, ENERGYSIZE); + /* This is a hack as version 0 differed in the definition + * of get_sr_golomb_shorten(). */ + if (s->version == 0) + residual_size--; + } + + /* calculate sample offset using means from previous blocks */ + if (s->nmean == 0) + coffset = s->offset[channel][0]; + else { + int32_t sum = (s->version < 2) ? 0 : s->nmean / 2; + for (i = 0; i < s->nmean; i++) + sum += s->offset[channel][i]; + coffset = sum / s->nmean; + if (s->version >= 2) + coffset = s->bitshift == 0 ? coffset : coffset >> s->bitshift - 1 >> 1; + } + + /* decode samples for this channel */ + if (cmd == FN_ZERO) { + for (i = 0; i < s->blocksize; i++) + s->decoded[channel][i] = 0; + } else { + if ((ret = decode_subframe_lpc(s, cmd, channel, + residual_size, coffset)) < 0) + return ret; + } + + /* update means with info from the current block */ + if (s->nmean > 0) { + int32_t sum = (s->version < 2) ? 0 : s->blocksize / 2; + for (i = 0; i < s->blocksize; i++) + sum += s->decoded[channel][i]; + + for (i = 1; i < s->nmean; i++) + s->offset[channel][i - 1] = s->offset[channel][i]; + + if (s->version < 2) + s->offset[channel][s->nmean - 1] = sum / s->blocksize; + else + s->offset[channel][s->nmean - 1] = (sum / s->blocksize) << s->bitshift; + } + + /* copy wrap samples for use with next block */ + for (i = -s->nwrap; i < 0; i++) + s->decoded[channel][i] = s->decoded[channel][i + s->blocksize]; + + /* shift samples to add in unused zero bits which were removed + * during encoding */ + fix_bitshift(s, s->decoded[channel]); + + /* if this is the last channel in the block, output the samples */ + s->cur_chan++; + if (s->cur_chan == s->channels) { + uint8_t *samples_u8; + int16_t *samples_s16; + int chan; + + /* get output buffer */ + frame->nb_samples = s->blocksize; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (chan = 0; chan < s->channels; chan++) { + samples_u8 = ((uint8_t **)frame->extended_data)[chan]; + samples_s16 = ((int16_t **)frame->extended_data)[chan]; + for (i = 0; i < s->blocksize; i++) { + switch (s->internal_ftype) { + case TYPE_U8: + *samples_u8++ = av_clip_uint8(s->decoded[chan][i]); + break; + case TYPE_S16HL: + case TYPE_S16LH: + *samples_s16++ = av_clip_int16(s->decoded[chan][i]); + break; + } + } + } + + *got_frame_ptr = 1; + } + } + } + if (s->cur_chan < s->channels) + *got_frame_ptr = 0; + +finish_frame: + s->bitindex = get_bits_count(&s->gb) - 8 * (get_bits_count(&s->gb) / 8); + i = get_bits_count(&s->gb) / 8; + if (i > buf_size) { + av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", i - buf_size); + s->bitstream_size = 0; + s->bitstream_index = 0; + return AVERROR_INVALIDDATA; + } + if (s->bitstream_size) { + s->bitstream_index += i; + s->bitstream_size -= i; + return input_buf_size; + } else + return i; +} + +static av_cold int shorten_decode_close(AVCodecContext *avctx) +{ + ShortenContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->channels; i++) { + s->decoded[i] = NULL; + av_freep(&s->decoded_base[i]); + av_freep(&s->offset[i]); + } + av_freep(&s->bitstream); + av_freep(&s->coeffs); + + return 0; +} + +AVCodec ff_shorten_decoder = { + .name = "shorten", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SHORTEN, + .priv_data_size = sizeof(ShortenContext), + .init = shorten_decode_init, + .close = shorten_decode_close, + .decode = shorten_decode_frame, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Shorten"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/simple_idct.c b/ffmpeg/libavcodec/simple_idct.c new file mode 100644 index 0000000..d204565 --- /dev/null +++ b/ffmpeg/libavcodec/simple_idct.c @@ -0,0 +1,233 @@ +/* + * Simple IDCT + * + * Copyright (c) 2001 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 + */ + +/** + * @file + * simpleidct in C. + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "mathops.h" +#include "simple_idct.h" + +#define BIT_DEPTH 8 +#include "simple_idct_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 10 +#include "simple_idct_template.c" +#undef BIT_DEPTH + +/* 2x4x8 idct */ + +#define CN_SHIFT 12 +#define C_FIX(x) ((int)((x) * (1 << CN_SHIFT) + 0.5)) +#define C1 C_FIX(0.6532814824) +#define C2 C_FIX(0.2705980501) + +/* row idct is multiple by 16 * sqrt(2.0), col idct4 is normalized, + and the butterfly must be multiplied by 0.5 * sqrt(2.0) */ +#define C_SHIFT (4+1+12) + +static inline void idct4col_put(uint8_t *dest, int line_size, const int16_t *col) +{ + int c0, c1, c2, c3, a0, a1, a2, a3; + + a0 = col[8*0]; + a1 = col[8*2]; + a2 = col[8*4]; + a3 = col[8*6]; + c0 = ((a0 + a2) << (CN_SHIFT - 1)) + (1 << (C_SHIFT - 1)); + c2 = ((a0 - a2) << (CN_SHIFT - 1)) + (1 << (C_SHIFT - 1)); + c1 = a1 * C1 + a3 * C2; + c3 = a1 * C2 - a3 * C1; + dest[0] = av_clip_uint8((c0 + c1) >> C_SHIFT); + dest += line_size; + dest[0] = av_clip_uint8((c2 + c3) >> C_SHIFT); + dest += line_size; + dest[0] = av_clip_uint8((c2 - c3) >> C_SHIFT); + dest += line_size; + dest[0] = av_clip_uint8((c0 - c1) >> C_SHIFT); +} + +#define BF(k) \ +{\ + int a0, a1;\ + a0 = ptr[k];\ + a1 = ptr[8 + k];\ + ptr[k] = a0 + a1;\ + ptr[8 + k] = a0 - a1;\ +} + +/* only used by DV codec. The input must be interlaced. 128 is added + to the pixels before clamping to avoid systematic error + (1024*sqrt(2)) offset would be needed otherwise. */ +/* XXX: I think a 1.0/sqrt(2) normalization should be needed to + compensate the extra butterfly stage - I don't have the full DV + specification */ +void ff_simple_idct248_put(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + int16_t *ptr; + + /* butterfly */ + ptr = block; + for(i=0;i<4;i++) { + BF(0); + BF(1); + BF(2); + BF(3); + BF(4); + BF(5); + BF(6); + BF(7); + ptr += 2 * 8; + } + + /* IDCT8 on each line */ + for(i=0; i<8; i++) { + idctRowCondDC_8(block + i*8, 0); + } + + /* IDCT4 and store */ + for(i=0;i<8;i++) { + idct4col_put(dest + i, 2 * line_size, block + i); + idct4col_put(dest + line_size + i, 2 * line_size, block + 8 + i); + } +} + +/* 8x4 & 4x8 WMV2 IDCT */ +#undef CN_SHIFT +#undef C_SHIFT +#undef C_FIX +#undef C1 +#undef C2 +#define CN_SHIFT 12 +#define C_FIX(x) ((int)((x) * 1.414213562 * (1 << CN_SHIFT) + 0.5)) +#define C1 C_FIX(0.6532814824) +#define C2 C_FIX(0.2705980501) +#define C3 C_FIX(0.5) +#define C_SHIFT (4+1+12) +static inline void idct4col_add(uint8_t *dest, int line_size, const int16_t *col) +{ + int c0, c1, c2, c3, a0, a1, a2, a3; + + a0 = col[8*0]; + a1 = col[8*1]; + a2 = col[8*2]; + a3 = col[8*3]; + c0 = (a0 + a2)*C3 + (1 << (C_SHIFT - 1)); + c2 = (a0 - a2)*C3 + (1 << (C_SHIFT - 1)); + c1 = a1 * C1 + a3 * C2; + c3 = a1 * C2 - a3 * C1; + dest[0] = av_clip_uint8(dest[0] + ((c0 + c1) >> C_SHIFT)); + dest += line_size; + dest[0] = av_clip_uint8(dest[0] + ((c2 + c3) >> C_SHIFT)); + dest += line_size; + dest[0] = av_clip_uint8(dest[0] + ((c2 - c3) >> C_SHIFT)); + dest += line_size; + dest[0] = av_clip_uint8(dest[0] + ((c0 - c1) >> C_SHIFT)); +} + +#define RN_SHIFT 15 +#define R_FIX(x) ((int)((x) * 1.414213562 * (1 << RN_SHIFT) + 0.5)) +#define R1 R_FIX(0.6532814824) +#define R2 R_FIX(0.2705980501) +#define R3 R_FIX(0.5) +#define R_SHIFT 11 +static inline void idct4row(int16_t *row) +{ + int c0, c1, c2, c3, a0, a1, a2, a3; + + a0 = row[0]; + a1 = row[1]; + a2 = row[2]; + a3 = row[3]; + c0 = (a0 + a2)*R3 + (1 << (R_SHIFT - 1)); + c2 = (a0 - a2)*R3 + (1 << (R_SHIFT - 1)); + c1 = a1 * R1 + a3 * R2; + c3 = a1 * R2 - a3 * R1; + row[0]= (c0 + c1) >> R_SHIFT; + row[1]= (c2 + c3) >> R_SHIFT; + row[2]= (c2 - c3) >> R_SHIFT; + row[3]= (c0 - c1) >> R_SHIFT; +} + +void ff_simple_idct84_add(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + + /* IDCT8 on each line */ + for(i=0; i<4; i++) { + idctRowCondDC_8(block + i*8, 0); + } + + /* IDCT4 and store */ + for(i=0;i<8;i++) { + idct4col_add(dest + i, line_size, block + i); + } +} + +void ff_simple_idct48_add(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + + /* IDCT4 on each line */ + for(i=0; i<8; i++) { + idct4row(block + i*8); + } + + /* IDCT8 and store */ + for(i=0; i<4; i++){ + idctSparseColAdd_8(dest + i, line_size, block + i); + } +} + +void ff_simple_idct44_add(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + + /* IDCT4 on each line */ + for(i=0; i<4; i++) { + idct4row(block + i*8); + } + + /* IDCT4 and store */ + for(i=0; i<4; i++){ + idct4col_add(dest + i, line_size, block + i); + } +} + +void ff_prores_idct(int16_t *block, const int16_t *qmat) +{ + int i; + + for (i = 0; i < 64; i++) + block[i] *= qmat[i]; + + for (i = 0; i < 8; i++) + idctRowCondDC_10(block + i*8, 2); + + for (i = 0; i < 8; i++) + idctSparseCol_10(block + i); +} diff --git a/ffmpeg/libavcodec/simple_idct.h b/ffmpeg/libavcodec/simple_idct.h new file mode 100644 index 0000000..3fec5e0 --- /dev/null +++ b/ffmpeg/libavcodec/simple_idct.h @@ -0,0 +1,57 @@ +/* + * Simple IDCT + * + * Copyright (c) 2001 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 + */ + +/** + * @file + * simple idct header. + */ + +#ifndef AVCODEC_SIMPLE_IDCT_H +#define AVCODEC_SIMPLE_IDCT_H + +#include + +void ff_simple_idct_put_8(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_add_8(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_8(int16_t *block); + +void ff_simple_idct_put_10(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_add_10(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_10(int16_t *block); +/** + * Special version of ff_simple_idct_10() which does dequantization + * and scales by a factor of 2 more between the two IDCTs to account + * for larger scale of input coefficients. + */ +void ff_prores_idct(int16_t *block, const int16_t *qmat); + +void ff_simple_idct_mmx(int16_t *block); +void ff_simple_idct_add_mmx(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct_put_mmx(uint8_t *dest, int line_size, int16_t *block); + +void ff_simple_idct248_put(uint8_t *dest, int line_size, int16_t *block); + +void ff_simple_idct84_add(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct48_add(uint8_t *dest, int line_size, int16_t *block); +void ff_simple_idct44_add(uint8_t *dest, int line_size, int16_t *block); + +#endif /* AVCODEC_SIMPLE_IDCT_H */ diff --git a/ffmpeg/libavcodec/simple_idct_template.c b/ffmpeg/libavcodec/simple_idct_template.c new file mode 100644 index 0000000..dabfbda --- /dev/null +++ b/ffmpeg/libavcodec/simple_idct_template.c @@ -0,0 +1,324 @@ +/* + * Simple IDCT + * + * Copyright (c) 2001 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 + */ + +/** + * @file + * simpleidct in C. + */ + +/* + based upon some outcommented c code from mpeg2dec (idct_mmx.c + written by Aaron Holtzman ) + */ + +#include "bit_depth_template.c" + +#undef W1 +#undef W2 +#undef W3 +#undef W4 +#undef W5 +#undef W6 +#undef W7 +#undef ROW_SHIFT +#undef COL_SHIFT +#undef DC_SHIFT +#undef MUL +#undef MAC + +#if BIT_DEPTH == 8 + +#define W1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define W7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 + +#define ROW_SHIFT 11 +#define COL_SHIFT 20 +#define DC_SHIFT 3 + +#define MUL(a, b) MUL16(a, b) +#define MAC(a, b, c) MAC16(a, b, c) + +#elif BIT_DEPTH == 10 + +#define W1 90901 +#define W2 85627 +#define W3 77062 +#define W4 65535 +#define W5 51491 +#define W6 35468 +#define W7 18081 + +#define ROW_SHIFT 15 +#define COL_SHIFT 20 +#define DC_SHIFT 1 + +#define MUL(a, b) ((a) * (b)) +#define MAC(a, b, c) ((a) += (b) * (c)) + +#else + +#error "Unsupported bitdepth" + +#endif + +static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift) +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + +#if HAVE_FAST_64BIT +#define ROW0_MASK (0xffffLL << 48 * HAVE_BIGENDIAN) + if (((((uint64_t *)row)[0] & ~ROW0_MASK) | ((uint64_t *)row)[1]) == 0) { + uint64_t temp; + if (DC_SHIFT - extra_shift > 0) { + temp = (row[0] << (DC_SHIFT - extra_shift)) & 0xffff; + } else { + temp = (row[0] >> (extra_shift - DC_SHIFT)) & 0xffff; + } + temp += temp << 16; + temp += temp << 32; + ((uint64_t *)row)[0] = temp; + ((uint64_t *)row)[1] = temp; + return; + } +#else + if (!(((uint32_t*)row)[1] | + ((uint32_t*)row)[2] | + ((uint32_t*)row)[3] | + row[1])) { + uint32_t temp; + if (DC_SHIFT - extra_shift > 0) { + temp = (row[0] << (DC_SHIFT - extra_shift)) & 0xffff; + } else { + temp = (row[0] >> (extra_shift - DC_SHIFT)) & 0xffff; + } + temp += temp << 16; + ((uint32_t*)row)[0]=((uint32_t*)row)[1] = + ((uint32_t*)row)[2]=((uint32_t*)row)[3] = temp; + return; + } +#endif + + a0 = (W4 * row[0]) + (1 << (ROW_SHIFT - 1)); + a1 = a0; + a2 = a0; + a3 = a0; + + a0 += W2 * row[2]; + a1 += W6 * row[2]; + a2 -= W6 * row[2]; + a3 -= W2 * row[2]; + + b0 = MUL(W1, row[1]); + MAC(b0, W3, row[3]); + b1 = MUL(W3, row[1]); + MAC(b1, -W7, row[3]); + b2 = MUL(W5, row[1]); + MAC(b2, -W1, row[3]); + b3 = MUL(W7, row[1]); + MAC(b3, -W5, row[3]); + + if (AV_RN64A(row + 4)) { + a0 += W4*row[4] + W6*row[6]; + a1 += - W4*row[4] - W2*row[6]; + a2 += - W4*row[4] + W2*row[6]; + a3 += W4*row[4] - W6*row[6]; + + MAC(b0, W5, row[5]); + MAC(b0, W7, row[7]); + + MAC(b1, -W1, row[5]); + MAC(b1, -W5, row[7]); + + MAC(b2, W7, row[5]); + MAC(b2, W3, row[7]); + + MAC(b3, W3, row[5]); + MAC(b3, -W1, row[7]); + } + + row[0] = (a0 + b0) >> (ROW_SHIFT + extra_shift); + row[7] = (a0 - b0) >> (ROW_SHIFT + extra_shift); + row[1] = (a1 + b1) >> (ROW_SHIFT + extra_shift); + row[6] = (a1 - b1) >> (ROW_SHIFT + extra_shift); + row[2] = (a2 + b2) >> (ROW_SHIFT + extra_shift); + row[5] = (a2 - b2) >> (ROW_SHIFT + extra_shift); + row[3] = (a3 + b3) >> (ROW_SHIFT + extra_shift); + row[4] = (a3 - b3) >> (ROW_SHIFT + extra_shift); +} + +#define IDCT_COLS do { \ + a0 = W4 * (col[8*0] + ((1<<(COL_SHIFT-1))/W4)); \ + a1 = a0; \ + a2 = a0; \ + a3 = a0; \ + \ + a0 += W2*col[8*2]; \ + a1 += W6*col[8*2]; \ + a2 += -W6*col[8*2]; \ + a3 += -W2*col[8*2]; \ + \ + b0 = MUL(W1, col[8*1]); \ + b1 = MUL(W3, col[8*1]); \ + b2 = MUL(W5, col[8*1]); \ + b3 = MUL(W7, col[8*1]); \ + \ + MAC(b0, W3, col[8*3]); \ + MAC(b1, -W7, col[8*3]); \ + MAC(b2, -W1, col[8*3]); \ + MAC(b3, -W5, col[8*3]); \ + \ + if (col[8*4]) { \ + a0 += W4*col[8*4]; \ + a1 += -W4*col[8*4]; \ + a2 += -W4*col[8*4]; \ + a3 += W4*col[8*4]; \ + } \ + \ + if (col[8*5]) { \ + MAC(b0, W5, col[8*5]); \ + MAC(b1, -W1, col[8*5]); \ + MAC(b2, W7, col[8*5]); \ + MAC(b3, W3, col[8*5]); \ + } \ + \ + if (col[8*6]) { \ + a0 += W6*col[8*6]; \ + a1 += -W2*col[8*6]; \ + a2 += W2*col[8*6]; \ + a3 += -W6*col[8*6]; \ + } \ + \ + if (col[8*7]) { \ + MAC(b0, W7, col[8*7]); \ + MAC(b1, -W5, col[8*7]); \ + MAC(b2, W3, col[8*7]); \ + MAC(b3, -W1, col[8*7]); \ + } \ + } while (0) + +static inline void FUNC(idctSparseColPut)(pixel *dest, int line_size, + int16_t *col) +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + + IDCT_COLS; + + dest[0] = av_clip_pixel((a0 + b0) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a1 + b1) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a2 + b2) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a3 + b3) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a3 - b3) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a2 - b2) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a1 - b1) >> COL_SHIFT); + dest += line_size; + dest[0] = av_clip_pixel((a0 - b0) >> COL_SHIFT); +} + +static inline void FUNC(idctSparseColAdd)(pixel *dest, int line_size, + int16_t *col) +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + + IDCT_COLS; + + dest[0] = av_clip_pixel(dest[0] + ((a0 + b0) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a1 + b1) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a2 + b2) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a3 + b3) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a3 - b3) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a2 - b2) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a1 - b1) >> COL_SHIFT)); + dest += line_size; + dest[0] = av_clip_pixel(dest[0] + ((a0 - b0) >> COL_SHIFT)); +} + +static inline void FUNC(idctSparseCol)(int16_t *col) +{ + int a0, a1, a2, a3, b0, b1, b2, b3; + + IDCT_COLS; + + col[0 ] = ((a0 + b0) >> COL_SHIFT); + col[8 ] = ((a1 + b1) >> COL_SHIFT); + col[16] = ((a2 + b2) >> COL_SHIFT); + col[24] = ((a3 + b3) >> COL_SHIFT); + col[32] = ((a3 - b3) >> COL_SHIFT); + col[40] = ((a2 - b2) >> COL_SHIFT); + col[48] = ((a1 - b1) >> COL_SHIFT); + col[56] = ((a0 - b0) >> COL_SHIFT); +} + +void FUNC(ff_simple_idct_put)(uint8_t *dest_, int line_size, int16_t *block) +{ + pixel *dest = (pixel *)dest_; + int i; + + line_size /= sizeof(pixel); + + for (i = 0; i < 8; i++) + FUNC(idctRowCondDC)(block + i*8, 0); + + for (i = 0; i < 8; i++) + FUNC(idctSparseColPut)(dest + i, line_size, block + i); +} + +void FUNC(ff_simple_idct_add)(uint8_t *dest_, int line_size, int16_t *block) +{ + pixel *dest = (pixel *)dest_; + int i; + + line_size /= sizeof(pixel); + + for (i = 0; i < 8; i++) + FUNC(idctRowCondDC)(block + i*8, 0); + + for (i = 0; i < 8; i++) + FUNC(idctSparseColAdd)(dest + i, line_size, block + i); +} + +void FUNC(ff_simple_idct)(int16_t *block) +{ + int i; + + for (i = 0; i < 8; i++) + FUNC(idctRowCondDC)(block + i*8, 0); + + for (i = 0; i < 8; i++) + FUNC(idctSparseCol)(block + i); +} diff --git a/ffmpeg/libavcodec/sinewin.c b/ffmpeg/libavcodec/sinewin.c new file mode 100644 index 0000000..1fa0e95 --- /dev/null +++ b/ffmpeg/libavcodec/sinewin.c @@ -0,0 +1,20 @@ +/* + * 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 "sinewin.h" +#include "sinewin_tablegen.h" diff --git a/ffmpeg/libavcodec/sinewin.h b/ffmpeg/libavcodec/sinewin.h new file mode 100644 index 0000000..2268fd5 --- /dev/null +++ b/ffmpeg/libavcodec/sinewin.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008 Robert Swain + * + * 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 + */ + +#ifndef AVCODEC_SINEWIN_H +#define AVCODEC_SINEWIN_H + +#include "config.h" +#include "libavutil/mem.h" + +#if CONFIG_HARDCODED_TABLES +# define SINETABLE_CONST const +#else +# define SINETABLE_CONST +#endif + +#define SINETABLE(size) \ + SINETABLE_CONST DECLARE_ALIGNED(32, float, ff_sine_##size)[size] + +/** + * Generate a sine window. + * @param window pointer to half window + * @param n size of half window + */ +void ff_sine_window_init(float *window, int n); + +/** + * initialize the specified entry of ff_sine_windows + */ +void ff_init_ff_sine_windows(int index); + +extern SINETABLE( 32); +extern SINETABLE( 64); +extern SINETABLE( 128); +extern SINETABLE( 256); +extern SINETABLE( 512); +extern SINETABLE(1024); +extern SINETABLE(2048); +extern SINETABLE(4096); +extern SINETABLE(8192); + +extern SINETABLE_CONST float * const ff_sine_windows[14]; + +#endif /* AVCODEC_SINEWIN_H */ diff --git a/ffmpeg/libavcodec/sinewin_tablegen.c b/ffmpeg/libavcodec/sinewin_tablegen.c new file mode 100644 index 0000000..561ae3e --- /dev/null +++ b/ffmpeg/libavcodec/sinewin_tablegen.c @@ -0,0 +1,46 @@ +/* + * Generate a header file for hardcoded sine windows + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 +#define CONFIG_HARDCODED_TABLES 0 +#define SINETABLE_CONST +#define SINETABLE(size) \ + float ff_sine_##size[size] +#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#include "sinewin_tablegen.h" +#include "tableprint.h" + +int main(void) +{ + int i; + + write_fileheader(); + + for (i = 5; i <= 13; i++) { + ff_init_ff_sine_windows(i); + printf("SINETABLE(%4i) = {\n", 1 << i); + write_float_array(ff_sine_windows[i], 1 << i); + printf("};\n"); + } + + return 0; +} diff --git a/ffmpeg/libavcodec/sinewin_tablegen.h b/ffmpeg/libavcodec/sinewin_tablegen.h new file mode 100644 index 0000000..2b9c4f2 --- /dev/null +++ b/ffmpeg/libavcodec/sinewin_tablegen.h @@ -0,0 +1,67 @@ +/* + * Header file for hardcoded sine windows + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_SINEWIN_TABLEGEN_H +#define AVCODEC_SINEWIN_TABLEGEN_H + +#include +// do not use libavutil/libm.h since this is compiled both +// for the host and the target and config.h is only valid for the target +#include +#include "libavutil/attributes.h" +#include "libavutil/common.h" + +#if !CONFIG_HARDCODED_TABLES +SINETABLE( 32); +SINETABLE( 64); +SINETABLE( 128); +SINETABLE( 256); +SINETABLE( 512); +SINETABLE(1024); +SINETABLE(2048); +SINETABLE(4096); +SINETABLE(8192); +#else +#include "libavcodec/sinewin_tables.h" +#endif + +SINETABLE_CONST float * const ff_sine_windows[] = { + NULL, NULL, NULL, NULL, NULL, // unused + ff_sine_32 , ff_sine_64 , + ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024, ff_sine_2048, ff_sine_4096, ff_sine_8192 +}; + +// Generate a sine window. +av_cold void ff_sine_window_init(float *window, int n) { + int i; + for(i = 0; i < n; i++) + window[i] = sinf((i + 0.5) * (M_PI / (2.0 * n))); +} + +av_cold void ff_init_ff_sine_windows(int index) { + assert(index >= 0 && index < FF_ARRAY_ELEMS(ff_sine_windows)); +#if !CONFIG_HARDCODED_TABLES + ff_sine_window_init(ff_sine_windows[index], 1 << index); +#endif +} + +#endif /* AVCODEC_SINEWIN_TABLEGEN_H */ diff --git a/ffmpeg/libavcodec/sipr.c b/ffmpeg/libavcodec/sipr.c new file mode 100644 index 0000000..35e8bf5 --- /dev/null +++ b/ffmpeg/libavcodec/sipr.c @@ -0,0 +1,574 @@ +/* + * SIPR / ACELP.NET decoder + * + * Copyright (c) 2008 Vladimir Voroshilov + * Copyright (c) 2009 Vitor Sessak + * + * 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 +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "libavutil/mathematics.h" +#include "avcodec.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" + +#include "lsp.h" +#include "acelp_vectors.h" +#include "acelp_pitch_delay.h" +#include "acelp_filters.h" +#include "celp_filters.h" + +#define MAX_SUBFRAME_COUNT 5 + +#include "sipr.h" +#include "siprdata.h" + +typedef struct { + const char *mode_name; + uint16_t bits_per_frame; + uint8_t subframe_count; + uint8_t frames_per_packet; + float pitch_sharp_factor; + + /* bitstream parameters */ + uint8_t number_of_fc_indexes; + uint8_t ma_predictor_bits; ///< size in bits of the switched MA predictor + + /** size in bits of the i-th stage vector of quantizer */ + uint8_t vq_indexes_bits[5]; + + /** size in bits of the adaptive-codebook index for every subframe */ + uint8_t pitch_delay_bits[5]; + + uint8_t gp_index_bits; + uint8_t fc_index_bits[10]; ///< size in bits of the fixed codebook indexes + uint8_t gc_index_bits; ///< size in bits of the gain codebook indexes +} SiprModeParam; + +static const SiprModeParam modes[MODE_COUNT] = { + [MODE_16k] = { + .mode_name = "16k", + .bits_per_frame = 160, + .subframe_count = SUBFRAME_COUNT_16k, + .frames_per_packet = 1, + .pitch_sharp_factor = 0.00, + + .number_of_fc_indexes = 10, + .ma_predictor_bits = 1, + .vq_indexes_bits = {7, 8, 7, 7, 7}, + .pitch_delay_bits = {9, 6}, + .gp_index_bits = 4, + .fc_index_bits = {4, 5, 4, 5, 4, 5, 4, 5, 4, 5}, + .gc_index_bits = 5 + }, + + [MODE_8k5] = { + .mode_name = "8k5", + .bits_per_frame = 152, + .subframe_count = 3, + .frames_per_packet = 1, + .pitch_sharp_factor = 0.8, + + .number_of_fc_indexes = 3, + .ma_predictor_bits = 0, + .vq_indexes_bits = {6, 7, 7, 7, 5}, + .pitch_delay_bits = {8, 5, 5}, + .gp_index_bits = 0, + .fc_index_bits = {9, 9, 9}, + .gc_index_bits = 7 + }, + + [MODE_6k5] = { + .mode_name = "6k5", + .bits_per_frame = 232, + .subframe_count = 3, + .frames_per_packet = 2, + .pitch_sharp_factor = 0.8, + + .number_of_fc_indexes = 3, + .ma_predictor_bits = 0, + .vq_indexes_bits = {6, 7, 7, 7, 5}, + .pitch_delay_bits = {8, 5, 5}, + .gp_index_bits = 0, + .fc_index_bits = {5, 5, 5}, + .gc_index_bits = 7 + }, + + [MODE_5k0] = { + .mode_name = "5k0", + .bits_per_frame = 296, + .subframe_count = 5, + .frames_per_packet = 2, + .pitch_sharp_factor = 0.85, + + .number_of_fc_indexes = 1, + .ma_predictor_bits = 0, + .vq_indexes_bits = {6, 7, 7, 7, 5}, + .pitch_delay_bits = {8, 5, 8, 5, 5}, + .gp_index_bits = 0, + .fc_index_bits = {10}, + .gc_index_bits = 7 + } +}; + +const float ff_pow_0_5[] = { + 1.0/(1 << 1), 1.0/(1 << 2), 1.0/(1 << 3), 1.0/(1 << 4), + 1.0/(1 << 5), 1.0/(1 << 6), 1.0/(1 << 7), 1.0/(1 << 8), + 1.0/(1 << 9), 1.0/(1 << 10), 1.0/(1 << 11), 1.0/(1 << 12), + 1.0/(1 << 13), 1.0/(1 << 14), 1.0/(1 << 15), 1.0/(1 << 16) +}; + +static void dequant(float *out, const int *idx, const float *cbs[]) +{ + int i; + int stride = 2; + int num_vec = 5; + + for (i = 0; i < num_vec; i++) + memcpy(out + stride*i, cbs[i] + stride*idx[i], stride*sizeof(float)); + +} + +static void lsf_decode_fp(float *lsfnew, float *lsf_history, + const SiprParameters *parm) +{ + int i; + float lsf_tmp[LP_FILTER_ORDER]; + + dequant(lsf_tmp, parm->vq_indexes, lsf_codebooks); + + for (i = 0; i < LP_FILTER_ORDER; i++) + lsfnew[i] = lsf_history[i] * 0.33 + lsf_tmp[i] + mean_lsf[i]; + + ff_sort_nearly_sorted_floats(lsfnew, LP_FILTER_ORDER - 1); + + /* Note that a minimum distance is not enforced between the last value and + the previous one, contrary to what is done in ff_acelp_reorder_lsf() */ + ff_set_min_dist_lsf(lsfnew, LSFQ_DIFF_MIN, LP_FILTER_ORDER - 1); + lsfnew[9] = FFMIN(lsfnew[LP_FILTER_ORDER - 1], 1.3 * M_PI); + + memcpy(lsf_history, lsf_tmp, LP_FILTER_ORDER * sizeof(*lsf_history)); + + for (i = 0; i < LP_FILTER_ORDER - 1; i++) + lsfnew[i] = cos(lsfnew[i]); + lsfnew[LP_FILTER_ORDER - 1] *= 6.153848 / M_PI; +} + +/** Apply pitch lag to the fixed vector (AMR section 6.1.2). */ +static void pitch_sharpening(int pitch_lag_int, float beta, + float *fixed_vector) +{ + int i; + + for (i = pitch_lag_int; i < SUBFR_SIZE; i++) + fixed_vector[i] += beta * fixed_vector[i - pitch_lag_int]; +} + +/** + * Extract decoding parameters from the input bitstream. + * @param parms parameters structure + * @param pgb pointer to initialized GetBitContext structure + */ +static void decode_parameters(SiprParameters* parms, GetBitContext *pgb, + const SiprModeParam *p) +{ + int i, j; + + if (p->ma_predictor_bits) + parms->ma_pred_switch = get_bits(pgb, p->ma_predictor_bits); + + for (i = 0; i < 5; i++) + parms->vq_indexes[i] = get_bits(pgb, p->vq_indexes_bits[i]); + + for (i = 0; i < p->subframe_count; i++) { + parms->pitch_delay[i] = get_bits(pgb, p->pitch_delay_bits[i]); + if (p->gp_index_bits) + parms->gp_index[i] = get_bits(pgb, p->gp_index_bits); + + for (j = 0; j < p->number_of_fc_indexes; j++) + parms->fc_indexes[i][j] = get_bits(pgb, p->fc_index_bits[j]); + + parms->gc_index[i] = get_bits(pgb, p->gc_index_bits); + } +} + +static void sipr_decode_lp(float *lsfnew, const float *lsfold, float *Az, + int num_subfr) +{ + double lsfint[LP_FILTER_ORDER]; + int i,j; + float t, t0 = 1.0 / num_subfr; + + t = t0 * 0.5; + for (i = 0; i < num_subfr; i++) { + for (j = 0; j < LP_FILTER_ORDER; j++) + lsfint[j] = lsfold[j] * (1 - t) + t * lsfnew[j]; + + ff_amrwb_lsp2lpc(lsfint, Az, LP_FILTER_ORDER); + Az += LP_FILTER_ORDER; + t += t0; + } +} + +/** + * Evaluate the adaptive impulse response. + */ +static void eval_ir(const float *Az, int pitch_lag, float *freq, + float pitch_sharp_factor) +{ + float tmp1[SUBFR_SIZE+1], tmp2[LP_FILTER_ORDER+1]; + int i; + + tmp1[0] = 1.; + for (i = 0; i < LP_FILTER_ORDER; i++) { + tmp1[i+1] = Az[i] * ff_pow_0_55[i]; + tmp2[i ] = Az[i] * ff_pow_0_7 [i]; + } + memset(tmp1 + 11, 0, 37 * sizeof(float)); + + ff_celp_lp_synthesis_filterf(freq, tmp2, tmp1, SUBFR_SIZE, + LP_FILTER_ORDER); + + pitch_sharpening(pitch_lag, pitch_sharp_factor, freq); +} + +/** + * Evaluate the convolution of a vector with a sparse vector. + */ +static void convolute_with_sparse(float *out, const AMRFixed *pulses, + const float *shape, int length) +{ + int i, j; + + memset(out, 0, length*sizeof(float)); + for (i = 0; i < pulses->n; i++) + for (j = pulses->x[i]; j < length; j++) + out[j] += pulses->y[i] * shape[j - pulses->x[i]]; +} + +/** + * Apply postfilter, very similar to AMR one. + */ +static void postfilter_5k0(SiprContext *ctx, const float *lpc, float *samples) +{ + float buf[SUBFR_SIZE + LP_FILTER_ORDER]; + float *pole_out = buf + LP_FILTER_ORDER; + float lpc_n[LP_FILTER_ORDER]; + float lpc_d[LP_FILTER_ORDER]; + int i; + + for (i = 0; i < LP_FILTER_ORDER; i++) { + lpc_d[i] = lpc[i] * ff_pow_0_75[i]; + lpc_n[i] = lpc[i] * ff_pow_0_5 [i]; + }; + + memcpy(pole_out - LP_FILTER_ORDER, ctx->postfilter_mem, + LP_FILTER_ORDER*sizeof(float)); + + ff_celp_lp_synthesis_filterf(pole_out, lpc_d, samples, SUBFR_SIZE, + LP_FILTER_ORDER); + + memcpy(ctx->postfilter_mem, pole_out + SUBFR_SIZE - LP_FILTER_ORDER, + LP_FILTER_ORDER*sizeof(float)); + + ff_tilt_compensation(&ctx->tilt_mem, 0.4, pole_out, SUBFR_SIZE); + + memcpy(pole_out - LP_FILTER_ORDER, ctx->postfilter_mem5k0, + LP_FILTER_ORDER*sizeof(*pole_out)); + + memcpy(ctx->postfilter_mem5k0, pole_out + SUBFR_SIZE - LP_FILTER_ORDER, + LP_FILTER_ORDER*sizeof(*pole_out)); + + ff_celp_lp_zero_synthesis_filterf(samples, lpc_n, pole_out, SUBFR_SIZE, + LP_FILTER_ORDER); + +} + +static void decode_fixed_sparse(AMRFixed *fixed_sparse, const int16_t *pulses, + SiprMode mode, int low_gain) +{ + int i; + + switch (mode) { + case MODE_6k5: + for (i = 0; i < 3; i++) { + fixed_sparse->x[i] = 3 * (pulses[i] & 0xf) + i; + fixed_sparse->y[i] = pulses[i] & 0x10 ? -1 : 1; + } + fixed_sparse->n = 3; + break; + case MODE_8k5: + for (i = 0; i < 3; i++) { + fixed_sparse->x[2*i ] = 3 * ((pulses[i] >> 4) & 0xf) + i; + fixed_sparse->x[2*i + 1] = 3 * ( pulses[i] & 0xf) + i; + + fixed_sparse->y[2*i ] = (pulses[i] & 0x100) ? -1.0: 1.0; + + fixed_sparse->y[2*i + 1] = + (fixed_sparse->x[2*i + 1] < fixed_sparse->x[2*i]) ? + -fixed_sparse->y[2*i ] : fixed_sparse->y[2*i]; + } + + fixed_sparse->n = 6; + break; + case MODE_5k0: + default: + if (low_gain) { + int offset = (pulses[0] & 0x200) ? 2 : 0; + int val = pulses[0]; + + for (i = 0; i < 3; i++) { + int index = (val & 0x7) * 6 + 4 - i*2; + + fixed_sparse->y[i] = (offset + index) & 0x3 ? -1 : 1; + fixed_sparse->x[i] = index; + + val >>= 3; + } + fixed_sparse->n = 3; + } else { + int pulse_subset = (pulses[0] >> 8) & 1; + + fixed_sparse->x[0] = ((pulses[0] >> 4) & 15) * 3 + pulse_subset; + fixed_sparse->x[1] = ( pulses[0] & 15) * 3 + pulse_subset + 1; + + fixed_sparse->y[0] = pulses[0] & 0x200 ? -1 : 1; + fixed_sparse->y[1] = -fixed_sparse->y[0]; + fixed_sparse->n = 2; + } + break; + } +} + +static void decode_frame(SiprContext *ctx, SiprParameters *params, + float *out_data) +{ + int i, j; + int subframe_count = modes[ctx->mode].subframe_count; + int frame_size = subframe_count * SUBFR_SIZE; + float Az[LP_FILTER_ORDER * MAX_SUBFRAME_COUNT]; + float *excitation; + float ir_buf[SUBFR_SIZE + LP_FILTER_ORDER]; + float lsf_new[LP_FILTER_ORDER]; + float *impulse_response = ir_buf + LP_FILTER_ORDER; + float *synth = ctx->synth_buf + 16; // 16 instead of LP_FILTER_ORDER for + // memory alignment + int t0_first = 0; + AMRFixed fixed_cb; + + memset(ir_buf, 0, LP_FILTER_ORDER * sizeof(float)); + lsf_decode_fp(lsf_new, ctx->lsf_history, params); + + sipr_decode_lp(lsf_new, ctx->lsp_history, Az, subframe_count); + + memcpy(ctx->lsp_history, lsf_new, LP_FILTER_ORDER * sizeof(float)); + + excitation = ctx->excitation + PITCH_DELAY_MAX + L_INTERPOL; + + for (i = 0; i < subframe_count; i++) { + float *pAz = Az + i*LP_FILTER_ORDER; + float fixed_vector[SUBFR_SIZE]; + int T0,T0_frac; + float pitch_gain, gain_code, avg_energy; + + ff_decode_pitch_lag(&T0, &T0_frac, params->pitch_delay[i], t0_first, i, + ctx->mode == MODE_5k0, 6); + + if (i == 0 || (i == 2 && ctx->mode == MODE_5k0)) + t0_first = T0; + + ff_acelp_interpolatef(excitation, excitation - T0 + (T0_frac <= 0), + ff_b60_sinc, 6, + 2 * ((2 + T0_frac)%3 + 1), LP_FILTER_ORDER, + SUBFR_SIZE); + + decode_fixed_sparse(&fixed_cb, params->fc_indexes[i], ctx->mode, + ctx->past_pitch_gain < 0.8); + + eval_ir(pAz, T0, impulse_response, modes[ctx->mode].pitch_sharp_factor); + + convolute_with_sparse(fixed_vector, &fixed_cb, impulse_response, + SUBFR_SIZE); + + avg_energy = (0.01 + avpriv_scalarproduct_float_c(fixed_vector, + fixed_vector, + SUBFR_SIZE)) / + SUBFR_SIZE; + + ctx->past_pitch_gain = pitch_gain = gain_cb[params->gc_index[i]][0]; + + gain_code = ff_amr_set_fixed_gain(gain_cb[params->gc_index[i]][1], + avg_energy, ctx->energy_history, + 34 - 15.0/(0.05*M_LN10/M_LN2), + pred); + + ff_weighted_vector_sumf(excitation, excitation, fixed_vector, + pitch_gain, gain_code, SUBFR_SIZE); + + pitch_gain *= 0.5 * pitch_gain; + pitch_gain = FFMIN(pitch_gain, 0.4); + + ctx->gain_mem = 0.7 * ctx->gain_mem + 0.3 * pitch_gain; + ctx->gain_mem = FFMIN(ctx->gain_mem, pitch_gain); + gain_code *= ctx->gain_mem; + + for (j = 0; j < SUBFR_SIZE; j++) + fixed_vector[j] = excitation[j] - gain_code * fixed_vector[j]; + + if (ctx->mode == MODE_5k0) { + postfilter_5k0(ctx, pAz, fixed_vector); + + ff_celp_lp_synthesis_filterf(ctx->postfilter_syn5k0 + LP_FILTER_ORDER + i*SUBFR_SIZE, + pAz, excitation, SUBFR_SIZE, + LP_FILTER_ORDER); + } + + ff_celp_lp_synthesis_filterf(synth + i*SUBFR_SIZE, pAz, fixed_vector, + SUBFR_SIZE, LP_FILTER_ORDER); + + excitation += SUBFR_SIZE; + } + + memcpy(synth - LP_FILTER_ORDER, synth + frame_size - LP_FILTER_ORDER, + LP_FILTER_ORDER * sizeof(float)); + + if (ctx->mode == MODE_5k0) { + for (i = 0; i < subframe_count; i++) { + float energy = avpriv_scalarproduct_float_c(ctx->postfilter_syn5k0 + LP_FILTER_ORDER + i * SUBFR_SIZE, + ctx->postfilter_syn5k0 + LP_FILTER_ORDER + i * SUBFR_SIZE, + SUBFR_SIZE); + ff_adaptive_gain_control(&synth[i * SUBFR_SIZE], + &synth[i * SUBFR_SIZE], energy, + SUBFR_SIZE, 0.9, &ctx->postfilter_agc); + } + + memcpy(ctx->postfilter_syn5k0, ctx->postfilter_syn5k0 + frame_size, + LP_FILTER_ORDER*sizeof(float)); + } + memmove(ctx->excitation, excitation - PITCH_DELAY_MAX - L_INTERPOL, + (PITCH_DELAY_MAX + L_INTERPOL) * sizeof(float)); + + ff_acelp_apply_order_2_transfer_function(out_data, synth, + (const float[2]) {-1.99997 , 1.000000000}, + (const float[2]) {-1.93307352, 0.935891986}, + 0.939805806, + ctx->highpass_filt_mem, + frame_size); +} + +static av_cold int sipr_decoder_init(AVCodecContext * avctx) +{ + SiprContext *ctx = avctx->priv_data; + int i; + + switch (avctx->block_align) { + case 20: ctx->mode = MODE_16k; break; + case 19: ctx->mode = MODE_8k5; break; + case 29: ctx->mode = MODE_6k5; break; + case 37: ctx->mode = MODE_5k0; break; + default: + if (avctx->bit_rate > 12200) ctx->mode = MODE_16k; + else if (avctx->bit_rate > 7500 ) ctx->mode = MODE_8k5; + else if (avctx->bit_rate > 5750 ) ctx->mode = MODE_6k5; + else ctx->mode = MODE_5k0; + av_log(avctx, AV_LOG_WARNING, + "Invalid block_align: %d. Mode %s guessed based on bitrate: %d\n", + avctx->block_align, modes[ctx->mode].mode_name, avctx->bit_rate); + } + + av_log(avctx, AV_LOG_DEBUG, "Mode: %s\n", modes[ctx->mode].mode_name); + + if (ctx->mode == MODE_16k) { + ff_sipr_init_16k(ctx); + ctx->decode_frame = ff_sipr_decode_frame_16k; + } else { + ctx->decode_frame = decode_frame; + } + + for (i = 0; i < LP_FILTER_ORDER; i++) + ctx->lsp_history[i] = cos((i+1) * M_PI / (LP_FILTER_ORDER + 1)); + + for (i = 0; i < 4; i++) + ctx->energy_history[i] = -14; + + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + return 0; +} + +static int sipr_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + SiprContext *ctx = avctx->priv_data; + AVFrame *frame = data; + const uint8_t *buf=avpkt->data; + SiprParameters parm; + const SiprModeParam *mode_par = &modes[ctx->mode]; + GetBitContext gb; + float *samples; + int subframe_size = ctx->mode == MODE_16k ? L_SUBFR_16k : SUBFR_SIZE; + int i, ret; + + ctx->avctx = avctx; + if (avpkt->size < (mode_par->bits_per_frame >> 3)) { + av_log(avctx, AV_LOG_ERROR, + "Error processing packet: packet size (%d) too small\n", + avpkt->size); + return -1; + } + + /* get output buffer */ + frame->nb_samples = mode_par->frames_per_packet * subframe_size * + mode_par->subframe_count; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (float *)frame->data[0]; + + init_get_bits(&gb, buf, mode_par->bits_per_frame); + + for (i = 0; i < mode_par->frames_per_packet; i++) { + decode_parameters(&parm, &gb, mode_par); + + ctx->decode_frame(ctx, &parm, samples); + + samples += subframe_size * mode_par->subframe_count; + } + + *got_frame_ptr = 1; + + return mode_par->bits_per_frame >> 3; +} + +AVCodec ff_sipr_decoder = { + .name = "sipr", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SIPR, + .priv_data_size = sizeof(SiprContext), + .init = sipr_decoder_init, + .decode = sipr_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("RealAudio SIPR / ACELP.NET"), +}; diff --git a/ffmpeg/libavcodec/sipr.h b/ffmpeg/libavcodec/sipr.h new file mode 100644 index 0000000..34f7f99 --- /dev/null +++ b/ffmpeg/libavcodec/sipr.h @@ -0,0 +1,109 @@ +/* + * SIPR / ACELP.NET decoder + * + * Copyright (c) 2008 Vladimir Voroshilov + * Copyright (c) 2009 Vitor Sessak + * + * 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 + */ + +#ifndef AVCODEC_SIPR_H +#define AVCODEC_SIPR_H + +#include "avcodec.h" +#include "acelp_pitch_delay.h" +#include "libavutil/mem.h" + +#define LP_FILTER_ORDER_16k 16 +#define L_SUBFR_16k 80 +#define PITCH_MIN 30 +#define PITCH_MAX 281 + +#define LSFQ_DIFF_MIN (0.0125 * M_PI) + +#define LP_FILTER_ORDER 10 + +/** Number of past samples needed for excitation interpolation */ +#define L_INTERPOL (LP_FILTER_ORDER + 1) + +/** Subframe size for all modes except 16k */ +#define SUBFR_SIZE 48 + +#define SUBFRAME_COUNT_16k 2 + +typedef enum { + MODE_16k, + MODE_8k5, + MODE_6k5, + MODE_5k0, + MODE_COUNT +} SiprMode; + +typedef struct SiprParameters { + int ma_pred_switch; ///< switched moving average predictor + int vq_indexes[5]; + int pitch_delay[5]; ///< pitch delay + int gp_index[5]; ///< adaptive-codebook gain indexes + int16_t fc_indexes[5][10]; ///< fixed-codebook indexes + int gc_index[5]; ///< fixed-codebook gain indexes +} SiprParameters; + +typedef struct SiprContext { + AVCodecContext *avctx; + + SiprMode mode; + + float past_pitch_gain; + float lsf_history[LP_FILTER_ORDER_16k]; + + float excitation[L_INTERPOL + PITCH_MAX + 2 * L_SUBFR_16k]; + + DECLARE_ALIGNED(16, float, synth_buf)[LP_FILTER_ORDER + 5*SUBFR_SIZE + 6]; + + float lsp_history[LP_FILTER_ORDER]; + float gain_mem; + float energy_history[4]; + float highpass_filt_mem[2]; + float postfilter_mem[PITCH_DELAY_MAX + LP_FILTER_ORDER]; + + /* 5k0 */ + float tilt_mem; + float postfilter_agc; + float postfilter_mem5k0[PITCH_DELAY_MAX + LP_FILTER_ORDER]; + float postfilter_syn5k0[LP_FILTER_ORDER + SUBFR_SIZE*5]; + + /* 16k */ + int pitch_lag_prev; + float iir_mem[LP_FILTER_ORDER_16k+1]; + float filt_buf[2][LP_FILTER_ORDER_16k+1]; + float *filt_mem[2]; + float mem_preemph[LP_FILTER_ORDER_16k]; + float synth[LP_FILTER_ORDER_16k]; + double lsp_history_16k[16]; + + void (*decode_frame)(struct SiprContext *ctx, SiprParameters *params, + float *out_data); +} SiprContext; + +extern const float ff_pow_0_5[16]; + +void ff_sipr_init_16k(SiprContext *ctx); + +void ff_sipr_decode_frame_16k(SiprContext *ctx, SiprParameters *params, + float *out_data); + +#endif /* AVCODEC_SIPR_H */ diff --git a/ffmpeg/libavcodec/sipr16k.c b/ffmpeg/libavcodec/sipr16k.c new file mode 100644 index 0000000..fbf7497 --- /dev/null +++ b/ffmpeg/libavcodec/sipr16k.c @@ -0,0 +1,282 @@ +/* + * SIPR decoder for the 16k mode + * + * Copyright (c) 2008 Vladimir Voroshilov + * Copyright (c) 2009 Vitor Sessak + * + * 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 "sipr.h" +#include "libavutil/common.h" +#include "libavutil/float_dsp.h" +#include "libavutil/mathematics.h" +#include "lsp.h" +#include "celp_filters.h" +#include "acelp_vectors.h" +#include "acelp_pitch_delay.h" +#include "acelp_filters.h" +#include "celp_filters.h" + +#include "sipr16kdata.h" + +/** + * Convert an lsf vector into an lsp vector. + * + * @param lsf input lsf vector + * @param lsp output lsp vector + */ +static void lsf2lsp(const float *lsf, double *lsp) +{ + int i; + + for (i = 0; i < LP_FILTER_ORDER_16k; i++) + lsp[i] = cosf(lsf[i]); +} + +static void dequant(float *out, const int *idx, const float *cbs[]) +{ + int i; + + for (i = 0; i < 4; i++) + memcpy(out + 3*i, cbs[i] + 3*idx[i], 3*sizeof(float)); + + memcpy(out + 12, cbs[4] + 4*idx[4], 4*sizeof(float)); +} + +static void lsf_decode_fp_16k(float* lsf_history, float* isp_new, + const int* parm, int ma_pred) +{ + int i; + float isp_q[LP_FILTER_ORDER_16k]; + + dequant(isp_q, parm, lsf_codebooks_16k); + + for (i = 0; i < LP_FILTER_ORDER_16k; i++) { + isp_new[i] = (1 - qu[ma_pred]) * isp_q[i] + + qu[ma_pred] * lsf_history[i] + + mean_lsf_16k[i]; + } + + memcpy(lsf_history, isp_q, LP_FILTER_ORDER_16k * sizeof(float)); +} + +static int dec_delay3_1st(int index) +{ + if (index < 390) { + return index + 88; + } else + return 3 * index - 690; +} + +static int dec_delay3_2nd(int index, int pit_min, int pit_max, + int pitch_lag_prev) +{ + if (index < 62) { + int pitch_delay_min = av_clip(pitch_lag_prev - 10, + pit_min, pit_max - 19); + return 3 * pitch_delay_min + index - 2; + } else + return 3 * pitch_lag_prev; +} + +static void postfilter(float *out_data, float* synth, float* iir_mem, + float* filt_mem[2], float* mem_preemph) +{ + float buf[30 + LP_FILTER_ORDER_16k]; + float *tmpbuf = buf + LP_FILTER_ORDER_16k; + float s; + int i; + + for (i = 0; i < LP_FILTER_ORDER_16k; i++) + filt_mem[0][i] = iir_mem[i] * ff_pow_0_5[i]; + + memcpy(tmpbuf - LP_FILTER_ORDER_16k, mem_preemph, + LP_FILTER_ORDER_16k*sizeof(*buf)); + + ff_celp_lp_synthesis_filterf(tmpbuf, filt_mem[1], synth, 30, + LP_FILTER_ORDER_16k); + + memcpy(synth - LP_FILTER_ORDER_16k, mem_preemph, + LP_FILTER_ORDER_16k * sizeof(*synth)); + + ff_celp_lp_synthesis_filterf(synth, filt_mem[0], synth, 30, + LP_FILTER_ORDER_16k); + + memcpy(out_data + 30 - LP_FILTER_ORDER_16k, + synth + 30 - LP_FILTER_ORDER_16k, + LP_FILTER_ORDER_16k * sizeof(*synth)); + + ff_celp_lp_synthesis_filterf(out_data + 30, filt_mem[0], + synth + 30, 2 * L_SUBFR_16k - 30, + LP_FILTER_ORDER_16k); + + + memcpy(mem_preemph, out_data + 2*L_SUBFR_16k - LP_FILTER_ORDER_16k, + LP_FILTER_ORDER_16k * sizeof(*synth)); + + FFSWAP(float *, filt_mem[0], filt_mem[1]); + for (i = 0, s = 0; i < 30; i++, s += 1.0/30) + out_data[i] = tmpbuf[i] + s * (synth[i] - tmpbuf[i]); +} + +/** + * Floating point version of ff_acelp_lp_decode(). + */ +static void acelp_lp_decodef(float *lp_1st, float *lp_2nd, + const double *lsp_2nd, const double *lsp_prev) +{ + double lsp_1st[LP_FILTER_ORDER_16k]; + int i; + + /* LSP values for first subframe (3.2.5 of G.729, Equation 24) */ + for (i = 0; i < LP_FILTER_ORDER_16k; i++) + lsp_1st[i] = (lsp_2nd[i] + lsp_prev[i]) * 0.5; + + ff_acelp_lspd2lpc(lsp_1st, lp_1st, LP_FILTER_ORDER_16k >> 1); + + /* LSP values for second subframe (3.2.5 of G.729) */ + ff_acelp_lspd2lpc(lsp_2nd, lp_2nd, LP_FILTER_ORDER_16k >> 1); +} + +/** + * Floating point version of ff_acelp_decode_gain_code(). + */ +static float acelp_decode_gain_codef(float gain_corr_factor, const float *fc_v, + float mr_energy, const float *quant_energy, + const float *ma_prediction_coeff, + int subframe_size, int ma_pred_order) +{ + mr_energy += avpriv_scalarproduct_float_c(quant_energy, ma_prediction_coeff, + ma_pred_order); + + mr_energy = gain_corr_factor * exp(M_LN10 / 20. * mr_energy) / + sqrt((0.01 + avpriv_scalarproduct_float_c(fc_v, fc_v, subframe_size))); + return mr_energy; +} + +#define DIVIDE_BY_3(x) ((x) * 10923 >> 15) + +void ff_sipr_decode_frame_16k(SiprContext *ctx, SiprParameters *params, + float *out_data) +{ + int frame_size = SUBFRAME_COUNT_16k * L_SUBFR_16k; + float *synth = ctx->synth_buf + LP_FILTER_ORDER_16k; + float lsf_new[LP_FILTER_ORDER_16k]; + double lsp_new[LP_FILTER_ORDER_16k]; + float Az[2][LP_FILTER_ORDER_16k]; + float fixed_vector[L_SUBFR_16k]; + float pitch_fac, gain_code; + + int i; + int pitch_delay_3x; + + float *excitation = ctx->excitation + 292; + + lsf_decode_fp_16k(ctx->lsf_history, lsf_new, params->vq_indexes, + params->ma_pred_switch); + + ff_set_min_dist_lsf(lsf_new, LSFQ_DIFF_MIN / 2, LP_FILTER_ORDER_16k); + + lsf2lsp(lsf_new, lsp_new); + + acelp_lp_decodef(Az[0], Az[1], lsp_new, ctx->lsp_history_16k); + + memcpy(ctx->lsp_history_16k, lsp_new, LP_FILTER_ORDER_16k * sizeof(double)); + + memcpy(synth - LP_FILTER_ORDER_16k, ctx->synth, + LP_FILTER_ORDER_16k * sizeof(*synth)); + + for (i = 0; i < SUBFRAME_COUNT_16k; i++) { + int i_subfr = i * L_SUBFR_16k; + AMRFixed f; + float gain_corr_factor; + int pitch_delay_int; + int pitch_delay_frac; + + if (!i) { + pitch_delay_3x = dec_delay3_1st(params->pitch_delay[i]); + } else + pitch_delay_3x = dec_delay3_2nd(params->pitch_delay[i], + PITCH_MIN, PITCH_MAX, + ctx->pitch_lag_prev); + + pitch_fac = gain_pitch_cb_16k[params->gp_index[i]]; + f.pitch_fac = FFMIN(pitch_fac, 1.0); + f.pitch_lag = DIVIDE_BY_3(pitch_delay_3x+1); + ctx->pitch_lag_prev = f.pitch_lag; + + pitch_delay_int = DIVIDE_BY_3(pitch_delay_3x + 2); + pitch_delay_frac = pitch_delay_3x + 2 - 3*pitch_delay_int; + + ff_acelp_interpolatef(&excitation[i_subfr], + &excitation[i_subfr] - pitch_delay_int + 1, + sinc_win, 3, pitch_delay_frac + 1, + LP_FILTER_ORDER, L_SUBFR_16k); + + + memset(fixed_vector, 0, sizeof(fixed_vector)); + + ff_decode_10_pulses_35bits(params->fc_indexes[i], &f, + ff_fc_4pulses_8bits_tracks_13, 5, 4); + + ff_set_fixed_vector(fixed_vector, &f, 1.0, L_SUBFR_16k); + + gain_corr_factor = gain_cb_16k[params->gc_index[i]]; + gain_code = gain_corr_factor * + acelp_decode_gain_codef(sqrt(L_SUBFR_16k), fixed_vector, + 19.0 - 15.0/(0.05*M_LN10/M_LN2), + pred_16k, ctx->energy_history, + L_SUBFR_16k, 2); + + ctx->energy_history[1] = ctx->energy_history[0]; + ctx->energy_history[0] = 20.0 * log10f(gain_corr_factor); + + ff_weighted_vector_sumf(&excitation[i_subfr], &excitation[i_subfr], + fixed_vector, pitch_fac, + gain_code, L_SUBFR_16k); + + ff_celp_lp_synthesis_filterf(synth + i_subfr, Az[i], + &excitation[i_subfr], L_SUBFR_16k, + LP_FILTER_ORDER_16k); + + } + memcpy(ctx->synth, synth + frame_size - LP_FILTER_ORDER_16k, + LP_FILTER_ORDER_16k * sizeof(*synth)); + + memmove(ctx->excitation, ctx->excitation + 2 * L_SUBFR_16k, + (L_INTERPOL+PITCH_MAX) * sizeof(float)); + + postfilter(out_data, synth, ctx->iir_mem, ctx->filt_mem, ctx->mem_preemph); + + memcpy(ctx->iir_mem, Az[1], LP_FILTER_ORDER_16k * sizeof(float)); +} + +void ff_sipr_init_16k(SiprContext *ctx) +{ + int i; + + for (i = 0; i < LP_FILTER_ORDER_16k; i++) + ctx->lsp_history_16k[i] = cos((i + 1) * M_PI/(LP_FILTER_ORDER_16k + 1)); + + ctx->filt_mem[0] = ctx->filt_buf[0]; + ctx->filt_mem[1] = ctx->filt_buf[1]; + + ctx->pitch_lag_prev = 180; +} diff --git a/ffmpeg/libavcodec/sipr16kdata.h b/ffmpeg/libavcodec/sipr16kdata.h new file mode 100644 index 0000000..96bf0e9 --- /dev/null +++ b/ffmpeg/libavcodec/sipr16kdata.h @@ -0,0 +1,533 @@ +/* + * SIPR decoder for the 16k mode + * + * Copyright (c) 2008 Vladimir Voroshilov + * Copyright (c) 2009 Vitor Sessak + * + * 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 + */ + +#ifndef AVCODEC_SIPR16KDATA_H +#define AVCODEC_SIPR16KDATA_H + +static const float pred_16k[2] = {0.8, 0.6}; +static const float qu[2] = { 0.12, 0.5}; + +static const float gain_cb_16k[32] = { + 0.07499, 0.10593, 0.14125, 0.18836, + 0.23714, 0.28184, 0.32734, 0.37584, + 0.42170, 0.47315, 0.53088, 0.59566, + 0.66834, 0.74989, 0.84140, 0.94406, + 1.05925, 1.18850, 1.33352, 1.49624, + 1.67880, 1.88365, 2.11349, 2.37137, + 2.66073, 3.05492, 3.54813, 4.21697, + 5.30884, 7.07946, 9.44061, 13.33521, +}; + +static const float gain_pitch_cb_16k[16] = { + 0.00, 0.2, 0.40, 0.5, 0.60, 0.7, 0.75, 0.8, + 0.85, 0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, +}; + + +static const float mean_lsf_16k[16] = { + 0.131554, 0.246615, 0.435896, 0.644419, + 0.827810, 1.017876, 1.198910, 1.379159, + 1.562157, 1.736908, 1.940719, 2.131963, + 2.347162, 2.521521, 2.717870, 2.847068 +}; + +/** + * Hamming windowed sinc function, like in AMR + */ +static const float sinc_win[40] = { + 0.874475, 0.755101, 0.455962, 0.118807, -0.114223, -0.176778, + -0.101923, 0.015553, 0.086555, 0.078193, 0.018660, -0.037513, + -0.052733, -0.027459, 0.009967, 0.030278, 0.024050, 0.003055, + -0.013862, -0.016162, -0.006725, 0.004212, 0.008634, 0.005721, + -0.000000, -0.003710, -0.003690, -0.001228, 0.001409, 0.002610, +}; + +static const float lsf_cb1_16k[128][3] = { + {-0.089990, -0.172485, -0.203391}, {-0.094710, -0.178687, -0.134483}, + {-0.056398, -0.131952, -0.154500}, {-0.051362, -0.128138, -0.198549}, + {-0.061700, -0.142830, -0.251623}, {-0.041512, -0.115637, -0.229420}, + {-0.036544, -0.107512, -0.173125}, {-0.024158, -0.088450, -0.204144}, + {-0.038690, -0.103368, -0.132674}, {-0.056954, -0.128472, -0.104669}, + {-0.020963, -0.076785, -0.163199}, {-0.012952, -0.077249, -0.128385}, + {-0.032787, -0.097044, -0.093967}, {-0.035214, -0.053838, -0.111940}, + {-0.013850, -0.036926, -0.139328}, {-0.004956, -0.065092, -0.087709}, + {-0.065354, -0.065595, -0.079064}, {-0.023627, -0.081457, -0.054195}, + {-0.027335, -0.035244, -0.068034}, { 0.016555, -0.047075, -0.128286}, + { 0.021066, -0.037252, -0.092041}, { 0.014681, -0.043044, -0.057739}, + {-0.008493, -0.008143, -0.102486}, {-0.002303, -0.061540, -0.022952}, + {-0.006061, -0.014278, -0.033652}, {-0.005276, 0.011246, -0.062762}, + { 0.043411, -0.006303, -0.063730}, { 0.035885, -0.010052, -0.115290}, + { 0.030628, -0.031538, -0.017807}, { 0.022345, 0.028210, -0.032335}, + { 0.026535, 0.027536, -0.091150}, {-0.003365, -0.008077, 0.015687}, + {-0.026013, 0.017493, -0.010355}, { 0.059069, 0.010634, -0.007530}, + { 0.044038, -0.019424, 0.030453}, {-0.036065, -0.034215, -0.007758}, + { 0.022486, 0.042543, 0.027870}, {-0.049985, -0.016085, 0.021768}, + {-0.021715, 0.021168, 0.052076}, {-0.004243, -0.061228, 0.027640}, + {-0.033950, -0.017287, 0.064656}, { 0.016151, 0.000727, 0.062757}, + {-0.063456, -0.043152, 0.056707}, {-0.067715, 0.006126, 0.058178}, + {-0.038931, 0.051673, 0.030636}, {-0.073017, -0.074716, 0.026387}, + {-0.039893, -0.104629, 0.039616}, {-0.073179, -0.074601, 0.082069}, + {-0.066154, -0.027180, 0.099439}, {-0.075167, -0.121149, 0.071938}, + {-0.030382, -0.092582, 0.091067}, {-0.084519, -0.137542, 0.023626}, + {-0.060956, -0.121259, -0.015264}, {-0.030069, -0.093823, -0.008692}, + {-0.063564, -0.065225, -0.025820}, {-0.052074, -0.117595, -0.059689}, + {-0.091652, -0.165173, -0.045573}, {-0.070167, -0.121342, 0.131707}, + {-0.061024, -0.005833, -0.051035}, { 0.007837, -0.051816, 0.074575}, + {-0.070643, -0.053927, 0.149498}, {-0.014358, -0.066681, 0.139708}, + {-0.058186, 0.029576, 0.092923}, {-0.023371, 0.007058, 0.112484}, + {-0.057969, 0.022786, 0.148420}, { 0.029439, -0.017673, 0.121423}, + {-0.015811, 0.056785, 0.091594}, { 0.004347, 0.056680, 0.137848}, + {-0.004464, 0.002342, 0.184013}, { 0.029660, 0.046870, 0.082654}, + { 0.059408, 0.001016, 0.086063}, { 0.055263, 0.027574, 0.155037}, + { 0.062166, 0.064323, 0.117371}, { 0.022967, 0.100050, 0.077227}, + { 0.041795, 0.096343, 0.170421}, { 0.053189, 0.122931, 0.118549}, + { 0.094247, 0.094448, 0.078395}, { 0.082407, 0.033408, 0.041085}, + { 0.096820, 0.115960, 0.149433}, { 0.067804, 0.121849, 0.025336}, + {-0.008421, 0.104316, 0.032314}, { 0.031013, 0.073218, -0.004899}, + { 0.085079, 0.060323, -0.009687}, { 0.028174, 0.092766, -0.055590}, + { 0.070133, 0.039160, -0.061035}, {-0.039211, 0.072517, -0.028756}, + { 0.129686, 0.100233, -0.046998}, { 0.154189, 0.107616, 0.022791}, + {-0.049331, 0.094184, 0.087984}, {-0.013179, 0.126552, 0.125099}, + {-0.058716, 0.098524, 0.150886}, {-0.022753, 0.080011, 0.191127}, + { 0.013451, 0.164593, 0.153768}, { 0.074818, 0.181214, 0.108211}, + { 0.091323, 0.169249, 0.168460}, { 0.033885, 0.155516, 0.213745}, + {-0.032128, 0.227238, 0.135815}, {-0.059176, 0.168980, 0.229110}, + { 0.033917, 0.229753, 0.222264}, { 0.082702, 0.116370, 0.224697}, + { 0.127737, 0.186658, 0.212783}, { 0.047528, 0.063920, 0.216856}, + {-0.002446, 0.114174, 0.263289}, {-0.077783, 0.082523, 0.249697}, + { 0.010023, 0.024267, 0.256874}, { 0.053190, 0.111422, 0.310407}, + {-0.078804, 0.004444, 0.224078}, {-0.055253, -0.059180, 0.217892}, + {-0.065371, 0.008124, 0.333405}, {-0.076188, -0.098767, 0.286983}, + {-0.071911, -0.115804, 0.198031}, {-0.062473, 0.183639, 0.370162}, + {-0.042666, 0.255210, 0.262720}, { 0.011999, 0.217530, 0.318291}, + {-0.042144, 0.322087, 0.326387}, { 0.090663, 0.205835, 0.294784}, + { 0.058218, 0.293649, 0.277927}, { 0.157506, 0.282870, 0.294610}, + { 0.118248, 0.261007, 0.148614}, { 0.065261, 0.332362, 0.411912}, + { 0.141269, 0.451850, 0.315726}, { 0.001706, 0.456301, 0.357590}, + {-0.052947, 0.356559, 0.456944}, { 0.247707, 0.263837, 0.152591}, + { 0.306847, 0.417373, 0.258553}, { 0.166347, 0.149222, 0.118973}, + { 0.379709, 0.292172, 0.139875}, { 0.010171, -0.055170, -0.174523} +}; + +static const float lsf_cb2_16k[256][3] = { + {-0.213011, -0.293385, -0.330597}, {-0.212582, -0.240992, -0.338239}, + {-0.223373, -0.306214, -0.277192}, {-0.231138, -0.287729, -0.229412}, + {-0.238466, -0.228571, -0.260954}, {-0.140931, -0.247018, -0.258566}, + {-0.136239, -0.249669, -0.350143}, {-0.149738, -0.192970, -0.281475}, + {-0.167058, -0.261052, -0.196301}, {-0.177049, -0.201324, -0.207897}, + {-0.116915, -0.200629, -0.212526}, {-0.162247, -0.143805, -0.245093}, + {-0.082042, -0.191842, -0.266338}, {-0.098846, -0.208511, -0.320481}, + {-0.113510, -0.152470, -0.222474}, {-0.066197, -0.179112, -0.207813}, + {-0.129490, -0.169320, -0.155238}, {-0.078843, -0.190292, -0.155172}, + {-0.087790, -0.147729, -0.169351}, {-0.141037, -0.127207, -0.177910}, + {-0.126525, -0.223961, -0.153639}, {-0.101464, -0.189953, -0.114559}, + {-0.102450, -0.106303, -0.151171}, {-0.103208, -0.144457, -0.105378}, + {-0.170794, -0.140525, -0.136428}, {-0.168641, -0.203064, -0.135368}, + {-0.138193, -0.116042, -0.111905}, {-0.145085, -0.168581, -0.092613}, + {-0.126379, -0.220431, -0.091327}, {-0.212934, -0.184797, -0.101632}, + {-0.193711, -0.140556, -0.078304}, {-0.173674, -0.197276, -0.060140}, + {-0.197897, -0.241907, -0.091997}, {-0.156037, -0.258519, -0.111628}, + {-0.241964, -0.191124, -0.063140}, {-0.261340, -0.240847, -0.103132}, + {-0.221621, -0.242972, -0.041255}, {-0.224166, -0.232742, -0.161568}, + {-0.203591, -0.294470, -0.126035}, {-0.209540, -0.303149, -0.053170}, + {-0.253859, -0.295066, -0.156050}, {-0.278143, -0.331105, -0.085237}, + {-0.300273, -0.198750, -0.094834}, {-0.260477, -0.169713, -0.132476}, + {-0.211889, -0.172454, -0.164281}, {-0.228370, -0.122149, -0.124178}, + {-0.254629, -0.135668, -0.081692}, {-0.263813, -0.154928, -0.213596}, + {-0.308224, -0.106877, -0.084404}, {-0.242644, -0.082862, -0.085835}, + {-0.252084, -0.064888, -0.146498}, {-0.198162, -0.105721, -0.188887}, + {-0.189238, -0.088028, -0.109736}, {-0.197598, -0.099831, -0.044030}, + {-0.269017, -0.105991, -0.021513}, {-0.231349, -0.058825, -0.041407}, + {-0.225589, -0.027501, -0.087160}, {-0.160347, -0.058341, -0.079789}, + {-0.158729, -0.108951, -0.067262}, {-0.170483, -0.053023, -0.017561}, + {-0.175207, -0.013649, -0.049513}, {-0.156004, -0.108378, -0.004052}, + {-0.219958, -0.082362, 0.014950}, {-0.217785, -0.012981, -0.009410}, + {-0.123290, -0.040849, -0.040910}, {-0.119861, -0.095078, -0.060246}, + {-0.117537, -0.065479, 0.002968}, {-0.103231, -0.113298, -0.023282}, + {-0.136365, -0.149524, -0.051387}, {-0.119332, -0.164400, -0.009103}, + {-0.104522, -0.060948, -0.083056}, {-0.071461, -0.070787, -0.037347}, + {-0.081116, -0.149015, -0.056740}, {-0.069561, -0.108099, -0.069167}, + {-0.055624, -0.117369, -0.025091}, {-0.091941, -0.190091, -0.060020}, + {-0.072003, -0.168433, -0.006540}, {-0.033305, -0.154427, -0.054608}, + {-0.062988, -0.127093, -0.108307}, {-0.056690, -0.170813, -0.102834}, + {-0.018273, -0.127863, -0.094998}, {-0.056239, -0.123678, -0.146262}, + {-0.023442, -0.154617, -0.137417}, {-0.051903, -0.078379, -0.093395}, + {-0.014599, -0.104412, -0.135959}, {-0.051582, -0.081280, -0.140643}, + {-0.092727, -0.091930, -0.107816}, {-0.024814, -0.140993, -0.183243}, + {-0.064307, -0.113024, -0.194788}, {-0.000118, -0.098858, -0.195336}, + {-0.028090, -0.048258, -0.164101}, {-0.093414, -0.055969, -0.172743}, + {-0.114445, -0.104336, -0.215204}, {-0.048518, -0.132063, -0.242991}, + {-0.159620, -0.060240, -0.178592}, {-0.135728, -0.067473, -0.131876}, + {-0.078464, -0.038040, -0.125105}, {-0.011061, -0.064011, -0.102496}, + {-0.033887, -0.026485, -0.109493}, {-0.129128, -0.014216, -0.111329}, + {-0.190687, -0.030660, -0.135825}, {-0.082037, 0.010997, -0.100167}, + {-0.183403, 0.001651, -0.098962}, {-0.074775, -0.030335, -0.062217}, + {-0.031759, -0.050551, -0.059420}, {-0.051439, 0.010827, -0.052148}, + {-0.126744, 0.008689, -0.047785}, {-0.145916, 0.042019, -0.077431}, + {-0.093552, 0.054143, -0.060473}, {-0.090660, 0.012868, -0.018195}, + {-0.079783, -0.033071, 0.001482}, {-0.033010, -0.022331, -0.014506}, + {-0.004798, -0.017339, -0.060120}, {-0.025021, 0.026390, -0.003263}, + {-0.001437, 0.025994, -0.040892}, {-0.074821, 0.019005, 0.027549}, + {-0.030811, -0.012114, 0.034284}, { 0.006785, 0.004618, 0.018717}, + { 0.013392, -0.032597, -0.023731}, { 0.035994, 0.005963, -0.011757}, + { 0.008071, -0.045750, 0.024889}, { 0.013055, 0.017040, 0.054121}, + {-0.012989, 0.044864, 0.036327}, { 0.025054, 0.047137, 0.009974}, + { 0.053801, 0.024178, 0.031774}, { 0.056442, -0.030647, 0.021291}, + { 0.032247, 0.052680, 0.049886}, { 0.035369, 0.090207, 0.031394}, + { 0.064720, 0.070390, 0.040938}, { 0.022112, 0.054834, 0.091059}, + { 0.041765, 0.086248, 0.070196}, { 0.070645, 0.060852, 0.078825}, + { 0.058506, 0.016920, 0.081612}, { 0.000009, 0.086500, 0.059849}, + { 0.071253, 0.107392, 0.059046}, { 0.094702, 0.096160, 0.090982}, + { 0.047639, 0.110877, 0.111227}, { 0.122444, 0.090909, 0.057396}, + { 0.101916, 0.052299, 0.029909}, { 0.076560, 0.086094, -0.007252}, + { 0.123411, 0.030769, 0.082749}, { 0.135579, 0.103022, 0.009540}, + { 0.120576, 0.065284, -0.024095}, { 0.077483, 0.028526, -0.012369}, + { 0.128747, 0.017901, -0.003874}, { 0.158254, 0.046962, 0.029577}, + { 0.102287, -0.002211, 0.037329}, { 0.089654, -0.021372, -0.006857}, + { 0.137917, 0.027228, -0.053223}, { 0.098728, -0.012192, -0.048518}, + { 0.083974, 0.036153, -0.062266}, { 0.048230, -0.010241, -0.052293}, + { 0.110135, 0.007715, -0.095233}, { 0.068294, -0.014317, -0.104029}, + { 0.063909, -0.056416, -0.063023}, { 0.059133, -0.044675, -0.023780}, + { 0.030748, 0.021845, -0.086332}, { 0.023994, -0.045574, -0.076232}, + { 0.052147, -0.059825, -0.109667}, { 0.013087, -0.020420, -0.121945}, + { 0.018163, -0.096765, -0.088758}, { 0.020196, -0.076470, -0.048112}, + { 0.020282, -0.084204, -0.135535}, { 0.040076, -0.053464, -0.161949}, + {-0.017796, -0.103070, -0.059559}, {-0.016484, -0.070138, -0.016866}, + { 0.004849, -0.112481, -0.017731}, { 0.040160, -0.073873, -0.005327}, + { 0.002202, -0.094723, 0.045366}, {-0.056918, -0.081578, 0.017875}, + {-0.031099, -0.141708, 0.009186}, {-0.102802, -0.122675, 0.030060}, + {-0.061717, -0.145116, 0.076680}, {-0.073607, -0.050464, 0.072853}, + {-0.117403, -0.194921, 0.040101}, {-0.185236, -0.133620, 0.045939}, + {-0.160174, -0.057226, 0.056641}, {-0.178489, -0.173435, -0.007806}, + {-0.199916, -0.204866, 0.047342}, {-0.152337, -0.249651, 0.034656}, + {-0.185637, -0.230942, -0.002072}, {-0.122548, -0.215209, -0.024552}, + {-0.249578, -0.209714, 0.009470}, {-0.160108, -0.257702, -0.040992}, + {-0.216694, -0.289353, 0.027182}, {-0.226390, -0.147844, -0.022742}, + {-0.288737, -0.272150, -0.013948}, {-0.262554, -0.237035, 0.072473}, + {-0.306267, -0.188335, -0.032894}, {-0.259666, -0.345816, 0.024138}, + {-0.271093, -0.137143, 0.040404}, {-0.201317, -0.286782, 0.107615}, + {-0.235725, -0.163396, 0.113844}, {-0.159988, -0.209788, 0.112140}, + {-0.262985, -0.056741, 0.093506}, {-0.277226, -0.037306, 0.016008}, + {-0.293486, -0.040422, -0.062018}, {-0.214921, 0.022900, 0.055295}, + {-0.253889, 0.058575, -0.000151}, {-0.246689, 0.024242, -0.058488}, + {-0.143790, 0.006767, 0.014061}, {-0.187077, 0.048882, -0.035625}, + {-0.196369, 0.112085, 0.031546}, {-0.124264, 0.086197, -0.020800}, + {-0.126249, 0.016960, 0.095741}, {-0.079816, 0.080398, 0.051038}, + {-0.056269, 0.075380, -0.028262}, {-0.120493, 0.148495, 0.028430}, + {-0.161750, 0.101290, 0.117806}, {-0.003247, 0.083393, -0.017061}, + {-0.034007, 0.142542, 0.007402}, {-0.037618, 0.025871, 0.089496}, + {-0.082819, 0.184435, 0.073224}, { 0.006448, 0.167015, 0.080548}, + { 0.035315, 0.144022, 0.003218}, {-0.023459, 0.088147, 0.152604}, + { 0.006247, -0.024099, 0.077792}, { 0.039894, 0.057586, -0.042455}, + {-0.020417, 0.035400, -0.093971}, { 0.075465, 0.052063, 0.145582}, + { 0.078027, 0.184720, 0.092096}, { 0.107295, 0.148380, 0.022264}, + { 0.066928, -0.052831, 0.065108}, { 0.093295, 0.118157, 0.149815}, + { 0.119373, 0.137114, 0.099536}, { 0.138653, 0.075509, 0.121545}, + { 0.174025, 0.077531, 0.077169}, { 0.165839, 0.150080, 0.133423}, + { 0.173276, 0.155887, 0.048150}, { 0.162910, 0.095898, 0.171896}, + { 0.214577, 0.112888, 0.115579}, { 0.204755, 0.106392, 0.032337}, + { 0.178853, 0.205034, 0.114760}, { 0.177401, 0.070504, -0.013778}, + { 0.241624, 0.166921, 0.066087}, { 0.219595, 0.183553, 0.172332}, + { 0.123671, 0.170842, 0.167216}, { 0.177104, 0.240197, 0.186359}, + { 0.272003, 0.220214, 0.126073}, { 0.093748, 0.235843, 0.160998}, + { 0.141510, 0.190012, 0.240416}, { 0.046878, 0.168984, 0.190412}, + { 0.094898, 0.107038, 0.235003}, { 0.108592, 0.269536, 0.262528}, + {-0.027754, 0.234355, 0.134544}, { 0.265127, 0.267540, 0.199041}, + { 0.199523, 0.291507, 0.265171}, { 0.266177, 0.209339, 0.350369}, + { 0.322159, 0.344794, 0.270823}, { 0.399957, 0.264065, 0.110387}, + { 0.277817, 0.127407, -0.035625}, {-0.177038, 0.208155, 0.119077}, + { 0.049075, -0.076294, 0.145711}, { 0.187246, 0.042865, -0.127097}, + { 0.117885, -0.023489, -0.138658}, {-0.284256, 0.068153, 0.124259} +}; + +static const float lsf_cb3_16k[128][3] = { + {-0.223412, -0.236300, -0.188067}, {-0.202286, -0.218711, -0.102947}, + {-0.251652, -0.161020, -0.125280}, {-0.169223, -0.138155, -0.140430}, + {-0.176427, -0.146628, -0.222632}, {-0.120584, -0.187276, -0.180164}, + {-0.195559, -0.074225, -0.169109}, {-0.144551, -0.142774, -0.073340}, + {-0.111001, -0.111310, -0.130696}, {-0.095221, -0.174684, -0.111841}, + {-0.112158, -0.103049, -0.195130}, {-0.059989, -0.142170, -0.157850}, + {-0.127598, -0.051759, -0.153109}, {-0.063753, -0.067898, -0.164117}, + {-0.141753, -0.068274, -0.091999}, {-0.060482, -0.101054, -0.099475}, + {-0.104699, -0.104456, -0.066496}, {-0.073649, -0.052614, -0.091612}, + {-0.088268, -0.019072, -0.129956}, {-0.018837, -0.104115, -0.127837}, + {-0.021630, -0.033055, -0.129868}, {-0.083768, -0.047549, -0.041407}, + {-0.055892, -0.108526, -0.043200}, {-0.027816, -0.062499, -0.048190}, + {-0.002248, -0.110428, -0.062868}, { 0.001270, -0.033245, -0.072404}, + {-0.042747, -0.013835, -0.033829}, {-0.037615, -0.147833, -0.083912}, + {-0.045023, 0.006011, -0.092182}, {-0.050411, -0.081832, 0.005787}, + { 0.000357, -0.104282, -0.009428}, {-0.003893, -0.047892, -0.001506}, + {-0.040077, -0.147110, -0.009065}, {-0.060858, -0.030972, 0.012999}, + {-0.014674, 0.001370, 0.005554}, {-0.101362, -0.126061, -0.001898}, + {-0.102519, -0.000390, -0.015721}, {-0.132687, -0.069608, -0.019928}, + {-0.102227, -0.076131, 0.043306}, {-0.055193, 0.027001, 0.011857}, + {-0.156427, -0.016629, 0.017480}, {-0.078736, 0.002809, 0.057979}, + {-0.157789, -0.016693, -0.055073}, {-0.179397, -0.095520, 0.022065}, + {-0.110219, 0.010408, -0.081927}, {-0.125392, 0.049111, 0.044595}, + {-0.112528, 0.063173, -0.024954}, {-0.185525, 0.053093, -0.032102}, + {-0.176887, -0.019379, -0.115125}, {-0.249706, -0.017664, -0.059188}, + {-0.200243, -0.103311, -0.066846}, {-0.055404, 0.045106, -0.046991}, + {-0.000544, 0.022690, -0.044831}, { 0.022298, -0.016367, -0.022509}, + { 0.028278, 0.017585, -0.100612}, { 0.061781, -0.020826, -0.068190}, + { 0.029157, -0.074477, -0.098898}, { 0.043073, -0.067234, -0.032293}, + { 0.060157, 0.034636, -0.034885}, { 0.071153, -0.013881, -0.009036}, + { 0.054196, -0.029989, -0.131139}, { 0.030193, 0.024976, 0.009861}, + { 0.055943, -0.045304, 0.031927}, { 0.033217, -0.002418, 0.038165}, + { 0.063814, 0.045625, 0.025309}, { 0.033689, 0.038819, 0.049700}, + { 0.073582, 0.028527, 0.060200}, {-0.007957, 0.022531, 0.043687}, + {-0.000984, 0.054518, 0.018742}, { 0.057004, 0.060916, 0.060573}, + { 0.009883, 0.015238, 0.080211}, { 0.022742, 0.070832, 0.068855}, + { 0.053001, 0.029790, 0.091446}, {-0.042447, 0.060379, 0.061462}, + { 0.076826, 0.062468, 0.089653}, { 0.039065, 0.069768, 0.119128}, + { 0.064145, 0.095353, 0.071621}, { 0.094411, 0.069527, 0.054197}, + { 0.042812, 0.093060, 0.027980}, { 0.094791, 0.099189, 0.101112}, + { 0.117611, 0.048601, 0.093111}, { 0.119951, 0.122758, 0.051546}, + { 0.103558, 0.085245, -0.010700}, { 0.150126, 0.059766, 0.020280}, + { 0.108066, 0.017170, 0.008606}, { 0.108422, 0.023253, -0.063942}, + { 0.019652, 0.072284, -0.030331}, { 0.192719, 0.075624, 0.071156}, + { 0.221140, 0.069191, -0.035085}, { 0.188367, 0.126200, 0.035225}, + { 0.185760, 0.043537, -0.101714}, {-0.042518, 0.099646, 0.003244}, + {-0.015308, -0.027521, 0.046006}, { 0.034086, -0.045777, 0.095989}, + { 0.007174, -0.093358, 0.046459}, {-0.051248, -0.062095, 0.083161}, + {-0.045626, -0.133301, 0.052997}, {-0.037840, 0.024042, 0.131097}, + {-0.020217, -0.115942, 0.126170}, {-0.134550, -0.036291, 0.111322}, + {-0.110576, -0.160024, 0.091841}, {-0.093308, -0.184958, 0.013939}, + {-0.082735, -0.167417, -0.051725}, {-0.169934, -0.173003, -0.007155}, + {-0.128244, -0.213123, -0.053337}, {-0.079852, -0.154116, -0.246546}, + {-0.032242, -0.108756, -0.204133}, {-0.140117, -0.199495, -0.284505}, + { 0.010842, -0.074979, -0.166333}, {-0.093313, 0.145006, 0.034110}, + {-0.039236, 0.113213, 0.111053}, { 0.040613, -0.031783, 0.174058}, + {-0.164232, 0.131421, 0.149842}, { 0.026893, 0.107281, 0.179297}, + { 0.047086, 0.158606, 0.103267}, {-0.070567, 0.210459, 0.134734}, + { 0.094392, 0.137050, 0.166892}, { 0.086039, 0.063657, 0.168825}, + { 0.159371, 0.120897, 0.154357}, { 0.147101, 0.160684, 0.114882}, + { 0.120158, 0.199650, 0.180948}, { 0.191417, 0.174500, 0.170734}, + { 0.159153, 0.142165, 0.233347}, { 0.232002, 0.150181, 0.102736}, + { 0.188299, 0.221738, 0.228748}, { 0.256786, 0.209685, 0.161534}, + { 0.257861, 0.247793, 0.250516}, {-0.164461, -0.000143, 0.232461} +}; + +static const float lsf_cb4_16k[128][3] = { + {-0.193369, -0.304643, -0.253777}, {-0.164125, -0.277786, -0.153116}, + {-0.135681, -0.209120, -0.211724}, {-0.121822, -0.215734, -0.292207}, + {-0.198781, -0.161674, -0.242538}, {-0.164147, -0.180570, -0.138070}, + {-0.095915, -0.198695, -0.154309}, {-0.248386, -0.234462, -0.136984}, + {-0.164968, -0.108318, -0.175635}, {-0.124171, -0.111809, -0.224402}, + {-0.067398, -0.157017, -0.195759}, {-0.090132, -0.119174, -0.165253}, + {-0.099460, -0.146895, -0.106799}, {-0.141493, -0.108103, -0.108880}, + {-0.085088, -0.098340, -0.109953}, {-0.105526, -0.054463, -0.154315}, + {-0.040480, -0.144285, -0.124042}, {-0.040969, -0.084039, -0.142880}, + {-0.049082, -0.118553, -0.066686}, {-0.096336, -0.087515, -0.055741}, + {-0.058605, -0.059327, -0.089275}, {-0.121842, -0.058681, -0.086949}, + {-0.053792, -0.022025, -0.124451}, {-0.036744, -0.068891, -0.045865}, + { 0.003900, -0.098237, -0.091158}, {-0.001664, -0.045089, -0.081353}, + {-0.072829, -0.034087, -0.038416}, {-0.100822, -0.007330, -0.088715}, + {-0.035911, -0.005864, -0.062577}, {-0.020205, -0.026547, -0.019634}, + { 0.004291, -0.041290, -0.138181}, { 0.023404, -0.010932, -0.044904}, + { 0.013557, 0.014823, -0.092943}, { 0.059673, -0.031024, -0.095739}, + { 0.021130, -0.080607, -0.034594}, { 0.024655, -0.035564, 0.003243}, + { 0.017106, 0.006952, -0.000308}, { 0.075208, -0.030910, -0.031181}, + { 0.024965, 0.048632, -0.039448}, { 0.057028, 0.021547, -0.009418}, + {-0.018577, 0.023697, -0.009759}, { 0.024077, 0.033053, 0.024324}, + { 0.037052, -0.003436, 0.044530}, {-0.012871, -0.007179, 0.031795}, + { 0.077877, 0.021547, 0.023131}, { 0.053365, 0.052078, 0.029433}, + { 0.011429, 0.070426, 0.028734}, {-0.001827, 0.033115, 0.061505}, + {-0.044870, 0.038568, 0.026239}, { 0.061633, 0.034799, 0.059784}, + { 0.034261, 0.060342, 0.065185}, { 0.058981, 0.082481, 0.047252}, + { 0.090008, 0.065942, 0.044470}, { 0.066961, 0.073728, -0.000428}, + { 0.074763, 0.060293, 0.085632}, { 0.066366, 0.103375, 0.079642}, + { 0.122297, 0.036558, 0.058745}, { 0.111042, 0.092093, 0.085412}, + { 0.099243, 0.115476, 0.039254}, { 0.019973, 0.122844, 0.050255}, + { 0.159571, 0.098965, 0.051740}, { 0.137624, 0.072405, -0.006922}, + { 0.130240, 0.146091, 0.089698}, { 0.138335, 0.092968, 0.136193}, + { 0.066031, 0.149304, 0.125476}, { 0.202749, 0.145751, 0.077122}, + { 0.002224, 0.082811, 0.131200}, { 0.124476, 0.178073, 0.162336}, + { 0.174722, 0.190298, 0.127106}, { 0.202193, 0.153569, 0.163840}, + { 0.242604, 0.197796, 0.136929}, { 0.185809, 0.229348, 0.193353}, + {-0.058814, 0.195178, 0.141821}, { 0.253646, 0.247175, 0.205766}, + { 0.061433, -0.025542, 0.119311}, {-0.057816, 0.082445, 0.073243}, + {-0.069239, 0.148678, 0.031146}, {-0.030217, -0.008503, 0.106194}, + {-0.026708, 0.087469, -0.009589}, {-0.090418, 0.000265, 0.056807}, + {-0.050607, -0.019383, 0.010494}, {-0.079397, 0.008233, -0.011469}, + {-0.072634, -0.061165, 0.046917}, {-0.075741, -0.072343, -0.007557}, + {-0.025162, -0.073363, 0.005173}, {-0.123371, -0.041257, -0.008375}, + {-0.139904, 0.018285, 0.009920}, {-0.143421, -0.104238, 0.033457}, + {-0.100923, -0.134400, -0.023257}, {-0.157791, -0.095042, -0.036959}, + {-0.219890, -0.078637, 0.001815}, {-0.183607, -0.023053, -0.043678}, + {-0.145303, -0.158923, -0.059045}, {-0.197615, -0.165199, 0.028099}, + {-0.225131, -0.167756, -0.056401}, {-0.216572, -0.104751, -0.102964}, + {-0.171336, -0.241967, -0.063404}, {-0.134035, -0.205614, 0.011831}, + {-0.297116, -0.211173, -0.015352}, {-0.086464, -0.200592, -0.070454}, + {-0.217777, -0.278403, 0.030398}, {-0.236248, -0.323694, -0.087588}, + {-0.222074, -0.210785, 0.106210}, {-0.283400, -0.097077, 0.041303}, + {-0.078417, -0.154464, 0.062956}, {-0.214417, -0.100695, 0.121909}, + {-0.178576, -0.028847, 0.061042}, {-0.037999, -0.144233, -0.010546}, + {-0.086695, -0.070996, 0.125282}, { 0.010788, -0.085006, 0.058527}, + {-0.154015, 0.066560, 0.071038}, {-0.143503, 0.033260, 0.154393}, + {-0.134069, 0.032420, -0.056293}, {-0.110851, 0.086908, 0.003920}, + {-0.057254, 0.047674, -0.055571}, {-0.214206, 0.068784, -0.004735}, + {-0.257264, 0.050468, 0.081702}, {-0.291834, 0.004120, -0.022366}, + {-0.173309, -0.029081, -0.115901}, {-0.207622, 0.168664, 0.136030}, + { 0.090541, 0.032754, -0.057330}, { 0.140219, -0.000735, -0.015633}, + { 0.136697, -0.017163, -0.100909}, { 0.029838, -0.089515, -0.147130}, + {-0.055367, -0.072683, -0.214015}, { 0.048680, -0.057633, -0.212429}, + {-0.013134, -0.113898, -0.196403}, {-0.071702, -0.159408, -0.254895} +}; + +static const float lsf_cb5_16k[128][4] = { + {-0.201277, -0.278679, -0.173262, -0.198580}, + {-0.214667, -0.151922, -0.117551, -0.192713}, + {-0.160962, -0.207728, -0.124750, -0.129749}, + {-0.131043, -0.137818, -0.155281, -0.166308}, + {-0.179134, -0.169602, -0.165223, -0.066293}, + {-0.136474, -0.177035, -0.250127, -0.134370}, + {-0.066970, -0.146274, -0.170638, -0.134436}, + {-0.083288, -0.165860, -0.103437, -0.140361}, + {-0.130474, -0.119317, -0.124393, -0.086408}, + {-0.127609, -0.134415, -0.073592, -0.116103}, + {-0.113027, -0.091756, -0.107786, -0.131935}, + {-0.125530, -0.182152, -0.093796, -0.045088}, + {-0.077122, -0.138052, -0.166271, -0.038886}, + {-0.073027, -0.106845, -0.067073, -0.113910}, + {-0.049146, -0.107019, -0.112531, -0.063388}, + {-0.101539, -0.119586, -0.050297, -0.040670}, + {-0.107784, -0.066913, -0.080993, -0.052352}, + {-0.152155, -0.103010, -0.090461, -0.015526}, + {-0.153087, -0.087656, -0.029889, -0.037367}, + {-0.215281, -0.138062, -0.089162, -0.050839}, + {-0.053350, -0.060169, -0.063459, -0.024499}, + {-0.051674, -0.076355, -0.033733, -0.077211}, + {-0.045047, -0.107006, -0.020880, -0.024525}, + {-0.083003, -0.063672, -0.013243, -0.028324}, + {-0.104104, -0.075450, -0.032746, 0.024480}, + {-0.085695, -0.019502, -0.045121, -0.025016}, + {-0.123120, -0.030844, -0.003533, -0.016224}, + {-0.025568, -0.049172, -0.003911, -0.027522}, + {-0.039029, -0.019857, -0.043211, -0.058087}, + {-0.040122, -0.023067, -0.001356, 0.008607}, + {-0.063351, -0.001776, 0.016015, -0.027088}, + {-0.068110, -0.038838, 0.042525, 0.001076}, + {-0.043623, -0.020736, -0.047862, 0.037710}, + {-0.041052, 0.021954, -0.025660, 0.000758}, + {-0.013035, 0.002583, -0.008233, -0.037300}, + {-0.005523, -0.014670, 0.019651, -0.012667}, + {-0.004409, -0.014437, -0.059412, -0.019701}, + { 0.024946, -0.011663, -0.014351, -0.028762}, + { 0.012660, 0.018489, -0.010205, 0.012695}, + {-0.004423, 0.017827, 0.040544, 0.003629}, + { 0.020684, 0.026743, 0.007752, -0.025595}, + { 0.032071, 0.000043, 0.026188, -0.006444}, + { 0.058793, 0.015820, -0.001119, -0.017415}, + { 0.020156, -0.047590, 0.004227, 0.008670}, + { 0.054770, 0.032135, 0.029770, -0.009767}, + { 0.030884, 0.047757, 0.033068, 0.006866}, + { 0.062039, 0.011646, 0.056037, 0.016859}, + { 0.013798, -0.028196, 0.060710, 0.014299}, + { 0.100043, 0.041445, 0.023379, -0.014889}, + { 0.062728, -0.042821, 0.002180, -0.055380}, + { 0.061663, 0.018767, -0.015571, -0.074095}, + { 0.062980, 0.080497, 0.011808, -0.031787}, + { 0.084964, 0.043100, -0.025877, 0.020309}, + { 0.014707, 0.035421, -0.041440, -0.053373}, + { 0.081268, 0.005791, -0.066290, -0.039825}, + { 0.017691, -0.020401, -0.040513, -0.083960}, + { 0.120874, 0.055753, -0.025988, -0.059552}, + { 0.079912, 0.007894, -0.085380, -0.114587}, + { 0.036856, -0.039331, -0.104237, -0.069116}, + { 0.008526, -0.064273, -0.048312, -0.038595}, + { 0.033461, -0.028956, -0.066505, 0.038722}, + {-0.042064, -0.043989, -0.100653, -0.071550}, + {-0.015342, -0.064850, -0.065675, -0.122769}, + {-0.006581, -0.004919, -0.113564, -0.145753}, + { 0.008273, -0.070702, -0.164998, -0.095541}, + {-0.001698, -0.063744, -0.129971, -0.011162}, + {-0.048471, -0.087500, -0.111006, -0.161823}, + {-0.032193, -0.091955, -0.080642, 0.012288}, + {-0.095873, -0.015986, -0.072722, -0.101745}, + {-0.079477, -0.082060, -0.203008, -0.100297}, + {-0.023883, -0.064022, -0.168341, -0.211739}, + {-0.070530, -0.103547, -0.123858, 0.055049}, + {-0.033503, -0.076812, -0.016287, 0.044159}, + {-0.088427, -0.161682, -0.058579, 0.013873}, + {-0.083068, -0.168222, -0.016773, -0.080209}, + {-0.080548, -0.139090, 0.030544, 0.007171}, + {-0.117482, -0.083718, 0.027074, -0.003674}, + {-0.163085, -0.156856, -0.012618, -0.022329}, + {-0.176540, -0.113042, -0.020148, 0.051770}, + {-0.153891, -0.199293, -0.043244, 0.028331}, + {-0.107822, -0.150615, 0.016430, 0.092919}, + {-0.137676, -0.183224, 0.066026, 0.029343}, + {-0.191106, -0.099250, 0.045370, 0.004084}, + {-0.237042, -0.130815, -0.022543, -0.029428}, + {-0.201014, -0.053591, -0.007305, -0.033547}, + {-0.249286, -0.228408, 0.005002, 0.007146}, + {-0.206509, -0.211998, -0.061352, -0.047233}, + {-0.255702, -0.135114, 0.076375, 0.036630}, + {-0.296271, -0.073946, -0.007273, -0.019601}, + {-0.302917, -0.175111, -0.070024, -0.043905}, + {-0.239275, -0.043962, -0.084982, -0.067446}, + {-0.254583, -0.294720, -0.088762, -0.070451}, + {-0.205583, -0.238996, -0.124753, 0.033076}, + {-0.205583, -0.215882, -0.028472, 0.118679}, + {-0.153640, -0.204464, -0.039654, -0.134441}, + {-0.145929, -0.191970, -0.175308, 0.021366}, + {-0.149348, -0.212569, -0.118324, 0.103812}, + {-0.166397, -0.220581, -0.265260, -0.029113}, + {-0.164171, -0.231262, -0.258828, 0.061427}, + {-0.200198, -0.263453, -0.212016, 0.115359}, + {-0.130088, -0.212168, -0.202368, 0.118563}, + {-0.206387, -0.078075, -0.227856, -0.111165}, + {-0.129605, -0.176848, -0.241584, -0.259900}, + {-0.176826, -0.045901, -0.141712, -0.209345}, + {-0.351173, -0.031097, -0.133935, -0.182412}, + {-0.164232, 0.027006, -0.014039, -0.053567}, + {-0.171037, -0.025924, 0.030972, 0.017329}, + {-0.080862, -0.021577, 0.007652, 0.063968}, + {-0.061788, 0.042024, -0.018783, -0.057979}, + {-0.110311, 0.054760, 0.031446, -0.006710}, + {-0.136637, 0.022171, 0.084991, 0.028039}, + {-0.254471, -0.004376, 0.078034, 0.033649}, + {-0.234464, 0.088157, 0.040999, 0.002639}, + {-0.037095, 0.059443, 0.072180, 0.015027}, + {-0.046841, -0.004813, 0.088266, 0.038786}, + {-0.086782, 0.120100, 0.082655, 0.020271}, + {-0.118361, -0.069242, 0.094867, 0.039200}, + {-0.023342, -0.084303, 0.052684, 0.017093}, + {-0.014194, 0.001012, 0.011946, 0.074125}, + {-0.015342, 0.076396, 0.022365, -0.028001}, + { 0.027706, 0.037047, 0.107573, 0.060815}, + { 0.030615, 0.040664, 0.010467, 0.074289}, + { 0.038646, 0.115584, 0.069627, 0.007642}, + { 0.096463, 0.069818, 0.062494, 0.015413}, + { 0.054834, 0.065232, 0.054286, 0.110088}, + { 0.152312, 0.092371, 0.026420, -0.013184}, + { 0.144264, 0.123438, 0.080131, 0.023233}, + { 0.124405, 0.009943, -0.148477, -0.205184} +}; + +static const float *lsf_codebooks_16k[] = { + lsf_cb1_16k[0], lsf_cb2_16k[0], lsf_cb3_16k[0], lsf_cb4_16k[0], + lsf_cb5_16k[0] +}; + +#endif /* AVCODEC_SIPR16KDATA_H */ diff --git a/ffmpeg/libavcodec/siprdata.h b/ffmpeg/libavcodec/siprdata.h new file mode 100644 index 0000000..ed804ee --- /dev/null +++ b/ffmpeg/libavcodec/siprdata.h @@ -0,0 +1,263 @@ +/* + * SIPR / ACELP.NET decoder + * + * Copyright (c) 2008 Vladimir Voroshilov + * Copyright (c) 2009 Vitor Sessak + * + * 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 + */ + +#ifndef AVCODEC_SIPRDATA_H +#define AVCODEC_SIPRDATA_H + +static const float mean_lsf[10] = { + 0.297151, 0.452308, 0.765443, 1.134803, 1.421125, + 1.773822, 2.049173, 2.375914, 2.585097, 0.075756 +}; + +static const float lsf_cb1[64][2] = { + { 0.007587, -0.005843}, { 0.042163, -0.028048}, {-0.017147, -0.060705}, + { 0.013773, -0.038108}, {-0.041563, -0.078571}, {-0.076928, -0.119343}, + { 0.012654, 0.176005}, { 0.059737, 0.156869}, { 0.171767, 0.231837}, + { 0.114030, 0.242047}, { 0.168977, 0.283101}, { 0.146210, 0.397961}, + { 0.249446, 0.268421}, { 0.137074, 0.186724}, {-0.057736, -0.135638}, + {-0.109664, -0.124611}, {-0.021234, -0.031174}, {-0.013990, -0.091819}, + {-0.040046, -0.111426}, {-0.016830, 0.055361}, { 0.057815, 0.071606}, + { 0.060670, 0.114436}, { 0.106695, 0.140838}, { 0.093601, 0.092793}, + { 0.039593, 0.006142}, {-0.066589, -0.092463}, {-0.102589, -0.171380}, + {-0.059621, -0.050671}, { 0.166131, 0.139773}, { 0.213069, 0.190761}, + { 0.061820, 0.037661}, { 0.136471, 0.090823}, {-0.019789, 0.013515}, + { 0.022280, 0.079473}, { 0.215281, 0.461959}, { 0.206497, 0.340077}, + { 0.012249, -0.065596}, { 0.091345, 0.190871}, { 0.019506, 0.037266}, + {-0.050702, -0.013223}, {-0.057334, 0.028943}, { 0.291512, 0.371415}, + {-0.053467, 0.084160}, { 0.025372, 0.375310}, { 0.269995, 0.566520}, + {-0.095259, -0.012353}, { 0.050479, 0.212893}, { 0.101219, 0.049320}, + { 0.072426, 0.283362}, {-0.084116, -0.150542}, {-0.031485, 0.144922}, + { 0.012714, 0.256910}, {-0.009528, 0.102768}, {-0.039572, 0.204967}, + {-0.098800, 0.055038}, { 0.020719, 0.128387}, {-0.045559, -0.178373}, + {-0.082338, 0.136933}, {-0.058270, 0.292806}, { 0.084242, 0.505112}, + { 0.121825, 0.326386}, {-0.102658, -0.069341}, { 0.071675, 0.004744}, + {-0.117763, -0.202608} +}; + +static const float lsf_cb2[128][2] = { + { 0.025412, 0.006095}, {-0.069803, 0.010650}, {-0.175957, -0.185800}, + {-0.139298, -0.048013}, {-0.156150, -0.129688}, {-0.160523, 0.068022}, + { 0.199683, 0.259982}, { 0.258038, 0.236147}, { 0.367089, 0.304716}, + { 0.251764, 0.305853}, { 0.394314, 0.382153}, { 0.448579, 0.337438}, + { 0.323286, 0.425563}, { 0.015369, 0.123820}, {-0.026770, 0.083881}, + {-0.112161, -0.097993}, {-0.221847, -0.161311}, {-0.050014, -0.092862}, + {-0.214960, -0.398498}, {-0.114062, -0.241381}, { 0.137950, 0.138852}, + { 0.031529, 0.065719}, { 0.208734, 0.084760}, { 0.157862, 0.057535}, + { 0.124750, 0.011922}, {-0.035227, -0.154397}, {-0.105523, -0.291427}, + {-0.073488, -0.201948}, {-0.224184, -0.273290}, {-0.168019, -0.240297}, + {-0.271591, -0.384682}, {-0.124784, 0.014253}, { 0.004210, -0.110418}, + { 0.074270, -0.014272}, { 0.053058, -0.068672}, {-0.090098, -0.145019}, + { 0.303214, 0.210323}, { 0.413443, 0.272002}, { 0.356904, 0.230646}, + {-0.035186, -0.028579}, {-0.117558, 0.115105}, {-0.159225, 0.218385}, + {-0.230178, 0.172901}, {-0.216148, -0.110195}, { 0.309444, 0.101508}, + { 0.250489, 0.118338}, { 0.293324, 0.151205}, {-0.023634, 0.033084}, + { 0.076708, 0.114024}, { 0.123119, 0.087704}, {-0.060265, 0.126543}, + {-0.223766, -0.021903}, {-0.241987, -0.328089}, { 0.205598, 0.147925}, + {-0.087010, 0.064601}, {-0.287892, -0.286099}, {-0.179451, -0.350781}, + {-0.219572, 0.043816}, {-0.217263, 0.245550}, {-0.286743, -0.180981}, + { 0.172659, 0.112620}, {-0.105422, 0.176856}, { 0.006176, -0.051491}, + { 0.099802, 0.176322}, {-0.186620, -0.068980}, { 0.164689, 0.185018}, + { 0.519877, 0.376111}, { 0.521941, 0.533731}, { 0.473375, 0.439534}, + { 0.214235, 0.202476}, { 0.579215, 0.466969}, { 0.310414, 0.271057}, + { 0.257450, 0.058939}, { 0.023936, -0.169464}, {-0.268817, -0.064531}, + {-0.174182, -0.000198}, {-0.268405, -0.234529}, {-0.296522, 0.247140}, + { 0.115950, -0.072194}, {-0.303666, 0.149084}, {-0.347762, -0.011002}, + {-0.223829, -0.214137}, {-0.278958, -0.457975}, { 0.135500, 0.238466}, + { 0.312730, 0.342760}, { 0.071754, -0.125912}, { 0.485938, 0.260429}, + { 0.037536, 0.179771}, { 0.391493, 0.156938}, { 0.397320, 0.484446}, + {-0.308630, -0.342418}, {-0.269599, -0.128453}, {-0.086683, -0.043863}, + { 0.421115, 0.213521}, { 0.082417, 0.049006}, {-0.087873, 0.238126}, + { 0.338899, 0.166131}, {-0.166988, 0.147105}, {-0.167214, -0.294075}, + { 0.588706, 0.328303}, { 0.207270, 0.017671}, {-0.141658, 0.291147}, + {-0.140850, 0.374321}, { 0.028180, 0.322510}, {-0.229858, 0.328036}, + {-0.060743, -0.260916}, {-0.011131, 0.246442}, {-0.058151, 0.310760}, + {-0.127536, -0.186432}, {-0.128523, -0.334884}, {-0.283899, 0.077729}, + {-0.031595, 0.181015}, {-0.329330, -0.108630}, {-0.215739, 0.107458}, + { 0.175734, 0.327134}, { 0.255801, 0.176077}, { 0.228265, 0.396859}, + {-0.370909, -0.185081}, {-0.355138, -0.300405}, { 0.061669, 0.242616}, + { 0.104489, 0.307995}, {-0.320021, -0.234002}, { 0.077349, 0.416286}, + {-0.339471, -0.407609}, {-0.019384, -0.215111}, { 0.168229, -0.032453}, + {-0.040140, 0.399658}, {-0.275141, 0.008218} +}; + +static const float lsf_cb3[128][2] = { + { 0.024608, 0.006198}, {-0.216616, -0.398169}, {-0.089601, -0.201370}, + {-0.121878, -0.305281}, { 0.037913, 0.059320}, { 0.245126, 0.244089}, + { 0.266853, 0.182476}, { 0.319362, 0.203481}, { 0.349945, 0.252644}, + { 0.393849, 0.279272}, { 0.445707, 0.258063}, { 0.387321, 0.200855}, + {-0.038818, 0.129603}, {-0.009510, 0.076441}, {-0.023892, -0.028199}, + {-0.117134, -0.145990}, {-0.186585, -0.052886}, {-0.034250, -0.084547}, + {-0.087443, -0.095426}, {-0.453322, -0.174493}, {-0.363975, -0.148186}, + {-0.334413, -0.202479}, {-0.221313, -0.181320}, {-0.131146, -0.050611}, + {-0.104706, 0.115139}, { 0.192765, 0.275417}, { 0.014184, 0.194251}, + { 0.154215, 0.226949}, { 0.084031, 0.221759}, { 0.189438, 0.164566}, + { 0.130737, 0.170962}, {-0.066815, 0.062954}, {-0.177176, -0.145167}, + {-0.247608, -0.129767}, {-0.187886, -0.293720}, {-0.244036, -0.344655}, + {-0.203063, -0.234947}, {-0.292715, -0.158421}, { 0.064990, -0.028164}, + { 0.147664, 0.085995}, { 0.107977, 0.002253}, { 0.071286, 0.027533}, + { 0.021017, -0.049807}, {-0.272056, -0.217857}, {-0.065596, 0.008375}, + {-0.150818, -0.195514}, {-0.012767, -0.150787}, { 0.238541, 0.136606}, + { 0.291741, 0.114024}, { 0.202677, 0.103701}, { 0.140985, 0.037759}, + {-0.257347, -0.442383}, {-0.320666, -0.319742}, {-0.488725, -0.603660}, + {-0.319170, -0.469806}, { 0.014970, -0.101074}, { 0.102209, 0.066790}, + {-0.076202, -0.044884}, { 0.073868, 0.152565}, { 0.070755, -0.091358}, + {-0.016751, 0.027216}, { 0.071201, 0.096981}, {-0.060975, -0.145638}, + { 0.114156, 0.117587}, {-0.284757, -0.029101}, {-0.253005, -0.073645}, + {-0.204028, -0.098492}, {-0.114508, 0.001219}, {-0.225284, -0.011998}, + {-0.235670, 0.084330}, { 0.161921, 0.128334}, { 0.025717, 0.119456}, + {-0.255292, -0.281471}, {-0.392803, -0.095809}, { 0.039229, -0.152110}, + {-0.310905, -0.099233}, {-0.268773, 0.032308}, {-0.340150, 0.013129}, + {-0.344890, -0.045157}, {-0.188423, 0.265603}, {-0.168235, -0.000936}, + { 0.000462, 0.297000}, { 0.263674, 0.371214}, {-0.146797, -0.098225}, + {-0.386557, -0.282426}, {-0.070940, -0.255550}, { 0.293258, 0.252785}, + { 0.408332, 0.387751}, {-0.381914, -0.358918}, {-0.463621, -0.315560}, + {-0.323681, -0.258465}, { 0.250055, 0.071195}, {-0.405256, -0.429754}, + {-0.135748, -0.251274}, { 0.186827, 0.060177}, { 0.116742, -0.053526}, + {-0.403321, -0.220339}, {-0.414144, -0.021108}, {-0.416877, 0.050184}, + {-0.470083, -0.079564}, {-0.315554, 0.219217}, {-0.273183, 0.138437}, + { 0.253231, 0.306374}, { 0.177802, 0.346298}, { 0.210358, 0.207697}, + {-0.323480, 0.077519}, {-0.193136, 0.048170}, { 0.114492, 0.292778}, + {-0.130766, 0.056677}, {-0.171572, -0.349267}, {-0.370076, -0.536392}, + {-0.311109, -0.389953}, { 0.334928, 0.367664}, { 0.351246, 0.438664}, + { 0.518803, 0.331253}, { 0.437061, 0.327257}, { 0.318906, 0.307389}, + {-0.025972, -0.206758}, { 0.373278, 0.325438}, { 0.473488, 0.389441}, + { 0.478553, 0.477990}, { 0.332783, 0.153825}, { 0.212098, 0.452336}, + { 0.161522, -0.011212}, { 0.209368, 0.020687}, {-0.086262, 0.204493}, + {-0.388643, 0.133640}, {-0.177016, 0.134404} +}; + +static const float lsf_cb4[128][2] = { + {-0.003594, -0.022447}, { 0.070651, 0.028334}, {-0.290374, -0.018347}, + {-0.224495, -0.370312}, {-0.269555, -0.131227}, {-0.122714, -0.267733}, + { 0.173325, 0.138698}, { 0.161946, 0.020687}, { 0.111706, 0.022510}, + { 0.097638, 0.056049}, { 0.139754, 0.059920}, { 0.056549, -0.050586}, + { 0.036301, 0.021501}, {-0.066347, 0.012324}, {-0.066972, 0.096136}, + {-0.120062, -0.084201}, { 0.011225, 0.047425}, {-0.012846, -0.067390}, + {-0.116201, 0.122874}, {-0.027819, 0.035453}, {-0.024743, 0.072835}, + {-0.034061, -0.001310}, { 0.077469, 0.081609}, { 0.128347, 0.139584}, + { 0.183416, 0.086563}, {-0.155839, -0.053775}, {-0.190403, -0.018639}, + {-0.202548, -0.062841}, {-0.373733, -0.275094}, {-0.394260, -0.186513}, + {-0.465700, -0.220031}, { 0.064400, -0.095825}, {-0.262053, -0.199837}, + {-0.167233, -0.094402}, { 0.048600, 0.057567}, {-0.007122, 0.168506}, + { 0.050938, 0.156451}, {-0.060828, 0.147083}, {-0.171889, 0.195822}, + {-0.218934, 0.138431}, {-0.270532, 0.195775}, {-0.405818, 0.075643}, + {-0.440187, 0.193387}, {-0.484968, 0.157607}, {-0.480560, 0.067230}, + {-0.436757, -0.111847}, {-0.040731, -0.040363}, {-0.202319, -0.170457}, + {-0.158515, -0.134551}, {-0.356709, -0.378549}, {-0.268820, -0.289831}, + {-0.188486, -0.289306}, {-0.148139, -0.177616}, {-0.071591, -0.191128}, + {-0.052270, -0.150589}, {-0.020543, -0.116220}, { 0.039584, -0.012592}, + {-0.268226, 0.042704}, {-0.209755, 0.069423}, {-0.168964, 0.124504}, + {-0.363240, 0.188266}, {-0.524935, -0.025010}, {-0.105894, -0.002699}, + {-0.251830, -0.062018}, {-0.310480, -0.082325}, { 0.014652, 0.083127}, + {-0.136512, 0.033116}, {-0.073755, -0.025236}, { 0.110766, 0.095954}, + { 0.002878, 0.011838}, {-0.074977, -0.244586}, {-0.047023, -0.081339}, + {-0.183249, 0.029525}, { 0.263435, 0.206934}, {-0.156721, -0.229993}, + {-0.112224, -0.208941}, {-0.116534, -0.123191}, {-0.073988, -0.111668}, + { 0.029484, -0.137573}, {-0.009802, -0.161685}, {-0.023273, 0.114043}, + {-0.332651, 0.049072}, {-0.394009, 0.018608}, {-0.433543, -0.035318}, + {-0.368459, -0.108024}, {-0.350215, -0.037617}, {-0.321140, -0.178537}, + { 0.020307, -0.048487}, {-0.210512, -0.232274}, {-0.082140, -0.065443}, + { 0.081961, -0.009340}, { 0.146794, 0.101973}, { 0.213999, 0.124687}, + { 0.100217, -0.054095}, {-0.114411, -0.041403}, {-0.097631, 0.037061}, + {-0.099651, -0.157978}, {-0.215790, -0.116550}, {-0.107100, 0.076300}, + { 0.084653, 0.126088}, { 0.246439, 0.091442}, { 0.160077, 0.188536}, + { 0.273900, 0.279190}, { 0.320417, 0.232550}, { 0.132710, -0.018988}, + { 0.018950, -0.091681}, {-0.032073, -0.202906}, { 0.212789, 0.178188}, + { 0.208580, 0.239726}, { 0.049420, 0.099840}, {-0.145695, -0.010619}, + {-0.132525, -0.322660}, { 0.019666, 0.126603}, { 0.260809, 0.147727}, + {-0.232795, -0.001090}, {-0.049826, 0.225987}, {-0.154774, 0.076614}, + { 0.045032, 0.221397}, { 0.321014, 0.161632}, {-0.062379, 0.053586}, + { 0.132252, 0.246675}, { 0.392627, 0.271905}, {-0.264585, 0.102344}, + {-0.327200, 0.121624}, {-0.399642, 0.124445}, {-0.108335, 0.179171}, + { 0.100374, 0.182731}, { 0.203852, 0.049505} +}; + +static const float lsf_cb5[32][2] = { + {-0.047705, 0.008002}, { 0.011332, 0.065028}, {-0.021796, -0.034777}, + {-0.147394, -0.001241}, {-0.001577, 0.020599}, {-0.083827, -0.028975}, + {-0.177707, 0.066046}, {-0.043241, -0.165144}, { 0.053322, 0.096519}, + {-0.097688, 0.106484}, {-0.023392, 0.111234}, {-0.146747, -0.159360}, + { 0.027241, -0.011806}, {-0.043156, 0.057667}, { 0.019516, -0.062116}, + { 0.025990, 0.162533}, { 0.091888, 0.009720}, {-0.098511, 0.036414}, + { 0.013722, -0.116512}, { 0.054833, -0.180975}, { 0.119497, 0.128774}, + { 0.118378, -0.125997}, { 0.065882, -0.030932}, { 0.120581, -0.039964}, + {-0.050561, -0.088577}, { 0.050134, 0.033194}, {-0.129654, -0.075112}, + {-0.225334, -0.040234}, { 0.070629, -0.084455}, { 0.095508, 0.063548}, + { 0.150514, 0.034366}, { 0.186092, -0.069272} +}; + +static const float *lsf_codebooks[] = { + lsf_cb1[0], lsf_cb2[0], lsf_cb3[0], lsf_cb4[0], lsf_cb5[0] +}; + +static const float gain_cb[128][2] = { + {0.035230, 0.161540}, {0.049223, 0.448359}, {0.057443, 0.809043}, + {0.072434, 1.760306}, {0.111491, 0.566418}, {0.112820, 1.098524}, + {0.143493, 0.726856}, {0.144840, 0.347800}, {0.180341, 1.050010}, + {0.188171, 2.197256}, {0.189771, 0.256947}, {0.198260, 0.484678}, + {0.210622, 0.755825}, {0.220694, 0.590788}, {0.237062, 1.322214}, + {0.255175, 0.338710}, {0.298980, 0.919051}, {0.314627, 0.520961}, + {0.337106, 1.469863}, {0.341422, 2.804546}, {0.363257, 0.736222}, + {0.363881, 0.367640}, {0.369850, 1.937934}, {0.370136, 1.075201}, + {0.397152, 0.549410}, {0.426557, 0.876015}, {0.450686, 0.215588}, + {0.468116, 0.671848}, {0.470495, 1.242034}, {0.474180, 1.739845}, + {0.484875, 0.490564}, {0.498917, 0.971238}, {0.530996, 0.785765}, + {0.539768, 2.130689}, {0.546021, 0.589544}, {0.546632, 3.050846}, + {0.552336, 0.389775}, {0.556302, 1.400103}, {0.559688, 1.105421}, + {0.574140, 0.667513}, {0.595547, 0.828943}, {0.597771, 0.496929}, + {0.617079, 1.863075}, {0.619657, 1.221713}, {0.621172, 0.950275}, + {0.628426, 0.630766}, {0.628689, 4.242164}, {0.640899, 1.529846}, + {0.645813, 0.331127}, {0.653056, 0.748168}, {0.662909, 1.077438}, + {0.669505, 2.631114}, {0.681570, 1.839298}, {0.687844, 0.903400}, + {0.688660, 1.270830}, {0.695070, 0.578227}, {0.697926, 0.428440}, + {0.715454, 0.812355}, {0.729981, 1.539357}, {0.737434, 1.106765}, + {0.740241, 2.033374}, {0.740871, 0.568460}, {0.752689, 0.698461}, + {0.756587, 0.893078}, {0.767797, 0.499246}, {0.768516, 3.712434}, + {0.773153, 1.332360}, {0.786125, 1.042996}, {0.788792, 0.238388}, + {0.790861, 2.273229}, {0.795338, 1.582767}, {0.809621, 0.595501}, + {0.821032, 0.756460}, {0.824590, 0.922925}, {0.826019, 1.186793}, + {0.827426, 1.885076}, {0.830080, 6.088666}, {0.837028, 2.819993}, + {0.845561, 1.490623}, {0.848323, 0.410436}, {0.856522, 0.729725}, + {0.862636, 0.966880}, {0.874561, 1.681660}, {0.874751, 1.177630}, + {0.879289, 2.301300}, {0.886671, 0.613068}, {0.896729, 0.781097}, + {0.904777, 3.484111}, {0.906098, 1.330892}, {0.919182, 1.877203}, + {0.919901, 0.569511}, {0.921772, 1.034126}, {0.922439, 0.376000}, + {0.934221, 1.485214}, {0.938842, 0.869135}, {0.939166, 2.378294}, + {0.958933, 1.122722}, {0.959042, 0.694098}, {0.960995, 1.743430}, + {0.970763, 2.884897}, {0.982881, 0.814506}, {0.990141, 1.330022}, + {0.996447, 1.823381}, {1.000013, 0.967498}, {1.000743, 0.480597}, + {1.008020, 5.095226}, {1.013883, 2.105435}, {1.026438, 0.691312}, + {1.027361, 1.558169}, {1.030123, 3.586526}, {1.033916, 1.118036}, + {1.039315, 2.543360}, {1.068596, 0.836380}, {1.081023, 1.318768}, + {1.093150, 2.267843}, {1.095607, 1.712383}, {1.102816, 1.037334}, + {1.103231, 3.536292}, {1.107320, 0.508615}, {1.150000, 7.999000}, + {1.156731, 1.236772}, {1.168428, 2.268084}, {1.184130, 0.775839}, + {1.210609, 1.511840}, {1.220663, 4.365683}, {1.224016, 0.983179}, + {1.252236, 2.778535}, {1.301176, 1.923126} +}; + +static const float pred[4] = { + 0.200, 0.334, 0.504, 0.691 +}; + +#endif /* AVCODEC_SIPRDATA_H */ diff --git a/ffmpeg/libavcodec/smacker.c b/ffmpeg/libavcodec/smacker.c new file mode 100644 index 0000000..c070150 --- /dev/null +++ b/ffmpeg/libavcodec/smacker.c @@ -0,0 +1,782 @@ +/* + * Smacker decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Smacker decoder + */ + +/* + * Based on http://wiki.multimedia.cx/index.php?title=Smacker + */ + +#include +#include + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "internal.h" +#include "mathops.h" + +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "bytestream.h" + +#define SMKTREE_BITS 9 +#define SMK_NODE 0x80000000 + +/* + * Decoder context + */ +typedef struct SmackVContext { + AVCodecContext *avctx; + AVFrame pic; + + int *mmap_tbl, *mclr_tbl, *full_tbl, *type_tbl; + int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; +} SmackVContext; + +/** + * Context used for code reconstructing + */ +typedef struct HuffContext { + int length; + int maxlength; + int current; + uint32_t *bits; + int *lengths; + int *values; +} HuffContext; + +/* common parameters used for decode_bigtree */ +typedef struct DBCtx { + VLC *v1, *v2; + int *recode1, *recode2; + int escapes[3]; + int *last; + int lcur; +} DBCtx; + +/* possible runs of blocks */ +static const int block_runs[64] = { + 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, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 128, 256, 512, 1024, 2048 }; + +enum SmkBlockTypes { + SMK_BLK_MONO = 0, + SMK_BLK_FULL = 1, + SMK_BLK_SKIP = 2, + SMK_BLK_FILL = 3 }; + +/** + * Decode local frame tree + */ +static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) +{ + if(length > 32 || length > 3*SMKTREE_BITS) { + av_log(NULL, AV_LOG_ERROR, "length too long\n"); + return AVERROR_INVALIDDATA; + } + if(!get_bits1(gb)){ //Leaf + if(hc->current >= 256){ + av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); + return AVERROR_INVALIDDATA; + } + if(length){ + hc->bits[hc->current] = prefix; + hc->lengths[hc->current] = length; + } else { + hc->bits[hc->current] = 0; + hc->lengths[hc->current] = 0; + } + hc->values[hc->current] = get_bits(gb, 8); + hc->current++; + if(hc->maxlength < length) + hc->maxlength = length; + return 0; + } else { //Node + int r; + length++; + r = smacker_decode_tree(gb, hc, prefix, length); + if(r) + return r; + return smacker_decode_tree(gb, hc, prefix | (1 << (length - 1)), length); + } +} + +/** + * Decode header tree + */ +static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, DBCtx *ctx) +{ + if (hc->current + 1 >= hc->length) { + av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); + return AVERROR_INVALIDDATA; + } + if(!get_bits1(gb)){ //Leaf + int val, i1, i2; + i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) : 0; + i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) : 0; + if (i1 < 0 || i2 < 0) + return AVERROR_INVALIDDATA; + val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); + if(val == ctx->escapes[0]) { + ctx->last[0] = hc->current; + val = 0; + } else if(val == ctx->escapes[1]) { + ctx->last[1] = hc->current; + val = 0; + } else if(val == ctx->escapes[2]) { + ctx->last[2] = hc->current; + val = 0; + } + + hc->values[hc->current++] = val; + return 1; + } else { //Node + int r = 0, r_new, t; + + t = hc->current++; + r = smacker_decode_bigtree(gb, hc, ctx); + if(r < 0) + return r; + hc->values[t] = SMK_NODE | r; + r++; + r_new = smacker_decode_bigtree(gb, hc, ctx); + if (r_new < 0) + return r_new; + return r + r_new; + } +} + +/** + * Store large tree as FFmpeg's vlc codes + */ +static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) +{ + int res; + HuffContext huff; + HuffContext tmp1, tmp2; + VLC vlc[2] = { { 0 } }; + int escapes[3]; + DBCtx ctx; + int err = 0; + + if(size >= UINT_MAX>>4){ // (((size + 3) >> 2) + 3) << 2 must not overflow + av_log(smk->avctx, AV_LOG_ERROR, "size too large\n"); + return AVERROR_INVALIDDATA; + } + + tmp1.length = 256; + tmp1.maxlength = 0; + tmp1.current = 0; + tmp1.bits = av_mallocz(256 * 4); + tmp1.lengths = av_mallocz(256 * sizeof(int)); + tmp1.values = av_mallocz(256 * sizeof(int)); + + tmp2.length = 256; + tmp2.maxlength = 0; + tmp2.current = 0; + tmp2.bits = av_mallocz(256 * 4); + tmp2.lengths = av_mallocz(256 * sizeof(int)); + tmp2.values = av_mallocz(256 * sizeof(int)); + + if(get_bits1(gb)) { + res = smacker_decode_tree(gb, &tmp1, 0, 0); + if (res < 0) + return res; + skip_bits1(gb); + if(tmp1.current > 1) { + res = init_vlc(&vlc[0], SMKTREE_BITS, tmp1.length, + tmp1.lengths, sizeof(int), sizeof(int), + tmp1.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); + if(res < 0) { + av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); + return AVERROR_INVALIDDATA; + } + } + } + if (!vlc[0].table) { + av_log(smk->avctx, AV_LOG_ERROR, "Skipping low bytes tree\n"); + } + if(get_bits1(gb)){ + res = smacker_decode_tree(gb, &tmp2, 0, 0); + if (res < 0) + return res; + skip_bits1(gb); + if(tmp2.current > 1) { + res = init_vlc(&vlc[1], SMKTREE_BITS, tmp2.length, + tmp2.lengths, sizeof(int), sizeof(int), + tmp2.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); + if(res < 0) { + av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); + return AVERROR_INVALIDDATA; + } + } + } + if (!vlc[1].table) { + av_log(smk->avctx, AV_LOG_ERROR, "Skipping high bytes tree\n"); + } + + escapes[0] = get_bits(gb, 16); + escapes[1] = get_bits(gb, 16); + escapes[2] = get_bits(gb, 16); + + last[0] = last[1] = last[2] = -1; + + ctx.escapes[0] = escapes[0]; + ctx.escapes[1] = escapes[1]; + ctx.escapes[2] = escapes[2]; + ctx.v1 = &vlc[0]; + ctx.v2 = &vlc[1]; + ctx.recode1 = tmp1.values; + ctx.recode2 = tmp2.values; + ctx.last = last; + + huff.length = ((size + 3) >> 2) + 3; + huff.maxlength = 0; + huff.current = 0; + huff.values = av_mallocz(huff.length * sizeof(int)); + + if (smacker_decode_bigtree(gb, &huff, &ctx) < 0) + err = -1; + skip_bits1(gb); + if(ctx.last[0] == -1) ctx.last[0] = huff.current++; + if(ctx.last[1] == -1) ctx.last[1] = huff.current++; + if(ctx.last[2] == -1) ctx.last[2] = huff.current++; + if(huff.current > huff.length){ + ctx.last[0] = ctx.last[1] = ctx.last[2] = 1; + av_log(smk->avctx, AV_LOG_ERROR, "bigtree damaged\n"); + return AVERROR_INVALIDDATA; + } + + *recodes = huff.values; + + if(vlc[0].table) + ff_free_vlc(&vlc[0]); + if(vlc[1].table) + ff_free_vlc(&vlc[1]); + av_free(tmp1.bits); + av_free(tmp1.lengths); + av_free(tmp1.values); + av_free(tmp2.bits); + av_free(tmp2.lengths); + av_free(tmp2.values); + + return err; +} + +static int decode_header_trees(SmackVContext *smk) { + GetBitContext gb; + int mmap_size, mclr_size, full_size, type_size; + + mmap_size = AV_RL32(smk->avctx->extradata); + mclr_size = AV_RL32(smk->avctx->extradata + 4); + full_size = AV_RL32(smk->avctx->extradata + 8); + type_size = AV_RL32(smk->avctx->extradata + 12); + + init_get_bits(&gb, smk->avctx->extradata + 16, (smk->avctx->extradata_size - 16) * 8); + + if(!get_bits1(&gb)) { + av_log(smk->avctx, AV_LOG_INFO, "Skipping MMAP tree\n"); + smk->mmap_tbl = av_malloc(sizeof(int) * 2); + smk->mmap_tbl[0] = 0; + smk->mmap_last[0] = smk->mmap_last[1] = smk->mmap_last[2] = 1; + } else { + if (smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size)) + return AVERROR_INVALIDDATA; + } + if(!get_bits1(&gb)) { + av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n"); + smk->mclr_tbl = av_malloc(sizeof(int) * 2); + smk->mclr_tbl[0] = 0; + smk->mclr_last[0] = smk->mclr_last[1] = smk->mclr_last[2] = 1; + } else { + if (smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size)) + return AVERROR_INVALIDDATA; + } + if(!get_bits1(&gb)) { + av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n"); + smk->full_tbl = av_malloc(sizeof(int) * 2); + smk->full_tbl[0] = 0; + smk->full_last[0] = smk->full_last[1] = smk->full_last[2] = 1; + } else { + if (smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size)) + return AVERROR_INVALIDDATA; + } + if(!get_bits1(&gb)) { + av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n"); + smk->type_tbl = av_malloc(sizeof(int) * 2); + smk->type_tbl[0] = 0; + smk->type_last[0] = smk->type_last[1] = smk->type_last[2] = 1; + } else { + if (smacker_decode_header_tree(smk, &gb, &smk->type_tbl, smk->type_last, type_size)) + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static av_always_inline void last_reset(int *recode, int *last) { + recode[last[0]] = recode[last[1]] = recode[last[2]] = 0; +} + +/* get code and update history */ +static av_always_inline int smk_get_code(GetBitContext *gb, int *recode, int *last) { + register int *table = recode; + int v; + + while(*table & SMK_NODE) { + if(get_bits1(gb)) + table += (*table) & (~SMK_NODE); + table++; + } + v = *table; + + if(v != recode[last[0]]) { + recode[last[2]] = recode[last[1]]; + recode[last[1]] = recode[last[0]]; + recode[last[0]] = v; + } + return v; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + SmackVContext * const smk = avctx->priv_data; + uint8_t *out; + uint32_t *pal; + GetByteContext gb2; + GetBitContext gb; + int blocks, blk, bw, bh; + int i, ret; + int stride; + int flags; + + if (avpkt->size <= 769) + return AVERROR_INVALIDDATA; + + if ((ret = ff_reget_buffer(avctx, &smk->pic)) < 0) + return ret; + + /* make the palette available on the way out */ + pal = (uint32_t*)smk->pic.data[1]; + bytestream2_init(&gb2, avpkt->data, avpkt->size); + flags = bytestream2_get_byteu(&gb2); + smk->pic.palette_has_changed = flags & 1; + smk->pic.key_frame = !!(flags & 2); + if(smk->pic.key_frame) + smk->pic.pict_type = AV_PICTURE_TYPE_I; + else + smk->pic.pict_type = AV_PICTURE_TYPE_P; + + for(i = 0; i < 256; i++) + *pal++ = 0xFFU << 24 | bytestream2_get_be24u(&gb2); + + last_reset(smk->mmap_tbl, smk->mmap_last); + last_reset(smk->mclr_tbl, smk->mclr_last); + last_reset(smk->full_tbl, smk->full_last); + last_reset(smk->type_tbl, smk->type_last); + init_get_bits(&gb, avpkt->data + 769, (avpkt->size - 769) * 8); + + blk = 0; + bw = avctx->width >> 2; + bh = avctx->height >> 2; + blocks = bw * bh; + out = smk->pic.data[0]; + stride = smk->pic.linesize[0]; + while(blk < blocks) { + int type, run, mode; + uint16_t pix; + + type = smk_get_code(&gb, smk->type_tbl, smk->type_last); + run = block_runs[(type >> 2) & 0x3F]; + switch(type & 3){ + case SMK_BLK_MONO: + while(run-- && blk < blocks){ + int clr, map; + int hi, lo; + clr = smk_get_code(&gb, smk->mclr_tbl, smk->mclr_last); + map = smk_get_code(&gb, smk->mmap_tbl, smk->mmap_last); + out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4; + hi = clr >> 8; + lo = clr & 0xFF; + for(i = 0; i < 4; i++) { + if(map & 1) out[0] = hi; else out[0] = lo; + if(map & 2) out[1] = hi; else out[1] = lo; + if(map & 4) out[2] = hi; else out[2] = lo; + if(map & 8) out[3] = hi; else out[3] = lo; + map >>= 4; + out += stride; + } + blk++; + } + break; + case SMK_BLK_FULL: + mode = 0; + if(avctx->codec_tag == MKTAG('S', 'M', 'K', '4')) { // In case of Smacker v4 we have three modes + if(get_bits1(&gb)) mode = 1; + else if(get_bits1(&gb)) mode = 2; + } + while(run-- && blk < blocks){ + out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4; + switch(mode){ + case 0: + for(i = 0; i < 4; i++) { + pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); + AV_WL16(out+2,pix); + pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); + AV_WL16(out,pix); + out += stride; + } + break; + case 1: + pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + out[0] = out[1] = pix & 0xFF; + out[2] = out[3] = pix >> 8; + out += stride; + break; + case 2: + for(i = 0; i < 2; i++) { + uint16_t pix1, pix2; + pix2 = smk_get_code(&gb, smk->full_tbl, smk->full_last); + pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last); + AV_WL16(out,pix1); + AV_WL16(out+2,pix2); + out += stride; + AV_WL16(out,pix1); + AV_WL16(out+2,pix2); + out += stride; + } + break; + } + blk++; + } + break; + case SMK_BLK_SKIP: + while(run-- && blk < blocks) + blk++; + break; + case SMK_BLK_FILL: + mode = type >> 8; + while(run-- && blk < blocks){ + uint32_t col; + out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4; + col = mode * 0x01010101; + for(i = 0; i < 4; i++) { + *((uint32_t*)out) = col; + out += stride; + } + blk++; + } + break; + } + + } + + if ((ret = av_frame_ref(data, &smk->pic)) < 0) + return ret; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return avpkt->size; +} + + + +/* + * + * Init smacker decoder + * + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + SmackVContext * const c = avctx->priv_data; + + c->avctx = avctx; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + avcodec_get_frame_defaults(&c->pic); + + /* decode huffman trees from extradata */ + if(avctx->extradata_size < 16){ + av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n"); + return AVERROR(EINVAL); + } + + if (decode_header_trees(c)) + return AVERROR_INVALIDDATA; + + return 0; +} + + + +/* + * + * Uninit smacker decoder + * + */ +static av_cold int decode_end(AVCodecContext *avctx) +{ + SmackVContext * const smk = avctx->priv_data; + + av_freep(&smk->mmap_tbl); + av_freep(&smk->mclr_tbl); + av_freep(&smk->full_tbl); + av_freep(&smk->type_tbl); + + av_frame_unref(&smk->pic); + + return 0; +} + + +static av_cold int smka_decode_init(AVCodecContext *avctx) +{ + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + avctx->sample_fmt = avctx->bits_per_coded_sample == 8 ? AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16; + + return 0; +} + +/** + * Decode Smacker audio data + */ +static int smka_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + GetBitContext gb; + HuffContext h[4] = { { 0 } }; + VLC vlc[4] = { { 0 } }; + int16_t *samples; + uint8_t *samples8; + int val; + int i, res, ret; + int unp_size; + int bits, stereo; + int pred[2] = {0, 0}; + + if (buf_size <= 4) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + + unp_size = AV_RL32(buf); + + if (unp_size > (1U<<24)) { + av_log(avctx, AV_LOG_ERROR, "packet is too big\n"); + return AVERROR_INVALIDDATA; + } + + init_get_bits(&gb, buf + 4, (buf_size - 4) * 8); + + if(!get_bits1(&gb)){ + av_log(avctx, AV_LOG_INFO, "Sound: no data\n"); + *got_frame_ptr = 0; + return 1; + } + stereo = get_bits1(&gb); + bits = get_bits1(&gb); + if (stereo ^ (avctx->channels != 1)) { + av_log(avctx, AV_LOG_ERROR, "channels mismatch\n"); + return AVERROR(EINVAL); + } + if (bits && avctx->sample_fmt == AV_SAMPLE_FMT_U8) { + av_log(avctx, AV_LOG_ERROR, "sample format mismatch\n"); + return AVERROR(EINVAL); + } + + /* get output buffer */ + frame->nb_samples = unp_size / (avctx->channels * (bits + 1)); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + samples8 = frame->data[0]; + + // Initialize + for(i = 0; i < (1 << (bits + stereo)); i++) { + h[i].length = 256; + h[i].maxlength = 0; + h[i].current = 0; + h[i].bits = av_mallocz(256 * 4); + h[i].lengths = av_mallocz(256 * sizeof(int)); + h[i].values = av_mallocz(256 * sizeof(int)); + skip_bits1(&gb); + res = smacker_decode_tree(&gb, &h[i], 0, 0); + if (res < 0) + return res; + skip_bits1(&gb); + if(h[i].current > 1) { + res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length, + h[i].lengths, sizeof(int), sizeof(int), + h[i].bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); + if(res < 0) { + av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); + return AVERROR_INVALIDDATA; + } + } + } + if(bits) { //decode 16-bit data + for(i = stereo; i >= 0; i--) + pred[i] = sign_extend(av_bswap16(get_bits(&gb, 16)), 16); + for(i = 0; i <= stereo; i++) + *samples++ = pred[i]; + for(; i < unp_size / 2; i++) { + if(get_bits_left(&gb)<0) + return AVERROR_INVALIDDATA; + if(i & stereo) { + if(vlc[2].table) + res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3); + else + res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } + val = h[2].values[res]; + if(vlc[3].table) + res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3); + else + res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } + val |= h[3].values[res] << 8; + pred[1] += sign_extend(val, 16); + *samples++ = av_clip_int16(pred[1]); + } else { + if(vlc[0].table) + res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); + else + res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } + val = h[0].values[res]; + if(vlc[1].table) + res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); + else + res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } + val |= h[1].values[res] << 8; + pred[0] += sign_extend(val, 16); + *samples++ = av_clip_int16(pred[0]); + } + } + } else { //8-bit data + for(i = stereo; i >= 0; i--) + pred[i] = get_bits(&gb, 8); + for(i = 0; i <= stereo; i++) + *samples8++ = pred[i]; + for(; i < unp_size; i++) { + if(get_bits_left(&gb)<0) + return AVERROR_INVALIDDATA; + if(i & stereo){ + if(vlc[1].table) + res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); + else + res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } + pred[1] += sign_extend(h[1].values[res], 8); + *samples8++ = av_clip_uint8(pred[1]); + } else { + if(vlc[0].table) + res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); + else + res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } + pred[0] += sign_extend(h[0].values[res], 8); + *samples8++ = av_clip_uint8(pred[0]); + } + } + } + + for(i = 0; i < 4; i++) { + if(vlc[i].table) + ff_free_vlc(&vlc[i]); + av_free(h[i].bits); + av_free(h[i].lengths); + av_free(h[i].values); + } + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_smacker_decoder = { + .name = "smackvid", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SMACKVIDEO, + .priv_data_size = sizeof(SmackVContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Smacker video"), +}; + +AVCodec ff_smackaud_decoder = { + .name = "smackaud", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SMACKAUDIO, + .init = smka_decode_init, + .decode = smka_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), +}; diff --git a/ffmpeg/libavcodec/smc.c b/ffmpeg/libavcodec/smc.c new file mode 100644 index 0000000..2c7ab9a --- /dev/null +++ b/ffmpeg/libavcodec/smc.c @@ -0,0 +1,474 @@ +/* + * Quicktime Graphics (SMC) Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * QT SMC Video Decoder by Mike Melanson (melanson@pcisys.net) + * For more information about the SMC format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * The SMC decoder outputs PAL8 colorspace data. + */ + +#include +#include +#include + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define CPAIR 2 +#define CQUAD 4 +#define COCTET 8 + +#define COLORS_PER_TABLE 256 + +typedef struct SmcContext { + + AVCodecContext *avctx; + AVFrame frame; + + GetByteContext gb; + + /* SMC color tables */ + unsigned char color_pairs[COLORS_PER_TABLE * CPAIR]; + unsigned char color_quads[COLORS_PER_TABLE * CQUAD]; + unsigned char color_octets[COLORS_PER_TABLE * COCTET]; + + uint32_t pal[256]; +} SmcContext; + +#define GET_BLOCK_COUNT() \ + (opcode & 0x10) ? (1 + bytestream2_get_byte(&s->gb)) : 1 + (opcode & 0x0F); + +#define ADVANCE_BLOCK() \ +{ \ + pixel_ptr += 4; \ + if (pixel_ptr >= width) \ + { \ + pixel_ptr = 0; \ + row_ptr += stride * 4; \ + } \ + total_blocks--; \ + if (total_blocks < 0) \ + { \ + av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)\n"); \ + return; \ + } \ +} + +static void smc_decode_stream(SmcContext *s) +{ + int width = s->avctx->width; + int height = s->avctx->height; + int stride = s->frame.linesize[0]; + int i; + int chunk_size; + int buf_size = bytestream2_size(&s->gb); + unsigned char opcode; + int n_blocks; + unsigned int color_flags; + unsigned int color_flags_a; + unsigned int color_flags_b; + unsigned int flag_mask; + + unsigned char *pixels = s->frame.data[0]; + + int image_size = height * s->frame.linesize[0]; + int row_ptr = 0; + int pixel_ptr = 0; + int pixel_x, pixel_y; + int row_inc = stride - 4; + int block_ptr; + int prev_block_ptr; + int prev_block_ptr1, prev_block_ptr2; + int prev_block_flag; + int total_blocks; + int color_table_index; /* indexes to color pair, quad, or octet tables */ + int pixel; + + int color_pair_index = 0; + int color_quad_index = 0; + int color_octet_index = 0; + + /* make the palette available */ + memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE); + + bytestream2_skip(&s->gb, 1); + chunk_size = bytestream2_get_be24(&s->gb); + if (chunk_size != buf_size) + av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n", + chunk_size, buf_size); + + chunk_size = buf_size; + total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4); + + /* traverse through the blocks */ + while (total_blocks) { + /* sanity checks */ + /* make sure the row pointer hasn't gone wild */ + if (row_ptr >= image_size) { + av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)\n", + row_ptr, image_size); + return; + } + + opcode = bytestream2_get_byte(&s->gb); + switch (opcode & 0xF0) { + /* skip n blocks */ + case 0x00: + case 0x10: + n_blocks = GET_BLOCK_COUNT(); + while (n_blocks--) { + ADVANCE_BLOCK(); + } + break; + + /* repeat last block n times */ + case 0x20: + case 0x30: + n_blocks = GET_BLOCK_COUNT(); + + /* sanity check */ + if ((row_ptr == 0) && (pixel_ptr == 0)) { + av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yet\n", + opcode & 0xF0); + return; + } + + /* figure out where the previous block started */ + if (pixel_ptr == 0) + prev_block_ptr1 = + (row_ptr - s->avctx->width * 4) + s->avctx->width - 4; + else + prev_block_ptr1 = row_ptr + pixel_ptr - 4; + + while (n_blocks--) { + block_ptr = row_ptr + pixel_ptr; + prev_block_ptr = prev_block_ptr1; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + pixels[block_ptr++] = pixels[prev_block_ptr++]; + } + block_ptr += row_inc; + prev_block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* repeat previous pair of blocks n times */ + case 0x40: + case 0x50: + n_blocks = GET_BLOCK_COUNT(); + n_blocks *= 2; + + /* sanity check */ + if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) { + av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yet\n", + opcode & 0xF0); + return; + } + + /* figure out where the previous 2 blocks started */ + if (pixel_ptr == 0) + prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + + s->avctx->width - 4 * 2; + else if (pixel_ptr == 4) + prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc; + else + prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2; + + if (pixel_ptr == 0) + prev_block_ptr2 = (row_ptr - s->avctx->width * 4) + row_inc; + else + prev_block_ptr2 = row_ptr + pixel_ptr - 4; + + prev_block_flag = 0; + while (n_blocks--) { + block_ptr = row_ptr + pixel_ptr; + if (prev_block_flag) + prev_block_ptr = prev_block_ptr2; + else + prev_block_ptr = prev_block_ptr1; + prev_block_flag = !prev_block_flag; + + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + pixels[block_ptr++] = pixels[prev_block_ptr++]; + } + block_ptr += row_inc; + prev_block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* 1-color block encoding */ + case 0x60: + case 0x70: + n_blocks = GET_BLOCK_COUNT(); + pixel = bytestream2_get_byte(&s->gb); + + while (n_blocks--) { + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + pixels[block_ptr++] = pixel; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* 2-color block encoding */ + case 0x80: + case 0x90: + n_blocks = (opcode & 0x0F) + 1; + + /* figure out which color pair to use to paint the 2-color block */ + if ((opcode & 0xF0) == 0x80) { + /* fetch the next 2 colors from bytestream and store in next + * available entry in the color pair table */ + for (i = 0; i < CPAIR; i++) { + pixel = bytestream2_get_byte(&s->gb); + color_table_index = CPAIR * color_pair_index + i; + s->color_pairs[color_table_index] = pixel; + } + /* this is the base index to use for this block */ + color_table_index = CPAIR * color_pair_index; + color_pair_index++; + /* wraparound */ + if (color_pair_index == COLORS_PER_TABLE) + color_pair_index = 0; + } else + color_table_index = CPAIR * bytestream2_get_byte(&s->gb); + + while (n_blocks--) { + color_flags = bytestream2_get_be16(&s->gb); + flag_mask = 0x8000; + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + if (color_flags & flag_mask) + pixel = color_table_index + 1; + else + pixel = color_table_index; + flag_mask >>= 1; + pixels[block_ptr++] = s->color_pairs[pixel]; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* 4-color block encoding */ + case 0xA0: + case 0xB0: + n_blocks = (opcode & 0x0F) + 1; + + /* figure out which color quad to use to paint the 4-color block */ + if ((opcode & 0xF0) == 0xA0) { + /* fetch the next 4 colors from bytestream and store in next + * available entry in the color quad table */ + for (i = 0; i < CQUAD; i++) { + pixel = bytestream2_get_byte(&s->gb); + color_table_index = CQUAD * color_quad_index + i; + s->color_quads[color_table_index] = pixel; + } + /* this is the base index to use for this block */ + color_table_index = CQUAD * color_quad_index; + color_quad_index++; + /* wraparound */ + if (color_quad_index == COLORS_PER_TABLE) + color_quad_index = 0; + } else + color_table_index = CQUAD * bytestream2_get_byte(&s->gb); + + while (n_blocks--) { + color_flags = bytestream2_get_be32(&s->gb); + /* flag mask actually acts as a bit shift count here */ + flag_mask = 30; + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + pixel = color_table_index + + ((color_flags >> flag_mask) & 0x03); + flag_mask -= 2; + pixels[block_ptr++] = s->color_quads[pixel]; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* 8-color block encoding */ + case 0xC0: + case 0xD0: + n_blocks = (opcode & 0x0F) + 1; + + /* figure out which color octet to use to paint the 8-color block */ + if ((opcode & 0xF0) == 0xC0) { + /* fetch the next 8 colors from bytestream and store in next + * available entry in the color octet table */ + for (i = 0; i < COCTET; i++) { + pixel = bytestream2_get_byte(&s->gb); + color_table_index = COCTET * color_octet_index + i; + s->color_octets[color_table_index] = pixel; + } + /* this is the base index to use for this block */ + color_table_index = COCTET * color_octet_index; + color_octet_index++; + /* wraparound */ + if (color_octet_index == COLORS_PER_TABLE) + color_octet_index = 0; + } else + color_table_index = COCTET * bytestream2_get_byte(&s->gb); + + while (n_blocks--) { + /* + For this input of 6 hex bytes: + 01 23 45 67 89 AB + Mangle it to this output: + flags_a = xx012456, flags_b = xx89A37B + */ + /* build the color flags */ + int val1 = bytestream2_get_be16(&s->gb); + int val2 = bytestream2_get_be16(&s->gb); + int val3 = bytestream2_get_be16(&s->gb); + color_flags_a = ((val1 & 0xFFF0) << 8) | (val2 >> 4); + color_flags_b = ((val3 & 0xFFF0) << 8) | + ((val1 & 0x0F) << 8) | ((val2 & 0x0F) << 4) | (val3 & 0x0F); + + color_flags = color_flags_a; + /* flag mask actually acts as a bit shift count here */ + flag_mask = 21; + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + /* reload flags at third row (iteration pixel_y == 2) */ + if (pixel_y == 2) { + color_flags = color_flags_b; + flag_mask = 21; + } + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + pixel = color_table_index + + ((color_flags >> flag_mask) & 0x07); + flag_mask -= 3; + pixels[block_ptr++] = s->color_octets[pixel]; + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + /* 16-color block encoding (every pixel is a different color) */ + case 0xE0: + n_blocks = (opcode & 0x0F) + 1; + + while (n_blocks--) { + block_ptr = row_ptr + pixel_ptr; + for (pixel_y = 0; pixel_y < 4; pixel_y++) { + for (pixel_x = 0; pixel_x < 4; pixel_x++) { + pixels[block_ptr++] = bytestream2_get_byte(&s->gb); + } + block_ptr += row_inc; + } + ADVANCE_BLOCK(); + } + break; + + case 0xF0: + avpriv_request_sample(s->avctx, "0xF0 opcode"); + break; + } + } + + return; +} + +static av_cold int smc_decode_init(AVCodecContext *avctx) +{ + SmcContext *s = avctx->priv_data; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + +static int smc_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + SmcContext *s = avctx->priv_data; + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + int ret; + + bytestream2_init(&s->gb, buf, buf_size); + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + if (pal) { + s->frame.palette_has_changed = 1; + memcpy(s->pal, pal, AVPALETTE_SIZE); + } + + smc_decode_stream(s); + + *got_frame = 1; + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int smc_decode_end(AVCodecContext *avctx) +{ + SmcContext *s = avctx->priv_data; + + av_frame_unref(&s->frame); + + return 0; +} + +AVCodec ff_smc_decoder = { + .name = "smc", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SMC, + .priv_data_size = sizeof(SmcContext), + .init = smc_decode_init, + .close = smc_decode_end, + .decode = smc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"), +}; diff --git a/ffmpeg/libavcodec/snow.c b/ffmpeg/libavcodec/snow.c new file mode 100644 index 0000000..de19687 --- /dev/null +++ b/ffmpeg/libavcodec/snow.c @@ -0,0 +1,692 @@ +/* + * Copyright (C) 2004 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 "libavutil/intmath.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dsputil.h" +#include "snow_dwt.h" +#include "internal.h" +#include "snow.h" +#include "snowdata.h" + +#include "rangecoder.h" +#include "mathops.h" +#include "h263.h" + + +void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, + int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + int y, x; + IDWTELEM * dst; + for(y=0; y>1); + const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1); + const uint8_t *obmc4= obmc3+ (obmc_stride>>1); + dst = slice_buffer_get_line(sb, src_y + y); + for(x=0; x>= 8 - FRAC_BITS; + } + if(add){ + v += dst[x + src_x]; + v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS; + if(v&(~255)) v= ~(v>>31); + dst8[x + y*src_stride] = v; + }else{ + dst[x + src_x] -= v; + } + } + } +} + +void ff_snow_reset_contexts(SnowContext *s){ //FIXME better initial contexts + int plane_index, level, orientation; + + for(plane_index=0; plane_index<3; plane_index++){ + for(level=0; levelplane[plane_index].band[level][orientation].state, MID_STATE, sizeof(s->plane[plane_index].band[level][orientation].state)); + } + } + } + memset(s->header_state, MID_STATE, sizeof(s->header_state)); + memset(s->block_state, MID_STATE, sizeof(s->block_state)); +} + +int ff_snow_alloc_blocks(SnowContext *s){ + int w= -((-s->avctx->width )>>LOG2_MB_SIZE); + int h= -((-s->avctx->height)>>LOG2_MB_SIZE); + + s->b_width = w; + s->b_height= h; + + av_free(s->block); + s->block= av_mallocz(w * h * sizeof(BlockNode) << (s->block_max_depth*2)); + return 0; +} + +static void init_qexp(void){ + int i; + double v=128; + + for(i=0; i>4; + + b= needs[l] | needs[r]; + if(p && !p->diag_mc) + b= 15; + + if(b&5){ + for(y=0; y < b_h+HTAPS_MAX-1; y++){ + for(x=0; x < b_w; x++){ + int a_1=src[x + HTAPS_MAX/2-4]; + int a0= src[x + HTAPS_MAX/2-3]; + int a1= src[x + HTAPS_MAX/2-2]; + int a2= src[x + HTAPS_MAX/2-1]; + int a3= src[x + HTAPS_MAX/2+0]; + int a4= src[x + HTAPS_MAX/2+1]; + int a5= src[x + HTAPS_MAX/2+2]; + int a6= src[x + HTAPS_MAX/2+3]; + int am=0; + if(!p || p->fast_mc){ + am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5); + tmpI[x]= am; + am= (am+16)>>5; + }else{ + am= p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6); + tmpI[x]= am; + am= (am+32)>>6; + } + + if(am&(~255)) am= ~(am>>31); + tmp2[x]= am; + } + tmpI+= 64; + tmp2+= 64; + src += stride; + } + src -= stride*y; + } + src += HTAPS_MAX/2 - 1; + tmp2= tmp2t[1]; + + if(b&2){ + for(y=0; y < b_h; y++){ + for(x=0; x < b_w+1; x++){ + int a_1=src[x + (HTAPS_MAX/2-4)*stride]; + int a0= src[x + (HTAPS_MAX/2-3)*stride]; + int a1= src[x + (HTAPS_MAX/2-2)*stride]; + int a2= src[x + (HTAPS_MAX/2-1)*stride]; + int a3= src[x + (HTAPS_MAX/2+0)*stride]; + int a4= src[x + (HTAPS_MAX/2+1)*stride]; + int a5= src[x + (HTAPS_MAX/2+2)*stride]; + int a6= src[x + (HTAPS_MAX/2+3)*stride]; + int am=0; + if(!p || p->fast_mc) + am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 16)>>5; + else + am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 32)>>6; + + if(am&(~255)) am= ~(am>>31); + tmp2[x]= am; + } + src += stride; + tmp2+= 64; + } + src -= stride*y; + } + src += stride*(HTAPS_MAX/2 - 1); + tmp2= tmp2t[2]; + tmpI= tmpIt; + if(b&4){ + for(y=0; y < b_h; y++){ + for(x=0; x < b_w; x++){ + int a_1=tmpI[x + (HTAPS_MAX/2-4)*64]; + int a0= tmpI[x + (HTAPS_MAX/2-3)*64]; + int a1= tmpI[x + (HTAPS_MAX/2-2)*64]; + int a2= tmpI[x + (HTAPS_MAX/2-1)*64]; + int a3= tmpI[x + (HTAPS_MAX/2+0)*64]; + int a4= tmpI[x + (HTAPS_MAX/2+1)*64]; + int a5= tmpI[x + (HTAPS_MAX/2+2)*64]; + int a6= tmpI[x + (HTAPS_MAX/2+3)*64]; + int am=0; + if(!p || p->fast_mc) + am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 512)>>10; + else + am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 2048)>>12; + if(am&(~255)) am= ~(am>>31); + tmp2[x]= am; + } + tmpI+= 64; + tmp2+= 64; + } + } + + hpel[ 0]= src; + hpel[ 1]= tmp2t[0] + 64*(HTAPS_MAX/2-1); + hpel[ 2]= src + 1; + + hpel[ 4]= tmp2t[1]; + hpel[ 5]= tmp2t[2]; + hpel[ 6]= tmp2t[1] + 1; + + hpel[ 8]= src + stride; + hpel[ 9]= hpel[1] + 64; + hpel[10]= hpel[8] + 1; + +#define MC_STRIDE(x) (needs[x] ? 64 : stride) + + if(b==15){ + int dxy = dx / 8 + dy / 8 * 4; + const uint8_t *src1 = hpel[dxy ]; + const uint8_t *src2 = hpel[dxy + 1]; + const uint8_t *src3 = hpel[dxy + 4]; + const uint8_t *src4 = hpel[dxy + 5]; + int stride1 = MC_STRIDE(dxy); + int stride2 = MC_STRIDE(dxy + 1); + int stride3 = MC_STRIDE(dxy + 4); + int stride4 = MC_STRIDE(dxy + 5); + dx&=7; + dy&=7; + for(y=0; y < b_h; y++){ + for(x=0; x < b_w; x++){ + dst[x]= ((8-dx)*(8-dy)*src1[x] + dx*(8-dy)*src2[x]+ + (8-dx)* dy *src3[x] + dx* dy *src4[x]+32)>>6; + } + src1+=stride1; + src2+=stride2; + src3+=stride3; + src4+=stride4; + dst +=stride; + } + }else{ + const uint8_t *src1= hpel[l]; + const uint8_t *src2= hpel[r]; + int stride1 = MC_STRIDE(l); + int stride2 = MC_STRIDE(r); + int a= weight[((dx&7) + (8*(dy&7)))]; + int b= 8-a; + for(y=0; y < b_h; y++){ + for(x=0; x < b_w; x++){ + dst[x]= (a*src1[x] + b*src2[x] + 4)>>3; + } + src1+=stride1; + src2+=stride2; + dst +=stride; + } + } +} + +void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){ + if(block->type & BLOCK_INTRA){ + int x, y; + const unsigned color = block->color[plane_index]; + const unsigned color4 = color*0x01010101; + if(b_w==32){ + for(y=0; y < b_h; y++){ + *(uint32_t*)&dst[0 + y*stride]= color4; + *(uint32_t*)&dst[4 + y*stride]= color4; + *(uint32_t*)&dst[8 + y*stride]= color4; + *(uint32_t*)&dst[12+ y*stride]= color4; + *(uint32_t*)&dst[16+ y*stride]= color4; + *(uint32_t*)&dst[20+ y*stride]= color4; + *(uint32_t*)&dst[24+ y*stride]= color4; + *(uint32_t*)&dst[28+ y*stride]= color4; + } + }else if(b_w==16){ + for(y=0; y < b_h; y++){ + *(uint32_t*)&dst[0 + y*stride]= color4; + *(uint32_t*)&dst[4 + y*stride]= color4; + *(uint32_t*)&dst[8 + y*stride]= color4; + *(uint32_t*)&dst[12+ y*stride]= color4; + } + }else if(b_w==8){ + for(y=0; y < b_h; y++){ + *(uint32_t*)&dst[0 + y*stride]= color4; + *(uint32_t*)&dst[4 + y*stride]= color4; + } + }else if(b_w==4){ + for(y=0; y < b_h; y++){ + *(uint32_t*)&dst[0 + y*stride]= color4; + } + }else{ + for(y=0; y < b_h; y++){ + for(x=0; x < b_w; x++){ + dst[x + y*stride]= color; + } + } + } + }else{ + uint8_t *src= s->last_picture[block->ref].data[plane_index]; + const int scale= plane_index ? (2*s->mv_scale)>>s->chroma_h_shift : 2*s->mv_scale; + int mx= block->mx*scale; + int my= block->my*scale; + const int dx= mx&15; + const int dy= my&15; + const int tab_index= 3 - (b_w>>2) + (b_w>>4); + sx += (mx>>4) - (HTAPS_MAX/2-1); + sy += (my>>4) - (HTAPS_MAX/2-1); + src += sx + sy*stride; + if( (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0) + || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){ + s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h); + src= tmp + MB_SIZE; + } + + av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale + +// assert(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h); +// assert(!(b_w&(b_w-1))); + av_assert2(b_w>1 && b_h>1); + av_assert2((tab_index>=0 && tab_index<4) || b_w==32); + if((dx&3) || (dy&3) || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) || (b_w&(b_w-1)) || !s->plane[plane_index].fast_mc ) + mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy); + else if(b_w==32){ + int y; + for(y=0; yh264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 3 + (y+3)*stride,stride); + s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 19 + (y+3)*stride,stride); + } + }else if(b_w==b_h) + s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst,src + 3 + 3*stride,stride); + else if(b_w==2*b_h){ + s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst ,src + 3 + 3*stride,stride); + s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 3 + b_h + 3*stride,stride); + }else{ + av_assert2(2*b_w==b_h); + s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst ,src + 3 + 3*stride ,stride); + s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst+b_w*stride,src + 3 + 3*stride+b_w*stride,stride); + } + } +} + +#define mca(dx,dy,b_w)\ +static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int h){\ + av_assert2(h==b_w);\ + mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, stride, b_w, b_w, dx, dy);\ +} + +mca( 0, 0,16) +mca( 8, 0,16) +mca( 0, 8,16) +mca( 8, 8,16) +mca( 0, 0,8) +mca( 8, 0,8) +mca( 0, 8,8) +mca( 8, 8,8) + +av_cold int ff_snow_common_init(AVCodecContext *avctx){ + SnowContext *s = avctx->priv_data; + int width, height; + int i, j; + + s->avctx= avctx; + s->max_ref_frames=1; //just make sure it's not an invalid value in case of no initial keyframe + + ff_dsputil_init(&s->dsp, avctx); + ff_hpeldsp_init(&s->hdsp, avctx->flags); + ff_videodsp_init(&s->vdsp, 8); + ff_dwt_init(&s->dwt); + ff_h264qpel_init(&s->h264qpel, 8); + +#define mcf(dx,dy)\ + s->dsp.put_qpel_pixels_tab [0][dy+dx/4]=\ + s->dsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\ + s->h264qpel.put_h264_qpel_pixels_tab[0][dy+dx/4];\ + s->dsp.put_qpel_pixels_tab [1][dy+dx/4]=\ + s->dsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\ + s->h264qpel.put_h264_qpel_pixels_tab[1][dy+dx/4]; + + mcf( 0, 0) + mcf( 4, 0) + mcf( 8, 0) + mcf(12, 0) + mcf( 0, 4) + mcf( 4, 4) + mcf( 8, 4) + mcf(12, 4) + mcf( 0, 8) + mcf( 4, 8) + mcf( 8, 8) + mcf(12, 8) + mcf( 0,12) + mcf( 4,12) + mcf( 8,12) + mcf(12,12) + +#define mcfh(dx,dy)\ + s->hdsp.put_pixels_tab [0][dy/4+dx/8]=\ + s->hdsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\ + mc_block_hpel ## dx ## dy ## 16;\ + s->hdsp.put_pixels_tab [1][dy/4+dx/8]=\ + s->hdsp.put_no_rnd_pixels_tab[1][dy/4+dx/8]=\ + mc_block_hpel ## dx ## dy ## 8; + + mcfh(0, 0) + mcfh(8, 0) + mcfh(0, 8) + mcfh(8, 8) + + init_qexp(); + +// dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift); + + width= s->avctx->width; + height= s->avctx->height; + + FF_ALLOCZ_OR_GOTO(avctx, s->spatial_idwt_buffer, width * height * sizeof(IDWTELEM), fail); + FF_ALLOCZ_OR_GOTO(avctx, s->spatial_dwt_buffer, width * height * sizeof(DWTELEM), fail); //FIXME this does not belong here + FF_ALLOCZ_OR_GOTO(avctx, s->temp_dwt_buffer, width * sizeof(DWTELEM), fail); + FF_ALLOCZ_OR_GOTO(avctx, s->temp_idwt_buffer, width * sizeof(IDWTELEM), fail); + FF_ALLOC_OR_GOTO(avctx, s->run_buffer, ((width + 1) >> 1) * ((height + 1) >> 1) * sizeof(*s->run_buffer), fail); + + for(i=0; ilast_picture[i]); + } + + avcodec_get_frame_defaults(&s->mconly_picture); + avcodec_get_frame_defaults(&s->current_picture); + + return 0; +fail: + return AVERROR(ENOMEM); +} + +int ff_snow_common_init_after_header(AVCodecContext *avctx) { + SnowContext *s = avctx->priv_data; + int plane_index, level, orientation; + int ret, emu_buf_size; + + if(!s->scratchbuf) { + if ((ret = ff_get_buffer(s->avctx, &s->mconly_picture, + AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + FF_ALLOCZ_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture.linesize[0], 2*avctx->width+256)*7*MB_SIZE, fail); + emu_buf_size = FFMAX(s->mconly_picture.linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1); + FF_ALLOC_OR_GOTO(avctx, s->emu_edge_buffer, emu_buf_size, fail); + } + + if(s->mconly_picture.format != avctx->pix_fmt) { + av_log(avctx, AV_LOG_ERROR, "pixel format changed\n"); + return AVERROR_INVALIDDATA; + } + + for(plane_index=0; plane_index<3; plane_index++){ + int w= s->avctx->width; + int h= s->avctx->height; + + if(plane_index){ + w>>= s->chroma_h_shift; + h>>= s->chroma_v_shift; + } + s->plane[plane_index].width = w; + s->plane[plane_index].height= h; + + for(level=s->spatial_decomposition_count-1; level>=0; level--){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &s->plane[plane_index].band[level][orientation]; + + b->buf= s->spatial_dwt_buffer; + b->level= level; + b->stride= s->plane[plane_index].width << (s->spatial_decomposition_count - level); + b->width = (w + !(orientation&1))>>1; + b->height= (h + !(orientation>1))>>1; + + b->stride_line = 1 << (s->spatial_decomposition_count - level); + b->buf_x_offset = 0; + b->buf_y_offset = 0; + + if(orientation&1){ + b->buf += (w+1)>>1; + b->buf_x_offset = (w+1)>>1; + } + if(orientation>1){ + b->buf += b->stride>>1; + b->buf_y_offset = b->stride_line >> 1; + } + b->ibuf= s->spatial_idwt_buffer + (b->buf - s->spatial_dwt_buffer); + + if(level) + b->parent= &s->plane[plane_index].band[level-1][orientation]; + //FIXME avoid this realloc + av_freep(&b->x_coeff); + b->x_coeff=av_mallocz(((b->width+1) * b->height+1)*sizeof(x_and_coeff)); + } + w= (w+1)>>1; + h= (h+1)>>1; + } + } + + return 0; +fail: + return AVERROR(ENOMEM); +} + +#define USE_HALFPEL_PLANE 0 + +static void halfpel_interpol(SnowContext *s, uint8_t *halfpel[4][4], AVFrame *frame){ + int p,x,y; + + for(p=0; p<3; p++){ + int is_chroma= !!p; + int w= is_chroma ? s->avctx->width >>s->chroma_h_shift : s->avctx->width; + int h= is_chroma ? s->avctx->height>>s->chroma_v_shift : s->avctx->height; + int ls= frame->linesize[p]; + uint8_t *src= frame->data[p]; + + halfpel[1][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls); + halfpel[2][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls); + halfpel[3][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls); + + halfpel[0][p]= src; + for(y=0; y>5; + } + } + for(y=0; y>5; + } + } + src= halfpel[1][p]; + for(y=0; y>5; + } + } + +//FIXME border! + } +} + +void ff_snow_release_buffer(AVCodecContext *avctx) +{ + SnowContext *s = avctx->priv_data; + int i; + + if(s->last_picture[s->max_ref_frames-1].data[0]){ + av_frame_unref(&s->last_picture[s->max_ref_frames-1]); + for(i=0; i<9; i++) + if(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3]) + av_free(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] - EDGE_WIDTH*(1+s->current_picture.linesize[i%3])); + } +} + +int ff_snow_frame_start(SnowContext *s){ + AVFrame tmp; + int i, ret; + int w= s->avctx->width; //FIXME round up to x16 ? + int h= s->avctx->height; + + if (s->current_picture.data[0] && !(s->avctx->flags&CODEC_FLAG_EMU_EDGE)) { + s->dsp.draw_edges(s->current_picture.data[0], + s->current_picture.linesize[0], w , h , + EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.data[1], + s->current_picture.linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift, + EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM); + s->dsp.draw_edges(s->current_picture.data[2], + s->current_picture.linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift, + EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM); + } + + ff_snow_release_buffer(s->avctx); + + av_frame_move_ref(&tmp, &s->last_picture[s->max_ref_frames-1]); + for(i=s->max_ref_frames-1; i>0; i--) + av_frame_move_ref(&s->last_picture[i+1], &s->last_picture[i]); + memmove(s->halfpel_plane+1, s->halfpel_plane, (s->max_ref_frames-1)*sizeof(void*)*4*4); + if(USE_HALFPEL_PLANE && s->current_picture.data[0]) + halfpel_interpol(s, s->halfpel_plane[0], &s->current_picture); + av_frame_move_ref(&s->last_picture[0], &s->current_picture); + av_frame_move_ref(&s->current_picture, &tmp); + + if(s->keyframe){ + s->ref_frames= 0; + }else{ + int i; + for(i=0; imax_ref_frames && s->last_picture[i].data[0]; i++) + if(i && s->last_picture[i-1].key_frame) + break; + s->ref_frames= i; + if(s->ref_frames==0){ + av_log(s->avctx,AV_LOG_ERROR, "No reference frames\n"); + return -1; + } + } + + if ((ret = ff_get_buffer(s->avctx, &s->current_picture, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + s->current_picture.key_frame= s->keyframe; + + return 0; +} + +av_cold void ff_snow_common_end(SnowContext *s) +{ + int plane_index, level, orientation, i; + + av_freep(&s->spatial_dwt_buffer); + av_freep(&s->temp_dwt_buffer); + av_freep(&s->spatial_idwt_buffer); + av_freep(&s->temp_idwt_buffer); + av_freep(&s->run_buffer); + + s->m.me.temp= NULL; + av_freep(&s->m.me.scratchpad); + av_freep(&s->m.me.map); + av_freep(&s->m.me.score_map); + av_freep(&s->m.obmc_scratchpad); + + av_freep(&s->block); + av_freep(&s->scratchbuf); + av_freep(&s->emu_edge_buffer); + + for(i=0; iref_mvs[i]); + av_freep(&s->ref_scores[i]); + if(s->last_picture[i].data[0]) { + av_assert0(s->last_picture[i].data[0] != s->current_picture.data[0]); + av_frame_unref(&s->last_picture[i]); + } + } + + for(plane_index=0; plane_index<3; plane_index++){ + for(level=s->spatial_decomposition_count-1; level>=0; level--){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &s->plane[plane_index].band[level][orientation]; + + av_freep(&b->x_coeff); + } + } + } + av_frame_unref(&s->mconly_picture); + av_frame_unref(&s->current_picture); +} diff --git a/ffmpeg/libavcodec/snow.h b/ffmpeg/libavcodec/snow.h new file mode 100644 index 0000000..922a48e --- /dev/null +++ b/ffmpeg/libavcodec/snow.h @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2004 Michael Niedermayer + * Copyright (C) 2006 Robert Edele + * + * 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 + */ + +#ifndef AVCODEC_SNOW_H +#define AVCODEC_SNOW_H + +#include "dsputil.h" +#include "hpeldsp.h" +#include "snow_dwt.h" + +#include "rangecoder.h" +#include "mathops.h" +#include "mpegvideo.h" +#include "h264qpel.h" + +#define MID_STATE 128 + +#define MAX_PLANES 4 +#define QSHIFT 5 +#define QROOT (1<>1]; + (*i)--; + } +} + +static av_always_inline void snow_interleave_line_footer(int * i, IDWTELEM * low, IDWTELEM * high){ + for (; (*i)>=0; (*i)-=2){ + low[(*i)+1] = high[(*i)>>1]; + low[*i] = low[(*i)>>1]; + } +} + +static av_always_inline void snow_horizontal_compose_lift_lead_out(int i, IDWTELEM * dst, IDWTELEM * src, IDWTELEM * ref, int width, int w, int lift_high, int mul, int add, int shift){ + for(; i> shift); + } + + if((width^lift_high)&1){ + dst[w] = src[w] - ((mul * 2 * ref[w] + add) >> shift); + } +} + +static av_always_inline void snow_horizontal_compose_liftS_lead_out(int i, IDWTELEM * dst, IDWTELEM * src, IDWTELEM * ref, int width, int w){ + for(; i> W_BS); + } + + if(width&1){ + dst[w] = src[w] + ((2 * ref[w] + W_BO + 4 * src[w]) >> W_BS); + } +} + +/* common code */ + +int ff_snow_common_init(AVCodecContext *avctx); +int ff_snow_common_init_after_header(AVCodecContext *avctx); +void ff_snow_common_end(SnowContext *s); +void ff_snow_release_buffer(AVCodecContext *avctx); +void ff_snow_reset_contexts(SnowContext *s); +int ff_snow_alloc_blocks(SnowContext *s); +int ff_snow_frame_start(SnowContext *s); +void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int stride, + int sx, int sy, int b_w, int b_h, BlockNode *block, + int plane_index, int w, int h); +/* common inline functions */ +//XXX doublecheck all of them should stay inlined + +static inline void snow_set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){ + const int w= s->b_width << s->block_max_depth; + const int rem_depth= s->block_max_depth - level; + const int index= (x + y*w) << rem_depth; + const int block_w= 1<block[index + i + j*w]= block; + } + } +} + +static inline void pred_mv(SnowContext *s, int *mx, int *my, int ref, + const BlockNode *left, const BlockNode *top, const BlockNode *tr){ + if(s->ref_frames == 1){ + *mx = mid_pred(left->mx, top->mx, tr->mx); + *my = mid_pred(left->my, top->my, tr->my); + }else{ + const int *scale = ff_scale_mv_ref[ref]; + *mx = mid_pred((left->mx * scale[left->ref] + 128) >>8, + (top ->mx * scale[top ->ref] + 128) >>8, + (tr ->mx * scale[tr ->ref] + 128) >>8); + *my = mid_pred((left->my * scale[left->ref] + 128) >>8, + (top ->my * scale[top ->ref] + 128) >>8, + (tr ->my * scale[tr ->ref] + 128) >>8); + } +} + +static av_always_inline int same_block(BlockNode *a, BlockNode *b){ + if((a->type&BLOCK_INTRA) && (b->type&BLOCK_INTRA)){ + return !((a->color[0] - b->color[0]) | (a->color[1] - b->color[1]) | (a->color[2] - b->color[2])); + }else{ + return !((a->mx - b->mx) | (a->my - b->my) | (a->ref - b->ref) | ((a->type ^ b->type)&BLOCK_INTRA)); + } +} + +//FIXME name cleanup (b_w, block_w, b_width stuff) +//XXX should we really inline it? +static av_always_inline void add_yblock(SnowContext *s, int sliced, slice_buffer *sb, IDWTELEM *dst, uint8_t *dst8, const uint8_t *obmc, int src_x, int src_y, int b_w, int b_h, int w, int h, int dst_stride, int src_stride, int obmc_stride, int b_x, int b_y, int add, int offset_dst, int plane_index){ + const int b_width = s->b_width << s->block_max_depth; + const int b_height= s->b_height << s->block_max_depth; + const int b_stride= b_width; + BlockNode *lt= &s->block[b_x + b_y*b_stride]; + BlockNode *rt= lt+1; + BlockNode *lb= lt+b_stride; + BlockNode *rb= lb+1; + uint8_t *block[4]; + int tmp_step= src_stride >= 7*MB_SIZE ? MB_SIZE : MB_SIZE*src_stride; + uint8_t *tmp = s->scratchbuf; + uint8_t *ptmp; + int x,y; + + if(b_x<0){ + lt= rt; + lb= rb; + }else if(b_x + 1 >= b_width){ + rt= lt; + rb= lb; + } + if(b_y<0){ + lt= lb; + rt= rb; + }else if(b_y + 1 >= b_height){ + lb= lt; + rb= rt; + } + + if(src_x<0){ //FIXME merge with prev & always round internal width up to *16 + obmc -= src_x; + b_w += src_x; + if(!sliced && !offset_dst) + dst -= src_x; + src_x=0; + }else if(src_x + b_w > w){ + b_w = w - src_x; + } + if(src_y<0){ + obmc -= src_y*obmc_stride; + b_h += src_y; + if(!sliced && !offset_dst) + dst -= src_y*dst_stride; + src_y=0; + }else if(src_y + b_h> h){ + b_h = h - src_y; + } + + if(b_w<=0 || b_h<=0) return; + + av_assert2(src_stride > 2*MB_SIZE + 5); + + if(!sliced && offset_dst) + dst += src_x + src_y*dst_stride; + dst8+= src_x + src_y*src_stride; +// src += src_x + src_y*src_stride; + + ptmp= tmp + 3*tmp_step; + block[0]= ptmp; + ptmp+=tmp_step; + ff_snow_pred_block(s, block[0], tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h); + + if(same_block(lt, rt)){ + block[1]= block[0]; + }else{ + block[1]= ptmp; + ptmp+=tmp_step; + ff_snow_pred_block(s, block[1], tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h); + } + + if(same_block(lt, lb)){ + block[2]= block[0]; + }else if(same_block(rt, lb)){ + block[2]= block[1]; + }else{ + block[2]= ptmp; + ptmp+=tmp_step; + ff_snow_pred_block(s, block[2], tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h); + } + + if(same_block(lt, rb) ){ + block[3]= block[0]; + }else if(same_block(rt, rb)){ + block[3]= block[1]; + }else if(same_block(lb, rb)){ + block[3]= block[2]; + }else{ + block[3]= ptmp; + ff_snow_pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h); + } + if(sliced){ + s->dwt.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + }else{ + for(y=0; y>1); + const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1); + const uint8_t *obmc4= obmc3+ (obmc_stride>>1); + for(x=0; x>= 8 - FRAC_BITS; + } + if(add){ + v += dst[x + y*dst_stride]; + v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS; + if(v&(~255)) v= ~(v>>31); + dst8[x + y*src_stride] = v; + }else{ + dst[x + y*dst_stride] -= v; + } + } + } + } +} + +static av_always_inline void predict_slice(SnowContext *s, IDWTELEM *buf, int plane_index, int add, int mb_y){ + Plane *p= &s->plane[plane_index]; + const int mb_w= s->b_width << s->block_max_depth; + const int mb_h= s->b_height << s->block_max_depth; + int x, y, mb_x; + int block_size = MB_SIZE >> s->block_max_depth; + int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; + int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth]; + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; + int ref_stride= s->current_picture.linesize[plane_index]; + uint8_t *dst8= s->current_picture.data[plane_index]; + int w= p->width; + int h= p->height; + av_assert2(s->chroma_h_shift == s->chroma_v_shift); // obmc params assume squares + if(s->keyframe || (s->avctx->debug&512)){ + if(mb_y==mb_h) + return; + + if(add){ + for(y=block_h*mb_y; y>= FRAC_BITS; + if(v&(~255)) v= ~(v>>31); + dst8[x + y*ref_stride]= v; + } + } + }else{ + for(y=block_h*mb_y; yb_height << s->block_max_depth; + int mb_y; + for(mb_y=0; mb_y<=mb_h; mb_y++) + predict_slice(s, buf, plane_index, add, mb_y); +} + +static inline void set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){ + const int w= s->b_width << s->block_max_depth; + const int rem_depth= s->block_max_depth - level; + const int index= (x + y*w) << rem_depth; + const int block_w= 1<block[index + i + j*w]= block; + } + } +} + +static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){ + SnowContext *s = c->avctx->priv_data; + const int offset[3]= { + y*c-> stride + x, + ((y*c->uvstride + x)>>s->chroma_h_shift), + ((y*c->uvstride + x)>>s->chroma_h_shift), + }; + int i; + for(i=0; i<3; i++){ + c->src[0][i]= src [i]; + c->ref[0][i]= ref [i] + offset[i]; + } + av_assert2(!ref_index); +} + + +/* bitstream functions */ + +extern const int8_t ff_quant3bA[256]; + +#define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0 + +static inline void put_symbol(RangeCoder *c, uint8_t *state, int v, int is_signed){ + int i; + + if(v){ + const int a= FFABS(v); + const int e= av_log2(a); + const int el= FFMIN(e, 10); + put_rac(c, state+0, 0); + + for(i=0; i=el; i--){ + put_rac(c, state+22+9, (a>>i)&1); //22..31 + } + for(; i>=0; i--){ + put_rac(c, state+22+i, (a>>i)&1); //22..31 + } + + if(is_signed) + put_rac(c, state+11 + el, v < 0); //11..21 + }else{ + put_rac(c, state+0, 1); + } +} + +static inline int get_symbol(RangeCoder *c, uint8_t *state, int is_signed){ + if(get_rac(c, state+0)) + return 0; + else{ + int i, e, a; + e= 0; + while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10 + e++; + } + + a= 1; + for(i=e-1; i>=0; i--){ + a += a + get_rac(c, state+22 + FFMIN(i,9)); //22..31 + } + + e= -(is_signed && get_rac(c, state+11 + FFMIN(e,10))); //11..21 + return (a^e)-e; + } +} + +static inline void put_symbol2(RangeCoder *c, uint8_t *state, int v, int log2){ + int i; + int r= log2>=0 ? 1<=0); + av_assert2(log2>=-4); + + while(v >= r){ + put_rac(c, state+4+log2, 1); + v -= r; + log2++; + if(log2>0) r+=r; + } + put_rac(c, state+4+log2, 0); + + for(i=log2-1; i>=0; i--){ + put_rac(c, state+31-i, (v>>i)&1); + } +} + +static inline int get_symbol2(RangeCoder *c, uint8_t *state, int log2){ + int i; + int r= log2>=0 ? 1<=-4); + + while(log2<28 && get_rac(c, state+4+log2)){ + v+= r; + log2++; + if(log2>0) r+=r; + } + + for(i=log2-1; i>=0; i--){ + v+= get_rac(c, state+31-i)<width; + const int h= b->height; + int x,y; + + int run, runs; + x_and_coeff *xc= b->x_coeff; + x_and_coeff *prev_xc= NULL; + x_and_coeff *prev2_xc= xc; + x_and_coeff *parent_xc= parent ? parent->x_coeff : NULL; + x_and_coeff *prev_parent_xc= parent_xc; + + runs= get_symbol2(&s->c, b->state[30], 0); + if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3); + else run= INT_MAX; + + for(y=0; yx == 0){ + rt= prev_xc->coeff; + } + for(x=0; xx <= x) + prev_xc++; + if(prev_xc->x == x + 1) + rt= prev_xc->coeff; + else + rt=0; + } + if(parent_xc){ + if(x>>1 > parent_xc->x){ + parent_xc++; + } + if(x>>1 == parent_xc->x){ + p= parent_xc->coeff; + } + } + if(/*ll|*/l|lt|t|rt|p){ + int context= av_log2(/*FFABS(ll) + */3*(l>>1) + (lt>>1) + (t&~1) + (rt>>1) + (p>>1)); + + v=get_rac(&s->c, &b->state[0][context]); + if(v){ + v= 2*(get_symbol2(&s->c, b->state[context + 2], context-4) + 1); + v+=get_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l&0xFF] + 3*ff_quant3bA[t&0xFF]]); + + xc->x=x; + (xc++)->coeff= v; + } + }else{ + if(!run){ + if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3); + else run= INT_MAX; + v= 2*(get_symbol2(&s->c, b->state[0 + 2], 0-4) + 1); + v+=get_rac(&s->c, &b->state[0][16 + 1 + 3]); + + xc->x=x; + (xc++)->coeff= v; + }else{ + int max_run; + run--; + v=0; + av_assert2(run >= 0); + if(y) max_run= FFMIN(run, prev_xc->x - x - 2); + else max_run= FFMIN(run, w-x-1); + if(parent_xc) + max_run= FFMIN(max_run, 2*parent_xc->x - x - 1); + av_assert2(max_run >= 0 && max_run <= run); + + x+= max_run; + run-= max_run; + } + } + } + (xc++)->x= w+1; //end marker + prev_xc= prev2_xc; + prev2_xc= xc; + + if(parent_xc){ + if(y&1){ + while(parent_xc->x != parent->width+1) + parent_xc++; + parent_xc++; + prev_parent_xc= parent_xc; + }else{ + parent_xc= prev_parent_xc; + } + } + } + + (xc++)->x= w+1; //end marker +} + +#endif /* AVCODEC_SNOW_H */ diff --git a/ffmpeg/libavcodec/snow_dwt.c b/ffmpeg/libavcodec/snow_dwt.c new file mode 100644 index 0000000..28edf6a --- /dev/null +++ b/ffmpeg/libavcodec/snow_dwt.c @@ -0,0 +1,865 @@ +/* + * Copyright (C) 2004-2010 Michael Niedermayer + * Copyright (C) 2008 David Conrad + * + * 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 "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "dsputil.h" +#include "snow_dwt.h" + +int ff_slice_buffer_init(slice_buffer *buf, int line_count, + int max_allocated_lines, int line_width, + IDWTELEM *base_buffer) +{ + int i; + + buf->base_buffer = base_buffer; + buf->line_count = line_count; + buf->line_width = line_width; + buf->data_count = max_allocated_lines; + buf->line = av_mallocz(sizeof(IDWTELEM *) * line_count); + if (!buf->line) + return AVERROR(ENOMEM); + buf->data_stack = av_malloc(sizeof(IDWTELEM *) * max_allocated_lines); + if (!buf->data_stack) { + av_freep(&buf->line); + return AVERROR(ENOMEM); + } + + for (i = 0; i < max_allocated_lines; i++) { + buf->data_stack[i] = av_malloc(sizeof(IDWTELEM) * line_width); + if (!buf->data_stack[i]) { + for (i--; i >=0; i--) + av_freep(&buf->data_stack[i]); + av_freep(&buf->data_stack); + av_freep(&buf->line); + return AVERROR(ENOMEM); + } + } + + buf->data_stack_top = max_allocated_lines - 1; + return 0; +} + +IDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line) +{ + IDWTELEM *buffer; + + av_assert0(buf->data_stack_top >= 0); +// av_assert1(!buf->line[line]); + if (buf->line[line]) + return buf->line[line]; + + buffer = buf->data_stack[buf->data_stack_top]; + buf->data_stack_top--; + buf->line[line] = buffer; + + return buffer; +} + +void ff_slice_buffer_release(slice_buffer *buf, int line) +{ + IDWTELEM *buffer; + + av_assert1(line >= 0 && line < buf->line_count); + av_assert1(buf->line[line]); + + buffer = buf->line[line]; + buf->data_stack_top++; + buf->data_stack[buf->data_stack_top] = buffer; + buf->line[line] = NULL; +} + +void ff_slice_buffer_flush(slice_buffer *buf) +{ + int i; + for (i = 0; i < buf->line_count; i++) + if (buf->line[i]) + ff_slice_buffer_release(buf, i); +} + +void ff_slice_buffer_destroy(slice_buffer *buf) +{ + int i; + ff_slice_buffer_flush(buf); + + for (i = buf->data_count - 1; i >= 0; i--) + av_freep(&buf->data_stack[i]); + av_freep(&buf->data_stack); + av_freep(&buf->line); +} + +static inline int mirror(int v, int m) +{ + while ((unsigned)v > (unsigned)m) { + v = -v; + if (v < 0) + v += 2 * m; + } + return v; +} + +static av_always_inline void lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, + int dst_step, int src_step, int ref_step, + int width, int mul, int add, int shift, + int highpass, int inverse) +{ + const int mirror_left = !highpass; + const int mirror_right = (width & 1) ^ highpass; + const int w = (width >> 1) - 1 + (highpass & width); + int i; + +#define LIFT(src, ref, inv) ((src) + ((inv) ? -(ref) : +(ref))) + if (mirror_left) { + dst[0] = LIFT(src[0], ((mul * 2 * ref[0] + add) >> shift), inverse); + dst += dst_step; + src += src_step; + } + + for (i = 0; i < w; i++) + dst[i * dst_step] = LIFT(src[i * src_step], + ((mul * (ref[i * ref_step] + + ref[(i + 1) * ref_step]) + + add) >> shift), + inverse); + + if (mirror_right) + dst[w * dst_step] = LIFT(src[w * src_step], + ((mul * 2 * ref[w * ref_step] + add) >> shift), + inverse); +} + +static av_always_inline void liftS(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, + int dst_step, int src_step, int ref_step, + int width, int mul, int add, int shift, + int highpass, int inverse) +{ + const int mirror_left = !highpass; + const int mirror_right = (width & 1) ^ highpass; + const int w = (width >> 1) - 1 + (highpass & width); + int i; + + av_assert1(shift == 4); +#define LIFTS(src, ref, inv) \ + ((inv) ? (src) + (((ref) + 4 * (src)) >> shift) \ + : -((-16 * (src) + (ref) + add / \ + 4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23))) + if (mirror_left) { + dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse); + dst += dst_step; + src += src_step; + } + + for (i = 0; i < w; i++) + dst[i * dst_step] = LIFTS(src[i * src_step], + mul * (ref[i * ref_step] + + ref[(i + 1) * ref_step]) + add, + inverse); + + if (mirror_right) + dst[w * dst_step] = LIFTS(src[w * src_step], + mul * 2 * ref[w * ref_step] + add, + inverse); +} + +static void horizontal_decompose53i(DWTELEM *b, DWTELEM *temp, int width) +{ + const int width2 = width >> 1; + int x; + const int w2 = (width + 1) >> 1; + + for (x = 0; x < width2; x++) { + temp[x] = b[2 * x]; + temp[x + w2] = b[2 * x + 1]; + } + if (width & 1) + temp[x] = b[2 * x]; + lift(b + w2, temp + w2, temp, 1, 1, 1, width, -1, 0, 1, 1, 0); + lift(b, temp, b + w2, 1, 1, 1, width, 1, 2, 2, 0, 0); +} + +static void vertical_decompose53iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] -= (b0[i] + b2[i]) >> 1; +} + +static void vertical_decompose53iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] += (b0[i] + b2[i] + 2) >> 2; +} + +static void spatial_decompose53i(DWTELEM *buffer, DWTELEM *temp, + int width, int height, int stride) +{ + int y; + DWTELEM *b0 = buffer + mirror(-2 - 1, height - 1) * stride; + DWTELEM *b1 = buffer + mirror(-2, height - 1) * stride; + + for (y = -2; y < height; y += 2) { + DWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride; + DWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride; + + if (y + 1 < (unsigned)height) + horizontal_decompose53i(b2, temp, width); + if (y + 2 < (unsigned)height) + horizontal_decompose53i(b3, temp, width); + + if (y + 1 < (unsigned)height) + vertical_decompose53iH0(b1, b2, b3, width); + if (y + 0 < (unsigned)height) + vertical_decompose53iL0(b0, b1, b2, width); + + b0 = b2; + b1 = b3; + } +} + +static void horizontal_decompose97i(DWTELEM *b, DWTELEM *temp, int width) +{ + const int w2 = (width + 1) >> 1; + + lift(temp + w2, b + 1, b, 1, 2, 2, width, W_AM, W_AO, W_AS, 1, 1); + liftS(temp, b, temp + w2, 1, 2, 1, width, W_BM, W_BO, W_BS, 0, 0); + lift(b + w2, temp + w2, temp, 1, 1, 1, width, W_CM, W_CO, W_CS, 1, 0); + lift(b, temp, b + w2, 1, 1, 1, width, W_DM, W_DO, W_DS, 0, 0); +} + +static void vertical_decompose97iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] -= (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS; +} + +static void vertical_decompose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] += (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS; +} + +static void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] = (16 * 4 * b1[i] - 4 * (b0[i] + b2[i]) + W_BO * 5 + (5 << 27)) / + (5 * 16) - (1 << 23); +} + +static void vertical_decompose97iL1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] += (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS; +} + +static void spatial_decompose97i(DWTELEM *buffer, DWTELEM *temp, + int width, int height, int stride) +{ + int y; + DWTELEM *b0 = buffer + mirror(-4 - 1, height - 1) * stride; + DWTELEM *b1 = buffer + mirror(-4, height - 1) * stride; + DWTELEM *b2 = buffer + mirror(-4 + 1, height - 1) * stride; + DWTELEM *b3 = buffer + mirror(-4 + 2, height - 1) * stride; + + for (y = -4; y < height; y += 2) { + DWTELEM *b4 = buffer + mirror(y + 3, height - 1) * stride; + DWTELEM *b5 = buffer + mirror(y + 4, height - 1) * stride; + + if (y + 3 < (unsigned)height) + horizontal_decompose97i(b4, temp, width); + if (y + 4 < (unsigned)height) + horizontal_decompose97i(b5, temp, width); + + if (y + 3 < (unsigned)height) + vertical_decompose97iH0(b3, b4, b5, width); + if (y + 2 < (unsigned)height) + vertical_decompose97iL0(b2, b3, b4, width); + if (y + 1 < (unsigned)height) + vertical_decompose97iH1(b1, b2, b3, width); + if (y + 0 < (unsigned)height) + vertical_decompose97iL1(b0, b1, b2, width); + + b0 = b2; + b1 = b3; + b2 = b4; + b3 = b5; + } +} + +void ff_spatial_dwt(DWTELEM *buffer, DWTELEM *temp, int width, int height, + int stride, int type, int decomposition_count) +{ + int level; + + for (level = 0; level < decomposition_count; level++) { + switch (type) { + case DWT_97: + spatial_decompose97i(buffer, temp, + width >> level, height >> level, + stride << level); + break; + case DWT_53: + spatial_decompose53i(buffer, temp, + width >> level, height >> level, + stride << level); + break; + } + } +} + +static void horizontal_compose53i(IDWTELEM *b, IDWTELEM *temp, int width) +{ + const int width2 = width >> 1; + const int w2 = (width + 1) >> 1; + int x; + + for (x = 0; x < width2; x++) { + temp[2 * x] = b[x]; + temp[2 * x + 1] = b[x + w2]; + } + if (width & 1) + temp[2 * x] = b[x]; + + b[0] = temp[0] - ((temp[1] + 1) >> 1); + for (x = 2; x < width - 1; x += 2) { + b[x] = temp[x] - ((temp[x - 1] + temp[x + 1] + 2) >> 2); + b[x - 1] = temp[x - 1] + ((b[x - 2] + b[x] + 1) >> 1); + } + if (width & 1) { + b[x] = temp[x] - ((temp[x - 1] + 1) >> 1); + b[x - 1] = temp[x - 1] + ((b[x - 2] + b[x] + 1) >> 1); + } else + b[x - 1] = temp[x - 1] + b[x - 2]; +} + +static void vertical_compose53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] += (b0[i] + b2[i]) >> 1; +} + +static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] -= (b0[i] + b2[i] + 2) >> 2; +} + +static void spatial_compose53i_buffered_init(DWTCompose *cs, slice_buffer *sb, + int height, int stride_line) +{ + cs->b0 = slice_buffer_get_line(sb, + mirror(-1 - 1, height - 1) * stride_line); + cs->b1 = slice_buffer_get_line(sb, mirror(-1, height - 1) * stride_line); + cs->y = -1; +} + +static void spatial_compose53i_init(DWTCompose *cs, IDWTELEM *buffer, + int height, int stride) +{ + cs->b0 = buffer + mirror(-1 - 1, height - 1) * stride; + cs->b1 = buffer + mirror(-1, height - 1) * stride; + cs->y = -1; +} + +static void spatial_compose53i_dy_buffered(DWTCompose *cs, slice_buffer *sb, + IDWTELEM *temp, + int width, int height, + int stride_line) +{ + int y = cs->y; + + IDWTELEM *b0 = cs->b0; + IDWTELEM *b1 = cs->b1; + IDWTELEM *b2 = slice_buffer_get_line(sb, + mirror(y + 1, height - 1) * + stride_line); + IDWTELEM *b3 = slice_buffer_get_line(sb, + mirror(y + 2, height - 1) * + stride_line); + + if (y + 1 < (unsigned)height && y < (unsigned)height) { + int x; + + for (x = 0; x < width; x++) { + b2[x] -= (b1[x] + b3[x] + 2) >> 2; + b1[x] += (b0[x] + b2[x]) >> 1; + } + } else { + if (y + 1 < (unsigned)height) + vertical_compose53iL0(b1, b2, b3, width); + if (y + 0 < (unsigned)height) + vertical_compose53iH0(b0, b1, b2, width); + } + + if (y - 1 < (unsigned)height) + horizontal_compose53i(b0, temp, width); + if (y + 0 < (unsigned)height) + horizontal_compose53i(b1, temp, width); + + cs->b0 = b2; + cs->b1 = b3; + cs->y += 2; +} + +static void spatial_compose53i_dy(DWTCompose *cs, IDWTELEM *buffer, + IDWTELEM *temp, int width, int height, + int stride) +{ + int y = cs->y; + IDWTELEM *b0 = cs->b0; + IDWTELEM *b1 = cs->b1; + IDWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride; + IDWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride; + + if (y + 1 < (unsigned)height) + vertical_compose53iL0(b1, b2, b3, width); + if (y + 0 < (unsigned)height) + vertical_compose53iH0(b0, b1, b2, width); + + if (y - 1 < (unsigned)height) + horizontal_compose53i(b0, temp, width); + if (y + 0 < (unsigned)height) + horizontal_compose53i(b1, temp, width); + + cs->b0 = b2; + cs->b1 = b3; + cs->y += 2; +} + +void ff_snow_horizontal_compose97i(IDWTELEM *b, IDWTELEM *temp, int width) +{ + const int w2 = (width + 1) >> 1; + int x; + + temp[0] = b[0] - ((3 * b[w2] + 2) >> 2); + for (x = 1; x < (width >> 1); x++) { + temp[2 * x] = b[x] - ((3 * (b[x + w2 - 1] + b[x + w2]) + 4) >> 3); + temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x]; + } + if (width & 1) { + temp[2 * x] = b[x] - ((3 * b[x + w2 - 1] + 2) >> 2); + temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x]; + } else + temp[2 * x - 1] = b[x + w2 - 1] - 2 * temp[2 * x - 2]; + + b[0] = temp[0] + ((2 * temp[0] + temp[1] + 4) >> 3); + for (x = 2; x < width - 1; x += 2) { + b[x] = temp[x] + ((4 * temp[x] + temp[x - 1] + temp[x + 1] + 8) >> 4); + b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1); + } + if (width & 1) { + b[x] = temp[x] + ((2 * temp[x] + temp[x - 1] + 4) >> 3); + b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1); + } else + b[x - 1] = temp[x - 1] + 3 * b[x - 2]; +} + +static void vertical_compose97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS; +} + +static void vertical_compose97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] -= (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS; +} + +static void vertical_compose97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] += (W_BM * (b0[i] + b2[i]) + 4 * b1[i] + W_BO) >> W_BS; +} + +static void vertical_compose97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + int width) +{ + int i; + + for (i = 0; i < width; i++) + b1[i] -= (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS; +} + +void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, + int width) +{ + int i; + + for (i = 0; i < width; i++) { + b4[i] -= (W_DM * (b3[i] + b5[i]) + W_DO) >> W_DS; + b3[i] -= (W_CM * (b2[i] + b4[i]) + W_CO) >> W_CS; + b2[i] += (W_BM * (b1[i] + b3[i]) + 4 * b2[i] + W_BO) >> W_BS; + b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS; + } +} + +static void spatial_compose97i_buffered_init(DWTCompose *cs, slice_buffer *sb, + int height, int stride_line) +{ + cs->b0 = slice_buffer_get_line(sb, mirror(-3 - 1, height - 1) * stride_line); + cs->b1 = slice_buffer_get_line(sb, mirror(-3, height - 1) * stride_line); + cs->b2 = slice_buffer_get_line(sb, mirror(-3 + 1, height - 1) * stride_line); + cs->b3 = slice_buffer_get_line(sb, mirror(-3 + 2, height - 1) * stride_line); + cs->y = -3; +} + +static void spatial_compose97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, + int stride) +{ + cs->b0 = buffer + mirror(-3 - 1, height - 1) * stride; + cs->b1 = buffer + mirror(-3, height - 1) * stride; + cs->b2 = buffer + mirror(-3 + 1, height - 1) * stride; + cs->b3 = buffer + mirror(-3 + 2, height - 1) * stride; + cs->y = -3; +} + +static void spatial_compose97i_dy_buffered(SnowDWTContext *dsp, DWTCompose *cs, + slice_buffer * sb, IDWTELEM *temp, + int width, int height, + int stride_line) +{ + int y = cs->y; + + IDWTELEM *b0 = cs->b0; + IDWTELEM *b1 = cs->b1; + IDWTELEM *b2 = cs->b2; + IDWTELEM *b3 = cs->b3; + IDWTELEM *b4 = slice_buffer_get_line(sb, + mirror(y + 3, height - 1) * + stride_line); + IDWTELEM *b5 = slice_buffer_get_line(sb, + mirror(y + 4, height - 1) * + stride_line); + + if (y > 0 && y + 4 < height) { + dsp->vertical_compose97i(b0, b1, b2, b3, b4, b5, width); + } else { + if (y + 3 < (unsigned)height) + vertical_compose97iL1(b3, b4, b5, width); + if (y + 2 < (unsigned)height) + vertical_compose97iH1(b2, b3, b4, width); + if (y + 1 < (unsigned)height) + vertical_compose97iL0(b1, b2, b3, width); + if (y + 0 < (unsigned)height) + vertical_compose97iH0(b0, b1, b2, width); + } + + if (y - 1 < (unsigned)height) + dsp->horizontal_compose97i(b0, temp, width); + if (y + 0 < (unsigned)height) + dsp->horizontal_compose97i(b1, temp, width); + + cs->b0 = b2; + cs->b1 = b3; + cs->b2 = b4; + cs->b3 = b5; + cs->y += 2; +} + +static void spatial_compose97i_dy(DWTCompose *cs, IDWTELEM *buffer, + IDWTELEM *temp, int width, int height, + int stride) +{ + int y = cs->y; + IDWTELEM *b0 = cs->b0; + IDWTELEM *b1 = cs->b1; + IDWTELEM *b2 = cs->b2; + IDWTELEM *b3 = cs->b3; + IDWTELEM *b4 = buffer + mirror(y + 3, height - 1) * stride; + IDWTELEM *b5 = buffer + mirror(y + 4, height - 1) * stride; + + if (y + 3 < (unsigned)height) + vertical_compose97iL1(b3, b4, b5, width); + if (y + 2 < (unsigned)height) + vertical_compose97iH1(b2, b3, b4, width); + if (y + 1 < (unsigned)height) + vertical_compose97iL0(b1, b2, b3, width); + if (y + 0 < (unsigned)height) + vertical_compose97iH0(b0, b1, b2, width); + + if (y - 1 < (unsigned)height) + ff_snow_horizontal_compose97i(b0, temp, width); + if (y + 0 < (unsigned)height) + ff_snow_horizontal_compose97i(b1, temp, width); + + cs->b0 = b2; + cs->b1 = b3; + cs->b2 = b4; + cs->b3 = b5; + cs->y += 2; +} + +void ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer *sb, int width, + int height, int stride_line, int type, + int decomposition_count) +{ + int level; + for (level = decomposition_count - 1; level >= 0; level--) { + switch (type) { + case DWT_97: + spatial_compose97i_buffered_init(cs + level, sb, height >> level, + stride_line << level); + break; + case DWT_53: + spatial_compose53i_buffered_init(cs + level, sb, height >> level, + stride_line << level); + break; + } + } +} + +void ff_spatial_idwt_buffered_slice(SnowDWTContext *dsp, DWTCompose *cs, + slice_buffer *slice_buf, IDWTELEM *temp, + int width, int height, int stride_line, + int type, int decomposition_count, int y) +{ + const int support = type == 1 ? 3 : 5; + int level; + if (type == 2) + return; + + for (level = decomposition_count - 1; level >= 0; level--) + while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) { + switch (type) { + case DWT_97: + spatial_compose97i_dy_buffered(dsp, cs + level, slice_buf, temp, + width >> level, + height >> level, + stride_line << level); + break; + case DWT_53: + spatial_compose53i_dy_buffered(cs + level, slice_buf, temp, + width >> level, + height >> level, + stride_line << level); + break; + } + } +} + +static void ff_spatial_idwt_init(DWTCompose *cs, IDWTELEM *buffer, int width, + int height, int stride, int type, + int decomposition_count) +{ + int level; + for (level = decomposition_count - 1; level >= 0; level--) { + switch (type) { + case DWT_97: + spatial_compose97i_init(cs + level, buffer, height >> level, + stride << level); + break; + case DWT_53: + spatial_compose53i_init(cs + level, buffer, height >> level, + stride << level); + break; + } + } +} + +static void ff_spatial_idwt_slice(DWTCompose *cs, IDWTELEM *buffer, + IDWTELEM *temp, int width, int height, + int stride, int type, + int decomposition_count, int y) +{ + const int support = type == 1 ? 3 : 5; + int level; + if (type == 2) + return; + + for (level = decomposition_count - 1; level >= 0; level--) + while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) { + switch (type) { + case DWT_97: + spatial_compose97i_dy(cs + level, buffer, temp, width >> level, + height >> level, stride << level); + break; + case DWT_53: + spatial_compose53i_dy(cs + level, buffer, temp, width >> level, + height >> level, stride << level); + break; + } + } +} + +void ff_spatial_idwt(IDWTELEM *buffer, IDWTELEM *temp, int width, int height, + int stride, int type, int decomposition_count) +{ + DWTCompose cs[MAX_DECOMPOSITIONS]; + int y; + ff_spatial_idwt_init(cs, buffer, width, height, stride, type, + decomposition_count); + for (y = 0; y < height; y += 4) + ff_spatial_idwt_slice(cs, buffer, temp, width, height, stride, type, + decomposition_count, y); +} + +static inline int w_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, + int w, int h, int type) +{ + int s, i, j; + const int dec_count = w == 8 ? 3 : 4; + int tmp[32 * 32], tmp2[32]; + int level, ori; + static const int scale[2][2][4][4] = { + { + { // 9/7 8x8 dec=3 + { 268, 239, 239, 213 }, + { 0, 224, 224, 152 }, + { 0, 135, 135, 110 }, + }, + { // 9/7 16x16 or 32x32 dec=4 + { 344, 310, 310, 280 }, + { 0, 320, 320, 228 }, + { 0, 175, 175, 136 }, + { 0, 129, 129, 102 }, + } + }, + { + { // 5/3 8x8 dec=3 + { 275, 245, 245, 218 }, + { 0, 230, 230, 156 }, + { 0, 138, 138, 113 }, + }, + { // 5/3 16x16 or 32x32 dec=4 + { 352, 317, 317, 286 }, + { 0, 328, 328, 233 }, + { 0, 180, 180, 140 }, + { 0, 132, 132, 105 }, + } + } + }; + + for (i = 0; i < h; i++) { + for (j = 0; j < w; j += 4) { + tmp[32 * i + j + 0] = (pix1[j + 0] - pix2[j + 0]) << 4; + tmp[32 * i + j + 1] = (pix1[j + 1] - pix2[j + 1]) << 4; + tmp[32 * i + j + 2] = (pix1[j + 2] - pix2[j + 2]) << 4; + tmp[32 * i + j + 3] = (pix1[j + 3] - pix2[j + 3]) << 4; + } + pix1 += line_size; + pix2 += line_size; + } + + ff_spatial_dwt(tmp, tmp2, w, h, 32, type, dec_count); + + s = 0; + av_assert1(w == h); + for (level = 0; level < dec_count; level++) + for (ori = level ? 1 : 0; ori < 4; ori++) { + int size = w >> (dec_count - level); + int sx = (ori & 1) ? size : 0; + int stride = 32 << (dec_count - level); + int sy = (ori & 2) ? stride >> 1 : 0; + + for (i = 0; i < size; i++) + for (j = 0; j < size; j++) { + int v = tmp[sx + sy + i * stride + j] * + scale[type][dec_count - 3][level][ori]; + s += FFABS(v); + } + } + av_assert1(s >= 0); + return s >> 9; +} + +static int w53_8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + return w_c(v, pix1, pix2, line_size, 8, h, 1); +} + +static int w97_8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + return w_c(v, pix1, pix2, line_size, 8, h, 0); +} + +static int w53_16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + return w_c(v, pix1, pix2, line_size, 16, h, 1); +} + +static int w97_16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + return w_c(v, pix1, pix2, line_size, 16, h, 0); +} + +int ff_w53_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + return w_c(v, pix1, pix2, line_size, 32, h, 1); +} + +int ff_w97_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h) +{ + return w_c(v, pix1, pix2, line_size, 32, h, 0); +} + +void ff_dsputil_init_dwt(DSPContext *c) +{ + c->w53[0] = w53_16_c; + c->w53[1] = w53_8_c; + c->w97[0] = w97_16_c; + c->w97[1] = w97_8_c; +} + +void ff_dwt_init(SnowDWTContext *c) +{ + c->vertical_compose97i = ff_snow_vertical_compose97i; + c->horizontal_compose97i = ff_snow_horizontal_compose97i; + c->inner_add_yblock = ff_snow_inner_add_yblock; + + if (HAVE_MMX) + ff_dwt_init_x86(c); +} + + diff --git a/ffmpeg/libavcodec/snow_dwt.h b/ffmpeg/libavcodec/snow_dwt.h new file mode 100644 index 0000000..0806b38 --- /dev/null +++ b/ffmpeg/libavcodec/snow_dwt.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2004-2010 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 + */ + +#ifndef AVCODEC_SNOW_DWT_H +#define AVCODEC_SNOW_DWT_H + +#include + +typedef int DWTELEM; +typedef short IDWTELEM; + +#define MAX_DECOMPOSITIONS 8 + +typedef struct DWTCompose { + IDWTELEM *b0; + IDWTELEM *b1; + IDWTELEM *b2; + IDWTELEM *b3; + int y; +} DWTCompose; + +/** Used to minimize the amount of memory used in order to + * optimize cache performance. **/ +typedef struct slice_buffer_s { + IDWTELEM **line; ///< For use by idwt and predict_slices. + IDWTELEM **data_stack; ///< Used for internal purposes. + int data_stack_top; + int line_count; + int line_width; + int data_count; + IDWTELEM *base_buffer; ///< Buffer that this structure is caching. +} slice_buffer; + +struct SnowDWTContext; + +typedef struct SnowDWTContext { + void (*vertical_compose97i)(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, + int width); + void (*horizontal_compose97i)(IDWTELEM *b, IDWTELEM *temp, int width); + void (*inner_add_yblock)(const uint8_t *obmc, const int obmc_stride, + uint8_t **block, int b_w, int b_h, int src_x, + int src_y, int src_stride, slice_buffer *sb, + int add, uint8_t *dst8); +} SnowDWTContext; + + +#define DWT_97 0 +#define DWT_53 1 + +#define liftS lift +#define W_AM 3 +#define W_AO 0 +#define W_AS 1 + +#undef liftS +#define W_BM 1 +#define W_BO 8 +#define W_BS 4 + +#define W_CM 1 +#define W_CO 0 +#define W_CS 0 + +#define W_DM 3 +#define W_DO 4 +#define W_DS 3 + +#define slice_buffer_get_line(slice_buf, line_num) \ + ((slice_buf)->line[line_num] ? (slice_buf)->line[line_num] \ + : ff_slice_buffer_load_line((slice_buf), \ + (line_num))) + +int ff_slice_buffer_init(slice_buffer *buf, int line_count, + int max_allocated_lines, int line_width, + IDWTELEM *base_buffer); +void ff_slice_buffer_release(slice_buffer *buf, int line); +void ff_slice_buffer_flush(slice_buffer *buf); +void ff_slice_buffer_destroy(slice_buffer *buf); +IDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line); + +void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, + IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, + int width); +void ff_snow_horizontal_compose97i(IDWTELEM *b, IDWTELEM *temp, int width); +void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, + uint8_t **block, int b_w, int b_h, int src_x, + int src_y, int src_stride, slice_buffer *sb, + int add, uint8_t *dst8); + +int ff_w53_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); +int ff_w97_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h); + +void ff_spatial_dwt(int *buffer, int *temp, int width, int height, int stride, + int type, int decomposition_count); + +void ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer *sb, int width, + int height, int stride_line, int type, + int decomposition_count); +void ff_spatial_idwt_buffered_slice(SnowDWTContext *dsp, DWTCompose *cs, + slice_buffer *slice_buf, IDWTELEM *temp, + int width, int height, int stride_line, + int type, int decomposition_count, int y); +void ff_spatial_idwt(IDWTELEM *buffer, IDWTELEM *temp, int width, int height, + int stride, int type, int decomposition_count); + +void ff_dwt_init(SnowDWTContext *c); +void ff_dwt_init_x86(SnowDWTContext *c); + +#endif /* AVCODEC_DWT_H */ diff --git a/ffmpeg/libavcodec/snowdata.h b/ffmpeg/libavcodec/snowdata.h new file mode 100644 index 0000000..490fdf8 --- /dev/null +++ b/ffmpeg/libavcodec/snowdata.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2004 Michael Niedermayer + * Copyright (C) 2006 Robert Edele + * + * 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 + */ + +#ifndef AVCODEC_SNOWDATA_H +#define AVCODEC_SNOWDATA_H + +#include "snow.h" + +static const uint8_t obmc32[1024]={ + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, + 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0, + 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0, + 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0, + 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4, + 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4, + 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4, + 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4, + 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4, + 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4, + 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4, + 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4, + 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8, + 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8, + 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8, + 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8, + 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8, + 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8, + 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8, + 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8, + 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4, + 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4, + 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4, + 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4, + 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4, + 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4, + 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4, + 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4, + 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0, + 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0, + 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0, + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, + //error:0.000020 +}; +static const uint8_t obmc16[256]={ + 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0, + 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4, + 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4, + 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8, + 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8, + 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12, + 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12, + 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16, + 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16, + 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12, + 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12, + 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8, + 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8, + 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4, + 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4, + 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0, +//error:0.000015 +}; + +//linear *64 +static const uint8_t obmc8[64]={ + 4, 12, 20, 28, 28, 20, 12, 4, + 12, 36, 60, 84, 84, 60, 36, 12, + 20, 60,100,140,140,100, 60, 20, + 28, 84,140,196,196,140, 84, 28, + 28, 84,140,196,196,140, 84, 28, + 20, 60,100,140,140,100, 60, 20, + 12, 36, 60, 84, 84, 60, 36, 12, + 4, 12, 20, 28, 28, 20, 12, 4, +//error:0.000000 +}; + +//linear *64 +static const uint8_t obmc4[16]={ + 16, 48, 48, 16, + 48,144,144, 48, + 48,144,144, 48, + 16, 48, 48, 16, +//error:0.000000 +}; + +const int8_t ff_quant3bA[256]={ + 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, +}; + +const uint8_t * const ff_obmc_tab[4]= { + obmc32, obmc16, obmc8, obmc4 +}; + +/* runtime generated tables */ +uint8_t ff_qexp[QROOT]; +int ff_scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES]; + + +#endif /* AVCODEC_SNOW_H */ diff --git a/ffmpeg/libavcodec/snowdec.c b/ffmpeg/libavcodec/snowdec.c new file mode 100644 index 0000000..c8a0327 --- /dev/null +++ b/ffmpeg/libavcodec/snowdec.c @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2004 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 "libavutil/intmath.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "dsputil.h" +#include "snow_dwt.h" +#include "internal.h" +#include "snow.h" + +#include "rangecoder.h" +#include "mathops.h" + +#include "mpegvideo.h" +#include "h263.h" + +#undef NDEBUG +#include + +static av_always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){ + Plane *p= &s->plane[plane_index]; + const int mb_w= s->b_width << s->block_max_depth; + const int mb_h= s->b_height << s->block_max_depth; + int x, y, mb_x; + int block_size = MB_SIZE >> s->block_max_depth; + int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; + int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth]; + int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; + int ref_stride= s->current_picture.linesize[plane_index]; + uint8_t *dst8= s->current_picture.data[plane_index]; + int w= p->width; + int h= p->height; + + if(s->keyframe || (s->avctx->debug&512)){ + if(mb_y==mb_h) + return; + + if(add){ + for(y=block_h*mb_y; yline[y]; + for(x=0; x>= FRAC_BITS; + if(v&(~255)) v= ~(v>>31); + dst8[x + y*ref_stride]= v; + } + } + }else{ + for(y=block_h*mb_y; yline[y]; + for(x=0; xwidth; + int y; + const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); + int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); + int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; + int new_index = 0; + + if(b->ibuf == s->spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){ + qadd= 0; + qmul= 1<stride_line + b->buf_y_offset) + b->buf_x_offset; + memset(line, 0, b->width*sizeof(IDWTELEM)); + v = b->x_coeff[new_index].coeff; + x = b->x_coeff[new_index++].x; + while(x < w){ + register int t= ( (v>>1)*qmul + qadd)>>QEXPSHIFT; + register int u= -(v&1); + line[x] = (t^u) - u; + + v = b->x_coeff[new_index].coeff; + x = b->x_coeff[new_index++].x; + } + } + + /* Save our variables for the next slice. */ + save_state[0] = new_index; + + return; +} + +static int decode_q_branch(SnowContext *s, int level, int x, int y){ + const int w= s->b_width << s->block_max_depth; + const int rem_depth= s->block_max_depth - level; + const int index= (x + y*w) << rem_depth; + int trx= (x+1)<block[index-1] : &null_block; + const BlockNode *top = y ? &s->block[index-w] : &null_block; + const BlockNode *tl = y && x ? &s->block[index-w-1] : left; + const BlockNode *tr = y && trxblock[index-w+(1<level + 2*top->level + tl->level + tr->level; + int res; + + if(s->keyframe){ + set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA); + return 0; + } + + if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){ + int type, mx, my; + int l = left->color[0]; + int cb= left->color[1]; + int cr= left->color[2]; + int ref = 0; + int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref); + int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 0*av_log2(2*FFABS(tr->mx - top->mx)); + int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my)); + + type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0; + + if(type){ + pred_mv(s, &mx, &my, 0, left, top, tr); + l += get_symbol(&s->c, &s->block_state[32], 1); + cb+= get_symbol(&s->c, &s->block_state[64], 1); + cr+= get_symbol(&s->c, &s->block_state[96], 1); + }else{ + if(s->ref_frames > 1) + ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0); + if (ref >= s->ref_frames) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid ref\n"); + return AVERROR_INVALIDDATA; + } + pred_mv(s, &mx, &my, ref, left, top, tr); + mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1); + my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1); + } + set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type); + }else{ + if ((res = decode_q_branch(s, level+1, 2*x+0, 2*y+0)) < 0 || + (res = decode_q_branch(s, level+1, 2*x+1, 2*y+0)) < 0 || + (res = decode_q_branch(s, level+1, 2*x+0, 2*y+1)) < 0 || + (res = decode_q_branch(s, level+1, 2*x+1, 2*y+1)) < 0) + return res; + } + return 0; +} + +static void dequantize_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int start_y, int end_y){ + const int w= b->width; + const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); + const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); + const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; + int x,y; + + if(s->qlog == LOSSLESS_QLOG) return; + + for(y=start_y; ystride_line) + b->buf_y_offset) + b->buf_x_offset; + for(x=0; x>(QEXPSHIFT)); //FIXME try different bias + }else if(i>0){ + line[x]= (( i*qmul + qadd)>>(QEXPSHIFT)); + } + } + } +} + +static void correlate_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median, int start_y, int end_y){ + const int w= b->width; + int x,y; + + IDWTELEM * line=0; // silence silly "could be used without having been initialized" warning + IDWTELEM * prev; + + if (start_y != 0) + line = slice_buffer_get_line(sb, ((start_y - 1) * b->stride_line) + b->buf_y_offset) + b->buf_x_offset; + + for(y=start_y; ystride_line) + b->buf_y_offset) + b->buf_x_offset; + for(x=0; xspatial_decomposition_count; level++){ + for(orientation=level ? 1:0; orientation<4; orientation++){ + int q; + if (plane_index==2) q= s->plane[1].band[level][orientation].qlog; + else if(orientation==2) q= s->plane[plane_index].band[level][1].qlog; + else q= get_symbol(&s->c, s->header_state, 1); + s->plane[plane_index].band[level][orientation].qlog= q; + } + } + } +} + +#define GET_S(dst, check) \ + tmp= get_symbol(&s->c, s->header_state, 0);\ + if(!(check)){\ + av_log(s->avctx, AV_LOG_ERROR, "Error " #dst " is %d\n", tmp);\ + return -1;\ + }\ + dst= tmp; + +static int decode_header(SnowContext *s){ + int plane_index, tmp; + uint8_t kstate[32]; + + memset(kstate, MID_STATE, sizeof(kstate)); + + s->keyframe= get_rac(&s->c, kstate); + if(s->keyframe || s->always_reset){ + ff_snow_reset_contexts(s); + s->spatial_decomposition_type= + s->qlog= + s->qbias= + s->mv_scale= + s->block_max_depth= 0; + } + if(s->keyframe){ + GET_S(s->version, tmp <= 0U) + s->always_reset= get_rac(&s->c, s->header_state); + s->temporal_decomposition_type= get_symbol(&s->c, s->header_state, 0); + s->temporal_decomposition_count= get_symbol(&s->c, s->header_state, 0); + GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS) + s->colorspace_type= get_symbol(&s->c, s->header_state, 0); + s->chroma_h_shift= get_symbol(&s->c, s->header_state, 0); + s->chroma_v_shift= get_symbol(&s->c, s->header_state, 0); + + if(s->chroma_h_shift == 1 && s->chroma_v_shift==1){ + s->avctx->pix_fmt= AV_PIX_FMT_YUV420P; + }else if(s->chroma_h_shift == 0 && s->chroma_v_shift==0){ + s->avctx->pix_fmt= AV_PIX_FMT_YUV444P; + }else if(s->chroma_h_shift == 2 && s->chroma_v_shift==2){ + s->avctx->pix_fmt= AV_PIX_FMT_YUV410P; + } else { + av_log(s, AV_LOG_ERROR, "unsupported color subsample mode %d %d\n", s->chroma_h_shift, s->chroma_v_shift); + s->chroma_h_shift = s->chroma_v_shift = 1; + s->avctx->pix_fmt= AV_PIX_FMT_YUV420P; + return AVERROR_INVALIDDATA; + } + + s->spatial_scalability= get_rac(&s->c, s->header_state); +// s->rate_scalability= get_rac(&s->c, s->header_state); + GET_S(s->max_ref_frames, tmp < (unsigned)MAX_REF_FRAMES) + s->max_ref_frames++; + + decode_qlogs(s); + } + + if(!s->keyframe){ + if(get_rac(&s->c, s->header_state)){ + for(plane_index=0; plane_index<2; plane_index++){ + int htaps, i, sum=0; + Plane *p= &s->plane[plane_index]; + p->diag_mc= get_rac(&s->c, s->header_state); + htaps= get_symbol(&s->c, s->header_state, 0)*2 + 2; + if((unsigned)htaps > HTAPS_MAX || htaps==0) + return -1; + p->htaps= htaps; + for(i= htaps/2; i; i--){ + p->hcoeff[i]= get_symbol(&s->c, s->header_state, 0) * (1-2*(i&1)); + sum += p->hcoeff[i]; + } + p->hcoeff[0]= 32-sum; + } + s->plane[2].diag_mc= s->plane[1].diag_mc; + s->plane[2].htaps = s->plane[1].htaps; + memcpy(s->plane[2].hcoeff, s->plane[1].hcoeff, sizeof(s->plane[1].hcoeff)); + } + if(get_rac(&s->c, s->header_state)){ + GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS) + decode_qlogs(s); + } + } + + s->spatial_decomposition_type+= get_symbol(&s->c, s->header_state, 1); + if(s->spatial_decomposition_type > 1U){ + av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_type %d not supported\n", s->spatial_decomposition_type); + return -1; + } + if(FFMIN(s->avctx-> width>>s->chroma_h_shift, + s->avctx->height>>s->chroma_v_shift) >> (s->spatial_decomposition_count-1) <= 1){ + av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_count %d too large for size\n", s->spatial_decomposition_count); + return -1; + } + + + s->qlog += get_symbol(&s->c, s->header_state, 1); + s->mv_scale += get_symbol(&s->c, s->header_state, 1); + s->qbias += get_symbol(&s->c, s->header_state, 1); + s->block_max_depth+= get_symbol(&s->c, s->header_state, 1); + if(s->block_max_depth > 1 || s->block_max_depth < 0){ + av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth); + s->block_max_depth= 0; + return -1; + } + + return 0; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + int ret; + + if ((ret = ff_snow_common_init(avctx)) < 0) { + ff_snow_common_end(avctx->priv_data); + return ret; + } + + return 0; +} + +static int decode_blocks(SnowContext *s){ + int x, y; + int w= s->b_width; + int h= s->b_height; + int res; + + for(y=0; ydata; + int buf_size = avpkt->size; + SnowContext *s = avctx->priv_data; + RangeCoder * const c= &s->c; + int bytes_read; + AVFrame *picture = data; + int level, orientation, plane_index; + int res; + + ff_init_range_decoder(c, buf, buf_size); + ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); + + s->current_picture.pict_type= AV_PICTURE_TYPE_I; //FIXME I vs. P + if(decode_header(s)<0) + return -1; + if ((res=ff_snow_common_init_after_header(avctx)) < 0) + return res; + + // realloc slice buffer for the case that spatial_decomposition_count changed + ff_slice_buffer_destroy(&s->sb); + if ((res = ff_slice_buffer_init(&s->sb, s->plane[0].height, + (MB_SIZE >> s->block_max_depth) + + s->spatial_decomposition_count * 11 + 1, + s->plane[0].width, + s->spatial_idwt_buffer)) < 0) + return res; + + for(plane_index=0; plane_index<3; plane_index++){ + Plane *p= &s->plane[plane_index]; + p->fast_mc= p->diag_mc && p->htaps==6 && p->hcoeff[0]==40 + && p->hcoeff[1]==-10 + && p->hcoeff[2]==2; + } + + ff_snow_alloc_blocks(s); + + if(ff_snow_frame_start(s) < 0) + return -1; + //keyframe flag duplication mess FIXME + if(avctx->debug&FF_DEBUG_PICT_INFO) + av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog); + + if ((res = decode_blocks(s)) < 0) + return res; + + for(plane_index=0; plane_index<3; plane_index++){ + Plane *p= &s->plane[plane_index]; + int w= p->width; + int h= p->height; + int x, y; + int decode_state[MAX_DECOMPOSITIONS][4][1]; /* Stored state info for unpack_coeffs. 1 variable per instance. */ + + if(s->avctx->debug&2048){ + memset(s->spatial_dwt_buffer, 0, sizeof(DWTELEM)*w*h); + predict_plane(s, s->spatial_idwt_buffer, plane_index, 1); + + for(y=0; ycurrent_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x]; + s->mconly_picture.data[plane_index][y*s->mconly_picture.linesize[plane_index] + x]= v; + } + } + } + + { + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + unpack_coeffs(s, b, b->parent, orientation); + } + } + } + + { + const int mb_h= s->b_height << s->block_max_depth; + const int block_size = MB_SIZE >> s->block_max_depth; + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; + int mb_y; + DWTCompose cs[MAX_DECOMPOSITIONS]; + int yd=0, yq=0; + int y; + int end_y; + + ff_spatial_idwt_buffered_init(cs, &s->sb, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count); + for(mb_y=0; mb_y<=mb_h; mb_y++){ + + int slice_starty = block_h*mb_y; + int slice_h = block_h*(mb_y+1); + + if (!(s->keyframe || s->avctx->debug&512)){ + slice_starty = FFMAX(0, slice_starty - (block_h >> 1)); + slice_h -= (block_h >> 1); + } + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + int start_y; + int end_y; + int our_mb_start = mb_y; + int our_mb_end = (mb_y + 1); + const int extra= 3; + start_y = (mb_y ? ((block_h * our_mb_start) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra: 0); + end_y = (((block_h * our_mb_end) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra); + if (!(s->keyframe || s->avctx->debug&512)){ + start_y = FFMAX(0, start_y - (block_h >> (1+s->spatial_decomposition_count - level))); + end_y = FFMAX(0, end_y - (block_h >> (1+s->spatial_decomposition_count - level))); + } + start_y = FFMIN(b->height, start_y); + end_y = FFMIN(b->height, end_y); + + if (start_y != end_y){ + if (orientation == 0){ + SubBand * correlate_band = &p->band[0][0]; + int correlate_end_y = FFMIN(b->height, end_y + 1); + int correlate_start_y = FFMIN(b->height, (start_y ? start_y + 1 : 0)); + decode_subband_slice_buffered(s, correlate_band, &s->sb, correlate_start_y, correlate_end_y, decode_state[0][0]); + correlate_slice_buffered(s, &s->sb, correlate_band, correlate_band->ibuf, correlate_band->stride, 1, 0, correlate_start_y, correlate_end_y); + dequantize_slice_buffered(s, &s->sb, correlate_band, correlate_band->ibuf, correlate_band->stride, start_y, end_y); + } + else + decode_subband_slice_buffered(s, b, &s->sb, start_y, end_y, decode_state[level][orientation]); + } + } + } + + for(; yddwt, cs, &s->sb, s->temp_idwt_buffer, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count, yd); + } + + if(s->qlog == LOSSLESS_QLOG){ + for(; yqsb, yq); + for(x=0; xsb, s->spatial_idwt_buffer, plane_index, 1, mb_y); + + y = FFMIN(p->height, slice_starty); + end_y = FFMIN(p->height, slice_h); + while(y < end_y) + ff_slice_buffer_release(&s->sb, y++); + } + + ff_slice_buffer_flush(&s->sb); + } + + } + + emms_c(); + + ff_snow_release_buffer(avctx); + + if(!(s->avctx->debug&2048)) + av_frame_ref(picture, &s->current_picture); + else + av_frame_ref(picture, &s->mconly_picture); + + *got_frame = 1; + + bytes_read= c->bytestream - c->bytestream_start; + if(bytes_read ==0) av_log(s->avctx, AV_LOG_ERROR, "error at end of frame\n"); //FIXME + + return bytes_read; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + SnowContext *s = avctx->priv_data; + + ff_slice_buffer_destroy(&s->sb); + + ff_snow_common_end(s); + + return 0; +} + +AVCodec ff_snow_decoder = { + .name = "snow", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SNOW, + .priv_data_size = sizeof(SnowContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/, + .long_name = NULL_IF_CONFIG_SMALL("Snow"), +}; diff --git a/ffmpeg/libavcodec/snowenc.c b/ffmpeg/libavcodec/snowenc.c new file mode 100644 index 0000000..7266ee1 --- /dev/null +++ b/ffmpeg/libavcodec/snowenc.c @@ -0,0 +1,2112 @@ +/* + * Copyright (C) 2004 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 "libavutil/intmath.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "avcodec.h" +#include "internal.h" +#include "dsputil.h" +#include "internal.h" +#include "snow_dwt.h" +#include "snow.h" + +#include "rangecoder.h" +#include "mathops.h" + +#include "mpegvideo.h" +#include "h263.h" + +#undef NDEBUG +#include + +#define QUANTIZE2 0 + +#if QUANTIZE2==1 +#define Q2_STEP 8 + +static void find_sse(SnowContext *s, Plane *p, int *score, int score_stride, IDWTELEM *r0, IDWTELEM *r1, int level, int orientation){ + SubBand *b= &p->band[level][orientation]; + int x, y; + int xo=0; + int yo=0; + int step= 1 << (s->spatial_decomposition_count - level); + + if(orientation&1) + xo= step>>1; + if(orientation&2) + yo= step>>1; + + //FIXME bias for nonzero ? + //FIXME optimize + memset(score, 0, sizeof(*score)*score_stride*((p->height + Q2_STEP-1)/Q2_STEP)); + for(y=0; yheight; y++){ + for(x=0; xwidth; x++){ + int sx= (x-xo + step/2) / step / Q2_STEP; + int sy= (y-yo + step/2) / step / Q2_STEP; + int v= r0[x + y*p->width] - r1[x + y*p->width]; + assert(sx>=0 && sy>=0 && sx < score_stride); + v= ((v+8)>>4)<<4; + score[sx + sy*score_stride] += v*v; + assert(score[sx + sy*score_stride] >= 0); + } + } +} + +static void dequantize_all(SnowContext *s, Plane *p, IDWTELEM *buffer, int width, int height){ + int level, orientation; + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + IDWTELEM *dst= buffer + (b->ibuf - s->spatial_idwt_buffer); + + dequantize(s, b, dst, b->stride); + } + } +} + +static void dwt_quantize(SnowContext *s, Plane *p, DWTELEM *buffer, int width, int height, int stride, int type){ + int level, orientation, ys, xs, x, y, pass; + IDWTELEM best_dequant[height * stride]; + IDWTELEM idwt2_buffer[height * stride]; + const int score_stride= (width + 10)/Q2_STEP; + int best_score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size + int score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size + int threshold= (s->m.lambda * s->m.lambda) >> 6; + + //FIXME pass the copy cleanly ? + +// memcpy(dwt_buffer, buffer, height * stride * sizeof(DWTELEM)); + ff_spatial_dwt(buffer, s->temp_dwt_buffer, width, height, stride, type, s->spatial_decomposition_count); + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + IDWTELEM *dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer); + DWTELEM *src= buffer + (b-> buf - s->spatial_dwt_buffer); + assert(src == b->buf); // code does not depend on this but it is true currently + + quantize(s, b, dst, src, b->stride, s->qbias); + } + } + for(pass=0; pass<1; pass++){ + if(s->qbias == 0) //keyframe + continue; + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + IDWTELEM *dst= idwt2_buffer + (b->ibuf - s->spatial_idwt_buffer); + IDWTELEM *best_dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer); + + for(ys= 0; ystemp_idwt_buffer, width, height, stride, type, s->spatial_decomposition_count); + find_sse(s, p, best_score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation); + memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); + for(y=ys; yheight; y+= Q2_STEP){ + for(x=xs; xwidth; x+= Q2_STEP){ + if(dst[x + y*b->stride]<0) dst[x + y*b->stride]++; + if(dst[x + y*b->stride]>0) dst[x + y*b->stride]--; + //FIXME try more than just -- + } + } + dequantize_all(s, p, idwt2_buffer, width, height); + ff_spatial_idwt(idwt2_buffer, s->temp_idwt_buffer, width, height, stride, type, s->spatial_decomposition_count); + find_sse(s, p, score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation); + for(y=ys; yheight; y+= Q2_STEP){ + for(x=xs; xwidth; x+= Q2_STEP){ + int score_idx= x/Q2_STEP + (y/Q2_STEP)*score_stride; + if(score[score_idx] <= best_score[score_idx] + threshold){ + best_score[score_idx]= score[score_idx]; + if(best_dst[x + y*b->stride]<0) best_dst[x + y*b->stride]++; + if(best_dst[x + y*b->stride]>0) best_dst[x + y*b->stride]--; + //FIXME copy instead + } + } + } + } + } + } + } + } + memcpy(s->spatial_idwt_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); //FIXME work with that directly instead of copy at the end +} + +#endif /* QUANTIZE2==1 */ + +static av_cold int encode_init(AVCodecContext *avctx) +{ + SnowContext *s = avctx->priv_data; + int plane_index, ret; + + if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ + av_log(avctx, AV_LOG_ERROR, "This codec is under development, files encoded with it may not be decodable with future versions!!!\n" + "Use vstrict=-2 / -strict -2 to use it anyway.\n"); + return -1; + } + + if(avctx->prediction_method == DWT_97 + && (avctx->flags & CODEC_FLAG_QSCALE) + && avctx->global_quality == 0){ + av_log(avctx, AV_LOG_ERROR, "The 9/7 wavelet is incompatible with lossless mode.\n"); + return -1; + } + + s->spatial_decomposition_type= avctx->prediction_method; //FIXME add decorrelator type r transform_type + + s->mv_scale = (avctx->flags & CODEC_FLAG_QPEL) ? 2 : 4; + s->block_max_depth= (avctx->flags & CODEC_FLAG_4MV ) ? 1 : 0; + + for(plane_index=0; plane_index<3; plane_index++){ + s->plane[plane_index].diag_mc= 1; + s->plane[plane_index].htaps= 6; + s->plane[plane_index].hcoeff[0]= 40; + s->plane[plane_index].hcoeff[1]= -10; + s->plane[plane_index].hcoeff[2]= 2; + s->plane[plane_index].fast_mc= 1; + } + + if ((ret = ff_snow_common_init(avctx)) < 0) { + ff_snow_common_end(avctx->priv_data); + return ret; + } + ff_snow_alloc_blocks(s); + + s->version=0; + + s->m.avctx = avctx; + s->m.flags = avctx->flags; + s->m.bit_rate= avctx->bit_rate; + + s->m.me.temp = + s->m.me.scratchpad= av_mallocz((avctx->width+64)*2*16*2*sizeof(uint8_t)); + s->m.me.map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t)); + s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t)); + s->m.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t)); + ff_h263_encode_init(&s->m); //mv_penalty + + s->max_ref_frames = FFMAX(FFMIN(avctx->refs, MAX_REF_FRAMES), 1); + + if(avctx->flags&CODEC_FLAG_PASS1){ + if(!avctx->stats_out) + avctx->stats_out = av_mallocz(256); + } + if((avctx->flags&CODEC_FLAG_PASS2) || !(avctx->flags&CODEC_FLAG_QSCALE)){ + if(ff_rate_control_init(&s->m) < 0) + return -1; + } + s->pass1_rc= !(avctx->flags & (CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2)); + + avctx->coded_frame= &s->current_picture; + switch(avctx->pix_fmt){ + case AV_PIX_FMT_YUV444P: +// case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV420P: +// case AV_PIX_FMT_GRAY8: +// case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_YUV410P: + s->colorspace_type= 0; + break; +/* case AV_PIX_FMT_RGB32: + s->colorspace= 1; + break;*/ + default: + av_log(avctx, AV_LOG_ERROR, "pixel format not supported\n"); + return -1; + } + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift); + + ff_set_cmp(&s->dsp, s->dsp.me_cmp, s->avctx->me_cmp); + ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, s->avctx->me_sub_cmp); + + if ((ret = ff_get_buffer(s->avctx, &s->input_picture, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if(s->avctx->me_method == ME_ITER){ + int i; + int size= s->b_width * s->b_height << 2*s->block_max_depth; + for(i=0; imax_ref_frames; i++){ + s->ref_mvs[i]= av_mallocz(size*sizeof(int16_t[2])); + s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t)); + } + } + + return 0; +} + +//near copy & paste from dsputil, FIXME +static int pix_sum(uint8_t * pix, int line_size, int w, int h) +{ + int s, i, j; + + s = 0; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + s += pix[0]; + pix ++; + } + pix += line_size - w; + } + return s; +} + +//near copy & paste from dsputil, FIXME +static int pix_norm1(uint8_t * pix, int line_size, int w) +{ + int s, i, j; + uint32_t *sq = ff_squareTbl + 256; + + s = 0; + for (i = 0; i < w; i++) { + for (j = 0; j < w; j ++) { + s += sq[pix[0]]; + pix ++; + } + pix += line_size - w; + } + return s; +} + +static inline int get_penalty_factor(int lambda, int lambda2, int type){ + switch(type&0xFF){ + default: + case FF_CMP_SAD: + return lambda>>FF_LAMBDA_SHIFT; + case FF_CMP_DCT: + return (3*lambda)>>(FF_LAMBDA_SHIFT+1); + case FF_CMP_W53: + return (4*lambda)>>(FF_LAMBDA_SHIFT); + case FF_CMP_W97: + return (2*lambda)>>(FF_LAMBDA_SHIFT); + case FF_CMP_SATD: + case FF_CMP_DCT264: + return (2*lambda)>>FF_LAMBDA_SHIFT; + case FF_CMP_RD: + case FF_CMP_PSNR: + case FF_CMP_SSE: + case FF_CMP_NSSE: + return lambda2>>FF_LAMBDA_SHIFT; + case FF_CMP_BIT: + return 1; + } +} + +//FIXME copy&paste +#define P_LEFT P[1] +#define P_TOP P[2] +#define P_TOPRIGHT P[3] +#define P_MEDIAN P[4] +#define P_MV1 P[9] +#define FLAG_QPEL 1 //must be 1 + +static int encode_q_branch(SnowContext *s, int level, int x, int y){ + uint8_t p_buffer[1024]; + uint8_t i_buffer[1024]; + uint8_t p_state[sizeof(s->block_state)]; + uint8_t i_state[sizeof(s->block_state)]; + RangeCoder pc, ic; + uint8_t *pbbak= s->c.bytestream; + uint8_t *pbbak_start= s->c.bytestream_start; + int score, score2, iscore, i_len, p_len, block_s, sum, base_bits; + const int w= s->b_width << s->block_max_depth; + const int h= s->b_height << s->block_max_depth; + const int rem_depth= s->block_max_depth - level; + const int index= (x + y*w) << rem_depth; + const int block_w= 1<<(LOG2_MB_SIZE - level); + int trx= (x+1)<block[index-1] : &null_block; + const BlockNode *top = y ? &s->block[index-w] : &null_block; + const BlockNode *right = trxblock[index+1] : &null_block; + const BlockNode *bottom= tryblock[index+w] : &null_block; + const BlockNode *tl = y && x ? &s->block[index-w-1] : left; + const BlockNode *tr = y && trxblock[index-w+(1<color[0]; + int pcb= left->color[1]; + int pcr= left->color[2]; + int pmx, pmy; + int mx=0, my=0; + int l,cr,cb; + const int stride= s->current_picture.linesize[0]; + const int uvstride= s->current_picture.linesize[1]; + uint8_t *current_data[3]= { s->input_picture.data[0] + (x + y* stride)*block_w, + s->input_picture.data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift), + s->input_picture.data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)}; + int P[10][2]; + int16_t last_mv[3][2]; + int qpel= !!(s->avctx->flags & CODEC_FLAG_QPEL); //unused + const int shift= 1+qpel; + MotionEstContext *c= &s->m.me; + int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref); + int mx_context= av_log2(2*FFABS(left->mx - top->mx)); + int my_context= av_log2(2*FFABS(left->my - top->my)); + int s_context= 2*left->level + 2*top->level + tl->level + tr->level; + int ref, best_ref, ref_score, ref_mx, ref_my; + + assert(sizeof(s->block_state) >= 256); + if(s->keyframe){ + set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA); + return 0; + } + +// clip predictors / edge ? + + P_LEFT[0]= left->mx; + P_LEFT[1]= left->my; + P_TOP [0]= top->mx; + P_TOP [1]= top->my; + P_TOPRIGHT[0]= tr->mx; + P_TOPRIGHT[1]= tr->my; + + last_mv[0][0]= s->block[index].mx; + last_mv[0][1]= s->block[index].my; + last_mv[1][0]= right->mx; + last_mv[1][1]= right->my; + last_mv[2][0]= bottom->mx; + last_mv[2][1]= bottom->my; + + s->m.mb_stride=2; + s->m.mb_x= + s->m.mb_y= 0; + c->skip= 0; + + assert(c-> stride == stride); + assert(c->uvstride == uvstride); + + c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp); + c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp); + c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp); + c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_MV; + + c->xmin = - x*block_w - 16+3; + c->ymin = - y*block_w - 16+3; + c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3; + c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3; + + if(P_LEFT[0] > (c->xmax<xmax< (c->ymax<ymax< (c->xmax<xmax< (c->ymax<ymax<xmin<xmin< (c->xmax<xmax< (c->ymax<ymax<pred_x= P_LEFT[0]; + c->pred_y= P_LEFT[1]; + } else { + c->pred_x = P_MEDIAN[0]; + c->pred_y = P_MEDIAN[1]; + } + + score= INT_MAX; + best_ref= 0; + for(ref=0; refref_frames; ref++){ + init_ref(c, current_data, s->last_picture[ref].data, NULL, block_w*x, block_w*y, 0); + + ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv, + (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w); + + assert(ref_mx >= c->xmin); + assert(ref_mx <= c->xmax); + assert(ref_my >= c->ymin); + assert(ref_my <= c->ymax); + + ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w); + ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0); + ref_score+= 2*av_log2(2*ref)*c->penalty_factor; + if(s->ref_mvs[ref]){ + s->ref_mvs[ref][index][0]= ref_mx; + s->ref_mvs[ref][index][1]= ref_my; + s->ref_scores[ref][index]= ref_score; + } + if(score > ref_score){ + score= ref_score; + best_ref= ref; + mx= ref_mx; + my= ref_my; + } + } + //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2 + + // subpel search + base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start); + pc= s->c; + pc.bytestream_start= + pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo + memcpy(p_state, s->block_state, sizeof(s->block_state)); + + if(level!=s->block_max_depth) + put_rac(&pc, &p_state[4 + s_context], 1); + put_rac(&pc, &p_state[1 + left->type + top->type], 0); + if(s->ref_frames > 1) + put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0); + pred_mv(s, &pmx, &pmy, best_ref, left, top, tr); + put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1); + put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1); + p_len= pc.bytestream - pc.bytestream_start; + score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT; + + block_s= block_w*block_w; + sum = pix_sum(current_data[0], stride, block_w, block_w); + l= (sum + block_s/2)/block_s; + iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s; + + block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift); + sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift); + cb= (sum + block_s/2)/block_s; +// iscore += pix_norm1(¤t_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s; + sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift); + cr= (sum + block_s/2)/block_s; +// iscore += pix_norm1(¤t_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s; + + ic= s->c; + ic.bytestream_start= + ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo + memcpy(i_state, s->block_state, sizeof(s->block_state)); + if(level!=s->block_max_depth) + put_rac(&ic, &i_state[4 + s_context], 1); + put_rac(&ic, &i_state[1 + left->type + top->type], 1); + put_symbol(&ic, &i_state[32], l-pl , 1); + put_symbol(&ic, &i_state[64], cb-pcb, 1); + put_symbol(&ic, &i_state[96], cr-pcr, 1); + i_len= ic.bytestream - ic.bytestream_start; + iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT; + +// assert(score==256*256*256*64-1); + assert(iscore < 255*255*256 + s->lambda2*10); + assert(iscore >= 0); + assert(l>=0 && l<=255); + assert(pl>=0 && pl<=255); + + if(level==0){ + int varc= iscore >> 8; + int vard= score >> 8; + if (vard <= 64 || vard < varc) + c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc); + else + c->scene_change_score+= s->m.qscale; + } + + if(level!=s->block_max_depth){ + put_rac(&s->c, &s->block_state[4 + s_context], 0); + score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0); + score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0); + score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1); + score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1); + score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead + + if(score2 < score && score2 < iscore) + return score2; + } + + if(iscore < score){ + pred_mv(s, &pmx, &pmy, 0, left, top, tr); + memcpy(pbbak, i_buffer, i_len); + s->c= ic; + s->c.bytestream_start= pbbak_start; + s->c.bytestream= pbbak + i_len; + set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA); + memcpy(s->block_state, i_state, sizeof(s->block_state)); + return iscore; + }else{ + memcpy(pbbak, p_buffer, p_len); + s->c= pc; + s->c.bytestream_start= pbbak_start; + s->c.bytestream= pbbak + p_len; + set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0); + memcpy(s->block_state, p_state, sizeof(s->block_state)); + return score; + } +} + +static void encode_q_branch2(SnowContext *s, int level, int x, int y){ + const int w= s->b_width << s->block_max_depth; + const int rem_depth= s->block_max_depth - level; + const int index= (x + y*w) << rem_depth; + int trx= (x+1)<block[index]; + const BlockNode *left = x ? &s->block[index-1] : &null_block; + const BlockNode *top = y ? &s->block[index-w] : &null_block; + const BlockNode *tl = y && x ? &s->block[index-w-1] : left; + const BlockNode *tr = y && trxblock[index-w+(1<color[0]; + int pcb= left->color[1]; + int pcr= left->color[2]; + int pmx, pmy; + int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref); + int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref; + int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref; + int s_context= 2*left->level + 2*top->level + tl->level + tr->level; + + if(s->keyframe){ + set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA); + return; + } + + if(level!=s->block_max_depth){ + if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){ + put_rac(&s->c, &s->block_state[4 + s_context], 1); + }else{ + put_rac(&s->c, &s->block_state[4 + s_context], 0); + encode_q_branch2(s, level+1, 2*x+0, 2*y+0); + encode_q_branch2(s, level+1, 2*x+1, 2*y+0); + encode_q_branch2(s, level+1, 2*x+0, 2*y+1); + encode_q_branch2(s, level+1, 2*x+1, 2*y+1); + return; + } + } + if(b->type & BLOCK_INTRA){ + pred_mv(s, &pmx, &pmy, 0, left, top, tr); + put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1); + put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1); + put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1); + put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1); + set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA); + }else{ + pred_mv(s, &pmx, &pmy, b->ref, left, top, tr); + put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0); + if(s->ref_frames > 1) + put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0); + put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1); + put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1); + set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0); + } +} + +static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){ + int i, x2, y2; + Plane *p= &s->plane[plane_index]; + const int block_size = MB_SIZE >> s->block_max_depth; + const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth]; + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; + const int ref_stride= s->current_picture.linesize[plane_index]; + uint8_t *src= s-> input_picture.data[plane_index]; + IDWTELEM *dst= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned + const int b_stride = s->b_width << s->block_max_depth; + const int w= p->width; + const int h= p->height; + int index= mb_x + mb_y*b_stride; + BlockNode *b= &s->block[index]; + BlockNode backup= *b; + int ab=0; + int aa=0; + + av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above + + b->type|= BLOCK_INTRA; + b->color[plane_index]= 0; + memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM)); + + for(i=0; i<4; i++){ + int mb_x2= mb_x + (i &1) - 1; + int mb_y2= mb_y + (i>>1) - 1; + int x= block_w*mb_x2 + block_w/2; + int y= block_h*mb_y2 + block_h/2; + + add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc, + x, y, block_w, block_h, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index); + + for(y2= FFMAX(y, 0); y2h) obmc_v += obmc[index - block_h*obmc_stride]; + if(x+block_w>w) obmc_v += obmc[index - block_w]; + //FIXME precalculate this or simplify it somehow else + + d = -dst[index] + (1<<(FRAC_BITS-1)); + dst[index] = d; + ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v; + aa += obmc_v * obmc_v; //FIXME precalculate this + } + } + } + *b= backup; + + return av_clip( ROUNDED_DIV(ab<b_width << s->block_max_depth; + const int b_height = s->b_height<< s->block_max_depth; + int index= x + y*b_stride; + const BlockNode *b = &s->block[index]; + const BlockNode *left = x ? &s->block[index-1] : &null_block; + const BlockNode *top = y ? &s->block[index-b_stride] : &null_block; + const BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left; + const BlockNode *tr = y && x+wblock[index-b_stride+w] : tl; + int dmx, dmy; +// int mx_context= av_log2(2*FFABS(left->mx - top->mx)); +// int my_context= av_log2(2*FFABS(left->my - top->my)); + + if(x<0 || x>=b_stride || y>=b_height) + return 0; +/* +1 0 0 +01X 1-2 1 +001XX 3-6 2-3 +0001XXX 7-14 4-7 +00001XXXX 15-30 8-15 +*/ +//FIXME try accurate rate +//FIXME intra and inter predictors if surrounding blocks are not the same type + if(b->type & BLOCK_INTRA){ + return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0])) + + av_log2(2*FFABS(left->color[1] - b->color[1])) + + av_log2(2*FFABS(left->color[2] - b->color[2]))); + }else{ + pred_mv(s, &dmx, &dmy, b->ref, left, top, tr); + dmx-= b->mx; + dmy-= b->my; + return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda + + av_log2(2*FFABS(dmy)) + + av_log2(2*b->ref)); + } +} + +static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){ + Plane *p= &s->plane[plane_index]; + const int block_size = MB_SIZE >> s->block_max_depth; + const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; + const int ref_stride= s->current_picture.linesize[plane_index]; + uint8_t *dst= s->current_picture.data[plane_index]; + uint8_t *src= s-> input_picture.data[plane_index]; + IDWTELEM *pred= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4; + uint8_t *cur = s->scratchbuf; + uint8_t *tmp = s->emu_edge_buffer; + const int b_stride = s->b_width << s->block_max_depth; + const int b_height = s->b_height<< s->block_max_depth; + const int w= p->width; + const int h= p->height; + int distortion; + int rate= 0; + const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp); + int sx= block_w*mb_x - block_w/2; + int sy= block_h*mb_y - block_h/2; + int x0= FFMAX(0,-sx); + int y0= FFMAX(0,-sy); + int x1= FFMIN(block_w*2, w-sx); + int y1= FFMIN(block_h*2, h-sy); + int i,x,y; + + av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w + + ff_snow_pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_h*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h); + + for(y=y0; y= LOG2_OBMC_MAX + int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX); +#else + int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS); +#endif + v = (v + pred1[x]) >> FRAC_BITS; + if(v&(~255)) v= ~(v>>31); + dst1[x] = v; + } + } + + /* copy the regions where obmc[] = (uint8_t)256 */ + if(LOG2_OBMC_MAX == 8 + && (mb_x == 0 || mb_x == b_stride-1) + && (mb_y == 0 || mb_y == b_height-1)){ + if(mb_x == 0) + x1 = block_w; + else + x0 = block_w; + if(mb_y == 0) + y1 = block_h; + else + y0 = block_h; + for(y=y0; yavctx->me_cmp == FF_CMP_W97) + distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); + else if(s->avctx->me_cmp == FF_CMP_W53) + distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); + else{ + distortion = 0; + for(i=0; i<4; i++){ + int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride; + distortion += s->dsp.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16); + } + } + }else{ + assert(block_w==8); + distortion = s->dsp.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2); + } + + if(plane_index==0){ + for(i=0; i<4; i++){ +/* ..RRr + * .RXx. + * rxx.. + */ + rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1); + } + if(mb_x == b_stride-2) + rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1); + } + return distortion + rate*penalty_factor; +} + +static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){ + int i, y2; + Plane *p= &s->plane[plane_index]; + const int block_size = MB_SIZE >> s->block_max_depth; + const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth]; + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; + const int ref_stride= s->current_picture.linesize[plane_index]; + uint8_t *dst= s->current_picture.data[plane_index]; + uint8_t *src= s-> input_picture.data[plane_index]; + //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst + // const has only been removed from zero_dst to suppress a warning + static IDWTELEM zero_dst[4096]; //FIXME + const int b_stride = s->b_width << s->block_max_depth; + const int w= p->width; + const int h= p->height; + int distortion= 0; + int rate= 0; + const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp); + + av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below + + for(i=0; i<9; i++){ + int mb_x2= mb_x + (i%3) - 1; + int mb_y2= mb_y + (i/3) - 1; + int x= block_w*mb_x2 + block_w/2; + int y= block_h*mb_y2 + block_h/2; + + add_yblock(s, 0, NULL, zero_dst, dst, obmc, + x, y, block_w, block_h, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index); + + //FIXME find a cleaner/simpler way to skip the outside stuff + for(y2= y; y2<0; y2++) + memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w); + for(y2= h; y2 w){ + for(y2= y; y2dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h); + } + + if(plane_index==0){ + BlockNode *b= &s->block[mb_x+mb_y*b_stride]; + int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1); + +/* ..RRRr + * .RXXx. + * .RXXx. + * rxxx. + */ + if(merged) + rate = get_block_bits(s, mb_x, mb_y, 2); + for(i=merged?4:0; i<9; i++){ + static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}}; + rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1); + } + } + return distortion + rate*penalty_factor; +} + +static int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){ + const int w= b->width; + const int h= b->height; + int x, y; + + if(1){ + int run=0; + int *runs = s->run_buffer; + int run_index=0; + int max_index; + + for(y=0; y 1){ + if(orientation==1) ll= src[y + (x-2)*stride]; + else ll= src[x - 2 + y*stride]; + }*/ + } + if(parent){ + int px= x>>1; + int py= y>>1; + if(pxparent->width && pyparent->height) + p= parent[px + py*2*stride]; + } + if(!(/*ll|*/l|lt|t|rt|p)){ + if(v){ + runs[run_index++]= run; + run=0; + }else{ + run++; + } + } + } + } + max_index= run_index; + runs[run_index++]= run; + run_index=0; + run= runs[run_index++]; + + put_symbol2(&s->c, b->state[30], max_index, 0); + if(run_index <= max_index) + put_symbol2(&s->c, b->state[1], run, 3); + + for(y=0; yc.bytestream_end - s->c.bytestream < w*40){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + for(x=0; x 1){ + if(orientation==1) ll= src[y + (x-2)*stride]; + else ll= src[x - 2 + y*stride]; + }*/ + } + if(parent){ + int px= x>>1; + int py= y>>1; + if(pxparent->width && pyparent->height) + p= parent[px + py*2*stride]; + } + if(/*ll|*/l|lt|t|rt|p){ + int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p)); + + put_rac(&s->c, &b->state[0][context], !!v); + }else{ + if(!run){ + run= runs[run_index++]; + + if(run_index <= max_index) + put_symbol2(&s->c, b->state[1], run, 3); + assert(v); + }else{ + run--; + assert(!v); + } + } + if(v){ + int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p)); + int l2= 2*FFABS(l) + (l<0); + int t2= 2*FFABS(t) + (t<0); + + put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4); + put_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l2&0xFF] + 3*ff_quant3bA[t2&0xFF]], v<0); + } + } + } + } + return 0; +} + +static int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){ +// encode_subband_qtree(s, b, src, parent, stride, orientation); +// encode_subband_z0run(s, b, src, parent, stride, orientation); + return encode_subband_c0run(s, b, src, parent, stride, orientation); +// encode_subband_dzr(s, b, src, parent, stride, orientation); +} + +static av_always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){ + const int b_stride= s->b_width << s->block_max_depth; + BlockNode *block= &s->block[mb_x + mb_y * b_stride]; + BlockNode backup= *block; + unsigned value; + int rd, index; + + assert(mb_x>=0 && mb_y>=0); + assert(mb_xcolor[0] = p[0]; + block->color[1] = p[1]; + block->color[2] = p[2]; + block->type |= BLOCK_INTRA; + }else{ + index= (p[0] + 31*p[1]) & (ME_CACHE_SIZE-1); + value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6) + (block->ref<<12); + if(s->me_cache[index] == value) + return 0; + s->me_cache[index]= value; + + block->mx= p[0]; + block->my= p[1]; + block->type &= ~BLOCK_INTRA; + } + + rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged); + +//FIXME chroma + if(rd < *best_rd){ + *best_rd= rd; + return 1; + }else{ + *block= backup; + return 0; + } +} + +/* special case for int[2] args we discard afterwards, + * fixes compilation problem with gcc 2.95 */ +static av_always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){ + int p[2] = {p0, p1}; + return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd); +} + +static av_always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){ + const int b_stride= s->b_width << s->block_max_depth; + BlockNode *block= &s->block[mb_x + mb_y * b_stride]; + BlockNode backup[4]; + unsigned value; + int rd, index; + + /* We don't initialize backup[] during variable declaration, because + * that fails to compile on MSVC: "cannot convert from 'BlockNode' to + * 'int16_t'". */ + backup[0] = block[0]; + backup[1] = block[1]; + backup[2] = block[b_stride]; + backup[3] = block[b_stride + 1]; + + assert(mb_x>=0 && mb_y>=0); + assert(mb_xme_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12); + if(s->me_cache[index] == value) + return 0; + s->me_cache[index]= value; + + block->mx= p0; + block->my= p1; + block->ref= ref; + block->type &= ~BLOCK_INTRA; + block[1]= block[b_stride]= block[b_stride+1]= *block; + + rd= get_4block_rd(s, mb_x, mb_y, 0); + +//FIXME chroma + if(rd < *best_rd){ + *best_rd= rd; + return 1; + }else{ + block[0]= backup[0]; + block[1]= backup[1]; + block[b_stride]= backup[2]; + block[b_stride+1]= backup[3]; + return 0; + } +} + +static void iterative_me(SnowContext *s){ + int pass, mb_x, mb_y; + const int b_width = s->b_width << s->block_max_depth; + const int b_height= s->b_height << s->block_max_depth; + const int b_stride= b_width; + int color[3]; + + { + RangeCoder r = s->c; + uint8_t state[sizeof(s->block_state)]; + memcpy(state, s->block_state, sizeof(s->block_state)); + for(mb_y= 0; mb_yb_height; mb_y++) + for(mb_x= 0; mb_xb_width; mb_x++) + encode_q_branch(s, 0, mb_x, mb_y); + s->c = r; + memcpy(s->block_state, state, sizeof(s->block_state)); + } + + for(pass=0; pass<25; pass++){ + int change= 0; + + for(mb_y= 0; mb_yblock[index]; + BlockNode *tb = mb_y ? &s->block[index-b_stride ] : NULL; + BlockNode *lb = mb_x ? &s->block[index -1] : NULL; + BlockNode *rb = mb_x+1block[index +1] : NULL; + BlockNode *bb = mb_y+1block[index+b_stride ] : NULL; + BlockNode *tlb= mb_x && mb_y ? &s->block[index-b_stride-1] : NULL; + BlockNode *trb= mb_x+1block[index-b_stride+1] : NULL; + BlockNode *blb= mb_x && mb_y+1block[index+b_stride-1] : NULL; + BlockNode *brb= mb_x+1block[index+b_stride+1] : NULL; + const int b_w= (MB_SIZE >> s->block_max_depth); + uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2]; + + if(pass && (block->type & BLOCK_OPT)) + continue; + block->type |= BLOCK_OPT; + + backup= *block; + + if(!s->me_cache_generation) + memset(s->me_cache, 0, sizeof(s->me_cache)); + s->me_cache_generation += 1<<22; + + //FIXME precalculate + { + int x, y; + for (y = 0; y < b_w * 2; y++) + memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2); + if(mb_x==0) + for(y=0; y input_picture.data[0]; + uint8_t *dst= s->current_picture.data[0]; + const int stride= s->current_picture.linesize[0]; + const int block_w= MB_SIZE >> s->block_max_depth; + const int block_h= MB_SIZE >> s->block_max_depth; + const int sx= block_w*mb_x - block_w/2; + const int sy= block_h*mb_y - block_h/2; + const int w= s->plane[0].width; + const int h= s->plane[0].height; + int y; + + for(y=sy; y<0; y++) + memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2); + for(y=h; y w){ + for(y=sy; y 0 && (block->type&BLOCK_INTRA)){ + int color0[3]= {block->color[0], block->color[1], block->color[2]}; + check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd); + }else + check_block_inter(s, mb_x, mb_y, block->mx, block->my, obmc_edged, &best_rd); + + ref_b= *block; + ref_rd= best_rd; + for(ref=0; ref < s->ref_frames; ref++){ + int16_t (*mvr)[2]= &s->ref_mvs[ref][index]; + if(s->ref_scores[ref][index] > s->ref_scores[ref_b.ref][index]*3/2) //FIXME tune threshold + continue; + block->ref= ref; + best_rd= INT_MAX; + + check_block_inter(s, mb_x, mb_y, mvr[0][0], mvr[0][1], obmc_edged, &best_rd); + check_block_inter(s, mb_x, mb_y, 0, 0, obmc_edged, &best_rd); + if(tb) + check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd); + if(lb) + check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd); + if(rb) + check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd); + if(bb) + check_block_inter(s, mb_x, mb_y, mvr[b_stride][0], mvr[b_stride][1], obmc_edged, &best_rd); + + /* fullpel ME */ + //FIXME avoid subpel interpolation / round to nearest integer + do{ + dia_change=0; + for(i=0; iavctx->dia_size, 1); i++){ + for(j=0; jmx+4*(i-j), block->my+(4*j), obmc_edged, &best_rd); + dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my-(4*j), obmc_edged, &best_rd); + dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+4*(i-j), block->my-(4*j), obmc_edged, &best_rd); + dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my+(4*j), obmc_edged, &best_rd); + } + } + }while(dia_change); + /* subpel ME */ + do{ + static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},}; + dia_change=0; + for(i=0; i<8; i++) + dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+square[i][0], block->my+square[i][1], obmc_edged, &best_rd); + }while(dia_change); + //FIXME or try the standard 2 pass qpel or similar + + mvr[0][0]= block->mx; + mvr[0][1]= block->my; + if(ref_rd > best_rd){ + ref_rd= best_rd; + ref_b= *block; + } + } + best_rd= ref_rd; + *block= ref_b; + check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd); + //FIXME RD style color selection + if(!same_block(block, &backup)){ + if(tb ) tb ->type &= ~BLOCK_OPT; + if(lb ) lb ->type &= ~BLOCK_OPT; + if(rb ) rb ->type &= ~BLOCK_OPT; + if(bb ) bb ->type &= ~BLOCK_OPT; + if(tlb) tlb->type &= ~BLOCK_OPT; + if(trb) trb->type &= ~BLOCK_OPT; + if(blb) blb->type &= ~BLOCK_OPT; + if(brb) brb->type &= ~BLOCK_OPT; + change ++; + } + } + } + av_log(s->avctx, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change); + if(!change) + break; + } + + if(s->block_max_depth == 1){ + int change= 0; + for(mb_y= 0; mb_yblock[index]; + b[1]= b[0]+1; + b[2]= b[0]+b_stride; + b[3]= b[2]+1; + if(same_block(b[0], b[1]) && + same_block(b[0], b[2]) && + same_block(b[0], b[3])) + continue; + + if(!s->me_cache_generation) + memset(s->me_cache, 0, sizeof(s->me_cache)); + s->me_cache_generation += 1<<22; + + init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0); + + //FIXME more multiref search? + check_4block_inter(s, mb_x, mb_y, + (b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2, + (b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, 0, &best_rd); + + for(i=0; i<4; i++) + if(!(b[i]->type&BLOCK_INTRA)) + check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, b[i]->ref, &best_rd); + + if(init_rd != best_rd) + change++; + } + } + av_log(s->avctx, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4); + } +} + +static void encode_blocks(SnowContext *s, int search){ + int x, y; + int w= s->b_width; + int h= s->b_height; + + if(s->avctx->me_method == ME_ITER && !s->keyframe && search) + iterative_me(s); + + for(y=0; yc.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return; + } + for(x=0; xavctx->me_method == ME_ITER || !search) + encode_q_branch2(s, 0, x, y); + else + encode_q_branch (s, 0, x, y); + } + } +} + +static void quantize(SnowContext *s, SubBand *b, IDWTELEM *dst, DWTELEM *src, int stride, int bias){ + const int w= b->width; + const int h= b->height; + const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); + const int qmul= ff_qexp[qlog&(QROOT-1)]<<((qlog>>QSHIFT) + ENCODER_EXTRA_BITS); + int x,y, thres1, thres2; + + if(s->qlog == LOSSLESS_QLOG){ + for(y=0; y>3; + thres1= ((qmul - bias)>>QEXPSHIFT) - 1; + thres2= 2*thres1; + + if(!bias){ + for(y=0; y thres2){ + if(i>=0){ + i<<= QEXPSHIFT; + i/= qmul; //FIXME optimize + dst[x + y*stride]= i; + }else{ + i= -i; + i<<= QEXPSHIFT; + i/= qmul; //FIXME optimize + dst[x + y*stride]= -i; + } + }else + dst[x + y*stride]= 0; + } + } + }else{ + for(y=0; y thres2){ + if(i>=0){ + i<<= QEXPSHIFT; + i= (i + bias) / qmul; //FIXME optimize + dst[x + y*stride]= i; + }else{ + i= -i; + i<<= QEXPSHIFT; + i= (i + bias) / qmul; //FIXME optimize + dst[x + y*stride]= -i; + } + }else + dst[x + y*stride]= 0; + } + } + } +} + +static void dequantize(SnowContext *s, SubBand *b, IDWTELEM *src, int stride){ + const int w= b->width; + const int h= b->height; + const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); + const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); + const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; + int x,y; + + if(s->qlog == LOSSLESS_QLOG) return; + + for(y=0; y>(QEXPSHIFT)); //FIXME try different bias + }else if(i>0){ + src[x + y*stride]= (( i*qmul + qadd)>>(QEXPSHIFT)); + } + } + } +} + +static void decorrelate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){ + const int w= b->width; + const int h= b->height; + int x,y; + + for(y=h-1; y>=0; y--){ + for(x=w-1; x>=0; x--){ + int i= x + y*stride; + + if(x){ + if(use_median){ + if(y && x+1width; + const int h= b->height; + int x,y; + + for(y=0; yspatial_decomposition_count; level++){ + for(orientation=level ? 1:0; orientation<4; orientation++){ + if(orientation==2) continue; + put_symbol(&s->c, s->header_state, s->plane[plane_index].band[level][orientation].qlog, 1); + } + } + } +} + +static void encode_header(SnowContext *s){ + int plane_index, i; + uint8_t kstate[32]; + + memset(kstate, MID_STATE, sizeof(kstate)); + + put_rac(&s->c, kstate, s->keyframe); + if(s->keyframe || s->always_reset){ + ff_snow_reset_contexts(s); + s->last_spatial_decomposition_type= + s->last_qlog= + s->last_qbias= + s->last_mv_scale= + s->last_block_max_depth= 0; + for(plane_index=0; plane_index<2; plane_index++){ + Plane *p= &s->plane[plane_index]; + p->last_htaps=0; + p->last_diag_mc=0; + memset(p->last_hcoeff, 0, sizeof(p->last_hcoeff)); + } + } + if(s->keyframe){ + put_symbol(&s->c, s->header_state, s->version, 0); + put_rac(&s->c, s->header_state, s->always_reset); + put_symbol(&s->c, s->header_state, s->temporal_decomposition_type, 0); + put_symbol(&s->c, s->header_state, s->temporal_decomposition_count, 0); + put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0); + put_symbol(&s->c, s->header_state, s->colorspace_type, 0); + put_symbol(&s->c, s->header_state, s->chroma_h_shift, 0); + put_symbol(&s->c, s->header_state, s->chroma_v_shift, 0); + put_rac(&s->c, s->header_state, s->spatial_scalability); +// put_rac(&s->c, s->header_state, s->rate_scalability); + put_symbol(&s->c, s->header_state, s->max_ref_frames-1, 0); + + encode_qlogs(s); + } + + if(!s->keyframe){ + int update_mc=0; + for(plane_index=0; plane_index<2; plane_index++){ + Plane *p= &s->plane[plane_index]; + update_mc |= p->last_htaps != p->htaps; + update_mc |= p->last_diag_mc != p->diag_mc; + update_mc |= !!memcmp(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff)); + } + put_rac(&s->c, s->header_state, update_mc); + if(update_mc){ + for(plane_index=0; plane_index<2; plane_index++){ + Plane *p= &s->plane[plane_index]; + put_rac(&s->c, s->header_state, p->diag_mc); + put_symbol(&s->c, s->header_state, p->htaps/2-1, 0); + for(i= p->htaps/2; i; i--) + put_symbol(&s->c, s->header_state, FFABS(p->hcoeff[i]), 0); + } + } + if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){ + put_rac(&s->c, s->header_state, 1); + put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0); + encode_qlogs(s); + }else + put_rac(&s->c, s->header_state, 0); + } + + put_symbol(&s->c, s->header_state, s->spatial_decomposition_type - s->last_spatial_decomposition_type, 1); + put_symbol(&s->c, s->header_state, s->qlog - s->last_qlog , 1); + put_symbol(&s->c, s->header_state, s->mv_scale - s->last_mv_scale, 1); + put_symbol(&s->c, s->header_state, s->qbias - s->last_qbias , 1); + put_symbol(&s->c, s->header_state, s->block_max_depth - s->last_block_max_depth, 1); + +} + +static void update_last_header_values(SnowContext *s){ + int plane_index; + + if(!s->keyframe){ + for(plane_index=0; plane_index<2; plane_index++){ + Plane *p= &s->plane[plane_index]; + p->last_diag_mc= p->diag_mc; + p->last_htaps = p->htaps; + memcpy(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff)); + } + } + + s->last_spatial_decomposition_type = s->spatial_decomposition_type; + s->last_qlog = s->qlog; + s->last_qbias = s->qbias; + s->last_mv_scale = s->mv_scale; + s->last_block_max_depth = s->block_max_depth; + s->last_spatial_decomposition_count = s->spatial_decomposition_count; +} + +static int qscale2qlog(int qscale){ + return rint(QROOT*log2(qscale / (float)FF_QP2LAMBDA)) + + 61*QROOT/8; ///< 64 > 60 +} + +static int ratecontrol_1pass(SnowContext *s, AVFrame *pict) +{ + /* Estimate the frame's complexity as a sum of weighted dwt coefficients. + * FIXME we know exact mv bits at this point, + * but ratecontrol isn't set up to include them. */ + uint32_t coef_sum= 0; + int level, orientation, delta_qlog; + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &s->plane[0].band[level][orientation]; + IDWTELEM *buf= b->ibuf; + const int w= b->width; + const int h= b->height; + const int stride= b->stride; + const int qlog= av_clip(2*QROOT + b->qlog, 0, QROOT*16); + const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); + const int qdiv= (1<<16)/qmul; + int x, y; + //FIXME this is ugly + for(y=0; ybuf[x+y*stride]; + if(orientation==0) + decorrelate(s, b, buf, stride, 1, 0); + for(y=0; y> 16; + } + } + + /* ugly, ratecontrol just takes a sqrt again */ + coef_sum = (uint64_t)coef_sum * coef_sum >> 16; + assert(coef_sum < INT_MAX); + + if(pict->pict_type == AV_PICTURE_TYPE_I){ + s->m.current_picture.mb_var_sum= coef_sum; + s->m.current_picture.mc_mb_var_sum= 0; + }else{ + s->m.current_picture.mc_mb_var_sum= coef_sum; + s->m.current_picture.mb_var_sum= 0; + } + + pict->quality= ff_rate_estimate_qscale(&s->m, 1); + if (pict->quality < 0) + return INT_MIN; + s->lambda= pict->quality * 3/2; + delta_qlog= qscale2qlog(pict->quality) - s->qlog; + s->qlog+= delta_qlog; + return delta_qlog; +} + +static void calculate_visual_weight(SnowContext *s, Plane *p){ + int width = p->width; + int height= p->height; + int level, orientation, x, y; + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + IDWTELEM *ibuf= b->ibuf; + int64_t error=0; + + memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height); + ibuf[b->width/2 + b->height/2*b->stride]= 256*16; + ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count); + for(y=0; yspatial_idwt_buffer[x + y*width]*16; + error += d*d; + } + } + + b->qlog= (int)(log(352256.0/sqrt(error)) / log(pow(2.0, 1.0/QROOT))+0.5); + } + } +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + SnowContext *s = avctx->priv_data; + RangeCoder * const c= &s->c; + AVFrame *pic = &s->new_picture; + const int width= s->avctx->width; + const int height= s->avctx->height; + int level, orientation, plane_index, i, y, ret; + uint8_t rc_header_bak[sizeof(s->header_state)]; + uint8_t rc_block_bak[sizeof(s->block_state)]; + + if ((ret = ff_alloc_packet2(avctx, pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + ff_init_range_encoder(c, pkt->data, pkt->size); + ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); + + for(i=0; i<3; i++){ + int hshift= i ? s->chroma_h_shift : 0; + int vshift= i ? s->chroma_v_shift : 0; + for(y=0; y<(height>>vshift); y++) + memcpy(&s->input_picture.data[i][y * s->input_picture.linesize[i]], + &pict->data[i][y * pict->linesize[i]], + width>>hshift); + s->dsp.draw_edges(s->input_picture.data[i], s->input_picture.linesize[i], + width >> hshift, height >> vshift, + EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, + EDGE_TOP | EDGE_BOTTOM); + + } + emms_c(); + s->new_picture = *pict; + + s->m.picture_number= avctx->frame_number; + if(avctx->flags&CODEC_FLAG_PASS2){ + s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_number].new_pict_type; + s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I; + if(!(avctx->flags&CODEC_FLAG_QSCALE)) { + pic->quality = ff_rate_estimate_qscale(&s->m, 0); + if (pic->quality < 0) + return -1; + } + }else{ + s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0; + s->m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + } + + if(s->pass1_rc && avctx->frame_number == 0) + pic->quality = 2*FF_QP2LAMBDA; + if (pic->quality) { + s->qlog = qscale2qlog(pic->quality); + s->lambda = pic->quality * 3/2; + } + if (s->qlog < 0 || (!pic->quality && (avctx->flags & CODEC_FLAG_QSCALE))) { + s->qlog= LOSSLESS_QLOG; + s->lambda = 0; + }//else keep previous frame's qlog until after motion estimation + + ff_snow_frame_start(s); + + s->m.current_picture_ptr= &s->m.current_picture; + s->m.last_picture.f.pts = s->m.current_picture.f.pts; + s->m.current_picture.f.pts = pict->pts; + if(pic->pict_type == AV_PICTURE_TYPE_P){ + int block_width = (width +15)>>4; + int block_height= (height+15)>>4; + int stride= s->current_picture.linesize[0]; + + assert(s->current_picture.data[0]); + assert(s->last_picture[0].data[0]); + + s->m.avctx= s->avctx; + s->m.current_picture.f.data[0] = s->current_picture.data[0]; + s->m. last_picture.f.data[0] = s->last_picture[0].data[0]; + s->m. new_picture.f.data[0] = s-> input_picture.data[0]; + s->m. last_picture_ptr= &s->m. last_picture; + s->m.linesize= + s->m. last_picture.f.linesize[0] = + s->m. new_picture.f.linesize[0] = + s->m.current_picture.f.linesize[0] = stride; + s->m.uvlinesize= s->current_picture.linesize[1]; + s->m.width = width; + s->m.height= height; + s->m.mb_width = block_width; + s->m.mb_height= block_height; + s->m.mb_stride= s->m.mb_width+1; + s->m.b8_stride= 2*s->m.mb_width+1; + s->m.f_code=1; + s->m.pict_type = pic->pict_type; + s->m.me_method= s->avctx->me_method; + s->m.me.scene_change_score=0; + s->m.flags= s->avctx->flags; + s->m.quarter_sample= (s->avctx->flags & CODEC_FLAG_QPEL)!=0; + s->m.out_format= FMT_H263; + s->m.unrestricted_mv= 1; + + s->m.lambda = s->lambda; + s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7); + s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT; + + s->m.dsp= s->dsp; //move + s->m.hdsp = s->hdsp; + ff_init_me(&s->m); + s->hdsp = s->m.hdsp; + s->dsp= s->m.dsp; + } + + if(s->pass1_rc){ + memcpy(rc_header_bak, s->header_state, sizeof(s->header_state)); + memcpy(rc_block_bak, s->block_state, sizeof(s->block_state)); + } + +redo_frame: + + if (pic->pict_type == AV_PICTURE_TYPE_I) + s->spatial_decomposition_count= 5; + else + s->spatial_decomposition_count= 5; + + while( !(width >>(s->chroma_h_shift + s->spatial_decomposition_count)) + || !(height>>(s->chroma_v_shift + s->spatial_decomposition_count))) + s->spatial_decomposition_count--; + + s->m.pict_type = pic->pict_type; + s->qbias = pic->pict_type == AV_PICTURE_TYPE_P ? 2 : 0; + + ff_snow_common_init_after_header(avctx); + + if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){ + for(plane_index=0; plane_index<3; plane_index++){ + calculate_visual_weight(s, &s->plane[plane_index]); + } + } + + encode_header(s); + s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start); + encode_blocks(s, 1); + s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits; + + for(plane_index=0; plane_index<3; plane_index++){ + Plane *p= &s->plane[plane_index]; + int w= p->width; + int h= p->height; + int x, y; +// int bits= put_bits_count(&s->c.pb); + + if (!s->memc_only) { + //FIXME optimize + if(pict->data[plane_index]) //FIXME gray hack + for(y=0; yspatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<spatial_idwt_buffer, plane_index, 0); + + if( plane_index==0 + && pic->pict_type == AV_PICTURE_TYPE_P + && !(avctx->flags&CODEC_FLAG_PASS2) + && s->m.me.scene_change_score > s->avctx->scenechange_threshold){ + ff_init_range_encoder(c, pkt->data, pkt->size); + ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); + pic->pict_type= AV_PICTURE_TYPE_I; + s->keyframe=1; + s->current_picture.key_frame=1; + goto redo_frame; + } + + if(s->qlog == LOSSLESS_QLOG){ + for(y=0; yspatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS; + } + } + }else{ + for(y=0; yspatial_dwt_buffer[y*w + x]=s->spatial_idwt_buffer[y*w + x]<spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type); + else*/ + ff_spatial_dwt(s->spatial_dwt_buffer, s->temp_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count); + + if(s->pass1_rc && plane_index==0){ + int delta_qlog = ratecontrol_1pass(s, pic); + if (delta_qlog <= INT_MIN) + return -1; + if(delta_qlog){ + //reordering qlog in the bitstream would eliminate this reset + ff_init_range_encoder(c, pkt->data, pkt->size); + memcpy(s->header_state, rc_header_bak, sizeof(s->header_state)); + memcpy(s->block_state, rc_block_bak, sizeof(s->block_state)); + encode_header(s); + encode_blocks(s, 0); + } + } + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + + if(!QUANTIZE2) + quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias); + if(orientation==0) + decorrelate(s, b, b->ibuf, b->stride, pic->pict_type == AV_PICTURE_TYPE_P, 0); + if (!s->no_bitstream) + encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation); + assert(b->parent==NULL || b->parent->stride == b->stride*2); + if(orientation==0) + correlate(s, b, b->ibuf, b->stride, 1, 0); + } + } + + for(level=0; levelspatial_decomposition_count; level++){ + for(orientation=level ? 1 : 0; orientation<4; orientation++){ + SubBand *b= &p->band[level][orientation]; + + dequantize(s, b, b->ibuf, b->stride); + } + } + + ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count); + if(s->qlog == LOSSLESS_QLOG){ + for(y=0; yspatial_idwt_buffer[y*w + x]<<=FRAC_BITS; + } + } + } + predict_plane(s, s->spatial_idwt_buffer, plane_index, 1); + }else{ + //ME/MC only + if(pic->pict_type == AV_PICTURE_TYPE_I){ + for(y=0; ycurrent_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x]= + pict->data[plane_index][y*pict->linesize[plane_index] + x]; + } + } + }else{ + memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h); + predict_plane(s, s->spatial_idwt_buffer, plane_index, 1); + } + } + if(s->avctx->flags&CODEC_FLAG_PSNR){ + int64_t error= 0; + + if(pict->data[plane_index]) //FIXME gray hack + for(y=0; ycurrent_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x]; + error += d*d; + } + } + s->avctx->error[plane_index] += error; + s->current_picture.error[plane_index] = error; + } + + } + + update_last_header_values(s); + + ff_snow_release_buffer(avctx); + + s->current_picture.coded_picture_number = avctx->frame_number; + s->current_picture.pict_type = pict->pict_type; + s->current_picture.quality = pict->quality; + s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start); + s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits; + s->m.current_picture.f.display_picture_number = + s->m.current_picture.f.coded_picture_number = avctx->frame_number; + s->m.current_picture.f.quality = pic->quality; + s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start); + if(s->pass1_rc) + if (ff_rate_estimate_qscale(&s->m, 0) < 0) + return -1; + if(avctx->flags&CODEC_FLAG_PASS1) + ff_write_pass1_stats(&s->m); + s->m.last_pict_type = s->m.pict_type; + avctx->frame_bits = s->m.frame_bits; + avctx->mv_bits = s->m.mv_bits; + avctx->misc_bits = s->m.misc_bits; + avctx->p_tex_bits = s->m.p_tex_bits; + + emms_c(); + + pkt->size = ff_rac_terminate(c); + if (avctx->coded_frame->key_frame) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int encode_end(AVCodecContext *avctx) +{ + SnowContext *s = avctx->priv_data; + + ff_snow_common_end(s); + av_frame_unref(&s->input_picture); + av_free(avctx->stats_out); + + return 0; +} + +#define OFFSET(x) offsetof(SnowContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "memc_only", "Only do ME/MC (I frames -> ref, P frame -> ME+MC).", OFFSET(memc_only), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "no_bitstream", "Skip final bitstream writeout.", OFFSET(no_bitstream), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL }, +}; + +static const AVClass snowenc_class = { + .class_name = "snow encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_snow_encoder = { + .name = "snow", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SNOW, + .priv_data_size = sizeof(SnowContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("Snow"), + .priv_class = &snowenc_class, +}; + + +#ifdef TEST +#undef malloc +#undef free +#undef printf + +#include "libavutil/lfg.h" +#include "libavutil/mathematics.h" + +int main(void){ +#define width 256 +#define height 256 + int buffer[2][width*height]; + SnowContext s; + int i; + AVLFG prng; + s.spatial_decomposition_count=6; + s.spatial_decomposition_type=1; + + s.temp_dwt_buffer = av_mallocz(width * sizeof(DWTELEM)); + s.temp_idwt_buffer = av_mallocz(width * sizeof(IDWTELEM)); + + av_lfg_init(&prng, 1); + + printf("testing 5/3 DWT\n"); + for(i=0; i20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); + + { + int level, orientation, x, y; + int64_t errors[8][4]; + int64_t g=0; + + memset(errors, 0, sizeof(errors)); + s.spatial_decomposition_count=3; + s.spatial_decomposition_type=0; + for(level=0; level> (s.spatial_decomposition_count-level); + int h= height >> (s.spatial_decomposition_count-level); + int stride= width << (s.spatial_decomposition_count-level); + DWTELEM *buf= buffer[0]; + int64_t error=0; + + if(orientation&1) buf+=w; + if(orientation>1) buf+=stride>>1; + + memset(buffer[0], 0, sizeof(int)*width*height); + buf[w/2 + h/2*stride]= 256*256; + ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); + for(y=0; y> (s.spatial_decomposition_count-level); + //int h= height >> (s.spatial_decomposition_count-level); + int stride= width << (s.spatial_decomposition_count-level); + DWTELEM *buf= buffer[0]; + int64_t error=0; + + buf+=w; + buf+=stride>>1; + + memset(buffer[0], 0, sizeof(int)*width*height); + for(y=0; y2 channels support + * - more decorrelation types + * - more tap_quant tests + * - selectable intlist writers/readers (bonk-style, golomb, cabac) + */ + +#define MAX_CHANNELS 2 + +#define MID_SIDE 0 +#define LEFT_SIDE 1 +#define RIGHT_SIDE 2 + +typedef struct SonicContext { + AVFrame frame; + int lossless, decorrelation; + + int num_taps, downsampling; + double quantization; + + int channels, samplerate, block_align, frame_size; + + int *tap_quant; + int *int_samples; + int *coded_samples[MAX_CHANNELS]; + + // for encoding + int *tail; + int tail_size; + int *window; + int window_size; + + // for decoding + int *predictor_k; + int *predictor_state[MAX_CHANNELS]; +} SonicContext; + +#define LATTICE_SHIFT 10 +#define SAMPLE_SHIFT 4 +#define LATTICE_FACTOR (1 << LATTICE_SHIFT) +#define SAMPLE_FACTOR (1 << SAMPLE_SHIFT) + +#define BASE_QUANT 0.6 +#define RATE_VARIATION 3.0 + +static inline int divide(int a, int b) +{ + if (a < 0) + return -( (-a + b/2)/b ); + else + return (a + b/2)/b; +} + +static inline int shift(int a,int b) +{ + return (a+(1<<(b-1))) >> b; +} + +static inline int shift_down(int a,int b) +{ + return (a>>b)+((a<0)?1:0); +} + +#if 1 +static inline int intlist_write(PutBitContext *pb, int *buf, int entries, int base_2_part) +{ + int i; + + for (i = 0; i < entries; i++) + set_se_golomb(pb, buf[i]); + + return 1; +} + +static inline int intlist_read(GetBitContext *gb, int *buf, int entries, int base_2_part) +{ + int i; + + for (i = 0; i < entries; i++) + buf[i] = get_se_golomb(gb); + + return 1; +} + +#else + +#define ADAPT_LEVEL 8 + +static int bits_to_store(uint64_t x) +{ + int res = 0; + + while(x) + { + res++; + x >>= 1; + } + return res; +} + +static void write_uint_max(PutBitContext *pb, unsigned int value, unsigned int max) +{ + int i, bits; + + if (!max) + return; + + bits = bits_to_store(max); + + for (i = 0; i < bits-1; i++) + put_bits(pb, 1, value & (1 << i)); + + if ( (value | (1 << (bits-1))) <= max) + put_bits(pb, 1, value & (1 << (bits-1))); +} + +static unsigned int read_uint_max(GetBitContext *gb, int max) +{ + int i, bits, value = 0; + + if (!max) + return 0; + + bits = bits_to_store(max); + + for (i = 0; i < bits-1; i++) + if (get_bits1(gb)) + value += 1 << i; + + if ( (value | (1<<(bits-1))) <= max) + if (get_bits1(gb)) + value += 1 << (bits-1); + + return value; +} + +static int intlist_write(PutBitContext *pb, int *buf, int entries, int base_2_part) +{ + int i, j, x = 0, low_bits = 0, max = 0; + int step = 256, pos = 0, dominant = 0, any = 0; + int *copy, *bits; + + copy = av_mallocz(4* entries); + if (!copy) + return -1; + + if (base_2_part) + { + int energy = 0; + + for (i = 0; i < entries; i++) + energy += abs(buf[i]); + + low_bits = bits_to_store(energy / (entries * 2)); + if (low_bits > 15) + low_bits = 15; + + put_bits(pb, 4, low_bits); + } + + for (i = 0; i < entries; i++) + { + put_bits(pb, low_bits, abs(buf[i])); + copy[i] = abs(buf[i]) >> low_bits; + if (copy[i] > max) + max = abs(copy[i]); + } + + bits = av_mallocz(4* entries*max); + if (!bits) + { +// av_free(copy); + return -1; + } + + for (i = 0; i <= max; i++) + { + for (j = 0; j < entries; j++) + if (copy[j] >= i) + bits[x++] = copy[j] > i; + } + + // store bitstream + while (pos < x) + { + int steplet = step >> 8; + + if (pos + steplet > x) + steplet = x - pos; + + for (i = 0; i < steplet; i++) + if (bits[i+pos] != dominant) + any = 1; + + put_bits(pb, 1, any); + + if (!any) + { + pos += steplet; + step += step / ADAPT_LEVEL; + } + else + { + int interloper = 0; + + while (((pos + interloper) < x) && (bits[pos + interloper] == dominant)) + interloper++; + + // note change + write_uint_max(pb, interloper, (step >> 8) - 1); + + pos += interloper + 1; + step -= step / ADAPT_LEVEL; + } + + if (step < 256) + { + step = 65536 / step; + dominant = !dominant; + } + } + + // store signs + for (i = 0; i < entries; i++) + if (buf[i]) + put_bits(pb, 1, buf[i] < 0); + +// av_free(bits); +// av_free(copy); + + return 0; +} + +static int intlist_read(GetBitContext *gb, int *buf, int entries, int base_2_part) +{ + int i, low_bits = 0, x = 0; + int n_zeros = 0, step = 256, dominant = 0; + int pos = 0, level = 0; + int *bits = av_mallocz(4* entries); + + if (!bits) + return -1; + + if (base_2_part) + { + low_bits = get_bits(gb, 4); + + if (low_bits) + for (i = 0; i < entries; i++) + buf[i] = get_bits(gb, low_bits); + } + +// av_log(NULL, AV_LOG_INFO, "entries: %d, low bits: %d\n", entries, low_bits); + + while (n_zeros < entries) + { + int steplet = step >> 8; + + if (!get_bits1(gb)) + { + for (i = 0; i < steplet; i++) + bits[x++] = dominant; + + if (!dominant) + n_zeros += steplet; + + step += step / ADAPT_LEVEL; + } + else + { + int actual_run = read_uint_max(gb, steplet-1); + +// av_log(NULL, AV_LOG_INFO, "actual run: %d\n", actual_run); + + for (i = 0; i < actual_run; i++) + bits[x++] = dominant; + + bits[x++] = !dominant; + + if (!dominant) + n_zeros += actual_run; + else + n_zeros++; + + step -= step / ADAPT_LEVEL; + } + + if (step < 256) + { + step = 65536 / step; + dominant = !dominant; + } + } + + // reconstruct unsigned values + n_zeros = 0; + for (i = 0; n_zeros < entries; i++) + { + while(1) + { + if (pos >= entries) + { + pos = 0; + level += 1 << low_bits; + } + + if (buf[pos] >= level) + break; + + pos++; + } + + if (bits[i]) + buf[pos] += 1 << low_bits; + else + n_zeros++; + + pos++; + } +// av_free(bits); + + // read signs + for (i = 0; i < entries; i++) + if (buf[i] && get_bits1(gb)) + buf[i] = -buf[i]; + +// av_log(NULL, AV_LOG_INFO, "zeros: %d pos: %d\n", n_zeros, pos); + + return 0; +} +#endif + +static void predictor_init_state(int *k, int *state, int order) +{ + int i; + + for (i = order-2; i >= 0; i--) + { + int j, p, x = state[i]; + + for (j = 0, p = i+1; p < order; j++,p++) + { + int tmp = x + shift_down(k[j] * state[p], LATTICE_SHIFT); + state[p] += shift_down(k[j]*x, LATTICE_SHIFT); + x = tmp; + } + } +} + +static int predictor_calc_error(int *k, int *state, int order, int error) +{ + int i, x = error - shift_down(k[order-1] * state[order-1], LATTICE_SHIFT); + +#if 1 + int *k_ptr = &(k[order-2]), + *state_ptr = &(state[order-2]); + for (i = order-2; i >= 0; i--, k_ptr--, state_ptr--) + { + int k_value = *k_ptr, state_value = *state_ptr; + x -= shift_down(k_value * state_value, LATTICE_SHIFT); + state_ptr[1] = state_value + shift_down(k_value * x, LATTICE_SHIFT); + } +#else + for (i = order-2; i >= 0; i--) + { + x -= shift_down(k[i] * state[i], LATTICE_SHIFT); + state[i+1] = state[i] + shift_down(k[i] * x, LATTICE_SHIFT); + } +#endif + + // don't drift too far, to avoid overflows + if (x > (SAMPLE_FACTOR<<16)) x = (SAMPLE_FACTOR<<16); + if (x < -(SAMPLE_FACTOR<<16)) x = -(SAMPLE_FACTOR<<16); + + state[0] = x; + + return x; +} + +#if CONFIG_SONIC_ENCODER || CONFIG_SONIC_LS_ENCODER +// Heavily modified Levinson-Durbin algorithm which +// copes better with quantization, and calculates the +// actual whitened result as it goes. + +static void modified_levinson_durbin(int *window, int window_entries, + int *out, int out_entries, int channels, int *tap_quant) +{ + int i; + int *state = av_mallocz(4* window_entries); + + memcpy(state, window, 4* window_entries); + + for (i = 0; i < out_entries; i++) + { + int step = (i+1)*channels, k, j; + double xx = 0.0, xy = 0.0; +#if 1 + int *x_ptr = &(window[step]), *state_ptr = &(state[0]); + j = window_entries - step; + for (;j>=0;j--,x_ptr++,state_ptr++) + { + double x_value = *x_ptr, state_value = *state_ptr; + xx += state_value*state_value; + xy += x_value*state_value; + } +#else + for (j = 0; j <= (window_entries - step); j++); + { + double stepval = window[step+j], stateval = window[j]; +// xx += (double)window[j]*(double)window[j]; +// xy += (double)window[step+j]*(double)window[j]; + xx += stateval*stateval; + xy += stepval*stateval; + } +#endif + if (xx == 0.0) + k = 0; + else + k = (int)(floor(-xy/xx * (double)LATTICE_FACTOR / (double)(tap_quant[i]) + 0.5)); + + if (k > (LATTICE_FACTOR/tap_quant[i])) + k = LATTICE_FACTOR/tap_quant[i]; + if (-k > (LATTICE_FACTOR/tap_quant[i])) + k = -(LATTICE_FACTOR/tap_quant[i]); + + out[i] = k; + k *= tap_quant[i]; + +#if 1 + x_ptr = &(window[step]); + state_ptr = &(state[0]); + j = window_entries - step; + for (;j>=0;j--,x_ptr++,state_ptr++) + { + int x_value = *x_ptr, state_value = *state_ptr; + *x_ptr = x_value + shift_down(k*state_value,LATTICE_SHIFT); + *state_ptr = state_value + shift_down(k*x_value, LATTICE_SHIFT); + } +#else + for (j=0; j <= (window_entries - step); j++) + { + int stepval = window[step+j], stateval=state[j]; + window[step+j] += shift_down(k * stateval, LATTICE_SHIFT); + state[j] += shift_down(k * stepval, LATTICE_SHIFT); + } +#endif + } + + av_free(state); +} + +static inline int code_samplerate(int samplerate) +{ + switch (samplerate) + { + case 44100: return 0; + case 22050: return 1; + case 11025: return 2; + case 96000: return 3; + case 48000: return 4; + case 32000: return 5; + case 24000: return 6; + case 16000: return 7; + case 8000: return 8; + } + return -1; +} + +static av_cold int sonic_encode_init(AVCodecContext *avctx) +{ + SonicContext *s = avctx->priv_data; + PutBitContext pb; + int i, version = 0; + + if (avctx->channels > MAX_CHANNELS) + { + av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n"); + return -1; /* only stereo or mono for now */ + } + + if (avctx->channels == 2) + s->decorrelation = MID_SIDE; + + if (avctx->codec->id == AV_CODEC_ID_SONIC_LS) + { + s->lossless = 1; + s->num_taps = 32; + s->downsampling = 1; + s->quantization = 0.0; + } + else + { + s->num_taps = 128; + s->downsampling = 2; + s->quantization = 1.0; + } + + // max tap 2048 + if ((s->num_taps < 32) || (s->num_taps > 1024) || + ((s->num_taps>>5)<<5 != s->num_taps)) + { + av_log(avctx, AV_LOG_ERROR, "Invalid number of taps\n"); + return -1; + } + + // generate taps + s->tap_quant = av_mallocz(4* s->num_taps); + for (i = 0; i < s->num_taps; i++) + s->tap_quant[i] = (int)(sqrt(i+1)); + + s->channels = avctx->channels; + s->samplerate = avctx->sample_rate; + + s->block_align = (int)(2048.0*s->samplerate/44100)/s->downsampling; + s->frame_size = s->channels*s->block_align*s->downsampling; + + s->tail_size = s->num_taps*s->channels; + s->tail = av_mallocz(4 * s->tail_size); + if (!s->tail) + return -1; + + s->predictor_k = av_mallocz(4 * s->num_taps); + if (!s->predictor_k) + return -1; + + for (i = 0; i < s->channels; i++) + { + s->coded_samples[i] = av_mallocz(4* s->block_align); + if (!s->coded_samples[i]) + return -1; + } + + s->int_samples = av_mallocz(4* s->frame_size); + + s->window_size = ((2*s->tail_size)+s->frame_size); + s->window = av_mallocz(4* s->window_size); + if (!s->window) + return -1; + + avctx->extradata = av_mallocz(16); + if (!avctx->extradata) + return -1; + init_put_bits(&pb, avctx->extradata, 16*8); + + put_bits(&pb, 2, version); // version + if (version == 1) + { + put_bits(&pb, 2, s->channels); + put_bits(&pb, 4, code_samplerate(s->samplerate)); + } + put_bits(&pb, 1, s->lossless); + if (!s->lossless) + put_bits(&pb, 3, SAMPLE_SHIFT); // XXX FIXME: sample precision + put_bits(&pb, 2, s->decorrelation); + put_bits(&pb, 2, s->downsampling); + put_bits(&pb, 5, (s->num_taps >> 5)-1); // 32..1024 + put_bits(&pb, 1, 0); // XXX FIXME: no custom tap quant table + + flush_put_bits(&pb); + avctx->extradata_size = put_bits_count(&pb)/8; + + av_log(avctx, AV_LOG_INFO, "Sonic: ver: %d ls: %d dr: %d taps: %d block: %d frame: %d downsamp: %d\n", + version, s->lossless, s->decorrelation, s->num_taps, s->block_align, s->frame_size, s->downsampling); + + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + avctx->coded_frame->key_frame = 1; + avctx->frame_size = s->block_align*s->downsampling; + + return 0; +} + +static av_cold int sonic_encode_close(AVCodecContext *avctx) +{ + SonicContext *s = avctx->priv_data; + int i; + + av_freep(&avctx->coded_frame); + + for (i = 0; i < s->channels; i++) + av_free(s->coded_samples[i]); + + av_free(s->predictor_k); + av_free(s->tail); + av_free(s->tap_quant); + av_free(s->window); + av_free(s->int_samples); + + return 0; +} + +static int sonic_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + SonicContext *s = avctx->priv_data; + PutBitContext pb; + int i, j, ch, quant = 0, x = 0; + int ret; + const short *samples = (const int16_t*)frame->data[0]; + + if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size * 5 + 1000)) < 0) + return ret; + + init_put_bits(&pb, avpkt->data, avpkt->size); + + // short -> internal + for (i = 0; i < s->frame_size; i++) + s->int_samples[i] = samples[i]; + + if (!s->lossless) + for (i = 0; i < s->frame_size; i++) + s->int_samples[i] = s->int_samples[i] << SAMPLE_SHIFT; + + switch(s->decorrelation) + { + case MID_SIDE: + for (i = 0; i < s->frame_size; i += s->channels) + { + s->int_samples[i] += s->int_samples[i+1]; + s->int_samples[i+1] -= shift(s->int_samples[i], 1); + } + break; + case LEFT_SIDE: + for (i = 0; i < s->frame_size; i += s->channels) + s->int_samples[i+1] -= s->int_samples[i]; + break; + case RIGHT_SIDE: + for (i = 0; i < s->frame_size; i += s->channels) + s->int_samples[i] -= s->int_samples[i+1]; + break; + } + + memset(s->window, 0, 4* s->window_size); + + for (i = 0; i < s->tail_size; i++) + s->window[x++] = s->tail[i]; + + for (i = 0; i < s->frame_size; i++) + s->window[x++] = s->int_samples[i]; + + for (i = 0; i < s->tail_size; i++) + s->window[x++] = 0; + + for (i = 0; i < s->tail_size; i++) + s->tail[i] = s->int_samples[s->frame_size - s->tail_size + i]; + + // generate taps + modified_levinson_durbin(s->window, s->window_size, + s->predictor_k, s->num_taps, s->channels, s->tap_quant); + if (intlist_write(&pb, s->predictor_k, s->num_taps, 0) < 0) + return -1; + + for (ch = 0; ch < s->channels; ch++) + { + x = s->tail_size+ch; + for (i = 0; i < s->block_align; i++) + { + int sum = 0; + for (j = 0; j < s->downsampling; j++, x += s->channels) + sum += s->window[x]; + s->coded_samples[ch][i] = sum; + } + } + + // simple rate control code + if (!s->lossless) + { + double energy1 = 0.0, energy2 = 0.0; + for (ch = 0; ch < s->channels; ch++) + { + for (i = 0; i < s->block_align; i++) + { + double sample = s->coded_samples[ch][i]; + energy2 += sample*sample; + energy1 += fabs(sample); + } + } + + energy2 = sqrt(energy2/(s->channels*s->block_align)); + energy1 = sqrt(2.0)*energy1/(s->channels*s->block_align); + + // increase bitrate when samples are like a gaussian distribution + // reduce bitrate when samples are like a two-tailed exponential distribution + + if (energy2 > energy1) + energy2 += (energy2-energy1)*RATE_VARIATION; + + quant = (int)(BASE_QUANT*s->quantization*energy2/SAMPLE_FACTOR); +// av_log(avctx, AV_LOG_DEBUG, "quant: %d energy: %f / %f\n", quant, energy1, energy2); + + if (quant < 1) + quant = 1; + if (quant > 65534) + quant = 65534; + + set_ue_golomb(&pb, quant); + + quant *= SAMPLE_FACTOR; + } + + // write out coded samples + for (ch = 0; ch < s->channels; ch++) + { + if (!s->lossless) + for (i = 0; i < s->block_align; i++) + s->coded_samples[ch][i] = divide(s->coded_samples[ch][i], quant); + + if (intlist_write(&pb, s->coded_samples[ch], s->block_align, 1) < 0) + return -1; + } + +// av_log(avctx, AV_LOG_DEBUG, "used bytes: %d\n", (put_bits_count(&pb)+7)/8); + + flush_put_bits(&pb); + avpkt->size = (put_bits_count(&pb)+7)/8; + *got_packet_ptr = 1; + return 0; +} +#endif /* CONFIG_SONIC_ENCODER || CONFIG_SONIC_LS_ENCODER */ + +#if CONFIG_SONIC_DECODER +static const int samplerate_table[] = + { 44100, 22050, 11025, 96000, 48000, 32000, 24000, 16000, 8000 }; + +static av_cold int sonic_decode_init(AVCodecContext *avctx) +{ + SonicContext *s = avctx->priv_data; + GetBitContext gb; + int i, version; + + s->channels = avctx->channels; + s->samplerate = avctx->sample_rate; + + avcodec_get_frame_defaults(&s->frame); + avctx->coded_frame = &s->frame; + + if (!avctx->extradata) + { + av_log(avctx, AV_LOG_ERROR, "No mandatory headers present\n"); + return -1; + } + + init_get_bits(&gb, avctx->extradata, avctx->extradata_size); + + version = get_bits(&gb, 2); + if (version > 1) + { + av_log(avctx, AV_LOG_ERROR, "Unsupported Sonic version, please report\n"); + return -1; + } + + if (version == 1) + { + s->channels = get_bits(&gb, 2); + s->samplerate = samplerate_table[get_bits(&gb, 4)]; + av_log(avctx, AV_LOG_INFO, "Sonicv2 chans: %d samprate: %d\n", + s->channels, s->samplerate); + } + + if (s->channels > MAX_CHANNELS) + { + av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n"); + return -1; + } + + s->lossless = get_bits1(&gb); + if (!s->lossless) + skip_bits(&gb, 3); // XXX FIXME + s->decorrelation = get_bits(&gb, 2); + + s->downsampling = get_bits(&gb, 2); + if (!s->downsampling) { + av_log(avctx, AV_LOG_ERROR, "invalid downsampling value\n"); + return AVERROR_INVALIDDATA; + } + + s->num_taps = (get_bits(&gb, 5)+1)<<5; + if (get_bits1(&gb)) // XXX FIXME + av_log(avctx, AV_LOG_INFO, "Custom quant table\n"); + + s->block_align = (int)(2048.0*s->samplerate/44100)/s->downsampling; + s->frame_size = s->channels*s->block_align*s->downsampling; +// avctx->frame_size = s->block_align; + + av_log(avctx, AV_LOG_INFO, "Sonic: ver: %d ls: %d dr: %d taps: %d block: %d frame: %d downsamp: %d\n", + version, s->lossless, s->decorrelation, s->num_taps, s->block_align, s->frame_size, s->downsampling); + + // generate taps + s->tap_quant = av_mallocz(4* s->num_taps); + for (i = 0; i < s->num_taps; i++) + s->tap_quant[i] = (int)(sqrt(i+1)); + + s->predictor_k = av_mallocz(4* s->num_taps); + + for (i = 0; i < s->channels; i++) + { + s->predictor_state[i] = av_mallocz(4* s->num_taps); + if (!s->predictor_state[i]) + return -1; + } + + for (i = 0; i < s->channels; i++) + { + s->coded_samples[i] = av_mallocz(4* s->block_align); + if (!s->coded_samples[i]) + return -1; + } + s->int_samples = av_mallocz(4* s->frame_size); + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + return 0; +} + +static av_cold int sonic_decode_close(AVCodecContext *avctx) +{ + SonicContext *s = avctx->priv_data; + int i; + + av_free(s->int_samples); + av_free(s->tap_quant); + av_free(s->predictor_k); + + for (i = 0; i < s->channels; i++) + { + av_free(s->predictor_state[i]); + av_free(s->coded_samples[i]); + } + + return 0; +} + +static int sonic_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame_ptr, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + SonicContext *s = avctx->priv_data; + GetBitContext gb; + int i, quant, ch, j, ret; + int16_t *samples; + + if (buf_size == 0) return 0; + + s->frame.nb_samples = s->frame_size; + if ((ret = ff_get_buffer(avctx, &s->frame, 0)) < 0) + return ret; + samples = (int16_t *)s->frame.data[0]; + +// av_log(NULL, AV_LOG_INFO, "buf_size: %d\n", buf_size); + + init_get_bits(&gb, buf, buf_size*8); + + intlist_read(&gb, s->predictor_k, s->num_taps, 0); + + // dequantize + for (i = 0; i < s->num_taps; i++) + s->predictor_k[i] *= s->tap_quant[i]; + + if (s->lossless) + quant = 1; + else + quant = get_ue_golomb(&gb) * SAMPLE_FACTOR; + +// av_log(NULL, AV_LOG_INFO, "quant: %d\n", quant); + + for (ch = 0; ch < s->channels; ch++) + { + int x = ch; + + predictor_init_state(s->predictor_k, s->predictor_state[ch], s->num_taps); + + intlist_read(&gb, s->coded_samples[ch], s->block_align, 1); + + for (i = 0; i < s->block_align; i++) + { + for (j = 0; j < s->downsampling - 1; j++) + { + s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, 0); + x += s->channels; + } + + s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, s->coded_samples[ch][i] * quant); + x += s->channels; + } + + for (i = 0; i < s->num_taps; i++) + s->predictor_state[ch][i] = s->int_samples[s->frame_size - s->channels + ch - i*s->channels]; + } + + switch(s->decorrelation) + { + case MID_SIDE: + for (i = 0; i < s->frame_size; i += s->channels) + { + s->int_samples[i+1] += shift(s->int_samples[i], 1); + s->int_samples[i] -= s->int_samples[i+1]; + } + break; + case LEFT_SIDE: + for (i = 0; i < s->frame_size; i += s->channels) + s->int_samples[i+1] += s->int_samples[i]; + break; + case RIGHT_SIDE: + for (i = 0; i < s->frame_size; i += s->channels) + s->int_samples[i] += s->int_samples[i+1]; + break; + } + + if (!s->lossless) + for (i = 0; i < s->frame_size; i++) + s->int_samples[i] = shift(s->int_samples[i], SAMPLE_SHIFT); + + // internal -> short + for (i = 0; i < s->frame_size; i++) + samples[i] = av_clip_int16(s->int_samples[i]); + + align_get_bits(&gb); + + *got_frame_ptr = 1; + *(AVFrame*)data = s->frame; + + return (get_bits_count(&gb)+7)/8; +} + +AVCodec ff_sonic_decoder = { + .name = "sonic", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SONIC, + .priv_data_size = sizeof(SonicContext), + .init = sonic_decode_init, + .close = sonic_decode_close, + .decode = sonic_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_EXPERIMENTAL, + .long_name = NULL_IF_CONFIG_SMALL("Sonic"), +}; +#endif /* CONFIG_SONIC_DECODER */ + +#if CONFIG_SONIC_ENCODER +AVCodec ff_sonic_encoder = { + .name = "sonic", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SONIC, + .priv_data_size = sizeof(SonicContext), + .init = sonic_encode_init, + .encode2 = sonic_encode_frame, + .capabilities = CODEC_CAP_EXPERIMENTAL, + .close = sonic_encode_close, + .long_name = NULL_IF_CONFIG_SMALL("Sonic"), +}; +#endif + +#if CONFIG_SONIC_LS_ENCODER +AVCodec ff_sonic_ls_encoder = { + .name = "sonicls", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_SONIC_LS, + .priv_data_size = sizeof(SonicContext), + .init = sonic_encode_init, + .encode2 = sonic_encode_frame, + .capabilities = CODEC_CAP_EXPERIMENTAL, + .close = sonic_encode_close, + .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), +}; +#endif diff --git a/ffmpeg/libavcodec/sp5x.h b/ffmpeg/libavcodec/sp5x.h new file mode 100644 index 0000000..004fcbb --- /dev/null +++ b/ffmpeg/libavcodec/sp5x.h @@ -0,0 +1,238 @@ +/* + * Sunplus JPEG tables + * Copyright (c) 2003 the ffmpeg project + * + * 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 + */ + +#ifndef AVCODEC_SP5X_H +#define AVCODEC_SP5X_H + +#include + +static const uint8_t sp5x_data_sof[] = +{ + 0xFF, 0xC0, /* SOF */ + 0x00, 0x11, /* len */ + 0x08, /* bits */ + 0x00, 0xf0, /* height (default: 240) */ + 0x01, 0x40, /* width (default: 240) */ + 0x03, /* nb components */ + 0x01, 0x22, 0x00, /* 21 vs 22 ? */ + 0x02, 0x11, 0x01, + 0x03, 0x11, 0x01 +}; + +static const uint8_t sp5x_data_sos[] = +{ + 0xFF, 0xDA, /* SOS */ + 0x00, 0x0C, /* len */ + 0x03, /* nb components */ + 0x01, 0x00, + 0x02, 0x11, + 0x03, 0x11, + 0x00, /* Ss */ + 0x3F, /* Se */ + 0x00 /* Ah/Al */ +}; + +static const uint8_t sp5x_data_dqt[] = +{ + 0xFF, 0xDB, /* DQT */ + 0x00, 0x84, /* len */ + 0x00, + 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, + 0x04, 0x04, 0x06, 0x05, 0x05, 0x06, 0x08, 0x0D, + 0x08, 0x08, 0x07, 0x07, 0x08, 0x10, 0x0C, 0x0C, + 0x0A, 0x0D, 0x14, 0x11, 0x15, 0x14, 0x13, 0x11, + 0x13, 0x13, 0x16, 0x18, 0x1F, 0x1A, 0x16, 0x17, + 0x1E, 0x17, 0x13, 0x13, 0x1B, 0x25, 0x1C, 0x1E, + 0x20, 0x21, 0x23, 0x23, 0x23, 0x15, 0x1A, 0x27, + 0x29, 0x26, 0x22, 0x29, 0x1F, 0x22, 0x23, 0x22, + 0x01, + 0x05, 0x06, 0x06, 0x08, 0x07, 0x08, 0x10, 0x08, + 0x08, 0x10, 0x22, 0x16, 0x13, 0x16, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 +}; + +static const uint8_t sp5x_data_dht[] = { + 0xFF, 0xC4, /* DHT */ + 0x01, 0xA2, /* len */ + 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, + 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, + 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, + 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, + 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, + 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, + 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, + 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, + 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, + 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, + 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, + 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, + 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x11, 0x00, 0x02, + 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, + 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, + 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, + 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, + 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, + 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, + 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, + 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, + 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, + 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, + 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, + 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, + 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, + 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA +}; + + +static const uint8_t sp5x_quant_table[20][64]= +{ + /* index 0, Q50 */ + { 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, + 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, + 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80,109, 81, 87, + 95, 98,103,104,103, 62, 77,113,121,112,100,120, 92,101,103, 99 }, + { 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }, + + /* index 1, Q70 */ + { 10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24, + 16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31, + 34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52, + 57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59 }, + { 10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59 }, + + /* index 2, Q80 */ + { 6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16, + 10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20, + 22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35, + 38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40 }, + { 7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 }, + + /* index 3, Q85 */ + { 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12, + 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15, + 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26, + 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30 }, + { 5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + + /* index 4, Q90 */ + { 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 4, 3, 3, 4, 5, 8, + 5, 5, 4, 4, 5, 10, 7, 7, 6, 8, 12, 10, 12, 12, 11, 10, + 11, 11, 13, 14, 18, 16, 13, 14, 17, 14, 11, 11, 16, 22, 16, 17, + 19, 20, 21, 21, 21, 12, 15, 23, 24, 22, 20, 24, 18, 20, 21, 20 }, + { 3, 4, 4, 5, 4, 5, 9, 5, 5, 9, 20, 13, 11, 13, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 }, + + /* index 5, Q60 */ + { 13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32, + 21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41, + 45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70, + 76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79 }, + { 14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79 }, + + /* index 6, Q25 */ + { 32, 22, 24, 28, 24, 20, 32, 28, 26, 28, 36, 34, 32, 38, 48, 80, + 52, 48, 44, 44, 48, 98, 70, 74, 58, 80,116,102,122,120,114,102, + 112,110,128,144,184,156,128,136,174,138,110,112,160,218,162,174, + 190,196,206,208,206,124,154,226,242,224,200,240,184,202,206,198 }, + { 34, 36, 36, 48, 42, 48, 94, 52, 52, 94,198,132,112,132,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198 }, + + /* index 7, Q95 */ + { 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 4, + 3, 2, 2, 2, 2, 5, 4, 4, 3, 4, 6, 5, 6, 6, 6, 5, + 6, 6, 6, 7, 9, 8, 6, 7, 9, 7, 6, 6, 8, 11, 8, 9, + 10, 10, 10, 10, 10, 6, 8, 11, 12, 11, 10, 12, 9, 10, 10, 10 }, + { 2, 2, 2, 2, 2, 2, 5, 3, 3, 5, 10, 7, 6, 7, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, + + /* index 8, Q93 */ + { 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 2, 2, 3, 3, 6, + 4, 3, 3, 3, 3, 7, 5, 5, 4, 6, 8, 7, 9, 8, 8, 7, + 8, 8, 9, 10, 13, 11, 9, 10, 12, 10, 8, 8, 11, 15, 11, 12, + 13, 14, 14, 15, 14, 9, 11, 16, 17, 16, 14, 17, 13, 14, 14, 14 }, + { 2, 3, 3, 3, 3, 3, 7, 4, 4, 7, 14, 9, 8, 9, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }, + + /* index 9, Q40 */ + { 20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50, + 33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64, + 70, 69, 80, 90,115, 98, 80, 85,109, 86, 69, 70,100,136,101,109, + 119,123,129,130,129, 78, 96,141,151,140,125,150,115,126,129,124 }, + { 21, 23, 23, 30, 26, 30, 59, 33, 33, 59,124, 83, 70, 83,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124 } +}; + +#endif /* AVCODEC_SP5X_H */ diff --git a/ffmpeg/libavcodec/sp5xdec.c b/ffmpeg/libavcodec/sp5xdec.c new file mode 100644 index 0000000..b083015 --- /dev/null +++ b/ffmpeg/libavcodec/sp5xdec.c @@ -0,0 +1,121 @@ +/* + * Sunplus JPEG decoder (SP5X) + * Copyright (c) 2003 Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * Sunplus JPEG decoder (SP5X). + */ + +#include "avcodec.h" +#include "mjpeg.h" +#include "mjpegdec.h" +#include "sp5x.h" + + +static int sp5x_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVPacket avpkt_recoded; + const int qscale = 5; + uint8_t *recoded; + int i = 0, j = 0; + + if (!avctx->width || !avctx->height) + return -1; + + recoded = av_mallocz(buf_size + 1024); + if (!recoded) + return -1; + + /* SOI */ + recoded[j++] = 0xFF; + recoded[j++] = 0xD8; + + memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt)); + memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64); + memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64); + j += sizeof(sp5x_data_dqt); + + memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht)); + j += sizeof(sp5x_data_dht); + + memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof)); + AV_WB16(recoded+j+5, avctx->coded_height); + AV_WB16(recoded+j+7, avctx->coded_width); + j += sizeof(sp5x_data_sof); + + memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos)); + j += sizeof(sp5x_data_sos); + + if(avctx->codec_id==AV_CODEC_ID_AMV) + for (i = 2; i < buf_size-2 && j < buf_size+1024-2; i++) + recoded[j++] = buf[i]; + else + for (i = 14; i < buf_size && j < buf_size+1024-3; i++) + { + recoded[j++] = buf[i]; + if (buf[i] == 0xff) + recoded[j++] = 0; + } + + /* EOI */ + recoded[j++] = 0xFF; + recoded[j++] = 0xD9; + + av_init_packet(&avpkt_recoded); + avpkt_recoded.data = recoded; + avpkt_recoded.size = j; + i = ff_mjpeg_decode_frame(avctx, data, got_frame, &avpkt_recoded); + + av_free(recoded); + + return i < 0 ? i : avpkt->size; +} + +#if CONFIG_SP5X_DECODER +AVCodec ff_sp5x_decoder = { + .name = "sp5x", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SP5X, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = sp5x_decode_frame, + .capabilities = CODEC_CAP_DR1, + .max_lowres = 3, + .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), +}; +#endif +#if CONFIG_AMV_DECODER +AVCodec ff_amv_decoder = { + .name = "amv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AMV, + .priv_data_size = sizeof(MJpegDecodeContext), + .init = ff_mjpeg_decode_init, + .close = ff_mjpeg_decode_end, + .decode = sp5x_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), +}; +#endif diff --git a/ffmpeg/libavcodec/sparc/Makefile b/ffmpeg/libavcodec/sparc/Makefile new file mode 100644 index 0000000..aeb0f47 --- /dev/null +++ b/ffmpeg/libavcodec/sparc/Makefile @@ -0,0 +1,4 @@ +VIS-OBJS += sparc/dsputil_vis.o \ + sparc/simple_idct_vis.o \ + +VIS-OBJS-$(CONFIG_HPELDSP) += sparc/hpeldsp_vis.o diff --git a/ffmpeg/libavcodec/sparc/dsputil_vis.c b/ffmpeg/libavcodec/sparc/dsputil_vis.c new file mode 100644 index 0000000..9c3494b --- /dev/null +++ b/ffmpeg/libavcodec/sparc/dsputil_vis.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2003 David S. Miller + * + * 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 + */ + +/* The *no_round* functions have been added by James A. Morrison, 2003,2004. + The vis code from libmpeg2 was adapted for libavcodec by James A. Morrison. + */ + +#include "config.h" + +#include + +#include "libavutil/attributes.h" +#include "libavcodec/dsputil.h" +#include "libavutil/mem.h" +#include "dsputil_vis.h" + +#include "vis.h" + +#define ACCEL_SPARC_VIS 1 +#define ACCEL_SPARC_VIS2 2 + +static int vis_level(void) +{ + int accel = 0; + accel |= ACCEL_SPARC_VIS; + accel |= ACCEL_SPARC_VIS2; + return accel; +} + +/* libavcodec initialization code */ +av_cold void ff_dsputil_init_vis(DSPContext *c, AVCodecContext *avctx) +{ + /* VIS-specific optimizations */ + int accel = vis_level (); + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + + if (accel & ACCEL_SPARC_VIS && !high_bit_depth) { + if (avctx->idct_algo == FF_IDCT_SIMPLEVIS) { + c->idct_put = ff_simple_idct_put_vis; + c->idct_add = ff_simple_idct_add_vis; + c->idct = ff_simple_idct_vis; + c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; + } + } +} diff --git a/ffmpeg/libavcodec/sparc/dsputil_vis.h b/ffmpeg/libavcodec/sparc/dsputil_vis.h new file mode 100644 index 0000000..d7e2e63 --- /dev/null +++ b/ffmpeg/libavcodec/sparc/dsputil_vis.h @@ -0,0 +1,28 @@ +/* + * 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 + */ + +#ifndef AVCODEC_SPARC_DSPUTIL_VIS_H +#define AVCODEC_SPARC_DSPUTIL_VIS_H + +#include + +void ff_simple_idct_put_vis(uint8_t *dest, int line_size, int16_t *data); +void ff_simple_idct_add_vis(uint8_t *dest, int line_size, int16_t *data); +void ff_simple_idct_vis(int16_t *data); + +#endif /* AVCODEC_SPARC_DSPUTIL_VIS_H */ diff --git a/ffmpeg/libavcodec/sparc/hpeldsp_vis.c b/ffmpeg/libavcodec/sparc/hpeldsp_vis.c new file mode 100644 index 0000000..da2d47e --- /dev/null +++ b/ffmpeg/libavcodec/sparc/hpeldsp_vis.c @@ -0,0 +1,3537 @@ +/* + * Copyright (C) 2003 David S. Miller + * + * 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 + */ + +/* The *no_round* functions have been added by James A. Morrison, 2003,2004. + The vis code from libmpeg2 was adapted for libavcodec by James A. Morrison. + */ + +#include "config.h" + +#include + +#include "libavcodec/hpeldsp.h" +#include "libavutil/mem.h" + +#include "vis.h" + +/* The trick used in some of this file is the formula from the MMX + * motion comp code, which is: + * + * (x+y+1)>>1 == (x|y)-((x^y)>>1) + * + * This allows us to average 8 bytes at a time in a 64-bit FPU reg. + * We avoid overflows by masking before we do the shift, and we + * implement the shift by multiplying by 1/2 using mul8x16. So in + * VIS this is (assume 'x' is in f0, 'y' is in f2, a repeating mask + * of '0xfe' is in f4, a repeating mask of '0x7f' is in f6, and + * the value 0x80808080 is in f8): + * + * fxor f0, f2, f10 + * fand f10, f4, f10 + * fmul8x16 f8, f10, f10 + * fand f10, f6, f10 + * for f0, f2, f12 + * fpsub16 f12, f10, f10 + */ + +#define DUP4(x) {x, x, x, x} +#define DUP8(x) {x, x, x, x, x, x, x, x} +DECLARE_ALIGNED(8, static const int16_t, constants1)[] = DUP4 (1); +DECLARE_ALIGNED(8, static const int16_t, constants2)[] = DUP4 (2); +DECLARE_ALIGNED(8, static const int16_t, constants3)[] = DUP4 (3); +DECLARE_ALIGNED(8, static const int16_t, constants6)[] = DUP4 (6); +DECLARE_ALIGNED(8, static const int8_t, constants_fe)[] = DUP8 (0xfe); +DECLARE_ALIGNED(8, static const int8_t, constants_7f)[] = DUP8 (0x7f); +DECLARE_ALIGNED(8, static const int8_t, constants128)[] = DUP8 (128); +DECLARE_ALIGNED(8, static const int16_t, constants256_512)[] = + {256, 512, 256, 512}; +DECLARE_ALIGNED(8, static const int16_t, constants256_1024)[] = + {256, 1024, 256, 1024}; + +#define REF_0 0 +#define REF_0_1 1 +#define REF_2 2 +#define REF_2_1 3 +#define REF_4 4 +#define REF_4_1 5 +#define REF_6 6 +#define REF_6_1 7 +#define REF_S0 8 +#define REF_S0_1 9 +#define REF_S2 10 +#define REF_S2_1 11 +#define REF_S4 12 +#define REF_S4_1 13 +#define REF_S6 14 +#define REF_S6_1 15 +#define DST_0 16 +#define DST_1 17 +#define DST_2 18 +#define DST_3 19 +#define CONST_1 20 +#define CONST_2 20 +#define CONST_3 20 +#define CONST_6 20 +#define MASK_fe 20 +#define CONST_128 22 +#define CONST_256 22 +#define CONST_512 22 +#define CONST_1024 22 +#define TMP0 24 +#define TMP1 25 +#define TMP2 26 +#define TMP3 27 +#define TMP4 28 +#define TMP5 29 +#define ZERO 30 +#define MASK_7f 30 + +#define TMP6 32 +#define TMP8 34 +#define TMP10 36 +#define TMP12 38 +#define TMP14 40 +#define TMP16 42 +#define TMP18 44 +#define TMP20 46 +#define TMP22 48 +#define TMP24 50 +#define TMP26 52 +#define TMP28 54 +#define TMP30 56 +#define TMP32 58 + +static void MC_put_o_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + do { /* 5 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + + vis_faligndata(TMP0, TMP2, REF_0); + vis_st64(REF_0, dest[0]); + + vis_faligndata(TMP2, TMP4, REF_2); + vis_st64_2(REF_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_put_o_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + do { /* 4 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + ref += stride; + + /* stall */ + + vis_faligndata(TMP0, TMP2, REF_0); + vis_st64(REF_0, dest[0]); + dest += stride; + } while (--height); +} + + +static void MC_avg_o_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + int stride_8 = stride + 8; + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(dest[0], DST_0); + + vis_ld64(dest[8], DST_2); + + vis_ld64(constants_fe[0], MASK_fe); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP2, TMP4, REF_2); + + vis_ld64(constants128[0], CONST_128); + + ref += stride; + height = (height >> 1) - 1; + + do { /* 24 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(DST_0, REF_0, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP6, MASK_fe, TMP6); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_xor(DST_2, REF_2, TMP8); + + vis_and(TMP8, MASK_fe, TMP8); + + vis_or(DST_0, REF_0, TMP10); + vis_ld64_2(dest, stride, DST_0); + vis_mul8x16(CONST_128, TMP8, TMP8); + + vis_or(DST_2, REF_2, TMP12); + vis_ld64_2(dest, stride_8, DST_2); + + vis_ld64(ref[0], TMP14); + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_psub16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_psub16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + + dest += stride; + vis_ld64_2(ref, 8, TMP16); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 16, TMP18); + vis_faligndata(TMP2, TMP4, REF_2); + ref += stride; + + vis_xor(DST_0, REF_0, TMP20); + + vis_and(TMP20, MASK_fe, TMP20); + + vis_xor(DST_2, REF_2, TMP22); + vis_mul8x16(CONST_128, TMP20, TMP20); + + vis_and(TMP22, MASK_fe, TMP22); + + vis_or(DST_0, REF_0, TMP24); + vis_mul8x16(CONST_128, TMP22, TMP22); + + vis_or(DST_2, REF_2, TMP26); + + vis_ld64_2(dest, stride, DST_0); + vis_faligndata(TMP14, TMP16, REF_0); + + vis_ld64_2(dest, stride_8, DST_2); + vis_faligndata(TMP16, TMP18, REF_2); + + vis_and(TMP20, MASK_7f, TMP20); + + vis_and(TMP22, MASK_7f, TMP22); + + vis_psub16(TMP24, TMP20, TMP20); + vis_st64(TMP20, dest[0]); + + vis_psub16(TMP26, TMP22, TMP22); + vis_st64_2(TMP22, dest, 8); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(DST_0, REF_0, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP6, MASK_fe, TMP6); + + vis_ld64_2(ref, 16, TMP4); + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_xor(DST_2, REF_2, TMP8); + + vis_and(TMP8, MASK_fe, TMP8); + + vis_or(DST_0, REF_0, TMP10); + vis_ld64_2(dest, stride, DST_0); + vis_mul8x16(CONST_128, TMP8, TMP8); + + vis_or(DST_2, REF_2, TMP12); + vis_ld64_2(dest, stride_8, DST_2); + + vis_ld64(ref[0], TMP14); + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_psub16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_psub16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + + dest += stride; + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_2); + + vis_xor(DST_0, REF_0, TMP20); + + vis_and(TMP20, MASK_fe, TMP20); + + vis_xor(DST_2, REF_2, TMP22); + vis_mul8x16(CONST_128, TMP20, TMP20); + + vis_and(TMP22, MASK_fe, TMP22); + + vis_or(DST_0, REF_0, TMP24); + vis_mul8x16(CONST_128, TMP22, TMP22); + + vis_or(DST_2, REF_2, TMP26); + + vis_and(TMP20, MASK_7f, TMP20); + + vis_and(TMP22, MASK_7f, TMP22); + + vis_psub16(TMP24, TMP20, TMP20); + vis_st64(TMP20, dest[0]); + + vis_psub16(TMP26, TMP22, TMP22); + vis_st64_2(TMP22, dest, 8); +} + +static void MC_avg_o_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_ld64(dest[0], DST_0); + + vis_ld64(constants_fe[0], MASK_fe); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants128[0], CONST_128); + + ref += stride; + height = (height >> 1) - 1; + + do { /* 12 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(DST_0, REF_0, TMP4); + + vis_ld64(ref[8], TMP2); + vis_and(TMP4, MASK_fe, TMP4); + + vis_or(DST_0, REF_0, TMP6); + vis_ld64_2(dest, stride, DST_0); + ref += stride; + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_ld64(ref[0], TMP12); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(ref[8], TMP2); + vis_xor(DST_0, REF_0, TMP0); + ref += stride; + + vis_and(TMP0, MASK_fe, TMP0); + + vis_and(TMP4, MASK_7f, TMP4); + + vis_psub16(TMP6, TMP4, TMP4); + vis_st64(TMP4, dest[0]); + dest += stride; + vis_mul8x16(CONST_128, TMP0, TMP0); + + vis_or(DST_0, REF_0, TMP6); + vis_ld64_2(dest, stride, DST_0); + + vis_faligndata(TMP12, TMP2, REF_0); + + vis_and(TMP0, MASK_7f, TMP0); + + vis_psub16(TMP6, TMP0, TMP4); + vis_st64(TMP4, dest[0]); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(DST_0, REF_0, TMP4); + + vis_ld64(ref[8], TMP2); + vis_and(TMP4, MASK_fe, TMP4); + + vis_or(DST_0, REF_0, TMP6); + vis_ld64_2(dest, stride, DST_0); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_xor(DST_0, REF_0, TMP0); + + vis_and(TMP0, MASK_fe, TMP0); + + vis_and(TMP4, MASK_7f, TMP4); + + vis_psub16(TMP6, TMP4, TMP4); + vis_st64(TMP4, dest[0]); + dest += stride; + vis_mul8x16(CONST_128, TMP0, TMP0); + + vis_or(DST_0, REF_0, TMP6); + + vis_and(TMP0, MASK_7f, TMP0); + + vis_psub16(TMP6, TMP0, TMP4); + vis_st64(TMP4, dest[0]); +} + +static void MC_put_x_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64_2(ref, 16, TMP4); + + vis_ld64(constants_fe[0], MASK_fe); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants128[0], CONST_128); + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + ref += stride; + height = (height >> 1) - 1; + + do { /* 34 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP8); + + vis_ld64_2(ref, 16, TMP4); + vis_and(TMP6, MASK_fe, TMP6); + ref += stride; + + vis_ld64(ref[0], TMP14); + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_ld64_2(ref, 8, TMP16); + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_or(REF_0, REF_2, TMP10); + + vis_ld64_2(ref, 16, TMP18); + ref += stride; + vis_or(REF_4, REF_6, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_psub16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_psub16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + dest += stride; + + vis_xor(REF_0, REF_2, TMP6); + + vis_xor(REF_4, REF_6, TMP8); + + vis_and(TMP6, MASK_fe, TMP6); + + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_or(REF_0, REF_2, TMP10); + + vis_or(REF_4, REF_6, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP14, TMP16, REF_0); + + vis_faligndata(TMP16, TMP18, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP14, TMP16, REF_2); + vis_faligndata(TMP16, TMP18, REF_6); + } else { + vis_src1(TMP16, REF_2); + vis_src1(TMP18, REF_6); + } + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_psub16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_psub16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP8); + + vis_ld64_2(ref, 16, TMP4); + vis_and(TMP6, MASK_fe, TMP6); + + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_or(REF_0, REF_2, TMP10); + + vis_or(REF_4, REF_6, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_psub16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_psub16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + dest += stride; + + vis_xor(REF_0, REF_2, TMP6); + + vis_xor(REF_4, REF_6, TMP8); + + vis_and(TMP6, MASK_fe, TMP6); + + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_or(REF_0, REF_2, TMP10); + + vis_or(REF_4, REF_6, TMP12); + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_psub16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_psub16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); +} + +static void MC_put_x_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_ld64(constants_fe[0], MASK_fe); + + vis_ld64(constants_7f[0], MASK_7f); + + vis_ld64(constants128[0], CONST_128); + vis_faligndata(TMP0, TMP2, REF_0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + } else { + vis_src1(TMP2, REF_2); + } + + ref += stride; + height = (height >> 1) - 1; + + do { /* 20 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP4, MASK_fe, TMP4); + ref += stride; + + vis_ld64(ref[0], TMP8); + vis_or(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, 8, TMP10); + ref += stride; + vis_faligndata(TMP0, TMP2, REF_0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + } else { + vis_src1(TMP2, REF_2); + } + + vis_and(TMP4, MASK_7f, TMP4); + + vis_psub16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_or(REF_0, REF_2, TMP14); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_alignaddr_g0((void *)off); + vis_faligndata(TMP8, TMP10, REF_0); + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP8, TMP10, REF_2); + } else { + vis_src1(TMP10, REF_2); + } + + vis_and(TMP12, MASK_7f, TMP12); + + vis_psub16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP4, MASK_fe, TMP4); + + vis_or(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP0, TMP2, REF_0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + } else { + vis_src1(TMP2, REF_2); + } + + vis_and(TMP4, MASK_7f, TMP4); + + vis_psub16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_or(REF_0, REF_2, TMP14); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_psub16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; +} + +static void MC_avg_x_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + vis_ld64(constants3[0], CONST_3); + vis_fzero(ZERO); + vis_ld64(constants256_512[0], CONST_256); + + ref = vis_alignaddr(ref); + do { /* 26 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_alignaddr_g0((void *)off); + + vis_ld64(ref[16], TMP4); + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(dest[8], DST_2); + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + vis_mul8x16au(REF_0, CONST_256, TMP0); + + vis_pmerge(ZERO, REF_2, TMP4); + vis_mul8x16au(REF_0_1, CONST_256, TMP2); + + vis_pmerge(ZERO, REF_2_1, TMP6); + + vis_padd16(TMP0, TMP4, TMP0); + + vis_mul8x16al(DST_0, CONST_512, TMP4); + vis_padd16(TMP2, TMP6, TMP2); + + vis_mul8x16al(DST_1, CONST_512, TMP6); + + vis_mul8x16au(REF_6, CONST_256, TMP12); + + vis_padd16(TMP0, TMP4, TMP0); + vis_mul8x16au(REF_6_1, CONST_256, TMP14); + + vis_padd16(TMP2, TMP6, TMP2); + vis_mul8x16au(REF_4, CONST_256, TMP16); + + vis_padd16(TMP0, CONST_3, TMP8); + vis_mul8x16au(REF_4_1, CONST_256, TMP18); + + vis_padd16(TMP2, CONST_3, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_padd16(TMP16, TMP12, TMP0); + + vis_st64(DST_0, dest[0]); + vis_mul8x16al(DST_2, CONST_512, TMP4); + vis_padd16(TMP18, TMP14, TMP2); + + vis_mul8x16al(DST_3, CONST_512, TMP6); + vis_padd16(TMP0, CONST_3, TMP0); + + vis_padd16(TMP2, CONST_3, TMP2); + + vis_padd16(TMP0, TMP4, TMP0); + + vis_padd16(TMP2, TMP6, TMP2); + vis_pack16(TMP0, DST_2); + + vis_pack16(TMP2, DST_3); + vis_st64(DST_2, dest[8]); + + ref += stride; + dest += stride; + } while (--height); +} + +static void MC_avg_x_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_times_2 = stride << 1; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + vis_ld64(constants3[0], CONST_3); + vis_fzero(ZERO); + vis_ld64(constants256_512[0], CONST_256); + + ref = vis_alignaddr(ref); + height >>= 2; + do { /* 47 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + + vis_alignaddr_g0((void *)off); + + vis_ld64(ref[0], TMP4); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 8, TMP6); + ref += stride; + + vis_ld64(ref[0], TMP8); + + vis_ld64_2(ref, 8, TMP10); + ref += stride; + vis_faligndata(TMP4, TMP6, REF_4); + + vis_ld64(ref[0], TMP12); + + vis_ld64_2(ref, 8, TMP14); + ref += stride; + vis_faligndata(TMP8, TMP10, REF_S0); + + vis_faligndata(TMP12, TMP14, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP0, TMP2, REF_2); + + vis_ld64_2(dest, stride, DST_2); + vis_faligndata(TMP4, TMP6, REF_6); + + vis_faligndata(TMP8, TMP10, REF_S2); + + vis_faligndata(TMP12, TMP14, REF_S6); + } else { + vis_ld64(dest[0], DST_0); + vis_src1(TMP2, REF_2); + + vis_ld64_2(dest, stride, DST_2); + vis_src1(TMP6, REF_6); + + vis_src1(TMP10, REF_S2); + + vis_src1(TMP14, REF_S6); + } + + vis_pmerge(ZERO, REF_0, TMP0); + vis_mul8x16au(REF_0_1, CONST_256, TMP2); + + vis_pmerge(ZERO, REF_2, TMP4); + vis_mul8x16au(REF_2_1, CONST_256, TMP6); + + vis_padd16(TMP0, CONST_3, TMP0); + vis_mul8x16al(DST_0, CONST_512, TMP16); + + vis_padd16(TMP2, CONST_3, TMP2); + vis_mul8x16al(DST_1, CONST_512, TMP18); + + vis_padd16(TMP0, TMP4, TMP0); + vis_mul8x16au(REF_4, CONST_256, TMP8); + + vis_padd16(TMP2, TMP6, TMP2); + vis_mul8x16au(REF_4_1, CONST_256, TMP10); + + vis_padd16(TMP0, TMP16, TMP0); + vis_mul8x16au(REF_6, CONST_256, TMP12); + + vis_padd16(TMP2, TMP18, TMP2); + vis_mul8x16au(REF_6_1, CONST_256, TMP14); + + vis_padd16(TMP8, CONST_3, TMP8); + vis_mul8x16al(DST_2, CONST_512, TMP16); + + vis_padd16(TMP8, TMP12, TMP8); + vis_mul8x16al(DST_3, CONST_512, TMP18); + + vis_padd16(TMP10, TMP14, TMP10); + vis_pack16(TMP0, DST_0); + + vis_pack16(TMP2, DST_1); + vis_st64(DST_0, dest[0]); + dest += stride; + vis_padd16(TMP10, CONST_3, TMP10); + + vis_ld64_2(dest, stride, DST_0); + vis_padd16(TMP8, TMP16, TMP8); + + vis_ld64_2(dest, stride_times_2, TMP4/*DST_2*/); + vis_padd16(TMP10, TMP18, TMP10); + vis_pack16(TMP8, DST_2); + + vis_pack16(TMP10, DST_3); + vis_st64(DST_2, dest[0]); + dest += stride; + + vis_mul8x16au(REF_S0_1, CONST_256, TMP2); + vis_pmerge(ZERO, REF_S0, TMP0); + + vis_pmerge(ZERO, REF_S2, TMP24); + vis_mul8x16au(REF_S2_1, CONST_256, TMP6); + + vis_padd16(TMP0, CONST_3, TMP0); + vis_mul8x16au(REF_S4, CONST_256, TMP8); + + vis_padd16(TMP2, CONST_3, TMP2); + vis_mul8x16au(REF_S4_1, CONST_256, TMP10); + + vis_padd16(TMP0, TMP24, TMP0); + vis_mul8x16au(REF_S6, CONST_256, TMP12); + + vis_padd16(TMP2, TMP6, TMP2); + vis_mul8x16au(REF_S6_1, CONST_256, TMP14); + + vis_padd16(TMP8, CONST_3, TMP8); + vis_mul8x16al(DST_0, CONST_512, TMP16); + + vis_padd16(TMP10, CONST_3, TMP10); + vis_mul8x16al(DST_1, CONST_512, TMP18); + + vis_padd16(TMP8, TMP12, TMP8); + vis_mul8x16al(TMP4/*DST_2*/, CONST_512, TMP20); + + vis_mul8x16al(TMP5/*DST_3*/, CONST_512, TMP22); + vis_padd16(TMP0, TMP16, TMP0); + + vis_padd16(TMP2, TMP18, TMP2); + vis_pack16(TMP0, DST_0); + + vis_padd16(TMP10, TMP14, TMP10); + vis_pack16(TMP2, DST_1); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_padd16(TMP8, TMP20, TMP8); + + vis_padd16(TMP10, TMP22, TMP10); + vis_pack16(TMP8, DST_2); + + vis_pack16(TMP10, DST_3); + vis_st64(DST_2, dest[0]); + dest += stride; + } while (--height); +} + +static void MC_put_y_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + + vis_ld64(ref[0], TMP6); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 8, TMP8); + vis_faligndata(TMP2, TMP4, REF_4); + + vis_ld64_2(ref, 16, TMP10); + ref += stride; + + vis_ld64(constants_fe[0], MASK_fe); + vis_faligndata(TMP6, TMP8, REF_2); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP8, TMP10, REF_6); + + vis_ld64(constants128[0], CONST_128); + height = (height >> 1) - 1; + do { /* 24 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP12); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP16); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + vis_or(REF_0, REF_2, TMP14); + + vis_ld64(ref[0], TMP6); + vis_or(REF_4, REF_6, TMP18); + + vis_ld64_2(ref, 8, TMP8); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 16, TMP10); + ref += stride; + vis_faligndata(TMP2, TMP4, REF_4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_and(TMP16, MASK_fe, TMP16); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_mul8x16(CONST_128, TMP16, TMP16); + vis_xor(REF_0, REF_2, TMP0); + + vis_xor(REF_4, REF_6, TMP2); + + vis_or(REF_0, REF_2, TMP20); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_and(TMP16, MASK_7f, TMP16); + + vis_psub16(TMP14, TMP12, TMP12); + vis_st64(TMP12, dest[0]); + + vis_psub16(TMP18, TMP16, TMP16); + vis_st64_2(TMP16, dest, 8); + dest += stride; + + vis_or(REF_4, REF_6, TMP18); + + vis_and(TMP0, MASK_fe, TMP0); + + vis_and(TMP2, MASK_fe, TMP2); + vis_mul8x16(CONST_128, TMP0, TMP0); + + vis_faligndata(TMP6, TMP8, REF_2); + vis_mul8x16(CONST_128, TMP2, TMP2); + + vis_faligndata(TMP8, TMP10, REF_6); + + vis_and(TMP0, MASK_7f, TMP0); + + vis_and(TMP2, MASK_7f, TMP2); + + vis_psub16(TMP20, TMP0, TMP0); + vis_st64(TMP0, dest[0]); + + vis_psub16(TMP18, TMP2, TMP2); + vis_st64_2(TMP2, dest, 8); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP12); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP16); + + vis_ld64_2(ref, 16, TMP4); + vis_or(REF_0, REF_2, TMP14); + + vis_or(REF_4, REF_6, TMP18); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_and(TMP16, MASK_fe, TMP16); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_mul8x16(CONST_128, TMP16, TMP16); + vis_xor(REF_0, REF_2, TMP0); + + vis_xor(REF_4, REF_6, TMP2); + + vis_or(REF_0, REF_2, TMP20); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_and(TMP16, MASK_7f, TMP16); + + vis_psub16(TMP14, TMP12, TMP12); + vis_st64(TMP12, dest[0]); + + vis_psub16(TMP18, TMP16, TMP16); + vis_st64_2(TMP16, dest, 8); + dest += stride; + + vis_or(REF_4, REF_6, TMP18); + + vis_and(TMP0, MASK_fe, TMP0); + + vis_and(TMP2, MASK_fe, TMP2); + vis_mul8x16(CONST_128, TMP0, TMP0); + + vis_mul8x16(CONST_128, TMP2, TMP2); + + vis_and(TMP0, MASK_7f, TMP0); + + vis_and(TMP2, MASK_7f, TMP2); + + vis_psub16(TMP20, TMP0, TMP0); + vis_st64(TMP0, dest[0]); + + vis_psub16(TMP18, TMP2, TMP2); + vis_st64_2(TMP2, dest, 8); +} + +static void MC_put_y_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + + vis_ld64(ref[0], TMP4); + + vis_ld64_2(ref, 8, TMP6); + ref += stride; + + vis_ld64(constants_fe[0], MASK_fe); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP4, TMP6, REF_2); + + vis_ld64(constants128[0], CONST_128); + height = (height >> 1) - 1; + do { /* 12 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + vis_and(TMP4, MASK_fe, TMP4); + + vis_or(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_faligndata(TMP0, TMP2, REF_0); + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP4, MASK_7f, TMP4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_mul8x16(CONST_128, TMP12, TMP12); + vis_or(REF_0, REF_2, TMP14); + + vis_psub16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_faligndata(TMP0, TMP2, REF_2); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_psub16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP4, MASK_fe, TMP4); + + vis_or(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP4, MASK_7f, TMP4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_mul8x16(CONST_128, TMP12, TMP12); + vis_or(REF_0, REF_2, TMP14); + + vis_psub16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_and(TMP12, MASK_7f, TMP12); + + vis_psub16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); +} + +static void MC_avg_y_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + int stride_8 = stride + 8; + int stride_16 = stride + 16; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(constants3[0], CONST_3); + vis_faligndata(TMP0, TMP2, REF_2); + + vis_ld64(constants256_512[0], CONST_256); + vis_faligndata(TMP2, TMP4, REF_6); + height >>= 1; + + do { /* 31 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_pmerge(ZERO, REF_2, TMP12); + vis_mul8x16au(REF_2_1, CONST_256, TMP14); + + vis_ld64_2(ref, stride_8, TMP2); + vis_pmerge(ZERO, REF_6, TMP16); + vis_mul8x16au(REF_6_1, CONST_256, TMP18); + + vis_ld64_2(ref, stride_16, TMP4); + ref += stride; + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(dest, 8, DST_2); + vis_faligndata(TMP2, TMP4, REF_4); + + vis_ld64_2(ref, stride, TMP6); + vis_pmerge(ZERO, REF_0, TMP0); + vis_mul8x16au(REF_0_1, CONST_256, TMP2); + + vis_ld64_2(ref, stride_8, TMP8); + vis_pmerge(ZERO, REF_4, TMP4); + + vis_ld64_2(ref, stride_16, TMP10); + ref += stride; + + vis_ld64_2(dest, stride, REF_S0/*DST_4*/); + vis_faligndata(TMP6, TMP8, REF_2); + vis_mul8x16au(REF_4_1, CONST_256, TMP6); + + vis_ld64_2(dest, stride_8, REF_S2/*DST_6*/); + vis_faligndata(TMP8, TMP10, REF_6); + vis_mul8x16al(DST_0, CONST_512, TMP20); + + vis_padd16(TMP0, CONST_3, TMP0); + vis_mul8x16al(DST_1, CONST_512, TMP22); + + vis_padd16(TMP2, CONST_3, TMP2); + vis_mul8x16al(DST_2, CONST_512, TMP24); + + vis_padd16(TMP4, CONST_3, TMP4); + vis_mul8x16al(DST_3, CONST_512, TMP26); + + vis_padd16(TMP6, CONST_3, TMP6); + + vis_padd16(TMP12, TMP20, TMP12); + vis_mul8x16al(REF_S0, CONST_512, TMP20); + + vis_padd16(TMP14, TMP22, TMP14); + vis_mul8x16al(REF_S0_1, CONST_512, TMP22); + + vis_padd16(TMP16, TMP24, TMP16); + vis_mul8x16al(REF_S2, CONST_512, TMP24); + + vis_padd16(TMP18, TMP26, TMP18); + vis_mul8x16al(REF_S2_1, CONST_512, TMP26); + + vis_padd16(TMP12, TMP0, TMP12); + vis_mul8x16au(REF_2, CONST_256, TMP28); + + vis_padd16(TMP14, TMP2, TMP14); + vis_mul8x16au(REF_2_1, CONST_256, TMP30); + + vis_padd16(TMP16, TMP4, TMP16); + vis_mul8x16au(REF_6, CONST_256, REF_S4); + + vis_padd16(TMP18, TMP6, TMP18); + vis_mul8x16au(REF_6_1, CONST_256, REF_S6); + + vis_pack16(TMP12, DST_0); + vis_padd16(TMP28, TMP0, TMP12); + + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + vis_padd16(TMP30, TMP2, TMP14); + + vis_pack16(TMP16, DST_2); + vis_padd16(REF_S4, TMP4, TMP16); + + vis_pack16(TMP18, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + vis_padd16(REF_S6, TMP6, TMP18); + + vis_padd16(TMP12, TMP20, TMP12); + + vis_padd16(TMP14, TMP22, TMP14); + vis_pack16(TMP12, DST_0); + + vis_padd16(TMP16, TMP24, TMP16); + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + + vis_padd16(TMP18, TMP26, TMP18); + vis_pack16(TMP16, DST_2); + + vis_pack16(TMP18, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_avg_y_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + int stride_8 = stride + 8; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(constants3[0], CONST_3); + vis_faligndata(TMP0, TMP2, REF_2); + + vis_ld64(constants256_512[0], CONST_256); + + height >>= 1; + do { /* 20 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_pmerge(ZERO, REF_2, TMP8); + vis_mul8x16au(REF_2_1, CONST_256, TMP10); + + vis_ld64_2(ref, stride_8, TMP2); + ref += stride; + + vis_ld64(dest[0], DST_0); + + vis_ld64_2(dest, stride, DST_2); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, stride, TMP4); + vis_mul8x16al(DST_0, CONST_512, TMP16); + vis_pmerge(ZERO, REF_0, TMP12); + + vis_ld64_2(ref, stride_8, TMP6); + ref += stride; + vis_mul8x16al(DST_1, CONST_512, TMP18); + vis_pmerge(ZERO, REF_0_1, TMP14); + + vis_padd16(TMP12, CONST_3, TMP12); + vis_mul8x16al(DST_2, CONST_512, TMP24); + + vis_padd16(TMP14, CONST_3, TMP14); + vis_mul8x16al(DST_3, CONST_512, TMP26); + + vis_faligndata(TMP4, TMP6, REF_2); + + vis_padd16(TMP8, TMP12, TMP8); + + vis_padd16(TMP10, TMP14, TMP10); + vis_mul8x16au(REF_2, CONST_256, TMP20); + + vis_padd16(TMP8, TMP16, TMP0); + vis_mul8x16au(REF_2_1, CONST_256, TMP22); + + vis_padd16(TMP10, TMP18, TMP2); + vis_pack16(TMP0, DST_0); + + vis_pack16(TMP2, DST_1); + vis_st64(DST_0, dest[0]); + dest += stride; + vis_padd16(TMP12, TMP20, TMP12); + + vis_padd16(TMP14, TMP22, TMP14); + + vis_padd16(TMP12, TMP24, TMP0); + + vis_padd16(TMP14, TMP26, TMP2); + vis_pack16(TMP0, DST_2); + + vis_pack16(TMP2, DST_3); + vis_st64(DST_2, dest[0]); + dest += stride; + } while (--height); +} + +static void MC_put_xy_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + int stride_16 = stride + 16; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(constants2[0], CONST_2); + vis_faligndata(TMP0, TMP2, REF_S0); + + vis_ld64(constants256_512[0], CONST_256); + vis_faligndata(TMP2, TMP4, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + vis_faligndata(TMP2, TMP4, REF_S6); + } else { + vis_src1(TMP2, REF_S2); + vis_src1(TMP4, REF_S6); + } + + height >>= 1; + do { + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP12); + vis_pmerge(ZERO, REF_S0_1, TMP14); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride_8, TMP2); + vis_mul8x16au(REF_S2, CONST_256, TMP16); + vis_pmerge(ZERO, REF_S2_1, TMP18); + + vis_ld64_2(ref, stride_16, TMP4); + ref += stride; + vis_mul8x16au(REF_S4, CONST_256, TMP20); + vis_pmerge(ZERO, REF_S4_1, TMP22); + + vis_ld64_2(ref, stride, TMP6); + vis_mul8x16au(REF_S6, CONST_256, TMP24); + vis_pmerge(ZERO, REF_S6_1, TMP26); + + vis_ld64_2(ref, stride_8, TMP8); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, stride_16, TMP10); + ref += stride; + vis_faligndata(TMP2, TMP4, REF_4); + + vis_faligndata(TMP6, TMP8, REF_S0); + + vis_faligndata(TMP8, TMP10, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + vis_faligndata(TMP6, TMP8, REF_S2); + vis_faligndata(TMP8, TMP10, REF_S6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + vis_src1(TMP8, REF_S2); + vis_src1(TMP10, REF_S6); + } + + vis_mul8x16au(REF_0, CONST_256, TMP0); + vis_pmerge(ZERO, REF_0_1, TMP2); + + vis_mul8x16au(REF_2, CONST_256, TMP4); + vis_pmerge(ZERO, REF_2_1, TMP6); + + vis_padd16(TMP0, CONST_2, TMP8); + vis_mul8x16au(REF_4, CONST_256, TMP0); + + vis_padd16(TMP2, CONST_2, TMP10); + vis_mul8x16au(REF_4_1, CONST_256, TMP2); + + vis_padd16(TMP8, TMP4, TMP8); + vis_mul8x16au(REF_6, CONST_256, TMP4); + + vis_padd16(TMP10, TMP6, TMP10); + vis_mul8x16au(REF_6_1, CONST_256, TMP6); + + vis_padd16(TMP12, TMP8, TMP12); + + vis_padd16(TMP14, TMP10, TMP14); + + vis_padd16(TMP12, TMP16, TMP12); + + vis_padd16(TMP14, TMP18, TMP14); + vis_pack16(TMP12, DST_0); + + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + vis_padd16(TMP0, CONST_2, TMP12); + + vis_mul8x16au(REF_S0, CONST_256, TMP0); + vis_padd16(TMP2, CONST_2, TMP14); + + vis_mul8x16au(REF_S0_1, CONST_256, TMP2); + vis_padd16(TMP12, TMP4, TMP12); + + vis_mul8x16au(REF_S2, CONST_256, TMP4); + vis_padd16(TMP14, TMP6, TMP14); + + vis_mul8x16au(REF_S2_1, CONST_256, TMP6); + vis_padd16(TMP20, TMP12, TMP20); + + vis_padd16(TMP22, TMP14, TMP22); + + vis_padd16(TMP20, TMP24, TMP20); + + vis_padd16(TMP22, TMP26, TMP22); + vis_pack16(TMP20, DST_2); + + vis_pack16(TMP22, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + vis_padd16(TMP0, TMP4, TMP24); + + vis_mul8x16au(REF_S4, CONST_256, TMP0); + vis_padd16(TMP2, TMP6, TMP26); + + vis_mul8x16au(REF_S4_1, CONST_256, TMP2); + vis_padd16(TMP24, TMP8, TMP24); + + vis_padd16(TMP26, TMP10, TMP26); + vis_pack16(TMP24, DST_0); + + vis_pack16(TMP26, DST_1); + vis_st64(DST_0, dest[0]); + vis_pmerge(ZERO, REF_S6, TMP4); + + vis_pmerge(ZERO, REF_S6_1, TMP6); + + vis_padd16(TMP0, TMP4, TMP0); + + vis_padd16(TMP2, TMP6, TMP2); + + vis_padd16(TMP0, TMP12, TMP0); + + vis_padd16(TMP2, TMP14, TMP2); + vis_pack16(TMP0, DST_2); + + vis_pack16(TMP2, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_put_xy_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(constants2[0], CONST_2); + + vis_ld64(constants256_512[0], CONST_256); + vis_faligndata(TMP0, TMP2, REF_S0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + } else { + vis_src1(TMP2, REF_S2); + } + + height >>= 1; + do { /* 26 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP8); + vis_pmerge(ZERO, REF_S2, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride_8, TMP2); + ref += stride; + vis_mul8x16au(REF_S0_1, CONST_256, TMP10); + vis_pmerge(ZERO, REF_S2_1, TMP14); + + vis_ld64_2(ref, stride, TMP4); + + vis_ld64_2(ref, stride_8, TMP6); + ref += stride; + vis_faligndata(TMP0, TMP2, REF_S4); + + vis_pmerge(ZERO, REF_S4, TMP18); + + vis_pmerge(ZERO, REF_S4_1, TMP20); + + vis_faligndata(TMP4, TMP6, REF_S0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S6); + vis_faligndata(TMP4, TMP6, REF_S2); + } else { + vis_src1(TMP2, REF_S6); + vis_src1(TMP6, REF_S2); + } + + vis_padd16(TMP18, CONST_2, TMP18); + vis_mul8x16au(REF_S6, CONST_256, TMP22); + + vis_padd16(TMP20, CONST_2, TMP20); + vis_mul8x16au(REF_S6_1, CONST_256, TMP24); + + vis_mul8x16au(REF_S0, CONST_256, TMP26); + vis_pmerge(ZERO, REF_S0_1, TMP28); + + vis_mul8x16au(REF_S2, CONST_256, TMP30); + vis_padd16(TMP18, TMP22, TMP18); + + vis_mul8x16au(REF_S2_1, CONST_256, TMP32); + vis_padd16(TMP20, TMP24, TMP20); + + vis_padd16(TMP8, TMP18, TMP8); + + vis_padd16(TMP10, TMP20, TMP10); + + vis_padd16(TMP8, TMP12, TMP8); + + vis_padd16(TMP10, TMP14, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_st64(DST_0, dest[0]); + dest += stride; + vis_padd16(TMP18, TMP26, TMP18); + + vis_padd16(TMP20, TMP28, TMP20); + + vis_padd16(TMP18, TMP30, TMP18); + + vis_padd16(TMP20, TMP32, TMP20); + vis_pack16(TMP18, DST_2); + + vis_pack16(TMP20, DST_3); + vis_st64(DST_2, dest[0]); + dest += stride; + } while (--height); +} + +static void MC_avg_xy_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + int stride_16 = stride + 16; + + vis_set_gsr(4 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(constants6[0], CONST_6); + vis_faligndata(TMP0, TMP2, REF_S0); + + vis_ld64(constants256_1024[0], CONST_256); + vis_faligndata(TMP2, TMP4, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + vis_faligndata(TMP2, TMP4, REF_S6); + } else { + vis_src1(TMP2, REF_S2); + vis_src1(TMP4, REF_S6); + } + + height >>= 1; + do { /* 55 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP12); + vis_pmerge(ZERO, REF_S0_1, TMP14); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride_8, TMP2); + vis_mul8x16au(REF_S2, CONST_256, TMP16); + vis_pmerge(ZERO, REF_S2_1, TMP18); + + vis_ld64_2(ref, stride_16, TMP4); + ref += stride; + vis_mul8x16au(REF_S4, CONST_256, TMP20); + vis_pmerge(ZERO, REF_S4_1, TMP22); + + vis_ld64_2(ref, stride, TMP6); + vis_mul8x16au(REF_S6, CONST_256, TMP24); + vis_pmerge(ZERO, REF_S6_1, TMP26); + + vis_ld64_2(ref, stride_8, TMP8); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, stride_16, TMP10); + ref += stride; + vis_faligndata(TMP2, TMP4, REF_4); + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP6, TMP8, REF_S0); + + vis_ld64_2(dest, 8, DST_2); + vis_faligndata(TMP8, TMP10, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + vis_faligndata(TMP6, TMP8, REF_S2); + vis_faligndata(TMP8, TMP10, REF_S6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + vis_src1(TMP8, REF_S2); + vis_src1(TMP10, REF_S6); + } + + vis_mul8x16al(DST_0, CONST_1024, TMP30); + vis_pmerge(ZERO, REF_0, TMP0); + + vis_mul8x16al(DST_1, CONST_1024, TMP32); + vis_pmerge(ZERO, REF_0_1, TMP2); + + vis_mul8x16au(REF_2, CONST_256, TMP4); + vis_pmerge(ZERO, REF_2_1, TMP6); + + vis_mul8x16al(DST_2, CONST_1024, REF_0); + vis_padd16(TMP0, CONST_6, TMP0); + + vis_mul8x16al(DST_3, CONST_1024, REF_2); + vis_padd16(TMP2, CONST_6, TMP2); + + vis_padd16(TMP0, TMP4, TMP0); + vis_mul8x16au(REF_4, CONST_256, TMP4); + + vis_padd16(TMP2, TMP6, TMP2); + vis_mul8x16au(REF_4_1, CONST_256, TMP6); + + vis_padd16(TMP12, TMP0, TMP12); + vis_mul8x16au(REF_6, CONST_256, TMP8); + + vis_padd16(TMP14, TMP2, TMP14); + vis_mul8x16au(REF_6_1, CONST_256, TMP10); + + vis_padd16(TMP12, TMP16, TMP12); + vis_mul8x16au(REF_S0, CONST_256, REF_4); + + vis_padd16(TMP14, TMP18, TMP14); + vis_mul8x16au(REF_S0_1, CONST_256, REF_6); + + vis_padd16(TMP12, TMP30, TMP12); + + vis_padd16(TMP14, TMP32, TMP14); + vis_pack16(TMP12, DST_0); + + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + vis_padd16(TMP4, CONST_6, TMP4); + + vis_ld64_2(dest, stride, DST_0); + vis_padd16(TMP6, CONST_6, TMP6); + vis_mul8x16au(REF_S2, CONST_256, TMP12); + + vis_padd16(TMP4, TMP8, TMP4); + vis_mul8x16au(REF_S2_1, CONST_256, TMP14); + + vis_padd16(TMP6, TMP10, TMP6); + + vis_padd16(TMP20, TMP4, TMP20); + + vis_padd16(TMP22, TMP6, TMP22); + + vis_padd16(TMP20, TMP24, TMP20); + + vis_padd16(TMP22, TMP26, TMP22); + + vis_padd16(TMP20, REF_0, TMP20); + vis_mul8x16au(REF_S4, CONST_256, REF_0); + + vis_padd16(TMP22, REF_2, TMP22); + vis_pack16(TMP20, DST_2); + + vis_pack16(TMP22, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + + vis_ld64_2(dest, 8, DST_2); + vis_mul8x16al(DST_0, CONST_1024, TMP30); + vis_pmerge(ZERO, REF_S4_1, REF_2); + + vis_mul8x16al(DST_1, CONST_1024, TMP32); + vis_padd16(REF_4, TMP0, TMP8); + + vis_mul8x16au(REF_S6, CONST_256, REF_4); + vis_padd16(REF_6, TMP2, TMP10); + + vis_mul8x16au(REF_S6_1, CONST_256, REF_6); + vis_padd16(TMP8, TMP12, TMP8); + + vis_padd16(TMP10, TMP14, TMP10); + + vis_padd16(TMP8, TMP30, TMP8); + + vis_padd16(TMP10, TMP32, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_st64(DST_0, dest[0]); + + vis_padd16(REF_0, TMP4, REF_0); + + vis_mul8x16al(DST_2, CONST_1024, TMP30); + vis_padd16(REF_2, TMP6, REF_2); + + vis_mul8x16al(DST_3, CONST_1024, TMP32); + vis_padd16(REF_0, REF_4, REF_0); + + vis_padd16(REF_2, REF_6, REF_2); + + vis_padd16(REF_0, TMP30, REF_0); + + /* stall */ + + vis_padd16(REF_2, TMP32, REF_2); + vis_pack16(REF_0, DST_2); + + vis_pack16(REF_2, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_avg_xy_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + + vis_set_gsr(4 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + vis_fzero(ZERO); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64(constants6[0], CONST_6); + + vis_ld64(constants256_1024[0], CONST_256); + vis_faligndata(TMP0, TMP2, REF_S0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + } else { + vis_src1(TMP2, REF_S2); + } + + height >>= 1; + do { /* 31 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP8); + vis_pmerge(ZERO, REF_S0_1, TMP10); + + vis_ld64_2(ref, stride_8, TMP2); + ref += stride; + vis_mul8x16au(REF_S2, CONST_256, TMP12); + vis_pmerge(ZERO, REF_S2_1, TMP14); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride, TMP4); + vis_faligndata(TMP0, TMP2, REF_S4); + + vis_ld64_2(ref, stride_8, TMP6); + ref += stride; + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP4, TMP6, REF_S0); + + vis_ld64_2(dest, stride, DST_2); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S6); + vis_faligndata(TMP4, TMP6, REF_S2); + } else { + vis_src1(TMP2, REF_S6); + vis_src1(TMP6, REF_S2); + } + + vis_mul8x16al(DST_0, CONST_1024, TMP30); + vis_pmerge(ZERO, REF_S4, TMP22); + + vis_mul8x16al(DST_1, CONST_1024, TMP32); + vis_pmerge(ZERO, REF_S4_1, TMP24); + + vis_mul8x16au(REF_S6, CONST_256, TMP26); + vis_pmerge(ZERO, REF_S6_1, TMP28); + + vis_mul8x16au(REF_S0, CONST_256, REF_S4); + vis_padd16(TMP22, CONST_6, TMP22); + + vis_mul8x16au(REF_S0_1, CONST_256, REF_S6); + vis_padd16(TMP24, CONST_6, TMP24); + + vis_mul8x16al(DST_2, CONST_1024, REF_0); + vis_padd16(TMP22, TMP26, TMP22); + + vis_mul8x16al(DST_3, CONST_1024, REF_2); + vis_padd16(TMP24, TMP28, TMP24); + + vis_mul8x16au(REF_S2, CONST_256, TMP26); + vis_padd16(TMP8, TMP22, TMP8); + + vis_mul8x16au(REF_S2_1, CONST_256, TMP28); + vis_padd16(TMP10, TMP24, TMP10); + + vis_padd16(TMP8, TMP12, TMP8); + + vis_padd16(TMP10, TMP14, TMP10); + + vis_padd16(TMP8, TMP30, TMP8); + + vis_padd16(TMP10, TMP32, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_padd16(REF_S4, TMP22, TMP12); + + vis_padd16(REF_S6, TMP24, TMP14); + + vis_padd16(TMP12, TMP26, TMP12); + + vis_padd16(TMP14, TMP28, TMP14); + + vis_padd16(TMP12, REF_0, TMP12); + + vis_padd16(TMP14, REF_2, TMP14); + vis_pack16(TMP12, DST_2); + + vis_pack16(TMP14, DST_3); + vis_st64(DST_2, dest[0]); + dest += stride; + } while (--height); +} + +/* End of rounding code */ + +/* Start of no rounding code */ +/* The trick used in some of this file is the formula from the MMX + * motion comp code, which is: + * + * (x+y)>>1 == (x&y)+((x^y)>>1) + * + * This allows us to average 8 bytes at a time in a 64-bit FPU reg. + * We avoid overflows by masking before we do the shift, and we + * implement the shift by multiplying by 1/2 using mul8x16. So in + * VIS this is (assume 'x' is in f0, 'y' is in f2, a repeating mask + * of '0xfe' is in f4, a repeating mask of '0x7f' is in f6, and + * the value 0x80808080 is in f8): + * + * fxor f0, f2, f10 + * fand f10, f4, f10 + * fmul8x16 f8, f10, f10 + * fand f10, f6, f10 + * fand f0, f2, f12 + * fpadd16 f12, f10, f10 + */ + +static void MC_put_no_round_o_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + do { /* 5 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + + vis_faligndata(TMP0, TMP2, REF_0); + vis_st64(REF_0, dest[0]); + + vis_faligndata(TMP2, TMP4, REF_2); + vis_st64_2(REF_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_put_no_round_o_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + do { /* 4 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + ref += stride; + + /* stall */ + + vis_faligndata(TMP0, TMP2, REF_0); + vis_st64(REF_0, dest[0]); + dest += stride; + } while (--height); +} + + +static void MC_avg_no_round_o_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + int stride_8 = stride + 8; + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(dest[0], DST_0); + + vis_ld64(dest[8], DST_2); + + vis_ld64(constants_fe[0], MASK_fe); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP2, TMP4, REF_2); + + vis_ld64(constants128[0], CONST_128); + + ref += stride; + height = (height >> 1) - 1; + + do { /* 24 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(DST_0, REF_0, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP6, MASK_fe, TMP6); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_xor(DST_2, REF_2, TMP8); + + vis_and(TMP8, MASK_fe, TMP8); + + vis_and(DST_0, REF_0, TMP10); + vis_ld64_2(dest, stride, DST_0); + vis_mul8x16(CONST_128, TMP8, TMP8); + + vis_and(DST_2, REF_2, TMP12); + vis_ld64_2(dest, stride_8, DST_2); + + vis_ld64(ref[0], TMP14); + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_padd16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_padd16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + + dest += stride; + vis_ld64_2(ref, 8, TMP16); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 16, TMP18); + vis_faligndata(TMP2, TMP4, REF_2); + ref += stride; + + vis_xor(DST_0, REF_0, TMP20); + + vis_and(TMP20, MASK_fe, TMP20); + + vis_xor(DST_2, REF_2, TMP22); + vis_mul8x16(CONST_128, TMP20, TMP20); + + vis_and(TMP22, MASK_fe, TMP22); + + vis_and(DST_0, REF_0, TMP24); + vis_mul8x16(CONST_128, TMP22, TMP22); + + vis_and(DST_2, REF_2, TMP26); + + vis_ld64_2(dest, stride, DST_0); + vis_faligndata(TMP14, TMP16, REF_0); + + vis_ld64_2(dest, stride_8, DST_2); + vis_faligndata(TMP16, TMP18, REF_2); + + vis_and(TMP20, MASK_7f, TMP20); + + vis_and(TMP22, MASK_7f, TMP22); + + vis_padd16(TMP24, TMP20, TMP20); + vis_st64(TMP20, dest[0]); + + vis_padd16(TMP26, TMP22, TMP22); + vis_st64_2(TMP22, dest, 8); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(DST_0, REF_0, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP6, MASK_fe, TMP6); + + vis_ld64_2(ref, 16, TMP4); + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_xor(DST_2, REF_2, TMP8); + + vis_and(TMP8, MASK_fe, TMP8); + + vis_and(DST_0, REF_0, TMP10); + vis_ld64_2(dest, stride, DST_0); + vis_mul8x16(CONST_128, TMP8, TMP8); + + vis_and(DST_2, REF_2, TMP12); + vis_ld64_2(dest, stride_8, DST_2); + + vis_ld64(ref[0], TMP14); + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_padd16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_padd16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + + dest += stride; + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_2); + + vis_xor(DST_0, REF_0, TMP20); + + vis_and(TMP20, MASK_fe, TMP20); + + vis_xor(DST_2, REF_2, TMP22); + vis_mul8x16(CONST_128, TMP20, TMP20); + + vis_and(TMP22, MASK_fe, TMP22); + + vis_and(DST_0, REF_0, TMP24); + vis_mul8x16(CONST_128, TMP22, TMP22); + + vis_and(DST_2, REF_2, TMP26); + + vis_and(TMP20, MASK_7f, TMP20); + + vis_and(TMP22, MASK_7f, TMP22); + + vis_padd16(TMP24, TMP20, TMP20); + vis_st64(TMP20, dest[0]); + + vis_padd16(TMP26, TMP22, TMP22); + vis_st64_2(TMP22, dest, 8); +} + +static void MC_put_no_round_x_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64_2(ref, 16, TMP4); + + vis_ld64(constants_fe[0], MASK_fe); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants128[0], CONST_128); + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + ref += stride; + height = (height >> 1) - 1; + + do { /* 34 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP8); + + vis_ld64_2(ref, 16, TMP4); + vis_and(TMP6, MASK_fe, TMP6); + ref += stride; + + vis_ld64(ref[0], TMP14); + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_ld64_2(ref, 8, TMP16); + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_and(REF_0, REF_2, TMP10); + + vis_ld64_2(ref, 16, TMP18); + ref += stride; + vis_and(REF_4, REF_6, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_padd16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_padd16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + dest += stride; + + vis_xor(REF_0, REF_2, TMP6); + + vis_xor(REF_4, REF_6, TMP8); + + vis_and(TMP6, MASK_fe, TMP6); + + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_and(REF_0, REF_2, TMP10); + + vis_and(REF_4, REF_6, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP14, TMP16, REF_0); + + vis_faligndata(TMP16, TMP18, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP14, TMP16, REF_2); + vis_faligndata(TMP16, TMP18, REF_6); + } else { + vis_src1(TMP16, REF_2); + vis_src1(TMP18, REF_6); + } + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_padd16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_padd16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP6); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP8); + + vis_ld64_2(ref, 16, TMP4); + vis_and(TMP6, MASK_fe, TMP6); + + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_and(REF_0, REF_2, TMP10); + + vis_and(REF_4, REF_6, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_padd16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_padd16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); + dest += stride; + + vis_xor(REF_0, REF_2, TMP6); + + vis_xor(REF_4, REF_6, TMP8); + + vis_and(TMP6, MASK_fe, TMP6); + + vis_mul8x16(CONST_128, TMP6, TMP6); + vis_and(TMP8, MASK_fe, TMP8); + + vis_mul8x16(CONST_128, TMP8, TMP8); + vis_and(REF_0, REF_2, TMP10); + + vis_and(REF_4, REF_6, TMP12); + + vis_and(TMP6, MASK_7f, TMP6); + + vis_and(TMP8, MASK_7f, TMP8); + + vis_padd16(TMP10, TMP6, TMP6); + vis_st64(TMP6, dest[0]); + + vis_padd16(TMP12, TMP8, TMP8); + vis_st64_2(TMP8, dest, 8); +} + +static void MC_put_no_round_x_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + + ref = vis_alignaddr(ref); + + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_ld64(constants_fe[0], MASK_fe); + + vis_ld64(constants_7f[0], MASK_7f); + + vis_ld64(constants128[0], CONST_128); + vis_faligndata(TMP0, TMP2, REF_0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + } else { + vis_src1(TMP2, REF_2); + } + + ref += stride; + height = (height >> 1) - 1; + + do { /* 20 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP4, MASK_fe, TMP4); + ref += stride; + + vis_ld64(ref[0], TMP8); + vis_and(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, 8, TMP10); + ref += stride; + vis_faligndata(TMP0, TMP2, REF_0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + } else { + vis_src1(TMP2, REF_2); + } + + vis_and(TMP4, MASK_7f, TMP4); + + vis_padd16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_and(REF_0, REF_2, TMP14); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_alignaddr_g0((void *)off); + vis_faligndata(TMP8, TMP10, REF_0); + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP8, TMP10, REF_2); + } else { + vis_src1(TMP10, REF_2); + } + + vis_and(TMP12, MASK_7f, TMP12); + + vis_padd16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP4, MASK_fe, TMP4); + + vis_and(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_alignaddr_g0((void *)off); + + vis_faligndata(TMP0, TMP2, REF_0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + } else { + vis_src1(TMP2, REF_2); + } + + vis_and(TMP4, MASK_7f, TMP4); + + vis_padd16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_and(REF_0, REF_2, TMP14); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_padd16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; +} + +static void MC_avg_no_round_x_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + vis_ld64(constants3[0], CONST_3); + vis_fzero(ZERO); + vis_ld64(constants256_512[0], CONST_256); + + ref = vis_alignaddr(ref); + do { /* 26 cycles */ + vis_ld64(ref[0], TMP0); + + vis_ld64(ref[8], TMP2); + + vis_alignaddr_g0((void *)off); + + vis_ld64(ref[16], TMP4); + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(dest[8], DST_2); + vis_faligndata(TMP2, TMP4, REF_4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + } + + vis_mul8x16au(REF_0, CONST_256, TMP0); + + vis_pmerge(ZERO, REF_2, TMP4); + vis_mul8x16au(REF_0_1, CONST_256, TMP2); + + vis_pmerge(ZERO, REF_2_1, TMP6); + + vis_padd16(TMP0, TMP4, TMP0); + + vis_mul8x16al(DST_0, CONST_512, TMP4); + vis_padd16(TMP2, TMP6, TMP2); + + vis_mul8x16al(DST_1, CONST_512, TMP6); + + vis_mul8x16au(REF_6, CONST_256, TMP12); + + vis_padd16(TMP0, TMP4, TMP0); + vis_mul8x16au(REF_6_1, CONST_256, TMP14); + + vis_padd16(TMP2, TMP6, TMP2); + vis_mul8x16au(REF_4, CONST_256, TMP16); + + vis_padd16(TMP0, CONST_3, TMP8); + vis_mul8x16au(REF_4_1, CONST_256, TMP18); + + vis_padd16(TMP2, CONST_3, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_padd16(TMP16, TMP12, TMP0); + + vis_st64(DST_0, dest[0]); + vis_mul8x16al(DST_2, CONST_512, TMP4); + vis_padd16(TMP18, TMP14, TMP2); + + vis_mul8x16al(DST_3, CONST_512, TMP6); + vis_padd16(TMP0, CONST_3, TMP0); + + vis_padd16(TMP2, CONST_3, TMP2); + + vis_padd16(TMP0, TMP4, TMP0); + + vis_padd16(TMP2, TMP6, TMP2); + vis_pack16(TMP0, DST_2); + + vis_pack16(TMP2, DST_3); + vis_st64(DST_2, dest[8]); + + ref += stride; + dest += stride; + } while (--height); +} + +static void MC_put_no_round_y_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + + vis_ld64(ref[0], TMP6); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 8, TMP8); + vis_faligndata(TMP2, TMP4, REF_4); + + vis_ld64_2(ref, 16, TMP10); + ref += stride; + + vis_ld64(constants_fe[0], MASK_fe); + vis_faligndata(TMP6, TMP8, REF_2); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP8, TMP10, REF_6); + + vis_ld64(constants128[0], CONST_128); + height = (height >> 1) - 1; + do { /* 24 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP12); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP16); + + vis_ld64_2(ref, 16, TMP4); + ref += stride; + vis_and(REF_0, REF_2, TMP14); + + vis_ld64(ref[0], TMP6); + vis_and(REF_4, REF_6, TMP18); + + vis_ld64_2(ref, 8, TMP8); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, 16, TMP10); + ref += stride; + vis_faligndata(TMP2, TMP4, REF_4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_and(TMP16, MASK_fe, TMP16); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_mul8x16(CONST_128, TMP16, TMP16); + vis_xor(REF_0, REF_2, TMP0); + + vis_xor(REF_4, REF_6, TMP2); + + vis_and(REF_0, REF_2, TMP20); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_and(TMP16, MASK_7f, TMP16); + + vis_padd16(TMP14, TMP12, TMP12); + vis_st64(TMP12, dest[0]); + + vis_padd16(TMP18, TMP16, TMP16); + vis_st64_2(TMP16, dest, 8); + dest += stride; + + vis_and(REF_4, REF_6, TMP18); + + vis_and(TMP0, MASK_fe, TMP0); + + vis_and(TMP2, MASK_fe, TMP2); + vis_mul8x16(CONST_128, TMP0, TMP0); + + vis_faligndata(TMP6, TMP8, REF_2); + vis_mul8x16(CONST_128, TMP2, TMP2); + + vis_faligndata(TMP8, TMP10, REF_6); + + vis_and(TMP0, MASK_7f, TMP0); + + vis_and(TMP2, MASK_7f, TMP2); + + vis_padd16(TMP20, TMP0, TMP0); + vis_st64(TMP0, dest[0]); + + vis_padd16(TMP18, TMP2, TMP2); + vis_st64_2(TMP2, dest, 8); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP12); + + vis_ld64_2(ref, 8, TMP2); + vis_xor(REF_4, REF_6, TMP16); + + vis_ld64_2(ref, 16, TMP4); + vis_and(REF_0, REF_2, TMP14); + + vis_and(REF_4, REF_6, TMP18); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_faligndata(TMP2, TMP4, REF_4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_and(TMP16, MASK_fe, TMP16); + vis_mul8x16(CONST_128, TMP12, TMP12); + + vis_mul8x16(CONST_128, TMP16, TMP16); + vis_xor(REF_0, REF_2, TMP0); + + vis_xor(REF_4, REF_6, TMP2); + + vis_and(REF_0, REF_2, TMP20); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_and(TMP16, MASK_7f, TMP16); + + vis_padd16(TMP14, TMP12, TMP12); + vis_st64(TMP12, dest[0]); + + vis_padd16(TMP18, TMP16, TMP16); + vis_st64_2(TMP16, dest, 8); + dest += stride; + + vis_and(REF_4, REF_6, TMP18); + + vis_and(TMP0, MASK_fe, TMP0); + + vis_and(TMP2, MASK_fe, TMP2); + vis_mul8x16(CONST_128, TMP0, TMP0); + + vis_mul8x16(CONST_128, TMP2, TMP2); + + vis_and(TMP0, MASK_7f, TMP0); + + vis_and(TMP2, MASK_7f, TMP2); + + vis_padd16(TMP20, TMP0, TMP0); + vis_st64(TMP0, dest[0]); + + vis_padd16(TMP18, TMP2, TMP2); + vis_st64_2(TMP2, dest, 8); +} + +static void MC_put_no_round_y_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + ref = vis_alignaddr(ref); + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + + vis_ld64(ref[0], TMP4); + + vis_ld64_2(ref, 8, TMP6); + ref += stride; + + vis_ld64(constants_fe[0], MASK_fe); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64(constants_7f[0], MASK_7f); + vis_faligndata(TMP4, TMP6, REF_2); + + vis_ld64(constants128[0], CONST_128); + height = (height >> 1) - 1; + do { /* 12 cycles */ + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + vis_and(TMP4, MASK_fe, TMP4); + + vis_and(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_faligndata(TMP0, TMP2, REF_0); + vis_ld64(ref[0], TMP0); + + vis_ld64_2(ref, 8, TMP2); + ref += stride; + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP4, MASK_7f, TMP4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_mul8x16(CONST_128, TMP12, TMP12); + vis_and(REF_0, REF_2, TMP14); + + vis_padd16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_faligndata(TMP0, TMP2, REF_2); + + vis_and(TMP12, MASK_7f, TMP12); + + vis_padd16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + } while (--height); + + vis_ld64(ref[0], TMP0); + vis_xor(REF_0, REF_2, TMP4); + + vis_ld64_2(ref, 8, TMP2); + vis_and(TMP4, MASK_fe, TMP4); + + vis_and(REF_0, REF_2, TMP6); + vis_mul8x16(CONST_128, TMP4, TMP4); + + vis_faligndata(TMP0, TMP2, REF_0); + + vis_xor(REF_0, REF_2, TMP12); + + vis_and(TMP4, MASK_7f, TMP4); + + vis_and(TMP12, MASK_fe, TMP12); + + vis_mul8x16(CONST_128, TMP12, TMP12); + vis_and(REF_0, REF_2, TMP14); + + vis_padd16(TMP6, TMP4, DST_0); + vis_st64(DST_0, dest[0]); + dest += stride; + + vis_and(TMP12, MASK_7f, TMP12); + + vis_padd16(TMP14, TMP12, DST_0); + vis_st64(DST_0, dest[0]); +} + +static void MC_avg_no_round_y_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + int stride_8 = stride + 8; + int stride_16 = stride + 16; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(constants3[0], CONST_3); + vis_faligndata(TMP0, TMP2, REF_2); + + vis_ld64(constants256_512[0], CONST_256); + vis_faligndata(TMP2, TMP4, REF_6); + height >>= 1; + + do { /* 31 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_pmerge(ZERO, REF_2, TMP12); + vis_mul8x16au(REF_2_1, CONST_256, TMP14); + + vis_ld64_2(ref, stride_8, TMP2); + vis_pmerge(ZERO, REF_6, TMP16); + vis_mul8x16au(REF_6_1, CONST_256, TMP18); + + vis_ld64_2(ref, stride_16, TMP4); + ref += stride; + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(dest, 8, DST_2); + vis_faligndata(TMP2, TMP4, REF_4); + + vis_ld64_2(ref, stride, TMP6); + vis_pmerge(ZERO, REF_0, TMP0); + vis_mul8x16au(REF_0_1, CONST_256, TMP2); + + vis_ld64_2(ref, stride_8, TMP8); + vis_pmerge(ZERO, REF_4, TMP4); + + vis_ld64_2(ref, stride_16, TMP10); + ref += stride; + + vis_ld64_2(dest, stride, REF_S0/*DST_4*/); + vis_faligndata(TMP6, TMP8, REF_2); + vis_mul8x16au(REF_4_1, CONST_256, TMP6); + + vis_ld64_2(dest, stride_8, REF_S2/*DST_6*/); + vis_faligndata(TMP8, TMP10, REF_6); + vis_mul8x16al(DST_0, CONST_512, TMP20); + + vis_padd16(TMP0, CONST_3, TMP0); + vis_mul8x16al(DST_1, CONST_512, TMP22); + + vis_padd16(TMP2, CONST_3, TMP2); + vis_mul8x16al(DST_2, CONST_512, TMP24); + + vis_padd16(TMP4, CONST_3, TMP4); + vis_mul8x16al(DST_3, CONST_512, TMP26); + + vis_padd16(TMP6, CONST_3, TMP6); + + vis_padd16(TMP12, TMP20, TMP12); + vis_mul8x16al(REF_S0, CONST_512, TMP20); + + vis_padd16(TMP14, TMP22, TMP14); + vis_mul8x16al(REF_S0_1, CONST_512, TMP22); + + vis_padd16(TMP16, TMP24, TMP16); + vis_mul8x16al(REF_S2, CONST_512, TMP24); + + vis_padd16(TMP18, TMP26, TMP18); + vis_mul8x16al(REF_S2_1, CONST_512, TMP26); + + vis_padd16(TMP12, TMP0, TMP12); + vis_mul8x16au(REF_2, CONST_256, TMP28); + + vis_padd16(TMP14, TMP2, TMP14); + vis_mul8x16au(REF_2_1, CONST_256, TMP30); + + vis_padd16(TMP16, TMP4, TMP16); + vis_mul8x16au(REF_6, CONST_256, REF_S4); + + vis_padd16(TMP18, TMP6, TMP18); + vis_mul8x16au(REF_6_1, CONST_256, REF_S6); + + vis_pack16(TMP12, DST_0); + vis_padd16(TMP28, TMP0, TMP12); + + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + vis_padd16(TMP30, TMP2, TMP14); + + vis_pack16(TMP16, DST_2); + vis_padd16(REF_S4, TMP4, TMP16); + + vis_pack16(TMP18, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + vis_padd16(REF_S6, TMP6, TMP18); + + vis_padd16(TMP12, TMP20, TMP12); + + vis_padd16(TMP14, TMP22, TMP14); + vis_pack16(TMP12, DST_0); + + vis_padd16(TMP16, TMP24, TMP16); + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + + vis_padd16(TMP18, TMP26, TMP18); + vis_pack16(TMP16, DST_2); + + vis_pack16(TMP18, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_put_no_round_xy_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + int stride_16 = stride + 16; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(constants1[0], CONST_1); + vis_faligndata(TMP0, TMP2, REF_S0); + + vis_ld64(constants256_512[0], CONST_256); + vis_faligndata(TMP2, TMP4, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + vis_faligndata(TMP2, TMP4, REF_S6); + } else { + vis_src1(TMP2, REF_S2); + vis_src1(TMP4, REF_S6); + } + + height >>= 1; + do { + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP12); + vis_pmerge(ZERO, REF_S0_1, TMP14); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride_8, TMP2); + vis_mul8x16au(REF_S2, CONST_256, TMP16); + vis_pmerge(ZERO, REF_S2_1, TMP18); + + vis_ld64_2(ref, stride_16, TMP4); + ref += stride; + vis_mul8x16au(REF_S4, CONST_256, TMP20); + vis_pmerge(ZERO, REF_S4_1, TMP22); + + vis_ld64_2(ref, stride, TMP6); + vis_mul8x16au(REF_S6, CONST_256, TMP24); + vis_pmerge(ZERO, REF_S6_1, TMP26); + + vis_ld64_2(ref, stride_8, TMP8); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, stride_16, TMP10); + ref += stride; + vis_faligndata(TMP2, TMP4, REF_4); + + vis_faligndata(TMP6, TMP8, REF_S0); + + vis_faligndata(TMP8, TMP10, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + vis_faligndata(TMP6, TMP8, REF_S2); + vis_faligndata(TMP8, TMP10, REF_S6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + vis_src1(TMP8, REF_S2); + vis_src1(TMP10, REF_S6); + } + + vis_mul8x16au(REF_0, CONST_256, TMP0); + vis_pmerge(ZERO, REF_0_1, TMP2); + + vis_mul8x16au(REF_2, CONST_256, TMP4); + vis_pmerge(ZERO, REF_2_1, TMP6); + + vis_padd16(TMP0, CONST_2, TMP8); + vis_mul8x16au(REF_4, CONST_256, TMP0); + + vis_padd16(TMP2, CONST_1, TMP10); + vis_mul8x16au(REF_4_1, CONST_256, TMP2); + + vis_padd16(TMP8, TMP4, TMP8); + vis_mul8x16au(REF_6, CONST_256, TMP4); + + vis_padd16(TMP10, TMP6, TMP10); + vis_mul8x16au(REF_6_1, CONST_256, TMP6); + + vis_padd16(TMP12, TMP8, TMP12); + + vis_padd16(TMP14, TMP10, TMP14); + + vis_padd16(TMP12, TMP16, TMP12); + + vis_padd16(TMP14, TMP18, TMP14); + vis_pack16(TMP12, DST_0); + + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + vis_padd16(TMP0, CONST_1, TMP12); + + vis_mul8x16au(REF_S0, CONST_256, TMP0); + vis_padd16(TMP2, CONST_1, TMP14); + + vis_mul8x16au(REF_S0_1, CONST_256, TMP2); + vis_padd16(TMP12, TMP4, TMP12); + + vis_mul8x16au(REF_S2, CONST_256, TMP4); + vis_padd16(TMP14, TMP6, TMP14); + + vis_mul8x16au(REF_S2_1, CONST_256, TMP6); + vis_padd16(TMP20, TMP12, TMP20); + + vis_padd16(TMP22, TMP14, TMP22); + + vis_padd16(TMP20, TMP24, TMP20); + + vis_padd16(TMP22, TMP26, TMP22); + vis_pack16(TMP20, DST_2); + + vis_pack16(TMP22, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + vis_padd16(TMP0, TMP4, TMP24); + + vis_mul8x16au(REF_S4, CONST_256, TMP0); + vis_padd16(TMP2, TMP6, TMP26); + + vis_mul8x16au(REF_S4_1, CONST_256, TMP2); + vis_padd16(TMP24, TMP8, TMP24); + + vis_padd16(TMP26, TMP10, TMP26); + vis_pack16(TMP24, DST_0); + + vis_pack16(TMP26, DST_1); + vis_st64(DST_0, dest[0]); + vis_pmerge(ZERO, REF_S6, TMP4); + + vis_pmerge(ZERO, REF_S6_1, TMP6); + + vis_padd16(TMP0, TMP4, TMP0); + + vis_padd16(TMP2, TMP6, TMP2); + + vis_padd16(TMP0, TMP12, TMP0); + + vis_padd16(TMP2, TMP14, TMP2); + vis_pack16(TMP0, DST_2); + + vis_pack16(TMP2, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + } while (--height); +} + +static void MC_put_no_round_xy_8_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + + vis_set_gsr(5 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(constants1[0], CONST_1); + + vis_ld64(constants256_512[0], CONST_256); + vis_faligndata(TMP0, TMP2, REF_S0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + } else { + vis_src1(TMP2, REF_S2); + } + + height >>= 1; + do { /* 26 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP8); + vis_pmerge(ZERO, REF_S2, TMP12); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride_8, TMP2); + ref += stride; + vis_mul8x16au(REF_S0_1, CONST_256, TMP10); + vis_pmerge(ZERO, REF_S2_1, TMP14); + + vis_ld64_2(ref, stride, TMP4); + + vis_ld64_2(ref, stride_8, TMP6); + ref += stride; + vis_faligndata(TMP0, TMP2, REF_S4); + + vis_pmerge(ZERO, REF_S4, TMP18); + + vis_pmerge(ZERO, REF_S4_1, TMP20); + + vis_faligndata(TMP4, TMP6, REF_S0); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S6); + vis_faligndata(TMP4, TMP6, REF_S2); + } else { + vis_src1(TMP2, REF_S6); + vis_src1(TMP6, REF_S2); + } + + vis_padd16(TMP18, CONST_1, TMP18); + vis_mul8x16au(REF_S6, CONST_256, TMP22); + + vis_padd16(TMP20, CONST_1, TMP20); + vis_mul8x16au(REF_S6_1, CONST_256, TMP24); + + vis_mul8x16au(REF_S0, CONST_256, TMP26); + vis_pmerge(ZERO, REF_S0_1, TMP28); + + vis_mul8x16au(REF_S2, CONST_256, TMP30); + vis_padd16(TMP18, TMP22, TMP18); + + vis_mul8x16au(REF_S2_1, CONST_256, TMP32); + vis_padd16(TMP20, TMP24, TMP20); + + vis_padd16(TMP8, TMP18, TMP8); + + vis_padd16(TMP10, TMP20, TMP10); + + vis_padd16(TMP8, TMP12, TMP8); + + vis_padd16(TMP10, TMP14, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_st64(DST_0, dest[0]); + dest += stride; + vis_padd16(TMP18, TMP26, TMP18); + + vis_padd16(TMP20, TMP28, TMP20); + + vis_padd16(TMP18, TMP30, TMP18); + + vis_padd16(TMP20, TMP32, TMP20); + vis_pack16(TMP18, DST_2); + + vis_pack16(TMP20, DST_3); + vis_st64(DST_2, dest[0]); + dest += stride; + } while (--height); +} + +static void MC_avg_no_round_xy_16_vis (uint8_t * dest, const uint8_t * ref, + const ptrdiff_t stride, int height) +{ + unsigned long off = (unsigned long) ref & 0x7; + unsigned long off_plus_1 = off + 1; + int stride_8 = stride + 8; + int stride_16 = stride + 16; + + vis_set_gsr(4 << VIS_GSR_SCALEFACT_SHIFT); + + ref = vis_alignaddr(ref); + + vis_ld64(ref[ 0], TMP0); + vis_fzero(ZERO); + + vis_ld64(ref[ 8], TMP2); + + vis_ld64(ref[16], TMP4); + + vis_ld64(constants6[0], CONST_6); + vis_faligndata(TMP0, TMP2, REF_S0); + + vis_ld64(constants256_1024[0], CONST_256); + vis_faligndata(TMP2, TMP4, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_S2); + vis_faligndata(TMP2, TMP4, REF_S6); + } else { + vis_src1(TMP2, REF_S2); + vis_src1(TMP4, REF_S6); + } + + height >>= 1; + do { /* 55 cycles */ + vis_ld64_2(ref, stride, TMP0); + vis_mul8x16au(REF_S0, CONST_256, TMP12); + vis_pmerge(ZERO, REF_S0_1, TMP14); + + vis_alignaddr_g0((void *)off); + + vis_ld64_2(ref, stride_8, TMP2); + vis_mul8x16au(REF_S2, CONST_256, TMP16); + vis_pmerge(ZERO, REF_S2_1, TMP18); + + vis_ld64_2(ref, stride_16, TMP4); + ref += stride; + vis_mul8x16au(REF_S4, CONST_256, TMP20); + vis_pmerge(ZERO, REF_S4_1, TMP22); + + vis_ld64_2(ref, stride, TMP6); + vis_mul8x16au(REF_S6, CONST_256, TMP24); + vis_pmerge(ZERO, REF_S6_1, TMP26); + + vis_ld64_2(ref, stride_8, TMP8); + vis_faligndata(TMP0, TMP2, REF_0); + + vis_ld64_2(ref, stride_16, TMP10); + ref += stride; + vis_faligndata(TMP2, TMP4, REF_4); + + vis_ld64(dest[0], DST_0); + vis_faligndata(TMP6, TMP8, REF_S0); + + vis_ld64_2(dest, 8, DST_2); + vis_faligndata(TMP8, TMP10, REF_S4); + + if (off != 0x7) { + vis_alignaddr_g0((void *)off_plus_1); + vis_faligndata(TMP0, TMP2, REF_2); + vis_faligndata(TMP2, TMP4, REF_6); + vis_faligndata(TMP6, TMP8, REF_S2); + vis_faligndata(TMP8, TMP10, REF_S6); + } else { + vis_src1(TMP2, REF_2); + vis_src1(TMP4, REF_6); + vis_src1(TMP8, REF_S2); + vis_src1(TMP10, REF_S6); + } + + vis_mul8x16al(DST_0, CONST_1024, TMP30); + vis_pmerge(ZERO, REF_0, TMP0); + + vis_mul8x16al(DST_1, CONST_1024, TMP32); + vis_pmerge(ZERO, REF_0_1, TMP2); + + vis_mul8x16au(REF_2, CONST_256, TMP4); + vis_pmerge(ZERO, REF_2_1, TMP6); + + vis_mul8x16al(DST_2, CONST_1024, REF_0); + vis_padd16(TMP0, CONST_6, TMP0); + + vis_mul8x16al(DST_3, CONST_1024, REF_2); + vis_padd16(TMP2, CONST_6, TMP2); + + vis_padd16(TMP0, TMP4, TMP0); + vis_mul8x16au(REF_4, CONST_256, TMP4); + + vis_padd16(TMP2, TMP6, TMP2); + vis_mul8x16au(REF_4_1, CONST_256, TMP6); + + vis_padd16(TMP12, TMP0, TMP12); + vis_mul8x16au(REF_6, CONST_256, TMP8); + + vis_padd16(TMP14, TMP2, TMP14); + vis_mul8x16au(REF_6_1, CONST_256, TMP10); + + vis_padd16(TMP12, TMP16, TMP12); + vis_mul8x16au(REF_S0, CONST_256, REF_4); + + vis_padd16(TMP14, TMP18, TMP14); + vis_mul8x16au(REF_S0_1, CONST_256, REF_6); + + vis_padd16(TMP12, TMP30, TMP12); + + vis_padd16(TMP14, TMP32, TMP14); + vis_pack16(TMP12, DST_0); + + vis_pack16(TMP14, DST_1); + vis_st64(DST_0, dest[0]); + vis_padd16(TMP4, CONST_6, TMP4); + + vis_ld64_2(dest, stride, DST_0); + vis_padd16(TMP6, CONST_6, TMP6); + vis_mul8x16au(REF_S2, CONST_256, TMP12); + + vis_padd16(TMP4, TMP8, TMP4); + vis_mul8x16au(REF_S2_1, CONST_256, TMP14); + + vis_padd16(TMP6, TMP10, TMP6); + + vis_padd16(TMP20, TMP4, TMP20); + + vis_padd16(TMP22, TMP6, TMP22); + + vis_padd16(TMP20, TMP24, TMP20); + + vis_padd16(TMP22, TMP26, TMP22); + + vis_padd16(TMP20, REF_0, TMP20); + vis_mul8x16au(REF_S4, CONST_256, REF_0); + + vis_padd16(TMP22, REF_2, TMP22); + vis_pack16(TMP20, DST_2); + + vis_pack16(TMP22, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + + vis_ld64_2(dest, 8, DST_2); + vis_mul8x16al(DST_0, CONST_1024, TMP30); + vis_pmerge(ZERO, REF_S4_1, REF_2); + + vis_mul8x16al(DST_1, CONST_1024, TMP32); + vis_padd16(REF_4, TMP0, TMP8); + + vis_mul8x16au(REF_S6, CONST_256, REF_4); + vis_padd16(REF_6, TMP2, TMP10); + + vis_mul8x16au(REF_S6_1, CONST_256, REF_6); + vis_padd16(TMP8, TMP12, TMP8); + + vis_padd16(TMP10, TMP14, TMP10); + + vis_padd16(TMP8, TMP30, TMP8); + + vis_padd16(TMP10, TMP32, TMP10); + vis_pack16(TMP8, DST_0); + + vis_pack16(TMP10, DST_1); + vis_st64(DST_0, dest[0]); + + vis_padd16(REF_0, TMP4, REF_0); + + vis_mul8x16al(DST_2, CONST_1024, TMP30); + vis_padd16(REF_2, TMP6, REF_2); + + vis_mul8x16al(DST_3, CONST_1024, TMP32); + vis_padd16(REF_0, REF_4, REF_0); + + vis_padd16(REF_2, REF_6, REF_2); + + vis_padd16(REF_0, TMP30, REF_0); + + /* stall */ + + vis_padd16(REF_2, TMP32, REF_2); + vis_pack16(REF_0, DST_2); + + vis_pack16(REF_2, DST_3); + vis_st64_2(DST_2, dest, 8); + dest += stride; + } while (--height); +} + +/* End of no rounding code */ + +#define ACCEL_SPARC_VIS 1 +#define ACCEL_SPARC_VIS2 2 + +static int vis_level(void) +{ + int accel = 0; + accel |= ACCEL_SPARC_VIS; + accel |= ACCEL_SPARC_VIS2; + return accel; +} + +/* libavcodec initialization code */ +void ff_hpeldsp_init_vis(HpelDSPContext* c, int flags) +{ + /* VIS-specific optimizations */ + int accel = vis_level (); + + if (accel & ACCEL_SPARC_VIS) { + c->put_pixels_tab[0][0] = MC_put_o_16_vis; + c->put_pixels_tab[0][1] = MC_put_x_16_vis; + c->put_pixels_tab[0][2] = MC_put_y_16_vis; + c->put_pixels_tab[0][3] = MC_put_xy_16_vis; + + c->put_pixels_tab[1][0] = MC_put_o_8_vis; + c->put_pixels_tab[1][1] = MC_put_x_8_vis; + c->put_pixels_tab[1][2] = MC_put_y_8_vis; + c->put_pixels_tab[1][3] = MC_put_xy_8_vis; + + c->avg_pixels_tab[0][0] = MC_avg_o_16_vis; + c->avg_pixels_tab[0][1] = MC_avg_x_16_vis; + c->avg_pixels_tab[0][2] = MC_avg_y_16_vis; + c->avg_pixels_tab[0][3] = MC_avg_xy_16_vis; + + c->avg_pixels_tab[1][0] = MC_avg_o_8_vis; + c->avg_pixels_tab[1][1] = MC_avg_x_8_vis; + c->avg_pixels_tab[1][2] = MC_avg_y_8_vis; + c->avg_pixels_tab[1][3] = MC_avg_xy_8_vis; + + c->put_no_rnd_pixels_tab[0][0] = MC_put_no_round_o_16_vis; + c->put_no_rnd_pixels_tab[0][1] = MC_put_no_round_x_16_vis; + c->put_no_rnd_pixels_tab[0][2] = MC_put_no_round_y_16_vis; + c->put_no_rnd_pixels_tab[0][3] = MC_put_no_round_xy_16_vis; + + c->put_no_rnd_pixels_tab[1][0] = MC_put_no_round_o_8_vis; + c->put_no_rnd_pixels_tab[1][1] = MC_put_no_round_x_8_vis; + c->put_no_rnd_pixels_tab[1][2] = MC_put_no_round_y_8_vis; + c->put_no_rnd_pixels_tab[1][3] = MC_put_no_round_xy_8_vis; + + c->avg_no_rnd_pixels_tab[0] = MC_avg_no_round_o_16_vis; + c->avg_no_rnd_pixels_tab[1] = MC_avg_no_round_x_16_vis; + c->avg_no_rnd_pixels_tab[2] = MC_avg_no_round_y_16_vis; + c->avg_no_rnd_pixels_tab[3] = MC_avg_no_round_xy_16_vis; + } +} diff --git a/ffmpeg/libavcodec/sparc/simple_idct_vis.c b/ffmpeg/libavcodec/sparc/simple_idct_vis.c new file mode 100644 index 0000000..c9923e0 --- /dev/null +++ b/ffmpeg/libavcodec/sparc/simple_idct_vis.c @@ -0,0 +1,531 @@ +/* + * SPARC VIS optimized inverse DCT + * Copyright (c) 2007 Denes Balatoni < dbalatoni XatX interware XdotX hu > + * + * I did consult the following fine web page about dct + * http://www.geocities.com/ssavekar/dct.htm + * + * 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 "dsputil_vis.h" +#include "libavutil/mem.h" + +static const DECLARE_ALIGNED(8, int16_t, coeffs)[28] = { + - 1259,- 1259,- 1259,- 1259, + - 4989,- 4989,- 4989,- 4989, + -11045,-11045,-11045,-11045, + -19195,-19195,-19195,-19195, + -29126,-29126,-29126,-29126, + 25080, 25080, 25080, 25080, + 12785, 12785, 12785, 12785 +}; +static const DECLARE_ALIGNED(8, uint16_t, scale)[4] = { + 65536>>6, 65536>>6, 65536>>6, 65536>>6 +}; +static const DECLARE_ALIGNED(8, uint16_t, rounder)[4] = { + 1<<5, 1<<5, 1<<5, 1<<5 +}; +static const DECLARE_ALIGNED(8, uint16_t, expand)[4] = { + 1<<14, 1<<14, 1<<14, 1<<14 +}; + +#define INIT_IDCT \ + "ldd [%1], %%f32 \n\t"\ + "ldd [%1+8], %%f34 \n\t"\ + "ldd [%1+16], %%f36 \n\t"\ + "ldd [%1+24], %%f38 \n\t"\ + "ldd [%1+32], %%f40 \n\t"\ + "ldd [%1+40], %%f42 \n\t"\ + "ldd [%1+48], %%f44 \n\t"\ + "ldd [%0], %%f46 \n\t"\ + "fzero %%f62 \n\t"\ + +#define LOADSCALE(in) \ + "ldd [" in "], %%f0 \n\t"\ + "ldd [" in "+16], %%f2 \n\t"\ + "ldd [" in "+32], %%f4 \n\t"\ + "ldd [" in "+48], %%f6 \n\t"\ + "ldd [" in "+64], %%f8 \n\t"\ + "ldd [" in "+80], %%f10 \n\t"\ + "ldd [" in "+96], %%f12 \n\t"\ + "ldd [" in "+112], %%f14 \n\t"\ + "fpadd16 %%f0, %%f0, %%f0 \n\t"\ + "fpadd16 %%f2, %%f2, %%f2 \n\t"\ + "fpadd16 %%f4, %%f4, %%f4 \n\t"\ + "fpadd16 %%f6, %%f6, %%f6 \n\t"\ + "fpadd16 %%f8, %%f8, %%f8 \n\t"\ + "fpadd16 %%f10, %%f10, %%f10 \n\t"\ + "fpadd16 %%f12, %%f12, %%f12 \n\t"\ + "fpadd16 %%f14, %%f14, %%f14 \n\t"\ +\ + "fpadd16 %%f0, %%f0, %%f0 \n\t"\ + "fpadd16 %%f2, %%f2, %%f2 \n\t"\ + "fpadd16 %%f4, %%f4, %%f4 \n\t"\ + "fpadd16 %%f6, %%f6, %%f6 \n\t"\ + "fpadd16 %%f8, %%f8, %%f8 \n\t"\ + "fpadd16 %%f10, %%f10, %%f10 \n\t"\ + "fpadd16 %%f12, %%f12, %%f12 \n\t"\ + "fpadd16 %%f14, %%f14, %%f14 \n\t"\ +\ + "fpadd16 %%f0, %%f0, %%f0 \n\t"\ + "fpadd16 %%f2, %%f2, %%f2 \n\t"\ + "fpadd16 %%f4, %%f4, %%f4 \n\t"\ + "fpadd16 %%f6, %%f6, %%f6 \n\t"\ + "fpadd16 %%f8, %%f8, %%f8 \n\t"\ + "fpadd16 %%f10, %%f10, %%f10 \n\t"\ + "fpadd16 %%f12, %%f12, %%f12 \n\t"\ + "fpadd16 %%f14, %%f14, %%f14 \n\t"\ +\ + "fpadd16 %%f0, %%f0, %%f0 \n\t"\ + "fpadd16 %%f2, %%f2, %%f2 \n\t"\ + "fpadd16 %%f4, %%f4, %%f4 \n\t"\ + "fpadd16 %%f6, %%f6, %%f6 \n\t"\ + "fpadd16 %%f8, %%f8, %%f8 \n\t"\ + "fpadd16 %%f10, %%f10, %%f10 \n\t"\ + "fpadd16 %%f12, %%f12, %%f12 \n\t"\ + "fpadd16 %%f14, %%f14, %%f14 \n\t"\ + +#define LOAD(in) \ + "ldd [" in "], %%f16 \n\t"\ + "ldd [" in "+8], %%f18 \n\t"\ + "ldd [" in "+16], %%f20 \n\t"\ + "ldd [" in "+24], %%f22 \n\t"\ + "ldd [" in "+32], %%f24 \n\t"\ + "ldd [" in "+40], %%f26 \n\t"\ + "ldd [" in "+48], %%f28 \n\t"\ + "ldd [" in "+56], %%f30 \n\t"\ + +#define TRANSPOSE \ + "fpmerge %%f16, %%f24, %%f0 \n\t"\ + "fpmerge %%f20, %%f28, %%f2 \n\t"\ + "fpmerge %%f17, %%f25, %%f4 \n\t"\ + "fpmerge %%f21, %%f29, %%f6 \n\t"\ + "fpmerge %%f18, %%f26, %%f8 \n\t"\ + "fpmerge %%f22, %%f30, %%f10 \n\t"\ + "fpmerge %%f19, %%f27, %%f12 \n\t"\ + "fpmerge %%f23, %%f31, %%f14 \n\t"\ +\ + "fpmerge %%f0, %%f2, %%f16 \n\t"\ + "fpmerge %%f1, %%f3, %%f18 \n\t"\ + "fpmerge %%f4, %%f6, %%f20 \n\t"\ + "fpmerge %%f5, %%f7, %%f22 \n\t"\ + "fpmerge %%f8, %%f10, %%f24 \n\t"\ + "fpmerge %%f9, %%f11, %%f26 \n\t"\ + "fpmerge %%f12, %%f14, %%f28 \n\t"\ + "fpmerge %%f13, %%f15, %%f30 \n\t"\ +\ + "fpmerge %%f16, %%f17, %%f0 \n\t"\ + "fpmerge %%f18, %%f19, %%f2 \n\t"\ + "fpmerge %%f20, %%f21, %%f4 \n\t"\ + "fpmerge %%f22, %%f23, %%f6 \n\t"\ + "fpmerge %%f24, %%f25, %%f8 \n\t"\ + "fpmerge %%f26, %%f27, %%f10 \n\t"\ + "fpmerge %%f28, %%f29, %%f12 \n\t"\ + "fpmerge %%f30, %%f31, %%f14 \n\t"\ + +#define IDCT4ROWS \ + /* 1. column */\ + "fmul8ulx16 %%f0, %%f38, %%f28 \n\t"\ + "for %%f4, %%f6, %%f60 \n\t"\ + "fmul8ulx16 %%f2, %%f32, %%f18 \n\t"\ + "fmul8ulx16 %%f2, %%f36, %%f22 \n\t"\ + "fmul8ulx16 %%f2, %%f40, %%f26 \n\t"\ + "fmul8ulx16 %%f2, %%f44, %%f30 \n\t"\ +\ + ADDROUNDER\ +\ + "fmul8sux16 %%f0, %%f38, %%f48 \n\t"\ + "fcmpd %%fcc0, %%f62, %%f60 \n\t"\ + "for %%f8, %%f10, %%f60 \n\t"\ + "fmul8sux16 %%f2, %%f32, %%f50 \n\t"\ + "fmul8sux16 %%f2, %%f36, %%f52 \n\t"\ + "fmul8sux16 %%f2, %%f40, %%f54 \n\t"\ + "fmul8sux16 %%f2, %%f44, %%f56 \n\t"\ +\ + "fpadd16 %%f48, %%f28, %%f28 \n\t"\ + "fcmpd %%fcc1, %%f62, %%f60 \n\t"\ + "for %%f12, %%f14, %%f60 \n\t"\ + "fpadd16 %%f50, %%f18, %%f18 \n\t"\ + "fpadd16 %%f52, %%f22, %%f22 \n\t"\ + "fpadd16 %%f54, %%f26, %%f26 \n\t"\ + "fpadd16 %%f56, %%f30, %%f30 \n\t"\ +\ + "fpadd16 %%f28, %%f0, %%f16 \n\t"\ + "fcmpd %%fcc2, %%f62, %%f60 \n\t"\ + "fpadd16 %%f28, %%f0, %%f20 \n\t"\ + "fpadd16 %%f28, %%f0, %%f24 \n\t"\ + "fpadd16 %%f28, %%f0, %%f28 \n\t"\ + "fpadd16 %%f18, %%f2, %%f18 \n\t"\ + "fpadd16 %%f22, %%f2, %%f22 \n\t"\ + /* 2. column */\ + "fbe %%fcc0, 3f \n\t"\ + "fpadd16 %%f26, %%f2, %%f26 \n\t"\ + "fmul8ulx16 %%f4, %%f34, %%f48 \n\t"\ + "fmul8ulx16 %%f4, %%f42, %%f50 \n\t"\ + "fmul8ulx16 %%f6, %%f36, %%f52 \n\t"\ + "fmul8ulx16 %%f6, %%f44, %%f54 \n\t"\ + "fmul8ulx16 %%f6, %%f32, %%f56 \n\t"\ + "fmul8ulx16 %%f6, %%f40, %%f58 \n\t"\ +\ + "fpadd16 %%f16, %%f48, %%f16 \n\t"\ + "fpadd16 %%f20, %%f50, %%f20 \n\t"\ + "fpsub16 %%f24, %%f50, %%f24 \n\t"\ + "fpsub16 %%f28, %%f48, %%f28 \n\t"\ + "fpadd16 %%f18, %%f52, %%f18 \n\t"\ + "fpsub16 %%f22, %%f54, %%f22 \n\t"\ + "fpsub16 %%f26, %%f56, %%f26 \n\t"\ + "fpsub16 %%f30, %%f58, %%f30 \n\t"\ +\ + "fmul8sux16 %%f4, %%f34, %%f48 \n\t"\ + "fmul8sux16 %%f4, %%f42, %%f50 \n\t"\ + "fmul8sux16 %%f6, %%f36, %%f52 \n\t"\ + "fmul8sux16 %%f6, %%f44, %%f54 \n\t"\ + "fmul8sux16 %%f6, %%f32, %%f56 \n\t"\ + "fmul8sux16 %%f6, %%f40, %%f58 \n\t"\ +\ + "fpadd16 %%f16, %%f48, %%f16 \n\t"\ + "fpadd16 %%f20, %%f50, %%f20 \n\t"\ + "fpsub16 %%f24, %%f50, %%f24 \n\t"\ + "fpsub16 %%f28, %%f48, %%f28 \n\t"\ + "fpadd16 %%f18, %%f52, %%f18 \n\t"\ + "fpsub16 %%f22, %%f54, %%f22 \n\t"\ + "fpsub16 %%f26, %%f56, %%f26 \n\t"\ + "fpsub16 %%f30, %%f58, %%f30 \n\t"\ +\ + "fpadd16 %%f16, %%f4, %%f16 \n\t"\ + "fpsub16 %%f28, %%f4, %%f28 \n\t"\ + "fpadd16 %%f18, %%f6, %%f18 \n\t"\ + "fpsub16 %%f26, %%f6, %%f26 \n\t"\ + /* 3. column */\ + "3: \n\t"\ + "fbe %%fcc1, 4f \n\t"\ + "fpsub16 %%f30, %%f6, %%f30 \n\t"\ + "fmul8ulx16 %%f8, %%f38, %%f48 \n\t"\ + "fmul8ulx16 %%f10, %%f40, %%f50 \n\t"\ + "fmul8ulx16 %%f10, %%f32, %%f52 \n\t"\ + "fmul8ulx16 %%f10, %%f44, %%f54 \n\t"\ + "fmul8ulx16 %%f10, %%f36, %%f56 \n\t"\ +\ + "fpadd16 %%f16, %%f48, %%f16 \n\t"\ + "fpsub16 %%f20, %%f48, %%f20 \n\t"\ + "fpsub16 %%f24, %%f48, %%f24 \n\t"\ + "fpadd16 %%f28, %%f48, %%f28 \n\t"\ + "fpadd16 %%f18, %%f50, %%f18 \n\t"\ + "fpsub16 %%f22, %%f52, %%f22 \n\t"\ + "fpadd16 %%f26, %%f54, %%f26 \n\t"\ + "fpadd16 %%f30, %%f56, %%f30 \n\t"\ +\ + "fmul8sux16 %%f8, %%f38, %%f48 \n\t"\ + "fmul8sux16 %%f10, %%f40, %%f50 \n\t"\ + "fmul8sux16 %%f10, %%f32, %%f52 \n\t"\ + "fmul8sux16 %%f10, %%f44, %%f54 \n\t"\ + "fmul8sux16 %%f10, %%f36, %%f56 \n\t"\ +\ + "fpadd16 %%f16, %%f48, %%f16 \n\t"\ + "fpsub16 %%f20, %%f48, %%f20 \n\t"\ + "fpsub16 %%f24, %%f48, %%f24 \n\t"\ + "fpadd16 %%f28, %%f48, %%f28 \n\t"\ + "fpadd16 %%f18, %%f50, %%f18 \n\t"\ + "fpsub16 %%f22, %%f52, %%f22 \n\t"\ + "fpadd16 %%f26, %%f54, %%f26 \n\t"\ + "fpadd16 %%f30, %%f56, %%f30 \n\t"\ +\ + "fpadd16 %%f16, %%f8, %%f16 \n\t"\ + "fpsub16 %%f20, %%f8, %%f20 \n\t"\ + "fpsub16 %%f24, %%f8, %%f24 \n\t"\ + "fpadd16 %%f28, %%f8, %%f28 \n\t"\ + "fpadd16 %%f18, %%f10, %%f18 \n\t"\ + "fpsub16 %%f22, %%f10, %%f22 \n\t"\ + /* 4. column */\ + "4: \n\t"\ + "fbe %%fcc2, 5f \n\t"\ + "fpadd16 %%f30, %%f10, %%f30 \n\t"\ + "fmul8ulx16 %%f12, %%f42, %%f48 \n\t"\ + "fmul8ulx16 %%f12, %%f34, %%f50 \n\t"\ + "fmul8ulx16 %%f14, %%f44, %%f52 \n\t"\ + "fmul8ulx16 %%f14, %%f40, %%f54 \n\t"\ + "fmul8ulx16 %%f14, %%f36, %%f56 \n\t"\ + "fmul8ulx16 %%f14, %%f32, %%f58 \n\t"\ +\ + "fpadd16 %%f16, %%f48, %%f16 \n\t"\ + "fpsub16 %%f20, %%f50, %%f20 \n\t"\ + "fpadd16 %%f24, %%f50, %%f24 \n\t"\ + "fpsub16 %%f28, %%f48, %%f28 \n\t"\ + "fpadd16 %%f18, %%f52, %%f18 \n\t"\ + "fpsub16 %%f22, %%f54, %%f22 \n\t"\ + "fpadd16 %%f26, %%f56, %%f26 \n\t"\ + "fpsub16 %%f30, %%f58, %%f30 \n\t"\ +\ + "fmul8sux16 %%f12, %%f42, %%f48 \n\t"\ + "fmul8sux16 %%f12, %%f34, %%f50 \n\t"\ + "fmul8sux16 %%f14, %%f44, %%f52 \n\t"\ + "fmul8sux16 %%f14, %%f40, %%f54 \n\t"\ + "fmul8sux16 %%f14, %%f36, %%f56 \n\t"\ + "fmul8sux16 %%f14, %%f32, %%f58 \n\t"\ +\ + "fpadd16 %%f16, %%f48, %%f16 \n\t"\ + "fpsub16 %%f20, %%f50, %%f20 \n\t"\ + "fpadd16 %%f24, %%f50, %%f24 \n\t"\ + "fpsub16 %%f28, %%f48, %%f28 \n\t"\ + "fpadd16 %%f18, %%f52, %%f18 \n\t"\ + "fpsub16 %%f22, %%f54, %%f22 \n\t"\ + "fpadd16 %%f26, %%f56, %%f26 \n\t"\ + "fpsub16 %%f30, %%f58, %%f30 \n\t"\ +\ + "fpsub16 %%f20, %%f12, %%f20 \n\t"\ + "fpadd16 %%f24, %%f12, %%f24 \n\t"\ + "fpsub16 %%f22, %%f14, %%f22 \n\t"\ + "fpadd16 %%f26, %%f14, %%f26 \n\t"\ + "fpsub16 %%f30, %%f14, %%f30 \n\t"\ + /* final butterfly */\ + "5: \n\t"\ + "fpsub16 %%f16, %%f18, %%f48 \n\t"\ + "fpsub16 %%f20, %%f22, %%f50 \n\t"\ + "fpsub16 %%f24, %%f26, %%f52 \n\t"\ + "fpsub16 %%f28, %%f30, %%f54 \n\t"\ + "fpadd16 %%f16, %%f18, %%f16 \n\t"\ + "fpadd16 %%f20, %%f22, %%f20 \n\t"\ + "fpadd16 %%f24, %%f26, %%f24 \n\t"\ + "fpadd16 %%f28, %%f30, %%f28 \n\t"\ + +#define STOREROWS(out) \ + "std %%f48, [" out "+112] \n\t"\ + "std %%f50, [" out "+96] \n\t"\ + "std %%f52, [" out "+80] \n\t"\ + "std %%f54, [" out "+64] \n\t"\ + "std %%f16, [" out "] \n\t"\ + "std %%f20, [" out "+16] \n\t"\ + "std %%f24, [" out "+32] \n\t"\ + "std %%f28, [" out "+48] \n\t"\ + +#define SCALEROWS \ + "fmul8sux16 %%f46, %%f48, %%f48 \n\t"\ + "fmul8sux16 %%f46, %%f50, %%f50 \n\t"\ + "fmul8sux16 %%f46, %%f52, %%f52 \n\t"\ + "fmul8sux16 %%f46, %%f54, %%f54 \n\t"\ + "fmul8sux16 %%f46, %%f16, %%f16 \n\t"\ + "fmul8sux16 %%f46, %%f20, %%f20 \n\t"\ + "fmul8sux16 %%f46, %%f24, %%f24 \n\t"\ + "fmul8sux16 %%f46, %%f28, %%f28 \n\t"\ + +#define PUTPIXELSCLAMPED(dest) \ + "fpack16 %%f48, %%f14 \n\t"\ + "fpack16 %%f50, %%f12 \n\t"\ + "fpack16 %%f16, %%f0 \n\t"\ + "fpack16 %%f20, %%f2 \n\t"\ + "fpack16 %%f24, %%f4 \n\t"\ + "fpack16 %%f28, %%f6 \n\t"\ + "fpack16 %%f54, %%f8 \n\t"\ + "fpack16 %%f52, %%f10 \n\t"\ + "st %%f0, [%3+" dest "] \n\t"\ + "st %%f2, [%5+" dest "] \n\t"\ + "st %%f4, [%6+" dest "] \n\t"\ + "st %%f6, [%7+" dest "] \n\t"\ + "st %%f8, [%8+" dest "] \n\t"\ + "st %%f10, [%9+" dest "] \n\t"\ + "st %%f12, [%10+" dest "] \n\t"\ + "st %%f14, [%11+" dest "] \n\t"\ + +#define ADDPIXELSCLAMPED(dest) \ + "ldd [%5], %%f18 \n\t"\ + "ld [%3+" dest"], %%f0 \n\t"\ + "ld [%6+" dest"], %%f2 \n\t"\ + "ld [%7+" dest"], %%f4 \n\t"\ + "ld [%8+" dest"], %%f6 \n\t"\ + "ld [%9+" dest"], %%f8 \n\t"\ + "ld [%10+" dest"], %%f10 \n\t"\ + "ld [%11+" dest"], %%f12 \n\t"\ + "ld [%12+" dest"], %%f14 \n\t"\ + "fmul8x16 %%f0, %%f18, %%f0 \n\t"\ + "fmul8x16 %%f2, %%f18, %%f2 \n\t"\ + "fmul8x16 %%f4, %%f18, %%f4 \n\t"\ + "fmul8x16 %%f6, %%f18, %%f6 \n\t"\ + "fmul8x16 %%f8, %%f18, %%f8 \n\t"\ + "fmul8x16 %%f10, %%f18, %%f10 \n\t"\ + "fmul8x16 %%f12, %%f18, %%f12 \n\t"\ + "fmul8x16 %%f14, %%f18, %%f14 \n\t"\ + "fpadd16 %%f0, %%f16, %%f0 \n\t"\ + "fpadd16 %%f2, %%f20, %%f2 \n\t"\ + "fpadd16 %%f4, %%f24, %%f4 \n\t"\ + "fpadd16 %%f6, %%f28, %%f6 \n\t"\ + "fpadd16 %%f8, %%f54, %%f8 \n\t"\ + "fpadd16 %%f10, %%f52, %%f10 \n\t"\ + "fpadd16 %%f12, %%f50, %%f12 \n\t"\ + "fpadd16 %%f14, %%f48, %%f14 \n\t"\ + "fpack16 %%f0, %%f0 \n\t"\ + "fpack16 %%f2, %%f2 \n\t"\ + "fpack16 %%f4, %%f4 \n\t"\ + "fpack16 %%f6, %%f6 \n\t"\ + "fpack16 %%f8, %%f8 \n\t"\ + "fpack16 %%f10, %%f10 \n\t"\ + "fpack16 %%f12, %%f12 \n\t"\ + "fpack16 %%f14, %%f14 \n\t"\ + "st %%f0, [%3+" dest "] \n\t"\ + "st %%f2, [%6+" dest "] \n\t"\ + "st %%f4, [%7+" dest "] \n\t"\ + "st %%f6, [%8+" dest "] \n\t"\ + "st %%f8, [%9+" dest "] \n\t"\ + "st %%f10, [%10+" dest "] \n\t"\ + "st %%f12, [%11+" dest "] \n\t"\ + "st %%f14, [%12+" dest "] \n\t"\ + + +void ff_simple_idct_vis(int16_t *data) { + int out1, out2, out3, out4; + DECLARE_ALIGNED(8, int16_t, temp)[8*8]; + + __asm__ volatile( + INIT_IDCT + +#define ADDROUNDER + + // shift right 16-4=12 + LOADSCALE("%2+8") + IDCT4ROWS + STOREROWS("%3+8") + LOADSCALE("%2+0") + IDCT4ROWS + "std %%f48, [%3+112] \n\t" + "std %%f50, [%3+96] \n\t" + "std %%f52, [%3+80] \n\t" + "std %%f54, [%3+64] \n\t" + + // shift right 16+4 + "ldd [%3+8], %%f18 \n\t" + "ldd [%3+24], %%f22 \n\t" + "ldd [%3+40], %%f26 \n\t" + "ldd [%3+56], %%f30 \n\t" + TRANSPOSE + IDCT4ROWS + SCALEROWS + STOREROWS("%2+0") + LOAD("%3+64") + TRANSPOSE + IDCT4ROWS + SCALEROWS + STOREROWS("%2+8") + + : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4) + : "0" (scale), "1" (coeffs), "2" (data), "3" (temp) + ); +} + +void ff_simple_idct_put_vis(uint8_t *dest, int line_size, int16_t *data) { + int out1, out2, out3, out4, out5; + int r1, r2, r3, r4, r5, r6, r7; + + __asm__ volatile( + "wr %%g0, 0x8, %%gsr \n\t" + + INIT_IDCT + + "add %3, %4, %5 \n\t" + "add %5, %4, %6 \n\t" + "add %6, %4, %7 \n\t" + "add %7, %4, %8 \n\t" + "add %8, %4, %9 \n\t" + "add %9, %4, %10 \n\t" + "add %10, %4, %11 \n\t" + + // shift right 16-4=12 + LOADSCALE("%2+8") + IDCT4ROWS + STOREROWS("%2+8") + LOADSCALE("%2+0") + IDCT4ROWS + "std %%f48, [%2+112] \n\t" + "std %%f50, [%2+96] \n\t" + "std %%f52, [%2+80] \n\t" + "std %%f54, [%2+64] \n\t" + +#undef ADDROUNDER +#define ADDROUNDER "fpadd16 %%f28, %%f46, %%f28 \n\t" + + // shift right 16+4 + "ldd [%2+8], %%f18 \n\t" + "ldd [%2+24], %%f22 \n\t" + "ldd [%2+40], %%f26 \n\t" + "ldd [%2+56], %%f30 \n\t" + TRANSPOSE + IDCT4ROWS + PUTPIXELSCLAMPED("0") + LOAD("%2+64") + TRANSPOSE + IDCT4ROWS + PUTPIXELSCLAMPED("4") + + : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4), "=r" (out5), + "=r" (r1), "=r" (r2), "=r" (r3), "=r" (r4), "=r" (r5), "=r" (r6), "=r" (r7) + : "0" (rounder), "1" (coeffs), "2" (data), "3" (dest), "4" (line_size) + ); +} + +void ff_simple_idct_add_vis(uint8_t *dest, int line_size, int16_t *data) { + int out1, out2, out3, out4, out5, out6; + int r1, r2, r3, r4, r5, r6, r7; + + __asm__ volatile( + "wr %%g0, 0x8, %%gsr \n\t" + + INIT_IDCT + + "add %3, %4, %6 \n\t" + "add %6, %4, %7 \n\t" + "add %7, %4, %8 \n\t" + "add %8, %4, %9 \n\t" + "add %9, %4, %10 \n\t" + "add %10, %4, %11 \n\t" + "add %11, %4, %12 \n\t" + +#undef ADDROUNDER +#define ADDROUNDER + + // shift right 16-4=12 + LOADSCALE("%2+8") + IDCT4ROWS + STOREROWS("%2+8") + LOADSCALE("%2+0") + IDCT4ROWS + "std %%f48, [%2+112] \n\t" + "std %%f50, [%2+96] \n\t" + "std %%f52, [%2+80] \n\t" + "std %%f54, [%2+64] \n\t" + +#undef ADDROUNDER +#define ADDROUNDER "fpadd16 %%f28, %%f46, %%f28 \n\t" + + // shift right 16+4 + "ldd [%2+8], %%f18 \n\t" + "ldd [%2+24], %%f22 \n\t" + "ldd [%2+40], %%f26 \n\t" + "ldd [%2+56], %%f30 \n\t" + TRANSPOSE + IDCT4ROWS + ADDPIXELSCLAMPED("0") + LOAD("%2+64") + TRANSPOSE + IDCT4ROWS + ADDPIXELSCLAMPED("4") + + : "=r" (out1), "=r" (out2), "=r" (out3), "=r" (out4), "=r" (out5), "=r" (out6), + "=r" (r1), "=r" (r2), "=r" (r3), "=r" (r4), "=r" (r5), "=r" (r6), "=r" (r7) + : "0" (rounder), "1" (coeffs), "2" (data), "3" (dest), "4" (line_size), "5" (expand) + ); +} diff --git a/ffmpeg/libavcodec/sparc/vis.h b/ffmpeg/libavcodec/sparc/vis.h new file mode 100644 index 0000000..adee91b --- /dev/null +++ b/ffmpeg/libavcodec/sparc/vis.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2003 David S. Miller + * + * 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 + */ + +/* You may be asking why I hard-code the instruction opcodes and don't + * use the normal VIS assembler mnenomics for the VIS instructions. + * + * The reason is that Sun, in their infinite wisdom, decided that a binary + * using a VIS instruction will cause it to be marked (in the ELF headers) + * as doing so, and this prevents the OS from loading such binaries if the + * current cpu doesn't have VIS. There is no way to easily override this + * behavior of the assembler that I am aware of. + * + * This totally defeats what libmpeg2 is trying to do which is allow a + * single binary to be created, and then detect the availability of VIS + * at runtime. + * + * I'm not saying that tainting the binary by default is bad, rather I'm + * saying that not providing a way to override this easily unnecessarily + * ties people's hands. + * + * Thus, we do the opcode encoding by hand and output 32-bit words in + * the assembler to keep the binary from becoming tainted. + */ + +#ifndef AVCODEC_SPARC_VIS_H +#define AVCODEC_SPARC_VIS_H + +#define vis_opc_base ((0x1 << 31) | (0x36 << 19)) +#define vis_opf(X) ((X) << 5) +#define vis_sreg(X) (X) +#define vis_dreg(X) (((X)&0x1f)|((X)>>5)) +#define vis_rs1_s(X) (vis_sreg(X) << 14) +#define vis_rs1_d(X) (vis_dreg(X) << 14) +#define vis_rs2_s(X) (vis_sreg(X) << 0) +#define vis_rs2_d(X) (vis_dreg(X) << 0) +#define vis_rd_s(X) (vis_sreg(X) << 25) +#define vis_rd_d(X) (vis_dreg(X) << 25) + +#define vis_ss2s(opf,rs1,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs1_s(rs1) | \ + vis_rs2_s(rs2) | \ + vis_rd_s(rd))) + +#define vis_dd2d(opf,rs1,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs1_d(rs1) | \ + vis_rs2_d(rs2) | \ + vis_rd_d(rd))) + +#define vis_ss2d(opf,rs1,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs1_s(rs1) | \ + vis_rs2_s(rs2) | \ + vis_rd_d(rd))) + +#define vis_sd2d(opf,rs1,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs1_s(rs1) | \ + vis_rs2_d(rs2) | \ + vis_rd_d(rd))) + +#define vis_d2s(opf,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs2_d(rs2) | \ + vis_rd_s(rd))) + +#define vis_s2d(opf,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs2_s(rs2) | \ + vis_rd_d(rd))) + +#define vis_d12d(opf,rs1,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs1_d(rs1) | \ + vis_rd_d(rd))) + +#define vis_d22d(opf,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs2_d(rs2) | \ + vis_rd_d(rd))) + +#define vis_s12s(opf,rs1,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs1_s(rs1) | \ + vis_rd_s(rd))) + +#define vis_s22s(opf,rs2,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rs2_s(rs2) | \ + vis_rd_s(rd))) + +#define vis_s(opf,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rd_s(rd))) + +#define vis_d(opf,rd) \ + __asm__ volatile (".word %0" \ + : : "i" (vis_opc_base | vis_opf(opf) | \ + vis_rd_d(rd))) + +#define vis_r2m(op,rd,mem) \ + __asm__ volatile (#op "\t%%f" #rd ", [%0]" : : "r" (&(mem)) ) + +#define vis_r2m_2(op,rd,mem1,mem2) \ + __asm__ volatile (#op "\t%%f" #rd ", [%0 + %1]" : : "r" (mem1), "r" (mem2) ) + +#define vis_m2r(op,mem,rd) \ + __asm__ volatile (#op "\t[%0], %%f" #rd : : "r" (&(mem)) ) + +#define vis_m2r_2(op,mem1,mem2,rd) \ + __asm__ volatile (#op "\t[%0 + %1], %%f" #rd : : "r" (mem1), "r" (mem2) ) + +static inline void vis_set_gsr(unsigned int _val) +{ + register unsigned int val __asm__("g1"); + + val = _val; + __asm__ volatile(".word 0xa7804000" + : : "r" (val)); +} + +#define VIS_GSR_ALIGNADDR_MASK 0x0000007 +#define VIS_GSR_ALIGNADDR_SHIFT 0 +#define VIS_GSR_SCALEFACT_MASK 0x0000078 +#define VIS_GSR_SCALEFACT_SHIFT 3 + +#define vis_ld32(mem,rs1) vis_m2r(ld, mem, rs1) +#define vis_ld32_2(mem1,mem2,rs1) vis_m2r_2(ld, mem1, mem2, rs1) +#define vis_st32(rs1,mem) vis_r2m(st, rs1, mem) +#define vis_st32_2(rs1,mem1,mem2) vis_r2m_2(st, rs1, mem1, mem2) +#define vis_ld64(mem,rs1) vis_m2r(ldd, mem, rs1) +#define vis_ld64_2(mem1,mem2,rs1) vis_m2r_2(ldd, mem1, mem2, rs1) +#define vis_st64(rs1,mem) vis_r2m(std, rs1, mem) +#define vis_st64_2(rs1,mem1,mem2) vis_r2m_2(std, rs1, mem1, mem2) + +#define vis_ldblk(mem, rd) \ +do { register void *__mem __asm__("g1"); \ + __mem = &(mem); \ + __asm__ volatile(".word 0xc1985e00 | %1" \ + : \ + : "r" (__mem), \ + "i" (vis_rd_d(rd)) \ + : "memory"); \ +} while (0) + +#define vis_stblk(rd, mem) \ +do { register void *__mem __asm__("g1"); \ + __mem = &(mem); \ + __asm__ volatile(".word 0xc1b85e00 | %1" \ + : \ + : "r" (__mem), \ + "i" (vis_rd_d(rd)) \ + : "memory"); \ +} while (0) + +#define vis_membar_storestore() \ + __asm__ volatile(".word 0x8143e008" : : : "memory") + +#define vis_membar_sync() \ + __asm__ volatile(".word 0x8143e040" : : : "memory") + +/* 16 and 32 bit partitioned addition and subtraction. The normal + * versions perform 4 16-bit or 2 32-bit additions or subtractions. + * The 's' versions perform 2 16-bit or 1 32-bit additions or + * subtractions. + */ + +#define vis_padd16(rs1,rs2,rd) vis_dd2d(0x50, rs1, rs2, rd) +#define vis_padd16s(rs1,rs2,rd) vis_ss2s(0x51, rs1, rs2, rd) +#define vis_padd32(rs1,rs2,rd) vis_dd2d(0x52, rs1, rs2, rd) +#define vis_padd32s(rs1,rs2,rd) vis_ss2s(0x53, rs1, rs2, rd) +#define vis_psub16(rs1,rs2,rd) vis_dd2d(0x54, rs1, rs2, rd) +#define vis_psub16s(rs1,rs2,rd) vis_ss2s(0x55, rs1, rs2, rd) +#define vis_psub32(rs1,rs2,rd) vis_dd2d(0x56, rs1, rs2, rd) +#define vis_psub32s(rs1,rs2,rd) vis_ss2s(0x57, rs1, rs2, rd) + +/* Pixel formatting instructions. */ + +#define vis_pack16(rs2,rd) vis_d2s( 0x3b, rs2, rd) +#define vis_pack32(rs1,rs2,rd) vis_dd2d(0x3a, rs1, rs2, rd) +#define vis_packfix(rs2,rd) vis_d2s( 0x3d, rs2, rd) +#define vis_expand(rs2,rd) vis_s2d( 0x4d, rs2, rd) +#define vis_pmerge(rs1,rs2,rd) vis_ss2d(0x4b, rs1, rs2, rd) + +/* Partitioned multiply instructions. */ + +#define vis_mul8x16(rs1,rs2,rd) vis_sd2d(0x31, rs1, rs2, rd) +#define vis_mul8x16au(rs1,rs2,rd) vis_ss2d(0x33, rs1, rs2, rd) +#define vis_mul8x16al(rs1,rs2,rd) vis_ss2d(0x35, rs1, rs2, rd) +#define vis_mul8sux16(rs1,rs2,rd) vis_dd2d(0x36, rs1, rs2, rd) +#define vis_mul8ulx16(rs1,rs2,rd) vis_dd2d(0x37, rs1, rs2, rd) +#define vis_muld8sux16(rs1,rs2,rd) vis_ss2d(0x38, rs1, rs2, rd) +#define vis_muld8ulx16(rs1,rs2,rd) vis_ss2d(0x39, rs1, rs2, rd) + +/* Alignment instructions. */ + +static inline const void *vis_alignaddr(const void *_ptr) +{ + register const void *ptr __asm__("g1"); + + ptr = _ptr; + + __asm__ volatile(".word %2" + : "=&r" (ptr) + : "0" (ptr), + "i" (vis_opc_base | vis_opf(0x18) | + vis_rs1_s(1) | + vis_rs2_s(0) | + vis_rd_s(1))); + + return ptr; +} + +static inline void vis_alignaddr_g0(void *_ptr) +{ + register void *ptr __asm__("g1"); + + ptr = _ptr; + + __asm__ volatile(".word %2" + : "=&r" (ptr) + : "0" (ptr), + "i" (vis_opc_base | vis_opf(0x18) | + vis_rs1_s(1) | + vis_rs2_s(0) | + vis_rd_s(0))); +} + +static inline void *vis_alignaddrl(void *_ptr) +{ + register void *ptr __asm__("g1"); + + ptr = _ptr; + + __asm__ volatile(".word %2" + : "=&r" (ptr) + : "0" (ptr), + "i" (vis_opc_base | vis_opf(0x19) | + vis_rs1_s(1) | + vis_rs2_s(0) | + vis_rd_s(1))); + + return ptr; +} + +static inline void vis_alignaddrl_g0(void *_ptr) +{ + register void *ptr __asm__("g1"); + + ptr = _ptr; + + __asm__ volatile(".word %2" + : "=&r" (ptr) + : "0" (ptr), + "i" (vis_opc_base | vis_opf(0x19) | + vis_rs1_s(1) | + vis_rs2_s(0) | + vis_rd_s(0))); +} + +#define vis_faligndata(rs1,rs2,rd) vis_dd2d(0x48, rs1, rs2, rd) + +/* Logical operate instructions. */ + +#define vis_fzero(rd) vis_d( 0x60, rd) +#define vis_fzeros(rd) vis_s( 0x61, rd) +#define vis_fone(rd) vis_d( 0x7e, rd) +#define vis_fones(rd) vis_s( 0x7f, rd) +#define vis_src1(rs1,rd) vis_d12d(0x74, rs1, rd) +#define vis_src1s(rs1,rd) vis_s12s(0x75, rs1, rd) +#define vis_src2(rs2,rd) vis_d22d(0x78, rs2, rd) +#define vis_src2s(rs2,rd) vis_s22s(0x79, rs2, rd) +#define vis_not1(rs1,rd) vis_d12d(0x6a, rs1, rd) +#define vis_not1s(rs1,rd) vis_s12s(0x6b, rs1, rd) +#define vis_not2(rs2,rd) vis_d22d(0x66, rs2, rd) +#define vis_not2s(rs2,rd) vis_s22s(0x67, rs2, rd) +#define vis_or(rs1,rs2,rd) vis_dd2d(0x7c, rs1, rs2, rd) +#define vis_ors(rs1,rs2,rd) vis_ss2s(0x7d, rs1, rs2, rd) +#define vis_nor(rs1,rs2,rd) vis_dd2d(0x62, rs1, rs2, rd) +#define vis_nors(rs1,rs2,rd) vis_ss2s(0x63, rs1, rs2, rd) +#define vis_and(rs1,rs2,rd) vis_dd2d(0x70, rs1, rs2, rd) +#define vis_ands(rs1,rs2,rd) vis_ss2s(0x71, rs1, rs2, rd) +#define vis_nand(rs1,rs2,rd) vis_dd2d(0x6e, rs1, rs2, rd) +#define vis_nands(rs1,rs2,rd) vis_ss2s(0x6f, rs1, rs2, rd) +#define vis_xor(rs1,rs2,rd) vis_dd2d(0x6c, rs1, rs2, rd) +#define vis_xors(rs1,rs2,rd) vis_ss2s(0x6d, rs1, rs2, rd) +#define vis_xnor(rs1,rs2,rd) vis_dd2d(0x72, rs1, rs2, rd) +#define vis_xnors(rs1,rs2,rd) vis_ss2s(0x73, rs1, rs2, rd) +#define vis_ornot1(rs1,rs2,rd) vis_dd2d(0x7a, rs1, rs2, rd) +#define vis_ornot1s(rs1,rs2,rd) vis_ss2s(0x7b, rs1, rs2, rd) +#define vis_ornot2(rs1,rs2,rd) vis_dd2d(0x76, rs1, rs2, rd) +#define vis_ornot2s(rs1,rs2,rd) vis_ss2s(0x77, rs1, rs2, rd) +#define vis_andnot1(rs1,rs2,rd) vis_dd2d(0x68, rs1, rs2, rd) +#define vis_andnot1s(rs1,rs2,rd) vis_ss2s(0x69, rs1, rs2, rd) +#define vis_andnot2(rs1,rs2,rd) vis_dd2d(0x64, rs1, rs2, rd) +#define vis_andnot2s(rs1,rs2,rd) vis_ss2s(0x65, rs1, rs2, rd) + +/* Pixel component distance. */ + +#define vis_pdist(rs1,rs2,rd) vis_dd2d(0x3e, rs1, rs2, rd) + +#endif /* AVCODEC_SPARC_VIS_H */ diff --git a/ffmpeg/libavcodec/srtdec.c b/ffmpeg/libavcodec/srtdec.c new file mode 100644 index 0000000..267561c --- /dev/null +++ b/ffmpeg/libavcodec/srtdec.c @@ -0,0 +1,282 @@ +/* + * SubRip subtitle decoder + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/parseutils.h" +#include "avcodec.h" +#include "ass.h" + +static int html_color_parse(AVCodecContext *avctx, const char *str) +{ + uint8_t rgba[4]; + if (av_parse_color(rgba, str, strcspn(str, "\" >"), avctx) < 0) + return -1; + return rgba[0] | rgba[1] << 8 | rgba[2] << 16; +} + +enum { + PARAM_UNKNOWN = -1, + PARAM_SIZE, + PARAM_COLOR, + PARAM_FACE, + PARAM_NUMBER +}; + +typedef struct { + char tag[128]; + char param[PARAM_NUMBER][128]; +} SrtStack; + +static const char *srt_to_ass(AVCodecContext *avctx, char *out, char *out_end, + const char *in, int x1, int y1, int x2, int y2) +{ + char *param, buffer[128], tmp[128]; + int len, tag_close, sptr = 1, line_start = 1, an = 0, end = 0; + SrtStack stack[16]; + + stack[0].tag[0] = 0; + strcpy(stack[0].param[PARAM_SIZE], "{\\fs}"); + strcpy(stack[0].param[PARAM_COLOR], "{\\c}"); + strcpy(stack[0].param[PARAM_FACE], "{\\fn}"); + + if (x1 >= 0 && y1 >= 0) { + if (x2 >= 0 && y2 >= 0 && (x2 != x1 || y2 != y1)) + snprintf(out, out_end-out, + "{\\an1}{\\move(%d,%d,%d,%d)}", x1, y1, x2, y2); + else + snprintf(out, out_end-out, "{\\an1}{\\pos(%d,%d)}", x1, y1); + out += strlen(out); + } + + for (; out < out_end && !end && *in; in++) { + switch (*in) { + case '\r': + break; + case '\n': + if (line_start) { + end = 1; + break; + } + while (out[-1] == ' ') + out--; + snprintf(out, out_end-out, "\\N"); + if(out= 0 && len > 0; + if ((an != 1 && (len = 0, sscanf(in, "{\\%*[^}]}%n", &len) >= 0 && len > 0)) || + (len = 0, sscanf(in, "{%*1[CcFfoPSsYy]:%*[^}]}%n", &len) >= 0 && len > 0)) { + in += len - 1; + } else + *out++ = *in; + break; + case '<': + tag_close = in[1] == '/'; + len = 0; + if (sscanf(in+tag_close+1, "%127[^>]>%n", buffer, &len) >= 1 && len > 0) { + if ((param = strchr(buffer, ' '))) + *param++ = 0; + if ((!tag_close && sptr < FF_ARRAY_ELEMS(stack)) || + ( tag_close && sptr > 0 && !strcmp(stack[sptr-1].tag, buffer))) { + int i, j, unknown = 0; + in += len + tag_close; + if (!tag_close) + memset(stack+sptr, 0, sizeof(*stack)); + if (!strcmp(buffer, "font")) { + if (tag_close) { + for (i=PARAM_NUMBER-1; i>=0; i--) + if (stack[sptr-1].param[i][0]) + for (j=sptr-2; j>=0; j--) + if (stack[j].param[i][0]) { + snprintf(out, out_end-out, + "%s", stack[j].param[i]); + if(out", buffer); + } + if (tag_close) { + sptr--; + } else if (unknown && !strstr(in, tmp)) { + in -= len + tag_close; + *out++ = *in; + } else + av_strlcpy(stack[sptr++].tag, buffer, + sizeof(stack[0].tag)); + break; + } + } + default: + *out++ = *in; + break; + } + if (*in != ' ' && *in != '\r' && *in != '\n') + line_start = 0; + } + + out = FFMIN(out, out_end-3); + while (!strncmp(out-2, "\\N", 2)) + out -= 2; + while (out[-1] == ' ') + out--; + snprintf(out, out_end-out, "\r\n"); + return in; +} + +static const char *read_ts(const char *buf, int *ts_start, int *ts_end, + int *x1, int *y1, int *x2, int *y2) +{ + int i, hs, ms, ss, he, me, se; + + for (i=0; i<2; i++) { + /* try to read timestamps in either the first or second line */ + int c = sscanf(buf, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d" + "%*[ ]X1:%u X2:%u Y1:%u Y2:%u", + &hs, &ms, &ss, ts_start, &he, &me, &se, ts_end, + x1, x2, y1, y2); + buf += strcspn(buf, "\n") + 1; + if (c >= 8) { + *ts_start = 100*(ss + 60*(ms + 60*hs)) + *ts_start/10; + *ts_end = 100*(se + 60*(me + 60*he)) + *ts_end /10; + return buf; + } + } + return NULL; +} + +static int srt_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + int ts_start, ts_end, x1 = -1, y1 = -1, x2 = -1, y2 = -1; + char buffer[2048]; + const char *ptr = avpkt->data; + const char *end = avpkt->data + avpkt->size; + int size; + const uint8_t *p = av_packet_get_side_data(avpkt, AV_PKT_DATA_SUBTITLE_POSITION, &size); + + if (p && size == 16) { + x1 = AV_RL32(p ); + y1 = AV_RL32(p + 4); + x2 = AV_RL32(p + 8); + y2 = AV_RL32(p + 12); + } + + if (avpkt->size <= 0) + return avpkt->size; + + while (ptr < end && *ptr) { + if (avctx->codec->id == AV_CODEC_ID_SRT) { + ptr = read_ts(ptr, &ts_start, &ts_end, &x1, &y1, &x2, &y2); + if (!ptr) + break; + } else { + // Do final divide-by-10 outside rescale to force rounding down. + ts_start = av_rescale_q(avpkt->pts, + avctx->time_base, + (AVRational){1,100}); + ts_end = av_rescale_q(avpkt->pts + avpkt->duration, + avctx->time_base, + (AVRational){1,100}); + } + ptr = srt_to_ass(avctx, buffer, buffer+sizeof(buffer), ptr, + x1, y1, x2, y2); + ff_ass_add_rect(sub, buffer, ts_start, ts_end-ts_start, 0); + } + + *got_sub_ptr = sub->num_rects > 0; + return avpkt->size; +} + +#if CONFIG_SRT_DECODER +/* deprecated decoder */ +AVCodec ff_srt_decoder = { + .name = "srt", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle with embedded timing"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SRT, + .init = ff_ass_subtitle_header_default, + .decode = srt_decode_frame, +}; +#endif + +#if CONFIG_SUBRIP_DECODER +AVCodec ff_subrip_decoder = { + .name = "subrip", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SUBRIP, + .init = ff_ass_subtitle_header_default, + .decode = srt_decode_frame, +}; +#endif diff --git a/ffmpeg/libavcodec/srtenc.c b/ffmpeg/libavcodec/srtenc.c new file mode 100644 index 0000000..3036a7f --- /dev/null +++ b/ffmpeg/libavcodec/srtenc.c @@ -0,0 +1,324 @@ +/* + * SubRip subtitle encoder + * Copyright (c) 2010 Aurelien Jacobs + * + * 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 "avcodec.h" +#include "libavutil/avstring.h" +#include "ass_split.h" +#include "ass.h" + + +#define SRT_STACK_SIZE 64 + +typedef struct { + AVCodecContext *avctx; + ASSSplitContext *ass_ctx; + char buffer[2048]; + char *ptr; + char *end; + char *dialog_start; + int count; + char stack[SRT_STACK_SIZE]; + int stack_ptr; + int alignment_applied; +} SRTContext; + + +#ifdef __GNUC__ +__attribute__ ((__format__ (__printf__, 2, 3))) +#endif +static void srt_print(SRTContext *s, const char *str, ...) +{ + va_list vargs; + va_start(vargs, str); + s->ptr += vsnprintf(s->ptr, s->end - s->ptr, str, vargs); + va_end(vargs); +} + +static int srt_stack_push(SRTContext *s, const char c) +{ + if (s->stack_ptr >= SRT_STACK_SIZE) + return -1; + s->stack[s->stack_ptr++] = c; + return 0; +} + +static char srt_stack_pop(SRTContext *s) +{ + if (s->stack_ptr <= 0) + return 0; + return s->stack[--s->stack_ptr]; +} + +static int srt_stack_find(SRTContext *s, const char c) +{ + int i; + for (i = s->stack_ptr-1; i >= 0; i--) + if (s->stack[i] == c) + break; + return i; +} + +static void srt_close_tag(SRTContext *s, char tag) +{ + srt_print(s, "", tag, tag == 'f' ? "ont" : ""); +} + +static void srt_stack_push_pop(SRTContext *s, const char c, int close) +{ + if (close) { + int i = c ? srt_stack_find(s, c) : 0; + if (i < 0) + return; + while (s->stack_ptr != i) + srt_close_tag(s, srt_stack_pop(s)); + } else if (srt_stack_push(s, c) < 0) + av_log(s->avctx, AV_LOG_ERROR, "tag stack overflow\n"); +} + +static void srt_style_apply(SRTContext *s, const char *style) +{ + ASSStyle *st = ff_ass_style_get(s->ass_ctx, style); + if (st) { + int c = st->primary_color & 0xFFFFFF; + if (st->font_name && strcmp(st->font_name, ASS_DEFAULT_FONT) || + st->font_size != ASS_DEFAULT_FONT_SIZE || + c != ASS_DEFAULT_COLOR) { + srt_print(s, "font_name && strcmp(st->font_name, ASS_DEFAULT_FONT)) + srt_print(s, " face=\"%s\"", st->font_name); + if (st->font_size != ASS_DEFAULT_FONT_SIZE) + srt_print(s, " size=\"%d\"", st->font_size); + if (c != ASS_DEFAULT_COLOR) + srt_print(s, " color=\"#%06x\"", + (c & 0xFF0000) >> 16 | c & 0xFF00 | (c & 0xFF) << 16); + srt_print(s, ">"); + srt_stack_push(s, 'f'); + } + if (st->bold != ASS_DEFAULT_BOLD) { + srt_print(s, ""); + srt_stack_push(s, 'b'); + } + if (st->italic != ASS_DEFAULT_ITALIC) { + srt_print(s, ""); + srt_stack_push(s, 'i'); + } + if (st->underline != ASS_DEFAULT_UNDERLINE) { + srt_print(s, ""); + srt_stack_push(s, 'u'); + } + if (st->alignment != ASS_DEFAULT_ALIGNMENT) { + srt_print(s, "{\\an%d}", st->alignment); + s->alignment_applied = 1; + } + } +} + + +static av_cold int srt_encode_init(AVCodecContext *avctx) +{ + SRTContext *s = avctx->priv_data; + s->avctx = avctx; + s->ass_ctx = ff_ass_split(avctx->subtitle_header); + return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; +} + +static void srt_text_cb(void *priv, const char *text, int len) +{ + SRTContext *s = priv; + av_strlcpy(s->ptr, text, FFMIN(s->end-s->ptr, len+1)); + s->ptr += len; +} + +static void srt_new_line_cb(void *priv, int forced) +{ + srt_print(priv, "\r\n"); +} + +static void srt_style_cb(void *priv, char style, int close) +{ + srt_stack_push_pop(priv, style, close); + if (!close) + srt_print(priv, "<%c>", style); +} + +static void srt_color_cb(void *priv, unsigned int color, unsigned int color_id) +{ + if (color_id > 1) + return; + srt_stack_push_pop(priv, 'f', color == 0xFFFFFFFF); + if (color != 0xFFFFFFFF) + srt_print(priv, "", + (color & 0xFF0000) >> 16 | color & 0xFF00 | (color & 0xFF) << 16); +} + +static void srt_font_name_cb(void *priv, const char *name) +{ + srt_stack_push_pop(priv, 'f', !name); + if (name) + srt_print(priv, "", name); +} + +static void srt_font_size_cb(void *priv, int size) +{ + srt_stack_push_pop(priv, 'f', size < 0); + if (size >= 0) + srt_print(priv, "", size); +} + +static void srt_alignment_cb(void *priv, int alignment) +{ + SRTContext *s = priv; + if (!s->alignment_applied && alignment >= 0) { + srt_print(s, "{\\an%d}", alignment); + s->alignment_applied = 1; + } +} + +static void srt_cancel_overrides_cb(void *priv, const char *style) +{ + srt_stack_push_pop(priv, 0, 1); + srt_style_apply(priv, style); +} + +static void srt_move_cb(void *priv, int x1, int y1, int x2, int y2, + int t1, int t2) +{ + SRTContext *s = priv; + + if (s->avctx->codec->id == AV_CODEC_ID_SRT) { + char buffer[32]; + int len = snprintf(buffer, sizeof(buffer), + " X1:%03u X2:%03u Y1:%03u Y2:%03u", x1, x2, y1, y2); + if (s->end - s->ptr > len) { + memmove(s->dialog_start+len, s->dialog_start, s->ptr-s->dialog_start+1); + memcpy(s->dialog_start, buffer, len); + s->ptr += len; + } + } +} + +static void srt_end_cb(void *priv) +{ + SRTContext *s = priv; + + srt_stack_push_pop(priv, 0, 1); + if (s->avctx->codec->id == AV_CODEC_ID_SRT) + srt_print(priv, "\r\n\r\n"); +} + +static const ASSCodesCallbacks srt_callbacks = { + .text = srt_text_cb, + .new_line = srt_new_line_cb, + .style = srt_style_cb, + .color = srt_color_cb, + .font_name = srt_font_name_cb, + .font_size = srt_font_size_cb, + .alignment = srt_alignment_cb, + .cancel_overrides = srt_cancel_overrides_cb, + .move = srt_move_cb, + .end = srt_end_cb, +}; + +static int srt_encode_frame(AVCodecContext *avctx, + unsigned char *buf, int bufsize, const AVSubtitle *sub) +{ + SRTContext *s = avctx->priv_data; + ASSDialog *dialog; + int i, len, num; + + s->ptr = s->buffer; + s->end = s->ptr + sizeof(s->buffer); + + for (i=0; inum_rects; i++) { + + if (sub->rects[i]->type != SUBTITLE_ASS) { + av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n"); + return AVERROR(ENOSYS); + } + + dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num); + for (; dialog && num--; dialog++) { + if (avctx->codec->id == AV_CODEC_ID_SRT) { + int sh, sm, ss, sc = 10 * dialog->start; + int eh, em, es, ec = 10 * dialog->end; + sh = sc/3600000; sc -= 3600000*sh; + sm = sc/ 60000; sc -= 60000*sm; + ss = sc/ 1000; sc -= 1000*ss; + eh = ec/3600000; ec -= 3600000*eh; + em = ec/ 60000; ec -= 60000*em; + es = ec/ 1000; ec -= 1000*es; + srt_print(s,"%d\r\n%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d\r\n", + ++s->count, sh, sm, ss, sc, eh, em, es, ec); + s->dialog_start = s->ptr - 2; + } + s->alignment_applied = 0; + srt_style_apply(s, dialog->style); + ff_ass_split_override_codes(&srt_callbacks, s, dialog->text); + } + } + + if (s->ptr == s->buffer) + return 0; + + len = av_strlcpy(buf, s->buffer, bufsize); + + if (len > bufsize-1) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); + return -1; + } + + return len; +} + +static int srt_encode_close(AVCodecContext *avctx) +{ + SRTContext *s = avctx->priv_data; + ff_ass_split_free(s->ass_ctx); + return 0; +} + +#if CONFIG_SRT_ENCODER +/* deprecated encoder */ +AVCodec ff_srt_encoder = { + .name = "srt", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle with embedded timing"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SRT, + .priv_data_size = sizeof(SRTContext), + .init = srt_encode_init, + .encode_sub = srt_encode_frame, + .close = srt_encode_close, +}; +#endif + +#if CONFIG_SUBRIP_ENCODER +AVCodec ff_subrip_encoder = { + .name = "subrip", + .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SUBRIP, + .priv_data_size = sizeof(SRTContext), + .init = srt_encode_init, + .encode_sub = srt_encode_frame, + .close = srt_encode_close, +}; +#endif diff --git a/ffmpeg/libavcodec/subviewerdec.c b/ffmpeg/libavcodec/subviewerdec.c new file mode 100644 index 0000000..63be418 --- /dev/null +++ b/ffmpeg/libavcodec/subviewerdec.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012 Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * SubViewer subtitle decoder + * @see https://en.wikipedia.org/wiki/SubViewer + */ + +#include "avcodec.h" +#include "ass.h" +#include "libavutil/bprint.h" + +static int subviewer_event_to_ass(AVBPrint *buf, const char *p) +{ + while (*p) { + if (!strncmp(p, "[br]", 4)) { + av_bprintf(buf, "\\N"); + p += 4; + } else { + if (p[0] == '\n' && p[1]) + av_bprintf(buf, "\\N"); + else if (*p != '\n' && *p != '\r') + av_bprint_chars(buf, *p, 1); + p++; + } + } + + av_bprintf(buf, "\r\n"); + return 0; +} + +static int subviewer_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + char c; + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + AVBPrint buf; + + /* To be removed later */ + if (ptr && sscanf(ptr, "%*u:%*u:%*u.%*u,%*u:%*u:%*u.%*u%c", &c) == 1) { + av_log(avctx, AV_LOG_ERROR, "AVPacket is not clean (contains timing " + "information). You need to upgrade your libavformat or " + "sanitize your packet.\n"); + return AVERROR_INVALIDDATA; + } + + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + // note: no need to rescale pts & duration since they are in the same + // timebase as ASS (1/100) + if (ptr && avpkt->size > 0 && !subviewer_event_to_ass(&buf, ptr)) + ff_ass_add_rect(sub, buf.str, avpkt->pts, avpkt->duration, 0); + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +AVCodec ff_subviewer_decoder = { + .name = "subviewer", + .long_name = NULL_IF_CONFIG_SMALL("SubViewer subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SUBVIEWER, + .decode = subviewer_decode_frame, + .init = ff_ass_subtitle_header_default, +}; diff --git a/ffmpeg/libavcodec/sunrast.c b/ffmpeg/libavcodec/sunrast.c new file mode 100644 index 0000000..1e25b60 --- /dev/null +++ b/ffmpeg/libavcodec/sunrast.c @@ -0,0 +1,217 @@ +/* + * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image decoder + * Copyright (c) 2007, 2008 Ivo van Poorten + * + * 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" +#include "sunrast.h" + +static int sunrast_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end = avpkt->data + avpkt->size; + AVFrame * const p = data; + unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen; + uint8_t *ptr, *ptr2 = NULL; + const uint8_t *bufstart = buf; + int ret; + + if (avpkt->size < 32) + return AVERROR_INVALIDDATA; + + if (AV_RB32(buf) != RAS_MAGIC) { + av_log(avctx, AV_LOG_ERROR, "this is not sunras encoded data\n"); + return AVERROR_INVALIDDATA; + } + + w = AV_RB32(buf + 4); + h = AV_RB32(buf + 8); + depth = AV_RB32(buf + 12); + type = AV_RB32(buf + 20); + maptype = AV_RB32(buf + 24); + maplength = AV_RB32(buf + 28); + buf += 32; + + if (type == RT_EXPERIMENTAL) { + avpriv_request_sample(avctx, "TIFF/IFF/EXPERIMENTAL (compression) type"); + return AVERROR_PATCHWELCOME; + } + if (type > RT_FORMAT_IFF) { + av_log(avctx, AV_LOG_ERROR, "invalid (compression) type\n"); + return AVERROR_INVALIDDATA; + } + if (av_image_check_size(w, h, 0, avctx)) { + av_log(avctx, AV_LOG_ERROR, "invalid image size\n"); + return AVERROR_INVALIDDATA; + } + if (maptype == RMT_RAW) { + avpriv_request_sample(avctx, "Unknown colormap type"); + return AVERROR_PATCHWELCOME; + } + if (maptype > RMT_RAW) { + av_log(avctx, AV_LOG_ERROR, "invalid colormap type\n"); + return AVERROR_INVALIDDATA; + } + + if (type == RT_FORMAT_TIFF || type == RT_FORMAT_IFF) { + av_log(avctx, AV_LOG_ERROR, "unsupported (compression) type\n"); + return -1; + } + + switch (depth) { + case 1: + avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_MONOWHITE; + break; + case 4: + avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_NONE; + break; + case 8: + avctx->pix_fmt = maplength ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8; + break; + case 24: + avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_BGR24; + break; + case 32: + avctx->pix_fmt = (type == RT_FORMAT_RGB) ? AV_PIX_FMT_0RGB : AV_PIX_FMT_0BGR; + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid depth\n"); + return AVERROR_INVALIDDATA; + } + + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + + if (buf_end - buf < maplength) + return AVERROR_INVALIDDATA; + + if (depth > 8 && maplength) { + av_log(avctx, AV_LOG_WARNING, "useless colormap found or file is corrupted, trying to recover\n"); + + } else if (maplength) { + unsigned int len = maplength / 3; + + if (maplength % 3 || maplength > 768) { + av_log(avctx, AV_LOG_WARNING, "invalid colormap length\n"); + return AVERROR_INVALIDDATA; + } + + ptr = p->data[1]; + for (x = 0; x < len; x++, ptr += 4) + *(uint32_t *)ptr = (0xFFU<<24) + (buf[x]<<16) + (buf[len+x]<<8) + buf[len+len+x]; + } + + buf += maplength; + + if (maplength && depth < 8) { + ptr = ptr2 = av_malloc((w + 15) * h); + if (!ptr) + return AVERROR(ENOMEM); + stride = (w + 15 >> 3) * depth; + } else { + ptr = p->data[0]; + stride = p->linesize[0]; + } + + /* scanlines are aligned on 16 bit boundaries */ + len = (depth * w + 7) >> 3; + alen = len + (len & 1); + + if (type == RT_BYTE_ENCODED) { + int value, run; + uint8_t *end = ptr + h * stride; + + x = 0; + while (ptr != end && buf < buf_end) { + run = 1; + if (buf_end - buf < 1) + return AVERROR_INVALIDDATA; + + if ((value = *buf++) == RLE_TRIGGER) { + run = *buf++ + 1; + if (run != 1) + value = *buf++; + } + while (run--) { + if (x < len) + ptr[x] = value; + if (++x >= alen) { + x = 0; + ptr += stride; + if (ptr == end) + break; + } + } + } + } else { + for (y = 0; y < h; y++) { + if (buf_end - buf < len) + break; + memcpy(ptr, buf, len); + ptr += stride; + buf += alen; + } + } + if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && depth < 8) { + uint8_t *ptr_free = ptr2; + ptr = p->data[0]; + for (y=0; y> 3) * depth; x++) { + if (depth == 1) { + ptr[8*x] = ptr2[x] >> 7; + ptr[8*x+1] = ptr2[x] >> 6 & 1; + ptr[8*x+2] = ptr2[x] >> 5 & 1; + ptr[8*x+3] = ptr2[x] >> 4 & 1; + ptr[8*x+4] = ptr2[x] >> 3 & 1; + ptr[8*x+5] = ptr2[x] >> 2 & 1; + ptr[8*x+6] = ptr2[x] >> 1 & 1; + ptr[8*x+7] = ptr2[x] & 1; + } else { + ptr[2*x] = ptr2[x] >> 4; + ptr[2*x+1] = ptr2[x] & 0xF; + } + } + ptr += p->linesize[0]; + ptr2 += (w + 15 >> 3) * depth; + } + av_freep(&ptr_free); + } + + *got_frame = 1; + + return buf - bufstart; +} + +AVCodec ff_sunrast_decoder = { + .name = "sunrast", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SUNRAST, + .decode = sunrast_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), +}; diff --git a/ffmpeg/libavcodec/sunrast.h b/ffmpeg/libavcodec/sunrast.h new file mode 100644 index 0000000..d9fe307 --- /dev/null +++ b/ffmpeg/libavcodec/sunrast.h @@ -0,0 +1,56 @@ +/* + * Sun Rasterfile Image Format + * Copyright (c) 2007, 2008 Ivo van Poorten + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_SUNRAST_H +#define AVCODEC_SUNRAST_H + +#define RAS_MAGIC 0x59a66a95 + +#define RMT_NONE 0 +#define RMT_EQUAL_RGB 1 +#define RMT_RAW 2 ///< the data layout of this map type is unknown + +/* The Old and Standard format types indicate that the image data is + * uncompressed. There is no difference between the two formats. */ +#define RT_OLD 0 +#define RT_STANDARD 1 + +/* The Byte-Encoded format type indicates that the image data is compressed + * using a run-length encoding scheme. */ +#define RT_BYTE_ENCODED 2 +#define RLE_TRIGGER 0x80 + +/* The RGB format type indicates that the image is uncompressed with reverse + * component order from Old and Standard (RGB vs BGR). */ +#define RT_FORMAT_RGB 3 + +/* The TIFF and IFF format types indicate that the raster file was originally + * converted from either of these file formats. We do not have any samples or + * documentation of the format details. */ +#define RT_FORMAT_TIFF 4 +#define RT_FORMAT_IFF 5 + +/* The Experimental format type is implementation-specific and is generally an + * indication that the image file does not conform to the Sun Raster file + * format specification. */ +#define RT_EXPERIMENTAL 0xffff + +#endif /* AVCODEC_SUNRAST_H */ diff --git a/ffmpeg/libavcodec/sunrastenc.c b/ffmpeg/libavcodec/sunrastenc.c new file mode 100644 index 0000000..2c7e72f --- /dev/null +++ b/ffmpeg/libavcodec/sunrastenc.c @@ -0,0 +1,224 @@ +/* + * Sun Rasterfile (.sun/.ras/im{1,8,24}/.sunras) image encoder + * Copyright (c) 2012 Aneesh Dogra (lionaneesh) + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "sunrast.h" + +typedef struct SUNRASTContext { + AVFrame picture; + PutByteContext p; + int depth; ///< depth of pixel + int length; ///< length (bytes) of image + int type; ///< type of file + int maptype; ///< type of colormap + int maplength; ///< length (bytes) of colormap + int size; +} SUNRASTContext; + +static void sunrast_image_write_header(AVCodecContext *avctx) +{ + SUNRASTContext *s = avctx->priv_data; + + bytestream2_put_be32u(&s->p, RAS_MAGIC); + bytestream2_put_be32u(&s->p, avctx->width); + bytestream2_put_be32u(&s->p, avctx->height); + bytestream2_put_be32u(&s->p, s->depth); + bytestream2_put_be32u(&s->p, s->length); + bytestream2_put_be32u(&s->p, s->type); + bytestream2_put_be32u(&s->p, s->maptype); + bytestream2_put_be32u(&s->p, s->maplength); +} + +static void sunrast_image_write_image(AVCodecContext *avctx, + const uint8_t *pixels, + const uint32_t *palette_data, + int linesize) +{ + SUNRASTContext *s = avctx->priv_data; + const uint8_t *ptr; + int len, alen, x, y; + + if (s->maplength) { // palettized + PutByteContext pb_r, pb_g; + int len = s->maplength / 3; + + pb_r = s->p; + bytestream2_skip_p(&s->p, len); + pb_g = s->p; + bytestream2_skip_p(&s->p, len); + + for (x = 0; x < len; x++) { + uint32_t pixel = palette_data[x]; + + bytestream2_put_byteu(&pb_r, (pixel >> 16) & 0xFF); + bytestream2_put_byteu(&pb_g, (pixel >> 8) & 0xFF); + bytestream2_put_byteu(&s->p, pixel & 0xFF); + } + } + + len = (s->depth * avctx->width + 7) >> 3; + alen = len + (len & 1); + ptr = pixels; + + if (s->type == RT_BYTE_ENCODED) { + uint8_t value, value2; + int run; + + ptr = pixels; + +#define GET_VALUE y >= avctx->height ? 0 : x >= len ? ptr[len-1] : ptr[x] + + x = 0, y = 0; + value2 = GET_VALUE; + while (y < avctx->height) { + run = 1; + value = value2; + x++; + if (x >= alen) { + x = 0; + ptr += linesize, y++; + } + + value2 = GET_VALUE; + while (value2 == value && run < 256 && y < avctx->height) { + x++; + run++; + if (x >= alen) { + x = 0; + ptr += linesize, y++; + } + value2 = GET_VALUE; + } + + if (run > 2 || value == RLE_TRIGGER) { + bytestream2_put_byteu(&s->p, RLE_TRIGGER); + bytestream2_put_byteu(&s->p, run - 1); + if (run > 1) + bytestream2_put_byteu(&s->p, value); + } else if (run == 1) { + bytestream2_put_byteu(&s->p, value); + } else + bytestream2_put_be16u(&s->p, (value << 8) | value); + } + + // update data length for header + s->length = bytestream2_tell_p(&s->p) - 32 - s->maplength; + } else { + for (y = 0; y < avctx->height; y++) { + bytestream2_put_buffer(&s->p, ptr, len); + if (len < alen) + bytestream2_put_byteu(&s->p, 0); + ptr += linesize; + } + } +} + +static av_cold int sunrast_encode_init(AVCodecContext *avctx) +{ + SUNRASTContext *s = avctx->priv_data; + + switch (avctx->coder_type) { + case FF_CODER_TYPE_RLE: + s->type = RT_BYTE_ENCODED; + break; + case FF_CODER_TYPE_RAW: + s->type = RT_STANDARD; + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid coder_type\n"); + return AVERROR(EINVAL); + } + + avctx->coded_frame = &s->picture; + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + s->maptype = RMT_NONE; + s->maplength = 0; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_MONOWHITE: + s->depth = 1; + break; + case AV_PIX_FMT_PAL8 : + s->maptype = RMT_EQUAL_RGB; + s->maplength = 3 * 256; + case AV_PIX_FMT_GRAY8: + s->depth = 8; + break; + case AV_PIX_FMT_BGR24: + s->depth = 24; + break; + default: + return AVERROR_BUG; + } + s->length = avctx->height * (FFALIGN(avctx->width * s->depth, 16) >> 3); + s->size = 32 + s->maplength + + s->length * (s->type == RT_BYTE_ENCODED ? 2 : 1); + + return 0; +} + +static int sunrast_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + SUNRASTContext *s = avctx->priv_data; + int ret; + + if ((ret = ff_alloc_packet2(avctx, avpkt, s->size)) < 0) + return ret; + + bytestream2_init_writer(&s->p, avpkt->data, avpkt->size); + sunrast_image_write_header(avctx); + sunrast_image_write_image(avctx, frame->data[0], + (const uint32_t *)frame->data[1], + frame->linesize[0]); + // update data length in header after RLE + if (s->type == RT_BYTE_ENCODED) + AV_WB32(&avpkt->data[16], s->length); + + *got_packet_ptr = 1; + avpkt->flags |= AV_PKT_FLAG_KEY; + avpkt->size = bytestream2_tell_p(&s->p); + return 0; +} + +static const AVCodecDefault sunrast_defaults[] = { + { "coder", "rle" }, + { NULL }, +}; + +AVCodec ff_sunrast_encoder = { + .name = "sunrast", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SUNRAST, + .priv_data_size = sizeof(SUNRASTContext), + .init = sunrast_encode_init, + .encode2 = sunrast_encode_frame, + .defaults = sunrast_defaults, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, + AV_PIX_FMT_PAL8, + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_MONOWHITE, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), +}; diff --git a/ffmpeg/libavcodec/svq1.c b/ffmpeg/libavcodec/svq1.c new file mode 100644 index 0000000..c219f22 --- /dev/null +++ b/ffmpeg/libavcodec/svq1.c @@ -0,0 +1,43 @@ +/* + * SVQ1 decoder + * ported to MPlayer by Arpi + * ported to libavcodec by Nick Kurshev + * + * Copyright (C) 2002 the xine project + * Copyright (C) 2002 the ffmpeg project + * + * SVQ1 Encoder (c) 2004 Mike Melanson + * + * 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 + */ + +/** + * @file + * Sorenson Vector Quantizer #1 (SVQ1) video codec. + * For more information of the SVQ1 algorithm, visit: + * http://www.pcisys.net/~melanson/codecs/ + */ + +#include "svq1.h" +#include "svq1_cb.h" +#include "svq1_vlc.h" + +/* standard video sizes */ +const uint16_t ff_svq1_frame_size_table[7][2] = { + { 160, 120 }, { 128, 96 }, { 176, 144 }, { 352, 288 }, + { 704, 576 }, { 240, 180 }, { 320, 240 } +}; diff --git a/ffmpeg/libavcodec/svq1.h b/ffmpeg/libavcodec/svq1.h new file mode 100644 index 0000000..8380f22 --- /dev/null +++ b/ffmpeg/libavcodec/svq1.h @@ -0,0 +1,59 @@ +/* + * SVQ1 decoder + * ported to MPlayer by Arpi + * ported to libavcodec by Nick Kurshev + * + * Copyright (C) 2002 the xine project + * Copyright (C) 2002 the ffmpeg project + * + * SVQ1 Encoder (c) 2004 Mike Melanson + * + * 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 + */ + +/** + * @file + * Sorenson Vector Quantizer #1 (SVQ1) video codec. + * For more information of the SVQ1 algorithm, visit: + * http://www.pcisys.net/~melanson/codecs/ + */ + +#ifndef AVCODEC_SVQ1_H +#define AVCODEC_SVQ1_H + +#include + +#define SVQ1_BLOCK_SKIP 0 +#define SVQ1_BLOCK_INTER 1 +#define SVQ1_BLOCK_INTER_4V 2 +#define SVQ1_BLOCK_INTRA 3 + +uint16_t ff_svq1_packet_checksum(const uint8_t *data, + const int length, int value); + +extern const int8_t *const ff_svq1_inter_codebooks[6]; +extern const int8_t *const ff_svq1_intra_codebooks[6]; + +extern const uint8_t ff_svq1_block_type_vlc[4][2]; +extern const uint8_t ff_svq1_intra_multistage_vlc[6][8][2]; +extern const uint8_t ff_svq1_inter_multistage_vlc[6][8][2]; +extern const uint16_t ff_svq1_intra_mean_vlc[256][2]; +extern const uint16_t ff_svq1_inter_mean_vlc[512][2]; + +extern const uint16_t ff_svq1_frame_size_table[7][2]; + +#endif /* AVCODEC_SVQ1_H */ diff --git a/ffmpeg/libavcodec/svq13.c b/ffmpeg/libavcodec/svq13.c new file mode 100644 index 0000000..b821a44 --- /dev/null +++ b/ffmpeg/libavcodec/svq13.c @@ -0,0 +1,69 @@ +/* + * SVQ1/SVQ3 decoder common code + * + * 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 "svq1.h" + +static const uint16_t checksum_table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +uint16_t ff_svq1_packet_checksum (const uint8_t *data, + const int length, int value) +{ + int i; + + for (i = 0; i < length; i++) + value = checksum_table[data[i] ^ (value >> 8)] ^ ((value & 0xFF) << 8); + + return value; +} diff --git a/ffmpeg/libavcodec/svq1_cb.h b/ffmpeg/libavcodec/svq1_cb.h new file mode 100644 index 0000000..7926ce1 --- /dev/null +++ b/ffmpeg/libavcodec/svq1_cb.h @@ -0,0 +1,1525 @@ +/* + * SVQ1 decoder + * ported to MPlayer by Arpi + * ported to libavcodec by Nick Kurshev + * + * Copyright (C) 2002 the xine project + * Copyright (C) 2002 the ffmpeg project + * + * 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 + */ + +/** + * @file + * svq1 code books. + */ + +#ifndef AVCODEC_SVQ1_CB_H +#define AVCODEC_SVQ1_CB_H + +#include +#include + +#include "libavutil/mem.h" + +/* 6x16-entry codebook for inter-coded 4x2 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_inter_codebook_4x2)[768] = { + 7, 2, -6, -7, 7, 3, -3, -4, -7, -2, 7, 8, -8, -4, 3, 4, + 19, 17, 9, 3,-14,-16,-12, -8,-18,-16, -8, -3, 11, 14, 12, 8, + 7,-16,-10, 20, 7,-17,-10, 20, -6, 18, 8,-21, -7, 18, 9,-20, + 25, 3,-20,-14, 29, 7,-18,-13,-29, -4, 21, 14,-31, -6, 20, 14, + -19,-26,-28,-24, 31, 32, 22, 10, 15, 24, 31, 28,-32,-32,-22,-13, + 2, -8,-23,-26, -9, 3, 27, 35, 3, 11, 21, 21, 8, -4,-27,-34, + -30,-31, 12, 47,-29,-30, 13, 47, 38, 30,-17,-46, 34, 26,-19,-46, + -42,-50,-51,-43, 34, 48, 55, 48, 48, 54, 51, 42,-44,-52,-53,-47, + 4, 5, 0, -6, -2, -2, 0, 1,-11, -6, -1, -2, 1, 8, 9, 1, + 0, 1, -6, 5, 8, 1,-12, 2, 7,-14, -7, 8, 5, -8, 0, 8, + 1, 4, 11, 8,-12, -8, 0, -5, -1, 1, 0, 4,-15, -8, 3, 16, + 17, 8, -4, -6, 9, -4,-13, -8, 2, 6, 1,-18, -1, 11, 11,-12, + 6, 0, 2, 0, 14, 6, -7,-21, 1, -1,-13,-20, 1, 1, 10, 21, + -22, -5, 7, 13,-11, -1, 4, 12, -7, 0, 14, 19, -4, 3, -5,-19, + -26,-14, 10, 15, 18, 4, -6, -2, 25, 19, -5,-18,-20, -7, 4, 2, + -13, -6, -1, -4, 25, 37, -2,-35, 5, 4, 1, 1,-21,-36, 2, 43, + 2, -2, -1, 3, 8, -2, -6, -1, -2, -3, 2, 12, -5, -2, -2, -1, + -3, -1, -1, -5, -1, 7, 8, -2, 2, 7, 5, -3, 1, 1, -3, -8, + -3, -1, -3, -2, -2, -3, 2, 13, 15, 0,-11, -6, 3, 0, 0, 0, + -6, -9, -5, -4, 18, 4, 1, 3, 12, 3, 0, 4,-16, -3, 3, -3, + -17, 3, 18, 2, -1, -3, -1, -1, -6, 16, -8, 0, -9, 14, -7, 0, + 3,-13, 14, -5, 3,-13, 14, -4, -7, 20, 14,-23, 8, -7, -8, 4, + 8,-15,-19, 16,-10, 13, 11, -3, 9, -1, 1, 26, 5,-15,-27, 2, + -20, 7, 16, -4,-40, 9, 31, 1, 26,-12,-30, -7, 40, -2,-19, 4, + 6, 0, 0, 0, -6, -2, 1, 2, 0, -1, 0, -6, 9, 0, -2, -1, + -7, 8, 2, -3, -1, 2, -3, 2, 7, -4, -2, 4, 2, 0, 0, -6, + -3, -2, 9, 2, -2, -1, 0, -4, -3, -3, 0, -3, -6, 2, 10, 4, + 3, 0,-10, 8, 0, 0, -4, 4, -1, 1, 4, 2, 3, -7, -9, 7, + 2, 1, -9, -4, -1, 12, 0, 0, 3, -1, 7, -4, 3,-14, 4, 2, + -12, -9, 1, 11, 2, 5, 1, 0, 3, 1, 0, 2, 0, 8, 6,-19, + -6,-10, -7, -4, 9, 7, 5, 7, 6, 21, 3, -3,-11, -9, -5, -2, + -4, -9,-16, -1, -2, -5, 1, 36, 8, 11, 19, 0, 2, 5, -4,-41, + -1, -1, -2, -1, -2, -2, 1, 6, 0, 4, 1, -8, 1, 1, 1, 0, + -2, -3, 4, 0, 2, -1, 3, -3, 1, 3, -4, 1, -1, 3, 0, -5, + 3, 4, 2, 3, -2, -3, -6, -1, -2, -3, -2, 2, -4, 8, 1, 0, + -7, 4, 2, 6, -7, -1, 1, 0, -2, 2, -4, 1, 8, -6, 2, -1, + -6, 2, 0, 2, 5, 4, -8, -1, -1,-11, 0, 9, 0, -2, 2, 2, + 17, -5, -4, -1, -1, -4, -2, -2, 0,-13, 9, -3, -1, 12, -7, 2, + 0, -2, -5, 2, -7, -5, 20, -3, 7, 7, -1,-30, 3, 5, 8, 1, + -6, 3, -1, -4, 2, -2,-11, 18, 0, -7, 3, 14, 20, -3,-18, -9, + 7, -2, 0, -1, -2, 0, 0, -1, -4, -1, 1, 0, -2, 2, 0, 4, + 1, -3, 2, 1, 3, 1, -5, 1, -3, 0, -1, -2, 7, 1, 0, -3, + 2, 5, 0, -2, 2, -5, -1, 1, -1, -2, 4, -1, 0, -3, 5, 0, + 0, 3, -1, -2, -4, 1, 5, -1, -1, 0, -1, 9, -1, -2, -1, -1, + -2, 5, 5, -1, -2, 2, -3, -2, 1, 2,-11, 1, 2, 1, 3, 2, + 2,-10, -1, -2, 4, 2, 4, 1, 4, 5, -5, 1, 0, 6,-11, 1, + 1, 0, 6, 6, 0, 2, 1,-15, 7, 3, 5, 9,-30, 2, 2, 2, + -34, 1, 9, 2, 5, 8, 8, 2, 7, 2, 6, 6, 2,-27, 1, 4 +}; + +/* 6x16-entry codebook for inter-coded 4x4 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_inter_codebook_4x4)[1536] = { + 4, 0, -6, -7, -4, -8,-13, -9, -8, -8, -1, 6, -2, 5, 22, 27, + -16, -7, 11, 10,-18, -7, 13, 10,-15, -4, 12, 8, -9, -1, 9, 5, + -2, 2, 15,-16, -3, 2, 19,-19, -3, 2, 19,-19, -2, 3, 15,-14, + 17, 22, 22, 16, -6, -7, -5, -2,-12,-16,-16,-12, 1, 1, -1, -3, + 11,-17, 0, 8, 14,-21, -1, 9, 14,-21, -2, 8, 11,-16, -2, 6, + 7, -2,-16, 11, 9, -2,-21, 14, 10, -1,-22, 14, 8, -1,-18, 10, + -10, 16, 3, -9,-13, 20, 4,-11,-14, 21, 4,-10,-11, 16, 3, -8, + 11, 4, -9, -9, 15, 6,-12,-14, 17, 8,-12,-14, 16, 10, -7,-11, + 4, 10, 14, 13, -1, 7, 15, 16,-12, -7, 3, 8,-20,-23,-18,-10, + -10,-18,-26,-25, 4, 1, -6,-11, 13, 15, 11, 3, 12, 15, 13, 8, + -16,-19,-16,-11, 7, 12, 15, 11, 11, 16, 16, 11, -6, -9,-11,-10, + 18, 19, 12, 5, 18, 16, 5, -4, 6, 0,-10,-15, -9,-17,-23,-22, + -10,-14, -1, 21,-11,-17, 0, 29,-11,-16, 1, 30,-10,-14, 0, 23, + -16,-17,-12, -6,-19,-19,-14, -7, -3, -1, 1, 2, 27, 35, 29, 19, + -37, -8, 23, 23,-42, -9, 28, 29,-43,-10, 26, 28,-38,-11, 19, 22, + 32, 16,-16,-33, 39, 20,-18,-37, 38, 19,-19,-38, 32, 15,-17,-34, + 24, 9, -6, -4, -1,-10, -6, 3, -8, -9, -1, 3, 3, 7, 2, -6, + -1, -3, -1, 0, -1, 4, 2, -7, -3, 11, 3,-16, 1, 20, 9,-18, + -3, -8, 6, 12, -5,-10, 7, 13, -6, -9, 5, 7, -5, -5, 2, -1, + -8, 12, -3, -1,-10, 15, -3, 1,-11, 13, -4, 1,-11, 8, -3, 2, + 9, 6, -5,-12, 3, 0, -8,-13, -4, -4, -1, -1, -4, 1, 15, 18, + 9, 13, 14, 12, 4, 3, -1, -2, -2, -5, -8, -5, -7,-11, -9, -4, + 7, -5, -7, -4, 14, -2, -7, -4, 17, 0, -8, -5, 15, 1, -7, -5, + -10, -1, 6, 4,-15, -9, 2, 4, 2, -1, -3, 0, 25, 13, -8,-10, + 7, 11, -3,-16, 7, 11, -3,-15, 6, 7, -2, -9, 4, 2, -3, -5, + -7, -1, -1, 0, -9, -2, 2, 6,-12, -4, 6, 14,-13, -6, 8, 19, + -18,-18,-11, -5, -3, 0, 3, 4, 6, 8, 6, 6, 6, 6, 6, 6, + -5, 3, 13,-10, -6, 1, 15, -9, -6, -3, 15, -6, -6, -6, 10, -3, + 9, 1, -9, -9, 11, 9, 6, 5, 0, 3, 8, 7,-15,-14, -6, -5, + -11, -6, 11, 19, -2, -5, -9, -8, 6, 2, -9,-10, 6, 5, 4, 5, + -7, -3, 8, 15, -1, 3, 10, 15, 5, 5, -1, -2, 4, -2,-21,-25, + 6, -6, -6, 5, 8, -9, -7, 9, 8,-12, -7, 13, 4,-14, -7, 14, + -4, -3, 1, 1, -3, -5, -2, -3, 7, 0, -2, -4, 20, 7, -4, -4, + -3,-20, -6, 10, 6, 0, 0, 1, 5, 8, 5, -1, -3, 0, 0, -2, + 13, 6, -1, 2, 5, 3, 2, 3, -3, 0, 3, 0,-16, -8, -2, -5, + -2, -7, -6, 0, -3, -6, -3, 1, -5, -1, 2, -1, -1, 12, 16, 5, + -7, 1, 9, 8,-10, -2, 5, 3, -6, 2, 7, 3, -4, 0, -1, -7, + 3, 4, -9,-24, 0, 2, 6, 3, -1, -1, 4, 7, 5, 3, -1, -2, + 3, 6, -9, 2, 1, 6,-13, 1, 1, 8,-10, 2, 1, 8, -7, 1, + -3, -3, 2, 22, -2, -3, -5, 12, -2, -3,-10, 2, -3, -1, -4, 2, + 11, 12, 8, 2, -5, -5, -5, -8, -6, -4, 0, -3, -2, -1, 3, 3, + 12, -6, -2, -1, 12, -8, -2, -2, 9, -7, 0, -3, 4, -6, 2, -2, + -19, 1, 12, -3, -4, 4, 5, -4, 6, 1, -2, -1, 4, -4, -2, 7, + -3, -4, -7, -8, -4, -4, -2, 0, -1, 2, 14, 16, -4, -2, 4, 4, + -1, 7, 2, -5, -2, 0, -1, 1, 4, -3, -1, 13, 6,-12,-14, 8, + -1, 5, 4, -5, -2, 5, 3, -9, -2, 7, 4,-12, -1, 7, 4, -9, + -6, -3, 1, 1, 11, 11, 0, -6, 6, 4, -2, -7,-12,-10, 3, 10, + -2, -3, -3, -2, 6, 11, 14, 10, -9,-11,-10,-10, 2, 2, 3, 2, + -7, -5, -7, -1, -1, 2, 0, 7, -1, 1, 0, 9, 3, 4, -5, -1, + 10, -1,-15, -1, 4, 1, -5, 2, -3, 1, -1, 1, -3, 1, 4, 4, + 2, -1, 4, 10, 6, 2, -1, 0, 2, 2, -7,-12, -4, 2, 0, -3, + -1, -4, -1, -8, 3, -1, 2, -9, 4, 0, 5, -5, 2, 0, 8, 3, + 3, 2, 1, 1, 4, -2, 0, 3, 2, -1, 4, 1, 0, 6, -1,-25, + -1, -2, -2, -4, -3, 0, -1, -4, -1, -1, -4, 2, 0, -6, 2, 25, + -11, -1, 5, 0, 7, 0, -2, 2, 10, -1, -3, 4, -5, -5, -2, -1, + 0, 6, 3, -1, -2, -1, -1, 1, -1, -7,-12, -5, 8, 6, 2, 4, + 2, 6, -1, -6, 9, 10, -1, -4, 1, 0, -4, 0, 3, -2, -9, -5, + -4, 3, 4, 0, -4, 3, 3, 0,-11, 0, 3, 2,-11, 3, 7, 2, + 2, -4, 7, 3, 1, -8, 7, 1, -1,-12, 4, 1, 3, -9, 2, 2, + 2, -2, -2, 9,-17, -3, 3, 1, -4, 7, 1, -6, 5, 4, -1, 3, + -1, 2, 0, -4, -7, 8, 12, -1, -2, 5, 4, -5, 3, -5, -8, -2, + 0, 0, -5, -2, -2, -8, 3, 27, -1, -4, -3, 6, -3, 1, -2, -7, + 4, 4, 1, -1, -7,-10, -7, -3, 10, 10, 5, 3, -2, -2, -4, -3, + 0, 1, 5, 7, 4, -2,-16,-20, 0, 4, 7, 8, 2, 0, -2, -1, + -2, 1, 3, 17, -3, 1, -2, -1, -1, -2, -1, -2, -1, -5, -1, 0, + 5, -3, 1, 0, 6, -2, 0, 0, -1, -2, 0, -3,-11, 1, 8, -1, + 3, 0, 0, 0, 0, 2, 4, 1, 2, 0, 6, 1, -2,-18, -3, 2, + -14, 0, 6, 1, -5, -2, -1, 1, -1, 1, 0, 1, 1, 7, 4, 0, + -1, 0, 1, -4, 1, 8, 3, -4, -3, 4, 1, 3, -6, 1, -4, 1, + 1,-12, 3, 3, -1,-10, 0, -1, 2, 0, 2, 1, 3, 2, 2, 4, + 3, 0, 0, 3, 2, 0, -2, 1, 5, 2, -5, 0, 6, -1,-14, -1, + -2, -6, -3, -3, 2, -1, 4, 5, 6, -1, -2, 0, 4, 4, -1, -5, + -4, 1,-11, 0, -1, 2, -4, 1, 2, -3, 3, -1, 1, -2, 15, 0, + 1, -1, 0, -2, 1, -4, -7, 1, -2, -6, -1, 21, -2, 2, -1, 1, + 21, -1, -2, 0, -1, -3, 1, -2, -9, -2, 2, -1, 2, 1, -4, -1, + 1, 8, 2, -6,-10, -1, 4, 0, -4, -3, 3, 3, 5, 0, -1, -1, + 3, 2, 1, -2, -2, -2, 4, 3, 5, 2, -4,-17, 0, -2, 4, 3, + -7, -4, 0, 3, 9, 9, 2, -1,-11, -6, 0, -1, 5, 1, 0, 1, + 0, 17, 5,-11, 3, -2, -6, 0, 2, -2, -4, 1, -4, 1, 2, -1, + -5, -1, -5, -3, -3, 5, -3, -2, 4, 16, 2, -5, -2, 5, -1, -1, + 0, 0, -4, 1, -1, 2, 5, 11, -1, -1, -2, 1, -4, -2, -3, -1, + -5, -1, 10, 0, 6, 1, 0, -3, 0, -4, 1, 0, -2, -4, 3, -1, + 6, 9, 3, 0, -2, 1, -2, 0, -2, -3, -2, -2, 1, 0, 1, -6, + 1, 0, 2, 1, -1, 3, -2, 1, 0, -1,-15, 0, -1, 5, 2, 6, + 2, 0, 2, 2, 0,-12, -4, 6, 0, 1, 4, -1, 1, 2, 1, -4, + 1, -2, -7, 0, 0, 0, 0, -1, -5, 2, 11, 3, 1, 3, 0, -6, + 0, -3, -9, -4, 1, 3, -1, 0, 4, 1, -2, 0, 7, -3, -1, 6, + 1, -2, 6, 2, 0, -1, 3, -2, -2, 4, 0, 2, -1, 2,-14, 2, + 2, 2, 0, -1, -2, 3, -3,-14, 0, 2, 3, -3, 5, 1, 3, 2, + 1, -3, 4,-14, 1, -2, 11, -1, 0, -1, 3, 0, -1, 1, 0, 2, + -2, 3, -3, 2, -4, -1, -4, 3, -1, 2, 1, 3, -6, -2, 2, 7, + -2, 1, 2, 0, -2, 0, 0, -1, 12, 5, -1, 2, -8, -1, 1, -7, + 2, -2, -4, 2, 11, 0,-11, -2, 3, 1, -3, -1, 0, 3, 1, -1, + 0, 3, 0, -2, 0, -6, -1, -3, 12, -7, -2, 0, 7, -2, 1, 1, + 1, 2, 2, 2, -1, 2, 0, 2,-23, 0, 4, 0, 3, 2, 1, 3, + -4, -5, -1, 5, -3, 5, 10, -1, 0, 0, 3, -4, 1, -1, 2, -5 +}; + +/* 6x16-entry codebook for inter-coded 8x4 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_inter_codebook_8x4)[3072] = { + 9, 8, 4, 0, -3, -4, -4, -3, 9, 8, 4, -1, -4, -5, -5, -3, + 8, 7, 3, -2, -5, -5, -5, -4, 6, 4, 1, -2, -4, -5, -4, -3, + -12,-14,-11, -4, 1, 5, 6, 6, -8,-10, -7, -5, -2, 1, 1, 1, + 5, 4, 3, 1, 0, 0, -1, -1, 13, 13, 9, 6, 3, 0, -1, -2, + -4, -4, -3, -1, 1, 4, 8, 11, -5, -6, -4, -2, 0, 3, 8, 12, + -7, -7, -6, -4, -2, 2, 7, 10, -7, -7, -5, -4, -2, 1, 5, 8, + -3, -2, -1, 1, 3, 6, 7, 6, 2, 3, 5, 7, 8, 8, 6, 4, + 4, 5, 4, 3, 1, -2, -6, -7, 1, 0, -2, -7,-10,-14,-17,-16, + -5, -4, 1, 8, 9, 3, -3, -7, -7, -6, 1, 11, 12, 5, -3, -8, + -8, -7, 0, 9, 11, 5, -3, -7, -8, -6, -1, 5, 8, 4, -2, -6, + -4, -5, -7, -8, -9, -9, -8, -6, -4, -5, -6, -7, -7, -6, -4, -2, + 0, 1, 2, 3, 5, 8, 10, 9, 1, 2, 3, 6, 9, 12, 14, 13, + 5, 6, 6, 5, 4, 3, 2, 1, 5, 6, 7, 7, 6, 6, 6, 4, + -1, 0, 1, 1, 3, 5, 5, 5,-13,-16,-17,-17,-14,-10, -6, -4, + 9, 11, 13, 16, 15, 13, 12, 10, -4, -5, -6, -7, -7, -7, -6, -5, + -6, -6, -7, -7, -7, -7, -6, -5, -2, -1, 0, 0, 0, 0, 0, -1, + -11,-13,-15,-16,-16,-14,-12,-10, 2, 3, 4, 5, 4, 3, 3, 3, + 6, 7, 8, 8, 8, 7, 6, 5, 3, 4, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 1, -2, -7,-13,-17, 5, 7, 7, 5, 1, -5,-13,-19, + 6, 8, 9, 8, 5, -1, -9,-16, 6, 8, 10, 10, 7, 2, -4,-11, + 18, 9, -1,-10,-13, -9, -4, 0, 22, 12, -1,-12,-15,-10, -4, 2, + 23, 13, 0,-10,-13, -9, -3, 2, 20, 12, 2, -6, -9, -6, -2, 2, + -6, -6, -6, -7, -7, -7, -7, -6, -6, -7, -8, -8, -9, -9, -9, -8, + -3, -3, -3, -3, -3, -3, -3, -3, 12, 15, 18, 21, 21, 19, 17, 14, + 14, 16, 18, 18, 18, 16, 15, 13, 5, 6, 6, 5, 5, 4, 4, 3, + -6, -7, -9,-10,-10,-10, -9, -7,-10,-11,-13,-14,-14,-13,-12,-10, + -27,-17, -4, 5, 9, 10, 10, 7,-32,-19, -3, 7, 11, 12, 11, 8, + -30,-16, -2, 8, 12, 12, 10, 7,-23,-12, 0, 7, 10, 11, 9, 6, + 16, 17, 16, 12, 6, -1, -8,-12, 17, 18, 15, 10, 1, -8,-15,-18, + 15, 14, 10, 4, -5,-14,-20,-23, 10, 8, 4, -1, -9,-16,-21,-22, + -10,-12,-12,-11, -5, 4, 14, 20,-11,-13,-15,-12, -4, 7, 19, 27, + -11,-13,-14,-11, -3, 8, 21, 28,-10,-11,-12, -9, -2, 8, 18, 25, + -1, -1, -1, 1, 4, 6, 6, 5, 0, 0, 0, 2, 4, 3, 1, -2, + 0, 0, 2, 4, 4, -1, -7,-10, 0, 0, 3, 5, 3, -3,-11,-15, + -14,-13, -8, -1, 3, 3, -1, -4, -5, -4, -1, 4, 8, 8, 3, 0, + 3, 2, 2, 3, 4, 5, 3, 1, 5, 3, 0, -2, -2, -1, -1, -1, + 9, 1, -6, -6, -5, -3, -2, -1, 12, 1, -6, -6, -4, -2, -1, 0, + 14, 4, -4, -4, -2, -2, -1, -1, 14, 6, -1, -1, -1, -1, -1, -1, + 4, 6, 8, 10, 11, 9, 7, 5, -1, -1, -1, 0, 0, -1, -1, -2, + -2, -4, -4, -5, -5, -5, -5, -4, -2, -3, -3, -4, -4, -3, -2, -1, + 2, 3, 4, 4, 3, 1, 0, 0, -1, 1, 4, 5, 6, 5, 4, 3, + -8, -6, -2, 2, 3, 4, 4, 3,-14,-13, -9, -5, -2, -1, 0, 0, + -3, -4, -5, -4, 0, 7, 12, 13, -3, -4, -5, -5, -2, 4, 9, 10, + -2, -3, -4, -5, -4, -1, 3, 4, -1, -1, -2, -3, -3, -2, 0, 1, + 9, 5, -2, -8,-11,-10, -7, -4, 12, 10, 6, 2, 0, -1, 0, 0, + 2, 2, 3, 4, 3, 1, 1, 1, -9, -8, -4, 0, 1, 2, 1, 0, + 6, 8, 8, 5, 1, -5,-11,-13, 0, 1, 2, 2, -1, -4, -8,-11, + -3, -2, 1, 3, 3, 1, -1, -4, -2, -1, 2, 5, 6, 6, 4, 1, + 3, 4, 5, 5, 4, 1, -3, -6, 5, 6, 4, 2, 2, 2, 0, -3, + 6, 5, 0, -5, -5, -2, -1, -2, 7, 4, -3,-11,-12, -7, -3, -2, + 1, 0, -1, -1, -1, 0, 0, 0, 2, 3, 4, 4, 5, 5, 4, 3, + -7, -9, -9,-10,-10, -9, -7, -6, 3, 4, 5, 6, 5, 5, 5, 5, + -7, -7, -7, -7, -6, -6, -5, -4, -5, -4, -3, -1, -1, -1, 0, 0, + -3, -2, 1, 4, 5, 5, 5, 5, -2, -1, 3, 6, 9, 10, 10, 9, + -14, 1, 10, 3, -2, 0, 1, 1,-16, 2, 13, 3, -3, -1, 1, 0, + -15, 2, 12, 3, -4, -2, 1, 1,-10, 3, 10, 2, -3, -1, 1, 1, + 0, 1, 4, 2, -5,-10, -3, 11, -1, 1, 4, 2, -6,-13, -2, 15, + -1, 0, 3, 1, -6,-12, -1, 15, -1, 1, 2, 1, -4, -8, 0, 11, + 10, 5, -2, -2, 2, 5, 1, -4, 7, 0, -8, -6, 1, 5, 2, -4, + 2, -5,-12, -7, 2, 7, 4, -1, -1, -7,-10, -4, 4, 9, 7, 2, + -5, -5, -4, -6, -6, -5, -5, -3, -1, -2, -2, -4, -5, -6, -5, -4, + 6, 7, 7, 4, 0, -2, -3, -3, 13, 14, 13, 10, 5, 1, -1, -2, + 1, 1, 2, 2, 2, 2, 2, 2, -5, -6, -8, -9, -9, -8, -7, -6, + 7, 9, 10, 11, 11, 9, 7, 5, -1, -2, -3, -3, -4, -4, -4, -3, + -1, -1, 0, 0, 0, 0, -1, -1, -3, -3, -4, -5, -4, -3, -3, -2, + 2, 1, -1, -3, -3, -2, -1, 0, 12, 12, 8, 3, 1, 0, 0, 1, + -6, -8, -8, -6, -2, 2, 6, 8, 1, 1, -1, -2, 0, 3, 5, 7, + 3, 3, 1, -1, -1, 0, 0, 2, 0, 1, 0, -1, -1, -1, -2, -1, + 1, 0, 0, 0, 0, 0, 2, 4, 2, 1, 3, 4, 3, 1, 0, 2, + 2, 1, 0, 0, -1, -1, 0, 3, 5, 1, -6,-12,-13, -8, -1, 4, + -2, 0, -1, -2, -1, 0, 2, 3, -6, -3, -2, 0, 1, 1, 1, 1, + -9, -5, 0, 4, 5, 3, 1, 0, -8, -3, 3, 7, 8, 4, 1, 0, + 1, 2, 2, 3, 3, 1, -1, -3, 4, 5, 5, 6, 6, 5, 2, 0, + 0, 0, 0, 0, 1, 0, -2, -4, -3, -3, -4, -3, -3, -4, -7, -8, + 14, 12, 6, -1, -3, -3, 0, 0, 7, 5, 1, -3, -5, -4, -2, -1, + -2, -2, -2, -2, -2, -2, -1, -1, -6, -4, -1, 1, 1, 1, 0, -1, + 2, 2, 1, -3, -6, -7, -6, -3, 1, 0, -1, -3, -2, 1, 4, 6, + 0, 0, 1, 2, 4, 7, 8, 7, 0, 0, 0, 0, -1, -4, -7, -8, + 0, 2, 1, -2, -3, -3, -2, -1, -1, 1, 0, -3, -5, -2, 0, 2, + -2, -1, -2, -5, -4, 1, 6, 9, -3, -2, -3, -4, -2, 5, 11, 13, + -4, -2, 2, 6, 4, -3,-10,-14, -2, -1, 1, 4, 4, 1, -1, -2, + 0, 0, -1, -2, -2, 0, 4, 6, 2, 2, 0, -3, -3, 0, 5, 9, + -4, -4, -2, 1, 6, 9, 3, -7, -2, -2, -2, -1, 4, 8, 0,-11, + 1, 1, 0, 0, 2, 6, -1,-10, 2, 2, 1, 0, 2, 4, 0, -7, + -1, -2, -3, -6, -7, -8, -8, -8, 2, 3, 3, 1, -1, -2, -3, -4, + 5, 5, 5, 4, 3, 2, 0, -1, 3, 3, 3, 3, 2, 2, 1, 1, + 3, 3, 2, -2, -3, 0, 7, 10, 1, 2, 2, -2, -5, -4, 0, 3, + 0, 3, 4, 2, -3, -5, -6, -4, 0, 2, 4, 4, 1, -4, -7, -7, + 2, 4, 5, 5, 5, 5, 6, 6, -4, -4, -3, -5, -5, -3, -3, -2, + -3, -4, -4, -5, -4, -2, -2, -2, 1, 1, 0, 0, 2, 4, 5, 4, + -2, 0, 3, 4, 4, 3, 2, 2, -9, -7, -4, 0, 3, 6, 6, 6, + -5, -5, -3, -2, 0, 1, 3, 4, 5, 5, 2, -2, -4, -6, -5, -3, + 1, -6, -4, 7, 5, -2, -2, 1, 5, -5, -4, 6, 4, -5, -4, 1, + 5, -5, -4, 6, 4, -5, -3, 1, 1, -7, -3, 8, 7, -1, -3, 1, + -8, -7, -4, 0, 2, 4, 5, 5, 5, 6, 5, 2, -1, -5, -7, -7, + 5, 6, 4, 1, -3, -5, -6, -5, -7, -7, -5, -2, 1, 6, 9, 10, + 6, 3, 0, 1, 3, 0, -8,-14, 3, 0, -1, 1, 4, 3, 0, -4, + 1, 0, 0, 1, 2, 1, 1, 1, -1, -1, 1, 2, 1, -1, -1, 0, + 1, 1, 1, 1, 0, -2, -3, 0, 1, 2, 1, 0, -2, -8, -9, -4, + 1, 3, 3, 2, 1, -3, -3, 1, 0, 1, 1, 1, 1, 1, 4, 8, + 2, 5, 9, 7, 2, -1, -1, 1, -4, -1, 1, 0, -3, -4, -1, 2, + -3, 0, 3, 3, 0, -1, 0, 2, -4, -1, 1, 1, -2, -4, -5, -4, + 1, -1, -2, -2, -1, 2, 4, 5, 2, 1, 1, 0, -1, -1, 0, 0, + 2, 3, 4, 5, 4, 2, 1, 0, -9, -9, -6, -3, -1, -1, -1, -1, + -6, -6, 4, 7, 0, -2, -1, -2, -1, -2, 5, 6, -1, -2, 0, -1, + 4, -1, 1, 0, -4, -2, 0, -2, 7, 1, -1, -2, -3, 1, 3, 1, + 4, 2, 1, 3, 3, 1, 1, 2, 2, -2, -4, 0, 3, 1, 0, 0, + 1, -4, -8, -4, 1, 2, 1, 0, 2, -3, -9, -6, 0, 3, 3, 2, + -1, -1, 0, -1, -1, 0, 1, 2, 3, 1, -4, -8, -7, -3, 1, 2, + 2, -1, -3, -2, -1, 0, 1, 0, -1, 0, 5, 11, 9, 3, -1, -3, + -1, -2, -2, -1, 1, 1, 1, 1, 0, -1, 0, 3, 6, 6, 5, 5, + 2, 1, -1, -1, -2, -5, -6, -4, 2, 2, 2, 1, -1, -4, -5, -5, + -1, -3, -6, -7, -6, -4, -1, 1, 5, 5, 3, 4, 4, 3, 4, 5, + -1, -2, -3, -2, -2, -2, 0, 1, 0, 0, 0, 0, 0, 1, 2, 3, + -6, -6, -4, -1, 2, 2, 2, 2, -6, -7, -5, -2, 0, -1, -1, 0, + 2, 2, 2, 4, 4, 3, 3, 4, 2, 1, 0, -1, 0, 0, 2, 4, + 12, 5, -5, -8, -5, 0, 2, 2, 2, -3, -6, -3, 0, 0, -1, -2, + -2, -3, -1, 3, 4, 1, -2, -3, 2, 2, 3, 4, 3, 1, -1, -1, + 3, 2, 1, 0, 1, 4, 3, 0, 4, 3, 0, -5, -6, 0, 3, 3, + 2, 3, 1, -7,-12, -6, 1, 3, 1, 3, 4, -1, -6, -4, 0, 1, + -9, -4, 2, 6, 7, 4, 1, 0, -7, -1, 4, 6, 4, 0, -3, -3, + -6, 0, 4, 4, 1, -2, -3, -2, -4, 1, 3, 2, 0, -2, -1, 0, + 0, 5, 2, -5, -3, 3, 1, -4, -2, 4, 2, -6, -3, 6, 4, -3, + -1, 5, 3, -5, -1, 7, 3, -4, -1, 2, 0, -6, -3, 5, 3, -3, + -8, -3, 3, 5, 3, 1, -2, -2, 2, 4, 4, -2, -4, -3, 1, 3, + 2, 1, -3, -5, -3, 3, 4, 3, -5, -6, -5, 3, 10, 8, -1, -5, + 0, 3, 2, -4, -9, -7, 0, 6, -5, -1, 5, 7, 4, -1, -3, -3, + -5, -5, -2, 3, 6, 5, -1, -4, 9, 6, 0, -4, -2, 1, 1, -1, + -1, -1, -1, 1, 1, 0, -1, 0, -1, 0, 0, 0, 0, -1, -1, 0, + 2, 1, -2, -1, 1, 1, 0, 0, 12, 8, 2, -1, -1, -4, -7, -7, + 2, 1, 3, 6, 7, 4, 2, 0, 1, 0, -1, 0, -1, -4, -7, -8, + 0, 0, -1, 0, 0, 0, -1, -3, 0, 0, 0, 0, 1, 1, 0, -2, + -1, 0, 1, 1, 0, 0, -1, -2, 0, 0, -1, -3, -4, -3, -1, 1, + -1, 0, 0, 0, 1, 4, 10, 12, -1, 0, -2, -2, -3, -3, -1, 1, + -3, -1, -2, -4, 2, 9, 9, 7, -3, 0, -1, -3, 0, 2, -1, 1, + -1, 1, -2, -3, 0, -1, -3, 0, 0, 0, -3, -2, 0, -1, -1, 1, + -1, -2, -1, -1, -2, -1, -1, -2, 2, -1, -2, -1, 0, 1, 0, -2, + 3, -1, -2, 2, 5, 3, -1, -3, 1, -5, -5, 1, 6, 6, 2, 0, + 1, 2, 0, -1, 0, 1, 0, -2, -5, -3, -1, 0, 1, 2, 1, -2, + -7, -5, -2, -2, -2, -2, 0, 1, -1, 0, 1, 1, 0, 3, 9, 12, + 0, 6, 5, 1, -2, -3, 0, 3, 0, 6, 5, 1, 1, 1, 2, 3, + -5, -2, -2, -3, 0, 0, 0, 0, -6, -3, -3, -2, 0, 0, -1, -2, + 4, 4, 2, 1, 0, -1, -1, 0, -2, -2, 0, 1, 2, 1, 1, 0, + 2, 2, 1, -1, -3, -5, -9,-10, 2, 1, -1, -1, 1, 4, 4, 1, + 4, 0, -2, -2, -2, -2, -1, 0, 7, 1, -4, -3, -2, 0, 1, 1, + 10, 5, -1, -2, 0, 1, 1, 0, 5, 1, -3, -4, -3, -1, -1, -2, + 2, 1, -1, -3, -3, 1, 1, -1, -2, -1, 3, 0, -1, 1, 1, 0, + -3, 1, 7, 2, -3, -2, -1, 0, -2, 4, 8, -1, -8, -5, 0, 2, + -4, -1, 1, 2, 1, -3, -4, -2, -5, -3, -2, 1, 4, 4, 4, 6, + -3, -2, -4, -3, 0, 1, 1, 2, 2, 2, 2, 1, 2, 1, -1, -1, + -4, -1, 0, -1, -3, -3, -1, -1, 1, 4, 4, 2, 0, -1, -2, -3, + 4, 6, 5, 3, 2, 1, -2, -4, 0, 1, 1, 1, 1, -1, -4, -6, + 1, 2, 2, -1, -6, -5, -1, 2, -3, -2, 1, 1, -4, -3, 2, 5, + -2, -1, 2, 2, -3, -4, 0, 3, -2, -2, 2, 6, 5, 2, 1, 2, + 2, -3, -3, 0, 0, 2, 3, 1, 3, -1, 1, 3, 1, 2, -1, -5, + -5, -7, -4, -2, 1, 8, 8, 1, -1, 0, 2, 0, -3, 0, 1, -3, + -2, -5, -5, -2, -3, -1, 0, -2, -1, -4, 0, 4, 0, 2, 4, 0, + 0, 0, 8, 10, 2, 1, 3, -1, -4, -3, 2, 3, -3, -3, 1, -1, + 1, -2, -4, 2, 7, 3, -2, -1, 6, 4, -2, -1, 2, 0, -1, 3, + 1, 1, -2, -2, -2, -5, -3, 4, -6, -2, 1, 1, -1, -4, -2, 4, + -2, -1, -2, -2, 0, 1, 0, -2, -1, 1, 0, -1, 0, 0, -1, -3, + 0, 1, -2, -4, -3, -1, 0, 0, 6, 8, 5, 0, 0, 1, 2, 3, + -2, -2, 2, 5, 2, 0, 0, 1, 2, -2, -2, -1, -1, 1, 2, 4, + 2, -1, 0, 1, 0, 0, 0, 1, -8, -7, -1, 1, -1, -1, 1, 3, + 0, 3, 6, 2, -2, 1, 2, 0,-10, -7, -1, 0, -3, -1, 2, 1, + 0, 0, 2, 2, 1, 1, 1, -1, 3, 0, -2, -2, 0, 2, 1, 0, + 8, 1, 0, 0, -2, -3, -1, 0, 2, -2, 2, 5, 1, -2, -1, 1, + -3, -6, -3, -1, -3, -3, -1, 2, 2, 0, 1, 2, 2, 1, 0, 0, + 1, -1, -1, -2, -1, 0, 1, 0, 15, 9, 2, -1, -2, -3, -3, -3, + 0, -3, -2, 0, 0, -1, -1, -1, 1, 0, 1, 0, 0, -1, -1, -1, + 0, 2, 2, -2, -3, -3, -7, -8, 0, 2, 2, 0, 1, 2, 1, 1, + 1, 2, 2, 2, 3, 1, 0, 3, 1, 0, -1, -2, -1, -2, 0, 5, + -11, -6, -1, 1, 2, 3, 1, -3, 1, 4, 3, -1, -2, 1, 2, -1, + 2, 2, 1, -1, -2, 0, 1, -1, 0, 0, -1, -1, 0, 2, 3, 2, + 1, 1, 2, 1, -1, 1, 0, -4, 0, 0, 0, -2, -2, 2, 4, -2, + -2, -3, 0, 0, -1, 2, 1, -6, 0, 2, 5, 5, 3, 2, -1, -7, + 4, 2, 0, 0, 3, 3, 1, -1, 0, -1, -1, 3, 6, 4, 1, -1, + -2, -2, 0, 2, 2, 0, -2, -2, -1, 0, -1, -5, -7, -5, -1, 1, + 5, -1, -2, 0, 2, 4, 2, -5, 0, -5, -2, 2, 1, 2, 0, -6, + 6, 1, 0, 1, -2, -1, 4, 2, 2, -3, -3, 0, -1, -2, 0, 0, + 1, -1, 0, 2, 0, 0, 6, 11, 2, -1, -1, 0, -3, -2, 3, 5, + 0, -2, -1, 0, -1, 0, 0, -3, 1, -1, -1, -1, -2, -1, -3, -7, + 1, 1, -2, -2, 1, 3, 1, -2, -1, 2, 0, -1, -1, 1, 0, 0, + -4, 2, 3, -1, -2, -2, 0, 1,-11, -2, 4, 5, 6, 2, -1, -2, + -6, -2, 1, -1, -3, -4, 1, 9, -3, 0, 3, 3, 2, -3, -3, 3, + 1, 1, 0, 0, 1, -1, -2, 3, 2, 0, -3, -3, 0, -1, -1, 3, + 1, -1, -3, 1, 2, -6, -4, 6, 0, -2, -5, -2, 0, -3, -2, 3, + 2, 2, 1, -2, -2, 1, 2, -1, -1, 1, 1, -2, -1, 6, 7, -1, + 1, 0, -4, -2, 1, -2, -3, 1, -4, 0, -3, -2, 2, 0, -3, 0, + -3, 4, 3, 1, 8, 7, 0, -1, -3, 4, 1, -4, 2, 3, -2, -3, + -3, 6, 1, -4, 1, 1, -1, -1, -2, 4, -3, -3, 3, 0, -1, -1, + 1, 2, -4, 2, 4, -3, -1, 2, 3, -1, -4, 5, 4, -6, -3, 2 +}; + +/* 6x16-entry codebook for inter-coded 8x8 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_inter_codebook_8x8)[6144] = { + -4, -3, 4, 5, 2, 1, 1, 0, -5, -3, 5, 5, 2, 1, 0, 0, + -6, -4, 5, 5, 2, 1, 0, 0, -7, -4, 4, 5, 2, 1, 0, 0, + -8, -5, 3, 4, 2, 1, 0, 0, -8, -6, 3, 4, 1, 1, 1, 0, + -8, -6, 2, 4, 2, 1, 1, 0, -8, -6, 2, 4, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, + -2, -3, -3, -3, -3, -3, -3, -3, -2, -3, -3, -3, -3, -3, -4, -3, + -2, -2, -2, -2, -2, -3, -3, -2, 1, 1, 1, 1, 1, 0, -1, -1, + 4, 5, 5, 5, 4, 3, 3, 2, 7, 7, 8, 8, 8, 7, 6, 5, + 2, 1, 2, 4, 4, 0, -4, -6, 1, 1, 2, 5, 5, 1, -5, -7, + 1, 2, 1, 4, 5, 1, -5, -8, 1, 1, 1, 5, 5, 0, -6, -8, + 0, 1, 1, 5, 6, 1, -6, -9, 0, 0, 1, 4, 5, 0, -5, -8, + 0, 0, 1, 4, 5, 0, -5, -7, 0, 0, 1, 4, 4, 1, -4, -7, + 1, 2, 3, 0, -3, -4, -3, -1, 1, 3, 4, 0, -3, -4, -3, -1, + 2, 4, 5, 1, -3, -4, -3, -2, 2, 5, 6, 1, -3, -5, -4, -2, + 3, 6, 6, 1, -3, -5, -4, -2, 3, 6, 6, 1, -3, -5, -4, -2, + 3, 6, 6, 1, -3, -5, -4, -2, 3, 5, 5, 1, -3, -4, -4, -2, + 2, 2, 2, 2, 1, 0, 0, -1, 4, 4, 4, 3, 2, 1, 1, 0, + 4, 5, 4, 4, 3, 3, 2, 1, 4, 4, 4, 4, 4, 3, 2, 2, + 2, 3, 3, 3, 3, 3, 2, 1, -1, -1, -1, -1, 0, 0, 0, 0, + -5, -6, -6, -5, -5, -4, -3, -3, -7, -9, -9, -8, -7, -6, -6, -5, + 6, 6, 6, 6, 6, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, + 0, -1, -1, -1, -2, -2, -1, -1, -3, -5, -6, -6, -6, -6, -5, -4, + -3, -5, -6, -7, -6, -6, -5, -4, -1, -2, -2, -2, -2, -2, -1, -1, + 0, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 1, -2, -5, -4, 0, 2, 5, 2, 1, -2, -6, -5, 0, 3, 5, + 2, 1, -2, -6, -6, -1, 3, 6, 3, 2, -2, -7, -6, 0, 4, 7, + 2, 1, -2, -7, -5, 0, 5, 7, 2, 1, -2, -6, -5, 0, 4, 7, + 2, 1, -2, -6, -4, 0, 4, 6, 1, 1, -2, -5, -4, 0, 3, 6, + -10, -9, -6, -4, -1, 2, 3, 2,-10, -9, -5, -3, 0, 4, 4, 3, + -9, -7, -3, -1, 2, 5, 5, 3, -7, -5, -2, 0, 3, 5, 5, 3, + -6, -3, 0, 1, 4, 6, 5, 3, -4, -2, 1, 2, 3, 5, 4, 2, + -2, 0, 1, 2, 2, 4, 3, 1, -1, 1, 2, 2, 2, 3, 3, 1, + -4, -5, -5, -6, -6, -6, -6, -5, -3, -3, -4, -4, -4, -4, -4, -4, + 0, 0, 0, 0, -1, -1, -1, -1, 5, 5, 6, 5, 5, 4, 3, 2, + 5, 6, 7, 7, 7, 6, 5, 4, 3, 3, 4, 4, 4, 4, 3, 2, + 0, -1, 0, 0, -1, -1, 0, -1, -3, -3, -4, -4, -4, -4, -3, -3, + 1, -2, -5, 1, 5, 4, 2, 0, 1, -3, -6, 1, 6, 5, 2, 0, + 0, -4, -7, 0, 6, 6, 2, 1, -1, -5, -9, -1, 6, 6, 3, 1, + -1, -6,-10, -2, 6, 6, 3, 1, -1, -6, -9, -2, 5, 6, 3, 1, + -2, -6, -9, -2, 5, 5, 3, 1, -2, -6, -7, -2, 4, 4, 2, 1, + -5, -7, -8, -9, -9, -8, -7, -6, -5, -6, -6, -7, -7, -6, -6, -5, + -3, -3, -3, -4, -5, -5, -4, -4, -1, 0, 0, -1, -1, -1, -1, -1, + 0, 1, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 5, 5, 5, 4, + 3, 4, 5, 6, 8, 8, 8, 7, 3, 4, 5, 6, 7, 7, 7, 6, + 5, 6, 7, 8, 9, 10, 10, 9, 3, 4, 6, 7, 8, 9, 9, 8, + 0, 1, 2, 3, 4, 5, 5, 5, -1, -2, -1, -1, 0, 1, 2, 2, + -2, -3, -3, -3, -3, -2, -1, 0, -3, -4, -5, -5, -5, -5, -5, -4, + -4, -5, -5, -6, -7, -7, -6, -5, -3, -4, -5, -6, -7, -7, -6, -6, + 13, 7, 0, -3, -3, -4, -4, -5, 14, 7, 0, -3, -3, -4, -4, -4, + 15, 8, -1, -4, -4, -4, -5, -4, 15, 8, -1, -4, -4, -5, -4, -3, + 15, 7, -1, -4, -5, -5, -5, -4, 14, 7, -1, -4, -4, -4, -4, -3, + 12, 6, -1, -4, -4, -4, -4, -3, 11, 5, -1, -4, -4, -4, -4, -3, + -17, -4, 5, 4, 4, 4, 3, 3,-18, -5, 5, 4, 4, 4, 3, 3, + -19, -5, 6, 4, 4, 4, 3, 2,-20, -5, 6, 4, 4, 4, 3, 3, + -20, -4, 6, 4, 4, 5, 3, 3,-19, -5, 6, 4, 4, 5, 3, 3, + -18, -4, 5, 4, 4, 4, 3, 2,-17, -5, 4, 3, 4, 4, 3, 3, + -6, -6, -6, -4, -2, 1, 6, 11, -6, -7, -7, -4, -2, 2, 8, 13, + -8, -8, -7, -4, -2, 3, 9, 14, -8, -8, -7, -5, -1, 4, 10, 16, + -8, -8, -7, -5, -1, 4, 10, 17, -8, -8, -7, -4, 0, 5, 10, 16, + -8, -8, -6, -3, 0, 4, 9, 15, -7, -7, -5, -3, 0, 4, 8, 12, + 8, 7, 7, 5, 2, -2, -8,-14, 8, 8, 7, 5, 2, -2, -8,-15, + 8, 8, 7, 5, 1, -3, -9,-16, 8, 8, 7, 5, 1, -3,-10,-17, + 8, 9, 8, 5, 1, -3,-10,-17, 8, 8, 7, 4, 1, -4,-10,-16, + 7, 7, 7, 4, 1, -3, -9,-14, 6, 7, 6, 3, 0, -3, -9,-13, + 5, 1, -4, -4, -3, -1, 0, 0, 7, 2, -3, -3, -2, -1, 1, 0, + 7, 1, -3, -3, -1, 0, 1, 1, 6, 1, -3, -2, -1, 1, 1, 0, + 6, 0, -4, -2, -1, 0, 1, 0, 5, 0, -4, -3, -1, 0, 0, -1, + 5, 0, -3, -1, 0, 0, 0, -2, 4, 1, -2, -1, 0, 1, 0, -1, + 2, 2, 1, 1, -2, -6, -8, -8, 1, 1, 1, 1, -2, -5, -8, -8, + 1, 1, 1, 0, -1, -3, -5, -5, 0, 0, 0, 0, -1, -1, -1, -2, + 0, -1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 3, 2, + 2, 1, 1, 1, 2, 3, 4, 3, 3, 3, 3, 3, 4, 4, 5, 4, + -4, -4, -3, -2, 0, 0, 1, 1, -4, -4, -3, -2, -1, 0, 0, 1, + -2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, + 2, 2, 2, 2, 2, 2, 1, 1, 3, 4, 4, 4, 4, 4, 4, 3, + 1, 1, 1, 3, 3, 4, 3, 3, -5, -6, -5, -4, -3, -3, -2, -2, + -4, -2, -1, -1, -1, -1, 0, 1, -4, -2, -1, -1, -1, -1, 0, 1, + -3, -2, -1, -1, -1, 0, 1, 2, -4, -3, -2, -1, -1, 1, 3, 3, + -4, -3, -3, -1, -1, 1, 4, 5, -4, -3, -2, -2, -1, 1, 4, 7, + -2, -2, -1, -1, 0, 2, 6, 8, -1, 0, 0, 1, 1, 4, 7, 8, + -3, -3, -3, -2, -2, -1, -1, 0, -1, -1, 0, 1, 2, 2, 3, 3, + 0, 1, 2, 4, 5, 6, 6, 5, -1, 0, 2, 3, 5, 6, 5, 3, + -1, -1, 0, 2, 3, 3, 2, 1, -2, -2, -1, 0, -1, -3, -4, -4, + 0, 0, -1, -1, -2, -4, -8, -7, 1, 2, 1, 0, -1, -4, -6, -7, + -2, 4, 1, -6, 0, 3, 0, 0, -2, 5, 1, -7, 0, 3, 0, 0, + -3, 5, 1, -8, 0, 3, -1, -1, -2, 6, 1, -9, 0, 3, 0, -1, + -2, 6, 2, -8, 0, 4, 0, -1, -3, 5, 1, -7, 1, 4, 0, 0, + -2, 4, 1, -7, 0, 4, 1, 0, -1, 4, 1, -6, 0, 3, 1, 0, + 0, 0, 0, 3, 4, 5, 4, 1, 1, 1, 1, 2, 3, 3, 2, 0, + 2, 2, 1, 2, 2, 1, -1, -2, 4, 3, 1, 1, 0, -1, -3, -5, + 5, 3, 1, -1, -2, -3, -4, -6, 5, 3, 0, -2, -3, -5, -6, -7, + 4, 3, 0, -2, -3, -4, -5, -5, 4, 3, 0, -1, -2, -2, -3, -3, + 0, 0, 0, 0, -1, -5, -2, 6, 0, 0, 0, 1, -1, -6, -2, 8, + 0, 0, 0, 2, 0, -6, -3, 9, 0, -1, 0, 2, 0, -7, -2, 10, + 0, -1, 0, 2, -1, -8, -3, 10, 0, -1, -1, 2, -1, -7, -3, 9, + 0, -1, 0, 1, -1, -6, -3, 8, 0, 0, 0, 1, 0, -5, -2, 7, + 2, 3, 3, 2, 1, 0, -1, -1, 3, 4, 3, 2, 1, 0, -1, -2, + 3, 4, 4, 2, 1, -1, -2, -3, 2, 3, 3, 2, 0, -1, -2, -3, + -1, 0, 1, 1, 0, -1, -2, -2, -5, -4, -3, -1, 0, 1, 1, 1, + -8, -8, -5, -1, 1, 3, 4, 3,-10, -9, -5, 0, 3, 5, 6, 5, + -5, -1, 4, 5, 3, 1, 0, 0, -6, -1, 4, 5, 2, 0, -1, -2, + -6, -1, 5, 4, 2, -1, -2, -2, -7, -1, 4, 4, 1, -2, -3, -3, + -6, -1, 5, 4, 1, -2, -3, -3, -5, 0, 4, 4, 1, -1, -2, -2, + -4, 0, 5, 4, 1, -1, -1, -2, -3, 1, 4, 3, 1, -1, -1, -2, + -2, -3, -2, 1, 4, 6, 5, 3, -3, -4, -4, 0, 3, 5, 4, 2, + -3, -5, -5, -1, 2, 4, 3, 1, -4, -6, -4, -1, 2, 4, 2, -1, + -2, -4, -3, 1, 2, 4, 2, -1, -2, -4, -2, 1, 3, 3, 1, -2, + -2, -3, -2, 1, 3, 3, 1, -2, -2, -2, -1, 1, 3, 3, 0, -2, + -4, -4, -3, -2, -1, 2, 5, 7, -4, -4, -3, -3, -2, 1, 5, 7, + -2, -3, -2, -3, -3, -1, 3, 5, -1, -1, 0, -2, -3, -2, 2, 4, + 1, 1, 1, -1, -4, -3, 1, 3, 4, 3, 2, -1, -4, -3, -1, 1, + 6, 4, 3, 0, -3, -3, -2, 0, 6, 5, 3, 1, -2, -3, -2, -1, + 12, 11, 8, 4, 0, -2, -2, -1, 10, 9, 6, 2, -1, -2, -1, 0, + 4, 3, 2, 0, -1, -1, 0, 1, -1, -1, -1, -1, -2, 0, 1, 2, + -3, -5, -4, -2, -2, 0, 2, 3, -5, -5, -4, -2, -1, 0, 1, 2, + -5, -5, -4, -2, -1, 0, 1, 1, -4, -4, -3, -2, -2, -1, 0, 0, + 3, 3, 2, -1, -3, -4, -3, -2, 3, 2, 0, -2, -4, -4, -3, -2, + 2, 2, 1, -1, -3, -5, -4, -3, 3, 3, 3, 1, -2, -3, -3, -3, + 4, 4, 4, 3, 0, -2, -2, -2, 5, 5, 5, 3, 0, -1, -2, -2, + 5, 5, 4, 2, -1, -2, -3, -2, 3, 3, 3, 0, -2, -4, -4, -4, + -1, -1, 4, -2, -2, 6, 2, -5, -1, 0, 4, -2, -3, 6, 2, -6, + -1, 0, 4, -2, -3, 7, 3, -7, -1, -1, 4, -3, -4, 8, 3, -7, + 0, -1, 4, -3, -4, 7, 3, -6, -1, -1, 4, -3, -4, 7, 3, -6, + -1, -1, 3, -3, -4, 6, 3, -6, -1, 0, 3, -2, -3, 6, 3, -5, + 1, -2, -7, 2, 5, -2, -1, 1, 1, -2, -8, 3, 6, -3, -1, 2, + 2, -2, -9, 4, 7, -4, -2, 2, 3, -1, -9, 5, 7, -4, -1, 3, + 3, -1, -9, 4, 7, -4, -2, 2, 3, -1, -7, 4, 6, -4, -2, 1, + 2, 0, -6, 4, 6, -4, -1, 1, 2, 0, -5, 3, 4, -3, -1, 1, + -2, 2, 2, 0, 0, -1, -3, -4, -2, 2, 2, 1, 1, 0, -2, -4, + -2, 2, 2, 2, 2, 1, -1, -2, -3, 2, 3, 3, 4, 2, 0, -2, + -3, 2, 3, 2, 4, 2, 0, -3, -4, 1, 2, 1, 2, 1, -1, -3, + -5, 0, 1, 0, 1, 1, -2, -3, -4, 0, 0, 0, 1, 0, -2, -3, + 0, 0, -1, -2, -2, 2, 7, 8, 0, 0, -1, -3, -2, 1, 6, 7, + 0, 1, -1, -3, -3, 0, 4, 5, 0, 1, 0, -1, -1, 0, 1, 3, + 0, 2, 1, 1, 0, -1, 0, 1, -2, 0, 1, 2, 1, 0, -1, -1, + -5, -2, 0, 1, 1, 0, -3, -3, -6, -4, -1, 1, 1, -1, -3, -4, + -4, -2, 2, 5, 6, 4, 3, 2, -5, -3, 1, 4, 4, 2, 0, 0, + -4, -2, 0, 2, 1, -1, -2, -2, -2, -1, 0, 1, 0, -2, -3, -2, + -2, 0, 0, 0, -1, -1, -2, -1, -2, -1, -1, 0, 0, 0, 1, 2, + -2, -2, -1, -1, 0, 1, 3, 4, -2, -3, -2, -1, 0, 2, 4, 5, + 2, 1, -2, -2, -1, 0, 1, 0, 1, 0, -3, -3, -1, 0, 1, 0, + 0, -1, -3, -3, -1, 1, 1, 1, 0, 0, -3, -1, 1, 2, 3, 3, + 0, -1, -3, -1, 1, 3, 3, 3, -2, -2, -4, -2, 1, 3, 4, 4, + -3, -3, -4, -2, 1, 3, 3, 4, -2, -3, -5, -2, 1, 2, 3, 3, + 4, 5, 3, 4, 4, 4, 4, 5, 3, 3, 1, 0, 0, 0, 0, 1, + 1, 1, -1, -2, -3, -4, -3, -2, 2, 2, 0, -2, -2, -4, -3, -2, + 2, 3, 1, -1, -1, -3, -3, -2, 1, 2, 0, 0, -1, -2, -2, -1, + 0, 1, 0, -1, -1, -3, -2, -1, 1, 1, 0, -1, -1, -2, -2, -2, + -2, -1, -1, 0, 1, 2, 1, 0, 1, 2, 3, 5, 6, 5, 5, 3, + 1, 2, 3, 4, 5, 5, 4, 3, -2, -2, -3, -3, -2, -1, 0, 0, + -3, -3, -4, -5, -4, -3, -2, -1, -1, -1, -2, -2, -2, -1, 0, 0, + 0, 1, 0, -1, -1, 0, 0, 1, -1, 0, -1, -2, -3, -2, -2, -1, + 7, 7, 6, 5, 4, 2, -1, -2, 3, 3, 2, 2, 1, 0, -2, -3, + 0, -1, -1, -1, 0, -1, -2, -2, -1, -3, -2, -1, 0, 0, 0, 1, + 0, -2, -2, -1, -1, 1, 2, 2, 3, 1, -1, -1, -1, 1, 2, 2, + 3, 1, -2, -3, -2, -1, 1, 2, 1, -2, -5, -6, -5, -3, -2, 0, + 0, -1, -2, -3, -1, 0, -2, -2, 0, 0, -1, -1, 0, 1, -1, -2, + 0, 0, -2, -1, 0, 0, 0, -2, -1, -2, -3, -3, -2, -1, -3, -3, + -1, -2, -3, -3, -2, -2, -3, -4, 2, 2, 0, 0, 0, 0, -1, -2, + 5, 5, 3, 2, 2, 2, 0, -1, 8, 8, 6, 5, 4, 4, 2, 1, + -7, -8, -6, -3, -1, -1, -2, -1, -5, -5, -3, 0, 2, 1, 0, 0, + -1, -1, 0, 3, 4, 3, 1, 1, 2, 1, 1, 3, 4, 3, 2, 2, + 3, 2, 0, 2, 3, 2, 1, 2, 4, 2, -1, -1, 0, 1, 1, 1, + 3, 2, -2, -3, -2, -1, 0, 1, 3, 1, -3, -4, -3, -2, 0, 1, + -4, -2, -1, 2, 3, 3, 1, 0, -7, -5, -4, -2, 0, 0, -1, -2, + -6, -5, -5, -4, -2, -2, -2, -3, -1, 0, -1, -1, 0, 0, 0, -1, + 2, 3, 2, 2, 2, 2, 1, 0, 3, 5, 4, 3, 1, 0, 1, 0, + 3, 4, 3, 2, 0, -1, -1, -1, 5, 5, 3, 1, 0, -1, -1, -1, + 1, 1, 0, -1, -3, -5, -6, -4, 1, 1, 0, 0, 0, -3, -3, -1, + 0, -1, -1, 0, 1, 0, 1, 3, -2, -2, -3, -1, 2, 2, 4, 7, + -2, -2, -2, 0, 2, 2, 3, 6, -1, 0, 0, 1, 1, 0, 0, 3, + 0, 3, 3, 3, 1, -2, -3, -1, 1, 3, 4, 3, 0, -3, -5, -4, + 0, 2, 0, -1, -3, -4, -2, -2, 1, 4, 2, 0, -2, -3, -2, -1, + 3, 6, 3, 1, -2, -2, 0, -1, 4, 7, 4, 1, -2, -3, -1, 0, + 3, 6, 3, 0, -3, -3, -1, 0, 1, 3, 0, -1, -3, -2, 1, 1, + 0, 1, -1, -2, -3, -1, 2, 2, -2, -1, -3, -3, -3, -1, 1, 2, + 3, 1, -1, 0, 1, 0, 0, 0, 2, -1, -2, -1, 1, 0, -1, -1, + 1, -1, -2, 0, 1, 0, -2, -3, 0, -2, -1, 1, 3, 1, -3, -5, + 0, -2, -1, 2, 5, 2, -3, -5, 0, -2, -1, 4, 6, 3, -2, -5, + 0, -2, 0, 4, 7, 4, -2, -4, 0, -2, 0, 4, 6, 4, -2, -4, + -2, -2, -3, -4, -3, -2, -1, 0, 1, 1, 0, -1, -1, -1, 0, 1, + 3, 3, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 1, + 0, 0, 0, 0, -1, -1, -1, -1, -4, -4, -4, -4, -4, -4, -4, -3, + -3, -3, -2, -3, -2, -1, -1, 0, 3, 4, 4, 5, 5, 6, 6, 7, + -1, -2, 7, -2, -4, -1, -1, 0, -1, -2, 9, -1, -4, -1, -1, 0, + -1, -3, 10, -1, -4, -1, -1, 1, -1, -3, 10, -2, -3, -1, -1, 2, + -1, -2, 10, -2, -4, -1, -1, 2, -1, -2, 9, -2, -4, -1, -1, 2, + -1, -2, 8, -2, -4, 0, -1, 1, 0, -2, 7, -2, -3, -1, 0, 2, + 3, -4, 1, 3, -3, -2, 1, 0, 3, -5, 1, 4, -3, -2, 1, 0, + 3, -6, 2, 5, -3, -1, 3, 0, 3, -6, 2, 5, -3, -1, 2, 0, + 3, -6, 1, 5, -4, -2, 3, 0, 3, -6, 1, 5, -3, -2, 2, 0, + 2, -6, 1, 4, -3, -1, 1, 0, 2, -6, 1, 4, -2, -1, 1, 0, + 0, 0, 1, 1, 1, 0, 0, 2, 0, -1, 1, 1, 1, 0, 0, 2, + 0, -1, 0, 0, 0, 0, 0, 2, 0, -1, 0, 0, 0, 0, -1, 0, + 1, 0, 1, 0, 0, -1, -2, -1, 3, 1, 1, 0, 0, -2, -4, -3, + 5, 3, 2, 1, 0, -3, -5, -4, 5, 4, 2, 0, -1, -4, -5, -5, + 1, 0, -1, -2, -2, -3, -6, -9, 2, 0, -1, -1, 0, 0, -3, -6, + 1, 0, 0, -1, 0, 0, -2, -5, 2, 1, 1, 1, 1, 2, -1, -3, + 1, 1, 2, 1, 2, 2, 1, -1, 1, 1, 2, 1, 1, 1, 1, 1, + 0, 0, 2, 1, 0, 0, 2, 2, 0, 1, 2, 2, 0, 0, 2, 2, + -4, -3, 0, 1, 4, 6, 4, 3, -3, -2, 0, 0, 2, 4, 1, 0, + -1, -1, 0, 0, 1, 1, -2, -3, 1, 1, 1, 0, 1, 1, -3, -5, + 1, 1, 1, 0, 1, 1, -3, -5, -1, 0, 0, -1, 1, 1, -2, -4, + -1, 0, 0, -1, 1, 2, 0, -2, -1, 0, 0, 0, 2, 3, 1, 0, + -1, 0, 3, 4, 0, -4, -5, -5, 0, 0, 4, 5, 2, -2, -3, -2, + 0, -1, 2, 4, 2, -1, -1, 0, 0, -2, -1, 1, 0, -2, 0, 1, + 1, -2, -2, 0, 0, -1, -1, 1, 1, -2, -3, 0, 1, 0, -1, 0, + 1, -2, -2, 1, 3, 1, 0, 0, 1, -2, -1, 2, 4, 2, 0, 0, + 1, 2, 3, 2, 0, 2, 2, 1, -1, 0, 1, 0, -3, 1, 1, 1, + -1, 0, 0, -2, -4, 0, 2, 1, -1, 2, 2, -1, -5, 0, 2, 1, + -1, 3, 4, -1, -5, 0, 2, 1, -2, 2, 4, 0, -4, -1, 0, 0, + -4, 0, 2, 0, -4, -2, 0, 0, -5, -1, 2, 1, -2, 1, 3, 2, + 1, 0, 1, 0, 1, 2, -1, -2, 2, 0, -1, -2, 1, 3, 0, -1, + 3, 0, -2, -4, 0, 3, 1, 0, 5, 1, -3, -5, -2, 2, 1, 1, + 6, 1, -2, -5, -2, 1, 0, 1, 5, 1, -1, -5, -2, 0, -1, 0, + 3, 0, -2, -4, -2, 0, -1, 0, 1, -1, 0, -2, 0, 1, 0, 1, + 1, 1, 2, 3, 2, 1, 1, 2, -1, -1, 0, 1, 1, 0, 1, 1, + -4, -3, 0, 0, 1, 1, 1, 2, -4, -3, 0, 2, 2, 2, 3, 2, + -5, -4, 0, 1, 1, 1, 1, 2, -5, -4, -1, -1, -2, -2, -1, 0, + -3, -2, 0, 0, -2, -3, -2, -1, 2, 3, 4, 4, 2, 0, 0, 0, + -4, -2, 0, 1, 0, 0, 0, 0, -3, -1, 1, 1, 0, 0, 0, 0, + -2, 0, 2, 2, 0, 0, 0, 2, -1, 1, 2, 1, -1, 0, 3, 5, + 0, 2, 1, -1, -2, 0, 5, 6, 0, 1, 0, -3, -3, 0, 4, 6, + 1, 1, -2, -4, -4, -3, 1, 2, 1, 0, -2, -4, -5, -4, -2, 0, + -1, -3, -3, -3, -3, -2, -1, -1, 3, 2, 1, 0, 0, 1, 1, 1, + 5, 4, 3, 2, 1, 1, 2, 2, 2, 1, 0, -2, -2, -2, -1, -1, + 0, 0, 0, -1, -2, -2, -2, -2, 0, 1, 3, 3, 2, 1, -1, -1, + 0, 1, 3, 4, 3, 2, 1, -1, -4, -3, -1, 1, 0, -2, -3, -3, + -3, -4, -7, -8, -7, -4, -1, 2, 0, -1, -3, -4, -4, -2, 0, 2, + 1, 0, 0, -1, -3, -2, 0, 2, 2, 1, 1, 0, -1, -1, 0, 2, + 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 2, 3, 3, 2, 2, 0, 0, 1, 3, 4, 4, 3, 2, + 3, 3, 3, 0, -1, 0, 1, 2, 1, 1, 1, -1, -2, -1, -1, 1, + -2, -2, -1, -3, -3, -2, -2, 0, -4, -4, -2, -2, -2, -2, -3, 0, + -4, -4, -1, 1, 1, 0, -1, 2, -3, -1, 2, 3, 4, 3, 3, 5, + -2, 0, 2, 3, 3, 3, 3, 3, -2, -2, 0, 0, 0, 0, 0, 1, + 0, 2, 1, -1, -3, -1, 3, -2, -1, 0, -1, -1, -3, 0, 4, -2, + -2, -2, -2, -2, -2, 1, 5, -2, -3, -2, -3, -1, -2, 1, 4, -3, + -2, 0, -1, 0, -1, 0, 3, -5, 1, 2, 1, 2, 0, 0, 2, -5, + 2, 4, 2, 3, 1, 1, 3, -3, 1, 2, 1, 1, 0, 1, 4, -2, + 4, -3, -4, -1, 3, 3, 1, 3, 4, -4, -4, -1, 3, 2, 0, 2, + 4, -3, -4, 0, 2, 2, -1, 1, 4, -3, -2, 1, 2, 1, -2, 0, + 2, -4, -2, 1, 2, 0, -3, 0, 2, -3, -2, 0, 1, 0, -2, 2, + 3, -1, -1, 0, 0, 0, 0, 3, 2, -2, -2, -2, -1, -1, -1, 2, + 2, 2, 3, 4, 3, 1, 0, -1, 1, 0, 1, 2, 1, -1, -2, -2, + 2, 1, 2, 1, 1, 0, -1, -1, 4, 3, 4, 3, 2, 1, 1, 1, + 3, 2, 2, 2, 1, 1, 1, 1, -1, -2, -1, 0, -1, -1, -1, -1, + -3, -3, -2, -1, -2, -2, -2, -2, -4, -4, -3, -3, -4, -4, -3, -3, + 2, 1, -1, -3, -4, -2, 3, 4, 2, 2, 1, -1, -3, -2, 1, 2, + 1, 2, 3, 3, 0, -2, -1, -2, -1, 0, 2, 4, 2, 0, -1, -3, + -2, -2, 0, 3, 3, 2, 0, -3, 0, -2, -3, -1, 1, 2, 2, -1, + 3, -1, -4, -5, -3, 0, 2, 0, 6, 3, -2, -6, -5, 0, 3, 1, + -2, 3, -2, 0, 3, -2, -2, 1, -3, 4, -3, 0, 3, -2, -1, 2, + -3, 5, -3, 0, 4, -2, -1, 2, -2, 4, -4, -1, 3, -3, -2, 2, + -3, 4, -3, 0, 3, -3, -1, 2, -2, 5, -2, 0, 3, -3, -1, 2, + -2, 4, -3, 1, 3, -2, -1, 2, -2, 3, -2, 1, 3, -2, 0, 2, + 1, 0, 0, -1, 1, 2, -4, -1, 2, 0, 0, -1, 1, 2, -4, -2, + 1, 1, 1, -1, 2, 4, -2, 0, 0, -1, 1, -1, 2, 5, -1, 1, + 0, -1, 0, -2, 1, 5, -1, 1, 0, -1, -1, -2, 0, 3, -3, -1, + 1, 1, 0, -2, 0, 3, -3, -1, 1, 1, 0, -3, 0, 3, -2, 0, + 1, 0, -1, 1, 1, 2, 4, 5, 1, 0, -1, 1, 1, 1, 5, 7, + 0, 0, -2, -1, -1, 0, 3, 5, 0, -1, -2, -1, -1, -1, 2, 3, + 0, -1, -3, -1, -1, -1, 1, 2, -1, -2, -4, -2, -2, -2, 0, 0, + -1, -2, -2, -1, -2, -2, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, + 3, 3, 0, -1, -1, 1, 4, 4, 2, 3, 0, -2, -2, 0, 1, 1, + 2, 3, 1, -1, -1, 0, 1, 0, 1, 2, 0, -1, -1, -1, 0, -2, + 0, 1, 0, -1, -2, -1, 0, -2, 0, 1, 0, -1, -2, -1, 1, 0, + 1, 1, -1, -3, -4, -3, 1, 3, 1, 2, -1, -3, -5, -4, 1, 3, + -3, -2, 0, 1, 1, 1, 0, -2, 0, 1, 1, 1, 0, 0, -1, -3, + 1, 2, 1, 1, 0, -1, -1, -2, 0, -1, -3, -1, -1, -1, 0, -1, + 0, -3, -6, -3, -2, -1, 1, 1, 2, -1, -4, -3, -2, 0, 2, 2, + 5, 4, 1, 1, 0, 1, 3, 2, 5, 4, 2, 1, 0, -1, 0, 1, + -2, 0, -2, -5, -6, -3, 0, 0, -2, 0, 1, 0, -1, 1, 2, 2, + -2, 0, 1, 3, 2, 2, 2, 1, -2, 0, 2, 4, 3, 2, 1, 1, + -2, 0, 2, 3, 2, 0, -1, 0, -3, -1, 1, 1, 0, -1, -1, 1, + -4, -1, 1, 0, -1, -2, 0, 2, -4, -1, 0, -1, -1, -2, 1, 4, + -3, 0, 0, -1, 1, 1, 1, 0, -3, 1, 0, -1, 0, 0, -1, -1, + -1, 3, 3, 0, 1, 0, 0, 1, -3, 2, 2, -2, -1, 0, 0, 1, + -5, 0, 0, -2, -1, 1, 0, 2, -7, -2, 1, 0, 1, 2, 2, 2, + -5, 0, 3, 2, 3, 3, 2, 2, -3, 2, 4, 1, 0, 0, -2, -3, + 5, 2, -2, -2, 0, -1, -1, -1, 2, -1, -4, -3, -1, -2, -1, -1, + 0, -2, -2, 1, 2, -1, 0, 1, -1, -2, -1, 3, 3, -1, 0, 2, + 1, 0, 0, 3, 3, -2, -1, 2, 2, 1, 1, 3, 2, -2, -2, 0, + 1, 0, -1, 1, 1, -3, -3, -2, 1, 0, 1, 2, 3, 0, 0, 0, + -4, -5, -3, 0, 1, -1, -2, -1, -2, -3, -1, 1, 2, 0, 0, 0, + 1, 1, 2, 1, 2, 1, 1, 1, 3, 4, 3, 1, 0, -2, -1, -1, + 3, 3, 2, 0, -2, -3, -3, -2, 1, 1, 0, -1, -2, -4, -2, -2, + 2, 1, 0, 0, 0, -1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 3, + 0, 0, 0, -1, -2, -1, 1, 0, -2, -1, -1, -2, -3, -2, 0, 0, + -1, 0, 0, -1, -2, 0, 1, 1, 1, 1, 0, -1, -1, 1, 3, 1, + 2, 2, 0, -2, -1, 2, 3, 0, 3, 1, -1, -1, 1, 4, 2, -2, + 2, 0, -3, -1, 3, 5, 0, -5, 1, -1, -2, 0, 3, 3, -1, -6, + -1, 0, 3, 4, 2, 0, 1, 2, -2, -1, 0, 1, -1, -2, 0, 1, + -2, -3, -2, -3, -6, -7, -6, -3, 2, 2, 3, 1, -1, -2, -3, -2, + 2, 2, 3, 1, 0, 0, 0, 0, 2, 1, 1, 0, 1, 1, 0, 1, + 1, 0, 0, 0, 0, 1, 1, 2, 1, 0, -1, 0, 0, 2, 2, 1, + 1, 1, 3, 1, -1, -1, -1, 1, -2, -1, 0, 0, -2, -2, -1, 2, + -2, -2, 1, 1, 1, 0, 1, 3, -2, -2, 0, -1, 0, -1, 0, 2, + 0, 0, 1, 0, -1, -1, -2, 1, 3, 2, 2, 1, 0, -2, -2, 1, + 5, 3, 3, 2, 1, 1, 1, 4, 0, -3, -4, -5, -4, -3, -1, 1, + -6, -4, -1, 2, 2, 0, 0, -1, -4, -2, 1, 3, 3, 2, 2, 0, + -3, -2, -1, 2, 3, 3, 2, 0, -3, -2, -2, 1, 2, 1, 1, -1, + -2, -2, -2, 0, 2, 2, 1, -1, -1, -1, -1, 1, 2, 3, 2, 0, + -1, -1, -2, 1, 2, 2, 2, -1, 0, -1, -2, 0, 2, 1, 0, -1, + 6, 4, 2, 1, 0, 0, 0, 1, 4, 2, -1, -2, -2, -2, -1, -1, + 2, 1, -1, -2, -2, -2, -2, -1, 2, 2, 0, -2, -2, -2, -1, 0, + 0, 0, -1, -2, -2, -1, 0, 1, -3, -3, -2, -1, -1, -2, -1, 0, + -3, -2, 2, 3, 2, 0, -1, -2, -2, 0, 4, 5, 5, 2, 0, -1, + 5, 4, 2, 0, -1, -2, -1, -1, 4, 3, 2, 1, 0, -1, 0, -1, + 1, 1, 0, 1, 1, 0, 1, -1, -2, -1, -1, 0, 0, -2, -2, -3, + -1, 0, 0, 0, -1, -3, -3, -5, 0, 1, 1, -1, -1, -2, -2, -3, + -1, -1, -1, -2, -1, 1, 3, 1, -1, -2, -2, -1, 2, 5, 6, 5, + -3, -3, -2, 1, 1, -2, -1, -1, 1, 2, 3, 4, 1, -3, -1, -3, + 3, 2, 0, 1, -1, -3, -1, -3, 1, 0, -1, 0, -1, -1, 1, 0, + 1, 1, 0, 1, 2, 2, 5, 3, 1, 1, 1, 2, 2, 2, 3, 0, + -3, -1, -2, -2, -3, -3, -1, -3, -1, 1, 1, 0, -1, -1, 0, -2, + 2, 0, -2, -2, 2, 4, 1, -2, 1, 0, -2, -1, 3, 5, 2, -1, + -1, -2, -3, -2, 1, 3, 1, -2, -1, -2, -1, -1, 0, 2, 1, -1, + 0, 0, 1, 1, 1, 2, 2, 0, 0, 1, 4, 4, 2, 2, 3, 1, + -2, -1, 2, 1, -2, -3, -2, -3, -1, 0, 1, 0, -3, -4, -4, -5, + 4, 0, -3, -4, -4, -4, -2, -1, 5, 0, -1, 0, -1, -3, -2, -1, + 4, 0, 0, 1, 1, 0, 0, 0, 0, -3, -2, -1, 0, 0, 1, 0, + 0, -2, 0, 0, 1, 1, 2, 1, 2, 0, 0, 0, 1, 1, 1, 0, + 2, 0, -1, -1, 1, 1, 1, 0, 1, -1, -2, -2, 0, 2, 2, 2, + -3, -5, -2, 0, -1, -3, -3, 0, 0, -2, 0, 2, 2, 0, 0, 3, + 2, -1, -2, 0, 0, -1, -1, 2, 5, 2, -1, -1, -1, -1, -1, 2, + 5, 2, 0, -1, -1, 0, -1, 2, 2, 1, 0, 0, 0, 1, 0, 2, + -1, -1, 1, 1, 2, 2, 1, 2, -3, -2, 0, 0, 0, 0, -2, -1, + 0, 3, 2, 0, -2, -3, -3, -3, 0, 3, 3, 1, 0, 0, 1, 2, + -1, 0, -1, -2, -1, -1, 1, 3, -1, 0, -1, -2, -1, -1, 0, 2, + -1, 0, -1, -2, 0, 0, -1, 2, -1, 0, -1, -2, -1, -1, -2, 1, + 0, 1, 0, -3, -1, -1, -1, 2, 5, 5, 2, -1, -1, -1, 1, 3, + 0, 0, 1, -1, -3, -2, 0, 2, 1, 1, 3, 0, -2, -2, 0, 1, + 1, 1, 3, 1, 0, 0, -1, -1, 0, -1, 2, 1, 1, 0, -1, -3, + -1, -2, 1, 1, 1, 0, -2, -4, -1, 0, 2, 1, 1, 0, -1, -3, + 1, 1, 3, 2, 1, 0, -2, -3, 2, 2, 4, 2, 1, -1, -2, -4, + 1, 2, 2, 2, 0, -2, 0, 2, -1, -1, -2, -3, -4, -5, -3, 1, + 0, 1, 1, 0, -1, -1, -1, 1, 0, 1, 1, 1, 0, 0, 0, 2, + 0, 1, 1, 2, 1, 1, 1, 2, -1, -1, 0, 2, 2, 2, 2, 3, + -2, -4, -4, -1, -2, -2, -2, 0, 1, 0, 0, 1, 0, 0, 0, 1, + 0, -1, -3, -2, 0, 2, 2, 1, 0, -1, -2, -3, 0, 1, 1, 2, + 1, 0, -2, -3, -1, 0, 0, 1, -1, 0, -1, -2, 0, 0, -1, 0, + -1, 1, 1, 0, 2, 2, 0, 0, 0, 2, 3, 1, 3, 5, 3, 2, + -1, 1, 1, -2, 0, 3, 1, 1, -1, 0, 0, -4, -4, -1, -1, -1, + -1, 1, 1, 0, 1, 2, 1, 2, -3, 0, 1, 0, 1, 1, 0, 2, + -5, -3, -1, -1, 0, 1, 0, 1, -4, -3, -2, -3, -2, -1, -1, 0, + 0, 0, -1, -2, -2, -2, -2, 0, 3, 4, 2, 0, 0, 0, 0, 1, + 2, 1, 0, 0, 0, 0, -1, 0, 0, 1, 2, 3, 4, 4, 3, 2, + -1, 4, 7, 4, 0, 0, 0, 0, -1, 4, 6, 3, 0, 1, 1, 1, + 0, 3, 4, 0, -1, 0, 0, 1, 0, 1, 1, -2, -1, 0, -1, -1, + -1, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, + -1, -3, -3, 0, 1, -1, -2, -1, -3, -4, -4, -2, -1, -2, -2, -1, + 2, 2, 1, 0, 1, 1, 0, -3, -2, -1, 0, 0, 1, 1, 0, -3, + -2, -1, 0, 1, 2, 1, 1, -2, 1, 2, 2, 2, 3, 3, 2, -1, + 1, 2, 1, 0, 1, 1, 2, -1, 0, 1, -2, -4, -2, 0, 1, -1, + 1, 1, -1, -3, -2, 0, -1, -3, 1, 2, 0, -1, 0, 1, -1, -4, + -1, -1, -2, -2, 0, 3, 4, 3, 1, 1, -1, -3, -2, 0, 0, 0, + 2, 2, 2, 2, 2, 1, -1, -1, 1, 1, 1, 3, 3, 0, -2, -2, + 0, -1, -1, -1, 0, -2, -1, -1, -1, -3, -4, -3, -2, -2, 0, 2, + -1, -1, 0, 1, 2, 2, 3, 5, -2, -1, -1, 0, 0, 0, 0, 1, + -2, -3, 2, 0, 0, 1, 1, -1, -1, -4, 1, -2, -1, 2, 2, 0, + 1, -4, 0, -2, -2, 1, 1, -1, 2, -3, 1, -1, -1, 1, 1, -1, + 3, -2, 3, 1, 0, 1, 1, -1, 1, -3, 2, 1, 0, 1, 0, -1, + -1, -5, 1, 0, -1, 0, 1, 1, 0, -3, 3, 3, 1, 2, 3, 3, + 0, -1, -2, 1, 5, 5, 2, -1, 1, -1, -2, -1, 1, 1, -2, -5, + 1, 1, -1, -2, -1, -1, -1, -3, 1, 1, -1, -1, -1, 2, 4, 3, + -1, -1, -1, -1, -1, 0, 4, 3, -1, -1, 0, 1, -1, -3, -1, -1, + 0, 0, 0, 2, 2, 0, 0, -1, 0, -2, -3, 0, 1, 1, 3, 2, + 2, 3, 2, 1, 0, 0, -2, -2, 2, 3, 0, 1, 1, 3, 3, 2, + 0, 0, -3, -1, -1, 2, 2, 3, -2, -2, -3, 1, 1, 2, 1, 1, + -2, -1, -2, 2, 1, 1, -1, -2, 0, 1, 0, 2, 0, 0, -2, -2, + 0, 1, 0, 2, 0, 0, -2, -2, -3, -2, -2, 0, -1, -2, -2, -3, + 0, 1, -1, 3, -1, 1, 3, -1, 0, 1, -1, 3, -1, -1, 2, -3, + 1, 1, -2, 3, -1, -3, 0, -3, 2, 2, -2, 3, 0, -2, 1, -2, + 1, 1, -3, 3, -1, -2, 1, -3, 1, 1, -3, 3, 0, -1, 1, -2, + 1, 2, -1, 4, 0, -1, 1, -2, 0, 1, -1, 3, -1, -3, 0, -3, + -3, -3, -1, 1, 2, 1, -1, -2, -2, -2, 0, 2, 1, 0, -2, -2, + -3, -2, 1, 2, 1, -1, -2, -1, -3, -2, 2, 4, 0, -2, -2, 1, + -3, -1, 2, 4, 0, -2, -2, 2, -1, 1, 4, 3, -1, -3, -2, 2, + 0, 2, 4, 2, -1, -2, -1, 2, 0, 1, 2, 0, -1, 0, 1, 3, + 3, 0, -5, 1, 4, 0, 0, 1, 1, -2, -5, 2, 5, -1, -2, 1, + -1, 0, 0, 3, 3, 1, 0, -1, -2, 3, 4, -2, -3, -1, 0, -2, + -3, 3, 5, -3, -3, 0, 0, -2, -1, 3, 2, -2, -2, 2, 2, -1, + 2, 0, 0, -1, 0, 0, 0, 0, 0, -3, -2, 1, 3, 0, -2, -2 +}; + +/* list of codebooks for inter-coded vectors */ +const int8_t* const ff_svq1_inter_codebooks[6] = { + svq1_inter_codebook_4x2, svq1_inter_codebook_4x4, + svq1_inter_codebook_8x4, svq1_inter_codebook_8x8, + NULL, NULL, +}; + +/* 6x16-entry codebook for intra-coded 4x2 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_intra_codebook_4x2)[768] = { + 12, 13, 13, 11, -7,-10,-15,-17,-16,-15,-12,-10, 11, 15, 15, 12, + 2, 17, 20, 15,-45,-24, 2, 13, 21, 20, -6,-36, 12, 16, -1,-27, + -18,-21, 10, 45,-11,-20, -7, 21, 43, -8,-28, 0, 33,-16,-28, 3, + -12,-18,-18, -6,-20,-10, 28, 55, -5,-18,-21,-18, 56, 30, -6,-20, + -34, 27, 29,-22,-30, 29, 26,-25, 30, 34, 33, 26,-25,-31,-35,-33, + -31,-35,-36,-32, 29, 36, 37, 31,-71,-12, 38, 34,-63, -1, 42, 33, + 58, 37,-31,-60, 55, 34,-33,-61,-57,-57, 22, 93,-57,-58, 21, 93, + 59, 69, 70, 62,-63,-68,-68,-60,-64,-71,-71,-64, 63, 73, 72, 62, + -2, 0, 7, 15,-11,-10, -3, 5, -5, -8,-10,-10, 1, 9, 14, 9, + 15, 8, -4,-11, 12, 2,-11,-12, -8, 0, 19, 28, 4, -1,-15,-26, + -15, 27, 2,-14,-14, 22, 1, -9, -4, -6,-13,-10, -6,-14, 6, 47, + -35,-20, 6, 23, 6, 9, 6, 4, -6, 2, 23,-22, -7, 4, 28,-21, + 20,-22, -2, 6, 22,-28, -5, 8,-10,-18,-16,-12, 36, 19, 2, -1, + -3, 0, 4, 8,-45,-10, 23, 23, 40, 15,-20,-35, -4, -1, 4, 1, + 9, -5,-33, 24, 8, 3,-26, 19, -1, 4, 6, -3, 32, 25,-13,-49, + 24, 24, 15, 7,-17,-27,-19, -7,-47, 0, 39, 24,-21, -6, 7, 4, + -1, 0,-10,-13, 1, 1, 5, 16, 20, 5, -3, -9, -1, -4, -2, -6, + -17, -7, 1, 4, 12, 7, 0, 0, 3, 0, 12, 11, -3, 1, 0,-23, + 4, 17, -6, 0, 6, 3,-25, 0,-17, 10, 8, 5,-14, 4, 1, 4, + 13, 10, 4, 2,-23, -9, 1, 2, 3, -3, 1, 7, 1,-23, -7, 20, + -7,-18, 2, 12, -5, -4, 10, 9, 4, 10, 7,-24, 6, 3, 4,-10, + 22,-14,-22, 6, 0, 5, 5, -1, -4, 3,-11, -4, -7, 31, 7,-14, + -5,-16, -1, 42, -4, -2, -9, -5, 5, -8, -6, -3, 42, -4,-21, -5, + -18, 12, 20,-12, 13,-13,-10, 7, -8, -9, -2,-18,-16, 6, 40, 8, + 10, -1, 0, 4, -3, 4, -1,-13, -2, 6, 1,-15, 5, 3, 1, 2, + -4, -2, 1, 3, 15, 0, -9, -4, -3, -4, -4, -4, -3, 5, 16, -3, + 2, 13, 3, 4, -3, -8,-10, 0, -6, -2, -4, -1, -2, -3, -6, 23, + 6, -6, 7, 1, 4,-18, 5, 1, -1, 1,-15, 14, -5, 6, -4, 4, + 2, 2, 2, 6,-24, 2, 7, 3,-26, 0, 3, 3, 5, 7, 1, 6, + 14, -2,-18, -3, 7, 5, -4, 2, -6, 3, 32, 1, -6, -6, -6,-12, + 5,-36, 7, 6, 9, -1, 11, 0, 4, 4, 5, 3, 4, 15, 3,-38, + 10, 23, -5,-42, 0, 4, 4, 4, 23, 17, -6,-13,-13,-37, 1, 29, + 5,-14, -1, 1, 5, 0, 3, 1, 0, 4, -5, 2, 8, 0, 0,-10, + 4, 7, -2, -3,-10, 3, 1, 1,-12, -1, 13, 3, 0, -1, 1, -3, + 0, -1, 3, 1, -6, -9, 3, 9, -6, 1, -4, -6, 8, -1, 0, 8, + -3, -3, 0, 18, -5, -1, -4, -1, -8, -2, 3, -4, 0, 17, -1, -5, + 5, -2, 9,-10, 1, -5, 6, -5, 4, 2, 2, 3, 10,-14, -8, 1, + -1, -2,-18, -1, -1, 20, 1, 2, -1, 1, -9, 1, -1, -9, 22, -4, + 6, -4, 8, -3, -1, 7,-19, 5, -7, 31, -4, -4, -6, 0, -5, -5, + -7, -8,-19, -4, 1, 1, 4, 32, 38, -1, -8, 4, -7, -8, -6,-12, + -1, 0, -7, 1, -1, 9, -1, 0, 9, -1, -1, 0, 2, -6, 1, -3, + -12, 0, 2, 1, 1, 1, 8, 0, 9, 1, 0, 2, -2, 1,-11, 0, + 0, 8, 2,-10, -1, 2, -1, 0, -2, -4, 0, -5, -2, -1, -1, 14, + -3, 7, -1, 5, 0,-10, 1, 1, -1, -5, 14, -1, -2, 1, -3, -2, + -6, 0, 0, 6, 2, 3, -9, 4, 4, -5, -1, -1, -7, 3, 8, -1, + 2, -4, -1,-11, 11, 2, 1, 0, -1, 2, 3, 9, 0, 2, 0,-15, + 3, 5,-20, 3, 3, -1, 3, 3, 1, -1, 16, 1, 2,-29, 9, 2, + -13, -6, -1, -3, 36, -1, -8, -3, 2, 5, 4, 2,-37, 9, 11, 3 +}; + +/* 6x16-entry codebook for intra-coded 4x4 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_intra_codebook_4x4)[1536] = { + -11, -3, 3, 6,-10, -1, 5, 7, -9, -1, 6, 7, -9, -1, 4, 6, + 5, 7, 0,-14, 6, 9, 2,-15, 6, 9, 2,-15, 4, 6, 0,-14, + 16, 3, -5, -6, 16, 1, -8, -8, 14, -1, -9, -9, 12, 0, -8, -8, + 8, 12, 16, 17, -2, 2, 6, 9,-10, -8, -4, 0,-15,-14,-11, -7, + -7,-10, -2, 16, -7,-11, -3, 18, -7,-11, -1, 20, -6, -8, 1, 19, + -9,-13,-16,-17, 2, -2, -7, -9, 11, 8, 4, -1, 16, 15, 11, 7, + -22, -2, 13, 15,-24, -2, 14, 16,-25, -4, 13, 15,-25, -6, 10, 13, + 26, 26, 22, 16, 17, 15, 9, 3, -2, -6,-11,-14,-20,-25,-28,-28, + -27,-27,-25,-21,-16,-15,-11, -7, 3, 8, 12, 13, 23, 28, 31, 30, + 20, 16, -7,-33, 22, 19, -6,-35, 22, 19, -6,-34, 20, 17, -6,-32, + -20,-20, 2, 38,-21,-22, 2, 40,-21,-22, 2, 40,-20,-20, 3, 38, + -47, -4, 24, 26,-50, -3, 26, 27,-50, -3, 26, 27,-47, -4, 24, 26, + 45, 6,-23,-27, 48, 5,-25,-28, 48, 5,-26,-28, 44, 6,-24,-27, + -30,-36,-10, 76,-31,-37,-11, 78,-31,-37,-11, 78,-31,-36,-10, 77, + -53,-32, 35, 52,-54,-34, 36, 52,-54,-34, 36, 52,-53,-33, 34, 51, + -93,-34, 62, 65,-93,-34, 62, 66,-93,-34, 62, 65,-93,-34, 60, 64, + -7, 0, 2, 2, -8, -1, 3, 3, -8, 0, 4, 5, -6, 1, 5, 5, + 3, 7, 11, 11, 2, 2, 3, 3, 1, -2, -6, -7, 1, -5,-11,-13, + 3, -2, -4, -3, 7, 0, -5, -5, 12, 4, -5, -7, 14, 6, -4, -7, + 18, 14, 3, -2, 6, 4, 0, -3, -8, -5, -2, 0,-16,-11, -2, 2, + -8, -6, 7, 18, -7, -8, 2, 13, -4, -6, -2, 6, 0, -4, -3, 1, + 1, -3,-13,-18, 0, -1, -5, -7, -1, 1, 6, 7, -2, 4, 15, 17, + -15,-14, -7, -2, -6, -5, -1, 0, 6, 6, 3, 1, 15, 13, 6, 1, + 2, -2,-11, 10, 2, -1,-12, 11, 3, -1,-12, 11, 2, -2,-11, 11, + -9, 14, -1, -5, -9, 15, -2, -5, -8, 16, -2, -5, -7, 15, -1, -4, + 2, 6, 8, 8, -2, 3, 9, 12,-11, -5, 4, 10,-19,-16, -8, 0, + 14, 8, -7,-15, 12, 7, -7,-14, 8, 5, -4, -9, 5, 3, -1, -4, + 12,-14, -2, 2, 13,-15, -1, 3, 14,-15, -1, 3, 13,-14, -1, 3, + 0, 6, 10,-13, 0, 6, 10,-15, 0, 7, 9,-17, 1, 6, 8,-16, + -8, -5, 15, -2, -8, -6, 17, -2, -8, -6, 16, -3, -8, -5, 15, -2, + -9,-11,-11,-10, 9, 10, 9, 8, 8, 10, 10, 9, -8, -9, -8, -7, + 9, 10, 9, 7, -8,-10,-10,-10, -7,-10,-11,-11, 11, 12, 11, 8, + 0, 10, 7, 0, 0, 7, 0, -6, 0, 2, -5, -6, -2, -1, -4, -1, + 5, 0, -6, -9, 2, 2, 2, 1, -2, 0, 5, 7, -6, -5, 1, 4, + 3, -8, 2, -1, 4, -9, 3, 0, 5, -7, 3, 0, 7, -5, 3, 0, + -5, -3, 2, 9, -6, -3, 1, 8, -6, -3, 1, 7, -5, -2, 0, 4, + 13, 8, 3, 1, -3, -5, -4, -1, -8, -7, -3, 0, -1, 1, 3, 2, + 3, 2, -5,-12, 4, 3, -2, -9, 3, 4, 1, -4, 3, 5, 4, -1, + -9, -8, -4, 0, 8, 6, 2, 0, 10, 8, 3, 0, -6, -5, -3, -1, + -3, -9,-12, -5, 0, -3, -5, 0, 2, 3, 2, 4, 5, 8, 7, 6, + -1, -2, 5, 12, -1, -1, 5, 9, 2, 1, -1, -2, 2, -1,-11,-17, + -7, 3, 3, -1, -9, 3, 4, -1,-10, 4, 6, -1, -9, 5, 7, 0, + -18, -7, 2, 2, -8, 1, 5, 3, 3, 4, 1, 0, 9, 5, -2, -3, + -2, 0, 6, 8, -4, -5, -5, -3, 1, -2, -6, -8, 10, 9, 3, -1, + 0, -2, -2, 0, 0, -4, -5, 0, -2, -8, -4, 8, -5, -7, 6, 24, + 9, 1, -7, 1, 9, 1, -8, 1, 8, 0,-10, 1, 8, -1,-11, -1, + 8, 8, 6, 3, 5, 4, 3, 2, -2, -3, -1, 0,-10,-13, -8, -4, + 0, 4, 2, -3, 0, 6, 3, -5, 3, 10, 2,-12, 5, 10, -4,-22, + 0, -4, -1, 3, 1, -4, -1, 5, 1, -5, 0, 8, -1, -6, -2, 7, + -1, -1, -2, -4, -1, -2, -4, -6, -1, -1, -1, -2, 1, 5, 10, 9, + 10, 3, 0, -2, 6, -1, -2, -5, 3, -1, -2, -6, 2, 0, 0, -5, + 6, 3, 0, 0, 6, 3, 1, 1, 4, -2, -2, 1, 0, -9, -9, -2, + -11, -3, 1, 2, -6, 2, 4, 5, -3, 2, 3, 4, -2, 1, 1, 2, + -6, -4, -1, -2, 2, -1, -1, -2, 10, 2, -2, -2, 11, 2, -4, -1, + 6, 0, -2, 2, 3, 3, 0, 0, -6, 3, 3, 0,-17, -1, 5, 0, + -1, 4, 10, 11, -3, -2, 0, 1, -3, -4, -5, -3, -1, -2, -2, -1, + 2, -3, -9,-12, 3, 3, 3, 2, 2, 2, 4, 4, 2, 1, -1, -2, + -2, 9, 5,-10, -3, 5, 5, -5, -2, 1, 2, 0, -1, -2, -2, 1, + -2, -3, 7, -2, -1, -3, 7, -3, -1, -2, 8, -4, -2, -2, 7, -3, + 1, -8, -3, 12, 2, -2, -2, 4, 1, 3, 0, -5, -1, 5, 2, -7, + -1, 3, 1, -5, -7, -2, 3, 1, -2, -7, -2, 2, 20, 3, -5, -1, + 5, 0, -3, -2, -7, -7, 0, 6, -6, 0, 7, 6, 2, 6, 0, -7, + -2, 6, -7, 1, -2, 7, -8, 3, -2, 7, -7, 3, -1, 7, -6, 2, + -5, -2, 5, 7, 4, 1, -4, -8, 6, 3, -2, -5, -7, -5, 3, 7, + -1, -1, 6, 5, 0, -1, 1, -4, 2, 1, 0, -7, 1, 0, 0, -4, + -8, 0, 3, 1, -2, 1, -1, -1, 1, -1, -3, 1, 1, -2, 1, 9, + 5, 2, -3, -4, -1, 0, -1, -3, -3, 1, 3, 1, -4, 0, 4, 2, + 2, -2, -2, 12, 0, -2, -5, 3, -1, 0, -3, 1, -3, -1, -2, 1, + 1, 5, 3, 0, -6, -4, -2, 1, 0, -2, -2, 2, 6, 1, -4, -1, + -3, -5, -5, -1, 3, 5, 5, 4, 0, 3, 1, -1, -2, 1, -2, -3, + 2, -4, -5, -3, 4, -2, -3, -2, 6, 0, -1, -1, 7, 1, 0, 0, + -3, -2, -2, 0, -2, -3, -5, -1, -2, 2, 0, -1, -1, 11, 9, -1, + 0, 1, -1,-10, -1, 1, 0, -6, 1, 0, 1, 4, 2, -5, -1, 13, + -2, 4, 5, 0, -5, 1, 6, 3, -6, -2, 3, 2, -5, -2, 0, -2, + -1, 1, 1, -2, -1, -2, 0, 2, 5, 5, 5, 7, 0, -4, -8, -7, + 0, 2, -1, -5, -1, 2, 2, -3, 0, 5, 3, -5, 3, 8, 2,-12, + 8, 4, 0, -2, 10, -1, -4, -1, 3, -6, -3, 0, -4, -5, 0, 0, + 0,-10, -4, 2, -1, -6, 3, 5, -1, -3, 6, 4, 0, -2, 4, 2, + 0, 8, 1, -1, 0, 11, 1, -3, -1, 6, -2, -4, -3, -2, -7, -4, + 0, -1, -1, -1, 4, 5, 6, 5, -5, -9, -8, -5, 2, 2, 3, 2, + 0, 2, 6, 1, 2, 0, 3, 0, 1, -2, -1, -2, 0, -1, -3, -6, + 0, 0, 2, 0, 4, 0, 2, 1, 5, -2, 0, 0, -2, -9, -1, 2, + 0, 1, 0,-10, -1, 1, 8, 0, -1, -2, 4, 0, 1, -1, 2, -1, + -3, -2, 2, -1, -3, -1, 2, -3, 0, -1, 1, 0, 8, 1, -1, 3, + 0, 1, 1, 2, 0, -4, -2, 0, -1, -5, 1, -1, -2, -1, 11, 2, + 1, 5, -2, -2, 0, 2, -4, 0, -2, 1, -5, 1, 0, 5, 0, 1, + -5, -3, 0, 6, -4, 2, 0, 0, -3, 5, 1, 0, -3, 3, 0, 0, + 3, -2, -3, 1, 1, -4, 0, 8, -2, -3, -2, 3, 1, 2, -1, -1, + 1, 1, 0, 2, 2, 0, 1, 6, 1, -1, 2, 1, 0, 3, 0,-19, + 1, -3, -2, 2, 6, 5, -2, -7, -3, 1, 3, 1, -1, -1, 0, 2, + -8, -1, -1, -4, 1, 1, -1, 2, 4, 3, 2, 3, -5, 1, 3, 0, + 0, 2, -1, 1, -3, 0, 0, 5, -5, -2, 0, 8, -4, -4, -4, 6, + 1, 2, 1, 2, 2, 2, -3, 2, 4, 0, -9, 0, 7, 0,-11, 1, + 0, 0, 0, -2, 3, 3, -1, -6, 4, 3, -3,-10, -1, 2, 6, 2, + 7, -2, -3, 5, -4, 0, 3, -1, -4, 2, 1, -7, 2, -1, -1, 3, + 3, 2, 2, 2, -5, -7, -7, -5, 5, 6, 4, 2, -2, -1, 0, 1 +}; + +/* 6x16-entry codebook for intra-coded 8x4 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_intra_codebook_8x4)[3072] = { + 5, 6, 6, 6, 7, 7, 8, 8, 0, 0, 0, 0, 0, 1, 2, 3, + -3, -4, -4, -5, -5, -4, -3, -2, -4, -4, -4, -5, -4, -4, -3, -3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 4, 4, 5, 5, 5, + -1, 0, 1, 1, 2, 3, 4, 4, -9,-10, -9, -9, -8, -7, -6, -5, + -4, -4, -5, -6, -6, -7, -7, -7, 0, -1, -2, -2, -3, -3, -4, -4, + 4, 4, 3, 3, 2, 1, 1, 0, 7, 7, 7, 6, 6, 5, 4, 4, + 2, 4, 5, 6, 4, 1, -3, -6, 3, 4, 5, 5, 4, 0, -5, -8, + 2, 3, 4, 4, 2, -2, -7,-10, 2, 2, 2, 1, 0, -4, -9,-12, + -9, -7, -3, 1, 4, 4, 3, 3,-10, -7, -2, 3, 5, 5, 3, 3, + -9, -6, -2, 3, 6, 5, 4, 3, -8, -6, -1, 3, 4, 4, 3, 2, + -5, -5, -5, -5, -3, 1, 4, 7, -5, -5, -5, -4, -2, 1, 6, 8, + -4, -5, -4, -3, -1, 3, 8, 10, -3, -4, -3, -2, 1, 5, 9, 11, + -2, -2, -2, -2, -2, -2, -2, -2, -4, -5, -5, -5, -5, -5, -5, -4, + -3, -4, -4, -4, -4, -4, -4, -3, 9, 10, 10, 11, 11, 11, 10, 10, + 7, 4, 1, -2, -4, -6, -9,-10, 9, 7, 3, 0, -2, -4, -8, -9, + 11, 8, 4, 2, 0, -3, -6, -8, 11, 9, 5, 3, 1, -2, -5, -7, + -13,-13,-13,-12,-11,-10, -8, -8, 0, 1, 2, 3, 4, 4, 4, 3, + 3, 4, 5, 6, 6, 6, 5, 4, 3, 4, 4, 4, 3, 3, 3, 2, + 10, 10, 11, 10, 9, 9, 8, 7, 6, 6, 6, 6, 5, 4, 3, 2, + 0, 0, 0, -1, -2, -3, -4, -4,-10,-10,-11,-12,-13,-14,-14,-14, + 16, 16, 17, 16, 15, 13, 12, 11, -1, -2, -3, -4, -4, -4, -4, -3, + -4, -5, -6, -6, -6, -6, -6, -6, -5, -6, -6, -6, -6, -6, -5, -5, + -13,-13,-13,-12,-11,-10, -8, -6, -9, -8, -7, -6, -4, -2, 0, 1, + -2, -1, 1, 3, 5, 7, 8, 9, 5, 7, 9, 11, 13, 14, 15, 15, + 16, 14, 11, 7, 2, -3, -7, -9, 14, 12, 8, 3, -1, -6, -9,-11, + 11, 9, 4, 0, -4, -8,-11,-13, 8, 5, 1, -3, -6,-10,-12,-14, + -18,-15, -9, -3, 1, 6, 9, 11,-17,-13, -7, -1, 3, 7, 11, 12, + -15,-11, -5, 1, 5, 9, 12, 13,-13, -9, -3, 2, 5, 9, 11, 13, + 22, 21, 19, 15, 10, 3, -4, -9, 20, 18, 15, 9, 2, -5,-12,-17, + 16, 13, 8, 1, -7,-14,-20,-24, 10, 6, -1, -8,-15,-21,-25,-27, + -25,-23,-20,-14, -7, 1, 9, 14,-23,-21,-16, -9, 0, 9, 16, 21, + -20,-16,-10, -1, 8, 16, 22, 25,-15,-11, -3, 6, 14, 20, 25, 27, + -4, -2, 0, 1, 2, 2, 2, 2, -5, -2, 0, 2, 3, 3, 3, 3, + -6, -4, -1, 1, 2, 3, 3, 3, -7, -5, -2, 0, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 0, -2, -3, 3, 3, 2, 1, 0, -1, -3, -4, + 4, 3, 2, 1, 0, -2, -4, -6, 5, 4, 3, 1, -1, -3, -5, -6, + 5, 6, 6, 4, 2, 0, -2, -3, 3, 4, 4, 4, 3, 1, 0, -1, + -2, -2, -1, -1, -1, -1, -2, -2, -5, -4, -3, -2, -2, -2, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -1, -3, -4, -4, -4, -3, -3, -3, -3, + -1, -1, -1, -1, -1, -1, -1, -2, 5, 6, 6, 6, 6, 5, 4, 3, + 4, 4, 4, 4, 4, 5, 6, 7, 0, -1, -1, -1, -1, 0, 1, 2, + -2, -3, -3, -3, -3, -2, -1, 0, -3, -3, -4, -4, -4, -3, -2, -1, + 0, -2, -4, -4, -2, 0, 2, 3, 0, -2, -3, -3, -1, 2, 4, 5, + -1, -2, -4, -3, 0, 3, 5, 6, -2, -3, -4, -3, -1, 2, 4, 5, + 9, 4, 0, -3, -3, -1, 0, 1, 8, 4, -1, -4, -3, -1, 1, 2, + 6, 2, -3, -5, -4, -2, 0, 1, 5, 1, -3, -4, -4, -2, 0, 1, + 5, 3, 1, -1, -4, -8,-10,-10, 3, 3, 2, 1, 0, -2, -3, -4, + 1, 1, 1, 2, 3, 2, 1, 0, -1, 0, 1, 2, 3, 4, 3, 2, + 0, 1, 2, 2, 1, -1, -3, -3, 0, 1, 1, 1, -1, -2, -4, -3, + -3, -3, -3, -3, -3, -3, -1, 2, -4, -4, -3, 0, 3, 7, 12, 14, + -5, -5, -6, -6, -6, -6, -6, -5, 2, 2, 2, 1, 0, 0, 0, 0, + 4, 4, 3, 2, 1, 0, 0, 0, 6, 6, 5, 4, 2, 2, 1, 1, + -7, -7, -6, -3, 0, 4, 7, 8, -1, -2, -3, -3, -2, -1, 1, 2, + 3, 3, 1, -1, -2, -2, -2, -1, 6, 6, 4, 2, 0, -2, -2, -2, + -6, -5, -2, 2, 5, 9, 11, 12, -4, -4, -2, 0, 2, 4, 5, 6, + -3, -2, -2, -2, -2, -1, 0, 1, -2, -2, -2, -3, -3, -3, -3, -2, + -7, -3, 1, 3, 3, 0, -3, -5, -6, -2, 3, 5, 4, 1, -3, -5, + -5, -1, 4, 6, 5, 2, -3, -4, -4, 0, 5, 7, 6, 3, -1, -3, + 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -3, -3, -3, -3, -2, -1, + 6, 7, 8, 9, 9, 8, 7, 6, -4, -4, -5, -5, -6, -6, -5, -4, + -9, -8, -6, -4, 0, 3, 6, 6, -5, -4, -1, 3, 5, 6, 5, 3, + 1, 3, 6, 6, 4, 1, -2, -5, 6, 7, 5, 1, -3, -7,-10,-11, + 10, 9, 5, 1, -3, -6, -6, -4, 5, 3, -1, -5, -6, -5, -2, 2, + -2, -4, -6, -6, -4, 1, 6, 10, -6, -7, -7, -4, 1, 7, 11, 12, + 6, 5, 3, 2, 0, 0, 0, 0, 2, 1, -1, -2, -3, -2, -1, -1, + 0, -1, -2, -4, -4, -2, -1, 1, 0, 0, -1, -2, -1, 0, 2, 3, + 0, -1, -2, -2, -2, -2, -1, -1, 5, 4, 2, 1, 0, 0, 0, 0, + 6, 5, 3, 1, 0, 0, 0, 0, 2, 0, -2, -4, -4, -3, -2, -2, + -7, -4, 0, 2, 2, 2, 2, 1, -7, -3, 0, 0, 0, 0, 0, 0, + -4, -1, 1, 1, 0, 0, 0, 1, -1, 1, 2, 2, 2, 2, 3, 3, + -2, 0, 2, 2, 1, 1, 1, 1, -1, 1, 2, 2, 1, 0, 0, -1, + 0, 2, 4, 2, 0, -1, -2, -3, 1, 2, 3, 1, -2, -4, -6, -6, + 1, 2, 2, 4, 5, 6, 4, 1, 0, -1, -1, -1, 0, 0, -2, -4, + 0, 0, -1, -2, -2, -2, -4, -6, 2, 1, 0, 0, 1, 1, -1, -3, + 1, 1, 1, 1, 1, 2, 3, 3, 0, 0, 1, 0, 1, 2, 4, 4, + -1, -1, -1, -1, 0, 1, 2, 3, -4, -4, -5, -5, -5, -3, -1, 0, + -6, -5, -5, -4, -3, -2, -1, -1, -1, 0, 0, 1, 1, 2, 3, 3, + 0, 1, 1, 1, 2, 2, 3, 4, 0, 0, -1, -1, 0, 1, 2, 3, + 0, 1, 1, 1, 0, 0, -1, -1, 1, 3, 3, 2, 1, -1, -2, -2, + -2, 0, 2, 2, 2, 2, 1, 1, -9, -8, -4, -2, 1, 3, 3, 3, + -1, -1, -1, -2, -3, -3, -3, -4, 0, 0, 0, -1, -2, -2, -3, -3, + 2, 2, 2, 0, -1, -1, -1, -1, 5, 5, 4, 3, 2, 2, 2, 2, + 6, 3, -1, -4, -3, -1, 1, 1, 2, -1, -3, -4, -1, 2, 2, 0, + -1, -2, -2, 1, 4, 4, 1, -3, -2, -1, 1, 4, 6, 3, -3, -8, + 3, 3, 2, 1, -1, -2, -2, -2, -4, -4, -2, -1, 1, 3, 4, 4, + -4, -5, -5, -4, -2, 0, 2, 2, 7, 7, 4, 1, -1, -2, -3, -2, + -1, 1, 3, 0, -4, -6, 0, 6, -2, 1, 4, 1, -4, -6, -1, 7, + -3, 1, 4, 2, -3, -6, -1, 6, -2, 0, 3, 2, -2, -5, -1, 4, + 1, -1, -2, 1, 4, 4, -1, -7, 1, -1, -4, -1, 5, 6, 0, -6, + 3, 0, -4, -3, 3, 6, 2, -4, 3, 0, -5, -4, 1, 4, 1, -3, + 2, 2, 3, 3, 3, 3, 2, 2, -4, -5, -6, -7, -7, -7, -7, -6, + 1, 2, 3, 3, 3, 3, 2, 2, 0, 0, 1, 1, 1, 2, 2, 1, + 3, -3, -3, 3, 4, -2, -2, 2, 3, -4, -4, 4, 4, -4, -4, 2, + 4, -4, -4, 4, 4, -4, -3, 3, 3, -3, -4, 3, 3, -3, -3, 3, + -2, -2, -2, -2, -2, -2, -1, -1, 6, 7, 8, 8, 8, 7, 6, 5, + -5, -6, -7, -7, -8, -7, -6, -5, 1, 1, 2, 2, 2, 2, 1, 1, + 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, + -2, -3, -2, -2, -2, -3, -3, -3, 2, 3, 5, 6, 4, 2, 1, 0, + 8, 6, 2, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, -1, -1, -1, + 1, -1, 0, 0, 0, -1, -2, -3, -2, -2, -1, 0, 0, -2, -4, -5, + 3, 1, -1, -2, -3, -4, -5, -5, 2, 1, 0, 0, 1, 1, 0, 0, + 0, -1, -1, 0, 2, 2, 2, 2, -1, -2, -1, 1, 2, 2, 2, 2, + 0, -1, -2, -1, -1, -1, -1, 0, -1, -2, -2, -1, -1, 0, 0, 1, + 2, 1, 1, 2, 2, 1, 1, 0, 6, 5, 3, 1, 0, -2, -4, -4, + -3, -2, -1, 0, 1, 1, 0, -1, 0, 1, 3, 4, 5, 5, 3, 1, + -1, -1, -1, 0, 1, 0, -1, -2, -2, -2, -2, -1, 0, -1, -2, -3, + 0, -1, -2, -2, -1, -1, 0, 2, 1, -1, -2, -1, -1, -1, 0, 2, + 1, 0, -2, -2, -2, -2, 1, 5, 1, -1, -2, -2, -2, 0, 5, 10, + 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0, 0, 1, 2, + 1, 2, 2, 3, 4, 4, 6, 5, -3, -3, -3, -2, -2, -3, -3, -3, + 1, -1, -2, -2, 0, 3, 5, 7, 2, 0, -2, -3, -2, 0, 2, 3, + 3, 1, -2, -3, -3, -2, -1, -1, 3, 1, 0, -1, -1, -1, -1, -1, + 1, 3, 5, 4, 2, -1, -3, -4, -3, -2, 1, 2, 1, 0, -1, -2, + -5, -3, 0, 2, 2, 1, 0, 0, -3, -1, 1, 2, 2, 1, 0, 0, + 0, -1, -1, -1, 1, 2, 3, 4, -3, -4, -4, -3, -1, 0, 0, 1, + -2, -3, -2, -1, 1, 1, 1, 1, -2, -2, 0, 3, 4, 4, 3, 2, + -4, -4, -3, -2, -1, 1, 2, 3, 0, 1, 1, 1, -1, -2, -3, -3, + 3, 4, 5, 4, 2, -1, -3, -3, -2, -2, 0, 2, 2, 2, 1, 0, + -4, 0, 5, 7, 4, -1, -4, -4, -1, 2, 4, 3, 0, -3, -3, -2, + 2, 1, 0, -1, -2, -2, 0, 1, 0, 0, -1, -2, -2, -1, 1, 2, + -4, -3, -2, -1, 0, 1, 2, 2, 10, 9, 5, 0, -3, -4, -3, -2, + 1, -1, -2, -2, -1, 0, 0, 0, -2, -2, -1, 1, 1, 1, 0, -1, + -5, -3, 0, 3, 4, 2, 0, -2, -2, -1, 0, 1, 1, 0, -1, -1, + 3, 2, -1, -2, -2, -1, 1, 1, 7, 5, -1, -5, -6, -2, 2, 4, + -2, 3, 3, -3, -4, 1, 2, -2, -3, 3, 4, -3, -4, 2, 3, -2, + -3, 3, 4, -3, -4, 2, 3, -2, -4, 2, 4, -2, -3, 1, 2, -1, + 4, 3, -1, -3, -3, -1, 1, 2, -4, -6, -4, 0, 4, 5, 4, 1, + 0, 2, 5, 6, 2, -3, -5, -4, 1, 1, -1, -3, -5, -2, 2, 4, + -1, 0, 1, 2, 2, 3, 3, 4, -1, 0, 1, 1, 0, -1, -1, -1, + -1, 0, 1, 2, 2, 1, -1, -2, -3, -2, -1, 0, 0, -1, -2, -3, + 1, 1, 1, 1, 0, 0, 1, 2, 1, 0, -1, 0, 0, 1, 1, 0, + 1, -2, -4, -1, 1, 2, 1, 0, 1, -4, -7, -3, 1, 3, 2, 1, + 1, 1, 1, 1, 1, 1, 0, -1, 1, 1, 1, 0, 1, 2, 2, 0, + 1, 1, 0, 0, 0, 2, 0, -3, 3, 2, 0, -1, -1, -2, -6, -9, + 0, 0, 0, 1, 0, 0, 1, 2, 1, 0, 0, 0, -1, -1, 0, 2, + 0, 1, 1, 1, -1, -3, -2, 0, -7, -5, 1, 6, 6, 2, -1, -1, + 3, 1, -1, -3, -4, -2, 1, 4, 2, 0, -2, -3, -4, -3, -1, 2, + 2, 2, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, + -1, 1, 1, -2, -5, -6, -4, -1, -1, 1, 4, 3, 2, 0, 1, 2, + -1, 0, 2, 3, 1, 0, 0, 1, -1, 0, 1, 0, 0, -1, -1, 0, + 0, 1, 2, 2, 0, -2, -1, 1, -2, -1, -1, -2, -1, 2, 6, 8, + -1, -1, -2, -3, -2, 0, 1, 2, -1, 0, 0, -1, -1, 0, -1, -1, + 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, -1, -1, 1, + -1, 0, 2, 2, -1, -3, -2, 3, 0, 2, 3, 0, -5, -7, -2, 4, + -1, 0, 0, 0, -1, -2, -3, -3, -1, 0, -1, -2, -2, -2, -2, -2, + 1, 1, 0, 0, 1, 2, 0, -1, 1, 2, 1, 2, 5, 6, 2, 0, + -2, -4, -3, 0, 2, 2, 0, -3, 3, 1, 0, 1, 2, 1, -2, -3, + 3, 1, 0, 0, 0, 0, 0, -1, 1, -1, -2, -2, -1, 1, 3, 3, + 3, 2, 1, 2, 4, 3, 1, -2, -2, -4, -4, -3, -1, 0, -2, -3, + 1, 0, -1, -1, 0, 1, 0, -1, 3, 2, 0, 0, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 2, 3, 3, 2, 2, 2, 1, 1, + 0, -1, -2, -3, -5, -5, -5, -4, 1, 1, 0, -1, 0, 1, 3, 3, + -9, -6, -2, 0, 1, 1, 2, 2, -6, -2, 1, 2, 1, 1, 0, 1, + -2, 1, 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 0, 1, 1, 1, + 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, -3, -2, 0, + -3, -3, -3, -2, -1, 3, 7, 9, 1, 2, 2, 2, 0, -2, -4, -3, + 2, 0, -2, -1, 3, 4, -1, -6, 1, 0, -2, -3, -1, 3, 3, 0, + 0, 3, 3, 0, -2, -1, 1, 1, -6, -1, 3, 2, -1, -2, 0, 1, + 5, 3, 0, -2, -3, 0, 2, 1, 1, 1, 2, 2, 0, -2, -4, -7, + -3, -2, 1, 2, 2, 1, -1, -4, 2, 2, 0, -2, -2, 0, 2, 2, + 0, 0, -2, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + -2, -1, 0, 1, 0, 1, 2, 3, -4, -2, 0, 0, -1, 0, 2, 3, + -2, -2, -2, -1, -1, 0, 2, 4, 0, 0, 0, 0, -1, -1, 0, 1, + 0, -1, -1, -1, -1, -1, 0, 0, 6, 4, 2, 0, -1, -2, -1, -1, + 0, 1, 1, 1, 1, -1, -5,-10, 1, 1, 1, 1, 1, 1, 0, -4, + 1, 0, 1, 1, 1, 1, 1, -1, 2, 1, 1, 1, 0, 0, 0, 0, + -3, 1, 4, 3, 3, 1, -1, 0, -4, 0, 1, 0, -1, 0, 0, 0, + -5, 0, 2, 1, 1, 1, 0, -1, -1, 2, 1, -2, -2, -1, 0, -1, + 2, 4, 5, 3, 0, -1, 1, 2, 0, 0, 1, 0, -2, -2, -1, -1, + -2, -2, -2, -2, -3, -2, -1, 0, 0, 0, 1, 0, 0, 0, 1, 2, + 0, -2, -2, -3, -1, 2, 2, -1, 1, 0, 0, 0, 1, 5, 3, -2, + -1, -1, 0, -1, 0, 2, 0, -5, -1, 0, 1, 0, 0, 2, 2, -2, + 3, 1, -1, -1, 0, 1, 1, 2, 1, 0, 0, 1, 1, 1, 1, 1, + -10, -8, -2, 1, 2, 1, 1, 1, -1, 1, 2, 1, 0, 0, 0, 0, + -1, -1, 0, 1, 2, 2, 2, 1, -1, -1, -1, 0, -1, -3, -5, -4, + 1, 1, 2, 1, 1, 0, 0, 2, -1, -2, -1, -1, -1, 0, 2, 4, + -3, -7, -5, 0, 2, 0, 0, 0, 3, -1, -2, 1, 2, 1, 1, 2, + 1, -2, -1, 1, 2, 1, 0, 1, 0, -1, 0, 3, 2, -1, -1, -1, + 2, 1, 1, 0, 0, 0, 0, 0, -9, -7, -2, 3, 3, 2, 1, 1, + 3, 2, 0, -2, -2, -1, 1, 1, 0, -1, 0, 0, 1, 1, 0, 0, + -2, -1, 1, 1, 1, 0, 0, 0, 1, 2, 1, -2, -4, -3, 1, 2, + 1, 2, 1, -2, -3, 0, 3, 1, -1, -1, 0, 0, 1, 3, 0, -4, + 2, 0, -1, 1, 2, -2, -2, 3, 2, 0, -1, 2, 3, -2, -4, 1, + 0, 1, 1, 1, 2, -2, -6, -2, -1, 0, 0, 0, 2, 0, -2, -1, + -1, -1, 1, 2, 1, -2, -3, -2, 3, -1, -2, -1, -1, 0, 1, 2, + 10, 4, 0, 0, -1, -2, -2, -1, 3, -1, -2, -1, 0, -1, -1, 0, + -5, 2, 7, 1, -4, -2, 1, 0, -2, 2, 3, -1, -3, 0, 2, 0, + 2, 1, 0, 0, 1, 1, -1, -2, 1, -2, -2, -1, -1, -2, 0, 0, + 0, 3, -2, -7, -1, 3, 0, 0, 1, 3, -3, -5, 2, 3, -1, 0, + 0, 2, -2, -2, 4, 2, -2, 0, -1, 1, -1, 0, 2, -1, -2, 1, + 4, 0, -3, -4, -2, 1, 2, 1, 0, 0, 3, 5, 3, 1, -1, -2, + 1, 1, 1, -1, -3, -1, 1, 1, 1, -1, -2, -2, 0, 0, -1, -2 +}; + +/* 6x16-entry codebook for intra-coded 8x8 vectors */ +DECLARE_ALIGNED(4, static const int8_t, svq1_intra_codebook_8x8)[6144] = { + 4, 4, 3, 2, 2, 1, 0, -1, 4, 3, 3, 2, 1, 0, -1, -1, + 3, 3, 2, 2, 1, 0, -1, -2, 3, 2, 2, 1, 0, -1, -2, -3, + 2, 2, 1, 0, -1, -1, -2, -3, 2, 1, 0, 0, -1, -2, -3, -4, + 1, 0, 0, -1, -2, -3, -4, -4, 0, 0, -1, -2, -2, -3, -4, -4, + 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, + 1, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 1, + -1, 0, 0, 0, 0, 0, 1, 1, -2, -2, -1, -1, -1, -1, -1, -1, + -3, -3, -3, -3, -3, -3, -2, -2, -5, -4, -4, -4, -4, -4, -4, -3, + -4, -2, -1, 0, 1, 2, 2, 3, -4, -2, -1, 0, 1, 2, 3, 3, + -4, -3, -1, 0, 1, 2, 3, 3, -4, -3, -1, 0, 1, 2, 3, 3, + -5, -3, -1, 0, 1, 2, 3, 3, -5, -3, -1, 0, 1, 2, 3, 3, + -5, -3, -1, 0, 1, 1, 2, 3, -5, -3, -2, -1, 0, 1, 2, 3, + 4, 4, 5, 5, 6, 6, 7, 7, 2, 2, 2, 3, 3, 4, 4, 4, + 0, 0, 0, 0, 1, 1, 1, 2, -2, -2, -2, -2, -1, -1, -1, 0, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -1, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -2, -2, -2, -2, + 5, 3, 1, -1, -2, -3, -3, -3, 5, 3, 1, -1, -2, -3, -3, -3, + 5, 3, 1, -1, -2, -3, -3, -3, 5, 3, 1, -1, -2, -3, -3, -3, + 5, 4, 1, 0, -2, -3, -3, -3, 6, 4, 2, 0, -2, -2, -3, -3, + 6, 4, 2, 0, -1, -2, -2, -3, 6, 4, 2, 1, -1, -2, -2, -2, + -1, 1, 3, 3, 2, 0, -3, -6, -1, 1, 3, 4, 3, 0, -3, -6, + -1, 1, 4, 4, 3, 1, -3, -6, -1, 1, 3, 4, 3, 1, -3, -6, + -2, 1, 3, 4, 3, 1, -3, -6, -2, 1, 3, 4, 3, 1, -3, -7, + -2, 1, 3, 3, 2, 0, -3, -7, -2, 0, 2, 3, 2, 0, -3, -6, + 10, 9, 8, 6, 6, 5, 4, 4, 6, 5, 4, 3, 2, 2, 2, 1, + 2, 1, 0, -1, -2, -2, -2, -1, -1, -2, -3, -4, -4, -4, -4, -3, + -2, -3, -4, -4, -5, -4, -4, -3, -2, -2, -3, -3, -3, -3, -2, -2, + -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1, 2, + -2, -1, 1, 2, 4, 5, 7, 8, -3, -2, 0, 1, 3, 5, 7, 8, + -4, -3, -1, 0, 2, 4, 6, 7, -5, -4, -2, -1, 1, 3, 5, 7, + -6, -5, -3, -2, 0, 2, 4, 6, -6, -5, -4, -2, -1, 1, 3, 5, + -7, -6, -5, -3, -2, 0, 2, 3, -8, -7, -5, -4, -3, -1, 1, 2, + 11, 9, 7, 5, 3, 1, -1, -1, 10, 8, 6, 3, 1, 0, -2, -2, + 9, 7, 5, 2, 0, -2, -3, -4, 8, 6, 3, 1, -1, -3, -4, -4, + 6, 4, 2, -1, -3, -4, -5, -5, 5, 3, 0, -2, -4, -5, -6, -6, + 3, 1, -1, -3, -5, -6, -7, -7, 2, 0, -2, -4, -6, -6, -7, -7, + 5, 6, 7, 7, 7, 8, 8, 8, 3, 4, 5, 5, 6, 6, 6, 6, + 0, 2, 2, 3, 4, 4, 4, 5, -2, -1, 0, 1, 2, 2, 3, 3, + -4, -3, -2, -1, 0, 1, 1, 2, -6, -5, -4, -3, -2, -2, -1, 0, + -8, -7, -6, -6, -5, -4, -3, -3,-10, -9, -8, -8, -7, -6, -6, -5, + 6, 5, 3, 1, -1, -3, -6, -8, 6, 5, 4, 2, -1, -3, -6, -8, + 6, 5, 4, 2, 0, -3, -6, -8, 6, 5, 4, 2, 0, -3, -6, -8, + 6, 6, 4, 2, 0, -3, -6, -8, 6, 5, 4, 2, 0, -3, -6, -8, + 6, 5, 4, 2, 0, -3, -6, -8, 6, 5, 4, 2, -1, -3, -5, -8, + 11, 10, 9, 8, 7, 6, 5, 4, 8, 8, 7, 6, 5, 4, 3, 2, + 6, 5, 4, 4, 2, 2, 1, 0, 3, 3, 2, 1, 0, 0, -1, -2, + 1, 1, 0, -1, -2, -2, -3, -3, -1, -1, -2, -3, -4, -4, -5, -5, + -3, -4, -4, -5, -6, -6, -7, -7, -5, -5, -6, -7, -8, -8, -8, -8, + -14,-13,-12,-11, -9, -7, -6, -4,-12,-11,-10, -9, -7, -5, -3, -1, + -10, -9, -7, -6, -3, -2, 0, 2, -8, -6, -4, -2, 0, 2, 4, 5, + -5, -3, 0, 2, 4, 5, 7, 8, -2, 0, 2, 4, 6, 8, 9, 10, + 0, 3, 5, 7, 8, 10, 11, 12, 3, 5, 7, 8, 10, 11, 12, 12, + -19,-19,-18,-18,-17,-16,-15,-14,-15,-15,-14,-13,-12,-11,-10, -9, + -11,-10, -9, -8, -6, -5, -4, -3, -6, -5, -3, -2, -1, 0, 1, 2, + -1, 0, 2, 3, 4, 5, 6, 6, 4, 6, 7, 8, 9, 10, 10, 10, + 9, 10, 11, 12, 13, 14, 14, 14, 12, 14, 14, 15, 16, 16, 16, 16, + 22, 21, 19, 17, 14, 11, 9, 5, 20, 19, 17, 14, 11, 8, 4, 1, + 17, 15, 13, 10, 6, 3, 0, -4, 13, 11, 8, 5, 1, -2, -5, -9, + 9, 6, 3, -1, -4, -7,-11,-13, 4, 0, -3, -6, -9,-12,-15,-17, + -2, -5, -8,-11,-14,-16,-18,-20, -8,-10,-13,-16,-17,-19,-21,-22, + 17, 18, 18, 18, 17, 16, 16, 14, 16, 16, 15, 15, 14, 13, 12, 11, + 12, 12, 11, 10, 9, 8, 7, 5, 7, 6, 6, 4, 3, 2, 1, -1, + 1, 0, -1, -2, -3, -4, -5, -6, -5, -6, -7, -8, -9,-10,-11,-12, + -11,-12,-13,-14,-15,-16,-16,-17,-16,-17,-17,-18,-19,-20,-20,-20, + 0, 0, 0, 0, -1, -1, -2, -3, 1, 0, 0, 0, 0, -1, -2, -3, + 1, 1, 0, 0, -1, -1, -2, -2, 1, 1, 1, 0, 0, -1, -1, -2, + 2, 1, 1, 1, 0, -1, -1, -2, 2, 2, 1, 1, 0, 0, -1, -2, + 2, 2, 1, 1, 1, 0, -1, -1, 2, 2, 1, 1, 1, 0, 0, -2, + 0, -1, -1, 0, 0, 1, 2, 3, 0, -1, -1, 0, 1, 1, 2, 2, + -1, -1, -1, -1, 0, 1, 2, 2, -1, -1, -2, -1, 0, 1, 1, 2, + -1, -2, -2, -1, 0, 0, 1, 2, -1, -2, -2, -2, -1, 0, 1, 2, + -1, -1, -2, -1, 0, 0, 1, 2, -1, -1, -1, -1, 0, 1, 1, 2, + 3, 2, 2, 2, 1, 1, 0, 0, 3, 2, 2, 2, 2, 1, 0, 0, + 2, 2, 2, 1, 1, 1, 0, 0, 2, 2, 1, 1, 1, 0, 0, -1, + 1, 1, 1, 0, 0, 0, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -2, -2, -2, -2, + 5, 2, 0, 0, -1, 0, 0, 0, 4, 2, 0, -1, -1, -1, 0, -1, + 4, 1, -1, -1, -2, -1, -1, -1, 4, 1, -1, -1, -2, -1, -1, -1, + 4, 1, -1, -2, -2, -1, -1, -1, 4, 1, -1, -2, -2, -1, -1, -1, + 4, 1, -1, -1, -1, -1, -1, -1, 4, 2, 0, -1, 0, 0, 0, -1, + -2, -1, 0, 1, 1, 1, 1, 1, -3, -1, 0, 1, 1, 1, 1, 1, + -3, -1, 0, 1, 1, 1, 1, 1, -3, -1, 0, 1, 1, 1, 1, 1, + -3, -2, 0, 1, 2, 2, 1, 1, -4, -2, 0, 1, 2, 2, 2, 2, + -5, -3, -1, 1, 1, 2, 1, 2, -5, -3, -2, 0, 1, 1, 1, 1, + 3, 3, 1, 0, -2, -4, -4, -5, 3, 3, 2, 0, -1, -2, -3, -4, + 2, 2, 1, 1, 0, -1, -2, -2, 1, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, -2, -1, -1, 0, 0, 1, 2, 2, + -3, -2, -2, -1, 0, 1, 2, 3, -3, -3, -2, -1, 0, 1, 2, 3, + -3, -3, -3, -3, -3, -2, -2, -2, -3, -3, -2, -2, -2, -1, -1, -1, + -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 2, 2, 2, 2, + 1, 1, 1, 2, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + -8, -7, -5, -3, -2, -1, 0, -1, -4, -3, -1, 0, 1, 2, 1, 1, + -1, 1, 2, 3, 3, 2, 2, 1, 1, 2, 3, 3, 2, 2, 1, 0, + 2, 3, 3, 2, 1, 0, 0, -1, 1, 2, 1, 0, -1, -1, -1, -1, + 1, 1, 0, -1, -1, -2, -2, -1, 1, 1, 0, 0, -1, -1, 0, -1, + -4, -3, -2, 0, 1, 2, 3, 3, -4, -3, -2, 0, 1, 2, 2, 2, + -3, -3, -2, -1, 0, 1, 1, 1, -2, -2, -2, -1, -1, 0, 0, 0, + 0, -1, -1, -1, -1, -1, -1, -1, 2, 1, 1, 0, 0, -1, -1, -2, + 3, 3, 3, 1, 0, -1, -2, -2, 5, 4, 4, 2, 1, 0, -1, -2, + 0, 0, 0, 0, 1, 2, 3, 3, 0, -1, 0, 0, 1, 2, 3, 3, + 0, -1, 0, 0, 1, 2, 3, 2, 0, 0, 0, 1, 1, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 1, 0, 0, -1, -2, + 2, 1, 0, 0, -2, -3, -5, -6, 0, -1, -1, -3, -5, -6, -8, -9, + -2, 0, 1, 2, 2, 1, -1, -4, -2, 0, 2, 2, 2, 1, -1, -4, + -2, 0, 2, 2, 2, 1, -1, -3, -2, 0, 2, 2, 2, 1, -1, -3, + -2, -1, 2, 2, 2, 1, -1, -3, -2, -1, 1, 2, 2, 1, -1, -3, + -3, -1, 1, 2, 2, 1, -1, -3, -2, -1, 1, 2, 2, 1, -1, -3, + -1, 1, 1, -1, -3, -3, 0, 4, -1, 1, 1, -1, -3, -3, 0, 4, + -1, 1, 1, 0, -3, -3, 0, 4, -1, 1, 2, 0, -3, -3, 0, 5, + 0, 1, 2, 0, -3, -4, 0, 4, 0, 1, 2, 0, -3, -4, 0, 5, + 0, 1, 2, 0, -3, -3, 0, 4, 0, 1, 2, -1, -2, -2, 0, 4, + 6, 6, 5, 6, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1, 0, 0, 0, 0, 0, + -1, -2, -2, -2, -2, -2, -2, -1, -3, -3, -3, -3, -3, -3, -3, -2, + -3, -4, -4, -3, -3, -3, -2, -2, -2, -2, -2, -2, -1, -1, 0, 0, + 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, + 4, 1, -2, -3, -3, -1, 1, 3, 4, 1, -2, -4, -3, -1, 1, 3, + 5, 1, -2, -4, -3, -1, 1, 4, 5, 1, -2, -3, -3, -1, 2, 4, + 5, 1, -2, -3, -3, -1, 2, 4, 4, 0, -3, -4, -3, -1, 2, 4, + 4, 0, -3, -3, -3, -1, 1, 3, 3, 0, -2, -3, -2, -1, 1, 3, + -3, -4, -4, -4, -4, -4, -4, -4, -1, -1, -1, -1, -1, -1, -2, -2, + 2, 1, 1, 2, 2, 1, 1, 1, 3, 3, 3, 4, 4, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 3, 3, 1, 2, 1, 2, 2, 2, 2, 2, + -2, -2, -2, -1, -1, -1, 0, 0, -4, -4, -4, -4, -3, -3, -3, -3, + -1, -2, -3, -3, -2, -2, -1, 0, 0, -1, -2, -2, -2, -1, 0, 1, + 2, 1, -1, -1, -1, -1, 0, 1, 3, 1, 0, -1, -1, 0, 0, 1, + 3, 2, 0, -1, 0, 0, 0, 1, 3, 1, 0, -1, 0, 0, 0, 1, + 3, 1, 0, -1, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 1, 1, 2, 3, 4, 0, 0, -1, 0, 0, 0, 2, 3, + 0, -1, -1, -1, -1, -1, 0, 1, 0, -1, -1, -1, -1, -1, -1, 0, + 0, 0, -1, -1, -1, -2, -2, -1, 1, 0, 0, -1, -1, -2, -2, -1, + 2, 2, 1, 0, -1, -1, -1, -1, 3, 3, 2, 1, 0, -1, -1, 0, + 1, 0, 1, 0, 0, -1, -2, -1, 0, 0, 0, 0, -1, -1, -2, -1, + 0, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, + -1, -1, -1, 0, 0, 0, 1, 1, -1, -1, -1, 0, 1, 1, 2, 3, + -2, -2, -1, 0, 1, 2, 3, 4, -2, -2, -1, 0, 1, 2, 4, 5, + -3, -1, 1, 0, 0, -1, 0, 1, -3, 0, 1, 0, -1, -1, 0, 2, + -3, 0, 1, 0, -1, -1, 0, 2, -2, 1, 2, 0, -1, -1, 0, 2, + -2, 1, 2, 0, -1, -1, 0, 2, -2, 1, 2, 0, -1, -1, 0, 2, + -1, 2, 2, 0, -1, -1, 0, 2, -1, 1, 1, 0, -1, -1, -1, 1, + -2, -2, -1, 1, 3, 4, 3, 1, -2, -2, -1, 0, 2, 3, 2, 0, + -2, -2, -1, 0, 1, 2, 1, -1, -1, -1, -1, 0, 1, 2, 1, -1, + -1, -1, -1, 0, 1, 1, 0, -2, 0, -1, -1, 0, 1, 1, 0, -1, + 0, -1, -1, 0, 1, 1, 1, -1, 0, -1, -1, 0, 0, 1, 0, -1, + -2, -1, 0, 1, 1, 1, 1, 1, -2, -1, 0, 0, 0, 0, 0, 0, + -2, -1, -1, 0, -1, -1, -2, -2, -2, -1, -1, -1, -1, -2, -2, -3, + -1, 0, 1, 1, 0, -1, -2, -2, 1, 2, 3, 3, 2, 1, 0, 0, + 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, + 0, -1, -1, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, 0, 0, 1, 1, 0, 0, 0, + -3, -2, -1, -1, -1, -1, 0, -1, -5, -5, -4, -3, -2, -2, -2, -1, + 1, 1, 1, 1, 2, 1, 0, -1, 1, 1, 1, 2, 1, 1, 0, -1, + 1, 1, 1, 1, 1, 1, 0, -2, 2, 1, 1, 1, 1, 1, 0, -2, + 1, 1, 0, 0, 0, 0, -1, -3, 1, 1, 0, 0, 0, -1, -2, -3, + 1, 1, 0, 0, -1, -1, -2, -4, 1, 0, 0, -1, -2, -2, -3, -4, + 8, 7, 5, 3, 2, 1, 1, 1, 2, 1, 0, 0, -1, -1, -2, -1, + -1, -1, -1, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, -1, -1, 0, + 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + -1, 0, 0, 0, 0, 0, -1, -1, -2, -2, -1, -1, -1, -2, -2, -1, + 9, 4, 0, -2, -2, -2, -1, -1, 7, 2, -1, -2, -2, -1, 0, 0, + 4, 0, -2, -2, -1, 0, 1, 1, 1, -2, -2, -2, -1, 0, 1, 1, + -1, -2, -2, -1, 0, 1, 1, 1, -1, -2, -1, 0, 1, 1, 1, 0, + -1, -1, 0, 1, 1, 1, 0, -1, 0, -1, 0, 1, 0, 0, -1, -1, + 0, 1, 1, 1, 1, 1, 0, 0, 1, 2, 2, 2, 1, 0, 0, 0, + 2, 2, 2, 2, 1, 0, -1, -1, 1, 1, 1, 0, -1, -2, -2, -2, + 0, 0, 0, -1, -2, -3, -2, -2, -1, -1, -1, -2, -2, -2, -1, 0, + -1, -1, -1, -1, 0, 0, 1, 2, -1, -1, -1, 0, 1, 2, 3, 4, + -1, -1, 0, 0, -1, -2, -3, -3, -1, -1, 0, 0, 0, -1, -1, -1, + -2, -2, -1, 0, 1, 1, 1, 1, -2, -2, -2, 0, 1, 2, 3, 3, + -1, -1, -1, 0, 1, 3, 3, 3, 1, 0, 0, 0, 1, 1, 2, 2, + 2, 2, 1, 0, 0, -1, -1, -1, 3, 2, 1, 0, -1, -2, -3, -3, + -1, -1, -1, -2, -2, -3, -4, -5, 0, 0, 0, -1, -1, -3, -3, -4, + 1, 1, 1, 0, 0, -1, -2, -3, 2, 2, 2, 1, 1, 0, -1, -1, + 2, 2, 2, 2, 1, 1, 0, -1, 2, 2, 2, 2, 2, 1, 0, 0, + 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, -1, + -2, 2, 3, 1, -1, 1, 1, -1, -3, 2, 3, 0, -1, 1, 1, -1, + -3, 2, 3, 0, -1, 1, 1, -1, -4, 2, 3, 0, -1, 1, 1, -2, + -4, 1, 3, 0, -1, 1, 1, -2, -4, 1, 3, -1, -2, 1, 1, -2, + -3, 1, 2, 0, -1, 1, 1, -2, -3, 1, 2, 0, -1, 1, 1, -1, + -1, -1, -1, -2, -2, -2, -2, -2, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 2, 2, 2, + -2, -2, -1, -1, -1, 0, 0, 0, -3, -3, -3, -3, -3, -3, -3, -2, + -1, -1, -1, -1, -2, -2, -2, -2, 4, 4, 4, 4, 4, 3, 3, 2, + -3, -3, -2, -1, 0, 1, 2, 5, -3, -3, -3, -2, -1, 1, 3, 6, + -3, -3, -2, -2, 0, 2, 3, 5, -3, -2, -2, -2, 0, 1, 3, 5, + -2, -2, -2, -1, -1, 1, 3, 5, -2, -2, -1, -1, 0, 1, 2, 4, + -1, -1, -1, -1, 0, 1, 1, 4, -1, -1, -1, -1, 0, 1, 2, 3, + 0, -1, 0, 1, 1, 0, -1, -1, 0, 0, 0, 1, 2, 0, -1, -1, + 1, 0, -1, 0, 1, 0, 0, 0, 1, -1, -2, -1, 0, 0, 0, 0, + 1, -2, -3, -1, 0, 0, 0, 1, 1, -1, -3, -2, 0, 1, 1, 2, + 1, -1, -2, -1, 0, 1, 1, 2, 2, 0, -1, 0, 1, 1, 2, 2, + 1, 1, 1, 1, 0, 0, 1, 2, -1, 0, 0, -1, 0, 0, 0, 1, + -3, -2, -1, -1, -1, 0, 1, 1, -4, -2, -1, 0, 0, 1, 1, 1, + -3, -2, 0, 0, 1, 1, 1, 1, -3, -1, 0, 1, 1, 1, 0, 0, + -1, 0, 1, 1, 1, 0, 0, -1, 0, 1, 2, 2, 1, 0, 0, -1, + -4, -4, -4, -3, -2, -1, -1, -1, -2, -2, -2, -1, 0, 0, 0, 0, + -1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 2, 2, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 0, -1, 0, 0, 1, 1, 1, 0, 0, + 1, 2, 2, 2, 1, -1, -2, -4, 1, 1, 2, 2, 1, 0, -2, -4, + 0, 1, 1, 1, 1, 0, -1, -3, -1, 0, 1, 1, 0, 0, -1, -2, + -1, 0, 1, 1, 1, 0, 0, -1, -2, -1, 0, 0, 0, 0, 0, -1, + -1, -1, 0, 1, 1, 0, 0, 0, -1, 0, 1, 1, 1, 1, 1, 0, + 2, 2, 0, -1, -2, -1, -1, -2, 1, 1, -1, -2, -2, -1, -1, -2, + 1, 1, -1, -2, -2, 0, 0, -1, 1, 1, 0, -2, -1, 1, 1, 0, + 1, 1, 0, -1, -1, 1, 2, 1, 1, 1, 0, -1, -1, 1, 2, 1, + 1, 1, 0, -1, -1, 1, 1, 1, 1, 1, 0, -1, 0, 1, 1, 1, + 0, 0, -1, -2, -4, -4, -4, -4, 3, 3, 3, 2, 1, 0, 0, 0, + 3, 3, 3, 3, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, + -1, -1, 0, -1, -1, 1, 2, -1, 1, 1, 0, 0, 0, 2, 3, -1, + 1, 1, 0, -1, -1, 1, 3, -1, 1, 1, 0, -2, -2, 0, 1, -2, + 1, 0, 0, -2, -2, 0, 1, -3, 0, 0, 0, 0, -1, 1, 1, -3, + 0, 1, 1, 0, 1, 2, 1, -3, -1, 0, 1, 1, 1, 2, 1, -4, + -4, -3, 0, 1, 1, 1, 0, 0, -4, -2, 0, 1, 1, 1, 0, -1, + -3, -1, 1, 1, 1, 0, -1, -1, -1, 1, 1, 1, 1, 0, -1, 0, + 1, 2, 2, 1, 0, -1, 0, 0, 2, 2, 1, 0, -1, -1, 0, 1, + 2, 1, 0, -1, -2, -1, 0, 1, 2, 2, 0, -1, -2, -1, 1, 1, + 1, 1, 0, 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, + 1, 0, 0, -1, -1, -1, -1, -1, 2, 1, 0, 0, -1, -1, -1, -1, + 5, 3, 2, 1, 0, 0, 0, 0, 6, 5, 3, 2, 1, 0, 0, 0, + 4, 4, 3, 1, 0, 0, 0, 1, 3, 3, 2, 1, 0, 0, 0, 1, + 2, 2, 1, 0, -1, -1, 0, 1, 0, 0, 0, -1, -1, -1, 0, 1, + 0, 0, -1, -1, -2, -1, 0, 2, 0, -1, -1, -2, -2, -2, 0, 1, + 0, -1, -1, -2, -2, -2, -1, 0, 0, 0, -1, -2, -2, -2, -1, 0, + 0, 0, -1, -1, -1, 0, 2, 3, 0, -1, -2, -2, -1, -1, 1, 2, + 1, 0, -1, -1, -1, 0, 0, 0, 1, 1, 1, 0, 0, 0, -1, -1, + 1, 2, 1, 0, 0, -1, -1, -1, -1, 0, 0, 0, -1, -1, -1, -1, + -3, -2, -1, -1, 0, 1, 1, 2, -4, -3, -1, 1, 2, 3, 5, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, -1, 0, 0, 0, 1, -1, -1, -2, -2, -2, -1, -1, 0, + 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, + 1, 1, 1, 1, 2, 2, 1, 1, -4, -3, -4, -4, -4, -4, -3, -3, + -1, 0, 1, 2, 2, 3, 3, 3, -1, -1, -1, -1, 0, 0, 0, 0, + 0, 0, -1, -2, -2, -3, -3, -2, 3, 2, 1, 0, -1, -2, -2, -2, + 4, 3, 2, 1, 1, 0, 0, 0, 2, 2, 1, 1, 0, 1, 1, 1, + 0, -1, -1, -1, -1, 0, 0, 1, -2, -2, -2, -2, -2, -1, 0, 0, + 1, -1, 0, 2, 1, -2, -1, 1, 1, -1, 0, 2, 1, -2, -2, 1, + 1, -1, 0, 3, 2, -2, -1, 1, 0, -2, 0, 3, 2, -2, -2, 1, + 0, -2, 0, 3, 2, -2, -2, 1, 0, -2, 0, 3, 1, -2, -1, 1, + 0, -2, 0, 2, 1, -2, -2, 1, 0, -1, 0, 2, 1, -2, -1, 1, + 0, 1, 2, 2, 3, 3, 2, 2, 0, 1, 1, 2, 3, 3, 2, 1, + 0, 0, 1, 2, 2, 2, 2, 1, -1, 0, 0, 1, 1, 1, 1, 1, + -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -2, -2, -2, -2, -2, -1, + 0, 0, -1, -2, -1, 0, 3, 5, 0, 0, -1, -1, -1, 0, 2, 4, + 1, 1, 0, 0, -1, -1, 1, 2, 1, 2, 1, 1, 0, -1, -1, 0, + 0, 1, 2, 1, 0, -1, -2, -2, -1, 0, 1, 2, 1, 0, -3, -3, + -2, -1, 1, 2, 2, 0, -2, -4, -2, -1, 0, 2, 2, 1, -1, -3, + 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, + -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, -1, -1, 0, + 0, 0, 1, 1, 0, 0, 0, 1, 3, 3, 3, 4, 3, 3, 3, 3, + 5, 1, -2, -2, 0, 0, 0, -1, 4, -1, -3, -1, 0, 0, 0, -1, + 3, -1, -1, 0, 1, 1, 0, -1, 2, 0, 0, 1, 1, 1, 0, -2, + 1, 0, 0, 1, 1, 1, 0, -2, 0, -1, -1, -1, 0, 0, 0, -1, + 0, -1, -1, -1, -1, 0, 0, -1, 2, 1, 0, 0, 0, 1, 0, 0, + 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, + 1, -1, -1, 0, 0, 0, 0, 0, 2, 0, -1, -1, -1, -1, -1, 0, + 3, 1, -1, -1, -2, -2, -2, -1, 4, 2, 1, 0, -1, -2, -2, -1, + 2, 1, 0, 0, -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 1, 1, + 0, 1, 2, 2, 2, 1, -1, -3, 0, 0, 1, 1, 1, 0, -1, -2, + 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, -1, 0, 0, 1, 1, 0, + 0, 0, -1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 1, 1, 2, 1, -1, -3, 0, 0, 0, 1, 1, -1, -4, -5, + -2, -2, -2, -1, 0, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 0, -2, -3, 0, 0, 1, 1, 0, -1, -3, -4, + -1, -1, 0, 1, 0, 0, -2, -3, -1, -1, 0, 1, 1, 1, 0, -1, + 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 1, 2, 1, 2, 0, 0, 0, 0, -1, 1, + 0, 2, 0, -1, 1, 0, -1, 0, 0, 1, 0, 0, 2, 1, 0, 1, + 0, 1, -1, 0, 2, 2, 0, 1, -1, 0, -1, -1, 2, 1, 1, 2, + -2, -2, -3, -2, 0, 1, 1, 1, -2, -2, -3, -3, -1, -1, -1, 0, + -3, -1, 0, 1, 2, 1, 1, 0, -3, -1, 0, 1, 2, 1, 1, 1, + -2, 0, 0, 1, 1, 1, 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, + -2, 0, 0, 0, 0, -1, -1, 0, -2, 0, 0, 0, 0, 0, -1, -1, + -3, 0, 1, 1, 1, 1, 0, 1, -5, -2, 0, 1, 2, 2, 1, 2, + -2, -1, -1, 0, 0, 1, 2, 3, 0, 0, 1, 1, 0, 0, 1, 2, + 0, 0, 1, 0, -1, -1, 0, 1, -1, -1, -1, -1, -2, -2, -1, 0, + -2, -2, -2, -2, -2, -1, 0, 1, 0, 0, 0, -1, 0, 1, 2, 2, + 2, 1, 0, 0, 0, 1, 2, 2, 2, 1, 0, -1, -1, -1, 0, 0, + 0, 1, 1, 1, 1, 1, -1, -4, -1, -1, 0, 1, 1, 1, 0, -3, + -2, -1, 0, 0, 1, 2, 2, -2, -1, 0, 0, 0, 0, 2, 3, -1, + -1, 0, 0, 0, 0, 1, 2, 0, 0, 0, -1, -2, -1, 1, 1, 0, + 0, 0, -1, -2, -2, 0, 2, 1, 0, 0, -1, -2, -1, 1, 2, 2, + 1, 0, 0, 0, -2, -3, -2, -3, 0, 0, 1, 0, -2, -2, -1, -1, + 0, -1, 1, 1, -1, -1, 0, 0, 0, -1, 1, 1, -1, -1, 0, 0, + 0, 1, 2, 1, -1, -1, 0, 1, 1, 2, 3, 2, 0, 0, 1, 2, + -1, 0, 2, 1, 0, 0, 2, 3, -2, -1, 0, 0, -1, 0, 1, 2, + 1, 1, 0, -1, -2, -2, -1, 1, 1, 1, 1, -1, -2, -2, 0, 2, + 1, 1, 1, -1, -1, -1, 0, 2, 0, 0, 0, 0, 0, 0, 1, 2, + -1, -1, -1, 0, 0, 0, 1, 2, -1, -2, -1, 1, 1, 1, 0, 0, + -1, -2, -1, 1, 2, 2, 0, -1, -1, -2, -1, 2, 2, 2, 0, -1, + -1, -1, -1, -2, -1, -1, 0, 1, 0, 0, -1, -1, -1, 0, 1, 2, + 1, 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, + 1, 2, 1, 0, -1, -2, -2, -3, 2, 2, 1, 0, -2, -3, -4, -4, + -4, -2, 1, 1, 1, 1, 0, 0, -2, 0, 1, 0, 0, 0, 0, 0, + 0, 1, 1, -2, -2, -1, 0, 1, 2, 2, 1, -2, -2, -1, 1, 2, + 1, 2, 1, -2, -2, -1, 1, 2, -1, 1, 1, -1, -1, -1, 0, 1, + -2, 0, 1, 1, 0, -1, -1, 0, -2, 0, 2, 2, 1, -1, -1, 0, + 1, 1, 0, 0, 0, 1, 0, 0, -2, -3, -3, -2, -2, -1, 0, 0, + -3, -4, -3, -2, -1, 0, 0, 0, -1, -1, 0, 1, 2, 3, 2, 1, + 0, 1, 2, 3, 3, 3, 2, 1, 1, 1, 1, 2, 1, 0, 0, -1, + 0, 0, 0, 0, -1, -1, -1, -1, 0, -1, -1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, -1, -1, 0, 2, 0, 0, 1, 0, -1, -1, 1, 1, + -2, -1, 0, 1, 1, 1, 1, 1, -3, -3, 0, 2, 2, 1, 1, 0, + -2, -2, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, -1, -1, + 3, 1, -1, -3, -2, -1, 0, 1, 4, 2, -1, -3, -3, -1, 1, 2, + 0, 0, 0, -1, -1, -1, -1, -1, 1, 2, 1, 0, 0, 0, -1, -1, + 2, 3, 3, 2, 1, 0, -1, -1, 3, 4, 4, 2, 1, 0, -1, -2, + 3, 3, 2, 1, 0, -1, -2, -2, 1, 1, 0, -1, -1, -2, -2, -3, + 0, 0, 0, -1, -1, -2, -2, -2, -1, -1, -1, -1, -1, -2, -2, -1, + 1, 2, 2, 2, 2, 1, 2, 2, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 0, -1, -2, 0, 0, 0, 0, 1, 0, -1, -4, + 1, 0, 0, 0, 0, 0, -2, -5, 1, 0, 0, 0, 0, 0, -1, -4, + 1, 0, -1, 0, 0, 0, -1, -3, 0, -1, -1, 0, 1, 1, 1, -1, + -2, -1, 0, 0, -1, -1, -1, -2, -1, 0, 0, 0, -1, -1, -2, -2, + 0, 1, 1, 0, -1, -1, -1, -2, 0, 1, 1, 0, 0, 0, -1, -1, + 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 2, 2, 1, + 1, 1, 0, 0, 1, 2, 2, 1, 1, 1, 0, -1, 0, 1, 1, 0, + 4, 2, 1, 0, 0, 1, 1, 1, 4, 2, 1, 0, 0, 0, 0, 1, + 3, 1, 0, 0, -1, -1, -1, 0, 1, 0, 0, -1, -1, -2, -1, 0, + 0, 0, 0, 0, -1, -1, -1, 0, -1, -1, 0, 0, -1, -1, 0, 1, + -2, -1, 0, -1, -1, 0, 0, 1, -2, -2, -1, -2, -1, 0, 0, 1, + 0, 1, 1, 1, 2, 1, 0, -1, -1, -1, -1, 0, 0, -1, -2, -2, + -1, 0, -1, 0, 0, -1, -2, -1, 0, 0, 0, 0, 0, 0, 1, 2, + 0, 0, 0, 0, 0, 0, 2, 3, -1, 0, -1, -1, -1, -1, 0, 3, + -1, 0, 0, -1, -1, -2, 0, 3, 0, 0, 0, 0, -1, -1, 1, 4, + 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, -1, -2, -1, -2, -1, 1, + -1, -1, -2, -2, -2, -3, -2, 0, -1, 0, -1, -1, -1, -2, -1, 1, + 1, 1, 0, 0, 1, 0, 0, 1, 2, 2, 0, 0, 1, 0, 0, 1, + 2, 2, 0, 0, 0, 0, -1, -1, 2, 2, 0, 0, 1, 0, -1, -1, + -1, 0, 1, 1, 0, -1, -1, -1, 1, 2, 3, 2, 1, 0, 0, 0, + 0, 1, 1, 1, 0, -1, 0, 0, -2, -2, -1, 0, 1, 0, 0, 0, + -2, -2, -1, 2, 2, 2, 1, 0, -2, -1, 0, 1, 1, 0, 0, -1, + -1, -1, 0, 0, -1, -2, -1, -2, 0, 1, 1, 1, 0, 0, 1, 1, + -3, -3, -3, -2, -1, -1, -2, -2, -1, -1, 0, 1, 2, 1, 0, 0, + 1, 1, 1, 2, 2, 1, 0, 0, 1, 1, 1, 1, 1, 0, -1, 1, + 1, 0, -1, -1, 0, 0, -1, 1, 0, -1, -1, -1, 0, -1, -1, 1, + 1, 0, -1, 0, 0, -1, 0, 2, 2, 0, -1, 0, 0, 0, 0, 2, + 1, 0, -2, -1, 0, 1, 1, 0, 2, 0, -1, -1, 0, 1, 1, 0, + 1, 0, -2, -1, 0, 1, 0, -1, 1, 0, -1, -1, 0, 1, 0, -1, + 0, 1, 1, 0, 1, 1, 0, 0, -2, 1, 2, 1, 0, 0, 0, 1, + -5, 0, 2, 1, 0, -1, 0, 1, -6, -1, 2, 1, 0, -1, 0, 0, + 5, 3, 0, -1, -2, -1, -1, -1, 1, 1, 0, -1, -1, 0, -1, -1, + -1, 0, 1, 1, 2, 2, 1, 0, -2, -1, 0, 1, 2, 1, 1, 1, + -2, -1, -1, -1, 0, -1, 0, 1, 0, 1, 0, 0, -1, -1, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 0, -3, -2, 0, 1, 1, 0, 0, -1, + -1, 0, 1, 0, -1, 0, 2, 3, -1, 0, 0, -2, -4, -2, -1, 0, + 0, 1, 1, 0, -2, -1, 0, -1, 1, 2, 3, 1, 0, 1, 1, 0, + -1, 0, 1, 1, 1, 1, 1, 0, -2, -3, -2, 0, 0, 0, 1, 0, + -1, -2, -2, 0, 1, 0, 0, -1, 3, 1, 0, 0, 1, 0, -1, -1, + -2, -1, 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, 0, 1, 1, 1, + -1, -1, -1, 0, 1, 1, 1, 1, 0, -2, -3, -1, 1, 0, 0, 0, + 1, -1, -3, -1, 1, 1, 0, -1, 3, 1, -1, 1, 2, 2, 0, -1, + 3, 1, 0, 1, 2, 1, 1, 0, 0, -2, -2, -1, -1, 0, 0, 0, + 1, 0, -1, -1, 1, 2, 1, 0, 0, -1, -2, -1, 1, 2, 2, 1, + -1, -1, -1, 0, 0, 1, 2, 0, -2, 0, 0, 0, 0, 0, 1, -1, + -1, 0, 1, 0, -1, -1, -1, -1, 0, 1, 1, 2, 0, -2, -1, 0, + 1, 2, 2, 2, 1, -1, -1, 0, 0, 1, 1, 1, 0, -2, -2, -1, + 0, 0, -1, -1, -1, -1, -2, -2, 0, 0, -1, 0, 1, 2, 2, 1, + 0, 0, -1, -1, 0, 1, 2, 2, 1, 1, -1, -2, -1, -1, -1, -1, + 2, 2, 1, 0, 0, -1, -2, -2, 1, 2, 2, 1, 0, 0, -2, -2, + 0, 0, 0, 0, 1, 1, 0, -1, 0, -1, -1, -1, 2, 3, 2, 1, + 0, -2, 1, 2, -1, 0, 0, 1, -1, -2, 2, 3, -1, 0, 0, 0, + 0, -2, 2, 3, -1, -1, 0, 0, 0, -1, 3, 2, -2, 0, 1, 0, + 0, -1, 3, 1, -2, 0, 1, 0, 0, -1, 2, 1, -1, 1, 0, -1, + 0, 0, 1, -1, -2, 0, 0, -1, 1, 0, 0, -2, -2, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -2, 0, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 1, 1, 2, 3, 1, 0, 0, -1, 0, 0, 1, 2, + 0, -1, -1, -2, -1, 0, 1, 2, -2, -2, -2, -2, -1, 0, 1, 1, + -1, -1, -1, -1, 0, 0, 0, -1, 2, 2, 2, 0, -1, -1, -2, -4, + -1, -2, -1, -1, 0, 1, 2, 3, -1, -1, -1, -1, 0, 1, 2, 3, + 1, 0, -1, 0, -1, 0, 1, 2, 1, 0, 0, 0, -1, 0, 2, 2, + 1, 0, -1, -1, -2, 0, 1, 2, 0, -2, -2, -2, -3, -1, 0, 1, + 0, -2, -2, -2, -2, -1, 1, 1, 0, 0, 0, 0, 0, 1, 2, 2 +}; + +/* list of codebooks for intra-coded vectors */ +const int8_t* const ff_svq1_intra_codebooks[6] = { + svq1_intra_codebook_4x2, svq1_intra_codebook_4x4, + svq1_intra_codebook_8x4, svq1_intra_codebook_8x8, + NULL, NULL, +}; + +#endif /* AVCODEC_SVQ1_CB_H */ diff --git a/ffmpeg/libavcodec/svq1_vlc.h b/ffmpeg/libavcodec/svq1_vlc.h new file mode 100644 index 0000000..e56d894 --- /dev/null +++ b/ffmpeg/libavcodec/svq1_vlc.h @@ -0,0 +1,268 @@ +/* + * copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +#ifndef AVCODEC_SVQ1_VLC_H +#define AVCODEC_SVQ1_VLC_H + +#include + +/* values in this table range from 0..3; adjust retrieved value by +0 */ +const uint8_t ff_svq1_block_type_vlc[4][2] = { + /* { code, length } */ + { 0x1, 1 }, { 0x1, 2 }, { 0x1, 3 }, { 0x0, 3 } +}; + +/* values in this table range from -1..6; adjust retrieved value by -1 */ +const uint8_t ff_svq1_intra_multistage_vlc[6][8][2] = { + /* { code, length } */ + { { 0x1, 5 }, { 0x1, 1 }, { 0x3, 3 }, { 0x2, 3 }, + { 0x3, 4 }, { 0x2, 4 }, { 0x0, 5 }, { 0x1, 4 } }, + { { 0x1, 4 }, { 0x3, 2 }, { 0x5, 3 }, { 0x4, 3 }, + { 0x3, 3 }, { 0x2, 3 }, { 0x0, 4 }, { 0x1, 3 } }, + { { 0x1, 5 }, { 0x1, 1 }, { 0x3, 3 }, { 0x0, 5 }, + { 0x3, 4 }, { 0x2, 3 }, { 0x2, 4 }, { 0x1, 4 } }, + { { 0x1, 6 }, { 0x1, 1 }, { 0x1, 2 }, { 0x0, 6 }, + { 0x3, 4 }, { 0x2, 4 }, { 0x1, 5 }, { 0x1, 4 } }, + { { 0x1, 6 }, { 0x1, 1 }, { 0x1, 2 }, { 0x3, 5 }, + { 0x2, 5 }, { 0x0, 6 }, { 0x1, 5 }, { 0x1, 3 } }, + { { 0x1, 7 }, { 0x1, 1 }, { 0x1, 2 }, { 0x1, 3 }, + { 0x1, 4 }, { 0x1, 6 }, { 0x0, 7 }, { 0x1, 5 } } +}; + +/* values in this table range from -1..6; adjust retrieved value by -1 */ +const uint8_t ff_svq1_inter_multistage_vlc[6][8][2] = { + /* { code, length } */ + { { 0x3, 2 }, { 0x5, 3 }, { 0x4, 3 }, { 0x3, 3 }, + { 0x2, 3 }, { 0x1, 3 }, { 0x1, 4 }, { 0x0, 4 } }, + { { 0x3, 2 }, { 0x5, 3 }, { 0x4, 3 }, { 0x3, 3 }, + { 0x2, 3 }, { 0x1, 3 }, { 0x1, 4 }, { 0x0, 4 } }, + { { 0x1, 1 }, { 0x3, 3 }, { 0x2, 3 }, { 0x3, 4 }, + { 0x2, 4 }, { 0x1, 4 }, { 0x1, 5 }, { 0x0, 5 } }, + { { 0x1, 1 }, { 0x3, 3 }, { 0x2, 3 }, { 0x3, 4 }, + { 0x2, 4 }, { 0x1, 4 }, { 0x1, 5 }, { 0x0, 5 } }, + { { 0x1, 1 }, { 0x3, 3 }, { 0x2, 3 }, { 0x3, 4 }, + { 0x2, 4 }, { 0x1, 4 }, { 0x1, 5 }, { 0x0, 5 } }, + { { 0x1, 1 }, { 0x1, 2 }, { 0x1, 3 }, { 0x3, 5 }, + { 0x2, 5 }, { 0x1, 5 }, { 0x1, 6 }, { 0x0, 6 } } +}; + +/* values in this table range from 0..255; adjust retrieved value by +0 */ +const uint16_t ff_svq1_intra_mean_vlc[256][2] = { + /* { code, length } */ + { 0x37, 6 }, { 0x56, 7 }, { 0x01, 17 }, { 0x01, 20 }, + { 0x02, 20 }, { 0x03, 20 }, { 0x00, 20 }, { 0x04, 20 }, + { 0x05, 20 }, { 0x03, 19 }, { 0x15, 11 }, { 0x42, 9 }, + { 0x14, 11 }, { 0x03, 14 }, { 0x02, 14 }, { 0x01, 15 }, + { 0x01, 16 }, { 0x01, 12 }, { 0x2B, 10 }, { 0x18, 11 }, + { 0x0C, 11 }, { 0x41, 9 }, { 0x78, 8 }, { 0x6C, 8 }, + { 0x55, 7 }, { 0x0F, 4 }, { 0x0E, 4 }, { 0x34, 6 }, + { 0x51, 7 }, { 0x72, 8 }, { 0x6E, 8 }, { 0x40, 9 }, + { 0x3F, 9 }, { 0x3E, 9 }, { 0x3D, 9 }, { 0x3C, 9 }, + { 0x3B, 9 }, { 0x3A, 9 }, { 0x39, 9 }, { 0x38, 9 }, + { 0x37, 9 }, { 0x43, 9 }, { 0x46, 9 }, { 0x47, 9 }, + { 0x45, 9 }, { 0x44, 9 }, { 0x49, 9 }, { 0x48, 9 }, + { 0x4A, 8 }, { 0x79, 8 }, { 0x76, 8 }, { 0x77, 8 }, + { 0x71, 8 }, { 0x75, 8 }, { 0x74, 8 }, { 0x73, 8 }, + { 0x6A, 8 }, { 0x55, 8 }, { 0x70, 8 }, { 0x6F, 8 }, + { 0x52, 8 }, { 0x6D, 8 }, { 0x4C, 8 }, { 0x6B, 8 }, + { 0x40, 7 }, { 0x69, 8 }, { 0x68, 8 }, { 0x67, 8 }, + { 0x66, 8 }, { 0x65, 8 }, { 0x64, 8 }, { 0x63, 8 }, + { 0x62, 8 }, { 0x61, 8 }, { 0x60, 8 }, { 0x5F, 8 }, + { 0x5E, 8 }, { 0x5D, 8 }, { 0x5C, 8 }, { 0x5B, 8 }, + { 0x5A, 8 }, { 0x59, 8 }, { 0x58, 8 }, { 0x57, 8 }, + { 0x56, 8 }, { 0x3D, 7 }, { 0x54, 8 }, { 0x53, 8 }, + { 0x3F, 7 }, { 0x51, 8 }, { 0x50, 8 }, { 0x4F, 8 }, + { 0x4E, 8 }, { 0x4D, 8 }, { 0x41, 7 }, { 0x4B, 8 }, + { 0x53, 7 }, { 0x3E, 7 }, { 0x48, 8 }, { 0x4F, 7 }, + { 0x52, 7 }, { 0x45, 8 }, { 0x50, 7 }, { 0x43, 8 }, + { 0x42, 8 }, { 0x41, 8 }, { 0x42, 7 }, { 0x43, 7 }, + { 0x3E, 8 }, { 0x44, 7 }, { 0x3C, 8 }, { 0x45, 7 }, + { 0x46, 7 }, { 0x47, 7 }, { 0x48, 7 }, { 0x49, 7 }, + { 0x4A, 7 }, { 0x4B, 7 }, { 0x4C, 7 }, { 0x4D, 7 }, + { 0x4E, 7 }, { 0x58, 7 }, { 0x59, 7 }, { 0x5A, 7 }, + { 0x5B, 7 }, { 0x5C, 7 }, { 0x5D, 7 }, { 0x44, 8 }, + { 0x49, 8 }, { 0x29, 8 }, { 0x3F, 8 }, { 0x3D, 8 }, + { 0x3B, 8 }, { 0x2C, 8 }, { 0x28, 8 }, { 0x25, 8 }, + { 0x26, 8 }, { 0x5E, 7 }, { 0x57, 7 }, { 0x54, 7 }, + { 0x5F, 7 }, { 0x62, 7 }, { 0x63, 7 }, { 0x64, 7 }, + { 0x61, 7 }, { 0x65, 7 }, { 0x67, 7 }, { 0x66, 7 }, + { 0x35, 6 }, { 0x36, 6 }, { 0x60, 7 }, { 0x39, 8 }, + { 0x3A, 8 }, { 0x38, 8 }, { 0x37, 8 }, { 0x36, 8 }, + { 0x35, 8 }, { 0x34, 8 }, { 0x33, 8 }, { 0x32, 8 }, + { 0x31, 8 }, { 0x30, 8 }, { 0x2D, 8 }, { 0x2B, 8 }, + { 0x2A, 8 }, { 0x27, 8 }, { 0x40, 8 }, { 0x46, 8 }, + { 0x47, 8 }, { 0x26, 9 }, { 0x25, 9 }, { 0x24, 9 }, + { 0x23, 9 }, { 0x22, 9 }, { 0x2E, 8 }, { 0x2F, 8 }, + { 0x1F, 9 }, { 0x36, 9 }, { 0x1D, 9 }, { 0x21, 9 }, + { 0x1B, 9 }, { 0x1C, 9 }, { 0x19, 9 }, { 0x1A, 9 }, + { 0x18, 9 }, { 0x17, 9 }, { 0x16, 9 }, { 0x1E, 9 }, + { 0x20, 9 }, { 0x27, 9 }, { 0x28, 9 }, { 0x29, 9 }, + { 0x2A, 9 }, { 0x2B, 9 }, { 0x2C, 9 }, { 0x2D, 9 }, + { 0x2E, 9 }, { 0x2F, 9 }, { 0x30, 9 }, { 0x35, 9 }, + { 0x31, 9 }, { 0x32, 9 }, { 0x33, 9 }, { 0x34, 9 }, + { 0x19, 10 }, { 0x2A, 10 }, { 0x17, 10 }, { 0x16, 10 }, + { 0x15, 10 }, { 0x28, 10 }, { 0x26, 10 }, { 0x25, 10 }, + { 0x22, 10 }, { 0x21, 10 }, { 0x18, 10 }, { 0x14, 10 }, + { 0x29, 10 }, { 0x12, 10 }, { 0x0D, 10 }, { 0x0E, 10 }, + { 0x0F, 10 }, { 0x10, 10 }, { 0x11, 10 }, { 0x1A, 10 }, + { 0x1B, 10 }, { 0x1C, 10 }, { 0x1D, 10 }, { 0x1E, 10 }, + { 0x1F, 10 }, { 0x20, 10 }, { 0x13, 10 }, { 0x23, 10 }, + { 0x24, 10 }, { 0x09, 11 }, { 0x08, 11 }, { 0x07, 11 }, + { 0x27, 10 }, { 0x05, 11 }, { 0x0B, 11 }, { 0x06, 11 }, + { 0x04, 11 }, { 0x03, 11 }, { 0x02, 11 }, { 0x01, 11 }, + { 0x0A, 11 }, { 0x16, 11 }, { 0x19, 11 }, { 0x17, 11 }, + { 0x0D, 11 }, { 0x0E, 11 }, { 0x0F, 11 }, { 0x10, 11 }, + { 0x11, 11 }, { 0x12, 11 }, { 0x13, 11 }, { 0x01, 14 } +}; + +/* values in this table range from -256..255; adjust retrieved value by -256 */ +const uint16_t ff_svq1_inter_mean_vlc[512][2] = { + /* { code, length } */ + { 0x5A, 22 }, { 0xD4, 22 }, { 0xD5, 22 }, { 0xD6, 22 }, + { 0xD7, 22 }, { 0xD8, 22 }, { 0xD9, 22 }, { 0xDA, 22 }, + { 0xDB, 22 }, { 0xDC, 22 }, { 0xDD, 22 }, { 0xDE, 22 }, + { 0xDF, 22 }, { 0xE0, 22 }, { 0xE1, 22 }, { 0xE2, 22 }, + { 0xE3, 22 }, { 0xE4, 22 }, { 0xE5, 22 }, { 0xE6, 22 }, + { 0xE8, 22 }, { 0xCB, 22 }, { 0xE9, 22 }, { 0xEA, 22 }, + { 0xE7, 22 }, { 0xEC, 22 }, { 0xED, 22 }, { 0xEE, 22 }, + { 0xEF, 22 }, { 0xF0, 22 }, { 0xF1, 22 }, { 0xF2, 22 }, + { 0xF3, 22 }, { 0xF4, 22 }, { 0xF5, 22 }, { 0xF6, 22 }, + { 0xF7, 22 }, { 0xF8, 22 }, { 0x102,22 }, { 0xEB, 22 }, + { 0xF9, 22 }, { 0xFC, 22 }, { 0xFD, 22 }, { 0xFE, 22 }, + { 0x100,22 }, { 0x5C, 22 }, { 0x60, 22 }, { 0x101,22 }, + { 0x71, 22 }, { 0x104,22 }, { 0x105,22 }, { 0xFB, 22 }, + { 0xFF, 22 }, { 0x86, 21 }, { 0xFA, 22 }, { 0x7C, 22 }, + { 0x75, 22 }, { 0x103,22 }, { 0x78, 22 }, { 0xD3, 22 }, + { 0x7B, 22 }, { 0x82, 22 }, { 0xD2, 22 }, { 0xD1, 22 }, + { 0xD0, 22 }, { 0xCF, 22 }, { 0xCE, 22 }, { 0xCD, 22 }, + { 0xCC, 22 }, { 0xC3, 22 }, { 0xCA, 22 }, { 0xC9, 22 }, + { 0xC8, 22 }, { 0xC7, 22 }, { 0xC6, 22 }, { 0xC5, 22 }, + { 0x8B, 22 }, { 0xC4, 22 }, { 0xC2, 22 }, { 0xC1, 22 }, + { 0xC0, 22 }, { 0xBF, 22 }, { 0xBE, 22 }, { 0xBD, 22 }, + { 0xBC, 22 }, { 0xBB, 22 }, { 0xBA, 22 }, { 0xB9, 22 }, + { 0x61, 22 }, { 0x84, 22 }, { 0x85, 22 }, { 0x86, 22 }, + { 0x87, 22 }, { 0x88, 22 }, { 0x89, 22 }, { 0x8A, 22 }, + { 0x8C, 22 }, { 0x8D, 22 }, { 0x8E, 22 }, { 0x8F, 22 }, + { 0x90, 22 }, { 0x91, 22 }, { 0x92, 22 }, { 0x93, 22 }, + { 0x94, 22 }, { 0x95, 22 }, { 0x96, 22 }, { 0x97, 22 }, + { 0x98, 22 }, { 0x99, 22 }, { 0x9A, 22 }, { 0x9B, 22 }, + { 0x9C, 22 }, { 0x9D, 22 }, { 0x9E, 22 }, { 0x9F, 22 }, + { 0xA0, 22 }, { 0xA1, 22 }, { 0xA2, 22 }, { 0xA3, 22 }, + { 0xA4, 22 }, { 0xA5, 22 }, { 0xA6, 22 }, { 0xA7, 22 }, + { 0xA8, 22 }, { 0xA9, 22 }, { 0xAA, 22 }, { 0xAB, 22 }, + { 0x7F, 22 }, { 0x8F, 21 }, { 0xAC, 22 }, { 0xAD, 22 }, + { 0xAE, 22 }, { 0xAF, 22 }, { 0xB0, 22 }, { 0xB1, 22 }, + { 0x53, 20 }, { 0x90, 21 }, { 0xB2, 22 }, { 0x91, 21 }, + { 0xB3, 22 }, { 0xB4, 22 }, { 0x54, 20 }, { 0xB5, 22 }, + { 0xB6, 22 }, { 0x8C, 21 }, { 0x34, 19 }, { 0x3D, 18 }, + { 0x55, 20 }, { 0xB7, 22 }, { 0xB8, 22 }, { 0x8B, 21 }, + { 0x56, 20 }, { 0x3D, 19 }, { 0x57, 20 }, { 0x58, 20 }, + { 0x40, 19 }, { 0x43, 19 }, { 0x47, 19 }, { 0x2A, 18 }, + { 0x2E, 19 }, { 0x2C, 18 }, { 0x46, 19 }, { 0x59, 20 }, + { 0x49, 19 }, { 0x2D, 19 }, { 0x38, 18 }, { 0x36, 18 }, + { 0x39, 18 }, { 0x45, 19 }, { 0x28, 18 }, { 0x30, 18 }, + { 0x35, 18 }, { 0x20, 17 }, { 0x44, 19 }, { 0x32, 18 }, + { 0x31, 18 }, { 0x1F, 17 }, { 0x2F, 18 }, { 0x2E, 18 }, + { 0x2D, 18 }, { 0x21, 17 }, { 0x22, 17 }, { 0x23, 17 }, + { 0x24, 17 }, { 0x27, 16 }, { 0x23, 16 }, { 0x20, 16 }, + { 0x1D, 16 }, { 0x25, 16 }, { 0x1E, 16 }, { 0x24, 16 }, + { 0x2A, 16 }, { 0x26, 16 }, { 0x21, 15 }, { 0x29, 16 }, + { 0x22, 15 }, { 0x23, 15 }, { 0x24, 15 }, { 0x1B, 15 }, + { 0x1A, 15 }, { 0x1D, 15 }, { 0x1F, 15 }, { 0x27, 15 }, + { 0x17, 14 }, { 0x18, 14 }, { 0x19, 14 }, { 0x1B, 14 }, + { 0x1C, 14 }, { 0x1E, 14 }, { 0x25, 14 }, { 0x20, 14 }, + { 0x21, 14 }, { 0x13, 13 }, { 0x14, 13 }, { 0x15, 13 }, + { 0x16, 13 }, { 0x17, 13 }, { 0x18, 13 }, { 0x19, 13 }, + { 0x1A, 13 }, { 0x18, 12 }, { 0x17, 12 }, { 0x15, 12 }, + { 0x14, 12 }, { 0x13, 12 }, { 0x12, 12 }, { 0x0F, 11 }, + { 0x10, 11 }, { 0x12, 11 }, { 0x13, 11 }, { 0x1B, 11 }, + { 0x1A, 11 }, { 0x0E, 10 }, { 0x13, 10 }, { 0x0F, 10 }, + { 0x10, 10 }, { 0x11, 10 }, { 0x12, 10 }, { 0x0D, 9 }, + { 0x14, 9 }, { 0x15, 9 }, { 0x0C, 9 }, { 0x13, 9 }, + { 0x0F, 8 }, { 0x0E, 8 }, { 0x10, 8 }, { 0x11, 8 }, + { 0x0C, 7 }, { 0x09, 7 }, { 0x0A, 7 }, { 0x08, 6 }, + { 0x09, 6 }, { 0x09, 5 }, { 0x08, 5 }, { 0x05, 4 }, + { 0x01, 1 }, { 0x03, 3 }, { 0x07, 5 }, { 0x06, 5 }, + { 0x0B, 6 }, { 0x0A, 6 }, { 0x0E, 7 }, { 0x0F, 7 }, + { 0x0B, 7 }, { 0x0D, 7 }, { 0x0B, 8 }, { 0x0D, 8 }, + { 0x0C, 8 }, { 0x0F, 9 }, { 0x10, 9 }, { 0x11, 9 }, + { 0x0E, 9 }, { 0x12, 9 }, { 0x17, 10 }, { 0x14, 10 }, + { 0x16, 10 }, { 0x15, 10 }, { 0x19, 11 }, { 0x18, 11 }, + { 0x17, 11 }, { 0x16, 11 }, { 0x15, 11 }, { 0x14, 11 }, + { 0x11, 11 }, { 0x19, 12 }, { 0x1A, 12 }, { 0x16, 12 }, + { 0x1D, 12 }, { 0x1B, 12 }, { 0x1C, 12 }, { 0x20, 13 }, + { 0x1C, 13 }, { 0x23, 13 }, { 0x22, 13 }, { 0x21, 13 }, + { 0x1F, 13 }, { 0x1E, 13 }, { 0x1B, 13 }, { 0x1D, 13 }, + { 0x24, 14 }, { 0x16, 14 }, { 0x1A, 14 }, { 0x22, 14 }, + { 0x1D, 14 }, { 0x1F, 14 }, { 0x15, 14 }, { 0x23, 14 }, + { 0x18, 15 }, { 0x20, 15 }, { 0x29, 15 }, { 0x28, 15 }, + { 0x26, 15 }, { 0x25, 15 }, { 0x19, 15 }, { 0x1C, 15 }, + { 0x1E, 15 }, { 0x17, 15 }, { 0x2C, 16 }, { 0x2B, 16 }, + { 0x1C, 16 }, { 0x21, 16 }, { 0x2D, 16 }, { 0x28, 16 }, + { 0x1F, 16 }, { 0x1B, 16 }, { 0x1A, 16 }, { 0x22, 16 }, + { 0x2D, 17 }, { 0x32, 17 }, { 0x2C, 17 }, { 0x27, 17 }, + { 0x31, 17 }, { 0x33, 17 }, { 0x2F, 17 }, { 0x2B, 17 }, + { 0x37, 18 }, { 0x2A, 17 }, { 0x2E, 17 }, { 0x30, 17 }, + { 0x29, 17 }, { 0x28, 17 }, { 0x26, 17 }, { 0x25, 17 }, + { 0x2F, 19 }, { 0x33, 18 }, { 0x34, 18 }, { 0x30, 19 }, + { 0x3A, 18 }, { 0x3B, 18 }, { 0x31, 19 }, { 0x3C, 18 }, + { 0x2B, 18 }, { 0x29, 18 }, { 0x48, 19 }, { 0x27, 18 }, + { 0x42, 19 }, { 0x41, 19 }, { 0x26, 18 }, { 0x52, 20 }, + { 0x51, 20 }, { 0x3F, 19 }, { 0x3E, 19 }, { 0x39, 19 }, + { 0x3C, 19 }, { 0x3B, 19 }, { 0x3A, 19 }, { 0x25, 18 }, + { 0x38, 19 }, { 0x50, 20 }, { 0x37, 19 }, { 0x36, 19 }, + { 0x87, 21 }, { 0x4F, 20 }, { 0x35, 19 }, { 0x4E, 20 }, + { 0x33, 19 }, { 0x32, 19 }, { 0x4D, 20 }, { 0x4C, 20 }, + { 0x83, 22 }, { 0x4B, 20 }, { 0x81, 22 }, { 0x80, 22 }, + { 0x8E, 21 }, { 0x7E, 22 }, { 0x7D, 22 }, { 0x84, 21 }, + { 0x8D, 21 }, { 0x7A, 22 }, { 0x79, 22 }, { 0x4A, 20 }, + { 0x77, 22 }, { 0x76, 22 }, { 0x89, 21 }, { 0x74, 22 }, + { 0x73, 22 }, { 0x72, 22 }, { 0x49, 20 }, { 0x70, 22 }, + { 0x6F, 22 }, { 0x6E, 22 }, { 0x6D, 22 }, { 0x6C, 22 }, + { 0x6B, 22 }, { 0x6A, 22 }, { 0x69, 22 }, { 0x68, 22 }, + { 0x67, 22 }, { 0x66, 22 }, { 0x65, 22 }, { 0x64, 22 }, + { 0x63, 22 }, { 0x62, 22 }, { 0x8A, 21 }, { 0x88, 21 }, + { 0x5F, 22 }, { 0x5E, 22 }, { 0x5D, 22 }, { 0x85, 21 }, + { 0x5B, 22 }, { 0x83, 21 }, { 0x59, 22 }, { 0x58, 22 }, + { 0x57, 22 }, { 0x56, 22 }, { 0x55, 22 }, { 0x54, 22 }, + { 0x53, 22 }, { 0x52, 22 }, { 0x51, 22 }, { 0x50, 22 }, + { 0x4F, 22 }, { 0x4E, 22 }, { 0x4D, 22 }, { 0x4C, 22 }, + { 0x4B, 22 }, { 0x4A, 22 }, { 0x49, 22 }, { 0x48, 22 }, + { 0x47, 22 }, { 0x46, 22 }, { 0x45, 22 }, { 0x44, 22 }, + { 0x43, 22 }, { 0x42, 22 }, { 0x41, 22 }, { 0x40, 22 }, + { 0x3F, 22 }, { 0x3E, 22 }, { 0x3D, 22 }, { 0x3C, 22 }, + { 0x3B, 22 }, { 0x3A, 22 }, { 0x39, 22 }, { 0x38, 22 }, + { 0x37, 22 }, { 0x36, 22 }, { 0x35, 22 }, { 0x34, 22 }, + { 0x33, 22 }, { 0x32, 22 }, { 0x31, 22 }, { 0x30, 22 }, + { 0x2F, 22 }, { 0x2E, 22 }, { 0x2D, 22 }, { 0x2C, 22 }, + { 0x2B, 22 }, { 0x2A, 22 }, { 0x29, 22 }, { 0x28, 22 }, + { 0x27, 22 }, { 0x26, 22 }, { 0x25, 22 }, { 0x24, 22 }, + { 0x23, 22 }, { 0x22, 22 }, { 0x21, 22 }, { 0x20, 22 }, + { 0x1F, 22 }, { 0x1E, 22 }, { 0x1D, 22 }, { 0x1C, 22 }, + { 0x1B, 22 }, { 0x1A, 22 }, { 0x19, 22 }, { 0x18, 22 }, + { 0x17, 22 }, { 0x16, 22 }, { 0x15, 22 }, { 0x14, 22 }, + { 0x13, 22 }, { 0x12, 22 }, { 0x11, 22 }, { 0x10, 22 }, + { 0x0F, 22 }, { 0x0E, 22 }, { 0x0D, 22 }, { 0x0C, 22 }, + { 0x0B, 22 }, { 0x0A, 22 }, { 0x09, 22 }, { 0x08, 22 }, + { 0x07, 22 }, { 0x06, 22 }, { 0x05, 22 }, { 0x04, 22 }, + { 0x03, 22 }, { 0x02, 22 }, { 0x01, 22 }, { 0x00, 22 } +}; + +#endif /* AVCODEC_SVQ1_VLC_H */ diff --git a/ffmpeg/libavcodec/svq1dec.c b/ffmpeg/libavcodec/svq1dec.c new file mode 100644 index 0000000..c71b361 --- /dev/null +++ b/ffmpeg/libavcodec/svq1dec.c @@ -0,0 +1,821 @@ +/* + * SVQ1 decoder + * ported to MPlayer by Arpi + * ported to libavcodec by Nick Kurshev + * + * Copyright (C) 2002 the xine project + * Copyright (C) 2002 the ffmpeg project + * + * SVQ1 Encoder (c) 2004 Mike Melanson + * + * 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 + */ + +/** + * @file + * Sorenson Vector Quantizer #1 (SVQ1) video codec. + * For more information of the SVQ1 algorithm, visit: + * http://www.pcisys.net/~melanson/codecs/ + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "hpeldsp.h" +#include "internal.h" +#include "mathops.h" +#include "svq1.h" + +#undef NDEBUG +#include + +extern const uint8_t ff_mvtab[33][2]; + +static VLC svq1_block_type; +static VLC svq1_motion_component; +static VLC svq1_intra_multistage[6]; +static VLC svq1_inter_multistage[6]; +static VLC svq1_intra_mean; +static VLC svq1_inter_mean; + +/* motion vector (prediction) */ +typedef struct svq1_pmv_s { + int x; + int y; +} svq1_pmv; + +typedef struct SVQ1Context { + HpelDSPContext hdsp; + GetBitContext gb; + AVFrame *prev; + int width; + int height; + int frame_code; + int nonref; // 1 if the current frame won't be referenced +} SVQ1Context; + +static const uint8_t string_table[256] = { + 0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54, + 0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D, + 0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06, + 0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F, + 0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0, + 0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9, + 0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2, + 0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B, + 0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9, + 0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0, + 0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B, + 0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2, + 0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D, + 0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44, + 0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F, + 0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16, + 0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB, + 0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92, + 0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9, + 0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0, + 0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F, + 0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36, + 0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D, + 0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64, + 0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26, + 0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F, + 0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74, + 0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D, + 0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82, + 0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB, + 0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0, + 0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9 +}; + +#define SVQ1_PROCESS_VECTOR() \ + for (; level > 0; i++) { \ + /* process next depth */ \ + if (i == m) { \ + m = n; \ + if (--level == 0) \ + break; \ + } \ + /* divide block if next bit set */ \ + if (!get_bits1(bitbuf)) \ + break; \ + /* add child nodes */ \ + list[n++] = list[i]; \ + list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level >> 1) + 1));\ + } + +#define SVQ1_ADD_CODEBOOK() \ + /* add codebook entries to vector */ \ + for (j = 0; j < stages; j++) { \ + n3 = codebook[entries[j]] ^ 0x80808080; \ + n1 += (n3 & 0xFF00FF00) >> 8; \ + n2 += n3 & 0x00FF00FF; \ + } \ + \ + /* clip to [0..255] */ \ + if (n1 & 0xFF00FF00) { \ + n3 = (n1 >> 15 & 0x00010001 | 0x01000100) - 0x00010001; \ + n1 += 0x7F007F00; \ + n1 |= (~n1 >> 15 & 0x00010001 | 0x01000100) - 0x00010001; \ + n1 &= n3 & 0x00FF00FF; \ + } \ + \ + if (n2 & 0xFF00FF00) { \ + n3 = (n2 >> 15 & 0x00010001 | 0x01000100) - 0x00010001; \ + n2 += 0x7F007F00; \ + n2 |= (~n2 >> 15 & 0x00010001 | 0x01000100) - 0x00010001; \ + n2 &= n3 & 0x00FF00FF; \ + } + +#define SVQ1_CALC_CODEBOOK_ENTRIES(cbook) \ + codebook = (const uint32_t *)cbook[level]; \ + if (stages > 0) \ + bit_cache = get_bits(bitbuf, 4 * stages); \ + /* calculate codebook entries for this vector */ \ + for (j = 0; j < stages; j++) { \ + entries[j] = (((bit_cache >> (4 * (stages - j - 1))) & 0xF) + \ + 16 * j) << (level + 1); \ + } \ + mean -= stages * 128; \ + n4 = (mean << 16) + mean; + +static int svq1_decode_block_intra(GetBitContext *bitbuf, uint8_t *pixels, + int pitch) +{ + uint32_t bit_cache; + uint8_t *list[63]; + uint32_t *dst; + const uint32_t *codebook; + int entries[6]; + int i, j, m, n; + int mean, stages; + unsigned x, y, width, height, level; + uint32_t n1, n2, n3, n4; + + /* initialize list for breadth first processing of vectors */ + list[0] = pixels; + + /* recursively process vector */ + for (i = 0, m = 1, n = 1, level = 5; i < n; i++) { + SVQ1_PROCESS_VECTOR(); + + /* destination address and vector size */ + dst = (uint32_t *)list[i]; + width = 1 << ((4 + level) / 2); + height = 1 << ((3 + level) / 2); + + /* get number of stages (-1 skips vector, 0 for mean only) */ + stages = get_vlc2(bitbuf, svq1_intra_multistage[level].table, 3, 3) - 1; + + if (stages == -1) { + for (y = 0; y < height; y++) + memset(&dst[y * (pitch / 4)], 0, width); + continue; /* skip vector */ + } + + if (stages > 0 && level >= 4) { + av_dlog(NULL, + "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n", + stages, level); + return AVERROR_INVALIDDATA; /* invalid vector */ + } + + mean = get_vlc2(bitbuf, svq1_intra_mean.table, 8, 3); + + if (stages == 0) { + for (y = 0; y < height; y++) + memset(&dst[y * (pitch / 4)], mean, width); + } else { + SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_intra_codebooks); + + for (y = 0; y < height; y++) { + for (x = 0; x < width / 4; x++, codebook++) { + n1 = n4; + n2 = n4; + SVQ1_ADD_CODEBOOK() + /* store result */ + dst[x] = n1 << 8 | n2; + } + dst += pitch / 4; + } + } + } + + return 0; +} + +static int svq1_decode_block_non_intra(GetBitContext *bitbuf, uint8_t *pixels, + int pitch) +{ + uint32_t bit_cache; + uint8_t *list[63]; + uint32_t *dst; + const uint32_t *codebook; + int entries[6]; + int i, j, m, n; + int mean, stages; + int x, y, width, height, level; + uint32_t n1, n2, n3, n4; + + /* initialize list for breadth first processing of vectors */ + list[0] = pixels; + + /* recursively process vector */ + for (i = 0, m = 1, n = 1, level = 5; i < n; i++) { + SVQ1_PROCESS_VECTOR(); + + /* destination address and vector size */ + dst = (uint32_t *)list[i]; + width = 1 << ((4 + level) / 2); + height = 1 << ((3 + level) / 2); + + /* get number of stages (-1 skips vector, 0 for mean only) */ + stages = get_vlc2(bitbuf, svq1_inter_multistage[level].table, 3, 2) - 1; + + if (stages == -1) + continue; /* skip vector */ + + if ((stages > 0) && (level >= 4)) { + av_dlog(NULL, + "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n", + stages, level); + return AVERROR_INVALIDDATA; /* invalid vector */ + } + + mean = get_vlc2(bitbuf, svq1_inter_mean.table, 9, 3) - 256; + + SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_inter_codebooks); + + for (y = 0; y < height; y++) { + for (x = 0; x < width / 4; x++, codebook++) { + n3 = dst[x]; + /* add mean value to vector */ + n1 = n4 + ((n3 & 0xFF00FF00) >> 8); + n2 = n4 + (n3 & 0x00FF00FF); + SVQ1_ADD_CODEBOOK() + /* store result */ + dst[x] = n1 << 8 | n2; + } + dst += pitch / 4; + } + } + return 0; +} + +static int svq1_decode_motion_vector(GetBitContext *bitbuf, svq1_pmv *mv, + svq1_pmv **pmv) +{ + int diff; + int i; + + for (i = 0; i < 2; i++) { + /* get motion code */ + diff = get_vlc2(bitbuf, svq1_motion_component.table, 7, 2); + if (diff < 0) + return AVERROR_INVALIDDATA; + else if (diff) { + if (get_bits1(bitbuf)) + diff = -diff; + } + + /* add median of motion vector predictors and clip result */ + if (i == 1) + mv->y = sign_extend(diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y), 6); + else + mv->x = sign_extend(diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x), 6); + } + + return 0; +} + +static void svq1_skip_block(uint8_t *current, uint8_t *previous, + int pitch, int x, int y) +{ + uint8_t *src; + uint8_t *dst; + int i; + + src = &previous[x + y * pitch]; + dst = current; + + for (i = 0; i < 16; i++) { + memcpy(dst, src, 16); + src += pitch; + dst += pitch; + } +} + +static int svq1_motion_inter_block(HpelDSPContext *hdsp, GetBitContext *bitbuf, + uint8_t *current, uint8_t *previous, + int pitch, svq1_pmv *motion, int x, int y) +{ + uint8_t *src; + uint8_t *dst; + svq1_pmv mv; + svq1_pmv *pmv[3]; + int result; + + /* predict and decode motion vector */ + pmv[0] = &motion[0]; + if (y == 0) { + pmv[1] = + pmv[2] = pmv[0]; + } else { + pmv[1] = &motion[x / 8 + 2]; + pmv[2] = &motion[x / 8 + 4]; + } + + result = svq1_decode_motion_vector(bitbuf, &mv, pmv); + if (result) + return result; + + motion[0].x = + motion[x / 8 + 2].x = + motion[x / 8 + 3].x = mv.x; + motion[0].y = + motion[x / 8 + 2].y = + motion[x / 8 + 3].y = mv.y; + + if (y + (mv.y >> 1) < 0) + mv.y = 0; + if (x + (mv.x >> 1) < 0) + mv.x = 0; + + src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1)) * pitch]; + dst = current; + + hdsp->put_pixels_tab[0][(mv.y & 1) << 1 | (mv.x & 1)](dst, src, pitch, 16); + + return 0; +} + +static int svq1_motion_inter_4v_block(HpelDSPContext *hdsp, GetBitContext *bitbuf, + uint8_t *current, uint8_t *previous, + int pitch, svq1_pmv *motion, int x, int y) +{ + uint8_t *src; + uint8_t *dst; + svq1_pmv mv; + svq1_pmv *pmv[4]; + int i, result; + + /* predict and decode motion vector (0) */ + pmv[0] = &motion[0]; + if (y == 0) { + pmv[1] = + pmv[2] = pmv[0]; + } else { + pmv[1] = &motion[(x / 8) + 2]; + pmv[2] = &motion[(x / 8) + 4]; + } + + result = svq1_decode_motion_vector(bitbuf, &mv, pmv); + if (result) + return result; + + /* predict and decode motion vector (1) */ + pmv[0] = &mv; + if (y == 0) { + pmv[1] = + pmv[2] = pmv[0]; + } else { + pmv[1] = &motion[(x / 8) + 3]; + } + result = svq1_decode_motion_vector(bitbuf, &motion[0], pmv); + if (result) + return result; + + /* predict and decode motion vector (2) */ + pmv[1] = &motion[0]; + pmv[2] = &motion[(x / 8) + 1]; + + result = svq1_decode_motion_vector(bitbuf, &motion[(x / 8) + 2], pmv); + if (result) + return result; + + /* predict and decode motion vector (3) */ + pmv[2] = &motion[(x / 8) + 2]; + pmv[3] = &motion[(x / 8) + 3]; + + result = svq1_decode_motion_vector(bitbuf, pmv[3], pmv); + if (result) + return result; + + /* form predictions */ + for (i = 0; i < 4; i++) { + int mvx = pmv[i]->x + (i & 1) * 16; + int mvy = pmv[i]->y + (i >> 1) * 16; + + // FIXME: clipping or padding? + if (y + (mvy >> 1) < 0) + mvy = 0; + if (x + (mvx >> 1) < 0) + mvx = 0; + + src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1)) * pitch]; + dst = current; + + hdsp->put_pixels_tab[1][((mvy & 1) << 1) | (mvx & 1)](dst, src, pitch, 8); + + /* select next block */ + if (i & 1) + current += 8 * (pitch - 1); + else + current += 8; + } + + return 0; +} + +static int svq1_decode_delta_block(AVCodecContext *avctx, HpelDSPContext *hdsp, + GetBitContext *bitbuf, + uint8_t *current, uint8_t *previous, + int pitch, svq1_pmv *motion, int x, int y) +{ + uint32_t block_type; + int result = 0; + + /* get block type */ + block_type = get_vlc2(bitbuf, svq1_block_type.table, 2, 2); + + /* reset motion vectors */ + if (block_type == SVQ1_BLOCK_SKIP || block_type == SVQ1_BLOCK_INTRA) { + motion[0].x = + motion[0].y = + motion[x / 8 + 2].x = + motion[x / 8 + 2].y = + motion[x / 8 + 3].x = + motion[x / 8 + 3].y = 0; + } + + switch (block_type) { + case SVQ1_BLOCK_SKIP: + svq1_skip_block(current, previous, pitch, x, y); + break; + + case SVQ1_BLOCK_INTER: + result = svq1_motion_inter_block(hdsp, bitbuf, current, previous, + pitch, motion, x, y); + + if (result != 0) { + av_dlog(avctx, "Error in svq1_motion_inter_block %i\n", result); + break; + } + result = svq1_decode_block_non_intra(bitbuf, current, pitch); + break; + + case SVQ1_BLOCK_INTER_4V: + result = svq1_motion_inter_4v_block(hdsp, bitbuf, current, previous, + pitch, motion, x, y); + + if (result != 0) { + av_dlog(avctx, "Error in svq1_motion_inter_4v_block %i\n", result); + break; + } + result = svq1_decode_block_non_intra(bitbuf, current, pitch); + break; + + case SVQ1_BLOCK_INTRA: + result = svq1_decode_block_intra(bitbuf, current, pitch); + break; + } + + return result; +} + +static void svq1_parse_string(GetBitContext *bitbuf, uint8_t *out) +{ + uint8_t seed; + int i; + + out[0] = get_bits(bitbuf, 8); + seed = string_table[out[0]]; + + for (i = 1; i <= out[0]; i++) { + out[i] = get_bits(bitbuf, 8) ^ seed; + seed = string_table[out[i] ^ seed]; + } +} + +static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame) +{ + SVQ1Context *s = avctx->priv_data; + GetBitContext *bitbuf = &s->gb; + int frame_size_code; + int width = s->width; + int height = s->height; + + skip_bits(bitbuf, 8); /* temporal_reference */ + + /* frame type */ + s->nonref = 0; + switch (get_bits(bitbuf, 2)) { + case 0: + frame->pict_type = AV_PICTURE_TYPE_I; + break; + case 2: + s->nonref = 1; + case 1: + frame->pict_type = AV_PICTURE_TYPE_P; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid frame type.\n"); + return AVERROR_INVALIDDATA; + } + + if (frame->pict_type == AV_PICTURE_TYPE_I) { + /* unknown fields */ + if (s->frame_code == 0x50 || s->frame_code == 0x60) { + int csum = get_bits(bitbuf, 16); + + csum = ff_svq1_packet_checksum(bitbuf->buffer, + bitbuf->size_in_bits >> 3, + csum); + + av_dlog(avctx, "%s checksum (%02x) for packet data\n", + (csum == 0) ? "correct" : "incorrect", csum); + } + + if ((s->frame_code ^ 0x10) >= 0x50) { + uint8_t msg[256]; + + svq1_parse_string(bitbuf, msg); + + av_log(avctx, AV_LOG_INFO, + "embedded message: \"%s\"\n", (char *)msg); + } + + skip_bits(bitbuf, 2); + skip_bits(bitbuf, 2); + skip_bits1(bitbuf); + + /* load frame size */ + frame_size_code = get_bits(bitbuf, 3); + + if (frame_size_code == 7) { + /* load width, height (12 bits each) */ + width = get_bits(bitbuf, 12); + height = get_bits(bitbuf, 12); + + if (!width || !height) + return AVERROR_INVALIDDATA; + } else { + /* get width, height from table */ + width = ff_svq1_frame_size_table[frame_size_code][0]; + height = ff_svq1_frame_size_table[frame_size_code][1]; + } + } + + /* unknown fields */ + if (get_bits1(bitbuf)) { + skip_bits1(bitbuf); /* use packet checksum if (1) */ + skip_bits1(bitbuf); /* component checksums after image data if (1) */ + + if (get_bits(bitbuf, 2) != 0) + return AVERROR_INVALIDDATA; + } + + if (get_bits1(bitbuf)) { + skip_bits1(bitbuf); + skip_bits(bitbuf, 4); + skip_bits1(bitbuf); + skip_bits(bitbuf, 2); + + while (get_bits1(bitbuf)) + skip_bits(bitbuf, 8); + } + + s->width = width; + s->height = height; + return 0; +} + +static int svq1_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + SVQ1Context *s = avctx->priv_data; + AVFrame *cur = data; + uint8_t *current; + int result, i, x, y, width, height; + svq1_pmv *pmv; + + /* initialize bit buffer */ + init_get_bits(&s->gb, buf, buf_size * 8); + + /* decode frame header */ + s->frame_code = get_bits(&s->gb, 22); + + if ((s->frame_code & ~0x70) || !(s->frame_code & 0x60)) + return AVERROR_INVALIDDATA; + + /* swap some header bytes (why?) */ + if (s->frame_code != 0x20) { + uint32_t *src = (uint32_t *)(buf + 4); + + if (buf_size < 36) + return AVERROR_INVALIDDATA; + + for (i = 0; i < 4; i++) + src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i]; + } + + result = svq1_decode_frame_header(avctx, cur); + if (result != 0) { + av_dlog(avctx, "Error in svq1_decode_frame_header %i\n", result); + return result; + } + avcodec_set_dimensions(avctx, s->width, s->height); + + if ((avctx->skip_frame >= AVDISCARD_NONREF && s->nonref) || + (avctx->skip_frame >= AVDISCARD_NONKEY && + cur->pict_type != AV_PICTURE_TYPE_I) || + avctx->skip_frame >= AVDISCARD_ALL) + return buf_size; + + result = ff_get_buffer(avctx, cur, s->nonref ? 0 : AV_GET_BUFFER_FLAG_REF); + if (result < 0) + return result; + + pmv = av_malloc((FFALIGN(s->width, 16) / 8 + 3) * sizeof(*pmv)); + if (!pmv) + return AVERROR(ENOMEM); + + /* decode y, u and v components */ + for (i = 0; i < 3; i++) { + int linesize = cur->linesize[i]; + if (i == 0) { + width = FFALIGN(s->width, 16); + height = FFALIGN(s->height, 16); + } else { + if (avctx->flags & CODEC_FLAG_GRAY) + break; + width = FFALIGN(s->width / 4, 16); + height = FFALIGN(s->height / 4, 16); + } + + current = cur->data[i]; + + if (cur->pict_type == AV_PICTURE_TYPE_I) { + /* keyframe */ + for (y = 0; y < height; y += 16) { + for (x = 0; x < width; x += 16) { + result = svq1_decode_block_intra(&s->gb, ¤t[x], + linesize); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Error in svq1_decode_block %i (keyframe)\n", + result); + goto err; + } + } + current += 16 * linesize; + } + } else { + /* delta frame */ + uint8_t *previous = s->prev->data[i]; + if (!previous || s->prev->width != cur->width || s->prev->height != cur->height) { + av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); + result = AVERROR_INVALIDDATA; + goto err; + } + + memset(pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv)); + + for (y = 0; y < height; y += 16) { + for (x = 0; x < width; x += 16) { + result = svq1_decode_delta_block(avctx, &s->hdsp, + &s->gb, ¤t[x], + previous, linesize, + pmv, x, y); + if (result) { + av_dlog(avctx, + "Error in svq1_decode_delta_block %i\n", + result); + goto err; + } + } + + pmv[0].x = + pmv[0].y = 0; + + current += 16 * linesize; + } + } + } + + if (!s->nonref) { + av_frame_unref(s->prev); + result = av_frame_ref(s->prev, cur); + if (result < 0) + goto err; + } + + *got_frame = 1; + result = buf_size; + +err: + av_free(pmv); + return result; +} + +static av_cold int svq1_decode_init(AVCodecContext *avctx) +{ + SVQ1Context *s = avctx->priv_data; + int i; + int offset = 0; + + s->prev = avcodec_alloc_frame(); + if (!s->prev) + return AVERROR(ENOMEM); + + s->width = avctx->width + 3 & ~3; + s->height = avctx->height + 3 & ~3; + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + + ff_hpeldsp_init(&s->hdsp, avctx->flags); + + INIT_VLC_STATIC(&svq1_block_type, 2, 4, + &ff_svq1_block_type_vlc[0][1], 2, 1, + &ff_svq1_block_type_vlc[0][0], 2, 1, 6); + + INIT_VLC_STATIC(&svq1_motion_component, 7, 33, + &ff_mvtab[0][1], 2, 1, + &ff_mvtab[0][0], 2, 1, 176); + + for (i = 0; i < 6; i++) { + static const uint8_t sizes[2][6] = { { 14, 10, 14, 18, 16, 18 }, + { 10, 10, 14, 14, 14, 16 } }; + static VLC_TYPE table[168][2]; + svq1_intra_multistage[i].table = &table[offset]; + svq1_intra_multistage[i].table_allocated = sizes[0][i]; + offset += sizes[0][i]; + init_vlc(&svq1_intra_multistage[i], 3, 8, + &ff_svq1_intra_multistage_vlc[i][0][1], 2, 1, + &ff_svq1_intra_multistage_vlc[i][0][0], 2, 1, + INIT_VLC_USE_NEW_STATIC); + svq1_inter_multistage[i].table = &table[offset]; + svq1_inter_multistage[i].table_allocated = sizes[1][i]; + offset += sizes[1][i]; + init_vlc(&svq1_inter_multistage[i], 3, 8, + &ff_svq1_inter_multistage_vlc[i][0][1], 2, 1, + &ff_svq1_inter_multistage_vlc[i][0][0], 2, 1, + INIT_VLC_USE_NEW_STATIC); + } + + INIT_VLC_STATIC(&svq1_intra_mean, 8, 256, + &ff_svq1_intra_mean_vlc[0][1], 4, 2, + &ff_svq1_intra_mean_vlc[0][0], 4, 2, 632); + + INIT_VLC_STATIC(&svq1_inter_mean, 9, 512, + &ff_svq1_inter_mean_vlc[0][1], 4, 2, + &ff_svq1_inter_mean_vlc[0][0], 4, 2, 1434); + + return 0; +} + +static av_cold int svq1_decode_end(AVCodecContext *avctx) +{ + SVQ1Context *s = avctx->priv_data; + + av_frame_free(&s->prev); + + return 0; +} + +static void svq1_flush(AVCodecContext *avctx) +{ + SVQ1Context *s = avctx->priv_data; + + av_frame_unref(s->prev); +} + +AVCodec ff_svq1_decoder = { + .name = "svq1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SVQ1, + .priv_data_size = sizeof(SVQ1Context), + .init = svq1_decode_init, + .close = svq1_decode_end, + .decode = svq1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = svq1_flush, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), +}; diff --git a/ffmpeg/libavcodec/svq1enc.c b/ffmpeg/libavcodec/svq1enc.c new file mode 100644 index 0000000..cf9157f --- /dev/null +++ b/ffmpeg/libavcodec/svq1enc.c @@ -0,0 +1,635 @@ +/* + * SVQ1 Encoder + * Copyright (C) 2004 Mike Melanson + * + * 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 + */ + +/** + * @file + * Sorenson Vector Quantizer #1 (SVQ1) video codec. + * For more information of the SVQ1 algorithm, visit: + * http://www.pcisys.net/~melanson/codecs/ + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "hpeldsp.h" +#include "mpegvideo.h" +#include "h263.h" +#include "internal.h" +#include "libavutil/avassert.h" +#include "svq1.h" +#include "svq1enc_cb.h" + + +typedef struct SVQ1Context { + /* FIXME: Needed for motion estimation, should not be used for anything + * else, the idea is to make the motion estimation eventually independent + * of MpegEncContext, so this will be removed then. */ + MpegEncContext m; + AVCodecContext *avctx; + DSPContext dsp; + HpelDSPContext hdsp; + AVFrame picture; + AVFrame current_picture; + AVFrame last_picture; + PutBitContext pb; + GetBitContext gb; + + /* why ooh why this sick breadth first order, + * everything is slower and more complex */ + PutBitContext reorder_pb[6]; + + int frame_width; + int frame_height; + + /* Y plane block dimensions */ + int y_block_width; + int y_block_height; + + /* U & V plane (C planes) block dimensions */ + int c_block_width; + int c_block_height; + + uint16_t *mb_type; + uint32_t *dummy; + int16_t (*motion_val8[3])[2]; + int16_t (*motion_val16[3])[2]; + + int64_t rd_total; + + uint8_t *scratchbuf; +} SVQ1Context; + +static void svq1_write_header(SVQ1Context *s, int frame_type) +{ + int i; + + /* frame code */ + put_bits(&s->pb, 22, 0x20); + + /* temporal reference (sure hope this is a "don't care") */ + put_bits(&s->pb, 8, 0x00); + + /* frame type */ + put_bits(&s->pb, 2, frame_type - 1); + + if (frame_type == AV_PICTURE_TYPE_I) { + /* no checksum since frame code is 0x20 */ + /* no embedded string either */ + /* output 5 unknown bits (2 + 2 + 1) */ + put_bits(&s->pb, 5, 2); /* 2 needed by quicktime decoder */ + + i = ff_match_2uint16((void*)ff_svq1_frame_size_table, + FF_ARRAY_ELEMS(ff_svq1_frame_size_table), + s->frame_width, s->frame_height); + put_bits(&s->pb, 3, i); + + if (i == 7) { + put_bits(&s->pb, 12, s->frame_width); + put_bits(&s->pb, 12, s->frame_height); + } + } + + /* no checksum or extra data (next 2 bits get 0) */ + put_bits(&s->pb, 2, 0); +} + +#define QUALITY_THRESHOLD 100 +#define THRESHOLD_MULTIPLIER 0.6 + +static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, + uint8_t *decoded, int stride, int level, + int threshold, int lambda, int intra) +{ + int count, y, x, i, j, split, best_mean, best_score, best_count; + int best_vector[6]; + int block_sum[7] = { 0, 0, 0, 0, 0, 0 }; + int w = 2 << (level + 2 >> 1); + int h = 2 << (level + 1 >> 1); + int size = w * h; + int16_t block[7][256]; + const int8_t *codebook_sum, *codebook; + const uint16_t(*mean_vlc)[2]; + const uint8_t(*multistage_vlc)[2]; + + best_score = 0; + // FIXME: Optimize, this does not need to be done multiple times. + if (intra) { + codebook_sum = svq1_intra_codebook_sum[level]; + codebook = ff_svq1_intra_codebooks[level]; + mean_vlc = ff_svq1_intra_mean_vlc; + multistage_vlc = ff_svq1_intra_multistage_vlc[level]; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + int v = src[x + y * stride]; + block[0][x + w * y] = v; + best_score += v * v; + block_sum[0] += v; + } + } + } else { + codebook_sum = svq1_inter_codebook_sum[level]; + codebook = ff_svq1_inter_codebooks[level]; + mean_vlc = ff_svq1_inter_mean_vlc + 256; + multistage_vlc = ff_svq1_inter_multistage_vlc[level]; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + int v = src[x + y * stride] - ref[x + y * stride]; + block[0][x + w * y] = v; + best_score += v * v; + block_sum[0] += v; + } + } + } + + best_count = 0; + best_score -= (int)((unsigned)block_sum[0] * block_sum[0] >> (level + 3)); + best_mean = block_sum[0] + (size >> 1) >> (level + 3); + + if (level < 4) { + for (count = 1; count < 7; count++) { + int best_vector_score = INT_MAX; + int best_vector_sum = -999, best_vector_mean = -999; + const int stage = count - 1; + const int8_t *vector; + + for (i = 0; i < 16; i++) { + int sum = codebook_sum[stage * 16 + i]; + int sqr, diff, score; + + vector = codebook + stage * size * 16 + i * size; + sqr = s->dsp.ssd_int8_vs_int16(vector, block[stage], size); + diff = block_sum[stage] - sum; + score = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64bit slooow + if (score < best_vector_score) { + int mean = diff + (size >> 1) >> (level + 3); + av_assert2(mean > -300 && mean < 300); + mean = av_clip(mean, intra ? 0 : -256, 255); + best_vector_score = score; + best_vector[stage] = i; + best_vector_sum = sum; + best_vector_mean = mean; + } + } + av_assert0(best_vector_mean != -999); + vector = codebook + stage * size * 16 + best_vector[stage] * size; + for (j = 0; j < size; j++) + block[stage + 1][j] = block[stage][j] - vector[j]; + block_sum[stage + 1] = block_sum[stage] - best_vector_sum; + best_vector_score += lambda * + (+1 + 4 * count + + multistage_vlc[1 + count][1] + + mean_vlc[best_vector_mean][1]); + + if (best_vector_score < best_score) { + best_score = best_vector_score; + best_count = count; + best_mean = best_vector_mean; + } + } + } + + split = 0; + if (best_score > threshold && level) { + int score = 0; + int offset = level & 1 ? stride * h / 2 : w / 2; + PutBitContext backup[6]; + + for (i = level - 1; i >= 0; i--) + backup[i] = s->reorder_pb[i]; + score += encode_block(s, src, ref, decoded, stride, level - 1, + threshold >> 1, lambda, intra); + score += encode_block(s, src + offset, ref + offset, decoded + offset, + stride, level - 1, threshold >> 1, lambda, intra); + score += lambda; + + if (score < best_score) { + best_score = score; + split = 1; + } else { + for (i = level - 1; i >= 0; i--) + s->reorder_pb[i] = backup[i]; + } + } + if (level > 0) + put_bits(&s->reorder_pb[level], 1, split); + + if (!split) { + av_assert1(best_mean >= 0 && best_mean < 256 || !intra); + av_assert1(best_mean >= -256 && best_mean < 256); + av_assert1(best_count >= 0 && best_count < 7); + av_assert1(level < 4 || best_count == 0); + + /* output the encoding */ + put_bits(&s->reorder_pb[level], + multistage_vlc[1 + best_count][1], + multistage_vlc[1 + best_count][0]); + put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1], + mean_vlc[best_mean][0]); + + for (i = 0; i < best_count; i++) { + av_assert2(best_vector[i] >= 0 && best_vector[i] < 16); + put_bits(&s->reorder_pb[level], 4, best_vector[i]); + } + + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + decoded[x + y * stride] = src[x + y * stride] - + block[best_count][x + w * y] + + best_mean; + } + + return best_score; +} + +static int svq1_encode_plane(SVQ1Context *s, int plane, + unsigned char *src_plane, + unsigned char *ref_plane, + unsigned char *decoded_plane, + int width, int height, int src_stride, int stride) +{ + int x, y; + int i; + int block_width, block_height; + int level; + int threshold[6]; + uint8_t *src = s->scratchbuf + stride * 16; + const int lambda = (s->picture.quality * s->picture.quality) >> + (2 * FF_LAMBDA_SHIFT); + + /* figure out the acceptable level thresholds in advance */ + threshold[5] = QUALITY_THRESHOLD; + for (level = 4; level >= 0; level--) + threshold[level] = threshold[level + 1] * THRESHOLD_MULTIPLIER; + + block_width = (width + 15) / 16; + block_height = (height + 15) / 16; + + if (s->picture.pict_type == AV_PICTURE_TYPE_P) { + s->m.avctx = s->avctx; + s->m.current_picture_ptr = &s->m.current_picture; + s->m.last_picture_ptr = &s->m.last_picture; + s->m.last_picture.f.data[0] = ref_plane; + s->m.linesize = + s->m.last_picture.f.linesize[0] = + s->m.new_picture.f.linesize[0] = + s->m.current_picture.f.linesize[0] = stride; + s->m.width = width; + s->m.height = height; + s->m.mb_width = block_width; + s->m.mb_height = block_height; + s->m.mb_stride = s->m.mb_width + 1; + s->m.b8_stride = 2 * s->m.mb_width + 1; + s->m.f_code = 1; + s->m.pict_type = s->picture.pict_type; + s->m.me_method = s->avctx->me_method; + s->m.me.scene_change_score = 0; + s->m.flags = s->avctx->flags; + // s->m.out_format = FMT_H263; + // s->m.unrestricted_mv = 1; + s->m.lambda = s->picture.quality; + s->m.qscale = s->m.lambda * 139 + + FF_LAMBDA_SCALE * 64 >> + FF_LAMBDA_SHIFT + 7; + s->m.lambda2 = s->m.lambda * s->m.lambda + + FF_LAMBDA_SCALE / 2 >> + FF_LAMBDA_SHIFT; + + if (!s->motion_val8[plane]) { + s->motion_val8[plane] = av_mallocz((s->m.b8_stride * + block_height * 2 + 2) * + 2 * sizeof(int16_t)); + s->motion_val16[plane] = av_mallocz((s->m.mb_stride * + (block_height + 2) + 1) * + 2 * sizeof(int16_t)); + } + + s->m.mb_type = s->mb_type; + + // dummies, to avoid segfaults + s->m.current_picture.mb_mean = (uint8_t *)s->dummy; + s->m.current_picture.mb_var = (uint16_t *)s->dummy; + s->m.current_picture.mc_mb_var = (uint16_t *)s->dummy; + s->m.current_picture.mb_type = s->dummy; + + s->m.current_picture.motion_val[0] = s->motion_val8[plane] + 2; + s->m.p_mv_table = s->motion_val16[plane] + + s->m.mb_stride + 1; + s->m.dsp = s->dsp; // move + ff_init_me(&s->m); + + s->m.me.dia_size = s->avctx->dia_size; + s->m.first_slice_line = 1; + for (y = 0; y < block_height; y++) { + s->m.new_picture.f.data[0] = src - y * 16 * stride; // ugly + s->m.mb_y = y; + + for (i = 0; i < 16 && i + 16 * y < height; i++) { + memcpy(&src[i * stride], &src_plane[(i + 16 * y) * src_stride], + width); + for (x = width; x < 16 * block_width; x++) + src[i * stride + x] = src[i * stride + x - 1]; + } + for (; i < 16 && i + 16 * y < 16 * block_height; i++) + memcpy(&src[i * stride], &src[(i - 1) * stride], + 16 * block_width); + + for (x = 0; x < block_width; x++) { + s->m.mb_x = x; + ff_init_block_index(&s->m); + ff_update_block_index(&s->m); + + ff_estimate_p_frame_motion(&s->m, x, y); + } + s->m.first_slice_line = 0; + } + + ff_fix_long_p_mvs(&s->m); + ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code, + CANDIDATE_MB_TYPE_INTER, 0); + } + + s->m.first_slice_line = 1; + for (y = 0; y < block_height; y++) { + for (i = 0; i < 16 && i + 16 * y < height; i++) { + memcpy(&src[i * stride], &src_plane[(i + 16 * y) * src_stride], + width); + for (x = width; x < 16 * block_width; x++) + src[i * stride + x] = src[i * stride + x - 1]; + } + for (; i < 16 && i + 16 * y < 16 * block_height; i++) + memcpy(&src[i * stride], &src[(i - 1) * stride], 16 * block_width); + + s->m.mb_y = y; + for (x = 0; x < block_width; x++) { + uint8_t reorder_buffer[3][6][7 * 32]; + int count[3][6]; + int offset = y * 16 * stride + x * 16; + uint8_t *decoded = decoded_plane + offset; + uint8_t *ref = ref_plane + offset; + int score[4] = { 0, 0, 0, 0 }, best; + uint8_t *temp = s->scratchbuf; + + if (s->pb.buf_end - s->pb.buf - + (put_bits_count(&s->pb) >> 3) < 3000) { // FIXME: check size + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + + s->m.mb_x = x; + ff_init_block_index(&s->m); + ff_update_block_index(&s->m); + + if (s->picture.pict_type == AV_PICTURE_TYPE_I || + (s->m.mb_type[x + y * s->m.mb_stride] & + CANDIDATE_MB_TYPE_INTRA)) { + for (i = 0; i < 6; i++) + init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i], + 7 * 32); + if (s->picture.pict_type == AV_PICTURE_TYPE_P) { + const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA]; + put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); + score[0] = vlc[1] * lambda; + } + score[0] += encode_block(s, src + 16 * x, NULL, temp, stride, + 5, 64, lambda, 1); + for (i = 0; i < 6; i++) { + count[0][i] = put_bits_count(&s->reorder_pb[i]); + flush_put_bits(&s->reorder_pb[i]); + } + } else + score[0] = INT_MAX; + + best = 0; + + if (s->picture.pict_type == AV_PICTURE_TYPE_P) { + const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER]; + int mx, my, pred_x, pred_y, dxy; + int16_t *motion_ptr; + + motion_ptr = ff_h263_pred_motion(&s->m, 0, 0, &pred_x, &pred_y); + if (s->m.mb_type[x + y * s->m.mb_stride] & + CANDIDATE_MB_TYPE_INTER) { + for (i = 0; i < 6; i++) + init_put_bits(&s->reorder_pb[i], reorder_buffer[1][i], + 7 * 32); + + put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); + + s->m.pb = s->reorder_pb[5]; + mx = motion_ptr[0]; + my = motion_ptr[1]; + av_assert1(mx >= -32 && mx <= 31); + av_assert1(my >= -32 && my <= 31); + av_assert1(pred_x >= -32 && pred_x <= 31); + av_assert1(pred_y >= -32 && pred_y <= 31); + ff_h263_encode_motion(&s->m, mx - pred_x, 1); + ff_h263_encode_motion(&s->m, my - pred_y, 1); + s->reorder_pb[5] = s->m.pb; + score[1] += lambda * put_bits_count(&s->reorder_pb[5]); + + dxy = (mx & 1) + 2 * (my & 1); + + s->hdsp.put_pixels_tab[0][dxy](temp + 16, + ref + (mx >> 1) + + stride * (my >> 1), + stride, 16); + + score[1] += encode_block(s, src + 16 * x, temp + 16, + decoded, stride, 5, 64, lambda, 0); + best = score[1] <= score[0]; + + vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_SKIP]; + score[2] = s->dsp.sse[0](NULL, src + 16 * x, ref, + stride, 16); + score[2] += vlc[1] * lambda; + if (score[2] < score[best] && mx == 0 && my == 0) { + best = 2; + s->hdsp.put_pixels_tab[0][0](decoded, ref, stride, 16); + for (i = 0; i < 6; i++) + count[2][i] = 0; + put_bits(&s->pb, vlc[1], vlc[0]); + } + } + + if (best == 1) { + for (i = 0; i < 6; i++) { + count[1][i] = put_bits_count(&s->reorder_pb[i]); + flush_put_bits(&s->reorder_pb[i]); + } + } else { + motion_ptr[0] = + motion_ptr[1] = + motion_ptr[2] = + motion_ptr[3] = + motion_ptr[0 + 2 * s->m.b8_stride] = + motion_ptr[1 + 2 * s->m.b8_stride] = + motion_ptr[2 + 2 * s->m.b8_stride] = + motion_ptr[3 + 2 * s->m.b8_stride] = 0; + } + } + + s->rd_total += score[best]; + + for (i = 5; i >= 0; i--) + avpriv_copy_bits(&s->pb, reorder_buffer[best][i], + count[best][i]); + if (best == 0) + s->hdsp.put_pixels_tab[0][0](decoded, temp, stride, 16); + } + s->m.first_slice_line = 0; + } + return 0; +} + +static av_cold int svq1_encode_init(AVCodecContext *avctx) +{ + SVQ1Context *const s = avctx->priv_data; + + ff_dsputil_init(&s->dsp, avctx); + ff_hpeldsp_init(&s->hdsp, avctx->flags); + avctx->coded_frame = &s->picture; + + s->frame_width = avctx->width; + s->frame_height = avctx->height; + + s->y_block_width = (s->frame_width + 15) / 16; + s->y_block_height = (s->frame_height + 15) / 16; + + s->c_block_width = (s->frame_width / 4 + 15) / 16; + s->c_block_height = (s->frame_height / 4 + 15) / 16; + + s->avctx = avctx; + s->m.avctx = avctx; + s->m.picture_structure = PICT_FRAME; + s->m.me.temp = + s->m.me.scratchpad = av_mallocz((avctx->width + 64) * + 2 * 16 * 2 * sizeof(uint8_t)); + s->m.me.map = av_mallocz(ME_MAP_SIZE * sizeof(uint32_t)); + s->m.me.score_map = av_mallocz(ME_MAP_SIZE * sizeof(uint32_t)); + s->mb_type = av_mallocz((s->y_block_width + 1) * + s->y_block_height * sizeof(int16_t)); + s->dummy = av_mallocz((s->y_block_width + 1) * + s->y_block_height * sizeof(int32_t)); + ff_h263_encode_init(&s->m); // mv_penalty + + return 0; +} + +static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + SVQ1Context *const s = avctx->priv_data; + AVFrame *const p = &s->picture; + AVFrame temp; + int i, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, s->y_block_width * s->y_block_height * + MAX_MB_BYTES*3 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + + if (avctx->pix_fmt != AV_PIX_FMT_YUV410P) { + av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); + return -1; + } + + if (!s->current_picture.data[0]) { + if ((ret = ff_get_buffer(avctx, &s->current_picture, 0))< 0 || + (ret = ff_get_buffer(avctx, &s->last_picture, 0)) < 0) { + return ret; + } + s->scratchbuf = av_malloc(s->current_picture.linesize[0] * 16 * 2); + } + + temp = s->current_picture; + s->current_picture = s->last_picture; + s->last_picture = temp; + + init_put_bits(&s->pb, pkt->data, pkt->size); + + *p = *pict; + p->pict_type = avctx->gop_size && avctx->frame_number % avctx->gop_size ? + AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + p->key_frame = p->pict_type == AV_PICTURE_TYPE_I; + + svq1_write_header(s, p->pict_type); + for (i = 0; i < 3; i++) + if (svq1_encode_plane(s, i, + s->picture.data[i], + s->last_picture.data[i], + s->current_picture.data[i], + s->frame_width / (i ? 4 : 1), + s->frame_height / (i ? 4 : 1), + s->picture.linesize[i], + s->current_picture.linesize[i]) < 0) + return -1; + + // avpriv_align_put_bits(&s->pb); + while (put_bits_count(&s->pb) & 31) + put_bits(&s->pb, 1, 0); + + flush_put_bits(&s->pb); + + pkt->size = put_bits_count(&s->pb) / 8; + if (p->pict_type == AV_PICTURE_TYPE_I) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int svq1_encode_end(AVCodecContext *avctx) +{ + SVQ1Context *const s = avctx->priv_data; + int i; + + av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", + s->rd_total / (double)(avctx->width * avctx->height * + avctx->frame_number)); + + av_freep(&s->m.me.scratchpad); + av_freep(&s->m.me.map); + av_freep(&s->m.me.score_map); + av_freep(&s->mb_type); + av_freep(&s->dummy); + av_freep(&s->scratchbuf); + + for (i = 0; i < 3; i++) { + av_freep(&s->motion_val8[i]); + av_freep(&s->motion_val16[i]); + } + + av_frame_unref(&s->current_picture); + av_frame_unref(&s->last_picture); + + return 0; +} + +AVCodec ff_svq1_encoder = { + .name = "svq1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SVQ1, + .priv_data_size = sizeof(SVQ1Context), + .init = svq1_encode_init, + .encode2 = svq1_encode_frame, + .close = svq1_encode_end, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), +}; diff --git a/ffmpeg/libavcodec/svq1enc_cb.h b/ffmpeg/libavcodec/svq1enc_cb.h new file mode 100644 index 0000000..1edb4ec --- /dev/null +++ b/ffmpeg/libavcodec/svq1enc_cb.h @@ -0,0 +1,86 @@ +/* + * SVQ1 Encoder + * Copyright (C) 2004 Mike Melanson + * + * 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 + */ + +/** + * @file + * svq1 code books. + */ + +#ifndef AVCODEC_SVQ1ENC_CB_H +#define AVCODEC_SVQ1ENC_CB_H + +#include + +static const int8_t svq1_inter_codebook_sum[4][16*6] = { + { -1, 1, -2, 0, 1, -1, -1, -1, -2, -1, 1, -1, -1, 0, -1, -1, + 0, -1, -1, -1, -1, 0, -1, 0, 0, 0, -3, 1, -1, 0, 1, -1, + 1, -1, 2, 2, 1, 1, 2, 0, 0, 0, -1, 1, 1, 0, 0, 0, + 1, -1, 0, 1, -1, 1, 1, 0, 1, 0, -1, 1, 1, 0, 0, 0, + -2, 0, 0, -2, 0, 0, -2, 0, -2, -1, -2, -1, 0, 0, -1, 0, + 1, 0, 1, -1, 2, 2, 1, 2, 2, 1, 0, 1, 1, 0, 1, 1, }, + { -2, 1, -1, -1, 1, 0, 1, -1, -1, -1, 1, -1, 0, -1, 0, -1, + 0, 0, 0, -2, 0, 1, 0, -1, -1, 0, 2, -3, 1, -2, 3, -1, + 2, 0, 2, 1, 1, -1, 1, 1, 0, 0, 1, 1, 2, -2, 1, 0, + -2, -1, 2, -2, -2, 0, -3, 0, -1, 0, -1, 0, -1, 0, -2, -3, + 1, -2, -2, -1, 1, -1, -1, 1, -1, 1, 1, 0, -2, 0, 1, 1, + 1, 1, 2, 1, 0, 0, -1, 0, 0, 1, 0, 1, -1, 1, 0, 2, }, + { 0, 0, 0, -3, 1, 1, 1, -3, 0, -1, 0, -3, 1, -3, 0, -2, + 1, 2, -1, -3, 0, -3, 1, -1, 0, -1, 0, 0, 1, 2, 1, 1, + -1, 2, -3, 3, 1, 0, -5, 1, 0, -1, -3, 1, 0, 2, 0, -3, + 4, 2, 0, -2, 1, -2, 3, -2, 1, 1, 0, -1, 2, 5, 3, 1, + -1, 0, 2, -3, -2, 0, 0, -2, 2, -3, -1, -1, 2, 1, 0, -2, + 3, -1, 1, -1, 2, 4, 0, 1, 0, 1, 0, -1, -3, -2, -1, 0, }, + { 0, 2, -1, -1, 2, -4, -2, 3, 0, -1, -5, 1, 0, 1, 0, 6, + -2, 2, 0, 1, 1, -1, -1, -2, 1, -2, -1, 0, 2, -2, -2, -1, + -4, 2, -1, -3, -1, -2, 2, -1, 2, -1, 2, 0, 3, -3, -3, 0, + -3, 0, 0, -2, 4, -4, 0, -1, 4, 0, -2, -2, 3, -2, 0, 4, + 5, 0, 1, 0, -3, 3, 3, 2, 0, 0, 1, 2, -5, -2, -3, 0, + -3, 2, -2, 2, -2, 4, 7, -3, 4, 2, 3, 2, -1, 0, -3, 1, } +}; + +static const int8_t svq1_intra_codebook_sum[4][16*6] = { + { 0, 0, 0, -1, -1, -1, -1, -2, 0, -1, -1, 0, -1, 0, 1, 0, + 1, 0, -1, 1, 0, 0, -1, 1, -1, 0, 0, 0, -1, 1, 0, 0, + -1, 0, 0, 1, -1, 1, 0, -1, -1, 0, 1, 1, 0, 0, -1, 1, + 0, 1, 0, 0, 1, -1, 0, 0, 0, -1, 1, 0, 1, 0, -2, 1, + 0, -1, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0, -1, 0, 0, 0, + 0, 1, 1, 0, 0, -1, 0, 1, 0, 0, 0, 0, -1, 1, 1, -1, }, + { -1, -2, 0, -1, 1, 0, -1, 0, -1, -4, -1, -2, -1, -2, 1, -2, + 0, 0, 4, -2, -1, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 0, + 1, 1, 0, -1, -1, -1, 1, 0, -1, -3, -3, 1, -1, 1, -2, -1, + 1, -1, 0, 1, 2, 1, -1, -1, 1, 1, 1, 2, 1, 0, 1, -2, + -2, 0, -1, -2, -2, 0, -1, -1, -1, 0, 1, 0, -1, -1, 0, -1, + 0, 2, 1, 2, 2, 1, -1, 1, 0, 2, 0, -1, 1, 0, 0, 0, }, + { -2, 0, -1, -1, 1, 1, -2, 0, -2, 0, 1, -2, -2, 1, -1, -1, + 3, -2, 0, -3, -4, -3, 2, 1, 0, 3, -2, 2, 3, 2, 2, -1, + -3, 1, 0, 1, 0, 0, 0, 1, -2, 1, -2, -2, -1, -2, -2, 2, + 0, -4, 0, 2, -1, 0, 2, 2, 2, 1, 0, -1, -1, 1, -3, 2, + 2, 1, 0, 3, 1, -1, 1, 3, 1, 0, 1, 1, 2, -1, 1, -1, + -2, -1, 0, -1, 1, -1, 1, -2, -2, -1, -1, -3, 1, -4, -3, 1, }, + { -2, 0, -2, 3, -1, -1, 0, 2, 2, -1, -3, 2, 1, 0, -2, -1, + -3, -2, -2, 1, 2, -3, 0, 1, -5, -2, -3, 0, -2, -1, 2, 0, + -1, -1, 0, -2, 1, 3, -7, -2, -2, -1, 2, -1, 0, 3, 1, 3, + 1, 0, 0, 1, 2, 3, 1, 2, 0, -2, -2, 1, 1, 2, 2, 3, + 4, 1, -1, 2, -2, 4, 0, 0, 0, 4, 2, 0, -2, -2, 2, -4, + -1, 5, -2, -2, -3, 2, -3, -1, 3, -3, 0, 4, 3, 0, 1, -2, } +}; + +#endif /* AVCODEC_SVQ1ENC_CB_H */ diff --git a/ffmpeg/libavcodec/svq3.c b/ffmpeg/libavcodec/svq3.c new file mode 100644 index 0000000..53c4d32 --- /dev/null +++ b/ffmpeg/libavcodec/svq3.c @@ -0,0 +1,1350 @@ +/* + * Copyright (c) 2003 The FFmpeg Project + * + * 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 + */ + +/* + * How to use this decoder: + * SVQ3 data is transported within Apple Quicktime files. Quicktime files + * have stsd atoms to describe media trak properties. A stsd atom for a + * video trak contains 1 or more ImageDescription atoms. These atoms begin + * with the 4-byte length of the atom followed by the codec fourcc. Some + * decoders need information in this atom to operate correctly. Such + * is the case with SVQ3. In order to get the best use out of this decoder, + * the calling app must make the SVQ3 ImageDescription atom available + * via the AVCodecContext's extradata[_size] field: + * + * AVCodecContext.extradata = pointer to ImageDescription, first characters + * are expected to be 'S', 'V', 'Q', and '3', NOT the 4-byte atom length + * AVCodecContext.extradata_size = size of ImageDescription atom memory + * buffer (which will be the same as the ImageDescription atom size field + * from the QT file, minus 4 bytes since the length is missing) + * + * You will know you have these parameters passed correctly when the decoder + * correctly decodes this file: + * http://samples.mplayerhq.hu/V-codecs/SVQ3/Vertical400kbit.sorenson3.mov + */ +#include "internal.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "h264.h" + +#include "h264data.h" // FIXME FIXME FIXME + +#include "h264_mvpred.h" +#include "golomb.h" +#include "hpeldsp.h" +#include "rectangle.h" +#include "vdpau_internal.h" + +#if CONFIG_ZLIB +#include +#endif + +#include "svq1.h" +#include "svq3.h" + +/** + * @file + * svq3 decoder. + */ + +typedef struct { + H264Context h; + HpelDSPContext hdsp; + Picture *cur_pic; + Picture *next_pic; + Picture *last_pic; + int halfpel_flag; + int thirdpel_flag; + int unknown_flag; + int next_slice_index; + uint32_t watermark_key; + uint8_t *buf; + int buf_size; + int adaptive_quant; + int next_p_frame_damaged; + int h_edge_pos; + int v_edge_pos; + int last_frame_output; +} SVQ3Context; + +#define FULLPEL_MODE 1 +#define HALFPEL_MODE 2 +#define THIRDPEL_MODE 3 +#define PREDICT_MODE 4 + +/* dual scan (from some older h264 draft) + * o-->o-->o o + * | /| + * o o o / o + * | / | |/ | + * o o o o + * / + * o-->o-->o-->o + */ +static const uint8_t svq3_scan[16] = { + 0 + 0 * 4, 1 + 0 * 4, 2 + 0 * 4, 2 + 1 * 4, + 2 + 2 * 4, 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4, + 0 + 1 * 4, 0 + 2 * 4, 1 + 1 * 4, 1 + 2 * 4, + 0 + 3 * 4, 1 + 3 * 4, 2 + 3 * 4, 3 + 3 * 4, +}; + +static const uint8_t svq3_pred_0[25][2] = { + { 0, 0 }, + { 1, 0 }, { 0, 1 }, + { 0, 2 }, { 1, 1 }, { 2, 0 }, + { 3, 0 }, { 2, 1 }, { 1, 2 }, { 0, 3 }, + { 0, 4 }, { 1, 3 }, { 2, 2 }, { 3, 1 }, { 4, 0 }, + { 4, 1 }, { 3, 2 }, { 2, 3 }, { 1, 4 }, + { 2, 4 }, { 3, 3 }, { 4, 2 }, + { 4, 3 }, { 3, 4 }, + { 4, 4 } +}; + +static const int8_t svq3_pred_1[6][6][5] = { + { { 2, -1, -1, -1, -1 }, { 2, 1, -1, -1, -1 }, { 1, 2, -1, -1, -1 }, + { 2, 1, -1, -1, -1 }, { 1, 2, -1, -1, -1 }, { 1, 2, -1, -1, -1 } }, + { { 0, 2, -1, -1, -1 }, { 0, 2, 1, 4, 3 }, { 0, 1, 2, 4, 3 }, + { 0, 2, 1, 4, 3 }, { 2, 0, 1, 3, 4 }, { 0, 4, 2, 1, 3 } }, + { { 2, 0, -1, -1, -1 }, { 2, 1, 0, 4, 3 }, { 1, 2, 4, 0, 3 }, + { 2, 1, 0, 4, 3 }, { 2, 1, 4, 3, 0 }, { 1, 2, 4, 0, 3 } }, + { { 2, 0, -1, -1, -1 }, { 2, 0, 1, 4, 3 }, { 1, 2, 0, 4, 3 }, + { 2, 1, 0, 4, 3 }, { 2, 1, 3, 4, 0 }, { 2, 4, 1, 0, 3 } }, + { { 0, 2, -1, -1, -1 }, { 0, 2, 1, 3, 4 }, { 1, 2, 3, 0, 4 }, + { 2, 0, 1, 3, 4 }, { 2, 1, 3, 0, 4 }, { 2, 0, 4, 3, 1 } }, + { { 0, 2, -1, -1, -1 }, { 0, 2, 4, 1, 3 }, { 1, 4, 2, 0, 3 }, + { 4, 2, 0, 1, 3 }, { 2, 0, 1, 4, 3 }, { 4, 2, 1, 0, 3 } }, +}; + +static const struct { + uint8_t run; + uint8_t level; +} svq3_dct_tables[2][16] = { + { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 0, 2 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, + { 0, 3 }, { 1, 2 }, { 2, 2 }, { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 0, 4 } }, + { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 0, 2 }, { 2, 1 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, + { 3, 1 }, { 4, 1 }, { 1, 2 }, { 1, 3 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 } } +}; + +static const uint32_t svq3_dequant_coeff[32] = { + 3881, 4351, 4890, 5481, 6154, 6914, 7761, 8718, + 9781, 10987, 12339, 13828, 15523, 17435, 19561, 21873, + 24552, 27656, 30847, 34870, 38807, 43747, 49103, 54683, + 61694, 68745, 77615, 89113, 100253, 109366, 126635, 141533 +}; + +void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp) +{ + const int qmul = svq3_dequant_coeff[qp]; +#define stride 16 + int i; + int temp[16]; + static const uint8_t x_offset[4] = { 0, 1 * stride, 4 * stride, 5 * stride }; + + for (i = 0; i < 4; i++) { + const int z0 = 13 * (input[4 * i + 0] + input[4 * i + 2]); + const int z1 = 13 * (input[4 * i + 0] - input[4 * i + 2]); + const int z2 = 7 * input[4 * i + 1] - 17 * input[4 * i + 3]; + const int z3 = 17 * input[4 * i + 1] + 7 * input[4 * i + 3]; + + temp[4 * i + 0] = z0 + z3; + temp[4 * i + 1] = z1 + z2; + temp[4 * i + 2] = z1 - z2; + temp[4 * i + 3] = z0 - z3; + } + + for (i = 0; i < 4; i++) { + const int offset = x_offset[i]; + const int z0 = 13 * (temp[4 * 0 + i] + temp[4 * 2 + i]); + const int z1 = 13 * (temp[4 * 0 + i] - temp[4 * 2 + i]); + const int z2 = 7 * temp[4 * 1 + i] - 17 * temp[4 * 3 + i]; + const int z3 = 17 * temp[4 * 1 + i] + 7 * temp[4 * 3 + i]; + + output[stride * 0 + offset] = (z0 + z3) * qmul + 0x80000 >> 20; + output[stride * 2 + offset] = (z1 + z2) * qmul + 0x80000 >> 20; + output[stride * 8 + offset] = (z1 - z2) * qmul + 0x80000 >> 20; + output[stride * 10 + offset] = (z0 - z3) * qmul + 0x80000 >> 20; + } +} +#undef stride + +void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, + int stride, int qp, int dc) +{ + const int qmul = svq3_dequant_coeff[qp]; + int i; + + if (dc) { + dc = 13 * 13 * (dc == 1 ? 1538 * block[0] + : qmul * (block[0] >> 3) / 2); + block[0] = 0; + } + + for (i = 0; i < 4; i++) { + const int z0 = 13 * (block[0 + 4 * i] + block[2 + 4 * i]); + const int z1 = 13 * (block[0 + 4 * i] - block[2 + 4 * i]); + const int z2 = 7 * block[1 + 4 * i] - 17 * block[3 + 4 * i]; + const int z3 = 17 * block[1 + 4 * i] + 7 * block[3 + 4 * i]; + + block[0 + 4 * i] = z0 + z3; + block[1 + 4 * i] = z1 + z2; + block[2 + 4 * i] = z1 - z2; + block[3 + 4 * i] = z0 - z3; + } + + for (i = 0; i < 4; i++) { + const int z0 = 13 * (block[i + 4 * 0] + block[i + 4 * 2]); + const int z1 = 13 * (block[i + 4 * 0] - block[i + 4 * 2]); + const int z2 = 7 * block[i + 4 * 1] - 17 * block[i + 4 * 3]; + const int z3 = 17 * block[i + 4 * 1] + 7 * block[i + 4 * 3]; + const int rr = (dc + 0x80000); + + dst[i + stride * 0] = av_clip_uint8(dst[i + stride * 0] + ((z0 + z3) * qmul + rr >> 20)); + dst[i + stride * 1] = av_clip_uint8(dst[i + stride * 1] + ((z1 + z2) * qmul + rr >> 20)); + dst[i + stride * 2] = av_clip_uint8(dst[i + stride * 2] + ((z1 - z2) * qmul + rr >> 20)); + dst[i + stride * 3] = av_clip_uint8(dst[i + stride * 3] + ((z0 - z3) * qmul + rr >> 20)); + } + + memset(block, 0, 16 * sizeof(int16_t)); +} + +static inline int svq3_decode_block(GetBitContext *gb, int16_t *block, + int index, const int type) +{ + static const uint8_t *const scan_patterns[4] = + { luma_dc_zigzag_scan, zigzag_scan, svq3_scan, chroma_dc_scan }; + + int run, level, sign, limit; + unsigned vlc; + const int intra = 3 * type >> 2; + const uint8_t *const scan = scan_patterns[type]; + + for (limit = (16 >> intra); index < 16; index = limit, limit += 8) { + for (; (vlc = svq3_get_ue_golomb(gb)) != 0; index++) { + if ((int32_t)vlc < 0) + return -1; + + sign = (vlc & 1) ? 0 : -1; + vlc = vlc + 1 >> 1; + + if (type == 3) { + if (vlc < 3) { + run = 0; + level = vlc; + } else if (vlc < 4) { + run = 1; + level = 1; + } else { + run = vlc & 0x3; + level = (vlc + 9 >> 2) - run; + } + } else { + if (vlc < 16U) { + run = svq3_dct_tables[intra][vlc].run; + level = svq3_dct_tables[intra][vlc].level; + } else if (intra) { + run = vlc & 0x7; + level = (vlc >> 3) + ((run == 0) ? 8 : ((run < 2) ? 2 : ((run < 5) ? 0 : -1))); + } else { + run = vlc & 0xF; + level = (vlc >> 4) + ((run == 0) ? 4 : ((run < 3) ? 2 : ((run < 10) ? 1 : 0))); + } + } + + + if ((index += run) >= limit) + return -1; + + block[scan[index]] = (level ^ sign) - sign; + } + + if (type != 2) { + break; + } + } + + return 0; +} + +static inline void svq3_mc_dir_part(SVQ3Context *s, + int x, int y, int width, int height, + int mx, int my, int dxy, + int thirdpel, int dir, int avg) +{ + H264Context *h = &s->h; + const Picture *pic = (dir == 0) ? s->last_pic : s->next_pic; + uint8_t *src, *dest; + int i, emu = 0; + int blocksize = 2 - (width >> 3); // 16->0, 8->1, 4->2 + + mx += x; + my += y; + + if (mx < 0 || mx >= s->h_edge_pos - width - 1 || + my < 0 || my >= s->v_edge_pos - height - 1) { + emu = 1; + mx = av_clip(mx, -16, s->h_edge_pos - width + 15); + my = av_clip(my, -16, s->v_edge_pos - height + 15); + } + + /* form component predictions */ + dest = h->cur_pic.f.data[0] + x + y * h->linesize; + src = pic->f.data[0] + mx + my * h->linesize; + + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src, h->linesize, + width + 1, height + 1, + mx, my, s->h_edge_pos, s->v_edge_pos); + src = h->edge_emu_buffer; + } + if (thirdpel) + (avg ? h->dsp.avg_tpel_pixels_tab + : h->dsp.put_tpel_pixels_tab)[dxy](dest, src, h->linesize, + width, height); + else + (avg ? s->hdsp.avg_pixels_tab + : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, h->linesize, + height); + + if (!(h->flags & CODEC_FLAG_GRAY)) { + mx = mx + (mx < (int) x) >> 1; + my = my + (my < (int) y) >> 1; + width = width >> 1; + height = height >> 1; + blocksize++; + + for (i = 1; i < 3; i++) { + dest = h->cur_pic.f.data[i] + (x >> 1) + (y >> 1) * h->uvlinesize; + src = pic->f.data[i] + mx + my * h->uvlinesize; + + if (emu) { + h->vdsp.emulated_edge_mc(h->edge_emu_buffer, src, h->uvlinesize, + width + 1, height + 1, + mx, my, (s->h_edge_pos >> 1), + s->v_edge_pos >> 1); + src = h->edge_emu_buffer; + } + if (thirdpel) + (avg ? h->dsp.avg_tpel_pixels_tab + : h->dsp.put_tpel_pixels_tab)[dxy](dest, src, + h->uvlinesize, + width, height); + else + (avg ? s->hdsp.avg_pixels_tab + : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, + h->uvlinesize, + height); + } + } +} + +static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode, + int dir, int avg) +{ + int i, j, k, mx, my, dx, dy, x, y; + H264Context *h = &s->h; + const int part_width = ((size & 5) == 4) ? 4 : 16 >> (size & 1); + const int part_height = 16 >> ((unsigned)(size + 1) / 3); + const int extra_width = (mode == PREDICT_MODE) ? -16 * 6 : 0; + const int h_edge_pos = 6 * (s->h_edge_pos - part_width) - extra_width; + const int v_edge_pos = 6 * (s->v_edge_pos - part_height) - extra_width; + + for (i = 0; i < 16; i += part_height) + for (j = 0; j < 16; j += part_width) { + const int b_xy = (4 * h->mb_x + (j >> 2)) + + (4 * h->mb_y + (i >> 2)) * h->b_stride; + int dxy; + x = 16 * h->mb_x + j; + y = 16 * h->mb_y + i; + k = (j >> 2 & 1) + (i >> 1 & 2) + + (j >> 1 & 4) + (i & 8); + + if (mode != PREDICT_MODE) { + pred_motion(h, k, part_width >> 2, dir, 1, &mx, &my); + } else { + mx = s->next_pic->motion_val[0][b_xy][0] << 1; + my = s->next_pic->motion_val[0][b_xy][1] << 1; + + if (dir == 0) { + mx = mx * h->frame_num_offset / + h->prev_frame_num_offset + 1 >> 1; + my = my * h->frame_num_offset / + h->prev_frame_num_offset + 1 >> 1; + } else { + mx = mx * (h->frame_num_offset - h->prev_frame_num_offset) / + h->prev_frame_num_offset + 1 >> 1; + my = my * (h->frame_num_offset - h->prev_frame_num_offset) / + h->prev_frame_num_offset + 1 >> 1; + } + } + + /* clip motion vector prediction to frame border */ + mx = av_clip(mx, extra_width - 6 * x, h_edge_pos - 6 * x); + my = av_clip(my, extra_width - 6 * y, v_edge_pos - 6 * y); + + /* get (optional) motion vector differential */ + if (mode == PREDICT_MODE) { + dx = dy = 0; + } else { + dy = svq3_get_se_golomb(&h->gb); + dx = svq3_get_se_golomb(&h->gb); + + if (dx == INVALID_VLC || dy == INVALID_VLC) { + av_log(h->avctx, AV_LOG_ERROR, "invalid MV vlc\n"); + return -1; + } + } + + /* compute motion vector */ + if (mode == THIRDPEL_MODE) { + int fx, fy; + mx = (mx + 1 >> 1) + dx; + my = (my + 1 >> 1) + dy; + fx = (unsigned)(mx + 0x3000) / 3 - 0x1000; + fy = (unsigned)(my + 0x3000) / 3 - 0x1000; + dxy = (mx - 3 * fx) + 4 * (my - 3 * fy); + + svq3_mc_dir_part(s, x, y, part_width, part_height, + fx, fy, dxy, 1, dir, avg); + mx += mx; + my += my; + } else if (mode == HALFPEL_MODE || mode == PREDICT_MODE) { + mx = (unsigned)(mx + 1 + 0x3000) / 3 + dx - 0x1000; + my = (unsigned)(my + 1 + 0x3000) / 3 + dy - 0x1000; + dxy = (mx & 1) + 2 * (my & 1); + + svq3_mc_dir_part(s, x, y, part_width, part_height, + mx >> 1, my >> 1, dxy, 0, dir, avg); + mx *= 3; + my *= 3; + } else { + mx = (unsigned)(mx + 3 + 0x6000) / 6 + dx - 0x1000; + my = (unsigned)(my + 3 + 0x6000) / 6 + dy - 0x1000; + + svq3_mc_dir_part(s, x, y, part_width, part_height, + mx, my, 0, 0, dir, avg); + mx *= 6; + my *= 6; + } + + /* update mv_cache */ + if (mode != PREDICT_MODE) { + int32_t mv = pack16to32(mx, my); + + if (part_height == 8 && i < 8) { + AV_WN32A(h->mv_cache[dir][scan8[k] + 1 * 8], mv); + + if (part_width == 8 && j < 8) + AV_WN32A(h->mv_cache[dir][scan8[k] + 1 + 1 * 8], mv); + } + if (part_width == 8 && j < 8) + AV_WN32A(h->mv_cache[dir][scan8[k] + 1], mv); + if (part_width == 4 || part_height == 4) + AV_WN32A(h->mv_cache[dir][scan8[k]], mv); + } + + /* write back motion vectors */ + fill_rectangle(h->cur_pic.motion_val[dir][b_xy], + part_width >> 2, part_height >> 2, h->b_stride, + pack16to32(mx, my), 4); + } + + return 0; +} + +static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) +{ + H264Context *h = &s->h; + int i, j, k, m, dir, mode; + int cbp = 0; + uint32_t vlc; + int8_t *top, *left; + const int mb_xy = h->mb_xy; + const int b_xy = 4 * h->mb_x + 4 * h->mb_y * h->b_stride; + + h->top_samples_available = (h->mb_y == 0) ? 0x33FF : 0xFFFF; + h->left_samples_available = (h->mb_x == 0) ? 0x5F5F : 0xFFFF; + h->topright_samples_available = 0xFFFF; + + if (mb_type == 0) { /* SKIP */ + if (h->pict_type == AV_PICTURE_TYPE_P || + s->next_pic->mb_type[mb_xy] == -1) { + svq3_mc_dir_part(s, 16 * h->mb_x, 16 * h->mb_y, 16, 16, + 0, 0, 0, 0, 0, 0); + + if (h->pict_type == AV_PICTURE_TYPE_B) + svq3_mc_dir_part(s, 16 * h->mb_x, 16 * h->mb_y, 16, 16, + 0, 0, 0, 0, 1, 1); + + mb_type = MB_TYPE_SKIP; + } else { + mb_type = FFMIN(s->next_pic->mb_type[mb_xy], 6); + if (svq3_mc_dir(s, mb_type, PREDICT_MODE, 0, 0) < 0) + return -1; + if (svq3_mc_dir(s, mb_type, PREDICT_MODE, 1, 1) < 0) + return -1; + + mb_type = MB_TYPE_16x16; + } + } else if (mb_type < 8) { /* INTER */ + if (s->thirdpel_flag && s->halfpel_flag == !get_bits1(&h->gb)) + mode = THIRDPEL_MODE; + else if (s->halfpel_flag && + s->thirdpel_flag == !get_bits1(&h->gb)) + mode = HALFPEL_MODE; + else + mode = FULLPEL_MODE; + + /* fill caches */ + /* note ref_cache should contain here: + * ???????? + * ???11111 + * N??11111 + * N??11111 + * N??11111 + */ + + for (m = 0; m < 2; m++) { + if (h->mb_x > 0 && h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6] != -1) { + for (i = 0; i < 4; i++) + AV_COPY32(h->mv_cache[m][scan8[0] - 1 + i * 8], + h->cur_pic.motion_val[m][b_xy - 1 + i * h->b_stride]); + } else { + for (i = 0; i < 4; i++) + AV_ZERO32(h->mv_cache[m][scan8[0] - 1 + i * 8]); + } + if (h->mb_y > 0) { + memcpy(h->mv_cache[m][scan8[0] - 1 * 8], + h->cur_pic.motion_val[m][b_xy - h->b_stride], + 4 * 2 * sizeof(int16_t)); + memset(&h->ref_cache[m][scan8[0] - 1 * 8], + (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4); + + if (h->mb_x < h->mb_width - 1) { + AV_COPY32(h->mv_cache[m][scan8[0] + 4 - 1 * 8], + h->cur_pic.motion_val[m][b_xy - h->b_stride + 4]); + h->ref_cache[m][scan8[0] + 4 - 1 * 8] = + (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride + 1] + 6] == -1 || + h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1; + } else + h->ref_cache[m][scan8[0] + 4 - 1 * 8] = PART_NOT_AVAILABLE; + if (h->mb_x > 0) { + AV_COPY32(h->mv_cache[m][scan8[0] - 1 - 1 * 8], + h->cur_pic.motion_val[m][b_xy - h->b_stride - 1]); + h->ref_cache[m][scan8[0] - 1 - 1 * 8] = + (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride - 1] + 3] == -1) ? PART_NOT_AVAILABLE : 1; + } else + h->ref_cache[m][scan8[0] - 1 - 1 * 8] = PART_NOT_AVAILABLE; + } else + memset(&h->ref_cache[m][scan8[0] - 1 * 8 - 1], + PART_NOT_AVAILABLE, 8); + + if (h->pict_type != AV_PICTURE_TYPE_B) + break; + } + + /* decode motion vector(s) and form prediction(s) */ + if (h->pict_type == AV_PICTURE_TYPE_P) { + if (svq3_mc_dir(s, mb_type - 1, mode, 0, 0) < 0) + return -1; + } else { /* AV_PICTURE_TYPE_B */ + if (mb_type != 2) { + if (svq3_mc_dir(s, 0, mode, 0, 0) < 0) + return -1; + } else { + for (i = 0; i < 4; i++) + memset(h->cur_pic.motion_val[0][b_xy + i * h->b_stride], + 0, 4 * 2 * sizeof(int16_t)); + } + if (mb_type != 1) { + if (svq3_mc_dir(s, 0, mode, 1, mb_type == 3) < 0) + return -1; + } else { + for (i = 0; i < 4; i++) + memset(h->cur_pic.motion_val[1][b_xy + i * h->b_stride], + 0, 4 * 2 * sizeof(int16_t)); + } + } + + mb_type = MB_TYPE_16x16; + } else if (mb_type == 8 || mb_type == 33) { /* INTRA4x4 */ + memset(h->intra4x4_pred_mode_cache, -1, 8 * 5 * sizeof(int8_t)); + + if (mb_type == 8) { + if (h->mb_x > 0) { + for (i = 0; i < 4; i++) + h->intra4x4_pred_mode_cache[scan8[0] - 1 + i * 8] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6 - i]; + if (h->intra4x4_pred_mode_cache[scan8[0] - 1] == -1) + h->left_samples_available = 0x5F5F; + } + if (h->mb_y > 0) { + h->intra4x4_pred_mode_cache[4 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 0]; + h->intra4x4_pred_mode_cache[5 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 1]; + h->intra4x4_pred_mode_cache[6 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 2]; + h->intra4x4_pred_mode_cache[7 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 3]; + + if (h->intra4x4_pred_mode_cache[4 + 8 * 0] == -1) + h->top_samples_available = 0x33FF; + } + + /* decode prediction codes for luma blocks */ + for (i = 0; i < 16; i += 2) { + vlc = svq3_get_ue_golomb(&h->gb); + + if (vlc >= 25U) { + av_log(h->avctx, AV_LOG_ERROR, "luma prediction:%d\n", vlc); + return -1; + } + + left = &h->intra4x4_pred_mode_cache[scan8[i] - 1]; + top = &h->intra4x4_pred_mode_cache[scan8[i] - 8]; + + left[1] = svq3_pred_1[top[0] + 1][left[0] + 1][svq3_pred_0[vlc][0]]; + left[2] = svq3_pred_1[top[1] + 1][left[1] + 1][svq3_pred_0[vlc][1]]; + + if (left[1] == -1 || left[2] == -1) { + av_log(h->avctx, AV_LOG_ERROR, "weird prediction\n"); + return -1; + } + } + } else { /* mb_type == 33, DC_128_PRED block type */ + for (i = 0; i < 4; i++) + memset(&h->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_PRED, 4); + } + + write_back_intra_pred_mode(h); + + if (mb_type == 8) { + ff_h264_check_intra4x4_pred_mode(h); + + h->top_samples_available = (h->mb_y == 0) ? 0x33FF : 0xFFFF; + h->left_samples_available = (h->mb_x == 0) ? 0x5F5F : 0xFFFF; + } else { + for (i = 0; i < 4; i++) + memset(&h->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_128_PRED, 4); + + h->top_samples_available = 0x33FF; + h->left_samples_available = 0x5F5F; + } + + mb_type = MB_TYPE_INTRA4x4; + } else { /* INTRA16x16 */ + dir = i_mb_type_info[mb_type - 8].pred_mode; + dir = (dir >> 1) ^ 3 * (dir & 1) ^ 1; + + if ((h->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, dir, 0)) == -1) { + av_log(h->avctx, AV_LOG_ERROR, "check_intra_pred_mode = -1\n"); + return -1; + } + + cbp = i_mb_type_info[mb_type - 8].cbp; + mb_type = MB_TYPE_INTRA16x16; + } + + if (!IS_INTER(mb_type) && h->pict_type != AV_PICTURE_TYPE_I) { + for (i = 0; i < 4; i++) + memset(h->cur_pic.motion_val[0][b_xy + i * h->b_stride], + 0, 4 * 2 * sizeof(int16_t)); + if (h->pict_type == AV_PICTURE_TYPE_B) { + for (i = 0; i < 4; i++) + memset(h->cur_pic.motion_val[1][b_xy + i * h->b_stride], + 0, 4 * 2 * sizeof(int16_t)); + } + } + if (!IS_INTRA4x4(mb_type)) { + memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy], DC_PRED, 8); + } + if (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B) { + memset(h->non_zero_count_cache + 8, 0, 14 * 8 * sizeof(uint8_t)); + } + + if (!IS_INTRA16x16(mb_type) && + (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B)) { + if ((vlc = svq3_get_ue_golomb(&h->gb)) >= 48U){ + av_log(h->avctx, AV_LOG_ERROR, "cbp_vlc=%d\n", vlc); + return -1; + } + + cbp = IS_INTRA(mb_type) ? golomb_to_intra4x4_cbp[vlc] + : golomb_to_inter_cbp[vlc]; + } + if (IS_INTRA16x16(mb_type) || + (h->pict_type != AV_PICTURE_TYPE_I && s->adaptive_quant && cbp)) { + h->qscale += svq3_get_se_golomb(&h->gb); + + if (h->qscale > 31u) { + av_log(h->avctx, AV_LOG_ERROR, "qscale:%d\n", h->qscale); + return -1; + } + } + if (IS_INTRA16x16(mb_type)) { + AV_ZERO128(h->mb_luma_dc[0] + 0); + AV_ZERO128(h->mb_luma_dc[0] + 8); + if (svq3_decode_block(&h->gb, h->mb_luma_dc[0], 0, 1)) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding intra luma dc\n"); + return -1; + } + } + + if (cbp) { + const int index = IS_INTRA16x16(mb_type) ? 1 : 0; + const int type = ((h->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1); + + for (i = 0; i < 4; i++) + if ((cbp & (1 << i))) { + for (j = 0; j < 4; j++) { + k = index ? (1 * (j & 1) + 2 * (i & 1) + + 2 * (j & 2) + 4 * (i & 2)) + : (4 * i + j); + h->non_zero_count_cache[scan8[k]] = 1; + + if (svq3_decode_block(&h->gb, &h->mb[16 * k], index, type)) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding block\n"); + return -1; + } + } + } + + if ((cbp & 0x30)) { + for (i = 1; i < 3; ++i) + if (svq3_decode_block(&h->gb, &h->mb[16 * 16 * i], 0, 3)) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding chroma dc block\n"); + return -1; + } + + if ((cbp & 0x20)) { + for (i = 1; i < 3; i++) { + for (j = 0; j < 4; j++) { + k = 16 * i + j; + h->non_zero_count_cache[scan8[k]] = 1; + + if (svq3_decode_block(&h->gb, &h->mb[16 * k], 1, 1)) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding chroma ac block\n"); + return -1; + } + } + } + } + } + } + + h->cbp = cbp; + h->cur_pic.mb_type[mb_xy] = mb_type; + + if (IS_INTRA(mb_type)) + h->chroma_pred_mode = ff_h264_check_intra_pred_mode(h, DC_PRED8x8, 1); + + return 0; +} + +static int svq3_decode_slice_header(AVCodecContext *avctx) +{ + SVQ3Context *s = avctx->priv_data; + H264Context *h = &s->h; + const int mb_xy = h->mb_xy; + int i, header; + unsigned slice_id; + + header = get_bits(&h->gb, 8); + + if (((header & 0x9F) != 1 && (header & 0x9F) != 2) || (header & 0x60) == 0) { + /* TODO: what? */ + av_log(avctx, AV_LOG_ERROR, "unsupported slice header (%02X)\n", header); + return -1; + } else { + int length = header >> 5 & 3; + + s->next_slice_index = get_bits_count(&h->gb) + + 8 * show_bits(&h->gb, 8 * length) + + 8 * length; + + if (s->next_slice_index > h->gb.size_in_bits) { + av_log(avctx, AV_LOG_ERROR, "slice after bitstream end\n"); + return -1; + } + + h->gb.size_in_bits = s->next_slice_index - 8 * (length - 1); + skip_bits(&h->gb, 8); + + if (s->watermark_key) { + uint32_t header = AV_RL32(&h->gb.buffer[(get_bits_count(&h->gb) >> 3) + 1]); + AV_WL32(&h->gb.buffer[(get_bits_count(&h->gb) >> 3) + 1], + header ^ s->watermark_key); + } + if (length > 0) { + memcpy((uint8_t *) &h->gb.buffer[get_bits_count(&h->gb) >> 3], + &h->gb.buffer[h->gb.size_in_bits >> 3], length - 1); + } + skip_bits_long(&h->gb, 0); + } + + if ((slice_id = svq3_get_ue_golomb(&h->gb)) >= 3) { + av_log(h->avctx, AV_LOG_ERROR, "illegal slice type %d \n", slice_id); + return -1; + } + + h->slice_type = golomb_to_pict_type[slice_id]; + + if ((header & 0x9F) == 2) { + i = (h->mb_num < 64) ? 6 : (1 + av_log2(h->mb_num - 1)); + h->mb_skip_run = get_bits(&h->gb, i) - + (h->mb_y * h->mb_width + h->mb_x); + } else { + skip_bits1(&h->gb); + h->mb_skip_run = 0; + } + + h->slice_num = get_bits(&h->gb, 8); + h->qscale = get_bits(&h->gb, 5); + s->adaptive_quant = get_bits1(&h->gb); + + /* unknown fields */ + skip_bits1(&h->gb); + + if (s->unknown_flag) + skip_bits1(&h->gb); + + skip_bits1(&h->gb); + skip_bits(&h->gb, 2); + + while (get_bits1(&h->gb)) + skip_bits(&h->gb, 8); + + /* reset intra predictors and invalidate motion vector references */ + if (h->mb_x > 0) { + memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - 1] + 3, + -1, 4 * sizeof(int8_t)); + memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - h->mb_x], + -1, 8 * sizeof(int8_t) * h->mb_x); + } + if (h->mb_y > 0) { + memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - h->mb_stride], + -1, 8 * sizeof(int8_t) * (h->mb_width - h->mb_x)); + + if (h->mb_x > 0) + h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride - 1] + 3] = -1; + } + + return 0; +} + +static av_cold int svq3_decode_init(AVCodecContext *avctx) +{ + SVQ3Context *s = avctx->priv_data; + H264Context *h = &s->h; + int m; + unsigned char *extradata; + unsigned char *extradata_end; + unsigned int size; + int marker_found = 0; + + s->cur_pic = av_mallocz(sizeof(*s->cur_pic)); + s->last_pic = av_mallocz(sizeof(*s->last_pic)); + s->next_pic = av_mallocz(sizeof(*s->next_pic)); + if (!s->next_pic || !s->last_pic || !s->cur_pic) { + av_freep(&s->cur_pic); + av_freep(&s->last_pic); + av_freep(&s->next_pic); + return AVERROR(ENOMEM); + } + + if (ff_h264_decode_init(avctx) < 0) + return -1; + + ff_hpeldsp_init(&s->hdsp, avctx->flags); + h->flags = avctx->flags; + h->is_complex = 1; + h->sps.chroma_format_idc = 1; + h->picture_structure = PICT_FRAME; + avctx->pix_fmt = avctx->codec->pix_fmts[0]; + + h->chroma_qp[0] = h->chroma_qp[1] = 4; + h->chroma_x_shift = h->chroma_y_shift = 1; + + s->halfpel_flag = 1; + s->thirdpel_flag = 1; + s->unknown_flag = 0; + + /* prowl for the "SEQH" marker in the extradata */ + extradata = (unsigned char *)avctx->extradata; + extradata_end = avctx->extradata + avctx->extradata_size; + if (extradata) { + for (m = 0; m + 8 < avctx->extradata_size; m++) { + if (!memcmp(extradata, "SEQH", 4)) { + marker_found = 1; + break; + } + extradata++; + } + } + + /* if a match was found, parse the extra data */ + if (marker_found) { + GetBitContext gb; + int frame_size_code; + + size = AV_RB32(&extradata[4]); + if (size > extradata_end - extradata - 8) + return AVERROR_INVALIDDATA; + init_get_bits(&gb, extradata + 8, size * 8); + + /* 'frame size code' and optional 'width, height' */ + frame_size_code = get_bits(&gb, 3); + switch (frame_size_code) { + case 0: + avctx->width = 160; + avctx->height = 120; + break; + case 1: + avctx->width = 128; + avctx->height = 96; + break; + case 2: + avctx->width = 176; + avctx->height = 144; + break; + case 3: + avctx->width = 352; + avctx->height = 288; + break; + case 4: + avctx->width = 704; + avctx->height = 576; + break; + case 5: + avctx->width = 240; + avctx->height = 180; + break; + case 6: + avctx->width = 320; + avctx->height = 240; + break; + case 7: + avctx->width = get_bits(&gb, 12); + avctx->height = get_bits(&gb, 12); + break; + } + + s->halfpel_flag = get_bits1(&gb); + s->thirdpel_flag = get_bits1(&gb); + + /* unknown fields */ + skip_bits1(&gb); + skip_bits1(&gb); + skip_bits1(&gb); + skip_bits1(&gb); + + h->low_delay = get_bits1(&gb); + + /* unknown field */ + skip_bits1(&gb); + + while (get_bits1(&gb)) + skip_bits(&gb, 8); + + s->unknown_flag = get_bits1(&gb); + avctx->has_b_frames = !h->low_delay; + if (s->unknown_flag) { +#if CONFIG_ZLIB + unsigned watermark_width = svq3_get_ue_golomb(&gb); + unsigned watermark_height = svq3_get_ue_golomb(&gb); + int u1 = svq3_get_ue_golomb(&gb); + int u2 = get_bits(&gb, 8); + int u3 = get_bits(&gb, 2); + int u4 = svq3_get_ue_golomb(&gb); + unsigned long buf_len = watermark_width * + watermark_height * 4; + int offset = get_bits_count(&gb) + 7 >> 3; + uint8_t *buf; + + if (watermark_height <= 0 || (uint64_t)watermark_width*4 > UINT_MAX/watermark_height) + return -1; + + buf = av_malloc(buf_len); + av_log(avctx, AV_LOG_DEBUG, "watermark size: %dx%d\n", + watermark_width, watermark_height); + av_log(avctx, AV_LOG_DEBUG, + "u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n", + u1, u2, u3, u4, offset); + if (uncompress(buf, &buf_len, extradata + 8 + offset, + size - offset) != Z_OK) { + av_log(avctx, AV_LOG_ERROR, + "could not uncompress watermark logo\n"); + av_free(buf); + return -1; + } + s->watermark_key = ff_svq1_packet_checksum(buf, buf_len, 0); + s->watermark_key = s->watermark_key << 16 | s->watermark_key; + av_log(avctx, AV_LOG_DEBUG, + "watermark key %#x\n", s->watermark_key); + av_free(buf); +#else + av_log(avctx, AV_LOG_ERROR, + "this svq3 file contains watermark which need zlib support compiled in\n"); + return -1; +#endif + } + } + + h->width = avctx->width; + h->height = avctx->height; + h->mb_width = (h->width + 15) / 16; + h->mb_height = (h->height + 15) / 16; + h->mb_stride = h->mb_width + 1; + h->mb_num = h->mb_width * h->mb_height; + h->b_stride = 4 * h->mb_width; + s->h_edge_pos = h->mb_width * 16; + s->v_edge_pos = h->mb_height * 16; + + if (ff_h264_alloc_tables(h) < 0) { + av_log(avctx, AV_LOG_ERROR, "svq3 memory allocation failed\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static void free_picture(AVCodecContext *avctx, Picture *pic) +{ + int i; + for (i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } + av_buffer_unref(&pic->mb_type_buf); + + av_frame_unref(&pic->f); +} + +static int get_buffer(AVCodecContext *avctx, Picture *pic) +{ + SVQ3Context *s = avctx->priv_data; + H264Context *h = &s->h; + const int big_mb_num = h->mb_stride * (h->mb_height + 1) + 1; + const int mb_array_size = h->mb_stride * h->mb_height; + const int b4_stride = h->mb_width * 4 + 1; + const int b4_array_size = b4_stride * h->mb_height * 4; + int ret; + + if (!pic->motion_val_buf[0]) { + int i; + + pic->mb_type_buf = av_buffer_allocz((big_mb_num + h->mb_stride) * sizeof(uint32_t)); + if (!pic->mb_type_buf) + return AVERROR(ENOMEM); + pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * h->mb_stride + 1; + + for (i = 0; i < 2; i++) { + pic->motion_val_buf[i] = av_buffer_allocz(2 * (b4_array_size + 4) * sizeof(int16_t)); + pic->ref_index_buf[i] = av_buffer_allocz(4 * mb_array_size); + if (!pic->motion_val_buf[i] || !pic->ref_index_buf[i]) { + ret = AVERROR(ENOMEM); + goto fail; + } + + pic->motion_val[i] = (int16_t (*)[2])pic->motion_val_buf[i]->data + 4; + pic->ref_index[i] = pic->ref_index_buf[i]->data; + } + } + pic->reference = !(h->pict_type == AV_PICTURE_TYPE_B); + + ret = ff_get_buffer(avctx, &pic->f, + pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); + if (ret < 0) + goto fail; + + if (!h->edge_emu_buffer) { + h->edge_emu_buffer = av_mallocz(pic->f.linesize[0] * 17); + if (!h->edge_emu_buffer) + return AVERROR(ENOMEM); + } + + h->linesize = pic->f.linesize[0]; + h->uvlinesize = pic->f.linesize[1]; + + return 0; +fail: + free_picture(avctx, pic); + return ret; +} + +static int svq3_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + SVQ3Context *s = avctx->priv_data; + H264Context *h = &s->h; + int buf_size = avpkt->size; + int left; + uint8_t *buf; + int ret, m, i; + + /* special case for last picture */ + if (buf_size == 0) { + if (s->next_pic->f.data[0] && !h->low_delay && !s->last_frame_output) { + ret = av_frame_ref(data, &s->next_pic->f); + if (ret < 0) + return ret; + s->last_frame_output = 1; + *got_frame = 1; + } + return 0; + } + + h->mb_x = h->mb_y = h->mb_xy = 0; + + if (s->watermark_key) { + av_fast_malloc(&s->buf, &s->buf_size, + buf_size+FF_INPUT_BUFFER_PADDING_SIZE); + if (!s->buf) + return AVERROR(ENOMEM); + memcpy(s->buf, avpkt->data, buf_size); + buf = s->buf; + } else { + buf = avpkt->data; + } + + init_get_bits(&h->gb, buf, 8 * buf_size); + + if (svq3_decode_slice_header(avctx)) + return -1; + + h->pict_type = h->slice_type; + + if (h->pict_type != AV_PICTURE_TYPE_B) + FFSWAP(Picture*, s->next_pic, s->last_pic); + + av_frame_unref(&s->cur_pic->f); + + /* for skipping the frame */ + s->cur_pic->f.pict_type = h->pict_type; + s->cur_pic->f.key_frame = (h->pict_type == AV_PICTURE_TYPE_I); + + ret = get_buffer(avctx, s->cur_pic); + if (ret < 0) + return ret; + + h->cur_pic_ptr = s->cur_pic; + av_frame_unref(&h->cur_pic.f); + h->cur_pic = *s->cur_pic; + ret = av_frame_ref(&h->cur_pic.f, &s->cur_pic->f); + if (ret < 0) + return ret; + + for (i = 0; i < 16; i++) { + h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * h->linesize * ((scan8[i] - scan8[0]) >> 3); + } + for (i = 0; i < 16; i++) { + h->block_offset[16 + i] = + h->block_offset[32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + h->block_offset[48 + 16 + i] = + h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * h->uvlinesize * ((scan8[i] - scan8[0]) >> 3); + } + + if (h->pict_type != AV_PICTURE_TYPE_I) { + if (!s->last_pic->f.data[0]) { + av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); + ret = get_buffer(avctx, s->last_pic); + if (ret < 0) + return ret; + memset(s->last_pic->f.data[0], 0, avctx->height * s->last_pic->f.linesize[0]); + memset(s->last_pic->f.data[1], 0x80, (avctx->height / 2) * + s->last_pic->f.linesize[1]); + memset(s->last_pic->f.data[2], 0x80, (avctx->height / 2) * + s->last_pic->f.linesize[2]); + } + + if (h->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f.data[0]) { + av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); + ret = get_buffer(avctx, s->next_pic); + if (ret < 0) + return ret; + memset(s->next_pic->f.data[0], 0, avctx->height * s->next_pic->f.linesize[0]); + memset(s->next_pic->f.data[1], 0x80, (avctx->height / 2) * + s->next_pic->f.linesize[1]); + memset(s->next_pic->f.data[2], 0x80, (avctx->height / 2) * + s->next_pic->f.linesize[2]); + } + } + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(h->avctx, AV_LOG_DEBUG, + "%c hpel:%d, tpel:%d aqp:%d qp:%d, slice_num:%02X\n", + av_get_picture_type_char(h->pict_type), + s->halfpel_flag, s->thirdpel_flag, + s->adaptive_quant, h->qscale, h->slice_num); + + if (avctx->skip_frame >= AVDISCARD_NONREF && h->pict_type == AV_PICTURE_TYPE_B || + avctx->skip_frame >= AVDISCARD_NONKEY && h->pict_type != AV_PICTURE_TYPE_I || + avctx->skip_frame >= AVDISCARD_ALL) + return 0; + + if (s->next_p_frame_damaged) { + if (h->pict_type == AV_PICTURE_TYPE_B) + return 0; + else + s->next_p_frame_damaged = 0; + } + + if (h->pict_type == AV_PICTURE_TYPE_B) { + h->frame_num_offset = h->slice_num - h->prev_frame_num; + + if (h->frame_num_offset < 0) + h->frame_num_offset += 256; + if (h->frame_num_offset == 0 || + h->frame_num_offset >= h->prev_frame_num_offset) { + av_log(h->avctx, AV_LOG_ERROR, "error in B-frame picture id\n"); + return -1; + } + } else { + h->prev_frame_num = h->frame_num; + h->frame_num = h->slice_num; + h->prev_frame_num_offset = h->frame_num - h->prev_frame_num; + + if (h->prev_frame_num_offset < 0) + h->prev_frame_num_offset += 256; + } + + for (m = 0; m < 2; m++) { + int i; + for (i = 0; i < 4; i++) { + int j; + for (j = -1; j < 4; j++) + h->ref_cache[m][scan8[0] + 8 * i + j] = 1; + if (i < 3) + h->ref_cache[m][scan8[0] + 8 * i + j] = PART_NOT_AVAILABLE; + } + } + + for (h->mb_y = 0; h->mb_y < h->mb_height; h->mb_y++) { + for (h->mb_x = 0; h->mb_x < h->mb_width; h->mb_x++) { + unsigned mb_type; + h->mb_xy = h->mb_x + h->mb_y * h->mb_stride; + + if ((get_bits_count(&h->gb) + 7) >= h->gb.size_in_bits && + ((get_bits_count(&h->gb) & 7) == 0 || + show_bits(&h->gb, -get_bits_count(&h->gb) & 7) == 0)) { + skip_bits(&h->gb, s->next_slice_index - get_bits_count(&h->gb)); + h->gb.size_in_bits = 8 * buf_size; + + if (svq3_decode_slice_header(avctx)) + return -1; + + /* TODO: support s->mb_skip_run */ + } + + mb_type = svq3_get_ue_golomb(&h->gb); + + if (h->pict_type == AV_PICTURE_TYPE_I) + mb_type += 8; + else if (h->pict_type == AV_PICTURE_TYPE_B && mb_type >= 4) + mb_type += 4; + if (mb_type > 33 || svq3_decode_mb(s, mb_type)) { + av_log(h->avctx, AV_LOG_ERROR, + "error while decoding MB %d %d\n", h->mb_x, h->mb_y); + return -1; + } + + if (mb_type != 0 || h->cbp) + ff_h264_hl_decode_mb(h); + + if (h->pict_type != AV_PICTURE_TYPE_B && !h->low_delay) + h->cur_pic.mb_type[h->mb_x + h->mb_y * h->mb_stride] = + (h->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1; + } + + ff_draw_horiz_band(avctx, NULL, s->cur_pic, s->last_pic->f.data[0] ? s->last_pic : NULL, + 16 * h->mb_y, 16, h->picture_structure, 0, 0, + h->low_delay, h->mb_height * 16, h->mb_width * 16); + } + + left = buf_size*8 - get_bits_count(&h->gb); + + if (h->mb_y != h->mb_height || h->mb_x != h->mb_width) { + av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, h->mb_y, h->mb_x, left); + //av_hex_dump(stderr, buf+buf_size-8, 8); + } + + if (left < 0) { + av_log(avctx, AV_LOG_ERROR, "frame num %d left %d\n", avctx->frame_number, left); + return -1; + } + + if (h->pict_type == AV_PICTURE_TYPE_B || h->low_delay) + ret = av_frame_ref(data, &s->cur_pic->f); + else if (s->last_pic->f.data[0]) + ret = av_frame_ref(data, &s->last_pic->f); + if (ret < 0) + return ret; + + /* Do not output the last pic after seeking. */ + if (s->last_pic->f.data[0] || h->low_delay) + *got_frame = 1; + + if (h->pict_type != AV_PICTURE_TYPE_B) { + FFSWAP(Picture*, s->cur_pic, s->next_pic); + } else { + av_frame_unref(&s->cur_pic->f); + } + + return buf_size; +} + +static int svq3_decode_end(AVCodecContext *avctx) +{ + SVQ3Context *s = avctx->priv_data; + H264Context *h = &s->h; + + free_picture(avctx, s->cur_pic); + free_picture(avctx, s->next_pic); + free_picture(avctx, s->last_pic); + av_freep(&s->cur_pic); + av_freep(&s->next_pic); + av_freep(&s->last_pic); + + av_frame_unref(&h->cur_pic.f); + + ff_h264_free_context(h); + + av_freep(&s->buf); + s->buf_size = 0; + av_freep(&h->edge_emu_buffer); + + return 0; +} + +AVCodec ff_svq3_decoder = { + .name = "svq3", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_SVQ3, + .priv_data_size = sizeof(SVQ3Context), + .init = svq3_decode_init, + .close = svq3_decode_end, + .decode = svq3_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_DR1 | + CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 3 / Sorenson Video 3 / SVQ3"), + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_NONE}, +}; diff --git a/ffmpeg/libavcodec/svq3.h b/ffmpeg/libavcodec/svq3.h new file mode 100644 index 0000000..7a57d8a --- /dev/null +++ b/ffmpeg/libavcodec/svq3.h @@ -0,0 +1,27 @@ +/* + * 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 + */ + +#ifndef AVCODEC_SVQ3_H +#define AVCODEC_SVQ3_H + +#include + +void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp); +void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, int stride, int qp, int dc); + +#endif /* AVCODEC_DSPUTIL_H */ diff --git a/ffmpeg/libavcodec/synth_filter.c b/ffmpeg/libavcodec/synth_filter.c new file mode 100644 index 0000000..5f10530 --- /dev/null +++ b/ffmpeg/libavcodec/synth_filter.c @@ -0,0 +1,64 @@ +/* + * copyright (c) 2008 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 "fft.h" +#include "synth_filter.h" + +static void synth_filter_float(FFTContext *imdct, + float *synth_buf_ptr, int *synth_buf_offset, + float synth_buf2[32], const float window[512], + float out[32], const float in[32], float scale) +{ + float *synth_buf= synth_buf_ptr + *synth_buf_offset; + int i, j; + + imdct->imdct_half(imdct, synth_buf, in); + + for (i = 0; i < 16; i++){ + float a= synth_buf2[i ]; + float b= synth_buf2[i + 16]; + float c= 0; + float d= 0; + for (j = 0; j < 512 - *synth_buf_offset; j += 64){ + a += window[i + j ]*(-synth_buf[15 - i + j ]); + b += window[i + j + 16]*( synth_buf[ i + j ]); + c += window[i + j + 32]*( synth_buf[16 + i + j ]); + d += window[i + j + 48]*( synth_buf[31 - i + j ]); + } + for ( ; j < 512; j += 64){ + a += window[i + j ]*(-synth_buf[15 - i + j - 512]); + b += window[i + j + 16]*( synth_buf[ i + j - 512]); + c += window[i + j + 32]*( synth_buf[16 + i + j - 512]); + d += window[i + j + 48]*( synth_buf[31 - i + j - 512]); + } + out[i ] = a*scale; + out[i + 16] = b*scale; + synth_buf2[i ] = c; + synth_buf2[i + 16] = d; + } + *synth_buf_offset= (*synth_buf_offset - 32)&511; +} + +av_cold void ff_synth_filter_init(SynthFilterContext *c) +{ + c->synth_filter_float = synth_filter_float; + + if (ARCH_ARM) ff_synth_filter_init_arm(c); +} diff --git a/ffmpeg/libavcodec/synth_filter.h b/ffmpeg/libavcodec/synth_filter.h new file mode 100644 index 0000000..33edcc4 --- /dev/null +++ b/ffmpeg/libavcodec/synth_filter.h @@ -0,0 +1,37 @@ +/* + * copyright (c) 2008 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 + */ + +#ifndef AVCODEC_SYNTH_FILTER_H +#define AVCODEC_SYNTH_FILTER_H + +#include "fft.h" + +typedef struct SynthFilterContext { + void (*synth_filter_float)(FFTContext *imdct, + float *synth_buf_ptr, int *synth_buf_offset, + float synth_buf2[32], const float window[512], + float out[32], const float in[32], + float scale); +} SynthFilterContext; + +void ff_synth_filter_init(SynthFilterContext *c); +void ff_synth_filter_init_arm(SynthFilterContext *c); + +#endif /* AVCODEC_SYNTH_FILTER_H */ diff --git a/ffmpeg/libavcodec/tableprint.h b/ffmpeg/libavcodec/tableprint.h new file mode 100644 index 0000000..1b39dc6 --- /dev/null +++ b/ffmpeg/libavcodec/tableprint.h @@ -0,0 +1,111 @@ +/* + * Generate a file for hardcoded tables + * + * Copyright (c) 2009 Reimar Döffinger + * + * 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 + */ + +#ifndef AVCODEC_TABLEPRINT_H +#define AVCODEC_TABLEPRINT_H + +#include +#include + +#include "libavutil/common.h" + +#define WRITE_1D_FUNC_ARGV(type, linebrk, fmtstr, ...)\ +void write_##type##_array(const type *data, int len)\ +{\ + int i;\ + printf(" ");\ + for (i = 0; i < len - 1; i++) {\ + printf(" "fmtstr",", __VA_ARGS__);\ + if ((i & linebrk) == linebrk) printf("\n ");\ + }\ + printf(" "fmtstr"\n", __VA_ARGS__);\ +} + +#define WRITE_1D_FUNC(type, fmtstr, linebrk)\ + WRITE_1D_FUNC_ARGV(type, linebrk, fmtstr, data[i]) + +#define WRITE_2D_FUNC(type)\ +void write_##type##_2d_array(const void *arg, int len, int len2)\ +{\ + const type *data = arg;\ + int i;\ + printf(" {\n");\ + for (i = 0; i < len; i++) {\ + write_##type##_array(data + i * len2, len2);\ + printf(i == len - 1 ? " }\n" : " }, {\n");\ + }\ +} + +/** + * @name Predefined functions for printing tables + * + * @{ + */ +void write_int8_t_array (const int8_t *, int); +void write_uint8_t_array (const uint8_t *, int); +void write_uint16_t_array (const uint16_t *, int); +void write_uint32_t_array (const uint32_t *, int); +void write_float_array (const float *, int); +void write_int8_t_2d_array (const void *, int, int); +void write_uint8_t_2d_array (const void *, int, int); +void write_uint32_t_2d_array(const void *, int, int); +void write_float_2d_array (const void *, int, int); +/** @} */ // end of printfuncs group + +#define WRITE_ARRAY(prefix, type, name) \ + do { \ + const size_t array_size = FF_ARRAY_ELEMS(name); \ + printf(prefix" "#type" "#name"[%zu] = {\n", \ + array_size); \ + write_##type##_array(name, array_size); \ + printf("};\n"); \ + } while(0) + +#define WRITE_2D_ARRAY(prefix, type, name) \ + do { \ + const size_t array_size1 = FF_ARRAY_ELEMS(name); \ + const size_t array_size2 = FF_ARRAY_ELEMS(name[0]); \ + printf(prefix" "#type" "#name"[%zu][%zu] = {\n", \ + array_size1, array_size2 ); \ + write_##type##_2d_array(name, array_size1, array_size2); \ + printf("};\n"); \ + } while(0) + + +WRITE_1D_FUNC(int8_t, "%3"PRIi8, 15) +WRITE_1D_FUNC(uint8_t, "0x%02"PRIx8, 15) +WRITE_1D_FUNC(uint16_t, "0x%08"PRIx16, 7) +WRITE_1D_FUNC(uint32_t, "0x%08"PRIx32, 7) +WRITE_1D_FUNC(float, "%.18e", 3) + +WRITE_2D_FUNC(int8_t) +WRITE_2D_FUNC(uint8_t) +WRITE_2D_FUNC(uint32_t) +WRITE_2D_FUNC(float) + +static inline void write_fileheader(void) +{ + printf("/* This file was automatically generated. */\n"); + printf("#include \n"); +} + +#endif /* AVCODEC_TABLEPRINT_H */ diff --git a/ffmpeg/libavcodec/tak.c b/ffmpeg/libavcodec/tak.c new file mode 100644 index 0000000..92dc44c --- /dev/null +++ b/ffmpeg/libavcodec/tak.c @@ -0,0 +1,175 @@ +/* + * TAK common code + * Copyright (c) 2012 Paul B Mahol + * + * 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 "libavutil/bswap.h" +#include "libavutil/crc.h" +#include "libavutil/intreadwrite.h" +#include "tak.h" + +static const int64_t tak_channel_layouts[] = { + 0, + AV_CH_FRONT_LEFT, + AV_CH_FRONT_RIGHT, + AV_CH_FRONT_CENTER, + AV_CH_LOW_FREQUENCY, + AV_CH_BACK_LEFT, + AV_CH_BACK_RIGHT, + AV_CH_FRONT_LEFT_OF_CENTER, + AV_CH_FRONT_RIGHT_OF_CENTER, + AV_CH_BACK_CENTER, + AV_CH_SIDE_LEFT, + AV_CH_SIDE_RIGHT, + AV_CH_TOP_CENTER, + AV_CH_TOP_FRONT_LEFT, + AV_CH_TOP_FRONT_CENTER, + AV_CH_TOP_FRONT_RIGHT, + AV_CH_TOP_BACK_LEFT, + AV_CH_TOP_BACK_CENTER, + AV_CH_TOP_BACK_RIGHT, +}; + +static const uint16_t frame_duration_type_quants[] = { + 3, 4, 6, 8, 4096, 8192, 16384, 512, 1024, 2048, +}; + +static int tak_get_nb_samples(int sample_rate, enum TAKFrameSizeType type) +{ + int nb_samples, max_nb_samples; + + if (type <= TAK_FST_250ms) { + nb_samples = sample_rate * frame_duration_type_quants[type] >> + TAK_FRAME_DURATION_QUANT_SHIFT; + max_nb_samples = 16384; + } else if (type < FF_ARRAY_ELEMS(frame_duration_type_quants)) { + nb_samples = frame_duration_type_quants[type]; + max_nb_samples = sample_rate * + frame_duration_type_quants[TAK_FST_250ms] >> + TAK_FRAME_DURATION_QUANT_SHIFT; + } else { + return AVERROR_INVALIDDATA; + } + + if (nb_samples <= 0 || nb_samples > max_nb_samples) + return AVERROR_INVALIDDATA; + + return nb_samples; +} + +static int crc_init = 0; +#if CONFIG_SMALL +#define CRC_TABLE_SIZE 257 +#else +#define CRC_TABLE_SIZE 1024 +#endif +static AVCRC crc_24[CRC_TABLE_SIZE]; + +av_cold void ff_tak_init_crc(void) +{ + if (!crc_init) { + av_crc_init(crc_24, 0, 24, 0x864CFBU, sizeof(crc_24)); + crc_init = 1; + } +} + +int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size) +{ + uint32_t crc, CRC; + + if (buf_size < 4) + return AVERROR_INVALIDDATA; + buf_size -= 3; + + CRC = av_bswap32(AV_RL24(buf + buf_size)) >> 8; + crc = av_crc(crc_24, 0xCE04B7U, buf, buf_size); + if (CRC != crc) + return AVERROR_INVALIDDATA; + + return 0; +} + +void avpriv_tak_parse_streaminfo(GetBitContext *gb, TAKStreamInfo *s) +{ + uint64_t channel_mask = 0; + int frame_type, i; + + s->codec = get_bits(gb, TAK_ENCODER_CODEC_BITS); + skip_bits(gb, TAK_ENCODER_PROFILE_BITS); + + frame_type = get_bits(gb, TAK_SIZE_FRAME_DURATION_BITS); + s->samples = get_bits64(gb, TAK_SIZE_SAMPLES_NUM_BITS); + + s->data_type = get_bits(gb, TAK_FORMAT_DATA_TYPE_BITS); + s->sample_rate = get_bits(gb, TAK_FORMAT_SAMPLE_RATE_BITS) + + TAK_SAMPLE_RATE_MIN; + s->bps = get_bits(gb, TAK_FORMAT_BPS_BITS) + + TAK_BPS_MIN; + s->channels = get_bits(gb, TAK_FORMAT_CHANNEL_BITS) + + TAK_CHANNELS_MIN; + + if (get_bits1(gb)) { + skip_bits(gb, TAK_FORMAT_VALID_BITS); + if (get_bits1(gb)) { + for (i = 0; i < s->channels; i++) { + int value = get_bits(gb, TAK_FORMAT_CH_LAYOUT_BITS); + + if (value < FF_ARRAY_ELEMS(tak_channel_layouts)) + channel_mask |= tak_channel_layouts[value]; + } + } + } + + s->ch_layout = channel_mask; + s->frame_samples = tak_get_nb_samples(s->sample_rate, frame_type); +} + +int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, + TAKStreamInfo *ti, int log_level_offset) +{ + if (get_bits(gb, TAK_FRAME_HEADER_SYNC_ID_BITS) != TAK_FRAME_HEADER_SYNC_ID) { + av_log(avctx, AV_LOG_ERROR + log_level_offset, "missing sync id\n"); + return AVERROR_INVALIDDATA; + } + + ti->flags = get_bits(gb, TAK_FRAME_HEADER_FLAGS_BITS); + ti->frame_num = get_bits(gb, TAK_FRAME_HEADER_NO_BITS); + + if (ti->flags & TAK_FRAME_FLAG_IS_LAST) { + ti->last_frame_samples = get_bits(gb, TAK_FRAME_HEADER_SAMPLE_COUNT_BITS) + 1; + skip_bits(gb, 2); + } else { + ti->last_frame_samples = 0; + } + + if (ti->flags & TAK_FRAME_FLAG_HAS_INFO) { + avpriv_tak_parse_streaminfo(gb, ti); + + if (get_bits(gb, 6)) + skip_bits(gb, 25); + align_get_bits(gb); + } + + if (ti->flags & TAK_FRAME_FLAG_HAS_METADATA) + return AVERROR_INVALIDDATA; + + skip_bits(gb, 24); + + return 0; +} diff --git a/ffmpeg/libavcodec/tak.h b/ffmpeg/libavcodec/tak.h new file mode 100644 index 0000000..876468d --- /dev/null +++ b/ffmpeg/libavcodec/tak.h @@ -0,0 +1,165 @@ +/* + * TAK decoder/demuxer common code + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +/** + * @file + * TAK (Tom's lossless Audio Kompressor) decoder/demuxer common functions + */ + +#ifndef AVCODEC_TAK_H +#define AVCODEC_TAK_H + +#include + +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "avcodec.h" + +#define TAK_FORMAT_DATA_TYPE_BITS 3 +#define TAK_FORMAT_SAMPLE_RATE_BITS 18 +#define TAK_FORMAT_BPS_BITS 5 +#define TAK_FORMAT_CHANNEL_BITS 4 +#define TAK_FORMAT_VALID_BITS 5 +#define TAK_FORMAT_CH_LAYOUT_BITS 6 +#define TAK_SIZE_FRAME_DURATION_BITS 4 +#define TAK_SIZE_SAMPLES_NUM_BITS 35 +#define TAK_LAST_FRAME_POS_BITS 40 +#define TAK_LAST_FRAME_SIZE_BITS 24 +#define TAK_ENCODER_CODEC_BITS 6 +#define TAK_ENCODER_PROFILE_BITS 4 +#define TAK_ENCODER_VERSION_BITS 24 +#define TAK_SAMPLE_RATE_MIN 6000 +#define TAK_CHANNELS_MIN 1 +#define TAK_BPS_MIN 8 +#define TAK_FRAME_HEADER_FLAGS_BITS 3 +#define TAK_FRAME_HEADER_SYNC_ID 0xA0FF +#define TAK_FRAME_HEADER_SYNC_ID_BITS 16 +#define TAK_FRAME_HEADER_SAMPLE_COUNT_BITS 14 +#define TAK_FRAME_HEADER_NO_BITS 21 +#define TAK_FRAME_DURATION_QUANT_SHIFT 5 +#define TAK_CRC24_BITS 24 + + +#define TAK_FRAME_FLAG_IS_LAST 0x1 +#define TAK_FRAME_FLAG_HAS_INFO 0x2 +#define TAK_FRAME_FLAG_HAS_METADATA 0x4 + +#define TAK_MAX_CHANNELS (1 << TAK_FORMAT_CHANNEL_BITS) + +#define TAK_MIN_FRAME_HEADER_BITS (TAK_FRAME_HEADER_SYNC_ID_BITS + \ + TAK_FRAME_HEADER_FLAGS_BITS + \ + TAK_FRAME_HEADER_NO_BITS + \ + TAK_CRC24_BITS) + +#define TAK_MIN_FRAME_HEADER_LAST_BITS (TAK_MIN_FRAME_HEADER_BITS + 2 + \ + TAK_FRAME_HEADER_SAMPLE_COUNT_BITS) + +#define TAK_ENCODER_BITS (TAK_ENCODER_CODEC_BITS + \ + TAK_ENCODER_PROFILE_BITS) + +#define TAK_SIZE_BITS (TAK_SIZE_SAMPLES_NUM_BITS + \ + TAK_SIZE_FRAME_DURATION_BITS) + +#define TAK_FORMAT_BITS (TAK_FORMAT_DATA_TYPE_BITS + \ + TAK_FORMAT_SAMPLE_RATE_BITS + \ + TAK_FORMAT_BPS_BITS + \ + TAK_FORMAT_CHANNEL_BITS + 1 + \ + TAK_FORMAT_VALID_BITS + 1 + \ + TAK_FORMAT_CH_LAYOUT_BITS * \ + TAK_MAX_CHANNELS) + +#define TAK_STREAMINFO_BITS (TAK_ENCODER_BITS + \ + TAK_SIZE_BITS + \ + TAK_FORMAT_BITS) + +#define TAK_MAX_FRAME_HEADER_BITS (TAK_MIN_FRAME_HEADER_LAST_BITS + \ + TAK_STREAMINFO_BITS + 31) + +#define TAK_STREAMINFO_BYTES ((TAK_STREAMINFO_BITS + 7) / 8) +#define TAK_MAX_FRAME_HEADER_BYTES ((TAK_MAX_FRAME_HEADER_BITS + 7) / 8) +#define TAK_MIN_FRAME_HEADER_BYTES ((TAK_MIN_FRAME_HEADER_BITS + 7) / 8) + +enum TAKCodecType { + TAK_CODEC_MONO_STEREO = 2, + TAK_CODEC_MULTICHANNEL = 4, +}; + +enum TAKMetaDataType { + TAK_METADATA_END = 0, + TAK_METADATA_STREAMINFO, + TAK_METADATA_SEEKTABLE, + TAK_METADATA_SIMPLE_WAVE_DATA, + TAK_METADATA_ENCODER, + TAK_METADATA_PADDING, + TAK_METADATA_MD5, + TAK_METADATA_LAST_FRAME, +}; + +enum TAKFrameSizeType { + TAK_FST_94ms = 0, + TAK_FST_125ms, + TAK_FST_188ms, + TAK_FST_250ms, + TAK_FST_4096, + TAK_FST_8192, + TAK_FST_16384, + TAK_FST_512, + TAK_FST_1024, + TAK_FST_2048, +}; + +typedef struct TAKStreamInfo { + int flags; + enum TAKCodecType codec; + int data_type; + int sample_rate; + int channels; + int bps; + int frame_num; + int frame_samples; + int last_frame_samples; + uint64_t ch_layout; + int64_t samples; +} TAKStreamInfo; + +void ff_tak_init_crc(void); + +int ff_tak_check_crc(const uint8_t *buf, unsigned int buf_size); + +/** + * Parse the Streaminfo metadata block. + * @param[in] gb pointer to GetBitContext + * @param[out] s storage for parsed information + */ +void avpriv_tak_parse_streaminfo(GetBitContext *gb, TAKStreamInfo *s); + +/** + * Validate and decode a frame header. + * @param avctx AVCodecContext to use as av_log() context + * @param[in] gb GetBitContext from which to read frame header + * @param[out] s frame information + * @param log_level_offset log level offset, can be used to silence + * error messages. + * @return non-zero on error, 0 if OK + */ +int ff_tak_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, + TAKStreamInfo *s, int log_level_offset); +#endif /* AVCODEC_TAK_H */ diff --git a/ffmpeg/libavcodec/tak_parser.c b/ffmpeg/libavcodec/tak_parser.c new file mode 100644 index 0000000..0f2fbc2 --- /dev/null +++ b/ffmpeg/libavcodec/tak_parser.c @@ -0,0 +1,128 @@ +/* + * TAK parser + * Copyright (c) 2012 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 + */ + +/** + * @file + * TAK parser + **/ + +#include "tak.h" +#include "parser.h" + +typedef struct TAKParseContext { + ParseContext pc; + TAKStreamInfo ti; + int index; +} TAKParseContext; + +static av_cold int tak_init(AVCodecParserContext *s) +{ + ff_tak_init_crc(); + return 0; +} + +static int tak_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + TAKParseContext *t = s->priv_data; + ParseContext *pc = &t->pc; + int next = END_NOT_FOUND; + GetBitContext gb; + int consumed = 0; + int needed = buf_size ? TAK_MAX_FRAME_HEADER_BYTES : 8; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + TAKStreamInfo ti; + init_get_bits(&gb, buf, buf_size); + if (!ff_tak_decode_frame_header(avctx, &gb, &ti, 127)) + s->duration = t->ti.last_frame_samples ? t->ti.last_frame_samples + : t->ti.frame_samples; + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; + } + + while (buf_size || t->index + needed <= pc->index) { + if (buf_size && t->index + TAK_MAX_FRAME_HEADER_BYTES > pc->index) { + int tmp_buf_size = FFMIN(2 * TAK_MAX_FRAME_HEADER_BYTES, + buf_size); + const uint8_t *tmp_buf = buf; + + if (ff_combine_frame(pc, END_NOT_FOUND, &tmp_buf, &tmp_buf_size) != -1) + return AVERROR(ENOMEM); + consumed += tmp_buf_size; + buf += tmp_buf_size; + buf_size -= tmp_buf_size; + } + + for (; t->index + needed <= pc->index; t->index++) { + if (pc->buffer[ t->index ] == 0xFF && + pc->buffer[ t->index + 1 ] == 0xA0) { + TAKStreamInfo ti; + + init_get_bits(&gb, pc->buffer + t->index, + 8 * (pc->index - t->index)); + if (!ff_tak_decode_frame_header(avctx, &gb, + pc->frame_start_found ? &ti : &t->ti, 127) && + !ff_tak_check_crc(pc->buffer + t->index, + get_bits_count(&gb) / 8)) { + if (!pc->frame_start_found) { + pc->frame_start_found = 1; + s->duration = t->ti.last_frame_samples ? + t->ti.last_frame_samples : + t->ti.frame_samples; + } else { + pc->frame_start_found = 0; + next = t->index - pc->index; + t->index = 0; + goto found; + } + } + } + } + } +found: + + if (consumed && !buf_size && next == END_NOT_FOUND || + ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size + consumed; + } + + if (next != END_NOT_FOUND) { + next += consumed; + pc->overread = FFMAX(0, -next); + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +AVCodecParser ff_tak_parser = { + .codec_ids = { AV_CODEC_ID_TAK }, + .priv_data_size = sizeof(TAKParseContext), + .parser_init = tak_init, + .parser_parse = tak_parse, + .parser_close = ff_parse_close, +}; diff --git a/ffmpeg/libavcodec/takdec.c b/ffmpeg/libavcodec/takdec.c new file mode 100644 index 0000000..43382f1 --- /dev/null +++ b/ffmpeg/libavcodec/takdec.c @@ -0,0 +1,938 @@ +/* + * TAK decoder + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +/** + * @file + * TAK (Tom's lossless Audio Kompressor) decoder + * @author Paul B Mahol + */ + +#include "libavutil/internal.h" +#include "libavutil/samplefmt.h" +#include "tak.h" +#include "avcodec.h" +#include "dsputil.h" +#include "internal.h" +#include "unary.h" + +#define MAX_SUBFRAMES 8 ///< max number of subframes per channel +#define MAX_PREDICTORS 256 + +typedef struct MCDParam { + int8_t present; ///< decorrelation parameter availability for this channel + int8_t index; ///< index into array of decorrelation types + int8_t chan1; + int8_t chan2; +} MCDParam; + +typedef struct TAKDecContext { + AVCodecContext *avctx; ///< parent AVCodecContext + DSPContext dsp; + TAKStreamInfo ti; + GetBitContext gb; ///< bitstream reader initialized to start at the current frame + + int uval; + int nb_samples; ///< number of samples in the current frame + uint8_t *decode_buffer; + unsigned int decode_buffer_size; + int32_t *decoded[TAK_MAX_CHANNELS]; ///< decoded samples for each channel + + int8_t lpc_mode[TAK_MAX_CHANNELS]; + int8_t sample_shift[TAK_MAX_CHANNELS]; ///< shift applied to every sample in the channel + int16_t predictors[MAX_PREDICTORS]; + int nb_subframes; ///< number of subframes in the current frame + int16_t subframe_len[MAX_SUBFRAMES]; ///< subframe length in samples + int subframe_scale; + + int8_t dmode; ///< channel decorrelation type in the current frame + + MCDParam mcdparams[TAK_MAX_CHANNELS]; ///< multichannel decorrelation parameters + + int8_t coding_mode[128]; + DECLARE_ALIGNED(16, int16_t, filter)[MAX_PREDICTORS]; + DECLARE_ALIGNED(16, int16_t, residues)[544]; +} TAKDecContext; + +static const int8_t mc_dmodes[] = { 1, 3, 4, 6, }; + +static const uint16_t predictor_sizes[] = { + 4, 8, 12, 16, 24, 32, 48, 64, 80, 96, 128, 160, 192, 224, 256, 0, +}; + +static const struct CParam { + int init; + int escape; + int scale; + int aescape; + int bias; +} xcodes[50] = { + { 0x01, 0x0000001, 0x0000001, 0x0000003, 0x0000008 }, + { 0x02, 0x0000003, 0x0000001, 0x0000007, 0x0000006 }, + { 0x03, 0x0000005, 0x0000002, 0x000000E, 0x000000D }, + { 0x03, 0x0000003, 0x0000003, 0x000000D, 0x0000018 }, + { 0x04, 0x000000B, 0x0000004, 0x000001C, 0x0000019 }, + { 0x04, 0x0000006, 0x0000006, 0x000001A, 0x0000030 }, + { 0x05, 0x0000016, 0x0000008, 0x0000038, 0x0000032 }, + { 0x05, 0x000000C, 0x000000C, 0x0000034, 0x0000060 }, + { 0x06, 0x000002C, 0x0000010, 0x0000070, 0x0000064 }, + { 0x06, 0x0000018, 0x0000018, 0x0000068, 0x00000C0 }, + { 0x07, 0x0000058, 0x0000020, 0x00000E0, 0x00000C8 }, + { 0x07, 0x0000030, 0x0000030, 0x00000D0, 0x0000180 }, + { 0x08, 0x00000B0, 0x0000040, 0x00001C0, 0x0000190 }, + { 0x08, 0x0000060, 0x0000060, 0x00001A0, 0x0000300 }, + { 0x09, 0x0000160, 0x0000080, 0x0000380, 0x0000320 }, + { 0x09, 0x00000C0, 0x00000C0, 0x0000340, 0x0000600 }, + { 0x0A, 0x00002C0, 0x0000100, 0x0000700, 0x0000640 }, + { 0x0A, 0x0000180, 0x0000180, 0x0000680, 0x0000C00 }, + { 0x0B, 0x0000580, 0x0000200, 0x0000E00, 0x0000C80 }, + { 0x0B, 0x0000300, 0x0000300, 0x0000D00, 0x0001800 }, + { 0x0C, 0x0000B00, 0x0000400, 0x0001C00, 0x0001900 }, + { 0x0C, 0x0000600, 0x0000600, 0x0001A00, 0x0003000 }, + { 0x0D, 0x0001600, 0x0000800, 0x0003800, 0x0003200 }, + { 0x0D, 0x0000C00, 0x0000C00, 0x0003400, 0x0006000 }, + { 0x0E, 0x0002C00, 0x0001000, 0x0007000, 0x0006400 }, + { 0x0E, 0x0001800, 0x0001800, 0x0006800, 0x000C000 }, + { 0x0F, 0x0005800, 0x0002000, 0x000E000, 0x000C800 }, + { 0x0F, 0x0003000, 0x0003000, 0x000D000, 0x0018000 }, + { 0x10, 0x000B000, 0x0004000, 0x001C000, 0x0019000 }, + { 0x10, 0x0006000, 0x0006000, 0x001A000, 0x0030000 }, + { 0x11, 0x0016000, 0x0008000, 0x0038000, 0x0032000 }, + { 0x11, 0x000C000, 0x000C000, 0x0034000, 0x0060000 }, + { 0x12, 0x002C000, 0x0010000, 0x0070000, 0x0064000 }, + { 0x12, 0x0018000, 0x0018000, 0x0068000, 0x00C0000 }, + { 0x13, 0x0058000, 0x0020000, 0x00E0000, 0x00C8000 }, + { 0x13, 0x0030000, 0x0030000, 0x00D0000, 0x0180000 }, + { 0x14, 0x00B0000, 0x0040000, 0x01C0000, 0x0190000 }, + { 0x14, 0x0060000, 0x0060000, 0x01A0000, 0x0300000 }, + { 0x15, 0x0160000, 0x0080000, 0x0380000, 0x0320000 }, + { 0x15, 0x00C0000, 0x00C0000, 0x0340000, 0x0600000 }, + { 0x16, 0x02C0000, 0x0100000, 0x0700000, 0x0640000 }, + { 0x16, 0x0180000, 0x0180000, 0x0680000, 0x0C00000 }, + { 0x17, 0x0580000, 0x0200000, 0x0E00000, 0x0C80000 }, + { 0x17, 0x0300000, 0x0300000, 0x0D00000, 0x1800000 }, + { 0x18, 0x0B00000, 0x0400000, 0x1C00000, 0x1900000 }, + { 0x18, 0x0600000, 0x0600000, 0x1A00000, 0x3000000 }, + { 0x19, 0x1600000, 0x0800000, 0x3800000, 0x3200000 }, + { 0x19, 0x0C00000, 0x0C00000, 0x3400000, 0x6000000 }, + { 0x1A, 0x2C00000, 0x1000000, 0x7000000, 0x6400000 }, + { 0x1A, 0x1800000, 0x1800000, 0x6800000, 0xC000000 }, +}; + +static int set_bps_params(AVCodecContext *avctx) +{ + switch (avctx->bits_per_raw_sample) { + case 8: + avctx->sample_fmt = AV_SAMPLE_FMT_U8P; + break; + case 16: + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + break; + case 24: + avctx->sample_fmt = AV_SAMPLE_FMT_S32P; + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid/unsupported bits per sample: %d\n", + avctx->bits_per_raw_sample); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static void set_sample_rate_params(AVCodecContext *avctx) +{ + TAKDecContext *s = avctx->priv_data; + int shift = 3 - (avctx->sample_rate / 11025); + shift = FFMAX(0, shift); + s->uval = FFALIGN(avctx->sample_rate + 511 >> 9, 4) << shift; + s->subframe_scale = FFALIGN(avctx->sample_rate + 511 >> 9, 4) << 1; +} + +static av_cold int tak_decode_init(AVCodecContext *avctx) +{ + TAKDecContext *s = avctx->priv_data; + + ff_tak_init_crc(); + ff_dsputil_init(&s->dsp, avctx); + + s->avctx = avctx; + avctx->bits_per_raw_sample = avctx->bits_per_coded_sample; + + set_sample_rate_params(avctx); + + return set_bps_params(avctx); +} + +static void decode_lpc(int32_t *coeffs, int mode, int length) +{ + int i; + + if (length < 2) + return; + + if (mode == 1) { + int a1 = *coeffs++; + for (i = 0; i < length - 1 >> 1; i++) { + *coeffs += a1; + coeffs[1] += *coeffs; + a1 = coeffs[1]; + coeffs += 2; + } + if (length - 1 & 1) + *coeffs += a1; + } else if (mode == 2) { + int a1 = coeffs[1]; + int a2 = a1 + *coeffs; + coeffs[1] = a2; + if (length > 2) { + coeffs += 2; + for (i = 0; i < length - 2 >> 1; i++) { + int a3 = *coeffs + a1; + int a4 = a3 + a2; + *coeffs = a4; + a1 = coeffs[1] + a3; + a2 = a1 + a4; + coeffs[1] = a2; + coeffs += 2; + } + if (length & 1) + *coeffs += a1 + a2; + } + } else if (mode == 3) { + int a1 = coeffs[1]; + int a2 = a1 + *coeffs; + coeffs[1] = a2; + if (length > 2) { + int a3 = coeffs[2]; + int a4 = a3 + a1; + int a5 = a4 + a2; + coeffs += 3; + for (i = 0; i < length - 3; i++) { + a3 += *coeffs; + a4 += a3; + a5 += a4; + *coeffs = a5; + coeffs++; + } + } + } +} + +static int decode_segment(TAKDecContext *s, int8_t mode, int32_t *decoded, int len) +{ + struct CParam code; + GetBitContext *gb = &s->gb; + int i; + + if (!mode) { + memset(decoded, 0, len * sizeof(*decoded)); + return 0; + } + + if (mode > FF_ARRAY_ELEMS(xcodes)) + return AVERROR_INVALIDDATA; + code = xcodes[mode - 1]; + + for (i = 0; i < len; i++) { + int x = get_bits_long(gb, code.init); + if (x >= code.escape && get_bits1(gb)) { + x |= 1 << code.init; + if (x >= code.aescape) { + int scale = get_unary(gb, 1, 9); + if (scale == 9) { + int scale_bits = get_bits(gb, 3); + if (scale_bits > 0) { + if (scale_bits == 7) { + scale_bits += get_bits(gb, 5); + if (scale_bits > 29) + return AVERROR_INVALIDDATA; + } + scale = get_bits_long(gb, scale_bits) + 1; + x += code.scale * scale; + } + x += code.bias; + } else + x += code.scale * scale - code.escape; + } else + x -= code.escape; + } + decoded[i] = (x >> 1) ^ -(x & 1); + } + + return 0; +} + +static int decode_residues(TAKDecContext *s, int32_t *decoded, int length) +{ + GetBitContext *gb = &s->gb; + int i, mode, ret; + + if (length > s->nb_samples) + return AVERROR_INVALIDDATA; + + if (get_bits1(gb)) { + int wlength, rval; + + wlength = length / s->uval; + + rval = length - (wlength * s->uval); + + if (rval < s->uval / 2) + rval += s->uval; + else + wlength++; + + if (wlength <= 1 || wlength > 128) + return AVERROR_INVALIDDATA; + + s->coding_mode[0] = mode = get_bits(gb, 6); + + for (i = 1; i < wlength; i++) { + int c = get_unary(gb, 1, 6); + + switch (c) { + case 6: + mode = get_bits(gb, 6); + break; + case 5: + case 4: + case 3: { + /* mode += sign ? (1 - c) : (c - 1) */ + int sign = get_bits1(gb); + mode += (-sign ^ (c - 1)) + sign; + break; + } + case 2: + mode++; + break; + case 1: + mode--; + break; + } + s->coding_mode[i] = mode; + } + + i = 0; + while (i < wlength) { + int len = 0; + + mode = s->coding_mode[i]; + do { + if (i >= wlength - 1) + len += rval; + else + len += s->uval; + i++; + + if (i == wlength) + break; + } while (s->coding_mode[i] == mode); + + if ((ret = decode_segment(s, mode, decoded, len)) < 0) + return ret; + decoded += len; + } + } else { + mode = get_bits(gb, 6); + if ((ret = decode_segment(s, mode, decoded, length)) < 0) + return ret; + } + + return 0; +} + +static int get_bits_esc4(GetBitContext *gb) +{ + if (get_bits1(gb)) + return get_bits(gb, 4) + 1; + else + return 0; +} + +static int decode_subframe(TAKDecContext *s, int32_t *decoded, + int subframe_size, int prev_subframe_size) +{ + GetBitContext *gb = &s->gb; + int tmp, x, y, i, j, ret = 0; + int dshift, size, filter_quant, filter_order; + int tfilter[MAX_PREDICTORS]; + + if (!get_bits1(gb)) + return decode_residues(s, decoded, subframe_size); + + filter_order = predictor_sizes[get_bits(gb, 4)]; + + if (prev_subframe_size > 0 && get_bits1(gb)) { + if (filter_order > prev_subframe_size) + return AVERROR_INVALIDDATA; + + decoded -= filter_order; + subframe_size += filter_order; + + if (filter_order > subframe_size) + return AVERROR_INVALIDDATA; + } else { + int lpc_mode; + + if (filter_order > subframe_size) + return AVERROR_INVALIDDATA; + + lpc_mode = get_bits(gb, 2); + if (lpc_mode > 2) + return AVERROR_INVALIDDATA; + + if ((ret = decode_residues(s, decoded, filter_order)) < 0) + return ret; + + if (lpc_mode) + decode_lpc(decoded, lpc_mode, filter_order); + } + + dshift = get_bits_esc4(gb); + size = get_bits1(gb) + 6; + + filter_quant = 10; + if (get_bits1(gb)) { + filter_quant -= get_bits(gb, 3) + 1; + if (filter_quant < 3) + return AVERROR_INVALIDDATA; + } + + s->predictors[0] = get_sbits(gb, 10); + s->predictors[1] = get_sbits(gb, 10); + s->predictors[2] = get_sbits(gb, size) << (10 - size); + s->predictors[3] = get_sbits(gb, size) << (10 - size); + if (filter_order > 4) { + tmp = size - get_bits1(gb); + + for (i = 4; i < filter_order; i++) { + if (!(i & 3)) + x = tmp - get_bits(gb, 2); + s->predictors[i] = get_sbits(gb, x) << (10 - size); + } + } + + tfilter[0] = s->predictors[0] << 6; + for (i = 1; i < filter_order; i++) { + int32_t *p1 = &tfilter[0]; + int32_t *p2 = &tfilter[i - 1]; + + for (j = 0; j < (i + 1) / 2; j++) { + x = *p1 + (s->predictors[i] * *p2 + 256 >> 9); + *p2 += s->predictors[i] * *p1 + 256 >> 9; + *p1++ = x; + p2--; + } + + tfilter[i] = s->predictors[i] << 6; + } + + x = 1 << (32 - (15 - filter_quant)); + y = 1 << ((15 - filter_quant) - 1); + for (i = 0, j = filter_order - 1; i < filter_order / 2; i++, j--) { + tmp = y + tfilter[j]; + s->filter[j] = x - ((tfilter[i] + y) >> (15 - filter_quant)); + s->filter[i] = x - ((tfilter[j] + y) >> (15 - filter_quant)); + } + + if ((ret = decode_residues(s, &decoded[filter_order], + subframe_size - filter_order)) < 0) + return ret; + + for (i = 0; i < filter_order; i++) + s->residues[i] = *decoded++ >> dshift; + + y = FF_ARRAY_ELEMS(s->residues) - filter_order; + x = subframe_size - filter_order; + while (x > 0) { + tmp = FFMIN(y, x); + + for (i = 0; i < tmp; i++) { + int v = 1 << (filter_quant - 1); + + if (!(filter_order & 15)) { + v += s->dsp.scalarproduct_int16(&s->residues[i], s->filter, + filter_order); + } else if (filter_order & 4) { + for (j = 0; j < filter_order; j += 4) { + v += s->residues[i + j + 3] * s->filter[j + 3] + + s->residues[i + j + 2] * s->filter[j + 2] + + s->residues[i + j + 1] * s->filter[j + 1] + + s->residues[i + j ] * s->filter[j ]; + } + } else { + for (j = 0; j < filter_order; j += 8) { + v += s->residues[i + j + 7] * s->filter[j + 7] + + s->residues[i + j + 6] * s->filter[j + 6] + + s->residues[i + j + 5] * s->filter[j + 5] + + s->residues[i + j + 4] * s->filter[j + 4] + + s->residues[i + j + 3] * s->filter[j + 3] + + s->residues[i + j + 2] * s->filter[j + 2] + + s->residues[i + j + 1] * s->filter[j + 1] + + s->residues[i + j ] * s->filter[j ]; + } + } + v = (av_clip(v >> filter_quant, -8192, 8191) << dshift) - *decoded; + *decoded++ = v; + s->residues[filter_order + i] = v >> dshift; + } + + x -= tmp; + if (x > 0) + memcpy(s->residues, &s->residues[y], 2 * filter_order); + } + + emms_c(); + + return 0; +} + +static int decode_channel(TAKDecContext *s, int chan) +{ + AVCodecContext *avctx = s->avctx; + GetBitContext *gb = &s->gb; + int32_t *decoded = s->decoded[chan]; + int left = s->nb_samples - 1; + int i = 0, ret, prev = 0; + + s->sample_shift[chan] = get_bits_esc4(gb); + if (s->sample_shift[chan] >= avctx->bits_per_raw_sample) + return AVERROR_INVALIDDATA; + + *decoded++ = get_sbits(gb, avctx->bits_per_raw_sample - s->sample_shift[chan]); + s->lpc_mode[chan] = get_bits(gb, 2); + s->nb_subframes = get_bits(gb, 3) + 1; + + if (s->nb_subframes > 1) { + if (get_bits_left(gb) < (s->nb_subframes - 1) * 6) + return AVERROR_INVALIDDATA; + + for (; i < s->nb_subframes - 1; i++) { + int v = get_bits(gb, 6); + + s->subframe_len[i] = (v - prev) * s->subframe_scale; + if (s->subframe_len[i] <= 0) + return AVERROR_INVALIDDATA; + + left -= s->subframe_len[i]; + prev = v; + } + + if (left <= 0) + return AVERROR_INVALIDDATA; + } + s->subframe_len[i] = left; + + prev = 0; + for (i = 0; i < s->nb_subframes; i++) { + if ((ret = decode_subframe(s, decoded, s->subframe_len[i], prev)) < 0) + return ret; + decoded += s->subframe_len[i]; + prev = s->subframe_len[i]; + } + + return 0; +} + +static int decorrelate(TAKDecContext *s, int c1, int c2, int length) +{ + GetBitContext *gb = &s->gb; + int32_t *p1 = s->decoded[c1] + 1; + int32_t *p2 = s->decoded[c2] + 1; + int i; + int dshift, dfactor; + + switch (s->dmode) { + case 1: /* left/side */ + for (i = 0; i < length; i++) { + int32_t a = p1[i]; + int32_t b = p2[i]; + p2[i] = a + b; + } + break; + case 2: /* side/right */ + for (i = 0; i < length; i++) { + int32_t a = p1[i]; + int32_t b = p2[i]; + p1[i] = b - a; + } + break; + case 3: /* side/mid */ + for (i = 0; i < length; i++) { + int32_t a = p1[i]; + int32_t b = p2[i]; + a -= b >> 1; + p1[i] = a; + p2[i] = a + b; + } + break; + case 4: /* side/left with scale factor */ + FFSWAP(int32_t*, p1, p2); + case 5: /* side/right with scale factor */ + dshift = get_bits_esc4(gb); + dfactor = get_sbits(gb, 10); + for (i = 0; i < length; i++) { + int32_t a = p1[i]; + int32_t b = p2[i]; + b = dfactor * (b >> dshift) + 128 >> 8 << dshift; + p1[i] = b - a; + } + break; + case 6: + FFSWAP(int32_t*, p1, p2); + case 7: { + int length2, order_half, filter_order, dval1, dval2; + int tmp, x, code_size; + + if (length < 256) + return AVERROR_INVALIDDATA; + + dshift = get_bits_esc4(gb); + filter_order = 8 << get_bits1(gb); + dval1 = get_bits1(gb); + dval2 = get_bits1(gb); + + for (i = 0; i < filter_order; i++) { + if (!(i & 3)) + code_size = 14 - get_bits(gb, 3); + s->filter[i] = get_sbits(gb, code_size); + } + + order_half = filter_order / 2; + length2 = length - (filter_order - 1); + + /* decorrelate beginning samples */ + if (dval1) { + for (i = 0; i < order_half; i++) { + int32_t a = p1[i]; + int32_t b = p2[i]; + p1[i] = a + b; + } + } + + /* decorrelate ending samples */ + if (dval2) { + for (i = length2 + order_half; i < length; i++) { + int32_t a = p1[i]; + int32_t b = p2[i]; + p1[i] = a + b; + } + } + + + for (i = 0; i < filter_order; i++) + s->residues[i] = *p2++ >> dshift; + + p1 += order_half; + x = FF_ARRAY_ELEMS(s->residues) - filter_order; + for (; length2 > 0; length2 -= tmp) { + tmp = FFMIN(length2, x); + + for (i = 0; i < tmp; i++) + s->residues[filter_order + i] = *p2++ >> dshift; + + for (i = 0; i < tmp; i++) { + int v = 1 << 9; + + if (filter_order == 16) { + v += s->dsp.scalarproduct_int16(&s->residues[i], s->filter, + filter_order); + } else { + v += s->residues[i + 7] * s->filter[7] + + s->residues[i + 6] * s->filter[6] + + s->residues[i + 5] * s->filter[5] + + s->residues[i + 4] * s->filter[4] + + s->residues[i + 3] * s->filter[3] + + s->residues[i + 2] * s->filter[2] + + s->residues[i + 1] * s->filter[1] + + s->residues[i ] * s->filter[0]; + } + + v = (av_clip(v >> 10, -8192, 8191) << dshift) - *p1; + *p1++ = v; + } + + memcpy(s->residues, &s->residues[tmp], 2 * filter_order); + } + + emms_c(); + break; + } + } + + return 0; +} + +static int tak_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + TAKDecContext *s = avctx->priv_data; + AVFrame *frame = data; + GetBitContext *gb = &s->gb; + int chan, i, ret, hsize; + + if (pkt->size < TAK_MIN_FRAME_HEADER_BYTES) + return AVERROR_INVALIDDATA; + + if ((ret = init_get_bits8(gb, pkt->data, pkt->size)) < 0) + return ret; + + if ((ret = ff_tak_decode_frame_header(avctx, gb, &s->ti, 0)) < 0) + return ret; + + if (avctx->err_recognition & AV_EF_CRCCHECK) { + hsize = get_bits_count(gb) / 8; + if (ff_tak_check_crc(pkt->data, hsize)) { + av_log(avctx, AV_LOG_ERROR, "CRC error\n"); + return AVERROR_INVALIDDATA; + } + } + + if (s->ti.codec != TAK_CODEC_MONO_STEREO && + s->ti.codec != TAK_CODEC_MULTICHANNEL) { + av_log(avctx, AV_LOG_ERROR, "unsupported codec: %d\n", s->ti.codec); + return AVERROR_PATCHWELCOME; + } + if (s->ti.data_type) { + av_log(avctx, AV_LOG_ERROR, + "unsupported data type: %d\n", s->ti.data_type); + return AVERROR_INVALIDDATA; + } + if (s->ti.codec == TAK_CODEC_MONO_STEREO && s->ti.channels > 2) { + av_log(avctx, AV_LOG_ERROR, + "invalid number of channels: %d\n", s->ti.channels); + return AVERROR_INVALIDDATA; + } + if (s->ti.channels > 6) { + av_log(avctx, AV_LOG_ERROR, + "unsupported number of channels: %d\n", s->ti.channels); + return AVERROR_INVALIDDATA; + } + + if (s->ti.frame_samples <= 0) { + av_log(avctx, AV_LOG_ERROR, "unsupported/invalid number of samples\n"); + return AVERROR_INVALIDDATA; + } + + if (s->ti.bps != avctx->bits_per_raw_sample) { + avctx->bits_per_raw_sample = s->ti.bps; + if ((ret = set_bps_params(avctx)) < 0) + return ret; + } + if (s->ti.sample_rate != avctx->sample_rate) { + avctx->sample_rate = s->ti.sample_rate; + set_sample_rate_params(avctx); + } + if (s->ti.ch_layout) + avctx->channel_layout = s->ti.ch_layout; + avctx->channels = s->ti.channels; + + s->nb_samples = s->ti.last_frame_samples ? s->ti.last_frame_samples + : s->ti.frame_samples; + + frame->nb_samples = s->nb_samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (avctx->bits_per_raw_sample <= 16) { + int buf_size = av_samples_get_buffer_size(NULL, avctx->channels, + s->nb_samples, + AV_SAMPLE_FMT_S32P, 0); + av_fast_malloc(&s->decode_buffer, &s->decode_buffer_size, buf_size); + if (!s->decode_buffer) + return AVERROR(ENOMEM); + ret = av_samples_fill_arrays((uint8_t **)s->decoded, NULL, + s->decode_buffer, avctx->channels, + s->nb_samples, AV_SAMPLE_FMT_S32P, 0); + if (ret < 0) + return ret; + } else { + for (chan = 0; chan < avctx->channels; chan++) + s->decoded[chan] = (int32_t *)frame->extended_data[chan]; + } + + if (s->nb_samples < 16) { + for (chan = 0; chan < avctx->channels; chan++) { + int32_t *decoded = s->decoded[chan]; + for (i = 0; i < s->nb_samples; i++) + decoded[i] = get_sbits(gb, avctx->bits_per_raw_sample); + } + } else { + if (s->ti.codec == TAK_CODEC_MONO_STEREO) { + for (chan = 0; chan < avctx->channels; chan++) + if (ret = decode_channel(s, chan)) + return ret; + + if (avctx->channels == 2) { + s->nb_subframes = get_bits(gb, 1) + 1; + if (s->nb_subframes > 1) { + s->subframe_len[1] = get_bits(gb, 6); + } + + s->dmode = get_bits(gb, 3); + if (ret = decorrelate(s, 0, 1, s->nb_samples - 1)) + return ret; + } + } else if (s->ti.codec == TAK_CODEC_MULTICHANNEL) { + if (get_bits1(gb)) { + int ch_mask = 0; + + chan = get_bits(gb, 4) + 1; + if (chan > avctx->channels) + return AVERROR_INVALIDDATA; + + for (i = 0; i < chan; i++) { + int nbit = get_bits(gb, 4); + + if (nbit >= avctx->channels) + return AVERROR_INVALIDDATA; + + if (ch_mask & 1 << nbit) + return AVERROR_INVALIDDATA; + + s->mcdparams[i].present = get_bits1(gb); + if (s->mcdparams[i].present) { + s->mcdparams[i].index = get_bits(gb, 2); + s->mcdparams[i].chan2 = get_bits(gb, 4); + if (s->mcdparams[i].index == 1) { + if ((nbit == s->mcdparams[i].chan2) || + (ch_mask & 1 << s->mcdparams[i].chan2)) + return AVERROR_INVALIDDATA; + + ch_mask |= 1 << s->mcdparams[i].chan2; + } else if (!(ch_mask & 1 << s->mcdparams[i].chan2)) { + return AVERROR_INVALIDDATA; + } + } + s->mcdparams[i].chan1 = nbit; + + ch_mask |= 1 << nbit; + } + } else { + chan = avctx->channels; + for (i = 0; i < chan; i++) { + s->mcdparams[i].present = 0; + s->mcdparams[i].chan1 = i; + } + } + + for (i = 0; i < chan; i++) { + if (s->mcdparams[i].present && s->mcdparams[i].index == 1) + if (ret = decode_channel(s, s->mcdparams[i].chan2)) + return ret; + + if (ret = decode_channel(s, s->mcdparams[i].chan1)) + return ret; + + if (s->mcdparams[i].present) { + s->dmode = mc_dmodes[s->mcdparams[i].index]; + if (ret = decorrelate(s, + s->mcdparams[i].chan2, + s->mcdparams[i].chan1, + s->nb_samples - 1)) + return ret; + } + } + } + + for (chan = 0; chan < avctx->channels; chan++) { + int32_t *decoded = s->decoded[chan]; + + if (s->lpc_mode[chan]) + decode_lpc(decoded, s->lpc_mode[chan], s->nb_samples); + + if (s->sample_shift[chan] > 0) + for (i = 0; i < s->nb_samples; i++) + decoded[i] <<= s->sample_shift[chan]; + } + } + + align_get_bits(gb); + skip_bits(gb, 24); + if (get_bits_left(gb) < 0) + av_log(avctx, AV_LOG_DEBUG, "overread\n"); + else if (get_bits_left(gb) > 0) + av_log(avctx, AV_LOG_DEBUG, "underread\n"); + + if (avctx->err_recognition & AV_EF_CRCCHECK) { + if (ff_tak_check_crc(pkt->data + hsize, + get_bits_count(gb) / 8 - hsize)) { + av_log(avctx, AV_LOG_ERROR, "CRC error\n"); + return AVERROR_INVALIDDATA; + } + } + + /* convert to output buffer */ + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_U8P: + for (chan = 0; chan < avctx->channels; chan++) { + uint8_t *samples = (uint8_t *)frame->extended_data[chan]; + int32_t *decoded = s->decoded[chan]; + for (i = 0; i < s->nb_samples; i++) + samples[i] = decoded[i] + 0x80; + } + break; + case AV_SAMPLE_FMT_S16P: + for (chan = 0; chan < avctx->channels; chan++) { + int16_t *samples = (int16_t *)frame->extended_data[chan]; + int32_t *decoded = s->decoded[chan]; + for (i = 0; i < s->nb_samples; i++) + samples[i] = decoded[i]; + } + break; + case AV_SAMPLE_FMT_S32P: + for (chan = 0; chan < avctx->channels; chan++) { + int32_t *samples = (int32_t *)frame->extended_data[chan]; + for (i = 0; i < s->nb_samples; i++) + samples[i] <<= 8; + } + break; + } + + *got_frame_ptr = 1; + + return pkt->size; +} + +static av_cold int tak_decode_close(AVCodecContext *avctx) +{ + TAKDecContext *s = avctx->priv_data; + + av_freep(&s->decode_buffer); + + return 0; +} + +AVCodec ff_tak_decoder = { + .name = "tak", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_TAK, + .priv_data_size = sizeof(TAKDecContext), + .init = tak_decode_init, + .close = tak_decode_close, + .decode = tak_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/targa.c b/ffmpeg/libavcodec/targa.c new file mode 100644 index 0000000..ff4390f --- /dev/null +++ b/ffmpeg/libavcodec/targa.c @@ -0,0 +1,307 @@ +/* + * Targa (.tga) image decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "targa.h" + +typedef struct TargaContext { + GetByteContext gb; +} TargaContext; + +static uint8_t *advance_line(uint8_t *start, uint8_t *line, + int stride, int *y, int h, int interleave) +{ + *y += interleave; + + if (*y < h) { + return line + interleave * stride; + } else { + *y = (*y + 1) & (interleave - 1); + if (*y && *y < h) { + return start + *y * stride; + } else { + return NULL; + } + } +} + +static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s, + uint8_t *start, int w, int h, int stride, + int bpp, int interleave) +{ + int x, y; + int depth = (bpp + 1) >> 3; + int type, count; + uint8_t *line = start; + uint8_t *dst = line; + + x = y = count = 0; + while (dst) { + if (bytestream2_get_bytes_left(&s->gb) <= 0) { + av_log(avctx, AV_LOG_ERROR, + "Ran ouf of data before end-of-image\n"); + return AVERROR_INVALIDDATA; + } + type = bytestream2_get_byteu(&s->gb); + count = (type & 0x7F) + 1; + type &= 0x80; + if (!type) { + do { + int n = FFMIN(count, w - x); + bytestream2_get_buffer(&s->gb, dst, n * depth); + count -= n; + dst += n * depth; + x += n; + if (x == w) { + x = 0; + dst = line = advance_line(start, line, stride, &y, h, interleave); + } + } while (dst && count > 0); + } else { + uint8_t tmp[4]; + bytestream2_get_buffer(&s->gb, tmp, depth); + do { + int n = FFMIN(count, w - x); + count -= n; + x += n; + do { + memcpy(dst, tmp, depth); + dst += depth; + } while (--n); + if (x == w) { + x = 0; + dst = line = advance_line(start, line, stride, &y, h, interleave); + } + } while (dst && count > 0); + } + } + + if (count) { + av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + TargaContext * const s = avctx->priv_data; + AVFrame * const p = data; + uint8_t *dst; + int stride; + int idlen, pal, compr, y, w, h, bpp, flags, ret; + int first_clr, colors, csize; + int interleave; + + bytestream2_init(&s->gb, avpkt->data, avpkt->size); + + /* parse image header */ + idlen = bytestream2_get_byte(&s->gb); + pal = bytestream2_get_byte(&s->gb); + compr = bytestream2_get_byte(&s->gb); + first_clr = bytestream2_get_le16(&s->gb); + colors = bytestream2_get_le16(&s->gb); + csize = bytestream2_get_byte(&s->gb); + bytestream2_skip(&s->gb, 4); /* 2: x, 2: y */ + w = bytestream2_get_le16(&s->gb); + h = bytestream2_get_le16(&s->gb); + bpp = bytestream2_get_byte(&s->gb); + + if (bytestream2_get_bytes_left(&s->gb) <= idlen) { + av_log(avctx, AV_LOG_ERROR, + "Not enough data to read header\n"); + return AVERROR_INVALIDDATA; + } + + flags = bytestream2_get_byte(&s->gb); + + if (!pal && (first_clr || colors || csize)) { + av_log(avctx, AV_LOG_WARNING, "File without colormap has colormap information set.\n"); + // specification says we should ignore those value in this case + first_clr = colors = csize = 0; + } + + // skip identifier if any + bytestream2_skip(&s->gb, idlen); + + switch (bpp) { + case 8: + avctx->pix_fmt = ((compr & (~TGA_RLE)) == TGA_BW) ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_PAL8; + break; + case 15: + case 16: + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case 32: + avctx->pix_fmt = AV_PIX_FMT_BGRA; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Bit depth %i is not supported\n", bpp); + return AVERROR_INVALIDDATA; + } + + if (colors && (colors + first_clr) > 256) { + av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr); + return AVERROR_INVALIDDATA; + } + + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) + return ret; + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + if (flags & TGA_TOPTOBOTTOM) { + dst = p->data[0]; + stride = p->linesize[0]; + } else { //image is upside-down + dst = p->data[0] + p->linesize[0] * (h - 1); + stride = -p->linesize[0]; + } + + interleave = flags & TGA_INTERLEAVE2 ? 2 : + flags & TGA_INTERLEAVE4 ? 4 : 1; + + if (colors) { + int pal_size, pal_sample_size; + + switch (csize) { + case 32: pal_sample_size = 4; break; + case 24: pal_sample_size = 3; break; + case 16: + case 15: pal_sample_size = 2; break; + default: + av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize); + return AVERROR_INVALIDDATA; + } + pal_size = colors * pal_sample_size; + if (avctx->pix_fmt != AV_PIX_FMT_PAL8) //should not occur but skip palette anyway + bytestream2_skip(&s->gb, pal_size); + else { + int t; + uint32_t *pal = ((uint32_t *)p->data[1]) + first_clr; + + if (bytestream2_get_bytes_left(&s->gb) < pal_size) { + av_log(avctx, AV_LOG_ERROR, + "Not enough data to read palette\n"); + return AVERROR_INVALIDDATA; + } + switch (pal_sample_size) { + case 4: + for (t = 0; t < colors; t++) + *pal++ = bytestream2_get_le32u(&s->gb); + break; + case 3: + /* RGB24 */ + for (t = 0; t < colors; t++) + *pal++ = (0xffU<<24) | bytestream2_get_le24u(&s->gb); + break; + case 2: + /* RGB555 */ + for (t = 0; t < colors; t++) { + uint32_t v = bytestream2_get_le16u(&s->gb); + v = ((v & 0x7C00) << 9) | + ((v & 0x03E0) << 6) | + ((v & 0x001F) << 3); + /* left bit replication */ + v |= (v & 0xE0E0E0U) >> 5; + *pal++ = (0xffU<<24) | v; + } + break; + } + p->palette_has_changed = 1; + } + } + + if ((compr & (~TGA_RLE)) == TGA_NODATA) { + memset(p->data[0], 0, p->linesize[0] * h); + } else { + if (compr & TGA_RLE) { + int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp, interleave); + if (res < 0) + return res; + } else { + size_t img_size = w * ((bpp + 1) >> 3); + uint8_t *line; + if (bytestream2_get_bytes_left(&s->gb) < img_size * h) { + av_log(avctx, AV_LOG_ERROR, + "Not enough data available for image\n"); + return AVERROR_INVALIDDATA; + } + + line = dst; + y = 0; + do { + bytestream2_get_buffer(&s->gb, line, img_size); + line = advance_line(dst, line, stride, &y, h, interleave); + } while (line); + } + } + + if (flags & TGA_RIGHTTOLEFT) { // right-to-left, needs horizontal flip + int x; + for (y = 0; y < h; y++) { + void *line = &p->data[0][y * p->linesize[0]]; + for (x = 0; x < w >> 1; x++) { + switch (bpp) { + case 32: + FFSWAP(uint32_t, ((uint32_t *)line)[x], ((uint32_t *)line)[w - x - 1]); + break; + case 24: + FFSWAP(uint8_t, ((uint8_t *)line)[3 * x ], ((uint8_t *)line)[3 * w - 3 * x - 3]); + FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 1], ((uint8_t *)line)[3 * w - 3 * x - 2]); + FFSWAP(uint8_t, ((uint8_t *)line)[3 * x + 2], ((uint8_t *)line)[3 * w - 3 * x - 1]); + break; + case 16: + FFSWAP(uint16_t, ((uint16_t *)line)[x], ((uint16_t *)line)[w - x - 1]); + break; + case 8: + FFSWAP(uint8_t, ((uint8_t *)line)[x], ((uint8_t *)line)[w - x - 1]); + } + } + } + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_targa_decoder = { + .name = "targa", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TARGA, + .priv_data_size = sizeof(TargaContext), + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), +}; diff --git a/ffmpeg/libavcodec/targa.h b/ffmpeg/libavcodec/targa.h new file mode 100644 index 0000000..c2f5224 --- /dev/null +++ b/ffmpeg/libavcodec/targa.h @@ -0,0 +1,48 @@ +/* + * 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 + */ + +#ifndef AVCODEC_TARGA_H +#define AVCODEC_TARGA_H + +/** + * @file + * targa file common definitions + * + * Based on: + * http://www.gamers.org/dEngine/quake3/TGA.txt + * + * and other specs you can find referenced for example in: + * http://en.wikipedia.org/wiki/Truevision_TGA + */ + +enum TargaCompr { + TGA_NODATA = 0, // no image data + TGA_PAL = 1, // palettized + TGA_RGB = 2, // true-color + TGA_BW = 3, // black & white or grayscale + TGA_RLE = 8, // flag pointing that data is RLE-coded +}; + +enum TargaFlags { + TGA_RIGHTTOLEFT = 0x10, // right-to-left (flipped horizontally) + TGA_TOPTOBOTTOM = 0x20, // top-to-bottom (NOT flipped vertically) + TGA_INTERLEAVE2 = 0x40, // 2-way interleave, odd then even lines + TGA_INTERLEAVE4 = 0x80, // 4-way interleave +}; + +#endif /* AVCODEC_TARGA_H */ diff --git a/ffmpeg/libavcodec/targa_y216dec.c b/ffmpeg/libavcodec/targa_y216dec.c new file mode 100644 index 0000000..38694ce --- /dev/null +++ b/ffmpeg/libavcodec/targa_y216dec.c @@ -0,0 +1,90 @@ +/* + * Pinnacle TARGA CineWave YUV16 decoder + * Copyright (c) 2012 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int y216_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV422P16; + avctx->bits_per_raw_sample = 14; + + return 0; +} + +static int y216_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *pic = data; + const uint16_t *src = (uint16_t *)avpkt->data; + uint16_t *y, *u, *v, aligned_width = FFALIGN(avctx->width, 4); + int i, j, ret; + + if (avpkt->size < 4 * avctx->height * aligned_width) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + y = (uint16_t *)pic->data[0]; + u = (uint16_t *)pic->data[1]; + v = (uint16_t *)pic->data[2]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width >> 1; j++) { + u[ j ] = src[4 * j ] << 2 | src[4 * j ] >> 14; + y[2 * j ] = src[4 * j + 1] << 2 | src[4 * j + 1] >> 14; + v[ j ] = src[4 * j + 2] << 2 | src[4 * j + 2] >> 14; + y[2 * j + 1] = src[4 * j + 3] << 2 | src[4 * j + 3] >> 14; + } + + y += pic->linesize[0] >> 1; + u += pic->linesize[1] >> 1; + v += pic->linesize[2] >> 1; + src += aligned_width << 1; + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int y216_decode_close(AVCodecContext *avctx) +{ + + return 0; +} + +AVCodec ff_targa_y216_decoder = { + .name = "targa_y216", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TARGA_Y216, + .init = y216_decode_init, + .decode = y216_decode_frame, + .close = y216_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"), +}; diff --git a/ffmpeg/libavcodec/targaenc.c b/ffmpeg/libavcodec/targaenc.c new file mode 100644 index 0000000..b2c679d --- /dev/null +++ b/ffmpeg/libavcodec/targaenc.c @@ -0,0 +1,201 @@ +/* + * Targa (.tga) image encoder + * Copyright (c) 2007 Bobby Bingham + * + * 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 "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "internal.h" +#include "rle.h" +#include "targa.h" + +typedef struct TargaContext { + AVFrame picture; +} TargaContext; + +/** + * RLE compress the image, with maximum size of out_size + * @param outbuf Output buffer + * @param out_size Maximum output size + * @param pic Image to compress + * @param bpp Bytes per pixel + * @param w Image width + * @param h Image height + * @return Size of output in bytes, or -1 if larger than out_size + */ +static int targa_encode_rle(uint8_t *outbuf, int out_size, const AVFrame *pic, + int bpp, int w, int h) +{ + int y,ret; + uint8_t *out; + + out = outbuf; + + for(y = 0; y < h; y ++) { + ret = ff_rle_encode(out, out_size, pic->data[0] + pic->linesize[0] * y, bpp, w, 0x7f, 0, -1, 0); + if(ret == -1){ + return -1; + } + out+= ret; + out_size -= ret; + } + + return out - outbuf; +} + +static int targa_encode_normal(uint8_t *outbuf, const AVFrame *pic, int bpp, int w, int h) +{ + int i, n = bpp * w; + uint8_t *out = outbuf; + uint8_t *ptr = pic->data[0]; + + for(i=0; i < h; i++) { + memcpy(out, ptr, n); + out += n; + ptr += pic->linesize[0]; + } + + return out - outbuf; +} + +static int targa_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *p, int *got_packet) +{ + int bpp, picsize, datasize = -1, ret, i; + uint8_t *out; + + if(avctx->width > 0xffff || avctx->height > 0xffff) { + av_log(avctx, AV_LOG_ERROR, "image dimensions too large\n"); + return AVERROR(EINVAL); + } + picsize = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + if ((ret = ff_alloc_packet2(avctx, pkt, picsize + 45)) < 0) + return ret; + + /* zero out the header and only set applicable fields */ + memset(pkt->data, 0, 12); + AV_WL16(pkt->data+12, avctx->width); + AV_WL16(pkt->data+14, avctx->height); + /* image descriptor byte: origin is always top-left, bits 0-3 specify alpha */ + pkt->data[17] = 0x20 | (avctx->pix_fmt == AV_PIX_FMT_BGRA ? 8 : 0); + + out = pkt->data + 18; /* skip past the header we write */ + + avctx->bits_per_coded_sample = av_get_bits_per_pixel(av_pix_fmt_desc_get(avctx->pix_fmt)); + switch(avctx->pix_fmt) { + case AV_PIX_FMT_PAL8: { + int pal_bpp = 24; /* Only write 32bit palette if there is transparency information */ + for (i = 0; i < 256; i++) + if (AV_RN32(p->data[1] + 4 * i) >> 24 != 0xFF) { + pal_bpp = 32; + break; + } + pkt->data[1] = 1; /* palette present */ + pkt->data[2] = TGA_PAL; /* uncompressed palettised image */ + pkt->data[6] = 1; /* palette contains 256 entries */ + pkt->data[7] = pal_bpp; /* palette contains pal_bpp bit entries */ + pkt->data[16] = 8; /* bpp */ + for (i = 0; i < 256; i++) + if (pal_bpp == 32) { + AV_WL32(pkt->data + 18 + 4 * i, *(uint32_t *)(p->data[1] + i * 4)); + } else { + AV_WL24(pkt->data + 18 + 3 * i, *(uint32_t *)(p->data[1] + i * 4)); + } + out += 32 * pal_bpp; /* skip past the palette we just output */ + break; + } + case AV_PIX_FMT_GRAY8: + pkt->data[2] = TGA_BW; /* uncompressed grayscale image */ + avctx->bits_per_coded_sample = 0x28; + pkt->data[16] = 8; /* bpp */ + break; + case AV_PIX_FMT_RGB555LE: + pkt->data[2] = TGA_RGB; /* uncompressed true-color image */ + avctx->bits_per_coded_sample = + pkt->data[16] = 16; /* bpp */ + break; + case AV_PIX_FMT_BGR24: + pkt->data[2] = TGA_RGB; /* uncompressed true-color image */ + pkt->data[16] = 24; /* bpp */ + break; + case AV_PIX_FMT_BGRA: + pkt->data[2] = TGA_RGB; /* uncompressed true-color image */ + pkt->data[16] = 32; /* bpp */ + break; + default: + av_log(avctx, AV_LOG_ERROR, "Pixel format '%s' not supported.\n", + av_get_pix_fmt_name(avctx->pix_fmt)); + return AVERROR(EINVAL); + } + bpp = pkt->data[16] >> 3; + + /* try RLE compression */ + if (avctx->coder_type != FF_CODER_TYPE_RAW) + datasize = targa_encode_rle(out, picsize, p, bpp, avctx->width, avctx->height); + + /* if that worked well, mark the picture as RLE compressed */ + if(datasize >= 0) + pkt->data[2] |= TGA_RLE; + + /* if RLE didn't make it smaller, go back to no compression */ + else datasize = targa_encode_normal(out, p, bpp, avctx->width, avctx->height); + + out += datasize; + + /* The standard recommends including this section, even if we don't use + * any of the features it affords. TODO: take advantage of the pixel + * aspect ratio and encoder ID fields available? */ + memcpy(out, "\0\0\0\0\0\0\0\0TRUEVISION-XFILE.", 26); + + pkt->size = out + 26 - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int targa_encode_init(AVCodecContext *avctx) +{ + TargaContext *s = avctx->priv_data; + + avcodec_get_frame_defaults(&s->picture); + s->picture.key_frame= 1; + s->picture.pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame= &s->picture; + + return 0; +} + +AVCodec ff_targa_encoder = { + .name = "targa", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TARGA, + .priv_data_size = sizeof(TargaContext), + .init = targa_encode_init, + .encode2 = targa_encode_frame, + .pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_RGB555LE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, + AV_PIX_FMT_NONE + }, + .long_name= NULL_IF_CONFIG_SMALL("Truevision Targa image"), +}; diff --git a/ffmpeg/libavcodec/textdec.c b/ffmpeg/libavcodec/textdec.c new file mode 100644 index 0000000..f3e6117 --- /dev/null +++ b/ffmpeg/libavcodec/textdec.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2012 Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * Raw subtitles decoder + */ + +#include "avcodec.h" +#include "ass.h" +#include "libavutil/bprint.h" +#include "libavutil/opt.h" + +typedef struct { + AVClass *class; + const char *linebreaks; + int keep_ass_markup; +} TextContext; + +#define OFFSET(x) offsetof(TextContext, x) +#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "keep_ass_markup", "Set if ASS tags must be escaped", OFFSET(keep_ass_markup), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags=SD }, + { NULL } +}; + +static int text_event_to_ass(const AVCodecContext *avctx, AVBPrint *buf, + const char *p, const char *p_end) +{ + const TextContext *text = avctx->priv_data; + + for (; p < p_end && *p; p++) { + + /* forced custom line breaks, not accounted as "normal" EOL */ + if (text->linebreaks && strchr(text->linebreaks, *p)) { + av_bprintf(buf, "\\N"); + + /* standard ASS escaping so random characters don't get mis-interpreted + * as ASS */ + } else if (!text->keep_ass_markup && strchr("{}\\", *p)) { + av_bprintf(buf, "\\%c", *p); + + /* some packets might end abruptly (no \0 at the end, like for example + * in some cases of demuxing from a classic video container), some + * might be terminated with \n or \r\n which we have to remove (for + * consistency with those who haven't), and we also have to deal with + * evil cases such as \r at the end of the buffer (and no \0 terminated + * character) */ + } else if (p[0] == '\n') { + /* some stuff left so we can insert a line break */ + if (p < p_end - 1) + av_bprintf(buf, "\\N"); + } else if (p[0] == '\r' && p < p_end - 1 && p[1] == '\n') { + /* \r followed by a \n, we can skip it. We don't insert the \N yet + * because we don't know if it is followed by more text */ + continue; + + /* finally, a sane character */ + } else { + av_bprint_chars(buf, *p, 1); + } + } + av_bprintf(buf, "\r\n"); + return 0; +} + +static int text_decode_frame(AVCodecContext *avctx, void *data, + int *got_sub_ptr, AVPacket *avpkt) +{ + AVBPrint buf; + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + const int ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100}); + const int ts_duration = avpkt->duration != -1 ? + av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1; + + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + if (ptr && avpkt->size > 0 && *ptr && + !text_event_to_ass(avctx, &buf, ptr, ptr + avpkt->size)) { + if (!av_bprint_is_complete(&buf)) { + av_bprint_finalize(&buf, NULL); + return AVERROR(ENOMEM); + } + ff_ass_add_rect(sub, buf.str, ts_start, ts_duration, 0); + } + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +#define DECLARE_CLASS(decname) static const AVClass decname ## _decoder_class = { \ + .class_name = #decname " decoder", \ + .item_name = av_default_item_name, \ + .option = decname ## _options, \ + .version = LIBAVUTIL_VERSION_INT, \ +} + +#if CONFIG_TEXT_DECODER +#define text_options options +DECLARE_CLASS(text); + +AVCodec ff_text_decoder = { + .name = "text", + .priv_data_size = sizeof(TextContext), + .long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_TEXT, + .decode = text_decode_frame, + .init = ff_ass_subtitle_header_default, + .priv_class = &text_decoder_class, +}; +#endif + +#if CONFIG_VPLAYER_DECODER || CONFIG_PJS_DECODER || CONFIG_SUBVIEWER1_DECODER + +static int linebreak_init(AVCodecContext *avctx) +{ + TextContext *text = avctx->priv_data; + text->linebreaks = "|"; + return ff_ass_subtitle_header_default(avctx); +} + +#if CONFIG_VPLAYER_DECODER +#define vplayer_options options +DECLARE_CLASS(vplayer); + +AVCodec ff_vplayer_decoder = { + .name = "vplayer", + .priv_data_size = sizeof(TextContext), + .long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_VPLAYER, + .decode = text_decode_frame, + .init = linebreak_init, + .priv_class = &vplayer_decoder_class, +}; +#endif + +#if CONFIG_PJS_DECODER +#define pjs_options options +DECLARE_CLASS(pjs); + +AVCodec ff_pjs_decoder = { + .name = "pjs", + .priv_data_size = sizeof(TextContext), + .long_name = NULL_IF_CONFIG_SMALL("PJS subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_PJS, + .decode = text_decode_frame, + .init = linebreak_init, + .priv_class = &pjs_decoder_class, +}; +#endif + +#if CONFIG_SUBVIEWER1_DECODER +#define subviewer1_options options +DECLARE_CLASS(subviewer1); + +AVCodec ff_subviewer1_decoder = { + .name = "subviewer1", + .priv_data_size = sizeof(TextContext), + .long_name = NULL_IF_CONFIG_SMALL("SubViewer1 subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_SUBVIEWER1, + .decode = text_decode_frame, + .init = linebreak_init, + .priv_class = &subviewer1_decoder_class, +}; +#endif + +#endif /* text subtitles with '|' line break */ diff --git a/ffmpeg/libavcodec/thread.h b/ffmpeg/libavcodec/thread.h new file mode 100644 index 0000000..24e62b4 --- /dev/null +++ b/ffmpeg/libavcodec/thread.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2008 Alexander Strange + * + * 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 + */ + +/** + * @file + * Multithreading support functions + * @author Alexander Strange + */ + +#ifndef AVCODEC_THREAD_H +#define AVCODEC_THREAD_H + +#include "libavutil/buffer.h" + +#include "config.h" +#include "avcodec.h" + +typedef struct ThreadFrame { + AVFrame *f; + AVCodecContext *owner; + // progress->data is an array of 2 ints holding progress for top/bottom + // fields + AVBufferRef *progress; +} ThreadFrame; + +/** + * Wait for decoding threads to finish and reset internal state. + * Called by avcodec_flush_buffers(). + * + * @param avctx The context. + */ +void ff_thread_flush(AVCodecContext *avctx); + +/** + * Submit a new frame to a decoding thread. + * Returns the next available frame in picture. *got_picture_ptr + * will be 0 if none is available. + * The return value on success is the size of the consumed packet for + * compatibility with avcodec_decode_video2(). This means the decoder + * has to consume the full packet. + * + * Parameters are the same as avcodec_decode_video2(). + */ +int ff_thread_decode_frame(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, AVPacket *avpkt); + +/** + * If the codec defines update_thread_context(), call this + * when they are ready for the next thread to start decoding + * the next frame. After calling it, do not change any variables + * read by the update_thread_context() method, or call ff_thread_get_buffer(). + * + * @param avctx The context. + */ +void ff_thread_finish_setup(AVCodecContext *avctx); + +/** + * Notify later decoding threads when part of their reference picture is ready. + * Call this when some part of the picture is finished decoding. + * Later calls with lower values of progress have no effect. + * + * @param f The picture being decoded. + * @param progress Value, in arbitrary units, of how much of the picture has decoded. + * @param field The field being decoded, for field-picture codecs. + * 0 for top field or frame pictures, 1 for bottom field. + */ +void ff_thread_report_progress(ThreadFrame *f, int progress, int field); + +/** + * Wait for earlier decoding threads to finish reference pictures. + * Call this before accessing some part of a picture, with a given + * value for progress, and it will return after the responsible decoding + * thread calls ff_thread_report_progress() with the same or + * higher value for progress. + * + * @param f The picture being referenced. + * @param progress Value, in arbitrary units, to wait for. + * @param field The field being referenced, for field-picture codecs. + * 0 for top field or frame pictures, 1 for bottom field. + */ +void ff_thread_await_progress(ThreadFrame *f, int progress, int field); + +/** + * Wrapper around get_buffer() for frame-multithreaded codecs. + * Call this function instead of ff_get_buffer(f). + * Cannot be called after the codec has called ff_thread_finish_setup(). + * + * @param avctx The current context. + * @param f The frame to write into. + */ +int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags); + +/** + * Wrapper around release_buffer() frame-for multithreaded codecs. + * Call this function instead of avctx->release_buffer(f). + * The AVFrame will be copied and the actual release_buffer() call + * will be performed later. The contents of data pointed to by the + * AVFrame should not be changed until ff_thread_get_buffer() is called + * on it. + * + * @param avctx The current context. + * @param f The picture being released. + */ +void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f); + +int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src); + +int ff_thread_init(AVCodecContext *s); +void ff_thread_free(AVCodecContext *s); + +#endif /* AVCODEC_THREAD_H */ diff --git a/ffmpeg/libavcodec/tiertexseqv.c b/ffmpeg/libavcodec/tiertexseqv.c new file mode 100644 index 0000000..f892e4d --- /dev/null +++ b/ffmpeg/libavcodec/tiertexseqv.c @@ -0,0 +1,267 @@ +/* + * Tiertex Limited SEQ Video Decoder + * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) + * + * 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 + */ + +/** + * @file + * Tiertex Limited SEQ video decoder + */ + +#include "avcodec.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" + + +typedef struct SeqVideoContext { + AVCodecContext *avctx; + AVFrame frame; +} SeqVideoContext; + + +static const unsigned char *seq_unpack_rle_block(const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst, int dst_size) +{ + int i, len, sz; + GetBitContext gb; + int code_table[64]; + + /* get the rle codes */ + init_get_bits(&gb, src, (src_end - src) * 8); + for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { + if (get_bits_left(&gb) < 4) + return NULL; + code_table[i] = get_sbits(&gb, 4); + sz += FFABS(code_table[i]); + } + src += (get_bits_count(&gb) + 7) / 8; + + /* do the rle unpacking */ + for (i = 0; i < 64 && dst_size > 0; i++) { + len = code_table[i]; + if (len < 0) { + len = -len; + if (src_end - src < 1) + return NULL; + memset(dst, *src++, FFMIN(len, dst_size)); + } else { + if (src_end - src < len) + return NULL; + memcpy(dst, src, FFMIN(len, dst_size)); + src += len; + } + dst += len; + dst_size -= len; + } + return src; +} + +static const unsigned char *seq_decode_op1(SeqVideoContext *seq, + const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst) +{ + const unsigned char *color_table; + int b, i, len, bits; + GetBitContext gb; + unsigned char block[8 * 8]; + + if (src_end - src < 1) + return NULL; + len = *src++; + if (len & 0x80) { + switch (len & 3) { + case 1: + src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); + for (b = 0; b < 8; b++) { + memcpy(dst, &block[b * 8], 8); + dst += seq->frame.linesize[0]; + } + break; + case 2: + src = seq_unpack_rle_block(src, src_end, block, sizeof(block)); + for (i = 0; i < 8; i++) { + for (b = 0; b < 8; b++) + dst[b * seq->frame.linesize[0]] = block[i * 8 + b]; + ++dst; + } + break; + } + } else { + if (len <= 0) + return NULL; + bits = ff_log2_tab[len - 1] + 1; + if (src_end - src < len + 8 * bits) + return NULL; + color_table = src; + src += len; + init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; + for (b = 0; b < 8; b++) { + for (i = 0; i < 8; i++) + dst[i] = color_table[get_bits(&gb, bits)]; + dst += seq->frame.linesize[0]; + } + } + + return src; +} + +static const unsigned char *seq_decode_op2(SeqVideoContext *seq, + const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst) +{ + int i; + + if (src_end - src < 8 * 8) + return NULL; + + for (i = 0; i < 8; i++) { + memcpy(dst, src, 8); + src += 8; + dst += seq->frame.linesize[0]; + } + + return src; +} + +static const unsigned char *seq_decode_op3(SeqVideoContext *seq, + const unsigned char *src, + const unsigned char *src_end, + unsigned char *dst) +{ + int pos, offset; + + do { + if (src_end - src < 2) + return NULL; + pos = *src++; + offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7); + dst[offset] = *src++; + } while (!(pos & 0x80)); + + return src; +} + +static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size) +{ + const unsigned char *data_end = data + data_size; + GetBitContext gb; + int flags, i, j, x, y, op; + unsigned char c[3]; + unsigned char *dst; + uint32_t *palette; + + flags = *data++; + + if (flags & 1) { + palette = (uint32_t *)seq->frame.data[1]; + if (data_end - data < 256 * 3) + return AVERROR_INVALIDDATA; + for (i = 0; i < 256; i++) { + for (j = 0; j < 3; j++, data++) + c[j] = (*data << 2) | (*data >> 4); + palette[i] = 0xFFU << 24 | AV_RB24(c); + } + seq->frame.palette_has_changed = 1; + } + + if (flags & 2) { + if (data_end - data < 128) + return AVERROR_INVALIDDATA; + init_get_bits(&gb, data, 128 * 8); data += 128; + for (y = 0; y < 128; y += 8) + for (x = 0; x < 256; x += 8) { + dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x]; + op = get_bits(&gb, 2); + switch (op) { + case 1: + data = seq_decode_op1(seq, data, data_end, dst); + break; + case 2: + data = seq_decode_op2(seq, data, data_end, dst); + break; + case 3: + data = seq_decode_op3(seq, data, data_end, dst); + break; + } + if (!data) + return AVERROR_INVALIDDATA; + } + } + return 0; +} + +static av_cold int seqvideo_decode_init(AVCodecContext *avctx) +{ + SeqVideoContext *seq = avctx->priv_data; + + seq->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + avcodec_get_frame_defaults(&seq->frame); + + return 0; +} + +static int seqvideo_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int ret; + + SeqVideoContext *seq = avctx->priv_data; + + if ((ret = ff_reget_buffer(avctx, &seq->frame)) < 0) + return ret; + + if (seqvideo_decode(seq, buf, buf_size)) + return AVERROR_INVALIDDATA; + + if ((ret = av_frame_ref(data, &seq->frame)) < 0) + return ret; + *got_frame = 1; + + return buf_size; +} + +static av_cold int seqvideo_decode_end(AVCodecContext *avctx) +{ + SeqVideoContext *seq = avctx->priv_data; + + av_frame_unref(&seq->frame); + + return 0; +} + +AVCodec ff_tiertexseqvideo_decoder = { + .name = "tiertexseqvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TIERTEXSEQVIDEO, + .priv_data_size = sizeof(SeqVideoContext), + .init = seqvideo_decode_init, + .close = seqvideo_decode_end, + .decode = seqvideo_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), +}; diff --git a/ffmpeg/libavcodec/tiff.c b/ffmpeg/libavcodec/tiff.c new file mode 100644 index 0000000..6c2dc23 --- /dev/null +++ b/ffmpeg/libavcodec/tiff.c @@ -0,0 +1,1237 @@ +/* + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * TIFF image decoder + * @author Konstantin Shishkov + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "config.h" +#if CONFIG_ZLIB +#include +#endif +#include "lzw.h" +#include "tiff.h" +#include "tiff_data.h" +#include "faxcompr.h" +#include "internal.h" +#include "mathops.h" +#include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "libavutil/avstring.h" + +typedef struct TiffContext { + AVCodecContext *avctx; + GetByteContext gb; + + int width, height; + unsigned int bpp, bppcount; + uint32_t palette[256]; + int palette_is_set; + int le; + enum TiffCompr compr; + int invert; + int fax_opts; + int predictor; + int fill_order; + + int strips, rps, sstype; + int sot; + int stripsizesoff, stripsize, stripoff, strippos; + LZWState *lzw; + + uint8_t *deinvert_buf; + int deinvert_buf_size; + + int geotag_count; + TiffGeoTag *geotags; +} TiffContext; + +static unsigned tget_short(GetByteContext *gb, int le) +{ + unsigned v = le ? bytestream2_get_le16(gb) : bytestream2_get_be16(gb); + return v; +} + +static unsigned tget_long(GetByteContext *gb, int le) +{ + unsigned v = le ? bytestream2_get_le32(gb) : bytestream2_get_be32(gb); + return v; +} + +static double tget_double(GetByteContext *gb, int le) +{ + av_alias64 i = { .u64 = le ? bytestream2_get_le64(gb) : bytestream2_get_be64(gb)}; + return i.f64; +} + +static unsigned tget(GetByteContext *gb, int type, int le) +{ + switch (type) { + case TIFF_BYTE : return bytestream2_get_byte(gb); + case TIFF_SHORT: return tget_short(gb, le); + case TIFF_LONG : return tget_long(gb, le); + default : return UINT_MAX; + } +} + +static void free_geotags(TiffContext *const s) +{ + int i; + for (i = 0; i < s->geotag_count; i++) { + if (s->geotags[i].val) + av_freep(&s->geotags[i].val); + } + av_freep(&s->geotags); +} + +#define RET_GEOKEY(TYPE, array, element)\ + if (key >= TIFF_##TYPE##_KEY_ID_OFFSET &&\ + key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(ff_tiff_##array##_name_type_map))\ + return ff_tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].element; + +static const char *get_geokey_name(int key) +{ + RET_GEOKEY(VERT, vert, name); + RET_GEOKEY(PROJ, proj, name); + RET_GEOKEY(GEOG, geog, name); + RET_GEOKEY(CONF, conf, name); + + return NULL; +} + +static int get_geokey_type(int key) +{ + RET_GEOKEY(VERT, vert, type); + RET_GEOKEY(PROJ, proj, type); + RET_GEOKEY(GEOG, geog, type); + RET_GEOKEY(CONF, conf, type); + + return AVERROR_INVALIDDATA; +} + +static int cmp_id_key(const void *id, const void *k) +{ + return *(const int*)id - ((const TiffGeoTagKeyName*)k)->key; +} + +static const char *search_keyval(const TiffGeoTagKeyName *keys, int n, int id) +{ + TiffGeoTagKeyName *r = bsearch(&id, keys, n, sizeof(keys[0]), cmp_id_key); + if(r) + return r->name; + + return NULL; +} + +static char *get_geokey_val(int key, int val) +{ + char *ap; + + if (val == TIFF_GEO_KEY_UNDEFINED) + return av_strdup("undefined"); + if (val == TIFF_GEO_KEY_USER_DEFINED) + return av_strdup("User-Defined"); + +#define RET_GEOKEY_VAL(TYPE, array)\ + if (val >= TIFF_##TYPE##_OFFSET &&\ + val - TIFF_##TYPE##_OFFSET < FF_ARRAY_ELEMS(ff_tiff_##array##_codes))\ + return av_strdup(ff_tiff_##array##_codes[val - TIFF_##TYPE##_OFFSET]); + + switch (key) { + case TIFF_GT_MODEL_TYPE_GEOKEY: + RET_GEOKEY_VAL(GT_MODEL_TYPE, gt_model_type); + break; + case TIFF_GT_RASTER_TYPE_GEOKEY: + RET_GEOKEY_VAL(GT_RASTER_TYPE, gt_raster_type); + break; + case TIFF_GEOG_LINEAR_UNITS_GEOKEY: + case TIFF_PROJ_LINEAR_UNITS_GEOKEY: + case TIFF_VERTICAL_UNITS_GEOKEY: + RET_GEOKEY_VAL(LINEAR_UNIT, linear_unit); + break; + case TIFF_GEOG_ANGULAR_UNITS_GEOKEY: + case TIFF_GEOG_AZIMUTH_UNITS_GEOKEY: + RET_GEOKEY_VAL(ANGULAR_UNIT, angular_unit); + break; + case TIFF_GEOGRAPHIC_TYPE_GEOKEY: + RET_GEOKEY_VAL(GCS_TYPE, gcs_type); + RET_GEOKEY_VAL(GCSE_TYPE, gcse_type); + break; + case TIFF_GEOG_GEODETIC_DATUM_GEOKEY: + RET_GEOKEY_VAL(GEODETIC_DATUM, geodetic_datum); + RET_GEOKEY_VAL(GEODETIC_DATUM_E, geodetic_datum_e); + break; + case TIFF_GEOG_ELLIPSOID_GEOKEY: + RET_GEOKEY_VAL(ELLIPSOID, ellipsoid); + break; + case TIFF_GEOG_PRIME_MERIDIAN_GEOKEY: + RET_GEOKEY_VAL(PRIME_MERIDIAN, prime_meridian); + break; + case TIFF_PROJECTED_CS_TYPE_GEOKEY: + ap = av_strdup(search_keyval(ff_tiff_proj_cs_type_codes, FF_ARRAY_ELEMS(ff_tiff_proj_cs_type_codes), val)); + if(ap) return ap; + break; + case TIFF_PROJECTION_GEOKEY: + ap = av_strdup(search_keyval(ff_tiff_projection_codes, FF_ARRAY_ELEMS(ff_tiff_projection_codes), val)); + if(ap) return ap; + break; + case TIFF_PROJ_COORD_TRANS_GEOKEY: + RET_GEOKEY_VAL(COORD_TRANS, coord_trans); + break; + case TIFF_VERTICAL_CS_TYPE_GEOKEY: + RET_GEOKEY_VAL(VERT_CS, vert_cs); + RET_GEOKEY_VAL(ORTHO_VERT_CS, ortho_vert_cs); + break; + + } + + ap = av_malloc(14); + if (ap) + snprintf(ap, 14, "Unknown-%d", val); + return ap; +} + +static char *doubles2str(double *dp, int count, const char *sep) +{ + int i; + char *ap, *ap0; + uint64_t component_len; + if (!sep) sep = ", "; + component_len = 15LL + strlen(sep); + if (count >= (INT_MAX - 1)/component_len) + return NULL; + ap = av_malloc(component_len * count + 1); + if (!ap) + return NULL; + ap0 = ap; + ap[0] = '\0'; + for (i = 0; i < count; i++) { + unsigned l = snprintf(ap, component_len, "%f%s", dp[i], sep); + if(l >= component_len) { + av_free(ap0); + return NULL; + } + ap += l; + } + ap0[strlen(ap0) - strlen(sep)] = '\0'; + return ap0; +} + +static char *shorts2str(int16_t *sp, int count, const char *sep) +{ + int i; + char *ap, *ap0; + uint64_t component_len; + if (!sep) sep = ", "; + component_len = 7LL + strlen(sep); + if (count >= (INT_MAX - 1)/component_len) + return NULL; + ap = av_malloc(component_len * count + 1); + if (!ap) + return NULL; + ap0 = ap; + ap[0] = '\0'; + for (i = 0; i < count; i++) { + unsigned l = snprintf(ap, component_len, "%d%s", sp[i], sep); + if (l >= component_len) { + av_free(ap0); + return NULL; + } + ap += l; + } + ap0[strlen(ap0) - strlen(sep)] = '\0'; + return ap0; +} + +static int add_doubles_metadata(int count, + const char *name, const char *sep, + TiffContext *s, AVFrame *frame) +{ + char *ap; + int i; + double *dp; + + if (count >= INT_MAX / sizeof(int64_t) || count <= 0) + return AVERROR_INVALIDDATA; + if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t)) + return AVERROR_INVALIDDATA; + + dp = av_malloc(count * sizeof(double)); + if (!dp) + return AVERROR(ENOMEM); + + for (i = 0; i < count; i++) + dp[i] = tget_double(&s->gb, s->le); + ap = doubles2str(dp, count, sep); + av_freep(&dp); + if (!ap) + return AVERROR(ENOMEM); + av_dict_set(avpriv_frame_get_metadatap(frame), name, ap, AV_DICT_DONT_STRDUP_VAL); + return 0; +} + +static int add_shorts_metadata(int count, const char *name, + const char *sep, TiffContext *s, AVFrame *frame) +{ + char *ap; + int i; + int16_t *sp; + + if (count >= INT_MAX / sizeof(int16_t) || count <= 0) + return AVERROR_INVALIDDATA; + if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int16_t)) + return AVERROR_INVALIDDATA; + + sp = av_malloc(count * sizeof(int16_t)); + if (!sp) + return AVERROR(ENOMEM); + + for (i = 0; i < count; i++) + sp[i] = tget_short(&s->gb, s->le); + ap = shorts2str(sp, count, sep); + av_freep(&sp); + if (!ap) + return AVERROR(ENOMEM); + av_dict_set(avpriv_frame_get_metadatap(frame), name, ap, AV_DICT_DONT_STRDUP_VAL); + return 0; +} + +static int add_string_metadata(int count, const char *name, + TiffContext *s, AVFrame *frame) +{ + char *value; + + if (bytestream2_get_bytes_left(&s->gb) < count || count < 0) + return AVERROR_INVALIDDATA; + + value = av_malloc(count + 1); + if (!value) + return AVERROR(ENOMEM); + + bytestream2_get_bufferu(&s->gb, value, count); + value[count] = 0; + + av_dict_set(avpriv_frame_get_metadatap(frame), name, value, AV_DICT_DONT_STRDUP_VAL); + return 0; +} + +static int add_metadata(int count, int type, + const char *name, const char *sep, TiffContext *s, AVFrame *frame) +{ + switch(type) { + case TIFF_DOUBLE: return add_doubles_metadata(count, name, sep, s, frame); + case TIFF_SHORT : return add_shorts_metadata(count, name, sep, s, frame); + case TIFF_STRING: return add_string_metadata(count, name, s, frame); + default : return AVERROR_INVALIDDATA; + }; +} + +#if CONFIG_ZLIB +static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src, + int size) +{ + z_stream zstream = { 0 }; + int zret; + + zstream.next_in = (uint8_t *)src; + zstream.avail_in = size; + zstream.next_out = dst; + zstream.avail_out = *len; + zret = inflateInit(&zstream); + if (zret != Z_OK) { + av_log(NULL, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return zret; + } + zret = inflate(&zstream, Z_SYNC_FLUSH); + inflateEnd(&zstream); + *len = zstream.total_out; + return zret == Z_STREAM_END ? Z_OK : zret; +} +#endif + +static void av_always_inline horizontal_fill(unsigned int bpp, uint8_t* dst, + int usePtr, const uint8_t *src, + uint8_t c, int width, int offset) +{ + switch (bpp) { + case 1: + while (--width >= 0) { + dst[(width+offset)*8+7] = (usePtr ? src[width] : c) & 0x1; + dst[(width+offset)*8+6] = (usePtr ? src[width] : c) >> 1 & 0x1; + dst[(width+offset)*8+5] = (usePtr ? src[width] : c) >> 2 & 0x1; + dst[(width+offset)*8+4] = (usePtr ? src[width] : c) >> 3 & 0x1; + dst[(width+offset)*8+3] = (usePtr ? src[width] : c) >> 4 & 0x1; + dst[(width+offset)*8+2] = (usePtr ? src[width] : c) >> 5 & 0x1; + dst[(width+offset)*8+1] = (usePtr ? src[width] : c) >> 6 & 0x1; + dst[(width+offset)*8+0] = (usePtr ? src[width] : c) >> 7; + } + break; + case 2: + while (--width >= 0) { + dst[(width+offset)*4+3] = (usePtr ? src[width] : c) & 0x3; + dst[(width+offset)*4+2] = (usePtr ? src[width] : c) >> 2 & 0x3; + dst[(width+offset)*4+1] = (usePtr ? src[width] : c) >> 4 & 0x3; + dst[(width+offset)*4+0] = (usePtr ? src[width] : c) >> 6; + } + break; + case 4: + while (--width >= 0) { + dst[(width+offset)*2+1] = (usePtr ? src[width] : c) & 0xF; + dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; + } + break; + default: + if (usePtr) { + memcpy(dst + offset, src, width); + } else { + memset(dst + offset, c, width); + } + } +} + +static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, + const uint8_t *src, int size, int lines) +{ + int c, line, pixels, code, ret; + const uint8_t *ssrc = src; + int width = ((s->width * s->bpp) + 7) >> 3; + + if (size <= 0) + return AVERROR_INVALIDDATA; + +#if CONFIG_ZLIB + if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) { + uint8_t *src2 = NULL, *zbuf; + unsigned long outlen; + int i, ret; + outlen = width * lines; + zbuf = av_malloc(outlen); + if (!zbuf) + return AVERROR(ENOMEM); + if (s->fill_order) { + src2 = av_malloc((unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!src2) { + av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); + av_free(zbuf); + return AVERROR(ENOMEM); + } + for (i = 0; i < size; i++) + src2[i] = ff_reverse[src[i]]; + memset(src2 + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + src = src2; + } + ret = tiff_uncompress(zbuf, &outlen, src, size); + if (ret != Z_OK) { + av_log(s->avctx, AV_LOG_ERROR, + "Uncompressing failed (%lu of %lu) with error %d\n", outlen, + (unsigned long)width * lines, ret); + av_free(src2); + av_free(zbuf); + return AVERROR_UNKNOWN; + } + src = zbuf; + for (line = 0; line < lines; line++) { + if(s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8){ + horizontal_fill(s->bpp, dst, 1, src, 0, width, 0); + }else{ + memcpy(dst, src, width); + } + dst += stride; + src += width; + } + av_free(src2); + av_free(zbuf); + return 0; + } +#endif + if (s->compr == TIFF_LZW) { + if (s->fill_order) { + int i; + av_fast_padded_malloc(&s->deinvert_buf, &s->deinvert_buf_size, size); + if (!s->deinvert_buf) + return AVERROR(ENOMEM); + for (i = 0; i < size; i++) + s->deinvert_buf[i] = ff_reverse[src[i]]; + src = s->deinvert_buf; + ssrc = src; + } + if (size > 1 && !src[0] && (src[1]&1)) { + av_log(s->avctx, AV_LOG_ERROR, "Old style LZW is unsupported\n"); + } + if ((ret = ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF)) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n"); + return ret; + } + } + if (s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3 + || s->compr == TIFF_G4) { + int i, ret = 0; + uint8_t *src2 = av_malloc((unsigned)size + + FF_INPUT_BUFFER_PADDING_SIZE); + + if (!src2) { + av_log(s->avctx, AV_LOG_ERROR, + "Error allocating temporary buffer\n"); + return AVERROR(ENOMEM); + } + if (s->fax_opts & 2) { + av_log(s->avctx, AV_LOG_ERROR, + "Uncompressed fax mode is not supported (yet)\n"); + av_free(src2); + return AVERROR_INVALIDDATA; + } + if (!s->fill_order) { + memcpy(src2, src, size); + } else { + for (i = 0; i < size; i++) + src2[i] = ff_reverse[src[i]]; + } + memset(src2 + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + switch (s->compr) { + case TIFF_CCITT_RLE: + case TIFF_G3: + case TIFF_G4: + ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, + s->compr, s->fax_opts); + break; + } + if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) + for (line = 0; line < lines; line++) { + horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0); + dst += stride; + } + av_free(src2); + return ret; + } + for (line = 0; line < lines; line++) { + if (src - ssrc > size) { + av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); + return AVERROR_INVALIDDATA; + } + switch (s->compr) { + case TIFF_RAW: + if (ssrc + size - src < width) + return AVERROR_INVALIDDATA; + if (!s->fill_order) { + horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8), + dst, 1, src, 0, width, 0); + } else { + int i; + for (i = 0; i < width; i++) + dst[i] = ff_reverse[src[i]]; + } + src += width; + break; + case TIFF_PACKBITS: + for (pixels = 0; pixels < width;) { + if (ssrc + size - src < 2) { + av_log(s->avctx, AV_LOG_ERROR, "Read went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + code = (int8_t) * src++; + if (code >= 0) { + code++; + if (pixels + code > width) { + av_log(s->avctx, AV_LOG_ERROR, + "Copy went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + if (ssrc + size - src < code) { + av_log(s->avctx, AV_LOG_ERROR, "Read went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8), + dst, 1, src, 0, code, pixels); + src += code; + pixels += code; + } else if (code != -128) { // -127..-1 + code = (-code) + 1; + if (pixels + code > width) { + av_log(s->avctx, AV_LOG_ERROR, + "Run went out of bounds\n"); + return AVERROR_INVALIDDATA; + } + c = *src++; + horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8), + dst, 0, NULL, c, code, pixels); + pixels += code; + } + } + break; + case TIFF_LZW: + pixels = ff_lzw_decode(s->lzw, dst, width); + if (pixels < width) { + av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", + pixels, width); + return AVERROR_INVALIDDATA; + } + if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) + horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0); + break; + } + dst += stride; + } + return 0; +} + +static int init_image(TiffContext *s, AVFrame *frame) +{ + int i, ret; + uint32_t *pal; + + switch (s->bpp * 10 + s->bppcount) { + case 11: + if (!s->palette_is_set) { + s->avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; + break; + } + case 21: + case 41: + case 81: + s->avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + case 243: + s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + break; + case 161: + s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GRAY16LE : AV_PIX_FMT_GRAY16BE; + break; + case 162: + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8A; + break; + case 324: + s->avctx->pix_fmt = AV_PIX_FMT_RGBA; + break; + case 483: + s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; + break; + case 644: + s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, + "This format is not supported (bpp=%d, bppcount=%d)\n", + s->bpp, s->bppcount); + return AVERROR_INVALIDDATA; + } + if (s->width != s->avctx->width || s->height != s->avctx->height) { + if ((ret = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0) + return ret; + avcodec_set_dimensions(s->avctx, s->width, s->height); + } + if ((ret = ff_get_buffer(s->avctx, frame, 0)) < 0) + return ret; + if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8) { + if (s->palette_is_set) { + memcpy(frame->data[1], s->palette, sizeof(s->palette)); + } else { + /* make default grayscale pal */ + pal = (uint32_t *) frame->data[1]; + for (i = 0; i < 1<bpp; i++) + pal[i] = 0xFFU << 24 | i * 255 / ((1<bpp) - 1) * 0x010101; + } + } + return 0; +} + +static int tiff_decode_tag(TiffContext *s, AVFrame *frame) +{ + unsigned tag, type, count, off, value = 0; + int i, j, k, pos, start; + int ret; + uint32_t *pal; + double *dp; + + tag = tget_short(&s->gb, s->le); + type = tget_short(&s->gb, s->le); + count = tget_long(&s->gb, s->le); + off = tget_long(&s->gb, s->le); + start = bytestream2_tell(&s->gb); + + if (type == 0 || type >= FF_ARRAY_ELEMS(type_sizes)) { + av_log(s->avctx, AV_LOG_DEBUG, "Unknown tiff type (%u) encountered\n", + type); + return 0; + } + + if (count == 1) { + switch (type) { + case TIFF_BYTE: + case TIFF_SHORT: + bytestream2_seek(&s->gb, -4, SEEK_CUR); + value = tget(&s->gb, type, s->le); + break; + case TIFF_LONG: + value = off; + break; + case TIFF_STRING: + if (count <= 4) { + bytestream2_seek(&s->gb, -4, SEEK_CUR); + break; + } + default: + value = UINT_MAX; + bytestream2_seek(&s->gb, off, SEEK_SET); + } + } else { + if (count <= 4 && type_sizes[type] * count <= 4) { + bytestream2_seek(&s->gb, -4, SEEK_CUR); + } else { + bytestream2_seek(&s->gb, off, SEEK_SET); + } + } + + switch (tag) { + case TIFF_WIDTH: + s->width = value; + break; + case TIFF_HEIGHT: + s->height = value; + break; + case TIFF_BPP: + s->bppcount = count; + if (count > 4) { + av_log(s->avctx, AV_LOG_ERROR, + "This format is not supported (bpp=%d, %d components)\n", + s->bpp, count); + return AVERROR_INVALIDDATA; + } + if (count == 1) + s->bpp = value; + else { + switch (type) { + case TIFF_BYTE: + s->bpp = (off & 0xFF) + ((off >> 8) & 0xFF) + + ((off >> 16) & 0xFF) + ((off >> 24) & 0xFF); + break; + case TIFF_SHORT: + case TIFF_LONG: + s->bpp = 0; + if (bytestream2_get_bytes_left(&s->gb) < type_sizes[type] * count) + return AVERROR_INVALIDDATA; + for (i = 0; i < count; i++) + s->bpp += tget(&s->gb, type, s->le); + break; + default: + s->bpp = -1; + } + } + break; + case TIFF_SAMPLES_PER_PIXEL: + if (count != 1) { + av_log(s->avctx, AV_LOG_ERROR, + "Samples per pixel requires a single value, many provided\n"); + return AVERROR_INVALIDDATA; + } + if (value > 4U) { + av_log(s->avctx, AV_LOG_ERROR, + "Samples per pixel %d is too large\n", value); + return AVERROR_INVALIDDATA; + } + if (s->bppcount == 1) + s->bpp *= value; + s->bppcount = value; + break; + case TIFF_COMPR: + s->compr = value; + s->predictor = 0; + switch (s->compr) { + case TIFF_RAW: + case TIFF_PACKBITS: + case TIFF_LZW: + case TIFF_CCITT_RLE: + break; + case TIFF_G3: + case TIFF_G4: + s->fax_opts = 0; + break; + case TIFF_DEFLATE: + case TIFF_ADOBE_DEFLATE: +#if CONFIG_ZLIB + break; +#else + av_log(s->avctx, AV_LOG_ERROR, "Deflate: ZLib not compiled in\n"); + return AVERROR(ENOSYS); +#endif + case TIFF_JPEG: + case TIFF_NEWJPEG: + av_log(s->avctx, AV_LOG_ERROR, + "JPEG compression is not supported\n"); + return AVERROR_PATCHWELCOME; + default: + av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", + s->compr); + return AVERROR_INVALIDDATA; + } + break; + case TIFF_ROWSPERSTRIP: + if (type == TIFF_LONG && value == UINT_MAX) + value = s->height; + if (value < 1) { + av_log(s->avctx, AV_LOG_ERROR, + "Incorrect value of rows per strip\n"); + return AVERROR_INVALIDDATA; + } + s->rps = value; + break; + case TIFF_STRIP_OFFS: + if (count == 1) { + s->strippos = 0; + s->stripoff = value; + } else + s->strippos = off; + s->strips = count; + if (s->strips == 1) + s->rps = s->height; + s->sot = type; + if (s->strippos > bytestream2_size(&s->gb)) { + av_log(s->avctx, AV_LOG_ERROR, + "Tag referencing position outside the image\n"); + return AVERROR_INVALIDDATA; + } + break; + case TIFF_STRIP_SIZE: + if (count == 1) { + s->stripsizesoff = 0; + s->stripsize = value; + s->strips = 1; + } else { + s->stripsizesoff = off; + } + s->strips = count; + s->sstype = type; + if (s->stripsizesoff > bytestream2_size(&s->gb)) { + av_log(s->avctx, AV_LOG_ERROR, + "Tag referencing position outside the image\n"); + return AVERROR_INVALIDDATA; + } + break; + case TIFF_TILE_BYTE_COUNTS: + case TIFF_TILE_LENGTH: + case TIFF_TILE_OFFSETS: + case TIFF_TILE_WIDTH: + av_log(s->avctx, AV_LOG_ERROR, "Tiled images are not supported\n"); + return AVERROR_PATCHWELCOME; + break; + case TIFF_PREDICTOR: + s->predictor = value; + break; + case TIFF_INVERT: + switch (value) { + case 0: + s->invert = 1; + break; + case 1: + s->invert = 0; + break; + case 2: + case 3: + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "Color mode %d is not supported\n", + value); + return AVERROR_INVALIDDATA; + } + break; + case TIFF_FILL_ORDER: + if (value < 1 || value > 2) { + av_log(s->avctx, AV_LOG_ERROR, + "Unknown FillOrder value %d, trying default one\n", value); + value = 1; + } + s->fill_order = value - 1; + break; + case TIFF_PAL: + pal = (uint32_t *) s->palette; + off = type_sizes[type]; + if (count / 3 > 256 || bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3) + return AVERROR_INVALIDDATA; + off = (type_sizes[type] - 1) << 3; + for (k = 2; k >= 0; k--) { + for (i = 0; i < count / 3; i++) { + if (k == 2) + pal[i] = 0xFFU << 24; + j = (tget(&s->gb, type, s->le) >> off) << (k * 8); + pal[i] |= j; + } + } + s->palette_is_set = 1; + break; + case TIFF_PLANAR: + if (value == 2) { + av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n"); + return AVERROR_PATCHWELCOME; + } + break; + case TIFF_T4OPTIONS: + if (s->compr == TIFF_G3) + s->fax_opts = value; + break; + case TIFF_T6OPTIONS: + if (s->compr == TIFF_G4) + s->fax_opts = value; + break; +#define ADD_METADATA(count, name, sep)\ + if ((ret = add_metadata(count, type, name, sep, s, frame)) < 0) {\ + av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");\ + return ret;\ + } + case TIFF_MODEL_PIXEL_SCALE: + ADD_METADATA(count, "ModelPixelScaleTag", NULL); + break; + case TIFF_MODEL_TRANSFORMATION: + ADD_METADATA(count, "ModelTransformationTag", NULL); + break; + case TIFF_MODEL_TIEPOINT: + ADD_METADATA(count, "ModelTiepointTag", NULL); + break; + case TIFF_GEO_KEY_DIRECTORY: + ADD_METADATA(1, "GeoTIFF_Version", NULL); + ADD_METADATA(2, "GeoTIFF_Key_Revision", "."); + s->geotag_count = tget_short(&s->gb, s->le); + if (s->geotag_count > count / 4 - 1) { + s->geotag_count = count / 4 - 1; + av_log(s->avctx, AV_LOG_WARNING, "GeoTIFF key directory buffer shorter than specified\n"); + } + if (bytestream2_get_bytes_left(&s->gb) < s->geotag_count * sizeof(int16_t) * 4) { + s->geotag_count = 0; + return -1; + } + s->geotags = av_mallocz(sizeof(TiffGeoTag) * s->geotag_count); + if (!s->geotags) { + av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); + s->geotag_count = 0; + return AVERROR(ENOMEM); + } + for (i = 0; i < s->geotag_count; i++) { + s->geotags[i].key = tget_short(&s->gb, s->le); + s->geotags[i].type = tget_short(&s->gb, s->le); + s->geotags[i].count = tget_short(&s->gb, s->le); + + if (!s->geotags[i].type) + s->geotags[i].val = get_geokey_val(s->geotags[i].key, tget_short(&s->gb, s->le)); + else + s->geotags[i].offset = tget_short(&s->gb, s->le); + } + break; + case TIFF_GEO_DOUBLE_PARAMS: + if (count >= INT_MAX / sizeof(int64_t)) + return AVERROR_INVALIDDATA; + if (bytestream2_get_bytes_left(&s->gb) < count * sizeof(int64_t)) + return AVERROR_INVALIDDATA; + dp = av_malloc(count * sizeof(double)); + if (!dp) { + av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); + return AVERROR(ENOMEM); + } + for (i = 0; i < count; i++) + dp[i] = tget_double(&s->gb, s->le); + for (i = 0; i < s->geotag_count; i++) { + if (s->geotags[i].type == TIFF_GEO_DOUBLE_PARAMS) { + if (s->geotags[i].count == 0 + || s->geotags[i].offset + s->geotags[i].count > count) { + av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key); + } else { + char *ap = doubles2str(&dp[s->geotags[i].offset], s->geotags[i].count, ", "); + if (!ap) { + av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); + av_freep(&dp); + return AVERROR(ENOMEM); + } + s->geotags[i].val = ap; + } + } + } + av_freep(&dp); + break; + case TIFF_GEO_ASCII_PARAMS: + pos = bytestream2_tell(&s->gb); + for (i = 0; i < s->geotag_count; i++) { + if (s->geotags[i].type == TIFF_GEO_ASCII_PARAMS) { + if (s->geotags[i].count == 0 + || s->geotags[i].offset + s->geotags[i].count > count) { + av_log(s->avctx, AV_LOG_WARNING, "Invalid GeoTIFF key %d\n", s->geotags[i].key); + } else { + char *ap; + + bytestream2_seek(&s->gb, pos + s->geotags[i].offset, SEEK_SET); + if (bytestream2_get_bytes_left(&s->gb) < s->geotags[i].count) + return AVERROR_INVALIDDATA; + ap = av_malloc(s->geotags[i].count); + if (!ap) { + av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); + return AVERROR(ENOMEM); + } + bytestream2_get_bufferu(&s->gb, ap, s->geotags[i].count); + ap[s->geotags[i].count - 1] = '\0'; //replace the "|" delimiter with a 0 byte + s->geotags[i].val = ap; + } + } + } + break; + case TIFF_ARTIST: + ADD_METADATA(count, "artist", NULL); + break; + case TIFF_COPYRIGHT: + ADD_METADATA(count, "copyright", NULL); + break; + case TIFF_DATE: + ADD_METADATA(count, "date", NULL); + break; + case TIFF_DOCUMENT_NAME: + ADD_METADATA(count, "document_name", NULL); + break; + case TIFF_HOST_COMPUTER: + ADD_METADATA(count, "computer", NULL); + break; + case TIFF_IMAGE_DESCRIPTION: + ADD_METADATA(count, "description", NULL); + break; + case TIFF_MAKE: + ADD_METADATA(count, "make", NULL); + break; + case TIFF_MODEL: + ADD_METADATA(count, "model", NULL); + break; + case TIFF_PAGE_NAME: + ADD_METADATA(count, "page_name", NULL); + break; + case TIFF_PAGE_NUMBER: + ADD_METADATA(count, "page_number", " / "); + break; + case TIFF_SOFTWARE_NAME: + ADD_METADATA(count, "software", NULL); + break; + default: + av_log(s->avctx, AV_LOG_DEBUG, "Unknown or unsupported tag %d/0X%0X\n", + tag, tag); + } + bytestream2_seek(&s->gb, start, SEEK_SET); + return 0; +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, AVPacket *avpkt) +{ + TiffContext *const s = avctx->priv_data; + AVFrame *const p = data; + unsigned off; + int id, le, ret; + int i, j, entries; + int stride; + unsigned soff, ssize; + uint8_t *dst; + GetByteContext stripsizes; + GetByteContext stripdata; + + bytestream2_init(&s->gb, avpkt->data, avpkt->size); + + //parse image header + if (avpkt->size < 8) + return AVERROR_INVALIDDATA; + id = bytestream2_get_le16u(&s->gb); + if (id == 0x4949) + le = 1; + else if (id == 0x4D4D) + le = 0; + else { + av_log(avctx, AV_LOG_ERROR, "TIFF header not found\n"); + return AVERROR_INVALIDDATA; + } + s->le = le; + // TIFF_BPP is not a required tag and defaults to 1 + s->bppcount = s->bpp = 1; + s->invert = 0; + s->compr = TIFF_RAW; + s->fill_order = 0; + free_geotags(s); + + // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number + // that further identifies the file as a TIFF file" + if (tget_short(&s->gb, le) != 42) { + av_log(avctx, AV_LOG_ERROR, + "The answer to life, universe and everything is not correct!\n"); + return AVERROR_INVALIDDATA; + } + // Reset these offsets so we can tell if they were set this frame + s->stripsizesoff = s->strippos = 0; + /* parse image file directory */ + off = tget_long(&s->gb, le); + if (off >= UINT_MAX - 14 || avpkt->size < off + 14) { + av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image size\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_seek(&s->gb, off, SEEK_SET); + entries = tget_short(&s->gb, le); + if (bytestream2_get_bytes_left(&s->gb) < entries * 12) + return AVERROR_INVALIDDATA; + for (i = 0; i < entries; i++) { + if ((ret = tiff_decode_tag(s, p)) < 0) + return ret; + } + + for (i = 0; igeotag_count; i++) { + const char *keyname = get_geokey_name(s->geotags[i].key); + if (!keyname) { + av_log(avctx, AV_LOG_WARNING, "Unknown or unsupported GeoTIFF key %d\n", s->geotags[i].key); + continue; + } + if (get_geokey_type(s->geotags[i].key) != s->geotags[i].type) { + av_log(avctx, AV_LOG_WARNING, "Type of GeoTIFF key %d is wrong\n", s->geotags[i].key); + continue; + } + ret = av_dict_set(avpriv_frame_get_metadatap(p), keyname, s->geotags[i].val, 0); + if (ret<0) { + av_log(avctx, AV_LOG_ERROR, "Writing metadata with key '%s' failed\n", keyname); + return ret; + } + } + + if (!s->strippos && !s->stripoff) { + av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); + return AVERROR_INVALIDDATA; + } + /* now we have the data and may start decoding */ + if ((ret = init_image(s, p)) < 0) + return ret; + + if (s->strips == 1 && !s->stripsize) { + av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); + s->stripsize = avpkt->size - s->stripoff; + } + stride = p->linesize[0]; + dst = p->data[0]; + + if (s->stripsizesoff) { + if (s->stripsizesoff >= (unsigned)avpkt->size) + return AVERROR_INVALIDDATA; + bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, avpkt->size - s->stripsizesoff); + } + if (s->strippos) { + if (s->strippos >= (unsigned)avpkt->size) + return AVERROR_INVALIDDATA; + bytestream2_init(&stripdata, avpkt->data + s->strippos, avpkt->size - s->strippos); + } + + if (s->rps <= 0) { + av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < s->height; i += s->rps) { + if (s->stripsizesoff) + ssize = tget(&stripsizes, s->sstype, s->le); + else + ssize = s->stripsize; + + if (s->strippos) + soff = tget(&stripdata, s->sot, s->le); + else + soff = s->stripoff; + + if (soff > avpkt->size || ssize > avpkt->size - soff) { + av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); + return AVERROR_INVALIDDATA; + } + if (tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize, + FFMIN(s->rps, s->height - i)) < 0) + break; + dst += s->rps * stride; + } + if (s->predictor == 2) { + dst = p->data[0]; + soff = s->bpp >> 3; + ssize = s->width * soff; + if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48LE || + s->avctx->pix_fmt == AV_PIX_FMT_RGBA64LE) { + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j += 2) + AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff)); + dst += stride; + } + } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48BE || + s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j += 2) + AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff)); + dst += stride; + } + } else { + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j++) + dst[j] += dst[j - soff]; + dst += stride; + } + } + } + + if (s->invert) { + dst = p->data[0]; + for (i = 0; i < s->height; i++) { + for (j = 0; j < p->linesize[0]; j++) + dst[j] = (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 ? (1<bpp) - 1 : 255) - dst[j]; + dst += p->linesize[0]; + } + } + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int tiff_init(AVCodecContext *avctx) +{ + TiffContext *s = avctx->priv_data; + + s->width = 0; + s->height = 0; + s->avctx = avctx; + ff_lzw_decode_open(&s->lzw); + ff_ccitt_unpack_init(); + + return 0; +} + +static av_cold int tiff_end(AVCodecContext *avctx) +{ + TiffContext *const s = avctx->priv_data; + + free_geotags(s); + + ff_lzw_decode_close(&s->lzw); + av_freep(&s->deinvert_buf); + return 0; +} + +AVCodec ff_tiff_decoder = { + .name = "tiff", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TIFF, + .priv_data_size = sizeof(TiffContext), + .init = tiff_init, + .close = tiff_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), +}; diff --git a/ffmpeg/libavcodec/tiff.h b/ffmpeg/libavcodec/tiff.h new file mode 100644 index 0000000..6d760f0 --- /dev/null +++ b/ffmpeg/libavcodec/tiff.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * TIFF tables + * + * For more information about the TIFF format, check the official docs at: + * http://partners.adobe.com/public/developer/tiff/index.html + * @author Konstantin Shishkov + */ + +#ifndef AVCODEC_TIFF_H +#define AVCODEC_TIFF_H + +#include + +/** abridged list of TIFF tags */ +enum TiffTags{ + TIFF_SUBFILE = 0xfe, + TIFF_WIDTH = 0x100, + TIFF_HEIGHT, + TIFF_BPP, + TIFF_COMPR, + TIFF_INVERT = 0x106, + TIFF_FILL_ORDER = 0x10A, + TIFF_DOCUMENT_NAME = 0x10D, + TIFF_IMAGE_DESCRIPTION = 0x10E, + TIFF_MAKE = 0x10F, + TIFF_MODEL = 0x110, + TIFF_STRIP_OFFS = 0x111, + TIFF_SAMPLES_PER_PIXEL = 0x115, + TIFF_ROWSPERSTRIP = 0x116, + TIFF_STRIP_SIZE, + TIFF_XRES = 0x11A, + TIFF_YRES = 0x11B, + TIFF_PLANAR = 0x11C, + TIFF_PAGE_NAME = 0x11D, + TIFF_XPOS = 0x11E, + TIFF_YPOS = 0x11F, + TIFF_T4OPTIONS = 0x124, + TIFF_T6OPTIONS, + TIFF_RES_UNIT = 0x128, + TIFF_PAGE_NUMBER = 0x129, + TIFF_SOFTWARE_NAME = 0x131, + TIFF_DATE = 0x132, + TIFF_ARTIST = 0x13B, + TIFF_HOST_COMPUTER = 0x13C, + TIFF_PREDICTOR = 0x13D, + TIFF_PAL = 0x140, + TIFF_TILE_WIDTH = 0x142, + TIFF_TILE_LENGTH = 0x143, + TIFF_TILE_OFFSETS = 0x144, + TIFF_TILE_BYTE_COUNTS = 0x145, + TIFF_EXTRASAMPLES = 0x152, + TIFF_YCBCR_COEFFICIENTS = 0x211, + TIFF_YCBCR_SUBSAMPLING = 0x212, + TIFF_YCBCR_POSITIONING = 0x213, + TIFF_REFERENCE_BW = 0x214, + TIFF_COPYRIGHT = 0x8298, + TIFF_MODEL_TIEPOINT = 0x8482, + TIFF_MODEL_PIXEL_SCALE = 0x830E, + TIFF_MODEL_TRANSFORMATION = 0x8480, + TIFF_GEO_KEY_DIRECTORY = 0x87AF, + TIFF_GEO_DOUBLE_PARAMS = 0x87B0, + TIFF_GEO_ASCII_PARAMS = 0x87B1 +}; + +/** list of TIFF compression types */ +enum TiffCompr{ + TIFF_RAW = 1, + TIFF_CCITT_RLE, + TIFF_G3, + TIFF_G4, + TIFF_LZW, + TIFF_JPEG, + TIFF_NEWJPEG, + TIFF_ADOBE_DEFLATE, + TIFF_PACKBITS = 0x8005, + TIFF_DEFLATE = 0x80B2 +}; + +enum TiffTypes{ + TIFF_BYTE = 1, + TIFF_STRING, + TIFF_SHORT, + TIFF_LONG, + TIFF_RATIONAL, + TIFF_SBYTE, + TIFF_UNDEFINED, + TIFF_SSHORT, + TIFF_SLONG, + TIFF_SRATIONAL, + TIFF_FLOAT, + TIFF_DOUBLE, + TIFF_IFD +}; + +enum TiffGeoTagKey { + TIFF_GT_MODEL_TYPE_GEOKEY = 1024, + TIFF_GT_RASTER_TYPE_GEOKEY = 1025, + TIFF_GT_CITATION_GEOKEY = 1026, + TIFF_GEOGRAPHIC_TYPE_GEOKEY = 2048, + TIFF_GEOG_CITATION_GEOKEY = 2049, + TIFF_GEOG_GEODETIC_DATUM_GEOKEY = 2050, + TIFF_GEOG_PRIME_MERIDIAN_GEOKEY = 2051, + TIFF_GEOG_LINEAR_UNITS_GEOKEY = 2052, + TIFF_GEOG_LINEAR_UNIT_SIZE_GEOKEY = 2053, + TIFF_GEOG_ANGULAR_UNITS_GEOKEY = 2054, + TIFF_GEOG_ANGULAR_UNIT_SIZE_GEOKEY = 2055, + TIFF_GEOG_ELLIPSOID_GEOKEY = 2056, + TIFF_GEOG_SEMI_MAJOR_AXIS_GEOKEY = 2057, + TIFF_GEOG_SEMI_MINOR_AXIS_GEOKEY = 2058, + TIFF_GEOG_INV_FLATTENING_GEOKEY = 2059, + TIFF_GEOG_AZIMUTH_UNITS_GEOKEY = 2060, + TIFF_GEOG_PRIME_MERIDIAN_LONG_GEOKEY = 2061, + TIFF_PROJECTED_CS_TYPE_GEOKEY = 3072, + TIFF_PCS_CITATION_GEOKEY = 3073, + TIFF_PROJECTION_GEOKEY = 3074, + TIFF_PROJ_COORD_TRANS_GEOKEY = 3075, + TIFF_PROJ_LINEAR_UNITS_GEOKEY = 3076, + TIFF_PROJ_LINEAR_UNIT_SIZE_GEOKEY = 3077, + TIFF_PROJ_STD_PARALLEL1_GEOKEY = 3078, + TIFF_PROJ_STD_PARALLEL2_GEOKEY = 3079, + TIFF_PROJ_NAT_ORIGIN_LONG_GEOKEY = 3080, + TIFF_PROJ_NAT_ORIGIN_LAT_GEOKEY = 3081, + TIFF_PROJ_FALSE_EASTING_GEOKEY = 3082, + TIFF_PROJ_FALSE_NORTHING_GEOKEY = 3083, + TIFF_PROJ_FALSE_ORIGIN_LONG_GEOKEY = 3084, + TIFF_PROJ_FALSE_ORIGIN_LAT_GEOKEY = 3085, + TIFF_PROJ_FALSE_ORIGIN_EASTING_GEOKEY = 3086, + TIFF_PROJ_FALSE_ORIGIN_NORTHING_GEOKEY = 3087, + TIFF_PROJ_CENTER_LONG_GEOKEY = 3088, + TIFF_PROJ_CENTER_LAT_GEOKEY = 3089, + TIFF_PROJ_CENTER_EASTING_GEOKEY = 3090, + TIFF_PROJ_CENTER_NORTHING_GEOKEY = 3091, + TIFF_PROJ_SCALE_AT_NAT_ORIGIN_GEOKEY = 3092, + TIFF_PROJ_SCALE_AT_CENTER_GEOKEY = 3093, + TIFF_PROJ_AZIMUTH_ANGLE_GEOKEY = 3094, + TIFF_PROJ_STRAIGHT_VERT_POLE_LONG_GEOKEY = 3095, + TIFF_VERTICAL_CS_TYPE_GEOKEY = 4096, + TIFF_VERTICAL_CITATION_GEOKEY = 4097, + TIFF_VERTICAL_DATUM_GEOKEY = 4098, + TIFF_VERTICAL_UNITS_GEOKEY = 4099 +}; + +enum TiffGeoTagType { + GEOTIFF_SHORT = 0, + GEOTIFF_DOUBLE = 34736, + GEOTIFF_STRING = 34737 +}; + +/** sizes of various TIFF field types (string size = 100)*/ +static const uint8_t type_sizes[14] = { + 0, 1, 100, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4 +}; + +typedef struct TiffGeoTag { + enum TiffGeoTagKey key; + enum TiffTags type; + int count; + int offset; + char *val; +} TiffGeoTag; + +typedef struct TiffGeoTagKeyName { + const enum TiffGeoTagKey key; + const char *const name; +} TiffGeoTagKeyName; + +typedef struct TiffGeoTagNameType { + const char *const name; + const enum TiffGeoTagType type; +} TiffGeoTagNameType; + +#endif /* AVCODEC_TIFF_H */ diff --git a/ffmpeg/libavcodec/tiff_data.c b/ffmpeg/libavcodec/tiff_data.c new file mode 100644 index 0000000..5bfe009 --- /dev/null +++ b/ffmpeg/libavcodec/tiff_data.c @@ -0,0 +1,1870 @@ +/* + * TIFF data tables + * Copyright (c) 2011 Thomas Kuehnel + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * TIFF data tables + * @author Thomas Kuehnel + * @see GeoTIFF specification at + * http://www.remotesensing.org/geotiff/spec/geotiffhome.html + */ + +#include "tiff_data.h" + +const TiffGeoTagNameType ff_tiff_conf_name_type_map[] = { + {"GTModelTypeGeoKey", GEOTIFF_SHORT }, + {"GTRasterTypeGeoKey", GEOTIFF_SHORT }, + {"GTCitationGeoKey", GEOTIFF_STRING} +}; + +const TiffGeoTagNameType ff_tiff_geog_name_type_map[] = { + {"GeographicTypeGeoKey", GEOTIFF_SHORT }, + {"GeogCitationGeoKey", GEOTIFF_STRING}, + {"GeogGeodeticDatumGeoKey", GEOTIFF_SHORT }, + {"GeogPrimeMeridianGeoKey", GEOTIFF_SHORT }, + {"GeogLinearUnitsGeoKey", GEOTIFF_SHORT }, + {"GeogLinearUnitSizeGeoKey", GEOTIFF_DOUBLE}, + {"GeogAngularUnitsGeoKey", GEOTIFF_SHORT }, + {"GeogAngularUnitSizeGeoKey", GEOTIFF_DOUBLE}, + {"GeogEllipsoidGeoKey", GEOTIFF_SHORT }, + {"GeogSemiMajorAxisGeoKey", GEOTIFF_DOUBLE}, + {"GeogSemiMinorAxisGeoKey", GEOTIFF_DOUBLE}, + {"GeogInvFlatteningGeoKey", GEOTIFF_DOUBLE}, + {"GeogAzimuthUnitsGeoKey", GEOTIFF_SHORT }, + {"GeogPrimeMeridianLongGeoKey", GEOTIFF_DOUBLE} +}; + +const TiffGeoTagNameType ff_tiff_proj_name_type_map[] = { + {"ProjectedCSTypeGeoKey", GEOTIFF_SHORT }, + {"PCSCitationGeoKey", GEOTIFF_STRING}, + {"ProjectionGeoKey", GEOTIFF_SHORT }, + {"ProjCoordTransGeoKey", GEOTIFF_SHORT }, + {"ProjLinearUnitsGeoKey", GEOTIFF_SHORT }, + {"ProjLinearUnitSizeGeoKey", GEOTIFF_DOUBLE}, + {"ProjStdParallel1GeoKey", GEOTIFF_DOUBLE}, + {"ProjStdParallel2GeoKey", GEOTIFF_DOUBLE}, + {"ProjNatOriginLongGeoKey", GEOTIFF_DOUBLE}, + {"ProjNatOriginLatGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseEastingGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseNorthingGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginLongGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginLatGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginEastingGeoKey", GEOTIFF_DOUBLE}, + {"ProjFalseOriginNorthingGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterLongGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterLatGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterEastingGeoKey", GEOTIFF_DOUBLE}, + {"ProjCenterNorthingGeoKey", GEOTIFF_DOUBLE}, + {"ProjScaleAtNatOriginGeoKey", GEOTIFF_DOUBLE}, + {"ProjScaleAtCenterGeoKey", GEOTIFF_DOUBLE}, + {"ProjAzimuthAngleGeoKey", GEOTIFF_DOUBLE}, + {"ProjStraightVertPoleLongGeoKey", GEOTIFF_DOUBLE} +}; + +const TiffGeoTagNameType ff_tiff_vert_name_type_map[] = { + {"VerticalCSTypeGeoKey", GEOTIFF_SHORT }, + {"VerticalCitationGeoKey", GEOTIFF_STRING}, + {"VerticalDatumGeoKey", GEOTIFF_SHORT }, + {"VerticalUnitsGeoKey", GEOTIFF_SHORT } +}; + +const char *const ff_tiff_gt_model_type_codes[] = { + "ModelTypeProjected", + "ModelTypeGeographic", + "ModelTypeGeocentric" +}; + +const char *const ff_tiff_gt_raster_type_codes[] = { + "RasterPixelIsArea", + "RasterPixelIsPoint" +}; + +const char *const ff_tiff_linear_unit_codes[] = { + "Linear_Meter", + "Linear_Foot", + "Linear_Foot_US_Survey", + "Linear_Foot_Modified_American", + "Linear_Foot_Clarke", + "Linear_Foot_Indian", + "Linear_Link", + "Linear_Link_Benoit", + "Linear_Link_Sears", + "Linear_Chain_Benoit", + "Linear_Chain_Sears", + "Linear_Yard_Sears", + "Linear_Yard_Indian", + "Linear_Fathom", + "Linear_Mile_International_Nautical" +}; + +const char *const ff_tiff_angular_unit_codes[] = { + "Angular_Radian", + "Angular_Degree", + "Angular_Arc_Minute", + "Angular_Arc_Second", + "Angular_Grad", + "Angular_Gon", + "Angular_DMS", + "Angular_DMS_Hemisphere" +}; + +const char *const ff_tiff_gcs_type_codes[] = { + "GCS_Adindan", + "GCS_AGD66", + "GCS_AGD84", + "GCS_Ain_el_Abd", + "GCS_Afgooye", + "GCS_Agadez", + "GCS_Lisbon", + "GCS_Aratu", + "GCS_Arc_1950", + "GCS_Arc_1960", + "GCS_Batavia", + "GCS_Barbados", + "GCS_Beduaram", + "GCS_Beijing_1954", + "GCS_Belge_1950", + "GCS_Bermuda_1957", + "GCS_Bern_1898", + "GCS_Bogota", + "GCS_Bukit_Rimpah", + "GCS_Camacupa", + "GCS_Campo_Inchauspe", + "GCS_Cape", + "GCS_Carthage", + "GCS_Chua", + "GCS_Corrego_Alegre", + "GCS_Cote_d_Ivoire", + "GCS_Deir_ez_Zor", + "GCS_Douala", + "GCS_Egypt_1907", + "GCS_ED50", + "GCS_ED87", + "GCS_Fahud", + "GCS_Gandajika_1970", + "GCS_Garoua", + "GCS_Guyane_Francaise", + "GCS_Hu_Tzu_Shan", + "GCS_HD72", + "GCS_ID74", + "GCS_Indian_1954", + "GCS_Indian_1975", + "GCS_Jamaica_1875", + "GCS_JAD69", + "GCS_Kalianpur", + "GCS_Kandawala", + "GCS_Kertau", + "GCS_KOC", + "GCS_La_Canoa", + "GCS_PSAD56", + "GCS_Lake", + "GCS_Leigon", + "GCS_Liberia_1964", + "GCS_Lome", + "GCS_Luzon_1911", + "GCS_Hito_XVIII_1963", + "GCS_Herat_North", + "GCS_Mahe_1971", + "GCS_Makassar", + "GCS_EUREF89", + "GCS_Malongo_1987", + "GCS_Manoca", + "GCS_Merchich", + "GCS_Massawa", + "GCS_Minna", + "GCS_Mhast", + "GCS_Monte_Mario", + "GCS_M_poraloko", + "GCS_NAD27", + "GCS_NAD_Michigan", + "GCS_NAD83", + "GCS_Nahrwan_1967", + "GCS_Naparima_1972", + "GCS_GD49", + "GCS_NGO_1948", + "GCS_Datum_73", + "GCS_NTF", + "GCS_NSWC_9Z_2", + "GCS_OSGB_1936", + "GCS_OSGB70", + "GCS_OS_SN80", + "GCS_Padang", + "GCS_Palestine_1923", + "GCS_Pointe_Noire", + "GCS_GDA94", + "GCS_Pulkovo_1942", + "GCS_Qatar", + "GCS_Qatar_1948", + "GCS_Qornoq", + "GCS_Loma_Quintana", + "GCS_Amersfoort", + "GCS_RT38", + "GCS_SAD69", + "GCS_Sapper_Hill_1943", + "GCS_Schwarzeck", + "GCS_Segora", + "GCS_Serindung", + "GCS_Sudan", + "GCS_Tananarive", + "GCS_Timbalai_1948", + "GCS_TM65", + "GCS_TM75", + "GCS_Tokyo", + "GCS_Trinidad_1903", + "GCS_TC_1948", + "GCS_Voirol_1875", + "GCS_Voirol_Unifie", + "GCS_Bern_1938", + "GCS_Nord_Sahara_1959", + "GCS_Stockholm_1938", + "GCS_Yacare", + "GCS_Yoff", + "GCS_Zanderij", + "GCS_MGI", + "GCS_Belge_1972", + "GCS_DHDN", + "GCS_Conakry_1905", + "GCS_WGS_72", + "GCS_WGS_72BE", + "GCS_WGS_84", + "GCS_Bern_1898_Bern", + "GCS_Bogota_Bogota", + "GCS_Lisbon_Lisbon", + "GCS_Makassar_Jakarta", + "GCS_MGI_Ferro", + "GCS_Monte_Mario_Rome", + "GCS_NTF_Paris", + "GCS_Padang_Jakarta", + "GCS_Belge_1950_Brussels", + "GCS_Tananarive_Paris", + "GCS_Voirol_1875_Paris", + "GCS_Voirol_Unifie_Paris", + "GCS_Batavia_Jakarta", + "GCS_ATF_Paris", + "GCS_NDG_Paris" +}; + +const char *const ff_tiff_gcse_type_codes[] = { + "GCSE_Airy1830", + "GCSE_AiryModified1849", + "GCSE_AustralianNationalSpheroid", + "GCSE_Bessel1841", + "GCSE_BesselModified", + "GCSE_BesselNamibia", + "GCSE_Clarke1858", + "GCSE_Clarke1866", + "GCSE_Clarke1866Michigan", + "GCSE_Clarke1880_Benoit", + "GCSE_Clarke1880_IGN", + "GCSE_Clarke1880_RGS", + "GCSE_Clarke1880_Arc", + "GCSE_Clarke1880_SGA1922", + "GCSE_Everest1830_1937Adjustment", + "GCSE_Everest1830_1967Definition", + "GCSE_Everest1830_1975Definition", + "GCSE_Everest1830Modified", + "GCSE_GRS1980", + "GCSE_Helmert1906", + "GCSE_IndonesianNationalSpheroid", + "GCSE_International1924", + "GCSE_International1967", + "GCSE_Krassowsky1940", + "GCSE_NWL9D", + "GCSE_NWL10D", + "GCSE_Plessis1817", + "GCSE_Struve1860", + "GCSE_WarOffice", + "GCSE_WGS84", + "GCSE_GEM10C", + "GCSE_OSU86F", + "GCSE_OSU91A", + "GCSE_Clarke1880", + "GCSE_Sphere" +}; + +const char *const ff_tiff_geodetic_datum_codes[] = { + "Datum_Adindan", + "Datum_Australian_Geodetic_Datum_1966", + "Datum_Australian_Geodetic_Datum_1984", + "Datum_Ain_el_Abd_1970", + "Datum_Afgooye", + "Datum_Agadez", + "Datum_Lisbon", + "Datum_Aratu", + "Datum_Arc_1950", + "Datum_Arc_1960", + "Datum_Batavia", + "Datum_Barbados", + "Datum_Beduaram", + "Datum_Beijing_1954", + "Datum_Reseau_National_Belge_1950", + "Datum_Bermuda_1957", + "Datum_Bern_1898", + "Datum_Bogota", + "Datum_Bukit_Rimpah", + "Datum_Camacupa", + "Datum_Campo_Inchauspe", + "Datum_Cape", + "Datum_Carthage", + "Datum_Chua", + "Datum_Corrego_Alegre", + "Datum_Cote_d_Ivoire", + "Datum_Deir_ez_Zor", + "Datum_Douala", + "Datum_Egypt_1907", + "Datum_European_Datum_1950", + "Datum_European_Datum_1987", + "Datum_Fahud", + "Datum_Gandajika_1970", + "Datum_Garoua", + "Datum_Guyane_Francaise", + "Datum_Hu_Tzu_Shan", + "Datum_Hungarian_Datum_1972", + "Datum_Indonesian_Datum_1974", + "Datum_Indian_1954", + "Datum_Indian_1975", + "Datum_Jamaica_1875", + "Datum_Jamaica_1969", + "Datum_Kalianpur", + "Datum_Kandawala", + "Datum_Kertau", + "Datum_Kuwait_Oil_Company", + "Datum_La_Canoa", + "Datum_Provisional_S_American_Datum_1956", + "Datum_Lake", + "Datum_Leigon", + "Datum_Liberia_1964", + "Datum_Lome", + "Datum_Luzon_1911", + "Datum_Hito_XVIII_1963", + "Datum_Herat_North", + "Datum_Mahe_1971", + "Datum_Makassar", + "Datum_European_Reference_System_1989", + "Datum_Malongo_1987", + "Datum_Manoca", + "Datum_Merchich", + "Datum_Massawa", + "Datum_Minna", + "Datum_Mhast", + "Datum_Monte_Mario", + "Datum_M_poraloko", + "Datum_North_American_Datum_1927", + "Datum_NAD_Michigan", + "Datum_North_American_Datum_1983", + "Datum_Nahrwan_1967", + "Datum_Naparima_1972", + "Datum_New_Zealand_Geodetic_Datum_1949", + "Datum_NGO_1948", + "Datum_Datum_73", + "Datum_Nouvelle_Triangulation_Francaise", + "Datum_NSWC_9Z_2", + "Datum_OSGB_1936", + "Datum_OSGB_1970_SN", + "Datum_OS_SN_1980", + "Datum_Padang_1884", + "Datum_Palestine_1923", + "Datum_Pointe_Noire", + "Datum_Geocentric_Datum_of_Australia_1994", + "Datum_Pulkovo_1942", + "Datum_Qatar", + "Datum_Qatar_1948", + "Datum_Qornoq", + "Datum_Loma_Quintana", + "Datum_Amersfoort", + "Datum_RT38", + "Datum_South_American_Datum_1969", + "Datum_Sapper_Hill_1943", + "Datum_Schwarzeck", + "Datum_Segora", + "Datum_Serindung", + "Datum_Sudan", + "Datum_Tananarive_1925", + "Datum_Timbalai_1948", + "Datum_TM65", + "Datum_TM75", + "Datum_Tokyo", + "Datum_Trinidad_1903", + "Datum_Trucial_Coast_1948", + "Datum_Voirol_1875", + "Datum_Voirol_Unifie_1960", + "Datum_Bern_1938", + "Datum_Nord_Sahara_1959", + "Datum_Stockholm_1938", + "Datum_Yacare", + "Datum_Yoff", + "Datum_Zanderij", + "Datum_Militar_Geographische_Institut", + "Datum_Reseau_National_Belge_1972", + "Datum_Deutsche_Hauptdreiecksnetz", + "Datum_Conakry_1905", + "Datum_WGS72", + "Datum_WGS72_Transit_Broadcast_Ephemeris", + "Datum_WGS84", + "Datum_Ancienne_Triangulation_Francaise", + "Datum_Nord_de_Guerre" +}; + +const char *const ff_tiff_geodetic_datum_e_codes[] = { + "DatumE_Airy1830", + "DatumE_AiryModified1849", + "DatumE_AustralianNationalSpheroid", + "DatumE_Bessel1841", + "DatumE_BesselModified", + "DatumE_BesselNamibia", + "DatumE_Clarke1858", + "DatumE_Clarke1866", + "DatumE_Clarke1866Michigan", + "DatumE_Clarke1880_Benoit", + "DatumE_Clarke1880_IGN", + "DatumE_Clarke1880_RGS", + "DatumE_Clarke1880_Arc", + "DatumE_Clarke1880_SGA1922", + "DatumE_Everest1830_1937Adjustment", + "DatumE_Everest1830_1967Definition", + "DatumE_Everest1830_1975Definition", + "DatumE_Everest1830Modified", + "DatumE_GRS1980", + "DatumE_Helmert1906", + "DatumE_IndonesianNationalSpheroid", + "DatumE_International1924", + "DatumE_International1967", + "DatumE_Krassowsky1960", + "DatumE_NWL9D", + "DatumE_NWL10D", + "DatumE_Plessis1817", + "DatumE_Struve1860", + "DatumE_WarOffice", + "DatumE_WGS84", + "DatumE_GEM10C", + "DatumE_OSU86F", + "DatumE_OSU91A", + "DatumE_Clarke1880", + "DatumE_Sphere" +}; + +const char *const ff_tiff_ellipsoid_codes[] = { + "Ellipse_Airy_1830", + "Ellipse_Airy_Modified_1849", + "Ellipse_Australian_National_Spheroid", + "Ellipse_Bessel_1841", + "Ellipse_Bessel_Modified", + "Ellipse_Bessel_Namibia", + "Ellipse_Clarke_1858", + "Ellipse_Clarke_1866", + "Ellipse_Clarke_1866_Michigan", + "Ellipse_Clarke_1880_Benoit", + "Ellipse_Clarke_1880_IGN", + "Ellipse_Clarke_1880_RGS", + "Ellipse_Clarke_1880_Arc", + "Ellipse_Clarke_1880_SGA_1922", + "Ellipse_Everest_1830_1937_Adjustment", + "Ellipse_Everest_1830_1967_Definition", + "Ellipse_Everest_1830_1975_Definition", + "Ellipse_Everest_1830_Modified", + "Ellipse_GRS_1980", + "Ellipse_Helmert_1906", + "Ellipse_Indonesian_National_Spheroid", + "Ellipse_International_1924", + "Ellipse_International_1967", + "Ellipse_Krassowsky_1940", + "Ellipse_NWL_9D", + "Ellipse_NWL_10D", + "Ellipse_Plessis_1817", + "Ellipse_Struve_1860", + "Ellipse_War_Office", + "Ellipse_WGS_84", + "Ellipse_GEM_10C", + "Ellipse_OSU86F", + "Ellipse_OSU91A", + "Ellipse_Clarke_1880", + "Ellipse_Sphere" +}; + +const char *const ff_tiff_prime_meridian_codes[] = { + "PM_Greenwich", + "PM_Lisbon", + "PM_Paris", + "PM_Bogota", + "PM_Madrid", + "PM_Rome", + "PM_Bern", + "PM_Jakarta", + "PM_Ferro", + "PM_Brussels", + "PM_Stockholm" +}; + +const TiffGeoTagKeyName ff_tiff_proj_cs_type_codes[] = { + {20137, "PCS_Adindan_UTM_zone_37N"}, + {20138, "PCS_Adindan_UTM_zone_38N"}, + {20248, "PCS_AGD66_AMG_zone_48"}, + {20249, "PCS_AGD66_AMG_zone_49"}, + {20250, "PCS_AGD66_AMG_zone_50"}, + {20251, "PCS_AGD66_AMG_zone_51"}, + {20252, "PCS_AGD66_AMG_zone_52"}, + {20253, "PCS_AGD66_AMG_zone_53"}, + {20254, "PCS_AGD66_AMG_zone_54"}, + {20255, "PCS_AGD66_AMG_zone_55"}, + {20256, "PCS_AGD66_AMG_zone_56"}, + {20257, "PCS_AGD66_AMG_zone_57"}, + {20258, "PCS_AGD66_AMG_zone_58"}, + {20348, "PCS_AGD84_AMG_zone_48"}, + {20349, "PCS_AGD84_AMG_zone_49"}, + {20350, "PCS_AGD84_AMG_zone_50"}, + {20351, "PCS_AGD84_AMG_zone_51"}, + {20352, "PCS_AGD84_AMG_zone_52"}, + {20353, "PCS_AGD84_AMG_zone_53"}, + {20354, "PCS_AGD84_AMG_zone_54"}, + {20355, "PCS_AGD84_AMG_zone_55"}, + {20356, "PCS_AGD84_AMG_zone_56"}, + {20357, "PCS_AGD84_AMG_zone_57"}, + {20358, "PCS_AGD84_AMG_zone_58"}, + {20437, "PCS_Ain_el_Abd_UTM_zone_37N"}, + {20438, "PCS_Ain_el_Abd_UTM_zone_38N"}, + {20439, "PCS_Ain_el_Abd_UTM_zone_39N"}, + {20499, "PCS_Ain_el_Abd_Bahrain_Grid"}, + {20538, "PCS_Afgooye_UTM_zone_38N"}, + {20539, "PCS_Afgooye_UTM_zone_39N"}, + {20700, "PCS_Lisbon_Portugese_Grid"}, + {20822, "PCS_Aratu_UTM_zone_22S"}, + {20823, "PCS_Aratu_UTM_zone_23S"}, + {20824, "PCS_Aratu_UTM_zone_24S"}, + {20973, "PCS_Arc_1950_Lo13"}, + {20975, "PCS_Arc_1950_Lo15"}, + {20977, "PCS_Arc_1950_Lo17"}, + {20979, "PCS_Arc_1950_Lo19"}, + {20981, "PCS_Arc_1950_Lo21"}, + {20983, "PCS_Arc_1950_Lo23"}, + {20985, "PCS_Arc_1950_Lo25"}, + {20987, "PCS_Arc_1950_Lo27"}, + {20989, "PCS_Arc_1950_Lo29"}, + {20991, "PCS_Arc_1950_Lo31"}, + {20993, "PCS_Arc_1950_Lo33"}, + {20995, "PCS_Arc_1950_Lo35"}, + {21100, "PCS_Batavia_NEIEZ"}, + {21148, "PCS_Batavia_UTM_zone_48S"}, + {21149, "PCS_Batavia_UTM_zone_49S"}, + {21150, "PCS_Batavia_UTM_zone_50S"}, + {21413, "PCS_Beijing_Gauss_zone_13"}, + {21414, "PCS_Beijing_Gauss_zone_14"}, + {21415, "PCS_Beijing_Gauss_zone_15"}, + {21416, "PCS_Beijing_Gauss_zone_16"}, + {21417, "PCS_Beijing_Gauss_zone_17"}, + {21418, "PCS_Beijing_Gauss_zone_18"}, + {21419, "PCS_Beijing_Gauss_zone_19"}, + {21420, "PCS_Beijing_Gauss_zone_20"}, + {21421, "PCS_Beijing_Gauss_zone_21"}, + {21422, "PCS_Beijing_Gauss_zone_22"}, + {21423, "PCS_Beijing_Gauss_zone_23"}, + {21473, "PCS_Beijing_Gauss_13N"}, + {21474, "PCS_Beijing_Gauss_14N"}, + {21475, "PCS_Beijing_Gauss_15N"}, + {21476, "PCS_Beijing_Gauss_16N"}, + {21477, "PCS_Beijing_Gauss_17N"}, + {21478, "PCS_Beijing_Gauss_18N"}, + {21479, "PCS_Beijing_Gauss_19N"}, + {21480, "PCS_Beijing_Gauss_20N"}, + {21481, "PCS_Beijing_Gauss_21N"}, + {21482, "PCS_Beijing_Gauss_22N"}, + {21483, "PCS_Beijing_Gauss_23N"}, + {21500, "PCS_Belge_Lambert_50"}, + {21790, "PCS_Bern_1898_Swiss_Old"}, + {21817, "PCS_Bogota_UTM_zone_17N"}, + {21818, "PCS_Bogota_UTM_zone_18N"}, + {21891, "PCS_Bogota_Colombia_3W"}, + {21892, "PCS_Bogota_Colombia_Bogota"}, + {21893, "PCS_Bogota_Colombia_3E"}, + {21894, "PCS_Bogota_Colombia_6E"}, + {22032, "PCS_Camacupa_UTM_32S"}, + {22033, "PCS_Camacupa_UTM_33S"}, + {22191, "PCS_C_Inchauspe_Argentina_1"}, + {22192, "PCS_C_Inchauspe_Argentina_2"}, + {22193, "PCS_C_Inchauspe_Argentina_3"}, + {22194, "PCS_C_Inchauspe_Argentina_4"}, + {22195, "PCS_C_Inchauspe_Argentina_5"}, + {22196, "PCS_C_Inchauspe_Argentina_6"}, + {22197, "PCS_C_Inchauspe_Argentina_7"}, + {22332, "PCS_Carthage_UTM_zone_32N"}, + {22391, "PCS_Carthage_Nord_Tunisie"}, + {22392, "PCS_Carthage_Sud_Tunisie"}, + {22523, "PCS_Corrego_Alegre_UTM_23S"}, + {22524, "PCS_Corrego_Alegre_UTM_24S"}, + {22832, "PCS_Douala_UTM_zone_32N"}, + {22992, "PCS_Egypt_1907_Red_Belt"}, + {22993, "PCS_Egypt_1907_Purple_Belt"}, + {22994, "PCS_Egypt_1907_Ext_Purple"}, + {23028, "PCS_ED50_UTM_zone_28N"}, + {23029, "PCS_ED50_UTM_zone_29N"}, + {23030, "PCS_ED50_UTM_zone_30N"}, + {23031, "PCS_ED50_UTM_zone_31N"}, + {23032, "PCS_ED50_UTM_zone_32N"}, + {23033, "PCS_ED50_UTM_zone_33N"}, + {23034, "PCS_ED50_UTM_zone_34N"}, + {23035, "PCS_ED50_UTM_zone_35N"}, + {23036, "PCS_ED50_UTM_zone_36N"}, + {23037, "PCS_ED50_UTM_zone_37N"}, + {23038, "PCS_ED50_UTM_zone_38N"}, + {23239, "PCS_Fahud_UTM_zone_39N"}, + {23240, "PCS_Fahud_UTM_zone_40N"}, + {23433, "PCS_Garoua_UTM_zone_33N"}, + {23846, "PCS_ID74_UTM_zone_46N"}, + {23847, "PCS_ID74_UTM_zone_47N"}, + {23848, "PCS_ID74_UTM_zone_48N"}, + {23849, "PCS_ID74_UTM_zone_49N"}, + {23850, "PCS_ID74_UTM_zone_50N"}, + {23851, "PCS_ID74_UTM_zone_51N"}, + {23852, "PCS_ID74_UTM_zone_52N"}, + {23853, "PCS_ID74_UTM_zone_53N"}, + {23886, "PCS_ID74_UTM_zone_46S"}, + {23887, "PCS_ID74_UTM_zone_47S"}, + {23888, "PCS_ID74_UTM_zone_48S"}, + {23889, "PCS_ID74_UTM_zone_49S"}, + {23890, "PCS_ID74_UTM_zone_50S"}, + {23891, "PCS_ID74_UTM_zone_51S"}, + {23892, "PCS_ID74_UTM_zone_52S"}, + {23893, "PCS_ID74_UTM_zone_53S"}, + {23894, "PCS_ID74_UTM_zone_54S"}, + {23947, "PCS_Indian_1954_UTM_47N"}, + {23948, "PCS_Indian_1954_UTM_48N"}, + {24047, "PCS_Indian_1975_UTM_47N"}, + {24048, "PCS_Indian_1975_UTM_48N"}, + {24100, "PCS_Jamaica_1875_Old_Grid"}, + {24200, "PCS_JAD69_Jamaica_Grid"}, + {24370, "PCS_Kalianpur_India_0"}, + {24371, "PCS_Kalianpur_India_I"}, + {24372, "PCS_Kalianpur_India_IIa"}, + {24373, "PCS_Kalianpur_India_IIIa"}, + {24374, "PCS_Kalianpur_India_IVa"}, + {24382, "PCS_Kalianpur_India_IIb"}, + {24383, "PCS_Kalianpur_India_IIIb"}, + {24384, "PCS_Kalianpur_India_IVb"}, + {24500, "PCS_Kertau_Singapore_Grid"}, + {24547, "PCS_Kertau_UTM_zone_47N"}, + {24548, "PCS_Kertau_UTM_zone_48N"}, + {24720, "PCS_La_Canoa_UTM_zone_20N"}, + {24721, "PCS_La_Canoa_UTM_zone_21N"}, + {24818, "PCS_PSAD56_UTM_zone_18N"}, + {24819, "PCS_PSAD56_UTM_zone_19N"}, + {24820, "PCS_PSAD56_UTM_zone_20N"}, + {24821, "PCS_PSAD56_UTM_zone_21N"}, + {24877, "PCS_PSAD56_UTM_zone_17S"}, + {24878, "PCS_PSAD56_UTM_zone_18S"}, + {24879, "PCS_PSAD56_UTM_zone_19S"}, + {24880, "PCS_PSAD56_UTM_zone_20S"}, + {24891, "PCS_PSAD56_Peru_west_zone"}, + {24892, "PCS_PSAD56_Peru_central"}, + {24893, "PCS_PSAD56_Peru_east_zone"}, + {25000, "PCS_Leigon_Ghana_Grid"}, + {25231, "PCS_Lome_UTM_zone_31N"}, + {25391, "PCS_Luzon_Philippines_I"}, + {25392, "PCS_Luzon_Philippines_II"}, + {25393, "PCS_Luzon_Philippines_III"}, + {25394, "PCS_Luzon_Philippines_IV"}, + {25395, "PCS_Luzon_Philippines_V"}, + {25700, "PCS_Makassar_NEIEZ"}, + {25932, "PCS_Malongo_1987_UTM_32S"}, + {26191, "PCS_Merchich_Nord_Maroc"}, + {26192, "PCS_Merchich_Sud_Maroc"}, + {26193, "PCS_Merchich_Sahara"}, + {26237, "PCS_Massawa_UTM_zone_37N"}, + {26331, "PCS_Minna_UTM_zone_31N"}, + {26332, "PCS_Minna_UTM_zone_32N"}, + {26391, "PCS_Minna_Nigeria_West"}, + {26392, "PCS_Minna_Nigeria_Mid_Belt"}, + {26393, "PCS_Minna_Nigeria_East"}, + {26432, "PCS_Mhast_UTM_zone_32S"}, + {26591, "PCS_Monte_Mario_Italy_1"}, + {26592, "PCS_Monte_Mario_Italy_2"}, + {26632, "PCS_M_poraloko_UTM_32N"}, + {26692, "PCS_M_poraloko_UTM_32S"}, + {26703, "PCS_NAD27_UTM_zone_3N"}, + {26704, "PCS_NAD27_UTM_zone_4N"}, + {26705, "PCS_NAD27_UTM_zone_5N"}, + {26706, "PCS_NAD27_UTM_zone_6N"}, + {26707, "PCS_NAD27_UTM_zone_7N"}, + {26708, "PCS_NAD27_UTM_zone_8N"}, + {26709, "PCS_NAD27_UTM_zone_9N"}, + {26710, "PCS_NAD27_UTM_zone_10N"}, + {26711, "PCS_NAD27_UTM_zone_11N"}, + {26712, "PCS_NAD27_UTM_zone_12N"}, + {26713, "PCS_NAD27_UTM_zone_13N"}, + {26714, "PCS_NAD27_UTM_zone_14N"}, + {26715, "PCS_NAD27_UTM_zone_15N"}, + {26716, "PCS_NAD27_UTM_zone_16N"}, + {26717, "PCS_NAD27_UTM_zone_17N"}, + {26718, "PCS_NAD27_UTM_zone_18N"}, + {26719, "PCS_NAD27_UTM_zone_19N"}, + {26720, "PCS_NAD27_UTM_zone_20N"}, + {26721, "PCS_NAD27_UTM_zone_21N"}, + {26722, "PCS_NAD27_UTM_zone_22N"}, + {26729, "PCS_NAD27_Alabama_East"}, + {26730, "PCS_NAD27_Alabama_West"}, + {26731, "PCS_NAD27_Alaska_zone_1"}, + {26732, "PCS_NAD27_Alaska_zone_2"}, + {26733, "PCS_NAD27_Alaska_zone_3"}, + {26734, "PCS_NAD27_Alaska_zone_4"}, + {26735, "PCS_NAD27_Alaska_zone_5"}, + {26736, "PCS_NAD27_Alaska_zone_6"}, + {26737, "PCS_NAD27_Alaska_zone_7"}, + {26738, "PCS_NAD27_Alaska_zone_8"}, + {26739, "PCS_NAD27_Alaska_zone_9"}, + {26740, "PCS_NAD27_Alaska_zone_10"}, + {26741, "PCS_NAD27_California_I"}, + {26742, "PCS_NAD27_California_II"}, + {26743, "PCS_NAD27_California_III"}, + {26744, "PCS_NAD27_California_IV"}, + {26745, "PCS_NAD27_California_V"}, + {26746, "PCS_NAD27_California_VI"}, + {26747, "PCS_NAD27_California_VII"}, + {26748, "PCS_NAD27_Arizona_East"}, + {26749, "PCS_NAD27_Arizona_Central"}, + {26750, "PCS_NAD27_Arizona_West"}, + {26751, "PCS_NAD27_Arkansas_North"}, + {26752, "PCS_NAD27_Arkansas_South"}, + {26753, "PCS_NAD27_Colorado_North"}, + {26754, "PCS_NAD27_Colorado_Central"}, + {26755, "PCS_NAD27_Colorado_South"}, + {26756, "PCS_NAD27_Connecticut"}, + {26757, "PCS_NAD27_Delaware"}, + {26758, "PCS_NAD27_Florida_East"}, + {26759, "PCS_NAD27_Florida_West"}, + {26760, "PCS_NAD27_Florida_North"}, + {26761, "PCS_NAD27_Hawaii_zone_1"}, + {26762, "PCS_NAD27_Hawaii_zone_2"}, + {26763, "PCS_NAD27_Hawaii_zone_3"}, + {26764, "PCS_NAD27_Hawaii_zone_4"}, + {26765, "PCS_NAD27_Hawaii_zone_5"}, + {26766, "PCS_NAD27_Georgia_East"}, + {26767, "PCS_NAD27_Georgia_West"}, + {26768, "PCS_NAD27_Idaho_East"}, + {26769, "PCS_NAD27_Idaho_Central"}, + {26770, "PCS_NAD27_Idaho_West"}, + {26771, "PCS_NAD27_Illinois_East"}, + {26772, "PCS_NAD27_Illinois_West"}, + {26773, "PCS_NAD27_Indiana_East"}, + {26774, "PCS_NAD27_BLM_14N_feet"}, + {26774, "PCS_NAD27_Indiana_West"}, + {26775, "PCS_NAD27_BLM_15N_feet"}, + {26775, "PCS_NAD27_Iowa_North"}, + {26776, "PCS_NAD27_BLM_16N_feet"}, + {26776, "PCS_NAD27_Iowa_South"}, + {26777, "PCS_NAD27_BLM_17N_feet"}, + {26777, "PCS_NAD27_Kansas_North"}, + {26778, "PCS_NAD27_Kansas_South"}, + {26779, "PCS_NAD27_Kentucky_North"}, + {26780, "PCS_NAD27_Kentucky_South"}, + {26781, "PCS_NAD27_Louisiana_North"}, + {26782, "PCS_NAD27_Louisiana_South"}, + {26783, "PCS_NAD27_Maine_East"}, + {26784, "PCS_NAD27_Maine_West"}, + {26785, "PCS_NAD27_Maryland"}, + {26786, "PCS_NAD27_Massachusetts"}, + {26787, "PCS_NAD27_Massachusetts_Is"}, + {26788, "PCS_NAD27_Michigan_North"}, + {26789, "PCS_NAD27_Michigan_Central"}, + {26790, "PCS_NAD27_Michigan_South"}, + {26791, "PCS_NAD27_Minnesota_North"}, + {26792, "PCS_NAD27_Minnesota_Cent"}, + {26793, "PCS_NAD27_Minnesota_South"}, + {26794, "PCS_NAD27_Mississippi_East"}, + {26795, "PCS_NAD27_Mississippi_West"}, + {26796, "PCS_NAD27_Missouri_East"}, + {26797, "PCS_NAD27_Missouri_Central"}, + {26798, "PCS_NAD27_Missouri_West"}, + {26801, "PCS_NAD_Michigan_Michigan_East"}, + {26802, "PCS_NAD_Michigan_Michigan_Old_Central"}, + {26803, "PCS_NAD_Michigan_Michigan_West"}, + {26903, "PCS_NAD83_UTM_zone_3N"}, + {26904, "PCS_NAD83_UTM_zone_4N"}, + {26905, "PCS_NAD83_UTM_zone_5N"}, + {26906, "PCS_NAD83_UTM_zone_6N"}, + {26907, "PCS_NAD83_UTM_zone_7N"}, + {26908, "PCS_NAD83_UTM_zone_8N"}, + {26909, "PCS_NAD83_UTM_zone_9N"}, + {26910, "PCS_NAD83_UTM_zone_10N"}, + {26911, "PCS_NAD83_UTM_zone_11N"}, + {26912, "PCS_NAD83_UTM_zone_12N"}, + {26913, "PCS_NAD83_UTM_zone_13N"}, + {26914, "PCS_NAD83_UTM_zone_14N"}, + {26915, "PCS_NAD83_UTM_zone_15N"}, + {26916, "PCS_NAD83_UTM_zone_16N"}, + {26917, "PCS_NAD83_UTM_zone_17N"}, + {26918, "PCS_NAD83_UTM_zone_18N"}, + {26919, "PCS_NAD83_UTM_zone_19N"}, + {26920, "PCS_NAD83_UTM_zone_20N"}, + {26921, "PCS_NAD83_UTM_zone_21N"}, + {26922, "PCS_NAD83_UTM_zone_22N"}, + {26923, "PCS_NAD83_UTM_zone_23N"}, + {26929, "PCS_NAD83_Alabama_East"}, + {26930, "PCS_NAD83_Alabama_West"}, + {26931, "PCS_NAD83_Alaska_zone_1"}, + {26932, "PCS_NAD83_Alaska_zone_2"}, + {26933, "PCS_NAD83_Alaska_zone_3"}, + {26934, "PCS_NAD83_Alaska_zone_4"}, + {26935, "PCS_NAD83_Alaska_zone_5"}, + {26936, "PCS_NAD83_Alaska_zone_6"}, + {26937, "PCS_NAD83_Alaska_zone_7"}, + {26938, "PCS_NAD83_Alaska_zone_8"}, + {26939, "PCS_NAD83_Alaska_zone_9"}, + {26940, "PCS_NAD83_Alaska_zone_10"}, + {26941, "PCS_NAD83_California_1"}, + {26942, "PCS_NAD83_California_2"}, + {26943, "PCS_NAD83_California_3"}, + {26944, "PCS_NAD83_California_4"}, + {26945, "PCS_NAD83_California_5"}, + {26946, "PCS_NAD83_California_6"}, + {26948, "PCS_NAD83_Arizona_East"}, + {26949, "PCS_NAD83_Arizona_Central"}, + {26950, "PCS_NAD83_Arizona_West"}, + {26951, "PCS_NAD83_Arkansas_North"}, + {26952, "PCS_NAD83_Arkansas_South"}, + {26953, "PCS_NAD83_Colorado_North"}, + {26954, "PCS_NAD83_Colorado_Central"}, + {26955, "PCS_NAD83_Colorado_South"}, + {26956, "PCS_NAD83_Connecticut"}, + {26957, "PCS_NAD83_Delaware"}, + {26958, "PCS_NAD83_Florida_East"}, + {26959, "PCS_NAD83_Florida_West"}, + {26960, "PCS_NAD83_Florida_North"}, + {26961, "PCS_NAD83_Hawaii_zone_1"}, + {26962, "PCS_NAD83_Hawaii_zone_2"}, + {26963, "PCS_NAD83_Hawaii_zone_3"}, + {26964, "PCS_NAD83_Hawaii_zone_4"}, + {26965, "PCS_NAD83_Hawaii_zone_5"}, + {26966, "PCS_NAD83_Georgia_East"}, + {26967, "PCS_NAD83_Georgia_West"}, + {26968, "PCS_NAD83_Idaho_East"}, + {26969, "PCS_NAD83_Idaho_Central"}, + {26970, "PCS_NAD83_Idaho_West"}, + {26971, "PCS_NAD83_Illinois_East"}, + {26972, "PCS_NAD83_Illinois_West"}, + {26973, "PCS_NAD83_Indiana_East"}, + {26974, "PCS_NAD83_Indiana_West"}, + {26975, "PCS_NAD83_Iowa_North"}, + {26976, "PCS_NAD83_Iowa_South"}, + {26977, "PCS_NAD83_Kansas_North"}, + {26978, "PCS_NAD83_Kansas_South"}, + {26979, "PCS_NAD83_Kentucky_North"}, + {26980, "PCS_NAD83_Kentucky_South"}, + {26981, "PCS_NAD83_Louisiana_North"}, + {26982, "PCS_NAD83_Louisiana_South"}, + {26983, "PCS_NAD83_Maine_East"}, + {26984, "PCS_NAD83_Maine_West"}, + {26985, "PCS_NAD83_Maryland"}, + {26986, "PCS_NAD83_Massachusetts"}, + {26987, "PCS_NAD83_Massachusetts_Is"}, + {26988, "PCS_NAD83_Michigan_North"}, + {26989, "PCS_NAD83_Michigan_Central"}, + {26990, "PCS_NAD83_Michigan_South"}, + {26991, "PCS_NAD83_Minnesota_North"}, + {26992, "PCS_NAD83_Minnesota_Cent"}, + {26993, "PCS_NAD83_Minnesota_South"}, + {26994, "PCS_NAD83_Mississippi_East"}, + {26995, "PCS_NAD83_Mississippi_West"}, + {26996, "PCS_NAD83_Missouri_East"}, + {26997, "PCS_NAD83_Missouri_Central"}, + {26998, "PCS_NAD83_Missouri_West"}, + {27038, "PCS_Nahrwan_1967_UTM_38N"}, + {27039, "PCS_Nahrwan_1967_UTM_39N"}, + {27040, "PCS_Nahrwan_1967_UTM_40N"}, + {27120, "PCS_Naparima_UTM_20N"}, + {27200, "PCS_GD49_NZ_Map_Grid"}, + {27291, "PCS_GD49_North_Island_Grid"}, + {27292, "PCS_GD49_South_Island_Grid"}, + {27429, "PCS_Datum_73_UTM_zone_29N"}, + {27500, "PCS_ATF_Nord_de_Guerre"}, + {27581, "PCS_NTF_France_I"}, + {27582, "PCS_NTF_France_II"}, + {27583, "PCS_NTF_France_III"}, + {27591, "PCS_NTF_Nord_France"}, + {27592, "PCS_NTF_Centre_France"}, + {27593, "PCS_NTF_Sud_France"}, + {27700, "PCS_British_National_Grid"}, + {28232, "PCS_Point_Noire_UTM_32S"}, + {28348, "PCS_GDA94_MGA_zone_48"}, + {28349, "PCS_GDA94_MGA_zone_49"}, + {28350, "PCS_GDA94_MGA_zone_50"}, + {28351, "PCS_GDA94_MGA_zone_51"}, + {28352, "PCS_GDA94_MGA_zone_52"}, + {28353, "PCS_GDA94_MGA_zone_53"}, + {28354, "PCS_GDA94_MGA_zone_54"}, + {28355, "PCS_GDA94_MGA_zone_55"}, + {28356, "PCS_GDA94_MGA_zone_56"}, + {28357, "PCS_GDA94_MGA_zone_57"}, + {28358, "PCS_GDA94_MGA_zone_58"}, + {28404, "PCS_Pulkovo_Gauss_zone_4"}, + {28405, "PCS_Pulkovo_Gauss_zone_5"}, + {28406, "PCS_Pulkovo_Gauss_zone_6"}, + {28407, "PCS_Pulkovo_Gauss_zone_7"}, + {28408, "PCS_Pulkovo_Gauss_zone_8"}, + {28409, "PCS_Pulkovo_Gauss_zone_9"}, + {28410, "PCS_Pulkovo_Gauss_zone_10"}, + {28411, "PCS_Pulkovo_Gauss_zone_11"}, + {28412, "PCS_Pulkovo_Gauss_zone_12"}, + {28413, "PCS_Pulkovo_Gauss_zone_13"}, + {28414, "PCS_Pulkovo_Gauss_zone_14"}, + {28415, "PCS_Pulkovo_Gauss_zone_15"}, + {28416, "PCS_Pulkovo_Gauss_zone_16"}, + {28417, "PCS_Pulkovo_Gauss_zone_17"}, + {28418, "PCS_Pulkovo_Gauss_zone_18"}, + {28419, "PCS_Pulkovo_Gauss_zone_19"}, + {28420, "PCS_Pulkovo_Gauss_zone_20"}, + {28421, "PCS_Pulkovo_Gauss_zone_21"}, + {28422, "PCS_Pulkovo_Gauss_zone_22"}, + {28423, "PCS_Pulkovo_Gauss_zone_23"}, + {28424, "PCS_Pulkovo_Gauss_zone_24"}, + {28425, "PCS_Pulkovo_Gauss_zone_25"}, + {28426, "PCS_Pulkovo_Gauss_zone_26"}, + {28427, "PCS_Pulkovo_Gauss_zone_27"}, + {28428, "PCS_Pulkovo_Gauss_zone_28"}, + {28429, "PCS_Pulkovo_Gauss_zone_29"}, + {28430, "PCS_Pulkovo_Gauss_zone_30"}, + {28431, "PCS_Pulkovo_Gauss_zone_31"}, + {28432, "PCS_Pulkovo_Gauss_zone_32"}, + {28464, "PCS_Pulkovo_Gauss_4N"}, + {28465, "PCS_Pulkovo_Gauss_5N"}, + {28466, "PCS_Pulkovo_Gauss_6N"}, + {28467, "PCS_Pulkovo_Gauss_7N"}, + {28468, "PCS_Pulkovo_Gauss_8N"}, + {28469, "PCS_Pulkovo_Gauss_9N"}, + {28470, "PCS_Pulkovo_Gauss_10N"}, + {28471, "PCS_Pulkovo_Gauss_11N"}, + {28472, "PCS_Pulkovo_Gauss_12N"}, + {28473, "PCS_Pulkovo_Gauss_13N"}, + {28474, "PCS_Pulkovo_Gauss_14N"}, + {28475, "PCS_Pulkovo_Gauss_15N"}, + {28476, "PCS_Pulkovo_Gauss_16N"}, + {28477, "PCS_Pulkovo_Gauss_17N"}, + {28478, "PCS_Pulkovo_Gauss_18N"}, + {28479, "PCS_Pulkovo_Gauss_19N"}, + {28480, "PCS_Pulkovo_Gauss_20N"}, + {28481, "PCS_Pulkovo_Gauss_21N"}, + {28482, "PCS_Pulkovo_Gauss_22N"}, + {28483, "PCS_Pulkovo_Gauss_23N"}, + {28484, "PCS_Pulkovo_Gauss_24N"}, + {28485, "PCS_Pulkovo_Gauss_25N"}, + {28486, "PCS_Pulkovo_Gauss_26N"}, + {28487, "PCS_Pulkovo_Gauss_27N"}, + {28488, "PCS_Pulkovo_Gauss_28N"}, + {28489, "PCS_Pulkovo_Gauss_29N"}, + {28490, "PCS_Pulkovo_Gauss_30N"}, + {28491, "PCS_Pulkovo_Gauss_31N"}, + {28492, "PCS_Pulkovo_Gauss_32N"}, + {28600, "PCS_Qatar_National_Grid"}, + {28991, "PCS_RD_Netherlands_Old"}, + {28992, "PCS_RD_Netherlands_New"}, + {29118, "PCS_SAD69_UTM_zone_18N"}, + {29119, "PCS_SAD69_UTM_zone_19N"}, + {29120, "PCS_SAD69_UTM_zone_20N"}, + {29121, "PCS_SAD69_UTM_zone_21N"}, + {29122, "PCS_SAD69_UTM_zone_22N"}, + {29177, "PCS_SAD69_UTM_zone_17S"}, + {29178, "PCS_SAD69_UTM_zone_18S"}, + {29179, "PCS_SAD69_UTM_zone_19S"}, + {29180, "PCS_SAD69_UTM_zone_20S"}, + {29181, "PCS_SAD69_UTM_zone_21S"}, + {29182, "PCS_SAD69_UTM_zone_22S"}, + {29183, "PCS_SAD69_UTM_zone_23S"}, + {29184, "PCS_SAD69_UTM_zone_24S"}, + {29185, "PCS_SAD69_UTM_zone_25S"}, + {29220, "PCS_Sapper_Hill_UTM_20S"}, + {29221, "PCS_Sapper_Hill_UTM_21S"}, + {29333, "PCS_Schwarzeck_UTM_33S"}, + {29635, "PCS_Sudan_UTM_zone_35N"}, + {29636, "PCS_Sudan_UTM_zone_36N"}, + {29700, "PCS_Tananarive_Laborde"}, + {29738, "PCS_Tananarive_UTM_38S"}, + {29739, "PCS_Tananarive_UTM_39S"}, + {29800, "PCS_Timbalai_1948_Borneo"}, + {29849, "PCS_Timbalai_1948_UTM_49N"}, + {29850, "PCS_Timbalai_1948_UTM_50N"}, + {29900, "PCS_TM65_Irish_Nat_Grid"}, + {30200, "PCS_Trinidad_1903_Trinidad"}, + {30339, "PCS_TC_1948_UTM_zone_39N"}, + {30340, "PCS_TC_1948_UTM_zone_40N"}, + {30491, "PCS_Voirol_N_Algerie_ancien"}, + {30492, "PCS_Voirol_S_Algerie_ancien"}, + {30591, "PCS_Voirol_Unifie_N_Algerie"}, + {30592, "PCS_Voirol_Unifie_S_Algerie"}, + {30600, "PCS_Bern_1938_Swiss_New"}, + {30729, "PCS_Nord_Sahara_UTM_29N"}, + {30730, "PCS_Nord_Sahara_UTM_30N"}, + {30731, "PCS_Nord_Sahara_UTM_31N"}, + {30732, "PCS_Nord_Sahara_UTM_32N"}, + {31028, "PCS_Yoff_UTM_zone_28N"}, + {31121, "PCS_Zanderij_UTM_zone_21N"}, + {31291, "PCS_MGI_Austria_West"}, + {31292, "PCS_MGI_Austria_Central"}, + {31293, "PCS_MGI_Austria_East"}, + {31300, "PCS_Belge_Lambert_72"}, + {31491, "PCS_DHDN_Germany_zone_1"}, + {31492, "PCS_DHDN_Germany_zone_2"}, + {31493, "PCS_DHDN_Germany_zone_3"}, + {31494, "PCS_DHDN_Germany_zone_4"}, + {31495, "PCS_DHDN_Germany_zone_5"}, + {32001, "PCS_NAD27_Montana_North"}, + {32002, "PCS_NAD27_Montana_Central"}, + {32003, "PCS_NAD27_Montana_South"}, + {32005, "PCS_NAD27_Nebraska_North"}, + {32006, "PCS_NAD27_Nebraska_South"}, + {32007, "PCS_NAD27_Nevada_East"}, + {32008, "PCS_NAD27_Nevada_Central"}, + {32009, "PCS_NAD27_Nevada_West"}, + {32010, "PCS_NAD27_New_Hampshire"}, + {32011, "PCS_NAD27_New_Jersey"}, + {32012, "PCS_NAD27_New_Mexico_East"}, + {32013, "PCS_NAD27_New_Mexico_Cent"}, + {32014, "PCS_NAD27_New_Mexico_West"}, + {32015, "PCS_NAD27_New_York_East"}, + {32016, "PCS_NAD27_New_York_Central"}, + {32017, "PCS_NAD27_New_York_West"}, + {32018, "PCS_NAD27_New_York_Long_Is"}, + {32019, "PCS_NAD27_North_Carolina"}, + {32020, "PCS_NAD27_North_Dakota_N"}, + {32021, "PCS_NAD27_North_Dakota_S"}, + {32022, "PCS_NAD27_Ohio_North"}, + {32023, "PCS_NAD27_Ohio_South"}, + {32024, "PCS_NAD27_Oklahoma_North"}, + {32025, "PCS_NAD27_Oklahoma_South"}, + {32026, "PCS_NAD27_Oregon_North"}, + {32027, "PCS_NAD27_Oregon_South"}, + {32028, "PCS_NAD27_Pennsylvania_N"}, + {32029, "PCS_NAD27_Pennsylvania_S"}, + {32030, "PCS_NAD27_Rhode_Island"}, + {32031, "PCS_NAD27_South_Carolina_N"}, + {32033, "PCS_NAD27_South_Carolina_S"}, + {32034, "PCS_NAD27_South_Dakota_N"}, + {32035, "PCS_NAD27_South_Dakota_S"}, + {32036, "PCS_NAD27_Tennessee"}, + {32037, "PCS_NAD27_Texas_North"}, + {32038, "PCS_NAD27_Texas_North_Cen"}, + {32039, "PCS_NAD27_Texas_Central"}, + {32040, "PCS_NAD27_Texas_South_Cen"}, + {32041, "PCS_NAD27_Texas_South"}, + {32042, "PCS_NAD27_Utah_North"}, + {32043, "PCS_NAD27_Utah_Central"}, + {32044, "PCS_NAD27_Utah_South"}, + {32045, "PCS_NAD27_Vermont"}, + {32046, "PCS_NAD27_Virginia_North"}, + {32047, "PCS_NAD27_Virginia_South"}, + {32048, "PCS_NAD27_Washington_North"}, + {32049, "PCS_NAD27_Washington_South"}, + {32050, "PCS_NAD27_West_Virginia_N"}, + {32051, "PCS_NAD27_West_Virginia_S"}, + {32052, "PCS_NAD27_Wisconsin_North"}, + {32053, "PCS_NAD27_Wisconsin_Cen"}, + {32054, "PCS_NAD27_Wisconsin_South"}, + {32055, "PCS_NAD27_Wyoming_East"}, + {32056, "PCS_NAD27_Wyoming_E_Cen"}, + {32057, "PCS_NAD27_Wyoming_W_Cen"}, + {32058, "PCS_NAD27_Wyoming_West"}, + {32059, "PCS_NAD27_Puerto_Rico"}, + {32060, "PCS_NAD27_St_Croix"}, + {32100, "PCS_NAD83_Montana"}, + {32104, "PCS_NAD83_Nebraska"}, + {32107, "PCS_NAD83_Nevada_East"}, + {32108, "PCS_NAD83_Nevada_Central"}, + {32109, "PCS_NAD83_Nevada_West"}, + {32110, "PCS_NAD83_New_Hampshire"}, + {32111, "PCS_NAD83_New_Jersey"}, + {32112, "PCS_NAD83_New_Mexico_East"}, + {32113, "PCS_NAD83_New_Mexico_Cent"}, + {32114, "PCS_NAD83_New_Mexico_West"}, + {32115, "PCS_NAD83_New_York_East"}, + {32116, "PCS_NAD83_New_York_Central"}, + {32117, "PCS_NAD83_New_York_West"}, + {32118, "PCS_NAD83_New_York_Long_Is"}, + {32119, "PCS_NAD83_North_Carolina"}, + {32120, "PCS_NAD83_North_Dakota_N"}, + {32121, "PCS_NAD83_North_Dakota_S"}, + {32122, "PCS_NAD83_Ohio_North"}, + {32123, "PCS_NAD83_Ohio_South"}, + {32124, "PCS_NAD83_Oklahoma_North"}, + {32125, "PCS_NAD83_Oklahoma_South"}, + {32126, "PCS_NAD83_Oregon_North"}, + {32127, "PCS_NAD83_Oregon_South"}, + {32128, "PCS_NAD83_Pennsylvania_N"}, + {32129, "PCS_NAD83_Pennsylvania_S"}, + {32130, "PCS_NAD83_Rhode_Island"}, + {32133, "PCS_NAD83_South_Carolina"}, + {32134, "PCS_NAD83_South_Dakota_N"}, + {32135, "PCS_NAD83_South_Dakota_S"}, + {32136, "PCS_NAD83_Tennessee"}, + {32137, "PCS_NAD83_Texas_North"}, + {32138, "PCS_NAD83_Texas_North_Cen"}, + {32139, "PCS_NAD83_Texas_Central"}, + {32140, "PCS_NAD83_Texas_South_Cen"}, + {32141, "PCS_NAD83_Texas_South"}, + {32142, "PCS_NAD83_Utah_North"}, + {32143, "PCS_NAD83_Utah_Central"}, + {32144, "PCS_NAD83_Utah_South"}, + {32145, "PCS_NAD83_Vermont"}, + {32146, "PCS_NAD83_Virginia_North"}, + {32147, "PCS_NAD83_Virginia_South"}, + {32148, "PCS_NAD83_Washington_North"}, + {32149, "PCS_NAD83_Washington_South"}, + {32150, "PCS_NAD83_West_Virginia_N"}, + {32151, "PCS_NAD83_West_Virginia_S"}, + {32152, "PCS_NAD83_Wisconsin_North"}, + {32153, "PCS_NAD83_Wisconsin_Cen"}, + {32154, "PCS_NAD83_Wisconsin_South"}, + {32155, "PCS_NAD83_Wyoming_East"}, + {32156, "PCS_NAD83_Wyoming_E_Cen"}, + {32157, "PCS_NAD83_Wyoming_W_Cen"}, + {32158, "PCS_NAD83_Wyoming_West"}, + {32161, "PCS_NAD83_Puerto_Rico_Virgin_Is"}, + {32201, "PCS_WGS72_UTM_zone_1N"}, + {32202, "PCS_WGS72_UTM_zone_2N"}, + {32203, "PCS_WGS72_UTM_zone_3N"}, + {32204, "PCS_WGS72_UTM_zone_4N"}, + {32205, "PCS_WGS72_UTM_zone_5N"}, + {32206, "PCS_WGS72_UTM_zone_6N"}, + {32207, "PCS_WGS72_UTM_zone_7N"}, + {32208, "PCS_WGS72_UTM_zone_8N"}, + {32209, "PCS_WGS72_UTM_zone_9N"}, + {32210, "PCS_WGS72_UTM_zone_10N"}, + {32211, "PCS_WGS72_UTM_zone_11N"}, + {32212, "PCS_WGS72_UTM_zone_12N"}, + {32213, "PCS_WGS72_UTM_zone_13N"}, + {32214, "PCS_WGS72_UTM_zone_14N"}, + {32215, "PCS_WGS72_UTM_zone_15N"}, + {32216, "PCS_WGS72_UTM_zone_16N"}, + {32217, "PCS_WGS72_UTM_zone_17N"}, + {32218, "PCS_WGS72_UTM_zone_18N"}, + {32219, "PCS_WGS72_UTM_zone_19N"}, + {32220, "PCS_WGS72_UTM_zone_20N"}, + {32221, "PCS_WGS72_UTM_zone_21N"}, + {32222, "PCS_WGS72_UTM_zone_22N"}, + {32223, "PCS_WGS72_UTM_zone_23N"}, + {32224, "PCS_WGS72_UTM_zone_24N"}, + {32225, "PCS_WGS72_UTM_zone_25N"}, + {32226, "PCS_WGS72_UTM_zone_26N"}, + {32227, "PCS_WGS72_UTM_zone_27N"}, + {32228, "PCS_WGS72_UTM_zone_28N"}, + {32229, "PCS_WGS72_UTM_zone_29N"}, + {32230, "PCS_WGS72_UTM_zone_30N"}, + {32231, "PCS_WGS72_UTM_zone_31N"}, + {32232, "PCS_WGS72_UTM_zone_32N"}, + {32233, "PCS_WGS72_UTM_zone_33N"}, + {32234, "PCS_WGS72_UTM_zone_34N"}, + {32235, "PCS_WGS72_UTM_zone_35N"}, + {32236, "PCS_WGS72_UTM_zone_36N"}, + {32237, "PCS_WGS72_UTM_zone_37N"}, + {32238, "PCS_WGS72_UTM_zone_38N"}, + {32239, "PCS_WGS72_UTM_zone_39N"}, + {32240, "PCS_WGS72_UTM_zone_40N"}, + {32241, "PCS_WGS72_UTM_zone_41N"}, + {32242, "PCS_WGS72_UTM_zone_42N"}, + {32243, "PCS_WGS72_UTM_zone_43N"}, + {32244, "PCS_WGS72_UTM_zone_44N"}, + {32245, "PCS_WGS72_UTM_zone_45N"}, + {32246, "PCS_WGS72_UTM_zone_46N"}, + {32247, "PCS_WGS72_UTM_zone_47N"}, + {32248, "PCS_WGS72_UTM_zone_48N"}, + {32249, "PCS_WGS72_UTM_zone_49N"}, + {32250, "PCS_WGS72_UTM_zone_50N"}, + {32251, "PCS_WGS72_UTM_zone_51N"}, + {32252, "PCS_WGS72_UTM_zone_52N"}, + {32253, "PCS_WGS72_UTM_zone_53N"}, + {32254, "PCS_WGS72_UTM_zone_54N"}, + {32255, "PCS_WGS72_UTM_zone_55N"}, + {32256, "PCS_WGS72_UTM_zone_56N"}, + {32257, "PCS_WGS72_UTM_zone_57N"}, + {32258, "PCS_WGS72_UTM_zone_58N"}, + {32259, "PCS_WGS72_UTM_zone_59N"}, + {32260, "PCS_WGS72_UTM_zone_60N"}, + {32301, "PCS_WGS72_UTM_zone_1S"}, + {32302, "PCS_WGS72_UTM_zone_2S"}, + {32303, "PCS_WGS72_UTM_zone_3S"}, + {32304, "PCS_WGS72_UTM_zone_4S"}, + {32305, "PCS_WGS72_UTM_zone_5S"}, + {32306, "PCS_WGS72_UTM_zone_6S"}, + {32307, "PCS_WGS72_UTM_zone_7S"}, + {32308, "PCS_WGS72_UTM_zone_8S"}, + {32309, "PCS_WGS72_UTM_zone_9S"}, + {32310, "PCS_WGS72_UTM_zone_10S"}, + {32311, "PCS_WGS72_UTM_zone_11S"}, + {32312, "PCS_WGS72_UTM_zone_12S"}, + {32313, "PCS_WGS72_UTM_zone_13S"}, + {32314, "PCS_WGS72_UTM_zone_14S"}, + {32315, "PCS_WGS72_UTM_zone_15S"}, + {32316, "PCS_WGS72_UTM_zone_16S"}, + {32317, "PCS_WGS72_UTM_zone_17S"}, + {32318, "PCS_WGS72_UTM_zone_18S"}, + {32319, "PCS_WGS72_UTM_zone_19S"}, + {32320, "PCS_WGS72_UTM_zone_20S"}, + {32321, "PCS_WGS72_UTM_zone_21S"}, + {32322, "PCS_WGS72_UTM_zone_22S"}, + {32323, "PCS_WGS72_UTM_zone_23S"}, + {32324, "PCS_WGS72_UTM_zone_24S"}, + {32325, "PCS_WGS72_UTM_zone_25S"}, + {32326, "PCS_WGS72_UTM_zone_26S"}, + {32327, "PCS_WGS72_UTM_zone_27S"}, + {32328, "PCS_WGS72_UTM_zone_28S"}, + {32329, "PCS_WGS72_UTM_zone_29S"}, + {32330, "PCS_WGS72_UTM_zone_30S"}, + {32331, "PCS_WGS72_UTM_zone_31S"}, + {32332, "PCS_WGS72_UTM_zone_32S"}, + {32333, "PCS_WGS72_UTM_zone_33S"}, + {32334, "PCS_WGS72_UTM_zone_34S"}, + {32335, "PCS_WGS72_UTM_zone_35S"}, + {32336, "PCS_WGS72_UTM_zone_36S"}, + {32337, "PCS_WGS72_UTM_zone_37S"}, + {32338, "PCS_WGS72_UTM_zone_38S"}, + {32339, "PCS_WGS72_UTM_zone_39S"}, + {32340, "PCS_WGS72_UTM_zone_40S"}, + {32341, "PCS_WGS72_UTM_zone_41S"}, + {32342, "PCS_WGS72_UTM_zone_42S"}, + {32343, "PCS_WGS72_UTM_zone_43S"}, + {32344, "PCS_WGS72_UTM_zone_44S"}, + {32345, "PCS_WGS72_UTM_zone_45S"}, + {32346, "PCS_WGS72_UTM_zone_46S"}, + {32347, "PCS_WGS72_UTM_zone_47S"}, + {32348, "PCS_WGS72_UTM_zone_48S"}, + {32349, "PCS_WGS72_UTM_zone_49S"}, + {32350, "PCS_WGS72_UTM_zone_50S"}, + {32351, "PCS_WGS72_UTM_zone_51S"}, + {32352, "PCS_WGS72_UTM_zone_52S"}, + {32353, "PCS_WGS72_UTM_zone_53S"}, + {32354, "PCS_WGS72_UTM_zone_54S"}, + {32355, "PCS_WGS72_UTM_zone_55S"}, + {32356, "PCS_WGS72_UTM_zone_56S"}, + {32357, "PCS_WGS72_UTM_zone_57S"}, + {32358, "PCS_WGS72_UTM_zone_58S"}, + {32359, "PCS_WGS72_UTM_zone_59S"}, + {32360, "PCS_WGS72_UTM_zone_60S"}, + {32401, "PCS_WGS72BE_UTM_zone_1N"}, + {32402, "PCS_WGS72BE_UTM_zone_2N"}, + {32403, "PCS_WGS72BE_UTM_zone_3N"}, + {32404, "PCS_WGS72BE_UTM_zone_4N"}, + {32405, "PCS_WGS72BE_UTM_zone_5N"}, + {32406, "PCS_WGS72BE_UTM_zone_6N"}, + {32407, "PCS_WGS72BE_UTM_zone_7N"}, + {32408, "PCS_WGS72BE_UTM_zone_8N"}, + {32409, "PCS_WGS72BE_UTM_zone_9N"}, + {32410, "PCS_WGS72BE_UTM_zone_10N"}, + {32411, "PCS_WGS72BE_UTM_zone_11N"}, + {32412, "PCS_WGS72BE_UTM_zone_12N"}, + {32413, "PCS_WGS72BE_UTM_zone_13N"}, + {32414, "PCS_WGS72BE_UTM_zone_14N"}, + {32415, "PCS_WGS72BE_UTM_zone_15N"}, + {32416, "PCS_WGS72BE_UTM_zone_16N"}, + {32417, "PCS_WGS72BE_UTM_zone_17N"}, + {32418, "PCS_WGS72BE_UTM_zone_18N"}, + {32419, "PCS_WGS72BE_UTM_zone_19N"}, + {32420, "PCS_WGS72BE_UTM_zone_20N"}, + {32421, "PCS_WGS72BE_UTM_zone_21N"}, + {32422, "PCS_WGS72BE_UTM_zone_22N"}, + {32423, "PCS_WGS72BE_UTM_zone_23N"}, + {32424, "PCS_WGS72BE_UTM_zone_24N"}, + {32425, "PCS_WGS72BE_UTM_zone_25N"}, + {32426, "PCS_WGS72BE_UTM_zone_26N"}, + {32427, "PCS_WGS72BE_UTM_zone_27N"}, + {32428, "PCS_WGS72BE_UTM_zone_28N"}, + {32429, "PCS_WGS72BE_UTM_zone_29N"}, + {32430, "PCS_WGS72BE_UTM_zone_30N"}, + {32431, "PCS_WGS72BE_UTM_zone_31N"}, + {32432, "PCS_WGS72BE_UTM_zone_32N"}, + {32433, "PCS_WGS72BE_UTM_zone_33N"}, + {32434, "PCS_WGS72BE_UTM_zone_34N"}, + {32435, "PCS_WGS72BE_UTM_zone_35N"}, + {32436, "PCS_WGS72BE_UTM_zone_36N"}, + {32437, "PCS_WGS72BE_UTM_zone_37N"}, + {32438, "PCS_WGS72BE_UTM_zone_38N"}, + {32439, "PCS_WGS72BE_UTM_zone_39N"}, + {32440, "PCS_WGS72BE_UTM_zone_40N"}, + {32441, "PCS_WGS72BE_UTM_zone_41N"}, + {32442, "PCS_WGS72BE_UTM_zone_42N"}, + {32443, "PCS_WGS72BE_UTM_zone_43N"}, + {32444, "PCS_WGS72BE_UTM_zone_44N"}, + {32445, "PCS_WGS72BE_UTM_zone_45N"}, + {32446, "PCS_WGS72BE_UTM_zone_46N"}, + {32447, "PCS_WGS72BE_UTM_zone_47N"}, + {32448, "PCS_WGS72BE_UTM_zone_48N"}, + {32449, "PCS_WGS72BE_UTM_zone_49N"}, + {32450, "PCS_WGS72BE_UTM_zone_50N"}, + {32451, "PCS_WGS72BE_UTM_zone_51N"}, + {32452, "PCS_WGS72BE_UTM_zone_52N"}, + {32453, "PCS_WGS72BE_UTM_zone_53N"}, + {32454, "PCS_WGS72BE_UTM_zone_54N"}, + {32455, "PCS_WGS72BE_UTM_zone_55N"}, + {32456, "PCS_WGS72BE_UTM_zone_56N"}, + {32457, "PCS_WGS72BE_UTM_zone_57N"}, + {32458, "PCS_WGS72BE_UTM_zone_58N"}, + {32459, "PCS_WGS72BE_UTM_zone_59N"}, + {32460, "PCS_WGS72BE_UTM_zone_60N"}, + {32501, "PCS_WGS72BE_UTM_zone_1S"}, + {32502, "PCS_WGS72BE_UTM_zone_2S"}, + {32503, "PCS_WGS72BE_UTM_zone_3S"}, + {32504, "PCS_WGS72BE_UTM_zone_4S"}, + {32505, "PCS_WGS72BE_UTM_zone_5S"}, + {32506, "PCS_WGS72BE_UTM_zone_6S"}, + {32507, "PCS_WGS72BE_UTM_zone_7S"}, + {32508, "PCS_WGS72BE_UTM_zone_8S"}, + {32509, "PCS_WGS72BE_UTM_zone_9S"}, + {32510, "PCS_WGS72BE_UTM_zone_10S"}, + {32511, "PCS_WGS72BE_UTM_zone_11S"}, + {32512, "PCS_WGS72BE_UTM_zone_12S"}, + {32513, "PCS_WGS72BE_UTM_zone_13S"}, + {32514, "PCS_WGS72BE_UTM_zone_14S"}, + {32515, "PCS_WGS72BE_UTM_zone_15S"}, + {32516, "PCS_WGS72BE_UTM_zone_16S"}, + {32517, "PCS_WGS72BE_UTM_zone_17S"}, + {32518, "PCS_WGS72BE_UTM_zone_18S"}, + {32519, "PCS_WGS72BE_UTM_zone_19S"}, + {32520, "PCS_WGS72BE_UTM_zone_20S"}, + {32521, "PCS_WGS72BE_UTM_zone_21S"}, + {32522, "PCS_WGS72BE_UTM_zone_22S"}, + {32523, "PCS_WGS72BE_UTM_zone_23S"}, + {32524, "PCS_WGS72BE_UTM_zone_24S"}, + {32525, "PCS_WGS72BE_UTM_zone_25S"}, + {32526, "PCS_WGS72BE_UTM_zone_26S"}, + {32527, "PCS_WGS72BE_UTM_zone_27S"}, + {32528, "PCS_WGS72BE_UTM_zone_28S"}, + {32529, "PCS_WGS72BE_UTM_zone_29S"}, + {32530, "PCS_WGS72BE_UTM_zone_30S"}, + {32531, "PCS_WGS72BE_UTM_zone_31S"}, + {32532, "PCS_WGS72BE_UTM_zone_32S"}, + {32533, "PCS_WGS72BE_UTM_zone_33S"}, + {32534, "PCS_WGS72BE_UTM_zone_34S"}, + {32535, "PCS_WGS72BE_UTM_zone_35S"}, + {32536, "PCS_WGS72BE_UTM_zone_36S"}, + {32537, "PCS_WGS72BE_UTM_zone_37S"}, + {32538, "PCS_WGS72BE_UTM_zone_38S"}, + {32539, "PCS_WGS72BE_UTM_zone_39S"}, + {32540, "PCS_WGS72BE_UTM_zone_40S"}, + {32541, "PCS_WGS72BE_UTM_zone_41S"}, + {32542, "PCS_WGS72BE_UTM_zone_42S"}, + {32543, "PCS_WGS72BE_UTM_zone_43S"}, + {32544, "PCS_WGS72BE_UTM_zone_44S"}, + {32545, "PCS_WGS72BE_UTM_zone_45S"}, + {32546, "PCS_WGS72BE_UTM_zone_46S"}, + {32547, "PCS_WGS72BE_UTM_zone_47S"}, + {32548, "PCS_WGS72BE_UTM_zone_48S"}, + {32549, "PCS_WGS72BE_UTM_zone_49S"}, + {32550, "PCS_WGS72BE_UTM_zone_50S"}, + {32551, "PCS_WGS72BE_UTM_zone_51S"}, + {32552, "PCS_WGS72BE_UTM_zone_52S"}, + {32553, "PCS_WGS72BE_UTM_zone_53S"}, + {32554, "PCS_WGS72BE_UTM_zone_54S"}, + {32555, "PCS_WGS72BE_UTM_zone_55S"}, + {32556, "PCS_WGS72BE_UTM_zone_56S"}, + {32557, "PCS_WGS72BE_UTM_zone_57S"}, + {32558, "PCS_WGS72BE_UTM_zone_58S"}, + {32559, "PCS_WGS72BE_UTM_zone_59S"}, + {32560, "PCS_WGS72BE_UTM_zone_60S"}, + {32601, "PCS_WGS84_UTM_zone_1N"}, + {32602, "PCS_WGS84_UTM_zone_2N"}, + {32603, "PCS_WGS84_UTM_zone_3N"}, + {32604, "PCS_WGS84_UTM_zone_4N"}, + {32605, "PCS_WGS84_UTM_zone_5N"}, + {32606, "PCS_WGS84_UTM_zone_6N"}, + {32607, "PCS_WGS84_UTM_zone_7N"}, + {32608, "PCS_WGS84_UTM_zone_8N"}, + {32609, "PCS_WGS84_UTM_zone_9N"}, + {32610, "PCS_WGS84_UTM_zone_10N"}, + {32611, "PCS_WGS84_UTM_zone_11N"}, + {32612, "PCS_WGS84_UTM_zone_12N"}, + {32613, "PCS_WGS84_UTM_zone_13N"}, + {32614, "PCS_WGS84_UTM_zone_14N"}, + {32615, "PCS_WGS84_UTM_zone_15N"}, + {32616, "PCS_WGS84_UTM_zone_16N"}, + {32617, "PCS_WGS84_UTM_zone_17N"}, + {32618, "PCS_WGS84_UTM_zone_18N"}, + {32619, "PCS_WGS84_UTM_zone_19N"}, + {32620, "PCS_WGS84_UTM_zone_20N"}, + {32621, "PCS_WGS84_UTM_zone_21N"}, + {32622, "PCS_WGS84_UTM_zone_22N"}, + {32623, "PCS_WGS84_UTM_zone_23N"}, + {32624, "PCS_WGS84_UTM_zone_24N"}, + {32625, "PCS_WGS84_UTM_zone_25N"}, + {32626, "PCS_WGS84_UTM_zone_26N"}, + {32627, "PCS_WGS84_UTM_zone_27N"}, + {32628, "PCS_WGS84_UTM_zone_28N"}, + {32629, "PCS_WGS84_UTM_zone_29N"}, + {32630, "PCS_WGS84_UTM_zone_30N"}, + {32631, "PCS_WGS84_UTM_zone_31N"}, + {32632, "PCS_WGS84_UTM_zone_32N"}, + {32633, "PCS_WGS84_UTM_zone_33N"}, + {32634, "PCS_WGS84_UTM_zone_34N"}, + {32635, "PCS_WGS84_UTM_zone_35N"}, + {32636, "PCS_WGS84_UTM_zone_36N"}, + {32637, "PCS_WGS84_UTM_zone_37N"}, + {32638, "PCS_WGS84_UTM_zone_38N"}, + {32639, "PCS_WGS84_UTM_zone_39N"}, + {32640, "PCS_WGS84_UTM_zone_40N"}, + {32641, "PCS_WGS84_UTM_zone_41N"}, + {32642, "PCS_WGS84_UTM_zone_42N"}, + {32643, "PCS_WGS84_UTM_zone_43N"}, + {32644, "PCS_WGS84_UTM_zone_44N"}, + {32645, "PCS_WGS84_UTM_zone_45N"}, + {32646, "PCS_WGS84_UTM_zone_46N"}, + {32647, "PCS_WGS84_UTM_zone_47N"}, + {32648, "PCS_WGS84_UTM_zone_48N"}, + {32649, "PCS_WGS84_UTM_zone_49N"}, + {32650, "PCS_WGS84_UTM_zone_50N"}, + {32651, "PCS_WGS84_UTM_zone_51N"}, + {32652, "PCS_WGS84_UTM_zone_52N"}, + {32653, "PCS_WGS84_UTM_zone_53N"}, + {32654, "PCS_WGS84_UTM_zone_54N"}, + {32655, "PCS_WGS84_UTM_zone_55N"}, + {32656, "PCS_WGS84_UTM_zone_56N"}, + {32657, "PCS_WGS84_UTM_zone_57N"}, + {32658, "PCS_WGS84_UTM_zone_58N"}, + {32659, "PCS_WGS84_UTM_zone_59N"}, + {32660, "PCS_WGS84_UTM_zone_60N"}, + {32701, "PCS_WGS84_UTM_zone_1S"}, + {32702, "PCS_WGS84_UTM_zone_2S"}, + {32703, "PCS_WGS84_UTM_zone_3S"}, + {32704, "PCS_WGS84_UTM_zone_4S"}, + {32705, "PCS_WGS84_UTM_zone_5S"}, + {32706, "PCS_WGS84_UTM_zone_6S"}, + {32707, "PCS_WGS84_UTM_zone_7S"}, + {32708, "PCS_WGS84_UTM_zone_8S"}, + {32709, "PCS_WGS84_UTM_zone_9S"}, + {32710, "PCS_WGS84_UTM_zone_10S"}, + {32711, "PCS_WGS84_UTM_zone_11S"}, + {32712, "PCS_WGS84_UTM_zone_12S"}, + {32713, "PCS_WGS84_UTM_zone_13S"}, + {32714, "PCS_WGS84_UTM_zone_14S"}, + {32715, "PCS_WGS84_UTM_zone_15S"}, + {32716, "PCS_WGS84_UTM_zone_16S"}, + {32717, "PCS_WGS84_UTM_zone_17S"}, + {32718, "PCS_WGS84_UTM_zone_18S"}, + {32719, "PCS_WGS84_UTM_zone_19S"}, + {32720, "PCS_WGS84_UTM_zone_20S"}, + {32721, "PCS_WGS84_UTM_zone_21S"}, + {32722, "PCS_WGS84_UTM_zone_22S"}, + {32723, "PCS_WGS84_UTM_zone_23S"}, + {32724, "PCS_WGS84_UTM_zone_24S"}, + {32725, "PCS_WGS84_UTM_zone_25S"}, + {32726, "PCS_WGS84_UTM_zone_26S"}, + {32727, "PCS_WGS84_UTM_zone_27S"}, + {32728, "PCS_WGS84_UTM_zone_28S"}, + {32729, "PCS_WGS84_UTM_zone_29S"}, + {32730, "PCS_WGS84_UTM_zone_30S"}, + {32731, "PCS_WGS84_UTM_zone_31S"}, + {32732, "PCS_WGS84_UTM_zone_32S"}, + {32733, "PCS_WGS84_UTM_zone_33S"}, + {32734, "PCS_WGS84_UTM_zone_34S"}, + {32735, "PCS_WGS84_UTM_zone_35S"}, + {32736, "PCS_WGS84_UTM_zone_36S"}, + {32737, "PCS_WGS84_UTM_zone_37S"}, + {32738, "PCS_WGS84_UTM_zone_38S"}, + {32739, "PCS_WGS84_UTM_zone_39S"}, + {32740, "PCS_WGS84_UTM_zone_40S"}, + {32741, "PCS_WGS84_UTM_zone_41S"}, + {32742, "PCS_WGS84_UTM_zone_42S"}, + {32743, "PCS_WGS84_UTM_zone_43S"}, + {32744, "PCS_WGS84_UTM_zone_44S"}, + {32745, "PCS_WGS84_UTM_zone_45S"}, + {32746, "PCS_WGS84_UTM_zone_46S"}, + {32747, "PCS_WGS84_UTM_zone_47S"}, + {32748, "PCS_WGS84_UTM_zone_48S"}, + {32749, "PCS_WGS84_UTM_zone_49S"}, + {32750, "PCS_WGS84_UTM_zone_50S"}, + {32751, "PCS_WGS84_UTM_zone_51S"}, + {32752, "PCS_WGS84_UTM_zone_52S"}, + {32753, "PCS_WGS84_UTM_zone_53S"}, + {32754, "PCS_WGS84_UTM_zone_54S"}, + {32755, "PCS_WGS84_UTM_zone_55S"}, + {32756, "PCS_WGS84_UTM_zone_56S"}, + {32757, "PCS_WGS84_UTM_zone_57S"}, + {32758, "PCS_WGS84_UTM_zone_58S"}, + {32759, "PCS_WGS84_UTM_zone_59S"}, + {32760, "PCS_WGS84_UTM_zone_60S"} +}; + +const TiffGeoTagKeyName ff_tiff_projection_codes[] = { + {10101, "Proj_Alabama_CS27_East"}, + {10102, "Proj_Alabama_CS27_West"}, + {10131, "Proj_Alabama_CS83_East"}, + {10132, "Proj_Alabama_CS83_West"}, + {10201, "Proj_Arizona_Coordinate_System_east"}, + {10202, "Proj_Arizona_Coordinate_System_Central"}, + {10203, "Proj_Arizona_Coordinate_System_west"}, + {10231, "Proj_Arizona_CS83_east"}, + {10232, "Proj_Arizona_CS83_Central"}, + {10233, "Proj_Arizona_CS83_west"}, + {10301, "Proj_Arkansas_CS27_North"}, + {10302, "Proj_Arkansas_CS27_South"}, + {10331, "Proj_Arkansas_CS83_North"}, + {10332, "Proj_Arkansas_CS83_South"}, + {10401, "Proj_California_CS27_I"}, + {10402, "Proj_California_CS27_II"}, + {10403, "Proj_California_CS27_III"}, + {10404, "Proj_California_CS27_IV"}, + {10405, "Proj_California_CS27_V"}, + {10406, "Proj_California_CS27_VI"}, + {10407, "Proj_California_CS27_VII"}, + {10431, "Proj_California_CS83_1"}, + {10432, "Proj_California_CS83_2"}, + {10433, "Proj_California_CS83_3"}, + {10434, "Proj_California_CS83_4"}, + {10435, "Proj_California_CS83_5"}, + {10436, "Proj_California_CS83_6"}, + {10501, "Proj_Colorado_CS27_North"}, + {10502, "Proj_Colorado_CS27_Central"}, + {10503, "Proj_Colorado_CS27_South"}, + {10531, "Proj_Colorado_CS83_North"}, + {10532, "Proj_Colorado_CS83_Central"}, + {10533, "Proj_Colorado_CS83_South"}, + {10600, "Proj_Connecticut_CS27"}, + {10630, "Proj_Connecticut_CS83"}, + {10700, "Proj_Delaware_CS27"}, + {10730, "Proj_Delaware_CS83"}, + {10901, "Proj_Florida_CS27_East"}, + {10902, "Proj_Florida_CS27_West"}, + {10903, "Proj_Florida_CS27_North"}, + {10931, "Proj_Florida_CS83_East"}, + {10932, "Proj_Florida_CS83_West"}, + {10933, "Proj_Florida_CS83_North"}, + {11001, "Proj_Georgia_CS27_East"}, + {11002, "Proj_Georgia_CS27_West"}, + {11031, "Proj_Georgia_CS83_East"}, + {11032, "Proj_Georgia_CS83_West"}, + {11101, "Proj_Idaho_CS27_East"}, + {11102, "Proj_Idaho_CS27_Central"}, + {11103, "Proj_Idaho_CS27_West"}, + {11131, "Proj_Idaho_CS83_East"}, + {11132, "Proj_Idaho_CS83_Central"}, + {11133, "Proj_Idaho_CS83_West"}, + {11201, "Proj_Illinois_CS27_East"}, + {11202, "Proj_Illinois_CS27_West"}, + {11231, "Proj_Illinois_CS83_East"}, + {11232, "Proj_Illinois_CS83_West"}, + {11301, "Proj_Indiana_CS27_East"}, + {11302, "Proj_Indiana_CS27_West"}, + {11331, "Proj_Indiana_CS83_East"}, + {11332, "Proj_Indiana_CS83_West"}, + {11401, "Proj_Iowa_CS27_North"}, + {11402, "Proj_Iowa_CS27_South"}, + {11431, "Proj_Iowa_CS83_North"}, + {11432, "Proj_Iowa_CS83_South"}, + {11501, "Proj_Kansas_CS27_North"}, + {11502, "Proj_Kansas_CS27_South"}, + {11531, "Proj_Kansas_CS83_North"}, + {11532, "Proj_Kansas_CS83_South"}, + {11601, "Proj_Kentucky_CS27_North"}, + {11602, "Proj_Kentucky_CS27_South"}, + {11631, "Proj_Kentucky_CS83_North"}, + {11632, "Proj_Kentucky_CS83_South"}, + {11701, "Proj_Louisiana_CS27_North"}, + {11702, "Proj_Louisiana_CS27_South"}, + {11731, "Proj_Louisiana_CS83_North"}, + {11732, "Proj_Louisiana_CS83_South"}, + {11801, "Proj_Maine_CS27_East"}, + {11802, "Proj_Maine_CS27_West"}, + {11831, "Proj_Maine_CS83_East"}, + {11832, "Proj_Maine_CS83_West"}, + {11900, "Proj_Maryland_CS27"}, + {11930, "Proj_Maryland_CS83"}, + {12001, "Proj_Massachusetts_CS27_Mainland"}, + {12002, "Proj_Massachusetts_CS27_Island"}, + {12031, "Proj_Massachusetts_CS83_Mainland"}, + {12032, "Proj_Massachusetts_CS83_Island"}, + {12101, "Proj_Michigan_State_Plane_East"}, + {12102, "Proj_Michigan_State_Plane_Old_Central"}, + {12103, "Proj_Michigan_State_Plane_West"}, + {12111, "Proj_Michigan_CS27_North"}, + {12112, "Proj_Michigan_CS27_Central"}, + {12113, "Proj_Michigan_CS27_South"}, + {12141, "Proj_Michigan_CS83_North"}, + {12142, "Proj_Michigan_CS83_Central"}, + {12143, "Proj_Michigan_CS83_South"}, + {12201, "Proj_Minnesota_CS27_North"}, + {12202, "Proj_Minnesota_CS27_Central"}, + {12203, "Proj_Minnesota_CS27_South"}, + {12231, "Proj_Minnesota_CS83_North"}, + {12232, "Proj_Minnesota_CS83_Central"}, + {12233, "Proj_Minnesota_CS83_South"}, + {12301, "Proj_Mississippi_CS27_East"}, + {12302, "Proj_Mississippi_CS27_West"}, + {12331, "Proj_Mississippi_CS83_East"}, + {12332, "Proj_Mississippi_CS83_West"}, + {12401, "Proj_Missouri_CS27_East"}, + {12402, "Proj_Missouri_CS27_Central"}, + {12403, "Proj_Missouri_CS27_West"}, + {12431, "Proj_Missouri_CS83_East"}, + {12432, "Proj_Missouri_CS83_Central"}, + {12433, "Proj_Missouri_CS83_West"}, + {12501, "Proj_Montana_CS27_North"}, + {12502, "Proj_Montana_CS27_Central"}, + {12503, "Proj_Montana_CS27_South"}, + {12530, "Proj_Montana_CS83"}, + {12601, "Proj_Nebraska_CS27_North"}, + {12602, "Proj_Nebraska_CS27_South"}, + {12630, "Proj_Nebraska_CS83"}, + {12701, "Proj_Nevada_CS27_East"}, + {12702, "Proj_Nevada_CS27_Central"}, + {12703, "Proj_Nevada_CS27_West"}, + {12731, "Proj_Nevada_CS83_East"}, + {12732, "Proj_Nevada_CS83_Central"}, + {12733, "Proj_Nevada_CS83_West"}, + {12800, "Proj_New_Hampshire_CS27"}, + {12830, "Proj_New_Hampshire_CS83"}, + {12900, "Proj_New_Jersey_CS27"}, + {12930, "Proj_New_Jersey_CS83"}, + {13001, "Proj_New_Mexico_CS27_East"}, + {13002, "Proj_New_Mexico_CS27_Central"}, + {13003, "Proj_New_Mexico_CS27_West"}, + {13031, "Proj_New_Mexico_CS83_East"}, + {13032, "Proj_New_Mexico_CS83_Central"}, + {13033, "Proj_New_Mexico_CS83_West"}, + {13101, "Proj_New_York_CS27_East"}, + {13102, "Proj_New_York_CS27_Central"}, + {13103, "Proj_New_York_CS27_West"}, + {13104, "Proj_New_York_CS27_Long_Island"}, + {13131, "Proj_New_York_CS83_East"}, + {13132, "Proj_New_York_CS83_Central"}, + {13133, "Proj_New_York_CS83_West"}, + {13134, "Proj_New_York_CS83_Long_Island"}, + {13200, "Proj_North_Carolina_CS27"}, + {13230, "Proj_North_Carolina_CS83"}, + {13301, "Proj_North_Dakota_CS27_North"}, + {13302, "Proj_North_Dakota_CS27_South"}, + {13331, "Proj_North_Dakota_CS83_North"}, + {13332, "Proj_North_Dakota_CS83_South"}, + {13401, "Proj_Ohio_CS27_North"}, + {13402, "Proj_Ohio_CS27_South"}, + {13431, "Proj_Ohio_CS83_North"}, + {13432, "Proj_Ohio_CS83_South"}, + {13501, "Proj_Oklahoma_CS27_North"}, + {13502, "Proj_Oklahoma_CS27_South"}, + {13531, "Proj_Oklahoma_CS83_North"}, + {13532, "Proj_Oklahoma_CS83_South"}, + {13601, "Proj_Oregon_CS27_North"}, + {13602, "Proj_Oregon_CS27_South"}, + {13631, "Proj_Oregon_CS83_North"}, + {13632, "Proj_Oregon_CS83_South"}, + {13701, "Proj_Pennsylvania_CS27_North"}, + {13702, "Proj_Pennsylvania_CS27_South"}, + {13731, "Proj_Pennsylvania_CS83_North"}, + {13732, "Proj_Pennsylvania_CS83_South"}, + {13800, "Proj_Rhode_Island_CS27"}, + {13830, "Proj_Rhode_Island_CS83"}, + {13901, "Proj_South_Carolina_CS27_North"}, + {13902, "Proj_South_Carolina_CS27_South"}, + {13930, "Proj_South_Carolina_CS83"}, + {14001, "Proj_South_Dakota_CS27_North"}, + {14002, "Proj_South_Dakota_CS27_South"}, + {14031, "Proj_South_Dakota_CS83_North"}, + {14032, "Proj_South_Dakota_CS83_South"}, + {14100, "Proj_Tennessee_CS27"}, + {14130, "Proj_Tennessee_CS83"}, + {14201, "Proj_Texas_CS27_North"}, + {14202, "Proj_Texas_CS27_North_Central"}, + {14203, "Proj_Texas_CS27_Central"}, + {14204, "Proj_Texas_CS27_South_Central"}, + {14205, "Proj_Texas_CS27_South"}, + {14231, "Proj_Texas_CS83_North"}, + {14232, "Proj_Texas_CS83_North_Central"}, + {14233, "Proj_Texas_CS83_Central"}, + {14234, "Proj_Texas_CS83_South_Central"}, + {14235, "Proj_Texas_CS83_South"}, + {14301, "Proj_Utah_CS27_North"}, + {14302, "Proj_Utah_CS27_Central"}, + {14303, "Proj_Utah_CS27_South"}, + {14331, "Proj_Utah_CS83_North"}, + {14332, "Proj_Utah_CS83_Central"}, + {14333, "Proj_Utah_CS83_South"}, + {14400, "Proj_Vermont_CS27"}, + {14430, "Proj_Vermont_CS83"}, + {14501, "Proj_Virginia_CS27_North"}, + {14502, "Proj_Virginia_CS27_South"}, + {14531, "Proj_Virginia_CS83_North"}, + {14532, "Proj_Virginia_CS83_South"}, + {14601, "Proj_Washington_CS27_North"}, + {14602, "Proj_Washington_CS27_South"}, + {14631, "Proj_Washington_CS83_North"}, + {14632, "Proj_Washington_CS83_South"}, + {14701, "Proj_West_Virginia_CS27_North"}, + {14702, "Proj_West_Virginia_CS27_South"}, + {14731, "Proj_West_Virginia_CS83_North"}, + {14732, "Proj_West_Virginia_CS83_South"}, + {14801, "Proj_Wisconsin_CS27_North"}, + {14802, "Proj_Wisconsin_CS27_Central"}, + {14803, "Proj_Wisconsin_CS27_South"}, + {14831, "Proj_Wisconsin_CS83_North"}, + {14832, "Proj_Wisconsin_CS83_Central"}, + {14833, "Proj_Wisconsin_CS83_South"}, + {14901, "Proj_Wyoming_CS27_East"}, + {14902, "Proj_Wyoming_CS27_East_Central"}, + {14903, "Proj_Wyoming_CS27_West_Central"}, + {14904, "Proj_Wyoming_CS27_West"}, + {14931, "Proj_Wyoming_CS83_East"}, + {14932, "Proj_Wyoming_CS83_East_Central"}, + {14933, "Proj_Wyoming_CS83_West_Central"}, + {14934, "Proj_Wyoming_CS83_West"}, + {15001, "Proj_Alaska_CS27_1"}, + {15002, "Proj_Alaska_CS27_2"}, + {15003, "Proj_Alaska_CS27_3"}, + {15004, "Proj_Alaska_CS27_4"}, + {15005, "Proj_Alaska_CS27_5"}, + {15006, "Proj_Alaska_CS27_6"}, + {15007, "Proj_Alaska_CS27_7"}, + {15008, "Proj_Alaska_CS27_8"}, + {15009, "Proj_Alaska_CS27_9"}, + {15010, "Proj_Alaska_CS27_10"}, + {15031, "Proj_Alaska_CS83_1"}, + {15032, "Proj_Alaska_CS83_2"}, + {15033, "Proj_Alaska_CS83_3"}, + {15034, "Proj_Alaska_CS83_4"}, + {15035, "Proj_Alaska_CS83_5"}, + {15036, "Proj_Alaska_CS83_6"}, + {15037, "Proj_Alaska_CS83_7"}, + {15038, "Proj_Alaska_CS83_8"}, + {15039, "Proj_Alaska_CS83_9"}, + {15040, "Proj_Alaska_CS83_10"}, + {15101, "Proj_Hawaii_CS27_1"}, + {15102, "Proj_Hawaii_CS27_2"}, + {15103, "Proj_Hawaii_CS27_3"}, + {15104, "Proj_Hawaii_CS27_4"}, + {15105, "Proj_Hawaii_CS27_5"}, + {15131, "Proj_Hawaii_CS83_1"}, + {15132, "Proj_Hawaii_CS83_2"}, + {15133, "Proj_Hawaii_CS83_3"}, + {15134, "Proj_Hawaii_CS83_4"}, + {15135, "Proj_Hawaii_CS83_5"}, + {15201, "Proj_Puerto_Rico_CS27"}, + {15202, "Proj_St_Croix"}, + {15230, "Proj_Puerto_Rico_Virgin_Is"}, + {15914, "Proj_BLM_14N_feet"}, + {15915, "Proj_BLM_15N_feet"}, + {15916, "Proj_BLM_16N_feet"}, + {15917, "Proj_BLM_17N_feet"}, + {17348, "Proj_Map_Grid_of_Australia_48"}, + {17349, "Proj_Map_Grid_of_Australia_49"}, + {17350, "Proj_Map_Grid_of_Australia_50"}, + {17351, "Proj_Map_Grid_of_Australia_51"}, + {17352, "Proj_Map_Grid_of_Australia_52"}, + {17353, "Proj_Map_Grid_of_Australia_53"}, + {17354, "Proj_Map_Grid_of_Australia_54"}, + {17355, "Proj_Map_Grid_of_Australia_55"}, + {17356, "Proj_Map_Grid_of_Australia_56"}, + {17357, "Proj_Map_Grid_of_Australia_57"}, + {17358, "Proj_Map_Grid_of_Australia_58"}, + {17448, "Proj_Australian_Map_Grid_48"}, + {17449, "Proj_Australian_Map_Grid_49"}, + {17450, "Proj_Australian_Map_Grid_50"}, + {17451, "Proj_Australian_Map_Grid_51"}, + {17452, "Proj_Australian_Map_Grid_52"}, + {17453, "Proj_Australian_Map_Grid_53"}, + {17454, "Proj_Australian_Map_Grid_54"}, + {17455, "Proj_Australian_Map_Grid_55"}, + {17456, "Proj_Australian_Map_Grid_56"}, + {17457, "Proj_Australian_Map_Grid_57"}, + {17458, "Proj_Australian_Map_Grid_58"}, + {18031, "Proj_Argentina_1"}, + {18032, "Proj_Argentina_2"}, + {18033, "Proj_Argentina_3"}, + {18034, "Proj_Argentina_4"}, + {18035, "Proj_Argentina_5"}, + {18036, "Proj_Argentina_6"}, + {18037, "Proj_Argentina_7"}, + {18051, "Proj_Colombia_3W"}, + {18052, "Proj_Colombia_Bogota"}, + {18053, "Proj_Colombia_3E"}, + {18054, "Proj_Colombia_6E"}, + {18072, "Proj_Egypt_Red_Belt"}, + {18073, "Proj_Egypt_Purple_Belt"}, + {18074, "Proj_Extended_Purple_Belt"}, + {18141, "Proj_New_Zealand_North_Island_Nat_Grid"}, + {18142, "Proj_New_Zealand_South_Island_Nat_Grid"}, + {19900, "Proj_Bahrain_Grid"}, + {19905, "Proj_Netherlands_E_Indies_Equatorial"}, + {19912, "Proj_RSO_Borneo"} +}; + +const char *const ff_tiff_coord_trans_codes[] = { + "CT_TransverseMercator", + "CT_TransvMercator_Modified_Alaska", + "CT_ObliqueMercator", + "CT_ObliqueMercator_Laborde", + "CT_ObliqueMercator_Rosenmund", + "CT_ObliqueMercator_Spherical", + "CT_Mercator", + "CT_LambertConfConic_2SP", + "CT_LambertConfConic_Helmert", + "CT_LambertAzimEqualArea", + "CT_AlbersEqualArea", + "CT_AzimuthalEquidistant", + "CT_EquidistantConic", + "CT_Stereographic", + "CT_PolarStereographic", + "CT_ObliqueStereographic", + "CT_Equirectangular", + "CT_CassiniSoldner", + "CT_Gnomonic", + "CT_MillerCylindrical", + "CT_Orthographic", + "CT_Polyconic", + "CT_Robinson", + "CT_Sinusoidal", + "CT_VanDerGrinten", + "CT_NewZealandMapGrid", + "CT_TransvMercator_SouthOriented" +}; + +const char *const ff_tiff_vert_cs_codes[] = { + "VertCS_Airy_1830_ellipsoid", + "VertCS_Airy_Modified_1849_ellipsoid", + "VertCS_ANS_ellipsoid", + "VertCS_Bessel_1841_ellipsoid", + "VertCS_Bessel_Modified_ellipsoid", + "VertCS_Bessel_Namibia_ellipsoid", + "VertCS_Clarke_1858_ellipsoid", + "VertCS_Clarke_1866_ellipsoid", + "VertCS_Clarke_1880_Benoit_ellipsoid", + "VertCS_Clarke_1880_IGN_ellipsoid", + "VertCS_Clarke_1880_RGS_ellipsoid", + "VertCS_Clarke_1880_Arc_ellipsoid", + "VertCS_Clarke_1880_SGA_1922_ellipsoid", + "VertCS_Everest_1830_1937_Adjustment_ellipsoid", + "VertCS_Everest_1830_1967_Definition_ellipsoid", + "VertCS_Everest_1830_1975_Definition_ellipsoid", + "VertCS_Everest_1830_Modified_ellipsoid", + "VertCS_GRS_1980_ellipsoid", + "VertCS_Helmert_1906_ellipsoid", + "VertCS_INS_ellipsoid", + "VertCS_International_1924_ellipsoid", + "VertCS_International_1967_ellipsoid", + "VertCS_Krassowsky_1940_ellipsoid", + "VertCS_NWL_9D_ellipsoid", + "VertCS_NWL_10D_ellipsoid", + "VertCS_Plessis_1817_ellipsoid", + "VertCS_Struve_1860_ellipsoid", + "VertCS_War_Office_ellipsoid", + "VertCS_WGS_84_ellipsoid", + "VertCS_GEM_10C_ellipsoid", + "VertCS_OSU86F_ellipsoid", + "VertCS_OSU91A_ellipsoid" +}; + +const char *const ff_tiff_ortho_vert_cs_codes[] = { + "VertCS_Newlyn", + "VertCS_North_American_Vertical_Datum_1929", + "VertCS_North_American_Vertical_Datum_1988", + "VertCS_Yellow_Sea_1956", + "VertCS_Baltic_Sea", + "VertCS_Caspian_Sea" +}; diff --git a/ffmpeg/libavcodec/tiff_data.h b/ffmpeg/libavcodec/tiff_data.h new file mode 100644 index 0000000..91a4e1e --- /dev/null +++ b/ffmpeg/libavcodec/tiff_data.h @@ -0,0 +1,92 @@ +/* + * TIFF data tables + * Copyright (c) 2011 Thomas Kuehnel + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * TIFF data tables + * @author Thomas Kuehnel + * @see GeoTIFF specification at + * http://www.remotesensing.org/geotiff/spec/geotiffhome.html + */ + +#ifndef AVCODEC_TIFF_DATA_H +#define AVCODEC_TIFF_DATA_H + +#include "tiff.h" + +#define TIFF_CONF_KEY_ID_OFFSET 1024 +extern const TiffGeoTagNameType ff_tiff_conf_name_type_map[3]; + +#define TIFF_GEOG_KEY_ID_OFFSET 2048 +extern const TiffGeoTagNameType ff_tiff_geog_name_type_map[14]; + +#define TIFF_PROJ_KEY_ID_OFFSET 3072 +extern const TiffGeoTagNameType ff_tiff_proj_name_type_map[24]; + +#define TIFF_VERT_KEY_ID_OFFSET 4096 +extern const TiffGeoTagNameType ff_tiff_vert_name_type_map[4]; + +#define TIFF_GEO_KEY_UNDEFINED 0 +#define TIFF_GEO_KEY_USER_DEFINED 32767 + +#define TIFF_GT_MODEL_TYPE_OFFSET 1 +extern const char *const ff_tiff_gt_model_type_codes[3]; + +#define TIFF_GT_RASTER_TYPE_OFFSET 1 +extern const char *const ff_tiff_gt_raster_type_codes[2]; + +#define TIFF_LINEAR_UNIT_OFFSET 9001 +extern const char *const ff_tiff_linear_unit_codes[15]; + +#define TIFF_ANGULAR_UNIT_OFFSET 9101 +extern const char *const ff_tiff_angular_unit_codes[8]; + +#define TIFF_GCS_TYPE_OFFSET 4201 +extern const char *const ff_tiff_gcs_type_codes[133]; + +#define TIFF_GCSE_TYPE_OFFSET 4001 +extern const char *const ff_tiff_gcse_type_codes[35]; + +#define TIFF_GEODETIC_DATUM_OFFSET 6201 +extern const char *const ff_tiff_geodetic_datum_codes[120]; + +#define TIFF_GEODETIC_DATUM_E_OFFSET 6001 +extern const char *const ff_tiff_geodetic_datum_e_codes[35]; + +#define TIFF_ELLIPSOID_OFFSET 7001 +extern const char *const ff_tiff_ellipsoid_codes[35]; + +#define TIFF_PRIME_MERIDIAN_OFFSET 8901 +extern const char *const ff_tiff_prime_meridian_codes[11]; + +extern const TiffGeoTagKeyName ff_tiff_proj_cs_type_codes[978]; + +extern const TiffGeoTagKeyName ff_tiff_projection_codes[298]; + +#define TIFF_COORD_TRANS_OFFSET 1 +extern const char *const ff_tiff_coord_trans_codes[27]; + +#define TIFF_VERT_CS_OFFSET 5001 +extern const char *const ff_tiff_vert_cs_codes[32]; + +#define TIFF_ORTHO_VERT_CS_OFFSET 5101 +extern const char *const ff_tiff_ortho_vert_cs_codes[6]; +#endif diff --git a/ffmpeg/libavcodec/tiffenc.c b/ffmpeg/libavcodec/tiffenc.c new file mode 100644 index 0000000..61294b9 --- /dev/null +++ b/ffmpeg/libavcodec/tiffenc.c @@ -0,0 +1,546 @@ +/* + * TIFF image encoder + * Copyright (c) 2007 Bartlomiej Wolowiec + * + * 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 + */ + +/** + * @file + * TIFF image encoder + * @author Bartlomiej Wolowiec + */ + +#include "libavutil/imgutils.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avcodec.h" +#include "config.h" +#if CONFIG_ZLIB +#include +#endif +#include "bytestream.h" +#include "internal.h" +#include "tiff.h" +#include "rle.h" +#include "lzw.h" +#include "put_bits.h" + +#define TIFF_MAX_ENTRY 32 + +/** sizes of various TIFF field types (string size = 1)*/ +static const uint8_t type_sizes2[14] = { + 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4 +}; + +typedef struct TiffEncoderContext { + AVClass *class; ///< for private options + AVCodecContext *avctx; + AVFrame picture; + + int width; ///< picture width + int height; ///< picture height + unsigned int bpp; ///< bits per pixel + int compr; ///< compression level + int bpp_tab_size; ///< bpp_tab size + int photometric_interpretation; ///< photometric interpretation + int strips; ///< number of strips + uint32_t *strip_sizes; + unsigned int strip_sizes_size; + uint32_t *strip_offsets; + unsigned int strip_offsets_size; + uint8_t *yuv_line; + unsigned int yuv_line_size; + int rps; ///< row per strip + uint8_t entries[TIFF_MAX_ENTRY*12]; ///< entires in header + int num_entries; ///< number of entires + uint8_t **buf; ///< actual position in buffer + uint8_t *buf_start; ///< pointer to first byte in buffer + int buf_size; ///< buffer size + uint16_t subsampling[2]; ///< YUV subsampling factors + struct LZWEncodeState *lzws; ///< LZW Encode state + uint32_t dpi; ///< image resolution in DPI +} TiffEncoderContext; + + +/** + * Check free space in buffer. + * + * @param s Tiff context + * @param need Needed bytes + * @return 0 - ok, 1 - no free space + */ +static inline int check_size(TiffEncoderContext * s, uint64_t need) +{ + if (s->buf_size < *s->buf - s->buf_start + need) { + *s->buf = s->buf_start + s->buf_size + 1; + av_log(s->avctx, AV_LOG_ERROR, "Buffer is too small\n"); + return 1; + } + return 0; +} + +/** + * Put n values to buffer. + * + * @param p pointer to pointer to output buffer + * @param n number of values + * @param val pointer to values + * @param type type of values + * @param flip = 0 - normal copy, >0 - flip + */ +static void tnput(uint8_t ** p, int n, const uint8_t * val, enum TiffTypes type, + int flip) +{ + int i; +#if HAVE_BIGENDIAN + flip ^= ((int[]) {0, 0, 0, 1, 3, 3})[type]; +#endif + for (i = 0; i < n * type_sizes2[type]; i++) + *(*p)++ = val[i ^ flip]; +} + +/** + * Add entry to directory in tiff header. + * + * @param s Tiff context + * @param tag tag that identifies the entry + * @param type entry type + * @param count the number of values + * @param ptr_val pointer to values + */ +static void add_entry(TiffEncoderContext * s, + enum TiffTags tag, enum TiffTypes type, int count, + const void *ptr_val) +{ + uint8_t *entries_ptr = s->entries + 12 * s->num_entries; + + av_assert0(s->num_entries < TIFF_MAX_ENTRY); + + bytestream_put_le16(&entries_ptr, tag); + bytestream_put_le16(&entries_ptr, type); + bytestream_put_le32(&entries_ptr, count); + + if (type_sizes[type] * (int64_t)count <= 4) { + tnput(&entries_ptr, count, ptr_val, type, 0); + } else { + bytestream_put_le32(&entries_ptr, *s->buf - s->buf_start); + check_size(s, count * (int64_t)type_sizes2[type]); + tnput(s->buf, count, ptr_val, type, 0); + } + + s->num_entries++; +} + +static void add_entry1(TiffEncoderContext * s, + enum TiffTags tag, enum TiffTypes type, int val){ + uint16_t w = val; + uint32_t dw= val; + add_entry(s, tag, type, 1, type == TIFF_SHORT ? (void *)&w : (void *)&dw); +} + +/** + * Encode one strip in tiff file. + * + * @param s Tiff context + * @param src input buffer + * @param dst output buffer + * @param n size of input buffer + * @param compr compression method + * @return number of output bytes. If an output error is encountered, -1 is returned + */ +static int encode_strip(TiffEncoderContext * s, const int8_t * src, + uint8_t * dst, int n, int compr) +{ + + switch (compr) { +#if CONFIG_ZLIB + case TIFF_DEFLATE: + case TIFF_ADOBE_DEFLATE: + { + unsigned long zlen = s->buf_size - (*s->buf - s->buf_start); + if (compress(dst, &zlen, src, n) != Z_OK) { + av_log(s->avctx, AV_LOG_ERROR, "Compressing failed\n"); + return -1; + } + return zlen; + } +#endif + case TIFF_RAW: + if (check_size(s, n)) + return -1; + memcpy(dst, src, n); + return n; + case TIFF_PACKBITS: + return ff_rle_encode(dst, s->buf_size - (*s->buf - s->buf_start), src, 1, n, 2, 0xff, -1, 0); + case TIFF_LZW: + return ff_lzw_encode(s->lzws, src, n); + default: + return -1; + } +} + +static void pack_yuv(TiffEncoderContext * s, uint8_t * dst, int lnum) +{ + AVFrame *p = &s->picture; + int i, j, k; + int w = (s->width - 1) / s->subsampling[0] + 1; + uint8_t *pu = &p->data[1][lnum / s->subsampling[1] * p->linesize[1]]; + uint8_t *pv = &p->data[2][lnum / s->subsampling[1] * p->linesize[2]]; + if(s->width % s->subsampling[0] || s->height % s->subsampling[1]){ + for (i = 0; i < w; i++){ + for (j = 0; j < s->subsampling[1]; j++) + for (k = 0; k < s->subsampling[0]; k++) + *dst++ = p->data[0][FFMIN(lnum + j, s->height-1) * p->linesize[0] + + FFMIN(i * s->subsampling[0] + k, s->width-1)]; + *dst++ = *pu++; + *dst++ = *pv++; + } + }else{ + for (i = 0; i < w; i++){ + for (j = 0; j < s->subsampling[1]; j++) + for (k = 0; k < s->subsampling[0]; k++) + *dst++ = p->data[0][(lnum + j) * p->linesize[0] + + i * s->subsampling[0] + k]; + *dst++ = *pu++; + *dst++ = *pv++; + } + } +} + +static av_cold int encode_init(AVCodecContext *avctx) +{ + TiffEncoderContext *s = avctx->priv_data; + + avctx->coded_frame= &s->picture; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + avctx->coded_frame->key_frame = 1; + s->avctx = avctx; + + return 0; +} + +static int encode_frame(AVCodecContext * avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + TiffEncoderContext *s = avctx->priv_data; + AVFrame *const p = &s->picture; + int i; + uint8_t *ptr; + uint8_t *offset; + uint32_t strips; + int bytes_per_row; + uint32_t res[2] = { s->dpi, 1 }; // image resolution (72/1) + uint16_t bpp_tab[4]; + int ret = -1; + int is_yuv = 0, alpha = 0; + int shift_h, shift_v; + + *p = *pict; + + s->width = avctx->width; + s->height = avctx->height; + s->subsampling[0] = 1; + s->subsampling[1] = 1; + + avctx->bits_per_coded_sample = + s->bpp = av_get_bits_per_pixel(desc); + s->bpp_tab_size = desc->nb_components; + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGBA64LE: + case AV_PIX_FMT_RGBA: + alpha = 1; + case AV_PIX_FMT_RGB48LE: + case AV_PIX_FMT_RGB24: + s->photometric_interpretation = 2; + break; + case AV_PIX_FMT_GRAY8: + avctx->bits_per_coded_sample = 0x28; + case AV_PIX_FMT_GRAY8A: + alpha = avctx->pix_fmt == AV_PIX_FMT_GRAY8A; + case AV_PIX_FMT_GRAY16LE: + case AV_PIX_FMT_MONOBLACK: + s->photometric_interpretation = 1; + break; + case AV_PIX_FMT_PAL8: + s->photometric_interpretation = 3; + break; + case AV_PIX_FMT_MONOWHITE: + s->photometric_interpretation = 0; + break; + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV440P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV410P: + case AV_PIX_FMT_YUV411P: + s->photometric_interpretation = 6; + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &shift_h, &shift_v); + s->subsampling[0] = 1 << shift_h; + s->subsampling[1] = 1 << shift_v; + is_yuv = 1; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, + "This colors format is not supported\n"); + return -1; + } + + for (i = 0; i < s->bpp_tab_size; i++) + bpp_tab[i] = desc->comp[i].depth_minus1 + 1; + + if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE || s->compr == TIFF_LZW) + //best choose for DEFLATE + s->rps = s->height; + else + s->rps = FFMAX(8192 / (((s->width * s->bpp) >> 3) + 1), 1); // suggest size of strip + s->rps = ((s->rps - 1) / s->subsampling[1] + 1) * s->subsampling[1]; // round rps up + + strips = (s->height - 1) / s->rps + 1; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width * avctx->height * s->bpp * 2 + + avctx->height * 4 + FF_MIN_BUFFER_SIZE)) < 0) + return ret; + ptr = pkt->data; + s->buf_start = pkt->data; + s->buf = &ptr; + s->buf_size = pkt->size; + + if (check_size(s, 8)) + goto fail; + + // write header + bytestream_put_le16(&ptr, 0x4949); + bytestream_put_le16(&ptr, 42); + + offset = ptr; + bytestream_put_le32(&ptr, 0); + + av_fast_padded_mallocz(&s->strip_sizes, &s->strip_sizes_size, sizeof(s->strip_sizes[0]) * strips); + av_fast_padded_mallocz(&s->strip_offsets, &s->strip_offsets_size, sizeof(s->strip_offsets[0]) * strips); + + if (!s->strip_sizes || !s->strip_offsets) { + ret = AVERROR(ENOMEM); + goto fail; + } + + bytes_per_row = (((s->width - 1)/s->subsampling[0] + 1) * s->bpp + * s->subsampling[0] * s->subsampling[1] + 7) >> 3; + if (is_yuv){ + av_fast_padded_malloc(&s->yuv_line, &s->yuv_line_size, bytes_per_row); + if (s->yuv_line == NULL){ + av_log(s->avctx, AV_LOG_ERROR, "Not enough memory\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + } + +#if CONFIG_ZLIB + if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) { + uint8_t *zbuf; + int zlen, zn; + int j; + + zlen = bytes_per_row * s->rps; + zbuf = av_malloc(zlen); + if (!zbuf) { + ret = AVERROR(ENOMEM); + goto fail; + } + s->strip_offsets[0] = ptr - pkt->data; + zn = 0; + for (j = 0; j < s->rps; j++) { + if (is_yuv){ + pack_yuv(s, s->yuv_line, j); + memcpy(zbuf + zn, s->yuv_line, bytes_per_row); + j += s->subsampling[1] - 1; + } + else + memcpy(zbuf + j * bytes_per_row, + p->data[0] + j * p->linesize[0], bytes_per_row); + zn += bytes_per_row; + } + ret = encode_strip(s, zbuf, ptr, zn, s->compr); + av_free(zbuf); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n"); + goto fail; + } + ptr += ret; + s->strip_sizes[0] = ptr - pkt->data - s->strip_offsets[0]; + } else +#endif + { + if (s->compr == TIFF_LZW) { + s->lzws = av_malloc(ff_lzw_encode_state_size); + if (!s->lzws) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + for (i = 0; i < s->height; i++) { + if (s->strip_sizes[i / s->rps] == 0) { + if(s->compr == TIFF_LZW){ + ff_lzw_encode_init(s->lzws, ptr, s->buf_size - (*s->buf - s->buf_start), + 12, FF_LZW_TIFF, put_bits); + } + s->strip_offsets[i / s->rps] = ptr - pkt->data; + } + if (is_yuv){ + pack_yuv(s, s->yuv_line, i); + ret = encode_strip(s, s->yuv_line, ptr, bytes_per_row, s->compr); + i += s->subsampling[1] - 1; + } + else + ret = encode_strip(s, p->data[0] + i * p->linesize[0], + ptr, bytes_per_row, s->compr); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Encode strip failed\n"); + goto fail; + } + s->strip_sizes[i / s->rps] += ret; + ptr += ret; + if(s->compr == TIFF_LZW && (i==s->height-1 || i%s->rps == s->rps-1)){ + ret = ff_lzw_encode_flush(s->lzws, flush_put_bits); + s->strip_sizes[(i / s->rps )] += ret ; + ptr += ret; + } + } + if(s->compr == TIFF_LZW) + av_free(s->lzws); + } + + s->num_entries = 0; + + add_entry1(s,TIFF_SUBFILE, TIFF_LONG, 0); + add_entry1(s,TIFF_WIDTH, TIFF_LONG, s->width); + add_entry1(s,TIFF_HEIGHT, TIFF_LONG, s->height); + + if (s->bpp_tab_size) + add_entry(s, TIFF_BPP, TIFF_SHORT, s->bpp_tab_size, bpp_tab); + + add_entry1(s,TIFF_COMPR, TIFF_SHORT, s->compr); + add_entry1(s,TIFF_INVERT, TIFF_SHORT, s->photometric_interpretation); + add_entry(s, TIFF_STRIP_OFFS, TIFF_LONG, strips, s->strip_offsets); + + if (s->bpp_tab_size) + add_entry1(s,TIFF_SAMPLES_PER_PIXEL, TIFF_SHORT, s->bpp_tab_size); + + add_entry1(s,TIFF_ROWSPERSTRIP, TIFF_LONG, s->rps); + add_entry(s, TIFF_STRIP_SIZE, TIFF_LONG, strips, s->strip_sizes); + add_entry(s, TIFF_XRES, TIFF_RATIONAL, 1, res); + add_entry(s, TIFF_YRES, TIFF_RATIONAL, 1, res); + add_entry1(s,TIFF_RES_UNIT, TIFF_SHORT, 2); + + if(!(avctx->flags & CODEC_FLAG_BITEXACT)) + add_entry(s, TIFF_SOFTWARE_NAME, TIFF_STRING, + strlen(LIBAVCODEC_IDENT) + 1, LIBAVCODEC_IDENT); + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + uint16_t pal[256 * 3]; + for (i = 0; i < 256; i++) { + uint32_t rgb = *(uint32_t *) (p->data[1] + i * 4); + pal[i] = ((rgb >> 16) & 0xff) * 257; + pal[i + 256] = ((rgb >> 8 ) & 0xff) * 257; + pal[i + 512] = ( rgb & 0xff) * 257; + } + add_entry(s, TIFF_PAL, TIFF_SHORT, 256 * 3, pal); + } + if (alpha) + add_entry1(s,TIFF_EXTRASAMPLES, TIFF_SHORT, 2); + if (is_yuv){ + /** according to CCIR Recommendation 601.1 */ + uint32_t refbw[12] = {15, 1, 235, 1, 128, 1, 240, 1, 128, 1, 240, 1}; + add_entry(s, TIFF_YCBCR_SUBSAMPLING, TIFF_SHORT, 2, s->subsampling); + if (avctx->chroma_sample_location == AVCHROMA_LOC_TOPLEFT) + add_entry1(s, TIFF_YCBCR_POSITIONING, TIFF_SHORT, 2); + add_entry(s, TIFF_REFERENCE_BW, TIFF_RATIONAL, 6, refbw); + } + bytestream_put_le32(&offset, ptr - pkt->data); // write offset to dir + + if (check_size(s, 6 + s->num_entries * 12)) { + ret = AVERROR(EINVAL); + goto fail; + } + bytestream_put_le16(&ptr, s->num_entries); // write tag count + bytestream_put_buffer(&ptr, s->entries, s->num_entries * 12); + bytestream_put_le32(&ptr, 0); + + pkt->size = ptr - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + +fail: + return ret < 0 ? ret : 0; +} + +static av_cold int encode_close(AVCodecContext *avctx) +{ + TiffEncoderContext *s = avctx->priv_data; + + av_freep(&s->strip_sizes); + av_freep(&s->strip_offsets); + av_freep(&s->yuv_line); + + return 0; +} + +#define OFFSET(x) offsetof(TiffEncoderContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + {"dpi", "set the image resolution (in dpi)", OFFSET(dpi), AV_OPT_TYPE_INT, {.i64 = 72}, 1, 0x10000, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM}, + { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, {.i64 = TIFF_PACKBITS}, TIFF_RAW, TIFF_DEFLATE, VE, "compression_algo" }, + { "packbits", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_PACKBITS}, 0, 0, VE, "compression_algo" }, + { "raw", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_RAW}, 0, 0, VE, "compression_algo" }, + { "lzw", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_LZW}, 0, 0, VE, "compression_algo" }, +#if CONFIG_ZLIB + { "deflate", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_DEFLATE}, 0, 0, VE, "compression_algo" }, +#endif + { NULL }, +}; + +static const AVClass tiffenc_class = { + .class_name = "TIFF encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_tiff_encoder = { + .name = "tiff", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TIFF, + .priv_data_size = sizeof(TiffEncoderContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGB24, AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16LE, + AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_MONOWHITE, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_RGB48LE, + AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64LE, + AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .priv_class = &tiffenc_class, +}; diff --git a/ffmpeg/libavcodec/timecode.c b/ffmpeg/libavcodec/timecode.c new file mode 100644 index 0000000..f9862e5 --- /dev/null +++ b/ffmpeg/libavcodec/timecode.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2006 Smartjog S.A.S, Baptiste Coudurier + * Copyright (C) 2011 Smartjog S.A.S, Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * Timecode helpers + * This *private* API is deprecated, please use the one available in libavutil instead. + */ + +#include "version.h" + +#if FF_API_OLD_TIMECODE + +#include +#include "timecode.h" +#include "libavutil/log.h" + +int avpriv_framenum_to_drop_timecode(int frame_num) +{ + /* only works for NTSC 29.97 */ + int d = frame_num / 17982; + int m = frame_num % 17982; + //if (m < 2) m += 2; /* not needed since -2,-1 / 1798 in C returns 0 */ + return frame_num + 18 * d + 2 * ((m - 2) / 1798); +} + +uint32_t avpriv_framenum_to_smpte_timecode(unsigned frame, int fps, int drop) +{ + return (0 << 31) | // color frame flag + (drop << 30) | // drop frame flag + ( ((frame % fps) / 10) << 28) | // tens of frames + ( ((frame % fps) % 10) << 24) | // units of frames + (0 << 23) | // field phase (NTSC), b0 (PAL) + ((((frame / fps) % 60) / 10) << 20) | // tens of seconds + ((((frame / fps) % 60) % 10) << 16) | // units of seconds + (0 << 15) | // b0 (NTSC), b2 (PAL) + ((((frame / (fps * 60)) % 60) / 10) << 12) | // tens of minutes + ((((frame / (fps * 60)) % 60) % 10) << 8) | // units of minutes + (0 << 7) | // b1 + (0 << 6) | // b2 (NTSC), field phase (PAL) + ((((frame / (fps * 3600) % 24)) / 10) << 4) | // tens of hours + ( (frame / (fps * 3600) % 24)) % 10; // units of hours +} + +int avpriv_check_timecode_rate(void *avcl, AVRational rate, int drop) +{ + int fps; + + if (!rate.num || !rate.den) { + av_log(avcl, AV_LOG_ERROR, "Timecode frame rate must be specified\n"); + return -1; + } + fps = (rate.num + rate.den/2) / rate.den; + if (drop && fps != 30) { + av_log(avcl, AV_LOG_ERROR, "Drop frame is only allowed with 30000/1001 FPS\n"); + return -2; + } + switch (fps) { + case 24: + case 25: + case 30: return 0; + + default: + av_log(avcl, AV_LOG_ERROR, "Timecode frame rate not supported\n"); + return -3; + } +} + +char *avpriv_timecode_to_string(char *buf, const struct ff_timecode *tc, unsigned frame) +{ + int frame_num = tc->start + frame; + int fps = (tc->rate.num + tc->rate.den/2) / tc->rate.den; + int hh, mm, ss, ff, neg = 0; + + if (tc->drop) + frame_num = avpriv_framenum_to_drop_timecode(frame_num); + if (frame_num < 0) { + frame_num = -frame_num; + neg = 1; + } + ff = frame_num % fps; + ss = frame_num / fps % 60; + mm = frame_num / (fps*60) % 60; + hh = frame_num / (fps*3600); + snprintf(buf, 16, "%s%02d:%02d:%02d%c%02d", + neg ? "-" : "", + hh, mm, ss, tc->drop ? ';' : ':', ff); + return buf; +} + +int avpriv_init_smpte_timecode(void *avcl, struct ff_timecode *tc) +{ + int hh, mm, ss, ff, fps, ret; + char c; + + if (sscanf(tc->str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) { + av_log(avcl, AV_LOG_ERROR, "unable to parse timecode, " + "syntax: hh:mm:ss[:;.]ff\n"); + return -1; + } + + tc->drop = c != ':'; // drop if ';', '.', ... + + ret = avpriv_check_timecode_rate(avcl, tc->rate, tc->drop); + if (ret < 0) + return ret; + + fps = (tc->rate.num + tc->rate.den/2) / tc->rate.den; + tc->start = (hh*3600 + mm*60 + ss) * fps + ff; + + if (tc->drop) { /* adjust frame number */ + int tmins = 60*hh + mm; + tc->start -= 2 * (tmins - tmins/10); + } + return 0; +} + +int ff_framenum_to_drop_timecode(int frame_num) +{ + return avpriv_framenum_to_drop_timecode(frame_num); +} + +uint32_t ff_framenum_to_smtpe_timecode(unsigned frame, int fps, int drop) +{ + return avpriv_framenum_to_smpte_timecode(frame, fps, drop); +} + +int ff_init_smtpe_timecode(void *avcl, struct ff_timecode *tc) +{ + return avpriv_init_smpte_timecode(avcl, tc); +} +#endif diff --git a/ffmpeg/libavcodec/timecode.h b/ffmpeg/libavcodec/timecode.h new file mode 100644 index 0000000..8bc69e9 --- /dev/null +++ b/ffmpeg/libavcodec/timecode.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2006 Smartjog S.A.S, Baptiste Coudurier + * Copyright (C) 2011 Smartjog S.A.S, Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * Timecode helpers header + * This *private* API is deprecated, please use the one available in libavutil instead. + */ + +#ifndef AVCODEC_TIMECODE_H +#define AVCODEC_TIMECODE_H + +#include "version.h" + +#if FF_API_OLD_TIMECODE + +#include +#include "avcodec.h" +#include "libavutil/rational.h" + +#define TIMECODE_OPT(ctx, flags) \ + "timecode", "set timecode value following hh:mm:ss[:;.]ff format, " \ + "use ';' or '.' before frame number for drop frame", \ + offsetof(ctx, tc.str), \ + AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, flags + +struct ff_timecode { + char *str; ///< string following the hh:mm:ss[:;.]ff format + int start; ///< timecode frame start + int drop; ///< drop flag (1 if drop, else 0) + AVRational rate; ///< Frame rate in rational form +}; + +/** + * @brief Adjust frame number for NTSC drop frame time code + * @param frame_num Actual frame number to adjust + * @return Adjusted frame number + * @warning Adjustment is only valid in NTSC 29.97 + */ +int avpriv_framenum_to_drop_timecode(int frame_num); + +/** + * @brief Convert frame id (timecode) to SMPTE 12M binary representation + * @param frame Frame number + * @param fps Frame rate + * @param drop Drop flag + * @return The actual binary representation + */ +uint32_t avpriv_framenum_to_smpte_timecode(unsigned frame, int fps, int drop); + +/** + * @brief Load timecode string in buf + * @param buf Destination buffer + * @param tc Timecode struct pointer + * @param frame Frame id (timecode frame is computed with tc->start+frame) + * @return a pointer to the buf parameter + * @note timecode representation can be a negative timecode and have + * more than 24 hours. + * @note buf must have enough space to store the timecode representation: 16 + * bytes is the minimum required size. + */ +char *avpriv_timecode_to_string(char *buf, const struct ff_timecode *tc, unsigned frame); + +/** + * Check if timecode rate is valid and consistent with the drop flag. + * + * @return 0 on success, negative value on failure + */ +int avpriv_check_timecode_rate(void *avcl, AVRational rate, int drop); + +/** + * Parse SMTPE 12M time representation (hh:mm:ss[:;.]ff). str and rate fields + * from tc struct must be set. + * + * @param avcl A pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct (used for av_log). + * @param tc Timecode struct pointer + * @return 0 on success, negative value on failure + * @warning Adjustement is only valid in NTSC 29.97 + */ +int avpriv_init_smpte_timecode(void *avcl, struct ff_timecode *tc); + +attribute_deprecated int ff_framenum_to_drop_timecode(int frame_num); +attribute_deprecated uint32_t ff_framenum_to_smtpe_timecode(unsigned frame, int fps, int drop); +attribute_deprecated int ff_init_smtpe_timecode(void *avcl, struct ff_timecode *tc); +#endif + +#endif /* AVCODEC_TIMECODE_H */ diff --git a/ffmpeg/libavcodec/tmv.c b/ffmpeg/libavcodec/tmv.c new file mode 100644 index 0000000..279298c --- /dev/null +++ b/ffmpeg/libavcodec/tmv.c @@ -0,0 +1,97 @@ +/* + * 8088flex TMV video decoder + * Copyright (c) 2009 Daniel Verkamp + * + * 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 + */ + +/** + * @file + * 8088flex TMV video decoder + * @author Daniel Verkamp + * @see http://www.oldskool.org/pc/8088_Corruption + */ + +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/internal.h" +#include "libavutil/xga_font_data.h" + +#include "cga_data.h" + +static int tmv_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *src = avpkt->data; + uint8_t *dst; + unsigned char_cols = avctx->width >> 3; + unsigned char_rows = avctx->height >> 3; + unsigned x, y, fg, bg, c; + int ret; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (avpkt->size < 2*char_rows*char_cols) { + av_log(avctx, AV_LOG_ERROR, + "Input buffer too small, truncated sample?\n"); + *got_frame = 0; + return AVERROR_INVALIDDATA; + } + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + dst = frame->data[0]; + + frame->palette_has_changed = 1; + memcpy(frame->data[1], ff_cga_palette, 16 * 4); + memset(frame->data[1] + 16 * 4, 0, AVPALETTE_SIZE - 16 * 4); + + for (y = 0; y < char_rows; y++) { + for (x = 0; x < char_cols; x++) { + c = *src++; + bg = *src >> 4; + fg = *src++ & 0xF; + ff_draw_pc_font(dst + x * 8, frame->linesize[0], + avpriv_cga_font, 8, c, fg, bg); + } + dst += frame->linesize[0] * 8; + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int tmv_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_PAL8; + return 0; +} + +AVCodec ff_tmv_decoder = { + .name = "tmv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TMV, + .init = tmv_decode_init, + .decode = tmv_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("8088flex TMV"), +}; diff --git a/ffmpeg/libavcodec/truemotion1.c b/ffmpeg/libavcodec/truemotion1.c new file mode 100644 index 0000000..5a387ca --- /dev/null +++ b/ffmpeg/libavcodec/truemotion1.c @@ -0,0 +1,909 @@ +/* + * Duck TrueMotion 1.0 Decoder + * Copyright (C) 2003 Alex Beregszaszi & Mike Melanson + * + * 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 + */ + +/** + * @file + * Duck TrueMotion v1 Video Decoder by + * Alex Beregszaszi and + * Mike Melanson (melanson@pcisys.net) + * + * The TrueMotion v1 decoder presently only decodes 16-bit TM1 data and + * outputs RGB555 (or RGB565) data. 24-bit TM1 data is not supported yet. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" + +#include "truemotion1data.h" + +typedef struct TrueMotion1Context { + AVCodecContext *avctx; + AVFrame frame; + + const uint8_t *buf; + int size; + + const uint8_t *mb_change_bits; + int mb_change_bits_row_size; + const uint8_t *index_stream; + int index_stream_size; + + int flags; + int x, y, w, h; + + uint32_t y_predictor_table[1024]; + uint32_t c_predictor_table[1024]; + uint32_t fat_y_predictor_table[1024]; + uint32_t fat_c_predictor_table[1024]; + + int compression; + int block_type; + int block_width; + int block_height; + + int16_t ydt[8]; + int16_t cdt[8]; + int16_t fat_ydt[8]; + int16_t fat_cdt[8]; + + int last_deltaset, last_vectable; + + unsigned int *vert_pred; + int vert_pred_size; + +} TrueMotion1Context; + +#define FLAG_SPRITE 32 +#define FLAG_KEYFRAME 16 +#define FLAG_INTERFRAME 8 +#define FLAG_INTERPOLATED 4 + +struct frame_header { + uint8_t header_size; + uint8_t compression; + uint8_t deltaset; + uint8_t vectable; + uint16_t ysize; + uint16_t xsize; + uint16_t checksum; + uint8_t version; + uint8_t header_type; + uint8_t flags; + uint8_t control; + uint16_t xoffset; + uint16_t yoffset; + uint16_t width; + uint16_t height; +}; + +#define ALGO_NOP 0 +#define ALGO_RGB16V 1 +#define ALGO_RGB16H 2 +#define ALGO_RGB24H 3 + +/* these are the various block sizes that can occupy a 4x4 block */ +#define BLOCK_2x2 0 +#define BLOCK_2x4 1 +#define BLOCK_4x2 2 +#define BLOCK_4x4 3 + +typedef struct comp_types { + int algorithm; + int block_width; // vres + int block_height; // hres + int block_type; +} comp_types; + +/* { valid for metatype }, algorithm, num of deltas, vert res, horiz res */ +static const comp_types compression_types[17] = { + { ALGO_NOP, 0, 0, 0 }, + + { ALGO_RGB16V, 4, 4, BLOCK_4x4 }, + { ALGO_RGB16H, 4, 4, BLOCK_4x4 }, + { ALGO_RGB16V, 4, 2, BLOCK_4x2 }, + { ALGO_RGB16H, 4, 2, BLOCK_4x2 }, + + { ALGO_RGB16V, 2, 4, BLOCK_2x4 }, + { ALGO_RGB16H, 2, 4, BLOCK_2x4 }, + { ALGO_RGB16V, 2, 2, BLOCK_2x2 }, + { ALGO_RGB16H, 2, 2, BLOCK_2x2 }, + + { ALGO_NOP, 4, 4, BLOCK_4x4 }, + { ALGO_RGB24H, 4, 4, BLOCK_4x4 }, + { ALGO_NOP, 4, 2, BLOCK_4x2 }, + { ALGO_RGB24H, 4, 2, BLOCK_4x2 }, + + { ALGO_NOP, 2, 4, BLOCK_2x4 }, + { ALGO_RGB24H, 2, 4, BLOCK_2x4 }, + { ALGO_NOP, 2, 2, BLOCK_2x2 }, + { ALGO_RGB24H, 2, 2, BLOCK_2x2 } +}; + +static void select_delta_tables(TrueMotion1Context *s, int delta_table_index) +{ + int i; + + if (delta_table_index > 3) + return; + + memcpy(s->ydt, ydts[delta_table_index], 8 * sizeof(int16_t)); + memcpy(s->cdt, cdts[delta_table_index], 8 * sizeof(int16_t)); + memcpy(s->fat_ydt, fat_ydts[delta_table_index], 8 * sizeof(int16_t)); + memcpy(s->fat_cdt, fat_cdts[delta_table_index], 8 * sizeof(int16_t)); + + /* Y skinny deltas need to be halved for some reason; maybe the + * skinny Y deltas should be modified */ + for (i = 0; i < 8; i++) + { + /* drop the lsb before dividing by 2-- net effect: round down + * when dividing a negative number (e.g., -3/2 = -2, not -1) */ + s->ydt[i] &= 0xFFFE; + s->ydt[i] /= 2; + } +} + +#if HAVE_BIGENDIAN +static int make_ydt15_entry(int p2, int p1, int16_t *ydt) +#else +static int make_ydt15_entry(int p1, int p2, int16_t *ydt) +#endif +{ + int lo, hi; + + lo = ydt[p1]; + lo += (lo << 5) + (lo << 10); + hi = ydt[p2]; + hi += (hi << 5) + (hi << 10); + return (lo + (hi << 16)) << 1; +} + +static int make_cdt15_entry(int p1, int p2, int16_t *cdt) +{ + int r, b, lo; + + b = cdt[p2]; + r = cdt[p1] << 10; + lo = b + r; + return (lo + (lo << 16)) << 1; +} + +#if HAVE_BIGENDIAN +static int make_ydt16_entry(int p2, int p1, int16_t *ydt) +#else +static int make_ydt16_entry(int p1, int p2, int16_t *ydt) +#endif +{ + int lo, hi; + + lo = ydt[p1]; + lo += (lo << 6) + (lo << 11); + hi = ydt[p2]; + hi += (hi << 6) + (hi << 11); + return (lo + (hi << 16)) << 1; +} + +static int make_cdt16_entry(int p1, int p2, int16_t *cdt) +{ + int r, b, lo; + + b = cdt[p2]; + r = cdt[p1] << 11; + lo = b + r; + return (lo + (lo << 16)) << 1; +} + +static int make_ydt24_entry(int p1, int p2, int16_t *ydt) +{ + int lo, hi; + + lo = ydt[p1]; + hi = ydt[p2]; + return (lo + (hi << 8) + (hi << 16)) << 1; +} + +static int make_cdt24_entry(int p1, int p2, int16_t *cdt) +{ + int r, b; + + b = cdt[p2]; + r = cdt[p1]<<16; + return (b+r) << 1; +} + +static void gen_vector_table15(TrueMotion1Context *s, const uint8_t *sel_vector_table) +{ + int len, i, j; + unsigned char delta_pair; + + for (i = 0; i < 1024; i += 4) + { + len = *sel_vector_table++ / 2; + for (j = 0; j < len; j++) + { + delta_pair = *sel_vector_table++; + s->y_predictor_table[i+j] = 0xfffffffe & + make_ydt15_entry(delta_pair >> 4, delta_pair & 0xf, s->ydt); + s->c_predictor_table[i+j] = 0xfffffffe & + make_cdt15_entry(delta_pair >> 4, delta_pair & 0xf, s->cdt); + } + s->y_predictor_table[i+(j-1)] |= 1; + s->c_predictor_table[i+(j-1)] |= 1; + } +} + +static void gen_vector_table16(TrueMotion1Context *s, const uint8_t *sel_vector_table) +{ + int len, i, j; + unsigned char delta_pair; + + for (i = 0; i < 1024; i += 4) + { + len = *sel_vector_table++ / 2; + for (j = 0; j < len; j++) + { + delta_pair = *sel_vector_table++; + s->y_predictor_table[i+j] = 0xfffffffe & + make_ydt16_entry(delta_pair >> 4, delta_pair & 0xf, s->ydt); + s->c_predictor_table[i+j] = 0xfffffffe & + make_cdt16_entry(delta_pair >> 4, delta_pair & 0xf, s->cdt); + } + s->y_predictor_table[i+(j-1)] |= 1; + s->c_predictor_table[i+(j-1)] |= 1; + } +} + +static void gen_vector_table24(TrueMotion1Context *s, const uint8_t *sel_vector_table) +{ + int len, i, j; + unsigned char delta_pair; + + for (i = 0; i < 1024; i += 4) + { + len = *sel_vector_table++ / 2; + for (j = 0; j < len; j++) + { + delta_pair = *sel_vector_table++; + s->y_predictor_table[i+j] = 0xfffffffe & + make_ydt24_entry(delta_pair >> 4, delta_pair & 0xf, s->ydt); + s->c_predictor_table[i+j] = 0xfffffffe & + make_cdt24_entry(delta_pair >> 4, delta_pair & 0xf, s->cdt); + s->fat_y_predictor_table[i+j] = 0xfffffffe & + make_ydt24_entry(delta_pair >> 4, delta_pair & 0xf, s->fat_ydt); + s->fat_c_predictor_table[i+j] = 0xfffffffe & + make_cdt24_entry(delta_pair >> 4, delta_pair & 0xf, s->fat_cdt); + } + s->y_predictor_table[i+(j-1)] |= 1; + s->c_predictor_table[i+(j-1)] |= 1; + s->fat_y_predictor_table[i+(j-1)] |= 1; + s->fat_c_predictor_table[i+(j-1)] |= 1; + } +} + +/* Returns the number of bytes consumed from the bytestream. Returns -1 if + * there was an error while decoding the header */ +static int truemotion1_decode_header(TrueMotion1Context *s) +{ + int i, ret; + int width_shift = 0; + int new_pix_fmt; + struct frame_header header; + uint8_t header_buffer[128] = { 0 }; /* logical maximum size of the header */ + const uint8_t *sel_vector_table; + + header.header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f; + if (s->buf[0] < 0x10 || header.header_size >= s->size) + { + av_log(s->avctx, AV_LOG_ERROR, "invalid header size (%d)\n", s->buf[0]); + return AVERROR_INVALIDDATA; + } + + /* unscramble the header bytes with a XOR operation */ + for (i = 1; i < header.header_size; i++) + header_buffer[i - 1] = s->buf[i] ^ s->buf[i + 1]; + + header.compression = header_buffer[0]; + header.deltaset = header_buffer[1]; + header.vectable = header_buffer[2]; + header.ysize = AV_RL16(&header_buffer[3]); + header.xsize = AV_RL16(&header_buffer[5]); + header.checksum = AV_RL16(&header_buffer[7]); + header.version = header_buffer[9]; + header.header_type = header_buffer[10]; + header.flags = header_buffer[11]; + header.control = header_buffer[12]; + + /* Version 2 */ + if (header.version >= 2) + { + if (header.header_type > 3) + { + av_log(s->avctx, AV_LOG_ERROR, "invalid header type (%d)\n", header.header_type); + return AVERROR_INVALIDDATA; + } else if ((header.header_type == 2) || (header.header_type == 3)) { + s->flags = header.flags; + if (!(s->flags & FLAG_INTERFRAME)) + s->flags |= FLAG_KEYFRAME; + } else + s->flags = FLAG_KEYFRAME; + } else /* Version 1 */ + s->flags = FLAG_KEYFRAME; + + if (s->flags & FLAG_SPRITE) { + avpriv_request_sample(s->avctx, "Frame with sprite"); + /* FIXME header.width, height, xoffset and yoffset aren't initialized */ + return AVERROR_PATCHWELCOME; + } else { + s->w = header.xsize; + s->h = header.ysize; + if (header.header_type < 2) { + if ((s->w < 213) && (s->h >= 176)) + { + s->flags |= FLAG_INTERPOLATED; + avpriv_request_sample(s->avctx, "Interpolated frame"); + } + } + } + + if (header.compression >= 17) { + av_log(s->avctx, AV_LOG_ERROR, "invalid compression type (%d)\n", header.compression); + return AVERROR_INVALIDDATA; + } + + if ((header.deltaset != s->last_deltaset) || + (header.vectable != s->last_vectable)) + select_delta_tables(s, header.deltaset); + + if ((header.compression & 1) && header.header_type) + sel_vector_table = pc_tbl2; + else { + if (header.vectable > 0 && header.vectable < 4) + sel_vector_table = tables[header.vectable - 1]; + else { + av_log(s->avctx, AV_LOG_ERROR, "invalid vector table id (%d)\n", header.vectable); + return AVERROR_INVALIDDATA; + } + } + + if (compression_types[header.compression].algorithm == ALGO_RGB24H) { + new_pix_fmt = AV_PIX_FMT_RGB32; + width_shift = 1; + } else + new_pix_fmt = AV_PIX_FMT_RGB555; // RGB565 is supported as well + + s->w >>= width_shift; + if ((ret = av_image_check_size(s->w, s->h, 0, s->avctx)) < 0) + return ret; + + if (s->w != s->avctx->width || s->h != s->avctx->height || + new_pix_fmt != s->avctx->pix_fmt) { + av_frame_unref(&s->frame); + s->avctx->sample_aspect_ratio = (AVRational){ 1 << width_shift, 1 }; + s->avctx->pix_fmt = new_pix_fmt; + avcodec_set_dimensions(s->avctx, s->w, s->h); + av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); + } + + /* There is 1 change bit per 4 pixels, so each change byte represents + * 32 pixels; divide width by 4 to obtain the number of change bits and + * then round up to the nearest byte. */ + s->mb_change_bits_row_size = ((s->avctx->width >> (2 - width_shift)) + 7) >> 3; + + if ((header.deltaset != s->last_deltaset) || (header.vectable != s->last_vectable)) + { + if (compression_types[header.compression].algorithm == ALGO_RGB24H) + gen_vector_table24(s, sel_vector_table); + else + if (s->avctx->pix_fmt == AV_PIX_FMT_RGB555) + gen_vector_table15(s, sel_vector_table); + else + gen_vector_table16(s, sel_vector_table); + } + + /* set up pointers to the other key data chunks */ + s->mb_change_bits = s->buf + header.header_size; + if (s->flags & FLAG_KEYFRAME) { + /* no change bits specified for a keyframe; only index bytes */ + s->index_stream = s->mb_change_bits; + } else { + /* one change bit per 4x4 block */ + s->index_stream = s->mb_change_bits + + (s->mb_change_bits_row_size * (s->avctx->height >> 2)); + } + s->index_stream_size = s->size - (s->index_stream - s->buf); + + s->last_deltaset = header.deltaset; + s->last_vectable = header.vectable; + s->compression = header.compression; + s->block_width = compression_types[header.compression].block_width; + s->block_height = compression_types[header.compression].block_height; + s->block_type = compression_types[header.compression].block_type; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, "tables: %d / %d c:%d %dx%d t:%d %s%s%s%s\n", + s->last_deltaset, s->last_vectable, s->compression, s->block_width, + s->block_height, s->block_type, + s->flags & FLAG_KEYFRAME ? " KEY" : "", + s->flags & FLAG_INTERFRAME ? " INTER" : "", + s->flags & FLAG_SPRITE ? " SPRITE" : "", + s->flags & FLAG_INTERPOLATED ? " INTERPOL" : ""); + + return header.header_size; +} + +static av_cold int truemotion1_decode_init(AVCodecContext *avctx) +{ + TrueMotion1Context *s = avctx->priv_data; + + s->avctx = avctx; + + // FIXME: it may change ? +// if (avctx->bits_per_sample == 24) +// avctx->pix_fmt = AV_PIX_FMT_RGB24; +// else +// avctx->pix_fmt = AV_PIX_FMT_RGB555; + + avcodec_get_frame_defaults(&s->frame); + + /* there is a vertical predictor for each pixel in a line; each vertical + * predictor is 0 to start with */ + av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); + + return 0; +} + +/* +Block decoding order: + +dxi: Y-Y +dxic: Y-C-Y +dxic2: Y-C-Y-C + +hres,vres,i,i%vres (0 < i < 4) +2x2 0: 0 dxic2 +2x2 1: 1 dxi +2x2 2: 0 dxic2 +2x2 3: 1 dxi +2x4 0: 0 dxic2 +2x4 1: 1 dxi +2x4 2: 2 dxi +2x4 3: 3 dxi +4x2 0: 0 dxic +4x2 1: 1 dxi +4x2 2: 0 dxic +4x2 3: 1 dxi +4x4 0: 0 dxic +4x4 1: 1 dxi +4x4 2: 2 dxi +4x4 3: 3 dxi +*/ + +#define GET_NEXT_INDEX() \ +{\ + if (index_stream_index >= s->index_stream_size) { \ + av_log(s->avctx, AV_LOG_INFO, " help! truemotion1 decoder went out of bounds\n"); \ + return; \ + } \ + index = s->index_stream[index_stream_index++] * 4; \ +} + +#define APPLY_C_PREDICTOR() \ + if(index > 1023){\ + av_log(s->avctx, AV_LOG_ERROR, " index %d went out of bounds\n", index); \ + return; \ + }\ + predictor_pair = s->c_predictor_table[index]; \ + horiz_pred += (predictor_pair >> 1); \ + if (predictor_pair & 1) { \ + GET_NEXT_INDEX() \ + if (!index) { \ + GET_NEXT_INDEX() \ + predictor_pair = s->c_predictor_table[index]; \ + horiz_pred += ((predictor_pair >> 1) * 5); \ + if (predictor_pair & 1) \ + GET_NEXT_INDEX() \ + else \ + index++; \ + } \ + } else \ + index++; + +#define APPLY_C_PREDICTOR_24() \ + if(index > 1023){\ + av_log(s->avctx, AV_LOG_ERROR, " index %d went out of bounds\n", index); \ + return; \ + }\ + predictor_pair = s->c_predictor_table[index]; \ + horiz_pred += (predictor_pair >> 1); \ + if (predictor_pair & 1) { \ + GET_NEXT_INDEX() \ + if (!index) { \ + GET_NEXT_INDEX() \ + predictor_pair = s->fat_c_predictor_table[index]; \ + horiz_pred += (predictor_pair >> 1); \ + if (predictor_pair & 1) \ + GET_NEXT_INDEX() \ + else \ + index++; \ + } \ + } else \ + index++; + + +#define APPLY_Y_PREDICTOR() \ + if(index > 1023){\ + av_log(s->avctx, AV_LOG_ERROR, " index %d went out of bounds\n", index); \ + return; \ + }\ + predictor_pair = s->y_predictor_table[index]; \ + horiz_pred += (predictor_pair >> 1); \ + if (predictor_pair & 1) { \ + GET_NEXT_INDEX() \ + if (!index) { \ + GET_NEXT_INDEX() \ + predictor_pair = s->y_predictor_table[index]; \ + horiz_pred += ((predictor_pair >> 1) * 5); \ + if (predictor_pair & 1) \ + GET_NEXT_INDEX() \ + else \ + index++; \ + } \ + } else \ + index++; + +#define APPLY_Y_PREDICTOR_24() \ + if(index > 1023){\ + av_log(s->avctx, AV_LOG_ERROR, " index %d went out of bounds\n", index); \ + return; \ + }\ + predictor_pair = s->y_predictor_table[index]; \ + horiz_pred += (predictor_pair >> 1); \ + if (predictor_pair & 1) { \ + GET_NEXT_INDEX() \ + if (!index) { \ + GET_NEXT_INDEX() \ + predictor_pair = s->fat_y_predictor_table[index]; \ + horiz_pred += (predictor_pair >> 1); \ + if (predictor_pair & 1) \ + GET_NEXT_INDEX() \ + else \ + index++; \ + } \ + } else \ + index++; + +#define OUTPUT_PIXEL_PAIR() \ + *current_pixel_pair = *vert_pred + horiz_pred; \ + *vert_pred++ = *current_pixel_pair++; + +static void truemotion1_decode_16bit(TrueMotion1Context *s) +{ + int y; + int pixels_left; /* remaining pixels on this line */ + unsigned int predictor_pair; + unsigned int horiz_pred; + unsigned int *vert_pred; + unsigned int *current_pixel_pair; + unsigned char *current_line = s->frame.data[0]; + int keyframe = s->flags & FLAG_KEYFRAME; + + /* these variables are for managing the stream of macroblock change bits */ + const unsigned char *mb_change_bits = s->mb_change_bits; + unsigned char mb_change_byte; + unsigned char mb_change_byte_mask; + int mb_change_index; + + /* these variables are for managing the main index stream */ + int index_stream_index = 0; /* yes, the index into the index stream */ + int index; + + /* clean out the line buffer */ + memset(s->vert_pred, 0, s->avctx->width * sizeof(unsigned int)); + + GET_NEXT_INDEX(); + + for (y = 0; y < s->avctx->height; y++) { + + /* re-init variables for the next line iteration */ + horiz_pred = 0; + current_pixel_pair = (unsigned int *)current_line; + vert_pred = s->vert_pred; + mb_change_index = 0; + mb_change_byte = mb_change_bits[mb_change_index++]; + mb_change_byte_mask = 0x01; + pixels_left = s->avctx->width; + + while (pixels_left > 0) { + + if (keyframe || ((mb_change_byte & mb_change_byte_mask) == 0)) { + + switch (y & 3) { + case 0: + /* if macroblock width is 2, apply C-Y-C-Y; else + * apply C-Y-Y */ + if (s->block_width == 2) { + APPLY_C_PREDICTOR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + APPLY_C_PREDICTOR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + } else { + APPLY_C_PREDICTOR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + } + break; + + case 1: + case 3: + /* always apply 2 Y predictors on these iterations */ + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + break; + + case 2: + /* this iteration might be C-Y-C-Y, Y-Y, or C-Y-Y + * depending on the macroblock type */ + if (s->block_type == BLOCK_2x2) { + APPLY_C_PREDICTOR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + APPLY_C_PREDICTOR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + } else if (s->block_type == BLOCK_4x2) { + APPLY_C_PREDICTOR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + } else { + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR(); + OUTPUT_PIXEL_PAIR(); + } + break; + } + + } else { + + /* skip (copy) four pixels, but reassign the horizontal + * predictor */ + *vert_pred++ = *current_pixel_pair++; + horiz_pred = *current_pixel_pair - *vert_pred; + *vert_pred++ = *current_pixel_pair++; + + } + + if (!keyframe) { + mb_change_byte_mask <<= 1; + + /* next byte */ + if (!mb_change_byte_mask) { + mb_change_byte = mb_change_bits[mb_change_index++]; + mb_change_byte_mask = 0x01; + } + } + + pixels_left -= 4; + } + + /* next change row */ + if (((y + 1) & 3) == 0) + mb_change_bits += s->mb_change_bits_row_size; + + current_line += s->frame.linesize[0]; + } +} + +static void truemotion1_decode_24bit(TrueMotion1Context *s) +{ + int y; + int pixels_left; /* remaining pixels on this line */ + unsigned int predictor_pair; + unsigned int horiz_pred; + unsigned int *vert_pred; + unsigned int *current_pixel_pair; + unsigned char *current_line = s->frame.data[0]; + int keyframe = s->flags & FLAG_KEYFRAME; + + /* these variables are for managing the stream of macroblock change bits */ + const unsigned char *mb_change_bits = s->mb_change_bits; + unsigned char mb_change_byte; + unsigned char mb_change_byte_mask; + int mb_change_index; + + /* these variables are for managing the main index stream */ + int index_stream_index = 0; /* yes, the index into the index stream */ + int index; + + /* clean out the line buffer */ + memset(s->vert_pred, 0, s->avctx->width * sizeof(unsigned int)); + + GET_NEXT_INDEX(); + + for (y = 0; y < s->avctx->height; y++) { + + /* re-init variables for the next line iteration */ + horiz_pred = 0; + current_pixel_pair = (unsigned int *)current_line; + vert_pred = s->vert_pred; + mb_change_index = 0; + mb_change_byte = mb_change_bits[mb_change_index++]; + mb_change_byte_mask = 0x01; + pixels_left = s->avctx->width; + + while (pixels_left > 0) { + + if (keyframe || ((mb_change_byte & mb_change_byte_mask) == 0)) { + + switch (y & 3) { + case 0: + /* if macroblock width is 2, apply C-Y-C-Y; else + * apply C-Y-Y */ + if (s->block_width == 2) { + APPLY_C_PREDICTOR_24(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + APPLY_C_PREDICTOR_24(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + } else { + APPLY_C_PREDICTOR_24(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + } + break; + + case 1: + case 3: + /* always apply 2 Y predictors on these iterations */ + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + break; + + case 2: + /* this iteration might be C-Y-C-Y, Y-Y, or C-Y-Y + * depending on the macroblock type */ + if (s->block_type == BLOCK_2x2) { + APPLY_C_PREDICTOR_24(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + APPLY_C_PREDICTOR_24(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + } else if (s->block_type == BLOCK_4x2) { + APPLY_C_PREDICTOR_24(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + } else { + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + APPLY_Y_PREDICTOR_24(); + OUTPUT_PIXEL_PAIR(); + } + break; + } + + } else { + + /* skip (copy) four pixels, but reassign the horizontal + * predictor */ + *vert_pred++ = *current_pixel_pair++; + horiz_pred = *current_pixel_pair - *vert_pred; + *vert_pred++ = *current_pixel_pair++; + + } + + if (!keyframe) { + mb_change_byte_mask <<= 1; + + /* next byte */ + if (!mb_change_byte_mask) { + mb_change_byte = mb_change_bits[mb_change_index++]; + mb_change_byte_mask = 0x01; + } + } + + pixels_left -= 2; + } + + /* next change row */ + if (((y + 1) & 3) == 0) + mb_change_bits += s->mb_change_bits_row_size; + + current_line += s->frame.linesize[0]; + } +} + + +static int truemotion1_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int ret, buf_size = avpkt->size; + TrueMotion1Context *s = avctx->priv_data; + + s->buf = buf; + s->size = buf_size; + + if ((ret = truemotion1_decode_header(s)) < 0) + return ret; + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + if (compression_types[s->compression].algorithm == ALGO_RGB24H) { + truemotion1_decode_24bit(s); + } else if (compression_types[s->compression].algorithm != ALGO_NOP) { + truemotion1_decode_16bit(s); + } + + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int truemotion1_decode_end(AVCodecContext *avctx) +{ + TrueMotion1Context *s = avctx->priv_data; + + av_frame_unref(&s->frame); + av_free(s->vert_pred); + + return 0; +} + +AVCodec ff_truemotion1_decoder = { + .name = "truemotion1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TRUEMOTION1, + .priv_data_size = sizeof(TrueMotion1Context), + .init = truemotion1_decode_init, + .close = truemotion1_decode_end, + .decode = truemotion1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 1.0"), +}; diff --git a/ffmpeg/libavcodec/truemotion1data.h b/ffmpeg/libavcodec/truemotion1data.h new file mode 100644 index 0000000..3e58143 --- /dev/null +++ b/ffmpeg/libavcodec/truemotion1data.h @@ -0,0 +1,832 @@ +/* + * Duck Truemotion v1 Decoding Tables + * + * Data in this file was originally part of VpVision from On2 which is + * distributed under the GNU GPL. It is redistributed with libavcodec under + * the GNU LGPL using the common understanding that data tables necessary + * for decoding algorithms are not necessarily copyrightable. + * + * 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 + */ +#ifndef AVCODEC_TRUEMOTION1DATA_H +#define AVCODEC_TRUEMOTION1DATA_H + +#include +#include + +/* Y delta tables, skinny and fat */ +static const int16_t ydt1[8] = { 0, -2, 2, -6, 6, -12, 12, -12 }; +static const int16_t ydt2[8] = { 0, -2, 4, -6, 8, -12, 12, -12 }; +static const int16_t ydt3[8] = { 4, -6, 20, -20, 46, -46, 94, -94 }; +static const int16_t fat_ydt3[8] = { 0, -15, 50, -50, 115, -115, 235, -235 }; +static const int16_t ydt4[8] = { 0, -4, 4, -16, 16, -36, 36, -80 }; +/* NOTE: This table breaks the [+,-] pattern that the rest of the + * tables maintain. Is this intentional? */ +static const int16_t fat_ydt4[8] = { 0, 40, 80, -76, 160, -154, 236, -236 }; + +/* C delta tables, skinny and fat */ +static const int16_t cdt1[8] = { 0, -1, 1, -2, 3, -4, 5, -4 }; +static const int16_t cdt2[8] = { 0, -4, 3, -16, 20, -32, 36, -32 }; +static const int16_t fat_cdt2[8] = { 0, -20, 15, -80, 100, -160, 180, -160 }; +static const int16_t cdt3[8] = { 0, -2, 2, -8, 8, -18, 18, -40 }; + +/* all the delta tables to choose from, at all 4 delta levels */ +static const int16_t * const ydts[] = { ydt1, ydt2, ydt3, ydt4, NULL }; +static const int16_t * const fat_ydts[] = { fat_ydt3, fat_ydt3, fat_ydt3, fat_ydt4, NULL }; +static const int16_t * const cdts[] = { cdt1, cdt1, cdt2, cdt3, NULL }; +static const int16_t * const fat_cdts[] = { fat_cdt2, fat_cdt2, fat_cdt2, fat_ydt4, NULL }; + +static const uint8_t pc_tbl2[] = { +0x8,0x00,0x00,0x00,0x00, +0x8,0x00,0x00,0x00,0x00, +0x8,0x10,0x00,0x00,0x00, +0x8,0x01,0x00,0x00,0x00, +0x8,0x00,0x10,0x00,0x00, +0x8,0x00,0x01,0x00,0x00, +0x8,0x00,0x00,0x10,0x00, +0x8,0x00,0x00,0x01,0x00, +0x8,0x00,0x00,0x00,0x10, +0x8,0x00,0x00,0x00,0x01, +0x6,0x00,0x00,0x00, +0x6,0x10,0x00,0x00, +0x6,0x01,0x00,0x00, +0x6,0x00,0x10,0x00, +0x6,0x00,0x01,0x00, +0x6,0x00,0x00,0x01, +0x6,0x00,0x00,0x10, +0x6,0x00,0x00,0x02, +0x6,0x00,0x00,0x20, +0x6,0x20,0x10,0x00, +0x6,0x00,0x02,0x01, +0x6,0x00,0x20,0x10, +0x6,0x02,0x01,0x00, +0x6,0x11,0x00,0x00, +0x6,0x00,0x20,0x00, +0x6,0x00,0x02,0x00, +0x6,0x20,0x00,0x00, +0x6,0x01,0x10,0x00, +0x6,0x02,0x00,0x00, +0x6,0x01,0x00,0x02, +0x6,0x10,0x00,0x20, +0x6,0x00,0x01,0x02, +0x6,0x10,0x01,0x00, +0x6,0x00,0x10,0x20, +0x6,0x10,0x10,0x00, +0x6,0x10,0x00,0x01, +0x6,0x20,0x00,0x10, +0x6,0x02,0x00,0x01, +0x6,0x01,0x01,0x00, +0x6,0x01,0x00,0x10, +0x6,0x00,0x11,0x00, +0x6,0x10,0x00,0x02, +0x6,0x00,0x01,0x10, +0x6,0x00,0x00,0x11, +0x6,0x10,0x00,0x10, +0x6,0x01,0x00,0x01, +0x6,0x00,0x00,0x22, +0x6,0x02,0x01,0x01, +0x6,0x10,0x20,0x10, +0x6,0x01,0x02,0x01, +0x6,0x20,0x10,0x10, +0x6,0x01,0x00,0x20, +0x6,0x00,0x10,0x01, +0x6,0x21,0x10,0x00, +0x6,0x10,0x02,0x01, +0x6,0x12,0x01,0x00, +0x6,0x01,0x20,0x10, +0x6,0x01,0x02,0x00, +0x6,0x10,0x20,0x00, +0x6,0x00,0x10,0x02, +0x6,0x00,0x01,0x20, +0x6,0x00,0x02,0x21, +0x6,0x00,0x02,0x20, +0x6,0x00,0x00,0x12, +0x6,0x00,0x00,0x21, +0x6,0x20,0x11,0x00, +0x6,0x00,0x01,0x01, +0x6,0x11,0x10,0x00, +0x6,0x00,0x20,0x12, +0x6,0x00,0x20,0x11, +0x6,0x20,0x10,0x02, +0x6,0x02,0x01,0x20, +0x6,0x00,0x22,0x11, +0x6,0x00,0x10,0x10, +0x6,0x02,0x11,0x00, +0x6,0x00,0x21,0x10, +0x6,0x00,0x02,0x03, +0x6,0x20,0x10,0x01, +0x6,0x00,0x12,0x01, +0x4,0x11,0x00, +0x4,0x00,0x22, +0x4,0x20,0x00, +0x4,0x01,0x10, +0x4,0x02,0x20, +0x4,0x00,0x20, +0x4,0x02,0x00, +0x4,0x10,0x01, +0x4,0x00,0x11, +0x4,0x02,0x01, +0x4,0x02,0x21, +0x4,0x00,0x02, +0x4,0x20,0x02, +0x4,0x01,0x01, +0x4,0x10,0x10, +0x4,0x10,0x02, +0x4,0x22,0x00, +0x4,0x10,0x00, +0x4,0x01,0x00, +0x4,0x21,0x00, +0x4,0x12,0x00, +0x4,0x00,0x10, +0x4,0x20,0x12, +0x4,0x01,0x11, +0x4,0x00,0x01, +0x4,0x01,0x02, +0x4,0x11,0x02, +0x4,0x11,0x01, +0x4,0x10,0x20, +0x4,0x20,0x01, +0x4,0x22,0x11, +0x4,0x00,0x12, +0x4,0x20,0x10, +0x4,0x22,0x01, +0x4,0x01,0x20, +0x4,0x00,0x21, +0x4,0x10,0x11, +0x4,0x21,0x10, +0x4,0x10,0x22, +0x4,0x02,0x03, +0x4,0x12,0x01, +0x4,0x20,0x11, +0x4,0x11,0x10, +0x4,0x20,0x30, +0x4,0x11,0x20, +0x4,0x02,0x10, +0x4,0x22,0x10, +0x4,0x11,0x11, +0x4,0x30,0x20, +0x4,0x30,0x00, +0x4,0x01,0x22, +0x4,0x01,0x12, +0x4,0x02,0x11, +0x4,0x03,0x02, +0x4,0x03,0x00, +0x4,0x10,0x21, +0x4,0x12,0x20, +0x4,0x00,0x00, +0x4,0x12,0x21, +0x4,0x21,0x11, +0x4,0x02,0x22, +0x4,0x10,0x12, +0x4,0x31,0x00, +0x4,0x20,0x20, +0x4,0x00,0x03, +0x4,0x02,0x02, +0x4,0x22,0x20, +0x4,0x01,0x21, +0x4,0x21,0x02, +0x4,0x21,0x12, +0x4,0x11,0x22, +0x4,0x00,0x30, +0x4,0x12,0x11, +0x4,0x20,0x22, +0x4,0x31,0x20, +0x4,0x21,0x30, +0x4,0x22,0x02, +0x4,0x22,0x22, +0x4,0x20,0x31, +0x4,0x13,0x02, +0x4,0x03,0x10, +0x4,0x11,0x12, +0x4,0x00,0x13, +0x4,0x21,0x01, +0x4,0x12,0x03, +0x4,0x13,0x00, +0x4,0x13,0x10, +0x4,0x02,0x13, +0x4,0x30,0x01, +0x4,0x12,0x10, +0x4,0x22,0x13, +0x4,0x03,0x12, +0x4,0x31,0x01, +0x4,0x30,0x22, +0x4,0x00,0x31, +0x4,0x01,0x31, +0x4,0x02,0x23, +0x4,0x01,0x30, +0x4,0x11,0x21, +0x4,0x22,0x21, +0x4,0x01,0x13, +0x4,0x10,0x03, +0x4,0x22,0x03, +0x4,0x30,0x21, +0x4,0x21,0x31, +0x4,0x33,0x00, +0x4,0x13,0x12, +0x4,0x11,0x31, +0x4,0x30,0x02, +0x4,0x12,0x02, +0x4,0x11,0x13, +0x4,0x12,0x22, +0x4,0x20,0x32, +0x4,0x10,0x13, +0x4,0x22,0x31, +0x4,0x21,0x20, +0x4,0x01,0x33, +0x4,0x33,0x10, +0x4,0x20,0x13, +0x4,0x31,0x22, +0x4,0x13,0x30, +0x4,0x01,0x03, +0x4,0x11,0x33, +0x4,0x20,0x21, +0x4,0x13,0x31, +0x4,0x03,0x22, +0x4,0x31,0x02, +0x4,0x00,0x24, +0x2,0x00, +0x2,0x10, +0x2,0x20, +0x2,0x30, +0x2,0x40, +0x2,0x50, +0x2,0x60, +0x2,0x01, +0x2,0x11, +0x2,0x21, +0x2,0x31, +0x2,0x41, +0x2,0x51, +0x2,0x61, +0x2,0x02, +0x2,0x12, +0x2,0x22, +0x2,0x32, +0x2,0x42, +0x2,0x52, +0x2,0x62, +0x2,0x03, +0x2,0x13, +0x2,0x23, +0x2,0x33, +0x2,0x43, +0x2,0x53, +0x2,0x63, +0x2,0x04, +0x2,0x14, +0x2,0x24, +0x2,0x34, +0x2,0x44, +0x2,0x54, +0x2,0x64, +0x2,0x05, +0x2,0x15, +0x2,0x25, +0x2,0x35, +0x2,0x45, +0x2,0x55, +0x2,0x65, +0x2,0x06, +0x2,0x16, +0x2,0x26, +0x2,0x36, +0x2,0x46, +0x2,0x56, +0x2,0x66 +}; + +static const uint8_t pc_tbl3[] = { +0x6,0x00,0x00,0x00, +0x6,0x00,0x00,0x00, +0x6,0x00,0x00,0x01, +0x6,0x00,0x00,0x10, +0x6,0x00,0x00,0x11, +0x6,0x00,0x01,0x00, +0x6,0x00,0x01,0x01, +0x6,0x00,0x01,0x10, +0x6,0x00,0x01,0x11, +0x6,0x00,0x10,0x00, +0x6,0x00,0x10,0x01, +0x6,0x00,0x10,0x10, +0x6,0x00,0x10,0x11, +0x6,0x00,0x11,0x00, +0x6,0x00,0x11,0x01, +0x6,0x00,0x11,0x10, +0x6,0x00,0x11,0x11, +0x6,0x01,0x00,0x00, +0x6,0x01,0x00,0x01, +0x6,0x01,0x00,0x10, +0x6,0x01,0x00,0x11, +0x6,0x01,0x01,0x00, +0x6,0x01,0x01,0x01, +0x6,0x01,0x01,0x10, +0x6,0x01,0x01,0x11, +0x6,0x01,0x10,0x00, +0x6,0x01,0x10,0x01, +0x6,0x01,0x10,0x10, +0x6,0x01,0x10,0x11, +0x6,0x01,0x11,0x00, +0x6,0x01,0x11,0x01, +0x6,0x01,0x11,0x10, +0x6,0x01,0x11,0x11, +0x6,0x10,0x00,0x00, +0x6,0x10,0x00,0x01, +0x6,0x10,0x00,0x10, +0x6,0x10,0x00,0x11, +0x6,0x10,0x01,0x00, +0x6,0x10,0x01,0x01, +0x6,0x10,0x01,0x10, +0x6,0x10,0x01,0x11, +0x6,0x10,0x10,0x00, +0x6,0x10,0x10,0x01, +0x6,0x10,0x10,0x10, +0x6,0x10,0x10,0x11, +0x6,0x10,0x11,0x00, +0x6,0x10,0x11,0x01, +0x6,0x10,0x11,0x10, +0x6,0x10,0x11,0x11, +0x6,0x11,0x00,0x00, +0x6,0x11,0x00,0x01, +0x6,0x11,0x00,0x10, +0x6,0x11,0x00,0x11, +0x6,0x11,0x01,0x00, +0x6,0x11,0x01,0x01, +0x6,0x11,0x01,0x10, +0x6,0x11,0x01,0x11, +0x6,0x11,0x10,0x00, +0x6,0x11,0x10,0x01, +0x6,0x11,0x10,0x10, +0x6,0x11,0x10,0x11, +0x6,0x11,0x11,0x00, +0x6,0x11,0x11,0x01, +0x6,0x11,0x11,0x10, +0x4,0x00,0x00, +0x4,0x00,0x01, +0x4,0x00,0x02, +0x4,0x00,0x03, +0x4,0x00,0x10, +0x4,0x00,0x11, +0x4,0x00,0x12, +0x4,0x00,0x13, +0x4,0x00,0x20, +0x4,0x00,0x21, +0x4,0x00,0x22, +0x4,0x00,0x23, +0x4,0x00,0x30, +0x4,0x00,0x31, +0x4,0x00,0x32, +0x4,0x00,0x33, +0x4,0x01,0x00, +0x4,0x01,0x01, +0x4,0x01,0x02, +0x4,0x01,0x03, +0x4,0x01,0x10, +0x4,0x01,0x11, +0x4,0x01,0x12, +0x4,0x01,0x13, +0x4,0x01,0x20, +0x4,0x01,0x21, +0x4,0x01,0x22, +0x4,0x01,0x23, +0x4,0x01,0x30, +0x4,0x01,0x31, +0x4,0x01,0x32, +0x4,0x01,0x33, +0x4,0x02,0x00, +0x4,0x02,0x01, +0x4,0x02,0x02, +0x4,0x02,0x03, +0x4,0x02,0x10, +0x4,0x02,0x11, +0x4,0x02,0x12, +0x4,0x02,0x13, +0x4,0x02,0x20, +0x4,0x02,0x21, +0x4,0x02,0x22, +0x4,0x02,0x23, +0x4,0x02,0x30, +0x4,0x02,0x31, +0x4,0x02,0x32, +0x4,0x02,0x33, +0x4,0x03,0x00, +0x4,0x03,0x01, +0x4,0x03,0x02, +0x4,0x03,0x03, +0x4,0x03,0x10, +0x4,0x03,0x11, +0x4,0x03,0x12, +0x4,0x03,0x13, +0x4,0x03,0x20, +0x4,0x03,0x21, +0x4,0x03,0x22, +0x4,0x03,0x23, +0x4,0x03,0x30, +0x4,0x03,0x31, +0x4,0x03,0x32, +0x4,0x03,0x33, +0x4,0x10,0x00, +0x4,0x10,0x01, +0x4,0x10,0x02, +0x4,0x10,0x03, +0x4,0x10,0x10, +0x4,0x10,0x11, +0x4,0x10,0x12, +0x4,0x10,0x13, +0x4,0x10,0x20, +0x4,0x10,0x21, +0x4,0x10,0x22, +0x4,0x10,0x23, +0x4,0x10,0x30, +0x4,0x10,0x31, +0x4,0x10,0x32, +0x4,0x10,0x33, +0x4,0x11,0x00, +0x4,0x11,0x01, +0x4,0x11,0x02, +0x4,0x11,0x03, +0x4,0x11,0x10, +0x4,0x11,0x11, +0x4,0x11,0x12, +0x4,0x11,0x13, +0x4,0x11,0x20, +0x4,0x11,0x21, +0x4,0x11,0x22, +0x4,0x11,0x23, +0x4,0x11,0x30, +0x4,0x11,0x31, +0x4,0x11,0x32, +0x4,0x11,0x33, +0x4,0x12,0x00, +0x4,0x12,0x01, +0x4,0x12,0x02, +0x4,0x12,0x03, +0x4,0x12,0x10, +0x4,0x12,0x11, +0x4,0x12,0x12, +0x4,0x12,0x13, +0x4,0x12,0x20, +0x4,0x12,0x21, +0x4,0x12,0x22, +0x4,0x12,0x23, +0x4,0x12,0x30, +0x4,0x12,0x31, +0x4,0x12,0x32, +0x4,0x12,0x33, +0x4,0x13,0x00, +0x4,0x13,0x01, +0x4,0x13,0x02, +0x4,0x13,0x03, +0x4,0x13,0x10, +0x4,0x13,0x11, +0x4,0x13,0x12, +0x4,0x13,0x13, +0x4,0x13,0x20, +0x4,0x13,0x21, +0x4,0x13,0x22, +0x4,0x13,0x23, +0x4,0x13,0x30, +0x4,0x13,0x31, +0x4,0x13,0x32, +0x4,0x13,0x33, +0x2,0x00, +0x2,0x10, +0x2,0x20, +0x2,0x30, +0x2,0x40, +0x2,0x50, +0x2,0x60, +0x2,0x70, +0x2,0x01, +0x2,0x11, +0x2,0x21, +0x2,0x31, +0x2,0x41, +0x2,0x51, +0x2,0x61, +0x2,0x71, +0x2,0x02, +0x2,0x12, +0x2,0x22, +0x2,0x32, +0x2,0x42, +0x2,0x52, +0x2,0x62, +0x2,0x72, +0x2,0x03, +0x2,0x13, +0x2,0x23, +0x2,0x33, +0x2,0x43, +0x2,0x53, +0x2,0x63, +0x2,0x73, +0x2,0x04, +0x2,0x14, +0x2,0x24, +0x2,0x34, +0x2,0x44, +0x2,0x54, +0x2,0x64, +0x2,0x74, +0x2,0x05, +0x2,0x15, +0x2,0x25, +0x2,0x35, +0x2,0x45, +0x2,0x55, +0x2,0x65, +0x2,0x75, +0x2,0x06, +0x2,0x16, +0x2,0x26, +0x2,0x36, +0x2,0x46, +0x2,0x56, +0x2,0x66, +0x2,0x76, +0x2,0x07, +0x2,0x17, +0x2,0x27, +0x2,0x37, +0x2,0x47, +0x2,0x57, +0x2,0x67, +0x2,0x77 +}; + +static const uint8_t pc_tbl4[] = { +0x8,0x00,0x00,0x00,0x00, +0x8,0x00,0x00,0x00,0x00, +0x8,0x20,0x00,0x00,0x00, +0x8,0x00,0x00,0x00,0x01, +0x8,0x10,0x00,0x00,0x00, +0x8,0x00,0x00,0x00,0x02, +0x8,0x01,0x00,0x00,0x00, +0x8,0x00,0x00,0x00,0x10, +0x8,0x02,0x00,0x00,0x00, +0x6,0x00,0x00,0x00, +0x6,0x20,0x00,0x00, +0x6,0x00,0x00,0x01, +0x6,0x10,0x00,0x00, +0x6,0x00,0x00,0x02, +0x6,0x00,0x10,0x00, +0x6,0x00,0x20,0x00, +0x6,0x00,0x02,0x00, +0x6,0x00,0x01,0x00, +0x6,0x01,0x00,0x00, +0x6,0x00,0x00,0x20, +0x6,0x02,0x00,0x00, +0x6,0x00,0x00,0x10, +0x6,0x10,0x00,0x20, +0x6,0x01,0x00,0x02, +0x6,0x20,0x00,0x10, +0x6,0x02,0x00,0x01, +0x6,0x20,0x10,0x00, +0x6,0x00,0x12,0x00, +0x6,0x00,0x02,0x01, +0x6,0x02,0x01,0x00, +0x6,0x00,0x21,0x00, +0x6,0x00,0x01,0x02, +0x6,0x00,0x20,0x10, +0x6,0x00,0x00,0x21, +0x6,0x00,0x00,0x12, +0x6,0x00,0x01,0x20, +0x6,0x12,0x00,0x00, +0x6,0x00,0x10,0x20, +0x6,0x01,0x20,0x00, +0x6,0x02,0x10,0x00, +0x6,0x10,0x20,0x00, +0x6,0x01,0x02,0x00, +0x6,0x21,0x00,0x00, +0x6,0x00,0x02,0x10, +0x6,0x20,0x01,0x00, +0x6,0x00,0x22,0x00, +0x6,0x10,0x02,0x00, +0x6,0x00,0x10,0x02, +0x6,0x11,0x00,0x00, +0x6,0x00,0x11,0x00, +0x6,0x22,0x00,0x00, +0x6,0x20,0x00,0x02, +0x6,0x10,0x00,0x01, +0x6,0x00,0x20,0x01, +0x6,0x02,0x20,0x00, +0x6,0x01,0x10,0x00, +0x6,0x01,0x00,0x20, +0x6,0x00,0x20,0x02, +0x6,0x01,0x20,0x02, +0x6,0x10,0x01,0x00, +0x6,0x02,0x00,0x10, +0x6,0x00,0x10,0x01, +0x6,0x10,0x01,0x20, +0x6,0x20,0x02,0x10, +0x6,0x00,0x00,0x22, +0x6,0x10,0x00,0x02, +0x6,0x00,0x02,0x20, +0x6,0x20,0x02,0x00, +0x6,0x00,0x00,0x11, +0x6,0x02,0x10,0x01, +0x6,0x00,0x01,0x10, +0x6,0x00,0x02,0x11, +0x4,0x01,0x02, +0x4,0x02,0x01, +0x4,0x01,0x00, +0x4,0x10,0x20, +0x4,0x20,0x10, +0x4,0x20,0x00, +0x4,0x11,0x00, +0x4,0x02,0x00, +0x4,0x12,0x00, +0x4,0x00,0x21, +0x4,0x22,0x00, +0x4,0x00,0x12, +0x4,0x21,0x00, +0x4,0x02,0x11, +0x4,0x00,0x01, +0x4,0x10,0x02, +0x4,0x02,0x20, +0x4,0x20,0x11, +0x4,0x01,0x10, +0x4,0x21,0x10, +0x4,0x10,0x00, +0x4,0x10,0x22, +0x4,0x20,0x20, +0x4,0x00,0x22, +0x4,0x01,0x22, +0x4,0x20,0x01, +0x4,0x02,0x02, +0x4,0x00,0x20, +0x4,0x00,0x10, +0x4,0x00,0x11, +0x4,0x22,0x01, +0x4,0x11,0x20, +0x4,0x12,0x01, +0x4,0x12,0x20, +0x4,0x11,0x02, +0x4,0x10,0x10, +0x4,0x01,0x01, +0x4,0x02,0x21, +0x4,0x20,0x12, +0x4,0x01,0x12, +0x4,0x22,0x11, +0x4,0x21,0x12, +0x4,0x22,0x10, +0x4,0x21,0x02, +0x4,0x20,0x02, +0x4,0x10,0x01, +0x4,0x00,0x02, +0x4,0x10,0x21, +0x4,0x01,0x20, +0x4,0x11,0x22, +0x4,0x12,0x21, +0x4,0x22,0x20, +0x4,0x02,0x10, +0x4,0x02,0x22, +0x4,0x11,0x10, +0x4,0x22,0x02, +0x4,0x20,0x21, +0x4,0x01,0x11, +0x4,0x11,0x01, +0x4,0x10,0x12, +0x4,0x02,0x12, +0x4,0x20,0x22, +0x4,0x21,0x20, +0x4,0x01,0x21, +0x4,0x12,0x02, +0x4,0x21,0x11, +0x4,0x12,0x22, +0x4,0x12,0x10, +0x4,0x22,0x21, +0x4,0x10,0x11, +0x4,0x21,0x01, +0x4,0x11,0x12, +0x4,0x12,0x11, +0x4,0x66,0x66, +0x4,0x22,0x22, +0x4,0x11,0x21, +0x4,0x11,0x11, +0x4,0x21,0x22, +0x4,0x00,0x00, +0x4,0x22,0x12, +0x4,0x12,0x12, +0x4,0x21,0x21, +0x4,0x42,0x00, +0x4,0x00,0x04, +0x4,0x40,0x00, +0x4,0x30,0x00, +0x4,0x31,0x00, +0x4,0x00,0x03, +0x4,0x00,0x14, +0x4,0x00,0x13, +0x4,0x01,0x24, +0x4,0x20,0x13, +0x4,0x01,0x42, +0x4,0x14,0x20, +0x4,0x42,0x02, +0x4,0x13,0x00, +0x4,0x00,0x24, +0x4,0x31,0x20, +0x4,0x22,0x13, +0x4,0x11,0x24, +0x4,0x12,0x66, +0x4,0x30,0x01, +0x4,0x02,0x13, +0x4,0x12,0x42, +0x4,0x40,0x10, +0x4,0x40,0x02, +0x4,0x01,0x04, +0x4,0x24,0x00, +0x4,0x42,0x10, +0x4,0x21,0x13, +0x4,0x13,0x12, +0x4,0x31,0x21, +0x4,0x21,0x24, +0x4,0x00,0x40, +0x4,0x10,0x24, +0x4,0x10,0x42, +0x4,0x32,0x01, +0x4,0x11,0x42, +0x4,0x20,0x31, +0x4,0x12,0x40, +0x2,0x00, +0x2,0x10, +0x2,0x20, +0x2,0x30, +0x2,0x40, +0x2,0x50, +0x2,0x60, +0x2,0x70, +0x2,0x01, +0x2,0x11, +0x2,0x21, +0x2,0x31, +0x2,0x41, +0x2,0x51, +0x2,0x61, +0x2,0x71, +0x2,0x02, +0x2,0x12, +0x2,0x22, +0x2,0x32, +0x2,0x42, +0x2,0x52, +0x2,0x62, +0x2,0x72, +0x2,0x03, +0x2,0x13, +0x2,0x23, +0x2,0x33, +0x2,0x43, +0x2,0x53, +0x2,0x63, +0x2,0x73, +0x2,0x04, +0x2,0x14, +0x2,0x24, +0x2,0x34, +0x2,0x44, +0x2,0x54, +0x2,0x64, +0x2,0x74, +0x2,0x05, +0x2,0x15, +0x2,0x25, +0x2,0x35, +0x2,0x45, +0x2,0x55, +0x2,0x65, +0x2,0x75, +0x2,0x06, +0x2,0x16, +0x2,0x26, +0x2,0x36, +0x2,0x46, +0x2,0x56, +0x2,0x66, +0x2,0x76, +0x2,0x07, +0x2,0x17, +0x2,0x27, +0x2,0x37, +0x2,0x47, +0x2,0x57, +0x2,0x67, +0x2,0x77 +}; + +static const uint8_t * const tables[] = { pc_tbl2, pc_tbl3, pc_tbl4 }; + +#endif /* AVCODEC_TRUEMOTION1DATA_H */ diff --git a/ffmpeg/libavcodec/truemotion2.c b/ffmpeg/libavcodec/truemotion2.c new file mode 100644 index 0000000..7783386 --- /dev/null +++ b/ffmpeg/libavcodec/truemotion2.c @@ -0,0 +1,1004 @@ +/* + * Duck/ON2 TrueMotion 2 Decoder + * Copyright (c) 2005 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Duck TrueMotion2 decoder. + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "dsputil.h" +#include "internal.h" + +#define TM2_ESCAPE 0x80000000 +#define TM2_DELTAS 64 + +/* Huffman-coded streams of different types of blocks */ +enum TM2_STREAMS { + TM2_C_HI = 0, + TM2_C_LO, + TM2_L_HI, + TM2_L_LO, + TM2_UPD, + TM2_MOT, + TM2_TYPE, + TM2_NUM_STREAMS +}; + +/* Block types */ +enum TM2_BLOCKS { + TM2_HI_RES = 0, + TM2_MED_RES, + TM2_LOW_RES, + TM2_NULL_RES, + TM2_UPDATE, + TM2_STILL, + TM2_MOTION +}; + +typedef struct TM2Context { + AVCodecContext *avctx; + AVFrame pic; + + GetBitContext gb; + DSPContext dsp; + + uint8_t *buffer; + int buffer_size; + + /* TM2 streams */ + int *tokens[TM2_NUM_STREAMS]; + int tok_lens[TM2_NUM_STREAMS]; + int tok_ptrs[TM2_NUM_STREAMS]; + int deltas[TM2_NUM_STREAMS][TM2_DELTAS]; + /* for blocks decoding */ + int D[4]; + int CD[4]; + int *last; + int *clast; + + /* data for current and previous frame */ + int *Y1_base, *U1_base, *V1_base, *Y2_base, *U2_base, *V2_base; + int *Y1, *U1, *V1, *Y2, *U2, *V2; + int y_stride, uv_stride; + int cur; +} TM2Context; + +/** +* Huffman codes for each of streams +*/ +typedef struct TM2Codes { + VLC vlc; ///< table for FFmpeg bitstream reader + int bits; + int *recode; ///< table for converting from code indexes to values + int length; +} TM2Codes; + +/** +* structure for gathering Huffman codes information +*/ +typedef struct TM2Huff { + int val_bits; ///< length of literal + int max_bits; ///< maximum length of code + int min_bits; ///< minimum length of code + int nodes; ///< total number of nodes in tree + int num; ///< current number filled + int max_num; ///< total number of codes + int *nums; ///< literals + uint32_t *bits; ///< codes + int *lens; ///< codelengths +} TM2Huff; + +static int tm2_read_tree(TM2Context *ctx, uint32_t prefix, int length, TM2Huff *huff) +{ + int ret; + if (length > huff->max_bits) { + av_log(ctx->avctx, AV_LOG_ERROR, "Tree exceeded its given depth (%i)\n", + huff->max_bits); + return AVERROR_INVALIDDATA; + } + + if (!get_bits1(&ctx->gb)) { /* literal */ + if (length == 0) { + length = 1; + } + if (huff->num >= huff->max_num) { + av_log(ctx->avctx, AV_LOG_DEBUG, "Too many literals\n"); + return AVERROR_INVALIDDATA; + } + huff->nums[huff->num] = get_bits_long(&ctx->gb, huff->val_bits); + huff->bits[huff->num] = prefix; + huff->lens[huff->num] = length; + huff->num++; + return 0; + } else { /* non-terminal node */ + if ((ret = tm2_read_tree(ctx, prefix << 1, length + 1, huff)) < 0) + return ret; + if ((ret = tm2_read_tree(ctx, (prefix << 1) | 1, length + 1, huff)) < 0) + return ret; + } + return 0; +} + +static int tm2_build_huff_table(TM2Context *ctx, TM2Codes *code) +{ + TM2Huff huff; + int res = 0; + + huff.val_bits = get_bits(&ctx->gb, 5); + huff.max_bits = get_bits(&ctx->gb, 5); + huff.min_bits = get_bits(&ctx->gb, 5); + huff.nodes = get_bits_long(&ctx->gb, 17); + huff.num = 0; + + /* check for correct codes parameters */ + if ((huff.val_bits < 1) || (huff.val_bits > 32) || + (huff.max_bits < 0) || (huff.max_bits > 25)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect tree parameters - literal " + "length: %i, max code length: %i\n", huff.val_bits, huff.max_bits); + return AVERROR_INVALIDDATA; + } + if ((huff.nodes <= 0) || (huff.nodes > 0x10000)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of Huffman tree " + "nodes: %i\n", huff.nodes); + return AVERROR_INVALIDDATA; + } + /* one-node tree */ + if (huff.max_bits == 0) + huff.max_bits = 1; + + /* allocate space for codes - it is exactly ceil(nodes / 2) entries */ + huff.max_num = (huff.nodes + 1) >> 1; + huff.nums = av_mallocz(huff.max_num * sizeof(int)); + huff.bits = av_mallocz(huff.max_num * sizeof(uint32_t)); + huff.lens = av_mallocz(huff.max_num * sizeof(int)); + + res = tm2_read_tree(ctx, 0, 0, &huff); + + if (huff.num != huff.max_num) { + av_log(ctx->avctx, AV_LOG_ERROR, "Got less codes than expected: %i of %i\n", + huff.num, huff.max_num); + res = AVERROR_INVALIDDATA; + } + + /* convert codes to vlc_table */ + if (res >= 0) { + int i; + + res = init_vlc(&code->vlc, huff.max_bits, huff.max_num, + huff.lens, sizeof(int), sizeof(int), + huff.bits, sizeof(uint32_t), sizeof(uint32_t), 0); + if (res < 0) + av_log(ctx->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); + else { + code->bits = huff.max_bits; + code->length = huff.max_num; + code->recode = av_malloc(code->length * sizeof(int)); + for (i = 0; i < code->length; i++) + code->recode[i] = huff.nums[i]; + } + } + /* free allocated memory */ + av_free(huff.nums); + av_free(huff.bits); + av_free(huff.lens); + + return res; +} + +static void tm2_free_codes(TM2Codes *code) +{ + av_free(code->recode); + if (code->vlc.table) + ff_free_vlc(&code->vlc); +} + +static inline int tm2_get_token(GetBitContext *gb, TM2Codes *code) +{ + int val; + val = get_vlc2(gb, code->vlc.table, code->bits, 1); + if(val<0) + return -1; + return code->recode[val]; +} + +#define TM2_OLD_HEADER_MAGIC 0x00000100 +#define TM2_NEW_HEADER_MAGIC 0x00000101 + +static inline int tm2_read_header(TM2Context *ctx, const uint8_t *buf) +{ + uint32_t magic = AV_RL32(buf); + + switch (magic) { + case TM2_OLD_HEADER_MAGIC: + avpriv_request_sample(ctx->avctx, "Old TM2 header"); + return 0; + case TM2_NEW_HEADER_MAGIC: + return 0; + default: + av_log(ctx->avctx, AV_LOG_ERROR, "Not a TM2 header: 0x%08X\n", magic); + return AVERROR_INVALIDDATA; + } +} + +static int tm2_read_deltas(TM2Context *ctx, int stream_id) +{ + int d, mb; + int i, v; + + d = get_bits(&ctx->gb, 9); + mb = get_bits(&ctx->gb, 5); + + if ((d < 1) || (d > TM2_DELTAS) || (mb < 1) || (mb > 32)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect delta table: %i deltas x %i bits\n", d, mb); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < d; i++) { + v = get_bits_long(&ctx->gb, mb); + if (v & (1 << (mb - 1))) + ctx->deltas[stream_id][i] = v - (1 << mb); + else + ctx->deltas[stream_id][i] = v; + } + for (; i < TM2_DELTAS; i++) + ctx->deltas[stream_id][i] = 0; + + return 0; +} + +static int tm2_read_stream(TM2Context *ctx, const uint8_t *buf, int stream_id, int buf_size) +{ + int i, ret; + int skip = 0; + int len, toks, pos; + TM2Codes codes; + GetByteContext gb; + + if (buf_size < 4) { + av_log(ctx->avctx, AV_LOG_ERROR, "not enough space for len left\n"); + return AVERROR_INVALIDDATA; + } + + /* get stream length in dwords */ + bytestream2_init(&gb, buf, buf_size); + len = bytestream2_get_be32(&gb); + skip = len * 4 + 4; + + if (len == 0) + return 4; + + if (len >= INT_MAX/4-1 || len < 0 || skip > buf_size) { + av_log(ctx->avctx, AV_LOG_ERROR, "invalid stream size\n"); + return AVERROR_INVALIDDATA; + } + + toks = bytestream2_get_be32(&gb); + if (toks & 1) { + len = bytestream2_get_be32(&gb); + if (len == TM2_ESCAPE) { + len = bytestream2_get_be32(&gb); + } + if (len > 0) { + pos = bytestream2_tell(&gb); + if (skip <= pos) + return AVERROR_INVALIDDATA; + init_get_bits(&ctx->gb, buf + pos, (skip - pos) * 8); + if ((ret = tm2_read_deltas(ctx, stream_id)) < 0) + return ret; + bytestream2_skip(&gb, ((get_bits_count(&ctx->gb) + 31) >> 5) << 2); + } + } + /* skip unused fields */ + len = bytestream2_get_be32(&gb); + if (len == TM2_ESCAPE) { /* some unknown length - could be escaped too */ + bytestream2_skip(&gb, 8); /* unused by decoder */ + } else { + bytestream2_skip(&gb, 4); /* unused by decoder */ + } + + pos = bytestream2_tell(&gb); + if (skip <= pos) + return AVERROR_INVALIDDATA; + init_get_bits(&ctx->gb, buf + pos, (skip - pos) * 8); + if ((ret = tm2_build_huff_table(ctx, &codes)) < 0) + return ret; + bytestream2_skip(&gb, ((get_bits_count(&ctx->gb) + 31) >> 5) << 2); + + toks >>= 1; + /* check if we have sane number of tokens */ + if ((toks < 0) || (toks > 0xFFFFFF)) { + av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of tokens: %i\n", toks); + tm2_free_codes(&codes); + return AVERROR_INVALIDDATA; + } + ctx->tokens[stream_id] = av_realloc(ctx->tokens[stream_id], toks * sizeof(int)); + ctx->tok_lens[stream_id] = toks; + len = bytestream2_get_be32(&gb); + if (len > 0) { + pos = bytestream2_tell(&gb); + if (skip <= pos) + return AVERROR_INVALIDDATA; + init_get_bits(&ctx->gb, buf + pos, (skip - pos) * 8); + for (i = 0; i < toks; i++) { + if (get_bits_left(&ctx->gb) <= 0) { + av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of tokens: %i\n", toks); + return AVERROR_INVALIDDATA; + } + ctx->tokens[stream_id][i] = tm2_get_token(&ctx->gb, &codes); + if (stream_id <= TM2_MOT && ctx->tokens[stream_id][i] >= TM2_DELTAS || ctx->tokens[stream_id][i]<0) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid delta token index %d for type %d, n=%d\n", + ctx->tokens[stream_id][i], stream_id, i); + return AVERROR_INVALIDDATA; + } + } + } else { + for (i = 0; i < toks; i++) { + ctx->tokens[stream_id][i] = codes.recode[0]; + if (stream_id <= TM2_MOT && ctx->tokens[stream_id][i] >= TM2_DELTAS) { + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid delta token index %d for type %d, n=%d\n", + ctx->tokens[stream_id][i], stream_id, i); + return AVERROR_INVALIDDATA; + } + } + } + tm2_free_codes(&codes); + + return skip; +} + +static inline int GET_TOK(TM2Context *ctx,int type) +{ + if (ctx->tok_ptrs[type] >= ctx->tok_lens[type]) { + av_log(ctx->avctx, AV_LOG_ERROR, "Read token from stream %i out of bounds (%i>=%i)\n", type, ctx->tok_ptrs[type], ctx->tok_lens[type]); + return 0; + } + if (type <= TM2_MOT) { + if (ctx->tokens[type][ctx->tok_ptrs[type]] >= TM2_DELTAS) { + av_log(ctx->avctx, AV_LOG_ERROR, "token %d is too large\n", ctx->tokens[type][ctx->tok_ptrs[type]]); + return 0; + } + return ctx->deltas[type][ctx->tokens[type][ctx->tok_ptrs[type]++]]; + } + return ctx->tokens[type][ctx->tok_ptrs[type]++]; +} + +/* blocks decoding routines */ + +/* common Y, U, V pointers initialisation */ +#define TM2_INIT_POINTERS() \ + int *last, *clast; \ + int *Y, *U, *V;\ + int Ystride, Ustride, Vstride;\ +\ + Ystride = ctx->y_stride;\ + Vstride = ctx->uv_stride;\ + Ustride = ctx->uv_stride;\ + Y = (ctx->cur?ctx->Y2:ctx->Y1) + by * 4 * Ystride + bx * 4;\ + V = (ctx->cur?ctx->V2:ctx->V1) + by * 2 * Vstride + bx * 2;\ + U = (ctx->cur?ctx->U2:ctx->U1) + by * 2 * Ustride + bx * 2;\ + last = ctx->last + bx * 4;\ + clast = ctx->clast + bx * 4; + +#define TM2_INIT_POINTERS_2() \ + int *Yo, *Uo, *Vo;\ + int oYstride, oUstride, oVstride;\ +\ + TM2_INIT_POINTERS();\ + oYstride = Ystride;\ + oVstride = Vstride;\ + oUstride = Ustride;\ + Yo = (ctx->cur?ctx->Y1:ctx->Y2) + by * 4 * oYstride + bx * 4;\ + Vo = (ctx->cur?ctx->V1:ctx->V2) + by * 2 * oVstride + bx * 2;\ + Uo = (ctx->cur?ctx->U1:ctx->U2) + by * 2 * oUstride + bx * 2; + +/* recalculate last and delta values for next blocks */ +#define TM2_RECALC_BLOCK(CHR, stride, last, CD) {\ + CD[0] = CHR[1] - last[1];\ + CD[1] = (int)CHR[stride + 1] - (int)CHR[1];\ + last[0] = (int)CHR[stride + 0];\ + last[1] = (int)CHR[stride + 1];} + +/* common operations - add deltas to 4x4 block of luma or 2x2 blocks of chroma */ +static inline void tm2_apply_deltas(TM2Context *ctx, int* Y, int stride, int *deltas, int *last) +{ + int ct, d; + int i, j; + + for (j = 0; j < 4; j++){ + ct = ctx->D[j]; + for (i = 0; i < 4; i++){ + d = deltas[i + j * 4]; + ct += d; + last[i] += ct; + Y[i] = av_clip_uint8(last[i]); + } + Y += stride; + ctx->D[j] = ct; + } +} + +static inline void tm2_high_chroma(int *data, int stride, int *last, int *CD, int *deltas) +{ + int i, j; + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++) { + CD[j] += deltas[i + j * 2]; + last[i] += CD[j]; + data[i] = last[i]; + } + data += stride; + } +} + +static inline void tm2_low_chroma(int *data, int stride, int *clast, int *CD, int *deltas, int bx) +{ + int t; + int l; + int prev; + + if (bx > 0) + prev = clast[-3]; + else + prev = 0; + t = (CD[0] + CD[1]) >> 1; + l = (prev - CD[0] - CD[1] + clast[1]) >> 1; + CD[1] = CD[0] + CD[1] - t; + CD[0] = t; + clast[0] = l; + + tm2_high_chroma(data, stride, clast, CD, deltas); +} + +static inline void tm2_hi_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i; + int deltas[16]; + TM2_INIT_POINTERS(); + + /* hi-res chroma */ + for (i = 0; i < 4; i++) { + deltas[i] = GET_TOK(ctx, TM2_C_HI); + deltas[i + 4] = GET_TOK(ctx, TM2_C_HI); + } + tm2_high_chroma(U, Ustride, clast, ctx->CD, deltas); + tm2_high_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas + 4); + + /* hi-res luma */ + for (i = 0; i < 16; i++) + deltas[i] = GET_TOK(ctx, TM2_L_HI); + + tm2_apply_deltas(ctx, Y, Ystride, deltas, last); +} + +static inline void tm2_med_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i; + int deltas[16]; + TM2_INIT_POINTERS(); + + /* low-res chroma */ + deltas[0] = GET_TOK(ctx, TM2_C_LO); + deltas[1] = deltas[2] = deltas[3] = 0; + tm2_low_chroma(U, Ustride, clast, ctx->CD, deltas, bx); + + deltas[0] = GET_TOK(ctx, TM2_C_LO); + deltas[1] = deltas[2] = deltas[3] = 0; + tm2_low_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas, bx); + + /* hi-res luma */ + for (i = 0; i < 16; i++) + deltas[i] = GET_TOK(ctx, TM2_L_HI); + + tm2_apply_deltas(ctx, Y, Ystride, deltas, last); +} + +static inline void tm2_low_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i; + int t1, t2; + int deltas[16]; + TM2_INIT_POINTERS(); + + /* low-res chroma */ + deltas[0] = GET_TOK(ctx, TM2_C_LO); + deltas[1] = deltas[2] = deltas[3] = 0; + tm2_low_chroma(U, Ustride, clast, ctx->CD, deltas, bx); + + deltas[0] = GET_TOK(ctx, TM2_C_LO); + deltas[1] = deltas[2] = deltas[3] = 0; + tm2_low_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas, bx); + + /* low-res luma */ + for (i = 0; i < 16; i++) + deltas[i] = 0; + + deltas[ 0] = GET_TOK(ctx, TM2_L_LO); + deltas[ 2] = GET_TOK(ctx, TM2_L_LO); + deltas[ 8] = GET_TOK(ctx, TM2_L_LO); + deltas[10] = GET_TOK(ctx, TM2_L_LO); + + if (bx > 0) + last[0] = (last[-1] - ctx->D[0] - ctx->D[1] - ctx->D[2] - ctx->D[3] + last[1]) >> 1; + else + last[0] = (last[1] - ctx->D[0] - ctx->D[1] - ctx->D[2] - ctx->D[3])>> 1; + last[2] = (last[1] + last[3]) >> 1; + + t1 = ctx->D[0] + ctx->D[1]; + ctx->D[0] = t1 >> 1; + ctx->D[1] = t1 - (t1 >> 1); + t2 = ctx->D[2] + ctx->D[3]; + ctx->D[2] = t2 >> 1; + ctx->D[3] = t2 - (t2 >> 1); + + tm2_apply_deltas(ctx, Y, Ystride, deltas, last); +} + +static inline void tm2_null_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i; + int ct; + int left, right, diff; + int deltas[16]; + TM2_INIT_POINTERS(); + + /* null chroma */ + deltas[0] = deltas[1] = deltas[2] = deltas[3] = 0; + tm2_low_chroma(U, Ustride, clast, ctx->CD, deltas, bx); + + deltas[0] = deltas[1] = deltas[2] = deltas[3] = 0; + tm2_low_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas, bx); + + /* null luma */ + for (i = 0; i < 16; i++) + deltas[i] = 0; + + ct = ctx->D[0] + ctx->D[1] + ctx->D[2] + ctx->D[3]; + + if (bx > 0) + left = last[-1] - ct; + else + left = 0; + + right = last[3]; + diff = right - left; + last[0] = left + (diff >> 2); + last[1] = left + (diff >> 1); + last[2] = right - (diff >> 2); + last[3] = right; + { + int tp = left; + + ctx->D[0] = (tp + (ct >> 2)) - left; + left += ctx->D[0]; + ctx->D[1] = (tp + (ct >> 1)) - left; + left += ctx->D[1]; + ctx->D[2] = ((tp + ct) - (ct >> 2)) - left; + left += ctx->D[2]; + ctx->D[3] = (tp + ct) - left; + } + tm2_apply_deltas(ctx, Y, Ystride, deltas, last); +} + +static inline void tm2_still_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i, j; + TM2_INIT_POINTERS_2(); + + /* update chroma */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++){ + U[i] = Uo[i]; + V[i] = Vo[i]; + } + U += Ustride; V += Vstride; + Uo += oUstride; Vo += oVstride; + } + U -= Ustride * 2; + V -= Vstride * 2; + TM2_RECALC_BLOCK(U, Ustride, clast, ctx->CD); + TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); + + /* update deltas */ + ctx->D[0] = Yo[3] - last[3]; + ctx->D[1] = Yo[3 + oYstride] - Yo[3]; + ctx->D[2] = Yo[3 + oYstride * 2] - Yo[3 + oYstride]; + ctx->D[3] = Yo[3 + oYstride * 3] - Yo[3 + oYstride * 2]; + + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) { + Y[i] = Yo[i]; + last[i] = Yo[i]; + } + Y += Ystride; + Yo += oYstride; + } +} + +static inline void tm2_update_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i, j; + int d; + TM2_INIT_POINTERS_2(); + + /* update chroma */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++) { + U[i] = Uo[i] + GET_TOK(ctx, TM2_UPD); + V[i] = Vo[i] + GET_TOK(ctx, TM2_UPD); + } + U += Ustride; + V += Vstride; + Uo += oUstride; + Vo += oVstride; + } + U -= Ustride * 2; + V -= Vstride * 2; + TM2_RECALC_BLOCK(U, Ustride, clast, ctx->CD); + TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); + + /* update deltas */ + ctx->D[0] = Yo[3] - last[3]; + ctx->D[1] = Yo[3 + oYstride] - Yo[3]; + ctx->D[2] = Yo[3 + oYstride * 2] - Yo[3 + oYstride]; + ctx->D[3] = Yo[3 + oYstride * 3] - Yo[3 + oYstride * 2]; + + for (j = 0; j < 4; j++) { + d = last[3]; + for (i = 0; i < 4; i++) { + Y[i] = Yo[i] + GET_TOK(ctx, TM2_UPD); + last[i] = Y[i]; + } + ctx->D[j] = last[3] - d; + Y += Ystride; + Yo += oYstride; + } +} + +static inline void tm2_motion_block(TM2Context *ctx, AVFrame *pic, int bx, int by) +{ + int i, j; + int mx, my; + TM2_INIT_POINTERS_2(); + + mx = GET_TOK(ctx, TM2_MOT); + my = GET_TOK(ctx, TM2_MOT); + mx = av_clip(mx, -(bx * 4 + 4), ctx->avctx->width - bx * 4); + my = av_clip(my, -(by * 4 + 4), ctx->avctx->height - by * 4); + + if (4*bx+mx<0 || 4*by+my<0 || 4*bx+mx+4 > ctx->avctx->width || 4*by+my+4 > ctx->avctx->height) { + av_log(ctx->avctx, AV_LOG_ERROR, "MV out of picture\n"); + return; + } + + Yo += my * oYstride + mx; + Uo += (my >> 1) * oUstride + (mx >> 1); + Vo += (my >> 1) * oVstride + (mx >> 1); + + /* copy chroma */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 2; i++) { + U[i] = Uo[i]; + V[i] = Vo[i]; + } + U += Ustride; + V += Vstride; + Uo += oUstride; + Vo += oVstride; + } + U -= Ustride * 2; + V -= Vstride * 2; + TM2_RECALC_BLOCK(U, Ustride, clast, ctx->CD); + TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); + + /* copy luma */ + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++) { + Y[i] = Yo[i]; + } + Y += Ystride; + Yo += oYstride; + } + /* calculate deltas */ + Y -= Ystride * 4; + ctx->D[0] = Y[3] - last[3]; + ctx->D[1] = Y[3 + Ystride] - Y[3]; + ctx->D[2] = Y[3 + Ystride * 2] - Y[3 + Ystride]; + ctx->D[3] = Y[3 + Ystride * 3] - Y[3 + Ystride * 2]; + for (i = 0; i < 4; i++) + last[i] = Y[i + Ystride * 3]; +} + +static int tm2_decode_blocks(TM2Context *ctx, AVFrame *p) +{ + int i, j; + int w = ctx->avctx->width, h = ctx->avctx->height, bw = w >> 2, bh = h >> 2, cw = w >> 1; + int type; + int keyframe = 1; + int *Y, *U, *V; + uint8_t *dst; + + for (i = 0; i < TM2_NUM_STREAMS; i++) + ctx->tok_ptrs[i] = 0; + + if (ctx->tok_lens[TM2_TYPE]avctx,AV_LOG_ERROR,"Got %i tokens for %i blocks\n",ctx->tok_lens[TM2_TYPE],bw*bh); + return AVERROR_INVALIDDATA; + } + + memset(ctx->last, 0, 4 * bw * sizeof(int)); + memset(ctx->clast, 0, 4 * bw * sizeof(int)); + + for (j = 0; j < bh; j++) { + memset(ctx->D, 0, 4 * sizeof(int)); + memset(ctx->CD, 0, 4 * sizeof(int)); + for (i = 0; i < bw; i++) { + type = GET_TOK(ctx, TM2_TYPE); + switch(type) { + case TM2_HI_RES: + tm2_hi_res_block(ctx, p, i, j); + break; + case TM2_MED_RES: + tm2_med_res_block(ctx, p, i, j); + break; + case TM2_LOW_RES: + tm2_low_res_block(ctx, p, i, j); + break; + case TM2_NULL_RES: + tm2_null_res_block(ctx, p, i, j); + break; + case TM2_UPDATE: + tm2_update_block(ctx, p, i, j); + keyframe = 0; + break; + case TM2_STILL: + tm2_still_block(ctx, p, i, j); + keyframe = 0; + break; + case TM2_MOTION: + tm2_motion_block(ctx, p, i, j); + keyframe = 0; + break; + default: + av_log(ctx->avctx, AV_LOG_ERROR, "Skipping unknown block type %i\n", type); + } + } + } + + /* copy data from our buffer to AVFrame */ + Y = (ctx->cur?ctx->Y2:ctx->Y1); + U = (ctx->cur?ctx->U2:ctx->U1); + V = (ctx->cur?ctx->V2:ctx->V1); + dst = p->data[0]; + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + int y = Y[i], u = U[i >> 1], v = V[i >> 1]; + dst[3*i+0] = av_clip_uint8(y + v); + dst[3*i+1] = av_clip_uint8(y); + dst[3*i+2] = av_clip_uint8(y + u); + } + + /* horizontal edge extension */ + Y[-4] = Y[-3] = Y[-2] = Y[-1] = Y[0]; + Y[w + 3] = Y[w + 2] = Y[w + 1] = Y[w] = Y[w - 1]; + + /* vertical edge extension */ + if (j == 0) { + memcpy(Y - 4 - 1 * ctx->y_stride, Y - 4, ctx->y_stride); + memcpy(Y - 4 - 2 * ctx->y_stride, Y - 4, ctx->y_stride); + memcpy(Y - 4 - 3 * ctx->y_stride, Y - 4, ctx->y_stride); + memcpy(Y - 4 - 4 * ctx->y_stride, Y - 4, ctx->y_stride); + } else if (j == h - 1) { + memcpy(Y - 4 + 1 * ctx->y_stride, Y - 4, ctx->y_stride); + memcpy(Y - 4 + 2 * ctx->y_stride, Y - 4, ctx->y_stride); + memcpy(Y - 4 + 3 * ctx->y_stride, Y - 4, ctx->y_stride); + memcpy(Y - 4 + 4 * ctx->y_stride, Y - 4, ctx->y_stride); + } + + Y += ctx->y_stride; + if (j & 1) { + /* horizontal edge extension */ + U[-2] = U[-1] = U[0]; + V[-2] = V[-1] = V[0]; + U[cw + 1] = U[cw] = U[cw - 1]; + V[cw + 1] = V[cw] = V[cw - 1]; + + /* vertical edge extension */ + if (j == 1) { + memcpy(U - 2 - 1 * ctx->uv_stride, U - 2, ctx->uv_stride); + memcpy(V - 2 - 1 * ctx->uv_stride, V - 2, ctx->uv_stride); + memcpy(U - 2 - 2 * ctx->uv_stride, U - 2, ctx->uv_stride); + memcpy(V - 2 - 2 * ctx->uv_stride, V - 2, ctx->uv_stride); + } else if (j == h - 1) { + memcpy(U - 2 + 1 * ctx->uv_stride, U - 2, ctx->uv_stride); + memcpy(V - 2 + 1 * ctx->uv_stride, V - 2, ctx->uv_stride); + memcpy(U - 2 + 2 * ctx->uv_stride, U - 2, ctx->uv_stride); + memcpy(V - 2 + 2 * ctx->uv_stride, V - 2, ctx->uv_stride); + } + + U += ctx->uv_stride; + V += ctx->uv_stride; + } + dst += p->linesize[0]; + } + + return keyframe; +} + +static const int tm2_stream_order[TM2_NUM_STREAMS] = { + TM2_C_HI, TM2_C_LO, TM2_L_HI, TM2_L_LO, TM2_UPD, TM2_MOT, TM2_TYPE +}; + +#define TM2_HEADER_SIZE 40 + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + TM2Context * const l = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size & ~3; + AVFrame * const p = &l->pic; + int offset = TM2_HEADER_SIZE; + int i, t, ret; + + av_fast_padded_malloc(&l->buffer, &l->buffer_size, buf_size); + if (!l->buffer) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); + return AVERROR(ENOMEM); + } + + if ((ret = ff_reget_buffer(avctx, p)) < 0) + return ret; + + l->dsp.bswap_buf((uint32_t*)l->buffer, (const uint32_t*)buf, buf_size >> 2); + + if ((ret = tm2_read_header(l, l->buffer)) < 0) { + return ret; + } + + for (i = 0; i < TM2_NUM_STREAMS; i++) { + if (offset >= buf_size) { + av_log(avctx, AV_LOG_ERROR, "no space for tm2_read_stream\n"); + return AVERROR_INVALIDDATA; + } + + t = tm2_read_stream(l, l->buffer + offset, tm2_stream_order[i], + buf_size - offset); + if (t < 0) { + int j = tm2_stream_order[i]; + memset(l->tokens[j], 0, sizeof(**l->tokens) * l->tok_lens[j]); + return t; + } + offset += t; + } + p->key_frame = tm2_decode_blocks(l, p); + if (p->key_frame) + p->pict_type = AV_PICTURE_TYPE_I; + else + p->pict_type = AV_PICTURE_TYPE_P; + + l->cur = !l->cur; + *got_frame = 1; + ret = av_frame_ref(data, &l->pic); + + return (ret < 0) ? ret : buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + TM2Context * const l = avctx->priv_data; + int i, w = avctx->width, h = avctx->height; + + if ((avctx->width & 3) || (avctx->height & 3)) { + av_log(avctx, AV_LOG_ERROR, "Width and height must be multiple of 4\n"); + return AVERROR(EINVAL); + } + + l->avctx = avctx; + avcodec_get_frame_defaults(&l->pic); + avctx->pix_fmt = AV_PIX_FMT_BGR24; + + ff_dsputil_init(&l->dsp, avctx); + + l->last = av_malloc(4 * sizeof(*l->last) * (w >> 2)); + l->clast = av_malloc(4 * sizeof(*l->clast) * (w >> 2)); + + for (i = 0; i < TM2_NUM_STREAMS; i++) { + l->tokens[i] = NULL; + l->tok_lens[i] = 0; + } + + w += 8; + h += 8; + l->Y1_base = av_mallocz(sizeof(*l->Y1_base) * w * h); + l->Y2_base = av_mallocz(sizeof(*l->Y2_base) * w * h); + l->y_stride = w; + w = (w + 1) >> 1; + h = (h + 1) >> 1; + l->U1_base = av_mallocz(sizeof(*l->U1_base) * w * h); + l->V1_base = av_mallocz(sizeof(*l->V1_base) * w * h); + l->U2_base = av_mallocz(sizeof(*l->U2_base) * w * h); + l->V2_base = av_mallocz(sizeof(*l->V1_base) * w * h); + l->uv_stride = w; + l->cur = 0; + if (!l->Y1_base || !l->Y2_base || !l->U1_base || + !l->V1_base || !l->U2_base || !l->V2_base || + !l->last || !l->clast) { + av_freep(l->Y1_base); + av_freep(l->Y2_base); + av_freep(l->U1_base); + av_freep(l->U2_base); + av_freep(l->V1_base); + av_freep(l->V2_base); + av_freep(l->last); + av_freep(l->clast); + return AVERROR(ENOMEM); + } + l->Y1 = l->Y1_base + l->y_stride * 4 + 4; + l->Y2 = l->Y2_base + l->y_stride * 4 + 4; + l->U1 = l->U1_base + l->uv_stride * 2 + 2; + l->U2 = l->U2_base + l->uv_stride * 2 + 2; + l->V1 = l->V1_base + l->uv_stride * 2 + 2; + l->V2 = l->V2_base + l->uv_stride * 2 + 2; + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + TM2Context * const l = avctx->priv_data; + AVFrame *pic = &l->pic; + int i; + + av_free(l->last); + av_free(l->clast); + for (i = 0; i < TM2_NUM_STREAMS; i++) + av_free(l->tokens[i]); + if (l->Y1) { + av_free(l->Y1_base); + av_free(l->U1_base); + av_free(l->V1_base); + av_free(l->Y2_base); + av_free(l->U2_base); + av_free(l->V2_base); + } + av_freep(&l->buffer); + l->buffer_size = 0; + + av_frame_unref(pic); + + return 0; +} + +AVCodec ff_truemotion2_decoder = { + .name = "truemotion2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TRUEMOTION2, + .priv_data_size = sizeof(TM2Context), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0"), +}; diff --git a/ffmpeg/libavcodec/truespeech.c b/ffmpeg/libavcodec/truespeech.c new file mode 100644 index 0000000..2eb218c --- /dev/null +++ b/ffmpeg/libavcodec/truespeech.c @@ -0,0 +1,366 @@ +/* + * DSP Group TrueSpeech compatible decoder + * Copyright (c) 2005 Konstantin Shishkov + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "internal.h" + +#include "truespeech_data.h" +/** + * @file + * TrueSpeech decoder. + */ + +/** + * TrueSpeech decoder context + */ +typedef struct { + DSPContext dsp; + /* input data */ + DECLARE_ALIGNED(16, uint8_t, buffer)[32]; + int16_t vector[8]; ///< input vector: 5/5/4/4/4/3/3/3 + int offset1[2]; ///< 8-bit value, used in one copying offset + int offset2[4]; ///< 7-bit value, encodes offsets for copying and for two-point filter + int pulseoff[4]; ///< 4-bit offset of pulse values block + int pulsepos[4]; ///< 27-bit variable, encodes 7 pulse positions + int pulseval[4]; ///< 7x2-bit pulse values + int flag; ///< 1-bit flag, shows how to choose filters + /* temporary data */ + int filtbuf[146]; // some big vector used for storing filters + int prevfilt[8]; // filter from previous frame + int16_t tmp1[8]; // coefficients for adding to out + int16_t tmp2[8]; // coefficients for adding to out + int16_t tmp3[8]; // coefficients for adding to out + int16_t cvector[8]; // correlated input vector + int filtval; // gain value for one function + int16_t newvec[60]; // tmp vector + int16_t filters[32]; // filters for every subframe +} TSContext; + +static av_cold int truespeech_decode_init(AVCodecContext * avctx) +{ + TSContext *c = avctx->priv_data; + + if (avctx->channels != 1) { + avpriv_request_sample(avctx, "Channel count %d", avctx->channels); + return AVERROR_PATCHWELCOME; + } + + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + ff_dsputil_init(&c->dsp, avctx); + + return 0; +} + +static void truespeech_read_frame(TSContext *dec, const uint8_t *input) +{ + GetBitContext gb; + + dec->dsp.bswap_buf((uint32_t *)dec->buffer, (const uint32_t *)input, 8); + init_get_bits(&gb, dec->buffer, 32 * 8); + + dec->vector[7] = ts_codebook[7][get_bits(&gb, 3)]; + dec->vector[6] = ts_codebook[6][get_bits(&gb, 3)]; + dec->vector[5] = ts_codebook[5][get_bits(&gb, 3)]; + dec->vector[4] = ts_codebook[4][get_bits(&gb, 4)]; + dec->vector[3] = ts_codebook[3][get_bits(&gb, 4)]; + dec->vector[2] = ts_codebook[2][get_bits(&gb, 4)]; + dec->vector[1] = ts_codebook[1][get_bits(&gb, 5)]; + dec->vector[0] = ts_codebook[0][get_bits(&gb, 5)]; + dec->flag = get_bits1(&gb); + + dec->offset1[0] = get_bits(&gb, 4) << 4; + dec->offset2[3] = get_bits(&gb, 7); + dec->offset2[2] = get_bits(&gb, 7); + dec->offset2[1] = get_bits(&gb, 7); + dec->offset2[0] = get_bits(&gb, 7); + + dec->offset1[1] = get_bits(&gb, 4); + dec->pulseval[1] = get_bits(&gb, 14); + dec->pulseval[0] = get_bits(&gb, 14); + + dec->offset1[1] |= get_bits(&gb, 4) << 4; + dec->pulseval[3] = get_bits(&gb, 14); + dec->pulseval[2] = get_bits(&gb, 14); + + dec->offset1[0] |= get_bits1(&gb); + dec->pulsepos[0] = get_bits_long(&gb, 27); + dec->pulseoff[0] = get_bits(&gb, 4); + + dec->offset1[0] |= get_bits1(&gb) << 1; + dec->pulsepos[1] = get_bits_long(&gb, 27); + dec->pulseoff[1] = get_bits(&gb, 4); + + dec->offset1[0] |= get_bits1(&gb) << 2; + dec->pulsepos[2] = get_bits_long(&gb, 27); + dec->pulseoff[2] = get_bits(&gb, 4); + + dec->offset1[0] |= get_bits1(&gb) << 3; + dec->pulsepos[3] = get_bits_long(&gb, 27); + dec->pulseoff[3] = get_bits(&gb, 4); +} + +static void truespeech_correlate_filter(TSContext *dec) +{ + int16_t tmp[8]; + int i, j; + + for(i = 0; i < 8; i++){ + if(i > 0){ + memcpy(tmp, dec->cvector, i * sizeof(*tmp)); + for(j = 0; j < i; j++) + dec->cvector[j] = ((tmp[i - j - 1] * dec->vector[i]) + + (dec->cvector[j] << 15) + 0x4000) >> 15; + } + dec->cvector[i] = (8 - dec->vector[i]) >> 3; + } + for(i = 0; i < 8; i++) + dec->cvector[i] = (dec->cvector[i] * ts_decay_994_1000[i]) >> 15; + + dec->filtval = dec->vector[0]; +} + +static void truespeech_filters_merge(TSContext *dec) +{ + int i; + + if(!dec->flag){ + for(i = 0; i < 8; i++){ + dec->filters[i + 0] = dec->prevfilt[i]; + dec->filters[i + 8] = dec->prevfilt[i]; + } + }else{ + for(i = 0; i < 8; i++){ + dec->filters[i + 0]=(dec->cvector[i] * 21846 + dec->prevfilt[i] * 10923 + 16384) >> 15; + dec->filters[i + 8]=(dec->cvector[i] * 10923 + dec->prevfilt[i] * 21846 + 16384) >> 15; + } + } + for(i = 0; i < 8; i++){ + dec->filters[i + 16] = dec->cvector[i]; + dec->filters[i + 24] = dec->cvector[i]; + } +} + +static void truespeech_apply_twopoint_filter(TSContext *dec, int quart) +{ + int16_t tmp[146 + 60], *ptr0, *ptr1; + const int16_t *filter; + int i, t, off; + + t = dec->offset2[quart]; + if(t == 127){ + memset(dec->newvec, 0, 60 * sizeof(*dec->newvec)); + return; + } + for(i = 0; i < 146; i++) + tmp[i] = dec->filtbuf[i]; + off = (t / 25) + dec->offset1[quart >> 1] + 18; + off = av_clip(off, 0, 145); + ptr0 = tmp + 145 - off; + ptr1 = tmp + 146; + filter = ts_order2_coeffs + (t % 25) * 2; + for(i = 0; i < 60; i++){ + t = (ptr0[0] * filter[0] + ptr0[1] * filter[1] + 0x2000) >> 14; + ptr0++; + dec->newvec[i] = t; + ptr1[i] = t; + } +} + +static void truespeech_place_pulses(TSContext *dec, int16_t *out, int quart) +{ + int16_t tmp[7]; + int i, j, t; + const int16_t *ptr1; + int16_t *ptr2; + int coef; + + memset(out, 0, 60 * sizeof(*out)); + for(i = 0; i < 7; i++) { + t = dec->pulseval[quart] & 3; + dec->pulseval[quart] >>= 2; + tmp[6 - i] = ts_pulse_scales[dec->pulseoff[quart] * 4 + t]; + } + + coef = dec->pulsepos[quart] >> 15; + ptr1 = ts_pulse_values + 30; + ptr2 = tmp; + for(i = 0, j = 3; (i < 30) && (j > 0); i++){ + t = *ptr1++; + if(coef >= t) + coef -= t; + else{ + out[i] = *ptr2++; + ptr1 += 30; + j--; + } + } + coef = dec->pulsepos[quart] & 0x7FFF; + ptr1 = ts_pulse_values; + for(i = 30, j = 4; (i < 60) && (j > 0); i++){ + t = *ptr1++; + if(coef >= t) + coef -= t; + else{ + out[i] = *ptr2++; + ptr1 += 30; + j--; + } + } + +} + +static void truespeech_update_filters(TSContext *dec, int16_t *out, int quart) +{ + int i; + + memmove(dec->filtbuf, &dec->filtbuf[60], 86 * sizeof(*dec->filtbuf)); + for(i = 0; i < 60; i++){ + dec->filtbuf[i + 86] = out[i] + dec->newvec[i] - (dec->newvec[i] >> 3); + out[i] += dec->newvec[i]; + } +} + +static void truespeech_synth(TSContext *dec, int16_t *out, int quart) +{ + int i,k; + int t[8]; + int16_t *ptr0, *ptr1; + + ptr0 = dec->tmp1; + ptr1 = dec->filters + quart * 8; + for(i = 0; i < 60; i++){ + int sum = 0; + for(k = 0; k < 8; k++) + sum += ptr0[k] * ptr1[k]; + sum = (sum + (out[i] << 12) + 0x800) >> 12; + out[i] = av_clip(sum, -0x7FFE, 0x7FFE); + for(k = 7; k > 0; k--) + ptr0[k] = ptr0[k - 1]; + ptr0[0] = out[i]; + } + + for(i = 0; i < 8; i++) + t[i] = (ts_decay_35_64[i] * ptr1[i]) >> 15; + + ptr0 = dec->tmp2; + for(i = 0; i < 60; i++){ + int sum = 0; + for(k = 0; k < 8; k++) + sum += ptr0[k] * t[k]; + for(k = 7; k > 0; k--) + ptr0[k] = ptr0[k - 1]; + ptr0[0] = out[i]; + out[i] = ((out[i] << 12) - sum) >> 12; + } + + for(i = 0; i < 8; i++) + t[i] = (ts_decay_3_4[i] * ptr1[i]) >> 15; + + ptr0 = dec->tmp3; + for(i = 0; i < 60; i++){ + int sum = out[i] << 12; + for(k = 0; k < 8; k++) + sum += ptr0[k] * t[k]; + for(k = 7; k > 0; k--) + ptr0[k] = ptr0[k - 1]; + ptr0[0] = av_clip((sum + 0x800) >> 12, -0x7FFE, 0x7FFE); + + sum = ((ptr0[1] * (dec->filtval - (dec->filtval >> 2))) >> 4) + sum; + sum = sum - (sum >> 3); + out[i] = av_clip((sum + 0x800) >> 12, -0x7FFE, 0x7FFE); + } +} + +static void truespeech_save_prevvec(TSContext *c) +{ + int i; + + for(i = 0; i < 8; i++) + c->prevfilt[i] = c->cvector[i]; +} + +static int truespeech_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + TSContext *c = avctx->priv_data; + + int i, j; + int16_t *samples; + int iterations, ret; + + iterations = buf_size / 32; + + if (!iterations) { + av_log(avctx, AV_LOG_ERROR, + "Too small input buffer (%d bytes), need at least 32 bytes\n", buf_size); + return -1; + } + + /* get output buffer */ + frame->nb_samples = iterations * 240; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (int16_t *)frame->data[0]; + + memset(samples, 0, iterations * 240 * sizeof(*samples)); + + for(j = 0; j < iterations; j++) { + truespeech_read_frame(c, buf); + buf += 32; + + truespeech_correlate_filter(c); + truespeech_filters_merge(c); + + for(i = 0; i < 4; i++) { + truespeech_apply_twopoint_filter(c, i); + truespeech_place_pulses (c, samples, i); + truespeech_update_filters(c, samples, i); + truespeech_synth (c, samples, i); + samples += 60; + } + + truespeech_save_prevvec(c); + } + + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_truespeech_decoder = { + .name = "truespeech", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_TRUESPEECH, + .priv_data_size = sizeof(TSContext), + .init = truespeech_decode_init, + .decode = truespeech_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"), +}; diff --git a/ffmpeg/libavcodec/truespeech_data.h b/ffmpeg/libavcodec/truespeech_data.h new file mode 100644 index 0000000..73ebda5 --- /dev/null +++ b/ffmpeg/libavcodec/truespeech_data.h @@ -0,0 +1,159 @@ +/* + * DSP Group TrueSpeech compatible decoder + * copyright (c) 2005 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_TRUESPEECH_DATA_H +#define AVCODEC_TRUESPEECH_DATA_H + +#include + +/* codebooks fo expanding input filter */ +static const int16_t ts_cb_0[32] = { + 0x8240, 0x8364, 0x84CE, 0x865D, 0x8805, 0x89DE, 0x8BD7, 0x8DF4, + 0x9051, 0x92E2, 0x95DE, 0x990F, 0x9C81, 0xA079, 0xA54C, 0xAAD2, + 0xB18A, 0xB90A, 0xC124, 0xC9CC, 0xD339, 0xDDD3, 0xE9D6, 0xF893, + 0x096F, 0x1ACA, 0x29EC, 0x381F, 0x45F9, 0x546A, 0x63C3, 0x73B5, +}; + +static const int16_t ts_cb_1[32] = { + 0x9F65, 0xB56B, 0xC583, 0xD371, 0xE018, 0xEBB4, 0xF61C, 0xFF59, + 0x085B, 0x1106, 0x1952, 0x214A, 0x28C9, 0x2FF8, 0x36E6, 0x3D92, + 0x43DF, 0x49BB, 0x4F46, 0x5467, 0x5930, 0x5DA3, 0x61EC, 0x65F9, + 0x69D4, 0x6D5A, 0x709E, 0x73AD, 0x766B, 0x78F0, 0x7B5A, 0x7DA5, +}; + +static const int16_t ts_cb_2[16] = { + 0x96F8, 0xA3B4, 0xAF45, 0xBA53, 0xC4B1, 0xCECC, 0xD86F, 0xE21E, + 0xEBF3, 0xF640, 0x00F7, 0x0C20, 0x1881, 0x269A, 0x376B, 0x4D60, +}; + +static const int16_t ts_cb_3[16] = { + 0xC654, 0xDEF2, 0xEFAA, 0xFD94, 0x096A, 0x143F, 0x1E7B, 0x282C, + 0x3176, 0x3A89, 0x439F, 0x4CA2, 0x557F, 0x5E50, 0x6718, 0x6F8D, +}; + +static const int16_t ts_cb_4[16] = { + 0xABE7, 0xBBA8, 0xC81C, 0xD326, 0xDD0E, 0xE5D4, 0xEE22, 0xF618, + 0xFE28, 0x064F, 0x0EB7, 0x17B8, 0x21AA, 0x2D8B, 0x3BA2, 0x4DF9, +}; + +static const int16_t ts_cb_5[8] = { + 0xD51B, 0xF12E, 0x042E, 0x13C7, 0x2260, 0x311B, 0x40DE, 0x5385, +}; + +static const int16_t ts_cb_6[8] = { + 0xB550, 0xC825, 0xD980, 0xE997, 0xF883, 0x0752, 0x1811, 0x2E18, +}; + +static const int16_t ts_cb_7[8] = { + 0xCEF0, 0xE4F9, 0xF6BB, 0x0646, 0x14F5, 0x23FF, 0x356F, 0x4A8D, +}; + +static const int16_t * const ts_codebook[8] = { + ts_cb_0, ts_cb_1, ts_cb_2, ts_cb_3, ts_cb_4, ts_cb_5, ts_cb_6, ts_cb_7 +}; + +/* table used for decoding pulse positions */ +static const int16_t ts_pulse_values[120] = { + 0x0E46, 0x0CCC, 0x0B6D, 0x0A28, 0x08FC, 0x07E8, 0x06EB, 0x0604, + 0x0532, 0x0474, 0x03C9, 0x0330, 0x02A8, 0x0230, 0x01C7, 0x016C, + 0x011E, 0x00DC, 0x00A5, 0x0078, 0x0054, 0x0038, 0x0023, 0x0014, + 0x000A, 0x0004, 0x0001, 0x0000, 0x0000, 0x0000, + + 0x0196, 0x017A, 0x015F, 0x0145, 0x012C, 0x0114, 0x00FD, 0x00E7, + 0x00D2, 0x00BE, 0x00AB, 0x0099, 0x0088, 0x0078, 0x0069, 0x005B, + 0x004E, 0x0042, 0x0037, 0x002D, 0x0024, 0x001C, 0x0015, 0x000F, + 0x000A, 0x0006, 0x0003, 0x0001, 0x0000, 0x0000, + + 0x001D, 0x001C, 0x001B, 0x001A, 0x0019, 0x0018, 0x0017, 0x0016, + 0x0015, 0x0014, 0x0013, 0x0012, 0x0011, 0x0010, 0x000F, 0x000E, + 0x000D, 0x000C, 0x000B, 0x000A, 0x0009, 0x0008, 0x0007, 0x0006, + 0x0005, 0x0004, 0x0003, 0x0002, 0x0001, 0x0000, + + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001 +}; + +/* filter for correlated input filter */ +static const int16_t ts_decay_994_1000[8] = + { 0x7F3B, 0x7E78, 0x7DB6, 0x7CF5, 0x7C35, 0x7B76, 0x7AB8, 0x79FC }; + +/* two-point filters table */ +static const int16_t ts_order2_coeffs[25 * 2] = { + 0xED2F, 0x5239, + 0x54F1, 0xE4A9, + 0x2620, 0xEE3E, + 0x09D6, 0x2C40, + 0xEFB5, 0x2BE0, + + 0x3FE1, 0x3339, + 0x442F, 0xE6FE, + 0x4458, 0xF9DF, + 0xF231, 0x43DB, + 0x3DB0, 0xF705, + + 0x4F7B, 0xFEFB, + 0x26AD, 0x0CDC, + 0x33C2, 0x0739, + 0x12BE, 0x43A2, + 0x1BDF, 0x1F3E, + + 0x0211, 0x0796, + 0x2AEB, 0x163F, + 0x050D, 0x3A38, + 0x0D1E, 0x0D78, + 0x150F, 0x3346, + + 0x38A4, 0x0B7D, + 0x2D5D, 0x1FDF, + 0x19B7, 0x2822, + 0x0D99, 0x1F12, + 0x194C, 0x0CE6 +}; + +/* possible pulse values */ +static const int16_t ts_pulse_scales[64] = { + 0x0002, 0x0006, 0xFFFE, 0xFFFA, + 0x0004, 0x000C, 0xFFFC, 0xFFF4, + 0x0006, 0x0012, 0xFFFA, 0xFFEE, + 0x000A, 0x001E, 0xFFF6, 0xFFE2, + 0x0010, 0x0030, 0xFFF0, 0xFFD0, + 0x0019, 0x004B, 0xFFE7, 0xFFB5, + 0x0028, 0x0078, 0xFFD8, 0xFF88, + 0x0040, 0x00C0, 0xFFC0, 0xFF40, + 0x0065, 0x012F, 0xFF9B, 0xFED1, + 0x00A1, 0x01E3, 0xFF5F, 0xFE1D, + 0x0100, 0x0300, 0xFF00, 0xFD00, + 0x0196, 0x04C2, 0xFE6A, 0xFB3E, + 0x0285, 0x078F, 0xFD7B, 0xF871, + 0x0400, 0x0C00, 0xFC00, 0xF400, + 0x0659, 0x130B, 0xF9A7, 0xECF5, + 0x0A14, 0x1E3C, 0xF5EC, 0xE1C4 +}; + +/* filters used in final output calculations */ +static const int16_t ts_decay_35_64[8] = + { 0x4666, 0x26B8, 0x154C, 0x0BB6, 0x0671, 0x038B, 0x01F3, 0x0112 }; +static const int16_t ts_decay_3_4[8] = + { 0x6000, 0x4800, 0x3600, 0x2880, 0x1E60, 0x16C8, 0x1116, 0x0CD1 }; + +#endif /* AVCODEC_TRUESPEECH_DATA_H */ diff --git a/ffmpeg/libavcodec/tscc.c b/ffmpeg/libavcodec/tscc.c new file mode 100644 index 0000000..6e1e077 --- /dev/null +++ b/ffmpeg/libavcodec/tscc.c @@ -0,0 +1,190 @@ +/* + * TechSmith Camtasia decoder + * Copyright (c) 2004 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * TechSmith Camtasia decoder + * + * Fourcc: TSCC + * + * Codec is very simple: + * it codes picture (picture difference, really) + * with algorithm almost identical to Windows RLE8, + * only without padding and with greater pixel sizes, + * then this coded picture is packed with ZLib + * + * Supports: BGR8,BGR555,BGR24 - only BGR8 and BGR555 tested + * + */ + +#include +#include + +#include "avcodec.h" +#include "internal.h" +#include "msrledec.h" + +#include + +typedef struct TsccContext { + + AVCodecContext *avctx; + AVFrame *frame; + + // Bits per pixel + int bpp; + // Decompressed data size + unsigned int decomp_size; + // Decompression buffer + unsigned char* decomp_buf; + GetByteContext gb; + int height; + z_stream zstream; + + uint32_t pal[256]; +} CamtasiaContext; + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + CamtasiaContext * const c = avctx->priv_data; + const unsigned char *encoded = buf; + AVFrame *frame = c->frame; + int zret; // Zlib return code + int ret, len = buf_size; + + if ((ret = ff_reget_buffer(avctx, frame)) < 0) + return ret; + + zret = inflateReset(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); + return AVERROR_UNKNOWN; + } + c->zstream.next_in = (uint8_t*)encoded; + c->zstream.avail_in = len; + c->zstream.next_out = c->decomp_buf; + c->zstream.avail_out = c->decomp_size; + zret = inflate(&c->zstream, Z_FINISH); + // Z_DATA_ERROR means empty picture + if ((zret != Z_OK) && (zret != Z_STREAM_END) && (zret != Z_DATA_ERROR)) { + av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret); + return AVERROR_UNKNOWN; + } + + + if (zret != Z_DATA_ERROR) { + bytestream2_init(&c->gb, c->decomp_buf, + c->decomp_size - c->zstream.avail_out); + ff_msrle_decode(avctx, (AVPicture*)frame, c->bpp, &c->gb); + } + + /* make the palette available on the way out */ + if (c->avctx->pix_fmt == AV_PIX_FMT_PAL8) { + const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL); + + if (pal) { + frame->palette_has_changed = 1; + memcpy(c->pal, pal, AVPALETTE_SIZE); + } + memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); + } + + if ((ret = av_frame_ref(data, frame)) < 0) + return ret; + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + CamtasiaContext * const c = avctx->priv_data; + int zret; // Zlib return code + + c->avctx = avctx; + + c->height = avctx->height; + + // Needed if zlib unused or init aborted before inflateInit + memset(&c->zstream, 0, sizeof(z_stream)); + switch(avctx->bits_per_coded_sample){ + case 8: avctx->pix_fmt = AV_PIX_FMT_PAL8; break; + case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break; + case 24: + avctx->pix_fmt = AV_PIX_FMT_BGR24; + break; + case 32: avctx->pix_fmt = AV_PIX_FMT_RGB32; break; + default: av_log(avctx, AV_LOG_ERROR, "Camtasia error: unknown depth %i bpp\n", avctx->bits_per_coded_sample); + return AVERROR_PATCHWELCOME; + } + c->bpp = avctx->bits_per_coded_sample; + // buffer size for RLE 'best' case when 2-byte code precedes each pixel and there may be padding after it too + c->decomp_size = (((avctx->width * c->bpp + 7) >> 3) + 3 * avctx->width + 2) * avctx->height + 2; + + /* Allocate decompression buffer */ + if (c->decomp_size) { + if ((c->decomp_buf = av_malloc(c->decomp_size)) == NULL) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + } + + c->zstream.zalloc = Z_NULL; + c->zstream.zfree = Z_NULL; + c->zstream.opaque = Z_NULL; + zret = inflateInit(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return AVERROR_UNKNOWN; + } + + c->frame = av_frame_alloc(); + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + CamtasiaContext * const c = avctx->priv_data; + + av_freep(&c->decomp_buf); + av_frame_free(&c->frame); + + inflateEnd(&c->zstream); + + return 0; +} + +AVCodec ff_tscc_decoder = { + .name = "camtasia", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TSCC, + .priv_data_size = sizeof(CamtasiaContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Capture Codec"), +}; diff --git a/ffmpeg/libavcodec/tscc2.c b/ffmpeg/libavcodec/tscc2.c new file mode 100644 index 0000000..f275ff9 --- /dev/null +++ b/ffmpeg/libavcodec/tscc2.c @@ -0,0 +1,377 @@ +/* + * TechSmith Screen Codec 2 (aka Dora) decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * TechSmith Screen Codec 2 decoder + */ + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "get_bits.h" +#include "bytestream.h" +#include "internal.h" +#include "tscc2data.h" + +typedef struct TSCC2Context { + AVCodecContext *avctx; + AVFrame pic; + int mb_width, mb_height; + uint8_t *slice_quants; + int quant[2]; + int q[2][3]; + GetBitContext gb; + + VLC dc_vlc, nc_vlc[NUM_VLC_SETS], ac_vlc[NUM_VLC_SETS]; + int block[16]; +} TSCC2Context; + +static av_cold void free_vlcs(TSCC2Context *c) +{ + int i; + + ff_free_vlc(&c->dc_vlc); + for (i = 0; i < NUM_VLC_SETS; i++) { + ff_free_vlc(c->nc_vlc + i); + ff_free_vlc(c->ac_vlc + i); + } +} + +static av_cold int init_vlcs(TSCC2Context *c) +{ + int i, ret; + + ret = ff_init_vlc_sparse(&c->dc_vlc, 9, DC_VLC_COUNT, + tscc2_dc_vlc_bits, 1, 1, + tscc2_dc_vlc_codes, 2, 2, + tscc2_dc_vlc_syms, 2, 2, INIT_VLC_LE); + if (ret) + return ret; + + for (i = 0; i < NUM_VLC_SETS; i++) { + ret = ff_init_vlc_sparse(c->nc_vlc + i, 9, 16, + tscc2_nc_vlc_bits[i], 1, 1, + tscc2_nc_vlc_codes[i], 2, 2, + tscc2_nc_vlc_syms, 1, 1, INIT_VLC_LE); + if (ret) { + free_vlcs(c); + return ret; + } + ret = ff_init_vlc_sparse(c->ac_vlc + i, 9, tscc2_ac_vlc_sizes[i], + tscc2_ac_vlc_bits[i], 1, 1, + tscc2_ac_vlc_codes[i], 2, 2, + tscc2_ac_vlc_syms[i], 2, 2, INIT_VLC_LE); + if (ret) { + free_vlcs(c); + return ret; + } + } + + return 0; +} + +#define DEQUANT(val, q) ((q * val + 0x80) >> 8) +#define DCT1D(d0, d1, d2, d3, s0, s1, s2, s3, OP) \ + OP(d0, 5 * ((s0) + (s1) + (s2)) + 2 * (s3)); \ + OP(d1, 5 * ((s0) - (s2) - (s3)) + 2 * (s1)); \ + OP(d2, 5 * ((s0) - (s2) + (s3)) - 2 * (s1)); \ + OP(d3, 5 * ((s0) - (s1) + (s2)) - 2 * (s3)); \ + +#define COL_OP(a, b) a = b +#define ROW_OP(a, b) a = ((b) + 0x20) >> 6 + +static void tscc2_idct4_put(int *in, int q[3], uint8_t *dst, int stride) +{ + int i; + int tblk[4 * 4]; + int t0, t1, t2, t3; + + for (i = 0; i < 4; i++) { + t0 = DEQUANT(q[0 + (i & 1)], in[0 * 4 + i]); + t1 = DEQUANT(q[1 + (i & 1)], in[1 * 4 + i]); + t2 = DEQUANT(q[0 + (i & 1)], in[2 * 4 + i]); + t3 = DEQUANT(q[1 + (i & 1)], in[3 * 4 + i]); + DCT1D(tblk[0 * 4 + i], tblk[1 * 4 + i], + tblk[2 * 4 + i], tblk[3 * 4 + i], + t0, t1, t2, t3, COL_OP); + } + for (i = 0; i < 4; i++) { + DCT1D(dst[0], dst[1], dst[2], dst[3], + tblk[i * 4 + 0], tblk[i * 4 + 1], + tblk[i * 4 + 2], tblk[i * 4 + 3], ROW_OP); + dst += stride; + } +} + +static int tscc2_decode_mb(TSCC2Context *c, int *q, int vlc_set, + uint8_t *dst, int stride, int plane) +{ + GetBitContext *gb = &c->gb; + int prev_dc, dc, nc, ac, bpos, val; + int i, j, k, l; + + if (get_bits1(gb)) { + if (get_bits1(gb)) { + val = get_bits(gb, 8); + for (i = 0; i < 8; i++, dst += stride) + memset(dst, val, 16); + } else { + if (get_bits_left(gb) < 16 * 8 * 8) + return AVERROR_INVALIDDATA; + for (i = 0; i < 8; i++) { + for (j = 0; j < 16; j++) + dst[j] = get_bits(gb, 8); + dst += stride; + } + } + return 0; + } + + prev_dc = 0; + for (j = 0; j < 2; j++) { + for (k = 0; k < 4; k++) { + if (!(j | k)) { + dc = get_bits(gb, 8); + } else { + dc = get_vlc2(gb, c->dc_vlc.table, 9, 2); + if (dc == -1) + return AVERROR_INVALIDDATA; + if (dc == 0x100) + dc = get_bits(gb, 8); + } + dc = (dc + prev_dc) & 0xFF; + prev_dc = dc; + c->block[0] = dc; + + nc = get_vlc2(gb, c->nc_vlc[vlc_set].table, 9, 1); + if (nc == -1) + return AVERROR_INVALIDDATA; + + bpos = 1; + memset(c->block + 1, 0, 15 * sizeof(*c->block)); + for (l = 0; l < nc; l++) { + ac = get_vlc2(gb, c->ac_vlc[vlc_set].table, 9, 2); + if (ac == -1) + return AVERROR_INVALIDDATA; + if (ac == 0x1000) + ac = get_bits(gb, 12); + bpos += ac & 0xF; + if (bpos >= 16) + return AVERROR_INVALIDDATA; + val = sign_extend(ac >> 4, 8); + c->block[tscc2_zigzag[bpos++]] = val; + } + tscc2_idct4_put(c->block, q, dst + k * 4, stride); + } + dst += 4 * stride; + } + return 0; +} + +static int tscc2_decode_slice(TSCC2Context *c, int mb_y, + const uint8_t *buf, int buf_size) +{ + int i, mb_x, q, ret; + int off; + + init_get_bits(&c->gb, buf, buf_size * 8); + + for (mb_x = 0; mb_x < c->mb_width; mb_x++) { + q = c->slice_quants[mb_x + c->mb_width * mb_y]; + + if (q == 0 || q == 3) // skip block + continue; + for (i = 0; i < 3; i++) { + off = mb_x * 16 + mb_y * 8 * c->pic.linesize[i]; + ret = tscc2_decode_mb(c, c->q[q - 1], c->quant[q - 1] - 2, + c->pic.data[i] + off, c->pic.linesize[i], i); + if (ret) + return ret; + } + } + + return 0; +} + +static int tscc2_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + TSCC2Context *c = avctx->priv_data; + GetByteContext gb; + uint32_t frame_type, size; + int i, val, len, pos = 0; + int num_mb = c->mb_width * c->mb_height; + int ret; + + bytestream2_init(&gb, buf, buf_size); + frame_type = bytestream2_get_byte(&gb); + if (frame_type > 1) { + av_log(avctx, AV_LOG_ERROR, "Incorrect frame type %d\n", frame_type); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_reget_buffer(avctx, &c->pic)) < 0) + return ret; + + if (frame_type == 0) { + *got_frame = 1; + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + return buf_size; + } + + if (bytestream2_get_bytes_left(&gb) < 4) { + av_log(avctx, AV_LOG_ERROR, "Frame is too short\n"); + return AVERROR_INVALIDDATA; + } + + c->quant[0] = bytestream2_get_byte(&gb); + c->quant[1] = bytestream2_get_byte(&gb); + if (c->quant[0] < 2 || c->quant[0] > NUM_VLC_SETS + 1 || + c->quant[1] < 2 || c->quant[1] > NUM_VLC_SETS + 1) { + av_log(avctx, AV_LOG_ERROR, "Invalid quantisers %d / %d\n", + c->quant[0], c->quant[1]); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < 3; i++) { + c->q[0][i] = tscc2_quants[c->quant[0] - 2][i]; + c->q[1][i] = tscc2_quants[c->quant[1] - 2][i]; + } + + bytestream2_skip(&gb, 1); + + size = bytestream2_get_le32(&gb); + if (size > bytestream2_get_bytes_left(&gb)) { + av_log(avctx, AV_LOG_ERROR, "Slice properties chunk is too large\n"); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < size; i++) { + val = bytestream2_get_byte(&gb); + len = val & 0x3F; + val >>= 6; + if (pos + len > num_mb) { + av_log(avctx, AV_LOG_ERROR, "Too many slice properties\n"); + return AVERROR_INVALIDDATA; + } + memset(c->slice_quants + pos, val, len); + pos += len; + } + if (pos < num_mb) { + av_log(avctx, AV_LOG_ERROR, "Too few slice properties (%d / %d)\n", + pos, num_mb); + return AVERROR_INVALIDDATA; + } + + for (i = 0; i < c->mb_height; i++) { + size = bytestream2_peek_byte(&gb); + if (size & 1) { + size = bytestream2_get_byte(&gb) - 1; + } else { + size = bytestream2_get_le32(&gb) >> 1; + } + if (!size) { + int skip_row = 1, j, off = i * c->mb_width; + for (j = 0; j < c->mb_width; j++) { + if (c->slice_quants[off + j] == 1 || + c->slice_quants[off + j] == 2) { + skip_row = 0; + break; + } + } + if (!skip_row) { + av_log(avctx, AV_LOG_ERROR, "Non-skip row with zero size\n"); + return AVERROR_INVALIDDATA; + } + } + if (bytestream2_get_bytes_left(&gb) < size) { + av_log(avctx, AV_LOG_ERROR, "Invalid slice size (%d/%d)\n", + size, bytestream2_get_bytes_left(&gb)); + return AVERROR_INVALIDDATA; + } + ret = tscc2_decode_slice(c, i, buf + bytestream2_tell(&gb), size); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error decoding slice %d\n", i); + return ret; + } + bytestream2_skip(&gb, size); + } + + *got_frame = 1; + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int tscc2_decode_init(AVCodecContext *avctx) +{ + TSCC2Context * const c = avctx->priv_data; + int ret; + + c->avctx = avctx; + + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + + if ((ret = init_vlcs(c)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n"); + return ret; + } + + c->mb_width = FFALIGN(avctx->width, 16) >> 4; + c->mb_height = FFALIGN(avctx->height, 8) >> 3; + c->slice_quants = av_malloc(c->mb_width * c->mb_height); + if (!c->slice_quants) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate slice information\n"); + free_vlcs(c); + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int tscc2_decode_end(AVCodecContext *avctx) +{ + TSCC2Context * const c = avctx->priv_data; + + av_frame_unref(&c->pic); + av_freep(&c->slice_quants); + free_vlcs(c); + + return 0; +} + +AVCodec ff_tscc2_decoder = { + .name = "tscc2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TSCC2, + .priv_data_size = sizeof(TSCC2Context), + .init = tscc2_decode_init, + .close = tscc2_decode_end, + .decode = tscc2_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Codec 2"), +}; diff --git a/ffmpeg/libavcodec/tscc2data.h b/ffmpeg/libavcodec/tscc2data.h new file mode 100644 index 0000000..4586da7 --- /dev/null +++ b/ffmpeg/libavcodec/tscc2data.h @@ -0,0 +1,935 @@ +/* + * TechSmith Screen Codec 2 (aka Dora) decoder + * Copyright (c) 2012 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_TSCC2_DATA_H +#define AVCODEC_TSCC2_DATA_H + +#include + +static const uint8_t tscc2_zigzag[16] = { + 0, 1, 4, 8, + 5, 2, 3, 6, + 9, 12, 13, 10, + 7, 11, 14, 15 +}; + +#define NUM_VLC_SETS 13 + +static const uint16_t tscc2_quants[NUM_VLC_SETS][3] = { + { 655, 861, 1130 }, { 983, 1291, 1695 }, { 1311, 1721, 2260 }, + { 1638, 2151, 2825 }, { 1966, 2582, 3390 }, { 2294, 3012, 3955 }, + { 2621, 3442, 4520 }, { 2949, 3872, 5085 }, { 3277, 4303, 5650 }, + { 3604, 4733, 6215 }, { 3932, 5163, 6780 }, { 4260, 5593, 7345 }, + { 4588, 6024, 7910 }, +}; + +#define DC_VLC_COUNT 47 + +static const uint16_t tscc2_dc_vlc_syms[DC_VLC_COUNT] = { + 0x100, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, + 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, + 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, + 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, +}; + +static const uint16_t tscc2_dc_vlc_codes[DC_VLC_COUNT] = { + 0x000A, 0x0000, 0x0006, 0x002E, 0x0002, 0x000E, 0x001A, 0x007E, + 0x004E, 0x005A, 0x00E2, 0x01BE, 0x01BA, 0x00BA, 0x0072, 0x0022, + 0x02BE, 0x00BE, 0x033A, 0x03F2, 0x01F2, 0x03A2, 0x0122, 0x0322, + 0x01A2, 0x0172, 0x0372, 0x013A, 0x00CE, 0x02CE, 0x02FE, 0x00FE, + 0x00A2, 0x00F2, 0x003A, 0x01CE, 0x01FE, 0x0062, 0x00DA, 0x003E, + 0x0032, 0x007A, 0x0012, 0x001E, 0x0016, 0x0004, 0x0001, +}; + +static const uint8_t tscc2_dc_vlc_bits[DC_VLC_COUNT] = { + 5, 3, 5, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 9, 9, 9, 9, 9, 8, 8, 8, + 7, 7, 6, 6, 5, 3, 1, +}; + +static const uint8_t tscc2_nc_vlc_syms[16] = { + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, +}; + +static const uint16_t tscc2_nc_vlc_codes[NUM_VLC_SETS][16] = { + { 0x0023, 0x0003, 0x0031, 0x0021, 0x0011, 0x0053, 0x0013, 0x0001, + 0x0009, 0x0029, 0x0033, 0x0019, 0x000B, 0x0005, 0x0007, 0x0000, }, + { 0x0030, 0x0022, 0x0028, 0x0020, 0x0008, 0x0000, 0x0032, 0x0072, + 0x0010, 0x0002, 0x0012, 0x0018, 0x000A, 0x0004, 0x0006, 0x0001, }, + { 0x0032, 0x0038, 0x0020, 0x0008, 0x0002, 0x0018, 0x0072, 0x0000, + 0x0028, 0x0022, 0x0012, 0x0010, 0x000A, 0x0004, 0x0006, 0x0001, }, + { 0x0032, 0x0010, 0x0072, 0x0030, 0x0022, 0x0038, 0x0008, 0x0028, + 0x0018, 0x0002, 0x0012, 0x0000, 0x000A, 0x0004, 0x0006, 0x0001, }, + { 0x0012, 0x0052, 0x0000, 0x0020, 0x0018, 0x0022, 0x0008, 0x0028, + 0x0038, 0x0002, 0x0032, 0x0010, 0x000A, 0x0004, 0x0006, 0x0001, }, + { 0x0016, 0x0096, 0x0006, 0x0046, 0x0056, 0x0002, 0x0036, 0x0076, + 0x0012, 0x0022, 0x0032, 0x0026, 0x000A, 0x000E, 0x0000, 0x0001, }, + { 0x001A, 0x009A, 0x0032, 0x0072, 0x005A, 0x007A, 0x003A, 0x0002, + 0x0012, 0x0022, 0x000A, 0x002A, 0x0006, 0x000E, 0x0000, 0x0001, }, + { 0x002A, 0x00AA, 0x0002, 0x0042, 0x006A, 0x003A, 0x007A, 0x0022, + 0x0032, 0x0012, 0x000A, 0x001A, 0x0006, 0x000E, 0x0000, 0x0001, }, + { 0x0042, 0x00C2, 0x0002, 0x000A, 0x004A, 0x003A, 0x007A, 0x0022, + 0x0012, 0x0032, 0x002A, 0x001A, 0x0006, 0x000E, 0x0000, 0x0001, }, + { 0x00BA, 0x01BA, 0x003A, 0x0012, 0x0052, 0x007A, 0x0002, 0x0022, + 0x0032, 0x000A, 0x002A, 0x001A, 0x0000, 0x0004, 0x0006, 0x0001, }, + { 0x00AA, 0x01AA, 0x002A, 0x0022, 0x0062, 0x006A, 0x0002, 0x0012, + 0x0032, 0x000A, 0x001A, 0x003A, 0x0000, 0x0004, 0x0006, 0x0001, }, + { 0x00AA, 0x01AA, 0x002A, 0x0022, 0x0062, 0x006A, 0x0002, 0x0012, + 0x0032, 0x000A, 0x003A, 0x001A, 0x0000, 0x0004, 0x0006, 0x0001, }, + { 0x008A, 0x018A, 0x000A, 0x0022, 0x0062, 0x004A, 0x0002, 0x0012, + 0x0032, 0x002A, 0x001A, 0x003A, 0x0000, 0x0004, 0x0006, 0x0001, }, +}; + +static const uint8_t tscc2_nc_vlc_bits[NUM_VLC_SETS][16] = { + { 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, + { 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 6, 5, 4, 3, 3, 1 }, + { 7, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, + { 7, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, + { 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4, 3, 3, 1 }, + { 8, 8, 7, 7, 7, 6, 7, 7, 6, 6, 6, 6, 4, 4, 2, 1 }, + { 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 4, 4, 2, 1 }, + { 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 4, 4, 2, 1 }, + { 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 4, 4, 2, 1 }, + { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, + { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, + { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, + { 9, 9, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 3, 3, 3, 1 }, +}; + +static const uint16_t ac_vlc_desc0_syms[172] = { + 0x1000, 0xFF8, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, + 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, + 0xFD6, 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, 0xFC5, + 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB2, 0xFB1, + 0xFB0, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, 0xF91, 0xF90, + 0xF83, 0xF81, 0xF80, 0xF73, 0xF71, 0xF70, 0xF61, 0xF60, + 0xF51, 0xF50, 0xF45, 0xF41, 0xF40, 0xF31, 0xF30, 0xF21, + 0xF20, 0xF10, 0xF00, 0xEF0, 0xEE0, 0xED5, 0xED1, 0xED0, + 0xEC0, 0xEB0, 0xEA0, 0xE90, 0xE80, 0xE70, 0xE60, 0xE50, + 0xE40, 0xE30, 0xE20, 0xE10, 0xE00, 0xDF0, 0xDE0, 0xDD0, + 0xDC0, 0xDB0, 0xDA0, 0xD90, 0xD80, 0xD60, 0xCD1, 0x280, + 0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200, + 0x1F0, 0x1E0, 0x1D0, 0x1C0, 0x1B0, 0x1A1, 0x1A0, 0x190, + 0x180, 0x170, 0x160, 0x150, 0x140, 0x130, 0x121, 0x120, + 0x111, 0x110, 0x101, 0x100, 0x0F1, 0x0F0, 0x0E1, 0x0E0, + 0x0D1, 0x0D0, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A5, 0x0A1, + 0x0A0, 0x091, 0x090, 0x081, 0x080, 0x075, 0x071, 0x070, + 0x065, 0x063, 0x061, 0x060, 0x055, 0x053, 0x052, 0x051, + 0x050, 0x046, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, + 0x035, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, + 0x023, 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, + 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc0_codes[172] = { + 0x001F, 0x0D71, 0x013F, 0x006C, 0x00A7, 0x0067, 0x001C, 0x0008, + 0x0005, 0x06F1, 0x002C, 0x04BA, 0x0072, 0x01AA, 0x0002, 0x0006, + 0x06AC, 0x02AF, 0x06EF, 0x018F, 0x000A, 0x0009, 0x02AC, 0x042A, + 0x06E1, 0x068F, 0x00B1, 0x0000, 0x0317, 0x0C17, 0x0612, 0x010F, + 0x0011, 0x0FBA, 0x002A, 0x0172, 0x000C, 0x05AC, 0x03D7, 0x0037, + 0x0E8F, 0x02F2, 0x0041, 0x0BE1, 0x057F, 0x004A, 0x00AF, 0x006F, + 0x06AA, 0x0097, 0x0101, 0x0012, 0x0081, 0x0571, 0x0092, 0x0EAF, + 0x01BF, 0x00D7, 0x0031, 0x0001, 0x01F2, 0x0F17, 0x053A, 0x00BF, + 0x038F, 0x0217, 0x0371, 0x01F1, 0x01BA, 0x022A, 0x02BF, 0x028F, + 0x008F, 0x03F1, 0x00E1, 0x00BA, 0x00F2, 0x0EBF, 0x06AF, 0x048F, + 0x0FE1, 0x0271, 0x07BA, 0x0D3A, 0x0C12, 0x08AC, 0x0717, 0x00AC, + 0x0412, 0x0901, 0x04E1, 0x07E1, 0x0417, 0x0CAF, 0x04AC, 0x01AC, + 0x04F2, 0x03BA, 0x05D7, 0x07F1, 0x01D7, 0x04AF, 0x04EF, 0x03AC, + 0x00AA, 0x01E1, 0x0071, 0x00F1, 0x012C, 0x03EF, 0x082A, 0x0112, + 0x03E1, 0x01FA, 0x0DAC, 0x0131, 0x0E12, 0x000F, 0x0B17, 0x007F, + 0x0AEF, 0x007A, 0x02AA, 0x0061, 0x0671, 0x0027, 0x013A, 0x058F, + 0x00FF, 0x033A, 0x0032, 0x0301, 0x0021, 0x0C8F, 0x037F, 0x0077, + 0x02F1, 0x02E1, 0x003A, 0x003C, 0x0212, 0x0817, 0x0CE1, 0x003F, + 0x0007, 0x0017, 0x0501, 0x02BA, 0x06BF, 0x0057, 0x0010, 0x02EF, + 0x0117, 0x017F, 0x00EF, 0x006A, 0x0019, 0x0171, 0x01EF, 0x06BA, + 0x012A, 0x00FA, 0x0022, 0x000E, 0x0AE1, 0x01AF, 0x0052, 0x002F, + 0x004F, 0x001A, 0x0004, 0x0003, +}; + +static const uint8_t ac_vlc_desc0_bits[172] = { + 6, 12, 9, 7, 8, 7, 6, 4, + 3, 11, 9, 11, 9, 9, 6, 4, + 11, 11, 11, 11, 7, 5, 11, 11, + 11, 12, 8, 5, 12, 12, 12, 9, + 6, 12, 12, 9, 6, 12, 10, 7, + 12, 10, 7, 12, 11, 7, 11, 8, + 11, 8, 12, 11, 8, 12, 8, 12, + 9, 9, 9, 9, 9, 12, 12, 10, + 10, 10, 10, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 11, 12, 12, 12, + 12, 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 11, 11, 11, 12, 11, 10, + 10, 10, 10, 10, 9, 10, 12, 9, + 12, 9, 12, 9, 12, 9, 12, 9, + 12, 8, 11, 8, 11, 8, 11, 11, + 8, 10, 7, 10, 7, 12, 10, 7, + 11, 12, 9, 6, 11, 12, 12, 9, + 6, 12, 11, 11, 12, 8, 5, 12, + 10, 11, 11, 7, 5, 11, 10, 11, + 9, 9, 6, 4, 12, 9, 7, 8, + 7, 6, 4, 3, +}; + +static const uint16_t ac_vlc_desc1_syms[169] = { + 0x1000, 0xFF8, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, + 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, + 0xFD6, 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, 0xFC5, + 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, 0xFB2, + 0xFB1, 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, + 0xF93, 0xF91, 0xF90, 0xF85, 0xF81, 0xF80, 0xF71, 0xF70, + 0xF61, 0xF60, 0xF51, 0xF50, 0xF45, 0xF41, 0xF40, 0xF31, + 0xF30, 0xF21, 0xF20, 0xF11, 0xF10, 0xF01, 0xF00, 0xEF1, + 0xEF0, 0xEE1, 0xEE0, 0xED0, 0xEC6, 0xEC0, 0xEB6, 0xEB0, + 0xEA0, 0xE90, 0xE80, 0xE70, 0xE60, 0xE50, 0xE40, 0xE33, + 0xE31, 0xE30, 0xE20, 0xE10, 0xE00, 0xDF0, 0xDE1, 0xDE0, + 0xDC0, 0xDB0, 0xDA0, 0x250, 0x240, 0x1F0, 0x1E0, 0x1D0, + 0x1C0, 0x1B0, 0x1A0, 0x190, 0x180, 0x170, 0x160, 0x150, + 0x140, 0x130, 0x120, 0x111, 0x110, 0x101, 0x100, 0x0F1, + 0x0F0, 0x0E1, 0x0E0, 0x0D1, 0x0D0, 0x0C6, 0x0C1, 0x0C0, + 0x0B1, 0x0B0, 0x0A1, 0x0A0, 0x095, 0x091, 0x090, 0x085, + 0x081, 0x080, 0x075, 0x071, 0x070, 0x065, 0x063, 0x061, + 0x060, 0x055, 0x053, 0x052, 0x051, 0x050, 0x046, 0x045, + 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, 0x033, 0x032, + 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, + 0x020, 0x018, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, + 0x010, +}; + +static const uint16_t ac_vlc_desc1_codes[169] = { + 0x0019, 0x027D, 0x0084, 0x0044, 0x009D, 0x003D, 0x000A, 0x0002, + 0x0003, 0x00EA, 0x02FD, 0x017A, 0x01C6, 0x00B6, 0x0026, 0x000E, + 0x0095, 0x0260, 0x032A, 0x0360, 0x0006, 0x0005, 0x05B6, 0x036A, + 0x06F6, 0x0704, 0x00FA, 0x0010, 0x0279, 0x04D4, 0x00F6, 0x066A, + 0x001D, 0x0029, 0x05F9, 0x0846, 0x04F6, 0x01D4, 0x0038, 0x0446, + 0x0160, 0x031D, 0x0075, 0x0054, 0x02D4, 0x005A, 0x05FD, 0x0040, + 0x06EA, 0x0055, 0x0460, 0x009A, 0x052A, 0x00A0, 0x00D8, 0x0380, + 0x017D, 0x092A, 0x00F9, 0x0D7A, 0x0179, 0x0304, 0x002A, 0x0104, + 0x01A0, 0x0780, 0x007D, 0x03F9, 0x0C46, 0x03EA, 0x0E6A, 0x0204, + 0x01FD, 0x051D, 0x02AA, 0x05EA, 0x00AA, 0x0080, 0x067D, 0x09EA, + 0x0C95, 0x09F9, 0x07B6, 0x0DB6, 0x012A, 0x0904, 0x0454, 0x0FB6, + 0x0960, 0x08D4, 0x0495, 0x0F80, 0x0560, 0x0B04, 0x057A, 0x0079, + 0x0795, 0x0E7D, 0x0060, 0x076A, 0x03B6, 0x0395, 0x0180, 0x02A0, + 0x006A, 0x0195, 0x0295, 0x0646, 0x03FD, 0x01F9, 0x0154, 0x0DF9, + 0x00C6, 0x0F95, 0x01F6, 0x0480, 0x0000, 0x0A79, 0x04AA, 0x00E0, + 0x0246, 0x001A, 0x0479, 0x0015, 0x0D60, 0x0280, 0x0018, 0x01EA, + 0x037A, 0x003A, 0x011D, 0x00FD, 0x0035, 0x0A7D, 0x04A0, 0x0146, + 0x0024, 0x01B6, 0x0504, 0x0046, 0x0020, 0x0009, 0x00D4, 0x03AA, + 0x0679, 0x026A, 0x0036, 0x0008, 0x02F6, 0x01AA, 0x016A, 0x0254, + 0x0039, 0x000D, 0x0004, 0x0176, 0x02EA, 0x007A, 0x0076, 0x0016, + 0x0001, 0x0879, 0x0058, 0x0014, 0x00D5, 0x005D, 0x0034, 0x000C, + 0x0007, +}; + +static const uint8_t ac_vlc_desc1_bits[169] = { + 6, 12, 8, 7, 8, 7, 6, 4, + 3, 10, 10, 11, 9, 9, 6, 4, + 11, 10, 10, 10, 7, 5, 12, 11, + 11, 11, 8, 5, 12, 11, 11, 12, + 9, 6, 12, 12, 11, 9, 6, 12, + 12, 10, 7, 11, 10, 7, 11, 7, + 11, 8, 11, 8, 11, 11, 8, 11, + 9, 12, 9, 12, 9, 12, 9, 12, + 9, 12, 10, 10, 12, 10, 12, 10, + 11, 11, 10, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 11, 11, 11, 11, 10, 10, + 10, 10, 10, 11, 10, 12, 9, 12, + 9, 12, 9, 11, 8, 12, 11, 8, + 11, 8, 11, 8, 12, 10, 7, 12, + 10, 7, 11, 10, 7, 12, 11, 9, + 6, 11, 11, 12, 8, 6, 12, 10, + 11, 11, 8, 5, 11, 10, 10, 10, + 7, 5, 10, 9, 11, 9, 9, 6, + 4, 12, 8, 7, 8, 7, 6, 4, + 3, +}; + +static const uint16_t ac_vlc_desc2_syms[165] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD6, 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, + 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, + 0xFB2, 0xFB1, 0xFB0, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, + 0xF93, 0xF91, 0xF90, 0xF81, 0xF80, 0xF75, 0xF71, 0xF70, + 0xF61, 0xF60, 0xF51, 0xF50, 0xF41, 0xF40, 0xF36, 0xF31, + 0xF30, 0xF26, 0xF21, 0xF20, 0xF16, 0xF11, 0xF10, 0xF06, + 0xF01, 0xF00, 0xEF1, 0xEF0, 0xEE1, 0xEE0, 0xED0, 0xEC0, + 0xEB3, 0xEB1, 0xEB0, 0xEA3, 0xEA1, 0xEA0, 0xE90, 0xE81, + 0xE80, 0xE71, 0xE70, 0xE61, 0xE60, 0xE50, 0xE40, 0xE30, + 0xE10, 0xE00, 0x241, 0x240, 0x231, 0x1D0, 0x1C0, 0x1B3, + 0x1B0, 0x1A0, 0x190, 0x180, 0x170, 0x160, 0x150, 0x140, + 0x130, 0x120, 0x110, 0x100, 0x0F0, 0x0E0, 0x0D1, 0x0D0, + 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A5, 0x0A1, 0x0A0, 0x096, + 0x095, 0x091, 0x090, 0x086, 0x085, 0x081, 0x080, 0x075, + 0x071, 0x070, 0x065, 0x063, 0x061, 0x060, 0x055, 0x053, + 0x052, 0x051, 0x050, 0x045, 0x043, 0x042, 0x041, 0x040, + 0x036, 0x035, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, + 0x024, 0x023, 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, + 0x014, 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc2_codes[165] = { + 0x0034, 0x059C, 0x0280, 0x001C, 0x004C, 0x00BD, 0x0020, 0x003C, + 0x000A, 0x0003, 0x00FD, 0x008C, 0x0332, 0x01D5, 0x0055, 0x003E, + 0x0001, 0x07E4, 0x0264, 0x00B2, 0x00A2, 0x005C, 0x0005, 0x02A2, + 0x011D, 0x0132, 0x076C, 0x0012, 0x0018, 0x01E4, 0x05E4, 0x02B2, + 0x0432, 0x017D, 0x000E, 0x055D, 0x0955, 0x0164, 0x0028, 0x0D62, + 0x0B24, 0x02DE, 0x001E, 0x0340, 0x0014, 0x0555, 0x0180, 0x00DD, + 0x01B2, 0x0092, 0x036C, 0x00EC, 0x00E4, 0x00C0, 0x0C64, 0x095D, + 0x01DE, 0x0AE4, 0x0C32, 0x01A2, 0x06E4, 0x0832, 0x01A4, 0x015D, + 0x0732, 0x031D, 0x0F9C, 0x03E2, 0x09E2, 0x02FD, 0x0224, 0x051D, + 0x02E4, 0x019C, 0x05B2, 0x0355, 0x0064, 0x016C, 0x038C, 0x0880, + 0x0480, 0x06B2, 0x0540, 0x0080, 0x075D, 0x0155, 0x0424, 0x0680, + 0x0A62, 0x0A80, 0x078C, 0x0D9C, 0x0F8C, 0x0562, 0x0FF2, 0x0464, + 0x0B55, 0x01E2, 0x0032, 0x07F2, 0x0140, 0x03E4, 0x0662, 0x0755, + 0x0380, 0x026C, 0x0232, 0x001D, 0x0040, 0x00E2, 0x035D, 0x00F2, + 0x0162, 0x01FD, 0x03F2, 0x000C, 0x0EA2, 0x05F2, 0x0072, 0x04E4, + 0x0F32, 0x018C, 0x009D, 0x0324, 0x079C, 0x006C, 0x0054, 0x0F5D, + 0x021D, 0x0015, 0x0024, 0x06A2, 0x009C, 0x0004, 0x0062, 0x056C, + 0x0262, 0x0000, 0x002E, 0x01F2, 0x0124, 0x039C, 0x005E, 0x0010, + 0x0724, 0x00A4, 0x00DE, 0x0362, 0x0052, 0x000D, 0x03B2, 0x007D, + 0x05E2, 0x00D5, 0x005D, 0x0035, 0x0009, 0x099C, 0x0022, 0x002C, + 0x003D, 0x0008, 0x0002, 0x0006, 0x0007, +}; + +static const uint8_t ac_vlc_desc2_bits[165] = { + 6, 12, 12, 8, 7, 8, 6, 6, + 4, 3, 10, 9, 11, 9, 9, 6, + 4, 11, 10, 10, 10, 7, 5, 11, + 11, 10, 11, 8, 5, 11, 11, 11, + 12, 9, 6, 11, 12, 9, 6, 12, + 12, 10, 7, 10, 7, 11, 10, 8, + 11, 8, 11, 8, 11, 8, 12, 12, + 9, 12, 12, 9, 11, 12, 9, 12, + 12, 10, 12, 10, 12, 10, 10, 11, + 12, 12, 11, 12, 11, 11, 11, 12, + 11, 11, 11, 12, 12, 12, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 11, + 10, 10, 10, 10, 9, 9, 11, 9, + 11, 9, 11, 8, 12, 11, 8, 11, + 12, 10, 8, 12, 12, 10, 7, 12, + 10, 7, 11, 12, 9, 6, 10, 11, + 12, 8, 6, 11, 10, 11, 8, 5, + 11, 9, 10, 10, 7, 5, 10, 9, + 11, 9, 9, 6, 4, 12, 8, 7, + 8, 6, 6, 4, 3, +}; + +static const uint16_t ac_vlc_desc3_syms[162] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD6, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, + 0xFC6, 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, + 0xFB2, 0xFB1, 0xFB0, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF95, + 0xF93, 0xF91, 0xF90, 0xF85, 0xF83, 0xF81, 0xF80, 0xF71, + 0xF70, 0xF66, 0xF61, 0xF60, 0xF56, 0xF51, 0xF50, 0xF46, + 0xF41, 0xF40, 0xF36, 0xF31, 0xF30, 0xF26, 0xF21, 0xF20, + 0xF11, 0xF10, 0xF01, 0xF00, 0xEF3, 0xEF1, 0xEF0, 0xEE3, + 0xEE1, 0xEE0, 0xED3, 0xED1, 0xED0, 0xEC1, 0xEC0, 0xEB1, + 0xEB0, 0xEA0, 0xE90, 0xE80, 0xE70, 0x1E1, 0x1D1, 0x1D0, + 0x1C1, 0x1B1, 0x1A1, 0x180, 0x170, 0x163, 0x160, 0x150, + 0x140, 0x130, 0x123, 0x120, 0x113, 0x110, 0x100, 0x0F0, + 0x0E0, 0x0D1, 0x0D0, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A1, + 0x0A0, 0x095, 0x091, 0x090, 0x085, 0x081, 0x080, 0x076, + 0x075, 0x073, 0x071, 0x070, 0x066, 0x065, 0x063, 0x061, + 0x060, 0x055, 0x053, 0x052, 0x051, 0x050, 0x045, 0x043, + 0x042, 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, + 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, + 0x020, 0x018, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, + 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc3_codes[162] = { + 0x001D, 0x087C, 0x0AE8, 0x003A, 0x001C, 0x0008, 0x000C, 0x0032, + 0x0006, 0x0003, 0x03A5, 0x01EC, 0x01A5, 0x0080, 0x0030, 0x0005, + 0x0001, 0x0040, 0x03FC, 0x02D4, 0x0154, 0x02FC, 0x003C, 0x0015, + 0x051A, 0x0000, 0x02EC, 0x077C, 0x00D2, 0x0018, 0x03E8, 0x04EC, + 0x027C, 0x01FA, 0x0022, 0x0765, 0x0EA5, 0x0054, 0x0010, 0x08EC, + 0x0AAC, 0x03BA, 0x0042, 0x065D, 0x0AD4, 0x005C, 0x0028, 0x03C0, + 0x00E5, 0x035C, 0x04FA, 0x00DC, 0x06A5, 0x075C, 0x00C8, 0x05A5, + 0x04D4, 0x00BA, 0x01C0, 0x05E8, 0x012C, 0x00E8, 0x01B0, 0x00B0, + 0x025D, 0x002C, 0x0A52, 0x025C, 0x01E8, 0x00FA, 0x0348, 0x0652, + 0x0B7C, 0x0365, 0x031A, 0x0E52, 0x011A, 0x0200, 0x01BA, 0x02AC, + 0x06D4, 0x01FC, 0x05BA, 0x0DFC, 0x0248, 0x0EE8, 0x0B1A, 0x0CFC, + 0x0F65, 0x0B5C, 0x0DC0, 0x007C, 0x0548, 0x08A5, 0x00FC, 0x03B0, + 0x0148, 0x06AC, 0x0252, 0x071A, 0x02E8, 0x0240, 0x00AC, 0x021A, + 0x0140, 0x08E8, 0x01AC, 0x00EC, 0x0152, 0x00A5, 0x0068, 0x001A, + 0x006C, 0x05C0, 0x015C, 0x0025, 0x05B0, 0x017C, 0x0014, 0x047C, + 0x00D4, 0x06E8, 0x00C0, 0x0002, 0x0A5D, 0x04E8, 0x0A7C, 0x01D4, + 0x0020, 0x04A5, 0x07B0, 0x037C, 0x015D, 0x002A, 0x005D, 0x0048, + 0x067C, 0x007A, 0x0004, 0x04FC, 0x02FA, 0x0648, 0x0100, 0x0052, + 0x005A, 0x000D, 0x0165, 0x0065, 0x02A5, 0x0070, 0x00F0, 0x003D, + 0x0009, 0x05FC, 0x0E48, 0x009A, 0x0012, 0x00DD, 0x0034, 0x000A, + 0x000E, 0x0007, +}; + +static const uint8_t ac_vlc_desc3_bits[162] = { + 7, 12, 12, 8, 7, 7, 6, 6, + 4, 3, 10, 9, 11, 8, 8, 6, + 4, 10, 10, 12, 9, 10, 7, 5, + 11, 10, 10, 11, 8, 5, 10, 11, + 12, 9, 6, 12, 12, 9, 6, 12, + 12, 10, 7, 11, 12, 10, 7, 10, + 8, 12, 11, 8, 12, 11, 8, 11, + 11, 9, 11, 11, 9, 12, 11, 9, + 12, 9, 12, 10, 11, 11, 10, 12, + 12, 11, 12, 12, 11, 10, 11, 12, + 11, 11, 11, 12, 11, 12, 12, 12, + 12, 12, 12, 12, 11, 12, 11, 11, + 11, 11, 12, 11, 12, 10, 10, 10, + 9, 12, 9, 12, 9, 12, 8, 10, + 8, 12, 10, 8, 11, 10, 7, 11, + 11, 12, 9, 7, 12, 11, 12, 9, + 6, 11, 11, 12, 9, 6, 10, 10, + 11, 8, 5, 12, 10, 12, 9, 10, + 7, 5, 10, 9, 11, 8, 8, 6, + 4, 12, 12, 8, 7, 8, 6, 6, + 4, 3, +}; + +static const uint16_t ac_vlc_desc4_syms[131] = { + 0x1000, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, 0xFF0, + 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, 0xFD6, + 0xFD5, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, 0xFC3, 0xFC2, + 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, 0xFB0, 0xFA5, 0xFA3, + 0xFA1, 0xFA0, 0xF93, 0xF91, 0xF90, 0xF81, 0xF80, 0xF76, + 0xF71, 0xF70, 0xF66, 0xF61, 0xF60, 0xF56, 0xF51, 0xF50, + 0xF41, 0xF40, 0xF31, 0xF30, 0xF23, 0xF21, 0xF20, 0xF13, + 0xF11, 0xF10, 0xF03, 0xF01, 0xF00, 0xEF1, 0xEF0, 0xEE0, + 0xED0, 0xEC0, 0xEB0, 0x191, 0x181, 0x180, 0x171, 0x161, + 0x140, 0x130, 0x123, 0x120, 0x110, 0x100, 0x0F3, 0x0F0, + 0x0E0, 0x0D0, 0x0C0, 0x0B1, 0x0B0, 0x0A1, 0x0A0, 0x091, + 0x090, 0x085, 0x081, 0x080, 0x075, 0x071, 0x070, 0x066, + 0x065, 0x063, 0x061, 0x060, 0x056, 0x055, 0x053, 0x051, + 0x050, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, + 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, + 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, 0x013, + 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc4_codes[131] = { + 0x006B, 0x00BE, 0x0052, 0x00F3, 0x005B, 0x003A, 0x0009, 0x0007, + 0x00DA, 0x03FB, 0x0123, 0x00B3, 0x01B3, 0x002E, 0x0006, 0x030A, + 0x005A, 0x004A, 0x034A, 0x0072, 0x0005, 0x02DA, 0x0173, 0x04FB, + 0x0032, 0x0013, 0x039B, 0x0B9B, 0x011E, 0x0002, 0x00FB, 0x021E, + 0x009B, 0x007E, 0x0E1A, 0x03CA, 0x007B, 0x02FB, 0x0033, 0x03AB, + 0x0463, 0x008A, 0x0773, 0x041E, 0x002B, 0x031B, 0x065A, 0x011A, + 0x060A, 0x01DA, 0x0963, 0x0323, 0x0BAB, 0x059E, 0x010A, 0x05AB, + 0x0CFB, 0x071B, 0x079E, 0x0F9E, 0x0263, 0x079B, 0x0563, 0x019E, + 0x01AB, 0x0E63, 0x029B, 0x04CA, 0x0DAB, 0x0663, 0x0B1B, 0x020A, + 0x0A1E, 0x021A, 0x0063, 0x061E, 0x06FB, 0x025A, 0x0163, 0x0573, + 0x000A, 0x0223, 0x011B, 0x0C1A, 0x015A, 0x0863, 0x00AB, 0x02CA, + 0x00B2, 0x0A0A, 0x01CA, 0x00A3, 0x0B73, 0x0023, 0x0012, 0x039E, + 0x001A, 0x0CCA, 0x01FB, 0x005E, 0x0A9B, 0x00CA, 0x0373, 0x009E, + 0x0022, 0x07AB, 0x001E, 0x0EFB, 0x009A, 0x000B, 0x041A, 0x019B, + 0x0363, 0x014A, 0x006A, 0x0015, 0x069B, 0x0073, 0x0523, 0x001B, + 0x012B, 0x0003, 0x0001, 0x061A, 0x003E, 0x002A, 0x00E3, 0x003B, + 0x000E, 0x000D, 0x0000, +}; + +static const uint8_t ac_vlc_desc4_bits[131] = { + 7, 8, 7, 8, 7, 6, 4, 3, + 10, 10, 11, 9, 9, 6, 4, 10, + 10, 9, 10, 7, 5, 10, 11, 12, + 8, 6, 12, 12, 9, 6, 11, 12, + 10, 7, 12, 10, 8, 11, 8, 12, + 11, 8, 11, 11, 9, 12, 11, 9, + 11, 9, 12, 10, 12, 11, 10, 12, + 12, 11, 12, 12, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 11, 12, 11, 12, 11, 12, 11, + 10, 10, 10, 12, 9, 12, 9, 10, + 8, 12, 10, 8, 12, 10, 7, 11, + 11, 12, 10, 7, 12, 11, 12, 9, + 6, 11, 11, 12, 8, 6, 12, 10, + 10, 10, 7, 5, 11, 9, 11, 9, + 9, 6, 4, 12, 8, 7, 8, 7, + 6, 4, 2, +}; + +static const uint16_t ac_vlc_desc5_syms[132] = { + 0x1000, 0xFF8, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, 0xFF1, + 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, 0xFE0, + 0xFD6, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, + 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, 0xFB0, + 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF93, 0xF91, 0xF90, 0xF86, + 0xF85, 0xF81, 0xF80, 0xF76, 0xF75, 0xF71, 0xF70, 0xF66, + 0xF61, 0xF60, 0xF51, 0xF50, 0xF43, 0xF41, 0xF40, 0xF33, + 0xF31, 0xF30, 0xF23, 0xF21, 0xF20, 0xF11, 0xF10, 0xF00, + 0xEF0, 0xEE0, 0xEC1, 0xEC0, 0x151, 0x141, 0x140, 0x131, + 0x121, 0x120, 0x111, 0x110, 0x103, 0x100, 0x0F0, 0x0E0, + 0x0D3, 0x0D0, 0x0C3, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A1, + 0x0A0, 0x091, 0x090, 0x081, 0x080, 0x075, 0x071, 0x070, + 0x065, 0x061, 0x060, 0x056, 0x055, 0x053, 0x052, 0x051, + 0x050, 0x046, 0x045, 0x043, 0x042, 0x041, 0x040, 0x035, + 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, + 0x023, 0x022, 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, + 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc5_codes[132] = { + 0x0001, 0x0D62, 0x00BD, 0x0022, 0x009B, 0x0032, 0x0019, 0x0005, + 0x0007, 0x034D, 0x009A, 0x012B, 0x0052, 0x006B, 0x003A, 0x0006, + 0x06FD, 0x017D, 0x081A, 0x031B, 0x031A, 0x0012, 0x0011, 0x0202, + 0x00FD, 0x051B, 0x00D2, 0x001D, 0x011A, 0x0782, 0x018D, 0x007B, + 0x067D, 0x037D, 0x0021, 0x0E8D, 0x0562, 0x008D, 0x00BB, 0x053D, + 0x082A, 0x0002, 0x000D, 0x0302, 0x007D, 0x053B, 0x003B, 0x0A4D, + 0x027D, 0x01FD, 0x042A, 0x01C2, 0x041A, 0x0182, 0x014D, 0x0162, + 0x00C2, 0x032A, 0x0D9A, 0x012A, 0x0102, 0x087D, 0x072B, 0x039A, + 0x0362, 0x019A, 0x0C62, 0x04C2, 0x0D1B, 0x028D, 0x0762, 0x0E7D, + 0x0E41, 0x059A, 0x024D, 0x093B, 0x052B, 0x011B, 0x064D, 0x013D, + 0x0382, 0x0262, 0x0641, 0x0462, 0x004D, 0x0CC2, 0x033B, 0x068D, + 0x0141, 0x0D2B, 0x001B, 0x0041, 0x00C1, 0x0C41, 0x01E2, 0x00EB, + 0x062A, 0x0082, 0x0061, 0x02FD, 0x047D, 0x013B, 0x002A, 0x003D, + 0x005B, 0x022A, 0x02C2, 0x0241, 0x0062, 0x00AA, 0x000B, 0x00E2, + 0x001A, 0x033D, 0x021A, 0x006A, 0x0009, 0x032B, 0x002B, 0x04FD, + 0x0042, 0x016B, 0x002D, 0x000E, 0x0441, 0x00CD, 0x005A, 0x00AB, + 0x000A, 0x0039, 0x0003, 0x0000, +}; + +static const uint8_t ac_vlc_desc5_bits[132] = { + 7, 12, 8, 7, 8, 6, 6, 4, + 3, 10, 9, 11, 8, 9, 6, 4, + 11, 10, 12, 10, 10, 7, 5, 10, + 11, 12, 8, 6, 10, 11, 9, 7, + 12, 10, 7, 12, 12, 10, 8, 11, + 12, 10, 8, 10, 12, 11, 9, 12, + 11, 9, 11, 9, 11, 10, 10, 11, + 11, 10, 12, 10, 10, 12, 11, 10, + 11, 11, 12, 12, 12, 11, 11, 12, + 12, 12, 12, 12, 12, 11, 11, 11, + 11, 10, 12, 12, 10, 12, 10, 12, + 9, 12, 9, 11, 8, 12, 9, 8, + 11, 9, 7, 11, 11, 12, 12, 9, + 7, 11, 10, 11, 11, 8, 6, 9, + 12, 10, 10, 7, 5, 11, 9, 11, + 8, 9, 6, 4, 12, 8, 7, 8, + 6, 6, 4, 2, +}; + +static const uint16_t ac_vlc_desc6_syms[130] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD6, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, + 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, + 0xFB0, 0xFA6, 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF95, 0xF93, + 0xF91, 0xF90, 0xF86, 0xF85, 0xF81, 0xF80, 0xF76, 0xF71, + 0xF70, 0xF63, 0xF61, 0xF60, 0xF53, 0xF51, 0xF50, 0xF43, + 0xF41, 0xF40, 0xF31, 0xF30, 0xF20, 0xF10, 0xF00, 0xEF0, + 0xEE1, 0x131, 0x121, 0x120, 0x111, 0x110, 0x101, 0x100, + 0x0F1, 0x0F0, 0x0E3, 0x0E1, 0x0E0, 0x0D1, 0x0D0, 0x0C3, + 0x0C0, 0x0B3, 0x0B1, 0x0B0, 0x0A1, 0x0A0, 0x091, 0x090, + 0x081, 0x080, 0x075, 0x071, 0x070, 0x065, 0x063, 0x061, + 0x060, 0x056, 0x055, 0x053, 0x051, 0x050, 0x046, 0x045, + 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, + 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, + 0x021, 0x020, 0x018, 0x016, 0x015, 0x014, 0x013, 0x012, + 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc6_codes[130] = { + 0x0022, 0x0BB2, 0x0942, 0x002B, 0x0072, 0x0002, 0x001A, 0x0039, + 0x000D, 0x0007, 0x007B, 0x008E, 0x06DB, 0x00EA, 0x015B, 0x002E, + 0x0006, 0x0959, 0x027B, 0x0A0E, 0x01AB, 0x008A, 0x0012, 0x001E, + 0x0575, 0x005B, 0x02AB, 0x00C2, 0x0015, 0x036A, 0x04B2, 0x0099, + 0x001B, 0x0519, 0x0C19, 0x00DB, 0x004E, 0x0042, 0x0159, 0x03B2, + 0x030E, 0x00EB, 0x0252, 0x0EAB, 0x018A, 0x00E2, 0x06AB, 0x0242, + 0x017B, 0x0452, 0x0319, 0x0152, 0x025B, 0x016A, 0x00AB, 0x0052, + 0x05B2, 0x010E, 0x038E, 0x028A, 0x0359, 0x0019, 0x078A, 0x0C52, + 0x0D8E, 0x0ED9, 0x02D9, 0x0662, 0x0119, 0x09B2, 0x0BAB, 0x0D19, + 0x0C5B, 0x00B2, 0x0542, 0x0B8A, 0x02B2, 0x0142, 0x065B, 0x058E, + 0x0062, 0x018E, 0x038A, 0x00D9, 0x0419, 0x0162, 0x03AB, 0x0075, + 0x07B2, 0x0032, 0x020E, 0x07AB, 0x006B, 0x045B, 0x01B2, 0x0199, + 0x002A, 0x0375, 0x0775, 0x0AAB, 0x01D9, 0x003B, 0x060E, 0x0342, + 0x0175, 0x0262, 0x000A, 0x0005, 0x0559, 0x006A, 0x0D59, 0x0219, + 0x000E, 0x004A, 0x0009, 0x0719, 0x0059, 0x02DB, 0x00D2, 0x01DB, + 0x0025, 0x0001, 0x06D9, 0x00F5, 0x0035, 0x00FB, 0x003A, 0x000B, + 0x0003, 0x0000, +}; + +static const uint8_t ac_vlc_desc6_bits[130] = { + 7, 12, 12, 8, 7, 7, 6, 6, + 4, 3, 10, 9, 11, 8, 9, 6, + 4, 12, 10, 12, 10, 10, 7, 5, + 11, 11, 12, 8, 6, 10, 11, 9, + 7, 12, 12, 10, 7, 10, 12, 12, + 10, 8, 10, 12, 10, 8, 12, 10, + 9, 12, 11, 9, 11, 10, 10, 11, + 11, 10, 10, 10, 10, 11, 11, 12, + 12, 12, 11, 11, 11, 12, 12, 12, + 12, 11, 11, 12, 10, 12, 11, 12, + 10, 11, 12, 10, 12, 9, 12, 9, + 11, 8, 12, 11, 8, 12, 12, 9, + 7, 11, 11, 12, 9, 7, 11, 10, + 11, 11, 8, 6, 12, 9, 12, 10, + 10, 7, 5, 11, 9, 11, 8, 9, + 6, 4, 12, 8, 7, 8, 6, 6, + 4, 2, +}; + +static const uint16_t ac_vlc_desc7_syms[125] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, + 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB5, 0xFB3, 0xFB1, 0xFB0, + 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF95, 0xF93, + 0xF91, 0xF90, 0xF86, 0xF81, 0xF80, 0xF73, 0xF71, 0xF70, + 0xF63, 0xF61, 0xF60, 0xF53, 0xF51, 0xF50, 0xF41, 0xF40, + 0xF31, 0xF30, 0xF20, 0xF10, 0xF01, 0xF00, 0x121, 0x111, + 0x101, 0x100, 0x0F1, 0x0F0, 0x0E1, 0x0E0, 0x0D1, 0x0D0, + 0x0C3, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A3, 0x0A1, 0x0A0, + 0x093, 0x091, 0x090, 0x081, 0x080, 0x071, 0x070, 0x065, + 0x063, 0x061, 0x060, 0x055, 0x053, 0x052, 0x051, 0x050, + 0x046, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, + 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, + 0x023, 0x022, 0x021, 0x020, 0x018, 0x017, 0x016, 0x015, + 0x014, 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc7_codes[125] = { + 0x0053, 0x009A, 0x0EE2, 0x00D3, 0x006A, 0x0052, 0x003A, 0x0035, + 0x000D, 0x0007, 0x0062, 0x0125, 0x0142, 0x0019, 0x01F3, 0x0029, + 0x000E, 0x0082, 0x0ADA, 0x02E3, 0x00E2, 0x0022, 0x0006, 0x0065, + 0x05E3, 0x0765, 0x0032, 0x0039, 0x0F99, 0x05E2, 0x0099, 0x0033, + 0x0362, 0x0799, 0x0F65, 0x0073, 0x004A, 0x02A5, 0x0162, 0x0742, + 0x01A5, 0x00D9, 0x0342, 0x005A, 0x00AA, 0x0EF3, 0x0182, 0x01DA, + 0x0382, 0x035A, 0x00F3, 0x0673, 0x0165, 0x00E5, 0x06F3, 0x0225, + 0x0842, 0x025A, 0x07E3, 0x0399, 0x07A5, 0x072A, 0x0F2A, 0x09E3, + 0x0273, 0x049A, 0x02E5, 0x0B99, 0x02E2, 0x0E73, 0x0562, 0x02F3, + 0x032A, 0x0F42, 0x00DA, 0x0999, 0x012A, 0x0365, 0x00A5, 0x00E3, + 0x0199, 0x03E3, 0x019A, 0x01E2, 0x0173, 0x06E5, 0x0059, 0x01E3, + 0x02DA, 0x002A, 0x000A, 0x06DA, 0x0FA5, 0x0042, 0x01E5, 0x0013, + 0x03E2, 0x015A, 0x03A5, 0x0442, 0x001A, 0x0005, 0x04A5, 0x0265, + 0x08A5, 0x0025, 0x029A, 0x0072, 0x0016, 0x0599, 0x00C2, 0x0242, + 0x00B2, 0x0002, 0x0015, 0x0001, 0x0BE3, 0x06E2, 0x0063, 0x0023, + 0x0012, 0x0009, 0x0003, 0x000B, 0x0000, +}; + +static const uint8_t ac_vlc_desc7_bits[125] = { + 8, 11, 12, 8, 7, 7, 6, 6, + 4, 3, 9, 9, 10, 8, 9, 6, + 4, 9, 12, 10, 10, 7, 5, 10, + 11, 12, 8, 6, 12, 11, 9, 7, + 10, 12, 12, 10, 7, 10, 11, 12, + 10, 8, 11, 10, 8, 12, 10, 9, + 10, 10, 10, 12, 10, 10, 12, 10, + 12, 10, 11, 12, 12, 12, 12, 12, + 11, 11, 11, 12, 11, 12, 11, 11, + 11, 12, 10, 12, 10, 11, 12, 10, + 12, 12, 9, 11, 9, 11, 8, 12, + 12, 9, 7, 11, 12, 12, 9, 7, + 10, 10, 11, 11, 8, 6, 11, 10, + 12, 10, 10, 7, 5, 11, 8, 10, + 8, 8, 6, 4, 12, 12, 8, 7, + 7, 6, 6, 4, 2, +}; + +static const uint16_t ac_vlc_desc8_syms[121] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, + 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, 0xFB1, + 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF96, 0xF95, + 0xF93, 0xF91, 0xF90, 0xF86, 0xF83, 0xF81, 0xF80, 0xF73, + 0xF71, 0xF70, 0xF63, 0xF61, 0xF60, 0xF51, 0xF50, 0xF41, + 0xF40, 0xF30, 0xF21, 0xF20, 0x111, 0x101, 0x0F1, 0x0E1, + 0x0E0, 0x0D1, 0x0D0, 0x0C1, 0x0C0, 0x0B3, 0x0B1, 0x0B0, + 0x0A3, 0x0A1, 0x0A0, 0x093, 0x091, 0x090, 0x083, 0x081, + 0x080, 0x073, 0x071, 0x070, 0x065, 0x063, 0x061, 0x060, + 0x055, 0x053, 0x051, 0x050, 0x046, 0x045, 0x043, 0x042, + 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, 0x031, + 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, + 0x018, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, + 0x010, +}; + +static const uint16_t ac_vlc_desc8_codes[121] = { + 0x00F6, 0x0676, 0x0EB6, 0x00F3, 0x0056, 0x006A, 0x0039, 0x0003, + 0x000D, 0x0007, 0x00A2, 0x0173, 0x00CA, 0x0025, 0x0082, 0x0019, + 0x0001, 0x00B6, 0x0276, 0x02E3, 0x00B2, 0x0062, 0x001A, 0x0175, + 0x01E3, 0x0BE5, 0x004A, 0x0029, 0x07A5, 0x00E3, 0x030A, 0x0176, + 0x0023, 0x0042, 0x05CA, 0x00A5, 0x0142, 0x0052, 0x04A5, 0x0B02, + 0x0D22, 0x0375, 0x0065, 0x0522, 0x0DE3, 0x010A, 0x00F5, 0x0136, + 0x0275, 0x01B2, 0x03F5, 0x03E3, 0x0002, 0x08E3, 0x01A2, 0x0B36, + 0x020A, 0x0076, 0x0CE3, 0x07E5, 0x070A, 0x03A5, 0x02B6, 0x0036, + 0x01E5, 0x02A5, 0x05E3, 0x07B6, 0x07F5, 0x0736, 0x0BA5, 0x0075, + 0x0302, 0x0FE5, 0x01B6, 0x0102, 0x04E3, 0x0022, 0x08A5, 0x01CA, + 0x00E5, 0x0F0A, 0x05E5, 0x0096, 0x0A76, 0x0336, 0x0236, 0x0012, + 0x03B6, 0x0BF5, 0x0073, 0x0035, 0x02B2, 0x000A, 0x0476, 0x0122, + 0x0016, 0x0009, 0x0322, 0x01F5, 0x03E5, 0x01A5, 0x03CA, 0x0072, + 0x0006, 0x06A5, 0x0032, 0x02CA, 0x008A, 0x00C2, 0x0015, 0x000E, + 0x0702, 0x06B6, 0x0063, 0x0033, 0x002A, 0x0005, 0x0013, 0x000B, + 0x0000, +}; + +static const uint8_t ac_vlc_desc8_bits[121] = { + 8, 11, 12, 8, 7, 7, 6, 6, + 4, 3, 9, 9, 10, 8, 8, 6, + 4, 10, 12, 10, 10, 7, 5, 10, + 11, 12, 8, 6, 11, 12, 11, 9, + 7, 9, 11, 12, 9, 7, 11, 12, + 12, 10, 8, 12, 12, 10, 9, 10, + 10, 9, 12, 10, 9, 12, 9, 12, + 10, 11, 12, 12, 12, 12, 11, 10, + 11, 11, 12, 11, 11, 11, 12, 10, + 12, 12, 10, 10, 12, 9, 12, 11, + 9, 12, 11, 8, 12, 12, 10, 7, + 11, 12, 9, 7, 10, 10, 11, 11, + 8, 6, 10, 10, 12, 10, 10, 7, + 5, 11, 8, 10, 8, 8, 6, 4, + 11, 12, 8, 7, 7, 6, 6, 4, + 2, +}; + +static const uint16_t ac_vlc_desc9_syms[114] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC5, + 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, 0xFB2, + 0xFB1, 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, 0xF96, + 0xF93, 0xF91, 0xF90, 0xF83, 0xF81, 0xF80, 0xF73, 0xF71, + 0xF70, 0xF61, 0xF60, 0xF51, 0xF50, 0xF40, 0xF31, 0xF30, + 0xF21, 0x121, 0x0F1, 0x0E1, 0x0D1, 0x0D0, 0x0C1, 0x0C0, + 0x0B1, 0x0B0, 0x0A3, 0x0A1, 0x0A0, 0x093, 0x091, 0x090, + 0x083, 0x081, 0x080, 0x073, 0x071, 0x070, 0x065, 0x063, + 0x061, 0x060, 0x055, 0x053, 0x051, 0x050, 0x045, 0x043, + 0x042, 0x041, 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, + 0x031, 0x030, 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, + 0x020, 0x018, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, + 0x011, 0x010, +}; + +static const uint16_t ac_vlc_desc9_codes[114] = { + 0x0061, 0x0403, 0x0DB1, 0x0012, 0x0071, 0x0056, 0x0035, 0x0023, + 0x000D, 0x0007, 0x0243, 0x01D3, 0x026A, 0x00A1, 0x00A2, 0x0011, + 0x000E, 0x01AA, 0x0531, 0x0093, 0x0222, 0x0032, 0x0006, 0x07F2, + 0x04D3, 0x0C43, 0x0072, 0x0001, 0x0343, 0x05F2, 0x04AA, 0x03F2, + 0x0031, 0x0045, 0x0143, 0x00AA, 0x0B31, 0x00F2, 0x00C3, 0x0693, + 0x0BF2, 0x0203, 0x00E1, 0x03B1, 0x02D3, 0x00B1, 0x056A, 0x01D2, + 0x008A, 0x046A, 0x01E2, 0x0003, 0x0103, 0x01B1, 0x02E2, 0x0293, + 0x016A, 0x04E2, 0x0443, 0x0521, 0x0321, 0x0043, 0x00D3, 0x00E2, + 0x0703, 0x00D2, 0x0731, 0x0A93, 0x0393, 0x0803, 0x0422, 0x0383, + 0x018A, 0x006A, 0x0021, 0x096A, 0x0303, 0x0052, 0x0CE2, 0x0D31, + 0x038A, 0x0013, 0x01F2, 0x0E93, 0x0083, 0x0005, 0x02D2, 0x0121, + 0x0022, 0x00EA, 0x0036, 0x0122, 0x0193, 0x0331, 0x0183, 0x02AA, + 0x004A, 0x001A, 0x0131, 0x002A, 0x036A, 0x000A, 0x0062, 0x0025, + 0x0009, 0x06E2, 0x05B1, 0x0053, 0x0002, 0x0016, 0x0015, 0x0033, + 0x000B, 0x0000, +}; + +static const uint8_t ac_vlc_desc9_bits[114] = { + 8, 11, 12, 7, 7, 7, 6, 6, + 4, 3, 10, 9, 10, 8, 8, 6, + 4, 9, 12, 10, 10, 7, 5, 11, + 11, 12, 8, 6, 10, 11, 11, 12, + 9, 7, 10, 11, 12, 9, 8, 12, + 12, 10, 8, 10, 10, 9, 11, 9, + 9, 11, 9, 12, 10, 11, 11, 12, + 12, 12, 12, 11, 10, 11, 11, 11, + 11, 10, 11, 12, 10, 12, 11, 10, + 10, 11, 9, 12, 11, 8, 12, 12, + 10, 8, 11, 12, 9, 7, 10, 11, + 11, 8, 6, 9, 10, 12, 10, 10, + 7, 5, 11, 8, 10, 8, 8, 6, + 4, 11, 12, 8, 6, 7, 6, 6, + 4, 2, +}; + +static const uint16_t ac_vlc_descA_syms[110] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, + 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, + 0xFB2, 0xFB1, 0xFB0, 0xFA6, 0xFA5, 0xFA3, 0xFA1, 0xFA0, + 0xF96, 0xF93, 0xF91, 0xF90, 0xF83, 0xF81, 0xF80, 0xF73, + 0xF71, 0xF70, 0xF61, 0xF60, 0xF51, 0xF50, 0xF41, 0xF40, + 0xF31, 0x0E1, 0x0D1, 0x0C1, 0x0C0, 0x0B1, 0x0B0, 0x0A1, + 0x0A0, 0x093, 0x091, 0x090, 0x083, 0x081, 0x080, 0x073, + 0x071, 0x070, 0x063, 0x061, 0x060, 0x055, 0x053, 0x051, + 0x050, 0x045, 0x044, 0x043, 0x042, 0x041, 0x040, 0x036, + 0x035, 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, + 0x024, 0x023, 0x022, 0x021, 0x020, 0x018, 0x017, 0x016, + 0x015, 0x014, 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_descA_codes[110] = { + 0x002A, 0x04C5, 0x02A3, 0x004A, 0x0015, 0x0005, 0x0003, 0x0013, + 0x000D, 0x0007, 0x0171, 0x0032, 0x0371, 0x0076, 0x0042, 0x0011, + 0x000E, 0x00AA, 0x04D5, 0x03A3, 0x06A3, 0x0062, 0x001A, 0x06D5, + 0x07F2, 0x0223, 0x0CD5, 0x006A, 0x0001, 0x00F6, 0x0623, 0x03F2, + 0x07EA, 0x01F1, 0x0021, 0x03D5, 0x08C2, 0x07F6, 0x00F2, 0x00E3, + 0x0FEA, 0x02C5, 0x01AA, 0x0082, 0x04A3, 0x00B6, 0x0071, 0x03B2, + 0x0023, 0x01B6, 0x08A3, 0x0002, 0x0BB2, 0x00C5, 0x02EA, 0x0C23, + 0x0FF6, 0x0423, 0x07B2, 0x01C5, 0x07D5, 0x01EA, 0x06EA, 0x02C2, + 0x01F6, 0x01D5, 0x01B2, 0x00B2, 0x04F1, 0x03EA, 0x01A2, 0x02A2, + 0x02D5, 0x0123, 0x00D5, 0x01F2, 0x0055, 0x05B2, 0x04C2, 0x0102, + 0x0061, 0x05D5, 0x00C2, 0x00F1, 0x00A3, 0x0045, 0x0016, 0x01A3, + 0x01C2, 0x08D5, 0x03C5, 0x00EA, 0x000A, 0x0006, 0x00A2, 0x0036, + 0x02F1, 0x0072, 0x0022, 0x0025, 0x0009, 0x03F6, 0x0AA3, 0x0063, + 0x0012, 0x0031, 0x0035, 0x0033, 0x000B, 0x0000, +}; + +static const uint8_t ac_vlc_descA_bits[110] = { + 8, 11, 12, 7, 7, 7, 6, 6, + 4, 3, 10, 8, 10, 8, 8, 6, + 4, 9, 12, 10, 11, 7, 5, 11, + 11, 11, 12, 8, 6, 9, 11, 11, + 12, 9, 7, 11, 12, 12, 9, 8, + 12, 10, 9, 8, 11, 9, 9, 12, + 11, 9, 12, 9, 12, 11, 11, 12, + 12, 12, 11, 10, 11, 10, 11, 10, + 10, 11, 11, 9, 11, 11, 9, 10, + 11, 9, 12, 10, 8, 11, 11, 9, + 7, 11, 12, 11, 12, 8, 6, 10, + 9, 12, 10, 10, 7, 5, 10, 8, + 10, 8, 8, 6, 4, 11, 12, 8, + 6, 7, 6, 6, 4, 2, +}; + +static const uint16_t ac_vlc_descB_syms[101] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, + 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, + 0xFB1, 0xFB0, 0xFA6, 0xFA3, 0xFA1, 0xFA0, 0xF93, 0xF91, + 0xF90, 0xF83, 0xF81, 0xF80, 0xF71, 0xF70, 0xF61, 0xF60, + 0xF51, 0xF50, 0xF41, 0x0F1, 0x0D1, 0x0C1, 0x0B1, 0x0B0, + 0x0A1, 0x0A0, 0x091, 0x090, 0x083, 0x081, 0x080, 0x073, + 0x071, 0x070, 0x063, 0x061, 0x060, 0x055, 0x053, 0x051, + 0x050, 0x045, 0x043, 0x042, 0x041, 0x040, 0x036, 0x035, + 0x034, 0x033, 0x032, 0x031, 0x030, 0x026, 0x025, 0x024, + 0x023, 0x022, 0x021, 0x020, 0x018, 0x017, 0x016, 0x015, + 0x014, 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_descB_codes[101] = { + 0x00EE, 0x03A5, 0x0B73, 0x004E, 0x0035, 0x0015, 0x0023, 0x0013, + 0x000D, 0x0007, 0x0673, 0x01F3, 0x02FE, 0x0096, 0x0133, 0x001E, + 0x0001, 0x0116, 0x00F5, 0x03F5, 0x0473, 0x0052, 0x001A, 0x01D5, + 0x0025, 0x0073, 0x0633, 0x0086, 0x0036, 0x012E, 0x0155, 0x0006, + 0x0055, 0x000E, 0x0106, 0x023E, 0x0192, 0x0075, 0x0173, 0x01AE, + 0x00D5, 0x08F5, 0x002E, 0x01FE, 0x0406, 0x00AE, 0x0E3E, 0x0206, + 0x013E, 0x0373, 0x0D55, 0x063E, 0x0E33, 0x033E, 0x01F5, 0x0273, + 0x003E, 0x06A5, 0x0092, 0x03D5, 0x04F5, 0x053E, 0x0016, 0x00FE, + 0x07A5, 0x0125, 0x0506, 0x0292, 0x00BE, 0x0425, 0x0F73, 0x02F5, + 0x0056, 0x0233, 0x02A5, 0x0C25, 0x007E, 0x0026, 0x0355, 0x0033, + 0x0555, 0x01A5, 0x0306, 0x0046, 0x000A, 0x0225, 0x006E, 0x00A5, + 0x0012, 0x00F3, 0x0005, 0x0009, 0x073E, 0x0773, 0x00B3, 0x0032, + 0x0065, 0x0003, 0x0002, 0x000B, 0x0000, +}; + +static const uint8_t ac_vlc_descB_bits[101] = { + 8, 11, 12, 7, 7, 7, 6, 6, + 4, 3, 11, 9, 10, 8, 9, 6, + 4, 9, 12, 10, 11, 7, 5, 10, + 11, 11, 12, 8, 6, 9, 11, 11, + 9, 7, 11, 11, 9, 8, 10, 9, + 9, 12, 9, 9, 11, 9, 12, 10, + 11, 12, 12, 12, 12, 11, 10, 11, + 10, 11, 10, 10, 11, 11, 9, 10, + 11, 9, 11, 10, 8, 12, 12, 10, + 7, 11, 11, 12, 8, 6, 10, 10, + 12, 10, 10, 7, 5, 10, 8, 10, + 8, 9, 6, 4, 11, 12, 8, 6, + 7, 6, 5, 4, 2, +}; + +static const uint16_t ac_vlc_descC_syms[96] = { + 0x1000, 0xFF8, 0xFF7, 0xFF6, 0xFF5, 0xFF4, 0xFF3, 0xFF2, + 0xFF1, 0xFF0, 0xFE6, 0xFE5, 0xFE4, 0xFE3, 0xFE2, 0xFE1, + 0xFE0, 0xFD5, 0xFD4, 0xFD3, 0xFD2, 0xFD1, 0xFD0, 0xFC6, + 0xFC5, 0xFC3, 0xFC2, 0xFC1, 0xFC0, 0xFB6, 0xFB5, 0xFB3, + 0xFB1, 0xFB0, 0xFA6, 0xFA3, 0xFA1, 0xFA0, 0xF93, 0xF91, + 0xF90, 0xF81, 0xF80, 0xF71, 0xF70, 0xF61, 0xF60, 0xF51, + 0x0E1, 0x0C1, 0x0B1, 0x0A1, 0x0A0, 0x091, 0x090, 0x083, + 0x081, 0x080, 0x073, 0x071, 0x070, 0x063, 0x061, 0x060, + 0x055, 0x053, 0x051, 0x050, 0x045, 0x043, 0x042, 0x041, + 0x040, 0x036, 0x035, 0x034, 0x033, 0x032, 0x031, 0x030, + 0x026, 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x018, + 0x017, 0x016, 0x015, 0x014, 0x013, 0x012, 0x011, 0x010, +}; + +static const uint16_t ac_vlc_descC_codes[96] = { + 0x00DE, 0x072E, 0x0576, 0x006E, 0x0075, 0x0055, 0x0013, 0x0033, + 0x000D, 0x0007, 0x07D2, 0x0052, 0x0065, 0x00CE, 0x0183, 0x003E, + 0x0001, 0x002E, 0x0F35, 0x0003, 0x0243, 0x001A, 0x0006, 0x01A5, + 0x0043, 0x0012, 0x0E43, 0x00B6, 0x0016, 0x0135, 0x0176, 0x0643, + 0x0035, 0x001E, 0x0735, 0x0283, 0x0125, 0x00AE, 0x00D2, 0x0165, + 0x0103, 0x0603, 0x00E5, 0x0C43, 0x02B5, 0x04A5, 0x00A5, 0x0443, + 0x0265, 0x0476, 0x0212, 0x0112, 0x0376, 0x012E, 0x02D2, 0x0083, + 0x0483, 0x015E, 0x06A5, 0x0335, 0x005E, 0x0025, 0x01D2, 0x00F6, + 0x03D2, 0x032E, 0x03B5, 0x005A, 0x0203, 0x02A5, 0x0BD2, 0x004E, + 0x0032, 0x01B5, 0x00B5, 0x0A65, 0x0225, 0x0276, 0x000E, 0x000A, + 0x03E5, 0x0143, 0x01E5, 0x0036, 0x0092, 0x0005, 0x0009, 0x0665, + 0x0076, 0x00C3, 0x003A, 0x0015, 0x0023, 0x0002, 0x000B, 0x0000, +}; + +static const uint8_t ac_vlc_descC_bits[96] = { + 8, 11, 11, 7, 7, 7, 6, 6, + 4, 3, 11, 8, 10, 8, 9, 6, + 4, 9, 12, 10, 11, 7, 5, 9, + 11, 10, 12, 8, 6, 10, 11, 12, + 9, 7, 12, 10, 9, 8, 10, 9, + 9, 11, 9, 12, 10, 11, 11, 12, + 12, 11, 10, 9, 10, 10, 10, 11, + 11, 9, 11, 11, 9, 10, 10, 8, + 12, 11, 10, 7, 11, 11, 12, 8, + 6, 10, 10, 12, 10, 10, 7, 5, + 10, 9, 10, 8, 8, 6, 4, 11, + 11, 8, 6, 7, 6, 5, 4, 2, +}; + +static const int tscc2_ac_vlc_sizes[NUM_VLC_SETS] = { + 172, 169, 165, 162, 131, 132, 130, 125, 121, 114, 110, 101, 96 +}; + +static const uint16_t *tscc2_ac_vlc_syms[NUM_VLC_SETS] = { + ac_vlc_desc0_syms, ac_vlc_desc1_syms, ac_vlc_desc2_syms, ac_vlc_desc3_syms, + ac_vlc_desc4_syms, ac_vlc_desc5_syms, ac_vlc_desc6_syms, ac_vlc_desc7_syms, + ac_vlc_desc8_syms, ac_vlc_desc9_syms, ac_vlc_descA_syms, ac_vlc_descB_syms, + ac_vlc_descC_syms, +}; + +static const uint16_t *tscc2_ac_vlc_codes[NUM_VLC_SETS] = { + ac_vlc_desc0_codes, ac_vlc_desc1_codes, ac_vlc_desc2_codes, + ac_vlc_desc3_codes, ac_vlc_desc4_codes, ac_vlc_desc5_codes, + ac_vlc_desc6_codes, ac_vlc_desc7_codes, ac_vlc_desc8_codes, + ac_vlc_desc9_codes, ac_vlc_descA_codes, ac_vlc_descB_codes, + ac_vlc_descC_codes, +}; + +static const uint8_t *tscc2_ac_vlc_bits[NUM_VLC_SETS] = { + ac_vlc_desc0_bits, ac_vlc_desc1_bits, ac_vlc_desc2_bits, ac_vlc_desc3_bits, + ac_vlc_desc4_bits, ac_vlc_desc5_bits, ac_vlc_desc6_bits, ac_vlc_desc7_bits, + ac_vlc_desc8_bits, ac_vlc_desc9_bits, ac_vlc_descA_bits, ac_vlc_descB_bits, + ac_vlc_descC_bits, +}; + +#endif /* AVCODEC_TSCC2_DATA_H */ diff --git a/ffmpeg/libavcodec/tta.c b/ffmpeg/libavcodec/tta.c new file mode 100644 index 0000000..8b4ca5a --- /dev/null +++ b/ffmpeg/libavcodec/tta.c @@ -0,0 +1,515 @@ +/* + * TTA (The Lossless True Audio) decoder + * Copyright (c) 2006 Alex Beregszaszi + * + * 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 + */ + +/** + * @file + * TTA (The Lossless True Audio) decoder + * @see http://www.true-audio.com/ + * @see http://tta.corecodec.org/ + * @author Alex Beregszaszi + */ + +#define BITSTREAM_READER_LE +//#define DEBUG +#include +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "libavutil/crc.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +#define FORMAT_SIMPLE 1 +#define FORMAT_ENCRYPTED 2 + +#define MAX_ORDER 16 +typedef struct TTAFilter { + int32_t shift, round, error; + int32_t qm[MAX_ORDER]; + int32_t dx[MAX_ORDER]; + int32_t dl[MAX_ORDER]; +} TTAFilter; + +typedef struct TTARice { + uint32_t k0, k1, sum0, sum1; +} TTARice; + +typedef struct TTAChannel { + int32_t predictor; + TTAFilter filter; + TTARice rice; +} TTAChannel; + +typedef struct TTAContext { + AVClass *class; + AVCodecContext *avctx; + GetBitContext gb; + const AVCRC *crc_table; + + int format, channels, bps; + unsigned data_length; + int frame_length, last_frame_length; + + int32_t *decode_buffer; + + uint8_t crc_pass[8]; + uint8_t *pass; + TTAChannel *ch_ctx; +} TTAContext; + +static const uint32_t shift_1[] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 +}; + +static const uint32_t * const shift_16 = shift_1 + 4; + +static const int32_t ttafilter_configs[4] = { + 10, + 9, + 10, + 12 +}; + +static void ttafilter_init(TTAContext *s, TTAFilter *c, int32_t shift) { + memset(c, 0, sizeof(TTAFilter)); + if (s->format == FORMAT_ENCRYPTED) { + int i; + for (i = 0; i < 8; i++) + c->qm[i] = sign_extend(s->crc_pass[i], 8); + } + c->shift = shift; + c->round = shift_1[shift-1]; +// c->round = 1 << (shift - 1); +} + +static inline void ttafilter_process(TTAFilter *c, int32_t *in) +{ + register int32_t *dl = c->dl, *qm = c->qm, *dx = c->dx, sum = c->round; + + if (c->error < 0) { + qm[0] -= dx[0]; qm[1] -= dx[1]; qm[2] -= dx[2]; qm[3] -= dx[3]; + qm[4] -= dx[4]; qm[5] -= dx[5]; qm[6] -= dx[6]; qm[7] -= dx[7]; + } else if (c->error > 0) { + qm[0] += dx[0]; qm[1] += dx[1]; qm[2] += dx[2]; qm[3] += dx[3]; + qm[4] += dx[4]; qm[5] += dx[5]; qm[6] += dx[6]; qm[7] += dx[7]; + } + + sum += dl[0] * qm[0] + dl[1] * qm[1] + dl[2] * qm[2] + dl[3] * qm[3] + + dl[4] * qm[4] + dl[5] * qm[5] + dl[6] * qm[6] + dl[7] * qm[7]; + + dx[0] = dx[1]; dx[1] = dx[2]; dx[2] = dx[3]; dx[3] = dx[4]; + dl[0] = dl[1]; dl[1] = dl[2]; dl[2] = dl[3]; dl[3] = dl[4]; + + dx[4] = ((dl[4] >> 30) | 1); + dx[5] = ((dl[5] >> 30) | 2) & ~1; + dx[6] = ((dl[6] >> 30) | 2) & ~1; + dx[7] = ((dl[7] >> 30) | 4) & ~3; + + c->error = *in; + *in += (sum >> c->shift); + + dl[4] = -dl[5]; dl[5] = -dl[6]; + dl[6] = *in - dl[7]; dl[7] = *in; + dl[5] += dl[6]; dl[4] += dl[5]; +} + +static void rice_init(TTARice *c, uint32_t k0, uint32_t k1) +{ + c->k0 = k0; + c->k1 = k1; + c->sum0 = shift_16[k0]; + c->sum1 = shift_16[k1]; +} + +static int tta_get_unary(GetBitContext *gb) +{ + int ret = 0; + + // count ones + while (get_bits_left(gb) > 0 && get_bits1(gb)) + ret++; + return ret; +} + +static const int64_t tta_channel_layouts[7] = { + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_QUAD, + 0, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER, + AV_CH_LAYOUT_7POINT1_WIDE +}; + +static int tta_check_crc(TTAContext *s, const uint8_t *buf, int buf_size) +{ + uint32_t crc, CRC; + + CRC = AV_RL32(buf + buf_size); + crc = av_crc(s->crc_table, 0xFFFFFFFFU, buf, buf_size); + if (CRC != (crc ^ 0xFFFFFFFFU)) { + av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static uint64_t tta_check_crc64(uint8_t *pass) +{ + uint64_t crc = UINT64_MAX, poly = 0x42F0E1EBA9EA3693U; + uint8_t *end = pass + strlen(pass); + int i; + + while (pass < end) { + crc ^= (uint64_t)*pass++ << 56; + for (i = 0; i < 8; i++) + crc = (crc << 1) ^ (poly & (((int64_t) crc) >> 63)); + } + + return crc ^ UINT64_MAX; +} + +static av_cold int tta_decode_init(AVCodecContext * avctx) +{ + TTAContext *s = avctx->priv_data; + int total_frames; + + s->avctx = avctx; + + // 30bytes includes a seektable with one frame + if (avctx->extradata_size < 30) + return AVERROR_INVALIDDATA; + + init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size * 8); + if (show_bits_long(&s->gb, 32) == AV_RL32("TTA1")) + { + if (avctx->err_recognition & AV_EF_CRCCHECK) { + s->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE); + tta_check_crc(s, avctx->extradata, 18); + } + + /* signature */ + skip_bits_long(&s->gb, 32); + + s->format = get_bits(&s->gb, 16); + if (s->format > 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid format\n"); + return AVERROR_INVALIDDATA; + } + if (s->format == FORMAT_ENCRYPTED) { + if (!s->pass) { + av_log(avctx, AV_LOG_ERROR, "Missing password for encrypted stream. Please use the -password option\n"); + return AVERROR(EINVAL); + } + AV_WL64(s->crc_pass, tta_check_crc64(s->pass)); + } + avctx->channels = s->channels = get_bits(&s->gb, 16); + if (s->channels > 1 && s->channels < 9) + avctx->channel_layout = tta_channel_layouts[s->channels-2]; + avctx->bits_per_raw_sample = get_bits(&s->gb, 16); + s->bps = (avctx->bits_per_raw_sample + 7) / 8; + avctx->sample_rate = get_bits_long(&s->gb, 32); + s->data_length = get_bits_long(&s->gb, 32); + skip_bits_long(&s->gb, 32); // CRC32 of header + + if (s->channels == 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } else if (avctx->sample_rate == 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid samplerate\n"); + return AVERROR_INVALIDDATA; + } + + switch(s->bps) { + case 1: avctx->sample_fmt = AV_SAMPLE_FMT_U8; break; + case 2: + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + break; + case 3: + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + break; + //case 4: avctx->sample_fmt = AV_SAMPLE_FMT_S32; break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid/unsupported sample format.\n"); + return AVERROR_INVALIDDATA; + } + + // prevent overflow + if (avctx->sample_rate > 0x7FFFFFu) { + av_log(avctx, AV_LOG_ERROR, "sample_rate too large\n"); + return AVERROR(EINVAL); + } + s->frame_length = 256 * avctx->sample_rate / 245; + + s->last_frame_length = s->data_length % s->frame_length; + total_frames = s->data_length / s->frame_length + + (s->last_frame_length ? 1 : 0); + + av_log(avctx, AV_LOG_DEBUG, "format: %d chans: %d bps: %d rate: %d block: %d\n", + s->format, avctx->channels, avctx->bits_per_coded_sample, avctx->sample_rate, + avctx->block_align); + av_log(avctx, AV_LOG_DEBUG, "data_length: %d frame_length: %d last: %d total: %d\n", + s->data_length, s->frame_length, s->last_frame_length, total_frames); + + // FIXME: seek table + if (avctx->extradata_size <= 26 || total_frames > INT_MAX / 4 || + avctx->extradata_size - 26 < total_frames * 4) + av_log(avctx, AV_LOG_WARNING, "Seek table missing or too small\n"); + else if (avctx->err_recognition & AV_EF_CRCCHECK) { + if (tta_check_crc(s, avctx->extradata + 22, total_frames * 4)) + return AVERROR_INVALIDDATA; + } + skip_bits_long(&s->gb, 32 * total_frames); + skip_bits_long(&s->gb, 32); // CRC32 of seektable + + if(s->frame_length >= UINT_MAX / (s->channels * sizeof(int32_t))){ + av_log(avctx, AV_LOG_ERROR, "frame_length too large\n"); + return AVERROR_INVALIDDATA; + } + + if (s->bps < 3) { + s->decode_buffer = av_mallocz(sizeof(int32_t)*s->frame_length*s->channels); + if (!s->decode_buffer) + return AVERROR(ENOMEM); + } else + s->decode_buffer = NULL; + s->ch_ctx = av_malloc(avctx->channels * sizeof(*s->ch_ctx)); + if (!s->ch_ctx) { + av_freep(&s->decode_buffer); + return AVERROR(ENOMEM); + } + } else { + av_log(avctx, AV_LOG_ERROR, "Wrong extradata present\n"); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static int tta_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + TTAContext *s = avctx->priv_data; + int i, ret; + int cur_chan = 0, framelen = s->frame_length; + int32_t *p; + + if (avctx->err_recognition & AV_EF_CRCCHECK) { + if (buf_size < 4 || tta_check_crc(s, buf, buf_size - 4)) + return AVERROR_INVALIDDATA; + } + + init_get_bits(&s->gb, buf, buf_size*8); + + /* get output buffer */ + frame->nb_samples = framelen; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + // decode directly to output buffer for 24-bit sample format + if (s->bps == 3) + s->decode_buffer = (int32_t *)frame->data[0]; + + // init per channel states + for (i = 0; i < s->channels; i++) { + s->ch_ctx[i].predictor = 0; + ttafilter_init(s, &s->ch_ctx[i].filter, ttafilter_configs[s->bps-1]); + rice_init(&s->ch_ctx[i].rice, 10, 10); + } + + i = 0; + for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) { + int32_t *predictor = &s->ch_ctx[cur_chan].predictor; + TTAFilter *filter = &s->ch_ctx[cur_chan].filter; + TTARice *rice = &s->ch_ctx[cur_chan].rice; + uint32_t unary, depth, k; + int32_t value; + + unary = tta_get_unary(&s->gb); + + if (unary == 0) { + depth = 0; + k = rice->k0; + } else { + depth = 1; + k = rice->k1; + unary--; + } + + if (get_bits_left(&s->gb) < k) { + ret = AVERROR_INVALIDDATA; + goto error; + } + + if (k) { + if (k > MIN_CACHE_BITS) { + ret = AVERROR_INVALIDDATA; + goto error; + } + value = (unary << k) + get_bits(&s->gb, k); + } else + value = unary; + + // FIXME: copy paste from original + switch (depth) { + case 1: + rice->sum1 += value - (rice->sum1 >> 4); + if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1]) + rice->k1--; + else if(rice->sum1 > shift_16[rice->k1 + 1]) + rice->k1++; + value += shift_1[rice->k0]; + default: + rice->sum0 += value - (rice->sum0 >> 4); + if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0]) + rice->k0--; + else if(rice->sum0 > shift_16[rice->k0 + 1]) + rice->k0++; + } + + // extract coded value + *p = 1 + ((value >> 1) ^ ((value & 1) - 1)); + + // run hybrid filter + ttafilter_process(filter, p); + + // fixed order prediction +#define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k) + switch (s->bps) { + case 1: *p += PRED(*predictor, 4); break; + case 2: + case 3: *p += PRED(*predictor, 5); break; + case 4: *p += *predictor; break; + } + *predictor = *p; + + // flip channels + if (cur_chan < (s->channels-1)) + cur_chan++; + else { + // decorrelate in case of multiple channels + if (s->channels > 1) { + int32_t *r = p - 1; + for (*p += *r / 2; r > p - s->channels; r--) + *r = *(r + 1) - *r; + } + cur_chan = 0; + i++; + // check for last frame + if (i == s->last_frame_length && get_bits_left(&s->gb) / 8 == 4) { + frame->nb_samples = framelen = s->last_frame_length; + break; + } + } + } + + align_get_bits(&s->gb); + if (get_bits_left(&s->gb) < 32) { + ret = AVERROR_INVALIDDATA; + goto error; + } + skip_bits_long(&s->gb, 32); // frame crc + + // convert to output buffer + switch (s->bps) { + case 1: { + uint8_t *samples = (uint8_t *)frame->data[0]; + for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) + *samples++ = *p + 0x80; + break; + } + case 2: { + int16_t *samples = (int16_t *)frame->data[0]; + for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) + *samples++ = *p; + break; + } + case 3: { + // shift samples for 24-bit sample format + int32_t *samples = (int32_t *)frame->data[0]; + for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) + *samples++ <<= 8; + // reset decode buffer + s->decode_buffer = NULL; + break; + } + } + + *got_frame_ptr = 1; + + return buf_size; +error: + // reset decode buffer + if (s->bps == 3) + s->decode_buffer = NULL; + return ret; +} + +static av_cold int tta_decode_close(AVCodecContext *avctx) { + TTAContext *s = avctx->priv_data; + + if (s->bps < 3) + av_free(s->decode_buffer); + s->decode_buffer = NULL; + av_freep(&s->ch_ctx); + + return 0; +} + +#define OFFSET(x) offsetof(TTAContext, x) +#define DEC (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) +static const AVOption options[] = { + { "password", "Set decoding password", OFFSET(pass), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC }, + { NULL }, +}; + +static const AVClass tta_decoder_class = { + .class_name = "TTA Decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_tta_decoder = { + .name = "tta", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_TTA, + .priv_data_size = sizeof(TTAContext), + .init = tta_decode_init, + .close = tta_decode_close, + .decode = tta_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), + .priv_class = &tta_decoder_class, +}; diff --git a/ffmpeg/libavcodec/twinvq.c b/ffmpeg/libavcodec/twinvq.c new file mode 100644 index 0000000..8b9c79f --- /dev/null +++ b/ffmpeg/libavcodec/twinvq.c @@ -0,0 +1,1185 @@ +/* + * TwinVQ decoder + * Copyright (c) 2009 Vitor Sessak + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "avcodec.h" +#include "get_bits.h" +#include "fft.h" +#include "internal.h" +#include "lsp.h" +#include "sinewin.h" + +#include +#include + +#include "twinvq_data.h" + +enum FrameType { + FT_SHORT = 0, ///< Short frame (divided in n sub-blocks) + FT_MEDIUM, ///< Medium frame (divided in mmtab; + int size_s = mtab->size / mtab->fmode[FT_SHORT].sub; + + for (i = 0; i < size_s/2; i++) { + float cos_i = tctx->cos_tabs[0][i]; + lpc[i] = eval_lpc_spectrum(cos_vals, cos_i, mtab->n_lsp); + lpc[size_s-i-1] = eval_lpc_spectrum(cos_vals, -cos_i, mtab->n_lsp); + } +} + +static void interpolate(float *out, float v1, float v2, int size) +{ + int i; + float step = (v1 - v2)/(size + 1); + + for (i = 0; i < size; i++) { + v2 += step; + out[i] = v2; + } +} + +static inline float get_cos(int idx, int part, const float *cos_tab, int size) +{ + return part ? -cos_tab[size - idx - 1] : + cos_tab[ idx ]; +} + +/** + * Evaluate the LPC amplitude spectrum envelope from the line spectrum pairs. + * Probably for speed reasons, the coefficients are evaluated as + * siiiibiiiisiiiibiiiisiiiibiiiisiiiibiiiis ... + * where s is an evaluated value, i is a value interpolated from the others + * and b might be either calculated or interpolated, depending on an + * unexplained condition. + * + * @param step the size of a block "siiiibiiii" + * @param in the cosinus of the LSP data + * @param part is 0 for 0...PI (positive cossinus values) and 1 for PI...2PI + (negative cossinus values) + * @param size the size of the whole output + */ +static inline void eval_lpcenv_or_interp(TwinContext *tctx, + enum FrameType ftype, + float *out, const float *in, + int size, int step, int part) +{ + int i; + const ModeTab *mtab = tctx->mtab; + const float *cos_tab = tctx->cos_tabs[ftype]; + + // Fill the 's' + for (i = 0; i < size; i += step) + out[i] = + eval_lpc_spectrum(in, + get_cos(i, part, cos_tab, size), + mtab->n_lsp); + + // Fill the 'iiiibiiii' + for (i = step; i <= size - 2*step; i += step) { + if (out[i + step] + out[i - step] > 1.95*out[i] || + out[i + step] >= out[i - step]) { + interpolate(out + i - step + 1, out[i], out[i-step], step - 1); + } else { + out[i - step/2] = + eval_lpc_spectrum(in, + get_cos(i-step/2, part, cos_tab, size), + mtab->n_lsp); + interpolate(out + i - step + 1, out[i-step/2], out[i-step ], step/2 - 1); + interpolate(out + i - step/2 + 1, out[i ], out[i-step/2], step/2 - 1); + } + } + + interpolate(out + size - 2*step + 1, out[size-step], out[size - 2*step], step - 1); +} + +static void eval_lpcenv_2parts(TwinContext *tctx, enum FrameType ftype, + const float *buf, float *lpc, + int size, int step) +{ + eval_lpcenv_or_interp(tctx, ftype, lpc , buf, size/2, step, 0); + eval_lpcenv_or_interp(tctx, ftype, lpc + size/2, buf, size/2, 2*step, 1); + + interpolate(lpc+size/2-step+1, lpc[size/2], lpc[size/2-step], step); + + memset_float(lpc + size - 2*step + 1, lpc[size - 2*step], 2*step - 1); +} + +/** + * Inverse quantization. Read CB coefficients for cb1 and cb2 from the + * bitstream, sum the corresponding vectors and write the result to *out + * after permutation. + */ +static void dequant(TwinContext *tctx, GetBitContext *gb, float *out, + enum FrameType ftype, + const int16_t *cb0, const int16_t *cb1, int cb_len) +{ + int pos = 0; + int i, j; + + for (i = 0; i < tctx->n_div[ftype]; i++) { + int tmp0, tmp1; + int sign0 = 1; + int sign1 = 1; + const int16_t *tab0, *tab1; + int length = tctx->length[ftype][i >= tctx->length_change[ftype]]; + int bitstream_second_part = (i >= tctx->bits_main_spec_change[ftype]); + + int bits = tctx->bits_main_spec[0][ftype][bitstream_second_part]; + if (bits == 7) { + if (get_bits1(gb)) + sign0 = -1; + bits = 6; + } + tmp0 = get_bits(gb, bits); + + bits = tctx->bits_main_spec[1][ftype][bitstream_second_part]; + + if (bits == 7) { + if (get_bits1(gb)) + sign1 = -1; + + bits = 6; + } + tmp1 = get_bits(gb, bits); + + tab0 = cb0 + tmp0*cb_len; + tab1 = cb1 + tmp1*cb_len; + + for (j = 0; j < length; j++) + out[tctx->permut[ftype][pos+j]] = sign0*tab0[j] + sign1*tab1[j]; + + pos += length; + } + +} + +static inline float mulawinv(float y, float clip, float mu) +{ + y = av_clipf(y/clip, -1, 1); + return clip * FFSIGN(y) * (exp(log(1+mu) * fabs(y)) - 1) / mu; +} + +/** + * Evaluate a*b/400 rounded to the nearest integer. When, for example, + * a*b == 200 and the nearest integer is ill-defined, use a table to emulate + * the following broken float-based implementation used by the binary decoder: + * + * @code + * static int very_broken_op(int a, int b) + * { + * static float test; // Ugh, force gcc to do the division first... + * + * test = a/400.; + * return b * test + 0.5; + * } + * @endcode + * + * @note if this function is replaced by just ROUNDED_DIV(a*b,400.), the stddev + * between the original file (before encoding with Yamaha encoder) and the + * decoded output increases, which leads one to believe that the encoder expects + * exactly this broken calculation. + */ +static int very_broken_op(int a, int b) +{ + int x = a*b + 200; + int size; + const uint8_t *rtab; + + if (x%400 || b%5) + return x/400; + + x /= 400; + + size = tabs[b/5].size; + rtab = tabs[b/5].tab; + return x - rtab[size*av_log2(2*(x - 1)/size)+(x - 1)%size]; +} + +/** + * Sum to data a periodic peak of a given period, width and shape. + * + * @param period the period of the peak divised by 400.0 + */ +static void add_peak(int period, int width, const float *shape, + float ppc_gain, float *speech, int len) +{ + int i, j; + + const float *shape_end = shape + len; + int center; + + // First peak centered around zero + for (i = 0; i < width/2; i++) + speech[i] += ppc_gain * *shape++; + + for (i = 1; i < ROUNDED_DIV(len,width) ; i++) { + center = very_broken_op(period, i); + for (j = -width/2; j < (width+1)/2; j++) + speech[j+center] += ppc_gain * *shape++; + } + + // For the last block, be careful not to go beyond the end of the buffer + center = very_broken_op(period, i); + for (j = -width/2; j < (width + 1)/2 && shape < shape_end; j++) + speech[j+center] += ppc_gain * *shape++; +} + +static void decode_ppc(TwinContext *tctx, int period_coef, const float *shape, + float ppc_gain, float *speech) +{ + const ModeTab *mtab = tctx->mtab; + int isampf = tctx->avctx->sample_rate/1000; + int ibps = tctx->avctx->bit_rate/(1000 * tctx->avctx->channels); + int min_period = ROUNDED_DIV( 40*2*mtab->size, isampf); + int max_period = ROUNDED_DIV(6*40*2*mtab->size, isampf); + int period_range = max_period - min_period; + + // This is actually the period multiplied by 400. It is just linearly coded + // between its maximum and minimum value. + int period = min_period + + ROUNDED_DIV(period_coef*period_range, (1 << mtab->ppc_period_bit) - 1); + int width; + + if (isampf == 22 && ibps == 32) { + // For some unknown reason, NTT decided to code this case differently... + width = ROUNDED_DIV((period + 800)* mtab->peak_per2wid, 400*mtab->size); + } else + width = (period )* mtab->peak_per2wid/(400*mtab->size); + + add_peak(period, width, shape, ppc_gain, speech, mtab->ppc_shape_len); +} + +static void dec_gain(TwinContext *tctx, GetBitContext *gb, enum FrameType ftype, + float *out) +{ + const ModeTab *mtab = tctx->mtab; + int i, j; + int sub = mtab->fmode[ftype].sub; + float step = AMP_MAX / ((1 << GAIN_BITS) - 1); + float sub_step = SUB_AMP_MAX / ((1 << SUB_GAIN_BITS) - 1); + + if (ftype == FT_LONG) { + for (i = 0; i < tctx->avctx->channels; i++) + out[i] = (1./(1<<13)) * + mulawinv(step * 0.5 + step * get_bits(gb, GAIN_BITS), + AMP_MAX, MULAW_MU); + } else { + for (i = 0; i < tctx->avctx->channels; i++) { + float val = (1./(1<<23)) * + mulawinv(step * 0.5 + step * get_bits(gb, GAIN_BITS), + AMP_MAX, MULAW_MU); + + for (j = 0; j < sub; j++) { + out[i*sub + j] = + val*mulawinv(sub_step* 0.5 + + sub_step* get_bits(gb, SUB_GAIN_BITS), + SUB_AMP_MAX, MULAW_MU); + } + } + } +} + +/** + * Rearrange the LSP coefficients so that they have a minimum distance of + * min_dist. This function does it exactly as described in section of 3.2.4 + * of the G.729 specification (but interestingly is different from what the + * reference decoder actually does). + */ +static void rearrange_lsp(int order, float *lsp, float min_dist) +{ + int i; + float min_dist2 = min_dist * 0.5; + for (i = 1; i < order; i++) + if (lsp[i] - lsp[i-1] < min_dist) { + float avg = (lsp[i] + lsp[i-1]) * 0.5; + + lsp[i-1] = avg - min_dist2; + lsp[i ] = avg + min_dist2; + } +} + +static void decode_lsp(TwinContext *tctx, int lpc_idx1, uint8_t *lpc_idx2, + int lpc_hist_idx, float *lsp, float *hist) +{ + const ModeTab *mtab = tctx->mtab; + int i, j; + + const float *cb = mtab->lspcodebook; + const float *cb2 = cb + (1 << mtab->lsp_bit1)*mtab->n_lsp; + const float *cb3 = cb2 + (1 << mtab->lsp_bit2)*mtab->n_lsp; + + const int8_t funny_rounding[4] = { + -2, + mtab->lsp_split == 4 ? -2 : 1, + mtab->lsp_split == 4 ? -2 : 1, + 0 + }; + + j = 0; + for (i = 0; i < mtab->lsp_split; i++) { + int chunk_end = ((i + 1)*mtab->n_lsp + funny_rounding[i])/mtab->lsp_split; + for (; j < chunk_end; j++) + lsp[j] = cb [lpc_idx1 * mtab->n_lsp + j] + + cb2[lpc_idx2[i] * mtab->n_lsp + j]; + } + + rearrange_lsp(mtab->n_lsp, lsp, 0.0001); + + for (i = 0; i < mtab->n_lsp; i++) { + float tmp1 = 1. - cb3[lpc_hist_idx*mtab->n_lsp + i]; + float tmp2 = hist[i] * cb3[lpc_hist_idx*mtab->n_lsp + i]; + hist[i] = lsp[i]; + lsp[i] = lsp[i] * tmp1 + tmp2; + } + + rearrange_lsp(mtab->n_lsp, lsp, 0.0001); + rearrange_lsp(mtab->n_lsp, lsp, 0.000095); + ff_sort_nearly_sorted_floats(lsp, mtab->n_lsp); +} + +static void dec_lpc_spectrum_inv(TwinContext *tctx, float *lsp, + enum FrameType ftype, float *lpc) +{ + int i; + int size = tctx->mtab->size / tctx->mtab->fmode[ftype].sub; + + for (i = 0; i < tctx->mtab->n_lsp; i++) + lsp[i] = 2*cos(lsp[i]); + + switch (ftype) { + case FT_LONG: + eval_lpcenv_2parts(tctx, ftype, lsp, lpc, size, 8); + break; + case FT_MEDIUM: + eval_lpcenv_2parts(tctx, ftype, lsp, lpc, size, 2); + break; + case FT_SHORT: + eval_lpcenv(tctx, lsp, lpc); + break; + } +} + +static void imdct_and_window(TwinContext *tctx, enum FrameType ftype, int wtype, + float *in, float *prev, int ch) +{ + FFTContext *mdct = &tctx->mdct_ctx[ftype]; + const ModeTab *mtab = tctx->mtab; + int bsize = mtab->size / mtab->fmode[ftype].sub; + int size = mtab->size; + float *buf1 = tctx->tmp_buf; + int j; + int wsize; // Window size + float *out = tctx->curr_frame + 2*ch*mtab->size; + float *out2 = out; + float *prev_buf; + int first_wsize; + + static const uint8_t wtype_to_wsize[] = {0, 0, 2, 2, 2, 1, 0, 1, 1}; + int types_sizes[] = { + mtab->size / mtab->fmode[FT_LONG ].sub, + mtab->size / mtab->fmode[FT_MEDIUM].sub, + mtab->size / (2*mtab->fmode[FT_SHORT ].sub), + }; + + wsize = types_sizes[wtype_to_wsize[wtype]]; + first_wsize = wsize; + prev_buf = prev + (size - bsize)/2; + + for (j = 0; j < mtab->fmode[ftype].sub; j++) { + int sub_wtype = ftype == FT_MEDIUM ? 8 : wtype; + + if (!j && wtype == 4) + sub_wtype = 4; + else if (j == mtab->fmode[ftype].sub-1 && wtype == 7) + sub_wtype = 7; + + wsize = types_sizes[wtype_to_wsize[sub_wtype]]; + + mdct->imdct_half(mdct, buf1 + bsize*j, in + bsize*j); + + tctx->fdsp.vector_fmul_window(out2, prev_buf + (bsize-wsize) / 2, + buf1 + bsize * j, + ff_sine_windows[av_log2(wsize)], + wsize / 2); + out2 += wsize; + + memcpy(out2, buf1 + bsize*j + wsize/2, (bsize - wsize/2)*sizeof(float)); + + out2 += ftype == FT_MEDIUM ? (bsize-wsize)/2 : bsize - wsize; + + prev_buf = buf1 + bsize*j + bsize/2; + } + + tctx->last_block_pos[ch] = (size + first_wsize)/2; +} + +static void imdct_output(TwinContext *tctx, enum FrameType ftype, int wtype, + float **out) +{ + const ModeTab *mtab = tctx->mtab; + int size1, size2; + float *prev_buf = tctx->prev_frame + tctx->last_block_pos[0]; + int i; + + for (i = 0; i < tctx->avctx->channels; i++) { + imdct_and_window(tctx, ftype, wtype, + tctx->spectrum + i*mtab->size, + prev_buf + 2*i*mtab->size, + i); + } + + if (!out) + return; + + size2 = tctx->last_block_pos[0]; + size1 = mtab->size - size2; + + memcpy(&out[0][0 ], prev_buf, size1 * sizeof(out[0][0])); + memcpy(&out[0][size1], tctx->curr_frame, size2 * sizeof(out[0][0])); + + if (tctx->avctx->channels == 2) { + memcpy(&out[1][0], &prev_buf[2*mtab->size], size1 * sizeof(out[1][0])); + memcpy(&out[1][size1], &tctx->curr_frame[2*mtab->size], size2 * sizeof(out[1][0])); + tctx->fdsp.butterflies_float(out[0], out[1], mtab->size); + } +} + +static void dec_bark_env(TwinContext *tctx, const uint8_t *in, int use_hist, + int ch, float *out, float gain, enum FrameType ftype) +{ + const ModeTab *mtab = tctx->mtab; + int i,j; + float *hist = tctx->bark_hist[ftype][ch]; + float val = ((const float []) {0.4, 0.35, 0.28})[ftype]; + int bark_n_coef = mtab->fmode[ftype].bark_n_coef; + int fw_cb_len = mtab->fmode[ftype].bark_env_size / bark_n_coef; + int idx = 0; + + for (i = 0; i < fw_cb_len; i++) + for (j = 0; j < bark_n_coef; j++, idx++) { + float tmp2 = + mtab->fmode[ftype].bark_cb[fw_cb_len*in[j] + i] * (1./4096); + float st = use_hist ? + (1. - val) * tmp2 + val*hist[idx] + 1. : tmp2 + 1.; + + hist[idx] = tmp2; + if (st < -1.) st = 1.; + + memset_float(out, st * gain, mtab->fmode[ftype].bark_tab[idx]); + out += mtab->fmode[ftype].bark_tab[idx]; + } + +} + +static void read_and_decode_spectrum(TwinContext *tctx, GetBitContext *gb, + float *out, enum FrameType ftype) +{ + const ModeTab *mtab = tctx->mtab; + int channels = tctx->avctx->channels; + int sub = mtab->fmode[ftype].sub; + int block_size = mtab->size / sub; + float gain[CHANNELS_MAX*SUBBLOCKS_MAX]; + float ppc_shape[PPC_SHAPE_LEN_MAX * CHANNELS_MAX * 4]; + uint8_t bark1[CHANNELS_MAX][SUBBLOCKS_MAX][BARK_N_COEF_MAX]; + uint8_t bark_use_hist[CHANNELS_MAX][SUBBLOCKS_MAX]; + + uint8_t lpc_idx1[CHANNELS_MAX]; + uint8_t lpc_idx2[CHANNELS_MAX][LSP_SPLIT_MAX]; + uint8_t lpc_hist_idx[CHANNELS_MAX]; + + int i, j, k; + + dequant(tctx, gb, out, ftype, + mtab->fmode[ftype].cb0, mtab->fmode[ftype].cb1, + mtab->fmode[ftype].cb_len_read); + + for (i = 0; i < channels; i++) + for (j = 0; j < sub; j++) + for (k = 0; k < mtab->fmode[ftype].bark_n_coef; k++) + bark1[i][j][k] = + get_bits(gb, mtab->fmode[ftype].bark_n_bit); + + for (i = 0; i < channels; i++) + for (j = 0; j < sub; j++) + bark_use_hist[i][j] = get_bits1(gb); + + dec_gain(tctx, gb, ftype, gain); + + for (i = 0; i < channels; i++) { + lpc_hist_idx[i] = get_bits(gb, tctx->mtab->lsp_bit0); + lpc_idx1 [i] = get_bits(gb, tctx->mtab->lsp_bit1); + + for (j = 0; j < tctx->mtab->lsp_split; j++) + lpc_idx2[i][j] = get_bits(gb, tctx->mtab->lsp_bit2); + } + + if (ftype == FT_LONG) { + int cb_len_p = (tctx->n_div[3] + mtab->ppc_shape_len*channels - 1)/ + tctx->n_div[3]; + dequant(tctx, gb, ppc_shape, FT_PPC, mtab->ppc_shape_cb, + mtab->ppc_shape_cb + cb_len_p*PPC_SHAPE_CB_SIZE, cb_len_p); + } + + for (i = 0; i < channels; i++) { + float *chunk = out + mtab->size * i; + float lsp[LSP_COEFS_MAX]; + + for (j = 0; j < sub; j++) { + dec_bark_env(tctx, bark1[i][j], bark_use_hist[i][j], i, + tctx->tmp_buf, gain[sub*i+j], ftype); + + tctx->fdsp.vector_fmul(chunk + block_size*j, chunk + block_size*j, + tctx->tmp_buf, block_size); + + } + + if (ftype == FT_LONG) { + float pgain_step = 25000. / ((1 << mtab->pgain_bit) - 1); + int p_coef = get_bits(gb, tctx->mtab->ppc_period_bit); + int g_coef = get_bits(gb, tctx->mtab->pgain_bit); + float v = 1./8192* + mulawinv(pgain_step*g_coef+ pgain_step/2, 25000., PGAIN_MU); + + decode_ppc(tctx, p_coef, ppc_shape + i*mtab->ppc_shape_len, v, + chunk); + } + + decode_lsp(tctx, lpc_idx1[i], lpc_idx2[i], lpc_hist_idx[i], lsp, + tctx->lsp_hist[i]); + + dec_lpc_spectrum_inv(tctx, lsp, ftype, tctx->tmp_buf); + + for (j = 0; j < mtab->fmode[ftype].sub; j++) { + tctx->fdsp.vector_fmul(chunk, chunk, tctx->tmp_buf, block_size); + chunk += block_size; + } + } +} + +static int twin_decode_frame(AVCodecContext * avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + TwinContext *tctx = avctx->priv_data; + GetBitContext gb; + const ModeTab *mtab = tctx->mtab; + float **out = NULL; + enum FrameType ftype; + int window_type, ret; + static const enum FrameType wtype_to_ftype_table[] = { + FT_LONG, FT_LONG, FT_SHORT, FT_LONG, + FT_MEDIUM, FT_LONG, FT_LONG, FT_MEDIUM, FT_MEDIUM + }; + + if (buf_size*8 < avctx->bit_rate*mtab->size/avctx->sample_rate + 8) { + av_log(avctx, AV_LOG_ERROR, + "Frame too small (%d bytes). Truncated file?\n", buf_size); + return AVERROR(EINVAL); + } + + /* get output buffer */ + if (tctx->discarded_packets >= 2) { + frame->nb_samples = mtab->size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + out = (float **)frame->extended_data; + } + + init_get_bits(&gb, buf, buf_size * 8); + skip_bits(&gb, get_bits(&gb, 8)); + window_type = get_bits(&gb, WINDOW_TYPE_BITS); + + if (window_type > 8) { + av_log(avctx, AV_LOG_ERROR, "Invalid window type, broken sample?\n"); + return -1; + } + + ftype = wtype_to_ftype_table[window_type]; + + read_and_decode_spectrum(tctx, &gb, tctx->spectrum, ftype); + + imdct_output(tctx, ftype, window_type, out); + + FFSWAP(float*, tctx->curr_frame, tctx->prev_frame); + + if (tctx->discarded_packets < 2) { + tctx->discarded_packets++; + *got_frame_ptr = 0; + return buf_size; + } + + *got_frame_ptr = 1; + + return buf_size; +} + +/** + * Init IMDCT and windowing tables + */ +static av_cold int init_mdct_win(TwinContext *tctx) +{ + int i, j, ret; + const ModeTab *mtab = tctx->mtab; + int size_s = mtab->size / mtab->fmode[FT_SHORT].sub; + int size_m = mtab->size / mtab->fmode[FT_MEDIUM].sub; + int channels = tctx->avctx->channels; + float norm = channels == 1 ? 2. : 1.; + + for (i = 0; i < 3; i++) { + int bsize = tctx->mtab->size/tctx->mtab->fmode[i].sub; + if ((ret = ff_mdct_init(&tctx->mdct_ctx[i], av_log2(bsize) + 1, 1, + -sqrt(norm/bsize) / (1<<15)))) + return ret; + } + + FF_ALLOC_OR_GOTO(tctx->avctx, tctx->tmp_buf, + mtab->size * sizeof(*tctx->tmp_buf), alloc_fail); + + FF_ALLOC_OR_GOTO(tctx->avctx, tctx->spectrum, + 2 * mtab->size * channels * sizeof(*tctx->spectrum), + alloc_fail); + FF_ALLOC_OR_GOTO(tctx->avctx, tctx->curr_frame, + 2 * mtab->size * channels * sizeof(*tctx->curr_frame), + alloc_fail); + FF_ALLOC_OR_GOTO(tctx->avctx, tctx->prev_frame, + 2 * mtab->size * channels * sizeof(*tctx->prev_frame), + alloc_fail); + + for (i = 0; i < 3; i++) { + int m = 4*mtab->size/mtab->fmode[i].sub; + double freq = 2*M_PI/m; + FF_ALLOC_OR_GOTO(tctx->avctx, tctx->cos_tabs[i], + (m / 4) * sizeof(*tctx->cos_tabs[i]), alloc_fail); + + for (j = 0; j <= m/8; j++) + tctx->cos_tabs[i][j] = cos((2*j + 1)*freq); + for (j = 1; j < m/8; j++) + tctx->cos_tabs[i][m/4-j] = tctx->cos_tabs[i][j]; + } + + + ff_init_ff_sine_windows(av_log2(size_m)); + ff_init_ff_sine_windows(av_log2(size_s/2)); + ff_init_ff_sine_windows(av_log2(mtab->size)); + + return 0; +alloc_fail: + return AVERROR(ENOMEM); +} + +/** + * Interpret the data as if it were a num_blocks x line_len[0] matrix and for + * each line do a cyclic permutation, i.e. + * abcdefghijklm -> defghijklmabc + * where the amount to be shifted is evaluated depending on the column. + */ +static void permutate_in_line(int16_t *tab, int num_vect, int num_blocks, + int block_size, + const uint8_t line_len[2], int length_div, + enum FrameType ftype) + +{ + int i,j; + + for (i = 0; i < line_len[0]; i++) { + int shift; + + if (num_blocks == 1 || + (ftype == FT_LONG && num_vect % num_blocks) || + (ftype != FT_LONG && num_vect & 1 ) || + i == line_len[1]) { + shift = 0; + } else if (ftype == FT_LONG) { + shift = i; + } else + shift = i*i; + + for (j = 0; j < num_vect && (j+num_vect*i < block_size*num_blocks); j++) + tab[i*num_vect+j] = i*num_vect + (j + shift) % num_vect; + } +} + +/** + * Interpret the input data as in the following table: + * + * @verbatim + * + * abcdefgh + * ijklmnop + * qrstuvw + * x123456 + * + * @endverbatim + * + * and transpose it, giving the output + * aiqxbjr1cks2dlt3emu4fvn5gow6hp + */ +static void transpose_perm(int16_t *out, int16_t *in, int num_vect, + const uint8_t line_len[2], int length_div) +{ + int i,j; + int cont= 0; + for (i = 0; i < num_vect; i++) + for (j = 0; j < line_len[i >= length_div]; j++) + out[cont++] = in[j*num_vect + i]; +} + +static void linear_perm(int16_t *out, int16_t *in, int n_blocks, int size) +{ + int block_size = size/n_blocks; + int i; + + for (i = 0; i < size; i++) + out[i] = block_size * (in[i] % n_blocks) + in[i] / n_blocks; +} + +static av_cold void construct_perm_table(TwinContext *tctx,enum FrameType ftype) +{ + int block_size; + const ModeTab *mtab = tctx->mtab; + int size; + int16_t *tmp_perm = (int16_t *) tctx->tmp_buf; + + if (ftype == FT_PPC) { + size = tctx->avctx->channels; + block_size = mtab->ppc_shape_len; + } else { + size = tctx->avctx->channels * mtab->fmode[ftype].sub; + block_size = mtab->size / mtab->fmode[ftype].sub; + } + + permutate_in_line(tmp_perm, tctx->n_div[ftype], size, + block_size, tctx->length[ftype], + tctx->length_change[ftype], ftype); + + transpose_perm(tctx->permut[ftype], tmp_perm, tctx->n_div[ftype], + tctx->length[ftype], tctx->length_change[ftype]); + + linear_perm(tctx->permut[ftype], tctx->permut[ftype], size, + size*block_size); +} + +static av_cold void init_bitstream_params(TwinContext *tctx) +{ + const ModeTab *mtab = tctx->mtab; + int n_ch = tctx->avctx->channels; + int total_fr_bits = tctx->avctx->bit_rate*mtab->size/ + tctx->avctx->sample_rate; + + int lsp_bits_per_block = n_ch*(mtab->lsp_bit0 + mtab->lsp_bit1 + + mtab->lsp_split*mtab->lsp_bit2); + + int ppc_bits = n_ch*(mtab->pgain_bit + mtab->ppc_shape_bit + + mtab->ppc_period_bit); + + int bsize_no_main_cb[3]; + int bse_bits[3]; + int i; + enum FrameType frametype; + + for (i = 0; i < 3; i++) + // +1 for history usage switch + bse_bits[i] = n_ch * + (mtab->fmode[i].bark_n_coef * mtab->fmode[i].bark_n_bit + 1); + + bsize_no_main_cb[2] = bse_bits[2] + lsp_bits_per_block + ppc_bits + + WINDOW_TYPE_BITS + n_ch*GAIN_BITS; + + for (i = 0; i < 2; i++) + bsize_no_main_cb[i] = + lsp_bits_per_block + n_ch*GAIN_BITS + WINDOW_TYPE_BITS + + mtab->fmode[i].sub*(bse_bits[i] + n_ch*SUB_GAIN_BITS); + + // The remaining bits are all used for the main spectrum coefficients + for (i = 0; i < 4; i++) { + int bit_size; + int vect_size; + int rounded_up, rounded_down, num_rounded_down, num_rounded_up; + if (i == 3) { + bit_size = n_ch * mtab->ppc_shape_bit; + vect_size = n_ch * mtab->ppc_shape_len; + } else { + bit_size = total_fr_bits - bsize_no_main_cb[i]; + vect_size = n_ch * mtab->size; + } + + tctx->n_div[i] = (bit_size + 13) / 14; + + rounded_up = (bit_size + tctx->n_div[i] - 1)/tctx->n_div[i]; + rounded_down = (bit_size )/tctx->n_div[i]; + num_rounded_down = rounded_up * tctx->n_div[i] - bit_size; + num_rounded_up = tctx->n_div[i] - num_rounded_down; + tctx->bits_main_spec[0][i][0] = (rounded_up + 1)/2; + tctx->bits_main_spec[1][i][0] = (rounded_up )/2; + tctx->bits_main_spec[0][i][1] = (rounded_down + 1)/2; + tctx->bits_main_spec[1][i][1] = (rounded_down )/2; + tctx->bits_main_spec_change[i] = num_rounded_up; + + rounded_up = (vect_size + tctx->n_div[i] - 1)/tctx->n_div[i]; + rounded_down = (vect_size )/tctx->n_div[i]; + num_rounded_down = rounded_up * tctx->n_div[i] - vect_size; + num_rounded_up = tctx->n_div[i] - num_rounded_down; + tctx->length[i][0] = rounded_up; + tctx->length[i][1] = rounded_down; + tctx->length_change[i] = num_rounded_up; + } + + for (frametype = FT_SHORT; frametype <= FT_PPC; frametype++) + construct_perm_table(tctx, frametype); +} + +static av_cold int twin_decode_close(AVCodecContext *avctx) +{ + TwinContext *tctx = avctx->priv_data; + int i; + + for (i = 0; i < 3; i++) { + ff_mdct_end(&tctx->mdct_ctx[i]); + av_free(tctx->cos_tabs[i]); + } + + + av_free(tctx->curr_frame); + av_free(tctx->spectrum); + av_free(tctx->prev_frame); + av_free(tctx->tmp_buf); + + return 0; +} + +static av_cold int twin_decode_init(AVCodecContext *avctx) +{ + int ret; + TwinContext *tctx = avctx->priv_data; + int isampf, ibps; + + tctx->avctx = avctx; + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + if (!avctx->extradata || avctx->extradata_size < 12) { + av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n"); + return AVERROR_INVALIDDATA; + } + avctx->channels = AV_RB32(avctx->extradata ) + 1; + avctx->bit_rate = AV_RB32(avctx->extradata + 4) * 1000; + isampf = AV_RB32(avctx->extradata + 8); + + if (isampf < 8 || isampf > 44) { + av_log(avctx, AV_LOG_ERROR, "Unsupported sample rate\n"); + return AVERROR_INVALIDDATA; + } + switch (isampf) { + case 44: avctx->sample_rate = 44100; break; + case 22: avctx->sample_rate = 22050; break; + case 11: avctx->sample_rate = 11025; break; + default: avctx->sample_rate = isampf * 1000; break; + } + + if (avctx->channels <= 0 || avctx->channels > CHANNELS_MAX) { + av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n", + avctx->channels); + return -1; + } + avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + + ibps = avctx->bit_rate / (1000 * avctx->channels); + + if (ibps > 255U) { + av_log(avctx, AV_LOG_ERROR, "unsupported per channel bitrate %dkbps\n", ibps); + return AVERROR_INVALIDDATA; + } + + switch ((isampf << 8) + ibps) { + case (8 <<8) + 8: tctx->mtab = &mode_08_08; break; + case (11<<8) + 8: tctx->mtab = &mode_11_08; break; + case (11<<8) + 10: tctx->mtab = &mode_11_10; break; + case (16<<8) + 16: tctx->mtab = &mode_16_16; break; + case (22<<8) + 20: tctx->mtab = &mode_22_20; break; + case (22<<8) + 24: tctx->mtab = &mode_22_24; break; + case (22<<8) + 32: tctx->mtab = &mode_22_32; break; + case (44<<8) + 40: tctx->mtab = &mode_44_40; break; + case (44<<8) + 48: tctx->mtab = &mode_44_48; break; + default: + av_log(avctx, AV_LOG_ERROR, "This version does not support %d kHz - %d kbit/s/ch mode.\n", isampf, isampf); + return -1; + } + + avpriv_float_dsp_init(&tctx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + if ((ret = init_mdct_win(tctx))) { + av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); + twin_decode_close(avctx); + return ret; + } + init_bitstream_params(tctx); + + memset_float(tctx->bark_hist[0][0], 0.1, FF_ARRAY_ELEMS(tctx->bark_hist)); + + return 0; +} + +AVCodec ff_twinvq_decoder = { + .name = "twinvq", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_TWINVQ, + .priv_data_size = sizeof(TwinContext), + .init = twin_decode_init, + .close = twin_decode_close, + .decode = twin_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/twinvq_data.h b/ffmpeg/libavcodec/twinvq_data.h new file mode 100644 index 0000000..63911f8 --- /dev/null +++ b/ffmpeg/libavcodec/twinvq_data.h @@ -0,0 +1,11137 @@ +/* + * TwinVQ decoder + * Copyright (c) 2009 Vitor Sessak + * + * 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 + */ + +#ifndef AVCODEC_TWINVQ_DATA_H +#define AVCODEC_TWINVQ_DATA_H + +#include +#include + +/* + * The bark_tab_* tables are constructed so that + * + * /i-1 \ + * |-- | + * bark |\ bark_tab[j] | == i + * |/ | + * |-- | + * \j=0 / + * + * + * for some slightly nonconventional bark-scale function + */ +static const uint16_t bark_tab_l08_512[] = { + 7, 8, 7, 8, 8, 8, 8, 8, 8, 9, + 9, 10, 10, 11, 11, 12, 12, 14, 15, 16, + 18, 19, 21, 24, 27, 30, 35, 40, 46, 53 +}; + +static const uint16_t bark_tab_l11_512[] = { + 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, + 8, 8, 8, 9, 10, 10, 11, 13, 13, 15, + 17, 18, 21, 25, 27, 33, 38, 45, 54, 66 +}; + +static const uint16_t bark_tab_l16_1024[] = { + 9, 9, 8, 9, 10, 9, 10, 10, 10, 12, + 11, 13, 13, 14, 16, 17, 19, 20, 24, 26, + 30, 35, 40, 48, 56, 68, 83, 102, 128, 165 +}; + +static const uint16_t bark_tab_l22_1024[] = { + 6, 7, 6, 6, 7, 7, 7, 7, 7, 8, + 9, 8, 10, 10, 11, 12, 13, 15, 16, 18, + 21, 24, 27, 33, 38, 46, 55, 68, 84, 107, + 140, 191 +}; + +static const uint16_t bark_tab_l22_512[] = { + 3, 3, 3, 4, 3, 3, 4, 3, 4, 4, + 4, 5, 4, 5, 6, 6, 7, 7, 8, 9, + 10, 12, 14, 16, 20, 22, 28, 34, 42, 53, + 71, 95 +}; + +static const uint16_t bark_tab_l44_2048[] = { + 5, 6, 5, 6, 5, 6, 6, 6, 6, 6, + 7, 7, 7, 8, 8, 9, 9, 10, 11, 11, + 13, 14, 16, 17, 19, 22, 25, 29, 33, 39, + 46, 54, 64, 79, 98, 123, 161, 220, 320, 512 +}; + +static const uint16_t bark_tab_m08_256[] = { + 6, 5, 6, 6, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 13, 15, 18, 20, 25, 31, 39 +}; + +static const uint16_t bark_tab_m11_256[] = { + 4, 5, 4, 5, 5, 5, 6, 5, 7, 7, + 8, 9, 10, 12, 15, 17, 22, 28, 35, 47 +}; + +static const uint16_t bark_tab_m16_512[] = { + 7, 6, 7, 7, 7, 8, 9, 9, 10, 11, + 14, 15, 18, 22, 27, 34, 44, 59, 81, 117 +}; + +static const uint16_t bark_tab_m22_256[] = { + 3, 2, 3, 2, 3, 3, 4, 3, 4, 5, + 5, 7, 8, 9, 13, 16, 22, 30, 44, 70 +}; + +static const uint16_t bark_tab_m22_512[] = { + 5, 5, 5, 6, 5, 7, 6, 7, 9, 9, + 11, 13, 15, 20, 24, 33, 43, 61, 88, 140 +}; + +static const uint16_t bark_tab_m44_512[] = { + 3, 2, 3, 3, 3, 4, 3, 5, 4, 6, + 7, 8, 10, 14, 18, 25, 36, 55, 95, 208 +}; + +static const uint16_t bark_tab_s08_64[] = { + 3, 3, 3, 3, 4, 5, 6, 8, 12, 17 +}; + +static const uint16_t bark_tab_s11_64[] = { + 2, 3, 2, 3, 3, 4, 6, 8, 12, 21 +}; + +static const uint16_t bark_tab_s16_128[] = { + 3, 4, 4, 4, 5, 7, 10, 16, 26, 49 +}; + +static const uint16_t bark_tab_s22_128[] = { + 3, 2, 3, 4, 4, 6, 9, 14, 26, 57 +}; + +static const uint16_t bark_tab_s44_128[] = { + 1, 2, 1, 2, 3, 4, 6, 10, 23, 76 +}; + + +/** + * TwinVQ codebooks. They are coded in a struct so we can use code such as + * + * float val = tab.fcb0808l[get_bits(gb, 12)]; + * + * without risking a segfault on malformed files. + */ +static const struct twinvq_data { + float lsp08[504]; + int16_t fcb08l[640]; + int16_t fcb08m[320]; + int16_t fcb08s[320]; + int16_t shape08[1280]; + + int16_t cb0808l0[1088]; + int16_t cb0808l1[1088]; + int16_t cb0808s0[1152]; + int16_t cb0808s1[1152]; + int16_t cb0808m0[1024]; + int16_t cb0808m1[1024]; + + int16_t cb1108l0[1728]; + int16_t cb1108l1[1728]; + int16_t cb1108m0[1536]; + int16_t cb1108m1[1536]; + int16_t cb1108s0[1856]; + int16_t cb1108s1[1856]; + + int16_t fcb11l[640]; + int16_t fcb11m[320]; + int16_t fcb11s[320]; + int16_t shape11[1280]; + float lsp11[1312]; + + int16_t cb1110l0[1280]; + int16_t cb1110l1[1280]; + int16_t cb1110m0[1152]; + int16_t cb1110m1[1152]; + int16_t cb1110s0[1344]; + int16_t cb1110s1[1344]; + + int16_t fcb16l[640]; + int16_t fcb16m[320]; + int16_t fcb16s[320]; + int16_t shape16[1920]; + float lsp16[1400]; + + int16_t cb1616l0[1024]; + int16_t cb1616l1[1024]; + int16_t cb1616m0[960]; + int16_t cb1616m1[960]; + int16_t cb1616s0[1024]; + int16_t cb1616s1[1024]; + + int16_t cb2220l0[1152]; + int16_t cb2220l1[1152]; + int16_t cb2220m0[1088]; + int16_t cb2220m1[1088]; + int16_t cb2220s0[1152]; + int16_t cb2220s1[1152]; + + int16_t fcb22l_1[512]; + int16_t fcb22m_1[640]; + int16_t fcb22s_1[640]; + int16_t shape22_1[1152]; + float lsp22_1[1312]; + + int16_t cb2224l0[960]; + int16_t cb2224l1[960]; + int16_t cb2224m0[896]; + int16_t cb2224m1[896]; + int16_t cb2224s0[960]; + int16_t cb2224s1[960]; + + int16_t fcb22l_2[512]; + int16_t fcb22m_2[640]; + int16_t fcb22s_2[640]; + int16_t shape22_2[1152]; + float lsp22_2[1312]; + + int16_t cb2232l0[768]; + int16_t cb2232l1[768]; + int16_t cb2232m0[704]; + int16_t cb2232m1[704]; + int16_t cb2232s0[704]; + int16_t cb2232s1[704]; + + int16_t cb4440l0[1088]; + int16_t cb4440l1[1088]; + int16_t cb4440m0[1088]; + int16_t cb4440m1[1088]; + int16_t cb4440s0[1152]; + int16_t cb4440s1[1152]; + + int16_t fcb44l[640]; + int16_t fcb44m[640]; + int16_t fcb44s[640]; + int16_t shape44[1152]; + float lsp44[1640]; + + int16_t cb4448l0[896]; + int16_t cb4448l1[896]; + int16_t cb4448m0[896]; + int16_t cb4448m1[896]; + int16_t cb4448s0[960]; + int16_t cb4448s1[960]; +} tab = { +.cb0808l0 = { + 96, -12592, -12443, 425, 182, -456, -341, -843, + 615, 689, 982, 1470, -518, 231, -538, 282, + 409, -600, -303, -29, 51, -4, -115, 79, + -27, 450, -937, -461, -554, -159, 426, 710, +-29106, -2148, 99, 3426, 1838, 12427, 585, -2080, + -2524, -474, 1572, 718, 578, -344, 188, 328, + 12125, 112, 654, -1232, -1644, 288, 553, 1513, + 966, 1012, 49, 631, -111, -238, -116, -182, + -21, -46, 334, 11013, -454, -261, 12, 21, + 52, -20440, -295, -502, -516, -329, -230, 465, + 59, 270, 971, -127, 505, -194, 43, -30, + 300, 38, 665, -613, 33, -172, -153, 323, + -166, 54, 399, 109, 186, -1765, -222, 138, + 16, 204, 30111, 208, -564, -612, 156, -146, + -345, 321, -138, 202, -184, 93, 710, -15945, +-13401, 234, -1113, 146, -9, 56, -628, -834, + -1268, 872, 61, -1184, -126, -205, 145, -109, + -8248, 113, -146, 1288, 9142, 857, -782, -686, + -256, -650, 1061, -202, 12, -709, -88, 273, + 497, 150, -59, -8807, 240, 532, 16, 1482, + 11012, -444, 1918, -1786, 1934, 172, 598, -1324, + 5638, -3166, 492, -545, -770, 1067, 0, -356, + -421, 1684, 273, -502, 316, 1116, 807, -529, + -831, -13379, -420, 236, 470, -2590, -193, -47, + 580, -1613, 798, 27, -16, -12768, -893, 256, + 0, 1659, 1463, 544, 196, -30444, 314, -421, + 508, -276, -173, 414, -380, -371, -40, -121, + 375, 432, -438, 1, -350, -280, 1198, -373, + 452, 100, -68, 9053, 165, 770, 73, 291, + 717, 515, 596, -323, -4, -2, 803, 738, + 2605, 30, 73, 455, 11280, 1534, -283, 1502, + -9126, -4760, -570, 483, -179, -8628, -1639, 322, + -56, 6149, -3330, 114, 4598, -1976, -34, -56, + 840, 753, 12292, -7100, -492, 320, -412, 908, + 1186, 444, 6546, -788, 5394, 697, 13105, 194, + -394, 294, 2639, 12, -1009, -1426, -36, 2106, + -252, -31979, -66, 341, 996, 298, 105, 6, + 10, 106, -498, -244, -105, -574, 16, -206, + 24, -2067, -381, 10265, -103, -762, -785, -2036, +-11927, 16, -710, -35, -270, -99, 4, 772, + -272, -186, -328, -14936, -57, -1357, -175, -606, + 220, 918, -11, 398, -189, -278, 138, 429, + 509, -701, -43, -42, -630, -560, 11736, -528, + 10286, -633, -870, 423, 550, -888, 297, -170, + 258, 2234, 486, 292, -446, -11858, 10008, 52, + 1203, -164, 810, -1527, -604, -883, -588, -96, + 332, 148, -180, 223, 356, 285, 434, -57, + -172, -520, -432, -72, 294, -93, -134, 316, + 30647, -351, 278, 84, -439, 589, 105, 1001, + 297, 660, 196, 171, 178, -90, -55, 1172, + 21100, 227, -288, 372, 162, 458, -555, -1329, + 380, 366, -104, 105, 674, -378, 1328, 283, + -1928, 549, 762, 454, 55, 606, 12499, 24, + 435, 23, 29, 6170, 1129, -95, 97, 569, + 132, 491, 164, -288, -1011, -134, 1234, -427, + -254, -524, 226, -14114, 328, -70, 1666, -189, + -2352, 1097, 619, 632, -981, 745, 587, -27, + -200, -871, 50, 470, -246, 2610, 581, 254, + 9893, -586, 880, -11894, 386, 1135, 117, 1072, + 116, -830, -160, -1002, -699, -66, -230, -260, + 112, 106, 221, 297, -47, 7642, 170, -330, + -599, -51, -476, 33, 475, 624, 6199, -350, + -406, 184, 906, -528, 382, 401, 348, 26, + -186, 33, -130, -62, -50, 1268, -132, -109, + 1164, -354, 675, 3, -402, -244, 644, 648, + -132, -4, 45, 20386, -136, 568, 126, 376, + 14476, -376, 267, 13518, -260, 111, 1014, 758, + 439, 551, -164, 207, 128, -416, 616, 690, + -9460, -1856, 1123, 826, -265, -762, 1596, -632, + 52, -622, -894, 367, -433, -100, 1873, 756, +-17436, 168, -541, 550, 145, -5612, -1057, -1344, + -656, -194, 216, -500, -245, 246, 64, 688, + 727, 12538, -5492, 252, -908, -424, -532, -659, + -277, -230, -736, -183, 35, -228, 200, -12, + -248, -60, -493, 433, 446, 366, -644, 92, + -324, 29, 833, -21542, -977, 94, 379, 49, + -1058, 248, -178, 85, -961, -1198, -48, 467, + -242, -10202, 1556, 11263, -716, 814, -1686, 3594, + -27, 694, -802, 390, 4144, -663, 44, -546, + 312, -28, -484, 981, -307, 496, 408, 203, + 12543, 296, -1240, 159, 846, -957, -1493, -618, + 1593, 11868, 2616, 1954, 412, -922, -1320, 3325, + -254, -1892, 607, -2223, -8745, -1486, 17, 343, + -50, -562, 22011, -350, -491, -70, -60, 617, + 768, -346, 387, 660, 1409, 222, 616, 173, + -1323, 4017, -207, -525, -13243, 11, 440, -614, + -280, 549, -670, -79, 459, 560, -102, -214, + -54, -1201, 230, -526, 857, 1044, -369, 2470, +-11010, -12586, 243, -205, 838, -920, 348, -738, + 1319, 86, -78, -428, -1909, -155, 2, 508, + 711, -292, 1699, 225, -101, -163, 540, 9692, + 235, -183, -38, 198, -466, -204, -8957, -914, + -299, 193, 10, 723, 643, -533, -1418, 323, + 20, 334, -886, -331, 368, 130, -30233, -152, + -14, 637, 132, -232, -149, -430, 64, -243, + -376, 370, 388, 196, -1098, 117, -794, -16, + -274, 348, 464, -28156, 184, 322, -101, 2, + -27, -183, 610, 256, -160, -573, -226, 588, + 1613, 1028, 9518, -2151, -1602, -528, -356, -116, +-11511, 1828, -2206, -47, -757, -1479, -1429, -14717, + 1686, 253, 802, 462, -37, -916, -289, -401, + 13383, 353, -74, 114, -189, 636, 434, -639, + 1013, 234, 11752, 219, 1464, -132, -12838, 125, + -592, -40, -162, -1772, 506, 479, 422, 36, + 15, -960, 799, 517, 1311, -409, 748, 729, + 446, 11029, -13039, 1257, -651, -13, -742, 1416, + -388, -274, -795, 163, -572, 74, 430, -90, + -126, -74, -598, 140, 125, -20, -20332, 208, + 37, 19, -174, -209, 305, 28, -402, 28, + -315, -1, -134, 440, -832, 79, -635, -304, + 8, -32768, 625, 470, -1224, -351, 546, -1171, + -706, 652, 31, 7484, -448, 916, 1244, -379, + -300, 68, 868, 607, 247, 70, -984, 14314, + 21, -350, -82, 368, 456, -742, 472, 34, + 782, -498, -879, 700, 417, 216, 415, -161, + -181, -608, 1570, 862, -96, -114, 8095, -26, + 168, -363, -804, -36, -770, 139, -171, 6645, + -1425, 4826, -5288, 1358, -11747, -64, 650, -3206, + -1692, 789, -2047, -279, 916, -1648, 1164, 2044, + -144, -717, -392, -216, 372, 348, 1052, -175, + 668, 308, -15, 29112, -406, -774, 365, -1006, + -526, 1076, 59, -672, -87, -106, 174, 96, + 615, 462, -43, -496, 112, 149, -56, -182, + -268, -32768, -205, -676, 165, -1210, -325, 7964, + -44, 546, -699, 285, -418, 355, 238, 550, + 67, 425, 384, -950, -330, -208, -452, 212, + 11610, -190, 37, -907, -11137, -982, 585, -783, + -864, 164, -24, -514, -211, 2, -510, -580, + 595, 128, 100, -229, -55, 290, -539, 40, + -7786, -270, 295, -508, 562, -1196, 218, 33, + 3788, -8954, -1082, 297, -906, -322, 123, 1162, + -343, -11655, 88, -28, 1173, 9, -99, 36, +-11987, 356, 12630, 767, -183, -983, -559, 186, + 1148, 530, -440, 1230, -456, -133, -424, 35, + -357, 418, 1457, -687, 740, -242, 17855, -368, + -1057, -262, -646, 406, -712, -1058, -84, 454 +}, + +.cb0808l1 = { + 982, -26, -721, 359, 509, 13290, 2391, 727, + 325, 328, 269, -156, 346, -242, -31, -356, + 741, 396, -98, 108, 35, -237, -29684, 196, + -69, 462, -339, 24, -1221, 352, -658, 396, + 243, -1658, -458, -1153, 5, -662, -47, 18, + -572, -567, -2084, -980, -210, 150, -396, 14836, + -210, 0, -162, -539, 588, -868, 248, -8576, + 1020, 526, 1056, 262, -149, 818, -1353, -1120, + 767, -738, -634, -14742, -105, 811, 1718, -116, + -64, 307, 920, -1244, 2388, 10213, -4505, -250, + 617, -1725, -645, 1258, 1146, -590, 707, -12, + 372, 1794, 1012, -149, 404, -978, -306, 168, + -1536, 89, 142, 938, -19891, 973, -481, -419, + -904, -455, -1821, -1617, 654, -2022, 1906, -497, +-11346, -330, -11679, -14, 1, 535, -377, 1057, + -214, -213, 430, -13, -3379, -11250, 911, -716, + -240, -10, 260, 132, -611, -64, -594, -8540, + 837, -3717, -1154, 906, 10623, -502, -167, 67, + 119, 13501, -1469, 213, -1048, -1403, 432, -1079, + 45, -230, -730, -203, -595, -1150, -460, -97, + 395, -304, 27816, -300, -16, 153, -671, 551, + 436, -956, -182, 194, 113, -5504, 194, 263, + -332, -517, -244, -396, 540, 56, -371, 446, + 147, -66, 7, -306, 1440, -308, 327, 645, + 597, -6642, 72, 392, -138, -50, -144, -262, + 504, -230, 114, 2076, 8175, 1188, 290, -872, + 202, 69, 82, -281, -126, -291, -158, -152, + -45, 239, 153, -516, -422, -691, 801, 28, + 496, -298, -11118, 10430, -227, -851, 214, -801, + 538, 834, -137, 942, 573, 405, 1308, 2234, + 300, 1269, 12361, -752, 2177, -743, 60, 464, + 946, 302, -422, 116, -1200, -110, -843, 284, + -578, 732, -308, 153, -64, 156, 225, -29232, + -452, -466, -130, 888, 240, 305, -83, 236, + 208, 417, 1530, 294, 594, 351, 508, 137, + -7274, -184, 201, 44, -635, -891, -652, -596, + 380, -652, -8670, -76, -3746, -732, 262, -1860, + -1030, 1366, -279, 444, 911, 209, 330, 251, + -208, -747, 65, -10154, -204, 12960, -325, 347, + -465, -730, -727, 385, -89, -763, -427, 868, + -39, -859, 34, -29, -388, -1324, -218, 2051, + -1593, 5511, 10507, -8516, 2254, 5847, -1474, 1994, + 4704, -1876, 880, -3810, -489, -946, -1225, -1104, + 125, 139, -668, 2232, -537, 179, -215, 63, + 144, 72, 1198, 9750, 248, -709, 308, 10552, + -434, -462, 13569, 1096, -491, -262, 804, -1599, + 679, 569, 604, 1326, 213, -2026, 324, -2612, + -373, -12818, -20, 38, -171, 316, 15516, 306, + 763, 97, 91, -832, 23, -437, -390, 505, + -1226, 2518, 106, -2065, 315, 86, 523, 172, + -1012, -13851, 3358, 2610, -381, -194, 1200, -4106, + -1298, -3637, -1534, 780, 1367, -544, -770, 1690, + 1047, -54, 2136, 12502, 32, 6689, 706, -1172, + 846, -4853, 2146, 2548, -39, -465, -596, 177, + 213, 421, 28, -388, 11, 69, 31, -83, + -28, -166, -150, -19836, -323, 3, 659, 783, + 390, 139, -138, 31, -111, 453, -80, 432, + -519, -259, 686, 11431, 163, -13179, 554, 40, + -379, -120, -692, 340, 169, 120, -476, 643, + 778, 501, -128, 543, 1275, -134, 20568, 201, + 401, 512, -362, -210, -269, -812, 112, 75, + 149, -547, -494, -418, -100, -13621, -1002, 1176, + 1634, -395, -4289, -1531, -47, 850, -1102, 13558, + -403, 683, -164, -2215, -1180, -1750, 344, 630, + -968, 669, 540, 26, -594, 192, -17, -336, + 19645, 1133, 18, -56, 418, -426, -1535, 409, + 732, 186, 268, -20422, -22, 62, -621, 722, + 440, 96, -307, -128, 480, 5, 87, 668, + -361, -599, -22, 652, -176, -114, 214, -12233, + -698, 232, 608, -126, -714, -488, -228, 929, + -1582, -19845, 245, -460, 124, 57, 328, -436, + -158, 236, -196, -534, 209, 69, 229, 210, + -251, 1100, 583, 415, 210, 189, -219, 1242, + 19482, -105, 190, -374, -43, -232, 253, 561, + -297, -376, -1077, -308, 13486, -12462, 64, -190, + -298, -643, 460, 232, -987, -478, 1596, 168, + -722, 616, -873, -98, -948, 231, -1102, 11915, + 746, -495, 1248, 1203, 11067, -32, 160, -94, + -24, -153, -209, -1453, -1059, -313, -922, 1143, + -538, -1348, -323, 679, -54, -232, -470, 2075, +-19135, 628, -774, 35, 247, -86, 721, 512, + 1305, 850, 9760, 248, -2404, -220, 6, -73, + -1370, 567, 1432, -2529, -1508, 14358, -992, -1111, + -940, -111, 968, -530, 576, 102, -1045, 453, + 180, -94, -7936, -310, 512, 996, -32, -1062, + -150, -26, -6687, -181, -336, -1510, 616, 70, + -332, -175, 624, -546, 171, 364, 1011, 68, + -284, -368, 711, 46, 73, -34, -419, 404, + 28270, 283, -324, 335, -131, 316, 212, -27, + -342, -1062, 470, 1269, 454, 286, -1928, -1674, + -739, -389, 1073, -6172, -317, -586, -194, -182, +-13034, -848, 4596, -659, 709, -630, -310, 400, + 344, -276, 430, 876, -2047, -1012, -1672, -180, + 64, 22005, -736, 829, 266, 182, 436, -112, + -36, 131, 252, -63, 154, 368, 107, 93, + -42, -32768, 0, 200, -230, 271, -1776, 4329, + 986, -553, 481, 1888, -2770, 848, -6305, 264, + 12244, 1610, -640, 1348, -2742, -2078, 907, -1115, + 370, -16539, -1571, -176, 24, -515, 234, 954, + 605, 613, -154, 463, 535, -160, 684, 470, + 827, 10458, 150, -669, -6684, 339, -542, -730, + -351, 984, 212, 116, -7, 62, 926, 2175, + -185, -552, 489, -209, 5247, 38, 366, 53, + 16, 263, -142, -535, -224, 338, -174, -125, + 113, -12750, 400, -410, 281, -12, 744, -173, + 486, -12159, -107, -183, -484, 2, 150, 1, + -239, 7, -399, -608, -873, 698, -1623, 701, + -773, 272, -832, -94, -921, 885, 13588, 178, + 192, 148, 1346, 44, 59, -275, -14, -328, + 212, 133, -223, 300, -394, -275, -43, -76, + -47, 322, -208, 21713, 484, 329, 1860, 40, + -916, 502, 130, 477, 1754, 503, 7984, -338, + -323, -230, 354, 928, 430, -89, -94, 108, + -543, 365, -130, 70, 902, -131, 58, 469, + 580, -30949, 36, 232, -410, -451, 104, -8698, + 113, -1682, -42, -279, -92, -280, -477, -386, + -531, 832, 80, -15002, -56, 93, 164, -721, + 8388, -412, -2396, 584, 1004, -310, -2229, -304, + -383, 275, 1062, 1266, 297, -70, -909, 891, + 131, -1046, 539, 32502, 1000, -21, -229, 138, + 1528, -175, 546, 326, 168, -320, 716, -291, + -298, -227, 1094, -59, -12561, 12943, 786, 600, + -206, 889, -761, 54, 332, -1253, -597, 357, + -1124, -50, -168, 1172, 2266, 75, -174, 583, + 408, -157, 14666, 378, 302, -5, 48, 109, + 28, -21, 1044, 529, -859, -1182, -202, 1984, + 308, 402, 66, -1139, 2595, -380, 1119, 309, + 482, -10705, 100, -4591, 11646, -1364, -365, 9521, + -318, -23, 1076, -135, -2742, -833, 78, 910, + 96, -20, -599, 46, 855, -1265, 4748, 2394, + -250, -9096, -962, 191, -346, 348, 342, 1909, + 15330, 266, 540, 271, 2986, 1356, 1542, -1019, + -895, 737, 281, 684, -538, 10414, -922, 287, + 679, 204, -11142, -2321, -346, -1572, -250, -315, + -604, 1336, 311, 1317, -1111, 409, -104, -221, +-14125, -1511, -990, 705, -808, 587, 676, 348 +}, + +.cb0808s0 = { + -7488, -1327, -5244, -2049, -3736, -45, 446, 1558, + -755, -6052, 6034, -4326, 740, -348, 12369, 2115, + -662, -685, -6592, 10176, 8575, -1035, -2752, -4453, + -283, 1547, 4776, -2932, 700, 3425, -3905, 1073, + 2356, -7094, -1705, -435, 4840, -1944, 1188, 780, + -3963, -6170, -1726, 4759, -4356, -2124, -1686, 321, + -901, 1414, -923, -2678, -1198, -14777, -2038, -3528, + 123, 11216, 1904, -1914, 7588, 2744, -4265, -4886, + -3530, -1495, -1709, -5857, 3829, 2196, -4842, -817, + -874, -5649, -2181, -3871, 3774, -1368, 322, -1126, + -996, -3873, 13698, -9369, -848, 3797, -667, -1083, + 2429, -3351, -1672, -3562, -1590, -3507, 552, 6610, + -4137, -10061, -5452, -6142, -1454, 1726, -1298, -4479, + 6126, 1626, -2791, 1584, 1300, 5726, 2584, 11109, + 696, -3344, -2418, 9029, 4346, -3554, 1393, 144, + 2051, 8916, 6174, 5170, 376, 9778, -2298, -4119, + 3733, -35, -2673, 2222, 1383, 2046, 2859, -16131, + 1637, -1195, -662, 2800, -2241, 3801, -5062, -978, + 5670, -5449, -79, 3479, 606, 3766, -1325, -265, + 907, -745, 1005, -14528, -4227, -3955, -7194, 3690, + 2166, -2520, 11555, -511, 5900, -388, -3854, -3440, + 2136, -868, -2986, 722, 1286, -4027, 10382, -1646, + 5193, 2539, 1239, 7819, -67, 3382, -3297, -46, + -3808, 830, 1313, -2188, -4346, 5922, -1057, -6294, + 14317, 2001, 968, 4150, -4121, 1412, -302, -8401, + -1388, 10649, -9513, 1042, 840, -4606, 2098, 1166, + 1472, -802, -2810, 420, -561, -325, 2652, -2866, + 1334, 4878, 958, 83, 456, 1203, -7594, 14590, + -1210, 2202, -1954, -1938, -3413, -1096, 6036, -1675, + -1320, -4485, -10665, 10026, -2484, -3273, 4753, -275, + -3542, 924, 1262, 7348, -2959, -749, -408, 4594, + 4876, -491, 3409, 4616, 110, 557, -1378, -1616, + -4532, 1699, 1412, 579, -494, 716, 197, -23346, + -2284, 156, 1096, -151, -1827, 688, -322, 2371, + -7909, -1324, -1683, 7861, 7074, -451, 258, 9088, + 1900, 8660, 840, 3491, -3275, 3029, -475, -2122, + -5725, -8668, -6069, -3458, 4240, -3007, -5463, 9395, + -2686, 4718, -717, 42, -1802, 3122, -3197, -5212, + -1572, -243, -451, 8213, -2199, -3372, 4110, -8176, +-10525, -5551, 4312, 682, 2069, 1985, -3713, -6780, + 1193, 2831, -2228, 486, -3667, -789, -1691, 4567, + 464, -2114, -2340, -1881, 1921, 1602, 18418, 1535, + -567, 228, -9359, -6027, -267, 3628, 32767, 1423, + -74, -2817, 2112, -128, -1516, -2446, 1673, 2812, + -1582, 2125, 618, 2569, 2714, -1710, 340, 3255, + 848, 3379, -2317, -2361, -1823, 412, -2496, -18164, + -1224, 2552, -3040, 144, -597, 7716, 4916, -2867, + -2172, 2120, -2776, 675, -11985, 1692, -1384, -3588, + 4310, 1020, -4215, -251, -7090, -1916, 1914, -2804, + 6189, -6732, -1370, -3704, 450, -2652, 6553, -38, + 10348, 1244, -2246, -3729, -2158, -1340, 2357, 3118, + 9378, -1727, 3150, -3867, 1277, -15, 769, -2352, + -411, 1428, -14032, -1029, 2828, -1894, 6084, -36, + 518, 13159, 1095, -1185, -3207, -555, -3256, -76, + 3884, 3394, 1010, 1946, 160, -4863, 4714, -7087, + -3985, 5602, 3350, 7822, -5729, -7701, 9296, 3067, + 3582, 5256, 13629, -4012, -2206, -3867, -664, -104, + 4397, -7862, 36, 955, -38, -973, 3458, 5004, + 364, -9116, -2764, -2168, -1892, -7632, -4834, -5788, + -3565, -1245, -4544, 6552, 4601, 2342, 6625, 1040, + 2154, -6985, 5838, -1912, -3439, 1189, -2422, -555, + 3286, -14872, -776, 1228, 2434, 120, 13673, 904, + -1354, 645, -1550, -1377, -1888, 1416, -679, -1685, + 1731, 2404, -5786, 3285, -193, -123, 1973, 3663, + -1388, -14961, -3597, 5555, -1420, 284, 1527, -2575, + 1941, 871, 3900, -2168, -12763, 2970, -408, -3131, + -6426, 1892, 782, 6768, -284, 1034, 9785, 6029, + -3873, -4102, -4349, 2548, -3686, -5622, 4769, -351, + 8178, -7253, 3687, 624, -4386, 4028, -2780, -1938, + -4061, -1872, -1264, 7300, 760, 8530, -821, -874, +-14225, -1143, -5400, -850, -2537, 478, 1668, -1244, + -362, 877, 3481, -1338, -5218, 2091, 3996, -577, + 390, 8626, 820, 181, -988, 5604, 9694, 1112, + -3064, -266, 1234, -486, 1264, -2173, -13671, 3729, + -3212, 2548, 1745, -9363, 8065, 3713, -3343, -4847, + 2808, -4716, -2175, 25, -5718, 4056, 1855, 4663, + 2324, -1166, 543, 2, 3931, -3196, 2771, -920, + -2907, -746, -1241, -306, 2793, -22, -2642, 3048, + 3256, 1804, -1310, 17876, -1816, 56, -1694, -465, + -534, -2274, 6139, -2247, -2515, -1077, 3305, 1519, + 273, 1128, -1637, 2561, -1534, 874, -22808, -1119, + -2551, -10344, -2229, -3510, 194, 2594, 1737, 4713, + 13767, 3532, -311, 8097, -1012, -841, -4360, 793, + -267, -206, 12905, -2683, -6424, 196, 7098, -1690, + -690, 1236, -2882, -2668, -2020, 8291, -2714, -4607, + -923, -2077, -2878, 1687, -10457, -1575, 2172, -3974, + 5795, 1748, -1852, -5143, 4763, -5097, -2840, -1851, + 2634, 5970, 180, -3326, -1655, 1226, 375, 5137, + -2678, -5246, 4327, -3670, 9956, -1976, 2189, 2952, + -6785, -697, 1129, -5768, -5819, 6532, 3650, -1711, + 3857, 47, -9618, -1941, 2524, -1244, 7242, 11646, + -64, 2304, 201, -3707, -700, 149, 2692, -805, + 3978, 2738, -977, -1004, -5776, 12779, 7454, -353, + -4731, -3866, 7076, 146, -3302, 3065, 1955, -343, + -1459, -426, -5906, -1318, 500, -1014, -1002, -2090, + -2924, -20521, 2610, 1581, 397, -3380, -2885, 510, + -1147, 3398, 1914, 99, -119, 144, -3128, 2445, + 1791, 397, 3734, -80, -3410, -3798, -1142, -1515, + -2615, -1540, 5193, 2187, 940, 4969, -2334, -16589, + 325, -2186, -4567, 5121, -894, -6848, -6002, 1832, + -568, 8259, 833, 3420, -4459, -748, 3442, 4358, + -3041, -10203, 9303, -1511, -4821, 1950, -966, 3573, + 453, 705, 16238, -901, -163, -2866, -104, -1767, + -1779, -1249, 3251, 1975, 1254, -838, -390, -3150, + 1020, 2526, -2025, 662, -2817, -1338, -855, -3442, +-21123, 241, -134, -952, -588, 2572, 2080, 8153, + 114, 9732, -6774, -5266, -2462, 2286, -599, -426, + 1396, -7051, -1228, 312, -4495, -2525, 4649, -1305, + -1106, -2366, 2232, 4065, -18674, -1295, -3259, -1004, + -5136, 206, 1177, -5130, 2394, 2518, -1381, 2564, + -138, 4341, 16988, 2546, 6782, -3433, 850, -970, + -255, 1308, 2228, 1704, -1283, 1452, -2608, 1487, + 3106, -2267, -2998, -6814, 1654, 21195, 1555, 968, + 154, 124, -1258, 714, -407, 44, 247, 992, + 2228, 2824, 1435, -341, 1212, -1612, 6126, 1636, + -8368, 578, -5418, 217, -191, 204, -7147, 5110, + 3766, 5055, -5979, 6683, 368, -3597, -4595, 7630, + -3611, -2384, 1369, 6995, -3299, -53, 2036, -4654, + 4259, 9618, -1012, -2964, 4397, -2112, 11885, -1648, + -942, -3474, -544, -1410, -1958, -1535, 2981, -1591, +-16787, 335, 4609, -1990, 3821, -645, 1842, -64, + -3485, 3202, -374, -58, -1410, 7304, -1958, -2142, +-11412, -2533, 513, -6149, -6679, 2152, 3153, 5102, + 2216, -1361, 2260, 4863, -7031, 1538, -5250, -2511, + 96, 3339, -3447, -3708, 7168, -4168, 838, -3134, + 3228, -1531, -5598, 14125, 208, -2150, 819, -1085, + 12282, 6714, -2778, -9252, -5117, -6623, -1711, -4253, + -6306, -1292, -1370, -1027, -908, -2863, -1832, 4645, + -722, -284, -161, -5106, 7110, -12494, -1514, -5453, + -3308, 3520, 1101, -1096, -2325, -746, -33, 2645, + -4458, -797, -684, 1514, 1716, -6204, 6580, -3427, + -650, -10493, 4868, 5833, -2385, -274, 1530, 3892, + -1940, -1415, -2389, -11499, -2064, 937, -333, 1361, + -1583, 5458, -2296, -3263, -8344, -4236, -6357, -2372, + -3115, 1336, -2184, 194, -4262, -7838, 6946, 4535, + 749, 7332, 67, -327, 273, 3211, -1825, -357, + 7039, 3346, 6282, 488, -3940, 10196, 6463, 327, + 4407, 909, 889, -4943, -622, -4049, 2532, 1870, + 652, 1778, 663, 3063, -1012, -1390, 4162, 20486, + -86, 3166, 325, -1912, 511, -634, 1262, -4719, + -1490, 6767, -3314, -125, 4490, -10334, 5386, 9932, + 781, 290, 2198, 1695, 3790, -1878, 7760, -300, + 2021, 5508, 2200, 232, 7138, 1370, -3268, 3496, + 13934, -1230, -2303, 958, 141, 3348, -2867, -987 +}, + +.cb0808s1 = { + 9313, 734, 6610, -3629, -12020, 5317, -244, -1858, + 2, -1812, -6486, 892, 926, -236, 1016, -1249, + -469, -238, -1908, -10594, -4704, -907, -7746, 3847, + 564, -5956, 3395, 371, -5136, 4001, 1180, 769, + -555, -1872, -2943, -1744, 8620, 1485, 9901, -1392, + 3425, -7940, 151, 376, 1984, 3031, 3815, -974, + 537, -7038, 1964, -5625, 4457, -10214, -1787, -2768, + -8514, 176, -3692, 6441, 3148, 602, -2000, 13769, + -2792, 1104, -2067, -6219, 1515, -288, 3240, -5490, + 11589, 3742, -2343, -1752, 3701, 7525, -1676, 845, + 6895, 2884, 3540, 2454, 1010, 2454, -5761, 2035, + 3369, -9628, -862, -7060, 1802, 5676, 2396, 2757, + 5891, -701, -11896, -4061, 7932, -272, 2562, 83, + 560, -5180, -2223, -356, -3343, 2874, -1370, -7612, + 1773, 2006, -4258, 5312, 342, 8196, 4939, 519, + 3568, 4420, 2768, -11872, -3021, 1893, 1690, -5483, + -8129, 7540, -116, -2064, -4473, 1141, 1930, 656, + -7728, -2742, -3276, 2782, 2860, -6082, 5198, -4751, + -486, -789, -16932, -566, 5116, 1196, 832, 4282, + 78, 3088, 2768, 2125, 1027, 1712, 310, 808, + -1595, -106, 3174, 4598, -2945, 1551, -7688, 620, + -1640, 339, 4538, 3339, 532, -351, 260, 249, + -2135, -543, -18362, -648, -3871, 5514, -1782, -11301, + -374, -2078, 1610, 50, -4439, -2546, -3058, 839, + -9221, 2618, 1790, 103, -1061, -363, 285, -3542, + 503, -437, 30, 1382, 75, -2852, -1028, 3095, + 4318, -2316, 739, 801, -22765, 2162, 913, 1698, + 149, 2049, -313, -803, 3393, -1476, 4396, -4003, + 854, -1344, 1062, 10009, 6332, -8522, -2616, -9904, + -390, -3146, -2951, 4222, 5538, 495, 3776, -13684, + 4687, -2187, -905, 4997, 6209, 4775, -1234, 1956, + -4607, 3006, -370, -670, -12448, -5802, 8151, 140, + 1485, -6340, 2139, 1231, 22, -212, 2090, -676, + 2366, -701, -4113, 365, 2970, -577, 918, 7324, + -709, 2035, 5162, 7232, -13287, -3259, -908, -1900, + -4255, -2590, 318, 4891, 696, -40, -1647, 1572, + -1221, 4896, 5241, 49, -2083, -5068, 7645, 8978, + 1628, 2895, -4930, -8068, 2266, 2025, -1868, 3250, + 2642, -785, -14571, 9979, 3481, -2246, 1154, 2646, + 2616, -2033, -2936, -1300, 2490, 879, -1237, -1228, + -724, -1780, 524, -6619, -3339, -2526, 3533, 844, + 2946, 2208, -3522, -12411, -3062, 2380, 448, 604, + -4708, 2403, 1914, -58, 149, -3704, -2019, 4246, + -7020, -3197, -712, -2219, 10036, -2776, -3166, 2648, + 2947, 3386, 6445, 1587, -268, -536, 1895, -9005, + 10791, -982, 8215, 6414, 5166, 4751, 160, 3050, + -865, 6216, -1187, -7077, 1640, 5078, 4354, 1762, + -3869, 1174, -149, 1078, 1884, 5149, 15091, -432, + -2441, -1102, -1194, 1078, -1535, 8289, -2702, 4007, + 694, 72, 685, 2816, 13244, -422, -7094, 432, + 2044, -12004, -276, 2174, -908, -4784, 5725, -250, + 22, 5116, -2, 2686, 955, -8509, -7697, -3735, + 672, -1202, 4299, 4284, 12352, -2362, 5757, 1317, + 4293, 508, 3050, -524, 1097, 3346, -537, -2440, + -1596, -5659, 4188, -625, 1659, 3061, 2791, 1712, + -2991, 966, -16903, 610, -3314, 4160, -3750, 580, + -3407, -340, -11829, -520, -1625, 2905, 674, -147, + -5284, -4278, -5021, 4635, 6299, 2207, 2595, -7811, + -68, 4107, 4314, -1540, -11044, -2214, -803, 232, + -7602, -95, 1130, 4991, -361, 1675, 4487, 3607, + -6192, -130, 137, -1440, 2826, 178, -13834, -984, + 1149, 1230, 1587, 1571, 3286, 5293, -2259, 2021, + -6211, -7608, -2710, 2502, 4315, -539, -8530, -746, + -654, -4003, -5917, -3728, 4522, -10350, -1266, 210, + 5078, -2988, -3866, 3919, 969, -1063, -6300, -4584, + -2420, -2094, -884, 2338, -3150, 5461, -1145, -734, + 1644, 2183, 19114, -1144, -2313, -404, 1236, 3583, + 134, 1802, -4088, -2795, 681, 3738, 1831, 16571, + 917, -2290, -3648, -1588, -158, -528, -792, 394, + -7432, 2446, 402, -391, -73, -1398, 1286, -6503, + 5216, 1094, -939, 1673, -2038, 15842, -1971, 4160, + -1664, 7231, 642, 5770, 4209, -1839, 220, -266, + 165, 2055, 5222, -3344, -6544, 5412, 1514, 586, + 1591, -15256, -2715, 941, 1308, -9170, -2863, 4935, + -2913, -1291, 2791, 7967, 14, -1101, 3774, 3580, + 848, 1337, 1138, -2839, -3564, -5300, 12429, 14, + 1466, -7114, 1198, -3474, -237, -2577, -1305, 445, + 1069, -174, 1684, 3902, 229, 5842, -690, 978, + -754, 1182, -859, 21078, -185, 710, 797, -2155, + 367, -2168, 1002, 3805, -924, 468, -2322, -3590, + 1608, 3387, 18, 1536, -858, 642, -7964, 17689, + 9843, -4878, -3003, 7373, 5934, 4286, 10484, -63, + -4629, 974, -2227, 2602, 3810, 1905, -1668, -2130, + 2020, -2360, 2853, 612, 5070, -1248, -868, -497, + 3478, -1937, -3006, -645, 3589, 3019, -3293, 16469, + -5243, -2918, 1788, -2569, 3717, -9630, -1352, -3870, + -416, -4190, -8863, -6888, -498, -814, -783, -4625, + 5841, 1562, -2173, 481, 280, 816, 4742, -9962, + 11799, -2029, -2460, 4972, -600, -1452, -1901, -2122, + 3130, 2686, -819, -2366, 866, -2093, 1052, -58, + 284, 3830, -4738, -4114, -1321, 1307, -2820, 4915, +-11701, 522, -1982, 7024, 8403, 1762, -46, 532, + 5097, 5013, -615, 3086, 2089, 6899, -1107, -4047, + -2903, 5356, -4802, -965, 6706, 3895, 9022, 1388, + 10971, 5927, -2954, -965, -3473, -5177, -2654, 3418, + -5315, -16695, -6587, -416, 404, 1230, -2586, -3292, + 1390, 14, -481, -4446, 1335, 109, 1060, 3958, + 1275, -5655, 1253, -2411, 207, -12550, 6208, -2447, + -3415, 2503, 848, 3094, 9336, 2647, 2455, 2238, + 2356, -2132, 5347, 915, 2227, -103, 5832, -2504, + 7562, 9568, -6100, 4091, 2668, -1722, 287, 6763, + 4058, -387, -2060, 5522, 3184, 4766, -158, 650, +-11284, 11841, 6230, -4232, 5308, 3174, 4926, -2970, + -4761, -980, 117, 1944, -1974, -5484, 6534, -266, + -7222, 924, -2654, -588, 9609, -2337, 1892, -2110, + 5088, 1856, 7964, -4029, -940, 1429, 805, -4705, + -1362, 892, -189, -8354, 3259, 194, 767, -2877, + -4165, -990, 12185, -160, -2002, -1384, -5388, -1604, + 226, -6353, -4157, 1773, 2360, -4356, -730, -5462, + -4054, -15669, -1528, -394, 4101, -203, 2792, -787, + 3391, -299, 6384, -1630, -7186, -12765, 4618, 934, + -401, 2790, 2284, -4932, -1260, -6009, -2590, -2285, + -1289, 3366, -4192, -4462, 32767, -3135, -1888, 67, + -2874, 150, 4760, -1571, 584, -2187, 358, -1733, + -1286, -4573, -2003, 1872, 940, -1942, -255, -8856, + -1320, -3348, 4854, -509, 2836, -14, 2490, -1537, + 882, 1188, -3132, -15209, -1633, -44, -2827, 368, + -1099, -1073, -467, 6318, 5863, 2840, -5200, 569, + -2984, 6587, 9596, -4924, 457, 4879, -4449, 3528, + 1868, -3894, -3905, 15420, -2590, -599, -4975, 3892, + -1454, -616, 1890, -2700, -3268, -1386, -1065, -3078, + -2454, -1902, 4726, -34, -4218, 1619, -3074, 5540, + -6392, -3570, 2687, -8742, 333, -106, 2326, -1737, + -3775, 397, -3553, -6632, -6066, 9567, 2904, -889, + 1136, 1295, 19390, -268, -3127, -180, 1696, -814, + -775, -4914, -456, -758, -866, 1102, -3740, -374, + 469, -6902, 1440, -10243, -6221, -4797, -3074, -1142, + 297, 5069, -1547, 5474, 716, -454, 3806, 4100, + 2901, -2169, -744, 5032, -5586, -2986, 2286, 2414, + 7860, -2672, -46, -10046, 5348, -1018, 1016, 9142, + 4543, 5587, 2228, -2684, -4594, -2457, -1850, -3651, + -1806, 4826, -11686, 1940, -3529, 1078, -5234, -2420, + -83, -2322, -5134, -775, 677, -9257, -864, -915, + 4494, 411, -4820, 5999, 4472, 5823, -4597, 3121, + -1868, -1539, 2338, -4249, 1154, -13422, 791, -1235, + -1240, 364, 177, -1508, -2527, -2949, -2062, 118, + -3115, 293, -1927, 18644, -1100, 152, -2528, 1914, + -1380, -1624, 302, -831, -920, 320, -879, -1252, + 813, -11, 6960, -522, 3092, -119, 1486, 3068, + 6690, -3079, 13305, 6342, 937, 1632, -1026, 1896, + -2335, -3961, 5510, 2782, 187, -2448, -1251, 756, +-15856, 3179, -1155, 808, -1748, -6593, 1494, -3122, + -98, -3808, 491, 1752, 3188, 2158, -1924, 763, + 1165, 148, -3161, -1284, 18082, -195, -1125, 845 +}, + +.cb0808m0 = { +-18656, -461, 236, -1122, -796, -101, 851, -3748, + 1374, -8549, -3366, -1482, 1026, 2046, 4394, -521, + 232, -486, -1656, 32767, 1954, -1183, -130, 392, + 194, -868, 2883, -168, -1674, -910, -34, 819, + -1105, 1628, -4871, -585, -1170, -572, 451, 3911, + 10770, -35, -4126, 7124, 7110, -860, -3914, -3294, + 272, -647, 220, 11965, -3378, 2726, 1990, 1624, + -3689, 9884, 2394, 3096, -518, 5169, -4018, 3108, + 168, 1256, -410, -3851, -11176, -10479, 2042, 1421, + 1488, -992, -1562, -653, -1191, 2246, 467, 4732, + 154, 729, 7244, -18, 1313, -51, -1824, 1218, + 1473, -6763, -11270, -4295, 4118, 1043, -5782, 1370, + 46, -11027, 4086, -1501, -11, -621, 464, 781, + 13680, 257, 554, 3119, 750, -1857, 1046, -1252, + -512, 739, 14811, 12642, 3841, 2824, 163, 1620, + 39, 4766, 1411, -2197, 525, 658, 419, 5, + 92, 1544, 290, -2038, 10603, -5764, -3335, -6629, + -2579, 4020, -3107, 2779, 849, 5678, 260, 2804, + 99, 1339, 544, 1438, -450, -598, 764, 1568, + -1034, -4560, 2604, -18205, 1644, 1003, -675, 3217, + -334, -832, -1452, 322, 608, 300, -4776, -812, + -36, 627, 1654, -248, -838, 21571, -89, -1626, + 530, -1151, 9440, 522, -6138, 2213, -10095, -562, + 1000, 5037, -122, -3, 7064, 397, -2118, 362, + 15791, -1047, -15010, -1527, -1356, -2805, -560, -3148, + 266, -45, 1324, -3312, -1772, 2382, 189, 6537, + 124, -1272, 156, 588, -2678, -3106, 2828, -3684, + 689, 3884, 4650, 192, -323, -5426, -722, 11486, + -607, 3591, 4299, 2117, 362, -9114, 11700, -3391, + 2357, 7639, 2197, 4350, 2970, -2525, 169, -6112, + 91, 1520, -19, 1558, -4588, -837, -8163, 897, + -7992, 2080, -3102, 774, -10592, -314, -137, -524, + 87, -799, -111, 74, 1312, 862, 266, 243, + 199, -288, 1205, -829, 1650, 2880, -24776, 3867, +-13101, 597, -9778, -2084, -3089, -1112, 548, -638, + 3727, -446, 4877, 2099, 68, -2736, -4914, -7103, + 263, -9228, -782, -2109, 1088, -1881, -1424, -30, + -1353, 586, 4085, -3573, -11921, 2366, 516, -1028, + 834, -234, 2150, -15893, 2305, -3619, -2567, -8366, + 610, 2946, -2383, 2293, 946, -3550, -6770, -1481, + -758, -864, -232, 2855, 40, -2330, 2069, -345, + 1801, -589, -1241, 647, 6988, -2625, 14308, 2801, + 759, -2740, -680, 964, 365, -506, 22268, 1766, + -202, -2751, -293, 3754, 1280, -521, -3355, 4615, + 594, -1783, -39, -46, 48, -2638, -551, 2548, + -1880, 3730, -1726, 939, -345, -7, -1630, -23405, + -1002, 5655, 2100, 440, 1682, 1020, -594, 344, + 1511, -1286, 5518, 473, -11398, -4552, 720, 4701, + 7726, 126, -1953, -484, -1648, -1766, 1589, 996, + -688, -381, 1678, 1498, -528, -860, -667, -823, + 32767, -463, -243, -1242, 1074, 2460, -1411, -459, + -1533, 1462, -2603, -784, -391, 338, 3444, 2170, + -924, 949, 1972, 1520, -3062, -671, 12908, 2636, + 2805, 722, -12016, -26, 616, 1192, 1193, -1028, + -128, -22850, 191, 408, -3105, -592, -440, 1264, + -2580, 847, 850, 2300, -278, 126, 2214, -2693, + -21, -194, -594, -533, 45, 570, 38, 636, + 1276, 171, 29846, 648, 911, -358, 300, 602, + 413, -10167, -54, -1353, 42, -1770, 491, -12154, + -1808, 26, 425, 2009, 910, -8134, 362, 2001, + -114, -2586, -1049, -249, -312, 160, 1677, 27043, + -44, 160, 834, 243, -606, -272, -979, -1605, + 105, -491, 754, -230, 2442, 24, -5139, -395, + -3562, 14436, -1208, -3232, 2555, -12980, -906, 429, + 217, -432, -1263, -244, -225, 912, -64, 780, + 1101, 854, -240, 308, -28630, 518, 32, 976, + -8642, -3041, 1801, -742, -1513, 128, -3189, 857, +-14277, -1802, 1229, -68, -565, 65, 4094, 1614, + -8254, -1153, -640, 16225, 3508, -1383, -3882, -347, + 1346, 3845, 2665, 2340, -1862, -5318, 1402, -1352, +-21682, -694, -1182, 286, -806, 2133, 1848, -532, + -3750, 7564, 1054, 284, -3742, 2559, 2748, 3408, + -1544, -342, -22578, 1225, 958, 2559, 267, 378, + -3608, -1404, -1669, -13, 1135, 153, -625, 1436, + 211, 556, 739, 1094, 10452, 850, 5128, 11469, + 121, 4937, -3643, 1371, -373, -6686, 229, -3256, + -75, 1304, -1023, -452, 288, 12709, 13572, -501, + 1840, -1044, -2014, -4077, -2726, -1010, -3826, -629, + -466, -923, -847, 5784, 898, -12036, 1253, -1741, + 1546, -3710, 2782, -3430, -1810, 263, -8254, 3126, + 55, -376, 202, 968, -1686, 944, -15300, -2664, + 1393, 783, -11080, 1714, -1666, -1064, -4859, -2344, + 334, 1313, -1209, 877, -1828, -2130, -3057, 340, + 8030, -3222, 11622, -5620, 1469, 3340, 2862, -3945, + -868, 351, -1314, 2277, -2346, 12384, 996, -2460, + 1810, 703, -2158, 3168, -9887, 8754, 3503, -1414, + 445, 850, -30, 2389, -617, 3271, -1606, -5633, + 2993, 10009, 5704, -11589, 4278, 1304, -2418, 479, +-16596, -12349, 2915, 327, 895, 1278, 1412, -310, + -653, -1287, 880, -4294, 38, 2179, -2074, -1810, + 198, -1544, -8008, 2456, -2821, -3223, -3713, 11763, + -2081, -141, 4833, 1652, 3598, 551, -1655, -1154, + -60, -302, 739, -1494, 2595, -1006, 2665, 10834, +-11270, -2996, -636, -446, 1816, -1539, 4149, -184, + -100, -55, 265, 2207, 639, -162, -2210, -626, + 605, -21149, 2163, -970, -330, -4655, 3396, -3092, + -544, -650, -304, 93, -1484, -888, -8982, 1871, + 1701, -1423, 1671, -11, -1287, -14292, 592, 1040, + -622, 13202, -660, -12745, -2836, -1832, 3481, 1546, + 235, -646, 2132, -602, 2391, 1534, 3599, -4932, + -296, -1855, -2075, -2646, -219, -10248, 1161, 5955, + 6954, 9109, 3498, -5932, -1787, 373, 1234, 1244, + -813, -76, 9083, -5120, -499, -1774, -2150, 10601, + -170, 1160, 982, -597, 95, 151, -534, 6554, + 840, -958, -720, 2066, -50, -2877, -74, -2068, +-24760, -725, -357, 1273, 1941, 2525, 46, -819, + -230, 1030, 2291, -287, 1092, -2315, 427, -19, + 448, 1698, 9797, 10962, 3034, 2622, -2652, -1128, + -194, -180, -1176, -1794, -22248, 244, -3, -1856, + -1054, -2751, -459, -62, -433, -2274, -1790, -192, + -720, -421, 55, -721, 1960, 1094, 2500, -2353, + -480, -784, -1221, -505, 1738, -9960, -10772, -13657, + 122, 387, -667, -454, 988, 30780, -757, -2319, + 878, 962, 753, 1306, 716, -771, 539, -705, + 508, 1915, 2114, 937, 447, 935, -1432, -1143, + 4435, 11759, -2442, -53, -10601, 1979, 5419, -2296, + -172, -5987, -1168, -2012, 2257, -1451, 97, -1253, + 5548, 884, -14448, 3134, 2549, 172, 5404, 869, + -83, 597, -12416, 762, -1035, -805, -1369, -804, + 664, 9644, -4329, 1130, -1526, -2900, 628, 620, + -6436, -2370, 2107, -11836, 37, 864, 2105, 314, + 216, -529, 810, 3141, 3716, 7019, -2653, 1466, +-14940, 13128, 1218, 2287, -145, -443, -923, 476, + 2411, 5428, -611, 2212, 1450, -3042, -4750, 3562, + 587, -15378, -15151, 600, 1029, -2353, -934, 1986, + 1444, -2171, 1020, -700, -1508, 195, -2466, -798, + 16460, -2164, 520, 2711, -13832, -2024, -871, -5268, + 3556, 117, -416, -8, 2128, -1570, 2052, -3169 +}, + +.cb0808m1 = { + 16492, -295, 2556, 1303, -440, 7584, 3305, -3422, + -1196, -1809, 2142, -1292, 1048, 314, 1945, 578, + 1080, -255, 1109, 617, 1597, 198, -29081, -243, + 54, -33, 76, -418, 1332, 475, 1495, 1554, + -782, 308, -1286, 1044, 300, 1544, 646, 9441, + 2577, -11140, 1421, 1107, -483, -590, 625, 8544, + 446, -1814, 1714, 685, 9620, -4981, -3100, -724, + 8439, -2333, 506, 3557, -1160, -2199, -659, 4107, + 8620, -1406, -3745, 1729, 10756, 868, -82, 2584, + -3140, 3632, 2617, 3880, -1175, -163, 1864, -980, + 551, 201, -433, -1464, 708, 1926, -8471, 3870, + -2376, 15567, 2112, 753, -2450, 72, 1131, 2932, + -139, 6392, 1547, 3, 625, -823, -1750, 811, + -977, -1389, 1300, 1184, 399, 4684, 196, 3679, + -1672, -218, -11023, 98, 492, 4072, 1213, -2004, + 3602, -1787, 1288, -9442, 4157, -4267, 3509, 5317, + -574, -11094, 1078, 6240, 1593, -12773, 408, 3960, + 1116, 1517, -816, -577, -696, 554, 1645, -936, + 83, -20255, -754, 1460, 1110, 1412, -757, 377, + 2373, -1608, -1414, -1028, -3152, 1534, -4145, 2274, + -286, -7058, 2286, 4013, 2515, 2681, -5602, 0, + -1740, 257, 756, 11496, 954, 4513, 3968, 4851, + 278, -511, 829, 2853, -9743, -3723, -1550, -444, + 4256, -679, -11411, -4290, -1470, -4191, -952, -239, + -198, 1361, 9527, 1481, -981, 1403, 991, -255, + 9326, 1832, -1936, -135, 1123, 2756, 1932, 2543, + 795, 12612, 2429, -498, -13185, 3812, -1628, 196, + 1822, 4333, 2760, -676, -2902, 1244, -1974, -7046, +-12216, 1503, -2176, 1916, 365, 636, -11348, -5030, + -3319, -3794, -1016, 1157, -4158, 3424, 344, 4494, + 812, -3074, 4356, 293, -3463, 1232, 1746, 2696, + -8269, -961, -4316, 130, -4278, -14007, 3025, -2703, + 179, -10176, 1511, -1460, -1100, -1171, -1575, -2596, + -2026, -11400, 2689, 1480, 743, -1669, 2728, 742, + -60, 11452, 84, -662, 1424, -15103, -410, 2141, + -1664, -1378, -122, 97, -358, -820, 382, -3865, + 374, 1698, -21, -752, 595, -8771, -731, 9368, + 1698, -2586, -6790, -2507, -1776, 4993, -3867, -2807, + -190, 14465, -13938, 3095, -1198, 374, 1682, 1888, + 286, -576, -2094, 454, -690, 1396, -1139, -422, + 405, 238, 1718, 2048, 13448, -151, -247, 202, + -900, -5630, 3121, -10988, -1615, 1955, -3901, 3360, + 1429, 3928, 1951, -1099, -435, 1572, 1500, 19176, + 731, -439, 3686, -3039, 244, -4270, -34, 1289, + 296, -406, 2216, -1400, -1946, 264, 1536, 2992, + 54, 892, -181, -1545, 278, 24923, 989, 1301, + -1279, -188, -198, -661, 612, -1520, 2355, -12972, + -694, -560, 1364, -2988, -6236, 2555, -6630, 1423, + 440, -598, -1092, 304, -2529, -1698, -909, 2560, + 844, 768, -2988, -661, 18432, 1158, -639, 5070, + 11015, -14, 2313, 756, -1941, -10986, -490, -5235, + 2646, 2406, 170, -546, 337, 6499, -4450, 5598, + 299, -504, 14322, -972, 9356, -2056, 8812, -1599, + -1931, 2084, 119, -983, -305, 1437, 403, 2651, + -159, 229, 209, 1438, -1789, -1159, 1017, 416, + 408, 454, 858, -652, -1554, 1198, 18278, 122, + 433, -165, 162, -10532, 11563, 4754, -2022, 4246, + -1396, -2417, -1796, -1496, -1279, 3877, -1217, -770, + 983, -609, 1766, -184, -5664, 546, 7948, 1978, + -250, 4350, 3498, 2797, 802, 846, -12628, -1092, + -240, 781, -11252, -955, 9944, -222, 1177, 1262, + -534, 1790, -7396, 1452, 4251, 303, -3714, -2295, + -290, -227, 672, 22690, -622, -466, 1599, -496, + 326, 871, -1948, 148, 449, 214, -2175, 713, + 394, 1921, -28716, -786, 1083, -641, 1232, -246, + 1572, 1575, -879, -2962, -57, 369, 1633, -1457, + 1194, -1222, 304, -955, 104, -1249, -935, 135, + -758, 3483, -1190, 1457, 1130, -1284, -3709, 18042, + 6, 25, 1233, -328, 347, -512, 2071, 328, +-18037, 4582, 3841, -434, -745, 332, -576, 3006, + 336, -11505, -646, 3509, -996, 1270, 2041, 1353, + 1193, 2976, 11569, -3165, 1450, 4351, 2522, -10022, + -6, 12602, 874, 518, 475, 1251, -3290, -2674, + 4802, -11794, -946, -426, -2846, 1619, 1105, -1022, + -1, 1759, 646, 10347, -2937, 13505, 1104, 614, + 1149, -800, 2377, -115, 792, -948, -2431, -1779, + -1142, 809, -3130, 447, -15516, 313, 11235, -1346, + -2426, -2737, -1738, 2236, 1094, 802, 1323, 3612, + -213, 1383, 2800, 10394, 1210, -2360, -10203, -1991, + -102, -2669, 2303, -2184, 1830, -1158, -5633, -4083, + -252, 311, 612, -331, -2786, -12421, 9994, -6006, + -4996, -954, 1014, -1147, 860, 1252, 1114, -2069, + 266, -230, -591, -4442, 230, 20603, 1386, 1130, + -1468, -3600, 2168, 836, -1754, -511, -542, 216, + 26, 3476, 1165, -4293, 3098, -245, -579, 1830, + 2248, 5326, -18357, 397, 5466, 734, 3920, -3678, + 319, -1062, -610, -7509, -1064, 1456, -5729, 1088, + 9099, 2266, 241, 201, -10017, -1545, -2799, 1491, + 27098, -60, -1736, 1387, 859, -1474, -79, -1122, + -971, -1302, 906, -1133, -2659, -296, 1344, -2698, + -448, -1476, -212, -1585, 1310, 14353, -2165, -2229, + -656, 5219, -3266, -1850, 7942, 4997, -2295, 519, + 608, -9498, -1700, 1770, -15308, 1286, -2914, 2252, + -717, 2136, 2478, -3747, 2362, -5, -237, 2334, + 701, -774, -672, -20, -599, 623, -700, -713, + -979, -29926, -1090, 848, -141, 1273, -711, 1782, + -221, -103, 170, -185, -1059, 3066, 1321, 1182, + 3641, -217, 1959, 11806, 2390, -10312, -2575, 1612, + 596, -352, 2197, -2041, 2385, -898, -9363, -1144, +-10896, 20, -7842, -1047, 3687, 2147, 2584, -249, + -72, 32767, 1936, 446, -889, -845, -896, 1269, + 448, 327, -3411, 4, 702, -1900, -646, 799, + -770, 662, -911, -856, 287, 1667, -108, -64, + 16, 1578, -2059, -27327, 112, -188, 2504, -692, + 250, 360, 564, 868, 4147, 1340, 18080, -3584, + 445, 364, -2623, -412, -2918, -116, 2611, -2396, + -44, 10934, -1512, -1166, 239, 913, 190, -14681, + -767, 2610, 2931, -2389, 3590, -1680, 6287, -531, + -616, 1317, -1034, -900, 871, -329, 467, 1200, + -1914, 1108, 3150, -6878, 544, -14411, 2807, 5427, + 13361, 1448, -1753, 524, -5851, 1467, -1866, 6888, + -8742, 1372, -1515, 4883, -2248, -1042, 4628, 10768, + 149, -358, -1287, -1289, 32767, -1137, 941, -2112, + 451, -1436, 174, 294, 475, -3667, 1610, 1641, + -599, 626, 2058, 671, 1626, -985, -123, 2040, + 421, 1797, 18448, 2538, -359, -5042, 3096, -1136, + -320, 1823, 30, -12002, -1297, -850, -418, -1497, + -1761, 5073, 10944, 212, -4713, -1614, -1752, -2135, + 483, 1043, -1989, -293, 39, -1049, 67, -7482, + 712, -5358, 896, 12460, -1744, -1793, 1538, 3577, + -6, 418, -72, 1072, 1367, 1080, 3564, 1468, + 482, -1298, -6442, -299, -12934, -757, -4199, 3842, +-11331, -1216, -206, 1598, -1135, -3240, 3294, -286, + -540, 777, 1188, -1189, 4516, 2638, 2071, 9702, + -900, 1002, 18707, -705, -1856, 1185, -4832, -1694, + -3502, -2324, -2826, -4600, 1996, -3110, 110, 117, + 405, -16854, -510, -14725, 1699, 1922, -2117, -2718, + 45, 1064, 507, -1781, 2106, -2310, 1239, 5860 +}, + +.cb1108l0 = { + 2354, 8016, 12528, -947, -348, 1760, 2054, -3960, + -2125, -3578, 3932, 1647, -3316, 6053, 392, -3128, + 3209, -2445, 463, -2835, -1555, 1259, 296, -1465, + 1839, -4811, 420, -215, 469, -1013, -272, 185, +-27061, -1154, 8, 298, 259, -953, -555, 472, + 617, -1127, -673, 982, -398, -1681, 328, 882, + 614, 800, 431, 84, 880, -240, 15758, -14324, + 1301, 1578, 932, -694, -1456, 2435, -1651, 1464, + 227, 1527, 527, -128, 698, 2405, -726, 1489, + 1016, 1938, -1897, -1478, -238, 932, 2507, -519, + -1147, 557, 2334, 700, -12914, 14861, 158, 255, + 1195, -883, 3359, -1045, 2095, 520, 249, 926, + 789, 1392, -185, -1654, 902, 9, -2166, -1916, + 543, -2126, 2842, -332, 1356, -344, 436, -404, + -174, -489, 858, 258, 229, -45, 327, -316, + -1176, -454, 115, -220, -458, -194, 271, -530, + 1572, -574, -25068, 167, 601, -1027, -1705, -3144, + -4231, -1636, -1012, -1002, -519, -825, -458, 945, + 546, 193, -17909, -156, -1067, 826, 338, 1152, + 562, -506, 848, 239, 188, 656, 97, -174, + -59, 242, 1946, -67, 745, 2043, 424, -192, + 574, -524, 1553, 566, 1480, -747, 487, -20623, + 872, -1089, 1034, 1357, 919, 153, 154, 498, + 54, 555, -989, 707, -85, -21, 700, -1424, + 90, 655, -399, 123, -709, 117, 438, 330, + -720, 190, 812, -138, 460, -32768, -162, -410, + -327, -122, -1208, -554, -502, -178, -309, 373, + 4295, -945, -5502, -2752, -6615, -1241, 1278, -1315, + -7683, -986, -419, -50, 2384, -4640, -6246, -11804, + -308, -446, 3486, -4824, 1736, -590, 960, 195, + 593, 164, 3355, 1655, 1233, 66, -787, -347, +-13751, 74, -1209, -812, -4098, -102, 910, -1659, + -2036, -3147, -2075, -2605, -1240, 4499, 1727, -9484, + 549, 728, 3411, 1958, -4439, -1064, 5690, -1600, + -1984, 1695, -588, 4815, -138, -3380, -512, 1553, + 1978, 4310, -730, -402, 828, 2124, 14216, -222, + 2757, -8686, 523, 2516, 1017, 790, -136, -470, + -252, -717, 808, -1113, 13766, -114, -1182, 3053, + -5238, -2231, 1720, -511, -987, 1592, -1257, -2578, + 1777, 1075, 2367, -227, 2330, -672, -2620, -1449, + 2122, 362, 1249, 1338, -327, -21631, -1540, 24, + -2356, -656, 1981, -92, -207, -2188, 34, -457, + -1291, 1231, -460, -128, -396, 593, -671, -1513, + 136, -335, 560, -1121, 490, 1008, 948, 8629, + -3344, 467, 881, -5731, 1120, -300, -1432, 1227, + 1558, 990, -1078, 214, -922, -81, 1120, -15586, + -1176, 1203, -1911, 151, 1484, 1555, -421, -420, + -428, -762, 292, -59, 1075, -649, -841, 494, + 194, 27, -768, -356, 54, 163, -73, 293, + -1717, -392, 750, 234, 751, -111, 26858, 911, + -389, 451, 442, 260, -117, 270, 19, -2429, + 618, -962, 378, 10, -1954, -1336, 525, -258, + -693, -4155, 10265, 2924, -1361, 3197, 10199, 6870, + -2608, -5792, 619, -1994, -2035, -701, 2598, 465, + -575, 311, 175, 162, -1191, 162, -157, -147, + 325, 551, 536, -188, -290, -165, 343, 14, + -268, -27113, 278, 127, -233, -68, 606, 125, + 665, 438, -442, 2510, 800, -1991, -641, -386, + -1574, 78, 946, 189, 106, -2249, -268, -1708, + -1192, 986, 3076, 1807, 21, -5884, -964, 256, +-15916, -1320, -2867, -3562, 491, 3502, -337, -1542, + 496, -3182, 1676, -2371, -4264, -2053, 14342, -5674, + 1744, 1813, -3731, -3761, 1350, 1783, -438, -920, + 2366, 1438, -687, 512, -1934, 323, -3158, 1775, + 1964, -6742, 10162, 7763, 1469, 1967, 851, 2742, + 7413, -3338, 742, 1854, 310, -192, -936, -1770, + -775, -976, -1532, -1436, -670, -4032, 1194, -1336, + -4369, 332, 604, 962, -27563, -972, 842, -743, + 275, 713, -251, -799, -1190, 372, -213, -423, + 202, 1189, -31, 1084, -974, 756, -148, -1669, + 640, -549, -339, -1506, -112, -598, -870, 410, +-13307, 13141, -1911, 2308, -92, -776, 221, 1503, + 1578, 803, -308, -1672, -404, -83, -3517, -1327, + -606, -2426, -61, -513, 318, -1805, 2049, 1887, + -777, 1268, -542, -116, 3550, -18840, -2986, -979, + 2653, -2875, -922, -10520, 804, 107, 3234, -1270, + -608, 1042, 3599, 965, -342, -2096, -267, 1704, + -3939, 791, 2180, -985, 816, -716, -2661, 99, + 1523, 11902, -1782, 775, -12517, 3244, -3762, 2046, + -278, 1539, 2895, -2425, -10, 990, 1484, -1377, + -3399, -984, 3171, 1513, 696, -785, 155, -1072, + 414, 2016, -1932, -3124, -1126, 68, 3855, 1360, + 4074, 17596, 1714, -596, 4000, 1656, 230, -258, + 2266, 843, -1720, 4624, -714, 854, 696, 636, + -1357, 350, -1256, -523, 168, -9933, -766, 198, + 2680, 8060, 2168, -2789, -14255, 1444, -520, 169, + 1032, 1478, 294, -644, -320, 856, 1282, -216, + -1000, -925, 2, -890, 679, -629, 1152, -1329, +-13941, -16385, -1050, -1022, 106, -1151, -41, -709, + 1771, -882, -729, -1420, 1544, -120, 386, -838, + -2744, 1559, 904, 273, -4221, -1065, -312, -1046, + 234, 830, 387, 172, -956, -332, 360, 408, + 125, 90, 348, 915, -264, 911, 263, 124, + -620, -612, 220, 164, 202, 124, -30252, -159, + 1006, -320, 283, -1641, -1312, -9057, 5525, 7520, + -2884, -12194, 2771, -1164, 1842, 1261, -582, 766, + 2498, 393, 953, -617, -756, -323, -1862, 1195, + -1326, -436, -965, 366, -6727, -1226, 9014, 400, + -1258, -812, -279, -404, 1621, 86, 1622, -16, + 96, -515, -257, -39, -134, 1843, -294, -491, + -908, -120, -720, -1162, -1555, 405, -134, 528, + 23596, -77, 183, -444, 2077, 955, 649, 2246, + 3236, 735, -1202, 7954, 9440, 6134, -7267, 28, + -3398, 500, 4965, -1230, 306, 357, 2942, -906, + -4733, 903, -3945, 4447, 1046, -1125, 465, 1183, +-12710, -1018, -11302, 5177, -219, -6232, 1552, 2061, + -1372, -1290, -822, 295, 814, -3003, -527, -614, + -856, 802, 167, 1178, -494, -1625, 754, -1550, + 682, -1286, -480, -694, 86, -67, -1429, -1235, + -559, -311, 322, -308, -56, 296, -158, -24, + -748, -197, 26954, 1054, 209, -226, 165, 681, + -131, 341, 341, 1510, 615, 907, -264, 1355, + 388, 198, -5, 418, -783, 28539, 82, -559, + -459, -344, 279, -114, 966, -529, -423, 286, + -418, -766, 42, 186, 461, 418, -688, 2937, + 2793, 146, 1709, -665, 2022, 293, -1522, -2740, +-15926, -600, -1503, -1732, -2827, -1027, 1702, 252, + -643, 470, -815, 858, -1954, 1190, 1847, -16, + 266, 29, 486, 25985, 139, 220, 433, -330, + 168, -362, -562, 180, 906, 386, -845, 664, + 1064, -616, -1498, -335, -164, -930, -854, -869, + -101, -204, 835, 117, -16034, -4478, 2634, 1629, + -1873, -1156, -373, -526, 2537, 967, -2433, -857, + 1264, -1670, 113, 845, 7654, -1343, 5245, -1605, + 2236, -1190, -48, 3340, -1981, -1606, -1369, -227, + -727, -570, 1136, 1868, 667, 92, -144, 531, + 949, -1086, 530, 1764, 302, 190, -28036, 182, + 825, 229, -656, 585, 444, 200, -1195, -1855, + -387, -781, 1156, 692, -1164, -517, -464, -275, + -328, 218, -970, 174, -384, -561, -38, -720, + -140, 1021, -271, -57, 463, -25313, -342, -40, + 26, 159, -854, 916, -1532, -1033, 265, 105, + -719, -588, 96, -435, -296, -226, 224, 357, + 30, 576, -66, -30037, -72, 374, 32, 256, + 304, -852, -706, 248, -741, -379, 980, 629, + 1344, 3858, -2211, -153, -3914, -3775, 1570, 718, + -1042, -1338, -4409, 1338, 5118, 5186, 3619, 2142, + 9081, -2784, 4169, 3598, 6621, 4562, -170, -614, + 1196, -1174, 5024, 721, -71, 267, 4, 25598, + -369, 356, 331, 1099, 377, -356, -938, 1161, + -863, 1107, -132, 222, 148, 1410, 908, 60, + 377, 1280, 468, 690, 454, 247, -4552, 6122, + -267, 2973, -5932, -6424, -4983, -4193, -3386, 1691, + 1349, 1419, -3730, 300, 12150, -2927, 1588, -34, + -2435, -271, -961, -1744, 1881, -73, -453, -788, + -798, 9166, 2744, 858, 342, 991, -287, 822, + -37, 1156, -1493, 723, -14127, -1755, 2029, -933, + -1276, 632, -5249, 464, -272, 1149, -290, 4693, + -728, -1475, 841, 10, -283, 92, -268, -295, + 358, 160, 405, 2, -381, 679, 716, -190, + 128, 275, 255, 123, -412, -453, -273, 26, + -174, -340, 644, -376, 27584, -25, 66, 3107, + -1707, 911, 500, -1029, 1029, -1557, 9020, -398, + -2512, -582, 1131, -16696, -429, -1284, -3, 2320, + -532, -302, -174, -146, -413, 2152, 1009, 42, + 402, -1471, 157, 5742, -782, -229, 2379, 646, + 2842, -1776, -463, -2749, -3617, -1710, -12281, -566, + 263, -3174, -2337, 9590, -1150, 2465, 4577, 2064, + -648, -2175, -1877, -674, -634, -338, 343, -1492, + 878, -530, 1072, 13670, -4542, 746, 9704, -4188, + -7076, 1179, -740, -589, -876, 268, -1080, -986, + -4584, 2692, 3032, -2067, 230, -3533, 944, -4950, + -1908, 1452, -255, -698, 1460, -606, -250, -154, +-22303, -945, 1626, -588, -482, -1549, -129, 978, + -631, -722, 1094, 1771, -311, 532, -508, 696, + -1128, 1270, 854, -84, 4290, 414, 3351, 1061, + 931, -2936, -9606, -35, 2514, -1095, 567, -452, + -8520, 4037, -431, 2744, -2276, 2647, -1188, -454, + -400, -3698, -315, 11558, -667, 512, 162, -395, +-13015, -11, -1944, -890, -14358, -3850, -4296, 1310, + -580, -248, 1305, 402, -1049, 115, 2085, -1797, + -1172, -321, -919, -313, -512, -131, 1619, 576, + 499, -2024, 130, 14, -76, -6324, 495, 2445, +-16757, -2348, -2706, -1906, 2377, -2252, -619, -2579, + 643, -661, -1276, 935, 893, 992, -2204, -2451, + -395, -508, 1163, -216, -13034, -718, -1018, -1675, + -698, 710, -257, 2658, 1178, 2046, -2270, -2588, +-14442, -1142, -1026, 2247, -536, 314, 123, -1175, + -673, 1576, -2600, 5, 964, 619, -1714, -14811, + -1502, -1646, -1151, -93, -11652, -222, 343, -2203, + -351, -928, -289, 2679, 2101, 742, 747, -2245, + 146, -1828, -2728, 1058, 1048, 3046, 242, 4432, + 246, 350, -13419, 768, -805, 1819, 14332, 1316, + -370, 391, -1421, -1426, -355, -812, -64, 196, + -2917, 1097, -1550, -1246, 436, -62, -813, 1350, + 555, -2236, -1589, 980, -1483, 10122, -2434, 7236, +-15225, 1513, 2090, -1224, -83, -2821, 664, 658, + -3242, -1031, 1509, 2667, -160, -1315, 1060, 891, + 432, -1311, -2503, 1304, 1295, 1745, -722, -2496, + -4409, -3360, -2776, -2793, -4921, 12616, -1031, -443, + 1495, -2416, -4640, 4508, -2944, 2608, 1323, -394, + -415, -2111, -2065, 1030, -3636, -1338, 2916, -3007, + -3680, -3152, -115, 577, 2742, 785, -4429, -1945, + -304, -4883, -133, -3136, -1927, -576, 618, 1780, + 2568, -2102, -158, -3986, -1187, 280, 655, 162, + -1352, -5730, 15372, -1314, 1553, 274, -2873, 4221, + 4610, -4143, -13699, 2760, -1255, -238, 1487, 1583, + 1422, -2272, 4734, -6368, 795, -406, 1498, 1588, + -500, -2744, -875, 2080, 1901, 960, 344, 979, + -258, 952, 2526, -11785, 893, 669, 1361, 518, + -1368, 3854, 2539, 623, -1835, -4177, 2686, -2956, + -2804, 1121, -8890, 1377, 1125, -3990, 140, 3594, + 1757, 2271, 366, 1723, 2150, 13557, -1768, -1433, + -6632, -578, 3266, 2509, 7142, 680, 1532, 1318, + -1123, 5668, 1283, -412, -5404, 2893, -2647, -2695, + -1412, 340, -650, 863, 1895, 2867, 384, 626, + 856, 508, 1365, -295, 960, -26080, 234, -4, + 239, -412, -6, -765, 736, -30, 136, 912, + 538, -792, 413, 871, -437, 305, 30, -194, + 1105, -1113, 3550, -4854, 449, -549, -7626, 3706, + -3698, 1778, 1441, 2240, 73, 513, -3383, -2346, + -1372, 3955, 2973, 1175, -6087, 5071, -2135, 8552, + 4961, -1201, -1458, -2627, -730, 515, -756, 476, + -1104, 2115, -1276, 498, 336, -451, 809, -1030, + 556, -211, -70, -93, 89, -755, 296, 872, + -282, 380, -298, 2774, 660, 1339, -545, 429 +}, + +.cb1108l1 = { +-13570, -9232, -673, 267, -819, 1633, -33, 623, + -850, -4376, -1135, 999, -262, 1928, 695, -1751, + -2793, 772, 5064, -1158, 280, -2144, 1313, 888, + -2482, 469, 2996, -1406, 12525, -1200, -1202, 939, + -3, 847, 818, -924, 135, -1308, -12000, -544, + -592, -3914, 441, 3372, 3188, 1314, -1836, -706, + -844, -1319, 1029, -1754, 172, 2468, -903, -889, +-14602, -2054, 11694, -1980, -730, -1661, 214, 1243, + -337, -646, -95, 1432, -854, -236, 88, -2, + 514, -1643, -84, 3561, 302, 770, -1248, 480, + 664, 738, 1728, -1783, -2227, -702, -3582, -16641, + 1713, 1506, 660, -2471, 2061, -48, -3161, 1697, + 900, -1477, 558, 287, -5515, 1023, -1972, 999, + -1856, -3022, -228, 711, 1270, 2644, -648, 1064, + 3899, -1205, -754, 1080, 1262, 18, 860, 2274, + 655, 494, -221, -15647, 1334, -473, -1648, -341, + 3541, 3109, -1671, 639, -2491, 185, 477, -388, + 5198, -5680, 812, 700, 2180, -536, -19468, -2508, + 2592, 2901, 32, -1165, 1500, -422, -790, -1914, + 971, 111, 1226, -1302, 541, -3862, -832, 642, + 305, -3870, 8921, 570, 180, 1734, -1572, -891, + 17672, -756, 702, 2740, -647, 2122, 102, -1371, + 461, 454, 204, -307, -1248, -2330, 1353, -1783, + -1939, -601, 512, 2118, -2178, 254, 1190, -1252, + 923, 1166, 360, 320, 320, 1210, -142, -416, + 1260, -205, 1403, -1025, 19252, 328, 58, 21, + -1044, 1786, 2153, 697, -436, -1617, -869, -493, + -2419, -3102, 1995, 1519, -1799, -153, 2689, -665, + -1371, -915, 18486, 941, -2612, -1057, 1076, -3351, + -48, -1478, 575, 728, 130, -168, 40, 898, + 2141, 1518, -965, -1910, 896, 838, 1220, 416, + -1494, 1404, -126, 21472, 604, 1740, 102, -812, + -796, -734, 1082, -507, -468, -1732, 1171, 252, + 359, 436, -765, 791, 726, -810, 1838, -1798, + 5662, -2362, 1275, -2829, -4041, 1398, 2681, 480, + 13740, -752, 2252, 1306, -1026, 1834, 54, 9993, + 559, 1370, 711, 1918, -1757, 646, 16, -3262, + 2676, 1751, -2595, 4782, -1050, 2401, -15131, 1100, + 386, 708, -359, 455, -25, -950, 241, -482, + 268, 2327, -2766, -142, -1992, -566, -36, 990, + -6302, 3245, -1394, -1579, 760, -757, -2115, -8542, + -2945, -800, -4027, -3102, -1319, -1989, -1787, -426, + 590, 1031, 467, 31, 2674, 1686, -14352, 1174, + -1446, -813, -1267, 2919, 2052, -1574, -753, 3369, + -1090, 3830, 2042, 11376, 1140, 895, 1130, -720, + -1284, -2277, 49, -724, 397, 13201, -985, 1599, + -365, 1517, -496, 978, 2152, 1391, 1777, 3032, + -936, 280, 1719, -4551, 4874, -941, -160, 956, + -676, -229, -548, 183, -16606, -855, -3433, 1248, + -578, 2254, -532, 3081, -1406, -1859, -605, 1809, + -1001, -114, -1222, 3890, -609, 3114, -2430, -2142, + 440, 1780, 1606, -4211, 1047, -456, 8280, 9, + 5866, -1718, -932, -13049, -562, 3097, -583, -21, + -1972, 1254, -172, 527, 2282, 5064, -5391, 1074, + 357, 1845, 24, -996, 100, -50, 1098, 2905, + -417, -937, -439, 247, 18502, -2380, -2088, -402, + -580, 83, -282, -70, 969, 540, -219, -1132, + -1701, -195, -3030, -2748, -1974, -1304, -1909, 1080, + 1042, 1124, -128, 5816, 2303, 2840, -2420, 35, + 16550, 721, -2079, -1489, 1023, -654, 2025, 1479, + -185, -2449, 500, 3034, 2663, 3911, 1203, 998, + 594, -533, -163, -262, 739, 13, -426, 182, + 394, 350, -30055, -371, 150, -430, 147, -1122, + 43, -390, 298, 831, -194, 158, -114, -257, + -1346, -585, 206, -456, 478, -502, -1710, -1719, + -581, -536, 45, -861, 825, 1093, -255, -685, + 38, -20, 419, -594, 10, -1408, -526, -19191, + 196, -1496, 255, 1844, -8759, -3565, -1009, -926, + -818, -1195, 236, 2898, -182, 14344, -1384, 1064, + 1181, -1846, 543, -583, 170, -3305, -1187, -2406, + -40, -1051, -1071, -28, 1482, -1060, -1057, 3028, + -2023, 913, 1052, 980, -5158, 4642, -14067, 3920, + 1450, -4497, -1591, 842, -2222, -392, -42, -3546, + -258, -3566, 2595, 225, -2696, 4624, 2283, 1483, + -1506, 2164, 151, 380, -3207, -1086, -10594, 2005, + 2379, -2567, -925, -363, -1261, 13174, -73, 1168, + 2215, -1721, 726, 525, 1048, 322, -827, 2117, + 3890, 1346, -3512, 2243, 638, 2259, -1371, -2260, + 10590, 851, -1247, -894, 1871, -882, -1955, 3822, + -3654, -1730, 906, 2074, -548, 885, -2501, -1316, + -3275, -10694, 2031, 1077, 3013, -1105, 2951, 1907, + 1218, 194, 1860, -1662, 178, 915, 1092, 809, + -451, -610, -728, 799, -129, -101, -905, -2, + 2470, 1292, -137, 544, -18795, -1081, -300, -59, + 282, -329, -544, -1324, 2155, 9326, 462, -388, + -303, -2940, -608, -13652, 532, -1350, -1026, 1330, + 5559, -333, 4961, 707, -1832, 1070, 2483, -2016, + -315, 2197, 849, -348, 379, -2179, -15691, 903, + 3192, 3888, 396, 4610, 3261, -2589, -4903, -643, + 3604, -1380, 1524, -2155, 469, -3528, -790, 429, + -3862, 1797, -104, 2364, -1162, -1559, 1011, 1849, + -235, -1952, -2088, 1436, 2502, -3862, -1704, -14859, + -2863, 710, 624, 4373, -6302, -616, -807, -1577, + -2492, -620, -917, 948, 4957, -848, -863, 514, + -2210, 2162, -753, -15168, -2068, 12472, -2611, -723, + 2797, -8573, -2270, 978, -2597, 2215, -684, 2535, + 3114, -261, -178, 2385, -4869, 1161, -32, -1469, + 2074, -1407, 3226, -992, 4546, -3158, 1044, 463, + -5285, 4, -1396, -1395, 1770, -1767, -860, -6, + -2242, -1548, -667, 587, -982, -2246, -1312, 1550, + -542, 5302, -716, 135, -15895, 3382, -478, 1279, + 615, 3365, 1620, -12613, -230, 3101, 3230, -1307, + 2860, 628, 647, -3595, -214, -1631, 2783, 748, + 1088, -57, -6014, 2496, 359, 719, 1476, -750, + -1644, -2125, 3913, -3788, 565, -1118, -1411, 1377, + -1020, -246, 18851, -1438, -1150, -1492, -681, -798, + -776, 960, 911, -1449, 336, -1114, -2111, -877, + -532, 668, 1018, 1098, 408, 2032, -607, -656, + -5997, 3089, 2462, -18368, -1027, 78, -4066, 439, + -845, 1476, 290, 490, -452, 1638, -3381, 80, + 1699, 458, 260, 1215, -516, 1883, -62, 35, + -2540, -1703, -1042, 1751, -422, 1222, 207, -104, + 1112, 151, -473, -522, 26426, 562, 884, -2201, + -281, 238, -839, 1037, -588, 81, -109, -2, + -32, 75, 654, 489, 524, -388, -1408, -906, + -1193, -936, -273, -40, -100, -662, -522, -145, + 119, 614, -922, -25329, -180, -668, -574, 161, + -448, 173, 750, -609, -812, -125, 814, 572, + 2602, 20372, 244, 1820, 724, 515, 932, -1290, + -712, -990, -305, -13, -763, -1157, 481, -764, + 320, 624, -620, 642, -1494, -568, -601, -655, + -790, -1348, 334, -1302, 382, 782, -1122, -641, +-23549, 180, 463, -634, -666, 599, -356, -1071, + 816, -576, 1208, 912, -377, 624, 1049, 42, + -95, 370, 1932, -167, -275, 142, -159, -410, + 595, -562, -632, 748, 1192, 614, -41, -18, + -156, -61, 1280, -686, 363, 759, 756, -19362, + -614, 2151, -1185, 169, 327, 1494, 782, -1313, + -134, 841, 218, -76, -2980, 202, 80, 281, + 89, -61, -1678, 59, -125, 195, 320, -1310, + -56, 806, 47, -65, 249, 18432, -666, -506, + -204, -194, -560, -416, -3641, 330, -268, 842, + 10600, -176, 424, -1744, -3609, -1682, -844, -309, + -538, 435, 14251, -1281, 373, 2748, -702, -1358, + -766, 3480, -679, 4039, 529, -5698, -38, -813, + 1203, 4734, 318, -1044, -5109, 2187, -3474, 415, + 2436, -3021, -1628, -456, -1451, 3406, -1798, 1001, + -8648, 468, 1188, 497, 4628, -948, -4073, -11894, + -2750, -738, 1520, -4070, -810, -5755, -1370, 2978, + 4460, 917, 1221, -324, -1166, 2339, -1221, -2048, + 714, 6884, 3096, 6998, 13, -275, -3879, 790, + 104, 1383, 2056, 1957, -9216, -430, -199, 261, + 764, -109, -210, 795, 884, -334, 1546, -272, + -35, 738, -268, -13, -448, 645, 97, 76, + 1284, -343, -654, 112, 643, 22846, 634, -597, + -621, -784, -380, 951, -452, -685, 140, 688, + -770, 247, -679, -228, -26856, 311, -546, -444, + 606, 69, -195, 18, -220, -334, -42, 543, + -28, 492, 766, 208, -1206, -554, 213, -1112, + -1675, -608, 382, 2011, 5077, -17442, 1367, -702, + -856, -416, -1728, -1987, 2966, -1952, 38, 152, + 712, 210, -589, 3029, -1189, -2016, -8071, 10746, + -2143, -556, -1964, 162, -504, 995, 982, -2565, + -634, -985, -1668, 444, -2098, -411, 488, 1397, + -1134, 1888, -920, -279, 15057, -757, -1258, -3040, + -890, -105, -670, -490, -238, -2419, -1302, 915, + -784, -929, 1653, -89, 1076, 445, 2538, -1424, + 19175, -91, 437, 752, 254, 935, 854, -1666, + -86, -543, 1053, 664, -155, -485, -3994, -50, + 50, -58, -2626, 1801, -314, -16052, -1831, 1009, + 2344, -3030, -938, 1761, -1283, -150, -425, -6660, + -900, 1374, 803, 549, -2683, 837, 483, -655, + 4610, 1259, -45, 834, 1103, -3250, -3604, -2882, + -2463, -5331, 11312, -1653, -3505, -1855, -4962, 8579, + 2370, -2474, 501, -1282, 985, -924, 3452, 456, + -242, 3878, -2095, 2994, 7076, -459, 2574, 16116, + 8277, -88, 572, -38, 0, 1664, -553, 1820, + -2096, 1076, 415, -420, 1900, -1696, -130, 298, + -1555, 201, -404, -1831, -932, 844, 9606, -497, +-16304, 3278, 918, -523, -1573, 2488, -813, 147, + 1540, 3795, 1390, 1061, -78, -10, 574, 2620, + -1143, -512, -582, -1496, 736, -4323, 786, -2873, + -1342, 3932, 14508, 12635, -899, 1730, -673, 386, + -676, 2787, -2780, -2960, 375, 475, -2188, 2250, + 851, 788, 268, 1264, 2973, -94, 1062, 1006, + -697, 669, -635, -986, -4848, -1486, -6, -3914, + 6267, -1560, 8, -503, 5273, -3545, 69, 15146, + 2263, -1490, -548, 1740, 1636, -892, -895, 769, + -471, 226, 6497, -2466, -2037, -1068, 1075, -902, + 13668, -1213, 12424, -3523, -124, -1090, 972, -1134, + -494, -2568, 881, -3081, 369, -254, -618, -914, + 443, -1254, 658, 1322, 546, -14, 778, -116, + -378, -802, -268, 48, 1140, 25942, 503, -637, + -871, 1050, 298, -187, 387, -406, 343, 212, + 110, 723, 695, -47, -50, -568, -66, 347, + -1588, 20, 701, -485, -98, -787, 4502, 1046, + -1628, -2526, 185, 1016, -256, -700, -403, -154, + 103, -752, -689, 2084, -1463, 2294, 360, 17590, + -698, -1262, 788, 116, 755, 751, -440, -610, + -469, 1235, -2314, 1240, -308, 553, 1065, 24442, + -733, 667, 4, -484, 93, -263, -361, -278, + -1524, 176, 1311, 1561, 435, -436, -1079, 260, + -366, 472, -1049, 647, 158, 302, -931, -36, + -990, 736, -444, 1077, -1560, -251, 148, 1000, + 1096, -300, -224, -307, -17646, 39, 206, 74, + 505, -3051, -1285, -793, -724, 718, 324, 803, + 874, 6062, -2235, -3321, -550, 9264, 3483, -4172, + -4024, -471, 858, 2682, -1078, -1922, 2088, 1135, + -878, 545, 2205, 836, -1088, 547, 12461, 2222, + -828, -3841, 4797, -2360, -2510, -4029, -2213, 13736, + 1032, -958, 1895, 264, -1499, -2066, -241, 1324, + -224, -792, 776, 2130, 2600, -2276, -4239, 3260, + 1610, -1620, -1220, -2752, 979, -2028, 19626, -2146, + 684, -729, -235, -289, 588, -600, 245, -879, + -816, 413, -87, -1158, -246, 69, 970, -111, + 500, 1097, 1087, -138, -1356, 30, -434, -452, +-22802, 177, 492, 206, -257, -854, 1445, 37, + 1384, 97, -258, 811, -222, 53, 548, 1744, + 124, -1031, 1076, 186, 453, -173, 1180, -2235, + 583, -392, -1542, -726, 2937, -3635, -856, 1446, + 7796, -2779, -962, -2277, 1651, 1960, -1460, -1277, + -9794, -288, 2459, 2350, -2521, 84, 578, 2286, + 480, 1620, 6421, -200, 170, 1513, 198, -1001, + -491, -1000, 161, -482, 607, 214, 743, -292, + -394, -192, 92, 73, -415, -316, 593, -42, + -346, 456, 44, 950, 129, -189, 806, -221 +}, + +.cb1108s0 = { +-32768, -828, 9569, 331, 6938, 3122, -1008, 2847, + 646, -5690, 1712, -795, -4406, 1368, 307, -526, + -2206, 26, -210, 1358, 746, 1920, 667, 3866, + -413, -720, -4328, -2475, -1189, -863, -3809, -5052, + -8567, 2859, 1915, 4895, 12440, -13002, 2757, -5969, + 4054, 1100, -9430, 4930, 10266, -1522, 7092, -8778, + -1968, 4325, 8440, 3888, -1966, -688, -2455, 2966, + -2380, 1682, 4956, -2310, -3706, 404, 6774, 17562, +-12437, -2667, 4864, -9411, -6436, -9316, -903, -5526, + 3463, -1690, -5250, -12568, 2338, -1310, -3019, 776, + -641, 3483, 54, -10732, -3878, -691, -17615, 4530, + 10267, 7830, 8488, -12624, -4514, -17183, 7070, 3115, + 4176, 383, -4558, 410, 6379, 6242, 4702, 4853, + -217, 446, -3811, -2396, 244, -2120, 3275, 5122, + 180, 4523, 8680, -1868, -6164, 2636, -5056, -4039, +-11618, 4014, 11349, -2616, 8240, -5119, 1988, -2552, + 6060, 3206, -662, 2686, 1116, -10447, -3004, 650, + 7811, -12148, -327, 856, -916, -397, -600, 4621, + 3011, 5539, 5417, -2374, 9667, -4714, 7821, -2819, + 573, 4492, 1882, -26770, 1486, -6963, 1103, 2515, + 8196, 1849, -7492, -5243, 2106, -5290, -11000, -1410, + -3448, -8548, -4536, -7730, 3083, 6109, -14458, -8624, + -381, 7840, 4694, -3906, 8223, 3315, 5849, 13112, +-13132, 6081, 11801, -7624, -376, -6372, -6817, 6834, + 1760, -1435, 1072, 3505, -1494, -709, 5786, 454, + 1807, 2650, 7728, 1357, -1002, -5366, -2368, 2052, + 333, 6312, -336, 8274, -1653, -4309, -6630, 2841, + 2448, 8398, 5376, -7248, -1474, -1842, -4119, 838, + 501, -4206, 4052, -1250, -20943, -3338, -592, -2973, + 7057, -128, -3235, -4313, -2510, -11313, -4925, 3103, + 1448, -5186, -1322, -16815, 1956, -7950, 2641, -2890, + 4396, 2322, -1381, -1911, 448, 2543, 3535, 782, + 3719, -624, 1610, -2843, 7583, 1794, 700, 3107, + 4528, 5461, 2540, -1074, 5976, 741, 576, 4426, + 4400, -4920, 5724, -3734, -1186, 10645, 1100, 10537, + 2828, 11670, -8391, -32572, -9405, -6807, -875, 2277, + 736, -4546, -18693, 1204, -1083, 3422, -3328, 6013, + -2992, 5812, 2744, -11668, -2519, -2384, -3635, 6532, + 6874, -2820, -5222, -12261, -14266, -6663, -1150, -2032, + 2099, 4642, 1638, -4162, -644, 249, -3133, 11830, +-10712, 12370, 4818, -1924, -5639, -6448, 2455, -4898, + -613, 1760, 2393, 1414, 7039, -7018, 5901, -2900, + 3786, -3230, -3718, 3514, -4040, -4676, 6367, -1449, + -2758, -2888, 4066, -7140, 408, -7656, 3156, 19919, + -1858, 6671, 352, -3355, 3074, 5524, -1429, 1954, + -6664, -10082, 4405, -1598, -806, 1779, -6913, 7062, + 5064, 6518, -1042, 3400, -5530, -1192, 590, -3298, + -772, 571, -6239, 9810, -12380, 1302, 1344, -3430, + 3830, 4106, 5792, -6196, 224, -2604, 3954, -12551, + -5539, -8306, 1801, -4521, 3578, -4349, -5716, 4960, + 3620, 1516, 5779, 5550, -3710, 3329, 10542, 4198, + 5148, -3291, 196, 6232, 6943, -1303, -10306, 1862, + 6547, -1544, -2996, 2868, -4389, -6894, 28557, -13130, + 1397, -2331, -4076, 2870, 3592, 6613, 265, -4790, + -3514, -3152, 8710, 230, 3142, -1264, 1822, -769, + 6168, -1792, 2189, 2660, -2664, 3402, -533, -3100, + -476, -1164, 6092, -2930, 3372, -5895, 8507, -918, + -4716, -1582, 23959, 1506, 2360, -117, 2029, -452, + -6575, 964, -13132, -2838, 3800, -3355, 3168, 5230, + 11116, 826, -1711, -3546, 7398, -4092, -2884, 743, + -1784, -3824, -3437, 1050, -3306, 928, -5109, -7999, + 1581, 8609, -4662, -3594, -1618, 9929, -3982, -5591, + -8789, -1444, -12011, 1304, 12668, -5138, 10837, -7951, + -4089, 3921, -5375, -2486, -2590, 11398, -80, 7734, + -4547, -11286, -7098, -7758, 5303, 7380, -11266, -11138, + -8676, 30, 6328, 597, 7852, 3144, -3933, 15142, + 3954, 12197, -507, -1667, 5517, -4187, 709, -1330, + 2094, 4739, 1341, 8276, 8544, -10107, -10151, 3641, + 771, 4798, 4839, -3254, -9246, -7304, 14850, -18155, + 3068, 4993, -4930, 10985, 6270, 8528, 5904, -13010, + -7824, 1300, -706, -156, -4228, 302, 9962, -3087, + 4472, 4541, 13179, -6576, -2541, 8284, -51, 5366, + -4369, 289, 3890, -3671, 1894, 21820, -3031, 5336, + -8412, 2487, -1211, -6759, 1292, 3749, -8904, 638, + 6863, 154, 1145, -684, 6648, -3874, 2005, 4670, + 4408, 4191, 3984, 632, 2957, -1532, -3974, -2576, + -1636, -3714, -136, -4946, 3900, 367, 27072, 1864, + 1426, -3321, 860, -1768, -2009, -3436, 2666, -9899, + -1328, -2330, -3078, -3258, -4600, 5604, -5248, 1703, + 4403, -4781, -8275, 6717, -3860, 10980, -10634, -8360, + -2291, 20311, 7602, -4028, 483, -4886, 2677, -4921, + 6065, 5393, -2145, 6201, -472, 1796, 2869, -3578, + 3053, -2342, -3193, -2589, -3215, 1322, 536, -164, + -314, 4800, -1903, -1338, -11833, -23399, 5562, 4440, + -1864, 2520, -4251, -1464, 5053, -8553, -3852, -5932, + -849, -7113, -3493, -5338, -1671, 1496, 4504, -1830, + 5716, -210, 1397, -2060, 2242, -583, 2604, 5355, + 13938, 13150, 1346, 2649, -1527, -4568, 8891, 7399, + -6492, -10371, -4885, 13056, -8262, -1267, -2959, -868, + 5941, 299, -601, 8834, 1436, 5404, 1914, -3775, + 980, 8848, -2270, -1952, 6902, 8642, -25725, 9556, + 14540, 1998, -13157, 308, -13844, -10126, -2147, 8296, + 1772, 1094, -9712, -8560, -7552, 5527, -1446, -1097, + -5798, -17270, 2860, -210, 2136, 175, 729, 11775, + -5154, -4202, 13342, 3977, 14494, -5659, 9105, -11067, + -3694, 4794, -593, 6817, 1875, -4975, 3663, 4141, + -8317, -8932, 2127, -4176, 1136, -148, 7640, 8127, + -744, 2354, 389, 1600, -6475, -4558, 10735, 11407, + 3896, 13098, 1814, 5191, -3850, 2629, 18430, 8343, + 4630, -4624, -702, -3834, -2276, -2894, -1556, 1437, + 424, 5652, -6260, 2387, -5845, 7496, 10657, -2754, + 4806, 1169, 1308, -4114, -5347, 15076, 5686, 7287, + 3004, -6254, 5186, -14096, 10323, -1974, -9355, -5544, + -986, -5998, 261, 4494, 2467, -1911, -603, -4548, + -1344, 1995, -1603, 10464, 5222, 3714, -5342, -8039, + 12530, -26465, -1813, 4044, 746, 8123, -12078, -4703, + 2971, -4487, 2556, 3904, -2518, 1504, 5774, 5431, + 1120, -934, -5202, -6826, -8774, 7156, -2392, 10643, + -2918, -4298, 3361, -3758, -894, 5828, -203, -4905, + 6480, 11771, -19830, -17545, -4920, -17263, 10066, 10125, + -8980, -19719, 23554, 27907, 2607, -7014, 6128, -23759, + -4802, -7099, 874, 13103, 21667, -8475, -12938, -13122, + -3694, -18860, -3518, -3586, 12658, -793, 10661, 6925, + -730, -11373, -7845, 94, -2627, -6044, -2213, -4381, +-10198, -5816, -56, -4349, 3722, 3911, -1719, -2513, +-13290, 3218, 105, 1876, -76, -1107, 2563, 4520, + 10288, 5862, -7738, 6180, 9863, 1380, 6756, 2632, +-18798, 9314, 7190, -7454, 432, -15141, 8462, 2128, + -2386, -2710, 292, -751, -3125, 6147, 4941, 3146, + 3046, 120, 321, -5884, 5105, -4300, 6264, -317, + 1667, -694, 7950, 5639, -3284, 1089, -6456, -14694, + -3527, -1104, 4313, -20858, 7920, -10782, -13536, 933, + 4523, 2640, 2118, 97, -614, 9834, -9515, 232, + 5086, -6720, -1529, 568, 3139, -3665, -8567, -13771, + 6274, -4370, -5653, -8920, -7667, -9391, -6653, 12489, + -3666, -5103, -12324, 4796, -540, 10396, 3668, -3467, + 7124, -4398, 87, -12139, -204, 1213, -2190, 11948, + -2641, -2434, -5647, 2819, 3148, 3558, -6455, 3705, + 1644, -3090, -4225, -5998, 112, 17789, -7220, 2166, + 4153, 4516, -1100, -1667, -1402, -8837, 6344, -1586, + -3451, 2357, 616, -392, -8163, -11579, 6160, -2783, + 7895, 11321, -11847, 8070, 5231, -6496, -3172, -3470, + -2960, -11437, 465, -470, -2568, 11197, -9417, -4117, + -1162, -1893, -2361, 551, 14478, 3510, -1372, 3117, + -8236, -2904, 14556, 3191, 200, 2166, -13974, 2718, + 3946, 2444, 1982, 5320, 2087, -2222, 1573, 742, + -8828, -3917, -11080, -241, -8472, 6119, 290, -2364, + -3163, 1923, -1964, -582, 2564, -5566, -6411, 2069, + 7392, 9115, 25316, 1504, 2540, -814, -1746, 566, + -1580, -2290, 170, 698, 105, 9567, -6714, -584, + -4934, -379, -491, -978, 4580, 1180, -3355, 1882, + -4343, 4817, 1503, 9968, -8878, -4908, 3419, -4818, + -2254, 6694, -4368, -10849, -5093, 4510, -3129, 152, + 1926, -4490, 1510, -17764, -6699, 962, 3474, 4981, + 25, -7128, 1432, 5386, 3108, -4545, 1092, 1663, + -1363, 3076, -8916, 6158, 244, -1181, -825, -933, + -5570, 17221, -535, -2892, -5031, -1297, -3010, 5840, + 678, 748, 3944, 1630, -3648, -5457, -2618, 876, + 6655, -2834, 2597, -6667, 1330, -40, -4423, 6257, + 743, 6083, -584, -3742, -1401, 1779, -5166, 4559, + 5558, 8588, -6476, 7521, -1561, 4950, -778, 3564, + 11403, -1010, -3151, -14151, -1020, 2595, -3278, 24555, + -4859, -909, 2314, 1301, 2098, -5664, 3938, -4050, + -203, 3368, -2580, 3061, -9266, -6263, -6748, 3890, + 1950, -329, 1050, -1106, 588, 23705, -661, 6913, + 722, -5820, 2147, 3789, -1689, 661, 5389, -8519, + 1152, 3800, 7160, 5234, 1343, 3218, -2900, -391, + -4258, 5084, -4783, 7262, -10013, -811, -5252, 6474, +-17338, -2388, -2596, -8715, 5836, 9523, 639, 4652, + 3071, 3114, -1648, 1563, -931, -10143, 4394, -2838, +-11900, -1012, 841, -5812, -3048, -2715, -196, -5794, +-20022, 1949, 3464, -770, 2200, -3564, 1975, -6242, + -1937, 3954, 5678, -2744, 1888, -3825, 5770, 3869, + 8315, -7386, 1318, 1302, -5534, -4554, 924, -3804, + -4292, -22757, -7972, -7469, -3543, 7858, -10125, -2637, + -4765, -10644, -5944, 1159, -3293, 4363, -1219, -12248, + 5060, -7232, 6947, -1609, -3037, -5084, 6580, 15873, + 5336, 7295, 2386, 2961, 4655, 9714, 5080, 11635, + 1790, 2897, 687, -914, -692, -6653, -8562, -1412, + 244, 4478, 1650, 7175, 1046, -6689, 3693, -3520, + 6046, -1336, 1976, 16822, -1176, 792, -1733, 8286, + -7359, -2402, -8536, 1392, -3271, 6580, -4939, 1562, + 595, -4237, 4872, 4266, -1798, -6589, 7457, 4207, + 9978, -3996, -2236, -3078, 1861, 10101, -2394, -3250, + -7619, -7082, -14305, 5664, -1337, -11019, -3839, 10190, + 7249, 3086, -1782, 24, -3566, 10769, -4102, -6408, + -688, -8987, 3018, -5942, 7478, -368, -7931, -3018, + 6766, -78, 5705, -3264, -1100, 4850, 4518, -28, + -6276, 4905, 7094, -4394, -2846, -88, 434, 2039, + 352, 9827, 12372, 1207, -8561, -4476, 1496, -4927, + 2087, -6730, 1134, -81, 57, -8701, -2918, 3953, + -2844, -1842, 4804, -5315, -401, 7060, -16397, -4802, + -9849, 17542, -11715, -12432, -6676, 9323, -13189, -5761, + 8054, -620, -7431, 3726, 17790, 7880, 251, 2983, + 3736, 7118, 17197, 8613, 1445, -15290, -16184, 11084, + -4971, -5922, -1893, 9067, 9321, -8139, 714, 182, + -3138, 7258, -1874, -2781, 10800, 2915, 5316, -5206, + -2581, 10219, -484, 862, 119, 6628, 1514, 3883, + -880, 7586, -2573, 3279, 3801, 4492, -3850, 9416, + -38, 7518, -574, 4052, -1136, -668, 9672, -9536, + 2551, -4223, -1074, -3616, 8446, 158, 3262, 7965, + 1311, -8634, -6786, 700, 4973, 917, -754, -1156, + 6054, 2067, 10757, 421, 1030, 11351, 2149, -4286, + 12075, 4593, 1193, -5290, -8566, -2965, 6824, -6238, + 2392, -3395, 5350, -2789, 7529, -1873, 3032, -1494, + -2703, -18535, 1583, 9539, 2556, -4422, -6079, -2699, + -7860, -4573, -8236, 4281, -1079, -17578, -2840, 7468, + 4675, -5002, -1268, -1529, -8222, 8285, -766, -4314, + 6048, 11507, 5046, -2444, 3186, 1732, 7872, 6598, + 2828, -2920, 8278, 13263, -10204, 1334, -5552, 10532, + 5412, 2554, -10076, 1128, -3959, -3210, 4091, 1824, + 4984, 5558, -2204, 2080, -3802, 6614, -7380, 3612, + -4624, 6366, -1795, 4038, 6227, -4312, -4910, -2127, + 15077, 4144, -16885, 3757, 2303, -670, 5625, -2590, + -2594, 2491, -3174, 4199, 1152, -1532, -7308, -8578, + 6431, 2975, 6032, 3037, -7451, -2643, 5503, -7856, + -2451, 5309, -3678, 8145, 1864, -8341, -15575, 7716, +-10337, 8935, 12350, -10418, -4092, 734, 10400, 10934, + 5724, 1778, 5836, -3203, -10700, 2766, 4178, -18135, +-16589, -5465, -5005, 7239, 25480, 7310, -6408, 6142, + -7748, -1423, -4318, -321, -2899, 3728, -3184, -3578, +-11598, -1223, -8554, 656, -3945, -4084, -724, 301, + 9539, 9695, -1799, -2602, -1379, -5282, -4709, 11858, + 9562, -7508, 4886, 896, 5780, -160, -12724, -9598, + 1220, -5411, -5072, -6476, -11763, -104, 9311, 5230, + 591, 4342, 263, 13198, -17801, -1892, 2619, 18194, + -2080, 16536, 18497, -25926, 25541, 66, -6648, 1627, + 2794, -3790, 9424, 1387, 20702, 5260, 5211, 1702, + 1019, -11143, -6501, -18711, 10869, -4204, 4994, 1722, + 8569, 3670, 4386, -16874, 8876, -2297, -2743, -4562, + -9207, 8033, -346, -3586, -9451, 3242, 1552, 4278, + -6787, 7118, 3630, 4602, -7371, -12789, -10424, -14922, + -3010, 1885, 4144, -4490, 4074, 7796, -1201, -7244, + 2675, 1221, -7060, -12828, -3520, 1983, -4615, 8207, + 1606, 517, 3646, -7252, 816, -3690, -674, 13100, +-16254, 4727, -8184, -968, -5366, -2288, -20260, 1174, +-19384, -4199, -5292, 582, -13118, 1836, 1698, -2034, +-14601, 6642, -10530, 482, -851, 9968, 7050, -13366, + -8354, 4740, -20050, -193, -1881, -1205, -4042, 7067, + 12872, 5846, -4792, -1833, 2504, -3222, -1607, 2634, + 4587, 6761, 1549, 1124, 9427, 3978, -8305, 7524, + 2507, -5744, 3238, 5238, -3664, 694, -28496, -1674 +}, + +.cb1108s1 = { +-10979, 8698, -630, 4660, 3060, -7292, 10140, 11942, + 1448, -5820, -3144, 3100, 10575, 6888, 3505, 9996, + 2787, -484, 8057, 1503, 6329, 3074, 3954, 9419, + -736, 2333, -1858, 3264, -4026, 16130, -14501, -5284, + -472, 850, -7258, 1542, 1473, -2348, -7055, -9574, + -2275, -4383, 7542, -360, -2945, -3878, 28, 809, + 600, 2246, 587, -1779, -3456, -737, 3242, -2523, + -1862, 6127, 899, 1070, -15614, 10990, -3084, 9546, + 7339, 8899, -1490, -10379, -9193, -3857, 8289, 7261, + 12489, 7814, -6458, 1223, 15486, -10960, -1880, 4922, + -7819, -527, -2370, 3687, 1358, 10367, -14266, -1496, + 1060, -9325, -5582, -3947, -17536, 1470, 4878, 10793, + 2904, -2566, -4995, 6549, 6141, 11048, 3177, -494, + 9087, 797, -2575, -5616, 1197, 2966, -11287, 4658, + -504, 4571, 1814, 18830, 26254, 2399, 8750, 2656, + 8206, -12987, -9119, -1027, -457, 1228, 6137, 2322, + 1732, -5694, -892, -249, -178, -7009, -4368, 402, + -5564, -5183, 2470, -4745, 2788, -3255, -5181, -706, + 40, -4915, 8926, -3633, -2455, 15054, 5376, -867, + -7270, -979, 7053, -7433, 13749, 5039, -2234, 8474, + 7031, -3917, 5127, -7602, 580, 12067, 2252, 149, + 86, -582, -5729, 2193, 4178, -9195, -11824, 3897, + 1298, -1044, 6450, 1885, -19562, 6205, -4610, -2544, + 5192, -4885, 5021, -2373, -102, 7358, -2434, -3512, + -4048, 3070, 45, -1344, 202, -2189, 448, 1172, + 2939, -547, 1003, -6370, 3643, -1157, 3932, -6044, +-12882, 1959, -1574, 2574, 14854, -16317, -6627, 505, + 1102, -9361, -8087, 7525, -1466, 284, 3756, -383, + 5147, 5060, -474, 531, -6144, -1872, -1206, 527, + -4861, -12410, 7508, -7226, 5046, -12233, -4153, 4628, +-14402, -5265, 534, 1528, -13408, -62, -18757, -1280, + -9301, -10254, -8990, -6335, -7724, -3394, 1951, -13271, + -1389, -5274, -4616, -9643, -10295, 1332, -5618, -10737, + -7536, -9314, -7006, -760, 7694, 2955, -404, -2800, + 15250, -3828, 5994, 5408, 8411, 16568, -7280, -6901, + -222, -1554, -862, -1871, 939, -3678, -4348, -3200, + 3220, 1614, 8598, 8162, 1749, -7378, -1658, 931, + 3870, 9183, 1509, -5068, -17, 5733, -8121, 2769, + -3195, -3296, 8940, 2828, -2470, -2448, 7413, -2851, + -1058, -4505, -9653, -5074, 73, -3286, -4014, -1760, + 2562, 13690, -3464, 5438, -3394, 16997, -2944, 291, + 4224, 1175, -2237, -6894, -5479, -1291, 3390, 5455, + 898, 3461, -7914, -4785, 1879, 1059, -3721, -5796, + 5054, -3931, 6315, -2460, 1909, 573, -3373, 3052, + -178, 986, 572, -5976, 5781, -4928, -10539, 580, +-18727, 757, 1759, -4049, 2232, 1890, 4115, 699, + -2934, 4926, 2391, 10848, 5103, 4340, -1518, 2288, + 2283, 8886, -5131, -4429, -4384, -3265, 11933, 3993, + 11474, 3721, 1532, 976, 6112, 1954, -2360, -1783, + 2080, -6356, 2482, -4646, -1992, 1590, 1790, 3290, + -2312, -564, 508, -1688, -7522, -9263, 3059, 1883, + -3005, -1303, -9146, 10282, 1333, 4692, -2083, -15792, + 2208, 1128, -11574, -7149, -1126, -4995, 18963, -6262, + 5045, 2179, -822, -1249, 10092, -338, 5744, 1635, + 2535, 6114, -1339, -8337, -4370, 4288, 2468, 3051, + 12491, -9554, -4034, 522, -1085, 5852, -2759, 4918, +-10717, -194, -11376, 3059, 12075, 1037, 5260, 816, + 5918, -1987, 7924, -6022, -10374, 11607, 25035, -11598, + 16894, 2458, -5461, -2039, 385, 6002, 7574, 1229, + -834, -1032, -7453, 2694, -1447, 3632, 4215, 3541, + 2936, -3294, 1001, -6451, -4595, -11682, 7880, 2261, + 3786, -2849, 2276, -826, 3742, 7586, -334, 2837, + -2331, -12849, 1170, -1150, -5253, -997, -8996, 8124, + 2234, 904, -2294, 3144, 7352, -5452, 1536, -8800, + 1886, -18282, -9787, -8066, -12066, 1536, 4460, -1345, + 1418, 7471, 13451, -7299, 5507, 6795, -184, 8905, + -2040, -4933, 4998, 7317, -6667, -5134, 9094, -8561, + -2534, 3422, 2278, 3118, 205, 5811, 2247, 5946, + 1078, -2105, -6946, 170, -1625, -4734, -1447, -4329, + -4553, -2230, -8738, -15289, 7311, 6665, 5047, 1984, + 11896, 13922, -10490, -9313, 1424, -2991, 1408, 335, + 8914, 3773, 8814, 7917, -4560, -114, -624, 8984, + -1598, -580, 3233, 590, -2172, -3162, -3985, 5394, + 13842, -11625, 73, 12826, -1204, 5119, 10304, -10006, + -2695, 1318, 156, 84, -760, -4638, -3804, 3041, + -782, -2994, -3113, 637, -3256, -5831, 452, -1204, + 1614, -11626, -4769, 10612, -8710, -20019, 10542, -4279, + 6912, -1429, 3812, 2844, 3903, -11622, -8954, 180, + 3898, 3858, 119, 1385, 4038, -5899, -969, -5454, + 13305, -6748, 5934, 8027, -7348, -3797, -29781, -4956, + 2037, -2331, -3292, 8254, 6597, 4446, -7848, 6250, + 1400, -1182, -4966, -3490, -1410, -2286, 3334, 350, + 9271, 2987, -934, -5702, -3881, -97, -671, 5108, + -133, 1302, 11630, -8858, -3027, -42, 3682, -1507, + 3992, 5641, 2778, -8698, -2509, -1360, 77, 2116, + 98, 2853, -6334, 5915, -1214, -2721, 8921, 1380, + -4158, -4315, -4740, -21049, 7044, 866, 2094, -9442, + 9003, -5147, -4897, 3407, -11558, 4280, 4508, 6697, + 1612, 1508, 8547, -14257, -151, -9530, -7250, 11321, +-14430, -4944, -2488, 1349, -248, -1490, 1749, 3970, + -5830, 20767, 4642, 3236, 36, -17079, -11099, 5996, +-10759, -39, 7822, -7527, -1431, 179, -3841, 2298, + 1407, -241, -2303, 9244, -3626, 6609, 1959, -518, + 368, 1678, -5334, -5849, -4986, -2363, 607, 2809, + -1006, -7695, 10022, 2216, -8992, 4282, 807, 14707, + 9528, -11065, 3014, 3157, 5597, 1139, -1298, -3642, + 7839, 860, -4336, 2624, -4171, 1791, -2825, 5362, + -529, 1494, 337, -4487, -671, 5360, 3283, 4933, +-14692, 4033, -4365, 2713, -6903, -1784, -10862, 6173, + 5278, 14859, -852, 10020, 12304, 8898, -3089, 9183, + 1841, 8276, 4929, -261, -1264, 615, 3615, 14535, + 6557, 519, 4228, 7382, -1805, -4529, 4992, 4277, + -342, -9610, -5193, -7022, -23264, 2402, -740, 2875, + -5052, 1983, 4987, 3336, -3806, 1335, -2868, 846, + 7652, 936, 3510, -4570, -3010, -8805, 6177, -4413, + 5879, -15204, -1632, 13416, -4543, 3838, -9293, 1744, + 920, 15544, 3820, -5852, 3935, 2357, -6486, 1932, + 12044, -6374, -2545, -2389, 2755, -8073, -8203, 4659, + 4286, 16128, -987, 434, -4495, -4428, -4816, -10329, + -4529, -13408, -13283, -1136, 4002, -1271, 3547, -5274, + -5577, 701, -365, -2764, 370, -369, 2611, -832, + 3862, 4604, -7786, 11170, -1453, -1568, 10758, 168, + 402, -1985, 1436, -8858, 10080, -8559, 3998, -4310, +-13478, -3104, -11458, 506, -18194, -3724, -6768, 7960, + -4213, 1121, -1658, -1141, -1874, -383, -5090, 748, + -1032, -1207, 1046, -1865, -2387, 2126, -3672, 6733, + -2794, 3797, 15562, -11989, 170, 6129, 658, 929, + 4800, -4296, -955, -2189, -188, 3180, -118, -766, + -2182, -6928, -2254, 6615, -4422, 6324, -31, 3742, + -5832, -5022, 4671, 1574, -6309, 288, -2768, -2492, + -4818, -5192, -248, -3236, -429, 120, 1182, -10486, + -2964, -3713, -5978, 11817, -20052, -6525, 2054, -879, + -602, -2843, 7244, -1372, 417, -172, 3322, -6556, + -7021, 5842, 7357, -2799, 3660, 7579, 4682, -2242, + 73, -9247, 21061, -2060, -3614, 2486, 4793, -2959, + -510, -74, -5982, 2274, -4147, 3260, 1994, -1678, + -7494, -13624, 2560, -7375, -896, -4945, -2838, -11096, + -1969, 5879, 444, -3220, 14630, 4915, -2376, -8475, + 9854, 11380, 11060, 1534, -14413, 4366, -9544, -10646, + -7654, -17916, 3481, -3240, 1776, -2436, -8403, 3679, + -1914, 12537, -5540, -5294, 5995, 5968, -2609, -16882, + 789, -9506, -10075, -12142, -7580, -7090, -2046, 11065, + 7617, -3503, -2013, 3516, 6347, -195, -3119, 2444, + 14, -4998, 767, 4976, -3974, 9038, 579, 1804, + -8206, 32767, -5633, 1018, 13388, 996, -12737, -3179, + -2058, 13663, 1274, -4475, 7386, -1698, 17927, -6118, + 15942, -2922, -3434, 5903, 6333, -9149, 14140, -1488, + 2999, 1151, 2361, -1935, -10243, -11566, -5319, 965, + 5146, 3652, -441, -2173, -3484, 3685, -13595, -1703, + -78, -1408, 18517, -3788, -3266, 3162, 996, 19950, + -8560, 4989, 6593, -5329, 2950, -13896, -3524, 5590, + 4055, 6084, 2493, 12659, -5786, 4858, 7252, -7111, + -7318, 5411, 7393, -8714, -3454, -1562, 1919, -49, + -680, 7285, -398, -2956, 7100, 5563, -538, 1719, + -16, -3824, 437, -6842, 1504, 5694, 1214, 3209, +-15562, -4365, 9329, -25577, 1425, -2598, -8389, -6891, + -3275, 3304, -3993, -6391, -934, 7862, 4844, -134, + 9890, -4646, 2468, -9901, -4111, -3080, -5056, 476, +-13099, 1447, 205, -2424, 7098, -12075, -4646, -13725, + 8367, -2910, -8461, 1387, 3553, -10228, -2771, 4698, + -6483, 12234, -8086, 3329, 2374, 452, -1805, 5083, + 2014, 164, 7143, 81, 6062, 2838, 5318, -4982, + 1440, 2014, -3273, -6658, -798, -3204, 1398, -599, + -5834, 2070, 4644, -17238, 390, -1684, -4932, 8961, +-12217, -3079, 6574, 1387, -5991, -7803, 1285, 7439, + -395, -3048, 2038, -847, -690, -5127, 2228, -4180, + -3499, 530, -584, 9884, -323, 446, -15644, -9162, + -1683, 3643, -3578, 2634, 496, 8097, 109, 1056, + 1422, 5452, 6517, -449, -2389, 302, 6827, 1507, + -3106, -7188, -4909, -441, 12955, -3933, -5322, 5155, +-23171, -2780, -2655, -4048, 12844, -3709, 6555, -5700, + 3780, -6566, -4415, 11091, 11291, 6443, 9146, -796, + -1420, 5600, 12098, -5790, 6619, -10474, -12177, -5890, + 21700, 11148, 3427, 3130, -5727, 14646, 13953, -2721, + 1404, -3102, -4693, 4762, 1757, 2533, 3998, -530, + -758, 5301, -1426, 8948, -720, 6877, -3863, 2396, + 5266, -685, 890, -7188, 2742, -270, 8125, -804, + 32292, 6964, 8599, -3466, -1080, -8423, 2070, -295, + -157, -5432, 152, 2478, -3738, 1104, 1500, -5290, + -2463, -6386, -2537, -2331, -3290, -2398, 159, 6588, + -2547, -2424, -2184, 8316, 5670, -5608, -2600, 2659, + 166, 14828, 2622, -10490, -16378, 64, 434, 4576, + -3010, 2479, -6798, 3431, 360, -1067, 3421, 664, + 4029, -4050, -240, 3875, 672, 3587, 501, 2494, + -48, 9997, 3259, 8551, -7624, 17342, 10765, 4328, + -3721, 1729, -2844, -6330, 5114, 15589, -261, -7554, + 2708, 7260, 5852, -8736, 436, -6160, -588, -5919, + 5752, 3127, -4558, 540, 74, -4048, 3735, 7873, + -2869, -544, -111, 5182, 1032, 2315, -159, 5105, + 4106, -494, 678, -4756, -3865, -7389, -2492, 7193, + 5146, -7926, 12043, 11137, 1719, 2307, -5476, 12679, + 7996, 726, 933, 3222, 7515, 678, -5858, -2716, + 1503, -3014, -2125, 4982, -4984, 467, 986, 5450, + -1472, 5314, -1285, 218, -3411, 4511, 8047, 4268, + -8307, -10587, 17200, 3303, 7553, 5361, 1108, -7982, + 8240, -5856, -3376, -3952, -2884, 4401, -7252, 4078, + 7538, 3420, -13834, -1139, 10742, -2536, 636, 7758, + 4282, -3505, 1190, -7382, -8164, 5306, -408, -5005, + 2776, 7806, 4781, -7903, -2370, 13884, 542, 5643, + 6948, 6471, 2699, 815, 4454, 1882, 2290, -3856, + -3086, 8215, 3234, 4444, -1580, 2835, -3083, 6706, + 7409, 4626, 2658, 2308, 7965, -1034, -2584, 344, + 704, 12280, 10344, -8032, -4410, -6168, 6860, 7977, + -5630, -6680, -5001, -6199, -10378, -1764, -3322, -4284, + -1048, 2721, -11738, -11800, -7975, 2754, 3424, -7641, + -2245, -4945, -194, -1948, -2850, 4111, -21846, -8750, + 4306, 24494, 10428, 26998, 4976, -2701, -3283, -723, + -1539, 6758, -9730, -3517, 6401, -4546, -410, -9900, + -4947, 6996, 10983, 5110, 19948, -78, -1794, 11051, + -14, 316, 6447, -20430, 9363, 9062, -2134, 13711, + 6448, 6655, -5232, 4610, -10352, -3042, -8713, 5777, + -2438, -2602, -7293, -755, 6736, 2960, -3676, -2882, + -9806, 1342, 1242, 2122, 2749, 631, 6502, 2266, +-12996, 13620, 19762, 8096, 702, -4394, -8668, -1460, + -3228, -173, -6239, 4643, -1916, 4098, -2234, 1202, + 1763, 6170, -6320, 12984, -5936, 8301, 6021, 2191, + 466, -4044, -1913, -3458, 8197, -3249, -5935, 2383, + -4241, 4977, -4415, 704, 3488, -8356, 10229, 562, + 14, -4828, -3890, -7599, -4208, -3166, 1132, -16584, + -506, 1397, 6266, 3307, 5782, 2349, 3257, -3017, + 7814, 1216, 7440, -10096, 12698, 944, 1221, -1683, + 152, 6020, -7910, 3897, -6954, -9439, -9838, -3860, + -5383, -4228, -1980, -4045, 7442, -5504, 2145, 636, + 2857, -4538, -820, 4275, -2104, 5076, 5191, -363, +-23254, 1962, -66, 7550, 88, 8721, -1361, 7733, + -2661, 5282, -5112, -24, -975, -3200, -2235, 5144, + 213, -6340, -3974, 1266, -2383, 2432, -124, -233, + -3504, 10604, 806, -918, 11601, 19332, 206, 7456, + -8885, -9692, 3087, 3685, -2183, -7538, 11970, -5098, + -7364, -1173, -3099, 6532, -6850, 4622, -828, 390, + 467, -5364, 4442, -1878, 8949, -4340, -261, -2720, + 6659, 16184, -6552, -3736, -15416, 15774, -306, -4240, + -1807, -10304, 11073, 2743, 3974, -5557, -3499, 5315, +-10742, -378, -4517, -5949, -7664, -2830, -6510, -6096, + 2052, 3425, 1971, -3328, 5326, -1362, 1806, -14286, +-12774, 6058, -3365, -735, -2586, -18658, 6664, 9502, + -1590, 323, 6445, -17766, 14694, -9786, 3696, -4547, + 1601, 3645, -584, 910, 2516, 8197, 3898, 4306, + 631, -2020, 4309, -765, -6591, 2083, 8969, -1474, + -27, 9130, -5808, 8492, -135, 2230, 2296, -4509, + 4600, 4951, 1930, -2564, -5889, -1338, -11737, 6387, + -3649, -5447, -2462, -4751, -1012, 3523, -3504, -9510 +}, + +.cb1108m0 = { + -2417, 4623, 2916, -4257, 120, -10323, 1198, -10252, + -117, 8767, 3160, 2323, 1162, -650, 2237, -4171, + 2386, 432, 1627, -7255, 38, 124, -3658, -1558, +-11711, 10, 8146, 1700, -1975, -16731, 2397, 1056, + -2502, -2660, -2731, -2477, 1488, 1220, 4880, -1156, + 1805, -3, -3009, -6233, -2216, 3440, -3082, 2124, + 70, -2461, 1125, 1919, 11949, -2506, -622, 2209, + -702, 2685, 9183, -510, -2806, -1129, -1823, -1746, + -3600, 2298, -3360, 10793, -1714, 1662, -62, 395, + 14142, -261, -144, -9896, 11481, -884, -2197, 352, + -326, -453, -1984, 2027, -1466, 3290, 94, 3481, + 2533, 4401, 5492, 3803, 247, -896, -1688, -3166, + 1130, -1125, -1973, 322, 867, -1936, 714, -880, + 8, 2313, 23418, -1682, -677, 384, -2140, -386, + 920, -2523, -495, -1494, 3027, -707, 1172, -1403, + 2177, -2137, -885, -1035, -1637, 375, 2452, -3709, + -1171, 2069, 1095, -1937, -686, -956, 2034, 3410, + -3075, -359, -598, -2084, 18550, 1781, -45, 1400, + -1580, -13180, -609, -1376, -3145, -248, 5661, 6886, + -3915, -194, 9876, 1065, 3879, -1726, -837, -660, + -7467, -3055, 3516, 283, -1604, -625, 1165, 3023, + -1531, -1825, 1430, -561, -881, 1346, -129, -1817, + 851, -32768, -294, -188, -116, -646, 1176, 630, + 903, 417, -2487, 352, -789, 571, -127, -2054, + -2112, 418, 1631, 266, -270, 362, -2765, -1198, + -182, 3586, -1272, 1470, -66, -18384, -1230, 823, + 1171, 1350, 1101, 1410, -3730, 1535, -101, -3234, + 2315, -34, -458, 1361, -16497, -990, 1438, 2542, + -1193, 586, -1708, 2689, 2741, 6010, 4209, -5974, + -628, 1556, 2238, 6134, -3040, -2937, 2188, -1660, + 1137, 1316, -2650, 905, -502, -93, -1177, -31964, + -1170, 1504, -1284, -104, 168, 55, 3478, -161, + 2818, -484, -32, -1536, 1218, -854, -351, 4465, + 16922, 681, 4198, 419, -414, 6824, -3906, 11598, + 75, 4904, 1374, 64, -2692, -3759, 3065, -1397, + -202, -347, -2466, 96, 1035, -765, -258, 3711, + 1437, -18250, 566, 976, 2483, 4, -1096, 1906, + 3745, -2621, -2756, 1864, -560, 98, 821, -4094, + 5349, 1369, -5245, -2170, 2932, -1052, 3932, -413, + -400, 31206, 1125, 1631, 43, -764, 1666, 780, + 2036, -564, 64, 1311, -202, 843, -2030, 856, + 1766, -3163, -1158, -626, 316, 127, 1783, 1918, + 3384, -2887, -5885, 1763, 4910, -248, 17100, -3022, + -1880, -2927, -1287, -3308, -1767, -2622, -1460, -250, + 3597, -4526, 946, -1533, 1059, -8, -807, -1283, + 1436, -11184, 643, 398, -1565, 1983, -60, -9862, + 1219, 322, 3132, -2043, 1138, 6258, -3540, 790, + -923, -4692, -1401, 2733, -8918, 4905, 6181, 192, + 82, -1094, 4, -634, -1323, -2865, 1036, 1484, + -2461, -937, 414, 221, 2179, -438, 1273, -2690, + 18442, 2781, 1788, 2264, -1230, 4284, -4708, 1190, + -4810, -975, 230, -3728, 2504, 3602, 3488, 88, + 1322, 487, 2965, -3731, -2341, 5937, 8545, 1716, + 7308, 9017, 6426, 727, 3992, -4584, 388, 3714, + 1164, 18, 445, 1253, 398, -1989, -824, -430, + 745, -5447, 2176, -1986, -3963, 2861, 194, 17739, + 1891, -5368, 4172, 125, 530, -2766, 1179, 401, + 1759, -1609, 31234, 910, 1100, 1036, -948, -1101, + -614, 1768, -344, 840, -696, -842, 320, -1444, + -2560, -3199, 58, -2172, 1375, -3002, -821, -863, +-12096, -2484, -677, -2130, 4450, 3568, -3192, -1114, + -3218, 3121, -503, 5570, -561, 3896, 10566, -3065, + -2768, 1398, 1719, -2708, 1952, -142, 4777, -978, + 2238, -5780, -430, 1228, -1298, -2923, 4353, -1621, + -2368, -2908, -8012, 4398, -502, 518, -6964, 622, + -377, 3758, 6598, 4438, 6849, -7696, 470, 3585, + 466, -14664, 3438, 14706, -1944, -2544, -785, 3653, + 1274, 443, -694, 1968, -3499, 2855, -3930, -1210, + -528, 1931, 3849, -772, -2659, 4499, -3624, -540, + -1645, -949, -382, 979, 595, 165, 429, -80, +-20468, 1040, 544, 2545, -5010, -2122, -2840, -335, + -405, 404, -50, -2996, 1226, 519, -1046, 3745, + -2317, 6211, -14500, 9754, -5802, 5230, -3112, 1506, + 3741, 664, -902, 197, 2476, -3618, 2040, -1066, + 2338, -257, -2580, -293, 2740, -576, 2050, -865, + -3666, -2090, -1831, -32056, 658, 1549, 1602, 1728, + -534, 390, -1517, -627, -4025, -797, -2351, 2759, + -102, 2574, -56, 796, -232, -886, 1639, -2773, + 1007, 830, 5880, -2220, 762, -3834, -2865, -415, + 584, -3498, -4546, -16108, 344, -4072, 551, -5435, + 2007, -1418, 3838, -1662, 1981, 3545, 1424, 769, + 2135, 1705, -15076, -636, 283, 3386, 97, -1048, + -3933, 204, -8616, -556, -2936, 4241, 5100, 1777, + 98, 719, 6202, -1496, 708, 2160, -2396, 4060, + 1513, 2253, -46, -1823, -132, 709, -756, -944, + 575, 1070, -1583, 587, -24575, -1989, 874, -568, + 1040, 1116, -4002, 3196, 2826, 117, 1590, 2456, + 938, 112, -938, -1268, 5056, -2851, 2995, 2559, +-13121, -8374, 3593, -6684, 3663, 766, 747, 1016, + -921, 2241, -1942, 4269, -3312, -1012, 2340, 2781, + -3881, 2532, -1976, -1436, -3219, 420, 22088, -742, + -640, 3270, 1446, 1935, 1279, 1913, 1377, -3297, + -751, 4209, -1052, 2381, 2938, -1330, 2154, 2784, + -2420, 1270, 2334, -526, 1480, -435, 2206, 252, + -510, -1018, -1469, -1294, -950, 424, 1058, -2317, + -846, -20737, -1877, 88, -431, -1268, 116, -378, + -2326, 3115, -246, 30, -4725, 648, 2084, 14286, + -817, 2496, -1947, -4869, -9703, 1505, -2476, -2108, + 747, -449, 3002, -5464, -514, 1805, 2559, 2494, + 12782, -1232, 12091, 2118, 3996, 2592, 1058, 510, + -1384, -3050, 2533, -408, 5219, 3044, 3242, -185, + 2654, -3723, 16, -1723, 1823, 6144, -4806, 182, + 1772, 4841, 16390, -96, 2505, -7713, -5244, -3316, + -6776, 1448, -1470, 4238, 294, 889, -2372, -6281, + -2423, 5423, 2119, 2897, 1378, 817, -993, -1599, +-14662, 3014, -3397, -6182, -245, 4897, 5116, 2285, + -2863, 1174, 415, -6777, 3863, -6009, -4722, -119, + 606, -2247, 4447, 1064, -1935, 2705, -2629, -1144, +-11980, 3805, 882, 1634, 5446, -4300, 643, 3436, + 7632, 592, 998, 674, -2647, 4644, -6854, 1368, + -146, -3395, 10599, 1369, 3852, 1689, 2437, -3937, + 3405, 2517, 1895, -14092, -1142, 2570, 10163, 1608, + -2445, 850, -1678, 3112, -3465, 3138, 4413, -1973, + -4151, 1163, 1822, -3819, -1568, -407, -2642, 424, + 365, -3599, 164, -1448, 1062, 1536, 1590, -1982, + 200, 18572, -230, -638, -1253, 1650, 2280, 4945, + 4527, -2353, -4216, 3752, -3807, 3686, -4816, 2382, +-14833, 1306, 17246, -739, 2012, 3521, 1473, -1436, + 1514, -142, -461, 1038, 2462, 971, 1354, 1272, + 1787, 2420, -922, 3364, 2250, 497, 1349, 2795, +-32768, 425, 1874, -72, 2461, 389, -306, -1180, + -646, 251, 299, -2735, 577, 1055, 1826, 1620, + -1214, 1422, -901, -1273, -2367, -1241, 366, 521, + -433, 55, 4000, 3035, -1390, 2505, 1786, -15397, + 413, -5916, -234, 3559, -6776, -5068, 2251, 36, + -180, 596, 5744, -2450, -1276, -4786, -1872, 24, + 252, 464, 2833, -136, -25600, -33, 873, 2646, + 1471, -1336, -1330, -276, 1778, -242, -951, 1580, + -79, -858, -927, -4310, -604, 7568, -1713, -948, + 192, -260, -1334, -1116, -705, 638, 132, 1186, + -952, 1157, 428, 2039, 1568, 1778, 22453, -2190, + 2176, 1674, -3996, 1294, 1162, 274, 415, -2877, + 464, 505, -1842, -1066, -2241, -761, -291, 8, + -987, -104, 796, -32768, 1302, -809, 571, 1214, + 455, 686, 656, -1752, 886, -790, 644, -1114, + 2358, 11452, -4398, 1334, 13095, 3230, -1818, 4053, + -1990, -1093, 878, 3796, 2712, -1523, -1229, 1077, + 960, 1250, -75, -3233, -7734, 2783, 8430, -327, + -1428, -1687, -4092, 269, 3161, -569, -1267, 1774, + 2772, -2033, 171, -520, 1551, 3719, -3364, -220, + 1904, -1282, -2008, -818, 4261, -886, -19201, -3454, + -478, -2645, -2601, -2124, -3977, 2960, 1563, -432, + -989, 2682, 1734, -9085, 4614, -4454, 2535, -7201, + -220, -10022, -431, -7907, 889, -9658, 6653, 762, + -1827, 5886, 862, -1836, -430, -16363, 5709, 851, + 1814, 304, 5045, 1685, -1004, 5108, -5936, -3143, + 940, 1832, -270, -674, 1441, -241, 3222, -551, + -434, -69, -3584, 349, -1354, -12080, 3639, 5219, + 7583, -1023, 2078, 3263, -5807, -873, 4085, -5153, + -3623, -436, -4717, -1803, -6274, -2049, -247, 2516, + 1922, 10204, 2194, -1574, -535, 656, 1638, -3091, + 1156, 1377, -1220, 4956, -221, 4984, -1154, 4603, + -1618, -5655, -2583, 13494, -2442, -3968, 3086, 1098, + -1625, -13781, -12826, 2659, 3604, -702, -1900, -3508, + -6283, 2320, 1979, -2823, -4890, -1728, 2, -4402, + -437, 1932, -3272, 2853, -3018, 840, -632, -6691, + -484, 9579, 1008, 11677, -2814, -2029, 8048, -1170, + -7366, -2664, 3349, 1319, -1160, -1864, 606, 1568, + 5428, -4763, -2470, 2145, 1798, -502, -1538, -3736, + -1376, 1330, -3567, -78, 478, -743, 890, -800, + -44, -1832, -1761, -1022, -996, -846, 1188, -1042, + -3202, -2439, 1602, 3601, 564, 18338, -17, 1327, + -387, -1998, -1260, 3352, 849, -4780, 1932, -56, + 2625, 10753, -1676, -10536, 2980, 1542, 1177, -3113, + -859, 522, 3092, 9588, 2882, -4540, -1406, -5183, + 50, -4245, 3649, -420, -3612, -5290, -1919, 14559, + -2605, 1169, -2009, 10760, -2372, 339, -2538, 4476, + 3001, -4570, -3158, -3465, 2873, 650, -2099, 76, + 1166, -1469, -2769, -391, 4215, -630, -1448, -1796, + -1573, 5914, 807, -1580, 2072, 99, 580, -2999, + 1079, -202, 17940, -1233, -4909, 1079, 390, -891, + 1834, -2155, -2642, -1703, 1856, -14125, 2081, 3178, + -2480, -4342, -11991, -2050, 1046, 2412, 436, 1046, + -2291, -1718, -3087, 1710, -963, -1914, -3423, 6190, + -1238, -4333, 115, -10550, -2742, -919, -4849, 1502, + -3054, -3304, 2300, -1850, 2337, -6643, 1995, -1279, + -238, 738, -124, 13593, 252, -1424, -165, 2786, + -1717, -838, -11244, -10971, -902, -3330, -2580, -2735, + -171, 4041, -2149, 2502, 6726, -738, -4235, 368, + 6144, -1718, -8620, -1888, 112, -282, -19, 4126, + 10797, 610, -3097, 7783, -2974, -2058, -3558, 470, + -5914, 10322, -20, 85, -1652, 6111, -1398, 2613, + 3733, -3716, 1930, -4325, -1199, -921, -446, 1095, + 1006, 910, -2323, -351, 808, -32768, 274, 1346, + 105, 2360, -1184, 2249, -970, 153, 3180, 1307, + 2207, -962, 2209, -921, 1504, -117, -2111, -3734, + 5738, 8014, 76, 1566, 3013, -462, -3600, 3939, + 4862, 1038, 4312, -790, -426, -1656, 20, -10568, + -6389, -6597, 4230, 2910, 2504, -2962, 256, 814, + -488, 824, -355, 3574, -1890, -2657, -767, 2730, + -1087, -2538, -3522, -4067, 6249, -3354, 13923, 4070, +-11004, 4703, 909, -5968, -5483, -4242, -780, -2489 +}, + +.cb1108m1 = { + 752, -4098, 7726, 592, -9487, 2004, 318, -4322, + 6989, -3350, -478, -4308, 2023, 753, -7081, -3934, + -866, 6267, -5710, 2100, -8467, 100, -4654, -6773, + 4271, 10728, 11618, 1128, 12733, 1471, -5518, -1162, + -2159, -402, -632, -4720, -28, -1412, -1037, 897, + -1242, -1735, -2632, -3460, 3389, -582, 206, 325, + -2547, 46, 1340, -4424, -13408, -4918, -2832, 1454, + 2127, 1276, 2292, -3973, -3230, -7810, 542, 4227, + 2673, -8490, -902, 1361, -1398, -1986, -991, -680, + 602, -2887, -557, 2656, 3214, 1794, 31241, 1462, + -1457, -3750, -1923, -2381, 1313, -128, -172, -647, + -574, 1045, 2438, 1662, 503, 288, 1535, -1016, + 2487, -820, 4692, 2799, -31949, 166, -1655, -2192, + -636, 1357, -2361, -459, -1752, 2782, -293, -144, + 1900, 685, 1766, 1900, -347, -4488, 590, 915, + 798, 1133, -4494, -1388, 75, 884, 13088, -2392, + 679, -315, -7520, 1086, 3873, 3297, -812, -626, + -9443, 2548, -6417, 1619, 7196, -57, 5, 3594, + -1922, 184, 2784, -261, -3310, 2779, 174, 2814, + -965, -2912, -1835, 425, -4285, 896, 2001, 3717, + 775, -1192, 22365, -175, 1522, -711, -1135, 5123, + -517, 870, 4323, 585, -437, 260, -1737, -1984, + 2522, -2539, -973, -8812, -16173, 4678, -4107, 130, + -7832, 1140, 2792, 3394, -692, -4105, -299, 1488, + 1246, 604, 2796, -3767, 579, 188, -1544, 86, + 424, 1204, 4441, -1000, 15227, 3459, -3444, -1631, + -2177, 3497, 1684, 925, 2872, -3905, 5729, 647, + 913, -758, -547, 566, 1787, 792, -1509, -1641, + -926, -1515, -116, 1266, 481, -3944, 28526, -2279, + 5577, 1026, 4082, -605, 696, 1094, -478, 5732, + 7247, 1461, 1521, -234, -42, -878, 270, -554, + 3702, -71, 1362, 7719, 305, -13654, -4985, -1072, + -2044, 6851, 438, -8435, 923, -537, 1511, -1003, + 2056, -2299, -15578, 503, 1944, 3188, 2318, 1761, + 1290, -2322, -568, -1591, -2746, -1966, -9784, 1514, + -5596, 4070, -181, -3006, -1903, -240, -1143, 393, + -1530, -822, 520, 989, -1600, -3374, 946, 678, + 86, -1957, 1947, 1188, 356, 719, -2874, -2245, +-19010, 547, 9067, 439, -2384, 847, -3307, -116, + -1114, -445, -3505, -967, -1252, 4880, 625, 1478, + -2970, -2275, 1337, 422, 3870, -1906, -1033, 1724, + -532, 1734, 1011, -21848, -477, -251, -615, 770, + 7520, 1030, -4372, -446, -3156, -2314, 172, 901, + 70, 1837, 1205, -1344, 2933, 1080, -1290, 1353, + 10205, 1158, 11135, 560, -3480, -2376, 7539, -5418, +-14092, 2138, -253, -9344, -1907, 2177, 687, 2772, + -2730, -546, -4180, 2021, -577, 2530, -3822, -7080, + 971, 2083, -1220, 203, 3187, 3705, -752, -2591, + -704, -17469, -1168, -214, 2518, 308, -585, 1117, + -1893, 2488, 1856, -23, 2418, -2922, 1960, 235, + -1629, -8277, 1088, 2032, 874, 2763, -1867, 60, + 1684, 834, -2676, 1574, -3098, 3250, -3723, -126, + 59, -787, 2710, 930, 1384, 475, -3915, -1162, + 1640, -16818, 2356, -70, 761, 4151, -778, 523, + -183, 19374, -4223, -1379, -1667, -1690, -512, 8742, + -34, 3816, -678, 2749, 2418, -341, -1216, 4280, + -2208, -264, -2884, 4679, -821, 1824, -6724, -1528, +-12042, -9908, 935, 4338, -116, 612, 6, -161, + 1935, 1600, -442, 4059, 2510, 2186, -7678, 3600, + -2460, -1072, -122, -1817, -246, 2786, 9079, 525, + -226, 2628, -2549, 1459, 4533, 1111, -17410, 4529, + -2545, -3272, 403, -2758, -1876, 2734, 2136, -6171, + -2055, 1163, -2820, 2992, 2978, 1458, 1572, 2508, + 13576, -1545, 14861, -796, -6444, 4022, -4358, -529, + 3439, -2630, -2457, 3030, -2972, -398, 471, 2547, + 1127, 1344, 202, 420, -1858, -589, 594, 1478, + 5590, 1682, -1560, -378, -2198, 400, 2231, 566, + -80, -2042, -4557, -2309, 8743, -4258, 1291, 11770, + 718, 2342, 2912, 5170, 2470, 6832, 833, 4990, + 2009, -1258, -898, -1414, 1214, 670, -2104, -5068, + 788, -18997, -743, -864, -356, 1592, -5786, 652, + 4952, -2319, -1097, 2177, -1654, 2879, -1645, -172, + -1581, -3062, -805, -1065, -2222, 20857, -1146, 864, + 1690, -1794, 855, 307, 2320, 3618, 6184, -4129, + 187, -2423, 4946, -3072, -213, -2621, -2026, -5793, + -986, -1597, 2125, 1474, 1766, 360, -4652, -1030, + 1546, -1085, -253, 1016, -96, -1608, -7017, -4855, + 1295, -271, 3751, 341, 19804, -2006, 2322, -2298, + 353, -2077, -764, 212, 150, -1140, 564, -614, + 268, -2023, -332, -699, -937, 1684, -1617, -22863, + 1202, -144, 62, 373, -598, 184, 987, 3721, + -611, 86, 3676, 362, -652, -214, -311, -694, + -1973, 2351, -733, -1601, -1189, 28227, -154, 10, + -347, 3400, 1333, -1695, -773, 1362, -447, -2999, + -626, -1776, 2474, 2195, -1041, -797, 1828, 62, + 3397, -1779, -2924, 1740, -1694, 4083, 15100, 3871, + -7821, -108, 292, 998, 3141, 5813, -918, -1290, + -902, 895, -1336, -50, 2014, -2066, 2383, 68, + 31769, -334, 1243, 1981, -715, 125, -380, -1272, + 1068, -357, -1734, -1138, -630, 1042, 688, -438, + -558, -2460, -2894, 4196, -1004, -2177, -2291, -4701, +-13990, 747, -5558, -2754, 1950, -2780, 8414, -1286, + -946, 220, -2507, -192, 3726, -1361, 1296, -2215, + 872, 8270, -2797, -6732, 1256, -1957, -2916, 107, +-14847, 1868, 4638, 1292, -1006, 5285, 2947, -5028, + 942, 153, 420, -1152, -391, 3612, 4621, 172, + 762, -876, -3561, -14406, -552, -2570, -4448, -15704, + -806, -928, 3380, -686, -2604, -3895, -714, -626, + -1763, 1144, 485, 34, -1922, 1528, -213, 5050, + -804, 185, 96, 3320, -621, -329, -1444, 864, + -1684, 16583, 1872, 3327, 2146, 1132, -8216, 73, + 6524, 1623, -4147, -4985, 1450, -646, -7189, 4524, + -1596, 2120, 3913, 680, 2094, 1660, 752, -1221, + 2414, 3986, -10314, 2096, 129, -5458, 634, -5426, + -594, -9731, 2083, -2284, -5085, -4777, -1323, -1740, + 6157, -841, -126, 247, -1163, -7005, 3863, -764, + -1552, 1356, 10788, -745, -12481, -73, 5234, -3220, + 2979, 635, 3372, -540, -36, 2887, 5221, 931, + -1724, -4824, 780, -49, 120, -739, 890, 714, + -1438, -458, -1861, -16732, -1858, -13282, 2182, -6796, + -3307, 556, -2968, 542, -2358, 1463, -3536, 1866, + 2833, -1369, -1576, -2825, 3561, -1625, 1858, -1052, + -1079, 1302, -2049, 19052, -1188, -4137, 1592, -4705, + 1082, -1168, 2355, 649, -1900, -2582, 1000, -3065, + -2399, 3625, 1062, 860, 2586, -2645, 14755, 3147, + 5002, -6720, 1728, -2114, 5090, -2838, 3020, -5048, + 4182, 2237, 706, -4945, -86, -1908, -1207, 135, + 675, -200, -22134, 1492, 2490, -1324, -1135, -842, + 1457, 185, 1342, 3516, -882, 1069, 1159, -52, + 1844, -1186, 554, 3860, 1824, -2136, -881, -1281, +-13259, -705, -90, 2150, 573, 2787, 1068, -1968, + 121, 805, 4382, -1033, -9220, -744, -1446, 7180, + 257, -5983, -1643, -6198, 1854, -3524, 1060, -118, + 56, -843, 2832, -98, -3493, 368, 6, -1877, + -3615, -1954, 17971, 962, 1532, -1754, 3776, 661, + -2025, -60, -1013, -1222, -3062, -69, -4933, 3064, + -1176, 213, 477, 1081, 1679, -2328, 1984, -21759, + -881, -54, -1101, -1092, 598, 1648, -3384, -213, + 379, -1318, -1972, 630, -536, -1970, -461, -356, +-22416, -1855, -113, 876, -2809, -587, -2323, -56, + 2177, -797, 1649, -4069, 1350, -2075, 101, -1384, + 1703, 1085, 471, 8093, 1020, -4112, 970, 866, + -1456, -341, 1418, -12938, 379, 9787, 1814, 2337, + -1705, 9913, 1026, 1962, -744, -2900, -1690, 1534, + -959, -629, 2330, 3735, 4742, -3139, -2135, 2298, + -2765, -1389, -3634, 27139, 671, 2208, 494, 1015, + -1197, -239, -321, -1145, -679, -637, -3116, 544, + -952, 882, 396, 1087, -3163, -2684, 759, -725, + -2186, -542, 2545, 3669, 24, 1689, 10473, 1836, + -419, 322, 2475, 1908, -1346, 50, -6401, -3644, + 552, 2348, 1327, 11853, 2467, 5493, 1544, 464, + 1796, -2801, 8217, 1014, -2103, 3764, 8091, 170, +-12422, 1708, -2438, -1873, 1970, 2160, -5027, -647, + -118, 2830, 2379, -1091, -5723, 124, 3017, 417, + 55, 1376, -1079, 7122, 3086, 17847, 2468, 3273, + -599, 3302, -922, -2073, -1696, 805, 2022, -1899, + 3188, 1425, -4364, -140, -3760, 437, 1393, -1298, + 17166, -1283, -2904, -692, 518, -404, 944, -1990, + -968, 1323, 2376, -11708, 2187, 3164, -559, 2212, + 1598, -1741, 360, 633, 3075, -660, -1012, 778, + 565, -2020, -123, 5, -2217, -2967, 374, 272, + 336, -1725, -408, -2270, -2645, -1044, -517, 1911, + -386, -4439, -7603, -1000, 7660, 589, 14931, 2901, + 11998, -13102, -1919, 3904, 86, 1617, 7324, 3078, + 1714, 4636, -2504, -194, -3274, -710, 33, -1965, + -2298, 2513, 726, 75, 67, 884, 2104, 4110, + 1936, 10387, 2722, -1970, -12496, 4799, 3086, -2938, + 1719, -2138, -338, -1124, 971, -4200, 480, -3361, + 6220, 5954, 1830, 1001, 2996, 4166, -2854, -437, + -1430, 1072, -312, -12949, 3113, -2479, -2034, 6956, + 2805, 2128, 856, -8803, -4709, -1274, -120, 1252, + 3898, 6526, -3914, -2276, 2754, -2604, -3038, 4136, + 2598, -2172, 4861, -2457, 2, -2693, -808, 3527, + -1184, 392, -2202, 2406, 960, -1064, -2589, 1161, + 2418, 728, -466, -4865, 211, 14720, -2093, -1977, + 85, -12618, -2073, -3028, -1067, 1734, -2491, 9506, + -422, -2718, -2966, 3883, -2852, 336, 1306, -2297, + 2009, 2589, 3071, 192, -1239, -10553, 2, -1174, + -3036, 9939, -27, -1278, 1448, 18655, 761, 931, + 445, -94, 206, 448, -1865, 232, -4353, 4596, + -260, -976, 594, 648, 796, -1376, -1186, 3056, + 3171, -5675, 6179, -1287, 16934, -1478, 1090, 577, + 8075, 1119, 2943, -3208, 1852, 1986, 6003, 901, + -962, -3196, -1907, 392, -2605, 2796, 4082, -456, + -3109, -1219, 123, 2470, 174, -1254, -1350, -4919, + 1271, 12302, -1154, -6317, -3346, -1315, -144, 1214, + -49, 3491, -1029, -2043, -8373, 4197, 4971, 9808, + 9732, 700, 2247, -2755, -2034, 3260, 839, -10554, + 1661, 11484, -3180, -1909, 1089, -813, 3116, -2103, + -3726, -4514, 663, 1152, 3902, 4862, 2739, -3828, + 707, 2712, -8009, -832, -16492, -1472, -2422, -5593, + 322, -1894, 2810, 109, -1788, 2050, 3539, -3112, + -6178, 2487, 2102, -135, 3163, 2096, 4123, -310, + -1090, -2, -2662, -17087, 1373, 1448, 162, 527, + 655, -2248, -3530, 194, 1305, 7590, -5515, 1225, + 1607, -3816, 2185, -2679, -4486, -582, 4981, -1675, + 147, 14790, 119, 11771, -1228, 1012, -6133, -2247, + -3913, 1348, -1846, -513, -6386, -749, 6726, 745, + -809, -799, 3224, 43, -2230, 2598, 2994, -1590, +-11198, -14476, -256, 695, 877, -3680, -2734, -1448, + 1336, -1633, 3327, 3497, 2956, -782, 2958, -1866, + 2876, 2003, -856, 1282, 5068, 391, -10539, 1703 +}, + +.cb1110l0 = { +-14944, -14950, -73, -1141, 1532, -575, -620, -816, + 1185, -1597, -2651, 1426, -1458, 1317, -1320, -19, + -209, -352, -163, 912, -85, -180, -546, -1121, + -435, -345, 229, 364, -850, 632, -426, -359, +-32768, 278, -1021, 310, -31, -355, -442, -234, + 415, -202, -10393, 1645, -378, -2270, 837, -1857, + 556, -935, -1344, 3016, 3452, 1597, 1378, 466, +-13740, -878, 1475, 237, -1301, 9756, -592, 23, + -192, 335, -58, 285, 376, 40, 24, 292, + 426, -1962, -798, 745, 1379, -34, 397, -14748, + -6285, 7343, -6374, 4442, -14800, 1878, -24, 1606, + -728, -476, 1754, -1052, 911, 3139, -1444, -222, + -1968, 1858, 1330, 244, 213, 935, -92, -348, + 155, 418, 29128, 236, -190, -226, -309, -178, + -690, 46, 716, -534, 147, -630, -75, -826, + 37, 4745, -1056, 2400, 1398, 1494, 460, -221, + 2908, -656, -15611, -2940, 2342, -98, 581, -3144, + -471, 3772, 2057, 1583, 13738, -139, 330, 1175, + 429, 63, -14544, -374, 1439, -1226, -422, -690, + 816, 1279, -592, 1642, 700, 1338, 0, -714, + 46, 377, -188, -366, -197, -637, -622, -262, + -69, -637, -1266, 257, 620, -1040, 324, -19064, + -602, -463, -1329, 513, 2699, -421, -1918, 2250, + -404, 403, -1514, 134, 147, 3, 426, 605, + 276, 561, -26, -294, 630, -500, -480, -133, + -712, -1144, 238, -633, 173, -29164, -1182, -274, + -138, -271, -232, 30, 706, -168, -848, 704, + -2132, -248, -108, 669, 1165, 234, 1243, -12201, + 2208, -1971, -829, 10305, -3964, -1502, -409, -3918, + 4520, -2259, -797, 2235, -5560, -1710, -2472, 280, + -1747, -980, -4529, -5208, -1813, 330, 890, -6220, + -710, -5583, -4704, -913, 2920, -12484, -4340, 334, + -1303, 283, -740, -1261, 3556, 3210, -11640, -14438, + -2557, -795, 747, 546, -2488, 1891, 485, 725, + 338, 1579, 2092, 2354, 284, 2812, 490, 1442, + 187, -2699, 1196, -1783, 1228, 2364, 13364, 258, + 2102, -6163, -200, -5475, 2804, -576, 6878, -2852, + 2246, 1186, 584, -136, 5258, 3825, 3045, -1661, + -5246, 2548, -5054, -4383, -1542, 12912, -1580, 1268, + -1415, -2012, 1021, -2106, 979, 2390, 3411, -1076, + -439, 5416, 1333, 440, 3422, -13384, 2540, 2544, + -3668, -2308, 1042, 589, 4166, 5090, 1539, -3447, + 7003, -4396, 319, -590, 481, -471, 22260, -1936, + -297, 1302, 1163, 937, -164, 847, 768, 827, + -430, 792, 472, -1557, 712, -602, -1007, -278, + -974, -3198, 10560, -2124, 335, -1206, 629, -13712, + 12, -1673, -691, -666, -2890, 826, 1792, -1547, + -2016, 807, 1810, 841, -814, 1214, 760, -1056, + 404, -94, 144, 297, -584, 106, 116, -132, + 236, -507, 86, 853, -670, 413, 32767, 730, + 10835, -502, 1297, -3857, -1035, -1602, -164, -1721, + 1468, 507, 1064, 1478, 4323, -760, -882, -4331, + 2564, -10933, 3000, 2101, -2492, -72, 12636, 2743, + -1113, -8334, 6720, 2348, 491, -23, -1065, 1506, + 2090, -1731, -1997, 675, 425, 8165, 695, 2285, + -433, 515, -465, -347, -1006, 357, -55, 57, + 481, -31494, -816, 60, 76, -439, -328, -217, + 265, 123, 839, 218, 1355, 243, -878, -12819, + 5168, 318, 1376, -2931, 12689, -83, -220, 2848, + -770, 150, 1631, 1955, 1552, -1371, -3053, 1752, + -7250, -24, -514, -5568, -1529, -112, 419, -1136, + -672, -1847, -1136, 90, 453, 4810, 13012, -2355, + -2477, 1393, 451, 3390, 12, -2228, 1840, -2543, + -2404, -2969, 186, -444, 204, -265, -11467, 2204, + 1821, 3591, 67, 8821, 4015, -183, -5902, -1468, + 11394, 3062, -128, -476, 2495, -2888, 13482, 686, + -1320, 371, -884, 1829, -1810, 337, -1124, -1442, + 432, 1950, -1203, 663, -10445, 2310, 766, 137, + 4418, 2821, 135, 116, -12164, -3592, 686, 2310, + 1229, 1930, -1756, -1309, 1439, -3741, -305, 1547, + -9940, 3198, 1333, 2403, -2847, -3892, -259, -1766, + 881, 14310, -1711, -840, 2259, 3027, -1527, 1156, + 2904, -75, -728, 1536, -127, 152, -3240, -726, +-11914, 1037, -851, -1893, -748, -3294, -1114, 6072, + 103, -1539, 4573, -1637, 5242, 2705, -9890, 254, + -1565, -407, 1818, -23004, 1110, 119, 256, -707, + -451, -679, 374, -935, -669, 403, -10, -594, + -525, 1403, -1016, -553, 595, -169, 2523, -82, + 947, 11572, -1166, 11668, -4962, 842, -860, 89, + -3308, -640, 558, -851, 622, -1002, -4933, 2762, + 1991, -121, 1401, -111, -49, 868, 135, -1392, + -279, -560, 412, -241, 1414, -802, -1256, -298, + 447, 17738, -320, -1150, 1650, -398, 5626, 6076, + -8919, 455, 12716, -2094, 157, 1361, -1515, 1494, + -6210, -553, -1785, -424, -3049, -4066, -1188, -732, + 1992, -1926, 1495, 1085, -22434, 1187, 391, -1512, + 747, -313, -502, 1331, 456, -323, 246, -581, + 56, 1448, 2071, 535, 782, 520, -136, -290, +-12350, -11858, -456, 2340, -310, 22, 2210, -2531, + -392, -898, 3919, 1354, -332, -4255, 169, 425, + -476, 2577, -1172, 1984, 266, 514, -516, 2481, + 81, 2103, -710, 273, 1405, -14811, 5858, 3621, + -982, 345, 2044, 158, -2050, -602, 954, 342, + 239, 157, -317, -35, -260, 307, -31972, 228, + -77, 225, -154, 643, -883, -518, 32, 372, + 208, -22488, -458, 530, 104, 254, -775, -1264, + -571, 900, -263, -323, -296, 962, 520, 548, + -2196, 42, 1408, -211, -16117, 2052, 12656, -822, + 507, 321, -772, -786, -144, -3539, 892, -3430, + 19, -1831, 1161, 1836, 988, -1134, -704, -2994, + 692, 765, 457, 1624, 502, 13, 364, 337, + 32108, 1517, -225, 189, 141, 985, -572, 262, + -146, 31, 236, 269, -278, -1686, -13968, 1247, + -1009, 1046, 13467, 1276, -268, 307, -1383, 1544, + 136, 949, 70, 446, 1391, -2188, 745, -374, +-14231, -712, -15202, -533, -108, -2244, -1232, 450, + -895, 1086, -782, -1082, -718, -660, 796, -2095, + 2722, -468, -1717, 147, -23566, 377, -220, -1731, + -1416, 486, -241, 266, -802, -322, 1066, -544, + -167, 520, -1297, -100, 622, 670, -188, 711, + 32, 1155, 628, 350, -112, -154, -1048, -44, + 36, -454, 304, 32767, 356, 462, -1194, 549, + 138, 0, 1044, -119, 195, 1098, 521, 3294, + -3776, -224, 4297, -1256, -303, 2107, 300, -13283, + 2933, -3194, -1408, -4152, 4195, 287, -932, 1247, + 13453, 277, 418, -598, 87, 1132, -80, -405, +-13400, 656, -1310, -1447, -3974, 1719, 313, 500, + 1078, -114, 1449, -293, -120, -4754, 5583, 235, + -5140, -865, -484, 15572, 336, -1854, -154, -454, + -1475, -726, -3718, -4048, 1575, 480, 1094, -2209, + -3202, 420, -564, -48, 964, -2667, 2172, -1666, + 112, -730, 203, 3618, -15857, -4853, 48, -1084, + 1512, -937, 3353, -453, 223, 2267, 139, 190, + 1959, -720, 4389, 681, 10383, -112, 12390, -882, + 1695, 3539, -169, 3131, -122, 3627, 252, 185, + -523, 112, -219, 214, -182, -102, 118, 230, + -60, -801, -25, 42, -279, 262, -32358, 344, + -542, 382, -223, -404, 1201, -2646, -163, -803, + 3041, -1009, 3818, 756, 5834, 14249, -1828, 139, + -218, -658, -1314, -4980, -3322, -1461, -1598, -91, + 2464, -954, -5203, -791, 1339, -13598, 594, 702, + -388, -1115, -2377, -370, -3658, -3322, 1871, 2513, + 2910, 4095, -2195, 4291, 886, -567, 1182, -302, + -672, -21, -268, -29244, -199, -1024, -1284, 485, + 1432, -1086, 119, 1030, 418, -643, -1165, 1847, + -30, -844, -909, -416, -604, -609, -289, -391, + -238, -94, -391, -810, 413, 356, 954, -1935, + 30996, 441, 138, 1381, 1130, -2313, 558, -203, + -248, -951, 408, 1815, 256, -429, -892, -695, + 1138, 439, -760, -63, 6498, 570, 15252, -3397, + 170, 935, 338, 1, -528, 524, -541, -281, + -3, 499, -333, 685, 436, 32176, 389, -153, + 572, 256, 53, 16, -902, 724, 2849, 2503, + 80, 667, -1867, 742, 15205, -8715, -2588, -476, + -450, -733, -891, 1178, -1751, -1630, -114, 144, + -138, 10145, -188, -1608, -131, -247, -544, 9774, + -610, -2868, -3472, 345, -9294, 3724, 2634, -5124, + -392, 2551, -649, 782, -18, -160, -351, 12074, + 13865, -1294, 1262, -3135, -2861, 18, 753, 167, + 620, -2432, 1998, 740, 1902, 400, -206, 3518, + -3563, -632, 72, -1810, 1520, -827, -572, 1604, + -613, 3704, -736, 11100, 12702, -3189, -792, -3552, + 1621, 1841, 1236, 1215, -457, 9542, 9278, 2633, + -8801, 862, 1741, -4840, -2620, 616, 324, 2152, + 3632, 880, -472, 1927, -3456, -2105, -965, 3426, + -1893, 3095, -1152, -3542, 182, 998, -386, 1202, + 481, -1951, -510, -931, 1688, 151, -13664, -3894, + -973, -906, 1524, 9576, 2607, 12497, -819, -5214, + 5936, -634, -610, -4148, -421, -486, -1864, -306, + 2421, 724, -219, -1304, -2106, -504, 6762, 5266 +}, + +.cb1110l1 = { + -2972, -1201, -1388, -1762, 340, 21127, -999, 126, + 111, -1224, -1738, 311, -712, -450, -114, -648, + -752, -172, 67, 375, -967, -1032, -10763, -1885, + -2223, -3258, 480, -228, -143, -1299, 13128, -3062, + 1418, 6, -649, -1816, -288, 767, 345, 876, + -491, 948, 540, -167, 1969, -1883, -455, 20584, + -656, 114, 308, 279, 1105, -594, 1332, 255, + -356, -186, -540, 1898, -873, -477, 1404, 30475, + 370, -322, -337, -206, -440, -894, -54, -466, + -640, -408, -256, -560, -1503, 626, -573, -1684, + 419, 407, 2076, 5022, 3143, -1135, -12118, -12082, + -1462, -2060, -5432, -1092, 1575, 1958, -968, 122, + 958, -5312, 677, -1952, -12276, -1594, 1211, -1094, + 1992, -11032, -2993, -834, -1297, -1139, 312, -1546, + -4253, 1191, 21, 2771, 639, -2514, 6623, 746, + 1830, 2967, 1688, -14893, 7988, 4099, -97, 1165, + -2350, 65, -1308, 1834, -2084, 1683, 5118, -1633, + -10, -5282, 403, -1489, -264, 398, -2420, 12854, + -1498, -2642, -1486, 826, 699, -2213, -2296, 11849, + 478, -2202, -561, -250, 199, -2433, -948, -402, + 433, 403, 13031, -124, -180, 1499, -643, 527, + 11368, 5833, 938, 3202, -452, 2875, -1163, -117, + -2047, -1068, 211, 3122, -236, 13548, -702, 352, + -312, -1901, -2145, 2334, -12100, -76, -419, 362, + 3501, -220, -3086, 572, 1537, 3240, -1489, -1012, + 640, -513, 930, 390, 31019, 724, -78, -706, + 183, -157, -122, -847, -1156, 301, 508, -456, + 321, 317, 1300, -512, -1743, 10190, -294, -116, + 4183, 1374, 13360, -1339, 1832, 2547, -702, -2782, + -1464, 1176, -1287, 2256, 2169, 836, 2096, -248, + 1777, 11306, -211, 265, -3834, 336, 1936, -586, + 633, 1037, -1915, 12862, 930, -273, 2333, -3239, + 429, 374, 2518, -671, 570, -2208, 385, -284, +-15613, -1752, 1341, -531, -744, -1111, 290, -2302, + -1012, -2933, -366, -30, -4595, 1400, 560, 48, + 15739, -945, 411, 1876, 2441, -2144, -1222, 12448, + 54, -726, -2743, 2548, 2100, 1307, 408, -198, + -1802, -63, -1919, 933, -329, -528, -15918, 1704, + 3028, 217, 606, -2804, 2052, 9320, 592, 969, + 6836, 647, -671, 584, -1, 3564, -2575, 436, + -2195, 414, -201, 1099, -772, -220, -578, -467, + 125, -934, 271, -21476, 288, 215, 216, 476, + -560, 768, 1142, -169, -1112, -14096, -14436, 2769, + -1464, -61, 1373, -3539, -1067, 1175, -1549, -861, + -332, -1876, 3159, 340, 1711, -2453, 457, 2536, + 1114, -2278, 2464, -3253, -466, 12291, 12484, -2868, + -800, 1142, -4244, -178, 3781, 1542, -663, 1976, + 3105, 145, -100, -1774, -1039, 1627, 15540, 4194, + 5392, 741, 1816, -544, -9100, 4255, -1083, -1266, + 2580, -4200, 1934, 1721, 129, 2276, -2704, -1341, + -1310, -11926, -1478, 199, 755, 619, 4231, -478, + -1627, -1242, 1842, 13170, -2416, 778, 192, 273, + 782, 774, 2188, -838, 3139, -1532, -1639, -1073, + -596, 770, -353, -53, 82, -322, -20584, -344, + -443, 158, -144, -554, 50, 954, -145, -336, + -2050, 596, -950, -2690, 13908, -13783, 4792, 879, + 584, -2987, 967, 192, -585, -783, -1341, -3108, + -1622, 2478, -1362, -1470, -1556, -430, -110, -736, + -8097, 2073, 964, -417, 1669, -5425, -7846, 536, + 12883, -1690, 1143, -242, -438, -2274, 57, 302, + -574, 637, 2816, -1642, 2166, -172, 893, 421, + -614, -565, -338, -526, -1085, -939, -1138, -991, + 1919, 1720, -18845, -1950, -342, 1930, 321, 184, + -956, -374, -462, -216, -6, 26, 386, -50, + 603, -720, 634, -252, 261, -860, 218, 22846, + 11544, -459, -946, 452, -102, -1203, -1802, -1105, + -310, 787, -220, -1113, -2043, 650, 13767, -3638, + -296, -902, -413, 252, -816, -172, -505, -1335, + 890, 768, -523, 808, -331, 20000, -264, 1763, + 133, -1, -464, 949, -954, -147, 1780, -190, + 30, -7422, -4615, -1006, -470, -742, 500, 7509, + 1500, 1550, -3614, 810, 2595, 1506, -12926, 3588, + 402, -2547, 1505, 65, 4, 3382, -2201, -2441, + -1521, -5450, -3820, 282, 5212, 1186, -1056, -2334, + 988, 12987, 390, 4141, -2680, 1663, -8034, -1792, + -225, -674, -7147, 13254, 1631, 10163, -3332, -7, + -675, -735, 772, -2299, -326, 1641, -1174, -1911, + 82, 776, 891, -445, 18590, 238, 1417, -2372, + -9718, -2682, 600, -1401, 604, -1791, -22, 1546, + -1764, 525, -1355, 348, 3260, 1115, 204, 524, + 225, -12776, -679, -15595, -1188, 1078, 82, -859, + 28, 819, -1220, 563, 2309, 331, -1158, -2010, + -264, -383, 1732, -424, -2742, -775, -329, 132, + 391, 1261, 1033, -9812, -11829, 2433, 2690, 606, + -2724, 7216, -296, -1834, -1694, 456, -4732, -400, + -3192, 1428, -316, -13674, -2702, 2320, -6548, -2025, + 1222, 1749, 4005, 2924, -3539, -5104, -2333, -1438, + 2598, 62, -757, 760, 343, 154, -31947, -534, + 1296, 697, 88, 345, -577, -500, -174, -326, + -198, 272, 157, -815, -636, -1163, -867, -273, + 1054, 774, 1624, 989, 107, -1088, -673, 2143, +-22962, -566, 151, 72, -27, 1034, -444, 501, + 1905, -1455, 21, 289, -10670, -789, -2421, -2686, + -327, 804, -3009, 907, 960, 1379, -43, -552, + 2203, -1406, -911, -11094, -529, 4458, -4152, -70, + 3162, -12546, 326, 874, 1426, 3019, 2315, 104, +-12516, -1591, -2877, 772, 1982, 1160, -4491, 3417, + -1524, -2139, 130, 930, 9359, -18308, -376, 4090, + -468, 156, -216, 60, -643, -3440, 256, -835, + -2389, 1660, -542, -1628, 4270, 3574, -3136, 433, + 1069, 30024, 561, 268, 790, 294, 207, -1552, + -736, -97, -215, -98, 690, 686, -202, -736, + -453, 655, 511, -156, 1006, 361, 1424, -1254, + -361, -1253, -1419, -290, 78, 555, 565, -488, + -923, -18193, -630, -908, 188, 925, -1684, 241, + -319, -14478, 17007, -1415, 274, 592, 1344, 1784, + -731, 344, 992, 141, 290, 481, 628, 623, + -1166, -2092, 140, -1056, 13736, 754, 1980, -238, + 2132, -1372, -2216, -12057, -1662, 66, 1742, 2209, + -962, -1574, -3044, 173, -3066, 183, -4476, -1016, + 6160, 780, -1193, -3334, 179, -371, 244, 160, + -686, 669, 330, 426, 65, 159, -664, -186, + 479, -742, 54, 605, 32603, -941, 370, -91, + 856, 825, 1042, 374, 651, 313, 734, -240, + -49, -685, -1994, -604, -875, 44, -884, 886, + 13012, -1506, -4317, -1926, 3050, -1027, -482, -40, + 137, -2560, 1366, -11812, 2112, 2266, -2690, -1339, + -700, -243, 2322, -1042, 4635, -3210, 4281, 47, + 670, 9218, 1165, 814, -62, -2276, 12987, -714, + 2481, 1355, 896, 2840, -1664, 2048, -345, 2285, + 1754, -669, 2284, -288, -575, 944, -1528, 44, + 1071, -706, -543, -1347, 880, 257, 1364, 1444, +-17896, 99, 1539, 1813, -611, 355, -2290, 980, + -787, 132, 300, 2353, 204, -798, -296, -594, + 895, 842, 18755, 1129, 79, -189, 515, 882, + -286, 109, 305, 374, 1323, 861, -18, -78, + 294, -320, 674, 504, -159, -549, -95, -32403, + -90, 658, 1082, 1611, -137, -74, 1160, -794, + -55, 822, 2627, 1203, -3540, 9829, -7860, -9063, + -4015, -894, -2218, 729, -879, -1869, -2446, 4050, + -488, 13211, -290, -820, 371, 14196, 866, -891, + 218, -1838, 2162, 1144, -186, 512, 1416, 546, + 3298, -1253, 128, 1202, 557, -1967, 680, 545, + -139, -3008, 18453, -3322, -137, 163, 1377, 1116, + 2572, -1577, -1846, 651, -1319, 796, -862, 331, + 4383, 2453, -1894, 3264, 14137, 842, -3087, 3740, + -1100, -2400, -1364, 2406, 417, -2393, -868, -3158, + -9712, 3480, -1403, 1896, 201, 1285, -593, -11718, + 99, -539, -186, 45, -2266, -12228, -2658, 2802, + -1198, 1022, -3840, 1401, -1918, 1655, 1725, 96, + -205, -913, 1629, 568, -1285, 1264, -1160, 594, + 223, -336, -1436, -472, -19792, 553, 1494, -195, + 570, 282, -653, -54, -1115, 153, -484, 141, + -188, -278, -173, 464, 13, -634, -42, 390, + -464, -246, 622, 1229, -692, 29175, -574, 1150, + -135, 2685, 2452, 63, -962, -918, -1657, -1978, + -172, -677, -3414, 1345, -3964, 2875, -1412, -654, + -3000, 10739, 11348, -2232, 516, 8303, -189, 2564, + -150, -373, 903, -275, 2394, -1135, 508, 424, + -1704, -2222, -3789, 1938, 216, -12702, 2488, -1364, + -2175, 1114, -819, -2756, 1564, 952, 36, 609, + -933, -1568, 110, 143, -1575, -4236, 528, 15042, + -1920, 348, -2623, 5217, 1911, -1088, 259, -590, + 364, 2081, -3585, 662, 249, -119, -111, 778, + 2167, 11, 2500, 7182, 14452, 4388, 4121, 3623, + 1598, 532, -507, 877, 3830, 372, -2184, -2810, + 11748, -2095, -1079, -3070, -768, 2901, -3587, -2572, + 10008, 563, -4588, 1026, 1117, 1879, -12004, -416, + 317, 2032, 1800, 1058, -84, -296, -1748, 2588, +-11019, -1627, -3264, 2480, 96, 2146, -2672, 2418 +}, + +.cb1110s0 = { +-32746, 360, -2774, -672, -1808, -14, -1037, -1327, + 1409, -2215, 172, 1557, 945, 2031, -702, 1844, + -1106, 472, 2603, -978, 2782, -5691, 1473, -5668, + 7129, 6600, -2160, 108, -1844, 2062, -2395, -740, + 1690, -45, -725, 77, 7236, -12903, -3356, -764, + 1870, 720, -2201, 790, 9950, -3694, -5340, -4031, + 4115, 6863, 2352, 1484, 3606, -4855, 714, 4104, + 6240, 7261, -6855, 4919, -2847, 6701, 7469, -616, +-11442, -1935, 9157, -4072, 133, -5976, 2455, -9360, + -2898, -4353, -7721, -3098, -3505, 2568, -5432, -576, +-10072, 250, 2173, -4196, -4322, 2688, 5220, -6026, + -346, 11678, 2071, -7344, -2182, -530, -180, -2568, + 1524, -1617, -8825, -4845, 2794, -2813, -2669, -2423, + -2709, -8985, 2105, -4629, 708, 2040, -5680, -2470, + -7277, 6841, 6523, 4196, -6788, -1982, 3844, -5000, + 156, 1930, 1780, -3824, -286, 3908, 1703, 7304, + 1145, 144, 1180, 7145, 3175, -13823, 6580, -3066, + -6321, -9739, 4432, -1145, 2923, -2636, 3838, -7037, + -3913, 1262, -1398, 363, -141, -886, -5667, -212, + -2118, -2717, 2724, -18802, -2098, -155, -1399, 782, + 797, 766, 2613, 5374, -3767, -1711, 624, 693, + 2544, -6153, 7179, 6835, -762, 5061, 655, 2600, + 9208, -7030, 7047, 1654, -3404, 176, -5486, 1374, +-15378, -487, 7456, -1954, 2404, -2994, -1608, 2362, + -498, -7952, -6143, -3996, 1596, -3013, 1181, -1534, + -5265, 220, -2677, 1047, -4629, -15066, 3966, -446, +-11713, -5694, -393, -250, -1336, -7394, 1508, 6239, + 3788, 6273, 6215, 822, 2657, 8057, 8391, -658, + -2561, -11587, -2589, -6702, -9227, -1016, -2220, -9702, + 5988, 1859, -6100, -4594, 221, 2529, 2217, 8273, + 1804, -6128, -2859, -8259, -4707, -2494, 1913, -352, + -4561, -289, -1801, -994, -4445, -1001, 5422, 10868, + -7366, 1679, -5195, -6859, 2982, -406, 2400, 4520, + -3611, -1892, 4900, -3504, 771, 2774, -772, -1929, + -7354, 375, 628, 4522, 1069, -969, 8083, -155, + 3178, -1138, 1752, -17288, 4390, -2483, -2071, -1353, + -1155, -456, -2683, 6798, -1908, 1797, -6657, -2770, + 5610, -14518, 5922, -3964, -938, -853, 1416, -1077, + -4562, -160, 5820, -3031, 5091, 1987, -2746, -3779, + 238, -264, -3074, -11718, 9370, 9806, -6302, 3979, + -2938, 4034, 393, -1399, -4466, 2181, 756, 394, + 2264, -3664, 78, 470, -3228, 3942, -1714, 708, + 4988, 1938, -2722, 4555, -5054, -1026, 19312, 354, + 107, -5357, -4364, 597, -2566, -2812, -2278, -446, + 1384, -371, -2566, -388, -3964, -8989, 9136, 3389, + 8440, -5570, -1262, -5874, 2056, -5973, -185, 4540, + -4924, 154, -3653, -1113, -3048, 7099, -2734, 2940, + -6704, 1543, -8120, 10134, -9485, -6645, 4816, -442, + -32, -2430, 4932, -6129, -5050, 6120, -2147, -6910, + -1342, 1075, -2458, 50, -4747, -3080, 1886, 1490, + 18972, 48, 787, 2441, -405, 1668, -1399, 2202, + 2175, -3592, 1548, -2728, -4864, 504, 383, 376, + -1073, 2142, 504, -3114, 6378, -5516, 13462, 196, + 1840, 7087, 792, -3583, 302, 1012, -5504, 270, + 3354, -4486, -2312, -2522, -2872, -3899, -2261, 5211, + 1417, -3075, -151, -985, -772, -1630, 164, 659, + 1496, -349, -621, -32, -2982, -1720, -3475, -7370, + -1541, 1122, 20474, 1726, 4474, -3228, 7024, 3265, + 522, -2193, -2113, 5388, 1912, 5929, 11768, -1162, + 2600, 4048, 652, 3360, -3215, 376, 10028, 6054, + -3814, -1155, 93, 4512, -3581, -4037, 7484, -1481, + 2797, 2635, -12275, -2780, -6235, 5739, 2687, 376, + 5984, -2547, -8834, 4332, 2752, 1942, 1002, -3312, + 5251, -86, -7794, 918, -2413, 3131, -3316, 2095, + -4569, -15382, -5534, 1290, 5179, 2928, 3034, 2365, + 270, -7476, -3024, 6910, 1355, -6262, -2040, 10490, + 1432, 12284, 1125, -3160, 4518, 973, -2351, -1726, + 1967, 1488, 382, 3559, -3742, -2908, -944, -1662, + 682, 902, -4360, 5026, -4252, -1212, -3269, -6024, + -3788, 9128, -2638, -1625, 315, 3087, -3265, -10441, + -7207, -4078, -3266, -7543, -5223, 5460, 2496, -9258, + -227, 4048, 860, -520, 13616, -3458, 3837, 809, + -104, -4062, -4846, -136, -1631, 13977, -1136, 3380, + 1099, -4022, 1831, 3360, -9034, -52, -516, 10144, + 5074, 4866, 8282, -972, 2496, 2336, 8766, 2881, + 2417, -5588, 3064, 3934, -4202, 627, -986, 1750, + 958, -2348, 5006, -2597, -90, 133, 23271, 2431, + -3984, 1894, -2094, -1816, 5007, -3164, 2526, -1862, + 2651, 1809, 7173, 3410, 154, 14930, 3032, -5314, + 44, 8868, -543, -2158, 5341, 258, -8188, 3772, + 2804, 7544, 8339, -3560, -63, -735, 1300, -4308, + -1085, -4986, 1564, -6744, -2605, -310, 1275, 1166, + -640, 4814, 4373, 3103, -1242, 6049, -4786, 597, + 182, 2371, 6950, -2265, 389, -14669, -1942, -2733, + -485, -865, -597, -1376, 1626, -3956, -1244, 1532, + 3918, -3311, 1574, -88, -20573, -5471, -71, -1731, + 1436, 2428, 3982, -4576, -914, 5460, -4973, 1650, + -2364, -2486, 3212, 5424, -2501, 4595, -937, 728, + -5140, -9948, 1437, 10560, -5704, -264, -2752, 949, + 5229, -1445, 430, 827, 4103, -1999, -4625, -4171, + -8769, -8927, 7161, 4539, 6968, 5975, -4626, -2793, + 10080, -10386, -2479, 1724, 2992, 354, 3650, 3328, + 4490, -1931, 7348, 7283, -3304, 4446, -1698, -1224, + -3002, 4340, 1041, 607, -454, -4261, -18071, -1199, + -3902, 570, 5808, 5582, 6710, 235, -205, -4288, + 3472, -686, -103, -3658, -436, -9680, -190, 275, + -919, 2522, -2087, 9096, 5060, -6450, 10282, 3344, + -8167, -7688, 11881, 3101, -1280, -9942, -11741, 2213, + 712, 3976, -4218, -5285, 2797, 2996, 4006, 2053, + 2344, 6200, 141, 2616, -3981, 6970, -4194, -1621, +-13724, 7772, 2800, 2220, 445, -266, 4030, 444, + -228, 2642, 1617, -2511, 1699, 8740, 3438, -2063, + -2093, 1806, 950, -7112, -1513, -2886, -8789, 870, + 3456, -4126, -3330, 541, -10173, -1789, 3156, 4466, + -5965, 479, 5177, -2806, 2506, -1646, -3609, 1617, + -7373, -3146, -2389, 3601, 7850, 89, -3373, 4670, + -4180, -3186, 3056, -1691, 1314, 9234, -7799, 1323, + -4360, -9866, -1930, 8091, -13452, 8503, 1980, 11247, + 7688, -5953, -4165, -3192, 540, 1631, 131, 2250, + 5330, -146, -8724, -3148, 2834, 1148, -3886, 374, + -1836, -3898, 9649, 1119, 10221, 128, 8868, -7301, + 2601, 1252, 2340, -3789, 4682, 181, 4434, -1740, + 4368, 879, -620, 2046, 1842, 844, -925, -2506, + -3344, -8820, -722, -451, 521, 903, -1286, -3059, + -5308, -4759, -2706, -1429, 2762, 927, -1459, -7274, +-12028, 8838, 3987, 2406, 8626, -3128, 6505, -4322, + -197, -2464, 2738, -46, 161, 13919, 2252, 2059, + 981, 204, 1161, 4910, 683, -4311, 2081, -1932, + 1119, -6067, -5325, 8528, -4704, -5522, -6183, 5744, + -3407, -2021, 2688, -3230, 2490, -976, -500, -7834, + 2064, 3191, 4740, 3686, 1762, 2604, -2442, -5720, + -7550, 457, -3478, -8097, -6510, -9105, 8031, -4895, + 500, -2436, 1483, -4415, -2023, -3768, -2497, -1911, + 789, 566, -969, -4204, 6128, -5076, 2664, -4222, + 6755, 1774, 6881, 64, 1205, -9243, 4782, 4432, + 5193, -2258, -4787, -7433, 1755, -794, 1297, -7535, + 12773, 9124, 806, 2348, -8112, 7874, -4348, -1410, + -350, -2528, 576, 661, 272, 4598, 691, 1913, + -3349, -1881, -1854, -779, -821, 8444, 60, 2570, + -1813, -1354, -4512, -5471, 4728, 3289, 2617, -9326, + -6670, -859, -2713, -9839, 4676, -2657, 3106, -1393, + 10278, -3069, -2253, 1015, 2246, -2227, 16, -388, + 7962, 1493, -3122, -2707, 7982, -6106, -1462, -1665, + -1302, 2347, 3640, -15122, -2211, 417, 6819, 959, + -2876, -6868, 11060, -2329, -302, 1595, -4610, 9514, + 12677, -4614, -2899, -141, -4857, 1447, 6400, -2894, + 1696, -2888, 1889, 3489, 2775, -504, -6597, -5258, + -7256, -379, -1249, -136, 3118, -3537, 3295, -3458, + 2103, -399, 15281, -222, -1809, 172, 2257, 1947, + 707, 3562, -5691, 3575, -2210, 5750, 815, 4059, + -16, 1306, -13308, -1733, -1338, -3477, 5247, -1950, + -5148, -678, 8074, 1740, 290, 2033, 4639, -4240, + -536, -5214, -1366, 2491, 501, -59, -4480, 430, + -285, -5947, -755, -14559, 5696, 6960, 4462, 2317, + 6414, -13174, 4962, -899, 5924, 11100, 5303, -970, + -2528, -6239, 2253, 2236, 553, 458, -2229, 8016, + -7082, 2869, -4209, -4460, -6536, 3557, -1766, 7815, + -655, -6029, -5250, -1627, 2646, -3466, -3584, 901, + 10305, -895, -427, 949, -2776, 3436, 769, -4131, + 9019, -4898, -3562, -7978, -359, 1358, -1528, -3095, + 5840, -6214, 2591, -2086, 9480, 640, 2858, 216, + -3625, 5740, -7008, -1097, -2091, -143, 4832, 6210, + -1358, 3998, -714, 835, -4004, 3664, 1980, 1240, + 2902, 510, -1565, 427, -2052, -4208, -1505, 1187, + -1229, 3732, -932, -1014, 4784, 18474, -5111, 3047, + -54, -1547, -3892, 8612, 274, 1446, -3548, -7689, + -423, 1192, -4508, -10403, -8735, -446, 444, -6353, + 4008, -1462, -8906, -1161, -2395, 2442, 2204, -5472, +-17376, 2471, -689, 1394, -3657, -2119, -769, 2872, + 1393, -2701, -3536, 3650, -378, 859, -3338, 1412, + 3010, -3243, -335, -3619, -511, -1931, -7126, -5018, + -9332, -4440, 1906, -2265, 1386, 8072, -6576, -1300, + 5458, -4894, 630, -7146, 2263, 810, 2968, 1124, + -2219, 2292, -3914, -1836, -6683, 1511, -2755, 1396, + 2425, -23842, 2249, -53, -891, -1678, -1766, -1788, + 502, -4210, 211, 10376, -5507, 837, -6196, 2132, + -472, -10153, 7234, -1456, -148, 4886, 2427, 2371, + 1234, -962, 6298, 1016, 1735, -566, -878, -8071 +}, + +.cb1110s1 = { + 2525, 12164, 4861, 9505, -7371, -414, 3002, 576, + -347, -998, 2861, -804, 3034, 810, -788, -539, + -2092, 4970, 1828, -2869, -2802, 6649, 3673, -193, + -4034, 722, 1642, 3792, 8770, 10428, -3303, -3849, + -4520, -234, -4190, -1219, -1300, -4128, 8384, -1150, + 1578, -6174, -1072, -4871, -8180, -6698, 3806, -7386, + -2545, 1052, -550, -1148, -1308, -8834, -2654, 1982, + 8716, 6579, 1360, -2404, 1893, 2680, 3801, 11097, + 1455, 2453, -7585, -7503, -12710, -420, 2023, -656, + 1124, 2872, 9676, -4309, -202, 1458, -6526, -534, + -1535, 924, 3068, -1142, 5073, 1284, -5632, 869, + -1637, -2898, 4900, -10202, -10488, -1097, 1890, 11006, + -44, 1368, -1979, 6507, 316, 961, 8, -4085, + 2561, -2034, -1077, 2594, -465, -5134, -868, 54, + -6694, 9608, -3516, 7165, 11011, 9542, 4780, -2800, + -1130, -1714, -2684, -369, 4746, -2688, 4146, -7652, + 984, -3263, -276, -9134, -2848, -3983, 9994, 3608, + 3234, -596, 263, 3102, -178, -2264, 3820, -4293, + -5752, -3577, -3914, 1095, -1562, 22110, 4610, 69, + -2999, 254, 2178, -2901, -1203, -1292, 2642, -3254, + -1389, 2955, 1340, 542, 810, 1369, 3208, -795, + -3272, -2717, -1129, 8781, -6854, -3028, -616, 729, + 529, -6946, 1621, 9574, -14909, 5398, 854, -774, + -9978, -5417, -2516, -4683, 5715, -66, 3336, -5040, + 640, -7566, 3494, 7016, -2269, 1376, -13994, 6448, + -3948, -1697, -3988, -6559, 2376, 4231, -3131, 2045, + -2417, -5919, -7016, -1695, 9046, -7966, 5187, -2553, + 1402, -2351, -220, 5931, -1823, -2270, 584, -3784, + 2924, 6166, -3035, 2370, 4923, -1080, 682, -7899, +-10827, -1824, -908, 1568, -3565, 4033, -4266, -1948, + 923, 5488, -203, -2396, -907, 2783, -3278, 1415, + 7710, -190, -5208, -2279, 1266, -1132, -3392, 10251, + -1064, 11283, 2162, 2213, -5088, 4479, -4658, -1803, + 1534, -4233, -4073, 6938, 3966, -4878, -332, 5961, + 9217, 488, 6520, 4430, 7988, 9383, -2586, 1206, + -6983, -873, 1251, 1849, 5945, -2144, -2032, -1852, + 416, 3720, 2419, 8462, 3173, 11524, -2894, -5517, + -211, 17830, 3170, 1098, -721, -2066, -1956, -3097, + -1061, 2815, 447, 701, 449, -485, 2609, 1239, + 2257, -1760, 3091, 7538, 3710, -2689, -3092, 6903, + -2457, 3271, 6355, -1486, -828, 1994, -3575, 3949, + 3185, 2606, -4912, -16039, -8833, 1831, 2580, 1993, + -1117, -3408, -7590, -7278, -141, 2696, 805, 1896, + 308, 378, 9308, 2894, -4324, 1042, 837, 4716, + -4702, 2493, -5173, 8616, -468, -14829, 3759, 3251, + -4237, -1340, 5224, 2099, -764, -8263, -1699, 76, + -1464, 2115, -582, 3286, -3653, 1017, 1696, -1414, + -668, -9748, -5730, 2413, -1270, -6070, 17002, 2164, + -5440, 1801, -2123, 800, 2135, 4801, -887, -2141, + -647, -4846, -463, -577, -1846, -555, -1929, 2046, + 8272, -8399, 3886, -5950, -4202, -12600, -2805, 477, + 65, 6140, 1089, -4737, 8967, 1952, -1968, -3660, + 6641, 850, -3304, -1775, 4010, 10819, 14365, -696, + -1331, -1724, -237, -3611, 244, 3005, 4349, -182, + -4124, 2466, 2746, -61, 3391, -1392, 3788, 1582, + 3723, 7140, -2207, -3678, -2675, -252, -7476, 9426, + -6196, 3226, 3554, -6326, -4284, 6346, -4432, 5199, + -2633, -2499, 1200, -1140, -3910, 6624, 16732, 5946, + -766, 2630, -1200, 1988, 5510, -1199, 4126, 1287, + 454, -1795, 2664, 5001, 1058, 500, -437, 2992, + -2012, -160, 796, -4846, -6572, -10088, 603, 483, + -4510, -12799, 3502, -1784, 3510, -3956, 6038, 9044, + -6029, 7170, -1608, 120, 914, -200, 3939, -6274, + 3020, 6235, -2754, 5368, -1693, -6028, 386, -2006, + 1898, -11704, -9973, -525, -2624, 1799, 4140, 3248, + -57, -3731, 3764, 5582, -3830, -2484, -2066, 1517, + -900, -8250, -8191, 2676, 1147, 6752, 6908, 1196, + -2634, 3408, 2980, -1042, 3971, 632, -4946, -5690, + 133, 2445, -446, -1294, -777, 3356, -5628, -6020, + -8042, 5069, -1421, -2701, -15117, 3074, -912, -2574, + 2643, 5252, -2118, 3849, -3793, -850, 4170, 6240, + -697, 6976, -3752, 1155, 7769, -8912, -7728, 4224, + -2362, -3760, 3688, 2402, -3411, -3165, -2550, -8, + -209, -334, -837, 5688, 3425, -4564, 9999, -4780, + 3093, 4346, -5556, 1636, 1755, -14696, 1810, 6547, + -60, 4054, 10539, 6118, -4414, 1760, 3581, -841, + 4471, -23, 180, 259, -4439, -13230, -1326, 1913, + -621, -1641, -2882, -4934, 516, -3886, -4468, -110, + -4526, -5157, 7550, -4449, 813, -4364, 1768, -8829, + 2003, -1372, 1873, -209, 1539, 1076, -12408, -1464, + -1878, 1563, 2020, 704, 1425, -275, -3718, 4618, + -1120, -5057, -3590, 4022, -1977, 620, 143, -2507, + 3697, -3263, 616, -3002, -3347, 21051, -4398, 364, + -1924, 284, -2724, -2297, 4916, 2702, 4866, 4293, + -2781, 1094, -1525, -562, 5487, -2098, 4658, 1362, + -597, -3426, 3173, -5174, 3922, -3844, 1482, 4711, + 5853, 1490, 5499, -17537, 956, 544, 268, -4782, + -504, -4003, -911, 599, 1746, -7322, 1907, 1990, + 16985, 3171, -2645, 1040, -7239, 5618, 304, 3606, + -3377, 3630, 7319, 108, -496, 1026, 3062, -392, + 2366, 1948, -530, 806, 2700, -2676, -2717, 5238, +-16008, -823, -264, -1560, -1014, -760, -3684, -330, + 5644, -1668, -10239, -2583, 7411, -593, 2193, -1479, + -2892, 3834, -3625, -12234, -1103, 1868, -5121, 3879, + 2748, 1936, 2026, 4572, -6037, 3310, -8678, 11724, + 5290, -2316, 4131, 834, -3915, 869, -1734, -5752, + 1255, 9534, -3625, -115, -5912, -125, 2298, -1494, + 5910, -496, -2719, 1320, 3175, -3012, -3906, 4602, + -4760, -5918, -2568, 6632, -8802, -5876, 6358, 2349, + 207, 5191, 8369, -5932, 2710, 7950, 3673, -2592, + 1311, 8384, -4360, 8614, -5662, 1180, 2147, 1044, + 1591, -5555, -1597, 4418, 38, -1579, 4675, -1725, + -1693, -6470, 3066, -7601, -12822, 524, -2986, -3406, + 8860, -1266, -930, 4316, 1171, -2908, 199, -1785, + -2851, -3588, 3072, -3585, -2668, -1123, 1508, 460, + 6780, -19480, 2854, -1574, 1004, 5074, 1907, -1988, + 1177, 74, -1436, 2224, 1232, -3008, -3454, -862, + 604, -653, 2778, 2349, 3242, 8426, -430, 3684, + 4814, -1886, 5118, 1487, 442, -2322, -900, -2854, + -234, -10350, -7922, -745, -1490, -5638, -6014, -4079, + -2979, -351, 9493, -2274, -11362, -8166, -7364, 8261, + 1554, -1722, 4651, -831, 2276, 1502, 2600, 1266, + 4456, -4145, -3837, -3584, 4242, 4058, -2395, -6971, + 4486, 3233, 6226, 1306, -11506, -6223, -5132, 1537, + -4407, 1510, 5732, 2808, 5817, -4972, -2900, 897, + -2441, -1819, 5651, -6988, -10063, -2288, -5820, -1250, + 925, 3120, 6125, -9901, -137, 3684, -6601, 1077, + 3272, 21, 3341, -838, -3643, -1727, -4417, 660, + -6551, -184, -8125, -1780, 5232, 6077, -7968, 6423, + 3823, 3026, 4555, 464, 3318, -5504, 837, -3571, + 3853, -2277, -1864, -742, -5380, 6096, 6856, 1076, + 877, -642, 1926, -4712, -14482, -3323, -2672, 7485, + -2116, -3932, 2233, -3270, 326, 2221, 132, -1893, + -748, 453, 3597, -2308, -4371, 5632, 3609, -1033, + -444, -2591, 17359, -3120, -2604, 3157, -370, 9242, + -1606, 2675, -853, 1475, -416, -3280, -1159, 191, + -3670, 282, 4282, -957, -2978, 3564, 91, -20520, + -3046, 1248, 1277, 3368, 1118, 311, -598, 1406, + -2377, -1444, 1417, -3626, 167, -6440, 3341, 629, + -2523, 4398, -1187, 4322, -383, 1934, -3298, -8530, + 2195, 5220, 510, -1256, -6932, -1061, 5141, -16242, + -1390, -546, -3760, -2029, -929, -6044, -3503, 312, + 8478, 701, 8865, 4715, 1987, 1342, 1400, -71, + -5229, -1547, -8827, 2349, 12836, -1479, 4621, 6003, + -6749, -3184, -5667, -2930, -1074, 3204, 330, 4692, + 2872, -10808, 75, -1260, 18003, 4100, -1462, 1391, + -1667, -2039, -687, -4806, 5913, 2682, 7730, 7034, + 2703, 1666, 120, 1601, 2123, 1402, -4702, -11229, + 7875, -5591, 4634, -2274, 3015, -597, -7520, -1095, + -4814, -173, 5562, 1533, 2807, 8466, 5195, 7806, + 2585, -2877, 6938, -3942, 402, -3825, 4162, 9149, + -6423, 2447, 7041, 2932, -9813, 2124, -58, -3, +-12856, -7973, 1484, 907, 180, 8042, -2124, 4356, + -4117, 1126, -9706, -2101, 3957, -1877, 1139, 7148, + 3707, -1341, 4509, -1220, 4570, -1650, -6504, 7036, +-10268, -328, 4678, -12205, 5062, 6089, -496, -7740, + 2207, 4489, -205, 1386, -2695, -1442, 4730, 892, + 12061, 3818, -3305, 4431, 9300, 3470, 4608, 4315, + 892, 866, -1714, 1529, 2569, -11398, -3068, -282, + 1626, 587, -1568, -1630, -220, -2033, 7141, -2732, + -3541, 3404, 15514, 1883, -2697, -926, 5972, 6485, + -6794, 2111, 2490, 1201, 5467, -2352, 3264, -97, + 2400, -728, -3364, 3417, 1481, 2862, 462, 2855, + -5233, 5740, 7208, -10508, -3254, 1450, -1270, -293, + 3400, -6978, 10035, -1213, 4308, 2641, 8579, 8518, + -2919, -351, -459, -2069, -617, 638, -1347, 107, + 6009, 2035, -280, 2009, 3280, -1236, -14960, -5177, + -2440, 965, -2646, -2095, 5274, 1825, 3705, 3831, + -446, -4018, 7178, -2415, 4344, 1850, -509, -500, + 1056, -4374, 5709, 1336, 3352, 7915, -2302, 12209, +-14362, 6429, 1423, 2912, 6474, -1599, 1116, 2280, + -1738, 3108, -5792, -3554, 623, -1110, -6114, 4488, + 8941, -3176, 13670, -3320, -327, -2657, -7349, 3782, + -1481, 5737, -200, 2968, -9474, 5752, 5056, 4688, + -5352, -432, -906, -3832, -8519, -7, 3667, 3583, + 6250, 8724, 10737, 9371, 950, -1630, -10740, 5788, + 4111, -2910, 437, -2482, 1910, 185, -2168, -3155, + -3515, -1754, 4978, 4298, -6921, 476, -2778, 546 +}, + +.cb1110m0 = { + 3666, -1078, -175, 1370, 2491, -10050, -685, -7617, + 4002, 11104, 903, 5948, 2821, 3050, -2465, 1151, + -848, -2139, 12321, -1408, -1469, 2046, -2693, 2479, + -3498, 3077, -3822, 1841, -2404, -11172, -407, -3062, + -1725, -5475, 597, 1924, -197, 434, -1648, 2678, + -2462, 1148, 599, 1284, -13171, -949, -6508, 754, + 7466, 5924, 1411, -536, 10825, 588, 297, -310, + -593, -896, 784, -242, 716, 501, -52, 4043, + -755, -690, 2630, 17762, -2159, 2126, 954, -1316, + 11129, 1570, 387, -2639, 13953, -311, 5231, -2297, + -3612, -678, -1117, 690, -279, 2403, -1541, 493, + -1692, -2048, -771, -933, 423, 700, 840, 739, + 1956, -944, 612, -2678, 101, 245, -786, 850, + 269, 1355, 21773, 463, -2589, 596, -519, 788, + -43, 1220, 10674, 4847, 1192, 335, 875, -106, + 10644, 2600, 5391, -262, 2296, -5928, -1072, -122, + 2504, 1313, 1117, -981, 350, 375, -810, 8, + 1462, -2020, -2368, 8, 22663, 1537, 87, 908, + 832, -4884, 312, 620, 1042, -4444, 660, 1582, + -2710, -2954, 10012, -9580, 8102, 5696, -1371, -3035, + -3347, 402, 218, 1096, -1924, 88, -2270, 4175, + -1083, -497, -2437, -3332, -824, 212, -2362, 4600, + -7800, -11501, 7795, 236, -1336, -12920, 705, 4532, + -1488, 11746, -3213, -2650, 2524, -2638, -128, -328, + 3402, 453, -242, -2500, 2224, 708, 450, -3014, + -132, 1251, -131, -831, -710, -21985, 222, -2132, + -3261, 490, -3020, -860, 2550, 892, -623, -3666, + -664, -131, 2018, 2817, -12005, 496, -610, -7238, + -3909, -2867, 6872, 1903, 848, 6644, 3812, -5686, + -4055, -377, -2096, -10247, -1068, 1486, 415, -253, + -2186, 1050, 771, -6856, 1044, 7466, 2953, -7514, + 1601, 7015, -1778, -1622, -3364, -1755, 2835, 176, + 2700, 991, 2560, -554, 4867, 1571, -5610, 2610, + 12438, -3751, -9964, -2753, 4856, -2595, -5423, 10025, + 812, 687, 2715, 4013, 3086, -12039, 328, -3992, + 4044, -3920, -111, -553, -1720, 2454, 1706, -1365, + 804, -32329, -471, 897, -4670, 780, -3680, -1409, + -2630, 20, 184, -157, -290, 2794, -546, -160, + 1564, 1146, 628, -4787, -239, 11233, -492, 1955, + 608, 9273, -3220, 3830, 390, -5982, -3342, -3384, + 2356, 1820, -3473, 979, -40, -20190, 47, -200, + 5106, -381, 1824, -197, 2280, 2434, -2633, -1409, + -1109, -1072, 857, 1554, 7459, 6, 12130, -1078, + 1038, -300, -13748, 3201, -762, 2670, -1051, -445, + 914, -172, -558, 2634, -1158, 3129, -74, -3415, + 1086, -8892, 118, -647, 285, 186, 3022, -5077, + 1342, 3453, -7991, -65, 4690, 944, 3717, -1909, + -9783, -367, -1699, -772, -32768, 1286, -408, 340, + -340, 430, 1274, 596, -109, -727, 276, -946, + 139, 1804, -1050, -3562, -1392, -1179, 257, 1639, + 25708, 2278, 2415, 2174, 153, 126, -60, 592, + 994, -334, -268, 1826, -306, -2241, 2774, -3188, + 758, -450, 8023, 542, 6819, -1712, 14195, -2198, + 281, -12, -590, -1153, 4568, -3676, 1973, -5221, + -1839, -603, 3324, 2492, -3070, -846, 123, -1184, + 667, -10886, -65, -2615, 971, 10219, -1245, 7378, + -2122, -2306, 571, -2298, 1958, -4356, -9210, 4321, + 2805, 1888, 11129, 1282, -5819, -2528, -873, 1123, + -5968, -2644, -5515, -2151, -944, -7712, -2007, -2260, + -1920, 2100, -325, 153, 1050, 10, 1462, 650, +-12559, 3530, 754, 4493, 1528, -6991, -4842, 1483, + -2408, 2785, -1651, -830, 1433, -2464, 18899, -1891, + -3137, 996, 2485, 3056, -1061, -4015, -2282, 1356, + -2572, -490, 1209, 1137, 4, -636, -1282, 1001, + -1190, -172, -14049, -4256, -1972, 2225, -4738, -1054, + 5254, 8113, 4294, 36, 11765, -3993, -1084, 3864, + -3016, -10356, 353, 2963, -1228, 536, 609, -343, + 1246, 3617, -3667, 4794, -20360, 473, 725, -1246, + -1649, 1900, -2589, -2869, -2550, -886, -1164, -1876, + 307, 3784, -4782, -476, -700, 2118, -1860, 1533, + -5013, 2356, 3305, 3338, -14312, -1278, -322, 1950, + -954, -1990, 1438, 3358, 7479, 3046, -6677, -3078, + 1717, 3113, -12484, -1302, -221, -510, 10423, -3497, + 4170, -3606, 6983, -2902, 458, 667, 566, 2415, + -403, -2898, -44, -1832, -110, 1799, 1172, 7, + -1534, 90, 686, -26902, 1601, -822, 658, 182, + -151, 345, 1488, 1416, -272, 1560, 9774, 2084, + 16, -14344, 1428, 514, 2658, -1312, 2095, 454, + -1783, -2056, 4529, 1154, -2239, 956, 668, -1396, + -2898, 405, -12659, -12556, -650, -587, 3461, -2470, + 0, -3156, 3186, -4104, 1729, 1438, -1842, -422, + 4476, 1945, -932, -1439, -702, -1398, 3349, 1876, + -999, -2086, -17879, -432, 4036, -2299, 1133, 88, + -2221, -2730, -938, -998, -132, -426, 2084, 2060, + -1134, -313, 402, -538, -2593, 2022, 725, 1566, + -2070, 21622, 1767, -424, -32672, 205, -1239, -3253, + 198, -1257, 2342, -1918, 1505, 452, 1348, -604, + 978, 1079, -4, 2476, -1247, -146, -861, -1928, +-12222, -13042, -1384, -1971, -1428, 1224, -639, -83, + 1034, 3488, -2310, -565, 74, -335, 2774, 602, + 872, -2132, -147, 2160, 244, 162, 12600, 628, +-10194, -1296, 1068, -1824, -4945, 3194, 2066, -895, + -784, 2347, -1982, 73, 1030, 12589, -62, -2272, + 3827, -1776, 2546, -1417, 3310, 4726, -3078, -548, + -8522, 1632, -6667, 1008, 1128, 805, 954, 616, + 499, -31526, -1327, 790, -190, 1058, -1157, 1432, + -16, 411, -3180, 827, 327, 914, 1716, 1442, + 1052, -1635, -1805, -4145, -13678, 3597, -2273, -5920, + 3592, 1136, -211, 717, 3901, -5132, 3036, -601, + 12976, 1633, 10316, -1674, -468, 905, 2331, 841, + -247, -6053, -593, -3281, 4291, 5159, -1053, -1814, + 2613, 2221, 1146, 871, -421, -542, 923, -3567, + -1138, 10051, 10860, -6121, -661, -5677, -890, -266, + 2100, 6223, -70, -2658, -78, 3424, 714, 2138, + -1355, -981, 1990, 772, 938, 1311, -1963, 924, +-22516, 260, -341, 1251, -1578, 23, 1375, 1068, + 2688, -3965, 713, -5342, -257, 37, -6034, -276, + 228, -1240, -7171, -3402, -14677, 1708, -317, -2880, + 874, 1466, 524, 2091, 565, -4220, -265, 52, + -3373, -220, -3175, 2646, 448, -1628, -1986, 2200, + 3722, -15752, 7120, -2036, -2170, -627, -1079, -4060, + 2257, -925, -3418, -13488, -1308, 3476, -783, -3924, + -820, -860, 2418, 2982, -8753, 9001, 294, -11915, + -969, 3329, -761, 1459, -5308, 1811, 379, 306, + 632, -2732, 2512, 1188, -3470, -2167, -572, -2274, + -1657, 24074, -159, -138, -1826, -2527, -3117, -906, + -1770, -1182, 1240, -3064, 2313, -790, 336, -3843, +-13384, -423, 13066, -14, -1908, -32, 2607, 487, + -2426, 195, 135, 2742, 1540, -1034, 856, -2288, + -287, -774, 497, 1760, 191, 178, 298, 38, +-30898, 801, -1456, 2311, 1272, -1845, 334, -933, + 183, -1614, 739, 1881, -13548, -13589, 1496, -2075, + -1281, -1510, 108, 3683, -1120, 752, -980, -277, + -1289, 2016, -290, 1838, -321, -139, -881, -12391, +-14713, 1906, 990, -3202, 2320, 749, 1872, -2545, + -1457, -1727, 734, -327, -316, 1062, -3149, -2959, + 2210, 912, 952, 1926, -8918, 1098, 594, -1439, + -1402, 11097, 3482, -472, 219, -3845, -662, 9715, + 3928, 1254, -2009, 12375, -1724, 13938, 1892, -1390, + 686, 2174, 1010, -1297, -199, 1855, 463, 2601, + 4408, 1978, 1679, -1614, -3, -11965, 16220, 828, + 1497, -747, -484, 519, -1804, -3814, 3287, 2104, + 1149, 478, -3918, 1504, 2376, -316, -520, -1449, + -3918, 664, 2772, -16434, 334, -540, -778, -2812, + -6026, -4392, -2446, 3479, 3742, -624, 3895, 1145, + -344, 333, 11898, -2725, 12873, -1145, -1807, -279, + -452, -1581, 548, -5180, -2012, 3411, 1188, -1407, + -4016, -468, 1904, -1724, -11390, -30, 14402, 1610, + -2138, 1249, 346, 6097, -1433, -655, -174, 3652, + 4010, 954, -1458, -354, -1872, -2689, 880, -846, + -1304, -1725, 1750, -1186, 1520, 499, -583, 18201, + -1083, -3323, 3072, -5440, -182, 1065, -1112, -984, + 2501, -529, 613, 2054, 460, -5245, 2827, -1445, + -2403, -12898, 1504, -8428, -1035, -4620, 1704, -2586 +}, + +.cb1110m1 = { + 1442, 12425, -2072, 741, -3624, 12979, 2031, -364, + 3750, -5082, -1968, 146, 670, -3988, -831, 3962, + 397, 6213, -1178, 816, -88, -432, -9620, 11572, + 194, 289, -1958, -2115, -871, 5372, -3145, 3612, + 1644, 826, 525, -2545, -514, -537, 2485, -1014, + 1276, 541, -936, -302, -1172, 183, 827, 23939, + 1120, -346, -313, 2759, 3934, -3082, -2260, -906, + -967, 1496, 102, -2782, 323, -1109, -37, 2554, + -2920, 998, -930, -1952, -1138, 1842, -1593, 17345, + -1214, -1065, 2182, -1169, 11745, 278, 8310, 1491, + -564, 1169, 8406, 1359, -1249, -2094, -1365, 4069, + 1828, 897, 1258, 1083, 4319, 610, 766, 2273, + 4057, 621, 338, 1317, -20941, 548, -2012, 563, + 1102, -27, 3007, 1129, -1068, 1282, -2939, 2983, + 1958, 1800, 1912, 1728, -606, 1804, -4768, 5068, + -1365, 4543, 399, -14152, -6206, 6187, -2205, 1174, + -1892, -3284, -206, 2872, -2622, -43, 11268, -104, + 292, -1836, -6276, 725, 2066, -604, 11382, -448, + 742, 2854, -910, -838, -1802, 3678, -397, -530, +-10647, 2356, 12161, 1506, 2649, -3335, 3128, 2169, + 5942, 2152, 14124, 428, 187, 248, 1592, -44, + -59, -2934, 1883, -923, 2673, -847, 150, -2142, + -7620, 11078, -595, 6490, -13673, 948, 219, -1314, + -3080, 1339, 11020, 1362, 247, -1863, 1069, -3786, + 1706, 1064, 320, 4535, 136, 3795, 1465, -1356, + -449, 13, -421, 1769, 20470, 2181, -371, 2444, + -744, 2263, -155, -688, -236, -4481, 1551, 2812, + 2476, -1436, -470, -272, 2276, 594, -858, -978, + 1122, 2468, -9350, -353, -1020, 494, 13167, 1770, + 1734, -70, -4630, 12358, -818, -979, -3931, 1000, + -4343, 2570, 5567, 3322, 2930, -236, -4796, 6987, + -1658, 4291, 1118, 1710, -2050, -13566, -2, -23, + 2104, 1101, -316, 1906, 1643, 340, 5940, 3180, + -837, 1978, -10514, 1466, -6936, 3600, 1205, 957, + -211, -8272, 1611, 5330, -5217, -2264, -5681, -3085, + -9201, -62, 3366, 1370, -9494, 244, -5516, 1210, + 2930, -432, -1265, 376, -1910, -1016, -845, 3228, + 1094, -3168, 634, -265, -3426, 4367, -4004, -277, +-15081, 3998, 9671, 3418, 691, 9124, -2723, 1939, + 2311, 581, -4980, 3381, -1502, 878, -1037, 1496, + 3002, 904, -5388, -3300, 263, 1277, -694, 766, + 1781, 1134, 250, -32602, -285, 210, 2550, -383, + 908, 302, 292, -352, 2615, -97, -1863, 1908, + 2685, -502, -3767, 416, 990, -602, -1533, 43, + 1288, 1326, 16638, 433, -1204, 1850, -1609, 1407, + -7196, 2319, 5770, 1584, 1150, -634, -1686, 1359, + -1396, 438, 246, 186, -11262, -1194, -3790, -3267, + 2692, 755, 142, 16276, -2338, -1341, 10433, 38, + -1510, -2520, -3205, 913, 3783, -1622, -4744, 1891, + 2502, -8, -2962, 2091, 14986, 1270, 2931, 682, + 1073, -10215, 1606, -1010, -822, 1168, -1403, 254, + 1156, 3206, 3958, 1739, -402, -654, -4862, -1869, + 2643, -2858, 658, -910, -2548, 5428, -1992, -208, + 1950, -15526, 520, -4212, 3182, 4160, 1524, -2916, + 586, 3213, 675, 185, -629, 669, -838, 502, + -4065, 353, -4072, -1832, -2108, 5034, 2484, 15386, + -2102, 4988, 70, 1011, 2568, 1360, -2821, 3352, +-11074, -2686, 611, 460, 1811, 3093, 34, -9140, + -1163, 26, -875, 2510, 1134, -1322, 2274, -960, + -823, -510, 1092, 1490, 1466, -1978, 32767, -2379, + -1019, -633, -1306, -242, 2050, 1336, -2668, -2195, + -442, 8, 2292, 4344, -2439, -1472, 1035, -14443, + -1820, 6309, -2096, 45, 3617, 1561, 1252, 2828, + 10682, -894, 10841, 2373, -101, 913, 2160, 2653, + 2960, -4433, 1193, 4892, -2123, -7911, 991, -2643, + -1364, -3641, -9736, 444, 869, 2990, 926, -1220, + -1676, 7492, 4376, -3742, -6964, 4531, 7522, -2686, + 164, 1070, -7305, 1863, 542, 146, -800, 18492, + -4849, -3876, 2162, 5111, 2606, 4243, -3035, -2990, + -1710, -426, -5315, -2332, -1020, -268, -1242, -39, + -1684, -32768, 1288, -726, -1768, 304, 702, -2969, + -700, 586, 1541, -1099, -348, -2816, -2181, -1260, + -1658, 2278, 323, -1548, 2513, 11816, -2416, -5837, + -118, 6770, 3360, -4097, -264, -1270, 1064, -9862, + -3669, -56, 603, -1475, 1464, -9553, 6, -3091, + 5331, -396, 892, -2774, -4674, 3667, -9982, -5160, + -1146, -4026, -2032, 2936, 1805, -1026, 1065, -420, + -572, 1756, -479, -583, 30760, -732, 750, 270, + -1541, 28, -1114, -96, -264, 1167, 548, 570, + 84, -1981, -2110, -1136, 358, -6337, -257, -14658, + 1144, -9032, 322, -3730, -3086, -1351, -3320, -4116, + -396, -129, -3202, 1403, -347, 2400, -371, 532, + 1555, -2760, 1078, 804, -1314, 21956, 2231, -2808, + -1947, 838, 12428, -14514, -384, -1554, -675, -885, + 1358, 1612, -3266, -98, 1876, -447, 2241, 3375, + -1765, 2792, 674, -1513, -1132, -3696, 11368, -1916, + -2778, -466, -377, 2090, 3897, 5422, -2550, 2360, + 3279, 8657, 990, -2128, 2592, -970, -2397, -269, + 22742, 694, 310, -2433, 920, -690, 1478, 1370, + -450, 445, -1379, -1244, 2374, 1400, -1040, -5692, + -1700, -1630, -4068, -1193, -719, -2953, -3562, 264, +-13247, -4629, 5, 3245, -5724, 2449, 3190, -5375, + -3560, -3834, 1271, 1568, -762, 2938, 782, -1390, + 243, -466, 1376, 974, -1646, -1784, 249, -514, +-13543, 1904, 10778, -772, -155, 7838, -30, 3634, + -473, -9100, -112, -3990, -840, 1495, -2346, -326, + 3655, 1292, -292, -10972, 3431, -262, 171, -9775, + -985, 578, 312, -2553, 3375, -8316, 1410, -1326, + 2459, -3116, 1079, 7194, 2720, 1998, 2742, 4672, + -1589, -8932, -124, -652, -72, 2409, -926, -3661, + -3762, 14832, -1350, -2234, 1258, -1604, 169, 103, + 1263, -400, -765, 144, 824, 855, -13344, -1629, + 1977, 2995, -1964, -650, -219, -11607, -6062, -792, + -1243, -1438, 1757, 1436, -3739, 812, -856, -9603, + -2428, -11372, 3273, -2318, -8263, 1551, -2054, -3646, + 3149, 2255, 594, -412, -3030, 1558, 694, -1211, + 618, 3256, 6526, -1572, -9054, 6655, -3208, 3616, + 2162, 3137, 4254, 4610, -10040, 1188, 335, -615, + 640, -1990, -314, 6014, -2392, -2174, 343, 6730, + -1320, 183, -97, -3566, 2988, -13343, -1573, -9070, + 428, 2839, 6728, -1109, -1113, -1102, 5012, 1308, + -3943, 3207, 764, -2928, 1144, -3044, 4033, 1846, + 6460, -4165, 8509, 9824, 15708, -642, 748, 124, + -406, 13033, 807, -299, 1319, 1499, -1206, -1102, + -3129, 3795, 47, -2483, -2470, 2287, 4028, 1656, + -364, -1712, -1568, -3940, -2770, -13688, 796, 3380, + 363, 1673, 1160, -3934, 2884, -5060, 832, 4799, + 364, -3030, -10596, -1805, -3256, -2492, -1831, 1088, + 11108, 3236, 5128, 3052, 4486, 84, 2078, 200, + -4071, 1713, 1539, 24597, -1019, 32, -48, 82, + 81, 1171, -1261, -1783, -1693, 2194, 1714, -225, + -1989, 402, 2611, -708, -15901, 222, -507, 12855, + 1162, -1536, -2884, 1911, -1256, -926, -1875, -1448, + -2730, 3059, -1231, 1680, 1824, 1288, -215, -9, + 40, -957, 27662, -1844, -1927, -846, -1144, -439, + -3507, -2844, -1880, 637, 1042, 237, 1007, -387, +-11913, -2584, -142, 624, -494, 1439, 2225, -13017, + -1901, -1253, -1071, -7083, -2154, 814, 3867, 1130, + -2611, -2260, 1548, -12389, -1018, 102, 1178, 1058, +-14863, 2020, 4094, -1259, -861, -886, -3119, 2638, + 1725, -1364, -2086, 183, 507, -978, -3086, -14966, + 759, -1341, -70, 8538, 2974, -140, 2509, -4460, + 2724, -1372, 491, -6138, -345, -2170, -1187, -330, +-11090, 15657, -300, 2105, 496, -2093, -447, 2000, + 3451, 1482, 758, 4142, 562, -4042, 1491, 3183, + 1685, -2729, 1611, 11698, 14918, 25, 842, -2766, + -667, -1564, -2619, 646, 1391, 862, -909, -2141, + -589, 1468, -755, 1324, -765, 634, 195, -19622, + -1006, -1161, 2434, -1808, 4168, 4108, -2580, -635, + -2533, -2170, -3701, -1047, -363, 769, 5064, -8, + -654, 2346, 752, 13736, -4056, 7, 5492, 7326, + -4894, -3860, 3325, -3947, 4721, 5557, -3699, 194, +-12957, 1052, -1317, -2642, -2931, 1050, -3951, 2392, + -9683, 2519, 2880, -3700, -1820, 831, 4370, -1177 +}, + +.cb1616l0 = { + -185, -20290, 476, -272, 31, -638, 806, -61, + 220, 176, 178, -788, -441, -333, -360, -263, + -116, -512, 9794, -727, 8904, 1192, -277, 756, + -670, 795, -311, 240, -617, -675, -970, 756, + 857, 529, -166, 674, 890, -522, 837, 79, + -618, -1308, -13832, 744, 5422, 2688, 531, 398, + 1500, -1965, -209, -346, 613, 2147, 10053, -1398, + 189, -108, 471, -1202, 999, 178, 762, -601, + 1116, 9468, -281, 763, -1204, -822, -20, -160, + -806, 14720, -269, 143, -1362, -532, -788, -1532, + -405, 85, -271, -4959, 276, -34, -28, -66, + 112, -188, -582, -678, 128, 680, 982, 596, + 12154, -10468, -167, -380, 734, -296, 282, -223, + -86, -342, -812, 514, 387, -418, -364, -1216, + 14, 373, 357, 10897, 11235, -714, 206, -618, + -607, 596, 190, 726, 496, -300, 95, 1022, + -153, 212, -540, 252, 281, 238, -234, 28, + 24, 184, 32767, -627, 569, 323, 486, 544, + -348, -589, -284, 238, 228, 475, 83, -7753, + 182, 745, 400, -633, -207, 137, 382, 90, + 78, 715, 448, 463, 937, 10203, -12047, -667, + -370, -1516, -360, 94, 832, 1027, 1013, 92, + -5446, 834, 302, 764, -94, -462, 8095, 1057, + 308, -635, 308, -877, -946, -616, 51, 1090, +-13351, 490, -819, 15182, -384, 411, -546, -242, + 460, -323, 76, 277, 1582, 900, -1119, 345, + 1316, 1138, 2020, 1612, -148, 812, 1241, -10350, + -9495, -965, -69, 1967, -168, -128, 1042, 447, + 491, -133, -5083, -450, -164, 50, 326, 269, + -283, 226, -40, -334, -110, 60, -47, 169, + 9166, 1188, -942, -14, 2112, -230, 634, -741, + -214, -336, -606, 3102, 59, 216, 1805, -1176, + 211, -8, 564, 156, -261, 300, 597, -21842, + 66, -232, -506, -1126, 1057, 603, 1448, -391, + 249, -9445, -10240, 694, 167, -1158, -645, -385, + -209, 330, 519, -345, -600, 192, 78, -229, + 208, -9053, -383, 10646, -264, 84, 295, -148, + 87, 1292, 257, 1080, -564, -2395, -1200, -484, + -48, -513, -383, -11, -516, -17356, -1172, -218, + 124, -327, 31, 328, -80, 231, 58, -951, + 560, -501, -392, 30528, -56, 382, -515, -50, + -155, 338, 0, -414, -899, 95, 11, 378, + -350, 459, 673, 76, 86, 379, 32222, 143, + -48, 425, -394, -60, -348, 450, -489, 220, + 56, 1129, -125, 322, 168, -16, 322, -293, + 294, -38, 328, 141, 692, -82, -160, -32768, + -140, -1543, 1079, 1052, -924, -569, 168, -1782, + 815, 706, -1318, -3436, 2860, 10922, 236, 10311, + 882, -1911, 11, 1638, -189, 245, -858, 11060, + -826, 696, 224, 1707, 1766, 472, 10832, -265, + -161, 163, 478, -258, -284, -86, 496, 425, + -71, -10344, -141, 425, -1457, 1145, -63, -713, + -583, -327, 628, 368, -18, -1746, -525, -338, + -110, -359, 92, -233, -21328, 460, -275, -98, + -58, 51, 208, 56, -1145, -51, -242, 65, + 76, 214, 141, 28, -86, 26, 925, 193, + 9980, -326, 11342, 176, -534, -303, 130, -1575, + 189, -496, -699, 381, 411, 644, 229, -147, + 694, -1998, 523, -1576, 8028, -10385, -1924, 1174, + 608, 2402, 575, -1753, 437, -816, 1267, 147, + 1448, -614, 865, 1076, -156, 5000, 2020, 2021, + 10283, -460, -2381, -3226, -3991, 4904, -284, 105, + -268, 1049, 203, -646, 732, 6490, -128, 932, + 10, -866, 74, -64, 834, 204, 159, -162, + -170, -110, -28908, 52, -512, -72, 327, 615, + 534, -484, 131, -262, 31, -407, 284, 33, + 11118, -170, 318, 12848, -1126, -659, 500, 310, + -403, -234, 237, -544, 1232, -243, -1178, -965, + -117, 108, -1304, 11728, -2254, 1231, -1077, -136, + -632, -103, -256, -1644, -300, 1680, -1175, -956, + -43, 1718, 175, 144, 275, -802, -223, 1116, + 321, -871, -1174, -1175, 1008, 255, 31172, 28, + -621, -222, -12473, -10995, -712, 247, 1762, 418, + -181, 90, 92, -406, -435, -105, -596, 2262, + -116, -1574, -3402, 6796, 7944, 973, -2661, 2260, + 621, -6984, 382, -1375, -2604, 1550, -1453, 1133, + 966, 403, 284, -72, -36, 174, 457, -90, + 38, -437, -476, -370, 469, 32767, -267, 350, + 694, -169, -782, 2110, -620, -782, -669, -6478, + 10550, -3294, 485, 177, 553, -3232, 1628, 2335, + -870, -360, -1112, 2197, -474, -5113, 3346, 878, + 566, -3823, -1175, 357, 10509, 1077, -514, 1012, + 38, 59, 669, 654, 349, -1046, 355, 192, + 57, 95, 11869, -702, 10201, 204, 45, -608, + -444, 921, -1070, -316, 1286, -2566, 2026, -127, + -79, -954, 93, -1288, -10024, 693, 8820, -366, + -84, -6378, 1682, -627, 386, 254, 503, -152, + -336, 38, -341, 373, -85, 1088, -1707, 119, + -242, 242, -326, -162, 109, 70, -114, -831, + -279, -32768, 62, 58, 214, 136, 194, -103, +-10047, -610, 91, -310, 12059, 346, -656, 986, + 478, 364, 1777, -173, -663, -103, 1011, -373, + 200, 1632, -13098, 3651, 418, 478, 68, -217, + 169, 78, -1176, -1191, -1664, -328, 152, -1053, + 547, 527, -10435, -176, 11131, -137, -36, 1062, + 33, 71, -730, 2080, 2061, -372, -637, -84, + 744, 109, -357, 550, 309, -239, -134, 135, +-20461, -177, -690, -488, -36, -415, 275, 64, + 378, 11250, -802, -569, -200, 1499, 13103, -1090, + -175, 189, -162, -751, 1052, -949, -98, 1249, + 479, -1304, 3293, 771, 1642, -381, 1423, 2258, + 1184, 4806, -10950, -3873, 348, -815, -5315, -3306, + -3307, 2337, 776, -125, -48, -435, -155, -30, + 294, 116, 96, -47, 1022, -391, -183, 252, + 826, -32, 293, -1369, 18310, -146, 239, -266, + 34, -154, -704, -498, -135, 228, -563, -210, + -158, -514, -201, -571, -341, -428, 74, -152, + 297, -162, -644, -216, -252, -13810, 705, 464, + 21097, 74, -169, 792, 12, 131, 320, -398, + -446, 44, -362, 388, -22, -13, -209, 1205, + 9341, 590, -683, -351, 177, -1618, 495, 14, + -319, 755, 11352, 249, -989, 1574, -922, -364, + 366, -10348, 337, -558, -124, 12056, 102, 802, + -548, -254, 1532, 7, -282, -459, -839, 171, + -4445, -1610, -1515, -37, 970, 306, -881, -238, + -154, -58, 27, 435, 166, 571, 225, -844, + -9967, -192, -874, -459, -1283, -1431, 1552, -38, + -686, -207, 709, 11982, -383, 1922, -92, -60, + 708, -900, 867, 39, 1470, 517, -182, -456, + 90, 1026, -192, 9988, 942, 48, 789, 981, + 74, -692, -1283, 1239, 1625, -1121, -286, -1115, + 294, 13228, 980, 312, -745, 11711, 1055, 1052, + -907, 201, 688, 364, 1171, 96, -591, -981, + -246, 875, -352, 677, 881, -397, 12890, 10, + 0, 412, 76, 464, 275, -721, -28, -197, + 104, -238, -372, -272, 490, 1426, 963, -13232, + -1190, 790, 161, -321, 1138, 646, 359, -183, + -659, -129, 348, -22703, 1016, -147, 26, -80 +}, + +.cb1616l1 = { + 292, 310, -255, 305, 69, 25001, -16, -668, + 210, 17, -12, 45, -758, -76, -544, -882, + 61, 26, -1682, -8820, 154, -11775, 64, 472, + -464, 245, 478, -1560, 869, 2192, 98, 645, + -95, -9369, -594, -635, -11132, 900, 1606, -904, + 841, 2570, -1464, 961, 1056, 669, 461, 3307, + -157, -644, 121, -694, 170, 116, 393, 1507, + -233, -654, -162, 108, 98, 17471, 347, -11344, + -701, -284, -246, -337, -1903, 14, 9865, 453, +-11318, -3662, 2373, 1106, -1424, -1709, -2743, -860, + 11008, 1579, -38, -1381, 467, -487, -1306, 369, + 426, -424, 128, 1078, 1085, 683, 12552, 792, + -184, -278, 186, 2006, 363, 310, -75, 862, + 377, 490, -256, -1568, -124, -10785, -1456, -524, + -1259, 517, -1844, 914, 769, 945, 739, -1053, + -691, 177, 96, -1070, -162, -707, -594, -9885, + 103, 452, -734, -6774, -753, 192, 88, -292, + 201, -532, 231, -281, -691, -1232, -1768, -753, + 369, 1556, -139, 668, 941, 264, 10372, 9740, + 976, 2519, -88, 941, 446, -130, 2131, -631, + 325, 285, 176, -236, -634, -91, 112, 32767, + -233, -726, 156, 881, -217, -497, -236, -1106, + 283, 164, -328, -629, -27442, -17, 176, -338, + -192, 538, -773, 634, -180, 872, -190, -530, + 586, 6994, 3060, -336, 736, -1268, -1142, -69, + -1359, -1047, -975, -86, 12489, 1162, -509, -478, + 717, -514, -502, -1755, 11064, 7668, 340, 230, + -127, 1490, -63, 680, -297, 125, 1700, 2505, + 3, -2043, 255, 1547, 569, -2483, 733, -896, + 881, 4780, 1544, -13442, 1328, 1937, -4448, -384, + 749, 173, 7350, 156, -144, 52, -527, -34, + -3, -173, 118, -528, -75, 39, 42, -874, +-14636, 474, -413, -106, -115, -431, 54, 722, + 156, -468, 369, 149, -68, -791, 1318, 2150, + 69, 454, 19032, 3, 111, -40, 349, 88, + 385, -54, -395, -224, -519, 0, -219, 179, + -253, -11379, 11005, 1857, -126, -248, 304, -616, + 351, 324, 500, 1494, -1390, 2349, -1257, -1114, + -213, 8156, -2066, 9746, 763, -848, 349, -7, + 723, -966, 469, 91, -252, 1336, 579, 1816, + 1372, -941, 364, 276, -33, 7, -425, -433, + -21, 546, -671, -31271, -926, 101, 147, 302, + -552, 224, 568, -2386, 519, -458, 13171, -1464, + 1161, 639, -10, -877, 331, 3372, -72, 5158, + -706, 906, 2668, 1008, -2732, 3264, 105, 630, + 673, -1948, -196, -13130, 1726, 737, 4829, 93, + 654, 2175, 3858, -5, 245, -471, 369, 5435, + 356, -12934, 61, 1984, 975, 706, -2454, -642, + -93, -780, -443, -1487, -460, 1112, 385, 309, +-10268, 197, -1692, -1870, 50, -1934, 5380, -1193, + 775, -493, -992, -557, 2952, 408, 4616, -1341, + 10774, 5305, 854, 3031, 67, 617, 2436, -2072, + -1469, 804, -578, 243, 264, 9150, 200, 10753, + -350, 182, -52, -406, 508, -761, -161, -1142, + 25, 484, 127, 126, 477, -341, 110, 371, + 32767, 1090, 678, 175, 146, 1020, -897, 878, + -137, -507, -534, 658, 678, 505, -753, -207, + 391, 60, -23279, -772, -1323, -1578, -3, 196, + -749, 220, -482, -785, 456, 38, 1034, -579, + -58, -1539, 421, -746, 238, 1531, 21290, 586, + -441, -276, 1512, 553, -1407, -276, 60, -1068, + 299, 650, -25, 12590, 2058, 925, -295, -1744, + 5152, 4935, -419, 272, -383, -665, -194, -255, + 574, -267, 541, 1031, -282, -648, 622, -1464, + -28, -269, -533, -80, -476, 282, -336, 125, + 104, 464, -8948, 849, 171, 1518, -296, 51, + -27, 3097, -5103, -412, -494, -194, -713, -1277, + 102, 1740, -445, 3432, 1180, 6404, -10908, -970, + 31, 142, -242, -79, -78, -76, 124, 1031, + 83, -55, 1522, -613, -32768, -394, 1306, 287, + 701, -4725, -1085, 415, -122, -538, -675, 82, + 116, -728, -99, 500, 659, -329, 292, -106, + 9243, -340, -11933, -498, 341, -825, -401, -402, + 142, -13, -309, -722, 141, 0, -681, 494, + 671, -1210, 1466, -1335, 11743, -280, 1616, -11481, + 52, 317, 902, -653, -967, -494, -162, -685, + -438, 756, 81, -207, 577, -7476, -353, 918, + -31, -107, 181, 523, -46, -752, 373, -908, + -1808, -916, 632, 1508, -35, -6943, 64, 13072, + -655, 163, 1221, -1655, -2568, -446, -401, 470, + -622, -944, 3744, -458, 203, 125, 238, 5196, + 21, 12193, 1095, 1091, -787, -1157, -980, -1154, + 7707, -29, 106, 1226, 696, -974, -379, -537, + 56, 95, -477, -528, -11245, -1014, 140, 380, + 89, 540, 84, -619, -322, -572, -240, -26, + 727, 310, 43, -790, -31, -24318, 110, 618, + 44, -108, 89, -191, -33, -201, -490, 43, + -136, 1366, -2, 162, -832, 469, -140, -278, + 600, -15775, -1699, 184, 1825, 728, -1803, -876, + 152, 60, -813, 3063, -929, 972, -282, 718, + 8426, -888, 1383, -664, 571, 958, 982, 236, + -548, 66, 1898, -274, 10715, -1693, 79, -1254, + 296, 609, 682, -1074, 272, 157, -18972, 377, + -12, 438, 536, -672, 292, 719, -464, 1106, + -296, -812, 6, -334, 67, 678, 382, 678, + 301, -22165, 184, 80, -671, -86, 139, -298, + 416, -610, 1057, 15, -230, 376, -768, 643, + 58, 27, 178, -742, 60, -500, 485, -19923, + -1016, 717, 1126, 287, 2171, -388, 1453, -21, + -268, -1555, -263, 713, 1709, -1103, -10699, 1788, + -8, -501, -892, 11476, -2006, 466, 8070, -286, + 163, 35, 494, 76, 1428, -2249, 100, -1542, + 319, -214, -701, 10130, -294, -11962, -656, 227, + -512, -1014, 213, -600, -720, 63, -180, 1286, + 1063, -9671, -1056, 1269, 1484, 20, 790, 29, + -9906, -373, 608, 361, -659, 43, -1034, -96, + -219, -65, 392, -19615, -464, 212, 820, -182, + -227, 463, 301, 642, -219, 386, -1170, 108, + -5583, 422, -507, 530, -1058, -131, 20, -14487, + 101, -14, -415, 32, -1133, -917, 944, -832, + 580, 2509, -959, 470, 1184, 432, -1238, 193, +-13382, 2329, 1993, 1035, 80, 3139, -553, 1683, + 390, 1480, 642, 564, -11173, 422, -984, -559, + -686, 168, -777, -810, -1278, -427, -96, 1691, + 29172, -435, -50, -968, 221, 685, 52, -373, + 525, -563, 350, 528, 305, 705, 313, 612, + -254, -220, -1638, -156, 24, 109, -893, -697, + 245, 2579, 667, -142, 12315, -694, 3799, 5, + -438, -473, -426, 59, -5381, -56, 200, -280, + -276, 96, 435, 729, 336, 123, -714, -372, +-12609, -12053, -238, 223, -242, 230, 663, -645, + 98, 515, 3, 724, 510, -48, 1090, -173, + -5024, 536, 635, -143, 702, 172, -196, 164, + 190, -152, -180, 238, -142, -329, 191, -296, + -416, 11775, -496, -95, 392, 994, -584, -925, + -963, 286, -458, 3104, -1990, 968, -1430, 998, + -407, 28485, 436, 42, 378, -210, 148, -149, + -532, 94, -628, 186, -186, -274, 250, -316 +}, + +.cb1616s0 = { + 5604, 1491, -2064, 1321, -2846, -3007, -1899, -896, + 556, 1969, -2225, 18515, 4156, 1333, 3489, -2168, + 1897, -1440, -1514, -13837, 1017, 4797, 453, -2101, + -6822, 923, 185, 754, -201, -4151, 126, -793, + -437, 2474, 4286, -6405, 4007, -1644, -757, -13106, + 2460, -1874, -1867, -1099, -5146, 2945, 2162, -4427, + 1692, 763, 1756, -821, 66, -348, 2001, 702, + 1046, -1365, -570, 1073, 32655, -9, 450, -761, + 908, -200, -572, -1306, 2589, 2406, 1926, 1772, + 11042, -1989, 3914, -1192, 1817, -11710, 2985, -2942, + 15684, 1919, -667, -1267, 5212, 444, 864, -3844, + 438, -2382, 974, 983, -887, -822, 185, 245, + -3192, 1030, 1441, -28152, -2616, -380, 300, 1990, + -94, -999, 285, 553, 2107, 960, -859, 1001, + -1632, 2208, -1302, 1331, -3956, 10593, -1931, -4486, + 9376, -6587, -463, -3605, 2460, 1306, 2, 1987, + 1643, -552, 1327, 1124, -581, 1347, 650, -29514, + 278, 1062, 1459, 951, 2416, 396, -594, 930, + 434, 3308, -2816, 5466, 4831, -2869, -68, -894, + 58, -13036, 210, -1940, -2524, 1139, 2044, -32, + 969, 2187, 516, 581, 8185, 2080, 176, -708, + 1529, 1132, -675, -1384, -10949, 1174, -5245, 580, + 7490, 3258, 4314, 2706, -13676, -1735, 1937, 577, + -108, 2676, 612, -966, -966, 3255, 1401, 1443, + -1850, -252, 9270, 5037, -1492, -1957, -2134, 1198, + 3470, 10482, -468, -671, -1655, -955, 3248, 3360, + 448, -1854, -25145, -2771, -3318, 561, -672, 1791, + 2194, -598, 1673, -420, 547, 122, -160, -172, + 1686, -397, 1187, 11, -879, -58, 323, 180, + -2588, -2139, -1794, -2924, 999, -26969, -1280, -1401, + -770, 6159, -4449, -4174, 5270, -4813, 4139, -2023, + 2694, 2884, 3418, -5948, 3118, -1176, 4691, 8566, +-32768, -681, -553, -216, -216, -931, -507, 579, + -932, -740, 349, 81, 2120, -1222, 564, -1576, + 1241, 159, 2579, 3236, 19205, -744, -1727, -1803, + 1247, -575, -261, 261, 540, -255, -60, -1428, +-14184, -5194, 863, 997, 1043, -828, 466, -12553, + 2106, 56, -566, 1142, 401, 1360, 2322, 629, + 937, 2954, -10086, -12, 2554, -5760, 523, -15184, + 636, 156, 165, -2638, 1134, 658, 4398, -1385, + -1924, 1179, 3222, -908, -1153, 18082, 1011, 1948, + -1007, 352, -172, -6446, -22, -228, -264, 73, + 76, 2229, -1349, 6103, -11588, 576, 3374, -1616, + 7904, 3146, 984, 1056, -1626, 3113, -3674, 203, + -452, -938, 2074, 2409, -1228, -8186, -2766, 11098, + 1598, -8658, -735, 556, 1610, -7419, -5267, 1158, + 2841, 4497, 7551, -2066, 1105, 761, 2549, -1764, + 2870, 3889, -1478, 1912, 2504, -1417, 963, -14602, + 579, 28, -2953, 1589, 3962, -1372, -3304, 566, + 2687, 9700, -2464, -13110, 3005, -772, -3775, -138, + -4244, 5031, 2523, -2883, 582, -446, -274, 3311, + -157, -784, -948, -292, 3085, -781, 954, -2133, + -6693, 13909, -2236, 416, -2589, -3194, 668, -1988, + -2234, 2365, 1034, 1201, -100, 1688, 372, 156, + -254, 931, 576, -4680, 566, -1823, 294, 1645, + 27678, -1353, -1230, 1744, 570, 1679, 608, -35, + -7150, -4383, -11992, -2910, -2096, 512, 1838, 3129, + -410, -2306, -551, -3904, 4140, -12782, -1743, -106, + -4190, -5554, 12975, -573, -3532, -4050, 15, 1307, + 62, 1643, -1988, 5774, 2064, 4734, 1009, 2038, + -2794, -2704, 2275, -279, -1588, -910, 31315, 1249, + -1642, 78, 164, -260, -878, 698, 1189, 159, + -6137, -1994, 775, 3484, 1635, 1121, 4391, -5883, +-11300, 3722, -422, -2180, -3206, -3181, -1490, 291, + 1326, 399, 1952, -8405, 2240, 175, 3541, 4258, + 1518, -781, 1105, 498, -348, 771, 15918, 120, + 379, -2036, -3723, 10948, -1827, 3220, 40, 210, + -294, -813, -2349, -707, 967, 953, 2625, -13614, + -1519, 9454, 11606, -903, 817, 6237, -8878, -160, + -1768, 444, -2812, -1697, -1010, -964, 1846, 2997, + 2633, -1924, 501, -1464, 2402, -986, -1143, 527, + 1187, -929, 20923, -563, 785, -486, -940, 1625, + -796, -697, 348, -428, 1451, 1087, -2252, -2481, + 939, 890, -2508, -1357, -1868, 1395, -6386, -21986, + 2574, -384, -324, 7752, 2996, -641, -7903, -5745, + -4226, -4178, -4394, 9307, 3906, -227, -496, 4556, + 1099, -838, -2546, 1190, 9937, 11057, 3846, -156, + 433, -2873, -1769, 36, 3188, 4490, 4369, 4714, + -4681, -2804, -1525, -947, -5064, -4180, -1348, -1404, + -1097, -3922, -1088, -444, -13636, -1547, 1685, -1625, + -8494, 2492, -72, 9893, 2470, 705, 105, 5609, + -5403, 846, 90, -688, 1184, 6286, -253, -1610, + 3348, -2082, 8838, -2453, -1315, -1235, -719, -4607, + -2138, -5522, -10466, 1900, 1541, -2688, 729, 368, + -8845, 1282, 438, -2532, -2328, 4833, -6145, 4037, + 3584, 7965, -1495, 6999, -5037, -1364, 7095, 4253, + 2711, -8336, 3946, -1347, 192, -820, -328, -1152, + 1554, 869, 5053, 9707, -5888, -4294, -3858, -3344, + 8344, -644, 1750, -1796, -149, -3706, -14823, 656, + -1487, -2466, 640, -2286, -2902, 2906, 44, 211, + -336, 29976, -298, 2092, -688, 1857, 1807, -1705, + 3211, 425, -1046, 128, 1191, -1966, -726, -3040, + -3632, 1212, 2986, 5266, 1086, 3624, 3068, 422, + 989, 24479, 3791, -2229, -3713, -2379, -1370, -1799, + 2742, -3259, -4973, -626, 2287, 5655, 663, -918, + 13266, 7762, -1131, 2490, -3123, 2869, -846, -2828, + 119, 14540, 4588, -2784, -3713, -2547, 3698, 3189, + 3372, -5436, 856, 4382, 4124, 3406, -336, -911, + -137, 4268, -4436, 1566, 1169, -3020, 13980, -162, + -7226, -2550, -946, -2408, -1056, -587, -273, -932, + -219, -8021, -1086, -2587, 3852, 1235, -22, 222, + -1100, -1594, 137, -1985, 10225, 4998, -348, -450, + 6651, -2217, -7705, 2508, 10061, -4512, -2262, 6156, + 2962, 150, -2456, 1089, -927, -609, -3130, -1682, + -1215, -9251, -130, -3776, -309, -13872, -276, -6922, + -82, 2660, -1255, -6562, 2640, 2646, 422, -84, + -6020, -11551, -1710, -3462, -2666, 12510, 3145, -218, + 2956, 447, 30, 2268, -2410, -1400, 660, 431, + 3068, 258, -2862, 3919, 2693, -744, 3070, -2179, + -1192, -932, -2095, -279, 2045, -8205, 15263, -4415, + 2116, 4047, 10308, 3110, 1368, -1547, 10919, 988, + -81, -907, -1728, -1052, -3539, -4769, -2576, -1038, + 9255, 152, 431, 2455, -1544, 1880, -312, 2724, +-13336, -4197, -1199, 709, -695, -1687, 442, -2564, + -1626, -1888, 1870, 3539, -2922, -3506, -7890, -5486, + -1640, 2178, 2173, -3200, -4626, 1116, 13161, -5221, + -852, -1047, -3328, -3975, -4441, 2870, -1458, 5664, + -28, 3853, 1809, 2721, 658, -15262, 3611, 3223, + 595, 44, -5327, -2486, -1806, 606, -2474, -1236, + 983, 1741, -8390, 1948, 1875, -1806, -6294, -814, + -747, 2209, -1332, 2058, -1326, 5808, 1113, -10765, + -584, 4038, 1412, -3356, 24, -12826, -4322, -2287, +-10793, 3008, -6903, -1273, 1590, -608, -514, -309, + -144, -2024, 1822, 4375, 1122, -631, -76, -595, + 192, -11323, 8168, 10180, -646, 2478, 4516, 1095, + 94, 6, 1251, -658, 2620, 626, 3078, 727, + 7769, 966, -3593, -6990, -2358, 1022, 1288, 2733, + -259, -291, 2482, 297, -1268, 10338, 739, -1862 +}, + +.cb1616s1 = { +-12873, -2429, 6659, 4401, -2250, 1684, 1508, 1780, + -1081, -10, -6012, 895, -2373, -1263, 125, 1448, + 4744, 1556, -7267, 2354, -11368, 1155, -7699, -1424, + -914, -591, 2472, 538, 1431, 953, 5, -3066, + -1063, 3, 406, 979, 922, -668, 1633, 2, + 649, -139, 964, 860, -18807, 1944, 2183, -1358, + 1395, -1167, 5369, -3525, 735, -2698, 10556, -1137, + -3979, 1383, -1997, 5995, 6465, 2310, 1781, -311, + 3376, 7199, -2745, -1656, -5702, 3180, 3017, -5673, + -712, -8902, 2058, -570, 170, 2276, 3869, -9332, + -7965, 1130, 2111, 5638, -1507, 2944, 1574, -919, + -1459, -970, 11093, 544, -2952, -146, -4684, -303, + -528, -1199, -890, -2720, -1665, -10952, 373, 1657, + 1960, -1386, 299, -4356, -4527, 8948, 7378, 1580, + 1301, -6057, 7650, -7399, 4646, -1768, 2756, -263, + -286, -334, 1369, -786, -3760, 824, -13524, -5099, + -1693, -347, -1821, 1992, 3462, 1421, 4900, -462, +-13331, -1617, -2350, 4083, -8721, -5880, 4900, 2912, + 235, 10369, -1340, 776, -2598, 14344, -3805, -568, + -3788, 3591, -394, -1077, 3908, 6080, 1953, -1454, + -1013, 507, 10097, 3396, -4662, -763, 2506, 1486, + 3088, 580, -86, 1117, 1606, -3454, -10782, 4870, + 6170, 4020, -5675, 6848, 439, -8765, 3877, 6250, + 734, 3245, -874, -4312, -879, -4368, -1287, 3212, + -2130, -1435, 1619, -280, -3082, -1070, -18921, 940, + -2428, -1548, -1142, -271, 193, -240, -890, 918, + -4350, -5042, -8994, 5060, -6495, 3455, -259, 892, + -1290, 1348, -1049, -12681, -49, 18286, 75, 791, + 1830, -4116, 10240, -12, -459, 2477, -2582, -3344, + -1598, 982, -324, -48, -4229, -8476, 11120, 100, + -6238, 1164, 2369, -2052, 247, 626, 2213, 2279, + -2627, 289, -471, -1136, -1818, 15413, 579, 1034, + -6835, -8645, -12667, 758, -932, -4398, 565, 458, + -2024, -4050, -3100, 1897, 1324, 3191, 1876, 7660, + 385, -1066, -1539, -1317, -2632, 766, 63, 389, + -189, 1136, -653, 802, 755, 70, -29812, 640, +-11953, 10901, 2078, -529, 10373, 2509, -2776, -104, + -2232, 174, -837, 158, 1507, 1963, -273, 1534, + 1084, 8469, 2568, 12662, -2276, 2808, 2052, -7430, + 434, 3777, 991, 664, 2724, 1631, -3632, 2099, + -582, 4140, 757, 11248, 540, -1425, -10204, 1604, + 600, -2034, -1060, 977, 1843, 3831, -933, -816, + 2975, -6413, 1589, -915, -696, 2155, -556, -17893, + 3348, -1239, 1014, -2539, 1588, -320, 2402, -1485, + -8062, -1046, -1458, 200, 1323, 357, -3752, 2836, + 5774, -11638, -913, -648, 1676, 246, -1277, -1065, + 2334, 14911, 228, 880, -2172, 3072, -2520, 1445, + 1442, 2568, -1254, 730, -1950, -192, 12003, -1587, + 2558, 714, 33, 4324, -4642, -231, -279, -255, + 17824, 1292, 3530, -766, -64, 245, 1677, 1716, + 2507, -3594, -3532, 3000, 1996, -5342, -1868, -5642, + -21, 1132, -1202, 1104, -6543, 1242, 457, -1711, +-32768, 49, -458, 295, 858, 2043, 1268, -1257, + -346, 793, 554, 1260, -1082, 985, -1453, 1704, + 2431, -2858, 1466, -5424, -8870, 4714, -1539, 5767, + 110, -2568, -1482, -348, -11580, -2838, 1213, -599, + -1591, -3472, -6907, 6191, 3928, 4708, 1326, -1510, + 6322, 3849, -4112, 7689, 5976, -3298, 372, -5450, + -2208, 6564, -6915, 911, 4216, 1682, -739, -2146, + 203, 350, -816, 351, -3386, -3016, -15045, -10824, + -553, -4969, 138, 256, 1672, -1840, 2851, 15838, + 2934, 1871, -600, -3293, -845, -2696, 1463, -1075, + 720, -1177, -1538, 2415, 7315, -484, 1082, 962, + 766, -845, -10687, -5932, -4410, 3840, 362, 194, + -4576, 10209, -3548, -127, -1202, 246, -734, 770, + 311, -3126, 772, -2422, -1141, -12330, 960, 1567, + 2816, 80, -4414, -778, 665, 2308, -420, -180, + -1242, -423, 12138, 113, -1477, 2899, 214, 348, + -927, -764, 26, -1127, -2288, -32768, 1302, 394, + 646, -453, -946, -838, 1649, -2292, 1182, -1558, + -6413, -265, -1942, -3467, 1863, -3526, 3446, -863, + 886, 202, -202, 15706, 2226, 1763, 894, 936, + 16191, -693, 1682, 6678, 1742, 1365, 700, -1765, + -803, 299, -2194, 1259, 689, 1670, -635, 28, + 11890, -14, -878, -5439, 103, 11124, 528, 1179, + -62, 868, -664, 749, -1128, 1429, -485, 1920, + -866, 1176, 1051, 379, -29470, 2354, -252, -1648, + -412, -804, 1339, -383, -812, 959, 893, -1741, + 1462, -1868, 470, 2112, -1889, -2236, -1668, -755, + -2562, 1354, 6183, -10964, 5651, -1062, 2550, -6225, + -194, 1687, -782, 1568, -85, 10, -8, 1128, + -521, -1090, -1933, -3441, -2698, 3049, -5822, 20847, + 710, 789, -1872, 1082, -1242, 4152, 1624, 10795, + -2149, -134, 1087, 900, -7943, 5178, -3429, -11622, + -3617, -7444, -824, 3462, -579, -830, 1010, -3301, + 12202, -5446, -1763, 340, -744, -509, 554, 1140, + 12266, -1328, 4652, 992, -1931, -708, 1074, 2762, + 2931, -414, -217, 10166, -4167, -903, 660, 1000, + 27, -1037, -1532, 1308, 8655, 9087, -2998, 9928, + -3722, -556, 4812, 3062, 600, 1281, 3879, 114, + -5404, 1869, 2174, 2083, -11631, -301, -3609, 2443, + 2300, 4863, -838, -29, 2166, 1319, 2110, 1387, + -741, -1225, -1729, -13536, -7376, -1520, 619, -4919, + 2517, -4338, -1650, 475, 456, 4372, 792, 3224, + 1963, -547, -2071, 2142, -254, 1549, -6846, 2430, + -96, 19844, 595, 1197, -1367, 2019, 2014, -1547, + -3775, -1186, -9690, -394, -4106, -1728, -1036, 2945, + 509, 14242, -1893, -2494, -3004, 458, -1753, 2628, + 9790, 3450, -1652, -322, 8263, 3952, -2156, -2110, + -442, 1256, 1561, -4913, -3452, 74, 3051, 8907, + -3376, -96, 16654, 557, 520, -446, -2520, -1712, + 2151, -2423, 3761, -3507, 487, 2103, 777, -416, + 509, 468, 3629, -3155, 11460, 2106, -2191, -1014, + 1154, 9317, 704, -282, 3098, 2722, 84, 150, + -5922, 3063, 8373, -11896, -1157, -2286, -1781, 7331, + 1331, -334, -974, -1653, 752, -1970, -89, -3470, + 2418, -1334, 3615, 12770, -116, 1965, -1643, 1480, + -2225, -10686, -1174, 530, -972, -933, 719, 722, + 1530, -317, 105, -14155, 2569, 4506, -8502, -681, + -1544, -542, -2814, -1161, -629, -1776, -3540, -1366, + -3681, 1838, -1630, -703, 12613, -12335, -2020, 2173, + 27, 315, 4766, 4590, -1603, -68, 1154, -2940, + 1198, 7884, 2502, -586, 440, -5124, -2454, -2597, + -826, 7401, 2803, 4552, -3212, 2966, -5567, 588, + 2216, 7444, -2633, -5922, 434, 3423, 4084, 2296, + 13258, 2070, -4624, -1226, 166, -367, -527, 1110, + -1407, -150, 140, 584, -373, -2649, 862, 500, + 3292, -3506, -679, -20109, 1775, -726, 3378, 754, + -1962, -5764, -1338, -3628, -691, 4554, -1890, -6021, + -6566, 2590, 262, 2509, 257, -4386, -2480, 6352, + -2026, 1234, -399, 22808, -2221, -626, -714, -339, + -1196, -455, -80, 713, 1662, 474, -2324, -527, + 4101, -10526, -4617, 10492, -1143, 805, 1360, 3796, + 942, 684, 2596, 1313, 1589, -570, 5476, -27, + 9220, -1493, 2631, -6726, -2976, -14295, 137, -734, + -2015, 658, 323, 83, 2539, -1230, 1714, -2080, + 658, -18803, 2978, 996, -3374, -28, -1335, 150, + 2154, 1069, -852, 293, 535, -1004, -993, -3692 +}, + +.cb1616m0 = { +-16476, -11442, -305, -196, -767, -2167, -1, 378, + -2200, 22, 2405, 944, -1786, -806, 669, 952, + 10435, -2752, -1625, 1060, -12314, 1283, 234, -2405, + 627, 798, -1058, 311, -2794, -2715, 73, -214, + 813, -2749, 10732, -445, -12147, -2507, -1972, 1652, + -1920, 215, 298, 1106, 826, -7445, 69, -1679, + -675, 1249, 1444, -1109, -48, -1452, -2368, 3034, + -492, 13068, 311, -3446, 326, -1426, 2384, -2146, + 2916, 8957, -196, 2212, 447, 1775, 2607, -11962, + -278, 4335, -1743, 135, 212, -41, -92, 164, + -11, -504, 828, -519, -834, 251, 1919, 762, + 24917, -180, -132, -330, 138, 225, 1038, 3, + 32138, -388, 208, -638, -1338, -165, 200, -230, + 225, -777, -2270, 8198, 583, 3946, -1534, 1666, + -1032, 11384, 202, 30, 2758, -505, -2815, 1265, + 64, -17, -360, 636, 134, 502, 259, 872, +-28148, -1046, -348, -86, -739, 55, 448, 168, + -656, 1094, -1074, 4552, -834, 2296, 2356, -572, + -1917, 10979, 3127, -52, -9969, -527, 1994, -1626, + 1041, 3310, -2319, 2232, -11444, -2400, -1788, -1254, + 5265, 3198, 7088, 4522, 1292, -191, -15886, 2787, + 22, -1610, 184, 380, 521, 336, -158, 877, + 468, 6515, -756, -5484, 100, -464, 9244, -2726, + -1644, -2741, -5362, -1635, 894, -1849, 10118, -3264, + -4472, 1255, -3571, -437, -1050, 1505, -11178, -193, +-11513, -24, 719, 212, -1999, -725, 502, -1164, + -1060, -618, -91, -738, 740, -2254, -4635, 2700, + 95, -853, 1093, -11620, -968, 9492, -25, -664, + 367, 1105, 5501, -112, 7516, 10286, 821, -484, + 204, 1425, -3491, -1234, -4240, 3807, 2877, 1824, + 423, 466, -428, -845, -86, 13276, 8436, -690, + -688, 574, -2874, -552, 4540, 926, -5443, 629, + -395, 2090, -17468, 335, 2419, 1275, -3750, -1589, + 470, -1735, 330, 2532, 1094, -6218, -884, -236, + -9678, -9945, -447, 542, -728, -1922, 108, -2193, + -946, 3270, 2121, 2624, 1010, -10742, -102, 2813, +-13070, 1523, -1532, -1291, 420, -1999, 262, -1194, + -4226, -1450, -275, 83, 1168, 1590, -1517, -426, + -1424, 152, 676, 11463, 824, -2092, -1106, -11502, + -2327, -278, 2597, -11, 793, -118, 393, 580, + -499, -743, -77, -427, -408, -692, -29195, -247, + -2014, -922, 97, 581, 5469, -1419, -698, 1490, + -3814, -2818, -13816, 680, 3595, 1544, 2366, -3018, + 2479, 323, 346, -260, 337, 2730, 12214, -1118, +-11301, -3028, 212, -41, 1764, -580, 553, 5454, + -8, -366, -1202, 901, -796, -8350, 4380, -1452, + -300, 1152, 3058, -3476, -27, 13046, 34, -11438, + -1321, -1528, 13237, 114, 2514, 976, -571, -1192, + -2050, -1635, -964, 416, -23, -1083, -9, 32767, + -548, 556, -1217, -56, 325, 1048, -145, 202, + 1520, 44, 402, 400, -611, 8667, -1083, 1068, + 1224, -12031, 2318, -1109, 1266, 1306, 4673, 285, + -5603, 1555, -100, -1059, 403, -213, -680, -904, + 11443, 581, 12160, -638, 309, -65, 933, -2280, + 1958, 2642, 1808, 7945, -2088, 850, -428, 785, + -989, 1234, -1413, 745, -10756, 1943, -184, 3252, + -96, 932, -664, 13222, 11326, -1374, -327, 1901, + 1069, -1540, 104, -139, -904, 106, 1664, 925, + 46, 353, -835, -554, 1618, -956, -437, -727, + -3403, 1038, 968, 436, 46, -4385, 340, -16903, + -498, 47, -554, -399, -2418, -347, 358, 23280, + 234, -172, -338, 1058, -2172, -1, 1710, -64, + -583, -2224, -780, -637, 3500, 108, 1045, 828, + -728, 9466, -2487, -12773, 1924, -1158, 208, 49, + 136, 12055, 42, -1381, -375, -11534, -249, 1602, + 996, 204, -710, 4761, -511, -15761, 166, -1184, + -192, 50, -105, 890, -9566, 2062, -1536, 133, + -185, -643, -172, -894, -355, -16, -1395, 542, + 2160, -481, -1104, -793, 517, -20454, 698, -181, + -135, -434, 1677, -181, -415, -738, -1574, 1664, +-14058, 597, -12354, -460, -313, 1724, -686, 85, + -1162, -648, 865, 165, -225, -1947, 2818, -778, + -4010, 402, 686, 11170, -332, 10336, -757, 4794, + 2204, -477, -292, -366, 8412, -2476, 494, 510, + 10514, 769, 642, -441, 1079, 6954, 4246, -2272, + -290, -224, 1312, 398, 1536, -692, 330, 157, + -946, -100, -1830, 214, -25652, 1382, -1836, -440, + 110, -506, -438, -2370, 126, 562, -3515, 1014, + 8526, -1641, -2493, 4411, -9210, 2110, 625, 114, + 323, 2450, 2407, 682, 1999, -9424, 2480, 69, + -2091, -11845, -3684, -429, -1622, -919, -518, 70, + 1450, -3523, 5126, 5706, -1451, 2633, 820, -204, + 11338, -8014, 753, -103, 290, -923, 1408, 298, + -1962, -887, 9691, -1366, -11048, -55, -223, -1040, + -163, 132, 676, -760, 4990, -310, -9286, -2427, + 14442, -418, -802, -359, -323, 2877, -210, -1436, + 1574, -1206, 265, -155, -225, -32768, 347, 222, + -1165, 200, 924, 1135, -843, -66, -343, -334, + -113, 209, 14, -203, 1214, -896, 910, -1496, + 1831, -7833, -841, -10453, 1605, -8514, -477, -48, + -241, -58, -32768, 213, 108, 450, 1155, -30, + 89, 240, -768, 1332, 290, -1377, 951, 586, + -8939, 1298, 496, 705, -1661, 1798, -1906, -2233, + -1716, -986, -2204, -1149, 2686, 8578, 32767, 645, + -661, -135, 770, -432, -550, -385, -272, 625, + 1234, -729, 19, 1753, -284, -106, -655, 750, + -442, 23143, -328, -520, -506, 790, -1048, -730, + -471, -438, 483, -374, 939, -226, -397, -849, +-12054, -772, -40, -11776, 232, -540, -2497, -679, + 337, 1357, 458, -341, -7542, 1001, 492, -416, + -1496, -8966, 9814, -1752, -674, 2526, -544, -2900, + -1318, -1578, -238, 75, 11181, 1750, -3182, 564, + -570, 528, 1004, 146, 1144, 7430, 158, 9524, + -36, -340, -441, 596, -1659, 1420, -686, -36, + -596, 2215, -1295, -19722, -2149, -1046, -2339, -1166, + 3057, -370, -556, -33, -322, 260, -23, -106, + -323, 147, -57, 179, 458, 684, -1283, 1251, + 1231, -18548, -513, -480, -695, 593, 3072, 1960, + 322, -702, -1043, -544, 6005, 1378, 100, -225, + -848, -1294, -3346, 828, -2610, -3010, 9623, -1329, + 1956, -1098, -3730, 1137, 12413, -1260, 2457, -10844, + 6824, -4289, -653, -302, -4415, 650, -1684, 6129, + -370, -652, -3245, -473, -150, -3018, 1864, -1258, + 928, -2379, 14451, -119, 2282, -248, 3139, 6502, + 4318, 2214, -1627, 126, -422, 326, -622, -302, + 32252, -268, 456, -260, -260, -968, 391, -497, + 152, 1764, -10580, -369, 277, 70, -13137, -1114, + -1111, 464, 2266, -2968, 728, -1216, 1726, 1044, + 344, -16436, 1558, 3178, -551, 604, 442, -891, + 9570, 1596, -541, -2182, 730, -906, 242, 935 +}, + +.cb1616m1 = { + -116, -53, -24868, -544, -783, 97, -912, -1202, + -622, -147, -215, -362, -16, -522, -1694, -358, + -724, 2628, 439, -18106, -1566, 3048, 4133, -1238, + -3233, -1130, -2884, -2762, 1031, -1037, 63, -2219, + 10701, -1518, -10322, 1425, 792, -1820, 380, -777, + -3017, 1531, -1052, -3491, 1085, -428, -765, -113, + 42, -265, 365, 99, -859, 35, 610, 44, + -495, 262, 1689, 2082, 21605, 412, -717, -1163, + -3285, -5062, -1583, 599, -277, -62, 615, 6014, + -1781, 465, -544, -14114, 11277, -20, 696, 663, + 1156, -240, 631, -2802, 333, -2544, -1628, 775, + -960, -553, 496, -378, 526, -421, -426, 290, + 555, 403, 390, -31714, 25, 449, 654, -334, + -1317, 165, 496, 1554, -88, -777, 626, -1511, + -9020, -1725, 12705, -798, -1240, 195, 1932, -833, + -939, 43, 182, 2547, 4879, 9234, 370, 2058, + -7757, 544, 1106, -660, 546, 9983, 225, 124, + 952, -2153, -1732, 2760, -1270, -176, 3334, -6735, + -526, 10475, -627, 7835, -2263, 475, 731, 908, + 8264, 1605, -192, 5026, 2414, 5223, 595, 1093, + 2345, -796, 8663, 1028, 8188, -185, -1506, -3044, + -100, -1818, -6369, -170, 1728, -9249, 886, -2111, + -349, -1146, 2127, 11622, -8043, 2880, 2215, 1693, + -2303, 1698, 1121, -3575, -927, -716, 1940, 2514, +-11672, 1619, 916, -7, -585, 508, -1316, -972, + 778, 9774, -2126, 2368, -56, 6716, 1169, -3656, + -1330, 9530, -12158, 1188, -11426, -353, 945, -1941, + 1750, 962, -1133, 1793, 2318, -2641, 1109, 933, + 804, 505, 60, -1642, -2238, -2328, -1558, -1568, + -27, 952, 4, 1376, -862, -18404, -1828, 4107, + -454, 52, -1202, 1150, 686, -1950, -497, -10883, + 400, -422, 1734, -54, 11165, -3309, 6402, -877, +-19967, -400, 1642, 1305, -2432, -3115, 375, 3898, + 1812, -5305, -946, 1717, -757, 3322, 126, 747, + 1836, 9957, 1904, 658, 13043, -1779, 675, 716, + -453, 670, -1572, 210, -1533, -133, 294, 546, +-24084, -1036, -485, -117, -184, -624, 273, -901, + 866, 609, -1119, 28, 250, 13, 70, 1178, + 882, -632, -21624, -1339, 926, -1814, -1279, 1868, + -181, 383, -679, -1070, 5091, 1148, 1034, 2144, + -2779, -3810, 4536, 1713, 1003, 13322, 2866, -3217, + 2508, 4395, 480, 14, 167, 763, -34, 1034, + -1342, -1349, -100, -225, 464, -914, -1403, -1851, + 23767, 770, -457, -257, -1072, 1201, 583, -59, + 2627, 1469, -7, -11642, 3352, -1003, -6, 11588, + -311, -2435, -2180, -2352, 1952, 5532, 1945, 7281, + 504, 11882, -603, 45, 42, -1396, -1115, -1041, + -1061, 566, -2733, -765, 687, 118, -1174, -20412, + -244, -986, -151, 2888, 1102, -1303, -135, 529, + 1186, 13220, -183, 906, -4209, -4455, 2247, 246, + -6474, 2794, 1450, -6495, -1819, 598, -438, 244, + -1064, -673, -672, -1563, 543, -2278, -3087, -811, + 1866, 80, -18987, -682, 569, -551, 514, 6876, + 7582, 839, -4031, 823, 2342, -1300, 1180, 702, +-10168, -1957, 485, -374, -151, -11066, -461, -12824, + -1221, 1281, -718, 2012, 330, -289, -487, -207, + -722, 394, 156, -2023, -11006, -373, -4, -238, + 10581, 991, -1236, -814, 553, 1295, -2269, 2783, + -1973, 681, 9759, 3674, -1680, -12118, -1340, -2372, + -288, 2143, -328, 809, 312, 2038, 736, -10, + 908, -11319, 74, 6362, -1122, 1546, -184, 1630, + -1851, -2143, 1048, 8858, -462, -6458, -1540, 811, + 130, -3542, -10424, 9353, 388, 1168, -1797, 1796, + -4151, -2329, 1, -272, 846, -642, 248, -1144, + -9863, -1684, -190, 7611, -4147, -692, 5354, -2363, + 609, -4926, 3166, 2094, 857, -369, 118, 725, + -899, -601, -6, 556, -32540, 950, -478, 757, + 136, -560, -754, 562, -448, 223, -704, 616, + 365, 22610, 1191, -1264, -94, 927, -294, -1270, + -16, -2520, -2026, 420, -6621, -504, 9666, 452, + -379, -1888, 536, 1161, -3021, 609, -4890, -231, + 3926, -943, 32767, -615, 300, 870, -742, 429, + -42, 155, 1060, -900, -347, 34, 491, -3625, + -1529, 10175, 178, -7938, -406, 1628, -362, -7340, + -433, 489, 568, 674, 536, -2886, -6118, -16, + -531, 182, 1498, -4194, -306, 63, -1429, 1109, + 631, -10386, -16, -5938, -52, 10638, -793, 35, + -874, 1633, -252, 709, -286, -780, 17172, -32, + 912, 137, -1684, 2781, -5637, 338, 10961, 1401, + 176, 1890, 563, -371, 578, -235, -882, -616, + -591, -672, -821, 12194, 917, 778, -427, 358, + -1411, 2032, -1372, 1891, -1784, 1830, -1808, -464, + 13973, 2016, 8606, -914, -7329, -1853, -2627, 2219, + 2628, 2161, 2185, 2414, 8857, -273, 1016, 2253, + 1070, 907, 367, -430, 574, 1039, 93, 170, + 255, -267, 550, -668, 287, 1827, 19833, 244, + -3731, 4, 21365, -127, 356, 643, 2016, 3290, + 1242, 46, -734, -2298, -316, -6618, -296, -1465, + 657, -1451, 469, 212, 2823, -2803, -11862, 931, + 44, 660, 1576, 1848, -10529, 2813, -1163, -260, + -195, 16320, -3447, -262, -76, -439, -3487, 1292, + 3330, -616, 1477, 1900, 8843, 81, -846, 6845, + -95, -112, -231, 129, 6982, 165, -3115, 2456, + 2032, 12201, 2747, 1691, -728, -1935, -239, 968, + 15578, -2260, -1813, 440, 2188, -3845, 1278, -136, + -1388, -7850, -462, 2921, -1740, -136, 164, 103, + -206, 32767, -459, 1249, 736, -590, -797, 628, + 612, 327, 396, 552, -128, -76, -258, -557, + 429, 170, 532, -347, 169, -593, 28319, -633, + -1339, -997, -258, 324, 628, 3254, -1118, 8902, + -63, 4762, -2820, 2429, 820, -46, -5366, -2193, + -9005, -1304, -597, -10143, 555, -3000, 294, -1577, + -871, -140, 726, 3700, -2226, 903, -253, 10330, + -2946, 656, 725, -668, -920, 1653, 1312, 1623, + -1150, -11970, 2157, 4532, -340, -8648, -616, -1429, + -980, -30, 647, -474, 442, 5098, 188, -1258, + -8172, -10927, -4207, -112, 2501, -3241, -1949, 159, + -525, 1090, 420, 10418, -11897, 1072, -78, -1028, + 3367, -2647, 3421, 2021, 2358, -973, 272, 27911, + 472, -402, 1397, -927, -1032, -1274, 848, 221, + -2745, -710, -692, -409, 1922, 142, 594, 1053, +-11350, -791, 3767, 1569, 541, 11921, 134, 368, + -948, -2689, 896, -1193, 1190, 8514, 1436, 1017, + 599, -3358, 4002, 12936, -675, 1044, -1210, 296, + -1109, 1992, 1282, 774, -13102, -608, -11145, 134, + 278, 944, -888, 350, -1574, 189, -2542, 3476, + -3018, 3368, -9304, -1839, 533, -2, 1057, 686, +-11819, -1146, -973, 1594, 3526, -2890, -1528, 3489, + -475, -259, -9610, -475, -984, -3559, -742, 408, + -130, -2291, 899, 12177, -1934, -162, -3238, 1610 +}, + +.cb2220l0 = { +-12528, 350, 1782, -474, 1439, -14269, -8, -1782, + -753, -1720, 167, -440, -2706, 222, -1629, -288, + 671, -111, 10270, 878, 152, 330, -1000, 639, + -1280, 1111, -2072, 1439, -476, 553, -2974, -614, + 1666, -466, 11811, -1393, 154, 624, -697, 176, + 1108, 504, 250, 572, -6, 704, 16, 647, + -1143, -1407, -411, 23745, 319, -189, -404, -641, + -86, -707, -770, -302, 13, -398, 76, -681, + -525, 354, -1225, -757, -23170, -484, -965, -430, + 13477, 898, 505, -17, 13812, -890, 357, 662, + 1000, -935, -60, 944, 400, -432, -221, 1047, + 307, -180, 5260, 16509, 650, -269, 1563, -6002, + -3082, 186, -3334, -5770, 1010, -394, 128, -699, + 537, -27, 1014, -531, -50, -163, -1664, -1026, + 732, -1296, 21856, 574, 416, -745, -443, -1382, + 272, 791, 1308, -308, -1636, 168, -10922, 119, + -1190, 1123, 1492, 1706, 1076, -2016, 3270, -994, + 876, -2316, -2992, 12625, -412, -159, 5249, 1424, + -304, 557, -431, -360, -340, -561, -292, 1748, + -224, 1789, -352, 386, 136, 76, 1309, -270, +-24204, -515, 1142, 2119, 1144, -173, 1008, -693, + -430, -1052, 1890, -12483, -11416, 2918, 1591, -1202, + -1782, -1335, 1354, 1703, -510, 4287, -854, 1153, + 2018, -518, -960, 11825, 1295, -563, 11252, 190, + 4078, 222, -3115, 3306, 747, 2638, 1015, -1674, + 8032, -2386, 573, -349, -832, 96, 9564, 11708, + -483, 1326, 1804, -2903, -2024, -234, 1009, 3229, + -232, 803, 275, 444, -629, -192, 381, -1289, + -109, -29019, 270, -420, -408, -466, 113, -537, + -266, 296, 180, 506, 1015, -565, -517, 1494, +-11053, 3968, -1735, 3474, -1991, -8326, 8075, 1740, + -3995, -1287, -2558, 1030, 3742, -618, -2600, -1783, + 2696, 1480, 1054, 341, 3762, 4225, -1742, -11582, + 4348, -8756, 493, -404, 3840, -1049, -683, -962, + 163, 10997, -97, -848, -4632, 2794, 2684, 2540, + 739, 8534, 3688, -878, 3138, 2576, 6444, 3674, + -2371, -218, 2864, 12270, 2866, 189, 4549, 4894, + -6378, -1050, -3166, -5897, 2245, 2803, -70, -1909, + 2783, 3951, 153, 11221, -658, 12780, -238, 3418, + -2235, 754, 311, -739, -2414, 702, 1076, 303, + -320, 47, -3288, -234, -1376, 3022, -103, -1780, + 716, 11886, 10942, -5402, -5431, 1196, -624, -885, + -652, -3248, 74, -435, -686, 154, 8675, 3325, + -1779, -341, 564, -901, 1335, -639, 3494, -1820, + 290, -92, -3088, 4775, -2140, 2334, 710, 10536, +-15042, 14823, -1082, -1045, 1008, 734, 241, -1048, + -933, 245, 913, 114, 322, -1798, 246, 1067, + 348, 408, -183, -728, -12915, 685, 1525, 1694, + 183, -168, 12703, -1268, 1613, -2072, 1546, 743, + 2356, 2135, -550, -153, 1327, 2, 12487, -3111, + 2347, -1722, -300, -193, 2222, -1928, -658, -384, + -5738, -1141, 3634, 10312, -69, -1549, 10879, 1795, + -361, -1838, 143, 1202, 327, -15549, -1268, -194, + 3284, -12, -344, -2042, 1663, 334, -798, -873, + 1736, -324, 195, -417, -382, -22936, 812, -478, + -962, -451, 730, 382, -135, 1311, -290, 122, + 148, -775, -305, -32218, -84, 98, 374, 369, + -44, 923, -432, 156, -1471, 236, -39, 143, + -146, 835, 135, 229, -297, 1690, 6786, -12169, + 815, -176, 1868, -9, -3052, 108, 114, 260, + 11337, -2689, -132, 765, -239, 54, 691, -9737, + -627, -474, 12212, 2222, -7595, -239, 1793, 2115, + 563, -2390, -1991, 2906, 675, 923, 146, -3605, + 981, -1725, 92, -562, -21192, 304, -450, -323, + -889, -726, 688, -1186, 2590, 466, 326, -734, + 308, -782, -3219, 963, 454, 1348, -513, 953, + -1414, -320, 1012, -1148, 1185, -17356, -15, 1546, + 1346, 2182, -2457, 1426, -1690, 155, 8793, 1394, + 510, 2608, -203, 2697, 608, 2612, -13542, 177, + 4642, -824, 1877, -1864, 1681, -1033, 1487, -749, + 356, -11, -1, -366, -215, 1531, -38, -922, + -378, -296, 1245, 19967, -2389, -459, -3729, -163, + 6578, 354, -1471, 195, 353, 1831, -605, -2291, + -359, 947, 8409, 3454, 12416, 2434, 3485, 40, + 350, 1640, 738, -9827, 935, -171, -944, 1407, + -399, 571, 2805, -13108, 784, 678, 2405, 328, + -417, 1188, -1596, -649, -1358, -1130, 341, 202, + -2459, 11307, -2250, -3518, -1812, 3338, -924, 10027, + 3004, 703, -184, -666, 223, -1644, -7221, 3507, + 10108, 1324, -412, -371, -92, 2496, 3182, 10, + 10269, -998, -1010, 610, 3296, -1842, 407, 406, + -1609, -181, 2202, -662, -1450, 1360, 1488, -212, + 1501, -214, -555, 168, 275, 301, -950, 3272, + -323, 20632, -21, -1729, 11013, 2149, -9278, 6735, + -593, -7374, -430, -2776, 2343, -1374, 519, -4876, + 827, -2477, -1971, 1249, -23380, -1810, 199, -761, + 2182, 1654, 447, -488, -1219, 364, -53, -382, + -989, 154, -545, -872, 776, -211, 7706, -767, + 8006, -138, 1989, -180, 306, 486, 1112, -648, + -12, 1538, -300, 2458, -5833, -1181, -7680, -6700, + -621, -308, -29995, 602, -24, 94, 752, 517, + 86, -249, 1058, 704, -404, -387, 106, -632, + -159, 1275, -197, -1263, -1210, -1689, -10488, 1950, + -2037, 5974, -3960, 38, 1284, 2851, -2813, -1613, + -1646, 10164, 138, -2956, 196, -118, -484, 860, + 124, -262, 30, -1448, 128, 287, 327, 590, + 27272, 391, -738, -1631, -481, -1511, 82, -574, + -737, -614, -447, -80, 292, -19, 252, -2, +-28117, 332, 141, 1485, -154, 1382, -1755, -422, + -1692, -2144, 910, 1004, 1894, -1537, 897, -458, + 19483, -1321, 2280, 622, 288, -2253, -1001, -976, + -408, -394, 132, -250, -428, -22, 140, 287, + -141, 30981, -293, 631, 729, -2, -231, -127, + 377, -879, -294, -107, 253, -964, 1258, 570, + 71, 9421, 8358, 9295, 8354, -546, 1153, -1807, + 1577, 2911, -1808, 1808, -1631, -1348, -6977, -382, + 1625, -2793, 10633, 1977, -1793, -12480, 1, 2010, + 23, 423, 1102, -1920, -478, 1845, 1016, 465, + 758, 800, -1540, 5448, -10472, -2749, -989, -6362, + 9283, 373, -2560, -5478, -1618, 20, -564, -1074, + 4075, -471, -515, 409, -2069, 359, -788, -11618, + 2524, 917, 2757, 243, -3261, 6922, 6268, -3148, + -2804, -3412, -4262, -1903, 1043, -12255, -162, 1598, + 496, 454, 1401, -1635, -12711, -673, 3392, 1255, + 1602, -1206, -297, -2066, 3009, 1149, 1285, -1307, + 412, 27971, 183, 569, 1304, -706, 824, -635, + -358, -340, -28, -1344, 955, 14, 676, -243, + -20, -11947, 1350, 8122, 196, -10161, 4925, -3764, + 1661, -401, 145, 253, 680, 718, -614, -613, + 498, -293, -4257, -684, -14853, -10522, 698, 1537, + -2016, 1162, -2684, -1578, 8, -238, -3214, -2749, + -1577, -1187, 113, -1457, 1068, 590, 25, -644, + 1000, 2430, -1612, 13246, -2684, -1642, -4648, 816, + -1103, -7556, 5753, -3998, -1338, -776, -1958, -9652, + -1288, -290, -4240, -2788, -8191, 1625, 2558, 1238, + -1824, -39, -3129, -8916, -3302, -5632, -1768, 866, + 708, 684, 3530, -8772, 1485, 677, -10398, 686, + -852, -6974, 5286, -2658, 612, 1180, -3367, 4285, + 5708, 1416, 166, 2787, -3697, 1431, 1648, 7942, + -544, -1064, -514, -840, -870, 1246, -3582, -9310, + -3802, 4025, -8251, 5978, 132, -619, 2792, 9786, + 1244, 242, -1948, -4701, -5904, 951, 7486, -3494, + 48, -4468, -2403, 6090, -2343, -4175, 1336, -2546, + -281, -736, -1758, -1720, 11066, -918, -1354, 3885, + -33, -4116, 1246, -218, -8082, -766, 7796, 1505, + 1559, -964, 1741, -454, -1628, -762, 3034, -804, + -888, -9682, 9603, -2556, 2874, -5456, 3066, -7747, + 956, -660, -1538, -381, -760, 1747, 547, -517, + -697, -1411, 410, -514, -3988, -219, 13358, -2393, + -280, 11230, 2640, 795, 2534, -8094, -1838, 71, + 16, -203, 4224, -96, -2829, 2010, 1961, -1312, + -1266, 3952, 6894, 6996, -8062, 4708, 1193, -3439, + 1549, 935, 170, 614, -868, 43, -246, -188, + -940, 130, 126, -736, 697, -510, -56, 1596 +}, + +.cb2220l1 = { +-13582, 1049, 15596, -101, 707, 2677, 542, -522, + -636, 194, -2361, -1252, 524, -32, 227, -419, + -652, -601, 84, -10428, -1417, 13117, -573, 3774, + -3632, 2025, -1237, -692, -1486, 192, 1221, 452, + 436, -764, -2636, -153, -685, 118, -424, -635, + -458, 209, -577, -12042, 4240, -10861, 49, -1534, + -991, -2416, -280, 2095, -1841, 1278, -94, -423, + -572, -949, 734, -1087, 12449, 6514, -4582, -7845, + -3722, 1446, 2531, -1238, -2070, 1515, -1331, 2382, + 1066, -1298, -1189, 6811, -1868, -1082, -1732, 356, + -2622, 493, -3345, 1367, 1737, 4497, -14734, -1350, + -354, -1340, 8478, -1152, 1832, 1793, 830, 974, +-13918, 522, -1472, -2502, -2625, -157, -360, -17, + -830, 673, 36, -1339, -14860, 522, -13377, 851, + 937, -1103, -44, 408, -364, -953, -392, 1837, + 2342, 1236, 111, -218, -919, 985, 10077, -1065, + 1840, -124, 3780, -11015, 204, 437, -830, 6712, + -1720, 288, -991, 1094, 5647, -1296, -2284, 1642, + 1000, -35, -115, 208, -244, -1099, -832, -2092, + 802, -163, 3343, -964, 314, 126, -1204, 754, +-17838, -826, 4414, 8331, -770, 1246, -3500, 1680, + 833, -108, 494, -910, -6314, -2832, 2553, -6230, + 1165, 3631, -1717, 2404, -32768, 520, -38, 1228, + -708, 58, 260, 771, 588, -448, 389, 156, + 606, -830, 400, -488, -188, 536, -1428, 11982, + -156, -1407, 1796, 1036, 905, 1371, -1472, 325, + 3098, -1436, 6449, 2105, -11183, 1632, -1848, 1019, + 1247, 1308, -1351, -823, 1679, -651, 978, 296, + 1088, 3965, -1414, -11838, 139, 8664, -3452, -1804, + 3088, -2044, -221, -1347, 1232, -909, -1323, -1409, + 1399, 2557, 14552, 1535, -5088, 1699, 1012, 3333, + 3940, 2294, 1189, -2256, -484, -3307, -1333, 464, + -305, -744, -24, -20464, 332, 2968, 308, -649, + 292, -402, 1226, -2575, -1505, -100, 1413, 733, + -1024, 616, -121, -322, 67, -161, -708, 251, + 462, -26697, -1112, -1381, -324, -286, 1091, 662, + 15830, 13124, -1049, -1816, -355, 1848, -801, -1710, + 2513, 458, -798, 386, -726, -356, -1240, -1133, + -388, 631, 91, 1867, 2511, -306, 3097, 14399, + -571, 2191, -2916, 2850, 761, -2442, 698, -2193, + -2739, -1914, -4077, -4631, 12702, 333, 1162, -6248, +-12466, -310, -107, -2465, -163, 1970, -998, -1253, + 2007, 79, -426, -276, 365, 568, -520, 23642, + 276, 1059, 184, 1081, 650, 2286, -191, 883, + -1946, 246, 64, -225, 800, 910, -136, 1187, + 955, -15604, 12847, -747, 874, 506, -646, 1920, + -449, -321, 1152, 1341, 1653, 341, -32, 907, + 673, 1045, 1245, -499, -10331, 4683, -1121, -3164, + 3382, 6397, -1341, -769, 1186, 229, -1354, -7370, + 155, 1858, 5617, -3487, -247, -783, 724, 508, + 14029, -528, 1853, 1572, 580, -708, 528, -1394, + 8922, 2284, 550, 3084, -1726, -3235, -700, 7132, + -3540, -200, 3288, -815, -2189, 1232, 2412, 2088, + -1101, 12592, 806, 1508, 1741, 13, 1124, -3883, + -687, -8180, -3094, -3346, 1781, 11836, -657, -3469, + 1429, -1822, -3433, 87, 3871, 651, -965, -1757, + 6778, 109, 112, -131, 710, 11943, -12107, -3460, + -726, 1002, -3803, 580, 2756, -1293, 116, 457, + 581, 3834, -1678, -977, 1242, -2040, 232, -10034, + 1644, -2290, 1368, 172, -3012, 1423, -2620, 3608, +-10831, -303, -1610, 3246, 562, 5212, 448, -877, + 954, 688, -8981, 579, 717, 1315, -952, 6817, + 662, 3218, 7213, -2116, 10446, 1012, 2270, -858, + 10, -1066, 10618, 6108, -547, 3221, -893, 3888, + -1088, -10085, -247, 1064, -3500, 3123, -2480, -2128, + 2788, -2253, -9756, -472, -166, -680, 727, 74, +-14151, -189, -1734, 610, -1169, 845, 94, -786, + 394, -581, 500, 1981, -10940, 354, 500, 399, + -1952, -373, 2197, -4712, -2582, 2751, 654, 613, + -1254, 1406, 2056, -12518, 1583, -582, 4834, -1541, + 508, -20580, 270, 1214, 515, -1082, 5, 7, + -533, -28, 1270, -1307, 497, -57, -331, 933, + 92, -856, -10458, -4576, -9991, 2426, 6552, -3022, + 279, -562, -192, 1878, -2237, 4978, -1753, 332, + -1462, -853, 238, 478, 9746, -7385, -10290, -8278, + 457, 3121, 841, 48, -3745, -1298, -637, -1820, + -468, -248, 1400, 394, -125, -950, 11524, -1860, + 426, -773, 12669, -1620, -158, 1625, 1045, 768, + -66, -12, 1625, -770, 559, 54, 593, 14468, + 14994, 490, 543, -811, 700, -277, 900, -178, + -2000, 475, 241, 950, 106, -1260, 874, -862, + 18907, -1947, -844, 205, 1253, -83, 1966, 2300, + -2694, 852, 2450, 661, -334, -518, -1136, -2377, + 325, 1152, 511, 881, -22205, 898, 574, -582, + -265, -1362, -253, -40, -780, -1967, 469, 1484, + -818, -926, 958, -415, -7934, -330, 330, 1439, + 1643, 77, 1034, -156, -12094, 3782, -5725, -520, + -598, 2345, 3506, 5333, -322, 99, -48, 1490, + 20, 11393, 3468, -1144, 7013, -3728, 7145, 1432, + 1810, 26, -912, -6530, -1079, 1771, 95, 4007, +-11346, -43, 249, -14616, -249, 1, -725, 244, + 1053, 1815, -626, 408, -344, 1972, 2222, 2288, + -2324, -411, -3993, 494, -706, -5078, -11695, -3645, + -2090, 2465, 5893, -5096, 6815, -537, 5003, 1258, + 185, -1555, -875, -2047, -170, -433, -194, -1020, + 349, -724, -31811, 197, 251, -418, -222, -618, + 278, 554, 363, 183, -898, 14, 350, 745, + -2054, -1623, 806, -770, -1246, 1594, -54, -18501, + 1516, 840, -86, 484, 514, 1209, 978, 564, + -537, 34, -431, 128, 938, -1807, 832, -90, +-29509, -642, 1397, -52, 523, -393, 216, 908, + 9, -63, 710, -949, 3, -184, 175, 613, + -687, -408, 27, -855, 18258, 1282, -948, -219, + 2374, 1668, -4567, 1063, -2045, 12026, 461, 3074, + 1050, -1788, 169, -13442, 612, 19, -2019, 685, + 452, -152, 299, 310, -2327, 348, -215, 1634, + -201, 2162, -10300, 12452, -3733, -420, 2388, 518, + -2308, -160, 1552, 3347, 1650, 3293, -1108, 2065, +-12618, 20, -42, -643, 202, -1298, 251, 2489, + 1322, 2362, 3698, -190, 592, -12484, -937, 2072, + 1531, 302, -409, -899, -1016, -388, 1103, 30006, + 789, -1609, -548, -1002, 1055, 605, -955, 1557, + 452, -623, 810, 597, -696, 10628, -1174, 606, + 2628, -553, -2297, 6668, -2600, 787, 3504, -3606, + 4087, 1052, 6276, -7619, 337, 2565, -13, 1205, + -124, 1222, -28082, -79, -553, 628, 542, 1315, + -609, 322, -895, -377, -694, 610, 239, -152, + -2901, 9890, 716, 1030, -3306, 988, -738, 562, + -2209, -1676, 4507, 1165, -12924, 866, -154, 3664, + -367, -2580, -7286, -572, 2167, 118, 508, -4429, + -480, 842, 2489, -1636, -2042, 1125, 1847, 2586, + -5639, 3361, -760, 11189, 623, -282, 1353, -279, + 515, -816, 713, 322, 417, -2820, -1114, -1563, + 401, -21604, -1300, -972, -2298, -483, 2176, -830, + 2135, -4084, 1095, 1950, -1937, 539, -374, 3197, + 682, 472, -1368, -8095, -12026, 4833, 5586, 467, + 2400, 148, 381, -138, 954, -459, -724, 970, + 156, -1955, -1363, 560, -761, -1708, -1599, -17408, + -1064, -1372, -500, 1160, 735, 441, -773, -228, + 420, -1128, 260, 930, 12879, -926, -231, 1355, + -850, 559, 11377, -1729, 2478, 961, 336, 1056, + 5081, 9788, -555, 4067, 8664, -2720, -1462, 3012, + -7280, 965, 1462, -4703, 3649, 2084, -699, -262, + 408, -188, 2193, -2216, -4509, -736, -1039, -4848, + -8243, -7958, -172, -1318, 9566, 4665, 3363, -3672, + 1581, -551, -2024, 1630, 1543, 90, -1728, -792, + -1799, 2571, 80, -412, -301, -2870, 1796, -5327, + 111, 17342, 592, -2108, 477, 1541, 1266, -1062, + -215, -2210, 223, 1215, -197, 87, -18340, -67, + 804, -398, -118, -3457, -741, -1935, -704, -274, + 566, -872, -1821, 12874, 5057, 2069, 1742, -6205, + -6115, -1614, -294, 187, -5210, 1734, -1466, -2162, + -2266, -642, -148, 440, 2, 233, -319, -637, + -734, -230, 301, 508, -433, 311, -313, -1206 +}, + +.cb2220s0 = { +-15119, 7508, 1337, 4182, -2914, -3733, 2686, -470, + 2249, -3901, 1444, 3805, 99, -1771, -354, -903, + -2755, -709, -4980, 214, -2750, -652, -1042, 1434, + -1090, -612, -2574, 1274, 1310, -760, 1420, -112, + 2776, -4843, 15060, -4929, -3942, -5721, -1628, -1142, + 3023, -1435, 1402, 1010, 623, -3527, 2624, 184, + 988, 98, 340, 16676, -1262, -1162, 3183, -4816, + -592, 1019, -1406, -2478, 2371, -1004, 3944, 803, + 5665, -2261, 16427, 349, 3113, -916, 442, -1754, + -3551, -1351, 1563, -1316, 532, 343, -392, 1509, + -717, -122, 2462, -929, -185, -683, -18780, 2682, + -123, 518, -379, -5160, 245, 1940, 13964, -12311, + 590, -30, 159, -1558, -1940, 36, -1528, -515, + -1178, 856, -395, 29, -5854, -12943, 13286, -2572, + 1049, 768, 3292, -3921, -52, -462, 1968, 4933, + 630, 930, 1026, 2606, 319, -277, 6333, -2119, + -4700, 2164, 1583, 154, 2107, -1467, 339, 634, +-17240, -595, -3525, -2690, -1788, -476, -41, 165, + -1016, -1456, -348, 11289, -2920, -3804, 2357, 12012, + 3848, 1796, 2164, -5555, 4527, -201, 965, -4893, + 3419, 6441, 1691, -77, 348, -769, 27319, -345, + -336, -541, -320, 972, 926, -1026, 1052, 702, + 224, 76, 742, 220, 6292, 8625, -3742, 4139, + -5989, -5615, -641, -231, -837, 6156, 4141, 3792, + 4746, 9972, 1800, -397, -2237, -2218, -7595, -2761, + -496, -1451, 1178, -970, -1226, 2527, -2105, 1778, + 1446, 1986, 9970, -13107, -985, -1142, -1367, -329, + -4498, 590, 36, 2073, -1069, 862, 133, 2516, + -27, 4494, -11602, -1638, 2524, 1449, 5684, -611, + -9452, -2618, 5006, 3481, -639, 379, -2333, -498, + -713, 382, 784, 269, -5692, -350, 524, -18705, + -1042, -1349, 1210, 1770, 3964, 4908, -1131, 17535, + -788, -1896, 30, -2682, 1044, 1604, -3740, 18, + 1771, 331, 4279, 2634, -368, -447, -6995, -1224, + -688, -5368, -236, -8872, 2449, -12189, 4465, 1895, + 2484, 1315, -5446, -457, -575, 101, 2356, -1585, + 3204, -104, -7244, -1678, -801, -2620, -4603, -11876, + -1787, 2962, -1796, -3385, -411, 5796, 2900, -562, + 835, 293, 7127, 4939, 721, -2972, -482, 121, + -2694, -2277, 412, 12770, -342, 718, 3306, 502, + -7281, -307, 552, 7158, 3289, -5051, 5230, -1185, + 3024, -942, -1347, -283, -13937, -208, 2576, -906, + 1848, 5692, -2434, 175, 7837, 1872, -4536, -3341, + -957, 14787, -1598, 9058, 3776, 407, -1734, 1259, + -3011, -131, -3589, -614, 272, -2968, -1611, 3645, + -8126, 2120, 4868, -5462, -13235, -3452, -6077, 5064, + -1593, -1395, -2427, -1139, -958, 1585, -1330, 2178, + -778, 3545, 2836, 7712, 5993, -432, 3575, 929, + -7951, 115, 2180, 3904, -193, 1556, -252, -913, + 2574, 11948, -4525, 1391, -8513, 4540, -12815, -3379, + -4676, 1838, -5676, 1321, -6168, 1397, 1020, 438, + -141, 3424, 392, -512, -1614, -1396, -318, -2451, + 1545, -7132, -1763, -424, 3575, -828, 19216, 1978, + 1624, -1969, -1667, -772, -2031, -781, 1732, 244, + -212, 416, 900, -8960, 1002, -1077, 4667, -3527, + 1586, -13109, -2442, 3829, 4358, 1056, 2960, -1087, + -662, 4775, -6316, 6157, -3736, -2040, -187, 904, + 1254, -636, 2032, -734, -1271, -2691, 3376, 564, + -7769, -5482, 840, 14171, -5828, -966, 1685, -10192, + -388, -434, 3706, 594, 2188, 365, 209, 298, + 1825, -236, 12762, 1644, 3199, -468, 12876, 130, + -2169, -3406, -3571, -4655, 2339, 10757, 1292, 2920, + 289, -314, -591, -1631, -1778, -1296, -254, 469, + -9408, 1154, 334, -4, -1922, 2787, 317, 416, + -1703, 14075, 1601, 638, -2260, -973, -824, 2816, + -2954, 3282, -3716, -882, -3447, 3058, -6701, 1233, + 177, 3579, 3508, -3539, -10511, 7507, 7608, -1928, + 2482, -719, 2278, 5167, 9828, 10572, -3635, -2750, + 3407, -116, 3343, -3432, -3375, 982, 903, -3239, + -444, -1574, -333, 9613, -1914, -532, 1879, -78, +-17944, -7029, 1586, -3122, 360, -401, 1219, -2086, + 3066, 878, 5780, -948, 102, 1952, 418, -416, + 1002, 1380, 1297, -92, -640, -555, -1159, -28517, + -1757, -696, 124, -618, 1590, 300, -598, 924, + -190, -1734, -4196, -5345, -14068, 5971, 8293, -3878, + -1448, -1777, -174, 921, -1555, -866, 560, 232, + -1914, -4002, -772, 1960, -4945, 3424, 6492, 3675, + -800, 5346, 4404, -639, 10697, 1631, -1446, -4469, + -7804, 3721, 4824, -620, 1099, -2956, 5175, -2453, + -4894, 2562, -1842, 4940, 1391, 2818, 1095, -4285, + 6469, -1966, -14564, -2232, 592, 5570, -2682, 2651, + 4678, -7444, -2387, 6812, -12757, -5664, -42, 134, + -2861, -1780, -158, 1410, -4990, 673, 2083, -2639, + 3019, -2, 8305, -1981, -2114, -54, 2892, 1659, +-14913, -74, -1092, -1187, 2465, -2218, 791, -608, + 3077, 26, -1096, -1692, 3234, -7116, -1835, -5244, + 398, 10137, 698, 2298, 498, 7060, 6430, 1393, + 2540, 487, -1534, -1926, -5139, 3425, 4533, 5067, + -535, -924, 938, -1799, 16120, 2037, -3727, -821, + 2986, 2314, -223, 1358, 9, 2697, -1806, -940, + -3630, -1843, -2776, -2246, 580, -1678, 2427, 2126, + -1935, 2956, 849, 18234, 638, 342, 1036, 249, + -24, 2713, -1973, -134, -4469, -2014, -6162, -19776, + 703, -50, 2295, -2294, 1971, 1179, 1014, 2374, + -1480, 1513, 630, 1542, 24716, 3534, 2926, 662, + -2886, -521, -348, 402, 1112, -371, 1587, 1822, + 1880, 1284, 302, 1873, 1284, -924, 6420, 4650, + 7986, 427, 361, -8276, 304, -11911, -1305, -2018, + 189, 258, 839, -942, 479, -3162, -1195, -1138, + 1560, -1850, -5304, -10132, -10533, -1301, -3147, -680, + 56, 4260, -6867, -1350, -1094, -1385, 1831, -2, + -941, 3740, 7701, -855, 3304, 3444, -4467, 269, + -4092, 588, 13957, -1566, -3561, 1936, 2816, 2982, + 1804, 2710, 419, 685, 4468, 488, -9520, -2738, + 3974, -9978, -1681, -2418, 2340, -717, -899, -2855, +-10470, 1030, -2346, -5555, 2559, 2180, -5324, 1832, + 10294, 342, 11318, -2376, -3904, -1524, -3806, 1078, + -1896, 7199, -3522, 1364, 2291, -911, -156, -4327, + -778, -30451, -577, -158, 560, 2749, 799, 2689, + 337, -301, -1218, 1243, 687, -880, -419, 40, + -280, 4, 1834, 9908, 1953, 408, 1080, 8777, + 3861, 552, -6906, -3546, -6666, 35, -1903, 4788, + 5080, 2865, -233, 1031, -4519, -13752, -2417, -1742, + -7389, 3191, -626, -411, -7351, 3063, -1801, -4377, + -2974, -124, 2778, 2733, 349, -1191, -6528, -1699, + 6907, 239, -2765, -5706, 3627, 2096, -20, 2285, + 7164, 3523, -11582, 3616, -614, 6266, -285, 3643, + 1506, 3665, 1261, -2338, 418, -5062, 4893, 2945, + 1923, -2990, -4531, -8858, 2769, -5029, 2202, 3337, + 10703, 716, 5614, -14982, -2366, -5415, 25, -1665, + 4353, 3060, -2159, 1005, -1587, -368, -949, -2788, + 1063, 1307, -59, -46, -6337, 500, -1194, 2914, + 2372, -1393, -1914, 3820, -1160, -135, 3777, -14151, + 5208, -2290, 5738, 1018, 385, 1883, -2626, -9289, + 1082, 1558, -1756, 2720, -519, -13050, -3672, 1759, + -13, 3471, 4071, -5977, 167, -4210, 2219, 1344, + -2412, 4497, -6946, 660, 8774, -3141, 6080, -4478, + 2520, -609, -3080, -741, 7864, 7428, -333, 1154, + -1849, 1478, 460, -338, -6651, -2480, 1692, 2104, + 1642, 2720, 1017, 2759, -1822, -2668, -2265, -1019, + -8926, 1487, 733, -15128, 5543, -4214, -7044, 666, + 7108, 2222, -2454, 4995, 5108, 1481, 2242, 5743, + -487, 9669, 295, 3539, 4836, 487, -1541, 824, + -5946, 6692, -368, -1390, -6103, 4545, 2671, -12272, + 3160, 760, -2080, 3523, -2752, -2940, -718, 2202, + -5523, 2346, -5580, -5007, 6212, -5406, -11348, 1272, + 5389, 2331, 3691, -1184, -3585, -4500, -603, -38, + -5285, -531, 4844, -3850, 3944, -6525, -5723, -2313, + -985, 879, 578, -3217, -3600, -2814, 1432, 11568, + -1461, -1761, -4110, -4104, -103, -1803, 5195, -1477, + 1348, 107, 3902, 1215, 3522, -3404, 9098, -237, + 68, 34, -2524, -12040, -6183, 2122, 470, -1257, + 346, -232, -1725, 5913, -1525, -5873, 1846, -11368, + 1043, -1027, 4201, -3864, -4294, 7756, 1847, -3688 +}, + +.cb2220s1 = { + 32767, -2256, 16, 2156, 267, 1128, 1394, -1936, + -488, -405, -345, 1068, 578, 1504, -1192, -405, + 292, 1149, 4243, 152, 1036, 1782, 2655, -23349, + -1100, -1933, 354, 966, -1554, 1173, -1186, 495, + 618, 1009, -2715, 461, 5974, 939, 3552, 1325, + 3385, -956, 2177, 2101, -145, -1000, 2326, 2466, + 2822, 15822, -581, -713, 4398, 828, -3249, -3942, + 1990, -862, 2272, 348, -2972, 241, -2678, -1881, +-22307, 417, -587, 312, 280, -2524, 2380, 299, + 3931, 178, 2910, -2544, -356, -786, 546, -73, + -862, 240, -1653, 1286, -3875, -2072, -1477, 16800, + -1148, 2099, 3216, 5174, 2177, 3042, -796, 414, + -506, 883, 1837, 1451, 2864, 850, 2395, -414, + 3254, -1937, -16379, -3976, 2178, -1473, 4759, -832, + 8890, 3324, -3053, -407, -1530, -431, -1220, 128, + -3472, 980, 52, -14716, 1732, 1931, -6518, -1784, +-11113, 4466, -24, -8559, 105, 5478, -4116, -2213, + -3006, 1738, -4189, 3310, -753, 1869, 580, -885, + 3089, 8146, -4990, -1825, -524, 3620, -6920, 621, + -1064, 4633, -1509, 80, -10949, -2752, 476, -3684, + 3547, -1967, 3364, 2887, -729, 7921, -4216, -3681, +-14417, -3978, 261, -1146, -1124, -901, 777, 783, + -2, -989, -1582, 3988, 7785, -6371, -2258, 3344, + 354, 13289, 3339, 316, -3186, -2088, -1951, 310, + -545, -704, -40, 4416, -392, -1033, 5650, 99, + -3008, -3716, 2448, -3758, 9463, -1793, -130, 1705, + 6501, -2214, 2970, -10476, 564, -5952, -541, 2077, + -90, 6588, -2858, -1733, -9247, -345, -3170, 4986, + 3353, -4868, 8873, 113, -5223, 1562, -163, -2446, + -4459, -8052, 1106, -10883, 1185, -1756, -152, 3109, + 181, -1427, 8291, 11419, -6265, 2116, -469, 5150, + 1355, 182, -740, 779, -7754, 1868, 144, 3936, + -60, -784, -231, 879, 17032, -2273, 1886, -538, + 1015, 1798, -633, 1090, 1910, 128, -6094, -1946, + -1570, -727, -18457, 498, 784, -4419, 1656, -21, + 154, 2430, 3815, -41, -2708, -1594, 228, -784, + 7284, -452, -7634, -12868, 3564, 5473, -1244, 2231, + 28, 4321, -1464, 1402, -1358, 2241, 656, -1128, + 1160, -2352, 3641, -680, 1816, 6864, -42, 1269, + -280, -1265, -2048, 238, -653, 13571, 3874, -269, + 7977, 2238, -1246, -2066, 4741, 1706, 3498, 595, + 2559, 55, 593, 1681, 1612, 43, -2756, 2702, + 2439, -2471, -809, 1890, 17032, -787, -4280, 1167, + -1926, -4973, -1181, -2764, -4151, 2962, 3444, 844, + 2446, 14013, 3326, -1195, -1829, 1588, 1765, -3140, + 8562, -14425, 4040, 2003, -738, -1032, -3314, -2236, + 548, 768, -2348, 436, 1755, 31, -4616, 1259, + 269, 1543, -1393, 5338, -16463, 2900, -2480, 1659, + 217, -5864, 3878, 5268, 1244, -520, -1202, 1238, + 182, -1049, -695, -320, -6832, -5904, 2914, -2616, + 2586, -10958, -3258, -1846, -4633, 2371, 3251, -3583, + 2631, -4162, 3035, 2718, 616, 2890, 206, 16128, + 979, 3551, -6864, -3221, 5881, 3692, 1718, 234, + -2844, 1668, 102, 2687, -838, 988, 1116, 533, + 4026, -7235, 5972, -13781, -3394, -3518, -294, -6383, + 1675, 4507, 5444, 385, -1931, 930, 699, 1639, + 415, 6720, 7854, 1514, 3192, -2253, -14786, -1307, + 871, 1329, 1881, 6628, 2851, -85, -2284, -4538, + -837, -2232, 269, -2227, 13930, -2063, -7540, 8978, + 1195, 2717, -1282, -972, 1305, 3864, 2412, 2308, + -4824, -3282, -864, -489, -1458, 2192, 15903, 2460, + 2792, -4137, 1034, -359, 5, 2297, -6, -3859, + 478, -1535, 2080, -741, 2030, -603, -2640, -1902, + -8208, 3818, -1273, -8138, 2015, 9169, -3440, -1779, + 4076, -576, -93, -1718, 744, 2563, 6744, -3841, + 1355, 1590, -4196, -13924, 356, 13381, 2552, -2862, + 2790, -578, 3562, 2711, -686, -3783, -489, 1230, + 896, 1208, -1101, -3482, -2478, 772, 1254, 320, + -1825, -327, 1070, -1712, 295, -18141, -2618, 1537, + -603, 3782, -1272, -1901, 414, 169, -6574, -6966, + 2711, -3292, 13204, -1324, 3620, 4962, 2835, 4177, + 4861, -2378, -5534, 3701, -4224, -631, -3199, -653, + 4785, -1045, -2097, 580, 2190, -140, 48, 3075, + -1346, -810, 2016, 566, -2543, 235, -5930, 1956, + 481, 19003, -3938, 6489, 2697, 4796, 3435, 7102, + 3062, 1460, -5814, 2723, 4181, -4979, -2534, -2058, + -136, 3554, -2684, 15252, 4112, -3146, 2812, 7182, + -2642, 5443, -1043, -803, 2786, -1622, 1988, -780, + 1482, -13015, -1762, -1377, -4005, 161, -9568, 8166, + 1832, 330, -6484, 945, -4388, 1090, -524, 1556, + -582, 320, 770, -938, -8757, 977, 1084, -7062, + 3552, 775, -4708, -2281, -552, -10027, 4263, 1197, + -672, -93, 5716, -3825, -4526, 1781, 9799, 4450, + 1981, -3149, -9664, 3119, 3794, -91, 6710, 840, + -1098, 11310, -2933, 785, -2573, 748, 1803, -1401, + -1547, -4118, 849, -580, -1404, 1536, -9382, -1610, + 2335, 403, -2939, -3015, -3753, -7593, 1640, 3346, + -2594, -8028, 5485, 2189, -3369, 2106, 5369, -2573, + -515, 1459, 6996, 1344, -389, -7009, 10332, -840, + -3869, 901, -6449, -2348, -2461, -4103, -810, -2060, + 1040, 117, 32241, -231, 945, 999, -1183, 180, + 1443, 188, 855, -1634, 774, -202, 99, 1714, + 286, -849, 1968, -9743, -15458, -859, -3726, 2257, + 355, -167, -1674, 1808, -488, 1118, -1416, -1685, + 2928, 1471, -1145, -536, 2307, -972, -1191, 1625, + -1436, 378, 20178, -638, 1826, 472, -300, -845, + -1045, 1074, -1041, -510, -39, 516, 4548, 2741, +-10197, -2336, 3828, 2093, -4148, -9138, 4239, 2520, + -3536, -3807, 2998, -2226, -6898, 4838, 2552, -2024, + -5579, 1370, 11706, -7626, 1566, 989, -4934, -1345, + -5962, 4259, 1158, -3712, -2710, -1037, 105, -2733, + 1068, 3682, 3904, 2044, 184, 537, -3438, -1376, + 332, 17812, -3170, 2386, -2090, 3481, -1352, 431, + -1016, -1062, -564, -1752, -2602, 1299, 6720, 789, + 1275, -9801, 5320, 2327, -4048, 4443, -7820, 1112, + 1232, -1139, -920, -744, -845, -3754, 5958, -5388, + 3336, -3578, -4027, 688, -7043, -136, -163, -1395, + 13400, 1729, -1862, 2612, 321, -3874, 947, -990, + -3164, 11487, 46, -1978, -2139, 1222, 3897, -9664, + 3692, 5431, -3364, -3706, 180, -4009, 2563, -313, + 3228, -1631, -9763, -9184, -6058, -4594, 1040, -3323, + 321, -3233, 5035, -1919, -5525, 1899, 1196, -1834, + -391, 549, -2114, -1436, -2624, 2441, 618, -27606, + -841, -936, 1067, 1157, 230, 784, -755, 1798, + -219, -1026, -1119, 320, -2611, -1382, 8776, 1151, + 3739, -607, 2997, -7704, -5870, 1800, 1357, 4973, + -9674, -5182, -50, -886, 2056, -802, -1909, 574, + -1716, -6388, -2882, -3526, -3188, -543, 244, 9648, + 5129, -5069, 598, -9049, 1834, -3375, 1369, 1461, + -1295, -380, -274, 7258, -9353, -2401, 11915, -5087, + 1505, 4211, -719, -902, 1762, -168, 642, 699, + -2067, -933, 1092, -958, 715, -1978, -1968, -1613, + -1263, -777, 1170, -9652, -9570, 612, -3935, 237, + 386, 4237, -1468, -10172, -4964, 2919, -6428, -7184, + 119, 3610, 59, 3168, -5474, -853, -5735, -1765, + 3063, -1352, 944, -1934, -3500, 9282, 5920, 784, + 90, 275, 3211, 2418, -8570, -10498, -2026, -1020, + -2989, 1511, -41, -11462, -1980, 5296, 2614, -21, + 770, -156, -2817, -4748, -8672, 3447, -7231, 4598, + -1347, -689, -3198, 434, 56, -2065, 1798, 13761, + -533, -1280, -796, 2481, 56, 1377, -5473, 9116, + -1185, -602, 2547, -3693, -8880, 2978, 9093, 1829, + 4844, -649, 316, -162, 1520, -5814, 4860, 199, + -1330, -5182, -6269, 2642, 1220, 2816, -4098, -3981, +-13264, -398, 361, 2768, -4786, 1023, -97, 655, + -397, 2403, -1576, -386, -1112, 792, -1195, -759, + 742, 729, -2916, -1020, 21350, -26, -3577, 659, + -1263, 1378, -4339, 1880, 4842, -669, -1203, 5936, + 816, -8356, 3660, 1673, -677, -2370, 1652, 8710, + -1254, 6171, -6868, -891, -6752, -169, -5678, -7588, + -3247, 2982, 5281, -4941, -359, -3354, 851, -1609, +-11194, 610, 261, -1936, 2715, -3540, -2488, 2086, + 6110, 914, -3224, 1777, -1558, 937, 3736, -3109, + 1903, 4250, -4478, 2636, 2292, -1451, 10231, 7600 +}, + +.cb2220m0 = { +-26430, -533, 1599, 208, -293, 2303, 704, 1586, + -1064, -1630, 690, 1697, 623, 1786, 332, 682, + 199, 12695, 475, 1288, -2471, -797, -68, 9659, + -816, -2465, 546, -1421, 1596, -926, 4471, 2360, + 5551, -900, 297, 96, 400, 936, 1548, -1066, + -1625, 652, 1416, -118, -525, 683, 1545, 1340, + 20684, 936, -1033, -773, 8416, 954, -4822, 4223, +-10815, -312, -896, 531, 3140, -1649, 508, 10294, + -315, -2078, 584, 1523, 118, 997, -11837, -605, + -262, -1732, -613, 12220, -2666, -1802, -507, -4410, + -100, 2127, -114, -886, -2806, 500, 1034, -2811, + 12642, 1015, -9193, -4201, 238, 1096, -1159, 1619, + 2534, 1644, -3465, 4797, 639, 2583, -1316, -9884, + 948, 1479, 1186, -1760, -343, -1286, -1653, 678, + -7439, 4542, -6295, -1600, -6978, 48, 448, 369, + 1597, -3696, -2121, 1002, 2428, -11368, 5385, 827, +-10674, -2252, 2240, 1230, -3074, -1894, 296, -2216, + 571, 114, -497, -1675, 1311, -2297, 1843, -350, + -856, 2067, 1198, -588, 270, -470, 2640, 274, + 19586, -762, -11471, -623, -506, 4236, -10981, -214, + -1856, 409, -1276, -935, -1681, 5116, 774, 3008, + 4388, -112, -9493, -1108, 1454, 1385, 1065, 519, + -486, 308, -1141, 289, 1424, -3672, -15989, -3738, + -1592, -258, 3304, 62, 1441, 45, -686, -1070, + -1616, -701, 2313, 1918, 4843, 654, -16902, 263, + 1837, -4062, 2727, -709, 1524, -1628, 2025, -281, + 264, 1238, -1023, -11981, -2990, -1293, 801, -9606, + -604, -210, 1248, 4014, 3652, -11286, -2094, -470, + -1330, 14523, -2388, 1413, -3968, 641, 2936, 161, + -1687, -1260, 1722, -1968, 364, -854, -14386, 10146, + 792, 133, 1746, 261, 3345, -408, 2036, 272, + 1412, 720, -3302, -1495, -4334, 2210, 799, 17546, + 2600, 1314, 764, 1327, 3433, -377, 4296, 2402, + -1074, 470, 7220, -2556, 3326, -4338, -2086, -1945, + 11865, 3525, 1513, 1520, -1814, -13020, -929, -2001, + -1496, 580, -3293, -3146, -2185, 1442, 390, -2026, + -2141, -192, -18700, -2039, -4330, 1691, -250, 1451, + -2913, 2832, -3284, 2899, 1529, -888, 486, -2381, + -1459, -2663, 530, -717, -248, -1714, 12662, 1820, +-11488, -1044, 3035, 3872, -2430, 679, 1075, 475, + -593, 930, -1751, 405, -2308, 2148, 510, -2798, + 445, -240, -6865, 2106, -11323, 670, 4342, 154, + -7748, -1805, 5381, -842, -697, -709, 688, -498, + 5525, 15212, -2006, -4146, -2452, 2392, -3522, -2023, + 1306, 5522, 916, -3616, -287, -653, 333, -330, + 4, -24886, 635, 119, -1949, 899, -36, -37, + 2658, -133, 2064, -534, -549, -1745, -70, 32767, + 1089, -869, 150, -599, -1146, -574, -424, 377, + -648, -303, 590, 453, 1910, -351, 553, 304, + -752, -752, -502, -42, -31211, -634, 449, 638, + 1086, -1406, 1220, 802, -924, -1874, -212, 86, + -200, -1140, 618, -621, -605, -10976, 1699, -603, + 2056, -4448, -1519, 2564, -743, 12304, 1482, 547, + -1589, -817, -217, -1633, -1089, -2270, 181, -634, + 3890, 734, -1319, -2035, 3304, 13144, -9076, -4067, + 70, 1309, 1067, -354, 1529, 1379, -1002, -3324, + -525, -817, -1438, 10834, 1036, 12441, 1242, 2461, + 2858, 2257, 430, -1177, 1142, -870, 844, 1102, + 1208, -1482, 830, 17622, -2753, 6, 174, 4385, + -339, 2157, -155, -68, -190, -1181, 29, -2046, + -2140, 27, 949, 1889, 446, -54, 16696, -49, + -3304, -1929, 1833, 3735, -495, -1225, -11743, -2259, + 891, -1954, 2848, -504, 1164, -2489, 861, 579, +-11547, 976, -42, 1477, -2428, -1561, 112, 74, + -2721, 12046, 632, 1283, -1900, 1990, -1193, 1606, + -1370, -2812, -1309, -1419, -12526, 3391, -4213, -2710, + 269, 90, 14575, -345, 820, 6118, 892, 6302, + -2825, 332, -3071, 2279, 3756, 185, -3029, 2402, + 245, 1010, -273, -32751, -140, -600, 482, 1516, + -462, 1931, 1941, 272, -310, 544, -422, -815, + -1116, 803, -617, -1640, -4336, -11735, 3656, -1176, + 1170, -6209, 2139, -1571, 2067, 1011, 9842, 790, + 1702, -191, 911, 2771, -253, 794, -3862, -1885, + -494, 2070, -2682, 772, 763, 4304, -15657, -2194, + -1998, -963, -5222, -175, 238, 32, 10067, -692, + 2824, -474, 3016, -11994, -51, 713, 2423, 2864, + -338, 4838, -1095, 215, -13471, -2, 704, 752, +-14654, 1396, 484, 564, -886, -775, -1099, 775, + -1035, 1661, -1013, -1118, 449, 822, 14253, -13238, + -1084, -1107, -1672, 996, 472, 2237, -440, 1186, + 1200, -2112, -1388, -1093, -1902, 555, -328, -1493, + -2034, 426, -2144, -388, -20028, 1285, 1122, 730, + 1661, -1576, -2084, 2930, 337, -66, 1591, 8685, + 2361, 146, 1370, 22, 1371, -105, -4190, 371, +-13252, 328, 1301, -995, 3689, 6422, -79, -1407, + -384, 828, 840, 854, 266, 1222, 796, -550, + -729, -1213, -87, 524, 1070, 22334, -2333, 574, + 680, -624, 463, 4047, -236, 114, 1020, -692, + 1575, -320, -3229, 222, 520, 996, 2104, -5404, +-18197, -1105, -184, -1057, 10712, -2509, -7140, -2307, + 1333, 3041, 183, 1241, -7861, -3060, 1432, 9, + -1431, -2605, 2663, 273, 250, 770, -740, 6699, +-10929, -7227, 105, -2983, -1203, 1637, -6072, -6630, + 933, -1526, 658, 2612, 5377, -91, -66, 4944, + 3025, 2723, -869, 142, 10532, 9858, -207, 3072, + -2610, 0, 81, 1078, 2136, -266, 223, 931, + -385, 983, 1029, 108, 2290, -491, 26685, 565, + -140, -662, 680, -2206, -803, -777, -250, -467, + 98, 2944, -12296, -4190, -2254, -748, -2076, 4780, + -510, -221, 1428, -6162, 2693, 6238, -4030, 266, + 6540, 2502, 5147, -4649, 1804, -10514, -3413, 2503, + 2143, -1924, -3811, 3674, 4341, -1054, -3130, -1260, + -576, 887, 25908, -773, 1186, 548, -606, -744, + -995, 1320, -507, 279, 1803, -2451, 880, -31, + -5, 1615, 770, -11818, 1062, -1126, 472, -297, +-12126, -1197, 1912, -962, 1241, 2348, 2332, -3047, + 1561, 3844, 720, -387, 371, 2942, 1174, -2347, + 1244, 10148, -1620, -11788, 1315, -31, -1867, 3450, + -1589, 5180, 3184, -2614, -13, 130, 107, 297, + 113, -1407, 29190, -544, -173, 990, 913, -1848, + -990, 1230, 264, 1896, -6974, -102, -2232, 3826, + -2269, -5027, 94, -12612, 436, -5979, 1757, 1757, + -724, 2378, 2584, 728, -1022, -7274, 668, 744, + -516, 420, -11866, 246, -1357, 2406, 3674, -2594, + 1638, -3037, -2402, 1525, -7304, -1078, 1772, 9264, + 12366, 202, 2, -728, 684, -437, 1446, -3546, + 828, -2106, -2736, 964, -180, 6524, 2250, 514, + -782, 675, 1418, -11225, 2760, -3970, -545, 9128, + -6601, -556, -1966, -4625, -149, -198, -3330, -1575, + -6198, 656, 674, 367, 1809, 155, -5126, 6109, + -572, 4927, 1448, -1855, 1636, 8648, 2010, 8973, + 3087, 10172, 34, -1183, -12, -1057, 192, -2955, + 1034, -374, 2500, 9318, -4090, -5220, -404, -1022, + -1458, -1367, 765, -1193, 1542, 302, -1337, -34, + 1449, 1434, 2210, 404, -3277, -8024, 1363, -7591, + 9096, -9179, 1176, -7311, 544, -8942, -713, -56, + 2623, -35, 1623, 2212, 1733, -712, -1327, -320, + -1966, 11352, -1276, -3804, -550, 520, -4848, 550, + 1488, 944, 10756, -782, 5643, -2647, -6513, -3500, + -2877, 1880, -6634, 2349, 256, 440, 188, -8428, + -4580, 2479, 4763, -1807, -513, -4292, -1729, -6878, + 448, -6706, -1162, 4938, -721, 5465, 1409, -8759, + -898, -4254, -5230, -3886, -7969, 1730, 3656, 1198, + 3537, 33, 4091, -2088, -7646, 1160, 2922, 855, + -1254, -2616, -770, -685, -100, -577, -4927, -792, + -2107, 9613, 2563, 5096, 6143, -3404, -8630, 4164 +}, + +.cb2220m1 = { + 32524, -324, 411, -34, -697, 818, -71, 2326, + -142, -989, -1512, 358, -260, 3791, -575, 93, + 224, 208, -1101, 32767, 1147, -203, 2015, 461, + 668, -296, -3340, -38, 720, -993, 1765, -1344, + 1323, 648, -997, 729, 581, 349, 861, -2035, + 1791, -2142, -822, -1425, 820, -6555, -811, -15708, + -912, 4835, 1500, -604, 527, -937, -640, -1240, + 4692, 1259, 174, -12040, 450, 8196, 2796, -5123, + 1595, 538, -101, -218, 5581, 367, -2700, 277, + 2111, 2718, 1458, 155, -100, 3284, -498, 9961, + -1505, -10336, -1170, 5337, 1032, -14947, 1154, -578, +-11773, -945, -660, 669, 2340, -1038, 1520, 713, + 2663, 422, -1242, 1918, -234, -1793, -1580, -271, + -5628, -2010, -12209, -1784, -4417, -2804, -3123, -4316, + 126, 6353, -2391, -2088, 836, -2550, 521, -1258, + 918, 4471, -528, 4243, -615, 3453, -6683, 1784, + 790, 13200, 700, 322, -815, 6049, -290, 928, + -1121, -1531, -878, -1150, 1404, 325, -530, -435, + -254, -804, -2536, 589, 8439, -1087, -16248, -637, + -1528, 305, -1577, 642, -22699, -139, 1319, 588, + -3079, 800, -597, -1408, -1150, 3145, -868, 3244, + -1004, 1004, -1459, -11618, -4557, -3643, -914, 4238, + -626, 4025, 3227, 537, -4285, 2010, 747, 1595, + 1599, 5994, -797, -911, 2854, -3426, -8488, -1899, + -301, -2146, -111, -522, -1852, 3075, -3864, -1531, + 654, 193, -11264, 5561, 304, 525, 346, -2761, + -1124, 1134, 8354, -12460, -1023, -7634, -2750, -1518, + 5001, 1480, -1039, -502, 1455, 586, 1012, -1270, + 12435, 895, 1169, 466, -10696, -3861, 4381, 1790, + 767, -1808, -537, -1057, -2374, -2058, 9992, -858, + -1568, -678, -3812, -1520, 1521, 230, -1716, 13418, + -1930, -979, 3272, 1116, -4555, -559, -320, 12080, + 13696, -286, 652, 2420, 1725, -277, 213, -1046, + 1642, -576, -1514, -973, -1501, 77, 537, -606, + 1144, -680, -568, 1104, 2176, -969, 1657, -784, + 1107, -1056, -59, -5607, 64, 11913, -178, 8703, + 3744, 276, -50, -12807, 1122, -6138, 1901, -439, + 733, 6829, 3001, -61, -1005, 3816, 3987, -3588, + -778, 2257, 12101, 196, 13796, 355, 1407, 989, + 101, 1041, 988, 1274, -1478, -1127, 1320, -442, + 3452, -1717, 1244, -466, -868, -323, 502, 1243, + -70, 897, 958, 2781, -2492, 788, 744, -12324, + 1111, -11704, -452, -734, 19574, -45, -584, -2387, + -830, 603, 380, 787, -2962, 2046, 2524, -2403, + 699, -4144, 1587, 573, 588, 238, -88, 31, + -278, -32768, -1173, -745, 667, -188, 1221, -369, + -261, 322, -2054, 651, 100, -2092, 315, 1558, + 596, -407, -146, -1234, -30970, -71, 633, 536, + -1345, 1819, 655, 680, -1453, 492, -1265, -1292, + 1780, -68, 1008, 215, -19980, -521, -3148, -256, + 193, 916, 453, 86, 116, 108, 1518, -1420, + -1501, 688, 669, 1196, -1579, -942, 868, 804, + 110, 1126, 202, 1086, 23516, 1070, -1623, 747, + -38, -116, 1176, 554, -2361, 1008, 1085, 1972, + -1794, -96, 464, -20910, -1208, -3857, -466, -2173, + 2461, 2364, -931, -684, 3056, -719, -936, 887, + -3149, 1004, 7085, -2985, -9393, 5142, -9621, 150, + 174, 572, -2232, -390, 1356, 160, -10796, 2256, + 2238, 242, 1663, 485, 12378, 1236, 688, -2908, + 1084, 1047, 4850, -72, -642, 1604, 152, -850, + 670, 968, -3207, 1690, 105, -2516, 11539, 390, + -1117, -588, -10771, 2879, 4742, -8351, 1571, -850, + -605, -1959, 395, 12324, 1750, 2290, -92, 774, + -2897, 1025, -1841, 546, 3904, 3908, 11494, 9, + 1340, -11976, -525, 1522, -43, -43, -1860, -6160, + -199, 2479, 4593, -2876, -2985, 1044, -62, -812, + 10424, -2489, -1098, 796, -1292, -2070, 1096, -1944, + -2145, -4374, 1041, -1014, 9036, -2142, 328, -8232, + 152, -13336, -2225, 13716, -367, -558, -1942, 161, + -472, 2224, -748, 3550, -809, -493, 2121, 1234, + 772, 5146, 2485, -2282, 7546, -1441, 1595, 9176, + 6208, 1292, 1704, 3968, -1500, -1974, -3519, -2826, + 149, -903, 504, -187, -940, 121, -215, -615, + -257, -1954, 958, 2057, -191, 21258, -726, 2081, + 1278, 1670, -854, 2730, -8132, -530, 1004, 2574, + 1430, -2536, -10851, 1389, 155, -140, 2158, 2762, + 3807, 3850, -3728, -954, -11366, 709, 14727, 514, + 694, -87, 857, -249, -419, 617, -418, -1144, + -32, -2182, -839, 1449, -1072, -785, -246, 13634, + 12488, 358, -447, -2262, 926, 1023, -901, -345, + 2260, -1530, -1466, -2973, -2170, 2090, 44, -23476, + 603, -1740, -345, -438, -3004, 1322, -3088, 1274, + 341, -348, -534, 1055, 3026, -932, 514, 8958, +-15489, -374, 1077, 1166, 48, 1016, -918, -27, + -410, -266, -1401, -3888, -2918, -2146, 2815, 1834, + -875, 162, -678, 1876, -2033, 1999, -12854, -1563, + 192, 414, 782, -3109, 1432, -4197, 2358, 8517, + 784, 1256, -1362, 2938, -11355, -5184, -10314, -39, + -2182, -1686, 241, -195, -232, -6169, 206, 181, + -470, 1008, -599, -284, 733, -836, 648, -138, + 2078, 313, 24432, 548, -441, 1446, -1628, -1218, + -64, -716, -2456, 1987, -352, -1025, -1951, 1320, + 350, 744, 2598, -984, -18328, 622, -4, -1572, + 893, -3043, -4365, 127, -1, -226, -1696, 1332, + -1360, 6756, 2596, 12059, 370, -3690, 497, 585, + 1619, -778, 9174, -2046, 2214, 2004, 1133, 1069, + 132, -250, -1555, -906, 561, -12904, -1039, -8006, + 1876, 2300, -1116, 1895, 1782, 3734, -1108, 1338, + -1409, -248, 16117, -1458, 156, -2626, 64, -1199, + -3544, 4283, -3390, -404, 1426, -907, -2768, -780, + -34, -18656, 2003, 515, 3171, -653, 762, -3352, + -154, -1171, -452, -1590, -5936, 519, 1210, 502, + -409, 2262, 695, 1028, 8652, 2532, -2636, 3472, + -1186, 1350, -651, -639, 8382, -3234, 630, -10323, + -2285, -1916, 826, -1449, -738, -344, 1022, -3248, +-20921, -200, 568, -84, 777, -1570, -2756, 2834, + 26, 3878, -1709, 101, 1433, -2238, 305, 61, + -1041, 2399, 628, -1509, -388, 946, 733, -1538, + -650, 19935, 478, -10696, 850, -682, 447, 2311, + 35, -1258, 2332, -11417, 1743, -834, 660, 3170, + 2378, -2734, -762, -1151, -1802, -9324, 4625, 2304, + -1186, 1180, 4894, 662, -7067, 869, 613, 1802, + 4839, 3412, -5460, -862, -4202, 7876, -1057, 2872, + -1336, 1731, -10788, 1088, 3433, 42, -939, 2479, + 6425, 991, -1621, 3222, -2464, 2988, -29, 481, + 11606, -2800, -8315, 7660, -3385, 1217, -728, -3670, + 684, -2295, -724, -567, -2150, -106, -1920, -2143, + 3465, 1968, -1089, -11953, -2704, 3049, -1351, 7225, + 5727, -525, 2639, 1955, 2259, 6489, -1867, 1544, + -3199, -4992, 2420, 4119, -2860, -9505, -2152, 10204, + -1133, -1201, -1468, -2989, 4658, 578, 1115, 368, + 1570, -776, -503, 1554, 1329, -696, -760, 575, + -1527, -3865, 8372, -3378, -8137, -8392, -3471, -1854, + -4852, 5270, -634, 608, 1289, -7660, 4983, -1266, + -2070, -906, 3291, 2459, 4807, -4241, 5773, -2258, + -4500, 2634, -13176, 6412, 282, -5849, 294, -626, + 888, -1088, 656, 192, -630, -3405, -12469, 2882, + 2184, 3920, 2715, -6852, -1111, 869, -161, 341, + 1856, -9450, 2719, -579, -3840, -8763, 1153, -3532, + -571, -766, 8301, 2936, -10501, -1073, 10068, -2930, + 6308, -2747, 3093, -1710, -3865, -1464, -4447, 446, + 898, 5386, -1074, -4651, 6205, 455, -1773, -1270, + 6986, -2493, 4076, 10605, -2522, 977, 4098, 1153, + -434, 4071, -2890, 2920, 9175, 2276, 4699, 642, + -1067, -968, 508, -1752, 728, 3260, -500, 1414, + 5554, 2761, 1973, -4704, 2127, 1397, -1070, -14536 +}, + +.cb2224l0 = { +-12451, 389, 917, 1238, -626, -904, -1877, 2328, +-12808, -1345, 406, 80, 383, -3841, 1188, -907, + 2369, -13409, 11191, -2547, -532, 762, -1627, 680, + -2305, -811, -1118, 3232, 3413, -2010, -453, -6816, + -4100, 1643, 11209, 933, -2272, 1440, -2465, -6862, + 186, 1563, -8468, -1832, -1166, -596, -326, 105, + -115, -352, -624, 31621, 129, -301, -615, -313, + -176, 620, -5, -1354, -3563, 678, -301, 621, + 904, -769, -1314, -956, -2294, -362, 381, -2398, + 17085, 100, 3962, -830, 18705, 237, -1296, 3534, + 1452, 259, 1690, -3106, -3624, -316, -16, 5900, + 2195, -1008, 14335, 14173, -1637, 1130, 1110, 499, + -1516, 500, -720, -494, -1010, -1264, -773, 1389, + 212, 8036, 780, 608, -415, 931, -301, -2186, + 2256, -706, 12972, -3461, -3695, 2073, -2768, -1525, + -7539, -441, -753, 4558, -8171, -1751, -6885, 4077, + 6714, 53, 1090, -3006, 3688, -1162, -59, 302, + 928, -450, 238, 10809, 353, 698, -476, 172, + -2198, -4377, -7518, 1605, 6348, 5147, -165, 165, + -463, -93, 1251, 671, 587, -402, -227, -462, +-27960, 215, -56, -958, -657, 508, 98, -2811, + -1443, 3076, 6218, -9760, -10465, -770, 345, 3076, + -116, -2884, 2215, -2652, 1306, 2638, -124, -317, + 366, 1461, -295, 5073, 460, 1920, 12216, -7032, + 6816, 3037, -2630, -1087, -1315, 123, -582, -2137, + 5061, 291, 1740, -214, 1920, -3470, 10895, 9491, + 3558, -1256, -448, -10304, -2391, 1890, 484, 11057, + 6636, 422, 2316, -1663, -348, 633, 1200, 1788, + -1124, -24435, 140, 869, 738, 223, -1429, 602, + 433, -196, -1127, -1937, -879, -310, -564, 1022, + -4380, 7247, -3938, 4461, 2219, -8465, 9266, -4564, + -3169, -3463, -477, 749, 2460, -776, 294, -171, + 1072, 1748, 1000, -208, 1908, -998, -1898, -10485, + 2360, -11950, -2412, -2609, 3885, -2738, 1348, -559, + -1342, 9366, 1560, -816, 1178, 342, -175, 1286, + 3014, 10641, 246, 3128, 6618, -305, 10906, 6359, + -4395, 1415, 196, 11136, 1772, -3047, 3313, -1231, + -1974, -3021, -1480, -1345, -830, 1551, 2521, -506, + 7821, 7715, 5078, 8215, 2102, 1552, 2247, 3766, + -3158, -1811, 631, 3980, -397, 9030, -1267, -1974, + 1539, -360, -315, 796, -4749, 2076, -1017, 717, + 2290, 11212, 9365, 1626, 379, 2060, 1329, 4, + -25, -1348, 566, -1266, 1670, 2166, 13123, 42, + 2416, -2170, -6380, 172, 316, 40, 300, -487, + 402, -220, 846, -894, -1413, -2227, 1962, 19478, +-14756, 14377, -582, -770, -186, -1008, -1520, -722, + -885, 2622, 311, -753, 480, 539, -1011, -1748, + -832, -603, -2015, 869, -14860, -600, 2110, 484, + -5874, 1532, 3290, -222, -4670, -33, -794, -2061, + -1185, -96, 337, 515, -1887, 26, 20283, -455, + -799, -62, -1083, 236, -1721, -569, -1259, 361, + 1090, -226, 1480, 13367, -638, 940, 3736, 6419, + -5995, 830, -6599, 4549, 1583, -9001, 1104, -1281, + -1270, -94, 1104, -2076, 652, 2263, 1465, -25, + 9046, -8139, -2646, -13200, -534, -15244, -1448, -1390, + 452, 584, -314, -1192, 951, 885, 396, 776, + 1303, 1298, -448, -32641, -234, -62, 31, -164, + -1042, -82, -26, -272, -559, -164, 669, -500, + 516, 1347, 9615, 1123, -1346, -1898, 8341, -10583, + 2286, -5233, 1503, 454, -2024, 4248, -2298, -2117, + 13390, -849, 2078, 1096, -651, -12232, -374, -812, + -3729, -829, -144, 1213, -469, 1112, 1146, 816, + 818, -912, -967, 907, 12, 2443, -759, -1833, + -174, -838, 488, -1560, -18242, -558, 5510, -1316, + 1758, 3957, -7130, -1394, 4962, 3870, -1907, -9247, + 2217, -3880, -4413, 1893, -3085, -202, 599, 1307, + 1574, -1070, -2593, -2722, 9506, -10170, 1105, 4879, + 2208, 38, 5596, -5990, -3205, 35, 9405, -219, + 618, 1308, 353, 3457, 1712, 717, -12937, 25, + 2176, -2590, -1223, 528, 1318, 4588, 7678, 5743, + -8430, -4487, 1364, 8082, -1727, -387, 469, 3172, + 401, -2771, 694, 14554, -2278, 3640, -11084, 924, + -593, -3841, -4338, 227, 750, 2974, -2834, -1765, + 2133, -1181, 5149, 11758, 11949, 3538, 2442, 2801, + 1457, -822, -3419, -2468, 191, -646, -975, -1271, + 832, 3088, -495, -10022, 1817, 1319, -880, 1342, + -1448, -3597, -3310, 8753, -161, -6550, 1422, -640, + -508, 11542, -277, -165, 837, 7389, -942, 11009, + -97, 1548, 1418, -445, 2105, -946, -8676, 5274, + 8842, 576, -1392, -1737, -1276, 5491, 312, 3624, + 2806, 2157, -537, 1656, 1982, -1300, -146, 463, + 496, 16792, -140, -1755, -832, -2123, -399, 5811, + -702, 2891, -3630, -1843, 346, 508, -364, -498, + -558, 32048, -744, 90, -372, 430, 704, 871, + 139, 772, 696, -108, -18, 310, -411, -798, + 465, -165, -321, 745, -27861, -752, 499, -215, + 172, 35, -196, -770, 274, -546, -96, -470, + -8976, 9156, 581, 904, -4644, -7801, 3525, -607, + 6444, 4058, -696, -1107, -632, 1475, 196, -933, + 883, 1101, 278, 433, 544, -497, 4, -1882, + 1504, 594, -30386, 218, 211, 850, -989, 319, + -867, -42, 754, 498, -70, -562, 660, -11561, + 54, 803, 425, 966, -1017, -1224, -12630, 1834, + -41, 98, -1083, 3508, 1750, -1751, 72, -503, + -38, 22211, 252, 88, 221, 690, 82, -1340, + 508, 638, 832, 482, 51, 7954, 2702, -1176, + 8830, -311, 2536, -6072, -4147, 5234, 494, -157, + -1289, -5678, -1617, 1508, -140, -55, 713, 440, +-32583, 105, -394, -613, -972, 578, 1122, -32, + 114, -228, 342, -1237, 1123, 1126, -188, -106, + 11308, -3787, 563, 3423, -9926, 1623, -2551, -1448, + -4125, 918, -1366, -476, -66, 4, 761, 164, + -61, 20445, 238, 296, 492, -1126, -98, -1201, + 14, -1840, -865, 1178, -869, 105, 907, 248, + 1538, 2990, 11691, 7783, 1566, -6704, 2397, 594, + -1825, -383, 4264, 1911, 468, 1018, -676, -2676, + -7756, -2623, 10705, 2710, -8078, -5256, 1699, -2100, + -355, -2086, 10828, 611, 18, -830, 978, -4181, + 1324, -5262, -327, 1796, -9777, 1306, -1934, -8930, + 9520, -2364, -3997, -10209, -6326, 1394, -1758, 868, + 1192, -2916, -23, -1586, -296, 438, -279, -14171, + -1554, -206, 2383, 506, 1181, 8298, -491, -2771, + -4286, -7116, -1680, 506, 1729, -12965, -925, -985, + 420, -1746, -267, -478, -11763, -1030, 187, -3878, + 1516, 2472, -371, 29, 809, -1700, -152, 560, + 1833, 14397, 968, -96, -3242, -2497, -76, 2096, + 9593, -1200, 446, 1505, 8058, 1722, 501, 923, + -1171, -9516, -2536, 7368, -2, -5304, -2440, -352, + 510, 320, 301, 120, 687, -942, 137, 824, + -316, 1312, 510, -1133, -27448, -404, 1041, 272 +}, + +.cb2224l1 = { +-14840, -1361, 12733, 798, -496, 1691, -1668, -1730, + 928, -3233, 338, -578, 156, 784, -787, -242, + -618, -853, -1282, -11766, 3970, 12178, -2034, 244, + -3411, 300, 159, 3494, -3060, -1459, -2484, -10680, + 752, 227, -1612, -922, -549, 158, 2260, -7640, + -4479, -4075, -2412, -7707, 600, -12358, 93, -1666, + -795, -13060, 61, 511, -2102, -2122, 364, -157, + 2310, -1552, 1260, 158, 9503, 7050, 7, -5902, + -7098, 444, 3736, -1836, 3109, -2328, 457, -871, + -327, -780, 661, 8684, 2530, -268, 954, 1380, + -1029, 418, -136, -3515, 1953, -1688, -8623, -3292, + 7758, 2796, 11643, -931, -501, -873, -444, -1342, +-13900, -246, -283, -1779, 998, -1318, 408, 1505, + -462, 10667, -1813, 78, -16514, 360, -2029, 942, + 1674, 171, 317, 244, 1183, 724, 760, 1634, + 863, 793, 126, -326, 980, -629, 22219, -649, + 1274, 717, 1355, -1853, -1792, -1017, -2104, -768, + -1708, 2302, 2353, 11167, 10734, -3412, -2266, 75, + -104, 425, -880, 2072, 2934, -930, 270, -2414, + -925, 1023, -746, -236, -1620, 825, 1324, -101, +-19348, -1291, 585, 2165, 2891, 3662, -577, 1800, + 408, -1486, 107, 351, -319, 1104, 956, 403, + 628, -277, -57, 938, -32768, -71, -441, -208, + -32, 191, 314, -171, 613, 749, 844, -472, + -444, 952, 42, -8026, 2720, 1911, -2780, 12311, + -122, 3569, -91, 6048, -776, 1694, -63, -1272, + 3581, 1622, 2538, 190, -13108, -820, -3056, 1189, + -1428, -244, -752, -6187, -3473, -697, 1368, 1043, + 7702, 352, -140, -12999, -80, 12672, -1473, 3113, + 1505, 667, 2392, 1767, 537, 1949, 657, -130, + 980, 1743, 8269, 2380, -2311, 197, -651, 2531, + 553, -1117, -396, 472, 4565, -12672, 2322, -360, +-12766, 2205, -2651, -10690, -218, 586, 5229, 34, + 59, 1730, 1226, 2106, 4008, -1878, -9520, -1366, + -1174, -290, -1037, 1642, 1234, 305, -1279, -642, + 1126, -13199, -29, 642, 2928, 1936, -260, 588, + 11690, 9282, -3362, 7732, 1073, 2738, 4688, -1507, + -1461, -2271, -1131, 1969, -2152, 1637, -774, 66, + -1190, -206, -491, -1080, 644, -378, 367, 17980, + -1583, 2162, 918, -121, -432, 115, 5, 791, + 1968, -2287, -1574, -9545, 11146, 3540, -4700, -515, + -4548, 881, 591, 1044, -259, -978, 2, 232, + 778, -198, -1161, -378, -83, 421, 282, 26564, + -801, -1628, -1983, -301, 931, 886, 2196, 1453, + 752, 2956, -3478, 490, -1420, 13303, 1293, -9466, + 462, -12829, 11130, 8061, 593, 3697, -611, -534, + -698, -1148, 1598, 293, -726, -698, 289, 180, + 876, -369, -43, 234, -21629, -1448, -753, -480, + 956, 994, 531, -916, 630, 720, -2300, -9544, + -1418, 993, 2130, -2359, 2460, -339, -277, 1577, + 12206, -3507, -1280, 1938, 871, -1850, -809, -3364, + 6918, 1134, 5010, 8772, 2103, -9775, -1404, 5148, + -1494, 1549, 1761, -812, 654, -611, 822, -229, + -384, 10466, -337, 2207, 131, 2818, -2925, -3374, + -8786, -8552, -2282, 88, -1058, 8571, 2900, -529, + -1569, 1882, -981, 204, 2955, -4227, 4196, -3041, + 10804, 1822, 82, 1936, 2380, 12992, -5659, -3449, + 1329, -1668, 1291, -1726, 8328, 314, 2737, -677, + 2384, -910, -878, 687, 640, -721, -912, -12772, + -2079, -398, -1788, -2516, -8711, -1038, -985, -7151, + -9057, 890, 459, -298, 918, -10061, 848, -716, + 1822, 836, -9516, -985, -1379, -409, -2237, 1036, + -1082, -1704, 1333, -1432, 11463, -2355, -5975, -1674, + -640, -554, 8352, 2732, -5251, 4243, -354, 3662, + -592, -9317, -1205, -1084, -995, 11288, -2098, -1620, + 2367, -1286, -5312, -64, 540, -2327, -2703, -2013, + -8649, -1306, -948, 1443, 664, 2400, 4706, 4061, + 387, -20, 1859, 9283, -18175, 806, -1401, 1253, + 596, 2176, -1682, 2209, 733, 1404, -6652, 2754, + 950, 2346, 3629, -6875, 5069, -9302, 1472, 942, + 1184, -10432, 960, 3987, 1985, 421, 300, -716, + 938, 500, -160, 226, -87, -1648, -1857, -1977, + -323, 2305, -13843, -4148, -2978, 5430, -3422, -1138, + -2146, 1548, -1430, 734, -339, 8598, -4568, -496, + 477, 4969, 2593, 2842, 8645, -2365, -7455, -2687, + 249, 7516, -53, 219, 1139, -668, 566, -522, + 1289, 33, -141, -920, 2526, -2797, 16456, -2000, + -758, -194, 10984, 187, 1686, -4799, 9671, 1838, + -1224, 1325, 656, -5434, 3207, 1813, 1833, 14375, + 12259, -95, -536, -1746, -3568, -442, 964, -1472, + 1345, 2692, -589, 520, 616, 357, 326, -1363, + 28603, 700, 473, -908, -1129, 1046, 1106, -471, + -472, -980, 29, 574, -350, -545, -585, -1936, + 279, 882, -880, -52, -30552, 371, -154, -1275, + -1914, 104, -110, 1122, -719, 729, -743, 360, + 766, 198, -11674, 612, -10602, 1157, 186, -3132, + 3070, 1535, 155, 774, -9432, 4966, -6717, 320, + 5167, 112, 2727, 11228, 1368, 1864, 1197, -1519, + 1504, 17863, 49, 2212, 611, -1788, 2932, 395, + 32, -566, 2425, -9457, 673, 670, -247, 1617, +-12578, 1408, 462, -14935, 1438, -808, -1850, -784, + 1856, -1648, 767, -1452, -1652, -1621, 1016, 1428, +-11203, 4217, -6410, 2570, -1016, -1720, -9036, -390, + 62, -1245, 3027, -255, 1646, 1358, -907, -864, + -118, 874, 268, 252, 104, -926, -552, -1206, + 965, -208, -24472, 890, -1516, -630, -885, -804, + -374, -22520, -1143, -777, 532, 185, 603, 1775, + -1887, 413, -458, -1036, -211, 2693, 6976, -9498, + 1437, 10163, 2450, -1574, 4941, 884, -470, -3366, + 4664, 420, -568, 5703, 10, -1692, 143, 1592, +-10966, 2891, -2961, 3938, 1990, 1726, -5247, 3326, + -6575, 584, -277, -441, 1679, -520, 1339, 1077, +-11462, -267, -351, 201, 10939, 4150, 3890, 1484, + 2615, -676, -448, 2316, -1278, 9734, -3039, 2841, + 964, -7557, 156, -7228, -120, 5533, -4322, 1796, + 2555, -9912, -3038, 2236, 1190, 222, -1684, 3273, + -1768, 6233, -6442, 8545, -49, -45, 2366, 293, + 308, -689, 308, 368, -452, 1125, 2326, -2335, +-17793, 2027, -779, 734, -2032, 1246, -2898, 4174, + -74, -40, -3105, -2135, 996, -12714, 3614, 4936, + -1928, 1528, -4158, -1791, -2318, 907, -326, 22513, + -660, 1022, 434, -564, 28, -112, 252, 372, + -842, -2, 648, 2323, -614, 23377, -263, 486, + -408, -362, -821, -724, 972, 1248, 444, -1741, + -420, -1371, 1088, -565, 22, -394, -64, -292, + -103, -501, -30510, -294, -266, 433, -700, 742, + -756, -407, -961, -148, -1416, -1041, -481, 121, + 346, 10240, 12629, 1476, -2647, 1350, -2012, -262, + -5621, 714, 4398, -2732, -10473, 9834, -5165, -991, + -557, -2733, -3460, 5779, 659, 1472, 2029, -2339 +}, + +.cb2224s0 = { +-27522, 2628, -2486, 277, 874, -2351, 2725, 915, + 994, -1209, -439, 2936, 46, 1014, -1816, -3561, +-14386, 3113, -10400, -1025, 2114, 1328, -278, 1182, + -1820, 3928, -1062, -282, -1327, -1468, 5975, 2342, + -630, -4217, 10116, -1254, -2646, -5210, -9942, 1904, + 21, 504, 2325, 1443, 6470, 2598, 8130, 810, + 304, -1059, -645, 14634, -3198, 4277, -669, -7170, + 1554, -2321, 2386, -1072, 2483, -4141, 2841, 3414, + 8014, -3141, 10857, 6634, 3138, 3199, -320, 36, + -1366, -4129, 3157, 2602, 4273, -2435, 2645, 2986, + -3712, -3995, -5476, -4693, -1664, 6384, -11201, 1320, + 2184, -5102, -2984, -1569, -2116, -1513, 14284, -11182, + -2925, -731, -1321, -6363, 1483, 3463, 1292, -2065, + -357, 9108, 6371, 3840, -6905, -8918, 2906, -1658, + 757, 1998, -580, -708, 2198, 1867, 960, 4522, + 1896, -1674, -4943, 2695, -2465, -2078, 9755, -4853, + -2602, 3466, 3897, -3633, 4918, -2049, 3730, -1982, +-10085, -3458, -1866, 32, -1706, 3648, -308, -942, + -1630, 1730, 512, 14612, 3415, 974, 3079, 765, + 897, -270, -1813, -1533, 1118, -2805, -2764, 1130, + -1798, 4594, -3134, 964, -20082, 2574, 32450, -1379, + 52, 358, -226, 1902, 257, -1071, -650, -399, + -381, 2073, 2310, 2164, 8221, 1433, -629, 1440, + 1120, -3362, -4642, 2000, 378, 1208, -2648, 4534, + 3307, 13200, 2780, 3100, -3194, -10606, -11563, -4491, + 2218, -4500, 622, 1313, 2682, 3003, -1387, -3886, + -1567, -4864, 10899, -20606, -1606, -60, 602, 125, + -730, -1112, 979, 325, -13, -185, 1241, -288, + -552, 6042, -7049, -7359, -1456, 493, 11204, -65, + -2170, -5248, 2248, -1046, 591, 2085, -2844, 244, + -3454, 581, 1315, 3043, 304, -620, 405, -19944, + 769, 1076, -1456, -694, 2560, -1046, 2514, 14552, + 1586, -7027, -4710, 1366, 1552, 4354, 3296, 462, + 600, 500, 3225, 5083, -792, 3199, -698, -3589, + -2596, -3350, 2758, -3019, 5664, -9387, 4716, -3125, + 3306, 6268, -592, -622, -4144, -6290, 4990, -748, + 1854, -1042, -2996, -4279, 338, -1864, -8639, -11208, + 932, -722, 1788, -1927, 450, 2191, 11828, -6400, + 5364, -2236, 3212, 8340, -3229, -2846, -4676, -1825, + 2628, -303, -589, 7728, -4216, -3866, -4400, -194, +-11316, 5646, 3716, 4827, 232, -583, 308, -1833, + 2153, -2508, -46, 857, -9587, 2768, 5136, 1462, + 5142, 7990, -3424, 1067, 7462, 4944, 98, 1014, + -4750, 13824, 1130, 2334, 9393, 2416, -4519, 27, + 2000, 929, -204, 481, -2780, -3720, 1267, 269, + -5383, -1999, 1249, -4238, -9351, -7440, -5964, 6154, + -6827, 3112, -2613, -164, 1604, 1245, -50, 8619, + -4044, 4652, 2846, 8359, 5345, -2902, 2295, 4801, + -5016, -6270, 2893, 2732, -3510, -2613, 4548, -6376, + 4510, 10566, 1859, 1038, -8381, 2782, -1622, 159, + -1035, -3232, -3766, 1580, -720, -4476, -3863, -920, + -2135, -458, 352, -2645, 3029, 301, -1145, -478, + 3696, -11700, 9930, 6649, 7290, 2362, 17226, 3238, + 1786, 662, 971, -736, -647, 1745, -506, -777, + 1458, 2406, -1417, -7933, -846, -2654, 1104, 618, + -2783, -10168, -3322, 9498, -939, -2342, -1876, -1914, + 84, 3468, -6533, 7796, -3797, -1318, -2183, 1310, + -895, 4943, 1062, -4468, 142, -244, 884, 613, +-13963, -5853, -947, 18703, -964, 1090, 1070, 1388, + -1572, -1110, 671, 1706, 620, -262, -2421, -2277, + -5665, -5212, 4994, 2379, -593, 2048, 14489, 1165, + -1775, -2093, 2466, 419, 404, 5429, 3089, -1350, + 1975, 2281, 60, 599, -1600, 2286, 2358, 6698, +-16423, 3760, 666, -1309, -1346, 2786, 2364, 1448, + 1114, 17956, -5301, 2430, 1178, -164, 2195, 3927, + -122, -737, 1468, 307, -1863, 1592, -7714, -2428, + 958, 220, 59, 4124, -1945, 11151, 8604, -2077, + -4787, -4578, 1096, 2685, 6478, 8314, -6221, -3842, + 2173, -43, 104, -2510, 3109, -2324, -4238, -4709, + -3233, 3228, 11454, 2428, 578, 780, -1096, 72, +-22624, -1421, -4104, 226, 464, -1726, -1971, 2068, + 1142, 1412, 1412, 798, -2605, -3451, -1104, -2224, + -2250, -3470, -572, -1420, -1292, -58, -217, -21417, + -172, -6368, 30, -2170, 95, 378, -2926, -2180, + 2820, -683, 2018, -4313, -13469, 5396, 1808, -592, + 4732, -6602, -5602, -983, -4130, -477, -1236, -2263, + 3992, -12962, -1778, -2631, -2421, -746, 1964, 1754, + -760, 2753, -116, -3860, 10246, -448, -1318, -100, +-10372, 1420, -210, 2768, 48, -2373, 7721, -3217, + -328, 1543, -2527, 3709, 4024, -916, -4588, -726, + -4302, -982, -14714, 3615, -1190, 9051, 199, 2252, + 1348, -4204, 693, 1241, -14160, -2460, -2017, 2997, + 766, -360, -450, -2919, -7976, 3210, -179, 8935, + 670, 1155, 6888, -2249, 2729, 1810, 6283, 684, + -9717, -1763, -921, -4578, 3941, -6408, 1431, -2742, + -91, -2094, -2118, -9752, 2801, -2497, 147, -5901, + -5270, 13170, 2810, 1576, -3191, 10253, 4226, -1340, + 2456, 1079, 12541, -5124, -8356, -1000, -558, 180, + -2070, -1880, -5718, -687, 10549, 1066, 220, -4147, + -695, 3648, -3460, -3143, -1623, 2150, -11222, -2566, + -6395, 3552, -4176, -698, 1248, 112, -4628, -960, + -724, 1191, 2084, 15207, -346, 371, 190, 5345, + -4283, -7482, 1354, -4424, -3775, -4143, 1444, -14876, + -589, 2498, 1305, -486, 1628, -867, 1584, 1094, + -10, -1260, -1046, 2528, 27472, 910, -1069, 829, + -117, -1097, 770, 252, -1412, 2353, 2200, -11, + 624, 8459, 6320, -9465, 1225, 2532, 5415, 9252, + -1441, -1378, 1081, -1997, -3904, -14740, -5220, 3627, + 5725, 6180, -5336, 72, 4638, 915, -496, 628, + 1880, -420, 2800, -7143, -7578, 3180, -4210, -1111, + 2979, -442, -182, 2778, 2398, -13878, 2209, -282, + -888, 180, 3584, -1005, 2, 999, -3074, 1205, + -4605, 5250, 17255, 2839, 2718, -678, -2651, 160, + 1596, 4685, 2324, 3100, 3744, -1954, -11674, 621, + -678, -6242, -3449, -1890, 3134, -289, -7162, 2268, + -8437, -624, 4999, -5946, 13013, 244, -200, -1494, + -1108, 3768, 445, 2429, -1264, 786, -2993, 3482, + 2448, -968, -1184, 213, -772, 4931, 42, -3850, + 2020, -17970, 84, 3016, -602, 1805, 731, 3522, + -2606, -637, 25535, 680, 1083, 4138, 1602, 190, + -1854, -962, -379, -2499, 2453, -362, -4552, 4689, + 2168, -5930, -10552, -5585, -4694, 2447, 2047, 5420, + 3908, -1449, -90, -68, 496, -12713, -2127, 1406, +-10766, 2438, 2278, 2962, -6411, -22, -1966, 2814, + -1746, -383, -2381, -5981, 10920, -12354, -656, 2260, + 5200, -1908, -2275, 4276, 1174, -932, -532, 2832, + 601, 1551, -8434, -4170, -6411, 9099, -6886, 2243, + 561, 2026, -3598, -1125, 646, -5188, 6017, -632, + 772, -2919, -3776, -9938, 2461, -122, 128, -1416, + -1533, 343, 1318, -13738, -1528, -6418, -1196, 832 +}, + +.cb2224s1 = { + 32767, -749, -1885, -806, 739, -1858, 3902, 1029, + 332, -2122, 1240, 2705, 1362, 190, 1058, -1404, + 1224, 1122, 1208, 190, 1984, -1355, 1694, -21000, + -1012, 2418, -1269, -1154, 1113, 2291, -2317, 315, + 12872, -2296, -1510, 1104, 11324, -1146, -1018, 1326, + -902, 168, 647, -1828, -3838, -5682, 2732, -238, + -134, 13450, 1570, 2424, 996, -3494, -3720, 4897, + 5875, 149, -6367, 6659, -2329, 6916, 1134, 425, +-19014, -479, -1900, 3470, -1777, -811, 1723, -46, + -2103, -1298, 2929, -4279, -639, -2443, 7231, -1187, + -2145, -777, -3287, 4895, 8878, -9318, 289, 4015, + -3148, -598, 2226, 11700, 114, 3237, 9586, -4570, + 2592, 3614, -2272, -2829, -3356, -1095, -5290, 4709, + -1867, -1930, -20722, 937, 892, 1415, 1544, 2950, + 5090, 937, -1411, 123, -31, -1568, 338, -938, + 5465, 5796, 480, -2782, 3351, -2489, -383, 1529, + -5686, 2446, -693, -12796, -599, 1894, -1576, -2244, + -4686, 10165, -1085, 10050, 2681, 1138, 2544, -1809, + -806, 5278, -8730, -3740, -2343, 971, -3254, -165, + -212, -4164, 850, 233, -13694, 442, 1073, 3854, +-12926, -2001, 3468, -765, 829, 2174, 1531, -6036, +-10848, -11009, 803, 1713, 2884, 1992, 75, -2989, + 268, 346, 1998, 4798, 8976, -4632, 1863, -4127, + -612, 4790, 10946, -1296, 8009, -1351, 356, -1711, + 313, 2301, 1318, 8050, 700, 1218, 2270, -2156, + 67, 1537, 1941, 3442, 13321, 691, 2344, 2594, + 1551, 3853, 7279, -10441, 1006, -11862, 5532, -611, + -582, 2257, -2873, 3993, -5133, -2264, -2478, 1576, + 1834, -4931, 10264, -1429, -10404, 393, -3715, -1470, + -2003, 384, 4869, -6780, -1297, 1572, 1043, 6980, + -4382, -3005, 3698, 4176, -1348, -4972, 1574, 9815, + -5995, -979, 3609, 3702, -8503, 668, 3354, 2552, + 9183, -1175, 1224, -2859, 11176, 6088, -1355, 84, + 1271, -380, 5336, 299, -690, -365, -8047, -3679, + -3204, 1334, -13451, -1392, 2200, -3646, -1046, -4292, + 741, -1701, 1722, 2061, -1358, 7266, -6356, 963, + 2190, -1349, -1882, -14128, -4662, 3552, 565, -1109, + 5413, 1239, -2618, 794, -2064, 11805, 9004, -2134, + 2804, 946, 80, -2387, -1205, 11, 1642, -1825, + -2324, -5018, 4208, 5285, 661, 12430, 1907, 784, + 10864, 340, 18, -138, 2885, -2247, 17, 334, + -3172, 2977, 970, 536, -1540, -516, -488, -512, + -1334, -1930, -2418, 1078, 24837, 12, 2060, -252, + -2536, -2206, -3179, -6785, -8842, 8736, 1393, 119, + 1652, 10126, 856, 855, -742, -289, -2208, 3831, + 6909, -6556, 2472, -245, -1729, 1460, -3014, 59, + -58, 132, 3903, -3762, -1419, 13273, 2708, -7752, + 84, 3525, -1305, -334, -13421, 5931, -4845, -2697, + 666, 558, -1102, 632, -2946, 4153, -4018, 4516, + 4875, 4460, -1567, 2233, 386, -754, 1256, 2145, + -1692, -13046, 1581, -518, 4397, 1215, -723, 3413, + -640, -5088, 1711, -714, 2536, 2433, -691, 10758, + -8764, 5541, -2071, -1662, 12955, 12998, 1252, -94, + 802, 2573, -2557, -66, -832, 106, -728, 1050, + -811, -2684, 629, -16524, 1531, -1617, 1348, 204, + 1722, 368, 554, -1752, 114, 1349, 1952, -1007, + 2626, 2035, 8148, -2539, -4296, -4460, -8542, -3089, + -1543, -857, -2617, -1765, 6642, 2167, -1531, -6881, + 86, -414, -5896, -5152, 17445, 1129, -5006, 2936, + -3432, -2226, 1176, 972, 1170, 530, 3390, 260, + -2909, -3550, -5255, 1771, -382, -1690, 17070, 2688, + 566, 2430, -1768, 3373, 1460, -3464, -629, 3119, + 430, -3554, 8357, 7075, 293, 2955, -61, -6919, + -4939, 3678, -6852, 652, 2206, 5918, -2768, -3022, + 5721, -770, -1102, -1057, -2760, 3086, 5611, -160, + 2714, -1042, 2569, -14248, 3846, 8212, 5392, 144, +-11896, 618, 1212, 3283, -3777, -715, -3870, 2528, + -2900, 1645, -1786, -1852, 2776, -1348, -586, 234, + -4, -1666, 46, 2095, -1987, -18728, -2980, 2501, + 4042, 79, -1849, -2013, 8047, -1898, -108, 340, + -4760, 2134, 9000, 347, 10365, 4779, 6660, 1694, + -3253, -2282, -1488, 10406, -8054, -3414, -2934, -1611, + 3172, -2195, 4973, 1249, 2888, -4054, -5738, -2995, + -2282, 1977, -353, -516, 5322, 3225, -4907, 1303, + -4656, 9947, -236, 9382, 2332, 2076, 1470, 3173, + 4712, 2645, 559, 4904, 1511, -1715, -4856, 5750, + -1276, -306, -5980, 14393, 1443, 85, 156, 7718, + 793, 4199, 2122, 1098, 128, -1996, -1397, -20, + -534, -13296, -1518, -2970, -1001, -6474, -6146, 8337, + 5476, 3058, -526, -1295, 1623, -8791, 1257, 2006, + -5725, 3035, -2917, 1280, -8479, 5934, 9870, -13131, + 14, 1088, -9, 1969, 366, -3214, 192, 2764, + 1499, 346, -2031, -2900, -2529, 1072, 11717, 5206, + -44, -2514, -8900, 2892, 2132, 3635, 3735, 2726, + 1398, 6035, -2830, -4568, 424, -8696, 1368, -3860, + 1823, -2620, 4546, -2210, 1660, -1672, -10524, -484, + 950, 11, -4494, -6220, -5653, -13332, 2868, 460, + -4120, -4030, -3277, 522, -3403, 1126, -170, -1892, + -4366, 1304, 3477, -1507, 1111, -594, 1670, -8416, + -1690, 2492, -7109, 2531, 4131, -8123, -4884, 16505, + -240, -63, 32099, 974, -1360, -2395, -2005, -1156, + -877, -416, -922, 1857, 766, 71, 1380, -259, + -272, -1924, 2498, -3290, -16045, -2064, 2966, 2936, + -1265, 2121, 488, 3781, 1484, -1193, 4776, -1001, + -669, 1569, -379, -604, -5, -1943, 757, 359, + -560, 118, 17941, 2323, 215, 7621, -3582, -8130, + -698, 9893, -2752, -417, -1262, -1504, 3319, 1186, + -2192, 3014, 781, -3602, -6190, -7725, 3169, 2038, + 1175, 612, 2477, -4136, -12152, 4538, 567, -116, + -3222, -470, -118, -9257, -635, 3078, -11596, 93, + -4178, 4150, 5985, 4414, -2110, 542, -1125, -1242, + -234, 807, -1385, -2448, 824, 109, -1826, 3032, + 269, 14188, 3468, 908, -12, 2290, 5758, 1685, + 680, 5963, -2763, -173, -34, 3135, 1230, 2226, + 2471, -9546, 2266, -1583, 729, 3506, -10664, -652, + 2212, -620, 2762, -751, -6337, -4339, 4131, -1234, + 5423, -2279, -2884, -929, -12582, 416, 2046, -3854, + 11130, -2738, -670, -202, 6216, -7266, 9726, 1308, + -1761, 4696, -1061, -144, 482, -1586, 4377, -5016, + -3894, 2296, 4340, -555, -3003, -2117, -962, 100, + 4548, -1870, -13885, 1351, -3226, -8114, 377, -391, + -1344, -2148, 4756, -3518, -14429, -670, -238, 400, + 1234, 4389, 1181, 1046, 425, -32, 840, -29846, + 1580, -992, 1844, 1961, -1305, 1055, 418, 52, + -641, 2430, -1773, -5323, 3341, -5367, 14027, 3051, + 3864, 404, 4186, -1875, -5822, -4321, 112, 395, + -177, 1080, -3008, 520, 8, 226, 1430, -1635, + 8, -2632, -3249, -3595, 622, 564, 8404, 14463, + 160, -7828, -4113, -16547, 848, 6320, 2311, 4074, + -2050, 668, 1463, -2322, 1790, 864, 317, -594 +}, + +.cb2224m0 = { +-17338, 5737, -912, 5906, -5315, 920, 2743, -2232, + 1943, -753, 1696, -1818, -2272, -564, -1306, -527, + -156, 9952, 36, 2524, 2053, 1841, -1670, 10622, + 2532, -5616, -324, -1132, -1148, 1920, 10232, -75, + -630, -10796, 1618, 1104, -2557, -603, 2115, 966, + -3763, -3183, -851, 4502, -1565, 10062, 313, -709, + 10707, 867, 3820, -2747, 3470, -1942, -486, 4092, + -6289, -2363, 556, 3190, 5046, -1869, 2886, 10572, + -948, -4191, 1544, -1727, 721, -3153, -712, 934, + 1610, 1070, 1248, 10645, 2340, -11102, -2744, -353, + -65, -4973, -1782, -1037, 1210, 1192, 1138, 1106, + 9422, 652, -9595, -1663, 460, 9107, -2827, 775, + 1131, 4732, 93, 476, 387, 32767, -161, 266, + -406, 604, 675, 83, -589, -639, 220, -830, + 2200, -142, -2000, -128, 902, 823, 287, 717, + 1857, -1626, 208, 2784, -72, -19310, 6190, -2063, + -9101, 3419, 1721, -2092, 332, -6533, -7594, 1138, + 807, -2582, -668, 410, -497, 1526, 96, 944, + 3319, 1294, -335, 1964, -380, -618, 3069, 101, + 18964, -2298, -10304, -1190, -998, -1384, -11466, -256, + -4475, 4027, -3532, 1828, -1311, -3417, -3925, -221, + 27688, 2277, -1227, 1043, -399, -3327, 515, 1665, + -616, 2724, -546, 4608, -576, -103, -9064, -1281, + -563, -3588, 2174, -824, 3379, -2360, 354, 844, + -7044, -2295, -2613, -11152, 1006, -1064, -17007, 1180, + 387, -8448, 836, -578, 2621, -356, -1476, 2362, + 822, 4547, 118, -11628, 352, 367, -958, -12423, + -65, -1591, -2304, -2880, 1684, 1708, -1693, -781, + -71, 10012, -534, -3672, 417, -2048, -1955, 10491, + -1257, 861, -414, -4058, 3042, 1529, -5823, 6877, + -3918, 993, 221, 2576, -7780, 170, -648, -139, + -3410, 7974, -756, 2657, -596, 12527, -199, 13752, + 2198, -938, -2265, 1736, 257, 1517, -676, -1165, + -2874, -2433, 123, -829, 2605, -10270, -3158, 3624, + 2072, 6960, 1490, 4634, 455, -8175, 1139, -4545, + -1491, 3727, -8738, -1951, 593, 14, 2897, 2490, + -2273, -1436, -10992, 3005, -4392, -3434, -4561, -1014, + -9506, -1609, -1248, -1593, -190, -10472, 3264, -2274, + 5097, -633, 473, 427, 725, 1577, 11032, 318, +-12228, 78, -1116, 441, 1930, 4041, -648, -4324, + -224, 2738, 8826, -40, 327, 1761, 2371, 171, + 4039, -3411, -2495, 1150, -12181, -1704, 35, 528, + 417, 626, 1866, -472, 466, 905, -854, -875, + 1194, 24371, 488, 26, 695, 1777, 798, -169, + -16, -1252, 395, 871, 1170, -635, -1637, 2094, + -5427, -16393, -384, 3872, 33, -687, -1777, -4160, + 3020, -1906, 3868, 699, -400, 6755, -3253, 12699, + 1474, 7312, 991, -646, 26770, 2524, 2144, -500, + 1096, -1869, 1036, -1707, 521, -2091, 1445, 2335, + 107, 238, -227, -120, -32768, 591, -257, 867, + -1231, 650, -465, 356, 431, 762, -516, -594, + 512, 242, 2298, 1012, -1538, -11748, 3551, -5608, + -2174, -2428, 10557, 625, 1002, 27865, -589, -1527, + -1552, 156, 1905, 1041, -4190, 2300, 1603, -980, + -1764, 484, 1555, -2664, 381, 11676, -8848, -3060, + 675, -646, 736, -1279, -1261, -1988, 543, -1880, + 1917, -2165, 2846, 11863, 2076, 10381, -307, 4354, + 73, -2788, -2464, 964, -218, 1552, 1846, 1470, + 577, -594, 725, 30798, 43, 13, -1474, 260, + 1218, 1433, -114, 1020, -648, -678, -1879, -65, + 791, 366, 8547, 931, 1091, 1018, 16312, -1116, + -777, -1098, 404, 180, -899, -2865, -10089, -751, + 40, -2358, -2980, 3574, 7905, -190, 9207, -18, +-18766, -270, -5300, -2023, 2422, -1189, 1267, -1085, + -704, 6823, 2164, 2, 125, -2319, 411, 591, + -488, -566, -3394, 304, -12375, -268, 11098, -150, + -2392, -1255, 3172, 162, 1295, 5897, 7944, 6019, + 3329, -2014, 2957, -4933, 4805, 2780, -5453, 2680, + 3220, 2784, -549, -19908, -1222, 550, -3540, 1822, + 4082, 2399, -6844, 2145, 938, -597, 122, -20, +-14986, -1620, 1575, 561, 408, -6305, 760, 1634, + 2652, -8301, -2988, 1864, 2524, 3228, 7466, -2620, + 410, 1364, 1740, 2204, 1999, 1704, -2601, -351, + -104, 10688, -7166, 134, -346, 11852, -13322, -3171, + -1230, 1109, -2336, -962, -563, 1030, 2832, -969, + -1997, 3233, -414, -8246, -2074, 2737, 3557, 1625, + 1036, 845, 1848, 1710, -10388, -4586, 6915, 2734, + -8693, -667, 1568, 1758, 2396, -3262, -2497, -1472, +-11848, -689, 3379, 1692, 1449, 2844, 8524, -15598, + 337, 590, 3303, -1594, -2548, 4529, 433, -1921, + 920, 1061, -1693, 191, 44, 957, -2397, -1126, + 41, 2164, -1587, 568, -17290, 4687, -1028, -403, + 1169, -1282, -1602, 242, -1234, 1870, 1067, 2444, + 1752, -2552, 8775, 1384, 5683, -4770, -12436, -680, +-13344, -196, -276, -299, 734, 12378, 2364, 327, + -1494, 560, -90, 3394, 496, 2357, 629, -17, + 1040, -706, 589, 294, -1135, 25012, 444, 1206, + -298, 1424, 1524, -2188, -64, -1101, -1998, 374, + 1377, -1382, -11349, 1456, -171, -2369, 6966, -2808, + -8987, 3390, -811, 671, 3032, -3396, -9815, 2246, + 4418, -678, 1851, -1592, -11038, -1194, -3612, 2589, + -250, -495, 1203, 1348, -805, 1853, -345, -555, + -8755, -9695, -3768, -1506, -8172, -322, -7163, -6319, + 2052, 116, -4459, -2328, 4857, -2569, 1419, 959, + 1138, 7034, 4836, 3449, 6826, 13411, -893, 981, + -2060, -3710, 3177, -761, -1128, 4386, -127, 6698, + 3426, -2922, -61, 408, 1426, -1238, 15468, 94, + 373, 3597, -2432, -1989, -859, -8976, 2938, -777, + 409, -206, -7758, 3384, 295, -466, 29, 7925, + 2048, 930, 2296, -10030, 330, 7864, -1004, -385, + 2130, 388, 3587, -4480, 1560, -12768, -2606, 8178, + 771, -3519, -1590, -592, 2192, -1126, -77, -3947, + 1868, -1304, 11107, 781, 6240, 4134, -3314, 407, + -6125, 5168, -503, 2155, -990, 143, 219, -9950, + -1186, -1446, 1930, -8963, -4084, -6141, -976, 153, +-13665, 564, 13631, 138, -269, 379, 1333, -1710, + -940, -511, 1214, -2190, 1347, -1397, -1321, 94, + -1802, 6627, 1306, -12347, 2780, -1091, -4362, 5047, + -446, -3472, 6064, 1075, 478, 769, 58, 802, + 562, -1581, 28580, 194, 1338, 573, -555, 617, + -409, -1249, -8, 1133, 952, -120, 2502, 5313, + 969, -1664, 1769, -12199, 5551, -402, 4862, 3270 +}, + +.cb2224m1 = { + 32767, -54, 1385, -206, 19, 522, -1176, -667, + -260, -1388, -1751, -2234, 228, -343, -893, -898, + -1004, 2517, -232, 20996, 507, -1857, 2574, 840, + -615, -1922, 660, 844, 52, 1272, 609, -692, + 21805, 938, 678, -399, -22, -1839, -996, 1560, + 218, 3973, -6547, -1151, -3914, -789, 938, -11509, + -2282, -606, -327, 3088, 797, -1540, -7598, 1378, + -100, 2108, -1907, -11671, 1538, 11136, 310, -2096, + -3037, 3181, 1731, 2043, 3424, -1098, 2046, 545, + -1778, 605, 932, 832, -2356, -1498, 1129, 11542, + 119, -10994, -3720, 4316, 346, -9141, 3921, -918, + -5476, 372, -318, 9254, -681, 4896, 1587, 1620, + 1850, 4057, -1507, -362, -1074, -328, -1502, -3092, + 2735, -378, -11572, -1292, -2575, -3397, -7566, -8977, + 1670, 8659, -655, 884, 1815, -9348, 570, 394, + 1670, 1942, -195, 386, 553, 8885, -9206, -624, + -2312, 15852, 782, 562, -1497, 720, 1804, 1415, + -3809, 3783, -1918, -3496, -637, 581, 1161, 961, + -960, -930, -1673, 904, 11510, -2286, -9964, 2964, + -5752, 2229, 786, -1479, -18882, 1517, 128, 3282, + 157, -2178, -564, -6029, 766, -4599, 3620, -4380, +-20114, -677, 2134, -93, 1486, 648, -4790, 1862, + -1476, -56, -3443, -2622, -2806, -1185, 122, 1801, + -1547, 12241, -2785, 2386, 56, -4075, -10964, -832, + -4744, -1350, 2849, -255, -1375, 163, 1306, 37, + 2304, -1396, -11234, 9712, 1732, -2262, 3632, -431, + -579, -4045, 806, -12168, -1309, 840, -1474, 918, + -1240, -1601, 48, -4137, 6934, 3968, 7370, 4088, + 8648, 2351, 1466, 615, -12314, -2347, 4382, 862, + -4288, -3138, 1886, -4357, 375, 1949, 73, 287, + 135, -60, -1498, -2427, 1263, 3322, -582, 17508, + -1202, 1558, 3351, 484, -439, -571, -370, 11952, + 11656, -1407, -1410, -2976, -459, 397, 1980, -1374, + 1237, 5044, -2074, 405, -10650, -174, -12556, -1962, + 4569, -1293, -200, 3106, 343, 748, 1918, 1084, + -670, 3, -1070, -397, 3965, 9966, -609, 9691, + -900, 137, 2305, -5944, -944, -1500, 638, -703, + -582, 10098, -523, 776, 1266, 4860, 6213, 1181, + -5634, 518, 9116, -4740, 10683, -547, -1295, -91, + 104, -3115, -1724, -17, 1953, -745, 694, -474, + 12248, -596, -674, 765, 674, 4494, 1205, 5883, + -1638, -3996, -664, 8694, -5620, 3968, -717, -10425, + -285, -12605, 368, -3904, 12363, -1288, 1242, -1497, + -3117, 2396, -220, 1700, -2788, 250, 107, -150, + 345, 681, -44, -2466, -389, 2098, 312, 54, + 2734, -22225, -1232, -1778, 1063, -1586, -6658, 344, + -2889, -4348, -3685, -2100, 12, -1755, -6401, -149, + 8150, -10689, -748, 1443, -32768, 1698, 1461, 216, + 1373, -2814, 1014, 1135, -227, -1309, -616, 1566, + 395, -724, 852, 1579, -9647, -1214, 728, 329, + 9244, 179, 7204, -836, -3954, 168, -5722, 152, + -2886, 472, -651, 5114, 8734, -71, 11406, 1098, + -1452, 1190, 598, -880, 14611, 12540, -1523, 1340, + 1015, 1510, -208, 206, 1314, -1532, -246, -3210, + -1637, -197, 197, -32768, 1448, -191, -1720, -217, + 1021, 973, -2099, 56, 606, 39, -1569, -1205, + -2375, -2156, 4798, 2504, -11914, 933, -6015, 2657, + -2911, -5173, -1964, 1576, 5268, 1190, 675, 856, + -1718, -4332, 166, 1556, 19005, 2040, 1198, -2170, + 1824, -3409, 121, 830, -252, -525, 289, -1701, + 292, 854, -1150, -1108, 171, 511, 22114, 662, + -1263, -540, -2306, -2332, 869, -5191, 186, 536, + 410, -7576, 590, 13625, 3519, 3858, -2787, -376, + -6506, 891, 5025, -2054, 8316, -2115, 7668, -5808, + -2464, -2422, 1541, -3851, 1578, 420, -617, -6507, + -858, 160, 3876, -2830, -5970, -3295, 9829, 1099, + 1617, 3502, -3124, -4116, 138, 287, 914, -548, + 1056, -1546, 1218, -227, 11632, -574, -996, -9894, + 808, -5868, -1457, 8374, -2086, -280, 1038, 528, + 1862, 284, 3926, -144, 7168, 1224, 11628, -221, + 1018, 1683, 922, 561, 6910, 1895, 3044, 12613, + -74, -1424, 1654, 8872, 2255, -990, -2039, 269, + 9558, 10122, 958, 466, -1948, -1242, 1042, 886, + -1143, -3444, -8720, 1918, -300, 19074, -1629, 991, + 908, -896, 1207, 3602, -4802, -2912, 4100, 2936, + -1344, 459, -6904, -714, 524, 171, -1430, 1454, + -2725, 1130, -757, 2861, -11174, -2768, 5466, 3662, + 110, -1999, 12376, -2173, -2508, -2838, -2025, -4378, + 134, -9856, 1738, 1027, 1428, 38, -1560, 12824, + 13932, 549, 586, 720, 923, -1040, -2827, -3272, + 1902, -2113, 2624, 3296, -34, 12291, 1449, -12138, + -796, 186, 2777, -1007, 3276, -587, -1917, -130, + 2120, -564, -364, 1005, -615, 1504, -2412, 9219, +-11412, -2490, 1262, -2720, 1608, -3276, 1294, 1882, + -188, 7090, 6029, -4207, -2739, 72, -10035, -1672, + 1509, -124, -1649, 420, -3623, -1069, -11225, -754, + -388, 790, -3209, -330, -2632, -11920, 3178, -1788, + 2585, 4146, 1944, -2757, -10616, 220, -14136, 2158, + -274, 2010, -362, 1107, -348, -1990, 96, -985, + 1599, 1566, 1393, 304, -1380, -924, -285, 620, + -30, -902, 26210, 1485, 1042, -1160, 352, -177, + 1245, 1879, -18, 727, -421, 223, -1298, 1066, + 962, 1306, 3866, 870, -18780, -3873, 107, -1408, + -1261, 808, -818, 1738, 1439, -2156, -1499, -2108, + -4626, 4039, -964, 16682, -1169, 266, 9373, 1238, + -2728, 2381, 12159, 2155, -472, -2293, -513, 3808, + -690, -2190, -1139, -6, 1379, -22803, 1380, -612, + 308, 1394, -902, -1454, -2620, -1080, -2864, -3301, + 108, 218, 8718, -617, -1098, 1436, -2005, -3966, + -2658, 6152, -874, -4636, 8705, -3382, -12072, 418, + -1837, -12582, 270, -788, -1174, 2156, 461, -297, + 478, -632, -356, 5796, -12024, 416, 2602, 3544, + -1240, -970, 4874, 7221, 704, 8940, 2316, 1174, + 2537, 5380, -5, -1818, 3020, -4120, 7042, -9618, + -1622, 3576, 2455, -298, 451, -5298, 7371, -1570, +-12956, 9758, -216, 889, 5395, -2779, -4036, 1736, + -1871, -2036, -1119, 1847, 912, 2292, 850, 220, + 1300, 2228, 399, -2885, -2696, 2399, 3179, 6266, + 1629, 13091, -232, -5322, 1397, -724, 1666, -2012, + 3643, 1400, -2724, -18007, -506, -103, 1318, 2473, + 965, -587, 1135, -904, -510, -10767, 1937, -585, + -73, -1662, 3021, 340, -12475, -1618, -1, -1914 +}, + +.cb2232l0 = { + -9947, -673, 522, -36, 396, -433, 949, -442, +-12495, -2186, 4280, -997, -1715, -7385, -379, 3498, + -572, -9897, 6686, -4736, 577, 1866, 659, -123, + -1682, 420, -866, 4458, 5821, 3155, 7929, -5562, + -1798, 3086, 8556, -65, -8943, 2354, -4187, -3798, + 627, -1859, -9760, -1811, -1724, -45, -1838, 1638, + 499, 148, -335, 20916, -264, -556, -269, -1014, + -1531, 711, -519, 462, -5117, 3944, -950, 8277, + 878, -4803, -5003, -4402, -4722, 2988, -144, -6887, + 10661, -909, 700, -2287, 12126, -101, -761, 1836, + 827, -609, 538, 442, -4504, 1812, 3818, 7359, + 96, -555, 1598, 10040, -554, 924, 3426, -1786, + 2620, -2132, 867, -519, -2299, -672, -508, 201, + -2457, 10872, -5003, 5422, -8890, -104, 2579, 940, + 401, 871, 11167, 1216, 1054, -2876, -1523, -3950, + -1229, -3410, -428, 3648, -9389, -3025, -1752, 7583, + 3953, 1938, 3899, 1435, 8170, 1019, -2320, 1299, + -1152, 226, 394, 11328, -1471, 604, -184, 567, + -3704, -5723, -5938, 423, 9362, 4546, -3318, -3395, + 5084, -4341, -1781, -2619, 1078, -365, 151, -413, +-21591, -968, -202, -183, 849, -481, 407, -11, + -2708, 2472, 2689, -9232, -9482, -1776, 645, -1510, + -1410, -6115, -114, -2550, 1922, 1668, 288, -1302, + 948, 1967, 52, 2393, -1975, 374, 17358, -1332, + 5303, 3195, -2674, 4784, -1418, -1359, -57, -2126, + 4618, 8890, 6455, 1181, 76, 374, 9585, 8762, + 672, -642, 666, -6485, 1751, 3255, -934, 6196, + 892, 171, -102, -44, -326, 1330, -320, -480, + -842, -22376, -561, -141, 635, -6528, 5711, 2400, + 838, 2846, -3212, -5341, -5479, 4961, 2110, -7480, + -4215, 7964, -1308, 1219, 1541, -4418, 6293, -4522, + -4887, -5760, 2790, 1441, 6135, -1133, -1627, 1235, + 914, 572, -1043, -1473, -519, -4618, -1228, -12212, + 1101, -10794, -4292, -4355, 6431, -588, -992, 612, + -1771, 6751, 4871, 581, 620, -352, 277, 727, + 2226, 8552, -43, 2295, 9409, 1122, 7618, 1885, + 1192, -1432, -1103, 8666, -2078, -403, -1787, 1572, + -2200, -7705, -6743, -1277, -1228, 955, 7613, -1536, + 8530, 5703, 5446, 4251, -853, 4910, 1578, 2832, + 1274, -2610, 243, 2820, 951, 9240, 1617, 605, + -6755, -2728, -5658, 3866, -157, 1215, -8470, -2038, + -189, 10411, 7444, -376, 407, -1128, 770, -410, + 503, 1707, 786, -529, 82, -27, 21512, -282, + 81, -1129, -686, -555, 2674, -99, 1284, 2216, + 1238, 404, -3398, 1010, 3966, -1134, -2682, 14222, + -1581, 9779, -1114, 848, 1905, 2129, -3937, -4742, + 1229, 8051, -4344, 3914, 4273, -659, 159, -1188, + -1844, 912, -1256, -478, -16158, -2869, 959, -2096, + -2166, 2360, 7861, -2718, -6358, 7653, 6639, -3239, + -1690, -1242, 3439, 1254, -954, 604, 17512, -288, + 2412, 211, -298, 2656, -5217, -1770, 892, 1979, + -1482, 3498, -40, 10424, -1038, -1862, 9905, 298, + 77, 2179, -4444, 2580, -2069, -6473, 61, 84, + 1035, -645, -662, -824, -743, -104, -1962, -124, + 4976, -5378, -1254, -7055, -3474, -10695, -1254, 2547, + -694, 3194, -82, -2634, 230, 358, -12, 1594, + -90, 598, -76, -21136, -1278, 846, -84, 259, + -2536, -4442, 2337, -1606, -3264, -3126, -591, -1295, + -2440, -2592, 10888, 5821, -862, -5070, 10402, -10633, + 159, -2660, 894, -2112, -1774, 3732, -1020, 422, + 9487, 1608, -992, 2046, 275, -10676, 2606, -999, + 477, -1868, -1690, 4764, -6419, -7550, 8159, 529, + 2308, -394, -2394, 2826, 6680, 496, 3628, -646, + 3186, -657, -2260, -1416, -9202, 496, 6624, 2441, + 1554, -2195, -8458, -3459, 466, 6706, 1056, -8777, + 5436, -4000, -3130, 4794, -6127, 2008, 1602, 195, + 558, -1362, -880, -2662, 9726, -9793, 2989, -3182, + -2378, -1338, 1086, -4682, 372, -399, 11129, -601, + -666, 5206, -1106, 362, 3155, 328, -9862, 719, + 1602, 998, -2342, 857, 1510, 476, 7256, 4652, + -5750, -4991, 4611, 8718, -4434, -4119, -351, -1606, + -1033, -3717, 3585, 9381, -1594, 5052, -7414, -205, + 2356, -5949, -8738, 1526, -1838, 4760, -5444, 623, + 112, -2863, 5710, 4920, 9497, 3759, 10748, -201, + 716, 747, -2559, -4077, -449, -741, -136, -1303, + -572, 1886, -986, -10529, -51, 1360, 2418, 116, + -1490, 1928, -9977, 4720, 227, -11212, 3730, -2996, + 1300, 9935, 356, -4618, -384, 972, 3174, 3732, + -803, 2666, 790, 2067, 2343, -1209, -10147, 21, + 9066, -4564, 2508, -176, 264, 9834, 3360, 7278, + 9386, -1274, 522, -50, 4150, -884, 592, -688, + 309, 20750, 672, -1326, -346, 366, 2058, -607, + 633, 620, -677, 330, 69, 432, 319, 436, + -300, 21845, -318, -676, 320, -386, 889, -724, + -1394, -2664, -431, 2046, -136, 5520, 6700, 1192, + 5779, 9386, -3541, -5638, -16125, -259, 545, -267, + 1972, -2366, -43, 615, 251, 1003, -980, 2262, +-10519, 12166, 2007, -884, -1560, -1250, -491, -438, + 820, 1212, 3512, 354, -1066, -46, 98, 315, + 8532, 944, -1297, 8011, 1029, -383, -1606, -8381, + -1650, 2852, -958, 1757, -4270, 2160, -9283, 2918, + -3718, -224, 6154, -5671, 3764, -554, 5214, -2526, + -31, 547, 6, 1633, -4562, 1424, 1177, -866, + 1648, 653, 6056, -1845, -1271, -350, 596, -2286, + 9893, -6594, 1099, 630, -537, 230, 972, -134, + -491, 79, 306, -74, 253, 208, -1804, 73 +}, + +.cb2232l1 = { +-11397, 378, 12845, -1813, 342, 329, 1165, 550, + 556, -115, 755, 117, 2511, 260, -1189, -1406, + -1528, 1866, 3300, -9678, 1025, 10413, 199, 2878, + -3572, 8701, -1895, -1189, -576, -3384, -162, -10866, + 3253, -1267, 91, 2277, -86, -3394, 6576, -2475, + -1136, -4295, -1610, -8064, 297, -8908, -4433, -2954, + -82, -11426, -4610, 2063, 1522, -7972, -495, 1799, + 2922, -5179, -865, 4739, 11072, 3927, -483, -11111, + -2375, -1432, 1210, -1342, 2418, 1688, 852, -64, + 133, -4582, -7136, 10558, -3417, -3162, 2033, 3149, + -3050, 2532, 568, -2444, 4082, -2859, -10350, -4983, + 6633, 230, 5954, -1140, -657, -998, 1156, 736, + -8894, 64, 939, -260, -1704, -526, -1330, -869, + -2427, 12377, 1296, -120, -10560, 1794, -9090, 1487, + 7162, 519, -382, -3234, -66, 1294, 2363, 1482, + 498, -4053, -752, -154, -587, -293, 16533, 65, + -1211, 1666, 291, 2820, 2222, 2, 865, 344, + -1206, -1214, -2162, 8842, 11063, -2093, 1896, -857, + -144, 321, -9548, 4464, 5038, -282, 1160, -194, + 823, 3479, -8234, 5834, -320, 7114, -184, -2663, +-11670, 472, -2013, -1282, 4390, 4453, -2126, -2483, + -900, -6262, -2237, -539, -1134, 164, 426, -8969, + -1746, -1960, 8172, -2127, -19948, 657, -712, 344, + -443, 458, -564, 56, 756, -157, 274, -1324, + -3372, 2981, 635, -9454, -4916, 2884, 2316, 8200, + -1452, 2135, 1785, -1054, 82, 5007, -4164, 642, + 9241, 5091, 1002, 2467, -8409, -854, -861, -2317, + 405, -1810, -793, -7907, 496, -1005, 3373, -1016, + 9527, -542, 1672, -9105, 280, 11170, 273, 908, + 89, -233, 10850, 870, 436, 1630, 3328, -499, + 5091, 1224, 9135, -480, -1134, 2428, -2904, 5077, + 2014, 2859, 4277, 7763, 8719, -11474, 1619, 1167, + -3188, -1063, -433, -4291, 2646, 1024, 2008, 317, + 746, 327, 6824, 1174, 8978, 5254, -8948, -136, + -2602, -1442, -698, -950, 1800, 296, -1016, 1653, + 3771, -9326, 4536, 7033, 4729, 6630, 1042, 167, + 11485, 12338, -147, 2834, 611, 1844, -313, 486, + -916, -887, -1423, 642, 242, 75, -1875, -645, + -1239, -2118, 1458, -272, -1703, 949, 778, 21826, + 214, -1320, 310, 2680, -1542, -2202, 1072, -132, + -2067, -3593, -8293, -10331, 9030, 402, -2702, 2984, +-12068, 3170, -1098, -1175, -1188, 2998, 1159, -1712, + -904, 236, 42, 823, 548, -546, -1954, 15989, + -2212, 1886, 2300, 2293, 2606, 2905, 2365, -1214, + 1592, 1362, -2210, 1674, -1892, 15049, -1012, -2824, + -792, -11447, 11144, 4853, -357, -1230, 748, 1212, + -294, -424, -2720, 78, -2149, 966, 7794, 1645, + 138, -709, 464, 3614, -10308, 310, -4726, -3694, + 1088, -576, 690, 68, -145, -3282, -9280, -9537, + -1274, 3202, 588, 1790, 1437, 3880, -1803, -1154, + 15082, -2388, -1746, -885, 2267, 1813, 1688, -1039, + 9775, 350, 3218, 10550, 1048, -3731, -3748, 3517, + -910, -663, -413, -1045, -1236, -248, -132, -1196, + 12, 15815, 653, 1429, -371, 4094, -3050, 567, + -5524, -11128, -4261, 1929, -1719, 8236, 686, 1309, + -1057, -715, -2586, 1327, -38, -6180, 3499, -2080, + 8980, -1890, 62, -1004, 3308, 5809, -5778, -3865, + -610, 180, -519, 3129, 9000, 1607, 8484, -4056, + 4741, -4491, -355, -1324, 1203, -1864, -811, -15995, + -121, 1325, -817, -2170, -5753, 731, -1875, -2286, + -9193, -307, 247, 2469, -1738, -12290, 31, 1028, + 670, -66, -1856, 570, -3542, -3401, 144, -320, + -524, 184, -928, -1606, 10978, -3114, -8861, 1467, + 1156, 872, 8276, 5655, -695, 2788, 3733, 2155, + -2044, -10260, 1683, 1859, -263, 17966, -19, 1621, + 50, -261, -4143, 1245, -22, -1564, 809, 2462, + -8005, 1247, -1471, -763, -1686, -698, 2868, 796, + 4036, -3672, 11209, 1102, -9369, -1008, 1273, -906, + -4458, 1642, -3254, 3563, -94, -6267, -604, 8687, + 2388, 2214, 1759, -7788, 4296, -7467, 3547, 3248, + 845, -7784, -2195, -42, 5327, -1002, -3915, -4581, + -1215, -919, -3444, 5142, -1874, -3020, -2627, 1129, + -4456, 1840, -11472, -914, -6366, 3495, -2775, 484, + -5859, 980, -1967, 1350, 929, 6856, -3952, -3365, + 1514, 7423, -675, -2260, 6027, -3072, -6388, -3716, + -2398, 5564, 1447, -86, 1180, -1239, -1372, -435, + -1314, -1978, 942, -2018, 1027, 704, 20417, -94, + -1239, 252, -171, -1100, 1684, 1401, 623, -354, + -2674, -5042, -734, -6631, 7587, 4901, -1596, 6806, + 4230, -859, -867, 1266, -3869, -3972, 1548, -4889, + 2811, 2263, 2468, 354, -6197, -1278, 1947, 5675, + 10612, -1730, 2056, -70, 3034, -583, 879, -3719, + -8623, -1241, 822, 5832, 163, -1075, -784, 398, + 1170, -717, -374, 856, -21602, 89, -513, 260, + 854, 1152, 762, -601, 523, -107, 1033, 1877, + -1456, 226, -20758, 365, -8943, 1305, 193, 948, + 295, 2696, -3165, -1982, -2439, 1067, -12266, -1018, + 3400, -178, 1995, 11745, 1833, 9785, 1171, 582, + -1844, 157, -1242, -4080, 864, -1771, -4257, 721, + -4010, 7990, 142, 730, 1976, -6623, 4637, -7394, + -1143, -835, 3341, 1732, -7266, -448, 5379, 290, + 1855, 6977, 6637, -6561, -1370, -1767, -2769, -1189, + 3872, -4895, -4679, 3906, -1664, 1514, 7908, -7960, + -4147, -1235, -1706, 3314, 144, 1668, -9505, 2268, + 4147, 2515, -1451, 6475, 1675, 106, 981, 201, + 309, 60, -133, -472, 561, -380, 1130, 91 +}, + +.cb2232s0 = { +-26218, 1606, -390, -696, 266, -947, 561, -1526, + -8, 1080, -187, 5671, 2249, -30, -4129, -768, +-10908, 3826, -10422, -144, -1259, -1372, -3553, 1287, + -5151, 6442, -5101, 1386, 791, -1593, 12942, -764, + 424, -6212, 9733, 702, -9721, 524, -4818, -1232, + 6, -484, -818, 955, 6425, 3594, 5156, -286, + 1514, 4466, -1756, 11321, -679, -1481, -477, -8015, + -3059, 4476, 679, -1143, 2877, 2581, 3230, 239, + 12018, -1597, 13431, 11852, 260, 3306, -714, 1299, + -4375, -778, 170, -565, -3510, -6632, 3354, 5901, + -1070, -5912, -3430, -4970, -4712, 2648, -9113, 1561, + 1002, -5659, -3177, 638, 2289, -1050, 12310, -10364, + 2830, -961, -194, -6442, 2206, 3454, -2087, 4327, + 1080, 10257, 8107, 4904, -3141, -2339, 7568, -363, + 3765, 7960, 7067, 1496, -3842, 1805, 2415, 913, + -1641, -5411, -7583, 4597, -1324, 2882, 11310, -2570, + -2877, 3544, 4642, -2249, 7110, -307, -3413, -2871, + -8974, -6358, -5703, 4046, 83, 1887, -3476, -4346, + -2995, -346, -46, 22143, -576, 2597, 696, 1520, + 140, 2937, -3356, -988, 4090, -1246, -3347, 1387, + 2264, 1282, 7040, -806, -12810, -1105, 32767, -4266, + 108, -1998, -680, -1279, -467, -110, 462, 768, + 1678, 1408, -1888, -1115, 9430, 5852, -3578, 5367, + -1096, -4310, -9588, 4350, 6048, 2516, 3214, 4468, + -276, 15175, -848, -2875, -314, -6002, -11743, 448, + 9238, -3026, -3934, 2840, -2070, 1850, 444, 511, + -542, -7382, 6002, -14447, -1498, 176, 812, -2632, + -2291, -3312, 3953, 370, -2154, 1678, -1186, -6382, + 1544, 3534, -3767, -7459, 7265, -3272, 10669, -1677, + -7046, -1679, -132, 2108, -1948, -2938, -5393, -6222, +-11293, 2066, 981, -731, 1869, -2211, 3558, -21513, + -678, -493, -2087, 245, 635, -2011, -3316, 13445, + 2089, -10186, 1114, -1241, 2121, -2305, 3316, -1282, + 2733, 318, 3534, 4844, -1439, 8932, -7649, -556, + -7519, -3442, 5068, -3546, 8586, -8425, 7146, -683, + 665, 3052, -2581, 248, -8320, 2270, 7045, -800, + 5890, 2187, -251, -2552, -3867, 3665, -1643, -11757, + -5542, 1806, 3669, -508, -3436, 600, 10412, -5426, + 1680, -4545, 11536, -1859, -5446, -4594, -4300, -1173, + 282, 2100, -2556, 9486, -7325, -7252, -3155, -775, +-13674, 4272, 3066, 9352, 1647, 1136, 794, -520, + -654, 1539, -2244, 3155, -12039, 731, 3379, -1904, + 6866, 9669, -2384, 2099, -2426, 1633, -3358, -5662, + 2164, 10679, -5330, 7066, 5826, -187, -4840, -1174, + -3694, 976, -2548, 2292, -3517, -1007, -4041, 684, +-14986, -4789, -4135, -4376, -10678, -1482, -10466, 3575, + -1960, 3185, 1198, -196, -892, -5424, 4802, 13608, + -7772, 3952, 4404, -52, 1097, 3182, -2699, 900, + -1258, -8055, -3102, 784, -2574, 1556, 1060, -5417, + 537, 11991, -650, -487, -10250, 6766, -3716, 1062, + 2525, 1039, -3002, 5742, -502, -4583, -144, -144, + -5896, -978, 1786, -1420, 1944, -130, -5202, -1578, + 7821, -11675, 9980, 5065, 5942, -362, 16344, -801, + 1932, 1242, -10, 791, -170, -2468, -479, 3297, + 4328, 11473, -1549, -12316, 209, 1739, 1875, 1305, + -4310, -13049, -4913, 9208, -966, 2570, -138, 890, + 1373, -1324, -965, 8563, -7560, 490, -1392, 5695, + -5656, 5431, 3974, -1131, -1246, -1334, -3859, -3150, +-12976, -6929, 665, 9393, 490, 2212, 18, 542, + 229, -3925, 1836, 4223, 5268, 1200, 471, 20, + -9914, -5774, 8362, 5929, -7087, 2005, 15624, 1626, + 5419, -1492, -1536, -417, 1957, 2585, -404, -1125, + 2296, 596, 836, -356, 745, -2810, 2879, -2354, +-21682, -108, 726, -862, 593, -42, 266, -1356, + -2119, 19613, 814, 2462, -2940, 222, 3595, 5634, + -807, 1219, 2446, 5666, -1839, 7092, -10581, -5136, + -2408, 5726, -1116, -2348, -6318, 8991, 6750, -5321, + -7344, -2194, -5544, 1705, 12500, 9069, -1966, -4914, + 2225, 3537, -1485, -5141, 434, -1620, -5383, -710, + -5443, 3930, 7082, 667, -3289, -3202, -2097, 1970, +-11647, -2927, -2098, -1345, 3449, -2075, 262, -756, + 1829, -271, -1292, 1079, -5746, -344, 3660, -4456, + 3593, -7652, -1367, -828, -2290, 1063, 4234, -17596, + -911, -6068, 1040, -2956, 2704, 1763, 974, 3132, + 697, 1267, 240, -5520, -12368, 10830, -633, -5939, + 2307, 1868, -2216, -1261, 597, -6302, -5145, 3550, + 7519, -6963, 3752, 876, -1912, 30, -9192, 1075, + -4632, 9108, 1139, 911, 9290, 1268, -1006, -1718, + -6668, 3294, -1510, 6527, 456, -1400, 11424, -4168, + -3940, 4738, -4863, 2990, 3202, -441, -4744, 4623, + -4351, 3997, -11016, -737, 136, 7978, -3801, 4170, + 3602, -2217, 849, -2552, -22232, 323, 193, -4, + -1030, 590, 1625, 3208, -10595, 2624, -741, 13121, + -1044, 1601, 5175, 2199, -3833, 1804, -2314, 793, +-11486, -655, -3320, -2975, 4065, -3124, -706, -7264, + -1038, -3082, -5503, -7147, 8367, 1205, -1092, -1694, + -1078, 11584, 8, -1237, -2077, 9732, 4963, 2780, + 674, 581, 8226, -1231, -9252, 644, -3284, -744 +}, + +.cb2232s1 = { + 32767, -45, 422, -1139, -1052, -2085, -695, -612, + 1451, -288, 58, -878, 53, 2912, -1891, -7148, + 1893, 3028, 165, 963, 2260, -7904, 5857, -18824, + -2617, -1030, -872, 1500, 1118, -745, 143, -436, + 1239, -3840, 1785, -2506, 20237, -1026, -1556, -1371, + -660, -1185, 939, 1315, -3658, -5428, 587, -4105, + 1596, 12612, 5781, 1172, -3490, -1182, -333, 6258, + -2594, 2144, -4830, -190, 1972, 2687, 1327, -987, +-15046, 4659, -71, 6890, 1588, -4787, 4318, -3704, + 496, -5601, 1954, -1250, -3389, -5156, 9238, 2298, + -4945, 183, -2036, 114, 12250, -2330, 71, -3395, + -1402, 3668, 531, 10915, 1162, 7738, 9089, -1250, + 1500, 6357, 1155, -5094, -2641, 1657, 470, 2022, + 535, -306, -18031, -903, 2913, -5486, 1769, -1419, + 9082, 2149, 3516, 6960, 833, 1123, 1266, 1672, + -690, 9634, -2986, -4675, 1006, -2205, -2919, -3205, + -2759, 107, -931, -9694, 2340, -862, -2782, -3636, + -9414, 9564, 1057, 8664, 1326, 3928, 1452, -4692, + -3437, 8610, -10466, -6638, -2879, 3408, 861, -3057, + -823, 164, 3153, -3698, -15693, -886, 1456, 3278, + -6160, -57, 1110, 22, -2985, 7299, -1082, -7921, +-12212, 480, -7645, -211, 1586, 3874, 3242, -883, + 6730, -1597, -506, 3744, 7552, -7607, -65, -1442, + 266, 10012, 1594, -2628, 6988, -1049, -516, -691, + 672, 4913, 1788, 14973, 342, 962, 7212, 1124, + 500, 1135, -311, 3886, 12548, 5432, 6219, 3341, + -122, 5636, 6871, -10831, 4010, -10084, 1456, 5216, + -1013, 1102, 4164, -1490, -5186, -242, -4498, 3322, + 3584, -2176, 5704, 515, -11556, 1446, 4303, -3928, + -4227, -7268, 6069, -11330, 822, -2054, -3035, -2516, + -1816, -3796, 8408, 8849, -3030, -8201, 1149, 7388, + 1036, 2586, 5618, -2274, -5037, -1497, 384, 1454, + 8154, 1672, -2409, 3347, 13258, -979, 513, 7826, + 2662, 1818, 5537, -1104, 2645, -10632, -8767, -5667, + -1029, 806, -9040, -4684, 792, -5008, -5807, -3924, + 964, 313, -2521, 1106, -5728, 13534, -8078, 4216, + -1388, -2588, 986, -14536, -1410, 3461, 1360, -1348, + -104, 1493, -2858, -2860, 2045, 18330, 4814, -3628, + -705, -3228, -660, -2664, 2616, 4548, 3753, 1574, + -1319, -1110, 556, 3304, -2803, 13052, 4592, 2922, + 13667, -2322, -3056, -2717, 174, -4222, -4296, -7695, + 1366, 1786, 1041, -110, -1997, 4102, -1855, -900, + 203, 1311, 3412, 4107, 22609, -4112, 427, -2488, + 257, -1267, -1277, -6430, -7193, 10667, 4495, -4317, + 6846, 13213, 7335, -972, -3137, 335, -609, 3131, + 2406, -3762, 2151, -5188, -7675, 2068, -2027, 3722, + -773, -3276, 1539, -7886, 1005, 13693, 4601, -8386, + -508, 5662, -4889, 93, -10603, 4051, -2, 1094, + -4897, -2274, -2377, 2228, -5507, -464, -3455, -227, + 9433, 8093, -2245, 3701, -1047, -6827, 2037, 1926, + -3610, -15420, -581, -6127, -2075, 2501, -2216, 5385, + -2297, -2660, 1563, 3244, 1418, -2012, 2964, 12235, + -8595, 2728, -3541, -6511, 11038, 11326, -183, -1102, + 1038, 1224, 20, 1441, -349, 1240, -7737, -930, + 1411, 6945, 4130, -13544, -2625, 3550, 3149, -730, + 7658, 3098, 673, -2259, 2556, 1543, 1478, -951, + -8128, 4951, 11919, 4588, -8448, 784, -11498, -1908, + 2578, 2936, -7496, -5834, 1987, 3407, -4133, -4924, + -1348, -1300, 916, 899, 20257, 2027, 1450, 4388, + -3748, 3846, 2187, -1158, 4720, -3613, 5312, 4055, + 448, -6383, -8794, -2232, 1920, 834, 27087, -754, + 90, 1410, -985, -1381, -61, 650, 1080, 7035, + -2772, -1233, 13410, 4494, -472, -2896, -5083, -2217, + -5778, 437, -6853, 4996, 3442, 6092, -6497, -3871, + 4024, -898, -73, -3067, -2793, 5640, 6076, -2454, + 3598, -277, 1672, -6858, 2419, 9753, 6292, 8835, + -9909, -4724, -618, 7266, -416, 1965, -4968, 2421, + 1155, 3815, -116, -3725, 7872, -4901, 2383, 1612, + -2186, -2302, 2791, -2226, 1144, -13379, -6602, -806, + 7099, -2098, 4194, -2128, 8663, -4275, 452, -135, + -6053, 1280, 12815, 3278, 8452, 4479, -1648, 1453, + 1407, -966, -1016, 3173, -7333, -4552, -13176, -1744, + 577, -1572, 611, 1202, -146, -5773, 3012, -3016, + -1581, 3162, 3818, -1970, 6195, 1946, -9656, 2861, + -7875, 3133, -7840, 10951, -1684, -306, -227, 9776, + -82, 1736, 1180, 3457, -2874, 5365, -7428, 7604, + 2623, -2998, -2270, 10410, 1252, -2725, -4433, 1758, + -5225, 6522, 6698, 712, 4694, -2392, 240, 423, + -3030, -12708, -3136, -5176, 480, -1624, -12900, 7537, + 4371, 1186, -1828, -757, -1850, -974, -3755, 1415, + -6302, 2642, -3823, -1570, -8090, 8251, 1945, -9213, + 1147, 4128, -4301, 806, -1745, 704, -2496, 1375, + -802, 9, -808, -252, -5453, 3857, 10353, -536, + 1875, -2896, -10792, 3358, 1063, -890, 7200, 3660, + 406, 2840, -6973, -4469, 4638, -8091, 2772, -8035, + 1728, -5315, 7234, -2718, 3707, -1226, -11858, -2397, + 772, 3285, -4089, -1400, 1113, -16680, 1885, -435, + -959, 242, -817, 259, -2010, -1857, -557, -914 +}, + +.cb2232m0 = { +-13394, 14382, -488, -1088, -817, 100, 305, 2267, + 2527, -1584, 995, -5781, -3585, -1826, 803, -4108, + -3137, 12111, -211, 838, 4879, -1964, -1728, 13830, + 2084, -11535, 664, -2499, -3421, -703, 4528, 968, + 1008, -12010, 984, 2658, 422, 1412, 10772, 2216, + -4291, 1329, -2324, 2392, -2029, 12322, 1053, 169, + 12635, -902, -62, -670, -3007, -3322, -2948, 1817, +-10688, -1264, 1949, 2734, 1072, -1429, 2085, 10312, + -1685, -4433, -1287, -9620, -1132, 20, 614, 2470, + 2821, 5934, 3526, 11292, 50, -12970, -11948, 1114, + 1980, -945, -713, -5357, 3766, -447, 969, 2247, + 11854, 2148, -12393, 1518, 610, 4527, 1164, 1347, + -1422, 649, 653, 855, -24, 30152, 20, -564, + -2825, -11, -1408, -80, 239, 305, -3163, -854, + 568, -18, -4212, -403, 288, -3009, 229, -1152, + 16390, -877, -458, 316, -128, -12165, 1088, -828, +-10886, -269, 747, -1026, 1716, -10920, -9204, -3123, + 958, -6128, -260, -851, -1524, -2386, -6472, 228, + 2667, 3158, -140, 1719, 2330, -2730, 3080, 44, + 15743, -2167, -11637, -607, 476, 408, -12505, -1862, + -1892, -440, -3785, -2348, 1229, -338, -438, -797, + 29933, -715, 366, -197, 576, -188, 484, 240, + -4844, 1168, -1054, 863, 875, -295, -16091, -1972, + 3976, 3833, 3056, -770, 1011, -3098, 165, 3973, + -9367, -18, -299, -11254, 1005, 8644, -14788, -2268, + 2644, -8410, 578, 2169, -766, 2764, 2378, 3282, + -2710, 7612, -542, -12062, -2437, -414, -506, -10332, + 2732, 839, -2593, 923, 1159, -1057, -7333, -86, + 2832, 11328, -1616, -302, 4399, -547, 6107, 9983, + -6901, -85, -544, -4916, 366, 4878, -8662, 7313, + -3056, -1027, 2381, 8906, -7270, 509, -1124, -2512, + -1636, 5830, -5868, 2369, -3236, 12557, -2713, 12793, + -2957, 1688, -852, 4723, -122, -2336, -4698, -1306, + -7399, -2090, -1953, -1505, 3335, -10906, -2598, 1322, + 2556, 7210, -1553, 1262, 1878, -10719, 1746, -2736, + 1448, 8734, -9602, 828, 1752, -1632, 8037, 2728, + 562, -1879, -10572, -544, -2254, -1997, -6384, -87, + -5878, -473, 498, -2960, -5698, -11500, 1815, 2050, + 7388, 5230, 2782, 5602, 514, -306, 13022, 523, +-10776, -846, 716, 270, 3350, -6021, 1420, -6175, + -1978, 3967, 11612, 3320, -4100, -2468, 4595, -5338, + 65, 3478, 19, 3501, -15896, -1335, -1861, -1944, + 3935, 3630, 4627, -5892, -458, 383, -211, -594, + -165, 24865, -656, 2300, -404, 257, 214, -643, + 2298, -180, 35, 4974, 834, -998, -1738, 5449, + -9222, -10858, 4188, 9147, -5639, -1691, 990, -1945, + 3421, -3527, 9005, -2038, -2369, 5098, 967, 15840, + 196, -3204, -1079, -776, 11806, -1352, -2053, 2011, + 309, 642, 1541, -1466, -4465, 6679, 5756, 7474, + -58, -1864, 5908, -1576, -30374, -904, -571, -1136, + 425, -22, 666, 1150, -734, 82, 1254, -226, + -437, -890, 1464, -3368, 987, -11885, 1127, -7224, + 1872, -8198, 8775, -2695, 1457, 15102, -899, -1384, + -1975, 1891, 3128, 1465, -1649, -1363, 1483, 303, + -534, -7, -1710, -1377, 769, 12698, -8987, -802, + 4636, 572, 2004, -3513, 442, -9863, 3215, -4550, + 2138, -4346, 5682, 11053, 7220, 9842, 797, -1399, + -2679, -5857, -2143, 3241, 2330, 248, -630, 1044, + 639, -3432, 125, 22083, 1976, -1003, 813, 552, + -571, 4358, -6200, 3635, 5439, -636, 233, -4856, + -3519, -460, 6956, -4215, 1537, 7895, 13910, -7637, + 1392, 1572, 648, 3690, -1988, -2463, -3302, 677, + -924, -535, -6025, 4126, 7178, -4145, 4960, -1860, +-10926, -1470, -9506, -226, -258, 32, -479, 2222, + 94, 11358, 3984, -2732, 2111, -590, -2444, -344, + -425, 598, -1382, -1213, -17632, 1566, 1387, -3521, + -57, -1829, 4788, 574, -206, 7962, 9157, 6459, + -1594, -1355, 4874, 1066, 2006, 1793, -7569, 2369, + 1108, 1305, -3046, -14052, -1736, -4045, -4328, 7497, + 3304, 1518, -5666, -529, 4256, 4667, 932, -1495, +-10414, -414, -2110, -3150, -1250, -8799, -419, 5162, + 8497, -8720, -746, -3015, 6403, 3855, 7350, 165, + -59, -958, 5780, 6044, 1736, 3016, 31, 1012, + 3422, 7598, -6837, -2092, 2262, 6171, -10362, -2108, + -1352, 1798, -4872, -6369, 2507, 2640, 6074, 1835, + 2948, 388, 398, -9295, -5384, -2088, 2096, 742, + 3286, 441, 7135, -2112, -9958, -5612, 2479, 5427, +-10114, -674, 308, -1037, 770, 514, 1868, -252, +-11901, -984, 670, 2506, 5396, -1047, 9113, -10865, + 4872, 1720, 2226, 947, -2336, 2649, 173, -1464, + -2874, 4463, -1270, 3429, 6242, -5380, -7772, -4550, + -8451, 2045, -2855, 5336, -15066, -418, -4886, -648, + 3736, 945, -956, -4825, -116, 130, 1889, 9642, + 3790, -4371, 7180, -1556, 6562, -2207, -7910, 506, +-21594, 662, -338, -943, -1022, 6453, 301, -464, + -457, 840, 3313, 10946, -294, 8156, 138, -1425, + 2397, -792, 6468, 4615, -511, 15938, 494, 274, + -5976, -660, 3894, -2140, 1424, 2003, 4101, 2823 +}, + +.cb2232m1 = { + 20456, -1952, -1581, 869, 628, 76, 1404, 4060, + 508, -3177, -946, -2992, 2422, 1139, -1931, -240, + 1011, 365, -1106, 20973, -1438, 372, 137, -1058, + 1171, -1252, 2794, 1434, 1814, 482, 3948, -2704, + 20422, -241, 441, -1121, 499, 1036, -918, 9708, + -3166, -488, -10379, -3201, -5254, -1871, 5665, -12622, + -7591, 127, 1469, -2267, 1813, -4197, 2065, -602, + -395, -652, 333, -19114, -1092, 4310, 1590, 1688, + -1453, 177, 4402, 1168, 5972, -1295, -3258, 1542, + -4832, 3377, -5545, -3622, -4944, 2064, -2846, 8118, + -845, -6778, -3640, 5729, -907, -11007, -5, 2634, +-11118, 2108, 144, 13299, 251, 336, 563, -75, + 3004, 169, -3892, 1477, 1066, -1571, -1113, -1088, + 517, 465, -21841, -1541, -1094, 1841, -9213, -17478, + 1662, 8, 1192, 1174, 1014, -5659, -695, 316, + -5161, 1803, -1056, -2369, -2919, 2941, -9712, 1975, + 426, 11214, 2288, 6186, -7348, -3062, 3341, 3252, + -4102, -346, -876, -7088, -3330, 4507, 310, -1632, + 299, -2636, -2740, -752, 10159, -7201, -9568, 3134, + -4002, -41, 2479, -1816, -14099, 3575, 1161, 6427, + -2466, 390, -1883, -6265, -1266, -263, 1474, -592, +-21234, 94, 4187, 1, 3227, -3273, 1950, 406, + 543, 1661, -2648, -9252, -2048, -5987, -722, 4932, + -4410, 12504, -1572, 2244, 5610, 307, -9710, -3642, + -6436, 4368, 2956, -2269, -6196, 4069, -766, -3695, + 3416, -5786, -9668, 11677, 1208, -965, 1516, 1132, + 1018, -6168, 1970, -10357, 1379, -725, -8789, 3730, + -65, -4758, -1818, -1050, 9641, 4519, 2886, 2667, + 6348, 2436, -438, 1978, -9374, -1286, 3893, -2073, +-11199, -2081, 3345, -3444, -9480, 2410, 1986, -1869, + 3252, 5949, -2119, -401, -214, 3416, -1067, 18510, + -2986, 3510, 508, -357, -837, -1205, 2884, 11587, + 11565, -555, -2664, -873, 3642, -2068, 1734, -4408, + 330, -181, -1358, 1407, -9739, 809, -10203, -2066, + 3440, -2063, 3238, 3734, 1671, 750, 6890, 4068, + 1238, 493, -1330, 76, 8918, 10855, 85, 12236, + 3570, -1074, 3008, -9424, -3186, 1271, -380, -157, + -4974, 10575, -1378, -219, 1354, -1589, 10936, 2268, + -3787, -1040, 7567, 924, 10490, -806, -1318, -1576, + -209, 93, -3745, -3820, 439, -9828, -6265, -864, + 31342, 35, 1332, 443, -590, 846, 104, 868, + -863, 1526, -1088, 11494, -7055, 3564, 109, -3072, + -2234, -4530, 1866, -3425, 9940, 3158, -1821, -680, + -1124, 2884, 1191, -61, -9698, 7596, -558, -9019, + -1181, 208, -1342, -68, -312, 294, -1468, 1410, + 39, -21081, 724, -2137, 935, -8, -10297, 3509, + -6510, -6558, -6906, -1905, 1915, 5920, -8983, 3416, + 7300, -1372, -1422, 1822, -10433, -2530, 1669, 554, + -3008, -3351, -922, 8279, -5184, 5520, 4785, 683, + -506, -4558, 1938, 8442, -12639, -54, -2907, -820, + 10004, 1780, 485, 1401, -3786, 786, -5937, 2632, + -1540, 972, -3342, 2294, 8076, -1006, 11731, -1825, + 3036, 1085, 1160, -9680, 11111, 7838, -2504, -2112, + 2376, 2534, 3624, 555, 3610, -520, -831, -15, + -498, 167, 711, -22685, -999, -1466, -1643, -394, + 5404, -4247, -2307, 4052, -1156, -1240, -490, -1598, + -4365, -8382, 10493, 464, -16592, 3723, -7709, -821, + -4218, -922, 398, 5635, 2184, 5090, -7144, 2420, + 792, -324, -1278, 3172, 13101, 1608, -3996, -2219, + 2995, -6924, 816, -2482, -406, 3458, 503, -8154, + 3460, 2542, -3703, 8524, -61, -430, 23212, 1203, + 2335, 5556, -476, 923, -565, 593, -1611, 1814, + -1614, -7067, -1957, 10166, -4306, -421, -4026, 1854, + -9881, 667, 7720, -2906, 7003, -1823, 6344, -8614, + -2965, -2720, -62, -802, 1945, 4574, -4604, -8341, + 518, -3543, 95, -4262, -5220, -133, 10270, 1999, + 3234, 8900, -4866, -3708, -4465, 4542, 2545, 1770, + 6995, 3559, 1133, -1152, 14680, 1002, 634, -12913, + 1686, -1645, -1796, -50, 112, -1108, 1070, 686, + 1068, 1555, 896, 3498, 10458, -32, 12017, -737, + 650, -432, 404, 170, 10873, 1864, -1718, 11061, + -1556, -3766, 225, 6999, 1730, -6919, -1895, -2919, + 8250, 10050, -4631, -1488, -4801, -1504, -2736, -110, + -3630, -2752, -11162, 1128, -2580, 11692, -678, 1338, + 2175, -6030, 616, 1651, -7034, -3057, 2420, 1998, + 4383, -1721, -10762, -428, 2902, -906, -4298, 2141, + -1242, 5464, -607, 5389, -8946, -3890, 10884, 1544, + 628, -1969, 13902, -1570, -1080, -689, -4676, -3642, + 753, -11351, -110, -744, 4286, 1163, 3105, 9752, + 11143, 4296, -1698, 1012, 2284, -989, -958, -9481, + 738, 24, 426, 1638, 3898, 8885, 2938, -8826, + 2982, -1679, 8466, -651, 5144, 2736, 751, -84, + 7710, 3077, 2885, 146, -1102, -2569, -2039, 11059, + -9950, -1048, -1031, -33, -5118, -1096, -1986, 2306, + 2400, 9320, 6188, 500, 2090, 61, -11357, 118, + 1505, 1032, -1920, -164, -9744, -4670, -11029, -102, + -960, -1023, -2570, 4102, -3989, -11478, 772, -1515, + -1102, -2194, 1722, -1195, -8144, 746, -9534, 3250 +}, + +.cb4440l0 = { +-14497, -1982, 631, -984, -2115, -3252, 2755, 2017, + -2110, -8864, -792, -1291, -2761, -2365, 698, 1047, + 972, -14703, 10590, -3945, 663, 972, 1204, -2801, + 1295, -1296, 50, 1448, 888, -1879, 122, 78, + -183, -588, 16202, -388, -2240, 1136, 1266, -6445, + 2619, -1664, -6329, -2700, 1557, -497, 598, -110, + 1298, -334, 191, 29897, 387, 419, 76, 152, + 533, 78, 112, 101, 158, 136, -236, 88, + 43, 107, 84, 21, -6385, -1711, 1757, 1411, + 9152, -72, 1428, -1098, 10328, -506, -360, 285, + -36, -2816, 819, 88, 176, -481, -172, 2067, + 3268, 5479, 8605, 11272, -1880, 361, 1582, -4973, + -1379, 3835, 74, -3, 493, -431, 1390, 101, + -550, 59, 476, -469, -583, 568, 732, -1015, + -1104, -698, 23922, 1130, -1268, 280, 204, -59, + -9789, -317, 935, 2944, -10402, -2564, -4648, 1506, + 3834, -1002, 2805, -158, -409, 814, -150, -97, + -3573, -1550, 1356, 5350, -365, -2622, -3454, 310, + 1194, 911, -10928, 937, 7980, -5286, -554, 1999, + -1263, -562, 10, -321, 744, 44, 64, -274, +-30136, 340, -1051, 756, -30, -6, -269, -273, + 12, 95, 1565, -13194, -11810, -485, -1574, 414, + -240, -452, 564, 740, -476, 959, 1079, -1568, + -422, 37, -154, 10117, -68, 1412, 11862, -3420, + 4169, 5178, 527, -1027, -1030, -1985, 448, -716, + 1696, 1942, -254, 308, 1100, -790, 8102, 6630, + 3653, -1018, -587, -6990, -19, 1671, 1425, 8089, + 3708, -1182, 774, 659, 113, 437, 50, 835, + -532, -11209, 1682, -7490, -2592, 1234, -4689, -7301, + -143, 3361, 1121, 177, -473, 513, 136, 965, + -4020, 4639, -1212, 1271, 2905, -6865, 10499, -3800, + -3354, -5029, -3606, -950, 4490, 526, 1006, 2, + 1760, 5819, -55, -1098, -1843, 348, -2062, -9196, + 3712, -11466, -3218, -858, 2720, 589, 320, 861, + 59, 5357, 564, -380, 538, -142, 490, 212, + 1716, 670, 1904, -181, 2979, 943, 16916, 1271, + 988, -802, -1490, 9154, 643, 1725, 1347, -2827, + -4096, 485, -7091, -3180, -4747, -1604, 1576, -5724, + 6104, -139, 1726, 11715, 360, 7519, 2513, 5192, + -2208, -1993, 829, -387, -5724, 4418, 116, -2955, + -226, 249, 377, 2149, -2929, 5021, -3064, 800, + -1459, 11384, 8556, 1740, 368, -2839, -2049, 1438, + -1357, 4084, 1896, -528, 1621, -1760, 13741, 302, + -1018, -9774, -3521, 1302, 1374, 1139, 918, -1724, + -764, 858, 804, -1772, 372, -322, -526, 11924, +-11944, 4012, 1749, 1737, -1545, 68, 889, 280, + 690, -2200, 1068, -484, -171, 455, -44, -3178, + 2243, -590, 749, -792, -19876, 198, 236, 2695, + -3413, 652, 284, -820, -1134, -199, -112, -5650, + -418, 1047, 1090, 2260, -3297, -2164, 13524, 1720, + -326, 910, -1706, 3912, -1175, 1687, -2152, 50, + 35, 1718, 721, 9316, -2256, -4330, 6961, 4432, + -8043, 45, 1370, 3472, 2892, -3224, 1368, 1355, + -562, -694, 746, 198, 1188, 2819, 3131, -2371, + 6438, 847, 2111, -10187, -3451, -9826, -3502, 655, + 649, 1460, 270, 118, 45, 192, 188, -1139, + -258, 663, -84, -27519, -765, -905, 357, -4, + 89, -372, -24, 178, 1127, 209, 1177, -2762, + -587, 1488, 8989, 3217, -2550, 215, 9540, -7196, + 1259, -3716, 2767, -261, -216, 872, -3008, -2076, + 8682, 709, 3629, 87, -3114, -10624, 246, -1670, + -1738, 1229, 7624, -1120, 784, 305, 233, -185, + 280, -1466, -268, 198, 499, 308, -2187, -1149, + -388, -38, -338, -1084, -19424, 40, 1958, -2240, + -86, 264, -9876, -1287, 4086, 3742, 2502, -10078, + 4574, -1493, 1078, 3218, 2410, -364, 1049, 2638, + 35, -1295, 200, -2847, 10818, -12064, 2375, 348, + -353, 2788, -821, -3196, -511, 146, 2015, 235, + -1094, 2622, 2688, -79, 5176, -884, -11814, 794, + 2696, -6704, 3452, 1295, 3872, 2924, 4498, -166, + -598, -1213, 891, 5478, -266, -777, -5, -776, + 1003, -1837, -156, 17910, 453, -297, -1545, 857, + -288, -308, -6373, 2045, -1846, 3007, -2236, -1904, + 815, -2889, 4200, 8320, 9872, -614, -834, 3856, + 414, -234, 1559, -7451, 3641, -1230, 837, -127, + 2652, 411, -532, -12548, -1692, 1034, -2418, -968, + 558, -1564, -1952, 307, -1064, -6776, 1588, -2636, + 949, 8272, -12, -3468, 3481, 6588, 2580, 7393, + 272, 1528, 1818, -2206, -349, -396, -11704, 1487, + 9753, -4665, -24, 2084, -780, 5036, -647, 3668, + 561, 1099, -1094, 534, 1270, -99, 1006, -476, + -528, 12481, 1589, 1593, -1682, 7022, 2664, 8702, + -563, 1082, -206, 87, -1978, -144, 228, 1232, + 889, 14340, 65, -1061, 10510, -95, 649, 53, + -962, -383, 2479, 1322, -1798, 2840, -492, -419, + 90, -680, 79, 1026, -20912, 1593, -742, 1086, + 516, 699, 2393, -64, -2010, 46, -859, 111, + -440, 14281, 272, 797, -10141, -3734, 3126, -3050, + 1300, 73, -1754, -1278, 1890, -2710, 704, 1160, + 1, 269, -24, -622, 124, 138, -522, -510, + 95, -402, -27306, -470, -214, -159, 396, -201, + -372, 122, 136, -1005, 744, 1949, -810, -2648, + -726, -384, 955, 1232, 1354, -345, -19485, 1056, + -193, 1257, -263, 398, -752, 602, 98, 793, + 17, 20186, -189, -2615, -174, 166, 436, 411, + -1046, 374, -471, -253, 233, 8352, 1342, -1279, + 9305, 2190, -3239, -5262, -3454, 1844, 684, 303, + -4434, -6041, -3495, -2482, 389, 353, 159, -14, +-29179, -511, -158, 92, -401, -36, -297, 447, + -605, 269, 85, 212, 8, -118, -130, 207, + 13150, -8712, 2504, 1355, -3268, 1396, -4748, -2200, + -1560, 228, -162, 1179, 3024, 742, -860, 69, + 10, 30006, -538, -489, -125, -214, 364, -682, + -283, 532, -134, 227, -448, -20, -266, 70, + 2, 9310, 14858, 856, -493, -3357, 36, -248, + 214, 281, -73, 3268, 745, -245, -1007, 146, + 392, 36, 8042, 2953, -6603, -7697, 4425, -2498, + 571, -2194, 3388, -794, -561, -2763, 1912, -3030, + 225, 214, -27, 834, -10661, 437, -506, -535, + 8397, 1332, -2406, -8868, -2972, 1385, 296, 865, + 2318, 890, 244, -121, 226, 375, 896, -10381, + -2266, -3404, 983, 1255, 259, 11427, 455, -3041, + 307, -2446, 476, 723, 18, -10224, 510, 552, + -654, -876, -465, 628, -12572, 786, -393, -4162, + 938, -1327, -1695, -608, -1352, -131, -880, 830, + 1016, 21875, -408, -1560, -500, -1682, 453, -930, + 1316, -136, 434, -683, 412, 202, 233, 382, + -2002, -9267, -1034, 8710, 434, -8121, 3035, -3121, + 1792, 2712, -1537, -1082, 854, 1337, -1084, 91, + -4485, 2545, -4412, -1930, -12234, -4802, 4641, 437, + -928, 2163, -3154, 521, -665, -1200, 2654, 931, + -388, -118, -1144, 133, 5089, -1194, -1528, -967, + -795, 188, 1918, 897, -7046, -7617, 7118, 5755, + -2724, -7894, -472, -360, -591, 990, -3032, 7742, + 726, 5490, 9383, 479, -3032, -1904, 7158, 4706, + 2442, -1576, -58, -156, -3977, -2696, 4195, -166, + 3342, -1566, 3767, -4159, -5750, 5505, -7663, 4516, + -4073, -2612, 5136, -290, -666, 1282, 776, -566, + -602, -310, 1003, -648, 2928, -3159, 427, -1168, + -2702, -16990, -205, -343, -1196, -1980, 1653, -512, + -1820, -418, -3368, 3522, -1966, 4964, -5728, -5185, + -210, -1721, 10131, -7060, 3351, 334, -96, -3193, + -1713, -614, -2633, 147, -1552, -2363, -3724, -1731, + -7350, 5453, -2732, -2867, 12458, 416, 0, 4414, + 833, 590, 1617, 405, 73, 868, 232, 195, + 15, -196, -782, 749, -955, -84, 1176, -553 +}, + +.cb4440l1 = { +-12227, -3413, 12848, -1336, 20, 894, 254, -1001, + -1381, -406, -1157, -458, 300, -395, 825, -34, + 74, 382, -1018, -10266, 1338, 11091, 544, 797, + -4304, 1389, -747, 1924, -257, 2615, -37, -4375, + 782, 158, -378, 19, 652, -539, 1012, -4211, + 1263, -925, 96, -9226, 5921, -8209, -71, -1838, + -2201, -7441, -60, 393, -5626, -264, -1002, 85, + 1989, -1616, -216, -914, 9907, 8044, -578, -7830, + -1705, -3624, 2430, 59, 5813, 870, -317, -2545, + -4020, -1330, 1215, 9352, 5425, 324, -4803, -681, + -506, -4710, -6574, -4184, 65, 729, -1310, -1387, + 1385, 2364, 1672, 2493, -438, -1367, -907, 38, +-20220, -1644, 512, -413, 348, -112, -532, 785, + 1332, 7140, -1916, -1766, -11570, 1811, -9167, -76, + -1531, -175, -1739, -771, 2014, 519, 15, 576, + 8736, -979, -28, 1830, 329, -302, 12206, -1501, + 5195, -305, 1456, -581, 1488, 142, 235, -157, + 192, 1540, -922, 11056, 11823, -2964, -1488, 1712, + -2018, -880, -3282, -190, -198, 2436, -248, 222, + 22, 863, 1504, 2078, -2047, 216, -1270, -732, +-18252, 1186, 3178, -730, 432, 934, 1617, 873, + -491, -70, -768, 679, 1398, 537, -364, 172, + -541, -94, -24, -129, -26725, 201, -554, -357, + -71, 60, 96, -1665, 1425, 1244, 332, -1068, + 326, 834, -620, -1473, 1585, 1432, 928, 18782, + -1388, 2897, 448, 40, 1323, 1433, 787, 215, + 3297, 2586, -856, 451, -17700, 735, -43, 405, + -1252, 744, 1012, 677, 312, 206, -279, -432, + 6677, -87, -72, -10400, -106, 11224, 1152, -422, + 2024, 704, 2462, -1197, 232, -119, 4, -879, + 1600, -708, 3496, 279, -143, -1096, -555, 4594, + 1486, 161, 942, 2018, 2474, -16010, -380, -193, +-11415, 457, -276, -11220, -1604, -38, 813, -4044, + 1888, -4265, 1647, -882, 981, -734, -110, 140, + -3050, 1248, -549, -1167, -967, 3586, 688, -1380, + 424, -17959, 2022, 2274, -44, -1406, -432, 1335, + -659, 9555, -3581, 11045, 1870, 806, 599, -2065, + 156, -4420, 16, 2349, -609, -3058, -738, -60, + -548, -119, -49, 26, 1528, -1842, 6306, 14078, + -692, 5480, 321, 1996, 1376, -3086, 490, -54, + 1151, 932, 445, -9887, 15808, 3085, 866, -2020, + -1785, 2126, -920, 414, -290, 138, 244, 994, + -702, 1410, 330, 202, 675, -389, -241, 31306, + 380, 300, -53, 804, -109, 413, -44, 6, + 14, 486, -293, -112, 26, 11632, -836, -3948, + -518, -1364, 11360, 3558, -588, -2084, 490, 381, + -955, 2207, -2953, 1115, -265, 2, 65, 464, + -180, -111, -174, -152, -30508, 121, -207, -835, + 1126, -185, 91, -96, 222, -99, -93, -10138, + -430, -184, -372, -194, 953, -100, 382, -1422, + 13931, -1835, -1657, 821, 408, 808, -601, -463, + 7142, 5596, 3171, 2174, 2740, -11350, 1019, 1449, + -386, 1642, 3703, 4271, 1664, 2232, -674, 983, + 551, 8543, 154, -383, -2419, 1117, -520, -10966, + -4406, -3742, -79, -909, 1813, 5043, 412, 1099, + 1434, 173, 788, -92, -1004, 1288, -87, 931, + 10241, -855, 6, -405, 2580, 11455, 1150, -1916, + 3614, -262, 292, 897, 9673, -381, 1711, -2713, + -1111, 282, -2180, -2282, -2266, -724, -849, -11787, + 888, 3120, -1459, 495, -10812, -792, -274, -984, +-12223, -737, -2394, -299, -578, -2758, 1521, 774, + 1938, 857, -1935, 217, 654, 1452, -3695, 6734, + 804, 134, 946, -2156, 9495, -600, -1962, -5252, + -246, 1269, 8492, 1261, -2205, -106, -1314, 828, + 1013, -12059, 663, 436, -2648, 9863, -630, -2961, + 3004, 1015, -3153, -1475, -25, 399, -846, 430, + -1237, -156, -187, 1115, -502, -363, 386, -2820, + 942, -926, 727, 1130, -20388, -274, 1140, 198, + 199, 2548, 442, 157, -1546, 3693, 892, 460, + 6552, 4858, -2560, -8673, 1930, -8913, 3427, 686, + 61, -8830, -358, 1338, -74, 1180, 2871, -3822, + 104, 2414, -1742, 11425, -4522, 393, -3016, 972, + 34, 117, -16113, -6900, -6964, 1726, -843, -242, + -2141, 803, -1093, 442, 1776, 2429, -1000, 489, + 393, 635, 389, 1126, 12285, -1648, -11396, -2885, + -56, 3840, -174, 3177, -1708, 1189, 1914, 1514, + -189, -88, 276, -240, -120, -2929, 9823, 678, + 568, 26, 10080, -2575, -806, -64, 6406, -82, + -1171, 2169, -1804, -667, -37, 54, 4208, 10829, + 11920, -468, 1916, -809, -370, 144, 3616, -263, + -4352, -124, 300, -246, -440, -115, 447, -407, + 20869, -340, 54, -764, -807, -699, -283, 727, + -922, 1098, 577, -6, -809, -50, -115, -75, + 280, 156, 182, 225, -30432, -212, -417, -245, + 177, 94, 4, -627, 167, 47, 152, 148, + 1325, -2436, -10063, -696, -9966, 1032, -1024, -3702, + 3933, 400, 333, 692, -3858, 2599, -1215, -389, + 393, -666, 2135, 10280, -2443, 1972, 410, -392, + 590, 12322, -523, 1141, 52, -1468, 819, -213, + 162, 116, -614, -10630, -204, -1247, 535, 199, + -6058, 2538, 1644, -11539, -1562, 1462, -1493, -218, + -296, -605, 321, 607, -366, -257, -837, 4536, +-11683, 1266, -3805, 4496, 2854, 8, -8848, 124, + 656, -1041, 411, 144, 916, 445, -91, -260, + -149, -882, -433, -121, 345, 68, 349, 821, + 652, 251, -23053, 1015, 712, -73, 7038, -1520, + 5810, -12604, 2841, 425, 265, 1546, 938, 1851, + -1180, 2751, -498, 1289, -774, 327, 4047, -8132, + -2622, 5449, 3221, -2990, 10107, 1880, 173, -4006, + 399, -332, 642, 297, -4513, -1230, -330, -788, +-21881, 903, -1308, 547, -522, 1885, -1730, -63, + 973, 897, 670, -657, -232, 498, 92, -8, +-11010, 1072, -368, -1864, 11505, 3497, 730, 2158, + -1629, -1351, -1583, 2247, -1506, 2144, -902, 639, + 175, -6006, -986, -4246, -1510, 1785, -9792, -495, + 1995, -9189, -1414, -2550, 1578, 2390, -2989, 1673, + -1980, 21, -4054, 8552, 1155, -301, 1204, 3776, + 262, -1828, -1837, -1014, -9, 2711, 1467, 463, +-11605, 1743, -956, -1213, -3892, 1534, -10298, 22, + -902, -658, -1759, 2507, 1552, -12298, -1050, 623, + -3221, 1522, -36, -446, -5925, 2144, -2844, 15080, + -1984, 3631, 1931, 1894, 1193, -1694, -3172, -813, + -1336, 534, -365, 833, -293, 21759, -1266, -1216, + 996, -2, -393, -858, 759, 969, -230, -151, + 977, -874, 119, -896, 262, -118, 89, 95, + 94, -437, -30375, -462, 360, -588, -334, 86, + -1027, -208, 536, -196, 367, -467, 119, -32, + -2544, 6204, 8830, -264, -7847, 848, 2267, 3877, + -6378, -2249, 1420, -1868, -3443, 3747, -590, 58, + -274, -6065, -8472, 5906, 3109, 5834, 3905, 2086, + 1300, 3828, -518, -528, -3672, 1794, 4353, 408, + 566, -2577, -1137, 2749, -2662, -528, -7479, 5550, + 2932, -336, 3681, -2034, 212, -8733, 1017, 2258, + 8225, 387, 227, 877, 2752, -1375, 2636, 8131, + 3850, -6870, -1158, -3736, -8478, 228, -5809, 97, + -2555, -2956, -928, 678, 112, 1434, -1250, 1240, + -412, -4267, -3811, 4322, -3430, 7705, 5456, -6876, + -3452, 7329, 3142, 220, 662, 1531, -5492, -1388, + 6842, -3631, 362, 5029, 8052, -2367, -5346, 5724, + -358, 2469, 2196, -1426, -272, 534, -192, -531, + -705, -70, -259, 93, 335, -94, -145, -17, + 920, 1186, -818, -599, 343, -19859, 2968, 161, + 128, -4282, 598, 152, 1210, -1317, -1545, -229, + 181, -6488, 5699, 7270, 6271, 8809, 27, -4770, + -804, -168, -247, -680, -129, -470, -152, 915, + 176, -904, 622, 280, 2986, 1034, -1046, -482 +}, + +.cb4440s0 = { +-12085, 8192, -1802, 4587, 5947, -3183, -2629, 1837, + 2434, 252, -612, -4697, -576, 150, -704, -640, + 174, -126, -10309, 350, -3187, 4714, -2829, 12618, + -2172, 3502, 465, -159, -601, 1306, 1174, -448, + -292, -136, 242, 31, -9005, -6203, -10027, 25, + -209, -20, -1292, -1252, 4304, 3681, 4462, -4401, + 4412, 1240, -576, 3618, 595, -237, 2544, -6032, + -1511, 1523, -3668, -3472, 5552, -4901, -272, 5963, + 2740, -878, 13010, 191, -2017, 768, 455, -45, + -6873, -3664, 2639, -961, 3068, -4242, 1327, 2362, + -1909, -1114, 100, -5940, 220, 865, -12952, -76, + -1279, -591, 1092, -3502, 88, -2118, 13053, -10141, + -3024, -533, -1923, -4097, 135, 1672, -1661, 1646, + -370, -361, 644, -197, -6796, -10948, 11692, -974, + 488, 349, 3936, -1506, -149, 513, 1401, -1776, + -391, -210, 57, -56, -344, 1018, 7989, -4957, + 167, 987, -60, 62, 1622, 1207, -69, 338, +-16133, -46, 1018, -1460, -821, -646, 1316, 126, + -4631, -842, -1505, 15833, -6404, -4514, 2946, 2923, + 1198, -3141, -3109, -1613, 1853, -906, -436, -1110, + -282, -214, -3424, -3141, -3988, 284, 22262, 1269, + 1787, -1116, -1429, 1017, 371, -187, -825, 534, + 350, 1088, 26, 176, 8914, 6662, 935, 2074, + -7986, -4780, 2194, 1796, 697, -4040, 2486, 1700, + 9150, -37, -1560, 2449, -162, 128, -7469, -2690, + -281, -4698, 424, 535, 1416, 243, -575, -1160, + 326, -2417, 808, -15816, 994, -302, 26, 894, + -7376, 395, -586, 823, -1341, 972, 100, 241, + 743, 470, 267, -550, 474, 182, 18252, 178, + -182, -7, 3496, 2132, 863, -151, 741, -2158, + -763, -652, -503, -434, -736, 770, -156, -19071, + 443, -354, -243, 66, 4258, 6714, 3577, 17338, + 556, -3570, 1269, -1406, 1668, -349, -90, 781, + 82, 558, 936, -788, -1072, -21, -6472, -3022, + -475, -6997, -2816, -3774, 1683, -13950, 3482, -1872, + 2624, 1064, -318, 1300, -1214, 179, -11, -124, + 4560, -2827, -6314, -5736, 1159, 1309, -5462, -11652, + 4192, 151, -543, -3484, -2288, -119, 745, 1373, + -121, -629, 5204, 7650, -2062, -3370, -2894, -338, + -1361, 1080, -3674, 12852, -6119, -1578, -736, -241, + -1564, -109, -441, 335, 416, 1678, 4802, -3239, + 6182, 154, -3656, -1337, -17027, 1707, -381, -1704, + -377, 1022, -592, 983, -321, 37, -1846, -4500, + 2575, 14162, -560, 9385, 4179, -1340, -3466, 3235, + 1727, 1545, -23, 636, 280, -39, 871, 173, + -8915, -2427, 2146, -3698, -12153, -3773, -3873, 5042, + 112, 788, -1139, 245, 546, 278, -8, -1005, + 443, -76, -1256, 8255, 3841, 6116, 4226, 3705, + -1278, -6470, 5220, 5892, -3468, 2736, 5427, -3336, + -264, 1906, 294, -60, -7078, 7699, -9792, -7108, + -2030, 1055, -6962, 702, -2074, -232, 127, -430, + 658, -272, 757, 138, 159, -340, -4606, 1021, + 146, -7690, 6001, 5660, 3363, -367, 13222, -441, + 13, -874, 668, 2293, 875, 1238, 110, 778, + 1434, -976, 2151, -8169, 1421, 2622, 206, -795, + -816, -14443, -1583, 3356, 2971, -964, -321, -841, + -404, 111, -5595, 4248, -3819, 214, -2520, -712, + -1505, 849, 947, -876, 188, 3221, 863, 105, +-17336, 1818, 14, 17, -6349, 379, 4746, -12405, + -560, -3448, 3664, 8251, 845, 383, 1348, -739, + -780, 1695, 4828, -123, -647, 823, 9940, -183, + -1804, -7112, -161, 578, -619, 11534, 3214, 1586, + 4784, -2540, 1188, -304, -485, -648, -824, -595, + -8817, 4138, 927, -3259, -198, 4022, 2213, -1627, + 645, 14602, -1058, 1481, -1670, -113, 564, -710, + -451, -360, -1261, 2504, 247, 5566, -7262, 1344, + -5106, -1608, 1946, -4240, -7393, 10440, 3306, 1940, + -999, 155, 832, 55, 10218, 11475, -3252, -8295, + 1347, 2405, 3421, -2619, 2262, -2829, 754, -307, + 548, -2040, -1130, 317, 170, 292, 248, 2601, +-18930, -1942, 1417, 1678, 3310, -2578, -1969, 1550, + 3010, 70, 8, 3064, -848, 504, -172, 180, + 1787, -1133, 2427, 1002, -664, -40, 192, -23400, + -1004, 513, -818, -382, 360, 360, 268, 98, + -202, -192, -668, -12924, -11702, 7325, 797, 1937, + 674, -2458, -541, -1497, -1673, -955, -356, -486, + 182, 299, -46, 65, -4232, 1418, 6532, 2356, + -4894, 4870, 3369, -4585, 8743, 1497, -1451, 862, + -8612, -1718, 1716, -2389, 371, 592, 7397, -3188, + -649, 126, -1300, 1374, -1292, 645, -1494, 2736, + -1468, -1808, -17223, -352, 111, -222, -236, 171, + -198, -7994, -3822, 5324, -16856, -517, 119, 314, + -360, -515, 435, 520, -638, 1635, 420, 1191, + 830, 710, 6897, 2925, 3091, 510, 3268, -1702, +-16186, 718, -3127, -463, 763, -1035, 725, -122, + 646, 172, -164, -277, 5853, -7074, -10, -1770, + -2544, 5978, -874, -494, -232, 14465, 1815, -1902, + 987, -1533, 1216, 741, 620, 161, 4414, 4184, + -32, -2944, -4619, -462, 15701, -1026, -140, -2396, + -1747, -538, -1024, 219, 854, -351, 860, -226, + -4390, 732, -2003, -2430, -540, 592, 1622, 1180, + 385, -2052, 4050, 17401, -650, -243, 1709, 1261, + 95, -307, -5110, -666, -7094, -533, -1293, -17357, + 2929, 2389, -119, -413, 317, -962, 709, -1552, + 26, 175, 700, -570, 20120, 1107, 232, 169, + -889, -533, -1276, 22, 959, 866, -954, -792, + 873, -172, 1757, 195, 148, 423, 4490, 8782, + 631, 682, 1832, -3728, -1742, -11130, -1201, 1776, + 9268, -586, -1358, -646, 626, -866, 5, 263, + 3950, -760, -2914, -12751, -12669, 1513, -4, 631, + 1835, 312, -167, 1546, -532, 619, 1176, 1436, + -116, 312, 7054, 3120, 4075, -1320, 715, -206, + -1572, 1350, 17688, -1182, -1568, 680, 6, 207, + 1010, 600, -766, 554, -1483, 644, -8810, 624, + 148, -4015, -1536, -1863, 92, 730, -14806, 386, + -5174, -1420, -331, -254, -104, 275, -7268, 2563, + 11983, -65, 8043, -1623, -2589, -2610, 1328, 3154, + 1935, 3672, -1761, 4984, 661, 209, -1038, 122, + -1019, -28948, 55, 358, -539, 488, 55, 618, + 20, -314, 446, -1016, 618, -93, -94, -331, + -36, 194, -1706, 6628, 396, -146, -765, 10500, + 2619, -82, -10894, -3908, -888, -192, 620, 163, + 78, 774, -293, -104, -4826, -14066, -1883, -3258, + -4577, -1484, 5412, -4274, -4951, 3316, -907, 1948, + -1187, -404, 3654, 400, -70, 459, -3224, -3194, + 2338, 4390, -5, -3167, 3273, 116, -1026, -1668, + 3767, 272, -16662, 137, -1634, -1007, 220, -310, + 982, 8220, -16, -1251, -2644, -3344, 2236, -1573, + 8174, 612, 1142, -10799, 393, -707, 4804, 397, + 1232, -292, 5762, -15608, 2921, -6440, 3544, -2395, + -504, 1890, 172, -1010, 178, 380, -1163, 404, + -1230, 1034, -596, 105, -2038, 1991, 5613, -312, + -4156, -10205, 3092, -4704, -6101, -1620, -1037, -1130, + 1590, 8321, -797, 247, 954, -103, 3838, 2330, + 10064, 3197, -8508, 1300, -1012, -6607, -3861, 5651, + 31, -475, 1582, -1370, 1107, 2164, 743, -567, + 4842, -2930, 3191, -190, -2230, -47, 254, 2147, + 591, -512, 1312, 1159, 811, 1444, -1312, -257, + 16016, 789, -2562, 3983, -373, -9255, 302, -3655, + 5750, -3856, -6941, 3934, -2314, 5556, -4099, -265, + -479, -4843, -130, 20, -4859, 3083, 6482, -3738, + -3936, 590, -6368, -1784, 75, -3903, -6834, -4452, + -871, 764, -1118, 8731, 38, -148, -3368, -6330, + -370, 2234, 907, -2809, -1458, -2306, -402, 2679, + -1222, 1138, 192, -1317, 1012, 15514, 624, 279, + -4032, 2565, 6162, -938, 5760, 1685, 4350, 2939, + -825, -331, 1840, -556, 427, -4642, -23, 8346, + 7577, -467, 3848, 454, -3962, 373, -116, 2314, + 4868, -208, -1367, -1803, 2681, 806, -4279, 3348, + -528, 14027, -238, -457, -2764, 832, -4680, 4354, + 1219, -801, 2414, -5204, -3768, -6524, 5163, -10909, + 1656, 321, 3260, -1773, 214, -135, -4563, 5206, + -4794, 1486, 406, -1026, 281, 1799, -218, 320, + -908, 872, 1056, 2955, -208, -799, 15492, 334 +}, + +.cb4440s1 = { + 27498, -414, -266, 646, 229, 94, -15, 302, + -489, -401, 125, 752, -476, -200, -976, 195, + 4, -402, 2220, 1012, 1731, 2530, -652, -21380, + -679, -867, -195, -114, 1326, 2531, -348, -185, + -114, 178, -694, -298, 8752, 1735, 2640, -2374, + 6191, 1516, 5771, 6705, -253, -8502, 986, 2134, + -1854, 3490, -678, -48, 133, 844, -1635, 1630, + 6056, -756, -1109, 1563, -1445, -139, 580, -1448, +-18675, 846, -390, -259, 1548, -324, 281, 142, + 1792, 1211, 1328, -4308, -1032, -5412, 4742, -201, + -47, -297, -8403, 9715, 7268, -3756, 1573, 677, + -88, -145, 4877, 12946, 3264, 1809, 7230, -2583, + 1627, -1786, -7113, -1480, -2111, -508, 415, 1664, + -483, -538, -249, 80, 7005, -2562, -887, 3801, + 6411, 2222, 36, 875, -5089, 10897, 4014, 4948, + -1580, 1425, -1814, -391, -96, 322, -6484, 1896, + -7790, -950, -4235, -8362, 3118, 4843, 3754, 1070, + -1648, 7692, -1675, 3405, 918, 2270, 573, 193, + 6024, 8912, -4905, -1810, 985, 1877, 2158, -2150, + -386, 3908, 2030, 419, -12599, -570, -150, 1580, + 36, -152, 2, -538, -1565, 6809, -715, -6266, +-12725, -6718, 810, -603, 1547, 1001, 2250, 810, + 1773, -672, 327, 246, 6414, -7511, 916, -327, + 830, 11862, 4373, 1003, 6370, -1730, -2127, 613, + 1627, 626, 763, -864, 207, -233, 3738, -8644, + -1634, -2050, 3906, -451, 12986, -4828, -2973, -4714, + 545, 822, 735, -3539, -256, 65, -93, -94, + 2923, 7075, -3763, 6172, -9544, -2675, -3833, 930, + 418, -4496, 3790, 386, -7797, 234, -609, -259, + 454, 330, 1546, -7634, -1966, 515, -2496, 374, + 2633, -3014, 4126, 9920, -7103, 1441, -150, 7695, + 670, -48, -41, -512, -6849, -1785, 3755, 1860, + 2418, -2346, -1194, -1574, 15510, 444, -1515, 585, + 742, -199, -1115, -122, -11, 140, -7763, 1438, + -317, -444, -17149, -24, 2685, -856, -3166, 1109, + 308, 233, 30, 63, 530, 645, 84, 133, + 6139, -1183, -10673, -12790, -112, -1544, 4623, 576, + -804, 1023, -1646, 1192, 269, 2681, 44, -909, + -14, -414, 48, -4002, 4768, 3440, 3252, 1441, + 101, 372, 3166, -1398, 325, 16184, -711, 486, + 1328, 114, -450, -31, 1152, 2154, -69, -252, + 32, 922, 219, -2055, 421, -1377, 1006, -614, + 234, -40, -84, 204, 27171, 182, 1034, 1536, + 834, -8038, 1243, -3074, -7829, 11165, -1854, -1173, + -871, 4105, 3588, -3191, 188, -2102, 124, -166, + 8070, -11066, 6632, 2739, -7787, 184, -5872, 1360, + -1089, 1273, 84, -1683, -1584, 975, -206, 1160, + 180, 12, -6121, 5436, -14726, 5949, -6756, 834, + 1750, -3142, -878, 7, -220, -1933, -141, 160, + 26, 756, -800, 6, -8104, -6989, 3353, -3518, + 4510, -12430, 736, -2685, -1042, 32, 1184, -519, + -312, -1073, -402, 71, -422, -35, 1791, 12735, + -2281, 2623, -1502, -3878, 6727, 10541, -1110, 2308, + 870, 1124, 874, -1406, 123, 254, 405, 328, + 3828, -7541, 3096, -14145, -672, -1725, -423, -1918, + 4164, -411, 3094, -568, 3575, -2895, -378, -3065, + -232, 449, 8110, 2264, -1383, -557, -10683, -7628, + 4155, 754, -134, 6759, 1051, -2054, -900, -948, + 579, -1277, 151, 462, 11562, -310, -8260, 10238, + -1309, -3052, 345, -689, -1133, -588, 548, 980, + -1332, 881, 368, 776, -704, 422, 12433, 1314, + -1487, -4753, 2679, 3092, -939, 136, -586, 3504, + -1034, -6318, 3506, 420, 2326, 1034, -252, -398, + -6232, 4488, -6166, -1754, 908, 4884, -5188, -2985, + 10793, -116, 4674, 3980, -9, 805, 1568, -1620, + -88, -146, 3027, -16154, 2899, 7839, 5912, -427, + 270, -1467, -387, -351, 615, -322, -2, -1061, + -654, 56, -438, 132, 2388, 460, 2172, 1874, + -3028, 3302, 2035, -704, -1222, -19835, -472, -1858, + -1686, -286, 5, -748, 491, -350, -4344, 103, + 1473, 2440, 13575, -1350, 1456, 10377, 1962, 3036, + -1238, 1580, 607, 1352, 997, 1212, -489, 251, + 4075, -3457, 6186, 786, 300, -2532, -373, -2522, + 3108, -294, 4938, -2980, 1509, 12450, -695, -1128, + -96, 354, -3678, 8494, 2480, 2264, 5162, 11907, + 4721, 1111, 752, 2999, 3924, -1429, 321, 276, + 309, -603, 601, -62, 3337, -3570, 3273, 6618, + -2001, 950, 532, 972, 1619, 956, 65, -609, + -281, -14769, -438, 580, 230, -228, -10108, 12289, + 8904, 872, -3296, 1535, -384, 477, -913, -777, + 546, 445, -1004, -435, -716, -138, 572, 435, + 4626, -864, -5716, -2810, 1291, -4796, -241, 2527, + -2342, -1360, 4161, 1886, -128, -1521, 13726, 1818, + -554, -157, -9665, 2607, -1013, 579, 1122, 1571, + -2684, 11364, -6464, -184, -1542, -5670, -1091, -670, + 1273, -1051, -7, -278, -2551, -548, -10673, -1434, + -343, 317, -3108, -1615, -2239, -14132, 490, -454, + 2467, 1990, 470, -1072, 440, 290, 3006, -4420, + -2083, 3050, 2779, -2349, -590, -4941, 7464, -9000, + -2686, -2045, -8712, -3281, -2476, 648, -148, 408, + -1367, -1113, 27347, -1113, 739, 39, 1443, -208, + -686, 986, 735, -702, 76, 665, -194, -165, + 366, -606, -4908, -3932, -15941, -2810, 4572, 816, + -2092, 4213, -2492, 4006, 926, 210, -1110, -1635, + -270, -226, -362, -187, 1790, 3016, 2216, 3890, + 2018, -1325, 19784, -771, 356, 2118, -98, -688, + 1016, 978, 559, -39, 160, -310, 6622, -1754, +-11104, 204, -2212, 2370, -11610, 1119, 3216, 3102, + 524, 278, -829, 524, 28, 838, 374, -76, + -4593, -2933, 10697, -6510, -4970, -2025, -9383, -3428, + -4112, 2665, 1459, -1411, 421, 481, 842, -341, + 147, -158, 4108, 45, 4935, -21, -7905, 2058, + 1158, 15260, -567, -752, -992, -1094, -1059, 2370, + 820, 655, -261, 280, -3969, 6342, 8521, 3114, + 369, -12269, 1684, 4, 4686, 1985, -3668, -3040, + 677, -254, 57, -161, -989, -379, 7075, -580, + 2846, -3177, -2285, 958, -7096, -154, -515, -3345, + 13487, 3548, -1804, 290, -430, 726, 399, 54, + -2814, 10235, 1958, -3356, -1330, 536, 3218, -14194, + 200, -796, -862, -1480, 1811, -346, 604, -391, + -231, 513, -10495, -6029, -6492, -8746, -357, -221, + -1890, -2669, 8, -1756, -5812, -1048, 2258, 223, + -474, 1154, -226, 348, -1590, 2915, 158, -24059, + 875, -846, 1150, -1000, -844, -116, -246, -219, + -482, -367, 120, 517, -489, 442, 8148, 5040, + 3770, -1006, -51, -3175, -10278, -4468, 1188, 1497, + -6515, -5, -1628, -2387, -1297, -717, 1630, 232, + -3608, -6688, 2444, -792, -246, 411, 1464, 3661, + 3244, -1121, -1602, -15398, -443, 882, 1412, 926, + 16, -73, 2693, 7168, -9399, 528, 7916, -9270, + -1669, -2756, 1304, 3074, -1510, -2089, 1491, -1556, + -422, -414, 132, -192, 5988, 4500, 7572, -10978, + -4875, 3685, 1888, -660, -1750, -515, -2728, -3133, + -2742, 666, -2861, 626, 256, 243, 4587, -3567, + -288, 2314, 4765, -11036, 7322, 7581, 2651, 3264, + -394, -246, -891, -1464, -1717, 123, -517, -486, + -1019, 7215, 554, 722, -4253, 2393, 3053, 2881, + 1538, -2104, 573, 321, 673, 3902, -2855, 944, +-12816, 370, 3496, 952, -1435, 6379, 766, 2273, + -729, 80, -2432, -1150, 2408, -895, 15497, -1231, + -282, -3306, -435, -167, -3528, -5683, -6413, 2501, + -4825, 124, 3128, -425, -2800, -986, -2283, -495, + -3392, -1560, -2093, -11613, -37, 157, -438, -794, + 1988, -45, 1508, 20, 98, -458, -245, 1130, + 110, -525, -771, 1120, 710, -21758, 174, -210, + -4839, -2468, -648, -4388, -11, 2990, -181, -4790, + -4232, 3634, 6427, 2772, 166, -2996, -12005, 1630, + -249, 179, 856, -1250, -4216, 1993, 5164, 4757, + -5071, 4331, -3029, -1276, -11184, -2864, 1238, 6332, + -2431, 1276, -338, -476, -5659, -2410, 2510, 1853, + -4853, -3175, -1896, 10728, 3724, 960, 9963, 305, + -938, -646, -2760, 1436, 113, -74, -3098, -4090, + 2950, 2701, 992, 206, -1393, -2179, -10862, -2396, + -1008, 2639, -1547, -416, 9264, 1824, -360, 401 +}, + +.cb4440m0 = { +-25793, -238, 1193, -2635, -238, 1315, -2277, 1588, + -896, 512, -864, 611, -398, 1277, -212, -358, + 202, 13250, 16, -860, 1618, -1024, 310, 11560, + -746, -3876, 780, -4087, -475, 857, 1017, -1439, + -890, 155, 8556, 362, -1158, 2116, -291, -66, + -1272, 510, -1394, 2259, -4761, 808, -740, -937, + 13993, 191, 273, -7670, 6776, 846, -1907, 955, +-13206, -1956, 1697, 1670, -329, -244, 2395, 6119, + -802, -1007, 649, -974, 170, -2136, -10780, 1020, + 1270, 1954, 1118, 13348, 983, -1394, -594, -514, + -586, 1026, -1821, 548, -298, 3342, 837, -1395, + 13977, 1021, -7792, -2930, 1466, 5494, -843, 2432, + 1378, -68, 174, 407, 76, -877, 691, -9445, + 522, -3448, 2549, -412, -2358, 875, -5044, -952, +-10113, 6574, -6347, -2760, -662, 29, -227, 4884, + 1304, 411, -3320, 2434, 785, -14822, 4412, 2272, + -6407, 2172, -613, -1665, 296, 742, 624, 135, + 5316, -3191, -855, -2061, 485, -3188, 2998, 1382, + 2516, -2438, -3506, -238, 737, -629, 1001, 773, + 17540, 1478, -724, -764, -1231, -1254, -1582, -692, + -351, -1551, -171, 183, 38, -668, 756, -770, + 24344, -905, -7182, 502, -3766, -1690, 1588, 1522, + 1844, 1276, 1458, -777, 1731, 4856, -14860, -1097, + 36, -1310, 846, -1500, 521, -3669, -252, 4480, + -2602, -845, 597, -4512, 1062, -292, -18518, 1972, + -334, -80, -1256, -366, 3640, -436, -12, -1670, + -435, 1496, 1429, -11092, 1012, -936, -1224, -12240, + -3048, 210, 1905, -1197, -357, -9759, -2632, -332, + -3417, 15078, 1496, 2206, 1800, 205, 1384, 3546, + -1853, 755, 1016, 726, 58, -150, -13053, 10375, + -2589, -330, 1616, 3081, 2763, -2617, -1204, 324, + -53, 2968, 1485, 214, 124, -334, -237, 16784, + 2612, 1023, -4298, -2156, 4336, -4307, 4952, 1036, + 81, -762, 3416, 714, -187, -4100, -757, 1124, + 10224, 7059, 424, -316, 1281, -12262, 912, -1999, + 2, -731, -184, 879, -934, -202, -391, -1046, + -338, -101, -17511, -1712, -5580, -2327, -2478, 1770, + -5825, 1499, 578, -130, 1424, -1818, 110, 542, + 22, 988, -4227, 2836, -1447, 1170, 12335, 2179, +-11216, -2500, 64, -912, -954, 654, -802, -455, + -597, 234, -296, 811, 1083, 1848, 4148, 637, + -6608, -2362, -3382, -664, -13088, 2839, 3090, 3294, + -4554, 2518, -55, 837, 1392, 5905, 1287, -1484, + 965, 16533, -3507, -1903, -1562, 2408, 5037, -4816, + 1409, 361, -1890, 170, -610, -1755, -524, -867, + -6238, -20117, -745, -956, -176, 2998, 130, -668, + -843, -267, -364, -573, 495, 127, -66, 32767, + 271, -408, 654, -123, 1831, 151, 996, 82, + 628, -251, 144, 198, -88, 357, 37, 612, + 184, 238, -584, -52, -30025, -415, 404, -566, + 100, 659, -336, 877, 211, -730, -377, 184, + -5256, -1484, -1191, -2108, 24, -7821, 209, -2856, + -1844, 697, 5798, -1191, 427, 11858, 1000, -261, + 184, -686, 1182, -3142, -3138, 139, 144, 117, + 3658, -3566, -1562, 672, 2036, 15051, -5069, -551, + 529, 1696, -214, -2678, -5966, -3707, 2847, -2554, + -1760, -1196, 2088, 6372, 1778, 12935, 2189, 1992, + 1761, 578, -542, -753, -1182, 4321, 1871, 309, + 704, -1259, 884, 19136, -2665, 1096, 3048, -167, + 872, -344, -1092, 464, 3255, -86, 1608, -1062, + -1569, -1699, 4504, -274, 568, 1428, 20571, 1452, + -894, -791, 459, -882, -1048, -2944, -11095, -783, + -832, -2450, 650, 2784, 3156, 529, 457, 483, +-12553, 655, 686, -757, 929, 212, 1242, -201, + -1627, 4826, -1895, 997, -3225, 84, 80, 287, + -2136, 405, -188, -890, -18272, -511, -118, -3642, + -1018, 420, 12650, -474, -540, 6978, 6977, 4418, + 1162, -1332, -1112, -1765, 2640, 562, -1164, 1256, + 595, 567, -483, -31511, -960, -816, 756, 1505, + 12, -518, 234, 184, 679, 328, -600, -137, + 267, -440, 2540, 593, 1023, -11756, 626, -2034, + 5756, -9882, 3175, -1190, 1628, 3920, 3219, 1394, + 834, -140, 4036, 4722, -455, 3105, -1355, -3106, + 1000, 7806, -2227, 687, -1580, 3180, -12302, -1394, + -425, 488, -187, -36, 219, 158, 12006, 1683, + 2151, -2, -1110, -12250, -59, 672, 1844, 2084, + -2101, 1652, -783, 634, -13257, -339, 3932, 2260, +-12452, 152, 316, -688, 79, -912, -2081, 1384, + 188, 1942, -706, 204, 700, 1776, 13901, -13666, + -324, 472, 1055, -646, 82, -769, -877, -443, + -227, -900, 636, -870, 470, -112, -598, -4402, + -2726, 1775, -216, -43, -18675, -863, -4604, 3433, + 674, -155, 208, 1546, 294, -157, -616, 11070, + 1229, -528, 2124, 699, 3624, 54, -516, 194, +-13556, 1902, -506, -1317, 1916, 471, -342, 836, + 18, 906, 614, -8, -951, 1052, -97, 2212, + -924, 310, 6, -733, 122, 23731, 468, 345, + 1545, 1434, 611, 403, -3136, -2214, -54, 1023, + -1390, -5243, -3744, -258, 6871, -1778, 673, -2362, +-13007, -776, -974, -1077, 8386, -3978, -4325, 1236, + 4011, 1161, -263, 1224, -12957, -100, 2801, 1458, + -3081, 578, 17, 1037, -742, 5972, -632, 2904, +-12721, -6733, -478, 182, -1973, -820, -6911, -4904, + -942, -348, -353, -350, 7864, 34, 568, 1985, + 956, 3310, 118, -2067, 12600, 9063, 1609, -1261, + 296, -1248, -1656, -65, 1832, 1525, 1503, 5149, + 4370, -1638, -3868, 320, 1527, -424, 17676, 1780, + 1172, -1132, 1128, 1294, -322, -101, 462, -6668, + -3024, 7573, -11088, 1581, 13, -1398, 550, 4376, + 1623, 1727, 857, -5310, 2528, -529, -401, 539, + 6508, 4246, 4105, -5363, 96, -13407, -694, 5061, + 3445, -3283, -348, -1470, 1114, 602, -404, -129, + 642, 1547, 23110, -2255, 1969, 333, 1297, 116, + -1691, 364, -528, 758, -1239, -1826, -249, -395, + 684, -856, -638, -10000, -2773, -6151, -1244, -3138, + -9688, -1994, 7124, 1368, -1870, -312, 1863, -1006, + 963, 789, 743, -4158, -760, 1384, -7525, -959, + -262, 5752, 4005, -12037, -210, 886, -1961, 4895, + -251, -158, 212, 677, 518, 342, -226, -360, + 466, 17, 28392, -20, 246, -686, -258, 640, + -378, -120, -443, 1078, -2612, 2084, -1706, 4334, + -4675, -4634, 2336, -9998, 9975, -1285, 2778, 3292, + -1717, 138, 2114, -1120, -180, -1146, 11988, 829, + -2530, -8827, 6833, -1191, -1653, 2691, -4067, 1166, + 1971, 303, -544, -1459, -261, 1065, 3410, 2050, + 3163, -515, 5456, -4261, 5483, 1531, -2098, 2020, + 3773, 588, 915, 158, -11876, 282, -1180, 265, + 11036, -66, -1741, -1894, -4234, 3048, 218, -1030, + 2240, -12666, -2290, -1673, -1911, 1480, 287, -81, + 1182, 216, -10734, 2201, -58, -619, 8585, -574, + -4576, 1852, -468, -6759, -7667, 167, 995, -1114, + -1276, -2053, 2178, -8133, -1270, -7822, -10582, 5380, + 3037, 1071, 827, 4972, 1024, -129, -180, -3002, + -846, -736, 9587, 1890, 10287, -1954, 1042, 1558, + -950, 2406, -1852, 2275, 6694, -703, -910, 3854, + 812, 521, -1075, -761, 5357, -3911, 3892, 7944, + 4580, 5031, 1088, 7116, -1746, -5223, 2607, 3227, + 2296, 5603, 211, -731, 6450, -3312, -12378, -326, + 4245, 4168, -799, -3563, -505, 725, -5297, 2196, + 2221, -16, -3472, 315, 626, -6131, 71, 920, + -4383, -1340, -2675, -664, 7412, -1240, -1361, 997, + -3817, -2377, -11717, 1661, 22, 540, -5261, -950, + 7472, 3148, 7647, -4400, 4558, -4412, -869, -1528, + -2618, 8311, 2110, 534, -460, -223, -162, -828, + 274, 1844, 1861, -1583, 6899, 5222, -1772, -2880, + -6400, 4703, 2606, -3990, -1224, -4160, 9032, -299 +}, + +.cb4440m1 = { + 32767, 383, 857, -1579, -423, 1164, -1606, 1218, + -410, 777, -292, 122, 282, -74, -1394, 259, + -734, 102, -82, 32616, 427, -545, -146, -141, + 340, 506, -808, 171, -778, 900, -204, -277, + -228, -426, 566, -481, -1138, -907, 112, 2722, + 871, 115, -7202, 1953, -826, -1812, -396, -14722, + -840, 155, 1114, 5624, 1112, -147, -6383, 926, + 1505, 360, 937, -13391, 969, 7062, 2218, -3531, + 471, 458, 191, -465, 8664, -1168, 546, 2109, + -944, -74, 1644, -81, -760, -1920, 2659, 13330, + 1511, -1148, 1346, 796, -20, -15616, 1246, -1190, +-10882, -774, -70, 3643, -896, 1830, -192, 1018, + 1085, -95, -309, 659, 91, 727, -4486, 486, + -2078, 1235, -14415, -4053, -1619, -2589, -582, -4650, + 4076, -762, -1111, 277, 1448, -742, -314, -979, + 1889, 2679, -1972, 2480, 302, 2869, -9183, -445, + -1817, 12894, 106, 187, -1406, -615, -1174, 746, + -371, 382, 350, -1811, -527, 36, 500, -835, + -106, 1134, -2207, 1021, 348, 908, -21780, 448, + 688, -60, -1790, 1901, -22990, 1467, 596, -912, + -3190, 1484, 269, -409, -474, -1670, 1328, 152, + -402, 359, -734, -13208, 62, -4197, -6242, 5195, + -2841, 5030, 2794, 1264, -1130, 3821, 961, 729, + 1075, 49, -148, 7267, 2596, -5093, -8284, -6875, + -3059, 3909, -4635, 1402, -6334, -342, -3083, -861, + 490, 1257, -630, 128, 2240, 832, 1060, -1802, + -1652, 128, 7816, -14391, -6722, -3328, -2586, 3044, + 1088, 1577, 852, -142, -176, 1371, 1236, 976, + 12165, -1596, -199, -504, -11020, -582, 972, -1468, + -2402, -666, -3327, -2148, 1078, -194, 9675, -2102, + -1236, -70, -942, 291, 1364, 1403, -3362, 12963, + -375, -1728, 1615, -2354, 633, -506, -194, 13037, + 14172, 534, -1026, -425, 2488, -180, -678, -436, + 272, 1507, -334, 840, -1000, -1068, 1029, -306, + 24, -4435, -5994, -1307, 4251, 3968, 2527, -981, + -2626, -4400, -242, -1823, -679, 12831, -22, 51, + -381, 2422, -2376, -8156, -1477, -6974, 1102, -373, + 467, 11314, -554, -432, 824, 7277, 393, -178, + 179, -653, 11848, -1593, 14143, -731, -1036, -2322, + 261, -1992, -1152, -1430, -1354, -51, -285, -1637, + 144, -59, -2182, 5731, 538, -880, 397, 3010, + 707, -1822, -1006, 4686, -5096, 4246, -3096, -3997, + -254, -11025, 394, -345, 18780, -686, -517, -3422, + 104, -2173, 2439, -5400, -10, 1084, 1821, -602, + 1431, 405, 2143, 499, 405, 351, -62, -47, + 1954, -29915, 440, 1054, 559, -1210, 442, 928, + -1, 59, 279, -112, -110, -440, -396, 805, + 311, 858, -431, -1070, -30192, 135, 1246, -345, + 790, 498, 319, -302, -469, -10, 512, -829, + -526, -2052, 2456, 134, -19375, -1210, -1292, 640, + 3232, 2580, 973, -2412, 271, -282, 632, -523, + -847, -138, -990, 2501, 536, -166, 2100, -357, + 122, 466, -4, 2034, 20083, 1578, 444, -344, + -689, 5733, -456, -503, -592, -1350, -1038, 932, + -1916, 1098, -990, -22687, 1544, -442, -396, -570, + -683, -616, -1431, 118, 4113, -312, 2300, 2093, + -2344, -2955, 6343, 4306, -10078, 6286, -5794, -806, + 664, -217, 548, 5072, 4626, -1643, -11619, 779, + 1956, -2960, 614, 2087, 9104, -2418, 775, -4447, + 768, 1599, -1084, 999, 1652, 1090, 630, -1197, + -3495, -912, -9817, 648, 3278, 1828, 13605, 2757, + -831, -1191, -1846, -1441, -278, -8530, -455, -495, + 323, -911, 2500, 14100, 3635, 1016, -936, 5265, + -3092, 2125, -121, -64, -656, -337, 9438, -7600, + 1403, -11917, 2180, 2612, 1664, 1091, -318, -3300, + -427, 282, 1979, 894, -703, 514, 160, 1697, + 6508, 828, 187, -34, -1094, -2861, 240, -5013, + 6004, -4796, -991, 158, 11437, -1730, 354, 1195, + 3790, -10432, -3584, 13872, 336, 2043, 221, 604, + 2930, 1080, -1417, 1878, -878, -459, -419, 364, + -1037, 7764, 3100, 48, 11057, 1936, 2229, 9150, + -472, 1178, -129, 2876, -249, -258, -1181, -329, + -581, -1140, -1967, 347, -539, -394, 775, -1151, + -31, 1052, -1900, -213, -1552, 22484, 164, -113, + 135, -1294, 550, 7738, -7223, -739, 1362, 5518, + 193, -2170, -11861, -1357, 351, 2215, 165, 16, + -606, 727, -158, -772, -13420, -1248, 12422, -812, + 1768, -442, 1269, -1076, 899, 124, -249, -1110, + 653, -3064, -1632, 839, -230, 512, 642, 13230, + 13285, -552, -1113, -595, 864, 537, -1012, -539, + -615, -491, 1014, 800, -10, 534, -1227, -25011, + 1239, -26, 3834, 104, 762, 1259, 2112, -300, + -920, -812, 612, -1061, -378, -246, -7, 11042, +-18492, -1411, -77, 407, -556, 218, 1751, 1069, + -294, 1789, 904, 285, -76, 300, -160, -128, + -3398, -2001, 1689, 4946, -2750, 1427, -12632, -1873, + -1802, -1115, -2777, -4436, 2937, -6408, -467, 487, + 1043, 3914, -81, 1540, -11718, 1368, -12656, -583, + 1009, -416, 249, 1874, 1157, 994, -858, -154, + 294, 333, -26, 73, -1576, -20, -560, -1068, + 1325, -588, 26161, 1580, -411, -587, -1083, -79, + 762, 292, -622, 788, 284, 2014, 78, 554, + -516, 1340, 835, 300, -24827, 558, -705, -22, + 139, -159, -246, -585, 4318, 234, 1308, -198, + -3370, 5724, 2381, 13843, 4, 569, 8002, 1188, + -63, -1698, 4624, -405, -218, 4238, -888, -1180, + 3750, -4848, -9497, 293, -1087, -13274, -33, -2870, + 457, -618, 338, -34, 286, 345, -5321, 904, + -5656, -2082, 12644, -7423, 532, 958, -1997, -1483, + -2982, 3115, -1851, -2025, 1853, -918, -903, 1554, + 540, -16549, 1441, 2939, -1272, 3106, 2374, 3906, + -697, 1144, 750, -379, -6502, 980, 386, 36, + 1109, 1195, 6272, 4264, 1501, 5369, -1560, 3535, + 1084, 739, -1031, -4400, 8452, -430, -1787, -7669, + -231, -115, 4324, -1820, -2098, -786, 7478, -2709, +-14255, 5771, 115, -1700, -111, -1482, -1369, -112, + 122, -472, 233, 2427, 1816, 180, -481, 928, + 82, 84, -700, -448, -946, 1968, 1644, 168, + -167, 16164, 155, -10316, 941, -584, 488, 96, + 5205, 491, -1844, -13055, 1266, -352, -836, 558, + 1546, -1720, 313, 2033, 597, -14351, 4426, 3281, + -559, 2614, 3248, -2265, -10312, -1614, -288, 480, + 1419, -546, -485, 835, 960, 462, 923, 6518, + 834, -711, -12639, 8811, -207, 1806, 337, -1240, + -4796, 2383, 277, 1141, 969, 59, 197, 1365, + -614, -9144, 4824, -436, 4191, -2588, 4509, 391, + -5055, -3231, 6978, -6388, 51, 105, -863, 1050, + 13103, 12769, -420, -1562, -123, 2702, 292, 1061, + 123, 405, 1917, -275, 493, -95, -195, 130, + -2613, 9010, 196, -1382, 5903, 7281, 1585, 2557, + -876, 3166, 6910, 590, -3060, -559, 4722, 393, + 613, -392, -3022, 9892, 1808, 923, 8123, 9873, + -1665, 2349, 2894, 591, 2000, -3734, -917, 220, + 408, 296, -656, 2608, -1700, 400, -10734, 5434, + 6504, -1399, 2175, -1203, -6358, -1221, -5062, 45, + 970, -500, -1322, 1176, 5882, -11687, 6324, -2183, + 2327, 922, -5628, -3507, 2406, 874, 1399, 4518, + -343, 857, -224, 802, -725, -8561, 4432, 1974, + 1825, -2168, -451, -3408, 6587, 7589, 3361, -4711, + -1474, 3151, 1950, 1022, 1466, 9192, 4666, -822, + 1024, 2342, -2220, 1169, 10460, 2993, -988, -4407, + -6727, 902, 1659, 80, 106, 400, 34, 1746, + -6982, 10484, 6333, -845, -3333, 1764, 217, -4730, + -3306, -3664, -2830, 2254, -927, -55, 587, 1812, + 281, 4375, -3614, -1349, 1802, -6184, -2648, -4189, + -9381, -3243, -4147, 384, 2241, 5524, -478, -1534 +}, + +.cb4448l0 = { +-15402, -5156, -1798, -144, -4711, -4700, 2819, -389, + 148, -2600, 1706, -1906, -578, 495, 24, 829, + -383, -12581, 11667, -1039, 1395, 2670, -288, 23, + 628, -248, -512, 79, -326, -5428, -2830, -2476, + -1253, -915, 12042, -674, -110, 2950, 3885, -5799, + 983, 616, -652, -60, -372, 22, -141, -167, + 98, 125, -100, 27211, 133, -127, -271, -272, + -176, 1268, 173, -422, 2431, -3998, -2797, 2328, + 182, 6526, 3318, -6282, -10580, 3966, 8504, 527, + 9507, 6203, 990, -989, 6030, -136, 647, -1100, + -324, -2618, -2499, 500, -132, -842, 1237, 3599, + 2285, 2906, 10766, 11284, -2794, 242, 184, -1934, + 55, -839, -1181, 406, 855, 902, 10490, -327, + -1561, 5742, 428, 2218, 1523, 5229, 9130, -760, + 108, -140, 22229, 1132, 411, 720, 414, -356, + -745, -1276, -899, -562, 369, 5, -7770, 4101, + 3626, 126, -13, -4356, 728, -3197, 1930, -1470, + -6936, -410, 6720, 1897, -530, -4267, -2181, -876, + -472, -2540, -10234, 4008, 10217, -2561, -2021, 716, + -1378, -325, 427, -245, 314, -48, -118, -150, +-30295, -368, 256, 369, -656, -78, -246, -140, + -1250, -635, 1332, -13604, -10383, -1375, 353, 2417, + 2140, -349, 1460, -51, -309, 523, 509, 2352, + 1208, -377, -2023, 9708, 397, 1216, 10610, -4416, + 5520, 3902, -2119, -480, -420, 1170, 36, -3304, + 1550, -266, 1682, -808, 2420, 2700, 16239, 3910, + 572, -375, 85, -9775, -120, 2214, 2779, 11510, + 2628, -416, -1740, -1305, 1226, 78, 78, 635, + 422, -13892, 1302, -4117, -1218, 2681, -8436, -1723, + 2290, 2815, 1172, -181, -675, -475, -763, 2394, + -3639, 7903, -659, 2323, 4837, -6758, 9460, -1480, + -2403, -2783, 1496, 806, -458, -246, 12, -254, + 121, 1477, -633, -513, 791, 208, -390, -177, + -1292, -20471, -4401, -2678, 9026, 128, -265, 822, + 260, 11202, 3132, -1879, -3891, 1884, -842, -107, + 7516, 1208, -1552, -995, 1203, 2150, 11044, 1285, + 2282, 80, 1348, 5342, 2089, 924, 1472, -1454, + -8259, -226, -10259, -2335, -2442, 224, 3257, -1528, + 6685, 1630, 1969, 48, 4802, 6051, 987, 8662, + -2368, -4984, -1974, -4049, -5320, 5003, 299, -400, + 727, 208, -187, 2838, -4547, 9682, -2238, 1065, + -3206, 10091, 4915, 2945, -1635, -198, 1074, -698, + -716, -96, 1390, -2644, 1006, -4154, 10587, 1132, + 2912, -7399, -8350, 785, 156, -290, -142, -374, + -2161, 1066, 1358, -1798, 3050, -19, 452, 10470, +-10948, 4190, -984, -2089, -728, 1503, 4273, 812, + 4950, -3750, 844, -1231, -1582, -2517, 2385, -10537, + 5807, -4621, 332, -357, -12484, 1676, 160, 10762, + -1225, -1374, 14, -1389, -2900, -467, -1260, 459, + -861, 102, 1715, 4295, -7324, -7400, 10435, 287, + 1866, 765, 1730, 3430, -744, -2, -1773, -96, + 2001, 2165, 118, 9296, -4640, -4612, 7134, 5128, + -7967, 404, -433, -433, 2222, -8050, 2023, 2766, + -260, -2440, 1607, 2442, 7763, -486, 3766, 2355, + 7515, 230, 1248, -8873, -8224, -9135, -1402, -1812, + 1223, 152, -2316, -739, -405, -784, -598, 625, + 503, -175, -573, -31693, 502, -478, -554, -934, + 387, -80, -484, -701, -34, -51, -494, -1461, + 1005, 2920, 11532, 2667, -1674, -832, 8680, -5767, + 786, -1558, -2062, 1009, -392, 2099, -7277, -2587, + 6302, 3070, 4496, -1713, -4042, -8109, 1642, -1894, + 3450, 840, 3632, 160, 578, 149, 767, 754, + 208, -870, -672, 252, -30, -213, -482, 50, + -578, -2, -148, 246, -31918, -568, 130, 472, + 761, -27, -51, 454, 144, 124, 5844, -8354, + 9562, -3755, -262, 3286, 1120, 983, -628, -734, + -1732, -1424, 353, -403, 15877, -13552, -335, 337, + 519, 140, 297, 150, 725, -780, 876, -116, + -91, -128, 275, 2499, 9313, -768, -10469, 1148, + 2172, -6417, 3292, -2187, -1108, 3055, 1105, 625, + 794, 68, 337, 1384, -106, -516, 574, 868, + 849, -997, 81, 25796, 28, 206, -3556, -351, + 1058, 1126, -7826, 5310, -4102, 5352, -6835, -4032, + 1487, 230, 5617, 937, 10484, -71, 2653, 1203, + -1, 667, -1489, -10136, 7782, -763, 792, 1434, + -170, 367, 96, -21992, -252, 756, 145, -1476, + 1408, 1523, -819, -576, -476, -1068, -241, -39, + 1547, 9553, -622, -1799, 1861, 6115, -864, 10690, + -586, 470, 200, 1162, 586, 44, -11650, 3453, + 8734, -2754, -178, 236, -2650, 2654, 2699, 1180, + 5325, -458, -40, -218, -6, 126, 6794, 506, + 860, 11863, 652, 1665, -4213, 4863, 1424, 5712, + -663, -688, -10, -1421, -676, -1325, -378, -311, + -490, 19501, 1242, 268, 4581, 1587, -1153, 848, + -1378, -1159, 505, 63, 704, 1942, 2204, -2106, + 44, 479, -1098, 333, -21595, -617, -6444, 3547, + 1282, -1784, 4664, -1330, 2607, 1241, -3579, 247, + -875, 11359, -3013, -136, -12813, -14400, 1857, -998, + 1342, 1187, -338, 1263, 575, 1226, -995, 596, + 446, 293, 767, -356, 70, 786, 466, 202, + 149, 849, -28991, 652, 124, -209, -124, -406, + -5463, -1413, -1300, -5339, -1761, 4770, 2680, -10542, + 3486, 5601, 2932, 1581, 489, 521, -16583, 1, + -1529, 5942, 1234, 4714, -1647, 1150, 2802, 642, + 586, 3836, 240, 307, -490, 67, 771, 816, + -906, 1554, 1090, -2353, -629, 11291, 2941, -2982, + 9473, 1434, -4351, -8017, -5173, 8071, 1931, 1281, + -4055, -3224, -1918, -271, -204, 670, 3491, 107, +-31624, 227, 75, -91, 108, 171, -53, -201, + 373, 63, 118, 126, -104, 127, -88, 1810, + 11688, -10240, 550, 3692, -4978, -1619, 40, 911, + -1080, 580, -767, 333, 192, 403, 308, -904, + 142, 31169, 503, -1101, -146, -144, 35, 181, + -355, 54, 590, 499, 95, -1767, 444, -49, + 2160, 7176, 12032, 6478, -741, -5576, -644, -101, + -1251, -1268, 2365, 10029, 537, -1476, 307, 2108, + -2478, -944, 10725, 349, -4242, -135, 7577, -4492, + 1492, -2512, 7736, -5118, -6756, -2436, -1890, -2390, + 1620, 914, 1658, 47, -11692, -134, -1740, -196, + 9521, -136, -1376, -8682, -1136, 1096, 903, -1148, + -334, -228, -4, -675, -199, 1914, 2827, -11098, + -2129, -2559, -978, 175, 1832, 10075, -2358, -1888 +}, + +.cb4448l1 = { +-11514, -2858, 12392, -305, -206, 929, 473, -3120, + -2766, -1068, -1237, 420, -718, -21, -336, -45, + -478, -1517, 1830, -12644, 259, 11978, 257, 1494, + -1759, 247, -733, 112, -2242, 290, 234, -10260, + 1781, -1806, -4104, 1747, 38, -692, 4971, -9113, + -1925, -1580, -615, -9608, 3779, -11158, 469, -4736, + 299, -2815, 2108, 1910, -2356, 66, 523, -440, + 2298, -4219, -2512, -1110, 11192, 5932, -2629, -7985, + -992, 775, -1134, 3287, 900, -681, -39, -1206, + -1708, -6800, -361, 11024, 8496, -198, -3855, 1486, + -2547, 1773, 50, -276, -286, 785, -7884, 438, + 4590, 2794, 5333, 5476, 2108, 660, 3610, 2308, + -8538, 224, -132, 134, 731, 988, -1368, 3894, + 4318, 9911, -104, 320, -9506, 1721, -5690, 1712, + -8747, -1876, -5122, -1304, -162, 752, 3646, 1621, + 11089, 1117, -1971, 1058, 3070, 180, 23112, 175, + 483, -1028, -538, 497, 1053, 61, 788, -455, + 22, -55, -32, -326, 15956, -2045, 788, 9784, + -1170, -819, -3677, 647, -484, 578, -160, 286, + -421, 289, 8140, 3838, -578, -1866, -2074, 667, +-11951, 1684, 3439, 1280, 158, -1784, 1276, 638, + 562, 2045, -220, 852, -594, -2109, -2665, 2748, + 38, 91, 1377, -624, -18586, -498, -882, 36, + 536, -99, 62, -5275, 3051, 231, -6343, -1751, + 1206, -1646, -1347, -13590, 1431, -271, -442, 21934, + -143, -1824, -378, -463, 816, 379, 336, -291, + -652, 275, -758, 257, -14866, -1304, 7260, -3373, + 1249, -1992, 2734, -2565, -3064, -416, 2424, 279, + 10518, 206, -681, -14338, 666, 1843, -648, 526, + 1982, 366, 684, 1019, 192, 8, -482, -4785, + 2134, -1722, 10674, -1613, 33, 1148, -1566, 10226, + 3397, 667, -1100, -738, 2420, -14282, 451, 90, +-10346, 2673, 1175, -3639, 266, -566, 0, 1672, + 1082, 298, 359, -497, 1784, -570, -2538, 2522, + -3825, 6265, 99, -7927, 3160, 11079, 131, -2080, + 92, -29951, 268, -293, 240, 254, -182, -145, + 303, 12, 86, 596, 246, 136, 1020, -1521, + -1134, -10125, -5691, 6028, -3703, -4295, -3718, -5719, + -564, 660, -321, -1073, 83, -3068, 6167, 12788, + -762, 8057, -1215, 2379, 2142, -3625, -503, -1418, + -304, -649, -501, -12558, 12787, 3737, 1465, -3692, + -1321, 1106, -1136, -651, -50, 1608, 59, -583, + 82, 331, 443, 782, 93, 285, 310, 29149, + -698, -52, -909, -238, -222, -114, 4, 650, + -200, 235, 2541, 598, 378, 11000, 3101, -8228, + 1690, -4313, 6996, -11, -2620, -1458, -1428, 579, + -304, 20, -372, 897, 602, 432, -138, 690, + 593, -1485, 136, 191, -32147, 260, 199, 412, + -168, -41, -384, -362, -14, 242, 366, -318, + -304, 1544, 458, -7790, 3332, -5117, -1937, 868, + 12622, 906, 1941, 4763, 1698, 351, -234, -973, + 9166, 6726, 2686, 248, 3597, -9812, -400, 4155, + 2852, -415, 2218, 876, 1423, 3852, 2965, -410, + 1820, 8268, -1296, 686, 114, 3087, 3007, -9402, + -5751, -3459, -6674, 418, 4137, 4778, 56, -1399, + -1698, -2590, 8343, -2130, 2535, 6148, -134, -2393, + 11551, -338, 735, 630, -658, 13358, 949, -1136, + -217, -985, 182, -1014, 1459, 221, 7713, -1386, + -1427, 1326, 555, 66, 2694, -1535, -268, -13596, + 658, 305, 858, 548, -12748, -582, -1055, -659, +-12155, 940, -2164, -2518, -126, -132, -842, 641, + -483, -446, -5184, -186, -511, 1169, -6092, 6161, + 3082, -664, -2037, 847, 11032, -1306, -1673, -1219, + -36, 1862, 10053, 780, -282, -837, -263, 509, + -588, -12646, -769, -2164, -2219, 524, -3433, -6437, + 3890, -623, -7509, 241, 4042, 264, -1394, 3646, + -6925, -5184, 1218, -1476, -2240, 1882, 182, -3450, + -497, -148, 160, -1579, -19545, -80, 886, 913, + 708, 728, 393, -603, -778, 3414, -778, -1495, + 1205, 2342, 232, -3634, -76, -16792, -684, 1322, + 192, -13248, -658, 7650, 4731, -169, 5148, -1413, + 3026, 2480, -2190, 1004, -2082, 237, 171, -717, + -766, -525, -11802, -3776, -9914, 1374, -3250, 415, + -2787, -175, -1081, 792, 980, 11464, 834, 714, + -993, 150, 77, 2306, 11249, -3058, -3418, -1758, + -239, -119, -1408, 6083, -4276, 1827, 1660, 2287, + -2997, -576, 400, 2062, -3174, -6215, 10026, -1082, + 41, 249, 10026, -6199, -301, 280, 10120, 2249, + 527, -564, 1002, 622, 3341, 408, 2870, 12902, + 13307, 689, 336, -819, -43, 832, -1242, 657, + -106, 42, 1123, 149, -2072, 78, -303, 329, + 21745, -2172, -1204, 448, 1437, -560, -376, 311, + -73, 153, -785, -368, 54, -445, -92, 120, + -59, -377, 402, 567, -25820, 1284, 1288, 200, + -865, -1286, -41, -1862, 402, 179, -2338, -3876, + 4992, -1824, -10092, -3407, -8516, -3556, 130, -5695, + 5846, 2333, 2995, 2110, -6946, 5049, -2377, 1655, + -859, -4737, 1648, 7031, -7344, 4992, 1760, -711, + 3134, 14363, -907, 171, -1971, -3062, -1079, 600, + 603, -224, -440, -11328, -291, -663, 1878, -715, + -2724, 284, -456, -10970, -3225, -2240, 252, -977, + -360, 729, -572, 3981, 1615, -52, -5372, 6095, + -9888, 6873, -3830, 4916, 1834, -1581, -11268, -2316, + -398, 1361, 6151, 2736, -1968, 4624, -180, -260, + -1221, -5633, -1300, -1081, -1433, -509, 366, -388, + 1660, 340, -18997, 694, -1184, -813, 1324, 1261, + 735, -186, 5258, -583, -221, 1707, 149, 1022, + -835, 1089, 2939, 2025, 421, 411, 3609, -13797, + 464, 9214, 2462, -6257, 6032, 1911, 1282, -9673, + 974, -703, -128, 950, 369, 1160, -674, -312, +-13858, 1078, -7606, 8, 2786, 367, -6441, -824, + -195, 714, 484, 108, 475, 289, -1012, -1591, +-10880, -324, -647, -2199, 10378, 5781, 995, -416, + 871, -1240, -380, 70, -1893, 7632, 1727, -908, + -672, -10901, -962, -7322, 794, 1748, -5568, 1215, + 5845, -9575, -2413, -2159, 3077, 1359, -416, 6277, + -85, 1352, -3498, 6130, 1125, -236, 1950, 8481, + 716, -560, -1311, -228, 250, -440, -5320, -1941, + -9710, 4637, 1420, -102, -8222, 616, -2254, -528, + 196, -1315, -749, -97, -285, -15880, 1105, 630, + 368, -809, 29, -1688, -2314, 745, -1627, 19840, + -2380, 4108, 1670, 2763, 275, 530, 492, -589 +}, + +.cb4448s0 = { +-10720, 9997, -1313, 8849, 5152, -226, -2908, 303, + -842, -870, 165, -1372, -105, -154, 170, 2424, + -2476, -2126, -8329, 349, -4509, 5128, -92, 9086, + -7263, 416, -124, 341, -88, 239, 5172, 553, + 1526, 1728, 1955, -1489, -6595, -11237, -10224, -394, + -927, -932, 674, 743, 317, 4628, 8453, -3768, + 2545, 3506, -2406, 9108, 5643, 4660, 4116, -2452, + -1391, -154, -74, 180, 5270, -7922, 46, 11046, + 6076, 735, 7922, -196, -1080, 1445, -687, -2403, + -784, 742, -269, -498, 6010, -4045, 1053, 891, + -1538, 613, -84, -4254, -957, 4682, -14004, 2050, + -647, -718, 557, -2720, 2437, -7675, 11874, -9284, + -734, 775, -2231, 105, 366, 1360, -98, -126, + 508, 2647, 729, 762, -8806, -10413, 9008, -2093, + 1107, 201, 1421, 1181, -259, 1420, 828, 327, + -1956, -573, -874, 354, 2662, -1437, 10864, -9240, + -7648, 1670, 1598, 173, 438, -373, -566, 246, +-11999, 1817, -611, 1, -1652, 1876, 1354, 1270, + -789, 300, -321, 11577, -516, 329, 5723, 4732, + 1717, -6224, -5356, -6292, -370, -3644, -922, -50, + -14, -581, -1554, -1675, -20, -965, 28479, 658, + -498, -488, 504, -601, 437, -585, -245, -196, + 186, 281, -174, 159, 7469, 5890, -5112, 4918, + -9023, -360, 40, -2975, 4784, -437, 1609, 1032, + 2759, -297, 106, 5176, -4315, 568, -9536, -1297, + -6783, -10965, 1285, 264, 330, -508, -522, 624, + 662, 539, 7248, -13780, 40, 2140, -2188, 1925, + -8972, 1147, -1340, 870, 779, -4, -101, -374, + 781, 5733, -5712, -5777, 2080, 875, 13450, -1551, + -3229, -1818, -114, 1265, 501, 636, -576, -623, + -1269, 3006, 1023, 862, 1359, 1950, 588, -22648, + 218, -438, 1547, -408, -844, -263, -106, 14754, + -689, -9466, -978, -21, 1412, 43, 2012, 352, + 908, 277, -960, -747, -230, -1557, -7132, -5707, + 79, -2474, 2177, -5349, 2510, -12720, 2833, -2152, + -1693, 458, 197, -643, 735, -2728, -893, 2758, + 5196, -3566, -4294, -4914, -1222, 188, -8884, -6234, + 2391, -1518, 663, 572, -1465, 1147, 8486, 2037, + 2516, 941, 6092, 11602, -2559, -1702, -1848, -924, + -210, -108, -1052, 8360, -7567, -4588, -169, 3464, + -9206, 1842, -4329, -2499, -341, 592, 918, -102, + 340, 214, 1037, -324, -16289, 10308, -47, -29, + 1340, -603, -2763, -548, 392, 1489, -149, -769, + -67, 13270, -2233, 8257, 1582, 1034, -4270, 916, + 4486, 1191, -102, 159, 109, -536, -664, -987, + -8041, -1759, 4264, -5600, -13815, -1158, 1712, 2516, + -634, 504, 515, 732, -46, -685, -481, 1685, + -1782, 262, -3600, 14721, 6334, 7941, 101, 914, + -2141, -2, 182, 829, -215, -122, 6325, -3752, + -2812, 1618, 3512, -1591, -4276, 6994, -10349, -5675, + -1501, -1766, -1949, 436, 82, -5596, 2592, -1086, + -2804, 2540, 458, -550, -1834, -2401, -7563, 2340, + 1678, -7666, 4538, 27, 6337, 3642, 17068, 5310, + 1115, 1579, -142, -397, -670, 2010, 863, -504, + 845, 848, 770, -8821, 1963, 2782, 162, 1130, + 2597, -13699, -3996, 800, 2499, -1045, -1512, -186, + -59, -119, -5048, 6800, -8766, 784, -7091, -1002, + 335, 1993, -1045, 601, 1804, 166, 1343, 110, + -224, 2247, -344, -5, -4292, 5846, 8591, -11846, + -1303, -1027, 1759, -168, -194, -1281, 489, 378, + -5069, -3321, 11238, -375, -806, 3962, 9660, -2960, + -664, -1067, -627, 271, 1205, 1160, 261, 3725, + 7877, -679, 22, 598, -1086, -420, 2168, -46, +-15552, 420, 1220, 1332, -58, -156, 7777, -4657, + 352, 15316, -4760, -2140, -2577, -1321, 2037, -371, + -1254, -912, -1177, -1367, -103, 4572, -9482, -1599, + 294, 403, -272, -2331, -4365, 13467, 4585, -2554, + -1743, 545, 162, -369, 6074, 11273, -8856, -8175, + 2543, -7, 314, -2033, 2704, -1755, -1431, -791, + -276, 1085, 236, 6553, 1872, 387, 1056, -31, +-20610, -609, 608, 1007, 1604, -1501, -68, -527, + 204, 252, 2533, -721, 1468, 444, -72, 61, + -209, 512, -216, 42, 385, -490, -104, -29030, + -166, -4883, -2754, 788, -430, -867, 565, -1155, + 562, 1076, 1757, -2990, -14971, 8392, 902, 550, + 102, -6579, -6939, -319, 172, -863, 979, 2178, + 630, 160, 952, 946, -3955, 1515, 352, 2557, + -5339, 6166, 4588, -2040, 4031, -535, -2504, 2782, +-12136, 1338, -2758, 458, -671, 155, 6998, -2598, + -931, -396, -922, 2060, 447, -42, -649, -532, + -552, -1945, -16548, 815, -408, 3469, -4118, 875, + -1017, -11150, -511, 3846, -11349, -1928, -781, 2765, + -681, -713, 655, -218, -8032, -465, 295, 1591, + -383, -1889, 1627, 108, 1149, 2513, 388, -5702, +-15693, 24, 470, -4322, 3721, 1584, 1808, 350, + -1765, -620, -2953, 4354, 8512, -12533, -86, -2490, + -192, -507, 2024, 3942, -801, 13444, 738, -2086, + 162, 2013, 837, 56, -384, 3164, 5052, 1158, + -403, -6913, -4290, -2068, 16622, -2738, 856, -2884, + -2432, -410, -1179, -456, 504, -1359, 436, 352, + -6351, 327, -2196, -1502, 302, 338, -839, 235, + -520, 1283, 2710, 18814, 2256, -2, 400, 1300, + -1185, 1024, -3744, -3542, -4350, -763, 1902, -14737, + 5437, 48, -1589, -280, -67, 232, 2276, 1413, + 3284, -308, 1013, 610, 22787, -685, 724, 12, + -359, -1651, -1060, 569, 248, 3836, 605, -413, + 3380, -1360, -1120, -2933, -2368, -977, 10135, 12356, + 3739, -1571, -418, 580, -2662, -11460, -6128, 2867, + 11468, 825, -3201, -501, -138, -755, -554, 168, + 757, -564, 428, -12118, -15179, -1978, 432, -597, + 1528, 3038, -568, 1349, -3377, 914, 498, 928, + -91, -5, 9192, 3000, 2542, -1411, 626, 2705, + -763, 3247, 13736, 3034, 2170, -67, -852, -378, + 1264, -2771, -2415, -4236, 126, -1984, -13336, -1088, + -416, -1979, -520, 2506, -1505, 294, -2398, 218, + -8740, -3873, 2069, -1374, 86, -998, -3851, 1070, + 13357, 955, 3085, -536, 166, 926, 299, 6532, + 1324, -502, -1658, 1829, -1263, 445, -1902, 1452, + -2747, -16422, 1875, 1773, 452, 288, 5992, 1626, + 3659, -917, 2255, -1508, 356, 547, 158, 9, + -117, -1665, -595, 14392, -1013, 49, -4060, 12064, + 3666, -2903, -9145, -396, -4341, -953, 2758, -178, + -204, -462, 98, 222, -3622, -12200, -4484, -94, + -8642, -5694, 4034, -720, -1695, 751, -1668, -266, + -343, 296, -112, -900, -3750, -360, 1002, -7402, + 7758, 7370, 3332, -7517, -769, -1272, 412, -1451, + -89, -227, -11332, -472, -1108, -394, -339, -1981, + -3494, 12110, -564, -5958, -690, -1066, -130, 762, + -50, -1456, -1521, -8428, 994, -867, 2650, -2335, + 354, -2253, 4612, -12364, -2626, 1853, 577, -103 +}, + +.cb4448s1 = { + 25901, -239, 648, 167, -284, 198, -340, -1112, + -55, -242, -214, 528, 112, -259, -284, -250, + 23, 475, 780, -558, 111, 148, -2411, -19826, + -1158, 2799, -964, 44, -1204, 1187, -4036, 1872, + 3541, 768, 159, 1979, 3382, -113, 804, -1021, + 3708, -2577, 9697, 11527, -326, -7058, 4306, 1260, + 3782, 3370, 1595, 705, 2268, 2182, 1509, 1131, + 9877, -7260, -258, 49, 1686, -1472, -2556, -1973, +-22425, 338, 486, 963, 1069, -34, -1027, -90, + -881, -473, 554, -6326, -873, -9744, 10157, -1079, + 584, -1047, -1954, 6204, 2416, -899, 1452, 938, + -439, -664, 4231, 9370, 7800, 170, 9448, -4756, + 1967, 686, -1186, 636, -1719, -1244, -540, -728, + 306, -1778, -7980, -3418, 8318, -1828, 1556, 3487, + 10195, 3741, -510, 2077, -1496, 1241, 384, 477, + -1051, 7922, -4077, -2513, 849, -693, -9170, 4264, + -7940, -1703, 460, -2986, 586, 13, 377, 781, + -7047, 6852, -1350, 7537, -493, -1919, 379, 3108, + 4293, 8467, -3875, 63, 44, 493, 1496, -1577, + -5676, 3318, 6628, 5177, -11082, 1146, 3251, -1159, + -461, 442, 1250, 212, 176, 3586, 137, -9153, +-13772, -8211, 393, 1170, 1717, -671, 298, -233, + 883, -1533, 401, 254, 7700, -4827, 794, 377, + -376, 12240, 7298, 2445, 1168, -562, 1528, 563, + 421, -606, 0, 5792, -1069, 824, 3728, -2729, + 1005, -730, 4318, 644, 17336, -1588, 2100, -365, + 509, -415, 3684, -9128, -1096, -4278, 1549, -1247, + 5519, 11075, -2216, 6004, -3683, 409, -730, -414, + -263, -6623, 8194, 489, -9085, 334, -1104, -814, + 1412, 1522, -1657, -7029, -4142, -1274, -520, -40, + 650, -1886, 9701, 11456, -7567, 1176, 3268, 3016, + 1109, -117, -858, -155, -1249, -230, -216, 3945, + 9142, -2297, 134, -2563, 15131, 857, -1597, -618, + 150, -590, -166, -357, 388, -69, -8767, 2914, + 1087, 4673, -14373, 600, 382, -1893, 844, -242, + 544, -106, 568, -1141, 371, 2663, -1860, -725, + 8066, -1353, -8743, -10433, -1796, 427, -73, 178, + 96, 980, -478, 978, 1767, 6034, 633, 966, + 677, -65, -884, 417, 461, 62, -868, 93, + -100, 519, 16304, 2646, -1260, 12271, -140, 142, + 11138, -892, -2114, -629, 172, 744, -2056, -960, + 61, -980, 2082, -439, -3126, -2564, 1174, -78, + 254, -178, 1599, -436, 19023, 5335, -1686, -782, + 520, -8727, 256, -3588, -5694, 12323, -2091, 1511, + -656, 3872, 2370, -770, 282, 455, -573, -39, + 7845, -12566, 12690, -156, -442, -227, 575, -274, + -1717, 120, -40, 1866, 635, 161, 270, 1039, + 3256, -673, -3343, 4292, -14247, 7142, -4821, -591, + -418, 376, 21, 572, 551, 70, -5536, 79, + 2540, -505, -283, -350, -1279, -1630, 2234, -604, + 5246, -17580, -3022, -1052, -307, 6626, 2794, 1702, + 1875, -1876, 1011, -320, 1268, -282, 1072, 14370, + -8206, 1218, 630, 173, 7486, 15176, -6146, 4903, + -636, -1341, 1360, -1541, -1012, -778, 84, 426, + -124, -746, -252, -11085, 1783, -2833, 809, -744, + 2194, 3328, 7029, -5097, 4934, -3025, -641, 303, + -328, 258, 8674, 53, -3395, 975, -9944, -8550, + 3376, -714, 1078, 1186, 598, 808, -166, -752, + 484, -5088, 1484, -1278, 11394, -1876, -8236, 5159, + -1830, -1520, 2761, 592, -204, -1360, 454, 230, + -5038, -1582, -5617, 1346, -2045, 2306, 17764, 494, + 572, -1930, 339, 550, 784, 151, -753, 4708, + -3058, -8267, 3281, -1054, 870, -1201, -2005, -920, +-10115, 5395, -6423, -798, 367, -221, -5296, -2808, + 8313, -5077, 1655, -200, 114, 46, 350, -2374, + 868, -327, 377, -9570, 1231, 9258, 8752, 3074, + -4411, -308, 2315, 6824, -3303, -896, -1186, 579, + -2561, 2280, 586, -798, 4747, -3487, 1306, -1241, + -487, -90, -52, 3231, -555, -17702, -2681, 1649, + -17, -278, -647, -4225, 2740, -1248, -3826, 1356, + 3572, -1010, 16160, -422, 304, 3970, 1124, -317, + -554, 673, -1191, 3180, -4429, 1581, 1543, -2097, + 4208, -9363, 10146, 1896, 2904, -4112, -1428, -207, + 459, -35, 5395, -8960, 3141, 11004, 308, 3687, + 1540, -2156, -592, 1640, 1003, -280, 797, 204, + 6910, -824, 4724, 4729, 5553, -3165, 483, -12, + 33, -588, -379, 402, 3543, -9646, 74, 9603, + -465, 2872, -2367, -885, 2894, -133, 2758, -721, + 3473, -13322, 1506, -1344, 512, 1066, -8300, 11391, + 11976, -1201, 13, -612, 165, -1823, 154, -123, + 1234, -423, -367, -58, 384, 2687, 2536, 826, + 6223, 1750, -8589, 1126, 9772, -6646, 2043, 1826, + -1037, -2018, 692, -818, -3431, -467, 11006, 3407, + 880, -2047, -10303, 6168, 1428, -307, -18, 661, + -252, 754, 1207, -2797, -3057, -6235, 99, -931, + 1618, 692, 2790, -294, -1200, -5768, -11691, -5305, + -100, 390, -783, -11660, -4675, -13570, 2764, 1414, + -786, 385, 163, 718, 794, 1118, 827, -634, + -75, 6224, 3965, -2092, -1120, -6395, 5474, -12986, + -3985, 635, -544, -1877, -191, 0, 121, 379, + -3059, 132, 26320, -721, 1262, -706, 421, -85, + -38, 665, 590, -208, -196, 168, 10, 1271, + -218, -365, -5843, -5897, -12346, -3026, 5916, -115, + -2671, -1022, -203, 962, 995, -850, 527, -516, + -1641, 452, 68, 1204, 740, 385, 38, 752, + 150, -3088, 20608, -54, -39, 6109, 3224, -92, + -315, 4407, -306, 1317, -395, -1617, 9104, -3493, +-10724, -3059, 283, 81, -9791, -3210, 7307, 4459, + -639, -61, 1152, -184, 2290, 398, -2902, -2776, + -1624, 1153, 242, -8865, -3617, 309, -11933, -3847, + -5750, 3235, -153, -315, 382, 209, -923, 2072, + 458, 164, 3631, 3121, 3220, -828, -8644, 2215, + 3873, 12445, 533, -631, -53, -136, -728, -240, + 420, 2870, -4981, 906, -3272, 4735, 3613, 2412, + -3951, -10587, 7389, 564, 3266, -1348, 524, 1570, + 6611, 3354, -1042, 1862, 1860, -1187, 5761, -1722, + 8231, -7428, -5662, 1239, -2887, -218, 810, -1063, + 15078, 686, -2374, -293, -2031, -245, 4441, 5045, + 1100, 6722, 1787, -587, -380, 132, 5124, -12478, + 95, -1230, 1464, -1871, 929, 1430, 2666, -3768, + 2784, -3697, -8238, -247, 603, -8406, 1330, 1033, + -743, -2546, 2739, 856, -12698, -4970, 2290, -1104, + 34, -1048, -80, 634, -695, -84, 2374, -24793, + -1064, -1080, -254, -812, 252, -1582, -401, 765, + 847, 340, 479, -3163, 150, -187, 8432, 2607, + 2075, 1384, 423, -7361, -10262, -2254, 54, 1065, + 40, 857, 2014, -5076, 198, 657, 482, -422, + -2185, -850, -318, 164, -684, 2698, -1008, 17493, + -64, -6788, -5966, -14352, -2349, 2492, 266, 1077, + 1935, -99, 4270, 2319, -2391, 779, 187, -70 +}, + +.cb4448m0 = { +-20455, 663, -3140, 2540, -2110, -406, 1078, 1968, + -741, -2458, 490, -496, 338, 581, 1079, -616, + 154, 10097, 231, -228, 477, 20, 1372, 11492, + -1112, -3148, 547, 248, -676, 8197, 5902, -1299, + 519, -2808, 11529, -76, 1239, -1032, -542, 353, + -1071, 278, 274, 2781, -7741, 3260, 2711, 175, + 12340, 1110, -2348, -5303, 1440, 581, -70, 262, + -9902, -2375, 530, 1433, 1624, -1475, -947, 13450, + 1318, -1696, 207, 198, 1162, -944, -9329, -1046, + 195, -106, 682, 14624, -854, -2410, 1054, 242, + -348, 581, 463, 716, 760, 2714, 1356, -1359, + 13089, 2565, -10523, 1934, 637, 1218, 1160, 830, + 905, 272, 408, -581, -1426, 613, 2586, -8186, + 3748, -6663, 4372, -114, -4644, 2998, -9440, 685, + -8741, 3363, -5623, -4229, -7058, -1201, -822, 1806, + 8671, -856, -612, 1165, -426, 317, 6867, -80, + -7084, 1143, -1862, 2742, 669, 550, 22, 173, + 4301, -10406, 1042, -346, -1334, -2897, 647, 744, + 14, -1338, -1648, -1235, 3550, -455, 2125, 1188, + 17136, 1188, -6782, -849, 298, -1054, -9254, 409, + -1736, 1410, -7254, -1889, 457, -740, 22, 262, + 32242, 1657, -2308, 2688, -607, 609, 4, 150, + -264, 192, -140, 246, -393, -76, -15050, 390, + 969, 457, 1436, -649, 460, -12150, 1359, 1014, + -2103, -576, 55, -590, 113, -1410, -23431, 182, + -2386, -1568, 904, -218, -281, -188, -178, 63, + 211, 549, 687, -12069, -88, -654, -1070, -13155, + -124, -697, 438, 3174, 1700, 270, 234, -289, + -625, 15749, -2340, 8466, 397, -4460, -1030, 3206, + 1081, -1317, -1030, -72, 487, -1477, -8782, 6984, + -1221, 2395, 3198, 2995, 5862, -1195, -6075, -1020, + -934, 868, -470, -1024, 1202, -998, -1306, 22118, + 344, 540, -3137, -547, 2440, -28, 222, 372, + -424, -199, 1068, -917, -105, -4278, 52, -299, + 6933, 11715, -520, -2853, 58, -8575, 416, -1272, + 1128, -32, -1140, -1873, -495, 235, 2079, -314, + -1328, -2615, -20194, 848, -1553, 387, -6091, 906, +-10180, 8634, -506, 4078, 318, -2657, 1612, -126, + -1424, -4, -1745, -343, 302, 2439, 12190, 941, +-12534, -4756, -176, -90, -1295, 1041, 1875, -450, + 89, 212, 2098, 1708, 1876, 4065, 1682, 1972, + -4916, -951, -10683, 1443, -10978, 772, -1013, -235, + 59, 213, -230, 142, -576, 506, 101, 44, + -137, 26238, -47, -322, -289, 281, 2614, -4538, + 634, 1116, 1191, 2985, -759, -5527, 550, 2107, + -6018, -11013, -425, -221, 901, 217, 546, 213, + 2026, 695, 1074, -2132, -173, -1664, -783, 25065, + -326, 86, -632, 1398, 4708, -2911, 2376, 135, + -1471, -904, -2338, 987, 3216, -4564, 314, 15692, + -214, 1238, 230, -181, -30537, -294, 155, -607, + 218, -309, -180, -246, -102, -988, -644, 111, +-10517, -1604, -1180, -2748, 1191, -12959, -2, -1004, + 28, -196, 1974, -790, 809, 8802, -1204, 332, + 180, -3857, 1025, -5998, -9578, 94, -1069, -2398, + 185, 643, -1479, 322, 2544, 12584, -8308, -3856, + 1286, 1600, -2539, -2752, -2520, -367, -942, 417, + -309, -2162, 2044, 10886, 1764, 11028, 3810, 2955, + -1028, -1017, -1752, -487, -605, 48, 2312, -368, + -1758, -252, 371, 19882, -1994, 1675, 5494, -660, + -1669, 256, -54, -941, 4318, -306, 2143, 273, + -3367, -3088, 6509, -1884, -5400, -576, 11394, 875, + 455, 271, -218, 1401, -44, -5336, -12170, 4664, + -589, -3562, -1934, 5842, 1357, 3232, 1449, -402, +-11228, -96, -1509, 2073, -1751, 776, -439, 775, + -3302, 13521, -325, -118, -172, 411, -396, 6154, + -2455, -52, -4616, 783, -12488, -2085, 5817, -1278, + 635, -1713, 2888, -830, 649, 7482, 10134, 9147, + 3784, 1046, -1934, -2580, 102, -679, -124, 68, + 657, 417, -175, -32768, -80, 375, -941, 224, + 271, -232, 1519, -99, -680, 67, 66, -618, + 252, 1907, 5121, 2456, -2117, -9388, -1441, 636, + 7868, -8340, 1939, 1340, 1511, 711, 6530, -1748, + -183, 90, 2561, 5860, -364, 5117, -4101, -4028, + -944, 10526, -1028, 1047, 707, 12116, -12596, -4006, + 922, -1047, 348, -971, -272, -2388, 435, 246, + -1055, 148, -1852, -12418, -2531, 3524, 4103, -344, + 1667, 2818, -4576, -273, -8337, 183, 497, -144, + -9845, -292, -503, -1212, 4316, -1434, -11058, -3043, + -5817, -981, 813, 0, -718, -467, 10285, -19005, + -82, 776, 1192, 1030, 1560, 1080, -144, 729, + 606, -225, -389, -187, 552, -930, -444, -5959, + -1960, -1315, 2650, -1282, -18790, 1772, 263, 1410, + 812, -458, -476, 744, 2595, -426, -19, 9119, + 4529, -1502, 4673, 3675, 7430, 1084, -6966, -518, +-13552, 1054, 2474, -9499, 1041, 5114, 442, 2927, + 511, -1492, 217, -726, 398, -522, 35, 119, + -332, 106, 816, 437, -1223, 27612, 521, -29, + -462, 367, -966, 476, -2559, -3485, -160, 1487, + -272, -586, -6014, -232, 3679, -1864, 1244, 575, +-14591, -483, -1428, 20, 7874, -2948, -5965, 2383, + 3270, 490, 2750, -547, -9658, -1473, 943, 285, + -2388, -772, -1582, 3181, 3419, 2628, -197, 3376, +-13282, -7684, 3383, 70, -1174, -70, -6703, -7305, + -553, 3588, -826, -12, 7350, -3604, 345, 1098, + 3856, 918, 2038, -39, 11514, 15798, 1327, 1158, + 436, -918, 71, 953, 975, 1147, 174, 411, + 1467, 83, -4536, -1511, 5350, -3314, 13999, 18, + 4107, 1901, 834, 2614, 2356, -369, 943, -341, + -460, 4380, -10014, 3308, -3541, -3225, -621, 8449, + -1383, 4481, -1399, -3646, -936, 923, 221, 346, + 7828, 2406, 3021, -4993, 3012, -10903, -1925, 8153, + 382, -1453, 1238, 601, 1195, -2245, -2792, -4118, + 473, 4898, 12961, -6094, 5905, 1368, -2754, -303, + 768, -31, -1275, 1400, 596, -1326, 619, -1744, + 1145, -3977, 639, -10785, -1693, -11192, -541, -434, +-11384, -1017, 14361, 1398, 521, -3239, 1851, -491, + 237, -1024, 1002, -3002, -303, -33, -6532, 601, + -3726, 7832, 6090, -10107, 957, -1149, 689, 1327, + -51, 1945, 990, -106, 595, 234, 518, 1060, + 77, 837, 28880, -91, -395, -275, -265, -279, + -217, -300, 240, -1055, -406, 4314, -2139, 6349, + -2227, -5996, 963, -10386, 4629, -560, 1080, 134 +}, + +.cb4448m1 = { + 31577, -1322, 1533, -2224, 253, -1485, -92, 294, + 183, -580, 420, 172, -794, -206, -342, -338, + 53, -85, -920, 29517, 1073, -972, -1839, 1004, + 290, 46, 460, -71, -988, 1731, -362, -2070, + 3848, -2, -3842, 734, -1221, -8012, 1104, 6782, + 9673, 1082, -8561, -860, -2135, -1557, -1613, -13999, + 1664, 2268, -1570, -732, 1010, -402, -1139, -428, + 400, 1123, -2108, -11776, -345, 10608, 1245, -3142, + -3244, -1132, 1700, -308, 1573, 543, 678, 5160, + -3062, 433, 2703, -852, -4903, -1880, 1706, 13995, + 2465, -4844, -904, -148, 350, -11168, 1406, 312, +-11900, 397, 769, 5558, -1354, 187, -30, 231, + -1020, 202, 884, -198, -3151, -830, -8490, -670, + -2767, 1517, -12957, -3861, -2794, -1854, -180, 135, + 7140, 4103, -4427, 450, 494, -1033, -1110, -2857, + 11056, -711, -800, 3628, -180, -852, -10300, -2120, + -450, 14464, -511, 303, -1464, -542, -89, -204, + 500, -400, -318, 569, 216, 428, 350, 1973, + -137, -885, -1794, -974, 3977, 3382, -18624, -420, + -1947, 165, -449, 1395, -17313, -286, 2054, -447, + -2740, -1881, -550, -2166, 1360, -6021, -94, 148, + 676, -1619, -1737, -11977, -169, -1664, -7709, 6202, + -5954, 1681, 715, -263, 56, 369, 589, 564, + 1989, 1617, -1648, 9205, 1343, -11508, -7379, -3791, + -3136, 1049, -844, 24, -6714, -1736, -5734, -2907, + 5016, 2167, -5722, -1210, 6232, 428, 2467, -3334, + -1477, -711, 6728, -10274, -4930, -6224, -349, -710, + 1598, -713, -1708, -497, -254, 567, -884, 131, + 11520, -908, -1425, -1862, -13449, -1590, -669, 657, + 505, 236, -4, 21, 846, 100, 8248, -1847, + -131, -186, 181, -806, 3293, -1072, -1208, 14492, + 1555, 1527, 544, -120, -258, 6, -2401, 12455, + 10880, 1091, -2350, -939, -1252, -564, 150, -114, + 1419, 737, -1732, -440, -2303, -226, 536, -2492, + -1085, -10117, -11013, 3786, 5275, -10, 2479, 143, + -1647, -7945, 884, -1618, 2056, 12890, -424, 5986, + -1471, -666, -570, -1466, -499, 64, 566, -1738, + -639, 11380, -612, 1879, 1550, 12469, -299, -1501, + 2634, 1036, 3020, -13, 14974, -2066, -5786, -2667, + 5487, -6768, 468, -385, 778, -805, -536, -304, + 718, 386, 285, 7546, 643, 1462, 913, 4707, + 941, -3338, -194, 6669, -4493, 8869, -837, 400, + -877, -11113, 326, -2318, 13683, -1304, -1966, -933, + 312, 128, 470, -296, -322, 340, -1126, 1811, + 1999, 2885, 3201, 331, -2494, 3999, 660, -80, + -2063, -16771, -1337, 426, 4884, -6026, -40, 2093, + 342, -176, 83, 134, 796, -425, -8934, 2100, + 8550, 160, -221, -252, -32714, 1306, 1332, -609, + -109, 547, 848, 518, -40, 303, -246, -451, + -2177, -716, -750, 1, -21232, 1287, -1303, 2051, + 1659, 1501, -369, -1415, 274, 308, 260, 371, + -1409, -662, -7347, 7161, 3656, -1104, 8862, -5671, + 1370, 1122, 16, 1132, 17593, 6778, -993, 613, + -665, 3004, 3288, -1625, -1823, -1003, 740, -1002, + -888, -677, -1065, -25294, 997, -160, -180, -811, + 188, -333, -2483, -696, 1309, 120, 456, -116, + -2020, -896, 7216, 6328, -9170, 8407, -2986, -1684, + 680, 1752, -684, 613, 337, -629, -11750, -493, + -324, -907, -391, 1053, 14125, 142, 420, -1917, + -378, -1428, -90, -497, 1116, -464, 2170, 805, + -1572, -904, -9020, -534, 6450, -490, 10750, 279, + 765, 961, -3985, -2702, 2423, -4981, -1222, 1654, + -1089, -2157, 1940, 14331, -895, 1726, 1555, 122, + -3552, 1274, -598, -910, 3056, -1704, 6430, -10626, + 1014, -8773, 1009, 1936, -360, -468, -1029, -8841, + -625, 2212, 2234, 2720, 1190, -64, -2078, 4688, + 8690, 5150, -450, 744, -796, -5661, -332, -7938, + 2670, -4054, 1377, -1594, 11554, -4702, -3631, 745, + 742, -90, -1311, 12528, -4664, 834, -853, 1542, + 8560, 2209, 4091, 2876, 2117, -678, 1684, 785, + 304, 7980, 2126, -302, 8239, -2105, 1584, 11894, + -1055, -1391, 596, 2343, 86, 388, -1348, -1007, + 1428, 413, -9231, -10312, -7346, -1108, 1385, -1255, + -3954, 738, -1258, 410, 226, 15115, -1059, -4117, + -50, -504, -1726, 1425, -9974, -346, 688, 464, + 244, -586, -8880, 845, -659, 932, -1309, 290, + -29, -417, -2184, 1011, -9622, 1443, 9009, 1945, + 2698, -708, 10572, 2410, 1200, 4492, -2569, 1444, + 2735, -8604, 2274, -4057, 478, -199, 1285, 12695, + 12321, -2933, -1708, 1198, 675, -492, -560, -52, + -1261, 85, -480, -96, 696, -764, -1402, -31368, + -580, -675, -1678, -58, 600, -522, -292, 647, + -36, 154, -1148, 437, 1561, 588, 603, 7629, +-16973, 29, -828, -589, -919, -1372, -470, -445, + 428, 528, 5828, -353, -32, -1781, -702, -690, + -7196, -3253, 1942, 4600, -12102, -674, -10480, -2336, + 711, -2174, -7474, -1436, -451, -7133, 856, -2652, + 1892, 3464, -546, 676, -13296, -516, -13618, -997, + 938, 1686, 1006, 1358, -1371, 922, 534, -170, + 126, 255, -835, 50, 945, -1066, -1676, 3, + 1038, -437, 26030, 418, 27, -1092, -493, -428, + -606, -1097, -628, 298, 295, -806, 183, 146, + 1352, -84, -722, 833, -25667, 3176, 1001, -322, + -2339, 15, -475, -1257, 2116, 876, 637, -529, + -1108, 302, -2452, 19734, 58, 851, 9845, 1142, + 2168, 706, 11070, 1556, 544, 3002, 2238, -3974, + 2738, -48, -8324, -2186, -355, -14933, 2192, -2481, + 2700, 473, -486, 761, -208, 76, -78, 102, + -4896, 1378, 12377, -8269, 28, 1092, -5071, -1500, + -1190, -804, 1085, -766, 493, 22, -1041, 9136, + -1234, -12247, 967, 2672, -883, 4582, 4871, 1891, + -532, 329, 226, 446, -6710, 312, -914, 1416, + -1852, 3052, 6512, 8971, 5544, 6519, -579, 1021, + -241, 911, 782, -3456, 10158, -1865, 3941, -12300, + 8, 472, 882, -1580, -1799, -1025, -631, -127, +-15316, 8047, -200, -1860, 582, -4363, -1274, 1085, + -48, 2383, 638, 480, 369, -838, -1341, 414, + -114, 2757, 1222, -2194, -3394, 6469, 2418, 738, + -1656, 15594, -1090, 202, 727, -769, 484, 2462, + 4875, 1656, -3835, -16877, 5276, 239, 982, -1872, + -130, 901, 1352, -155, 4939, -8317, 9000, 2503, + 485, 1184, -548, -1356, -7482, -188, -1587, 496 +}, + +.fcb08l = { + -2539, -3275, -2699, -3345, -2843, 5501, 426, 7127, + -149, 3111, -2991, -2297, -2345, 2702, -969, -946, + 2837, 1114, 1800, 1271, 12249, -2282, -2309, 1566, + -2889, -3020, -2083, 3586, 8919, 2651, 4111, -1842, + -1588, -1428, 3251, -102, 156, -320, 722, 1711, + 20565, -3068, -2211, -3164, -3410, -3396, -2882, -2002, + 1730, 4077, -2696, -1694, -2839, 2948, -2739, -2380, + -2252, -1311, -269, 1900, -2796, -444, -2996, -2525, + 5194, 1459, 5042, -1089, 914, 4116, 7644, -3137, + -3156, 4028, -3435, -3240, -2585, 5542, 5119, 9885, + -2995, -3153, -3449, -3101, -3551, -3469, -2196, -1271, + 3869, 5413, -2800, -1990, 3371, -2286, -1022, 3190, + -550, 1723, 968, 1916, -2749, -1530, -2211, -2987, + -3357, -3262, -1042, 10277, 107, 2662, 9819, -2753, + 4269, -3277, 3125, -3131, -2974, -3251, 6466, 9484, + -2034, -2707, -2424, -3170, -2619, -2278, -143, -1641, + 11856, 5975, -1282, -2629, -2396, -2364, -2012, -1085, + -2576, -2422, -2206, 13731, -2261, 2751, -1768, 2482, + -1065, -347, -137, 31, 619, 385, -2257, -2215, + -1698, -2686, 4468, -2563, -1071, -1359, 7757, 3732, + -2856, 9018, -2046, -1494, -2234, -2209, -67, 1340, + 2433, 2965, -2722, -2151, -2966, -2780, -2732, -1509, + -2085, -1532, 6934, -1248, -1936, -2203, -787, -1781, + -895, -1990, 4693, -1818, -1569, 1954, -2283, -2403, + 10514, -3105, -1074, -2838, -1, 1192, 1113, 3309, + -2249, -2451, -1660, 2535, -1439, 3582, -1093, -594, + 1956, 758, 5349, -2524, -2320, -1903, -2055, 5075, + -941, -721, -536, 2197, -2309, -3027, -1460, -2911, + 11344, -2474, -1601, -1749, 3260, 2547, 3819, -1247, + -1449, 2835, -1118, -652, -516, -379, 531, 440, + -569, -2606, -2545, -2447, -1685, 8678, -1868, -2003, + -992, 5888, 8591, -1848, -2010, -2196, -2049, -658, + 3473, 214, 905, 317, -2050, -1083, -2593, 8754, + -2234, -2449, -1688, 2194, 2244, 2502, -1659, -2748, + 4584, -3011, 3702, -2307, -1887, -1960, -1068, 2889, + -3022, -2989, -2295, -2794, 3071, -1588, -43, 2627, + 1278, 2031, -2145, -2551, -2333, -3205, -3237, -2760, + 9082, -454, 4339, 1776, -2738, 4785, -2176, -1896, + 2148, 1350, 768, 249, 1001, 1499, 797, -2182, + -1443, -229, -32, 827, 401, 270, 581, 380, + -2370, -2376, -2679, -3099, -1742, -1149, 4666, -693, + 1109, 7547, -2496, -3063, -2818, -2621, -2016, 5722, + 4932, 1217, 2161, 2449, -2207, -2954, 3769, -2824, + -1809, -2946, -1693, -377, 1565, 4100, -2947, 3063, + -3062, -2919, -3093, -2520, -1712, 2383, 1305, 1867, + 10145, -2912, -3307, 7519, -3502, -1063, -2782, 8595, + -750, -1503, -3141, -2486, 2923, -2574, -1826, -1244, + 3537, 2494, 2583, 1560, -2722, 3284, 2245, -1258, + -658, -394, 483, 719, 1121, 1073, -2949, -1013, + -3048, 597, -3103, -2510, -1970, 7207, 8635, 1917, + -1772, -483, -2318, -1860, -2500, 2981, -1651, 550, + 696, 615, -2121, -2055, -1619, -2126, 3108, 3417, + -485, -47, 848, 1608, -2636, -1707, 3142, 3798, + 479, -1112, 597, -323, 1555, 1531, -2930, 2106, + -2398, -2314, -1835, 0, 2920, 896, 2356, 1259, + -2911, -3184, 593, -3570, -3389, -3263, 7340, 7640, + 6874, 6549, -1912, -1334, -1749, -568, -1718, -405, + -1375, 3456, -1024, -1903, 9384, -2721, -2485, -2377, + -3026, -899, -3133, -3032, -2452, 7715, 2492, -2450, + -1721, -2138, -1497, -55, 760, 2382, 1183, 1105, + -2782, 389, -1528, -927, 664, -531, 1405, 363, + 582, -292, -1678, -2718, -2763, -3140, -2799, -2178, + -2715, -2592, -972, -1226, 3278, -1173, 2916, -1548, + -446, -1241, -209, 379, 689, 538, 3110, 2857, + -1735, -1244, -589, -413, 65, 471, 522, 323, + -2043, -212, 1309, -471, -564, -16, 378, -320, + -437, 228, -2194, -2637, -2513, -2670, -1863, -954, + -2082, -2398, -2270, 5563, -2959, -2444, -2794, -1736, + -1631, -1324, 1482, -481, 2317, 1470, -2871, -2007, + 702, -1980, -491, -146, -695, -145, 2817, 1268, + -3395, -3456, -3069, -3433, -2874, -205, 806, 3038, + 3806, 2623, -2954, -1861, -712, 1017, -326, 44, + -93, 910, 775, 346, -2625, -2570, -2974, -2344, + -2712, -1930, -2213, 3521, -1341, 4327, -141, 835, + -1119, -1336, -1092, -1891, -860, -727, 315, 2562, + 4119, -2638, -2584, -1951, -2710, -2499, -1561, -952, + 2821, 2505, -2388, -1855, -2926, 1742, -2563, -2655, + -1802, 3082, 3063, 2456, -3304, -2670, -2147, -1504, + -309, 1421, 1661, 1546, 560, 615, -2590, -1593, + -1523, 2025, 3167, -841, -356, -648, 309, 1165 +}, + +.fcb08m = { + -2962, -2140, -2166, -1454, -1638, -1100, -835, 686, + 978, 550, -1630, -1021, -1424, -1867, -1118, -474, + 66, 6104, 904, 603, -829, -475, -1368, -1199, + 7255, -890, -465, 114, 118, 224, -2453, -1279, + 8192, -1289, -452, -47, 180, 324, 627, 209, + -2770, 11214, -857, -1720, -895, -531, -291, -264, + 232, -402, -2699, -2561, -2433, -2093, -1315, 86, + 2666, 1663, 1351, 2349, -2788, 4576, 3680, -1365, + -995, -513, 46, 44, 522, 142, -2739, -1654, + -1950, 4573, -659, -536, 285, 72, 875, 627, + 3142, 105, -941, 1245, -489, -495, -229, 44, + -236, -1083, -2336, -1193, -1620, -1859, -1339, -655, + 205, 1032, 5581, 1195, -2635, -1740, 2656, 1976, + -52, 784, -96, -165, 419, -486, 8850, -624, + -792, -1531, -765, -674, -730, -829, -150, -27, + 2255, -1177, 2727, -1430, 737, -902, -780, -729, + 169, 278, 3729, 3763, -32, -1581, -563, -573, + 77, -372, -64, -477, -2500, 526, -1682, 1464, + -830, -124, -548, 561, 202, 1115, -1682, -1552, + -2014, -2127, -1374, -749, -720, 64, 2097, 6944, + -2771, 4929, -1680, -2212, -1430, -801, 114, 891, + 1176, 855, 3571, -2187, -1566, -1694, 84, -46, + 932, 786, 765, 856, -1038, -498, -117, -1582, + -1379, -1162, 6293, -367, 594, 132, -2487, 2119, + -2153, -1749, 833, 1089, 507, 133, 337, 423, + -2777, 2507, 277, -1455, -1019, 1811, 639, -595, + 136, -1050, -2941, 4474, -176, 1095, 1113, -479, + 182, -295, -229, -605, -2035, -1649, -1171, 51, + 0, 125, 2844, -310, -82, -640, -2251, -2138, + -2270, -1567, 2260, 92, 368, 95, 1433, 1346, + 820, -2339, -1822, -895, -69, 158, 190, 911, + 1008, 764, 684, -1756, -1013, -1625, -1610, 6062, + -499, -1036, -139, 1129, 488, 524, -665, -870, + -347, -76, 123, 91, -12, 14, -2867, -2019, + 2858, -1903, -1165, 309, 287, 1250, 767, 776, + -2784, -2446, -1157, 460, 2589, 437, -285, 711, + -299, 402, -2683, -2271, -1714, -1535, -547, 4118, + 510, 1158, 700, 631, -2084, -1236, 509, -1009, + -510, -193, -1075, -793, 727, 2150, -2722, 968, + 1077, -1579, -1410, -894, 401, 1043, 427, 182 +}, + +.fcb08s = { + -2368, -2340, -1735, -1897, -1493, 984, 3062, 2826, + 1049, 164, 1181, -1990, -1833, -1720, -1360, 24, + 1485, 1923, 460, 511, 69, 78, -353, -3, + 3761, -480, -1538, -1063, 540, -64, -1546, -988, + 1514, -1167, -1354, -563, 1435, 880, 1123, 182, + -2243, -2109, -2378, -2201, -1491, -836, -124, 605, + 6159, 3636, -2770, -2959, -2956, -3019, -2154, -648, + 1805, 4698, 2929, 2078, -975, -360, -895, -623, + -593, -879, -345, 4333, 492, -56, -2102, -781, + -476, 1268, 606, -670, 1686, -105, 370, 461, + -221, -868, -1381, 297, 128, -578, -809, -938, + 3896, 490, 4032, 2675, -684, -1108, -1235, -915, + -874, -919, -802, -1040, -1324, -16, 2156, 1943, + -652, -666, -47, -1499, 168, -210, 4213, -1895, + -1734, -1767, -1412, -867, -71, 329, 855, 1294, + -1849, 4393, -1312, -1597, -564, 434, -454, 269, + 892, -31, -1170, 67, 370, -1144, -320, 3706, + -811, -190, -123, -166, -659, -1033, -789, -902, + -347, -280, -108, -313, 452, 3701, -1505, -2610, + -2758, -2550, -2034, -1361, -676, 713, 2263, 8286, + -2241, -2508, -2540, -1721, 182, 1947, 306, 1773, + 1220, 2909, -60, 73, -235, -1631, -1302, -692, + 4171, -830, 49, -188, -471, -2208, -2265, -1518, + -196, 2995, 2571, -579, -68, 805, -1294, 1274, + 4294, -1356, -702, -532, -465, -123, -400, -719, + 336, 3093, 1634, -906, -71, -502, -938, -982, + -742, -1187, -1757, 2890, -1591, 1303, 216, -311, + -404, -29, 501, -543, -1466, 1587, 309, -578, + -173, 34, 1116, 1286, -1184, -1174, -175, -732, + -619, 3508, -80, 191, -1059, -174, -429, -470, + 10000, -933, -1511, -1601, -1571, -1445, -1065, -1407, + -1053, -932, 1183, 7875, -460, -1609, -1618, -1398, + -1154, -1227, -1012, -1450, 20, 28, -235, -110, + 203, 105, 252, -154, -51, -58, 2940, -490, + 17, -51, 131, -106, -526, -566, -822, -1177, + -1335, 2749, 608, -1575, -1322, -1351, 111, 641, + 1441, -9, 733, -207, -273, -665, -630, -588, + -78, 254, 304, 762, -2661, -2677, -1238, -82, + 2569, 3001, 932, -1032, 211, -324, 40, 1395, + -836, -1119, -635, -1425, -1514, -1135, 1509, 2963 +}, + +.fcb11l = { + -3004, -2927, -2672, -2356, -735, 179, 950, 1734, + 1101, 1641, -1610, -1161, -1606, -179, -1634, 3383, + -610, 240, 73, 1128, 818, -1052, -1641, 724, + -1938, -1741, -1211, 3967, 1988, 1445, 3010, 2203, + -1685, -1698, -1838, -759, -144, 515, 999, 1215, + 3239, -1912, -2048, -1739, -1488, -148, 1590, 1370, + 1066, 1270, -2721, -1637, 99, -1964, 224, -946, + -1437, -954, 755, 1420, -2800, -2211, -2304, -2048, + 4853, -714, -383, 2159, 1823, 2328, -1619, -1584, + -1839, 5462, -1703, -802, -227, 485, 1017, 1695, + -2459, 2399, -1820, 2254, -1373, -767, 53, 705, + 1074, 1293, -1582, -2486, -2208, -2341, -2264, -2132, + -1578, -1043, 322, 7685, -2198, -1768, -2106, 16, + -2207, -1495, -1106, -961, -482, 1642, 6785, -1540, + -1540, -1449, -1177, -854, -307, 853, 1279, 1449, + 3253, -1427, 2314, -1473, -985, -1025, -321, 923, + 1140, 1166, -2704, 2664, -2444, -2717, 481, 3083, + -1449, 1225, 3168, 2389, -2124, -1981, -1342, -1939, + -1904, 4736, -885, -826, 3866, 2046, -290, -567, + -1986, -1880, 1966, -465, 1638, 683, 1005, 1099, + -2842, -2537, -2559, -2427, -1243, 4039, 1371, 3897, + 2529, 2400, -2586, -1328, 785, -1697, 1733, 2382, + -442, 190, 901, 1281, -2669, 2198, -1502, -1404, + 2593, -694, -186, 466, 1065, 1199, -1905, -1389, + 6171, -1817, -513, -989, -356, 246, 1619, 1883, + 36, -2178, -1602, 608, -1523, 23, 1265, 578, + 953, 1038, -483, -2278, -2138, -1740, 584, 244, + -54, -192, 915, 1097, -213, -1569, 1861, -1401, + 3686, -1625, -1234, -614, 860, 1311, -1397, 2315, + 1896, -1608, -1326, -1487, -99, 2241, 697, 1156, + 1711, -2099, -1507, -135, 1422, -695, -57, 1390, + 823, 937, -122, 479, 47, -2144, -1514, 955, + -1317, -726, 480, 1153, -2959, -2558, -2573, -1355, + -1879, -1446, 6435, 677, 3124, 3134, 1850, 1834, + -1396, -1417, 1290, -896, -561, 1428, 1007, 1105, + -2101, -2044, 1779, -1913, -1868, 1410, 916, 1232, + 1112, 1335, -2663, -104, -513, -96, -470, 480, + 1516, -150, 298, 714, -2558, 3076, 468, -745, + -945, -443, -849, -989, 341, 1102, 433, 588, + -1772, 462, -527, 670, -128, -108, 583, 701, + -2281, -2149, -2398, -2749, -2557, -1691, -1095, 1336, + 9088, 3844, -1799, -1861, -1908, -2242, -2184, 2313, + 3779, -809, 519, 2229, -1914, -1673, 1764, -634, + -1955, -1721, 405, -499, 243, 1632, -2377, 7289, + -1659, -1752, -1341, -948, -323, 841, 1703, 1774, + -2029, 2384, -1877, -1918, -1729, 1483, 483, 1916, + 576, 1258, -2310, -1796, 2208, -1579, 57, -1735, + -1161, 5177, 1674, 2468, -1907, -1499, 1868, 2275, + -620, -356, -228, 489, 1064, 849, -683, -1204, + -1761, -2211, -606, -764, -1056, 3888, 253, 1518, + -2555, -2075, 119, -1567, 971, -1178, 2683, 1476, + 978, 1419, -2947, -2418, -2164, 1178, 1582, 1470, + 896, 645, 1671, 1462, -2234, -1363, -1184, 1408, + 1042, -1091, -208, -49, 527, 917, 1266, -1444, + -2174, -2447, -2300, -1732, 3076, 5631, 248, 2195, + -2477, -1724, -2434, -2477, -2524, -1828, 2331, 845, + 1423, 1767, -2393, -1946, -857, -462, 344, 17, + -896, 2391, 892, 882, -828, -280, -752, -1136, + -1563, -1040, 1222, -1173, 1763, 1179, -1448, 1946, + -1815, -1588, -1638, -1282, 3302, 132, 509, 1408, + -2760, -2338, -1935, 1353, -1531, -1074, 1156, 3086, + 1374, 1667, 2302, -1623, -1897, -1991, -494, 2603, + -754, 524, 1265, 1304, 3062, -1359, -1365, 1987, + -1334, -916, -146, -40, 635, 1033, 1724, -1057, + 49, -1159, -774, 106, 1053, -153, 134, 691, + -119, -1226, 332, -363, -197, -69, -133, 573, + 190, 216, -2236, -294, 1288, -2110, -1537, -1005, + -1175, 56, 4227, 1623, -2440, -1894, -1623, -2377, + 2287, -1220, -1506, 177, 5689, 2849, -2857, -2166, + -2546, 2174, -2414, -2343, 559, -1020, 4650, 3514, + -2875, 1309, -2557, -2534, -2235, -1901, 1559, 4412, + 2301, 2204, -2969, -2018, -2399, -2834, -2431, 1316, + -1474, 1269, 2533, 3485, -2892, -2387, -2716, -2317, + -2031, -1992, -1311, 8071, 3933, 3807, -2139, 1909, + -2200, -2344, -2060, -1638, -1154, -210, 2781, 2139, + 1119, -1828, -2069, -2306, -1975, -1165, -444, 789, + 2409, 1551, -2929, -103, -1920, -2010, -904, 694, + -188, 4, 1051, 1190, -2649, -2454, -2205, -1651, + -1856, -1552, -1165, 352, 3351, 1266, -1719, 57, + -1828, -420, -938, -1251, -461, 1294, 1158, 893 +}, + +.fcb11m = { + -2704, -2459, -2349, -1535, 2807, 365, 1064, 892, + 830, 1222, -2190, -1542, -2285, 6443, -1607, -1362, + -605, 637, 883, 877, -2378, 2292, 3106, -1057, + 1776, -1094, -859, 249, 199, 256, -1537, 2098, + -1126, 2243, -1186, -193, -211, 211, 502, 308, + 3369, 3197, -1271, -1370, -355, -423, -537, 468, + -237, -99, -1439, -1748, -2185, -1972, -1357, -814, + -470, 815, 1306, 6390, 1983, -1169, -1749, -29, + -1368, 5929, -1539, -900, 576, 701, 1708, -1608, + -1148, 3522, -822, -120, -461, -158, -43, 39, + -2543, 8872, -1347, -1580, 222, -488, -162, 295, + 382, 291, 11143, -1223, -1270, -1399, -392, -563, + -500, -604, -544, -135, -1787, -1313, -1490, -1395, + -1100, -1278, -818, 6172, 768, 1597, -623, -681, + -1128, -1575, 7257, -665, -1021, -439, 932, 703, + -1496, -2168, -1945, -1454, -808, -1261, -354, 875, + 6706, 1956, -1773, -1503, -1536, -1162, -1386, -1885, + -1607, -318, -72, -7, -1932, -1349, 6150, -1852, + -345, -18, -81, 223, 339, 425, 362, -1623, + -1432, -1973, -1042, -1373, 7830, 38, -116, 1000, + 421, -2375, -1808, -1832, -1046, 2077, 955, 1576, + 581, 824, -2021, -1582, -1402, -1420, 69, 3549, + -513, 192, 262, 483, -2503, 4173, -11, -1532, + -893, 282, 187, 320, 176, 259, -2308, 2342, + -2385, -2147, -784, -375, 413, 833, 889, 1297, + 1415, -1085, -1009, -1501, -1246, -1298, 1553, 1384, + 332, 662, 2226, -2399, -1752, -857, 1899, 131, + 501, 209, 217, 346, 4294, -1811, -1694, -1080, + -752, -263, -228, 249, 628, 971, 2508, -1031, + 2871, -1054, 42, -202, -738, -170, -239, -290, + -2751, -2379, -2379, -1999, -1448, -380, 1594, 1279, + 1399, 1633, -2376, -1839, 1367, 1685, 356, -126, + -50, 143, 31, 33, 314, 160, -663, -687, + 25, 388, -267, -188, -188, -129, -2614, 1063, + -1835, -285, 2549, 205, -30, 370, 319, 297, + -87, -2208, -1164, -839, 894, -266, -410, 375, + 1263, 924, -2606, -2325, -1854, 1792, 407, 328, + -110, 575, 1090, 971, -2517, -1583, 1355, -1892, + -490, -203, 846, 724, 597, 779, -1650, -1281, + -1294, 549, -146, -548, 2947, -28, 265, 339 +}, + +.fcb11s = { + -1536, -2360, -2378, -2138, -1380, -346, 1575, 2779, + 3247, 1689, -340, -1788, -1839, 103, 31, 853, + -653, 3159, 365, 154, 404, -835, -716, -35, + 4309, -155, -1214, -1180, -750, -522, -753, 350, + -1660, -1603, -1159, -582, -489, 1067, 2615, 1747, + -1755, -2351, -2314, -1453, 922, 3458, 867, 439, + 493, 1212, -1584, -1655, 1300, 1783, 1641, 1442, + 816, -1283, -1456, -1417, 4998, 1923, -200, -1086, + -1060, -1016, -1074, -1217, -1285, -1245, 633, 390, + -1443, -1099, -507, 3041, 343, -163, -745, -667, + 2333, -2144, -2460, -2247, -2063, -1736, -742, 418, + 3124, 3504, 227, -735, 799, -1326, -20, -543, + 1900, 237, -671, -545, -1727, 121, -1750, 3700, + -485, -553, -77, -212, 942, 62, 1647, -688, + -1506, -1429, -619, -839, 172, 3209, -500, -371, + -1680, -1408, -1122, -563, 3627, -115, 510, 534, + -65, 199, 800, 5040, 631, -744, -612, -1023, + -1099, -1319, -1520, -1460, -1120, -274, -1220, 349, + 1848, -620, -1411, -616, 1771, 1024, -1223, -2195, + -2345, -2144, -1517, -1055, -385, 557, 1482, 6797, + -2274, 818, -460, -707, -274, 646, 654, 731, + 268, 347, 4583, -1289, -1452, -1193, -1072, -681, + -178, -131, -108, 547, -1521, -781, -1298, 239, + -486, -445, 3453, -226, 90, 653, -1237, 624, + 4692, -482, -798, -799, -766, -645, -890, -915, + 3748, -909, -1012, 85, 963, 375, -100, -1010, + -1269, -1508, 2106, -1194, 2632, 595, -826, -221, + -411, -1104, -1365, -1050, -2112, -863, 1943, -727, + -1079, -733, 78, 1990, 363, 953, 1325, 459, + -891, 3364, -410, -362, -547, -994, -1371, -1258, + 12270, -43, -1668, -1868, -2004, -2133, -1863, -1949, + -1805, -1288, -1640, 3783, -1414, -578, -505, -464, + -158, 252, 71, 76, 22, -20, -72, -13, + -19, -95, -14, 2, 23, -5, 1289, 630, + 291, -707, -794, -857, -715, -122, 551, 219, + -2358, -1905, -1397, 277, 572, 343, 789, 526, + 1629, 991, -980, 222, 740, 1199, 19, 1200, + -864, -467, -656, -138, 820, -2005, -924, 154, + 195, 393, 267, -183, 1024, 100, 1243, -872, + -705, -781, -422, -377, -910, -637, 89, 2849 +}, + +.fcb16l = { + -2676, -2246, -3119, -2904, -2707, -1946, 7718, 2292, + 2451, 4206, -1214, -362, 1116, -860, 30, -993, + -888, -1046, -3732, -2268, -2541, 6060, -2220, -1597, + -1650, -1320, 88, 1229, 2118, 2348, 1430, -1865, + -2190, -2122, -1844, -2069, -1746, 15, -1746, 1321, + -2671, -2993, -3247, -2811, -2141, -1360, 1886, 270, + -381, 5676, -2070, -444, -674, -1082, -1144, -346, + -823, 4630, -224, 1940, -2441, -2072, -2194, -295, + 2175, 1209, -734, 168, 923, 1359, -2667, 389, + -2585, -2279, -2195, -1141, -1016, -218, 109, 1926, + 5184, -2226, -1888, -1273, -1044, 25, 461, 886, + 1125, 1249, -2215, -2381, 3109, -1963, 3015, -2027, + -790, 1192, 1646, 2188, -2906, -2598, 484, -2372, + -1372, -1082, 1718, 664, 1391, 2396, -2518, 1937, + -2362, -2510, -1504, 2947, 446, 684, 1947, 2059, + -3263, -3001, -3240, -3034, -2598, 3367, 4407, 2327, + 2450, 2994, -2379, -1875, -1862, 6387, -1956, -1417, + -525, 1098, 1836, 2932, 1408, -1130, -1417, 1693, + -262, -645, -515, 443, 735, 619, -2834, -2246, + -2646, -2521, -811, 6608, -421, 1572, 2015, 3234, + -2086, -1435, 89, 1648, 838, -986, -1159, -1208, + -32, 1354, -2135, -2159, 7796, -2424, -949, -2040, + -1179, 228, 1187, 3008, -2963, -2500, -2074, -2025, + -1439, 1692, -378, -596, -62, 2419, -3522, -3132, + -2899, -3290, -2929, 2844, 49, 4307, 2754, 3897, + -2960, 1305, -1858, -831, -1379, -773, 3257, 979, + 975, 1513, -2849, -1610, 2483, 456, -1395, -634, + 847, 1320, 1116, 1175, 2497, -1554, 2176, -1697, + -997, -799, -120, 339, 996, 1379, 11359, -1557, + -2219, -2237, -1792, -2084, -1009, 781, 3341, 939, + 1954, -1860, -2347, -2117, -2000, -1394, 3825, 106, + 2595, 2162, -2938, -2488, -2112, 772, -1059, 1822, + 159, 1017, 2452, 1506, 1313, -2615, -2479, -2941, + -2220, -2510, -726, 4703, 1778, 3375, -3133, -2664, + -2821, -2771, 1559, -1000, -434, 1874, 4130, 2987, + -2998, -2692, -2326, 1580, -2231, -1347, 4166, 2021, + 1177, 2531, -2880, -2337, -2589, 1505, -2843, -2468, + -339, -1059, 3212, 4264, -3112, -2885, -2889, 975, + -2522, -2278, 721, 5057, 3989, 3373, -3098, -2947, + -1128, -2251, 1935, 2981, 3007, 975, 1983, 2048, + -2861, -2302, -2431, -1460, -1492, -1524, -944, 1556, + 1778, 1549, -2658, -2259, 2768, -2460, -1447, 2957, + 759, 324, 2533, 2477, -2935, -1687, -2554, -2647, + -1431, 118, -365, 10280, 1526, 3447, -2570, 2268, + -2351, -2115, 2588, -9, -834, 1115, 1878, 2365, + 79, 1132, -1619, -1406, -1568, -1766, -224, 825, + 2113, 1382, -548, -2669, -1797, -2691, -2139, -2495, + -210, 1276, 13623, 2315, 1965, -1713, -1610, -2187, + 2534, -1495, -1301, 622, 563, 2154, 2743, 3230, + -1784, -1774, -792, -493, -131, 156, 944, 1211, + -1886, 357, -1018, 225, -285, 1025, -134, 218, + 290, 153, 5869, -2407, -2856, -3051, -2540, -3238, + -2260, -370, -451, 6314, -500, -2554, -2110, -879, + -323, -537, 570, 1228, 1556, 1342, -2486, 3366, + 1838, -937, -959, -683, 63, 937, 652, 1212, + -2164, -1448, 166, -799, -550, -1317, 481, 299, + 5494, 1360, -3147, -2574, -989, 1550, 1952, -1502, + -96, 3517, 1304, 2311, -2931, -2146, -2174, -2052, + 579, 680, 896, 2697, 703, 1365, 4130, -2367, + -2627, -3125, -934, -3093, -2155, -955, 6025, 5024, + -3121, -3064, -2883, -2458, 1723, -842, 3032, 4391, + 2327, 2837, -2536, -2208, -1610, -2189, 6509, -1424, + -1116, 1427, 2830, 3370, 1084, -1562, -1655, -1628, + -491, 2260, -321, 421, 774, 1237, -3267, 977, + -3170, -3144, -2698, -1324, 1424, 3034, 3323, 3347, + -3021, -3061, 2027, -2345, 852, -2832, -1714, 5926, + 4517, 3839, -1490, -2416, -1726, -1268, -1458, -2137, + -1715, -580, 1403, 13408, -3005, -2706, -3063, -2745, + -2777, -2136, 2786, 202, 5141, 3407, -3104, -3001, + -3176, -3388, -3507, -2863, -2097, 2325, 2618, 6146, + -1997, -3152, -1036, -2694, -2587, -2986, -2750, -2219, + -1607, 5944, -2893, -2633, -2229, -2811, -2482, -2115, + -2219, -1180, 5246, 3252, -3111, -2052, -2693, -2934, + -1805, 2583, 353, 1262, 8588, 3900, -2468, -2726, + -1861, -2352, -2237, -2750, -2345, -1936, 9793, 8392, + -3490, -3124, -3596, -3630, -3154, -2390, 743, 6652, + 6366, 6143, -2852, -3547, -3124, -2718, -1094, -494, + 49, -1053, -3005, 32767, -1721, -1229, -1715, -1590, + 1587, -1233, 3384, -252, 312, 1120, -3287, -2926, + -3048, -2828, -2502, -1185, 2028, 3778, 487, 2083 +}, + +.fcb16m = { + 616, -1065, -1622, -1949, -1283, -863, 6819, 517, + 1135, 1282, 2631, -1447, -1477, -1004, 286, 1358, + -135, -340, 147, -130, 5435, -1609, -1916, -1758, + -1066, -1126, 478, 995, 1098, 1437, -1737, -1339, + -1864, -2009, -1038, -1004, -573, 810, 5974, 2840, + 349, -1559, -1496, -1151, -307, -82, 681, 827, + 550, 776, 1930, 166, -1100, -1489, -1185, -1182, + -1210, -326, 858, 1688, -2561, 3514, -736, 1555, + -59, -906, -123, 87, 102, 274, 1902, -459, + 3008, -984, -707, -334, -571, -317, -190, -371, + -2862, 607, 1346, -1517, -1220, -617, 2494, 697, + 190, 64, 3264, 3926, -1249, -1542, -933, -302, + -246, -248, 69, -283, -1766, -750, -1898, -1259, + 6841, -1546, -785, -64, 1208, 1294, -1522, -1742, + -1873, -1898, -1455, 7128, -752, 1718, 1398, 1123, + -2742, 4733, -1552, -2483, -2210, -495, 355, 864, + 830, 759, -2721, -2115, -1891, -1696, -1137, -1559, + -1265, -658, -591, 850, -699, 1262, -551, -1055, + 877, 96, -388, -192, -479, -1091, -2763, -1379, + 3290, 2331, -874, -307, -386, 615, 366, 133, + -2671, 5181, 4339, -894, -871, -634, -165, 409, + 91, -291, -2649, -411, 8039, -1947, -1156, 57, + 351, 1014, 472, -198, -1816, -590, 2887, -1702, + -1113, 3414, -556, 117, 483, -377, -1707, -1146, + -1155, 2518, 2014, -382, 3, -6, 206, -98, + 10770, 274, -1415, -1670, -1020, -1036, -786, -782, + -463, -552, -2500, 10460, -1624, -1787, -707, -1327, + -59, 375, 91, 22, -2776, -2343, -2104, 825, + -759, -823, 482, 1149, 1265, 570, -1676, -1826, + -1848, 6125, -1391, -820, -449, 844, 586, 535, + -2873, -2475, -2607, -2611, -1830, -487, 1643, 1680, + 2088, 2570, -2357, -993, 3189, -1473, 3506, -1203, + -793, 662, 464, 98, -2507, 1617, -1793, -1935, + -1307, -169, 9, 885, 728, 1178, -2010, -1346, + -1375, -187, -548, 2753, -464, -105, 799, 511, + -2170, -2428, -2177, -1497, 2072, 828, 441, 1020, + 873, 1000, -1297, -1531, -1863, -1967, -1516, -1088, + -758, -230, 1561, 6655, -2173, -1787, -1548, -1763, + -1366, -24, -645, 6836, 1480, 1923, -2728, -1859, + 1798, -2010, -1585, -677, -371, 1405, 1254, 1278 +}, + +.fcb16s = { + -2250, -2771, -2879, -2775, -2240, -1363, -272, 1233, + 6172, 5074, -2882, -2419, -2054, -2420, -1252, 347, + 1325, 1799, 1723, 4361, 774, 2066, 1874, 280, + -707, -605, -581, -662, -1104, -2038, 7111, -137, + -883, -1079, -1001, -54, -847, -1013, -1045, -832, + 4696, 3781, -624, -1485, -1360, -1359, -1307, -1219, + -866, -945, 5419, -1512, -2307, -2134, -2056, -1724, + -1653, -630, 157, 3399, -727, -860, -1381, -380, + -716, -1335, 3819, 78, -2, 277, -3185, -3118, + -2715, -3110, -1500, 1626, 3352, 3075, 1956, -539, + 16640, -1204, -2281, -2307, -2272, -2349, -2009, -2184, + -2777, -2375, -1015, 6208, -402, -1331, -1182, -763, + -730, -81, -591, -1184, -1927, 543, 4464, -1095, + -131, -542, -129, 486, -366, -1097, -1594, -554, + -15, -337, 3152, -723, 71, -40, 385, -309, + -769, 290, -853, -1058, -1196, -1557, -595, 3695, + 1129, 438, 1729, -1309, -971, -871, 90, 1418, + 1261, -23, -1382, -223, -1551, -713, -1044, 4495, + -160, -867, -1242, 1188, 159, 120, -1657, -951, + 1536, -159, -1310, 1101, -404, 155, 1717, -24, + -1607, 2347, 2056, -1943, -1313, -1297, -81, 34, + 1441, 354, -2110, -1873, -516, 1102, 2174, 2131, + 0, -946, -729, 61, 107, -14, -108, -50, + 42, -164, -177, -92, -29, 162, 1349, -2380, + -2099, -1692, -980, -49, -94, 331, 1317, 3819, + -482, -782, -775, -909, -640, -1099, -615, -225, + 1556, 2973, -630, 70, -186, -1599, -1076, 4440, + -890, 78, -76, -517, -855, -1886, -1521, -1206, + -1152, -900, 753, 1338, 1758, 2431, -2433, -1569, + -1294, -583, 552, 2040, -154, 250, 513, 2333, + -820, -1987, -2291, -2238, -1880, -1651, -1120, -262, + 2013, 9756, -2803, -2574, -2634, -2789, 356, -1838, + 325, 4584, 3584, 2486, -1524, 1874, -337, -1800, + -1659, 406, 2450, 1252, -245, -1030, 1985, -397, + -1565, -51, 148, 2039, -1212, -729, -700, -11, + 904, 649, 531, -2287, -1640, 766, -725, 171, + -1596, 1387, 3189, -672, -459, -794, -422, -714, + -195, -231, 185, 99, -952, -2248, -2170, -1190, + -457, 1458, 34, 1179, 2427, 1683, -1658, 3749, + -1816, -2000, 2823, -1243, -1415, 713, 875, 75 +}, + +.fcb22l_1 = { + 2198, -2215, -2251, -1966, -1540, -467, 403, 1647, + -2867, -2589, -34, -2314, -602, 2371, 2614, 2218, + -2494, 3659, 2708, -1076, -914, 233, 1149, 1425, + 319, -979, 1023, -682, 110, 239, 427, 703, + -2979, -2513, -2649, -2265, 7420, 526, 2174, 2932, + -2868, -2056, -2232, 1651, -1325, -856, -218, 2091, + 458, 1508, -1208, -845, 244, -441, 558, 752, + -700, -1370, -395, 980, -321, -232, -241, 293, + 10391, -1792, -1948, -1518, -1049, 43, 1524, 2033, + -2434, 303, 1730, -1205, -1432, -1183, -694, 1185, + -2531, -2656, -2751, -1756, -1321, -1100, 287, 8605, + -2868, -2554, 721, -2065, -1671, -771, 675, 2223, + -2690, -2501, -2313, 1829, 3189, 45, 1825, 2024, + -3153, -2824, -2729, -2308, 1686, -370, 482, 2606, + -2972, -2324, 2492, -1762, -1662, 28, 4976, 3214, + -2769, -316, -1146, -1954, 86, -60, -370, 1144, + 5519, -1785, -1538, -1044, -580, -89, 704, 1151, + -2586, -1094, 7473, -1220, -1076, -50, 1029, 1850, + 3546, 3279, -1806, -1191, -528, 682, 1160, 1341, + -2852, 1541, -2358, -1841, -2317, -1351, 993, 2417, + -2675, 2482, -2061, -2089, 3681, 626, 1619, 1818, + -2916, 2821, -2482, -2166, -1084, 1137, 5537, 2864, + -2499, -1782, 2156, 2558, -1117, 127, 1147, 1556, + -2572, 3865, -2008, -1805, -679, 119, 35, 1319, + -2704, -1872, -1756, 6843, -911, 322, 1641, 2461, + -2652, -1957, 1972, -1582, 3082, 84, 1086, 1487, + -2983, -2325, -2780, -2532, -1858, -279, 10092, 4519, + -2364, 2718, -1907, 2678, -1005, 246, 1499, 1679, + -2570, 8779, -2004, -1627, -844, 89, 1712, 2145, + 3316, -1763, -1642, 2819, -599, 9, 906, 1401, + -2289, -2224, 2462, -1580, -843, 2501, -24, 1310, + 3091, -1745, 2398, -1264, -731, 113, 831, 1328, + -2803, -2380, -2808, -2379, -2290, -1376, -234, 2242, + 3537, -2137, -2050, -1260, 2881, 177, 1158, 1424, + -3303, -3123, -3130, -2861, -2075, 2528, -43, 3890, + -3106, -2672, -2554, 1833, -826, 55, 4910, 3324, + 3993, -2176, -2446, -1848, -786, 3346, 1590, 2034, + -2725, -265, 303, 1076, -1985, 3661, 1556, 1983, + -3182, -2712, -2988, -2841, -1332, 4816, 6422, 4184, + -2230, -1248, -2176, -1806, -1617, -878, 3764, 1309, + -2280, 509, -211, 426, 773, 99, 513, 628, + 167, 196, -2256, -1802, -1157, 724, 1405, 1383, + 2384, -409, -672, -453, -205, -89, -12, 240, + 114, -2220, -807, -1302, -1612, -405, 1134, 1381, + 699, -1816, -2151, -1883, 2975, 928, 1527, 1565, + 775, -2141, -1981, -1532, -591, 3338, 683, 1763, + 466, -2028, -2086, 1448, -622, 589, 1294, 1150, + 145, -2382, -1093, -367, 986, 323, 404, 931, + -371, -2868, -2737, -2103, 129, 771, 1498, 1974, + -1481, -1060, -2398, -1125, 285, 2777, 2975, 1431, + -2720, 1748, -2375, -1847, -912, 3829, 808, 2034, + -2492, -2447, -1248, -991, 1449, 1304, 867, 1171, + -2999, -2556, -2763, -2298, 3359, 4277, 1991, 2850, + -2692, -2640, -2593, 1813, -458, 3068, 1012, 2049, + -3258, -2820, -2845, -2395, 2787, -45, 5457, 3568, + -2491, -2114, -1884, 6, -332, -232, 1680, 1139, + 2032, -2383, -2183, -1725, -914, 192, 4175, 2059, + -2922, -2972, -2920, -2210, -1143, 1850, 2468, 1871, + -3138, -99, -2651, -2510, -129, 631, 1677, 1925, + -3302, -3124, -3214, -3143, -2616, -761, 3978, 4234, + -1698, -824, -1975, -742, 2449, -610, 21, 998, + -3047, -2697, -2747, -1919, -1545, 7534, 1243, 3548, + -1863, -1257, 339, -1027, 122, -613, 1989, 953, + -2232, -1759, -1751, -969, -1591, 1917, -325, 889 +}, + +.fcb22m_1 = { + 13531, -1278, -2217, -1956, -1360, -892, -650, -866, + -255, 192, -1139, -1242, -2101, -1682, -1601, 2950, + 2340, 121, 662, 446, -2636, 1711, 615, -1864, + -1297, -1098, -296, 1070, 1284, 891, 7332, -2292, + -2334, -1889, -1170, 1884, -570, 52, 1146, 944, + -2083, -2192, -2420, -2165, -1542, -1474, -278, 4147, + 1506, 1666, 1014, -1657, -2225, -2261, 8568, -1445, + -523, -115, 999, 602, -2762, -2261, 271, -1797, + -1633, -790, 391, 907, 1302, 1076, -1907, -2219, + -2443, -1963, -1495, -1294, 4722, 935, 1691, 1370, + -2355, -1585, -2510, -2297, 2690, -1491, -647, 360, + 1460, 1479, -2041, 368, 10454, -1277, -716, -172, + -538, -287, 169, -232, 960, -1087, -2459, -2196, + -1189, -1967, -1586, -783, 5275, 2811, -1523, -1733, + -2373, -1946, -1586, -1280, -442, -205, 2330, 6319, + -2483, -2115, -2645, -2016, -1464, 89, 529, 1338, + 5291, 3186, 5770, -2311, -2696, -2420, -619, -2322, + 8434, -129, 1661, 1232, -1377, -1277, -1193, 406, + -1332, -1246, -999, -497, 1024, 1500, -2791, -1417, + -2173, 2419, -1492, -734, 2795, 559, 750, 519, + -2714, -509, 4622, 3679, -294, 73, -805, 602, + -99, 94, -2658, -1984, 6907, -1780, -1244, 272, + 874, 140, 1326, 693, -2679, -2274, -2551, 13351, + -2619, 4570, -1739, 2309, 1280, 1235, -1011, -2084, + -1968, -1404, 2568, 3147, -336, 270, 499, 506, + -1567, -2240, -2685, -1951, -2254, 2783, -1411, 8878, + 2321, 1691, -2567, -2450, -2572, -2286, -2038, -1803, + -1316, -315, 464, 1223, -1988, -927, -2035, 2165, + 3663, -919, -328, 229, -2, 217, -2773, -2160, + -2637, -2183, 5081, -1434, 1526, 2830, 1698, 1153, + -2810, -1132, 5408, -1992, 4267, -1357, 809, 563, + 9, -64, -2949, 7061, 4604, -1424, -1839, -610, + -251, 370, 901, 147, -2264, 3135, 3241, -1102, + -397, -1292, 39, 17, 380, 383, -1483, -1458, + 820, 2135, -646, -479, 173, 23, -274, -442, + -978, -1216, -1928, 7260, -1249, -956, -24, 250, + 438, 128, 4080, 152, 2677, -587, -667, -672, + -662, -492, -722, -688, -1907, -787, 3101, -1404, + -1234, -508, 3817, 424, 657, -86, -2179, -599, + 2141, -1446, -1847, 4341, -801, -26, -57, 216, + -1625, -802, 1752, -1301, 2617, -1545, -513, -401, + 234, 658, 1299, -1279, 874, -1408, -1135, -40, + -423, 394, 660, 684, 3341, -937, -1842, -1177, + 1945, -621, 19, -93, 141, -59, -2626, 3368, + -1588, -1959, -1506, 3729, -347, 218, 497, 585, + -2495, -2452, -2118, 578, -225, 378, 40, 1080, + 908, 761, -2070, -1607, 2534, -1535, 1493, 2664, + 215, 634, 317, -233, 4188, -1446, -2129, -1812, + -1428, -1579, -1038, 97, 989, 2038, 3671, -2707, + -2608, -2198, -1119, 1601, 1042, 1325, 1230, 1149, + -2566, -1054, 3659, -2173, -1772, -713, -1080, -101, + 987, 805, -1555, -749, -1510, 3443, -1402, 4172, + -696, 437, 276, 219, -2735, -2453, -2082, 3898, + -867, -582, -726, 1134, 1227, 1121, 2333, -963, + -1474, 2386, -959, -327, -138, 4, 268, 479, + -2889, -2896, -2701, -1975, -593, 1212, 1511, 1087, + 1482, 1612, -1703, 4874, 46, -1364, -1342, -544, + -879, -455, -488, -396, -2616, 849, -2424, -1976, + -1491, -739, 325, 1284, 1831, 1223, -48, -1457, + -2123, -1318, 1617, -1064, 2484, -467, 533, 707, + 351, 422, -525, -657, 202, -476, 133, -679, + -945, -832, 1906, -2981, -2605, -1911, -2541, 11553, + -1585, 1555, 2196, 1616, -2669, -2345, -2423, -1848, + -1756, 4918, -711, 1186, 1873, 1399, -672, -1401, + -1524, -1138, -674, 1285, 195, 884, -377, -1067, + -2125, 377, -1747, -1604, 837, -334, -115, -59, + 160, 483, -2220, 12861, -1633, -1616, -926, -1203, + -113, -90, 378, 148, 5740, 88, -2246, -1598, + -1546, -1694, 2790, -72, 590, 28, -2608, 4312, + -1068, 3091, -632, -651, 366, 63, 744, 375, + 1746, 2753, -2075, -1621, -1033, -471, 972, 199, + 575, 655, -2148, 2407, -2180, -1764, -1030, -1089, + 4083, -80, 417, 384, 1196, -2284, -2549, -1771, + -773, 213, 1188, 788, 1343, 1358, -2584, 7723, + -2171, -2301, -1497, -438, 1001, 110, 671, 939, + 6435, 5777, -1765, -1287, -1181, -1014, 87, -919, + -422, -444, -1930, 4906, -1660, -1558, 3617, -1177, + 261, 9, 261, -47, -2539, 2749, -2476, -2298, + -1047, -1319, -341, -604, 2111, 2779, -2935, 5011, + -1860, -2363, -1686, -1033, 800, 1774, 1700, 1478 +}, + +.fcb22s_1 = { + 11523, -796, -1488, -1897, -1888, -1691, -1767, -1794, + -1622, -1210, -2284, -2777, -2382, -1371, -238, 2997, + 3182, 588, 1129, 704, 248, 1703, -264, -1306, + -1147, -560, -1513, -956, 1667, 1340, 5220, -2276, + -2215, -2049, -1479, -1294, -774, 66, 1270, 2075, + -1435, -1981, -2322, -1896, -1321, -462, 138, 5022, + 2549, 1683, -100, -1744, -1528, -423, 6093, -61, + -288, -623, -650, -828, -1521, 134, 1240, -1399, + -1450, 612, -969, 2585, 945, -312, -1138, -2488, + -2513, -1988, -1607, -773, 3384, 1192, 2651, 2580, + -984, -2015, -1465, -1576, 2273, -1221, 91, 2615, + 840, 1299, -1069, -2151, -1899, -735, 440, 888, + -241, 502, 953, 3613, 1806, -1855, -2303, -1758, + -1318, -1484, -10, 597, 3723, 1992, -488, -2063, + -2284, -2172, -1905, -1547, -937, -18, 3276, 7184, + -1942, -2302, -2399, -1972, -1378, -635, 302, 1081, + 5454, 3358, -447, -807, 205, -1805, -1546, -446, + 6364, -916, 151, -377, -582, -856, -204, -731, + -884, -674, -257, -67, 1564, 2486, 1003, -1508, + -1692, 1515, -889, -622, 2366, 9, -17, -245, + 3733, -1057, -284, 3197, -31, -440, -1115, -1609, + -1834, -1930, 230, 262, 7344, -39, -1746, -562, + -1554, -1838, -1648, -1310, 2157, 80, -102, 238, + -823, -622, -720, -115, -274, 16, -1562, -1785, + -1535, -334, 2604, 3388, -410, -103, -348, -142, + 1676, -441, -2267, -1988, -1421, -680, 1302, 2682, + 383, -10, 1487, -1086, -251, -1134, 141, -84, + -1003, -898, 95, 2304, 802, -1549, -1562, 2650, + 2180, 64, -512, -832, -705, -429, 1826, -2283, + -1976, -1277, 2699, 504, 249, -9, 178, -33, + -1357, -1138, 3005, 293, 229, 1633, -197, -540, + -1245, -1617, -1269, 6639, 2437, -647, -1501, -1097, + -1051, -1150, -1183, -1461, 71, 1529, 2847, 1149, + -705, -1345, -1605, -629, -617, -60, -2081, -1435, + 938, 844, -1055, -841, 1179, 392, 1112, 946, + -1252, -1728, -266, 7063, -1335, -920, -1048, 206, + 48, -619, 4764, 274, 2394, -799, -798, -1003, + -1278, -1800, -1626, -1415, -498, 1439, 1643, -1978, + -1258, -1136, 1285, -9, 596, 141, -2211, 908, + 802, -470, -1125, 3216, -234, -412, 3, -980, + 15, -1047, 1530, 660, 1986, -480, -499, -550, + -733, -531, 1326, -1607, 787, -1136, -1002, -65, + 358, 743, 253, -294, 3498, -1033, -1270, -790, + 537, 1788, 309, -72, -1241, -1999, 609, 2981, + -1025, -1642, -958, 3845, -1221, -962, -965, -1612, + -1993, -33, -1136, 1086, -46, 1178, -229, 139, + 644, 718, -1696, 2411, 1019, -1056, 52, 224, + -487, -395, -40, 125, 3001, -1955, -1950, -784, + -1111, 897, -514, 159, 785, 1095, 2944, -2554, + -2407, -1975, -632, 1030, 1712, 366, 463, 125, + -2354, -796, 5663, -1055, -1151, -870, 348, -676, + 1447, 215, -1005, -1531, -910, 2249, -438, 2889, + 107, -404, -271, -534, -1022, -2117, -1738, 2261, + -257, -788, 32, 1747, 1196, 910, 33, 1, + -23, 28, -25, 19, 13, -29, -23, -48, + -907, -2113, -1978, -1426, -535, 1589, 1908, 2724, + 1646, -897, 758, 2326, 674, -1449, 111, 220, + 475, -162, -1465, -2036, -528, 1308, -2087, -2031, + -1308, 183, 35, 1097, 1008, 1864, -2116, -2303, + -1928, -261, 2342, -292, 1480, 268, 1582, 1079, + -1183, -1154, -777, 309, 1218, 683, 1314, 1677, + -758, -1745, 1422, -1331, -1638, -1100, -303, 5003, + -57, -379, -511, -756, -727, -2315, -1860, -1775, + -676, 3854, -67, -52, 2018, 1532, -160, -197, + -75, -1934, -1134, 2025, 1810, -491, 83, 646, + 390, -297, -441, -342, -479, -486, -296, -30, + 443, 1151, 3508, 6119, -493, -1427, -1393, -1273, + -1280, -1687, -1683, -1511, 5109, -1008, -1137, -638, + -649, -342, -590, -478, -577, -349, -579, 2548, + -463, 2107, -568, -678, -788, -454, -608, -452, + 1934, 1485, -1746, -1007, -1174, -573, 239, -119, + 679, -76, -1687, 1956, -898, -477, 456, -156, + 1460, 13, 92, -987, 554, -2772, -2578, -1694, + -235, 753, 1527, 1106, 1539, 1342, -1305, 6560, + -1526, -1765, -793, -600, 248, -542, -63, -421, + 4828, 1288, -1580, -1826, -1163, -1014, -221, -818, + -109, -61, 1265, 1939, -1265, -414, 1912, -190, + -1157, -675, -756, -935, 2529, 136, -1709, -1727, + -1819, -1504, -1232, -959, 1128, 4142, -1945, 2958, + -900, -1432, -1720, -1380, 381, 1473, 1235, 1062 +}, + +.fcb22l_2 = { + 2441, -2086, -2129, -2146, -1839, -1035, 295, 2465, + -2785, -2597, -81, -2162, -991, 3060, 3056, 2985, + -2415, 4009, 3058, -1165, -1281, -322, 629, 2232, + 481, -2255, 1165, -1455, -621, -29, 923, 1371, + -2822, -2421, -2596, -1908, 6338, 279, 1845, 3532, + -2955, -2571, -2554, 744, -1785, -909, 775, 3156, + 738, 1760, -458, -590, -73, 22, -91, 326, + -1098, -1511, -1000, 1741, -1024, -562, -399, 736, + 9669, -2109, -1872, -1539, -1208, -265, 994, 2364, + -2121, -98, 1523, -1427, -1450, -1157, -294, 1375, + -3007, -2669, -2847, -1777, -1196, -1257, 1065, 9128, + -2948, -2509, 470, -2521, -1947, -728, 503, 3810, + -2538, -2469, -2217, 1957, 2580, -229, 1212, 2263, + -3174, -2660, -2792, -2692, 1226, -512, 555, 3960, + -2979, -2426, 1978, -2182, -1868, -455, 4681, 4580, + -2514, -1642, -1029, -1712, 416, -838, -362, 1208, + 5211, -2128, -1867, -1337, -549, -70, 828, 1508, + -2272, -1611, 7307, -1612, -1244, -461, 749, 2510, + 3669, 3236, -1845, -1333, -866, 268, 850, 1686, + -2805, 1079, -2258, -2075, -2017, -1115, 214, 2735, + -2719, 2676, -2154, -1976, 2884, 393, 1247, 2382, + -3043, 2188, -2703, -2353, -1861, -208, 4419, 4511, + -2187, -1630, 2246, 2331, -1105, -198, 818, 1721, + -2180, 3571, -1841, -1738, -1020, 14, 407, 1028, + -2536, -2171, -2115, 6630, -968, -306, 1438, 3574, + -2411, -1857, 1911, -1546, 2709, 57, 910, 1727, + -3159, -2565, -2675, -2746, -2017, -534, 8461, 6103, + -2299, 2912, -1851, 2660, -1479, -97, 1148, 2204, + -2510, 8781, -2194, -1790, -1114, -110, 1140, 2885, + 3261, -1921, -1633, 2766, -788, -403, 610, 1651, + -2515, -2021, 2415, -1606, -1149, 2479, 297, 1693, + 3823, -1538, 2514, -1261, -904, -236, 550, 1581, + -2903, -2440, -2922, -2749, -2480, -1849, -423, 3613, + 3420, -1876, -1929, -1537, 2955, 58, 1014, 1950, + -3295, -3009, -3161, -2926, -2353, 2355, 351, 5502, + -3140, -2745, -2781, 1247, -1037, 538, 4939, 4382, + 3584, -2284, -2321, -1844, -743, 3156, 1546, 2358, + -562, -101, -497, -1196, -1023, 1972, 1255, 1374, + -3146, -2824, -3057, -2757, -1736, 3746, 5609, 5118, + -2155, -1665, -1701, -1780, -1975, -1127, 3185, 2036, + -2540, 324, -481, 311, 624, 719, 543, 1030, + 550, 513, -2430, -1817, -1129, 62, 1526, 1809, + 2172, -1314, -1035, -586, -292, 233, 209, 543, + -252, -2372, -1961, -1629, -1306, -408, 451, 1339, + 792, -2619, -2316, -1624, 1941, 678, 977, 1710, + 428, -2499, -2369, -2101, -1448, 2988, 874, 2497, + 451, -2263, -2204, 1403, -631, 694, 1424, 1658, + -243, -2104, -378, 355, 1446, 373, 377, 973, + -756, -2802, -2508, -2081, 177, 352, 2428, 2359, + -1533, -2710, -2544, -1102, 419, 3132, 1222, 1942, + -2756, 1844, -2429, -1854, -1283, 3960, 1633, 2917, + -2858, -2784, -2106, -1025, 1588, 905, 1092, 1657, + -3028, -2715, -2782, -2218, 2852, 4006, 2534, 3726, + -2783, -2355, -2146, 2113, -1201, 3361, 1178, 2670, + -3199, -2796, -2682, -2489, 1905, -471, 5097, 4436, + -2197, -1078, -2327, 420, -637, 10, 1647, 1362, + 1815, -2519, -2363, -2174, -1454, -31, 4125, 3446, + -3054, -2953, -2738, -2328, -1636, 1086, 2238, 2132, + -3089, -432, -2674, -2515, -168, 745, 2236, 2305, + -3214, -2953, -3159, -3086, -2748, -1200, 3346, 5127, + -1150, -501, -2109, -1662, 2301, -401, 651, 1320, + -3072, -2608, -2833, -2249, -1387, 7704, 1811, 4960, + -2474, -2589, 83, -499, -785, 194, 1312, 1442, + -2716, -1663, -2088, -1812, -1396, 1862, -369, 1397 +}, + +.fcb22m_2 = { + 8809, -2291, -2452, -1982, -1356, -423, 419, 588, + 897, 1086, 79, -2155, -1957, 367, 1080, 233, + 718, 441, 515, 642, 730, 2454, 774, -2299, + -1526, -784, -359, 96, 385, 482, 4905, -2501, + -2431, -2047, -1139, 131, 743, 999, 1243, 1294, + -2154, -433, -2461, -2201, -1552, -163, -200, 4009, + 1731, 1652, -2381, 5295, -1457, -895, 3480, -1230, + -94, 471, 554, 669, -2458, -1271, 278, -2238, + -1852, -813, 888, 1032, 801, 1008, -258, -538, + -1744, -2087, -1651, -1239, 2222, -4, 783, 882, + 478, 782, -1335, -1453, 1728, -627, -387, -205, + 221, 193, -2282, -518, 7464, -1808, -1134, -199, + 340, 321, 410, 617, 2278, -436, -2082, -1958, + -1493, -885, 628, 794, 855, 989, 232, -1115, + -2617, -2152, -1290, -1299, -458, 222, 3936, 3349, + -2240, -2787, -2689, -2255, -1241, 816, 2307, 1566, + 1685, 1723, 2960, -2134, -2532, -1798, -1128, -1073, + 5380, 1013, 1525, 1415, -1976, 456, -538, -1433, + -1347, 22, -496, 284, 387, 465, -2214, -1863, + -2261, 1049, -1487, -1222, 1610, 621, 1000, 1116, + -2393, -731, 4075, 2375, -1178, -908, -383, 327, + 543, 572, -2071, -2039, 3310, -1903, -1502, -72, + 123, 693, 721, 918, -1866, -1251, -1065, 5630, + -1574, -541, 1, 1014, 813, 887, -2145, -2421, + -2176, -1756, 1856, 408, -1, 759, 1109, 1276, + 3053, -2705, -2467, -2068, -1160, 1405, 459, 1167, + 1219, 1318, -2198, -2037, -2005, -2204, -2039, -1473, + -1529, 264, 1333, 1822, -2121, -1434, -472, 1901, + 2448, -589, -424, 248, 376, 602, -1571, -1032, + -1243, -1619, 5682, -1162, 362, 570, 865, 852, + -1875, -805, 4258, -1569, 2992, -1175, 51, 164, + 314, 648, -2083, 5574, 2553, -1866, -1156, -642, + -198, 330, 446, 602, -2365, 1601, 2873, -2043, + -1510, -1142, -20, 588, 535, 676, -2207, -1637, + 626, 745, -1548, -590, 745, 540, 505, 618, + 749, -1389, 857, 1387, -398, -606, -75, -86, + 11, 78, 3322, -1347, 1978, -1431, -745, -280, + -42, 135, 350, 376, -508, -1349, 2961, -1184, + -647, -1257, 3009, -374, 523, 616, -1848, -41, + 2652, -1609, -1603, 3284, -24, 502, 122, 448, + -2337, -1029, 734, -1533, 1523, -1312, -754, 335, + 510, 774, 769, -117, 139, -1254, -1468, -965, + -375, 2, 227, 518, 3187, -1524, -776, -1253, + 2977, -530, 319, -61, 244, 413, -2290, 3085, + -1763, -1480, -1374, 3272, -87, 323, 421, 652, + -2317, -2182, -1604, -1, -801, 1320, -156, 907, + 799, 918, -1494, -2205, 1137, 69, 1249, 3437, + 925, 29, 419, 448, 3574, -1564, -1713, 2374, + -941, -252, 123, 263, 366, 539, 1059, -1856, + -1753, 766, -1704, 106, 262, 596, 684, 820, + -2503, -1878, 1835, -594, -1024, -2105, -1567, 488, + 794, 883, -1626, -613, -1410, 2846, -1413, 3557, + -348, 460, 332, 577, -907, 700, -1680, 1130, + -1637, -793, -160, -38, 473, 630, 1487, 1872, + -1526, 1379, -806, 121, -383, 149, 259, 413, + 759, -2817, -2758, -2290, -1348, 460, 1782, 1536, + 1513, 1503, -2265, 3193, 117, -1704, -1367, -487, + 125, 365, 594, 651, -2287, 1272, -2537, -2038, + -1515, -578, 2994, 582, 941, 1058, -1556, -1583, + -720, -1584, 956, -1032, 1861, 146, 402, 429, + -2184, 1667, 1241, 289, 52, -232, -265, 210, + 248, 331, 1133, -1813, -1869, -1429, -1484, 5620, + -400, 1316, 1146, 1150, -1975, -818, -1921, -2054, + -1768, 2953, -544, 426, 856, 1107, 493, -2019, + 176, -1915, -1040, 717, -91, 728, 647, 776, + -2360, 739, -2136, 30, 636, -447, -116, 498, + 531, 775, -2250, 8607, -2075, -1928, -1072, -450, + 38, 439, 558, 778, 4484, 1056, -1830, -1716, + -988, -412, 260, 56, 425, 579, -2243, 4094, + -1267, 2172, -990, -562, 97, 304, 533, 609, + 790, 780, -2029, -1947, -1327, 1224, 255, 344, + 516, 660, -591, 1702, -118, -1402, 396, -1387, + 2268, -247, 177, 355, 1393, -2318, -1975, -1563, + 863, -939, -365, 411, 800, 1019, -2370, 4656, + -2301, -2111, -1679, -698, 458, 788, 1004, 1138, + 2285, 4924, -1940, -1955, -1159, -436, 237, 5, + 300, 364, -2492, 2165, -2021, -2072, 1504, -612, + -93, 249, 676, 799, -2411, 1952, -1752, -2418, + -2285, -1323, -621, 837, 1043, 1266, 76, 3160, + -2176, -2176, -1717, -1105, 1045, 410, 728, 940 +}, + +.fcb22s_2 = { + 6946, -1850, -1986, -1590, -1276, -1063, -1026, -1017, + -805, -346, 9, -2911, -2843, -1899, -198, 2193, + 3325, 1315, 37, -528, -371, 599, -751, -2157, + -1912, -855, 988, 1222, 1085, 953, 3212, -2793, + -2564, -1707, -657, 683, 1109, 683, 647, 446, + -1906, -2315, -2569, -2428, -1698, -600, 1100, 3790, + 3368, 2172, 2017, -895, -1354, -734, 2552, -403, + -68, -402, -752, -932, -1205, -1937, 572, -1434, + -500, -579, 291, 1723, 1312, 1695, -238, -1715, + -2029, -1525, -816, -363, 2816, 167, 2196, 1793, + 897, -1081, -262, -1338, 1052, -1231, -94, 1296, + 503, 184, 588, -2057, -911, -1933, -1769, 167, + 1013, 1774, 1414, 1289, 2406, -1906, -2055, -1952, + -1726, -1618, -451, 575, 3021, 2569, -776, -1649, + -2111, -1930, -1499, -1349, -595, 329, 3090, 5458, + -1954, -1309, -1554, -1159, -1132, 329, 714, 760, + 2529, 2417, 1046, -1025, -1114, -1325, -154, -1501, + 4160, -696, 230, 398, -2010, 385, -1344, 36, + -1269, -987, 1009, 1453, 1163, 1591, 916, -1534, + -508, 221, -1596, -1130, 1394, 539, 676, 676, + 1263, 2029, 284, 1592, 161, -124, -572, -1362, + -1946, -2148, -1488, -222, 4967, -1202, -939, -375, + -80, -593, -445, -418, -781, -1560, 31, 4757, + -1417, -954, -402, 193, -316, -278, -926, -895, + -1024, -436, 2673, 1991, 254, 28, -861, -1291, + 1475, -2708, -2689, -2118, -703, 290, 1841, 2048, + 1213, 594, 132, -2598, -2427, -988, -1111, -158, + 478, 2118, 2571, 830, -1430, -678, -773, 1340, + 2473, -798, -751, 215, 274, -65, 335, -1947, + -1796, -1436, 3862, -611, 105, -31, 775, 669, + 1439, -1266, 1670, -739, -1259, -572, -17, -107, + 176, 130, 3899, 3478, -548, -1429, -1176, -1104, + -1147, -1503, -1277, -1068, -258, 2645, 1753, -333, + -827, -1306, -827, -502, -306, -119, -1602, -1644, + 1922, 1127, -628, -1073, 348, 195, 616, 685, + 1750, -898, -1852, 1813, -700, 254, 598, -234, + -433, -1035, 2502, 94, 467, -1672, -905, 776, + 679, -11, -1071, -1845, -1083, -320, 690, 110, + -708, -1077, 2514, 70, -412, -300, -371, -717, + 1700, -1625, -1346, 1954, 14, -64, -121, 181, + -673, -909, 2274, -1389, 2058, -1503, 306, -187, + -209, -69, 1523, -632, -695, -1283, -988, -569, + -798, -521, 398, 2834, 1953, -2215, -1626, 106, + 6, -498, -57, 173, 731, 1002, -1706, 1701, + -328, -1745, -1398, 2176, -19, 311, 492, 667, + -1073, -1803, -1684, 703, -1316, 1803, 659, 913, + 906, 1033, -1982, -102, 945, -1620, 718, 555, + 613, 38, 394, 421, 2738, -1159, -2248, -1852, + -1568, 33, 363, 1490, 935, 561, 1464, -2466, + -1209, -1204, -692, 2009, 129, 354, 372, 380, + -2053, 1122, 2272, -824, -1355, -926, -122, 567, + 526, 923, -1320, 59, -226, 1674, -1512, 1498, + -631, 221, 26, -247, -40, -1615, -1597, 2111, + 34, -813, 200, 219, 758, 1000, 306, 394, + -430, -117, -409, -81, -207, 16, 36, 176, + -1737, -2898, -3005, -2214, -568, 2140, 4132, 2592, + 504, -521, -1509, 3610, 1070, -1890, -1319, -11, + 174, -148, -212, -347, -464, -1068, -2568, -2532, + -1973, -519, 2104, 3713, 1882, -145, -1319, -2375, + -1862, -843, 2061, -266, 1465, 866, 912, 1183, + -1784, 2072, 205, -375, 1112, -374, -534, -430, + -162, -204, 375, 82, -823, -1148, -752, 4681, + -339, -247, -790, -1088, -494, -2302, -2310, -1603, + 46, 3367, -50, 393, 1383, 1457, -1377, -2005, + 643, 326, 312, 1189, -225, 563, 261, -70, + -667, -1191, -2255, -470, 1000, 142, -525, 2285, + 756, 2061, -953, 5888, -1339, -1534, -1252, -16, + -116, -305, -375, -596, 3611, -889, -511, 43, + -809, -659, -737, -510, -258, -108, -1515, 2806, + -1555, 1025, -932, -601, 146, 164, 207, 71, + 1606, 93, -2420, -2311, -1641, -244, 1785, 804, + 1040, 427, -1510, 38, -2490, -1987, 44, 699, + 1407, 988, 1061, 411, 1162, -1382, -2669, -1635, + -905, 1503, 674, 1357, 869, 244, 411, 2612, + -1792, -2147, -1693, 1434, 281, 38, 228, 424, + 2291, 1354, -2128, -1377, -1014, -609, 131, -151, + 418, 602, 111, 2200, -1547, -1153, 1435, -1282, + 6, -111, -1, 92, 238, 613, -2271, -1181, + -1455, -919, -182, 1066, 1932, 1679, -1715, 2825, + -1764, -1759, -741, -829, 501, 746, 1056, 1416 +}, + +.fcb44l = { + 4868, -1851, -2031, -2019, -1751, -552, 756, 929, + 1389, 1590, -2090, -1202, -1317, 516, -1798, -1020, + -694, 4322, 1388, 1904, -2605, -1239, 1005, -757, + -1248, -358, 699, -201, 409, 1093, -2901, -2254, + -2605, -2595, -2104, -1681, 6854, 2692, 3155, 3446, + -2535, -1421, -1745, 898, -2046, -1457, -1044, -269, + 1748, 1873, -2268, -1098, 407, -1865, -2103, 1510, + -1217, -399, 1718, 2017, 3638, -1685, -1547, -1480, + 1637, -744, 580, 586, 1313, 1409, 617, -2020, + -1919, -2179, 932, -937, 559, 1795, 1528, 1596, + -2867, -2553, -2507, -2653, -2365, -1985, -170, 8679, + 4271, 4273, 2263, -1835, -1934, -1719, -1778, 2357, + 125, 1319, 1543, 1765, 3689, -1215, 2369, -1533, + -1611, -771, -123, 1005, 1297, 1465, -2491, 2631, + -1636, -1655, 1244, -1178, 386, 961, 1300, 1553, + -2357, -2404, -2305, -2177, -1714, -383, -98, 258, + 3902, 2475, -2923, -2580, -2685, -2803, -2678, -2428, + -1247, 450, 8174, 5035, -2302, -1629, -1495, 1832, + 1616, -577, 639, 872, 1122, 1437, 785, -1947, + -1976, 823, -1909, -1005, 430, 1244, 1713, 1664, + -2537, 8025, -1705, -2005, -2030, -1155, 64, 1106, + 1975, 2277, -2410, -2639, -2292, -1858, 162, 744, + 555, 1559, 1719, 1806, -2282, -1982, -1914, 1415, + -1785, 2197, 254, 763, 1338, 1741, -2509, -1991, + -2328, -1853, -2299, 5145, -34, 1495, 2913, 3018, + -2009, -1736, 2411, -1595, 1877, -1316, 693, 1042, + 1565, 1744, -2657, -2161, -2222, -2135, 4454, -1784, + 1331, 3208, 2852, 2955, 3738, -1338, -1425, 2090, + -1601, -279, -2, 712, 1220, 1436, -2385, -1265, + 7093, -1561, -1742, -1003, 283, 1009, 1843, 2055, + -2251, -2175, 2310, -1321, -1976, 1874, 164, 2781, + 2721, 2487, 2519, -1101, -1539, -1575, -1487, -724, + -25, 355, 643, 1011, -2296, -1799, -1895, -1700, + 2743, -924, -254, 32, 1504, 1910, -2811, 898, + -2363, -2518, -2408, -1737, -936, 221, 2588, 2527, + -2535, -2360, -2477, -1861, -1882, 1833, 3587, 1307, + 2141, 2274, -433, -1994, -1692, -1318, -1398, -350, + 1518, 1923, 835, 1262, -2246, 3383, 2458, -1464, + -1874, -983, -157, 531, 1490, 1729, 9543, -1713, + -2011, -2015, -1870, -969, -34, 1160, 1724, 1919, + -2530, 140, -1923, -1730, -1720, -605, 629, 1577, + 974, 1373, -2268, -1582, -933, 1124, -1624, -514, + 4156, -118, 1515, 1907, -2267, -574, -1311, -954, + -47, -1259, 15, 364, 854, 1009, -2221, 629, + 994, -1646, -1324, -1509, 2359, 3453, 1393, 1912, + 3586, -2286, -2537, -2560, -2415, -1748, -368, 3093, + 2881, 2611, -2556, 2792, -1558, 1117, -1681, -65, + -36, 516, 1233, 1514, 531, -1814, 998, -1795, + -1693, -871, 725, 868, 1504, 1465, 907, 300, + -2060, -2366, -2392, -1881, -596, 1754, 2169, 2104, + -2755, 2709, -2298, -2627, -2423, -1875, -733, 3886, + 2648, 2821, 623, -541, -163, -319, 85, 84, + 15, 716, 511, 572, 3948, 2773, -1504, -1746, + -1832, -934, -78, 988, 1277, 1518, -2678, 2216, + -2162, -2331, -2076, -968, 3445, 1070, 2077, 2206, + -2892, -2425, -2674, -2905, -2844, -2584, -1381, 3269, + 2696, 3281, -2090, -369, -1515, -1367, -200, 2089, + 739, 700, 866, 1169, -2276, -1057, 2851, 2589, + -1686, -515, -65, 579, 1278, 1593, -2837, -2458, + -2565, -2783, -2843, -2468, -1704, -1531, 1475, 4153, + -2209, -1857, -1873, -2177, 758, -1531, 3207, 1163, + 1506, 1851, -2383, -1683, -1839, 5772, -1815, -465, + 361, 1086, 1912, 2140, -2629, -1688, 1608, -2190, + -2419, -2064, -1253, 1397, 2099, 2306, 513, 1664, + -1683, -1629, -1682, -109, 269, 695, 1072, 1317, + 208, -1602, -1918, -1038, -813, 312, 24, 26, + 761, 990, -2288, -2225, -1948, -1932, -1832, -949, + -450, 920, 805, 1468, -2897, -2633, -2557, 464, + -2174, -1157, 1170, 2230, 2550, 2522, -2643, -1928, + -2255, -2578, 82, -2206, -63, 2663, 2007, 2292, + 226, -2541, -2687, -2753, -2229, -1556, 785, 3837, + 2331, 2492, -2496, -1740, -2465, -2295, -2151, 1142, + 363, 3967, 1943, 2432, -2619, -2400, 520, -2274, + -1900, -1486, 2135, 1407, 2300, 2288, -2811, -3066, + -3128, -3098, -2529, -1475, 2172, 3413, 3613, 3571, + 564, -2347, -2257, -2377, -1944, -1771, -582, 509, + 1683, 1975, -285, -2136, -2529, -2464, -2117, 278, + 1094, 1042, 2192, 1976, 1781, -1874, -2042, -2103, + -1744, -1044, 3373, 1252, 1861, 1873, -2688, -1849, + -2462, -2494, -2105, -1903, 2221, 250, 1653, 2233 +}, + +.fcb44m = { + 13151, -1763, -2583, -2518, -2181, -1036, -537, -112, + 214, 590, -608, -2270, -2228, -1301, -1018, 3687, + -471, -282, 909, 1665, -2426, 1713, -808, -1240, + -1366, -976, -140, 1730, 683, 191, 7253, -2076, + -2733, -2698, -2253, -1116, 376, 687, 1314, 1532, + -820, -1471, -2092, -2047, -1796, -1347, -732, 6348, + 2529, 1441, -1460, -1845, -1046, -1643, 8086, -928, + 90, 660, 428, -188, 604, -2022, 556, -1680, + -1641, -902, 834, 941, 1480, 1906, -2439, -2573, + -3091, -2853, -2419, -1606, 2312, 2624, 2659, 2659, + -1286, -2273, -2400, -1826, 2443, -1391, 685, 1822, + 1810, 1625, -1993, -731, 9737, -1476, -1183, -1244, + 34, -85, 0, 201, 4171, -2430, -2869, -2866, + -2488, -1154, -1253, 282, 2715, 3643, -2130, -2522, + -3259, -3051, -2977, -2204, -1264, 1103, 7113, 7948, + -1271, -1694, -2011, -1294, -1607, 247, -303, 715, + 4276, 1908, -2337, -2111, -2232, -2123, -1648, -1302, + 7686, 1213, 982, 984, -2594, -2127, -1981, -2104, + -2405, -1966, -936, -95, 326, 672, -2263, -893, + -1367, 1288, -1321, -1351, 2503, 747, 390, -247, + -2220, -860, 3641, 3766, -1724, -1487, -531, 239, + 134, -82, -2563, -1537, 3883, -1911, -2109, -1713, + 1056, 726, 977, 1091, -1874, -1366, -1628, 11069, + -1653, -696, 118, -78, 337, 29, 2449, -1438, + -601, -1533, -816, 1262, 540, 79, -460, -1403, + 3204, -1918, -1892, -1911, -1468, -976, -42, 2785, + 1088, 564, -236, -2267, -2324, -2130, -1880, -427, + -258, -543, 903, 5142, -1791, -1611, -1073, 2911, + 2993, -1295, -400, 229, 192, -85, 4461, -1711, + -1431, -1640, 3525, -1398, -101, -219, 327, 415, + -669, -1520, 6595, -1291, 5123, 155, -480, -518, + -552, -890, -2609, 7074, 3220, -1054, -1852, -1165, + -25, 89, -361, -140, -1610, 2214, 2903, -1737, + -1704, -1178, -708, -171, 177, 674, -1075, -890, + 82, 463, -1432, -1048, -703, -759, -247, 344, + 2448, -656, -1135, 4366, -583, -705, 40, -314, + -676, -1271, 4389, -952, 3249, -1606, -1524, -1172, + -490, 97, 128, -91, -66, -1293, 1696, -1114, + -1455, -519, 2620, 479, -257, -1512, -2037, -1281, + 1752, -1285, -1812, 2789, -52, 676, 409, 296, + -1977, -1043, 270, -1615, 2131, -1051, -161, -498, + 767, 1673, 1044, 27, -1107, -1730, -1856, -1264, + -275, -167, 893, 443, 3850, 97, -1244, -1691, + -1566, -1088, -1062, -837, -159, 1830, -1424, 2494, + -1878, -1532, -1991, 2919, 62, 399, 524, 381, + -1340, -2415, -2028, 218, -1342, 410, 815, 533, + 948, 1998, -1213, -1847, 3691, -2123, 1822, -1548, + 537, 987, 356, 123, 3876, -2476, -2021, -2195, + -1562, -737, 2250, 709, 797, 1102, 2065, -2258, + -2394, -1816, -1536, 1059, 4653, 1457, 456, -27, + -2226, -736, 765, -1879, -2188, -1793, -928, 892, + 1793, 2257, -1182, -1646, -1789, 6105, -1936, 4316, + -307, -143, 223, 236, -2213, -1862, -1823, 3326, + -1810, -1384, -453, 1007, 1331, 1405, 4135, -2298, + -1657, 1981, -1702, -853, -318, 298, 760, 1025, + -2537, -2782, -2985, -2687, -2839, 4493, -448, 4249, + 3048, 2678, 1045, 3227, -690, -1390, -976, -652, + 587, 194, -749, -1358, -730, 250, -2404, -2548, + -2157, -1027, 32, 2091, 1059, 1360, 262, -2135, + -2061, -1777, -1614, -246, 2004, 2605, 1516, -948, + -1060, -1076, -1643, -748, 144, 1595, 1730, 531, + -1086, -2182, -483, -2191, -2411, -1983, -2345, 10051, + -841, 1456, 924, 207, 4652, -1831, -2026, -1710, + -2235, 4036, -755, -70, 533, 887, -1899, -2326, + -2129, -2115, -1606, 1443, 2557, 941, 618, 527, + 949, -1547, -2067, -1785, 455, -60, 79, 202, + 912, 954, -2527, 14551, -1893, -2315, -2609, -1844, + 497, 287, -197, 626, 6839, -804, -1299, -1259, + -1109, -97, 976, 144, -343, -1375, -2334, 3740, + -1049, 2980, -1739, -474, 223, 137, 155, -171, + 2962, 1814, -2378, -2643, -2249, -1109, 858, 643, + 1630, 1399, -2098, 974, -1718, -2193, -2146, -1488, + 3353, -147, 1187, 1266, 1559, -2532, -2941, -2759, + -2101, -1098, 1562, 1049, 2045, 2159, -2298, 7439, + -2129, -2361, -2318, -1552, -422, 482, 985, 1111, + 6050, 5657, -1698, -2267, -2127, -1135, -140, -286, + -352, -124, -1230, 3492, -1370, -1221, 2958, -1239, + -472, -722, -169, -89, -2310, 2988, -2367, -2421, + -2589, -2034, -662, 421, 1863, 2736, -2612, 5429, + -2104, -2257, -2440, -1817, 4819, 883, 622, 636 +}, + +.fcb44s = { + 11239, -328, -2011, -1713, -1662, -1290, -1225, -1520, + -1541, -912, 400, -1103, -2698, -162, 263, -964, + 668, 405, 732, 2493, -2491, 1000, -2910, -793, + -1351, -515, 1051, 2002, 1757, 2150, -2010, -2021, + -2254, -1896, -1953, 664, 7067, 2632, 531, -1367, + -2228, 2113, -2019, 2309, -1458, -426, 1242, 338, + 205, -222, -1317, -1806, -2477, -2427, -2477, -1852, + -1472, -911, 2261, 10280, -2369, 382, 3180, -1210, + -1601, -748, -732, 504, 1440, 1142, -13, 610, + -2457, -739, -1318, -1013, -52, -470, 627, 4734, + 1248, 2947, -631, 1560, 2096, -833, -1173, -1475, + -2060, -2189, 967, -1451, -1544, -758, -538, -31, + 1395, 3550, -3, -1999, -1975, -1734, -2680, -2512, + -2037, -1306, -252, 1288, 6012, 4834, -1087, 3259, + 3115, -1369, -1136, -948, -264, -582, -677, -643, + -2500, 1284, -317, -1872, -1150, -1150, 310, 832, + 1597, 2842, 6295, 3806, -671, -1536, -1460, -1256, + -1223, -1504, -1672, -1471, 1358, 1004, -1893, 1114, + -1643, -103, -513, 189, 303, 140, -1618, -648, + -720, 7274, 573, -180, -731, -1226, -1564, -1742, + 151, 2103, -1562, -974, 94, 546, 3536, -205, + -1657, -2534, -2187, 2840, -1248, 451, 2615, 171, + 479, -305, -1299, -1708, -2144, -1593, -1289, 2766, + 2287, -400, 188, -51, 141, 105, -2128, 4976, + -1690, -1216, -1175, 297, 1454, 449, -478, -970, + -1914, -1459, 3036, 2668, -950, -634, -507, -374, + 4, 34, -1664, 2901, 847, 2817, -1154, -1651, + -1262, -1160, -624, 629, 1578, 765, -2002, -2121, + -1527, 1938, -272, 113, 287, 955, -1473, 60, + 8047, 137, -534, -841, -1077, -1504, -1788, -1758, + -1871, 119, 931, 1775, -704, 2792, 354, -501, + -1370, -2038, -1031, -1631, -1914, -879, 377, 7589, + 173, -196, -491, -1658, 3790, -773, -1731, 3028, + 49, -1013, -563, -1232, -953, -730, -2568, -1926, + -679, -267, -324, -962, 51, 461, 2728, 3631, + 3533, -1690, -2846, -2370, -1945, -917, -551, 276, + 2634, 3558, -2592, -1750, -2422, -1586, -1204, -1001, + 4603, 1802, 2673, 1685, 2710, -853, -2321, -1919, + -1603, -868, 3706, 290, 570, 338, -2245, -1704, + -1915, 545, -787, 1635, 1725, 526, 666, 1604, + 642, -1154, 3231, -1232, -1772, -623, 217, 27, + 3, 641, -2411, 1924, -967, -1583, -1499, 2316, + 1354, -115, 333, 559, -1721, 2475, -1942, -2114, + -1196, -571, 1769, 2350, 1315, -607, 4510, -1414, + -2228, -1312, 1439, 469, -248, -399, -270, -721, + -1517, -1247, -771, -36, 6488, 942, -279, -572, + -1041, -1908, -2388, -2281, -2595, -2275, -1529, 51, + 471, 4435, 3002, 2738, 4049, 1562, -2706, -1672, + -1649, -1204, -518, -280, 774, 1344, 6, -1950, + -1521, -1768, -972, 1420, 3011, -191, 644, 1478, + 3220, -313, 3030, -153, -841, -739, -378, -1013, + -1410, -1815, -2104, -1033, -2097, -1992, -943, 2391, + 424, 369, 1601, 3331, 1494, -2060, -2027, 1579, + -1407, 1120, -280, -197, 761, 1048, -710, 4094, + -1533, -1984, -1620, -1132, -515, -485, 971, 2644, + 3979, -661, -1891, -1120, -897, 2484, 1623, 21, + -1534, -2438, 3201, -1510, 858, -1459, -711, -1332, + -833, -240, 763, 1096, -1435, -29, 3174, -1773, + -19, 708, 1680, 403, -910, -2224, -2670, -619, + 1320, -751, -1323, -1022, 2875, 1080, 985, 1, + 191, 7823, -475, -604, -1126, -967, -1139, -1600, + -1767, -1161, -1342, -1960, -2112, -1793, -1596, 3103, + 535, 2001, 3235, 151, -2266, -807, -1977, -1661, + -1255, 2328, 2632, 3189, 621, -1130, -2183, -1127, + 2391, -884, 2173, -690, -354, -516, 352, 954, + 1847, -74, -1260, -1839, 2557, -1221, 228, -630, + -162, 386, 1462, -1889, -2596, -2216, -1869, -518, + 1281, 2329, 2653, 1117, -1535, -1038, -1752, -1862, + -1635, -1067, 994, 5212, 2719, -264, -2021, 1824, + -2110, -619, 1538, -397, -332, -153, 860, 1281, + 6568, -1790, -2459, -1707, -1708, -799, 294, 89, + 475, 992, -1668, -1819, -2010, -1623, 2079, 3255, + -388, 591, 1477, 581, -1544, 476, -1825, -959, + -1296, -1037, -453, 1146, 4693, 839, 2027, 3021, + -1731, -1746, -1964, -1115, 1197, 102, 164, -162, + -2301, -1281, -2022, 3983, -1122, -281, 85, 352, + 1042, 1599, 6463, -93, -2010, -1988, -2282, -2189, + -1915, -1721, 17, 4694, 424, -998, -111, -1995, + -1246, -1176, 78, -116, 1951, 3059, -1974, -1783, + -2243, -1238, 3935, -928, -15, 1265, 1536, 1907 +}, + +.shape08 = { + 5279, 1101, 12974, 5624, 2029, 3853, 5918, 1516, + -2905, -224, -92, -819, 803, 1091, 3091, -3355, + 152, -1214, -7317, -738, -8973, 546, 12035, -937, + 2216, 2113, 1214, -6577, 2006, -1661, -673, -5880, + 496, 454, 3400, 676, -322, 11388, 634, -1169, + 12556, -5804, -7724, 588, -6801, 1080, 354, -1681, + -942, 1926, -487, -580, 156, 79, 15253, 667, + 1155, 655, -719, 1999, -785, 214, 2822, 1020, + -1967, 73, -387, -137, -15225, -1552, -357, 2830, + 2140, 3070, -2552, 2410, 1230, 4131, 999, 248, + 531, -909, 3948, 12858, -8056, 2205, -2837, -171, + -1633, -129, -93, 1852, -1920, 157, 9647, -84, + -150, -1365, -1522, -13197, 6168, -3195, 5890, -1724, + -6407, -1340, -7435, -621, -5732, -2895, 145, 3974, + 728, 9840, -494, 7357, -394, -13614, -256, -1930, + 468, -266, 8001, -153, -365, 7652, 135, 1400, + -3869, 1091, -4935, -2884, 1259, 6819, 1025, -6667, + 1079, -9794, 6827, -4166, 1108, 1149, 18861, 593, + -177, -1067, -644, -2164, 4727, 85, -101, -10805, + -247, 8918, 2261, 5475, 756, 3018, -6535, 1941, + 359, -4229, 1206, 958, -878, 554, -18780, 2289, + 4906, -7412, -7685, 7932, 965, 2460, 4423, -563, + -3668, -3482, 3307, -1737, 971, -7480, 10742, 1978, + 2365, 20, -3625, 466, 2056, -6602, 9396, 3145, + 3162, 1857, -630, -6905, 1660, -3024, -2159, 1109, + 1282, 2767, 210, -2203, 3099, -7889, 1805, -13115, + 988, -6235, 1566, -1399, -9612, 1821, -519, -57, + 3428, -14024, 1141, -2542, -9396, -17, 440, -8591, + 2271, -7811, 1891, -935, -4330, -1303, 362, 426, + 319, 1176, 3176, 2202, -14308, -619, -2942, -2271, + -531, -652, 345, 17681, 1453, -1561, 341, -2077, + 933, 433, 1529, 463, -1095, 4912, -840, 16266, + 973, 1732, -718, 6702, -3659, 4037, -704, -2707, + 1423, 1291, 2300, 149, -933, -1338, 2019, 6173, + 481, 14937, -364, 3896, -443, 992, -896, 378, + -226, -1505, 268, -428, -2622, -289, -2069, 10472, + -3880, -5330, 385, 3053, -4642, 1525, -1557, 716, + 2504, 848, -450, -2018, -458, -705, -7120, -543, + -2138, 2548, -351, 737, 12906, -1012, 63, 15357, + 332, -837, -225, -1299, 2843, 1334, -669, 2083, + -707, 1171, 8219, 2190, 10567, 1370, -1376, -2919, + 2108, 10098, -388, 4442, 164, 490, 7580, 26, + -1848, -2919, 640, 4758, -108, 8194, -1325, -2314, + 447, 5178, -1095, 9902, -693, -3624, -223, 690, + 10495, 776, -919, -1621, 2046, 469, 1454, 3681, + -1090, -1776, 1457, 212, 2054, -994, 698, -496, + 22347, -623, 254, 960, -4073, 531, -2572, -14393, + -1022, 258, -3667, 994, 15242, 5078, -3618, 1925, + -1229, -1754, 1715, 4358, 1286, -2360, -4590, 1824, + 7864, 1423, -2146, -2763, -10635, 474, -829, 1159, + -157, -54, -158, -29, 202, -383, 285, -2, + 862, -364, 415, -123, -145, -9733, 1167, 10199, + -1408, -2992, 2131, -412, 4743, 2992, 3555, -617, + 9606, -2831, 2357, 5300, 625, -678, -500, -128, + -56, -6327, -1122, -2567, 1904, -1804, 709, 3194, + -148, -1371, -6534, -1748, -1490, 14159, 1466, 1395, + 1101, -2725, 503, 68, -1486, 0, 211, -1218, + -3, 20920, 1709, -208, -839, 4574, -6084, -6557, + -103, -984, -375, 8409, 1715, -2170, -5003, -3296, + 13482, 1211, -4159, 3496, 1040, 6925, 213, -1398, + 441, -1231, -814, 842, 1574, 1145, 1359, 437, + -1777, 20566, 259, -4573, -1412, -158, 10144, 1269, + 1405, -12631, -1104, -615, -15892, 355, -3795, -1158, + 3241, 252, 232, -179, -617, -2038, 285, -1014, + -1248, 1835, -1558, 1266, -10207, 629, -312, 11376, + 154, -288, 5915, -353, 60, 2695, -853, -103, + 15659, 2403, -1184, 3, 9236, -10953, 4434, 829, + 2563, -164, -848, -646, 7247, 895, 1726, -752, + -979, 1053, -971, 318, 2180, 927, 804, -262, + 446, 3261, -4926, -4523, 1247, 2039, 12770, -1191, + -1310, -5574, 4763, 657, -4139, 10821, -805, -1109, + -3189, -1721, 167, -10022, -1877, 2123, 328, -7048, + -2130, 2431, 1522, 3209, -8448, 1810, -5412, 9815, + -3677, 6575, -6237, -929, -434, -2375, -13586, 3497, + -1140, 1227, -6354, -507, 329, -1690, 1079, -880, + -3743, -4021, -4645, -6053, 958, 4594, -1122, -11628, + 1537, -3418, -1242, 133, -9335, 1611, -432, 10733, + -885, -468, -13466, 690, 214, 8968, 3441, 5451, + -219, 5492, -377, 409, 3812, 2450, 508, 6542, + 3824, -3705, -514, -8262, 1537, 7969, 946, -2869, + 8762, 417, 5094, 2104, 6694, -342, 1259, -4779, + -1445, -1519, 333, 4385, 652, -386, -580, -1892, + -873, 1862, 2704, 13837, -5415, -1975, 5881, 7150, + 8272, -6412, 704, 1854, 257, -3746, -9789, -9634, + -924, 1393, -3237, 259, -56, 4390, 4902, 1172, + 5114, -2616, -4409, -1180, 4691, 7400, -625, 8873, + 6846, -1224, -213, -5296, -3504, -147, 17828, -1347, + 3251, 1702, 1440, -2364, -491, -227, 1765, -446, + -9746, -2019, 11287, -195, -9559, -312, 888, 5789, + -1753, -11069, 2537, -265, -1762, -779, -8501, -308, + -89, 1973, 3640, 17344, 1326, -689, -398, -3820, + 2167, 229, -636, 2142, -6587, -751, 13243, 465, + -5946, -202, -968, -1060, -240, -10626, 3405, 1302, + -1263, 972, 11351, 100, 2266, -930, -2108, 5350, + -3186, 11130, 2073, -5616, 650, 2000, 1048, 5628, + -531, 674, 8453, 1030, 1152, 12095, 352, 409, + -1029, -1236, -190, -5724, -589, 3550, 1958, -14081, + -339, 1672, -1659, 4518, -75, -638, 5501, 277, + -578, -2185, 157, 2066, 8634, -2403, 1617, -12487, + -1881, 8273, 179, -2152, -1294, -512, -415, 456, + -141, -125, -405, 132, 49, -1978, -19085, -451, + -1480, 324, -5397, 235, -1217, 346, -1258, 3540, + 10075, 10291, 5060, -2057, 6156, -992, 9344, -3718, + 4296, 895, -8464, 341, 1426, 648, 1494, 2895, + -3760, 10139, 15531, -984, -1550, -1319, -1542, -119, + -517, -185, -3368, -9279, -3455, -4257, 1092, -10120, + 5072, 3099, 986, -2562, -12068, 1932, 6489, 950, + -2417, 1362, -567, 591, -715, -515, 3506, -726, + 6319, 214, -364, 3611, 1895, -2005, -273, 1513, + 2379, 475, -4855, -527, -11493, 27, 4343, -2394, + -639, -744, -2601, 10917, 1910, 2449, 1238, -2175, + 5322, -4054, -40, 4274, 684, 8152, 966, 10882, + -13, 4253, -287, -3192, 548, 2020, 189, -6894, + 797, 2160, 579, 4084, 1767, -4011, -640, 7697, + 791, 945, 1230, 6491, 1508, -3762, -433, 11340, + -129, -1131, -5121, 3148, 1544, -7648, 1866, 9660, + 2365, -2110, 782, -82, 3666, -701, 303, 298, + -1934, -125, -1427, -17589, -1188, 175, -7046, -488, + 1121, -6594, 489, -1551, 14349, 1499, -544, 17132, + 198, 2516, 2479, -978, -214, -3399, -1223, 2094, + 130, -1020, 1049, -710, 12801, -498, 297, -1365, + -187, -3169, -123, 9019, 958, 221, 14234, -590, + 961, 3092, 8, 255, -4586, 1789, 2522, -12577, + -91, -822, -805, -714, 5298, 1299, 3306, -1288, + 13176, 235, 1754, -67, 1912, -604, 3240, -2048, + -200, 772, -173, -996, 1368, 2380, 294, 763, + 19665, -196, 528, 182, -2394, 923, 749, -13578, + 855, 589, -9553, 0, 5737, 10399, 9147, -1655, + -3735, 1246, -2429, -1147, -2199, -2953, 614, -1404, + -449, -8524, -2271, 5001, -9517, 2940, -204, 3625, + -258, 32, 1521, -299, -1786, -2836, 1523, 2427, + -835, 3139, -197, 3351, -279, -14766, -1267, 5169, + -1039, -10967, 58, 641, -767, -1193, -591, -716, + -834, 8109, -915, -711, -10427, -1680, -638, 2643, + -850, -258, 10452, 362, -5394, -349, -14727, -655, + 1040, 1722, -10265, 551, -283, 9888, 408, -400, + 5980, 1878, 781, -923, -667, -789, -348, 624, + -260, 14515, -804, 1721, -2, 5356, 1802, 1218, + 498, 1871, -988, 16295, 4163, -2342, -4290, 3121, + 3269, 112, -3492, 1124, -1496, 1863, -1426, -1090, + 1598, -197, 1160, -1660, -1094, 477, -4104, -396, + 1605, 26134, 746, -12876, 2320, -1690, 8626, 39, + 1341, -1254, -1890, 2555, -13996, -1218, 3827, 1216, + -909, -180, 1720, -87, -143, 989, 340, -1426, + -4029, 3141, -9424, 466, -8227, 422, -7379, 2038, + 401, 98, 3602, -1223, -946, 2469, 1159, 727, + -268, 467, 203, -11079, 3850, -3469, -1965, -1857, + -1415, -2477, 3173, 7352, 9483, -5541, 6212, 1886, + -3868, 2728, 577, -5057, 321, 972, -77, 47, + 227, -38, -1037, -222, -347, -341, 1179, -948, + 592, -7485, 2218, -5955, 2698, 11798, 197, 6260, + 1711, 998, 8, -6223, -1184, 1145, -1781, 1376, + 1394, 388, -689, 2279, 6511, 2542, -4903, 3917, + -790, 535, -1903, -4448, 4216, -22, -6715, 5204, + 4807, 3193, -1064, 5403, 4503, -2434, -4296, 1383, + -1514, -4103, 747, 3928, 2987, 9513, 2492, -8691, + -993, -2667, -40, -170, -3116, 611, 2367, 16297, + -1256, -1404, -3462, 466, -524, 5464, 491, 706, + -7491, 2027, 373, -4086, 1620, -7789, 704, 5002, + 1706, 8325, -851, -9883, -3072, 4475, 2696, -8549 +}, + +.shape11 = { + 44, -10592, -832, -413, 612, 530, 379, 753, + 1442, -3006, -858, -1077, -12018, -196, -771, -1142, + -628, -2938, -439, -3323, 20, 12513, -2462, -1270, + -57, -8417, -690, 790, 276, 2349, -341, -1644, + 230, -2176, -202, -14725, 170, 1725, 3030, 683, + -231, 641, -242, -3252, 110, -1440, 2886, -1467, + -1155, 14395, 297, 52, 240, 3938, 9880, -7555, + -1214, 3351, 129, -1269, -168, 669, 13765, -1289, + -465, 10017, -632, -328, -276, -33, 31, 18883, + -148, -131, 525, 1669, 2288, -203, 868, -660, + 248, -409, -91, 295, -9174, -1484, 929, 2824, + 1097, -3205, -113, 2712, -1544, 527, 1419, -963, + -388, 691, -16791, -84, 72, -3802, -357, 1633, +-15182, 62, -6024, -742, -5396, 4470, -198, 1, + 1428, -1691, 18715, 1402, -2539, -375, -8455, -901, + -147, -3274, 9359, -277, -8941, 714, 2834, 2924, + -6326, 907, -123, 10487, -484, -4772, 877, 9840, + -505, -7562, 301, 671, 116, -371, 3740, 359, + 385, -5145, -908, 156, 9639, 3782, -9688, -4214, + -945, -7685, 334, 2185, -1342, 388, -1741, 278, + -231, -912, 905, -1039, 598, 2049, 662, -198, + 22378, 166, 116, -1699, 335, -8380, 1279, 1536, + 14955, 1254, 190, -2519, -608, 364, -561, 5748, + -1178, -923, 3183, -59, 13880, -2530, 241, -564, + -319, -7510, -9, -124, -20346, 305, -25, -400, + 222, -16943, -488, 802, -1685, 3323, -6198, 1000, + -903, -846, -387, 462, 847, 526, 10024, 2020, + 2090, -9563, 1416, 169, -12182, -428, 10388, 869, + 1068, 2201, -1041, -3180, 152, -646, 4, 4017, + -1069, 307, 5283, 3021, -13662, -493, 9, 542, + 152, -2617, -3870, -514, 13497, 1180, -603, 1255, + 2396, 7418, 8902, -11165, -2626, -5719, 1764, 858, + 1105, 1476, -1764, 1969, 977, -1738, -928, -13940, + 1444, -4157, 836, -12243, -369, -256, -15681, 5320, + -5170, -509, 353, -1581, -1455, 965, 716, 209, + -883, -317, -1961, 9128, -8197, 2173, -2434, -1126, + 4066, 1025, -16663, -7013, -147, 1617, -745, -3205, + 1496, 1822, -1199, -2999, 117, 619, -20002, -232, + 142, 3207, 561, -292, -1635, 1035, 37, 2712, + -243, -8269, 305, -2601, 495, 14516, 831, 260, + -54, 4217, 675, -1632, 4962, 793, 1066, 133, + -344, -12428, 95, 6164, -1298, -1860, 3622, -467, + -867, -1178, 11053, 118, -36, -6997, -763, 16019, + 16, 2459, 306, -820, -1135, 847, -709, 928, + -164, -293, -5736, 543, -11548, 5389, -2012, 300, + -228, -1043, 5107, -558, 1187, -140, -13034, -1571, + 740, -4967, -432, -6289, -1778, 3449, -337, -12607, + 344, -3790, -1598, -274, -346, -1494, -108, 325, + -1215, 819, 404, -568, -286, -21364, 15495, -2297, + 606, 117, 10, -193, -972, -292, -573, -1155, + -1289, -1025, 472, 1154, 843, 187, 586, 20569, + -5, -236, -1181, -1092, 700, 891, -603, -601, + 21648, -449, -193, -1103, -298, 2084, -251, 449, + -1414, 17168, -391, 104, -5465, 401, 8839, 781, + 1741, 201, -369, 466, 12358, -636, -945, 3928, + -605, -17445, 5020, -1289, 977, -6202, 1783, -507, + -76, 267, -31, -2731, -1560, -1225, 1348, 11176, + 1669, 754, 1671, -4038, 151, -371, 7283, 243, + 1387, 126, 1007, 1292, -15, 696, 282, -2623, + 1065, -1026, 191, -632, -132, -12957, -32, -1697, + -422, -240, 1352, 10252, 1067, 8296, -1244, -9, + -301, -3014, -249, -372, 10731, 535, 2147, -8959, + 346, -408, -8329, -1905, -48, -8176, 2782, 412, + 1425, -946, -748, 1095, -1370, 9086, -99, -143, + 68, -544, 264, 494, -377, 13, -618, 237, + 193, 3549, 317, -168, -7148, 2351, -244, -13240, + -3355, -2322, -533, 9554, 6906, 124, -694, -901, + -2762, 207, -915, -2520, -143, 8544, -678, -2788, + 12926, 791, 1296, 4861, -1470, 889, 3675, 806, + 290, -11146, 422, 9217, -31, 1608, 140, 3939, + -6903, -276, -704, 2353, -344, -1038, -230, -177, + 670, -617, -129, -857, -8231, 638, -411, -252, +-15709, -1218, 210, 288, 542, 533, -9087, -10493, + -624, 1175, 611, -230, 746, 1455, -590, 830, + 1756, -15800, 823, -1077, 788, 1071, 468, -1654, + 660, 983, -9697, -1300, 662, 2053, -281, 12949, + 389, -915, 197, -1742, -4587, 1746, 707, 1625, + 9021, 2204, 759, 1303, -428, -220, 41, -5499, +-16080, -193, 443, 443, -78, 889, -561, 5629, + -1073, 7019, 222, 1661, 1190, 1108, 94, 5624, + -3796, 407, -706, -122, 744, 363, 1648, -10896, + 595, 953, 85, -267, 195, 851, 17173, -636, + 243, 907, 2029, -700, 351, 1495, -157, -575, +-11664, 1252, 8341, -616, 3708, 5693, -6, -1753, + 1072, 863, -823, -4278, -12043, 750, 597, 3145, + 38, -8140, 3136, 290, 7, 11084, -876, 1842, + 175, 3458, 460, 1615, 11698, -827, 16, -12482, + 428, 411, 2625, -1352, 142, 529, 229, -48, + -965, -145, -592, 655, 499, 22095, 22141, 37, + -1875, 701, 45, 724, 1111, 1631, 262, -252, + -9092, 5325, 408, -637, -612, 647, 1268, 834, + -510, 603, 199, 816, -9904, 9533, -1580, 2669, + 1824, -2092, -701, -271, 7489, 46, -3295, -844, + -304, -226, -260, -692, -5, -527, 37, -49, + -1542, -69, -1087, 20519, 367, 1, 3487, 2535, + -5110, 642, 1223, -2130, -2894, 1752, -1618, 9732, + -1633, 6904, 137, 654, -358, 355, -21, -277, + -68, -188, 132, 530, 372, -315, -11498, 221, + 815, 2480, -1398, -123, 353, 3114, -12025, -1212, + -1111, 916, 6452, -1880, 1867, 307, -66, 1857, + 138, -980, -3088, -174, -41, -393, -656, 847, + 15824, -379, 358, 672, -389, 920, -21145, -393, + 350, -574, 1005, -2083, 26, 79, -203, -7967, + -3302, -5805, 772, -302, 2104, -1240, 13710, 6816, + 2282, -3709, -1512, -81, -2216, -3005, 444, -795, + 751, 2163, 20751, 780, 542, -480, 624, -425, + 769, 2474, -5903, 399, 10564, -112, 69, -1409, + 1885, 2339, 67, -620, 196, -2432, 6046, -1673, + 6512, 809, 7904, -516, 4278, 223, 359, 16512, + 1224, -480, -505, -735, -502, -593, -4565, 1914, + 122, -531, 1442, 464, 69, 292, 410, -581, +-19848, 1059, 132, 1392, 5917, 705, -7706, 2496, + -1487, -791, 11939, 185, -265, -2412, 630, -8028, + 1434, 10315, -1541, -3756, -2403, -1918, 1050, 8057, + 234, 13546, -92, -2172, -671, 11631, 103, 116, + -171, -4604, -267, -602, 15, 454, 6859, -2151, + -8707, -1664, 61, 2518, -969, 903, 1209, -1435, + 13531, 590, 236, -821, 598, 1186, -7690, 134, + -1005, -18177, -148, 519, 900, 951, 406, -3584, + 47, 9439, 1418, -797, -3353, -703, -1798, -1244, + 291, -2784, 14612, 2029, -161, 1040, -4130, 3064, + 1721, -2898, 269, 3367, 1379, 14359, -690, -655, + 2010, -4935, -681, -2606, 11651, 748, 101, 13593, + 629, 28, -540, -854, 1405, 558, -8785, -1016, +-13043, 121, -556, 4959, 1694, -720, -138, -3897, + 182, 1938, 844, 919, -683, 12042, -1101, -155, + -1375, -1509, 11, 220, 821, 21721, -367, -634, + -1468, -174, 1002, -1203, 318, 11672, -2114, 2472, + -1701, 5932, -661, 1094, 2500, -5609, 254, 437, + -911, -1611, -8005, 217, -1139, 1321, -10713, -2183, + 1163, -890, -622, 12820, 1021, -13578, 1040, 3216, + 592, 686, 737, -2881, -1693, 3995, -455, 4666, + -4124, -9316, 2061, 10645, 271, 264, -6829, 641, + 2061, -6683, -512, -747, -9131, 2445, 343, -9944, + -2888, 607, -10855, 871, 418, 504, 936, 1079, + 273, 400, -17752, -391, -1543, -6193, 1482, 737, + 2096, -982, 167, 972, 336, 1063, -1272, -1602, + -1907, 9, -191, -15207, -119, 4047, 1479, -1405, + 526, -18462, -627, -1996, -1022, -1544, 312, 7972, + -227, 797, -5204, -2160, 391, -423, 257, 3836, + 442, -1931, 22, 143, -203, 362, -73, 15679, + -289, -1445, 577, 858, 11408, -1970, -1022, 1550, + 882, -3699, -2697, 3978, 600, 86, 3858, 8683, + -7681, -4856, 4051, -1321, -587, 46, -499, -354, + -655, -15717, 67, 490, -2670, 474, -1374, 5601, + 60, -17615, -808, 87, 367, 579, 1057, 1020, + -394, 1181, -189, -10846, 763, 2635, 282, -3279, + -866, -15257, -449, 112, -15577, 227, 269, 13964, + -1273, 1513, -1487, 195, 319, 2527, -286, -5883, + -5360, -959, 2791, -3335, -945, -1985, -903, -11418, + 8525, 669, 6106, 153, -1169, -1198, -553, 7037, + 528, -4237, 717, -214, 1824, 10108, 961, 9077, + 1899, 10407, -207, -29, 355, -6794, 111, -13627, + 1361, -3577, 291, 4534, 2209, -1579, 109, 523, + 456, 10990, 31, -448, 385, 1481, 2, 15266, + 798, 5759, 860, -16424, -1315, 1631, -456, -977, + -180, -2593, 1191, 5959, -32, 8112, -506, -7766, + -1871, -15310, 662, 196, -20401, 925, 446, -2035, + -620, -686, -249, -2517, 423, 703, 633, 828, + -182, -37, -406, -149, 821, -22255, 652, 522 +}, + +.shape16 = { + -786, 193, -15441, 200, 1050, -16545, -41, 329, + -869, -170, -858, 2725, 217, 447, 2107, -23, + -387, -10280, -383, -320, 387, 16012, -79, -967, + 3528, -2123, -537, -636, -1761, 949, 100, -17, + -446, 261, 22527, 331, 26, -87, -206, -2292, + -1178, -164, 598, 147, 889, -14487, -2823, -1280, + -1892, 33, -1763, 993, 4807, -953, 2181, -588, + 59, -296, 218, 291, -104, 495, -1092, 2232, +-14904, -983, -2919, 795, -17207, -2045, 2988, 597, +-10312, -718, -2196, -5822, 847, 1304, -757, -4714, + -148, 831, -734, 806, 4348, -308, 244, 566, + 2706, 604, -748, -864, -568, -219, -128, -688, + -218, 110, -29289, 482, 76, -1447, -142, -417, + -253, 8124, -19775, 990, 4546, -1012, -8082, 133, + -1612, -2243, -3788, 1568, -2892, 852, -1642, -3479, + -23, 1300, -564, -1037, 249, -14533, -43, 321, + -680, 10, -417, 23426, 397, -108, 1843, 180, + 11976, -9613, 353, 3768, 130, -1035, 4340, 218, + 596, -224, -779, -1680, 1326, 152, -971, -9725, + -355, 5328, -459, 16242, -438, 926, 6210, 1912, + 769, 2621, -148, -1008, 517, 341, -3594, -965, + 11383, -874, -16949, 1167, -3371, -1655, 586, -132, + 3990, -770, 211, 246, 514, -166, -734, 30408, + -258, -521, -20, 339, 499, -2572, 2110, 272, + 1357, 123, 2841, -320, -31, -444, -501, 215, + -42, 595, 108, 484, -223, 937, 475, -72, + -319, 75, -205, -978, -9155, 145, 2020, -3, + 2438, 4046, -1281, -875, 1532, -598, 12288, 369, + -2046, 343, -778, 1769, -2589, -641, 17437, 1793, + -592, -1954, -1607, 6184, 3440, -512, -2710, -1330, + -127, 8765, 83, -243, -315, 709, 256, 1176, + -1198, -463, 970, -302, -568, -997, -1022, 159, + 11008, 27, 13074, 1523, -3239, 2330, -4808, 6115, + -9933, 1449, 2153, -3111, 1780, -731, 121, -881, +-14289, -265, 566, -611, -253, -2965, 250, -105, + -66, 2570, -1922, 2712, 1907, -2025, -454, 173, + 1463, -29, -31955, -113, -1751, -3353, 254, 1001, + 6781, -29, -639, -1289, 288, 498, -21505, 48, + 109, -2151, -223, 1360, -3430, 658, -4185, -1706, + 1244, 1899, 124, 12, -35, 289, 382, 433, + 261, -131, 54, -646, -280, 86, 180, 153, + -169, -20242, -95, 734, -524, 77, 102, 8468, + -421, 29, -3, 51, 1526, -600, -264, 355, + 1949, -985, -291, -86, 10212, -789, -393, -182, + -51, 946, -16716, -954, 1179, -2745, -509, -4774, + -587, -608, 7657, -509, -388, 987, 109, -218, +-17579, -524, -467, -1643, -444, 1430, 2541, -124, + 1785, 27, 7905, -73, -3135, -1241, -254, -2114, + 1175, 780, -50, 4055, 535, 438, 32, -113, + -260, 81, 1102, -59, 29188, -48, 212, -29, + -344, 559, 856, -483, 608, -40, -1498, 112, + 10374, 1198, -434, 4053, 1286, 236, 1823, 16046, + 592, 1583, 78, -5243, 1311, 456, -1342, -546, + -353, 13289, -333, -529, -20859, 183, -167, -1368, + -338, -690, 4248, -205, -666, -634, -1653, 1174, + 234, -18622, 891, 284, -2632, -1516, 289, 11242, + 727, 133, 284, -323, -1370, 908, -13169, -412, + 1155, 410, 610, -3072, -8220, -637, 242, -647, + -2072, 16041, 2292, -8009, 351, -3137, -3075, -1051, + 4569, 125, 23, 1281, 2487, 520, -209, -688, + 205, -1248, 246, -601, 533, -12209, -2298, 826, + -2762, 45, 15123, 721, 1128, 798, -676, 349, + -153, 263, 89, -854, -24, -350, -227, 157, + 587, -240, -185, 663, -32328, -148, -204, -2396, + -597, -344, 8104, -280, -375, 264, 648, 741, + -290, -321, 263, -569, -381, 167, 1757, -29636, + 30, 393, 398, 590, -242, 81, 1601, 3683, + 787, -336, 675, -1080, -713, 261, 18420, 1760, + 609, -4610, -551, 2790, 19807, 1347, -125, -9412, + -261, 548, 1056, 179, -917, -181, 12637, -267, + 621, -11908, 1366, 76, 5875, -742, 394, 155, + -370, 2481, 46, -15392, -344, -9750, -1353, -2242, + -1685, -1286, 2320, -2176, -1729, 705, -1582, 1590, + 1603, 21129, -3555, 2192, -883, 3438, 233, 1965, + -537, 399, -4818, -4085, 559, -292, 1290, -2700, + 10, -301, -1865, 226, 52, -1346, 306, 316, +-12281, -525, 285, 9631, -2, -849, 1620, 128, + 176, -1021, -473, 7929, -133, 2459, -33, -1517, +-22047, -2300, 98, -3513, 334, 4617, -193, -1309, + -1279, 738, -443, 95, 406, 660, -705, -54, + -39, 26396, -766, 249, -2423, 7759, -689, -3909, +-17404, 65, 1849, 945, 15907, 1386, -433, -831, + -6349, -3919, 1870, 8096, 311, 15043, 1709, -315, + 1288, 7522, -215, -5072, 1246, -1486, 3762, 4526, + 1517, -1936, -543, -263, 771, -10215, -425, -5098, + 59, -266, -1012, -380, -2131, 630, 405, 665, + -4550, 1403, 8, -46, -879, 398, -532, -185, + -286, 921, -65, 378, 669, 174, -15280, 91, + -776, 8480, 2463, 184, 2065, -666, -561, 4122, + 594, 732, 4007, -852, -71, 194, -126, 1765, + -1570, 968, -257, -288, 950, 27482, -333, 370, + -1429, 285, 558, 11245, -135, 565, 1296, -261, + -62, 600, 1455, 1457, 820, 357, -1203, 169, + 16611, -893, 359, 231, 418, -547, -95, 3866, + -511, -6344, -205, 923, -239, -16205, -1619, 217, + -3362, -6342, -1551, 649, -492, 264, -55, 170, + 16992, -91, 306, 43, -2770, 582, -1740, 77, + -882, 268, -515, -45, -6093, 24, -5596, 9034, + 284, 3211, 846, 1158, -1118, -604, -514, 1402, + -493, -938, -3892, 242, 643, 1421, -434, -406, + -102, -88, -11733, 161, 518, 978, 1508, 248, + -1036, 1407, -396, 293, 1154, -1435, 495, 8243, + 20, -845, -5373, 659, 2366, 29148, 145, 603, + 4088, -251, -2841, -2526, 20682, -1357, -2454, 660, + -125, 347, 11772, -113, -357, -2181, -1234, 1908, + -432, 16555, -248, 822, 15516, -158, -653, 1573, + 93, -2730, -1111, 958, -1550, -1153, 17, 610, + 781, -372, -1640, 144, -135, -1171, 22140, -427, + -26, 690, -800, -1497, -300, 5438, 390, 11304, + 9253, 1098, 5564, -9, 3856, 965, 2016, -12797, + 1687, 915, 3687, 539, 2496, 702, -1324, -71, +-12955, 7456, 4626, -848, -1815, 831, 2151, 7921, + -3000, 123, 1189, -1489, 222, 4973, 1936, 54, +-10527, -1238, -1157, 628, 14112, -2164, 1478, -985, + -4102, 635, 225, -311, -609, -1015, 301, 507, + -85, 443, 186, -552, -711, -16988, -1327, 220, + 565, -1673, -543, 18633, 331, 127, -342, 22, + -77, -360, -439, -501, -1848, -1147, -483, 1133, + -351, 41, 908, 502, -658, 474, -430, -11348, + -1, -531, 451, 709, 227, -978, 348, -265, + 269, -376, 2511, -188, -111, -387, 809, 1009, + 1570, -755, -11463, 667, -895, 446, 276, 145, + -513, -117, -462, -340, 1457, -963, 191, -788, + -150, -979, -507, -27540, 122, 368, -73, 10051, + -465, 642, 507, -6828, 241, -5025, 1598, -1174, + 2373, -2272, -1910, -108, 15, 166, 2, 10518, + 933, -12716, 510, 778, -424, 414, 4899, 759, + 862, -438, -886, 457, 304, 23639, 136, -203, + 478, -565, 244, -541, 2419, -773, 1107, -217, + 1579, -1037, 476, -97, 995, 17973, 161, 16466, + -178, -718, -1606, 947, 1991, 2266, 1249, 2708, + -611, 1424, -142, -53, 36, 509, 26159, -144, + 357, -37, -234, 587, 311, -509, -1639, -332, + -1618, -382, 302, -8657, -68, -30, 545, -12834, + 158, 158, 135, 621, -354, -871, 451, 1220, + -31, 2, -13414, 60, 3, -380, 541, -44, + 552, -366, 155, -462, 61, -232, -15426, 317, + 688, 1121, 2933, 7151, -168, -9167, -2521, 745, + 2792, -10448, 569, -3823, 630, -4626, -95, -416, + 828, 259, 72, 171, 635, -250, -128, -426, + -153, 260, -771, 314, 235, 26, 32281, -343, + 751, -1443, 324, -684, 1900, -1334, 2022, 30, + 1073, -2406, 2080, -485, -320, 15328, -860, -529, +-16444, -219, 1736, -149, -160, -828, 1089, 413, + 241, 3720, -90, 146, 1109, 243, -321, -256, + -68, 88, -50, 571, 1179, -25030, 104, 929, + 35, 529, 117, -13724, 734, -1344, 456, 5586, + 1566, -12573, -840, -1617, -2494, 1791, 1901, 3066, + -2159, -414, -3856, -9894, -1608, -657, 15355, -773, + -9217, -658, -972, 4730, -2986, -3478, -757, -1416, + -3702, 18089, 629, 7061, 124, 5843, 158, 19017, + -2204, -6976, 1629, -5657, 1101, -1859, -1425, -548, + -1132, -5043, 1074, -592, -196, 1902, 22705, -1228, + 214, -685, -2036, -2368, -315, -914, 533, 218, + 1091, -627, 2031, 13922, 104, -450, 4494, -498, + -361, 24734, 623, 1029, 2437, -1123, -5092, -6551, + 438, 16562, 375, -13102, -193, -2004, 3556, 179, + 1832, 2086, 798, -534, -195, -7105, 796, 3969, +-12269, 1570, 4273, -2692, 1240, -2901, -2045, -2453, + 372, 613, -548, -245, 687, 258, -8964, -1500, + -1519, -993, 17571, -357, 916, -1202, 1752, 2081, + -536, -3185, -1062, 19335, 721, -9958, 1052, -872, + 248, -3133, 456, 1641, 149, -11, 2955, 310, + -3178, -18823, 497, -971, -6587, -1380, 351, 106, + -43, 607, -4754, 213, 1030, 5377, -804, -2557, + 850, 1081, -706, 1325, -14922, -794, -14060, -1953, + 891, -3296, 329, -510, -1126, 1113, 1753, -411, + 1769, 429, -185, -1020, 194, -106, 11470, -591, + -272, 422, 337, 524, -150, 822, 51, -120, + 7193, 802, 640, -140, -42, 28125, -1020, 285, + -465, 3195, 69, 482, -953, 262, -7672, -373, + 5158, 5625, -3003, 550, 5371, 5619, -2200, 5392, + -804, 135, 1300, -3610, -23, -433, 13503, 224, + 911, -14421, -502, -2151, -1667, -1933, 2888, -277, + 547, -989, 3115, -32, -680, -164, 804, 412, + 62, -154, -190, 156, -10938, -360, -88, 843, + 328, -773, -267, -12668, 856, 1496, -243, -586, + 736, -2175, -677, -3069, 7480, -1764, -4024, -2569, + 1805, 194, -6814, -1135, -237, 2682, -156, -890, + 1285, 368, 1802, -683, -163, 1191, -13063, -496, + -335, 17482, 746, 818, 48, 21419, -598, -1753, + -1169, -2135, 40, -9114, 592, -3912, 1980, -264, + -304, 8138, -185, 286, -3024, 48, -1630, 909, + 661, -662, 18085, 240, -201, 69, 192, 305, +-22167, 692, -1135, -996, 398, -74, 18553, -958, + 1223, -5578, 508, -352, 1234, -450, 497, 780, + 79, 51, -221, 255, -26, 13352, -170, 231, + 590, 169, -733, -812, -65, -219, -20939, 200, + 35, -177, -454, 632, -267, -407, -120, 623, + -176, -664, 715, -23, 318, 148, 1125, 16, + 709, -21687, -230, -413, 1398, -1235, -283, 1615, + 175, -299, 349, 400, -112, 21762, -665, 364, + 1089, 1303, -54, 523, -381, -1312, 48, -886, + -1260, 408, 415, -8349, 7115, 180, -774, 3508, + -971, -255, -195, 81, -2674, -977, -355, -1500, + 178, -2081, -4432, -1014, 340, 5818, 138, -106, + 16917, 1203, 349, 3271, 961, 363, 6008, -6043, + 3736, -730, -4201, -514, -6131, -68, -14935, -1781, + -3898, -40, -18944, -461, -1694, -1269, -755, -81, + 2369, 484, 531, 14114, 85, 32, -10142, -142, + 600, -2374, 375, 675, -2663, 155, -947, 6427, + 11476, 1253, 5049, 1063, 2003, -1608, 2463, -2168, + -1128, 1079, 383, -996, 368, 1208, -3554, -959, + 4596, -1209, -4154, 1270, 9365, -2775, -1751, 998, +-20023, -347, 1505, 218, -142, 342, -128, -523, + -159, 75, -467, 257, -133, -142, 712, -621, + 428, -29584, 13, 402, -455, 119, -483, 1121, + -461, 960, 807, -46, 297, 14856, 221, -356, + 221, 15037, -4744, -2555, 447, -1418, 1464, 1391, + -1404, -5812, 512, -2321, 9882, 242, -2298, -137, + -849, -3182, 9394, 1412, 1052, 1369, -904, -494, + -231, 1113, 1087, -13317, 768, -1178, -3011, 24, + 229, 164, -10170, 328, 308, -591, 213, -543, + -82, -790, -875, 794, -558, -7651, -573, 1266, + -2084, 2275, -187, 97, 384, -11830, -185, -472, + 1365, 11636, -1405, 360, -487, -440, -1820, -349, + -293, 285, 25, -139, -415, -540, -108, 1136, + -673, 230, 19202, -545, -542, 919, 1221, -518, + 196, -21900, 795, 115, -16, 459, 3339, -347, + -346, -186, -695, -267, -714, 185, 266, -1218, + 120, -249, 233, -110, -30412, 285, 219, 2256, + 536, -442, 673, -1487, -477, -60, -1806, 183, + -7195, -577, 2230, -7594, -3230, 65, 22963, 111, + 390, 7134, -3716, -5123, -475, -32, -98, -466, + -118, -43, 74, -1071, -902, 1714, 4004, 26, + 97, 1680, 423, 252, 9667, 550, 354, -222, + 19, -224, -807, 365, 593, 363, -851, -28, + 553, 238, -481, 769, 279, 18367, -462, 286, + 4825, -141, 500, 20383, 1618, -31, -514, -2484, + -327, -8506, -705, -872, 530, -9997, -36, -431, + 2824, 3185, 1712, -318, 9513, -10065, 614, -503, + 389, 12830, -113, -15, -1007, -523, -1293, -2102, + -543, -1157, -583, 1228, 262, -674, -1847, -242, + 299, -12025, 547, -591, -9173, 275, 412, 2493, + 997, 1229, 1982, 27554, 245, 106, -1320, -153, + -423, -955, -449, 392, 824, 796, -1181, 1640, + -884, -70, 8789, 10021, -1806, 1019, 90, 1494, + 2071, -911, -1159, 212, 2207, -994, -2500, -497, + 92, -11544, -398, -774, 1474, 32, -671, -171, + -1250, -249, 1161, -654, -205, -36, 1733, 763 +}, + +.shape22_1 = { + 987, -6, -621, -220, -2438, -387, -535, -23, + -934, -68, -4985, 575, 483, 7243, -1075, 917, + 1739, -1832, -580, 1564, 131, -180, -1271, 3672, + 161, 1040, 1737, 2719, 1101, -185, -1410, 221, + -422, -8675, -753, -401, -5388, 13, 762, 1378, + 1113, 1768, -177, 3397, 2162, 267, 2261, -156, + 1708, -848, -79, -1819, -3159, -5548, -745, 7208, + -1039, 7555, -134, 2661, -2112, 2270, -1991, 441, + -6248, 246, 166, 2092, -1402, -242, -13600, -539, + 391, 2395, 11001, -981, 10906, -403, 823, 1647, + -294, 93, 504, -5448, 1213, -1849, -3077, 790, + -841, 12812, -11266, -1882, -805, -274, 1968, -49, + 1189, -80, -281, -40, 409, 2423, 581, -1362, + 207, -869, -589, 3294, -318, -4592, -476, 1014, + -135, -17999, -194, 807, -2946, -222, 44, -514, + -4407, -1201, 1155, -235, 98, 4432, -342, 2386, + 1402, -956, 3357, 1959, 4790, -139, -3494, -4280, + -589, -8422, 363, -746, 640, -360, -1007, -1100, + -7989, -12630, 1006, -1608, -864, -226, -915, -2032, + 1274, 596, 1864, 1067, 1597, 460, -2003, -5560, + -8020, 2354, 379, -3151, 44, 7024, -698, -2901, + 4976, 927, 1223, -93, 172, 189, 6639, -6082, + -726, -524, -3068, -3802, 16, -1039, -105, 2333, + -350, -306, -379, -832, 1282, 56, 3529, 562, + -603, 5954, 294, -1265, 8045, -3990, -169, -123, + -3267, 572, -879, 1562, -1185, 799, -9589, 407, + -590, 65, -2848, 433, -5547, -19, 7180, -7904, + -392, 323, -448, -4481, -3773, -5286, 1957, 226, + -2040, 3292, 2987, -1704, 2835, -149, 1435, 823, + 1775, -2769, 146, 234, -131, -15, 268, 37, + 139, 22, -196, 91, -3503, -5421, 24, -280, + 58, 370, 655, 1412, 113, 306, 16404, -234, + 315, -957, 72, -1129, 1993, -18719, -1415, 1349, + 2340, 541, 313, -1360, 31, 1441, -78, -9905, + -393, 367, -712, -2009, 372, -297, -123, 303, + -458, -323, 46, 8701, -1301, -8768, -43, 1818, + 212, -543, -5077, -8037, -2536, 702, 792, -381, + -272, 1941, 6320, -1871, -13938, -262, -2063, 108, + -861, 485, -440, 768, 5665, -302, 305, -13784, + 2889, -127, -94, 145, 1308, 7911, -8376, -643, + -596, 1357, -943, 1329, -84, -62, 1651, 391, + -2295, -5456, -357, -4611, 1361, 3961, -295, 642, + -698, 8614, 1613, -526, -120, -205, 17, -20171, + 1252, -261, 535, -1244, 92, -315, 878, 380, + 157, 3217, -493, -773, 513, -510, 11304, -899, + -27, 398, -6386, 659, -1001, -2737, -13295, 1219, + -1014, -193, 445, -2393, 344, -25, -599, -2848, + 884, 94, -11, -564, -36, 9939, -3530, 462, + -942, 10089, 824, 2994, -293, 71, 10167, -457, + 711, -964, -2128, 2530, 160, -2558, 2451, 1654, + -3828, 1560, 879, -1023, -8354, 851, -77, -112, + 19572, 2010, -1077, -1329, -1282, 1277, 252, -5622, + 4617, 58, -2315, -459, -1249, 92, 708, -737, + -3323, 182, 1557, -657, 546, -447, 19117, 1645, + -336, -26, -2041, 5926, 4746, -1866, 3922, 2798, + 5320, 7, 470, 842, 229, -567, 742, -3306, + 659, -871, -226, -2593, -1003, -1373, 595, -768, + 20658, 944, 1228, 279, -1531, -618, 361, -4019, + -343, -351, 7143, 293, 92, -2713, -269, -30, + -332, 4093, 216, 239, -563, 1943, -944, -2268, + 70, -209, 440, 1493, -446, 491, -362, 25, + -331, 433, -1585, 173, 1126, -3614, -234, -2649, + 1181, -641, -160, 3727, -841, -2134, -1396, -5758, + -14, 364, -4651, 1151, 194, -5234, 5878, -1348, + -1388, -233, 3810, -860, 9479, -24, -6616, 1387, + -455, 447, -224, -2997, 12, 3502, -73, 470, + -9170, 1677, -740, -592, -1638, 675, -93, -17842, + 1750, -847, 993, -2393, -49, -2029, 1940, 588, + 475, -3467, 55, 5087, 2989, 380, 915, -2782, + 2418, 11303, 1098, 1009, 1372, -5780, -303, 1451, + 972, -7433, -571, 1661, 64, 10265, 1541, -50, + -964, -738, -253, -3105, -695, -546, -775, -18971, + -3094, -2379, 738, 1625, 623, 1073, 782, 723, + -3417, -578, -189, 4108, 1115, -1222, -9102, -4736, + 347, 946, 322, -3699, 193, -15139, 367, 969, + -788, -694, -620, -26, -16, 4, -478, 20792, + -1175, -231, 2566, -1270, 162, 181, -1451, -5370, + -2429, -8910, -3794, -5807, -1655, 248, 4432, 1393, + -2451, -2706, -744, 687, 842, -1281, 2960, -2348, + 153, -1671, -1433, -1250, -1096, 2501, -5393, 4266, + -1098, 880, -1215, 817, -443, 10053, 705, -689, + -2679, -1205, -3302, -809, -918, -1005, 124, -329, + 108, -52, -5305, -419, 128, -8137, 1427, 387, + -235, -2582, 190, -173, -1031, 2672, -985, 3309, + -5927, 7327, -8463, -2, 6035, 743, 552, -14, + -580, -68, -11886, 476, 61, 1172, -529, -988, + 871, -776, -332, 20870, 384, 7795, -10830, 723, + 1690, -519, 962, 663, 1300, -465, 47, -3578, + 56, -8131, 2041, -8524, -1303, 6349, 1903, -6726, + 1156, -224, 1286, -2355, -3415, 985, -502, -2474, + 49, -2789, -3616, -1707, 3363, -140, 1702, -1919, +-11518, -404, 62, -6933, -1187, 10830, 132, 284, + -639, 1349, 2367, -311, -626, 745, 5660, -152, + -121, -5236, -481, 5889, -1263, -8443, -33, 936, + 423, -117, 111, -1055, -103, -321, 1286, -611, + 777, 827, 422, -162, -6767, -241, 289, -441, + -1344, 2706, -1260, -4649, -847, -16107, -263, -1826, + -521, -760, 942, 309, -2692, -4835, -853, -806, + -276, -322, 5647, 1219, -433, -346, -1171, -1028, + 191, -406, 444, 33, 272, 3502, 475, -2178, + 1915, -290, -1037, 833, -695, -121, 415, 556, + 1025, -2268, 334, 2847, -1768, -389, -14034, -3878, + 836, 4605, -1985, -359, 1478, -149, 823, -926, + -828, 135, 469, -645, -328, -94, -178, 2820, + 781, -2361, -5778, 1312, 3918, -1, -3654, -942, + -2495, 615, 210, -17006, -396, -445, 382, 563, + -1738, 95, -9107, 4869, 348, 527, 5688, -145, + -1195, -2367, -749, -187, 6697, 27, 347, 12571, + -64, -427, 3765, 824, -1216, -1126, 5997, 586, + 110, -294, -240, 1646, -186, 1360, 413, -6459, + -1535, -3208, -520, -621, 8613, 1098, -19, -199, +-11446, -657, -353, 906, 678, -19375, -126, 1688, + 644, 1231, -2151, -742, 320, -68, -12426, -2750, + 1483, -1603, -2639, 3028, 2662, -140, 5405, -917, + -407, 207, 9392, -569, 931, -124, -82, 6370, + 477, -12264, 1093, 3427, -732, -50, 232, -67, + 609, 1615, -463, 583, 1808, 1499, -509, -24431, + 231, -72, -192, -333, -7554, -342, -9036, -304, + 136, -15450, 1333, -1147, -1488, -1440, 75, 63, + 747, 297, -251, 30, -301, -1810, -86, 544, +-10446, 1300, 10468, 218, -2471, 1982, 423, 3046, + -1112, -657, -104, 10671, -46, -10953, -6205, -1275, + 1972, 937, -75, -330, -529, -2581, 1510, -1881, + -1372, -1725, 14541, -560, -884, 946, -307, -5031, + 7798, -190, 720, 1525, 29, 868, 1238, 372, + -462, 2467, -2661, 2721, -1514, 723, -2782, -494, + 240, -7147, 587, 751, 1613, 11054, 1074, 275, + 972, -970, 27, -75, 24, -9, 163, 88, + 21, 87, -78, -743, -128, -2336, -235, -743, + -3918, -333, 1088, -195, -166, 782, -119, -3263, + 604, 2155, -258, -1282, -129, 43, -5124, -472, + 685, -14243, -1294, -99, -1922, -284, -422, -1112, + -3194, -1977, 1448, -419, -7172, 20, -70, 2102, + 0, 278, 1882, -10005, 1612, 6020, 71, -141, + 1027, -43, -864, -448, -21257, -336, -2090, 5207, + 674, 722, 1030, 1367, 1963, 6057, 984, -1087, + -3690, 47, -61, 104, -81, 895, 22, 728, + -191, 3219, 5228, -27, -802, 1438, -9026, -1352, + -581, 912, -664, -23, -522, -912, 178, -603, + 571, 574, 406, 564, 175, -405, -2965, -1072, + 1749, -957, -402, 9431, 1649, -409, 291, 5765, + 808, 6754, 727, -37, -254, 1530, 213, 3253, + 357, 371, 45, -1276, -12432, 2799, -1924, -176, + -1107, -183, 198, 3662, 20, -1166, 2507, -3484 +}, + +.shape22_2 = { + 1688, -307, -590, 971, -3616, -1632, -218, 1861, + -1479, -367, -6584, 487, -951, 10808, -232, 444, + 89, -1216, -1577, 1283, 249, -3, -3646, 2205, + -1116, 2630, 2110, 3193, 270, -189, 78, -826, + 1010, -10520, -370, 1234, -5604, -262, 1277, 1440, + 2225, 2466, 305, 2469, -740, 120, 3184, 2125, + 1185, -3230, 1597, -1670, -8283, -9857, -129, 8932, + -1355, 8755, 707, -256, -135, 423, 1543, 1782, + -4875, 403, 373, 1570, -183, 782, -9617, -2539, + 1090, 523, 6929, -1226, 10329, -278, -999, -260, + -1810, 666, -463, -6100, 2040, 256, 532, -1475, + 383, 13137, -10953, -2226, -1243, 1584, -2348, -809, + 3602, -816, 194, 480, 84, 2297, 344, -5181, + -6243, -2616, 2093, 7112, -2373, -1346, 291, -372, + -863, -16911, -1878, 378, -826, 579, 737, -468, + -2288, 264, 634, 108, -254, 4717, -1286, 2885, + 986, -4944, -98, 2007, 991, -2252, -2887, -6141, + -605, -10474, 896, 6, 235, -407, -70, 478, + -8392, -10870, 575, -672, 103, 320, -179, -229, + 445, -380, 1124, 3271, -1327, -275, -239, -10381, + -9102, 1361, 96, -1255, -277, 9316, -415, -2258, + 8992, -117, 1625, -704, -980, 752, 9133, -8792, + -423, -272, -865, -2285, 443, -2014, -2592, 3180, + 1198, 2570, 3360, -7090, 3311, 697, 2229, 46, + -472, 6984, -140, -780, 10391, -1078, 48, -564, + -5073, 1576, -826, -483, 952, 1099, -11536, -652, + 375, 440, -7319, 2646, -2089, 2804, 3795, -6704, + 251, 811, -1224, -1976, -4943, -6671, 780, -2856, + -7907, 2447, 3755, -135, 1127, 328, 553, 3450, + 351, -5054, -5, 1077, 109, -254, -391, -511, + 404, -61, 510, 395, -6044, -7454, 364, -575, + 65, -410, -1921, -248, 128, 311, 17131, -2135, + -563, -884, 2356, -3951, -1176, -16695, -1534, 1977, + 626, 2478, 1554, -1070, 38, -551, 370, -11053, + -331, 1062, -1385, -1681, 1028, 3350, 239, -76, + -156, 49, 397, 7060, -2834, -6527, 22, 1920, + -951, 356, -7674, -8903, -120, 317, -303, 160, + 530, 4611, 1083, 514, -12207, -283, 1413, -848, + -645, -432, 0, -192, 4780, -3485, -1192, -10574, + 1274, -3057, 475, -188, 183, 7865, -11214, -268, + 491, 1422, -28, 149, 515, -1651, 670, -450, + -958, -4288, 567, -182, 668, 4069, -213, -1176, + 148, 8854, -151, 474, 599, 1297, 237, -19186, + 2993, -482, -591, -1322, 25, -628, -828, -203, + -1500, 5519, -84, 723, -1137, 1217, 13045, -707, + -372, -200, -4142, -790, 188, -6760, -8288, 766, + 366, 444, -517, -2679, -1470, -61, 161, -3734, + 3053, 2012, 439, 627, 524, 5538, 549, -473, + -2244, 8399, -6395, 5811, 851, 58, 11376, -6, + -337, -689, -1510, -690, -388, -3587, 2665, 3371, + -1850, -953, -513, 581, -10296, 548, 1092, 565, + 18045, 215, -1486, -1270, 450, -880, 407, -6547, + 8393, 206, -515, -1565, -219, -1872, 1479, 382, + -569, -5002, -1247, -45, -740, -1791, 17177, -1210, + 761, 132, -1627, 4970, 5563, 722, 5614, 430, + 5659, 139, 1193, 1513, 1144, -1319, 561, -5145, + 1010, 199, 656, -3958, 3544, -1758, 810, -1578, + 15976, -139, -1035, -416, -543, -418, 2824, -6541, + 94, -673, 11741, 426, -15, -5280, 780, 1795, + -4616, 8192, -297, -206, 883, 2369, -395, -4266, + -3120, -199, 985, 1240, 352, 232, -170, 176, + 413, -495, -1399, 754, 618, -6103, -179, -2546, + 965, -1362, -806, 838, -3912, -1346, -3135, -937, + 219, 307, -3509, 1210, 2381, -7923, 6358, -885, + 2902, 284, 2560, 1789, 6878, 6, -4418, -2206, + -1091, 1840, -118, -2659, 1008, 2192, 1651, 1363, + -7772, 1252, -1200, 133, -757, 501, -98, -17197, + 98, -543, 1743, 621, -809, -1950, -793, 1168, + -743, -7124, 166, 7875, -4466, 356, -1430, -467, + 8589, 9931, 520, -866, 1945, -599, -434, 113, + 589, -3456, 597, 6076, 1114, 9660, 1532, 2073, + -138, -721, -1030, -1309, 625, -4040, 1211, -18836, + -3963, -4468, 197, 600, -1004, -816, -560, -476, + -2160, -2, 26, 8162, 1057, -178, -11739, -1882, + 1000, -227, 109, -1852, -1163, -17143, 140, -718, + -1150, 33, 1397, -45, -205, 153, -1494, 20509, + -51, -904, -599, 1915, 884, 504, -1819, -4487, + 1252, -1259, -2200, -5601, -448, -686, 5778, 873, + -4282, -533, 295, -450, 1422, 2393, 3267, -3911, + 249, -3605, -3190, -1096, -2422, 274, -1918, 4070, + -206, -432, 1919, -645, -275, 12954, 311, 1479, + -2664, -852, -4809, 1102, -375, 20, 1659, -1179, + 1199, 44, -5590, -1112, -566, -11369, -125, -871, + 158, 1208, 265, -519, -405, 2439, -1129, 1827, + -9461, 8548, -1606, 380, 4924, 662, 1314, -391, + -2024, 827, -13381, -198, -142, 1600, 3329, 125, + -672, -220, 557, 18642, 60, 7296, -10472, -712, + 1188, 808, 64, 479, 555, 264, 394, -611, + -810, -7943, -235, -6889, -1575, 1320, -381, -7414, + 1740, -744, 369, -626, -6899, -2144, -593, 668, + -351, -3756, -5143, -1814, 806, -475, 588, -507, + -9088, -629, 154, -6945, -1105, 10658, -435, 384, + -757, 1183, 3806, -747, -378, 535, 10224, 626, + -866, -1931, -1484, 5818, -750, -9628, -250, 589, + -653, -198, 104, -934, 1207, 46, 960, -1032, + 4236, 4471, -2896, 1551, -7714, -1921, 746, -671, + 5114, 5482, -522, -3344, -1905, -9220, -663, -1355, + -611, 65, 1368, 628, -1276, -6780, -2623, -661, + -117, -437, 5507, 3205, 928, 537, -9487, 80, + -102, -538, -277, 863, -1421, 6054, 1227, 696, + 3582, -508, -1757, 145, -1705, -1201, 4157, -3314, + 2291, -834, 821, 552, -724, 513, -9730, -8944, + 1913, 501, -216, 716, 2766, -823, 2535, 314, + 1774, -3372, 235, 244, -1216, -710, 689, 6736, + -52, 218, -8382, -444, 920, 569, -4890, -2050, + -612, 1708, -481, -15500, -2878, -691, 538, -125, + -81, -862, -10094, 12050, -1392, -326, 133, 61, + -50, 715, -6662, -673, 10745, -596, 44, 3906, + 247, -745, 4950, -210, 497, -1875, 8197, 2141, + 1454, -23, -1480, 2184, -804, 5515, -1311, -8893, + -2880, -3606, -282, -116, 8084, 618, -403, 1106, +-14405, 1159, 229, 742, -184, -19445, -329, -747, + -1240, 1487, -1670, -839, -77, -882, -10986, -2851, + -24, -747, -3615, 1939, 1389, 132, 5367, 1355, + 408, -1272, 11388, 153, 2708, -1503, 169, 7357, + 51, -13586, -404, -304, 626, 163, -1814, -515, + 445, 589, -1194, 770, 555, 246, -165, -21192, + 184, -265, -1116, -485, -8107, -1992, -10805, -880, + -1455, -15154, 2312, -1712, -11, -1899, -400, -2, + 314, -318, -280, -658, -1066, -2584, 1027, 801, +-11960, 1519, 8873, 465, -3229, 1801, -348, 749, + 7, 1079, -2051, 11521, -831, -13425, -6315, -1135, + 1088, 1056, -46, -1006, 374, -5065, 1163, -402, + -50, -1459, 9586, 514, -1439, -638, -155, -5289, + 8043, -612, 739, 1084, -60, 891, 786, -6, + -1078, 2097, -5333, 3497, 23, -913, 1303, 957, + -35, -6418, -146, -971, 2738, 9695, -1722, -2002, + 905, -1749, -917, 122, 379, -325, -455, 230, + 825, -137, -335, -96, -160, 390, 731, -2621, + -5889, -3949, 5138, 839, -1190, -66, 961, -4600, + 2345, 1607, -2448, -6653, -592, -106, -7619, -794, + -1186, -12587, -11, -2224, -225, -2903, 534, 1355, + -7002, 314, 494, 1950, -8545, -2531, -2438, -77, + 886, -1851, 944, -10156, 3003, 1846, 1919, 2019, + 471, 451, -436, -1012, -20121, 275, 98, 1776, + 578, 96, -16, 1156, 3689, 7, -207, 920, + 105, -58, -175, 163, 697, -407, -61, 1261, + 1297, 5061, 5326, -1126, 516, 1208, -11108, 441, + 7, -899, -19, -368, 438, -1911, 602, 716, + 313, 853, 1448, -817, -1453, 1384, -4371, 1043, + 1884, 1619, 2196, 10075, -1548, -1201, -796, 5228, + 2657, 8244, -605, 422, -693, 3171, 657, 5438, + -171, 633, 1579, -1718, -12265, 1083, -976, -293, + -3802, -306, -668, 7818, -1340, -402, 2231, -4472 +}, + +.shape44 = { + -40, -282, 1366, -1173, -3484, 355, -1078, 3800, + 4386, -35, -4192, 523, 1291, 678, 156, 2272, + -1043, 1075, -1849, -314, -522, 392, 2098, -79, + 473, -275, 2, 6398, 451, 94, 173, -431, + 1115, -10788, 35, 1823, -3380, -97, -98, -350, + -23, -1264, -308, 8948, -695, -79, 3520, 308, + 340, -362, -547, 1207, -1182, -10392, -148, 3580, + 481, -425, 862, 4894, 736, -152, -626, 23, + -5853, 39, -143, 418, -103, -1457, -12826, -122, + 283, -225, 10561, -153, 8872, -806, -51, 93, + 420, -209, 345, -7661, -732, -48, 479, -225, + 276, 13385, -12578, -1440, -265, -274, 1105, -3376, + -691, -579, -972, 300, 349, 362, 722, -472, + 185, 814, 14, 4746, 761, -336, 1691, 888, + -1669, -18717, 827, -2605, 921, 155, 68, 112, + -3032, -287, 414, -86, -62, -213, -106, 807, + -619, 598, -178, 3104, -481, -1553, 1250, -8363, + -686, -9608, 116, -47, 321, -89, 939, -35, + -7995, -10159, -526, 145, 363, 2170, 1077, -1223, + -738, 120, -408, -390, -80, -404, -1607, -10187, + -6432, 961, 94, -1459, 489, 6641, 372, 1007, + 5958, -834, 222, 51, 282, -1005, 4473, -8841, + -73, -477, -557, 121, -165, -1195, 438, 139, + -190, -4205, -4278, -4617, -7592, 40, -422, -459, + 594, 7331, 164, 297, 2631, -9075, -78, 372, + -6213, -1053, 182, -71, -386, -604, -11720, 552, + -617, 413, 1292, 4, -485, 1162, 6051, -5168, + -181, 1024, -630, -275, -4067, -8627, 1386, 970, + -423, 2973, 2360, 363, -274, 410, 48, 768, + 2958, -427, 86, 64, -128, -273, -182, -292, + 868, 463, 73, -116, -6509, -5295, -37, 691, + 344, -120, 168, 419, 494, -1175, 18896, -135, + -376, -218, -453, -916, -1040, -22179, -846, -1005, + 264, 159, 597, -952, -825, 393, -328, -14694, + 371, -263, 740, 38, -1001, 1289, -668, 187, + -155, 143, 683, 7133, -563, -8383, -291, 176, + 75, 613, -6965, -11480, 324, -490, 586, 416, + 762, 5777, 64, -47, -4124, -1196, -113, 701, + -211, 2335, 130, 684, 7278, -158, -213, 297, + 10845, -1439, -465, 17, -792, 6499, -10187, -444, + -1416, 482, 636, 1472, 752, 157, -334, -3230, + -19, -6747, 660, -3082, 4057, 6801, -19, 635, + 19, 9807, 526, 126, 444, -190, -418, -26754, + -202, 243, 597, 10, 345, 814, -330, 160, + 344, 3986, 470, 459, 2387, -549, 11889, -1837, + -30, 2608, 615, 2301, -771, -1589, -6935, 1321, + 4287, 295, -558, -1503, -611, 2104, 411, -218, + 1145, -426, 58, -102, 13, 7499, 476, -4032, + -2237, -2658, -1943, 5268, 1039, 389, 7091, -22, + 156, -186, 2432, -878, 305, -1726, 3209, 361, + -1030, 505, 618, -262, -1877, 268, 757, 24, + 24306, 102, 973, 142, -953, -1199, 116, -255, + 5370, -347, -365, 937, -6939, -1189, -760, 531, + -1759, -705, -557, -620, 1151, 250, 21629, -1532, + -128, 1421, -211, 592, 5126, 197, -716, 1113, + 5844, -266, -12, -813, 85, 994, -2106, -3915, + 1402, 533, 521, -883, 87, -386, -2, -4350, + 19790, -180, -363, 60, 101, -1717, 119, -381, + 100, -565, 3264, 3052, 200, -7319, 26, 347, + -482, 10609, -766, 526, -623, 3495, 339, -4406, + -59, -213, 686, -603, 133, 99, 48, 1716, + -1214, 1397, -2396, -384, -901, -3750, -660, -4314, + 313, 192, 292, 259, -644, 176, 2099, 7961, + -29, 642, -2970, 1792, -61, -4348, 578, 1867, + -1868, 32, 5262, 137, 6109, 443, -176, 351, + 400, 1874, -175, -4065, 697, 292, -744, 121, + -5134, 6996, -198, 628, 1073, -599, -116, -17900, + 647, -1049, -663, 1427, -94, 721, 311, 337, + 1376, -2784, 3947, 1342, 1577, -406, -260, -10228, + 109, 2358, 2437, 346, 1261, -308, -2094, 1682, + 144, -675, 183, 428, -950, 1249, -1546, 33, + -254, 681, -1264, -964, -310, 838, 100, -21952, + -1484, -1564, 339, 298, 67, -338, 89, 709, + 53, 258, -359, 2803, 1553, -312, -7993, -1627, + 1189, 476, -123, 336, -767, -18522, 589, 942, + -645, -381, -1913, -582, 55, -876, -509, 25143, + 690, -787, -1136, 114, 162, 342, -231, -8742, + 99, -646, -474, -1384, -110, -98, 8634, -14, + -9676, -312, 358, 496, -676, -97, 1904, -2124, + -66, -1868, 502, -513, -3244, 2079, -1476, 5440, + -40, -381, 500, -238, -471, 12160, 248, -1005, + -2886, 173, -3369, -355, -256, -117, -474, -1282, + -355, 130, -4833, 31, -232, -12931, -826, 322, + 839, 1537, 73, 226, -1888, -483, -2848, -190, + 1271, 3597, -4514, -38, 6093, 347, -68, -415, + -105, -1664, -11461, -110, -399, 389, -511, 935, + -424, -1708, -1026, 23239, 298, 7363, -9206, -566, + 259, -412, -1213, 335, 614, 928, 972, -1919, + -407, 509, 303, -13762, -524, 10360, 1318, -2758, + 2350, -106, -119, -68, -6155, -255, -448, -34, + -64, -4382, 47, 635, -339, 406, -447, -445, +-10592, 233, 160, -5515, -1333, 6755, -952, 172, + -1260, -294, 3480, -352, -231, 415, 482, -498, + -191, -2034, 7934, 7997, -688, -9503, 376, -228, + -500, 222, -1021, -407, 261, 179, 622, 1217, + -443, -763, -508, -719, -4509, 91, 449, -283, + 91, -39, 961, -10148, 1596, -9161, -327, 221, + -470, 676, 12, 1416, 984, -10988, -5500, -189, + -727, 226, 4691, 688, 759, 930, -6444, -114, + -539, -526, -21, -1218, 650, 6088, 419, 6185, + -1200, 84, -1232, -34, -107, 60, 2248, 450, + 1187, 1264, -181, 857, 2235, -2859, -13483, -192, + -586, -207, -5569, 503, 3376, 1243, -700, 2119, + -2186, -296, 896, 299, 177, 184, 1375, 2498, + 161, 579, -3683, 443, -21, -186, -3474, 238, + 274, 277, -325, -8325, -223, 125, 191, 333, + -345, -1391, -7372, 11389, -1055, 4066, -1098, 87, + -203, 443, 363, -959, 15395, 4016, -254, 1611, + -168, -1070, 2709, -768, 506, -1245, 5821, 2499, + 1564, 27, 85, 1989, -1092, 150, -972, 660, + -33, 687, 545, -1564, 720, -196, -52, -1751, +-25380, -1246, -615, 391, -512, -23289, 460, 360, + -85, -723, -250, -163, -48, -921, -3988, 425, + -1268, -1695, 3233, -1093, -1166, 198, 7602, 21, + 354, 733, 12213, -347, 532, -427, 22, 2218, + -578, -3382, -474, -625, 78, -4546, 863, -53, + -357, -1529, 1014, 710, 1356, -430, -1633, -24823, + 95, 26, 590, -591, -7833, -1355, -9771, -502, + -907, -15433, 957, 463, 35, -496, 294, 2129, + 1274, -160, -83, 531, -767, 285, 232, 5983, + -6122, 1620, 4112, -239, -1733, -46, -1321, 467, + 613, -3747, -2284, 13991, 373, -17357, -219, -80, + -210, 1462, 37, -1692, 548, -5845, 420, 54, + -350, -285, 1981, 262, -874, 2844, -435, -6305, + 6449, 72, 631, -94, 96, -442, 1137, 89, + 364, 3392, -3512, -387, 1055, 318, -1111, -6971, + 344, -9105, -96, -9362, 190, -225, 370, 161, + -73, -1830, 174, 48, -518, -3486, 137, -235, + 810, 23, 80, -642, -35, -316, -269, -373, + -2413, -933, 2525, 267, -508, -200, 422, -3470, + -1273, 640, -1956, 139, 394, -1043, -11008, -158, + -1089, -2023, 202, -979, -744, -159, -392, -37, + -1679, 2183, 1365, -2883, -4752, -2255, 109, 1660, + -613, -511, 1284, -7331, 947, 7009, -2072, -321, + -936, -551, -875, 160, -27027, 654, 265, 164, + 376, 726, -149, 2813, -94, 5728, 702, -1118, + -2555, 217, -186, -107, 146, -83, -62, -196, + 708, 146, 3729, -416, 212, -163, -7861, 347, + 83, -1079, -994, 271, -1054, -1647, 139, -20, + 354, 1298, -3420, 1130, 161, 475, -3913, 468, + 23, 285, -1699, 8234, -947, 222, 260, 4276, + -341, 6387, 21, 490, -1908, -1654, -60, 2471, + 733, -135, 109, -1136, -14756, 4922, 1165, 149, + -3976, -66, -594, 6181, -110, 292, 1129, -591 +}, + +.lsp08 = { + 0.2702, 0.5096, 0.6437, 0.7672, 0.9639, 1.0696, 1.2625, 1.5789, + 1.9285, 2.2383, 2.5129, 2.8470, 0.1740, 0.3677, 0.6082, 0.8387, + 1.1084, 1.3721, 1.6362, 1.8733, 2.0640, 2.3442, 2.6087, 2.8548, + 0.1536, 0.3279, 0.5143, 0.6859, 0.9763, 1.2744, 1.5605, 1.8566, + 2.1007, 2.3450, 2.6075, 2.8850, 0.2075, 0.4533, 0.7709, 1.0377, + 1.2953, 1.5132, 1.7826, 2.0351, 2.2590, 2.4996, 2.6795, 2.8748, + 0.1393, 0.2453, 0.3754, 0.5453, 0.8148, 1.1289, 1.4389, 1.7592, + 2.0353, 2.3215, 2.5934, 2.8588, 0.1250, 0.3627, 0.7613, 1.1380, + 1.4163, 1.5565, 1.6920, 1.8130, 1.8678, 2.0427, 2.4318, 2.8544, + 0.2256, 0.4223, 0.6452, 0.8599, 1.0673, 1.3118, 1.5486, 1.8366, + 2.0759, 2.3026, 2.5284, 2.8030, 0.2304, 0.4404, 0.6891, 0.8964, + 1.1510, 1.4202, 1.6483, 1.8580, 2.1181, 2.3686, 2.6078, 2.9128, + 0.2230, 0.3816, 0.5520, 0.6062, 0.7909, 1.0988, 1.4330, 1.7846, + 2.0713, 2.3457, 2.6048, 2.8708, 0.2447, 0.5800, 0.8249, 0.9905, + 1.1721, 1.3990, 1.6694, 1.9064, 2.1307, 2.4255, 2.6815, 2.9117, + 0.1974, 0.3812, 0.5802, 0.7759, 0.9280, 1.1547, 1.4170, 1.6369, + 1.8890, 2.2587, 2.5626, 2.8239, 0.1209, 0.2510, 0.4841, 0.8048, + 1.1197, 1.3563, 1.6073, 1.8926, 2.1350, 2.3669, 2.6291, 2.8985, + 0.2352, 0.4347, 0.6582, 0.8178, 0.9548, 1.1654, 1.4942, 1.8812, + 2.1703, 2.3779, 2.6412, 2.8871, 0.2091, 0.4084, 0.6730, 0.9151, + 1.1259, 1.3262, 1.5937, 1.8129, 2.0237, 2.3317, 2.5778, 2.8620, + 0.1167, 0.2406, 0.4520, 0.7298, 0.9848, 1.2448, 1.5137, 1.7874, + 2.0280, 2.3020, 2.5914, 2.8794, 0.3003, 0.4966, 0.6520, 0.8505, + 1.1600, 1.3981, 1.5805, 1.8346, 2.0757, 2.3102, 2.5760, 2.8499, + 0.2451, 0.4163, 0.5960, 0.7805, 0.9507, 1.2438, 1.5587, 1.8581, + 2.0735, 2.3198, 2.5704, 2.8220, 0.3112, 0.5517, 0.7032, 0.8528, + 1.1489, 1.4257, 1.6848, 1.9388, 2.1577, 2.4265, 2.6678, 2.9051, + 0.2249, 0.3897, 0.5559, 0.7473, 1.0158, 1.3581, 1.6914, 1.9930, + 2.1843, 2.3534, 2.5512, 2.8065, 0.2600, 0.4574, 0.7349, 0.9691, + 1.1696, 1.3848, 1.6335, 1.9021, 2.1174, 2.3481, 2.5902, 2.8390, + 0.2246, 0.3372, 0.4560, 0.5249, 0.7056, 1.0273, 1.3810, 1.7132, + 1.9819, 2.2574, 2.5410, 2.8491, 0.1419, 0.4834, 0.8835, 1.1453, + 1.2839, 1.4224, 1.5593, 1.7877, 2.1285, 2.4070, 2.6043, 2.8511, + 0.1886, 0.3677, 0.5617, 0.8099, 1.1277, 1.3841, 1.5804, 1.8136, + 2.0307, 2.2805, 2.5399, 2.8322, 0.2351, 0.4151, 0.6675, 0.8713, + 1.0464, 1.3292, 1.6586, 1.9281, 2.1355, 2.3495, 2.6222, 2.8782, + 0.2700, 0.4489, 0.6206, 0.7121, 0.7737, 0.9848, 1.3658, 1.7433, + 2.0139, 2.2243, 2.4806, 2.8175, 0.2479, 0.4425, 0.6490, 0.8745, + 1.1161, 1.3849, 1.6773, 1.9566, 2.1491, 2.3624, 2.5685, 2.8114, + 0.2035, 0.3701, 0.5567, 0.7953, 1.0082, 1.2758, 1.5373, 1.7822, + 2.0175, 2.2601, 2.4759, 2.7771, 0.1856, 0.3461, 0.5998, 0.9041, + 1.2383, 1.4612, 1.6667, 1.9305, 2.1617, 2.4107, 2.6477, 2.8656, + 0.2107, 0.3715, 0.5289, 0.6651, 0.8420, 1.1168, 1.4401, 1.7230, + 1.9901, 2.2687, 2.5452, 2.8655, 0.1218, 0.2999, 0.6348, 0.9482, + 1.2745, 1.5876, 1.9129, 2.2348, 2.4020, 2.4922, 2.6351, 2.8357, + 0.1617, 0.3483, 0.5869, 0.8163, 1.0366, 1.2344, 1.4609, 1.7029, + 1.9476, 2.2337, 2.5258, 2.8442, 0.2505, 0.4894, 0.7510, 0.9152, + 1.0845, 1.3657, 1.6528, 1.8346, 2.0160, 2.2811, 2.5338, 2.8136, + 0.0947, 0.1158, 0.0578, -0.0337, -0.0066, 0.0104, -0.0447, -0.0505, +-0.0778, -0.0293, 0.0251, -0.0143, 0.0349, -0.0227, -0.0909, 0.0523, + 0.0325, -0.0410, -0.1045, -0.0899, -0.0009, 0.0075, -0.0575, -0.0855, +-0.0129, 0.0575, 0.0597, 0.0391, 0.0371, -0.0184, -0.0083, 0.0287, + 0.0143, 0.0167, 0.0120, -0.0168, 0.0452, 0.0223, -0.0352, 0.0119, +-0.0496, -0.0965, -0.0661, -0.0072, 0.1099, 0.0843, -0.0087, -0.0478, +-0.0128, -0.0120, -0.0004, 0.0731, 0.1047, 0.0630, 0.0196, -0.0103, +-0.0399, -0.0986, -0.0912, -0.0390, -0.0247, -0.0694, -0.0749, -0.0066, + 0.0223, 0.0634, 0.0343, -0.0134, 0.0727, 0.0241, 0.0066, 0.0437, + 0.0610, 0.0364, 0.0248, -0.0358, -0.0686, -0.0104, 0.0426, 0.0088, +-0.0137, -0.0165, 0.0671, 0.0815, -0.0863, -0.0644, -0.0088, 0.0023, + 0.0482, 0.1174, 0.1270, 0.0594, 0.0165, 0.0949, 0.1098, 0.0137, + 0.4951, 0.4999, 0.4958, 0.4907, 0.4984, 0.4965, 0.4958, 0.4996, + 0.4987, 0.4958, 0.4986, 0.4977, 0.2841, 0.2186, 0.1474, 0.1687, + 0.2217, 0.2632, 0.2706, 0.2624, 0.2162, 0.2453, 0.2460, 0.2531 +}, + +.lsp11 = { + 0.1103, 0.3862, 0.6863, 0.8447, 0.9231, 1.0261, 1.1248, 1.4057, + 1.6621, 1.8010, 1.8692, 2.0704, 2.3490, 2.6060, 2.7539, 2.8977, + 0.1273, 0.2407, 0.3812, 0.6004, 0.7767, 0.9383, 1.1344, 1.3351, + 1.5233, 1.7262, 1.9466, 2.1739, 2.3495, 2.5162, 2.7164, 2.9202, + 0.2010, 0.3330, 0.4488, 0.6465, 0.8046, 0.9889, 1.1479, 1.2964, + 1.4770, 1.6606, 1.8789, 2.1155, 2.3287, 2.5199, 2.7101, 2.9119, + 0.1168, 0.2197, 0.3279, 0.4691, 0.6268, 0.8251, 1.0533, 1.2714, + 1.4712, 1.6762, 1.8831, 2.1114, 2.3230, 2.5297, 2.7365, 2.9270, + 0.1405, 0.3109, 0.4986, 0.6891, 0.8634, 1.0583, 1.2594, 1.4349, + 1.6232, 1.8116, 1.9905, 2.1935, 2.3799, 2.5656, 2.7661, 2.9486, + 0.1703, 0.3057, 0.4403, 0.5225, 0.5969, 0.8110, 1.0729, 1.3215, + 1.5407, 1.7381, 1.9477, 2.1680, 2.3586, 2.5612, 2.7630, 2.9410, + 0.1128, 0.2628, 0.4523, 0.6495, 0.8176, 0.9816, 1.1746, 1.3710, + 1.5568, 1.7518, 1.9497, 2.1452, 2.3346, 2.5389, 2.7362, 2.9264, + 0.1809, 0.3287, 0.5205, 0.7264, 0.9298, 1.1217, 1.2970, 1.4894, + 1.6874, 1.8493, 2.0576, 2.2382, 2.4097, 2.6041, 2.7796, 2.9389, + 0.2502, 0.4709, 0.6892, 0.8346, 0.9209, 1.0455, 1.2399, 1.4616, + 1.6463, 1.8380, 2.0475, 2.2397, 2.4665, 2.6550, 2.7701, 2.8895, + 0.1040, 0.2340, 0.3964, 0.5740, 0.7764, 0.9941, 1.2000, 1.4014, + 1.6024, 1.7974, 1.9939, 2.1959, 2.3783, 2.5663, 2.7613, 2.9484, + 0.1912, 0.3393, 0.4743, 0.6313, 0.8014, 0.9879, 1.1855, 1.3922, + 1.5678, 1.7289, 1.9271, 2.1165, 2.3089, 2.5414, 2.7448, 2.9269, + 0.0965, 0.2025, 0.3398, 0.4990, 0.6934, 0.9386, 1.1730, 1.3766, + 1.5783, 1.7783, 1.9790, 2.1831, 2.3670, 2.5578, 2.7641, 2.9516, + 0.2126, 0.3652, 0.5545, 0.7170, 0.8674, 1.0640, 1.2558, 1.4061, + 1.5904, 1.8095, 1.9760, 2.1505, 2.3549, 2.5575, 2.7023, 2.8877, + 0.1827, 0.3426, 0.4894, 0.6488, 0.7960, 0.9535, 1.1217, 1.2798, + 1.4566, 1.6453, 1.8044, 2.0042, 2.2379, 2.4611, 2.6697, 2.8966, + 0.2034, 0.3822, 0.5231, 0.6960, 0.9200, 1.0394, 1.1616, 1.3772, + 1.5493, 1.7330, 1.9646, 2.1233, 2.3334, 2.5361, 2.7087, 2.9470, + 0.1050, 0.2060, 0.3705, 0.5998, 0.8337, 1.0577, 1.2559, 1.4327, + 1.6334, 1.8165, 1.9853, 2.2058, 2.4063, 2.5818, 2.7625, 2.9458, + 0.1419, 0.4053, 0.6660, 0.8911, 1.0405, 1.1547, 1.2506, 1.3926, + 1.5669, 1.7527, 1.9694, 2.2054, 2.3889, 2.5743, 2.7586, 2.9174, + 0.1514, 0.2825, 0.4309, 0.5772, 0.7470, 0.9703, 1.1462, 1.3316, + 1.5321, 1.7259, 1.9282, 2.1266, 2.3106, 2.5064, 2.7067, 2.9094, + 0.1693, 0.3156, 0.4878, 0.6635, 0.8206, 0.9569, 1.1154, 1.3064, + 1.5109, 1.7184, 1.9179, 2.1036, 2.2763, 2.4820, 2.6949, 2.9105, + 0.1432, 0.2718, 0.4241, 0.5564, 0.6939, 0.9011, 1.1582, 1.3948, + 1.6181, 1.8024, 1.9814, 2.1740, 2.3459, 2.5456, 2.7491, 2.9307, + 0.2294, 0.3857, 0.5590, 0.7434, 0.9189, 1.0941, 1.2740, 1.4456, + 1.6178, 1.7994, 1.9689, 2.1644, 2.3525, 2.5385, 2.7468, 2.9405, + 0.1667, 0.3109, 0.4612, 0.6032, 0.7375, 0.8866, 1.0840, 1.3053, + 1.4982, 1.7044, 1.9146, 2.1117, 2.2942, 2.4983, 2.7084, 2.9132, + 0.1810, 0.3205, 0.4696, 0.6231, 0.7641, 0.9959, 1.2427, 1.4361, + 1.5889, 1.7544, 1.9083, 2.0733, 2.2457, 2.4461, 2.6793, 2.9098, + 0.1164, 0.3753, 0.6068, 0.7503, 1.0100, 1.2131, 1.3793, 1.5302, + 1.6300, 1.7950, 1.9057, 2.1031, 2.3830, 2.5745, 2.6949, 2.8779, + 0.1571, 0.4378, 0.6735, 0.8312, 0.8944, 0.9818, 1.1622, 1.4094, + 1.6423, 1.8066, 1.9258, 2.1838, 2.4363, 2.6279, 2.7358, 2.8790, + 0.1398, 0.2686, 0.4248, 0.6156, 0.7870, 1.0035, 1.2012, 1.3689, + 1.5363, 1.7398, 1.9604, 2.1619, 2.3345, 2.5097, 2.7271, 2.9368, + 0.1913, 0.3338, 0.4987, 0.6446, 0.7852, 1.0163, 1.1886, 1.3610, + 1.5379, 1.7230, 1.8880, 2.0862, 2.2960, 2.4928, 2.7122, 2.9151, + 0.0908, 0.1752, 0.2899, 0.5365, 0.7761, 1.0100, 1.2124, 1.4060, + 1.6019, 1.8010, 1.9774, 2.1905, 2.3733, 2.5623, 2.7660, 2.9565, + 0.1773, 0.3179, 0.4925, 0.6864, 0.8452, 0.9897, 1.1860, 1.3722, + 1.5515, 1.7658, 1.9802, 2.1819, 2.3620, 2.5442, 2.7250, 2.9220, + 0.1286, 0.2341, 0.3689, 0.5364, 0.7176, 0.9350, 1.1083, 1.2943, + 1.4974, 1.7059, 1.9047, 2.1145, 2.3242, 2.5361, 2.7453, 2.9329, + 0.2273, 0.3834, 0.5565, 0.7192, 0.8431, 0.9962, 1.1763, 1.3571, + 1.5774, 1.7419, 1.9202, 2.1131, 2.2919, 2.4898, 2.6895, 2.9180, + 0.1775, 0.3058, 0.4274, 0.6023, 0.8151, 1.0734, 1.3211, 1.5178, + 1.6706, 1.8154, 1.9686, 2.1537, 2.3461, 2.5276, 2.7181, 2.9121, + 0.1653, 0.4304, 0.6361, 0.7824, 0.9183, 1.0452, 1.2071, 1.4077, + 1.6206, 1.8299, 2.0089, 2.1948, 2.3900, 2.5982, 2.7844, 2.9487, + 0.1492, 0.2609, 0.3820, 0.5485, 0.7243, 0.9319, 1.1538, 1.3579, + 1.5266, 1.7002, 1.8873, 2.1016, 2.3175, 2.5221, 2.7241, 2.9243, + 0.2074, 0.3781, 0.5209, 0.6869, 0.8577, 0.9875, 1.1849, 1.3568, + 1.4907, 1.7335, 1.8902, 2.1224, 2.3099, 2.4918, 2.7023, 2.8765, + 0.1359, 0.2254, 0.3286, 0.4432, 0.6586, 0.8964, 1.1125, 1.3523, + 1.5626, 1.7579, 1.9846, 2.1905, 2.3548, 2.5542, 2.7663, 2.9346, + 0.1430, 0.2966, 0.4685, 0.6493, 0.8315, 1.0304, 1.2220, 1.4082, + 1.5995, 1.7888, 1.9774, 2.1737, 2.3607, 2.5577, 2.7558, 2.9405, + 0.1477, 0.2694, 0.4056, 0.5626, 0.7051, 0.8647, 1.0491, 1.2488, + 1.4814, 1.7072, 1.9150, 2.1147, 2.3038, 2.5144, 2.7184, 2.9202, + 0.1690, 0.3033, 0.4580, 0.6686, 0.8536, 1.0293, 1.2124, 1.3998, + 1.5718, 1.7607, 1.9580, 2.1245, 2.2971, 2.4762, 2.6896, 2.9177, + 0.1092, 0.2779, 0.4853, 0.6880, 0.9011, 1.0953, 1.2752, 1.4618, + 1.6623, 1.8484, 2.0264, 2.2152, 2.4017, 2.5835, 2.7671, 2.9436, + 0.1497, 0.3637, 0.6014, 0.8032, 0.9963, 1.1835, 1.3741, 1.5698, + 1.7382, 1.9094, 2.0710, 2.2392, 2.4082, 2.5926, 2.7762, 2.9536, + 0.1434, 0.2492, 0.3966, 0.5934, 0.8033, 1.0657, 1.2796, 1.4276, + 1.5745, 1.7833, 1.9288, 2.1247, 2.3543, 2.5412, 2.7049, 2.8872, + 0.1612, 0.2926, 0.4574, 0.6387, 0.8265, 1.0180, 1.1808, 1.3526, + 1.5564, 1.7536, 1.9187, 2.1192, 2.3149, 2.5006, 2.7101, 2.9217, + 0.0828, 0.1863, 0.3235, 0.5050, 0.7250, 0.9867, 1.2093, 1.3941, + 1.5980, 1.7932, 1.9809, 2.1894, 2.3918, 2.5773, 2.7540, 2.9329, + 0.2001, 0.3655, 0.5290, 0.6761, 0.8027, 0.9972, 1.2090, 1.4255, + 1.6085, 1.7825, 1.9804, 2.1681, 2.3457, 2.5325, 2.7319, 2.9196, + 0.1505, 0.2767, 0.4254, 0.6054, 0.7821, 0.9567, 1.1294, 1.3080, + 1.4984, 1.6954, 1.8666, 2.0736, 2.2875, 2.4969, 2.7072, 2.9163, + 0.1589, 0.4151, 0.5749, 0.6651, 0.8061, 1.0470, 1.2616, 1.3690, + 1.4985, 1.7808, 1.9825, 2.1068, 2.2751, 2.5448, 2.7133, 2.8689, + 0.0916, 0.1846, 0.3788, 0.6329, 0.8774, 1.0687, 1.2653, 1.4561, + 1.6573, 1.8449, 2.0402, 2.2254, 2.3968, 2.5861, 2.7792, 2.9508, + 0.2282, 0.4159, 0.5834, 0.6899, 0.8108, 1.0321, 1.2795, 1.5262, + 1.6936, 1.8469, 2.0922, 2.2607, 2.3795, 2.5301, 2.7386, 2.9530, + 0.1651, 0.3004, 0.4555, 0.6179, 0.7891, 0.9584, 1.1372, 1.3707, + 1.5951, 1.7880, 1.9434, 2.1465, 2.3311, 2.5081, 2.6977, 2.8970, + 0.1279, 0.3828, 0.6330, 0.8323, 0.9652, 1.1175, 1.2319, 1.3511, + 1.5115, 1.6392, 1.7835, 1.9558, 2.2008, 2.4635, 2.6910, 2.9058, + 0.1193, 0.2185, 0.3521, 0.5311, 0.7378, 0.9239, 1.1105, 1.3217, + 1.5362, 1.7504, 1.9536, 2.1627, 2.3560, 2.5506, 2.7548, 2.9453, + 0.1806, 0.3432, 0.4981, 0.6948, 0.8928, 1.0527, 1.2467, 1.4140, + 1.6326, 1.7950, 1.9935, 2.1969, 2.3512, 2.5682, 2.7445, 2.9277, + 0.1846, 0.3112, 0.4568, 0.5891, 0.7317, 0.8493, 1.0204, 1.2022, + 1.3688, 1.6020, 1.8428, 2.0710, 2.2725, 2.4879, 2.7057, 2.9160, + 0.0880, 0.2514, 0.5332, 0.7272, 0.8906, 1.1354, 1.3199, 1.4941, + 1.6010, 1.7151, 1.8712, 2.0643, 2.2755, 2.5375, 2.7054, 2.8891, + 0.1382, 0.2833, 0.4658, 0.6897, 0.9071, 1.0716, 1.2469, 1.4143, + 1.5910, 1.7947, 1.9805, 2.1581, 2.3338, 2.5215, 2.7292, 2.9211, + 0.1061, 0.3494, 0.6327, 0.8570, 0.9748, 1.0560, 1.1529, 1.3250, + 1.6032, 1.8340, 1.9711, 2.1157, 2.3011, 2.5464, 2.8078, 2.9803, + 0.1603, 0.2839, 0.4307, 0.5980, 0.7980, 1.0399, 1.1971, 1.3524, + 1.5715, 1.7838, 1.9468, 2.1498, 2.3627, 2.5514, 2.7327, 2.9148, + 0.1691, 0.3117, 0.4796, 0.6895, 0.8732, 1.0164, 1.1916, 1.3707, + 1.5384, 1.7202, 1.8857, 2.0672, 2.2487, 2.4593, 2.6789, 2.8940, + 0.0965, 0.1702, 0.3191, 0.5721, 0.8100, 1.0241, 1.2272, 1.4196, + 1.6093, 1.8057, 1.9884, 2.2037, 2.3925, 2.5805, 2.7578, 2.9366, + 0.1950, 0.3519, 0.5272, 0.6973, 0.8732, 1.0656, 1.2112, 1.3959, + 1.6116, 1.7821, 1.9445, 2.1592, 2.3348, 2.5142, 2.7440, 2.9297, + 0.1388, 0.2557, 0.4120, 0.5727, 0.7354, 0.9196, 1.0985, 1.2805, + 1.4643, 1.6535, 1.8340, 2.0546, 2.2758, 2.4778, 2.6921, 2.9122, + 0.1823, 0.3336, 0.4957, 0.6771, 0.8563, 1.0137, 1.2299, 1.3849, + 1.5718, 1.7667, 1.9193, 2.1326, 2.3135, 2.5268, 2.7133, 2.8998, + 0.0790, 0.1901, 0.4083, 0.6456, 0.8463, 1.0285, 1.2297, 1.4181, + 1.6159, 1.8056, 1.9971, 2.1912, 2.3816, 2.5746, 2.7692, 2.9497, + 0.0049, 0.0116, 0.0045, 0.0039, -0.0010, -0.0122, -0.0205, -0.0034, +-0.0140, -0.0041, 0.0191, -0.0322, 0.0002, -0.0124, -0.0269, 0.0059, + 0.0586, 0.0339, -0.0389, -0.0319, -0.0079, -0.0205, -0.0363, -0.0211, + 0.0241, 0.0595, 0.0469, 0.0283, 0.0176, -0.0183, -0.0173, -0.0004, + 0.0024, 0.0145, 0.0534, 0.0197, -0.0065, -0.0067, 0.0133, 0.0358, +-0.0104, -0.0386, -0.0109, -0.0078, 0.0275, 0.0565, 0.0251, -0.0027, +-0.0053, 0.0171, 0.0088, 0.0495, 0.0141, 0.0039, -0.0445, -0.0426, +-0.0184, -0.0280, -0.0223, 0.0039, -0.0171, -0.0606, -0.0786, -0.0430, + 0.0544, 0.0595, 0.0320, -0.0012, 0.0108, 0.0185, 0.0066, 0.0408, + 0.0552, -0.0073, -0.0247, -0.0480, -0.0288, 0.0186, 0.0212, -0.0013, + 0.0403, 0.0598, 0.0690, 0.0516, -0.0298, -0.0177, 0.0278, 0.0168, +-0.0106, 0.0251, 0.0386, 0.0331, -0.0052, 0.0133, 0.0291, -0.0158, +-0.0329, -0.0367, 0.0287, 0.0462, -0.0176, 0.0049, 0.0242, -0.0034, + 0.0135, 0.0086, -0.0149, 0.0241, 0.0504, 0.0246, -0.0273, -0.0369, +-0.0108, -0.0449, -0.0625, -0.0414, -0.0292, -0.0571, -0.0440, -0.0088, + 0.0098, 0.0009, -0.0004, 0.0007, -0.0314, -0.0208, -0.0138, -0.0277, +-0.0044, 0.0522, 0.0315, -0.0270, -0.0277, -0.0256, -0.0103, -0.0201, +-0.0287, -0.0279, -0.0182, 0.0472, 0.0613, 0.0450, 0.0413, 0.0333, + 0.0444, 0.0223, 0.0061, 0.0316, 0.0321, 0.0501, 0.0460, 0.0250, + 0.0227, 0.0235, 0.0099, 0.0185, -0.0347, -0.0684, -0.0189, 0.0242, +-0.0190, -0.0273, -0.0012, -0.0253, 0.0293, -0.0231, -0.0219, -0.0010, + 0.0153, 0.0128, -0.0166, -0.0435, -0.0417, -0.0121, -0.0351, -0.0390, + 0.0077, -0.0278, -0.0355, 0.0092, -0.0063, 0.0005, 0.0216, 0.0461, + 0.0538, 0.0451, 0.0298, -0.0130, 0.0058, 0.0206, 0.0471, 0.0499, + 0.0280, 0.0086, -0.0007, -0.0317, 0.0259, 0.0176, 0.0043, 0.0212, + 0.0138, 0.0106, 0.0220, -0.0025, 0.0050, 0.0122, -0.0051, -0.0086, +-0.0472, -0.0005, 0.0193, 0.0032, 0.0246, 0.0222, 0.0090, -0.0320, +-0.0713, -0.0526, -0.0151, -0.0440, -0.0648, -0.0466, -0.0092, 0.0115, +-0.0129, 0.0053, -0.0344, -0.0385, 0.0392, 0.0599, 0.0414, 0.0165, +-0.0098, -0.0320, -0.0261, -0.0055, -0.0139, -0.0110, 0.0084, 0.0172, +-0.0492, -0.0537, -0.0320, -0.0036, 0.0265, 0.0385, 0.0064, -0.0280, +-0.0230, 0.0134, 0.0241, 0.0106, 0.0387, 0.0105, 0.0068, 0.0260, + 0.4940, 0.4911, 0.4849, 0.4820, 0.4837, 0.4839, 0.4824, 0.4799, + 0.4812, 0.4782, 0.4788, 0.4711, 0.4706, 0.4671, 0.4601, 0.4578, + 0.2954, 0.2121, 0.1859, 0.1958, 0.1474, 0.1086, 0.1351, 0.1362, + 0.1486, 0.1342, 0.1215, 0.1423, 0.1634, 0.1588, 0.1539, 0.1857 +}, + +.lsp16 = { + 0.1813, 0.3911, 0.6301, 0.8012, 1.0057, 1.2041, 1.4271, 1.6943, + 1.9402, 2.1733, 2.3521, 2.4989, 2.5839, 2.6846, 2.7634, 2.8950, + 0.1311, 0.3183, 0.4659, 0.5601, 0.6658, 0.7828, 1.0065, 1.2717, + 1.5185, 1.7339, 1.9530, 2.2189, 2.3739, 2.4991, 2.6984, 2.9256, + 0.1627, 0.4519, 0.6323, 0.7012, 0.7848, 0.9801, 1.1810, 1.3222, + 1.5413, 1.8129, 1.9338, 2.0809, 2.3180, 2.5189, 2.7066, 2.9514, + 0.1475, 0.2447, 0.4240, 0.5669, 0.7872, 0.9838, 1.1823, 1.3814, + 1.5358, 1.6820, 1.8794, 2.1419, 2.4132, 2.6112, 2.7911, 2.9511, + 0.1224, 0.2876, 0.5013, 0.6985, 0.8902, 1.0901, 1.2835, 1.4768, + 1.6596, 1.8538, 2.0467, 2.2304, 2.4124, 2.5942, 2.7729, 2.9531, + 0.1741, 0.3034, 0.4677, 0.5879, 0.7258, 0.9648, 1.1417, 1.3220, + 1.5081, 1.7151, 1.9212, 2.1286, 2.3208, 2.4938, 2.6765, 2.8891, + 0.1657, 0.3174, 0.4907, 0.6559, 0.8295, 1.0254, 1.2071, 1.3880, + 1.5737, 1.7845, 1.9027, 2.1139, 2.3323, 2.5157, 2.7323, 2.9015, + 0.1592, 0.2758, 0.4417, 0.6315, 0.8257, 0.9873, 1.1277, 1.2830, + 1.4337, 1.6315, 1.8899, 2.1356, 2.3572, 2.5632, 2.7468, 2.9420, + 0.1524, 0.4325, 0.5931, 0.7036, 0.7696, 0.8923, 1.1739, 1.4773, + 1.6609, 1.7911, 1.9666, 2.1972, 2.3754, 2.5045, 2.6613, 2.8882, + 0.2130, 0.3013, 0.3721, 0.4257, 0.5079, 0.7015, 0.9815, 1.2554, + 1.4648, 1.6966, 1.9138, 2.1075, 2.3318, 2.5292, 2.7453, 2.9347, + 0.1142, 0.3748, 0.6205, 0.7642, 0.8121, 0.9022, 0.9843, 1.1558, + 1.4467, 1.7422, 1.9574, 2.1302, 2.3812, 2.5898, 2.7720, 2.9583, + 0.1255, 0.2339, 0.3570, 0.5323, 0.7458, 1.0003, 1.1729, 1.3567, + 1.5217, 1.6977, 1.8924, 2.0942, 2.3145, 2.5408, 2.7553, 2.9337, + 0.1316, 0.2289, 0.4327, 0.6663, 0.8509, 0.9994, 1.1697, 1.3804, + 1.5609, 1.6903, 1.8572, 2.1019, 2.3687, 2.5789, 2.7715, 2.9472, + 0.1502, 0.2546, 0.3883, 0.5333, 0.6976, 0.9163, 1.1071, 1.3364, + 1.5420, 1.7525, 1.8948, 2.0839, 2.2819, 2.4651, 2.6875, 2.8987, + 0.1593, 0.3014, 0.4573, 0.6354, 0.8157, 0.9805, 1.1783, 1.3747, + 1.5678, 1.7326, 1.9286, 2.1340, 2.3253, 2.5280, 2.7180, 2.9298, + 0.1811, 0.3167, 0.4655, 0.6507, 0.8198, 1.0075, 1.1892, 1.3743, + 1.5227, 1.7090, 1.8849, 2.0743, 2.2750, 2.4830, 2.6896, 2.8953, + 0.1846, 0.3577, 0.5315, 0.7290, 0.9176, 1.1016, 1.2654, 1.4525, + 1.6315, 1.8268, 2.0238, 2.1934, 2.3868, 2.5753, 2.7682, 2.9469, + 0.0876, 0.1439, 0.2048, 0.3654, 0.6281, 0.8853, 1.0907, 1.2992, + 1.5227, 1.7373, 1.9395, 2.1419, 2.3488, 2.5486, 2.7466, 2.9348, + 0.1391, 0.4170, 0.6561, 0.7953, 0.8734, 0.9986, 1.1870, 1.4520, + 1.6042, 1.7910, 2.0135, 2.1870, 2.3358, 2.5066, 2.7409, 2.9955, + 0.0804, 0.1355, 0.2599, 0.4998, 0.7408, 0.9474, 1.1276, 1.3428, + 1.5556, 1.7712, 1.9699, 2.1535, 2.3605, 2.5548, 2.7489, 2.9325, + 0.1304, 0.3087, 0.4979, 0.6584, 0.8414, 1.0329, 1.2244, 1.4189, + 1.6118, 1.8200, 1.9985, 2.1893, 2.3915, 2.5794, 2.7647, 2.9344, + 0.1895, 0.2849, 0.3705, 0.4126, 0.6265, 0.9207, 1.1774, 1.3762, + 1.5757, 1.7728, 1.9568, 2.1662, 2.3615, 2.5575, 2.7561, 2.9416, + 0.1800, 0.3078, 0.4805, 0.6796, 0.8503, 1.0046, 1.1703, 1.3269, + 1.4862, 1.6502, 1.8454, 2.0873, 2.3175, 2.5356, 2.7516, 2.9469, + 0.1950, 0.3233, 0.4568, 0.5940, 0.7589, 0.9978, 1.1701, 1.3383, + 1.5017, 1.6565, 1.8243, 2.0605, 2.2938, 2.5147, 2.7419, 2.9396, + 0.2531, 0.4391, 0.5790, 0.7170, 0.8998, 1.1430, 1.3577, 1.5326, + 1.6328, 1.7627, 1.9726, 2.1762, 2.3563, 2.5478, 2.7385, 2.9067, + 0.1805, 0.2788, 0.3591, 0.3881, 0.5441, 0.8055, 1.0766, 1.3165, + 1.5316, 1.7508, 1.9477, 2.1374, 2.3438, 2.5484, 2.7501, 2.9410, + 0.2044, 0.3671, 0.5396, 0.7042, 0.8582, 0.9831, 1.1261, 1.3194, + 1.4769, 1.6979, 1.8717, 2.0463, 2.2620, 2.4739, 2.7054, 2.9208, + 0.1048, 0.2175, 0.4206, 0.5923, 0.7483, 0.9400, 1.1356, 1.3799, + 1.5958, 1.7320, 1.8984, 2.1296, 2.3594, 2.5492, 2.7387, 2.9305, + 0.0842, 0.1729, 0.3951, 0.6447, 0.8688, 1.0605, 1.2472, 1.4330, + 1.6232, 1.8144, 2.0216, 2.1915, 2.3878, 2.5763, 2.7685, 2.9464, + 0.1461, 0.2593, 0.4105, 0.5677, 0.7328, 0.8919, 1.0484, 1.2302, + 1.4386, 1.6635, 1.8873, 2.1024, 2.3116, 2.5268, 2.7273, 2.9269, + 0.1503, 0.3108, 0.4756, 0.6731, 0.8600, 1.0233, 1.2115, 1.3971, + 1.5915, 1.7892, 1.9517, 2.1603, 2.3487, 2.5460, 2.7308, 2.8998, + 0.2163, 0.3669, 0.5125, 0.6709, 0.8143, 0.9930, 1.2095, 1.4205, + 1.6176, 1.7112, 1.8398, 2.0896, 2.3513, 2.5290, 2.6667, 2.8960, + 0.2133, 0.4382, 0.6287, 0.8702, 1.1088, 1.3749, 1.6062, 1.7446, + 1.8333, 1.9122, 1.9614, 2.0669, 2.1789, 2.3449, 2.6038, 2.8849, + 0.1598, 0.2719, 0.3877, 0.4815, 0.5926, 0.7795, 1.0449, 1.3045, + 1.5210, 1.7391, 1.9462, 2.1397, 2.3553, 2.5458, 2.7540, 2.9392, + 0.2918, 0.5607, 0.6801, 0.7404, 0.8285, 0.9431, 1.1579, 1.4080, + 1.6332, 1.8472, 1.9738, 2.0771, 2.2890, 2.5178, 2.7445, 2.9830, + 0.1664, 0.2842, 0.3965, 0.5463, 0.8162, 1.0346, 1.1849, 1.3446, + 1.5122, 1.7563, 1.9960, 2.2002, 2.3796, 2.5689, 2.7712, 2.9550, + 0.0911, 0.2397, 0.5052, 0.7868, 1.0299, 1.1311, 1.2244, 1.3333, + 1.4395, 1.6790, 1.9369, 2.1717, 2.3689, 2.5538, 2.7340, 2.9326, + 0.1647, 0.2931, 0.3836, 0.4978, 0.6255, 0.9243, 1.1339, 1.3001, + 1.5269, 1.8010, 1.9715, 2.1419, 2.3784, 2.5503, 2.6719, 2.8745, + 0.2440, 0.3802, 0.4756, 0.6613, 0.8627, 1.0292, 1.2291, 1.4060, + 1.5198, 1.7354, 1.9044, 2.1010, 2.3147, 2.4996, 2.7171, 2.9041, + 0.1590, 0.2876, 0.4572, 0.5996, 0.7713, 0.9490, 1.1205, 1.2815, + 1.4516, 1.6385, 1.8179, 2.0457, 2.2759, 2.4785, 2.6861, 2.9080, + 0.2297, 0.4309, 0.5712, 0.6717, 0.8138, 1.0463, 1.2492, 1.4560, + 1.6796, 1.8458, 1.9642, 2.1452, 2.3636, 2.5395, 2.7456, 2.9495, + 0.2975, 0.4678, 0.4996, 0.5809, 0.6279, 0.6884, 0.8606, 1.1386, + 1.4412, 1.6876, 1.8760, 2.0932, 2.3178, 2.5166, 2.7345, 2.9280, + 0.1278, 0.3737, 0.6004, 0.7069, 0.8147, 1.0180, 1.2581, 1.3812, + 1.4855, 1.7268, 1.9970, 2.1258, 2.2936, 2.5702, 2.7563, 2.8983, + 0.1314, 0.2508, 0.3999, 0.5680, 0.7424, 0.9367, 1.1286, 1.3175, + 1.5336, 1.7404, 1.9317, 2.1404, 2.3514, 2.5562, 2.7510, 2.9402, + 0.1043, 0.2367, 0.4293, 0.6376, 0.8160, 0.9836, 1.1779, 1.3850, + 1.5835, 1.7875, 1.9765, 2.1593, 2.3654, 2.5577, 2.7465, 2.9398, + 0.1529, 0.2515, 0.3454, 0.4374, 0.7011, 0.9015, 1.0744, 1.3532, + 1.5699, 1.7545, 2.0021, 2.1259, 2.2278, 2.4546, 2.7264, 2.9425, + 0.1429, 0.2808, 0.4395, 0.6334, 0.8069, 0.9705, 1.1520, 1.3250, + 1.5109, 1.7285, 1.9356, 2.1469, 2.3479, 2.5554, 2.7512, 2.9348, + 0.1625, 0.3022, 0.4756, 0.6315, 0.8032, 0.9924, 1.1596, 1.3204, + 1.4994, 1.6929, 1.8955, 2.1090, 2.3025, 2.5018, 2.6908, 2.8980, + 0.1692, 0.3427, 0.5228, 0.7756, 0.9688, 1.0950, 1.3056, 1.4360, + 1.5675, 1.8049, 1.9376, 2.1151, 2.3407, 2.5012, 2.7192, 2.9258, + 0.0474, 0.1251, 0.1939, 0.3841, 0.6501, 0.9231, 1.1153, 1.3240, + 1.5478, 1.7599, 1.9651, 2.1510, 2.3645, 2.5552, 2.7542, 2.9393, + 0.2196, 0.4656, 0.7492, 0.9922, 1.1678, 1.2489, 1.3112, 1.3657, + 1.4223, 1.5302, 1.7212, 1.9996, 2.2523, 2.4844, 2.7036, 2.9145, + 0.1128, 0.2368, 0.3704, 0.5476, 0.7723, 0.9968, 1.1930, 1.3992, + 1.6013, 1.7957, 1.9888, 2.1857, 2.3825, 2.5705, 2.7616, 2.9434, + 0.1341, 0.2768, 0.4510, 0.6359, 0.8332, 1.0335, 1.2004, 1.3952, + 1.5762, 1.7681, 1.9815, 2.1735, 2.3657, 2.5552, 2.7514, 2.9498, + 0.1247, 0.2559, 0.3516, 0.4726, 0.6861, 0.9483, 1.1852, 1.3858, + 1.5851, 1.7815, 1.9778, 2.1737, 2.3729, 2.5664, 2.7620, 2.9429, + 0.1988, 0.3320, 0.4777, 0.6737, 0.8425, 1.0265, 1.1694, 1.3655, + 1.5463, 1.7135, 1.9385, 2.1650, 2.3529, 2.5367, 2.7545, 2.9585, + 0.1376, 0.2620, 0.4273, 0.6169, 0.7755, 0.9441, 1.1169, 1.3157, + 1.5179, 1.7020, 1.8931, 2.1059, 2.3112, 2.5136, 2.7169, 2.9198, + 0.2112, 0.4385, 0.6091, 0.7618, 0.9553, 1.1543, 1.3445, 1.5396, + 1.7153, 1.9192, 2.1263, 2.3593, 2.5958, 2.8171, 2.9394, 3.0409, + 0.1347, 0.2099, 0.2646, 0.3453, 0.5266, 0.7869, 1.0513, 1.2795, + 1.4880, 1.7181, 1.9294, 2.1332, 2.3362, 2.5442, 2.7433, 2.9362, + 0.3141, 0.5935, 0.7517, 0.8313, 0.8568, 0.9570, 1.0250, 1.1275, + 1.3422, 1.6303, 1.8577, 2.0705, 2.2957, 2.5095, 2.7244, 2.9262, + 0.0962, 0.2116, 0.3961, 0.5641, 0.7122, 0.8883, 1.1023, 1.3481, + 1.5623, 1.7554, 1.9618, 2.1675, 2.3706, 2.5556, 2.7430, 2.9337, + 0.0898, 0.1510, 0.3060, 0.5820, 0.8221, 1.0388, 1.2261, 1.4289, + 1.6054, 1.8103, 1.9941, 2.1844, 2.3742, 2.5711, 2.7632, 2.9474, + 0.1326, 0.2316, 0.3761, 0.5177, 0.6782, 0.8761, 1.0952, 1.3175, + 1.5078, 1.7034, 1.9051, 2.1245, 2.3424, 2.5484, 2.7444, 2.9389, + 0.1740, 0.3293, 0.5174, 0.6824, 0.8394, 1.0372, 1.2046, 1.3723, + 1.5656, 1.7444, 1.9442, 2.1386, 2.3139, 2.4960, 2.7071, 2.9297, + 0.2304, 0.3775, 0.4865, 0.6182, 0.7842, 0.9208, 1.1151, 1.2843, + 1.4641, 1.6988, 1.9209, 2.1260, 2.3099, 2.5229, 2.7414, 2.9276, + 0.0094, 0.0261, -0.0037, 0.0041, -0.0092, -0.0044, -0.0232, -0.0073, +-0.0047, -0.0021, 0.0250, -0.0580, -0.0140, -0.0342, -0.0586, 0.0020, + 0.0449, 0.0155, -0.0523, -0.0279, 0.0299, -0.0183, -0.0736, -0.0639, +-0.0017, 0.0336, 0.0209, 0.0046, 0.0077, -0.0148, -0.0114, -0.0120, + 0.0115, -0.0050, 0.0445, 0.0048, 0.0188, -0.0137, -0.0080, 0.0239, +-0.0184, -0.0524, -0.0195, -0.0126, 0.0284, 0.0632, 0.0141, -0.0093, +-0.0096, 0.0196, 0.0230, 0.0379, 0.0308, 0.0237, -0.0224, -0.0600, +-0.0755, -0.1074, -0.0988, -0.0606, -0.1038, -0.1552, -0.1480, -0.0672, + 0.0504, 0.0676, 0.0336, -0.0042, 0.0729, 0.1013, 0.0868, 0.0846, + 0.0954, 0.0515, -0.0066, -0.0851, -0.0485, 0.0294, 0.0395, 0.0087, + 0.0078, 0.0446, 0.0881, 0.0672, -0.0384, -0.0025, 0.0415, 0.0353, + 0.0080, 0.0052, 0.0190, 0.0182, 0.0069, 0.0168, 0.0374, 0.0037, +-0.0292, -0.0429, 0.0302, 0.0681, -0.0233, -0.0238, -0.0003, -0.0043, + 0.0054, -0.0029, -0.0149, 0.0642, 0.0622, 0.0341, -0.0232, -0.0461, +-0.0082, -0.0469, -0.0618, -0.0326, -0.0452, -0.0649, -0.0597, -0.0398, +-0.0318, -0.0116, 0.0011, 0.0009, -0.0384, -0.0384, -0.0156, -0.0260, +-0.0007, 0.0473, 0.0111, -0.0358, -0.0484, -0.0204, -0.0029, -0.0090, +-0.0285, -0.0495, -0.0376, 0.0917, 0.1192, 0.1026, 0.0745, 0.0397, + 0.0463, 0.0253, 0.0025, 0.0465, 0.0100, 0.0488, 0.0416, 0.0223, + 0.0263, 0.0072, -0.0053, 0.0595, 0.0060, -0.0518, -0.0316, -0.0043, +-0.0133, -0.0233, -0.0075, -0.0251, 0.0277, -0.0067, -0.0136, -0.0004, + 0.0235, 0.0112, -0.0182, -0.0324, -0.0210, -0.0035, -0.0395, -0.0384, + 0.0005, -0.0150, -0.0356, 0.0127, -0.0033, -0.0034, 0.0205, 0.0747, + 0.1138, 0.1015, 0.0995, -0.0161, -0.0045, 0.0129, 0.0472, 0.0575, + 0.0222, 0.0091, 0.0037, -0.0471, 0.0371, 0.0132, 0.0208, 0.0247, + 0.0117, 0.0164, 0.0225, 0.0124, -0.0023, 0.0088, -0.0046, 0.0047, +-0.0393, 0.0018, 0.0148, 0.0020, 0.0044, 0.0165, 0.0229, -0.0208, +-0.0477, -0.0310, -0.0164, -0.0390, -0.0764, -0.0525, -0.0094, 0.0075, +-0.0102, -0.0045, -0.0504, -0.0709, 0.0822, 0.0710, 0.0426, 0.0014, +-0.0371, -0.0400, -0.0157, -0.0155, -0.0173, -0.0138, -0.0015, 0.0134, +-0.0418, -0.0682, -0.0256, 0.0050, 0.0360, 0.0354, 0.0074, -0.0396, +-0.0235, 0.0284, 0.0494, 0.0153, 0.0448, 0.0025, -0.0061, 0.0252, + 0.1000, 0.2260, 0.2158, 0.2116, 0.2198, 0.2055, 0.2110, 0.1873, + 0.1907, 0.2071, 0.2164, 0.2009, 0.2059, 0.2124, 0.2141, 0.2093, + 0.0875, 0.0981, 0.1177, 0.1071, 0.1033, 0.1248, 0.1048, 0.1238, + 0.1166, 0.1008, 0.1062, 0.0992, 0.0994, 0.1067, 0.0999, 0.1187, + 0.0750, 0.0794, 0.0828, 0.0854, 0.0859, 0.0801, 0.0891, 0.0933, + 0.0969, 0.0920, 0.0915, 0.0862, 0.0868, 0.0891, 0.0842, 0.0824, + 0.0625, 0.0930, 0.0815, 0.0853, 0.0898, 0.0828, 0.0822, 0.0910, + 0.0873, 0.0906, 0.0856, 0.0840, 0.0774, 0.0785, 0.0684, 0.0711, + 0.3319, 0.4219, 0.4588, 0.4090, 0.4092, 0.4014, 0.3548, 0.3353, + 0.3708, 0.3352, 0.3720, 0.3538, 0.4084, 0.4289, 0.4060, 0.4210, + 0.0588, 0.0209, -0.0082, -0.0115, -0.0343, -0.0621, -0.0541, -0.0346, +-0.0346, -0.0366, -0.0220, -0.0265, -0.0102, 0.0374, 0.0306, 0.0404, + 0.0306, 0.0090, -0.0054, 0.0333, 0.0047, 0.0238, 0.0141, 0.0165, + 0.0306, 0.0420, 0.0159, 0.0124, 0.0414, 0.0158, -0.0237, 0.0141, + 0.0765, 0.0057, -0.0260, -0.0426, -0.0395, -0.0126, -0.0579, -0.0417 +}, + +.lsp22_1 = { + 0.0664, 0.1875, 0.4300, 0.6730, 0.8793, 1.0640, 1.2563, 1.4433, + 1.6394, 1.8176, 2.0029, 2.1921, 2.3796, 2.5671, 2.7595, 2.9536, + 0.2128, 0.4052, 0.5311, 0.6404, 0.7875, 0.8775, 1.0974, 1.3261, + 1.5563, 1.6790, 1.8339, 2.1195, 2.3226, 2.4609, 2.6440, 2.8947, + 0.2024, 0.3362, 0.4834, 0.6784, 0.9088, 1.0850, 1.2188, 1.4054, + 1.6102, 1.7767, 1.9679, 2.1436, 2.3445, 2.5467, 2.7429, 2.9320, + 0.1181, 0.2279, 0.4413, 0.6114, 0.7710, 0.9427, 1.1142, 1.2707, + 1.4892, 1.7416, 1.9526, 2.1466, 2.3629, 2.5445, 2.7293, 2.9205, + 0.1155, 0.2720, 0.4886, 0.6812, 0.8594, 1.0422, 1.2315, 1.4116, + 1.6137, 1.8020, 1.9758, 2.1743, 2.3602, 2.5568, 2.7472, 2.9374, + 0.1110, 0.3312, 0.4735, 0.5612, 0.7129, 0.8146, 1.0233, 1.3155, + 1.5765, 1.7746, 1.9574, 2.1416, 2.3220, 2.5384, 2.7334, 2.9318, + 0.1656, 0.3350, 0.4215, 0.5609, 0.6759, 0.8503, 1.1405, 1.4094, + 1.6057, 1.6860, 1.7639, 2.0031, 2.2680, 2.5076, 2.7263, 2.9368, + 0.1466, 0.3638, 0.4587, 0.5674, 0.7381, 0.8669, 0.9619, 1.1658, + 1.4667, 1.7440, 1.9335, 2.1018, 2.3022, 2.5281, 2.7359, 2.9261, + 0.1061, 0.2566, 0.4739, 0.6751, 0.8711, 1.0704, 1.2720, 1.4655, + 1.6605, 1.8494, 2.0290, 2.2197, 2.4008, 2.5912, 2.7772, 2.9513, + 0.1116, 0.2364, 0.3971, 0.6316, 0.8583, 1.0335, 1.1686, 1.3302, + 1.5612, 1.7877, 1.9829, 2.2052, 2.3596, 2.5460, 2.7341, 2.9290, + 0.2661, 0.4186, 0.5126, 0.6477, 0.8818, 1.1045, 1.2852, 1.4128, + 1.5851, 1.7593, 1.9399, 2.1757, 2.3684, 2.5136, 2.6927, 2.9064, + 0.1495, 0.2749, 0.4391, 0.6304, 0.8239, 1.0181, 1.1995, 1.3759, + 1.5669, 1.7722, 1.9671, 2.1635, 2.3586, 2.5528, 2.7445, 2.9311, + 0.0912, 0.1759, 0.3066, 0.5660, 0.8005, 0.9568, 1.1832, 1.4504, + 1.6259, 1.7948, 2.0113, 2.2002, 2.3654, 2.5583, 2.7929, 2.9735, + 0.1353, 0.2747, 0.4078, 0.5977, 0.7658, 0.9124, 1.1081, 1.3630, + 1.5875, 1.7847, 1.9323, 2.1181, 2.3321, 2.5046, 2.7183, 2.9225, + 0.1938, 0.4063, 0.4982, 0.6002, 0.7702, 0.9071, 1.1631, 1.3885, + 1.6043, 1.8118, 1.9306, 2.0893, 2.2724, 2.4609, 2.6283, 2.8802, + 0.1857, 0.3351, 0.4381, 0.6101, 0.7561, 0.8555, 1.0384, 1.3171, + 1.5667, 1.6904, 1.7552, 1.9689, 2.2597, 2.5260, 2.7272, 2.9337, + 0.1037, 0.2159, 0.4188, 0.6174, 0.8035, 1.0285, 1.2256, 1.4230, + 1.6400, 1.8322, 2.0144, 2.1988, 2.3810, 2.5682, 2.7613, 2.9438, + 0.1625, 0.2776, 0.4225, 0.6001, 0.7879, 0.9087, 1.0801, 1.2759, + 1.4899, 1.7448, 1.9911, 2.1770, 2.3723, 2.5777, 2.7971, 2.9444, + 0.2111, 0.3640, 0.5839, 0.7290, 0.8051, 1.0023, 1.2315, 1.4143, + 1.5878, 1.7755, 1.9804, 2.1498, 2.3312, 2.5350, 2.7613, 2.9472, + 0.1423, 0.2646, 0.4136, 0.6350, 0.8070, 0.9514, 1.1168, 1.3213, + 1.5776, 1.7721, 1.9404, 2.1545, 2.3385, 2.5137, 2.7396, 2.9553, + 0.1132, 0.2386, 0.4103, 0.5931, 0.7808, 0.9881, 1.1840, 1.3860, + 1.6021, 1.7990, 1.9922, 2.1885, 2.3852, 2.5717, 2.7640, 2.9510, + 0.1267, 0.2602, 0.3913, 0.5944, 0.7598, 0.9198, 1.0781, 1.2715, + 1.5299, 1.7573, 1.9308, 2.1346, 2.3267, 2.5419, 2.7466, 2.9320, + 0.2023, 0.3417, 0.4392, 0.6141, 0.7439, 0.8593, 1.1096, 1.3543, + 1.5185, 1.6553, 1.7862, 2.0341, 2.2718, 2.4834, 2.7103, 2.9466, + 0.1113, 0.2470, 0.3677, 0.5686, 0.7700, 0.9356, 1.0806, 1.2452, + 1.4830, 1.7344, 1.9268, 2.1404, 2.3371, 2.5169, 2.7329, 2.9012, + 0.1664, 0.3554, 0.5573, 0.7471, 0.9245, 1.0998, 1.2787, 1.4655, + 1.6654, 1.8346, 2.0179, 2.2159, 2.4096, 2.5946, 2.7790, 2.9530, + 0.1313, 0.2625, 0.4731, 0.6444, 0.8110, 0.9878, 1.1493, 1.3212, + 1.5719, 1.8138, 1.9861, 2.1943, 2.3714, 2.5578, 2.7346, 2.9296, + 0.1186, 0.3035, 0.5049, 0.6860, 0.8670, 0.9975, 1.1364, 1.3471, + 1.5695, 1.7412, 1.9346, 2.1506, 2.3413, 2.5531, 2.7794, 2.9627, + 0.1108, 0.2697, 0.4787, 0.6344, 0.7909, 0.9586, 1.1440, 1.3511, + 1.5686, 1.7601, 1.9246, 2.1241, 2.3293, 2.5390, 2.7315, 2.9333, + 0.0985, 0.2302, 0.3544, 0.5759, 0.7620, 0.9651, 1.1497, 1.3080, + 1.5500, 1.7845, 1.9518, 2.1734, 2.3565, 2.5665, 2.7605, 2.9102, + 0.1208, 0.2727, 0.4381, 0.5736, 0.7382, 0.8390, 1.0102, 1.2648, + 1.5100, 1.7440, 1.9619, 2.1430, 2.3307, 2.5159, 2.7264, 2.9211, + 0.1582, 0.2777, 0.4475, 0.6551, 0.8591, 1.0084, 1.1414, 1.3291, + 1.5902, 1.7826, 1.9543, 2.1659, 2.3233, 2.5044, 2.6935, 2.9199, + 0.1360, 0.2873, 0.4585, 0.6295, 0.7592, 0.9089, 1.0492, 1.2733, + 1.5391, 1.7768, 1.9372, 2.1329, 2.3168, 2.5015, 2.6857, 2.8837, + 0.0886, 0.1829, 0.3696, 0.6126, 0.8334, 1.0135, 1.2303, 1.4674, + 1.6743, 1.8564, 2.0530, 2.2370, 2.3960, 2.5787, 2.7756, 2.9377, + 0.2005, 0.3537, 0.4700, 0.6249, 0.7385, 0.9097, 1.1759, 1.3811, + 1.5314, 1.6705, 1.8546, 2.1229, 2.3292, 2.5251, 2.7951, 2.9646, + 0.1999, 0.3112, 0.4722, 0.7146, 0.8908, 1.0028, 1.1831, 1.3903, + 1.6125, 1.7514, 1.9083, 2.1248, 2.3271, 2.5339, 2.6945, 2.8918, + 0.1243, 0.2606, 0.4382, 0.5850, 0.7705, 0.9727, 1.1214, 1.3059, + 1.5218, 1.7406, 1.9137, 2.1353, 2.3354, 2.5299, 2.7287, 2.9068, + 0.1039, 0.2426, 0.4265, 0.6284, 0.8152, 0.9941, 1.2004, 1.4038, + 1.5912, 1.7763, 1.9650, 2.1598, 2.3474, 2.5488, 2.7419, 2.9322, + 0.1364, 0.2420, 0.3886, 0.5864, 0.7663, 0.8844, 1.0860, 1.3242, + 1.5518, 1.7893, 2.0004, 2.1562, 2.3619, 2.5516, 2.7687, 2.9181, + 0.1483, 0.2851, 0.4479, 0.6312, 0.7924, 0.9821, 1.1705, 1.3386, + 1.5375, 1.7226, 1.9053, 2.0991, 2.2898, 2.4953, 2.7000, 2.9146, + 0.2332, 0.4561, 0.5407, 0.6212, 0.7524, 0.8215, 0.9522, 1.1685, + 1.5216, 1.7132, 1.8291, 2.0647, 2.2811, 2.4857, 2.7071, 2.9281, + 0.1348, 0.3126, 0.5179, 0.7192, 0.9227, 1.1363, 1.3223, 1.4756, + 1.6509, 1.8191, 1.9991, 2.1976, 2.3877, 2.5768, 2.7590, 2.9386, + 0.1093, 0.2211, 0.4763, 0.6703, 0.8282, 0.9536, 1.1202, 1.3796, + 1.6043, 1.8031, 1.9832, 2.1604, 2.3578, 2.5856, 2.7650, 2.9291, + 0.1865, 0.3027, 0.4580, 0.6719, 0.8400, 1.0082, 1.1901, 1.3782, + 1.5448, 1.6885, 1.9477, 2.1381, 2.2797, 2.5113, 2.7465, 2.9414, + 0.1575, 0.3124, 0.4649, 0.6262, 0.8095, 0.9858, 1.1676, 1.3602, + 1.5646, 1.7582, 1.9550, 2.1671, 2.3628, 2.5734, 2.7670, 2.9519, + 0.1174, 0.2777, 0.4663, 0.6333, 0.8169, 1.0096, 1.1885, 1.3847, + 1.5803, 1.7571, 1.9380, 2.1398, 2.3414, 2.5407, 2.7360, 2.9375, + 0.1073, 0.2264, 0.4083, 0.5973, 0.7474, 0.9514, 1.1349, 1.3337, + 1.5433, 1.7348, 1.9380, 2.1436, 2.3441, 2.5438, 2.7457, 2.9383, + 0.1472, 0.2880, 0.4793, 0.6268, 0.8015, 1.0063, 1.1715, 1.3644, + 1.5525, 1.7410, 1.9258, 2.1227, 2.3214, 2.5149, 2.7148, 2.9196, + 0.1414, 0.2565, 0.4349, 0.6111, 0.7695, 0.9496, 1.1212, 1.3265, + 1.5218, 1.7209, 1.9015, 2.0887, 2.3158, 2.5077, 2.7233, 2.9421, + 0.1252, 0.2667, 0.4454, 0.6431, 0.8371, 1.0124, 1.2110, 1.4160, + 1.6240, 1.8242, 2.0047, 2.1974, 2.3902, 2.5778, 2.7637, 2.9481, + 0.1321, 0.2565, 0.3846, 0.5847, 0.7578, 0.9259, 1.0637, 1.2239, + 1.4690, 1.7346, 1.9750, 2.1882, 2.3712, 2.5509, 2.7280, 2.8885, + 0.1437, 0.2930, 0.4428, 0.6156, 0.8045, 0.9638, 1.1450, 1.3138, + 1.5144, 1.7355, 1.9469, 2.1534, 2.3414, 2.5452, 2.7353, 2.9334, + 0.1692, 0.2770, 0.3831, 0.6100, 0.7825, 0.9302, 1.0690, 1.2481, + 1.4615, 1.6799, 1.9165, 2.1739, 2.3435, 2.5349, 2.7520, 2.9163, + 0.1235, 0.2489, 0.4354, 0.6343, 0.8236, 1.0066, 1.1908, 1.3474, + 1.5656, 1.8275, 2.0620, 2.2548, 2.4135, 2.5913, 2.7639, 2.9334, + 0.1090, 0.1961, 0.3854, 0.5701, 0.7024, 0.8843, 1.1393, 1.3785, + 1.5940, 1.7797, 1.9442, 2.1740, 2.3853, 2.5773, 2.7727, 2.9406, + 0.1560, 0.3477, 0.5011, 0.6287, 0.7612, 0.9896, 1.1510, 1.3420, + 1.5435, 1.6816, 1.8731, 2.0651, 2.2613, 2.4999, 2.7027, 2.8971, + 0.1459, 0.2416, 0.3833, 0.5450, 0.7916, 0.9223, 1.0662, 1.1953, + 1.4029, 1.6616, 1.9320, 2.1459, 2.3386, 2.5081, 2.6799, 2.9195, + 0.1546, 0.3854, 0.6184, 0.8460, 1.0599, 1.2428, 1.3906, 1.5550, + 1.7388, 1.8945, 2.0757, 2.2386, 2.4014, 2.5705, 2.7574, 2.9400, + 0.1080, 0.2307, 0.4112, 0.6067, 0.7725, 0.9467, 1.1285, 1.3205, + 1.5348, 1.7609, 1.9937, 2.1878, 2.3583, 2.5515, 2.7199, 2.9049, + 0.1482, 0.3178, 0.4983, 0.6342, 0.7783, 0.9880, 1.2019, 1.3404, + 1.5223, 1.7296, 1.9211, 2.0943, 2.2928, 2.5008, 2.7136, 2.9224, + 0.1145, 0.2910, 0.4891, 0.6492, 0.8126, 0.9530, 1.1180, 1.3155, + 1.5054, 1.6893, 1.8899, 2.1188, 2.3389, 2.5512, 2.7313, 2.9224, + 0.0939, 0.1689, 0.3250, 0.5792, 0.7698, 0.9245, 1.1574, 1.3865, + 1.5959, 1.7977, 1.9821, 2.1528, 2.3326, 2.5540, 2.7553, 2.9179, + 0.1243, 0.2474, 0.3923, 0.6199, 0.7908, 0.9379, 1.1497, 1.3734, + 1.5582, 1.7420, 1.9539, 2.1385, 2.3240, 2.5277, 2.7311, 2.9178, + 0.1961, 0.3748, 0.5176, 0.6387, 0.8169, 1.0477, 1.2124, 1.3869, + 1.5604, 1.7225, 1.8770, 2.0837, 2.2960, 2.5103, 2.6945, 2.8862, + 0.1295, 0.2403, 0.4149, 0.6189, 0.7913, 0.9130, 1.0832, 1.2787, + 1.4860, 1.7112, 1.9502, 2.1348, 2.2776, 2.4982, 2.7431, 2.9522, + 0.0160, 0.0362, 0.0097, 0.0057, -0.0014, -0.0073, -0.0046, -0.0064, +-0.0121, 0.0019, 0.0149, -0.0440, -0.0479, -0.0382, -0.0480, -0.0182, + 0.0170, 0.0114, -0.0298, -0.0175, -0.0033, -0.0354, -0.0510, -0.0025, + 0.0307, 0.0351, 0.0338, 0.0420, 0.0138, -0.0175, -0.0102, 0.0053, + 0.0084, -0.0003, 0.0412, -0.0027, 0.0145, -0.0039, 0.0083, 0.0400, + 0.0001, -0.0262, 0.0055, -0.0082, 0.0348, 0.0433, 0.0137, -0.0024, +-0.0055, 0.0262, 0.0521, 0.0349, 0.0185, 0.0076, -0.0319, -0.0561, +-0.0460, -0.0253, -0.0097, 0.0163, 0.0184, -0.0037, -0.0480, -0.0371, + 0.0628, 0.0665, 0.0296, -0.0057, 0.0253, 0.0227, 0.0350, 0.0692, + 0.0545, 0.0218, 0.0094, -0.0449, -0.0372, 0.0005, 0.0258, 0.0118, + 0.0285, 0.0760, 0.0822, 0.0527, -0.0299, -0.0049, 0.0170, 0.0195, + 0.0136, 0.0286, 0.0289, 0.0139, 0.0054, 0.0152, 0.0244, 0.0028, +-0.0056, -0.0260, 0.0307, 0.0572, -0.0087, 0.0088, 0.0062, 0.0000, + 0.0125, 0.0000, -0.0292, 0.0820, 0.0872, 0.0646, 0.0346, 0.0076, +-0.0022, -0.0253, -0.0567, -0.0188, -0.0336, -0.0673, -0.0549, -0.0166, +-0.0259, -0.0140, 0.0040, -0.0029, -0.0430, -0.0531, -0.0253, -0.0019, +-0.0071, 0.0393, 0.0072, -0.0327, -0.0236, -0.0235, -0.0177, -0.0186, +-0.0280, -0.0201, -0.0077, 0.0383, 0.0418, 0.0321, 0.0294, 0.0169, + 0.0468, 0.0301, 0.0133, 0.0363, 0.0516, 0.0937, 0.1240, 0.1404, + 0.1325, 0.1178, 0.0999, 0.0251, -0.0037, -0.0495, -0.0703, -0.0219, +-0.0261, -0.0304, -0.0204, -0.0372, 0.0355, 0.0131, -0.0093, -0.0099, +-0.0069, -0.0034, -0.0065, -0.0208, -0.0231, -0.0117, -0.0211, -0.0243, + 0.0046, -0.0107, -0.0070, 0.0123, 0.0230, 0.0152, 0.0164, 0.0412, + 0.0619, 0.0858, 0.0862, -0.0056, 0.0125, 0.0182, 0.0347, 0.0388, + 0.0456, 0.0407, -0.0249, -0.0460, 0.0206, 0.0299, 0.0253, 0.0207, + 0.0177, 0.0238, 0.0253, 0.0030, 0.0042, 0.0020, -0.0081, -0.0136, +-0.0290, -0.0042, 0.0122, 0.0051, 0.0107, 0.0228, 0.0211, -0.0068, +-0.0436, -0.0299, -0.0078, -0.0779, -0.1157, -0.0679, 0.0172, 0.0150, +-0.0051, 0.0081, -0.0512, -0.0616, 0.0576, 0.0799, 0.0803, 0.0336, + 0.0001, -0.0298, -0.0747, -0.0115, -0.0101, -0.0170, -0.0050, 0.0174, +-0.0290, -0.0601, -0.0150, 0.0121, 0.0165, 0.0230, 0.0028, -0.0317, +-0.0165, 0.0356, 0.0451, 0.0120, 0.0321, 0.0084, -0.0058, 0.0122, + 0.1935, 0.1802, 0.2195, 0.2410, 0.2201, 0.1915, 0.1840, 0.1935, + 0.2213, 0.2079, 0.1858, 0.1974, 0.2239, 0.2173, 0.1840, 0.2120, + 0.4912, 0.4777, 0.4607, 0.4395, 0.4426, 0.4388, 0.4416, 0.4345, + 0.4239, 0.4331, 0.4522, 0.4423, 0.4475, 0.4387, 0.4525, 0.4446 +}, + +.lsp22_2 = { + 0.0712, 0.1830, 0.4167, 0.6669, 0.8738, 1.0696, 1.2555, 1.4426, + 1.6427, 1.8138, 1.9966, 2.1925, 2.3872, 2.5748, 2.7713, 2.9597, + 0.1894, 0.3942, 0.5418, 0.6747, 0.7517, 0.8763, 1.1189, 1.3072, + 1.5011, 1.6790, 1.8342, 2.0781, 2.2929, 2.4566, 2.6613, 2.9204, + 0.1767, 0.3403, 0.5173, 0.7055, 0.8899, 1.0696, 1.2302, 1.4111, + 1.5989, 1.7751, 1.9618, 2.1544, 2.3454, 2.5356, 2.7362, 2.9315, + 0.1240, 0.2361, 0.4423, 0.6326, 0.7729, 0.9387, 1.1142, 1.2847, + 1.4746, 1.7126, 1.9482, 2.1642, 2.3536, 2.5506, 2.7593, 2.9197, + 0.1213, 0.2782, 0.5011, 0.6910, 0.8564, 1.0462, 1.2315, 1.4232, + 1.6178, 1.8028, 1.9813, 2.1766, 2.3670, 2.5591, 2.7475, 2.9403, + 0.1382, 0.2995, 0.4693, 0.5874, 0.6929, 0.8102, 1.0094, 1.2960, + 1.5511, 1.7607, 1.9699, 2.1680, 2.3367, 2.5459, 2.7370, 2.9105, + 0.1428, 0.2690, 0.3713, 0.4757, 0.6664, 0.9019, 1.1276, 1.3674, + 1.5471, 1.6695, 1.8261, 2.0572, 2.2753, 2.4963, 2.7187, 2.9114, + 0.1669, 0.3085, 0.4489, 0.5724, 0.6934, 0.8465, 0.9680, 1.1641, + 1.4320, 1.6841, 1.8977, 2.1061, 2.3118, 2.5152, 2.7329, 2.9274, + 0.1128, 0.2709, 0.4803, 0.6878, 0.8673, 1.0693, 1.2749, 1.4657, + 1.6650, 1.8434, 2.0339, 2.2300, 2.4003, 2.5951, 2.7762, 2.9465, + 0.1201, 0.2345, 0.4021, 0.6379, 0.8651, 1.0256, 1.1630, 1.3250, + 1.5395, 1.7808, 2.0011, 2.1997, 2.3618, 2.5505, 2.7561, 2.9351, + 0.2575, 0.4163, 0.5081, 0.6484, 0.8570, 1.0832, 1.2732, 1.3933, + 1.5497, 1.7725, 1.9945, 2.2098, 2.3514, 2.5216, 2.7146, 2.8969, + 0.1367, 0.2656, 0.4470, 0.6398, 0.8146, 1.0125, 1.2142, 1.3960, + 1.5558, 1.7338, 1.9465, 2.1769, 2.4031, 2.5746, 2.7335, 2.9046, + 0.0868, 0.1723, 0.2785, 0.5071, 0.7732, 1.0024, 1.1924, 1.4220, + 1.6149, 1.8064, 1.9951, 2.1935, 2.3777, 2.5748, 2.7661, 2.9488, + 0.1428, 0.2592, 0.3875, 0.5810, 0.7513, 0.9334, 1.1096, 1.3565, + 1.5869, 1.7788, 1.9036, 2.0893, 2.3332, 2.5289, 2.7204, 2.9053, + 0.2313, 0.4066, 0.4960, 0.5853, 0.7799, 0.9201, 1.1365, 1.3499, + 1.5119, 1.7641, 1.9095, 2.0911, 2.2653, 2.4587, 2.7010, 2.8900, + 0.1927, 0.3424, 0.4682, 0.6035, 0.7330, 0.8492, 1.0477, 1.3083, + 1.5602, 1.6945, 1.7806, 2.0066, 2.2566, 2.4864, 2.7021, 2.9180, + 0.0962, 0.1933, 0.3968, 0.6077, 0.8083, 1.0224, 1.2307, 1.4344, + 1.6350, 1.8173, 2.0024, 2.1894, 2.3812, 2.5648, 2.7535, 2.9483, + 0.1469, 0.2679, 0.4272, 0.6080, 0.7949, 0.9247, 1.0741, 1.2722, + 1.5144, 1.7679, 2.0030, 2.1944, 2.3890, 2.5928, 2.8116, 2.9555, + 0.1618, 0.3917, 0.6111, 0.7511, 0.8325, 1.0010, 1.2397, 1.4147, + 1.5764, 1.7359, 1.9300, 2.1325, 2.3096, 2.5480, 2.7725, 2.9697, + 0.1561, 0.2634, 0.4062, 0.6139, 0.8059, 0.9618, 1.0948, 1.3179, + 1.5846, 1.7622, 1.9399, 2.1476, 2.3330, 2.5232, 2.7412, 2.9554, + 0.1076, 0.2320, 0.3977, 0.5798, 0.7707, 0.9975, 1.1884, 1.3793, + 1.6059, 1.8038, 1.9928, 2.1942, 2.3881, 2.5742, 2.7717, 2.9547, + 0.1360, 0.2493, 0.3827, 0.5644, 0.7384, 0.9087, 1.0865, 1.2902, + 1.5185, 1.7246, 1.9170, 2.1175, 2.3324, 2.5442, 2.7441, 2.9437, + 0.1684, 0.2990, 0.4406, 0.5834, 0.7305, 0.9028, 1.0801, 1.2756, + 1.4646, 1.6514, 1.8346, 2.0493, 2.2594, 2.4765, 2.6985, 2.9089, + 0.1145, 0.2295, 0.3421, 0.5032, 0.7007, 0.9057, 1.0830, 1.2733, + 1.4885, 1.6897, 1.8933, 2.1128, 2.3188, 2.5271, 2.7284, 2.9266, + 0.1705, 0.3815, 0.6120, 0.7964, 0.9342, 1.0926, 1.2741, 1.4645, + 1.6552, 1.8040, 1.9778, 2.1931, 2.3836, 2.5827, 2.7905, 2.9494, + 0.1284, 0.2622, 0.4714, 0.6559, 0.8004, 1.0005, 1.1416, 1.3163, + 1.5773, 1.8144, 1.9947, 2.2001, 2.3836, 2.5710, 2.7447, 2.9262, + 0.1164, 0.2882, 0.5349, 0.7310, 0.8483, 0.9729, 1.1331, 1.3350, + 1.5307, 1.7306, 1.9409, 2.1275, 2.3229, 2.5358, 2.7455, 2.9447, + 0.1159, 0.2646, 0.4677, 0.6375, 0.7771, 0.9557, 1.1398, 1.3514, + 1.5717, 1.7512, 1.9337, 2.1323, 2.3272, 2.5409, 2.7377, 2.9212, + 0.1080, 0.2143, 0.3475, 0.5307, 0.7358, 0.9681, 1.1489, 1.3289, + 1.5553, 1.7664, 1.9696, 2.1780, 2.3676, 2.5568, 2.7493, 2.9347, + 0.1331, 0.2430, 0.3879, 0.5092, 0.6324, 0.8119, 1.0327, 1.2657, + 1.4999, 1.7107, 1.9178, 2.1272, 2.3296, 2.5340, 2.7372, 2.9353, + 0.1557, 0.2873, 0.4558, 0.6548, 0.8472, 1.0106, 1.1480, 1.3281, + 1.5856, 1.7740, 1.9564, 2.1651, 2.3295, 2.5207, 2.7005, 2.9151, + 0.1397, 0.2761, 0.4533, 0.6374, 0.7510, 0.8767, 1.0408, 1.2909, + 1.5368, 1.7560, 1.9424, 2.1332, 2.3210, 2.5116, 2.6924, 2.8886, + 0.0945, 0.1653, 0.3601, 0.6129, 0.8378, 1.0333, 1.2417, 1.4539, + 1.6507, 1.8304, 2.0286, 2.2157, 2.3975, 2.5865, 2.7721, 2.9426, + 0.1892, 0.3863, 0.4896, 0.5909, 0.7294, 0.9483, 1.1575, 1.3542, + 1.4796, 1.6535, 1.9070, 2.1435, 2.3281, 2.4967, 2.7039, 2.9222, + 0.1614, 0.3129, 0.5086, 0.7048, 0.8730, 1.0239, 1.1905, 1.3799, + 1.5697, 1.7503, 1.9103, 2.1115, 2.3235, 2.5234, 2.6973, 2.8957, + 0.1199, 0.2590, 0.4273, 0.5935, 0.7542, 0.9625, 1.1225, 1.2998, + 1.5361, 1.7102, 1.9097, 2.1269, 2.3157, 2.5304, 2.7212, 2.9175, + 0.1087, 0.2373, 0.4261, 0.6277, 0.8092, 0.9884, 1.1954, 1.4077, + 1.6048, 1.7799, 1.9693, 2.1662, 2.3426, 2.5501, 2.7459, 2.9257, + 0.1262, 0.2216, 0.3857, 0.5799, 0.7148, 0.8610, 1.0752, 1.3306, + 1.5549, 1.7605, 1.9727, 2.1580, 2.3612, 2.5602, 2.7554, 2.9372, + 0.1445, 0.2832, 0.4469, 0.6283, 0.7991, 0.9796, 1.1504, 1.3323, + 1.5313, 1.7140, 1.8968, 2.0990, 2.2826, 2.4903, 2.7003, 2.9031, + 0.1647, 0.4068, 0.5428, 0.6539, 0.7682, 0.8479, 0.9372, 1.1691, + 1.4776, 1.7314, 1.9071, 2.0918, 2.2774, 2.5029, 2.7152, 2.9221, + 0.1274, 0.3052, 0.5238, 0.7280, 0.9229, 1.1211, 1.3071, 1.4784, + 1.6564, 1.8235, 2.0028, 2.1999, 2.3763, 2.5608, 2.7510, 2.9356, + 0.1076, 0.2195, 0.4815, 0.6873, 0.8241, 0.9443, 1.1066, 1.3687, + 1.6087, 1.8105, 1.9857, 2.1486, 2.3505, 2.5854, 2.7785, 2.9376, + 0.1755, 0.3089, 0.4695, 0.6648, 0.8315, 1.0202, 1.1774, 1.3554, + 1.5393, 1.7141, 1.9247, 2.1284, 2.2983, 2.4975, 2.7296, 2.9401, + 0.1636, 0.3166, 0.4594, 0.6199, 0.8161, 0.9879, 1.1738, 1.3642, + 1.5680, 1.7633, 1.9598, 2.1695, 2.3692, 2.5846, 2.7809, 2.9563, + 0.1219, 0.2662, 0.4620, 0.6491, 0.8353, 1.0150, 1.2065, 1.3944, + 1.5785, 1.7631, 1.9389, 2.1434, 2.3400, 2.5316, 2.7359, 2.9513, + 0.1072, 0.2258, 0.3968, 0.5642, 0.7222, 0.9367, 1.1458, 1.3347, + 1.5424, 1.7373, 1.9303, 2.1432, 2.3451, 2.5415, 2.7444, 2.9394, + 0.1393, 0.2950, 0.4724, 0.6407, 0.8034, 1.0031, 1.1712, 1.3552, + 1.5519, 1.7411, 1.9198, 2.1160, 2.3238, 2.5119, 2.7134, 2.9205, + 0.1358, 0.2613, 0.4239, 0.5991, 0.7643, 0.9379, 1.1213, 1.3115, + 1.5067, 1.7031, 1.8768, 2.0836, 2.3092, 2.5134, 2.7237, 2.9286, + 0.1267, 0.2695, 0.4524, 0.6591, 0.8396, 1.0173, 1.2183, 1.4205, + 1.6306, 1.8162, 2.0106, 2.2082, 2.3773, 2.5787, 2.7551, 2.9387, + 0.1314, 0.2529, 0.3837, 0.5494, 0.7446, 0.9097, 1.0489, 1.2385, + 1.4691, 1.7170, 1.9600, 2.1770, 2.3594, 2.5356, 2.7215, 2.9088, + 0.1538, 0.2931, 0.4449, 0.6041, 0.7959, 0.9666, 1.1355, 1.3214, + 1.5150, 1.7230, 1.9433, 2.1408, 2.3459, 2.5476, 2.7273, 2.9330, + 0.1771, 0.2834, 0.4136, 0.5856, 0.7516, 0.9363, 1.0596, 1.2462, + 1.4737, 1.6627, 1.8810, 2.1150, 2.3202, 2.5274, 2.7403, 2.9490, + 0.1248, 0.2494, 0.4397, 0.6352, 0.8226, 1.0015, 1.1799, 1.3458, + 1.5654, 1.8228, 2.0646, 2.2550, 2.4161, 2.5964, 2.7675, 2.9383, + 0.0933, 0.1993, 0.3105, 0.4371, 0.6417, 0.8935, 1.1244, 1.3508, + 1.5649, 1.7595, 1.9581, 2.1648, 2.3639, 2.5569, 2.7573, 2.9468, + 0.1794, 0.3229, 0.4758, 0.6238, 0.7821, 0.9640, 1.1205, 1.3116, + 1.5054, 1.6803, 1.8658, 2.0651, 2.2793, 2.4856, 2.6867, 2.9105, + 0.1252, 0.2397, 0.3844, 0.5398, 0.7044, 0.8799, 1.0526, 1.2270, + 1.4269, 1.6412, 1.8532, 2.0784, 2.2957, 2.5051, 2.7139, 2.9210, + 0.1391, 0.3494, 0.5738, 0.8024, 1.0098, 1.2094, 1.3830, 1.5509, + 1.7222, 1.8782, 2.0604, 2.2479, 2.4154, 2.5968, 2.7767, 2.9450, + 0.1122, 0.2180, 0.4175, 0.6074, 0.7559, 0.9465, 1.1513, 1.3340, + 1.5215, 1.7491, 1.9911, 2.1894, 2.3433, 2.5377, 2.7380, 2.9183, + 0.1595, 0.3029, 0.4842, 0.6324, 0.7874, 0.9814, 1.1992, 1.3554, + 1.5017, 1.7274, 1.9168, 2.0853, 2.2964, 2.5300, 2.7187, 2.9041, + 0.1350, 0.2747, 0.4791, 0.6638, 0.8050, 0.9644, 1.1238, 1.2987, + 1.4844, 1.6754, 1.8778, 2.0987, 2.3279, 2.5424, 2.7410, 2.9356, + 0.0914, 0.1727, 0.3143, 0.5124, 0.7123, 0.9323, 1.1706, 1.3821, + 1.5864, 1.7828, 1.9701, 2.1560, 2.3445, 2.5486, 2.7433, 2.9372, + 0.1222, 0.2359, 0.3931, 0.5912, 0.7776, 0.9505, 1.1623, 1.3723, + 1.5484, 1.7316, 1.9321, 2.1283, 2.3148, 2.5269, 2.7299, 2.9213, + 0.2089, 0.3872, 0.5090, 0.6413, 0.7967, 1.0226, 1.1897, 1.3908, + 1.5954, 1.7202, 1.8614, 2.1030, 2.2973, 2.5079, 2.7491, 2.8944, + 0.1288, 0.2423, 0.4108, 0.6062, 0.7688, 0.9188, 1.0876, 1.2866, + 1.4897, 1.6910, 1.9219, 2.1076, 2.2805, 2.5023, 2.7155, 2.9203, + 0.0192, 0.0462, 0.0128, 0.0054, -0.0156, -0.0118, -0.0135, 0.0030, +-0.0120, 0.0031, 0.0240, -0.0451, -0.0439, -0.0432, -0.0527, -0.0207, + 0.0253, 0.0084, -0.0305, -0.0144, 0.0046, -0.0378, -0.0467, -0.0102, + 0.0280, 0.0540, 0.0151, 0.0437, 0.0141, -0.0257, -0.0058, 0.0073, + 0.0107, 0.0054, 0.0371, -0.0105, 0.0165, -0.0143, 0.0148, 0.0382, +-0.0054, -0.0284, 0.0001, -0.0218, 0.0258, 0.0517, 0.0157, -0.0032, +-0.0190, 0.0343, 0.0576, 0.0346, 0.0392, -0.0158, -0.0323, -0.0578, +-0.0617, -0.0242, -0.0144, 0.0188, 0.0249, 0.0021, -0.0422, -0.0420, + 0.0750, 0.0762, 0.0325, -0.0066, 0.0332, 0.0376, 0.0388, 0.0630, + 0.0525, 0.0196, 0.0051, -0.0484, -0.0322, 0.0059, 0.0132, 0.0079, + 0.0237, 0.0774, 0.0697, 0.0184, -0.0321, -0.0327, 0.0274, 0.0284, + 0.0057, 0.0289, 0.0478, 0.0142, -0.0053, 0.0114, 0.0292, -0.0032, +-0.0111, -0.0389, 0.0282, 0.0613, 0.0200, -0.0006, 0.0111, 0.0048, + 0.0273, 0.0017, -0.0369, 0.0655, 0.0758, 0.0555, 0.0238, -0.0024, +-0.0100, -0.0419, -0.0696, -0.0158, -0.0479, -0.0744, -0.0356, -0.0245, +-0.0400, -0.0112, 0.0134, 0.0001, -0.0422, -0.0514, -0.0081, 0.0083, +-0.0151, 0.0323, -0.0001, -0.0444, -0.0406, -0.0214, -0.0050, -0.0235, +-0.0205, -0.0264, -0.0324, 0.0334, 0.0392, 0.0265, 0.0289, 0.0180, + 0.0493, 0.0227, 0.0194, 0.0365, 0.0544, 0.0674, 0.0559, 0.0732, + 0.0911, 0.0942, 0.0735, 0.0174, -0.0113, -0.0553, -0.0665, -0.0227, +-0.0259, -0.0266, -0.0239, -0.0379, 0.0329, 0.0173, -0.0210, -0.0114, +-0.0063, 0.0060, -0.0089, -0.0198, -0.0282, -0.0080, -0.0179, -0.0290, + 0.0046, -0.0126, -0.0066, 0.0350, 0.0532, 0.0235, 0.0198, 0.0212, + 0.0449, 0.0681, 0.0677, -0.0049, 0.0086, 0.0120, 0.0356, 0.0454, + 0.0592, 0.0449, -0.0271, -0.0510, -0.0110, 0.0234, 0.0203, 0.0243, + 0.0242, 0.0133, 0.0098, 0.0040, 0.0024, -0.0005, -0.0075, -0.0126, +-0.0393, -0.0052, 0.0165, 0.0016, -0.0193, 0.0239, 0.0336, 0.0029, +-0.0586, -0.0539, -0.0094, -0.0664, -0.0898, -0.0540, -0.0066, 0.0134, +-0.0074, 0.0067, -0.0521, -0.0431, 0.0104, 0.0690, 0.0663, 0.0197, +-0.0017, -0.0518, -0.0597, -0.0171, -0.0054, -0.0140, -0.0080, 0.0172, +-0.0362, -0.0713, -0.0310, 0.0096, 0.0243, 0.0381, -0.0062, -0.0392, +-0.0281, 0.0386, 0.0461, 0.0069, 0.0384, 0.0080, -0.0141, 0.0171, + 0.3368, 0.3128, 0.3304, 0.3392, 0.3185, 0.3037, 0.2789, 0.2692, + 0.2779, 0.2796, 0.2891, 0.2643, 0.2647, 0.2593, 0.2927, 0.3283, + 0.4978, 0.4988, 0.4969, 0.4997, 0.4957, 0.4985, 0.4970, 0.4978, + 0.4938, 0.4951, 0.4994, 0.4971, 0.4981, 0.4983, 0.4967, 0.4789 +}, + +.lsp44 = { + 0.0927, 0.2291, 0.4059, 0.5779, 0.7288, 0.8821, 1.0377, 1.1915, + 1.3433, 1.4931, 1.6475, 1.7989, 1.9381, 2.0858, 2.2321, 2.3765, + 2.5187, 2.6530, 2.7895, 2.9354, 0.0944, 0.1974, 0.3046, 0.4714, + 0.6116, 0.7829, 0.9027, 1.0375, 1.1869, 1.3488, 1.5036, 1.6781, + 1.8276, 1.9983, 2.1449, 2.3089, 2.4534, 2.6113, 2.7553, 2.9062, + 0.1168, 0.2843, 0.4907, 0.6706, 0.8100, 0.9417, 1.0753, 1.2014, + 1.3151, 1.4496, 1.5832, 1.7379, 1.8642, 2.0230, 2.1681, 2.3250, + 2.4676, 2.6242, 2.7602, 2.9066, 0.1353, 0.2335, 0.3370, 0.4380, + 0.5819, 0.7353, 0.8671, 1.0160, 1.1435, 1.2977, 1.4860, 1.6739, + 1.8412, 2.0028, 2.1537, 2.3124, 2.4741, 2.6272, 2.7862, 2.9536, + 0.1003, 0.2226, 0.3584, 0.4971, 0.6291, 0.7710, 0.9157, 1.0669, + 1.2143, 1.3624, 1.5104, 1.6681, 1.8164, 1.9823, 2.1394, 2.3082, + 2.4677, 2.6306, 2.7909, 2.9382, 0.1056, 0.2027, 0.2956, 0.4005, + 0.5215, 0.6708, 0.8545, 1.0557, 1.2344, 1.4023, 1.5676, 1.7278, + 1.8808, 2.0381, 2.1846, 2.3376, 2.4887, 2.6377, 2.7878, 2.9504, + 0.1015, 0.2462, 0.4122, 0.5783, 0.7233, 0.8833, 1.0377, 1.1903, + 1.3341, 1.4727, 1.6138, 1.7582, 1.8912, 2.0370, 2.1701, 2.3125, + 2.4500, 2.6006, 2.7507, 2.9166, 0.1787, 0.2418, 0.3265, 0.5379, + 0.6584, 0.7681, 0.9545, 1.1050, 1.2125, 1.3528, 1.4763, 1.6705, + 1.8136, 1.9594, 2.0936, 2.2724, 2.4394, 2.5919, 2.7037, 2.8747, + 0.0859, 0.1600, 0.2980, 0.4933, 0.6696, 0.8285, 0.9958, 1.1545, + 1.3107, 1.4591, 1.6127, 1.7652, 1.9143, 2.0680, 2.2171, 2.3643, + 2.5141, 2.6611, 2.8143, 2.9691, 0.0910, 0.2110, 0.3364, 0.4718, + 0.5856, 0.7298, 0.8910, 1.0514, 1.1988, 1.3572, 1.5178, 1.6861, + 1.8399, 2.0099, 2.1639, 2.3225, 2.4774, 2.6321, 2.7863, 2.9412, + 0.1904, 0.2874, 0.3681, 0.4981, 0.6248, 0.7880, 0.9121, 1.0750, + 1.2185, 1.3809, 1.5296, 1.7007, 1.8592, 2.0470, 2.1913, 2.3250, + 2.4519, 2.5984, 2.7408, 2.9023, 0.0917, 0.2067, 0.3246, 0.4961, + 0.6310, 0.8024, 0.9438, 1.1008, 1.2362, 1.3892, 1.5407, 1.7033, + 1.8427, 2.0061, 2.1498, 2.3117, 2.4550, 2.6053, 2.7462, 2.9029, + 0.0989, 0.2193, 0.3756, 0.5410, 0.6929, 0.8368, 0.9801, 1.1250, + 1.2677, 1.4184, 1.5677, 1.7292, 1.8770, 2.0311, 2.1803, 2.3306, + 2.4836, 2.6339, 2.7943, 2.9549, 0.0861, 0.1943, 0.3057, 0.4867, + 0.6194, 0.7592, 0.9184, 1.1052, 1.2486, 1.4064, 1.5609, 1.7273, + 1.8703, 2.0291, 2.1686, 2.3225, 2.4628, 2.6115, 2.7471, 2.9005, + 0.0932, 0.2110, 0.3737, 0.5479, 0.7120, 0.8570, 0.9975, 1.1364, + 1.2772, 1.4220, 1.5612, 1.7089, 1.8410, 1.9827, 2.1263, 2.2859, + 2.4459, 2.6172, 2.7788, 2.9395, 0.1193, 0.2341, 0.3523, 0.5029, + 0.6437, 0.7803, 0.9367, 1.1007, 1.2392, 1.3869, 1.5425, 1.7168, + 1.8709, 2.0248, 2.1584, 2.2949, 2.4308, 2.5823, 2.7235, 2.9034, + 0.0834, 0.1988, 0.3557, 0.5261, 0.6767, 0.8427, 1.0029, 1.1683, + 1.3138, 1.4527, 1.6046, 1.7583, 1.9011, 2.0517, 2.1928, 2.3397, + 2.4839, 2.6291, 2.7771, 2.9329, 0.0938, 0.1967, 0.3213, 0.4675, + 0.6068, 0.7664, 0.9418, 1.1120, 1.2535, 1.3932, 1.5243, 1.6801, + 1.8346, 1.9931, 2.1376, 2.3035, 2.4636, 2.6244, 2.7829, 2.9371, + 0.1017, 0.2552, 0.4327, 0.6017, 0.7467, 0.8797, 1.0097, 1.1442, + 1.2628, 1.4049, 1.5541, 1.7090, 1.8461, 1.9982, 2.1486, 2.3029, + 2.4513, 2.6075, 2.7594, 2.9209, 0.1031, 0.2295, 0.3747, 0.5122, + 0.6596, 0.7935, 0.9345, 1.1050, 1.2384, 1.3543, 1.4739, 1.6136, + 1.7447, 1.8914, 2.0434, 2.1916, 2.3557, 2.5396, 2.7419, 2.9401, + 0.1007, 0.2374, 0.3715, 0.5173, 0.6465, 0.8069, 0.9553, 1.1145, + 1.2594, 1.4143, 1.5617, 1.7166, 1.8457, 2.0012, 2.1462, 2.2864, + 2.4258, 2.5910, 2.7372, 2.9018, 0.0808, 0.1726, 0.2849, 0.4592, + 0.6118, 0.7853, 0.9588, 1.1256, 1.2751, 1.4392, 1.5898, 1.7514, + 1.8977, 2.0554, 2.1937, 2.3430, 2.4831, 2.6249, 2.7601, 2.9155, + 0.1669, 0.2574, 0.3694, 0.5569, 0.6773, 0.8061, 1.0160, 1.1667, + 1.2791, 1.4041, 1.5452, 1.7207, 1.8524, 2.0038, 2.1414, 2.3338, + 2.4747, 2.6157, 2.7303, 2.8848, 0.1598, 0.2521, 0.3416, 0.5149, + 0.6703, 0.7941, 0.9408, 1.1164, 1.2017, 1.3293, 1.4908, 1.6783, + 1.8438, 1.9927, 2.1149, 2.2698, 2.4420, 2.6193, 2.7583, 2.9103, + 0.0902, 0.1978, 0.3265, 0.4578, 0.5878, 0.7439, 0.9110, 1.0906, + 1.2556, 1.4125, 1.5688, 1.7295, 1.8829, 2.0472, 2.2058, 2.3537, + 2.5075, 2.6548, 2.8058, 2.9538, 0.0818, 0.1695, 0.2794, 0.4470, + 0.6069, 0.7641, 0.9313, 1.0946, 1.2411, 1.4072, 1.5640, 1.7186, + 1.8651, 2.0254, 2.1726, 2.3286, 2.4784, 2.6287, 2.7750, 2.9339, + 0.1980, 0.3134, 0.4099, 0.4975, 0.6491, 0.8376, 0.9441, 1.0298, + 1.1795, 1.3866, 1.5784, 1.7209, 1.8137, 1.9271, 2.0863, 2.2930, + 2.4696, 2.6184, 2.7587, 2.9251, 0.1338, 0.2341, 0.3566, 0.4797, + 0.6129, 0.7580, 0.9093, 1.0491, 1.1911, 1.3313, 1.4841, 1.6503, + 1.8035, 1.9685, 2.1128, 2.2694, 2.4093, 2.5728, 2.7206, 2.8994, + 0.0937, 0.2034, 0.3447, 0.5032, 0.6370, 0.7993, 0.9674, 1.1323, + 1.2830, 1.4199, 1.5492, 1.7010, 1.8513, 2.0087, 2.1550, 2.3115, + 2.4643, 2.6237, 2.7812, 2.9392, 0.1085, 0.2152, 0.3126, 0.4569, + 0.5718, 0.7213, 0.8837, 1.0604, 1.2053, 1.3755, 1.5397, 1.7001, + 1.8409, 2.0039, 2.1498, 2.3080, 2.4535, 2.6063, 2.7505, 2.9110, + 0.0562, 0.2066, 0.4034, 0.5490, 0.6682, 0.7924, 0.9495, 1.0800, + 1.1869, 1.3156, 1.4834, 1.6619, 1.8404, 2.0199, 2.1509, 2.2755, + 2.4072, 2.5580, 2.6993, 2.8913, 0.0939, 0.2303, 0.3742, 0.5260, + 0.6662, 0.8294, 0.9769, 1.1315, 1.2792, 1.4153, 1.5436, 1.6701, + 1.8215, 1.9920, 2.1310, 2.3005, 2.4534, 2.5786, 2.7204, 2.9068, + 0.1005, 0.2442, 0.3898, 0.5398, 0.6958, 0.8474, 1.0008, 1.1556, + 1.3020, 1.4456, 1.5954, 1.7470, 1.8922, 2.0500, 2.2019, 2.3492, + 2.4963, 2.6412, 2.7890, 2.9423, 0.1022, 0.2031, 0.3213, 0.4402, + 0.5637, 0.7117, 0.8673, 1.0242, 1.1727, 1.3206, 1.4846, 1.6465, + 1.8015, 1.9655, 2.1233, 2.2873, 2.4464, 2.6074, 2.7685, 2.9409, + 0.1985, 0.3497, 0.4622, 0.5982, 0.7489, 0.8752, 0.9925, 1.1679, + 1.3288, 1.4606, 1.5820, 1.7492, 1.8922, 2.0511, 2.1780, 2.3373, + 2.4760, 2.6233, 2.7466, 2.8978, 0.1284, 0.2433, 0.3630, 0.4852, + 0.6117, 0.7460, 0.8904, 1.0360, 1.1738, 1.3142, 1.4696, 1.6185, + 1.7719, 1.9318, 2.0961, 2.2697, 2.4408, 2.6046, 2.7681, 2.9451, + 0.1042, 0.2286, 0.3598, 0.5064, 0.6438, 0.7899, 0.9350, 1.0891, + 1.2323, 1.3807, 1.5225, 1.6747, 1.8153, 1.9669, 2.1145, 2.2832, + 2.4430, 2.6085, 2.7748, 2.9346, 0.0780, 0.1724, 0.2440, 0.3489, + 0.5280, 0.7426, 0.9272, 1.0914, 1.2562, 1.4188, 1.5804, 1.7376, + 1.8909, 2.0473, 2.1946, 2.3457, 2.4950, 2.6424, 2.7926, 2.9549, + 0.1103, 0.2608, 0.4087, 0.5538, 0.6923, 0.8418, 0.9940, 1.1507, + 1.2919, 1.4406, 1.5802, 1.7262, 1.8638, 2.0085, 2.1572, 2.2975, + 2.4329, 2.5866, 2.7380, 2.9107, 0.1297, 0.2532, 0.4003, 0.5329, + 0.6733, 0.7950, 0.9557, 1.0859, 1.2235, 1.3538, 1.5037, 1.6389, + 1.7964, 1.9285, 2.0898, 2.2541, 2.4231, 2.5711, 2.6875, 2.8947, + 0.0871, 0.1968, 0.3425, 0.4949, 0.6424, 0.7959, 0.9534, 1.1132, + 1.2656, 1.4229, 1.5785, 1.7271, 1.8729, 2.0355, 2.1998, 2.3562, + 2.5151, 2.6663, 2.8145, 2.9534, 0.1038, 0.2204, 0.3248, 0.4566, + 0.5947, 0.7443, 0.8811, 1.0379, 1.2031, 1.3772, 1.5430, 1.7092, + 1.8625, 2.0322, 2.1904, 2.3417, 2.4960, 2.6458, 2.7979, 2.9485, + 0.1329, 0.2763, 0.3943, 0.5147, 0.6512, 0.8071, 0.9410, 1.0879, + 1.2298, 1.3850, 1.5282, 1.6674, 1.8137, 1.9993, 2.1344, 2.2749, + 2.4257, 2.5863, 2.7410, 2.9184, 0.1052, 0.2142, 0.3584, 0.5033, + 0.6387, 0.7804, 0.9320, 1.0780, 1.2172, 1.3764, 1.5421, 1.6887, + 1.8246, 1.9833, 2.1245, 2.2797, 2.4237, 2.5779, 2.7257, 2.9097, + 0.1092, 0.2676, 0.4071, 0.5355, 0.6661, 0.8142, 0.9621, 1.1173, + 1.2628, 1.4185, 1.5696, 1.7220, 1.8595, 2.0178, 2.1720, 2.3221, + 2.4718, 2.6259, 2.7775, 2.9334, 0.0929, 0.2017, 0.3073, 0.4570, + 0.5775, 0.7635, 0.9299, 1.0832, 1.2334, 1.3935, 1.5420, 1.7112, + 1.8601, 2.0309, 2.1735, 2.3230, 2.4543, 2.6034, 2.7418, 2.8988, + 0.0775, 0.2005, 0.3490, 0.5200, 0.6747, 0.8383, 0.9885, 1.1738, + 1.3141, 1.4236, 1.5892, 1.7402, 1.8474, 2.0210, 2.1593, 2.2730, + 2.4235, 2.5604, 2.7128, 2.9005, 0.1104, 0.2292, 0.3353, 0.4732, + 0.6152, 0.7675, 0.9164, 1.0907, 1.2594, 1.4064, 1.5218, 1.6426, + 1.8018, 1.9937, 2.1362, 2.2961, 2.4523, 2.6083, 2.7613, 2.9202, + 0.0826, 0.2000, 0.3384, 0.5144, 0.6694, 0.8377, 0.9870, 1.1461, + 1.2950, 1.4495, 1.5872, 1.7387, 1.8793, 2.0329, 2.1723, 2.3114, + 2.4415, 2.5908, 2.7354, 2.9028, 0.1063, 0.2268, 0.3442, 0.4735, + 0.6116, 0.7507, 0.9028, 1.0768, 1.2426, 1.4052, 1.5566, 1.7015, + 1.8243, 1.9742, 2.1276, 2.2824, 2.4262, 2.5953, 2.7627, 2.9290, + 0.1150, 0.2814, 0.4543, 0.6095, 0.7373, 0.8592, 0.9908, 1.1108, + 1.2339, 1.3590, 1.4864, 1.6168, 1.7392, 1.8752, 2.0212, 2.1688, + 2.3128, 2.4869, 2.7019, 2.9239, 0.0948, 0.2074, 0.3433, 0.4943, + 0.6346, 0.7645, 0.8809, 1.0610, 1.2307, 1.3487, 1.4655, 1.6186, + 1.7534, 1.8859, 2.0486, 2.2200, 2.3835, 2.5581, 2.7565, 2.9502, + 0.1062, 0.2239, 0.3683, 0.5197, 0.6704, 0.8184, 0.9642, 1.1127, + 1.2556, 1.3976, 1.5405, 1.6940, 1.8375, 1.9888, 2.1377, 2.2980, + 2.4555, 2.6184, 2.7849, 2.9452, 0.0888, 0.2005, 0.2847, 0.4322, + 0.5763, 0.7577, 0.9262, 1.1095, 1.2719, 1.4331, 1.5843, 1.7452, + 1.8845, 2.0385, 2.1805, 2.3345, 2.4750, 2.6217, 2.7555, 2.9013, + 0.1713, 0.2617, 0.3868, 0.5859, 0.7073, 0.8535, 1.0593, 1.1778, + 1.3109, 1.4508, 1.5910, 1.7463, 1.8911, 2.0651, 2.2035, 2.3355, + 2.4947, 2.6440, 2.7424, 2.8943, 0.1346, 0.2549, 0.4089, 0.5488, + 0.6949, 0.8394, 0.9810, 1.1145, 1.2528, 1.4044, 1.5423, 1.6872, + 1.8274, 1.9726, 2.1403, 2.2809, 2.4128, 2.5564, 2.6887, 2.8895, + 0.0776, 0.1621, 0.2553, 0.4191, 0.5988, 0.7921, 0.9651, 1.1350, + 1.2930, 1.4475, 1.6011, 1.7585, 1.9068, 2.0638, 2.2102, 2.3594, + 2.5096, 2.6581, 2.8099, 2.9654, 0.0864, 0.1778, 0.2854, 0.4235, + 0.5568, 0.7220, 0.8963, 1.0609, 1.2217, 1.3830, 1.5422, 1.7018, + 1.8551, 2.0206, 2.1783, 2.3328, 2.4869, 2.6366, 2.7923, 2.9539, + 0.1144, 0.2576, 0.4186, 0.5594, 0.6875, 0.8221, 0.9598, 1.0944, + 1.2273, 1.3713, 1.5152, 1.6628, 1.8070, 1.9525, 2.0965, 2.2535, + 2.4132, 2.5725, 2.7250, 2.9150, 0.1079, 0.2221, 0.3334, 0.4845, + 0.6083, 0.7516, 0.9018, 1.0594, 1.2060, 1.3673, 1.5212, 1.6880, + 1.8208, 1.9831, 2.1269, 2.2909, 2.4366, 2.6027, 2.7339, 2.8924, + 0.0994, 0.2233, 0.3634, 0.5145, 0.6568, 0.8131, 0.9746, 1.1296, + 1.2666, 1.4116, 1.5748, 1.7264, 1.8649, 2.0217, 2.1716, 2.3293, + 2.4900, 2.6455, 2.7818, 2.9362, 0.1120, 0.2079, 0.3128, 0.4124, + 0.5291, 0.6816, 0.8478, 1.0150, 1.1772, 1.3456, 1.5208, 1.6882, + 1.8458, 2.0078, 2.1627, 2.3198, 2.4733, 2.6251, 2.7796, 2.9489, + 0.0853, 0.2030, 0.3669, 0.5326, 0.6678, 0.8086, 0.9526, 1.1142, + 1.2551, 1.4158, 1.5694, 1.7073, 1.8431, 1.9686, 2.1153, 2.2376, + 2.3686, 2.5591, 2.7320, 2.9104, 0.0905, 0.2166, 0.3539, 0.5201, + 0.6700, 0.8346, 0.9883, 1.1457, 1.2714, 1.3845, 1.5172, 1.6688, + 1.8008, 1.9535, 2.1019, 2.2708, 2.4135, 2.5974, 2.7486, 2.9033, + 0.0084, 0.0374, 0.0164, -0.0153, 0.0288, 0.0107, -0.0255, -0.0242, + 0.0000, -0.0055, -0.0081, -0.0075, -0.0022, -0.0052, -0.0069, -0.0017, + 0.0003, 0.0091, 0.0028, -0.0027, 0.0085, 0.0043, -0.0235, -0.0411, + 0.0202, 0.0359, 0.0376, 0.0321, 0.0306, -0.0358, -0.0276, -0.0090, + 0.0032, 0.0048, 0.0309, 0.0332, 0.0284, 0.0237, 0.0051, -0.0101, +-0.0233, -0.0428, -0.0585, -0.0387, 0.0039, 0.0081, 0.0029, -0.0017, +-0.0006, -0.0068, 0.0044, 0.0182, 0.0376, 0.0387, -0.0334, -0.0269, +-0.0182, -0.0069, -0.0026, 0.0035, -0.0049, -0.0212, -0.0408, -0.0245, + 0.0186, 0.0189, 0.0153, 0.0120, 0.0157, 0.0055, -0.0046, 0.0179, + 0.0284, -0.0032, -0.0261, -0.0205, -0.0039, 0.0174, 0.0299, 0.0207, + 0.0012, -0.0056, 0.0010, 0.0141, -0.0119, 0.0190, 0.0315, 0.0033, +-0.0128, 0.0300, 0.0328, 0.0308, 0.0353, 0.0266, 0.0066, -0.0328, +-0.0273, 0.0054, 0.0145, 0.0175, 0.0015, -0.0171, 0.0062, -0.0164, + 0.0045, -0.0071, 0.0025, 0.0278, 0.0283, 0.0117, -0.0026, -0.0285, +-0.0408, -0.0366, -0.0059, -0.0208, -0.0354, -0.0334, -0.0263, -0.0064, + 0.0072, -0.0006, -0.0235, -0.0037, -0.0307, -0.0294, -0.0163, -0.0197, +-0.0235, 0.0192, 0.0013, -0.0219, -0.0123, -0.0004, -0.0081, -0.0096, +-0.0123, -0.0101, 0.0021, 0.0151, 0.0106, 0.0151, 0.0292, 0.0033, + 0.0283, 0.0124, 0.0058, -0.0017, -0.0038, 0.0152, 0.0141, 0.0132, + 0.0178, 0.0157, 0.0073, 0.0176, 0.0141, 0.0097, -0.0092, -0.0163, +-0.0230, -0.0134, -0.0099, -0.0147, 0.0040, -0.0183, -0.0175, -0.0080, +-0.0083, -0.0290, -0.0417, -0.0398, -0.0269, -0.0199, -0.0143, -0.0053, +-0.0099, -0.0054, -0.0199, -0.0219, -0.0170, 0.0107, 0.0194, 0.0035, + 0.0437, 0.0406, 0.0215, 0.0120, 0.0053, -0.0028, 0.0238, 0.0337, + 0.0217, 0.0011, 0.0227, 0.0244, 0.0327, 0.0378, 0.0437, 0.0356, +-0.0033, 0.0113, 0.0407, 0.0334, -0.0125, -0.0003, -0.0141, -0.0273, +-0.0137, -0.0079, -0.0145, -0.0071, 0.0114, 0.0181, 0.0150, 0.0085, +-0.0077, -0.0038, -0.0219, -0.0263, -0.0187, -0.0233, 0.0133, 0.0265, +-0.0156, -0.0091, -0.0110, -0.0016, 0.0143, 0.0177, 0.0240, 0.0082, +-0.0143, -0.0257, -0.0014, 0.0002, 0.0082, 0.0180, 0.0325, 0.0340, +-0.0153, -0.0389, -0.0240, 0.0082, 0.0140, 0.0046, -0.0138, -0.0378, +-0.0366, 0.0297, 0.0252, 0.0078, 0.0063, 0.0006, 0.0044, 0.0074, + 0.0094, 0.0113, 0.0105, 0.0137, 0.0438, 0.0262, -0.0078, -0.0185, +-0.0215, -0.0407, -0.0435, -0.0208, -0.0004, -0.0144, -0.0205, -0.0248, +-0.0159, -0.0069, -0.0153, 0.0132, 0.0355, 0.0298, 0.0120, 0.0072, + 0.0236, 0.0526, 0.0479, 0.0233, -0.0133, -0.0283, -0.0468, -0.0549, +-0.0370, 0.0032, 0.0056, 0.0023, 0.0050, 0.0024, 0.0279, 0.0116, +-0.0045, -0.0012, 0.0107, 0.0190, 0.0253, 0.0191, 0.0043, 0.0193, +-0.0348, -0.0246, 0.0123, 0.0210, 0.0135, -0.0096, -0.0109, -0.0076, +-0.0156, -0.0290, 0.0160, 0.0194, 0.0219, 0.0259, 0.0250, 0.0195, + 0.4948, 0.4961, 0.4940, 0.4878, 0.4849, 0.4727, 0.4571, 0.4551, + 0.4534, 0.4468, 0.4412, 0.4354, 0.4298, 0.4272, 0.4498, 0.4506, + 0.4560, 0.4592, 0.4758, 0.4941, 0.2476, 0.1771, 0.1974, 0.1881, + 0.1667, 0.1826, 0.2067, 0.2031, 0.1734, 0.1534, 0.1415, 0.1761, + 0.1897, 0.1772, 0.1651, 0.1247, 0.1041, 0.1231, 0.1809, 0.2234 + }, +}; + + +static const uint8_t tab7[][35] = { + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0}, + {0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, + {0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0} +}; + +static const uint8_t tab8[][5] = { + {0, 0, 0, 1, 1}, + {0, 1, 0, 0, 1}, + {1, 1, 0, 0, 0}, + {1, 0, 0, 1, 0}, + {0, 0, 0, 1, 1}, + {0, 1, 0, 0, 1}, + {1, 1, 0, 0, 0}, + {1, 0, 0, 1, 0}, + {0, 0, 0, 1, 1}, + {0, 1, 0, 0, 1}, + {1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0}, + {0, 1, 0, 1, 0} +}; + +static const uint8_t tab9[][45] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, + 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 + },{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + } +}; + +static const uint8_t tab10[][25] = +{ + {1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0}, + {1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0}, + {1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}, + {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1} +}; + +static const uint8_t tab11[][55] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 + },{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + },{ + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + },{ + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }, { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + },{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + },{ + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + },{ + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + },{ + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + } +}; + +static const uint8_t tab12[][15] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1}, +}; + +static const struct { + int size; + const uint8_t *tab; +} tabs[] = { + {0 , NULL}, + {5 , &tab8 [0][0]},{5 , &tab8 [0][0]}, {15, &tab12[0][0]}, + {5 , &tab8 [0][0]},{25, &tab10[0][0]}, {15, &tab12[0][0]}, + {35, &tab7 [0][0]},{5 , &tab8 [0][0]}, {45, &tab9 [0][0]}, + {25, &tab10[0][0]},{55, &tab11[0][0]}, {15, &tab12[0][0]} +}; + +#endif /* AVCODEC_TWINVQ_DATA_H */ diff --git a/ffmpeg/libavcodec/txd.c b/ffmpeg/libavcodec/txd.c new file mode 100644 index 0000000..e8d483f --- /dev/null +++ b/ffmpeg/libavcodec/txd.c @@ -0,0 +1,142 @@ +/* + * Renderware TeXture Dictionary (.txd) image decoder + * Copyright (c) 2007 Ivo van Poorten + * + * See also: http://wiki.multimedia.cx/index.php?title=TXD + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "bytestream.h" +#include "avcodec.h" +#include "internal.h" +#include "s3tc.h" + +static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) { + GetByteContext gb; + AVFrame * const p = data; + unsigned int version, w, h, d3d_format, depth, stride, flags; + unsigned int y, v; + uint8_t *ptr; + uint32_t *pal; + int ret; + + bytestream2_init(&gb, avpkt->data, avpkt->size); + version = bytestream2_get_le32(&gb); + bytestream2_skip(&gb, 72); + d3d_format = bytestream2_get_le32(&gb); + w = bytestream2_get_le16(&gb); + h = bytestream2_get_le16(&gb); + depth = bytestream2_get_byte(&gb); + bytestream2_skip(&gb, 2); + flags = bytestream2_get_byte(&gb); + + if (version < 8 || version > 9) { + av_log(avctx, AV_LOG_ERROR, "texture data version %i is unsupported\n", + version); + return AVERROR_PATCHWELCOME; + } + + if (depth == 8) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else if (depth == 16 || depth == 32) { + avctx->pix_fmt = AV_PIX_FMT_RGB32; + } else { + av_log(avctx, AV_LOG_ERROR, "depth of %i is unsupported\n", depth); + return AVERROR_PATCHWELCOME; + } + + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) + return ret; + if (w != avctx->width || h != avctx->height) + avcodec_set_dimensions(avctx, w, h); + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->pict_type = AV_PICTURE_TYPE_I; + + ptr = p->data[0]; + stride = p->linesize[0]; + + if (depth == 8) { + pal = (uint32_t *) p->data[1]; + for (y = 0; y < 256; y++) { + v = bytestream2_get_be32(&gb); + pal[y] = (v >> 8) + (v << 24); + } + if (bytestream2_get_bytes_left(&gb) < w * h) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gb, 4); + for (y=0; ysize; + +unsupported: + av_log(avctx, AV_LOG_ERROR, "unsupported d3d format (%08x)\n", d3d_format); + return AVERROR_PATCHWELCOME; +} + +AVCodec ff_txd_decoder = { + .name = "txd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_TXD, + .decode = txd_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), +}; diff --git a/ffmpeg/libavcodec/ulti.c b/ffmpeg/libavcodec/ulti.c new file mode 100644 index 0000000..2120d97 --- /dev/null +++ b/ffmpeg/libavcodec/ulti.c @@ -0,0 +1,429 @@ +/* + * IBM Ultimotion Video Decoder + * Copyright (C) 2004 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * IBM Ultimotion Video Decoder. + */ + +#include +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#include "ulti_cb.h" + +typedef struct UltimotionDecodeContext { + AVCodecContext *avctx; + int width, height, blocks; + AVFrame frame; + const uint8_t *ulti_codebook; + GetByteContext gb; +} UltimotionDecodeContext; + +static av_cold int ulti_decode_init(AVCodecContext *avctx) +{ + UltimotionDecodeContext *s = avctx->priv_data; + + s->avctx = avctx; + s->width = avctx->width; + s->height = avctx->height; + s->blocks = (s->width / 8) * (s->height / 8); + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + avctx->coded_frame = &s->frame; + avctx->coded_frame = (AVFrame*) &s->frame; + s->ulti_codebook = ulti_codebook; + avcodec_get_frame_defaults(&s->frame); + + return 0; +} + +static av_cold int ulti_decode_end(AVCodecContext *avctx){ + UltimotionDecodeContext *s = avctx->priv_data; + AVFrame *pic = &s->frame; + + av_frame_unref(pic); + + return 0; +} + +static const int block_coords[8] = // 4x4 block coords in 8x8 superblock + { 0, 0, 0, 4, 4, 4, 4, 0}; + +static const int angle_by_index[4] = { 0, 2, 6, 12}; + +/* Lookup tables for luma and chroma - used by ulti_convert_yuv() */ +static const uint8_t ulti_lumas[64] = + { 0x10, 0x13, 0x17, 0x1A, 0x1E, 0x21, 0x25, 0x28, + 0x2C, 0x2F, 0x33, 0x36, 0x3A, 0x3D, 0x41, 0x44, + 0x48, 0x4B, 0x4F, 0x52, 0x56, 0x59, 0x5C, 0x60, + 0x63, 0x67, 0x6A, 0x6E, 0x71, 0x75, 0x78, 0x7C, + 0x7F, 0x83, 0x86, 0x8A, 0x8D, 0x91, 0x94, 0x98, + 0x9B, 0x9F, 0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB3, + 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 0xCC, 0xCF, + 0xD3, 0xD6, 0xDA, 0xDD, 0xE1, 0xE4, 0xE8, 0xEB}; + +static const uint8_t ulti_chromas[16] = + { 0x60, 0x67, 0x6D, 0x73, 0x7A, 0x80, 0x86, 0x8D, + 0x93, 0x99, 0xA0, 0xA6, 0xAC, 0xB3, 0xB9, 0xC0}; + +/* convert Ultimotion YUV block (sixteen 6-bit Y samples and + two 4-bit chroma samples) into standard YUV and put it into frame */ +static void ulti_convert_yuv(AVFrame *frame, int x, int y, + uint8_t *luma,int chroma) +{ + uint8_t *y_plane, *cr_plane, *cb_plane; + int i; + + y_plane = frame->data[0] + x + y * frame->linesize[0]; + cr_plane = frame->data[1] + (x / 4) + (y / 4) * frame->linesize[1]; + cb_plane = frame->data[2] + (x / 4) + (y / 4) * frame->linesize[2]; + + cr_plane[0] = ulti_chromas[chroma >> 4]; + + cb_plane[0] = ulti_chromas[chroma & 0xF]; + + + for(i = 0; i < 16; i++){ + y_plane[i & 3] = ulti_lumas[luma[i]]; + if((i & 3) == 3) { //next row + y_plane += frame->linesize[0]; + } + } +} + +/* generate block like in MS Video1 */ +static void ulti_pattern(AVFrame *frame, int x, int y, + int f0, int f1, int Y0, int Y1, int chroma) +{ + uint8_t Luma[16]; + int mask, i; + for(mask = 0x80, i = 0; mask; mask >>= 1, i++) { + if(f0 & mask) + Luma[i] = Y1; + else + Luma[i] = Y0; + } + + for(mask = 0x80, i = 8; mask; mask >>= 1, i++) { + if(f1 & mask) + Luma[i] = Y1; + else + Luma[i] = Y0; + } + + ulti_convert_yuv(frame, x, y, Luma, chroma); +} + +/* fill block with some gradient */ +static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int angle) +{ + uint8_t Luma[16]; + if(angle & 8) { //reverse order + int t; + angle &= 0x7; + t = Y[0]; + Y[0] = Y[3]; + Y[3] = t; + t = Y[1]; + Y[1] = Y[2]; + Y[2] = t; + } + switch(angle){ + case 0: + Luma[0] = Y[0]; Luma[1] = Y[1]; Luma[2] = Y[2]; Luma[3] = Y[3]; + Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3]; + Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3]; + Luma[12] = Y[0]; Luma[13] = Y[1]; Luma[14] = Y[2]; Luma[15] = Y[3]; + break; + case 1: + Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3]; + Luma[4] = Y[0]; Luma[5] = Y[1]; Luma[6] = Y[2]; Luma[7] = Y[3]; + Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[2]; Luma[11] = Y[3]; + Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2]; + break; + case 2: + Luma[0] = Y[1]; Luma[1] = Y[2]; Luma[2] = Y[3]; Luma[3] = Y[3]; + Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3]; + Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2]; + Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[1]; Luma[15] = Y[2]; + break; + case 3: + Luma[0] = Y[2]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3]; + Luma[4] = Y[1]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[3]; + Luma[8] = Y[0]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[2]; + Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[1]; + break; + case 4: + Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[3]; + Luma[4] = Y[2]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[2]; + Luma[8] = Y[1]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[1]; + Luma[12] = Y[0]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0]; + break; + case 5: + Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[3]; Luma[3] = Y[2]; + Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[2]; Luma[7] = Y[1]; + Luma[8] = Y[2]; Luma[9] = Y[1]; Luma[10] = Y[1]; Luma[11] = Y[0]; + Luma[12] = Y[1]; Luma[13] = Y[0]; Luma[14] = Y[0]; Luma[15] = Y[0]; + break; + case 6: + Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[2]; + Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[1]; + Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0]; + Luma[12] = Y[1]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0]; + break; + case 7: + Luma[0] = Y[3]; Luma[1] = Y[3]; Luma[2] = Y[2]; Luma[3] = Y[1]; + Luma[4] = Y[3]; Luma[5] = Y[2]; Luma[6] = Y[1]; Luma[7] = Y[0]; + Luma[8] = Y[3]; Luma[9] = Y[2]; Luma[10] = Y[1]; Luma[11] = Y[0]; + Luma[12] = Y[2]; Luma[13] = Y[1]; Luma[14] = Y[0]; Luma[15] = Y[0]; + break; + default: + Luma[0] = Y[0]; Luma[1] = Y[0]; Luma[2] = Y[1]; Luma[3] = Y[1]; + Luma[4] = Y[0]; Luma[5] = Y[0]; Luma[6] = Y[1]; Luma[7] = Y[1]; + Luma[8] = Y[2]; Luma[9] = Y[2]; Luma[10] = Y[3]; Luma[11] = Y[3]; + Luma[12] = Y[2]; Luma[13] = Y[2]; Luma[14] = Y[3]; Luma[15] = Y[3]; + break; + } + + ulti_convert_yuv(frame, x, y, Luma, chroma); +} + +static int ulti_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + UltimotionDecodeContext *s=avctx->priv_data; + int modifier = 0; + int uniq = 0; + int mode = 0; + int blocks = 0; + int done = 0; + int x = 0, y = 0; + int i, ret; + int skip; + int tmp; + + if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) + return ret; + + bytestream2_init(&s->gb, buf, buf_size); + + while(!done) { + int idx; + if(blocks >= s->blocks || y >= s->height) + break;//all blocks decoded + + if (bytestream2_get_bytes_left(&s->gb) < 1) + goto err; + idx = bytestream2_get_byteu(&s->gb); + if((idx & 0xF8) == 0x70) { + switch(idx) { + case 0x70: //change modifier + modifier = bytestream2_get_byte(&s->gb); + if(modifier>1) + av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); + break; + case 0x71: // set uniq flag + uniq = 1; + break; + case 0x72: //toggle mode + mode = !mode; + break; + case 0x73: //end-of-frame + done = 1; + break; + case 0x74: //skip some blocks + skip = bytestream2_get_byte(&s->gb); + if ((blocks + skip) >= s->blocks) + break; + blocks += skip; + x += skip * 8; + while(x >= s->width) { + x -= s->width; + y += 8; + } + break; + default: + av_log(avctx, AV_LOG_INFO, "warning: unknown escape 0x%02X\n", idx); + } + } else { //handle one block + int code; + int cf; + int angle = 0; + uint8_t Y[4]; // luma samples of block + int tx = 0, ty = 0; //coords of subblock + int chroma = 0; + if (mode || uniq) { + uniq = 0; + cf = 1; + chroma = 0; + } else { + cf = 0; + if (idx) { + chroma = bytestream2_get_byte(&s->gb); + } + } + for (i = 0; i < 4; i++) { // for every subblock + code = (idx >> (6 - i*2)) & 3; //extract 2 bits + if(!code) //skip subblock + continue; + if(cf) { + chroma = bytestream2_get_byte(&s->gb); + } + tx = x + block_coords[i * 2]; + ty = y + block_coords[(i * 2) + 1]; + switch(code) { + case 1: + tmp = bytestream2_get_byte(&s->gb); + + angle = angle_by_index[(tmp >> 6) & 0x3]; + + Y[0] = tmp & 0x3F; + Y[1] = Y[0]; + + if (angle) { + Y[2] = Y[0]+1; + if (Y[2] > 0x3F) + Y[2] = 0x3F; + Y[3] = Y[2]; + } else { + Y[2] = Y[0]; + Y[3] = Y[0]; + } + break; + + case 2: + if (modifier) { // unpack four luma samples + tmp = bytestream2_get_be24(&s->gb); + + Y[0] = (tmp >> 18) & 0x3F; + Y[1] = (tmp >> 12) & 0x3F; + Y[2] = (tmp >> 6) & 0x3F; + Y[3] = tmp & 0x3F; + angle = 16; + } else { // retrieve luma samples from codebook + tmp = bytestream2_get_be16(&s->gb); + + angle = (tmp >> 12) & 0xF; + tmp &= 0xFFF; + tmp <<= 2; + Y[0] = s->ulti_codebook[tmp]; + Y[1] = s->ulti_codebook[tmp + 1]; + Y[2] = s->ulti_codebook[tmp + 2]; + Y[3] = s->ulti_codebook[tmp + 3]; + } + break; + + case 3: + if (modifier) { // all 16 luma samples + uint8_t Luma[16]; + + if (bytestream2_get_bytes_left(&s->gb) < 12) + goto err; + tmp = bytestream2_get_be24u(&s->gb); + Luma[0] = (tmp >> 18) & 0x3F; + Luma[1] = (tmp >> 12) & 0x3F; + Luma[2] = (tmp >> 6) & 0x3F; + Luma[3] = tmp & 0x3F; + + tmp = bytestream2_get_be24u(&s->gb); + Luma[4] = (tmp >> 18) & 0x3F; + Luma[5] = (tmp >> 12) & 0x3F; + Luma[6] = (tmp >> 6) & 0x3F; + Luma[7] = tmp & 0x3F; + + tmp = bytestream2_get_be24u(&s->gb); + Luma[8] = (tmp >> 18) & 0x3F; + Luma[9] = (tmp >> 12) & 0x3F; + Luma[10] = (tmp >> 6) & 0x3F; + Luma[11] = tmp & 0x3F; + + tmp = bytestream2_get_be24u(&s->gb); + Luma[12] = (tmp >> 18) & 0x3F; + Luma[13] = (tmp >> 12) & 0x3F; + Luma[14] = (tmp >> 6) & 0x3F; + Luma[15] = tmp & 0x3F; + + ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); + } else { + if (bytestream2_get_bytes_left(&s->gb) < 4) + goto err; + tmp = bytestream2_get_byteu(&s->gb); + if(tmp & 0x80) { + angle = (tmp >> 4) & 0x7; + tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb); + Y[0] = (tmp >> 6) & 0x3F; + Y[1] = tmp & 0x3F; + Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F; + Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F; + ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block + } else { // some patterns + int f0, f1; + f0 = bytestream2_get_byteu(&s->gb); + f1 = tmp; + Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F; + Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F; + ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); + } + } + break; + } + if(code != 3) + ulti_grad(&s->frame, tx, ty, Y, chroma, angle); // draw block + } + blocks++; + x += 8; + if(x >= s->width) { + x = 0; + y += 8; + } + } + } + + *got_frame = 1; + if ((ret = av_frame_ref(data, &s->frame)) < 0) + return ret; + + return buf_size; + +err: + av_log(avctx, AV_LOG_ERROR, + "Insufficient data\n"); + return AVERROR_INVALIDDATA; +} + +AVCodec ff_ulti_decoder = { + .name = "ultimotion", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ULTI, + .priv_data_size = sizeof(UltimotionDecodeContext), + .init = ulti_decode_init, + .close = ulti_decode_end, + .decode = ulti_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"), +}; diff --git a/ffmpeg/libavcodec/ulti_cb.h b/ffmpeg/libavcodec/ulti_cb.h new file mode 100644 index 0000000..7061d83 --- /dev/null +++ b/ffmpeg/libavcodec/ulti_cb.h @@ -0,0 +1,4124 @@ +/* + * IBM Ultimotion Video Decoder + * copyright (C) 2004 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_ULTI_CB_H +#define AVCODEC_ULTI_CB_H + +static const unsigned char ulti_codebook[16384]={ + 0x00, 0x01, 0x01, 0x02, + 0x00, 0x01, 0x02, 0x03, + 0x00, 0x02, 0x03, 0x04, + 0x00, 0x01, 0x03, 0x04, + 0x00, 0x01, 0x02, 0x04, + 0x00, 0x02, 0x03, 0x05, + 0x00, 0x02, 0x04, 0x05, + 0x00, 0x01, 0x04, 0x05, + 0x00, 0x01, 0x03, 0x05, + 0x00, 0x02, 0x04, 0x06, + 0x00, 0x03, 0x05, 0x06, + 0x00, 0x01, 0x05, 0x06, + 0x00, 0x01, 0x03, 0x06, + 0x00, 0x06, 0x06, 0x06, + 0x00, 0x00, 0x06, 0x06, + 0x00, 0x00, 0x00, 0x06, + 0x00, 0x03, 0x04, 0x07, + 0x00, 0x03, 0x06, 0x07, + 0x00, 0x01, 0x06, 0x07, + 0x00, 0x01, 0x04, 0x07, + 0x00, 0x03, 0x05, 0x08, + 0x00, 0x04, 0x06, 0x08, + 0x00, 0x02, 0x06, 0x08, + 0x00, 0x02, 0x04, 0x08, + 0x00, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x08, 0x08, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x04, 0x07, 0x0B, + 0x00, 0x05, 0x09, 0x0B, + 0x00, 0x02, 0x09, 0x0B, + 0x00, 0x02, 0x06, 0x0B, + 0x00, 0x0B, 0x0B, 0x0B, + 0x00, 0x00, 0x0B, 0x0B, + 0x00, 0x00, 0x00, 0x0B, + 0x00, 0x05, 0x09, 0x0E, + 0x00, 0x07, 0x0B, 0x0E, + 0x00, 0x03, 0x0B, 0x0E, + 0x00, 0x03, 0x07, 0x0E, + 0x00, 0x0E, 0x0E, 0x0E, + 0x00, 0x00, 0x0E, 0x0E, + 0x00, 0x00, 0x00, 0x0E, + 0x00, 0x06, 0x0B, 0x11, + 0x00, 0x08, 0x0D, 0x11, + 0x00, 0x04, 0x0D, 0x11, + 0x00, 0x04, 0x09, 0x11, + 0x00, 0x11, 0x11, 0x11, + 0x00, 0x00, 0x11, 0x11, + 0x00, 0x00, 0x00, 0x11, + 0x00, 0x07, 0x0D, 0x14, + 0x00, 0x0A, 0x0F, 0x14, + 0x00, 0x05, 0x0F, 0x14, + 0x00, 0x05, 0x0A, 0x14, + 0x00, 0x14, 0x14, 0x14, + 0x00, 0x00, 0x14, 0x14, + 0x00, 0x00, 0x00, 0x14, + 0x00, 0x0B, 0x12, 0x17, + 0x00, 0x05, 0x12, 0x17, + 0x00, 0x05, 0x0C, 0x17, + 0x00, 0x17, 0x17, 0x17, + 0x00, 0x00, 0x17, 0x17, + 0x00, 0x00, 0x00, 0x17, + 0x00, 0x0D, 0x14, 0x1A, + 0x00, 0x06, 0x14, 0x1A, + 0x00, 0x06, 0x0D, 0x1A, + 0x00, 0x1A, 0x1A, 0x1A, + 0x00, 0x00, 0x1A, 0x1A, + 0x00, 0x00, 0x00, 0x1A, + 0x00, 0x0E, 0x16, 0x1D, + 0x00, 0x07, 0x16, 0x1D, + 0x00, 0x07, 0x0F, 0x1D, + 0x00, 0x1D, 0x1D, 0x1D, + 0x00, 0x00, 0x1D, 0x1D, + 0x00, 0x00, 0x00, 0x1D, + 0x00, 0x10, 0x18, 0x20, + 0x00, 0x08, 0x18, 0x20, + 0x00, 0x08, 0x10, 0x20, + 0x00, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x20, + 0x00, 0x23, 0x23, 0x23, + 0x00, 0x00, 0x23, 0x23, + 0x00, 0x00, 0x00, 0x23, + 0x00, 0x12, 0x1B, 0x24, + 0x00, 0x09, 0x1B, 0x24, + 0x00, 0x09, 0x12, 0x24, + 0x00, 0x28, 0x28, 0x28, + 0x00, 0x00, 0x28, 0x28, + 0x00, 0x00, 0x00, 0x28, + 0x00, 0x2E, 0x2E, 0x2E, + 0x00, 0x00, 0x2E, 0x2E, + 0x00, 0x00, 0x00, 0x2E, + 0x01, 0x02, 0x02, 0x03, + 0x01, 0x02, 0x03, 0x04, + 0x01, 0x03, 0x04, 0x05, + 0x01, 0x02, 0x04, 0x05, + 0x01, 0x02, 0x03, 0x05, + 0x01, 0x03, 0x04, 0x06, + 0x01, 0x03, 0x05, 0x06, + 0x01, 0x02, 0x05, 0x06, + 0x01, 0x02, 0x04, 0x06, + 0x01, 0x03, 0x05, 0x07, + 0x01, 0x04, 0x06, 0x07, + 0x01, 0x02, 0x06, 0x07, + 0x01, 0x02, 0x04, 0x07, + 0x01, 0x07, 0x07, 0x07, + 0x01, 0x01, 0x07, 0x07, + 0x01, 0x01, 0x01, 0x07, + 0x01, 0x04, 0x05, 0x08, + 0x01, 0x04, 0x07, 0x08, + 0x01, 0x02, 0x07, 0x08, + 0x01, 0x02, 0x05, 0x08, + 0x01, 0x04, 0x06, 0x09, + 0x01, 0x05, 0x07, 0x09, + 0x01, 0x03, 0x07, 0x09, + 0x01, 0x03, 0x05, 0x09, + 0x01, 0x09, 0x09, 0x09, + 0x01, 0x01, 0x09, 0x09, + 0x01, 0x01, 0x01, 0x09, + 0x01, 0x05, 0x08, 0x0C, + 0x01, 0x06, 0x0A, 0x0C, + 0x01, 0x03, 0x0A, 0x0C, + 0x01, 0x03, 0x07, 0x0C, + 0x01, 0x0C, 0x0C, 0x0C, + 0x01, 0x01, 0x0C, 0x0C, + 0x01, 0x01, 0x01, 0x0C, + 0x01, 0x06, 0x0A, 0x0F, + 0x01, 0x08, 0x0C, 0x0F, + 0x01, 0x04, 0x0C, 0x0F, + 0x01, 0x04, 0x08, 0x0F, + 0x01, 0x0F, 0x0F, 0x0F, + 0x01, 0x01, 0x0F, 0x0F, + 0x01, 0x01, 0x01, 0x0F, + 0x01, 0x07, 0x0C, 0x12, + 0x01, 0x09, 0x0E, 0x12, + 0x01, 0x05, 0x0E, 0x12, + 0x01, 0x05, 0x0A, 0x12, + 0x01, 0x12, 0x12, 0x12, + 0x01, 0x01, 0x12, 0x12, + 0x01, 0x01, 0x01, 0x12, + 0x01, 0x08, 0x0E, 0x15, + 0x01, 0x0B, 0x10, 0x15, + 0x01, 0x06, 0x10, 0x15, + 0x01, 0x06, 0x0B, 0x15, + 0x01, 0x15, 0x15, 0x15, + 0x01, 0x01, 0x15, 0x15, + 0x01, 0x01, 0x01, 0x15, + 0x01, 0x0C, 0x13, 0x18, + 0x01, 0x06, 0x13, 0x18, + 0x01, 0x06, 0x0D, 0x18, + 0x01, 0x18, 0x18, 0x18, + 0x01, 0x01, 0x18, 0x18, + 0x01, 0x01, 0x01, 0x18, + 0x01, 0x0E, 0x15, 0x1B, + 0x01, 0x07, 0x15, 0x1B, + 0x01, 0x07, 0x0E, 0x1B, + 0x01, 0x1B, 0x1B, 0x1B, + 0x01, 0x01, 0x1B, 0x1B, + 0x01, 0x01, 0x01, 0x1B, + 0x01, 0x0F, 0x17, 0x1E, + 0x01, 0x08, 0x17, 0x1E, + 0x01, 0x08, 0x10, 0x1E, + 0x01, 0x1E, 0x1E, 0x1E, + 0x01, 0x01, 0x1E, 0x1E, + 0x01, 0x01, 0x01, 0x1E, + 0x01, 0x11, 0x19, 0x21, + 0x01, 0x09, 0x19, 0x21, + 0x01, 0x09, 0x11, 0x21, + 0x01, 0x21, 0x21, 0x21, + 0x01, 0x01, 0x21, 0x21, + 0x01, 0x01, 0x01, 0x21, + 0x01, 0x24, 0x24, 0x24, + 0x01, 0x01, 0x24, 0x24, + 0x01, 0x01, 0x01, 0x24, + 0x01, 0x13, 0x1C, 0x25, + 0x01, 0x0A, 0x1C, 0x25, + 0x01, 0x0A, 0x13, 0x25, + 0x01, 0x29, 0x29, 0x29, + 0x01, 0x01, 0x29, 0x29, + 0x01, 0x01, 0x01, 0x29, + 0x01, 0x2F, 0x2F, 0x2F, + 0x01, 0x01, 0x2F, 0x2F, + 0x01, 0x01, 0x01, 0x2F, + 0x02, 0x03, 0x03, 0x04, + 0x02, 0x03, 0x04, 0x05, + 0x02, 0x04, 0x05, 0x06, + 0x02, 0x03, 0x05, 0x06, + 0x02, 0x03, 0x04, 0x06, + 0x02, 0x04, 0x05, 0x07, + 0x02, 0x04, 0x06, 0x07, + 0x02, 0x03, 0x06, 0x07, + 0x02, 0x03, 0x05, 0x07, + 0x02, 0x04, 0x06, 0x08, + 0x02, 0x05, 0x07, 0x08, + 0x02, 0x03, 0x07, 0x08, + 0x02, 0x03, 0x05, 0x08, + 0x02, 0x08, 0x08, 0x08, + 0x02, 0x02, 0x08, 0x08, + 0x02, 0x02, 0x02, 0x08, + 0x02, 0x05, 0x06, 0x09, + 0x02, 0x05, 0x08, 0x09, + 0x02, 0x03, 0x08, 0x09, + 0x02, 0x03, 0x06, 0x09, + 0x02, 0x05, 0x07, 0x0A, + 0x02, 0x06, 0x08, 0x0A, + 0x02, 0x04, 0x08, 0x0A, + 0x02, 0x04, 0x06, 0x0A, + 0x02, 0x0A, 0x0A, 0x0A, + 0x02, 0x02, 0x0A, 0x0A, + 0x02, 0x02, 0x02, 0x0A, + 0x02, 0x06, 0x09, 0x0D, + 0x02, 0x07, 0x0B, 0x0D, + 0x02, 0x04, 0x0B, 0x0D, + 0x02, 0x04, 0x08, 0x0D, + 0x02, 0x0D, 0x0D, 0x0D, + 0x02, 0x02, 0x0D, 0x0D, + 0x02, 0x02, 0x02, 0x0D, + 0x02, 0x07, 0x0B, 0x10, + 0x02, 0x09, 0x0D, 0x10, + 0x02, 0x05, 0x0D, 0x10, + 0x02, 0x05, 0x09, 0x10, + 0x02, 0x10, 0x10, 0x10, + 0x02, 0x02, 0x10, 0x10, + 0x02, 0x02, 0x02, 0x10, + 0x02, 0x08, 0x0D, 0x13, + 0x02, 0x0A, 0x0F, 0x13, + 0x02, 0x06, 0x0F, 0x13, + 0x02, 0x06, 0x0B, 0x13, + 0x02, 0x13, 0x13, 0x13, + 0x02, 0x02, 0x13, 0x13, + 0x02, 0x02, 0x02, 0x13, + 0x02, 0x09, 0x0F, 0x16, + 0x02, 0x0C, 0x11, 0x16, + 0x02, 0x07, 0x11, 0x16, + 0x02, 0x07, 0x0C, 0x16, + 0x02, 0x16, 0x16, 0x16, + 0x02, 0x02, 0x16, 0x16, + 0x02, 0x02, 0x02, 0x16, + 0x02, 0x0D, 0x14, 0x19, + 0x02, 0x07, 0x14, 0x19, + 0x02, 0x07, 0x0E, 0x19, + 0x02, 0x19, 0x19, 0x19, + 0x02, 0x02, 0x19, 0x19, + 0x02, 0x02, 0x02, 0x19, + 0x02, 0x0F, 0x16, 0x1C, + 0x02, 0x08, 0x16, 0x1C, + 0x02, 0x08, 0x0F, 0x1C, + 0x02, 0x1C, 0x1C, 0x1C, + 0x02, 0x02, 0x1C, 0x1C, + 0x02, 0x02, 0x02, 0x1C, + 0x02, 0x10, 0x18, 0x1F, + 0x02, 0x09, 0x18, 0x1F, + 0x02, 0x09, 0x11, 0x1F, + 0x02, 0x1F, 0x1F, 0x1F, + 0x02, 0x02, 0x1F, 0x1F, + 0x02, 0x02, 0x02, 0x1F, + 0x02, 0x12, 0x1A, 0x22, + 0x02, 0x0A, 0x1A, 0x22, + 0x02, 0x0A, 0x12, 0x22, + 0x02, 0x22, 0x22, 0x22, + 0x02, 0x02, 0x22, 0x22, + 0x02, 0x02, 0x02, 0x22, + 0x02, 0x25, 0x25, 0x25, + 0x02, 0x02, 0x25, 0x25, + 0x02, 0x02, 0x02, 0x25, + 0x02, 0x14, 0x1D, 0x26, + 0x02, 0x0B, 0x1D, 0x26, + 0x02, 0x0B, 0x14, 0x26, + 0x02, 0x2A, 0x2A, 0x2A, + 0x02, 0x02, 0x2A, 0x2A, + 0x02, 0x02, 0x02, 0x2A, + 0x02, 0x30, 0x30, 0x30, + 0x02, 0x02, 0x30, 0x30, + 0x02, 0x02, 0x02, 0x30, + 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x05, 0x06, + 0x03, 0x05, 0x06, 0x07, + 0x03, 0x04, 0x06, 0x07, + 0x03, 0x04, 0x05, 0x07, + 0x03, 0x05, 0x06, 0x08, + 0x03, 0x05, 0x07, 0x08, + 0x03, 0x04, 0x07, 0x08, + 0x03, 0x04, 0x06, 0x08, + 0x03, 0x05, 0x07, 0x09, + 0x03, 0x06, 0x08, 0x09, + 0x03, 0x04, 0x08, 0x09, + 0x03, 0x04, 0x06, 0x09, + 0x03, 0x09, 0x09, 0x09, + 0x03, 0x03, 0x09, 0x09, + 0x03, 0x03, 0x03, 0x09, + 0x03, 0x06, 0x07, 0x0A, + 0x03, 0x06, 0x09, 0x0A, + 0x03, 0x04, 0x09, 0x0A, + 0x03, 0x04, 0x07, 0x0A, + 0x03, 0x06, 0x08, 0x0B, + 0x03, 0x07, 0x09, 0x0B, + 0x03, 0x05, 0x09, 0x0B, + 0x03, 0x05, 0x07, 0x0B, + 0x03, 0x0B, 0x0B, 0x0B, + 0x03, 0x03, 0x0B, 0x0B, + 0x03, 0x03, 0x03, 0x0B, + 0x03, 0x07, 0x0A, 0x0E, + 0x03, 0x08, 0x0C, 0x0E, + 0x03, 0x05, 0x0C, 0x0E, + 0x03, 0x05, 0x09, 0x0E, + 0x03, 0x0E, 0x0E, 0x0E, + 0x03, 0x03, 0x0E, 0x0E, + 0x03, 0x03, 0x03, 0x0E, + 0x03, 0x08, 0x0C, 0x11, + 0x03, 0x0A, 0x0E, 0x11, + 0x03, 0x06, 0x0E, 0x11, + 0x03, 0x06, 0x0A, 0x11, + 0x03, 0x11, 0x11, 0x11, + 0x03, 0x03, 0x11, 0x11, + 0x03, 0x03, 0x03, 0x11, + 0x03, 0x09, 0x0E, 0x14, + 0x03, 0x0B, 0x10, 0x14, + 0x03, 0x07, 0x10, 0x14, + 0x03, 0x07, 0x0C, 0x14, + 0x03, 0x14, 0x14, 0x14, + 0x03, 0x03, 0x14, 0x14, + 0x03, 0x03, 0x03, 0x14, + 0x03, 0x0A, 0x10, 0x17, + 0x03, 0x0D, 0x12, 0x17, + 0x03, 0x08, 0x12, 0x17, + 0x03, 0x08, 0x0D, 0x17, + 0x03, 0x17, 0x17, 0x17, + 0x03, 0x03, 0x17, 0x17, + 0x03, 0x03, 0x03, 0x17, + 0x03, 0x0E, 0x15, 0x1A, + 0x03, 0x08, 0x15, 0x1A, + 0x03, 0x08, 0x0F, 0x1A, + 0x03, 0x1A, 0x1A, 0x1A, + 0x03, 0x03, 0x1A, 0x1A, + 0x03, 0x03, 0x03, 0x1A, + 0x03, 0x10, 0x17, 0x1D, + 0x03, 0x09, 0x17, 0x1D, + 0x03, 0x09, 0x10, 0x1D, + 0x03, 0x1D, 0x1D, 0x1D, + 0x03, 0x03, 0x1D, 0x1D, + 0x03, 0x03, 0x03, 0x1D, + 0x03, 0x11, 0x19, 0x20, + 0x03, 0x0A, 0x19, 0x20, + 0x03, 0x0A, 0x12, 0x20, + 0x03, 0x20, 0x20, 0x20, + 0x03, 0x03, 0x20, 0x20, + 0x03, 0x03, 0x03, 0x20, + 0x03, 0x13, 0x1B, 0x23, + 0x03, 0x0B, 0x1B, 0x23, + 0x03, 0x0B, 0x13, 0x23, + 0x03, 0x23, 0x23, 0x23, + 0x03, 0x03, 0x23, 0x23, + 0x03, 0x03, 0x03, 0x23, + 0x03, 0x26, 0x26, 0x26, + 0x03, 0x03, 0x26, 0x26, + 0x03, 0x03, 0x03, 0x26, + 0x03, 0x15, 0x1E, 0x27, + 0x03, 0x0C, 0x1E, 0x27, + 0x03, 0x0C, 0x15, 0x27, + 0x03, 0x2B, 0x2B, 0x2B, + 0x03, 0x03, 0x2B, 0x2B, + 0x03, 0x03, 0x03, 0x2B, + 0x03, 0x31, 0x31, 0x31, + 0x03, 0x03, 0x31, 0x31, + 0x03, 0x03, 0x03, 0x31, + 0x04, 0x05, 0x05, 0x06, + 0x04, 0x05, 0x06, 0x07, + 0x04, 0x06, 0x07, 0x08, + 0x04, 0x05, 0x07, 0x08, + 0x04, 0x05, 0x06, 0x08, + 0x04, 0x06, 0x07, 0x09, + 0x04, 0x06, 0x08, 0x09, + 0x04, 0x05, 0x08, 0x09, + 0x04, 0x05, 0x07, 0x09, + 0x04, 0x06, 0x08, 0x0A, + 0x04, 0x07, 0x09, 0x0A, + 0x04, 0x05, 0x09, 0x0A, + 0x04, 0x05, 0x07, 0x0A, + 0x04, 0x0A, 0x0A, 0x0A, + 0x04, 0x04, 0x0A, 0x0A, + 0x04, 0x04, 0x04, 0x0A, + 0x04, 0x07, 0x08, 0x0B, + 0x04, 0x07, 0x0A, 0x0B, + 0x04, 0x05, 0x0A, 0x0B, + 0x04, 0x05, 0x08, 0x0B, + 0x04, 0x07, 0x09, 0x0C, + 0x04, 0x08, 0x0A, 0x0C, + 0x04, 0x06, 0x0A, 0x0C, + 0x04, 0x06, 0x08, 0x0C, + 0x04, 0x0C, 0x0C, 0x0C, + 0x04, 0x04, 0x0C, 0x0C, + 0x04, 0x04, 0x04, 0x0C, + 0x04, 0x08, 0x0B, 0x0F, + 0x04, 0x09, 0x0D, 0x0F, + 0x04, 0x06, 0x0D, 0x0F, + 0x04, 0x06, 0x0A, 0x0F, + 0x04, 0x0F, 0x0F, 0x0F, + 0x04, 0x04, 0x0F, 0x0F, + 0x04, 0x04, 0x04, 0x0F, + 0x04, 0x09, 0x0D, 0x12, + 0x04, 0x0B, 0x0F, 0x12, + 0x04, 0x07, 0x0F, 0x12, + 0x04, 0x07, 0x0B, 0x12, + 0x04, 0x12, 0x12, 0x12, + 0x04, 0x04, 0x12, 0x12, + 0x04, 0x04, 0x04, 0x12, + 0x04, 0x0A, 0x0F, 0x15, + 0x04, 0x0C, 0x11, 0x15, + 0x04, 0x08, 0x11, 0x15, + 0x04, 0x08, 0x0D, 0x15, + 0x04, 0x15, 0x15, 0x15, + 0x04, 0x04, 0x15, 0x15, + 0x04, 0x04, 0x04, 0x15, + 0x04, 0x0B, 0x11, 0x18, + 0x04, 0x0E, 0x13, 0x18, + 0x04, 0x09, 0x13, 0x18, + 0x04, 0x09, 0x0E, 0x18, + 0x04, 0x18, 0x18, 0x18, + 0x04, 0x04, 0x18, 0x18, + 0x04, 0x04, 0x04, 0x18, + 0x04, 0x0F, 0x16, 0x1B, + 0x04, 0x09, 0x16, 0x1B, + 0x04, 0x09, 0x10, 0x1B, + 0x04, 0x1B, 0x1B, 0x1B, + 0x04, 0x04, 0x1B, 0x1B, + 0x04, 0x04, 0x04, 0x1B, + 0x04, 0x11, 0x18, 0x1E, + 0x04, 0x0A, 0x18, 0x1E, + 0x04, 0x0A, 0x11, 0x1E, + 0x04, 0x1E, 0x1E, 0x1E, + 0x04, 0x04, 0x1E, 0x1E, + 0x04, 0x04, 0x04, 0x1E, + 0x04, 0x12, 0x1A, 0x21, + 0x04, 0x0B, 0x1A, 0x21, + 0x04, 0x0B, 0x13, 0x21, + 0x04, 0x21, 0x21, 0x21, + 0x04, 0x04, 0x21, 0x21, + 0x04, 0x04, 0x04, 0x21, + 0x04, 0x14, 0x1C, 0x24, + 0x04, 0x0C, 0x1C, 0x24, + 0x04, 0x0C, 0x14, 0x24, + 0x04, 0x24, 0x24, 0x24, + 0x04, 0x04, 0x24, 0x24, + 0x04, 0x04, 0x04, 0x24, + 0x04, 0x27, 0x27, 0x27, + 0x04, 0x04, 0x27, 0x27, + 0x04, 0x04, 0x04, 0x27, + 0x04, 0x16, 0x1F, 0x28, + 0x04, 0x0D, 0x1F, 0x28, + 0x04, 0x0D, 0x16, 0x28, + 0x04, 0x2C, 0x2C, 0x2C, + 0x04, 0x04, 0x2C, 0x2C, + 0x04, 0x04, 0x04, 0x2C, + 0x04, 0x32, 0x32, 0x32, + 0x04, 0x04, 0x32, 0x32, + 0x04, 0x04, 0x04, 0x32, + 0x05, 0x06, 0x06, 0x07, + 0x05, 0x06, 0x07, 0x08, + 0x05, 0x07, 0x08, 0x09, + 0x05, 0x06, 0x08, 0x09, + 0x05, 0x06, 0x07, 0x09, + 0x05, 0x07, 0x08, 0x0A, + 0x05, 0x07, 0x09, 0x0A, + 0x05, 0x06, 0x09, 0x0A, + 0x05, 0x06, 0x08, 0x0A, + 0x05, 0x07, 0x09, 0x0B, + 0x05, 0x08, 0x0A, 0x0B, + 0x05, 0x06, 0x0A, 0x0B, + 0x05, 0x06, 0x08, 0x0B, + 0x05, 0x0B, 0x0B, 0x0B, + 0x05, 0x05, 0x0B, 0x0B, + 0x05, 0x05, 0x05, 0x0B, + 0x05, 0x08, 0x09, 0x0C, + 0x05, 0x08, 0x0B, 0x0C, + 0x05, 0x06, 0x0B, 0x0C, + 0x05, 0x06, 0x09, 0x0C, + 0x05, 0x08, 0x0A, 0x0D, + 0x05, 0x09, 0x0B, 0x0D, + 0x05, 0x07, 0x0B, 0x0D, + 0x05, 0x07, 0x09, 0x0D, + 0x05, 0x0D, 0x0D, 0x0D, + 0x05, 0x05, 0x0D, 0x0D, + 0x05, 0x05, 0x05, 0x0D, + 0x05, 0x09, 0x0C, 0x10, + 0x05, 0x0A, 0x0E, 0x10, + 0x05, 0x07, 0x0E, 0x10, + 0x05, 0x07, 0x0B, 0x10, + 0x05, 0x10, 0x10, 0x10, + 0x05, 0x05, 0x10, 0x10, + 0x05, 0x05, 0x05, 0x10, + 0x05, 0x0A, 0x0E, 0x13, + 0x05, 0x0C, 0x10, 0x13, + 0x05, 0x08, 0x10, 0x13, + 0x05, 0x08, 0x0C, 0x13, + 0x05, 0x13, 0x13, 0x13, + 0x05, 0x05, 0x13, 0x13, + 0x05, 0x05, 0x05, 0x13, + 0x05, 0x0B, 0x10, 0x16, + 0x05, 0x0D, 0x12, 0x16, + 0x05, 0x09, 0x12, 0x16, + 0x05, 0x09, 0x0E, 0x16, + 0x05, 0x16, 0x16, 0x16, + 0x05, 0x05, 0x16, 0x16, + 0x05, 0x05, 0x05, 0x16, + 0x05, 0x0C, 0x12, 0x19, + 0x05, 0x0F, 0x14, 0x19, + 0x05, 0x0A, 0x14, 0x19, + 0x05, 0x0A, 0x0F, 0x19, + 0x05, 0x19, 0x19, 0x19, + 0x05, 0x05, 0x19, 0x19, + 0x05, 0x05, 0x05, 0x19, + 0x05, 0x10, 0x17, 0x1C, + 0x05, 0x0A, 0x17, 0x1C, + 0x05, 0x0A, 0x11, 0x1C, + 0x05, 0x1C, 0x1C, 0x1C, + 0x05, 0x05, 0x1C, 0x1C, + 0x05, 0x05, 0x05, 0x1C, + 0x05, 0x12, 0x19, 0x1F, + 0x05, 0x0B, 0x19, 0x1F, + 0x05, 0x0B, 0x12, 0x1F, + 0x05, 0x1F, 0x1F, 0x1F, + 0x05, 0x05, 0x1F, 0x1F, + 0x05, 0x05, 0x05, 0x1F, + 0x05, 0x13, 0x1B, 0x22, + 0x05, 0x0C, 0x1B, 0x22, + 0x05, 0x0C, 0x14, 0x22, + 0x05, 0x22, 0x22, 0x22, + 0x05, 0x05, 0x22, 0x22, + 0x05, 0x05, 0x05, 0x22, + 0x05, 0x15, 0x1D, 0x25, + 0x05, 0x0D, 0x1D, 0x25, + 0x05, 0x0D, 0x15, 0x25, + 0x05, 0x25, 0x25, 0x25, + 0x05, 0x05, 0x25, 0x25, + 0x05, 0x05, 0x05, 0x25, + 0x05, 0x28, 0x28, 0x28, + 0x05, 0x05, 0x28, 0x28, + 0x05, 0x05, 0x05, 0x28, + 0x05, 0x17, 0x20, 0x29, + 0x05, 0x0E, 0x20, 0x29, + 0x05, 0x0E, 0x17, 0x29, + 0x05, 0x2D, 0x2D, 0x2D, + 0x05, 0x05, 0x2D, 0x2D, + 0x05, 0x05, 0x05, 0x2D, + 0x05, 0x33, 0x33, 0x33, + 0x05, 0x05, 0x33, 0x33, + 0x05, 0x05, 0x05, 0x33, + 0x06, 0x07, 0x07, 0x08, + 0x06, 0x07, 0x08, 0x09, + 0x06, 0x08, 0x09, 0x0A, + 0x06, 0x07, 0x09, 0x0A, + 0x06, 0x07, 0x08, 0x0A, + 0x06, 0x08, 0x09, 0x0B, + 0x06, 0x08, 0x0A, 0x0B, + 0x06, 0x07, 0x0A, 0x0B, + 0x06, 0x07, 0x09, 0x0B, + 0x06, 0x08, 0x0A, 0x0C, + 0x06, 0x09, 0x0B, 0x0C, + 0x06, 0x07, 0x0B, 0x0C, + 0x06, 0x07, 0x09, 0x0C, + 0x06, 0x0C, 0x0C, 0x0C, + 0x06, 0x06, 0x0C, 0x0C, + 0x06, 0x06, 0x06, 0x0C, + 0x06, 0x09, 0x0A, 0x0D, + 0x06, 0x09, 0x0C, 0x0D, + 0x06, 0x07, 0x0C, 0x0D, + 0x06, 0x07, 0x0A, 0x0D, + 0x06, 0x09, 0x0B, 0x0E, + 0x06, 0x0A, 0x0C, 0x0E, + 0x06, 0x08, 0x0C, 0x0E, + 0x06, 0x08, 0x0A, 0x0E, + 0x06, 0x0E, 0x0E, 0x0E, + 0x06, 0x06, 0x0E, 0x0E, + 0x06, 0x06, 0x06, 0x0E, + 0x06, 0x0A, 0x0D, 0x11, + 0x06, 0x0B, 0x0F, 0x11, + 0x06, 0x08, 0x0F, 0x11, + 0x06, 0x08, 0x0C, 0x11, + 0x06, 0x11, 0x11, 0x11, + 0x06, 0x06, 0x11, 0x11, + 0x06, 0x06, 0x06, 0x11, + 0x06, 0x0B, 0x0F, 0x14, + 0x06, 0x0D, 0x11, 0x14, + 0x06, 0x09, 0x11, 0x14, + 0x06, 0x09, 0x0D, 0x14, + 0x06, 0x14, 0x14, 0x14, + 0x06, 0x06, 0x14, 0x14, + 0x06, 0x06, 0x06, 0x14, + 0x06, 0x0C, 0x11, 0x17, + 0x06, 0x0E, 0x13, 0x17, + 0x06, 0x0A, 0x13, 0x17, + 0x06, 0x0A, 0x0F, 0x17, + 0x06, 0x17, 0x17, 0x17, + 0x06, 0x06, 0x17, 0x17, + 0x06, 0x06, 0x06, 0x17, + 0x06, 0x0D, 0x13, 0x1A, + 0x06, 0x10, 0x15, 0x1A, + 0x06, 0x0B, 0x15, 0x1A, + 0x06, 0x0B, 0x10, 0x1A, + 0x06, 0x1A, 0x1A, 0x1A, + 0x06, 0x06, 0x1A, 0x1A, + 0x06, 0x06, 0x06, 0x1A, + 0x06, 0x11, 0x18, 0x1D, + 0x06, 0x0B, 0x18, 0x1D, + 0x06, 0x0B, 0x12, 0x1D, + 0x06, 0x1D, 0x1D, 0x1D, + 0x06, 0x06, 0x1D, 0x1D, + 0x06, 0x06, 0x06, 0x1D, + 0x06, 0x13, 0x1A, 0x20, + 0x06, 0x0C, 0x1A, 0x20, + 0x06, 0x0C, 0x13, 0x20, + 0x06, 0x20, 0x20, 0x20, + 0x06, 0x06, 0x20, 0x20, + 0x06, 0x06, 0x06, 0x20, + 0x06, 0x14, 0x1C, 0x23, + 0x06, 0x0D, 0x1C, 0x23, + 0x06, 0x0D, 0x15, 0x23, + 0x06, 0x23, 0x23, 0x23, + 0x06, 0x06, 0x23, 0x23, + 0x06, 0x06, 0x06, 0x23, + 0x06, 0x16, 0x1E, 0x26, + 0x06, 0x0E, 0x1E, 0x26, + 0x06, 0x0E, 0x16, 0x26, + 0x06, 0x26, 0x26, 0x26, + 0x06, 0x06, 0x26, 0x26, + 0x06, 0x06, 0x06, 0x26, + 0x06, 0x29, 0x29, 0x29, + 0x06, 0x06, 0x29, 0x29, + 0x06, 0x06, 0x06, 0x29, + 0x06, 0x18, 0x21, 0x2A, + 0x06, 0x0F, 0x21, 0x2A, + 0x06, 0x0F, 0x18, 0x2A, + 0x06, 0x2E, 0x2E, 0x2E, + 0x06, 0x06, 0x2E, 0x2E, + 0x06, 0x06, 0x06, 0x2E, + 0x06, 0x34, 0x34, 0x34, + 0x06, 0x06, 0x34, 0x34, + 0x06, 0x06, 0x06, 0x34, + 0x07, 0x08, 0x08, 0x09, + 0x07, 0x08, 0x09, 0x0A, + 0x07, 0x09, 0x0A, 0x0B, + 0x07, 0x08, 0x0A, 0x0B, + 0x07, 0x08, 0x09, 0x0B, + 0x07, 0x09, 0x0A, 0x0C, + 0x07, 0x09, 0x0B, 0x0C, + 0x07, 0x08, 0x0B, 0x0C, + 0x07, 0x08, 0x0A, 0x0C, + 0x07, 0x09, 0x0B, 0x0D, + 0x07, 0x0A, 0x0C, 0x0D, + 0x07, 0x08, 0x0C, 0x0D, + 0x07, 0x08, 0x0A, 0x0D, + 0x07, 0x0D, 0x0D, 0x0D, + 0x07, 0x07, 0x0D, 0x0D, + 0x07, 0x07, 0x07, 0x0D, + 0x07, 0x0A, 0x0B, 0x0E, + 0x07, 0x0A, 0x0D, 0x0E, + 0x07, 0x08, 0x0D, 0x0E, + 0x07, 0x08, 0x0B, 0x0E, + 0x07, 0x0A, 0x0C, 0x0F, + 0x07, 0x0B, 0x0D, 0x0F, + 0x07, 0x09, 0x0D, 0x0F, + 0x07, 0x09, 0x0B, 0x0F, + 0x07, 0x0F, 0x0F, 0x0F, + 0x07, 0x07, 0x0F, 0x0F, + 0x07, 0x07, 0x07, 0x0F, + 0x07, 0x0B, 0x0E, 0x12, + 0x07, 0x0C, 0x10, 0x12, + 0x07, 0x09, 0x10, 0x12, + 0x07, 0x09, 0x0D, 0x12, + 0x07, 0x12, 0x12, 0x12, + 0x07, 0x07, 0x12, 0x12, + 0x07, 0x07, 0x07, 0x12, + 0x07, 0x0C, 0x10, 0x15, + 0x07, 0x0E, 0x12, 0x15, + 0x07, 0x0A, 0x12, 0x15, + 0x07, 0x0A, 0x0E, 0x15, + 0x07, 0x15, 0x15, 0x15, + 0x07, 0x07, 0x15, 0x15, + 0x07, 0x07, 0x07, 0x15, + 0x07, 0x0D, 0x12, 0x18, + 0x07, 0x0F, 0x14, 0x18, + 0x07, 0x0B, 0x14, 0x18, + 0x07, 0x0B, 0x10, 0x18, + 0x07, 0x18, 0x18, 0x18, + 0x07, 0x07, 0x18, 0x18, + 0x07, 0x07, 0x07, 0x18, + 0x07, 0x0E, 0x14, 0x1B, + 0x07, 0x11, 0x16, 0x1B, + 0x07, 0x0C, 0x16, 0x1B, + 0x07, 0x0C, 0x11, 0x1B, + 0x07, 0x1B, 0x1B, 0x1B, + 0x07, 0x07, 0x1B, 0x1B, + 0x07, 0x07, 0x07, 0x1B, + 0x07, 0x12, 0x19, 0x1E, + 0x07, 0x0C, 0x19, 0x1E, + 0x07, 0x0C, 0x13, 0x1E, + 0x07, 0x1E, 0x1E, 0x1E, + 0x07, 0x07, 0x1E, 0x1E, + 0x07, 0x07, 0x07, 0x1E, + 0x07, 0x14, 0x1B, 0x21, + 0x07, 0x0D, 0x1B, 0x21, + 0x07, 0x0D, 0x14, 0x21, + 0x07, 0x21, 0x21, 0x21, + 0x07, 0x07, 0x21, 0x21, + 0x07, 0x07, 0x07, 0x21, + 0x07, 0x15, 0x1D, 0x24, + 0x07, 0x0E, 0x1D, 0x24, + 0x07, 0x0E, 0x16, 0x24, + 0x07, 0x24, 0x24, 0x24, + 0x07, 0x07, 0x24, 0x24, + 0x07, 0x07, 0x07, 0x24, + 0x07, 0x17, 0x1F, 0x27, + 0x07, 0x0F, 0x1F, 0x27, + 0x07, 0x0F, 0x17, 0x27, + 0x07, 0x27, 0x27, 0x27, + 0x07, 0x07, 0x27, 0x27, + 0x07, 0x07, 0x07, 0x27, + 0x07, 0x2A, 0x2A, 0x2A, + 0x07, 0x07, 0x2A, 0x2A, + 0x07, 0x07, 0x07, 0x2A, + 0x07, 0x19, 0x22, 0x2B, + 0x07, 0x10, 0x22, 0x2B, + 0x07, 0x10, 0x19, 0x2B, + 0x07, 0x2F, 0x2F, 0x2F, + 0x07, 0x07, 0x2F, 0x2F, + 0x07, 0x07, 0x07, 0x2F, + 0x07, 0x35, 0x35, 0x35, + 0x07, 0x07, 0x35, 0x35, + 0x07, 0x07, 0x07, 0x35, + 0x08, 0x09, 0x09, 0x0A, + 0x08, 0x09, 0x0A, 0x0B, + 0x08, 0x0A, 0x0B, 0x0C, + 0x08, 0x09, 0x0B, 0x0C, + 0x08, 0x09, 0x0A, 0x0C, + 0x08, 0x0A, 0x0B, 0x0D, + 0x08, 0x0A, 0x0C, 0x0D, + 0x08, 0x09, 0x0C, 0x0D, + 0x08, 0x09, 0x0B, 0x0D, + 0x08, 0x0A, 0x0C, 0x0E, + 0x08, 0x0B, 0x0D, 0x0E, + 0x08, 0x09, 0x0D, 0x0E, + 0x08, 0x09, 0x0B, 0x0E, + 0x08, 0x0E, 0x0E, 0x0E, + 0x08, 0x08, 0x0E, 0x0E, + 0x08, 0x08, 0x08, 0x0E, + 0x08, 0x0B, 0x0C, 0x0F, + 0x08, 0x0B, 0x0E, 0x0F, + 0x08, 0x09, 0x0E, 0x0F, + 0x08, 0x09, 0x0C, 0x0F, + 0x08, 0x0B, 0x0D, 0x10, + 0x08, 0x0C, 0x0E, 0x10, + 0x08, 0x0A, 0x0E, 0x10, + 0x08, 0x0A, 0x0C, 0x10, + 0x08, 0x10, 0x10, 0x10, + 0x08, 0x08, 0x10, 0x10, + 0x08, 0x08, 0x08, 0x10, + 0x08, 0x0C, 0x0F, 0x13, + 0x08, 0x0D, 0x11, 0x13, + 0x08, 0x0A, 0x11, 0x13, + 0x08, 0x0A, 0x0E, 0x13, + 0x08, 0x13, 0x13, 0x13, + 0x08, 0x08, 0x13, 0x13, + 0x08, 0x08, 0x08, 0x13, + 0x08, 0x0D, 0x11, 0x16, + 0x08, 0x0F, 0x13, 0x16, + 0x08, 0x0B, 0x13, 0x16, + 0x08, 0x0B, 0x0F, 0x16, + 0x08, 0x16, 0x16, 0x16, + 0x08, 0x08, 0x16, 0x16, + 0x08, 0x08, 0x08, 0x16, + 0x08, 0x0E, 0x13, 0x19, + 0x08, 0x10, 0x15, 0x19, + 0x08, 0x0C, 0x15, 0x19, + 0x08, 0x0C, 0x11, 0x19, + 0x08, 0x19, 0x19, 0x19, + 0x08, 0x08, 0x19, 0x19, + 0x08, 0x08, 0x08, 0x19, + 0x08, 0x0F, 0x15, 0x1C, + 0x08, 0x12, 0x17, 0x1C, + 0x08, 0x0D, 0x17, 0x1C, + 0x08, 0x0D, 0x12, 0x1C, + 0x08, 0x1C, 0x1C, 0x1C, + 0x08, 0x08, 0x1C, 0x1C, + 0x08, 0x08, 0x08, 0x1C, + 0x08, 0x13, 0x1A, 0x1F, + 0x08, 0x0D, 0x1A, 0x1F, + 0x08, 0x0D, 0x14, 0x1F, + 0x08, 0x1F, 0x1F, 0x1F, + 0x08, 0x08, 0x1F, 0x1F, + 0x08, 0x08, 0x08, 0x1F, + 0x08, 0x15, 0x1C, 0x22, + 0x08, 0x0E, 0x1C, 0x22, + 0x08, 0x0E, 0x15, 0x22, + 0x08, 0x22, 0x22, 0x22, + 0x08, 0x08, 0x22, 0x22, + 0x08, 0x08, 0x08, 0x22, + 0x08, 0x16, 0x1E, 0x25, + 0x08, 0x0F, 0x1E, 0x25, + 0x08, 0x0F, 0x17, 0x25, + 0x08, 0x25, 0x25, 0x25, + 0x08, 0x08, 0x25, 0x25, + 0x08, 0x08, 0x08, 0x25, + 0x08, 0x18, 0x20, 0x28, + 0x08, 0x10, 0x20, 0x28, + 0x08, 0x10, 0x18, 0x28, + 0x08, 0x28, 0x28, 0x28, + 0x08, 0x08, 0x28, 0x28, + 0x08, 0x08, 0x08, 0x28, + 0x08, 0x2B, 0x2B, 0x2B, + 0x08, 0x08, 0x2B, 0x2B, + 0x08, 0x08, 0x08, 0x2B, + 0x08, 0x1A, 0x23, 0x2C, + 0x08, 0x11, 0x23, 0x2C, + 0x08, 0x11, 0x1A, 0x2C, + 0x08, 0x30, 0x30, 0x30, + 0x08, 0x08, 0x30, 0x30, + 0x08, 0x08, 0x08, 0x30, + 0x08, 0x36, 0x36, 0x36, + 0x08, 0x08, 0x36, 0x36, + 0x08, 0x08, 0x08, 0x36, + 0x09, 0x0A, 0x0A, 0x0B, + 0x09, 0x0A, 0x0B, 0x0C, + 0x09, 0x0B, 0x0C, 0x0D, + 0x09, 0x0A, 0x0C, 0x0D, + 0x09, 0x0A, 0x0B, 0x0D, + 0x09, 0x0B, 0x0C, 0x0E, + 0x09, 0x0B, 0x0D, 0x0E, + 0x09, 0x0A, 0x0D, 0x0E, + 0x09, 0x0A, 0x0C, 0x0E, + 0x09, 0x0B, 0x0D, 0x0F, + 0x09, 0x0C, 0x0E, 0x0F, + 0x09, 0x0A, 0x0E, 0x0F, + 0x09, 0x0A, 0x0C, 0x0F, + 0x09, 0x0F, 0x0F, 0x0F, + 0x09, 0x09, 0x0F, 0x0F, + 0x09, 0x09, 0x09, 0x0F, + 0x09, 0x0C, 0x0D, 0x10, + 0x09, 0x0C, 0x0F, 0x10, + 0x09, 0x0A, 0x0F, 0x10, + 0x09, 0x0A, 0x0D, 0x10, + 0x09, 0x0C, 0x0E, 0x11, + 0x09, 0x0D, 0x0F, 0x11, + 0x09, 0x0B, 0x0F, 0x11, + 0x09, 0x0B, 0x0D, 0x11, + 0x09, 0x11, 0x11, 0x11, + 0x09, 0x09, 0x11, 0x11, + 0x09, 0x09, 0x09, 0x11, + 0x09, 0x0D, 0x10, 0x14, + 0x09, 0x0E, 0x12, 0x14, + 0x09, 0x0B, 0x12, 0x14, + 0x09, 0x0B, 0x0F, 0x14, + 0x09, 0x14, 0x14, 0x14, + 0x09, 0x09, 0x14, 0x14, + 0x09, 0x09, 0x09, 0x14, + 0x09, 0x0E, 0x12, 0x17, + 0x09, 0x10, 0x14, 0x17, + 0x09, 0x0C, 0x14, 0x17, + 0x09, 0x0C, 0x10, 0x17, + 0x09, 0x17, 0x17, 0x17, + 0x09, 0x09, 0x17, 0x17, + 0x09, 0x09, 0x09, 0x17, + 0x09, 0x0F, 0x14, 0x1A, + 0x09, 0x11, 0x16, 0x1A, + 0x09, 0x0D, 0x16, 0x1A, + 0x09, 0x0D, 0x12, 0x1A, + 0x09, 0x1A, 0x1A, 0x1A, + 0x09, 0x09, 0x1A, 0x1A, + 0x09, 0x09, 0x09, 0x1A, + 0x09, 0x10, 0x16, 0x1D, + 0x09, 0x13, 0x18, 0x1D, + 0x09, 0x0E, 0x18, 0x1D, + 0x09, 0x0E, 0x13, 0x1D, + 0x09, 0x1D, 0x1D, 0x1D, + 0x09, 0x09, 0x1D, 0x1D, + 0x09, 0x09, 0x09, 0x1D, + 0x09, 0x14, 0x1B, 0x20, + 0x09, 0x0E, 0x1B, 0x20, + 0x09, 0x0E, 0x15, 0x20, + 0x09, 0x20, 0x20, 0x20, + 0x09, 0x09, 0x20, 0x20, + 0x09, 0x09, 0x09, 0x20, + 0x09, 0x16, 0x1D, 0x23, + 0x09, 0x0F, 0x1D, 0x23, + 0x09, 0x0F, 0x16, 0x23, + 0x09, 0x23, 0x23, 0x23, + 0x09, 0x09, 0x23, 0x23, + 0x09, 0x09, 0x09, 0x23, + 0x09, 0x17, 0x1F, 0x26, + 0x09, 0x10, 0x1F, 0x26, + 0x09, 0x10, 0x18, 0x26, + 0x09, 0x26, 0x26, 0x26, + 0x09, 0x09, 0x26, 0x26, + 0x09, 0x09, 0x09, 0x26, + 0x09, 0x19, 0x21, 0x29, + 0x09, 0x11, 0x21, 0x29, + 0x09, 0x11, 0x19, 0x29, + 0x09, 0x29, 0x29, 0x29, + 0x09, 0x09, 0x29, 0x29, + 0x09, 0x09, 0x09, 0x29, + 0x09, 0x2C, 0x2C, 0x2C, + 0x09, 0x09, 0x2C, 0x2C, + 0x09, 0x09, 0x09, 0x2C, + 0x09, 0x1B, 0x24, 0x2D, + 0x09, 0x12, 0x24, 0x2D, + 0x09, 0x12, 0x1B, 0x2D, + 0x09, 0x31, 0x31, 0x31, + 0x09, 0x09, 0x31, 0x31, + 0x09, 0x09, 0x09, 0x31, + 0x09, 0x37, 0x37, 0x37, + 0x09, 0x09, 0x37, 0x37, + 0x09, 0x09, 0x09, 0x37, + 0x0A, 0x0B, 0x0B, 0x0C, + 0x0A, 0x0B, 0x0C, 0x0D, + 0x0A, 0x0C, 0x0D, 0x0E, + 0x0A, 0x0B, 0x0D, 0x0E, + 0x0A, 0x0B, 0x0C, 0x0E, + 0x0A, 0x0C, 0x0D, 0x0F, + 0x0A, 0x0C, 0x0E, 0x0F, + 0x0A, 0x0B, 0x0E, 0x0F, + 0x0A, 0x0B, 0x0D, 0x0F, + 0x0A, 0x0C, 0x0E, 0x10, + 0x0A, 0x0D, 0x0F, 0x10, + 0x0A, 0x0B, 0x0F, 0x10, + 0x0A, 0x0B, 0x0D, 0x10, + 0x0A, 0x10, 0x10, 0x10, + 0x0A, 0x0A, 0x10, 0x10, + 0x0A, 0x0A, 0x0A, 0x10, + 0x0A, 0x0D, 0x0E, 0x11, + 0x0A, 0x0D, 0x10, 0x11, + 0x0A, 0x0B, 0x10, 0x11, + 0x0A, 0x0B, 0x0E, 0x11, + 0x0A, 0x0D, 0x0F, 0x12, + 0x0A, 0x0E, 0x10, 0x12, + 0x0A, 0x0C, 0x10, 0x12, + 0x0A, 0x0C, 0x0E, 0x12, + 0x0A, 0x12, 0x12, 0x12, + 0x0A, 0x0A, 0x12, 0x12, + 0x0A, 0x0A, 0x0A, 0x12, + 0x0A, 0x0E, 0x11, 0x15, + 0x0A, 0x0F, 0x13, 0x15, + 0x0A, 0x0C, 0x13, 0x15, + 0x0A, 0x0C, 0x10, 0x15, + 0x0A, 0x15, 0x15, 0x15, + 0x0A, 0x0A, 0x15, 0x15, + 0x0A, 0x0A, 0x0A, 0x15, + 0x0A, 0x0F, 0x13, 0x18, + 0x0A, 0x11, 0x15, 0x18, + 0x0A, 0x0D, 0x15, 0x18, + 0x0A, 0x0D, 0x11, 0x18, + 0x0A, 0x18, 0x18, 0x18, + 0x0A, 0x0A, 0x18, 0x18, + 0x0A, 0x0A, 0x0A, 0x18, + 0x0A, 0x10, 0x15, 0x1B, + 0x0A, 0x12, 0x17, 0x1B, + 0x0A, 0x0E, 0x17, 0x1B, + 0x0A, 0x0E, 0x13, 0x1B, + 0x0A, 0x1B, 0x1B, 0x1B, + 0x0A, 0x0A, 0x1B, 0x1B, + 0x0A, 0x0A, 0x0A, 0x1B, + 0x0A, 0x11, 0x17, 0x1E, + 0x0A, 0x14, 0x19, 0x1E, + 0x0A, 0x0F, 0x19, 0x1E, + 0x0A, 0x0F, 0x14, 0x1E, + 0x0A, 0x1E, 0x1E, 0x1E, + 0x0A, 0x0A, 0x1E, 0x1E, + 0x0A, 0x0A, 0x0A, 0x1E, + 0x0A, 0x15, 0x1C, 0x21, + 0x0A, 0x0F, 0x1C, 0x21, + 0x0A, 0x0F, 0x16, 0x21, + 0x0A, 0x21, 0x21, 0x21, + 0x0A, 0x0A, 0x21, 0x21, + 0x0A, 0x0A, 0x0A, 0x21, + 0x0A, 0x17, 0x1E, 0x24, + 0x0A, 0x10, 0x1E, 0x24, + 0x0A, 0x10, 0x17, 0x24, + 0x0A, 0x24, 0x24, 0x24, + 0x0A, 0x0A, 0x24, 0x24, + 0x0A, 0x0A, 0x0A, 0x24, + 0x0A, 0x18, 0x20, 0x27, + 0x0A, 0x11, 0x20, 0x27, + 0x0A, 0x11, 0x19, 0x27, + 0x0A, 0x27, 0x27, 0x27, + 0x0A, 0x0A, 0x27, 0x27, + 0x0A, 0x0A, 0x0A, 0x27, + 0x0A, 0x1A, 0x22, 0x2A, + 0x0A, 0x12, 0x22, 0x2A, + 0x0A, 0x12, 0x1A, 0x2A, + 0x0A, 0x2A, 0x2A, 0x2A, + 0x0A, 0x0A, 0x2A, 0x2A, + 0x0A, 0x0A, 0x0A, 0x2A, + 0x0A, 0x2D, 0x2D, 0x2D, + 0x0A, 0x0A, 0x2D, 0x2D, + 0x0A, 0x0A, 0x0A, 0x2D, + 0x0A, 0x1C, 0x25, 0x2E, + 0x0A, 0x13, 0x25, 0x2E, + 0x0A, 0x13, 0x1C, 0x2E, + 0x0A, 0x32, 0x32, 0x32, + 0x0A, 0x0A, 0x32, 0x32, + 0x0A, 0x0A, 0x0A, 0x32, + 0x0A, 0x38, 0x38, 0x38, + 0x0A, 0x0A, 0x38, 0x38, + 0x0A, 0x0A, 0x0A, 0x38, + 0x0B, 0x0C, 0x0C, 0x0D, + 0x0B, 0x0C, 0x0D, 0x0E, + 0x0B, 0x0D, 0x0E, 0x0F, + 0x0B, 0x0C, 0x0E, 0x0F, + 0x0B, 0x0C, 0x0D, 0x0F, + 0x0B, 0x0D, 0x0E, 0x10, + 0x0B, 0x0D, 0x0F, 0x10, + 0x0B, 0x0C, 0x0F, 0x10, + 0x0B, 0x0C, 0x0E, 0x10, + 0x0B, 0x0D, 0x0F, 0x11, + 0x0B, 0x0E, 0x10, 0x11, + 0x0B, 0x0C, 0x10, 0x11, + 0x0B, 0x0C, 0x0E, 0x11, + 0x0B, 0x11, 0x11, 0x11, + 0x0B, 0x0B, 0x11, 0x11, + 0x0B, 0x0B, 0x0B, 0x11, + 0x0B, 0x0E, 0x0F, 0x12, + 0x0B, 0x0E, 0x11, 0x12, + 0x0B, 0x0C, 0x11, 0x12, + 0x0B, 0x0C, 0x0F, 0x12, + 0x0B, 0x0E, 0x10, 0x13, + 0x0B, 0x0F, 0x11, 0x13, + 0x0B, 0x0D, 0x11, 0x13, + 0x0B, 0x0D, 0x0F, 0x13, + 0x0B, 0x13, 0x13, 0x13, + 0x0B, 0x0B, 0x13, 0x13, + 0x0B, 0x0B, 0x0B, 0x13, + 0x0B, 0x0F, 0x12, 0x16, + 0x0B, 0x10, 0x14, 0x16, + 0x0B, 0x0D, 0x14, 0x16, + 0x0B, 0x0D, 0x11, 0x16, + 0x0B, 0x16, 0x16, 0x16, + 0x0B, 0x0B, 0x16, 0x16, + 0x0B, 0x0B, 0x0B, 0x16, + 0x0B, 0x10, 0x14, 0x19, + 0x0B, 0x12, 0x16, 0x19, + 0x0B, 0x0E, 0x16, 0x19, + 0x0B, 0x0E, 0x12, 0x19, + 0x0B, 0x19, 0x19, 0x19, + 0x0B, 0x0B, 0x19, 0x19, + 0x0B, 0x0B, 0x0B, 0x19, + 0x0B, 0x11, 0x16, 0x1C, + 0x0B, 0x13, 0x18, 0x1C, + 0x0B, 0x0F, 0x18, 0x1C, + 0x0B, 0x0F, 0x14, 0x1C, + 0x0B, 0x1C, 0x1C, 0x1C, + 0x0B, 0x0B, 0x1C, 0x1C, + 0x0B, 0x0B, 0x0B, 0x1C, + 0x0B, 0x12, 0x18, 0x1F, + 0x0B, 0x15, 0x1A, 0x1F, + 0x0B, 0x10, 0x1A, 0x1F, + 0x0B, 0x10, 0x15, 0x1F, + 0x0B, 0x1F, 0x1F, 0x1F, + 0x0B, 0x0B, 0x1F, 0x1F, + 0x0B, 0x0B, 0x0B, 0x1F, + 0x0B, 0x16, 0x1D, 0x22, + 0x0B, 0x10, 0x1D, 0x22, + 0x0B, 0x10, 0x17, 0x22, + 0x0B, 0x22, 0x22, 0x22, + 0x0B, 0x0B, 0x22, 0x22, + 0x0B, 0x0B, 0x0B, 0x22, + 0x0B, 0x18, 0x1F, 0x25, + 0x0B, 0x11, 0x1F, 0x25, + 0x0B, 0x11, 0x18, 0x25, + 0x0B, 0x25, 0x25, 0x25, + 0x0B, 0x0B, 0x25, 0x25, + 0x0B, 0x0B, 0x0B, 0x25, + 0x0B, 0x19, 0x21, 0x28, + 0x0B, 0x12, 0x21, 0x28, + 0x0B, 0x12, 0x1A, 0x28, + 0x0B, 0x28, 0x28, 0x28, + 0x0B, 0x0B, 0x28, 0x28, + 0x0B, 0x0B, 0x0B, 0x28, + 0x0B, 0x1B, 0x23, 0x2B, + 0x0B, 0x13, 0x23, 0x2B, + 0x0B, 0x13, 0x1B, 0x2B, + 0x0B, 0x2B, 0x2B, 0x2B, + 0x0B, 0x0B, 0x2B, 0x2B, + 0x0B, 0x0B, 0x0B, 0x2B, + 0x0B, 0x2E, 0x2E, 0x2E, + 0x0B, 0x0B, 0x2E, 0x2E, + 0x0B, 0x0B, 0x0B, 0x2E, + 0x0B, 0x1D, 0x26, 0x2F, + 0x0B, 0x14, 0x26, 0x2F, + 0x0B, 0x14, 0x1D, 0x2F, + 0x0B, 0x33, 0x33, 0x33, + 0x0B, 0x0B, 0x33, 0x33, + 0x0B, 0x0B, 0x0B, 0x33, + 0x0B, 0x39, 0x39, 0x39, + 0x0B, 0x0B, 0x39, 0x39, + 0x0B, 0x0B, 0x0B, 0x39, + 0x0C, 0x0D, 0x0D, 0x0E, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x0C, 0x0E, 0x0F, 0x10, + 0x0C, 0x0D, 0x0F, 0x10, + 0x0C, 0x0D, 0x0E, 0x10, + 0x0C, 0x0E, 0x0F, 0x11, + 0x0C, 0x0E, 0x10, 0x11, + 0x0C, 0x0D, 0x10, 0x11, + 0x0C, 0x0D, 0x0F, 0x11, + 0x0C, 0x0E, 0x10, 0x12, + 0x0C, 0x0F, 0x11, 0x12, + 0x0C, 0x0D, 0x11, 0x12, + 0x0C, 0x0D, 0x0F, 0x12, + 0x0C, 0x12, 0x12, 0x12, + 0x0C, 0x0C, 0x12, 0x12, + 0x0C, 0x0C, 0x0C, 0x12, + 0x0C, 0x0F, 0x10, 0x13, + 0x0C, 0x0F, 0x12, 0x13, + 0x0C, 0x0D, 0x12, 0x13, + 0x0C, 0x0D, 0x10, 0x13, + 0x0C, 0x0F, 0x11, 0x14, + 0x0C, 0x10, 0x12, 0x14, + 0x0C, 0x0E, 0x12, 0x14, + 0x0C, 0x0E, 0x10, 0x14, + 0x0C, 0x14, 0x14, 0x14, + 0x0C, 0x0C, 0x14, 0x14, + 0x0C, 0x0C, 0x0C, 0x14, + 0x0C, 0x10, 0x13, 0x17, + 0x0C, 0x11, 0x15, 0x17, + 0x0C, 0x0E, 0x15, 0x17, + 0x0C, 0x0E, 0x12, 0x17, + 0x0C, 0x17, 0x17, 0x17, + 0x0C, 0x0C, 0x17, 0x17, + 0x0C, 0x0C, 0x0C, 0x17, + 0x0C, 0x11, 0x15, 0x1A, + 0x0C, 0x13, 0x17, 0x1A, + 0x0C, 0x0F, 0x17, 0x1A, + 0x0C, 0x0F, 0x13, 0x1A, + 0x0C, 0x1A, 0x1A, 0x1A, + 0x0C, 0x0C, 0x1A, 0x1A, + 0x0C, 0x0C, 0x0C, 0x1A, + 0x0C, 0x12, 0x17, 0x1D, + 0x0C, 0x14, 0x19, 0x1D, + 0x0C, 0x10, 0x19, 0x1D, + 0x0C, 0x10, 0x15, 0x1D, + 0x0C, 0x1D, 0x1D, 0x1D, + 0x0C, 0x0C, 0x1D, 0x1D, + 0x0C, 0x0C, 0x0C, 0x1D, + 0x0C, 0x13, 0x19, 0x20, + 0x0C, 0x16, 0x1B, 0x20, + 0x0C, 0x11, 0x1B, 0x20, + 0x0C, 0x11, 0x16, 0x20, + 0x0C, 0x20, 0x20, 0x20, + 0x0C, 0x0C, 0x20, 0x20, + 0x0C, 0x0C, 0x0C, 0x20, + 0x0C, 0x17, 0x1E, 0x23, + 0x0C, 0x11, 0x1E, 0x23, + 0x0C, 0x11, 0x18, 0x23, + 0x0C, 0x23, 0x23, 0x23, + 0x0C, 0x0C, 0x23, 0x23, + 0x0C, 0x0C, 0x0C, 0x23, + 0x0C, 0x19, 0x20, 0x26, + 0x0C, 0x12, 0x20, 0x26, + 0x0C, 0x12, 0x19, 0x26, + 0x0C, 0x26, 0x26, 0x26, + 0x0C, 0x0C, 0x26, 0x26, + 0x0C, 0x0C, 0x0C, 0x26, + 0x0C, 0x1A, 0x22, 0x29, + 0x0C, 0x13, 0x22, 0x29, + 0x0C, 0x13, 0x1B, 0x29, + 0x0C, 0x29, 0x29, 0x29, + 0x0C, 0x0C, 0x29, 0x29, + 0x0C, 0x0C, 0x0C, 0x29, + 0x0C, 0x1C, 0x24, 0x2C, + 0x0C, 0x14, 0x24, 0x2C, + 0x0C, 0x14, 0x1C, 0x2C, + 0x0C, 0x2C, 0x2C, 0x2C, + 0x0C, 0x0C, 0x2C, 0x2C, + 0x0C, 0x0C, 0x0C, 0x2C, + 0x0C, 0x2F, 0x2F, 0x2F, + 0x0C, 0x0C, 0x2F, 0x2F, + 0x0C, 0x0C, 0x0C, 0x2F, + 0x0C, 0x1E, 0x27, 0x30, + 0x0C, 0x15, 0x27, 0x30, + 0x0C, 0x15, 0x1E, 0x30, + 0x0C, 0x34, 0x34, 0x34, + 0x0C, 0x0C, 0x34, 0x34, + 0x0C, 0x0C, 0x0C, 0x34, + 0x0C, 0x3A, 0x3A, 0x3A, + 0x0C, 0x0C, 0x3A, 0x3A, + 0x0C, 0x0C, 0x0C, 0x3A, + 0x0D, 0x0E, 0x0E, 0x0F, + 0x0D, 0x0E, 0x0F, 0x10, + 0x0D, 0x0F, 0x10, 0x11, + 0x0D, 0x0E, 0x10, 0x11, + 0x0D, 0x0E, 0x0F, 0x11, + 0x0D, 0x0F, 0x10, 0x12, + 0x0D, 0x0F, 0x11, 0x12, + 0x0D, 0x0E, 0x11, 0x12, + 0x0D, 0x0E, 0x10, 0x12, + 0x0D, 0x0F, 0x11, 0x13, + 0x0D, 0x10, 0x12, 0x13, + 0x0D, 0x0E, 0x12, 0x13, + 0x0D, 0x0E, 0x10, 0x13, + 0x0D, 0x13, 0x13, 0x13, + 0x0D, 0x0D, 0x13, 0x13, + 0x0D, 0x0D, 0x0D, 0x13, + 0x0D, 0x10, 0x11, 0x14, + 0x0D, 0x10, 0x13, 0x14, + 0x0D, 0x0E, 0x13, 0x14, + 0x0D, 0x0E, 0x11, 0x14, + 0x0D, 0x10, 0x12, 0x15, + 0x0D, 0x11, 0x13, 0x15, + 0x0D, 0x0F, 0x13, 0x15, + 0x0D, 0x0F, 0x11, 0x15, + 0x0D, 0x15, 0x15, 0x15, + 0x0D, 0x0D, 0x15, 0x15, + 0x0D, 0x0D, 0x0D, 0x15, + 0x0D, 0x11, 0x14, 0x18, + 0x0D, 0x12, 0x16, 0x18, + 0x0D, 0x0F, 0x16, 0x18, + 0x0D, 0x0F, 0x13, 0x18, + 0x0D, 0x18, 0x18, 0x18, + 0x0D, 0x0D, 0x18, 0x18, + 0x0D, 0x0D, 0x0D, 0x18, + 0x0D, 0x12, 0x16, 0x1B, + 0x0D, 0x14, 0x18, 0x1B, + 0x0D, 0x10, 0x18, 0x1B, + 0x0D, 0x10, 0x14, 0x1B, + 0x0D, 0x1B, 0x1B, 0x1B, + 0x0D, 0x0D, 0x1B, 0x1B, + 0x0D, 0x0D, 0x0D, 0x1B, + 0x0D, 0x13, 0x18, 0x1E, + 0x0D, 0x15, 0x1A, 0x1E, + 0x0D, 0x11, 0x1A, 0x1E, + 0x0D, 0x11, 0x16, 0x1E, + 0x0D, 0x1E, 0x1E, 0x1E, + 0x0D, 0x0D, 0x1E, 0x1E, + 0x0D, 0x0D, 0x0D, 0x1E, + 0x0D, 0x14, 0x1A, 0x21, + 0x0D, 0x17, 0x1C, 0x21, + 0x0D, 0x12, 0x1C, 0x21, + 0x0D, 0x12, 0x17, 0x21, + 0x0D, 0x21, 0x21, 0x21, + 0x0D, 0x0D, 0x21, 0x21, + 0x0D, 0x0D, 0x0D, 0x21, + 0x0D, 0x18, 0x1F, 0x24, + 0x0D, 0x12, 0x1F, 0x24, + 0x0D, 0x12, 0x19, 0x24, + 0x0D, 0x24, 0x24, 0x24, + 0x0D, 0x0D, 0x24, 0x24, + 0x0D, 0x0D, 0x0D, 0x24, + 0x0D, 0x1A, 0x21, 0x27, + 0x0D, 0x13, 0x21, 0x27, + 0x0D, 0x13, 0x1A, 0x27, + 0x0D, 0x27, 0x27, 0x27, + 0x0D, 0x0D, 0x27, 0x27, + 0x0D, 0x0D, 0x0D, 0x27, + 0x0D, 0x1B, 0x23, 0x2A, + 0x0D, 0x14, 0x23, 0x2A, + 0x0D, 0x14, 0x1C, 0x2A, + 0x0D, 0x2A, 0x2A, 0x2A, + 0x0D, 0x0D, 0x2A, 0x2A, + 0x0D, 0x0D, 0x0D, 0x2A, + 0x0D, 0x1D, 0x25, 0x2D, + 0x0D, 0x15, 0x25, 0x2D, + 0x0D, 0x15, 0x1D, 0x2D, + 0x0D, 0x2D, 0x2D, 0x2D, + 0x0D, 0x0D, 0x2D, 0x2D, + 0x0D, 0x0D, 0x0D, 0x2D, + 0x0D, 0x30, 0x30, 0x30, + 0x0D, 0x0D, 0x30, 0x30, + 0x0D, 0x0D, 0x0D, 0x30, + 0x0D, 0x1F, 0x28, 0x31, + 0x0D, 0x16, 0x28, 0x31, + 0x0D, 0x16, 0x1F, 0x31, + 0x0D, 0x35, 0x35, 0x35, + 0x0D, 0x0D, 0x35, 0x35, + 0x0D, 0x0D, 0x0D, 0x35, + 0x0D, 0x3B, 0x3B, 0x3B, + 0x0D, 0x0D, 0x3B, 0x3B, + 0x0D, 0x0D, 0x0D, 0x3B, + 0x0E, 0x0F, 0x0F, 0x10, + 0x0E, 0x0F, 0x10, 0x11, + 0x0E, 0x10, 0x11, 0x12, + 0x0E, 0x0F, 0x11, 0x12, + 0x0E, 0x0F, 0x10, 0x12, + 0x0E, 0x10, 0x11, 0x13, + 0x0E, 0x10, 0x12, 0x13, + 0x0E, 0x0F, 0x12, 0x13, + 0x0E, 0x0F, 0x11, 0x13, + 0x0E, 0x10, 0x12, 0x14, + 0x0E, 0x11, 0x13, 0x14, + 0x0E, 0x0F, 0x13, 0x14, + 0x0E, 0x0F, 0x11, 0x14, + 0x0E, 0x14, 0x14, 0x14, + 0x0E, 0x0E, 0x14, 0x14, + 0x0E, 0x0E, 0x0E, 0x14, + 0x0E, 0x11, 0x12, 0x15, + 0x0E, 0x11, 0x14, 0x15, + 0x0E, 0x0F, 0x14, 0x15, + 0x0E, 0x0F, 0x12, 0x15, + 0x0E, 0x11, 0x13, 0x16, + 0x0E, 0x12, 0x14, 0x16, + 0x0E, 0x10, 0x14, 0x16, + 0x0E, 0x10, 0x12, 0x16, + 0x0E, 0x16, 0x16, 0x16, + 0x0E, 0x0E, 0x16, 0x16, + 0x0E, 0x0E, 0x0E, 0x16, + 0x0E, 0x12, 0x15, 0x19, + 0x0E, 0x13, 0x17, 0x19, + 0x0E, 0x10, 0x17, 0x19, + 0x0E, 0x10, 0x14, 0x19, + 0x0E, 0x19, 0x19, 0x19, + 0x0E, 0x0E, 0x19, 0x19, + 0x0E, 0x0E, 0x0E, 0x19, + 0x0E, 0x13, 0x17, 0x1C, + 0x0E, 0x15, 0x19, 0x1C, + 0x0E, 0x11, 0x19, 0x1C, + 0x0E, 0x11, 0x15, 0x1C, + 0x0E, 0x1C, 0x1C, 0x1C, + 0x0E, 0x0E, 0x1C, 0x1C, + 0x0E, 0x0E, 0x0E, 0x1C, + 0x0E, 0x14, 0x19, 0x1F, + 0x0E, 0x16, 0x1B, 0x1F, + 0x0E, 0x12, 0x1B, 0x1F, + 0x0E, 0x12, 0x17, 0x1F, + 0x0E, 0x1F, 0x1F, 0x1F, + 0x0E, 0x0E, 0x1F, 0x1F, + 0x0E, 0x0E, 0x0E, 0x1F, + 0x0E, 0x15, 0x1B, 0x22, + 0x0E, 0x18, 0x1D, 0x22, + 0x0E, 0x13, 0x1D, 0x22, + 0x0E, 0x13, 0x18, 0x22, + 0x0E, 0x22, 0x22, 0x22, + 0x0E, 0x0E, 0x22, 0x22, + 0x0E, 0x0E, 0x0E, 0x22, + 0x0E, 0x19, 0x20, 0x25, + 0x0E, 0x13, 0x20, 0x25, + 0x0E, 0x13, 0x1A, 0x25, + 0x0E, 0x25, 0x25, 0x25, + 0x0E, 0x0E, 0x25, 0x25, + 0x0E, 0x0E, 0x0E, 0x25, + 0x0E, 0x1B, 0x22, 0x28, + 0x0E, 0x14, 0x22, 0x28, + 0x0E, 0x14, 0x1B, 0x28, + 0x0E, 0x28, 0x28, 0x28, + 0x0E, 0x0E, 0x28, 0x28, + 0x0E, 0x0E, 0x0E, 0x28, + 0x0E, 0x1C, 0x24, 0x2B, + 0x0E, 0x15, 0x24, 0x2B, + 0x0E, 0x15, 0x1D, 0x2B, + 0x0E, 0x2B, 0x2B, 0x2B, + 0x0E, 0x0E, 0x2B, 0x2B, + 0x0E, 0x0E, 0x0E, 0x2B, + 0x0E, 0x1E, 0x26, 0x2E, + 0x0E, 0x16, 0x26, 0x2E, + 0x0E, 0x16, 0x1E, 0x2E, + 0x0E, 0x2E, 0x2E, 0x2E, + 0x0E, 0x0E, 0x2E, 0x2E, + 0x0E, 0x0E, 0x0E, 0x2E, + 0x0E, 0x31, 0x31, 0x31, + 0x0E, 0x0E, 0x31, 0x31, + 0x0E, 0x0E, 0x0E, 0x31, + 0x0E, 0x20, 0x29, 0x32, + 0x0E, 0x17, 0x29, 0x32, + 0x0E, 0x17, 0x20, 0x32, + 0x0E, 0x36, 0x36, 0x36, + 0x0E, 0x0E, 0x36, 0x36, + 0x0E, 0x0E, 0x0E, 0x36, + 0x0E, 0x3C, 0x3C, 0x3C, + 0x0E, 0x0E, 0x3C, 0x3C, + 0x0E, 0x0E, 0x0E, 0x3C, + 0x0F, 0x10, 0x10, 0x11, + 0x0F, 0x10, 0x11, 0x12, + 0x0F, 0x11, 0x12, 0x13, + 0x0F, 0x10, 0x12, 0x13, + 0x0F, 0x10, 0x11, 0x13, + 0x0F, 0x11, 0x12, 0x14, + 0x0F, 0x11, 0x13, 0x14, + 0x0F, 0x10, 0x13, 0x14, + 0x0F, 0x10, 0x12, 0x14, + 0x0F, 0x11, 0x13, 0x15, + 0x0F, 0x12, 0x14, 0x15, + 0x0F, 0x10, 0x14, 0x15, + 0x0F, 0x10, 0x12, 0x15, + 0x0F, 0x15, 0x15, 0x15, + 0x0F, 0x0F, 0x15, 0x15, + 0x0F, 0x0F, 0x0F, 0x15, + 0x0F, 0x12, 0x13, 0x16, + 0x0F, 0x12, 0x15, 0x16, + 0x0F, 0x10, 0x15, 0x16, + 0x0F, 0x10, 0x13, 0x16, + 0x0F, 0x12, 0x14, 0x17, + 0x0F, 0x13, 0x15, 0x17, + 0x0F, 0x11, 0x15, 0x17, + 0x0F, 0x11, 0x13, 0x17, + 0x0F, 0x17, 0x17, 0x17, + 0x0F, 0x0F, 0x17, 0x17, + 0x0F, 0x0F, 0x0F, 0x17, + 0x0F, 0x13, 0x16, 0x1A, + 0x0F, 0x14, 0x18, 0x1A, + 0x0F, 0x11, 0x18, 0x1A, + 0x0F, 0x11, 0x15, 0x1A, + 0x0F, 0x1A, 0x1A, 0x1A, + 0x0F, 0x0F, 0x1A, 0x1A, + 0x0F, 0x0F, 0x0F, 0x1A, + 0x0F, 0x14, 0x18, 0x1D, + 0x0F, 0x16, 0x1A, 0x1D, + 0x0F, 0x12, 0x1A, 0x1D, + 0x0F, 0x12, 0x16, 0x1D, + 0x0F, 0x1D, 0x1D, 0x1D, + 0x0F, 0x0F, 0x1D, 0x1D, + 0x0F, 0x0F, 0x0F, 0x1D, + 0x0F, 0x15, 0x1A, 0x20, + 0x0F, 0x17, 0x1C, 0x20, + 0x0F, 0x13, 0x1C, 0x20, + 0x0F, 0x13, 0x18, 0x20, + 0x0F, 0x20, 0x20, 0x20, + 0x0F, 0x0F, 0x20, 0x20, + 0x0F, 0x0F, 0x0F, 0x20, + 0x0F, 0x16, 0x1C, 0x23, + 0x0F, 0x19, 0x1E, 0x23, + 0x0F, 0x14, 0x1E, 0x23, + 0x0F, 0x14, 0x19, 0x23, + 0x0F, 0x23, 0x23, 0x23, + 0x0F, 0x0F, 0x23, 0x23, + 0x0F, 0x0F, 0x0F, 0x23, + 0x0F, 0x1A, 0x21, 0x26, + 0x0F, 0x14, 0x21, 0x26, + 0x0F, 0x14, 0x1B, 0x26, + 0x0F, 0x26, 0x26, 0x26, + 0x0F, 0x0F, 0x26, 0x26, + 0x0F, 0x0F, 0x0F, 0x26, + 0x0F, 0x1C, 0x23, 0x29, + 0x0F, 0x15, 0x23, 0x29, + 0x0F, 0x15, 0x1C, 0x29, + 0x0F, 0x29, 0x29, 0x29, + 0x0F, 0x0F, 0x29, 0x29, + 0x0F, 0x0F, 0x0F, 0x29, + 0x0F, 0x1D, 0x25, 0x2C, + 0x0F, 0x16, 0x25, 0x2C, + 0x0F, 0x16, 0x1E, 0x2C, + 0x0F, 0x2C, 0x2C, 0x2C, + 0x0F, 0x0F, 0x2C, 0x2C, + 0x0F, 0x0F, 0x0F, 0x2C, + 0x0F, 0x1F, 0x27, 0x2F, + 0x0F, 0x17, 0x27, 0x2F, + 0x0F, 0x17, 0x1F, 0x2F, + 0x0F, 0x2F, 0x2F, 0x2F, + 0x0F, 0x0F, 0x2F, 0x2F, + 0x0F, 0x0F, 0x0F, 0x2F, + 0x0F, 0x32, 0x32, 0x32, + 0x0F, 0x0F, 0x32, 0x32, + 0x0F, 0x0F, 0x0F, 0x32, + 0x0F, 0x21, 0x2A, 0x33, + 0x0F, 0x18, 0x2A, 0x33, + 0x0F, 0x18, 0x21, 0x33, + 0x0F, 0x37, 0x37, 0x37, + 0x0F, 0x0F, 0x37, 0x37, + 0x0F, 0x0F, 0x0F, 0x37, + 0x0F, 0x3D, 0x3D, 0x3D, + 0x0F, 0x0F, 0x3D, 0x3D, + 0x0F, 0x0F, 0x0F, 0x3D, + 0x10, 0x11, 0x11, 0x12, + 0x10, 0x11, 0x12, 0x13, + 0x10, 0x12, 0x13, 0x14, + 0x10, 0x11, 0x13, 0x14, + 0x10, 0x11, 0x12, 0x14, + 0x10, 0x12, 0x13, 0x15, + 0x10, 0x12, 0x14, 0x15, + 0x10, 0x11, 0x14, 0x15, + 0x10, 0x11, 0x13, 0x15, + 0x10, 0x12, 0x14, 0x16, + 0x10, 0x13, 0x15, 0x16, + 0x10, 0x11, 0x15, 0x16, + 0x10, 0x11, 0x13, 0x16, + 0x10, 0x16, 0x16, 0x16, + 0x10, 0x10, 0x16, 0x16, + 0x10, 0x10, 0x10, 0x16, + 0x10, 0x13, 0x14, 0x17, + 0x10, 0x13, 0x16, 0x17, + 0x10, 0x11, 0x16, 0x17, + 0x10, 0x11, 0x14, 0x17, + 0x10, 0x13, 0x15, 0x18, + 0x10, 0x14, 0x16, 0x18, + 0x10, 0x12, 0x16, 0x18, + 0x10, 0x12, 0x14, 0x18, + 0x10, 0x18, 0x18, 0x18, + 0x10, 0x10, 0x18, 0x18, + 0x10, 0x10, 0x10, 0x18, + 0x10, 0x14, 0x17, 0x1B, + 0x10, 0x15, 0x19, 0x1B, + 0x10, 0x12, 0x19, 0x1B, + 0x10, 0x12, 0x16, 0x1B, + 0x10, 0x1B, 0x1B, 0x1B, + 0x10, 0x10, 0x1B, 0x1B, + 0x10, 0x10, 0x10, 0x1B, + 0x10, 0x15, 0x19, 0x1E, + 0x10, 0x17, 0x1B, 0x1E, + 0x10, 0x13, 0x1B, 0x1E, + 0x10, 0x13, 0x17, 0x1E, + 0x10, 0x1E, 0x1E, 0x1E, + 0x10, 0x10, 0x1E, 0x1E, + 0x10, 0x10, 0x10, 0x1E, + 0x10, 0x16, 0x1B, 0x21, + 0x10, 0x18, 0x1D, 0x21, + 0x10, 0x14, 0x1D, 0x21, + 0x10, 0x14, 0x19, 0x21, + 0x10, 0x21, 0x21, 0x21, + 0x10, 0x10, 0x21, 0x21, + 0x10, 0x10, 0x10, 0x21, + 0x10, 0x17, 0x1D, 0x24, + 0x10, 0x1A, 0x1F, 0x24, + 0x10, 0x15, 0x1F, 0x24, + 0x10, 0x15, 0x1A, 0x24, + 0x10, 0x24, 0x24, 0x24, + 0x10, 0x10, 0x24, 0x24, + 0x10, 0x10, 0x10, 0x24, + 0x10, 0x1B, 0x22, 0x27, + 0x10, 0x15, 0x22, 0x27, + 0x10, 0x15, 0x1C, 0x27, + 0x10, 0x27, 0x27, 0x27, + 0x10, 0x10, 0x27, 0x27, + 0x10, 0x10, 0x10, 0x27, + 0x10, 0x1D, 0x24, 0x2A, + 0x10, 0x16, 0x24, 0x2A, + 0x10, 0x16, 0x1D, 0x2A, + 0x10, 0x2A, 0x2A, 0x2A, + 0x10, 0x10, 0x2A, 0x2A, + 0x10, 0x10, 0x10, 0x2A, + 0x10, 0x1E, 0x26, 0x2D, + 0x10, 0x17, 0x26, 0x2D, + 0x10, 0x17, 0x1F, 0x2D, + 0x10, 0x2D, 0x2D, 0x2D, + 0x10, 0x10, 0x2D, 0x2D, + 0x10, 0x10, 0x10, 0x2D, + 0x10, 0x20, 0x28, 0x30, + 0x10, 0x18, 0x28, 0x30, + 0x10, 0x18, 0x20, 0x30, + 0x10, 0x30, 0x30, 0x30, + 0x10, 0x10, 0x30, 0x30, + 0x10, 0x10, 0x10, 0x30, + 0x10, 0x33, 0x33, 0x33, + 0x10, 0x10, 0x33, 0x33, + 0x10, 0x10, 0x10, 0x33, + 0x10, 0x22, 0x2B, 0x34, + 0x10, 0x19, 0x2B, 0x34, + 0x10, 0x19, 0x22, 0x34, + 0x10, 0x38, 0x38, 0x38, + 0x10, 0x10, 0x38, 0x38, + 0x10, 0x10, 0x10, 0x38, + 0x10, 0x3E, 0x3E, 0x3E, + 0x10, 0x10, 0x3E, 0x3E, + 0x10, 0x10, 0x10, 0x3E, + 0x11, 0x12, 0x12, 0x13, + 0x11, 0x12, 0x13, 0x14, + 0x11, 0x13, 0x14, 0x15, + 0x11, 0x12, 0x14, 0x15, + 0x11, 0x12, 0x13, 0x15, + 0x11, 0x13, 0x14, 0x16, + 0x11, 0x13, 0x15, 0x16, + 0x11, 0x12, 0x15, 0x16, + 0x11, 0x12, 0x14, 0x16, + 0x11, 0x13, 0x15, 0x17, + 0x11, 0x14, 0x16, 0x17, + 0x11, 0x12, 0x16, 0x17, + 0x11, 0x12, 0x14, 0x17, + 0x11, 0x17, 0x17, 0x17, + 0x11, 0x11, 0x17, 0x17, + 0x11, 0x11, 0x11, 0x17, + 0x11, 0x14, 0x15, 0x18, + 0x11, 0x14, 0x17, 0x18, + 0x11, 0x12, 0x17, 0x18, + 0x11, 0x12, 0x15, 0x18, + 0x11, 0x14, 0x16, 0x19, + 0x11, 0x15, 0x17, 0x19, + 0x11, 0x13, 0x17, 0x19, + 0x11, 0x13, 0x15, 0x19, + 0x11, 0x19, 0x19, 0x19, + 0x11, 0x11, 0x19, 0x19, + 0x11, 0x11, 0x11, 0x19, + 0x11, 0x15, 0x18, 0x1C, + 0x11, 0x16, 0x1A, 0x1C, + 0x11, 0x13, 0x1A, 0x1C, + 0x11, 0x13, 0x17, 0x1C, + 0x11, 0x1C, 0x1C, 0x1C, + 0x11, 0x11, 0x1C, 0x1C, + 0x11, 0x11, 0x11, 0x1C, + 0x11, 0x16, 0x1A, 0x1F, + 0x11, 0x18, 0x1C, 0x1F, + 0x11, 0x14, 0x1C, 0x1F, + 0x11, 0x14, 0x18, 0x1F, + 0x11, 0x1F, 0x1F, 0x1F, + 0x11, 0x11, 0x1F, 0x1F, + 0x11, 0x11, 0x11, 0x1F, + 0x11, 0x17, 0x1C, 0x22, + 0x11, 0x19, 0x1E, 0x22, + 0x11, 0x15, 0x1E, 0x22, + 0x11, 0x15, 0x1A, 0x22, + 0x11, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x22, + 0x11, 0x18, 0x1E, 0x25, + 0x11, 0x1B, 0x20, 0x25, + 0x11, 0x16, 0x20, 0x25, + 0x11, 0x16, 0x1B, 0x25, + 0x11, 0x25, 0x25, 0x25, + 0x11, 0x11, 0x25, 0x25, + 0x11, 0x11, 0x11, 0x25, + 0x11, 0x1C, 0x23, 0x28, + 0x11, 0x16, 0x23, 0x28, + 0x11, 0x16, 0x1D, 0x28, + 0x11, 0x28, 0x28, 0x28, + 0x11, 0x11, 0x28, 0x28, + 0x11, 0x11, 0x11, 0x28, + 0x11, 0x1E, 0x25, 0x2B, + 0x11, 0x17, 0x25, 0x2B, + 0x11, 0x17, 0x1E, 0x2B, + 0x11, 0x2B, 0x2B, 0x2B, + 0x11, 0x11, 0x2B, 0x2B, + 0x11, 0x11, 0x11, 0x2B, + 0x11, 0x1F, 0x27, 0x2E, + 0x11, 0x18, 0x27, 0x2E, + 0x11, 0x18, 0x20, 0x2E, + 0x11, 0x2E, 0x2E, 0x2E, + 0x11, 0x11, 0x2E, 0x2E, + 0x11, 0x11, 0x11, 0x2E, + 0x11, 0x21, 0x29, 0x31, + 0x11, 0x19, 0x29, 0x31, + 0x11, 0x19, 0x21, 0x31, + 0x11, 0x31, 0x31, 0x31, + 0x11, 0x11, 0x31, 0x31, + 0x11, 0x11, 0x11, 0x31, + 0x11, 0x34, 0x34, 0x34, + 0x11, 0x11, 0x34, 0x34, + 0x11, 0x11, 0x11, 0x34, + 0x11, 0x23, 0x2C, 0x35, + 0x11, 0x1A, 0x2C, 0x35, + 0x11, 0x1A, 0x23, 0x35, + 0x11, 0x39, 0x39, 0x39, + 0x11, 0x11, 0x39, 0x39, + 0x11, 0x11, 0x11, 0x39, + 0x11, 0x3F, 0x3F, 0x3F, + 0x11, 0x11, 0x3F, 0x3F, + 0x11, 0x11, 0x11, 0x3F, + 0x12, 0x13, 0x13, 0x14, + 0x12, 0x13, 0x14, 0x15, + 0x12, 0x14, 0x15, 0x16, + 0x12, 0x13, 0x15, 0x16, + 0x12, 0x13, 0x14, 0x16, + 0x12, 0x14, 0x15, 0x17, + 0x12, 0x14, 0x16, 0x17, + 0x12, 0x13, 0x16, 0x17, + 0x12, 0x13, 0x15, 0x17, + 0x12, 0x14, 0x16, 0x18, + 0x12, 0x15, 0x17, 0x18, + 0x12, 0x13, 0x17, 0x18, + 0x12, 0x13, 0x15, 0x18, + 0x12, 0x18, 0x18, 0x18, + 0x12, 0x12, 0x18, 0x18, + 0x12, 0x12, 0x12, 0x18, + 0x12, 0x15, 0x16, 0x19, + 0x12, 0x15, 0x18, 0x19, + 0x12, 0x13, 0x18, 0x19, + 0x12, 0x13, 0x16, 0x19, + 0x12, 0x15, 0x17, 0x1A, + 0x12, 0x16, 0x18, 0x1A, + 0x12, 0x14, 0x18, 0x1A, + 0x12, 0x14, 0x16, 0x1A, + 0x12, 0x1A, 0x1A, 0x1A, + 0x12, 0x12, 0x1A, 0x1A, + 0x12, 0x12, 0x12, 0x1A, + 0x12, 0x16, 0x19, 0x1D, + 0x12, 0x17, 0x1B, 0x1D, + 0x12, 0x14, 0x1B, 0x1D, + 0x12, 0x14, 0x18, 0x1D, + 0x12, 0x1D, 0x1D, 0x1D, + 0x12, 0x12, 0x1D, 0x1D, + 0x12, 0x12, 0x12, 0x1D, + 0x12, 0x17, 0x1B, 0x20, + 0x12, 0x19, 0x1D, 0x20, + 0x12, 0x15, 0x1D, 0x20, + 0x12, 0x15, 0x19, 0x20, + 0x12, 0x20, 0x20, 0x20, + 0x12, 0x12, 0x20, 0x20, + 0x12, 0x12, 0x12, 0x20, + 0x12, 0x18, 0x1D, 0x23, + 0x12, 0x1A, 0x1F, 0x23, + 0x12, 0x16, 0x1F, 0x23, + 0x12, 0x16, 0x1B, 0x23, + 0x12, 0x23, 0x23, 0x23, + 0x12, 0x12, 0x23, 0x23, + 0x12, 0x12, 0x12, 0x23, + 0x12, 0x19, 0x1F, 0x26, + 0x12, 0x1C, 0x21, 0x26, + 0x12, 0x17, 0x21, 0x26, + 0x12, 0x17, 0x1C, 0x26, + 0x12, 0x26, 0x26, 0x26, + 0x12, 0x12, 0x26, 0x26, + 0x12, 0x12, 0x12, 0x26, + 0x12, 0x1D, 0x24, 0x29, + 0x12, 0x17, 0x24, 0x29, + 0x12, 0x17, 0x1E, 0x29, + 0x12, 0x29, 0x29, 0x29, + 0x12, 0x12, 0x29, 0x29, + 0x12, 0x12, 0x12, 0x29, + 0x12, 0x1F, 0x26, 0x2C, + 0x12, 0x18, 0x26, 0x2C, + 0x12, 0x18, 0x1F, 0x2C, + 0x12, 0x2C, 0x2C, 0x2C, + 0x12, 0x12, 0x2C, 0x2C, + 0x12, 0x12, 0x12, 0x2C, + 0x12, 0x20, 0x28, 0x2F, + 0x12, 0x19, 0x28, 0x2F, + 0x12, 0x19, 0x21, 0x2F, + 0x12, 0x2F, 0x2F, 0x2F, + 0x12, 0x12, 0x2F, 0x2F, + 0x12, 0x12, 0x12, 0x2F, + 0x12, 0x22, 0x2A, 0x32, + 0x12, 0x1A, 0x2A, 0x32, + 0x12, 0x1A, 0x22, 0x32, + 0x12, 0x32, 0x32, 0x32, + 0x12, 0x12, 0x32, 0x32, + 0x12, 0x12, 0x12, 0x32, + 0x12, 0x35, 0x35, 0x35, + 0x12, 0x12, 0x35, 0x35, + 0x12, 0x12, 0x12, 0x35, + 0x12, 0x24, 0x2D, 0x36, + 0x12, 0x1B, 0x2D, 0x36, + 0x12, 0x1B, 0x24, 0x36, + 0x12, 0x3A, 0x3A, 0x3A, + 0x12, 0x12, 0x3A, 0x3A, + 0x12, 0x12, 0x12, 0x3A, + 0x13, 0x14, 0x14, 0x15, + 0x13, 0x14, 0x15, 0x16, + 0x13, 0x15, 0x16, 0x17, + 0x13, 0x14, 0x16, 0x17, + 0x13, 0x14, 0x15, 0x17, + 0x13, 0x15, 0x16, 0x18, + 0x13, 0x15, 0x17, 0x18, + 0x13, 0x14, 0x17, 0x18, + 0x13, 0x14, 0x16, 0x18, + 0x13, 0x15, 0x17, 0x19, + 0x13, 0x16, 0x18, 0x19, + 0x13, 0x14, 0x18, 0x19, + 0x13, 0x14, 0x16, 0x19, + 0x13, 0x19, 0x19, 0x19, + 0x13, 0x13, 0x19, 0x19, + 0x13, 0x13, 0x13, 0x19, + 0x13, 0x16, 0x17, 0x1A, + 0x13, 0x16, 0x19, 0x1A, + 0x13, 0x14, 0x19, 0x1A, + 0x13, 0x14, 0x17, 0x1A, + 0x13, 0x16, 0x18, 0x1B, + 0x13, 0x17, 0x19, 0x1B, + 0x13, 0x15, 0x19, 0x1B, + 0x13, 0x15, 0x17, 0x1B, + 0x13, 0x1B, 0x1B, 0x1B, + 0x13, 0x13, 0x1B, 0x1B, + 0x13, 0x13, 0x13, 0x1B, + 0x13, 0x17, 0x1A, 0x1E, + 0x13, 0x18, 0x1C, 0x1E, + 0x13, 0x15, 0x1C, 0x1E, + 0x13, 0x15, 0x19, 0x1E, + 0x13, 0x1E, 0x1E, 0x1E, + 0x13, 0x13, 0x1E, 0x1E, + 0x13, 0x13, 0x13, 0x1E, + 0x13, 0x18, 0x1C, 0x21, + 0x13, 0x1A, 0x1E, 0x21, + 0x13, 0x16, 0x1E, 0x21, + 0x13, 0x16, 0x1A, 0x21, + 0x13, 0x21, 0x21, 0x21, + 0x13, 0x13, 0x21, 0x21, + 0x13, 0x13, 0x13, 0x21, + 0x13, 0x19, 0x1E, 0x24, + 0x13, 0x1B, 0x20, 0x24, + 0x13, 0x17, 0x20, 0x24, + 0x13, 0x17, 0x1C, 0x24, + 0x13, 0x24, 0x24, 0x24, + 0x13, 0x13, 0x24, 0x24, + 0x13, 0x13, 0x13, 0x24, + 0x13, 0x1A, 0x20, 0x27, + 0x13, 0x1D, 0x22, 0x27, + 0x13, 0x18, 0x22, 0x27, + 0x13, 0x18, 0x1D, 0x27, + 0x13, 0x27, 0x27, 0x27, + 0x13, 0x13, 0x27, 0x27, + 0x13, 0x13, 0x13, 0x27, + 0x13, 0x1E, 0x25, 0x2A, + 0x13, 0x18, 0x25, 0x2A, + 0x13, 0x18, 0x1F, 0x2A, + 0x13, 0x2A, 0x2A, 0x2A, + 0x13, 0x13, 0x2A, 0x2A, + 0x13, 0x13, 0x13, 0x2A, + 0x13, 0x20, 0x27, 0x2D, + 0x13, 0x19, 0x27, 0x2D, + 0x13, 0x19, 0x20, 0x2D, + 0x13, 0x2D, 0x2D, 0x2D, + 0x13, 0x13, 0x2D, 0x2D, + 0x13, 0x13, 0x13, 0x2D, + 0x13, 0x21, 0x29, 0x30, + 0x13, 0x1A, 0x29, 0x30, + 0x13, 0x1A, 0x22, 0x30, + 0x13, 0x30, 0x30, 0x30, + 0x13, 0x13, 0x30, 0x30, + 0x13, 0x13, 0x13, 0x30, + 0x13, 0x23, 0x2B, 0x33, + 0x13, 0x1B, 0x2B, 0x33, + 0x13, 0x1B, 0x23, 0x33, + 0x13, 0x33, 0x33, 0x33, + 0x13, 0x13, 0x33, 0x33, + 0x13, 0x13, 0x13, 0x33, + 0x13, 0x36, 0x36, 0x36, + 0x13, 0x13, 0x36, 0x36, + 0x13, 0x13, 0x13, 0x36, + 0x13, 0x25, 0x2E, 0x37, + 0x13, 0x1C, 0x2E, 0x37, + 0x13, 0x1C, 0x25, 0x37, + 0x13, 0x3B, 0x3B, 0x3B, + 0x13, 0x13, 0x3B, 0x3B, + 0x13, 0x13, 0x13, 0x3B, + 0x14, 0x15, 0x15, 0x16, + 0x14, 0x15, 0x16, 0x17, + 0x14, 0x16, 0x17, 0x18, + 0x14, 0x15, 0x17, 0x18, + 0x14, 0x15, 0x16, 0x18, + 0x14, 0x16, 0x17, 0x19, + 0x14, 0x16, 0x18, 0x19, + 0x14, 0x15, 0x18, 0x19, + 0x14, 0x15, 0x17, 0x19, + 0x14, 0x16, 0x18, 0x1A, + 0x14, 0x17, 0x19, 0x1A, + 0x14, 0x15, 0x19, 0x1A, + 0x14, 0x15, 0x17, 0x1A, + 0x14, 0x1A, 0x1A, 0x1A, + 0x14, 0x14, 0x1A, 0x1A, + 0x14, 0x14, 0x14, 0x1A, + 0x14, 0x17, 0x18, 0x1B, + 0x14, 0x17, 0x1A, 0x1B, + 0x14, 0x15, 0x1A, 0x1B, + 0x14, 0x15, 0x18, 0x1B, + 0x14, 0x17, 0x19, 0x1C, + 0x14, 0x18, 0x1A, 0x1C, + 0x14, 0x16, 0x1A, 0x1C, + 0x14, 0x16, 0x18, 0x1C, + 0x14, 0x1C, 0x1C, 0x1C, + 0x14, 0x14, 0x1C, 0x1C, + 0x14, 0x14, 0x14, 0x1C, + 0x14, 0x18, 0x1B, 0x1F, + 0x14, 0x19, 0x1D, 0x1F, + 0x14, 0x16, 0x1D, 0x1F, + 0x14, 0x16, 0x1A, 0x1F, + 0x14, 0x1F, 0x1F, 0x1F, + 0x14, 0x14, 0x1F, 0x1F, + 0x14, 0x14, 0x14, 0x1F, + 0x14, 0x19, 0x1D, 0x22, + 0x14, 0x1B, 0x1F, 0x22, + 0x14, 0x17, 0x1F, 0x22, + 0x14, 0x17, 0x1B, 0x22, + 0x14, 0x22, 0x22, 0x22, + 0x14, 0x14, 0x22, 0x22, + 0x14, 0x14, 0x14, 0x22, + 0x14, 0x1A, 0x1F, 0x25, + 0x14, 0x1C, 0x21, 0x25, + 0x14, 0x18, 0x21, 0x25, + 0x14, 0x18, 0x1D, 0x25, + 0x14, 0x25, 0x25, 0x25, + 0x14, 0x14, 0x25, 0x25, + 0x14, 0x14, 0x14, 0x25, + 0x14, 0x1B, 0x21, 0x28, + 0x14, 0x1E, 0x23, 0x28, + 0x14, 0x19, 0x23, 0x28, + 0x14, 0x19, 0x1E, 0x28, + 0x14, 0x28, 0x28, 0x28, + 0x14, 0x14, 0x28, 0x28, + 0x14, 0x14, 0x14, 0x28, + 0x14, 0x1F, 0x26, 0x2B, + 0x14, 0x19, 0x26, 0x2B, + 0x14, 0x19, 0x20, 0x2B, + 0x14, 0x2B, 0x2B, 0x2B, + 0x14, 0x14, 0x2B, 0x2B, + 0x14, 0x14, 0x14, 0x2B, + 0x14, 0x21, 0x28, 0x2E, + 0x14, 0x1A, 0x28, 0x2E, + 0x14, 0x1A, 0x21, 0x2E, + 0x14, 0x2E, 0x2E, 0x2E, + 0x14, 0x14, 0x2E, 0x2E, + 0x14, 0x14, 0x14, 0x2E, + 0x14, 0x22, 0x2A, 0x31, + 0x14, 0x1B, 0x2A, 0x31, + 0x14, 0x1B, 0x23, 0x31, + 0x14, 0x31, 0x31, 0x31, + 0x14, 0x14, 0x31, 0x31, + 0x14, 0x14, 0x14, 0x31, + 0x14, 0x24, 0x2C, 0x34, + 0x14, 0x1C, 0x2C, 0x34, + 0x14, 0x1C, 0x24, 0x34, + 0x14, 0x34, 0x34, 0x34, + 0x14, 0x14, 0x34, 0x34, + 0x14, 0x14, 0x14, 0x34, + 0x14, 0x37, 0x37, 0x37, + 0x14, 0x14, 0x37, 0x37, + 0x14, 0x14, 0x14, 0x37, + 0x14, 0x26, 0x2F, 0x38, + 0x14, 0x1D, 0x2F, 0x38, + 0x14, 0x1D, 0x26, 0x38, + 0x14, 0x3C, 0x3C, 0x3C, + 0x14, 0x14, 0x3C, 0x3C, + 0x14, 0x14, 0x14, 0x3C, + 0x15, 0x16, 0x16, 0x17, + 0x15, 0x16, 0x17, 0x18, + 0x15, 0x17, 0x18, 0x19, + 0x15, 0x16, 0x18, 0x19, + 0x15, 0x16, 0x17, 0x19, + 0x15, 0x17, 0x18, 0x1A, + 0x15, 0x17, 0x19, 0x1A, + 0x15, 0x16, 0x19, 0x1A, + 0x15, 0x16, 0x18, 0x1A, + 0x15, 0x17, 0x19, 0x1B, + 0x15, 0x18, 0x1A, 0x1B, + 0x15, 0x16, 0x1A, 0x1B, + 0x15, 0x16, 0x18, 0x1B, + 0x15, 0x1B, 0x1B, 0x1B, + 0x15, 0x15, 0x1B, 0x1B, + 0x15, 0x15, 0x15, 0x1B, + 0x15, 0x18, 0x19, 0x1C, + 0x15, 0x18, 0x1B, 0x1C, + 0x15, 0x16, 0x1B, 0x1C, + 0x15, 0x16, 0x19, 0x1C, + 0x15, 0x18, 0x1A, 0x1D, + 0x15, 0x19, 0x1B, 0x1D, + 0x15, 0x17, 0x1B, 0x1D, + 0x15, 0x17, 0x19, 0x1D, + 0x15, 0x1D, 0x1D, 0x1D, + 0x15, 0x15, 0x1D, 0x1D, + 0x15, 0x15, 0x15, 0x1D, + 0x15, 0x19, 0x1C, 0x20, + 0x15, 0x1A, 0x1E, 0x20, + 0x15, 0x17, 0x1E, 0x20, + 0x15, 0x17, 0x1B, 0x20, + 0x15, 0x20, 0x20, 0x20, + 0x15, 0x15, 0x20, 0x20, + 0x15, 0x15, 0x15, 0x20, + 0x15, 0x1A, 0x1E, 0x23, + 0x15, 0x1C, 0x20, 0x23, + 0x15, 0x18, 0x20, 0x23, + 0x15, 0x18, 0x1C, 0x23, + 0x15, 0x23, 0x23, 0x23, + 0x15, 0x15, 0x23, 0x23, + 0x15, 0x15, 0x15, 0x23, + 0x15, 0x1B, 0x20, 0x26, + 0x15, 0x1D, 0x22, 0x26, + 0x15, 0x19, 0x22, 0x26, + 0x15, 0x19, 0x1E, 0x26, + 0x15, 0x26, 0x26, 0x26, + 0x15, 0x15, 0x26, 0x26, + 0x15, 0x15, 0x15, 0x26, + 0x15, 0x1C, 0x22, 0x29, + 0x15, 0x1F, 0x24, 0x29, + 0x15, 0x1A, 0x24, 0x29, + 0x15, 0x1A, 0x1F, 0x29, + 0x15, 0x29, 0x29, 0x29, + 0x15, 0x15, 0x29, 0x29, + 0x15, 0x15, 0x15, 0x29, + 0x15, 0x20, 0x27, 0x2C, + 0x15, 0x1A, 0x27, 0x2C, + 0x15, 0x1A, 0x21, 0x2C, + 0x15, 0x2C, 0x2C, 0x2C, + 0x15, 0x15, 0x2C, 0x2C, + 0x15, 0x15, 0x15, 0x2C, + 0x15, 0x22, 0x29, 0x2F, + 0x15, 0x1B, 0x29, 0x2F, + 0x15, 0x1B, 0x22, 0x2F, + 0x15, 0x2F, 0x2F, 0x2F, + 0x15, 0x15, 0x2F, 0x2F, + 0x15, 0x15, 0x15, 0x2F, + 0x15, 0x23, 0x2B, 0x32, + 0x15, 0x1C, 0x2B, 0x32, + 0x15, 0x1C, 0x24, 0x32, + 0x15, 0x32, 0x32, 0x32, + 0x15, 0x15, 0x32, 0x32, + 0x15, 0x15, 0x15, 0x32, + 0x15, 0x25, 0x2D, 0x35, + 0x15, 0x1D, 0x2D, 0x35, + 0x15, 0x1D, 0x25, 0x35, + 0x15, 0x35, 0x35, 0x35, + 0x15, 0x15, 0x35, 0x35, + 0x15, 0x15, 0x15, 0x35, + 0x15, 0x38, 0x38, 0x38, + 0x15, 0x15, 0x38, 0x38, + 0x15, 0x15, 0x15, 0x38, + 0x15, 0x27, 0x30, 0x39, + 0x15, 0x1E, 0x30, 0x39, + 0x15, 0x1E, 0x27, 0x39, + 0x15, 0x3D, 0x3D, 0x3D, + 0x15, 0x15, 0x3D, 0x3D, + 0x15, 0x15, 0x15, 0x3D, + 0x16, 0x17, 0x17, 0x18, + 0x16, 0x17, 0x18, 0x19, + 0x16, 0x18, 0x19, 0x1A, + 0x16, 0x17, 0x19, 0x1A, + 0x16, 0x17, 0x18, 0x1A, + 0x16, 0x18, 0x19, 0x1B, + 0x16, 0x18, 0x1A, 0x1B, + 0x16, 0x17, 0x1A, 0x1B, + 0x16, 0x17, 0x19, 0x1B, + 0x16, 0x18, 0x1A, 0x1C, + 0x16, 0x19, 0x1B, 0x1C, + 0x16, 0x17, 0x1B, 0x1C, + 0x16, 0x17, 0x19, 0x1C, + 0x16, 0x1C, 0x1C, 0x1C, + 0x16, 0x16, 0x1C, 0x1C, + 0x16, 0x16, 0x16, 0x1C, + 0x16, 0x19, 0x1A, 0x1D, + 0x16, 0x19, 0x1C, 0x1D, + 0x16, 0x17, 0x1C, 0x1D, + 0x16, 0x17, 0x1A, 0x1D, + 0x16, 0x19, 0x1B, 0x1E, + 0x16, 0x1A, 0x1C, 0x1E, + 0x16, 0x18, 0x1C, 0x1E, + 0x16, 0x18, 0x1A, 0x1E, + 0x16, 0x1E, 0x1E, 0x1E, + 0x16, 0x16, 0x1E, 0x1E, + 0x16, 0x16, 0x16, 0x1E, + 0x16, 0x1A, 0x1D, 0x21, + 0x16, 0x1B, 0x1F, 0x21, + 0x16, 0x18, 0x1F, 0x21, + 0x16, 0x18, 0x1C, 0x21, + 0x16, 0x21, 0x21, 0x21, + 0x16, 0x16, 0x21, 0x21, + 0x16, 0x16, 0x16, 0x21, + 0x16, 0x1B, 0x1F, 0x24, + 0x16, 0x1D, 0x21, 0x24, + 0x16, 0x19, 0x21, 0x24, + 0x16, 0x19, 0x1D, 0x24, + 0x16, 0x24, 0x24, 0x24, + 0x16, 0x16, 0x24, 0x24, + 0x16, 0x16, 0x16, 0x24, + 0x16, 0x1C, 0x21, 0x27, + 0x16, 0x1E, 0x23, 0x27, + 0x16, 0x1A, 0x23, 0x27, + 0x16, 0x1A, 0x1F, 0x27, + 0x16, 0x27, 0x27, 0x27, + 0x16, 0x16, 0x27, 0x27, + 0x16, 0x16, 0x16, 0x27, + 0x16, 0x1D, 0x23, 0x2A, + 0x16, 0x20, 0x25, 0x2A, + 0x16, 0x1B, 0x25, 0x2A, + 0x16, 0x1B, 0x20, 0x2A, + 0x16, 0x2A, 0x2A, 0x2A, + 0x16, 0x16, 0x2A, 0x2A, + 0x16, 0x16, 0x16, 0x2A, + 0x16, 0x21, 0x28, 0x2D, + 0x16, 0x1B, 0x28, 0x2D, + 0x16, 0x1B, 0x22, 0x2D, + 0x16, 0x2D, 0x2D, 0x2D, + 0x16, 0x16, 0x2D, 0x2D, + 0x16, 0x16, 0x16, 0x2D, + 0x16, 0x23, 0x2A, 0x30, + 0x16, 0x1C, 0x2A, 0x30, + 0x16, 0x1C, 0x23, 0x30, + 0x16, 0x30, 0x30, 0x30, + 0x16, 0x16, 0x30, 0x30, + 0x16, 0x16, 0x16, 0x30, + 0x16, 0x24, 0x2C, 0x33, + 0x16, 0x1D, 0x2C, 0x33, + 0x16, 0x1D, 0x25, 0x33, + 0x16, 0x33, 0x33, 0x33, + 0x16, 0x16, 0x33, 0x33, + 0x16, 0x16, 0x16, 0x33, + 0x16, 0x26, 0x2E, 0x36, + 0x16, 0x1E, 0x2E, 0x36, + 0x16, 0x1E, 0x26, 0x36, + 0x16, 0x36, 0x36, 0x36, + 0x16, 0x16, 0x36, 0x36, + 0x16, 0x16, 0x16, 0x36, + 0x16, 0x39, 0x39, 0x39, + 0x16, 0x16, 0x39, 0x39, + 0x16, 0x16, 0x16, 0x39, + 0x16, 0x28, 0x31, 0x3A, + 0x16, 0x1F, 0x31, 0x3A, + 0x16, 0x1F, 0x28, 0x3A, + 0x16, 0x3E, 0x3E, 0x3E, + 0x16, 0x16, 0x3E, 0x3E, + 0x16, 0x16, 0x16, 0x3E, + 0x17, 0x18, 0x18, 0x19, + 0x17, 0x18, 0x19, 0x1A, + 0x17, 0x19, 0x1A, 0x1B, + 0x17, 0x18, 0x1A, 0x1B, + 0x17, 0x18, 0x19, 0x1B, + 0x17, 0x19, 0x1A, 0x1C, + 0x17, 0x19, 0x1B, 0x1C, + 0x17, 0x18, 0x1B, 0x1C, + 0x17, 0x18, 0x1A, 0x1C, + 0x17, 0x19, 0x1B, 0x1D, + 0x17, 0x1A, 0x1C, 0x1D, + 0x17, 0x18, 0x1C, 0x1D, + 0x17, 0x18, 0x1A, 0x1D, + 0x17, 0x1D, 0x1D, 0x1D, + 0x17, 0x17, 0x1D, 0x1D, + 0x17, 0x17, 0x17, 0x1D, + 0x17, 0x1A, 0x1B, 0x1E, + 0x17, 0x1A, 0x1D, 0x1E, + 0x17, 0x18, 0x1D, 0x1E, + 0x17, 0x18, 0x1B, 0x1E, + 0x17, 0x1A, 0x1C, 0x1F, + 0x17, 0x1B, 0x1D, 0x1F, + 0x17, 0x19, 0x1D, 0x1F, + 0x17, 0x19, 0x1B, 0x1F, + 0x17, 0x1F, 0x1F, 0x1F, + 0x17, 0x17, 0x1F, 0x1F, + 0x17, 0x17, 0x17, 0x1F, + 0x17, 0x1B, 0x1E, 0x22, + 0x17, 0x1C, 0x20, 0x22, + 0x17, 0x19, 0x20, 0x22, + 0x17, 0x19, 0x1D, 0x22, + 0x17, 0x22, 0x22, 0x22, + 0x17, 0x17, 0x22, 0x22, + 0x17, 0x17, 0x17, 0x22, + 0x17, 0x1C, 0x20, 0x25, + 0x17, 0x1E, 0x22, 0x25, + 0x17, 0x1A, 0x22, 0x25, + 0x17, 0x1A, 0x1E, 0x25, + 0x17, 0x25, 0x25, 0x25, + 0x17, 0x17, 0x25, 0x25, + 0x17, 0x17, 0x17, 0x25, + 0x17, 0x1D, 0x22, 0x28, + 0x17, 0x1F, 0x24, 0x28, + 0x17, 0x1B, 0x24, 0x28, + 0x17, 0x1B, 0x20, 0x28, + 0x17, 0x28, 0x28, 0x28, + 0x17, 0x17, 0x28, 0x28, + 0x17, 0x17, 0x17, 0x28, + 0x17, 0x1E, 0x24, 0x2B, + 0x17, 0x21, 0x26, 0x2B, + 0x17, 0x1C, 0x26, 0x2B, + 0x17, 0x1C, 0x21, 0x2B, + 0x17, 0x2B, 0x2B, 0x2B, + 0x17, 0x17, 0x2B, 0x2B, + 0x17, 0x17, 0x17, 0x2B, + 0x17, 0x22, 0x29, 0x2E, + 0x17, 0x1C, 0x29, 0x2E, + 0x17, 0x1C, 0x23, 0x2E, + 0x17, 0x2E, 0x2E, 0x2E, + 0x17, 0x17, 0x2E, 0x2E, + 0x17, 0x17, 0x17, 0x2E, + 0x17, 0x24, 0x2B, 0x31, + 0x17, 0x1D, 0x2B, 0x31, + 0x17, 0x1D, 0x24, 0x31, + 0x17, 0x31, 0x31, 0x31, + 0x17, 0x17, 0x31, 0x31, + 0x17, 0x17, 0x17, 0x31, + 0x17, 0x25, 0x2D, 0x34, + 0x17, 0x1E, 0x2D, 0x34, + 0x17, 0x1E, 0x26, 0x34, + 0x17, 0x34, 0x34, 0x34, + 0x17, 0x17, 0x34, 0x34, + 0x17, 0x17, 0x17, 0x34, + 0x17, 0x27, 0x2F, 0x37, + 0x17, 0x1F, 0x2F, 0x37, + 0x17, 0x1F, 0x27, 0x37, + 0x17, 0x37, 0x37, 0x37, + 0x17, 0x17, 0x37, 0x37, + 0x17, 0x17, 0x17, 0x37, + 0x17, 0x3A, 0x3A, 0x3A, + 0x17, 0x17, 0x3A, 0x3A, + 0x17, 0x17, 0x17, 0x3A, + 0x17, 0x29, 0x32, 0x3B, + 0x17, 0x20, 0x32, 0x3B, + 0x17, 0x20, 0x29, 0x3B, + 0x17, 0x3F, 0x3F, 0x3F, + 0x17, 0x17, 0x3F, 0x3F, + 0x17, 0x17, 0x17, 0x3F, + 0x18, 0x19, 0x19, 0x1A, + 0x18, 0x19, 0x1A, 0x1B, + 0x18, 0x1A, 0x1B, 0x1C, + 0x18, 0x19, 0x1B, 0x1C, + 0x18, 0x19, 0x1A, 0x1C, + 0x18, 0x1A, 0x1B, 0x1D, + 0x18, 0x1A, 0x1C, 0x1D, + 0x18, 0x19, 0x1C, 0x1D, + 0x18, 0x19, 0x1B, 0x1D, + 0x18, 0x1A, 0x1C, 0x1E, + 0x18, 0x1B, 0x1D, 0x1E, + 0x18, 0x19, 0x1D, 0x1E, + 0x18, 0x19, 0x1B, 0x1E, + 0x18, 0x1E, 0x1E, 0x1E, + 0x18, 0x18, 0x1E, 0x1E, + 0x18, 0x18, 0x18, 0x1E, + 0x18, 0x1B, 0x1C, 0x1F, + 0x18, 0x1B, 0x1E, 0x1F, + 0x18, 0x19, 0x1E, 0x1F, + 0x18, 0x19, 0x1C, 0x1F, + 0x18, 0x1B, 0x1D, 0x20, + 0x18, 0x1C, 0x1E, 0x20, + 0x18, 0x1A, 0x1E, 0x20, + 0x18, 0x1A, 0x1C, 0x20, + 0x18, 0x20, 0x20, 0x20, + 0x18, 0x18, 0x20, 0x20, + 0x18, 0x18, 0x18, 0x20, + 0x18, 0x1C, 0x1F, 0x23, + 0x18, 0x1D, 0x21, 0x23, + 0x18, 0x1A, 0x21, 0x23, + 0x18, 0x1A, 0x1E, 0x23, + 0x18, 0x23, 0x23, 0x23, + 0x18, 0x18, 0x23, 0x23, + 0x18, 0x18, 0x18, 0x23, + 0x18, 0x1D, 0x21, 0x26, + 0x18, 0x1F, 0x23, 0x26, + 0x18, 0x1B, 0x23, 0x26, + 0x18, 0x1B, 0x1F, 0x26, + 0x18, 0x26, 0x26, 0x26, + 0x18, 0x18, 0x26, 0x26, + 0x18, 0x18, 0x18, 0x26, + 0x18, 0x1E, 0x23, 0x29, + 0x18, 0x20, 0x25, 0x29, + 0x18, 0x1C, 0x25, 0x29, + 0x18, 0x1C, 0x21, 0x29, + 0x18, 0x29, 0x29, 0x29, + 0x18, 0x18, 0x29, 0x29, + 0x18, 0x18, 0x18, 0x29, + 0x18, 0x1F, 0x25, 0x2C, + 0x18, 0x22, 0x27, 0x2C, + 0x18, 0x1D, 0x27, 0x2C, + 0x18, 0x1D, 0x22, 0x2C, + 0x18, 0x2C, 0x2C, 0x2C, + 0x18, 0x18, 0x2C, 0x2C, + 0x18, 0x18, 0x18, 0x2C, + 0x18, 0x23, 0x2A, 0x2F, + 0x18, 0x1D, 0x2A, 0x2F, + 0x18, 0x1D, 0x24, 0x2F, + 0x18, 0x2F, 0x2F, 0x2F, + 0x18, 0x18, 0x2F, 0x2F, + 0x18, 0x18, 0x18, 0x2F, + 0x18, 0x25, 0x2C, 0x32, + 0x18, 0x1E, 0x2C, 0x32, + 0x18, 0x1E, 0x25, 0x32, + 0x18, 0x32, 0x32, 0x32, + 0x18, 0x18, 0x32, 0x32, + 0x18, 0x18, 0x18, 0x32, + 0x18, 0x26, 0x2E, 0x35, + 0x18, 0x1F, 0x2E, 0x35, + 0x18, 0x1F, 0x27, 0x35, + 0x18, 0x35, 0x35, 0x35, + 0x18, 0x18, 0x35, 0x35, + 0x18, 0x18, 0x18, 0x35, + 0x18, 0x28, 0x30, 0x38, + 0x18, 0x20, 0x30, 0x38, + 0x18, 0x20, 0x28, 0x38, + 0x18, 0x38, 0x38, 0x38, + 0x18, 0x18, 0x38, 0x38, + 0x18, 0x18, 0x18, 0x38, + 0x18, 0x3B, 0x3B, 0x3B, + 0x18, 0x18, 0x3B, 0x3B, + 0x18, 0x18, 0x18, 0x3B, + 0x18, 0x2A, 0x33, 0x3C, + 0x18, 0x21, 0x33, 0x3C, + 0x18, 0x21, 0x2A, 0x3C, + 0x19, 0x1A, 0x1A, 0x1B, + 0x19, 0x1A, 0x1B, 0x1C, + 0x19, 0x1B, 0x1C, 0x1D, + 0x19, 0x1A, 0x1C, 0x1D, + 0x19, 0x1A, 0x1B, 0x1D, + 0x19, 0x1B, 0x1C, 0x1E, + 0x19, 0x1B, 0x1D, 0x1E, + 0x19, 0x1A, 0x1D, 0x1E, + 0x19, 0x1A, 0x1C, 0x1E, + 0x19, 0x1B, 0x1D, 0x1F, + 0x19, 0x1C, 0x1E, 0x1F, + 0x19, 0x1A, 0x1E, 0x1F, + 0x19, 0x1A, 0x1C, 0x1F, + 0x19, 0x1F, 0x1F, 0x1F, + 0x19, 0x19, 0x1F, 0x1F, + 0x19, 0x19, 0x19, 0x1F, + 0x19, 0x1C, 0x1D, 0x20, + 0x19, 0x1C, 0x1F, 0x20, + 0x19, 0x1A, 0x1F, 0x20, + 0x19, 0x1A, 0x1D, 0x20, + 0x19, 0x1C, 0x1E, 0x21, + 0x19, 0x1D, 0x1F, 0x21, + 0x19, 0x1B, 0x1F, 0x21, + 0x19, 0x1B, 0x1D, 0x21, + 0x19, 0x21, 0x21, 0x21, + 0x19, 0x19, 0x21, 0x21, + 0x19, 0x19, 0x19, 0x21, + 0x19, 0x1D, 0x20, 0x24, + 0x19, 0x1E, 0x22, 0x24, + 0x19, 0x1B, 0x22, 0x24, + 0x19, 0x1B, 0x1F, 0x24, + 0x19, 0x24, 0x24, 0x24, + 0x19, 0x19, 0x24, 0x24, + 0x19, 0x19, 0x19, 0x24, + 0x19, 0x1E, 0x22, 0x27, + 0x19, 0x20, 0x24, 0x27, + 0x19, 0x1C, 0x24, 0x27, + 0x19, 0x1C, 0x20, 0x27, + 0x19, 0x27, 0x27, 0x27, + 0x19, 0x19, 0x27, 0x27, + 0x19, 0x19, 0x19, 0x27, + 0x19, 0x1F, 0x24, 0x2A, + 0x19, 0x21, 0x26, 0x2A, + 0x19, 0x1D, 0x26, 0x2A, + 0x19, 0x1D, 0x22, 0x2A, + 0x19, 0x2A, 0x2A, 0x2A, + 0x19, 0x19, 0x2A, 0x2A, + 0x19, 0x19, 0x19, 0x2A, + 0x19, 0x20, 0x26, 0x2D, + 0x19, 0x23, 0x28, 0x2D, + 0x19, 0x1E, 0x28, 0x2D, + 0x19, 0x1E, 0x23, 0x2D, + 0x19, 0x2D, 0x2D, 0x2D, + 0x19, 0x19, 0x2D, 0x2D, + 0x19, 0x19, 0x19, 0x2D, + 0x19, 0x24, 0x2B, 0x30, + 0x19, 0x1E, 0x2B, 0x30, + 0x19, 0x1E, 0x25, 0x30, + 0x19, 0x30, 0x30, 0x30, + 0x19, 0x19, 0x30, 0x30, + 0x19, 0x19, 0x19, 0x30, + 0x19, 0x26, 0x2D, 0x33, + 0x19, 0x1F, 0x2D, 0x33, + 0x19, 0x1F, 0x26, 0x33, + 0x19, 0x33, 0x33, 0x33, + 0x19, 0x19, 0x33, 0x33, + 0x19, 0x19, 0x19, 0x33, + 0x19, 0x27, 0x2F, 0x36, + 0x19, 0x20, 0x2F, 0x36, + 0x19, 0x20, 0x28, 0x36, + 0x19, 0x36, 0x36, 0x36, + 0x19, 0x19, 0x36, 0x36, + 0x19, 0x19, 0x19, 0x36, + 0x19, 0x29, 0x31, 0x39, + 0x19, 0x21, 0x31, 0x39, + 0x19, 0x21, 0x29, 0x39, + 0x19, 0x39, 0x39, 0x39, + 0x19, 0x19, 0x39, 0x39, + 0x19, 0x19, 0x19, 0x39, + 0x19, 0x3C, 0x3C, 0x3C, + 0x19, 0x19, 0x3C, 0x3C, + 0x19, 0x19, 0x19, 0x3C, + 0x19, 0x2B, 0x34, 0x3D, + 0x19, 0x22, 0x34, 0x3D, + 0x19, 0x22, 0x2B, 0x3D, + 0x1A, 0x1B, 0x1B, 0x1C, + 0x1A, 0x1B, 0x1C, 0x1D, + 0x1A, 0x1C, 0x1D, 0x1E, + 0x1A, 0x1B, 0x1D, 0x1E, + 0x1A, 0x1B, 0x1C, 0x1E, + 0x1A, 0x1C, 0x1D, 0x1F, + 0x1A, 0x1C, 0x1E, 0x1F, + 0x1A, 0x1B, 0x1E, 0x1F, + 0x1A, 0x1B, 0x1D, 0x1F, + 0x1A, 0x1C, 0x1E, 0x20, + 0x1A, 0x1D, 0x1F, 0x20, + 0x1A, 0x1B, 0x1F, 0x20, + 0x1A, 0x1B, 0x1D, 0x20, + 0x1A, 0x20, 0x20, 0x20, + 0x1A, 0x1A, 0x20, 0x20, + 0x1A, 0x1A, 0x1A, 0x20, + 0x1A, 0x1D, 0x1E, 0x21, + 0x1A, 0x1D, 0x20, 0x21, + 0x1A, 0x1B, 0x20, 0x21, + 0x1A, 0x1B, 0x1E, 0x21, + 0x1A, 0x1D, 0x1F, 0x22, + 0x1A, 0x1E, 0x20, 0x22, + 0x1A, 0x1C, 0x20, 0x22, + 0x1A, 0x1C, 0x1E, 0x22, + 0x1A, 0x22, 0x22, 0x22, + 0x1A, 0x1A, 0x22, 0x22, + 0x1A, 0x1A, 0x1A, 0x22, + 0x1A, 0x1E, 0x21, 0x25, + 0x1A, 0x1F, 0x23, 0x25, + 0x1A, 0x1C, 0x23, 0x25, + 0x1A, 0x1C, 0x20, 0x25, + 0x1A, 0x25, 0x25, 0x25, + 0x1A, 0x1A, 0x25, 0x25, + 0x1A, 0x1A, 0x1A, 0x25, + 0x1A, 0x1F, 0x23, 0x28, + 0x1A, 0x21, 0x25, 0x28, + 0x1A, 0x1D, 0x25, 0x28, + 0x1A, 0x1D, 0x21, 0x28, + 0x1A, 0x28, 0x28, 0x28, + 0x1A, 0x1A, 0x28, 0x28, + 0x1A, 0x1A, 0x1A, 0x28, + 0x1A, 0x20, 0x25, 0x2B, + 0x1A, 0x22, 0x27, 0x2B, + 0x1A, 0x1E, 0x27, 0x2B, + 0x1A, 0x1E, 0x23, 0x2B, + 0x1A, 0x2B, 0x2B, 0x2B, + 0x1A, 0x1A, 0x2B, 0x2B, + 0x1A, 0x1A, 0x1A, 0x2B, + 0x1A, 0x21, 0x27, 0x2E, + 0x1A, 0x24, 0x29, 0x2E, + 0x1A, 0x1F, 0x29, 0x2E, + 0x1A, 0x1F, 0x24, 0x2E, + 0x1A, 0x2E, 0x2E, 0x2E, + 0x1A, 0x1A, 0x2E, 0x2E, + 0x1A, 0x1A, 0x1A, 0x2E, + 0x1A, 0x25, 0x2C, 0x31, + 0x1A, 0x1F, 0x2C, 0x31, + 0x1A, 0x1F, 0x26, 0x31, + 0x1A, 0x31, 0x31, 0x31, + 0x1A, 0x1A, 0x31, 0x31, + 0x1A, 0x1A, 0x1A, 0x31, + 0x1A, 0x27, 0x2E, 0x34, + 0x1A, 0x20, 0x2E, 0x34, + 0x1A, 0x20, 0x27, 0x34, + 0x1A, 0x34, 0x34, 0x34, + 0x1A, 0x1A, 0x34, 0x34, + 0x1A, 0x1A, 0x1A, 0x34, + 0x1A, 0x28, 0x30, 0x37, + 0x1A, 0x21, 0x30, 0x37, + 0x1A, 0x21, 0x29, 0x37, + 0x1A, 0x37, 0x37, 0x37, + 0x1A, 0x1A, 0x37, 0x37, + 0x1A, 0x1A, 0x1A, 0x37, + 0x1A, 0x2A, 0x32, 0x3A, + 0x1A, 0x22, 0x32, 0x3A, + 0x1A, 0x22, 0x2A, 0x3A, + 0x1A, 0x3A, 0x3A, 0x3A, + 0x1A, 0x1A, 0x3A, 0x3A, + 0x1A, 0x1A, 0x1A, 0x3A, + 0x1A, 0x3D, 0x3D, 0x3D, + 0x1A, 0x1A, 0x3D, 0x3D, + 0x1A, 0x1A, 0x1A, 0x3D, + 0x1A, 0x2C, 0x35, 0x3E, + 0x1A, 0x23, 0x35, 0x3E, + 0x1A, 0x23, 0x2C, 0x3E, + 0x1B, 0x1C, 0x1C, 0x1D, + 0x1B, 0x1C, 0x1D, 0x1E, + 0x1B, 0x1D, 0x1E, 0x1F, + 0x1B, 0x1C, 0x1E, 0x1F, + 0x1B, 0x1C, 0x1D, 0x1F, + 0x1B, 0x1D, 0x1E, 0x20, + 0x1B, 0x1D, 0x1F, 0x20, + 0x1B, 0x1C, 0x1F, 0x20, + 0x1B, 0x1C, 0x1E, 0x20, + 0x1B, 0x1D, 0x1F, 0x21, + 0x1B, 0x1E, 0x20, 0x21, + 0x1B, 0x1C, 0x20, 0x21, + 0x1B, 0x1C, 0x1E, 0x21, + 0x1B, 0x21, 0x21, 0x21, + 0x1B, 0x1B, 0x21, 0x21, + 0x1B, 0x1B, 0x1B, 0x21, + 0x1B, 0x1E, 0x1F, 0x22, + 0x1B, 0x1E, 0x21, 0x22, + 0x1B, 0x1C, 0x21, 0x22, + 0x1B, 0x1C, 0x1F, 0x22, + 0x1B, 0x1E, 0x20, 0x23, + 0x1B, 0x1F, 0x21, 0x23, + 0x1B, 0x1D, 0x21, 0x23, + 0x1B, 0x1D, 0x1F, 0x23, + 0x1B, 0x23, 0x23, 0x23, + 0x1B, 0x1B, 0x23, 0x23, + 0x1B, 0x1B, 0x1B, 0x23, + 0x1B, 0x1F, 0x22, 0x26, + 0x1B, 0x20, 0x24, 0x26, + 0x1B, 0x1D, 0x24, 0x26, + 0x1B, 0x1D, 0x21, 0x26, + 0x1B, 0x26, 0x26, 0x26, + 0x1B, 0x1B, 0x26, 0x26, + 0x1B, 0x1B, 0x1B, 0x26, + 0x1B, 0x20, 0x24, 0x29, + 0x1B, 0x22, 0x26, 0x29, + 0x1B, 0x1E, 0x26, 0x29, + 0x1B, 0x1E, 0x22, 0x29, + 0x1B, 0x29, 0x29, 0x29, + 0x1B, 0x1B, 0x29, 0x29, + 0x1B, 0x1B, 0x1B, 0x29, + 0x1B, 0x21, 0x26, 0x2C, + 0x1B, 0x23, 0x28, 0x2C, + 0x1B, 0x1F, 0x28, 0x2C, + 0x1B, 0x1F, 0x24, 0x2C, + 0x1B, 0x2C, 0x2C, 0x2C, + 0x1B, 0x1B, 0x2C, 0x2C, + 0x1B, 0x1B, 0x1B, 0x2C, + 0x1B, 0x22, 0x28, 0x2F, + 0x1B, 0x25, 0x2A, 0x2F, + 0x1B, 0x20, 0x2A, 0x2F, + 0x1B, 0x20, 0x25, 0x2F, + 0x1B, 0x2F, 0x2F, 0x2F, + 0x1B, 0x1B, 0x2F, 0x2F, + 0x1B, 0x1B, 0x1B, 0x2F, + 0x1B, 0x26, 0x2D, 0x32, + 0x1B, 0x20, 0x2D, 0x32, + 0x1B, 0x20, 0x27, 0x32, + 0x1B, 0x32, 0x32, 0x32, + 0x1B, 0x1B, 0x32, 0x32, + 0x1B, 0x1B, 0x1B, 0x32, + 0x1B, 0x28, 0x2F, 0x35, + 0x1B, 0x21, 0x2F, 0x35, + 0x1B, 0x21, 0x28, 0x35, + 0x1B, 0x35, 0x35, 0x35, + 0x1B, 0x1B, 0x35, 0x35, + 0x1B, 0x1B, 0x1B, 0x35, + 0x1B, 0x29, 0x31, 0x38, + 0x1B, 0x22, 0x31, 0x38, + 0x1B, 0x22, 0x2A, 0x38, + 0x1B, 0x38, 0x38, 0x38, + 0x1B, 0x1B, 0x38, 0x38, + 0x1B, 0x1B, 0x1B, 0x38, + 0x1B, 0x2B, 0x33, 0x3B, + 0x1B, 0x23, 0x33, 0x3B, + 0x1B, 0x23, 0x2B, 0x3B, + 0x1B, 0x3B, 0x3B, 0x3B, + 0x1B, 0x1B, 0x3B, 0x3B, + 0x1B, 0x1B, 0x1B, 0x3B, + 0x1B, 0x3E, 0x3E, 0x3E, + 0x1B, 0x1B, 0x3E, 0x3E, + 0x1B, 0x1B, 0x1B, 0x3E, + 0x1B, 0x2D, 0x36, 0x3F, + 0x1B, 0x24, 0x36, 0x3F, + 0x1B, 0x24, 0x2D, 0x3F, + 0x1C, 0x1D, 0x1D, 0x1E, + 0x1C, 0x1D, 0x1E, 0x1F, + 0x1C, 0x1E, 0x1F, 0x20, + 0x1C, 0x1D, 0x1F, 0x20, + 0x1C, 0x1D, 0x1E, 0x20, + 0x1C, 0x1E, 0x1F, 0x21, + 0x1C, 0x1E, 0x20, 0x21, + 0x1C, 0x1D, 0x20, 0x21, + 0x1C, 0x1D, 0x1F, 0x21, + 0x1C, 0x1E, 0x20, 0x22, + 0x1C, 0x1F, 0x21, 0x22, + 0x1C, 0x1D, 0x21, 0x22, + 0x1C, 0x1D, 0x1F, 0x22, + 0x1C, 0x22, 0x22, 0x22, + 0x1C, 0x1C, 0x22, 0x22, + 0x1C, 0x1C, 0x1C, 0x22, + 0x1C, 0x1F, 0x20, 0x23, + 0x1C, 0x1F, 0x22, 0x23, + 0x1C, 0x1D, 0x22, 0x23, + 0x1C, 0x1D, 0x20, 0x23, + 0x1C, 0x1F, 0x21, 0x24, + 0x1C, 0x20, 0x22, 0x24, + 0x1C, 0x1E, 0x22, 0x24, + 0x1C, 0x1E, 0x20, 0x24, + 0x1C, 0x24, 0x24, 0x24, + 0x1C, 0x1C, 0x24, 0x24, + 0x1C, 0x1C, 0x1C, 0x24, + 0x1C, 0x20, 0x23, 0x27, + 0x1C, 0x21, 0x25, 0x27, + 0x1C, 0x1E, 0x25, 0x27, + 0x1C, 0x1E, 0x22, 0x27, + 0x1C, 0x27, 0x27, 0x27, + 0x1C, 0x1C, 0x27, 0x27, + 0x1C, 0x1C, 0x1C, 0x27, + 0x1C, 0x21, 0x25, 0x2A, + 0x1C, 0x23, 0x27, 0x2A, + 0x1C, 0x1F, 0x27, 0x2A, + 0x1C, 0x1F, 0x23, 0x2A, + 0x1C, 0x2A, 0x2A, 0x2A, + 0x1C, 0x1C, 0x2A, 0x2A, + 0x1C, 0x1C, 0x1C, 0x2A, + 0x1C, 0x22, 0x27, 0x2D, + 0x1C, 0x24, 0x29, 0x2D, + 0x1C, 0x20, 0x29, 0x2D, + 0x1C, 0x20, 0x25, 0x2D, + 0x1C, 0x2D, 0x2D, 0x2D, + 0x1C, 0x1C, 0x2D, 0x2D, + 0x1C, 0x1C, 0x1C, 0x2D, + 0x1C, 0x23, 0x29, 0x30, + 0x1C, 0x26, 0x2B, 0x30, + 0x1C, 0x21, 0x2B, 0x30, + 0x1C, 0x21, 0x26, 0x30, + 0x1C, 0x30, 0x30, 0x30, + 0x1C, 0x1C, 0x30, 0x30, + 0x1C, 0x1C, 0x1C, 0x30, + 0x1C, 0x27, 0x2E, 0x33, + 0x1C, 0x21, 0x2E, 0x33, + 0x1C, 0x21, 0x28, 0x33, + 0x1C, 0x33, 0x33, 0x33, + 0x1C, 0x1C, 0x33, 0x33, + 0x1C, 0x1C, 0x1C, 0x33, + 0x1C, 0x29, 0x30, 0x36, + 0x1C, 0x22, 0x30, 0x36, + 0x1C, 0x22, 0x29, 0x36, + 0x1C, 0x36, 0x36, 0x36, + 0x1C, 0x1C, 0x36, 0x36, + 0x1C, 0x1C, 0x1C, 0x36, + 0x1C, 0x2A, 0x32, 0x39, + 0x1C, 0x23, 0x32, 0x39, + 0x1C, 0x23, 0x2B, 0x39, + 0x1C, 0x39, 0x39, 0x39, + 0x1C, 0x1C, 0x39, 0x39, + 0x1C, 0x1C, 0x1C, 0x39, + 0x1C, 0x2C, 0x34, 0x3C, + 0x1C, 0x24, 0x34, 0x3C, + 0x1C, 0x24, 0x2C, 0x3C, + 0x1C, 0x3C, 0x3C, 0x3C, + 0x1C, 0x1C, 0x3C, 0x3C, + 0x1C, 0x1C, 0x1C, 0x3C, + 0x1C, 0x3F, 0x3F, 0x3F, + 0x1C, 0x1C, 0x3F, 0x3F, + 0x1C, 0x1C, 0x1C, 0x3F, + 0x1D, 0x1E, 0x1E, 0x1F, + 0x1D, 0x1E, 0x1F, 0x20, + 0x1D, 0x1F, 0x20, 0x21, + 0x1D, 0x1E, 0x20, 0x21, + 0x1D, 0x1E, 0x1F, 0x21, + 0x1D, 0x1F, 0x20, 0x22, + 0x1D, 0x1F, 0x21, 0x22, + 0x1D, 0x1E, 0x21, 0x22, + 0x1D, 0x1E, 0x20, 0x22, + 0x1D, 0x1F, 0x21, 0x23, + 0x1D, 0x20, 0x22, 0x23, + 0x1D, 0x1E, 0x22, 0x23, + 0x1D, 0x1E, 0x20, 0x23, + 0x1D, 0x23, 0x23, 0x23, + 0x1D, 0x1D, 0x23, 0x23, + 0x1D, 0x1D, 0x1D, 0x23, + 0x1D, 0x20, 0x21, 0x24, + 0x1D, 0x20, 0x23, 0x24, + 0x1D, 0x1E, 0x23, 0x24, + 0x1D, 0x1E, 0x21, 0x24, + 0x1D, 0x20, 0x22, 0x25, + 0x1D, 0x21, 0x23, 0x25, + 0x1D, 0x1F, 0x23, 0x25, + 0x1D, 0x1F, 0x21, 0x25, + 0x1D, 0x25, 0x25, 0x25, + 0x1D, 0x1D, 0x25, 0x25, + 0x1D, 0x1D, 0x1D, 0x25, + 0x1D, 0x21, 0x24, 0x28, + 0x1D, 0x22, 0x26, 0x28, + 0x1D, 0x1F, 0x26, 0x28, + 0x1D, 0x1F, 0x23, 0x28, + 0x1D, 0x28, 0x28, 0x28, + 0x1D, 0x1D, 0x28, 0x28, + 0x1D, 0x1D, 0x1D, 0x28, + 0x1D, 0x22, 0x26, 0x2B, + 0x1D, 0x24, 0x28, 0x2B, + 0x1D, 0x20, 0x28, 0x2B, + 0x1D, 0x20, 0x24, 0x2B, + 0x1D, 0x2B, 0x2B, 0x2B, + 0x1D, 0x1D, 0x2B, 0x2B, + 0x1D, 0x1D, 0x1D, 0x2B, + 0x1D, 0x23, 0x28, 0x2E, + 0x1D, 0x25, 0x2A, 0x2E, + 0x1D, 0x21, 0x2A, 0x2E, + 0x1D, 0x21, 0x26, 0x2E, + 0x1D, 0x2E, 0x2E, 0x2E, + 0x1D, 0x1D, 0x2E, 0x2E, + 0x1D, 0x1D, 0x1D, 0x2E, + 0x1D, 0x24, 0x2A, 0x31, + 0x1D, 0x27, 0x2C, 0x31, + 0x1D, 0x22, 0x2C, 0x31, + 0x1D, 0x22, 0x27, 0x31, + 0x1D, 0x31, 0x31, 0x31, + 0x1D, 0x1D, 0x31, 0x31, + 0x1D, 0x1D, 0x1D, 0x31, + 0x1D, 0x28, 0x2F, 0x34, + 0x1D, 0x22, 0x2F, 0x34, + 0x1D, 0x22, 0x29, 0x34, + 0x1D, 0x34, 0x34, 0x34, + 0x1D, 0x1D, 0x34, 0x34, + 0x1D, 0x1D, 0x1D, 0x34, + 0x1D, 0x2A, 0x31, 0x37, + 0x1D, 0x23, 0x31, 0x37, + 0x1D, 0x23, 0x2A, 0x37, + 0x1D, 0x37, 0x37, 0x37, + 0x1D, 0x1D, 0x37, 0x37, + 0x1D, 0x1D, 0x1D, 0x37, + 0x1D, 0x2B, 0x33, 0x3A, + 0x1D, 0x24, 0x33, 0x3A, + 0x1D, 0x24, 0x2C, 0x3A, + 0x1D, 0x3A, 0x3A, 0x3A, + 0x1D, 0x1D, 0x3A, 0x3A, + 0x1D, 0x1D, 0x1D, 0x3A, + 0x1D, 0x2D, 0x35, 0x3D, + 0x1D, 0x25, 0x35, 0x3D, + 0x1D, 0x25, 0x2D, 0x3D, + 0x1D, 0x3D, 0x3D, 0x3D, + 0x1D, 0x1D, 0x3D, 0x3D, + 0x1D, 0x1D, 0x1D, 0x3D, + 0x1E, 0x1F, 0x1F, 0x20, + 0x1E, 0x1F, 0x20, 0x21, + 0x1E, 0x20, 0x21, 0x22, + 0x1E, 0x1F, 0x21, 0x22, + 0x1E, 0x1F, 0x20, 0x22, + 0x1E, 0x20, 0x21, 0x23, + 0x1E, 0x20, 0x22, 0x23, + 0x1E, 0x1F, 0x22, 0x23, + 0x1E, 0x1F, 0x21, 0x23, + 0x1E, 0x20, 0x22, 0x24, + 0x1E, 0x21, 0x23, 0x24, + 0x1E, 0x1F, 0x23, 0x24, + 0x1E, 0x1F, 0x21, 0x24, + 0x1E, 0x24, 0x24, 0x24, + 0x1E, 0x1E, 0x24, 0x24, + 0x1E, 0x1E, 0x1E, 0x24, + 0x1E, 0x21, 0x22, 0x25, + 0x1E, 0x21, 0x24, 0x25, + 0x1E, 0x1F, 0x24, 0x25, + 0x1E, 0x1F, 0x22, 0x25, + 0x1E, 0x21, 0x23, 0x26, + 0x1E, 0x22, 0x24, 0x26, + 0x1E, 0x20, 0x24, 0x26, + 0x1E, 0x20, 0x22, 0x26, + 0x1E, 0x26, 0x26, 0x26, + 0x1E, 0x1E, 0x26, 0x26, + 0x1E, 0x1E, 0x1E, 0x26, + 0x1E, 0x22, 0x25, 0x29, + 0x1E, 0x23, 0x27, 0x29, + 0x1E, 0x20, 0x27, 0x29, + 0x1E, 0x20, 0x24, 0x29, + 0x1E, 0x29, 0x29, 0x29, + 0x1E, 0x1E, 0x29, 0x29, + 0x1E, 0x1E, 0x1E, 0x29, + 0x1E, 0x23, 0x27, 0x2C, + 0x1E, 0x25, 0x29, 0x2C, + 0x1E, 0x21, 0x29, 0x2C, + 0x1E, 0x21, 0x25, 0x2C, + 0x1E, 0x2C, 0x2C, 0x2C, + 0x1E, 0x1E, 0x2C, 0x2C, + 0x1E, 0x1E, 0x1E, 0x2C, + 0x1E, 0x24, 0x29, 0x2F, + 0x1E, 0x26, 0x2B, 0x2F, + 0x1E, 0x22, 0x2B, 0x2F, + 0x1E, 0x22, 0x27, 0x2F, + 0x1E, 0x2F, 0x2F, 0x2F, + 0x1E, 0x1E, 0x2F, 0x2F, + 0x1E, 0x1E, 0x1E, 0x2F, + 0x1E, 0x25, 0x2B, 0x32, + 0x1E, 0x28, 0x2D, 0x32, + 0x1E, 0x23, 0x2D, 0x32, + 0x1E, 0x23, 0x28, 0x32, + 0x1E, 0x32, 0x32, 0x32, + 0x1E, 0x1E, 0x32, 0x32, + 0x1E, 0x1E, 0x1E, 0x32, + 0x1E, 0x29, 0x30, 0x35, + 0x1E, 0x23, 0x30, 0x35, + 0x1E, 0x23, 0x2A, 0x35, + 0x1E, 0x35, 0x35, 0x35, + 0x1E, 0x1E, 0x35, 0x35, + 0x1E, 0x1E, 0x1E, 0x35, + 0x1E, 0x2B, 0x32, 0x38, + 0x1E, 0x24, 0x32, 0x38, + 0x1E, 0x24, 0x2B, 0x38, + 0x1E, 0x38, 0x38, 0x38, + 0x1E, 0x1E, 0x38, 0x38, + 0x1E, 0x1E, 0x1E, 0x38, + 0x1E, 0x2C, 0x34, 0x3B, + 0x1E, 0x25, 0x34, 0x3B, + 0x1E, 0x25, 0x2D, 0x3B, + 0x1E, 0x3B, 0x3B, 0x3B, + 0x1E, 0x1E, 0x3B, 0x3B, + 0x1E, 0x1E, 0x1E, 0x3B, + 0x1E, 0x2E, 0x36, 0x3E, + 0x1E, 0x26, 0x36, 0x3E, + 0x1E, 0x26, 0x2E, 0x3E, + 0x1E, 0x3E, 0x3E, 0x3E, + 0x1E, 0x1E, 0x3E, 0x3E, + 0x1E, 0x1E, 0x1E, 0x3E, + 0x1F, 0x20, 0x20, 0x21, + 0x1F, 0x20, 0x21, 0x22, + 0x1F, 0x21, 0x22, 0x23, + 0x1F, 0x20, 0x22, 0x23, + 0x1F, 0x20, 0x21, 0x23, + 0x1F, 0x21, 0x22, 0x24, + 0x1F, 0x21, 0x23, 0x24, + 0x1F, 0x20, 0x23, 0x24, + 0x1F, 0x20, 0x22, 0x24, + 0x1F, 0x21, 0x23, 0x25, + 0x1F, 0x22, 0x24, 0x25, + 0x1F, 0x20, 0x24, 0x25, + 0x1F, 0x20, 0x22, 0x25, + 0x1F, 0x25, 0x25, 0x25, + 0x1F, 0x1F, 0x25, 0x25, + 0x1F, 0x1F, 0x1F, 0x25, + 0x1F, 0x22, 0x23, 0x26, + 0x1F, 0x22, 0x25, 0x26, + 0x1F, 0x20, 0x25, 0x26, + 0x1F, 0x20, 0x23, 0x26, + 0x1F, 0x22, 0x24, 0x27, + 0x1F, 0x23, 0x25, 0x27, + 0x1F, 0x21, 0x25, 0x27, + 0x1F, 0x21, 0x23, 0x27, + 0x1F, 0x27, 0x27, 0x27, + 0x1F, 0x1F, 0x27, 0x27, + 0x1F, 0x1F, 0x1F, 0x27, + 0x1F, 0x23, 0x26, 0x2A, + 0x1F, 0x24, 0x28, 0x2A, + 0x1F, 0x21, 0x28, 0x2A, + 0x1F, 0x21, 0x25, 0x2A, + 0x1F, 0x2A, 0x2A, 0x2A, + 0x1F, 0x1F, 0x2A, 0x2A, + 0x1F, 0x1F, 0x1F, 0x2A, + 0x1F, 0x24, 0x28, 0x2D, + 0x1F, 0x26, 0x2A, 0x2D, + 0x1F, 0x22, 0x2A, 0x2D, + 0x1F, 0x22, 0x26, 0x2D, + 0x1F, 0x2D, 0x2D, 0x2D, + 0x1F, 0x1F, 0x2D, 0x2D, + 0x1F, 0x1F, 0x1F, 0x2D, + 0x1F, 0x25, 0x2A, 0x30, + 0x1F, 0x27, 0x2C, 0x30, + 0x1F, 0x23, 0x2C, 0x30, + 0x1F, 0x23, 0x28, 0x30, + 0x1F, 0x30, 0x30, 0x30, + 0x1F, 0x1F, 0x30, 0x30, + 0x1F, 0x1F, 0x1F, 0x30, + 0x1F, 0x26, 0x2C, 0x33, + 0x1F, 0x29, 0x2E, 0x33, + 0x1F, 0x24, 0x2E, 0x33, + 0x1F, 0x24, 0x29, 0x33, + 0x1F, 0x33, 0x33, 0x33, + 0x1F, 0x1F, 0x33, 0x33, + 0x1F, 0x1F, 0x1F, 0x33, + 0x1F, 0x2A, 0x31, 0x36, + 0x1F, 0x24, 0x31, 0x36, + 0x1F, 0x24, 0x2B, 0x36, + 0x1F, 0x36, 0x36, 0x36, + 0x1F, 0x1F, 0x36, 0x36, + 0x1F, 0x1F, 0x1F, 0x36, + 0x1F, 0x2C, 0x33, 0x39, + 0x1F, 0x25, 0x33, 0x39, + 0x1F, 0x25, 0x2C, 0x39, + 0x1F, 0x39, 0x39, 0x39, + 0x1F, 0x1F, 0x39, 0x39, + 0x1F, 0x1F, 0x1F, 0x39, + 0x1F, 0x2D, 0x35, 0x3C, + 0x1F, 0x26, 0x35, 0x3C, + 0x1F, 0x26, 0x2E, 0x3C, + 0x1F, 0x3C, 0x3C, 0x3C, + 0x1F, 0x1F, 0x3C, 0x3C, + 0x1F, 0x1F, 0x1F, 0x3C, + 0x1F, 0x2F, 0x37, 0x3F, + 0x1F, 0x27, 0x37, 0x3F, + 0x1F, 0x27, 0x2F, 0x3F, + 0x1F, 0x3F, 0x3F, 0x3F, + 0x1F, 0x1F, 0x3F, 0x3F, + 0x1F, 0x1F, 0x1F, 0x3F, + 0x20, 0x21, 0x21, 0x22, + 0x20, 0x21, 0x22, 0x23, + 0x20, 0x22, 0x23, 0x24, + 0x20, 0x21, 0x23, 0x24, + 0x20, 0x21, 0x22, 0x24, + 0x20, 0x22, 0x23, 0x25, + 0x20, 0x22, 0x24, 0x25, + 0x20, 0x21, 0x24, 0x25, + 0x20, 0x21, 0x23, 0x25, + 0x20, 0x22, 0x24, 0x26, + 0x20, 0x23, 0x25, 0x26, + 0x20, 0x21, 0x25, 0x26, + 0x20, 0x21, 0x23, 0x26, + 0x20, 0x26, 0x26, 0x26, + 0x20, 0x20, 0x26, 0x26, + 0x20, 0x20, 0x20, 0x26, + 0x20, 0x23, 0x24, 0x27, + 0x20, 0x23, 0x26, 0x27, + 0x20, 0x21, 0x26, 0x27, + 0x20, 0x21, 0x24, 0x27, + 0x20, 0x23, 0x25, 0x28, + 0x20, 0x24, 0x26, 0x28, + 0x20, 0x22, 0x26, 0x28, + 0x20, 0x22, 0x24, 0x28, + 0x20, 0x28, 0x28, 0x28, + 0x20, 0x20, 0x28, 0x28, + 0x20, 0x20, 0x20, 0x28, + 0x20, 0x24, 0x27, 0x2B, + 0x20, 0x25, 0x29, 0x2B, + 0x20, 0x22, 0x29, 0x2B, + 0x20, 0x22, 0x26, 0x2B, + 0x20, 0x2B, 0x2B, 0x2B, + 0x20, 0x20, 0x2B, 0x2B, + 0x20, 0x20, 0x20, 0x2B, + 0x20, 0x25, 0x29, 0x2E, + 0x20, 0x27, 0x2B, 0x2E, + 0x20, 0x23, 0x2B, 0x2E, + 0x20, 0x23, 0x27, 0x2E, + 0x20, 0x2E, 0x2E, 0x2E, + 0x20, 0x20, 0x2E, 0x2E, + 0x20, 0x20, 0x20, 0x2E, + 0x20, 0x26, 0x2B, 0x31, + 0x20, 0x28, 0x2D, 0x31, + 0x20, 0x24, 0x2D, 0x31, + 0x20, 0x24, 0x29, 0x31, + 0x20, 0x31, 0x31, 0x31, + 0x20, 0x20, 0x31, 0x31, + 0x20, 0x20, 0x20, 0x31, + 0x20, 0x27, 0x2D, 0x34, + 0x20, 0x2A, 0x2F, 0x34, + 0x20, 0x25, 0x2F, 0x34, + 0x20, 0x25, 0x2A, 0x34, + 0x20, 0x34, 0x34, 0x34, + 0x20, 0x20, 0x34, 0x34, + 0x20, 0x20, 0x20, 0x34, + 0x20, 0x2B, 0x32, 0x37, + 0x20, 0x25, 0x32, 0x37, + 0x20, 0x25, 0x2C, 0x37, + 0x20, 0x37, 0x37, 0x37, + 0x20, 0x20, 0x37, 0x37, + 0x20, 0x20, 0x20, 0x37, + 0x20, 0x2D, 0x34, 0x3A, + 0x20, 0x26, 0x34, 0x3A, + 0x20, 0x26, 0x2D, 0x3A, + 0x20, 0x3A, 0x3A, 0x3A, + 0x20, 0x20, 0x3A, 0x3A, + 0x20, 0x20, 0x20, 0x3A, + 0x20, 0x2E, 0x36, 0x3D, + 0x20, 0x27, 0x36, 0x3D, + 0x20, 0x27, 0x2F, 0x3D, + 0x20, 0x3D, 0x3D, 0x3D, + 0x20, 0x20, 0x3D, 0x3D, + 0x20, 0x20, 0x20, 0x3D, + 0x21, 0x22, 0x22, 0x23, + 0x21, 0x22, 0x23, 0x24, + 0x21, 0x23, 0x24, 0x25, + 0x21, 0x22, 0x24, 0x25, + 0x21, 0x22, 0x23, 0x25, + 0x21, 0x23, 0x24, 0x26, + 0x21, 0x23, 0x25, 0x26, + 0x21, 0x22, 0x25, 0x26, + 0x21, 0x22, 0x24, 0x26, + 0x21, 0x23, 0x25, 0x27, + 0x21, 0x24, 0x26, 0x27, + 0x21, 0x22, 0x26, 0x27, + 0x21, 0x22, 0x24, 0x27, + 0x21, 0x27, 0x27, 0x27, + 0x21, 0x21, 0x27, 0x27, + 0x21, 0x21, 0x21, 0x27, + 0x21, 0x24, 0x25, 0x28, + 0x21, 0x24, 0x27, 0x28, + 0x21, 0x22, 0x27, 0x28, + 0x21, 0x22, 0x25, 0x28, + 0x21, 0x24, 0x26, 0x29, + 0x21, 0x25, 0x27, 0x29, + 0x21, 0x23, 0x27, 0x29, + 0x21, 0x23, 0x25, 0x29, + 0x21, 0x29, 0x29, 0x29, + 0x21, 0x21, 0x29, 0x29, + 0x21, 0x21, 0x21, 0x29, + 0x21, 0x25, 0x28, 0x2C, + 0x21, 0x26, 0x2A, 0x2C, + 0x21, 0x23, 0x2A, 0x2C, + 0x21, 0x23, 0x27, 0x2C, + 0x21, 0x2C, 0x2C, 0x2C, + 0x21, 0x21, 0x2C, 0x2C, + 0x21, 0x21, 0x21, 0x2C, + 0x21, 0x26, 0x2A, 0x2F, + 0x21, 0x28, 0x2C, 0x2F, + 0x21, 0x24, 0x2C, 0x2F, + 0x21, 0x24, 0x28, 0x2F, + 0x21, 0x2F, 0x2F, 0x2F, + 0x21, 0x21, 0x2F, 0x2F, + 0x21, 0x21, 0x21, 0x2F, + 0x21, 0x27, 0x2C, 0x32, + 0x21, 0x29, 0x2E, 0x32, + 0x21, 0x25, 0x2E, 0x32, + 0x21, 0x25, 0x2A, 0x32, + 0x21, 0x32, 0x32, 0x32, + 0x21, 0x21, 0x32, 0x32, + 0x21, 0x21, 0x21, 0x32, + 0x21, 0x28, 0x2E, 0x35, + 0x21, 0x2B, 0x30, 0x35, + 0x21, 0x26, 0x30, 0x35, + 0x21, 0x26, 0x2B, 0x35, + 0x21, 0x35, 0x35, 0x35, + 0x21, 0x21, 0x35, 0x35, + 0x21, 0x21, 0x21, 0x35, + 0x21, 0x2C, 0x33, 0x38, + 0x21, 0x26, 0x33, 0x38, + 0x21, 0x26, 0x2D, 0x38, + 0x21, 0x38, 0x38, 0x38, + 0x21, 0x21, 0x38, 0x38, + 0x21, 0x21, 0x21, 0x38, + 0x21, 0x2E, 0x35, 0x3B, + 0x21, 0x27, 0x35, 0x3B, + 0x21, 0x27, 0x2E, 0x3B, + 0x21, 0x3B, 0x3B, 0x3B, + 0x21, 0x21, 0x3B, 0x3B, + 0x21, 0x21, 0x21, 0x3B, + 0x21, 0x2F, 0x37, 0x3E, + 0x21, 0x28, 0x37, 0x3E, + 0x21, 0x28, 0x30, 0x3E, + 0x21, 0x3E, 0x3E, 0x3E, + 0x21, 0x21, 0x3E, 0x3E, + 0x21, 0x21, 0x21, 0x3E, + 0x22, 0x23, 0x23, 0x24, + 0x22, 0x23, 0x24, 0x25, + 0x22, 0x24, 0x25, 0x26, + 0x22, 0x23, 0x25, 0x26, + 0x22, 0x23, 0x24, 0x26, + 0x22, 0x24, 0x25, 0x27, + 0x22, 0x24, 0x26, 0x27, + 0x22, 0x23, 0x26, 0x27, + 0x22, 0x23, 0x25, 0x27, + 0x22, 0x24, 0x26, 0x28, + 0x22, 0x25, 0x27, 0x28, + 0x22, 0x23, 0x27, 0x28, + 0x22, 0x23, 0x25, 0x28, + 0x22, 0x28, 0x28, 0x28, + 0x22, 0x22, 0x28, 0x28, + 0x22, 0x22, 0x22, 0x28, + 0x22, 0x25, 0x26, 0x29, + 0x22, 0x25, 0x28, 0x29, + 0x22, 0x23, 0x28, 0x29, + 0x22, 0x23, 0x26, 0x29, + 0x22, 0x25, 0x27, 0x2A, + 0x22, 0x26, 0x28, 0x2A, + 0x22, 0x24, 0x28, 0x2A, + 0x22, 0x24, 0x26, 0x2A, + 0x22, 0x2A, 0x2A, 0x2A, + 0x22, 0x22, 0x2A, 0x2A, + 0x22, 0x22, 0x22, 0x2A, + 0x22, 0x26, 0x29, 0x2D, + 0x22, 0x27, 0x2B, 0x2D, + 0x22, 0x24, 0x2B, 0x2D, + 0x22, 0x24, 0x28, 0x2D, + 0x22, 0x2D, 0x2D, 0x2D, + 0x22, 0x22, 0x2D, 0x2D, + 0x22, 0x22, 0x22, 0x2D, + 0x22, 0x27, 0x2B, 0x30, + 0x22, 0x29, 0x2D, 0x30, + 0x22, 0x25, 0x2D, 0x30, + 0x22, 0x25, 0x29, 0x30, + 0x22, 0x30, 0x30, 0x30, + 0x22, 0x22, 0x30, 0x30, + 0x22, 0x22, 0x22, 0x30, + 0x22, 0x28, 0x2D, 0x33, + 0x22, 0x2A, 0x2F, 0x33, + 0x22, 0x26, 0x2F, 0x33, + 0x22, 0x26, 0x2B, 0x33, + 0x22, 0x33, 0x33, 0x33, + 0x22, 0x22, 0x33, 0x33, + 0x22, 0x22, 0x22, 0x33, + 0x22, 0x29, 0x2F, 0x36, + 0x22, 0x2C, 0x31, 0x36, + 0x22, 0x27, 0x31, 0x36, + 0x22, 0x27, 0x2C, 0x36, + 0x22, 0x36, 0x36, 0x36, + 0x22, 0x22, 0x36, 0x36, + 0x22, 0x22, 0x22, 0x36, + 0x22, 0x2D, 0x34, 0x39, + 0x22, 0x27, 0x34, 0x39, + 0x22, 0x27, 0x2E, 0x39, + 0x22, 0x39, 0x39, 0x39, + 0x22, 0x22, 0x39, 0x39, + 0x22, 0x22, 0x22, 0x39, + 0x22, 0x2F, 0x36, 0x3C, + 0x22, 0x28, 0x36, 0x3C, + 0x22, 0x28, 0x2F, 0x3C, + 0x22, 0x3C, 0x3C, 0x3C, + 0x22, 0x22, 0x3C, 0x3C, + 0x22, 0x22, 0x22, 0x3C, + 0x22, 0x30, 0x38, 0x3F, + 0x22, 0x29, 0x38, 0x3F, + 0x22, 0x29, 0x31, 0x3F, + 0x22, 0x3F, 0x3F, 0x3F, + 0x22, 0x22, 0x3F, 0x3F, + 0x22, 0x22, 0x22, 0x3F, + 0x23, 0x24, 0x24, 0x25, + 0x23, 0x24, 0x25, 0x26, + 0x23, 0x25, 0x26, 0x27, + 0x23, 0x24, 0x26, 0x27, + 0x23, 0x24, 0x25, 0x27, + 0x23, 0x25, 0x26, 0x28, + 0x23, 0x25, 0x27, 0x28, + 0x23, 0x24, 0x27, 0x28, + 0x23, 0x24, 0x26, 0x28, + 0x23, 0x25, 0x27, 0x29, + 0x23, 0x26, 0x28, 0x29, + 0x23, 0x24, 0x28, 0x29, + 0x23, 0x24, 0x26, 0x29, + 0x23, 0x29, 0x29, 0x29, + 0x23, 0x23, 0x29, 0x29, + 0x23, 0x23, 0x23, 0x29, + 0x23, 0x26, 0x27, 0x2A, + 0x23, 0x26, 0x29, 0x2A, + 0x23, 0x24, 0x29, 0x2A, + 0x23, 0x24, 0x27, 0x2A, + 0x23, 0x26, 0x28, 0x2B, + 0x23, 0x27, 0x29, 0x2B, + 0x23, 0x25, 0x29, 0x2B, + 0x23, 0x25, 0x27, 0x2B, + 0x23, 0x2B, 0x2B, 0x2B, + 0x23, 0x23, 0x2B, 0x2B, + 0x23, 0x23, 0x23, 0x2B, + 0x23, 0x27, 0x2A, 0x2E, + 0x23, 0x28, 0x2C, 0x2E, + 0x23, 0x25, 0x2C, 0x2E, + 0x23, 0x25, 0x29, 0x2E, + 0x23, 0x2E, 0x2E, 0x2E, + 0x23, 0x23, 0x2E, 0x2E, + 0x23, 0x23, 0x23, 0x2E, + 0x23, 0x28, 0x2C, 0x31, + 0x23, 0x2A, 0x2E, 0x31, + 0x23, 0x26, 0x2E, 0x31, + 0x23, 0x26, 0x2A, 0x31, + 0x23, 0x31, 0x31, 0x31, + 0x23, 0x23, 0x31, 0x31, + 0x23, 0x23, 0x23, 0x31, + 0x23, 0x29, 0x2E, 0x34, + 0x23, 0x2B, 0x30, 0x34, + 0x23, 0x27, 0x30, 0x34, + 0x23, 0x27, 0x2C, 0x34, + 0x23, 0x34, 0x34, 0x34, + 0x23, 0x23, 0x34, 0x34, + 0x23, 0x23, 0x23, 0x34, + 0x23, 0x2A, 0x30, 0x37, + 0x23, 0x2D, 0x32, 0x37, + 0x23, 0x28, 0x32, 0x37, + 0x23, 0x28, 0x2D, 0x37, + 0x23, 0x37, 0x37, 0x37, + 0x23, 0x23, 0x37, 0x37, + 0x23, 0x23, 0x23, 0x37, + 0x23, 0x2E, 0x35, 0x3A, + 0x23, 0x28, 0x35, 0x3A, + 0x23, 0x28, 0x2F, 0x3A, + 0x23, 0x3A, 0x3A, 0x3A, + 0x23, 0x23, 0x3A, 0x3A, + 0x23, 0x23, 0x23, 0x3A, + 0x23, 0x30, 0x37, 0x3D, + 0x23, 0x29, 0x37, 0x3D, + 0x23, 0x29, 0x30, 0x3D, + 0x23, 0x3D, 0x3D, 0x3D, + 0x23, 0x23, 0x3D, 0x3D, + 0x23, 0x23, 0x23, 0x3D, + 0x24, 0x25, 0x25, 0x26, + 0x24, 0x25, 0x26, 0x27, + 0x24, 0x26, 0x27, 0x28, + 0x24, 0x25, 0x27, 0x28, + 0x24, 0x25, 0x26, 0x28, + 0x24, 0x26, 0x27, 0x29, + 0x24, 0x26, 0x28, 0x29, + 0x24, 0x25, 0x28, 0x29, + 0x24, 0x25, 0x27, 0x29, + 0x24, 0x26, 0x28, 0x2A, + 0x24, 0x27, 0x29, 0x2A, + 0x24, 0x25, 0x29, 0x2A, + 0x24, 0x25, 0x27, 0x2A, + 0x24, 0x2A, 0x2A, 0x2A, + 0x24, 0x24, 0x2A, 0x2A, + 0x24, 0x24, 0x24, 0x2A, + 0x24, 0x27, 0x28, 0x2B, + 0x24, 0x27, 0x2A, 0x2B, + 0x24, 0x25, 0x2A, 0x2B, + 0x24, 0x25, 0x28, 0x2B, + 0x24, 0x27, 0x29, 0x2C, + 0x24, 0x28, 0x2A, 0x2C, + 0x24, 0x26, 0x2A, 0x2C, + 0x24, 0x26, 0x28, 0x2C, + 0x24, 0x2C, 0x2C, 0x2C, + 0x24, 0x24, 0x2C, 0x2C, + 0x24, 0x24, 0x24, 0x2C, + 0x24, 0x28, 0x2B, 0x2F, + 0x24, 0x29, 0x2D, 0x2F, + 0x24, 0x26, 0x2D, 0x2F, + 0x24, 0x26, 0x2A, 0x2F, + 0x24, 0x2F, 0x2F, 0x2F, + 0x24, 0x24, 0x2F, 0x2F, + 0x24, 0x24, 0x24, 0x2F, + 0x24, 0x29, 0x2D, 0x32, + 0x24, 0x2B, 0x2F, 0x32, + 0x24, 0x27, 0x2F, 0x32, + 0x24, 0x27, 0x2B, 0x32, + 0x24, 0x32, 0x32, 0x32, + 0x24, 0x24, 0x32, 0x32, + 0x24, 0x24, 0x24, 0x32, + 0x24, 0x2A, 0x2F, 0x35, + 0x24, 0x2C, 0x31, 0x35, + 0x24, 0x28, 0x31, 0x35, + 0x24, 0x28, 0x2D, 0x35, + 0x24, 0x35, 0x35, 0x35, + 0x24, 0x24, 0x35, 0x35, + 0x24, 0x24, 0x24, 0x35, + 0x24, 0x2B, 0x31, 0x38, + 0x24, 0x2E, 0x33, 0x38, + 0x24, 0x29, 0x33, 0x38, + 0x24, 0x29, 0x2E, 0x38, + 0x24, 0x38, 0x38, 0x38, + 0x24, 0x24, 0x38, 0x38, + 0x24, 0x24, 0x24, 0x38, + 0x24, 0x2F, 0x36, 0x3B, + 0x24, 0x29, 0x36, 0x3B, + 0x24, 0x29, 0x30, 0x3B, + 0x24, 0x3B, 0x3B, 0x3B, + 0x24, 0x24, 0x3B, 0x3B, + 0x24, 0x24, 0x24, 0x3B, + 0x24, 0x31, 0x38, 0x3E, + 0x24, 0x2A, 0x38, 0x3E, + 0x24, 0x2A, 0x31, 0x3E, + 0x24, 0x3E, 0x3E, 0x3E, + 0x24, 0x24, 0x3E, 0x3E, + 0x24, 0x24, 0x24, 0x3E, + 0x25, 0x26, 0x26, 0x27, + 0x25, 0x26, 0x27, 0x28, + 0x25, 0x27, 0x28, 0x29, + 0x25, 0x26, 0x28, 0x29, + 0x25, 0x26, 0x27, 0x29, + 0x25, 0x27, 0x28, 0x2A, + 0x25, 0x27, 0x29, 0x2A, + 0x25, 0x26, 0x29, 0x2A, + 0x25, 0x26, 0x28, 0x2A, + 0x25, 0x27, 0x29, 0x2B, + 0x25, 0x28, 0x2A, 0x2B, + 0x25, 0x26, 0x2A, 0x2B, + 0x25, 0x26, 0x28, 0x2B, + 0x25, 0x2B, 0x2B, 0x2B, + 0x25, 0x25, 0x2B, 0x2B, + 0x25, 0x25, 0x25, 0x2B, + 0x25, 0x28, 0x29, 0x2C, + 0x25, 0x28, 0x2B, 0x2C, + 0x25, 0x26, 0x2B, 0x2C, + 0x25, 0x26, 0x29, 0x2C, + 0x25, 0x28, 0x2A, 0x2D, + 0x25, 0x29, 0x2B, 0x2D, + 0x25, 0x27, 0x2B, 0x2D, + 0x25, 0x27, 0x29, 0x2D, + 0x25, 0x2D, 0x2D, 0x2D, + 0x25, 0x25, 0x2D, 0x2D, + 0x25, 0x25, 0x25, 0x2D, + 0x25, 0x29, 0x2C, 0x30, + 0x25, 0x2A, 0x2E, 0x30, + 0x25, 0x27, 0x2E, 0x30, + 0x25, 0x27, 0x2B, 0x30, + 0x25, 0x30, 0x30, 0x30, + 0x25, 0x25, 0x30, 0x30, + 0x25, 0x25, 0x25, 0x30, + 0x25, 0x2A, 0x2E, 0x33, + 0x25, 0x2C, 0x30, 0x33, + 0x25, 0x28, 0x30, 0x33, + 0x25, 0x28, 0x2C, 0x33, + 0x25, 0x33, 0x33, 0x33, + 0x25, 0x25, 0x33, 0x33, + 0x25, 0x25, 0x25, 0x33, + 0x25, 0x2B, 0x30, 0x36, + 0x25, 0x2D, 0x32, 0x36, + 0x25, 0x29, 0x32, 0x36, + 0x25, 0x29, 0x2E, 0x36, + 0x25, 0x36, 0x36, 0x36, + 0x25, 0x25, 0x36, 0x36, + 0x25, 0x25, 0x25, 0x36, + 0x25, 0x2C, 0x32, 0x39, + 0x25, 0x2F, 0x34, 0x39, + 0x25, 0x2A, 0x34, 0x39, + 0x25, 0x2A, 0x2F, 0x39, + 0x25, 0x39, 0x39, 0x39, + 0x25, 0x25, 0x39, 0x39, + 0x25, 0x25, 0x25, 0x39, + 0x25, 0x30, 0x37, 0x3C, + 0x25, 0x2A, 0x37, 0x3C, + 0x25, 0x2A, 0x31, 0x3C, + 0x25, 0x3C, 0x3C, 0x3C, + 0x25, 0x25, 0x3C, 0x3C, + 0x25, 0x25, 0x25, 0x3C, + 0x25, 0x32, 0x39, 0x3F, + 0x25, 0x2B, 0x39, 0x3F, + 0x25, 0x2B, 0x32, 0x3F, + 0x25, 0x3F, 0x3F, 0x3F, + 0x25, 0x25, 0x3F, 0x3F, + 0x25, 0x25, 0x25, 0x3F, + 0x26, 0x27, 0x27, 0x28, + 0x26, 0x27, 0x28, 0x29, + 0x26, 0x28, 0x29, 0x2A, + 0x26, 0x27, 0x29, 0x2A, + 0x26, 0x27, 0x28, 0x2A, + 0x26, 0x28, 0x29, 0x2B, + 0x26, 0x28, 0x2A, 0x2B, + 0x26, 0x27, 0x2A, 0x2B, + 0x26, 0x27, 0x29, 0x2B, + 0x26, 0x28, 0x2A, 0x2C, + 0x26, 0x29, 0x2B, 0x2C, + 0x26, 0x27, 0x2B, 0x2C, + 0x26, 0x27, 0x29, 0x2C, + 0x26, 0x2C, 0x2C, 0x2C, + 0x26, 0x26, 0x2C, 0x2C, + 0x26, 0x26, 0x26, 0x2C, + 0x26, 0x29, 0x2A, 0x2D, + 0x26, 0x29, 0x2C, 0x2D, + 0x26, 0x27, 0x2C, 0x2D, + 0x26, 0x27, 0x2A, 0x2D, + 0x26, 0x29, 0x2B, 0x2E, + 0x26, 0x2A, 0x2C, 0x2E, + 0x26, 0x28, 0x2C, 0x2E, + 0x26, 0x28, 0x2A, 0x2E, + 0x26, 0x2E, 0x2E, 0x2E, + 0x26, 0x26, 0x2E, 0x2E, + 0x26, 0x26, 0x26, 0x2E, + 0x26, 0x2A, 0x2D, 0x31, + 0x26, 0x2B, 0x2F, 0x31, + 0x26, 0x28, 0x2F, 0x31, + 0x26, 0x28, 0x2C, 0x31, + 0x26, 0x31, 0x31, 0x31, + 0x26, 0x26, 0x31, 0x31, + 0x26, 0x26, 0x26, 0x31, + 0x26, 0x2B, 0x2F, 0x34, + 0x26, 0x2D, 0x31, 0x34, + 0x26, 0x29, 0x31, 0x34, + 0x26, 0x29, 0x2D, 0x34, + 0x26, 0x34, 0x34, 0x34, + 0x26, 0x26, 0x34, 0x34, + 0x26, 0x26, 0x26, 0x34, + 0x26, 0x2C, 0x31, 0x37, + 0x26, 0x2E, 0x33, 0x37, + 0x26, 0x2A, 0x33, 0x37, + 0x26, 0x2A, 0x2F, 0x37, + 0x26, 0x37, 0x37, 0x37, + 0x26, 0x26, 0x37, 0x37, + 0x26, 0x26, 0x26, 0x37, + 0x26, 0x2D, 0x33, 0x3A, + 0x26, 0x30, 0x35, 0x3A, + 0x26, 0x2B, 0x35, 0x3A, + 0x26, 0x2B, 0x30, 0x3A, + 0x26, 0x3A, 0x3A, 0x3A, + 0x26, 0x26, 0x3A, 0x3A, + 0x26, 0x26, 0x26, 0x3A, + 0x26, 0x31, 0x38, 0x3D, + 0x26, 0x2B, 0x38, 0x3D, + 0x26, 0x2B, 0x32, 0x3D, + 0x26, 0x3D, 0x3D, 0x3D, + 0x26, 0x26, 0x3D, 0x3D, + 0x26, 0x26, 0x26, 0x3D, + 0x27, 0x28, 0x28, 0x29, + 0x27, 0x28, 0x29, 0x2A, + 0x27, 0x29, 0x2A, 0x2B, + 0x27, 0x28, 0x2A, 0x2B, + 0x27, 0x28, 0x29, 0x2B, + 0x27, 0x29, 0x2A, 0x2C, + 0x27, 0x29, 0x2B, 0x2C, + 0x27, 0x28, 0x2B, 0x2C, + 0x27, 0x28, 0x2A, 0x2C, + 0x27, 0x29, 0x2B, 0x2D, + 0x27, 0x2A, 0x2C, 0x2D, + 0x27, 0x28, 0x2C, 0x2D, + 0x27, 0x28, 0x2A, 0x2D, + 0x27, 0x2D, 0x2D, 0x2D, + 0x27, 0x27, 0x2D, 0x2D, + 0x27, 0x27, 0x27, 0x2D, + 0x27, 0x2A, 0x2B, 0x2E, + 0x27, 0x2A, 0x2D, 0x2E, + 0x27, 0x28, 0x2D, 0x2E, + 0x27, 0x28, 0x2B, 0x2E, + 0x27, 0x2A, 0x2C, 0x2F, + 0x27, 0x2B, 0x2D, 0x2F, + 0x27, 0x29, 0x2D, 0x2F, + 0x27, 0x29, 0x2B, 0x2F, + 0x27, 0x2F, 0x2F, 0x2F, + 0x27, 0x27, 0x2F, 0x2F, + 0x27, 0x27, 0x27, 0x2F, + 0x27, 0x2B, 0x2E, 0x32, + 0x27, 0x2C, 0x30, 0x32, + 0x27, 0x29, 0x30, 0x32, + 0x27, 0x29, 0x2D, 0x32, + 0x27, 0x32, 0x32, 0x32, + 0x27, 0x27, 0x32, 0x32, + 0x27, 0x27, 0x27, 0x32, + 0x27, 0x2C, 0x30, 0x35, + 0x27, 0x2E, 0x32, 0x35, + 0x27, 0x2A, 0x32, 0x35, + 0x27, 0x2A, 0x2E, 0x35, + 0x27, 0x35, 0x35, 0x35, + 0x27, 0x27, 0x35, 0x35, + 0x27, 0x27, 0x27, 0x35, + 0x27, 0x2D, 0x32, 0x38, + 0x27, 0x2F, 0x34, 0x38, + 0x27, 0x2B, 0x34, 0x38, + 0x27, 0x2B, 0x30, 0x38, + 0x27, 0x38, 0x38, 0x38, + 0x27, 0x27, 0x38, 0x38, + 0x27, 0x27, 0x27, 0x38, + 0x27, 0x2E, 0x34, 0x3B, + 0x27, 0x31, 0x36, 0x3B, + 0x27, 0x2C, 0x36, 0x3B, + 0x27, 0x2C, 0x31, 0x3B, + 0x27, 0x3B, 0x3B, 0x3B, + 0x27, 0x27, 0x3B, 0x3B, + 0x27, 0x27, 0x27, 0x3B, + 0x27, 0x32, 0x39, 0x3E, + 0x27, 0x2C, 0x39, 0x3E, + 0x27, 0x2C, 0x33, 0x3E, + 0x27, 0x3E, 0x3E, 0x3E, + 0x27, 0x27, 0x3E, 0x3E, + 0x27, 0x27, 0x27, 0x3E, + 0x28, 0x29, 0x29, 0x2A, + 0x28, 0x29, 0x2A, 0x2B, + 0x28, 0x2A, 0x2B, 0x2C, + 0x28, 0x29, 0x2B, 0x2C, + 0x28, 0x29, 0x2A, 0x2C, + 0x28, 0x2A, 0x2B, 0x2D, + 0x28, 0x2A, 0x2C, 0x2D, + 0x28, 0x29, 0x2C, 0x2D, + 0x28, 0x29, 0x2B, 0x2D, + 0x28, 0x2A, 0x2C, 0x2E, + 0x28, 0x2B, 0x2D, 0x2E, + 0x28, 0x29, 0x2D, 0x2E, + 0x28, 0x29, 0x2B, 0x2E, + 0x28, 0x2E, 0x2E, 0x2E, + 0x28, 0x28, 0x2E, 0x2E, + 0x28, 0x28, 0x28, 0x2E, + 0x28, 0x2B, 0x2C, 0x2F, + 0x28, 0x2B, 0x2E, 0x2F, + 0x28, 0x29, 0x2E, 0x2F, + 0x28, 0x29, 0x2C, 0x2F, + 0x28, 0x2B, 0x2D, 0x30, + 0x28, 0x2C, 0x2E, 0x30, + 0x28, 0x2A, 0x2E, 0x30, + 0x28, 0x2A, 0x2C, 0x30, + 0x28, 0x30, 0x30, 0x30, + 0x28, 0x28, 0x30, 0x30, + 0x28, 0x28, 0x28, 0x30, + 0x28, 0x2C, 0x2F, 0x33, + 0x28, 0x2D, 0x31, 0x33, + 0x28, 0x2A, 0x31, 0x33, + 0x28, 0x2A, 0x2E, 0x33, + 0x28, 0x33, 0x33, 0x33, + 0x28, 0x28, 0x33, 0x33, + 0x28, 0x28, 0x28, 0x33, + 0x28, 0x2D, 0x31, 0x36, + 0x28, 0x2F, 0x33, 0x36, + 0x28, 0x2B, 0x33, 0x36, + 0x28, 0x2B, 0x2F, 0x36, + 0x28, 0x36, 0x36, 0x36, + 0x28, 0x28, 0x36, 0x36, + 0x28, 0x28, 0x28, 0x36, + 0x28, 0x2E, 0x33, 0x39, + 0x28, 0x30, 0x35, 0x39, + 0x28, 0x2C, 0x35, 0x39, + 0x28, 0x2C, 0x31, 0x39, + 0x28, 0x39, 0x39, 0x39, + 0x28, 0x28, 0x39, 0x39, + 0x28, 0x28, 0x28, 0x39, + 0x28, 0x2F, 0x35, 0x3C, + 0x28, 0x32, 0x37, 0x3C, + 0x28, 0x2D, 0x37, 0x3C, + 0x28, 0x2D, 0x32, 0x3C, + 0x28, 0x3C, 0x3C, 0x3C, + 0x28, 0x28, 0x3C, 0x3C, + 0x28, 0x28, 0x28, 0x3C, + 0x28, 0x33, 0x3A, 0x3F, + 0x28, 0x2D, 0x3A, 0x3F, + 0x28, 0x2D, 0x34, 0x3F, + 0x28, 0x3F, 0x3F, 0x3F, + 0x28, 0x28, 0x3F, 0x3F, + 0x28, 0x28, 0x28, 0x3F, + 0x29, 0x2A, 0x2A, 0x2B, + 0x29, 0x2A, 0x2B, 0x2C, + 0x29, 0x2B, 0x2C, 0x2D, + 0x29, 0x2A, 0x2C, 0x2D, + 0x29, 0x2A, 0x2B, 0x2D, + 0x29, 0x2B, 0x2C, 0x2E, + 0x29, 0x2B, 0x2D, 0x2E, + 0x29, 0x2A, 0x2D, 0x2E, + 0x29, 0x2A, 0x2C, 0x2E, + 0x29, 0x2B, 0x2D, 0x2F, + 0x29, 0x2C, 0x2E, 0x2F, + 0x29, 0x2A, 0x2E, 0x2F, + 0x29, 0x2A, 0x2C, 0x2F, + 0x29, 0x2F, 0x2F, 0x2F, + 0x29, 0x29, 0x2F, 0x2F, + 0x29, 0x29, 0x29, 0x2F, + 0x29, 0x2C, 0x2D, 0x30, + 0x29, 0x2C, 0x2F, 0x30, + 0x29, 0x2A, 0x2F, 0x30, + 0x29, 0x2A, 0x2D, 0x30, + 0x29, 0x2C, 0x2E, 0x31, + 0x29, 0x2D, 0x2F, 0x31, + 0x29, 0x2B, 0x2F, 0x31, + 0x29, 0x2B, 0x2D, 0x31, + 0x29, 0x31, 0x31, 0x31, + 0x29, 0x29, 0x31, 0x31, + 0x29, 0x29, 0x29, 0x31, + 0x29, 0x2D, 0x30, 0x34, + 0x29, 0x2E, 0x32, 0x34, + 0x29, 0x2B, 0x32, 0x34, + 0x29, 0x2B, 0x2F, 0x34, + 0x29, 0x34, 0x34, 0x34, + 0x29, 0x29, 0x34, 0x34, + 0x29, 0x29, 0x29, 0x34, + 0x29, 0x2E, 0x32, 0x37, + 0x29, 0x30, 0x34, 0x37, + 0x29, 0x2C, 0x34, 0x37, + 0x29, 0x2C, 0x30, 0x37, + 0x29, 0x37, 0x37, 0x37, + 0x29, 0x29, 0x37, 0x37, + 0x29, 0x29, 0x29, 0x37, + 0x29, 0x2F, 0x34, 0x3A, + 0x29, 0x31, 0x36, 0x3A, + 0x29, 0x2D, 0x36, 0x3A, + 0x29, 0x2D, 0x32, 0x3A, + 0x29, 0x3A, 0x3A, 0x3A, + 0x29, 0x29, 0x3A, 0x3A, + 0x29, 0x29, 0x29, 0x3A, + 0x29, 0x30, 0x36, 0x3D, + 0x29, 0x33, 0x38, 0x3D, + 0x29, 0x2E, 0x38, 0x3D, + 0x29, 0x2E, 0x33, 0x3D, + 0x29, 0x3D, 0x3D, 0x3D, + 0x29, 0x29, 0x3D, 0x3D, + 0x29, 0x29, 0x29, 0x3D, + 0x2A, 0x2B, 0x2B, 0x2C, + 0x2A, 0x2B, 0x2C, 0x2D, + 0x2A, 0x2C, 0x2D, 0x2E, + 0x2A, 0x2B, 0x2D, 0x2E, + 0x2A, 0x2B, 0x2C, 0x2E, + 0x2A, 0x2C, 0x2D, 0x2F, + 0x2A, 0x2C, 0x2E, 0x2F, + 0x2A, 0x2B, 0x2E, 0x2F, + 0x2A, 0x2B, 0x2D, 0x2F, + 0x2A, 0x2C, 0x2E, 0x30, + 0x2A, 0x2D, 0x2F, 0x30, + 0x2A, 0x2B, 0x2F, 0x30, + 0x2A, 0x2B, 0x2D, 0x30, + 0x2A, 0x30, 0x30, 0x30, + 0x2A, 0x2A, 0x30, 0x30, + 0x2A, 0x2A, 0x2A, 0x30, + 0x2A, 0x2D, 0x2E, 0x31, + 0x2A, 0x2D, 0x30, 0x31, + 0x2A, 0x2B, 0x30, 0x31, + 0x2A, 0x2B, 0x2E, 0x31, + 0x2A, 0x2D, 0x2F, 0x32, + 0x2A, 0x2E, 0x30, 0x32, + 0x2A, 0x2C, 0x30, 0x32, + 0x2A, 0x2C, 0x2E, 0x32, + 0x2A, 0x32, 0x32, 0x32, + 0x2A, 0x2A, 0x32, 0x32, + 0x2A, 0x2A, 0x2A, 0x32, + 0x2A, 0x2E, 0x31, 0x35, + 0x2A, 0x2F, 0x33, 0x35, + 0x2A, 0x2C, 0x33, 0x35, + 0x2A, 0x2C, 0x30, 0x35, + 0x2A, 0x35, 0x35, 0x35, + 0x2A, 0x2A, 0x35, 0x35, + 0x2A, 0x2A, 0x2A, 0x35, + 0x2A, 0x2F, 0x33, 0x38, + 0x2A, 0x31, 0x35, 0x38, + 0x2A, 0x2D, 0x35, 0x38, + 0x2A, 0x2D, 0x31, 0x38, + 0x2A, 0x38, 0x38, 0x38, + 0x2A, 0x2A, 0x38, 0x38, + 0x2A, 0x2A, 0x2A, 0x38, + 0x2A, 0x30, 0x35, 0x3B, + 0x2A, 0x32, 0x37, 0x3B, + 0x2A, 0x2E, 0x37, 0x3B, + 0x2A, 0x2E, 0x33, 0x3B, + 0x2A, 0x3B, 0x3B, 0x3B, + 0x2A, 0x2A, 0x3B, 0x3B, + 0x2A, 0x2A, 0x2A, 0x3B, + 0x2A, 0x31, 0x37, 0x3E, + 0x2A, 0x34, 0x39, 0x3E, + 0x2A, 0x2F, 0x39, 0x3E, + 0x2A, 0x2F, 0x34, 0x3E, + 0x2A, 0x3E, 0x3E, 0x3E, + 0x2A, 0x2A, 0x3E, 0x3E, + 0x2A, 0x2A, 0x2A, 0x3E, + 0x2B, 0x2C, 0x2C, 0x2D, + 0x2B, 0x2C, 0x2D, 0x2E, + 0x2B, 0x2D, 0x2E, 0x2F, + 0x2B, 0x2C, 0x2E, 0x2F, + 0x2B, 0x2C, 0x2D, 0x2F, + 0x2B, 0x2D, 0x2E, 0x30, + 0x2B, 0x2D, 0x2F, 0x30, + 0x2B, 0x2C, 0x2F, 0x30, + 0x2B, 0x2C, 0x2E, 0x30, + 0x2B, 0x2D, 0x2F, 0x31, + 0x2B, 0x2E, 0x30, 0x31, + 0x2B, 0x2C, 0x30, 0x31, + 0x2B, 0x2C, 0x2E, 0x31, + 0x2B, 0x31, 0x31, 0x31, + 0x2B, 0x2B, 0x31, 0x31, + 0x2B, 0x2B, 0x2B, 0x31, + 0x2B, 0x2E, 0x2F, 0x32, + 0x2B, 0x2E, 0x31, 0x32, + 0x2B, 0x2C, 0x31, 0x32, + 0x2B, 0x2C, 0x2F, 0x32, + 0x2B, 0x2E, 0x30, 0x33, + 0x2B, 0x2F, 0x31, 0x33, + 0x2B, 0x2D, 0x31, 0x33, + 0x2B, 0x2D, 0x2F, 0x33, + 0x2B, 0x33, 0x33, 0x33, + 0x2B, 0x2B, 0x33, 0x33, + 0x2B, 0x2B, 0x2B, 0x33, + 0x2B, 0x2F, 0x32, 0x36, + 0x2B, 0x30, 0x34, 0x36, + 0x2B, 0x2D, 0x34, 0x36, + 0x2B, 0x2D, 0x31, 0x36, + 0x2B, 0x36, 0x36, 0x36, + 0x2B, 0x2B, 0x36, 0x36, + 0x2B, 0x2B, 0x2B, 0x36, + 0x2B, 0x30, 0x34, 0x39, + 0x2B, 0x32, 0x36, 0x39, + 0x2B, 0x2E, 0x36, 0x39, + 0x2B, 0x2E, 0x32, 0x39, + 0x2B, 0x39, 0x39, 0x39, + 0x2B, 0x2B, 0x39, 0x39, + 0x2B, 0x2B, 0x2B, 0x39, + 0x2B, 0x31, 0x36, 0x3C, + 0x2B, 0x33, 0x38, 0x3C, + 0x2B, 0x2F, 0x38, 0x3C, + 0x2B, 0x2F, 0x34, 0x3C, + 0x2B, 0x3C, 0x3C, 0x3C, + 0x2B, 0x2B, 0x3C, 0x3C, + 0x2B, 0x2B, 0x2B, 0x3C, + 0x2B, 0x32, 0x38, 0x3F, + 0x2B, 0x35, 0x3A, 0x3F, + 0x2B, 0x30, 0x3A, 0x3F, + 0x2B, 0x30, 0x35, 0x3F, + 0x2B, 0x3F, 0x3F, 0x3F, + 0x2B, 0x2B, 0x3F, 0x3F, + 0x2B, 0x2B, 0x2B, 0x3F, + 0x2C, 0x2D, 0x2D, 0x2E, + 0x2C, 0x2D, 0x2E, 0x2F, + 0x2C, 0x2E, 0x2F, 0x30, + 0x2C, 0x2D, 0x2F, 0x30, + 0x2C, 0x2D, 0x2E, 0x30, + 0x2C, 0x2E, 0x2F, 0x31, + 0x2C, 0x2E, 0x30, 0x31, + 0x2C, 0x2D, 0x30, 0x31, + 0x2C, 0x2D, 0x2F, 0x31, + 0x2C, 0x2E, 0x30, 0x32, + 0x2C, 0x2F, 0x31, 0x32, + 0x2C, 0x2D, 0x31, 0x32, + 0x2C, 0x2D, 0x2F, 0x32, + 0x2C, 0x32, 0x32, 0x32, + 0x2C, 0x2C, 0x32, 0x32, + 0x2C, 0x2C, 0x2C, 0x32, + 0x2C, 0x2F, 0x30, 0x33, + 0x2C, 0x2F, 0x32, 0x33, + 0x2C, 0x2D, 0x32, 0x33, + 0x2C, 0x2D, 0x30, 0x33, + 0x2C, 0x2F, 0x31, 0x34, + 0x2C, 0x30, 0x32, 0x34, + 0x2C, 0x2E, 0x32, 0x34, + 0x2C, 0x2E, 0x30, 0x34, + 0x2C, 0x34, 0x34, 0x34, + 0x2C, 0x2C, 0x34, 0x34, + 0x2C, 0x2C, 0x2C, 0x34, + 0x2C, 0x30, 0x33, 0x37, + 0x2C, 0x31, 0x35, 0x37, + 0x2C, 0x2E, 0x35, 0x37, + 0x2C, 0x2E, 0x32, 0x37, + 0x2C, 0x37, 0x37, 0x37, + 0x2C, 0x2C, 0x37, 0x37, + 0x2C, 0x2C, 0x2C, 0x37, + 0x2C, 0x31, 0x35, 0x3A, + 0x2C, 0x33, 0x37, 0x3A, + 0x2C, 0x2F, 0x37, 0x3A, + 0x2C, 0x2F, 0x33, 0x3A, + 0x2C, 0x3A, 0x3A, 0x3A, + 0x2C, 0x2C, 0x3A, 0x3A, + 0x2C, 0x2C, 0x2C, 0x3A, + 0x2C, 0x32, 0x37, 0x3D, + 0x2C, 0x34, 0x39, 0x3D, + 0x2C, 0x30, 0x39, 0x3D, + 0x2C, 0x30, 0x35, 0x3D, + 0x2C, 0x3D, 0x3D, 0x3D, + 0x2C, 0x2C, 0x3D, 0x3D, + 0x2C, 0x2C, 0x2C, 0x3D, + 0x2D, 0x2E, 0x2E, 0x2F, + 0x2D, 0x2E, 0x2F, 0x30, + 0x2D, 0x2F, 0x30, 0x31, + 0x2D, 0x2E, 0x30, 0x31, + 0x2D, 0x2E, 0x2F, 0x31, + 0x2D, 0x2F, 0x30, 0x32, + 0x2D, 0x2F, 0x31, 0x32, + 0x2D, 0x2E, 0x31, 0x32, + 0x2D, 0x2E, 0x30, 0x32, + 0x2D, 0x2F, 0x31, 0x33, + 0x2D, 0x30, 0x32, 0x33, + 0x2D, 0x2E, 0x32, 0x33, + 0x2D, 0x2E, 0x30, 0x33, + 0x2D, 0x33, 0x33, 0x33, + 0x2D, 0x2D, 0x33, 0x33, + 0x2D, 0x2D, 0x2D, 0x33, + 0x2D, 0x30, 0x31, 0x34, + 0x2D, 0x30, 0x33, 0x34, + 0x2D, 0x2E, 0x33, 0x34, + 0x2D, 0x2E, 0x31, 0x34, + 0x2D, 0x30, 0x32, 0x35, + 0x2D, 0x31, 0x33, 0x35, + 0x2D, 0x2F, 0x33, 0x35, + 0x2D, 0x2F, 0x31, 0x35, + 0x2D, 0x35, 0x35, 0x35, + 0x2D, 0x2D, 0x35, 0x35, + 0x2D, 0x2D, 0x2D, 0x35, + 0x2D, 0x31, 0x34, 0x38, + 0x2D, 0x32, 0x36, 0x38, + 0x2D, 0x2F, 0x36, 0x38, + 0x2D, 0x2F, 0x33, 0x38, + 0x2D, 0x38, 0x38, 0x38, + 0x2D, 0x2D, 0x38, 0x38, + 0x2D, 0x2D, 0x2D, 0x38, + 0x2D, 0x32, 0x36, 0x3B, + 0x2D, 0x34, 0x38, 0x3B, + 0x2D, 0x30, 0x38, 0x3B, + 0x2D, 0x30, 0x34, 0x3B, + 0x2D, 0x3B, 0x3B, 0x3B, + 0x2D, 0x2D, 0x3B, 0x3B, + 0x2D, 0x2D, 0x2D, 0x3B, + 0x2D, 0x33, 0x38, 0x3E, + 0x2D, 0x35, 0x3A, 0x3E, + 0x2D, 0x31, 0x3A, 0x3E, + 0x2D, 0x31, 0x36, 0x3E, + 0x2D, 0x3E, 0x3E, 0x3E, + 0x2D, 0x2D, 0x3E, 0x3E, + 0x2D, 0x2D, 0x2D, 0x3E, + 0x2E, 0x2F, 0x2F, 0x30, + 0x2E, 0x2F, 0x30, 0x31, + 0x2E, 0x30, 0x31, 0x32, + 0x2E, 0x2F, 0x31, 0x32, + 0x2E, 0x2F, 0x30, 0x32, + 0x2E, 0x30, 0x31, 0x33, + 0x2E, 0x30, 0x32, 0x33, + 0x2E, 0x2F, 0x32, 0x33, + 0x2E, 0x2F, 0x31, 0x33, + 0x2E, 0x30, 0x32, 0x34, + 0x2E, 0x31, 0x33, 0x34, + 0x2E, 0x2F, 0x33, 0x34, + 0x2E, 0x2F, 0x31, 0x34, + 0x2E, 0x34, 0x34, 0x34, + 0x2E, 0x2E, 0x34, 0x34, + 0x2E, 0x2E, 0x2E, 0x34, + 0x2E, 0x31, 0x32, 0x35, + 0x2E, 0x31, 0x34, 0x35, + 0x2E, 0x2F, 0x34, 0x35, + 0x2E, 0x2F, 0x32, 0x35, + 0x2E, 0x31, 0x33, 0x36, + 0x2E, 0x32, 0x34, 0x36, + 0x2E, 0x30, 0x34, 0x36, + 0x2E, 0x30, 0x32, 0x36, + 0x2E, 0x36, 0x36, 0x36, + 0x2E, 0x2E, 0x36, 0x36, + 0x2E, 0x2E, 0x2E, 0x36, + 0x2E, 0x32, 0x35, 0x39, + 0x2E, 0x33, 0x37, 0x39, + 0x2E, 0x30, 0x37, 0x39, + 0x2E, 0x30, 0x34, 0x39, + 0x2E, 0x39, 0x39, 0x39, + 0x2E, 0x2E, 0x39, 0x39, + 0x2E, 0x2E, 0x2E, 0x39, + 0x2E, 0x33, 0x37, 0x3C, + 0x2E, 0x35, 0x39, 0x3C, + 0x2E, 0x31, 0x39, 0x3C, + 0x2E, 0x31, 0x35, 0x3C, + 0x2E, 0x3C, 0x3C, 0x3C, + 0x2E, 0x2E, 0x3C, 0x3C, + 0x2E, 0x2E, 0x2E, 0x3C, + 0x2E, 0x34, 0x39, 0x3F, + 0x2E, 0x36, 0x3B, 0x3F, + 0x2E, 0x32, 0x3B, 0x3F, + 0x2E, 0x32, 0x37, 0x3F, + 0x2E, 0x3F, 0x3F, 0x3F, + 0x2E, 0x2E, 0x3F, 0x3F, + 0x2E, 0x2E, 0x2E, 0x3F, + 0x2F, 0x30, 0x30, 0x31, + 0x2F, 0x30, 0x31, 0x32, + 0x2F, 0x31, 0x32, 0x33, + 0x2F, 0x30, 0x32, 0x33, + 0x2F, 0x30, 0x31, 0x33, + 0x2F, 0x31, 0x32, 0x34, + 0x2F, 0x31, 0x33, 0x34, + 0x2F, 0x30, 0x33, 0x34, + 0x2F, 0x30, 0x32, 0x34, + 0x2F, 0x31, 0x33, 0x35, + 0x2F, 0x32, 0x34, 0x35, + 0x2F, 0x30, 0x34, 0x35, + 0x2F, 0x30, 0x32, 0x35, + 0x2F, 0x35, 0x35, 0x35, + 0x2F, 0x2F, 0x35, 0x35, + 0x2F, 0x2F, 0x2F, 0x35, + 0x2F, 0x32, 0x33, 0x36, + 0x2F, 0x32, 0x35, 0x36, + 0x2F, 0x30, 0x35, 0x36, + 0x2F, 0x30, 0x33, 0x36, + 0x2F, 0x32, 0x34, 0x37, + 0x2F, 0x33, 0x35, 0x37, + 0x2F, 0x31, 0x35, 0x37, + 0x2F, 0x31, 0x33, 0x37, + 0x2F, 0x37, 0x37, 0x37, + 0x2F, 0x2F, 0x37, 0x37, + 0x2F, 0x2F, 0x2F, 0x37, + 0x2F, 0x33, 0x36, 0x3A, + 0x2F, 0x34, 0x38, 0x3A, + 0x2F, 0x31, 0x38, 0x3A, + 0x2F, 0x31, 0x35, 0x3A, + 0x2F, 0x3A, 0x3A, 0x3A, + 0x2F, 0x2F, 0x3A, 0x3A, + 0x2F, 0x2F, 0x2F, 0x3A, + 0x2F, 0x34, 0x38, 0x3D, + 0x2F, 0x36, 0x3A, 0x3D, + 0x2F, 0x32, 0x3A, 0x3D, + 0x2F, 0x32, 0x36, 0x3D, + 0x2F, 0x3D, 0x3D, 0x3D, + 0x2F, 0x2F, 0x3D, 0x3D, + 0x2F, 0x2F, 0x2F, 0x3D, + 0x30, 0x31, 0x31, 0x32, + 0x30, 0x31, 0x32, 0x33, + 0x30, 0x32, 0x33, 0x34, + 0x30, 0x31, 0x33, 0x34, + 0x30, 0x31, 0x32, 0x34, + 0x30, 0x32, 0x33, 0x35, + 0x30, 0x32, 0x34, 0x35, + 0x30, 0x31, 0x34, 0x35, + 0x30, 0x31, 0x33, 0x35, + 0x30, 0x32, 0x34, 0x36, + 0x30, 0x33, 0x35, 0x36, + 0x30, 0x31, 0x35, 0x36, + 0x30, 0x31, 0x33, 0x36, + 0x30, 0x36, 0x36, 0x36, + 0x30, 0x30, 0x36, 0x36, + 0x30, 0x30, 0x30, 0x36, + 0x30, 0x33, 0x34, 0x37, + 0x30, 0x33, 0x36, 0x37, + 0x30, 0x31, 0x36, 0x37, + 0x30, 0x31, 0x34, 0x37, + 0x30, 0x33, 0x35, 0x38, + 0x30, 0x34, 0x36, 0x38, + 0x30, 0x32, 0x36, 0x38, + 0x30, 0x32, 0x34, 0x38, + 0x30, 0x38, 0x38, 0x38, + 0x30, 0x30, 0x38, 0x38, + 0x30, 0x30, 0x30, 0x38, + 0x30, 0x34, 0x37, 0x3B, + 0x30, 0x35, 0x39, 0x3B, + 0x30, 0x32, 0x39, 0x3B, + 0x30, 0x32, 0x36, 0x3B, + 0x30, 0x3B, 0x3B, 0x3B, + 0x30, 0x30, 0x3B, 0x3B, + 0x30, 0x30, 0x30, 0x3B, + 0x30, 0x35, 0x39, 0x3E, + 0x30, 0x37, 0x3B, 0x3E, + 0x30, 0x33, 0x3B, 0x3E, + 0x30, 0x33, 0x37, 0x3E, + 0x30, 0x3E, 0x3E, 0x3E, + 0x30, 0x30, 0x3E, 0x3E, + 0x30, 0x30, 0x30, 0x3E, + 0x31, 0x32, 0x32, 0x33, + 0x31, 0x32, 0x33, 0x34, + 0x31, 0x33, 0x34, 0x35, + 0x31, 0x32, 0x34, 0x35, + 0x31, 0x32, 0x33, 0x35, + 0x31, 0x33, 0x34, 0x36, + 0x31, 0x33, 0x35, 0x36, + 0x31, 0x32, 0x35, 0x36, + 0x31, 0x32, 0x34, 0x36, + 0x31, 0x33, 0x35, 0x37, + 0x31, 0x34, 0x36, 0x37, + 0x31, 0x32, 0x36, 0x37, + 0x31, 0x32, 0x34, 0x37, + 0x31, 0x37, 0x37, 0x37, + 0x31, 0x31, 0x37, 0x37, + 0x31, 0x31, 0x31, 0x37, + 0x31, 0x34, 0x35, 0x38, + 0x31, 0x34, 0x37, 0x38, + 0x31, 0x32, 0x37, 0x38, + 0x31, 0x32, 0x35, 0x38, + 0x31, 0x34, 0x36, 0x39, + 0x31, 0x35, 0x37, 0x39, + 0x31, 0x33, 0x37, 0x39, + 0x31, 0x33, 0x35, 0x39, + 0x31, 0x39, 0x39, 0x39, + 0x31, 0x31, 0x39, 0x39, + 0x31, 0x31, 0x31, 0x39, + 0x31, 0x35, 0x38, 0x3C, + 0x31, 0x36, 0x3A, 0x3C, + 0x31, 0x33, 0x3A, 0x3C, + 0x31, 0x33, 0x37, 0x3C, + 0x31, 0x3C, 0x3C, 0x3C, + 0x31, 0x31, 0x3C, 0x3C, + 0x31, 0x31, 0x31, 0x3C, + 0x31, 0x36, 0x3A, 0x3F, + 0x31, 0x38, 0x3C, 0x3F, + 0x31, 0x34, 0x3C, 0x3F, + 0x31, 0x34, 0x38, 0x3F, + 0x31, 0x3F, 0x3F, 0x3F, + 0x31, 0x31, 0x3F, 0x3F, + 0x31, 0x31, 0x31, 0x3F, + 0x32, 0x33, 0x33, 0x34, + 0x32, 0x33, 0x34, 0x35, + 0x32, 0x34, 0x35, 0x36, + 0x32, 0x33, 0x35, 0x36, + 0x32, 0x33, 0x34, 0x36, + 0x32, 0x34, 0x35, 0x37, + 0x32, 0x34, 0x36, 0x37, + 0x32, 0x33, 0x36, 0x37, + 0x32, 0x33, 0x35, 0x37, + 0x32, 0x34, 0x36, 0x38, + 0x32, 0x35, 0x37, 0x38, + 0x32, 0x33, 0x37, 0x38, + 0x32, 0x33, 0x35, 0x38, + 0x32, 0x38, 0x38, 0x38, + 0x32, 0x32, 0x38, 0x38, + 0x32, 0x32, 0x32, 0x38, + 0x32, 0x35, 0x36, 0x39, + 0x32, 0x35, 0x38, 0x39, + 0x32, 0x33, 0x38, 0x39, + 0x32, 0x33, 0x36, 0x39, + 0x32, 0x35, 0x37, 0x3A, + 0x32, 0x36, 0x38, 0x3A, + 0x32, 0x34, 0x38, 0x3A, + 0x32, 0x34, 0x36, 0x3A, + 0x32, 0x3A, 0x3A, 0x3A, + 0x32, 0x32, 0x3A, 0x3A, + 0x32, 0x32, 0x32, 0x3A, + 0x32, 0x36, 0x39, 0x3D, + 0x32, 0x37, 0x3B, 0x3D, + 0x32, 0x34, 0x3B, 0x3D, + 0x32, 0x34, 0x38, 0x3D, + 0x32, 0x3D, 0x3D, 0x3D, + 0x32, 0x32, 0x3D, 0x3D, + 0x32, 0x32, 0x32, 0x3D, + 0x33, 0x34, 0x34, 0x35, + 0x33, 0x34, 0x35, 0x36, + 0x33, 0x35, 0x36, 0x37, + 0x33, 0x34, 0x36, 0x37, + 0x33, 0x34, 0x35, 0x37, + 0x33, 0x35, 0x36, 0x38, + 0x33, 0x35, 0x37, 0x38, + 0x33, 0x34, 0x37, 0x38, + 0x33, 0x34, 0x36, 0x38, + 0x33, 0x35, 0x37, 0x39, + 0x33, 0x36, 0x38, 0x39, + 0x33, 0x34, 0x38, 0x39, + 0x33, 0x34, 0x36, 0x39, + 0x33, 0x39, 0x39, 0x39, + 0x33, 0x33, 0x39, 0x39, + 0x33, 0x33, 0x33, 0x39, + 0x33, 0x36, 0x37, 0x3A, + 0x33, 0x36, 0x39, 0x3A, + 0x33, 0x34, 0x39, 0x3A, + 0x33, 0x34, 0x37, 0x3A, + 0x33, 0x36, 0x38, 0x3B, + 0x33, 0x37, 0x39, 0x3B, + 0x33, 0x35, 0x39, 0x3B, + 0x33, 0x35, 0x37, 0x3B, + 0x33, 0x3B, 0x3B, 0x3B, + 0x33, 0x33, 0x3B, 0x3B, + 0x33, 0x33, 0x33, 0x3B, + 0x33, 0x37, 0x3A, 0x3E, + 0x33, 0x38, 0x3C, 0x3E, + 0x33, 0x35, 0x3C, 0x3E, + 0x33, 0x35, 0x39, 0x3E, + 0x33, 0x3E, 0x3E, 0x3E, + 0x33, 0x33, 0x3E, 0x3E, + 0x33, 0x33, 0x33, 0x3E, + 0x34, 0x35, 0x35, 0x36, + 0x34, 0x35, 0x36, 0x37, + 0x34, 0x36, 0x37, 0x38, + 0x34, 0x35, 0x37, 0x38, + 0x34, 0x35, 0x36, 0x38, + 0x34, 0x36, 0x37, 0x39, + 0x34, 0x36, 0x38, 0x39, + 0x34, 0x35, 0x38, 0x39, + 0x34, 0x35, 0x37, 0x39, + 0x34, 0x36, 0x38, 0x3A, + 0x34, 0x37, 0x39, 0x3A, + 0x34, 0x35, 0x39, 0x3A, + 0x34, 0x35, 0x37, 0x3A, + 0x34, 0x3A, 0x3A, 0x3A, + 0x34, 0x34, 0x3A, 0x3A, + 0x34, 0x34, 0x34, 0x3A, + 0x34, 0x37, 0x38, 0x3B, + 0x34, 0x37, 0x3A, 0x3B, + 0x34, 0x35, 0x3A, 0x3B, + 0x34, 0x35, 0x38, 0x3B, + 0x34, 0x37, 0x39, 0x3C, + 0x34, 0x38, 0x3A, 0x3C, + 0x34, 0x36, 0x3A, 0x3C, + 0x34, 0x36, 0x38, 0x3C, + 0x34, 0x3C, 0x3C, 0x3C, + 0x34, 0x34, 0x3C, 0x3C, + 0x34, 0x34, 0x34, 0x3C, + 0x34, 0x38, 0x3B, 0x3F, + 0x34, 0x39, 0x3D, 0x3F, + 0x34, 0x36, 0x3D, 0x3F, + 0x34, 0x36, 0x3A, 0x3F, + 0x34, 0x3F, 0x3F, 0x3F, + 0x34, 0x34, 0x3F, 0x3F, + 0x34, 0x34, 0x34, 0x3F, + 0x35, 0x36, 0x36, 0x37, + 0x35, 0x36, 0x37, 0x38, + 0x35, 0x37, 0x38, 0x39, + 0x35, 0x36, 0x38, 0x39, + 0x35, 0x36, 0x37, 0x39, + 0x35, 0x37, 0x38, 0x3A, + 0x35, 0x37, 0x39, 0x3A, + 0x35, 0x36, 0x39, 0x3A, + 0x35, 0x36, 0x38, 0x3A, + 0x35, 0x37, 0x39, 0x3B, + 0x35, 0x38, 0x3A, 0x3B, + 0x35, 0x36, 0x3A, 0x3B, + 0x35, 0x36, 0x38, 0x3B, + 0x35, 0x3B, 0x3B, 0x3B, + 0x35, 0x35, 0x3B, 0x3B, + 0x35, 0x35, 0x35, 0x3B, + 0x35, 0x38, 0x39, 0x3C, + 0x35, 0x38, 0x3B, 0x3C, + 0x35, 0x36, 0x3B, 0x3C, + 0x35, 0x36, 0x39, 0x3C, + 0x35, 0x38, 0x3A, 0x3D, + 0x35, 0x39, 0x3B, 0x3D, + 0x35, 0x37, 0x3B, 0x3D, + 0x35, 0x37, 0x39, 0x3D, + 0x35, 0x3D, 0x3D, 0x3D, + 0x35, 0x35, 0x3D, 0x3D, + 0x35, 0x35, 0x35, 0x3D, + 0x36, 0x37, 0x37, 0x38, + 0x36, 0x37, 0x38, 0x39, + 0x36, 0x38, 0x39, 0x3A, + 0x36, 0x37, 0x39, 0x3A, + 0x36, 0x37, 0x38, 0x3A, + 0x36, 0x38, 0x39, 0x3B, + 0x36, 0x38, 0x3A, 0x3B, + 0x36, 0x37, 0x3A, 0x3B, + 0x36, 0x37, 0x39, 0x3B, + 0x36, 0x38, 0x3A, 0x3C, + 0x36, 0x39, 0x3B, 0x3C, + 0x36, 0x37, 0x3B, 0x3C, + 0x36, 0x37, 0x39, 0x3C, + 0x36, 0x3C, 0x3C, 0x3C, + 0x36, 0x36, 0x3C, 0x3C, + 0x36, 0x36, 0x36, 0x3C, + 0x36, 0x39, 0x3A, 0x3D, + 0x36, 0x39, 0x3C, 0x3D, + 0x36, 0x37, 0x3C, 0x3D, + 0x36, 0x37, 0x3A, 0x3D, + 0x36, 0x39, 0x3B, 0x3E, + 0x36, 0x3A, 0x3C, 0x3E, + 0x36, 0x38, 0x3C, 0x3E, + 0x36, 0x38, 0x3A, 0x3E, + 0x36, 0x3E, 0x3E, 0x3E, + 0x36, 0x36, 0x3E, 0x3E, + 0x36, 0x36, 0x36, 0x3E, + 0x37, 0x38, 0x38, 0x39, + 0x37, 0x38, 0x39, 0x3A, + 0x37, 0x39, 0x3A, 0x3B, + 0x37, 0x38, 0x3A, 0x3B, + 0x37, 0x38, 0x39, 0x3B, + 0x37, 0x39, 0x3A, 0x3C, + 0x37, 0x39, 0x3B, 0x3C, + 0x37, 0x38, 0x3B, 0x3C, + 0x37, 0x38, 0x3A, 0x3C, + 0x37, 0x39, 0x3B, 0x3D, + 0x37, 0x3A, 0x3C, 0x3D, + 0x37, 0x38, 0x3C, 0x3D, + 0x37, 0x38, 0x3A, 0x3D, + 0x37, 0x3D, 0x3D, 0x3D, + 0x37, 0x37, 0x3D, 0x3D, + 0x37, 0x37, 0x37, 0x3D, + 0x37, 0x3A, 0x3B, 0x3E, + 0x37, 0x3A, 0x3D, 0x3E, + 0x37, 0x38, 0x3D, 0x3E, + 0x37, 0x38, 0x3B, 0x3E, + 0x37, 0x3A, 0x3C, 0x3F, + 0x37, 0x3B, 0x3D, 0x3F, + 0x37, 0x39, 0x3D, 0x3F, + 0x37, 0x39, 0x3B, 0x3F, + 0x37, 0x3F, 0x3F, 0x3F, + 0x37, 0x37, 0x3F, 0x3F, + 0x37, 0x37, 0x37, 0x3F, + 0x38, 0x39, 0x39, 0x3A, + 0x38, 0x39, 0x3A, 0x3B, + 0x38, 0x3A, 0x3B, 0x3C, + 0x38, 0x39, 0x3B, 0x3C, + 0x38, 0x39, 0x3A, 0x3C, + 0x38, 0x3A, 0x3B, 0x3D, + 0x38, 0x3A, 0x3C, 0x3D, + 0x38, 0x39, 0x3C, 0x3D, + 0x38, 0x39, 0x3B, 0x3D, + 0x38, 0x3A, 0x3C, 0x3E, + 0x38, 0x3B, 0x3D, 0x3E, + 0x38, 0x39, 0x3D, 0x3E, + 0x38, 0x39, 0x3B, 0x3E, + 0x38, 0x3E, 0x3E, 0x3E, + 0x38, 0x38, 0x3E, 0x3E, + 0x38, 0x38, 0x38, 0x3E, + 0x38, 0x3B, 0x3C, 0x3F, + 0x38, 0x3B, 0x3E, 0x3F, + 0x38, 0x39, 0x3E, 0x3F, + 0x38, 0x39, 0x3C, 0x3F, + 0x39, 0x3A, 0x3A, 0x3B, + 0x39, 0x3A, 0x3B, 0x3C, + 0x39, 0x3B, 0x3C, 0x3D, + 0x39, 0x3A, 0x3C, 0x3D, + 0x39, 0x3A, 0x3B, 0x3D, + 0x39, 0x3B, 0x3C, 0x3E, + 0x39, 0x3B, 0x3D, 0x3E, + 0x39, 0x3A, 0x3D, 0x3E, + 0x39, 0x3A, 0x3C, 0x3E, + 0x39, 0x3B, 0x3D, 0x3F, + 0x39, 0x3C, 0x3E, 0x3F, + 0x39, 0x3A, 0x3E, 0x3F, + 0x39, 0x3A, 0x3C, 0x3F, + 0x39, 0x3F, 0x3F, 0x3F, + 0x39, 0x39, 0x3F, 0x3F, + 0x39, 0x39, 0x39, 0x3F, + 0x3A, 0x3B, 0x3B, 0x3C, + 0x3A, 0x3B, 0x3C, 0x3D, + 0x3A, 0x3C, 0x3D, 0x3E, + 0x3A, 0x3B, 0x3D, 0x3E, + 0x3A, 0x3B, 0x3C, 0x3E, + 0x3A, 0x3C, 0x3D, 0x3F, + 0x3A, 0x3C, 0x3E, 0x3F, + 0x3A, 0x3B, 0x3E, 0x3F, + 0x3A, 0x3B, 0x3D, 0x3F, + 0x3B, 0x3C, 0x3C, 0x3D, + 0x3B, 0x3C, 0x3D, 0x3E, + 0x3B, 0x3D, 0x3E, 0x3F, + 0x3B, 0x3C, 0x3E, 0x3F, + 0x3B, 0x3C, 0x3D, 0x3F, + 0x3C, 0x3D, 0x3D, 0x3E, + 0x3C, 0x3D, 0x3E, 0x3F, + 0x3D, 0x3E, 0x3E, 0x3F +}; + +#endif /* AVCODEC_ULTI_CB_H */ diff --git a/ffmpeg/libavcodec/unary.h b/ffmpeg/libavcodec/unary.h new file mode 100644 index 0000000..908dc93 --- /dev/null +++ b/ffmpeg/libavcodec/unary.h @@ -0,0 +1,56 @@ +/* + * copyright (c) 2004 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 + */ + +#ifndef AVCODEC_UNARY_H +#define AVCODEC_UNARY_H + +#include "get_bits.h" + +/** + * Get unary code of limited length + * @param gb GetBitContext + * @param[in] stop The bitstop value (unary code of 1's or 0's) + * @param[in] len Maximum length + * @return Unary length/index + */ +static inline int get_unary(GetBitContext *gb, int stop, int len) +{ + int i; + + for(i = 0; i < len && get_bits1(gb) != stop; i++); + return i; +} + +/** + * Get unary code terminated by a 0 with a maximum length of 33 + * @param gb GetBitContext + * @return Unary length/index + */ +static inline int get_unary_0_33(GetBitContext *gb) +{ + return get_unary(gb, 0, 33); +} + +static inline int get_unary_0_9(GetBitContext *gb) +{ + return get_unary(gb, 0, 9); +} + +#endif /* AVCODEC_UNARY_H */ diff --git a/ffmpeg/libavcodec/utils.c b/ffmpeg/libavcodec/utils.c new file mode 100644 index 0000000..c15b772 --- /dev/null +++ b/ffmpeg/libavcodec/utils.c @@ -0,0 +1,3095 @@ +/* + * utils for libavcodec + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + */ + +/** + * @file + * utils. + */ + +#include "config.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/channel_layout.h" +#include "libavutil/crc.h" +#include "libavutil/frame.h" +#include "libavutil/mathematics.h" +#include "libavutil/pixdesc.h" +#include "libavutil/imgutils.h" +#include "libavutil/samplefmt.h" +#include "libavutil/dict.h" +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "dsputil.h" +#include "libavutil/opt.h" +#include "thread.h" +#include "frame_thread_encoder.h" +#include "internal.h" +#include "bytestream.h" +#include "version.h" +#include +#include +#include +#include +#if CONFIG_ICONV +# include +#endif + +volatile int ff_avcodec_locked; +static int volatile entangled_thread_counter = 0; +static int (*ff_lockmgr_cb)(void **mutex, enum AVLockOp op); +static void *codec_mutex; +static void *avformat_mutex; + +void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) +{ + if (min_size < *size) + return ptr; + + min_size = FFMAX(17 * min_size / 16 + 32, min_size); + + ptr = av_realloc(ptr, min_size); + /* we could set this to the unmodified min_size but this is safer + * if the user lost the ptr and uses NULL now + */ + if (!ptr) + min_size = 0; + + *size = min_size; + + return ptr; +} + +static inline int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc) +{ + void **p = ptr; + if (min_size < *size) + return 0; + min_size = FFMAX(17 * min_size / 16 + 32, min_size); + av_free(*p); + *p = zero_realloc ? av_mallocz(min_size) : av_malloc(min_size); + if (!*p) + min_size = 0; + *size = min_size; + return 1; +} + +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size) +{ + ff_fast_malloc(ptr, size, min_size, 0); +} + +void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) +{ + uint8_t **p = ptr; + if (min_size > SIZE_MAX - FF_INPUT_BUFFER_PADDING_SIZE) { + av_freep(p); + *size = 0; + return; + } + if (!ff_fast_malloc(p, size, min_size + FF_INPUT_BUFFER_PADDING_SIZE, 1)) + memset(*p + min_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); +} + +void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size) +{ + uint8_t **p = ptr; + if (min_size > SIZE_MAX - FF_INPUT_BUFFER_PADDING_SIZE) { + av_freep(p); + *size = 0; + return; + } + if (!ff_fast_malloc(p, size, min_size + FF_INPUT_BUFFER_PADDING_SIZE, 1)) + memset(*p, 0, min_size + FF_INPUT_BUFFER_PADDING_SIZE); +} + +/* encoder management */ +static AVCodec *first_avcodec = NULL; + +AVCodec *av_codec_next(const AVCodec *c) +{ + if (c) + return c->next; + else + return first_avcodec; +} + +static void avcodec_init(void) +{ + static int initialized = 0; + + if (initialized != 0) + return; + initialized = 1; + + if (CONFIG_DSPUTIL) + ff_dsputil_static_init(); +} + +int av_codec_is_encoder(const AVCodec *codec) +{ + return codec && (codec->encode_sub || codec->encode2); +} + +int av_codec_is_decoder(const AVCodec *codec) +{ + return codec && codec->decode; +} + +void avcodec_register(AVCodec *codec) +{ + AVCodec **p; + avcodec_init(); + p = &first_avcodec; + while (*p != NULL) + p = &(*p)->next; + *p = codec; + codec->next = NULL; + + if (codec->init_static_data) + codec->init_static_data(codec); +} + +unsigned avcodec_get_edge_width(void) +{ + return EDGE_WIDTH; +} + +void avcodec_set_dimensions(AVCodecContext *s, int width, int height) +{ + s->coded_width = width; + s->coded_height = height; + s->width = -((-width ) >> s->lowres); + s->height = -((-height) >> s->lowres); +} + +#if (ARCH_ARM && HAVE_NEON) || ARCH_PPC || HAVE_MMX +# define STRIDE_ALIGN 16 +#else +# define STRIDE_ALIGN 8 +#endif + +void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, + int linesize_align[AV_NUM_DATA_POINTERS]) +{ + int i; + int w_align = 1; + int h_align = 1; + + switch (s->pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUYV422: + case AV_PIX_FMT_UYVY422: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV440P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GRAY8: + case AV_PIX_FMT_GRAY16BE: + case AV_PIX_FMT_GRAY16LE: + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUVJ422P: + case AV_PIX_FMT_YUVJ440P: + case AV_PIX_FMT_YUVJ444P: + case AV_PIX_FMT_YUVA420P: + case AV_PIX_FMT_YUVA422P: + case AV_PIX_FMT_YUVA444P: + case AV_PIX_FMT_YUV420P9LE: + case AV_PIX_FMT_YUV420P9BE: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV420P10BE: + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV420P12BE: + case AV_PIX_FMT_YUV420P14LE: + case AV_PIX_FMT_YUV420P14BE: + case AV_PIX_FMT_YUV422P9LE: + case AV_PIX_FMT_YUV422P9BE: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV422P10BE: + case AV_PIX_FMT_YUV422P12LE: + case AV_PIX_FMT_YUV422P12BE: + case AV_PIX_FMT_YUV422P14LE: + case AV_PIX_FMT_YUV422P14BE: + case AV_PIX_FMT_YUV444P9LE: + case AV_PIX_FMT_YUV444P9BE: + case AV_PIX_FMT_YUV444P10LE: + case AV_PIX_FMT_YUV444P10BE: + case AV_PIX_FMT_YUV444P12LE: + case AV_PIX_FMT_YUV444P12BE: + case AV_PIX_FMT_YUV444P14LE: + case AV_PIX_FMT_YUV444P14BE: + case AV_PIX_FMT_GBRP9LE: + case AV_PIX_FMT_GBRP9BE: + case AV_PIX_FMT_GBRP10LE: + case AV_PIX_FMT_GBRP10BE: + case AV_PIX_FMT_GBRP12LE: + case AV_PIX_FMT_GBRP12BE: + case AV_PIX_FMT_GBRP14LE: + case AV_PIX_FMT_GBRP14BE: + w_align = 16; //FIXME assume 16 pixel per macroblock + h_align = 16 * 2; // interlaced needs 2 macroblocks height + break; + case AV_PIX_FMT_YUV411P: + case AV_PIX_FMT_UYYVYY411: + w_align = 32; + h_align = 8; + break; + case AV_PIX_FMT_YUV410P: + if (s->codec_id == AV_CODEC_ID_SVQ1) { + w_align = 64; + h_align = 64; + } + break; + case AV_PIX_FMT_RGB555: + if (s->codec_id == AV_CODEC_ID_RPZA) { + w_align = 4; + h_align = 4; + } + break; + case AV_PIX_FMT_PAL8: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB8: + if (s->codec_id == AV_CODEC_ID_SMC || + s->codec_id == AV_CODEC_ID_CINEPAK) { + w_align = 4; + h_align = 4; + } + break; + case AV_PIX_FMT_BGR24: + if ((s->codec_id == AV_CODEC_ID_MSZH) || + (s->codec_id == AV_CODEC_ID_ZLIB)) { + w_align = 4; + h_align = 4; + } + break; + case AV_PIX_FMT_RGB24: + if (s->codec_id == AV_CODEC_ID_CINEPAK) { + w_align = 4; + h_align = 4; + } + break; + default: + w_align = 1; + h_align = 1; + break; + } + + if (s->codec_id == AV_CODEC_ID_IFF_ILBM || s->codec_id == AV_CODEC_ID_IFF_BYTERUN1) { + w_align = FFMAX(w_align, 8); + } + + *width = FFALIGN(*width, w_align); + *height = FFALIGN(*height, h_align); + if (s->codec_id == AV_CODEC_ID_H264 || s->lowres) + // some of the optimized chroma MC reads one line too much + // which is also done in mpeg decoders with lowres > 0 + *height += 2; + + for (i = 0; i < 4; i++) + linesize_align[i] = STRIDE_ALIGN; +} + +void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->pix_fmt); + int chroma_shift = desc->log2_chroma_w; + int linesize_align[AV_NUM_DATA_POINTERS]; + int align; + + avcodec_align_dimensions2(s, width, height, linesize_align); + align = FFMAX(linesize_align[0], linesize_align[3]); + linesize_align[1] <<= chroma_shift; + linesize_align[2] <<= chroma_shift; + align = FFMAX3(align, linesize_align[1], linesize_align[2]); + *width = FFALIGN(*width, align); +} + +int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, + enum AVSampleFormat sample_fmt, const uint8_t *buf, + int buf_size, int align) +{ + int ch, planar, needed_size, ret = 0; + + needed_size = av_samples_get_buffer_size(NULL, nb_channels, + frame->nb_samples, sample_fmt, + align); + if (buf_size < needed_size) + return AVERROR(EINVAL); + + planar = av_sample_fmt_is_planar(sample_fmt); + if (planar && nb_channels > AV_NUM_DATA_POINTERS) { + if (!(frame->extended_data = av_mallocz(nb_channels * + sizeof(*frame->extended_data)))) + return AVERROR(ENOMEM); + } else { + frame->extended_data = frame->data; + } + + if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0], + (uint8_t *)(intptr_t)buf, nb_channels, frame->nb_samples, + sample_fmt, align)) < 0) { + if (frame->extended_data != frame->data) + av_freep(&frame->extended_data); + return ret; + } + if (frame->extended_data != frame->data) { + for (ch = 0; ch < AV_NUM_DATA_POINTERS; ch++) + frame->data[ch] = frame->extended_data[ch]; + } + + return ret; +} + +static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) +{ + FramePool *pool = avctx->internal->pool; + int i, ret; + + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: { + AVPicture picture; + int size[4] = { 0 }; + int w = frame->width; + int h = frame->height; + int tmpsize, unaligned; + + if (pool->format == frame->format && + pool->width == frame->width && pool->height == frame->height) + return 0; + + avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); + + if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { + w += EDGE_WIDTH * 2; + h += EDGE_WIDTH * 2; + } + + do { + // NOTE: do not align linesizes individually, this breaks e.g. assumptions + // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 + av_image_fill_linesizes(picture.linesize, avctx->pix_fmt, w); + // increase alignment of w for next try (rhs gives the lowest bit set in w) + w += w & ~(w - 1); + + unaligned = 0; + for (i = 0; i < 4; i++) + unaligned |= picture.linesize[i] % pool->stride_align[i]; + } while (unaligned); + + tmpsize = av_image_fill_pointers(picture.data, avctx->pix_fmt, h, + NULL, picture.linesize); + if (tmpsize < 0) + return -1; + + for (i = 0; i < 3 && picture.data[i + 1]; i++) + size[i] = picture.data[i + 1] - picture.data[i]; + size[i] = tmpsize - (picture.data[i] - picture.data[0]); + + for (i = 0; i < 4; i++) { + av_buffer_pool_uninit(&pool->pools[i]); + pool->linesize[i] = picture.linesize[i]; + if (size[i]) { + pool->pools[i] = av_buffer_pool_init(size[i] + 16, NULL); + if (!pool->pools[i]) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + } + pool->format = frame->format; + pool->width = frame->width; + pool->height = frame->height; + + break; + } + case AVMEDIA_TYPE_AUDIO: { + int ch = av_frame_get_channels(frame); //av_get_channel_layout_nb_channels(frame->channel_layout); + int planar = av_sample_fmt_is_planar(frame->format); + int planes = planar ? ch : 1; + + if (pool->format == frame->format && pool->planes == planes && + pool->channels == ch && frame->nb_samples == pool->samples) + return 0; + + av_buffer_pool_uninit(&pool->pools[0]); + ret = av_samples_get_buffer_size(&pool->linesize[0], ch, + frame->nb_samples, frame->format, 0); + if (ret < 0) + goto fail; + + pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL); + if (!pool->pools[0]) { + ret = AVERROR(ENOMEM); + goto fail; + } + + pool->format = frame->format; + pool->planes = planes; + pool->channels = ch; + pool->samples = frame->nb_samples; + break; + } + default: av_assert0(0); + } + return 0; +fail: + for (i = 0; i < 4; i++) + av_buffer_pool_uninit(&pool->pools[i]); + pool->format = -1; + pool->planes = pool->channels = pool->samples = 0; + pool->width = pool->height = 0; + return ret; +} + +static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) +{ + FramePool *pool = avctx->internal->pool; + int planes = pool->planes; + int i; + + frame->linesize[0] = pool->linesize[0]; + + if (planes > AV_NUM_DATA_POINTERS) { + frame->extended_data = av_mallocz(planes * sizeof(*frame->extended_data)); + frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; + frame->extended_buf = av_mallocz(frame->nb_extended_buf * + sizeof(*frame->extended_buf)); + if (!frame->extended_data || !frame->extended_buf) { + av_freep(&frame->extended_data); + av_freep(&frame->extended_buf); + return AVERROR(ENOMEM); + } + } else { + frame->extended_data = frame->data; + av_assert0(frame->nb_extended_buf == 0); + } + + for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { + frame->buf[i] = av_buffer_pool_get(pool->pools[0]); + if (!frame->buf[i]) + goto fail; + frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; + } + for (i = 0; i < frame->nb_extended_buf; i++) { + frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); + if (!frame->extended_buf[i]) + goto fail; + frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; + } + + if (avctx->debug & FF_DEBUG_BUFFERS) + av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame); + + return 0; +fail: + av_frame_unref(frame); + return AVERROR(ENOMEM); +} + +static int video_get_buffer(AVCodecContext *s, AVFrame *pic) +{ + FramePool *pool = s->internal->pool; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); + int pixel_size = desc->comp[0].step_minus1 + 1; + int h_chroma_shift, v_chroma_shift; + int i; + + if (pic->data[0] != NULL) { + av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n"); + return -1; + } + + memset(pic->data, 0, sizeof(pic->data)); + pic->extended_data = pic->data; + + av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); + + for (i = 0; i < 4 && pool->pools[i]; i++) { + const int h_shift = i == 0 ? 0 : h_chroma_shift; + const int v_shift = i == 0 ? 0 : v_chroma_shift; + + pic->linesize[i] = pool->linesize[i]; + + pic->buf[i] = av_buffer_pool_get(pool->pools[i]); + if (!pic->buf[i]) + goto fail; + + // no edge if EDGE EMU or not planar YUV + if ((s->flags & CODEC_FLAG_EMU_EDGE) || !pool->pools[2]) + pic->data[i] = pic->buf[i]->data; + else { + pic->data[i] = pic->buf[i]->data + + FFALIGN((pic->linesize[i] * EDGE_WIDTH >> v_shift) + + (pixel_size * EDGE_WIDTH >> h_shift), pool->stride_align[i]); + } + } + for (; i < AV_NUM_DATA_POINTERS; i++) { + pic->data[i] = NULL; + pic->linesize[i] = 0; + } + if (pic->data[1] && !pic->data[2]) + avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt); + + if (s->debug & FF_DEBUG_BUFFERS) + av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic); + + return 0; +fail: + av_frame_unref(pic); + return AVERROR(ENOMEM); +} + +void avpriv_color_frame(AVFrame *frame, const int c[4]) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int p, y, x; + + av_assert0(desc->flags & PIX_FMT_PLANAR); + + for (p = 0; pnb_components; p++) { + uint8_t *dst = frame->data[p]; + int is_chroma = p == 1 || p == 2; + int bytes = -((-frame->width) >> (is_chroma ? desc->log2_chroma_w : 0)); + for (y = 0; y<-((-frame->height) >> (is_chroma ? desc->log2_chroma_h : 0)); y++){ + if (desc->comp[0].depth_minus1 >= 8) { + for (x = 0; xlinesize[p]; + } + } +} + +int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + int ret; + + if ((ret = update_frame_pool(avctx, frame)) < 0) + return ret; + +#if FF_API_GET_BUFFER + frame->type = FF_BUFFER_TYPE_INTERNAL; +#endif + + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + return video_get_buffer(avctx, frame); + case AVMEDIA_TYPE_AUDIO: + return audio_get_buffer(avctx, frame); + default: + return -1; + } +} + +int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame) +{ + if (avctx->pkt) { + frame->pkt_pts = avctx->pkt->pts; + av_frame_set_pkt_pos (frame, avctx->pkt->pos); + av_frame_set_pkt_duration(frame, avctx->pkt->duration); + av_frame_set_pkt_size (frame, avctx->pkt->size); + } else { + frame->pkt_pts = AV_NOPTS_VALUE; + av_frame_set_pkt_pos (frame, -1); + av_frame_set_pkt_duration(frame, 0); + av_frame_set_pkt_size (frame, -1); + } + frame->reordered_opaque = avctx->reordered_opaque; + + switch (avctx->codec->type) { + case AVMEDIA_TYPE_VIDEO: + if (!frame->width) + frame->width = avctx->width; + if (!frame->height) + frame->height = avctx->height; + if (frame->format < 0) + frame->format = avctx->pix_fmt; + if (!frame->sample_aspect_ratio.num) + frame->sample_aspect_ratio = avctx->sample_aspect_ratio; + break; + case AVMEDIA_TYPE_AUDIO: + if (!frame->sample_rate) + frame->sample_rate = avctx->sample_rate; + if (frame->format < 0) + frame->format = avctx->sample_fmt; + if (!frame->channel_layout) { + if (avctx->channel_layout) { + if (av_get_channel_layout_nb_channels(avctx->channel_layout) != + avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Inconsistent channel " + "configuration.\n"); + return AVERROR(EINVAL); + } + + frame->channel_layout = avctx->channel_layout; + } else { + if (avctx->channels > FF_SANE_NB_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "Too many channels: %d.\n", + avctx->channels); + return AVERROR(ENOSYS); + } + + frame->channel_layout = av_get_default_channel_layout(avctx->channels); + } + } + av_frame_set_channels(frame, avctx->channels); + break; + } + return 0; +} + +#if FF_API_GET_BUFFER +int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame) +{ + return avcodec_default_get_buffer2(avctx, frame, 0); +} + +typedef struct CompatReleaseBufPriv { + AVCodecContext avctx; + AVFrame frame; +} CompatReleaseBufPriv; + +static void compat_free_buffer(void *opaque, uint8_t *data) +{ + CompatReleaseBufPriv *priv = opaque; + if (priv->avctx.release_buffer) + priv->avctx.release_buffer(&priv->avctx, &priv->frame); + av_freep(&priv); +} + +static void compat_release_buffer(void *opaque, uint8_t *data) +{ + AVBufferRef *buf = opaque; + av_buffer_unref(&buf); +} +#endif + +static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + int ret; + + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0 || avctx->pix_fmt<0) { + av_log(avctx, AV_LOG_ERROR, "video_get_buffer: image parameters invalid\n"); + return AVERROR(EINVAL); + } + } + if ((ret = ff_init_buffer_info(avctx, frame)) < 0) + return ret; + +#if FF_API_GET_BUFFER + /* + * Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers. + * We wrap each plane in its own AVBuffer. Each of those has a reference to + * a dummy AVBuffer as its private data, unreffing it on free. + * When all the planes are freed, the dummy buffer's free callback calls + * release_buffer(). + */ + if (avctx->get_buffer) { + CompatReleaseBufPriv *priv = NULL; + AVBufferRef *dummy_buf = NULL; + int planes, i, ret; + + if (flags & AV_GET_BUFFER_FLAG_REF) + frame->reference = 1; + + ret = avctx->get_buffer(avctx, frame); + if (ret < 0) + return ret; + + /* return if the buffers are already set up + * this would happen e.g. when a custom get_buffer() calls + * avcodec_default_get_buffer + */ + if (frame->buf[0]) + return 0; + + priv = av_mallocz(sizeof(*priv)); + if (!priv) { + ret = AVERROR(ENOMEM); + goto fail; + } + priv->avctx = *avctx; + priv->frame = *frame; + + dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv, 0); + if (!dummy_buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + +#define WRAP_PLANE(ref_out, data, data_size) \ +do { \ + AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf); \ + if (!dummy_ref) { \ + ret = AVERROR(ENOMEM); \ + goto fail; \ + } \ + ref_out = av_buffer_create(data, data_size, compat_release_buffer, \ + dummy_ref, 0); \ + if (!ref_out) { \ + av_frame_unref(frame); \ + ret = AVERROR(ENOMEM); \ + goto fail; \ + } \ +} while (0) + + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + + planes = av_pix_fmt_count_planes(frame->format); + if (!desc || planes <= 0) { + ret = AVERROR(EINVAL); + goto fail; + } + + for (i = 0; i < planes; i++) { + int v_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; + int plane_size = (frame->height >> v_shift) * frame->linesize[i]; + + WRAP_PLANE(frame->buf[i], frame->data[i], plane_size); + } + } else { + int planar = av_sample_fmt_is_planar(frame->format); + planes = planar ? avctx->channels : 1; + + if (planes > FF_ARRAY_ELEMS(frame->buf)) { + frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf); + frame->extended_buf = av_malloc(sizeof(*frame->extended_buf) * + frame->nb_extended_buf); + if (!frame->extended_buf) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + + for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++) + WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]); + + for (i = 0; i < frame->nb_extended_buf; i++) + WRAP_PLANE(frame->extended_buf[i], + frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)], + frame->linesize[0]); + } + + av_buffer_unref(&dummy_buf); + + return 0; + +fail: + avctx->release_buffer(avctx, frame); + av_freep(&priv); + av_buffer_unref(&dummy_buf); + return ret; + } +#endif + + return avctx->get_buffer2(avctx, frame, flags); +} + +int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + int ret = get_buffer_internal(avctx, frame, flags); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; +} + +static int reget_buffer_internal(AVCodecContext *avctx, AVFrame *frame) +{ + AVFrame tmp; + int ret; + + av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO); + + if (frame->data[0] && (frame->width != avctx->width || frame->height != avctx->height || frame->format != avctx->pix_fmt)) { + av_log(avctx, AV_LOG_WARNING, "Picture changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s in reget buffer()\n", + frame->width, frame->height, av_get_pix_fmt_name(frame->format), avctx->width, avctx->height, av_get_pix_fmt_name(avctx->pix_fmt)); + av_frame_unref(frame); + } + + ff_init_buffer_info(avctx, frame); + + if (!frame->data[0]) + return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); + + if (av_frame_is_writable(frame)) + return 0; + + av_frame_move_ref(&tmp, frame); + + ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) { + av_frame_unref(&tmp); + return ret; + } + + av_image_copy(frame->data, frame->linesize, tmp.data, tmp.linesize, + frame->format, frame->width, frame->height); + + av_frame_unref(&tmp); + + return 0; +} + +int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame) +{ + int ret = reget_buffer_internal(avctx, frame); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); + return ret; +} + +#if FF_API_GET_BUFFER +void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) +{ + av_assert0(s->codec_type == AVMEDIA_TYPE_VIDEO); + + av_frame_unref(pic); +} + +int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic) +{ + av_assert0(0); +} +#endif + +int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size) +{ + int i; + + for (i = 0; i < count; i++) { + int r = func(c, (char *)arg + i * size); + if (ret) + ret[i] = r; + } + return 0; +} + +int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr), void *arg, int *ret, int count) +{ + int i; + + for (i = 0; i < count; i++) { + int r = func(c, arg, i, 0); + if (ret) + ret[i] = r; + } + return 0; +} + +static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + return desc->flags & PIX_FMT_HWACCEL; +} + +enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt) +{ + while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt)) + ++fmt; + return fmt[0]; +} + +void avcodec_get_frame_defaults(AVFrame *frame) +{ +#if LIBAVCODEC_VERSION_MAJOR >= 55 + // extended_data should explicitly be freed when needed, this code is unsafe currently + // also this is not compatible to the <55 ABI/API + if (frame->extended_data != frame->data && 0) + av_freep(&frame->extended_data); +#endif + + memset(frame, 0, sizeof(AVFrame)); + + frame->pts = + frame->pkt_dts = + frame->pkt_pts = AV_NOPTS_VALUE; + av_frame_set_best_effort_timestamp(frame, AV_NOPTS_VALUE); + av_frame_set_pkt_duration (frame, 0); + av_frame_set_pkt_pos (frame, -1); + av_frame_set_pkt_size (frame, -1); + frame->key_frame = 1; + frame->sample_aspect_ratio = (AVRational) {0, 1 }; + frame->format = -1; /* unknown */ + frame->extended_data = frame->data; +} + +AVFrame *avcodec_alloc_frame(void) +{ + AVFrame *frame = av_malloc(sizeof(AVFrame)); + + if (frame == NULL) + return NULL; + + frame->extended_data = NULL; + avcodec_get_frame_defaults(frame); + + return frame; +} + +void avcodec_free_frame(AVFrame **frame) +{ + AVFrame *f; + + if (!frame || !*frame) + return; + + f = *frame; + + if (f->extended_data != f->data) + av_freep(&f->extended_data); + + av_freep(frame); +} + +#define MAKE_ACCESSORS(str, name, type, field) \ + type av_##name##_get_##field(const str *s) { return s->field; } \ + void av_##name##_set_##field(str *s, type v) { s->field = v; } + +MAKE_ACCESSORS(AVCodecContext, codec, AVRational, pkt_timebase) +MAKE_ACCESSORS(AVCodecContext, codec, const AVCodecDescriptor *, codec_descriptor) + +static void avcodec_get_subtitle_defaults(AVSubtitle *sub) +{ + memset(sub, 0, sizeof(*sub)); + sub->pts = AV_NOPTS_VALUE; +} + +static int get_bit_rate(AVCodecContext *ctx) +{ + int bit_rate; + int bits_per_sample; + + switch (ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_SUBTITLE: + case AVMEDIA_TYPE_ATTACHMENT: + bit_rate = ctx->bit_rate; + break; + case AVMEDIA_TYPE_AUDIO: + bits_per_sample = av_get_bits_per_sample(ctx->codec_id); + bit_rate = bits_per_sample ? ctx->sample_rate * ctx->channels * bits_per_sample : ctx->bit_rate; + break; + default: + bit_rate = 0; + break; + } + return bit_rate; +} + +#if FF_API_AVCODEC_OPEN +int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) +{ + return avcodec_open2(avctx, codec, NULL); +} +#endif + +int attribute_align_arg ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) +{ + int ret = 0; + + ff_unlock_avcodec(); + + ret = avcodec_open2(avctx, codec, options); + + ff_lock_avcodec(avctx); + return ret; +} + +int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) +{ + int ret = 0; + AVDictionary *tmp = NULL; + + if (avcodec_is_open(avctx)) + return 0; + + if ((!codec && !avctx->codec)) { + av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2()\n"); + return AVERROR(EINVAL); + } + if ((codec && avctx->codec && codec != avctx->codec)) { + av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, " + "but %s passed to avcodec_open2()\n", avctx->codec->name, codec->name); + return AVERROR(EINVAL); + } + if (!codec) + codec = avctx->codec; + + if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE) + return AVERROR(EINVAL); + + if (options) + av_dict_copy(&tmp, *options, 0); + + ret = ff_lock_avcodec(avctx); + if (ret < 0) + return ret; + + avctx->internal = av_mallocz(sizeof(AVCodecInternal)); + if (!avctx->internal) { + ret = AVERROR(ENOMEM); + goto end; + } + + avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool)); + if (!avctx->internal->pool) { + ret = AVERROR(ENOMEM); + goto free_and_end; + } + + if (codec->priv_data_size > 0) { + if (!avctx->priv_data) { + avctx->priv_data = av_mallocz(codec->priv_data_size); + if (!avctx->priv_data) { + ret = AVERROR(ENOMEM); + goto end; + } + if (codec->priv_class) { + *(const AVClass **)avctx->priv_data = codec->priv_class; + av_opt_set_defaults(avctx->priv_data); + } + } + if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0) + goto free_and_end; + } else { + avctx->priv_data = NULL; + } + if ((ret = av_opt_set_dict(avctx, &tmp)) < 0) + goto free_and_end; + + // only call avcodec_set_dimensions() for non H.264/VP6F codecs so as not to overwrite previously setup dimensions + if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height && + (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F))) { + if (avctx->coded_width && avctx->coded_height) + avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height); + else if (avctx->width && avctx->height) + avcodec_set_dimensions(avctx, avctx->width, avctx->height); + } + + if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height) + && ( av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0 + || av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)) { + av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n"); + avcodec_set_dimensions(avctx, 0, 0); + } + + /* if the decoder init function was already called previously, + * free the already allocated subtitle_header before overwriting it */ + if (av_codec_is_decoder(codec)) + av_freep(&avctx->subtitle_header); + + if (avctx->channels > FF_SANE_NB_CHANNELS) { + ret = AVERROR(EINVAL); + goto free_and_end; + } + + avctx->codec = codec; + if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) && + avctx->codec_id == AV_CODEC_ID_NONE) { + avctx->codec_type = codec->type; + avctx->codec_id = codec->id; + } + if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type + && avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) { + av_log(avctx, AV_LOG_ERROR, "Codec type or id mismatches\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + avctx->frame_number = 0; + avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id); + + if (avctx->codec->capabilities & CODEC_CAP_EXPERIMENTAL && + avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + const char *codec_string = av_codec_is_encoder(codec) ? "encoder" : "decoder"; + AVCodec *codec2; + av_log(NULL, AV_LOG_ERROR, + "The %s '%s' is experimental but experimental codecs are not enabled, " + "add '-strict %d' if you want to use it.\n", + codec_string, codec->name, FF_COMPLIANCE_EXPERIMENTAL); + codec2 = av_codec_is_encoder(codec) ? avcodec_find_encoder(codec->id) : avcodec_find_decoder(codec->id); + if (!(codec2->capabilities & CODEC_CAP_EXPERIMENTAL)) + av_log(NULL, AV_LOG_ERROR, "Alternatively use the non experimental %s '%s'.\n", + codec_string, codec2->name); + ret = AVERROR_EXPERIMENTAL; + goto free_and_end; + } + + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && + (!avctx->time_base.num || !avctx->time_base.den)) { + avctx->time_base.num = 1; + avctx->time_base.den = avctx->sample_rate; + } + + if (!HAVE_THREADS) + av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n"); + + if (CONFIG_FRAME_THREAD_ENCODER) { + ff_unlock_avcodec(); //we will instanciate a few encoders thus kick the counter to prevent false detection of a problem + ret = ff_frame_thread_encoder_init(avctx, options ? *options : NULL); + ff_lock_avcodec(avctx); + if (ret < 0) + goto free_and_end; + } + + if (HAVE_THREADS && !avctx->thread_opaque + && !(avctx->internal->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME))) { + ret = ff_thread_init(avctx); + if (ret < 0) { + goto free_and_end; + } + } + if (!HAVE_THREADS && !(codec->capabilities & CODEC_CAP_AUTO_THREADS)) + avctx->thread_count = 1; + + if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) { + av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n", + avctx->codec->max_lowres); + ret = AVERROR(EINVAL); + goto free_and_end; + } + + if (av_codec_is_encoder(avctx->codec)) { + int i; + if (avctx->codec->sample_fmts) { + for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { + if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) + break; + if (avctx->channels == 1 && + av_get_planar_sample_fmt(avctx->sample_fmt) == + av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) { + avctx->sample_fmt = avctx->codec->sample_fmts[i]; + break; + } + } + if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt); + av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n", + (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf)); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } + if (avctx->codec->pix_fmts) { + for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) + if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) + break; + if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE + && !((avctx->codec_id == AV_CODEC_ID_MJPEG || avctx->codec_id == AV_CODEC_ID_LJPEG) + && avctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt); + av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is invalid or not supported\n", + (char *)av_x_if_null(av_get_pix_fmt_name(avctx->pix_fmt), buf)); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } + if (avctx->codec->supported_samplerates) { + for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) + if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) + break; + if (avctx->codec->supported_samplerates[i] == 0) { + av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", + avctx->sample_rate); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } + if (avctx->codec->channel_layouts) { + if (!avctx->channel_layout) { + av_log(avctx, AV_LOG_WARNING, "Channel layout not specified\n"); + } else { + for (i = 0; avctx->codec->channel_layouts[i] != 0; i++) + if (avctx->channel_layout == avctx->codec->channel_layouts[i]) + break; + if (avctx->codec->channel_layouts[i] == 0) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } + } + if (avctx->channel_layout && avctx->channels) { + int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + if (channels != avctx->channels) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_ERROR, + "Channel layout '%s' with %d channels does not match number of specified channels %d\n", + buf, channels, avctx->channels); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } else if (avctx->channel_layout) { + avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + } + if(avctx->codec_type == AVMEDIA_TYPE_VIDEO && + avctx->codec_id != AV_CODEC_ID_PNG // For mplayer + ) { + if (avctx->width <= 0 || avctx->height <= 0) { + av_log(avctx, AV_LOG_ERROR, "dimensions not set\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } + if ( (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) + && avctx->bit_rate>0 && avctx->bit_rate<1000) { + av_log(avctx, AV_LOG_WARNING, "Bitrate %d is extremely low, maybe you mean %dk\n", avctx->bit_rate, avctx->bit_rate); + } + + if (!avctx->rc_initial_buffer_occupancy) + avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3 / 4; + } + + avctx->pts_correction_num_faulty_pts = + avctx->pts_correction_num_faulty_dts = 0; + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; + + if ( avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME) + || avctx->internal->frame_thread_encoder)) { + ret = avctx->codec->init(avctx); + if (ret < 0) { + goto free_and_end; + } + } + + ret=0; + + if (av_codec_is_decoder(avctx->codec)) { + if (!avctx->bit_rate) + avctx->bit_rate = get_bit_rate(avctx); + /* validate channel layout from the decoder */ + if (avctx->channel_layout) { + int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + if (!avctx->channels) + avctx->channels = channels; + else if (channels != avctx->channels) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_WARNING, + "Channel layout '%s' with %d channels does not match specified number of channels %d: " + "ignoring specified channel layout\n", + buf, channels, avctx->channels); + avctx->channel_layout = 0; + } + } + if (avctx->channels && avctx->channels < 0 || + avctx->channels > FF_SANE_NB_CHANNELS) { + ret = AVERROR(EINVAL); + goto free_and_end; + } + if (avctx->sub_charenc) { + if (avctx->codec_type != AVMEDIA_TYPE_SUBTITLE) { + av_log(avctx, AV_LOG_ERROR, "Character encoding is only " + "supported with subtitles codecs\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } else if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) { + av_log(avctx, AV_LOG_WARNING, "Codec '%s' is bitmap-based, " + "subtitles character encoding will be ignored\n", + avctx->codec_descriptor->name); + avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_DO_NOTHING; + } else { + /* input character encoding is set for a text based subtitle + * codec at this point */ + if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_AUTOMATIC) + avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_PRE_DECODER; + + if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_PRE_DECODER) { +#if CONFIG_ICONV + iconv_t cd = iconv_open("UTF-8", avctx->sub_charenc); + if (cd == (iconv_t)-1) { + av_log(avctx, AV_LOG_ERROR, "Unable to open iconv context " + "with input character encoding \"%s\"\n", avctx->sub_charenc); + ret = AVERROR(errno); + goto free_and_end; + } + iconv_close(cd); +#else + av_log(avctx, AV_LOG_ERROR, "Character encoding subtitles " + "conversion needs a libavcodec built with iconv support " + "for this codec\n"); + ret = AVERROR(ENOSYS); + goto free_and_end; +#endif + } + } + } + } +end: + ff_unlock_avcodec(); + if (options) { + av_dict_free(options); + *options = tmp; + } + + return ret; +free_and_end: + av_dict_free(&tmp); + av_freep(&avctx->priv_data); + if (avctx->internal) + av_freep(&avctx->internal->pool); + av_freep(&avctx->internal); + avctx->codec = NULL; + goto end; +} + +int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size) +{ + if (size < 0 || avpkt->size < 0 || size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Size %d invalid\n", size); + return AVERROR(EINVAL); + } + + if (avctx) { + av_assert0(!avpkt->data || avpkt->data != avctx->internal->byte_buffer); + if (!avpkt->data || avpkt->size < size) { + av_fast_padded_malloc(&avctx->internal->byte_buffer, &avctx->internal->byte_buffer_size, size); + avpkt->data = avctx->internal->byte_buffer; + avpkt->size = avctx->internal->byte_buffer_size; + avpkt->destruct = NULL; + } + } + + if (avpkt->data) { + AVBufferRef *buf = avpkt->buf; +#if FF_API_DESTRUCT_PACKET + void *destruct = avpkt->destruct; +#endif + + if (avpkt->size < size) { + av_log(avctx, AV_LOG_ERROR, "User packet is too small (%d < %d)\n", avpkt->size, size); + return AVERROR(EINVAL); + } + + av_init_packet(avpkt); +#if FF_API_DESTRUCT_PACKET + avpkt->destruct = destruct; +#endif + avpkt->buf = buf; + avpkt->size = size; + return 0; + } else { + int ret = av_new_packet(avpkt, size); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet of size %d\n", size); + return ret; + } +} + +int ff_alloc_packet(AVPacket *avpkt, int size) +{ + return ff_alloc_packet2(NULL, avpkt, size); +} + +/** + * Pad last frame with silence. + */ +static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src) +{ + AVFrame *frame = NULL; + uint8_t *buf = NULL; + int ret; + + if (!(frame = avcodec_alloc_frame())) + return AVERROR(ENOMEM); + *frame = *src; + + if ((ret = av_samples_get_buffer_size(&frame->linesize[0], s->channels, + s->frame_size, s->sample_fmt, 0)) < 0) + goto fail; + + if (!(buf = av_malloc(ret))) { + ret = AVERROR(ENOMEM); + goto fail; + } + + frame->nb_samples = s->frame_size; + if ((ret = avcodec_fill_audio_frame(frame, s->channels, s->sample_fmt, + buf, ret, 0)) < 0) + goto fail; + if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0, + src->nb_samples, s->channels, s->sample_fmt)) < 0) + goto fail; + if ((ret = av_samples_set_silence(frame->extended_data, src->nb_samples, + frame->nb_samples - src->nb_samples, + s->channels, s->sample_fmt)) < 0) + goto fail; + + *dst = frame; + + return 0; + +fail: + if (frame->extended_data != frame->data) + av_freep(&frame->extended_data); + av_freep(&buf); + av_freep(&frame); + return ret; +} + +int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + AVFrame tmp; + AVFrame *padded_frame = NULL; + int ret; + AVPacket user_pkt = *avpkt; + int needs_realloc = !user_pkt.data; + + *got_packet_ptr = 0; + + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { + av_free_packet(avpkt); + av_init_packet(avpkt); + return 0; + } + + /* ensure that extended_data is properly set */ + if (frame && !frame->extended_data) { + if (av_sample_fmt_is_planar(avctx->sample_fmt) && + avctx->channels > AV_NUM_DATA_POINTERS) { + av_log(avctx, AV_LOG_ERROR, "Encoding to a planar sample format, " + "with more than %d channels, but extended_data is not set.\n", + AV_NUM_DATA_POINTERS); + return AVERROR(EINVAL); + } + av_log(avctx, AV_LOG_WARNING, "extended_data is not set.\n"); + + tmp = *frame; + tmp.extended_data = tmp.data; + frame = &tmp; + } + + /* check for valid frame size */ + if (frame) { + if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { + if (frame->nb_samples > avctx->frame_size) { + av_log(avctx, AV_LOG_ERROR, "more samples than frame size (avcodec_encode_audio2)\n"); + return AVERROR(EINVAL); + } + } else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { + if (frame->nb_samples < avctx->frame_size && + !avctx->internal->last_audio_frame) { + ret = pad_last_frame(avctx, &padded_frame, frame); + if (ret < 0) + return ret; + + frame = padded_frame; + avctx->internal->last_audio_frame = 1; + } + + if (frame->nb_samples != avctx->frame_size) { + av_log(avctx, AV_LOG_ERROR, "nb_samples (%d) != frame_size (%d) (avcodec_encode_audio2)\n", frame->nb_samples, avctx->frame_size); + ret = AVERROR(EINVAL); + goto end; + } + } + } + + ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); + if (!ret) { + if (*got_packet_ptr) { + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) { + if (avpkt->pts == AV_NOPTS_VALUE) + avpkt->pts = frame->pts; + if (!avpkt->duration) + avpkt->duration = ff_samples_to_time_base(avctx, + frame->nb_samples); + } + avpkt->dts = avpkt->pts; + } else { + avpkt->size = 0; + } + } + if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) { + needs_realloc = 0; + if (user_pkt.data) { + if (user_pkt.size >= avpkt->size) { + memcpy(user_pkt.data, avpkt->data, avpkt->size); + } else { + av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); + avpkt->size = user_pkt.size; + ret = -1; + } + avpkt->buf = user_pkt.buf; + avpkt->data = user_pkt.data; + avpkt->destruct = user_pkt.destruct; + } else { + if (av_dup_packet(avpkt) < 0) { + ret = AVERROR(ENOMEM); + } + } + } + + if (!ret) { + if (needs_realloc && avpkt->data) { + ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (ret >= 0) + avpkt->data = avpkt->buf->data; + } + + avctx->frame_number++; + } + + if (ret < 0 || !*got_packet_ptr) { + av_free_packet(avpkt); + av_init_packet(avpkt); + goto end; + } + + /* NOTE: if we add any audio encoders which output non-keyframe packets, + * this needs to be moved to the encoders, but for now we can do it + * here to simplify things */ + avpkt->flags |= AV_PKT_FLAG_KEY; + +end: + if (padded_frame) { + av_freep(&padded_frame->data[0]); + if (padded_frame->extended_data != padded_frame->data) + av_freep(&padded_frame->extended_data); + av_freep(&padded_frame); + } + + return ret; +} + +#if FF_API_OLD_ENCODE_AUDIO +int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const short *samples) +{ + AVPacket pkt; + AVFrame frame0 = { { 0 } }; + AVFrame *frame; + int ret, samples_size, got_packet; + + av_init_packet(&pkt); + pkt.data = buf; + pkt.size = buf_size; + + if (samples) { + frame = &frame0; + avcodec_get_frame_defaults(frame); + + if (avctx->frame_size) { + frame->nb_samples = avctx->frame_size; + } else { + /* if frame_size is not set, the number of samples must be + * calculated from the buffer size */ + int64_t nb_samples; + if (!av_get_bits_per_sample(avctx->codec_id)) { + av_log(avctx, AV_LOG_ERROR, "avcodec_encode_audio() does not " + "support this codec\n"); + return AVERROR(EINVAL); + } + nb_samples = (int64_t)buf_size * 8 / + (av_get_bits_per_sample(avctx->codec_id) * + avctx->channels); + if (nb_samples >= INT_MAX) + return AVERROR(EINVAL); + frame->nb_samples = nb_samples; + } + + /* it is assumed that the samples buffer is large enough based on the + * relevant parameters */ + samples_size = av_samples_get_buffer_size(NULL, avctx->channels, + frame->nb_samples, + avctx->sample_fmt, 1); + if ((ret = avcodec_fill_audio_frame(frame, avctx->channels, + avctx->sample_fmt, + (const uint8_t *)samples, + samples_size, 1)) < 0) + return ret; + + /* fabricate frame pts from sample count. + * this is needed because the avcodec_encode_audio() API does not have + * a way for the user to provide pts */ + if (avctx->sample_rate && avctx->time_base.num) + frame->pts = ff_samples_to_time_base(avctx, + avctx->internal->sample_count); + else + frame->pts = AV_NOPTS_VALUE; + avctx->internal->sample_count += frame->nb_samples; + } else { + frame = NULL; + } + + got_packet = 0; + ret = avcodec_encode_audio2(avctx, &pkt, frame, &got_packet); + if (!ret && got_packet && avctx->coded_frame) { + avctx->coded_frame->pts = pkt.pts; + avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + /* free any side data since we cannot return it */ + ff_packet_free_side_data(&pkt); + + if (frame && frame->extended_data != frame->data) + av_freep(&frame->extended_data); + + return ret ? ret : pkt.size; +} + +#endif + +#if FF_API_OLD_ENCODE_VIDEO +int attribute_align_arg avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVFrame *pict) +{ + AVPacket pkt; + int ret, got_packet = 0; + + if (buf_size < FF_MIN_BUFFER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n"); + return -1; + } + + av_init_packet(&pkt); + pkt.data = buf; + pkt.size = buf_size; + + ret = avcodec_encode_video2(avctx, &pkt, pict, &got_packet); + if (!ret && got_packet && avctx->coded_frame) { + avctx->coded_frame->pts = pkt.pts; + avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + + /* free any side data since we cannot return it */ + if (pkt.side_data_elems > 0) { + int i; + for (i = 0; i < pkt.side_data_elems; i++) + av_free(pkt.side_data[i].data); + av_freep(&pkt.side_data); + pkt.side_data_elems = 0; + } + + return ret ? ret : pkt.size; +} + +#endif + +int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + int ret; + AVPacket user_pkt = *avpkt; + int needs_realloc = !user_pkt.data; + + *got_packet_ptr = 0; + + if(CONFIG_FRAME_THREAD_ENCODER && + avctx->internal->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME)) + return ff_thread_video_encode_frame(avctx, avpkt, frame, got_packet_ptr); + + if ((avctx->flags&CODEC_FLAG_PASS1) && avctx->stats_out) + avctx->stats_out[0] = '\0'; + + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { + av_free_packet(avpkt); + av_init_packet(avpkt); + avpkt->size = 0; + return 0; + } + + if (av_image_check_size(avctx->width, avctx->height, 0, avctx)) + return AVERROR(EINVAL); + + av_assert0(avctx->codec->encode2); + + ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); + av_assert0(ret <= 0); + + if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) { + needs_realloc = 0; + if (user_pkt.data) { + if (user_pkt.size >= avpkt->size) { + memcpy(user_pkt.data, avpkt->data, avpkt->size); + } else { + av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); + avpkt->size = user_pkt.size; + ret = -1; + } + avpkt->buf = user_pkt.buf; + avpkt->data = user_pkt.data; + avpkt->destruct = user_pkt.destruct; + } else { + if (av_dup_packet(avpkt) < 0) { + ret = AVERROR(ENOMEM); + } + } + } + + if (!ret) { + if (!*got_packet_ptr) + avpkt->size = 0; + else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) + avpkt->pts = avpkt->dts = frame->pts; + + if (needs_realloc && avpkt->data) { + ret = av_buffer_realloc(&avpkt->buf, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (ret >= 0) + avpkt->data = avpkt->buf->data; + } + + avctx->frame_number++; + } + + if (ret < 0 || !*got_packet_ptr) + av_free_packet(avpkt); + + emms_c(); + return ret; +} + +int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, + const AVSubtitle *sub) +{ + int ret; + if (sub->start_display_time) { + av_log(avctx, AV_LOG_ERROR, "start_display_time must be 0.\n"); + return -1; + } + + ret = avctx->codec->encode_sub(avctx, buf, buf_size, sub); + avctx->frame_number++; + return ret; +} + +/** + * Attempt to guess proper monotonic timestamps for decoded video frames + * which might have incorrect times. Input timestamps may wrap around, in + * which case the output will as well. + * + * @param pts the pts field of the decoded AVPacket, as passed through + * AVFrame.pkt_pts + * @param dts the dts field of the decoded AVPacket + * @return one of the input values, may be AV_NOPTS_VALUE + */ +static int64_t guess_correct_pts(AVCodecContext *ctx, + int64_t reordered_pts, int64_t dts) +{ + int64_t pts = AV_NOPTS_VALUE; + + if (dts != AV_NOPTS_VALUE) { + ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts; + ctx->pts_correction_last_dts = dts; + } + if (reordered_pts != AV_NOPTS_VALUE) { + ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts; + ctx->pts_correction_last_pts = reordered_pts; + } + if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE) + && reordered_pts != AV_NOPTS_VALUE) + pts = reordered_pts; + else + pts = dts; + + return pts; +} + +static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt) +{ + int size = 0; + const uint8_t *data; + uint32_t flags; + + if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) + return; + + data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size); + if (!data || size < 4) + return; + flags = bytestream_get_le32(&data); + size -= 4; + if (size < 4) /* Required for any of the changes */ + return; + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { + avctx->channels = bytestream_get_le32(&data); + size -= 4; + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) { + if (size < 8) + return; + avctx->channel_layout = bytestream_get_le64(&data); + size -= 8; + } + if (size < 4) + return; + if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { + avctx->sample_rate = bytestream_get_le32(&data); + size -= 4; + } + if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) { + if (size < 8) + return; + avctx->width = bytestream_get_le32(&data); + avctx->height = bytestream_get_le32(&data); + avcodec_set_dimensions(avctx, avctx->width, avctx->height); + size -= 8; + } +} + +static int add_metadata_from_side_data(AVCodecContext *avctx, AVFrame *frame) +{ + int size, ret = 0; + const uint8_t *side_metadata; + const uint8_t *end; + + side_metadata = av_packet_get_side_data(avctx->pkt, + AV_PKT_DATA_STRINGS_METADATA, &size); + if (!side_metadata) + goto end; + end = side_metadata + size; + while (side_metadata < end) { + const uint8_t *key = side_metadata; + const uint8_t *val = side_metadata + strlen(key) + 1; + int ret = av_dict_set(avpriv_frame_get_metadatap(frame), key, val, 0); + if (ret < 0) + break; + side_metadata = val + strlen(val) + 1; + } +end: + return ret; +} + +int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, + int *got_picture_ptr, + const AVPacket *avpkt) +{ + AVCodecInternal *avci = avctx->internal; + int ret; + // copy to ensure we do not change avpkt + AVPacket tmp = *avpkt; + + if (avctx->codec->type != AVMEDIA_TYPE_VIDEO) { + av_log(avctx, AV_LOG_ERROR, "Invalid media type for video\n"); + return AVERROR(EINVAL); + } + + *got_picture_ptr = 0; + if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx)) + return AVERROR(EINVAL); + + avcodec_get_frame_defaults(picture); + + if (!avctx->refcounted_frames) + av_frame_unref(&avci->to_free); + + if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) { + int did_split = av_packet_split_side_data(&tmp); + apply_param_change(avctx, &tmp); + avctx->pkt = &tmp; + if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) + ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr, + &tmp); + else { + ret = avctx->codec->decode(avctx, picture, got_picture_ptr, + &tmp); + picture->pkt_dts = avpkt->dts; + + if(!avctx->has_b_frames){ + av_frame_set_pkt_pos(picture, avpkt->pos); + } + //FIXME these should be under if(!avctx->has_b_frames) + /* get_buffer is supposed to set frame parameters */ + if (!(avctx->codec->capabilities & CODEC_CAP_DR1)) { + if (!picture->sample_aspect_ratio.num) picture->sample_aspect_ratio = avctx->sample_aspect_ratio; + if (!picture->width) picture->width = avctx->width; + if (!picture->height) picture->height = avctx->height; + if (picture->format == AV_PIX_FMT_NONE) picture->format = avctx->pix_fmt; + } + } + add_metadata_from_side_data(avctx, picture); + + emms_c(); //needed to avoid an emms_c() call before every return; + + avctx->pkt = NULL; + if (did_split) { + ff_packet_free_side_data(&tmp); + if(ret == tmp.size) + ret = avpkt->size; + } + + if (ret < 0 && picture->data[0]) + av_frame_unref(picture); + + if (*got_picture_ptr) { + if (!avctx->refcounted_frames) { + avci->to_free = *picture; + avci->to_free.extended_data = avci->to_free.data; + } + + avctx->frame_number++; + av_frame_set_best_effort_timestamp(picture, + guess_correct_pts(avctx, + picture->pkt_pts, + picture->pkt_dts)); + } + } else + ret = 0; + + /* many decoders assign whole AVFrames, thus overwriting extended_data; + * make sure it's set correctly */ + picture->extended_data = picture->data; + + return ret; +} + +#if FF_API_OLD_DECODE_AUDIO +int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, + int *frame_size_ptr, + AVPacket *avpkt) +{ + AVFrame frame = { { 0 } }; + int ret, got_frame = 0; + + if (avctx->get_buffer != avcodec_default_get_buffer) { + av_log(avctx, AV_LOG_ERROR, "Custom get_buffer() for use with" + "avcodec_decode_audio3() detected. Overriding with avcodec_default_get_buffer\n"); + av_log(avctx, AV_LOG_ERROR, "Please port your application to " + "avcodec_decode_audio4()\n"); + avctx->get_buffer = avcodec_default_get_buffer; + avctx->release_buffer = avcodec_default_release_buffer; + } + + ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt); + + if (ret >= 0 && got_frame) { + int ch, plane_size; + int planar = av_sample_fmt_is_planar(avctx->sample_fmt); + int data_size = av_samples_get_buffer_size(&plane_size, avctx->channels, + frame.nb_samples, + avctx->sample_fmt, 1); + if (*frame_size_ptr < data_size) { + av_log(avctx, AV_LOG_ERROR, "output buffer size is too small for " + "the current frame (%d < %d)\n", *frame_size_ptr, data_size); + return AVERROR(EINVAL); + } + + memcpy(samples, frame.extended_data[0], plane_size); + + if (planar && avctx->channels > 1) { + uint8_t *out = ((uint8_t *)samples) + plane_size; + for (ch = 1; ch < avctx->channels; ch++) { + memcpy(out, frame.extended_data[ch], plane_size); + out += plane_size; + } + } + *frame_size_ptr = data_size; + } else { + *frame_size_ptr = 0; + } + return ret; +} + +#endif + +int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, + AVFrame *frame, + int *got_frame_ptr, + const AVPacket *avpkt) +{ + AVCodecInternal *avci = avctx->internal; + int planar, channels; + int ret = 0; + + *got_frame_ptr = 0; + + if (!avpkt->data && avpkt->size) { + av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); + return AVERROR(EINVAL); + } + if (avctx->codec->type != AVMEDIA_TYPE_AUDIO) { + av_log(avctx, AV_LOG_ERROR, "Invalid media type for audio\n"); + return AVERROR(EINVAL); + } + + avcodec_get_frame_defaults(frame); + + if (!avctx->refcounted_frames) + av_frame_unref(&avci->to_free); + + if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) { + uint8_t *side; + int side_size; + // copy to ensure we do not change avpkt + AVPacket tmp = *avpkt; + int did_split = av_packet_split_side_data(&tmp); + apply_param_change(avctx, &tmp); + + avctx->pkt = &tmp; + ret = avctx->codec->decode(avctx, frame, got_frame_ptr, &tmp); + if (ret >= 0 && *got_frame_ptr) { + add_metadata_from_side_data(avctx, frame); + avctx->frame_number++; + frame->pkt_dts = avpkt->dts; + av_frame_set_best_effort_timestamp(frame, + guess_correct_pts(avctx, + frame->pkt_pts, + frame->pkt_dts)); + if (frame->format == AV_SAMPLE_FMT_NONE) + frame->format = avctx->sample_fmt; + if (!frame->channel_layout) + frame->channel_layout = avctx->channel_layout; + if (!av_frame_get_channels(frame)) + av_frame_set_channels(frame, avctx->channels); + if (!frame->sample_rate) + frame->sample_rate = avctx->sample_rate; + if (!avctx->refcounted_frames) { + avci->to_free = *frame; + avci->to_free.extended_data = avci->to_free.data; + } + } + + side= av_packet_get_side_data(avctx->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size); + if(side && side_size>=10) { + avctx->internal->skip_samples = AV_RL32(side); + av_log(avctx, AV_LOG_DEBUG, "skip %d samples due to side data\n", + avctx->internal->skip_samples); + } + if (avctx->internal->skip_samples && *got_frame_ptr) { + if(frame->nb_samples <= avctx->internal->skip_samples){ + *got_frame_ptr = 0; + avctx->internal->skip_samples -= frame->nb_samples; + av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n", + avctx->internal->skip_samples); + } else { + av_samples_copy(frame->extended_data, frame->extended_data, 0, avctx->internal->skip_samples, + frame->nb_samples - avctx->internal->skip_samples, avctx->channels, frame->format); + if(avctx->pkt_timebase.num && avctx->sample_rate) { + int64_t diff_ts = av_rescale_q(avctx->internal->skip_samples, + (AVRational){1, avctx->sample_rate}, + avctx->pkt_timebase); + if(frame->pkt_pts!=AV_NOPTS_VALUE) + frame->pkt_pts += diff_ts; + if(frame->pkt_dts!=AV_NOPTS_VALUE) + frame->pkt_dts += diff_ts; + if (av_frame_get_pkt_duration(frame) >= diff_ts) + av_frame_set_pkt_duration(frame, av_frame_get_pkt_duration(frame) - diff_ts); + } else { + av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n"); + } + av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n", + avctx->internal->skip_samples, frame->nb_samples); + frame->nb_samples -= avctx->internal->skip_samples; + avctx->internal->skip_samples = 0; + } + } + + avctx->pkt = NULL; + if (did_split) { + ff_packet_free_side_data(&tmp); + if(ret == tmp.size) + ret = avpkt->size; + } + + if (ret < 0 && frame->data[0]) + av_frame_unref(frame); + } + + /* many decoders assign whole AVFrames, thus overwriting extended_data; + * make sure it's set correctly; assume decoders that actually use + * extended_data are doing it correctly */ + if (*got_frame_ptr) { + planar = av_sample_fmt_is_planar(frame->format); + channels = av_frame_get_channels(frame); + if (!(planar && channels > AV_NUM_DATA_POINTERS)) + frame->extended_data = frame->data; + } else { + frame->extended_data = NULL; + } + + return ret; +} + +#define UTF8_MAX_BYTES 4 /* 5 and 6 bytes sequences should not be used */ +static int recode_subtitle(AVCodecContext *avctx, + AVPacket *outpkt, const AVPacket *inpkt) +{ +#if CONFIG_ICONV + iconv_t cd = (iconv_t)-1; + int ret = 0; + char *inb, *outb; + size_t inl, outl; + AVPacket tmp; +#endif + + if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_PRE_DECODER) + return 0; + +#if CONFIG_ICONV + cd = iconv_open("UTF-8", avctx->sub_charenc); + av_assert0(cd != (iconv_t)-1); + + inb = inpkt->data; + inl = inpkt->size; + + if (inl >= INT_MAX / UTF8_MAX_BYTES - FF_INPUT_BUFFER_PADDING_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Subtitles packet is too big for recoding\n"); + ret = AVERROR(ENOMEM); + goto end; + } + + ret = av_new_packet(&tmp, inl * UTF8_MAX_BYTES); + if (ret < 0) + goto end; + outpkt->buf = tmp.buf; + outpkt->data = tmp.data; + outpkt->size = tmp.size; + outb = outpkt->data; + outl = outpkt->size; + + if (iconv(cd, &inb, &inl, &outb, &outl) == (size_t)-1 || + iconv(cd, NULL, NULL, &outb, &outl) == (size_t)-1 || + outl >= outpkt->size || inl != 0) { + av_log(avctx, AV_LOG_ERROR, "Unable to recode subtitle event \"%s\" " + "from %s to UTF-8\n", inpkt->data, avctx->sub_charenc); + av_free_packet(&tmp); + ret = AVERROR(errno); + goto end; + } + outpkt->size -= outl; + outpkt->data[outpkt->size - 1] = '\0'; + +end: + if (cd != (iconv_t)-1) + iconv_close(cd); + return ret; +#else + av_assert0(!"requesting subtitles recoding without iconv"); +#endif +} + +int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt) +{ + int ret = 0; + + if (avctx->codec->type != AVMEDIA_TYPE_SUBTITLE) { + av_log(avctx, AV_LOG_ERROR, "Invalid media type for subtitles\n"); + return AVERROR(EINVAL); + } + + *got_sub_ptr = 0; + avcodec_get_subtitle_defaults(sub); + + if (avpkt->size) { + AVPacket pkt_recoded; + AVPacket tmp = *avpkt; + int did_split = av_packet_split_side_data(&tmp); + //apply_param_change(avctx, &tmp); + + pkt_recoded = tmp; + ret = recode_subtitle(avctx, &pkt_recoded, &tmp); + if (ret < 0) { + *got_sub_ptr = 0; + } else { + avctx->pkt = &pkt_recoded; + + if (avctx->pkt_timebase.den && avpkt->pts != AV_NOPTS_VALUE) + sub->pts = av_rescale_q(avpkt->pts, + avctx->pkt_timebase, AV_TIME_BASE_Q); + ret = avctx->codec->decode(avctx, sub, got_sub_ptr, &pkt_recoded); + av_assert1((ret >= 0) >= !!*got_sub_ptr && + !!*got_sub_ptr >= !!sub->num_rects); + if (tmp.data != pkt_recoded.data) { // did we recode? + /* prevent from destroying side data from original packet */ + pkt_recoded.side_data = NULL; + pkt_recoded.side_data_elems = 0; + + av_free_packet(&pkt_recoded); + } + sub->format = !(avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB); + avctx->pkt = NULL; + } + + if (did_split) { + ff_packet_free_side_data(&tmp); + if(ret == tmp.size) + ret = avpkt->size; + } + + if (*got_sub_ptr) + avctx->frame_number++; + } + + return ret; +} + +void avsubtitle_free(AVSubtitle *sub) +{ + int i; + + for (i = 0; i < sub->num_rects; i++) { + av_freep(&sub->rects[i]->pict.data[0]); + av_freep(&sub->rects[i]->pict.data[1]); + av_freep(&sub->rects[i]->pict.data[2]); + av_freep(&sub->rects[i]->pict.data[3]); + av_freep(&sub->rects[i]->text); + av_freep(&sub->rects[i]->ass); + av_freep(&sub->rects[i]); + } + + av_freep(&sub->rects); + + memset(sub, 0, sizeof(AVSubtitle)); +} + +av_cold int ff_codec_close_recursive(AVCodecContext *avctx) +{ + int ret = 0; + + ff_unlock_avcodec(); + + ret = avcodec_close(avctx); + + ff_lock_avcodec(NULL); + return ret; +} + +av_cold int avcodec_close(AVCodecContext *avctx) +{ + int ret = ff_lock_avcodec(avctx); + if (ret < 0) + return ret; + + if (avcodec_is_open(avctx)) { + FramePool *pool = avctx->internal->pool; + int i; + if (CONFIG_FRAME_THREAD_ENCODER && + avctx->internal->frame_thread_encoder && avctx->thread_count > 1) { + ff_unlock_avcodec(); + ff_frame_thread_encoder_free(avctx); + ff_lock_avcodec(avctx); + } + if (HAVE_THREADS && avctx->thread_opaque) + ff_thread_free(avctx); + if (avctx->codec && avctx->codec->close) + avctx->codec->close(avctx); + avctx->coded_frame = NULL; + avctx->internal->byte_buffer_size = 0; + av_freep(&avctx->internal->byte_buffer); + if (!avctx->refcounted_frames) + av_frame_unref(&avctx->internal->to_free); + for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) + av_buffer_pool_uninit(&pool->pools[i]); + av_freep(&avctx->internal->pool); + av_freep(&avctx->internal); + } + + if (avctx->priv_data && avctx->codec && avctx->codec->priv_class) + av_opt_free(avctx->priv_data); + av_opt_free(avctx); + av_freep(&avctx->priv_data); + if (av_codec_is_encoder(avctx->codec)) + av_freep(&avctx->extradata); + avctx->codec = NULL; + avctx->active_thread_type = 0; + + ff_unlock_avcodec(); + return 0; +} + +static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) +{ + switch(id){ + //This is for future deprecatec codec ids, its empty since + //last major bump but will fill up again over time, please don't remove it +// case AV_CODEC_ID_UTVIDEO_DEPRECATED: return AV_CODEC_ID_UTVIDEO; + case AV_CODEC_ID_OPUS_DEPRECATED: return AV_CODEC_ID_OPUS; + case AV_CODEC_ID_TAK_DEPRECATED : return AV_CODEC_ID_TAK; + default : return id; + } +} + +static AVCodec *find_encdec(enum AVCodecID id, int encoder) +{ + AVCodec *p, *experimental = NULL; + p = first_avcodec; + id= remap_deprecated_codec_id(id); + while (p) { + if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) && + p->id == id) { + if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { + experimental = p; + } else + return p; + } + p = p->next; + } + return experimental; +} + +AVCodec *avcodec_find_encoder(enum AVCodecID id) +{ + return find_encdec(id, 1); +} + +AVCodec *avcodec_find_encoder_by_name(const char *name) +{ + AVCodec *p; + if (!name) + return NULL; + p = first_avcodec; + while (p) { + if (av_codec_is_encoder(p) && strcmp(name, p->name) == 0) + return p; + p = p->next; + } + return NULL; +} + +AVCodec *avcodec_find_decoder(enum AVCodecID id) +{ + return find_encdec(id, 0); +} + +AVCodec *avcodec_find_decoder_by_name(const char *name) +{ + AVCodec *p; + if (!name) + return NULL; + p = first_avcodec; + while (p) { + if (av_codec_is_decoder(p) && strcmp(name, p->name) == 0) + return p; + p = p->next; + } + return NULL; +} + +const char *avcodec_get_name(enum AVCodecID id) +{ + const AVCodecDescriptor *cd; + AVCodec *codec; + + if (id == AV_CODEC_ID_NONE) + return "none"; + cd = avcodec_descriptor_get(id); + if (cd) + return cd->name; + av_log(NULL, AV_LOG_WARNING, "Codec 0x%x is not in the full list.\n", id); + codec = avcodec_find_decoder(id); + if (codec) + return codec->name; + codec = avcodec_find_encoder(id); + if (codec) + return codec->name; + return "unknown_codec"; +} + +size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag) +{ + int i, len, ret = 0; + +#define TAG_PRINT(x) \ + (((x) >= '0' && (x) <= '9') || \ + ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || \ + ((x) == '.' || (x) == ' ' || (x) == '-' || (x) == '_')) + + for (i = 0; i < 4; i++) { + len = snprintf(buf, buf_size, + TAG_PRINT(codec_tag & 0xFF) ? "%c" : "[%d]", codec_tag & 0xFF); + buf += len; + buf_size = buf_size > len ? buf_size - len : 0; + ret += len; + codec_tag >>= 8; + } + return ret; +} + +void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) +{ + const char *codec_type; + const char *codec_name; + const char *profile = NULL; + const AVCodec *p; + int bitrate; + AVRational display_aspect_ratio; + + if (!buf || buf_size <= 0) + return; + codec_type = av_get_media_type_string(enc->codec_type); + codec_name = avcodec_get_name(enc->codec_id); + if (enc->profile != FF_PROFILE_UNKNOWN) { + if (enc->codec) + p = enc->codec; + else + p = encode ? avcodec_find_encoder(enc->codec_id) : + avcodec_find_decoder(enc->codec_id); + if (p) + profile = av_get_profile_name(p, enc->profile); + } + + snprintf(buf, buf_size, "%s: %s%s", codec_type ? codec_type : "unknown", + codec_name, enc->mb_decision ? " (hq)" : ""); + buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */ + if (profile) + snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); + if (enc->codec_tag) { + char tag_buf[32]; + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " (%s / 0x%04X)", tag_buf, enc->codec_tag); + } + + switch (enc->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (enc->pix_fmt != AV_PIX_FMT_NONE) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %s", + av_get_pix_fmt_name(enc->pix_fmt)); + if (enc->bits_per_raw_sample && + enc->bits_per_raw_sample <= av_pix_fmt_desc_get(enc->pix_fmt)->comp[0].depth_minus1) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " (%d bpc)", enc->bits_per_raw_sample); + } + if (enc->width) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %dx%d", + enc->width, enc->height); + if (enc->sample_aspect_ratio.num) { + av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, + enc->width * enc->sample_aspect_ratio.num, + enc->height * enc->sample_aspect_ratio.den, + 1024 * 1024); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " [SAR %d:%d DAR %d:%d]", + enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den, + display_aspect_ratio.num, display_aspect_ratio.den); + } + if (av_log_get_level() >= AV_LOG_DEBUG) { + int g = av_gcd(enc->time_base.num, enc->time_base.den); + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d/%d", + enc->time_base.num / g, enc->time_base.den / g); + } + } + if (encode) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", q=%d-%d", enc->qmin, enc->qmax); + } + break; + case AVMEDIA_TYPE_AUDIO: + if (enc->sample_rate) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d Hz", enc->sample_rate); + } + av_strlcat(buf, ", ", buf_size); + av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout); + if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %s", av_get_sample_fmt_name(enc->sample_fmt)); + } + break; + case AVMEDIA_TYPE_DATA: + if (av_log_get_level() >= AV_LOG_DEBUG) { + int g = av_gcd(enc->time_base.num, enc->time_base.den); + if (g) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d/%d", + enc->time_base.num / g, enc->time_base.den / g); + } + break; + default: + return; + } + if (encode) { + if (enc->flags & CODEC_FLAG_PASS1) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", pass 1"); + if (enc->flags & CODEC_FLAG_PASS2) + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", pass 2"); + } + bitrate = get_bit_rate(enc); + if (bitrate != 0) { + snprintf(buf + strlen(buf), buf_size - strlen(buf), + ", %d kb/s", bitrate / 1000); + } +} + +const char *av_get_profile_name(const AVCodec *codec, int profile) +{ + const AVProfile *p; + if (profile == FF_PROFILE_UNKNOWN || !codec->profiles) + return NULL; + + for (p = codec->profiles; p->profile != FF_PROFILE_UNKNOWN; p++) + if (p->profile == profile) + return p->name; + + return NULL; +} + +unsigned avcodec_version(void) +{ +// av_assert0(AV_CODEC_ID_V410==164); + av_assert0(AV_CODEC_ID_PCM_S8_PLANAR==65563); + av_assert0(AV_CODEC_ID_ADPCM_G722==69660); +// av_assert0(AV_CODEC_ID_BMV_AUDIO==86071); + av_assert0(AV_CODEC_ID_SRT==94216); + av_assert0(LIBAVCODEC_VERSION_MICRO >= 100); + + av_assert0(CODEC_ID_CLLC == AV_CODEC_ID_CLLC); + av_assert0(CODEC_ID_PCM_S8_PLANAR == AV_CODEC_ID_PCM_S8_PLANAR); + av_assert0(CODEC_ID_ADPCM_IMA_APC == AV_CODEC_ID_ADPCM_IMA_APC); + av_assert0(CODEC_ID_ILBC == AV_CODEC_ID_ILBC); + av_assert0(CODEC_ID_SRT == AV_CODEC_ID_SRT); + return LIBAVCODEC_VERSION_INT; +} + +const char *avcodec_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *avcodec_license(void) +{ +#define LICENSE_PREFIX "libavcodec license: " + return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; +} + +void avcodec_flush_buffers(AVCodecContext *avctx) +{ + if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) + ff_thread_flush(avctx); + else if (avctx->codec->flush) + avctx->codec->flush(avctx); + + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; +} + +int av_get_exact_bits_per_sample(enum AVCodecID codec_id) +{ + switch (codec_id) { + case AV_CODEC_ID_8SVX_EXP: + case AV_CODEC_ID_8SVX_FIB: + case AV_CODEC_ID_ADPCM_CT: + case AV_CODEC_ID_ADPCM_IMA_APC: + case AV_CODEC_ID_ADPCM_IMA_EA_SEAD: + case AV_CODEC_ID_ADPCM_IMA_OKI: + case AV_CODEC_ID_ADPCM_IMA_WS: + case AV_CODEC_ID_ADPCM_G722: + case AV_CODEC_ID_ADPCM_YAMAHA: + return 4; + case AV_CODEC_ID_PCM_ALAW: + case AV_CODEC_ID_PCM_MULAW: + case AV_CODEC_ID_PCM_S8: + case AV_CODEC_ID_PCM_S8_PLANAR: + case AV_CODEC_ID_PCM_U8: + case AV_CODEC_ID_PCM_ZORK: + return 8; + case AV_CODEC_ID_PCM_S16BE: + case AV_CODEC_ID_PCM_S16BE_PLANAR: + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_S16LE_PLANAR: + case AV_CODEC_ID_PCM_U16BE: + case AV_CODEC_ID_PCM_U16LE: + return 16; + case AV_CODEC_ID_PCM_S24DAUD: + case AV_CODEC_ID_PCM_S24BE: + case AV_CODEC_ID_PCM_S24LE: + case AV_CODEC_ID_PCM_S24LE_PLANAR: + case AV_CODEC_ID_PCM_U24BE: + case AV_CODEC_ID_PCM_U24LE: + return 24; + case AV_CODEC_ID_PCM_S32BE: + case AV_CODEC_ID_PCM_S32LE: + case AV_CODEC_ID_PCM_S32LE_PLANAR: + case AV_CODEC_ID_PCM_U32BE: + case AV_CODEC_ID_PCM_U32LE: + case AV_CODEC_ID_PCM_F32BE: + case AV_CODEC_ID_PCM_F32LE: + return 32; + case AV_CODEC_ID_PCM_F64BE: + case AV_CODEC_ID_PCM_F64LE: + return 64; + default: + return 0; + } +} + +enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be) +{ + static const enum AVCodecID map[AV_SAMPLE_FMT_NB][2] = { + [AV_SAMPLE_FMT_U8 ] = { AV_CODEC_ID_PCM_U8, AV_CODEC_ID_PCM_U8 }, + [AV_SAMPLE_FMT_S16 ] = { AV_CODEC_ID_PCM_S16LE, AV_CODEC_ID_PCM_S16BE }, + [AV_SAMPLE_FMT_S32 ] = { AV_CODEC_ID_PCM_S32LE, AV_CODEC_ID_PCM_S32BE }, + [AV_SAMPLE_FMT_FLT ] = { AV_CODEC_ID_PCM_F32LE, AV_CODEC_ID_PCM_F32BE }, + [AV_SAMPLE_FMT_DBL ] = { AV_CODEC_ID_PCM_F64LE, AV_CODEC_ID_PCM_F64BE }, + [AV_SAMPLE_FMT_U8P ] = { AV_CODEC_ID_PCM_U8, AV_CODEC_ID_PCM_U8 }, + [AV_SAMPLE_FMT_S16P] = { AV_CODEC_ID_PCM_S16LE, AV_CODEC_ID_PCM_S16BE }, + [AV_SAMPLE_FMT_S32P] = { AV_CODEC_ID_PCM_S32LE, AV_CODEC_ID_PCM_S32BE }, + [AV_SAMPLE_FMT_FLTP] = { AV_CODEC_ID_PCM_F32LE, AV_CODEC_ID_PCM_F32BE }, + [AV_SAMPLE_FMT_DBLP] = { AV_CODEC_ID_PCM_F64LE, AV_CODEC_ID_PCM_F64BE }, + }; + if (fmt < 0 || fmt >= AV_SAMPLE_FMT_NB) + return AV_CODEC_ID_NONE; + if (be < 0 || be > 1) + be = AV_NE(1, 0); + return map[fmt][be]; +} + +int av_get_bits_per_sample(enum AVCodecID codec_id) +{ + switch (codec_id) { + case AV_CODEC_ID_ADPCM_SBPRO_2: + return 2; + case AV_CODEC_ID_ADPCM_SBPRO_3: + return 3; + case AV_CODEC_ID_ADPCM_SBPRO_4: + case AV_CODEC_ID_ADPCM_IMA_WAV: + case AV_CODEC_ID_ADPCM_IMA_QT: + case AV_CODEC_ID_ADPCM_SWF: + case AV_CODEC_ID_ADPCM_MS: + return 4; + default: + return av_get_exact_bits_per_sample(codec_id); + } +} + +int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) +{ + int id, sr, ch, ba, tag, bps; + + id = avctx->codec_id; + sr = avctx->sample_rate; + ch = avctx->channels; + ba = avctx->block_align; + tag = avctx->codec_tag; + bps = av_get_exact_bits_per_sample(avctx->codec_id); + + /* codecs with an exact constant bits per sample */ + if (bps > 0 && ch > 0 && frame_bytes > 0 && ch < 32768 && bps < 32768) + return (frame_bytes * 8LL) / (bps * ch); + bps = avctx->bits_per_coded_sample; + + /* codecs with a fixed packet duration */ + switch (id) { + case AV_CODEC_ID_ADPCM_ADX: return 32; + case AV_CODEC_ID_ADPCM_IMA_QT: return 64; + case AV_CODEC_ID_ADPCM_EA_XAS: return 128; + case AV_CODEC_ID_AMR_NB: + case AV_CODEC_ID_EVRC: + case AV_CODEC_ID_GSM: + case AV_CODEC_ID_QCELP: + case AV_CODEC_ID_RA_288: return 160; + case AV_CODEC_ID_AMR_WB: + case AV_CODEC_ID_GSM_MS: return 320; + case AV_CODEC_ID_MP1: return 384; + case AV_CODEC_ID_ATRAC1: return 512; + case AV_CODEC_ID_ATRAC3: return 1024; + case AV_CODEC_ID_MP2: + case AV_CODEC_ID_MUSEPACK7: return 1152; + case AV_CODEC_ID_AC3: return 1536; + } + + if (sr > 0) { + /* calc from sample rate */ + if (id == AV_CODEC_ID_TTA) + return 256 * sr / 245; + + if (ch > 0) { + /* calc from sample rate and channels */ + if (id == AV_CODEC_ID_BINKAUDIO_DCT) + return (480 << (sr / 22050)) / ch; + } + } + + if (ba > 0) { + /* calc from block_align */ + if (id == AV_CODEC_ID_SIPR) { + switch (ba) { + case 20: return 160; + case 19: return 144; + case 29: return 288; + case 37: return 480; + } + } else if (id == AV_CODEC_ID_ILBC) { + switch (ba) { + case 38: return 160; + case 50: return 240; + } + } + } + + if (frame_bytes > 0) { + /* calc from frame_bytes only */ + if (id == AV_CODEC_ID_TRUESPEECH) + return 240 * (frame_bytes / 32); + if (id == AV_CODEC_ID_NELLYMOSER) + return 256 * (frame_bytes / 64); + if (id == AV_CODEC_ID_RA_144) + return 160 * (frame_bytes / 20); + if (id == AV_CODEC_ID_G723_1) + return 240 * (frame_bytes / 24); + + if (bps > 0) { + /* calc from frame_bytes and bits_per_coded_sample */ + if (id == AV_CODEC_ID_ADPCM_G726) + return frame_bytes * 8 / bps; + } + + if (ch > 0) { + /* calc from frame_bytes and channels */ + switch (id) { + case AV_CODEC_ID_ADPCM_AFC: + return frame_bytes / (9 * ch) * 16; + case AV_CODEC_ID_ADPCM_4XM: + case AV_CODEC_ID_ADPCM_IMA_ISS: + return (frame_bytes - 4 * ch) * 2 / ch; + case AV_CODEC_ID_ADPCM_IMA_SMJPEG: + return (frame_bytes - 4) * 2 / ch; + case AV_CODEC_ID_ADPCM_IMA_AMV: + return (frame_bytes - 8) * 2 / ch; + case AV_CODEC_ID_ADPCM_XA: + return (frame_bytes / 128) * 224 / ch; + case AV_CODEC_ID_INTERPLAY_DPCM: + return (frame_bytes - 6 - ch) / ch; + case AV_CODEC_ID_ROQ_DPCM: + return (frame_bytes - 8) / ch; + case AV_CODEC_ID_XAN_DPCM: + return (frame_bytes - 2 * ch) / ch; + case AV_CODEC_ID_MACE3: + return 3 * frame_bytes / ch; + case AV_CODEC_ID_MACE6: + return 6 * frame_bytes / ch; + case AV_CODEC_ID_PCM_LXF: + return 2 * (frame_bytes / (5 * ch)); + case AV_CODEC_ID_IAC: + case AV_CODEC_ID_IMC: + return 4 * frame_bytes / ch; + } + + if (tag) { + /* calc from frame_bytes, channels, and codec_tag */ + if (id == AV_CODEC_ID_SOL_DPCM) { + if (tag == 3) + return frame_bytes / ch; + else + return frame_bytes * 2 / ch; + } + } + + if (ba > 0) { + /* calc from frame_bytes, channels, and block_align */ + int blocks = frame_bytes / ba; + switch (avctx->codec_id) { + case AV_CODEC_ID_ADPCM_IMA_WAV: + return blocks * (1 + (ba - 4 * ch) / (4 * ch) * 8); + case AV_CODEC_ID_ADPCM_IMA_DK3: + return blocks * (((ba - 16) * 2 / 3 * 4) / ch); + case AV_CODEC_ID_ADPCM_IMA_DK4: + return blocks * (1 + (ba - 4 * ch) * 2 / ch); + case AV_CODEC_ID_ADPCM_MS: + return blocks * (2 + (ba - 7 * ch) * 2 / ch); + } + } + + if (bps > 0) { + /* calc from frame_bytes, channels, and bits_per_coded_sample */ + switch (avctx->codec_id) { + case AV_CODEC_ID_PCM_DVD: + if(bps<4) + return 0; + return 2 * (frame_bytes / ((bps * 2 / 8) * ch)); + case AV_CODEC_ID_PCM_BLURAY: + if(bps<4) + return 0; + return frame_bytes / ((FFALIGN(ch, 2) * bps) / 8); + case AV_CODEC_ID_S302M: + return 2 * (frame_bytes / ((bps + 4) / 4)) / ch; + } + } + } + } + + return 0; +} + +#if !HAVE_THREADS +int ff_thread_init(AVCodecContext *s) +{ + return -1; +} + +#endif + +unsigned int av_xiphlacing(unsigned char *s, unsigned int v) +{ + unsigned int n = 0; + + while (v >= 0xff) { + *s++ = 0xff; + v -= 0xff; + n++; + } + *s = v; + n++; + return n; +} + +int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b) +{ + int i; + for (i = 0; i < size && !(tab[i][0] == a && tab[i][1] == b); i++) ; + return i; +} + +#if FF_API_MISSING_SAMPLE +void av_log_missing_feature(void *avc, const char *feature, int want_sample) +{ + av_log(avc, AV_LOG_WARNING, "%s is not implemented. Update your FFmpeg " + "version to the newest one from Git. If the problem still " + "occurs, it means that your file has a feature which has not " + "been implemented.\n", feature); + if(want_sample) + av_log_ask_for_sample(avc, NULL); +} + +void av_log_ask_for_sample(void *avc, const char *msg, ...) +{ + va_list argument_list; + + va_start(argument_list, msg); + + if (msg) + av_vlog(avc, AV_LOG_WARNING, msg, argument_list); + av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " + "of this file to ftp://upload.ffmpeg.org/MPlayer/incoming/ " + "and contact the ffmpeg-devel mailing list.\n"); + + va_end(argument_list); +} +#endif /* FF_API_MISSING_SAMPLE */ + +static AVHWAccel *first_hwaccel = NULL; + +void av_register_hwaccel(AVHWAccel *hwaccel) +{ + AVHWAccel **p = &first_hwaccel; + while (*p) + p = &(*p)->next; + *p = hwaccel; + hwaccel->next = NULL; +} + +AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel) +{ + return hwaccel ? hwaccel->next : first_hwaccel; +} + +AVHWAccel *ff_find_hwaccel(enum AVCodecID codec_id, enum AVPixelFormat pix_fmt) +{ + AVHWAccel *hwaccel = NULL; + + while ((hwaccel = av_hwaccel_next(hwaccel))) + if (hwaccel->id == codec_id + && hwaccel->pix_fmt == pix_fmt) + return hwaccel; + return NULL; +} + +int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) +{ + if (ff_lockmgr_cb) { + if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) + return -1; + if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) + return -1; + } + + ff_lockmgr_cb = cb; + + if (ff_lockmgr_cb) { + if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) + return -1; + if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE)) + return -1; + } + return 0; +} + +int ff_lock_avcodec(AVCodecContext *log_ctx) +{ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) + return -1; + } + entangled_thread_counter++; + if (entangled_thread_counter != 1) { + av_log(log_ctx, AV_LOG_ERROR, "Insufficient thread locking around avcodec_open/close()\n"); + ff_avcodec_locked = 1; + ff_unlock_avcodec(); + return AVERROR(EINVAL); + } + av_assert0(!ff_avcodec_locked); + ff_avcodec_locked = 1; + return 0; +} + +int ff_unlock_avcodec(void) +{ + av_assert0(ff_avcodec_locked); + ff_avcodec_locked = 0; + entangled_thread_counter--; + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE)) + return -1; + } + return 0; +} + +int avpriv_lock_avformat(void) +{ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN)) + return -1; + } + return 0; +} + +int avpriv_unlock_avformat(void) +{ + if (ff_lockmgr_cb) { + if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE)) + return -1; + } + return 0; +} + +unsigned int avpriv_toupper4(unsigned int x) +{ + return av_toupper(x & 0xFF) + + (av_toupper((x >> 8) & 0xFF) << 8) + + (av_toupper((x >> 16) & 0xFF) << 16) + + (av_toupper((x >> 24) & 0xFF) << 24); +} + +int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src) +{ + int ret; + + dst->owner = src->owner; + + ret = av_frame_ref(dst->f, src->f); + if (ret < 0) + return ret; + + if (src->progress && + !(dst->progress = av_buffer_ref(src->progress))) { + ff_thread_release_buffer(dst->owner, dst); + return AVERROR(ENOMEM); + } + + return 0; +} + +#if !HAVE_THREADS + +int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) +{ + f->owner = avctx; + return ff_get_buffer(avctx, f->f, flags); +} + +void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) +{ + av_frame_unref(f->f); +} + +void ff_thread_finish_setup(AVCodecContext *avctx) +{ +} + +void ff_thread_report_progress(ThreadFrame *f, int progress, int field) +{ +} + +void ff_thread_await_progress(ThreadFrame *f, int progress, int field) +{ +} + +int ff_thread_can_start_frame(AVCodecContext *avctx) +{ + return 1; +} + +#endif + +enum AVMediaType avcodec_get_type(enum AVCodecID codec_id) +{ + AVCodec *c= avcodec_find_decoder(codec_id); + if(!c) + c= avcodec_find_encoder(codec_id); + if(c) + return c->type; + + if (codec_id <= AV_CODEC_ID_NONE) + return AVMEDIA_TYPE_UNKNOWN; + else if (codec_id < AV_CODEC_ID_FIRST_AUDIO) + return AVMEDIA_TYPE_VIDEO; + else if (codec_id < AV_CODEC_ID_FIRST_SUBTITLE) + return AVMEDIA_TYPE_AUDIO; + else if (codec_id < AV_CODEC_ID_FIRST_UNKNOWN) + return AVMEDIA_TYPE_SUBTITLE; + + return AVMEDIA_TYPE_UNKNOWN; +} + +int avcodec_is_open(AVCodecContext *s) +{ + return !!s->internal; +} + +int avpriv_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf) +{ + int ret; + char *str; + + ret = av_bprint_finalize(buf, &str); + if (ret < 0) + return ret; + avctx->extradata = str; + /* Note: the string is NUL terminated (so extradata can be read as a + * string), but the ending character is not accounted in the size (in + * binary formats you are likely not supposed to mux that character). When + * extradata is copied, it is also padded with FF_INPUT_BUFFER_PADDING_SIZE + * zeros. */ + avctx->extradata_size = buf->len; + return 0; +} diff --git a/ffmpeg/libavcodec/utvideo.c b/ffmpeg/libavcodec/utvideo.c new file mode 100644 index 0000000..308adb7 --- /dev/null +++ b/ffmpeg/libavcodec/utvideo.c @@ -0,0 +1,39 @@ +/* + * Common Ut Video code + * Copyright (c) 2011 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Common Ut Video code + */ + +#include "utvideo.h" + +const int ff_ut_pred_order[5] = { + PRED_LEFT, PRED_MEDIAN, PRED_MEDIAN, PRED_NONE, PRED_GRADIENT +}; + +const int ff_ut_rgb_order[4] = { 1, 2, 0, 3 }; // G, B, R, A + +int ff_ut_huff_cmp_len(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return (aa->len - bb->len)*256 + aa->sym - bb->sym; +} diff --git a/ffmpeg/libavcodec/utvideo.h b/ffmpeg/libavcodec/utvideo.h new file mode 100644 index 0000000..c00179e --- /dev/null +++ b/ffmpeg/libavcodec/utvideo.h @@ -0,0 +1,91 @@ +/* + * Common Ut Video header + * Copyright (c) 2011 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_UTVIDEO_H +#define AVCODEC_UTVIDEO_H + +/** + * @file + * Common Ut Video header + */ + +#include "libavutil/common.h" +#include "avcodec.h" +#include "dsputil.h" + +enum { + PRED_NONE = 0, + PRED_LEFT, + PRED_GRADIENT, + PRED_MEDIAN, +}; + +enum { + COMP_NONE = 0, + COMP_HUFF, +}; + +/* + * "Original format" markers. + * Based on values gotten from the official VFW encoder. + * They are not used during decoding, but they do have + * an informative role on seeing what was input + * to the encoder. + */ +enum { + UTVIDEO_RGB = MKTAG(0x00, 0x00, 0x01, 0x18), + UTVIDEO_RGBA = MKTAG(0x00, 0x00, 0x02, 0x18), + UTVIDEO_420 = MKTAG('Y', 'V', '1', '2'), + UTVIDEO_422 = MKTAG('Y', 'U', 'Y', '2'), +}; + +/* Mapping of libavcodec prediction modes to Ut Video's */ +extern const int ff_ut_pred_order[5]; + +/* Order of RGB(A) planes in Ut Video */ +extern const int ff_ut_rgb_order[4]; + +typedef struct UtvideoContext { + AVCodecContext *avctx; + DSPContext dsp; + + uint32_t frame_info_size, flags, frame_info; + int planes; + int slices; + int compression; + int interlaced; + int frame_pred; + + int slice_stride; + uint8_t *slice_bits, *slice_buffer[4]; + int slice_bits_size; +} UtvideoContext; + +typedef struct HuffEntry { + uint8_t sym; + uint8_t len; + uint32_t code; +} HuffEntry; + +/* Compare huffman tree nodes */ +int ff_ut_huff_cmp_len(const void *a, const void *b); + +#endif /* AVCODEC_UTVIDEO_H */ diff --git a/ffmpeg/libavcodec/utvideodec.c b/ffmpeg/libavcodec/utvideodec.c new file mode 100644 index 0000000..4efad1e --- /dev/null +++ b/ffmpeg/libavcodec/utvideodec.c @@ -0,0 +1,543 @@ +/* + * Ut Video decoder + * Copyright (c) 2011 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Ut Video decoder + */ + +#include + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "bytestream.h" +#include "get_bits.h" +#include "dsputil.h" +#include "thread.h" +#include "utvideo.h" + +static int build_huff(const uint8_t *src, VLC *vlc, int *fsym) +{ + int i; + HuffEntry he[256]; + int last; + uint32_t codes[256]; + uint8_t bits[256]; + uint8_t syms[256]; + uint32_t code; + + *fsym = -1; + for (i = 0; i < 256; i++) { + he[i].sym = i; + he[i].len = *src++; + } + qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len); + + if (!he[0].len) { + *fsym = he[0].sym; + return 0; + } + if (he[0].len > 32) + return -1; + + last = 255; + while (he[last].len == 255 && last) + last--; + + code = 1; + for (i = last; i >= 0; i--) { + codes[i] = code >> (32 - he[i].len); + bits[i] = he[i].len; + syms[i] = he[i].sym; + code += 0x80000000u >> (he[i].len - 1); + } + + return ff_init_vlc_sparse(vlc, FFMIN(he[last].len, 9), last + 1, + bits, sizeof(*bits), sizeof(*bits), + codes, sizeof(*codes), sizeof(*codes), + syms, sizeof(*syms), sizeof(*syms), 0); +} + +static int decode_plane(UtvideoContext *c, int plane_no, + uint8_t *dst, int step, int stride, + int width, int height, + const uint8_t *src, int use_pred) +{ + int i, j, slice, pix; + int sstart, send; + VLC vlc; + GetBitContext gb; + int prev, fsym; + const int cmask = ~(!plane_no && c->avctx->pix_fmt == AV_PIX_FMT_YUV420P); + + if (build_huff(src, &vlc, &fsym)) { + av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); + return AVERROR_INVALIDDATA; + } + if (fsym >= 0) { // build_huff reported a symbol to fill slices with + send = 0; + for (slice = 0; slice < c->slices; slice++) { + uint8_t *dest; + + sstart = send; + send = (height * (slice + 1) / c->slices) & cmask; + dest = dst + sstart * stride; + + prev = 0x80; + for (j = sstart; j < send; j++) { + for (i = 0; i < width * step; i += step) { + pix = fsym; + if (use_pred) { + prev += pix; + pix = prev; + } + dest[i] = pix; + } + dest += stride; + } + } + return 0; + } + + src += 256; + + send = 0; + for (slice = 0; slice < c->slices; slice++) { + uint8_t *dest; + int slice_data_start, slice_data_end, slice_size; + + sstart = send; + send = (height * (slice + 1) / c->slices) & cmask; + dest = dst + sstart * stride; + + // slice offset and size validation was done earlier + slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0; + slice_data_end = AV_RL32(src + slice * 4); + slice_size = slice_data_end - slice_data_start; + + if (!slice_size) { + av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol " + "yet a slice has a length of zero.\n"); + goto fail; + } + + memcpy(c->slice_bits, src + slice_data_start + c->slices * 4, + slice_size); + memset(c->slice_bits + slice_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + c->dsp.bswap_buf((uint32_t *) c->slice_bits, (uint32_t *) c->slice_bits, + (slice_data_end - slice_data_start + 3) >> 2); + init_get_bits(&gb, c->slice_bits, slice_size * 8); + + prev = 0x80; + for (j = sstart; j < send; j++) { + for (i = 0; i < width * step; i += step) { + if (get_bits_left(&gb) <= 0) { + av_log(c->avctx, AV_LOG_ERROR, + "Slice decoding ran out of bits\n"); + goto fail; + } + pix = get_vlc2(&gb, vlc.table, vlc.bits, 4); + if (pix < 0) { + av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n"); + goto fail; + } + if (use_pred) { + prev += pix; + pix = prev; + } + dest[i] = pix; + } + dest += stride; + } + if (get_bits_left(&gb) > 32) + av_log(c->avctx, AV_LOG_WARNING, + "%d bits left after decoding slice\n", get_bits_left(&gb)); + } + + ff_free_vlc(&vlc); + + return 0; +fail: + ff_free_vlc(&vlc); + return AVERROR_INVALIDDATA; +} + +static void restore_rgb_planes(uint8_t *src, int step, int stride, int width, + int height) +{ + int i, j; + uint8_t r, g, b; + + for (j = 0; j < height; j++) { + for (i = 0; i < width * step; i += step) { + r = src[i]; + g = src[i + 1]; + b = src[i + 2]; + src[i] = r + g - 0x80; + src[i + 2] = b + g - 0x80; + } + src += stride; + } +} + +static void restore_median(uint8_t *src, int step, int stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~rmode; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + bsrc[i] += A; + A = bsrc[i]; + } + bsrc += stride; + if (slice_height == 1) + continue; + // second line - first element has top prediction, the rest uses median + C = bsrc[-stride]; + bsrc[0] += C; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + B = bsrc[i - stride]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + bsrc += stride; + // the rest of lines use continuous median prediction + for (j = 2; j < slice_height; j++) { + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + bsrc += stride; + } + } +} + +/* UtVideo interlaced mode treats every two lines as a single one, + * so restoring function should take care of possible padding between + * two parts of the same "line". + */ +static void restore_median_il(uint8_t *src, int step, int stride, + int width, int height, int slices, int rmode) +{ + int i, j, slice; + int A, B, C; + uint8_t *bsrc; + int slice_start, slice_height; + const int cmask = ~(rmode ? 3 : 1); + const int stride2 = stride << 1; + + for (slice = 0; slice < slices; slice++) { + slice_start = ((slice * height) / slices) & cmask; + slice_height = ((((slice + 1) * height) / slices) & cmask) - + slice_start; + slice_height >>= 1; + + bsrc = src + slice_start * stride; + + // first line - left neighbour prediction + bsrc[0] += 0x80; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + bsrc[i] += A; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + bsrc[stride + i] += A; + A = bsrc[stride + i]; + } + bsrc += stride2; + if (slice_height == 1) + continue; + // second line - first element has top prediction, the rest uses median + C = bsrc[-stride2]; + bsrc[0] += C; + A = bsrc[0]; + for (i = step; i < width * step; i += step) { + B = bsrc[i - stride2]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride]; + bsrc[stride + i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[stride + i]; + } + bsrc += stride2; + // the rest of lines use continuous median prediction + for (j = 2; j < slice_height; j++) { + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride2]; + bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i]; + } + for (i = 0; i < width * step; i += step) { + B = bsrc[i - stride]; + bsrc[i + stride] += mid_pred(A, B, (uint8_t)(A + B - C)); + C = B; + A = bsrc[i + stride]; + } + bsrc += stride2; + } + } +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + UtvideoContext *c = avctx->priv_data; + int i, j; + const uint8_t *plane_start[5]; + int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size; + int ret; + GetByteContext gb; + ThreadFrame frame = { .f = data }; + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + /* parse plane structure to get frame flags and validate slice offsets */ + bytestream2_init(&gb, buf, buf_size); + for (i = 0; i < c->planes; i++) { + plane_start[i] = gb.buffer; + if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) { + av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_skipu(&gb, 256); + slice_start = 0; + slice_end = 0; + for (j = 0; j < c->slices; j++) { + slice_end = bytestream2_get_le32u(&gb); + slice_size = slice_end - slice_start; + if (slice_end < 0 || slice_size < 0 || + bytestream2_get_bytes_left(&gb) < slice_end) { + av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n"); + return AVERROR_INVALIDDATA; + } + slice_start = slice_end; + max_slice_size = FFMAX(max_slice_size, slice_size); + } + plane_size = slice_end; + bytestream2_skipu(&gb, plane_size); + } + plane_start[c->planes] = gb.buffer; + if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { + av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); + return AVERROR_INVALIDDATA; + } + c->frame_info = bytestream2_get_le32u(&gb); + av_log(avctx, AV_LOG_DEBUG, "frame information flags %X\n", c->frame_info); + + c->frame_pred = (c->frame_info >> 8) & 3; + + if (c->frame_pred == PRED_GRADIENT) { + avpriv_request_sample(avctx, "Frame with gradient prediction"); + return AVERROR_PATCHWELCOME; + } + + av_fast_malloc(&c->slice_bits, &c->slice_bits_size, + max_slice_size + FF_INPUT_BUFFER_PADDING_SIZE); + + if (!c->slice_bits) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); + return AVERROR(ENOMEM); + } + + switch (c->avctx->pix_fmt) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_RGBA: + for (i = 0; i < c->planes; i++) { + ret = decode_plane(c, i, frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], avctx->width, + avctx->height, plane_start[i], + c->frame_pred == PRED_LEFT); + if (ret) + return ret; + if (c->frame_pred == PRED_MEDIAN) { + if (!c->interlaced) { + restore_median(frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], avctx->width, + avctx->height, c->slices, 0); + } else { + restore_median_il(frame.f->data[0] + ff_ut_rgb_order[i], + c->planes, frame.f->linesize[0], + avctx->width, avctx->height, c->slices, + 0); + } + } + } + restore_rgb_planes(frame.f->data[0], c->planes, frame.f->linesize[0], + avctx->width, avctx->height); + break; + case AV_PIX_FMT_YUV420P: + for (i = 0; i < 3; i++) { + ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], + avctx->width >> !!i, avctx->height >> !!i, + plane_start[i], c->frame_pred == PRED_LEFT); + if (ret) + return ret; + if (c->frame_pred == PRED_MEDIAN) { + if (!c->interlaced) { + restore_median(frame.f->data[i], 1, frame.f->linesize[i], + avctx->width >> !!i, avctx->height >> !!i, + c->slices, !i); + } else { + restore_median_il(frame.f->data[i], 1, frame.f->linesize[i], + avctx->width >> !!i, + avctx->height >> !!i, + c->slices, !i); + } + } + } + break; + case AV_PIX_FMT_YUV422P: + for (i = 0; i < 3; i++) { + ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + plane_start[i], c->frame_pred == PRED_LEFT); + if (ret) + return ret; + if (c->frame_pred == PRED_MEDIAN) { + if (!c->interlaced) { + restore_median(frame.f->data[i], 1, frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); + } else { + restore_median_il(frame.f->data[i], 1, frame.f->linesize[i], + avctx->width >> !!i, avctx->height, + c->slices, 0); + } + } + } + break; + } + + frame.f->key_frame = 1; + frame.f->pict_type = AV_PICTURE_TYPE_I; + frame.f->interlaced_frame = !!c->interlaced; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + UtvideoContext * const c = avctx->priv_data; + + c->avctx = avctx; + + ff_dsputil_init(&c->dsp, avctx); + + if (avctx->extradata_size < 16) { + av_log(avctx, AV_LOG_ERROR, + "Insufficient extradata size %d, should be at least 16\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %X\n", + AV_RB32(avctx->extradata + 4)); + c->frame_info_size = AV_RL32(avctx->extradata + 8); + c->flags = AV_RL32(avctx->extradata + 12); + + if (c->frame_info_size != 4) + avpriv_request_sample(avctx, "Frame info not 4 bytes"); + av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08X\n", c->flags); + c->slices = (c->flags >> 24) + 1; + c->compression = c->flags & 1; + c->interlaced = c->flags & 0x800; + + c->slice_bits_size = 0; + + switch (avctx->codec_tag) { + case MKTAG('U', 'L', 'R', 'G'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_RGB24; + break; + case MKTAG('U', 'L', 'R', 'A'): + c->planes = 4; + avctx->pix_fmt = AV_PIX_FMT_RGBA; + break; + case MKTAG('U', 'L', 'Y', '0'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + break; + case MKTAG('U', 'L', 'Y', '2'): + c->planes = 3; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n", + avctx->codec_tag); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + UtvideoContext * const c = avctx->priv_data; + + av_freep(&c->slice_bits); + + return 0; +} + +AVCodec ff_utvideo_decoder = { + .name = "utvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_UTVIDEO, + .priv_data_size = sizeof(UtvideoContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), +}; diff --git a/ffmpeg/libavcodec/utvideoenc.c b/ffmpeg/libavcodec/utvideoenc.c new file mode 100644 index 0000000..acb25c3 --- /dev/null +++ b/ffmpeg/libavcodec/utvideoenc.c @@ -0,0 +1,622 @@ +/* + * Ut Video encoder + * Copyright (c) 2012 Jan Ekström + * + * 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 + */ + +/** + * @file + * Ut Video encoder + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" +#include "bytestream.h" +#include "put_bits.h" +#include "dsputil.h" +#include "mathops.h" +#include "utvideo.h" +#include "huffman.h" + +/* Compare huffentry symbols */ +static int huff_cmp_sym(const void *a, const void *b) +{ + const HuffEntry *aa = a, *bb = b; + return aa->sym - bb->sym; +} + +static av_cold int utvideo_encode_close(AVCodecContext *avctx) +{ + UtvideoContext *c = avctx->priv_data; + int i; + + av_freep(&avctx->coded_frame); + av_freep(&c->slice_bits); + for (i = 0; i < 4; i++) + av_freep(&c->slice_buffer[i]); + + return 0; +} + +static av_cold int utvideo_encode_init(AVCodecContext *avctx) +{ + UtvideoContext *c = avctx->priv_data; + int i; + uint32_t original_format; + + c->avctx = avctx; + c->frame_info_size = 4; + c->slice_stride = FFALIGN(avctx->width, 32); + + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGB24: + c->planes = 3; + avctx->codec_tag = MKTAG('U', 'L', 'R', 'G'); + original_format = UTVIDEO_RGB; + break; + case AV_PIX_FMT_RGBA: + c->planes = 4; + avctx->codec_tag = MKTAG('U', 'L', 'R', 'A'); + original_format = UTVIDEO_RGBA; + break; + case AV_PIX_FMT_YUV420P: + if (avctx->width & 1 || avctx->height & 1) { + av_log(avctx, AV_LOG_ERROR, + "4:2:0 video requires even width and height.\n"); + return AVERROR_INVALIDDATA; + } + c->planes = 3; + avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); + original_format = UTVIDEO_420; + break; + case AV_PIX_FMT_YUV422P: + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, + "4:2:2 video requires even width.\n"); + return AVERROR_INVALIDDATA; + } + c->planes = 3; + avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); + original_format = UTVIDEO_422; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n", + avctx->pix_fmt); + return AVERROR_INVALIDDATA; + } + + ff_dsputil_init(&c->dsp, avctx); + + /* Check the prediction method, and error out if unsupported */ + if (avctx->prediction_method < 0 || avctx->prediction_method > 4) { + av_log(avctx, AV_LOG_WARNING, + "Prediction method %d is not supported in Ut Video.\n", + avctx->prediction_method); + return AVERROR_OPTION_NOT_FOUND; + } + + if (avctx->prediction_method == FF_PRED_PLANE) { + av_log(avctx, AV_LOG_ERROR, + "Plane prediction is not supported in Ut Video.\n"); + return AVERROR_OPTION_NOT_FOUND; + } + + /* Convert from libavcodec prediction type to Ut Video's */ + c->frame_pred = ff_ut_pred_order[avctx->prediction_method]; + + if (c->frame_pred == PRED_GRADIENT) { + av_log(avctx, AV_LOG_ERROR, "Gradient prediction is not supported.\n"); + return AVERROR_OPTION_NOT_FOUND; + } + + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + utvideo_encode_close(avctx); + return AVERROR(ENOMEM); + } + + /* extradata size is 4 * 32bit */ + avctx->extradata_size = 16; + + avctx->extradata = av_mallocz(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + + if (!avctx->extradata) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata.\n"); + utvideo_encode_close(avctx); + return AVERROR(ENOMEM); + } + + for (i = 0; i < c->planes; i++) { + c->slice_buffer[i] = av_malloc(c->slice_stride * (avctx->height + 2) + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!c->slice_buffer[i]) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 1.\n"); + utvideo_encode_close(avctx); + return AVERROR(ENOMEM); + } + } + + /* + * Set the version of the encoder. + * Last byte is "implementation ID", which is + * obtained from the creator of the format. + * Libavcodec has been assigned with the ID 0xF0. + */ + AV_WB32(avctx->extradata, MKTAG(1, 0, 0, 0xF0)); + + /* + * Set the "original format" + * Not used for anything during decoding. + */ + AV_WL32(avctx->extradata + 4, original_format); + + /* Write 4 as the 'frame info size' */ + AV_WL32(avctx->extradata + 8, c->frame_info_size); + + /* + * Set how many slices are going to be used. + * Set one slice for now. + */ + c->slices = 1; + + /* Set compression mode */ + c->compression = COMP_HUFF; + + /* + * Set the encoding flags: + * - Slice count minus 1 + * - Interlaced encoding mode flag, set to zero for now. + * - Compression mode (none/huff) + * And write the flags. + */ + c->flags = (c->slices - 1) << 24; + c->flags |= 0 << 11; // bit field to signal interlaced encoding mode + c->flags |= c->compression; + + AV_WL32(avctx->extradata + 12, c->flags); + + return 0; +} + +static void mangle_rgb_planes(uint8_t *dst[4], int dst_stride, uint8_t *src, + int step, int stride, int width, int height) +{ + int i, j; + int k = 2 * dst_stride; + unsigned int g; + + for (j = 0; j < height; j++) { + if (step == 3) { + for (i = 0; i < width * step; i += step) { + g = src[i + 1]; + dst[0][k] = g; + g += 0x80; + dst[1][k] = src[i + 2] - g; + dst[2][k] = src[i + 0] - g; + k++; + } + } else { + for (i = 0; i < width * step; i += step) { + g = src[i + 1]; + dst[0][k] = g; + g += 0x80; + dst[1][k] = src[i + 2] - g; + dst[2][k] = src[i + 0] - g; + dst[3][k] = src[i + 3]; + k++; + } + } + k += dst_stride - width; + src += stride; + } +} + +/* Write data to a plane, no prediction applied */ +static void write_plane(uint8_t *src, uint8_t *dst, int stride, + int width, int height) +{ + int i, j; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) + *dst++ = src[i]; + + src += stride; + } +} + +/* Write data to a plane with left prediction */ +static void left_predict(uint8_t *src, uint8_t *dst, int stride, + int width, int height) +{ + int i, j; + uint8_t prev; + + prev = 0x80; /* Set the initial value */ + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + *dst++ = src[i] - prev; + prev = src[i]; + } + src += stride; + } +} + +/* Write data to a plane with median prediction */ +static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst, int stride, + int width, int height) +{ + int i, j; + int A, B; + uint8_t prev; + + /* First line uses left neighbour prediction */ + prev = 0x80; /* Set the initial value */ + for (i = 0; i < width; i++) { + *dst++ = src[i] - prev; + prev = src[i]; + } + + if (height == 1) + return; + + src += stride; + + /* + * Second line uses top prediction for the first sample, + * and median for the rest. + */ + A = B = 0; + + /* Rest of the coded part uses median prediction */ + for (j = 1; j < height; j++) { + c->dsp.sub_hfyu_median_prediction(dst, src - stride, src, width, &A, &B); + dst += width; + src += stride; + } +} + +/* Count the usage of values in a plane */ +static void count_usage(uint8_t *src, int width, + int height, uint64_t *counts) +{ + int i, j; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + counts[src[i]]++; + } + src += width; + } +} + +/* Calculate the actual huffman codes from the code lengths */ +static void calculate_codes(HuffEntry *he) +{ + int last, i; + uint32_t code; + + qsort(he, 256, sizeof(*he), ff_ut_huff_cmp_len); + + last = 255; + while (he[last].len == 255 && last) + last--; + + code = 1; + for (i = last; i >= 0; i--) { + he[i].code = code >> (32 - he[i].len); + code += 0x80000000u >> (he[i].len - 1); + } + + qsort(he, 256, sizeof(*he), huff_cmp_sym); +} + +/* Write huffman bit codes to a memory block */ +static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size, + int width, int height, HuffEntry *he) +{ + PutBitContext pb; + int i, j; + int count; + + init_put_bits(&pb, dst, dst_size); + + /* Write the codes */ + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) + put_bits(&pb, he[src[i]].len, he[src[i]].code); + + src += width; + } + + /* Pad output to a 32bit boundary */ + count = put_bits_count(&pb) & 0x1F; + + if (count) + put_bits(&pb, 32 - count, 0); + + /* Get the amount of bits written */ + count = put_bits_count(&pb); + + /* Flush the rest with zeroes */ + flush_put_bits(&pb); + + return count; +} + +static int encode_plane(AVCodecContext *avctx, uint8_t *src, + uint8_t *dst, int stride, + int width, int height, PutByteContext *pb) +{ + UtvideoContext *c = avctx->priv_data; + uint8_t lengths[256]; + uint64_t counts[256] = { 0 }; + + HuffEntry he[256]; + + uint32_t offset = 0, slice_len = 0; + int i, sstart, send = 0; + int symbol; + + /* Do prediction / make planes */ + switch (c->frame_pred) { + case PRED_NONE: + for (i = 0; i < c->slices; i++) { + sstart = send; + send = height * (i + 1) / c->slices; + write_plane(src + sstart * stride, dst + sstart * width, + stride, width, send - sstart); + } + break; + case PRED_LEFT: + for (i = 0; i < c->slices; i++) { + sstart = send; + send = height * (i + 1) / c->slices; + left_predict(src + sstart * stride, dst + sstart * width, + stride, width, send - sstart); + } + break; + case PRED_MEDIAN: + for (i = 0; i < c->slices; i++) { + sstart = send; + send = height * (i + 1) / c->slices; + median_predict(c, src + sstart * stride, dst + sstart * width, + stride, width, send - sstart); + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown prediction mode: %d\n", + c->frame_pred); + return AVERROR_OPTION_NOT_FOUND; + } + + /* Count the usage of values */ + count_usage(dst, width, height, counts); + + /* Check for a special case where only one symbol was used */ + for (symbol = 0; symbol < 256; symbol++) { + /* If non-zero count is found, see if it matches width * height */ + if (counts[symbol]) { + /* Special case if only one symbol was used */ + if (counts[symbol] == width * (int64_t)height) { + /* + * Write a zero for the single symbol + * used in the plane, else 0xFF. + */ + for (i = 0; i < 256; i++) { + if (i == symbol) + bytestream2_put_byte(pb, 0); + else + bytestream2_put_byte(pb, 0xFF); + } + + /* Write zeroes for lengths */ + for (i = 0; i < c->slices; i++) + bytestream2_put_le32(pb, 0); + + /* And that's all for that plane folks */ + return 0; + } + break; + } + } + + /* Calculate huffman lengths */ + ff_huff_gen_len_table(lengths, counts); + + /* + * Write the plane's header into the output packet: + * - huffman code lengths (256 bytes) + * - slice end offsets (gotten from the slice lengths) + */ + for (i = 0; i < 256; i++) { + bytestream2_put_byte(pb, lengths[i]); + + he[i].len = lengths[i]; + he[i].sym = i; + } + + /* Calculate the huffman codes themselves */ + calculate_codes(he); + + send = 0; + for (i = 0; i < c->slices; i++) { + sstart = send; + send = height * (i + 1) / c->slices; + + /* + * Write the huffman codes to a buffer, + * get the offset in bits and convert to bytes. + */ + offset += write_huff_codes(dst + sstart * width, c->slice_bits, + width * (send - sstart), width, + send - sstart, he) >> 3; + + slice_len = offset - slice_len; + + /* Byteswap the written huffman codes */ + c->dsp.bswap_buf((uint32_t *) c->slice_bits, + (uint32_t *) c->slice_bits, + slice_len >> 2); + + /* Write the offset to the stream */ + bytestream2_put_le32(pb, offset); + + /* Seek to the data part of the packet */ + bytestream2_seek_p(pb, 4 * (c->slices - i - 1) + + offset - slice_len, SEEK_CUR); + + /* Write the slices' data into the output packet */ + bytestream2_put_buffer(pb, c->slice_bits, slice_len); + + /* Seek back to the slice offsets */ + bytestream2_seek_p(pb, -4 * (c->slices - i - 1) - offset, + SEEK_CUR); + + slice_len = offset; + } + + /* And at the end seek to the end of written slice(s) */ + bytestream2_seek_p(pb, offset, SEEK_CUR); + + return 0; +} + +static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + UtvideoContext *c = avctx->priv_data; + PutByteContext pb; + + uint32_t frame_info; + + uint8_t *dst; + + int width = avctx->width, height = avctx->height; + int i, ret = 0; + + /* Allocate a new packet if needed, and set it to the pointer dst */ + ret = ff_alloc_packet2(avctx, pkt, (256 + 4 * c->slices + width * height) * + c->planes + 4); + + if (ret < 0) + return ret; + + dst = pkt->data; + + bytestream2_init_writer(&pb, dst, pkt->size); + + av_fast_malloc(&c->slice_bits, &c->slice_bits_size, + width * height + FF_INPUT_BUFFER_PADDING_SIZE); + + if (!c->slice_bits) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n"); + return AVERROR(ENOMEM); + } + + /* In case of RGB, mangle the planes to Ut Video's format */ + if (avctx->pix_fmt == AV_PIX_FMT_RGBA || avctx->pix_fmt == AV_PIX_FMT_RGB24) + mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data[0], + c->planes, pic->linesize[0], width, height); + + /* Deal with the planes */ + switch (avctx->pix_fmt) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_RGBA: + for (i = 0; i < c->planes; i++) { + ret = encode_plane(avctx, c->slice_buffer[i] + 2 * c->slice_stride, + c->slice_buffer[i], c->slice_stride, + width, height, &pb); + + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); + return ret; + } + } + break; + case AV_PIX_FMT_YUV422P: + for (i = 0; i < c->planes; i++) { + ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], + pic->linesize[i], width >> !!i, height, &pb); + + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); + return ret; + } + } + break; + case AV_PIX_FMT_YUV420P: + for (i = 0; i < c->planes; i++) { + ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0], + pic->linesize[i], width >> !!i, height >> !!i, + &pb); + + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i); + return ret; + } + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n", + avctx->pix_fmt); + return AVERROR_INVALIDDATA; + } + + /* + * Write frame information (LE 32bit unsigned) + * into the output packet. + * Contains the prediction method. + */ + frame_info = c->frame_pred << 8; + bytestream2_put_le32(&pb, frame_info); + + /* + * At least currently Ut Video is IDR only. + * Set flags accordingly. + */ + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + pkt->size = bytestream2_tell_p(&pb); + pkt->flags |= AV_PKT_FLAG_KEY; + + /* Packet should be done */ + *got_packet = 1; + + return 0; +} + +AVCodec ff_utvideo_encoder = { + .name = "utvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_UTVIDEO, + .priv_data_size = sizeof(UtvideoContext), + .init = utvideo_encode_init, + .encode2 = utvideo_encode_frame, + .close = utvideo_encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE + }, + .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), +}; diff --git a/ffmpeg/libavcodec/v210dec.c b/ffmpeg/libavcodec/v210dec.c new file mode 100644 index 0000000..42e25cc --- /dev/null +++ b/ffmpeg/libavcodec/v210dec.c @@ -0,0 +1,178 @@ +/* + * V210 decoder + * + * Copyright (C) 2009 Michael Niedermayer + * Copyright (c) 2009 Baptiste Coudurier + * + * 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 "avcodec.h" +#include "internal.h" +#include "v210dec.h" +#include "libavutil/bswap.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +#define READ_PIXELS(a, b, c) \ + do { \ + val = av_le2ne32(*src++); \ + *a++ = val & 0x3FF; \ + *b++ = (val >> 10) & 0x3FF; \ + *c++ = (val >> 20) & 0x3FF; \ + } while (0) + +static void v210_planar_unpack_c(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width) +{ + uint32_t val; + int i; + + for( i = 0; i < width-5; i += 6 ){ + READ_PIXELS(u, y, v); + READ_PIXELS(y, u, y); + READ_PIXELS(v, y, u); + READ_PIXELS(y, v, y); + } +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + V210DecContext *s = avctx->priv_data; + + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n"); + return AVERROR_INVALIDDATA; + } + avctx->pix_fmt = AV_PIX_FMT_YUV422P10; + avctx->bits_per_raw_sample = 10; + + s->unpack_frame = v210_planar_unpack_c; + + if (HAVE_MMX) + v210_x86_init(s); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + V210DecContext *s = avctx->priv_data; + + int h, w, ret, stride, aligned_input; + AVFrame *pic = data; + const uint8_t *psrc = avpkt->data; + uint16_t *y, *u, *v; + + if (s->custom_stride ) + stride = s->custom_stride; + else { + int aligned_width = ((avctx->width + 47) / 48) * 48; + stride = aligned_width * 8 / 3; + } + + if (avpkt->size < stride * avctx->height) { + if ((((avctx->width + 23) / 24) * 24 * 8) / 3 * avctx->height == avpkt->size) { + stride = avpkt->size / avctx->height; + if (!s->stride_warning_shown) + av_log(avctx, AV_LOG_WARNING, "Broken v210 with too small padding (64 byte) detected\n"); + s->stride_warning_shown = 1; + } else { + av_log(avctx, AV_LOG_ERROR, "packet too small\n"); + return AVERROR_INVALIDDATA; + } + } + + aligned_input = !((uintptr_t)psrc & 0xf) && !(stride & 0xf); + if (aligned_input != s->aligned_input) { + s->aligned_input = aligned_input; + if (HAVE_MMX) + v210_x86_init(s); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + y = (uint16_t*)pic->data[0]; + u = (uint16_t*)pic->data[1]; + v = (uint16_t*)pic->data[2]; + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + + for (h = 0; h < avctx->height; h++) { + const uint32_t *src = (const uint32_t*)psrc; + uint32_t val; + + w = (avctx->width / 6) * 6; + s->unpack_frame(src, y, u, v, w); + + y += w; + u += w >> 1; + v += w >> 1; + src += (w << 1) / 3; + + if (w < avctx->width - 1) { + READ_PIXELS(u, y, v); + + val = av_le2ne32(*src++); + *y++ = val & 0x3FF; + if (w < avctx->width - 3) { + *u++ = (val >> 10) & 0x3FF; + *y++ = (val >> 20) & 0x3FF; + + val = av_le2ne32(*src++); + *v++ = val & 0x3FF; + *y++ = (val >> 10) & 0x3FF; + } + } + + psrc += stride; + y += pic->linesize[0] / 2 - avctx->width; + u += pic->linesize[1] / 2 - avctx->width / 2; + v += pic->linesize[2] / 2 - avctx->width / 2; + } + + *got_frame = 1; + + return avpkt->size; +} + +#define V210DEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM +static const AVOption v210dec_options[] = { + {"custom_stride", "Custom V210 stride", offsetof(V210DecContext, custom_stride), FF_OPT_TYPE_INT, + {.i64 = 0}, INT_MIN, INT_MAX, V210DEC_FLAGS}, + {NULL} +}; + +static const AVClass v210dec_class = { + "V210 Decoder", + av_default_item_name, + v210dec_options, + LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_v210_decoder = { + .name = "v210", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V210, + .priv_data_size = sizeof(V210DecContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .priv_class = &v210dec_class, +}; diff --git a/ffmpeg/libavcodec/v210dec.h b/ffmpeg/libavcodec/v210dec.h new file mode 100644 index 0000000..e1e3d32 --- /dev/null +++ b/ffmpeg/libavcodec/v210dec.h @@ -0,0 +1,36 @@ +/* + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_V210DEC_H +#define AVCODEC_V210DEC_H + +#include "libavutil/log.h" +#include "libavutil/opt.h" + + +typedef struct { + AVClass *av_class; + int custom_stride; + int aligned_input; + int stride_warning_shown; + void (*unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); +} V210DecContext; + +void v210_x86_init(V210DecContext *s); + +#endif /* AVCODEC_V210DEC_H */ diff --git a/ffmpeg/libavcodec/v210enc.c b/ffmpeg/libavcodec/v210enc.c new file mode 100644 index 0000000..5527686 --- /dev/null +++ b/ffmpeg/libavcodec/v210enc.c @@ -0,0 +1,126 @@ +/* + * V210 encoder + * + * Copyright (C) 2009 Michael Niedermayer + * Copyright (c) 2009 Baptiste Coudurier + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +static av_cold int encode_init(AVCodecContext *avctx) +{ + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n"); + return AVERROR(EINVAL); + } + + if (avctx->bits_per_raw_sample != 10) + av_log(avctx, AV_LOG_WARNING, "bits per raw sample: %d != 10-bit\n", + avctx->bits_per_raw_sample); + + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + int aligned_width = ((avctx->width + 47) / 48) * 48; + int stride = aligned_width * 8 / 3; + int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4; + int h, w, ret; + const uint16_t *y = (const uint16_t*)pic->data[0]; + const uint16_t *u = (const uint16_t*)pic->data[1]; + const uint16_t *v = (const uint16_t*)pic->data[2]; + PutByteContext p; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->height * stride)) < 0) + return ret; + + bytestream2_init_writer(&p, pkt->data, pkt->size); + +#define CLIP(v) av_clip(v, 4, 1019) + +#define WRITE_PIXELS(a, b, c) \ + do { \ + val = CLIP(*a++); \ + val |= (CLIP(*b++) << 10) | \ + (CLIP(*c++) << 20); \ + bytestream2_put_le32u(&p, val); \ + } while (0) + + for (h = 0; h < avctx->height; h++) { + uint32_t val; + for (w = 0; w < avctx->width - 5; w += 6) { + WRITE_PIXELS(u, y, v); + WRITE_PIXELS(y, u, y); + WRITE_PIXELS(v, y, u); + WRITE_PIXELS(y, v, y); + } + if (w < avctx->width - 1) { + WRITE_PIXELS(u, y, v); + + val = CLIP(*y++); + if (w == avctx->width - 2) + bytestream2_put_le32u(&p, val); + if (w < avctx->width - 3) { + val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); + bytestream2_put_le32u(&p, val); + + val = CLIP(*v++) | (CLIP(*y++) << 10); + bytestream2_put_le32u(&p, val); + } + } + + bytestream2_set_buffer(&p, 0, line_padding); + + y += pic->linesize[0] / 2 - avctx->width; + u += pic->linesize[1] / 2 - avctx->width / 2; + v += pic->linesize[2] / 2 - avctx->width / 2; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_v210_encoder = { + .name = "v210", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V210, + .init = encode_init, + .encode2 = encode_frame, + .close = encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), +}; diff --git a/ffmpeg/libavcodec/v210x.c b/ffmpeg/libavcodec/v210x.c new file mode 100644 index 0000000..e4d5460 --- /dev/null +++ b/ffmpeg/libavcodec/v210x.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2009 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 "avcodec.h" +#include "internal.h" +#include "libavutil/bswap.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +static av_cold int decode_init(AVCodecContext *avctx) +{ + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "v210x needs even width\n"); + return AVERROR(EINVAL); + } + avctx->pix_fmt = AV_PIX_FMT_YUV422P16; + avctx->bits_per_raw_sample = 10; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint32_t *src = (const uint32_t *)avpkt->data; + AVFrame *pic = data; + int width = avctx->width; + int y = 0; + uint16_t *ydst, *udst, *vdst, *yend; + int ret; + + if (avpkt->size < avctx->width * avctx->height * 8 / 3) { + av_log(avctx, AV_LOG_ERROR, "Packet too small\n"); + return AVERROR_INVALIDDATA; + } + + if (avpkt->size > avctx->width * avctx->height * 8 / 3) { + avpriv_request_sample(avctx, "(Probably) padded data"); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + ydst = (uint16_t *)pic->data[0]; + udst = (uint16_t *)pic->data[1]; + vdst = (uint16_t *)pic->data[2]; + yend = ydst + width; + pic->pict_type = AV_PICTURE_TYPE_I; + pic->key_frame = 1; + + for (;;) { + uint32_t v = av_be2ne32(*src++); + *udst++ = (v >> 16) & 0xFFC0; + *ydst++ = (v >> 6 ) & 0xFFC0; + *vdst++ = (v << 4 ) & 0xFFC0; + + v = av_be2ne32(*src++); + *ydst++ = (v >> 16) & 0xFFC0; + + if (ydst >= yend) { + ydst += pic->linesize[0] / 2 - width; + udst += pic->linesize[1] / 2 - width / 2; + vdst += pic->linesize[2] / 2 - width / 2; + yend = ydst + width; + if (++y >= avctx->height) + break; + } + + *udst++ = (v >> 6 ) & 0xFFC0; + *ydst++ = (v << 4 ) & 0xFFC0; + + v = av_be2ne32(*src++); + *vdst++ = (v >> 16) & 0xFFC0; + *ydst++ = (v >> 6 ) & 0xFFC0; + + if (ydst >= yend) { + ydst += pic->linesize[0] / 2 - width; + udst += pic->linesize[1] / 2 - width / 2; + vdst += pic->linesize[2] / 2 - width / 2; + yend = ydst + width; + if (++y >= avctx->height) + break; + } + + *udst++ = (v << 4 ) & 0xFFC0; + + v = av_be2ne32(*src++); + *ydst++ = (v >> 16) & 0xFFC0; + *vdst++ = (v >> 6 ) & 0xFFC0; + *ydst++ = (v << 4 ) & 0xFFC0; + if (ydst >= yend) { + ydst += pic->linesize[0] / 2 - width; + udst += pic->linesize[1] / 2 - width / 2; + vdst += pic->linesize[2] / 2 - width / 2; + yend = ydst + width; + if (++y >= avctx->height) + break; + } + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_v210x_decoder = { + .name = "v210x", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V210X, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), +}; diff --git a/ffmpeg/libavcodec/v308dec.c b/ffmpeg/libavcodec/v308dec.c new file mode 100644 index 0000000..cddc779 --- /dev/null +++ b/ffmpeg/libavcodec/v308dec.c @@ -0,0 +1,91 @@ +/* + * v308 decoder + * Copyright (c) 2011 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int v308_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + + if (avctx->width & 1) + av_log(avctx, AV_LOG_WARNING, "v308 requires width to be even.\n"); + + return 0; +} + +static int v308_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *pic = data; + const uint8_t *src = avpkt->data; + uint8_t *y, *u, *v; + int i, j, ret; + + if (avpkt->size < 3 * avctx->height * avctx->width) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + y = pic->data[0]; + u = pic->data[1]; + v = pic->data[2]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width; j++) { + v[j] = *src++; + y[j] = *src++; + u[j] = *src++; + } + + y += pic->linesize[0]; + u += pic->linesize[1]; + v += pic->linesize[2]; + } + + *got_frame = 1; + *(AVFrame *)data = *pic; + + return avpkt->size; +} + +static av_cold int v308_decode_close(AVCodecContext *avctx) +{ + + return 0; +} + +AVCodec ff_v308_decoder = { + .name = "v308", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V308, + .init = v308_decode_init, + .decode = v308_decode_frame, + .close = v308_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), +}; diff --git a/ffmpeg/libavcodec/v308enc.c b/ffmpeg/libavcodec/v308enc.c new file mode 100644 index 0000000..10437cc --- /dev/null +++ b/ffmpeg/libavcodec/v308enc.c @@ -0,0 +1,94 @@ +/* + * v308 encoder + * + * Copyright (c) 2011 Carl Eugen Hoyos + * + * 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 "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +static av_cold int v308_encode_init(AVCodecContext *avctx) +{ + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "v308 requires width to be even.\n"); + return AVERROR_INVALIDDATA; + } + + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int v308_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + uint8_t *dst; + uint8_t *y, *u, *v; + int i, j, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width * avctx->height * 3)) < 0) + return ret; + dst = pkt->data; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + y = pic->data[0]; + u = pic->data[1]; + v = pic->data[2]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width; j++) { + *dst++ = v[j]; + *dst++ = y[j]; + *dst++ = u[j]; + } + y += pic->linesize[0]; + u += pic->linesize[1]; + v += pic->linesize[2]; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int v308_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_v308_encoder = { + .name = "v308", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V308, + .init = v308_encode_init, + .encode2 = v308_encode_frame, + .close = v308_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), +}; diff --git a/ffmpeg/libavcodec/v408dec.c b/ffmpeg/libavcodec/v408dec.c new file mode 100644 index 0000000..31c14dc --- /dev/null +++ b/ffmpeg/libavcodec/v408dec.c @@ -0,0 +1,111 @@ +/* + * v408 decoder + * Copyright (c) 2012 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int v408_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUVA444P; + + return 0; +} + +static int v408_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *pic = data; + const uint8_t *src = avpkt->data; + uint8_t *y, *u, *v, *a; + int i, j, ret; + + if (avpkt->size < 4 * avctx->height * avctx->width) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + y = pic->data[0]; + u = pic->data[1]; + v = pic->data[2]; + a = pic->data[3]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width; j++) { + if (avctx->codec_id==AV_CODEC_ID_AYUV) { + v[j] = *src++; + u[j] = *src++; + y[j] = *src++; + a[j] = *src++; + } else { + u[j] = *src++; + y[j] = *src++; + v[j] = *src++; + a[j] = *src++; + } + } + + y += pic->linesize[0]; + u += pic->linesize[1]; + v += pic->linesize[2]; + a += pic->linesize[3]; + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int v408_decode_close(AVCodecContext *avctx) +{ + + return 0; +} + +#if CONFIG_AYUV_DECODER +AVCodec ff_ayuv_decoder = { + .name = "ayuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AYUV, + .init = v408_decode_init, + .decode = v408_decode_frame, + .close = v408_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), +}; +#endif +#if CONFIG_V408_DECODER +AVCodec ff_v408_decoder = { + .name = "v408", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V408, + .init = v408_decode_init, + .decode = v408_decode_frame, + .close = v408_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), +}; +#endif diff --git a/ffmpeg/libavcodec/v408enc.c b/ffmpeg/libavcodec/v408enc.c new file mode 100644 index 0000000..694bdbf --- /dev/null +++ b/ffmpeg/libavcodec/v408enc.c @@ -0,0 +1,113 @@ +/* + * v408 encoder + * + * Copyright (c) 2012 Carl Eugen Hoyos + * + * 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 "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +static av_cold int v408_encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int v408_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + uint8_t *dst; + uint8_t *y, *u, *v, *a; + int i, j, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width * avctx->height * 4)) < 0) + return ret; + dst = pkt->data; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + y = pic->data[0]; + u = pic->data[1]; + v = pic->data[2]; + a = pic->data[3]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width; j++) { + if (avctx->codec_id==AV_CODEC_ID_AYUV) { + *dst++ = v[j]; + *dst++ = u[j]; + *dst++ = y[j]; + *dst++ = a[j]; + } else { + *dst++ = u[j]; + *dst++ = y[j]; + *dst++ = v[j]; + *dst++ = a[j]; + } + } + y += pic->linesize[0]; + u += pic->linesize[1]; + v += pic->linesize[2]; + a += pic->linesize[3]; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int v408_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +#if CONFIG_AYUV_ENCODER +AVCodec ff_ayuv_encoder = { + .name = "ayuv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AYUV, + .init = v408_encode_init, + .encode2 = v408_encode_frame, + .close = v408_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), +}; +#endif +#if CONFIG_V408_ENCODER +AVCodec ff_v408_encoder = { + .name = "v408", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V408, + .init = v408_encode_init, + .encode2 = v408_encode_frame, + .close = v408_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), +}; +#endif diff --git a/ffmpeg/libavcodec/v410dec.c b/ffmpeg/libavcodec/v410dec.c new file mode 100644 index 0000000..f8229e2 --- /dev/null +++ b/ffmpeg/libavcodec/v410dec.c @@ -0,0 +1,98 @@ +/* + * v410 decoder + * + * Copyright (c) 2011 Derek Buitenhuis + * + * 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +static av_cold int v410_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV444P10; + avctx->bits_per_raw_sample = 10; + + if (avctx->width & 1) { + if (avctx->err_recognition & AV_EF_EXPLODE) { + av_log(avctx, AV_LOG_ERROR, "v410 requires width to be even.\n"); + return AVERROR_INVALIDDATA; + } else { + av_log(avctx, AV_LOG_WARNING, "v410 requires width to be even, continuing anyway.\n"); + } + } + + return 0; +} + +static int v410_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *pic = data; + uint8_t *src = avpkt->data; + uint16_t *y, *u, *v; + uint32_t val; + int i, j, ret; + + if (avpkt->size < 4 * avctx->height * avctx->width) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + y = (uint16_t *)pic->data[0]; + u = (uint16_t *)pic->data[1]; + v = (uint16_t *)pic->data[2]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width; j++) { + val = AV_RL32(src); + + u[j] = (val >> 2) & 0x3FF; + y[j] = (val >> 12) & 0x3FF; + v[j] = (val >> 22); + + src += 4; + } + + y += pic->linesize[0] >> 1; + u += pic->linesize[1] >> 1; + v += pic->linesize[2] >> 1; + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_v410_decoder = { + .name = "v410", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V410, + .init = v410_decode_init, + .decode = v410_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), +}; diff --git a/ffmpeg/libavcodec/v410enc.c b/ffmpeg/libavcodec/v410enc.c new file mode 100644 index 0000000..9661c7c --- /dev/null +++ b/ffmpeg/libavcodec/v410enc.c @@ -0,0 +1,98 @@ +/* + * v410 encoder + * + * Copyright (c) 2011 Derek Buitenhuis + * + * 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 "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +static av_cold int v410_encode_init(AVCodecContext *avctx) +{ + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "v410 requires width to be even.\n"); + return AVERROR_INVALIDDATA; + } + + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int v410_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + uint8_t *dst; + uint16_t *y, *u, *v; + uint32_t val; + int i, j, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width * avctx->height * 4)) < 0) + return ret; + dst = pkt->data; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + y = (uint16_t *)pic->data[0]; + u = (uint16_t *)pic->data[1]; + v = (uint16_t *)pic->data[2]; + + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < avctx->width; j++) { + val = u[j] << 2; + val |= y[j] << 12; + val |= (uint32_t) v[j] << 22; + AV_WL32(dst, val); + dst += 4; + } + y += pic->linesize[0] >> 1; + u += pic->linesize[1] >> 1; + v += pic->linesize[2] >> 1; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int v410_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_v410_encoder = { + .name = "v410", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_V410, + .init = v410_encode_init, + .encode2 = v410_encode_frame, + .close = v410_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), +}; diff --git a/ffmpeg/libavcodec/vaapi.c b/ffmpeg/libavcodec/vaapi.c new file mode 100644 index 0000000..a220a9d --- /dev/null +++ b/ffmpeg/libavcodec/vaapi.c @@ -0,0 +1,219 @@ +/* + * Video Acceleration API (video decoding) + * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 "h264.h" +#include "vaapi_internal.h" + +/** + * @addtogroup VAAPI_Decoding + * + * @{ + */ + +static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int n_buffers) +{ + unsigned int i; + for (i = 0; i < n_buffers; i++) { + if (buffers[i]) { + vaDestroyBuffer(display, buffers[i]); + buffers[i] = 0; + } + } +} + +int ff_vaapi_render_picture(struct vaapi_context *vactx, VASurfaceID surface) +{ + VABufferID va_buffers[3]; + unsigned int n_va_buffers = 0; + + vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id); + va_buffers[n_va_buffers++] = vactx->pic_param_buf_id; + + if (vactx->iq_matrix_buf_id) { + vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id); + va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id; + } + + if (vactx->bitplane_buf_id) { + vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id); + va_buffers[n_va_buffers++] = vactx->bitplane_buf_id; + } + + if (vaBeginPicture(vactx->display, vactx->context_id, + surface) != VA_STATUS_SUCCESS) + return -1; + + if (vaRenderPicture(vactx->display, vactx->context_id, + va_buffers, n_va_buffers) != VA_STATUS_SUCCESS) + return -1; + + if (vaRenderPicture(vactx->display, vactx->context_id, + vactx->slice_buf_ids, + vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS) + return -1; + + if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS) + return -1; + + return 0; +} + +int ff_vaapi_commit_slices(struct vaapi_context *vactx) +{ + VABufferID *slice_buf_ids; + VABufferID slice_param_buf_id, slice_data_buf_id; + + if (vactx->slice_count == 0) + return 0; + + slice_buf_ids = + av_fast_realloc(vactx->slice_buf_ids, + &vactx->slice_buf_ids_alloc, + (vactx->n_slice_buf_ids + 2) * sizeof(slice_buf_ids[0])); + if (!slice_buf_ids) + return -1; + vactx->slice_buf_ids = slice_buf_ids; + + slice_param_buf_id = 0; + if (vaCreateBuffer(vactx->display, vactx->context_id, + VASliceParameterBufferType, + vactx->slice_param_size, + vactx->slice_count, vactx->slice_params, + &slice_param_buf_id) != VA_STATUS_SUCCESS) + return -1; + vactx->slice_count = 0; + + slice_data_buf_id = 0; + if (vaCreateBuffer(vactx->display, vactx->context_id, + VASliceDataBufferType, + vactx->slice_data_size, + 1, (void *)vactx->slice_data, + &slice_data_buf_id) != VA_STATUS_SUCCESS) + return -1; + vactx->slice_data = NULL; + vactx->slice_data_size = 0; + + slice_buf_ids[vactx->n_slice_buf_ids++] = slice_param_buf_id; + slice_buf_ids[vactx->n_slice_buf_ids++] = slice_data_buf_id; + return 0; +} + +static void *alloc_buffer(struct vaapi_context *vactx, int type, unsigned int size, uint32_t *buf_id) +{ + void *data = NULL; + + *buf_id = 0; + if (vaCreateBuffer(vactx->display, vactx->context_id, + type, size, 1, NULL, buf_id) == VA_STATUS_SUCCESS) + vaMapBuffer(vactx->display, *buf_id, &data); + + return data; +} + +void *ff_vaapi_alloc_pic_param(struct vaapi_context *vactx, unsigned int size) +{ + return alloc_buffer(vactx, VAPictureParameterBufferType, size, &vactx->pic_param_buf_id); +} + +void *ff_vaapi_alloc_iq_matrix(struct vaapi_context *vactx, unsigned int size) +{ + return alloc_buffer(vactx, VAIQMatrixBufferType, size, &vactx->iq_matrix_buf_id); +} + +uint8_t *ff_vaapi_alloc_bitplane(struct vaapi_context *vactx, uint32_t size) +{ + return alloc_buffer(vactx, VABitPlaneBufferType, size, &vactx->bitplane_buf_id); +} + +VASliceParameterBufferBase *ff_vaapi_alloc_slice(struct vaapi_context *vactx, const uint8_t *buffer, uint32_t size) +{ + uint8_t *slice_params; + VASliceParameterBufferBase *slice_param; + + if (!vactx->slice_data) + vactx->slice_data = buffer; + if (vactx->slice_data + vactx->slice_data_size != buffer) { + if (ff_vaapi_commit_slices(vactx) < 0) + return NULL; + vactx->slice_data = buffer; + } + + slice_params = + av_fast_realloc(vactx->slice_params, + &vactx->slice_params_alloc, + (vactx->slice_count + 1) * vactx->slice_param_size); + if (!slice_params) + return NULL; + vactx->slice_params = slice_params; + + slice_param = (VASliceParameterBufferBase *)(slice_params + vactx->slice_count * vactx->slice_param_size); + slice_param->slice_data_size = size; + slice_param->slice_data_offset = vactx->slice_data_size; + slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; + + vactx->slice_count++; + vactx->slice_data_size += size; + return slice_param; +} + +void ff_vaapi_common_end_frame(AVCodecContext *avctx) +{ + struct vaapi_context * const vactx = avctx->hwaccel_context; + + av_dlog(avctx, "ff_vaapi_common_end_frame()\n"); + + destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1); + destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1); + destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1); + destroy_buffers(vactx->display, vactx->slice_buf_ids, vactx->n_slice_buf_ids); + av_freep(&vactx->slice_buf_ids); + av_freep(&vactx->slice_params); + vactx->n_slice_buf_ids = 0; + vactx->slice_buf_ids_alloc = 0; + vactx->slice_count = 0; + vactx->slice_params_alloc = 0; +} + +int ff_vaapi_mpeg_end_frame(AVCodecContext *avctx) +{ + struct vaapi_context * const vactx = avctx->hwaccel_context; + MpegEncContext *s = avctx->priv_data; + int ret; + + ret = ff_vaapi_commit_slices(vactx); + if (ret < 0) + goto finish; + + ret = ff_vaapi_render_picture(vactx, + ff_vaapi_get_surface_id(s->current_picture_ptr)); + if (ret < 0) + goto finish; + + ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); + +finish: + ff_vaapi_common_end_frame(avctx); + return ret; +} + +/* @} */ diff --git a/ffmpeg/libavcodec/vaapi.h b/ffmpeg/libavcodec/vaapi.h new file mode 100644 index 0000000..815a27e --- /dev/null +++ b/ffmpeg/libavcodec/vaapi.h @@ -0,0 +1,173 @@ +/* + * Video Acceleration API (shared data between FFmpeg and the video player) + * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 + */ + +#ifndef AVCODEC_VAAPI_H +#define AVCODEC_VAAPI_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vaapi + * Public libavcodec VA API header. + */ + +#include + +/** + * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding + * @ingroup lavc_codec_hwaccel + * @{ + */ + +/** + * This structure is used to share data between the FFmpeg library and + * the client video application. + * This shall be zero-allocated and available as + * AVCodecContext.hwaccel_context. All user members can be set once + * during initialization or through each AVCodecContext.get_buffer() + * function call. In any case, they must be valid prior to calling + * decoding functions. + */ +struct vaapi_context { + /** + * Window system dependent data + * + * - encoding: unused + * - decoding: Set by user + */ + void *display; + + /** + * Configuration ID + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t config_id; + + /** + * Context ID (video decode pipeline) + * + * - encoding: unused + * - decoding: Set by user + */ + uint32_t context_id; + + /** + * VAPictureParameterBuffer ID + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t pic_param_buf_id; + + /** + * VAIQMatrixBuffer ID + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t iq_matrix_buf_id; + + /** + * VABitPlaneBuffer ID (for VC-1 decoding) + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t bitplane_buf_id; + + /** + * Slice parameter/data buffer IDs + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t *slice_buf_ids; + + /** + * Number of effective slice buffer IDs to send to the HW + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int n_slice_buf_ids; + + /** + * Size of pre-allocated slice_buf_ids + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_buf_ids_alloc; + + /** + * Pointer to VASliceParameterBuffers + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + void *slice_params; + + /** + * Size of a VASliceParameterBuffer element + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_param_size; + + /** + * Size of pre-allocated slice_params + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_params_alloc; + + /** + * Number of slices currently filled in + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + unsigned int slice_count; + + /** + * Pointer to slice data buffer base + * - encoding: unused + * - decoding: Set by libavcodec + */ + const uint8_t *slice_data; + + /** + * Current size of slice data + * + * - encoding: unused + * - decoding: Set by libavcodec + */ + uint32_t slice_data_size; +}; + +/* @} */ + +#endif /* AVCODEC_VAAPI_H */ diff --git a/ffmpeg/libavcodec/vaapi_h264.c b/ffmpeg/libavcodec/vaapi_h264.c new file mode 100644 index 0000000..ea0f434 --- /dev/null +++ b/ffmpeg/libavcodec/vaapi_h264.c @@ -0,0 +1,361 @@ +/* + * H.264 HW decode acceleration through VA API + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 "vaapi_internal.h" +#include "h264.h" + +/** + * @file + * This file implements the glue code between FFmpeg's and VA API's + * structures for H.264 decoding. + */ + +/** + * Initialize an empty VA API picture. + * + * VA API requires a fixed-size reference picture array. + */ +static void init_vaapi_pic(VAPictureH264 *va_pic) +{ + va_pic->picture_id = VA_INVALID_ID; + va_pic->flags = VA_PICTURE_H264_INVALID; + va_pic->TopFieldOrderCnt = 0; + va_pic->BottomFieldOrderCnt = 0; +} + +/** + * Translate an FFmpeg Picture into its VA API form. + * + * @param[out] va_pic A pointer to VA API's own picture struct + * @param[in] pic A pointer to the FFmpeg picture struct to convert + * @param[in] pic_structure The picture field type (as defined in mpegvideo.h), + * supersedes pic's field type if nonzero. + */ +static void fill_vaapi_pic(VAPictureH264 *va_pic, + Picture *pic, + int pic_structure) +{ + if (pic_structure == 0) + pic_structure = pic->reference; + pic_structure &= PICT_FRAME; /* PICT_TOP_FIELD|PICT_BOTTOM_FIELD */ + + va_pic->picture_id = ff_vaapi_get_surface_id(pic); + va_pic->frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; + + va_pic->flags = 0; + if (pic_structure != PICT_FRAME) + va_pic->flags |= (pic_structure & PICT_TOP_FIELD) ? VA_PICTURE_H264_TOP_FIELD : VA_PICTURE_H264_BOTTOM_FIELD; + if (pic->reference) + va_pic->flags |= pic->long_ref ? VA_PICTURE_H264_LONG_TERM_REFERENCE : VA_PICTURE_H264_SHORT_TERM_REFERENCE; + + va_pic->TopFieldOrderCnt = 0; + if (pic->field_poc[0] != INT_MAX) + va_pic->TopFieldOrderCnt = pic->field_poc[0]; + + va_pic->BottomFieldOrderCnt = 0; + if (pic->field_poc[1] != INT_MAX) + va_pic->BottomFieldOrderCnt = pic->field_poc[1]; +} + +/** Decoded Picture Buffer (DPB). */ +typedef struct DPB { + int size; ///< Current number of reference frames in the DPB + int max_size; ///< Max number of reference frames. This is FF_ARRAY_ELEMS(VAPictureParameterBufferH264.ReferenceFrames) + VAPictureH264 *va_pics; ///< Pointer to VAPictureParameterBufferH264.ReferenceFrames array +} DPB; + +/** + * Append picture to the decoded picture buffer, in a VA API form that + * merges the second field picture attributes with the first, if + * available. The decoded picture buffer's size must be large enough + * to receive the new VA API picture object. + */ +static int dpb_add(DPB *dpb, Picture *pic) +{ + int i; + + if (dpb->size >= dpb->max_size) + return -1; + + for (i = 0; i < dpb->size; i++) { + VAPictureH264 * const va_pic = &dpb->va_pics[i]; + if (va_pic->picture_id == ff_vaapi_get_surface_id(pic)) { + VAPictureH264 temp_va_pic; + fill_vaapi_pic(&temp_va_pic, pic, 0); + + if ((temp_va_pic.flags ^ va_pic->flags) & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) { + va_pic->flags |= temp_va_pic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD); + /* Merge second field */ + if (temp_va_pic.flags & VA_PICTURE_H264_TOP_FIELD) { + va_pic->TopFieldOrderCnt = temp_va_pic.TopFieldOrderCnt; + } else { + va_pic->BottomFieldOrderCnt = temp_va_pic.BottomFieldOrderCnt; + } + } + return 0; + } + } + + fill_vaapi_pic(&dpb->va_pics[dpb->size++], pic, 0); + return 0; +} + +/** Fill in VA API reference frames array. */ +static int fill_vaapi_ReferenceFrames(VAPictureParameterBufferH264 *pic_param, + H264Context *h) +{ + DPB dpb; + int i; + + dpb.size = 0; + dpb.max_size = FF_ARRAY_ELEMS(pic_param->ReferenceFrames); + dpb.va_pics = pic_param->ReferenceFrames; + for (i = 0; i < dpb.max_size; i++) + init_vaapi_pic(&dpb.va_pics[i]); + + for (i = 0; i < h->short_ref_count; i++) { + Picture * const pic = h->short_ref[i]; + if (pic && pic->reference && dpb_add(&dpb, pic) < 0) + return -1; + } + + for (i = 0; i < 16; i++) { + Picture * const pic = h->long_ref[i]; + if (pic && pic->reference && dpb_add(&dpb, pic) < 0) + return -1; + } + return 0; +} + +/** + * Fill in VA API reference picture lists from the FFmpeg reference + * picture list. + * + * @param[out] RefPicList VA API internal reference picture list + * @param[in] ref_list A pointer to the FFmpeg reference list + * @param[in] ref_count The number of reference pictures in ref_list + */ +static void fill_vaapi_RefPicList(VAPictureH264 RefPicList[32], + Picture *ref_list, + unsigned int ref_count) +{ + unsigned int i, n = 0; + for (i = 0; i < ref_count; i++) + if (ref_list[i].reference) + fill_vaapi_pic(&RefPicList[n++], &ref_list[i], 0); + + for (; n < 32; n++) + init_vaapi_pic(&RefPicList[n]); +} + +/** + * Fill in prediction weight table. + * + * VA API requires a plain prediction weight table as it does not infer + * any value. + * + * @param[in] h A pointer to the current H.264 context + * @param[in] list The reference frame list index to use + * @param[out] luma_weight_flag VA API plain luma weight flag + * @param[out] luma_weight VA API plain luma weight table + * @param[out] luma_offset VA API plain luma offset table + * @param[out] chroma_weight_flag VA API plain chroma weight flag + * @param[out] chroma_weight VA API plain chroma weight table + * @param[out] chroma_offset VA API plain chroma offset table + */ +static void fill_vaapi_plain_pred_weight_table(H264Context *h, + int list, + unsigned char *luma_weight_flag, + short luma_weight[32], + short luma_offset[32], + unsigned char *chroma_weight_flag, + short chroma_weight[32][2], + short chroma_offset[32][2]) +{ + unsigned int i, j; + + *luma_weight_flag = h->luma_weight_flag[list]; + *chroma_weight_flag = h->chroma_weight_flag[list]; + + for (i = 0; i < h->ref_count[list]; i++) { + /* VA API also wants the inferred (default) values, not + only what is available in the bitstream (7.4.3.2). */ + if (h->luma_weight_flag[list]) { + luma_weight[i] = h->luma_weight[i][list][0]; + luma_offset[i] = h->luma_weight[i][list][1]; + } else { + luma_weight[i] = 1 << h->luma_log2_weight_denom; + luma_offset[i] = 0; + } + for (j = 0; j < 2; j++) { + if (h->chroma_weight_flag[list]) { + chroma_weight[i][j] = h->chroma_weight[i][list][j][0]; + chroma_offset[i][j] = h->chroma_weight[i][list][j][1]; + } else { + chroma_weight[i][j] = 1 << h->chroma_log2_weight_denom; + chroma_offset[i][j] = 0; + } + } + } +} + +/** Initialize and start decoding a frame with VA API. */ +static int vaapi_h264_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + H264Context * const h = avctx->priv_data; + struct vaapi_context * const vactx = avctx->hwaccel_context; + VAPictureParameterBufferH264 *pic_param; + VAIQMatrixBufferH264 *iq_matrix; + + av_dlog(avctx, "vaapi_h264_start_frame()\n"); + + vactx->slice_param_size = sizeof(VASliceParameterBufferH264); + + /* Fill in VAPictureParameterBufferH264. */ + pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferH264)); + if (!pic_param) + return -1; + fill_vaapi_pic(&pic_param->CurrPic, h->cur_pic_ptr, h->picture_structure); + if (fill_vaapi_ReferenceFrames(pic_param, h) < 0) + return -1; + pic_param->picture_width_in_mbs_minus1 = h->mb_width - 1; + pic_param->picture_height_in_mbs_minus1 = h->mb_height - 1; + pic_param->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; + pic_param->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; + pic_param->num_ref_frames = h->sps.ref_frame_count; + pic_param->seq_fields.value = 0; /* reset all bits */ + pic_param->seq_fields.bits.chroma_format_idc = h->sps.chroma_format_idc; + pic_param->seq_fields.bits.residual_colour_transform_flag = h->sps.residual_color_transform_flag; /* XXX: only for 4:4:4 high profile? */ + pic_param->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag; + pic_param->seq_fields.bits.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; + pic_param->seq_fields.bits.mb_adaptive_frame_field_flag = h->sps.mb_aff; + pic_param->seq_fields.bits.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; + pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = h->sps.level_idc >= 31; /* A.3.3.2 */ + pic_param->seq_fields.bits.log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; + pic_param->seq_fields.bits.pic_order_cnt_type = h->sps.poc_type; + pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; + pic_param->seq_fields.bits.delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; + pic_param->num_slice_groups_minus1 = h->pps.slice_group_count - 1; + pic_param->slice_group_map_type = h->pps.mb_slice_group_map_type; + pic_param->slice_group_change_rate_minus1 = 0; /* XXX: unimplemented in FFmpeg */ + pic_param->pic_init_qp_minus26 = h->pps.init_qp - 26; + pic_param->pic_init_qs_minus26 = h->pps.init_qs - 26; + pic_param->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; + pic_param->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + pic_param->pic_fields.value = 0; /* reset all bits */ + pic_param->pic_fields.bits.entropy_coding_mode_flag = h->pps.cabac; + pic_param->pic_fields.bits.weighted_pred_flag = h->pps.weighted_pred; + pic_param->pic_fields.bits.weighted_bipred_idc = h->pps.weighted_bipred_idc; + pic_param->pic_fields.bits.transform_8x8_mode_flag = h->pps.transform_8x8_mode; + pic_param->pic_fields.bits.field_pic_flag = h->picture_structure != PICT_FRAME; + pic_param->pic_fields.bits.constrained_intra_pred_flag = h->pps.constrained_intra_pred; + pic_param->pic_fields.bits.pic_order_present_flag = h->pps.pic_order_present; + pic_param->pic_fields.bits.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; + pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; + pic_param->pic_fields.bits.reference_pic_flag = h->nal_ref_idc != 0; + pic_param->frame_num = h->frame_num; + + /* Fill in VAIQMatrixBufferH264. */ + iq_matrix = ff_vaapi_alloc_iq_matrix(vactx, sizeof(VAIQMatrixBufferH264)); + if (!iq_matrix) + return -1; + memcpy(iq_matrix->ScalingList4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->ScalingList4x4)); + memcpy(iq_matrix->ScalingList8x8[0], h->pps.scaling_matrix8[0], sizeof(iq_matrix->ScalingList8x8[0])); + memcpy(iq_matrix->ScalingList8x8[1], h->pps.scaling_matrix8[3], sizeof(iq_matrix->ScalingList8x8[0])); + return 0; +} + +/** End a hardware decoding based frame. */ +static int vaapi_h264_end_frame(AVCodecContext *avctx) +{ + struct vaapi_context * const vactx = avctx->hwaccel_context; + H264Context * const h = avctx->priv_data; + int ret; + + av_dlog(avctx, "vaapi_h264_end_frame()\n"); + ret = ff_vaapi_commit_slices(vactx); + if (ret < 0) + goto finish; + + ret = ff_vaapi_render_picture(vactx, ff_vaapi_get_surface_id(h->cur_pic_ptr)); + if (ret < 0) + goto finish; + + ff_h264_draw_horiz_band(h, 0, h->avctx->height); + +finish: + ff_vaapi_common_end_frame(avctx); + return ret; +} + +/** Decode the given H.264 slice with VA API. */ +static int vaapi_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + H264Context * const h = avctx->priv_data; + VASliceParameterBufferH264 *slice_param; + + av_dlog(avctx, "vaapi_h264_decode_slice(): buffer %p, size %d\n", + buffer, size); + + /* Fill in VASliceParameterBufferH264. */ + slice_param = (VASliceParameterBufferH264 *)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size); + if (!slice_param) + return -1; + slice_param->slice_data_bit_offset = get_bits_count(&h->gb) + 8; /* bit buffer started beyond nal_unit_type */ + slice_param->first_mb_in_slice = (h->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + h->mb_x; + slice_param->slice_type = ff_h264_get_slice_type(h); + slice_param->direct_spatial_mv_pred_flag = h->slice_type == AV_PICTURE_TYPE_B ? h->direct_spatial_mv_pred : 0; + slice_param->num_ref_idx_l0_active_minus1 = h->list_count > 0 ? h->ref_count[0] - 1 : 0; + slice_param->num_ref_idx_l1_active_minus1 = h->list_count > 1 ? h->ref_count[1] - 1 : 0; + slice_param->cabac_init_idc = h->cabac_init_idc; + slice_param->slice_qp_delta = h->qscale - h->pps.init_qp; + slice_param->disable_deblocking_filter_idc = h->deblocking_filter < 2 ? !h->deblocking_filter : h->deblocking_filter; + slice_param->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2 - 26; + slice_param->slice_beta_offset_div2 = h->slice_beta_offset / 2 - 26; + slice_param->luma_log2_weight_denom = h->luma_log2_weight_denom; + slice_param->chroma_log2_weight_denom = h->chroma_log2_weight_denom; + + fill_vaapi_RefPicList(slice_param->RefPicList0, h->ref_list[0], h->list_count > 0 ? h->ref_count[0] : 0); + fill_vaapi_RefPicList(slice_param->RefPicList1, h->ref_list[1], h->list_count > 1 ? h->ref_count[1] : 0); + + fill_vaapi_plain_pred_weight_table(h, 0, + &slice_param->luma_weight_l0_flag, slice_param->luma_weight_l0, slice_param->luma_offset_l0, + &slice_param->chroma_weight_l0_flag, slice_param->chroma_weight_l0, slice_param->chroma_offset_l0); + fill_vaapi_plain_pred_weight_table(h, 1, + &slice_param->luma_weight_l1_flag, slice_param->luma_weight_l1, slice_param->luma_offset_l1, + &slice_param->chroma_weight_l1_flag, slice_param->chroma_weight_l1, slice_param->chroma_offset_l1); + return 0; +} + +AVHWAccel ff_h264_vaapi_hwaccel = { + .name = "h264_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .start_frame = vaapi_h264_start_frame, + .end_frame = vaapi_h264_end_frame, + .decode_slice = vaapi_h264_decode_slice, +}; diff --git a/ffmpeg/libavcodec/vaapi_internal.h b/ffmpeg/libavcodec/vaapi_internal.h new file mode 100644 index 0000000..1ac0e9f --- /dev/null +++ b/ffmpeg/libavcodec/vaapi_internal.h @@ -0,0 +1,72 @@ +/* + * Video Acceleration API (video decoding) + * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 + */ + +#ifndef AVCODEC_VAAPI_INTERNAL_H +#define AVCODEC_VAAPI_INTERNAL_H + +#include +#include "vaapi.h" +#include "avcodec.h" +#include "mpegvideo.h" + +/** + * @addtogroup VAAPI_Decoding + * + * @{ + */ + +/** Extract VASurfaceID from a Picture */ +static inline VASurfaceID ff_vaapi_get_surface_id(Picture *pic) +{ + return (uintptr_t)pic->f.data[3]; +} + +/** Common AVHWAccel.end_frame() implementation */ +void ff_vaapi_common_end_frame(AVCodecContext *avctx); + +/** Allocate a new picture parameter buffer */ +void *ff_vaapi_alloc_pic_param(struct vaapi_context *vactx, unsigned int size); + +/** Allocate a new IQ matrix buffer */ +void *ff_vaapi_alloc_iq_matrix(struct vaapi_context *vactx, unsigned int size); + +/** Allocate a new bit-plane buffer */ +uint8_t *ff_vaapi_alloc_bitplane(struct vaapi_context *vactx, uint32_t size); + +/** + * Allocate a new slice descriptor for the input slice. + * + * @param vactx the VA API context + * @param buffer the slice data buffer base + * @param size the size of the slice in bytes + * @return the newly allocated slice parameter + */ +VASliceParameterBufferBase *ff_vaapi_alloc_slice(struct vaapi_context *vactx, const uint8_t *buffer, uint32_t size); + +int ff_vaapi_mpeg_end_frame(AVCodecContext *avctx); +int ff_vaapi_commit_slices(struct vaapi_context *vactx); +int ff_vaapi_render_picture(struct vaapi_context *vactx, VASurfaceID surface); + +/* @} */ + +#endif /* AVCODEC_VAAPI_INTERNAL_H */ diff --git a/ffmpeg/libavcodec/vaapi_mpeg2.c b/ffmpeg/libavcodec/vaapi_mpeg2.c new file mode 100644 index 0000000..d626f24 --- /dev/null +++ b/ffmpeg/libavcodec/vaapi_mpeg2.c @@ -0,0 +1,143 @@ +/* + * MPEG-2 HW decode acceleration through VA API + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 "vaapi_internal.h" + +/** Reconstruct bitstream f_code */ +static inline int mpeg2_get_f_code(MpegEncContext *s) +{ + return (s->mpeg_f_code[0][0] << 12) | (s->mpeg_f_code[0][1] << 8) | + (s->mpeg_f_code[1][0] << 4) | s->mpeg_f_code[1][1]; +} + +/** Determine frame start: first field for field picture or frame picture */ +static inline int mpeg2_get_is_frame_start(MpegEncContext *s) +{ + return s->first_field || s->picture_structure == PICT_FRAME; +} + +static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) +{ + struct MpegEncContext * const s = avctx->priv_data; + struct vaapi_context * const vactx = avctx->hwaccel_context; + VAPictureParameterBufferMPEG2 *pic_param; + VAIQMatrixBufferMPEG2 *iq_matrix; + int i; + + av_dlog(avctx, "vaapi_mpeg2_start_frame()\n"); + + vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG2); + + /* Fill in VAPictureParameterBufferMPEG2 */ + pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferMPEG2)); + if (!pic_param) + return -1; + pic_param->horizontal_size = s->width; + pic_param->vertical_size = s->height; + pic_param->forward_reference_picture = VA_INVALID_ID; + pic_param->backward_reference_picture = VA_INVALID_ID; + pic_param->picture_coding_type = s->pict_type; + pic_param->f_code = mpeg2_get_f_code(s); + pic_param->picture_coding_extension.value = 0; /* reset all bits */ + pic_param->picture_coding_extension.bits.intra_dc_precision = s->intra_dc_precision; + pic_param->picture_coding_extension.bits.picture_structure = s->picture_structure; + pic_param->picture_coding_extension.bits.top_field_first = s->top_field_first; + pic_param->picture_coding_extension.bits.frame_pred_frame_dct = s->frame_pred_frame_dct; + pic_param->picture_coding_extension.bits.concealment_motion_vectors = s->concealment_motion_vectors; + pic_param->picture_coding_extension.bits.q_scale_type = s->q_scale_type; + pic_param->picture_coding_extension.bits.intra_vlc_format = s->intra_vlc_format; + pic_param->picture_coding_extension.bits.alternate_scan = s->alternate_scan; + pic_param->picture_coding_extension.bits.repeat_first_field = s->repeat_first_field; + pic_param->picture_coding_extension.bits.progressive_frame = s->progressive_frame; + pic_param->picture_coding_extension.bits.is_first_field = mpeg2_get_is_frame_start(s); + + switch (s->pict_type) { + case AV_PICTURE_TYPE_B: + pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture); + // fall-through + case AV_PICTURE_TYPE_P: + pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture); + break; + } + + /* Fill in VAIQMatrixBufferMPEG2 */ + iq_matrix = ff_vaapi_alloc_iq_matrix(vactx, sizeof(VAIQMatrixBufferMPEG2)); + if (!iq_matrix) + return -1; + iq_matrix->load_intra_quantiser_matrix = 1; + iq_matrix->load_non_intra_quantiser_matrix = 1; + iq_matrix->load_chroma_intra_quantiser_matrix = 1; + iq_matrix->load_chroma_non_intra_quantiser_matrix = 1; + + for (i = 0; i < 64; i++) { + int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + iq_matrix->intra_quantiser_matrix[i] = s->intra_matrix[n]; + iq_matrix->non_intra_quantiser_matrix[i] = s->inter_matrix[n]; + iq_matrix->chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n]; + iq_matrix->chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n]; + } + return 0; +} + +static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + MpegEncContext * const s = avctx->priv_data; + VASliceParameterBufferMPEG2 *slice_param; + GetBitContext gb; + uint32_t quantiser_scale_code, intra_slice_flag, macroblock_offset; + + av_dlog(avctx, "vaapi_mpeg2_decode_slice(): buffer %p, size %d\n", buffer, size); + + /* Determine macroblock_offset */ + init_get_bits(&gb, buffer, 8 * size); + if (get_bits_long(&gb, 32) >> 8 != 1) /* start code */ + return AVERROR_INVALIDDATA; + quantiser_scale_code = get_bits(&gb, 5); + intra_slice_flag = get_bits1(&gb); + if (intra_slice_flag) { + skip_bits(&gb, 8); + while (get_bits1(&gb) != 0) + skip_bits(&gb, 8); + } + macroblock_offset = get_bits_count(&gb); + + /* Fill in VASliceParameterBufferMPEG2 */ + slice_param = (VASliceParameterBufferMPEG2 *)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size); + if (!slice_param) + return -1; + slice_param->macroblock_offset = macroblock_offset; + slice_param->slice_horizontal_position = s->mb_x; + slice_param->slice_vertical_position = s->mb_y >> (s->picture_structure != PICT_FRAME); + slice_param->quantiser_scale_code = quantiser_scale_code; + slice_param->intra_slice_flag = intra_slice_flag; + return 0; +} + +AVHWAccel ff_mpeg2_vaapi_hwaccel = { + .name = "mpeg2_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .start_frame = vaapi_mpeg2_start_frame, + .end_frame = ff_vaapi_mpeg_end_frame, + .decode_slice = vaapi_mpeg2_decode_slice, +}; diff --git a/ffmpeg/libavcodec/vaapi_mpeg4.c b/ffmpeg/libavcodec/vaapi_mpeg4.c new file mode 100644 index 0000000..bcc0eba --- /dev/null +++ b/ffmpeg/libavcodec/vaapi_mpeg4.c @@ -0,0 +1,169 @@ +/* + * MPEG-4 / H.263 HW decode acceleration through VA API + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 "vaapi_internal.h" +#include "h263.h" + +/** Reconstruct bitstream intra_dc_vlc_thr */ +static int mpeg4_get_intra_dc_vlc_thr(MpegEncContext *s) +{ + switch (s->intra_dc_threshold) { + case 99: return 0; + case 13: return 1; + case 15: return 2; + case 17: return 3; + case 19: return 4; + case 21: return 5; + case 23: return 6; + case 0: return 7; + } + return 0; +} + +static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) +{ + MpegEncContext * const s = avctx->priv_data; + struct vaapi_context * const vactx = avctx->hwaccel_context; + VAPictureParameterBufferMPEG4 *pic_param; + VAIQMatrixBufferMPEG4 *iq_matrix; + int i; + + av_dlog(avctx, "vaapi_mpeg4_start_frame()\n"); + + vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG4); + + /* Fill in VAPictureParameterBufferMPEG4 */ + pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferMPEG4)); + if (!pic_param) + return -1; + pic_param->vop_width = s->width; + pic_param->vop_height = s->height; + pic_param->forward_reference_picture = VA_INVALID_ID; + pic_param->backward_reference_picture = VA_INVALID_ID; + pic_param->vol_fields.value = 0; /* reset all bits */ + pic_param->vol_fields.bits.short_video_header = avctx->codec->id == AV_CODEC_ID_H263; + pic_param->vol_fields.bits.chroma_format = CHROMA_420; + pic_param->vol_fields.bits.interlaced = !s->progressive_sequence; + pic_param->vol_fields.bits.obmc_disable = 1; + pic_param->vol_fields.bits.sprite_enable = s->vol_sprite_usage; + pic_param->vol_fields.bits.sprite_warping_accuracy = s->sprite_warping_accuracy; + pic_param->vol_fields.bits.quant_type = s->mpeg_quant; + pic_param->vol_fields.bits.quarter_sample = s->quarter_sample; + pic_param->vol_fields.bits.data_partitioned = s->data_partitioning; + pic_param->vol_fields.bits.reversible_vlc = s->rvlc; + pic_param->vol_fields.bits.resync_marker_disable = !s->resync_marker; + pic_param->no_of_sprite_warping_points = s->num_sprite_warping_points; + for (i = 0; i < s->num_sprite_warping_points && i < 3; i++) { + pic_param->sprite_trajectory_du[i] = s->sprite_traj[i][0]; + pic_param->sprite_trajectory_dv[i] = s->sprite_traj[i][1]; + } + pic_param->quant_precision = s->quant_precision; + pic_param->vop_fields.value = 0; /* reset all bits */ + pic_param->vop_fields.bits.vop_coding_type = s->pict_type - AV_PICTURE_TYPE_I; + pic_param->vop_fields.bits.backward_reference_vop_coding_type = s->pict_type == AV_PICTURE_TYPE_B ? s->next_picture.f.pict_type - AV_PICTURE_TYPE_I : 0; + pic_param->vop_fields.bits.vop_rounding_type = s->no_rounding; + pic_param->vop_fields.bits.intra_dc_vlc_thr = mpeg4_get_intra_dc_vlc_thr(s); + pic_param->vop_fields.bits.top_field_first = s->top_field_first; + pic_param->vop_fields.bits.alternate_vertical_scan_flag = s->alternate_scan; + pic_param->vop_fcode_forward = s->f_code; + pic_param->vop_fcode_backward = s->b_code; + pic_param->vop_time_increment_resolution = avctx->time_base.den; + pic_param->num_macroblocks_in_gob = s->mb_width * ff_h263_get_gob_height(s); + pic_param->num_gobs_in_vop = (s->mb_width * s->mb_height) / pic_param->num_macroblocks_in_gob; + pic_param->TRB = s->pb_time; + pic_param->TRD = s->pp_time; + + if (s->pict_type == AV_PICTURE_TYPE_B) + pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture); + if (s->pict_type != AV_PICTURE_TYPE_I) + pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture); + + /* Fill in VAIQMatrixBufferMPEG4 */ + /* Only the first inverse quantisation method uses the weighting matrices */ + if (pic_param->vol_fields.bits.quant_type) { + iq_matrix = ff_vaapi_alloc_iq_matrix(vactx, sizeof(VAIQMatrixBufferMPEG4)); + if (!iq_matrix) + return -1; + iq_matrix->load_intra_quant_mat = 1; + iq_matrix->load_non_intra_quant_mat = 1; + + for (i = 0; i < 64; i++) { + int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; + iq_matrix->intra_quant_mat[i] = s->intra_matrix[n]; + iq_matrix->non_intra_quant_mat[i] = s->inter_matrix[n]; + } + } + return 0; +} + +static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + MpegEncContext * const s = avctx->priv_data; + VASliceParameterBufferMPEG4 *slice_param; + + av_dlog(avctx, "vaapi_mpeg4_decode_slice(): buffer %p, size %d\n", buffer, size); + + /* video_plane_with_short_video_header() contains all GOBs + * in-order, and this is what VA API (Intel backend) expects: only + * a single slice param. So fake macroblock_number for FFmpeg so + * that we don't call vaapi_mpeg4_decode_slice() again + */ + if (avctx->codec->id == AV_CODEC_ID_H263) + size = s->gb.buffer_end - buffer; + + /* Fill in VASliceParameterBufferMPEG4 */ + slice_param = (VASliceParameterBufferMPEG4 *)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size); + if (!slice_param) + return -1; + slice_param->macroblock_offset = get_bits_count(&s->gb) % 8; + slice_param->macroblock_number = s->mb_y * s->mb_width + s->mb_x; + slice_param->quant_scale = s->qscale; + + if (avctx->codec->id == AV_CODEC_ID_H263) + s->mb_y = s->mb_height; + + return 0; +} + +#if CONFIG_MPEG4_VAAPI_HWACCEL +AVHWAccel ff_mpeg4_vaapi_hwaccel = { + .name = "mpeg4_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .start_frame = vaapi_mpeg4_start_frame, + .end_frame = ff_vaapi_mpeg_end_frame, + .decode_slice = vaapi_mpeg4_decode_slice, +}; +#endif + +#if CONFIG_H263_VAAPI_HWACCEL +AVHWAccel ff_h263_vaapi_hwaccel = { + .name = "h263_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263, + .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .start_frame = vaapi_mpeg4_start_frame, + .end_frame = ff_vaapi_mpeg_end_frame, + .decode_slice = vaapi_mpeg4_decode_slice, +}; +#endif diff --git a/ffmpeg/libavcodec/vaapi_vc1.c b/ffmpeg/libavcodec/vaapi_vc1.c new file mode 100644 index 0000000..b8f0530 --- /dev/null +++ b/ffmpeg/libavcodec/vaapi_vc1.c @@ -0,0 +1,356 @@ +/* + * VC-1 HW decode acceleration through VA API + * + * Copyright (C) 2008-2009 Splitted-Desktop Systems + * + * 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 "vaapi_internal.h" +#include "vc1.h" +#include "vc1data.h" + +/** Translate FFmpeg MV modes to VA API */ +static int get_VAMvModeVC1(enum MVModes mv_mode) +{ + switch (mv_mode) { + case MV_PMODE_1MV_HPEL_BILIN: return VAMvMode1MvHalfPelBilinear; + case MV_PMODE_1MV: return VAMvMode1Mv; + case MV_PMODE_1MV_HPEL: return VAMvMode1MvHalfPel; + case MV_PMODE_MIXED_MV: return VAMvModeMixedMv; + case MV_PMODE_INTENSITY_COMP: return VAMvModeIntensityCompensation; + } + return 0; +} + +/** Check whether the MVTYPEMB bitplane is present */ +static inline int vc1_has_MVTYPEMB_bitplane(VC1Context *v) +{ + if (v->mv_type_is_raw) + return 0; + return v->s.pict_type == AV_PICTURE_TYPE_P && + (v->mv_mode == MV_PMODE_MIXED_MV || + (v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->mv_mode2 == MV_PMODE_MIXED_MV)); +} + +/** Check whether the SKIPMB bitplane is present */ +static inline int vc1_has_SKIPMB_bitplane(VC1Context *v) +{ + if (v->skip_is_raw) + return 0; + return v->s.pict_type == AV_PICTURE_TYPE_P || + (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type); +} + +/** Check whether the DIRECTMB bitplane is present */ +static inline int vc1_has_DIRECTMB_bitplane(VC1Context *v) +{ + if (v->dmb_is_raw) + return 0; + return v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type; +} + +/** Check whether the ACPRED bitplane is present */ +static inline int vc1_has_ACPRED_bitplane(VC1Context *v) +{ + if (v->acpred_is_raw) + return 0; + return v->profile == PROFILE_ADVANCED && + (v->s.pict_type == AV_PICTURE_TYPE_I || + (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type)); +} + +/** Check whether the OVERFLAGS bitplane is present */ +static inline int vc1_has_OVERFLAGS_bitplane(VC1Context *v) +{ + if (v->overflg_is_raw) + return 0; + return v->profile == PROFILE_ADVANCED && + (v->s.pict_type == AV_PICTURE_TYPE_I || + (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type)) && + (v->overlap && v->pq <= 8) && + v->condover == CONDOVER_SELECT; +} + +/** Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */ +static int vc1_get_PTYPE(VC1Context *v) +{ + MpegEncContext * const s = &v->s; + switch (s->pict_type) { + case AV_PICTURE_TYPE_I: return 0; + case AV_PICTURE_TYPE_P: return v->p_frame_skipped ? 4 : 1; + case AV_PICTURE_TYPE_B: return v->bi_type ? 3 : 2; + } + return 0; +} + +/** Reconstruct bitstream MVMODE (7.1.1.32) */ +static inline VAMvModeVC1 vc1_get_MVMODE(VC1Context *v) +{ + if (v->s.pict_type == AV_PICTURE_TYPE_P || + (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type)) + return get_VAMvModeVC1(v->mv_mode); + return 0; +} + +/** Reconstruct bitstream MVMODE2 (7.1.1.33) */ +static inline VAMvModeVC1 vc1_get_MVMODE2(VC1Context *v) +{ + if (v->s.pict_type == AV_PICTURE_TYPE_P && v->mv_mode == MV_PMODE_INTENSITY_COMP) + return get_VAMvModeVC1(v->mv_mode2); + return 0; +} + +/** Reconstruct bitstream TTFRM (7.1.1.41, Table-53) */ +static inline int vc1_get_TTFRM(VC1Context *v) +{ + switch (v->ttfrm) { + case TT_8X8: return 0; + case TT_8X4: return 1; + case TT_4X8: return 2; + case TT_4X4: return 3; + } + return 0; +} + +/** Pack FFmpeg bitplanes into a VABitPlaneBuffer element */ +static inline void vc1_pack_bitplanes(uint8_t *bitplane, int n, const uint8_t *ff_bp[3], int x, int y, int stride) +{ + const int bitplane_index = n / 2; + const int ff_bp_index = y * stride + x; + uint8_t v = 0; + if (ff_bp[0]) + v = ff_bp[0][ff_bp_index]; + if (ff_bp[1]) + v |= ff_bp[1][ff_bp_index] << 1; + if (ff_bp[2]) + v |= ff_bp[2][ff_bp_index] << 2; + bitplane[bitplane_index] = (bitplane[bitplane_index] << 4) | v; +} + +static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) +{ + VC1Context * const v = avctx->priv_data; + MpegEncContext * const s = &v->s; + struct vaapi_context * const vactx = avctx->hwaccel_context; + VAPictureParameterBufferVC1 *pic_param; + + av_dlog(avctx, "vaapi_vc1_start_frame()\n"); + + vactx->slice_param_size = sizeof(VASliceParameterBufferVC1); + + /* Fill in VAPictureParameterBufferVC1 */ + pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferVC1)); + if (!pic_param) + return -1; + pic_param->forward_reference_picture = VA_INVALID_ID; + pic_param->backward_reference_picture = VA_INVALID_ID; + pic_param->inloop_decoded_picture = VA_INVALID_ID; + pic_param->sequence_fields.value = 0; /* reset all bits */ + pic_param->sequence_fields.bits.pulldown = v->broadcast; + pic_param->sequence_fields.bits.interlace = v->interlace; + pic_param->sequence_fields.bits.tfcntrflag = v->tfcntrflag; + pic_param->sequence_fields.bits.finterpflag = v->finterpflag; + pic_param->sequence_fields.bits.psf = v->psf; + pic_param->sequence_fields.bits.multires = v->multires; + pic_param->sequence_fields.bits.overlap = v->overlap; + pic_param->sequence_fields.bits.syncmarker = s->resync_marker; + pic_param->sequence_fields.bits.rangered = v->rangered; + pic_param->sequence_fields.bits.max_b_frames = s->avctx->max_b_frames; +#if VA_CHECK_VERSION(0,32,0) + pic_param->sequence_fields.bits.profile = v->profile; +#endif + pic_param->coded_width = s->avctx->coded_width; + pic_param->coded_height = s->avctx->coded_height; + pic_param->entrypoint_fields.value = 0; /* reset all bits */ + pic_param->entrypoint_fields.bits.broken_link = v->broken_link; + pic_param->entrypoint_fields.bits.closed_entry = v->closed_entry; + pic_param->entrypoint_fields.bits.panscan_flag = v->panscanflag; + pic_param->entrypoint_fields.bits.loopfilter = s->loop_filter; + pic_param->conditional_overlap_flag = v->condover; + pic_param->fast_uvmc_flag = v->fastuvmc; + pic_param->range_mapping_fields.value = 0; /* reset all bits */ + pic_param->range_mapping_fields.bits.luma_flag = v->range_mapy_flag; + pic_param->range_mapping_fields.bits.luma = v->range_mapy; + pic_param->range_mapping_fields.bits.chroma_flag = v->range_mapuv_flag; + pic_param->range_mapping_fields.bits.chroma = v->range_mapuv; + pic_param->b_picture_fraction = v->bfraction_lut_index; + pic_param->cbp_table = v->cbpcy_vlc ? v->cbpcy_vlc - ff_vc1_cbpcy_p_vlc : 0; + pic_param->mb_mode_table = 0; /* XXX: interlaced frame */ + pic_param->range_reduction_frame = v->rangeredfrm; + pic_param->rounding_control = v->rnd; + pic_param->post_processing = v->postproc; + pic_param->picture_resolution_index = v->respic; + pic_param->luma_scale = v->lumscale; + pic_param->luma_shift = v->lumshift; + pic_param->picture_fields.value = 0; /* reset all bits */ + pic_param->picture_fields.bits.picture_type = vc1_get_PTYPE(v); + pic_param->picture_fields.bits.frame_coding_mode = v->fcm; + pic_param->picture_fields.bits.top_field_first = v->tff; + pic_param->picture_fields.bits.is_first_field = v->fcm == 0; /* XXX: interlaced frame */ + pic_param->picture_fields.bits.intensity_compensation = v->mv_mode == MV_PMODE_INTENSITY_COMP; + pic_param->raw_coding.value = 0; /* reset all bits */ + pic_param->raw_coding.flags.mv_type_mb = v->mv_type_is_raw; + pic_param->raw_coding.flags.direct_mb = v->dmb_is_raw; + pic_param->raw_coding.flags.skip_mb = v->skip_is_raw; + pic_param->raw_coding.flags.field_tx = 0; /* XXX: interlaced frame */ + pic_param->raw_coding.flags.forward_mb = 0; /* XXX: interlaced frame */ + pic_param->raw_coding.flags.ac_pred = v->acpred_is_raw; + pic_param->raw_coding.flags.overflags = v->overflg_is_raw; + pic_param->bitplane_present.value = 0; /* reset all bits */ + pic_param->bitplane_present.flags.bp_mv_type_mb = vc1_has_MVTYPEMB_bitplane(v); + pic_param->bitplane_present.flags.bp_direct_mb = vc1_has_DIRECTMB_bitplane(v); + pic_param->bitplane_present.flags.bp_skip_mb = vc1_has_SKIPMB_bitplane(v); + pic_param->bitplane_present.flags.bp_field_tx = 0; /* XXX: interlaced frame */ + pic_param->bitplane_present.flags.bp_forward_mb = 0; /* XXX: interlaced frame */ + pic_param->bitplane_present.flags.bp_ac_pred = vc1_has_ACPRED_bitplane(v); + pic_param->bitplane_present.flags.bp_overflags = vc1_has_OVERFLAGS_bitplane(v); + pic_param->reference_fields.value = 0; /* reset all bits */ + pic_param->reference_fields.bits.reference_distance_flag = v->refdist_flag; + pic_param->reference_fields.bits.reference_distance = 0; /* XXX: interlaced frame */ + pic_param->reference_fields.bits.num_reference_pictures = 0; /* XXX: interlaced frame */ + pic_param->reference_fields.bits.reference_field_pic_indicator = 0; /* XXX: interlaced frame */ + pic_param->mv_fields.value = 0; /* reset all bits */ + pic_param->mv_fields.bits.mv_mode = vc1_get_MVMODE(v); + pic_param->mv_fields.bits.mv_mode2 = vc1_get_MVMODE2(v); + pic_param->mv_fields.bits.mv_table = s->mv_table_index; + pic_param->mv_fields.bits.two_mv_block_pattern_table = 0; /* XXX: interlaced frame */ + pic_param->mv_fields.bits.four_mv_switch = 0; /* XXX: interlaced frame */ + pic_param->mv_fields.bits.four_mv_block_pattern_table = 0; /* XXX: interlaced frame */ + pic_param->mv_fields.bits.extended_mv_flag = v->extended_mv; + pic_param->mv_fields.bits.extended_mv_range = v->mvrange; + pic_param->mv_fields.bits.extended_dmv_flag = v->extended_dmv; + pic_param->mv_fields.bits.extended_dmv_range = 0; /* XXX: interlaced frame */ + pic_param->pic_quantizer_fields.value = 0; /* reset all bits */ + pic_param->pic_quantizer_fields.bits.dquant = v->dquant; + pic_param->pic_quantizer_fields.bits.quantizer = v->quantizer_mode; + pic_param->pic_quantizer_fields.bits.half_qp = v->halfpq; + pic_param->pic_quantizer_fields.bits.pic_quantizer_scale = v->pq; + pic_param->pic_quantizer_fields.bits.pic_quantizer_type = v->pquantizer; + pic_param->pic_quantizer_fields.bits.dq_frame = v->dquantfrm; + pic_param->pic_quantizer_fields.bits.dq_profile = v->dqprofile; + pic_param->pic_quantizer_fields.bits.dq_sb_edge = v->dqprofile == DQPROFILE_SINGLE_EDGE ? v->dqsbedge : 0; + pic_param->pic_quantizer_fields.bits.dq_db_edge = v->dqprofile == DQPROFILE_DOUBLE_EDGES ? v->dqsbedge : 0; + pic_param->pic_quantizer_fields.bits.dq_binary_level = v->dqbilevel; + pic_param->pic_quantizer_fields.bits.alt_pic_quantizer = v->altpq; + pic_param->transform_fields.value = 0; /* reset all bits */ + pic_param->transform_fields.bits.variable_sized_transform_flag = v->vstransform; + pic_param->transform_fields.bits.mb_level_transform_type_flag = v->ttmbf; + pic_param->transform_fields.bits.frame_level_transform_type = vc1_get_TTFRM(v); + pic_param->transform_fields.bits.transform_ac_codingset_idx1 = v->c_ac_table_index; + pic_param->transform_fields.bits.transform_ac_codingset_idx2 = v->y_ac_table_index; + pic_param->transform_fields.bits.intra_transform_dc_table = v->s.dc_table_index; + + switch (s->pict_type) { + case AV_PICTURE_TYPE_B: + pic_param->backward_reference_picture = ff_vaapi_get_surface_id(&s->next_picture); + // fall-through + case AV_PICTURE_TYPE_P: + pic_param->forward_reference_picture = ff_vaapi_get_surface_id(&s->last_picture); + break; + } + + if (pic_param->bitplane_present.value) { + uint8_t *bitplane; + const uint8_t *ff_bp[3]; + int x, y, n; + + switch (s->pict_type) { + case AV_PICTURE_TYPE_P: + ff_bp[0] = pic_param->bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL; + ff_bp[1] = pic_param->bitplane_present.flags.bp_skip_mb ? s->mbskip_table : NULL; + ff_bp[2] = pic_param->bitplane_present.flags.bp_mv_type_mb ? v->mv_type_mb_plane : NULL; + break; + case AV_PICTURE_TYPE_B: + if (!v->bi_type) { + ff_bp[0] = pic_param->bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL; + ff_bp[1] = pic_param->bitplane_present.flags.bp_skip_mb ? s->mbskip_table : NULL; + ff_bp[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */ + break; + } + /* fall-through (BI-type) */ + case AV_PICTURE_TYPE_I: + ff_bp[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */ + ff_bp[1] = pic_param->bitplane_present.flags.bp_ac_pred ? v->acpred_plane : NULL; + ff_bp[2] = pic_param->bitplane_present.flags.bp_overflags ? v->over_flags_plane : NULL; + break; + default: + ff_bp[0] = NULL; + ff_bp[1] = NULL; + ff_bp[2] = NULL; + break; + } + + bitplane = ff_vaapi_alloc_bitplane(vactx, (s->mb_width * s->mb_height + 1) / 2); + if (!bitplane) + return -1; + + n = 0; + for (y = 0; y < s->mb_height; y++) + for (x = 0; x < s->mb_width; x++, n++) + vc1_pack_bitplanes(bitplane, n, ff_bp, x, y, s->mb_stride); + if (n & 1) /* move last nibble to the high order */ + bitplane[n/2] <<= 4; + } + return 0; +} + +static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) +{ + VC1Context * const v = avctx->priv_data; + MpegEncContext * const s = &v->s; + VASliceParameterBufferVC1 *slice_param; + + av_dlog(avctx, "vaapi_vc1_decode_slice(): buffer %p, size %d\n", buffer, size); + + /* Current bit buffer is beyond any marker for VC-1, so skip it */ + if (avctx->codec_id == AV_CODEC_ID_VC1 && IS_MARKER(AV_RB32(buffer))) { + buffer += 4; + size -= 4; + } + + /* Fill in VASliceParameterBufferVC1 */ + slice_param = (VASliceParameterBufferVC1 *)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size); + if (!slice_param) + return -1; + slice_param->macroblock_offset = get_bits_count(&s->gb); + slice_param->slice_vertical_position = s->mb_y; + return 0; +} + +#if CONFIG_WMV3_VAAPI_HWACCEL +AVHWAccel ff_wmv3_vaapi_hwaccel = { + .name = "wmv3_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .start_frame = vaapi_vc1_start_frame, + .end_frame = ff_vaapi_mpeg_end_frame, + .decode_slice = vaapi_vc1_decode_slice, +}; +#endif + +AVHWAccel ff_vc1_vaapi_hwaccel = { + .name = "vc1_vaapi", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_VAAPI_VLD, + .start_frame = vaapi_vc1_start_frame, + .end_frame = ff_vaapi_mpeg_end_frame, + .decode_slice = vaapi_vc1_decode_slice, +}; diff --git a/ffmpeg/libavcodec/vb.c b/ffmpeg/libavcodec/vb.c new file mode 100644 index 0000000..29cd104 --- /dev/null +++ b/ffmpeg/libavcodec/vb.c @@ -0,0 +1,277 @@ +/* + * Beam Software VB decoder + * Copyright (c) 2007 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * VB Video decoder + */ + +#include +#include + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +enum VBFlags { + VB_HAS_GMC = 0x01, + VB_HAS_AUDIO = 0x04, + VB_HAS_VIDEO = 0x08, + VB_HAS_PALETTE = 0x10, + VB_HAS_LENGTH = 0x20 +}; + +typedef struct VBDecContext { + AVCodecContext *avctx; + + uint8_t *frame, *prev_frame; + uint32_t pal[AVPALETTE_COUNT]; + GetByteContext stream; +} VBDecContext; + +static const uint16_t vb_patterns[64] = { + 0x0660, 0xFF00, 0xCCCC, 0xF000, 0x8888, 0x000F, 0x1111, 0xFEC8, + 0x8CEF, 0x137F, 0xF731, 0xC800, 0x008C, 0x0013, 0x3100, 0xCC00, + 0x00CC, 0x0033, 0x3300, 0x0FF0, 0x6666, 0x00F0, 0x0F00, 0x2222, + 0x4444, 0xF600, 0x8CC8, 0x006F, 0x1331, 0x318C, 0xC813, 0x33CC, + 0x6600, 0x0CC0, 0x0066, 0x0330, 0xF900, 0xC88C, 0x009F, 0x3113, + 0x6000, 0x0880, 0x0006, 0x0110, 0xCC88, 0xFC00, 0x00CF, 0x88CC, + 0x003F, 0x1133, 0x3311, 0xF300, 0x6FF6, 0x0603, 0x08C6, 0x8C63, + 0xC631, 0x6310, 0xC060, 0x0136, 0x136C, 0x36C8, 0x6C80, 0x324C +}; + +static void vb_decode_palette(VBDecContext *c, int data_size) +{ + int start, size, i; + + start = bytestream2_get_byte(&c->stream); + size = (bytestream2_get_byte(&c->stream) - 1) & 0xFF; + if (start + size > 255) { + av_log(c->avctx, AV_LOG_ERROR, "Palette change runs beyond entry 256\n"); + return; + } + if (size*3+2 > data_size) { + av_log(c->avctx, AV_LOG_ERROR, "Palette data runs beyond chunk size\n"); + return; + } + for (i = start; i <= start + size; i++) + c->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&c->stream); +} + +static inline int check_pixel(uint8_t *buf, uint8_t *start, uint8_t *end) +{ + return buf >= start && buf < end; +} + +static inline int check_line(uint8_t *buf, uint8_t *start, uint8_t *end) +{ + return buf >= start && (buf + 4) <= end; +} + +static int vb_decode_framedata(VBDecContext *c, int offset) +{ + GetByteContext g; + uint8_t *prev, *cur; + int blk, blocks, t, blk2; + int blocktypes = 0; + int x, y, a, b; + int pattype, pattern; + const int width = c->avctx->width; + uint8_t *pstart = c->prev_frame; + uint8_t *pend = c->prev_frame + width*c->avctx->height; + + g = c->stream; + + prev = c->prev_frame + offset; + cur = c->frame; + + blocks = (c->avctx->width >> 2) * (c->avctx->height >> 2); + blk2 = 0; + for (blk = 0; blk < blocks; blk++) { + if (!(blk & 3)) { + blocktypes = bytestream2_get_byte(&g); + } + switch (blocktypes & 0xC0) { + case 0x00: //skip + for (y = 0; y < 4; y++) + if (check_line(prev + y*width, pstart, pend)) + memcpy(cur + y*width, prev + y*width, 4); + else + memset(cur + y*width, 0, 4); + break; + case 0x40: + t = bytestream2_get_byte(&g); + if (!t) { //raw block + if (bytestream2_get_bytes_left(&g) < 16) { + av_log(c->avctx, AV_LOG_ERROR, "Insufficient data\n"); + return AVERROR_INVALIDDATA; + } + for (y = 0; y < 4; y++) + bytestream2_get_buffer(&g, cur + y * width, 4); + } else { // motion compensation + x = ((t & 0xF)^8) - 8; + y = ((t >> 4) ^8) - 8; + t = x + y*width; + for (y = 0; y < 4; y++) + if (check_line(prev + t + y*width, pstart, pend)) + memcpy(cur + y*width, prev + t + y*width, 4); + else + memset(cur + y*width, 0, 4); + } + break; + case 0x80: // fill + t = bytestream2_get_byte(&g); + for (y = 0; y < 4; y++) + memset(cur + y*width, t, 4); + break; + case 0xC0: // pattern fill + t = bytestream2_get_byte(&g); + pattype = t >> 6; + pattern = vb_patterns[t & 0x3F]; + switch (pattype) { + case 0: + a = bytestream2_get_byte(&g); + b = bytestream2_get_byte(&g); + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++, pattern >>= 1) + cur[x + y*width] = (pattern & 1) ? b : a; + break; + case 1: + pattern = ~pattern; + case 2: + a = bytestream2_get_byte(&g); + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++, pattern >>= 1) + if (pattern & 1 && check_pixel(prev + x + y*width, pstart, pend)) + cur[x + y*width] = prev[x + y*width]; + else + cur[x + y*width] = a; + break; + case 3: + av_log(c->avctx, AV_LOG_ERROR, "Invalid opcode seen @%d\n", blk); + return AVERROR_INVALIDDATA; + } + break; + } + blocktypes <<= 2; + cur += 4; + prev += 4; + blk2++; + if (blk2 == (width >> 2)) { + blk2 = 0; + cur += width * 3; + prev += width * 3; + } + } + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + VBDecContext * const c = avctx->priv_data; + AVFrame *frame = data; + uint8_t *outptr, *srcptr; + int i, j, ret; + int flags; + uint32_t size; + int offset = 0; + + bytestream2_init(&c->stream, avpkt->data, avpkt->size); + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + flags = bytestream2_get_le16(&c->stream); + + if (flags & VB_HAS_GMC) { + i = (int16_t)bytestream2_get_le16(&c->stream); + j = (int16_t)bytestream2_get_le16(&c->stream); + offset = i + j * avctx->width; + } + if (flags & VB_HAS_VIDEO) { + size = bytestream2_get_le32(&c->stream); + if(size > bytestream2_get_bytes_left(&c->stream)+4 || size<4){ + av_log(avctx, AV_LOG_ERROR, "Frame size invalid\n"); + return -1; + } + vb_decode_framedata(c, offset); + bytestream2_skip(&c->stream, size - 4); + } + if (flags & VB_HAS_PALETTE) { + size = bytestream2_get_le32(&c->stream); + vb_decode_palette(c, size); + } + + memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); + frame->palette_has_changed = flags & VB_HAS_PALETTE; + + outptr = frame->data[0]; + srcptr = c->frame; + + for (i = 0; i < avctx->height; i++) { + memcpy(outptr, srcptr, avctx->width); + srcptr += avctx->width; + outptr += frame->linesize[0]; + } + + FFSWAP(uint8_t*, c->frame, c->prev_frame); + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return avpkt->size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + VBDecContext * const c = avctx->priv_data; + + c->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + c->frame = av_mallocz(avctx->width * avctx->height); + c->prev_frame = av_mallocz(avctx->width * avctx->height); + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + VBDecContext *c = avctx->priv_data; + + av_freep(&c->frame); + av_freep(&c->prev_frame); + + return 0; +} + +AVCodec ff_vb_decoder = { + .name = "vb", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VB, + .priv_data_size = sizeof(VBDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), + .capabilities = CODEC_CAP_DR1, +}; diff --git a/ffmpeg/libavcodec/vble.c b/ffmpeg/libavcodec/vble.c new file mode 100644 index 0000000..cbb2ffc --- /dev/null +++ b/ffmpeg/libavcodec/vble.c @@ -0,0 +1,213 @@ +/* + * VBLE Decoder + * Copyright (c) 2011 Derek Buitenhuis + * + * 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 + */ + +/** + * @file + * VBLE Decoder + */ + +#define BITSTREAM_READER_LE + +#include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" + +typedef struct { + AVCodecContext *avctx; + DSPContext dsp; + + int size; + uint8_t *val; ///< This array first holds the lengths of vlc symbols and then their value. +} VBLEContext; + +static int vble_unpack(VBLEContext *ctx, GetBitContext *gb) +{ + int i; + int allbits = 0; + static const uint8_t LUT[256] = { + 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, + }; + + /* Read all the lengths in first */ + for (i = 0; i < ctx->size; i++) { + /* At most we need to read 9 bits total to get indices up to 8 */ + int val = show_bits(gb, 8); + + // read reverse unary + if (val) { + val = LUT[val]; + skip_bits(gb, val + 1); + ctx->val[i] = val; + } else { + skip_bits(gb, 8); + if (!get_bits1(gb)) + return -1; + ctx->val[i] = 8; + } + allbits += ctx->val[i]; + } + + /* Check we have enough bits left */ + if (get_bits_left(gb) < allbits) + return -1; + return 0; +} + +static void vble_restore_plane(VBLEContext *ctx, AVFrame *pic, + GetBitContext *gb, int plane, + int offset, int width, int height) +{ + uint8_t *dst = pic->data[plane]; + uint8_t *val = ctx->val + offset; + int stride = pic->linesize[plane]; + int i, j, left, left_top; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + /* get_bits can't take a length of 0 */ + if (val[j]) { + int v = (1 << val[j]) + get_bits(gb, val[j]) - 1; + val[j] = (v >> 1) ^ -(v & 1); + } + } + if (i) { + left = 0; + left_top = dst[-stride]; + ctx->dsp.add_hfyu_median_prediction(dst, dst-stride, val, width, &left, &left_top); + } else { + dst[0] = val[0]; + for (j = 1; j < width; j++) + dst[j] = val[j] + dst[j - 1]; + } + dst += stride; + val += width; + } +} + +static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + VBLEContext *ctx = avctx->priv_data; + AVFrame *pic = data; + GetBitContext gb; + const uint8_t *src = avpkt->data; + int version; + int offset = 0; + int width_uv = avctx->width / 2, height_uv = avctx->height / 2; + int ret; + + if (avpkt->size < 4 || avpkt->size - 4 > INT_MAX/8) { + av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n"); + return AVERROR_INVALIDDATA; + } + + /* Allocate buffer */ + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + /* Set flags */ + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + /* Version should always be 1 */ + version = AV_RL32(src); + + if (version != 1) + av_log(avctx, AV_LOG_WARNING, "Unsupported VBLE Version: %d\n", version); + + init_get_bits(&gb, src + 4, (avpkt->size - 4) * 8); + + /* Unpack */ + if (vble_unpack(ctx, &gb) < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid Code\n"); + return AVERROR_INVALIDDATA; + } + + /* Restore planes. Should be almost identical to Huffyuv's. */ + vble_restore_plane(ctx, pic, &gb, 0, offset, avctx->width, avctx->height); + + /* Chroma */ + if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) { + offset += avctx->width * avctx->height; + vble_restore_plane(ctx, pic, &gb, 1, offset, width_uv, height_uv); + + offset += width_uv * height_uv; + vble_restore_plane(ctx, pic, &gb, 2, offset, width_uv, height_uv); + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int vble_decode_close(AVCodecContext *avctx) +{ + VBLEContext *ctx = avctx->priv_data; + av_freep(&ctx->val); + + return 0; +} + +static av_cold int vble_decode_init(AVCodecContext *avctx) +{ + VBLEContext *ctx = avctx->priv_data; + + /* Stash for later use */ + ctx->avctx = avctx; + ff_dsputil_init(&ctx->dsp, avctx); + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->bits_per_raw_sample = 8; + + ctx->size = avpicture_get_size(avctx->pix_fmt, + avctx->width, avctx->height); + + ctx->val = av_malloc(ctx->size * sizeof(*ctx->val)); + + if (!ctx->val) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate values buffer.\n"); + vble_decode_close(avctx); + return AVERROR(ENOMEM); + } + + return 0; +} + +AVCodec ff_vble_decoder = { + .name = "vble", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VBLE, + .priv_data_size = sizeof(VBLEContext), + .init = vble_decode_init, + .close = vble_decode_close, + .decode = vble_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("VBLE Lossless Codec"), +}; diff --git a/ffmpeg/libavcodec/vc1.c b/ffmpeg/libavcodec/vc1.c new file mode 100644 index 0000000..0b69711 --- /dev/null +++ b/ffmpeg/libavcodec/vc1.c @@ -0,0 +1,1666 @@ +/* + * VC-1 and WMV3 decoder common code + * Copyright (c) 2011 Mashiat Sarker Shakkhar + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, 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 + */ + +/** + * @file + * VC-1 and WMV3 decoder common code + * + */ + +#include "internal.h" +#include "avcodec.h" +#include "mpegvideo.h" +#include "vc1.h" +#include "vc1data.h" +#include "msmpeg4data.h" +#include "unary.h" +#include "simple_idct.h" + +#undef NDEBUG +#include + +/***********************************************************************/ +/** + * @name VC-1 Bitplane decoding + * @see 8.7, p56 + * @{ + */ + +/** + * Imode types + * @{ + */ +enum Imode { + IMODE_RAW, + IMODE_NORM2, + IMODE_DIFF2, + IMODE_NORM6, + IMODE_DIFF6, + IMODE_ROWSKIP, + IMODE_COLSKIP +}; +/** @} */ //imode defines + +/** Decode rows by checking if they are skipped + * @param plane Buffer to store decoded bits + * @param[in] width Width of this buffer + * @param[in] height Height of this buffer + * @param[in] stride of this buffer + */ +static void decode_rowskip(uint8_t* plane, int width, int height, int stride, + GetBitContext *gb) +{ + int x, y; + + for (y = 0; y < height; y++) { + if (!get_bits1(gb)) //rowskip + memset(plane, 0, width); + else + for (x = 0; x < width; x++) + plane[x] = get_bits1(gb); + plane += stride; + } +} + +/** Decode columns by checking if they are skipped + * @param plane Buffer to store decoded bits + * @param[in] width Width of this buffer + * @param[in] height Height of this buffer + * @param[in] stride of this buffer + * @todo FIXME: Optimize + */ +static void decode_colskip(uint8_t* plane, int width, int height, int stride, + GetBitContext *gb) +{ + int x, y; + + for (x = 0; x < width; x++) { + if (!get_bits1(gb)) //colskip + for (y = 0; y < height; y++) + plane[y*stride] = 0; + else + for (y = 0; y < height; y++) + plane[y*stride] = get_bits1(gb); + plane ++; + } +} + +/** Decode a bitplane's bits + * @param data bitplane where to store the decode bits + * @param[out] raw_flag pointer to the flag indicating that this bitplane is not coded explicitly + * @param v VC-1 context for bit reading and logging + * @return Status + * @todo FIXME: Optimize + */ +static int bitplane_decoding(uint8_t* data, int *raw_flag, VC1Context *v) +{ + GetBitContext *gb = &v->s.gb; + + int imode, x, y, code, offset; + uint8_t invert, *planep = data; + int width, height, stride; + + width = v->s.mb_width; + height = v->s.mb_height >> v->field_mode; + stride = v->s.mb_stride; + invert = get_bits1(gb); + imode = get_vlc2(gb, ff_vc1_imode_vlc.table, VC1_IMODE_VLC_BITS, 1); + + *raw_flag = 0; + switch (imode) { + case IMODE_RAW: + //Data is actually read in the MB layer (same for all tests == "raw") + *raw_flag = 1; //invert ignored + return invert; + case IMODE_DIFF2: + case IMODE_NORM2: + if ((height * width) & 1) { + *planep++ = get_bits1(gb); + offset = 1; + } + else + offset = 0; + // decode bitplane as one long line + for (y = offset; y < height * width; y += 2) { + code = get_vlc2(gb, ff_vc1_norm2_vlc.table, VC1_NORM2_VLC_BITS, 1); + *planep++ = code & 1; + offset++; + if (offset == width) { + offset = 0; + planep += stride - width; + } + *planep++ = code >> 1; + offset++; + if (offset == width) { + offset = 0; + planep += stride - width; + } + } + break; + case IMODE_DIFF6: + case IMODE_NORM6: + if (!(height % 3) && (width % 3)) { // use 2x3 decoding + for (y = 0; y < height; y += 3) { + for (x = width & 1; x < width; x += 2) { + code = get_vlc2(gb, ff_vc1_norm6_vlc.table, VC1_NORM6_VLC_BITS, 2); + if (code < 0) { + av_log(v->s.avctx, AV_LOG_DEBUG, "invalid NORM-6 VLC\n"); + return -1; + } + planep[x + 0] = (code >> 0) & 1; + planep[x + 1] = (code >> 1) & 1; + planep[x + 0 + stride] = (code >> 2) & 1; + planep[x + 1 + stride] = (code >> 3) & 1; + planep[x + 0 + stride * 2] = (code >> 4) & 1; + planep[x + 1 + stride * 2] = (code >> 5) & 1; + } + planep += stride * 3; + } + if (width & 1) + decode_colskip(data, 1, height, stride, &v->s.gb); + } else { // 3x2 + planep += (height & 1) * stride; + for (y = height & 1; y < height; y += 2) { + for (x = width % 3; x < width; x += 3) { + code = get_vlc2(gb, ff_vc1_norm6_vlc.table, VC1_NORM6_VLC_BITS, 2); + if (code < 0) { + av_log(v->s.avctx, AV_LOG_DEBUG, "invalid NORM-6 VLC\n"); + return -1; + } + planep[x + 0] = (code >> 0) & 1; + planep[x + 1] = (code >> 1) & 1; + planep[x + 2] = (code >> 2) & 1; + planep[x + 0 + stride] = (code >> 3) & 1; + planep[x + 1 + stride] = (code >> 4) & 1; + planep[x + 2 + stride] = (code >> 5) & 1; + } + planep += stride * 2; + } + x = width % 3; + if (x) + decode_colskip(data, x, height, stride, &v->s.gb); + if (height & 1) + decode_rowskip(data + x, width - x, 1, stride, &v->s.gb); + } + break; + case IMODE_ROWSKIP: + decode_rowskip(data, width, height, stride, &v->s.gb); + break; + case IMODE_COLSKIP: + decode_colskip(data, width, height, stride, &v->s.gb); + break; + default: + break; + } + + /* Applying diff operator */ + if (imode == IMODE_DIFF2 || imode == IMODE_DIFF6) { + planep = data; + planep[0] ^= invert; + for (x = 1; x < width; x++) + planep[x] ^= planep[x-1]; + for (y = 1; y < height; y++) { + planep += stride; + planep[0] ^= planep[-stride]; + for (x = 1; x < width; x++) { + if (planep[x-1] != planep[x-stride]) planep[x] ^= invert; + else planep[x] ^= planep[x-1]; + } + } + } else if (invert) { + planep = data; + for (x = 0; x < stride * height; x++) + planep[x] = !planep[x]; //FIXME stride + } + return (imode << 1) + invert; +} + +/** @} */ //Bitplane group + +/***********************************************************************/ +/** VOP Dquant decoding + * @param v VC-1 Context + */ +static int vop_dquant_decoding(VC1Context *v) +{ + GetBitContext *gb = &v->s.gb; + int pqdiff; + + //variable size + if (v->dquant == 2) { + pqdiff = get_bits(gb, 3); + if (pqdiff == 7) + v->altpq = get_bits(gb, 5); + else + v->altpq = v->pq + pqdiff + 1; + } else { + v->dquantfrm = get_bits1(gb); + if (v->dquantfrm) { + v->dqprofile = get_bits(gb, 2); + switch (v->dqprofile) { + case DQPROFILE_SINGLE_EDGE: + case DQPROFILE_DOUBLE_EDGES: + v->dqsbedge = get_bits(gb, 2); + break; + case DQPROFILE_ALL_MBS: + v->dqbilevel = get_bits1(gb); + if (!v->dqbilevel) + v->halfpq = 0; + default: + break; //Forbidden ? + } + if (v->dqbilevel || v->dqprofile != DQPROFILE_ALL_MBS) { + pqdiff = get_bits(gb, 3); + if (pqdiff == 7) + v->altpq = get_bits(gb, 5); + else + v->altpq = v->pq + pqdiff + 1; + } + } + } + return 0; +} + +static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb); + +/** + * Decode Simple/Main Profiles sequence header + * @see Figure 7-8, p16-17 + * @param avctx Codec context + * @param gb GetBit context initialized from Codec context extra_data + * @return Status + */ +int ff_vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitContext *gb) +{ + av_log(avctx, AV_LOG_DEBUG, "Header: %0X\n", show_bits_long(gb, 32)); + v->profile = get_bits(gb, 2); + if (v->profile == PROFILE_COMPLEX) { + av_log(avctx, AV_LOG_WARNING, "WMV3 Complex Profile is not fully supported\n"); + } + + if (v->profile == PROFILE_ADVANCED) { + v->zz_8x4 = ff_vc1_adv_progressive_8x4_zz; + v->zz_4x8 = ff_vc1_adv_progressive_4x8_zz; + return decode_sequence_header_adv(v, gb); + } else { + v->zz_8x4 = ff_wmv2_scantableA; + v->zz_4x8 = ff_wmv2_scantableB; + v->res_y411 = get_bits1(gb); + v->res_sprite = get_bits1(gb); + if (v->res_y411) { + av_log(avctx, AV_LOG_ERROR, + "Old interlaced mode is not supported\n"); + return -1; + } + } + + // (fps-2)/4 (->30) + v->frmrtq_postproc = get_bits(gb, 3); //common + // (bitrate-32kbps)/64kbps + v->bitrtq_postproc = get_bits(gb, 5); //common + v->s.loop_filter = get_bits1(gb); //common + if (v->s.loop_filter == 1 && v->profile == PROFILE_SIMPLE) { + av_log(avctx, AV_LOG_ERROR, + "LOOPFILTER shall not be enabled in Simple Profile\n"); + } + if (v->s.avctx->skip_loop_filter >= AVDISCARD_ALL) + v->s.loop_filter = 0; + + v->res_x8 = get_bits1(gb); //reserved + v->multires = get_bits1(gb); + v->res_fasttx = get_bits1(gb); + if (!v->res_fasttx) { + v->vc1dsp.vc1_inv_trans_8x8 = ff_simple_idct_8; + v->vc1dsp.vc1_inv_trans_8x4 = ff_simple_idct84_add; + v->vc1dsp.vc1_inv_trans_4x8 = ff_simple_idct48_add; + v->vc1dsp.vc1_inv_trans_4x4 = ff_simple_idct44_add; + v->vc1dsp.vc1_inv_trans_8x8_dc = ff_simple_idct_add_8; + v->vc1dsp.vc1_inv_trans_8x4_dc = ff_simple_idct84_add; + v->vc1dsp.vc1_inv_trans_4x8_dc = ff_simple_idct48_add; + v->vc1dsp.vc1_inv_trans_4x4_dc = ff_simple_idct44_add; + } + + v->fastuvmc = get_bits1(gb); //common + if (!v->profile && !v->fastuvmc) { + av_log(avctx, AV_LOG_ERROR, + "FASTUVMC unavailable in Simple Profile\n"); + return -1; + } + v->extended_mv = get_bits1(gb); //common + if (!v->profile && v->extended_mv) + { + av_log(avctx, AV_LOG_ERROR, + "Extended MVs unavailable in Simple Profile\n"); + return -1; + } + v->dquant = get_bits(gb, 2); //common + v->vstransform = get_bits1(gb); //common + + v->res_transtab = get_bits1(gb); + if (v->res_transtab) + { + av_log(avctx, AV_LOG_ERROR, + "1 for reserved RES_TRANSTAB is forbidden\n"); + return -1; + } + + v->overlap = get_bits1(gb); //common + + v->s.resync_marker = get_bits1(gb); + v->rangered = get_bits1(gb); + if (v->rangered && v->profile == PROFILE_SIMPLE) { + av_log(avctx, AV_LOG_INFO, + "RANGERED should be set to 0 in Simple Profile\n"); + } + + v->s.max_b_frames = avctx->max_b_frames = get_bits(gb, 3); //common + v->quantizer_mode = get_bits(gb, 2); //common + + v->finterpflag = get_bits1(gb); //common + + if (v->res_sprite) { + int w = get_bits(gb, 11); + int h = get_bits(gb, 11); + avcodec_set_dimensions(v->s.avctx, w, h); + skip_bits(gb, 5); //frame rate + v->res_x8 = get_bits1(gb); + if (get_bits1(gb)) { // something to do with DC VLC selection + av_log(avctx, AV_LOG_ERROR, "Unsupported sprite feature\n"); + return -1; + } + skip_bits(gb, 3); //slice code + v->res_rtm_flag = 0; + } else { + v->res_rtm_flag = get_bits1(gb); //reserved + } + if (!v->res_rtm_flag) { + av_log(avctx, AV_LOG_ERROR, + "Old WMV3 version detected, some frames may be decoded incorrectly\n"); + //return -1; + } + //TODO: figure out what they mean (always 0x402F) + if (!v->res_fasttx) + skip_bits(gb, 16); + av_log(avctx, AV_LOG_DEBUG, + "Profile %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n" + "LoopFilter=%i, MultiRes=%i, FastUVMC=%i, Extended MV=%i\n" + "Rangered=%i, VSTransform=%i, Overlap=%i, SyncMarker=%i\n" + "DQuant=%i, Quantizer mode=%i, Max B frames=%i\n", + v->profile, v->frmrtq_postproc, v->bitrtq_postproc, + v->s.loop_filter, v->multires, v->fastuvmc, v->extended_mv, + v->rangered, v->vstransform, v->overlap, v->s.resync_marker, + v->dquant, v->quantizer_mode, avctx->max_b_frames); + return 0; +} + +static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) +{ + v->res_rtm_flag = 1; + v->level = get_bits(gb, 3); + if (v->level >= 5) { + av_log(v->s.avctx, AV_LOG_ERROR, "Reserved LEVEL %i\n",v->level); + } + v->chromaformat = get_bits(gb, 2); + if (v->chromaformat != 1) { + av_log(v->s.avctx, AV_LOG_ERROR, + "Only 4:2:0 chroma format supported\n"); + return -1; + } + + // (fps-2)/4 (->30) + v->frmrtq_postproc = get_bits(gb, 3); //common + // (bitrate-32kbps)/64kbps + v->bitrtq_postproc = get_bits(gb, 5); //common + v->postprocflag = get_bits1(gb); //common + + v->max_coded_width = (get_bits(gb, 12) + 1) << 1; + v->max_coded_height = (get_bits(gb, 12) + 1) << 1; + v->broadcast = get_bits1(gb); + v->interlace = get_bits1(gb); + v->tfcntrflag = get_bits1(gb); + v->finterpflag = get_bits1(gb); + skip_bits1(gb); // reserved + + av_log(v->s.avctx, AV_LOG_DEBUG, + "Advanced Profile level %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n" + "LoopFilter=%i, ChromaFormat=%i, Pulldown=%i, Interlace: %i\n" + "TFCTRflag=%i, FINTERPflag=%i\n", + v->level, v->frmrtq_postproc, v->bitrtq_postproc, + v->s.loop_filter, v->chromaformat, v->broadcast, v->interlace, + v->tfcntrflag, v->finterpflag); + + v->psf = get_bits1(gb); + if (v->psf) { //PsF, 6.1.13 + av_log(v->s.avctx, AV_LOG_ERROR, "Progressive Segmented Frame mode: not supported (yet)\n"); + return -1; + } + v->s.max_b_frames = v->s.avctx->max_b_frames = 7; + if (get_bits1(gb)) { //Display Info - decoding is not affected by it + int w, h, ar = 0; + av_log(v->s.avctx, AV_LOG_DEBUG, "Display extended info:\n"); + w = get_bits(gb, 14) + 1; + h = get_bits(gb, 14) + 1; + av_log(v->s.avctx, AV_LOG_DEBUG, "Display dimensions: %ix%i\n", w, h); + if (get_bits1(gb)) + ar = get_bits(gb, 4); + if (ar && ar < 14) { + v->s.avctx->sample_aspect_ratio = ff_vc1_pixel_aspect[ar]; + } else if (ar == 15) { + w = get_bits(gb, 8) + 1; + h = get_bits(gb, 8) + 1; + v->s.avctx->sample_aspect_ratio = (AVRational){w, h}; + } else { + av_reduce(&v->s.avctx->sample_aspect_ratio.num, + &v->s.avctx->sample_aspect_ratio.den, + v->s.avctx->height * w, + v->s.avctx->width * h, + 1 << 30); + } + av_log(v->s.avctx, AV_LOG_DEBUG, "Aspect: %i:%i\n", + v->s.avctx->sample_aspect_ratio.num, + v->s.avctx->sample_aspect_ratio.den); + + if (get_bits1(gb)) { //framerate stuff + if (get_bits1(gb)) { + v->s.avctx->time_base.num = 32; + v->s.avctx->time_base.den = get_bits(gb, 16) + 1; + } else { + int nr, dr; + nr = get_bits(gb, 8); + dr = get_bits(gb, 4); + if (nr > 0 && nr < 8 && dr > 0 && dr < 3) { + v->s.avctx->time_base.num = ff_vc1_fps_dr[dr - 1]; + v->s.avctx->time_base.den = ff_vc1_fps_nr[nr - 1] * 1000; + } + } + if (v->broadcast) { // Pulldown may be present + v->s.avctx->time_base.den *= 2; + v->s.avctx->ticks_per_frame = 2; + } + } + + if (get_bits1(gb)) { + v->s.avctx->color_primaries = get_bits(gb, 8); + v->s.avctx->color_trc = get_bits(gb, 8); + v->s.avctx->colorspace = get_bits(gb, 8); + v->s.avctx->color_range = AVCOL_RANGE_MPEG; + } + } + + v->hrd_param_flag = get_bits1(gb); + if (v->hrd_param_flag) { + int i; + v->hrd_num_leaky_buckets = get_bits(gb, 5); + skip_bits(gb, 4); //bitrate exponent + skip_bits(gb, 4); //buffer size exponent + for (i = 0; i < v->hrd_num_leaky_buckets; i++) { + skip_bits(gb, 16); //hrd_rate[n] + skip_bits(gb, 16); //hrd_buffer[n] + } + } + return 0; +} + +int ff_vc1_decode_entry_point(AVCodecContext *avctx, VC1Context *v, GetBitContext *gb) +{ + int i; + int w,h; + + av_log(avctx, AV_LOG_DEBUG, "Entry point: %08X\n", show_bits_long(gb, 32)); + v->broken_link = get_bits1(gb); + v->closed_entry = get_bits1(gb); + v->panscanflag = get_bits1(gb); + v->refdist_flag = get_bits1(gb); + v->s.loop_filter = get_bits1(gb); + if (v->s.avctx->skip_loop_filter >= AVDISCARD_ALL) + v->s.loop_filter = 0; + v->fastuvmc = get_bits1(gb); + v->extended_mv = get_bits1(gb); + v->dquant = get_bits(gb, 2); + v->vstransform = get_bits1(gb); + v->overlap = get_bits1(gb); + v->quantizer_mode = get_bits(gb, 2); + + if (v->hrd_param_flag) { + for (i = 0; i < v->hrd_num_leaky_buckets; i++) { + skip_bits(gb, 8); //hrd_full[n] + } + } + + if(get_bits1(gb)){ + w = (get_bits(gb, 12)+1)<<1; + h = (get_bits(gb, 12)+1)<<1; + } else { + w = v->max_coded_width; + h = v->max_coded_height; + } + avcodec_set_dimensions(avctx, w, h); + if (v->extended_mv) + v->extended_dmv = get_bits1(gb); + if ((v->range_mapy_flag = get_bits1(gb))) { + av_log(avctx, AV_LOG_ERROR, "Luma scaling is not supported, expect wrong picture\n"); + v->range_mapy = get_bits(gb, 3); + } + if ((v->range_mapuv_flag = get_bits1(gb))) { + av_log(avctx, AV_LOG_ERROR, "Chroma scaling is not supported, expect wrong picture\n"); + v->range_mapuv = get_bits(gb, 3); + } + + av_log(avctx, AV_LOG_DEBUG, "Entry point info:\n" + "BrokenLink=%i, ClosedEntry=%i, PanscanFlag=%i\n" + "RefDist=%i, Postproc=%i, FastUVMC=%i, ExtMV=%i\n" + "DQuant=%i, VSTransform=%i, Overlap=%i, Qmode=%i\n", + v->broken_link, v->closed_entry, v->panscanflag, v->refdist_flag, v->s.loop_filter, + v->fastuvmc, v->extended_mv, v->dquant, v->vstransform, v->overlap, v->quantizer_mode); + + return 0; +} + +int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) +{ + int pqindex, lowquant, status; + + if (v->finterpflag) + v->interpfrm = get_bits1(gb); + if (!v->s.avctx->codec) + return -1; + if (v->s.avctx->codec_id == AV_CODEC_ID_MSS2) + v->respic = + v->rangered = + v->multires = get_bits(gb, 2) == 1; + else + skip_bits(gb, 2); //framecnt unused + v->rangeredfrm = 0; + if (v->rangered) + v->rangeredfrm = get_bits1(gb); + v->s.pict_type = get_bits1(gb); + if (v->s.avctx->max_b_frames) { + if (!v->s.pict_type) { + if (get_bits1(gb)) + v->s.pict_type = AV_PICTURE_TYPE_I; + else + v->s.pict_type = AV_PICTURE_TYPE_B; + } else + v->s.pict_type = AV_PICTURE_TYPE_P; + } else + v->s.pict_type = v->s.pict_type ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + + v->bi_type = 0; + if (v->s.pict_type == AV_PICTURE_TYPE_B) { + v->bfraction_lut_index = get_vlc2(gb, ff_vc1_bfraction_vlc.table, VC1_BFRACTION_VLC_BITS, 1); + v->bfraction = ff_vc1_bfraction_lut[v->bfraction_lut_index]; + if (v->bfraction == 0) { + v->s.pict_type = AV_PICTURE_TYPE_BI; + } + } + if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) + skip_bits(gb, 7); // skip buffer fullness + + if (v->parse_only) + return 0; + + /* calculate RND */ + if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) + v->rnd = 1; + if (v->s.pict_type == AV_PICTURE_TYPE_P) + v->rnd ^= 1; + + /* Quantizer stuff */ + pqindex = get_bits(gb, 5); + if (!pqindex) + return -1; + if (v->quantizer_mode == QUANT_FRAME_IMPLICIT) + v->pq = ff_vc1_pquant_table[0][pqindex]; + else + v->pq = ff_vc1_pquant_table[1][pqindex]; + + v->pquantizer = 1; + if (v->quantizer_mode == QUANT_FRAME_IMPLICIT) + v->pquantizer = pqindex < 9; + if (v->quantizer_mode == QUANT_NON_UNIFORM) + v->pquantizer = 0; + v->pqindex = pqindex; + if (pqindex < 9) + v->halfpq = get_bits1(gb); + else + v->halfpq = 0; + if (v->quantizer_mode == QUANT_FRAME_EXPLICIT) + v->pquantizer = get_bits1(gb); + v->dquantfrm = 0; + if (v->extended_mv == 1) + v->mvrange = get_unary(gb, 0, 3); + v->k_x = v->mvrange + 9 + (v->mvrange >> 1); //k_x can be 9 10 12 13 + v->k_y = v->mvrange + 8; //k_y can be 8 9 10 11 + v->range_x = 1 << (v->k_x - 1); + v->range_y = 1 << (v->k_y - 1); + if (v->multires && v->s.pict_type != AV_PICTURE_TYPE_B) + v->respic = get_bits(gb, 2); + + if (v->res_x8 && (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI)) { + v->x8_type = get_bits1(gb); + } else + v->x8_type = 0; + av_dlog(v->s.avctx, "%c Frame: QP=[%i]%i (+%i/2) %i\n", + (v->s.pict_type == AV_PICTURE_TYPE_P) ? 'P' : ((v->s.pict_type == AV_PICTURE_TYPE_I) ? 'I' : 'B'), + pqindex, v->pq, v->halfpq, v->rangeredfrm); + + if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_P) + v->use_ic = 0; + + switch (v->s.pict_type) { + case AV_PICTURE_TYPE_P: + if (v->pq < 5) v->tt_index = 0; + else if (v->pq < 13) v->tt_index = 1; + else v->tt_index = 2; + + lowquant = (v->pq > 12) ? 0 : 1; + v->mv_mode = ff_vc1_mv_pmode_table[lowquant][get_unary(gb, 1, 4)]; + if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + int scale, shift, i; + v->mv_mode2 = ff_vc1_mv_pmode_table2[lowquant][get_unary(gb, 1, 3)]; + v->lumscale = get_bits(gb, 6); + v->lumshift = get_bits(gb, 6); + v->use_ic = 1; + /* fill lookup tables for intensity compensation */ + if (!v->lumscale) { + scale = -64; + shift = (255 - v->lumshift * 2) << 6; + if (v->lumshift > 31) + shift += 128 << 6; + } else { + scale = v->lumscale + 32; + if (v->lumshift > 31) + shift = (v->lumshift - 64) << 6; + else + shift = v->lumshift << 6; + } + for (i = 0; i < 256; i++) { + v->luty[i] = av_clip_uint8((scale * i + shift + 32) >> 6); + v->lutuv[i] = av_clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6); + } + } + v->qs_last = v->s.quarter_sample; + if (v->mv_mode == MV_PMODE_1MV_HPEL || v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) + v->s.quarter_sample = 0; + else if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + if (v->mv_mode2 == MV_PMODE_1MV_HPEL || v->mv_mode2 == MV_PMODE_1MV_HPEL_BILIN) + v->s.quarter_sample = 0; + else + v->s.quarter_sample = 1; + } else + v->s.quarter_sample = 1; + v->s.mspel = !(v->mv_mode == MV_PMODE_1MV_HPEL_BILIN || (v->mv_mode == MV_PMODE_INTENSITY_COMP && v->mv_mode2 == MV_PMODE_1MV_HPEL_BILIN)); + + if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->mv_mode2 == MV_PMODE_MIXED_MV) || + v->mv_mode == MV_PMODE_MIXED_MV) { + status = bitplane_decoding(v->mv_type_mb_plane, &v->mv_type_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB MV Type plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + } else { + v->mv_type_is_raw = 0; + memset(v->mv_type_mb_plane, 0, v->s.mb_stride * v->s.mb_height); + } + status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + + /* Hopefully this is correct for P frames */ + v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + + if (v->dquant) { + av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); + vop_dquant_decoding(v); + } + + v->ttfrm = 0; //FIXME Is that so ? + if (v->vstransform) { + v->ttmbf = get_bits1(gb); + if (v->ttmbf) { + v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)]; + } + } else { + v->ttmbf = 1; + v->ttfrm = TT_8X8; + } + break; + case AV_PICTURE_TYPE_B: + if (v->pq < 5) v->tt_index = 0; + else if (v->pq < 13) v->tt_index = 1; + else v->tt_index = 2; + + v->mv_mode = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN; + v->qs_last = v->s.quarter_sample; + v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV); + v->s.mspel = v->s.quarter_sample; + + status = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Direct Type plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + + v->s.mv_table_index = get_bits(gb, 2); + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + + if (v->dquant) { + av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); + vop_dquant_decoding(v); + } + + v->ttfrm = 0; + if (v->vstransform) { + v->ttmbf = get_bits1(gb); + if (v->ttmbf) { + v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)]; + } + } else { + v->ttmbf = 1; + v->ttfrm = TT_8X8; + } + break; + } + + if (!v->x8_type) { + /* AC Syntax */ + v->c_ac_table_index = decode012(gb); + if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) { + v->y_ac_table_index = decode012(gb); + } + /* DC Syntax */ + v->s.dc_table_index = get_bits1(gb); + } + + if (v->s.pict_type == AV_PICTURE_TYPE_BI) { + v->s.pict_type = AV_PICTURE_TYPE_B; + v->bi_type = 1; + } + return 0; +} + +/* fill lookup tables for intensity compensation */ +#define INIT_LUT(lumscale, lumshift, luty, lutuv) \ + if (!lumscale) { \ + scale = -64; \ + shift = (255 - lumshift * 2) << 6; \ + if (lumshift > 31) \ + shift += 128 << 6; \ + } else { \ + scale = lumscale + 32; \ + if (lumshift > 31) \ + shift = (lumshift - 64) << 6; \ + else \ + shift = lumshift << 6; \ + } \ + for (i = 0; i < 256; i++) { \ + luty[i] = av_clip_uint8((scale * i + shift + 32) >> 6); \ + lutuv[i] = av_clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6); \ + } + +int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) +{ + int pqindex, lowquant; + int status; + int mbmodetab, imvtab, icbptab, twomvbptab, fourmvbptab; /* useful only for debugging */ + int scale, shift, i; /* for initializing LUT for intensity compensation */ + int field_mode, fcm; + + v->numref=0; + v->p_frame_skipped = 0; + if (v->second_field) { + if(v->fcm!=2 || v->field_mode!=1) + return -1; + v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + if (v->fptype & 4) + v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_BI : AV_PICTURE_TYPE_B; + v->s.current_picture_ptr->f.pict_type = v->s.pict_type; + if (!v->pic_header_flag) + goto parse_common_info; + } + + field_mode = 0; + if (v->interlace) { + fcm = decode012(gb); + if (fcm) { + if (fcm == ILACE_FIELD) + field_mode = 1; + if (!v->warn_interlaced++) + av_log(v->s.avctx, AV_LOG_ERROR, + "Interlaced frames/fields support is incomplete\n"); + } + } else { + fcm = PROGRESSIVE; + } + if (!v->first_pic_header_flag && v->field_mode != field_mode) + return -1; + v->field_mode = field_mode; + v->fcm = fcm; + + if (v->field_mode) { + v->fptype = get_bits(gb, 3); + v->s.pict_type = (v->fptype & 2) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + if (v->fptype & 4) // B-picture + v->s.pict_type = (v->fptype & 2) ? AV_PICTURE_TYPE_BI : AV_PICTURE_TYPE_B; + } else { + switch (get_unary(gb, 0, 4)) { + case 0: + v->s.pict_type = AV_PICTURE_TYPE_P; + break; + case 1: + v->s.pict_type = AV_PICTURE_TYPE_B; + break; + case 2: + v->s.pict_type = AV_PICTURE_TYPE_I; + break; + case 3: + v->s.pict_type = AV_PICTURE_TYPE_BI; + break; + case 4: + v->s.pict_type = AV_PICTURE_TYPE_P; // skipped pic + v->p_frame_skipped = 1; + break; + } + } + if (v->tfcntrflag) + skip_bits(gb, 8); + if (v->broadcast) { + if (!v->interlace || v->psf) { + v->rptfrm = get_bits(gb, 2); + } else { + v->tff = get_bits1(gb); + v->rff = get_bits1(gb); + } + } + if (v->panscanflag) { + avpriv_report_missing_feature(v->s.avctx, "Pan-scan"); + //... + } + if (v->p_frame_skipped) { + return 0; + } + v->rnd = get_bits1(gb); + if (v->interlace) + v->uvsamp = get_bits1(gb); + if(!ff_vc1_bfraction_vlc.table) + return 0; //parsing only, vlc tables havnt been allocated + if (v->field_mode) { + if (!v->refdist_flag) + v->refdist = 0; + else if ((v->s.pict_type != AV_PICTURE_TYPE_B) && (v->s.pict_type != AV_PICTURE_TYPE_BI)) { + v->refdist = get_bits(gb, 2); + if (v->refdist == 3) + v->refdist += get_unary(gb, 0, 16); + } + if ((v->s.pict_type == AV_PICTURE_TYPE_B) || (v->s.pict_type == AV_PICTURE_TYPE_BI)) { + v->bfraction_lut_index = get_vlc2(gb, ff_vc1_bfraction_vlc.table, VC1_BFRACTION_VLC_BITS, 1); + v->bfraction = ff_vc1_bfraction_lut[v->bfraction_lut_index]; + v->frfd = (v->bfraction * v->refdist) >> 8; + v->brfd = v->refdist - v->frfd - 1; + if (v->brfd < 0) + v->brfd = 0; + } + goto parse_common_info; + } + if (v->fcm == PROGRESSIVE) { + if (v->finterpflag) + v->interpfrm = get_bits1(gb); + if (v->s.pict_type == AV_PICTURE_TYPE_B) { + v->bfraction_lut_index = get_vlc2(gb, ff_vc1_bfraction_vlc.table, VC1_BFRACTION_VLC_BITS, 1); + v->bfraction = ff_vc1_bfraction_lut[v->bfraction_lut_index]; + if (v->bfraction == 0) { + v->s.pict_type = AV_PICTURE_TYPE_BI; /* XXX: should not happen here */ + } + } + } + + parse_common_info: + if (v->field_mode) + v->cur_field_type = !(v->tff ^ v->second_field); + pqindex = get_bits(gb, 5); + if (!pqindex) + return -1; + v->pqindex = pqindex; + if (v->quantizer_mode == QUANT_FRAME_IMPLICIT) + v->pq = ff_vc1_pquant_table[0][pqindex]; + else + v->pq = ff_vc1_pquant_table[1][pqindex]; + + v->pquantizer = 1; + if (v->quantizer_mode == QUANT_FRAME_IMPLICIT) + v->pquantizer = pqindex < 9; + if (v->quantizer_mode == QUANT_NON_UNIFORM) + v->pquantizer = 0; + v->pqindex = pqindex; + if (pqindex < 9) + v->halfpq = get_bits1(gb); + else + v->halfpq = 0; + if (v->quantizer_mode == QUANT_FRAME_EXPLICIT) + v->pquantizer = get_bits1(gb); + if (v->postprocflag) + v->postproc = get_bits(gb, 2); + + if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_P) + v->use_ic = 0; + + if (v->parse_only) + return 0; + + switch (v->s.pict_type) { + case AV_PICTURE_TYPE_I: + case AV_PICTURE_TYPE_BI: + if (v->fcm == ILACE_FRAME) { //interlace frame picture + status = bitplane_decoding(v->fieldtx_plane, &v->fieldtx_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "FIELDTX plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + } + status = bitplane_decoding(v->acpred_plane, &v->acpred_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "ACPRED plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + v->condover = CONDOVER_NONE; + if (v->overlap && v->pq <= 8) { + v->condover = decode012(gb); + if (v->condover == CONDOVER_SELECT) { + status = bitplane_decoding(v->over_flags_plane, &v->overflg_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "CONDOVER plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + } + } + break; + case AV_PICTURE_TYPE_P: + if (v->field_mode) { + v->numref = get_bits1(gb); + if (!v->numref) { + v->reffield = get_bits1(gb); + v->ref_field_type[0] = v->reffield ^ !v->cur_field_type; + } + } + if (v->extended_mv) + v->mvrange = get_unary(gb, 0, 3); + else + v->mvrange = 0; + if (v->interlace) { + if (v->extended_dmv) + v->dmvrange = get_unary(gb, 0, 3); + else + v->dmvrange = 0; + if (v->fcm == ILACE_FRAME) { // interlaced frame picture + v->fourmvswitch = get_bits1(gb); + v->intcomp = get_bits1(gb); + if (v->intcomp) { + v->lumscale = get_bits(gb, 6); + v->lumshift = get_bits(gb, 6); + INIT_LUT(v->lumscale, v->lumshift, v->luty, v->lutuv); + } + status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); + av_log(v->s.avctx, AV_LOG_DEBUG, "SKIPMB plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + mbmodetab = get_bits(gb, 2); + if (v->fourmvswitch) + v->mbmode_vlc = &ff_vc1_intfr_4mv_mbmode_vlc[mbmodetab]; + else + v->mbmode_vlc = &ff_vc1_intfr_non4mv_mbmode_vlc[mbmodetab]; + imvtab = get_bits(gb, 2); + v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[imvtab]; + // interlaced p-picture cbpcy range is [1, 63] + icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; + twomvbptab = get_bits(gb, 2); + v->twomvbp_vlc = &ff_vc1_2mv_block_pattern_vlc[twomvbptab]; + if (v->fourmvswitch) { + fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + } + } + } + v->k_x = v->mvrange + 9 + (v->mvrange >> 1); //k_x can be 9 10 12 13 + v->k_y = v->mvrange + 8; //k_y can be 8 9 10 11 + v->range_x = 1 << (v->k_x - 1); + v->range_y = 1 << (v->k_y - 1); + + if (v->pq < 5) + v->tt_index = 0; + else if (v->pq < 13) + v->tt_index = 1; + else + v->tt_index = 2; + if (v->fcm != ILACE_FRAME) { + int mvmode; + mvmode = get_unary(gb, 1, 4); + lowquant = (v->pq > 12) ? 0 : 1; + v->mv_mode = ff_vc1_mv_pmode_table[lowquant][mvmode]; + if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + int mvmode2; + mvmode2 = get_unary(gb, 1, 3); + v->mv_mode2 = ff_vc1_mv_pmode_table2[lowquant][mvmode2]; + if (v->field_mode) + v->intcompfield = decode210(gb); + v->lumscale = get_bits(gb, 6); + v->lumshift = get_bits(gb, 6); + INIT_LUT(v->lumscale, v->lumshift, v->luty, v->lutuv); + if ((v->field_mode) && !v->intcompfield) { + v->lumscale2 = get_bits(gb, 6); + v->lumshift2 = get_bits(gb, 6); + INIT_LUT(v->lumscale2, v->lumshift2, v->luty2, v->lutuv2); + } + v->use_ic = 1; + } + v->qs_last = v->s.quarter_sample; + if (v->mv_mode == MV_PMODE_1MV_HPEL || v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) + v->s.quarter_sample = 0; + else if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + if (v->mv_mode2 == MV_PMODE_1MV_HPEL || v->mv_mode2 == MV_PMODE_1MV_HPEL_BILIN) + v->s.quarter_sample = 0; + else + v->s.quarter_sample = 1; + } else + v->s.quarter_sample = 1; + v->s.mspel = !(v->mv_mode == MV_PMODE_1MV_HPEL_BILIN + || (v->mv_mode == MV_PMODE_INTENSITY_COMP + && v->mv_mode2 == MV_PMODE_1MV_HPEL_BILIN)); + } + if (v->fcm == PROGRESSIVE) { // progressive + if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->mv_mode2 == MV_PMODE_MIXED_MV) + || v->mv_mode == MV_PMODE_MIXED_MV) { + status = bitplane_decoding(v->mv_type_mb_plane, &v->mv_type_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB MV Type plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + } else { + v->mv_type_is_raw = 0; + memset(v->mv_type_mb_plane, 0, v->s.mb_stride * v->s.mb_height); + } + status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + + /* Hopefully this is correct for P frames */ + v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + } else if (v->fcm == ILACE_FRAME) { // frame interlaced + v->qs_last = v->s.quarter_sample; + v->s.quarter_sample = 1; + v->s.mspel = 1; + } else { // field interlaced + mbmodetab = get_bits(gb, 3); + imvtab = get_bits(gb, 2 + v->numref); + if (!v->numref) + v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[imvtab]; + else + v->imv_vlc = &ff_vc1_2ref_mvdata_vlc[imvtab]; + icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; + if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && + v->mv_mode2 == MV_PMODE_MIXED_MV) || v->mv_mode == MV_PMODE_MIXED_MV) { + fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + v->mbmode_vlc = &ff_vc1_if_mmv_mbmode_vlc[mbmodetab]; + } else { + v->mbmode_vlc = &ff_vc1_if_1mv_mbmode_vlc[mbmodetab]; + } + } + if (v->dquant) { + av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); + vop_dquant_decoding(v); + } + + v->ttfrm = 0; //FIXME Is that so ? + if (v->vstransform) { + v->ttmbf = get_bits1(gb); + if (v->ttmbf) { + v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)]; + } + } else { + v->ttmbf = 1; + v->ttfrm = TT_8X8; + } + break; + case AV_PICTURE_TYPE_B: + if (v->fcm == ILACE_FRAME) { + v->bfraction_lut_index = get_vlc2(gb, ff_vc1_bfraction_vlc.table, VC1_BFRACTION_VLC_BITS, 1); + v->bfraction = ff_vc1_bfraction_lut[v->bfraction_lut_index]; + if (v->bfraction == 0) { + return -1; + } + } + if (v->extended_mv) + v->mvrange = get_unary(gb, 0, 3); + else + v->mvrange = 0; + v->k_x = v->mvrange + 9 + (v->mvrange >> 1); //k_x can be 9 10 12 13 + v->k_y = v->mvrange + 8; //k_y can be 8 9 10 11 + v->range_x = 1 << (v->k_x - 1); + v->range_y = 1 << (v->k_y - 1); + + if (v->pq < 5) + v->tt_index = 0; + else if (v->pq < 13) + v->tt_index = 1; + else + v->tt_index = 2; + + if (v->field_mode) { + int mvmode; + av_log(v->s.avctx, AV_LOG_DEBUG, "B Fields\n"); + if (v->extended_dmv) + v->dmvrange = get_unary(gb, 0, 3); + mvmode = get_unary(gb, 1, 3); + lowquant = (v->pq > 12) ? 0 : 1; + v->mv_mode = ff_vc1_mv_pmode_table2[lowquant][mvmode]; + v->qs_last = v->s.quarter_sample; + v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV || v->mv_mode == MV_PMODE_MIXED_MV); + v->s.mspel = !(v->mv_mode == MV_PMODE_1MV_HPEL_BILIN || v->mv_mode == MV_PMODE_1MV_HPEL); + status = bitplane_decoding(v->forward_mb_plane, &v->fmb_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Forward Type plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + mbmodetab = get_bits(gb, 3); + if (v->mv_mode == MV_PMODE_MIXED_MV) + v->mbmode_vlc = &ff_vc1_if_mmv_mbmode_vlc[mbmodetab]; + else + v->mbmode_vlc = &ff_vc1_if_1mv_mbmode_vlc[mbmodetab]; + imvtab = get_bits(gb, 3); + v->imv_vlc = &ff_vc1_2ref_mvdata_vlc[imvtab]; + icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; + if (v->mv_mode == MV_PMODE_MIXED_MV) { + fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + } + v->numref = 1; // interlaced field B pictures are always 2-ref + } else if (v->fcm == ILACE_FRAME) { + if (v->extended_dmv) + v->dmvrange = get_unary(gb, 0, 3); + get_bits1(gb); /* intcomp - present but shall always be 0 */ + v->intcomp = 0; + v->mv_mode = MV_PMODE_1MV; + v->fourmvswitch = 0; + v->qs_last = v->s.quarter_sample; + v->s.quarter_sample = 1; + v->s.mspel = 1; + status = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Direct Type plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + mbmodetab = get_bits(gb, 2); + v->mbmode_vlc = &ff_vc1_intfr_non4mv_mbmode_vlc[mbmodetab]; + imvtab = get_bits(gb, 2); + v->imv_vlc = &ff_vc1_1ref_mvdata_vlc[imvtab]; + // interlaced p/b-picture cbpcy range is [1, 63] + icbptab = get_bits(gb, 3); + v->cbpcy_vlc = &ff_vc1_icbpcy_vlc[icbptab]; + twomvbptab = get_bits(gb, 2); + v->twomvbp_vlc = &ff_vc1_2mv_block_pattern_vlc[twomvbptab]; + fourmvbptab = get_bits(gb, 2); + v->fourmvbp_vlc = &ff_vc1_4mv_block_pattern_vlc[fourmvbptab]; + } else { + v->mv_mode = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN; + v->qs_last = v->s.quarter_sample; + v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV); + v->s.mspel = v->s.quarter_sample; + status = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Direct Type plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v); + if (status < 0) + return -1; + av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: " + "Imode: %i, Invert: %i\n", status>>1, status&1); + v->s.mv_table_index = get_bits(gb, 2); + v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)]; + } + + if (v->dquant) { + av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); + vop_dquant_decoding(v); + } + + v->ttfrm = 0; + if (v->vstransform) { + v->ttmbf = get_bits1(gb); + if (v->ttmbf) { + v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)]; + } + } else { + v->ttmbf = 1; + v->ttfrm = TT_8X8; + } + break; + } + + if (v->fcm != PROGRESSIVE && !v->s.quarter_sample) { + v->range_x <<= 1; + v->range_y <<= 1; + } + + /* AC Syntax */ + v->c_ac_table_index = decode012(gb); + if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) { + v->y_ac_table_index = decode012(gb); + } + /* DC Syntax */ + v->s.dc_table_index = get_bits1(gb); + if ((v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) + && v->dquant) { + av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); + vop_dquant_decoding(v); + } + + v->bi_type = 0; + if (v->s.pict_type == AV_PICTURE_TYPE_BI) { + v->s.pict_type = AV_PICTURE_TYPE_B; + v->bi_type = 1; + } + return 0; +} + +static const uint32_t vc1_ac_tables[AC_MODES][186][2] = { +{ +{ 0x0001, 2}, { 0x0005, 3}, { 0x000D, 4}, { 0x0012, 5}, { 0x000E, 6}, { 0x0015, 7}, +{ 0x0013, 8}, { 0x003F, 8}, { 0x004B, 9}, { 0x011F, 9}, { 0x00B8, 10}, { 0x03E3, 10}, +{ 0x0172, 11}, { 0x024D, 12}, { 0x03DA, 12}, { 0x02DD, 13}, { 0x1F55, 13}, { 0x05B9, 14}, +{ 0x3EAE, 14}, { 0x0000, 4}, { 0x0010, 5}, { 0x0008, 7}, { 0x0020, 8}, { 0x0029, 9}, +{ 0x01F4, 9}, { 0x0233, 10}, { 0x01E0, 11}, { 0x012A, 12}, { 0x03DD, 12}, { 0x050A, 13}, +{ 0x1F29, 13}, { 0x0A42, 14}, { 0x1272, 15}, { 0x1737, 15}, { 0x0003, 5}, { 0x0011, 7}, +{ 0x00C4, 8}, { 0x004B, 10}, { 0x00B4, 11}, { 0x07D4, 11}, { 0x0345, 12}, { 0x02D7, 13}, +{ 0x07BF, 13}, { 0x0938, 14}, { 0x0BBB, 14}, { 0x095E, 15}, { 0x0013, 5}, { 0x0078, 7}, +{ 0x0069, 9}, { 0x0232, 10}, { 0x0461, 11}, { 0x03EC, 12}, { 0x0520, 13}, { 0x1F2A, 13}, +{ 0x3E50, 14}, { 0x3E51, 14}, { 0x1486, 15}, { 0x000C, 6}, { 0x0024, 9}, { 0x0094, 11}, +{ 0x08C0, 12}, { 0x0F09, 14}, { 0x1EF0, 15}, { 0x003D, 6}, { 0x0053, 9}, { 0x01A0, 11}, +{ 0x02D6, 13}, { 0x0F08, 14}, { 0x0013, 7}, { 0x007C, 9}, { 0x07C1, 11}, { 0x04AC, 14}, +{ 0x001B, 7}, { 0x00A0, 10}, { 0x0344, 12}, { 0x0F79, 14}, { 0x0079, 7}, { 0x03E1, 10}, +{ 0x02D4, 13}, { 0x2306, 14}, { 0x0021, 8}, { 0x023C, 10}, { 0x0FAE, 12}, { 0x23DE, 14}, +{ 0x0035, 8}, { 0x0175, 11}, { 0x07B3, 13}, { 0x00C5, 8}, { 0x0174, 11}, { 0x0785, 13}, +{ 0x0048, 9}, { 0x01A3, 11}, { 0x049E, 13}, { 0x002C, 9}, { 0x00FA, 10}, { 0x07D6, 11}, +{ 0x0092, 10}, { 0x05CC, 13}, { 0x1EF1, 15}, { 0x00A3, 10}, { 0x03ED, 12}, { 0x093E, 14}, +{ 0x01E2, 11}, { 0x1273, 15}, { 0x07C4, 11}, { 0x1487, 15}, { 0x0291, 12}, { 0x0293, 12}, +{ 0x0F8A, 12}, { 0x0509, 13}, { 0x0508, 13}, { 0x078D, 13}, { 0x07BE, 13}, { 0x078C, 13}, +{ 0x04AE, 14}, { 0x0BBA, 14}, { 0x2307, 14}, { 0x0B9A, 14}, { 0x1736, 15}, { 0x000E, 4}, +{ 0x0045, 7}, { 0x01F3, 9}, { 0x047A, 11}, { 0x05DC, 13}, { 0x23DF, 14}, { 0x0019, 5}, +{ 0x0028, 9}, { 0x0176, 11}, { 0x049D, 13}, { 0x23DD, 14}, { 0x0030, 6}, { 0x00A2, 10}, +{ 0x02EF, 12}, { 0x05B8, 14}, { 0x003F, 6}, { 0x00A5, 10}, { 0x03DB, 12}, { 0x093F, 14}, +{ 0x0044, 7}, { 0x07CB, 11}, { 0x095F, 15}, { 0x0063, 7}, { 0x03C3, 12}, { 0x0015, 8}, +{ 0x08F6, 12}, { 0x0017, 8}, { 0x0498, 13}, { 0x002C, 8}, { 0x07B2, 13}, { 0x002F, 8}, +{ 0x1F54, 13}, { 0x008D, 8}, { 0x07BD, 13}, { 0x008E, 8}, { 0x1182, 13}, { 0x00FB, 8}, +{ 0x050B, 13}, { 0x002D, 8}, { 0x07C0, 11}, { 0x0079, 9}, { 0x1F5F, 13}, { 0x007A, 9}, +{ 0x1F56, 13}, { 0x0231, 10}, { 0x03E4, 10}, { 0x01A1, 11}, { 0x0143, 11}, { 0x01F7, 11}, +{ 0x016F, 12}, { 0x0292, 12}, { 0x02E7, 12}, { 0x016C, 12}, { 0x016D, 12}, { 0x03DC, 12}, +{ 0x0F8B, 12}, { 0x0499, 13}, { 0x03D8, 12}, { 0x078E, 13}, { 0x02D5, 13}, { 0x1F5E, 13}, +{ 0x1F2B, 13}, { 0x078F, 13}, { 0x04AD, 14}, { 0x3EAF, 14}, { 0x23DC, 14}, { 0x004A, 9} +}, +{ +{ 0x0000, 3}, { 0x0003, 4}, { 0x000B, 5}, { 0x0014, 6}, { 0x003F, 6}, { 0x005D, 7}, +{ 0x00A2, 8}, { 0x00AC, 9}, { 0x016E, 9}, { 0x020A, 10}, { 0x02E2, 10}, { 0x0432, 11}, +{ 0x05C9, 11}, { 0x0827, 12}, { 0x0B54, 12}, { 0x04E6, 13}, { 0x105F, 13}, { 0x172A, 13}, +{ 0x20B2, 14}, { 0x2D4E, 14}, { 0x39F0, 14}, { 0x4175, 15}, { 0x5A9E, 15}, { 0x0004, 4}, +{ 0x001E, 5}, { 0x0042, 7}, { 0x00B6, 8}, { 0x0173, 9}, { 0x0395, 10}, { 0x072E, 11}, +{ 0x0B94, 12}, { 0x16A4, 13}, { 0x20B3, 14}, { 0x2E45, 14}, { 0x0005, 5}, { 0x0040, 7}, +{ 0x0049, 9}, { 0x028F, 10}, { 0x05CB, 11}, { 0x048A, 13}, { 0x09DD, 14}, { 0x73E2, 15}, +{ 0x0018, 5}, { 0x0025, 8}, { 0x008A, 10}, { 0x051B, 11}, { 0x0E5F, 12}, { 0x09C9, 14}, +{ 0x139C, 15}, { 0x0029, 6}, { 0x004F, 9}, { 0x0412, 11}, { 0x048D, 13}, { 0x2E41, 14}, +{ 0x0038, 6}, { 0x010E, 9}, { 0x05A8, 11}, { 0x105C, 13}, { 0x39F2, 14}, { 0x0058, 7}, +{ 0x021F, 10}, { 0x0E7E, 12}, { 0x39FF, 14}, { 0x0023, 8}, { 0x02E3, 10}, { 0x04E5, 13}, +{ 0x2E40, 14}, { 0x00A1, 8}, { 0x05BE, 11}, { 0x09C8, 14}, { 0x0083, 8}, { 0x013A, 11}, +{ 0x1721, 13}, { 0x0044, 9}, { 0x0276, 12}, { 0x39F6, 14}, { 0x008B, 10}, { 0x04EF, 13}, +{ 0x5A9B, 15}, { 0x0208, 10}, { 0x1CFE, 13}, { 0x0399, 10}, { 0x1CB4, 13}, { 0x039E, 10}, +{ 0x39F3, 14}, { 0x05AB, 11}, { 0x73E3, 15}, { 0x0737, 11}, { 0x5A9F, 15}, { 0x082D, 12}, +{ 0x0E69, 12}, { 0x0E68, 12}, { 0x0433, 11}, { 0x0B7B, 12}, { 0x2DF8, 14}, { 0x2E56, 14}, +{ 0x2E57, 14}, { 0x39F7, 14}, { 0x51A5, 15}, { 0x0003, 3}, { 0x002A, 6}, { 0x00E4, 8}, +{ 0x028E, 10}, { 0x0735, 11}, { 0x1058, 13}, { 0x1CFA, 13}, { 0x2DF9, 14}, { 0x4174, 15}, +{ 0x0009, 4}, { 0x0054, 8}, { 0x0398, 10}, { 0x048B, 13}, { 0x139D, 15}, { 0x000D, 4}, +{ 0x00AD, 9}, { 0x0826, 12}, { 0x2D4C, 14}, { 0x0011, 5}, { 0x016B, 9}, { 0x0B7F, 12}, +{ 0x51A4, 15}, { 0x0019, 5}, { 0x021B, 10}, { 0x16FD, 13}, { 0x001D, 5}, { 0x0394, 10}, +{ 0x28D3, 14}, { 0x002B, 6}, { 0x05BC, 11}, { 0x5A9A, 15}, { 0x002F, 6}, { 0x0247, 12}, +{ 0x0010, 7}, { 0x0A35, 12}, { 0x003E, 6}, { 0x0B7A, 12}, { 0x0059, 7}, { 0x105E, 13}, +{ 0x0026, 8}, { 0x09CF, 14}, { 0x0055, 8}, { 0x1CB5, 13}, { 0x0057, 8}, { 0x0E5B, 12}, +{ 0x00A0, 8}, { 0x1468, 13}, { 0x0170, 9}, { 0x0090, 10}, { 0x01CE, 9}, { 0x021A, 10}, +{ 0x0218, 10}, { 0x0168, 9}, { 0x021E, 10}, { 0x0244, 12}, { 0x0736, 11}, { 0x0138, 11}, +{ 0x0519, 11}, { 0x0E5E, 12}, { 0x072C, 11}, { 0x0B55, 12}, { 0x09DC, 14}, { 0x20BB, 14}, +{ 0x048C, 13}, { 0x1723, 13}, { 0x2E44, 14}, { 0x16A5, 13}, { 0x0518, 11}, { 0x39FE, 14}, +{ 0x0169, 9} +}, +{ +{ 0x0001, 2}, { 0x0006, 3}, { 0x000F, 4}, { 0x0016, 5}, { 0x0020, 6}, { 0x0018, 7}, +{ 0x0008, 8}, { 0x009A, 8}, { 0x0056, 9}, { 0x013E, 9}, { 0x00F0, 10}, { 0x03A5, 10}, +{ 0x0077, 11}, { 0x01EF, 11}, { 0x009A, 12}, { 0x005D, 13}, { 0x0001, 4}, { 0x0011, 5}, +{ 0x0002, 7}, { 0x000B, 8}, { 0x0012, 9}, { 0x01D6, 9}, { 0x027E, 10}, { 0x0191, 11}, +{ 0x00EA, 12}, { 0x03DC, 12}, { 0x013B, 13}, { 0x0004, 5}, { 0x0014, 7}, { 0x009E, 8}, +{ 0x0009, 10}, { 0x01AC, 11}, { 0x01E2, 11}, { 0x03CA, 12}, { 0x005F, 13}, { 0x0017, 5}, +{ 0x004E, 7}, { 0x005E, 9}, { 0x00F3, 10}, { 0x01AD, 11}, { 0x00EC, 12}, { 0x05F0, 13}, +{ 0x000E, 6}, { 0x00E1, 8}, { 0x03A4, 10}, { 0x009C, 12}, { 0x013D, 13}, { 0x003B, 6}, +{ 0x001C, 9}, { 0x0014, 11}, { 0x09BE, 12}, { 0x0006, 7}, { 0x007A, 9}, { 0x0190, 11}, +{ 0x0137, 13}, { 0x001B, 7}, { 0x0008, 10}, { 0x075C, 11}, { 0x0071, 7}, { 0x00D7, 10}, +{ 0x09BF, 12}, { 0x0007, 8}, { 0x00AF, 10}, { 0x04CC, 11}, { 0x0034, 8}, { 0x0265, 10}, +{ 0x009F, 12}, { 0x00E0, 8}, { 0x0016, 11}, { 0x0327, 12}, { 0x0015, 9}, { 0x017D, 11}, +{ 0x0EBB, 12}, { 0x0014, 9}, { 0x00F6, 10}, { 0x01E4, 11}, { 0x00CB, 10}, { 0x099D, 12}, +{ 0x00CA, 10}, { 0x02FC, 12}, { 0x017F, 11}, { 0x04CD, 11}, { 0x02FD, 12}, { 0x04FE, 11}, +{ 0x013A, 13}, { 0x000A, 4}, { 0x0042, 7}, { 0x01D3, 9}, { 0x04DD, 11}, { 0x0012, 5}, +{ 0x00E8, 8}, { 0x004C, 11}, { 0x0136, 13}, { 0x0039, 6}, { 0x0264, 10}, { 0x0EBA, 12}, +{ 0x0000, 7}, { 0x00AE, 10}, { 0x099C, 12}, { 0x001F, 7}, { 0x04DE, 11}, { 0x0043, 7}, +{ 0x04DC, 11}, { 0x0003, 8}, { 0x03CB, 12}, { 0x0006, 8}, { 0x099E, 12}, { 0x002A, 8}, +{ 0x05F1, 13}, { 0x000F, 8}, { 0x09FE, 12}, { 0x0033, 8}, { 0x09FF, 12}, { 0x0098, 8}, +{ 0x099F, 12}, { 0x00EA, 8}, { 0x013C, 13}, { 0x002E, 8}, { 0x0192, 11}, { 0x0136, 9}, +{ 0x006A, 9}, { 0x0015, 11}, { 0x03AF, 10}, { 0x01E3, 11}, { 0x0074, 11}, { 0x00EB, 12}, +{ 0x02F9, 12}, { 0x005C, 13}, { 0x00ED, 12}, { 0x03DD, 12}, { 0x0326, 12}, { 0x005E, 13}, +{ 0x0016, 7} +}, +{ +{ 0x0004, 3}, { 0x0014, 5}, { 0x0017, 7}, { 0x007F, 8}, { 0x0154, 9}, { 0x01F2, 10}, +{ 0x00BF, 11}, { 0x0065, 12}, { 0x0AAA, 12}, { 0x0630, 13}, { 0x1597, 13}, { 0x03B7, 14}, +{ 0x2B22, 14}, { 0x0BE6, 15}, { 0x000B, 4}, { 0x0037, 7}, { 0x0062, 9}, { 0x0007, 11}, +{ 0x0166, 12}, { 0x00CE, 13}, { 0x1590, 13}, { 0x05F6, 14}, { 0x0BE7, 15}, { 0x0007, 5}, +{ 0x006D, 8}, { 0x0003, 11}, { 0x031F, 12}, { 0x05F2, 14}, { 0x0002, 6}, { 0x0061, 9}, +{ 0x0055, 12}, { 0x01DF, 14}, { 0x001A, 6}, { 0x001E, 10}, { 0x0AC9, 12}, { 0x2B23, 14}, +{ 0x001E, 6}, { 0x001F, 10}, { 0x0AC3, 12}, { 0x2B2B, 14}, { 0x0006, 7}, { 0x0004, 11}, +{ 0x02F8, 13}, { 0x0019, 7}, { 0x0006, 11}, { 0x063D, 13}, { 0x0057, 7}, { 0x0182, 11}, +{ 0x2AA2, 14}, { 0x0004, 8}, { 0x0180, 11}, { 0x059C, 14}, { 0x007D, 8}, { 0x0164, 12}, +{ 0x076D, 15}, { 0x0002, 9}, { 0x018D, 11}, { 0x1581, 13}, { 0x00AD, 8}, { 0x0060, 12}, +{ 0x0C67, 14}, { 0x001C, 9}, { 0x00EE, 13}, { 0x0003, 9}, { 0x02CF, 13}, { 0x00D9, 9}, +{ 0x1580, 13}, { 0x0002, 11}, { 0x0183, 11}, { 0x0057, 12}, { 0x0061, 12}, { 0x0031, 11}, +{ 0x0066, 12}, { 0x0631, 13}, { 0x0632, 13}, { 0x00AC, 13}, { 0x031D, 12}, { 0x0076, 12}, +{ 0x003A, 11}, { 0x0165, 12}, { 0x0C66, 14}, { 0x0003, 2}, { 0x0054, 7}, { 0x02AB, 10}, +{ 0x0016, 13}, { 0x05F7, 14}, { 0x0005, 4}, { 0x00F8, 9}, { 0x0AA9, 12}, { 0x005F, 15}, +{ 0x0004, 4}, { 0x001C, 10}, { 0x1550, 13}, { 0x0004, 5}, { 0x0077, 11}, { 0x076C, 15}, +{ 0x000E, 5}, { 0x000A, 12}, { 0x000C, 5}, { 0x0562, 11}, { 0x0004, 6}, { 0x031C, 12}, +{ 0x0006, 6}, { 0x00C8, 13}, { 0x000D, 6}, { 0x01DA, 13}, { 0x0007, 6}, { 0x00C9, 13}, +{ 0x0001, 7}, { 0x002E, 14}, { 0x0014, 7}, { 0x1596, 13}, { 0x000A, 7}, { 0x0AC2, 12}, +{ 0x0016, 7}, { 0x015B, 14}, { 0x0015, 7}, { 0x015A, 14}, { 0x000F, 8}, { 0x005E, 15}, +{ 0x007E, 8}, { 0x00AB, 8}, { 0x002D, 9}, { 0x00D8, 9}, { 0x000B, 9}, { 0x0014, 10}, +{ 0x02B3, 10}, { 0x01F3, 10}, { 0x003A, 10}, { 0x0000, 10}, { 0x0058, 10}, { 0x002E, 9}, +{ 0x005E, 10}, { 0x0563, 11}, { 0x00EC, 12}, { 0x0054, 12}, { 0x0AC1, 12}, { 0x1556, 13}, +{ 0x02FA, 13}, { 0x0181, 11}, { 0x1557, 13}, { 0x059D, 14}, { 0x2AA3, 14}, { 0x2B2A, 14}, +{ 0x01DE, 14}, { 0x063C, 13}, { 0x00CF, 13}, { 0x1594, 13}, { 0x000D, 9} +}, +{ +{ 0x0002, 2}, { 0x0006, 3}, { 0x000F, 4}, { 0x000D, 5}, { 0x000C, 5}, { 0x0015, 6}, +{ 0x0013, 6}, { 0x0012, 6}, { 0x0017, 7}, { 0x001F, 8}, { 0x001E, 8}, { 0x001D, 8}, +{ 0x0025, 9}, { 0x0024, 9}, { 0x0023, 9}, { 0x0021, 9}, { 0x0021, 10}, { 0x0020, 10}, +{ 0x000F, 10}, { 0x000E, 10}, { 0x0007, 11}, { 0x0006, 11}, { 0x0020, 11}, { 0x0021, 11}, +{ 0x0050, 12}, { 0x0051, 12}, { 0x0052, 12}, { 0x000E, 4}, { 0x0014, 6}, { 0x0016, 7}, +{ 0x001C, 8}, { 0x0020, 9}, { 0x001F, 9}, { 0x000D, 10}, { 0x0022, 11}, { 0x0053, 12}, +{ 0x0055, 12}, { 0x000B, 5}, { 0x0015, 7}, { 0x001E, 9}, { 0x000C, 10}, { 0x0056, 12}, +{ 0x0011, 6}, { 0x001B, 8}, { 0x001D, 9}, { 0x000B, 10}, { 0x0010, 6}, { 0x0022, 9}, +{ 0x000A, 10}, { 0x000D, 6}, { 0x001C, 9}, { 0x0008, 10}, { 0x0012, 7}, { 0x001B, 9}, +{ 0x0054, 12}, { 0x0014, 7}, { 0x001A, 9}, { 0x0057, 12}, { 0x0019, 8}, { 0x0009, 10}, +{ 0x0018, 8}, { 0x0023, 11}, { 0x0017, 8}, { 0x0019, 9}, { 0x0018, 9}, { 0x0007, 10}, +{ 0x0058, 12}, { 0x0007, 4}, { 0x000C, 6}, { 0x0016, 8}, { 0x0017, 9}, { 0x0006, 10}, +{ 0x0005, 11}, { 0x0004, 11}, { 0x0059, 12}, { 0x000F, 6}, { 0x0016, 9}, { 0x0005, 10}, +{ 0x000E, 6}, { 0x0004, 10}, { 0x0011, 7}, { 0x0024, 11}, { 0x0010, 7}, { 0x0025, 11}, +{ 0x0013, 7}, { 0x005A, 12}, { 0x0015, 8}, { 0x005B, 12}, { 0x0014, 8}, { 0x0013, 8}, +{ 0x001A, 8}, { 0x0015, 9}, { 0x0014, 9}, { 0x0013, 9}, { 0x0012, 9}, { 0x0011, 9}, +{ 0x0026, 11}, { 0x0027, 11}, { 0x005C, 12}, { 0x005D, 12}, { 0x005E, 12}, { 0x005F, 12}, +{ 0x0003, 7} +}, +{ +{ 0x0002, 2}, { 0x000F, 4}, { 0x0015, 6}, { 0x0017, 7}, { 0x001F, 8}, { 0x0025, 9}, +{ 0x0024, 9}, { 0x0021, 10}, { 0x0020, 10}, { 0x0007, 11}, { 0x0006, 11}, { 0x0020, 11}, +{ 0x0006, 3}, { 0x0014, 6}, { 0x001E, 8}, { 0x000F, 10}, { 0x0021, 11}, { 0x0050, 12}, +{ 0x000E, 4}, { 0x001D, 8}, { 0x000E, 10}, { 0x0051, 12}, { 0x000D, 5}, { 0x0023, 9}, +{ 0x000D, 10}, { 0x000C, 5}, { 0x0022, 9}, { 0x0052, 12}, { 0x000B, 5}, { 0x000C, 10}, +{ 0x0053, 12}, { 0x0013, 6}, { 0x000B, 10}, { 0x0054, 12}, { 0x0012, 6}, { 0x000A, 10}, +{ 0x0011, 6}, { 0x0009, 10}, { 0x0010, 6}, { 0x0008, 10}, { 0x0016, 7}, { 0x0055, 12}, +{ 0x0015, 7}, { 0x0014, 7}, { 0x001C, 8}, { 0x001B, 8}, { 0x0021, 9}, { 0x0020, 9}, +{ 0x001F, 9}, { 0x001E, 9}, { 0x001D, 9}, { 0x001C, 9}, { 0x001B, 9}, { 0x001A, 9}, +{ 0x0022, 11}, { 0x0023, 11}, { 0x0056, 12}, { 0x0057, 12}, { 0x0007, 4}, { 0x0019, 9}, +{ 0x0005, 11}, { 0x000F, 6}, { 0x0004, 11}, { 0x000E, 6}, { 0x000D, 6}, { 0x000C, 6}, +{ 0x0013, 7}, { 0x0012, 7}, { 0x0011, 7}, { 0x0010, 7}, { 0x001A, 8}, { 0x0019, 8}, +{ 0x0018, 8}, { 0x0017, 8}, { 0x0016, 8}, { 0x0015, 8}, { 0x0014, 8}, { 0x0013, 8}, +{ 0x0018, 9}, { 0x0017, 9}, { 0x0016, 9}, { 0x0015, 9}, { 0x0014, 9}, { 0x0013, 9}, +{ 0x0012, 9}, { 0x0011, 9}, { 0x0007, 10}, { 0x0006, 10}, { 0x0005, 10}, { 0x0004, 10}, +{ 0x0024, 11}, { 0x0025, 11}, { 0x0026, 11}, { 0x0027, 11}, { 0x0058, 12}, { 0x0059, 12}, +{ 0x005A, 12}, { 0x005B, 12}, { 0x005C, 12}, { 0x005D, 12}, { 0x005E, 12}, { 0x005F, 12}, +{ 0x0003, 7} +}, +{ +{ 0x0000, 2}, { 0x0003, 3}, { 0x000D, 4}, { 0x0005, 4}, { 0x001C, 5}, { 0x0016, 5}, +{ 0x003F, 6}, { 0x003A, 6}, { 0x002E, 6}, { 0x0022, 6}, { 0x007B, 7}, { 0x0067, 7}, +{ 0x005F, 7}, { 0x0047, 7}, { 0x0026, 7}, { 0x00EF, 8}, { 0x00CD, 8}, { 0x00C1, 8}, +{ 0x00A9, 8}, { 0x004F, 8}, { 0x01F2, 9}, { 0x01DD, 9}, { 0x0199, 9}, { 0x0185, 9}, +{ 0x015D, 9}, { 0x011B, 9}, { 0x03EF, 10}, { 0x03E1, 10}, { 0x03C8, 10}, { 0x0331, 10}, +{ 0x0303, 10}, { 0x02F1, 10}, { 0x02A0, 10}, { 0x0233, 10}, { 0x0126, 10}, { 0x07C0, 11}, +{ 0x076F, 11}, { 0x076C, 11}, { 0x0661, 11}, { 0x0604, 11}, { 0x0572, 11}, { 0x0551, 11}, +{ 0x046A, 11}, { 0x0274, 11}, { 0x0F27, 12}, { 0x0F24, 12}, { 0x0EDB, 12}, { 0x0C8E, 12}, +{ 0x0C0B, 12}, { 0x0C0A, 12}, { 0x0AE3, 12}, { 0x08D6, 12}, { 0x0490, 12}, { 0x0495, 12}, +{ 0x1F19, 13}, { 0x1DB5, 13}, { 0x0009, 4}, { 0x0010, 5}, { 0x0029, 6}, { 0x0062, 7}, +{ 0x00F3, 8}, { 0x00AD, 8}, { 0x01E5, 9}, { 0x0179, 9}, { 0x009C, 9}, { 0x03B1, 10}, +{ 0x02AE, 10}, { 0x0127, 10}, { 0x076E, 11}, { 0x0570, 11}, { 0x0275, 11}, { 0x0F25, 12}, +{ 0x0EC0, 12}, { 0x0AA0, 12}, { 0x08D7, 12}, { 0x1E4C, 13}, { 0x0008, 5}, { 0x0063, 7}, +{ 0x00AF, 8}, { 0x017B, 9}, { 0x03B3, 10}, { 0x07DD, 11}, { 0x0640, 11}, { 0x0F8D, 12}, +{ 0x0BC1, 12}, { 0x0491, 12}, { 0x0028, 6}, { 0x00C3, 8}, { 0x0151, 9}, { 0x02A1, 10}, +{ 0x0573, 11}, { 0x0EC3, 12}, { 0x1F35, 13}, { 0x0065, 7}, { 0x01DA, 9}, { 0x02AF, 10}, +{ 0x0277, 11}, { 0x08C9, 12}, { 0x1781, 13}, { 0x0025, 7}, { 0x0118, 9}, { 0x0646, 11}, +{ 0x0AA6, 12}, { 0x1780, 13}, { 0x00C9, 8}, { 0x0321, 10}, { 0x0F9B, 12}, { 0x191E, 13}, +{ 0x0048, 8}, { 0x07CC, 11}, { 0x0AA1, 12}, { 0x0180, 9}, { 0x0465, 11}, { 0x1905, 13}, +{ 0x03E2, 10}, { 0x0EC1, 12}, { 0x3C9B, 14}, { 0x02F4, 10}, { 0x08C8, 12}, { 0x07C1, 11}, +{ 0x0928, 13}, { 0x05E1, 11}, { 0x320D, 14}, { 0x0EC2, 12}, { 0x6418, 15}, { 0x1F34, 13}, +{ 0x0078, 7}, { 0x0155, 9}, { 0x0552, 11}, { 0x191F, 13}, { 0x00FA, 8}, { 0x07DC, 11}, +{ 0x1907, 13}, { 0x00AC, 8}, { 0x0249, 11}, { 0x13B1, 14}, { 0x01F6, 9}, { 0x0AE2, 12}, +{ 0x01DC, 9}, { 0x04ED, 12}, { 0x0184, 9}, { 0x1904, 13}, { 0x0156, 9}, { 0x09D9, 13}, +{ 0x03E7, 10}, { 0x0929, 13}, { 0x03B2, 10}, { 0x3B68, 14}, { 0x02F5, 10}, { 0x13B0, 14}, +{ 0x0322, 10}, { 0x3B69, 14}, { 0x0234, 10}, { 0x7935, 15}, { 0x07C7, 11}, { 0xC833, 16}, +{ 0x0660, 11}, { 0x7934, 15}, { 0x024B, 11}, { 0xC832, 16}, { 0x0AA7, 12}, { 0x1F18, 13}, +{ 0x007A, 7} +}, +{ +{ 0x0002, 2}, { 0x0000, 3}, { 0x001E, 5}, { 0x0004, 5}, { 0x0012, 6}, { 0x0070, 7}, +{ 0x001A, 7}, { 0x005F, 8}, { 0x0047, 8}, { 0x01D3, 9}, { 0x00B5, 9}, { 0x0057, 9}, +{ 0x03B5, 10}, { 0x016D, 10}, { 0x0162, 10}, { 0x07CE, 11}, { 0x0719, 11}, { 0x0691, 11}, +{ 0x02C6, 11}, { 0x0156, 11}, { 0x0F92, 12}, { 0x0D2E, 12}, { 0x0D20, 12}, { 0x059E, 12}, +{ 0x0468, 12}, { 0x02A6, 12}, { 0x1DA2, 13}, { 0x1C60, 13}, { 0x1A43, 13}, { 0x0B1D, 13}, +{ 0x08C0, 13}, { 0x055D, 13}, { 0x0003, 3}, { 0x000A, 5}, { 0x0077, 7}, { 0x00E5, 8}, +{ 0x01D9, 9}, { 0x03E5, 10}, { 0x0166, 10}, { 0x0694, 11}, { 0x0152, 11}, { 0x059F, 12}, +{ 0x1F3C, 13}, { 0x1A4B, 13}, { 0x055E, 13}, { 0x000C, 4}, { 0x007D, 7}, { 0x0044, 8}, +{ 0x03E0, 10}, { 0x0769, 11}, { 0x0E31, 12}, { 0x1F26, 13}, { 0x055C, 13}, { 0x001B, 5}, +{ 0x00E2, 8}, { 0x03A5, 10}, { 0x02C9, 11}, { 0x1F23, 13}, { 0x3B47, 14}, { 0x0007, 5}, +{ 0x01D8, 9}, { 0x02D8, 11}, { 0x1F27, 13}, { 0x3494, 14}, { 0x0035, 6}, { 0x03E1, 10}, +{ 0x059C, 12}, { 0x38C3, 14}, { 0x000C, 6}, { 0x0165, 10}, { 0x1D23, 13}, { 0x1638, 14}, +{ 0x0068, 7}, { 0x0693, 11}, { 0x3A45, 14}, { 0x0020, 7}, { 0x0F90, 12}, { 0x7CF6, 15}, +{ 0x00E8, 8}, { 0x058F, 12}, { 0x2CEF, 15}, { 0x0045, 8}, { 0x0B3A, 13}, { 0x01F1, 9}, +{ 0x3B46, 14}, { 0x01A7, 9}, { 0x1676, 14}, { 0x0056, 9}, { 0x692A, 15}, { 0x038D, 10}, +{ 0xE309, 16}, { 0x00AA, 10}, { 0x1C611, 17}, { 0x02DF, 11}, { 0xB3B9, 17}, { 0x02C8, 11}, +{ 0x38C20, 18}, { 0x01B0, 11}, { 0x16390, 18}, { 0x0F9F, 12}, { 0x16771, 18}, { 0x0ED0, 12}, +{ 0x71843, 19}, { 0x0D2A, 12}, { 0xF9E8C, 20}, { 0x0461, 12}, { 0xF9E8E, 20}, { 0x0B67, 13}, +{ 0x055F, 13}, { 0x003F, 6}, { 0x006D, 9}, { 0x0E90, 12}, { 0x054E, 13}, { 0x0013, 6}, +{ 0x0119, 10}, { 0x0B66, 13}, { 0x000B, 6}, { 0x0235, 11}, { 0x7CF5, 15}, { 0x0075, 7}, +{ 0x0D24, 12}, { 0xF9E9, 16}, { 0x002E, 7}, { 0x1F22, 13}, { 0x0021, 7}, { 0x054F, 13}, +{ 0x0014, 7}, { 0x3A44, 14}, { 0x00E4, 8}, { 0x7CF7, 15}, { 0x005E, 8}, { 0x7185, 15}, +{ 0x0037, 8}, { 0x2C73, 15}, { 0x01DB, 9}, { 0x59DD, 16}, { 0x01C7, 9}, { 0x692B, 15}, +{ 0x01A6, 9}, { 0x58E5, 16}, { 0x00B4, 9}, { 0x1F3D0, 17}, { 0x00B0, 9}, { 0xB1C9, 17}, +{ 0x03E6, 10}, { 0x16770, 18}, { 0x016E, 10}, { 0x3E7A2, 18}, { 0x011B, 10}, { 0xF9E8D, 20}, +{ 0x00D9, 10}, { 0xF9E8F, 20}, { 0x00A8, 10}, { 0x2C723, 19}, { 0x0749, 11}, { 0xE3084, 20}, +{ 0x0696, 11}, { 0x58E45, 20}, { 0x02DE, 11}, { 0xB1C88, 21}, { 0x0231, 11}, { 0x1C610A, 21}, +{ 0x01B1, 11}, { 0x71842D, 23}, { 0x0D2B, 12}, { 0x38C217, 22}, { 0x0D2F, 12}, { 0x163913, 22}, +{ 0x05B2, 12}, { 0x163912, 22}, { 0x0469, 12}, { 0x71842C, 23}, { 0x1A42, 13}, { 0x08C1, 13}, +{ 0x0073, 7} +} +}; + +static const uint16_t vlc_offs[] = { + 0, 520, 552, 616, 1128, 1160, 1224, 1740, 1772, 1836, 1900, 2436, + 2986, 3050, 3610, 4154, 4218, 4746, 5326, 5390, 5902, 6554, 7658, 8342, + 9304, 9988, 10630, 11234, 12174, 13006, 13560, 14232, 14786, 15432, 16350, 17522, + 20372, 21818, 22330, 22394, 23166, 23678, 23742, 24820, 25332, 25396, 26460, 26980, + 27048, 27592, 27600, 27608, 27616, 27624, 28224, 28258, 28290, 28802, 28834, 28866, + 29378, 29412, 29444, 29960, 29994, 30026, 30538, 30572, 30604, 31120, 31154, 31186, + 31714, 31746, 31778, 32306, 32340, 32372 +}; + +/** + * Init VC-1 specific tables and VC1Context members + * @param v The VC1Context to initialize + * @return Status + */ +int ff_vc1_init_common(VC1Context *v) +{ + static int done = 0; + int i = 0; + static VLC_TYPE vlc_table[32372][2]; + + v->hrd_rate = v->hrd_buffer = NULL; + + /* VLC tables */ + if (!done) { + INIT_VLC_STATIC(&ff_vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23, + ff_vc1_bfraction_bits, 1, 1, + ff_vc1_bfraction_codes, 1, 1, 1 << VC1_BFRACTION_VLC_BITS); + INIT_VLC_STATIC(&ff_vc1_norm2_vlc, VC1_NORM2_VLC_BITS, 4, + ff_vc1_norm2_bits, 1, 1, + ff_vc1_norm2_codes, 1, 1, 1 << VC1_NORM2_VLC_BITS); + INIT_VLC_STATIC(&ff_vc1_norm6_vlc, VC1_NORM6_VLC_BITS, 64, + ff_vc1_norm6_bits, 1, 1, + ff_vc1_norm6_codes, 2, 2, 556); + INIT_VLC_STATIC(&ff_vc1_imode_vlc, VC1_IMODE_VLC_BITS, 7, + ff_vc1_imode_bits, 1, 1, + ff_vc1_imode_codes, 1, 1, 1 << VC1_IMODE_VLC_BITS); + for (i = 0; i < 3; i++) { + ff_vc1_ttmb_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 0]]; + ff_vc1_ttmb_vlc[i].table_allocated = vlc_offs[i * 3 + 1] - vlc_offs[i * 3 + 0]; + init_vlc(&ff_vc1_ttmb_vlc[i], VC1_TTMB_VLC_BITS, 16, + ff_vc1_ttmb_bits[i], 1, 1, + ff_vc1_ttmb_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + ff_vc1_ttblk_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 1]]; + ff_vc1_ttblk_vlc[i].table_allocated = vlc_offs[i * 3 + 2] - vlc_offs[i * 3 + 1]; + init_vlc(&ff_vc1_ttblk_vlc[i], VC1_TTBLK_VLC_BITS, 8, + ff_vc1_ttblk_bits[i], 1, 1, + ff_vc1_ttblk_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_vc1_subblkpat_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 2]]; + ff_vc1_subblkpat_vlc[i].table_allocated = vlc_offs[i * 3 + 3] - vlc_offs[i * 3 + 2]; + init_vlc(&ff_vc1_subblkpat_vlc[i], VC1_SUBBLKPAT_VLC_BITS, 15, + ff_vc1_subblkpat_bits[i], 1, 1, + ff_vc1_subblkpat_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + for (i = 0; i < 4; i++) { + ff_vc1_4mv_block_pattern_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 9]]; + ff_vc1_4mv_block_pattern_vlc[i].table_allocated = vlc_offs[i * 3 + 10] - vlc_offs[i * 3 + 9]; + init_vlc(&ff_vc1_4mv_block_pattern_vlc[i], VC1_4MV_BLOCK_PATTERN_VLC_BITS, 16, + ff_vc1_4mv_block_pattern_bits[i], 1, 1, + ff_vc1_4mv_block_pattern_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_vc1_cbpcy_p_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 10]]; + ff_vc1_cbpcy_p_vlc[i].table_allocated = vlc_offs[i * 3 + 11] - vlc_offs[i * 3 + 10]; + init_vlc(&ff_vc1_cbpcy_p_vlc[i], VC1_CBPCY_P_VLC_BITS, 64, + ff_vc1_cbpcy_p_bits[i], 1, 1, + ff_vc1_cbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + ff_vc1_mv_diff_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 11]]; + ff_vc1_mv_diff_vlc[i].table_allocated = vlc_offs[i * 3 + 12] - vlc_offs[i * 3 + 11]; + init_vlc(&ff_vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73, + ff_vc1_mv_diff_bits[i], 1, 1, + ff_vc1_mv_diff_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + for (i = 0; i < 8; i++) { + ff_vc1_ac_coeff_table[i].table = &vlc_table[vlc_offs[i * 2 + 21]]; + ff_vc1_ac_coeff_table[i].table_allocated = vlc_offs[i * 2 + 22] - vlc_offs[i * 2 + 21]; + init_vlc(&ff_vc1_ac_coeff_table[i], AC_VLC_BITS, ff_vc1_ac_sizes[i], + &vc1_ac_tables[i][0][1], 8, 4, + &vc1_ac_tables[i][0][0], 8, 4, INIT_VLC_USE_NEW_STATIC); + /* initialize interlaced MVDATA tables (2-Ref) */ + ff_vc1_2ref_mvdata_vlc[i].table = &vlc_table[vlc_offs[i * 2 + 22]]; + ff_vc1_2ref_mvdata_vlc[i].table_allocated = vlc_offs[i * 2 + 23] - vlc_offs[i * 2 + 22]; + init_vlc(&ff_vc1_2ref_mvdata_vlc[i], VC1_2REF_MVDATA_VLC_BITS, 126, + ff_vc1_2ref_mvdata_bits[i], 1, 1, + ff_vc1_2ref_mvdata_codes[i], 4, 4, INIT_VLC_USE_NEW_STATIC); + } + for (i = 0; i < 4; i++) { + /* initialize 4MV MBMODE VLC tables for interlaced frame P picture */ + ff_vc1_intfr_4mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 37]]; + ff_vc1_intfr_4mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 38] - vlc_offs[i * 3 + 37]; + init_vlc(&ff_vc1_intfr_4mv_mbmode_vlc[i], VC1_INTFR_4MV_MBMODE_VLC_BITS, 15, + ff_vc1_intfr_4mv_mbmode_bits[i], 1, 1, + ff_vc1_intfr_4mv_mbmode_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + /* initialize NON-4MV MBMODE VLC tables for the same */ + ff_vc1_intfr_non4mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 38]]; + ff_vc1_intfr_non4mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 39] - vlc_offs[i * 3 + 38]; + init_vlc(&ff_vc1_intfr_non4mv_mbmode_vlc[i], VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 9, + ff_vc1_intfr_non4mv_mbmode_bits[i], 1, 1, + ff_vc1_intfr_non4mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + /* initialize interlaced MVDATA tables (1-Ref) */ + ff_vc1_1ref_mvdata_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 39]]; + ff_vc1_1ref_mvdata_vlc[i].table_allocated = vlc_offs[i * 3 + 40] - vlc_offs[i * 3 + 39]; + init_vlc(&ff_vc1_1ref_mvdata_vlc[i], VC1_1REF_MVDATA_VLC_BITS, 72, + ff_vc1_1ref_mvdata_bits[i], 1, 1, + ff_vc1_1ref_mvdata_codes[i], 4, 4, INIT_VLC_USE_NEW_STATIC); + } + for (i = 0; i < 4; i++) { + /* Initialize 2MV Block pattern VLC tables */ + ff_vc1_2mv_block_pattern_vlc[i].table = &vlc_table[vlc_offs[i + 49]]; + ff_vc1_2mv_block_pattern_vlc[i].table_allocated = vlc_offs[i + 50] - vlc_offs[i + 49]; + init_vlc(&ff_vc1_2mv_block_pattern_vlc[i], VC1_2MV_BLOCK_PATTERN_VLC_BITS, 4, + ff_vc1_2mv_block_pattern_bits[i], 1, 1, + ff_vc1_2mv_block_pattern_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + for (i = 0; i < 8; i++) { + /* Initialize interlaced CBPCY VLC tables (Table 124 - Table 131) */ + ff_vc1_icbpcy_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 53]]; + ff_vc1_icbpcy_vlc[i].table_allocated = vlc_offs[i * 3 + 54] - vlc_offs[i * 3 + 53]; + init_vlc(&ff_vc1_icbpcy_vlc[i], VC1_ICBPCY_VLC_BITS, 63, + ff_vc1_icbpcy_p_bits[i], 1, 1, + ff_vc1_icbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + /* Initialize interlaced field picture MBMODE VLC tables */ + ff_vc1_if_mmv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 54]]; + ff_vc1_if_mmv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 55] - vlc_offs[i * 3 + 54]; + init_vlc(&ff_vc1_if_mmv_mbmode_vlc[i], VC1_IF_MMV_MBMODE_VLC_BITS, 8, + ff_vc1_if_mmv_mbmode_bits[i], 1, 1, + ff_vc1_if_mmv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_vc1_if_1mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 55]]; + ff_vc1_if_1mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 56] - vlc_offs[i * 3 + 55]; + init_vlc(&ff_vc1_if_1mv_mbmode_vlc[i], VC1_IF_1MV_MBMODE_VLC_BITS, 6, + ff_vc1_if_1mv_mbmode_bits[i], 1, 1, + ff_vc1_if_1mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + done = 1; + } + + /* Other defaults */ + v->pq = -1; + v->mvrange = 0; /* 7.1.1.18, p80 */ + + return 0; +} diff --git a/ffmpeg/libavcodec/vc1.h b/ffmpeg/libavcodec/vc1.h new file mode 100644 index 0000000..596d4d3 --- /dev/null +++ b/ffmpeg/libavcodec/vc1.h @@ -0,0 +1,462 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, 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 + */ + +#ifndef AVCODEC_VC1_H +#define AVCODEC_VC1_H + +#include "avcodec.h" +#include "h264chroma.h" +#include "mpegvideo.h" +#include "intrax8.h" +#include "vc1dsp.h" + +#define AC_VLC_BITS 9 + +/** Markers used in VC-1 AP frame data */ +//@{ +enum VC1Code { + VC1_CODE_RES0 = 0x00000100, + VC1_CODE_ENDOFSEQ = 0x0000010A, + VC1_CODE_SLICE, + VC1_CODE_FIELD, + VC1_CODE_FRAME, + VC1_CODE_ENTRYPOINT, + VC1_CODE_SEQHDR, +}; +//@} + +#define IS_MARKER(x) (((x) & ~0xFF) == VC1_CODE_RES0) + +/** Available Profiles */ +//@{ +enum Profile { + PROFILE_SIMPLE, + PROFILE_MAIN, + PROFILE_COMPLEX, ///< TODO: WMV9 specific + PROFILE_ADVANCED +}; +//@} + +/** Sequence quantizer mode */ +//@{ +enum QuantMode { + QUANT_FRAME_IMPLICIT, ///< Implicitly specified at frame level + QUANT_FRAME_EXPLICIT, ///< Explicitly specified at frame level + QUANT_NON_UNIFORM, ///< Non-uniform quant used for all frames + QUANT_UNIFORM ///< Uniform quant used for all frames +}; +//@} + +/** Where quant can be changed */ +//@{ +enum DQProfile { + DQPROFILE_FOUR_EDGES, + DQPROFILE_DOUBLE_EDGES, + DQPROFILE_SINGLE_EDGE, + DQPROFILE_ALL_MBS +}; +//@} + +/** @name Where quant can be changed + */ +//@{ +enum DQSingleEdge { + DQSINGLE_BEDGE_LEFT, + DQSINGLE_BEDGE_TOP, + DQSINGLE_BEDGE_RIGHT, + DQSINGLE_BEDGE_BOTTOM +}; +//@} + +/** Which pair of edges is quantized with ALTPQUANT */ +//@{ +enum DQDoubleEdge { + DQDOUBLE_BEDGE_TOPLEFT, + DQDOUBLE_BEDGE_TOPRIGHT, + DQDOUBLE_BEDGE_BOTTOMRIGHT, + DQDOUBLE_BEDGE_BOTTOMLEFT +}; +//@} + +/** MV modes for P frames */ +//@{ +enum MVModes { + MV_PMODE_1MV_HPEL_BILIN, + MV_PMODE_1MV, + MV_PMODE_1MV_HPEL, + MV_PMODE_MIXED_MV, + MV_PMODE_INTENSITY_COMP +}; +//@} + +/** MBMODE for interlaced frame P-picture */ +//@{ +enum MBModesIntfr { + MV_PMODE_INTFR_1MV, + MV_PMODE_INTFR_2MV_FIELD, + MV_PMODE_INTFR_2MV, + MV_PMODE_INTFR_4MV_FIELD, + MV_PMODE_INTFR_4MV, + MV_PMODE_INTFR_INTRA, +}; +//@} + +/** @name MV types for B frames */ +//@{ +enum BMVTypes { + BMV_TYPE_BACKWARD, + BMV_TYPE_FORWARD, + BMV_TYPE_INTERPOLATED, + BMV_TYPE_DIRECT +}; +//@} + +/** @name Block types for P/B frames */ +//@{ +enum TransformTypes { + TT_8X8, + TT_8X4_BOTTOM, + TT_8X4_TOP, + TT_8X4, // both halves + TT_4X8_RIGHT, + TT_4X8_LEFT, + TT_4X8, // both halves + TT_4X4 +}; +//@} + +enum CodingSet { + CS_HIGH_MOT_INTRA = 0, + CS_HIGH_MOT_INTER, + CS_LOW_MOT_INTRA, + CS_LOW_MOT_INTER, + CS_MID_RATE_INTRA, + CS_MID_RATE_INTER, + CS_HIGH_RATE_INTRA, + CS_HIGH_RATE_INTER +}; + +/** @name Overlap conditions for Advanced Profile */ +//@{ +enum COTypes { + CONDOVER_NONE = 0, + CONDOVER_ALL, + CONDOVER_SELECT +}; +//@} + +/** + * FCM Frame Coding Mode + * @note some content might be marked interlaced + * but have fcm set to 0 as well (e.g. HD-DVD) + */ +enum FrameCodingMode { + PROGRESSIVE = 0, ///< in the bitstream is reported as 00b + ILACE_FRAME, ///< in the bitstream is reported as 10b + ILACE_FIELD ///< in the bitstream is reported as 11b +}; + +/** The VC1 Context + * @todo Change size wherever another size is more efficient + * Many members are only used for Advanced Profile + */ +typedef struct VC1Context{ + MpegEncContext s; + IntraX8Context x8; + H264ChromaContext h264chroma; + VC1DSPContext vc1dsp; + + int bits; + + /** Simple/Main Profile sequence header */ + //@{ + int res_sprite; ///< reserved, sprite mode + int res_y411; ///< reserved, old interlaced mode + int res_x8; ///< reserved + int multires; ///< frame-level RESPIC syntax element present + int res_fasttx; ///< reserved, always 1 + int res_transtab; ///< reserved, always 0 + int rangered; ///< RANGEREDFRM (range reduction) syntax element present + ///< at frame level + int res_rtm_flag; ///< reserved, set to 1 + int reserved; ///< reserved + //@} + + /** Advanced Profile */ + //@{ + int level; ///< 3bits, for Advanced/Simple Profile, provided by TS layer + int chromaformat; ///< 2bits, 2=4:2:0, only defined + int postprocflag; ///< Per-frame processing suggestion flag present + int broadcast; ///< TFF/RFF present + int interlace; ///< Progressive/interlaced (RPTFTM syntax element) + int tfcntrflag; ///< TFCNTR present + int panscanflag; ///< NUMPANSCANWIN, TOPLEFT{X,Y}, BOTRIGHT{X,Y} present + int refdist_flag; ///< REFDIST syntax element present in II, IP, PI or PP field picture headers + int extended_dmv; ///< Additional extended dmv range at P/B frame-level + int hrd_param_flag; ///< Presence of Hypothetical Reference + ///< Decoder parameters + int psf; ///< Progressive Segmented Frame + //@} + + /** Sequence header data for all Profiles + * TODO: choose between ints, uint8_ts and monobit flags + */ + //@{ + int profile; ///< 2bits, Profile + int frmrtq_postproc; ///< 3bits, + int bitrtq_postproc; ///< 5bits, quantized framerate-based postprocessing strength + int max_coded_width, max_coded_height; + int fastuvmc; ///< Rounding of qpel vector to hpel ? (not in Simple) + int extended_mv; ///< Ext MV in P/B (not in Simple) + int dquant; ///< How qscale varies with MBs, 2bits (not in Simple) + int vstransform; ///< variable-size [48]x[48] transform type + info + int overlap; ///< overlapped transforms in use + int quantizer_mode; ///< 2bits, quantizer mode used for sequence, see QUANT_* + int finterpflag; ///< INTERPFRM present + //@} + + /** Frame decoding info for all profiles */ + //@{ + uint8_t mv_mode; ///< MV coding monde + uint8_t mv_mode2; ///< Secondary MV coding mode (B frames) + int k_x; ///< Number of bits for MVs (depends on MV range) + int k_y; ///< Number of bits for MVs (depends on MV range) + int range_x, range_y; ///< MV range + uint8_t pq, altpq; ///< Current/alternate frame quantizer scale + uint8_t zz_8x8[4][64]; ///< Zigzag table for TT_8x8, permuted for IDCT + int left_blk_sh, top_blk_sh; ///< Either 3 or 0, positions of l/t in blk[] + const uint8_t* zz_8x4; ///< Zigzag scan table for TT_8x4 coding mode + const uint8_t* zz_4x8; ///< Zigzag scan table for TT_4x8 coding mode + /** pquant parameters */ + //@{ + uint8_t dquantfrm; + uint8_t dqprofile; + uint8_t dqsbedge; + uint8_t dqbilevel; + //@} + /** AC coding set indexes + * @see 8.1.1.10, p(1)10 + */ + //@{ + int c_ac_table_index; ///< Chroma index from ACFRM element + int y_ac_table_index; ///< Luma index from AC2FRM element + //@} + int ttfrm; ///< Transform type info present at frame level + uint8_t ttmbf; ///< Transform type flag + int *ttblk_base, *ttblk; ///< Transform type at the block level + int codingset; ///< index of current table set from 11.8 to use for luma block decoding + int codingset2; ///< index of current table set from 11.8 to use for chroma block decoding + int pqindex; ///< raw pqindex used in coding set selection + int a_avail, c_avail; + uint8_t *mb_type_base, *mb_type[3]; + + + /** Luma compensation parameters */ + //@{ + uint8_t lumscale; + uint8_t lumshift; + //@} + int16_t bfraction; ///< Relative position % anchors=> how to scale MVs + uint8_t halfpq; ///< Uniform quant over image and qp+.5 + uint8_t respic; ///< Frame-level flag for resized images + int buffer_fullness; ///< HRD info + /** Ranges: + * -# 0 -> [-64n 63.f] x [-32, 31.f] + * -# 1 -> [-128, 127.f] x [-64, 63.f] + * -# 2 -> [-512, 511.f] x [-128, 127.f] + * -# 3 -> [-1024, 1023.f] x [-256, 255.f] + */ + uint8_t mvrange; ///< Extended MV range flag + uint8_t pquantizer; ///< Uniform (over sequence) quantizer in use + VLC *cbpcy_vlc; ///< CBPCY VLC table + int tt_index; ///< Index for Transform Type tables (to decode TTMB) + uint8_t* mv_type_mb_plane; ///< bitplane for mv_type == (4MV) + uint8_t* direct_mb_plane; ///< bitplane for "direct" MBs + uint8_t* forward_mb_plane; ///< bitplane for "forward" MBs + int mv_type_is_raw; ///< mv type mb plane is not coded + int dmb_is_raw; ///< direct mb plane is raw + int fmb_is_raw; ///< forward mb plane is raw + int skip_is_raw; ///< skip mb plane is not coded + uint8_t luty[256], lutuv[256]; ///< lookup tables used for intensity compensation + int use_ic; ///< use intensity compensation in B-frames + int rnd; ///< rounding control + + /** Frame decoding info for S/M profiles only */ + //@{ + uint8_t rangeredfrm; ///< out_sample = CLIP((in_sample-128)*2+128) + uint8_t interpfrm; + //@} + + /** Frame decoding info for Advanced profile */ + //@{ + enum FrameCodingMode fcm; + uint8_t numpanscanwin; + uint8_t tfcntr; + uint8_t rptfrm, tff, rff; + uint16_t topleftx; + uint16_t toplefty; + uint16_t bottomrightx; + uint16_t bottomrighty; + uint8_t uvsamp; + uint8_t postproc; + int hrd_num_leaky_buckets; + uint8_t bit_rate_exponent; + uint8_t buffer_size_exponent; + uint8_t* acpred_plane; ///< AC prediction flags bitplane + int acpred_is_raw; + uint8_t* over_flags_plane; ///< Overflags bitplane + int overflg_is_raw; + uint8_t condover; + uint16_t *hrd_rate, *hrd_buffer; + uint8_t *hrd_fullness; + uint8_t range_mapy_flag; + uint8_t range_mapuv_flag; + uint8_t range_mapy; + uint8_t range_mapuv; + //@} + + /** Frame decoding info for interlaced picture */ + uint8_t dmvrange; ///< Extended differential MV range flag + int fourmvswitch; + int intcomp; + uint8_t lumscale2; ///< for interlaced field P picture + uint8_t lumshift2; + uint8_t luty2[256], lutuv2[256]; // lookup tables used for intensity compensation + VLC* mbmode_vlc; + VLC* imv_vlc; + VLC* twomvbp_vlc; + VLC* fourmvbp_vlc; + uint8_t twomvbp; + uint8_t fourmvbp; + uint8_t* fieldtx_plane; + int fieldtx_is_raw; + uint8_t zzi_8x8[64]; + uint8_t *blk_mv_type_base, *blk_mv_type; ///< 0: frame MV, 1: field MV (interlaced frame) + uint8_t *mv_f_base, *mv_f[2]; ///< 0: MV obtained from same field, 1: opposite field + uint8_t *mv_f_last_base, *mv_f_last[2]; + uint8_t *mv_f_next_base, *mv_f_next[2]; + int field_mode; ///< 1 for interlaced field pictures + int fptype; + int second_field; + int refdist; ///< distance of the current picture from reference + int numref; ///< number of past field pictures used as reference + // 0 corresponds to 1 and 1 corresponds to 2 references + int reffield; ///< if numref = 0 (1 reference) then reffield decides which + // field to use among the two fields from previous frame + int intcompfield; ///< which of the two fields to be intensity compensated + // 0: both fields, 1: bottom field, 2: top field + int cur_field_type; ///< 0: top, 1: bottom + int ref_field_type[2]; ///< forward and backward reference field type (top or bottom) + int blocks_off, mb_off; + int qs_last; ///< if qpel has been used in the previous (tr.) picture + int bmvtype; + int frfd, brfd; ///< reference frame distance (forward or backward) + int first_pic_header_flag; + int pic_header_flag; + + /** Frame decoding info for sprite modes */ + //@{ + int new_sprite; + int two_sprites; + AVFrame sprite_output_frame; + int output_width, output_height, sprite_width, sprite_height; + uint8_t* sr_rows[2][2]; ///< Sprite resizer line cache + //@} + + int p_frame_skipped; + int bi_type; + int x8_type; + + int16_t (*block)[6][64]; + int n_allocated_blks, cur_blk_idx, left_blk_idx, topleft_blk_idx, top_blk_idx; + uint32_t *cbp_base, *cbp; + uint8_t *is_intra_base, *is_intra; + int16_t (*luma_mv_base)[2], (*luma_mv)[2]; + uint8_t bfraction_lut_index; ///< Index for BFRACTION value (see Table 40, reproduced into ff_vc1_bfraction_lut[]) + uint8_t broken_link; ///< Broken link flag (BROKEN_LINK syntax element) + uint8_t closed_entry; ///< Closed entry point flag (CLOSED_ENTRY syntax element) + + int end_mb_x; ///< Horizontal macroblock limit (used only by mss2) + + int parse_only; ///< Context is used within parser + + int warn_interlaced; +} VC1Context; + +/** Find VC-1 marker in buffer + * @return position where next marker starts or end of buffer if no marker found + */ +static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end) +{ + uint32_t mrk = 0xFFFFFFFF; + + if (end-src < 4) + return end; + while (src < end) { + mrk = (mrk << 8) | *src++; + if (IS_MARKER(mrk)) + return src - 4; + } + return end; +} + +static av_always_inline int vc1_unescape_buffer(const uint8_t *src, int size, uint8_t *dst) +{ + int dsize = 0, i; + + if (size < 4) { + for (dsize = 0; dsize < size; dsize++) + *dst++ = *src++; + return size; + } + for (i = 0; i < size; i++, src++) { + if (src[0] == 3 && i >= 2 && !src[-1] && !src[-2] && i < size-1 && src[1] < 4) { + dst[dsize++] = src[1]; + src++; + i++; + } else + dst[dsize++] = *src; + } + return dsize; +} + +/** + * Decode Simple/Main Profiles sequence header + * @see Figure 7-8, p16-17 + * @param avctx Codec context + * @param gb GetBit context initialized from Codec context extra_data + * @return Status + */ +int ff_vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitContext *gb); + +int ff_vc1_decode_entry_point(AVCodecContext *avctx, VC1Context *v, GetBitContext *gb); + +int ff_vc1_parse_frame_header (VC1Context *v, GetBitContext *gb); +int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext *gb); +int ff_vc1_init_common(VC1Context *v); + +int ff_vc1_decode_init_alloc_tables(VC1Context *v); +void ff_vc1_init_transposed_scantables(VC1Context *v); +int ff_vc1_decode_end(AVCodecContext *avctx); +void ff_vc1_decode_blocks(VC1Context *v); + +#endif /* AVCODEC_VC1_H */ diff --git a/ffmpeg/libavcodec/vc1_parser.c b/ffmpeg/libavcodec/vc1_parser.c new file mode 100644 index 0000000..53af61c --- /dev/null +++ b/ffmpeg/libavcodec/vc1_parser.c @@ -0,0 +1,201 @@ +/* + * VC-1 and WMV3 parser + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, 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 + */ + +/** + * @file + * VC-1 and WMV3 parser + */ + +#include "parser.h" +#include "vc1.h" +#include "get_bits.h" + +typedef struct { + ParseContext pc; + VC1Context v; +} VC1ParseContext; + +static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + VC1ParseContext *vpc = s->priv_data; + GetBitContext gb; + const uint8_t *start, *end, *next; + uint8_t *buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + + vpc->v.s.avctx = avctx; + vpc->v.parse_only = 1; + next = buf; + s->repeat_pict = 0; + + for(start = buf, end = buf + buf_size; next < end; start = next){ + int buf2_size, size; + + next = find_next_marker(start + 4, end); + size = next - start - 4; + buf2_size = vc1_unescape_buffer(start + 4, size, buf2); + init_get_bits(&gb, buf2, buf2_size * 8); + if(size <= 0) continue; + switch(AV_RB32(start)){ + case VC1_CODE_SEQHDR: + ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb); + break; + case VC1_CODE_ENTRYPOINT: + ff_vc1_decode_entry_point(avctx, &vpc->v, &gb); + break; + case VC1_CODE_FRAME: + if(vpc->v.profile < PROFILE_ADVANCED) + ff_vc1_parse_frame_header (&vpc->v, &gb); + else + ff_vc1_parse_frame_header_adv(&vpc->v, &gb); + + /* keep AV_PICTURE_TYPE_BI internal to VC1 */ + if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI) + s->pict_type = AV_PICTURE_TYPE_B; + else + s->pict_type = vpc->v.s.pict_type; + + if (avctx->ticks_per_frame > 1){ + // process pulldown flags + s->repeat_pict = 1; + // Pulldown flags are only valid when 'broadcast' has been set. + // So ticks_per_frame will be 2 + if (vpc->v.rff){ + // repeat field + s->repeat_pict = 2; + }else if (vpc->v.rptfrm){ + // repeat frames + s->repeat_pict = vpc->v.rptfrm * 2 + 1; + } + } + + break; + } + } + + av_free(buf2); +} + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf, + int buf_size) { + int pic_found, i; + uint32_t state; + + pic_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!pic_found){ + for(i=0; iframe_start_found=0; + pc->state=-1; + return i-3; + } + } + } + pc->frame_start_found= pic_found; + pc->state= state; + return END_NOT_FOUND; +} + +static int vc1_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + VC1ParseContext *vpc = s->priv_data; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= vc1_find_frame_end(&vpc->pc, buf, buf_size); + + if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + vc1_extract_headers(s, avctx, buf, buf_size); + + *poutbuf = buf; + *poutbuf_size = buf_size; + return next; +} + +static int vc1_split(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + int i; + uint32_t state= -1; + int charged=0; + + for(i=0; ipriv_data; + vpc->v.s.slice_context_count = 1; + return ff_vc1_init_common(&vpc->v); +} + +AVCodecParser ff_vc1_parser = { + .codec_ids = { AV_CODEC_ID_VC1 }, + .priv_data_size = sizeof(VC1ParseContext), + .parser_init = vc1_parse_init, + .parser_parse = vc1_parse, + .parser_close = ff_parse_close, + .split = vc1_split, +}; diff --git a/ffmpeg/libavcodec/vc1acdata.h b/ffmpeg/libavcodec/vc1acdata.h new file mode 100644 index 0000000..a70b44a --- /dev/null +++ b/ffmpeg/libavcodec/vc1acdata.h @@ -0,0 +1,367 @@ +/* + * VC-1 and WMV3 decoder + * copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +#ifndef AVCODEC_VC1ACDATA_H +#define AVCODEC_VC1ACDATA_H + +#include + +#include "vc1data.h" + +/* which indexes point to last=1 entries in tables */ +static const int vc1_last_decode_table[AC_MODES] = { + 119, 99, 85, 81, 67, 58, 126, 109 +}; + +static const uint8_t vc1_index_decode_table[AC_MODES][185][2] = { +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 0, 15}, { 0, 16}, +{ 0, 17}, { 0, 18}, { 0, 19}, { 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, { 1, 5}, +{ 1, 6}, { 1, 7}, { 1, 8}, { 1, 9}, { 1, 10}, { 1, 11}, { 1, 12}, { 1, 13}, +{ 1, 14}, { 1, 15}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, { 2, 5}, { 2, 6}, +{ 2, 7}, { 2, 8}, { 2, 9}, { 2, 10}, { 2, 11}, { 2, 12}, { 3, 1}, { 3, 2}, +{ 3, 3}, { 3, 4}, { 3, 5}, { 3, 6}, { 3, 7}, { 3, 8}, { 3, 9}, { 3, 10}, +{ 3, 11}, { 4, 1}, { 4, 2}, { 4, 3}, { 4, 4}, { 4, 5}, { 4, 6}, { 5, 1}, +{ 5, 2}, { 5, 3}, { 5, 4}, { 5, 5}, { 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, +{ 7, 1}, { 7, 2}, { 7, 3}, { 7, 4}, { 8, 1}, { 8, 2}, { 8, 3}, { 8, 4}, +{ 9, 1}, { 9, 2}, { 9, 3}, { 9, 4}, { 10, 1}, { 10, 2}, { 10, 3}, { 11, 1}, +{ 11, 2}, { 11, 3}, { 12, 1}, { 12, 2}, { 12, 3}, { 13, 1}, { 13, 2}, { 13, 3}, +{ 14, 1}, { 14, 2}, { 14, 3}, { 15, 1}, { 15, 2}, { 15, 3}, { 16, 1}, { 16, 2}, +{ 17, 1}, { 17, 2}, { 18, 1}, { 19, 1}, { 20, 1}, { 21, 1}, { 22, 1}, { 23, 1}, +{ 24, 1}, { 25, 1}, { 26, 1}, { 27, 1}, { 28, 1}, { 29, 1}, { 30, 1}, { 0, 1}, +{ 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 1, 1}, { 1, 2}, { 1, 3}, +{ 1, 4}, { 1, 5}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, { 3, 1}, { 3, 2}, +{ 3, 3}, { 3, 4}, { 4, 1}, { 4, 2}, { 4, 3}, { 5, 1}, { 5, 2}, { 6, 1}, +{ 6, 2}, { 7, 1}, { 7, 2}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, { 10, 1}, +{ 10, 2}, { 11, 1}, { 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, +{ 14, 2}, { 15, 1}, { 15, 2}, { 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, +{ 21, 1}, { 22, 1}, { 23, 1}, { 24, 1}, { 25, 1}, { 26, 1}, { 27, 1}, { 28, 1}, +{ 29, 1}, { 30, 1}, { 31, 1}, { 32, 1}, { 33, 1}, { 34, 1}, { 35, 1}, { 36, 1}, +{ 37, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 0, 15}, { 0, 16}, +{ 0, 17}, { 0, 18}, { 0, 19}, { 0, 20}, { 0, 21}, { 0, 22}, { 0, 23}, { 1, 1}, +{ 1, 2}, { 1, 3}, { 1, 4}, { 1, 5}, { 1, 6}, { 1, 7}, { 1, 8}, { 1, 9}, +{ 1, 10}, { 1, 11}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, { 2, 5}, { 2, 6}, +{ 2, 7}, { 2, 8}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4}, { 3, 5}, { 3, 6}, +{ 3, 7}, { 4, 1}, { 4, 2}, { 4, 3}, { 4, 4}, { 4, 5}, { 5, 1}, { 5, 2}, +{ 5, 3}, { 5, 4}, { 5, 5}, { 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, { 7, 1}, +{ 7, 2}, { 7, 3}, { 7, 4}, { 8, 1}, { 8, 2}, { 8, 3}, { 9, 1}, { 9, 2}, +{ 9, 3}, { 10, 1}, { 10, 2}, { 10, 3}, { 11, 1}, { 11, 2}, { 11, 3}, { 12, 1}, +{ 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, { 14, 2}, { 15, 1}, { 15, 2}, { 16, 1}, +{ 16, 2}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, { 21, 1}, { 22, 1}, { 23, 1}, +{ 24, 1}, { 25, 1}, { 26, 1}, { 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, +{ 0, 6}, { 0, 7}, { 0, 8}, { 0, 9}, { 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, +{ 1, 5}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, { 3, 1}, { 3, 2}, { 3, 3}, +{ 3, 4}, { 4, 1}, { 4, 2}, { 4, 3}, { 5, 1}, { 5, 2}, { 5, 3}, { 6, 1}, +{ 6, 2}, { 6, 3}, { 7, 1}, { 7, 2}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, +{ 10, 1}, { 10, 2}, { 11, 1}, { 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, +{ 14, 1}, { 14, 2}, { 15, 1}, { 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, +{ 21, 1}, { 22, 1}, { 23, 1}, { 24, 1}, { 25, 1}, { 26, 1}, { 27, 1}, { 28, 1}, +{ 29, 1}, { 30, 1}, { 31, 1}, { 32, 1}, { 33, 1}, { 34, 1}, { 35, 1}, { 36, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 0, 15}, { 0, 16}, +{ 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, { 1, 5}, { 1, 6}, { 1, 7}, { 1, 8}, +{ 1, 9}, { 1, 10}, { 1, 11}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, { 2, 5}, +{ 2, 6}, { 2, 7}, { 2, 8}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4}, { 3, 5}, +{ 3, 6}, { 3, 7}, { 4, 1}, { 4, 2}, { 4, 3}, { 4, 4}, { 4, 5}, { 5, 1}, +{ 5, 2}, { 5, 3}, { 5, 4}, { 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, { 7, 1}, +{ 7, 2}, { 7, 3}, { 8, 1}, { 8, 2}, { 8, 3}, { 9, 1}, { 9, 2}, { 9, 3}, +{ 10, 1}, { 10, 2}, { 10, 3}, { 11, 1}, { 11, 2}, { 11, 3}, { 12, 1}, { 12, 2}, +{ 12, 3}, { 13, 1}, { 13, 2}, { 13, 3}, { 14, 1}, { 14, 2}, { 15, 1}, { 15, 2}, +{ 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, { 0, 1}, { 0, 2}, { 0, 3}, +{ 0, 4}, { 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, { 2, 1}, { 2, 2}, { 2, 3}, +{ 3, 1}, { 3, 2}, { 3, 3}, { 4, 1}, { 4, 2}, { 5, 1}, { 5, 2}, { 6, 1}, +{ 6, 2}, { 7, 1}, { 7, 2}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, { 10, 1}, +{ 10, 2}, { 11, 1}, { 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, +{ 15, 1}, { 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, { 21, 1}, { 22, 1}, +{ 23, 1}, { 24, 1}, { 25, 1}, { 26, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 1, 1}, { 1, 2}, +{ 1, 3}, { 1, 4}, { 1, 5}, { 1, 6}, { 1, 7}, { 1, 8}, { 1, 9}, { 2, 1}, +{ 2, 2}, { 2, 3}, { 2, 4}, { 2, 5}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4}, +{ 4, 1}, { 4, 2}, { 4, 3}, { 4, 4}, { 5, 1}, { 5, 2}, { 5, 3}, { 5, 4}, +{ 6, 1}, { 6, 2}, { 6, 3}, { 7, 1}, { 7, 2}, { 7, 3}, { 8, 1}, { 8, 2}, +{ 8, 3}, { 9, 1}, { 9, 2}, { 9, 3}, { 10, 1}, { 10, 2}, { 10, 3}, { 11, 1}, +{ 11, 2}, { 11, 3}, { 12, 1}, { 12, 2}, { 12, 3}, { 13, 1}, { 13, 2}, { 14, 1}, +{ 14, 2}, { 15, 1}, { 15, 2}, { 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, +{ 21, 1}, { 22, 1}, { 23, 1}, { 24, 1}, { 25, 1}, { 26, 1}, { 27, 1}, { 28, 1}, +{ 29, 1}, { 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 1, 1}, { 1, 2}, +{ 1, 3}, { 1, 4}, { 2, 1}, { 2, 2}, { 2, 3}, { 3, 1}, { 3, 2}, { 3, 3}, +{ 4, 1}, { 4, 2}, { 5, 1}, { 5, 2}, { 6, 1}, { 6, 2}, { 7, 1}, { 7, 2}, +{ 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, { 10, 1}, { 10, 2}, { 11, 1}, { 11, 2}, +{ 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, { 14, 2}, { 15, 1}, { 15, 2}, +{ 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, { 21, 1}, { 22, 1}, { 23, 1}, +{ 24, 1}, { 25, 1}, { 26, 1}, { 27, 1}, { 28, 1}, { 29, 1}, { 30, 1}, { 31, 1}, +{ 32, 1}, { 33, 1}, { 34, 1}, { 35, 1}, { 36, 1}, { 37, 1}, { 38, 1}, { 39, 1}, +{ 40, 1}, { 41, 1}, { 42, 1}, { 43, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 0, 15}, { 0, 16}, +{ 0, 17}, { 0, 18}, { 0, 19}, { 0, 20}, { 0, 21}, { 0, 22}, { 0, 23}, { 0, 24}, +{ 0, 25}, { 0, 26}, { 0, 27}, { 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, { 1, 5}, +{ 1, 6}, { 1, 7}, { 1, 8}, { 1, 9}, { 1, 10}, { 2, 1}, { 2, 2}, { 2, 3}, +{ 2, 4}, { 2, 5}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4}, { 4, 1}, { 4, 2}, +{ 4, 3}, { 5, 1}, { 5, 2}, { 5, 3}, { 6, 1}, { 6, 2}, { 6, 3}, { 7, 1}, +{ 7, 2}, { 7, 3}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, { 10, 1}, { 11, 1}, +{ 12, 1}, { 13, 1}, { 14, 1}, { 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, +{ 0, 6}, { 0, 7}, { 0, 8}, { 1, 1}, { 1, 2}, { 1, 3}, { 2, 1}, { 2, 2}, +{ 3, 1}, { 3, 2}, { 4, 1}, { 4, 2}, { 5, 1}, { 5, 2}, { 6, 1}, { 6, 2}, +{ 7, 1}, { 8, 1}, { 9, 1}, { 10, 1}, { 11, 1}, { 12, 1}, { 13, 1}, { 14, 1}, +{ 15, 1}, { 16, 1}, { 17, 1}, { 18, 1}, { 19, 1}, { 20, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, +{ 1, 5}, { 1, 6}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, { 3, 1}, { 3, 2}, +{ 3, 3}, { 4, 1}, { 4, 2}, { 4, 3}, { 5, 1}, { 5, 2}, { 5, 3}, { 6, 1}, +{ 6, 2}, { 6, 3}, { 7, 1}, { 7, 2}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, +{ 10, 1}, { 10, 2}, { 11, 1}, { 12, 1}, { 13, 1}, { 14, 1}, { 15, 1}, { 16, 1}, +{ 17, 1}, { 18, 1}, { 19, 1}, { 20, 1}, { 21, 1}, { 22, 1}, { 23, 1}, { 24, 1}, +{ 25, 1}, { 26, 1}, { 0, 1}, { 0, 2}, { 0, 3}, { 1, 1}, { 1, 2}, { 2, 1}, +{ 3, 1}, { 4, 1}, { 5, 1}, { 6, 1}, { 7, 1}, { 8, 1}, { 9, 1}, { 10, 1}, +{ 11, 1}, { 12, 1}, { 13, 1}, { 14, 1}, { 15, 1}, { 16, 1}, { 17, 1}, { 18, 1}, +{ 19, 1}, { 20, 1}, { 21, 1}, { 22, 1}, { 23, 1}, { 24, 1}, { 25, 1}, { 26, 1}, +{ 27, 1}, { 28, 1}, { 29, 1}, { 30, 1}, { 31, 1}, { 32, 1}, { 33, 1}, { 34, 1}, +{ 35, 1}, { 36, 1}, { 37, 1}, { 38, 1}, { 39, 1}, { 40, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 0, 15}, { 0, 16}, +{ 0, 17}, { 0, 18}, { 0, 19}, { 0, 20}, { 0, 21}, { 0, 22}, { 0, 23}, { 0, 24}, +{ 0, 25}, { 0, 26}, { 0, 27}, { 0, 28}, { 0, 29}, { 0, 30}, { 0, 31}, { 0, 32}, +{ 0, 33}, { 0, 34}, { 0, 35}, { 0, 36}, { 0, 37}, { 0, 38}, { 0, 39}, { 0, 40}, +{ 0, 41}, { 0, 42}, { 0, 43}, { 0, 44}, { 0, 45}, { 0, 46}, { 0, 47}, { 0, 48}, +{ 0, 49}, { 0, 50}, { 0, 51}, { 0, 52}, { 0, 53}, { 0, 54}, { 0, 55}, { 0, 56}, +{ 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, { 1, 5}, { 1, 6}, { 1, 7}, { 1, 8}, +{ 1, 9}, { 1, 10}, { 1, 11}, { 1, 12}, { 1, 13}, { 1, 14}, { 1, 15}, { 1, 16}, +{ 1, 17}, { 1, 18}, { 1, 19}, { 1, 20}, { 2, 1}, { 2, 2}, { 2, 3}, { 2, 4}, +{ 2, 5}, { 2, 6}, { 2, 7}, { 2, 8}, { 2, 9}, { 2, 10}, { 3, 1}, { 3, 2}, +{ 3, 3}, { 3, 4}, { 3, 5}, { 3, 6}, { 3, 7}, { 4, 1}, { 4, 2}, { 4, 3}, +{ 4, 4}, { 4, 5}, { 4, 6}, { 5, 1}, { 5, 2}, { 5, 3}, { 5, 4}, { 5, 5}, +{ 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, { 7, 1}, { 7, 2}, { 7, 3}, { 8, 1}, +{ 8, 2}, { 8, 3}, { 9, 1}, { 9, 2}, { 9, 3}, { 10, 1}, { 10, 2}, { 11, 1}, +{ 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, { 0, 1}, { 0, 2}, +{ 0, 3}, { 0, 4}, { 1, 1}, { 1, 2}, { 1, 3}, { 2, 1}, { 2, 2}, { 2, 3}, +{ 3, 1}, { 3, 2}, { 4, 1}, { 4, 2}, { 5, 1}, { 5, 2}, { 6, 1}, { 6, 2}, +{ 7, 1}, { 7, 2}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, { 10, 1}, { 10, 2}, +{ 11, 1}, { 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, { 14, 2}, +{ 15, 1}, { 16, 1} +}, +{ +{ 0, 1}, { 0, 2}, { 0, 3}, { 0, 4}, { 0, 5}, { 0, 6}, { 0, 7}, { 0, 8}, +{ 0, 9}, { 0, 10}, { 0, 11}, { 0, 12}, { 0, 13}, { 0, 14}, { 0, 15}, { 0, 16}, +{ 0, 17}, { 0, 18}, { 0, 19}, { 0, 20}, { 0, 21}, { 0, 22}, { 0, 23}, { 0, 24}, +{ 0, 25}, { 0, 26}, { 0, 27}, { 0, 28}, { 0, 29}, { 0, 30}, { 0, 31}, { 0, 32}, +{ 1, 1}, { 1, 2}, { 1, 3}, { 1, 4}, { 1, 5}, { 1, 6}, { 1, 7}, { 1, 8}, +{ 1, 9}, { 1, 10}, { 1, 11}, { 1, 12}, { 1, 13}, { 2, 1}, { 2, 2}, { 2, 3}, +{ 2, 4}, { 2, 5}, { 2, 6}, { 2, 7}, { 2, 8}, { 3, 1}, { 3, 2}, { 3, 3}, +{ 3, 4}, { 3, 5}, { 3, 6}, { 4, 1}, { 4, 2}, { 4, 3}, { 4, 4}, { 4, 5}, +{ 5, 1}, { 5, 2}, { 5, 3}, { 5, 4}, { 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, +{ 7, 1}, { 7, 2}, { 7, 3}, { 8, 1}, { 8, 2}, { 8, 3}, { 9, 1}, { 9, 2}, +{ 9, 3}, { 10, 1}, { 10, 2}, { 11, 1}, { 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, +{ 13, 2}, { 14, 1}, { 14, 2}, { 15, 1}, { 15, 2}, { 16, 1}, { 16, 2}, { 17, 1}, +{ 17, 2}, { 18, 1}, { 18, 2}, { 19, 1}, { 19, 2}, { 20, 1}, { 20, 2}, { 21, 1}, +{ 21, 2}, { 22, 1}, { 22, 2}, { 23, 1}, { 24, 1}, { 0, 1}, { 0, 2}, { 0, 3}, +{ 0, 4}, { 1, 1}, { 1, 2}, { 1, 3}, { 2, 1}, { 2, 2}, { 2, 3}, { 3, 1}, +{ 3, 2}, { 3, 3}, { 4, 1}, { 4, 2}, { 5, 1}, { 5, 2}, { 6, 1}, { 6, 2}, +{ 7, 1}, { 7, 2}, { 8, 1}, { 8, 2}, { 9, 1}, { 9, 2}, { 10, 1}, { 10, 2}, +{ 11, 1}, { 11, 2}, { 12, 1}, { 12, 2}, { 13, 1}, { 13, 2}, { 14, 1}, { 14, 2}, +{ 15, 1}, { 15, 2}, { 16, 1}, { 16, 2}, { 17, 1}, { 17, 2}, { 18, 1}, { 18, 2}, +{ 19, 1}, { 19, 2}, { 20, 1}, { 20, 2}, { 21, 1}, { 21, 2}, { 22, 1}, { 22, 2}, +{ 23, 1}, { 23, 2}, { 24, 1}, { 24, 2}, { 25, 1}, { 25, 2}, { 26, 1}, { 26, 2}, +{ 27, 1}, { 27, 2}, { 28, 1}, { 28, 2}, { 29, 1}, { 30, 1} +} +}; + +static const uint8_t vc1_delta_level_table[AC_MODES][31] = { +{ + 19, 15, 12, 11, 6, 5, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 +}, +{ + 23, 11, 8, 7, 5, 5, 4, 4, 3, 3, + 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 +}, +{ + 16, 11, 8, 7, 5, 4, 4, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, + 1 +}, +{ + 14, 9, 5, 4, 4, 4, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 +}, +{ + 27, 10, 5, 4, 3, 3, 3, 3, 2, 2, + 1, 1, 1, 1, 1 +}, +{ + 12, 6, 4, 3, 3, 3, 3, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 +}, +{ + 56, 20, 10, 7, 6, 5, 4, 3, 3, 3, + 2, 2, 2, 2, 1 +}, +{ + 32, 13, 8, 6, 5, 4, 4, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 1 +} +}; + +static const uint8_t vc1_last_delta_level_table[AC_MODES][44] = { +{ + 6, 5, 4, 4, 3, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 +}, +{ + 9, 5, 4, 4, 3, 3, 3, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 +}, +{ + 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 +}, +{ + 5, 4, 3, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1 +}, +{ + 8, 3, 2, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 +}, +{ + 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 +}, +{ + 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1 +}, +{ + 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1 +} +}; + +static const uint8_t vc1_delta_run_table[AC_MODES][57] = { +{ + -1, 30, 17, 15, 9, 5, 4, 3, 3, 3, + 3, 3, 2, 1, 1, 1, 0, 0, 0, + 0 +}, +{ + -1, 26, 16, 11, 7, 5, 3, 3, 2, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}, +{ + -1, 20, 15, 13, 6, 4, 3, 3, 2, 1, + 1, 1, 0, 0, 0, 0, 0 +}, +{ + -1, 29, 15, 12, 5, 2, 1, 1, 1, 1, + 0, 0, 0, 0, 0 +}, +{ + -1, 14, 9, 7, 3, 2, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}, +{ + -1, 26, 10, 6, 2, 1, 1, 0, 0, 0, + 0, 0, 0 +}, +{ + -1, 14, 13, 9, 6, 5, 4, 3, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 +}, +{ + -1, 24, 22, 9, 6, 4, 3, 2, 2, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 +} +}; + +static const uint8_t vc1_last_delta_run_table[AC_MODES][10] = { +{ + -1, 37, 15, 4, 3, 1, 0 +}, +{ + -1, 36, 14, 6, 3, 1, 0, 0, 0, + 0 +}, +{ + -1, 26, 13, 3, 1 +}, +{ + -1, 43, 15, 3, 1, 0 +}, +{ + -1, 20, 6, 1, 0, 0, 0, 0, 0 +}, +{ + -1, 40, 1, 0 +}, +{ + -1, 16, 14, 2, 0 +}, +{ + -1, 30, 28, 3, 0 +} +}; + +#endif /* AVCODEC_VC1ACDATA_H */ diff --git a/ffmpeg/libavcodec/vc1data.c b/ffmpeg/libavcodec/vc1data.c new file mode 100644 index 0000000..fc9ba6d --- /dev/null +++ b/ffmpeg/libavcodec/vc1data.c @@ -0,0 +1,1135 @@ +/* + * VC-1 and WMV3 decoder + * copyright (c) 2011 Mashiat Sarker Shakkhar + * copyright (c) 2006 Konstantin Shishkov + * (c) 2005 anonymous, Alex Beregszaszi, 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 + */ + +/** + * @file + * VC-1 tables. + */ + +#include "avcodec.h" +#include "vc1.h" +#include "vc1data.h" + +/** Table for conversion between TTBLK and TTMB */ +const int ff_vc1_ttblk_to_tt[3][8] = { + { TT_8X4, TT_4X8, TT_8X8, TT_4X4, TT_8X4_TOP, TT_8X4_BOTTOM, TT_4X8_RIGHT, TT_4X8_LEFT }, + { TT_8X8, TT_4X8_RIGHT, TT_4X8_LEFT, TT_4X4, TT_8X4, TT_4X8, TT_8X4_BOTTOM, TT_8X4_TOP }, + { TT_8X8, TT_4X8, TT_4X4, TT_8X4_BOTTOM, TT_4X8_RIGHT, TT_4X8_LEFT, TT_8X4, TT_8X4_TOP } +}; + +const int ff_vc1_ttfrm_to_tt[4] = { TT_8X8, TT_8X4, TT_4X8, TT_4X4 }; + +/** MV P mode - the 5th element is only used for mode 1 */ +const uint8_t ff_vc1_mv_pmode_table[2][5] = { + { MV_PMODE_1MV_HPEL_BILIN, MV_PMODE_1MV, MV_PMODE_1MV_HPEL, MV_PMODE_INTENSITY_COMP, MV_PMODE_MIXED_MV }, + { MV_PMODE_1MV, MV_PMODE_MIXED_MV, MV_PMODE_1MV_HPEL, MV_PMODE_INTENSITY_COMP, MV_PMODE_1MV_HPEL_BILIN } +}; +const uint8_t ff_vc1_mv_pmode_table2[2][4] = { + { MV_PMODE_1MV_HPEL_BILIN, MV_PMODE_1MV, MV_PMODE_1MV_HPEL, MV_PMODE_MIXED_MV }, + { MV_PMODE_1MV, MV_PMODE_MIXED_MV, MV_PMODE_1MV_HPEL, MV_PMODE_1MV_HPEL_BILIN } +}; + +/* MBMODE table for interlaced frame P-picture */ +const uint8_t ff_vc1_mbmode_intfrp[2][15][4] = { + { /* 1: 4-MV, 0: non-4-MV */ + /* Type, FIELDTX, 1-MV Differential present, Residuals (CBP) present */ + /* Table 164 - Table 167 */ + { MV_PMODE_INTFR_1MV , 0, 1, 1 }, + { MV_PMODE_INTFR_1MV , 1, 1, 1 }, + { MV_PMODE_INTFR_1MV , 0, 1, 0 }, + { MV_PMODE_INTFR_1MV , 0, 0, 1 }, + { MV_PMODE_INTFR_1MV , 1, 0, 1 }, + { MV_PMODE_INTFR_2MV_FIELD, 0, 0, 1 }, + { MV_PMODE_INTFR_2MV_FIELD, 1, 0, 1 }, + { MV_PMODE_INTFR_2MV_FIELD, 0, 0, 0 }, + { MV_PMODE_INTFR_INTRA , 0, 0, 0 } + }, + { + /* Table 160 - Table 163 */ + { MV_PMODE_INTFR_1MV , 0, 1, 1 }, + { MV_PMODE_INTFR_1MV , 1, 1, 1 }, + { MV_PMODE_INTFR_1MV , 0, 1, 0 }, + { MV_PMODE_INTFR_1MV , 0, 0, 1 }, + { MV_PMODE_INTFR_1MV , 1, 0, 1 }, + { MV_PMODE_INTFR_2MV_FIELD, 0, 0, 1 }, + { MV_PMODE_INTFR_2MV_FIELD, 1, 0, 1 }, + { MV_PMODE_INTFR_2MV_FIELD, 0, 0, 0 }, + { MV_PMODE_INTFR_4MV , 0, 0, 1 }, + { MV_PMODE_INTFR_4MV , 1, 0, 1 }, + { MV_PMODE_INTFR_4MV , 0, 0, 0 }, + { MV_PMODE_INTFR_4MV_FIELD, 0, 0, 1 }, + { MV_PMODE_INTFR_4MV_FIELD, 1, 0, 1 }, + { MV_PMODE_INTFR_4MV_FIELD, 0, 0, 0 }, + { MV_PMODE_INTFR_INTRA , 0, 0, 0 } + } +}; + +const int ff_vc1_fps_nr[7] = { 24, 25, 30, 50, 60, 48, 72 }, + ff_vc1_fps_dr[2] = { 1000, 1001 }; +const uint8_t ff_vc1_pquant_table[3][32] = { + /* Implicit quantizer */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 29, 31 }, + /* Explicit quantizer, pquantizer uniform */ + { 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 }, + /* Explicit quantizer, pquantizer non-uniform */ + { 0, 1, 1, 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, 29, 31 } +}; + +/** @name VC-1 VLC tables and defines + * @todo TODO move this into the context + */ +//@{ +#define VC1_BFRACTION_VLC_BITS 7 +VLC ff_vc1_bfraction_vlc; +#define VC1_IMODE_VLC_BITS 4 +VLC ff_vc1_imode_vlc; +#define VC1_NORM2_VLC_BITS 3 +VLC ff_vc1_norm2_vlc; +#define VC1_NORM6_VLC_BITS 9 +VLC ff_vc1_norm6_vlc; +/* Could be optimized, one table only needs 8 bits */ +#define VC1_TTMB_VLC_BITS 9 //12 +VLC ff_vc1_ttmb_vlc[3]; +#define VC1_MV_DIFF_VLC_BITS 9 //15 +VLC ff_vc1_mv_diff_vlc[4]; +#define VC1_CBPCY_P_VLC_BITS 9 //14 +VLC ff_vc1_cbpcy_p_vlc[4]; +#define VC1_ICBPCY_VLC_BITS 9 +VLC ff_vc1_icbpcy_vlc[8]; +#define VC1_4MV_BLOCK_PATTERN_VLC_BITS 6 +VLC ff_vc1_4mv_block_pattern_vlc[4]; +#define VC1_2MV_BLOCK_PATTERN_VLC_BITS 3 +VLC ff_vc1_2mv_block_pattern_vlc[4]; +#define VC1_TTBLK_VLC_BITS 5 +VLC ff_vc1_ttblk_vlc[3]; +#define VC1_SUBBLKPAT_VLC_BITS 6 +VLC ff_vc1_subblkpat_vlc[3]; +#define VC1_INTFR_4MV_MBMODE_VLC_BITS 9 +VLC ff_vc1_intfr_4mv_mbmode_vlc[4]; +#define VC1_INTFR_NON4MV_MBMODE_VLC_BITS 6 +VLC ff_vc1_intfr_non4mv_mbmode_vlc[4]; +#define VC1_IF_MMV_MBMODE_VLC_BITS 5 +VLC ff_vc1_if_mmv_mbmode_vlc[8]; +#define VC1_IF_1MV_MBMODE_VLC_BITS 5 +VLC ff_vc1_if_1mv_mbmode_vlc[8]; +#define VC1_1REF_MVDATA_VLC_BITS 9 +VLC ff_vc1_1ref_mvdata_vlc[4]; +#define VC1_2REF_MVDATA_VLC_BITS 9 +VLC ff_vc1_2ref_mvdata_vlc[8]; + +VLC ff_vc1_ac_coeff_table[8]; + +#define VC1_IF_MBMODE_VLC_BITS 5 // as a placeholder for VC1_IF_MMV_MBMODE_VLC_BITS + // or VC1_IF_1MV_MBMODE_VLC_BITS since they are the same +//@} + + +#if B_FRACTION_DEN == 840 // original bfraction from vc9data.h, not conforming to standard +/* bfraction is fractional, we scale to the GCD 3*5*7*8 = 840 */ +const int16_t ff_vc1_bfraction_lut[23] = { + 420 /*1/2*/, 280 /*1/3*/, 560 /*2/3*/, 210 /*1/4*/, + 630 /*3/4*/, 168 /*1/5*/, 336 /*2/5*/, + 504 /*3/5*/, 672 /*4/5*/, 140 /*1/6*/, 700 /*5/6*/, + 120 /*1/7*/, 240 /*2/7*/, 360 /*3/7*/, 480 /*4/7*/, + 600 /*5/7*/, 720 /*6/7*/, 105 /*1/8*/, 315 /*3/8*/, + 525 /*5/8*/, 735 /*7/8*/, + -1 /*inv.*/, 0 /*BI fm*/ +}; +#else +/* pre-computed scales for all bfractions and base=256 */ +const int16_t ff_vc1_bfraction_lut[23] = { + 128 /*1/2*/, 85 /*1/3*/, 170 /*2/3*/, 64 /*1/4*/, + 192 /*3/4*/, 51 /*1/5*/, 102 /*2/5*/, + 153 /*3/5*/, 204 /*4/5*/, 43 /*1/6*/, 215 /*5/6*/, + 37 /*1/7*/, 74 /*2/7*/, 111 /*3/7*/, 148 /*4/7*/, + 185 /*5/7*/, 222 /*6/7*/, 32 /*1/8*/, 96 /*3/8*/, + 160 /*5/8*/, 224 /*7/8*/, + -1 /*inv.*/, 0 /*BI fm*/ +}; +#endif + +const uint8_t ff_vc1_bfraction_bits[23] = { + 3, 3, 3, 3, + 3, 3, 3, + 7, 7, 7, 7, + 7, 7, 7, 7, + 7, 7, 7, 7, + 7, 7, + 7, 7 +}; +const uint8_t ff_vc1_bfraction_codes[23] = { + 0, 1, 2, 3, + 4, 5, 6, + 112, 113, 114, 115, + 116, 117, 118, 119, + 120, 121, 122, 123, + 124, 125, + 126, 127 +}; + +//Same as H.264 +const AVRational ff_vc1_pixel_aspect[16] = { + { 0, 1 }, + { 1, 1 }, + { 12, 11 }, + { 10, 11 }, + { 16, 11 }, + { 40, 33 }, + { 24, 11 }, + { 20, 11 }, + { 32, 11 }, + { 80, 33 }, + { 18, 11 }, + { 15, 11 }, + { 64, 33 }, + { 160, 99 }, + { 0, 1 }, + { 0, 1 } +}; + +/* BitPlane IMODE - such a small table... */ +const uint8_t ff_vc1_imode_codes[7] = { + 0, 2, 1, 3, 1, 2, 3 +}; +const uint8_t ff_vc1_imode_bits[7] = { + 4, 2, 3, 2, 4, 3, 3 +}; + +/* Normal-2 imode */ +const uint8_t ff_vc1_norm2_codes[4] = { + 0, 4, 5, 3 +}; +const uint8_t ff_vc1_norm2_bits[4] = { + 1, 3, 3, 2 +}; + +const uint16_t ff_vc1_norm6_codes[64] = { + 0x001, 0x002, 0x003, 0x000, 0x004, 0x001, 0x002, 0x047, 0x005, 0x003, 0x004, 0x04B, 0x005, 0x04D, 0x04E, 0x30E, + 0x006, 0x006, 0x007, 0x053, 0x008, 0x055, 0x056, 0x30D, 0x009, 0x059, 0x05A, 0x30C, 0x05C, 0x30B, 0x30A, 0x037, + 0x007, 0x00A, 0x00B, 0x043, 0x00C, 0x045, 0x046, 0x309, 0x00D, 0x049, 0x04A, 0x308, 0x04C, 0x307, 0x306, 0x036, + 0x00E, 0x051, 0x052, 0x305, 0x054, 0x304, 0x303, 0x035, 0x058, 0x302, 0x301, 0x034, 0x300, 0x033, 0x032, 0x007, +}; + +const uint8_t ff_vc1_norm6_bits[64] = { + 1, 4, 4, 8, 4, 8, 8, 10, 4, 8, 8, 10, 8, 10, 10, 13, + 4, 8, 8, 10, 8, 10, 10, 13, 8, 10, 10, 13, 10, 13, 13, 9, + 4, 8, 8, 10, 8, 10, 10, 13, 8, 10, 10, 13, 10, 13, 13, 9, + 8, 10, 10, 13, 10, 13, 13, 9, 10, 13, 13, 9, 13, 9, 9, 6, +}; + +/* 4MV Block pattern VLC tables */ +const uint8_t ff_vc1_4mv_block_pattern_codes[4][16] = { + { 14, 58, 59, 25, 12, 26, 15, 15, 13, 24, 27, 0, 28, 1, 2, 2 }, + { 8, 18, 19, 4, 20, 5, 30, 11, 21, 31, 6, 12, 7, 13, 14, 0 }, + { 15, 6, 7, 2, 8, 3, 28, 9, 10, 29, 4, 11, 5, 12, 13, 0 }, + { 0, 11, 12, 4, 13, 5, 30, 16, 14, 31, 6, 17, 7, 18, 19, 10 } +}; +const uint8_t ff_vc1_4mv_block_pattern_bits[4][16] = { + { 5, 6, 6, 5, 5, 5, 5, 4, 5, 5, 5, 3, 5, 3, 3, 2 }, + { 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2 }, + { 4, 4, 4, 4, 4, 4, 5, 4, 4, 5, 4, 4, 4, 4, 4, 3 }, + { 2, 4, 4, 4, 4, 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4 } +}; + +/* 2MV Block pattern VLC tables */ +const uint8_t ff_vc1_2mv_block_pattern_codes[4][4] = { + { 2, 1, 0, 3 }, { 1, 0, 2, 3 }, { 2, 0, 3, 1 }, { 1, 3, 2, 0 } +}; + +const uint8_t ff_vc1_2mv_block_pattern_bits[4][4] = { + { 2, 2, 2, 2 }, { 1, 2, 3, 3 }, { 3, 2, 3, 1 }, { 1, 3, 3, 2 } +}; + +/* Interlaced frame picture 4MV MBMODE VLC tables (p. 246, p. 360) */ +const uint16_t ff_vc1_intfr_4mv_mbmode_codes[4][15] = { + { 22, 17, 0, 47, 32, 10, 1, 3, 67, 133, 132, 92, 19, 93, 18 }, + { 3, 45, 0, 7, 23, 6, 1, 2, 10, 39, 44, 8, 18, 77, 76 }, + { 15, 6, 28, 9, 41, 6, 2, 15, 14, 8, 40, 29, 0, 21, 11 }, + { 7, 198, 1, 2, 193, 13, 25, 0, 97, 1599, 98, 398, 798, 192, 1598 } +}; + +const uint8_t ff_vc1_intfr_4mv_mbmode_bits[4][15] = { + { 5, 5, 2, 6, 6, 4, 2, 2, 7, 8, 8, 7, 5, 7, 5 }, + { 3, 6, 3, 3, 5, 3, 3, 3, 4, 6, 6, 4, 5, 7, 7 }, + { 4, 3, 5, 5, 7, 4, 2, 5, 5, 5, 7, 5, 2, 6, 5 }, + { 4, 9, 1, 3, 9, 5, 6, 2, 8, 12, 8, 10, 11, 9, 12 } +}; + +/* Interlaced frame picture NON-4MV MBMODE VLC tables (p. 363) */ +const uint8_t ff_vc1_intfr_non4mv_mbmode_codes[4][9] = { + { 9, 22, 0, 17, 16, 10, 1, 3, 23 }, + { 7, 0, 5, 2, 1, 1, 6, 3, 4 }, + { 1, 0, 10, 23, 44, 8, 3, 9, 45 }, + { 7, 97, 1, 2, 49, 13, 25, 0, 96 } +}; + +const uint8_t ff_vc1_intfr_non4mv_mbmode_bits[4][9] = { + { 4, 5, 2, 5, 5, 4, 2, 2, 5 }, + { 3, 4, 6, 2, 3, 2, 3, 5, 6 }, + { 2, 2, 4, 5, 6, 4, 2, 4, 6 }, + { 4, 8, 1, 3, 7, 5, 6, 2, 8 } +}; + +/* Interlaced field picture MBMODE VLC tables (p. 356 - 11.4.1, 11.4.2) */ +/* mixed-MV */ +const uint8_t ff_vc1_if_mmv_mbmode_codes[8][8] = { + { 16, 17, 3, 3, 0, 5, 9, 2 }, + { 8, 9, 3, 6, 7, 0, 5, 2 }, + { 16, 17, 5, 3, 0, 3, 9, 2 }, + { 56, 57, 15, 4, 5, 6, 29, 0 }, + { 52, 53, 27, 14, 15, 2, 12, 0 }, + { 56, 57, 29, 5, 6, 0, 15, 4 }, + { 16, 17, 6, 7, 0, 1, 9, 5 }, + { 56, 57, 0, 5, 6, 29, 4, 15 } +}; +const uint8_t ff_vc1_if_mmv_mbmode_bits[8][8] = { + { 6, 6, 2, 3, 2, 4, 5, 2 }, + { 5, 5, 3, 3, 3, 2, 4, 2 }, + { 6, 6, 4, 3, 2, 2, 5, 2 }, + { 6, 6, 4, 3, 3, 3, 5, 1 }, + { 6, 6, 5, 4, 4, 2, 4, 1 }, + { 6, 6, 5, 3, 3, 1, 4, 3 }, + { 5, 5, 3, 3, 2, 2, 4, 3 }, + { 6, 6, 1, 3, 3, 5, 3, 4 } +}; +/* 1MV */ +const uint8_t ff_vc1_if_1mv_mbmode_codes[8][6] = { + { 0, 1, 1, 1, 1, 1 }, + { 0, 1, 1, 1, 1, 1 }, + { 16, 17, 3, 0, 9, 5 }, + { 20, 21, 3, 11, 0, 4 }, + { 4, 5, 2, 3, 3, 0 }, + { 4, 5, 3, 2, 0, 3 }, + { 0, 1, 1, 1, 1, 1 }, + { 16, 17, 9, 5, 3, 0 } +}; +const uint8_t ff_vc1_if_1mv_mbmode_bits[8][6] = { + { 5, 5, 1, 3, 2, 4 }, + { 5, 5, 1, 2, 3, 4 }, + { 5, 5, 2, 1, 4, 3 }, + { 5, 5, 2, 4, 1, 3 }, + { 4, 4, 2, 3, 2, 2 }, + { 4, 4, 3, 2, 2, 2 }, + { 5, 5, 3, 4, 1, 2 }, + { 5, 5, 4, 3, 2, 1 } +}; + +/* Interlaced frame/field picture MVDATA VLC tables */ + +/* 1-reference tables */ +const uint32_t ff_vc1_1ref_mvdata_codes[4][72] = { /* uint32_t may be too big */ + { + 0x00005, 0x0000C, 0x0001E, 0x00012, 0x0000C, 0x00034, 0x00075, 0x00070, + 0x00000, 0x00008, 0x0001B, 0x00008, 0x0001D, 0x0007C, 0x000D6, 0x001DE, + 0x001AF, 0x00005, 0x0001B, 0x00026, 0x0001E, 0x00012, 0x00076, 0x0004D, + 0x001F6, 0x001F4, 0x00039, 0x0007F, 0x00027, 0x0006A, 0x00071, 0x00035, + 0x00071, 0x00068, 0x001DC, 0x00027, 0x00073, 0x000FF, 0x000E8, 0x000E9, + 0x0007E, 0x001F9, 0x001F5, 0x001FD, 0x0003E, 0x001CA, 0x003F9, 0x0004C, + 0x00069, 0x001FA, 0x001DF, 0x001F7, 0x00070, 0x001DD, 0x00E4D, 0x00727, + 0x00392, 0x001C8, 0x001CB, 0x003F8, 0x001AE, 0x001F8, 0x001FB, 0x0E4CE, + 0x0E4CF, 0x07260, 0x07261, 0x07262, 0x07263, 0x07264, 0x07265, 0x07266 + }, + { + 0x00007, 0x00001, 0x00007, 0x00016, 0x00001, 0x00045, 0x00018, 0x002B6, + 0x00006, 0x00004, 0x00017, 0x00010, 0x00029, 0x0002C, 0x0015A, 0x00066, + 0x0019E, 0x00009, 0x00028, 0x00017, 0x00000, 0x0002A, 0x00004, 0x0005B, + 0x000B5, 0x000CE, 0x00006, 0x00044, 0x0000F, 0x00046, 0x0000E, 0x000AC, + 0x00032, 0x00037, 0x011EB, 0x0000A, 0x0001A, 0x0011F, 0x00016, 0x00014, + 0x0002B, 0x00168, 0x00055, 0x023D5, 0x00057, 0x0002F, 0x00036, 0x0002E, + 0x00169, 0x00054, 0x0047B, 0x0019F, 0x02B7D, 0x0008E, 0x00ADE, 0x00479, + 0x0056E, 0x008F4, 0x015BF, 0x00478, 0x023D4, 0x0ADF1, 0x056F9, 0xADF0E, + 0xADF0F, 0x56F80, 0x56F81, 0x56F82, 0x56F83, 0x56F84, 0x56F85, 0x56F86 + }, + { + 0x00002, 0x00006, 0x00007, 0x0000D, 0x00007, 0x00030, 0x000FF, 0x001F0, + 0x00002, 0x00000, 0x00005, 0x00019, 0x0001E, 0x00007, 0x00063, 0x000FD, + 0x00023, 0x0000E, 0x0001B, 0x0001A, 0x00006, 0x00009, 0x00018, 0x000C5, + 0x00033, 0x001F1, 0x00002, 0x003FB, 0x001F3, 0x00022, 0x001FC, 0x00042, + 0x00623, 0x00083, 0x00620, 0x0007D, 0x00040, 0x00043, 0x003E4, 0x003E5, + 0x00191, 0x00FE9, 0x00105, 0x00208, 0x000FC, 0x00624, 0x00622, 0x00190, + 0x00626, 0x007F5, 0x00C4B, 0x01FD0, 0x0104D, 0x00065, 0x00C42, 0x000C9, + 0x00627, 0x00C43, 0x00C4A, 0x0104E, 0x01FD1, 0x0104F, 0x00412, 0x104CE, + 0x104CF, 0x08260, 0x08261, 0x08262, 0x08263, 0x08264, 0x08265, 0x08266 + }, + { + 0x0000D, 0x00001, 0x00004, 0x00000, 0x00017, 0x00005, 0x0007F, 0x0004D, + 0x00003, 0x00011, 0x0003E, 0x0003B, 0x00017, 0x00067, 0x0004A, 0x000C3, + 0x000F2, 0x0000A, 0x0002C, 0x00032, 0x0003D, 0x00015, 0x00028, 0x00093, + 0x000CC, 0x00096, 0x00003, 0x00075, 0x00020, 0x0002D, 0x00021, 0x00029, + 0x00090, 0x001D0, 0x001FB, 0x0001C, 0x0004C, 0x00060, 0x00009, 0x00008, + 0x0002D, 0x0009F, 0x001FA, 0x0013D, 0x00031, 0x000FC, 0x00058, 0x00092, + 0x000F0, 0x000F1, 0x000CD, 0x00185, 0x00165, 0x0004E, 0x00091, 0x000E9, + 0x00184, 0x001D1, 0x001E6, 0x00097, 0x001E7, 0x000B3, 0x0013C, 0x0164E, + 0x0164F, 0x00B20, 0x00B21, 0x00B22, 0x00B23, 0x00B24, 0x00B25, 0x00B26 + } +}; + +const uint8_t ff_vc1_1ref_mvdata_bits[4][72] = { + { + 3, 4, 5, 5, 5, 6, 7, 7, 2, 4, 5, 5, 6, 7, 8, 9, 9, 4, + 6, 6, 6, 6, 7, 8, 9, 9, 6, 8, 7, 7, 7, 7, 8, 8, 9, 6, + 8, 8, 8, 8, 8, 9, 9, 9, 7, 10, 10, 8, 8, 9, 9, 9, 8, 9, + 13, 12, 11, 10, 10, 10, 9, 9, 9, 17, 17, 16, 16, 16, 16, 16, 16, 16 + }, + { + 3, 3, 4, 5, 5, 7, 8, 10, 3, 4, 5, 5, 6, 7, 9, 10, 12, 4, + 6, 6, 5, 6, 6, 8, 9, 11, 4, 7, 7, 7, 7, 8, 9, 9, 13, 5, + 8, 9, 8, 8, 9, 10, 10, 14, 7, 9, 9, 9, 10, 10, 11, 12, 14, 8, + 12, 11, 11, 12, 13, 11, 14, 16, 15, 20, 20, 19, 19, 19, 19, 19, 19, 19 + }, + { + 3, 4, 4, 4, 5, 6, 8, 9, 2, 4, 5, 5, 5, 6, 7, 8, 8, 4, + 7, 7, 6, 6, 7, 8, 8, 9, 5, 10, 9, 8, 9, 9, 11, 10, 11, 7, + 9, 9, 10, 10, 11, 12, 11, 12, 8, 11, 11, 11, 11, 11, 12, 13, 15, 9, + 12, 10, 11, 12, 12, 15, 13, 15, 13, 19, 19, 18, 18, 18, 18, 18, 18, 18 + }, + { + 4, 4, 4, 4, 5, 5, 7, 7, 3, 5, 6, 6, 6, 7, 7, 8, 8, 4, + 6, 6, 6, 6, 7, 8, 8, 8, 4, 7, 6, 6, 6, 7, 8, 9, 9, 5, + 7, 7, 6, 6, 7, 8, 9, 9, 6, 8, 8, 8, 8, 8, 8, 9, 10, 7, + 8, 8, 9, 9, 9, 8, 9, 9, 9, 14, 14, 13, 13, 13, 13, 13, 13, 13 + } +}; + +/* 2-reference tables */ +const uint32_t ff_vc1_2ref_mvdata_codes[8][126] = { /* table 132 - table 139 */ + { + 0x0000C, 0x0001C, 0x0000B, 0x00000, 0x0000E, 0x0002A, 0x00050, 0x00368, + 0x00002, 0x0001A, 0x00004, 0x0003A, 0x0001D, 0x0006C, 0x000EF, 0x001BC, + 0x0015F, 0x0000F, 0x00003, 0x0001C, 0x0000D, 0x0000B, 0x0003E, 0x000A7, + 0x00146, 0x00199, 0x00006, 0x0001F, 0x00004, 0x0003C, 0x00007, 0x001BE, + 0x0008B, 0x0002C, 0x007B3, 0x00005, 0x000DB, 0x00056, 0x000EC, 0x00052, + 0x001BD, 0x00078, 0x000CF, 0x00573, 0x00009, 0x00023, 0x000ED, 0x00018, + 0x00006, 0x00044, 0x000F5, 0x00079, 0x006D2, 0x0006E, 0x0002B, 0x0015D, + 0x00017, 0x0037F, 0x00144, 0x000CE, 0x00028, 0x000AB, 0x00010, 0x001B5, + 0x000F7, 0x000A6, 0x0007B, 0x00028, 0x001ED, 0x001E9, 0x006FD, 0x00004, + 0x000F5, 0x00029, 0x0028A, 0x0028B, 0x0028F, 0x00DF9, 0x00335, 0x01E85, + 0x000EE, 0x002BD, 0x0002B, 0x003D8, 0x003D1, 0x00198, 0x001E9, 0x0051D, + 0x000B4, 0x0003F, 0x00455, 0x0022B, 0x00229, 0x00451, 0x00578, 0x007B2, + 0x00570, 0x00155, 0x00032, 0x003D0, 0x00054, 0x006D3, 0x00571, 0x00454, + 0x00334, 0x01BF1, 0x000B7, 0x00029, 0x01E84, 0x0016C, 0x0019B, 0x01BF0, + 0x00579, 0x00F43, 0x000B5, 0x008A1, 0x0002A, 0x0016D, 0x008A0, 0x007A0, + 0x003D1, 0x00AE5, 0x00154, 0x00AE4, 0x00A39, 0x00A38 + }, + { + 0x00003, 0x00009, 0x00016, 0x00010, 0x000D7, 0x00335, 0x00574, 0x00555, + 0x00000, 0x0001D, 0x00009, 0x00017, 0x0002C, 0x000AD, 0x00374, 0x006B3, + 0x00577, 0x0000F, 0x00018, 0x0000A, 0x0002E, 0x00022, 0x0017C, 0x00E7B, + 0x01B89, 0x015D8, 0x00008, 0x00034, 0x0006D, 0x00023, 0x001C2, 0x00376, + 0x002D3, 0x01C4A, 0x0330A, 0x00014, 0x0006A, 0x00072, 0x0006C, 0x000E3, + 0x0019B, 0x0073F, 0x01CF0, 0x00B41, 0x00032, 0x000E6, 0x000E0, 0x000CF, + 0x000AB, 0x0019C, 0x002AB, 0x00E2B, 0x015D9, 0x0006F, 0x001C3, 0x000AF, + 0x000BF, 0x000AC, 0x0017D, 0x006E3, 0x00E29, 0x01984, 0x00054, 0x000B5, + 0x0017A, 0x001AD, 0x00199, 0x00178, 0x00358, 0x002D2, 0x01C4B, 0x0005B, + 0x002A8, 0x00331, 0x00388, 0x0038B, 0x00370, 0x00713, 0x00CC3, 0x01CF1, + 0x001B9, 0x005EF, 0x00738, 0x002F2, 0x0033B, 0x002B9, 0x006EB, 0x00570, + 0x00E24, 0x0039D, 0x005A2, 0x005A3, 0x00E7D, 0x005EE, 0x00739, 0x00554, + 0x00AA5, 0x00AA4, 0x00377, 0x01CF5, 0x00BCE, 0x00E79, 0x00660, 0x00674, + 0x006EA, 0x00E7C, 0x00D65, 0x002F6, 0x015DA, 0x01B88, 0x005A1, 0x01CF4, + 0x005E6, 0x00E28, 0x00575, 0x00D64, 0x00334, 0x0330B, 0x015DB, 0x00B40, + 0x00BCF, 0x00DC5, 0x00E2A, 0x00675, 0x00571, 0x00553 + }, + { + 0x00004, 0x00002, 0x00010, 0x00003, 0x00017, 0x00045, 0x0003E, 0x0007E, + 0x00003, 0x00002, 0x00028, 0x0001E, 0x00015, 0x00047, 0x00002, 0x0014D, + 0x00060, 0x0000B, 0x00026, 0x00024, 0x00014, 0x00032, 0x0006F, 0x000C3, + 0x00531, 0x006E5, 0x00015, 0x0003F, 0x0002D, 0x00001, 0x0013E, 0x000DD, + 0x000F6, 0x00305, 0x00331, 0x0000E, 0x00003, 0x00034, 0x00033, 0x0001A, + 0x0014A, 0x000C5, 0x000F4, 0x006E4, 0x00001, 0x0003C, 0x0007D, 0x0008D, + 0x0009D, 0x00031, 0x0006E, 0x00296, 0x000CD, 0x00025, 0x00149, 0x00032, + 0x00089, 0x00036, 0x00088, 0x0006F, 0x00003, 0x0031D, 0x0000E, 0x001AA, + 0x0027E, 0x00061, 0x0014E, 0x0014F, 0x00067, 0x000FF, 0x00183, 0x00036, + 0x00357, 0x000F5, 0x000C6, 0x000C2, 0x00299, 0x00119, 0x00231, 0x00350, + 0x0002C, 0x0018F, 0x00530, 0x00297, 0x00004, 0x001B8, 0x000C0, 0x0027A, + 0x00311, 0x0009C, 0x00621, 0x00199, 0x0031C, 0x000F7, 0x003E3, 0x00356, + 0x00189, 0x00005, 0x0006B, 0x008C2, 0x00330, 0x004FF, 0x004F0, 0x00351, + 0x004F2, 0x001F2, 0x00373, 0x00000, 0x00C41, 0x008C3, 0x009EC, 0x003E2, + 0x00304, 0x004F7, 0x004F1, 0x001F0, 0x00148, 0x00C40, 0x009ED, 0x008C0, + 0x008C1, 0x004F3, 0x004FE, 0x000FE, 0x001F3, 0x001A9 + }, + { + 0x00000, 0x00004, 0x0002F, 0x00052, 0x00010, 0x000AD, 0x0050B, 0x00190, + 0x00003, 0x00016, 0x00007, 0x0000D, 0x000BB, 0x00173, 0x000C9, 0x0050F, + 0x0172C, 0x00003, 0x00011, 0x00005, 0x00043, 0x00023, 0x0004B, 0x0032E, + 0x02E5B, 0x00482, 0x00009, 0x0002A, 0x00014, 0x0002A, 0x00108, 0x005CA, + 0x0065A, 0x02136, 0x02132, 0x0000B, 0x00013, 0x00041, 0x000B8, 0x00174, + 0x00100, 0x014DA, 0x0404E, 0x01437, 0x0002B, 0x00085, 0x000A7, 0x000A0, + 0x0014C, 0x0029A, 0x0032C, 0x02133, 0x0142A, 0x00051, 0x00284, 0x000AC, + 0x00102, 0x00045, 0x00044, 0x0081B, 0x0065E, 0x00CB7, 0x00018, 0x0050C, + 0x00212, 0x002E4, 0x00203, 0x00094, 0x00122, 0x0081A, 0x00655, 0x00033, + 0x002BA, 0x00246, 0x00242, 0x00A6E, 0x0040C, 0x00808, 0x02134, 0x0404F, + 0x00175, 0x00405, 0x00247, 0x0012A, 0x00A14, 0x002BB, 0x00191, 0x0084F, + 0x01438, 0x000AF, 0x00B97, 0x00483, 0x0143B, 0x0032B, 0x00243, 0x0142B, + 0x00958, 0x029BF, 0x00049, 0x00A6C, 0x014DB, 0x004AD, 0x014DE, 0x0084E, + 0x01434, 0x00257, 0x02E5A, 0x00207, 0x01435, 0x01439, 0x00CB6, 0x0143A, + 0x00194, 0x00654, 0x02135, 0x0537C, 0x0015C, 0x00240, 0x01012, 0x0537D, + 0x00959, 0x01098, 0x01436, 0x0065F, 0x02026, 0x02137 + }, + { + 0x00005, 0x00019, 0x00016, 0x00011, 0x0003E, 0x0005E, 0x000EF, 0x000E2, + 0x00000, 0x00039, 0x0002B, 0x00026, 0x00028, 0x00012, 0x000C2, 0x000ED, + 0x0011D, 0x0000D, 0x00031, 0x0002A, 0x00025, 0x00020, 0x0005C, 0x001ED, + 0x0024D, 0x00770, 0x00006, 0x0007A, 0x00060, 0x0004F, 0x00048, 0x00039, + 0x00186, 0x00213, 0x00EC6, 0x0000F, 0x00026, 0x0005F, 0x00075, 0x00070, + 0x00027, 0x001DB, 0x003C6, 0x0078F, 0x0003F, 0x000A6, 0x000F0, 0x0003A, + 0x00052, 0x0004E, 0x000E3, 0x001D9, 0x0030F, 0x00010, 0x001DD, 0x000A7, + 0x000F7, 0x00022, 0x00092, 0x003C4, 0x002EF, 0x00762, 0x00079, 0x0008F, + 0x001DA, 0x00087, 0x000E8, 0x000BA, 0x00176, 0x000EE, 0x003B0, 0x00085, + 0x00119, 0x0030E, 0x00108, 0x001D2, 0x0010C, 0x00773, 0x00424, 0x00434, + 0x00071, 0x005DD, 0x001C1, 0x003A7, 0x00127, 0x0008D, 0x0021B, 0x007B2, + 0x001DF, 0x003D8, 0x00764, 0x00EE4, 0x003B3, 0x0074D, 0x001D8, 0x005DC, + 0x0084A, 0x00499, 0x003C5, 0x01D8E, 0x00765, 0x00435, 0x00771, 0x001C2, + 0x00118, 0x003BC, 0x00381, 0x00387, 0x07B33, 0x01097, 0x01096, 0x01ECD, + 0x00E99, 0x00F1C, 0x00F1D, 0x00EE5, 0x0011C, 0x07B32, 0x03D98, 0x01D8F, + 0x00E98, 0x00F67, 0x003BD, 0x00380, 0x00498, 0x00386 + }, + { + 0x0000D, 0x00010, 0x0002E, 0x00039, 0x0000D, 0x00074, 0x000ED, 0x000B6, + 0x00001, 0x00002, 0x00000, 0x00030, 0x00029, 0x00070, 0x000F3, 0x0008C, + 0x00166, 0x00009, 0x00033, 0x00078, 0x00006, 0x000C4, 0x0000B, 0x00163, + 0x000CC, 0x005BE, 0x0001F, 0x0002F, 0x00064, 0x00018, 0x000C6, 0x0000A, + 0x00162, 0x002C0, 0x00EF3, 0x00007, 0x0000F, 0x000E3, 0x000CA, 0x000B2, + 0x0018F, 0x003AE, 0x0075F, 0x00C51, 0x00015, 0x00047, 0x000EE, 0x000E2, + 0x000EA, 0x00009, 0x0016A, 0x002C3, 0x0059D, 0x0003D, 0x00008, 0x001D9, + 0x00032, 0x0000E, 0x0016E, 0x0032C, 0x0065B, 0x0196B, 0x00002, 0x0000F, + 0x001D8, 0x0008D, 0x000B4, 0x001E4, 0x00067, 0x00317, 0x00794, 0x00022, + 0x003BE, 0x00315, 0x00034, 0x00037, 0x002DE, 0x0006C, 0x00EFE, 0x0066C, + 0x00028, 0x003CB, 0x003AC, 0x00035, 0x0016B, 0x003BD, 0x002C1, 0x0062C, + 0x01DFE, 0x0000E, 0x0059E, 0x005BF, 0x000DA, 0x00629, 0x00584, 0x00EB7, + 0x00B0A, 0x0066D, 0x0000C, 0x0077E, 0x0059C, 0x00778, 0x0075E, 0x0075A, + 0x0062D, 0x00337, 0x00334, 0x00197, 0x01E57, 0x01DE4, 0x0196A, 0x01E56, + 0x00C50, 0x00B3F, 0x01E54, 0x00B0B, 0x0018E, 0x001B6, 0x01E55, 0x00CB4, + 0x00B3E, 0x00EB6, 0x01DE5, 0x01DFF, 0x00335, 0x001B7 + }, + { + 0x00001, 0x0000B, 0x00019, 0x0006F, 0x0002A, 0x00075, 0x007EB, 0x00163, + 0x00001, 0x0000E, 0x0001A, 0x0003E, 0x0001C, 0x0002D, 0x00164, 0x007EC, + 0x00165, 0x00004, 0x00006, 0x00036, 0x0007F, 0x000AE, 0x00158, 0x0015C, + 0x0056D, 0xFD510, 0x00000, 0x00004, 0x0007B, 0x000F3, 0x0003B, 0x007ED, + 0x002B3, 0x002CC, 0x0056E, 0x00018, 0x0003E, 0x00017, 0x0001E, 0x000AF, + 0x003F7, 0x0056F, 0x002CD, 0xFD511, 0x00014, 0x000AD, 0x000AA, 0x00014, + 0x000A8, 0x00153, 0x000E8, 0x001FE, 0x00DCF, 0x00078, 0x001B8, 0x00152, + 0x000FE, 0x002B1, 0x0015D, 0x00160, 0xFD512, 0xFD513, 0x0007A, 0x002B0, + 0x001E5, 0x000E9, 0x000FC, 0x006E6, 0x00DC8, 0x00584, 0xFD514, 0x000AB, + 0x00DDE, 0x00159, 0x003F4, 0x00DC9, 0x00DCA, 0x001FA, 0xFD515, 0xFD516, + 0x000FC, 0x001FF, 0x001E4, 0x000AF, 0x0015A, 0x00167, 0x00DCB, 0x00585, + 0xFD517, 0x003F7, 0x03F55, 0xFD518, 0x00DDC, 0x00586, 0x03F56, 0xFD519, + 0x03F57, 0xFD51A, 0x001BA, 0x00587, 0x00588, 0x00DDF, 0x002B2, 0xFD51B, + 0x00DCE, 0x003F6, 0xFD51C, 0x00FD4, 0xFD51D, 0xFD51E, 0xFD51F, 0x7EA80, + 0x7EA81, 0x0056C, 0x7EA82, 0x7EA83, 0x00376, 0x00589, 0x0058A, 0x7EA84, + 0x7EA85, 0x00DDD, 0x7EA86, 0x7EA87, 0x0058B, 0x07EA9 + }, + { + 0x00003, 0x0000E, 0x0000F, 0x0007E, 0x00062, 0x000C6, 0x00CD9, 0x0063E, + 0x00002, 0x00002, 0x00000, 0x00018, 0x0000C, 0x00069, 0x00039, 0x00707, + 0x00C7E, 0x00002, 0x0000D, 0x0001B, 0x0000F, 0x0019A, 0x00647, 0x01A37, + 0x346C4, 0x0346D, 0x00001, 0x0001E, 0x0007F, 0x0000A, 0x000E1, 0x00661, + 0x00CE4, 0x346C5, 0x346C6, 0x0001D, 0x00030, 0x0000D, 0x000CB, 0x00199, + 0x00320, 0x0008E, 0x0652E, 0x346C7, 0x0003E, 0x00039, 0x00035, 0x00033, + 0x0019F, 0x001C0, 0x00CDA, 0x346C8, 0x346C9, 0x0000B, 0x000D0, 0x0019E, + 0x00022, 0x00038, 0x0018E, 0x0031E, 0x03294, 0x0023C, 0x00032, 0x00012, + 0x00013, 0x00071, 0x0019D, 0x00020, 0x00C87, 0x00CC0, 0x346CA, 0x00338, + 0x00653, 0x001A2, 0x0032A, 0x00322, 0x00CE7, 0x00084, 0x0011F, 0x346CB, + 0x00325, 0x00649, 0x0032B, 0x00077, 0x00648, 0x00642, 0x00C86, 0x00C8C, + 0x346CC, 0x0003A, 0x019B7, 0x00043, 0x00327, 0x0008C, 0x0008D, 0x00C8D, + 0x346CD, 0x346CE, 0x00337, 0x00CE5, 0x00085, 0x00326, 0x00347, 0x00CA4, + 0x00C7F, 0x00D1A, 0x346CF, 0x00328, 0x1A360, 0x1A361, 0x00CD8, 0x0068C, + 0x03295, 0x03296, 0x0652F, 0x066D8, 0x00331, 0x00706, 0x0023D, 0x00076, + 0x00CC1, 0x00382, 0x00CE6, 0x066D9, 0x066DA, 0x066DB + } +}; + +const uint8_t ff_vc1_2ref_mvdata_bits[8][126] = { + { + 4, 5, 5, 5, 6, 7, 8, 10, 2, 5, 5, 6, 6, 7, 8, 9, + 10, 4, 5, 6, 6, 7, 8, 9, 10, 11, 4, 6, 6, 7, 7, 9, + 9, 10, 12, 5, 8, 8, 8, 8, 9, 9, 10, 12, 5, 7, 8, 7, + 7, 8, 9, 9, 11, 7, 9, 10, 9, 10, 10, 10, 10, 12, 6, 9, + 9, 9, 9, 9, 10, 10, 11, 7, 10, 10, 11, 11, 11, 12, 12, 14, + 8, 11, 10, 11, 11, 11, 11, 12, 12, 8, 12, 11, 11, 12, 12, 12, + 12, 13, 8, 12, 11, 11, 12, 12, 12, 13, 12, 9, 14, 13, 11, 13, + 12, 13, 12, 13, 9, 13, 13, 12, 12, 13, 13, 13, 13, 13 + }, + { + 3, 4, 5, 6, 8, 10, 11, 11, 2, 5, 5, 6, 7, 8, 10, 11, + 11, 4, 5, 5, 6, 7, 9, 12, 13, 13, 4, 6, 7, 7, 9, 10, + 11, 13, 14, 5, 7, 7, 7, 8, 9, 11, 13, 13, 6, 8, 8, 8, + 8, 9, 10, 12, 13, 7, 9, 8, 8, 8, 9, 11, 12, 13, 7, 9, + 9, 9, 9, 9, 10, 11, 13, 8, 10, 10, 10, 10, 10, 11, 12, 13, + 9, 11, 11, 10, 10, 10, 11, 11, 12, 10, 12, 12, 12, 11, 11, 11, + 12, 12, 10, 13, 12, 12, 11, 11, 11, 12, 12, 10, 13, 13, 12, 13, + 11, 12, 11, 12, 10, 14, 13, 13, 12, 12, 12, 11, 11, 11 + }, + { + 4, 4, 5, 5, 6, 7, 8, 9, 2, 5, 6, 6, 6, 7, 7, 9, + 9, 4, 6, 6, 6, 7, 8, 9, 11, 12, 5, 7, 7, 7, 9, 9, + 10, 11, 12, 5, 7, 7, 7, 7, 9, 9, 10, 12, 5, 8, 8, 8, + 8, 8, 9, 10, 10, 6, 9, 8, 8, 8, 8, 9, 9, 11, 6, 10, + 10, 9, 9, 9, 9, 10, 10, 7, 11, 10, 9, 9, 10, 9, 10, 11, + 7, 10, 11, 10, 10, 10, 9, 10, 11, 8, 12, 11, 11, 10, 11, 11, + 10, 10, 8, 12, 12, 11, 11, 11, 11, 10, 11, 8, 13, 12, 12, 11, + 11, 11, 11, 10, 9, 13, 12, 12, 12, 11, 11, 10, 10, 10 + }, + { + 3, 4, 6, 7, 7, 9, 11, 11, 2, 5, 5, 6, 8, 9, 10, 11, + 13, 3, 5, 5, 7, 8, 9, 12, 14, 13, 4, 6, 6, 7, 9, 11, + 13, 14, 14, 5, 7, 7, 8, 9, 9, 13, 15, 13, 6, 8, 8, 8, + 9, 10, 12, 14, 13, 7, 10, 9, 9, 9, 9, 12, 13, 14, 7, 11, + 10, 10, 10, 10, 11, 12, 13, 8, 11, 12, 12, 12, 11, 12, 14, 15, + 9, 11, 12, 11, 12, 11, 11, 12, 13, 9, 12, 13, 13, 12, 12, 13, + 14, 14, 9, 12, 13, 13, 13, 12, 13, 12, 14, 10, 13, 13, 14, 13, + 11, 13, 14, 15, 10, 12, 13, 15, 14, 13, 13, 13, 14, 14 + }, + { + 4, 5, 5, 5, 6, 7, 8, 8, 2, 6, 6, 6, 6, 6, 8, 9, + 10, 4, 6, 6, 6, 6, 7, 9, 10, 11, 4, 7, 7, 7, 7, 7, + 9, 10, 12, 5, 7, 7, 7, 7, 7, 9, 10, 11, 6, 8, 8, 7, + 7, 7, 8, 9, 10, 6, 9, 8, 8, 7, 8, 10, 10, 11, 7, 9, + 9, 8, 8, 8, 9, 9, 10, 8, 10, 10, 9, 9, 9, 11, 11, 11, + 8, 11, 10, 10, 9, 9, 10, 11, 10, 10, 12, 12, 11, 11, 10, 11, + 12, 11, 10, 13, 12, 11, 11, 10, 10, 11, 11, 11, 15, 13, 13, 13, + 12, 12, 12, 12, 10, 15, 14, 13, 12, 12, 11, 11, 11, 11 + }, + { + 4, 5, 6, 6, 6, 7, 8, 8, 2, 4, 5, 6, 6, 7, 8, 8, + 9, 4, 6, 7, 7, 8, 8, 9, 10, 11, 5, 6, 7, 7, 8, 8, + 9, 10, 12, 5, 7, 8, 8, 8, 9, 10, 11, 12, 5, 7, 8, 8, + 8, 8, 9, 10, 11, 6, 8, 9, 8, 8, 9, 10, 11, 13, 5, 8, + 9, 8, 8, 9, 9, 10, 11, 6, 10, 10, 9, 9, 10, 10, 12, 13, + 6, 10, 10, 9, 9, 10, 10, 11, 13, 7, 11, 11, 11, 11, 11, 12, + 12, 13, 7, 11, 11, 11, 11, 11, 11, 12, 12, 9, 13, 13, 13, 13, + 12, 12, 13, 12, 9, 12, 13, 12, 12, 12, 13, 13, 12, 12 + }, + { + 3, 5, 6, 8, 9, 10, 12, 12, 1, 5, 6, 7, 8, 9, 12, 12, + 12, 4, 6, 7, 8, 9, 12, 12, 14, 21, 4, 6, 8, 9, 9, 12, + 13, 13, 14, 6, 9, 8, 8, 9, 13, 14, 13, 21, 6, 9, 9, 8, + 9, 10, 11, 12, 13, 8, 10, 10, 11, 11, 12, 12, 21, 21, 8, 11, + 10, 11, 11, 12, 13, 14, 21, 9, 13, 10, 11, 13, 13, 12, 21, 21, + 9, 12, 10, 11, 12, 12, 13, 14, 21, 11, 15, 21, 13, 14, 15, 21, + 15, 21, 10, 14, 14, 13, 13, 21, 13, 13, 21, 13, 21, 21, 21, 20, + 20, 14, 20, 20, 11, 14, 14, 20, 20, 13, 20, 20, 14, 16 + }, + { + 2, 5, 6, 8, 9, 10, 13, 13, 2, 4, 5, 6, 8, 9, 10, 13, + 14, 3, 5, 7, 8, 10, 12, 15, 20, 16, 4, 6, 8, 8, 10, 12, + 13, 20, 20, 7, 8, 8, 9, 10, 11, 12, 16, 20, 7, 8, 8, 8, + 10, 11, 13, 20, 20, 8, 10, 10, 10, 10, 11, 12, 15, 14, 8, 9, + 9, 9, 10, 10, 13, 13, 20, 11, 12, 11, 11, 11, 13, 12, 13, 20, + 11, 12, 11, 11, 12, 12, 13, 13, 20, 10, 14, 11, 11, 12, 12, 13, + 20, 20, 11, 13, 12, 11, 12, 13, 14, 14, 20, 11, 19, 19, 13, 13, + 15, 15, 16, 16, 11, 13, 14, 11, 13, 12, 13, 16, 16, 16 + } +}; + +const uint8_t ff_wmv3_dc_scale_table[32] = { + 0, 2, 4, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21 +}; + +/* P-Picture CBPCY VLC tables */ +// Looks like original tables are not conforming to standard at all. Are they used for old WMV? +const uint16_t ff_vc1_cbpcy_p_codes[4][64] = { + { + 0, 6, 15, 13, 13, 11, 3, 13, 5, 8, 49, 10, 12, 114, 102, 119, + 1, 54, 96, 8, 10, 111, 5, 15, 12, 10, 2, 12, 13, 115, 53, 63, + 1, 7, 1, 7, 14, 12, 4, 14, 1, 9, 97, 11, 7, 58, 52, 62, + 4, 103, 1, 9, 11, 56, 101, 118, 4, 110, 100, 30, 2, 5, 4, 3 + }, + { + 0, 9, 1, 18, 5, 14, 237, 26, 3, 121, 3, 22, 13, 16, 6, 30, + 2, 10, 1, 20, 12, 241, 5, 28, 16, 12, 3, 24, 28, 124, 239, 247, + 1, 240, 1, 19, 18, 15, 4, 27, 1, 122, 2, 23, 1, 17, 7, 31, + 1, 11, 2, 21, 19, 246, 238, 29, 17, 13, 236, 25, 58, 63, 8, 125 + }, + { + 0, 201, 25, 231, 5, 221, 1, 3, 2, 414, 2, 241, 16, 225, 195, 492, + 2, 412, 1, 240, 7, 224, 98, 245, 1, 220, 96, 5, 9, 230, 101, 247, + 1, 102, 1, 415, 24, 3, 2, 244, 3, 54, 3, 484, 17, 114, 200, 493, + 3, 413, 1, 4, 13, 113, 99, 485, 4, 111, 194, 243, 5, 29, 26, 31 + }, + { + 0, 28, 12, 44, 3, 36, 20, 52, 2, 32, 16, 48, 8, 40, 24, 28, + 1, 30, 14, 46, 6, 38, 22, 54, 3, 34, 18, 50, 10, 42, 26, 30, + 1, 29, 13, 45, 5, 37, 21, 53, 2, 33, 17, 49, 9, 41, 25, 29, + 1, 31, 15, 47, 7, 39, 23, 55, 4, 35, 19, 51, 11, 43, 27, 31 + } +}; + +const uint8_t ff_vc1_cbpcy_p_bits[4][64] = { + { + 13, 13, 7, 13, 7, 13, 13, 12, 6, 13, 7, 12, 6, 8, 8, 8, + 5, 7, 8, 12, 6, 8, 13, 12, 7, 13, 13, 12, 6, 8, 7, 7, + 6, 13, 8, 12, 7, 13, 13, 12, 7, 13, 8, 12, 5, 7, 7, 7, + 6, 8, 13, 12, 6, 7, 8, 8, 5, 8, 8, 6, 3, 3, 3, 2 + }, + { + 14, 13, 8, 13, 3, 13, 8, 13, 3, 7, 8, 13, 4, 13, 13, 13, + 3, 13, 13, 13, 4, 8, 13, 13, 5, 13, 13, 13, 5, 7, 8, 8, + 3, 8, 14, 13, 5, 13, 13, 13, 4, 7, 13, 13, 6, 13, 13, 13, + 5, 13, 8, 13, 5, 8, 8, 13, 5, 13, 8, 13, 6, 6, 13, 7 + }, + { + 13, 8, 6, 8, 4, 8, 13, 12, 4, 9, 8, 8, 5, 8, 8, 9, + 5, 9, 10, 8, 4, 8, 7, 8, 6, 8, 7, 13, 4, 8, 7, 8, + 5, 7, 8, 9, 6, 13, 13, 8, 4, 6, 8, 9, 5, 7, 8, 9, + 5, 9, 9, 13, 5, 7, 7, 9, 4, 7, 8, 8, 3, 5, 5, 5 + }, + { + 9, 9, 9, 9, 2, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 8, + 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, + 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8 + } +}; + +/* Interlaced CBPCY VLC tables (Table 124 - Table 131) */ +const uint16_t ff_vc1_icbpcy_p_codes[8][63] = { + { + 0x2F1A, 0x2F1B, 0x178C, 0x0090, 0x02A8, 0x02A9, 0x0BC7, 0x0091, + 0x02AA, 0x02AB, 0x05E0, 0x004A, 0x0096, 0x0097, 0x00BD, 0x0092, + 0x02AC, 0x02AD, 0x05E1, 0x0098, 0x0132, 0x0133, 0x0179, 0x0134, + 0x026A, 0x026B, 0x02FC, 0x004E, 0x0040, 0x0041, 0x002B, 0x0093, + 0x02AE, 0x02AF, 0x05E2, 0x0136, 0x026E, 0x026F, 0x02FD, 0x009E, + 0x013E, 0x013F, 0x017F, 0x0050, 0x0042, 0x0043, 0x002C, 0x0051, + 0x00A4, 0x00A5, 0x00BE, 0x0053, 0x0044, 0x0045, 0x002D, 0x0054, + 0x0046, 0x0047, 0x002E, 0x0003, 0x0000, 0x0001, 0x0001 + }, + { + 0x0041, 0x0042, 0x0100, 0x0043, 0x0088, 0x0089, 0x0101, 0x0045, + 0x008C, 0x008D, 0x0102, 0x0010, 0x0022, 0x0023, 0x0024, 0x0047, + 0x0010, 0x0011, 0x0103, 0x0025, 0x0058, 0x0059, 0x005A, 0x005B, + 0x005A, 0x005B, 0x005C, 0x000C, 0x0030, 0x0031, 0x0019, 0x0009, + 0x0014, 0x0015, 0x002C, 0x005C, 0x005D, 0x005E, 0x005F, 0x0026, + 0x005D, 0x005E, 0x005F, 0x000D, 0x0034, 0x0035, 0x001B, 0x0014, + 0x0027, 0x002A, 0x002B, 0x000E, 0x0038, 0x0039, 0x001D, 0x000F, + 0x003C, 0x003D, 0x001F, 0x0005, 0x0009, 0x0000, 0x0003 + }, + { + 0x0032, 0x0033, 0x001A, 0x0026, 0x00E4, 0x00E5, 0x01E6, 0x0027, + 0x00E6, 0x00E7, 0x01E7, 0x000E, 0x0063, 0x006C, 0x0077, 0x0028, + 0x00E8, 0x00E9, 0x01E8, 0x007B, 0x00DA, 0x00DB, 0x00EC, 0x00F5, + 0x01B8, 0x01B9, 0x01DA, 0x0021, 0x004B, 0x0054, 0x002B, 0x0029, + 0x00EA, 0x00EB, 0x01E9, 0x004A, 0x01BA, 0x01BB, 0x01DB, 0x0020, + 0x00DE, 0x00DF, 0x00F2, 0x0022, 0x0055, 0x0058, 0x002D, 0x000F, + 0x0070, 0x0071, 0x0078, 0x0023, 0x0059, 0x005C, 0x002F, 0x0024, + 0x005D, 0x0062, 0x0030, 0x0002, 0x001F, 0x0006, 0x0000 + }, + { + 0x0028, 0x0029, 0x009D, 0x0000, 0x01EA, 0x01EB, 0x01EC, 0x0001, + 0x01ED, 0x01EE, 0x01EF, 0x0005, 0x00F0, 0x00F1, 0x003B, 0x0002, + 0x01F0, 0x01F1, 0x01F2, 0x003F, 0x015C, 0x015D, 0x0099, 0x0010, + 0x03D0, 0x03D1, 0x0130, 0x000F, 0x009E, 0x009F, 0x00FB, 0x0003, + 0x01F3, 0x01F4, 0x01F5, 0x0011, 0x03D2, 0x03D3, 0x0131, 0x0009, + 0x015E, 0x015F, 0x009C, 0x0010, 0x00A8, 0x00A9, 0x0038, 0x0006, + 0x00F2, 0x00F3, 0x004D, 0x0011, 0x00AA, 0x00AB, 0x0039, 0x0012, + 0x00AC, 0x00AD, 0x003A, 0x0006, 0x0016, 0x0017, 0x000E + }, + { + 0x003C, 0x003D, 0x001F, 0x000A, 0x0061, 0x0062, 0x0002, 0x000B, + 0x0063, 0x0064, 0x0003, 0x0007, 0x0003, 0x0004, 0x000B, 0x000C, + 0x0065, 0x0066, 0x0004, 0x0012, 0x000A, 0x000B, 0x0014, 0x001B, + 0x0018, 0x0019, 0x0034, 0x002C, 0x0067, 0x0068, 0x0035, 0x000D, + 0x0069, 0x006C, 0x0005, 0x0060, 0x001A, 0x001B, 0x0035, 0x0013, + 0x000E, 0x000F, 0x0015, 0x002D, 0x006D, 0x006E, 0x0038, 0x0008, + 0x0008, 0x0009, 0x000C, 0x002E, 0x006F, 0x0072, 0x003A, 0x002F, + 0x0073, 0x0000, 0x003B, 0x0007, 0x0014, 0x0015, 0x0004 + }, + { + 0x0038, 0x0039, 0x009D, 0x000A, 0x0091, 0x0092, 0x0093, 0x000B, + 0x0094, 0x0095, 0x0096, 0x0003, 0x00EE, 0x00EF, 0x0036, 0x000C, + 0x0097, 0x0098, 0x0099, 0x0008, 0x01E4, 0x01E5, 0x006A, 0x0018, + 0x03CC, 0x03CD, 0x00D6, 0x000E, 0x009E, 0x009F, 0x00F5, 0x000D, + 0x009A, 0x009B, 0x009C, 0x0019, 0x03CE, 0x03CF, 0x00D7, 0x0009, + 0x01E8, 0x01E9, 0x0090, 0x000F, 0x00E8, 0x00E9, 0x00F6, 0x0005, + 0x00F0, 0x00F1, 0x0037, 0x0010, 0x00EA, 0x00EB, 0x00F7, 0x0011, + 0x00EC, 0x00ED, 0x0034, 0x0000, 0x003E, 0x003F, 0x0002 + }, + { + 0x003C, 0x003D, 0x01CF, 0x0000, 0x00BF, 0x00E0, 0x01FC, 0x0001, + 0x00E1, 0x00E2, 0x01FD, 0x0009, 0x01F1, 0x01F2, 0x01F3, 0x0002, + 0x00E3, 0x00E4, 0x01FE, 0x0011, 0x03EE, 0x03EF, 0x03F0, 0x0021, + 0x07E2, 0x07E3, 0x07E4, 0x0018, 0x03F7, 0x03FE, 0x03FF, 0x0003, + 0x00E5, 0x00E6, 0x0080, 0x002E, 0x07E5, 0x07E6, 0x07E7, 0x0016, + 0x03F4, 0x03F5, 0x03F6, 0x0019, 0x0102, 0x0103, 0x0104, 0x000A, + 0x01F4, 0x01F5, 0x01F6, 0x001A, 0x0105, 0x0106, 0x0107, 0x001B, + 0x0178, 0x0179, 0x01CE, 0x001D, 0x00BD, 0x00BE, 0x01F0 + }, + { + 0x0003, 0x0004, 0x01B6, 0x0004, 0x002E, 0x002F, 0x000E, 0x0005, + 0x0030, 0x0031, 0x000F, 0x0003, 0x000A, 0x000B, 0x0014, 0x0006, + 0x0032, 0x0033, 0x0010, 0x0005, 0x0030, 0x0031, 0x0032, 0x0009, + 0x0066, 0x0067, 0x0068, 0x001D, 0x01B7, 0x01B8, 0x01B9, 0x0007, + 0x0034, 0x0035, 0x0011, 0x0016, 0x0069, 0x006A, 0x006B, 0x000A, + 0x0036, 0x0037, 0x00D8, 0x001E, 0x01BA, 0x01BB, 0x01BC, 0x0004, + 0x0015, 0x0016, 0x0017, 0x001F, 0x01BD, 0x01BE, 0x01BF, 0x0000, + 0x0010, 0x0011, 0x0012, 0x001C, 0x00D9, 0x00DA, 0x0013 + } +}; + +const uint8_t ff_vc1_icbpcy_p_bits[8][63] = { + { + 15, 15, 14, 9, 11, 11, 13, 9, 11, 11, 12, 8, 9, 9, 9, 9, + 11, 11, 12, 9, 10, 10, 10, 10, 11, 11, 11, 8, 8, 8, 7, 9, + 11, 11, 12, 10, 11, 11, 11, 9, 10, 10, 10, 8, 8, 8, 7, 8, + 9, 9, 9, 8, 8, 8, 7, 8, 8, 8, 7, 3, 3, 3, 1 + }, + { + 7, 7, 9, 7, 8, 8, 9, 7, 8, 8, 9, 6, 7, 7, 7, 7, + 7, 7, 9, 7, 8, 8, 8, 8, 9, 9, 9, 6, 7, 7, 6, 6, + 7, 7, 8, 8, 9, 9, 9, 7, 8, 8, 8, 6, 7, 7, 6, 6, + 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 3, 4, 3, 2 + }, + { + 6, 6, 5, 6, 8, 8, 9, 6, 8, 8, 9, 5, 7, 7, 7, 6, + 8, 8, 9, 7, 8, 8, 8, 8, 9, 9, 9, 6, 7, 7, 6, 6, + 8, 8, 9, 7, 9, 9, 9, 6, 8, 8, 8, 6, 7, 7, 6, 5, + 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 3, 5, 4, 2 + }, + { + 6, 6, 8, 4, 9, 9, 9, 4, 9, 9, 9, 4, 8, 8, 7, 4, + 9, 9, 9, 6, 9, 9, 8, 6, 10, 10, 9, 5, 8, 8, 8, 4, + 9, 9, 9, 6, 10, 10, 9, 5, 9, 9, 8, 5, 8, 8, 7, 4, + 8, 8, 7, 5, 8, 8, 7, 5, 8, 8, 7, 3, 5, 5, 4 + }, + { + 6, 6, 5, 5, 7, 7, 7, 5, 7, 7, 7, 5, 6, 6, 6, 5, + 7, 7, 7, 6, 7, 7, 7, 7, 8, 8, 8, 6, 7, 7, 6, 5, + 7, 7, 7, 7, 8, 8, 8, 6, 7, 7, 7, 6, 7, 7, 6, 5, + 6, 6, 6, 6, 7, 7, 6, 6, 7, 6, 6, 4, 5, 5, 3 + }, + { + 6, 6, 8, 4, 8, 8, 8, 4, 8, 8, 8, 4, 8, 8, 7, 4, + 8, 8, 8, 5, 9, 9, 8, 6, 10, 10, 9, 5, 8, 8, 8, 4, + 8, 8, 8, 6, 10, 10, 9, 5, 9, 9, 8, 5, 8, 8, 8, 4, + 8, 8, 7, 5, 8, 8, 8, 5, 8, 8, 7, 3, 6, 6, 4 + }, + { + 6, 6, 9, 3, 8, 8, 9, 3, 8, 8, 9, 4, 9, 9, 9, 3, + 8, 8, 9, 5, 10, 10, 10, 6, 11, 11, 11, 5, 10, 10, 10, 3, + 8, 8, 8, 6, 11, 11, 11, 5, 10, 10, 10, 5, 9, 9, 9, 4, + 9, 9, 9, 5, 9, 9, 9, 5, 9, 9, 9, 5, 8, 8, 9 + }, + { + 6, 6, 10, 3, 7, 7, 7, 3, 7, 7, 7, 4, 8, 8, 8, 3, + 7, 7, 7, 5, 9, 9, 9, 6, 10, 10, 10, 6, 10, 10, 10, 3, + 7, 7, 7, 6, 10, 10, 10, 5, 9, 9, 9, 6, 10, 10, 10, 4, + 8, 8, 8, 6, 10, 10, 10, 5, 9, 9, 9, 6, 9, 9, 9 + } +}; + +/* MacroBlock Transform Type: 7.1.3.11, p89 + * 8x8:B + * 8x4:B:btm 8x4:B:top 8x4:B:both, + * 4x8:B:right 4x8:B:left 4x8:B:both + * 4x4:B 8x8:MB + * 8x4:MB:btm 8x4:MB:top 8x4,MB,both + * 4x8,MB,right 4x8,MB,left + * 4x4,MB */ +const uint16_t ff_vc1_ttmb_codes[3][16] = { + { + 0x0003, + 0x002E, 0x005F, 0x0000, + 0x0016, 0x0015, 0x0001, + 0x0004, 0x0014, + 0x02F1, 0x0179, 0x017B, + 0x0BC0, 0x0BC1, 0x05E1, + 0x017A + }, + { + 0x0006, + 0x0006, 0x0003, 0x0007, + 0x000F, 0x000E, 0x0000, + 0x0002, 0x0002, + 0x0014, 0x0011, 0x000B, + 0x0009, 0x0021, 0x0015, + 0x0020 + }, + { + 0x0006, + 0x0000, 0x000E, 0x0005, + 0x0002, 0x0003, 0x0003, + 0x000F, 0x0002, + 0x0081, 0x0021, 0x0009, + 0x0101, 0x0041, 0x0011, + 0x0100 + } +}; + +const uint8_t ff_vc1_ttmb_bits[3][16] = { + { + 2, + 6, 7, 2, + 5, 5, 2, + 3, 5, + 10, 9, 9, + 12, 12, 11, + 9 + }, + { + 3, + 4, 4, 4, + 4, 4, 3, + 3, 2, + 7, 7, 6, + 6, 8, 7, + 8 + }, + { + 3, + 3, 4, 5, + 3, 3, 4, + 4, 2, + 10, 8, 6, + 11, 9, 7, + 11 + } +}; + +/* TTBLK (Transform Type per Block) tables */ +const uint8_t ff_vc1_ttblk_codes[3][8] = { + { 0, 1, 3, 5, 16, 17, 18, 19 }, + { 3, 0, 1, 2, 3, 5, 8, 9 }, + { 1, 0, 1, 4, 6, 7, 10, 11 } +}; +const uint8_t ff_vc1_ttblk_bits[3][8] = { + { 2, 2, 2, 3, 5, 5, 5, 5 }, + { 2, 3, 3, 3, 3, 3, 4, 4 }, + { 2, 3, 3, 3, 3, 3, 4, 4 } +}; + +/* SUBBLKPAT tables, p93-94, reordered */ +const uint8_t ff_vc1_subblkpat_codes[3][15] = { + { 14, 12, 7, 11, 9, 26, 2, 10, 27, 8, 0, 6, 1, 15, 1 }, + { 14, 0, 8, 15, 10, 4, 23, 13, 5, 9, 25, 3, 24, 22, 1 }, + { 5, 6, 2, 2, 8, 0, 28, 3, 1, 3, 29, 1, 19, 18, 15 } +}; +const uint8_t ff_vc1_subblkpat_bits[3][15] = { + { 5, 5, 5, 5, 5, 6, 4, 5, 6, 5, 4, 5, 4, 5, 1}, + { 4, 3, 4, 4, 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 2}, + { 3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4} +}; + +/* MV differential tables, p265 */ +const uint16_t ff_vc1_mv_diff_codes[4][73] = { + { + 0, 2, 3, 8, 576, 3, 2, 6, + 5, 577, 578, 7, 8, 9, 40, 19, + 37, 82, 21, 22, 23, 579, 580, 166, + 96, 167, 49, 194, 195, 581, 582, 583, + 292, 293, 294, 13, 2, 7, 24, 50, + 102, 295, 13, 7, 8, 18, 50, 103, + 38, 20, 21, 22, 39, 204, 103, 23, + 24, 25, 104, 410, 105, 106, 107, 108, + 109, 220, 411, 442, 222, 443, 446, 447, + 7 /* 73 elements */ + }, + { + 0, 4, 5, 3, 4, 3, 4, 5, + 20, 6, 21, 44, 45, 46, 3008, 95, + 112, 113, 57, 3009, 3010, 116, 117, 3011, + 118, 3012, 3013, 3014, 3015, 3016, 3017, 3018, + 3019, 3020, 3021, 3022, 1, 4, 15, 160, + 161, 41, 6, 11, 42, 162, 43, 119, + 56, 57, 58, 163, 236, 237, 3023, 119, + 120, 242, 122, 486, 1512, 487, 246, 494, + 1513, 495, 1514, 1515, 1516, 1517, 1518, 1519, + 31 /* 73 elements */ + }, + { + 0, 512, 513, 514, 515, 2, 3, 258, + 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 1, 5, 287, 288, + 289, 290, 6, 7, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 317, 318, + 319 /* 73 elements */ + }, + { + 0, 1, 1, 2, 3, 4, 1, 5, + 4, 3, 5, 8, 6, 9, 10, 11, + 12, 7, 104, 14, 105, 4, 10, 15, + 11, 6, 14, 8, 106, 107, 108, 15, + 109, 9, 55, 10, 1, 2, 1, 2, + 3, 12, 6, 2, 6, 7, 28, 7, + 15, 8, 5, 18, 29, 152, 77, 24, + 25, 26, 39, 108, 13, 109, 55, 56, + 57, 116, 11, 153, 234, 235, 118, 119, + 15 /* 73 elements */ + } +}; +const uint8_t ff_vc1_mv_diff_bits[4][73] = { + { + 6, 7, 7, 8, 14, 6, 5, 6, 7, 14, 14, 6, 6, 6, 8, 9, + 10, 9, 7, 7, 7, 14, 14, 10, 9, 10, 8, 10, 10, 14, 14, 14, + 13, 13, 13, 6, 3, 5, 6, 8, 9, 13, 5, 4, 4, 5, 7, 9, + 6, 5, 5, 5, 6, 9, 8, 5, 5, 5, 7, 10, 7, 7, 7, 7, + 7, 8, 10, 9, 8, 9, 9, 9, 3 /* 73 elements */ + }, + { + 5, 7, 7, 6, 6, 5, 5, 6, 7, 5, 7, 8, 8, 8, 14, 9, + 9, 9, 8, 14, 14, 9, 9, 14, 9, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 2, 3, 6, 8, 8, 6, 3, 4, 6, 8, 6, 9, + 6, 6, 6, 8, 8, 8, 14, 7, 7, 8, 7, 9, 13, 9, 8, 9, + 13, 9, 13, 13, 13, 13, 13, 13, 5 /* 73 elements */ + + }, + { + 3, 12, 12, 12, 12, 3, 4, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 1, 5, 11, 11, 11, 11, 4, 4, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11 /* 73 elements */ + }, + { + 15, 11, 15, 15, 15, 15, 12, 15, 12, 11, 12, 12, 15, 12, 12, 12, + 12, 15, 15, 12, 15, 10, 11, 12, 11, 10, 11, 10, 15, 15, 15, 11, + 15, 10, 14, 10, 4, 4, 5, 7, 8, 9, 5, 3, 4, 5, 6, 8, + 5, 4, 3, 5, 6, 8, 7, 5, 5, 5, 6, 7, 9, 7, 6, 6, + 6, 7, 10, 8, 8, 8, 7, 7, 4 /* 73 elements */ + } +}; + +/* DC differentials low+hi-mo, p217 are the same as in msmpeg4data .h */ + +/* Table 232 */ +const uint8_t ff_vc1_simple_progressive_4x4_zz [16] = { + 0, 8, 16, 1, + 9, 24, 17, 2, + 10, 18, 25, 3, + 11, 26, 19, 27 +}; + +const uint8_t ff_vc1_adv_progressive_8x4_zz [32] = { /* Table 233 */ + 0, 8, 1, 16, 2, 9, 10, 3, + 24, 17, 4, 11, 18, 12, 5, 19, + 25, 13, 20, 26, 27, 6, 21, 28, + 14, 22, 29, 7, 30, 15, 23, 31 +}; + +const uint8_t ff_vc1_adv_progressive_4x8_zz [32] = { /* Table 234 */ + 0, 1, 8, 2, + 9, 16, 17, 24, + 10, 32, 25, 18, + 40, 3, 33, 26, + 48, 11, 56, 41, + 34, 49, 57, 42, + 19, 50, 27, 58, + 35, 43, 51, 59 +}; + +const uint8_t ff_vc1_adv_interlaced_8x8_zz [64] = { /* Table 235 */ + 0, 8, 1, 16, 24, 9, 2, 32, + 40, 48, 56, 17, 10, 3, 25, 18, + 11, 4, 33, 41, 49, 57, 26, 34, + 42, 50, 58, 19, 12, 5, 27, 20, + 13, 6, 35, 28, 21, 14, 7, 15, + 22, 29, 36, 43, 51, 59, 60, 52, + 44, 37, 30, 23, 31, 38, 45, 53, + 61, 62, 54, 46, 39, 47, 55, 63 +}; + +const uint8_t ff_vc1_adv_interlaced_8x4_zz [32] = { /* Table 236 */ + 0, 8, 16, 24, 1, 9, 2, 17, + 25, 10, 3, 18, 26, 4, 11, 19, + 12, 5, 13, 20, 27, 6, 21, 28, + 14, 22, 29, 7, 30, 15, 23, 31 +}; + +const uint8_t ff_vc1_adv_interlaced_4x8_zz [32] = { /* Table 237 */ + 0, 1, 2, 8, + 16, 9, 24, 17, + 10, 3, 32, 40, + 48, 56, 25, 18, + 33, 26, 41, 34, + 49, 57, 11, 42, + 19, 50, 27, 58, + 35, 43, 51, 59 +}; + +const uint8_t ff_vc1_adv_interlaced_4x4_zz [16] = { /* Table 238 */ + 0, 8, 16, 24, + 1, 9, 17, 2, + 25, 10, 18, 3, + 26, 11, 19, 27 +}; + + +/* DQScale as specified in 8.1.3.9 - almost identical to 0x40000/i */ +const int32_t ff_vc1_dqscale[63] = { + 0x40000, 0x20000, 0x15555, 0x10000, 0xCCCD, 0xAAAB, 0x9249, 0x8000, + 0x71C7, 0x6666, 0x5D17, 0x5555, 0x4EC5, 0x4925, 0x4444, 0x4000, + 0x3C3C, 0x38E4, 0x35E5, 0x3333, 0x30C3, 0x2E8C, 0x2C86, 0x2AAB, + 0x28F6, 0x2762, 0x25ED, 0x2492, 0x234F, 0x2222, 0x2108, 0x2000, + 0x1F08, 0x1E1E, 0x1D42, 0x1C72, 0x1BAD, 0x1AF3, 0x1A42, 0x199A, + 0x18FA, 0x1862, 0x17D0, 0x1746, 0x16C1, 0x1643, 0x15CA, 0x1555, + 0x14E6, 0x147B, 0x1414, 0x13B1, 0x1352, 0x12F7, 0x129E, 0x1249, + 0x11F7, 0x11A8, 0x115B, 0x1111, 0x10C9, 0x1084, 0x1000 +}; + +/* P Interlaced field picture MV predictor scaling values (Table 114) */ +const uint16_t ff_vc1_field_mvpred_scales[2][7][4] = { +// Refdist: +// 0 1 2 3 or greater + { // current field is first + { 128, 192, 213, 224 }, // SCALEOPP + { 512, 341, 307, 293 }, // SCALESAME1 + { 219, 236, 242, 245 }, // SCALESAME2 + { 32, 48, 53, 56 }, // SCALEZONE1_X + { 8, 12, 13, 14 }, // SCALEZONE1_Y + { 37, 20, 14, 11 }, // ZONE1OFFSET_X + { 10, 5, 4, 3 } // ZONE1OFFSET_Y + }, + { // current field is second + { 128, 64, 43, 32 }, // SCALEOPP + { 512, 1024, 1536, 2048 }, // SCALESAME1 + { 219, 204, 200, 198 }, // SCALESAME2 + { 32, 16, 11, 8 }, // SCALEZONE1_X + { 8, 4, 3, 2 }, // SCALEZONE1_Y + { 37, 52, 56, 58 }, // ZONE1OFFSET_X + { 10, 13, 14, 15 } // ZONE1OFFSET_Y + } +}; + +/* B Interlaced field picture backward MV predictor scaling values for first field (Table 115) */ +const uint16_t ff_vc1_b_field_mvpred_scales[7][4] = { + // BRFD: + // 0 1 2 3 or greater + { 171, 205, 219, 228 }, // SCALESAME + { 384, 320, 299, 288 }, // SCALEOPP1 + { 230, 239, 244, 246 }, // SCALEOPP2 + { 43, 51, 55, 57 }, // SCALEZONE1_X + { 11, 13, 14, 14 }, // SCALEZONE1_Y + { 26, 17, 12, 10 }, // ZONE1OFFSET_X + { 7, 4, 3, 3 } // ZONE1OFFSET_Y +}; + +const int ff_vc1_ac_sizes[AC_MODES] = { + 186, 169, 133, 149, 103, 103, 163, 175 +}; diff --git a/ffmpeg/libavcodec/vc1data.h b/ffmpeg/libavcodec/vc1data.h new file mode 100644 index 0000000..eecb045 --- /dev/null +++ b/ffmpeg/libavcodec/vc1data.h @@ -0,0 +1,208 @@ +/* + * VC-1 and WMV3 decoder + * copyright (c) 2006 Konstantin Shishkov + * (c) 2005 anonymous, Alex Beregszaszi, 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 + */ + +/** + * @file + * VC-1 tables. + */ + +#ifndef AVCODEC_VC1DATA_H +#define AVCODEC_VC1DATA_H + +#include +#include "libavutil/rational.h" +#include "get_bits.h" + +/** Table for conversion between TTBLK and TTMB */ +extern const int ff_vc1_ttblk_to_tt[3][8]; + +extern const int ff_vc1_ttfrm_to_tt[4]; + +/** MV P mode - the 5th element is only used for mode 1 */ +extern const uint8_t ff_vc1_mv_pmode_table[2][5]; +extern const uint8_t ff_vc1_mv_pmode_table2[2][4]; + +extern const int ff_vc1_fps_nr[7], ff_vc1_fps_dr[2]; +extern const uint8_t ff_vc1_pquant_table[3][32]; + +/* MBMODE table for interlaced frame P-picture */ +extern const uint8_t ff_vc1_mbmode_intfrp[2][15][4]; + +/** @name VC-1 VLC tables and defines + * @todo TODO move this into the context + */ +//@{ +#define VC1_BFRACTION_VLC_BITS 7 +extern VLC ff_vc1_bfraction_vlc; +#define VC1_IMODE_VLC_BITS 4 +extern VLC ff_vc1_imode_vlc; +#define VC1_NORM2_VLC_BITS 3 +extern VLC ff_vc1_norm2_vlc; +#define VC1_NORM6_VLC_BITS 9 +extern VLC ff_vc1_norm6_vlc; +/* Could be optimized, one table only needs 8 bits */ +#define VC1_TTMB_VLC_BITS 9 //12 +extern VLC ff_vc1_ttmb_vlc[3]; +#define VC1_MV_DIFF_VLC_BITS 9 //15 +extern VLC ff_vc1_mv_diff_vlc[4]; +#define VC1_CBPCY_P_VLC_BITS 9 //14 +extern VLC ff_vc1_cbpcy_p_vlc[4]; +#define VC1_ICBPCY_VLC_BITS 9 +extern VLC ff_vc1_icbpcy_vlc[8]; +#define VC1_4MV_BLOCK_PATTERN_VLC_BITS 6 +extern VLC ff_vc1_4mv_block_pattern_vlc[4]; +#define VC1_2MV_BLOCK_PATTERN_VLC_BITS 3 +extern VLC ff_vc1_2mv_block_pattern_vlc[4]; +#define VC1_TTBLK_VLC_BITS 5 +extern VLC ff_vc1_ttblk_vlc[3]; +#define VC1_SUBBLKPAT_VLC_BITS 6 +extern VLC ff_vc1_subblkpat_vlc[3]; +#define VC1_INTFR_4MV_MBMODE_VLC_BITS 9 +extern VLC ff_vc1_intfr_4mv_mbmode_vlc[4]; +#define VC1_INTFR_NON4MV_MBMODE_VLC_BITS 6 +extern VLC ff_vc1_intfr_non4mv_mbmode_vlc[4]; +#define VC1_IF_MMV_MBMODE_VLC_BITS 5 +extern VLC ff_vc1_if_mmv_mbmode_vlc[8]; +#define VC1_IF_1MV_MBMODE_VLC_BITS 5 +extern VLC ff_vc1_if_1mv_mbmode_vlc[8]; +#define VC1_1REF_MVDATA_VLC_BITS 9 +extern VLC ff_vc1_1ref_mvdata_vlc[4]; +#define VC1_2REF_MVDATA_VLC_BITS 9 +extern VLC ff_vc1_2ref_mvdata_vlc[8]; + +extern VLC ff_vc1_ac_coeff_table[8]; + +#define VC1_IF_MBMODE_VLC_BITS 5 +//@} + + +/* Denominator used for ff_vc1_bfraction_lut */ +#define B_FRACTION_DEN 256 + +/* pre-computed scales for all bfractions and base=256 */ +extern const int16_t ff_vc1_bfraction_lut[23]; +extern const uint8_t ff_vc1_bfraction_bits[23]; +extern const uint8_t ff_vc1_bfraction_codes[23]; + +//Same as H.264 +extern const AVRational ff_vc1_pixel_aspect[16]; + +/* BitPlane IMODE - such a small table... */ +extern const uint8_t ff_vc1_imode_codes[7]; +extern const uint8_t ff_vc1_imode_bits[7]; + +/* Normal-2 imode */ +extern const uint8_t ff_vc1_norm2_codes[4]; +extern const uint8_t ff_vc1_norm2_bits[4]; +extern const uint16_t ff_vc1_norm6_codes[64]; +extern const uint8_t ff_vc1_norm6_bits[64]; +/* Normal-6 imode */ +extern const uint8_t ff_vc1_norm6_spec[64][5]; + +/* 4MV Block pattern VLC tables */ +extern const uint8_t ff_vc1_4mv_block_pattern_codes[4][16]; +extern const uint8_t ff_vc1_4mv_block_pattern_bits[4][16]; + +/* 2MV Block pattern VLC tables */ +extern const uint8_t ff_vc1_2mv_block_pattern_codes[4][4]; +extern const uint8_t ff_vc1_2mv_block_pattern_bits[4][4]; + +extern const uint8_t ff_wmv3_dc_scale_table[32]; + +/* P-Picture CBPCY VLC tables */ +extern const uint16_t ff_vc1_cbpcy_p_codes[4][64]; +extern const uint8_t ff_vc1_cbpcy_p_bits[4][64]; + +/* Interlaced CBPCY VLC tables (Table 124 - Table 131) */ +extern const uint16_t ff_vc1_icbpcy_p_codes[8][63]; +extern const uint8_t ff_vc1_icbpcy_p_bits[8][63]; + +/* MacroBlock Transform Type: 7.1.3.11, p89 + * 8x8:B + * 8x4:B:btm 8x4:B:top 8x4:B:both, + * 4x8:B:right 4x8:B:left 4x8:B:both + * 4x4:B 8x8:MB + * 8x4:MB:btm 8x4:MB:top 8x4,MB,both + * 4x8,MB,right 4x8,MB,left + * 4x4,MB */ +extern const uint16_t ff_vc1_ttmb_codes[3][16]; + +extern const uint8_t ff_vc1_ttmb_bits[3][16]; + +/* TTBLK (Transform Type per Block) tables */ +extern const uint8_t ff_vc1_ttblk_codes[3][8]; +extern const uint8_t ff_vc1_ttblk_bits[3][8]; + +/* SUBBLKPAT tables, p93-94, reordered */ +extern const uint8_t ff_vc1_subblkpat_codes[3][15]; +extern const uint8_t ff_vc1_subblkpat_bits[3][15]; + +/* MV differential tables, p265 */ +extern const uint16_t ff_vc1_mv_diff_codes[4][73]; +extern const uint8_t ff_vc1_mv_diff_bits[4][73]; + +/* Interlaced frame picture MBMODE VLC tables (p. 246, p. 360) */ +extern const uint16_t ff_vc1_intfr_4mv_mbmode_codes[4][15]; +extern const uint8_t ff_vc1_intfr_4mv_mbmode_bits[4][15]; +extern const uint8_t ff_vc1_intfr_non4mv_mbmode_codes[4][9]; +extern const uint8_t ff_vc1_intfr_non4mv_mbmode_bits[4][9]; + +/* Interlaced field picture MBMODE VLC tables (p. 356 - 11.4.1, 11.4.2) */ +extern const uint8_t ff_vc1_if_mmv_mbmode_codes[8][8]; +extern const uint8_t ff_vc1_if_mmv_mbmode_bits[8][8]; +extern const uint8_t ff_vc1_if_1mv_mbmode_codes[8][6]; +extern const uint8_t ff_vc1_if_1mv_mbmode_bits[8][6]; + +/* Interlaced frame/field picture MVDATA VLC tables */ +/* 1-reference tables */ +extern const uint32_t ff_vc1_1ref_mvdata_codes[4][72]; +extern const uint8_t ff_vc1_1ref_mvdata_bits[4][72]; +/* 2-reference tables */ +extern const uint32_t ff_vc1_2ref_mvdata_codes[8][126]; +extern const uint8_t ff_vc1_2ref_mvdata_bits[8][126]; + +/* DC differentials low+hi-mo, p217 are the same as in msmpeg4data .h */ + +/* Scantables/ZZ scan are at 11.9 (p262) and 8.1.1.12 (p10) */ +extern const uint8_t ff_vc1_simple_progressive_4x4_zz [16]; +extern const uint8_t ff_vc1_adv_progressive_8x4_zz [32]; +extern const uint8_t ff_vc1_adv_progressive_4x8_zz [32]; +extern const uint8_t ff_vc1_adv_interlaced_8x8_zz [64]; +extern const uint8_t ff_vc1_adv_interlaced_8x4_zz [32]; +extern const uint8_t ff_vc1_adv_interlaced_4x8_zz [32]; +extern const uint8_t ff_vc1_adv_interlaced_4x4_zz [16]; +extern const uint8_t ff_vc1_intra_horz_8x8_zz [64]; +extern const uint8_t ff_vc1_intra_vert_8x8_zz [64]; + +/* DQScale as specified in 8.1.3.9 - almost identical to 0x40000/i */ +extern const int32_t ff_vc1_dqscale[63]; + +/* P Interlaced field picture MV predictor scaling values (Table 114) */ +extern const uint16_t ff_vc1_field_mvpred_scales[2][7][4]; +/* B Interlaced field picture backward MV predictor scaling values for first field (Table 115) */ +extern const uint16_t ff_vc1_b_field_mvpred_scales[7][4]; + +#define AC_MODES 8 + +extern const int ff_vc1_ac_sizes[AC_MODES]; + +#endif /* AVCODEC_VC1DATA_H */ diff --git a/ffmpeg/libavcodec/vc1dec.c b/ffmpeg/libavcodec/vc1dec.c new file mode 100644 index 0000000..6451f0c --- /dev/null +++ b/ffmpeg/libavcodec/vc1dec.c @@ -0,0 +1,6266 @@ +/* + * VC-1 and WMV3 decoder + * Copyright (c) 2011 Mashiat Sarker Shakkhar + * Copyright (c) 2006-2007 Konstantin Shishkov + * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, 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 + */ + +/** + * @file + * VC-1 and WMV3 decoder + */ + +#include "internal.h" +#include "avcodec.h" +#include "error_resilience.h" +#include "mpegvideo.h" +#include "h263.h" +#include "h264chroma.h" +#include "vc1.h" +#include "vc1data.h" +#include "vc1acdata.h" +#include "msmpeg4data.h" +#include "unary.h" +#include "mathops.h" +#include "vdpau_internal.h" +#include "libavutil/avassert.h" + +#undef NDEBUG +#include + +#define MB_INTRA_VLC_BITS 9 +#define DC_VLC_BITS 9 + + +// offset tables for interlaced picture MVDATA decoding +static const int offset_table1[9] = { 0, 1, 2, 4, 8, 16, 32, 64, 128 }; +static const int offset_table2[9] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 }; + +/***********************************************************************/ +/** + * @name VC-1 Bitplane decoding + * @see 8.7, p56 + * @{ + */ + +/** + * Imode types + * @{ + */ +enum Imode { + IMODE_RAW, + IMODE_NORM2, + IMODE_DIFF2, + IMODE_NORM6, + IMODE_DIFF6, + IMODE_ROWSKIP, + IMODE_COLSKIP +}; +/** @} */ //imode defines + +static void init_block_index(VC1Context *v) +{ + MpegEncContext *s = &v->s; + ff_init_block_index(s); + if (v->field_mode && v->second_field) { + s->dest[0] += s->current_picture_ptr->f.linesize[0]; + s->dest[1] += s->current_picture_ptr->f.linesize[1]; + s->dest[2] += s->current_picture_ptr->f.linesize[2]; + } +} + + +/** @} */ //Bitplane group + +static void vc1_put_signed_blocks_clamped(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int topleft_mb_pos, top_mb_pos; + int stride_y, fieldtx = 0; + int v_dist; + + /* The put pixels loop is always one MB row behind the decoding loop, + * because we can only put pixels when overlap filtering is done, and + * for filtering of the bottom edge of a MB, we need the next MB row + * present as well. + * Within the row, the put pixels loop is also one MB col behind the + * decoding loop. The reason for this is again, because for filtering + * of the right MB edge, we need the next MB present. */ + if (!s->first_slice_line) { + if (s->mb_x) { + topleft_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x - 1; + if (v->fcm == ILACE_FRAME) + fieldtx = v->fieldtx_plane[topleft_mb_pos]; + stride_y = s->linesize << fieldtx; + v_dist = (16 - fieldtx) >> (fieldtx == 0); + s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][0], + s->dest[0] - 16 * s->linesize - 16, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][1], + s->dest[0] - 16 * s->linesize - 8, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][2], + s->dest[0] - v_dist * s->linesize - 16, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][3], + s->dest[0] - v_dist * s->linesize - 8, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][4], + s->dest[1] - 8 * s->uvlinesize - 8, + s->uvlinesize); + s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][5], + s->dest[2] - 8 * s->uvlinesize - 8, + s->uvlinesize); + } + if (s->mb_x == s->mb_width - 1) { + top_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x; + if (v->fcm == ILACE_FRAME) + fieldtx = v->fieldtx_plane[top_mb_pos]; + stride_y = s->linesize << fieldtx; + v_dist = fieldtx ? 15 : 8; + s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][0], + s->dest[0] - 16 * s->linesize, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][1], + s->dest[0] - 16 * s->linesize + 8, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][2], + s->dest[0] - v_dist * s->linesize, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][3], + s->dest[0] - v_dist * s->linesize + 8, + stride_y); + s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][4], + s->dest[1] - 8 * s->uvlinesize, + s->uvlinesize); + s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][5], + s->dest[2] - 8 * s->uvlinesize, + s->uvlinesize); + } + } + +#define inc_blk_idx(idx) do { \ + idx++; \ + if (idx >= v->n_allocated_blks) \ + idx = 0; \ + } while (0) + + inc_blk_idx(v->topleft_blk_idx); + inc_blk_idx(v->top_blk_idx); + inc_blk_idx(v->left_blk_idx); + inc_blk_idx(v->cur_blk_idx); +} + +static void vc1_loop_filter_iblk(VC1Context *v, int pq) +{ + MpegEncContext *s = &v->s; + int j; + if (!s->first_slice_line) { + v->vc1dsp.vc1_v_loop_filter16(s->dest[0], s->linesize, pq); + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq); + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1], s->uvlinesize, pq); + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); + } + } + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] + 8 * s->linesize, s->linesize, pq); + + if (s->mb_y == s->end_mb_y - 1) { + if (s->mb_x) { + v->vc1dsp.vc1_h_loop_filter16(s->dest[0], s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter8(s->dest[1], s->uvlinesize, pq); + v->vc1dsp.vc1_h_loop_filter8(s->dest[2], s->uvlinesize, pq); + } + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] + 8, s->linesize, pq); + } +} + +static void vc1_loop_filter_iblk_delayed(VC1Context *v, int pq) +{ + MpegEncContext *s = &v->s; + int j; + + /* The loopfilter runs 1 row and 1 column behind the overlap filter, which + * means it runs two rows/cols behind the decoding loop. */ + if (!s->first_slice_line) { + if (s->mb_x) { + if (s->mb_y >= s->start_mb_y + 2) { + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); + + if (s->mb_x >= 2) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 16, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize - 8, s->linesize, pq); + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq); + if (s->mb_x >= 2) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize - 8, s->uvlinesize, pq); + } + } + } + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize - 16, s->linesize, pq); + } + + if (s->mb_x == s->mb_width - 1) { + if (s->mb_y >= s->start_mb_y + 2) { + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); + + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 32 * s->linesize + 8, s->linesize, pq); + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_v_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); + if (s->mb_x >= 2) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 16 * s->uvlinesize, s->uvlinesize, pq); + } + } + } + v->vc1dsp.vc1_v_loop_filter16(s->dest[0] - 8 * s->linesize, s->linesize, pq); + } + + if (s->mb_y == s->end_mb_y) { + if (s->mb_x) { + if (s->mb_x >= 2) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 16, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize - 8, s->linesize, pq); + if (s->mb_x >= 2) { + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize - 8, s->uvlinesize, pq); + } + } + } + + if (s->mb_x == s->mb_width - 1) { + if (s->mb_x) + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize, s->linesize, pq); + v->vc1dsp.vc1_h_loop_filter16(s->dest[0] - 16 * s->linesize + 8, s->linesize, pq); + if (s->mb_x) { + for (j = 0; j < 2; j++) { + v->vc1dsp.vc1_h_loop_filter8(s->dest[j + 1] - 8 * s->uvlinesize, s->uvlinesize, pq); + } + } + } + } + } +} + +static void vc1_smooth_overlap_filter_iblk(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int mb_pos; + + if (v->condover == CONDOVER_NONE) + return; + + mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + /* Within a MB, the horizontal overlap always runs before the vertical. + * To accomplish that, we run the H on left and internal borders of the + * currently decoded MB. Then, we wait for the next overlap iteration + * to do H overlap on the right edge of this MB, before moving over and + * running the V overlap. Therefore, the V overlap makes us trail by one + * MB col and the H overlap filter makes us trail by one MB row. This + * is reflected in the time at which we run the put_pixels loop. */ + if (v->condover == CONDOVER_ALL || v->pq >= 9 || v->over_flags_plane[mb_pos]) { + if (s->mb_x && (v->condover == CONDOVER_ALL || v->pq >= 9 || + v->over_flags_plane[mb_pos - 1])) { + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][1], + v->block[v->cur_blk_idx][0]); + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][3], + v->block[v->cur_blk_idx][2]); + if (!(s->flags & CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][4], + v->block[v->cur_blk_idx][4]); + v->vc1dsp.vc1_h_s_overlap(v->block[v->left_blk_idx][5], + v->block[v->cur_blk_idx][5]); + } + } + v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][0], + v->block[v->cur_blk_idx][1]); + v->vc1dsp.vc1_h_s_overlap(v->block[v->cur_blk_idx][2], + v->block[v->cur_blk_idx][3]); + + if (s->mb_x == s->mb_width - 1) { + if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 || + v->over_flags_plane[mb_pos - s->mb_stride])) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][2], + v->block[v->cur_blk_idx][0]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][3], + v->block[v->cur_blk_idx][1]); + if (!(s->flags & CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][4], + v->block[v->cur_blk_idx][4]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->top_blk_idx][5], + v->block[v->cur_blk_idx][5]); + } + } + v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][0], + v->block[v->cur_blk_idx][2]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->cur_blk_idx][1], + v->block[v->cur_blk_idx][3]); + } + } + if (s->mb_x && (v->condover == CONDOVER_ALL || v->over_flags_plane[mb_pos - 1])) { + if (!s->first_slice_line && (v->condover == CONDOVER_ALL || v->pq >= 9 || + v->over_flags_plane[mb_pos - s->mb_stride - 1])) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][2], + v->block[v->left_blk_idx][0]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][3], + v->block[v->left_blk_idx][1]); + if (!(s->flags & CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][4], + v->block[v->left_blk_idx][4]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->topleft_blk_idx][5], + v->block[v->left_blk_idx][5]); + } + } + v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][0], + v->block[v->left_blk_idx][2]); + v->vc1dsp.vc1_v_s_overlap(v->block[v->left_blk_idx][1], + v->block[v->left_blk_idx][3]); + } +} + +/** Do motion compensation over 1 macroblock + * Mostly adapted hpel_motion and qpel_motion from mpegvideo.c + */ +static void vc1_mc_1mv(VC1Context *v, int dir) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcY, *srcU, *srcV; + int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; + int off, off_uv; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + int i; + + if ((!v->field_mode || + (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && + !v->s.last_picture.f.data[0]) + return; + + mx = s->mv[dir][0][0]; + my = s->mv[dir][0][1]; + + // store motion vectors for further use in B frames + if (s->pict_type == AV_PICTURE_TYPE_P) { + for (i = 0; i < 4; i++) { + s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx; + s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][1] = my; + } + } + + uvmx = (mx + ((mx & 3) == 3)) >> 1; + uvmy = (my + ((my & 3) == 3)) >> 1; + v->luma_mv[s->mb_x][0] = uvmx; + v->luma_mv[s->mb_x][1] = uvmy; + + if (v->field_mode && + v->cur_field_type != v->ref_field_type[dir]) { + my = my - 2 + 4 * v->cur_field_type; + uvmy = uvmy - 2 + 4 * v->cur_field_type; + } + + // fastuvmc shall be ignored for interlaced frame picture + if (v->fastuvmc && (v->fcm != ILACE_FRAME)) { + uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); + uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); + } + if (v->field_mode) { // interlaced field picture + if (!dir) { + if ((v->cur_field_type != v->ref_field_type[dir]) && v->second_field) { + srcY = s->current_picture.f.data[0]; + srcU = s->current_picture.f.data[1]; + srcV = s->current_picture.f.data[2]; + } else { + srcY = s->last_picture.f.data[0]; + srcU = s->last_picture.f.data[1]; + srcV = s->last_picture.f.data[2]; + } + } else { + srcY = s->next_picture.f.data[0]; + srcU = s->next_picture.f.data[1]; + srcV = s->next_picture.f.data[2]; + } + } else { + if (!dir) { + srcY = s->last_picture.f.data[0]; + srcU = s->last_picture.f.data[1]; + srcV = s->last_picture.f.data[2]; + } else { + srcY = s->next_picture.f.data[0]; + srcU = s->next_picture.f.data[1]; + srcV = s->next_picture.f.data[2]; + } + } + + if(!srcY) + return; + + src_x = s->mb_x * 16 + (mx >> 2); + src_y = s->mb_y * 16 + (my >> 2); + uvsrc_x = s->mb_x * 8 + (uvmx >> 2); + uvsrc_y = s->mb_y * 8 + (uvmy >> 2); + + if (v->profile != PROFILE_ADVANCED) { + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + } else { + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + + srcY += src_y * s->linesize + src_x; + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + + if (v->field_mode && v->ref_field_type[dir]) { + srcY += s->current_picture_ptr->f.linesize[0]; + srcU += s->current_picture_ptr->f.linesize[1]; + srcV += s->current_picture_ptr->f.linesize[2]; + } + + /* for grayscale we should not try to read from unknown area */ + if (s->flags & CODEC_FLAG_GRAY) { + srcU = s->edge_emu_buffer + 18 * s->linesize; + srcV = s->edge_emu_buffer + 18 * s->linesize; + } + + if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 22 || v_edge_pos < 22 + || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 + || (unsigned)(src_y - 1) > v_edge_pos - (my&3) - 16 - 3) { + uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; + + srcY -= s->mspel * (1 + s->linesize); + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize, + 17 + s->mspel * 2, 17 + s->mspel * 2, + src_x - s->mspel, src_y - s->mspel, + s->h_edge_pos, v_edge_pos); + srcY = s->edge_emu_buffer; + s->vdsp.emulated_edge_mc(uvbuf , srcU, s->uvlinesize, 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, s->uvlinesize, 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + srcU = uvbuf; + srcV = uvbuf + 16; + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = ((src[i] - 128) >> 1) + 128; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = ((src[i] - 128) >> 1) + 128; + src2[i] = ((src2[i] - 128) >> 1) + 128; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + /* if we deal with intensity compensation we need to scale source blocks */ + if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = v->luty[src[i]]; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = v->lutuv[src[i]]; + src2[i] = v->lutuv[src2[i]]; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + srcY += s->mspel * (1 + s->linesize); + } + + off = 0; + off_uv = 0; + if (s->mspel) { + dxy = ((my & 3) << 2) | (mx & 3); + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off , srcY , s->linesize, v->rnd); + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8, srcY + 8, s->linesize, v->rnd); + srcY += s->linesize * 8; + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize , srcY , s->linesize, v->rnd); + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize + 8, srcY + 8, s->linesize, v->rnd); + } else { // hpel mc - always used for luma + dxy = (my & 2) | ((mx & 2) >> 1); + if (!v->rnd) + s->hdsp.put_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16); + else + s->hdsp.put_no_rnd_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16); + } + + if (s->flags & CODEC_FLAG_GRAY) return; + /* Chroma MC always uses qpel bilinear */ + uvmx = (uvmx & 3) << 1; + uvmy = (uvmy & 3) << 1; + if (!v->rnd) { + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); + } else { + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); + } +} + +static inline int median4(int a, int b, int c, int d) +{ + if (a < b) { + if (c < d) return (FFMIN(b, d) + FFMAX(a, c)) / 2; + else return (FFMIN(b, c) + FFMAX(a, d)) / 2; + } else { + if (c < d) return (FFMIN(a, d) + FFMAX(b, c)) / 2; + else return (FFMIN(a, c) + FFMAX(b, d)) / 2; + } +} + +/** Do motion compensation for 4-MV macroblock - luminance block + */ +static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) +{ + MpegEncContext *s = &v->s; + uint8_t *srcY; + int dxy, mx, my, src_x, src_y; + int off; + int fieldmv = (v->fcm == ILACE_FRAME) ? v->blk_mv_type[s->block_index[n]] : 0; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + + if ((!v->field_mode || + (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && + !v->s.last_picture.f.data[0]) + return; + + mx = s->mv[dir][n][0]; + my = s->mv[dir][n][1]; + + if (!dir) { + if (v->field_mode) { + if ((v->cur_field_type != v->ref_field_type[dir]) && v->second_field) + srcY = s->current_picture.f.data[0]; + else + srcY = s->last_picture.f.data[0]; + } else + srcY = s->last_picture.f.data[0]; + } else + srcY = s->next_picture.f.data[0]; + + if(!srcY) + return; + + if (v->field_mode) { + if (v->cur_field_type != v->ref_field_type[dir]) + my = my - 2 + 4 * v->cur_field_type; + } + + if (s->pict_type == AV_PICTURE_TYPE_P && n == 3 && v->field_mode) { + int same_count = 0, opp_count = 0, k; + int chosen_mv[2][4][2], f; + int tx, ty; + for (k = 0; k < 4; k++) { + f = v->mv_f[0][s->block_index[k] + v->blocks_off]; + chosen_mv[f][f ? opp_count : same_count][0] = s->mv[0][k][0]; + chosen_mv[f][f ? opp_count : same_count][1] = s->mv[0][k][1]; + opp_count += f; + same_count += 1 - f; + } + f = opp_count > same_count; + switch (f ? opp_count : same_count) { + case 4: + tx = median4(chosen_mv[f][0][0], chosen_mv[f][1][0], + chosen_mv[f][2][0], chosen_mv[f][3][0]); + ty = median4(chosen_mv[f][0][1], chosen_mv[f][1][1], + chosen_mv[f][2][1], chosen_mv[f][3][1]); + break; + case 3: + tx = mid_pred(chosen_mv[f][0][0], chosen_mv[f][1][0], chosen_mv[f][2][0]); + ty = mid_pred(chosen_mv[f][0][1], chosen_mv[f][1][1], chosen_mv[f][2][1]); + break; + case 2: + tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2; + ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2; + break; + default: + av_assert2(0); + } + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; + for (k = 0; k < 4; k++) + v->mv_f[1][s->block_index[k] + v->blocks_off] = f; + } + + if (v->fcm == ILACE_FRAME) { // not sure if needed for other types of picture + int qx, qy; + int width = s->avctx->coded_width; + int height = s->avctx->coded_height >> 1; + if (s->pict_type == AV_PICTURE_TYPE_P) { + s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][0] = mx; + s->current_picture.motion_val[1][s->block_index[n] + v->blocks_off][1] = my; + } + qx = (s->mb_x * 16) + (mx >> 2); + qy = (s->mb_y * 8) + (my >> 3); + + if (qx < -17) + mx -= 4 * (qx + 17); + else if (qx > width) + mx -= 4 * (qx - width); + if (qy < -18) + my -= 8 * (qy + 18); + else if (qy > height + 1) + my -= 8 * (qy - height - 1); + } + + if ((v->fcm == ILACE_FRAME) && fieldmv) + off = ((n > 1) ? s->linesize : 0) + (n & 1) * 8; + else + off = s->linesize * 4 * (n & 2) + (n & 1) * 8; + + src_x = s->mb_x * 16 + (n & 1) * 8 + (mx >> 2); + if (!fieldmv) + src_y = s->mb_y * 16 + (n & 2) * 4 + (my >> 2); + else + src_y = s->mb_y * 16 + ((n > 1) ? 1 : 0) + (my >> 2); + + if (v->profile != PROFILE_ADVANCED) { + src_x = av_clip(src_x, -16, s->mb_width * 16); + src_y = av_clip(src_y, -16, s->mb_height * 16); + } else { + src_x = av_clip(src_x, -17, s->avctx->coded_width); + if (v->fcm == ILACE_FRAME) { + if (src_y & 1) + src_y = av_clip(src_y, -17, s->avctx->coded_height + 1); + else + src_y = av_clip(src_y, -18, s->avctx->coded_height); + } else { + src_y = av_clip(src_y, -18, s->avctx->coded_height + 1); + } + } + + srcY += src_y * s->linesize + src_x; + if (v->field_mode && v->ref_field_type[dir]) + srcY += s->current_picture_ptr->f.linesize[0]; + + if (fieldmv && !(src_y & 1)) + v_edge_pos--; + if (fieldmv && (src_y & 1) && src_y < 4) + src_y--; + if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 13 || v_edge_pos < 23 + || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2 + || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { + srcY -= s->mspel * (1 + (s->linesize << fieldmv)); + /* check emulate edge stride and offset */ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize, + 9 + s->mspel * 2, (9 + s->mspel * 2) << fieldmv, + src_x - s->mspel, src_y - (s->mspel << fieldmv), + s->h_edge_pos, v_edge_pos); + srcY = s->edge_emu_buffer; + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src; + + src = srcY; + for (j = 0; j < 9 + s->mspel * 2; j++) { + for (i = 0; i < 9 + s->mspel * 2; i++) + src[i] = ((src[i] - 128) >> 1) + 128; + src += s->linesize << fieldmv; + } + } + /* if we deal with intensity compensation we need to scale source blocks */ + if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + int i, j; + uint8_t *src; + + src = srcY; + for (j = 0; j < 9 + s->mspel * 2; j++) { + for (i = 0; i < 9 + s->mspel * 2; i++) + src[i] = v->luty[src[i]]; + src += s->linesize << fieldmv; + } + } + srcY += s->mspel * (1 + (s->linesize << fieldmv)); + } + + if (s->mspel) { + dxy = ((my & 3) << 2) | (mx & 3); + if (avg) + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); + else + v->vc1dsp.put_vc1_mspel_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize << fieldmv, v->rnd); + } else { // hpel mc - always used for luma + dxy = (my & 2) | ((mx & 2) >> 1); + if (!v->rnd) + s->hdsp.put_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8); + else + s->hdsp.put_no_rnd_pixels_tab[1][dxy](s->dest[0] + off, srcY, s->linesize, 8); + } +} + +static av_always_inline int get_chroma_mv(int *mvx, int *mvy, int *a, int flag, int *tx, int *ty) +{ + int idx, i; + static const int count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; + + idx = ((a[3] != flag) << 3) + | ((a[2] != flag) << 2) + | ((a[1] != flag) << 1) + | (a[0] != flag); + if (!idx) { + *tx = median4(mvx[0], mvx[1], mvx[2], mvx[3]); + *ty = median4(mvy[0], mvy[1], mvy[2], mvy[3]); + return 4; + } else if (count[idx] == 1) { + switch (idx) { + case 0x1: + *tx = mid_pred(mvx[1], mvx[2], mvx[3]); + *ty = mid_pred(mvy[1], mvy[2], mvy[3]); + return 3; + case 0x2: + *tx = mid_pred(mvx[0], mvx[2], mvx[3]); + *ty = mid_pred(mvy[0], mvy[2], mvy[3]); + return 3; + case 0x4: + *tx = mid_pred(mvx[0], mvx[1], mvx[3]); + *ty = mid_pred(mvy[0], mvy[1], mvy[3]); + return 3; + case 0x8: + *tx = mid_pred(mvx[0], mvx[1], mvx[2]); + *ty = mid_pred(mvy[0], mvy[1], mvy[2]); + return 3; + } + } else if (count[idx] == 2) { + int t1 = 0, t2 = 0; + for (i = 0; i < 3; i++) + if (!a[i]) { + t1 = i; + break; + } + for (i = t1 + 1; i < 4; i++) + if (!a[i]) { + t2 = i; + break; + } + *tx = (mvx[t1] + mvx[t2]) / 2; + *ty = (mvy[t1] + mvy[t2]) / 2; + return 2; + } else { + return 0; + } + return -1; +} + +/** Do motion compensation for 4-MV macroblock - both chroma blocks + */ +static void vc1_mc_4mv_chroma(VC1Context *v, int dir) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcU, *srcV; + int uvmx, uvmy, uvsrc_x, uvsrc_y; + int k, tx = 0, ty = 0; + int mvx[4], mvy[4], intra[4], mv_f[4]; + int valid_count; + int chroma_ref_type = v->cur_field_type, off = 0; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + + if (!v->field_mode && !v->s.last_picture.f.data[0]) + return; + if (s->flags & CODEC_FLAG_GRAY) + return; + + for (k = 0; k < 4; k++) { + mvx[k] = s->mv[dir][k][0]; + mvy[k] = s->mv[dir][k][1]; + intra[k] = v->mb_type[0][s->block_index[k]]; + if (v->field_mode) + mv_f[k] = v->mv_f[dir][s->block_index[k] + v->blocks_off]; + } + + /* calculate chroma MV vector from four luma MVs */ + if (!v->field_mode || (v->field_mode && !v->numref)) { + valid_count = get_chroma_mv(mvx, mvy, intra, 0, &tx, &ty); + chroma_ref_type = v->reffield; + if (!valid_count) { + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; + v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; + return; //no need to do MC for intra blocks + } + } else { + int dominant = 0; + if (mv_f[0] + mv_f[1] + mv_f[2] + mv_f[3] > 2) + dominant = 1; + valid_count = get_chroma_mv(mvx, mvy, mv_f, dominant, &tx, &ty); + if (dominant) + chroma_ref_type = !v->cur_field_type; + } + if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f.data[0]) + return; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; + uvmx = (tx + ((tx & 3) == 3)) >> 1; + uvmy = (ty + ((ty & 3) == 3)) >> 1; + + v->luma_mv[s->mb_x][0] = uvmx; + v->luma_mv[s->mb_x][1] = uvmy; + + if (v->fastuvmc) { + uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1)); + uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1)); + } + // Field conversion bias + if (v->cur_field_type != chroma_ref_type) + uvmy += 2 - 4 * chroma_ref_type; + + uvsrc_x = s->mb_x * 8 + (uvmx >> 2); + uvsrc_y = s->mb_y * 8 + (uvmy >> 2); + + if (v->profile != PROFILE_ADVANCED) { + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + } else { + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + + if (!dir) { + if (v->field_mode) { + if ((v->cur_field_type != chroma_ref_type) && v->cur_field_type) { + srcU = s->current_picture.f.data[1]; + srcV = s->current_picture.f.data[2]; + } else { + srcU = s->last_picture.f.data[1]; + srcV = s->last_picture.f.data[2]; + } + } else { + srcU = s->last_picture.f.data[1]; + srcV = s->last_picture.f.data[2]; + } + } else { + srcU = s->next_picture.f.data[1]; + srcV = s->next_picture.f.data[2]; + } + + if(!srcU) + return; + + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + + if (v->field_mode) { + if (chroma_ref_type) { + srcU += s->current_picture_ptr->f.linesize[1]; + srcV += s->current_picture_ptr->f.linesize[2]; + } + off = 0; + } + + if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 18 || v_edge_pos < 18 + || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9 + || (unsigned)uvsrc_y > (v_edge_pos >> 1) - 9) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer , srcU, s->uvlinesize, + 8 + 1, 8 + 1, uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(s->edge_emu_buffer + 16, srcV, s->uvlinesize, + 8 + 1, 8 + 1, uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos >> 1); + srcU = s->edge_emu_buffer; + srcV = s->edge_emu_buffer + 16; + + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src, *src2; + + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = ((src[i] - 128) >> 1) + 128; + src2[i] = ((src2[i] - 128) >> 1) + 128; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + /* if we deal with intensity compensation we need to scale source blocks */ + if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + int i, j; + uint8_t *src, *src2; + + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = v->lutuv[src[i]]; + src2[i] = v->lutuv[src2[i]]; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + } + + /* Chroma MC always uses qpel bilinear */ + uvmx = (uvmx & 3) << 1; + uvmy = (uvmy & 3) << 1; + if (!v->rnd) { + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[1] + off, srcU, s->uvlinesize, 8, uvmx, uvmy); + h264chroma->put_h264_chroma_pixels_tab[0](s->dest[2] + off, srcV, s->uvlinesize, 8, uvmx, uvmy); + } else { + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off, srcU, s->uvlinesize, 8, uvmx, uvmy); + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off, srcV, s->uvlinesize, 8, uvmx, uvmy); + } +} + +/** Do motion compensation for 4-MV field chroma macroblock (both U and V) + */ +static void vc1_mc_4mv_chroma4(VC1Context *v) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcU, *srcV; + int uvsrc_x, uvsrc_y; + int uvmx_field[4], uvmy_field[4]; + int i, off, tx, ty; + int fieldmv = v->blk_mv_type[s->block_index[0]]; + static const int s_rndtblfield[16] = { 0, 0, 1, 2, 4, 4, 5, 6, 2, 2, 3, 8, 6, 6, 7, 12 }; + int v_dist = fieldmv ? 1 : 4; // vertical offset for lower sub-blocks + int v_edge_pos = s->v_edge_pos >> 1; + + if (!v->s.last_picture.f.data[0]) + return; + if (s->flags & CODEC_FLAG_GRAY) + return; + + for (i = 0; i < 4; i++) { + tx = s->mv[0][i][0]; + uvmx_field[i] = (tx + ((tx & 3) == 3)) >> 1; + ty = s->mv[0][i][1]; + if (fieldmv) + uvmy_field[i] = (ty >> 4) * 8 + s_rndtblfield[ty & 0xF]; + else + uvmy_field[i] = (ty + ((ty & 3) == 3)) >> 1; + } + + for (i = 0; i < 4; i++) { + off = (i & 1) * 4 + ((i & 2) ? v_dist * s->uvlinesize : 0); + uvsrc_x = s->mb_x * 8 + (i & 1) * 4 + (uvmx_field[i] >> 2); + uvsrc_y = s->mb_y * 8 + ((i & 2) ? v_dist : 0) + (uvmy_field[i] >> 2); + // FIXME: implement proper pull-back (see vc1cropmv.c, vc1CROPMV_ChromaPullBack()) + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; + srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; + uvmx_field[i] = (uvmx_field[i] & 3) << 1; + uvmy_field[i] = (uvmy_field[i] & 3) << 1; + + if (fieldmv && !(uvsrc_y & 1)) + v_edge_pos = (s->v_edge_pos >> 1) - 1; + + if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) + uvsrc_y--; + if ((v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv) + || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5 + || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcU, s->uvlinesize, + 5, (5 << fieldmv), uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos); + s->vdsp.emulated_edge_mc(s->edge_emu_buffer + 16, srcV, s->uvlinesize, + 5, (5 << fieldmv), uvsrc_x, uvsrc_y, + s->h_edge_pos >> 1, v_edge_pos); + srcU = s->edge_emu_buffer; + srcV = s->edge_emu_buffer + 16; + + /* if we deal with intensity compensation we need to scale source blocks */ + if (v->mv_mode == MV_PMODE_INTENSITY_COMP) { + int i, j; + uint8_t *src, *src2; + + src = srcU; + src2 = srcV; + for (j = 0; j < 5; j++) { + for (i = 0; i < 5; i++) { + src[i] = v->lutuv[src[i]]; + src2[i] = v->lutuv[src2[i]]; + } + src += s->uvlinesize << 1; + src2 += s->uvlinesize << 1; + } + } + } + if (!v->rnd) { + h264chroma->put_h264_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + h264chroma->put_h264_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } else { + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[1] + off, srcU, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + v->vc1dsp.put_no_rnd_vc1_chroma_pixels_tab[1](s->dest[2] + off, srcV, s->uvlinesize << fieldmv, 4, uvmx_field[i], uvmy_field[i]); + } + } +} + +/***********************************************************************/ +/** + * @name VC-1 Block-level functions + * @see 7.1.4, p91 and 8.1.1.7, p(1)04 + * @{ + */ + +/** + * @def GET_MQUANT + * @brief Get macroblock-level quantizer scale + */ +#define GET_MQUANT() \ + if (v->dquantfrm) { \ + int edges = 0; \ + if (v->dqprofile == DQPROFILE_ALL_MBS) { \ + if (v->dqbilevel) { \ + mquant = (get_bits1(gb)) ? v->altpq : v->pq; \ + } else { \ + mqdiff = get_bits(gb, 3); \ + if (mqdiff != 7) \ + mquant = v->pq + mqdiff; \ + else \ + mquant = get_bits(gb, 5); \ + } \ + } \ + if (v->dqprofile == DQPROFILE_SINGLE_EDGE) \ + edges = 1 << v->dqsbedge; \ + else if (v->dqprofile == DQPROFILE_DOUBLE_EDGES) \ + edges = (3 << v->dqsbedge) % 15; \ + else if (v->dqprofile == DQPROFILE_FOUR_EDGES) \ + edges = 15; \ + if ((edges&1) && !s->mb_x) \ + mquant = v->altpq; \ + if ((edges&2) && s->first_slice_line) \ + mquant = v->altpq; \ + if ((edges&4) && s->mb_x == (s->mb_width - 1)) \ + mquant = v->altpq; \ + if ((edges&8) && s->mb_y == (s->mb_height - 1)) \ + mquant = v->altpq; \ + if (!mquant || mquant > 31) { \ + av_log(v->s.avctx, AV_LOG_ERROR, \ + "Overriding invalid mquant %d\n", mquant); \ + mquant = 1; \ + } \ + } + +/** + * @def GET_MVDATA(_dmv_x, _dmv_y) + * @brief Get MV differentials + * @see MVDATA decoding from 8.3.5.2, p(1)20 + * @param _dmv_x Horizontal differential for decoded MV + * @param _dmv_y Vertical differential for decoded MV + */ +#define GET_MVDATA(_dmv_x, _dmv_y) \ + index = 1 + get_vlc2(gb, ff_vc1_mv_diff_vlc[s->mv_table_index].table, \ + VC1_MV_DIFF_VLC_BITS, 2); \ + if (index > 36) { \ + mb_has_coeffs = 1; \ + index -= 37; \ + } else \ + mb_has_coeffs = 0; \ + s->mb_intra = 0; \ + if (!index) { \ + _dmv_x = _dmv_y = 0; \ + } else if (index == 35) { \ + _dmv_x = get_bits(gb, v->k_x - 1 + s->quarter_sample); \ + _dmv_y = get_bits(gb, v->k_y - 1 + s->quarter_sample); \ + } else if (index == 36) { \ + _dmv_x = 0; \ + _dmv_y = 0; \ + s->mb_intra = 1; \ + } else { \ + index1 = index % 6; \ + if (!s->quarter_sample && index1 == 5) val = 1; \ + else val = 0; \ + if (size_table[index1] - val > 0) \ + val = get_bits(gb, size_table[index1] - val); \ + else val = 0; \ + sign = 0 - (val&1); \ + _dmv_x = (sign ^ ((val>>1) + offset_table[index1])) - sign; \ + \ + index1 = index / 6; \ + if (!s->quarter_sample && index1 == 5) val = 1; \ + else val = 0; \ + if (size_table[index1] - val > 0) \ + val = get_bits(gb, size_table[index1] - val); \ + else val = 0; \ + sign = 0 - (val & 1); \ + _dmv_y = (sign ^ ((val >> 1) + offset_table[index1])) - sign; \ + } + +static av_always_inline void get_mvdata_interlaced(VC1Context *v, int *dmv_x, + int *dmv_y, int *pred_flag) +{ + int index, index1; + int extend_x = 0, extend_y = 0; + GetBitContext *gb = &v->s.gb; + int bits, esc; + int val, sign; + const int* offs_tab; + + if (v->numref) { + bits = VC1_2REF_MVDATA_VLC_BITS; + esc = 125; + } else { + bits = VC1_1REF_MVDATA_VLC_BITS; + esc = 71; + } + switch (v->dmvrange) { + case 1: + extend_x = 1; + break; + case 2: + extend_y = 1; + break; + case 3: + extend_x = extend_y = 1; + break; + } + index = get_vlc2(gb, v->imv_vlc->table, bits, 3); + if (index == esc) { + *dmv_x = get_bits(gb, v->k_x); + *dmv_y = get_bits(gb, v->k_y); + if (v->numref) { + if (pred_flag) { + *pred_flag = *dmv_y & 1; + *dmv_y = (*dmv_y + *pred_flag) >> 1; + } else { + *dmv_y = (*dmv_y + (*dmv_y & 1)) >> 1; + } + } + } + else { + av_assert0(index < esc); + if (extend_x) + offs_tab = offset_table2; + else + offs_tab = offset_table1; + index1 = (index + 1) % 9; + if (index1 != 0) { + val = get_bits(gb, index1 + extend_x); + sign = 0 -(val & 1); + *dmv_x = (sign ^ ((val >> 1) + offs_tab[index1])) - sign; + } else + *dmv_x = 0; + if (extend_y) + offs_tab = offset_table2; + else + offs_tab = offset_table1; + index1 = (index + 1) / 9; + if (index1 > v->numref) { + val = get_bits(gb, (index1 + (extend_y << v->numref)) >> v->numref); + sign = 0 - (val & 1); + *dmv_y = (sign ^ ((val >> 1) + offs_tab[index1 >> v->numref])) - sign; + } else + *dmv_y = 0; + if (v->numref && pred_flag) + *pred_flag = index1 & 1; + } +} + +static av_always_inline int scaleforsame_x(VC1Context *v, int n /* MV */, int dir) +{ + int scaledvalue, refdist; + int scalesame1, scalesame2; + int scalezone1_x, zone1offset_x; + int table_index = dir ^ v->second_field; + + if (v->s.pict_type != AV_PICTURE_TYPE_B) + refdist = v->refdist; + else + refdist = dir ? v->brfd : v->frfd; + if (refdist > 3) + refdist = 3; + scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist]; + scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist]; + scalezone1_x = ff_vc1_field_mvpred_scales[table_index][3][refdist]; + zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist]; + + if (FFABS(n) > 255) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_x) + scaledvalue = (n * scalesame1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x; + else + scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x; + } + } + return av_clip(scaledvalue, -v->range_x, v->range_x - 1); +} + +static av_always_inline int scaleforsame_y(VC1Context *v, int i, int n /* MV */, int dir) +{ + int scaledvalue, refdist; + int scalesame1, scalesame2; + int scalezone1_y, zone1offset_y; + int table_index = dir ^ v->second_field; + + if (v->s.pict_type != AV_PICTURE_TYPE_B) + refdist = v->refdist; + else + refdist = dir ? v->brfd : v->frfd; + if (refdist > 3) + refdist = 3; + scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist]; + scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist]; + scalezone1_y = ff_vc1_field_mvpred_scales[table_index][4][refdist]; + zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist]; + + if (FFABS(n) > 63) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_y) + scaledvalue = (n * scalesame1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y; + else + scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y; + } + } + + if (v->cur_field_type && !v->ref_field_type[dir]) + return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2); + else + return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1); +} + +static av_always_inline int scaleforopp_x(VC1Context *v, int n /* MV */) +{ + int scalezone1_x, zone1offset_x; + int scaleopp1, scaleopp2, brfd; + int scaledvalue; + + brfd = FFMIN(v->brfd, 3); + scalezone1_x = ff_vc1_b_field_mvpred_scales[3][brfd]; + zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd]; + scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd]; + scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd]; + + if (FFABS(n) > 255) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_x) + scaledvalue = (n * scaleopp1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x; + else + scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x; + } + } + return av_clip(scaledvalue, -v->range_x, v->range_x - 1); +} + +static av_always_inline int scaleforopp_y(VC1Context *v, int n /* MV */, int dir) +{ + int scalezone1_y, zone1offset_y; + int scaleopp1, scaleopp2, brfd; + int scaledvalue; + + brfd = FFMIN(v->brfd, 3); + scalezone1_y = ff_vc1_b_field_mvpred_scales[4][brfd]; + zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd]; + scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd]; + scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd]; + + if (FFABS(n) > 63) + scaledvalue = n; + else { + if (FFABS(n) < scalezone1_y) + scaledvalue = (n * scaleopp1) >> 8; + else { + if (n < 0) + scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y; + else + scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y; + } + } + if (v->cur_field_type && !v->ref_field_type[dir]) { + return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2); + } else { + return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1); + } +} + +static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */, + int dim, int dir) +{ + int brfd, scalesame; + int hpel = 1 - v->s.quarter_sample; + + n >>= hpel; + if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) { + if (dim) + n = scaleforsame_y(v, i, n, dir) << hpel; + else + n = scaleforsame_x(v, n, dir) << hpel; + return n; + } + brfd = FFMIN(v->brfd, 3); + scalesame = ff_vc1_b_field_mvpred_scales[0][brfd]; + + n = (n * scalesame >> 8) << hpel; + return n; +} + +static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */, + int dim, int dir) +{ + int refdist, scaleopp; + int hpel = 1 - v->s.quarter_sample; + + n >>= hpel; + if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) { + if (dim) + n = scaleforopp_y(v, n, dir) << hpel; + else + n = scaleforopp_x(v, n) << hpel; + return n; + } + if (v->s.pict_type != AV_PICTURE_TYPE_B) + refdist = FFMIN(v->refdist, 3); + else + refdist = dir ? v->brfd : v->frfd; + scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist]; + + n = (n * scaleopp >> 8) << hpel; + return n; +} + +/** Predict and set motion vector + */ +static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, + int mv1, int r_x, int r_y, uint8_t* is_intra, + int pred_flag, int dir) +{ + MpegEncContext *s = &v->s; + int xy, wrap, off = 0; + int16_t *A, *B, *C; + int px, py; + int sum; + int mixedmv_pic, num_samefield = 0, num_oppfield = 0; + int opposite, a_f, b_f, c_f; + int16_t field_predA[2]; + int16_t field_predB[2]; + int16_t field_predC[2]; + int a_valid, b_valid, c_valid; + int hybridmv_thresh, y_bias = 0; + + if (v->mv_mode == MV_PMODE_MIXED_MV || + ((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == MV_PMODE_MIXED_MV))) + mixedmv_pic = 1; + else + mixedmv_pic = 0; + /* scale MV difference to be quad-pel */ + dmv_x <<= 1 - s->quarter_sample; + dmv_y <<= 1 - s->quarter_sample; + + wrap = s->b8_stride; + xy = s->block_index[n]; + + if (s->mb_intra) { + s->mv[0][n][0] = s->current_picture.motion_val[0][xy + v->blocks_off][0] = 0; + s->mv[0][n][1] = s->current_picture.motion_val[0][xy + v->blocks_off][1] = 0; + s->current_picture.motion_val[1][xy + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; + if (mv1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[0][xy + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[0][xy + 1 + v->blocks_off][1] = 0; + s->current_picture.motion_val[0][xy + wrap + v->blocks_off][0] = 0; + s->current_picture.motion_val[0][xy + wrap + v->blocks_off][1] = 0; + s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[0][xy + wrap + 1 + v->blocks_off][1] = 0; + v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; + s->current_picture.motion_val[1][xy + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][xy + 1 + v->blocks_off][1] = 0; + s->current_picture.motion_val[1][xy + wrap][0] = 0; + s->current_picture.motion_val[1][xy + wrap + v->blocks_off][1] = 0; + s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][xy + wrap + 1 + v->blocks_off][1] = 0; + } + return; + } + + C = s->current_picture.motion_val[dir][xy - 1 + v->blocks_off]; + A = s->current_picture.motion_val[dir][xy - wrap + v->blocks_off]; + if (mv1) { + if (v->field_mode && mixedmv_pic) + off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; + else + off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2; + } else { + //in 4-MV mode different blocks have different B predictor position + switch (n) { + case 0: + off = (s->mb_x > 0) ? -1 : 1; + break; + case 1: + off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1; + break; + case 2: + off = 1; + break; + case 3: + off = -1; + } + } + B = s->current_picture.motion_val[dir][xy - wrap + off + v->blocks_off]; + + a_valid = !s->first_slice_line || (n == 2 || n == 3); + b_valid = a_valid && (s->mb_width > 1); + c_valid = s->mb_x || (n == 1 || n == 3); + if (v->field_mode) { + a_valid = a_valid && !is_intra[xy - wrap]; + b_valid = b_valid && !is_intra[xy - wrap + off]; + c_valid = c_valid && !is_intra[xy - 1]; + } + + if (a_valid) { + a_f = v->mv_f[dir][xy - wrap + v->blocks_off]; + num_oppfield += a_f; + num_samefield += 1 - a_f; + field_predA[0] = A[0]; + field_predA[1] = A[1]; + } else { + field_predA[0] = field_predA[1] = 0; + a_f = 0; + } + if (b_valid) { + b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; + num_oppfield += b_f; + num_samefield += 1 - b_f; + field_predB[0] = B[0]; + field_predB[1] = B[1]; + } else { + field_predB[0] = field_predB[1] = 0; + b_f = 0; + } + if (c_valid) { + c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; + num_oppfield += c_f; + num_samefield += 1 - c_f; + field_predC[0] = C[0]; + field_predC[1] = C[1]; + } else { + field_predC[0] = field_predC[1] = 0; + c_f = 0; + } + + if (v->field_mode) { + if (!v->numref) + // REFFIELD determines if the last field or the second-last field is + // to be used as reference + opposite = 1 - v->reffield; + else { + if (num_samefield <= num_oppfield) + opposite = 1 - pred_flag; + else + opposite = pred_flag; + } + } else + opposite = 0; + if (opposite) { + if (a_valid && !a_f) { + field_predA[0] = scaleforopp(v, field_predA[0], 0, dir); + field_predA[1] = scaleforopp(v, field_predA[1], 1, dir); + } + if (b_valid && !b_f) { + field_predB[0] = scaleforopp(v, field_predB[0], 0, dir); + field_predB[1] = scaleforopp(v, field_predB[1], 1, dir); + } + if (c_valid && !c_f) { + field_predC[0] = scaleforopp(v, field_predC[0], 0, dir); + field_predC[1] = scaleforopp(v, field_predC[1], 1, dir); + } + v->mv_f[dir][xy + v->blocks_off] = 1; + v->ref_field_type[dir] = !v->cur_field_type; + } else { + if (a_valid && a_f) { + field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir); + field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir); + } + if (b_valid && b_f) { + field_predB[0] = scaleforsame(v, n, field_predB[0], 0, dir); + field_predB[1] = scaleforsame(v, n, field_predB[1], 1, dir); + } + if (c_valid && c_f) { + field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir); + field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir); + } + v->mv_f[dir][xy + v->blocks_off] = 0; + v->ref_field_type[dir] = v->cur_field_type; + } + + if (a_valid) { + px = field_predA[0]; + py = field_predA[1]; + } else if (c_valid) { + px = field_predC[0]; + py = field_predC[1]; + } else if (b_valid) { + px = field_predB[0]; + py = field_predB[1]; + } else { + px = 0; + py = 0; + } + + if (num_samefield + num_oppfield > 1) { + px = mid_pred(field_predA[0], field_predB[0], field_predC[0]); + py = mid_pred(field_predA[1], field_predB[1], field_predC[1]); + } + + /* Pullback MV as specified in 8.3.5.3.4 */ + if (!v->field_mode) { + int qx, qy, X, Y; + qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0); + qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0); + X = (s->mb_width << 6) - 4; + Y = (s->mb_height << 6) - 4; + if (mv1) { + if (qx + px < -60) px = -60 - qx; + if (qy + py < -60) py = -60 - qy; + } else { + if (qx + px < -28) px = -28 - qx; + if (qy + py < -28) py = -28 - qy; + } + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } + + if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) { + /* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 10.3.5.4.3.5) */ + hybridmv_thresh = 32; + if (a_valid && c_valid) { + if (is_intra[xy - wrap]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]); + if (sum > hybridmv_thresh) { + if (get_bits1(&s->gb)) { // read HYBRIDPRED bit + px = field_predA[0]; + py = field_predA[1]; + } else { + px = field_predC[0]; + py = field_predC[1]; + } + } else { + if (is_intra[xy - 1]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - field_predC[0]) + FFABS(py - field_predC[1]); + if (sum > hybridmv_thresh) { + if (get_bits1(&s->gb)) { + px = field_predA[0]; + py = field_predA[1]; + } else { + px = field_predC[0]; + py = field_predC[1]; + } + } + } + } + } + + if (v->field_mode && v->numref) + r_y >>= 1; + if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0) + y_bias = 1; + /* store MV using signed modulus of MV range defined in 4.11 */ + s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1] = ((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + y_bias; + if (mv1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[dir][xy + 1 + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; + s->current_picture.motion_val[dir][xy + 1 + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; + s->current_picture.motion_val[dir][xy + wrap + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; + s->current_picture.motion_val[dir][xy + wrap + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; + s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] = s->current_picture.motion_val[dir][xy + v->blocks_off][0]; + s->current_picture.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] = s->current_picture.motion_val[dir][xy + v->blocks_off][1]; + v->mv_f[dir][xy + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off]; + v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off]; + } +} + +/** Predict and set motion vector for interlaced frame picture MBs + */ +static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, + int mvn, int r_x, int r_y, uint8_t* is_intra, int dir) +{ + MpegEncContext *s = &v->s; + int xy, wrap, off = 0; + int A[2], B[2], C[2]; + int px, py; + int a_valid = 0, b_valid = 0, c_valid = 0; + int field_a, field_b, field_c; // 0: same, 1: opposit + int total_valid, num_samefield, num_oppfield; + int pos_c, pos_b, n_adj; + + wrap = s->b8_stride; + xy = s->block_index[n]; + + if (s->mb_intra) { + s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0; + s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0; + s->current_picture.motion_val[1][xy][0] = 0; + s->current_picture.motion_val[1][xy][1] = 0; + if (mvn == 1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[0][xy + 1][0] = 0; + s->current_picture.motion_val[0][xy + 1][1] = 0; + s->current_picture.motion_val[0][xy + wrap][0] = 0; + s->current_picture.motion_val[0][xy + wrap][1] = 0; + s->current_picture.motion_val[0][xy + wrap + 1][0] = 0; + s->current_picture.motion_val[0][xy + wrap + 1][1] = 0; + v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; + s->current_picture.motion_val[1][xy + 1][0] = 0; + s->current_picture.motion_val[1][xy + 1][1] = 0; + s->current_picture.motion_val[1][xy + wrap][0] = 0; + s->current_picture.motion_val[1][xy + wrap][1] = 0; + s->current_picture.motion_val[1][xy + wrap + 1][0] = 0; + s->current_picture.motion_val[1][xy + wrap + 1][1] = 0; + } + return; + } + + off = ((n == 0) || (n == 1)) ? 1 : -1; + /* predict A */ + if (s->mb_x || (n == 1) || (n == 3)) { + if ((v->blk_mv_type[xy]) // current block (MB) has a field MV + || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV + A[0] = s->current_picture.motion_val[dir][xy - 1][0]; + A[1] = s->current_picture.motion_val[dir][xy - 1][1]; + a_valid = 1; + } else { // current block has frame mv and cand. has field MV (so average) + A[0] = (s->current_picture.motion_val[dir][xy - 1][0] + + s->current_picture.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1; + A[1] = (s->current_picture.motion_val[dir][xy - 1][1] + + s->current_picture.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1; + a_valid = 1; + } + if (!(n & 1) && v->is_intra[s->mb_x - 1]) { + a_valid = 0; + A[0] = A[1] = 0; + } + } else + A[0] = A[1] = 0; + /* Predict B and C */ + B[0] = B[1] = C[0] = C[1] = 0; + if (n == 0 || n == 1 || v->blk_mv_type[xy]) { + if (!s->first_slice_line) { + if (!v->is_intra[s->mb_x - s->mb_stride]) { + b_valid = 1; + n_adj = n | 2; + pos_b = s->block_index[n_adj] - 2 * wrap; + if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) { + n_adj = (n & 2) | (n & 1); + } + B[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0]; + B[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1]; + if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) { + B[0] = (B[0] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1; + B[1] = (B[1] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1; + } + } + if (s->mb_width > 1) { + if (!v->is_intra[s->mb_x - s->mb_stride + 1]) { + c_valid = 1; + n_adj = 2; + pos_c = s->block_index[2] - 2 * wrap + 2; + if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { + n_adj = n & 2; + } + C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0]; + C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1]; + if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { + C[0] = (1 + C[0] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1; + C[1] = (1 + C[1] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1; + } + if (s->mb_x == s->mb_width - 1) { + if (!v->is_intra[s->mb_x - s->mb_stride - 1]) { + c_valid = 1; + n_adj = 3; + pos_c = s->block_index[3] - 2 * wrap - 2; + if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) { + n_adj = n | 1; + } + C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0]; + C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1]; + if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) { + C[0] = (1 + C[0] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1; + C[1] = (1 + C[1] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1; + } + } else + c_valid = 0; + } + } + } + } + } else { + pos_b = s->block_index[1]; + b_valid = 1; + B[0] = s->current_picture.motion_val[dir][pos_b][0]; + B[1] = s->current_picture.motion_val[dir][pos_b][1]; + pos_c = s->block_index[0]; + c_valid = 1; + C[0] = s->current_picture.motion_val[dir][pos_c][0]; + C[1] = s->current_picture.motion_val[dir][pos_c][1]; + } + + total_valid = a_valid + b_valid + c_valid; + // check if predictor A is out of bounds + if (!s->mb_x && !(n == 1 || n == 3)) { + A[0] = A[1] = 0; + } + // check if predictor B is out of bounds + if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && !(n & 2))) { + B[0] = B[1] = C[0] = C[1] = 0; + } + if (!v->blk_mv_type[xy]) { + if (s->mb_width == 1) { + px = B[0]; + py = B[1]; + } else { + if (total_valid >= 2) { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } else if (total_valid) { + if (a_valid) { px = A[0]; py = A[1]; } + else if (b_valid) { px = B[0]; py = B[1]; } + else if (c_valid) { px = C[0]; py = C[1]; } + else av_assert2(0); + } else + px = py = 0; + } + } else { + if (a_valid) + field_a = (A[1] & 4) ? 1 : 0; + else + field_a = 0; + if (b_valid) + field_b = (B[1] & 4) ? 1 : 0; + else + field_b = 0; + if (c_valid) + field_c = (C[1] & 4) ? 1 : 0; + else + field_c = 0; + + num_oppfield = field_a + field_b + field_c; + num_samefield = total_valid - num_oppfield; + if (total_valid == 3) { + if ((num_samefield == 3) || (num_oppfield == 3)) { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } else if (num_samefield >= num_oppfield) { + /* take one MV from same field set depending on priority + the check for B may not be necessary */ + px = !field_a ? A[0] : B[0]; + py = !field_a ? A[1] : B[1]; + } else { + px = field_a ? A[0] : B[0]; + py = field_a ? A[1] : B[1]; + } + } else if (total_valid == 2) { + if (num_samefield >= num_oppfield) { + if (!field_a && a_valid) { + px = A[0]; + py = A[1]; + } else if (!field_b && b_valid) { + px = B[0]; + py = B[1]; + } else if (c_valid) { + px = C[0]; + py = C[1]; + } else px = py = 0; + } else { + if (field_a && a_valid) { + px = A[0]; + py = A[1]; + } else if (field_b && b_valid) { + px = B[0]; + py = B[1]; + } else if (c_valid) { + px = C[0]; + py = C[1]; + } else px = py = 0; + } + } else if (total_valid == 1) { + px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]); + py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]); + } else + px = py = 0; + } + + /* store MV using signed modulus of MV range defined in 4.11 */ + s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y; + if (mvn == 1) { /* duplicate motion data for 1-MV block */ + s->current_picture.motion_val[dir][xy + 1 ][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + 1 ][1] = s->current_picture.motion_val[dir][xy][1]; + s->current_picture.motion_val[dir][xy + wrap ][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + wrap ][1] = s->current_picture.motion_val[dir][xy][1]; + s->current_picture.motion_val[dir][xy + wrap + 1][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + wrap + 1][1] = s->current_picture.motion_val[dir][xy][1]; + } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */ + s->current_picture.motion_val[dir][xy + 1][0] = s->current_picture.motion_val[dir][xy][0]; + s->current_picture.motion_val[dir][xy + 1][1] = s->current_picture.motion_val[dir][xy][1]; + s->mv[dir][n + 1][0] = s->mv[dir][n][0]; + s->mv[dir][n + 1][1] = s->mv[dir][n][1]; + } +} + +/** Motion compensation for direct or interpolated blocks in B-frames + */ +static void vc1_interp_mc(VC1Context *v) +{ + MpegEncContext *s = &v->s; + H264ChromaContext *h264chroma = &v->h264chroma; + uint8_t *srcY, *srcU, *srcV; + int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; + int off, off_uv; + int v_edge_pos = s->v_edge_pos >> v->field_mode; + + if (!v->field_mode && !v->s.next_picture.f.data[0]) + return; + + mx = s->mv[1][0][0]; + my = s->mv[1][0][1]; + uvmx = (mx + ((mx & 3) == 3)) >> 1; + uvmy = (my + ((my & 3) == 3)) >> 1; + if (v->field_mode) { + if (v->cur_field_type != v->ref_field_type[1]) + my = my - 2 + 4 * v->cur_field_type; + uvmy = uvmy - 2 + 4 * v->cur_field_type; + } + if (v->fastuvmc) { + uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1)); + uvmy = uvmy + ((uvmy < 0) ? -(uvmy & 1) : (uvmy & 1)); + } + srcY = s->next_picture.f.data[0]; + srcU = s->next_picture.f.data[1]; + srcV = s->next_picture.f.data[2]; + + src_x = s->mb_x * 16 + (mx >> 2); + src_y = s->mb_y * 16 + (my >> 2); + uvsrc_x = s->mb_x * 8 + (uvmx >> 2); + uvsrc_y = s->mb_y * 8 + (uvmy >> 2); + + if (v->profile != PROFILE_ADVANCED) { + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + } else { + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + + srcY += src_y * s->linesize + src_x; + srcU += uvsrc_y * s->uvlinesize + uvsrc_x; + srcV += uvsrc_y * s->uvlinesize + uvsrc_x; + + if (v->field_mode && v->ref_field_type[1]) { + srcY += s->current_picture_ptr->f.linesize[0]; + srcU += s->current_picture_ptr->f.linesize[1]; + srcV += s->current_picture_ptr->f.linesize[2]; + } + + /* for grayscale we should not try to read from unknown area */ + if (s->flags & CODEC_FLAG_GRAY) { + srcU = s->edge_emu_buffer + 18 * s->linesize; + srcV = s->edge_emu_buffer + 18 * s->linesize; + } + + if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 + || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3 + || (unsigned)(src_y - 1) > v_edge_pos - (my & 3) - 16 - 3) { + uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; + + srcY -= s->mspel * (1 + s->linesize); + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize, + 17 + s->mspel * 2, 17 + s->mspel * 2, + src_x - s->mspel, src_y - s->mspel, + s->h_edge_pos, v_edge_pos); + srcY = s->edge_emu_buffer; + s->vdsp.emulated_edge_mc(uvbuf , srcU, s->uvlinesize, 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, s->uvlinesize, 8 + 1, 8 + 1, + uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1); + srcU = uvbuf; + srcV = uvbuf + 16; + /* if we deal with range reduction we need to scale source blocks */ + if (v->rangeredfrm) { + int i, j; + uint8_t *src, *src2; + + src = srcY; + for (j = 0; j < 17 + s->mspel * 2; j++) { + for (i = 0; i < 17 + s->mspel * 2; i++) + src[i] = ((src[i] - 128) >> 1) + 128; + src += s->linesize; + } + src = srcU; + src2 = srcV; + for (j = 0; j < 9; j++) { + for (i = 0; i < 9; i++) { + src[i] = ((src[i] - 128) >> 1) + 128; + src2[i] = ((src2[i] - 128) >> 1) + 128; + } + src += s->uvlinesize; + src2 += s->uvlinesize; + } + } + srcY += s->mspel * (1 + s->linesize); + } + + off = 0; + off_uv = 0; + + if (s->mspel) { + dxy = ((my & 3) << 2) | (mx & 3); + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off , srcY , s->linesize, v->rnd); + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8, srcY + 8, s->linesize, v->rnd); + srcY += s->linesize * 8; + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize , srcY , s->linesize, v->rnd); + v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize + 8, srcY + 8, s->linesize, v->rnd); + } else { // hpel mc + dxy = (my & 2) | ((mx & 2) >> 1); + + if (!v->rnd) + s->hdsp.avg_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16); + else + s->hdsp.avg_no_rnd_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize, 16); + } + + if (s->flags & CODEC_FLAG_GRAY) return; + /* Chroma MC always uses qpel blilinear */ + uvmx = (uvmx & 3) << 1; + uvmy = (uvmy & 3) << 1; + if (!v->rnd) { + h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); + h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); + } else { + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy); + v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy); + } +} + +static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs) +{ + int n = bfrac; + +#if B_FRACTION_DEN==256 + if (inv) + n -= 256; + if (!qs) + return 2 * ((value * n + 255) >> 9); + return (value * n + 128) >> 8; +#else + if (inv) + n -= B_FRACTION_DEN; + if (!qs) + return 2 * ((value * n + B_FRACTION_DEN - 1) / (2 * B_FRACTION_DEN)); + return (value * n + B_FRACTION_DEN/2) / B_FRACTION_DEN; +#endif +} + +/** Reconstruct motion vector for B-frame and do motion compensation + */ +static inline void vc1_b_mc(VC1Context *v, int dmv_x[2], int dmv_y[2], + int direct, int mode) +{ + if (v->use_ic) { + v->mv_mode2 = v->mv_mode; + v->mv_mode = MV_PMODE_INTENSITY_COMP; + } + if (direct) { + vc1_mc_1mv(v, 0); + vc1_interp_mc(v); + if (v->use_ic) + v->mv_mode = v->mv_mode2; + return; + } + if (mode == BMV_TYPE_INTERPOLATED) { + vc1_mc_1mv(v, 0); + vc1_interp_mc(v); + if (v->use_ic) + v->mv_mode = v->mv_mode2; + return; + } + + if (v->use_ic && (mode == BMV_TYPE_BACKWARD)) + v->mv_mode = v->mv_mode2; + vc1_mc_1mv(v, (mode == BMV_TYPE_BACKWARD)); + if (v->use_ic) + v->mv_mode = v->mv_mode2; +} + +static inline void vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], + int direct, int mvtype) +{ + MpegEncContext *s = &v->s; + int xy, wrap, off = 0; + int16_t *A, *B, *C; + int px, py; + int sum; + int r_x, r_y; + const uint8_t *is_intra = v->mb_type[0]; + + r_x = v->range_x; + r_y = v->range_y; + /* scale MV difference to be quad-pel */ + dmv_x[0] <<= 1 - s->quarter_sample; + dmv_y[0] <<= 1 - s->quarter_sample; + dmv_x[1] <<= 1 - s->quarter_sample; + dmv_y[1] <<= 1 - s->quarter_sample; + + wrap = s->b8_stride; + xy = s->block_index[0]; + + if (s->mb_intra) { + s->current_picture.motion_val[0][xy + v->blocks_off][0] = + s->current_picture.motion_val[0][xy + v->blocks_off][1] = + s->current_picture.motion_val[1][xy + v->blocks_off][0] = + s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0; + return; + } + if (!v->field_mode) { + s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 1, s->quarter_sample); + + /* Pullback predicted motion vectors as specified in 8.4.5.4 */ + s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); + s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); + s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6)); + s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6)); + } + if (direct) { + s->current_picture.motion_val[0][xy + v->blocks_off][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][xy + v->blocks_off][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][xy + v->blocks_off][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][xy + v->blocks_off][1] = s->mv[1][0][1]; + return; + } + + if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) { + C = s->current_picture.motion_val[0][xy - 2]; + A = s->current_picture.motion_val[0][xy - wrap * 2]; + off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; + B = s->current_picture.motion_val[0][xy - wrap * 2 + off]; + + if (!s->mb_x) C[0] = C[1] = 0; + if (!s->first_slice_line) { // predictor A is not out of bounds + if (s->mb_width == 1) { + px = A[0]; + py = A[1]; + } else { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } + } else if (s->mb_x) { // predictor C is not out of bounds + px = C[0]; + py = C[1]; + } else { + px = py = 0; + } + /* Pullback MV as specified in 8.3.5.3.4 */ + { + int qx, qy, X, Y; + if (v->profile < PROFILE_ADVANCED) { + qx = (s->mb_x << 5); + qy = (s->mb_y << 5); + X = (s->mb_width << 5) - 4; + Y = (s->mb_height << 5) - 4; + if (qx + px < -28) px = -28 - qx; + if (qy + py < -28) py = -28 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } else { + qx = (s->mb_x << 6); + qy = (s->mb_y << 6); + X = (s->mb_width << 6) - 4; + Y = (s->mb_height << 6) - 4; + if (qx + px < -60) px = -60 - qx; + if (qy + py < -60) py = -60 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } + } + /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ + if (0 && !s->first_slice_line && s->mb_x) { + if (is_intra[xy - wrap]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - A[0]) + FFABS(py - A[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } else { + if (is_intra[xy - 2]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - C[0]) + FFABS(py - C[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } + } + } + /* store MV using signed modulus of MV range defined in 4.11 */ + s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y; + } + if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) { + C = s->current_picture.motion_val[1][xy - 2]; + A = s->current_picture.motion_val[1][xy - wrap * 2]; + off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2; + B = s->current_picture.motion_val[1][xy - wrap * 2 + off]; + + if (!s->mb_x) + C[0] = C[1] = 0; + if (!s->first_slice_line) { // predictor A is not out of bounds + if (s->mb_width == 1) { + px = A[0]; + py = A[1]; + } else { + px = mid_pred(A[0], B[0], C[0]); + py = mid_pred(A[1], B[1], C[1]); + } + } else if (s->mb_x) { // predictor C is not out of bounds + px = C[0]; + py = C[1]; + } else { + px = py = 0; + } + /* Pullback MV as specified in 8.3.5.3.4 */ + { + int qx, qy, X, Y; + if (v->profile < PROFILE_ADVANCED) { + qx = (s->mb_x << 5); + qy = (s->mb_y << 5); + X = (s->mb_width << 5) - 4; + Y = (s->mb_height << 5) - 4; + if (qx + px < -28) px = -28 - qx; + if (qy + py < -28) py = -28 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } else { + qx = (s->mb_x << 6); + qy = (s->mb_y << 6); + X = (s->mb_width << 6) - 4; + Y = (s->mb_height << 6) - 4; + if (qx + px < -60) px = -60 - qx; + if (qy + py < -60) py = -60 - qy; + if (qx + px > X) px = X - qx; + if (qy + py > Y) py = Y - qy; + } + } + /* Calculate hybrid prediction as specified in 8.3.5.3.5 */ + if (0 && !s->first_slice_line && s->mb_x) { + if (is_intra[xy - wrap]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - A[0]) + FFABS(py - A[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } else { + if (is_intra[xy - 2]) + sum = FFABS(px) + FFABS(py); + else + sum = FFABS(px - C[0]) + FFABS(py - C[1]); + if (sum > 32) { + if (get_bits1(&s->gb)) { + px = A[0]; + py = A[1]; + } else { + px = C[0]; + py = C[1]; + } + } + } + } + /* store MV using signed modulus of MV range defined in 4.11 */ + + s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x; + s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y; + } + s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1]; +} + +static inline void vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y, int mv1, int *pred_flag) +{ + int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0; + MpegEncContext *s = &v->s; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + if (v->bmvtype == BMV_TYPE_DIRECT) { + int total_opp, k, f; + if (s->next_picture.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) { + s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], + v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1], + v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], + v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0] + v->blocks_off][1], + v->bfraction, 1, s->quarter_sample); + + total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off] + + v->mv_f_next[0][s->block_index[1] + v->blocks_off] + + v->mv_f_next[0][s->block_index[2] + v->blocks_off] + + v->mv_f_next[0][s->block_index[3] + v->blocks_off]; + f = (total_opp > 2) ? 1 : 0; + } else { + s->mv[0][0][0] = s->mv[0][0][1] = 0; + s->mv[1][0][0] = s->mv[1][0][1] = 0; + f = 0; + } + v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f; + for (k = 0; k < 4; k++) { + s->current_picture.motion_val[0][s->block_index[k] + v->blocks_off][0] = s->mv[0][0][0]; + s->current_picture.motion_val[0][s->block_index[k] + v->blocks_off][1] = s->mv[0][0][1]; + s->current_picture.motion_val[1][s->block_index[k] + v->blocks_off][0] = s->mv[1][0][0]; + s->current_picture.motion_val[1][s->block_index[k] + v->blocks_off][1] = s->mv[1][0][1]; + v->mv_f[0][s->block_index[k] + v->blocks_off] = f; + v->mv_f[1][s->block_index[k] + v->blocks_off] = f; + } + return; + } + if (v->bmvtype == BMV_TYPE_INTERPOLATED) { + vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0); + vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1); + return; + } + if (dir) { // backward + vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[1], 1); + if (n == 3 || mv1) { + vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); + } + } else { // forward + vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, v->mb_type[0], pred_flag[0], 0); + if (n == 3 || mv1) { + vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type[0], 0, 1); + } + } +} + +/** Get predicted DC value for I-frames only + * prediction dir: left=0, top=1 + * @param s MpegEncContext + * @param overlap flag indicating that overlap filtering is used + * @param pq integer part of picture quantizer + * @param[in] n block index in the current MB + * @param dc_val_ptr Pointer to DC predictor + * @param dir_ptr Prediction direction for use in AC prediction + */ +static inline int vc1_i_pred_dc(MpegEncContext *s, int overlap, int pq, int n, + int16_t **dc_val_ptr, int *dir_ptr) +{ + int a, b, c, wrap, pred, scale; + int16_t *dc_val; + static const uint16_t dcpred[32] = { + -1, 1024, 512, 341, 256, 205, 171, 146, 128, + 114, 102, 93, 85, 79, 73, 68, 64, + 60, 57, 54, 51, 49, 47, 45, 43, + 41, 39, 38, 37, 35, 34, 33 + }; + + /* find prediction - wmv3_dc_scale always used here in fact */ + if (n < 4) scale = s->y_dc_scale; + else scale = s->c_dc_scale; + + wrap = s->block_wrap[n]; + dc_val = s->dc_val[0] + s->block_index[n]; + + /* B A + * C X + */ + c = dc_val[ - 1]; + b = dc_val[ - 1 - wrap]; + a = dc_val[ - wrap]; + + if (pq < 9 || !overlap) { + /* Set outer values */ + if (s->first_slice_line && (n != 2 && n != 3)) + b = a = dcpred[scale]; + if (s->mb_x == 0 && (n != 1 && n != 3)) + b = c = dcpred[scale]; + } else { + /* Set outer values */ + if (s->first_slice_line && (n != 2 && n != 3)) + b = a = 0; + if (s->mb_x == 0 && (n != 1 && n != 3)) + b = c = 0; + } + + if (abs(a - b) <= abs(b - c)) { + pred = c; + *dir_ptr = 1; // left + } else { + pred = a; + *dir_ptr = 0; // top + } + + /* update predictor */ + *dc_val_ptr = &dc_val[0]; + return pred; +} + + +/** Get predicted DC value + * prediction dir: left=0, top=1 + * @param s MpegEncContext + * @param overlap flag indicating that overlap filtering is used + * @param pq integer part of picture quantizer + * @param[in] n block index in the current MB + * @param a_avail flag indicating top block availability + * @param c_avail flag indicating left block availability + * @param dc_val_ptr Pointer to DC predictor + * @param dir_ptr Prediction direction for use in AC prediction + */ +static inline int vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n, + int a_avail, int c_avail, + int16_t **dc_val_ptr, int *dir_ptr) +{ + int a, b, c, wrap, pred; + int16_t *dc_val; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int q1, q2 = 0; + int dqscale_index; + + wrap = s->block_wrap[n]; + dc_val = s->dc_val[0] + s->block_index[n]; + + /* B A + * C X + */ + c = dc_val[ - 1]; + b = dc_val[ - 1 - wrap]; + a = dc_val[ - wrap]; + /* scale predictors if needed */ + q1 = s->current_picture.qscale_table[mb_pos]; + dqscale_index = s->y_dc_scale_table[q1] - 1; + if (dqscale_index < 0) + return 0; + if (c_avail && (n != 1 && n != 3)) { + q2 = s->current_picture.qscale_table[mb_pos - 1]; + if (q2 && q2 != q1) + c = (c * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; + } + if (a_avail && (n != 2 && n != 3)) { + q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if (q2 && q2 != q1) + a = (a * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; + } + if (a_avail && c_avail && (n != 3)) { + int off = mb_pos; + if (n != 1) + off--; + if (n != 2) + off -= s->mb_stride; + q2 = s->current_picture.qscale_table[off]; + if (q2 && q2 != q1) + b = (b * s->y_dc_scale_table[q2] * ff_vc1_dqscale[dqscale_index] + 0x20000) >> 18; + } + + if (a_avail && c_avail) { + if (abs(a - b) <= abs(b - c)) { + pred = c; + *dir_ptr = 1; // left + } else { + pred = a; + *dir_ptr = 0; // top + } + } else if (a_avail) { + pred = a; + *dir_ptr = 0; // top + } else if (c_avail) { + pred = c; + *dir_ptr = 1; // left + } else { + pred = 0; + *dir_ptr = 1; // left + } + + /* update predictor */ + *dc_val_ptr = &dc_val[0]; + return pred; +} + +/** @} */ // Block group + +/** + * @name VC1 Macroblock-level functions in Simple/Main Profiles + * @see 7.1.4, p91 and 8.1.1.7, p(1)04 + * @{ + */ + +static inline int vc1_coded_block_pred(MpegEncContext * s, int n, + uint8_t **coded_block_ptr) +{ + int xy, wrap, pred, a, b, c; + + xy = s->block_index[n]; + wrap = s->b8_stride; + + /* B C + * A X + */ + a = s->coded_block[xy - 1 ]; + b = s->coded_block[xy - 1 - wrap]; + c = s->coded_block[xy - wrap]; + + if (b == c) { + pred = a; + } else { + pred = c; + } + + /* store value */ + *coded_block_ptr = &s->coded_block[xy]; + + return pred; +} + +/** + * Decode one AC coefficient + * @param v The VC1 context + * @param last Last coefficient + * @param skip How much zero coefficients to skip + * @param value Decoded AC coefficient value + * @param codingset set of VLC to decode data + * @see 8.1.3.4 + */ +static void vc1_decode_ac_coeff(VC1Context *v, int *last, int *skip, + int *value, int codingset) +{ + GetBitContext *gb = &v->s.gb; + int index, escape, run = 0, level = 0, lst = 0; + + index = get_vlc2(gb, ff_vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3); + if (index != ff_vc1_ac_sizes[codingset] - 1) { + run = vc1_index_decode_table[codingset][index][0]; + level = vc1_index_decode_table[codingset][index][1]; + lst = index >= vc1_last_decode_table[codingset] || get_bits_left(gb) < 0; + if (get_bits1(gb)) + level = -level; + } else { + escape = decode210(gb); + if (escape != 2) { + index = get_vlc2(gb, ff_vc1_ac_coeff_table[codingset].table, AC_VLC_BITS, 3); + run = vc1_index_decode_table[codingset][index][0]; + level = vc1_index_decode_table[codingset][index][1]; + lst = index >= vc1_last_decode_table[codingset]; + if (escape == 0) { + if (lst) + level += vc1_last_delta_level_table[codingset][run]; + else + level += vc1_delta_level_table[codingset][run]; + } else { + if (lst) + run += vc1_last_delta_run_table[codingset][level] + 1; + else + run += vc1_delta_run_table[codingset][level] + 1; + } + if (get_bits1(gb)) + level = -level; + } else { + int sign; + lst = get_bits1(gb); + if (v->s.esc3_level_length == 0) { + if (v->pq < 8 || v->dquantfrm) { // table 59 + v->s.esc3_level_length = get_bits(gb, 3); + if (!v->s.esc3_level_length) + v->s.esc3_level_length = get_bits(gb, 2) + 8; + } else { // table 60 + v->s.esc3_level_length = get_unary(gb, 1, 6) + 2; + } + v->s.esc3_run_length = 3 + get_bits(gb, 2); + } + run = get_bits(gb, v->s.esc3_run_length); + sign = get_bits1(gb); + level = get_bits(gb, v->s.esc3_level_length); + if (sign) + level = -level; + } + } + + *last = lst; + *skip = run; + *value = level; +} + +/** Decode intra block in intra frames - should be faster than decode_intra_block + * @param v VC1Context + * @param block block to decode + * @param[in] n subblock index + * @param coded are AC coeffs present or not + * @param codingset set of VLC to decode data + */ +static int vc1_decode_i_block(VC1Context *v, int16_t block[64], int n, + int coded, int codingset) +{ + GetBitContext *gb = &v->s.gb; + MpegEncContext *s = &v->s; + int dc_pred_dir = 0; /* Direction of the DC prediction used */ + int i; + int16_t *dc_val; + int16_t *ac_val, *ac_val2; + int dcdiff; + + /* Get DC differential */ + if (n < 4) { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (dcdiff < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); + return -1; + } + if (dcdiff) { + if (dcdiff == 119 /* ESC index value */) { + /* TODO: Optimize */ + if (v->pq == 1) dcdiff = get_bits(gb, 10); + else if (v->pq == 2) dcdiff = get_bits(gb, 9); + else dcdiff = get_bits(gb, 8); + } else { + if (v->pq == 1) + dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; + else if (v->pq == 2) + dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; + } + if (get_bits1(gb)) + dcdiff = -dcdiff; + } + + /* Prediction */ + dcdiff += vc1_i_pred_dc(&v->s, v->overlap, v->pq, n, &dc_val, &dc_pred_dir); + *dc_val = dcdiff; + + /* Store the quantized DC coeff, used for prediction */ + if (n < 4) { + block[0] = dcdiff * s->y_dc_scale; + } else { + block[0] = dcdiff * s->c_dc_scale; + } + /* Skip ? */ + if (!coded) { + goto not_coded; + } + + // AC Decoding + i = 1; + + { + int last = 0, skip, value; + const uint8_t *zz_table; + int scale; + int k; + + scale = v->pq * 2 + v->halfpq; + + if (v->s.ac_pred) { + if (!dc_pred_dir) + zz_table = v->zz_8x8[2]; + else + zz_table = v->zz_8x8[3]; + } else + zz_table = v->zz_8x8[1]; + + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + if (dc_pred_dir) // left + ac_val -= 16; + else // top + ac_val -= 16 * s->block_wrap[n]; + + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); + i += skip; + if (i > 63) + break; + block[zz_table[i++]] = value; + } + + /* apply AC prediction if needed */ + if (s->ac_pred) { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += ac_val[k]; + } else { // top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += ac_val[k + 8]; + } + } + /* save AC coeffs for further prediction */ + for (k = 1; k < 8; k++) { + ac_val2[k] = block[k << v->left_blk_sh]; + ac_val2[k + 8] = block[k << v->top_blk_sh]; + } + + /* scale AC coeffs */ + for (k = 1; k < 64; k++) + if (block[k]) { + block[k] *= scale; + if (!v->pquantizer) + block[k] += (block[k] < 0) ? -v->pq : v->pq; + } + + if (s->ac_pred) i = 63; + } + +not_coded: + if (!coded) { + int k, scale; + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + + i = 0; + scale = v->pq * 2 + v->halfpq; + memset(ac_val2, 0, 16 * 2); + if (dc_pred_dir) { // left + ac_val -= 16; + if (s->ac_pred) + memcpy(ac_val2, ac_val, 8 * 2); + } else { // top + ac_val -= 16 * s->block_wrap[n]; + if (s->ac_pred) + memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); + } + + /* apply AC prediction if needed */ + if (s->ac_pred) { + if (dc_pred_dir) { //left + for (k = 1; k < 8; k++) { + block[k << v->left_blk_sh] = ac_val[k] * scale; + if (!v->pquantizer && block[k << v->left_blk_sh]) + block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -v->pq : v->pq; + } + } else { // top + for (k = 1; k < 8; k++) { + block[k << v->top_blk_sh] = ac_val[k + 8] * scale; + if (!v->pquantizer && block[k << v->top_blk_sh]) + block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -v->pq : v->pq; + } + } + i = 63; + } + } + s->block_last_index[n] = i; + + return 0; +} + +/** Decode intra block in intra frames - should be faster than decode_intra_block + * @param v VC1Context + * @param block block to decode + * @param[in] n subblock number + * @param coded are AC coeffs present or not + * @param codingset set of VLC to decode data + * @param mquant quantizer value for this macroblock + */ +static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n, + int coded, int codingset, int mquant) +{ + GetBitContext *gb = &v->s.gb; + MpegEncContext *s = &v->s; + int dc_pred_dir = 0; /* Direction of the DC prediction used */ + int i; + int16_t *dc_val = NULL; + int16_t *ac_val, *ac_val2; + int dcdiff; + int a_avail = v->a_avail, c_avail = v->c_avail; + int use_pred = s->ac_pred; + int scale; + int q1, q2 = 0; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + + /* Get DC differential */ + if (n < 4) { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (dcdiff < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); + return -1; + } + if (dcdiff) { + if (dcdiff == 119 /* ESC index value */) { + /* TODO: Optimize */ + if (mquant == 1) dcdiff = get_bits(gb, 10); + else if (mquant == 2) dcdiff = get_bits(gb, 9); + else dcdiff = get_bits(gb, 8); + } else { + if (mquant == 1) + dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; + else if (mquant == 2) + dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; + } + if (get_bits1(gb)) + dcdiff = -dcdiff; + } + + /* Prediction */ + dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, v->a_avail, v->c_avail, &dc_val, &dc_pred_dir); + *dc_val = dcdiff; + + /* Store the quantized DC coeff, used for prediction */ + if (n < 4) { + block[0] = dcdiff * s->y_dc_scale; + } else { + block[0] = dcdiff * s->c_dc_scale; + } + + //AC Decoding + i = 1; + + /* check if AC is needed at all */ + if (!a_avail && !c_avail) + use_pred = 0; + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + + scale = mquant * 2 + ((mquant == v->pq) ? v->halfpq : 0); + + if (dc_pred_dir) // left + ac_val -= 16; + else // top + ac_val -= 16 * s->block_wrap[n]; + + q1 = s->current_picture.qscale_table[mb_pos]; + if ( dc_pred_dir && c_avail && mb_pos) + q2 = s->current_picture.qscale_table[mb_pos - 1]; + if (!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) + q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if ( dc_pred_dir && n == 1) + q2 = q1; + if (!dc_pred_dir && n == 2) + q2 = q1; + if (n == 3) + q2 = q1; + + if (coded) { + int last = 0, skip, value; + const uint8_t *zz_table; + int k; + + if (v->s.ac_pred) { + if (!use_pred && v->fcm == ILACE_FRAME) { + zz_table = v->zzi_8x8; + } else { + if (!dc_pred_dir) // top + zz_table = v->zz_8x8[2]; + else // left + zz_table = v->zz_8x8[3]; + } + } else { + if (v->fcm != ILACE_FRAME) + zz_table = v->zz_8x8[1]; + else + zz_table = v->zzi_8x8; + } + + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); + i += skip; + if (i > 63) + break; + block[zz_table[i++]] = value; + } + + /* apply AC prediction if needed */ + if (use_pred) { + /* scale predictors if needed*/ + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + + if (q1 < 1) + return AVERROR_INVALIDDATA; + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += (ac_val[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } else { // top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += (ac_val[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } else { + if (dc_pred_dir) { //left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += ac_val[k]; + } else { //top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += ac_val[k + 8]; + } + } + } + /* save AC coeffs for further prediction */ + for (k = 1; k < 8; k++) { + ac_val2[k ] = block[k << v->left_blk_sh]; + ac_val2[k + 8] = block[k << v->top_blk_sh]; + } + + /* scale AC coeffs */ + for (k = 1; k < 64; k++) + if (block[k]) { + block[k] *= scale; + if (!v->pquantizer) + block[k] += (block[k] < 0) ? -mquant : mquant; + } + + if (use_pred) i = 63; + } else { // no AC coeffs + int k; + + memset(ac_val2, 0, 16 * 2); + if (dc_pred_dir) { // left + if (use_pred) { + memcpy(ac_val2, ac_val, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } else { // top + if (use_pred) { + memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } + + /* apply AC prediction if needed */ + if (use_pred) { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) { + block[k << v->left_blk_sh] = ac_val2[k] * scale; + if (!v->pquantizer && block[k << v->left_blk_sh]) + block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -mquant : mquant; + } + } else { // top + for (k = 1; k < 8; k++) { + block[k << v->top_blk_sh] = ac_val2[k + 8] * scale; + if (!v->pquantizer && block[k << v->top_blk_sh]) + block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -mquant : mquant; + } + } + i = 63; + } + } + s->block_last_index[n] = i; + + return 0; +} + +/** Decode intra block in inter frames - more generic version than vc1_decode_i_block + * @param v VC1Context + * @param block block to decode + * @param[in] n subblock index + * @param coded are AC coeffs present or not + * @param mquant block quantizer + * @param codingset set of VLC to decode data + */ +static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n, + int coded, int mquant, int codingset) +{ + GetBitContext *gb = &v->s.gb; + MpegEncContext *s = &v->s; + int dc_pred_dir = 0; /* Direction of the DC prediction used */ + int i; + int16_t *dc_val = NULL; + int16_t *ac_val, *ac_val2; + int dcdiff; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int a_avail = v->a_avail, c_avail = v->c_avail; + int use_pred = s->ac_pred; + int scale; + int q1, q2 = 0; + + s->dsp.clear_block(block); + + /* XXX: Guard against dumb values of mquant */ + mquant = (mquant < 1) ? 0 : ((mquant > 31) ? 31 : mquant); + + /* Set DC scale - y and c use the same */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + + /* Get DC differential */ + if (n < 4) { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } else { + dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); + } + if (dcdiff < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); + return -1; + } + if (dcdiff) { + if (dcdiff == 119 /* ESC index value */) { + /* TODO: Optimize */ + if (mquant == 1) dcdiff = get_bits(gb, 10); + else if (mquant == 2) dcdiff = get_bits(gb, 9); + else dcdiff = get_bits(gb, 8); + } else { + if (mquant == 1) + dcdiff = (dcdiff << 2) + get_bits(gb, 2) - 3; + else if (mquant == 2) + dcdiff = (dcdiff << 1) + get_bits1(gb) - 1; + } + if (get_bits1(gb)) + dcdiff = -dcdiff; + } + + /* Prediction */ + dcdiff += vc1_pred_dc(&v->s, v->overlap, mquant, n, a_avail, c_avail, &dc_val, &dc_pred_dir); + *dc_val = dcdiff; + + /* Store the quantized DC coeff, used for prediction */ + + if (n < 4) { + block[0] = dcdiff * s->y_dc_scale; + } else { + block[0] = dcdiff * s->c_dc_scale; + } + + //AC Decoding + i = 1; + + /* check if AC is needed at all and adjust direction if needed */ + if (!a_avail) dc_pred_dir = 1; + if (!c_avail) dc_pred_dir = 0; + if (!a_avail && !c_avail) use_pred = 0; + ac_val = s->ac_val[0][0] + s->block_index[n] * 16; + ac_val2 = ac_val; + + scale = mquant * 2 + v->halfpq; + + if (dc_pred_dir) //left + ac_val -= 16; + else //top + ac_val -= 16 * s->block_wrap[n]; + + q1 = s->current_picture.qscale_table[mb_pos]; + if (dc_pred_dir && c_avail && mb_pos) + q2 = s->current_picture.qscale_table[mb_pos - 1]; + if (!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) + q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if ( dc_pred_dir && n == 1) + q2 = q1; + if (!dc_pred_dir && n == 2) + q2 = q1; + if (n == 3) q2 = q1; + + if (coded) { + int last = 0, skip, value; + int k; + + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, codingset); + i += skip; + if (i > 63) + break; + if (v->fcm == PROGRESSIVE) + block[v->zz_8x8[0][i++]] = value; + else { + if (use_pred && (v->fcm == ILACE_FRAME)) { + if (!dc_pred_dir) // top + block[v->zz_8x8[2][i++]] = value; + else // left + block[v->zz_8x8[3][i++]] = value; + } else { + block[v->zzi_8x8[i++]] = value; + } + } + } + + /* apply AC prediction if needed */ + if (use_pred) { + /* scale predictors if needed*/ + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + + if (q1 < 1) + return AVERROR_INVALIDDATA; + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += (ac_val[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } else { //top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += (ac_val[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } else { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) + block[k << v->left_blk_sh] += ac_val[k]; + } else { // top + for (k = 1; k < 8; k++) + block[k << v->top_blk_sh] += ac_val[k + 8]; + } + } + } + /* save AC coeffs for further prediction */ + for (k = 1; k < 8; k++) { + ac_val2[k ] = block[k << v->left_blk_sh]; + ac_val2[k + 8] = block[k << v->top_blk_sh]; + } + + /* scale AC coeffs */ + for (k = 1; k < 64; k++) + if (block[k]) { + block[k] *= scale; + if (!v->pquantizer) + block[k] += (block[k] < 0) ? -mquant : mquant; + } + + if (use_pred) i = 63; + } else { // no AC coeffs + int k; + + memset(ac_val2, 0, 16 * 2); + if (dc_pred_dir) { // left + if (use_pred) { + memcpy(ac_val2, ac_val, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k] = (ac_val2[k] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } else { // top + if (use_pred) { + memcpy(ac_val2 + 8, ac_val + 8, 8 * 2); + if (q2 && q1 != q2) { + q1 = q1 * 2 + ((q1 == v->pq) ? v->halfpq : 0) - 1; + q2 = q2 * 2 + ((q2 == v->pq) ? v->halfpq : 0) - 1; + if (q1 < 1) + return AVERROR_INVALIDDATA; + for (k = 1; k < 8; k++) + ac_val2[k + 8] = (ac_val2[k + 8] * q2 * ff_vc1_dqscale[q1 - 1] + 0x20000) >> 18; + } + } + } + + /* apply AC prediction if needed */ + if (use_pred) { + if (dc_pred_dir) { // left + for (k = 1; k < 8; k++) { + block[k << v->left_blk_sh] = ac_val2[k] * scale; + if (!v->pquantizer && block[k << v->left_blk_sh]) + block[k << v->left_blk_sh] += (block[k << v->left_blk_sh] < 0) ? -mquant : mquant; + } + } else { // top + for (k = 1; k < 8; k++) { + block[k << v->top_blk_sh] = ac_val2[k + 8] * scale; + if (!v->pquantizer && block[k << v->top_blk_sh]) + block[k << v->top_blk_sh] += (block[k << v->top_blk_sh] < 0) ? -mquant : mquant; + } + } + i = 63; + } + } + s->block_last_index[n] = i; + + return 0; +} + +/** Decode P block + */ +static int vc1_decode_p_block(VC1Context *v, int16_t block[64], int n, + int mquant, int ttmb, int first_block, + uint8_t *dst, int linesize, int skip_block, + int *ttmb_out) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int subblkpat = 0; + int scale, off, idx, last, skip, value; + int ttblk = ttmb & 7; + int pat = 0; + + s->dsp.clear_block(block); + + if (ttmb == -1) { + ttblk = ff_vc1_ttblk_to_tt[v->tt_index][get_vlc2(gb, ff_vc1_ttblk_vlc[v->tt_index].table, VC1_TTBLK_VLC_BITS, 1)]; + } + if (ttblk == TT_4X4) { + subblkpat = ~(get_vlc2(gb, ff_vc1_subblkpat_vlc[v->tt_index].table, VC1_SUBBLKPAT_VLC_BITS, 1) + 1); + } + if ((ttblk != TT_8X8 && ttblk != TT_4X4) + && ((v->ttmbf || (ttmb != -1 && (ttmb & 8) && !first_block)) + || (!v->res_rtm_flag && !first_block))) { + subblkpat = decode012(gb); + if (subblkpat) + subblkpat ^= 3; // swap decoded pattern bits + if (ttblk == TT_8X4_TOP || ttblk == TT_8X4_BOTTOM) + ttblk = TT_8X4; + if (ttblk == TT_4X8_RIGHT || ttblk == TT_4X8_LEFT) + ttblk = TT_4X8; + } + scale = 2 * mquant + ((v->pq == mquant) ? v->halfpq : 0); + + // convert transforms like 8X4_TOP to generic TT and SUBBLKPAT + if (ttblk == TT_8X4_TOP || ttblk == TT_8X4_BOTTOM) { + subblkpat = 2 - (ttblk == TT_8X4_TOP); + ttblk = TT_8X4; + } + if (ttblk == TT_4X8_RIGHT || ttblk == TT_4X8_LEFT) { + subblkpat = 2 - (ttblk == TT_4X8_LEFT); + ttblk = TT_4X8; + } + switch (ttblk) { + case TT_8X8: + pat = 0xF; + i = 0; + last = 0; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 63) + break; + if (!v->fcm) + idx = v->zz_8x8[0][i++]; + else + idx = v->zzi_8x8[i++]; + block[idx] = value * scale; + if (!v->pquantizer) + block[idx] += (block[idx] < 0) ? -mquant : mquant; + } + if (!skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_8x8_dc(dst, linesize, block); + else { + v->vc1dsp.vc1_inv_trans_8x8(block); + s->dsp.add_pixels_clamped(block, dst, linesize); + } + } + break; + case TT_4X4: + pat = ~subblkpat & 0xF; + for (j = 0; j < 4; j++) { + last = subblkpat & (1 << (3 - j)); + i = 0; + off = (j & 1) * 4 + (j & 2) * 16; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 15) + break; + if (!v->fcm) + idx = ff_vc1_simple_progressive_4x4_zz[i++]; + else + idx = ff_vc1_adv_interlaced_4x4_zz[i++]; + block[idx + off] = value * scale; + if (!v->pquantizer) + block[idx + off] += (block[idx + off] < 0) ? -mquant : mquant; + } + if (!(subblkpat & (1 << (3 - j))) && !skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_4x4_dc(dst + (j & 1) * 4 + (j & 2) * 2 * linesize, linesize, block + off); + else + v->vc1dsp.vc1_inv_trans_4x4(dst + (j & 1) * 4 + (j & 2) * 2 * linesize, linesize, block + off); + } + } + break; + case TT_8X4: + pat = ~((subblkpat & 2) * 6 + (subblkpat & 1) * 3) & 0xF; + for (j = 0; j < 2; j++) { + last = subblkpat & (1 << (1 - j)); + i = 0; + off = j * 32; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 31) + break; + if (!v->fcm) + idx = v->zz_8x4[i++] + off; + else + idx = ff_vc1_adv_interlaced_8x4_zz[i++] + off; + block[idx] = value * scale; + if (!v->pquantizer) + block[idx] += (block[idx] < 0) ? -mquant : mquant; + } + if (!(subblkpat & (1 << (1 - j))) && !skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_8x4_dc(dst + j * 4 * linesize, linesize, block + off); + else + v->vc1dsp.vc1_inv_trans_8x4(dst + j * 4 * linesize, linesize, block + off); + } + } + break; + case TT_4X8: + pat = ~(subblkpat * 5) & 0xF; + for (j = 0; j < 2; j++) { + last = subblkpat & (1 << (1 - j)); + i = 0; + off = j * 4; + while (!last) { + vc1_decode_ac_coeff(v, &last, &skip, &value, v->codingset2); + i += skip; + if (i > 31) + break; + if (!v->fcm) + idx = v->zz_4x8[i++] + off; + else + idx = ff_vc1_adv_interlaced_4x8_zz[i++] + off; + block[idx] = value * scale; + if (!v->pquantizer) + block[idx] += (block[idx] < 0) ? -mquant : mquant; + } + if (!(subblkpat & (1 << (1 - j))) && !skip_block) { + if (i == 1) + v->vc1dsp.vc1_inv_trans_4x8_dc(dst + j * 4, linesize, block + off); + else + v->vc1dsp.vc1_inv_trans_4x8(dst + j*4, linesize, block + off); + } + } + break; + } + if (ttmb_out) + *ttmb_out |= ttblk << (n * 4); + return pat; +} + +/** @} */ // Macroblock group + +static const int size_table [6] = { 0, 2, 3, 4, 5, 8 }; +static const int offset_table[6] = { 0, 1, 3, 7, 15, 31 }; + +static av_always_inline void vc1_apply_p_v_loop_filter(VC1Context *v, int block_num) +{ + MpegEncContext *s = &v->s; + int mb_cbp = v->cbp[s->mb_x - s->mb_stride], + block_cbp = mb_cbp >> (block_num * 4), bottom_cbp, + mb_is_intra = v->is_intra[s->mb_x - s->mb_stride], + block_is_intra = mb_is_intra >> (block_num * 4), bottom_is_intra; + int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk; + uint8_t *dst; + + if (block_num > 3) { + dst = s->dest[block_num - 3]; + } else { + dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 8) * linesize; + } + if (s->mb_y != s->end_mb_y || block_num < 2) { + int16_t (*mv)[2]; + int mv_stride; + + if (block_num > 3) { + bottom_cbp = v->cbp[s->mb_x] >> (block_num * 4); + bottom_is_intra = v->is_intra[s->mb_x] >> (block_num * 4); + mv = &v->luma_mv[s->mb_x - s->mb_stride]; + mv_stride = s->mb_stride; + } else { + bottom_cbp = (block_num < 2) ? (mb_cbp >> ((block_num + 2) * 4)) + : (v->cbp[s->mb_x] >> ((block_num - 2) * 4)); + bottom_is_intra = (block_num < 2) ? (mb_is_intra >> ((block_num + 2) * 4)) + : (v->is_intra[s->mb_x] >> ((block_num - 2) * 4)); + mv_stride = s->b8_stride; + mv = &s->current_picture.motion_val[0][s->block_index[block_num] - 2 * mv_stride]; + } + + if (bottom_is_intra & 1 || block_is_intra & 1 || + mv[0][0] != mv[mv_stride][0] || mv[0][1] != mv[mv_stride][1]) { + v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); + } else { + idx = ((bottom_cbp >> 2) | block_cbp) & 3; + if (idx == 3) { + v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq); + else + v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq); + } + } + } + + dst -= 4 * linesize; + ttblk = (v->ttblk[s->mb_x - s->mb_stride] >> (block_num * 4)) & 0xF; + if (ttblk == TT_4X4 || ttblk == TT_8X4) { + idx = (block_cbp | (block_cbp >> 2)) & 3; + if (idx == 3) { + v->vc1dsp.vc1_v_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_v_loop_filter4(dst + 4, linesize, v->pq); + else + v->vc1dsp.vc1_v_loop_filter4(dst, linesize, v->pq); + } + } +} + +static av_always_inline void vc1_apply_p_h_loop_filter(VC1Context *v, int block_num) +{ + MpegEncContext *s = &v->s; + int mb_cbp = v->cbp[s->mb_x - 1 - s->mb_stride], + block_cbp = mb_cbp >> (block_num * 4), right_cbp, + mb_is_intra = v->is_intra[s->mb_x - 1 - s->mb_stride], + block_is_intra = mb_is_intra >> (block_num * 4), right_is_intra; + int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize, ttblk; + uint8_t *dst; + + if (block_num > 3) { + dst = s->dest[block_num - 3] - 8 * linesize; + } else { + dst = s->dest[0] + (block_num & 1) * 8 + ((block_num & 2) * 4 - 16) * linesize - 8; + } + + if (s->mb_x != s->mb_width || !(block_num & 5)) { + int16_t (*mv)[2]; + + if (block_num > 3) { + right_cbp = v->cbp[s->mb_x - s->mb_stride] >> (block_num * 4); + right_is_intra = v->is_intra[s->mb_x - s->mb_stride] >> (block_num * 4); + mv = &v->luma_mv[s->mb_x - s->mb_stride - 1]; + } else { + right_cbp = (block_num & 1) ? (v->cbp[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) + : (mb_cbp >> ((block_num + 1) * 4)); + right_is_intra = (block_num & 1) ? (v->is_intra[s->mb_x - s->mb_stride] >> ((block_num - 1) * 4)) + : (mb_is_intra >> ((block_num + 1) * 4)); + mv = &s->current_picture.motion_val[0][s->block_index[block_num] - s->b8_stride * 2 - 2]; + } + if (block_is_intra & 1 || right_is_intra & 1 || mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1]) { + v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); + } else { + idx = ((right_cbp >> 1) | block_cbp) & 5; // FIXME check + if (idx == 5) { + v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize, linesize, v->pq); + else + v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq); + } + } + } + + dst -= 4; + ttblk = (v->ttblk[s->mb_x - s->mb_stride - 1] >> (block_num * 4)) & 0xf; + if (ttblk == TT_4X4 || ttblk == TT_4X8) { + idx = (block_cbp | (block_cbp >> 1)) & 5; + if (idx == 5) { + v->vc1dsp.vc1_h_loop_filter8(dst, linesize, v->pq); + } else if (idx) { + if (idx == 1) + v->vc1dsp.vc1_h_loop_filter4(dst + linesize * 4, linesize, v->pq); + else + v->vc1dsp.vc1_h_loop_filter4(dst, linesize, v->pq); + } + } +} + +static void vc1_apply_p_loop_filter(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int i; + + for (i = 0; i < 6; i++) { + vc1_apply_p_v_loop_filter(v, i); + } + + /* V always precedes H, therefore we run H one MB before V; + * at the end of a row, we catch up to complete the row */ + if (s->mb_x) { + for (i = 0; i < 6; i++) { + vc1_apply_p_h_loop_filter(v, i); + } + if (s->mb_x == s->mb_width - 1) { + s->mb_x++; + ff_update_block_index(s); + for (i = 0; i < 6; i++) { + vc1_apply_p_h_loop_filter(v, i); + } + } + } +} + +/** Decode one P-frame MB + */ +static int vc1_decode_p_mb(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int index, index1; /* LUT indexes */ + int val, sign; /* temp values */ + int first_block = 1; + int dst_idx, off; + int skipped, fourmv; + int block_cbp = 0, pat, block_tt = 0, block_intra = 0; + + mquant = v->pq; /* lossy initialization */ + + if (v->mv_type_is_raw) + fourmv = get_bits1(gb); + else + fourmv = v->mv_type_mb_plane[mb_pos]; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + if (!fourmv) { /* 1MV mode */ + if (!skipped) { + GET_MVDATA(dmv_x, dmv_y); + + if (s->mb_intra) { + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + } + s->current_picture.mb_type[mb_pos] = s->mb_intra ? MB_TYPE_INTRA : MB_TYPE_16x16; + vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); + + /* FIXME Set DC val for inter block ? */ + if (s->mb_intra && !mb_has_coeffs) { + GET_MQUANT(); + s->ac_pred = get_bits1(gb); + cbp = 0; + } else if (mb_has_coeffs) { + if (s->mb_intra) + s->ac_pred = get_bits1(gb); + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + GET_MQUANT(); + } else { + mquant = v->pq; + cbp = 0; + } + s->current_picture.qscale_table[mb_pos] = mquant; + + if (!v->ttmbf && !s->mb_intra && mb_has_coeffs) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, + VC1_TTMB_VLC_BITS, 2); + if (!s->mb_intra) vc1_mc_1mv(v, 0); + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + if (s->mb_intra) { + /* check if prediction blocks A and C are available */ + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + if (v->pq >= 9 && v->overlap) { + if (v->c_avail) + v->vc1dsp.vc1_h_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + if (v->a_avail) + v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + } + block_cbp |= 0xF << (i << 2); + block_intra |= 1 << i; + } else if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, first_block, + s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } else { // skipped + s->mb_intra = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + vc1_pred_mv(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0, 0); + vc1_mc_1mv(v, 0); + } + } else { // 4MV mode + if (!skipped /* unskipped MB */) { + int intra_count = 0, coded_inter = 0; + int is_intra[6], is_coded[6]; + /* Get CBPCY */ + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + val = ((cbp >> (5 - i)) & 1); + s->dc_val[0][s->block_index[i]] = 0; + s->mb_intra = 0; + if (i < 4) { + dmv_x = dmv_y = 0; + s->mb_intra = 0; + mb_has_coeffs = 0; + if (val) { + GET_MVDATA(dmv_x, dmv_y); + } + vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); + if (!s->mb_intra) + vc1_mc_4mv_luma(v, i, 0, 0); + intra_count += s->mb_intra; + is_intra[i] = s->mb_intra; + is_coded[i] = mb_has_coeffs; + } + if (i & 4) { + is_intra[i] = (intra_count >= 3); + is_coded[i] = val; + } + if (i == 4) + vc1_mc_4mv_chroma(v, 0); + v->mb_type[0][s->block_index[i]] = is_intra[i]; + if (!coded_inter) + coded_inter = !is_intra[i] & is_coded[i]; + } + // if there are no coded blocks then don't do anything more + dst_idx = 0; + if (!intra_count && !coded_inter) + goto end; + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* test if block is intra and has pred */ + { + int intrapred = 0; + for (i = 0; i < 6; i++) + if (is_intra[i]) { + if (((!s->first_slice_line || (i == 2 || i == 3)) && v->mb_type[0][s->block_index[i] - s->block_wrap[i]]) + || ((s->mb_x || (i == 1 || i == 3)) && v->mb_type[0][s->block_index[i] - 1])) { + intrapred = 1; + break; + } + } + if (intrapred) + s->ac_pred = get_bits1(gb); + else + s->ac_pred = 0; + } + if (!v->ttmbf && coded_inter) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + dst_idx += i >> 2; + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + s->mb_intra = is_intra[i]; + if (is_intra[i]) { + /* check if prediction blocks A and C are available */ + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, is_coded[i], mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize); + if (v->pq >= 9 && v->overlap) { + if (v->c_avail) + v->vc1dsp.vc1_h_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + if (v->a_avail) + v->vc1dsp.vc1_v_overlap(s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + } + block_cbp |= 0xF << (i << 2); + block_intra |= 1 << i; + } else if (is_coded[i]) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->flags & CODEC_FLAG_GRAY), + &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } else { // skipped MB + s->mb_intra = 0; + s->current_picture.qscale_table[mb_pos] = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + for (i = 0; i < 4; i++) { + vc1_pred_mv(v, i, 0, 0, 0, v->range_x, v->range_y, v->mb_type[0], 0, 0); + vc1_mc_4mv_luma(v, i, 0, 0); + } + vc1_mc_4mv_chroma(v, 0); + s->current_picture.qscale_table[mb_pos] = 0; + } + } +end: + v->cbp[s->mb_x] = block_cbp; + v->ttblk[s->mb_x] = block_tt; + v->is_intra[s->mb_x] = block_intra; + + return 0; +} + +/* Decode one macroblock in an interlaced frame p picture */ + +static int vc1_decode_p_mb_intfr(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int skipped, fourmv = 0, twomv = 0; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0, mvbp; + int stride_y, fieldtx; + + mquant = v->pq; /* Lossy initialization */ + + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + if (!skipped) { + if (v->fourmvswitch) + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_4MV_MBMODE_VLC_BITS, 2); // try getting this done + else + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); // in a single line + switch (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0]) { + /* store the motion vector type in a flag (useful later) */ + case MV_PMODE_INTFR_4MV: + fourmv = 1; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + break; + case MV_PMODE_INTFR_4MV_FIELD: + fourmv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + break; + case MV_PMODE_INTFR_2MV_FIELD: + twomv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + break; + case MV_PMODE_INTFR_1MV: + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + break; + } + if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB + for (i = 0; i < 4; i++) { + s->current_picture.motion_val[1][s->block_index[i]][0] = 0; + s->current_picture.motion_val[1][s->block_index[i]][1] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + s->mb_intra = v->is_intra[s->mb_x] = 1; + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 1; + fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = get_bits1(gb); + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (i < 4) { + stride_y = s->linesize << fieldtx; + off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; + } else { + stride_y = s->uvlinesize; + off = 0; + } + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, stride_y); + //TODO: loop filter + } + + } else { // inter MB + mb_has_coeffs = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][3]; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) { + v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); + } else { + if ((ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_4MV) + || (ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][0] == MV_PMODE_INTFR_4MV_FIELD)) { + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + } + } + s->mb_intra = v->is_intra[s->mb_x] = 0; + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 0; + fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][1]; + /* for all motion vector read MVDATA and motion compensate each block */ + dst_idx = 0; + if (fourmv) { + mvbp = v->fourmvbp; + for (i = 0; i < 6; i++) { + if (i < 4) { + dmv_x = dmv_y = 0; + val = ((mvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_4mv_luma(v, i, 0, 0); + } else if (i == 4) { + vc1_mc_4mv_chroma4(v); + } + } + } else if (twomv) { + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_4mv_luma(v, 0, 0, 0); + vc1_mc_4mv_luma(v, 1, 0, 0); + dmv_x = dmv_y = 0; + if (mvbp & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_4mv_luma(v, 2, 0, 0); + vc1_mc_4mv_luma(v, 3, 0, 0); + vc1_mc_4mv_chroma4(v); + } else { + mvbp = ff_vc1_mbmode_intfrp[v->fourmvswitch][idx_mbmode][2]; + dmv_x = dmv_y = 0; + if (mvbp) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_1mv(v, 0); + } + if (cbp) + GET_MQUANT(); // p. 227 + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + if (!fieldtx) + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + else + off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), + (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } + } else { // skipped + s->mb_intra = v->is_intra[s->mb_x] = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_1mv(v, 0); + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0])*s->mb_stride); + return 0; +} + +static int vc1_decode_p_mb_intfi(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp values */ + int first_block = 1; + int dst_idx, off; + int pred_flag = 0; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0; + + mquant = v->pq; /* Lossy initialization */ + + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); + if (idx_mbmode <= 1) { // intra MB + s->mb_intra = v->is_intra[s->mb_x] = 1; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = idx_mbmode & 1; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2); + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + v->mb_type[0][s->block_index[i]] = 1; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize); + // TODO: loop filter + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_16x16; + for (i = 0; i < 6; i++) v->mb_type[0][s->block_index[i]] = 0; + if (idx_mbmode <= 5) { // 1-MV + dmv_x = dmv_y = pred_flag = 0; + if (idx_mbmode & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); + } + vc1_pred_mv(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); + vc1_mc_1mv(v, 0); + mb_has_coeffs = !(idx_mbmode & 2); + } else { // 4-MV + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + for (i = 0; i < 6; i++) { + if (i < 4) { + dmv_x = dmv_y = pred_flag = 0; + val = ((v->fourmvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, &pred_flag); + } + vc1_pred_mv(v, i, dmv_x, dmv_y, 0, v->range_x, v->range_y, v->mb_type[0], pred_flag, 0); + vc1_mc_4mv_luma(v, i, 0, 0); + } else if (i == 4) + vc1_mc_4mv_chroma(v, 0); + } + mb_has_coeffs = idx_mbmode & 1; + } + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (cbp) { + GET_MQUANT(); + } + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) { + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + } + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->flags & CODEC_FLAG_GRAY), + &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) ttmb = -1; + first_block = 0; + } + } + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); + return 0; +} + +/** Decode one B-frame MB (in Main profile) + */ +static void vc1_decode_b_mb(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mb_has_coeffs = 0; /* last_flag */ + int index, index1; /* LUT indexes */ + int val, sign; /* temp values */ + int first_block = 1; + int dst_idx, off; + int skipped, direct; + int dmv_x[2], dmv_y[2]; + int bmvtype = BMV_TYPE_BACKWARD; + + mquant = v->pq; /* lossy initialization */ + s->mb_intra = 0; + + if (v->dmb_is_raw) + direct = get_bits1(gb); + else + direct = v->direct_mb_plane[mb_pos]; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.qscale_table[mb_pos] = 0; + + if (!direct) { + if (!skipped) { + GET_MVDATA(dmv_x[0], dmv_y[0]); + dmv_x[1] = dmv_x[0]; + dmv_y[1] = dmv_y[0]; + } + if (skipped || !s->mb_intra) { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; + break; + case 1: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + dmv_x[0] = dmv_y[0] = 0; + } + } + } + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = s->mb_intra; + + if (skipped) { + if (direct) + bmvtype = BMV_TYPE_INTERPOLATED; + vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + return; + } + if (direct) { + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + GET_MQUANT(); + s->mb_intra = 0; + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + dmv_x[0] = dmv_y[0] = dmv_x[1] = dmv_y[1] = 0; + vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + } else { + if (!mb_has_coeffs && !s->mb_intra) { + /* no coded blocks - effectively skipped */ + vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + return; + } + if (s->mb_intra && !mb_has_coeffs) { + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + s->ac_pred = get_bits1(gb); + cbp = 0; + vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + } else { + if (bmvtype == BMV_TYPE_INTERPOLATED) { + GET_MVDATA(dmv_x[0], dmv_y[0]); + if (!mb_has_coeffs) { + /* interpolated skipped block */ + vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + return; + } + } + vc1_pred_b_mv(v, dmv_x, dmv_y, direct, bmvtype); + if (!s->mb_intra) { + vc1_b_mc(v, dmv_x, dmv_y, direct, bmvtype); + } + if (s->mb_intra) + s->ac_pred = get_bits1(gb); + cbp = get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && !s->mb_intra && mb_has_coeffs) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + } + } + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + if (s->mb_intra) { + /* check if prediction blocks A and C are available */ + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, i & 4 ? s->uvlinesize : s->linesize); + } else if (val) { + vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->flags & CODEC_FLAG_GRAY), NULL); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } +} + +/** Decode one B-frame MB (in interlaced field B picture) + */ +static void vc1_decode_b_mb_intfi(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mb_has_coeffs = 0; /* last_flag */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int fwd; + int dmv_x[2], dmv_y[2], pred_flag[2]; + int bmvtype = BMV_TYPE_BACKWARD; + int idx_mbmode, interpmvp; + + mquant = v->pq; /* Lossy initialization */ + s->mb_intra = 0; + + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2); + if (idx_mbmode <= 1) { // intra MB + s->mb_intra = v->is_intra[s->mb_x] = 1; + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = idx_mbmode & 1; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2); + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[i][j] <<= 1; + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize); + // TODO: yet to perform loop filter + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_16x16; + for (i = 0; i < 6; i++) v->mb_type[0][s->block_index[i]] = 0; + if (v->fmb_is_raw) + fwd = v->forward_mb_plane[mb_pos] = get_bits1(gb); + else + fwd = v->forward_mb_plane[mb_pos]; + if (idx_mbmode <= 5) { // 1-MV + dmv_x[0] = dmv_x[1] = dmv_y[0] = dmv_y[1] = 0; + pred_flag[0] = pred_flag[1] = 0; + if (fwd) + bmvtype = BMV_TYPE_FORWARD; + else { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = BMV_TYPE_BACKWARD; + break; + case 1: + bmvtype = BMV_TYPE_DIRECT; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + interpmvp = get_bits1(gb); + } + } + v->bmvtype = bmvtype; + if (bmvtype != BMV_TYPE_DIRECT && idx_mbmode & 1) { + get_mvdata_interlaced(v, &dmv_x[bmvtype == BMV_TYPE_BACKWARD], &dmv_y[bmvtype == BMV_TYPE_BACKWARD], &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); + } + if (bmvtype == BMV_TYPE_INTERPOLATED && interpmvp) { + get_mvdata_interlaced(v, &dmv_x[1], &dmv_y[1], &pred_flag[1]); + } + if (bmvtype == BMV_TYPE_DIRECT) { + dmv_x[0] = dmv_y[0] = pred_flag[0] = 0; + dmv_x[1] = dmv_y[1] = pred_flag[0] = 0; + } + vc1_pred_b_mv_intfi(v, 0, dmv_x, dmv_y, 1, pred_flag); + vc1_b_mc(v, dmv_x, dmv_y, (bmvtype == BMV_TYPE_DIRECT), bmvtype); + mb_has_coeffs = !(idx_mbmode & 2); + } else { // 4-MV + if (fwd) + bmvtype = BMV_TYPE_FORWARD; + v->bmvtype = bmvtype; + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + for (i = 0; i < 6; i++) { + if (i < 4) { + dmv_x[0] = dmv_y[0] = pred_flag[0] = 0; + dmv_x[1] = dmv_y[1] = pred_flag[1] = 0; + val = ((v->fourmvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x[bmvtype == BMV_TYPE_BACKWARD], + &dmv_y[bmvtype == BMV_TYPE_BACKWARD], + &pred_flag[bmvtype == BMV_TYPE_BACKWARD]); + } + vc1_pred_b_mv_intfi(v, i, dmv_x, dmv_y, 0, pred_flag); + vc1_mc_4mv_luma(v, i, bmvtype == BMV_TYPE_BACKWARD, 0); + } else if (i == 4) + vc1_mc_4mv_chroma(v, bmvtype == BMV_TYPE_BACKWARD); + } + mb_has_coeffs = idx_mbmode & 1; + } + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (cbp) { + GET_MQUANT(); + } + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) { + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + } + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize; + if (val) { + vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : s->linesize, + (i & 4) && (s->flags & CODEC_FLAG_GRAY), NULL); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + } +} + +/** Decode one B-frame MB (in interlaced frame B picture) + */ +static int vc1_decode_b_mb_intfr(VC1Context *v) +{ + MpegEncContext *s = &v->s; + GetBitContext *gb = &s->gb; + int i, j; + int mb_pos = s->mb_x + s->mb_y * s->mb_stride; + int cbp = 0; /* cbp decoding stuff */ + int mqdiff, mquant; /* MB quantization */ + int ttmb = v->ttfrm; /* MB Transform type */ + int mvsw = 0; /* motion vector switch */ + int mb_has_coeffs = 1; /* last_flag */ + int dmv_x, dmv_y; /* Differential MV components */ + int val; /* temp value */ + int first_block = 1; + int dst_idx, off; + int skipped, direct, twomv = 0; + int block_cbp = 0, pat, block_tt = 0; + int idx_mbmode = 0, mvbp; + int stride_y, fieldtx; + int bmvtype = BMV_TYPE_BACKWARD; + int dir, dir2; + + mquant = v->pq; /* Lossy initialization */ + s->mb_intra = 0; + if (v->skip_is_raw) + skipped = get_bits1(gb); + else + skipped = v->s.mbskip_table[mb_pos]; + + if (!skipped) { + idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 2); + if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_2MV_FIELD) + { + twomv = 1; + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + } else { + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + } + } + + if (v->dmb_is_raw) + direct = get_bits1(gb); + else + direct = v->direct_mb_plane[mb_pos]; + + if (direct) { + s->mv[0][0][0] = s->current_picture.motion_val[0][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][0][1] = s->current_picture.motion_val[0][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][0][0] = s->current_picture.motion_val[1][s->block_index[0]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][0][1] = s->current_picture.motion_val[1][s->block_index[0]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[0]][1], v->bfraction, 1, s->quarter_sample); + + if (twomv) { + s->mv[0][2][0] = s->current_picture.motion_val[0][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 0, s->quarter_sample); + s->mv[0][2][1] = s->current_picture.motion_val[0][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 0, s->quarter_sample); + s->mv[1][2][0] = s->current_picture.motion_val[1][s->block_index[2]][0] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][0], v->bfraction, 1, s->quarter_sample); + s->mv[1][2][1] = s->current_picture.motion_val[1][s->block_index[2]][1] = scale_mv(s->next_picture.motion_val[1][s->block_index[2]][1], v->bfraction, 1, s->quarter_sample); + + for (i = 1; i < 4; i+=2) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][i-1][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][i-1][1]; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][i-1][0]; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][i-1][1]; + } + } else { + for (i = 1; i < 4; i++) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = s->mv[0][0][0]; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = s->mv[0][0][1]; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = s->mv[1][0][0]; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = s->mv[1][0][1]; + } + } + } + + if (ff_vc1_mbmode_intfrp[0][idx_mbmode][0] == MV_PMODE_INTFR_INTRA) { // intra MB + for (i = 0; i < 4; i++) { + s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0] = 0; + s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1] = 0; + s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = 0; + s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + s->mb_intra = v->is_intra[s->mb_x] = 1; + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 1; + fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb); + mb_has_coeffs = get_bits1(gb); + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + v->s.ac_pred = v->acpred_plane[mb_pos] = get_bits1(gb); + GET_MQUANT(); + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same (not sure if necessary here) */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + dst_idx = 0; + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + v->mb_type[0][s->block_index[i]] = s->mb_intra; + v->a_avail = v->c_avail = 0; + if (i == 2 || i == 3 || !s->first_slice_line) + v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]]; + if (i == 1 || i == 3 || s->mb_x) + v->c_avail = v->mb_type[0][s->block_index[i] - 1]; + + vc1_decode_intra_block(v, s->block[i], i, val, mquant, + (i & 4) ? v->codingset2 : v->codingset); + if ((i>3) && (s->flags & CODEC_FLAG_GRAY)) continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[i]); + if (i < 4) { + stride_y = s->linesize << fieldtx; + off = (fieldtx) ? ((i & 1) * 8) + ((i & 2) >> 1) * s->linesize : (i & 1) * 8 + 4 * (i & 2) * s->linesize; + } else { + stride_y = s->uvlinesize; + off = 0; + } + s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, stride_y); + } + } else { + s->mb_intra = v->is_intra[s->mb_x] = 0; + if (!direct) { + if (skipped || !s->mb_intra) { + bmvtype = decode012(gb); + switch (bmvtype) { + case 0: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_BACKWARD : BMV_TYPE_FORWARD; + break; + case 1: + bmvtype = (v->bfraction >= (B_FRACTION_DEN/2)) ? BMV_TYPE_FORWARD : BMV_TYPE_BACKWARD; + break; + case 2: + bmvtype = BMV_TYPE_INTERPOLATED; + } + } + + if (twomv && bmvtype != BMV_TYPE_INTERPOLATED) + mvsw = get_bits1(gb); + } + + if (!skipped) { // inter MB + mb_has_coeffs = ff_vc1_mbmode_intfrp[0][idx_mbmode][3]; + if (mb_has_coeffs) + cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_CBPCY_P_VLC_BITS, 2); + if (!direct) { + if (bmvtype == BMV_TYPE_INTERPOLATED & twomv) { + v->fourmvbp = get_vlc2(gb, v->fourmvbp_vlc->table, VC1_4MV_BLOCK_PATTERN_VLC_BITS, 1); + } + else if (bmvtype == BMV_TYPE_INTERPOLATED | twomv) { + v->twomvbp = get_vlc2(gb, v->twomvbp_vlc->table, VC1_2MV_BLOCK_PATTERN_VLC_BITS, 1); + } + } + + for (i = 0; i < 6; i++) + v->mb_type[0][s->block_index[i]] = 0; + fieldtx = v->fieldtx_plane[mb_pos] = ff_vc1_mbmode_intfrp[0][idx_mbmode][1]; + /* for all motion vector read MVDATA and motion compensate each block */ + dst_idx = 0; + if (direct) { + if (twomv) { + for (i = 0; i < 4; i++) { + vc1_mc_4mv_luma(v, i, 0, 0); + vc1_mc_4mv_luma(v, i, 1, 1); + } + vc1_mc_4mv_chroma4(v); + } else { + vc1_mc_1mv(v, 0); + vc1_interp_mc(v); + } + } else if (twomv && bmvtype == BMV_TYPE_INTERPOLATED) { + mvbp = v->fourmvbp; + for (i = 0; i < 4; i++) { + dir = i==1 || i==3; + dmv_x = dmv_y = 0; + val = ((mvbp >> (3 - i)) & 1); + if (val) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + j = i > 1 ? 2 : 0; + vc1_pred_mv_intfr(v, j, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); + vc1_mc_4mv_luma(v, j, dir, dir); + vc1_mc_4mv_luma(v, j+1, dir, dir); + } + + vc1_mc_4mv_chroma4(v); + } else if (bmvtype == BMV_TYPE_INTERPOLATED) { + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_mc_1mv(v, 0); + + dmv_x = dmv_y = 0; + if (mvbp & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], 1); + vc1_interp_mc(v); + } else if (twomv) { + dir = bmvtype == BMV_TYPE_BACKWARD; + dir2 = dir; + if (mvsw) + dir2 = !dir; + mvbp = v->twomvbp; + dmv_x = dmv_y = 0; + if (mvbp & 2) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir); + + dmv_x = dmv_y = 0; + if (mvbp & 1) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + vc1_pred_mv_intfr(v, 2, dmv_x, dmv_y, 2, v->range_x, v->range_y, v->mb_type[0], dir2); + + if (mvsw) { + for (i = 0; i<2; i++) { + s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; + s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; + s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; + s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; + } + } else { + vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); + vc1_pred_mv_intfr(v, 2, 0, 0, 2, v->range_x, v->range_y, v->mb_type[0], !dir); + } + + vc1_mc_4mv_luma(v, 0, dir, 0); + vc1_mc_4mv_luma(v, 1, dir, 0); + vc1_mc_4mv_luma(v, 2, dir2, 0); + vc1_mc_4mv_luma(v, 3, dir2, 0); + vc1_mc_4mv_chroma4(v); + } else { + dir = bmvtype == BMV_TYPE_BACKWARD; + + mvbp = ff_vc1_mbmode_intfrp[0][idx_mbmode][2]; + dmv_x = dmv_y = 0; + if (mvbp) { + get_mvdata_interlaced(v, &dmv_x, &dmv_y, 0); + } + + vc1_pred_mv_intfr(v, 0, dmv_x, dmv_y, 1, v->range_x, v->range_y, v->mb_type[0], dir); + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); + for (i = 0; i<2; i++) { + s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; + s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; + } + vc1_mc_1mv(v, dir); + } + + if (cbp) + GET_MQUANT(); // p. 227 + s->current_picture.qscale_table[mb_pos] = mquant; + if (!v->ttmbf && cbp) + ttmb = get_vlc2(gb, ff_vc1_ttmb_vlc[v->tt_index].table, VC1_TTMB_VLC_BITS, 2); + for (i = 0; i < 6; i++) { + s->dc_val[0][s->block_index[i]] = 0; + dst_idx += i >> 2; + val = ((cbp >> (5 - i)) & 1); + if (!fieldtx) + off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize); + else + off = (i & 4) ? 0 : ((i & 1) * 8 + ((i > 1) * s->linesize)); + if (val) { + pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb, + first_block, s->dest[dst_idx] + off, + (i & 4) ? s->uvlinesize : (s->linesize << fieldtx), + (i & 4) && (s->flags & CODEC_FLAG_GRAY), &block_tt); + block_cbp |= pat << (i << 2); + if (!v->ttmbf && ttmb < 8) + ttmb = -1; + first_block = 0; + } + } + + } else { // skipped + dir = 0; + for (i = 0; i < 6; i++) { + v->mb_type[0][s->block_index[i]] = 0; + s->dc_val[0][s->block_index[i]] = 0; + } + s->current_picture.mb_type[mb_pos] = MB_TYPE_SKIP; + s->current_picture.qscale_table[mb_pos] = 0; + v->blk_mv_type[s->block_index[0]] = 0; + v->blk_mv_type[s->block_index[1]] = 0; + v->blk_mv_type[s->block_index[2]] = 0; + v->blk_mv_type[s->block_index[3]] = 0; + + if (!direct) { + if (bmvtype == BMV_TYPE_INTERPOLATED) { + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 0); + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], 1); + } else { + dir = bmvtype == BMV_TYPE_BACKWARD; + vc1_pred_mv_intfr(v, 0, 0, 0, 1, v->range_x, v->range_y, v->mb_type[0], dir); + if (mvsw) { + int dir2 = dir; + if (mvsw) + dir2 = !dir; + for (i = 0; i<2; i++) { + s->mv[dir][i+2][0] = s->mv[dir][i][0] = s->current_picture.motion_val[dir][s->block_index[i+2]][0] = s->current_picture.motion_val[dir][s->block_index[i]][0]; + s->mv[dir][i+2][1] = s->mv[dir][i][1] = s->current_picture.motion_val[dir][s->block_index[i+2]][1] = s->current_picture.motion_val[dir][s->block_index[i]][1]; + s->mv[dir2][i+2][0] = s->mv[dir2][i][0] = s->current_picture.motion_val[dir2][s->block_index[i]][0] = s->current_picture.motion_val[dir2][s->block_index[i+2]][0]; + s->mv[dir2][i+2][1] = s->mv[dir2][i][1] = s->current_picture.motion_val[dir2][s->block_index[i]][1] = s->current_picture.motion_val[dir2][s->block_index[i+2]][1]; + } + } else { + v->blk_mv_type[s->block_index[0]] = 1; + v->blk_mv_type[s->block_index[1]] = 1; + v->blk_mv_type[s->block_index[2]] = 1; + v->blk_mv_type[s->block_index[3]] = 1; + vc1_pred_mv_intfr(v, 0, 0, 0, 2, v->range_x, v->range_y, 0, !dir); + for (i = 0; i<2; i++) { + s->mv[!dir][i+2][0] = s->mv[!dir][i][0] = s->current_picture.motion_val[!dir][s->block_index[i+2]][0] = s->current_picture.motion_val[!dir][s->block_index[i]][0]; + s->mv[!dir][i+2][1] = s->mv[!dir][i][1] = s->current_picture.motion_val[!dir][s->block_index[i+2]][1] = s->current_picture.motion_val[!dir][s->block_index[i]][1]; + } + } + } + } + + vc1_mc_1mv(v, dir); + if (direct || bmvtype == BMV_TYPE_INTERPOLATED) { + vc1_interp_mc(v); + } + } + } + if (s->mb_x == s->mb_width - 1) + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0])*s->mb_stride); + v->cbp[s->mb_x] = block_cbp; + v->ttblk[s->mb_x] = block_tt; + return 0; +} + +/** Decode blocks of I-frame + */ +static void vc1_decode_i_blocks(VC1Context *v) +{ + int k, j; + MpegEncContext *s = &v->s; + int cbp, val; + uint8_t *coded_val; + int mb_pos; + + /* select codingmode used for VLC tables selection */ + switch (v->y_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + /* Set DC scale - y and c use the same */ + s->y_dc_scale = s->y_dc_scale_table[v->pq]; + s->c_dc_scale = s->c_dc_scale_table[v->pq]; + + //do frame decode + s->mb_x = s->mb_y = 0; + s->mb_intra = 1; + s->first_slice_line = 1; + for (s->mb_y = 0; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < v->end_mb_x; s->mb_x++) { + uint8_t *dst[6]; + ff_update_block_index(s); + dst[0] = s->dest[0]; + dst[1] = dst[0] + 8; + dst[2] = s->dest[0] + s->linesize * 8; + dst[3] = dst[2] + 8; + dst[4] = s->dest[1]; + dst[5] = s->dest[2]; + s->dsp.clear_blocks(s->block[0]); + mb_pos = s->mb_x + s->mb_y * s->mb_width; + s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA; + s->current_picture.qscale_table[mb_pos] = v->pq; + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; + + // do actual MB decoding and displaying + cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + v->s.ac_pred = get_bits1(&v->s.gb); + + for (k = 0; k < 6; k++) { + val = ((cbp >> (5 - k)) & 1); + + if (k < 4) { + int pred = vc1_coded_block_pred(&v->s, k, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - k); + + vc1_decode_i_block(v, s->block[k], k, val, (k < 4) ? v->codingset : v->codingset2); + + if (k > 3 && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(s->block[k]); + if (v->pq >= 9 && v->overlap) { + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[k][j] <<= 1; + s->dsp.put_signed_pixels_clamped(s->block[k], dst[k], k & 4 ? s->uvlinesize : s->linesize); + } else { + if (v->rangeredfrm) + for (j = 0; j < 64; j++) + s->block[k][j] = (s->block[k][j] - 64) << 1; + s->dsp.put_pixels_clamped(s->block[k], dst[k], k & 4 ? s->uvlinesize : s->linesize); + } + } + + if (v->pq >= 9 && v->overlap) { + if (s->mb_x) { + v->vc1dsp.vc1_h_overlap(s->dest[0], s->linesize); + v->vc1dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize, s->linesize); + if (!(s->flags & CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_h_overlap(s->dest[1], s->uvlinesize); + v->vc1dsp.vc1_h_overlap(s->dest[2], s->uvlinesize); + } + } + v->vc1dsp.vc1_h_overlap(s->dest[0] + 8, s->linesize); + v->vc1dsp.vc1_h_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize); + if (!s->first_slice_line) { + v->vc1dsp.vc1_v_overlap(s->dest[0], s->linesize); + v->vc1dsp.vc1_v_overlap(s->dest[0] + 8, s->linesize); + if (!(s->flags & CODEC_FLAG_GRAY)) { + v->vc1dsp.vc1_v_overlap(s->dest[1], s->uvlinesize); + v->vc1dsp.vc1_v_overlap(s->dest[2], s->uvlinesize); + } + } + v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize, s->linesize); + v->vc1dsp.vc1_v_overlap(s->dest[0] + 8 * s->linesize + 8, s->linesize); + } + if (v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq); + + if (get_bits_count(&s->gb) > v->bits) { + ff_er_add_slice(&s->er, 0, 0, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", + get_bits_count(&s->gb), v->bits); + return; + } + } + if (!v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + else if (s->mb_y) + ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); + + s->first_slice_line = 0; + } + if (v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); + + /* This is intentionally mb_height and not end_mb_y - unlike in advanced + * profile, these only differ are when decoding MSS2 rectangles. */ + ff_er_add_slice(&s->er, 0, 0, s->mb_width - 1, s->mb_height - 1, ER_MB_END); +} + +/** Decode blocks of I-frame for advanced profile + */ +static void vc1_decode_i_blocks_adv(VC1Context *v) +{ + int k; + MpegEncContext *s = &v->s; + int cbp, val; + uint8_t *coded_val; + int mb_pos; + int mquant = v->pq; + int mqdiff; + GetBitContext *gb = &s->gb; + + /* select codingmode used for VLC tables selection */ + switch (v->y_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + // do frame decode + s->mb_x = s->mb_y = 0; + s->mb_intra = 1; + s->first_slice_line = 1; + s->mb_y = s->start_mb_y; + if (s->start_mb_y) { + s->mb_x = 0; + init_block_index(v); + memset(&s->coded_block[s->block_index[0] - s->b8_stride], 0, + (1 + s->b8_stride) * sizeof(*s->coded_block)); + } + for (; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (;s->mb_x < s->mb_width; s->mb_x++) { + int16_t (*block)[64] = v->block[v->cur_blk_idx]; + ff_update_block_index(s); + s->dsp.clear_blocks(block[0]); + mb_pos = s->mb_x + s->mb_y * s->mb_stride; + s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; + + // do actual MB decoding and displaying + if (v->fieldtx_is_raw) + v->fieldtx_plane[mb_pos] = get_bits1(&v->s.gb); + cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + if ( v->acpred_is_raw) + v->s.ac_pred = get_bits1(&v->s.gb); + else + v->s.ac_pred = v->acpred_plane[mb_pos]; + + if (v->condover == CONDOVER_SELECT && v->overflg_is_raw) + v->over_flags_plane[mb_pos] = get_bits1(&v->s.gb); + + GET_MQUANT(); + + s->current_picture.qscale_table[mb_pos] = mquant; + /* Set DC scale - y and c use the same */ + s->y_dc_scale = s->y_dc_scale_table[mquant]; + s->c_dc_scale = s->c_dc_scale_table[mquant]; + + for (k = 0; k < 6; k++) { + val = ((cbp >> (5 - k)) & 1); + + if (k < 4) { + int pred = vc1_coded_block_pred(&v->s, k, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - k); + + v->a_avail = !s->first_slice_line || (k == 2 || k == 3); + v->c_avail = !!s->mb_x || (k == 1 || k == 3); + + vc1_decode_i_block_adv(v, block[k], k, val, + (k < 4) ? v->codingset : v->codingset2, mquant); + + if (k > 3 && (s->flags & CODEC_FLAG_GRAY)) + continue; + v->vc1dsp.vc1_inv_trans_8x8(block[k]); + } + + vc1_smooth_overlap_filter_iblk(v); + vc1_put_signed_blocks_clamped(v); + if (v->s.loop_filter) vc1_loop_filter_iblk_delayed(v, v->pq); + + if (get_bits_count(&s->gb) > v->bits) { + // TODO: may need modification to handle slice coding + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", + get_bits_count(&s->gb), v->bits); + return; + } + } + if (!v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + else if (s->mb_y) + ff_mpeg_draw_horiz_band(s, (s->mb_y-1) * 16, 16); + s->first_slice_line = 0; + } + + /* raw bottom MB row */ + s->mb_x = 0; + init_block_index(v); + + for (;s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + vc1_put_signed_blocks_clamped(v); + if (v->s.loop_filter) + vc1_loop_filter_iblk_delayed(v, v->pq); + } + if (v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y-1)*16, 16); + ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, + (s->end_mb_y << v->field_mode) - 1, ER_MB_END); +} + +static void vc1_decode_p_blocks(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int apply_loop_filter; + + /* select codingmode used for VLC tables selection */ + switch (v->c_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + apply_loop_filter = s->loop_filter && !(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY); + s->first_slice_line = 1; + memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride); + for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + + if (v->fcm == ILACE_FIELD) + vc1_decode_p_mb_intfi(v); + else if (v->fcm == ILACE_FRAME) + vc1_decode_p_mb_intfr(v); + else vc1_decode_p_mb(v); + if (s->mb_y != s->start_mb_y && apply_loop_filter && v->fcm == PROGRESSIVE) + vc1_apply_p_loop_filter(v); + if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { + // TODO: may need modification to handle slice coding + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", + get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); + return; + } + } + memmove(v->cbp_base, v->cbp, sizeof(v->cbp_base[0]) * s->mb_stride); + memmove(v->ttblk_base, v->ttblk, sizeof(v->ttblk_base[0]) * s->mb_stride); + memmove(v->is_intra_base, v->is_intra, sizeof(v->is_intra_base[0]) * s->mb_stride); + memmove(v->luma_mv_base, v->luma_mv, sizeof(v->luma_mv_base[0]) * s->mb_stride); + if (s->mb_y != s->start_mb_y) ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); + s->first_slice_line = 0; + } + if (apply_loop_filter && v->fcm == PROGRESSIVE) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + vc1_apply_p_loop_filter(v); + } + } + if (s->end_mb_y >= s->start_mb_y) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); + ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, + (s->end_mb_y << v->field_mode) - 1, ER_MB_END); +} + +static void vc1_decode_b_blocks(VC1Context *v) +{ + MpegEncContext *s = &v->s; + + /* select codingmode used for VLC tables selection */ + switch (v->c_ac_table_index) { + case 0: + v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA; + break; + case 1: + v->codingset = CS_HIGH_MOT_INTRA; + break; + case 2: + v->codingset = CS_MID_RATE_INTRA; + break; + } + + switch (v->c_ac_table_index) { + case 0: + v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER; + break; + case 1: + v->codingset2 = CS_HIGH_MOT_INTER; + break; + case 2: + v->codingset2 = CS_MID_RATE_INTER; + break; + } + + s->first_slice_line = 1; + for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + for (; s->mb_x < s->mb_width; s->mb_x++) { + ff_update_block_index(s); + + if (v->fcm == ILACE_FIELD) + vc1_decode_b_mb_intfi(v); + else if (v->fcm == ILACE_FRAME) + vc1_decode_b_mb_intfr(v); + else + vc1_decode_b_mb(v); + if (get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { + // TODO: may need modification to handle slice coding + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR); + av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", + get_bits_count(&s->gb), v->bits, s->mb_x, s->mb_y); + return; + } + if (v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq); + } + if (!v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + else if (s->mb_y) + ff_mpeg_draw_horiz_band(s, (s->mb_y - 1) * 16, 16); + s->first_slice_line = 0; + } + if (v->s.loop_filter) + ff_mpeg_draw_horiz_band(s, (s->end_mb_y - 1) * 16, 16); + ff_er_add_slice(&s->er, 0, s->start_mb_y << v->field_mode, s->mb_width - 1, + (s->end_mb_y << v->field_mode) - 1, ER_MB_END); +} + +static void vc1_decode_skip_blocks(VC1Context *v) +{ + MpegEncContext *s = &v->s; + + ff_er_add_slice(&s->er, 0, s->start_mb_y, s->mb_width - 1, s->end_mb_y - 1, ER_MB_END); + s->first_slice_line = 1; + for (s->mb_y = s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x = 0; + init_block_index(v); + ff_update_block_index(s); + if (s->last_picture.f.data[0]) { + memcpy(s->dest[0], s->last_picture.f.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16); + memcpy(s->dest[1], s->last_picture.f.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + memcpy(s->dest[2], s->last_picture.f.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8); + } + ff_mpeg_draw_horiz_band(s, s->mb_y * 16, 16); + s->first_slice_line = 0; + } + s->pict_type = AV_PICTURE_TYPE_P; +} + +void ff_vc1_decode_blocks(VC1Context *v) +{ + + v->s.esc3_level_length = 0; + if (v->x8_type) { + ff_intrax8_decode_picture(&v->x8, 2*v->pq + v->halfpq, v->pq * !v->pquantizer); + } else { + v->cur_blk_idx = 0; + v->left_blk_idx = -1; + v->topleft_blk_idx = 1; + v->top_blk_idx = 2; + switch (v->s.pict_type) { + case AV_PICTURE_TYPE_I: + if (v->profile == PROFILE_ADVANCED) + vc1_decode_i_blocks_adv(v); + else + vc1_decode_i_blocks(v); + break; + case AV_PICTURE_TYPE_P: + if (v->p_frame_skipped) + vc1_decode_skip_blocks(v); + else + vc1_decode_p_blocks(v); + break; + case AV_PICTURE_TYPE_B: + if (v->bi_type) { + if (v->profile == PROFILE_ADVANCED) + vc1_decode_i_blocks_adv(v); + else + vc1_decode_i_blocks(v); + } else + vc1_decode_b_blocks(v); + break; + } + } +} + +#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER + +typedef struct { + /** + * Transform coefficients for both sprites in 16.16 fixed point format, + * in the order they appear in the bitstream: + * x scale + * rotation 1 (unused) + * x offset + * rotation 2 (unused) + * y scale + * y offset + * alpha + */ + int coefs[2][7]; + + int effect_type, effect_flag; + int effect_pcount1, effect_pcount2; ///< amount of effect parameters stored in effect_params + int effect_params1[15], effect_params2[10]; ///< effect parameters in 16.16 fixed point format +} SpriteData; + +static inline int get_fp_val(GetBitContext* gb) +{ + return (get_bits_long(gb, 30) - (1 << 29)) << 1; +} + +static void vc1_sprite_parse_transform(GetBitContext* gb, int c[7]) +{ + c[1] = c[3] = 0; + + switch (get_bits(gb, 2)) { + case 0: + c[0] = 1 << 16; + c[2] = get_fp_val(gb); + c[4] = 1 << 16; + break; + case 1: + c[0] = c[4] = get_fp_val(gb); + c[2] = get_fp_val(gb); + break; + case 2: + c[0] = get_fp_val(gb); + c[2] = get_fp_val(gb); + c[4] = get_fp_val(gb); + break; + case 3: + c[0] = get_fp_val(gb); + c[1] = get_fp_val(gb); + c[2] = get_fp_val(gb); + c[3] = get_fp_val(gb); + c[4] = get_fp_val(gb); + break; + } + c[5] = get_fp_val(gb); + if (get_bits1(gb)) + c[6] = get_fp_val(gb); + else + c[6] = 1 << 16; +} + +static void vc1_parse_sprites(VC1Context *v, GetBitContext* gb, SpriteData* sd) +{ + AVCodecContext *avctx = v->s.avctx; + int sprite, i; + + for (sprite = 0; sprite <= v->two_sprites; sprite++) { + vc1_sprite_parse_transform(gb, sd->coefs[sprite]); + if (sd->coefs[sprite][1] || sd->coefs[sprite][3]) + avpriv_request_sample(avctx, "Non-zero rotation coefficients"); + av_log(avctx, AV_LOG_DEBUG, sprite ? "S2:" : "S1:"); + for (i = 0; i < 7; i++) + av_log(avctx, AV_LOG_DEBUG, " %d.%.3d", + sd->coefs[sprite][i] / (1<<16), + (abs(sd->coefs[sprite][i]) & 0xFFFF) * 1000 / (1 << 16)); + av_log(avctx, AV_LOG_DEBUG, "\n"); + } + + skip_bits(gb, 2); + if (sd->effect_type = get_bits_long(gb, 30)) { + switch (sd->effect_pcount1 = get_bits(gb, 4)) { + case 7: + vc1_sprite_parse_transform(gb, sd->effect_params1); + break; + case 14: + vc1_sprite_parse_transform(gb, sd->effect_params1); + vc1_sprite_parse_transform(gb, sd->effect_params1 + 7); + break; + default: + for (i = 0; i < sd->effect_pcount1; i++) + sd->effect_params1[i] = get_fp_val(gb); + } + if (sd->effect_type != 13 || sd->effect_params1[0] != sd->coefs[0][6]) { + // effect 13 is simple alpha blending and matches the opacity above + av_log(avctx, AV_LOG_DEBUG, "Effect: %d; params: ", sd->effect_type); + for (i = 0; i < sd->effect_pcount1; i++) + av_log(avctx, AV_LOG_DEBUG, " %d.%.2d", + sd->effect_params1[i] / (1 << 16), + (abs(sd->effect_params1[i]) & 0xFFFF) * 1000 / (1 << 16)); + av_log(avctx, AV_LOG_DEBUG, "\n"); + } + + sd->effect_pcount2 = get_bits(gb, 16); + if (sd->effect_pcount2 > 10) { + av_log(avctx, AV_LOG_ERROR, "Too many effect parameters\n"); + return; + } else if (sd->effect_pcount2) { + i = -1; + av_log(avctx, AV_LOG_DEBUG, "Effect params 2: "); + while (++i < sd->effect_pcount2) { + sd->effect_params2[i] = get_fp_val(gb); + av_log(avctx, AV_LOG_DEBUG, " %d.%.2d", + sd->effect_params2[i] / (1 << 16), + (abs(sd->effect_params2[i]) & 0xFFFF) * 1000 / (1 << 16)); + } + av_log(avctx, AV_LOG_DEBUG, "\n"); + } + } + if (sd->effect_flag = get_bits1(gb)) + av_log(avctx, AV_LOG_DEBUG, "Effect flag set\n"); + + if (get_bits_count(gb) >= gb->size_in_bits + + (avctx->codec_id == AV_CODEC_ID_WMV3IMAGE ? 64 : 0)) + av_log(avctx, AV_LOG_ERROR, "Buffer overrun\n"); + if (get_bits_count(gb) < gb->size_in_bits - 8) + av_log(avctx, AV_LOG_WARNING, "Buffer not fully read\n"); +} + +static void vc1_draw_sprites(VC1Context *v, SpriteData* sd) +{ + int i, plane, row, sprite; + int sr_cache[2][2] = { { -1, -1 }, { -1, -1 } }; + uint8_t* src_h[2][2]; + int xoff[2], xadv[2], yoff[2], yadv[2], alpha; + int ysub[2]; + MpegEncContext *s = &v->s; + + for (i = 0; i < 2; i++) { + xoff[i] = av_clip(sd->coefs[i][2], 0, v->sprite_width-1 << 16); + xadv[i] = sd->coefs[i][0]; + if (xadv[i] != 1<<16 || (v->sprite_width << 16) - (v->output_width << 16) - xoff[i]) + xadv[i] = av_clip(xadv[i], 0, ((v->sprite_width<<16) - xoff[i] - 1) / v->output_width); + + yoff[i] = av_clip(sd->coefs[i][5], 0, v->sprite_height-1 << 16); + yadv[i] = av_clip(sd->coefs[i][4], 0, ((v->sprite_height << 16) - yoff[i]) / v->output_height); + } + alpha = av_clip(sd->coefs[1][6], 0, (1<<16) - 1); + + for (plane = 0; plane < (s->flags&CODEC_FLAG_GRAY ? 1 : 3); plane++) { + int width = v->output_width>>!!plane; + + for (row = 0; row < v->output_height>>!!plane; row++) { + uint8_t *dst = v->sprite_output_frame.data[plane] + + v->sprite_output_frame.linesize[plane] * row; + + for (sprite = 0; sprite <= v->two_sprites; sprite++) { + uint8_t *iplane = s->current_picture.f.data[plane]; + int iline = s->current_picture.f.linesize[plane]; + int ycoord = yoff[sprite] + yadv[sprite] * row; + int yline = ycoord >> 16; + int next_line; + ysub[sprite] = ycoord & 0xFFFF; + if (sprite) { + iplane = s->last_picture.f.data[plane]; + iline = s->last_picture.f.linesize[plane]; + } + next_line = FFMIN(yline + 1, (v->sprite_height >> !!plane) - 1) * iline; + if (!(xoff[sprite] & 0xFFFF) && xadv[sprite] == 1 << 16) { + src_h[sprite][0] = iplane + (xoff[sprite] >> 16) + yline * iline; + if (ysub[sprite]) + src_h[sprite][1] = iplane + (xoff[sprite] >> 16) + next_line; + } else { + if (sr_cache[sprite][0] != yline) { + if (sr_cache[sprite][1] == yline) { + FFSWAP(uint8_t*, v->sr_rows[sprite][0], v->sr_rows[sprite][1]); + FFSWAP(int, sr_cache[sprite][0], sr_cache[sprite][1]); + } else { + v->vc1dsp.sprite_h(v->sr_rows[sprite][0], iplane + yline * iline, xoff[sprite], xadv[sprite], width); + sr_cache[sprite][0] = yline; + } + } + if (ysub[sprite] && sr_cache[sprite][1] != yline + 1) { + v->vc1dsp.sprite_h(v->sr_rows[sprite][1], + iplane + next_line, xoff[sprite], + xadv[sprite], width); + sr_cache[sprite][1] = yline + 1; + } + src_h[sprite][0] = v->sr_rows[sprite][0]; + src_h[sprite][1] = v->sr_rows[sprite][1]; + } + } + + if (!v->two_sprites) { + if (ysub[0]) { + v->vc1dsp.sprite_v_single(dst, src_h[0][0], src_h[0][1], ysub[0], width); + } else { + memcpy(dst, src_h[0][0], width); + } + } else { + if (ysub[0] && ysub[1]) { + v->vc1dsp.sprite_v_double_twoscale(dst, src_h[0][0], src_h[0][1], ysub[0], + src_h[1][0], src_h[1][1], ysub[1], alpha, width); + } else if (ysub[0]) { + v->vc1dsp.sprite_v_double_onescale(dst, src_h[0][0], src_h[0][1], ysub[0], + src_h[1][0], alpha, width); + } else if (ysub[1]) { + v->vc1dsp.sprite_v_double_onescale(dst, src_h[1][0], src_h[1][1], ysub[1], + src_h[0][0], (1<<16)-1-alpha, width); + } else { + v->vc1dsp.sprite_v_double_noscale(dst, src_h[0][0], src_h[1][0], alpha, width); + } + } + } + + if (!plane) { + for (i = 0; i < 2; i++) { + xoff[i] >>= 1; + yoff[i] >>= 1; + } + } + + } +} + + +static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb) +{ + int ret; + MpegEncContext *s = &v->s; + AVCodecContext *avctx = s->avctx; + SpriteData sd; + + vc1_parse_sprites(v, gb, &sd); + + if (!s->current_picture.f.data[0]) { + av_log(avctx, AV_LOG_ERROR, "Got no sprites\n"); + return -1; + } + + if (v->two_sprites && (!s->last_picture_ptr || !s->last_picture.f.data[0])) { + av_log(avctx, AV_LOG_WARNING, "Need two sprites, only got one\n"); + v->two_sprites = 0; + } + + av_frame_unref(&v->sprite_output_frame); + if ((ret = ff_get_buffer(avctx, &v->sprite_output_frame, 0)) < 0) + return ret; + + vc1_draw_sprites(v, &sd); + + return 0; +} + +static void vc1_sprite_flush(AVCodecContext *avctx) +{ + VC1Context *v = avctx->priv_data; + MpegEncContext *s = &v->s; + AVFrame *f = &s->current_picture.f; + int plane, i; + + /* Windows Media Image codecs have a convergence interval of two keyframes. + Since we can't enforce it, clear to black the missing sprite. This is + wrong but it looks better than doing nothing. */ + + if (f->data[0]) + for (plane = 0; plane < (s->flags&CODEC_FLAG_GRAY ? 1 : 3); plane++) + for (i = 0; i < v->sprite_height>>!!plane; i++) + memset(f->data[plane] + i * f->linesize[plane], + plane ? 128 : 0, f->linesize[plane]); +} + +#endif + +av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v) +{ + MpegEncContext *s = &v->s; + int i; + + /* Allocate mb bitplanes */ + v->mv_type_mb_plane = av_malloc (s->mb_stride * s->mb_height); + v->direct_mb_plane = av_malloc (s->mb_stride * s->mb_height); + v->forward_mb_plane = av_malloc (s->mb_stride * s->mb_height); + v->fieldtx_plane = av_mallocz(s->mb_stride * s->mb_height); + v->acpred_plane = av_malloc (s->mb_stride * s->mb_height); + v->over_flags_plane = av_malloc (s->mb_stride * s->mb_height); + + v->n_allocated_blks = s->mb_width + 2; + v->block = av_malloc(sizeof(*v->block) * v->n_allocated_blks); + v->cbp_base = av_malloc(sizeof(v->cbp_base[0]) * 2 * s->mb_stride); + v->cbp = v->cbp_base + s->mb_stride; + v->ttblk_base = av_malloc(sizeof(v->ttblk_base[0]) * 2 * s->mb_stride); + v->ttblk = v->ttblk_base + s->mb_stride; + v->is_intra_base = av_mallocz(sizeof(v->is_intra_base[0]) * 2 * s->mb_stride); + v->is_intra = v->is_intra_base + s->mb_stride; + v->luma_mv_base = av_malloc(sizeof(v->luma_mv_base[0]) * 2 * s->mb_stride); + v->luma_mv = v->luma_mv_base + s->mb_stride; + + /* allocate block type info in that way so it could be used with s->block_index[] */ + v->mb_type_base = av_malloc(s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); + v->mb_type[0] = v->mb_type_base + s->b8_stride + 1; + v->mb_type[1] = v->mb_type_base + s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride + 1; + v->mb_type[2] = v->mb_type[1] + s->mb_stride * (s->mb_height + 1); + + /* allocate memory to store block level MV info */ + v->blk_mv_type_base = av_mallocz( s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); + v->blk_mv_type = v->blk_mv_type_base + s->b8_stride + 1; + v->mv_f_base = av_mallocz(2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); + v->mv_f[0] = v->mv_f_base + s->b8_stride + 1; + v->mv_f[1] = v->mv_f[0] + (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); + v->mv_f_last_base = av_mallocz(2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); + v->mv_f_last[0] = v->mv_f_last_base + s->b8_stride + 1; + v->mv_f_last[1] = v->mv_f_last[0] + (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); + v->mv_f_next_base = av_mallocz(2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); + v->mv_f_next[0] = v->mv_f_next_base + s->b8_stride + 1; + v->mv_f_next[1] = v->mv_f_next[0] + (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2); + + /* Init coded blocks info */ + if (v->profile == PROFILE_ADVANCED) { +// if (alloc_bitplane(&v->over_flags_plane, s->mb_width, s->mb_height) < 0) +// return -1; +// if (alloc_bitplane(&v->ac_pred_plane, s->mb_width, s->mb_height) < 0) +// return -1; + } + + ff_intrax8_common_init(&v->x8,s); + + if (s->avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || s->avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { + for (i = 0; i < 4; i++) + if (!(v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width))) return -1; + } + + if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->acpred_plane || !v->over_flags_plane || + !v->block || !v->cbp_base || !v->ttblk_base || !v->is_intra_base || !v->luma_mv_base || + !v->mb_type_base) + return -1; + + return 0; +} + +av_cold void ff_vc1_init_transposed_scantables(VC1Context *v) +{ + int i; + for (i = 0; i < 64; i++) { +#define transpose(x) ((x >> 3) | ((x & 7) << 3)) + v->zz_8x8[0][i] = transpose(ff_wmv1_scantable[0][i]); + v->zz_8x8[1][i] = transpose(ff_wmv1_scantable[1][i]); + v->zz_8x8[2][i] = transpose(ff_wmv1_scantable[2][i]); + v->zz_8x8[3][i] = transpose(ff_wmv1_scantable[3][i]); + v->zzi_8x8[i] = transpose(ff_vc1_adv_interlaced_8x8_zz[i]); + } + v->left_blk_sh = 0; + v->top_blk_sh = 3; +} + +/** Initialize a VC1/WMV3 decoder + * @todo TODO: Handle VC-1 IDUs (Transport level?) + * @todo TODO: Decypher remaining bits in extra_data + */ +static av_cold int vc1_decode_init(AVCodecContext *avctx) +{ + VC1Context *v = avctx->priv_data; + MpegEncContext *s = &v->s; + GetBitContext gb; + + /* save the container output size for WMImage */ + v->output_width = avctx->width; + v->output_height = avctx->height; + + if (!avctx->extradata_size || !avctx->extradata) + return -1; + if (!(avctx->flags & CODEC_FLAG_GRAY)) + avctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); + else + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt); + v->s.avctx = avctx; + avctx->flags |= CODEC_FLAG_EMU_EDGE; + v->s.flags |= CODEC_FLAG_EMU_EDGE; + + if (ff_vc1_init_common(v) < 0) + return -1; + // ensure static VLC tables are initialized + if (ff_msmpeg4_decode_init(avctx) < 0) + return -1; + if (ff_vc1_decode_init_alloc_tables(v) < 0) + return -1; + // Hack to ensure the above functions will be called + // again once we know all necessary settings. + // That this is necessary might indicate a bug. + ff_vc1_decode_end(avctx); + + ff_h264chroma_init(&v->h264chroma, 8); + ff_vc1dsp_init(&v->vc1dsp); + + if (avctx->codec_id == AV_CODEC_ID_WMV3 || avctx->codec_id == AV_CODEC_ID_WMV3IMAGE) { + int count = 0; + + // looks like WMV3 has a sequence header stored in the extradata + // advanced sequence header may be before the first frame + // the last byte of the extradata is a version number, 1 for the + // samples we can decode + + init_get_bits(&gb, avctx->extradata, avctx->extradata_size*8); + + if (ff_vc1_decode_sequence_header(avctx, v, &gb) < 0) + return -1; + + count = avctx->extradata_size*8 - get_bits_count(&gb); + if (count > 0) { + av_log(avctx, AV_LOG_INFO, "Extra data: %i bits left, value: %X\n", + count, get_bits(&gb, count)); + } else if (count < 0) { + av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count); + } + } else { // VC1/WVC1/WVP2 + const uint8_t *start = avctx->extradata; + uint8_t *end = avctx->extradata + avctx->extradata_size; + const uint8_t *next; + int size, buf2_size; + uint8_t *buf2 = NULL; + int seq_initialized = 0, ep_initialized = 0; + + if (avctx->extradata_size < 16) { + av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", avctx->extradata_size); + return -1; + } + + buf2 = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + start = find_next_marker(start, end); // in WVC1 extradata first byte is its size, but can be 0 in mkv + next = start; + for (; next < end; start = next) { + next = find_next_marker(start + 4, end); + size = next - start - 4; + if (size <= 0) + continue; + buf2_size = vc1_unescape_buffer(start + 4, size, buf2); + init_get_bits(&gb, buf2, buf2_size * 8); + switch (AV_RB32(start)) { + case VC1_CODE_SEQHDR: + if (ff_vc1_decode_sequence_header(avctx, v, &gb) < 0) { + av_free(buf2); + return -1; + } + seq_initialized = 1; + break; + case VC1_CODE_ENTRYPOINT: + if (ff_vc1_decode_entry_point(avctx, v, &gb) < 0) { + av_free(buf2); + return -1; + } + ep_initialized = 1; + break; + } + } + av_free(buf2); + if (!seq_initialized || !ep_initialized) { + av_log(avctx, AV_LOG_ERROR, "Incomplete extradata\n"); + return -1; + } + v->res_sprite = (avctx->codec_id == AV_CODEC_ID_VC1IMAGE); + } + + avctx->profile = v->profile; + if (v->profile == PROFILE_ADVANCED) + avctx->level = v->level; + + avctx->has_b_frames = !!avctx->max_b_frames; + + s->mb_width = (avctx->coded_width + 15) >> 4; + s->mb_height = (avctx->coded_height + 15) >> 4; + + if (v->profile == PROFILE_ADVANCED || v->res_fasttx) { + ff_vc1_init_transposed_scantables(v); + } else { + memcpy(v->zz_8x8, ff_wmv1_scantable, 4*64); + v->left_blk_sh = 3; + v->top_blk_sh = 0; + } + + if (avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { + v->sprite_width = avctx->coded_width; + v->sprite_height = avctx->coded_height; + + avctx->coded_width = avctx->width = v->output_width; + avctx->coded_height = avctx->height = v->output_height; + + // prevent 16.16 overflows + if (v->sprite_width > 1 << 14 || + v->sprite_height > 1 << 14 || + v->output_width > 1 << 14 || + v->output_height > 1 << 14) return -1; + + if ((v->sprite_width&1) || (v->sprite_height&1)) { + avpriv_request_sample(avctx, "odd sprites support"); + return AVERROR_PATCHWELCOME; + } + } + return 0; +} + +/** Close a VC1/WMV3 decoder + * @warning Initial try at using MpegEncContext stuff + */ +av_cold int ff_vc1_decode_end(AVCodecContext *avctx) +{ + VC1Context *v = avctx->priv_data; + int i; + + av_frame_unref(&v->sprite_output_frame); + + for (i = 0; i < 4; i++) + av_freep(&v->sr_rows[i >> 1][i & 1]); + av_freep(&v->hrd_rate); + av_freep(&v->hrd_buffer); + ff_MPV_common_end(&v->s); + av_freep(&v->mv_type_mb_plane); + av_freep(&v->direct_mb_plane); + av_freep(&v->forward_mb_plane); + av_freep(&v->fieldtx_plane); + av_freep(&v->acpred_plane); + av_freep(&v->over_flags_plane); + av_freep(&v->mb_type_base); + av_freep(&v->blk_mv_type_base); + av_freep(&v->mv_f_base); + av_freep(&v->mv_f_last_base); + av_freep(&v->mv_f_next_base); + av_freep(&v->block); + av_freep(&v->cbp_base); + av_freep(&v->ttblk_base); + av_freep(&v->is_intra_base); // FIXME use v->mb_type[] + av_freep(&v->luma_mv_base); + ff_intrax8_common_end(&v->x8); + return 0; +} + + +/** Decode a VC1/WMV3 frame + * @todo TODO: Handle VC-1 IDUs (Transport level?) + */ +static int vc1_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size, n_slices = 0, i, ret; + VC1Context *v = avctx->priv_data; + MpegEncContext *s = &v->s; + AVFrame *pict = data; + uint8_t *buf2 = NULL; + const uint8_t *buf_start = buf, *buf_start_second_field = NULL; + int mb_height, n_slices1=-1; + struct { + uint8_t *buf; + GetBitContext gb; + int mby_start; + } *slices = NULL, *tmp; + + v->second_field = 0; + + if(s->flags & CODEC_FLAG_LOW_DELAY) + s->low_delay = 1; + + /* no supplementary picture */ + if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) { + /* special case for last picture */ + if (s->low_delay == 0 && s->next_picture_ptr) { + if ((ret = av_frame_ref(pict, &s->next_picture_ptr->f)) < 0) + return ret; + s->next_picture_ptr = NULL; + + *got_frame = 1; + } + + return buf_size; + } + + if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) { + if (v->profile < PROFILE_ADVANCED) + avctx->pix_fmt = AV_PIX_FMT_VDPAU_WMV3; + else + avctx->pix_fmt = AV_PIX_FMT_VDPAU_VC1; + } + + //for advanced profile we may need to parse and unescape data + if (avctx->codec_id == AV_CODEC_ID_VC1 || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { + int buf_size2 = 0; + buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + + if (IS_MARKER(AV_RB32(buf))) { /* frame starts with marker and needs to be parsed */ + const uint8_t *start, *end, *next; + int size; + + next = buf; + for (start = buf, end = buf + buf_size; next < end; start = next) { + next = find_next_marker(start + 4, end); + size = next - start - 4; + if (size <= 0) continue; + switch (AV_RB32(start)) { + case VC1_CODE_FRAME: + if (avctx->hwaccel || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) + buf_start = start; + buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); + break; + case VC1_CODE_FIELD: { + int buf_size3; + if (avctx->hwaccel || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) + buf_start_second_field = start; + tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + if (!tmp) + goto err; + slices = tmp; + slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!slices[n_slices].buf) + goto err; + buf_size3 = vc1_unescape_buffer(start + 4, size, + slices[n_slices].buf); + init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, + buf_size3 << 3); + /* assuming that the field marker is at the exact middle, + hope it's correct */ + slices[n_slices].mby_start = s->mb_height >> 1; + n_slices1 = n_slices - 1; // index of the last slice of the first field + n_slices++; + break; + } + case VC1_CODE_ENTRYPOINT: /* it should be before frame data */ + buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); + init_get_bits(&s->gb, buf2, buf_size2 * 8); + ff_vc1_decode_entry_point(avctx, v, &s->gb); + break; + case VC1_CODE_SLICE: { + int buf_size3; + tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + if (!tmp) + goto err; + slices = tmp; + slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!slices[n_slices].buf) + goto err; + buf_size3 = vc1_unescape_buffer(start + 4, size, + slices[n_slices].buf); + init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, + buf_size3 << 3); + slices[n_slices].mby_start = get_bits(&slices[n_slices].gb, 9); + n_slices++; + break; + } + } + } + } else if (v->interlace && ((buf[0] & 0xC0) == 0xC0)) { /* WVC1 interlaced stores both fields divided by marker */ + const uint8_t *divider; + int buf_size3; + + divider = find_next_marker(buf, buf + buf_size); + if ((divider == (buf + buf_size)) || AV_RB32(divider) != VC1_CODE_FIELD) { + av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n"); + goto err; + } else { // found field marker, unescape second field + if (avctx->hwaccel || + s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) + buf_start_second_field = divider; + tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + if (!tmp) + goto err; + slices = tmp; + slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!slices[n_slices].buf) + goto err; + buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf); + init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, + buf_size3 << 3); + slices[n_slices].mby_start = s->mb_height >> 1; + n_slices1 = n_slices - 1; + n_slices++; + } + buf_size2 = vc1_unescape_buffer(buf, divider - buf, buf2); + } else { + buf_size2 = vc1_unescape_buffer(buf, buf_size, buf2); + } + init_get_bits(&s->gb, buf2, buf_size2*8); + } else + init_get_bits(&s->gb, buf, buf_size*8); + + if (v->res_sprite) { + v->new_sprite = !get_bits1(&s->gb); + v->two_sprites = get_bits1(&s->gb); + /* res_sprite means a Windows Media Image stream, AV_CODEC_ID_*IMAGE means + we're using the sprite compositor. These are intentionally kept separate + so you can get the raw sprites by using the wmv3 decoder for WMVP or + the vc1 one for WVP2 */ + if (avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { + if (v->new_sprite) { + // switch AVCodecContext parameters to those of the sprites + avctx->width = avctx->coded_width = v->sprite_width; + avctx->height = avctx->coded_height = v->sprite_height; + } else { + goto image; + } + } + } + + if (s->context_initialized && + (s->width != avctx->coded_width || + s->height != avctx->coded_height)) { + ff_vc1_decode_end(avctx); + } + + if (!s->context_initialized) { + if (ff_msmpeg4_decode_init(avctx) < 0 || ff_vc1_decode_init_alloc_tables(v) < 0) + goto err; + + s->low_delay = !avctx->has_b_frames || v->res_sprite; + + if (v->profile == PROFILE_ADVANCED) { + if(avctx->coded_width<=1 || avctx->coded_height<=1) + goto err; + s->h_edge_pos = avctx->coded_width; + s->v_edge_pos = avctx->coded_height; + } + } + + /* We need to set current_picture_ptr before reading the header, + * otherwise we cannot store anything in there. */ + if (s->current_picture_ptr == NULL || s->current_picture_ptr->f.data[0]) { + int i = ff_find_unused_picture(s, 0); + if (i < 0) + goto err; + s->current_picture_ptr = &s->picture[i]; + } + + // do parse frame header + v->pic_header_flag = 0; + v->first_pic_header_flag = 1; + if (v->profile < PROFILE_ADVANCED) { + if (ff_vc1_parse_frame_header(v, &s->gb) < 0) { + goto err; + } + } else { + if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) { + goto err; + } + } + v->first_pic_header_flag = 0; + + if (avctx->debug & FF_DEBUG_PICT_INFO) + av_log(v->s.avctx, AV_LOG_DEBUG, "pict_type: %c\n", av_get_picture_type_char(s->pict_type)); + + if ((avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) + && s->pict_type != AV_PICTURE_TYPE_I) { + av_log(v->s.avctx, AV_LOG_ERROR, "Sprite decoder: expected I-frame\n"); + goto err; + } + + if ((s->mb_height >> v->field_mode) == 0) { + av_log(v->s.avctx, AV_LOG_ERROR, "image too short\n"); + goto err; + } + + // process pulldown flags + s->current_picture_ptr->f.repeat_pict = 0; + // Pulldown flags are only valid when 'broadcast' has been set. + // So ticks_per_frame will be 2 + if (v->rff) { + // repeat field + s->current_picture_ptr->f.repeat_pict = 1; + } else if (v->rptfrm) { + // repeat frames + s->current_picture_ptr->f.repeat_pict = v->rptfrm * 2; + } + + // for skipping the frame + s->current_picture.f.pict_type = s->pict_type; + s->current_picture.f.key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + /* skip B-frames if we don't have reference frames */ + if (s->last_picture_ptr == NULL && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) { + goto err; + } + if ((avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B) || + (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I) || + avctx->skip_frame >= AVDISCARD_ALL) { + goto end; + } + + if (s->next_p_frame_damaged) { + if (s->pict_type == AV_PICTURE_TYPE_B) + goto end; + else + s->next_p_frame_damaged = 0; + } + + if (ff_MPV_frame_start(s, avctx) < 0) { + goto err; + } + + v->s.current_picture_ptr->f.interlaced_frame = (v->fcm != PROGRESSIVE); + v->s.current_picture_ptr->f.top_field_first = v->tff; + + s->me.qpel_put = s->dsp.put_qpel_pixels_tab; + s->me.qpel_avg = s->dsp.avg_qpel_pixels_tab; + + if ((CONFIG_VC1_VDPAU_DECODER) + &&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) + ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start); + else if (avctx->hwaccel) { + if (v->field_mode && buf_start_second_field) { + // decode first field + s->picture_structure = PICT_BOTTOM_FIELD - v->tff; + if (avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start) < 0) + goto err; + if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start) < 0) + goto err; + if (avctx->hwaccel->end_frame(avctx) < 0) + goto err; + + // decode second field + s->gb = slices[n_slices1 + 1].gb; + s->picture_structure = PICT_TOP_FIELD + v->tff; + v->second_field = 1; + v->pic_header_flag = 0; + if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) { + av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed"); + goto err; + } + v->s.current_picture_ptr->f.pict_type = v->s.pict_type; + + if (avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0) + goto err; + if (avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0) + goto err; + if (avctx->hwaccel->end_frame(avctx) < 0) + goto err; + } else { + s->picture_structure = PICT_FRAME; + if (avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start) < 0) + goto err; + if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0) + goto err; + if (avctx->hwaccel->end_frame(avctx) < 0) + goto err; + } + } else { + int header_ret = 0; + + + ff_mpeg_er_frame_start(s); + + v->bits = buf_size * 8; + v->end_mb_x = s->mb_width; + if (v->field_mode) { + uint8_t *tmp[2]; + s->current_picture.f.linesize[0] <<= 1; + s->current_picture.f.linesize[1] <<= 1; + s->current_picture.f.linesize[2] <<= 1; + s->linesize <<= 1; + s->uvlinesize <<= 1; + tmp[0] = v->mv_f_last[0]; + tmp[1] = v->mv_f_last[1]; + v->mv_f_last[0] = v->mv_f_next[0]; + v->mv_f_last[1] = v->mv_f_next[1]; + v->mv_f_next[0] = v->mv_f[0]; + v->mv_f_next[1] = v->mv_f[1]; + v->mv_f[0] = tmp[0]; + v->mv_f[1] = tmp[1]; + } + mb_height = s->mb_height >> v->field_mode; + for (i = 0; i <= n_slices; i++) { + if (i > 0 && slices[i - 1].mby_start >= mb_height) { + if (v->field_mode <= 0) { + av_log(v->s.avctx, AV_LOG_ERROR, "Slice %d starts beyond " + "picture boundary (%d >= %d)\n", i, + slices[i - 1].mby_start, mb_height); + continue; + } + v->second_field = 1; + v->blocks_off = s->b8_stride * (s->mb_height&~1); + v->mb_off = s->mb_stride * s->mb_height >> 1; + } else { + v->second_field = 0; + v->blocks_off = 0; + v->mb_off = 0; + } + if (i) { + v->pic_header_flag = 0; + if (v->field_mode && i == n_slices1 + 2) { + if ((header_ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) { + av_log(v->s.avctx, AV_LOG_ERROR, "Field header damaged\n"); + continue; + } + } else if (get_bits1(&s->gb)) { + v->pic_header_flag = 1; + if ((header_ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) { + av_log(v->s.avctx, AV_LOG_ERROR, "Slice header damaged\n"); + continue; + } + } + } + if (header_ret < 0) + continue; + s->start_mb_y = (i == 0) ? 0 : FFMAX(0, slices[i-1].mby_start % mb_height); + if (!v->field_mode || v->second_field) + s->end_mb_y = (i == n_slices ) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height); + else { + if (i >= n_slices) { + av_log(v->s.avctx, AV_LOG_ERROR, "first field slice count too large\n"); + continue; + } + s->end_mb_y = (i <= n_slices1 + 1) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height); + } + if (s->end_mb_y <= s->start_mb_y) { + av_log(v->s.avctx, AV_LOG_ERROR, "end mb y %d %d invalid\n", s->end_mb_y, s->start_mb_y); + continue; + } + if (!v->p_frame_skipped && s->pict_type != AV_PICTURE_TYPE_I && !v->cbpcy_vlc) { + av_log(v->s.avctx, AV_LOG_ERROR, "missing cbpcy_vlc\n"); + continue; + } + ff_vc1_decode_blocks(v); + if (i != n_slices) + s->gb = slices[i].gb; + } + if (v->field_mode) { + v->second_field = 0; + if (s->pict_type == AV_PICTURE_TYPE_B) { + memcpy(v->mv_f_base, v->mv_f_next_base, + 2 * (s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2)); + } + s->current_picture.f.linesize[0] >>= 1; + s->current_picture.f.linesize[1] >>= 1; + s->current_picture.f.linesize[2] >>= 1; + s->linesize >>= 1; + s->uvlinesize >>= 1; + } + av_dlog(s->avctx, "Consumed %i/%i bits\n", + get_bits_count(&s->gb), s->gb.size_in_bits); +// if (get_bits_count(&s->gb) > buf_size * 8) +// return -1; + if(s->er.error_occurred && s->pict_type == AV_PICTURE_TYPE_B) + goto err; + if(!v->field_mode) + ff_er_frame_end(&s->er); + } + + ff_MPV_frame_end(s); + + if (avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) { +image: + avctx->width = avctx->coded_width = v->output_width; + avctx->height = avctx->coded_height = v->output_height; + if (avctx->skip_frame >= AVDISCARD_NONREF) + goto end; +#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER + if (vc1_decode_sprites(v, &s->gb)) + goto err; +#endif + if ((ret = av_frame_ref(pict, &v->sprite_output_frame)) < 0) + goto err; + *got_frame = 1; + } else { + if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { + if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0) + goto err; + ff_print_debug_info(s, s->current_picture_ptr, pict); + } else if (s->last_picture_ptr != NULL) { + if ((ret = av_frame_ref(pict, &s->last_picture_ptr->f)) < 0) + goto err; + ff_print_debug_info(s, s->last_picture_ptr, pict); + } + if (s->last_picture_ptr || s->low_delay) { + *got_frame = 1; + } + } + +end: + av_free(buf2); + for (i = 0; i < n_slices; i++) + av_free(slices[i].buf); + av_free(slices); + return buf_size; + +err: + av_free(buf2); + for (i = 0; i < n_slices; i++) + av_free(slices[i].buf); + av_free(slices); + return -1; +} + + +static const AVProfile profiles[] = { + { FF_PROFILE_VC1_SIMPLE, "Simple" }, + { FF_PROFILE_VC1_MAIN, "Main" }, + { FF_PROFILE_VC1_COMPLEX, "Complex" }, + { FF_PROFILE_VC1_ADVANCED, "Advanced" }, + { FF_PROFILE_UNKNOWN }, +}; + +static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = { +#if CONFIG_DXVA2 + AV_PIX_FMT_DXVA2_VLD, +#endif +#if CONFIG_VAAPI + AV_PIX_FMT_VAAPI_VLD, +#endif +#if CONFIG_VDPAU + AV_PIX_FMT_VDPAU, +#endif + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +AVCodec ff_vc1_decoder = { + .name = "vc1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .priv_data_size = sizeof(VC1Context), + .init = vc1_decode_init, + .close = ff_vc1_decode_end, + .decode = vc1_decode_frame, + .flush = ff_mpeg_flush, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), + .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .profiles = NULL_IF_CONFIG_SMALL(profiles) +}; + +#if CONFIG_WMV3_DECODER +AVCodec ff_wmv3_decoder = { + .name = "wmv3", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .priv_data_size = sizeof(VC1Context), + .init = vc1_decode_init, + .close = ff_vc1_decode_end, + .decode = vc1_decode_frame, + .flush = ff_mpeg_flush, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), + .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .profiles = NULL_IF_CONFIG_SMALL(profiles) +}; +#endif + +#if CONFIG_WMV3_VDPAU_DECODER +AVCodec ff_wmv3_vdpau_decoder = { + .name = "wmv3_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .priv_data_size = sizeof(VC1Context), + .init = vc1_decode_init, + .close = ff_vc1_decode_end, + .decode = vc1_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 VDPAU"), + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU_WMV3, AV_PIX_FMT_NONE }, + .profiles = NULL_IF_CONFIG_SMALL(profiles) +}; +#endif + +#if CONFIG_VC1_VDPAU_DECODER +AVCodec ff_vc1_vdpau_decoder = { + .name = "vc1_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .priv_data_size = sizeof(VC1Context), + .init = vc1_decode_init, + .close = ff_vc1_decode_end, + .decode = vc1_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU, + .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1 VDPAU"), + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU_VC1, AV_PIX_FMT_NONE }, + .profiles = NULL_IF_CONFIG_SMALL(profiles) +}; +#endif + +#if CONFIG_WMV3IMAGE_DECODER +AVCodec ff_wmv3image_decoder = { + .name = "wmv3image", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3IMAGE, + .priv_data_size = sizeof(VC1Context), + .init = vc1_decode_init, + .close = ff_vc1_decode_end, + .decode = vc1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = vc1_sprite_flush, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), + .pix_fmts = ff_pixfmt_list_420 +}; +#endif + +#if CONFIG_VC1IMAGE_DECODER +AVCodec ff_vc1image_decoder = { + .name = "vc1image", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1IMAGE, + .priv_data_size = sizeof(VC1Context), + .init = vc1_decode_init, + .close = ff_vc1_decode_end, + .decode = vc1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .flush = vc1_sprite_flush, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), + .pix_fmts = ff_pixfmt_list_420 +}; +#endif diff --git a/ffmpeg/libavcodec/vc1dsp.c b/ffmpeg/libavcodec/vc1dsp.c new file mode 100644 index 0000000..f66921a --- /dev/null +++ b/ffmpeg/libavcodec/vc1dsp.c @@ -0,0 +1,874 @@ +/* + * VC-1 and WMV3 decoder - DSP functions + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** +* @file + * VC-1 and WMV3 decoder + * + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "h264chroma.h" +#include "rnd_avg.h" +#include "vc1dsp.h" + + +/** Apply overlap transform to horizontal edge +*/ +static void vc1_v_overlap_c(uint8_t* src, int stride) +{ + int i; + int a, b, c, d; + int d1, d2; + int rnd = 1; + for(i = 0; i < 8; i++) { + a = src[-2*stride]; + b = src[-stride]; + c = src[0]; + d = src[stride]; + d1 = (a - d + 3 + rnd) >> 3; + d2 = (a - d + b - c + 4 - rnd) >> 3; + + src[-2*stride] = a - d1; + src[-stride] = av_clip_uint8(b - d2); + src[0] = av_clip_uint8(c + d2); + src[stride] = d + d1; + src++; + rnd = !rnd; + } +} + +/** Apply overlap transform to vertical edge +*/ +static void vc1_h_overlap_c(uint8_t* src, int stride) +{ + int i; + int a, b, c, d; + int d1, d2; + int rnd = 1; + for(i = 0; i < 8; i++) { + a = src[-2]; + b = src[-1]; + c = src[0]; + d = src[1]; + d1 = (a - d + 3 + rnd) >> 3; + d2 = (a - d + b - c + 4 - rnd) >> 3; + + src[-2] = a - d1; + src[-1] = av_clip_uint8(b - d2); + src[0] = av_clip_uint8(c + d2); + src[1] = d + d1; + src += stride; + rnd = !rnd; + } +} + +static void vc1_v_s_overlap_c(int16_t *top, int16_t *bottom) +{ + int i; + int a, b, c, d; + int d1, d2; + int rnd1 = 4, rnd2 = 3; + for(i = 0; i < 8; i++) { + a = top[48]; + b = top[56]; + c = bottom[0]; + d = bottom[8]; + d1 = a - d; + d2 = a - d + b - c; + + top[48] = ((a << 3) - d1 + rnd1) >> 3; + top[56] = ((b << 3) - d2 + rnd2) >> 3; + bottom[0] = ((c << 3) + d2 + rnd1) >> 3; + bottom[8] = ((d << 3) + d1 + rnd2) >> 3; + + bottom++; + top++; + rnd2 = 7 - rnd2; + rnd1 = 7 - rnd1; + } +} + +static void vc1_h_s_overlap_c(int16_t *left, int16_t *right) +{ + int i; + int a, b, c, d; + int d1, d2; + int rnd1 = 4, rnd2 = 3; + for(i = 0; i < 8; i++) { + a = left[6]; + b = left[7]; + c = right[0]; + d = right[1]; + d1 = a - d; + d2 = a - d + b - c; + + left[6] = ((a << 3) - d1 + rnd1) >> 3; + left[7] = ((b << 3) - d2 + rnd2) >> 3; + right[0] = ((c << 3) + d2 + rnd1) >> 3; + right[1] = ((d << 3) + d1 + rnd2) >> 3; + + right += 8; + left += 8; + rnd2 = 7 - rnd2; + rnd1 = 7 - rnd1; + } +} + +/** + * VC-1 in-loop deblocking filter for one line + * @param src source block type + * @param stride block stride + * @param pq block quantizer + * @return whether other 3 pairs should be filtered or not + * @see 8.6 + */ +static av_always_inline int vc1_filter_line(uint8_t* src, int stride, int pq){ + int a0 = (2*(src[-2*stride] - src[ 1*stride]) - 5*(src[-1*stride] - src[ 0*stride]) + 4) >> 3; + int a0_sign = a0 >> 31; /* Store sign */ + a0 = (a0 ^ a0_sign) - a0_sign; /* a0 = FFABS(a0); */ + if(a0 < pq){ + int a1 = FFABS((2*(src[-4*stride] - src[-1*stride]) - 5*(src[-3*stride] - src[-2*stride]) + 4) >> 3); + int a2 = FFABS((2*(src[ 0*stride] - src[ 3*stride]) - 5*(src[ 1*stride] - src[ 2*stride]) + 4) >> 3); + if(a1 < a0 || a2 < a0){ + int clip = src[-1*stride] - src[ 0*stride]; + int clip_sign = clip >> 31; + clip = ((clip ^ clip_sign) - clip_sign)>>1; + if(clip){ + int a3 = FFMIN(a1, a2); + int d = 5 * (a3 - a0); + int d_sign = (d >> 31); + d = ((d ^ d_sign) - d_sign) >> 3; + d_sign ^= a0_sign; + + if( d_sign ^ clip_sign ) + d = 0; + else{ + d = FFMIN(d, clip); + d = (d ^ d_sign) - d_sign; /* Restore sign */ + src[-1*stride] = av_clip_uint8(src[-1*stride] - d); + src[ 0*stride] = av_clip_uint8(src[ 0*stride] + d); + } + return 1; + } + } + } + return 0; +} + +/** + * VC-1 in-loop deblocking filter + * @param src source block type + * @param step distance between horizontally adjacent elements + * @param stride distance between vertically adjacent elements + * @param len edge length to filter (4 or 8 pixels) + * @param pq block quantizer + * @see 8.6 + */ +static inline void vc1_loop_filter(uint8_t* src, int step, int stride, int len, int pq) +{ + int i; + int filt3; + + for(i = 0; i < len; i += 4){ + filt3 = vc1_filter_line(src + 2*step, stride, pq); + if(filt3){ + vc1_filter_line(src + 0*step, stride, pq); + vc1_filter_line(src + 1*step, stride, pq); + vc1_filter_line(src + 3*step, stride, pq); + } + src += step * 4; + } +} + +static void vc1_v_loop_filter4_c(uint8_t *src, int stride, int pq) +{ + vc1_loop_filter(src, 1, stride, 4, pq); +} + +static void vc1_h_loop_filter4_c(uint8_t *src, int stride, int pq) +{ + vc1_loop_filter(src, stride, 1, 4, pq); +} + +static void vc1_v_loop_filter8_c(uint8_t *src, int stride, int pq) +{ + vc1_loop_filter(src, 1, stride, 8, pq); +} + +static void vc1_h_loop_filter8_c(uint8_t *src, int stride, int pq) +{ + vc1_loop_filter(src, stride, 1, 8, pq); +} + +static void vc1_v_loop_filter16_c(uint8_t *src, int stride, int pq) +{ + vc1_loop_filter(src, 1, stride, 16, pq); +} + +static void vc1_h_loop_filter16_c(uint8_t *src, int stride, int pq) +{ + vc1_loop_filter(src, stride, 1, 16, pq); +} + +/** Do inverse transform on 8x8 block +*/ +static void vc1_inv_trans_8x8_dc_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + int dc = block[0]; + dc = (3 * dc + 1) >> 1; + dc = (3 * dc + 16) >> 5; + for(i = 0; i < 8; i++){ + dest[0] = av_clip_uint8(dest[0] + dc); + dest[1] = av_clip_uint8(dest[1] + dc); + dest[2] = av_clip_uint8(dest[2] + dc); + dest[3] = av_clip_uint8(dest[3] + dc); + dest[4] = av_clip_uint8(dest[4] + dc); + dest[5] = av_clip_uint8(dest[5] + dc); + dest[6] = av_clip_uint8(dest[6] + dc); + dest[7] = av_clip_uint8(dest[7] + dc); + dest += linesize; + } +} + +static void vc1_inv_trans_8x8_c(int16_t block[64]) +{ + int i; + register int t1,t2,t3,t4,t5,t6,t7,t8; + int16_t *src, *dst, temp[64]; + + src = block; + dst = temp; + for(i = 0; i < 8; i++){ + t1 = 12 * (src[ 0] + src[32]) + 4; + t2 = 12 * (src[ 0] - src[32]) + 4; + t3 = 16 * src[16] + 6 * src[48]; + t4 = 6 * src[16] - 16 * src[48]; + + t5 = t1 + t3; + t6 = t2 + t4; + t7 = t2 - t4; + t8 = t1 - t3; + + t1 = 16 * src[ 8] + 15 * src[24] + 9 * src[40] + 4 * src[56]; + t2 = 15 * src[ 8] - 4 * src[24] - 16 * src[40] - 9 * src[56]; + t3 = 9 * src[ 8] - 16 * src[24] + 4 * src[40] + 15 * src[56]; + t4 = 4 * src[ 8] - 9 * src[24] + 15 * src[40] - 16 * src[56]; + + dst[0] = (t5 + t1) >> 3; + dst[1] = (t6 + t2) >> 3; + dst[2] = (t7 + t3) >> 3; + dst[3] = (t8 + t4) >> 3; + dst[4] = (t8 - t4) >> 3; + dst[5] = (t7 - t3) >> 3; + dst[6] = (t6 - t2) >> 3; + dst[7] = (t5 - t1) >> 3; + + src += 1; + dst += 8; + } + + src = temp; + dst = block; + for(i = 0; i < 8; i++){ + t1 = 12 * (src[ 0] + src[32]) + 64; + t2 = 12 * (src[ 0] - src[32]) + 64; + t3 = 16 * src[16] + 6 * src[48]; + t4 = 6 * src[16] - 16 * src[48]; + + t5 = t1 + t3; + t6 = t2 + t4; + t7 = t2 - t4; + t8 = t1 - t3; + + t1 = 16 * src[ 8] + 15 * src[24] + 9 * src[40] + 4 * src[56]; + t2 = 15 * src[ 8] - 4 * src[24] - 16 * src[40] - 9 * src[56]; + t3 = 9 * src[ 8] - 16 * src[24] + 4 * src[40] + 15 * src[56]; + t4 = 4 * src[ 8] - 9 * src[24] + 15 * src[40] - 16 * src[56]; + + dst[ 0] = (t5 + t1) >> 7; + dst[ 8] = (t6 + t2) >> 7; + dst[16] = (t7 + t3) >> 7; + dst[24] = (t8 + t4) >> 7; + dst[32] = (t8 - t4 + 1) >> 7; + dst[40] = (t7 - t3 + 1) >> 7; + dst[48] = (t6 - t2 + 1) >> 7; + dst[56] = (t5 - t1 + 1) >> 7; + + src++; + dst++; + } +} + +/** Do inverse transform on 8x4 part of block +*/ +static void vc1_inv_trans_8x4_dc_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + int dc = block[0]; + dc = ( 3 * dc + 1) >> 1; + dc = (17 * dc + 64) >> 7; + for(i = 0; i < 4; i++){ + dest[0] = av_clip_uint8(dest[0] + dc); + dest[1] = av_clip_uint8(dest[1] + dc); + dest[2] = av_clip_uint8(dest[2] + dc); + dest[3] = av_clip_uint8(dest[3] + dc); + dest[4] = av_clip_uint8(dest[4] + dc); + dest[5] = av_clip_uint8(dest[5] + dc); + dest[6] = av_clip_uint8(dest[6] + dc); + dest[7] = av_clip_uint8(dest[7] + dc); + dest += linesize; + } +} + +static void vc1_inv_trans_8x4_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + register int t1,t2,t3,t4,t5,t6,t7,t8; + int16_t *src, *dst; + + src = block; + dst = block; + for(i = 0; i < 4; i++){ + t1 = 12 * (src[0] + src[4]) + 4; + t2 = 12 * (src[0] - src[4]) + 4; + t3 = 16 * src[2] + 6 * src[6]; + t4 = 6 * src[2] - 16 * src[6]; + + t5 = t1 + t3; + t6 = t2 + t4; + t7 = t2 - t4; + t8 = t1 - t3; + + t1 = 16 * src[1] + 15 * src[3] + 9 * src[5] + 4 * src[7]; + t2 = 15 * src[1] - 4 * src[3] - 16 * src[5] - 9 * src[7]; + t3 = 9 * src[1] - 16 * src[3] + 4 * src[5] + 15 * src[7]; + t4 = 4 * src[1] - 9 * src[3] + 15 * src[5] - 16 * src[7]; + + dst[0] = (t5 + t1) >> 3; + dst[1] = (t6 + t2) >> 3; + dst[2] = (t7 + t3) >> 3; + dst[3] = (t8 + t4) >> 3; + dst[4] = (t8 - t4) >> 3; + dst[5] = (t7 - t3) >> 3; + dst[6] = (t6 - t2) >> 3; + dst[7] = (t5 - t1) >> 3; + + src += 8; + dst += 8; + } + + src = block; + for(i = 0; i < 8; i++){ + t1 = 17 * (src[ 0] + src[16]) + 64; + t2 = 17 * (src[ 0] - src[16]) + 64; + t3 = 22 * src[ 8] + 10 * src[24]; + t4 = 22 * src[24] - 10 * src[ 8]; + + dest[0*linesize] = av_clip_uint8(dest[0*linesize] + ((t1 + t3) >> 7)); + dest[1*linesize] = av_clip_uint8(dest[1*linesize] + ((t2 - t4) >> 7)); + dest[2*linesize] = av_clip_uint8(dest[2*linesize] + ((t2 + t4) >> 7)); + dest[3*linesize] = av_clip_uint8(dest[3*linesize] + ((t1 - t3) >> 7)); + + src ++; + dest++; + } +} + +/** Do inverse transform on 4x8 parts of block +*/ +static void vc1_inv_trans_4x8_dc_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + int dc = block[0]; + dc = (17 * dc + 4) >> 3; + dc = (12 * dc + 64) >> 7; + for(i = 0; i < 8; i++){ + dest[0] = av_clip_uint8(dest[0] + dc); + dest[1] = av_clip_uint8(dest[1] + dc); + dest[2] = av_clip_uint8(dest[2] + dc); + dest[3] = av_clip_uint8(dest[3] + dc); + dest += linesize; + } +} + +static void vc1_inv_trans_4x8_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + register int t1,t2,t3,t4,t5,t6,t7,t8; + int16_t *src, *dst; + + src = block; + dst = block; + for(i = 0; i < 8; i++){ + t1 = 17 * (src[0] + src[2]) + 4; + t2 = 17 * (src[0] - src[2]) + 4; + t3 = 22 * src[1] + 10 * src[3]; + t4 = 22 * src[3] - 10 * src[1]; + + dst[0] = (t1 + t3) >> 3; + dst[1] = (t2 - t4) >> 3; + dst[2] = (t2 + t4) >> 3; + dst[3] = (t1 - t3) >> 3; + + src += 8; + dst += 8; + } + + src = block; + for(i = 0; i < 4; i++){ + t1 = 12 * (src[ 0] + src[32]) + 64; + t2 = 12 * (src[ 0] - src[32]) + 64; + t3 = 16 * src[16] + 6 * src[48]; + t4 = 6 * src[16] - 16 * src[48]; + + t5 = t1 + t3; + t6 = t2 + t4; + t7 = t2 - t4; + t8 = t1 - t3; + + t1 = 16 * src[ 8] + 15 * src[24] + 9 * src[40] + 4 * src[56]; + t2 = 15 * src[ 8] - 4 * src[24] - 16 * src[40] - 9 * src[56]; + t3 = 9 * src[ 8] - 16 * src[24] + 4 * src[40] + 15 * src[56]; + t4 = 4 * src[ 8] - 9 * src[24] + 15 * src[40] - 16 * src[56]; + + dest[0*linesize] = av_clip_uint8(dest[0*linesize] + ((t5 + t1) >> 7)); + dest[1*linesize] = av_clip_uint8(dest[1*linesize] + ((t6 + t2) >> 7)); + dest[2*linesize] = av_clip_uint8(dest[2*linesize] + ((t7 + t3) >> 7)); + dest[3*linesize] = av_clip_uint8(dest[3*linesize] + ((t8 + t4) >> 7)); + dest[4*linesize] = av_clip_uint8(dest[4*linesize] + ((t8 - t4 + 1) >> 7)); + dest[5*linesize] = av_clip_uint8(dest[5*linesize] + ((t7 - t3 + 1) >> 7)); + dest[6*linesize] = av_clip_uint8(dest[6*linesize] + ((t6 - t2 + 1) >> 7)); + dest[7*linesize] = av_clip_uint8(dest[7*linesize] + ((t5 - t1 + 1) >> 7)); + + src ++; + dest++; + } +} + +/** Do inverse transform on 4x4 part of block +*/ +static void vc1_inv_trans_4x4_dc_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + int dc = block[0]; + dc = (17 * dc + 4) >> 3; + dc = (17 * dc + 64) >> 7; + for(i = 0; i < 4; i++){ + dest[0] = av_clip_uint8(dest[0] + dc); + dest[1] = av_clip_uint8(dest[1] + dc); + dest[2] = av_clip_uint8(dest[2] + dc); + dest[3] = av_clip_uint8(dest[3] + dc); + dest += linesize; + } +} + +static void vc1_inv_trans_4x4_c(uint8_t *dest, int linesize, int16_t *block) +{ + int i; + register int t1,t2,t3,t4; + int16_t *src, *dst; + + src = block; + dst = block; + for(i = 0; i < 4; i++){ + t1 = 17 * (src[0] + src[2]) + 4; + t2 = 17 * (src[0] - src[2]) + 4; + t3 = 22 * src[1] + 10 * src[3]; + t4 = 22 * src[3] - 10 * src[1]; + + dst[0] = (t1 + t3) >> 3; + dst[1] = (t2 - t4) >> 3; + dst[2] = (t2 + t4) >> 3; + dst[3] = (t1 - t3) >> 3; + + src += 8; + dst += 8; + } + + src = block; + for(i = 0; i < 4; i++){ + t1 = 17 * (src[ 0] + src[16]) + 64; + t2 = 17 * (src[ 0] - src[16]) + 64; + t3 = 22 * src[ 8] + 10 * src[24]; + t4 = 22 * src[24] - 10 * src[ 8]; + + dest[0*linesize] = av_clip_uint8(dest[0*linesize] + ((t1 + t3) >> 7)); + dest[1*linesize] = av_clip_uint8(dest[1*linesize] + ((t2 - t4) >> 7)); + dest[2*linesize] = av_clip_uint8(dest[2*linesize] + ((t2 + t4) >> 7)); + dest[3*linesize] = av_clip_uint8(dest[3*linesize] + ((t1 - t3) >> 7)); + + src ++; + dest++; + } +} + +/* motion compensation functions */ +/** Filter in case of 2 filters */ +#define VC1_MSPEL_FILTER_16B(DIR, TYPE) \ +static av_always_inline int vc1_mspel_ ## DIR ## _filter_16bits(const TYPE *src, int stride, int mode) \ +{ \ + switch(mode){ \ + case 0: /* no shift - should not occur */ \ + return 0; \ + case 1: /* 1/4 shift */ \ + return -4*src[-stride] + 53*src[0] + 18*src[stride] - 3*src[stride*2]; \ + case 2: /* 1/2 shift */ \ + return -src[-stride] + 9*src[0] + 9*src[stride] - src[stride*2]; \ + case 3: /* 3/4 shift */ \ + return -3*src[-stride] + 18*src[0] + 53*src[stride] - 4*src[stride*2]; \ + } \ + return 0; /* should not occur */ \ +} + +VC1_MSPEL_FILTER_16B(ver, uint8_t) +VC1_MSPEL_FILTER_16B(hor, int16_t) + + +/** Filter used to interpolate fractional pel values + */ +static av_always_inline int vc1_mspel_filter(const uint8_t *src, int stride, int mode, int r) +{ + switch(mode){ + case 0: //no shift + return src[0]; + case 1: // 1/4 shift + return (-4*src[-stride] + 53*src[0] + 18*src[stride] - 3*src[stride*2] + 32 - r) >> 6; + case 2: // 1/2 shift + return (-src[-stride] + 9*src[0] + 9*src[stride] - src[stride*2] + 8 - r) >> 4; + case 3: // 3/4 shift + return (-3*src[-stride] + 18*src[0] + 53*src[stride] - 4*src[stride*2] + 32 - r) >> 6; + } + return 0; //should not occur +} + +/** Function used to do motion compensation with bicubic interpolation + */ +#define VC1_MSPEL_MC(OP, OP4, OPNAME)\ +static av_always_inline void OPNAME ## vc1_mspel_mc(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int hmode, int vmode, int rnd)\ +{\ + int i, j;\ +\ + if (vmode) { /* Horizontal filter to apply */\ + int r;\ +\ + if (hmode) { /* Vertical filter to apply, output to tmp */\ + static const int shift_value[] = { 0, 5, 1, 5 };\ + int shift = (shift_value[hmode]+shift_value[vmode])>>1;\ + int16_t tmp[11*8], *tptr = tmp;\ +\ + r = (1<<(shift-1)) + rnd-1;\ +\ + src -= 1;\ + for(j = 0; j < 8; j++) {\ + for(i = 0; i < 11; i++)\ + tptr[i] = (vc1_mspel_ver_filter_16bits(src + i, stride, vmode)+r)>>shift;\ + src += stride;\ + tptr += 11;\ + }\ +\ + r = 64-rnd;\ + tptr = tmp+1;\ + for(j = 0; j < 8; j++) {\ + for(i = 0; i < 8; i++)\ + OP(dst[i], (vc1_mspel_hor_filter_16bits(tptr + i, 1, hmode)+r)>>7);\ + dst += stride;\ + tptr += 11;\ + }\ +\ + return;\ + }\ + else { /* No horizontal filter, output 8 lines to dst */\ + r = 1-rnd;\ +\ + for(j = 0; j < 8; j++) {\ + for(i = 0; i < 8; i++)\ + OP(dst[i], vc1_mspel_filter(src + i, stride, vmode, r));\ + src += stride;\ + dst += stride;\ + }\ + return;\ + }\ + }\ +\ + /* Horizontal mode with no vertical mode */\ + for(j = 0; j < 8; j++) {\ + for(i = 0; i < 8; i++)\ + OP(dst[i], vc1_mspel_filter(src + i, 1, hmode, rnd));\ + dst += stride;\ + src += stride;\ + }\ +}\ +static void OPNAME ## pixels8x8_c(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int rnd){\ + int i;\ + for(i=0; i<8; i++){\ + OP4(*(uint32_t*)(block ), AV_RN32(pixels ));\ + OP4(*(uint32_t*)(block+4), AV_RN32(pixels+4));\ + pixels+=line_size;\ + block +=line_size;\ + }\ +} + +#define op_put(a, b) a = av_clip_uint8(b) +#define op_avg(a, b) a = (a + av_clip_uint8(b) + 1) >> 1 +#define op4_avg(a, b) a = rnd_avg32(a, b) +#define op4_put(a, b) a = b + +VC1_MSPEL_MC(op_put, op4_put, put_) +VC1_MSPEL_MC(op_avg, op4_avg, avg_) + +/* pixel functions - really are entry points to vc1_mspel_mc */ + +#define PUT_VC1_MSPEL(a, b)\ +static void put_vc1_mspel_mc ## a ## b ##_c(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc(dst, src, stride, a, b, rnd); \ +} \ +static void avg_vc1_mspel_mc ## a ## b ##_c(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + avg_vc1_mspel_mc(dst, src, stride, a, b, rnd); \ +} + +PUT_VC1_MSPEL(1, 0) +PUT_VC1_MSPEL(2, 0) +PUT_VC1_MSPEL(3, 0) + +PUT_VC1_MSPEL(0, 1) +PUT_VC1_MSPEL(1, 1) +PUT_VC1_MSPEL(2, 1) +PUT_VC1_MSPEL(3, 1) + +PUT_VC1_MSPEL(0, 2) +PUT_VC1_MSPEL(1, 2) +PUT_VC1_MSPEL(2, 2) +PUT_VC1_MSPEL(3, 2) + +PUT_VC1_MSPEL(0, 3) +PUT_VC1_MSPEL(1, 3) +PUT_VC1_MSPEL(2, 3) +PUT_VC1_MSPEL(3, 3) + +static void put_no_rnd_vc1_chroma_mc8_c(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){ + const int A=(8-x)*(8-y); + const int B=( x)*(8-y); + const int C=(8-x)*( y); + const int D=( x)*( y); + int i; + + av_assert2(x<8 && y<8 && x>=0 && y>=0); + + for(i=0; i> 6; + dst[1] = (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + 32 - 4) >> 6; + dst[2] = (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + 32 - 4) >> 6; + dst[3] = (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + 32 - 4) >> 6; + dst[4] = (A*src[4] + B*src[5] + C*src[stride+4] + D*src[stride+5] + 32 - 4) >> 6; + dst[5] = (A*src[5] + B*src[6] + C*src[stride+5] + D*src[stride+6] + 32 - 4) >> 6; + dst[6] = (A*src[6] + B*src[7] + C*src[stride+6] + D*src[stride+7] + 32 - 4) >> 6; + dst[7] = (A*src[7] + B*src[8] + C*src[stride+7] + D*src[stride+8] + 32 - 4) >> 6; + dst+= stride; + src+= stride; + } +} + +static void put_no_rnd_vc1_chroma_mc4_c(uint8_t *dst, uint8_t *src, int stride, int h, int x, int y){ + const int A=(8-x)*(8-y); + const int B=( x)*(8-y); + const int C=(8-x)*( y); + const int D=( x)*( y); + int i; + + av_assert2(x<8 && y<8 && x>=0 && y>=0); + + for(i=0; i> 6; + dst[1] = (A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + 32 - 4) >> 6; + dst[2] = (A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + 32 - 4) >> 6; + dst[3] = (A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + 32 - 4) >> 6; + dst+= stride; + src+= stride; + } +} + +#define avg2(a,b) ((a+b+1)>>1) +static void avg_no_rnd_vc1_chroma_mc8_c(uint8_t *dst/*align 8*/, uint8_t *src/*align 1*/, int stride, int h, int x, int y){ + const int A=(8-x)*(8-y); + const int B=( x)*(8-y); + const int C=(8-x)*( y); + const int D=( x)*( y); + int i; + + av_assert2(x<8 && y<8 && x>=0 && y>=0); + + for(i=0; i> 6)); + dst[1] = avg2(dst[1], ((A*src[1] + B*src[2] + C*src[stride+1] + D*src[stride+2] + 32 - 4) >> 6)); + dst[2] = avg2(dst[2], ((A*src[2] + B*src[3] + C*src[stride+2] + D*src[stride+3] + 32 - 4) >> 6)); + dst[3] = avg2(dst[3], ((A*src[3] + B*src[4] + C*src[stride+3] + D*src[stride+4] + 32 - 4) >> 6)); + dst[4] = avg2(dst[4], ((A*src[4] + B*src[5] + C*src[stride+4] + D*src[stride+5] + 32 - 4) >> 6)); + dst[5] = avg2(dst[5], ((A*src[5] + B*src[6] + C*src[stride+5] + D*src[stride+6] + 32 - 4) >> 6)); + dst[6] = avg2(dst[6], ((A*src[6] + B*src[7] + C*src[stride+6] + D*src[stride+7] + 32 - 4) >> 6)); + dst[7] = avg2(dst[7], ((A*src[7] + B*src[8] + C*src[stride+7] + D*src[stride+8] + 32 - 4) >> 6)); + dst+= stride; + src+= stride; + } +} + +#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER + +static void sprite_h_c(uint8_t *dst, const uint8_t *src, int offset, int advance, int count) +{ + while (count--) { + int a = src[(offset >> 16) ]; + int b = src[(offset >> 16) + 1]; + *dst++ = a + ((b - a) * (offset&0xFFFF) >> 16); + offset += advance; + } +} + +static av_always_inline void sprite_v_template(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, + int two_sprites, const uint8_t *src2a, const uint8_t *src2b, int offset2, + int alpha, int scaled, int width) +{ + int a1, b1, a2, b2; + while (width--) { + a1 = *src1a++; + if (scaled) { + b1 = *src1b++; + a1 = a1 + ((b1 - a1) * offset1 >> 16); + } + if (two_sprites) { + a2 = *src2a++; + if (scaled > 1) { + b2 = *src2b++; + a2 = a2 + ((b2 - a2) * offset2 >> 16); + } + a1 = a1 + ((a2 - a1) * alpha >> 16); + } + *dst++ = a1; + } +} + +static void sprite_v_single_c(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset, int width) +{ + sprite_v_template(dst, src1a, src1b, offset, 0, NULL, NULL, 0, 0, 1, width); +} + +static void sprite_v_double_noscale_c(uint8_t *dst, const uint8_t *src1a, const uint8_t *src2a, int alpha, int width) +{ + sprite_v_template(dst, src1a, NULL, 0, 1, src2a, NULL, 0, alpha, 0, width); +} + +static void sprite_v_double_onescale_c(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, + const uint8_t *src2a, int alpha, int width) +{ + sprite_v_template(dst, src1a, src1b, offset1, 1, src2a, NULL, 0, alpha, 1, width); +} + +static void sprite_v_double_twoscale_c(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, + const uint8_t *src2a, const uint8_t *src2b, int offset2, + int alpha, int width) +{ + sprite_v_template(dst, src1a, src1b, offset1, 1, src2a, src2b, offset2, alpha, 2, width); +} + +#endif + +av_cold void ff_vc1dsp_init(VC1DSPContext* dsp) { + dsp->vc1_inv_trans_8x8 = vc1_inv_trans_8x8_c; + dsp->vc1_inv_trans_4x8 = vc1_inv_trans_4x8_c; + dsp->vc1_inv_trans_8x4 = vc1_inv_trans_8x4_c; + dsp->vc1_inv_trans_4x4 = vc1_inv_trans_4x4_c; + dsp->vc1_inv_trans_8x8_dc = vc1_inv_trans_8x8_dc_c; + dsp->vc1_inv_trans_4x8_dc = vc1_inv_trans_4x8_dc_c; + dsp->vc1_inv_trans_8x4_dc = vc1_inv_trans_8x4_dc_c; + dsp->vc1_inv_trans_4x4_dc = vc1_inv_trans_4x4_dc_c; + dsp->vc1_h_overlap = vc1_h_overlap_c; + dsp->vc1_v_overlap = vc1_v_overlap_c; + dsp->vc1_h_s_overlap = vc1_h_s_overlap_c; + dsp->vc1_v_s_overlap = vc1_v_s_overlap_c; + dsp->vc1_v_loop_filter4 = vc1_v_loop_filter4_c; + dsp->vc1_h_loop_filter4 = vc1_h_loop_filter4_c; + dsp->vc1_v_loop_filter8 = vc1_v_loop_filter8_c; + dsp->vc1_h_loop_filter8 = vc1_h_loop_filter8_c; + dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_c; + dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_c; + + dsp->put_vc1_mspel_pixels_tab[ 0] = put_pixels8x8_c; + dsp->put_vc1_mspel_pixels_tab[ 1] = put_vc1_mspel_mc10_c; + dsp->put_vc1_mspel_pixels_tab[ 2] = put_vc1_mspel_mc20_c; + dsp->put_vc1_mspel_pixels_tab[ 3] = put_vc1_mspel_mc30_c; + dsp->put_vc1_mspel_pixels_tab[ 4] = put_vc1_mspel_mc01_c; + dsp->put_vc1_mspel_pixels_tab[ 5] = put_vc1_mspel_mc11_c; + dsp->put_vc1_mspel_pixels_tab[ 6] = put_vc1_mspel_mc21_c; + dsp->put_vc1_mspel_pixels_tab[ 7] = put_vc1_mspel_mc31_c; + dsp->put_vc1_mspel_pixels_tab[ 8] = put_vc1_mspel_mc02_c; + dsp->put_vc1_mspel_pixels_tab[ 9] = put_vc1_mspel_mc12_c; + dsp->put_vc1_mspel_pixels_tab[10] = put_vc1_mspel_mc22_c; + dsp->put_vc1_mspel_pixels_tab[11] = put_vc1_mspel_mc32_c; + dsp->put_vc1_mspel_pixels_tab[12] = put_vc1_mspel_mc03_c; + dsp->put_vc1_mspel_pixels_tab[13] = put_vc1_mspel_mc13_c; + dsp->put_vc1_mspel_pixels_tab[14] = put_vc1_mspel_mc23_c; + dsp->put_vc1_mspel_pixels_tab[15] = put_vc1_mspel_mc33_c; + + dsp->avg_vc1_mspel_pixels_tab[ 0] = avg_pixels8x8_c; + dsp->avg_vc1_mspel_pixels_tab[ 1] = avg_vc1_mspel_mc10_c; + dsp->avg_vc1_mspel_pixels_tab[ 2] = avg_vc1_mspel_mc20_c; + dsp->avg_vc1_mspel_pixels_tab[ 3] = avg_vc1_mspel_mc30_c; + dsp->avg_vc1_mspel_pixels_tab[ 4] = avg_vc1_mspel_mc01_c; + dsp->avg_vc1_mspel_pixels_tab[ 5] = avg_vc1_mspel_mc11_c; + dsp->avg_vc1_mspel_pixels_tab[ 6] = avg_vc1_mspel_mc21_c; + dsp->avg_vc1_mspel_pixels_tab[ 7] = avg_vc1_mspel_mc31_c; + dsp->avg_vc1_mspel_pixels_tab[ 8] = avg_vc1_mspel_mc02_c; + dsp->avg_vc1_mspel_pixels_tab[ 9] = avg_vc1_mspel_mc12_c; + dsp->avg_vc1_mspel_pixels_tab[10] = avg_vc1_mspel_mc22_c; + dsp->avg_vc1_mspel_pixels_tab[11] = avg_vc1_mspel_mc32_c; + dsp->avg_vc1_mspel_pixels_tab[12] = avg_vc1_mspel_mc03_c; + dsp->avg_vc1_mspel_pixels_tab[13] = avg_vc1_mspel_mc13_c; + dsp->avg_vc1_mspel_pixels_tab[14] = avg_vc1_mspel_mc23_c; + dsp->avg_vc1_mspel_pixels_tab[15] = avg_vc1_mspel_mc33_c; + + dsp->put_no_rnd_vc1_chroma_pixels_tab[0]= put_no_rnd_vc1_chroma_mc8_c; + dsp->avg_no_rnd_vc1_chroma_pixels_tab[0]= avg_no_rnd_vc1_chroma_mc8_c; + dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = put_no_rnd_vc1_chroma_mc4_c; + +#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER + dsp->sprite_h = sprite_h_c; + dsp->sprite_v_single = sprite_v_single_c; + dsp->sprite_v_double_noscale = sprite_v_double_noscale_c; + dsp->sprite_v_double_onescale = sprite_v_double_onescale_c; + dsp->sprite_v_double_twoscale = sprite_v_double_twoscale_c; +#endif + + if (HAVE_ALTIVEC) + ff_vc1dsp_init_altivec(dsp); + if (ARCH_X86) + ff_vc1dsp_init_x86(dsp); +} diff --git a/ffmpeg/libavcodec/vc1dsp.h b/ffmpeg/libavcodec/vc1dsp.h new file mode 100644 index 0000000..851e40c --- /dev/null +++ b/ffmpeg/libavcodec/vc1dsp.h @@ -0,0 +1,82 @@ +/* + * VC-1 and WMV3 decoder - DSP functions + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * VC-1 and WMV3 decoder + * + */ + +#ifndef AVCODEC_VC1DSP_H +#define AVCODEC_VC1DSP_H + +#include "dsputil.h" +#include "h264chroma.h" + +typedef void (*vc1op_pixels_func)(uint8_t *block/*align width (8 or 16)*/, const uint8_t *pixels/*align 1*/, ptrdiff_t line_size, int h); + +typedef struct VC1DSPContext { + /* vc1 functions */ + void (*vc1_inv_trans_8x8)(int16_t *b); + void (*vc1_inv_trans_8x4)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_inv_trans_4x8)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_inv_trans_4x4)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_inv_trans_8x8_dc)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_inv_trans_8x4_dc)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_inv_trans_4x8_dc)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_inv_trans_4x4_dc)(uint8_t *dest, int line_size, int16_t *block); + void (*vc1_v_overlap)(uint8_t *src, int stride); + void (*vc1_h_overlap)(uint8_t *src, int stride); + void (*vc1_v_s_overlap)(int16_t *top, int16_t *bottom); + void (*vc1_h_s_overlap)(int16_t *left, int16_t *right); + void (*vc1_v_loop_filter4)(uint8_t *src, int stride, int pq); + void (*vc1_h_loop_filter4)(uint8_t *src, int stride, int pq); + void (*vc1_v_loop_filter8)(uint8_t *src, int stride, int pq); + void (*vc1_h_loop_filter8)(uint8_t *src, int stride, int pq); + void (*vc1_v_loop_filter16)(uint8_t *src, int stride, int pq); + void (*vc1_h_loop_filter16)(uint8_t *src, int stride, int pq); + + /* put 8x8 block with bicubic interpolation and quarterpel precision + * last argument is actually round value instead of height + */ + vc1op_pixels_func put_vc1_mspel_pixels_tab[16]; + vc1op_pixels_func avg_vc1_mspel_pixels_tab[16]; + + /* This is really one func used in VC-1 decoding */ + h264_chroma_mc_func put_no_rnd_vc1_chroma_pixels_tab[3]; + h264_chroma_mc_func avg_no_rnd_vc1_chroma_pixels_tab[3]; + + /* Windows Media Image functions */ + void (*sprite_h)(uint8_t *dst, const uint8_t *src, int offset, int advance, int count); + void (*sprite_v_single)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset, int width); + void (*sprite_v_double_noscale)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src2a, int alpha, int width); + void (*sprite_v_double_onescale)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, + const uint8_t *src2a, int alpha, int width); + void (*sprite_v_double_twoscale)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1, + const uint8_t *src2a, const uint8_t *src2b, int offset2, + int alpha, int width); +} VC1DSPContext; + +void ff_vc1dsp_init(VC1DSPContext* c); +void ff_vc1dsp_init_altivec(VC1DSPContext* c); +void ff_vc1dsp_init_x86(VC1DSPContext* dsp); + +#endif /* AVCODEC_VC1DSP_H */ diff --git a/ffmpeg/libavcodec/vcr1.c b/ffmpeg/libavcodec/vcr1.c new file mode 100644 index 0000000..60bfcce --- /dev/null +++ b/ffmpeg/libavcodec/vcr1.c @@ -0,0 +1,128 @@ +/* + * ATI VCR1 codec + * Copyright (c) 2003 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 + */ + +/** + * @file + * ATI VCR1 codec + */ + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/internal.h" + +typedef struct VCR1Context { + int delta[16]; + int offset[4]; +} VCR1Context; + +static av_cold int vcr1_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV410P; + + if (avctx->width % 8 || avctx->height%4) { + avpriv_request_sample(avctx, "odd dimensions support"); + return AVERROR_PATCHWELCOME; + } + return 0; +} + +static int vcr1_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + VCR1Context *const a = avctx->priv_data; + AVFrame *const p = data; + const uint8_t *bytestream = buf; + int i, x, y, ret; + + if(buf_size < 16 + avctx->height + avctx->width*avctx->height*5/8){ + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + for (i = 0; i < 16; i++) { + a->delta[i] = *bytestream++; + bytestream++; + } + + for (y = 0; y < avctx->height; y++) { + int offset; + uint8_t *luma = &p->data[0][y * p->linesize[0]]; + + if ((y & 3) == 0) { + uint8_t *cb = &p->data[1][(y >> 2) * p->linesize[1]]; + uint8_t *cr = &p->data[2][(y >> 2) * p->linesize[2]]; + + for (i = 0; i < 4; i++) + a->offset[i] = *bytestream++; + + offset = a->offset[0] - a->delta[bytestream[2] & 0xF]; + for (x = 0; x < avctx->width; x += 4) { + luma[0] = offset += a->delta[bytestream[2] & 0xF]; + luma[1] = offset += a->delta[bytestream[2] >> 4]; + luma[2] = offset += a->delta[bytestream[0] & 0xF]; + luma[3] = offset += a->delta[bytestream[0] >> 4]; + luma += 4; + + *cb++ = bytestream[3]; + *cr++ = bytestream[1]; + + bytestream += 4; + } + } else { + offset = a->offset[y & 3] - a->delta[bytestream[2] & 0xF]; + + for (x = 0; x < avctx->width; x += 8) { + luma[0] = offset += a->delta[bytestream[2] & 0xF]; + luma[1] = offset += a->delta[bytestream[2] >> 4]; + luma[2] = offset += a->delta[bytestream[3] & 0xF]; + luma[3] = offset += a->delta[bytestream[3] >> 4]; + luma[4] = offset += a->delta[bytestream[0] & 0xF]; + luma[5] = offset += a->delta[bytestream[0] >> 4]; + luma[6] = offset += a->delta[bytestream[1] & 0xF]; + luma[7] = offset += a->delta[bytestream[1] >> 4]; + luma += 8; + bytestream += 4; + } + } + } + + *got_frame = 1; + + return buf_size; +} + +AVCodec ff_vcr1_decoder = { + .name = "vcr1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VCR1, + .priv_data_size = sizeof(VCR1Context), + .init = vcr1_decode_init, + .decode = vcr1_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"), +}; diff --git a/ffmpeg/libavcodec/vda.h b/ffmpeg/libavcodec/vda.h new file mode 100644 index 0000000..281785f --- /dev/null +++ b/ffmpeg/libavcodec/vda.h @@ -0,0 +1,151 @@ +/* + * VDA HW acceleration + * + * copyright (c) 2011 Sebastien Zwickert + * + * 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 + */ + +#ifndef AVCODEC_VDA_H +#define AVCODEC_VDA_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vda + * Public libavcodec VDA header. + */ + +#include + +// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes +// http://openradar.appspot.com/8026390 +#undef __GNUC_STDC_INLINE__ + +#define Picture QuickdrawPicture +#include +#undef Picture + +#include "libavcodec/version.h" + +/** + * @defgroup lavc_codec_hwaccel_vda VDA + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +/** + * This structure is used to provide the necessary configurations and data + * to the VDA FFmpeg HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct vda_context { + /** + * VDA decoder object. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + VDADecoder decoder; + + /** + * The Core Video pixel buffer that contains the current image data. + * + * encoding: unused + * decoding: Set by libavcodec. Unset by user. + */ + CVPixelBufferRef cv_buffer; + + /** + * Use the hardware decoder in synchronous mode. + * + * encoding: unused + * decoding: Set by user. + */ + int use_sync_decoding; + + /** + * The frame width. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int width; + + /** + * The frame height. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int height; + + /** + * The frame format. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int format; + + /** + * The pixel format for output image buffers. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + OSType cv_pix_fmt_type; + + /** + * The current bitstream buffer. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + uint8_t *priv_bitstream; + + /** + * The current size of the bitstream. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int priv_bitstream_size; + + /** + * The reference size used for fast reallocation. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int priv_allocated_size; +}; + +/** Create the video decoder. */ +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size); + +/** Destroy the video decoder. */ +int ff_vda_destroy_decoder(struct vda_context *vda_ctx); + +/** + * @} + */ + +#endif /* AVCODEC_VDA_H */ diff --git a/ffmpeg/libavcodec/vda_h264.c b/ffmpeg/libavcodec/vda_h264.c new file mode 100644 index 0000000..d0237c2 --- /dev/null +++ b/ffmpeg/libavcodec/vda_h264.c @@ -0,0 +1,237 @@ +/* + * VDA H264 HW acceleration. + * + * copyright (c) 2011 Sebastien Zwickert + * + * 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 +#include + +#include "vda.h" +#include "libavutil/avutil.h" +#include "h264.h" + + +/* Decoder callback that adds the vda frame to the queue in display order. */ +static void vda_decoder_callback (void *vda_hw_ctx, + CFDictionaryRef user_info, + OSStatus status, + uint32_t infoFlags, + CVImageBufferRef image_buffer) +{ + struct vda_context *vda_ctx = vda_hw_ctx; + + if (!image_buffer) + return; + + if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer)) + return; + + vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer); +} + +static int vda_sync_decode(struct vda_context *vda_ctx) +{ + OSStatus status; + CFDataRef coded_frame; + uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames + + coded_frame = CFDataCreate(kCFAllocatorDefault, + vda_ctx->priv_bitstream, + vda_ctx->priv_bitstream_size); + + status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL); + + if (kVDADecoderNoErr == status) + status = VDADecoderFlush(vda_ctx->decoder, flush_flags); + + CFRelease(coded_frame); + + return status; +} + + +static int vda_h264_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + struct vda_context *vda_ctx = avctx->hwaccel_context; + + if (!vda_ctx->decoder) + return -1; + + vda_ctx->priv_bitstream_size = 0; + + return 0; +} + +static int vda_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + struct vda_context *vda_ctx = avctx->hwaccel_context; + void *tmp; + + if (!vda_ctx->decoder) + return -1; + + tmp = av_fast_realloc(vda_ctx->priv_bitstream, + &vda_ctx->priv_allocated_size, + vda_ctx->priv_bitstream_size + size + 4); + if (!tmp) + return AVERROR(ENOMEM); + + vda_ctx->priv_bitstream = tmp; + + AV_WB32(vda_ctx->priv_bitstream + vda_ctx->priv_bitstream_size, size); + memcpy(vda_ctx->priv_bitstream + vda_ctx->priv_bitstream_size + 4, buffer, size); + + vda_ctx->priv_bitstream_size += size + 4; + + return 0; +} + +static int vda_h264_end_frame(AVCodecContext *avctx) +{ + H264Context *h = avctx->priv_data; + struct vda_context *vda_ctx = avctx->hwaccel_context; + AVFrame *frame = &h->cur_pic_ptr->f; + int status; + + if (!vda_ctx->decoder || !vda_ctx->priv_bitstream) + return -1; + + status = vda_sync_decode(vda_ctx); + frame->data[3] = (void*)vda_ctx->cv_buffer; + + if (status) + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status); + + return status; +} + +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size) +{ + OSStatus status; + CFNumberRef height; + CFNumberRef width; + CFNumberRef format; + CFDataRef avc_data; + CFMutableDictionaryRef config_info; + CFMutableDictionaryRef buffer_attributes; + CFMutableDictionaryRef io_surface_properties; + CFNumberRef cv_pix_fmt; + + vda_ctx->priv_bitstream = NULL; + vda_ctx->priv_allocated_size = 0; + + /* Each VCL NAL in the bitstream sent to the decoder + * is preceded by a 4 bytes length header. + * Change the avcC atom header if needed, to signal headers of 4 bytes. */ + if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) { + uint8_t *rw_extradata; + + if (!(rw_extradata = av_malloc(extradata_size))) + return AVERROR(ENOMEM); + + memcpy(rw_extradata, extradata, extradata_size); + + rw_extradata[4] |= 0x03; + + avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size); + + av_freep(&rw_extradata); + } else { + avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size); + } + + config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, + 4, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height); + width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width); + format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format); + + CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data); + + buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, + 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, + &vda_ctx->cv_pix_fmt_type); + CFDictionarySetValue(buffer_attributes, + kCVPixelBufferPixelFormatTypeKey, + cv_pix_fmt); + CFDictionarySetValue(buffer_attributes, + kCVPixelBufferIOSurfacePropertiesKey, + io_surface_properties); + + status = VDADecoderCreate(config_info, + buffer_attributes, + vda_decoder_callback, + vda_ctx, + &vda_ctx->decoder); + + CFRelease(height); + CFRelease(width); + CFRelease(format); + CFRelease(avc_data); + CFRelease(config_info); + CFRelease(io_surface_properties); + CFRelease(cv_pix_fmt); + CFRelease(buffer_attributes); + + return status; +} + +int ff_vda_destroy_decoder(struct vda_context *vda_ctx) +{ + OSStatus status = kVDADecoderNoErr; + + if (vda_ctx->decoder) + status = VDADecoderDestroy(vda_ctx->decoder); + + av_freep(&vda_ctx->priv_bitstream); + + return status; +} + +AVHWAccel ff_h264_vda_hwaccel = { + .name = "h264_vda", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_VDA_VLD, + .start_frame = vda_h264_start_frame, + .decode_slice = vda_h264_decode_slice, + .end_frame = vda_h264_end_frame, +}; diff --git a/ffmpeg/libavcodec/vda_h264_dec.c b/ffmpeg/libavcodec/vda_h264_dec.c new file mode 100644 index 0000000..d6c8f37 --- /dev/null +++ b/ffmpeg/libavcodec/vda_h264_dec.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2012, Xidorn Quan + * + * 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 + */ + +/** + * @file + * H.264 decoder via VDA + * @author Xidorn Quan + */ + +#include +#include + +#include "vda.h" +#include "h264.h" +#include "avcodec.h" + +#ifndef kCFCoreFoundationVersionNumber10_7 +#define kCFCoreFoundationVersionNumber10_7 635.00 +#endif + +extern AVCodec ff_h264_decoder, ff_h264_vda_decoder; + +static const enum AVPixelFormat vda_pixfmts_prior_10_7[] = { + AV_PIX_FMT_UYVY422, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +static const enum AVPixelFormat vda_pixfmts[] = { + AV_PIX_FMT_UYVY422, + AV_PIX_FMT_YUYV422, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NONE +}; + +typedef struct { + H264Context h264ctx; + int h264_initialized; + struct vda_context vda_ctx; + enum AVPixelFormat pix_fmt; +} VDADecoderContext; + +static enum AVPixelFormat get_format(struct AVCodecContext *avctx, + const enum AVPixelFormat *fmt) +{ + return AV_PIX_FMT_VDA_VLD; +} + +static int get_buffer(AVCodecContext *avctx, AVFrame *pic) +{ + pic->type = FF_BUFFER_TYPE_USER; + pic->data[0] = (void *)1; + return 0; +} + +static void release_buffer(AVCodecContext *avctx, AVFrame *pic) +{ + int i; + + CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3]; + CVPixelBufferUnlockBaseAddress(cv_buffer, 0); + CVPixelBufferRelease(cv_buffer); + + for (i = 0; i < 4; i++) + pic->data[i] = NULL; +} + +static int vdadec_decode(AVCodecContext *avctx, + void *data, int *got_frame, AVPacket *avpkt) +{ + VDADecoderContext *ctx = avctx->priv_data; + AVFrame *pic = data; + int ret; + + ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt); + if (*got_frame) { + CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3]; + CVPixelBufferLockBaseAddress(cv_buffer, 0); + pic->format = ctx->pix_fmt; + if (CVPixelBufferIsPlanar(cv_buffer)) { + int i, count = CVPixelBufferGetPlaneCount(cv_buffer); + av_assert0(count < 4); + for (i = 0; i < count; i++) { + pic->data[i] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer, i); + pic->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer, i); + } + } else { + pic->data[0] = CVPixelBufferGetBaseAddress(cv_buffer); + pic->linesize[0] = CVPixelBufferGetBytesPerRow(cv_buffer); + } + } + avctx->pix_fmt = ctx->pix_fmt; + + return ret; +} + +static av_cold int vdadec_close(AVCodecContext *avctx) +{ + VDADecoderContext *ctx = avctx->priv_data; + /* release buffers and decoder */ + ff_vda_destroy_decoder(&ctx->vda_ctx); + /* close H.264 decoder */ + if (ctx->h264_initialized) + ff_h264_decoder.close(avctx); + return 0; +} + +static av_cold int check_format(AVCodecContext *avctx) +{ + AVCodecParserContext *parser; + uint8_t *pout; + int psize; + int index; + H264Context *h; + int ret = -1; + + /* init parser & parse file */ + parser = av_parser_init(avctx->codec->id); + if (!parser) { + av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 parser.\n"); + goto final; + } + parser->flags = PARSER_FLAG_COMPLETE_FRAMES; + index = av_parser_parse2(parser, avctx, &pout, &psize, NULL, 0, 0, 0, 0); + if (index < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to parse this file.\n"); + goto release_parser; + } + + /* check if support */ + h = parser->priv_data; + switch (h->sps.bit_depth_luma) { + case 8: + if (!CHROMA444 && !CHROMA422) { + // only this will H.264 decoder switch to hwaccel + ret = 0; + break; + } + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported file.\n"); + } + +release_parser: + av_parser_close(parser); + +final: + return ret; +} + +static av_cold int vdadec_init(AVCodecContext *avctx) +{ + VDADecoderContext *ctx = avctx->priv_data; + struct vda_context *vda_ctx = &ctx->vda_ctx; + OSStatus status; + int ret; + + ctx->h264_initialized = 0; + + /* init pix_fmts of codec */ + if (!ff_h264_vda_decoder.pix_fmts) { + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7) + ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7; + else + ff_h264_vda_decoder.pix_fmts = vda_pixfmts; + } + + /* check if VDA supports this file */ + if (check_format(avctx) < 0) + goto failed; + + /* init vda */ + memset(vda_ctx, 0, sizeof(struct vda_context)); + vda_ctx->width = avctx->width; + vda_ctx->height = avctx->height; + vda_ctx->format = 'avc1'; + vda_ctx->use_sync_decoding = 1; + ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts); + switch (ctx->pix_fmt) { + case AV_PIX_FMT_UYVY422: + vda_ctx->cv_pix_fmt_type = '2vuy'; + break; + case AV_PIX_FMT_YUYV422: + vda_ctx->cv_pix_fmt_type = 'yuvs'; + break; + case AV_PIX_FMT_NV12: + vda_ctx->cv_pix_fmt_type = '420v'; + break; + case AV_PIX_FMT_YUV420P: + vda_ctx->cv_pix_fmt_type = 'y420'; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt); + goto failed; + } + status = ff_vda_create_decoder(vda_ctx, + avctx->extradata, avctx->extradata_size); + if (status != kVDADecoderNoErr) { + av_log(avctx, AV_LOG_ERROR, + "Failed to init VDA decoder: %d.\n", status); + goto failed; + } + avctx->hwaccel_context = vda_ctx; + + /* changes callback functions */ + avctx->get_format = get_format; + avctx->get_buffer = get_buffer; + avctx->release_buffer = release_buffer; + + /* init H.264 decoder */ + ret = ff_h264_decoder.init(avctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n"); + goto failed; + } + ctx->h264_initialized = 1; + + return 0; + +failed: + vdadec_close(avctx); + return -1; +} + +static void vdadec_flush(AVCodecContext *avctx) +{ + return ff_h264_decoder.flush(avctx); +} + +AVCodec ff_h264_vda_decoder = { + .name = "h264_vda", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .priv_data_size = sizeof(VDADecoderContext), + .init = vdadec_init, + .close = vdadec_close, + .decode = vdadec_decode, + .capabilities = CODEC_CAP_DELAY, + .flush = vdadec_flush, + .long_name = NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"), +}; diff --git a/ffmpeg/libavcodec/vdpau.c b/ffmpeg/libavcodec/vdpau.c new file mode 100644 index 0000000..5606902 --- /dev/null +++ b/ffmpeg/libavcodec/vdpau.c @@ -0,0 +1,414 @@ +/* + * Video Decode and Presentation API for UNIX (VDPAU) is used for + * HW decode acceleration for MPEG-1/2, MPEG-4 ASP, H.264 and VC-1. + * + * Copyright (c) 2008 NVIDIA + * + * 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 "avcodec.h" +#include "h264.h" +#include "vc1.h" + +#undef NDEBUG +#include + +#include "vdpau.h" +#include "vdpau_internal.h" + +/** + * @addtogroup VDPAU_Decoding + * + * @{ + */ + +int ff_vdpau_common_start_frame(AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + + hwctx->bitstream_buffers_used = 0; + return 0; +} + +int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + MpegEncContext *s = avctx->priv_data; + VdpVideoSurface surf = ff_vdpau_get_surface_id(s->current_picture_ptr); + + hwctx->render(hwctx->decoder, surf, (void *)&hwctx->info, + hwctx->bitstream_buffers_used, hwctx->bitstream_buffers); + + ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); + hwctx->bitstream_buffers_used = 0; + + return 0; +} + +int ff_vdpau_add_buffer(AVCodecContext *avctx, + const uint8_t *buf, uint32_t size) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + VdpBitstreamBuffer *buffers = hwctx->bitstream_buffers; + + buffers = av_fast_realloc(buffers, &hwctx->bitstream_buffers_allocated, + (hwctx->bitstream_buffers_used + 1) * sizeof(*buffers)); + if (!buffers) + return AVERROR(ENOMEM); + + hwctx->bitstream_buffers = buffers; + buffers += hwctx->bitstream_buffers_used++; + + buffers->struct_version = VDP_BITSTREAM_BUFFER_VERSION; + buffers->bitstream = buf; + buffers->bitstream_bytes = size; + return 0; +} + +/* Obsolete non-hwaccel VDPAU support below... */ + +void ff_vdpau_h264_set_reference_frames(H264Context *h) +{ + struct vdpau_render_state *render, *render_ref; + VdpReferenceFrameH264 *rf, *rf2; + Picture *pic; + int i, list, pic_frame_idx; + + render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0]; + assert(render); + + rf = &render->info.h264.referenceFrames[0]; +#define H264_RF_COUNT FF_ARRAY_ELEMS(render->info.h264.referenceFrames) + + for (list = 0; list < 2; ++list) { + Picture **lp = list ? h->long_ref : h->short_ref; + int ls = list ? 16 : h->short_ref_count; + + for (i = 0; i < ls; ++i) { + pic = lp[i]; + if (!pic || !pic->reference) + continue; + pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; + + render_ref = (struct vdpau_render_state *)pic->f.data[0]; + assert(render_ref); + + rf2 = &render->info.h264.referenceFrames[0]; + while (rf2 != rf) { + if ( + (rf2->surface == render_ref->surface) + && (rf2->is_long_term == pic->long_ref) + && (rf2->frame_idx == pic_frame_idx) + ) + break; + ++rf2; + } + if (rf2 != rf) { + rf2->top_is_reference |= (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE; + rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE; + continue; + } + + if (rf >= &render->info.h264.referenceFrames[H264_RF_COUNT]) + continue; + + rf->surface = render_ref->surface; + rf->is_long_term = pic->long_ref; + rf->top_is_reference = (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE; + rf->bottom_is_reference = (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE; + rf->field_order_cnt[0] = pic->field_poc[0]; + rf->field_order_cnt[1] = pic->field_poc[1]; + rf->frame_idx = pic_frame_idx; + + ++rf; + } + } + + for (; rf < &render->info.h264.referenceFrames[H264_RF_COUNT]; ++rf) { + rf->surface = VDP_INVALID_HANDLE; + rf->is_long_term = 0; + rf->top_is_reference = 0; + rf->bottom_is_reference = 0; + rf->field_order_cnt[0] = 0; + rf->field_order_cnt[1] = 0; + rf->frame_idx = 0; + } +} + +void ff_vdpau_add_data_chunk(uint8_t *data, const uint8_t *buf, int buf_size) +{ + struct vdpau_render_state *render = (struct vdpau_render_state*)data; + assert(render); + + render->bitstream_buffers= av_fast_realloc( + render->bitstream_buffers, + &render->bitstream_buffers_allocated, + sizeof(*render->bitstream_buffers)*(render->bitstream_buffers_used + 1) + ); + + render->bitstream_buffers[render->bitstream_buffers_used].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + render->bitstream_buffers[render->bitstream_buffers_used].bitstream = buf; + render->bitstream_buffers[render->bitstream_buffers_used].bitstream_bytes = buf_size; + render->bitstream_buffers_used++; +} + +void ff_vdpau_h264_picture_start(H264Context *h) +{ + struct vdpau_render_state *render; + int i; + + render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0]; + assert(render); + + for (i = 0; i < 2; ++i) { + int foc = h->cur_pic_ptr->field_poc[i]; + if (foc == INT_MAX) + foc = 0; + render->info.h264.field_order_cnt[i] = foc; + } + + render->info.h264.frame_num = h->frame_num; +} + +void ff_vdpau_h264_picture_complete(H264Context *h) +{ + struct vdpau_render_state *render; + + render = (struct vdpau_render_state *)h->cur_pic_ptr->f.data[0]; + assert(render); + + render->info.h264.slice_count = h->slice_num; + if (render->info.h264.slice_count < 1) + return; + + render->info.h264.is_reference = (h->cur_pic_ptr->reference & 3) ? VDP_TRUE : VDP_FALSE; + render->info.h264.field_pic_flag = h->picture_structure != PICT_FRAME; + render->info.h264.bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD; + render->info.h264.num_ref_frames = h->sps.ref_frame_count; + render->info.h264.mb_adaptive_frame_field_flag = h->sps.mb_aff && !render->info.h264.field_pic_flag; + render->info.h264.constrained_intra_pred_flag = h->pps.constrained_intra_pred; + render->info.h264.weighted_pred_flag = h->pps.weighted_pred; + render->info.h264.weighted_bipred_idc = h->pps.weighted_bipred_idc; + render->info.h264.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; + render->info.h264.transform_8x8_mode_flag = h->pps.transform_8x8_mode; + render->info.h264.chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; + render->info.h264.second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + render->info.h264.pic_init_qp_minus26 = h->pps.init_qp - 26; + render->info.h264.num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; + render->info.h264.num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; + render->info.h264.log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; + render->info.h264.pic_order_cnt_type = h->sps.poc_type; + render->info.h264.log2_max_pic_order_cnt_lsb_minus4 = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4; + render->info.h264.delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; + render->info.h264.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; + render->info.h264.entropy_coding_mode_flag = h->pps.cabac; + render->info.h264.pic_order_present_flag = h->pps.pic_order_present; + render->info.h264.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; + render->info.h264.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; + memcpy(render->info.h264.scaling_lists_4x4, h->pps.scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4)); + memcpy(render->info.h264.scaling_lists_8x8[0], h->pps.scaling_matrix8[0], sizeof(render->info.h264.scaling_lists_8x8[0])); + memcpy(render->info.h264.scaling_lists_8x8[1], h->pps.scaling_matrix8[3], sizeof(render->info.h264.scaling_lists_8x8[0])); + + ff_h264_draw_horiz_band(h, 0, h->avctx->height); + render->bitstream_buffers_used = 0; +} + +void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, + int buf_size, int slice_count) +{ + struct vdpau_render_state *render, *last, *next; + int i; + + if (!s->current_picture_ptr) return; + + render = (struct vdpau_render_state *)s->current_picture_ptr->f.data[0]; + assert(render); + + /* fill VdpPictureInfoMPEG1Or2 struct */ + render->info.mpeg.picture_structure = s->picture_structure; + render->info.mpeg.picture_coding_type = s->pict_type; + render->info.mpeg.intra_dc_precision = s->intra_dc_precision; + render->info.mpeg.frame_pred_frame_dct = s->frame_pred_frame_dct; + render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors; + render->info.mpeg.intra_vlc_format = s->intra_vlc_format; + render->info.mpeg.alternate_scan = s->alternate_scan; + render->info.mpeg.q_scale_type = s->q_scale_type; + render->info.mpeg.top_field_first = s->top_field_first; + render->info.mpeg.full_pel_forward_vector = s->full_pel[0]; // MPEG-1 only. Set 0 for MPEG-2 + render->info.mpeg.full_pel_backward_vector = s->full_pel[1]; // MPEG-1 only. Set 0 for MPEG-2 + render->info.mpeg.f_code[0][0] = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert. + render->info.mpeg.f_code[0][1] = s->mpeg_f_code[0][1]; + render->info.mpeg.f_code[1][0] = s->mpeg_f_code[1][0]; + render->info.mpeg.f_code[1][1] = s->mpeg_f_code[1][1]; + for (i = 0; i < 64; ++i) { + render->info.mpeg.intra_quantizer_matrix[i] = s->intra_matrix[i]; + render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i]; + } + + render->info.mpeg.forward_reference = VDP_INVALID_HANDLE; + render->info.mpeg.backward_reference = VDP_INVALID_HANDLE; + + switch(s->pict_type){ + case AV_PICTURE_TYPE_B: + next = (struct vdpau_render_state *)s->next_picture.f.data[0]; + assert(next); + render->info.mpeg.backward_reference = next->surface; + // no return here, going to set forward prediction + case AV_PICTURE_TYPE_P: + last = (struct vdpau_render_state *)s->last_picture.f.data[0]; + if (!last) // FIXME: Does this test make sense? + last = render; // predict second field from the first + render->info.mpeg.forward_reference = last->surface; + } + + ff_vdpau_add_data_chunk(s->current_picture_ptr->f.data[0], buf, buf_size); + + render->info.mpeg.slice_count = slice_count; + + if (slice_count) + ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); + render->bitstream_buffers_used = 0; +} + +void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf, + int buf_size) +{ + VC1Context *v = s->avctx->priv_data; + struct vdpau_render_state *render, *last, *next; + + render = (struct vdpau_render_state *)s->current_picture.f.data[0]; + assert(render); + + /* fill LvPictureInfoVC1 struct */ + render->info.vc1.frame_coding_mode = v->fcm; + render->info.vc1.postprocflag = v->postprocflag; + render->info.vc1.pulldown = v->broadcast; + render->info.vc1.interlace = v->interlace; + render->info.vc1.tfcntrflag = v->tfcntrflag; + render->info.vc1.finterpflag = v->finterpflag; + render->info.vc1.psf = v->psf; + render->info.vc1.dquant = v->dquant; + render->info.vc1.panscan_flag = v->panscanflag; + render->info.vc1.refdist_flag = v->refdist_flag; + render->info.vc1.quantizer = v->quantizer_mode; + render->info.vc1.extended_mv = v->extended_mv; + render->info.vc1.extended_dmv = v->extended_dmv; + render->info.vc1.overlap = v->overlap; + render->info.vc1.vstransform = v->vstransform; + render->info.vc1.loopfilter = v->s.loop_filter; + render->info.vc1.fastuvmc = v->fastuvmc; + render->info.vc1.range_mapy_flag = v->range_mapy_flag; + render->info.vc1.range_mapy = v->range_mapy; + render->info.vc1.range_mapuv_flag = v->range_mapuv_flag; + render->info.vc1.range_mapuv = v->range_mapuv; + /* Specific to simple/main profile only */ + render->info.vc1.multires = v->multires; + render->info.vc1.syncmarker = v->s.resync_marker; + render->info.vc1.rangered = v->rangered | (v->rangeredfrm << 1); + render->info.vc1.maxbframes = v->s.max_b_frames; + + render->info.vc1.deblockEnable = v->postprocflag & 1; + render->info.vc1.pquant = v->pq; + + render->info.vc1.forward_reference = VDP_INVALID_HANDLE; + render->info.vc1.backward_reference = VDP_INVALID_HANDLE; + + if (v->bi_type) + render->info.vc1.picture_type = 4; + else + render->info.vc1.picture_type = s->pict_type - 1 + s->pict_type / 3; + + switch(s->pict_type){ + case AV_PICTURE_TYPE_B: + next = (struct vdpau_render_state *)s->next_picture.f.data[0]; + assert(next); + render->info.vc1.backward_reference = next->surface; + // no break here, going to set forward prediction + case AV_PICTURE_TYPE_P: + last = (struct vdpau_render_state *)s->last_picture.f.data[0]; + if (!last) // FIXME: Does this test make sense? + last = render; // predict second field from the first + render->info.vc1.forward_reference = last->surface; + } + + ff_vdpau_add_data_chunk(s->current_picture_ptr->f.data[0], buf, buf_size); + + render->info.vc1.slice_count = 1; + + ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); + render->bitstream_buffers_used = 0; +} + +void ff_vdpau_mpeg4_decode_picture(MpegEncContext *s, const uint8_t *buf, + int buf_size) +{ + struct vdpau_render_state *render, *last, *next; + int i; + + if (!s->current_picture_ptr) return; + + render = (struct vdpau_render_state *)s->current_picture_ptr->f.data[0]; + assert(render); + + /* fill VdpPictureInfoMPEG4Part2 struct */ + render->info.mpeg4.trd[0] = s->pp_time; + render->info.mpeg4.trb[0] = s->pb_time; + render->info.mpeg4.trd[1] = s->pp_field_time >> 1; + render->info.mpeg4.trb[1] = s->pb_field_time >> 1; + render->info.mpeg4.vop_time_increment_resolution = s->avctx->time_base.den; + render->info.mpeg4.vop_coding_type = 0; + render->info.mpeg4.vop_fcode_forward = s->f_code; + render->info.mpeg4.vop_fcode_backward = s->b_code; + render->info.mpeg4.resync_marker_disable = !s->resync_marker; + render->info.mpeg4.interlaced = !s->progressive_sequence; + render->info.mpeg4.quant_type = s->mpeg_quant; + render->info.mpeg4.quarter_sample = s->quarter_sample; + render->info.mpeg4.short_video_header = s->avctx->codec->id == AV_CODEC_ID_H263; + render->info.mpeg4.rounding_control = s->no_rounding; + render->info.mpeg4.alternate_vertical_scan_flag = s->alternate_scan; + render->info.mpeg4.top_field_first = s->top_field_first; + for (i = 0; i < 64; ++i) { + render->info.mpeg4.intra_quantizer_matrix[i] = s->intra_matrix[i]; + render->info.mpeg4.non_intra_quantizer_matrix[i] = s->inter_matrix[i]; + } + render->info.mpeg4.forward_reference = VDP_INVALID_HANDLE; + render->info.mpeg4.backward_reference = VDP_INVALID_HANDLE; + + switch (s->pict_type) { + case AV_PICTURE_TYPE_B: + next = (struct vdpau_render_state *)s->next_picture.f.data[0]; + assert(next); + render->info.mpeg4.backward_reference = next->surface; + render->info.mpeg4.vop_coding_type = 2; + // no break here, going to set forward prediction + case AV_PICTURE_TYPE_P: + last = (struct vdpau_render_state *)s->last_picture.f.data[0]; + assert(last); + render->info.mpeg4.forward_reference = last->surface; + } + + ff_vdpau_add_data_chunk(s->current_picture_ptr->f.data[0], buf, buf_size); + + ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); + render->bitstream_buffers_used = 0; +} + +/* @}*/ diff --git a/ffmpeg/libavcodec/vdpau.h b/ffmpeg/libavcodec/vdpau.h new file mode 100644 index 0000000..df2aace --- /dev/null +++ b/ffmpeg/libavcodec/vdpau.h @@ -0,0 +1,151 @@ +/* + * The Video Decode and Presentation API for UNIX (VDPAU) is used for + * hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1. + * + * Copyright (C) 2008 NVIDIA + * + * 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 + */ + +#ifndef AVCODEC_VDPAU_H +#define AVCODEC_VDPAU_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_vdpau + * Public libavcodec VDPAU header. + */ + + +/** + * @defgroup lavc_codec_hwaccel_vdpau VDPAU Decoder and Renderer + * @ingroup lavc_codec_hwaccel + * + * VDPAU hardware acceleration has two modules + * - VDPAU decoding + * - VDPAU presentation + * + * The VDPAU decoding module parses all headers using FFmpeg + * parsing mechanisms and uses VDPAU for the actual decoding. + * + * As per the current implementation, the actual decoding + * and rendering (API calls) are done as part of the VDPAU + * presentation (vo_vdpau.c) module. + * + * @{ + */ + +#include +#include + +union FFVdpPictureInfo { + VdpPictureInfoH264 h264; + VdpPictureInfoMPEG1Or2 mpeg; + VdpPictureInfoVC1 vc1; + VdpPictureInfoMPEG4Part2 mpeg4; +}; + +/** + * This structure is used to share data between the libavcodec library and + * the client video application. + * The user shall zero-allocate the structure and make it available as + * AVCodecContext.hwaccel_context. Members can be set by the user once + * during initialization or through each AVCodecContext.get_buffer() + * function call. In any case, they must be valid prior to calling + * decoding functions. + */ +typedef struct AVVDPAUContext { + /** + * VDPAU decoder handle + * + * Set by user. + */ + VdpDecoder decoder; + + /** + * VDPAU decoder render callback + * + * Set by the user. + */ + VdpDecoderRender *render; + + /** + * VDPAU picture information + * + * Set by libavcodec. + */ + union FFVdpPictureInfo info; + + /** + * Allocated size of the bitstream_buffers table. + * + * Set by libavcodec. + */ + int bitstream_buffers_allocated; + + /** + * Useful bitstream buffers in the bitstream buffers table. + * + * Set by libavcodec. + */ + int bitstream_buffers_used; + + /** + * Table of bitstream buffers. + * The user is responsible for freeing this buffer using av_freep(). + * + * Set by libavcodec. + */ + VdpBitstreamBuffer *bitstream_buffers; +} AVVDPAUContext; + + +/** @brief The videoSurface is used for rendering. */ +#define FF_VDPAU_STATE_USED_FOR_RENDER 1 + +/** + * @brief The videoSurface is needed for reference/prediction. + * The codec manipulates this. + */ +#define FF_VDPAU_STATE_USED_FOR_REFERENCE 2 + +/** + * @brief This structure is used as a callback between the FFmpeg + * decoder (vd_) and presentation (vo_) module. + * This is used for defining a video frame containing surface, + * picture parameter, bitstream information etc which are passed + * between the FFmpeg decoder and its clients. + */ +struct vdpau_render_state { + VdpVideoSurface surface; ///< Used as rendered surface, never changed. + + int state; ///< Holds FF_VDPAU_STATE_* values. + + /** Describe size/location of the compressed video data. + Set to 0 when freeing bitstream_buffers. */ + int bitstream_buffers_allocated; + int bitstream_buffers_used; + /** The user is responsible for freeing this buffer using av_freep(). */ + VdpBitstreamBuffer *bitstream_buffers; + + /** picture parameter information for all supported codecs */ + union FFVdpPictureInfo info; +}; + +/* @}*/ + +#endif /* AVCODEC_VDPAU_H */ diff --git a/ffmpeg/libavcodec/vdpau_h264.c b/ffmpeg/libavcodec/vdpau_h264.c new file mode 100644 index 0000000..ad1aff0 --- /dev/null +++ b/ffmpeg/libavcodec/vdpau_h264.c @@ -0,0 +1,210 @@ +/* + * MPEG-4 Part 10 / AVC / H.264 HW decode acceleration through VDPAU + * + * Copyright (c) 2008 NVIDIA + * Copyright (c) 2013 Rémi Denis-Courmont + * + * 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 "avcodec.h" +#include "h264.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int32_t h264_foc(int foc) +{ + if (foc == INT_MAX) + foc = 0; + return foc; +} + +static void vdpau_h264_clear_rf(VdpReferenceFrameH264 *rf) +{ + rf->surface = VDP_INVALID_HANDLE; + rf->is_long_term = VDP_FALSE; + rf->top_is_reference = VDP_FALSE; + rf->bottom_is_reference = VDP_FALSE; + rf->field_order_cnt[0] = 0; + rf->field_order_cnt[1] = 0; + rf->frame_idx = 0; +} + +static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, Picture *pic, + int pic_structure) +{ + VdpVideoSurface surface = ff_vdpau_get_surface_id(pic); + + if (pic_structure == 0) + pic_structure = pic->reference; + + rf->surface = surface; + rf->is_long_term = pic->reference && pic->long_ref; + rf->top_is_reference = (pic_structure & PICT_TOP_FIELD) != 0; + rf->bottom_is_reference = (pic_structure & PICT_BOTTOM_FIELD) != 0; + rf->field_order_cnt[0] = h264_foc(pic->field_poc[0]); + rf->field_order_cnt[1] = h264_foc(pic->field_poc[1]); + rf->frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; +} + +static void vdpau_h264_set_reference_frames(AVCodecContext *avctx) +{ + H264Context * const h = avctx->priv_data; + AVVDPAUContext *hwctx = avctx->hwaccel_context; + VdpPictureInfoH264 *info = &hwctx->info.h264; + int list; + + VdpReferenceFrameH264 *rf = &info->referenceFrames[0]; +#define H264_RF_COUNT FF_ARRAY_ELEMS(info->referenceFrames) + + for (list = 0; list < 2; ++list) { + Picture **lp = list ? h->long_ref : h->short_ref; + int i, ls = list ? 16 : h->short_ref_count; + + for (i = 0; i < ls; ++i) { + Picture *pic = lp[i]; + VdpReferenceFrameH264 *rf2; + VdpVideoSurface surface_ref; + int pic_frame_idx; + + if (!pic || !pic->reference) + continue; + pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; + surface_ref = ff_vdpau_get_surface_id(pic); + + rf2 = &info->referenceFrames[0]; + while (rf2 != rf) { + if ((rf2->surface == surface_ref) && + (rf2->is_long_term == pic->long_ref) && + (rf2->frame_idx == pic_frame_idx)) + break; + ++rf2; + } + if (rf2 != rf) { + rf2->top_is_reference |= (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE; + rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE; + continue; + } + + if (rf >= &info->referenceFrames[H264_RF_COUNT]) + continue; + + vdpau_h264_set_rf(rf, pic, pic->reference); + ++rf; + } + } + + for (; rf < &info->referenceFrames[H264_RF_COUNT]; ++rf) + vdpau_h264_clear_rf(rf); +} + +static int vdpau_h264_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + H264Context * const h = avctx->priv_data; + AVVDPAUContext *hwctx = avctx->hwaccel_context; + VdpPictureInfoH264 *info = &hwctx->info.h264; + Picture *pic = h->cur_pic_ptr; + + /* init VdpPictureInfoH264 */ + info->slice_count = 0; + info->field_order_cnt[0] = h264_foc(pic->field_poc[0]); + info->field_order_cnt[1] = h264_foc(pic->field_poc[1]); + info->is_reference = h->nal_ref_idc != 0; + info->frame_num = h->frame_num; + info->field_pic_flag = h->picture_structure != PICT_FRAME; + info->bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD; + info->num_ref_frames = h->sps.ref_frame_count; + info->mb_adaptive_frame_field_flag = h->sps.mb_aff && !info->field_pic_flag; + info->constrained_intra_pred_flag = h->pps.constrained_intra_pred; + info->weighted_pred_flag = h->pps.weighted_pred; + info->weighted_bipred_idc = h->pps.weighted_bipred_idc; + info->frame_mbs_only_flag = h->sps.frame_mbs_only_flag; + info->transform_8x8_mode_flag = h->pps.transform_8x8_mode; + info->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; + info->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + info->pic_init_qp_minus26 = h->pps.init_qp - 26; + info->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; + info->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; + info->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; + info->pic_order_cnt_type = h->sps.poc_type; + info->log2_max_pic_order_cnt_lsb_minus4 = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4; + info->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; + info->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; + info->entropy_coding_mode_flag = h->pps.cabac; + info->pic_order_present_flag = h->pps.pic_order_present; + info->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; + info->redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; + + memcpy(info->scaling_lists_4x4, h->pps.scaling_matrix4, + sizeof(info->scaling_lists_4x4)); + memcpy(info->scaling_lists_8x8[0], h->pps.scaling_matrix8[0], + sizeof(info->scaling_lists_8x8[0])); + memcpy(info->scaling_lists_8x8[1], h->pps.scaling_matrix8[3], + sizeof(info->scaling_lists_8x8[1])); + + vdpau_h264_set_reference_frames(avctx); + + return ff_vdpau_common_start_frame(avctx, buffer, size); +} + +static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; + +static int vdpau_h264_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + int val; + + val = ff_vdpau_add_buffer(avctx, start_code_prefix, 3); + if (val) + return val; + + val = ff_vdpau_add_buffer(avctx, buffer, size); + if (val) + return val; + + hwctx->info.h264.slice_count++; + return 0; +} + +static int vdpau_h264_end_frame(AVCodecContext *avctx) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + H264Context *h = avctx->priv_data; + VdpVideoSurface surf = ff_vdpau_get_surface_id(h->cur_pic_ptr); + + hwctx->render(hwctx->decoder, surf, (void *)&hwctx->info, + hwctx->bitstream_buffers_used, hwctx->bitstream_buffers); + + ff_h264_draw_horiz_band(h, 0, h->avctx->height); + hwctx->bitstream_buffers_used = 0; + + return 0; +} + +AVHWAccel ff_h264_vdpau_hwaccel = { + .name = "h264_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H264, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_h264_start_frame, + .end_frame = vdpau_h264_end_frame, + .decode_slice = vdpau_h264_decode_slice, +}; diff --git a/ffmpeg/libavcodec/vdpau_internal.h b/ffmpeg/libavcodec/vdpau_internal.h new file mode 100644 index 0000000..790b3ef --- /dev/null +++ b/ffmpeg/libavcodec/vdpau_internal.h @@ -0,0 +1,60 @@ +/* + * Video Decode and Presentation API for UNIX (VDPAU) is used for + * HW decode acceleration for MPEG-1/2, H.264 and VC-1. + * + * Copyright (C) 2008 NVIDIA + * + * 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 + */ + +#ifndef AVCODEC_VDPAU_INTERNAL_H +#define AVCODEC_VDPAU_INTERNAL_H + +#include +#include "h264.h" +#include "mpegvideo.h" + +/** Extract VdpVideoSurface from a Picture */ +static inline uintptr_t ff_vdpau_get_surface_id(Picture *pic) +{ + return (uintptr_t)pic->f.data[3]; +} + +int ff_vdpau_common_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size); +int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx); +int ff_vdpau_add_buffer(AVCodecContext *avctx, + const uint8_t *buf, uint32_t buf_size); + + +void ff_vdpau_add_data_chunk(uint8_t *data, const uint8_t *buf, + int buf_size); + +void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, + int buf_size, int slice_count); + +void ff_vdpau_h264_picture_start(H264Context *h); +void ff_vdpau_h264_set_reference_frames(H264Context *h); +void ff_vdpau_h264_picture_complete(H264Context *h); + +void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf, + int buf_size); + +void ff_vdpau_mpeg4_decode_picture(MpegEncContext *s, const uint8_t *buf, + int buf_size); + +#endif /* AVCODEC_VDPAU_INTERNAL_H */ diff --git a/ffmpeg/libavcodec/vdpau_mpeg12.c b/ffmpeg/libavcodec/vdpau_mpeg12.c new file mode 100644 index 0000000..74e3f16 --- /dev/null +++ b/ffmpeg/libavcodec/vdpau_mpeg12.c @@ -0,0 +1,116 @@ +/* + * MPEG-1/2 HW decode acceleration through VDPAU + * + * Copyright (c) 2008 NVIDIA + * Copyright (c) 2013 Rémi Denis-Courmont + * + * 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 "avcodec.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int vdpau_mpeg_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + MpegEncContext * const s = avctx->priv_data; + AVVDPAUContext *hwctx = avctx->hwaccel_context; + VdpPictureInfoMPEG1Or2 *info = &hwctx->info.mpeg; + VdpVideoSurface ref; + int i; + + /* fill VdpPictureInfoMPEG1Or2 struct */ + info->forward_reference = VDP_INVALID_HANDLE; + info->backward_reference = VDP_INVALID_HANDLE; + + switch (s->pict_type) { + case AV_PICTURE_TYPE_B: + ref = ff_vdpau_get_surface_id(&s->next_picture); + assert(ref != VDP_INVALID_HANDLE); + hwctx->info.mpeg.backward_reference = ref; + /* fall through to forward prediction */ + case AV_PICTURE_TYPE_P: + ref = ff_vdpau_get_surface_id(&s->last_picture); + hwctx->info.mpeg.forward_reference = ref; + } + + info->slice_count = 0; + info->picture_structure = s->picture_structure; + info->picture_coding_type = s->pict_type; + info->intra_dc_precision = s->intra_dc_precision; + info->frame_pred_frame_dct = s->frame_pred_frame_dct; + info->concealment_motion_vectors = s->concealment_motion_vectors; + info->intra_vlc_format = s->intra_vlc_format; + info->alternate_scan = s->alternate_scan; + info->q_scale_type = s->q_scale_type; + info->top_field_first = s->top_field_first; + // Both for MPEG-1 only, zero for MPEG-2: + info->full_pel_forward_vector = s->full_pel[0]; + info->full_pel_backward_vector = s->full_pel[1]; + // For MPEG-1 fill both horizontal & vertical: + info->f_code[0][0] = s->mpeg_f_code[0][0]; + info->f_code[0][1] = s->mpeg_f_code[0][1]; + info->f_code[1][0] = s->mpeg_f_code[1][0]; + info->f_code[1][1] = s->mpeg_f_code[1][1]; + for (i = 0; i < 64; ++i) { + info->intra_quantizer_matrix[i] = s->intra_matrix[i]; + info->non_intra_quantizer_matrix[i] = s->inter_matrix[i]; + } + + return ff_vdpau_common_start_frame(avctx, buffer, size); +} + +static int vdpau_mpeg_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + int val; + + val = ff_vdpau_add_buffer(avctx, buffer, size); + if (val < 0) + return val; + + hwctx->info.mpeg.slice_count++; + return 0; +} + +#if CONFIG_MPEG1_VDPAU_HWACCEL +AVHWAccel ff_mpeg1_vdpau_hwaccel = { + .name = "mpeg1_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG1VIDEO, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_mpeg_start_frame, + .end_frame = ff_vdpau_mpeg_end_frame, + .decode_slice = vdpau_mpeg_decode_slice, +}; +#endif + +#if CONFIG_MPEG2_VDPAU_HWACCEL +AVHWAccel ff_mpeg2_vdpau_hwaccel = { + .name = "mpeg2_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG2VIDEO, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_mpeg_start_frame, + .end_frame = ff_vdpau_mpeg_end_frame, + .decode_slice = vdpau_mpeg_decode_slice, +}; +#endif diff --git a/ffmpeg/libavcodec/vdpau_mpeg4.c b/ffmpeg/libavcodec/vdpau_mpeg4.c new file mode 100644 index 0000000..cb8ee0a --- /dev/null +++ b/ffmpeg/libavcodec/vdpau_mpeg4.c @@ -0,0 +1,110 @@ +/* + * MPEG-4 Part 2 / H.263 decode acceleration through VDPAU + * + * Copyright (c) 2008 NVIDIA + * Copyright (c) 2013 Rémi Denis-Courmont + * + * 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 "avcodec.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int vdpau_mpeg4_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + MpegEncContext * const s = avctx->priv_data; + AVVDPAUContext *hwctx = avctx->hwaccel_context; + VdpPictureInfoMPEG4Part2 *info = &hwctx->info.mpeg4; + VdpVideoSurface ref; + int i; + + /* fill VdpPictureInfoMPEG4Part2 struct */ + info->forward_reference = VDP_INVALID_HANDLE; + info->backward_reference = VDP_INVALID_HANDLE; + info->vop_coding_type = 0; + + switch (s->pict_type) { + case AV_PICTURE_TYPE_B: + ref = ff_vdpau_get_surface_id(&s->next_picture); + assert(ref != VDP_INVALID_HANDLE); + info->backward_reference = ref; + info->vop_coding_type = 2; + /* fall-through */ + case AV_PICTURE_TYPE_P: + ref = ff_vdpau_get_surface_id(&s->last_picture); + assert(ref != VDP_INVALID_HANDLE); + info->forward_reference = ref; + } + + info->trd[0] = s->pp_time; + info->trb[0] = s->pb_time; + info->trd[1] = s->pp_field_time >> 1; + info->trb[1] = s->pb_field_time >> 1; + info->vop_time_increment_resolution = s->avctx->time_base.den; + info->vop_fcode_forward = s->f_code; + info->vop_fcode_backward = s->b_code; + info->resync_marker_disable = !s->resync_marker; + info->interlaced = !s->progressive_sequence; + info->quant_type = s->mpeg_quant; + info->quarter_sample = s->quarter_sample; + info->short_video_header = avctx->codec->id == AV_CODEC_ID_H263; + info->rounding_control = s->no_rounding; + info->alternate_vertical_scan_flag = s->alternate_scan; + info->top_field_first = s->top_field_first; + for (i = 0; i < 64; ++i) { + info->intra_quantizer_matrix[i] = s->intra_matrix[i]; + info->non_intra_quantizer_matrix[i] = s->inter_matrix[i]; + } + + ff_vdpau_common_start_frame(avctx, buffer, size); + return ff_vdpau_add_buffer(avctx, buffer, size); +} + +static int vdpau_mpeg4_decode_slice(av_unused AVCodecContext *avctx, + av_unused const uint8_t *buffer, + av_unused uint32_t size) +{ + return 0; +} + +#if CONFIG_H263_VDPAU_HWACCEL +AVHWAccel ff_h263_vdpau_hwaccel = { + .name = "h263_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_H263, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_mpeg4_start_frame, + .end_frame = ff_vdpau_mpeg_end_frame, + .decode_slice = vdpau_mpeg4_decode_slice, +}; +#endif + +#if CONFIG_MPEG4_VDPAU_HWACCEL +AVHWAccel ff_mpeg4_vdpau_hwaccel = { + .name = "mpeg4_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MPEG4, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_mpeg4_start_frame, + .end_frame = ff_vdpau_mpeg_end_frame, + .decode_slice = vdpau_mpeg4_decode_slice, +}; +#endif diff --git a/ffmpeg/libavcodec/vdpau_vc1.c b/ffmpeg/libavcodec/vdpau_vc1.c new file mode 100644 index 0000000..f5da9bb --- /dev/null +++ b/ffmpeg/libavcodec/vdpau_vc1.c @@ -0,0 +1,128 @@ +/* + * VC-1 decode acceleration through VDPAU + * + * Copyright (c) 2008 NVIDIA + * Copyright (c) 2013 Rémi Denis-Courmont + * + * 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 "avcodec.h" +#include "vc1.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int vdpau_vc1_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + VC1Context * const v = avctx->priv_data; + AVVDPAUContext *hwctx = avctx->hwaccel_context; + MpegEncContext * const s = &v->s; + VdpPictureInfoVC1 *info = &hwctx->info.vc1; + VdpVideoSurface ref; + + /* fill LvPictureInfoVC1 struct */ + info->forward_reference = VDP_INVALID_HANDLE; + info->backward_reference = VDP_INVALID_HANDLE; + + switch (s->pict_type) { + case AV_PICTURE_TYPE_B: + ref = ff_vdpau_get_surface_id(&s->next_picture); + assert(ref != VDP_INVALID_HANDLE); + info->backward_reference = ref; + /* fall-through */ + case AV_PICTURE_TYPE_P: + ref = ff_vdpau_get_surface_id(&s->last_picture); + assert(ref != VDP_INVALID_HANDLE); + info->forward_reference = ref; + } + + info->slice_count = 0; + if (v->bi_type) + info->picture_type = 4; + else + info->picture_type = s->pict_type - 1 + s->pict_type / 3; + + info->frame_coding_mode = v->fcm; + info->postprocflag = v->postprocflag; + info->pulldown = v->broadcast; + info->interlace = v->interlace; + info->tfcntrflag = v->tfcntrflag; + info->finterpflag = v->finterpflag; + info->psf = v->psf; + info->dquant = v->dquant; + info->panscan_flag = v->panscanflag; + info->refdist_flag = v->refdist_flag; + info->quantizer = v->quantizer_mode; + info->extended_mv = v->extended_mv; + info->extended_dmv = v->extended_dmv; + info->overlap = v->overlap; + info->vstransform = v->vstransform; + info->loopfilter = v->s.loop_filter; + info->fastuvmc = v->fastuvmc; + info->range_mapy_flag = v->range_mapy_flag; + info->range_mapy = v->range_mapy; + info->range_mapuv_flag = v->range_mapuv_flag; + info->range_mapuv = v->range_mapuv; + /* Specific to simple/main profile only */ + info->multires = v->multires; + info->syncmarker = v->s.resync_marker; + info->rangered = v->rangered | (v->rangeredfrm << 1); + info->maxbframes = v->s.max_b_frames; + info->deblockEnable = v->postprocflag & 1; + info->pquant = v->pq; + + return ff_vdpau_common_start_frame(avctx, buffer, size); +} + +static int vdpau_vc1_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + AVVDPAUContext *hwctx = avctx->hwaccel_context; + int val; + + val = ff_vdpau_add_buffer(avctx, buffer, size); + if (val < 0) + return val; + + hwctx->info.vc1.slice_count++; + return 0; +} + +#if CONFIG_WMV3_VDPAU_HWACCEL +AVHWAccel ff_wmv3_vdpau_hwaccel = { + .name = "wm3_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV3, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_vc1_start_frame, + .end_frame = ff_vdpau_mpeg_end_frame, + .decode_slice = vdpau_vc1_decode_slice, +}; +#endif + +AVHWAccel ff_vc1_vdpau_hwaccel = { + .name = "vc1_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VC1, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_vc1_start_frame, + .end_frame = ff_vdpau_mpeg_end_frame, + .decode_slice = vdpau_vc1_decode_slice, +}; diff --git a/ffmpeg/libavcodec/version.h b/ffmpeg/libavcodec/version.h new file mode 100644 index 0000000..5cf07bc --- /dev/null +++ b/ffmpeg/libavcodec/version.h @@ -0,0 +1,92 @@ +/* + * + * 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 + */ + +#ifndef AVCODEC_VERSION_H +#define AVCODEC_VERSION_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#include "libavutil/avutil.h" + +#define LIBAVCODEC_VERSION_MAJOR 55 +#define LIBAVCODEC_VERSION_MINOR 1 +#define LIBAVCODEC_VERSION_MICRO 100 + +#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \ + LIBAVCODEC_VERSION_MINOR, \ + LIBAVCODEC_VERSION_MICRO) +#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT + +#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * dropped at a future version bump. The defines themselves are not part of + * the public API and may change, break or disappear at any time. + */ + +#ifndef FF_API_REQUEST_CHANNELS +#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_ALLOC_CONTEXT +#define FF_API_ALLOC_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_AVCODEC_OPEN +#define FF_API_AVCODEC_OPEN (LIBAVCODEC_VERSION_MAJOR < 55) +#endif +#ifndef FF_API_OLD_DECODE_AUDIO +#define FF_API_OLD_DECODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_OLD_TIMECODE +#define FF_API_OLD_TIMECODE (LIBAVCODEC_VERSION_MAJOR < 55) +#endif + +#ifndef FF_API_OLD_ENCODE_AUDIO +#define FF_API_OLD_ENCODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_OLD_ENCODE_VIDEO +#define FF_API_OLD_ENCODE_VIDEO (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_CODEC_ID +#define FF_API_CODEC_ID (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_AVCODEC_RESAMPLE +#define FF_API_AVCODEC_RESAMPLE (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_DEINTERLACE +#define FF_API_DEINTERLACE (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_DESTRUCT_PACKET +#define FF_API_DESTRUCT_PACKET (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_GET_BUFFER +#define FF_API_GET_BUFFER (LIBAVCODEC_VERSION_MAJOR < 56) +#endif +#ifndef FF_API_MISSING_SAMPLE +#define FF_API_MISSING_SAMPLE (LIBAVCODEC_VERSION_MAJOR < 56) +#endif + +#endif /* AVCODEC_VERSION_H */ diff --git a/ffmpeg/libavcodec/videodsp.c b/ffmpeg/libavcodec/videodsp.c new file mode 100644 index 0000000..f91bac3 --- /dev/null +++ b/ffmpeg/libavcodec/videodsp.c @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 Ronald S. Bultje + * + * 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 "libavutil/avassert.h" +#include "libavutil/common.h" +#include "videodsp.h" + +#define BIT_DEPTH 8 +#include "videodsp_template.c" +#undef BIT_DEPTH + +#define BIT_DEPTH 16 +#include "videodsp_template.c" +#undef BIT_DEPTH + +static void just_return(uint8_t *buf, ptrdiff_t stride, int h) +{ +} + +void ff_videodsp_init(VideoDSPContext *ctx, int bpc) +{ + ctx->prefetch = just_return; + if (bpc <= 8) { + ctx->emulated_edge_mc = ff_emulated_edge_mc_8; + } else { + ctx->emulated_edge_mc = ff_emulated_edge_mc_16; + } + + if (ARCH_ARM) + ff_videodsp_init_arm(ctx, bpc); + if (ARCH_PPC) + ff_videodsp_init_ppc(ctx, bpc); + if (ARCH_X86) + ff_videodsp_init_x86(ctx, bpc); +} diff --git a/ffmpeg/libavcodec/videodsp.h b/ffmpeg/libavcodec/videodsp.h new file mode 100644 index 0000000..e397720 --- /dev/null +++ b/ffmpeg/libavcodec/videodsp.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Ronald S. Bultje + * + * 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 + */ + +/** + * @file + * Core video DSP helper functions + */ + +#ifndef AVCODEC_VIDEODSP_H +#define AVCODEC_VIDEODSP_H + +#include +#include + +#define EMULATED_EDGE(depth) \ +void ff_emulated_edge_mc_ ## depth (uint8_t *buf, const uint8_t *src, ptrdiff_t linesize,\ + int block_w, int block_h,\ + int src_x, int src_y, int w, int h); + +EMULATED_EDGE(8) +EMULATED_EDGE(16) + +typedef struct VideoDSPContext { + /** + * Copy a rectangular area of samples to a temporary buffer and replicate + * the border samples. + * + * @param buf destination buffer + * @param src source buffer + * @param linesize number of bytes between 2 vertically adjacent samples + * in both the source and destination buffers + * @param block_w width of block + * @param block_h height of block + * @param src_x x coordinate of the top left sample of the block in the + * source buffer + * @param src_y y coordinate of the top left sample of the block in the + * source buffer + * @param w width of the source buffer + * @param h height of the source buffer + */ + void (*emulated_edge_mc)(uint8_t *buf, const uint8_t *src, + ptrdiff_t linesize, int block_w, int block_h, + int src_x, int src_y, int w, int h); + + /** + * Prefetch memory into cache (if supported by hardware). + * + * @buf pointer to buffer to prefetch memory from + * @stride distance between two lines of buf (in bytes) + * @h number of lines to prefetch + */ + void (*prefetch)(uint8_t *buf, ptrdiff_t stride, int h); +} VideoDSPContext; + +void ff_videodsp_init(VideoDSPContext *ctx, int bpc); + +/* for internal use only (i.e. called by ff_videodsp_init() */ +void ff_videodsp_init_arm(VideoDSPContext *ctx, int bpc); +void ff_videodsp_init_ppc(VideoDSPContext *ctx, int bpc); +void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc); + +#endif /* AVCODEC_VIDEODSP_H */ diff --git a/ffmpeg/libavcodec/videodsp_template.c b/ffmpeg/libavcodec/videodsp_template.c new file mode 100644 index 0000000..44f6a4d --- /dev/null +++ b/ffmpeg/libavcodec/videodsp_template.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002-2012 Michael Niedermayer + * Copyright (C) 2012 Ronald S. Bultje + * + * 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 "bit_depth_template.c" +void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, + ptrdiff_t linesize_arg, + int block_w, int block_h, + int src_x, int src_y, int w, int h) +{ + int x, y; + int start_y, start_x, end_y, end_x; + int linesize = linesize_arg; + + if (!w || !h) + return; + + if (src_y >= h) { + src -= src_y * linesize; + src += (h - 1) * linesize; + src_y = h - 1; + } else if (src_y <= -block_h) { + src -= src_y * linesize; + src += (1 - block_h) * linesize; + src_y = 1 - block_h; + } + if (src_x >= w) { + src += (w - 1 - src_x) * sizeof(pixel); + src_x = w - 1; + } else if (src_x <= -block_w) { + src += (1 - block_w - src_x) * sizeof(pixel); + src_x = 1 - block_w; + } + + start_y = FFMAX(0, -src_y); + start_x = FFMAX(0, -src_x); + end_y = FFMIN(block_h, h-src_y); + end_x = FFMIN(block_w, w-src_x); + av_assert2(start_y < end_y && block_h); + av_assert2(start_x < end_x && block_w); + + w = end_x - start_x; + src += start_y * linesize + start_x * sizeof(pixel); + buf += start_x * sizeof(pixel); + + // top + for (y = 0; y < start_y; y++) { + memcpy(buf, src, w * sizeof(pixel)); + buf += linesize; + } + + // copy existing part + for (; y < end_y; y++) { + memcpy(buf, src, w * sizeof(pixel)); + src += linesize; + buf += linesize; + } + + // bottom + src -= linesize; + for (; y < block_h; y++) { + memcpy(buf, src, w * sizeof(pixel)); + buf += linesize; + } + + buf -= block_h * linesize + start_x * sizeof(pixel); + while (block_h--) { + pixel *bufp = (pixel *) buf; + + // left + for(x = 0; x < start_x; x++) { + bufp[x] = bufp[start_x]; + } + + // right + for (x = end_x; x < block_w; x++) { + bufp[x] = bufp[end_x - 1]; + } + buf += linesize; + } +} diff --git a/ffmpeg/libavcodec/vima.c b/ffmpeg/libavcodec/vima.c new file mode 100644 index 0000000..705839e --- /dev/null +++ b/ffmpeg/libavcodec/vima.c @@ -0,0 +1,233 @@ +/* + * LucasArts VIMA decoder + * Copyright (c) 2012 Paul B Mahol + * + * 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 "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "adpcm_data.h" + +typedef struct { + uint16_t predict_table[5786 * 2]; +} VimaContext; + +static const uint8_t size_table[] = +{ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +static const int8_t index_table1[] = +{ + -1, 4, -1, 4 +}; + +static const int8_t index_table2[] = +{ + -1, -1, 2, 6, -1, -1, 2, 6 +}; + +static const int8_t index_table3[] = +{ + -1, -1, -1, -1, 1, 2, 4, 6, + -1, -1, -1, -1, 1, 2, 4, 6 +}; + +static const int8_t index_table4[] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 2, 2, 4, 5, 6, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 2, 2, 4, 5, 6 +}; + +static const int8_t index_table5[] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 2, 2, 2, + 2, 4, 4, 4, 5, 5, 6, 6, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 2, 2, 2, + 2, 4, 4, 4, 5, 5, 6, 6 +}; + +static const int8_t index_table6[] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 6, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 6, 6 +}; + +static const int8_t* const step_index_tables[] = +{ + index_table1, index_table2, index_table3, + index_table4, index_table5, index_table6 +}; + +static av_cold int decode_init(AVCodecContext *avctx) +{ + VimaContext *vima = avctx->priv_data; + int start_pos; + + for (start_pos = 0; start_pos < 64; start_pos++) { + unsigned int dest_pos, table_pos; + + for (table_pos = 0, dest_pos = start_pos; + table_pos < FF_ARRAY_ELEMS(ff_adpcm_step_table); + table_pos++, dest_pos += 64) { + int put = 0, count, table_value; + + table_value = ff_adpcm_step_table[table_pos]; + for (count = 32; count != 0; count >>= 1) { + if (start_pos & count) + put += table_value; + table_value >>= 1; + } + vima->predict_table[dest_pos] = put; + } + } + + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *pkt) +{ + GetBitContext gb; + VimaContext *vima = avctx->priv_data; + AVFrame *frame = data; + int16_t pcm_data[2]; + uint32_t samples; + int8_t channel_hint[2]; + int ret, chan, channels = 1; + + if (pkt->size < 13) + return AVERROR_INVALIDDATA; + + if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) + return ret; + + samples = get_bits_long(&gb, 32); + if (samples == 0xffffffff) { + skip_bits_long(&gb, 32); + samples = get_bits_long(&gb, 32); + } + + if (samples > pkt->size * 2) + return AVERROR_INVALIDDATA; + + channel_hint[0] = get_sbits(&gb, 8); + if (channel_hint[0] & 0x80) { + channel_hint[0] = ~channel_hint[0]; + channels = 2; + } + avctx->channels = channels; + avctx->channel_layout = (channels == 2) ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + pcm_data[0] = get_sbits(&gb, 16); + if (channels > 1) { + channel_hint[1] = get_sbits(&gb, 8); + pcm_data[1] = get_sbits(&gb, 16); + } + + frame->nb_samples = samples; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (chan = 0; chan < channels; chan++) { + uint16_t *dest = (uint16_t*)frame->data[0] + chan; + int step_index = channel_hint[chan]; + int output = pcm_data[chan]; + int sample; + + for (sample = 0; sample < samples; sample++) { + int lookup_size, lookup, highbit, lowbits; + + step_index = av_clip(step_index, 0, 88); + lookup_size = size_table[step_index]; + lookup = get_bits(&gb, lookup_size); + highbit = 1 << (lookup_size - 1); + lowbits = highbit - 1; + + if (lookup & highbit) + lookup ^= highbit; + else + highbit = 0; + + if (lookup == lowbits) { + output = get_sbits(&gb, 16); + } else { + int predict_index, diff; + + predict_index = (lookup << (7 - lookup_size)) | (step_index << 6); + predict_index = av_clip(predict_index, 0, 5785); + diff = vima->predict_table[predict_index]; + if (lookup) + diff += ff_adpcm_step_table[step_index] >> (lookup_size - 1); + if (highbit) + diff = -diff; + + output = av_clip_int16(output + diff); + } + + *dest = output; + dest += channels; + + step_index += step_index_tables[lookup_size - 2][lookup]; + } + } + + *got_frame_ptr = 1; + + return pkt->size; +} + +AVCodec ff_vima_decoder = { + .name = "vima", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VIMA, + .priv_data_size = sizeof(VimaContext), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), +}; diff --git a/ffmpeg/libavcodec/vmdav.c b/ffmpeg/libavcodec/vmdav.c new file mode 100644 index 0000000..0e27ef6 --- /dev/null +++ b/ffmpeg/libavcodec/vmdav.c @@ -0,0 +1,662 @@ +/* + * Sierra VMD Audio & Video Decoders + * Copyright (C) 2004 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Sierra VMD audio & video decoders + * by Vladimir "VAG" Gneushev (vagsoft at mail.ru) + * for more information on the Sierra VMD format, visit: + * http://www.pcisys.net/~melanson/codecs/ + * + * The video decoder outputs PAL8 colorspace data. The decoder expects + * a 0x330-byte VMD file header to be transmitted via extradata during + * codec initialization. Each encoded frame that is sent to this decoder + * is expected to be prepended with the appropriate 16-byte frame + * information record from the VMD file. + * + * The audio decoder, like the video decoder, expects each encoded data + * chunk to be prepended with the appropriate 16-byte frame information + * record from the VMD file. It does not require the 0x330-byte VMD file + * header, but it does need the audio setup parameters passed in through + * normal libavcodec API means. + */ + +#include +#include +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +#define VMD_HEADER_SIZE 0x330 +#define PALETTE_COUNT 256 + +/* + * Video Decoder + */ + +typedef struct VmdVideoContext { + + AVCodecContext *avctx; + AVFrame prev_frame; + + const unsigned char *buf; + int size; + + unsigned char palette[PALETTE_COUNT * 4]; + unsigned char *unpack_buffer; + int unpack_buffer_size; + + int x_off, y_off; +} VmdVideoContext; + +#define QUEUE_SIZE 0x1000 +#define QUEUE_MASK 0x0FFF + +static void lz_unpack(const unsigned char *src, int src_len, + unsigned char *dest, int dest_len) +{ + const unsigned char *s; + const unsigned char *s_end; + unsigned char *d; + unsigned char *d_end; + unsigned char queue[QUEUE_SIZE]; + unsigned int qpos; + unsigned int dataleft; + unsigned int chainofs; + unsigned int chainlen; + unsigned int speclen; + unsigned char tag; + unsigned int i, j; + + s = src; + s_end = src + src_len; + d = dest; + d_end = d + dest_len; + + if (s_end - s < 8) + return; + dataleft = AV_RL32(s); + s += 4; + memset(queue, 0x20, QUEUE_SIZE); + if (AV_RL32(s) == 0x56781234) { + s += 4; + qpos = 0x111; + speclen = 0xF + 3; + } else { + qpos = 0xFEE; + speclen = 100; /* no speclen */ + } + + while (s_end - s > 0 && dataleft > 0) { + tag = *s++; + if ((tag == 0xFF) && (dataleft > 8)) { + if (d_end - d < 8 || s_end - s < 8) + return; + for (i = 0; i < 8; i++) { + queue[qpos++] = *d++ = *s++; + qpos &= QUEUE_MASK; + } + dataleft -= 8; + } else { + for (i = 0; i < 8; i++) { + if (dataleft == 0) + break; + if (tag & 0x01) { + if (d_end - d < 1 || s_end - s < 1) + return; + queue[qpos++] = *d++ = *s++; + qpos &= QUEUE_MASK; + dataleft--; + } else { + if (s_end - s < 2) + return; + chainofs = *s++; + chainofs |= ((*s & 0xF0) << 4); + chainlen = (*s++ & 0x0F) + 3; + if (chainlen == speclen) { + if (s_end - s < 1) + return; + chainlen = *s++ + 0xF + 3; + } + if (d_end - d < chainlen) + return; + for (j = 0; j < chainlen; j++) { + *d = queue[chainofs++ & QUEUE_MASK]; + queue[qpos++] = *d++; + qpos &= QUEUE_MASK; + } + dataleft -= chainlen; + } + tag >>= 1; + } + } + } +} + +static int rle_unpack(const unsigned char *src, int src_len, int src_count, + unsigned char *dest, int dest_len) +{ + const unsigned char *ps; + const unsigned char *ps_end; + unsigned char *pd; + int i, l; + unsigned char *dest_end = dest + dest_len; + + ps = src; + ps_end = src + src_len; + pd = dest; + if (src_count & 1) { + if (ps_end - ps < 1) + return 0; + *pd++ = *ps++; + } + + src_count >>= 1; + i = 0; + do { + if (ps_end - ps < 1) + break; + l = *ps++; + if (l & 0x80) { + l = (l & 0x7F) * 2; + if (dest_end - pd < l || ps_end - ps < l) + return ps - src; + memcpy(pd, ps, l); + ps += l; + pd += l; + } else { + if (dest_end - pd < i || ps_end - ps < 2) + return ps - src; + for (i = 0; i < l; i++) { + *pd++ = ps[0]; + *pd++ = ps[1]; + } + ps += 2; + } + i += l; + } while (i < src_count); + + return ps - src; +} + +static void vmd_decode(VmdVideoContext *s, AVFrame *frame) +{ + int i; + unsigned int *palette32; + unsigned char r, g, b; + + /* point to the start of the encoded data */ + const unsigned char *p = s->buf + 16; + const unsigned char *p_end = s->buf + s->size; + + const unsigned char *pb; + const unsigned char *pb_end; + unsigned char meth; + unsigned char *dp; /* pointer to current frame */ + unsigned char *pp; /* pointer to previous frame */ + unsigned char len; + int ofs; + + int frame_x, frame_y; + int frame_width, frame_height; + + frame_x = AV_RL16(&s->buf[6]); + frame_y = AV_RL16(&s->buf[8]); + frame_width = AV_RL16(&s->buf[10]) - frame_x + 1; + frame_height = AV_RL16(&s->buf[12]) - frame_y + 1; + if (frame_x < 0 || frame_width < 0 || + frame_x >= s->avctx->width || + frame_width > s->avctx->width || + frame_x + frame_width > s->avctx->width) + return; + if (frame_y < 0 || frame_height < 0 || + frame_y >= s->avctx->height || + frame_height > s->avctx->height || + frame_y + frame_height > s->avctx->height) + return; + + if ((frame_width == s->avctx->width && frame_height == s->avctx->height) && + (frame_x || frame_y)) { + + s->x_off = frame_x; + s->y_off = frame_y; + } + frame_x -= s->x_off; + frame_y -= s->y_off; + + /* if only a certain region will be updated, copy the entire previous + * frame before the decode */ + if (s->prev_frame.data[0] && + (frame_x || frame_y || (frame_width != s->avctx->width) || + (frame_height != s->avctx->height))) { + + memcpy(frame->data[0], s->prev_frame.data[0], + s->avctx->height * frame->linesize[0]); + } + + /* check if there is a new palette */ + if (s->buf[15] & 0x02) { + if (p_end - p < 2 + 3 * PALETTE_COUNT) + return; + p += 2; + palette32 = (unsigned int *)s->palette; + for (i = 0; i < PALETTE_COUNT; i++) { + r = *p++ * 4; + g = *p++ * 4; + b = *p++ * 4; + palette32[i] = 0xFFU << 24 | r << 16 | g << 8 | b; + palette32[i] |= palette32[i] >> 6 & 0x30303; + } + } + if (p < p_end) { + /* originally UnpackFrame in VAG's code */ + pb = p; + pb_end = p_end; + meth = *pb++; + if (meth & 0x80) { + lz_unpack(pb, p_end - pb, s->unpack_buffer, s->unpack_buffer_size); + meth &= 0x7F; + pb = s->unpack_buffer; + pb_end = s->unpack_buffer + s->unpack_buffer_size; + } + + dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x]; + pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x]; + switch (meth) { + case 1: + for (i = 0; i < frame_height; i++) { + ofs = 0; + do { + if (pb_end - pb < 1) + return; + len = *pb++; + if (len & 0x80) { + len = (len & 0x7F) + 1; + if (ofs + len > frame_width || pb_end - pb < len) + return; + memcpy(&dp[ofs], pb, len); + pb += len; + ofs += len; + } else { + /* interframe pixel copy */ + if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) + return; + memcpy(&dp[ofs], &pp[ofs], len + 1); + ofs += len + 1; + } + } while (ofs < frame_width); + if (ofs > frame_width) { + av_log(s->avctx, AV_LOG_ERROR, "offset > width (%d > %d)\n", + ofs, frame_width); + break; + } + dp += frame->linesize[0]; + pp += s->prev_frame.linesize[0]; + } + break; + + case 2: + for (i = 0; i < frame_height; i++) { + if (pb_end -pb < frame_width) + return; + memcpy(dp, pb, frame_width); + pb += frame_width; + dp += frame->linesize[0]; + pp += s->prev_frame.linesize[0]; + } + break; + + case 3: + for (i = 0; i < frame_height; i++) { + ofs = 0; + do { + if (pb_end - pb < 1) + return; + len = *pb++; + if (len & 0x80) { + len = (len & 0x7F) + 1; + if (pb_end - pb < 1) + return; + if (*pb++ == 0xFF) + len = rle_unpack(pb, pb_end - pb, len, &dp[ofs], frame_width - ofs); + else { + if (pb_end - pb < len) + return; + memcpy(&dp[ofs], pb, len); + } + pb += len; + ofs += len; + } else { + /* interframe pixel copy */ + if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) + return; + memcpy(&dp[ofs], &pp[ofs], len + 1); + ofs += len + 1; + } + } while (ofs < frame_width); + if (ofs > frame_width) { + av_log(s->avctx, AV_LOG_ERROR, "offset > width (%d > %d)\n", + ofs, frame_width); + } + dp += frame->linesize[0]; + pp += s->prev_frame.linesize[0]; + } + break; + } + } +} + +static av_cold int vmdvideo_decode_init(AVCodecContext *avctx) +{ + VmdVideoContext *s = avctx->priv_data; + int i; + unsigned int *palette32; + int palette_index = 0; + unsigned char r, g, b; + unsigned char *vmd_header; + unsigned char *raw_palette; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + /* make sure the VMD header made it */ + if (s->avctx->extradata_size != VMD_HEADER_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", + VMD_HEADER_SIZE); + return -1; + } + vmd_header = (unsigned char *)avctx->extradata; + + s->unpack_buffer_size = AV_RL32(&vmd_header[800]); + s->unpack_buffer = av_malloc(s->unpack_buffer_size); + if (!s->unpack_buffer) + return -1; + + /* load up the initial palette */ + raw_palette = &vmd_header[28]; + palette32 = (unsigned int *)s->palette; + for (i = 0; i < PALETTE_COUNT; i++) { + r = raw_palette[palette_index++] * 4; + g = raw_palette[palette_index++] * 4; + b = raw_palette[palette_index++] * 4; + palette32[i] = (r << 16) | (g << 8) | (b); + } + + avcodec_get_frame_defaults(&s->prev_frame); + + return 0; +} + +static int vmdvideo_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + VmdVideoContext *s = avctx->priv_data; + AVFrame *frame = data; + int ret; + + s->buf = buf; + s->size = buf_size; + + if (buf_size < 16) + return buf_size; + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + vmd_decode(s, frame); + + /* make the palette available on the way out */ + memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4); + + /* shuffle frames */ + av_frame_unref(&s->prev_frame); + if ((ret = av_frame_ref(&s->prev_frame, frame)) < 0) + return ret; + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) +{ + VmdVideoContext *s = avctx->priv_data; + + av_frame_unref(&s->prev_frame); + av_free(s->unpack_buffer); + + return 0; +} + + +/* + * Audio Decoder + */ + +#define BLOCK_TYPE_AUDIO 1 +#define BLOCK_TYPE_INITIAL 2 +#define BLOCK_TYPE_SILENCE 3 + +typedef struct VmdAudioContext { + int out_bps; + int chunk_size; +} VmdAudioContext; + +static const uint16_t vmdaudio_table[128] = { + 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, + 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120, + 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, + 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, + 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280, + 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0, + 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, + 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370, + 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0, + 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480, + 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, + 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00, + 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000 +}; + +static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) +{ + VmdAudioContext *s = avctx->priv_data; + + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + if (avctx->block_align < 1 || avctx->block_align % avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); + return AVERROR(EINVAL); + } + + avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : + AV_CH_LAYOUT_STEREO; + + if (avctx->bits_per_coded_sample == 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + else + avctx->sample_fmt = AV_SAMPLE_FMT_U8; + s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); + + s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); + + av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " + "block align = %d, sample rate = %d\n", + avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, + avctx->sample_rate); + + return 0; +} + +static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, + int channels) +{ + int ch; + const uint8_t *buf_end = buf + buf_size; + int predictor[2]; + int st = channels - 1; + + /* decode initial raw sample */ + for (ch = 0; ch < channels; ch++) { + predictor[ch] = (int16_t)AV_RL16(buf); + buf += 2; + *out++ = predictor[ch]; + } + + /* decode DPCM samples */ + ch = 0; + while (buf < buf_end) { + uint8_t b = *buf++; + if (b & 0x80) + predictor[ch] -= vmdaudio_table[b & 0x7F]; + else + predictor[ch] += vmdaudio_table[b]; + predictor[ch] = av_clip_int16(predictor[ch]); + *out++ = predictor[ch]; + ch ^= st; + } +} + +static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + const uint8_t *buf_end; + int buf_size = avpkt->size; + VmdAudioContext *s = avctx->priv_data; + int block_type, silent_chunks, audio_chunks; + int ret; + uint8_t *output_samples_u8; + int16_t *output_samples_s16; + + if (buf_size < 16) { + av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); + *got_frame_ptr = 0; + return buf_size; + } + + block_type = buf[6]; + if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) { + av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type); + return AVERROR(EINVAL); + } + buf += 16; + buf_size -= 16; + + /* get number of silent chunks */ + silent_chunks = 0; + if (block_type == BLOCK_TYPE_INITIAL) { + uint32_t flags; + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + flags = AV_RB32(buf); + silent_chunks = av_popcount(flags); + buf += 4; + buf_size -= 4; + } else if (block_type == BLOCK_TYPE_SILENCE) { + silent_chunks = 1; + buf_size = 0; // should already be zero but set it just to be sure + } + + /* ensure output buffer is large enough */ + audio_chunks = buf_size / s->chunk_size; + + /* get output buffer */ + frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / + avctx->channels; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + output_samples_u8 = frame->data[0]; + output_samples_s16 = (int16_t *)frame->data[0]; + + /* decode silent chunks */ + if (silent_chunks > 0) { + int silent_size = avctx->block_align * silent_chunks; + if (s->out_bps == 2) { + memset(output_samples_s16, 0x00, silent_size * 2); + output_samples_s16 += silent_size; + } else { + memset(output_samples_u8, 0x80, silent_size); + output_samples_u8 += silent_size; + } + } + + /* decode audio chunks */ + if (audio_chunks > 0) { + buf_end = buf + buf_size; + while (buf_end - buf >= s->chunk_size) { + if (s->out_bps == 2) { + decode_audio_s16(output_samples_s16, buf, s->chunk_size, + avctx->channels); + output_samples_s16 += avctx->block_align; + } else { + memcpy(output_samples_u8, buf, s->chunk_size); + output_samples_u8 += avctx->block_align; + } + buf += s->chunk_size; + } + } + + *got_frame_ptr = 1; + + return avpkt->size; +} + + +/* + * Public Data Structures + */ + +AVCodec ff_vmdvideo_decoder = { + .name = "vmdvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VMDVIDEO, + .priv_data_size = sizeof(VmdVideoContext), + .init = vmdvideo_decode_init, + .close = vmdvideo_decode_end, + .decode = vmdvideo_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), +}; + +AVCodec ff_vmdaudio_decoder = { + .name = "vmdaudio", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VMDAUDIO, + .priv_data_size = sizeof(VmdAudioContext), + .init = vmdaudio_decode_init, + .decode = vmdaudio_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), +}; diff --git a/ffmpeg/libavcodec/vmnc.c b/ffmpeg/libavcodec/vmnc.c new file mode 100644 index 0000000..99571a1 --- /dev/null +++ b/ffmpeg/libavcodec/vmnc.c @@ -0,0 +1,532 @@ +/* + * VMware Screen Codec (VMnc) decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * VMware Screen Codec (VMnc) decoder + * As Alex Beregszaszi discovered, this is effectively RFB data dump + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +enum EncTypes { + MAGIC_WMVd = 0x574D5664, + MAGIC_WMVe, + MAGIC_WMVf, + MAGIC_WMVg, + MAGIC_WMVh, + MAGIC_WMVi, + MAGIC_WMVj +}; + +enum HexTile_Flags { + HT_RAW = 1, // tile is raw + HT_BKG = 2, // background color is present + HT_FG = 4, // foreground color is present + HT_SUB = 8, // subrects are present + HT_CLR = 16 // each subrect has own color +}; + +/* + * Decoder context + */ +typedef struct VmncContext { + AVCodecContext *avctx; + AVFrame pic; + + int bpp; + int bpp2; + int bigendian; + uint8_t pal[768]; + int width, height; + + /* cursor data */ + int cur_w, cur_h; + int cur_x, cur_y; + int cur_hx, cur_hy; + uint8_t* curbits, *curmask; + uint8_t* screendta; +} VmncContext; + +/* read pixel value from stream */ +static av_always_inline int vmnc_get_pixel(const uint8_t* buf, int bpp, int be) { + switch(bpp * 2 + be) { + case 2: + case 3: return *buf; + case 4: return AV_RL16(buf); + case 5: return AV_RB16(buf); + case 8: return AV_RL32(buf); + case 9: return AV_RB32(buf); + default: return 0; + } +} + +static void load_cursor(VmncContext *c, const uint8_t *src) +{ + int i, j, p; + const int bpp = c->bpp2; + uint8_t *dst8 = c->curbits; + uint16_t *dst16 = (uint16_t*)c->curbits; + uint32_t *dst32 = (uint32_t*)c->curbits; + + for(j = 0; j < c->cur_h; j++) { + for(i = 0; i < c->cur_w; i++) { + p = vmnc_get_pixel(src, bpp, c->bigendian); + src += bpp; + if(bpp == 1) *dst8++ = p; + if(bpp == 2) *dst16++ = p; + if(bpp == 4) *dst32++ = p; + } + } + dst8 = c->curmask; + dst16 = (uint16_t*)c->curmask; + dst32 = (uint32_t*)c->curmask; + for(j = 0; j < c->cur_h; j++) { + for(i = 0; i < c->cur_w; i++) { + p = vmnc_get_pixel(src, bpp, c->bigendian); + src += bpp; + if(bpp == 1) *dst8++ = p; + if(bpp == 2) *dst16++ = p; + if(bpp == 4) *dst32++ = p; + } + } +} + +static void put_cursor(uint8_t *dst, int stride, VmncContext *c, int dx, int dy) +{ + int i, j; + int w, h, x, y; + w = c->cur_w; + if(c->width < c->cur_x + c->cur_w) w = c->width - c->cur_x; + h = c->cur_h; + if(c->height < c->cur_y + c->cur_h) h = c->height - c->cur_y; + x = c->cur_x; + y = c->cur_y; + if(x < 0) { + w += x; + x = 0; + } + if(y < 0) { + h += y; + y = 0; + } + + if((w < 1) || (h < 1)) return; + dst += x * c->bpp2 + y * stride; + + if(c->bpp2 == 1) { + uint8_t* cd = c->curbits, *msk = c->curmask; + for(j = 0; j < h; j++) { + for(i = 0; i < w; i++) + dst[i] = (dst[i] & cd[i]) ^ msk[i]; + msk += c->cur_w; + cd += c->cur_w; + dst += stride; + } + } else if(c->bpp2 == 2) { + uint16_t* cd = (uint16_t*)c->curbits, *msk = (uint16_t*)c->curmask; + uint16_t* dst2; + for(j = 0; j < h; j++) { + dst2 = (uint16_t*)dst; + for(i = 0; i < w; i++) + dst2[i] = (dst2[i] & cd[i]) ^ msk[i]; + msk += c->cur_w; + cd += c->cur_w; + dst += stride; + } + } else if(c->bpp2 == 4) { + uint32_t* cd = (uint32_t*)c->curbits, *msk = (uint32_t*)c->curmask; + uint32_t* dst2; + for(j = 0; j < h; j++) { + dst2 = (uint32_t*)dst; + for(i = 0; i < w; i++) + dst2[i] = (dst2[i] & cd[i]) ^ msk[i]; + msk += c->cur_w; + cd += c->cur_w; + dst += stride; + } + } +} + +/* fill rectangle with given color */ +static av_always_inline void paint_rect(uint8_t *dst, int dx, int dy, int w, int h, int color, int bpp, int stride) +{ + int i, j; + dst += dx * bpp + dy * stride; + if(bpp == 1){ + for(j = 0; j < h; j++) { + memset(dst, color, w); + dst += stride; + } + }else if(bpp == 2){ + uint16_t* dst2; + for(j = 0; j < h; j++) { + dst2 = (uint16_t*)dst; + for(i = 0; i < w; i++) { + *dst2++ = color; + } + dst += stride; + } + }else if(bpp == 4){ + uint32_t* dst2; + for(j = 0; j < h; j++) { + dst2 = (uint32_t*)dst; + for(i = 0; i < w; i++) { + dst2[i] = color; + } + dst += stride; + } + } +} + +static av_always_inline void paint_raw(uint8_t *dst, int w, int h, const uint8_t* src, int bpp, int be, int stride) +{ + int i, j, p; + for(j = 0; j < h; j++) { + for(i = 0; i < w; i++) { + p = vmnc_get_pixel(src, bpp, be); + src += bpp; + switch(bpp){ + case 1: + dst[i] = p; + break; + case 2: + ((uint16_t*)dst)[i] = p; + break; + case 4: + ((uint32_t*)dst)[i] = p; + break; + } + } + dst += stride; + } +} + +static int decode_hextile(VmncContext *c, uint8_t* dst, const uint8_t* src, int ssize, int w, int h, int stride) +{ + int i, j, k; + int bg = 0, fg = 0, rects, color, flags, xy, wh; + const int bpp = c->bpp2; + uint8_t *dst2; + int bw = 16, bh = 16; + const uint8_t *ssrc=src; + + for(j = 0; j < h; j += 16) { + dst2 = dst; + bw = 16; + if(j + 16 > h) bh = h - j; + for(i = 0; i < w; i += 16, dst2 += 16 * bpp) { + if(src - ssrc >= ssize) { + av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); + return -1; + } + if(i + 16 > w) bw = w - i; + flags = *src++; + if(flags & HT_RAW) { + if(src - ssrc > ssize - bw * bh * bpp) { + av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); + return -1; + } + paint_raw(dst2, bw, bh, src, bpp, c->bigendian, stride); + src += bw * bh * bpp; + } else { + if(flags & HT_BKG) { + bg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; + } + if(flags & HT_FG) { + fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; + } + rects = 0; + if(flags & HT_SUB) + rects = *src++; + color = !!(flags & HT_CLR); + + paint_rect(dst2, 0, 0, bw, bh, bg, bpp, stride); + + if(src - ssrc > ssize - rects * (color * bpp + 2)) { + av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); + return -1; + } + for(k = 0; k < rects; k++) { + if(color) { + fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; + } + xy = *src++; + wh = *src++; + paint_rect(dst2, xy >> 4, xy & 0xF, (wh>>4)+1, (wh & 0xF)+1, fg, bpp, stride); + } + } + } + dst += stride * 16; + } + return src - ssrc; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + VmncContext * const c = avctx->priv_data; + uint8_t *outptr; + const uint8_t *src = buf; + int dx, dy, w, h, depth, enc, chunks, res, size_left, ret; + + if ((ret = ff_reget_buffer(avctx, &c->pic)) < 0) + return ret; + + c->pic.key_frame = 0; + c->pic.pict_type = AV_PICTURE_TYPE_P; + + //restore screen after cursor + if(c->screendta) { + int i; + w = c->cur_w; + if(c->width < c->cur_x + w) w = c->width - c->cur_x; + h = c->cur_h; + if(c->height < c->cur_y + h) h = c->height - c->cur_y; + dx = c->cur_x; + if(dx < 0) { + w += dx; + dx = 0; + } + dy = c->cur_y; + if(dy < 0) { + h += dy; + dy = 0; + } + if((w > 0) && (h > 0)) { + outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; + for(i = 0; i < h; i++) { + memcpy(outptr, c->screendta + i * c->cur_w * c->bpp2, w * c->bpp2); + outptr += c->pic.linesize[0]; + } + } + } + src += 2; + chunks = AV_RB16(src); src += 2; + while(chunks--) { + if(buf_size - (src - buf) < 12) { + av_log(avctx, AV_LOG_ERROR, "Premature end of data!\n"); + return -1; + } + dx = AV_RB16(src); src += 2; + dy = AV_RB16(src); src += 2; + w = AV_RB16(src); src += 2; + h = AV_RB16(src); src += 2; + enc = AV_RB32(src); src += 4; + outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; + size_left = buf_size - (src - buf); + switch(enc) { + case MAGIC_WMVd: // cursor + if (w*(int64_t)h*c->bpp2 > INT_MAX/2 - 2) { + av_log(avctx, AV_LOG_ERROR, "dimensions too large\n"); + return AVERROR_INVALIDDATA; + } + if(size_left < 2 + w * h * c->bpp2 * 2) { + av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", 2 + w * h * c->bpp2 * 2, size_left); + return -1; + } + src += 2; + c->cur_w = w; + c->cur_h = h; + c->cur_hx = dx; + c->cur_hy = dy; + if((c->cur_hx > c->cur_w) || (c->cur_hy > c->cur_h)) { + av_log(avctx, AV_LOG_ERROR, "Cursor hot spot is not in image: %ix%i of %ix%i cursor size\n", c->cur_hx, c->cur_hy, c->cur_w, c->cur_h); + c->cur_hx = c->cur_hy = 0; + } + c->curbits = av_realloc(c->curbits, c->cur_w * c->cur_h * c->bpp2); + c->curmask = av_realloc(c->curmask, c->cur_w * c->cur_h * c->bpp2); + c->screendta = av_realloc(c->screendta, c->cur_w * c->cur_h * c->bpp2); + load_cursor(c, src); + src += w * h * c->bpp2 * 2; + break; + case MAGIC_WMVe: // unknown + src += 2; + break; + case MAGIC_WMVf: // update cursor position + c->cur_x = dx - c->cur_hx; + c->cur_y = dy - c->cur_hy; + break; + case MAGIC_WMVg: // unknown + src += 10; + break; + case MAGIC_WMVh: // unknown + src += 4; + break; + case MAGIC_WMVi: // ServerInitialization struct + c->pic.key_frame = 1; + c->pic.pict_type = AV_PICTURE_TYPE_I; + depth = *src++; + if(depth != c->bpp) { + av_log(avctx, AV_LOG_INFO, "Depth mismatch. Container %i bpp, Frame data: %i bpp\n", c->bpp, depth); + } + src++; + c->bigendian = *src++; + if(c->bigendian & (~1)) { + av_log(avctx, AV_LOG_INFO, "Invalid header: bigendian flag = %i\n", c->bigendian); + return -1; + } + //skip the rest of pixel format data + src += 13; + break; + case MAGIC_WMVj: // unknown + src += 2; + break; + case 0x00000000: // raw rectangle data + if((dx + w > c->width) || (dy + h > c->height)) { + av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height); + return -1; + } + if(size_left < w * h * c->bpp2) { + av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", w * h * c->bpp2, size_left); + return -1; + } + paint_raw(outptr, w, h, src, c->bpp2, c->bigendian, c->pic.linesize[0]); + src += w * h * c->bpp2; + break; + case 0x00000005: // HexTile encoded rectangle + if((dx + w > c->width) || (dy + h > c->height)) { + av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height); + return -1; + } + res = decode_hextile(c, outptr, src, size_left, w, h, c->pic.linesize[0]); + if(res < 0) + return -1; + src += res; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported block type 0x%08X\n", enc); + chunks = 0; // leave chunks decoding loop + } + } + if(c->screendta){ + int i; + //save screen data before painting cursor + w = c->cur_w; + if(c->width < c->cur_x + w) w = c->width - c->cur_x; + h = c->cur_h; + if(c->height < c->cur_y + h) h = c->height - c->cur_y; + dx = c->cur_x; + if(dx < 0) { + w += dx; + dx = 0; + } + dy = c->cur_y; + if(dy < 0) { + h += dy; + dy = 0; + } + if((w > 0) && (h > 0)) { + outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; + for(i = 0; i < h; i++) { + memcpy(c->screendta + i * c->cur_w * c->bpp2, outptr, w * c->bpp2); + outptr += c->pic.linesize[0]; + } + outptr = c->pic.data[0]; + put_cursor(outptr, c->pic.linesize[0], c, c->cur_x, c->cur_y); + } + } + *got_frame = 1; + if ((ret = av_frame_ref(data, &c->pic)) < 0) + return ret; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + + + +/* + * + * Init VMnc decoder + * + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + VmncContext * const c = avctx->priv_data; + + c->avctx = avctx; + + c->width = avctx->width; + c->height = avctx->height; + + c->bpp = avctx->bits_per_coded_sample; + c->bpp2 = c->bpp/8; + avcodec_get_frame_defaults(&c->pic); + + switch(c->bpp){ + case 8: + avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + case 16: + avctx->pix_fmt = AV_PIX_FMT_RGB555; + break; + case 32: + avctx->pix_fmt = AV_PIX_FMT_RGB32; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", c->bpp); + return AVERROR_INVALIDDATA; + } + + avcodec_get_frame_defaults(&c->pic); + + return 0; +} + + + +/* + * + * Uninit VMnc decoder + * + */ +static av_cold int decode_end(AVCodecContext *avctx) +{ + VmncContext * const c = avctx->priv_data; + + av_frame_unref(&c->pic); + + av_free(c->curbits); + av_free(c->curmask); + av_free(c->screendta); + return 0; +} + +AVCodec ff_vmnc_decoder = { + .name = "vmnc", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VMNC, + .priv_data_size = sizeof(VmncContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("VMware Screen Codec / VMware Video"), +}; diff --git a/ffmpeg/libavcodec/vorbis.c b/ffmpeg/libavcodec/vorbis.c new file mode 100644 index 0000000..6eb765d --- /dev/null +++ b/ffmpeg/libavcodec/vorbis.c @@ -0,0 +1,236 @@ +/** + * @file + * Common code for Vorbis I encoder and decoder + * @author Denes Balatoni ( dbalatoni programozo hu ) + * + * 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 + */ + +/** + * @file + * Common code for Vorbis I encoder and decoder + * @author Denes Balatoni ( dbalatoni programozo hu ) + */ + +#define BITSTREAM_READER_LE +#include "avcodec.h" +#include "get_bits.h" + +#include "vorbis.h" + + +/* Helper functions */ + +// x^(1/n) +unsigned int ff_vorbis_nth_root(unsigned int x, unsigned int n) +{ + unsigned int ret = 0, i, j; + + do { + ++ret; + for (i = 0, j = ret; i < n - 1; i++) + j *= ret; + } while (j <= x); + + return ret - 1; +} + +// Generate vlc codes from vorbis huffman code lengths + +// the two bits[p] > 32 checks should be redundant, all calling code should +// already ensure that, but since it allows overwriting the stack it seems +// reasonable to check redundantly. +int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num) +{ + uint32_t exit_at_level[33] = { 404 }; + + unsigned i, j, p, code; + +#ifdef DEBUG + GetBitContext gb; +#endif + + for (p = 0; (bits[p] == 0) && (p < num); ++p) + ; + if (p == num) + return 0; + + codes[p] = 0; + if (bits[p] > 32) + return 1; + for (i = 0; i < bits[p]; ++i) + exit_at_level[i+1] = 1 << i; + +#ifdef DEBUG + av_log(NULL, AV_LOG_INFO, " %u. of %u code len %d code %d - ", p, num, bits[p], codes[p]); + init_get_bits(&gb, (uint8_t *)&codes[p], bits[p]); + for (i = 0; i < bits[p]; ++i) + av_log(NULL, AV_LOG_INFO, "%s", get_bits1(&gb) ? "1" : "0"); + av_log(NULL, AV_LOG_INFO, "\n"); +#endif + + ++p; + + for (; p < num; ++p) { + if (bits[p] > 32) + return 1; + if (bits[p] == 0) + continue; + // find corresponding exit(node which the tree can grow further from) + for (i = bits[p]; i > 0; --i) + if (exit_at_level[i]) + break; + if (!i) // overspecified tree + return 1; + code = exit_at_level[i]; + exit_at_level[i] = 0; + // construct code (append 0s to end) and introduce new exits + for (j = i + 1 ;j <= bits[p]; ++j) + exit_at_level[j] = code + (1 << (j - 1)); + codes[p] = code; + +#ifdef DEBUG + av_log(NULL, AV_LOG_INFO, " %d. code len %d code %d - ", p, bits[p], codes[p]); + init_get_bits(&gb, (uint8_t *)&codes[p], bits[p]); + for (i = 0; i < bits[p]; ++i) + av_log(NULL, AV_LOG_INFO, "%s", get_bits1(&gb) ? "1" : "0"); + av_log(NULL, AV_LOG_INFO, "\n"); +#endif + + } + + //no exits should be left (underspecified tree - ie. unused valid vlcs - not allowed by SPEC) + for (p = 1; p < 33; p++) + if (exit_at_level[p]) + return 1; + + return 0; +} + +int ff_vorbis_ready_floor1_list(AVCodecContext *avctx, + vorbis_floor1_entry *list, int values) +{ + int i; + list[0].sort = 0; + list[1].sort = 1; + for (i = 2; i < values; i++) { + int j; + list[i].low = 0; + list[i].high = 1; + list[i].sort = i; + for (j = 2; j < i; j++) { + int tmp = list[j].x; + if (tmp < list[i].x) { + if (tmp > list[list[i].low].x) + list[i].low = j; + } else { + if (tmp < list[list[i].high].x) + list[i].high = j; + } + } + } + for (i = 0; i < values - 1; i++) { + int j; + for (j = i + 1; j < values; j++) { + if (list[i].x == list[j].x) { + av_log(avctx, AV_LOG_ERROR, + "Duplicate value found in floor 1 X coordinates\n"); + return AVERROR_INVALIDDATA; + } + if (list[list[i].sort].x > list[list[j].sort].x) { + int tmp = list[i].sort; + list[i].sort = list[j].sort; + list[j].sort = tmp; + } + } + } + return 0; +} + +static inline void render_line_unrolled(intptr_t x, int y, int x1, + intptr_t sy, int ady, int adx, + float *buf) +{ + int err = -adx; + x -= x1 - 1; + buf += x1 - 1; + while (++x < 0) { + err += ady; + if (err >= 0) { + err += ady - adx; + y += sy; + buf[x++] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)]; + } + buf[x] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)]; + } + if (x <= 0) { + if (err + ady >= 0) + y += sy; + buf[x] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)]; + } +} + +static void render_line(int x0, int y0, int x1, int y1, float *buf) +{ + int dy = y1 - y0; + int adx = x1 - x0; + int ady = FFABS(dy); + int sy = dy < 0 ? -1 : 1; + buf[x0] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y0)]; + if (ady*2 <= adx) { // optimized common case + render_line_unrolled(x0, y0, x1, sy, ady, adx, buf); + } else { + int base = dy / adx; + int x = x0; + int y = y0; + int err = -adx; + ady -= FFABS(base) * adx; + while (++x < x1) { + y += base; + err += ady; + if (err >= 0) { + err -= adx; + y += sy; + } + buf[x] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)]; + } + } +} + +void ff_vorbis_floor1_render_list(vorbis_floor1_entry * list, int values, + uint16_t *y_list, int *flag, + int multiplier, float *out, int samples) +{ + int lx, ly, i; + lx = 0; + ly = y_list[0] * multiplier; + for (i = 1; i < values; i++) { + int pos = list[i].sort; + if (flag[pos]) { + int x1 = list[pos].x; + int y1 = y_list[pos] * multiplier; + if (lx < samples) + render_line(lx, ly, FFMIN(x1,samples), y1, out); + lx = x1; + ly = y1; + } + if (lx >= samples) + break; + } + if (lx < samples) + render_line(lx, ly, samples, ly, out); +} diff --git a/ffmpeg/libavcodec/vorbis.h b/ffmpeg/libavcodec/vorbis.h new file mode 100644 index 0000000..98dd14f --- /dev/null +++ b/ffmpeg/libavcodec/vorbis.h @@ -0,0 +1,50 @@ +/* + * copyright (c) 2006 Oded Shimon + * + * 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 + */ + +#ifndef AVCODEC_VORBIS_H +#define AVCODEC_VORBIS_H + +#include "avcodec.h" + +extern const float ff_vorbis_floor1_inverse_db_table[256]; +extern const float * const ff_vorbis_vwin[8]; +extern const uint8_t ff_vorbis_channel_layout_offsets[8][8]; +extern const uint8_t ff_vorbis_encoding_channel_layout_offsets[8][8]; +extern const uint64_t ff_vorbis_channel_layouts[9]; + +typedef struct vorbis_floor1_entry { + uint16_t x; + uint16_t sort; + uint16_t low; + uint16_t high; +} vorbis_floor1_entry; + +int ff_vorbis_ready_floor1_list(AVCodecContext *avctx, + vorbis_floor1_entry *list, int values); +unsigned int ff_vorbis_nth_root(unsigned int x, unsigned int n); // x^(1/n) +int ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num); +void ff_vorbis_floor1_render_list(vorbis_floor1_entry * list, int values, + uint16_t *y_list, int *flag, + int multiplier, float * out, int samples); +void ff_vorbis_inverse_coupling(float *mag, float *ang, intptr_t blocksize); + +#define ilog(i) av_log2(2*(i)) + +#endif /* AVCODEC_VORBIS_H */ diff --git a/ffmpeg/libavcodec/vorbis_data.c b/ffmpeg/libavcodec/vorbis_data.c new file mode 100644 index 0000000..063a075 --- /dev/null +++ b/ffmpeg/libavcodec/vorbis_data.c @@ -0,0 +1,2193 @@ +/* + * copyright (c) 2005 Denes Balatoni ( dbalatoni programozo hu ) + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/mem.h" +#include "vorbis.h" + +const uint8_t ff_vorbis_channel_layout_offsets[8][8] = { + { 0 }, + { 0, 1 }, + { 0, 2, 1 }, + { 0, 1, 2, 3 }, + { 0, 2, 1, 3, 4 }, + { 0, 2, 1, 5, 3, 4 }, + { 0, 2, 1, 6, 5, 3, 4 }, + { 0, 2, 1, 7, 5, 6, 3, 4 }, +}; + +const uint8_t ff_vorbis_encoding_channel_layout_offsets[8][8] = { + { 0 }, + { 0, 1 }, + { 0, 2, 1 }, + { 0, 1, 2, 3 }, + { 0, 2, 1, 3, 4 }, + { 0, 2, 1, 4, 5, 3 }, + { 0, 2, 1, 5, 6, 4, 3 }, + { 0, 2, 1, 6, 7, 4, 5, 3 }, +}; + +const uint64_t ff_vorbis_channel_layouts[9] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_QUAD, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER, + AV_CH_LAYOUT_7POINT1, + 0 +}; + +DECLARE_ALIGNED(16, static const float, vwin64)[32] = { + 0.0009460463F, 0.0085006468F, 0.0235352254F, 0.0458950567F, + 0.0753351908F, 0.1115073077F, 0.1539457973F, 0.2020557475F, + 0.2551056759F, 0.3122276645F, 0.3724270287F, 0.4346027792F, + 0.4975789974F, 0.5601459521F, 0.6211085051F, 0.6793382689F, + 0.7338252629F, 0.7837245849F, 0.8283939355F, 0.8674186656F, + 0.9006222429F, 0.9280614787F, 0.9500073081F, 0.9669131782F, + 0.9793740220F, 0.9880792941F, 0.9937636139F, 0.9971582668F, + 0.9989462667F, 0.9997230082F, 0.9999638688F, 0.9999995525F, +}; + +DECLARE_ALIGNED(16, static const float, vwin128)[64] = { + 0.0002365472F, 0.0021280687F, 0.0059065254F, 0.0115626550F, + 0.0190823442F, 0.0284463735F, 0.0396300935F, 0.0526030430F, + 0.0673285281F, 0.0837631763F, 0.1018564887F, 0.1215504095F, + 0.1427789367F, 0.1654677960F, 0.1895342001F, 0.2148867160F, + 0.2414252576F, 0.2690412240F, 0.2976177952F, 0.3270303960F, + 0.3571473350F, 0.3878306189F, 0.4189369387F, 0.4503188188F, + 0.4818259135F, 0.5133064334F, 0.5446086751F, 0.5755826278F, + 0.6060816248F, 0.6359640047F, 0.6650947483F, 0.6933470543F, + 0.7206038179F, 0.7467589810F, 0.7717187213F, 0.7954024542F, + 0.8177436264F, 0.8386902831F, 0.8582053981F, 0.8762669622F, + 0.8928678298F, 0.9080153310F, 0.9217306608F, 0.9340480615F, + 0.9450138200F, 0.9546851041F, 0.9631286621F, 0.9704194171F, + 0.9766389810F, 0.9818741197F, 0.9862151938F, 0.9897546035F, + 0.9925852598F, 0.9947991032F, 0.9964856900F, 0.9977308602F, + 0.9986155015F, 0.9992144193F, 0.9995953200F, 0.9998179155F, + 0.9999331503F, 0.9999825563F, 0.9999977357F, 0.9999999720F, +}; + +DECLARE_ALIGNED(16, static const float, vwin256)[128] = { + 0.0000591390F, 0.0005321979F, 0.0014780301F, 0.0028960636F, + 0.0047854363F, 0.0071449926F, 0.0099732775F, 0.0132685298F, + 0.0170286741F, 0.0212513119F, 0.0259337111F, 0.0310727950F, + 0.0366651302F, 0.0427069140F, 0.0491939614F, 0.0561216907F, + 0.0634851102F, 0.0712788035F, 0.0794969160F, 0.0881331402F, + 0.0971807028F, 0.1066323515F, 0.1164803426F, 0.1267164297F, + 0.1373318534F, 0.1483173323F, 0.1596630553F, 0.1713586755F, + 0.1833933062F, 0.1957555184F, 0.2084333404F, 0.2214142599F, + 0.2346852280F, 0.2482326664F, 0.2620424757F, 0.2761000481F, + 0.2903902813F, 0.3048975959F, 0.3196059553F, 0.3344988887F, + 0.3495595160F, 0.3647705766F, 0.3801144597F, 0.3955732382F, + 0.4111287047F, 0.4267624093F, 0.4424557009F, 0.4581897696F, + 0.4739456913F, 0.4897044744F, 0.5054471075F, 0.5211546088F, + 0.5368080763F, 0.5523887395F, 0.5678780103F, 0.5832575361F, + 0.5985092508F, 0.6136154277F, 0.6285587300F, 0.6433222619F, + 0.6578896175F, 0.6722449294F, 0.6863729144F, 0.7002589187F, + 0.7138889597F, 0.7272497662F, 0.7403288154F, 0.7531143679F, + 0.7655954985F, 0.7777621249F, 0.7896050322F, 0.8011158947F, + 0.8122872932F, 0.8231127294F, 0.8335866365F, 0.8437043850F, + 0.8534622861F, 0.8628575905F, 0.8718884835F, 0.8805540765F, + 0.8888543947F, 0.8967903616F, 0.9043637797F, 0.9115773078F, + 0.9184344360F, 0.9249394562F, 0.9310974312F, 0.9369141608F, + 0.9423961446F, 0.9475505439F, 0.9523851406F, 0.9569082947F, + 0.9611289005F, 0.9650563408F, 0.9687004405F, 0.9720714191F, + 0.9751798427F, 0.9780365753F, 0.9806527301F, 0.9830396204F, + 0.9852087111F, 0.9871715701F, 0.9889398207F, 0.9905250941F, + 0.9919389832F, 0.9931929973F, 0.9942985174F, 0.9952667537F, + 0.9961087037F, 0.9968351119F, 0.9974564312F, 0.9979827858F, + 0.9984239359F, 0.9987892441F, 0.9990876435F, 0.9993276081F, + 0.9995171241F, 0.9996636648F, 0.9997741654F, 0.9998550016F, + 0.9999119692F, 0.9999502656F, 0.9999744742F, 0.9999885497F, + 0.9999958064F, 0.9999989077F, 0.9999998584F, 0.9999999983F, +}; + +DECLARE_ALIGNED(16, static const float, vwin512)[256] = { + 0.0000147849F, 0.0001330607F, 0.0003695946F, 0.0007243509F, + 0.0011972759F, 0.0017882983F, 0.0024973285F, 0.0033242588F, + 0.0042689632F, 0.0053312973F, 0.0065110982F, 0.0078081841F, + 0.0092223540F, 0.0107533880F, 0.0124010466F, 0.0141650703F, + 0.0160451800F, 0.0180410758F, 0.0201524373F, 0.0223789233F, + 0.0247201710F, 0.0271757958F, 0.0297453914F, 0.0324285286F, + 0.0352247556F, 0.0381335972F, 0.0411545545F, 0.0442871045F, + 0.0475306997F, 0.0508847676F, 0.0543487103F, 0.0579219038F, + 0.0616036982F, 0.0653934164F, 0.0692903546F, 0.0732937809F, + 0.0774029356F, 0.0816170305F, 0.0859352485F, 0.0903567428F, + 0.0948806375F, 0.0995060259F, 0.1042319712F, 0.1090575056F, + 0.1139816300F, 0.1190033137F, 0.1241214941F, 0.1293350764F, + 0.1346429333F, 0.1400439046F, 0.1455367974F, 0.1511203852F, + 0.1567934083F, 0.1625545735F, 0.1684025537F, 0.1743359881F, + 0.1803534820F, 0.1864536069F, 0.1926349000F, 0.1988958650F, + 0.2052349715F, 0.2116506555F, 0.2181413191F, 0.2247053313F, + 0.2313410275F, 0.2380467105F, 0.2448206500F, 0.2516610835F, + 0.2585662164F, 0.2655342226F, 0.2725632448F, 0.2796513950F, + 0.2867967551F, 0.2939973773F, 0.3012512852F, 0.3085564739F, + 0.3159109111F, 0.3233125375F, 0.3307592680F, 0.3382489922F, + 0.3457795756F, 0.3533488602F, 0.3609546657F, 0.3685947904F, + 0.3762670121F, 0.3839690896F, 0.3916987634F, 0.3994537572F, + 0.4072317788F, 0.4150305215F, 0.4228476653F, 0.4306808783F, + 0.4385278181F, 0.4463861329F, 0.4542534630F, 0.4621274424F, + 0.4700057001F, 0.4778858615F, 0.4857655502F, 0.4936423891F, + 0.5015140023F, 0.5093780165F, 0.5172320626F, 0.5250737772F, + 0.5329008043F, 0.5407107971F, 0.5485014192F, 0.5562703465F, + 0.5640152688F, 0.5717338914F, 0.5794239366F, 0.5870831457F, + 0.5947092801F, 0.6023001235F, 0.6098534829F, 0.6173671907F, + 0.6248391059F, 0.6322671161F, 0.6396491384F, 0.6469831217F, + 0.6542670475F, 0.6614989319F, 0.6686768267F, 0.6757988210F, + 0.6828630426F, 0.6898676592F, 0.6968108799F, 0.7036909564F, + 0.7105061843F, 0.7172549043F, 0.7239355032F, 0.7305464154F, + 0.7370861235F, 0.7435531598F, 0.7499461068F, 0.7562635986F, + 0.7625043214F, 0.7686670148F, 0.7747504721F, 0.7807535410F, + 0.7866751247F, 0.7925141825F, 0.7982697296F, 0.8039408387F, + 0.8095266395F, 0.8150263196F, 0.8204391248F, 0.8257643590F, + 0.8310013848F, 0.8361496236F, 0.8412085555F, 0.8461777194F, + 0.8510567129F, 0.8558451924F, 0.8605428730F, 0.8651495278F, + 0.8696649882F, 0.8740891432F, 0.8784219392F, 0.8826633797F, + 0.8868135244F, 0.8908724888F, 0.8948404441F, 0.8987176157F, + 0.9025042831F, 0.9062007791F, 0.9098074886F, 0.9133248482F, + 0.9167533451F, 0.9200935163F, 0.9233459472F, 0.9265112712F, + 0.9295901680F, 0.9325833632F, 0.9354916263F, 0.9383157705F, + 0.9410566504F, 0.9437151618F, 0.9462922398F, 0.9487888576F, + 0.9512060252F, 0.9535447882F, 0.9558062262F, 0.9579914516F, + 0.9601016078F, 0.9621378683F, 0.9641014348F, 0.9659935361F, + 0.9678154261F, 0.9695683830F, 0.9712537071F, 0.9728727198F, + 0.9744267618F, 0.9759171916F, 0.9773453842F, 0.9787127293F, + 0.9800206298F, 0.9812705006F, 0.9824637665F, 0.9836018613F, + 0.9846862258F, 0.9857183066F, 0.9866995544F, 0.9876314227F, + 0.9885153662F, 0.9893528393F, 0.9901452948F, 0.9908941823F, + 0.9916009470F, 0.9922670279F, 0.9928938570F, 0.9934828574F, + 0.9940354423F, 0.9945530133F, 0.9950369595F, 0.9954886562F, + 0.9959094633F, 0.9963007242F, 0.9966637649F, 0.9969998925F, + 0.9973103939F, 0.9975965351F, 0.9978595598F, 0.9981006885F, + 0.9983211172F, 0.9985220166F, 0.9987045311F, 0.9988697776F, + 0.9990188449F, 0.9991527924F, 0.9992726499F, 0.9993794157F, + 0.9994740570F, 0.9995575079F, 0.9996306699F, 0.9996944099F, + 0.9997495605F, 0.9997969190F, 0.9998372465F, 0.9998712678F, + 0.9998996704F, 0.9999231041F, 0.9999421807F, 0.9999574732F, + 0.9999695157F, 0.9999788026F, 0.9999857885F, 0.9999908879F, + 0.9999944746F, 0.9999968817F, 0.9999984010F, 0.9999992833F, + 0.9999997377F, 0.9999999317F, 0.9999999911F, 0.9999999999F, +}; + +DECLARE_ALIGNED(16, static const float, vwin1024)[512] = { + 0.0000036962F, 0.0000332659F, 0.0000924041F, 0.0001811086F, + 0.0002993761F, 0.0004472021F, 0.0006245811F, 0.0008315063F, + 0.0010679699F, 0.0013339631F, 0.0016294757F, 0.0019544965F, + 0.0023090133F, 0.0026930125F, 0.0031064797F, 0.0035493989F, + 0.0040217533F, 0.0045235250F, 0.0050546946F, 0.0056152418F, + 0.0062051451F, 0.0068243817F, 0.0074729278F, 0.0081507582F, + 0.0088578466F, 0.0095941655F, 0.0103596863F, 0.0111543789F, + 0.0119782122F, 0.0128311538F, 0.0137131701F, 0.0146242260F, + 0.0155642855F, 0.0165333111F, 0.0175312640F, 0.0185581042F, + 0.0196137903F, 0.0206982797F, 0.0218115284F, 0.0229534910F, + 0.0241241208F, 0.0253233698F, 0.0265511886F, 0.0278075263F, + 0.0290923308F, 0.0304055484F, 0.0317471241F, 0.0331170013F, + 0.0345151222F, 0.0359414274F, 0.0373958560F, 0.0388783456F, + 0.0403888325F, 0.0419272511F, 0.0434935347F, 0.0450876148F, + 0.0467094213F, 0.0483588828F, 0.0500359261F, 0.0517404765F, + 0.0534724575F, 0.0552317913F, 0.0570183983F, 0.0588321971F, + 0.0606731048F, 0.0625410369F, 0.0644359070F, 0.0663576272F, + 0.0683061077F, 0.0702812571F, 0.0722829821F, 0.0743111878F, + 0.0763657775F, 0.0784466526F, 0.0805537129F, 0.0826868561F, + 0.0848459782F, 0.0870309736F, 0.0892417345F, 0.0914781514F, + 0.0937401128F, 0.0960275056F, 0.0983402145F, 0.1006781223F, + 0.1030411101F, 0.1054290568F, 0.1078418397F, 0.1102793336F, + 0.1127414119F, 0.1152279457F, 0.1177388042F, 0.1202738544F, + 0.1228329618F, 0.1254159892F, 0.1280227980F, 0.1306532471F, + 0.1333071937F, 0.1359844927F, 0.1386849970F, 0.1414085575F, + 0.1441550230F, 0.1469242403F, 0.1497160539F, 0.1525303063F, + 0.1553668381F, 0.1582254875F, 0.1611060909F, 0.1640084822F, + 0.1669324936F, 0.1698779549F, 0.1728446939F, 0.1758325362F, + 0.1788413055F, 0.1818708232F, 0.1849209084F, 0.1879913785F, + 0.1910820485F, 0.1941927312F, 0.1973232376F, 0.2004733764F, + 0.2036429541F, 0.2068317752F, 0.2100396421F, 0.2132663552F, + 0.2165117125F, 0.2197755102F, 0.2230575422F, 0.2263576007F, + 0.2296754753F, 0.2330109540F, 0.2363638225F, 0.2397338646F, + 0.2431208619F, 0.2465245941F, 0.2499448389F, 0.2533813719F, + 0.2568339669F, 0.2603023956F, 0.2637864277F, 0.2672858312F, + 0.2708003718F, 0.2743298135F, 0.2778739186F, 0.2814324472F, + 0.2850051576F, 0.2885918065F, 0.2921921485F, 0.2958059366F, + 0.2994329219F, 0.3030728538F, 0.3067254799F, 0.3103905462F, + 0.3140677969F, 0.3177569747F, 0.3214578205F, 0.3251700736F, + 0.3288934718F, 0.3326277513F, 0.3363726468F, 0.3401278914F, + 0.3438932168F, 0.3476683533F, 0.3514530297F, 0.3552469734F, + 0.3590499106F, 0.3628615659F, 0.3666816630F, 0.3705099239F, + 0.3743460698F, 0.3781898204F, 0.3820408945F, 0.3858990095F, + 0.3897638820F, 0.3936352274F, 0.3975127601F, 0.4013961936F, + 0.4052852405F, 0.4091796123F, 0.4130790198F, 0.4169831732F, + 0.4208917815F, 0.4248045534F, 0.4287211965F, 0.4326414181F, + 0.4365649248F, 0.4404914225F, 0.4444206167F, 0.4483522125F, + 0.4522859146F, 0.4562214270F, 0.4601584538F, 0.4640966984F, + 0.4680358644F, 0.4719756548F, 0.4759157726F, 0.4798559209F, + 0.4837958024F, 0.4877351199F, 0.4916735765F, 0.4956108751F, + 0.4995467188F, 0.5034808109F, 0.5074128550F, 0.5113425550F, + 0.5152696149F, 0.5191937395F, 0.5231146336F, 0.5270320028F, + 0.5309455530F, 0.5348549910F, 0.5387600239F, 0.5426603597F, + 0.5465557070F, 0.5504457754F, 0.5543302752F, 0.5582089175F, + 0.5620814145F, 0.5659474793F, 0.5698068262F, 0.5736591704F, + 0.5775042283F, 0.5813417176F, 0.5851713571F, 0.5889928670F, + 0.5928059689F, 0.5966103856F, 0.6004058415F, 0.6041920626F, + 0.6079687761F, 0.6117357113F, 0.6154925986F, 0.6192391705F, + 0.6229751612F, 0.6267003064F, 0.6304143441F, 0.6341170137F, + 0.6378080569F, 0.6414872173F, 0.6451542405F, 0.6488088741F, + 0.6524508681F, 0.6560799742F, 0.6596959469F, 0.6632985424F, + 0.6668875197F, 0.6704626398F, 0.6740236662F, 0.6775703649F, + 0.6811025043F, 0.6846198554F, 0.6881221916F, 0.6916092892F, + 0.6950809269F, 0.6985368861F, 0.7019769510F, 0.7054009085F, + 0.7088085484F, 0.7121996632F, 0.7155740484F, 0.7189315023F, + 0.7222718263F, 0.7255948245F, 0.7289003043F, 0.7321880760F, + 0.7354579530F, 0.7387097518F, 0.7419432921F, 0.7451583966F, + 0.7483548915F, 0.7515326059F, 0.7546913723F, 0.7578310265F, + 0.7609514077F, 0.7640523581F, 0.7671337237F, 0.7701953535F, + 0.7732371001F, 0.7762588195F, 0.7792603711F, 0.7822416178F, + 0.7852024259F, 0.7881426654F, 0.7910622097F, 0.7939609356F, + 0.7968387237F, 0.7996954579F, 0.8025310261F, 0.8053453193F, + 0.8081382324F, 0.8109096638F, 0.8136595156F, 0.8163876936F, + 0.8190941071F, 0.8217786690F, 0.8244412960F, 0.8270819086F, + 0.8297004305F, 0.8322967896F, 0.8348709171F, 0.8374227481F, + 0.8399522213F, 0.8424592789F, 0.8449438672F, 0.8474059356F, + 0.8498454378F, 0.8522623306F, 0.8546565748F, 0.8570281348F, + 0.8593769787F, 0.8617030779F, 0.8640064080F, 0.8662869477F, + 0.8685446796F, 0.8707795899F, 0.8729916682F, 0.8751809079F, + 0.8773473059F, 0.8794908626F, 0.8816115819F, 0.8837094713F, + 0.8857845418F, 0.8878368079F, 0.8898662874F, 0.8918730019F, + 0.8938569760F, 0.8958182380F, 0.8977568194F, 0.8996727552F, + 0.9015660837F, 0.9034368465F, 0.9052850885F, 0.9071108577F, + 0.9089142057F, 0.9106951869F, 0.9124538591F, 0.9141902832F, + 0.9159045233F, 0.9175966464F, 0.9192667228F, 0.9209148257F, + 0.9225410313F, 0.9241454187F, 0.9257280701F, 0.9272890704F, + 0.9288285075F, 0.9303464720F, 0.9318430576F, 0.9333183603F, + 0.9347724792F, 0.9362055158F, 0.9376175745F, 0.9390087622F, + 0.9403791881F, 0.9417289644F, 0.9430582055F, 0.9443670283F, + 0.9456555521F, 0.9469238986F, 0.9481721917F, 0.9494005577F, + 0.9506091252F, 0.9517980248F, 0.9529673894F, 0.9541173540F, + 0.9552480557F, 0.9563596334F, 0.9574522282F, 0.9585259830F, + 0.9595810428F, 0.9606175542F, 0.9616356656F, 0.9626355274F, + 0.9636172915F, 0.9645811114F, 0.9655271425F, 0.9664555414F, + 0.9673664664F, 0.9682600774F, 0.9691365355F, 0.9699960034F, + 0.9708386448F, 0.9716646250F, 0.9724741103F, 0.9732672685F, + 0.9740442683F, 0.9748052795F, 0.9755504729F, 0.9762800205F, + 0.9769940950F, 0.9776928703F, 0.9783765210F, 0.9790452223F, + 0.9796991504F, 0.9803384823F, 0.9809633954F, 0.9815740679F, + 0.9821706784F, 0.9827534063F, 0.9833224312F, 0.9838779332F, + 0.9844200928F, 0.9849490910F, 0.9854651087F, 0.9859683274F, + 0.9864589286F, 0.9869370940F, 0.9874030054F, 0.9878568447F, + 0.9882987937F, 0.9887290343F, 0.9891477481F, 0.9895551169F, + 0.9899513220F, 0.9903365446F, 0.9907109658F, 0.9910747662F, + 0.9914281260F, 0.9917712252F, 0.9921042433F, 0.9924273593F, + 0.9927407516F, 0.9930445982F, 0.9933390763F, 0.9936243626F, + 0.9939006331F, 0.9941680631F, 0.9944268269F, 0.9946770982F, + 0.9949190498F, 0.9951528537F, 0.9953786808F, 0.9955967011F, + 0.9958070836F, 0.9960099963F, 0.9962056061F, 0.9963940787F, + 0.9965755786F, 0.9967502693F, 0.9969183129F, 0.9970798704F, + 0.9972351013F, 0.9973841640F, 0.9975272151F, 0.9976644103F, + 0.9977959036F, 0.9979218476F, 0.9980423932F, 0.9981576901F, + 0.9982678862F, 0.9983731278F, 0.9984735596F, 0.9985693247F, + 0.9986605645F, 0.9987474186F, 0.9988300248F, 0.9989085193F, + 0.9989830364F, 0.9990537085F, 0.9991206662F, 0.9991840382F, + 0.9992439513F, 0.9993005303F, 0.9993538982F, 0.9994041757F, + 0.9994514817F, 0.9994959330F, 0.9995376444F, 0.9995767286F, + 0.9996132960F, 0.9996474550F, 0.9996793121F, 0.9997089710F, + 0.9997365339F, 0.9997621003F, 0.9997857677F, 0.9998076311F, + 0.9998277836F, 0.9998463156F, 0.9998633155F, 0.9998788692F, + 0.9998930603F, 0.9999059701F, 0.9999176774F, 0.9999282586F, + 0.9999377880F, 0.9999463370F, 0.9999539749F, 0.9999607685F, + 0.9999667820F, 0.9999720773F, 0.9999767136F, 0.9999807479F, + 0.9999842344F, 0.9999872249F, 0.9999897688F, 0.9999919127F, + 0.9999937009F, 0.9999951749F, 0.9999963738F, 0.9999973342F, + 0.9999980900F, 0.9999986724F, 0.9999991103F, 0.9999994297F, + 0.9999996543F, 0.9999998049F, 0.9999999000F, 0.9999999552F, + 0.9999999836F, 0.9999999957F, 0.9999999994F, 1.0000000000F, +}; + +DECLARE_ALIGNED(16, static const float, vwin2048)[1024] = { + 0.0000009241F, 0.0000083165F, 0.0000231014F, 0.0000452785F, + 0.0000748476F, 0.0001118085F, 0.0001561608F, 0.0002079041F, + 0.0002670379F, 0.0003335617F, 0.0004074748F, 0.0004887765F, + 0.0005774661F, 0.0006735427F, 0.0007770054F, 0.0008878533F, + 0.0010060853F, 0.0011317002F, 0.0012646969F, 0.0014050742F, + 0.0015528307F, 0.0017079650F, 0.0018704756F, 0.0020403610F, + 0.0022176196F, 0.0024022497F, 0.0025942495F, 0.0027936173F, + 0.0030003511F, 0.0032144490F, 0.0034359088F, 0.0036647286F, + 0.0039009061F, 0.0041444391F, 0.0043953253F, 0.0046535621F, + 0.0049191472F, 0.0051920781F, 0.0054723520F, 0.0057599664F, + 0.0060549184F, 0.0063572052F, 0.0066668239F, 0.0069837715F, + 0.0073080449F, 0.0076396410F, 0.0079785566F, 0.0083247884F, + 0.0086783330F, 0.0090391871F, 0.0094073470F, 0.0097828092F, + 0.0101655700F, 0.0105556258F, 0.0109529726F, 0.0113576065F, + 0.0117695237F, 0.0121887200F, 0.0126151913F, 0.0130489335F, + 0.0134899422F, 0.0139382130F, 0.0143937415F, 0.0148565233F, + 0.0153265536F, 0.0158038279F, 0.0162883413F, 0.0167800889F, + 0.0172790660F, 0.0177852675F, 0.0182986882F, 0.0188193231F, + 0.0193471668F, 0.0198822141F, 0.0204244594F, 0.0209738974F, + 0.0215305225F, 0.0220943289F, 0.0226653109F, 0.0232434627F, + 0.0238287784F, 0.0244212519F, 0.0250208772F, 0.0256276481F, + 0.0262415582F, 0.0268626014F, 0.0274907711F, 0.0281260608F, + 0.0287684638F, 0.0294179736F, 0.0300745833F, 0.0307382859F, + 0.0314090747F, 0.0320869424F, 0.0327718819F, 0.0334638860F, + 0.0341629474F, 0.0348690586F, 0.0355822122F, 0.0363024004F, + 0.0370296157F, 0.0377638502F, 0.0385050960F, 0.0392533451F, + 0.0400085896F, 0.0407708211F, 0.0415400315F, 0.0423162123F, + 0.0430993552F, 0.0438894515F, 0.0446864926F, 0.0454904698F, + 0.0463013742F, 0.0471191969F, 0.0479439288F, 0.0487755607F, + 0.0496140836F, 0.0504594879F, 0.0513117642F, 0.0521709031F, + 0.0530368949F, 0.0539097297F, 0.0547893979F, 0.0556758894F, + 0.0565691941F, 0.0574693019F, 0.0583762026F, 0.0592898858F, + 0.0602103410F, 0.0611375576F, 0.0620715250F, 0.0630122324F, + 0.0639596688F, 0.0649138234F, 0.0658746848F, 0.0668422421F, + 0.0678164838F, 0.0687973985F, 0.0697849746F, 0.0707792005F, + 0.0717800645F, 0.0727875547F, 0.0738016591F, 0.0748223656F, + 0.0758496620F, 0.0768835359F, 0.0779239751F, 0.0789709668F, + 0.0800244985F, 0.0810845574F, 0.0821511306F, 0.0832242052F, + 0.0843037679F, 0.0853898056F, 0.0864823050F, 0.0875812525F, + 0.0886866347F, 0.0897984378F, 0.0909166480F, 0.0920412513F, + 0.0931722338F, 0.0943095813F, 0.0954532795F, 0.0966033140F, + 0.0977596702F, 0.0989223336F, 0.1000912894F, 0.1012665227F, + 0.1024480185F, 0.1036357616F, 0.1048297369F, 0.1060299290F, + 0.1072363224F, 0.1084489014F, 0.1096676504F, 0.1108925534F, + 0.1121235946F, 0.1133607577F, 0.1146040267F, 0.1158533850F, + 0.1171088163F, 0.1183703040F, 0.1196378312F, 0.1209113812F, + 0.1221909370F, 0.1234764815F, 0.1247679974F, 0.1260654674F, + 0.1273688740F, 0.1286781995F, 0.1299934263F, 0.1313145365F, + 0.1326415121F, 0.1339743349F, 0.1353129866F, 0.1366574490F, + 0.1380077035F, 0.1393637315F, 0.1407255141F, 0.1420930325F, + 0.1434662677F, 0.1448452004F, 0.1462298115F, 0.1476200814F, + 0.1490159906F, 0.1504175195F, 0.1518246482F, 0.1532373569F, + 0.1546556253F, 0.1560794333F, 0.1575087606F, 0.1589435866F, + 0.1603838909F, 0.1618296526F, 0.1632808509F, 0.1647374648F, + 0.1661994731F, 0.1676668546F, 0.1691395880F, 0.1706176516F, + 0.1721010238F, 0.1735896829F, 0.1750836068F, 0.1765827736F, + 0.1780871610F, 0.1795967468F, 0.1811115084F, 0.1826314234F, + 0.1841564689F, 0.1856866221F, 0.1872218600F, 0.1887621595F, + 0.1903074974F, 0.1918578503F, 0.1934131947F, 0.1949735068F, + 0.1965387630F, 0.1981089393F, 0.1996840117F, 0.2012639560F, + 0.2028487479F, 0.2044383630F, 0.2060327766F, 0.2076319642F, + 0.2092359007F, 0.2108445614F, 0.2124579211F, 0.2140759545F, + 0.2156986364F, 0.2173259411F, 0.2189578432F, 0.2205943168F, + 0.2222353361F, 0.2238808751F, 0.2255309076F, 0.2271854073F, + 0.2288443480F, 0.2305077030F, 0.2321754457F, 0.2338475493F, + 0.2355239869F, 0.2372047315F, 0.2388897560F, 0.2405790329F, + 0.2422725350F, 0.2439702347F, 0.2456721043F, 0.2473781159F, + 0.2490882418F, 0.2508024539F, 0.2525207240F, 0.2542430237F, + 0.2559693248F, 0.2576995986F, 0.2594338166F, 0.2611719498F, + 0.2629139695F, 0.2646598466F, 0.2664095520F, 0.2681630564F, + 0.2699203304F, 0.2716813445F, 0.2734460691F, 0.2752144744F, + 0.2769865307F, 0.2787622079F, 0.2805414760F, 0.2823243047F, + 0.2841106637F, 0.2859005227F, 0.2876938509F, 0.2894906179F, + 0.2912907928F, 0.2930943447F, 0.2949012426F, 0.2967114554F, + 0.2985249520F, 0.3003417009F, 0.3021616708F, 0.3039848301F, + 0.3058111471F, 0.3076405901F, 0.3094731273F, 0.3113087266F, + 0.3131473560F, 0.3149889833F, 0.3168335762F, 0.3186811024F, + 0.3205315294F, 0.3223848245F, 0.3242409552F, 0.3260998886F, + 0.3279615918F, 0.3298260319F, 0.3316931758F, 0.3335629903F, + 0.3354354423F, 0.3373104982F, 0.3391881247F, 0.3410682882F, + 0.3429509551F, 0.3448360917F, 0.3467236642F, 0.3486136387F, + 0.3505059811F, 0.3524006575F, 0.3542976336F, 0.3561968753F, + 0.3580983482F, 0.3600020179F, 0.3619078499F, 0.3638158096F, + 0.3657258625F, 0.3676379737F, 0.3695521086F, 0.3714682321F, + 0.3733863094F, 0.3753063055F, 0.3772281852F, 0.3791519134F, + 0.3810774548F, 0.3830047742F, 0.3849338362F, 0.3868646053F, + 0.3887970459F, 0.3907311227F, 0.3926667998F, 0.3946040417F, + 0.3965428125F, 0.3984830765F, 0.4004247978F, 0.4023679403F, + 0.4043124683F, 0.4062583455F, 0.4082055359F, 0.4101540034F, + 0.4121037117F, 0.4140546246F, 0.4160067058F, 0.4179599190F, + 0.4199142277F, 0.4218695956F, 0.4238259861F, 0.4257833627F, + 0.4277416888F, 0.4297009279F, 0.4316610433F, 0.4336219983F, + 0.4355837562F, 0.4375462803F, 0.4395095337F, 0.4414734797F, + 0.4434380815F, 0.4454033021F, 0.4473691046F, 0.4493354521F, + 0.4513023078F, 0.4532696345F, 0.4552373954F, 0.4572055533F, + 0.4591740713F, 0.4611429123F, 0.4631120393F, 0.4650814151F, + 0.4670510028F, 0.4690207650F, 0.4709906649F, 0.4729606651F, + 0.4749307287F, 0.4769008185F, 0.4788708972F, 0.4808409279F, + 0.4828108732F, 0.4847806962F, 0.4867503597F, 0.4887198264F, + 0.4906890593F, 0.4926580213F, 0.4946266753F, 0.4965949840F, + 0.4985629105F, 0.5005304176F, 0.5024974683F, 0.5044640255F, + 0.5064300522F, 0.5083955114F, 0.5103603659F, 0.5123245790F, + 0.5142881136F, 0.5162509328F, 0.5182129997F, 0.5201742774F, + 0.5221347290F, 0.5240943178F, 0.5260530070F, 0.5280107598F, + 0.5299675395F, 0.5319233095F, 0.5338780330F, 0.5358316736F, + 0.5377841946F, 0.5397355596F, 0.5416857320F, 0.5436346755F, + 0.5455823538F, 0.5475287304F, 0.5494737691F, 0.5514174337F, + 0.5533596881F, 0.5553004962F, 0.5572398218F, 0.5591776291F, + 0.5611138821F, 0.5630485449F, 0.5649815818F, 0.5669129570F, + 0.5688426349F, 0.5707705799F, 0.5726967564F, 0.5746211290F, + 0.5765436624F, 0.5784643212F, 0.5803830702F, 0.5822998743F, + 0.5842146984F, 0.5861275076F, 0.5880382669F, 0.5899469416F, + 0.5918534968F, 0.5937578981F, 0.5956601107F, 0.5975601004F, + 0.5994578326F, 0.6013532732F, 0.6032463880F, 0.6051371429F, + 0.6070255039F, 0.6089114372F, 0.6107949090F, 0.6126758856F, + 0.6145543334F, 0.6164302191F, 0.6183035092F, 0.6201741706F, + 0.6220421700F, 0.6239074745F, 0.6257700513F, 0.6276298674F, + 0.6294868903F, 0.6313410873F, 0.6331924262F, 0.6350408745F, + 0.6368864001F, 0.6387289710F, 0.6405685552F, 0.6424051209F, + 0.6442386364F, 0.6460690702F, 0.6478963910F, 0.6497205673F, + 0.6515415682F, 0.6533593625F, 0.6551739194F, 0.6569852082F, + 0.6587931984F, 0.6605978593F, 0.6623991609F, 0.6641970728F, + 0.6659915652F, 0.6677826081F, 0.6695701718F, 0.6713542268F, + 0.6731347437F, 0.6749116932F, 0.6766850461F, 0.6784547736F, + 0.6802208469F, 0.6819832374F, 0.6837419164F, 0.6854968559F, + 0.6872480275F, 0.6889954034F, 0.6907389556F, 0.6924786566F, + 0.6942144788F, 0.6959463950F, 0.6976743780F, 0.6993984008F, + 0.7011184365F, 0.7028344587F, 0.7045464407F, 0.7062543564F, + 0.7079581796F, 0.7096578844F, 0.7113534450F, 0.7130448359F, + 0.7147320316F, 0.7164150070F, 0.7180937371F, 0.7197681970F, + 0.7214383620F, 0.7231042077F, 0.7247657098F, 0.7264228443F, + 0.7280755871F, 0.7297239147F, 0.7313678035F, 0.7330072301F, + 0.7346421715F, 0.7362726046F, 0.7378985069F, 0.7395198556F, + 0.7411366285F, 0.7427488034F, 0.7443563584F, 0.7459592717F, + 0.7475575218F, 0.7491510873F, 0.7507399471F, 0.7523240803F, + 0.7539034661F, 0.7554780839F, 0.7570479136F, 0.7586129349F, + 0.7601731279F, 0.7617284730F, 0.7632789506F, 0.7648245416F, + 0.7663652267F, 0.7679009872F, 0.7694318044F, 0.7709576599F, + 0.7724785354F, 0.7739944130F, 0.7755052749F, 0.7770111035F, + 0.7785118815F, 0.7800075916F, 0.7814982170F, 0.7829837410F, + 0.7844641472F, 0.7859394191F, 0.7874095408F, 0.7888744965F, + 0.7903342706F, 0.7917888476F, 0.7932382124F, 0.7946823501F, + 0.7961212460F, 0.7975548855F, 0.7989832544F, 0.8004063386F, + 0.8018241244F, 0.8032365981F, 0.8046437463F, 0.8060455560F, + 0.8074420141F, 0.8088331080F, 0.8102188253F, 0.8115991536F, + 0.8129740810F, 0.8143435957F, 0.8157076861F, 0.8170663409F, + 0.8184195489F, 0.8197672994F, 0.8211095817F, 0.8224463853F, + 0.8237777001F, 0.8251035161F, 0.8264238235F, 0.8277386129F, + 0.8290478750F, 0.8303516008F, 0.8316497814F, 0.8329424083F, + 0.8342294731F, 0.8355109677F, 0.8367868841F, 0.8380572148F, + 0.8393219523F, 0.8405810893F, 0.8418346190F, 0.8430825345F, + 0.8443248294F, 0.8455614974F, 0.8467925323F, 0.8480179285F, + 0.8492376802F, 0.8504517822F, 0.8516602292F, 0.8528630164F, + 0.8540601391F, 0.8552515928F, 0.8564373733F, 0.8576174766F, + 0.8587918990F, 0.8599606368F, 0.8611236868F, 0.8622810460F, + 0.8634327113F, 0.8645786802F, 0.8657189504F, 0.8668535195F, + 0.8679823857F, 0.8691055472F, 0.8702230025F, 0.8713347503F, + 0.8724407896F, 0.8735411194F, 0.8746357394F, 0.8757246489F, + 0.8768078479F, 0.8778853364F, 0.8789571146F, 0.8800231832F, + 0.8810835427F, 0.8821381942F, 0.8831871387F, 0.8842303777F, + 0.8852679127F, 0.8862997456F, 0.8873258784F, 0.8883463132F, + 0.8893610527F, 0.8903700994F, 0.8913734562F, 0.8923711263F, + 0.8933631129F, 0.8943494196F, 0.8953300500F, 0.8963050083F, + 0.8972742985F, 0.8982379249F, 0.8991958922F, 0.9001482052F, + 0.9010948688F, 0.9020358883F, 0.9029712690F, 0.9039010165F, + 0.9048251367F, 0.9057436357F, 0.9066565195F, 0.9075637946F, + 0.9084654678F, 0.9093615456F, 0.9102520353F, 0.9111369440F, + 0.9120162792F, 0.9128900484F, 0.9137582595F, 0.9146209204F, + 0.9154780394F, 0.9163296248F, 0.9171756853F, 0.9180162296F, + 0.9188512667F, 0.9196808057F, 0.9205048559F, 0.9213234270F, + 0.9221365285F, 0.9229441704F, 0.9237463629F, 0.9245431160F, + 0.9253344404F, 0.9261203465F, 0.9269008453F, 0.9276759477F, + 0.9284456648F, 0.9292100080F, 0.9299689889F, 0.9307226190F, + 0.9314709103F, 0.9322138747F, 0.9329515245F, 0.9336838721F, + 0.9344109300F, 0.9351327108F, 0.9358492275F, 0.9365604931F, + 0.9372665208F, 0.9379673239F, 0.9386629160F, 0.9393533107F, + 0.9400385220F, 0.9407185637F, 0.9413934501F, 0.9420631954F, + 0.9427278141F, 0.9433873208F, 0.9440417304F, 0.9446910576F, + 0.9453353176F, 0.9459745255F, 0.9466086968F, 0.9472378469F, + 0.9478619915F, 0.9484811463F, 0.9490953274F, 0.9497045506F, + 0.9503088323F, 0.9509081888F, 0.9515026365F, 0.9520921921F, + 0.9526768723F, 0.9532566940F, 0.9538316742F, 0.9544018300F, + 0.9549671786F, 0.9555277375F, 0.9560835241F, 0.9566345562F, + 0.9571808513F, 0.9577224275F, 0.9582593027F, 0.9587914949F, + 0.9593190225F, 0.9598419038F, 0.9603601571F, 0.9608738012F, + 0.9613828546F, 0.9618873361F, 0.9623872646F, 0.9628826591F, + 0.9633735388F, 0.9638599227F, 0.9643418303F, 0.9648192808F, + 0.9652922939F, 0.9657608890F, 0.9662250860F, 0.9666849046F, + 0.9671403646F, 0.9675914861F, 0.9680382891F, 0.9684807937F, + 0.9689190202F, 0.9693529890F, 0.9697827203F, 0.9702082347F, + 0.9706295529F, 0.9710466953F, 0.9714596828F, 0.9718685362F, + 0.9722732762F, 0.9726739240F, 0.9730705005F, 0.9734630267F, + 0.9738515239F, 0.9742360134F, 0.9746165163F, 0.9749930540F, + 0.9753656481F, 0.9757343198F, 0.9760990909F, 0.9764599829F, + 0.9768170175F, 0.9771702164F, 0.9775196013F, 0.9778651941F, + 0.9782070167F, 0.9785450909F, 0.9788794388F, 0.9792100824F, + 0.9795370437F, 0.9798603449F, 0.9801800080F, 0.9804960554F, + 0.9808085092F, 0.9811173916F, 0.9814227251F, 0.9817245318F, + 0.9820228343F, 0.9823176549F, 0.9826090160F, 0.9828969402F, + 0.9831814498F, 0.9834625674F, 0.9837403156F, 0.9840147169F, + 0.9842857939F, 0.9845535692F, 0.9848180654F, 0.9850793052F, + 0.9853373113F, 0.9855921062F, 0.9858437127F, 0.9860921535F, + 0.9863374512F, 0.9865796287F, 0.9868187085F, 0.9870547136F, + 0.9872876664F, 0.9875175899F, 0.9877445067F, 0.9879684396F, + 0.9881894112F, 0.9884074444F, 0.9886225619F, 0.9888347863F, + 0.9890441404F, 0.9892506468F, 0.9894543284F, 0.9896552077F, + 0.9898533074F, 0.9900486502F, 0.9902412587F, 0.9904311555F, + 0.9906183633F, 0.9908029045F, 0.9909848019F, 0.9911640779F, + 0.9913407550F, 0.9915148557F, 0.9916864025F, 0.9918554179F, + 0.9920219241F, 0.9921859437F, 0.9923474989F, 0.9925066120F, + 0.9926633054F, 0.9928176012F, 0.9929695218F, 0.9931190891F, + 0.9932663254F, 0.9934112527F, 0.9935538932F, 0.9936942686F, + 0.9938324012F, 0.9939683126F, 0.9941020248F, 0.9942335597F, + 0.9943629388F, 0.9944901841F, 0.9946153170F, 0.9947383593F, + 0.9948593325F, 0.9949782579F, 0.9950951572F, 0.9952100516F, + 0.9953229625F, 0.9954339111F, 0.9955429186F, 0.9956500062F, + 0.9957551948F, 0.9958585056F, 0.9959599593F, 0.9960595769F, + 0.9961573792F, 0.9962533869F, 0.9963476206F, 0.9964401009F, + 0.9965308483F, 0.9966198833F, 0.9967072261F, 0.9967928971F, + 0.9968769164F, 0.9969593041F, 0.9970400804F, 0.9971192651F, + 0.9971968781F, 0.9972729391F, 0.9973474680F, 0.9974204842F, + 0.9974920074F, 0.9975620569F, 0.9976306521F, 0.9976978122F, + 0.9977635565F, 0.9978279039F, 0.9978908736F, 0.9979524842F, + 0.9980127547F, 0.9980717037F, 0.9981293499F, 0.9981857116F, + 0.9982408073F, 0.9982946554F, 0.9983472739F, 0.9983986810F, + 0.9984488947F, 0.9984979328F, 0.9985458132F, 0.9985925534F, + 0.9986381711F, 0.9986826838F, 0.9987261086F, 0.9987684630F, + 0.9988097640F, 0.9988500286F, 0.9988892738F, 0.9989275163F, + 0.9989647727F, 0.9990010597F, 0.9990363938F, 0.9990707911F, + 0.9991042679F, 0.9991368404F, 0.9991685244F, 0.9991993358F, + 0.9992292905F, 0.9992584038F, 0.9992866914F, 0.9993141686F, + 0.9993408506F, 0.9993667526F, 0.9993918895F, 0.9994162761F, + 0.9994399273F, 0.9994628576F, 0.9994850815F, 0.9995066133F, + 0.9995274672F, 0.9995476574F, 0.9995671978F, 0.9995861021F, + 0.9996043841F, 0.9996220573F, 0.9996391352F, 0.9996556310F, + 0.9996715579F, 0.9996869288F, 0.9997017568F, 0.9997160543F, + 0.9997298342F, 0.9997431088F, 0.9997558905F, 0.9997681914F, + 0.9997800236F, 0.9997913990F, 0.9998023292F, 0.9998128261F, + 0.9998229009F, 0.9998325650F, 0.9998418296F, 0.9998507058F, + 0.9998592044F, 0.9998673362F, 0.9998751117F, 0.9998825415F, + 0.9998896358F, 0.9998964047F, 0.9999028584F, 0.9999090066F, + 0.9999148590F, 0.9999204253F, 0.9999257148F, 0.9999307368F, + 0.9999355003F, 0.9999400144F, 0.9999442878F, 0.9999483293F, + 0.9999521472F, 0.9999557499F, 0.9999591457F, 0.9999623426F, + 0.9999653483F, 0.9999681708F, 0.9999708175F, 0.9999732959F, + 0.9999756132F, 0.9999777765F, 0.9999797928F, 0.9999816688F, + 0.9999834113F, 0.9999850266F, 0.9999865211F, 0.9999879009F, + 0.9999891721F, 0.9999903405F, 0.9999914118F, 0.9999923914F, + 0.9999932849F, 0.9999940972F, 0.9999948336F, 0.9999954989F, + 0.9999960978F, 0.9999966349F, 0.9999971146F, 0.9999975411F, + 0.9999979185F, 0.9999982507F, 0.9999985414F, 0.9999987944F, + 0.9999990129F, 0.9999992003F, 0.9999993596F, 0.9999994939F, + 0.9999996059F, 0.9999996981F, 0.9999997732F, 0.9999998333F, + 0.9999998805F, 0.9999999170F, 0.9999999444F, 0.9999999643F, + 0.9999999784F, 0.9999999878F, 0.9999999937F, 0.9999999972F, + 0.9999999990F, 0.9999999997F, 1.0000000000F, 1.0000000000F, +}; + +DECLARE_ALIGNED(16, static const float, vwin4096)[2048] = { + 0.0000002310F, 0.0000020791F, 0.0000057754F, 0.0000113197F, + 0.0000187121F, 0.0000279526F, 0.0000390412F, 0.0000519777F, + 0.0000667623F, 0.0000833949F, 0.0001018753F, 0.0001222036F, + 0.0001443798F, 0.0001684037F, 0.0001942754F, 0.0002219947F, + 0.0002515616F, 0.0002829761F, 0.0003162380F, 0.0003513472F, + 0.0003883038F, 0.0004271076F, 0.0004677584F, 0.0005102563F, + 0.0005546011F, 0.0006007928F, 0.0006488311F, 0.0006987160F, + 0.0007504474F, 0.0008040251F, 0.0008594490F, 0.0009167191F, + 0.0009758351F, 0.0010367969F, 0.0010996044F, 0.0011642574F, + 0.0012307558F, 0.0012990994F, 0.0013692880F, 0.0014413216F, + 0.0015151998F, 0.0015909226F, 0.0016684898F, 0.0017479011F, + 0.0018291565F, 0.0019122556F, 0.0019971983F, 0.0020839845F, + 0.0021726138F, 0.0022630861F, 0.0023554012F, 0.0024495588F, + 0.0025455588F, 0.0026434008F, 0.0027430847F, 0.0028446103F, + 0.0029479772F, 0.0030531853F, 0.0031602342F, 0.0032691238F, + 0.0033798538F, 0.0034924239F, 0.0036068338F, 0.0037230833F, + 0.0038411721F, 0.0039610999F, 0.0040828664F, 0.0042064714F, + 0.0043319145F, 0.0044591954F, 0.0045883139F, 0.0047192696F, + 0.0048520622F, 0.0049866914F, 0.0051231569F, 0.0052614583F, + 0.0054015953F, 0.0055435676F, 0.0056873748F, 0.0058330166F, + 0.0059804926F, 0.0061298026F, 0.0062809460F, 0.0064339226F, + 0.0065887320F, 0.0067453738F, 0.0069038476F, 0.0070641531F, + 0.0072262899F, 0.0073902575F, 0.0075560556F, 0.0077236838F, + 0.0078931417F, 0.0080644288F, 0.0082375447F, 0.0084124891F, + 0.0085892615F, 0.0087678614F, 0.0089482885F, 0.0091305422F, + 0.0093146223F, 0.0095005281F, 0.0096882592F, 0.0098778153F, + 0.0100691958F, 0.0102624002F, 0.0104574281F, 0.0106542791F, + 0.0108529525F, 0.0110534480F, 0.0112557651F, 0.0114599032F, + 0.0116658618F, 0.0118736405F, 0.0120832387F, 0.0122946560F, + 0.0125078917F, 0.0127229454F, 0.0129398166F, 0.0131585046F, + 0.0133790090F, 0.0136013292F, 0.0138254647F, 0.0140514149F, + 0.0142791792F, 0.0145087572F, 0.0147401481F, 0.0149733515F, + 0.0152083667F, 0.0154451932F, 0.0156838304F, 0.0159242777F, + 0.0161665345F, 0.0164106001F, 0.0166564741F, 0.0169041557F, + 0.0171536443F, 0.0174049393F, 0.0176580401F, 0.0179129461F, + 0.0181696565F, 0.0184281708F, 0.0186884883F, 0.0189506084F, + 0.0192145303F, 0.0194802535F, 0.0197477772F, 0.0200171008F, + 0.0202882236F, 0.0205611449F, 0.0208358639F, 0.0211123801F, + 0.0213906927F, 0.0216708011F, 0.0219527043F, 0.0222364019F, + 0.0225218930F, 0.0228091769F, 0.0230982529F, 0.0233891203F, + 0.0236817782F, 0.0239762259F, 0.0242724628F, 0.0245704880F, + 0.0248703007F, 0.0251719002F, 0.0254752858F, 0.0257804565F, + 0.0260874117F, 0.0263961506F, 0.0267066722F, 0.0270189760F, + 0.0273330609F, 0.0276489263F, 0.0279665712F, 0.0282859949F, + 0.0286071966F, 0.0289301753F, 0.0292549303F, 0.0295814607F, + 0.0299097656F, 0.0302398442F, 0.0305716957F, 0.0309053191F, + 0.0312407135F, 0.0315778782F, 0.0319168122F, 0.0322575145F, + 0.0325999844F, 0.0329442209F, 0.0332902231F, 0.0336379900F, + 0.0339875208F, 0.0343388146F, 0.0346918703F, 0.0350466871F, + 0.0354032640F, 0.0357616000F, 0.0361216943F, 0.0364835458F, + 0.0368471535F, 0.0372125166F, 0.0375796339F, 0.0379485046F, + 0.0383191276F, 0.0386915020F, 0.0390656267F, 0.0394415008F, + 0.0398191231F, 0.0401984927F, 0.0405796086F, 0.0409624698F, + 0.0413470751F, 0.0417334235F, 0.0421215141F, 0.0425113457F, + 0.0429029172F, 0.0432962277F, 0.0436912760F, 0.0440880610F, + 0.0444865817F, 0.0448868370F, 0.0452888257F, 0.0456925468F, + 0.0460979992F, 0.0465051816F, 0.0469140931F, 0.0473247325F, + 0.0477370986F, 0.0481511902F, 0.0485670064F, 0.0489845458F, + 0.0494038074F, 0.0498247899F, 0.0502474922F, 0.0506719131F, + 0.0510980514F, 0.0515259060F, 0.0519554756F, 0.0523867590F, + 0.0528197550F, 0.0532544624F, 0.0536908800F, 0.0541290066F, + 0.0545688408F, 0.0550103815F, 0.0554536274F, 0.0558985772F, + 0.0563452297F, 0.0567935837F, 0.0572436377F, 0.0576953907F, + 0.0581488412F, 0.0586039880F, 0.0590608297F, 0.0595193651F, + 0.0599795929F, 0.0604415117F, 0.0609051202F, 0.0613704170F, + 0.0618374009F, 0.0623060704F, 0.0627764243F, 0.0632484611F, + 0.0637221795F, 0.0641975781F, 0.0646746555F, 0.0651534104F, + 0.0656338413F, 0.0661159469F, 0.0665997257F, 0.0670851763F, + 0.0675722973F, 0.0680610873F, 0.0685515448F, 0.0690436684F, + 0.0695374567F, 0.0700329081F, 0.0705300213F, 0.0710287947F, + 0.0715292269F, 0.0720313163F, 0.0725350616F, 0.0730404612F, + 0.0735475136F, 0.0740562172F, 0.0745665707F, 0.0750785723F, + 0.0755922207F, 0.0761075143F, 0.0766244515F, 0.0771430307F, + 0.0776632505F, 0.0781851092F, 0.0787086052F, 0.0792337371F, + 0.0797605032F, 0.0802889018F, 0.0808189315F, 0.0813505905F, + 0.0818838773F, 0.0824187903F, 0.0829553277F, 0.0834934881F, + 0.0840332697F, 0.0845746708F, 0.0851176899F, 0.0856623252F, + 0.0862085751F, 0.0867564379F, 0.0873059119F, 0.0878569954F, + 0.0884096867F, 0.0889639840F, 0.0895198858F, 0.0900773902F, + 0.0906364955F, 0.0911972000F, 0.0917595019F, 0.0923233995F, + 0.0928888909F, 0.0934559745F, 0.0940246485F, 0.0945949110F, + 0.0951667604F, 0.0957401946F, 0.0963152121F, 0.0968918109F, + 0.0974699893F, 0.0980497454F, 0.0986310773F, 0.0992139832F, + 0.0997984614F, 0.1003845098F, 0.1009721267F, 0.1015613101F, + 0.1021520582F, 0.1027443692F, 0.1033382410F, 0.1039336718F, + 0.1045306597F, 0.1051292027F, 0.1057292990F, 0.1063309466F, + 0.1069341435F, 0.1075388878F, 0.1081451776F, 0.1087530108F, + 0.1093623856F, 0.1099732998F, 0.1105857516F, 0.1111997389F, + 0.1118152597F, 0.1124323121F, 0.1130508939F, 0.1136710032F, + 0.1142926379F, 0.1149157960F, 0.1155404755F, 0.1161666742F, + 0.1167943901F, 0.1174236211F, 0.1180543652F, 0.1186866202F, + 0.1193203841F, 0.1199556548F, 0.1205924300F, 0.1212307078F, + 0.1218704860F, 0.1225117624F, 0.1231545349F, 0.1237988013F, + 0.1244445596F, 0.1250918074F, 0.1257405427F, 0.1263907632F, + 0.1270424667F, 0.1276956512F, 0.1283503142F, 0.1290064537F, + 0.1296640674F, 0.1303231530F, 0.1309837084F, 0.1316457312F, + 0.1323092193F, 0.1329741703F, 0.1336405820F, 0.1343084520F, + 0.1349777782F, 0.1356485582F, 0.1363207897F, 0.1369944704F, + 0.1376695979F, 0.1383461700F, 0.1390241842F, 0.1397036384F, + 0.1403845300F, 0.1410668567F, 0.1417506162F, 0.1424358061F, + 0.1431224240F, 0.1438104674F, 0.1444999341F, 0.1451908216F, + 0.1458831274F, 0.1465768492F, 0.1472719844F, 0.1479685308F, + 0.1486664857F, 0.1493658468F, 0.1500666115F, 0.1507687775F, + 0.1514723422F, 0.1521773031F, 0.1528836577F, 0.1535914035F, + 0.1543005380F, 0.1550110587F, 0.1557229631F, 0.1564362485F, + 0.1571509124F, 0.1578669524F, 0.1585843657F, 0.1593031499F, + 0.1600233024F, 0.1607448205F, 0.1614677017F, 0.1621919433F, + 0.1629175428F, 0.1636444975F, 0.1643728047F, 0.1651024619F, + 0.1658334665F, 0.1665658156F, 0.1672995067F, 0.1680345371F, + 0.1687709041F, 0.1695086050F, 0.1702476372F, 0.1709879978F, + 0.1717296843F, 0.1724726938F, 0.1732170237F, 0.1739626711F, + 0.1747096335F, 0.1754579079F, 0.1762074916F, 0.1769583819F, + 0.1777105760F, 0.1784640710F, 0.1792188642F, 0.1799749529F, + 0.1807323340F, 0.1814910049F, 0.1822509628F, 0.1830122046F, + 0.1837747277F, 0.1845385292F, 0.1853036062F, 0.1860699558F, + 0.1868375751F, 0.1876064613F, 0.1883766114F, 0.1891480226F, + 0.1899206919F, 0.1906946164F, 0.1914697932F, 0.1922462194F, + 0.1930238919F, 0.1938028079F, 0.1945829643F, 0.1953643583F, + 0.1961469868F, 0.1969308468F, 0.1977159353F, 0.1985022494F, + 0.1992897859F, 0.2000785420F, 0.2008685145F, 0.2016597005F, + 0.2024520968F, 0.2032457005F, 0.2040405084F, 0.2048365175F, + 0.2056337247F, 0.2064321269F, 0.2072317211F, 0.2080325041F, + 0.2088344727F, 0.2096376240F, 0.2104419547F, 0.2112474618F, + 0.2120541420F, 0.2128619923F, 0.2136710094F, 0.2144811902F, + 0.2152925315F, 0.2161050301F, 0.2169186829F, 0.2177334866F, + 0.2185494381F, 0.2193665340F, 0.2201847712F, 0.2210041465F, + 0.2218246565F, 0.2226462981F, 0.2234690680F, 0.2242929629F, + 0.2251179796F, 0.2259441147F, 0.2267713650F, 0.2275997272F, + 0.2284291979F, 0.2292597739F, 0.2300914518F, 0.2309242283F, + 0.2317581001F, 0.2325930638F, 0.2334291160F, 0.2342662534F, + 0.2351044727F, 0.2359437703F, 0.2367841431F, 0.2376255875F, + 0.2384681001F, 0.2393116776F, 0.2401563165F, 0.2410020134F, + 0.2418487649F, 0.2426965675F, 0.2435454178F, 0.2443953122F, + 0.2452462474F, 0.2460982199F, 0.2469512262F, 0.2478052628F, + 0.2486603262F, 0.2495164129F, 0.2503735194F, 0.2512316421F, + 0.2520907776F, 0.2529509222F, 0.2538120726F, 0.2546742250F, + 0.2555373760F, 0.2564015219F, 0.2572666593F, 0.2581327845F, + 0.2589998939F, 0.2598679840F, 0.2607370510F, 0.2616070916F, + 0.2624781019F, 0.2633500783F, 0.2642230173F, 0.2650969152F, + 0.2659717684F, 0.2668475731F, 0.2677243257F, 0.2686020226F, + 0.2694806601F, 0.2703602344F, 0.2712407419F, 0.2721221789F, + 0.2730045417F, 0.2738878265F, 0.2747720297F, 0.2756571474F, + 0.2765431760F, 0.2774301117F, 0.2783179508F, 0.2792066895F, + 0.2800963240F, 0.2809868505F, 0.2818782654F, 0.2827705647F, + 0.2836637447F, 0.2845578016F, 0.2854527315F, 0.2863485307F, + 0.2872451953F, 0.2881427215F, 0.2890411055F, 0.2899403433F, + 0.2908404312F, 0.2917413654F, 0.2926431418F, 0.2935457567F, + 0.2944492061F, 0.2953534863F, 0.2962585932F, 0.2971645230F, + 0.2980712717F, 0.2989788356F, 0.2998872105F, 0.3007963927F, + 0.3017063781F, 0.3026171629F, 0.3035287430F, 0.3044411145F, + 0.3053542736F, 0.3062682161F, 0.3071829381F, 0.3080984356F, + 0.3090147047F, 0.3099317413F, 0.3108495414F, 0.3117681011F, + 0.3126874163F, 0.3136074830F, 0.3145282972F, 0.3154498548F, + 0.3163721517F, 0.3172951841F, 0.3182189477F, 0.3191434385F, + 0.3200686525F, 0.3209945856F, 0.3219212336F, 0.3228485927F, + 0.3237766585F, 0.3247054271F, 0.3256348943F, 0.3265650560F, + 0.3274959081F, 0.3284274465F, 0.3293596671F, 0.3302925657F, + 0.3312261382F, 0.3321603804F, 0.3330952882F, 0.3340308574F, + 0.3349670838F, 0.3359039634F, 0.3368414919F, 0.3377796651F, + 0.3387184789F, 0.3396579290F, 0.3405980113F, 0.3415387216F, + 0.3424800556F, 0.3434220091F, 0.3443645779F, 0.3453077578F, + 0.3462515446F, 0.3471959340F, 0.3481409217F, 0.3490865036F, + 0.3500326754F, 0.3509794328F, 0.3519267715F, 0.3528746873F, + 0.3538231759F, 0.3547722330F, 0.3557218544F, 0.3566720357F, + 0.3576227727F, 0.3585740610F, 0.3595258964F, 0.3604782745F, + 0.3614311910F, 0.3623846417F, 0.3633386221F, 0.3642931280F, + 0.3652481549F, 0.3662036987F, 0.3671597548F, 0.3681163191F, + 0.3690733870F, 0.3700309544F, 0.3709890167F, 0.3719475696F, + 0.3729066089F, 0.3738661299F, 0.3748261285F, 0.3757866002F, + 0.3767475406F, 0.3777089453F, 0.3786708100F, 0.3796331302F, + 0.3805959014F, 0.3815591194F, 0.3825227796F, 0.3834868777F, + 0.3844514093F, 0.3854163698F, 0.3863817549F, 0.3873475601F, + 0.3883137810F, 0.3892804131F, 0.3902474521F, 0.3912148933F, + 0.3921827325F, 0.3931509650F, 0.3941195865F, 0.3950885925F, + 0.3960579785F, 0.3970277400F, 0.3979978725F, 0.3989683716F, + 0.3999392328F, 0.4009104516F, 0.4018820234F, 0.4028539438F, + 0.4038262084F, 0.4047988125F, 0.4057717516F, 0.4067450214F, + 0.4077186172F, 0.4086925345F, 0.4096667688F, 0.4106413155F, + 0.4116161703F, 0.4125913284F, 0.4135667854F, 0.4145425368F, + 0.4155185780F, 0.4164949044F, 0.4174715116F, 0.4184483949F, + 0.4194255498F, 0.4204029718F, 0.4213806563F, 0.4223585987F, + 0.4233367946F, 0.4243152392F, 0.4252939281F, 0.4262728566F, + 0.4272520202F, 0.4282314144F, 0.4292110345F, 0.4301908760F, + 0.4311709343F, 0.4321512047F, 0.4331316828F, 0.4341123639F, + 0.4350932435F, 0.4360743168F, 0.4370555794F, 0.4380370267F, + 0.4390186540F, 0.4400004567F, 0.4409824303F, 0.4419645701F, + 0.4429468716F, 0.4439293300F, 0.4449119409F, 0.4458946996F, + 0.4468776014F, 0.4478606418F, 0.4488438162F, 0.4498271199F, + 0.4508105483F, 0.4517940967F, 0.4527777607F, 0.4537615355F, + 0.4547454165F, 0.4557293991F, 0.4567134786F, 0.4576976505F, + 0.4586819101F, 0.4596662527F, 0.4606506738F, 0.4616351687F, + 0.4626197328F, 0.4636043614F, 0.4645890499F, 0.4655737936F, + 0.4665585880F, 0.4675434284F, 0.4685283101F, 0.4695132286F, + 0.4704981791F, 0.4714831570F, 0.4724681577F, 0.4734531766F, + 0.4744382089F, 0.4754232501F, 0.4764082956F, 0.4773933406F, + 0.4783783806F, 0.4793634108F, 0.4803484267F, 0.4813334237F, + 0.4823183969F, 0.4833033419F, 0.4842882540F, 0.4852731285F, + 0.4862579608F, 0.4872427462F, 0.4882274802F, 0.4892121580F, + 0.4901967751F, 0.4911813267F, 0.4921658083F, 0.4931502151F, + 0.4941345427F, 0.4951187863F, 0.4961029412F, 0.4970870029F, + 0.4980709667F, 0.4990548280F, 0.5000385822F, 0.5010222245F, + 0.5020057505F, 0.5029891553F, 0.5039724345F, 0.5049555834F, + 0.5059385973F, 0.5069214716F, 0.5079042018F, 0.5088867831F, + 0.5098692110F, 0.5108514808F, 0.5118335879F, 0.5128155277F, + 0.5137972956F, 0.5147788869F, 0.5157602971F, 0.5167415215F, + 0.5177225555F, 0.5187033945F, 0.5196840339F, 0.5206644692F, + 0.5216446956F, 0.5226247086F, 0.5236045035F, 0.5245840759F, + 0.5255634211F, 0.5265425344F, 0.5275214114F, 0.5285000474F, + 0.5294784378F, 0.5304565781F, 0.5314344637F, 0.5324120899F, + 0.5333894522F, 0.5343665461F, 0.5353433670F, 0.5363199102F, + 0.5372961713F, 0.5382721457F, 0.5392478287F, 0.5402232159F, + 0.5411983027F, 0.5421730845F, 0.5431475569F, 0.5441217151F, + 0.5450955548F, 0.5460690714F, 0.5470422602F, 0.5480151169F, + 0.5489876368F, 0.5499598155F, 0.5509316484F, 0.5519031310F, + 0.5528742587F, 0.5538450271F, 0.5548154317F, 0.5557854680F, + 0.5567551314F, 0.5577244174F, 0.5586933216F, 0.5596618395F, + 0.5606299665F, 0.5615976983F, 0.5625650302F, 0.5635319580F, + 0.5644984770F, 0.5654645828F, 0.5664302709F, 0.5673955370F, + 0.5683603765F, 0.5693247850F, 0.5702887580F, 0.5712522912F, + 0.5722153800F, 0.5731780200F, 0.5741402069F, 0.5751019362F, + 0.5760632034F, 0.5770240042F, 0.5779843341F, 0.5789441889F, + 0.5799035639F, 0.5808624549F, 0.5818208575F, 0.5827787673F, + 0.5837361800F, 0.5846930910F, 0.5856494961F, 0.5866053910F, + 0.5875607712F, 0.5885156324F, 0.5894699703F, 0.5904237804F, + 0.5913770586F, 0.5923298004F, 0.5932820016F, 0.5942336578F, + 0.5951847646F, 0.5961353179F, 0.5970853132F, 0.5980347464F, + 0.5989836131F, 0.5999319090F, 0.6008796298F, 0.6018267713F, + 0.6027733292F, 0.6037192993F, 0.6046646773F, 0.6056094589F, + 0.6065536400F, 0.6074972162F, 0.6084401833F, 0.6093825372F, + 0.6103242736F, 0.6112653884F, 0.6122058772F, 0.6131457359F, + 0.6140849604F, 0.6150235464F, 0.6159614897F, 0.6168987862F, + 0.6178354318F, 0.6187714223F, 0.6197067535F, 0.6206414213F, + 0.6215754215F, 0.6225087501F, 0.6234414028F, 0.6243733757F, + 0.6253046646F, 0.6262352654F, 0.6271651739F, 0.6280943862F, + 0.6290228982F, 0.6299507057F, 0.6308778048F, 0.6318041913F, + 0.6327298612F, 0.6336548105F, 0.6345790352F, 0.6355025312F, + 0.6364252945F, 0.6373473211F, 0.6382686070F, 0.6391891483F, + 0.6401089409F, 0.6410279808F, 0.6419462642F, 0.6428637869F, + 0.6437805452F, 0.6446965350F, 0.6456117524F, 0.6465261935F, + 0.6474398544F, 0.6483527311F, 0.6492648197F, 0.6501761165F, + 0.6510866174F, 0.6519963186F, 0.6529052162F, 0.6538133064F, + 0.6547205854F, 0.6556270492F, 0.6565326941F, 0.6574375162F, + 0.6583415117F, 0.6592446769F, 0.6601470079F, 0.6610485009F, + 0.6619491521F, 0.6628489578F, 0.6637479143F, 0.6646460177F, + 0.6655432643F, 0.6664396505F, 0.6673351724F, 0.6682298264F, + 0.6691236087F, 0.6700165157F, 0.6709085436F, 0.6717996889F, + 0.6726899478F, 0.6735793167F, 0.6744677918F, 0.6753553697F, + 0.6762420466F, 0.6771278190F, 0.6780126832F, 0.6788966357F, + 0.6797796728F, 0.6806617909F, 0.6815429866F, 0.6824232562F, + 0.6833025961F, 0.6841810030F, 0.6850584731F, 0.6859350031F, + 0.6868105894F, 0.6876852284F, 0.6885589168F, 0.6894316510F, + 0.6903034275F, 0.6911742430F, 0.6920440939F, 0.6929129769F, + 0.6937808884F, 0.6946478251F, 0.6955137837F, 0.6963787606F, + 0.6972427525F, 0.6981057560F, 0.6989677678F, 0.6998287845F, + 0.7006888028F, 0.7015478194F, 0.7024058309F, 0.7032628340F, + 0.7041188254F, 0.7049738019F, 0.7058277601F, 0.7066806969F, + 0.7075326089F, 0.7083834929F, 0.7092333457F, 0.7100821640F, + 0.7109299447F, 0.7117766846F, 0.7126223804F, 0.7134670291F, + 0.7143106273F, 0.7151531721F, 0.7159946602F, 0.7168350885F, + 0.7176744539F, 0.7185127534F, 0.7193499837F, 0.7201861418F, + 0.7210212247F, 0.7218552293F, 0.7226881526F, 0.7235199914F, + 0.7243507428F, 0.7251804039F, 0.7260089715F, 0.7268364426F, + 0.7276628144F, 0.7284880839F, 0.7293122481F, 0.7301353040F, + 0.7309572487F, 0.7317780794F, 0.7325977930F, 0.7334163868F, + 0.7342338579F, 0.7350502033F, 0.7358654202F, 0.7366795059F, + 0.7374924573F, 0.7383042718F, 0.7391149465F, 0.7399244787F, + 0.7407328655F, 0.7415401041F, 0.7423461920F, 0.7431511261F, + 0.7439549040F, 0.7447575227F, 0.7455589797F, 0.7463592723F, + 0.7471583976F, 0.7479563532F, 0.7487531363F, 0.7495487443F, + 0.7503431745F, 0.7511364244F, 0.7519284913F, 0.7527193726F, + 0.7535090658F, 0.7542975683F, 0.7550848776F, 0.7558709910F, + 0.7566559062F, 0.7574396205F, 0.7582221314F, 0.7590034366F, + 0.7597835334F, 0.7605624194F, 0.7613400923F, 0.7621165495F, + 0.7628917886F, 0.7636658072F, 0.7644386030F, 0.7652101735F, + 0.7659805164F, 0.7667496292F, 0.7675175098F, 0.7682841556F, + 0.7690495645F, 0.7698137341F, 0.7705766622F, 0.7713383463F, + 0.7720987844F, 0.7728579741F, 0.7736159132F, 0.7743725994F, + 0.7751280306F, 0.7758822046F, 0.7766351192F, 0.7773867722F, + 0.7781371614F, 0.7788862848F, 0.7796341401F, 0.7803807253F, + 0.7811260383F, 0.7818700769F, 0.7826128392F, 0.7833543230F, + 0.7840945263F, 0.7848334471F, 0.7855710833F, 0.7863074330F, + 0.7870424941F, 0.7877762647F, 0.7885087428F, 0.7892399264F, + 0.7899698137F, 0.7906984026F, 0.7914256914F, 0.7921516780F, + 0.7928763607F, 0.7935997375F, 0.7943218065F, 0.7950425661F, + 0.7957620142F, 0.7964801492F, 0.7971969692F, 0.7979124724F, + 0.7986266570F, 0.7993395214F, 0.8000510638F, 0.8007612823F, + 0.8014701754F, 0.8021777413F, 0.8028839784F, 0.8035888849F, + 0.8042924592F, 0.8049946997F, 0.8056956048F, 0.8063951727F, + 0.8070934020F, 0.8077902910F, 0.8084858381F, 0.8091800419F, + 0.8098729007F, 0.8105644130F, 0.8112545774F, 0.8119433922F, + 0.8126308561F, 0.8133169676F, 0.8140017251F, 0.8146851272F, + 0.8153671726F, 0.8160478598F, 0.8167271874F, 0.8174051539F, + 0.8180817582F, 0.8187569986F, 0.8194308741F, 0.8201033831F, + 0.8207745244F, 0.8214442966F, 0.8221126986F, 0.8227797290F, + 0.8234453865F, 0.8241096700F, 0.8247725781F, 0.8254341097F, + 0.8260942636F, 0.8267530385F, 0.8274104334F, 0.8280664470F, + 0.8287210782F, 0.8293743259F, 0.8300261889F, 0.8306766662F, + 0.8313257566F, 0.8319734591F, 0.8326197727F, 0.8332646963F, + 0.8339082288F, 0.8345503692F, 0.8351911167F, 0.8358304700F, + 0.8364684284F, 0.8371049907F, 0.8377401562F, 0.8383739238F, + 0.8390062927F, 0.8396372618F, 0.8402668305F, 0.8408949977F, + 0.8415217626F, 0.8421471245F, 0.8427710823F, 0.8433936354F, + 0.8440147830F, 0.8446345242F, 0.8452528582F, 0.8458697844F, + 0.8464853020F, 0.8470994102F, 0.8477121084F, 0.8483233958F, + 0.8489332718F, 0.8495417356F, 0.8501487866F, 0.8507544243F, + 0.8513586479F, 0.8519614568F, 0.8525628505F, 0.8531628283F, + 0.8537613897F, 0.8543585341F, 0.8549542611F, 0.8555485699F, + 0.8561414603F, 0.8567329315F, 0.8573229832F, 0.8579116149F, + 0.8584988262F, 0.8590846165F, 0.8596689855F, 0.8602519327F, + 0.8608334577F, 0.8614135603F, 0.8619922399F, 0.8625694962F, + 0.8631453289F, 0.8637197377F, 0.8642927222F, 0.8648642821F, + 0.8654344172F, 0.8660031272F, 0.8665704118F, 0.8671362708F, + 0.8677007039F, 0.8682637109F, 0.8688252917F, 0.8693854460F, + 0.8699441737F, 0.8705014745F, 0.8710573485F, 0.8716117953F, + 0.8721648150F, 0.8727164073F, 0.8732665723F, 0.8738153098F, + 0.8743626197F, 0.8749085021F, 0.8754529569F, 0.8759959840F, + 0.8765375835F, 0.8770777553F, 0.8776164996F, 0.8781538162F, + 0.8786897054F, 0.8792241670F, 0.8797572013F, 0.8802888082F, + 0.8808189880F, 0.8813477407F, 0.8818750664F, 0.8824009653F, + 0.8829254375F, 0.8834484833F, 0.8839701028F, 0.8844902961F, + 0.8850090636F, 0.8855264054F, 0.8860423218F, 0.8865568131F, + 0.8870698794F, 0.8875815212F, 0.8880917386F, 0.8886005319F, + 0.8891079016F, 0.8896138479F, 0.8901183712F, 0.8906214719F, + 0.8911231503F, 0.8916234067F, 0.8921222417F, 0.8926196556F, + 0.8931156489F, 0.8936102219F, 0.8941033752F, 0.8945951092F, + 0.8950854244F, 0.8955743212F, 0.8960618003F, 0.8965478621F, + 0.8970325071F, 0.8975157359F, 0.8979975490F, 0.8984779471F, + 0.8989569307F, 0.8994345004F, 0.8999106568F, 0.9003854005F, + 0.9008587323F, 0.9013306526F, 0.9018011623F, 0.9022702619F, + 0.9027379521F, 0.9032042337F, 0.9036691074F, 0.9041325739F, + 0.9045946339F, 0.9050552882F, 0.9055145376F, 0.9059723828F, + 0.9064288246F, 0.9068838638F, 0.9073375013F, 0.9077897379F, + 0.9082405743F, 0.9086900115F, 0.9091380503F, 0.9095846917F, + 0.9100299364F, 0.9104737854F, 0.9109162397F, 0.9113573001F, + 0.9117969675F, 0.9122352430F, 0.9126721275F, 0.9131076219F, + 0.9135417273F, 0.9139744447F, 0.9144057750F, 0.9148357194F, + 0.9152642787F, 0.9156914542F, 0.9161172468F, 0.9165416576F, + 0.9169646877F, 0.9173863382F, 0.9178066102F, 0.9182255048F, + 0.9186430232F, 0.9190591665F, 0.9194739359F, 0.9198873324F, + 0.9202993574F, 0.9207100120F, 0.9211192973F, 0.9215272147F, + 0.9219337653F, 0.9223389504F, 0.9227427713F, 0.9231452290F, + 0.9235463251F, 0.9239460607F, 0.9243444371F, 0.9247414557F, + 0.9251371177F, 0.9255314245F, 0.9259243774F, 0.9263159778F, + 0.9267062270F, 0.9270951264F, 0.9274826774F, 0.9278688814F, + 0.9282537398F, 0.9286372540F, 0.9290194254F, 0.9294002555F, + 0.9297797458F, 0.9301578976F, 0.9305347125F, 0.9309101919F, + 0.9312843373F, 0.9316571503F, 0.9320286323F, 0.9323987849F, + 0.9327676097F, 0.9331351080F, 0.9335012816F, 0.9338661320F, + 0.9342296607F, 0.9345918694F, 0.9349527596F, 0.9353123330F, + 0.9356705911F, 0.9360275357F, 0.9363831683F, 0.9367374905F, + 0.9370905042F, 0.9374422108F, 0.9377926122F, 0.9381417099F, + 0.9384895057F, 0.9388360014F, 0.9391811985F, 0.9395250989F, + 0.9398677043F, 0.9402090165F, 0.9405490371F, 0.9408877680F, + 0.9412252110F, 0.9415613678F, 0.9418962402F, 0.9422298301F, + 0.9425621392F, 0.9428931695F, 0.9432229226F, 0.9435514005F, + 0.9438786050F, 0.9442045381F, 0.9445292014F, 0.9448525971F, + 0.9451747268F, 0.9454955926F, 0.9458151963F, 0.9461335399F, + 0.9464506253F, 0.9467664545F, 0.9470810293F, 0.9473943517F, + 0.9477064238F, 0.9480172474F, 0.9483268246F, 0.9486351573F, + 0.9489422475F, 0.9492480973F, 0.9495527087F, 0.9498560837F, + 0.9501582243F, 0.9504591325F, 0.9507588105F, 0.9510572603F, + 0.9513544839F, 0.9516504834F, 0.9519452609F, 0.9522388186F, + 0.9525311584F, 0.9528222826F, 0.9531121932F, 0.9534008923F, + 0.9536883821F, 0.9539746647F, 0.9542597424F, 0.9545436171F, + 0.9548262912F, 0.9551077667F, 0.9553880459F, 0.9556671309F, + 0.9559450239F, 0.9562217272F, 0.9564972429F, 0.9567715733F, + 0.9570447206F, 0.9573166871F, 0.9575874749F, 0.9578570863F, + 0.9581255236F, 0.9583927890F, 0.9586588849F, 0.9589238134F, + 0.9591875769F, 0.9594501777F, 0.9597116180F, 0.9599719003F, + 0.9602310267F, 0.9604889995F, 0.9607458213F, 0.9610014942F, + 0.9612560206F, 0.9615094028F, 0.9617616433F, 0.9620127443F, + 0.9622627083F, 0.9625115376F, 0.9627592345F, 0.9630058016F, + 0.9632512411F, 0.9634955555F, 0.9637387471F, 0.9639808185F, + 0.9642217720F, 0.9644616100F, 0.9647003349F, 0.9649379493F, + 0.9651744556F, 0.9654098561F, 0.9656441534F, 0.9658773499F, + 0.9661094480F, 0.9663404504F, 0.9665703593F, 0.9667991774F, + 0.9670269071F, 0.9672535509F, 0.9674791114F, 0.9677035909F, + 0.9679269921F, 0.9681493174F, 0.9683705694F, 0.9685907506F, + 0.9688098636F, 0.9690279108F, 0.9692448948F, 0.9694608182F, + 0.9696756836F, 0.9698894934F, 0.9701022503F, 0.9703139569F, + 0.9705246156F, 0.9707342291F, 0.9709428000F, 0.9711503309F, + 0.9713568243F, 0.9715622829F, 0.9717667093F, 0.9719701060F, + 0.9721724757F, 0.9723738210F, 0.9725741446F, 0.9727734490F, + 0.9729717369F, 0.9731690109F, 0.9733652737F, 0.9735605279F, + 0.9737547762F, 0.9739480212F, 0.9741402656F, 0.9743315120F, + 0.9745217631F, 0.9747110216F, 0.9748992901F, 0.9750865714F, + 0.9752728681F, 0.9754581829F, 0.9756425184F, 0.9758258775F, + 0.9760082627F, 0.9761896768F, 0.9763701224F, 0.9765496024F, + 0.9767281193F, 0.9769056760F, 0.9770822751F, 0.9772579193F, + 0.9774326114F, 0.9776063542F, 0.9777791502F, 0.9779510023F, + 0.9781219133F, 0.9782918858F, 0.9784609226F, 0.9786290264F, + 0.9787962000F, 0.9789624461F, 0.9791277676F, 0.9792921671F, + 0.9794556474F, 0.9796182113F, 0.9797798615F, 0.9799406009F, + 0.9801004321F, 0.9802593580F, 0.9804173813F, 0.9805745049F, + 0.9807307314F, 0.9808860637F, 0.9810405046F, 0.9811940568F, + 0.9813467232F, 0.9814985065F, 0.9816494095F, 0.9817994351F, + 0.9819485860F, 0.9820968650F, 0.9822442750F, 0.9823908186F, + 0.9825364988F, 0.9826813184F, 0.9828252801F, 0.9829683868F, + 0.9831106413F, 0.9832520463F, 0.9833926048F, 0.9835323195F, + 0.9836711932F, 0.9838092288F, 0.9839464291F, 0.9840827969F, + 0.9842183351F, 0.9843530464F, 0.9844869337F, 0.9846199998F, + 0.9847522475F, 0.9848836798F, 0.9850142993F, 0.9851441090F, + 0.9852731117F, 0.9854013101F, 0.9855287073F, 0.9856553058F, + 0.9857811087F, 0.9859061188F, 0.9860303388F, 0.9861537717F, + 0.9862764202F, 0.9863982872F, 0.9865193756F, 0.9866396882F, + 0.9867592277F, 0.9868779972F, 0.9869959993F, 0.9871132370F, + 0.9872297131F, 0.9873454304F, 0.9874603918F, 0.9875746001F, + 0.9876880581F, 0.9878007688F, 0.9879127348F, 0.9880239592F, + 0.9881344447F, 0.9882441941F, 0.9883532104F, 0.9884614962F, + 0.9885690546F, 0.9886758883F, 0.9887820001F, 0.9888873930F, + 0.9889920697F, 0.9890960331F, 0.9891992859F, 0.9893018312F, + 0.9894036716F, 0.9895048100F, 0.9896052493F, 0.9897049923F, + 0.9898040418F, 0.9899024006F, 0.9900000717F, 0.9900970577F, + 0.9901933616F, 0.9902889862F, 0.9903839343F, 0.9904782087F, + 0.9905718122F, 0.9906647477F, 0.9907570180F, 0.9908486259F, + 0.9909395742F, 0.9910298658F, 0.9911195034F, 0.9912084899F, + 0.9912968281F, 0.9913845208F, 0.9914715708F, 0.9915579810F, + 0.9916437540F, 0.9917288928F, 0.9918134001F, 0.9918972788F, + 0.9919805316F, 0.9920631613F, 0.9921451707F, 0.9922265626F, + 0.9923073399F, 0.9923875052F, 0.9924670615F, 0.9925460114F, + 0.9926243577F, 0.9927021033F, 0.9927792508F, 0.9928558032F, + 0.9929317631F, 0.9930071333F, 0.9930819167F, 0.9931561158F, + 0.9932297337F, 0.9933027728F, 0.9933752362F, 0.9934471264F, + 0.9935184462F, 0.9935891985F, 0.9936593859F, 0.9937290112F, + 0.9937980771F, 0.9938665864F, 0.9939345418F, 0.9940019460F, + 0.9940688018F, 0.9941351118F, 0.9942008789F, 0.9942661057F, + 0.9943307950F, 0.9943949494F, 0.9944585717F, 0.9945216645F, + 0.9945842307F, 0.9946462728F, 0.9947077936F, 0.9947687957F, + 0.9948292820F, 0.9948892550F, 0.9949487174F, 0.9950076719F, + 0.9950661212F, 0.9951240679F, 0.9951815148F, 0.9952384645F, + 0.9952949196F, 0.9953508828F, 0.9954063568F, 0.9954613442F, + 0.9955158476F, 0.9955698697F, 0.9956234132F, 0.9956764806F, + 0.9957290746F, 0.9957811978F, 0.9958328528F, 0.9958840423F, + 0.9959347688F, 0.9959850351F, 0.9960348435F, 0.9960841969F, + 0.9961330977F, 0.9961815486F, 0.9962295521F, 0.9962771108F, + 0.9963242274F, 0.9963709043F, 0.9964171441F, 0.9964629494F, + 0.9965083228F, 0.9965532668F, 0.9965977840F, 0.9966418768F, + 0.9966855479F, 0.9967287998F, 0.9967716350F, 0.9968140559F, + 0.9968560653F, 0.9968976655F, 0.9969388591F, 0.9969796485F, + 0.9970200363F, 0.9970600250F, 0.9970996170F, 0.9971388149F, + 0.9971776211F, 0.9972160380F, 0.9972540683F, 0.9972917142F, + 0.9973289783F, 0.9973658631F, 0.9974023709F, 0.9974385042F, + 0.9974742655F, 0.9975096571F, 0.9975446816F, 0.9975793413F, + 0.9976136386F, 0.9976475759F, 0.9976811557F, 0.9977143803F, + 0.9977472521F, 0.9977797736F, 0.9978119470F, 0.9978437748F, + 0.9978752593F, 0.9979064029F, 0.9979372079F, 0.9979676768F, + 0.9979978117F, 0.9980276151F, 0.9980570893F, 0.9980862367F, + 0.9981150595F, 0.9981435600F, 0.9981717406F, 0.9981996035F, + 0.9982271511F, 0.9982543856F, 0.9982813093F, 0.9983079246F, + 0.9983342336F, 0.9983602386F, 0.9983859418F, 0.9984113456F, + 0.9984364522F, 0.9984612638F, 0.9984857825F, 0.9985100108F, + 0.9985339507F, 0.9985576044F, 0.9985809743F, 0.9986040624F, + 0.9986268710F, 0.9986494022F, 0.9986716583F, 0.9986936413F, + 0.9987153535F, 0.9987367969F, 0.9987579738F, 0.9987788864F, + 0.9987995366F, 0.9988199267F, 0.9988400587F, 0.9988599348F, + 0.9988795572F, 0.9988989278F, 0.9989180487F, 0.9989369222F, + 0.9989555501F, 0.9989739347F, 0.9989920780F, 0.9990099820F, + 0.9990276487F, 0.9990450803F, 0.9990622787F, 0.9990792460F, + 0.9990959841F, 0.9991124952F, 0.9991287812F, 0.9991448440F, + 0.9991606858F, 0.9991763084F, 0.9991917139F, 0.9992069042F, + 0.9992218813F, 0.9992366471F, 0.9992512035F, 0.9992655525F, + 0.9992796961F, 0.9992936361F, 0.9993073744F, 0.9993209131F, + 0.9993342538F, 0.9993473987F, 0.9993603494F, 0.9993731080F, + 0.9993856762F, 0.9993980559F, 0.9994102490F, 0.9994222573F, + 0.9994340827F, 0.9994457269F, 0.9994571918F, 0.9994684793F, + 0.9994795910F, 0.9994905288F, 0.9995012945F, 0.9995118898F, + 0.9995223165F, 0.9995325765F, 0.9995426713F, 0.9995526029F, + 0.9995623728F, 0.9995719829F, 0.9995814349F, 0.9995907304F, + 0.9995998712F, 0.9996088590F, 0.9996176954F, 0.9996263821F, + 0.9996349208F, 0.9996433132F, 0.9996515609F, 0.9996596656F, + 0.9996676288F, 0.9996754522F, 0.9996831375F, 0.9996906862F, + 0.9996981000F, 0.9997053804F, 0.9997125290F, 0.9997195474F, + 0.9997264371F, 0.9997331998F, 0.9997398369F, 0.9997463500F, + 0.9997527406F, 0.9997590103F, 0.9997651606F, 0.9997711930F, + 0.9997771089F, 0.9997829098F, 0.9997885973F, 0.9997941728F, + 0.9997996378F, 0.9998049936F, 0.9998102419F, 0.9998153839F, + 0.9998204211F, 0.9998253550F, 0.9998301868F, 0.9998349182F, + 0.9998395503F, 0.9998440847F, 0.9998485226F, 0.9998528654F, + 0.9998571146F, 0.9998612713F, 0.9998653370F, 0.9998693130F, + 0.9998732007F, 0.9998770012F, 0.9998807159F, 0.9998843461F, + 0.9998878931F, 0.9998913581F, 0.9998947424F, 0.9998980473F, + 0.9999012740F, 0.9999044237F, 0.9999074976F, 0.9999104971F, + 0.9999134231F, 0.9999162771F, 0.9999190601F, 0.9999217733F, + 0.9999244179F, 0.9999269950F, 0.9999295058F, 0.9999319515F, + 0.9999343332F, 0.9999366519F, 0.9999389088F, 0.9999411050F, + 0.9999432416F, 0.9999453196F, 0.9999473402F, 0.9999493044F, + 0.9999512132F, 0.9999530677F, 0.9999548690F, 0.9999566180F, + 0.9999583157F, 0.9999599633F, 0.9999615616F, 0.9999631116F, + 0.9999646144F, 0.9999660709F, 0.9999674820F, 0.9999688487F, + 0.9999701719F, 0.9999714526F, 0.9999726917F, 0.9999738900F, + 0.9999750486F, 0.9999761682F, 0.9999772497F, 0.9999782941F, + 0.9999793021F, 0.9999802747F, 0.9999812126F, 0.9999821167F, + 0.9999829878F, 0.9999838268F, 0.9999846343F, 0.9999854113F, + 0.9999861584F, 0.9999868765F, 0.9999875664F, 0.9999882287F, + 0.9999888642F, 0.9999894736F, 0.9999900577F, 0.9999906172F, + 0.9999911528F, 0.9999916651F, 0.9999921548F, 0.9999926227F, + 0.9999930693F, 0.9999934954F, 0.9999939015F, 0.9999942883F, + 0.9999946564F, 0.9999950064F, 0.9999953390F, 0.9999956547F, + 0.9999959541F, 0.9999962377F, 0.9999965062F, 0.9999967601F, + 0.9999969998F, 0.9999972260F, 0.9999974392F, 0.9999976399F, + 0.9999978285F, 0.9999980056F, 0.9999981716F, 0.9999983271F, + 0.9999984724F, 0.9999986081F, 0.9999987345F, 0.9999988521F, + 0.9999989613F, 0.9999990625F, 0.9999991562F, 0.9999992426F, + 0.9999993223F, 0.9999993954F, 0.9999994625F, 0.9999995239F, + 0.9999995798F, 0.9999996307F, 0.9999996768F, 0.9999997184F, + 0.9999997559F, 0.9999997895F, 0.9999998195F, 0.9999998462F, + 0.9999998698F, 0.9999998906F, 0.9999999088F, 0.9999999246F, + 0.9999999383F, 0.9999999500F, 0.9999999600F, 0.9999999684F, + 0.9999999754F, 0.9999999811F, 0.9999999858F, 0.9999999896F, + 0.9999999925F, 0.9999999948F, 0.9999999965F, 0.9999999978F, + 0.9999999986F, 0.9999999992F, 0.9999999996F, 0.9999999998F, + 0.9999999999F, 1.0000000000F, 1.0000000000F, 1.0000000000F, +}; + +DECLARE_ALIGNED(16, static const float, vwin8192)[4096] = { + 0.0000000578F, 0.0000005198F, 0.0000014438F, 0.0000028299F, + 0.0000046780F, 0.0000069882F, 0.0000097604F, 0.0000129945F, + 0.0000166908F, 0.0000208490F, 0.0000254692F, 0.0000305515F, + 0.0000360958F, 0.0000421021F, 0.0000485704F, 0.0000555006F, + 0.0000628929F, 0.0000707472F, 0.0000790635F, 0.0000878417F, + 0.0000970820F, 0.0001067842F, 0.0001169483F, 0.0001275744F, + 0.0001386625F, 0.0001502126F, 0.0001622245F, 0.0001746984F, + 0.0001876343F, 0.0002010320F, 0.0002148917F, 0.0002292132F, + 0.0002439967F, 0.0002592421F, 0.0002749493F, 0.0002911184F, + 0.0003077493F, 0.0003248421F, 0.0003423967F, 0.0003604132F, + 0.0003788915F, 0.0003978316F, 0.0004172335F, 0.0004370971F, + 0.0004574226F, 0.0004782098F, 0.0004994587F, 0.0005211694F, + 0.0005433418F, 0.0005659759F, 0.0005890717F, 0.0006126292F, + 0.0006366484F, 0.0006611292F, 0.0006860716F, 0.0007114757F, + 0.0007373414F, 0.0007636687F, 0.0007904576F, 0.0008177080F, + 0.0008454200F, 0.0008735935F, 0.0009022285F, 0.0009313250F, + 0.0009608830F, 0.0009909025F, 0.0010213834F, 0.0010523257F, + 0.0010837295F, 0.0011155946F, 0.0011479211F, 0.0011807090F, + 0.0012139582F, 0.0012476687F, 0.0012818405F, 0.0013164736F, + 0.0013515679F, 0.0013871235F, 0.0014231402F, 0.0014596182F, + 0.0014965573F, 0.0015339576F, 0.0015718190F, 0.0016101415F, + 0.0016489251F, 0.0016881698F, 0.0017278754F, 0.0017680421F, + 0.0018086698F, 0.0018497584F, 0.0018913080F, 0.0019333185F, + 0.0019757898F, 0.0020187221F, 0.0020621151F, 0.0021059690F, + 0.0021502837F, 0.0021950591F, 0.0022402953F, 0.0022859921F, + 0.0023321497F, 0.0023787679F, 0.0024258467F, 0.0024733861F, + 0.0025213861F, 0.0025698466F, 0.0026187676F, 0.0026681491F, + 0.0027179911F, 0.0027682935F, 0.0028190562F, 0.0028702794F, + 0.0029219628F, 0.0029741066F, 0.0030267107F, 0.0030797749F, + 0.0031332994F, 0.0031872841F, 0.0032417289F, 0.0032966338F, + 0.0033519988F, 0.0034078238F, 0.0034641089F, 0.0035208539F, + 0.0035780589F, 0.0036357237F, 0.0036938485F, 0.0037524331F, + 0.0038114775F, 0.0038709817F, 0.0039309456F, 0.0039913692F, + 0.0040522524F, 0.0041135953F, 0.0041753978F, 0.0042376599F, + 0.0043003814F, 0.0043635624F, 0.0044272029F, 0.0044913028F, + 0.0045558620F, 0.0046208806F, 0.0046863585F, 0.0047522955F, + 0.0048186919F, 0.0048855473F, 0.0049528619F, 0.0050206356F, + 0.0050888684F, 0.0051575601F, 0.0052267108F, 0.0052963204F, + 0.0053663890F, 0.0054369163F, 0.0055079025F, 0.0055793474F, + 0.0056512510F, 0.0057236133F, 0.0057964342F, 0.0058697137F, + 0.0059434517F, 0.0060176482F, 0.0060923032F, 0.0061674166F, + 0.0062429883F, 0.0063190183F, 0.0063955066F, 0.0064724532F, + 0.0065498579F, 0.0066277207F, 0.0067060416F, 0.0067848205F, + 0.0068640575F, 0.0069437523F, 0.0070239051F, 0.0071045157F, + 0.0071855840F, 0.0072671102F, 0.0073490940F, 0.0074315355F, + 0.0075144345F, 0.0075977911F, 0.0076816052F, 0.0077658768F, + 0.0078506057F, 0.0079357920F, 0.0080214355F, 0.0081075363F, + 0.0081940943F, 0.0082811094F, 0.0083685816F, 0.0084565108F, + 0.0085448970F, 0.0086337401F, 0.0087230401F, 0.0088127969F, + 0.0089030104F, 0.0089936807F, 0.0090848076F, 0.0091763911F, + 0.0092684311F, 0.0093609276F, 0.0094538805F, 0.0095472898F, + 0.0096411554F, 0.0097354772F, 0.0098302552F, 0.0099254894F, + 0.0100211796F, 0.0101173259F, 0.0102139281F, 0.0103109863F, + 0.0104085002F, 0.0105064700F, 0.0106048955F, 0.0107037766F, + 0.0108031133F, 0.0109029056F, 0.0110031534F, 0.0111038565F, + 0.0112050151F, 0.0113066289F, 0.0114086980F, 0.0115112222F, + 0.0116142015F, 0.0117176359F, 0.0118215252F, 0.0119258695F, + 0.0120306686F, 0.0121359225F, 0.0122416312F, 0.0123477944F, + 0.0124544123F, 0.0125614847F, 0.0126690116F, 0.0127769928F, + 0.0128854284F, 0.0129943182F, 0.0131036623F, 0.0132134604F, + 0.0133237126F, 0.0134344188F, 0.0135455790F, 0.0136571929F, + 0.0137692607F, 0.0138817821F, 0.0139947572F, 0.0141081859F, + 0.0142220681F, 0.0143364037F, 0.0144511927F, 0.0145664350F, + 0.0146821304F, 0.0147982791F, 0.0149148808F, 0.0150319355F, + 0.0151494431F, 0.0152674036F, 0.0153858168F, 0.0155046828F, + 0.0156240014F, 0.0157437726F, 0.0158639962F, 0.0159846723F, + 0.0161058007F, 0.0162273814F, 0.0163494142F, 0.0164718991F, + 0.0165948361F, 0.0167182250F, 0.0168420658F, 0.0169663584F, + 0.0170911027F, 0.0172162987F, 0.0173419462F, 0.0174680452F, + 0.0175945956F, 0.0177215974F, 0.0178490504F, 0.0179769545F, + 0.0181053098F, 0.0182341160F, 0.0183633732F, 0.0184930812F, + 0.0186232399F, 0.0187538494F, 0.0188849094F, 0.0190164200F, + 0.0191483809F, 0.0192807923F, 0.0194136539F, 0.0195469656F, + 0.0196807275F, 0.0198149394F, 0.0199496012F, 0.0200847128F, + 0.0202202742F, 0.0203562853F, 0.0204927460F, 0.0206296561F, + 0.0207670157F, 0.0209048245F, 0.0210430826F, 0.0211817899F, + 0.0213209462F, 0.0214605515F, 0.0216006057F, 0.0217411086F, + 0.0218820603F, 0.0220234605F, 0.0221653093F, 0.0223076066F, + 0.0224503521F, 0.0225935459F, 0.0227371879F, 0.0228812779F, + 0.0230258160F, 0.0231708018F, 0.0233162355F, 0.0234621169F, + 0.0236084459F, 0.0237552224F, 0.0239024462F, 0.0240501175F, + 0.0241982359F, 0.0243468015F, 0.0244958141F, 0.0246452736F, + 0.0247951800F, 0.0249455331F, 0.0250963329F, 0.0252475792F, + 0.0253992720F, 0.0255514111F, 0.0257039965F, 0.0258570281F, + 0.0260105057F, 0.0261644293F, 0.0263187987F, 0.0264736139F, + 0.0266288747F, 0.0267845811F, 0.0269407330F, 0.0270973302F, + 0.0272543727F, 0.0274118604F, 0.0275697930F, 0.0277281707F, + 0.0278869932F, 0.0280462604F, 0.0282059723F, 0.0283661287F, + 0.0285267295F, 0.0286877747F, 0.0288492641F, 0.0290111976F, + 0.0291735751F, 0.0293363965F, 0.0294996617F, 0.0296633706F, + 0.0298275231F, 0.0299921190F, 0.0301571583F, 0.0303226409F, + 0.0304885667F, 0.0306549354F, 0.0308217472F, 0.0309890017F, + 0.0311566989F, 0.0313248388F, 0.0314934211F, 0.0316624459F, + 0.0318319128F, 0.0320018220F, 0.0321721732F, 0.0323429663F, + 0.0325142013F, 0.0326858779F, 0.0328579962F, 0.0330305559F, + 0.0332035570F, 0.0333769994F, 0.0335508829F, 0.0337252074F, + 0.0338999728F, 0.0340751790F, 0.0342508259F, 0.0344269134F, + 0.0346034412F, 0.0347804094F, 0.0349578178F, 0.0351356663F, + 0.0353139548F, 0.0354926831F, 0.0356718511F, 0.0358514588F, + 0.0360315059F, 0.0362119924F, 0.0363929182F, 0.0365742831F, + 0.0367560870F, 0.0369383297F, 0.0371210113F, 0.0373041315F, + 0.0374876902F, 0.0376716873F, 0.0378561226F, 0.0380409961F, + 0.0382263077F, 0.0384120571F, 0.0385982443F, 0.0387848691F, + 0.0389719315F, 0.0391594313F, 0.0393473683F, 0.0395357425F, + 0.0397245537F, 0.0399138017F, 0.0401034866F, 0.0402936080F, + 0.0404841660F, 0.0406751603F, 0.0408665909F, 0.0410584576F, + 0.0412507603F, 0.0414434988F, 0.0416366731F, 0.0418302829F, + 0.0420243282F, 0.0422188088F, 0.0424137246F, 0.0426090755F, + 0.0428048613F, 0.0430010819F, 0.0431977371F, 0.0433948269F, + 0.0435923511F, 0.0437903095F, 0.0439887020F, 0.0441875285F, + 0.0443867889F, 0.0445864830F, 0.0447866106F, 0.0449871717F, + 0.0451881661F, 0.0453895936F, 0.0455914542F, 0.0457937477F, + 0.0459964738F, 0.0461996326F, 0.0464032239F, 0.0466072475F, + 0.0468117032F, 0.0470165910F, 0.0472219107F, 0.0474276622F, + 0.0476338452F, 0.0478404597F, 0.0480475056F, 0.0482549827F, + 0.0484628907F, 0.0486712297F, 0.0488799994F, 0.0490891998F, + 0.0492988306F, 0.0495088917F, 0.0497193830F, 0.0499303043F, + 0.0501416554F, 0.0503534363F, 0.0505656468F, 0.0507782867F, + 0.0509913559F, 0.0512048542F, 0.0514187815F, 0.0516331376F, + 0.0518479225F, 0.0520631358F, 0.0522787775F, 0.0524948475F, + 0.0527113455F, 0.0529282715F, 0.0531456252F, 0.0533634066F, + 0.0535816154F, 0.0538002515F, 0.0540193148F, 0.0542388051F, + 0.0544587222F, 0.0546790660F, 0.0548998364F, 0.0551210331F, + 0.0553426561F, 0.0555647051F, 0.0557871801F, 0.0560100807F, + 0.0562334070F, 0.0564571587F, 0.0566813357F, 0.0569059378F, + 0.0571309649F, 0.0573564168F, 0.0575822933F, 0.0578085942F, + 0.0580353195F, 0.0582624689F, 0.0584900423F, 0.0587180396F, + 0.0589464605F, 0.0591753049F, 0.0594045726F, 0.0596342635F, + 0.0598643774F, 0.0600949141F, 0.0603258735F, 0.0605572555F, + 0.0607890597F, 0.0610212862F, 0.0612539346F, 0.0614870049F, + 0.0617204968F, 0.0619544103F, 0.0621887451F, 0.0624235010F, + 0.0626586780F, 0.0628942758F, 0.0631302942F, 0.0633667331F, + 0.0636035923F, 0.0638408717F, 0.0640785710F, 0.0643166901F, + 0.0645552288F, 0.0647941870F, 0.0650335645F, 0.0652733610F, + 0.0655135765F, 0.0657542108F, 0.0659952636F, 0.0662367348F, + 0.0664786242F, 0.0667209316F, 0.0669636570F, 0.0672068000F, + 0.0674503605F, 0.0676943384F, 0.0679387334F, 0.0681835454F, + 0.0684287742F, 0.0686744196F, 0.0689204814F, 0.0691669595F, + 0.0694138536F, 0.0696611637F, 0.0699088894F, 0.0701570307F, + 0.0704055873F, 0.0706545590F, 0.0709039458F, 0.0711537473F, + 0.0714039634F, 0.0716545939F, 0.0719056387F, 0.0721570975F, + 0.0724089702F, 0.0726612565F, 0.0729139563F, 0.0731670694F, + 0.0734205956F, 0.0736745347F, 0.0739288866F, 0.0741836510F, + 0.0744388277F, 0.0746944166F, 0.0749504175F, 0.0752068301F, + 0.0754636543F, 0.0757208899F, 0.0759785367F, 0.0762365946F, + 0.0764950632F, 0.0767539424F, 0.0770132320F, 0.0772729319F, + 0.0775330418F, 0.0777935616F, 0.0780544909F, 0.0783158298F, + 0.0785775778F, 0.0788397349F, 0.0791023009F, 0.0793652755F, + 0.0796286585F, 0.0798924498F, 0.0801566492F, 0.0804212564F, + 0.0806862712F, 0.0809516935F, 0.0812175231F, 0.0814837597F, + 0.0817504031F, 0.0820174532F, 0.0822849097F, 0.0825527724F, + 0.0828210412F, 0.0830897158F, 0.0833587960F, 0.0836282816F, + 0.0838981724F, 0.0841684682F, 0.0844391688F, 0.0847102740F, + 0.0849817835F, 0.0852536973F, 0.0855260150F, 0.0857987364F, + 0.0860718614F, 0.0863453897F, 0.0866193211F, 0.0868936554F, + 0.0871683924F, 0.0874435319F, 0.0877190737F, 0.0879950175F, + 0.0882713632F, 0.0885481105F, 0.0888252592F, 0.0891028091F, + 0.0893807600F, 0.0896591117F, 0.0899378639F, 0.0902170165F, + 0.0904965692F, 0.0907765218F, 0.0910568740F, 0.0913376258F, + 0.0916187767F, 0.0919003268F, 0.0921822756F, 0.0924646230F, + 0.0927473687F, 0.0930305126F, 0.0933140545F, 0.0935979940F, + 0.0938823310F, 0.0941670653F, 0.0944521966F, 0.0947377247F, + 0.0950236494F, 0.0953099704F, 0.0955966876F, 0.0958838007F, + 0.0961713094F, 0.0964592136F, 0.0967475131F, 0.0970362075F, + 0.0973252967F, 0.0976147805F, 0.0979046585F, 0.0981949307F, + 0.0984855967F, 0.0987766563F, 0.0990681093F, 0.0993599555F, + 0.0996521945F, 0.0999448263F, 0.1002378506F, 0.1005312671F, + 0.1008250755F, 0.1011192757F, 0.1014138675F, 0.1017088505F, + 0.1020042246F, 0.1022999895F, 0.1025961450F, 0.1028926909F, + 0.1031896268F, 0.1034869526F, 0.1037846680F, 0.1040827729F, + 0.1043812668F, 0.1046801497F, 0.1049794213F, 0.1052790813F, + 0.1055791294F, 0.1058795656F, 0.1061803894F, 0.1064816006F, + 0.1067831991F, 0.1070851846F, 0.1073875568F, 0.1076903155F, + 0.1079934604F, 0.1082969913F, 0.1086009079F, 0.1089052101F, + 0.1092098975F, 0.1095149699F, 0.1098204270F, 0.1101262687F, + 0.1104324946F, 0.1107391045F, 0.1110460982F, 0.1113534754F, + 0.1116612359F, 0.1119693793F, 0.1122779055F, 0.1125868142F, + 0.1128961052F, 0.1132057781F, 0.1135158328F, 0.1138262690F, + 0.1141370863F, 0.1144482847F, 0.1147598638F, 0.1150718233F, + 0.1153841631F, 0.1156968828F, 0.1160099822F, 0.1163234610F, + 0.1166373190F, 0.1169515559F, 0.1172661714F, 0.1175811654F, + 0.1178965374F, 0.1182122874F, 0.1185284149F, 0.1188449198F, + 0.1191618018F, 0.1194790606F, 0.1197966960F, 0.1201147076F, + 0.1204330953F, 0.1207518587F, 0.1210709976F, 0.1213905118F, + 0.1217104009F, 0.1220306647F, 0.1223513029F, 0.1226723153F, + 0.1229937016F, 0.1233154615F, 0.1236375948F, 0.1239601011F, + 0.1242829803F, 0.1246062319F, 0.1249298559F, 0.1252538518F, + 0.1255782195F, 0.1259029586F, 0.1262280689F, 0.1265535501F, + 0.1268794019F, 0.1272056241F, 0.1275322163F, 0.1278591784F, + 0.1281865099F, 0.1285142108F, 0.1288422805F, 0.1291707190F, + 0.1294995259F, 0.1298287009F, 0.1301582437F, 0.1304881542F, + 0.1308184319F, 0.1311490766F, 0.1314800881F, 0.1318114660F, + 0.1321432100F, 0.1324753200F, 0.1328077955F, 0.1331406364F, + 0.1334738422F, 0.1338074129F, 0.1341413479F, 0.1344756472F, + 0.1348103103F, 0.1351453370F, 0.1354807270F, 0.1358164801F, + 0.1361525959F, 0.1364890741F, 0.1368259145F, 0.1371631167F, + 0.1375006805F, 0.1378386056F, 0.1381768917F, 0.1385155384F, + 0.1388545456F, 0.1391939129F, 0.1395336400F, 0.1398737266F, + 0.1402141724F, 0.1405549772F, 0.1408961406F, 0.1412376623F, + 0.1415795421F, 0.1419217797F, 0.1422643746F, 0.1426073268F, + 0.1429506358F, 0.1432943013F, 0.1436383231F, 0.1439827008F, + 0.1443274342F, 0.1446725229F, 0.1450179667F, 0.1453637652F, + 0.1457099181F, 0.1460564252F, 0.1464032861F, 0.1467505006F, + 0.1470980682F, 0.1474459888F, 0.1477942620F, 0.1481428875F, + 0.1484918651F, 0.1488411942F, 0.1491908748F, 0.1495409065F, + 0.1498912889F, 0.1502420218F, 0.1505931048F, 0.1509445376F, + 0.1512963200F, 0.1516484516F, 0.1520009321F, 0.1523537612F, + 0.1527069385F, 0.1530604638F, 0.1534143368F, 0.1537685571F, + 0.1541231244F, 0.1544780384F, 0.1548332987F, 0.1551889052F, + 0.1555448574F, 0.1559011550F, 0.1562577978F, 0.1566147853F, + 0.1569721173F, 0.1573297935F, 0.1576878135F, 0.1580461771F, + 0.1584048838F, 0.1587639334F, 0.1591233255F, 0.1594830599F, + 0.1598431361F, 0.1602035540F, 0.1605643131F, 0.1609254131F, + 0.1612868537F, 0.1616486346F, 0.1620107555F, 0.1623732160F, + 0.1627360158F, 0.1630991545F, 0.1634626319F, 0.1638264476F, + 0.1641906013F, 0.1645550926F, 0.1649199212F, 0.1652850869F, + 0.1656505892F, 0.1660164278F, 0.1663826024F, 0.1667491127F, + 0.1671159583F, 0.1674831388F, 0.1678506541F, 0.1682185036F, + 0.1685866872F, 0.1689552044F, 0.1693240549F, 0.1696932384F, + 0.1700627545F, 0.1704326029F, 0.1708027833F, 0.1711732952F, + 0.1715441385F, 0.1719153127F, 0.1722868175F, 0.1726586526F, + 0.1730308176F, 0.1734033121F, 0.1737761359F, 0.1741492886F, + 0.1745227698F, 0.1748965792F, 0.1752707164F, 0.1756451812F, + 0.1760199731F, 0.1763950918F, 0.1767705370F, 0.1771463083F, + 0.1775224054F, 0.1778988279F, 0.1782755754F, 0.1786526477F, + 0.1790300444F, 0.1794077651F, 0.1797858094F, 0.1801641771F, + 0.1805428677F, 0.1809218810F, 0.1813012165F, 0.1816808739F, + 0.1820608528F, 0.1824411530F, 0.1828217739F, 0.1832027154F, + 0.1835839770F, 0.1839655584F, 0.1843474592F, 0.1847296790F, + 0.1851122175F, 0.1854950744F, 0.1858782492F, 0.1862617417F, + 0.1866455514F, 0.1870296780F, 0.1874141211F, 0.1877988804F, + 0.1881839555F, 0.1885693461F, 0.1889550517F, 0.1893410721F, + 0.1897274068F, 0.1901140555F, 0.1905010178F, 0.1908882933F, + 0.1912758818F, 0.1916637828F, 0.1920519959F, 0.1924405208F, + 0.1928293571F, 0.1932185044F, 0.1936079625F, 0.1939977308F, + 0.1943878091F, 0.1947781969F, 0.1951688939F, 0.1955598998F, + 0.1959512141F, 0.1963428364F, 0.1967347665F, 0.1971270038F, + 0.1975195482F, 0.1979123990F, 0.1983055561F, 0.1986990190F, + 0.1990927873F, 0.1994868607F, 0.1998812388F, 0.2002759212F, + 0.2006709075F, 0.2010661974F, 0.2014617904F, 0.2018576862F, + 0.2022538844F, 0.2026503847F, 0.2030471865F, 0.2034442897F, + 0.2038416937F, 0.2042393982F, 0.2046374028F, 0.2050357071F, + 0.2054343107F, 0.2058332133F, 0.2062324145F, 0.2066319138F, + 0.2070317110F, 0.2074318055F, 0.2078321970F, 0.2082328852F, + 0.2086338696F, 0.2090351498F, 0.2094367255F, 0.2098385962F, + 0.2102407617F, 0.2106432213F, 0.2110459749F, 0.2114490220F, + 0.2118523621F, 0.2122559950F, 0.2126599202F, 0.2130641373F, + 0.2134686459F, 0.2138734456F, 0.2142785361F, 0.2146839168F, + 0.2150895875F, 0.2154955478F, 0.2159017972F, 0.2163083353F, + 0.2167151617F, 0.2171222761F, 0.2175296780F, 0.2179373670F, + 0.2183453428F, 0.2187536049F, 0.2191621529F, 0.2195709864F, + 0.2199801051F, 0.2203895085F, 0.2207991961F, 0.2212091677F, + 0.2216194228F, 0.2220299610F, 0.2224407818F, 0.2228518850F, + 0.2232632699F, 0.2236749364F, 0.2240868839F, 0.2244991121F, + 0.2249116204F, 0.2253244086F, 0.2257374763F, 0.2261508229F, + 0.2265644481F, 0.2269783514F, 0.2273925326F, 0.2278069911F, + 0.2282217265F, 0.2286367384F, 0.2290520265F, 0.2294675902F, + 0.2298834292F, 0.2302995431F, 0.2307159314F, 0.2311325937F, + 0.2315495297F, 0.2319667388F, 0.2323842207F, 0.2328019749F, + 0.2332200011F, 0.2336382988F, 0.2340568675F, 0.2344757070F, + 0.2348948166F, 0.2353141961F, 0.2357338450F, 0.2361537629F, + 0.2365739493F, 0.2369944038F, 0.2374151261F, 0.2378361156F, + 0.2382573720F, 0.2386788948F, 0.2391006836F, 0.2395227380F, + 0.2399450575F, 0.2403676417F, 0.2407904902F, 0.2412136026F, + 0.2416369783F, 0.2420606171F, 0.2424845185F, 0.2429086820F, + 0.2433331072F, 0.2437577936F, 0.2441827409F, 0.2446079486F, + 0.2450334163F, 0.2454591435F, 0.2458851298F, 0.2463113747F, + 0.2467378779F, 0.2471646389F, 0.2475916573F, 0.2480189325F, + 0.2484464643F, 0.2488742521F, 0.2493022955F, 0.2497305940F, + 0.2501591473F, 0.2505879549F, 0.2510170163F, 0.2514463311F, + 0.2518758989F, 0.2523057193F, 0.2527357916F, 0.2531661157F, + 0.2535966909F, 0.2540275169F, 0.2544585931F, 0.2548899193F, + 0.2553214948F, 0.2557533193F, 0.2561853924F, 0.2566177135F, + 0.2570502822F, 0.2574830981F, 0.2579161608F, 0.2583494697F, + 0.2587830245F, 0.2592168246F, 0.2596508697F, 0.2600851593F, + 0.2605196929F, 0.2609544701F, 0.2613894904F, 0.2618247534F, + 0.2622602586F, 0.2626960055F, 0.2631319938F, 0.2635682230F, + 0.2640046925F, 0.2644414021F, 0.2648783511F, 0.2653155391F, + 0.2657529657F, 0.2661906305F, 0.2666285329F, 0.2670666725F, + 0.2675050489F, 0.2679436616F, 0.2683825101F, 0.2688215940F, + 0.2692609127F, 0.2697004660F, 0.2701402532F, 0.2705802739F, + 0.2710205278F, 0.2714610142F, 0.2719017327F, 0.2723426830F, + 0.2727838644F, 0.2732252766F, 0.2736669191F, 0.2741087914F, + 0.2745508930F, 0.2749932235F, 0.2754357824F, 0.2758785693F, + 0.2763215837F, 0.2767648251F, 0.2772082930F, 0.2776519870F, + 0.2780959066F, 0.2785400513F, 0.2789844207F, 0.2794290143F, + 0.2798738316F, 0.2803188722F, 0.2807641355F, 0.2812096211F, + 0.2816553286F, 0.2821012574F, 0.2825474071F, 0.2829937773F, + 0.2834403673F, 0.2838871768F, 0.2843342053F, 0.2847814523F, + 0.2852289174F, 0.2856765999F, 0.2861244996F, 0.2865726159F, + 0.2870209482F, 0.2874694962F, 0.2879182594F, 0.2883672372F, + 0.2888164293F, 0.2892658350F, 0.2897154540F, 0.2901652858F, + 0.2906153298F, 0.2910655856F, 0.2915160527F, 0.2919667306F, + 0.2924176189F, 0.2928687171F, 0.2933200246F, 0.2937715409F, + 0.2942232657F, 0.2946751984F, 0.2951273386F, 0.2955796856F, + 0.2960322391F, 0.2964849986F, 0.2969379636F, 0.2973911335F, + 0.2978445080F, 0.2982980864F, 0.2987518684F, 0.2992058534F, + 0.2996600409F, 0.3001144305F, 0.3005690217F, 0.3010238139F, + 0.3014788067F, 0.3019339995F, 0.3023893920F, 0.3028449835F, + 0.3033007736F, 0.3037567618F, 0.3042129477F, 0.3046693306F, + 0.3051259102F, 0.3055826859F, 0.3060396572F, 0.3064968236F, + 0.3069541847F, 0.3074117399F, 0.3078694887F, 0.3083274307F, + 0.3087855653F, 0.3092438920F, 0.3097024104F, 0.3101611199F, + 0.3106200200F, 0.3110791103F, 0.3115383902F, 0.3119978592F, + 0.3124575169F, 0.3129173627F, 0.3133773961F, 0.3138376166F, + 0.3142980238F, 0.3147586170F, 0.3152193959F, 0.3156803598F, + 0.3161415084F, 0.3166028410F, 0.3170643573F, 0.3175260566F, + 0.3179879384F, 0.3184500023F, 0.3189122478F, 0.3193746743F, + 0.3198372814F, 0.3203000685F, 0.3207630351F, 0.3212261807F, + 0.3216895048F, 0.3221530069F, 0.3226166865F, 0.3230805430F, + 0.3235445760F, 0.3240087849F, 0.3244731693F, 0.3249377285F, + 0.3254024622F, 0.3258673698F, 0.3263324507F, 0.3267977045F, + 0.3272631306F, 0.3277287286F, 0.3281944978F, 0.3286604379F, + 0.3291265482F, 0.3295928284F, 0.3300592777F, 0.3305258958F, + 0.3309926821F, 0.3314596361F, 0.3319267573F, 0.3323940451F, + 0.3328614990F, 0.3333291186F, 0.3337969033F, 0.3342648525F, + 0.3347329658F, 0.3352012427F, 0.3356696825F, 0.3361382849F, + 0.3366070492F, 0.3370759749F, 0.3375450616F, 0.3380143087F, + 0.3384837156F, 0.3389532819F, 0.3394230071F, 0.3398928905F, + 0.3403629317F, 0.3408331302F, 0.3413034854F, 0.3417739967F, + 0.3422446638F, 0.3427154860F, 0.3431864628F, 0.3436575938F, + 0.3441288782F, 0.3446003158F, 0.3450719058F, 0.3455436478F, + 0.3460155412F, 0.3464875856F, 0.3469597804F, 0.3474321250F, + 0.3479046189F, 0.3483772617F, 0.3488500527F, 0.3493229914F, + 0.3497960774F, 0.3502693100F, 0.3507426887F, 0.3512162131F, + 0.3516898825F, 0.3521636965F, 0.3526376545F, 0.3531117559F, + 0.3535860003F, 0.3540603870F, 0.3545349157F, 0.3550095856F, + 0.3554843964F, 0.3559593474F, 0.3564344381F, 0.3569096680F, + 0.3573850366F, 0.3578605432F, 0.3583361875F, 0.3588119687F, + 0.3592878865F, 0.3597639402F, 0.3602401293F, 0.3607164533F, + 0.3611929117F, 0.3616695038F, 0.3621462292F, 0.3626230873F, + 0.3631000776F, 0.3635771995F, 0.3640544525F, 0.3645318360F, + 0.3650093496F, 0.3654869926F, 0.3659647645F, 0.3664426648F, + 0.3669206930F, 0.3673988484F, 0.3678771306F, 0.3683555390F, + 0.3688340731F, 0.3693127322F, 0.3697915160F, 0.3702704237F, + 0.3707494549F, 0.3712286091F, 0.3717078857F, 0.3721872840F, + 0.3726668037F, 0.3731464441F, 0.3736262047F, 0.3741060850F, + 0.3745860843F, 0.3750662023F, 0.3755464382F, 0.3760267915F, + 0.3765072618F, 0.3769878484F, 0.3774685509F, 0.3779493686F, + 0.3784303010F, 0.3789113475F, 0.3793925076F, 0.3798737809F, + 0.3803551666F, 0.3808366642F, 0.3813182733F, 0.3817999932F, + 0.3822818234F, 0.3827637633F, 0.3832458124F, 0.3837279702F, + 0.3842102360F, 0.3846926093F, 0.3851750897F, 0.3856576764F, + 0.3861403690F, 0.3866231670F, 0.3871060696F, 0.3875890765F, + 0.3880721870F, 0.3885554007F, 0.3890387168F, 0.3895221349F, + 0.3900056544F, 0.3904892748F, 0.3909729955F, 0.3914568160F, + 0.3919407356F, 0.3924247539F, 0.3929088702F, 0.3933930841F, + 0.3938773949F, 0.3943618021F, 0.3948463052F, 0.3953309035F, + 0.3958155966F, 0.3963003838F, 0.3967852646F, 0.3972702385F, + 0.3977553048F, 0.3982404631F, 0.3987257127F, 0.3992110531F, + 0.3996964838F, 0.4001820041F, 0.4006676136F, 0.4011533116F, + 0.4016390976F, 0.4021249710F, 0.4026109313F, 0.4030969779F, + 0.4035831102F, 0.4040693277F, 0.4045556299F, 0.4050420160F, + 0.4055284857F, 0.4060150383F, 0.4065016732F, 0.4069883899F, + 0.4074751879F, 0.4079620665F, 0.4084490252F, 0.4089360635F, + 0.4094231807F, 0.4099103763F, 0.4103976498F, 0.4108850005F, + 0.4113724280F, 0.4118599315F, 0.4123475107F, 0.4128351648F, + 0.4133228934F, 0.4138106959F, 0.4142985716F, 0.4147865201F, + 0.4152745408F, 0.4157626330F, 0.4162507963F, 0.4167390301F, + 0.4172273337F, 0.4177157067F, 0.4182041484F, 0.4186926583F, + 0.4191812359F, 0.4196698805F, 0.4201585915F, 0.4206473685F, + 0.4211362108F, 0.4216251179F, 0.4221140892F, 0.4226031241F, + 0.4230922221F, 0.4235813826F, 0.4240706050F, 0.4245598887F, + 0.4250492332F, 0.4255386379F, 0.4260281022F, 0.4265176256F, + 0.4270072075F, 0.4274968473F, 0.4279865445F, 0.4284762984F, + 0.4289661086F, 0.4294559743F, 0.4299458951F, 0.4304358704F, + 0.4309258996F, 0.4314159822F, 0.4319061175F, 0.4323963050F, + 0.4328865441F, 0.4333768342F, 0.4338671749F, 0.4343575654F, + 0.4348480052F, 0.4353384938F, 0.4358290306F, 0.4363196149F, + 0.4368102463F, 0.4373009241F, 0.4377916478F, 0.4382824168F, + 0.4387732305F, 0.4392640884F, 0.4397549899F, 0.4402459343F, + 0.4407369212F, 0.4412279499F, 0.4417190198F, 0.4422101305F, + 0.4427012813F, 0.4431924717F, 0.4436837010F, 0.4441749686F, + 0.4446662742F, 0.4451576169F, 0.4456489963F, 0.4461404118F, + 0.4466318628F, 0.4471233487F, 0.4476148690F, 0.4481064230F, + 0.4485980103F, 0.4490896302F, 0.4495812821F, 0.4500729654F, + 0.4505646797F, 0.4510564243F, 0.4515481986F, 0.4520400021F, + 0.4525318341F, 0.4530236942F, 0.4535155816F, 0.4540074959F, + 0.4544994365F, 0.4549914028F, 0.4554833941F, 0.4559754100F, + 0.4564674499F, 0.4569595131F, 0.4574515991F, 0.4579437074F, + 0.4584358372F, 0.4589279881F, 0.4594201595F, 0.4599123508F, + 0.4604045615F, 0.4608967908F, 0.4613890383F, 0.4618813034F, + 0.4623735855F, 0.4628658841F, 0.4633581984F, 0.4638505281F, + 0.4643428724F, 0.4648352308F, 0.4653276028F, 0.4658199877F, + 0.4663123849F, 0.4668047940F, 0.4672972143F, 0.4677896451F, + 0.4682820861F, 0.4687745365F, 0.4692669958F, 0.4697594634F, + 0.4702519387F, 0.4707444211F, 0.4712369102F, 0.4717294052F, + 0.4722219056F, 0.4727144109F, 0.4732069204F, 0.4736994336F, + 0.4741919498F, 0.4746844686F, 0.4751769893F, 0.4756695113F, + 0.4761620341F, 0.4766545571F, 0.4771470797F, 0.4776396013F, + 0.4781321213F, 0.4786246392F, 0.4791171544F, 0.4796096663F, + 0.4801021744F, 0.4805946779F, 0.4810871765F, 0.4815796694F, + 0.4820721561F, 0.4825646360F, 0.4830571086F, 0.4835495732F, + 0.4840420293F, 0.4845344763F, 0.4850269136F, 0.4855193407F, + 0.4860117569F, 0.4865041617F, 0.4869965545F, 0.4874889347F, + 0.4879813018F, 0.4884736551F, 0.4889659941F, 0.4894583182F, + 0.4899506268F, 0.4904429193F, 0.4909351952F, 0.4914274538F, + 0.4919196947F, 0.4924119172F, 0.4929041207F, 0.4933963046F, + 0.4938884685F, 0.4943806116F, 0.4948727335F, 0.4953648335F, + 0.4958569110F, 0.4963489656F, 0.4968409965F, 0.4973330032F, + 0.4978249852F, 0.4983169419F, 0.4988088726F, 0.4993007768F, + 0.4997926539F, 0.5002845034F, 0.5007763247F, 0.5012681171F, + 0.5017598801F, 0.5022516132F, 0.5027433157F, 0.5032349871F, + 0.5037266268F, 0.5042182341F, 0.5047098086F, 0.5052013497F, + 0.5056928567F, 0.5061843292F, 0.5066757664F, 0.5071671679F, + 0.5076585330F, 0.5081498613F, 0.5086411520F, 0.5091324047F, + 0.5096236187F, 0.5101147934F, 0.5106059284F, 0.5110970230F, + 0.5115880766F, 0.5120790887F, 0.5125700587F, 0.5130609860F, + 0.5135518700F, 0.5140427102F, 0.5145335059F, 0.5150242566F, + 0.5155149618F, 0.5160056208F, 0.5164962331F, 0.5169867980F, + 0.5174773151F, 0.5179677837F, 0.5184582033F, 0.5189485733F, + 0.5194388931F, 0.5199291621F, 0.5204193798F, 0.5209095455F, + 0.5213996588F, 0.5218897190F, 0.5223797256F, 0.5228696779F, + 0.5233595755F, 0.5238494177F, 0.5243392039F, 0.5248289337F, + 0.5253186063F, 0.5258082213F, 0.5262977781F, 0.5267872760F, + 0.5272767146F, 0.5277660932F, 0.5282554112F, 0.5287446682F, + 0.5292338635F, 0.5297229965F, 0.5302120667F, 0.5307010736F, + 0.5311900164F, 0.5316788947F, 0.5321677079F, 0.5326564554F, + 0.5331451366F, 0.5336337511F, 0.5341222981F, 0.5346107771F, + 0.5350991876F, 0.5355875290F, 0.5360758007F, 0.5365640021F, + 0.5370521327F, 0.5375401920F, 0.5380281792F, 0.5385160939F, + 0.5390039355F, 0.5394917034F, 0.5399793971F, 0.5404670159F, + 0.5409545594F, 0.5414420269F, 0.5419294179F, 0.5424167318F, + 0.5429039680F, 0.5433911261F, 0.5438782053F, 0.5443652051F, + 0.5448521250F, 0.5453389644F, 0.5458257228F, 0.5463123995F, + 0.5467989940F, 0.5472855057F, 0.5477719341F, 0.5482582786F, + 0.5487445387F, 0.5492307137F, 0.5497168031F, 0.5502028063F, + 0.5506887228F, 0.5511745520F, 0.5516602934F, 0.5521459463F, + 0.5526315103F, 0.5531169847F, 0.5536023690F, 0.5540876626F, + 0.5545728649F, 0.5550579755F, 0.5555429937F, 0.5560279189F, + 0.5565127507F, 0.5569974884F, 0.5574821315F, 0.5579666794F, + 0.5584511316F, 0.5589354875F, 0.5594197465F, 0.5599039080F, + 0.5603879716F, 0.5608719367F, 0.5613558026F, 0.5618395689F, + 0.5623232350F, 0.5628068002F, 0.5632902642F, 0.5637736262F, + 0.5642568858F, 0.5647400423F, 0.5652230953F, 0.5657060442F, + 0.5661888883F, 0.5666716272F, 0.5671542603F, 0.5676367870F, + 0.5681192069F, 0.5686015192F, 0.5690837235F, 0.5695658192F, + 0.5700478058F, 0.5705296827F, 0.5710114494F, 0.5714931052F, + 0.5719746497F, 0.5724560822F, 0.5729374023F, 0.5734186094F, + 0.5738997029F, 0.5743806823F, 0.5748615470F, 0.5753422965F, + 0.5758229301F, 0.5763034475F, 0.5767838480F, 0.5772641310F, + 0.5777442960F, 0.5782243426F, 0.5787042700F, 0.5791840778F, + 0.5796637654F, 0.5801433322F, 0.5806227778F, 0.5811021016F, + 0.5815813029F, 0.5820603814F, 0.5825393363F, 0.5830181673F, + 0.5834968737F, 0.5839754549F, 0.5844539105F, 0.5849322399F, + 0.5854104425F, 0.5858885179F, 0.5863664653F, 0.5868442844F, + 0.5873219746F, 0.5877995353F, 0.5882769660F, 0.5887542661F, + 0.5892314351F, 0.5897084724F, 0.5901853776F, 0.5906621500F, + 0.5911387892F, 0.5916152945F, 0.5920916655F, 0.5925679016F, + 0.5930440022F, 0.5935199669F, 0.5939957950F, 0.5944714861F, + 0.5949470396F, 0.5954224550F, 0.5958977317F, 0.5963728692F, + 0.5968478669F, 0.5973227244F, 0.5977974411F, 0.5982720163F, + 0.5987464497F, 0.5992207407F, 0.5996948887F, 0.6001688932F, + 0.6006427537F, 0.6011164696F, 0.6015900405F, 0.6020634657F, + 0.6025367447F, 0.6030098770F, 0.6034828621F, 0.6039556995F, + 0.6044283885F, 0.6049009288F, 0.6053733196F, 0.6058455606F, + 0.6063176512F, 0.6067895909F, 0.6072613790F, 0.6077330152F, + 0.6082044989F, 0.6086758295F, 0.6091470065F, 0.6096180294F, + 0.6100888977F, 0.6105596108F, 0.6110301682F, 0.6115005694F, + 0.6119708139F, 0.6124409011F, 0.6129108305F, 0.6133806017F, + 0.6138502139F, 0.6143196669F, 0.6147889599F, 0.6152580926F, + 0.6157270643F, 0.6161958746F, 0.6166645230F, 0.6171330088F, + 0.6176013317F, 0.6180694910F, 0.6185374863F, 0.6190053171F, + 0.6194729827F, 0.6199404828F, 0.6204078167F, 0.6208749841F, + 0.6213419842F, 0.6218088168F, 0.6222754811F, 0.6227419768F, + 0.6232083032F, 0.6236744600F, 0.6241404465F, 0.6246062622F, + 0.6250719067F, 0.6255373795F, 0.6260026799F, 0.6264678076F, + 0.6269327619F, 0.6273975425F, 0.6278621487F, 0.6283265800F, + 0.6287908361F, 0.6292549163F, 0.6297188201F, 0.6301825471F, + 0.6306460966F, 0.6311094683F, 0.6315726617F, 0.6320356761F, + 0.6324985111F, 0.6329611662F, 0.6334236410F, 0.6338859348F, + 0.6343480472F, 0.6348099777F, 0.6352717257F, 0.6357332909F, + 0.6361946726F, 0.6366558704F, 0.6371168837F, 0.6375777122F, + 0.6380383552F, 0.6384988123F, 0.6389590830F, 0.6394191668F, + 0.6398790631F, 0.6403387716F, 0.6407982916F, 0.6412576228F, + 0.6417167645F, 0.6421757163F, 0.6426344778F, 0.6430930483F, + 0.6435514275F, 0.6440096149F, 0.6444676098F, 0.6449254119F, + 0.6453830207F, 0.6458404356F, 0.6462976562F, 0.6467546820F, + 0.6472115125F, 0.6476681472F, 0.6481245856F, 0.6485808273F, + 0.6490368717F, 0.6494927183F, 0.6499483667F, 0.6504038164F, + 0.6508590670F, 0.6513141178F, 0.6517689684F, 0.6522236185F, + 0.6526780673F, 0.6531323146F, 0.6535863598F, 0.6540402024F, + 0.6544938419F, 0.6549472779F, 0.6554005099F, 0.6558535373F, + 0.6563063598F, 0.6567589769F, 0.6572113880F, 0.6576635927F, + 0.6581155906F, 0.6585673810F, 0.6590189637F, 0.6594703380F, + 0.6599215035F, 0.6603724598F, 0.6608232064F, 0.6612737427F, + 0.6617240684F, 0.6621741829F, 0.6626240859F, 0.6630737767F, + 0.6635232550F, 0.6639725202F, 0.6644215720F, 0.6648704098F, + 0.6653190332F, 0.6657674417F, 0.6662156348F, 0.6666636121F, + 0.6671113731F, 0.6675589174F, 0.6680062445F, 0.6684533538F, + 0.6689002450F, 0.6693469177F, 0.6697933712F, 0.6702396052F, + 0.6706856193F, 0.6711314129F, 0.6715769855F, 0.6720223369F, + 0.6724674664F, 0.6729123736F, 0.6733570581F, 0.6738015194F, + 0.6742457570F, 0.6746897706F, 0.6751335596F, 0.6755771236F, + 0.6760204621F, 0.6764635747F, 0.6769064609F, 0.6773491204F, + 0.6777915525F, 0.6782337570F, 0.6786757332F, 0.6791174809F, + 0.6795589995F, 0.6800002886F, 0.6804413477F, 0.6808821765F, + 0.6813227743F, 0.6817631409F, 0.6822032758F, 0.6826431785F, + 0.6830828485F, 0.6835222855F, 0.6839614890F, 0.6844004585F, + 0.6848391936F, 0.6852776939F, 0.6857159589F, 0.6861539883F, + 0.6865917815F, 0.6870293381F, 0.6874666576F, 0.6879037398F, + 0.6883405840F, 0.6887771899F, 0.6892135571F, 0.6896496850F, + 0.6900855733F, 0.6905212216F, 0.6909566294F, 0.6913917963F, + 0.6918267218F, 0.6922614055F, 0.6926958471F, 0.6931300459F, + 0.6935640018F, 0.6939977141F, 0.6944311825F, 0.6948644066F, + 0.6952973859F, 0.6957301200F, 0.6961626085F, 0.6965948510F, + 0.6970268470F, 0.6974585961F, 0.6978900980F, 0.6983213521F, + 0.6987523580F, 0.6991831154F, 0.6996136238F, 0.7000438828F, + 0.7004738921F, 0.7009036510F, 0.7013331594F, 0.7017624166F, + 0.7021914224F, 0.7026201763F, 0.7030486779F, 0.7034769268F, + 0.7039049226F, 0.7043326648F, 0.7047601531F, 0.7051873870F, + 0.7056143662F, 0.7060410902F, 0.7064675586F, 0.7068937711F, + 0.7073197271F, 0.7077454264F, 0.7081708684F, 0.7085960529F, + 0.7090209793F, 0.7094456474F, 0.7098700566F, 0.7102942066F, + 0.7107180970F, 0.7111417274F, 0.7115650974F, 0.7119882066F, + 0.7124110545F, 0.7128336409F, 0.7132559653F, 0.7136780272F, + 0.7140998264F, 0.7145213624F, 0.7149426348F, 0.7153636433F, + 0.7157843874F, 0.7162048668F, 0.7166250810F, 0.7170450296F, + 0.7174647124F, 0.7178841289F, 0.7183032786F, 0.7187221613F, + 0.7191407765F, 0.7195591239F, 0.7199772030F, 0.7203950135F, + 0.7208125550F, 0.7212298271F, 0.7216468294F, 0.7220635616F, + 0.7224800233F, 0.7228962140F, 0.7233121335F, 0.7237277813F, + 0.7241431571F, 0.7245582604F, 0.7249730910F, 0.7253876484F, + 0.7258019322F, 0.7262159422F, 0.7266296778F, 0.7270431388F, + 0.7274563247F, 0.7278692353F, 0.7282818700F, 0.7286942287F, + 0.7291063108F, 0.7295181160F, 0.7299296440F, 0.7303408944F, + 0.7307518669F, 0.7311625609F, 0.7315729763F, 0.7319831126F, + 0.7323929695F, 0.7328025466F, 0.7332118435F, 0.7336208600F, + 0.7340295955F, 0.7344380499F, 0.7348462226F, 0.7352541134F, + 0.7356617220F, 0.7360690478F, 0.7364760907F, 0.7368828502F, + 0.7372893259F, 0.7376955176F, 0.7381014249F, 0.7385070475F, + 0.7389123849F, 0.7393174368F, 0.7397222029F, 0.7401266829F, + 0.7405308763F, 0.7409347829F, 0.7413384023F, 0.7417417341F, + 0.7421447780F, 0.7425475338F, 0.7429500009F, 0.7433521791F, + 0.7437540681F, 0.7441556674F, 0.7445569769F, 0.7449579960F, + 0.7453587245F, 0.7457591621F, 0.7461593084F, 0.7465591631F, + 0.7469587259F, 0.7473579963F, 0.7477569741F, 0.7481556590F, + 0.7485540506F, 0.7489521486F, 0.7493499526F, 0.7497474623F, + 0.7501446775F, 0.7505415977F, 0.7509382227F, 0.7513345521F, + 0.7517305856F, 0.7521263229F, 0.7525217636F, 0.7529169074F, + 0.7533117541F, 0.7537063032F, 0.7541005545F, 0.7544945076F, + 0.7548881623F, 0.7552815182F, 0.7556745749F, 0.7560673323F, + 0.7564597899F, 0.7568519474F, 0.7572438046F, 0.7576353611F, + 0.7580266166F, 0.7584175708F, 0.7588082235F, 0.7591985741F, + 0.7595886226F, 0.7599783685F, 0.7603678116F, 0.7607569515F, + 0.7611457879F, 0.7615343206F, 0.7619225493F, 0.7623104735F, + 0.7626980931F, 0.7630854078F, 0.7634724171F, 0.7638591209F, + 0.7642455188F, 0.7646316106F, 0.7650173959F, 0.7654028744F, + 0.7657880459F, 0.7661729100F, 0.7665574664F, 0.7669417150F, + 0.7673256553F, 0.7677092871F, 0.7680926100F, 0.7684756239F, + 0.7688583284F, 0.7692407232F, 0.7696228080F, 0.7700045826F, + 0.7703860467F, 0.7707671999F, 0.7711480420F, 0.7715285728F, + 0.7719087918F, 0.7722886989F, 0.7726682938F, 0.7730475762F, + 0.7734265458F, 0.7738052023F, 0.7741835454F, 0.7745615750F, + 0.7749392906F, 0.7753166921F, 0.7756937791F, 0.7760705514F, + 0.7764470087F, 0.7768231508F, 0.7771989773F, 0.7775744880F, + 0.7779496827F, 0.7783245610F, 0.7786991227F, 0.7790733676F, + 0.7794472953F, 0.7798209056F, 0.7801941982F, 0.7805671729F, + 0.7809398294F, 0.7813121675F, 0.7816841869F, 0.7820558873F, + 0.7824272684F, 0.7827983301F, 0.7831690720F, 0.7835394940F, + 0.7839095957F, 0.7842793768F, 0.7846488373F, 0.7850179767F, + 0.7853867948F, 0.7857552914F, 0.7861234663F, 0.7864913191F, + 0.7868588497F, 0.7872260578F, 0.7875929431F, 0.7879595055F, + 0.7883257445F, 0.7886916601F, 0.7890572520F, 0.7894225198F, + 0.7897874635F, 0.7901520827F, 0.7905163772F, 0.7908803468F, + 0.7912439912F, 0.7916073102F, 0.7919703035F, 0.7923329710F, + 0.7926953124F, 0.7930573274F, 0.7934190158F, 0.7937803774F, + 0.7941414120F, 0.7945021193F, 0.7948624991F, 0.7952225511F, + 0.7955822752F, 0.7959416711F, 0.7963007387F, 0.7966594775F, + 0.7970178875F, 0.7973759685F, 0.7977337201F, 0.7980911422F, + 0.7984482346F, 0.7988049970F, 0.7991614292F, 0.7995175310F, + 0.7998733022F, 0.8002287426F, 0.8005838519F, 0.8009386299F, + 0.8012930765F, 0.8016471914F, 0.8020009744F, 0.8023544253F, + 0.8027075438F, 0.8030603298F, 0.8034127831F, 0.8037649035F, + 0.8041166906F, 0.8044681445F, 0.8048192647F, 0.8051700512F, + 0.8055205038F, 0.8058706222F, 0.8062204062F, 0.8065698556F, + 0.8069189702F, 0.8072677499F, 0.8076161944F, 0.8079643036F, + 0.8083120772F, 0.8086595151F, 0.8090066170F, 0.8093533827F, + 0.8096998122F, 0.8100459051F, 0.8103916613F, 0.8107370806F, + 0.8110821628F, 0.8114269077F, 0.8117713151F, 0.8121153849F, + 0.8124591169F, 0.8128025108F, 0.8131455666F, 0.8134882839F, + 0.8138306627F, 0.8141727027F, 0.8145144038F, 0.8148557658F, + 0.8151967886F, 0.8155374718F, 0.8158778154F, 0.8162178192F, + 0.8165574830F, 0.8168968067F, 0.8172357900F, 0.8175744328F, + 0.8179127349F, 0.8182506962F, 0.8185883164F, 0.8189255955F, + 0.8192625332F, 0.8195991295F, 0.8199353840F, 0.8202712967F, + 0.8206068673F, 0.8209420958F, 0.8212769820F, 0.8216115256F, + 0.8219457266F, 0.8222795848F, 0.8226131000F, 0.8229462721F, + 0.8232791009F, 0.8236115863F, 0.8239437280F, 0.8242755260F, + 0.8246069801F, 0.8249380901F, 0.8252688559F, 0.8255992774F, + 0.8259293544F, 0.8262590867F, 0.8265884741F, 0.8269175167F, + 0.8272462141F, 0.8275745663F, 0.8279025732F, 0.8282302344F, + 0.8285575501F, 0.8288845199F, 0.8292111437F, 0.8295374215F, + 0.8298633530F, 0.8301889382F, 0.8305141768F, 0.8308390688F, + 0.8311636141F, 0.8314878124F, 0.8318116637F, 0.8321351678F, + 0.8324583246F, 0.8327811340F, 0.8331035957F, 0.8334257098F, + 0.8337474761F, 0.8340688944F, 0.8343899647F, 0.8347106867F, + 0.8350310605F, 0.8353510857F, 0.8356707624F, 0.8359900904F, + 0.8363090696F, 0.8366276999F, 0.8369459811F, 0.8372639131F, + 0.8375814958F, 0.8378987292F, 0.8382156130F, 0.8385321472F, + 0.8388483316F, 0.8391641662F, 0.8394796508F, 0.8397947853F, + 0.8401095697F, 0.8404240037F, 0.8407380873F, 0.8410518204F, + 0.8413652029F, 0.8416782347F, 0.8419909156F, 0.8423032456F, + 0.8426152245F, 0.8429268523F, 0.8432381289F, 0.8435490541F, + 0.8438596279F, 0.8441698502F, 0.8444797208F, 0.8447892396F, + 0.8450984067F, 0.8454072218F, 0.8457156849F, 0.8460237959F, + 0.8463315547F, 0.8466389612F, 0.8469460154F, 0.8472527170F, + 0.8475590661F, 0.8478650625F, 0.8481707063F, 0.8484759971F, + 0.8487809351F, 0.8490855201F, 0.8493897521F, 0.8496936308F, + 0.8499971564F, 0.8503003286F, 0.8506031474F, 0.8509056128F, + 0.8512077246F, 0.8515094828F, 0.8518108872F, 0.8521119379F, + 0.8524126348F, 0.8527129777F, 0.8530129666F, 0.8533126015F, + 0.8536118822F, 0.8539108087F, 0.8542093809F, 0.8545075988F, + 0.8548054623F, 0.8551029712F, 0.8554001257F, 0.8556969255F, + 0.8559933707F, 0.8562894611F, 0.8565851968F, 0.8568805775F, + 0.8571756034F, 0.8574702743F, 0.8577645902F, 0.8580585509F, + 0.8583521566F, 0.8586454070F, 0.8589383021F, 0.8592308420F, + 0.8595230265F, 0.8598148556F, 0.8601063292F, 0.8603974473F, + 0.8606882098F, 0.8609786167F, 0.8612686680F, 0.8615583636F, + 0.8618477034F, 0.8621366874F, 0.8624253156F, 0.8627135878F, + 0.8630015042F, 0.8632890646F, 0.8635762690F, 0.8638631173F, + 0.8641496096F, 0.8644357457F, 0.8647215257F, 0.8650069495F, + 0.8652920171F, 0.8655767283F, 0.8658610833F, 0.8661450820F, + 0.8664287243F, 0.8667120102F, 0.8669949397F, 0.8672775127F, + 0.8675597293F, 0.8678415894F, 0.8681230929F, 0.8684042398F, + 0.8686850302F, 0.8689654640F, 0.8692455412F, 0.8695252617F, + 0.8698046255F, 0.8700836327F, 0.8703622831F, 0.8706405768F, + 0.8709185138F, 0.8711960940F, 0.8714733174F, 0.8717501840F, + 0.8720266939F, 0.8723028469F, 0.8725786430F, 0.8728540824F, + 0.8731291648F, 0.8734038905F, 0.8736782592F, 0.8739522711F, + 0.8742259261F, 0.8744992242F, 0.8747721653F, 0.8750447496F, + 0.8753169770F, 0.8755888475F, 0.8758603611F, 0.8761315177F, + 0.8764023175F, 0.8766727603F, 0.8769428462F, 0.8772125752F, + 0.8774819474F, 0.8777509626F, 0.8780196209F, 0.8782879224F, + 0.8785558669F, 0.8788234546F, 0.8790906854F, 0.8793575594F, + 0.8796240765F, 0.8798902368F, 0.8801560403F, 0.8804214870F, + 0.8806865768F, 0.8809513099F, 0.8812156863F, 0.8814797059F, + 0.8817433687F, 0.8820066749F, 0.8822696243F, 0.8825322171F, + 0.8827944532F, 0.8830563327F, 0.8833178556F, 0.8835790219F, + 0.8838398316F, 0.8841002848F, 0.8843603815F, 0.8846201217F, + 0.8848795054F, 0.8851385327F, 0.8853972036F, 0.8856555182F, + 0.8859134764F, 0.8861710783F, 0.8864283239F, 0.8866852133F, + 0.8869417464F, 0.8871979234F, 0.8874537443F, 0.8877092090F, + 0.8879643177F, 0.8882190704F, 0.8884734671F, 0.8887275078F, + 0.8889811927F, 0.8892345216F, 0.8894874948F, 0.8897401122F, + 0.8899923738F, 0.8902442798F, 0.8904958301F, 0.8907470248F, + 0.8909978640F, 0.8912483477F, 0.8914984759F, 0.8917482487F, + 0.8919976662F, 0.8922467284F, 0.8924954353F, 0.8927437871F, + 0.8929917837F, 0.8932394252F, 0.8934867118F, 0.8937336433F, + 0.8939802199F, 0.8942264417F, 0.8944723087F, 0.8947178210F, + 0.8949629785F, 0.8952077815F, 0.8954522299F, 0.8956963239F, + 0.8959400634F, 0.8961834486F, 0.8964264795F, 0.8966691561F, + 0.8969114786F, 0.8971534470F, 0.8973950614F, 0.8976363219F, + 0.8978772284F, 0.8981177812F, 0.8983579802F, 0.8985978256F, + 0.8988373174F, 0.8990764556F, 0.8993152405F, 0.8995536720F, + 0.8997917502F, 0.9000294751F, 0.9002668470F, 0.9005038658F, + 0.9007405317F, 0.9009768446F, 0.9012128048F, 0.9014484123F, + 0.9016836671F, 0.9019185693F, 0.9021531191F, 0.9023873165F, + 0.9026211616F, 0.9028546546F, 0.9030877954F, 0.9033205841F, + 0.9035530210F, 0.9037851059F, 0.9040168392F, 0.9042482207F, + 0.9044792507F, 0.9047099293F, 0.9049402564F, 0.9051702323F, + 0.9053998569F, 0.9056291305F, 0.9058580531F, 0.9060866248F, + 0.9063148457F, 0.9065427159F, 0.9067702355F, 0.9069974046F, + 0.9072242233F, 0.9074506917F, 0.9076768100F, 0.9079025782F, + 0.9081279964F, 0.9083530647F, 0.9085777833F, 0.9088021523F, + 0.9090261717F, 0.9092498417F, 0.9094731623F, 0.9096961338F, + 0.9099187561F, 0.9101410295F, 0.9103629540F, 0.9105845297F, + 0.9108057568F, 0.9110266354F, 0.9112471656F, 0.9114673475F, + 0.9116871812F, 0.9119066668F, 0.9121258046F, 0.9123445945F, + 0.9125630367F, 0.9127811314F, 0.9129988786F, 0.9132162785F, + 0.9134333312F, 0.9136500368F, 0.9138663954F, 0.9140824073F, + 0.9142980724F, 0.9145133910F, 0.9147283632F, 0.9149429890F, + 0.9151572687F, 0.9153712023F, 0.9155847900F, 0.9157980319F, + 0.9160109282F, 0.9162234790F, 0.9164356844F, 0.9166475445F, + 0.9168590595F, 0.9170702296F, 0.9172810548F, 0.9174915354F, + 0.9177016714F, 0.9179114629F, 0.9181209102F, 0.9183300134F, + 0.9185387726F, 0.9187471879F, 0.9189552595F, 0.9191629876F, + 0.9193703723F, 0.9195774136F, 0.9197841119F, 0.9199904672F, + 0.9201964797F, 0.9204021495F, 0.9206074767F, 0.9208124616F, + 0.9210171043F, 0.9212214049F, 0.9214253636F, 0.9216289805F, + 0.9218322558F, 0.9220351896F, 0.9222377821F, 0.9224400335F, + 0.9226419439F, 0.9228435134F, 0.9230447423F, 0.9232456307F, + 0.9234461787F, 0.9236463865F, 0.9238462543F, 0.9240457822F, + 0.9242449704F, 0.9244438190F, 0.9246423282F, 0.9248404983F, + 0.9250383293F, 0.9252358214F, 0.9254329747F, 0.9256297896F, + 0.9258262660F, 0.9260224042F, 0.9262182044F, 0.9264136667F, + 0.9266087913F, 0.9268035783F, 0.9269980280F, 0.9271921405F, + 0.9273859160F, 0.9275793546F, 0.9277724566F, 0.9279652221F, + 0.9281576513F, 0.9283497443F, 0.9285415014F, 0.9287329227F, + 0.9289240084F, 0.9291147586F, 0.9293051737F, 0.9294952536F, + 0.9296849987F, 0.9298744091F, 0.9300634850F, 0.9302522266F, + 0.9304406340F, 0.9306287074F, 0.9308164471F, 0.9310038532F, + 0.9311909259F, 0.9313776654F, 0.9315640719F, 0.9317501455F, + 0.9319358865F, 0.9321212951F, 0.9323063713F, 0.9324911155F, + 0.9326755279F, 0.9328596085F, 0.9330433577F, 0.9332267756F, + 0.9334098623F, 0.9335926182F, 0.9337750434F, 0.9339571380F, + 0.9341389023F, 0.9343203366F, 0.9345014409F, 0.9346822155F, + 0.9348626606F, 0.9350427763F, 0.9352225630F, 0.9354020207F, + 0.9355811498F, 0.9357599503F, 0.9359384226F, 0.9361165667F, + 0.9362943830F, 0.9364718716F, 0.9366490327F, 0.9368258666F, + 0.9370023733F, 0.9371785533F, 0.9373544066F, 0.9375299335F, + 0.9377051341F, 0.9378800087F, 0.9380545576F, 0.9382287809F, + 0.9384026787F, 0.9385762515F, 0.9387494993F, 0.9389224223F, + 0.9390950209F, 0.9392672951F, 0.9394392453F, 0.9396108716F, + 0.9397821743F, 0.9399531536F, 0.9401238096F, 0.9402941427F, + 0.9404641530F, 0.9406338407F, 0.9408032061F, 0.9409722495F, + 0.9411409709F, 0.9413093707F, 0.9414774491F, 0.9416452062F, + 0.9418126424F, 0.9419797579F, 0.9421465528F, 0.9423130274F, + 0.9424791819F, 0.9426450166F, 0.9428105317F, 0.9429757274F, + 0.9431406039F, 0.9433051616F, 0.9434694005F, 0.9436333209F, + 0.9437969232F, 0.9439602074F, 0.9441231739F, 0.9442858229F, + 0.9444481545F, 0.9446101691F, 0.9447718669F, 0.9449332481F, + 0.9450943129F, 0.9452550617F, 0.9454154945F, 0.9455756118F, + 0.9457354136F, 0.9458949003F, 0.9460540721F, 0.9462129292F, + 0.9463714719F, 0.9465297003F, 0.9466876149F, 0.9468452157F, + 0.9470025031F, 0.9471594772F, 0.9473161384F, 0.9474724869F, + 0.9476285229F, 0.9477842466F, 0.9479396584F, 0.9480947585F, + 0.9482495470F, 0.9484040243F, 0.9485581906F, 0.9487120462F, + 0.9488655913F, 0.9490188262F, 0.9491717511F, 0.9493243662F, + 0.9494766718F, 0.9496286683F, 0.9497803557F, 0.9499317345F, + 0.9500828047F, 0.9502335668F, 0.9503840209F, 0.9505341673F, + 0.9506840062F, 0.9508335380F, 0.9509827629F, 0.9511316810F, + 0.9512802928F, 0.9514285984F, 0.9515765982F, 0.9517242923F, + 0.9518716810F, 0.9520187646F, 0.9521655434F, 0.9523120176F, + 0.9524581875F, 0.9526040534F, 0.9527496154F, 0.9528948739F, + 0.9530398292F, 0.9531844814F, 0.9533288310F, 0.9534728780F, + 0.9536166229F, 0.9537600659F, 0.9539032071F, 0.9540460470F, + 0.9541885858F, 0.9543308237F, 0.9544727611F, 0.9546143981F, + 0.9547557351F, 0.9548967723F, 0.9550375100F, 0.9551779485F, + 0.9553180881F, 0.9554579290F, 0.9555974714F, 0.9557367158F, + 0.9558756623F, 0.9560143112F, 0.9561526628F, 0.9562907174F, + 0.9564284752F, 0.9565659366F, 0.9567031017F, 0.9568399710F, + 0.9569765446F, 0.9571128229F, 0.9572488061F, 0.9573844944F, + 0.9575198883F, 0.9576549879F, 0.9577897936F, 0.9579243056F, + 0.9580585242F, 0.9581924497F, 0.9583260824F, 0.9584594226F, + 0.9585924705F, 0.9587252264F, 0.9588576906F, 0.9589898634F, + 0.9591217452F, 0.9592533360F, 0.9593846364F, 0.9595156465F, + 0.9596463666F, 0.9597767971F, 0.9599069382F, 0.9600367901F, + 0.9601663533F, 0.9602956279F, 0.9604246143F, 0.9605533128F, + 0.9606817236F, 0.9608098471F, 0.9609376835F, 0.9610652332F, + 0.9611924963F, 0.9613194733F, 0.9614461644F, 0.9615725699F, + 0.9616986901F, 0.9618245253F, 0.9619500757F, 0.9620753418F, + 0.9622003238F, 0.9623250219F, 0.9624494365F, 0.9625735679F, + 0.9626974163F, 0.9628209821F, 0.9629442656F, 0.9630672671F, + 0.9631899868F, 0.9633124251F, 0.9634345822F, 0.9635564585F, + 0.9636780543F, 0.9637993699F, 0.9639204056F, 0.9640411616F, + 0.9641616383F, 0.9642818359F, 0.9644017549F, 0.9645213955F, + 0.9646407579F, 0.9647598426F, 0.9648786497F, 0.9649971797F, + 0.9651154328F, 0.9652334092F, 0.9653511095F, 0.9654685337F, + 0.9655856823F, 0.9657025556F, 0.9658191538F, 0.9659354773F, + 0.9660515263F, 0.9661673013F, 0.9662828024F, 0.9663980300F, + 0.9665129845F, 0.9666276660F, 0.9667420750F, 0.9668562118F, + 0.9669700766F, 0.9670836698F, 0.9671969917F, 0.9673100425F, + 0.9674228227F, 0.9675353325F, 0.9676475722F, 0.9677595422F, + 0.9678712428F, 0.9679826742F, 0.9680938368F, 0.9682047309F, + 0.9683153569F, 0.9684257150F, 0.9685358056F, 0.9686456289F, + 0.9687551853F, 0.9688644752F, 0.9689734987F, 0.9690822564F, + 0.9691907483F, 0.9692989750F, 0.9694069367F, 0.9695146337F, + 0.9696220663F, 0.9697292349F, 0.9698361398F, 0.9699427813F, + 0.9700491597F, 0.9701552754F, 0.9702611286F, 0.9703667197F, + 0.9704720490F, 0.9705771169F, 0.9706819236F, 0.9707864695F, + 0.9708907549F, 0.9709947802F, 0.9710985456F, 0.9712020514F, + 0.9713052981F, 0.9714082859F, 0.9715110151F, 0.9716134862F, + 0.9717156993F, 0.9718176549F, 0.9719193532F, 0.9720207946F, + 0.9721219794F, 0.9722229080F, 0.9723235806F, 0.9724239976F, + 0.9725241593F, 0.9726240661F, 0.9727237183F, 0.9728231161F, + 0.9729222601F, 0.9730211503F, 0.9731197873F, 0.9732181713F, + 0.9733163027F, 0.9734141817F, 0.9735118088F, 0.9736091842F, + 0.9737063083F, 0.9738031814F, 0.9738998039F, 0.9739961760F, + 0.9740922981F, 0.9741881706F, 0.9742837938F, 0.9743791680F, + 0.9744742935F, 0.9745691707F, 0.9746637999F, 0.9747581814F, + 0.9748523157F, 0.9749462029F, 0.9750398435F, 0.9751332378F, + 0.9752263861F, 0.9753192887F, 0.9754119461F, 0.9755043585F, + 0.9755965262F, 0.9756884496F, 0.9757801291F, 0.9758715650F, + 0.9759627575F, 0.9760537071F, 0.9761444141F, 0.9762348789F, + 0.9763251016F, 0.9764150828F, 0.9765048228F, 0.9765943218F, + 0.9766835802F, 0.9767725984F, 0.9768613767F, 0.9769499154F, + 0.9770382149F, 0.9771262755F, 0.9772140976F, 0.9773016815F, + 0.9773890275F, 0.9774761360F, 0.9775630073F, 0.9776496418F, + 0.9777360398F, 0.9778222016F, 0.9779081277F, 0.9779938182F, + 0.9780792736F, 0.9781644943F, 0.9782494805F, 0.9783342326F, + 0.9784187509F, 0.9785030359F, 0.9785870877F, 0.9786709069F, + 0.9787544936F, 0.9788378484F, 0.9789209714F, 0.9790038631F, + 0.9790865238F, 0.9791689538F, 0.9792511535F, 0.9793331232F, + 0.9794148633F, 0.9794963742F, 0.9795776561F, 0.9796587094F, + 0.9797395345F, 0.9798201316F, 0.9799005013F, 0.9799806437F, + 0.9800605593F, 0.9801402483F, 0.9802197112F, 0.9802989483F, + 0.9803779600F, 0.9804567465F, 0.9805353082F, 0.9806136455F, + 0.9806917587F, 0.9807696482F, 0.9808473143F, 0.9809247574F, + 0.9810019778F, 0.9810789759F, 0.9811557519F, 0.9812323064F, + 0.9813086395F, 0.9813847517F, 0.9814606433F, 0.9815363147F, + 0.9816117662F, 0.9816869981F, 0.9817620108F, 0.9818368047F, + 0.9819113801F, 0.9819857374F, 0.9820598769F, 0.9821337989F, + 0.9822075038F, 0.9822809920F, 0.9823542638F, 0.9824273195F, + 0.9825001596F, 0.9825727843F, 0.9826451940F, 0.9827173891F, + 0.9827893700F, 0.9828611368F, 0.9829326901F, 0.9830040302F, + 0.9830751574F, 0.9831460720F, 0.9832167745F, 0.9832872652F, + 0.9833575444F, 0.9834276124F, 0.9834974697F, 0.9835671166F, + 0.9836365535F, 0.9837057806F, 0.9837747983F, 0.9838436071F, + 0.9839122072F, 0.9839805990F, 0.9840487829F, 0.9841167591F, + 0.9841845282F, 0.9842520903F, 0.9843194459F, 0.9843865953F, + 0.9844535389F, 0.9845202771F, 0.9845868101F, 0.9846531383F, + 0.9847192622F, 0.9847851820F, 0.9848508980F, 0.9849164108F, + 0.9849817205F, 0.9850468276F, 0.9851117324F, 0.9851764352F, + 0.9852409365F, 0.9853052366F, 0.9853693358F, 0.9854332344F, + 0.9854969330F, 0.9855604317F, 0.9856237309F, 0.9856868310F, + 0.9857497325F, 0.9858124355F, 0.9858749404F, 0.9859372477F, + 0.9859993577F, 0.9860612707F, 0.9861229871F, 0.9861845072F, + 0.9862458315F, 0.9863069601F, 0.9863678936F, 0.9864286322F, + 0.9864891764F, 0.9865495264F, 0.9866096826F, 0.9866696454F, + 0.9867294152F, 0.9867889922F, 0.9868483769F, 0.9869075695F, + 0.9869665706F, 0.9870253803F, 0.9870839991F, 0.9871424273F, + 0.9872006653F, 0.9872587135F, 0.9873165721F, 0.9873742415F, + 0.9874317222F, 0.9874890144F, 0.9875461185F, 0.9876030348F, + 0.9876597638F, 0.9877163057F, 0.9877726610F, 0.9878288300F, + 0.9878848130F, 0.9879406104F, 0.9879962225F, 0.9880516497F, + 0.9881068924F, 0.9881619509F, 0.9882168256F, 0.9882715168F, + 0.9883260249F, 0.9883803502F, 0.9884344931F, 0.9884884539F, + 0.9885422331F, 0.9885958309F, 0.9886492477F, 0.9887024838F, + 0.9887555397F, 0.9888084157F, 0.9888611120F, 0.9889136292F, + 0.9889659675F, 0.9890181273F, 0.9890701089F, 0.9891219128F, + 0.9891735392F, 0.9892249885F, 0.9892762610F, 0.9893273572F, + 0.9893782774F, 0.9894290219F, 0.9894795911F, 0.9895299853F, + 0.9895802049F, 0.9896302502F, 0.9896801217F, 0.9897298196F, + 0.9897793443F, 0.9898286961F, 0.9898778755F, 0.9899268828F, + 0.9899757183F, 0.9900243823F, 0.9900728753F, 0.9901211976F, + 0.9901693495F, 0.9902173314F, 0.9902651436F, 0.9903127865F, + 0.9903602605F, 0.9904075659F, 0.9904547031F, 0.9905016723F, + 0.9905484740F, 0.9905951086F, 0.9906415763F, 0.9906878775F, + 0.9907340126F, 0.9907799819F, 0.9908257858F, 0.9908714247F, + 0.9909168988F, 0.9909622086F, 0.9910073543F, 0.9910523364F, + 0.9910971552F, 0.9911418110F, 0.9911863042F, 0.9912306351F, + 0.9912748042F, 0.9913188117F, 0.9913626580F, 0.9914063435F, + 0.9914498684F, 0.9914932333F, 0.9915364383F, 0.9915794839F, + 0.9916223703F, 0.9916650981F, 0.9917076674F, 0.9917500787F, + 0.9917923323F, 0.9918344286F, 0.9918763679F, 0.9919181505F, + 0.9919597769F, 0.9920012473F, 0.9920425621F, 0.9920837217F, + 0.9921247263F, 0.9921655765F, 0.9922062724F, 0.9922468145F, + 0.9922872030F, 0.9923274385F, 0.9923675211F, 0.9924074513F, + 0.9924472294F, 0.9924868557F, 0.9925263306F, 0.9925656544F, + 0.9926048275F, 0.9926438503F, 0.9926827230F, 0.9927214461F, + 0.9927600199F, 0.9927984446F, 0.9928367208F, 0.9928748486F, + 0.9929128285F, 0.9929506608F, 0.9929883459F, 0.9930258841F, + 0.9930632757F, 0.9931005211F, 0.9931376207F, 0.9931745747F, + 0.9932113836F, 0.9932480476F, 0.9932845671F, 0.9933209425F, + 0.9933571742F, 0.9933932623F, 0.9934292074F, 0.9934650097F, + 0.9935006696F, 0.9935361874F, 0.9935715635F, 0.9936067982F, + 0.9936418919F, 0.9936768448F, 0.9937116574F, 0.9937463300F, + 0.9937808629F, 0.9938152565F, 0.9938495111F, 0.9938836271F, + 0.9939176047F, 0.9939514444F, 0.9939851465F, 0.9940187112F, + 0.9940521391F, 0.9940854303F, 0.9941185853F, 0.9941516044F, + 0.9941844879F, 0.9942172361F, 0.9942498495F, 0.9942823283F, + 0.9943146729F, 0.9943468836F, 0.9943789608F, 0.9944109047F, + 0.9944427158F, 0.9944743944F, 0.9945059408F, 0.9945373553F, + 0.9945686384F, 0.9945997902F, 0.9946308112F, 0.9946617017F, + 0.9946924621F, 0.9947230926F, 0.9947535937F, 0.9947839656F, + 0.9948142086F, 0.9948443232F, 0.9948743097F, 0.9949041683F, + 0.9949338995F, 0.9949635035F, 0.9949929807F, 0.9950223315F, + 0.9950515561F, 0.9950806549F, 0.9951096282F, 0.9951384764F, + 0.9951671998F, 0.9951957987F, 0.9952242735F, 0.9952526245F, + 0.9952808520F, 0.9953089564F, 0.9953369380F, 0.9953647971F, + 0.9953925340F, 0.9954201491F, 0.9954476428F, 0.9954750153F, + 0.9955022670F, 0.9955293981F, 0.9955564092F, 0.9955833003F, + 0.9956100720F, 0.9956367245F, 0.9956632582F, 0.9956896733F, + 0.9957159703F, 0.9957421494F, 0.9957682110F, 0.9957941553F, + 0.9958199828F, 0.9958456937F, 0.9958712884F, 0.9958967672F, + 0.9959221305F, 0.9959473784F, 0.9959725115F, 0.9959975300F, + 0.9960224342F, 0.9960472244F, 0.9960719011F, 0.9960964644F, + 0.9961209148F, 0.9961452525F, 0.9961694779F, 0.9961935913F, + 0.9962175930F, 0.9962414834F, 0.9962652627F, 0.9962889313F, + 0.9963124895F, 0.9963359377F, 0.9963592761F, 0.9963825051F, + 0.9964056250F, 0.9964286361F, 0.9964515387F, 0.9964743332F, + 0.9964970198F, 0.9965195990F, 0.9965420709F, 0.9965644360F, + 0.9965866946F, 0.9966088469F, 0.9966308932F, 0.9966528340F, + 0.9966746695F, 0.9966964001F, 0.9967180260F, 0.9967395475F, + 0.9967609651F, 0.9967822789F, 0.9968034894F, 0.9968245968F, + 0.9968456014F, 0.9968665036F, 0.9968873037F, 0.9969080019F, + 0.9969285987F, 0.9969490942F, 0.9969694889F, 0.9969897830F, + 0.9970099769F, 0.9970300708F, 0.9970500651F, 0.9970699601F, + 0.9970897561F, 0.9971094533F, 0.9971290522F, 0.9971485531F, + 0.9971679561F, 0.9971872617F, 0.9972064702F, 0.9972255818F, + 0.9972445968F, 0.9972635157F, 0.9972823386F, 0.9973010659F, + 0.9973196980F, 0.9973382350F, 0.9973566773F, 0.9973750253F, + 0.9973932791F, 0.9974114392F, 0.9974295059F, 0.9974474793F, + 0.9974653599F, 0.9974831480F, 0.9975008438F, 0.9975184476F, + 0.9975359598F, 0.9975533806F, 0.9975707104F, 0.9975879495F, + 0.9976050981F, 0.9976221566F, 0.9976391252F, 0.9976560043F, + 0.9976727941F, 0.9976894950F, 0.9977061073F, 0.9977226312F, + 0.9977390671F, 0.9977554152F, 0.9977716759F, 0.9977878495F, + 0.9978039361F, 0.9978199363F, 0.9978358501F, 0.9978516780F, + 0.9978674202F, 0.9978830771F, 0.9978986488F, 0.9979141358F, + 0.9979295383F, 0.9979448566F, 0.9979600909F, 0.9979752417F, + 0.9979903091F, 0.9980052936F, 0.9980201952F, 0.9980350145F, + 0.9980497515F, 0.9980644067F, 0.9980789804F, 0.9980934727F, + 0.9981078841F, 0.9981222147F, 0.9981364649F, 0.9981506350F, + 0.9981647253F, 0.9981787360F, 0.9981926674F, 0.9982065199F, + 0.9982202936F, 0.9982339890F, 0.9982476062F, 0.9982611456F, + 0.9982746074F, 0.9982879920F, 0.9983012996F, 0.9983145304F, + 0.9983276849F, 0.9983407632F, 0.9983537657F, 0.9983666926F, + 0.9983795442F, 0.9983923208F, 0.9984050226F, 0.9984176501F, + 0.9984302033F, 0.9984426827F, 0.9984550884F, 0.9984674208F, + 0.9984796802F, 0.9984918667F, 0.9985039808F, 0.9985160227F, + 0.9985279926F, 0.9985398909F, 0.9985517177F, 0.9985634734F, + 0.9985751583F, 0.9985867727F, 0.9985983167F, 0.9986097907F, + 0.9986211949F, 0.9986325297F, 0.9986437953F, 0.9986549919F, + 0.9986661199F, 0.9986771795F, 0.9986881710F, 0.9986990946F, + 0.9987099507F, 0.9987207394F, 0.9987314611F, 0.9987421161F, + 0.9987527045F, 0.9987632267F, 0.9987736829F, 0.9987840734F, + 0.9987943985F, 0.9988046584F, 0.9988148534F, 0.9988249838F, + 0.9988350498F, 0.9988450516F, 0.9988549897F, 0.9988648641F, + 0.9988746753F, 0.9988844233F, 0.9988941086F, 0.9989037313F, + 0.9989132918F, 0.9989227902F, 0.9989322269F, 0.9989416021F, + 0.9989509160F, 0.9989601690F, 0.9989693613F, 0.9989784931F, + 0.9989875647F, 0.9989965763F, 0.9990055283F, 0.9990144208F, + 0.9990232541F, 0.9990320286F, 0.9990407443F, 0.9990494016F, + 0.9990580008F, 0.9990665421F, 0.9990750257F, 0.9990834519F, + 0.9990918209F, 0.9991001331F, 0.9991083886F, 0.9991165877F, + 0.9991247307F, 0.9991328177F, 0.9991408491F, 0.9991488251F, + 0.9991567460F, 0.9991646119F, 0.9991724232F, 0.9991801801F, + 0.9991878828F, 0.9991955316F, 0.9992031267F, 0.9992106684F, + 0.9992181569F, 0.9992255925F, 0.9992329753F, 0.9992403057F, + 0.9992475839F, 0.9992548101F, 0.9992619846F, 0.9992691076F, + 0.9992761793F, 0.9992832001F, 0.9992901701F, 0.9992970895F, + 0.9993039587F, 0.9993107777F, 0.9993175470F, 0.9993242667F, + 0.9993309371F, 0.9993375583F, 0.9993441307F, 0.9993506545F, + 0.9993571298F, 0.9993635570F, 0.9993699362F, 0.9993762678F, + 0.9993825519F, 0.9993887887F, 0.9993949785F, 0.9994011216F, + 0.9994072181F, 0.9994132683F, 0.9994192725F, 0.9994252307F, + 0.9994311434F, 0.9994370107F, 0.9994428327F, 0.9994486099F, + 0.9994543423F, 0.9994600303F, 0.9994656739F, 0.9994712736F, + 0.9994768294F, 0.9994823417F, 0.9994878105F, 0.9994932363F, + 0.9994986191F, 0.9995039592F, 0.9995092568F, 0.9995145122F, + 0.9995197256F, 0.9995248971F, 0.9995300270F, 0.9995351156F, + 0.9995401630F, 0.9995451695F, 0.9995501352F, 0.9995550604F, + 0.9995599454F, 0.9995647903F, 0.9995695953F, 0.9995743607F, + 0.9995790866F, 0.9995837734F, 0.9995884211F, 0.9995930300F, + 0.9995976004F, 0.9996021324F, 0.9996066263F, 0.9996110822F, + 0.9996155004F, 0.9996198810F, 0.9996242244F, 0.9996285306F, + 0.9996327999F, 0.9996370326F, 0.9996412287F, 0.9996453886F, + 0.9996495125F, 0.9996536004F, 0.9996576527F, 0.9996616696F, + 0.9996656512F, 0.9996695977F, 0.9996735094F, 0.9996773865F, + 0.9996812291F, 0.9996850374F, 0.9996888118F, 0.9996925523F, + 0.9996962591F, 0.9996999325F, 0.9997035727F, 0.9997071798F, + 0.9997107541F, 0.9997142957F, 0.9997178049F, 0.9997212818F, + 0.9997247266F, 0.9997281396F, 0.9997315209F, 0.9997348708F, + 0.9997381893F, 0.9997414767F, 0.9997447333F, 0.9997479591F, + 0.9997511544F, 0.9997543194F, 0.9997574542F, 0.9997605591F, + 0.9997636342F, 0.9997666797F, 0.9997696958F, 0.9997726828F, + 0.9997756407F, 0.9997785698F, 0.9997814703F, 0.9997843423F, + 0.9997871860F, 0.9997900016F, 0.9997927894F, 0.9997955494F, + 0.9997982818F, 0.9998009869F, 0.9998036648F, 0.9998063157F, + 0.9998089398F, 0.9998115373F, 0.9998141082F, 0.9998166529F, + 0.9998191715F, 0.9998216642F, 0.9998241311F, 0.9998265724F, + 0.9998289884F, 0.9998313790F, 0.9998337447F, 0.9998360854F, + 0.9998384015F, 0.9998406930F, 0.9998429602F, 0.9998452031F, + 0.9998474221F, 0.9998496171F, 0.9998517885F, 0.9998539364F, + 0.9998560610F, 0.9998581624F, 0.9998602407F, 0.9998622962F, + 0.9998643291F, 0.9998663394F, 0.9998683274F, 0.9998702932F, + 0.9998722370F, 0.9998741589F, 0.9998760591F, 0.9998779378F, + 0.9998797952F, 0.9998816313F, 0.9998834464F, 0.9998852406F, + 0.9998870141F, 0.9998887670F, 0.9998904995F, 0.9998922117F, + 0.9998939039F, 0.9998955761F, 0.9998972285F, 0.9998988613F, + 0.9999004746F, 0.9999020686F, 0.9999036434F, 0.9999051992F, + 0.9999067362F, 0.9999082544F, 0.9999097541F, 0.9999112354F, + 0.9999126984F, 0.9999141433F, 0.9999155703F, 0.9999169794F, + 0.9999183709F, 0.9999197449F, 0.9999211014F, 0.9999224408F, + 0.9999237631F, 0.9999250684F, 0.9999263570F, 0.9999276289F, + 0.9999288843F, 0.9999301233F, 0.9999313461F, 0.9999325529F, + 0.9999337437F, 0.9999349187F, 0.9999360780F, 0.9999372218F, + 0.9999383503F, 0.9999394635F, 0.9999405616F, 0.9999416447F, + 0.9999427129F, 0.9999437665F, 0.9999448055F, 0.9999458301F, + 0.9999468404F, 0.9999478365F, 0.9999488185F, 0.9999497867F, + 0.9999507411F, 0.9999516819F, 0.9999526091F, 0.9999535230F, + 0.9999544236F, 0.9999553111F, 0.9999561856F, 0.9999570472F, + 0.9999578960F, 0.9999587323F, 0.9999595560F, 0.9999603674F, + 0.9999611666F, 0.9999619536F, 0.9999627286F, 0.9999634917F, + 0.9999642431F, 0.9999649828F, 0.9999657110F, 0.9999664278F, + 0.9999671334F, 0.9999678278F, 0.9999685111F, 0.9999691835F, + 0.9999698451F, 0.9999704960F, 0.9999711364F, 0.9999717662F, + 0.9999723858F, 0.9999729950F, 0.9999735942F, 0.9999741834F, + 0.9999747626F, 0.9999753321F, 0.9999758919F, 0.9999764421F, + 0.9999769828F, 0.9999775143F, 0.9999780364F, 0.9999785495F, + 0.9999790535F, 0.9999795485F, 0.9999800348F, 0.9999805124F, + 0.9999809813F, 0.9999814417F, 0.9999818938F, 0.9999823375F, + 0.9999827731F, 0.9999832005F, 0.9999836200F, 0.9999840316F, + 0.9999844353F, 0.9999848314F, 0.9999852199F, 0.9999856008F, + 0.9999859744F, 0.9999863407F, 0.9999866997F, 0.9999870516F, + 0.9999873965F, 0.9999877345F, 0.9999880656F, 0.9999883900F, + 0.9999887078F, 0.9999890190F, 0.9999893237F, 0.9999896220F, + 0.9999899140F, 0.9999901999F, 0.9999904796F, 0.9999907533F, + 0.9999910211F, 0.9999912830F, 0.9999915391F, 0.9999917896F, + 0.9999920345F, 0.9999922738F, 0.9999925077F, 0.9999927363F, + 0.9999929596F, 0.9999931777F, 0.9999933907F, 0.9999935987F, + 0.9999938018F, 0.9999940000F, 0.9999941934F, 0.9999943820F, + 0.9999945661F, 0.9999947456F, 0.9999949206F, 0.9999950912F, + 0.9999952575F, 0.9999954195F, 0.9999955773F, 0.9999957311F, + 0.9999958807F, 0.9999960265F, 0.9999961683F, 0.9999963063F, + 0.9999964405F, 0.9999965710F, 0.9999966979F, 0.9999968213F, + 0.9999969412F, 0.9999970576F, 0.9999971707F, 0.9999972805F, + 0.9999973871F, 0.9999974905F, 0.9999975909F, 0.9999976881F, + 0.9999977824F, 0.9999978738F, 0.9999979624F, 0.9999980481F, + 0.9999981311F, 0.9999982115F, 0.9999982892F, 0.9999983644F, + 0.9999984370F, 0.9999985072F, 0.9999985750F, 0.9999986405F, + 0.9999987037F, 0.9999987647F, 0.9999988235F, 0.9999988802F, + 0.9999989348F, 0.9999989873F, 0.9999990379F, 0.9999990866F, + 0.9999991334F, 0.9999991784F, 0.9999992217F, 0.9999992632F, + 0.9999993030F, 0.9999993411F, 0.9999993777F, 0.9999994128F, + 0.9999994463F, 0.9999994784F, 0.9999995091F, 0.9999995384F, + 0.9999995663F, 0.9999995930F, 0.9999996184F, 0.9999996426F, + 0.9999996657F, 0.9999996876F, 0.9999997084F, 0.9999997282F, + 0.9999997469F, 0.9999997647F, 0.9999997815F, 0.9999997973F, + 0.9999998123F, 0.9999998265F, 0.9999998398F, 0.9999998524F, + 0.9999998642F, 0.9999998753F, 0.9999998857F, 0.9999998954F, + 0.9999999045F, 0.9999999130F, 0.9999999209F, 0.9999999282F, + 0.9999999351F, 0.9999999414F, 0.9999999472F, 0.9999999526F, + 0.9999999576F, 0.9999999622F, 0.9999999664F, 0.9999999702F, + 0.9999999737F, 0.9999999769F, 0.9999999798F, 0.9999999824F, + 0.9999999847F, 0.9999999868F, 0.9999999887F, 0.9999999904F, + 0.9999999919F, 0.9999999932F, 0.9999999943F, 0.9999999953F, + 0.9999999961F, 0.9999999969F, 0.9999999975F, 0.9999999980F, + 0.9999999985F, 0.9999999988F, 0.9999999991F, 0.9999999993F, + 0.9999999995F, 0.9999999997F, 0.9999999998F, 0.9999999999F, + 0.9999999999F, 1.0000000000F, 1.0000000000F, 1.0000000000F, + 1.0000000000F, 1.0000000000F, 1.0000000000F, 1.0000000000F, +}; + +const float ff_vorbis_floor1_inverse_db_table[256]={ + 1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F, + 1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F, + 1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F, + 2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F, + 2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F, + 3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F, + 4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F, + 6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F, + 7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F, + 1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F, + 1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F, + 1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F, + 2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F, + 2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F, + 3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F, + 4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F, + 5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F, + 7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F, + 9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F, + 1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F, + 1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F, + 2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F, + 2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F, + 3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F, + 4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F, + 5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F, + 7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F, + 9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F, + 0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F, + 0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F, + 0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F, + 0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F, + 0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F, + 0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F, + 0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F, + 0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F, + 0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F, + 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, + 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, + 0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F, + 0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F, + 0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F, + 0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F, + 0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F, + 0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F, + 0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F, + 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, + 0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F, + 0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F, + 0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F, + 0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F, + 0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F, + 0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F, + 0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F, + 0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F, + 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, + 0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F, + 0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F, + 0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F, + 0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F, + 0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F, + 0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F, + 0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F, + 0.82788260F, 0.88168307F, 0.9389798F, 1.F, +}; + +const float * const ff_vorbis_vwin[8] = { + vwin64, vwin128, vwin256, vwin512, + vwin1024, vwin2048, vwin4096, vwin8192 +}; diff --git a/ffmpeg/libavcodec/vorbis_enc_data.h b/ffmpeg/libavcodec/vorbis_enc_data.h new file mode 100644 index 0000000..a51aaec --- /dev/null +++ b/ffmpeg/libavcodec/vorbis_enc_data.h @@ -0,0 +1,504 @@ +/* + * copyright (c) 2006 Oded Shimon + * + * 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 + */ + +#ifndef AVCODEC_VORBIS_ENC_DATA_H +#define AVCODEC_VORBIS_ENC_DATA_H + +#include + +static const uint8_t codebook0[] = { + 2, 10, 8, 14, 7, 12, 11, 14, 1, 5, 3, 7, 4, 9, 7, 13, +}; + +static const uint8_t codebook1[] = { + 1, 4, 2, 6, 3, 7, 5, 7, +}; + +static const uint8_t codebook2[] = { + 1, 5, 7, 21, 5, 8, 9, 21, 10, 9, 12, 20, 20, 16, 20, + 20, 4, 8, 9, 20, 6, 8, 9, 20, 11, 11, 13, 20, 20, 15, + 17, 20, 9, 11, 14, 20, 8, 10, 15, 20, 11, 13, 15, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 13, 20, 20, 20, 18, 18, 20, 20, + 20, 20, 20, 20, 3, 6, 8, 20, 6, 7, 9, 20, 10, 9, 12, + 20, 20, 20, 20, 20, 5, 7, 9, 20, 6, 6, 9, 20, 10, 9, + 12, 20, 20, 20, 20, 20, 8, 10, 13, 20, 8, 9, 12, 20, 11, + 10, 12, 20, 20, 20, 20, 20, 18, 20, 20, 20, 15, 17, 18, 20, + 18, 17, 18, 20, 20, 20, 20, 20, 7, 10, 12, 20, 8, 9, 11, + 20, 14, 13, 14, 20, 20, 20, 20, 20, 6, 9, 12, 20, 7, 8, + 11, 20, 12, 11, 13, 20, 20, 20, 20, 20, 9, 11, 15, 20, 8, + 10, 14, 20, 12, 11, 14, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 11, 16, 18, + 20, 15, 15, 17, 20, 20, 17, 20, 20, 20, 20, 20, 20, 9, 14, + 16, 20, 12, 12, 15, 20, 17, 15, 18, 20, 20, 20, 20, 20, 16, + 19, 18, 20, 15, 16, 20, 20, 17, 17, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, +}; + +static const uint8_t codebook3[] = { + 2, 3, 7, 13, 4, 4, 7, 15, 8, 6, 9, 17, 21, 16, 15, + 21, 2, 5, 7, 11, 5, 5, 7, 14, 9, 7, 10, 16, 17, 15, + 16, 21, 4, 7, 10, 17, 7, 7, 9, 15, 11, 9, 11, 16, 21, + 18, 15, 21, 18, 21, 21, 21, 15, 17, 17, 19, 21, 19, 18, 20, + 21, 21, 21, 20, +}; + +static const uint8_t codebook4[] = { + 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, + 5, 6, 5, 6, 5, 6, 5, 6, 5, 7, 5, 7, 5, 7, 5, + 7, 5, 8, 6, 8, 6, 8, 6, 9, 6, 9, 6, 10, 6, 10, + 6, 11, 6, 11, 7, 11, 7, 12, 7, 12, 7, 12, 7, 12, 7, + 12, 7, 12, 7, 12, 7, 12, 8, 13, 8, 12, 8, 12, 8, 13, + 8, 13, 9, 13, 9, 13, 9, 13, 9, 12, 10, 12, 10, 13, 10, + 14, 11, 14, 12, 14, 13, 14, 13, 14, 14, 15, 16, 15, 15, 15, + 14, 15, 17, 21, 22, 22, 21, 22, 22, 22, 22, 22, 22, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, +}; + +static const uint8_t codebook5[] = { + 2, 5, 5, 4, 5, 4, 5, 4, 5, 4, 6, 5, 6, 5, 6, + 5, 6, 5, 7, 5, 7, 6, 8, 6, 8, 6, 8, 6, 9, 6, + 9, 6, +}; + +static const uint8_t codebook6[] = { + 8, 5, 8, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, 4, 9, + 4, 9, 4, 9, 4, 9, 4, 8, 4, 8, 4, 9, 5, 9, 5, + 9, 5, 9, 5, 9, 6, 10, 6, 10, 7, 10, 8, 11, 9, 11, + 11, 12, 13, 12, 14, 13, 15, 13, 15, 14, 16, 14, 17, 15, 17, + 15, 15, 16, 16, 15, 16, 16, 16, 15, 18, 16, 15, 17, 17, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, +}; + +static const uint8_t codebook7[] = { + 1, 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 6, 5, 6, + 5, 6, 6, 7, 7, 7, 7, 8, 7, 8, 8, 9, 8, 10, 9, + 10, 9, +}; + +static const uint8_t codebook8[] = { + 4, 3, 4, 3, 4, 4, 5, 4, 5, 4, 5, 5, 6, 5, 6, + 5, 7, 5, 7, 6, 7, 6, 8, 7, 8, 7, 8, 7, 9, 8, + 9, 9, 9, 9, 10, 10, 10, 11, 9, 12, 9, 12, 9, 15, 10, + 14, 9, 13, 10, 13, 10, 12, 10, 12, 10, 13, 10, 12, 11, 13, + 11, 14, 12, 13, 13, 14, 14, 13, 14, 15, 14, 16, 13, 13, 14, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 15, 15, +}; + +static const uint8_t codebook9[] = { + 4, 5, 4, 5, 3, 5, 3, 5, 3, 5, 4, 4, 4, 4, 5, + 5, 5, +}; + +static const uint8_t codebook10[] = { + 3, 3, 4, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 5, + 7, 5, 8, 6, 8, 6, 9, 7, 10, 7, 10, 8, 10, 8, 11, + 9, 11, +}; + +static const uint8_t codebook11[] = { + 3, 7, 3, 8, 3, 10, 3, 8, 3, 9, 3, 8, 4, 9, 4, + 9, 5, 9, 6, 10, 6, 9, 7, 11, 7, 12, 9, 13, 10, 13, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, +}; + +static const uint8_t codebook12[] = { + 4, 5, 4, 5, 4, 5, 4, 5, 3, 5, 3, 5, 3, 5, 4, + 5, 4, +}; + +static const uint8_t codebook13[] = { + 4, 2, 4, 2, 5, 3, 5, 4, 6, 6, 6, 7, 7, 8, 7, + 8, 7, 8, 7, 9, 8, 9, 8, 9, 8, 10, 8, 11, 9, 12, + 9, 12, +}; + +static const uint8_t codebook14[] = { + 2, 5, 2, 6, 3, 6, 4, 7, 4, 7, 5, 9, 5, 11, 6, + 11, 6, 11, 7, 11, 6, 11, 6, 11, 9, 11, 8, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, + 10, 10, 10, +}; + +static const uint8_t codebook15[] = { + 5, 6, 11, 11, 11, 11, 10, 10, 12, 11, 5, 2, 11, 5, 6, + 6, 7, 9, 11, 13, 13, 10, 7, 11, 6, 7, 8, 9, 10, 12, + 11, 5, 11, 6, 8, 7, 9, 11, 14, 15, 11, 6, 6, 8, 4, + 5, 7, 8, 10, 13, 10, 5, 7, 7, 5, 5, 6, 8, 10, 11, + 10, 7, 7, 8, 6, 5, 5, 7, 9, 9, 11, 8, 8, 11, 8, + 7, 6, 6, 7, 9, 12, 11, 10, 13, 9, 9, 7, 7, 7, 9, + 11, 13, 12, 15, 12, 11, 9, 8, 8, 8, +}; + +static const uint8_t codebook16[] = { + 2, 4, 4, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, + 0, 0, 0, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, + 7, 8, 8, 0, 0, 0, 0, 0, 0, 6, 7, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, + 0, 0, 0, 0, 0, 0, 6, 8, 7, 0, 0, 0, 0, 0, 0, + 7, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, + 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, 7, 8, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 8, 8, 0, 0, 0, 0, 0, 0, 8, 8, 9, 0, 0, 0, + 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, 0, 0, 0, 0, 0, + 7, 9, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 7, 7, 0, 0, 0, 0, 0, 0, 7, 8, 8, + 0, 0, 0, 0, 0, 0, 7, 8, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 8, 0, 0, 0, + 0, 0, 0, 8, 9, 9, 0, 0, 0, 0, 0, 0, 7, 8, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 8, 8, 0, 0, 0, 0, 0, 0, 8, 9, 9, 0, 0, 0, + 0, 0, 0, 8, 9, 8, +}; + +static const uint8_t codebook17[] = { + 2, 5, 5, 0, 0, 0, 5, 5, 0, 0, 0, 5, 5, 0, 0, + 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, + 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 6, 0, 0, 0, 7, 7, 0, 0, + 0, 7, 7, 0, 0, 0, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, + 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, + 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 7, 7, 0, 0, 0, 7, 7, 0, 0, + 0, 7, 7, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, + 5, 7, 7, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 0, 0, + 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, + 0, 9, 9, 0, 0, 0, 9, 9, 0, 0, 0, 10, 10, 0, 0, + 0, 0, 0, 0, 0, 8, 10, 10, 0, 0, 0, 9, 9, 0, 0, + 0, 9, 9, 0, 0, 0, 10, 10, +}; + +static const uint8_t codebook18[] = { + 2, 4, 3, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 4, 4, 6, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 6, 6, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 9, 9, +}; + +static const uint8_t codebook19[] = { + 2, 3, 3, 6, 6, 0, 0, 0, 0, 0, 4, 4, 6, 6, 0, + 0, 0, 0, 0, 4, 4, 6, 6, 0, 0, 0, 0, 0, 5, 5, + 6, 6, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, + 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, + 0, 0, 0, 0, 0, 0, 9, 9, +}; + +static const uint8_t codebook20[] = { + 1, 3, 4, 6, 6, 7, 7, 9, 9, 0, 5, 5, 7, 7, 7, + 8, 9, 9, 0, 5, 5, 7, 7, 8, 8, 9, 9, 0, 7, 7, + 8, 8, 8, 8, 10, 10, 0, 0, 0, 8, 8, 8, 8, 10, 10, + 0, 0, 0, 9, 9, 9, 9, 10, 10, 0, 0, 0, 9, 9, 9, + 9, 10, 10, 0, 0, 0, 10, 10, 10, 10, 11, 11, 0, 0, 0, + 0, 0, 10, 10, 11, 11, +}; + +static const uint8_t codebook21[] = { + 2, 3, 3, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10, + 11, 10, 0, 5, 5, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, + 10, 10, 11, 11, 0, 5, 5, 7, 7, 8, 8, 9, 9, 9, 9, + 10, 10, 10, 10, 11, 11, 0, 6, 6, 7, 7, 8, 8, 9, 9, + 9, 9, 10, 10, 11, 11, 11, 11, 0, 0, 0, 7, 7, 8, 8, + 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 0, 0, 0, 8, 8, + 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 12, 12, 0, 0, 0, + 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 12, 12, 0, + 0, 0, 9, 9, 9, 9, 10, 10, 10, 10, 11, 10, 11, 11, 12, + 12, 0, 0, 0, 0, 0, 9, 9, 10, 10, 10, 10, 11, 11, 11, + 11, 12, 12, 0, 0, 0, 0, 0, 9, 8, 9, 9, 10, 10, 11, + 11, 12, 12, 12, 12, 0, 0, 0, 0, 0, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 11, 12, 12, 0, 0, 0, 0, 0, 9, 10, 10, + 10, 11, 11, 11, 11, 12, 12, 13, 13, 0, 0, 0, 0, 0, 0, + 0, 10, 10, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0, 0, 0, + 0, 0, 0, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 0, 0, + 0, 0, 0, 0, 0, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 11, 11, 12, 12, 12, 12, 13, 13, + 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, + 13, 13, 13, 13, +}; + +static const uint8_t codebook22[] = { + 1, 4, 4, 7, 6, 6, 7, 6, 6, 4, 7, 7, 10, 9, 9, + 11, 9, 9, 4, 7, 7, 10, 9, 9, 11, 9, 9, 7, 10, 10, + 11, 11, 10, 12, 11, 11, 6, 9, 9, 11, 10, 10, 11, 10, 10, + 6, 9, 9, 11, 10, 10, 11, 10, 10, 7, 11, 11, 11, 11, 11, + 12, 11, 11, 6, 9, 9, 11, 10, 10, 11, 10, 10, 6, 9, 9, + 11, 10, 10, 11, 10, 10, +}; + +static const uint8_t codebook23[] = { + 2, 4, 4, 6, 6, 7, 7, 7, 7, 8, 8, 10, 5, 5, 6, + 6, 7, 7, 8, 8, 8, 8, 10, 5, 5, 6, 6, 7, 7, 8, + 8, 8, 8, 10, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 10, + 10, 10, 7, 7, 8, 7, 8, 8, 8, 8, 10, 10, 10, 8, 8, + 8, 8, 8, 8, 8, 8, 10, 10, 10, 7, 8, 8, 8, 8, 8, + 8, 8, 10, 10, 10, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, + 10, 10, 10, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 9, + 9, 8, 8, 9, 8, 10, 10, 10, 10, 10, 8, 8, 8, 8, 8, + 8, +}; + +static const uint8_t codebook24[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 6, 5, + 5, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10, 7, 5, 5, 7, + 7, 8, 8, 8, 8, 9, 9, 11, 10, 0, 8, 8, 8, 8, 9, + 9, 9, 9, 10, 10, 11, 11, 0, 8, 8, 8, 8, 9, 9, 9, + 9, 10, 10, 11, 11, 0, 12, 12, 9, 9, 10, 10, 10, 10, 11, + 11, 11, 12, 0, 13, 13, 9, 9, 10, 10, 10, 10, 11, 11, 12, + 12, 0, 0, 0, 10, 10, 10, 10, 11, 11, 12, 12, 12, 12, 0, + 0, 0, 10, 10, 10, 10, 11, 11, 12, 12, 12, 12, 0, 0, 0, + 14, 14, 11, 11, 11, 11, 12, 12, 13, 13, 0, 0, 0, 14, 14, + 11, 11, 11, 11, 12, 12, 13, 13, 0, 0, 0, 0, 0, 12, 12, + 12, 12, 13, 13, 14, 13, 0, 0, 0, 0, 0, 13, 13, 12, 12, + 13, 12, 14, 13, +}; + +static const uint8_t codebook25[] = { + 2, 4, 4, 5, 5, 6, 5, 5, 5, 5, 6, 4, 5, 5, 5, + 6, 5, 5, 5, 5, 6, 6, 6, 5, 5, +}; + +static const uint8_t codebook26[] = { + 1, 4, 4, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 4, 9, + 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 9, 7, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, +}; + +static const uint8_t codebook27[] = { + 1, 4, 4, 6, 6, 7, 7, 8, 7, 9, 9, 10, 10, 10, 10, + 6, 5, 5, 7, 7, 8, 8, 10, 8, 11, 10, 12, 12, 13, 13, + 6, 5, 5, 7, 7, 8, 8, 10, 9, 11, 11, 12, 12, 13, 12, + 18, 8, 8, 8, 8, 9, 9, 10, 9, 11, 10, 12, 12, 13, 13, + 18, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 13, 12, 14, 13, + 18, 11, 11, 9, 9, 10, 10, 11, 11, 11, 12, 13, 12, 13, 14, + 18, 11, 11, 9, 8, 11, 10, 11, 11, 11, 11, 12, 12, 14, 13, + 18, 18, 18, 10, 11, 10, 11, 12, 12, 12, 12, 13, 12, 14, 13, + 18, 18, 18, 10, 11, 11, 9, 12, 11, 12, 12, 12, 13, 13, 13, + 18, 18, 17, 14, 14, 11, 11, 12, 12, 13, 12, 14, 12, 14, 13, + 18, 18, 18, 14, 14, 11, 10, 12, 9, 12, 13, 13, 13, 13, 13, + 18, 18, 17, 16, 18, 13, 13, 12, 12, 13, 11, 14, 12, 14, 14, + 17, 18, 18, 17, 18, 13, 12, 13, 10, 12, 11, 14, 14, 14, 14, + 17, 18, 18, 18, 18, 15, 16, 12, 12, 13, 10, 14, 12, 14, 15, + 18, 18, 18, 16, 17, 16, 14, 12, 11, 13, 10, 13, 13, 14, 15, +}; + +static const uint8_t codebook28[] = { + 2, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 10, 6, 6, 7, 7, 8, 7, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 10, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 10, 7, 7, 7, 7, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 7, 7, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, + 10, 10, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, + 9, 10, 10, 10, 11, 11, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 11, 10, 11, 11, 11, 9, 9, 9, 9, 9, 9, 10, + 10, 9, 9, 10, 9, 11, 10, 11, 11, 11, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 9, 11, 11, 11, 11, 11, 9, 9, 9, + 9, 10, 10, 9, 9, 9, 9, 10, 9, 11, 11, 11, 11, 11, 11, + 11, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 10, 9, 10, 10, 9, 10, 9, 9, 10, 9, 11, 10, + 10, 11, 11, 11, 11, 9, 10, 9, 9, 9, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 10, 10, 10, 9, 9, 10, 9, 10, 9, + 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 9, 9, 9, 9, + 9, 10, 10, 10, +}; + +static const struct { + int dim; + int len; + int real_len; + const uint8_t *clens; + int lookup; + float min; + float delta; + const uint8_t *quant; +} cvectors[] = { + { 2, 16, 16, codebook0, 0 }, + { 2, 8, 8, codebook1, 0 }, + { 2, 256, 256, codebook2, 0 }, + { 2, 64, 64, codebook3, 0 }, + { 2, 128, 128, codebook4, 0 }, + { 2, 32, 32, codebook5, 0 }, + { 2, 96, 96, codebook6, 0 }, + { 2, 32, 32, codebook7, 0 }, + { 2, 96, 96, codebook8, 0 }, + { 2, 17, 17, codebook9, 0 }, + { 2, 32, 32, codebook10, 0 }, + { 2, 78, 78, codebook11, 0 }, + { 2, 17, 17, codebook12, 0 }, + { 2, 32, 32, codebook13, 0 }, + { 2, 78, 78, codebook14, 0 }, + { 2, 100, 100, codebook15, 0 }, + { 8, 1641, 6561, codebook16, 1, -1.0, 1.0, (const uint8_t[]){ 1, 0, 2, } }, + { 4, 443, 625, codebook17, 1, -2.0, 1.0, (const uint8_t[]){ 2, 1, 3, 0, 4, } }, + { 4, 105, 625, codebook18, 1, -2.0, 1.0, (const uint8_t[]){ 2, 1, 3, 0, 4, } }, + { 2, 68, 81, codebook19, 1, -4.0, 1.0, (const uint8_t[]){ 4, 3, 5, 2, 6, 1, 7, 0, 8, } }, + { 2, 81, 81, codebook20, 1, -4.0, 1.0, (const uint8_t[]){ 4, 3, 5, 2, 6, 1, 7, 0, 8, } }, + { 2, 289, 289, codebook21, 1, -8.0, 1.0, (const uint8_t[]){ 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, 0, 16, } }, + { 4, 81, 81, codebook22, 1, -11.0, 11.0, (const uint8_t[]){ 1, 0, 2, } }, + { 2, 121, 121, codebook23, 1, -5.0, 1.0, (const uint8_t[]){ 5, 4, 6, 3, 7, 2, 8, 1, 9, 0, 10, } }, + { 2, 169, 169, codebook24, 1, -30.0, 5.0, (const uint8_t[]){ 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12, } }, + { 2, 25, 25, codebook25, 1, -2.0, 1.0, (const uint8_t[]){ 2, 1, 3, 0, 4, } }, + { 2, 169, 169, codebook26, 1, -1530.0, 255.0, (const uint8_t[]){ 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12, } }, + { 2, 225, 225, codebook27, 1, -119.0, 17.0, (const uint8_t[]){ 7, 6, 8, 5, 9, 4, 10, 3, 11, 2, 12, 1, 13, 0, 14, } }, + { 2, 289, 289, codebook28, 1, -8.0, 1.0, (const uint8_t[]){ 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, 0, 16, } }, +}; + +static const struct { + int dim; + int subclass; + int masterbook; + const int nbooks[4]; +} floor_classes[] = { + { 3, 0, 0, { 4 } }, + { 4, 1, 0, { 5, 6 } }, + { 3, 1, 1, { 7, 8 } }, + { 4, 2, 2, { -1, 9, 10, 11 } }, + { 3, 2, 3, { -1, 12, 13, 14 } }, +}; + +#endif /* AVCODEC_VORBIS_ENC_DATA_H */ diff --git a/ffmpeg/libavcodec/vorbis_parser.c b/ffmpeg/libavcodec/vorbis_parser.c new file mode 100644 index 0000000..22e0461 --- /dev/null +++ b/ffmpeg/libavcodec/vorbis_parser.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Vorbis audio parser + * + * Determines the duration for each packet. + */ + +#include "get_bits.h" +#include "parser.h" +#include "xiph.h" +#include "vorbis_parser.h" + +static int parse_id_header(AVCodecContext *avctx, VorbisParseContext *s, + const uint8_t *buf, int buf_size) +{ + /* Id header should be 30 bytes */ + if (buf_size < 30) { + av_log(avctx, AV_LOG_ERROR, "Id header is too short\n"); + return AVERROR_INVALIDDATA; + } + + /* make sure this is the Id header */ + if (buf[0] != 1) { + av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Id header\n"); + return AVERROR_INVALIDDATA; + } + + /* check for header signature */ + if (memcmp(&buf[1], "vorbis", 6)) { + av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Id header\n"); + return AVERROR_INVALIDDATA; + } + + if (!(buf[29] & 0x1)) { + av_log(avctx, AV_LOG_ERROR, "Invalid framing bit in Id header\n"); + return AVERROR_INVALIDDATA; + } + + s->blocksize[0] = 1 << (buf[28] & 0xF); + s->blocksize[1] = 1 << (buf[28] >> 4); + + return 0; +} + +static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, + const uint8_t *buf, int buf_size) +{ + GetBitContext gb, gb0; + uint8_t *rev_buf; + int i, ret = 0; + int got_framing_bit, mode_count, got_mode_header, last_mode_count = 0; + + /* avoid overread */ + if (buf_size < 7) { + av_log(avctx, AV_LOG_ERROR, "Setup header is too short\n"); + return AVERROR_INVALIDDATA; + } + + /* make sure this is the Setup header */ + if (buf[0] != 5) { + av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Setup header\n"); + return AVERROR_INVALIDDATA; + } + + /* check for header signature */ + if (memcmp(&buf[1], "vorbis", 6)) { + av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Setup header\n"); + return AVERROR_INVALIDDATA; + } + + /* reverse bytes so we can easily read backwards with get_bits() */ + if (!(rev_buf = av_malloc(buf_size))) { + av_log(avctx, AV_LOG_ERROR, "Out of memory\n"); + return AVERROR(ENOMEM); + } + for (i = 0; i < buf_size; i++) + rev_buf[i] = buf[buf_size - 1 - i]; + init_get_bits(&gb, rev_buf, buf_size * 8); + + got_framing_bit = 0; + while (get_bits_left(&gb) > 97) { + if (get_bits1(&gb)) { + got_framing_bit = get_bits_count(&gb); + break; + } + } + if (!got_framing_bit) { + av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n"); + ret = AVERROR_INVALIDDATA; + goto bad_header; + } + + /* Now we search backwards to find possible valid mode counts. This is not + * fool-proof because we could have false positive matches and read too + * far, but there isn't really any way to be sure without parsing through + * all the many variable-sized fields before the modes. This approach seems + * to work well in testing, and it is similar to how it is handled in + * liboggz. */ + mode_count = 0; + got_mode_header = 0; + while (get_bits_left(&gb) >= 97) { + if (get_bits(&gb, 8) > 63 || get_bits(&gb, 16) || get_bits(&gb, 16)) + break; + skip_bits(&gb, 1); + mode_count++; + if (mode_count > 64) + break; + gb0 = gb; + if (get_bits(&gb0, 6) + 1 == mode_count) { + got_mode_header = 1; + last_mode_count = mode_count; + } + } + if (!got_mode_header) { + av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n"); + ret = AVERROR_INVALIDDATA; + goto bad_header; + } + /* All samples I've seen use <= 2 modes, so ask for a sample if we find + * more than that, as it is most likely a false positive. If we get any + * we may need to approach this the long way and parse the whole Setup + * header, but I hope very much that it never comes to that. */ + if (last_mode_count > 2) { + avpriv_request_sample(avctx, + "%d modes (either a false positive or a " + "sample from an unknown encoder)", + last_mode_count); + } + /* We're limiting the mode count to 63 so that we know that the previous + * block flag will be in the first packet byte. */ + if (last_mode_count > 63) { + av_log(avctx, AV_LOG_ERROR, "Unsupported mode count: %d\n", + last_mode_count); + ret = AVERROR_INVALIDDATA; + goto bad_header; + } + s->mode_count = mode_count = last_mode_count; + /* Determine the number of bits required to code the mode and turn that + * into a bitmask to directly access the mode from the first frame byte. */ + s->mode_mask = ((1 << (av_log2(mode_count - 1) + 1)) - 1) << 1; + /* The previous window flag is the next bit after the mode */ + s->prev_mask = (s->mode_mask | 0x1) + 1; + + init_get_bits(&gb, rev_buf, buf_size * 8); + skip_bits_long(&gb, got_framing_bit); + for (i = mode_count - 1; i >= 0; i--) { + skip_bits_long(&gb, 40); + s->mode_blocksize[i] = get_bits1(&gb); + } + +bad_header: + av_free(rev_buf); + return ret; +} + +int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s) +{ + uint8_t *header_start[3]; + int header_len[3]; + int ret; + + s->avctx = avctx; + s->extradata_parsed = 1; + + if ((ret = avpriv_split_xiph_headers(avctx->extradata, + avctx->extradata_size, 30, + header_start, header_len)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Extradata corrupt.\n"); + return ret; + } + + if ((ret = parse_id_header(avctx, s, header_start[0], header_len[0])) < 0) + return ret; + + if ((ret = parse_setup_header(avctx, s, header_start[2], header_len[2])) < 0) + return ret; + + s->valid_extradata = 1; + s->previous_blocksize = s->blocksize[s->mode_blocksize[0]]; + + return 0; +} + +int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, + int buf_size) +{ + int duration = 0; + + if (s->valid_extradata && buf_size > 0) { + int mode, current_blocksize; + int previous_blocksize = s->previous_blocksize; + + if (buf[0] & 1) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid packet\n"); + return AVERROR_INVALIDDATA; + } + if (s->mode_count == 1) + mode = 0; + else + mode = (buf[0] & s->mode_mask) >> 1; + if (mode >= s->mode_count) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid mode in packet\n"); + return AVERROR_INVALIDDATA; + } + if(s->mode_blocksize[mode]){ + int flag = !!(buf[0] & s->prev_mask); + previous_blocksize = s->blocksize[flag]; + } + current_blocksize = s->blocksize[s->mode_blocksize[mode]]; + duration = (previous_blocksize + current_blocksize) >> 2; + s->previous_blocksize = current_blocksize; + } + + return duration; +} + +void avpriv_vorbis_parse_reset(VorbisParseContext *s) +{ + if (s->valid_extradata) + s->previous_blocksize = s->blocksize[0]; +} + +#if CONFIG_VORBIS_PARSER +static int vorbis_parse(AVCodecParserContext *s1, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + VorbisParseContext *s = s1->priv_data; + int duration; + + if (!s->extradata_parsed && avctx->extradata && avctx->extradata_size) + if (avpriv_vorbis_parse_extradata(avctx, s)) + goto end; + + if ((duration = avpriv_vorbis_parse_frame(s, buf, buf_size)) >= 0) + s1->duration = duration; + +end: + /* always return the full packet. this parser isn't doing any splitting or + combining, only packet analysis */ + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +AVCodecParser ff_vorbis_parser = { + .codec_ids = { AV_CODEC_ID_VORBIS }, + .priv_data_size = sizeof(VorbisParseContext), + .parser_parse = vorbis_parse, +}; +#endif /* CONFIG_VORBIS_PARSER */ diff --git a/ffmpeg/libavcodec/vorbis_parser.h b/ffmpeg/libavcodec/vorbis_parser.h new file mode 100644 index 0000000..480a918 --- /dev/null +++ b/ffmpeg/libavcodec/vorbis_parser.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 Justin Ruggles + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Vorbis audio parser + * + * Determines the duration for each packet. + */ + +#ifndef AVCODEC_VORBIS_PARSER_H +#define AVCODEC_VORBIS_PARSER_H + +#include "avcodec.h" + +typedef struct VorbisParseContext { + AVCodecContext *avctx; ///< codec context + int extradata_parsed; ///< we have attempted to parse extradata + int valid_extradata; ///< extradata is valid, so we can calculate duration + int blocksize[2]; ///< short and long window sizes + int previous_blocksize; ///< previous window size + int mode_blocksize[64]; ///< window size mapping for each mode + int mode_count; ///< number of modes + int mode_mask; ///< bitmask used to get the mode in each packet + int prev_mask; ///< bitmask used to get the previous mode flag in each packet +} VorbisParseContext; + +/** + * Initialize the Vorbis parser using headers in the extradata. + * + * @param avctx codec context + * @param s Vorbis parser context + */ +int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s); + +/** + * Get the duration for a Vorbis packet. + * + * avpriv_vorbis_parse_extradata() must have been successfully called prior to + * this in order for a correct duration to be returned. + * + * @param s Vorbis parser context + * @param buf buffer containing a Vorbis frame + * @param buf_size size of the buffer + */ +int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf, + int buf_size); + +void avpriv_vorbis_parse_reset(VorbisParseContext *s); + +#endif /* AVCODEC_VORBIS_PARSER_H */ diff --git a/ffmpeg/libavcodec/vorbisdec.c b/ffmpeg/libavcodec/vorbisdec.c new file mode 100644 index 0000000..f30745d --- /dev/null +++ b/ffmpeg/libavcodec/vorbisdec.c @@ -0,0 +1,1802 @@ +/** + * @file + * Vorbis I decoder + * @author Denes Balatoni ( dbalatoni programozo hu ) + * + * 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 + */ + +/** + * @file + * Vorbis I decoder + * @author Denes Balatoni ( dbalatoni programozo hu ) + */ + +#include +#include + +#define BITSTREAM_READER_LE +#include "libavutil/float_dsp.h" +#include "libavutil/avassert.h" +#include "avcodec.h" +#include "get_bits.h" +#include "fft.h" +#include "fmtconvert.h" +#include "internal.h" + +#include "vorbis.h" +#include "vorbisdsp.h" +#include "xiph.h" + +#define V_NB_BITS 8 +#define V_NB_BITS2 11 +#define V_MAX_VLCS (1 << 16) +#define V_MAX_PARTITIONS (1 << 20) + +typedef struct { + uint8_t dimensions; + uint8_t lookup_type; + uint8_t maxdepth; + VLC vlc; + float *codevectors; + unsigned int nb_bits; +} vorbis_codebook; + +typedef union vorbis_floor_u vorbis_floor_data; +typedef struct vorbis_floor0_s vorbis_floor0; +typedef struct vorbis_floor1_s vorbis_floor1; +struct vorbis_context_s; +typedef +int (* vorbis_floor_decode_func) + (struct vorbis_context_s *, vorbis_floor_data *, float *); +typedef struct { + uint8_t floor_type; + vorbis_floor_decode_func decode; + union vorbis_floor_u { + struct vorbis_floor0_s { + uint8_t order; + uint16_t rate; + uint16_t bark_map_size; + int32_t *map[2]; + uint32_t map_size[2]; + uint8_t amplitude_bits; + uint8_t amplitude_offset; + uint8_t num_books; + uint8_t *book_list; + float *lsp; + } t0; + struct vorbis_floor1_s { + uint8_t partitions; + uint8_t partition_class[32]; + uint8_t class_dimensions[16]; + uint8_t class_subclasses[16]; + uint8_t class_masterbook[16]; + int16_t subclass_books[16][8]; + uint8_t multiplier; + uint16_t x_list_dim; + vorbis_floor1_entry *list; + } t1; + } data; +} vorbis_floor; + +typedef struct { + uint16_t type; + uint32_t begin; + uint32_t end; + unsigned partition_size; + uint8_t classifications; + uint8_t classbook; + int16_t books[64][8]; + uint8_t maxpass; + uint16_t ptns_to_read; + uint8_t *classifs; +} vorbis_residue; + +typedef struct { + uint8_t submaps; + uint16_t coupling_steps; + uint8_t *magnitude; + uint8_t *angle; + uint8_t *mux; + uint8_t submap_floor[16]; + uint8_t submap_residue[16]; +} vorbis_mapping; + +typedef struct { + uint8_t blockflag; + uint16_t windowtype; + uint16_t transformtype; + uint8_t mapping; +} vorbis_mode; + +typedef struct vorbis_context_s { + AVCodecContext *avctx; + GetBitContext gb; + VorbisDSPContext dsp; + AVFloatDSPContext fdsp; + FmtConvertContext fmt_conv; + + FFTContext mdct[2]; + uint8_t first_frame; + uint32_t version; + uint8_t audio_channels; + uint32_t audio_samplerate; + uint32_t bitrate_maximum; + uint32_t bitrate_nominal; + uint32_t bitrate_minimum; + uint32_t blocksize[2]; + const float *win[2]; + uint16_t codebook_count; + vorbis_codebook *codebooks; + uint8_t floor_count; + vorbis_floor *floors; + uint8_t residue_count; + vorbis_residue *residues; + uint8_t mapping_count; + vorbis_mapping *mappings; + uint8_t mode_count; + vorbis_mode *modes; + uint8_t mode_number; // mode number for the current packet + uint8_t previous_window; + float *channel_residues; + float *saved; +} vorbis_context; + +/* Helper functions */ + +#define BARK(x) \ + (13.1f * atan(0.00074f * (x)) + 2.24f * atan(1.85e-8f * (x) * (x)) + 1e-4f * (x)) + +static const char idx_err_str[] = "Index value %d out of range (0 - %d) for %s at %s:%i\n"; +#define VALIDATE_INDEX(idx, limit) \ + if (idx >= limit) {\ + av_log(vc->avctx, AV_LOG_ERROR,\ + idx_err_str,\ + (int)(idx), (int)(limit - 1), #idx, __FILE__, __LINE__);\ + return AVERROR_INVALIDDATA;\ + } +#define GET_VALIDATED_INDEX(idx, bits, limit) \ + {\ + idx = get_bits(gb, bits);\ + VALIDATE_INDEX(idx, limit)\ + } + +static float vorbisfloat2float(unsigned val) +{ + double mant = val & 0x1fffff; + long exp = (val & 0x7fe00000L) >> 21; + if (val & 0x80000000) + mant = -mant; + return ldexp(mant, exp - 20 - 768); +} + + +// Free all allocated memory ----------------------------------------- + +static void vorbis_free(vorbis_context *vc) +{ + int i; + + av_freep(&vc->channel_residues); + av_freep(&vc->saved); + + if (vc->residues) + for (i = 0; i < vc->residue_count; i++) + av_free(vc->residues[i].classifs); + av_freep(&vc->residues); + av_freep(&vc->modes); + + ff_mdct_end(&vc->mdct[0]); + ff_mdct_end(&vc->mdct[1]); + + if (vc->codebooks) + for (i = 0; i < vc->codebook_count; ++i) { + av_free(vc->codebooks[i].codevectors); + ff_free_vlc(&vc->codebooks[i].vlc); + } + av_freep(&vc->codebooks); + + if (vc->floors) + for (i = 0; i < vc->floor_count; ++i) { + if (vc->floors[i].floor_type == 0) { + av_free(vc->floors[i].data.t0.map[0]); + av_free(vc->floors[i].data.t0.map[1]); + av_free(vc->floors[i].data.t0.book_list); + av_free(vc->floors[i].data.t0.lsp); + } else { + av_free(vc->floors[i].data.t1.list); + } + } + av_freep(&vc->floors); + + if (vc->mappings) + for (i = 0; i < vc->mapping_count; ++i) { + av_free(vc->mappings[i].magnitude); + av_free(vc->mappings[i].angle); + av_free(vc->mappings[i].mux); + } + av_freep(&vc->mappings); +} + +// Parse setup header ------------------------------------------------- + +// Process codebooks part + +static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc) +{ + unsigned cb; + uint8_t *tmp_vlc_bits = NULL; + uint32_t *tmp_vlc_codes = NULL; + GetBitContext *gb = &vc->gb; + uint16_t *codebook_multiplicands = NULL; + int ret = 0; + + vc->codebook_count = get_bits(gb, 8) + 1; + + av_dlog(NULL, " Codebooks: %d \n", vc->codebook_count); + + vc->codebooks = av_mallocz(vc->codebook_count * sizeof(*vc->codebooks)); + tmp_vlc_bits = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_bits)); + tmp_vlc_codes = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_codes)); + codebook_multiplicands = av_malloc(V_MAX_VLCS * sizeof(*codebook_multiplicands)); + if (!vc->codebooks || + !tmp_vlc_bits || !tmp_vlc_codes || !codebook_multiplicands) { + ret = AVERROR(ENOMEM); + goto error; + } + + for (cb = 0; cb < vc->codebook_count; ++cb) { + vorbis_codebook *codebook_setup = &vc->codebooks[cb]; + unsigned ordered, t, entries, used_entries = 0; + + av_dlog(NULL, " %u. Codebook\n", cb); + + if (get_bits(gb, 24) != 0x564342) { + av_log(vc->avctx, AV_LOG_ERROR, + " %u. Codebook setup data corrupt.\n", cb); + ret = AVERROR_INVALIDDATA; + goto error; + } + + codebook_setup->dimensions=get_bits(gb, 16); + if (codebook_setup->dimensions > 16 || codebook_setup->dimensions == 0) { + av_log(vc->avctx, AV_LOG_ERROR, + " %u. Codebook's dimension is invalid (%d).\n", + cb, codebook_setup->dimensions); + ret = AVERROR_INVALIDDATA; + goto error; + } + entries = get_bits(gb, 24); + if (entries > V_MAX_VLCS) { + av_log(vc->avctx, AV_LOG_ERROR, + " %u. Codebook has too many entries (%u).\n", + cb, entries); + ret = AVERROR_INVALIDDATA; + goto error; + } + + ordered = get_bits1(gb); + + av_dlog(NULL, " codebook_dimensions %d, codebook_entries %u\n", + codebook_setup->dimensions, entries); + + if (!ordered) { + unsigned ce, flag; + unsigned sparse = get_bits1(gb); + + av_dlog(NULL, " not ordered \n"); + + if (sparse) { + av_dlog(NULL, " sparse \n"); + + used_entries = 0; + for (ce = 0; ce < entries; ++ce) { + flag = get_bits1(gb); + if (flag) { + tmp_vlc_bits[ce] = get_bits(gb, 5) + 1; + ++used_entries; + } else + tmp_vlc_bits[ce] = 0; + } + } else { + av_dlog(NULL, " not sparse \n"); + + used_entries = entries; + for (ce = 0; ce < entries; ++ce) + tmp_vlc_bits[ce] = get_bits(gb, 5) + 1; + } + } else { + unsigned current_entry = 0; + unsigned current_length = get_bits(gb, 5) + 1; + + av_dlog(NULL, " ordered, current length: %u\n", current_length); //FIXME + + used_entries = entries; + for (; current_entry < used_entries && current_length <= 32; ++current_length) { + unsigned i, number; + + av_dlog(NULL, " number bits: %u ", ilog(entries - current_entry)); + + number = get_bits(gb, ilog(entries - current_entry)); + + av_dlog(NULL, " number: %u\n", number); + + for (i = current_entry; i < number+current_entry; ++i) + if (i < used_entries) + tmp_vlc_bits[i] = current_length; + + current_entry+=number; + } + if (current_entry>used_entries) { + av_log(vc->avctx, AV_LOG_ERROR, " More codelengths than codes in codebook. \n"); + ret = AVERROR_INVALIDDATA; + goto error; + } + } + + codebook_setup->lookup_type = get_bits(gb, 4); + + av_dlog(NULL, " lookup type: %d : %s \n", codebook_setup->lookup_type, + codebook_setup->lookup_type ? "vq" : "no lookup"); + +// If the codebook is used for (inverse) VQ, calculate codevectors. + + if (codebook_setup->lookup_type == 1) { + unsigned i, j, k; + unsigned codebook_lookup_values = ff_vorbis_nth_root(entries, codebook_setup->dimensions); + + float codebook_minimum_value = vorbisfloat2float(get_bits_long(gb, 32)); + float codebook_delta_value = vorbisfloat2float(get_bits_long(gb, 32)); + unsigned codebook_value_bits = get_bits(gb, 4) + 1; + unsigned codebook_sequence_p = get_bits1(gb); + + av_dlog(NULL, " We expect %d numbers for building the codevectors. \n", + codebook_lookup_values); + av_dlog(NULL, " delta %f minmum %f \n", + codebook_delta_value, codebook_minimum_value); + + for (i = 0; i < codebook_lookup_values; ++i) { + codebook_multiplicands[i] = get_bits(gb, codebook_value_bits); + + av_dlog(NULL, " multiplicands*delta+minmum : %e \n", + (float)codebook_multiplicands[i] * codebook_delta_value + codebook_minimum_value); + av_dlog(NULL, " multiplicand %u\n", codebook_multiplicands[i]); + } + +// Weed out unused vlcs and build codevector vector + codebook_setup->codevectors = used_entries ? av_mallocz(used_entries * + codebook_setup->dimensions * + sizeof(*codebook_setup->codevectors)) + : NULL; + for (j = 0, i = 0; i < entries; ++i) { + unsigned dim = codebook_setup->dimensions; + + if (tmp_vlc_bits[i]) { + float last = 0.0; + unsigned lookup_offset = i; + + av_dlog(vc->avctx, "Lookup offset %u ,", i); + + for (k = 0; k < dim; ++k) { + unsigned multiplicand_offset = lookup_offset % codebook_lookup_values; + codebook_setup->codevectors[j * dim + k] = codebook_multiplicands[multiplicand_offset] * codebook_delta_value + codebook_minimum_value + last; + if (codebook_sequence_p) + last = codebook_setup->codevectors[j * dim + k]; + lookup_offset/=codebook_lookup_values; + } + tmp_vlc_bits[j] = tmp_vlc_bits[i]; + + av_dlog(vc->avctx, "real lookup offset %u, vector: ", j); + for (k = 0; k < dim; ++k) + av_dlog(vc->avctx, " %f ", + codebook_setup->codevectors[j * dim + k]); + av_dlog(vc->avctx, "\n"); + + ++j; + } + } + if (j != used_entries) { + av_log(vc->avctx, AV_LOG_ERROR, "Bug in codevector vector building code. \n"); + ret = AVERROR_INVALIDDATA; + goto error; + } + entries = used_entries; + } else if (codebook_setup->lookup_type >= 2) { + av_log(vc->avctx, AV_LOG_ERROR, "Codebook lookup type not supported. \n"); + ret = AVERROR_INVALIDDATA; + goto error; + } + +// Initialize VLC table + if (ff_vorbis_len2vlc(tmp_vlc_bits, tmp_vlc_codes, entries)) { + av_log(vc->avctx, AV_LOG_ERROR, " Invalid code lengths while generating vlcs. \n"); + ret = AVERROR_INVALIDDATA; + goto error; + } + codebook_setup->maxdepth = 0; + for (t = 0; t < entries; ++t) + if (tmp_vlc_bits[t] >= codebook_setup->maxdepth) + codebook_setup->maxdepth = tmp_vlc_bits[t]; + + if (codebook_setup->maxdepth > 3 * V_NB_BITS) + codebook_setup->nb_bits = V_NB_BITS2; + else + codebook_setup->nb_bits = V_NB_BITS; + + codebook_setup->maxdepth = (codebook_setup->maxdepth+codebook_setup->nb_bits - 1) / codebook_setup->nb_bits; + + if ((ret = init_vlc(&codebook_setup->vlc, codebook_setup->nb_bits, + entries, tmp_vlc_bits, sizeof(*tmp_vlc_bits), + sizeof(*tmp_vlc_bits), tmp_vlc_codes, + sizeof(*tmp_vlc_codes), sizeof(*tmp_vlc_codes), + INIT_VLC_LE))) { + av_log(vc->avctx, AV_LOG_ERROR, " Error generating vlc tables. \n"); + goto error; + } + } + + av_free(tmp_vlc_bits); + av_free(tmp_vlc_codes); + av_free(codebook_multiplicands); + return 0; + +// Error: +error: + av_free(tmp_vlc_bits); + av_free(tmp_vlc_codes); + av_free(codebook_multiplicands); + return ret; +} + +// Process time domain transforms part (unused in Vorbis I) + +static int vorbis_parse_setup_hdr_tdtransforms(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + unsigned i, vorbis_time_count = get_bits(gb, 6) + 1; + + for (i = 0; i < vorbis_time_count; ++i) { + unsigned vorbis_tdtransform = get_bits(gb, 16); + + av_dlog(NULL, " Vorbis time domain transform %u: %u\n", + vorbis_time_count, vorbis_tdtransform); + + if (vorbis_tdtransform) { + av_log(vc->avctx, AV_LOG_ERROR, "Vorbis time domain transform data nonzero. \n"); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + +// Process floors part + +static int vorbis_floor0_decode(vorbis_context *vc, + vorbis_floor_data *vfu, float *vec); +static int create_map(vorbis_context *vc, unsigned floor_number); +static int vorbis_floor1_decode(vorbis_context *vc, + vorbis_floor_data *vfu, float *vec); +static int vorbis_parse_setup_hdr_floors(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + int i, j, k, ret; + + vc->floor_count = get_bits(gb, 6) + 1; + + vc->floors = av_mallocz(vc->floor_count * sizeof(*vc->floors)); + if (!vc->floors) + return AVERROR(ENOMEM); + + for (i = 0; i < vc->floor_count; ++i) { + vorbis_floor *floor_setup = &vc->floors[i]; + + floor_setup->floor_type = get_bits(gb, 16); + + av_dlog(NULL, " %d. floor type %d \n", i, floor_setup->floor_type); + + if (floor_setup->floor_type == 1) { + int maximum_class = -1; + unsigned rangebits, rangemax, floor1_values = 2; + + floor_setup->decode = vorbis_floor1_decode; + + floor_setup->data.t1.partitions = get_bits(gb, 5); + + av_dlog(NULL, " %d.floor: %d partitions \n", + i, floor_setup->data.t1.partitions); + + for (j = 0; j < floor_setup->data.t1.partitions; ++j) { + floor_setup->data.t1.partition_class[j] = get_bits(gb, 4); + if (floor_setup->data.t1.partition_class[j] > maximum_class) + maximum_class = floor_setup->data.t1.partition_class[j]; + + av_dlog(NULL, " %d. floor %d partition class %d \n", + i, j, floor_setup->data.t1.partition_class[j]); + + } + + av_dlog(NULL, " maximum class %d \n", maximum_class); + + for (j = 0; j <= maximum_class; ++j) { + floor_setup->data.t1.class_dimensions[j] = get_bits(gb, 3) + 1; + floor_setup->data.t1.class_subclasses[j] = get_bits(gb, 2); + + av_dlog(NULL, " %d floor %d class dim: %d subclasses %d \n", i, j, + floor_setup->data.t1.class_dimensions[j], + floor_setup->data.t1.class_subclasses[j]); + + if (floor_setup->data.t1.class_subclasses[j]) { + GET_VALIDATED_INDEX(floor_setup->data.t1.class_masterbook[j], 8, vc->codebook_count) + + av_dlog(NULL, " masterbook: %d \n", floor_setup->data.t1.class_masterbook[j]); + } + + for (k = 0; k < (1 << floor_setup->data.t1.class_subclasses[j]); ++k) { + int16_t bits = get_bits(gb, 8) - 1; + if (bits != -1) + VALIDATE_INDEX(bits, vc->codebook_count) + floor_setup->data.t1.subclass_books[j][k] = bits; + + av_dlog(NULL, " book %d. : %d \n", k, floor_setup->data.t1.subclass_books[j][k]); + } + } + + floor_setup->data.t1.multiplier = get_bits(gb, 2) + 1; + floor_setup->data.t1.x_list_dim = 2; + + for (j = 0; j < floor_setup->data.t1.partitions; ++j) + floor_setup->data.t1.x_list_dim+=floor_setup->data.t1.class_dimensions[floor_setup->data.t1.partition_class[j]]; + + floor_setup->data.t1.list = av_mallocz(floor_setup->data.t1.x_list_dim * + sizeof(*floor_setup->data.t1.list)); + if (!floor_setup->data.t1.list) + return AVERROR(ENOMEM); + + rangebits = get_bits(gb, 4); + rangemax = (1 << rangebits); + if (rangemax > vc->blocksize[1] / 2) { + av_log(vc->avctx, AV_LOG_ERROR, + "Floor value is too large for blocksize: %u (%"PRIu32")\n", + rangemax, vc->blocksize[1] / 2); + return AVERROR_INVALIDDATA; + } + floor_setup->data.t1.list[0].x = 0; + floor_setup->data.t1.list[1].x = rangemax; + + for (j = 0; j < floor_setup->data.t1.partitions; ++j) { + for (k = 0; k < floor_setup->data.t1.class_dimensions[floor_setup->data.t1.partition_class[j]]; ++k, ++floor1_values) { + floor_setup->data.t1.list[floor1_values].x = get_bits(gb, rangebits); + + av_dlog(NULL, " %u. floor1 Y coord. %d\n", floor1_values, + floor_setup->data.t1.list[floor1_values].x); + } + } + +// Precalculate order of x coordinates - needed for decode + if (ff_vorbis_ready_floor1_list(vc->avctx, + floor_setup->data.t1.list, + floor_setup->data.t1.x_list_dim)) { + return AVERROR_INVALIDDATA; + } + } else if (floor_setup->floor_type == 0) { + unsigned max_codebook_dim = 0; + + floor_setup->decode = vorbis_floor0_decode; + + floor_setup->data.t0.order = get_bits(gb, 8); + if (!floor_setup->data.t0.order) { + av_log(vc->avctx, AV_LOG_ERROR, "Floor 0 order is 0.\n"); + return AVERROR_INVALIDDATA; + } + floor_setup->data.t0.rate = get_bits(gb, 16); + if (!floor_setup->data.t0.rate) { + av_log(vc->avctx, AV_LOG_ERROR, "Floor 0 rate is 0.\n"); + return AVERROR_INVALIDDATA; + } + floor_setup->data.t0.bark_map_size = get_bits(gb, 16); + if (!floor_setup->data.t0.bark_map_size) { + av_log(vc->avctx, AV_LOG_ERROR, + "Floor 0 bark map size is 0.\n"); + return AVERROR_INVALIDDATA; + } + floor_setup->data.t0.amplitude_bits = get_bits(gb, 6); + floor_setup->data.t0.amplitude_offset = get_bits(gb, 8); + floor_setup->data.t0.num_books = get_bits(gb, 4) + 1; + + /* allocate mem for booklist */ + floor_setup->data.t0.book_list = + av_malloc(floor_setup->data.t0.num_books); + if (!floor_setup->data.t0.book_list) + return AVERROR(ENOMEM); + /* read book indexes */ + { + int idx; + unsigned book_idx; + for (idx = 0; idx < floor_setup->data.t0.num_books; ++idx) { + GET_VALIDATED_INDEX(book_idx, 8, vc->codebook_count) + floor_setup->data.t0.book_list[idx] = book_idx; + if (vc->codebooks[book_idx].dimensions > max_codebook_dim) + max_codebook_dim = vc->codebooks[book_idx].dimensions; + } + } + + if ((ret = create_map(vc, i)) < 0) + return ret; + + /* codebook dim is for padding if codebook dim doesn't * + * divide order+1 then we need to read more data */ + floor_setup->data.t0.lsp = + av_malloc((floor_setup->data.t0.order + 1 + max_codebook_dim) + * sizeof(*floor_setup->data.t0.lsp)); + if (!floor_setup->data.t0.lsp) + return AVERROR(ENOMEM); + + /* debug output parsed headers */ + av_dlog(NULL, "floor0 order: %u\n", floor_setup->data.t0.order); + av_dlog(NULL, "floor0 rate: %u\n", floor_setup->data.t0.rate); + av_dlog(NULL, "floor0 bark map size: %u\n", + floor_setup->data.t0.bark_map_size); + av_dlog(NULL, "floor0 amplitude bits: %u\n", + floor_setup->data.t0.amplitude_bits); + av_dlog(NULL, "floor0 amplitude offset: %u\n", + floor_setup->data.t0.amplitude_offset); + av_dlog(NULL, "floor0 number of books: %u\n", + floor_setup->data.t0.num_books); + av_dlog(NULL, "floor0 book list pointer: %p\n", + floor_setup->data.t0.book_list); + { + int idx; + for (idx = 0; idx < floor_setup->data.t0.num_books; ++idx) { + av_dlog(NULL, " Book %d: %u\n", idx + 1, + floor_setup->data.t0.book_list[idx]); + } + } + } else { + av_log(vc->avctx, AV_LOG_ERROR, "Invalid floor type!\n"); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + +// Process residues part + +static int vorbis_parse_setup_hdr_residues(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + unsigned i, j, k; + + vc->residue_count = get_bits(gb, 6)+1; + vc->residues = av_mallocz(vc->residue_count * sizeof(*vc->residues)); + if (!vc->residues) + return AVERROR(ENOMEM); + + av_dlog(NULL, " There are %d residues. \n", vc->residue_count); + + for (i = 0; i < vc->residue_count; ++i) { + vorbis_residue *res_setup = &vc->residues[i]; + uint8_t cascade[64]; + unsigned high_bits, low_bits; + + res_setup->type = get_bits(gb, 16); + + av_dlog(NULL, " %u. residue type %d\n", i, res_setup->type); + + res_setup->begin = get_bits(gb, 24); + res_setup->end = get_bits(gb, 24); + res_setup->partition_size = get_bits(gb, 24) + 1; + /* Validations to prevent a buffer overflow later. */ + if (res_setup->begin>res_setup->end || + res_setup->end > (res_setup->type == 2 ? vc->audio_channels : 1) * vc->blocksize[1] / 2 || + (res_setup->end-res_setup->begin) / res_setup->partition_size > V_MAX_PARTITIONS) { + av_log(vc->avctx, AV_LOG_ERROR, + "partition out of bounds: type, begin, end, size, blocksize: %"PRIu16", %"PRIu32", %"PRIu32", %u, %"PRIu32"\n", + res_setup->type, res_setup->begin, res_setup->end, + res_setup->partition_size, vc->blocksize[1] / 2); + return AVERROR_INVALIDDATA; + } + + res_setup->classifications = get_bits(gb, 6) + 1; + GET_VALIDATED_INDEX(res_setup->classbook, 8, vc->codebook_count) + + res_setup->ptns_to_read = + (res_setup->end - res_setup->begin) / res_setup->partition_size; + res_setup->classifs = av_malloc(res_setup->ptns_to_read * + vc->audio_channels * + sizeof(*res_setup->classifs)); + if (!res_setup->classifs) + return AVERROR(ENOMEM); + + av_dlog(NULL, " begin %d end %d part.size %d classif.s %d classbook %d \n", + res_setup->begin, res_setup->end, res_setup->partition_size, + res_setup->classifications, res_setup->classbook); + + for (j = 0; j < res_setup->classifications; ++j) { + high_bits = 0; + low_bits = get_bits(gb, 3); + if (get_bits1(gb)) + high_bits = get_bits(gb, 5); + cascade[j] = (high_bits << 3) + low_bits; + + av_dlog(NULL, " %u class cascade depth: %d\n", j, ilog(cascade[j])); + } + + res_setup->maxpass = 0; + for (j = 0; j < res_setup->classifications; ++j) { + for (k = 0; k < 8; ++k) { + if (cascade[j]&(1 << k)) { + GET_VALIDATED_INDEX(res_setup->books[j][k], 8, vc->codebook_count) + + av_dlog(NULL, " %u class cascade depth %u book: %d\n", + j, k, res_setup->books[j][k]); + + if (k>res_setup->maxpass) + res_setup->maxpass = k; + } else { + res_setup->books[j][k] = -1; + } + } + } + } + return 0; +} + +// Process mappings part + +static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + unsigned i, j; + + vc->mapping_count = get_bits(gb, 6)+1; + vc->mappings = av_mallocz(vc->mapping_count * sizeof(*vc->mappings)); + if (!vc->mappings) + return AVERROR(ENOMEM); + + av_dlog(NULL, " There are %d mappings. \n", vc->mapping_count); + + for (i = 0; i < vc->mapping_count; ++i) { + vorbis_mapping *mapping_setup = &vc->mappings[i]; + + if (get_bits(gb, 16)) { + av_log(vc->avctx, AV_LOG_ERROR, "Other mappings than type 0 are not compliant with the Vorbis I specification. \n"); + return AVERROR_INVALIDDATA; + } + if (get_bits1(gb)) { + mapping_setup->submaps = get_bits(gb, 4) + 1; + } else { + mapping_setup->submaps = 1; + } + + if (get_bits1(gb)) { + mapping_setup->coupling_steps = get_bits(gb, 8) + 1; + mapping_setup->magnitude = av_mallocz(mapping_setup->coupling_steps * + sizeof(*mapping_setup->magnitude)); + mapping_setup->angle = av_mallocz(mapping_setup->coupling_steps * + sizeof(*mapping_setup->angle)); + if (!mapping_setup->angle || !mapping_setup->magnitude) + return AVERROR(ENOMEM); + + for (j = 0; j < mapping_setup->coupling_steps; ++j) { + GET_VALIDATED_INDEX(mapping_setup->magnitude[j], ilog(vc->audio_channels - 1), vc->audio_channels) + GET_VALIDATED_INDEX(mapping_setup->angle[j], ilog(vc->audio_channels - 1), vc->audio_channels) + } + } else { + mapping_setup->coupling_steps = 0; + } + + av_dlog(NULL, " %u mapping coupling steps: %d\n", + i, mapping_setup->coupling_steps); + + if (get_bits(gb, 2)) { + av_log(vc->avctx, AV_LOG_ERROR, "%u. mapping setup data invalid.\n", i); + return AVERROR_INVALIDDATA; // following spec. + } + + if (mapping_setup->submaps>1) { + mapping_setup->mux = av_mallocz(vc->audio_channels * + sizeof(*mapping_setup->mux)); + if (!mapping_setup->mux) + return AVERROR(ENOMEM); + + for (j = 0; j < vc->audio_channels; ++j) + mapping_setup->mux[j] = get_bits(gb, 4); + } + + for (j = 0; j < mapping_setup->submaps; ++j) { + skip_bits(gb, 8); // FIXME check? + GET_VALIDATED_INDEX(mapping_setup->submap_floor[j], 8, vc->floor_count) + GET_VALIDATED_INDEX(mapping_setup->submap_residue[j], 8, vc->residue_count) + + av_dlog(NULL, " %u mapping %u submap : floor %d, residue %d\n", i, j, + mapping_setup->submap_floor[j], + mapping_setup->submap_residue[j]); + } + } + return 0; +} + +// Process modes part + +static int create_map(vorbis_context *vc, unsigned floor_number) +{ + vorbis_floor *floors = vc->floors; + vorbis_floor0 *vf; + int idx; + int blockflag, n; + int32_t *map; + + for (blockflag = 0; blockflag < 2; ++blockflag) { + n = vc->blocksize[blockflag] / 2; + floors[floor_number].data.t0.map[blockflag] = + av_malloc((n + 1) * sizeof(int32_t)); // n + sentinel + if (!floors[floor_number].data.t0.map[blockflag]) + return AVERROR(ENOMEM); + + map = floors[floor_number].data.t0.map[blockflag]; + vf = &floors[floor_number].data.t0; + + for (idx = 0; idx < n; ++idx) { + map[idx] = floor(BARK((vf->rate * idx) / (2.0f * n)) * + (vf->bark_map_size / BARK(vf->rate / 2.0f))); + if (vf->bark_map_size-1 < map[idx]) + map[idx] = vf->bark_map_size - 1; + } + map[n] = -1; + vf->map_size[blockflag] = n; + } + + for (idx = 0; idx <= n; ++idx) { + av_dlog(NULL, "floor0 map: map at pos %d is %d\n", idx, map[idx]); + } + + return 0; +} + +static int vorbis_parse_setup_hdr_modes(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + unsigned i; + + vc->mode_count = get_bits(gb, 6) + 1; + vc->modes = av_mallocz(vc->mode_count * sizeof(*vc->modes)); + if (!vc->modes) + return AVERROR(ENOMEM); + + av_dlog(NULL, " There are %d modes.\n", vc->mode_count); + + for (i = 0; i < vc->mode_count; ++i) { + vorbis_mode *mode_setup = &vc->modes[i]; + + mode_setup->blockflag = get_bits1(gb); + mode_setup->windowtype = get_bits(gb, 16); //FIXME check + mode_setup->transformtype = get_bits(gb, 16); //FIXME check + GET_VALIDATED_INDEX(mode_setup->mapping, 8, vc->mapping_count); + + av_dlog(NULL, " %u mode: blockflag %d, windowtype %d, transformtype %d, mapping %d\n", + i, mode_setup->blockflag, mode_setup->windowtype, + mode_setup->transformtype, mode_setup->mapping); + } + return 0; +} + +// Process the whole setup header using the functions above + +static int vorbis_parse_setup_hdr(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + int ret; + + if ((get_bits(gb, 8) != 'v') || (get_bits(gb, 8) != 'o') || + (get_bits(gb, 8) != 'r') || (get_bits(gb, 8) != 'b') || + (get_bits(gb, 8) != 'i') || (get_bits(gb, 8) != 's')) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (no vorbis signature). \n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = vorbis_parse_setup_hdr_codebooks(vc))) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (codebooks). \n"); + return ret; + } + if ((ret = vorbis_parse_setup_hdr_tdtransforms(vc))) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (time domain transforms). \n"); + return ret; + } + if ((ret = vorbis_parse_setup_hdr_floors(vc))) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (floors). \n"); + return ret; + } + if ((ret = vorbis_parse_setup_hdr_residues(vc))) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (residues). \n"); + return ret; + } + if ((ret = vorbis_parse_setup_hdr_mappings(vc))) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (mappings). \n"); + return ret; + } + if ((ret = vorbis_parse_setup_hdr_modes(vc))) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (modes). \n"); + return ret; + } + if (!get_bits1(gb)) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis setup header packet corrupt (framing flag). \n"); + return AVERROR_INVALIDDATA; // framing flag bit unset error + } + + return 0; +} + +// Process the identification header + +static int vorbis_parse_id_hdr(vorbis_context *vc) +{ + GetBitContext *gb = &vc->gb; + unsigned bl0, bl1; + + if ((get_bits(gb, 8) != 'v') || (get_bits(gb, 8) != 'o') || + (get_bits(gb, 8) != 'r') || (get_bits(gb, 8) != 'b') || + (get_bits(gb, 8) != 'i') || (get_bits(gb, 8) != 's')) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis id header packet corrupt (no vorbis signature). \n"); + return AVERROR_INVALIDDATA; + } + + vc->version = get_bits_long(gb, 32); //FIXME check 0 + vc->audio_channels = get_bits(gb, 8); + if (vc->audio_channels <= 0) { + av_log(vc->avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } + vc->audio_samplerate = get_bits_long(gb, 32); + if (vc->audio_samplerate <= 0) { + av_log(vc->avctx, AV_LOG_ERROR, "Invalid samplerate\n"); + return AVERROR_INVALIDDATA; + } + vc->bitrate_maximum = get_bits_long(gb, 32); + vc->bitrate_nominal = get_bits_long(gb, 32); + vc->bitrate_minimum = get_bits_long(gb, 32); + bl0 = get_bits(gb, 4); + bl1 = get_bits(gb, 4); + if (bl0 > 13 || bl0 < 6 || bl1 > 13 || bl1 < 6 || bl1 < bl0) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis id header packet corrupt (illegal blocksize). \n"); + return AVERROR_INVALIDDATA; + } + vc->blocksize[0] = (1 << bl0); + vc->blocksize[1] = (1 << bl1); + vc->win[0] = ff_vorbis_vwin[bl0 - 6]; + vc->win[1] = ff_vorbis_vwin[bl1 - 6]; + + if ((get_bits1(gb)) == 0) { + av_log(vc->avctx, AV_LOG_ERROR, " Vorbis id header packet corrupt (framing flag not set). \n"); + return AVERROR_INVALIDDATA; + } + + vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues)); + vc->saved = av_mallocz((vc->blocksize[1] / 4) * vc->audio_channels * sizeof(*vc->saved)); + if (!vc->channel_residues || !vc->saved) + return AVERROR(ENOMEM); + + vc->previous_window = 0; + + ff_mdct_init(&vc->mdct[0], bl0, 1, -1.0); + ff_mdct_init(&vc->mdct[1], bl1, 1, -1.0); + + av_dlog(NULL, " vorbis version %d \n audio_channels %d \n audio_samplerate %d \n bitrate_max %d \n bitrate_nom %d \n bitrate_min %d \n blk_0 %d blk_1 %d \n ", + vc->version, vc->audio_channels, vc->audio_samplerate, vc->bitrate_maximum, vc->bitrate_nominal, vc->bitrate_minimum, vc->blocksize[0], vc->blocksize[1]); + +/* + BLK = vc->blocksize[0]; + for (i = 0; i < BLK / 2; ++i) { + vc->win[0][i] = sin(0.5*3.14159265358*(sin(((float)i + 0.5) / (float)BLK*3.14159265358))*(sin(((float)i + 0.5) / (float)BLK*3.14159265358))); + } +*/ + + return 0; +} + +// Process the extradata using the functions above (identification header, setup header) + +static av_cold int vorbis_decode_init(AVCodecContext *avctx) +{ + vorbis_context *vc = avctx->priv_data; + uint8_t *headers = avctx->extradata; + int headers_len = avctx->extradata_size; + uint8_t *header_start[3]; + int header_len[3]; + GetBitContext *gb = &vc->gb; + int hdr_type, ret; + + vc->avctx = avctx; + ff_vorbisdsp_init(&vc->dsp); + avpriv_float_dsp_init(&vc->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + ff_fmt_convert_init(&vc->fmt_conv, avctx); + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + if (!headers_len) { + av_log(avctx, AV_LOG_ERROR, "Extradata missing.\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = avpriv_split_xiph_headers(headers, headers_len, 30, header_start, header_len)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Extradata corrupt.\n"); + return ret; + } + + init_get_bits(gb, header_start[0], header_len[0]*8); + hdr_type = get_bits(gb, 8); + if (hdr_type != 1) { + av_log(avctx, AV_LOG_ERROR, "First header is not the id header.\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = vorbis_parse_id_hdr(vc))) { + av_log(avctx, AV_LOG_ERROR, "Id header corrupt.\n"); + vorbis_free(vc); + return ret; + } + + init_get_bits(gb, header_start[2], header_len[2]*8); + hdr_type = get_bits(gb, 8); + if (hdr_type != 5) { + av_log(avctx, AV_LOG_ERROR, "Third header is not the setup header.\n"); + vorbis_free(vc); + return AVERROR_INVALIDDATA; + } + if ((ret = vorbis_parse_setup_hdr(vc))) { + av_log(avctx, AV_LOG_ERROR, "Setup header corrupt.\n"); + vorbis_free(vc); + return ret; + } + + if (vc->audio_channels > 8) + avctx->channel_layout = 0; + else + avctx->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1]; + + avctx->channels = vc->audio_channels; + avctx->sample_rate = vc->audio_samplerate; + + return 0; +} + +// Decode audiopackets ------------------------------------------------- + +// Read and decode floor + +static int vorbis_floor0_decode(vorbis_context *vc, + vorbis_floor_data *vfu, float *vec) +{ + vorbis_floor0 *vf = &vfu->t0; + float *lsp = vf->lsp; + unsigned amplitude, book_idx; + unsigned blockflag = vc->modes[vc->mode_number].blockflag; + + if (!vf->amplitude_bits) + return 1; + + amplitude = get_bits(&vc->gb, vf->amplitude_bits); + if (amplitude > 0) { + float last = 0; + unsigned idx, lsp_len = 0; + vorbis_codebook codebook; + + book_idx = get_bits(&vc->gb, ilog(vf->num_books)); + if (book_idx >= vf->num_books) { + av_log(vc->avctx, AV_LOG_ERROR, "floor0 dec: booknumber too high!\n"); + book_idx = 0; + } + av_dlog(NULL, "floor0 dec: booknumber: %u\n", book_idx); + codebook = vc->codebooks[vf->book_list[book_idx]]; + /* Invalid codebook! */ + if (!codebook.codevectors) + return AVERROR_INVALIDDATA; + + while (lsp_lenorder) { + int vec_off; + + av_dlog(NULL, "floor0 dec: book dimension: %d\n", codebook.dimensions); + av_dlog(NULL, "floor0 dec: maximum depth: %d\n", codebook.maxdepth); + /* read temp vector */ + vec_off = get_vlc2(&vc->gb, codebook.vlc.table, + codebook.nb_bits, codebook.maxdepth) + * codebook.dimensions; + av_dlog(NULL, "floor0 dec: vector offset: %d\n", vec_off); + /* copy each vector component and add last to it */ + for (idx = 0; idx < codebook.dimensions; ++idx) + lsp[lsp_len+idx] = codebook.codevectors[vec_off+idx] + last; + last = lsp[lsp_len+idx-1]; /* set last to last vector component */ + + lsp_len += codebook.dimensions; + } + /* DEBUG: output lsp coeffs */ + { + int idx; + for (idx = 0; idx < lsp_len; ++idx) + av_dlog(NULL, "floor0 dec: coeff at %d is %f\n", idx, lsp[idx]); + } + + /* synthesize floor output vector */ + { + int i; + int order = vf->order; + float wstep = M_PI / vf->bark_map_size; + + for (i = 0; i < order; i++) + lsp[i] = 2.0f * cos(lsp[i]); + + av_dlog(NULL, "floor0 synth: map_size = %"PRIu32"; m = %d; wstep = %f\n", + vf->map_size[blockflag], order, wstep); + + i = 0; + while (i < vf->map_size[blockflag]) { + int j, iter_cond = vf->map[blockflag][i]; + float p = 0.5f; + float q = 0.5f; + float two_cos_w = 2.0f * cos(wstep * iter_cond); // needed all times + + /* similar part for the q and p products */ + for (j = 0; j + 1 < order; j += 2) { + q *= lsp[j] - two_cos_w; + p *= lsp[j + 1] - two_cos_w; + } + if (j == order) { // even order + p *= p * (2.0f - two_cos_w); + q *= q * (2.0f + two_cos_w); + } else { // odd order + q *= two_cos_w-lsp[j]; // one more time for q + + /* final step and square */ + p *= p * (4.f - two_cos_w * two_cos_w); + q *= q; + } + + /* calculate linear floor value */ + q = exp((((amplitude*vf->amplitude_offset) / + (((1 << vf->amplitude_bits) - 1) * sqrt(p + q))) + - vf->amplitude_offset) * .11512925f); + + /* fill vector */ + do { + vec[i] = q; ++i; + } while (vf->map[blockflag][i] == iter_cond); + } + } + } else { + /* this channel is unused */ + return 1; + } + + av_dlog(NULL, " Floor0 decoded\n"); + + return 0; +} + +static int vorbis_floor1_decode(vorbis_context *vc, + vorbis_floor_data *vfu, float *vec) +{ + vorbis_floor1 *vf = &vfu->t1; + GetBitContext *gb = &vc->gb; + uint16_t range_v[4] = { 256, 128, 86, 64 }; + unsigned range = range_v[vf->multiplier - 1]; + uint16_t floor1_Y[258]; + uint16_t floor1_Y_final[258]; + int floor1_flag[258]; + unsigned partition_class, cdim, cbits, csub, cval, offset, i, j; + int book, adx, ady, dy, off, predicted, err; + + + if (!get_bits1(gb)) // silence + return 1; + +// Read values (or differences) for the floor's points + + floor1_Y[0] = get_bits(gb, ilog(range - 1)); + floor1_Y[1] = get_bits(gb, ilog(range - 1)); + + av_dlog(NULL, "floor 0 Y %d floor 1 Y %d \n", floor1_Y[0], floor1_Y[1]); + + offset = 2; + for (i = 0; i < vf->partitions; ++i) { + partition_class = vf->partition_class[i]; + cdim = vf->class_dimensions[partition_class]; + cbits = vf->class_subclasses[partition_class]; + csub = (1 << cbits) - 1; + cval = 0; + + av_dlog(NULL, "Cbits %u\n", cbits); + + if (cbits) // this reads all subclasses for this partition's class + cval = get_vlc2(gb, vc->codebooks[vf->class_masterbook[partition_class]].vlc.table, + vc->codebooks[vf->class_masterbook[partition_class]].nb_bits, 3); + + for (j = 0; j < cdim; ++j) { + book = vf->subclass_books[partition_class][cval & csub]; + + av_dlog(NULL, "book %d Cbits %u cval %u bits:%d\n", + book, cbits, cval, get_bits_count(gb)); + + cval = cval >> cbits; + if (book > -1) { + floor1_Y[offset+j] = get_vlc2(gb, vc->codebooks[book].vlc.table, + vc->codebooks[book].nb_bits, 3); + } else { + floor1_Y[offset+j] = 0; + } + + av_dlog(NULL, " floor(%d) = %d \n", + vf->list[offset+j].x, floor1_Y[offset+j]); + } + offset+=cdim; + } + +// Amplitude calculation from the differences + + floor1_flag[0] = 1; + floor1_flag[1] = 1; + floor1_Y_final[0] = floor1_Y[0]; + floor1_Y_final[1] = floor1_Y[1]; + + for (i = 2; i < vf->x_list_dim; ++i) { + unsigned val, highroom, lowroom, room, high_neigh_offs, low_neigh_offs; + + low_neigh_offs = vf->list[i].low; + high_neigh_offs = vf->list[i].high; + dy = floor1_Y_final[high_neigh_offs] - floor1_Y_final[low_neigh_offs]; // render_point begin + adx = vf->list[high_neigh_offs].x - vf->list[low_neigh_offs].x; + ady = FFABS(dy); + err = ady * (vf->list[i].x - vf->list[low_neigh_offs].x); + off = err / adx; + if (dy < 0) { + predicted = floor1_Y_final[low_neigh_offs] - off; + } else { + predicted = floor1_Y_final[low_neigh_offs] + off; + } // render_point end + + val = floor1_Y[i]; + highroom = range-predicted; + lowroom = predicted; + if (highroom < lowroom) { + room = highroom * 2; + } else { + room = lowroom * 2; // SPEC misspelling + } + if (val) { + floor1_flag[low_neigh_offs] = 1; + floor1_flag[high_neigh_offs] = 1; + floor1_flag[i] = 1; + if (val >= room) { + if (highroom > lowroom) { + floor1_Y_final[i] = av_clip_uint16(val - lowroom + predicted); + } else { + floor1_Y_final[i] = av_clip_uint16(predicted - val + highroom - 1); + } + } else { + if (val & 1) { + floor1_Y_final[i] = av_clip_uint16(predicted - (val + 1) / 2); + } else { + floor1_Y_final[i] = av_clip_uint16(predicted + val / 2); + } + } + } else { + floor1_flag[i] = 0; + floor1_Y_final[i] = av_clip_uint16(predicted); + } + + av_dlog(NULL, " Decoded floor(%d) = %u / val %u\n", + vf->list[i].x, floor1_Y_final[i], val); + } + +// Curve synth - connect the calculated dots and convert from dB scale FIXME optimize ? + + ff_vorbis_floor1_render_list(vf->list, vf->x_list_dim, floor1_Y_final, floor1_flag, vf->multiplier, vec, vf->list[1].x); + + av_dlog(NULL, " Floor decoded\n"); + + return 0; +} + +// Read and decode residue + +static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc, + vorbis_residue *vr, + unsigned ch, + uint8_t *do_not_decode, + float *vec, + unsigned vlen, + unsigned ch_left, + int vr_type) +{ + GetBitContext *gb = &vc->gb; + unsigned c_p_c = vc->codebooks[vr->classbook].dimensions; + unsigned ptns_to_read = vr->ptns_to_read; + uint8_t *classifs = vr->classifs; + unsigned pass, ch_used, i, j, k, l; + unsigned max_output = (ch - 1) * vlen; + + if (vr_type == 2) { + for (j = 1; j < ch; ++j) + do_not_decode[0] &= do_not_decode[j]; // FIXME - clobbering input + if (do_not_decode[0]) + return 0; + ch_used = 1; + max_output += vr->end / ch; + } else { + ch_used = ch; + max_output += vr->end; + } + + if (max_output > ch_left * vlen) { + av_log(vc->avctx, AV_LOG_ERROR, "Insufficient output buffer\n"); + return -1; + } + + av_dlog(NULL, " residue type 0/1/2 decode begin, ch: %d cpc %d \n", ch, c_p_c); + + for (pass = 0; pass <= vr->maxpass; ++pass) { // FIXME OPTIMIZE? + uint16_t voffset, partition_count, j_times_ptns_to_read; + + voffset = vr->begin; + for (partition_count = 0; partition_count < ptns_to_read;) { // SPEC error + if (!pass) { + unsigned inverse_class = ff_inverse[vr->classifications]; + for (j_times_ptns_to_read = 0, j = 0; j < ch_used; ++j) { + if (!do_not_decode[j]) { + unsigned temp = get_vlc2(gb, vc->codebooks[vr->classbook].vlc.table, + vc->codebooks[vr->classbook].nb_bits, 3); + + av_dlog(NULL, "Classword: %u\n", temp); + + av_assert0(vr->classifications > 1 && temp <= 65536); //needed for inverse[] + for (i = 0; i < c_p_c; ++i) { + unsigned temp2; + + temp2 = (((uint64_t)temp) * inverse_class) >> 32; + if (partition_count + c_p_c - 1 - i < ptns_to_read) + classifs[j_times_ptns_to_read + partition_count + c_p_c - 1 - i] = temp - temp2 * vr->classifications; + temp = temp2; + } + } + j_times_ptns_to_read += ptns_to_read; + } + } + for (i = 0; (i < c_p_c) && (partition_count < ptns_to_read); ++i) { + for (j_times_ptns_to_read = 0, j = 0; j < ch_used; ++j) { + unsigned voffs; + + if (!do_not_decode[j]) { + unsigned vqclass = classifs[j_times_ptns_to_read + partition_count]; + int vqbook = vr->books[vqclass][pass]; + + if (vqbook >= 0 && vc->codebooks[vqbook].codevectors) { + unsigned coffs; + unsigned dim = vc->codebooks[vqbook].dimensions; + unsigned step = FASTDIV(vr->partition_size << 1, dim << 1); + vorbis_codebook codebook = vc->codebooks[vqbook]; + + if (vr_type == 0) { + + voffs = voffset+j*vlen; + for (k = 0; k < step; ++k) { + coffs = get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; + for (l = 0; l < dim; ++l) + vec[voffs + k + l * step] += codebook.codevectors[coffs + l]; + } + } else if (vr_type == 1) { + voffs = voffset + j * vlen; + for (k = 0; k < step; ++k) { + coffs = get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; + for (l = 0; l < dim; ++l, ++voffs) { + vec[voffs]+=codebook.codevectors[coffs+l]; + + av_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d \n", + pass, voffs, vec[voffs], codebook.codevectors[coffs+l], coffs); + } + } + } else if (vr_type == 2 && ch == 2 && (voffset & 1) == 0 && (dim & 1) == 0) { // most frequent case optimized + voffs = voffset >> 1; + + if (dim == 2) { + for (k = 0; k < step; ++k) { + coffs = get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * 2; + vec[voffs + k ] += codebook.codevectors[coffs ]; + vec[voffs + k + vlen] += codebook.codevectors[coffs + 1]; + } + } else if (dim == 4) { + for (k = 0; k < step; ++k, voffs += 2) { + coffs = get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * 4; + vec[voffs ] += codebook.codevectors[coffs ]; + vec[voffs + 1 ] += codebook.codevectors[coffs + 2]; + vec[voffs + vlen ] += codebook.codevectors[coffs + 1]; + vec[voffs + vlen + 1] += codebook.codevectors[coffs + 3]; + } + } else + for (k = 0; k < step; ++k) { + coffs = get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; + for (l = 0; l < dim; l += 2, voffs++) { + vec[voffs ] += codebook.codevectors[coffs + l ]; + vec[voffs + vlen] += codebook.codevectors[coffs + l + 1]; + + av_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", + pass, voffset / ch + (voffs % ch) * vlen, + vec[voffset / ch + (voffs % ch) * vlen], + codebook.codevectors[coffs + l], coffs, l); + } + } + + } else if (vr_type == 2) { + unsigned voffs_div = FASTDIV(voffset << 1, ch <<1); + unsigned voffs_mod = voffset - voffs_div * ch; + + for (k = 0; k < step; ++k) { + coffs = get_vlc2(gb, codebook.vlc.table, codebook.nb_bits, 3) * dim; + for (l = 0; l < dim; ++l) { + vec[voffs_div + voffs_mod * vlen] += + codebook.codevectors[coffs + l]; + + av_dlog(NULL, " pass %d offs: %d curr: %f change: %f cv offs.: %d+%d \n", + pass, voffs_div + voffs_mod * vlen, + vec[voffs_div + voffs_mod * vlen], + codebook.codevectors[coffs + l], coffs, l); + + if (++voffs_mod == ch) { + voffs_div++; + voffs_mod = 0; + } + } + } + } + } + } + j_times_ptns_to_read += ptns_to_read; + } + ++partition_count; + voffset += vr->partition_size; + } + } + } + return 0; +} + +static inline int vorbis_residue_decode(vorbis_context *vc, vorbis_residue *vr, + unsigned ch, + uint8_t *do_not_decode, + float *vec, unsigned vlen, + unsigned ch_left) +{ + if (vr->type == 2) + return vorbis_residue_decode_internal(vc, vr, ch, do_not_decode, vec, vlen, ch_left, 2); + else if (vr->type == 1) + return vorbis_residue_decode_internal(vc, vr, ch, do_not_decode, vec, vlen, ch_left, 1); + else if (vr->type == 0) + return vorbis_residue_decode_internal(vc, vr, ch, do_not_decode, vec, vlen, ch_left, 0); + else { + av_log(vc->avctx, AV_LOG_ERROR, " Invalid residue type while residue decode?! \n"); + return AVERROR_INVALIDDATA; + } +} + +void ff_vorbis_inverse_coupling(float *mag, float *ang, intptr_t blocksize) +{ + int i; + for (i = 0; i < blocksize; i++) { + if (mag[i] > 0.0) { + if (ang[i] > 0.0) { + ang[i] = mag[i] - ang[i]; + } else { + float temp = ang[i]; + ang[i] = mag[i]; + mag[i] += temp; + } + } else { + if (ang[i] > 0.0) { + ang[i] += mag[i]; + } else { + float temp = ang[i]; + ang[i] = mag[i]; + mag[i] -= temp; + } + } + } +} + +// Decode the audio packet using the functions above + +static int vorbis_parse_audio_packet(vorbis_context *vc, float **floor_ptr) +{ + GetBitContext *gb = &vc->gb; + FFTContext *mdct; + unsigned previous_window = vc->previous_window; + unsigned mode_number, blockflag, blocksize; + int i, j; + uint8_t no_residue[255]; + uint8_t do_not_decode[255]; + vorbis_mapping *mapping; + float *ch_res_ptr = vc->channel_residues; + uint8_t res_chan[255]; + unsigned res_num = 0; + int retlen = 0; + unsigned ch_left = vc->audio_channels; + unsigned vlen; + + if (get_bits1(gb)) { + av_log(vc->avctx, AV_LOG_ERROR, "Not a Vorbis I audio packet.\n"); + return AVERROR_INVALIDDATA; // packet type not audio + } + + if (vc->mode_count == 1) { + mode_number = 0; + } else { + GET_VALIDATED_INDEX(mode_number, ilog(vc->mode_count-1), vc->mode_count) + } + vc->mode_number = mode_number; + mapping = &vc->mappings[vc->modes[mode_number].mapping]; + + av_dlog(NULL, " Mode number: %u , mapping: %d , blocktype %d\n", mode_number, + vc->modes[mode_number].mapping, vc->modes[mode_number].blockflag); + + blockflag = vc->modes[mode_number].blockflag; + blocksize = vc->blocksize[blockflag]; + vlen = blocksize / 2; + if (blockflag) { + previous_window = get_bits(gb, 1); + skip_bits1(gb); // next_window + } + + memset(ch_res_ptr, 0, sizeof(float) * vc->audio_channels * vlen); //FIXME can this be removed ? + for (i = 0; i < vc->audio_channels; ++i) + memset(floor_ptr[i], 0, vlen * sizeof(floor_ptr[0][0])); //FIXME can this be removed ? + +// Decode floor + + for (i = 0; i < vc->audio_channels; ++i) { + vorbis_floor *floor; + int ret; + if (mapping->submaps > 1) { + floor = &vc->floors[mapping->submap_floor[mapping->mux[i]]]; + } else { + floor = &vc->floors[mapping->submap_floor[0]]; + } + + ret = floor->decode(vc, &floor->data, floor_ptr[i]); + + if (ret < 0) { + av_log(vc->avctx, AV_LOG_ERROR, "Invalid codebook in vorbis_floor_decode.\n"); + return AVERROR_INVALIDDATA; + } + no_residue[i] = ret; + } + +// Nonzero vector propagate + + for (i = mapping->coupling_steps - 1; i >= 0; --i) { + if (!(no_residue[mapping->magnitude[i]] & no_residue[mapping->angle[i]])) { + no_residue[mapping->magnitude[i]] = 0; + no_residue[mapping->angle[i]] = 0; + } + } + +// Decode residue + + for (i = 0; i < mapping->submaps; ++i) { + vorbis_residue *residue; + unsigned ch = 0; + int ret; + + for (j = 0; j < vc->audio_channels; ++j) { + if ((mapping->submaps == 1) || (i == mapping->mux[j])) { + res_chan[j] = res_num; + if (no_residue[j]) { + do_not_decode[ch] = 1; + } else { + do_not_decode[ch] = 0; + } + ++ch; + ++res_num; + } + } + residue = &vc->residues[mapping->submap_residue[i]]; + if (ch_left < ch) { + av_log(vc->avctx, AV_LOG_ERROR, "Too many channels in vorbis_floor_decode.\n"); + return -1; + } + if (ch) { + ret = vorbis_residue_decode(vc, residue, ch, do_not_decode, ch_res_ptr, vlen, ch_left); + if (ret < 0) + return ret; + } + + ch_res_ptr += ch * vlen; + ch_left -= ch; + } + + if (ch_left > 0) + return AVERROR_INVALIDDATA; + +// Inverse coupling + + for (i = mapping->coupling_steps - 1; i >= 0; --i) { //warning: i has to be signed + float *mag, *ang; + + mag = vc->channel_residues+res_chan[mapping->magnitude[i]] * blocksize / 2; + ang = vc->channel_residues+res_chan[mapping->angle[i]] * blocksize / 2; + vc->dsp.vorbis_inverse_coupling(mag, ang, blocksize / 2); + } + +// Dotproduct, MDCT + + mdct = &vc->mdct[blockflag]; + + for (j = vc->audio_channels-1;j >= 0; j--) { + ch_res_ptr = vc->channel_residues + res_chan[j] * blocksize / 2; + vc->fdsp.vector_fmul(floor_ptr[j], floor_ptr[j], ch_res_ptr, blocksize / 2); + mdct->imdct_half(mdct, ch_res_ptr, floor_ptr[j]); + } + +// Overlap/add, save data for next overlapping + + retlen = (blocksize + vc->blocksize[previous_window]) / 4; + for (j = 0; j < vc->audio_channels; j++) { + unsigned bs0 = vc->blocksize[0]; + unsigned bs1 = vc->blocksize[1]; + float *residue = vc->channel_residues + res_chan[j] * blocksize / 2; + float *saved = vc->saved + j * bs1 / 4; + float *ret = floor_ptr[j]; + float *buf = residue; + const float *win = vc->win[blockflag & previous_window]; + + if (blockflag == previous_window) { + vc->fdsp.vector_fmul_window(ret, saved, buf, win, blocksize / 4); + } else if (blockflag > previous_window) { + vc->fdsp.vector_fmul_window(ret, saved, buf, win, bs0 / 4); + memcpy(ret+bs0/2, buf+bs0/4, ((bs1-bs0)/4) * sizeof(float)); + } else { + memcpy(ret, saved, ((bs1 - bs0) / 4) * sizeof(float)); + vc->fdsp.vector_fmul_window(ret + (bs1 - bs0) / 4, saved + (bs1 - bs0) / 4, buf, win, bs0 / 4); + } + memcpy(saved, buf + blocksize / 4, blocksize / 4 * sizeof(float)); + } + + vc->previous_window = blockflag; + return retlen; +} + +// Return the decoded audio packet through the standard api + +static int vorbis_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + vorbis_context *vc = avctx->priv_data; + AVFrame *frame = data; + GetBitContext *gb = &vc->gb; + float *channel_ptrs[255]; + int i, len, ret; + + av_dlog(NULL, "packet length %d \n", buf_size); + + if (*buf == 1 && buf_size > 7) { + init_get_bits(gb, buf+1, buf_size*8 - 8); + vorbis_free(vc); + if ((ret = vorbis_parse_id_hdr(vc))) { + av_log(avctx, AV_LOG_ERROR, "Id header corrupt.\n"); + vorbis_free(vc); + return ret; + } + + if (vc->audio_channels > 8) + avctx->channel_layout = 0; + else + avctx->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1]; + + avctx->channels = vc->audio_channels; + avctx->sample_rate = vc->audio_samplerate; + return buf_size; + } + + if (*buf == 3 && buf_size > 7) { + av_log(avctx, AV_LOG_DEBUG, "Ignoring comment header\n"); + return buf_size; + } + + if (*buf == 5 && buf_size > 7 && vc->channel_residues && !vc->modes) { + init_get_bits(gb, buf+1, buf_size*8 - 8); + if ((ret = vorbis_parse_setup_hdr(vc))) { + av_log(avctx, AV_LOG_ERROR, "Setup header corrupt.\n"); + vorbis_free(vc); + return ret; + } + return buf_size; + } + + if (!vc->channel_residues || !vc->modes) { + av_log(avctx, AV_LOG_ERROR, "Data packet before valid headers\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = vc->blocksize[1] / 2; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (vc->audio_channels > 8) { + for (i = 0; i < vc->audio_channels; i++) + channel_ptrs[i] = (float *)frame->extended_data[i]; + } else { + for (i = 0; i < vc->audio_channels; i++) { + int ch = ff_vorbis_channel_layout_offsets[vc->audio_channels - 1][i]; + channel_ptrs[ch] = (float *)frame->extended_data[i]; + } + } + + init_get_bits(gb, buf, buf_size*8); + + if ((len = vorbis_parse_audio_packet(vc, channel_ptrs)) <= 0) + return len; + + if (!vc->first_frame) { + vc->first_frame = 1; + *got_frame_ptr = 0; + av_frame_unref(frame); + return buf_size; + } + + av_dlog(NULL, "parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", + get_bits_count(gb) / 8, get_bits_count(gb) % 8, len); + + frame->nb_samples = len; + *got_frame_ptr = 1; + + return buf_size; +} + +// Close decoder + +static av_cold int vorbis_decode_close(AVCodecContext *avctx) +{ + vorbis_context *vc = avctx->priv_data; + + vorbis_free(vc); + + return 0; +} + +static av_cold void vorbis_decode_flush(AVCodecContext *avctx) +{ + vorbis_context *vc = avctx->priv_data; + + if (vc->saved) { + memset(vc->saved, 0, (vc->blocksize[1] / 4) * vc->audio_channels * + sizeof(*vc->saved)); + } + vc->previous_window = 0; +} + +AVCodec ff_vorbis_decoder = { + .name = "vorbis", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VORBIS, + .priv_data_size = sizeof(vorbis_context), + .init = vorbis_decode_init, + .close = vorbis_decode_close, + .decode = vorbis_decode_frame, + .flush = vorbis_decode_flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), + .channel_layouts = ff_vorbis_channel_layouts, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/vorbisdsp.c b/ffmpeg/libavcodec/vorbisdsp.c new file mode 100644 index 0000000..fd8dcd7 --- /dev/null +++ b/ffmpeg/libavcodec/vorbisdsp.c @@ -0,0 +1,33 @@ +/* + * 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 "config.h" +#include "vorbisdsp.h" +#include "vorbis.h" + +void ff_vorbisdsp_init(VorbisDSPContext *dsp) +{ + dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling; + + if (ARCH_X86) + ff_vorbisdsp_init_x86(dsp); + if (ARCH_PPC) + ff_vorbisdsp_init_ppc(dsp); + if (ARCH_ARM) + ff_vorbisdsp_init_arm(dsp); +} diff --git a/ffmpeg/libavcodec/vorbisdsp.h b/ffmpeg/libavcodec/vorbisdsp.h new file mode 100644 index 0000000..ed14049 --- /dev/null +++ b/ffmpeg/libavcodec/vorbisdsp.h @@ -0,0 +1,37 @@ +/* + * 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 + */ + +#ifndef AVCODEC_VORBISDSP_H +#define AVCODEC_VORBISDSP_H + +#include + +typedef struct VorbisDSPContext { + /* assume len is a multiple of 4, and arrays are 16-byte aligned */ + void (*vorbis_inverse_coupling)(float *mag, float *ang, + intptr_t blocksize); +} VorbisDSPContext; + +void ff_vorbisdsp_init(VorbisDSPContext *dsp); + +/* for internal use only */ +void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp); +void ff_vorbisdsp_init_arm(VorbisDSPContext *dsp); +void ff_vorbisdsp_init_ppc(VorbisDSPContext *dsp); + +#endif /* AVCODEC_VORBISDSP_H */ diff --git a/ffmpeg/libavcodec/vorbisenc.c b/ffmpeg/libavcodec/vorbisenc.c new file mode 100644 index 0000000..d685996 --- /dev/null +++ b/ffmpeg/libavcodec/vorbisenc.c @@ -0,0 +1,1205 @@ +/* + * copyright (c) 2006 Oded Shimon + * + * 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 + */ + +/** + * @file + * Native Vorbis encoder. + * @author Oded Shimon + */ + +#include +#include "avcodec.h" +#include "internal.h" +#include "fft.h" +#include "vorbis.h" +#include "vorbis_enc_data.h" + +#define BITSTREAM_WRITER_LE +#include "put_bits.h" + +#undef NDEBUG +#include + +typedef struct { + int nentries; + uint8_t *lens; + uint32_t *codewords; + int ndimensions; + float min; + float delta; + int seq_p; + int lookup; + int *quantlist; + float *dimensions; + float *pow2; +} vorbis_enc_codebook; + +typedef struct { + int dim; + int subclass; + int masterbook; + int *books; +} vorbis_enc_floor_class; + +typedef struct { + int partitions; + int *partition_to_class; + int nclasses; + vorbis_enc_floor_class *classes; + int multiplier; + int rangebits; + int values; + vorbis_floor1_entry *list; +} vorbis_enc_floor; + +typedef struct { + int type; + int begin; + int end; + int partition_size; + int classifications; + int classbook; + int8_t (*books)[8]; + float (*maxes)[2]; +} vorbis_enc_residue; + +typedef struct { + int submaps; + int *mux; + int *floor; + int *residue; + int coupling_steps; + int *magnitude; + int *angle; +} vorbis_enc_mapping; + +typedef struct { + int blockflag; + int mapping; +} vorbis_enc_mode; + +typedef struct { + int channels; + int sample_rate; + int log2_blocksize[2]; + FFTContext mdct[2]; + const float *win[2]; + int have_saved; + float *saved; + float *samples; + float *floor; // also used for tmp values for mdct + float *coeffs; // also used for residue after floor + float quality; + + int ncodebooks; + vorbis_enc_codebook *codebooks; + + int nfloors; + vorbis_enc_floor *floors; + + int nresidues; + vorbis_enc_residue *residues; + + int nmappings; + vorbis_enc_mapping *mappings; + + int nmodes; + vorbis_enc_mode *modes; + + int64_t next_pts; +} vorbis_enc_context; + +#define MAX_CHANNELS 2 +#define MAX_CODEBOOK_DIM 8 + +#define MAX_FLOOR_CLASS_DIM 4 +#define NUM_FLOOR_PARTITIONS 8 +#define MAX_FLOOR_VALUES (MAX_FLOOR_CLASS_DIM*NUM_FLOOR_PARTITIONS+2) + +#define RESIDUE_SIZE 1600 +#define RESIDUE_PART_SIZE 32 +#define NUM_RESIDUE_PARTITIONS (RESIDUE_SIZE/RESIDUE_PART_SIZE) + +static inline int put_codeword(PutBitContext *pb, vorbis_enc_codebook *cb, + int entry) +{ + assert(entry >= 0); + assert(entry < cb->nentries); + assert(cb->lens[entry]); + if (pb->size_in_bits - put_bits_count(pb) < cb->lens[entry]) + return AVERROR(EINVAL); + put_bits(pb, cb->lens[entry], cb->codewords[entry]); + return 0; +} + +static int cb_lookup_vals(int lookup, int dimensions, int entries) +{ + if (lookup == 1) + return ff_vorbis_nth_root(entries, dimensions); + else if (lookup == 2) + return dimensions *entries; + return 0; +} + +static int ready_codebook(vorbis_enc_codebook *cb) +{ + int i; + + ff_vorbis_len2vlc(cb->lens, cb->codewords, cb->nentries); + + if (!cb->lookup) { + cb->pow2 = cb->dimensions = NULL; + } else { + int vals = cb_lookup_vals(cb->lookup, cb->ndimensions, cb->nentries); + cb->dimensions = av_malloc(sizeof(float) * cb->nentries * cb->ndimensions); + cb->pow2 = av_mallocz(sizeof(float) * cb->nentries); + if (!cb->dimensions || !cb->pow2) + return AVERROR(ENOMEM); + for (i = 0; i < cb->nentries; i++) { + float last = 0; + int j; + int div = 1; + for (j = 0; j < cb->ndimensions; j++) { + int off; + if (cb->lookup == 1) + off = (i / div) % vals; // lookup type 1 + else + off = i * cb->ndimensions + j; // lookup type 2 + + cb->dimensions[i * cb->ndimensions + j] = last + cb->min + cb->quantlist[off] * cb->delta; + if (cb->seq_p) + last = cb->dimensions[i * cb->ndimensions + j]; + cb->pow2[i] += cb->dimensions[i * cb->ndimensions + j] * cb->dimensions[i * cb->ndimensions + j]; + div *= vals; + } + cb->pow2[i] /= 2.; + } + } + return 0; +} + +static int ready_residue(vorbis_enc_residue *rc, vorbis_enc_context *venc) +{ + int i; + assert(rc->type == 2); + rc->maxes = av_mallocz(sizeof(float[2]) * rc->classifications); + if (!rc->maxes) + return AVERROR(ENOMEM); + for (i = 0; i < rc->classifications; i++) { + int j; + vorbis_enc_codebook * cb; + for (j = 0; j < 8; j++) + if (rc->books[i][j] != -1) + break; + if (j == 8) // zero + continue; + cb = &venc->codebooks[rc->books[i][j]]; + assert(cb->ndimensions >= 2); + assert(cb->lookup); + + for (j = 0; j < cb->nentries; j++) { + float a; + if (!cb->lens[j]) + continue; + a = fabs(cb->dimensions[j * cb->ndimensions]); + if (a > rc->maxes[i][0]) + rc->maxes[i][0] = a; + a = fabs(cb->dimensions[j * cb->ndimensions + 1]); + if (a > rc->maxes[i][1]) + rc->maxes[i][1] = a; + } + } + // small bias + for (i = 0; i < rc->classifications; i++) { + rc->maxes[i][0] += 0.8; + rc->maxes[i][1] += 0.8; + } + return 0; +} + +static int create_vorbis_context(vorbis_enc_context *venc, + AVCodecContext *avctx) +{ + vorbis_enc_floor *fc; + vorbis_enc_residue *rc; + vorbis_enc_mapping *mc; + int i, book, ret; + + venc->channels = avctx->channels; + venc->sample_rate = avctx->sample_rate; + venc->log2_blocksize[0] = venc->log2_blocksize[1] = 11; + + venc->ncodebooks = FF_ARRAY_ELEMS(cvectors); + venc->codebooks = av_malloc(sizeof(vorbis_enc_codebook) * venc->ncodebooks); + if (!venc->codebooks) + return AVERROR(ENOMEM); + + // codebook 0..14 - floor1 book, values 0..255 + // codebook 15 residue masterbook + // codebook 16..29 residue + for (book = 0; book < venc->ncodebooks; book++) { + vorbis_enc_codebook *cb = &venc->codebooks[book]; + int vals; + cb->ndimensions = cvectors[book].dim; + cb->nentries = cvectors[book].real_len; + cb->min = cvectors[book].min; + cb->delta = cvectors[book].delta; + cb->lookup = cvectors[book].lookup; + cb->seq_p = 0; + + cb->lens = av_malloc(sizeof(uint8_t) * cb->nentries); + cb->codewords = av_malloc(sizeof(uint32_t) * cb->nentries); + if (!cb->lens || !cb->codewords) + return AVERROR(ENOMEM); + memcpy(cb->lens, cvectors[book].clens, cvectors[book].len); + memset(cb->lens + cvectors[book].len, 0, cb->nentries - cvectors[book].len); + + if (cb->lookup) { + vals = cb_lookup_vals(cb->lookup, cb->ndimensions, cb->nentries); + cb->quantlist = av_malloc(sizeof(int) * vals); + if (!cb->quantlist) + return AVERROR(ENOMEM); + for (i = 0; i < vals; i++) + cb->quantlist[i] = cvectors[book].quant[i]; + } else { + cb->quantlist = NULL; + } + if ((ret = ready_codebook(cb)) < 0) + return ret; + } + + venc->nfloors = 1; + venc->floors = av_malloc(sizeof(vorbis_enc_floor) * venc->nfloors); + if (!venc->floors) + return AVERROR(ENOMEM); + + // just 1 floor + fc = &venc->floors[0]; + fc->partitions = NUM_FLOOR_PARTITIONS; + fc->partition_to_class = av_malloc(sizeof(int) * fc->partitions); + if (!fc->partition_to_class) + return AVERROR(ENOMEM); + fc->nclasses = 0; + for (i = 0; i < fc->partitions; i++) { + static const int a[] = {0, 1, 2, 2, 3, 3, 4, 4}; + fc->partition_to_class[i] = a[i]; + fc->nclasses = FFMAX(fc->nclasses, fc->partition_to_class[i]); + } + fc->nclasses++; + fc->classes = av_malloc(sizeof(vorbis_enc_floor_class) * fc->nclasses); + if (!fc->classes) + return AVERROR(ENOMEM); + for (i = 0; i < fc->nclasses; i++) { + vorbis_enc_floor_class * c = &fc->classes[i]; + int j, books; + c->dim = floor_classes[i].dim; + c->subclass = floor_classes[i].subclass; + c->masterbook = floor_classes[i].masterbook; + books = (1 << c->subclass); + c->books = av_malloc(sizeof(int) * books); + if (!c->books) + return AVERROR(ENOMEM); + for (j = 0; j < books; j++) + c->books[j] = floor_classes[i].nbooks[j]; + } + fc->multiplier = 2; + fc->rangebits = venc->log2_blocksize[0] - 1; + + fc->values = 2; + for (i = 0; i < fc->partitions; i++) + fc->values += fc->classes[fc->partition_to_class[i]].dim; + + fc->list = av_malloc(sizeof(vorbis_floor1_entry) * fc->values); + if (!fc->list) + return AVERROR(ENOMEM); + fc->list[0].x = 0; + fc->list[1].x = 1 << fc->rangebits; + for (i = 2; i < fc->values; i++) { + static const int a[] = { + 93, 23,372, 6, 46,186,750, 14, 33, 65, + 130,260,556, 3, 10, 18, 28, 39, 55, 79, + 111,158,220,312,464,650,850 + }; + fc->list[i].x = a[i - 2]; + } + if (ff_vorbis_ready_floor1_list(avctx, fc->list, fc->values)) + return AVERROR_BUG; + + venc->nresidues = 1; + venc->residues = av_malloc(sizeof(vorbis_enc_residue) * venc->nresidues); + if (!venc->residues) + return AVERROR(ENOMEM); + + // single residue + rc = &venc->residues[0]; + rc->type = 2; + rc->begin = 0; + rc->end = 1600; + rc->partition_size = 32; + rc->classifications = 10; + rc->classbook = 15; + rc->books = av_malloc(sizeof(*rc->books) * rc->classifications); + if (!rc->books) + return AVERROR(ENOMEM); + { + static const int8_t a[10][8] = { + { -1, -1, -1, -1, -1, -1, -1, -1, }, + { -1, -1, 16, -1, -1, -1, -1, -1, }, + { -1, -1, 17, -1, -1, -1, -1, -1, }, + { -1, -1, 18, -1, -1, -1, -1, -1, }, + { -1, -1, 19, -1, -1, -1, -1, -1, }, + { -1, -1, 20, -1, -1, -1, -1, -1, }, + { -1, -1, 21, -1, -1, -1, -1, -1, }, + { 22, 23, -1, -1, -1, -1, -1, -1, }, + { 24, 25, -1, -1, -1, -1, -1, -1, }, + { 26, 27, 28, -1, -1, -1, -1, -1, }, + }; + memcpy(rc->books, a, sizeof a); + } + if ((ret = ready_residue(rc, venc)) < 0) + return ret; + + venc->nmappings = 1; + venc->mappings = av_malloc(sizeof(vorbis_enc_mapping) * venc->nmappings); + if (!venc->mappings) + return AVERROR(ENOMEM); + + // single mapping + mc = &venc->mappings[0]; + mc->submaps = 1; + mc->mux = av_malloc(sizeof(int) * venc->channels); + if (!mc->mux) + return AVERROR(ENOMEM); + for (i = 0; i < venc->channels; i++) + mc->mux[i] = 0; + mc->floor = av_malloc(sizeof(int) * mc->submaps); + mc->residue = av_malloc(sizeof(int) * mc->submaps); + if (!mc->floor || !mc->residue) + return AVERROR(ENOMEM); + for (i = 0; i < mc->submaps; i++) { + mc->floor[i] = 0; + mc->residue[i] = 0; + } + mc->coupling_steps = venc->channels == 2 ? 1 : 0; + mc->magnitude = av_malloc(sizeof(int) * mc->coupling_steps); + mc->angle = av_malloc(sizeof(int) * mc->coupling_steps); + if (!mc->magnitude || !mc->angle) + return AVERROR(ENOMEM); + if (mc->coupling_steps) { + mc->magnitude[0] = 0; + mc->angle[0] = 1; + } + + venc->nmodes = 1; + venc->modes = av_malloc(sizeof(vorbis_enc_mode) * venc->nmodes); + if (!venc->modes) + return AVERROR(ENOMEM); + + // single mode + venc->modes[0].blockflag = 0; + venc->modes[0].mapping = 0; + + venc->have_saved = 0; + venc->saved = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1]) / 2); + venc->samples = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1])); + venc->floor = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1]) / 2); + venc->coeffs = av_malloc(sizeof(float) * venc->channels * (1 << venc->log2_blocksize[1]) / 2); + if (!venc->saved || !venc->samples || !venc->floor || !venc->coeffs) + return AVERROR(ENOMEM); + + venc->win[0] = ff_vorbis_vwin[venc->log2_blocksize[0] - 6]; + venc->win[1] = ff_vorbis_vwin[venc->log2_blocksize[1] - 6]; + + if ((ret = ff_mdct_init(&venc->mdct[0], venc->log2_blocksize[0], 0, 1.0)) < 0) + return ret; + if ((ret = ff_mdct_init(&venc->mdct[1], venc->log2_blocksize[1], 0, 1.0)) < 0) + return ret; + + return 0; +} + +static void put_float(PutBitContext *pb, float f) +{ + int exp, mant; + uint32_t res = 0; + mant = (int)ldexp(frexp(f, &exp), 20); + exp += 788 - 20; + if (mant < 0) { + res |= (1U << 31); + mant = -mant; + } + res |= mant | (exp << 21); + put_bits32(pb, res); +} + +static void put_codebook_header(PutBitContext *pb, vorbis_enc_codebook *cb) +{ + int i; + int ordered = 0; + + put_bits(pb, 24, 0x564342); //magic + put_bits(pb, 16, cb->ndimensions); + put_bits(pb, 24, cb->nentries); + + for (i = 1; i < cb->nentries; i++) + if (cb->lens[i] < cb->lens[i-1]) + break; + if (i == cb->nentries) + ordered = 1; + + put_bits(pb, 1, ordered); + if (ordered) { + int len = cb->lens[0]; + put_bits(pb, 5, len - 1); + i = 0; + while (i < cb->nentries) { + int j; + for (j = 0; j+i < cb->nentries; j++) + if (cb->lens[j+i] != len) + break; + put_bits(pb, ilog(cb->nentries - i), j); + i += j; + len++; + } + } else { + int sparse = 0; + for (i = 0; i < cb->nentries; i++) + if (!cb->lens[i]) + break; + if (i != cb->nentries) + sparse = 1; + put_bits(pb, 1, sparse); + + for (i = 0; i < cb->nentries; i++) { + if (sparse) + put_bits(pb, 1, !!cb->lens[i]); + if (cb->lens[i]) + put_bits(pb, 5, cb->lens[i] - 1); + } + } + + put_bits(pb, 4, cb->lookup); + if (cb->lookup) { + int tmp = cb_lookup_vals(cb->lookup, cb->ndimensions, cb->nentries); + int bits = ilog(cb->quantlist[0]); + + for (i = 1; i < tmp; i++) + bits = FFMAX(bits, ilog(cb->quantlist[i])); + + put_float(pb, cb->min); + put_float(pb, cb->delta); + + put_bits(pb, 4, bits - 1); + put_bits(pb, 1, cb->seq_p); + + for (i = 0; i < tmp; i++) + put_bits(pb, bits, cb->quantlist[i]); + } +} + +static void put_floor_header(PutBitContext *pb, vorbis_enc_floor *fc) +{ + int i; + + put_bits(pb, 16, 1); // type, only floor1 is supported + + put_bits(pb, 5, fc->partitions); + + for (i = 0; i < fc->partitions; i++) + put_bits(pb, 4, fc->partition_to_class[i]); + + for (i = 0; i < fc->nclasses; i++) { + int j, books; + + put_bits(pb, 3, fc->classes[i].dim - 1); + put_bits(pb, 2, fc->classes[i].subclass); + + if (fc->classes[i].subclass) + put_bits(pb, 8, fc->classes[i].masterbook); + + books = (1 << fc->classes[i].subclass); + + for (j = 0; j < books; j++) + put_bits(pb, 8, fc->classes[i].books[j] + 1); + } + + put_bits(pb, 2, fc->multiplier - 1); + put_bits(pb, 4, fc->rangebits); + + for (i = 2; i < fc->values; i++) + put_bits(pb, fc->rangebits, fc->list[i].x); +} + +static void put_residue_header(PutBitContext *pb, vorbis_enc_residue *rc) +{ + int i; + + put_bits(pb, 16, rc->type); + + put_bits(pb, 24, rc->begin); + put_bits(pb, 24, rc->end); + put_bits(pb, 24, rc->partition_size - 1); + put_bits(pb, 6, rc->classifications - 1); + put_bits(pb, 8, rc->classbook); + + for (i = 0; i < rc->classifications; i++) { + int j, tmp = 0; + for (j = 0; j < 8; j++) + tmp |= (rc->books[i][j] != -1) << j; + + put_bits(pb, 3, tmp & 7); + put_bits(pb, 1, tmp > 7); + + if (tmp > 7) + put_bits(pb, 5, tmp >> 3); + } + + for (i = 0; i < rc->classifications; i++) { + int j; + for (j = 0; j < 8; j++) + if (rc->books[i][j] != -1) + put_bits(pb, 8, rc->books[i][j]); + } +} + +static int put_main_header(vorbis_enc_context *venc, uint8_t **out) +{ + int i; + PutBitContext pb; + uint8_t buffer[50000] = {0}, *p = buffer; + int buffer_len = sizeof buffer; + int len, hlens[3]; + + // identification header + init_put_bits(&pb, p, buffer_len); + put_bits(&pb, 8, 1); //magic + for (i = 0; "vorbis"[i]; i++) + put_bits(&pb, 8, "vorbis"[i]); + put_bits32(&pb, 0); // version + put_bits(&pb, 8, venc->channels); + put_bits32(&pb, venc->sample_rate); + put_bits32(&pb, 0); // bitrate + put_bits32(&pb, 0); // bitrate + put_bits32(&pb, 0); // bitrate + put_bits(&pb, 4, venc->log2_blocksize[0]); + put_bits(&pb, 4, venc->log2_blocksize[1]); + put_bits(&pb, 1, 1); // framing + + flush_put_bits(&pb); + hlens[0] = put_bits_count(&pb) >> 3; + buffer_len -= hlens[0]; + p += hlens[0]; + + // comment header + init_put_bits(&pb, p, buffer_len); + put_bits(&pb, 8, 3); //magic + for (i = 0; "vorbis"[i]; i++) + put_bits(&pb, 8, "vorbis"[i]); + put_bits32(&pb, 0); // vendor length TODO + put_bits32(&pb, 0); // amount of comments + put_bits(&pb, 1, 1); // framing + + flush_put_bits(&pb); + hlens[1] = put_bits_count(&pb) >> 3; + buffer_len -= hlens[1]; + p += hlens[1]; + + // setup header + init_put_bits(&pb, p, buffer_len); + put_bits(&pb, 8, 5); //magic + for (i = 0; "vorbis"[i]; i++) + put_bits(&pb, 8, "vorbis"[i]); + + // codebooks + put_bits(&pb, 8, venc->ncodebooks - 1); + for (i = 0; i < venc->ncodebooks; i++) + put_codebook_header(&pb, &venc->codebooks[i]); + + // time domain, reserved, zero + put_bits(&pb, 6, 0); + put_bits(&pb, 16, 0); + + // floors + put_bits(&pb, 6, venc->nfloors - 1); + for (i = 0; i < venc->nfloors; i++) + put_floor_header(&pb, &venc->floors[i]); + + // residues + put_bits(&pb, 6, venc->nresidues - 1); + for (i = 0; i < venc->nresidues; i++) + put_residue_header(&pb, &venc->residues[i]); + + // mappings + put_bits(&pb, 6, venc->nmappings - 1); + for (i = 0; i < venc->nmappings; i++) { + vorbis_enc_mapping *mc = &venc->mappings[i]; + int j; + put_bits(&pb, 16, 0); // mapping type + + put_bits(&pb, 1, mc->submaps > 1); + if (mc->submaps > 1) + put_bits(&pb, 4, mc->submaps - 1); + + put_bits(&pb, 1, !!mc->coupling_steps); + if (mc->coupling_steps) { + put_bits(&pb, 8, mc->coupling_steps - 1); + for (j = 0; j < mc->coupling_steps; j++) { + put_bits(&pb, ilog(venc->channels - 1), mc->magnitude[j]); + put_bits(&pb, ilog(venc->channels - 1), mc->angle[j]); + } + } + + put_bits(&pb, 2, 0); // reserved + + if (mc->submaps > 1) + for (j = 0; j < venc->channels; j++) + put_bits(&pb, 4, mc->mux[j]); + + for (j = 0; j < mc->submaps; j++) { + put_bits(&pb, 8, 0); // reserved time configuration + put_bits(&pb, 8, mc->floor[j]); + put_bits(&pb, 8, mc->residue[j]); + } + } + + // modes + put_bits(&pb, 6, venc->nmodes - 1); + for (i = 0; i < venc->nmodes; i++) { + put_bits(&pb, 1, venc->modes[i].blockflag); + put_bits(&pb, 16, 0); // reserved window type + put_bits(&pb, 16, 0); // reserved transform type + put_bits(&pb, 8, venc->modes[i].mapping); + } + + put_bits(&pb, 1, 1); // framing + + flush_put_bits(&pb); + hlens[2] = put_bits_count(&pb) >> 3; + + len = hlens[0] + hlens[1] + hlens[2]; + p = *out = av_mallocz(64 + len + len/255); + if (!p) + return AVERROR(ENOMEM); + + *p++ = 2; + p += av_xiphlacing(p, hlens[0]); + p += av_xiphlacing(p, hlens[1]); + buffer_len = 0; + for (i = 0; i < 3; i++) { + memcpy(p, buffer + buffer_len, hlens[i]); + p += hlens[i]; + buffer_len += hlens[i]; + } + + return p - *out; +} + +static float get_floor_average(vorbis_enc_floor * fc, float *coeffs, int i) +{ + int begin = fc->list[fc->list[FFMAX(i-1, 0)].sort].x; + int end = fc->list[fc->list[FFMIN(i+1, fc->values - 1)].sort].x; + int j; + float average = 0; + + for (j = begin; j < end; j++) + average += fabs(coeffs[j]); + return average / (end - begin); +} + +static void floor_fit(vorbis_enc_context *venc, vorbis_enc_floor *fc, + float *coeffs, uint16_t *posts, int samples) +{ + int range = 255 / fc->multiplier + 1; + int i; + float tot_average = 0.; + float averages[MAX_FLOOR_VALUES]; + for (i = 0; i < fc->values; i++) { + averages[i] = get_floor_average(fc, coeffs, i); + tot_average += averages[i]; + } + tot_average /= fc->values; + tot_average /= venc->quality; + + for (i = 0; i < fc->values; i++) { + int position = fc->list[fc->list[i].sort].x; + float average = averages[i]; + int j; + + average = sqrt(tot_average * average) * pow(1.25f, position*0.005f); // MAGIC! + for (j = 0; j < range - 1; j++) + if (ff_vorbis_floor1_inverse_db_table[j * fc->multiplier] > average) + break; + posts[fc->list[i].sort] = j; + } +} + +static int render_point(int x0, int y0, int x1, int y1, int x) +{ + return y0 + (x - x0) * (y1 - y0) / (x1 - x0); +} + +static int floor_encode(vorbis_enc_context *venc, vorbis_enc_floor *fc, + PutBitContext *pb, uint16_t *posts, + float *floor, int samples) +{ + int range = 255 / fc->multiplier + 1; + int coded[MAX_FLOOR_VALUES]; // first 2 values are unused + int i, counter; + + if (pb->size_in_bits - put_bits_count(pb) < 1 + 2 * ilog(range - 1)) + return AVERROR(EINVAL); + put_bits(pb, 1, 1); // non zero + put_bits(pb, ilog(range - 1), posts[0]); + put_bits(pb, ilog(range - 1), posts[1]); + coded[0] = coded[1] = 1; + + for (i = 2; i < fc->values; i++) { + int predicted = render_point(fc->list[fc->list[i].low].x, + posts[fc->list[i].low], + fc->list[fc->list[i].high].x, + posts[fc->list[i].high], + fc->list[i].x); + int highroom = range - predicted; + int lowroom = predicted; + int room = FFMIN(highroom, lowroom); + if (predicted == posts[i]) { + coded[i] = 0; // must be used later as flag! + continue; + } else { + if (!coded[fc->list[i].low ]) + coded[fc->list[i].low ] = -1; + if (!coded[fc->list[i].high]) + coded[fc->list[i].high] = -1; + } + if (posts[i] > predicted) { + if (posts[i] - predicted > room) + coded[i] = posts[i] - predicted + lowroom; + else + coded[i] = (posts[i] - predicted) << 1; + } else { + if (predicted - posts[i] > room) + coded[i] = predicted - posts[i] + highroom - 1; + else + coded[i] = ((predicted - posts[i]) << 1) - 1; + } + } + + counter = 2; + for (i = 0; i < fc->partitions; i++) { + vorbis_enc_floor_class * c = &fc->classes[fc->partition_to_class[i]]; + int k, cval = 0, csub = 1<subclass; + if (c->subclass) { + vorbis_enc_codebook * book = &venc->codebooks[c->masterbook]; + int cshift = 0; + for (k = 0; k < c->dim; k++) { + int l; + for (l = 0; l < csub; l++) { + int maxval = 1; + if (c->books[l] != -1) + maxval = venc->codebooks[c->books[l]].nentries; + // coded could be -1, but this still works, cause that is 0 + if (coded[counter + k] < maxval) + break; + } + assert(l != csub); + cval |= l << cshift; + cshift += c->subclass; + } + if (put_codeword(pb, book, cval)) + return AVERROR(EINVAL); + } + for (k = 0; k < c->dim; k++) { + int book = c->books[cval & (csub-1)]; + int entry = coded[counter++]; + cval >>= c->subclass; + if (book == -1) + continue; + if (entry == -1) + entry = 0; + if (put_codeword(pb, &venc->codebooks[book], entry)) + return AVERROR(EINVAL); + } + } + + ff_vorbis_floor1_render_list(fc->list, fc->values, posts, coded, + fc->multiplier, floor, samples); + + return 0; +} + +static float *put_vector(vorbis_enc_codebook *book, PutBitContext *pb, + float *num) +{ + int i, entry = -1; + float distance = FLT_MAX; + assert(book->dimensions); + for (i = 0; i < book->nentries; i++) { + float * vec = book->dimensions + i * book->ndimensions, d = book->pow2[i]; + int j; + if (!book->lens[i]) + continue; + for (j = 0; j < book->ndimensions; j++) + d -= vec[j] * num[j]; + if (distance > d) { + entry = i; + distance = d; + } + } + if (put_codeword(pb, book, entry)) + return NULL; + return &book->dimensions[entry * book->ndimensions]; +} + +static int residue_encode(vorbis_enc_context *venc, vorbis_enc_residue *rc, + PutBitContext *pb, float *coeffs, int samples, + int real_ch) +{ + int pass, i, j, p, k; + int psize = rc->partition_size; + int partitions = (rc->end - rc->begin) / psize; + int channels = (rc->type == 2) ? 1 : real_ch; + int classes[MAX_CHANNELS][NUM_RESIDUE_PARTITIONS]; + int classwords = venc->codebooks[rc->classbook].ndimensions; + + assert(rc->type == 2); + assert(real_ch == 2); + for (p = 0; p < partitions; p++) { + float max1 = 0., max2 = 0.; + int s = rc->begin + p * psize; + for (k = s; k < s + psize; k += 2) { + max1 = FFMAX(max1, fabs(coeffs[ k / real_ch])); + max2 = FFMAX(max2, fabs(coeffs[samples + k / real_ch])); + } + + for (i = 0; i < rc->classifications - 1; i++) + if (max1 < rc->maxes[i][0] && max2 < rc->maxes[i][1]) + break; + classes[0][p] = i; + } + + for (pass = 0; pass < 8; pass++) { + p = 0; + while (p < partitions) { + if (pass == 0) + for (j = 0; j < channels; j++) { + vorbis_enc_codebook * book = &venc->codebooks[rc->classbook]; + int entry = 0; + for (i = 0; i < classwords; i++) { + entry *= rc->classifications; + entry += classes[j][p + i]; + } + if (put_codeword(pb, book, entry)) + return AVERROR(EINVAL); + } + for (i = 0; i < classwords && p < partitions; i++, p++) { + for (j = 0; j < channels; j++) { + int nbook = rc->books[classes[j][p]][pass]; + vorbis_enc_codebook * book = &venc->codebooks[nbook]; + float *buf = coeffs + samples*j + rc->begin + p*psize; + if (nbook == -1) + continue; + + assert(rc->type == 0 || rc->type == 2); + assert(!(psize % book->ndimensions)); + + if (rc->type == 0) { + for (k = 0; k < psize; k += book->ndimensions) { + int l; + float *a = put_vector(book, pb, &buf[k]); + if (!a) + return AVERROR(EINVAL); + for (l = 0; l < book->ndimensions; l++) + buf[k + l] -= a[l]; + } + } else { + int s = rc->begin + p * psize, a1, b1; + a1 = (s % real_ch) * samples; + b1 = s / real_ch; + s = real_ch * samples; + for (k = 0; k < psize; k += book->ndimensions) { + int dim, a2 = a1, b2 = b1; + float vec[MAX_CODEBOOK_DIM], *pv = vec; + for (dim = book->ndimensions; dim--; ) { + *pv++ = coeffs[a2 + b2]; + if ((a2 += samples) == s) { + a2 = 0; + b2++; + } + } + pv = put_vector(book, pb, vec); + if (!pv) + return AVERROR(EINVAL); + for (dim = book->ndimensions; dim--; ) { + coeffs[a1 + b1] -= *pv++; + if ((a1 += samples) == s) { + a1 = 0; + b1++; + } + } + } + } + } + } + } + } + return 0; +} + +static int apply_window_and_mdct(vorbis_enc_context *venc, + float **audio, int samples) +{ + int i, channel; + const float * win = venc->win[0]; + int window_len = 1 << (venc->log2_blocksize[0] - 1); + float n = (float)(1 << venc->log2_blocksize[0]) / 4.; + // FIXME use dsp + + if (!venc->have_saved && !samples) + return 0; + + if (venc->have_saved) { + for (channel = 0; channel < venc->channels; channel++) + memcpy(venc->samples + channel * window_len * 2, + venc->saved + channel * window_len, sizeof(float) * window_len); + } else { + for (channel = 0; channel < venc->channels; channel++) + memset(venc->samples + channel * window_len * 2, 0, + sizeof(float) * window_len); + } + + if (samples) { + for (channel = 0; channel < venc->channels; channel++) { + float * offset = venc->samples + channel*window_len*2 + window_len; + for (i = 0; i < samples; i++) + offset[i] = audio[channel][i] / n * win[window_len - i - 1]; + } + } else { + for (channel = 0; channel < venc->channels; channel++) + memset(venc->samples + channel * window_len * 2 + window_len, + 0, sizeof(float) * window_len); + } + + for (channel = 0; channel < venc->channels; channel++) + venc->mdct[0].mdct_calc(&venc->mdct[0], venc->coeffs + channel * window_len, + venc->samples + channel * window_len * 2); + + if (samples) { + for (channel = 0; channel < venc->channels; channel++) { + float *offset = venc->saved + channel * window_len; + for (i = 0; i < samples; i++) + offset[i] = audio[channel][i] / n * win[i]; + } + venc->have_saved = 1; + } else { + venc->have_saved = 0; + } + return 1; +} + +static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + vorbis_enc_context *venc = avctx->priv_data; + float **audio = frame ? (float **)frame->extended_data : NULL; + int samples = frame ? frame->nb_samples : 0; + vorbis_enc_mode *mode; + vorbis_enc_mapping *mapping; + PutBitContext pb; + int i, ret; + + if (!apply_window_and_mdct(venc, audio, samples)) + return 0; + samples = 1 << (venc->log2_blocksize[0] - 1); + + if ((ret = ff_alloc_packet2(avctx, avpkt, 8192)) < 0) + return ret; + + init_put_bits(&pb, avpkt->data, avpkt->size); + + if (pb.size_in_bits - put_bits_count(&pb) < 1 + ilog(venc->nmodes - 1)) { + av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); + return AVERROR(EINVAL); + } + + put_bits(&pb, 1, 0); // magic bit + + put_bits(&pb, ilog(venc->nmodes - 1), 0); // 0 bits, the mode + + mode = &venc->modes[0]; + mapping = &venc->mappings[mode->mapping]; + if (mode->blockflag) { + put_bits(&pb, 1, 0); + put_bits(&pb, 1, 0); + } + + for (i = 0; i < venc->channels; i++) { + vorbis_enc_floor *fc = &venc->floors[mapping->floor[mapping->mux[i]]]; + uint16_t posts[MAX_FLOOR_VALUES]; + floor_fit(venc, fc, &venc->coeffs[i * samples], posts, samples); + if (floor_encode(venc, fc, &pb, posts, &venc->floor[i * samples], samples)) { + av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); + return AVERROR(EINVAL); + } + } + + for (i = 0; i < venc->channels * samples; i++) + venc->coeffs[i] /= venc->floor[i]; + + for (i = 0; i < mapping->coupling_steps; i++) { + float *mag = venc->coeffs + mapping->magnitude[i] * samples; + float *ang = venc->coeffs + mapping->angle[i] * samples; + int j; + for (j = 0; j < samples; j++) { + float a = ang[j]; + ang[j] -= mag[j]; + if (mag[j] > 0) + ang[j] = -ang[j]; + if (ang[j] < 0) + mag[j] = a; + } + } + + if (residue_encode(venc, &venc->residues[mapping->residue[mapping->mux[0]]], + &pb, venc->coeffs, samples, venc->channels)) { + av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); + return AVERROR(EINVAL); + } + + flush_put_bits(&pb); + avpkt->size = put_bits_count(&pb) >> 3; + + avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size); + if (frame) { + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = ff_samples_to_time_base(avctx, frame->pts); + } else + avpkt->pts = venc->next_pts; + if (avpkt->pts != AV_NOPTS_VALUE) + venc->next_pts = avpkt->pts + avpkt->duration; + + *got_packet_ptr = 1; + return 0; +} + + +static av_cold int vorbis_encode_close(AVCodecContext *avctx) +{ + vorbis_enc_context *venc = avctx->priv_data; + int i; + + if (venc->codebooks) + for (i = 0; i < venc->ncodebooks; i++) { + av_freep(&venc->codebooks[i].lens); + av_freep(&venc->codebooks[i].codewords); + av_freep(&venc->codebooks[i].quantlist); + av_freep(&venc->codebooks[i].dimensions); + av_freep(&venc->codebooks[i].pow2); + } + av_freep(&venc->codebooks); + + if (venc->floors) + for (i = 0; i < venc->nfloors; i++) { + int j; + if (venc->floors[i].classes) + for (j = 0; j < venc->floors[i].nclasses; j++) + av_freep(&venc->floors[i].classes[j].books); + av_freep(&venc->floors[i].classes); + av_freep(&venc->floors[i].partition_to_class); + av_freep(&venc->floors[i].list); + } + av_freep(&venc->floors); + + if (venc->residues) + for (i = 0; i < venc->nresidues; i++) { + av_freep(&venc->residues[i].books); + av_freep(&venc->residues[i].maxes); + } + av_freep(&venc->residues); + + if (venc->mappings) + for (i = 0; i < venc->nmappings; i++) { + av_freep(&venc->mappings[i].mux); + av_freep(&venc->mappings[i].floor); + av_freep(&venc->mappings[i].residue); + av_freep(&venc->mappings[i].magnitude); + av_freep(&venc->mappings[i].angle); + } + av_freep(&venc->mappings); + + av_freep(&venc->modes); + + av_freep(&venc->saved); + av_freep(&venc->samples); + av_freep(&venc->floor); + av_freep(&venc->coeffs); + + ff_mdct_end(&venc->mdct[0]); + ff_mdct_end(&venc->mdct[1]); + + av_freep(&avctx->extradata); + + return 0 ; +} + +static av_cold int vorbis_encode_init(AVCodecContext *avctx) +{ + vorbis_enc_context *venc = avctx->priv_data; + int ret; + + if (avctx->channels != 2) { + av_log(avctx, AV_LOG_ERROR, "Current FFmpeg Vorbis encoder only supports 2 channels.\n"); + return -1; + } + + if ((ret = create_vorbis_context(venc, avctx)) < 0) + goto error; + + avctx->bit_rate = 0; + if (avctx->flags & CODEC_FLAG_QSCALE) + venc->quality = avctx->global_quality / (float)FF_QP2LAMBDA; + else + venc->quality = 8; + venc->quality *= venc->quality; + + if ((ret = put_main_header(venc, (uint8_t**)&avctx->extradata)) < 0) + goto error; + avctx->extradata_size = ret; + + avctx->frame_size = 1 << (venc->log2_blocksize[0] - 1); + + return 0; +error: + vorbis_encode_close(avctx); + return ret; +} + +AVCodec ff_vorbis_encoder = { + .name = "vorbis", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_VORBIS, + .priv_data_size = sizeof(vorbis_enc_context), + .init = vorbis_encode_init, + .encode2 = vorbis_encode_frame, + .close = vorbis_encode_close, + .capabilities = CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), +}; diff --git a/ffmpeg/libavcodec/vp3.c b/ffmpeg/libavcodec/vp3.c new file mode 100644 index 0000000..1e76786 --- /dev/null +++ b/ffmpeg/libavcodec/vp3.c @@ -0,0 +1,2486 @@ +/* + * Copyright (C) 2003-2004 the ffmpeg project + * + * 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 + */ + +/** + * @file + * On2 VP3 Video Decoder + * + * VP3 Video Decoder by Mike Melanson (mike at multimedia.cx) + * For more information about the VP3 coding process, visit: + * http://wiki.multimedia.cx/index.php?title=On2_VP3 + * + * Theora decoder by Alex Beregszaszi + */ + +#include +#include +#include + +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" +#include "dsputil.h" +#include "get_bits.h" +#include "hpeldsp.h" +#include "videodsp.h" +#include "vp3data.h" +#include "vp3dsp.h" +#include "xiph.h" +#include "thread.h" + +#define FRAGMENT_PIXELS 8 + +//FIXME split things out into their own arrays +typedef struct Vp3Fragment { + int16_t dc; + uint8_t coding_method; + uint8_t qpi; +} Vp3Fragment; + +#define SB_NOT_CODED 0 +#define SB_PARTIALLY_CODED 1 +#define SB_FULLY_CODED 2 + +// This is the maximum length of a single long bit run that can be encoded +// for superblock coding or block qps. Theora special-cases this to read a +// bit instead of flipping the current bit to allow for runs longer than 4129. +#define MAXIMUM_LONG_BIT_RUN 4129 + +#define MODE_INTER_NO_MV 0 +#define MODE_INTRA 1 +#define MODE_INTER_PLUS_MV 2 +#define MODE_INTER_LAST_MV 3 +#define MODE_INTER_PRIOR_LAST 4 +#define MODE_USING_GOLDEN 5 +#define MODE_GOLDEN_MV 6 +#define MODE_INTER_FOURMV 7 +#define CODING_MODE_COUNT 8 + +/* special internal mode */ +#define MODE_COPY 8 + +static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb); +static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb); + + +/* There are 6 preset schemes, plus a free-form scheme */ +static const int ModeAlphabet[6][CODING_MODE_COUNT] = +{ + /* scheme 1: Last motion vector dominates */ + { MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, + MODE_INTER_PLUS_MV, MODE_INTER_NO_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + + /* scheme 2 */ + { MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, + MODE_INTER_NO_MV, MODE_INTER_PLUS_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + + /* scheme 3 */ + { MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV, + MODE_INTER_PRIOR_LAST, MODE_INTER_NO_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + + /* scheme 4 */ + { MODE_INTER_LAST_MV, MODE_INTER_PLUS_MV, + MODE_INTER_NO_MV, MODE_INTER_PRIOR_LAST, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + + /* scheme 5: No motion vector dominates */ + { MODE_INTER_NO_MV, MODE_INTER_LAST_MV, + MODE_INTER_PRIOR_LAST, MODE_INTER_PLUS_MV, + MODE_INTRA, MODE_USING_GOLDEN, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + + /* scheme 6 */ + { MODE_INTER_NO_MV, MODE_USING_GOLDEN, + MODE_INTER_LAST_MV, MODE_INTER_PRIOR_LAST, + MODE_INTER_PLUS_MV, MODE_INTRA, + MODE_GOLDEN_MV, MODE_INTER_FOURMV }, + +}; + +static const uint8_t hilbert_offset[16][2] = { + {0,0}, {1,0}, {1,1}, {0,1}, + {0,2}, {0,3}, {1,3}, {1,2}, + {2,2}, {2,3}, {3,3}, {3,2}, + {3,1}, {2,1}, {2,0}, {3,0} +}; + +#define MIN_DEQUANT_VAL 2 + +typedef struct Vp3DecodeContext { + AVCodecContext *avctx; + int theora, theora_tables; + int version; + int width, height; + int chroma_x_shift, chroma_y_shift; + ThreadFrame golden_frame; + ThreadFrame last_frame; + ThreadFrame current_frame; + int keyframe; + uint8_t idct_permutation[64]; + uint8_t idct_scantable[64]; + HpelDSPContext hdsp; + VideoDSPContext vdsp; + VP3DSPContext vp3dsp; + DECLARE_ALIGNED(16, int16_t, block)[64]; + int flipped_image; + int last_slice_end; + int skip_loop_filter; + + int qps[3]; + int nqps; + int last_qps[3]; + + int superblock_count; + int y_superblock_width; + int y_superblock_height; + int y_superblock_count; + int c_superblock_width; + int c_superblock_height; + int c_superblock_count; + int u_superblock_start; + int v_superblock_start; + unsigned char *superblock_coding; + + int macroblock_count; + int macroblock_width; + int macroblock_height; + + int fragment_count; + int fragment_width[2]; + int fragment_height[2]; + + Vp3Fragment *all_fragments; + int fragment_start[3]; + int data_offset[3]; + + int8_t (*motion_val[2])[2]; + + /* tables */ + uint16_t coded_dc_scale_factor[64]; + uint32_t coded_ac_scale_factor[64]; + uint8_t base_matrix[384][64]; + uint8_t qr_count[2][3]; + uint8_t qr_size [2][3][64]; + uint16_t qr_base[2][3][64]; + + /** + * This is a list of all tokens in bitstream order. Reordering takes place + * by pulling from each level during IDCT. As a consequence, IDCT must be + * in Hilbert order, making the minimum slice height 64 for 4:2:0 and 32 + * otherwise. The 32 different tokens with up to 12 bits of extradata are + * collapsed into 3 types, packed as follows: + * (from the low to high bits) + * + * 2 bits: type (0,1,2) + * 0: EOB run, 14 bits for run length (12 needed) + * 1: zero run, 7 bits for run length + * 7 bits for the next coefficient (3 needed) + * 2: coefficient, 14 bits (11 needed) + * + * Coefficients are signed, so are packed in the highest bits for automatic + * sign extension. + */ + int16_t *dct_tokens[3][64]; + int16_t *dct_tokens_base; +#define TOKEN_EOB(eob_run) ((eob_run) << 2) +#define TOKEN_ZERO_RUN(coeff, zero_run) (((coeff) << 9) + ((zero_run) << 2) + 1) +#define TOKEN_COEFF(coeff) (((coeff) << 2) + 2) + + /** + * number of blocks that contain DCT coefficients at the given level or higher + */ + int num_coded_frags[3][64]; + int total_num_coded_frags; + + /* this is a list of indexes into the all_fragments array indicating + * which of the fragments are coded */ + int *coded_fragment_list[3]; + + VLC dc_vlc[16]; + VLC ac_vlc_1[16]; + VLC ac_vlc_2[16]; + VLC ac_vlc_3[16]; + VLC ac_vlc_4[16]; + + VLC superblock_run_length_vlc; + VLC fragment_run_length_vlc; + VLC mode_code_vlc; + VLC motion_vector_vlc; + + /* these arrays need to be on 16-byte boundaries since SSE2 operations + * index into them */ + DECLARE_ALIGNED(16, int16_t, qmat)[3][2][3][64]; ///< qmat[qpi][is_inter][plane] + + /* This table contains superblock_count * 16 entries. Each set of 16 + * numbers corresponds to the fragment indexes 0..15 of the superblock. + * An entry will be -1 to indicate that no entry corresponds to that + * index. */ + int *superblock_fragments; + + /* This is an array that indicates how a particular macroblock + * is coded. */ + unsigned char *macroblock_coding; + + uint8_t *edge_emu_buffer; + + /* Huffman decode */ + int hti; + unsigned int hbits; + int entries; + int huff_code_size; + uint32_t huffman_table[80][32][2]; + + uint8_t filter_limit_values[64]; + DECLARE_ALIGNED(8, int, bounding_values_array)[256+2]; +} Vp3DecodeContext; + +/************************************************************************ + * VP3 specific functions + ************************************************************************/ + +static void vp3_decode_flush(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + + if (s->golden_frame.f) + ff_thread_release_buffer(avctx, &s->golden_frame); + if (s->last_frame.f) + ff_thread_release_buffer(avctx, &s->last_frame); + if (s->current_frame.f) + ff_thread_release_buffer(avctx, &s->current_frame); +} + +static av_cold int vp3_decode_end(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + int i; + + av_freep(&s->superblock_coding); + av_freep(&s->all_fragments); + av_freep(&s->coded_fragment_list[0]); + av_freep(&s->dct_tokens_base); + av_freep(&s->superblock_fragments); + av_freep(&s->macroblock_coding); + av_freep(&s->motion_val[0]); + av_freep(&s->motion_val[1]); + av_freep(&s->edge_emu_buffer); + + s->theora_tables = 0; + + /* release all frames */ + vp3_decode_flush(avctx); + av_frame_free(&s->current_frame.f); + av_frame_free(&s->last_frame.f); + av_frame_free(&s->golden_frame.f); + + if (avctx->internal->is_copy) + return 0; + + for (i = 0; i < 16; i++) { + ff_free_vlc(&s->dc_vlc[i]); + ff_free_vlc(&s->ac_vlc_1[i]); + ff_free_vlc(&s->ac_vlc_2[i]); + ff_free_vlc(&s->ac_vlc_3[i]); + ff_free_vlc(&s->ac_vlc_4[i]); + } + + ff_free_vlc(&s->superblock_run_length_vlc); + ff_free_vlc(&s->fragment_run_length_vlc); + ff_free_vlc(&s->mode_code_vlc); + ff_free_vlc(&s->motion_vector_vlc); + + + return 0; +} + +/** + * This function sets up all of the various blocks mappings: + * superblocks <-> fragments, macroblocks <-> fragments, + * superblocks <-> macroblocks + * + * @return 0 is successful; returns 1 if *anything* went wrong. + */ +static int init_block_mapping(Vp3DecodeContext *s) +{ + int sb_x, sb_y, plane; + int x, y, i, j = 0; + + for (plane = 0; plane < 3; plane++) { + int sb_width = plane ? s->c_superblock_width : s->y_superblock_width; + int sb_height = plane ? s->c_superblock_height : s->y_superblock_height; + int frag_width = s->fragment_width[!!plane]; + int frag_height = s->fragment_height[!!plane]; + + for (sb_y = 0; sb_y < sb_height; sb_y++) + for (sb_x = 0; sb_x < sb_width; sb_x++) + for (i = 0; i < 16; i++) { + x = 4*sb_x + hilbert_offset[i][0]; + y = 4*sb_y + hilbert_offset[i][1]; + + if (x < frag_width && y < frag_height) + s->superblock_fragments[j++] = s->fragment_start[plane] + y*frag_width + x; + else + s->superblock_fragments[j++] = -1; + } + } + + return 0; /* successful path out */ +} + +/* + * This function sets up the dequantization tables used for a particular + * frame. + */ +static void init_dequantizer(Vp3DecodeContext *s, int qpi) +{ + int ac_scale_factor = s->coded_ac_scale_factor[s->qps[qpi]]; + int dc_scale_factor = s->coded_dc_scale_factor[s->qps[qpi]]; + int i, plane, inter, qri, bmi, bmj, qistart; + + for(inter=0; inter<2; inter++){ + for(plane=0; plane<3; plane++){ + int sum=0; + for(qri=0; qriqr_count[inter][plane]; qri++){ + sum+= s->qr_size[inter][plane][qri]; + if(s->qps[qpi] <= sum) + break; + } + qistart= sum - s->qr_size[inter][plane][qri]; + bmi= s->qr_base[inter][plane][qri ]; + bmj= s->qr_base[inter][plane][qri+1]; + for(i=0; i<64; i++){ + int coeff= ( 2*(sum -s->qps[qpi])*s->base_matrix[bmi][i] + - 2*(qistart-s->qps[qpi])*s->base_matrix[bmj][i] + + s->qr_size[inter][plane][qri]) + / (2*s->qr_size[inter][plane][qri]); + + int qmin= 8<<(inter + !i); + int qscale= i ? ac_scale_factor : dc_scale_factor; + + s->qmat[qpi][inter][plane][s->idct_permutation[i]]= av_clip((qscale * coeff)/100 * 4, qmin, 4096); + } + // all DC coefficients use the same quant so as not to interfere with DC prediction + s->qmat[qpi][inter][plane][0] = s->qmat[0][inter][plane][0]; + } + } +} + +/* + * This function initializes the loop filter boundary limits if the frame's + * quality index is different from the previous frame's. + * + * The filter_limit_values may not be larger than 127. + */ +static void init_loop_filter(Vp3DecodeContext *s) +{ + int *bounding_values= s->bounding_values_array+127; + int filter_limit; + int x; + int value; + + filter_limit = s->filter_limit_values[s->qps[0]]; + av_assert0(filter_limit < 128U); + + /* set up the bounding values */ + memset(s->bounding_values_array, 0, 256 * sizeof(int)); + for (x = 0; x < filter_limit; x++) { + bounding_values[-x] = -x; + bounding_values[x] = x; + } + for (x = value = filter_limit; x < 128 && value; x++, value--) { + bounding_values[ x] = value; + bounding_values[-x] = -value; + } + if (value) + bounding_values[128] = value; + bounding_values[129] = bounding_values[130] = filter_limit * 0x02020202; +} + +/* + * This function unpacks all of the superblock/macroblock/fragment coding + * information from the bitstream. + */ +static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) +{ + int superblock_starts[3] = { 0, s->u_superblock_start, s->v_superblock_start }; + int bit = 0; + int current_superblock = 0; + int current_run = 0; + int num_partial_superblocks = 0; + + int i, j; + int current_fragment; + int plane; + + if (s->keyframe) { + memset(s->superblock_coding, SB_FULLY_CODED, s->superblock_count); + + } else { + + /* unpack the list of partially-coded superblocks */ + bit = get_bits1(gb) ^ 1; + current_run = 0; + + while (current_superblock < s->superblock_count && get_bits_left(gb) > 0) { + if (s->theora && current_run == MAXIMUM_LONG_BIT_RUN) + bit = get_bits1(gb); + else + bit ^= 1; + + current_run = get_vlc2(gb, + s->superblock_run_length_vlc.table, 6, 2) + 1; + if (current_run == 34) + current_run += get_bits(gb, 12); + + if (current_superblock + current_run > s->superblock_count) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid partially coded superblock run length\n"); + return -1; + } + + memset(s->superblock_coding + current_superblock, bit, current_run); + + current_superblock += current_run; + if (bit) + num_partial_superblocks += current_run; + } + + /* unpack the list of fully coded superblocks if any of the blocks were + * not marked as partially coded in the previous step */ + if (num_partial_superblocks < s->superblock_count) { + int superblocks_decoded = 0; + + current_superblock = 0; + bit = get_bits1(gb) ^ 1; + current_run = 0; + + while (superblocks_decoded < s->superblock_count - num_partial_superblocks + && get_bits_left(gb) > 0) { + + if (s->theora && current_run == MAXIMUM_LONG_BIT_RUN) + bit = get_bits1(gb); + else + bit ^= 1; + + current_run = get_vlc2(gb, + s->superblock_run_length_vlc.table, 6, 2) + 1; + if (current_run == 34) + current_run += get_bits(gb, 12); + + for (j = 0; j < current_run; current_superblock++) { + if (current_superblock >= s->superblock_count) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid fully coded superblock run length\n"); + return -1; + } + + /* skip any superblocks already marked as partially coded */ + if (s->superblock_coding[current_superblock] == SB_NOT_CODED) { + s->superblock_coding[current_superblock] = 2*bit; + j++; + } + } + superblocks_decoded += current_run; + } + } + + /* if there were partial blocks, initialize bitstream for + * unpacking fragment codings */ + if (num_partial_superblocks) { + + current_run = 0; + bit = get_bits1(gb); + /* toggle the bit because as soon as the first run length is + * fetched the bit will be toggled again */ + bit ^= 1; + } + } + + /* figure out which fragments are coded; iterate through each + * superblock (all planes) */ + s->total_num_coded_frags = 0; + memset(s->macroblock_coding, MODE_COPY, s->macroblock_count); + + for (plane = 0; plane < 3; plane++) { + int sb_start = superblock_starts[plane]; + int sb_end = sb_start + (plane ? s->c_superblock_count : s->y_superblock_count); + int num_coded_frags = 0; + + for (i = sb_start; i < sb_end && get_bits_left(gb) > 0; i++) { + + /* iterate through all 16 fragments in a superblock */ + for (j = 0; j < 16; j++) { + + /* if the fragment is in bounds, check its coding status */ + current_fragment = s->superblock_fragments[i * 16 + j]; + if (current_fragment != -1) { + int coded = s->superblock_coding[i]; + + if (s->superblock_coding[i] == SB_PARTIALLY_CODED) { + + /* fragment may or may not be coded; this is the case + * that cares about the fragment coding runs */ + if (current_run-- == 0) { + bit ^= 1; + current_run = get_vlc2(gb, + s->fragment_run_length_vlc.table, 5, 2); + } + coded = bit; + } + + if (coded) { + /* default mode; actual mode will be decoded in + * the next phase */ + s->all_fragments[current_fragment].coding_method = + MODE_INTER_NO_MV; + s->coded_fragment_list[plane][num_coded_frags++] = + current_fragment; + } else { + /* not coded; copy this fragment from the prior frame */ + s->all_fragments[current_fragment].coding_method = + MODE_COPY; + } + } + } + } + s->total_num_coded_frags += num_coded_frags; + for (i = 0; i < 64; i++) + s->num_coded_frags[plane][i] = num_coded_frags; + if (plane < 2) + s->coded_fragment_list[plane+1] = s->coded_fragment_list[plane] + num_coded_frags; + } + return 0; +} + +/* + * This function unpacks all the coding mode data for individual macroblocks + * from the bitstream. + */ +static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb) +{ + int i, j, k, sb_x, sb_y; + int scheme; + int current_macroblock; + int current_fragment; + int coding_mode; + int custom_mode_alphabet[CODING_MODE_COUNT]; + const int *alphabet; + Vp3Fragment *frag; + + if (s->keyframe) { + for (i = 0; i < s->fragment_count; i++) + s->all_fragments[i].coding_method = MODE_INTRA; + + } else { + + /* fetch the mode coding scheme for this frame */ + scheme = get_bits(gb, 3); + + /* is it a custom coding scheme? */ + if (scheme == 0) { + for (i = 0; i < 8; i++) + custom_mode_alphabet[i] = MODE_INTER_NO_MV; + for (i = 0; i < 8; i++) + custom_mode_alphabet[get_bits(gb, 3)] = i; + alphabet = custom_mode_alphabet; + } else + alphabet = ModeAlphabet[scheme-1]; + + /* iterate through all of the macroblocks that contain 1 or more + * coded fragments */ + for (sb_y = 0; sb_y < s->y_superblock_height; sb_y++) { + for (sb_x = 0; sb_x < s->y_superblock_width; sb_x++) { + if (get_bits_left(gb) <= 0) + return -1; + + for (j = 0; j < 4; j++) { + int mb_x = 2*sb_x + (j>>1); + int mb_y = 2*sb_y + (((j>>1)+j)&1); + current_macroblock = mb_y * s->macroblock_width + mb_x; + + if (mb_x >= s->macroblock_width || mb_y >= s->macroblock_height) + continue; + +#define BLOCK_X (2*mb_x + (k&1)) +#define BLOCK_Y (2*mb_y + (k>>1)) + /* coding modes are only stored if the macroblock has at least one + * luma block coded, otherwise it must be INTER_NO_MV */ + for (k = 0; k < 4; k++) { + current_fragment = BLOCK_Y*s->fragment_width[0] + BLOCK_X; + if (s->all_fragments[current_fragment].coding_method != MODE_COPY) + break; + } + if (k == 4) { + s->macroblock_coding[current_macroblock] = MODE_INTER_NO_MV; + continue; + } + + /* mode 7 means get 3 bits for each coding mode */ + if (scheme == 7) + coding_mode = get_bits(gb, 3); + else + coding_mode = alphabet + [get_vlc2(gb, s->mode_code_vlc.table, 3, 3)]; + + s->macroblock_coding[current_macroblock] = coding_mode; + for (k = 0; k < 4; k++) { + frag = s->all_fragments + BLOCK_Y*s->fragment_width[0] + BLOCK_X; + if (frag->coding_method != MODE_COPY) + frag->coding_method = coding_mode; + } + +#define SET_CHROMA_MODES \ + if (frag[s->fragment_start[1]].coding_method != MODE_COPY) \ + frag[s->fragment_start[1]].coding_method = coding_mode;\ + if (frag[s->fragment_start[2]].coding_method != MODE_COPY) \ + frag[s->fragment_start[2]].coding_method = coding_mode; + + if (s->chroma_y_shift) { + frag = s->all_fragments + mb_y*s->fragment_width[1] + mb_x; + SET_CHROMA_MODES + } else if (s->chroma_x_shift) { + frag = s->all_fragments + 2*mb_y*s->fragment_width[1] + mb_x; + for (k = 0; k < 2; k++) { + SET_CHROMA_MODES + frag += s->fragment_width[1]; + } + } else { + for (k = 0; k < 4; k++) { + frag = s->all_fragments + BLOCK_Y*s->fragment_width[1] + BLOCK_X; + SET_CHROMA_MODES + } + } + } + } + } + } + + return 0; +} + +/* + * This function unpacks all the motion vectors for the individual + * macroblocks from the bitstream. + */ +static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb) +{ + int j, k, sb_x, sb_y; + int coding_mode; + int motion_x[4]; + int motion_y[4]; + int last_motion_x = 0; + int last_motion_y = 0; + int prior_last_motion_x = 0; + int prior_last_motion_y = 0; + int current_macroblock; + int current_fragment; + int frag; + + if (s->keyframe) + return 0; + + /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme */ + coding_mode = get_bits1(gb); + + /* iterate through all of the macroblocks that contain 1 or more + * coded fragments */ + for (sb_y = 0; sb_y < s->y_superblock_height; sb_y++) { + for (sb_x = 0; sb_x < s->y_superblock_width; sb_x++) { + if (get_bits_left(gb) <= 0) + return -1; + + for (j = 0; j < 4; j++) { + int mb_x = 2*sb_x + (j>>1); + int mb_y = 2*sb_y + (((j>>1)+j)&1); + current_macroblock = mb_y * s->macroblock_width + mb_x; + + if (mb_x >= s->macroblock_width || mb_y >= s->macroblock_height || + (s->macroblock_coding[current_macroblock] == MODE_COPY)) + continue; + + switch (s->macroblock_coding[current_macroblock]) { + + case MODE_INTER_PLUS_MV: + case MODE_GOLDEN_MV: + /* all 6 fragments use the same motion vector */ + if (coding_mode == 0) { + motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + } else { + motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)]; + motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)]; + } + + /* vector maintenance, only on MODE_INTER_PLUS_MV */ + if (s->macroblock_coding[current_macroblock] == + MODE_INTER_PLUS_MV) { + prior_last_motion_x = last_motion_x; + prior_last_motion_y = last_motion_y; + last_motion_x = motion_x[0]; + last_motion_y = motion_y[0]; + } + break; + + case MODE_INTER_FOURMV: + /* vector maintenance */ + prior_last_motion_x = last_motion_x; + prior_last_motion_y = last_motion_y; + + /* fetch 4 vectors from the bitstream, one for each + * Y fragment, then average for the C fragment vectors */ + for (k = 0; k < 4; k++) { + current_fragment = BLOCK_Y*s->fragment_width[0] + BLOCK_X; + if (s->all_fragments[current_fragment].coding_method != MODE_COPY) { + if (coding_mode == 0) { + motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)]; + } else { + motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)]; + motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)]; + } + last_motion_x = motion_x[k]; + last_motion_y = motion_y[k]; + } else { + motion_x[k] = 0; + motion_y[k] = 0; + } + } + break; + + case MODE_INTER_LAST_MV: + /* all 6 fragments use the last motion vector */ + motion_x[0] = last_motion_x; + motion_y[0] = last_motion_y; + + /* no vector maintenance (last vector remains the + * last vector) */ + break; + + case MODE_INTER_PRIOR_LAST: + /* all 6 fragments use the motion vector prior to the + * last motion vector */ + motion_x[0] = prior_last_motion_x; + motion_y[0] = prior_last_motion_y; + + /* vector maintenance */ + prior_last_motion_x = last_motion_x; + prior_last_motion_y = last_motion_y; + last_motion_x = motion_x[0]; + last_motion_y = motion_y[0]; + break; + + default: + /* covers intra, inter without MV, golden without MV */ + motion_x[0] = 0; + motion_y[0] = 0; + + /* no vector maintenance */ + break; + } + + /* assign the motion vectors to the correct fragments */ + for (k = 0; k < 4; k++) { + current_fragment = + BLOCK_Y*s->fragment_width[0] + BLOCK_X; + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + s->motion_val[0][current_fragment][0] = motion_x[k]; + s->motion_val[0][current_fragment][1] = motion_y[k]; + } else { + s->motion_val[0][current_fragment][0] = motion_x[0]; + s->motion_val[0][current_fragment][1] = motion_y[0]; + } + } + + if (s->chroma_y_shift) { + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + motion_x[0] = RSHIFT(motion_x[0] + motion_x[1] + motion_x[2] + motion_x[3], 2); + motion_y[0] = RSHIFT(motion_y[0] + motion_y[1] + motion_y[2] + motion_y[3], 2); + } + motion_x[0] = (motion_x[0]>>1) | (motion_x[0]&1); + motion_y[0] = (motion_y[0]>>1) | (motion_y[0]&1); + frag = mb_y*s->fragment_width[1] + mb_x; + s->motion_val[1][frag][0] = motion_x[0]; + s->motion_val[1][frag][1] = motion_y[0]; + } else if (s->chroma_x_shift) { + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + motion_x[0] = RSHIFT(motion_x[0] + motion_x[1], 1); + motion_y[0] = RSHIFT(motion_y[0] + motion_y[1], 1); + motion_x[1] = RSHIFT(motion_x[2] + motion_x[3], 1); + motion_y[1] = RSHIFT(motion_y[2] + motion_y[3], 1); + } else { + motion_x[1] = motion_x[0]; + motion_y[1] = motion_y[0]; + } + motion_x[0] = (motion_x[0]>>1) | (motion_x[0]&1); + motion_x[1] = (motion_x[1]>>1) | (motion_x[1]&1); + + frag = 2*mb_y*s->fragment_width[1] + mb_x; + for (k = 0; k < 2; k++) { + s->motion_val[1][frag][0] = motion_x[k]; + s->motion_val[1][frag][1] = motion_y[k]; + frag += s->fragment_width[1]; + } + } else { + for (k = 0; k < 4; k++) { + frag = BLOCK_Y*s->fragment_width[1] + BLOCK_X; + if (s->macroblock_coding[current_macroblock] == MODE_INTER_FOURMV) { + s->motion_val[1][frag][0] = motion_x[k]; + s->motion_val[1][frag][1] = motion_y[k]; + } else { + s->motion_val[1][frag][0] = motion_x[0]; + s->motion_val[1][frag][1] = motion_y[0]; + } + } + } + } + } + } + + return 0; +} + +static int unpack_block_qpis(Vp3DecodeContext *s, GetBitContext *gb) +{ + int qpi, i, j, bit, run_length, blocks_decoded, num_blocks_at_qpi; + int num_blocks = s->total_num_coded_frags; + + for (qpi = 0; qpi < s->nqps-1 && num_blocks > 0; qpi++) { + i = blocks_decoded = num_blocks_at_qpi = 0; + + bit = get_bits1(gb) ^ 1; + run_length = 0; + + do { + if (run_length == MAXIMUM_LONG_BIT_RUN) + bit = get_bits1(gb); + else + bit ^= 1; + + run_length = get_vlc2(gb, s->superblock_run_length_vlc.table, 6, 2) + 1; + if (run_length == 34) + run_length += get_bits(gb, 12); + blocks_decoded += run_length; + + if (!bit) + num_blocks_at_qpi += run_length; + + for (j = 0; j < run_length; i++) { + if (i >= s->total_num_coded_frags) + return -1; + + if (s->all_fragments[s->coded_fragment_list[0][i]].qpi == qpi) { + s->all_fragments[s->coded_fragment_list[0][i]].qpi += bit; + j++; + } + } + } while (blocks_decoded < num_blocks && get_bits_left(gb) > 0); + + num_blocks -= num_blocks_at_qpi; + } + + return 0; +} + +/* + * This function is called by unpack_dct_coeffs() to extract the VLCs from + * the bitstream. The VLCs encode tokens which are used to unpack DCT + * data. This function unpacks all the VLCs for either the Y plane or both + * C planes, and is called for DC coefficients or different AC coefficient + * levels (since different coefficient types require different VLC tables. + * + * This function returns a residual eob run. E.g, if a particular token gave + * instructions to EOB the next 5 fragments and there were only 2 fragments + * left in the current fragment range, 3 would be returned so that it could + * be passed into the next call to this same function. + */ +static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, + VLC *table, int coeff_index, + int plane, + int eob_run) +{ + int i, j = 0; + int token; + int zero_run = 0; + int16_t coeff = 0; + int bits_to_get; + int blocks_ended; + int coeff_i = 0; + int num_coeffs = s->num_coded_frags[plane][coeff_index]; + int16_t *dct_tokens = s->dct_tokens[plane][coeff_index]; + + /* local references to structure members to avoid repeated deferences */ + int *coded_fragment_list = s->coded_fragment_list[plane]; + Vp3Fragment *all_fragments = s->all_fragments; + VLC_TYPE (*vlc_table)[2] = table->table; + + if (num_coeffs < 0) + av_log(s->avctx, AV_LOG_ERROR, "Invalid number of coefficents at level %d\n", coeff_index); + + if (eob_run > num_coeffs) { + coeff_i = blocks_ended = num_coeffs; + eob_run -= num_coeffs; + } else { + coeff_i = blocks_ended = eob_run; + eob_run = 0; + } + + // insert fake EOB token to cover the split between planes or zzi + if (blocks_ended) + dct_tokens[j++] = blocks_ended << 2; + + while (coeff_i < num_coeffs && get_bits_left(gb) > 0) { + /* decode a VLC into a token */ + token = get_vlc2(gb, vlc_table, 11, 3); + /* use the token to get a zero run, a coefficient, and an eob run */ + if ((unsigned) token <= 6U) { + eob_run = eob_run_base[token]; + if (eob_run_get_bits[token]) + eob_run += get_bits(gb, eob_run_get_bits[token]); + + // record only the number of blocks ended in this plane, + // any spill will be recorded in the next plane. + if (eob_run > num_coeffs - coeff_i) { + dct_tokens[j++] = TOKEN_EOB(num_coeffs - coeff_i); + blocks_ended += num_coeffs - coeff_i; + eob_run -= num_coeffs - coeff_i; + coeff_i = num_coeffs; + } else { + dct_tokens[j++] = TOKEN_EOB(eob_run); + blocks_ended += eob_run; + coeff_i += eob_run; + eob_run = 0; + } + } else if (token >= 0) { + bits_to_get = coeff_get_bits[token]; + if (bits_to_get) + bits_to_get = get_bits(gb, bits_to_get); + coeff = coeff_tables[token][bits_to_get]; + + zero_run = zero_run_base[token]; + if (zero_run_get_bits[token]) + zero_run += get_bits(gb, zero_run_get_bits[token]); + + if (zero_run) { + dct_tokens[j++] = TOKEN_ZERO_RUN(coeff, zero_run); + } else { + // Save DC into the fragment structure. DC prediction is + // done in raster order, so the actual DC can't be in with + // other tokens. We still need the token in dct_tokens[] + // however, or else the structure collapses on itself. + if (!coeff_index) + all_fragments[coded_fragment_list[coeff_i]].dc = coeff; + + dct_tokens[j++] = TOKEN_COEFF(coeff); + } + + if (coeff_index + zero_run > 64) { + av_log(s->avctx, AV_LOG_DEBUG, "Invalid zero run of %d with" + " %d coeffs left\n", zero_run, 64-coeff_index); + zero_run = 64 - coeff_index; + } + + // zero runs code multiple coefficients, + // so don't try to decode coeffs for those higher levels + for (i = coeff_index+1; i <= coeff_index+zero_run; i++) + s->num_coded_frags[plane][i]--; + coeff_i++; + } else { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid token %d\n", token); + return -1; + } + } + + if (blocks_ended > s->num_coded_frags[plane][coeff_index]) + av_log(s->avctx, AV_LOG_ERROR, "More blocks ended than coded!\n"); + + // decrement the number of blocks that have higher coeffecients for each + // EOB run at this level + if (blocks_ended) + for (i = coeff_index+1; i < 64; i++) + s->num_coded_frags[plane][i] -= blocks_ended; + + // setup the next buffer + if (plane < 2) + s->dct_tokens[plane+1][coeff_index] = dct_tokens + j; + else if (coeff_index < 63) + s->dct_tokens[0][coeff_index+1] = dct_tokens + j; + + return eob_run; +} + +static void reverse_dc_prediction(Vp3DecodeContext *s, + int first_fragment, + int fragment_width, + int fragment_height); +/* + * This function unpacks all of the DCT coefficient data from the + * bitstream. + */ +static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb) +{ + int i; + int dc_y_table; + int dc_c_table; + int ac_y_table; + int ac_c_table; + int residual_eob_run = 0; + VLC *y_tables[64]; + VLC *c_tables[64]; + + s->dct_tokens[0][0] = s->dct_tokens_base; + + /* fetch the DC table indexes */ + dc_y_table = get_bits(gb, 4); + dc_c_table = get_bits(gb, 4); + + /* unpack the Y plane DC coefficients */ + residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_y_table], 0, + 0, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + + /* reverse prediction of the Y-plane DC coefficients */ + reverse_dc_prediction(s, 0, s->fragment_width[0], s->fragment_height[0]); + + /* unpack the C plane DC coefficients */ + residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0, + 1, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0, + 2, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + + /* reverse prediction of the C-plane DC coefficients */ + if (!(s->avctx->flags & CODEC_FLAG_GRAY)) + { + reverse_dc_prediction(s, s->fragment_start[1], + s->fragment_width[1], s->fragment_height[1]); + reverse_dc_prediction(s, s->fragment_start[2], + s->fragment_width[1], s->fragment_height[1]); + } + + /* fetch the AC table indexes */ + ac_y_table = get_bits(gb, 4); + ac_c_table = get_bits(gb, 4); + + /* build tables of AC VLC tables */ + for (i = 1; i <= 5; i++) { + y_tables[i] = &s->ac_vlc_1[ac_y_table]; + c_tables[i] = &s->ac_vlc_1[ac_c_table]; + } + for (i = 6; i <= 14; i++) { + y_tables[i] = &s->ac_vlc_2[ac_y_table]; + c_tables[i] = &s->ac_vlc_2[ac_c_table]; + } + for (i = 15; i <= 27; i++) { + y_tables[i] = &s->ac_vlc_3[ac_y_table]; + c_tables[i] = &s->ac_vlc_3[ac_c_table]; + } + for (i = 28; i <= 63; i++) { + y_tables[i] = &s->ac_vlc_4[ac_y_table]; + c_tables[i] = &s->ac_vlc_4[ac_c_table]; + } + + /* decode all AC coefficents */ + for (i = 1; i <= 63; i++) { + residual_eob_run = unpack_vlcs(s, gb, y_tables[i], i, + 0, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + + residual_eob_run = unpack_vlcs(s, gb, c_tables[i], i, + 1, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + residual_eob_run = unpack_vlcs(s, gb, c_tables[i], i, + 2, residual_eob_run); + if (residual_eob_run < 0) + return residual_eob_run; + } + + return 0; +} + +/* + * This function reverses the DC prediction for each coded fragment in + * the frame. Much of this function is adapted directly from the original + * VP3 source code. + */ +#define COMPATIBLE_FRAME(x) \ + (compatible_frame[s->all_fragments[x].coding_method] == current_frame_type) +#define DC_COEFF(u) s->all_fragments[u].dc + +static void reverse_dc_prediction(Vp3DecodeContext *s, + int first_fragment, + int fragment_width, + int fragment_height) +{ + +#define PUL 8 +#define PU 4 +#define PUR 2 +#define PL 1 + + int x, y; + int i = first_fragment; + + int predicted_dc; + + /* DC values for the left, up-left, up, and up-right fragments */ + int vl, vul, vu, vur; + + /* indexes for the left, up-left, up, and up-right fragments */ + int l, ul, u, ur; + + /* + * The 6 fields mean: + * 0: up-left multiplier + * 1: up multiplier + * 2: up-right multiplier + * 3: left multiplier + */ + static const int predictor_transform[16][4] = { + { 0, 0, 0, 0}, + { 0, 0, 0,128}, // PL + { 0, 0,128, 0}, // PUR + { 0, 0, 53, 75}, // PUR|PL + { 0,128, 0, 0}, // PU + { 0, 64, 0, 64}, // PU|PL + { 0,128, 0, 0}, // PU|PUR + { 0, 0, 53, 75}, // PU|PUR|PL + {128, 0, 0, 0}, // PUL + { 0, 0, 0,128}, // PUL|PL + { 64, 0, 64, 0}, // PUL|PUR + { 0, 0, 53, 75}, // PUL|PUR|PL + { 0,128, 0, 0}, // PUL|PU + {-104,116, 0,116}, // PUL|PU|PL + { 24, 80, 24, 0}, // PUL|PU|PUR + {-104,116, 0,116} // PUL|PU|PUR|PL + }; + + /* This table shows which types of blocks can use other blocks for + * prediction. For example, INTRA is the only mode in this table to + * have a frame number of 0. That means INTRA blocks can only predict + * from other INTRA blocks. There are 2 golden frame coding types; + * blocks encoding in these modes can only predict from other blocks + * that were encoded with these 1 of these 2 modes. */ + static const unsigned char compatible_frame[9] = { + 1, /* MODE_INTER_NO_MV */ + 0, /* MODE_INTRA */ + 1, /* MODE_INTER_PLUS_MV */ + 1, /* MODE_INTER_LAST_MV */ + 1, /* MODE_INTER_PRIOR_MV */ + 2, /* MODE_USING_GOLDEN */ + 2, /* MODE_GOLDEN_MV */ + 1, /* MODE_INTER_FOUR_MV */ + 3 /* MODE_COPY */ + }; + int current_frame_type; + + /* there is a last DC predictor for each of the 3 frame types */ + short last_dc[3]; + + int transform = 0; + + vul = vu = vur = vl = 0; + last_dc[0] = last_dc[1] = last_dc[2] = 0; + + /* for each fragment row... */ + for (y = 0; y < fragment_height; y++) { + + /* for each fragment in a row... */ + for (x = 0; x < fragment_width; x++, i++) { + + /* reverse prediction if this block was coded */ + if (s->all_fragments[i].coding_method != MODE_COPY) { + + current_frame_type = + compatible_frame[s->all_fragments[i].coding_method]; + + transform= 0; + if(x){ + l= i-1; + vl = DC_COEFF(l); + if(COMPATIBLE_FRAME(l)) + transform |= PL; + } + if(y){ + u= i-fragment_width; + vu = DC_COEFF(u); + if(COMPATIBLE_FRAME(u)) + transform |= PU; + if(x){ + ul= i-fragment_width-1; + vul = DC_COEFF(ul); + if(COMPATIBLE_FRAME(ul)) + transform |= PUL; + } + if(x + 1 < fragment_width){ + ur= i-fragment_width+1; + vur = DC_COEFF(ur); + if(COMPATIBLE_FRAME(ur)) + transform |= PUR; + } + } + + if (transform == 0) { + + /* if there were no fragments to predict from, use last + * DC saved */ + predicted_dc = last_dc[current_frame_type]; + } else { + + /* apply the appropriate predictor transform */ + predicted_dc = + (predictor_transform[transform][0] * vul) + + (predictor_transform[transform][1] * vu) + + (predictor_transform[transform][2] * vur) + + (predictor_transform[transform][3] * vl); + + predicted_dc /= 128; + + /* check for outranging on the [ul u l] and + * [ul u ur l] predictors */ + if ((transform == 15) || (transform == 13)) { + if (FFABS(predicted_dc - vu) > 128) + predicted_dc = vu; + else if (FFABS(predicted_dc - vl) > 128) + predicted_dc = vl; + else if (FFABS(predicted_dc - vul) > 128) + predicted_dc = vul; + } + } + + /* at long last, apply the predictor */ + DC_COEFF(i) += predicted_dc; + /* save the DC */ + last_dc[current_frame_type] = DC_COEFF(i); + } + } + } +} + +static void apply_loop_filter(Vp3DecodeContext *s, int plane, int ystart, int yend) +{ + int x, y; + int *bounding_values= s->bounding_values_array+127; + + int width = s->fragment_width[!!plane]; + int height = s->fragment_height[!!plane]; + int fragment = s->fragment_start [plane] + ystart * width; + int stride = s->current_frame.f->linesize[plane]; + uint8_t *plane_data = s->current_frame.f->data [plane]; + if (!s->flipped_image) stride = -stride; + plane_data += s->data_offset[plane] + 8*ystart*stride; + + for (y = ystart; y < yend; y++) { + + for (x = 0; x < width; x++) { + /* This code basically just deblocks on the edges of coded blocks. + * However, it has to be much more complicated because of the + * braindamaged deblock ordering used in VP3/Theora. Order matters + * because some pixels get filtered twice. */ + if( s->all_fragments[fragment].coding_method != MODE_COPY ) + { + /* do not perform left edge filter for left columns frags */ + if (x > 0) { + s->vp3dsp.h_loop_filter( + plane_data + 8*x, + stride, bounding_values); + } + + /* do not perform top edge filter for top row fragments */ + if (y > 0) { + s->vp3dsp.v_loop_filter( + plane_data + 8*x, + stride, bounding_values); + } + + /* do not perform right edge filter for right column + * fragments or if right fragment neighbor is also coded + * in this frame (it will be filtered in next iteration) */ + if ((x < width - 1) && + (s->all_fragments[fragment + 1].coding_method == MODE_COPY)) { + s->vp3dsp.h_loop_filter( + plane_data + 8*x + 8, + stride, bounding_values); + } + + /* do not perform bottom edge filter for bottom row + * fragments or if bottom fragment neighbor is also coded + * in this frame (it will be filtered in the next row) */ + if ((y < height - 1) && + (s->all_fragments[fragment + width].coding_method == MODE_COPY)) { + s->vp3dsp.v_loop_filter( + plane_data + 8*x + 8*stride, + stride, bounding_values); + } + } + + fragment++; + } + plane_data += 8*stride; + } +} + +/** + * Pull DCT tokens from the 64 levels to decode and dequant the coefficients + * for the next block in coding order + */ +static inline int vp3_dequant(Vp3DecodeContext *s, Vp3Fragment *frag, + int plane, int inter, int16_t block[64]) +{ + int16_t *dequantizer = s->qmat[frag->qpi][inter][plane]; + uint8_t *perm = s->idct_scantable; + int i = 0; + + do { + int token = *s->dct_tokens[plane][i]; + switch (token & 3) { + case 0: // EOB + if (--token < 4) // 0-3 are token types, so the EOB run must now be 0 + s->dct_tokens[plane][i]++; + else + *s->dct_tokens[plane][i] = token & ~3; + goto end; + case 1: // zero run + s->dct_tokens[plane][i]++; + i += (token >> 2) & 0x7f; + if (i > 63) { + av_log(s->avctx, AV_LOG_ERROR, "Coefficient index overflow\n"); + return i; + } + block[perm[i]] = (token >> 9) * dequantizer[perm[i]]; + i++; + break; + case 2: // coeff + block[perm[i]] = (token >> 2) * dequantizer[perm[i]]; + s->dct_tokens[plane][i++]++; + break; + default: // shouldn't happen + return i; + } + } while (i < 64); + // return value is expected to be a valid level + i--; +end: + // the actual DC+prediction is in the fragment structure + block[0] = frag->dc * s->qmat[0][inter][plane][0]; + return i; +} + +/** + * called when all pixels up to row y are complete + */ +static void vp3_draw_horiz_band(Vp3DecodeContext *s, int y) +{ + int h, cy, i; + int offset[AV_NUM_DATA_POINTERS]; + + if (HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { + int y_flipped = s->flipped_image ? s->avctx->height-y : y; + + // At the end of the frame, report INT_MAX instead of the height of the frame. + // This makes the other threads' ff_thread_await_progress() calls cheaper, because + // they don't have to clip their values. + ff_thread_report_progress(&s->current_frame, y_flipped==s->avctx->height ? INT_MAX : y_flipped-1, 0); + } + + if(s->avctx->draw_horiz_band==NULL) + return; + + h= y - s->last_slice_end; + s->last_slice_end= y; + y -= h; + + if (!s->flipped_image) { + y = s->avctx->height - y - h; + } + + cy = y >> s->chroma_y_shift; + offset[0] = s->current_frame.f->linesize[0]*y; + offset[1] = s->current_frame.f->linesize[1]*cy; + offset[2] = s->current_frame.f->linesize[2]*cy; + for (i = 3; i < AV_NUM_DATA_POINTERS; i++) + offset[i] = 0; + + emms_c(); + s->avctx->draw_horiz_band(s->avctx, s->current_frame.f, offset, y, 3, h); +} + +/** + * Wait for the reference frame of the current fragment. + * The progress value is in luma pixel rows. + */ +static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment, int motion_y, int y) +{ + ThreadFrame *ref_frame; + int ref_row; + int border = motion_y&1; + + if (fragment->coding_method == MODE_USING_GOLDEN || + fragment->coding_method == MODE_GOLDEN_MV) + ref_frame = &s->golden_frame; + else + ref_frame = &s->last_frame; + + ref_row = y + (motion_y>>1); + ref_row = FFMAX(FFABS(ref_row), ref_row + 8 + border); + + ff_thread_await_progress(ref_frame, ref_row, 0); +} + +/* + * Perform the final rendering for a particular slice of data. + * The slice number ranges from 0..(c_superblock_height - 1). + */ +static void render_slice(Vp3DecodeContext *s, int slice) +{ + int x, y, i, j, fragment; + int16_t *block = s->block; + int motion_x = 0xdeadbeef, motion_y = 0xdeadbeef; + int motion_halfpel_index; + uint8_t *motion_source; + int plane, first_pixel; + + if (slice >= s->c_superblock_height) + return; + + for (plane = 0; plane < 3; plane++) { + uint8_t *output_plane = s->current_frame.f->data [plane] + s->data_offset[plane]; + uint8_t * last_plane = s-> last_frame.f->data [plane] + s->data_offset[plane]; + uint8_t *golden_plane = s-> golden_frame.f->data [plane] + s->data_offset[plane]; + int stride = s->current_frame.f->linesize[plane]; + int plane_width = s->width >> (plane && s->chroma_x_shift); + int plane_height = s->height >> (plane && s->chroma_y_shift); + int8_t (*motion_val)[2] = s->motion_val[!!plane]; + + int sb_x, sb_y = slice << (!plane && s->chroma_y_shift); + int slice_height = sb_y + 1 + (!plane && s->chroma_y_shift); + int slice_width = plane ? s->c_superblock_width : s->y_superblock_width; + + int fragment_width = s->fragment_width[!!plane]; + int fragment_height = s->fragment_height[!!plane]; + int fragment_start = s->fragment_start[plane]; + int do_await = !plane && HAVE_THREADS && (s->avctx->active_thread_type&FF_THREAD_FRAME); + + if (!s->flipped_image) stride = -stride; + if (CONFIG_GRAY && plane && (s->avctx->flags & CODEC_FLAG_GRAY)) + continue; + + /* for each superblock row in the slice (both of them)... */ + for (; sb_y < slice_height; sb_y++) { + + /* for each superblock in a row... */ + for (sb_x = 0; sb_x < slice_width; sb_x++) { + + /* for each block in a superblock... */ + for (j = 0; j < 16; j++) { + x = 4*sb_x + hilbert_offset[j][0]; + y = 4*sb_y + hilbert_offset[j][1]; + fragment = y*fragment_width + x; + + i = fragment_start + fragment; + + // bounds check + if (x >= fragment_width || y >= fragment_height) + continue; + + first_pixel = 8*y*stride + 8*x; + + if (do_await && s->all_fragments[i].coding_method != MODE_INTRA) + await_reference_row(s, &s->all_fragments[i], motion_val[fragment][1], (16*y) >> s->chroma_y_shift); + + /* transform if this block was coded */ + if (s->all_fragments[i].coding_method != MODE_COPY) { + if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) || + (s->all_fragments[i].coding_method == MODE_GOLDEN_MV)) + motion_source= golden_plane; + else + motion_source= last_plane; + + motion_source += first_pixel; + motion_halfpel_index = 0; + + /* sort out the motion vector if this fragment is coded + * using a motion vector method */ + if ((s->all_fragments[i].coding_method > MODE_INTRA) && + (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) { + int src_x, src_y; + motion_x = motion_val[fragment][0]; + motion_y = motion_val[fragment][1]; + + src_x= (motion_x>>1) + 8*x; + src_y= (motion_y>>1) + 8*y; + + motion_halfpel_index = motion_x & 0x01; + motion_source += (motion_x >> 1); + + motion_halfpel_index |= (motion_y & 0x01) << 1; + motion_source += ((motion_y >> 1) * stride); + + if(src_x<0 || src_y<0 || src_x + 9 >= plane_width || src_y + 9 >= plane_height){ + uint8_t *temp= s->edge_emu_buffer; + if(stride<0) temp -= 8*stride; + + s->vdsp.emulated_edge_mc(temp, motion_source, stride, 9, 9, src_x, src_y, plane_width, plane_height); + motion_source= temp; + } + } + + + /* first, take care of copying a block from either the + * previous or the golden frame */ + if (s->all_fragments[i].coding_method != MODE_INTRA) { + /* Note, it is possible to implement all MC cases with + put_no_rnd_pixels_l2 which would look more like the + VP3 source but this would be slower as + put_no_rnd_pixels_tab is better optimzed */ + if(motion_halfpel_index != 3){ + s->hdsp.put_no_rnd_pixels_tab[1][motion_halfpel_index]( + output_plane + first_pixel, + motion_source, stride, 8); + }else{ + int d= (motion_x ^ motion_y)>>31; // d is 0 if motion_x and _y have the same sign, else -1 + s->vp3dsp.put_no_rnd_pixels_l2( + output_plane + first_pixel, + motion_source - d, + motion_source + stride + 1 + d, + stride, 8); + } + } + + /* invert DCT and place (or add) in final output */ + + if (s->all_fragments[i].coding_method == MODE_INTRA) { + vp3_dequant(s, s->all_fragments + i, plane, 0, block); + s->vp3dsp.idct_put( + output_plane + first_pixel, + stride, + block); + } else { + if (vp3_dequant(s, s->all_fragments + i, plane, 1, block)) { + s->vp3dsp.idct_add( + output_plane + first_pixel, + stride, + block); + } else { + s->vp3dsp.idct_dc_add(output_plane + first_pixel, stride, block); + } + } + } else { + + /* copy directly from the previous frame */ + s->hdsp.put_pixels_tab[1][0]( + output_plane + first_pixel, + last_plane + first_pixel, + stride, 8); + + } + } + } + + // Filter up to the last row in the superblock row + if (!s->skip_loop_filter) + apply_loop_filter(s, plane, 4*sb_y - !!sb_y, FFMIN(4*sb_y+3, fragment_height-1)); + } + } + + /* this looks like a good place for slice dispatch... */ + /* algorithm: + * if (slice == s->macroblock_height - 1) + * dispatch (both last slice & 2nd-to-last slice); + * else if (slice > 0) + * dispatch (slice - 1); + */ + + vp3_draw_horiz_band(s, FFMIN((32 << s->chroma_y_shift) * (slice + 1) -16, s->height-16)); +} + +/// Allocate tables for per-frame data in Vp3DecodeContext +static av_cold int allocate_tables(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + int y_fragment_count, c_fragment_count; + + y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; + c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; + + s->superblock_coding = av_malloc(s->superblock_count); + s->all_fragments = av_malloc(s->fragment_count * sizeof(Vp3Fragment)); + s->coded_fragment_list[0] = av_malloc(s->fragment_count * sizeof(int)); + s->dct_tokens_base = av_malloc(64*s->fragment_count * sizeof(*s->dct_tokens_base)); + s->motion_val[0] = av_malloc(y_fragment_count * sizeof(*s->motion_val[0])); + s->motion_val[1] = av_malloc(c_fragment_count * sizeof(*s->motion_val[1])); + + /* work out the block mapping tables */ + s->superblock_fragments = av_malloc(s->superblock_count * 16 * sizeof(int)); + s->macroblock_coding = av_malloc(s->macroblock_count + 1); + + if (!s->superblock_coding || !s->all_fragments || !s->dct_tokens_base || + !s->coded_fragment_list[0] || !s->superblock_fragments || !s->macroblock_coding || + !s->motion_val[0] || !s->motion_val[1]) { + vp3_decode_end(avctx); + return -1; + } + + init_block_mapping(s); + + return 0; +} + +static av_cold int init_frames(Vp3DecodeContext *s) +{ + s->current_frame.f = av_frame_alloc(); + s->last_frame.f = av_frame_alloc(); + s->golden_frame.f = av_frame_alloc(); + + if (!s->current_frame.f || !s->last_frame.f || !s->golden_frame.f) { + av_frame_free(&s->current_frame.f); + av_frame_free(&s->last_frame.f); + av_frame_free(&s->golden_frame.f); + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_cold int vp3_decode_init(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + int i, inter, plane, ret; + int c_width; + int c_height; + int y_fragment_count, c_fragment_count; + + ret = init_frames(s); + if (ret < 0) + return ret; + + avctx->internal->allocate_progress = 1; + + if (avctx->codec_tag == MKTAG('V','P','3','0')) + s->version = 0; + else + s->version = 1; + + s->avctx = avctx; + s->width = FFALIGN(avctx->width, 16); + s->height = FFALIGN(avctx->height, 16); + if (avctx->codec_id != AV_CODEC_ID_THEORA) + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + ff_hpeldsp_init(&s->hdsp, avctx->flags | CODEC_FLAG_BITEXACT); + ff_videodsp_init(&s->vdsp, 8); + ff_vp3dsp_init(&s->vp3dsp, avctx->flags); + + for (i = 0; i < 64; i++) { +#define T(x) (x >> 3) | ((x & 7) << 3) + s->idct_permutation[i] = T(i); + s->idct_scantable[i] = T(ff_zigzag_direct[i]); +#undef T + } + + /* initialize to an impossible value which will force a recalculation + * in the first frame decode */ + for (i = 0; i < 3; i++) + s->qps[i] = -1; + + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift); + + s->y_superblock_width = (s->width + 31) / 32; + s->y_superblock_height = (s->height + 31) / 32; + s->y_superblock_count = s->y_superblock_width * s->y_superblock_height; + + /* work out the dimensions for the C planes */ + c_width = s->width >> s->chroma_x_shift; + c_height = s->height >> s->chroma_y_shift; + s->c_superblock_width = (c_width + 31) / 32; + s->c_superblock_height = (c_height + 31) / 32; + s->c_superblock_count = s->c_superblock_width * s->c_superblock_height; + + s->superblock_count = s->y_superblock_count + (s->c_superblock_count * 2); + s->u_superblock_start = s->y_superblock_count; + s->v_superblock_start = s->u_superblock_start + s->c_superblock_count; + + s->macroblock_width = (s->width + 15) / 16; + s->macroblock_height = (s->height + 15) / 16; + s->macroblock_count = s->macroblock_width * s->macroblock_height; + + s->fragment_width[0] = s->width / FRAGMENT_PIXELS; + s->fragment_height[0] = s->height / FRAGMENT_PIXELS; + s->fragment_width[1] = s->fragment_width[0] >> s->chroma_x_shift; + s->fragment_height[1] = s->fragment_height[0] >> s->chroma_y_shift; + + /* fragment count covers all 8x8 blocks for all 3 planes */ + y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; + c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; + s->fragment_count = y_fragment_count + 2*c_fragment_count; + s->fragment_start[1] = y_fragment_count; + s->fragment_start[2] = y_fragment_count + c_fragment_count; + + if (!s->theora_tables) + { + for (i = 0; i < 64; i++) { + s->coded_dc_scale_factor[i] = vp31_dc_scale_factor[i]; + s->coded_ac_scale_factor[i] = vp31_ac_scale_factor[i]; + s->base_matrix[0][i] = vp31_intra_y_dequant[i]; + s->base_matrix[1][i] = vp31_intra_c_dequant[i]; + s->base_matrix[2][i] = vp31_inter_dequant[i]; + s->filter_limit_values[i] = vp31_filter_limit_values[i]; + } + + for(inter=0; inter<2; inter++){ + for(plane=0; plane<3; plane++){ + s->qr_count[inter][plane]= 1; + s->qr_size [inter][plane][0]= 63; + s->qr_base [inter][plane][0]= + s->qr_base [inter][plane][1]= 2*inter + (!!plane)*!inter; + } + } + + /* init VLC tables */ + for (i = 0; i < 16; i++) { + + /* DC histograms */ + init_vlc(&s->dc_vlc[i], 11, 32, + &dc_bias[i][0][1], 4, 2, + &dc_bias[i][0][0], 4, 2, 0); + + /* group 1 AC histograms */ + init_vlc(&s->ac_vlc_1[i], 11, 32, + &ac_bias_0[i][0][1], 4, 2, + &ac_bias_0[i][0][0], 4, 2, 0); + + /* group 2 AC histograms */ + init_vlc(&s->ac_vlc_2[i], 11, 32, + &ac_bias_1[i][0][1], 4, 2, + &ac_bias_1[i][0][0], 4, 2, 0); + + /* group 3 AC histograms */ + init_vlc(&s->ac_vlc_3[i], 11, 32, + &ac_bias_2[i][0][1], 4, 2, + &ac_bias_2[i][0][0], 4, 2, 0); + + /* group 4 AC histograms */ + init_vlc(&s->ac_vlc_4[i], 11, 32, + &ac_bias_3[i][0][1], 4, 2, + &ac_bias_3[i][0][0], 4, 2, 0); + } + } else { + + for (i = 0; i < 16; i++) { + /* DC histograms */ + if (init_vlc(&s->dc_vlc[i], 11, 32, + &s->huffman_table[i][0][1], 8, 4, + &s->huffman_table[i][0][0], 8, 4, 0) < 0) + goto vlc_fail; + + /* group 1 AC histograms */ + if (init_vlc(&s->ac_vlc_1[i], 11, 32, + &s->huffman_table[i+16][0][1], 8, 4, + &s->huffman_table[i+16][0][0], 8, 4, 0) < 0) + goto vlc_fail; + + /* group 2 AC histograms */ + if (init_vlc(&s->ac_vlc_2[i], 11, 32, + &s->huffman_table[i+16*2][0][1], 8, 4, + &s->huffman_table[i+16*2][0][0], 8, 4, 0) < 0) + goto vlc_fail; + + /* group 3 AC histograms */ + if (init_vlc(&s->ac_vlc_3[i], 11, 32, + &s->huffman_table[i+16*3][0][1], 8, 4, + &s->huffman_table[i+16*3][0][0], 8, 4, 0) < 0) + goto vlc_fail; + + /* group 4 AC histograms */ + if (init_vlc(&s->ac_vlc_4[i], 11, 32, + &s->huffman_table[i+16*4][0][1], 8, 4, + &s->huffman_table[i+16*4][0][0], 8, 4, 0) < 0) + goto vlc_fail; + } + } + + init_vlc(&s->superblock_run_length_vlc, 6, 34, + &superblock_run_length_vlc_table[0][1], 4, 2, + &superblock_run_length_vlc_table[0][0], 4, 2, 0); + + init_vlc(&s->fragment_run_length_vlc, 5, 30, + &fragment_run_length_vlc_table[0][1], 4, 2, + &fragment_run_length_vlc_table[0][0], 4, 2, 0); + + init_vlc(&s->mode_code_vlc, 3, 8, + &mode_code_vlc_table[0][1], 2, 1, + &mode_code_vlc_table[0][0], 2, 1, 0); + + init_vlc(&s->motion_vector_vlc, 6, 63, + &motion_vector_vlc_table[0][1], 2, 1, + &motion_vector_vlc_table[0][0], 2, 1, 0); + + return allocate_tables(avctx); + +vlc_fail: + av_log(avctx, AV_LOG_FATAL, "Invalid huffman table\n"); + return -1; +} + +/// Release and shuffle frames after decode finishes +static int update_frames(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + int ret = 0; + + + /* shuffle frames (last = current) */ + ff_thread_release_buffer(avctx, &s->last_frame); + ret = ff_thread_ref_frame(&s->last_frame, &s->current_frame); + if (ret < 0) + goto fail; + + if (s->keyframe) { + ff_thread_release_buffer(avctx, &s->golden_frame); + ret = ff_thread_ref_frame(&s->golden_frame, &s->current_frame); + } + +fail: + ff_thread_release_buffer(avctx, &s->current_frame); + return ret; +} + +static int ref_frame(Vp3DecodeContext *s, ThreadFrame *dst, ThreadFrame *src) +{ + ff_thread_release_buffer(s->avctx, dst); + if (src->f->data[0]) + return ff_thread_ref_frame(dst, src); + return 0; +} + +static int ref_frames(Vp3DecodeContext *dst, Vp3DecodeContext *src) +{ + int ret; + if ((ret = ref_frame(dst, &dst->current_frame, &src->current_frame)) < 0 || + (ret = ref_frame(dst, &dst->golden_frame, &src->golden_frame)) < 0 || + (ret = ref_frame(dst, &dst->last_frame, &src->last_frame)) < 0) + return ret; + return 0; +} + +static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + Vp3DecodeContext *s = dst->priv_data, *s1 = src->priv_data; + int qps_changed = 0, i, err; + +#define copy_fields(to, from, start_field, end_field) memcpy(&to->start_field, &from->start_field, (char*)&to->end_field - (char*)&to->start_field) + + if (!s1->current_frame.f->data[0] + ||s->width != s1->width + ||s->height!= s1->height) { + if (s != s1) + ref_frames(s, s1); + return -1; + } + + if (s != s1) { + // init tables if the first frame hasn't been decoded + if (!s->current_frame.f->data[0]) { + int y_fragment_count, c_fragment_count; + s->avctx = dst; + err = allocate_tables(dst); + if (err) + return err; + y_fragment_count = s->fragment_width[0] * s->fragment_height[0]; + c_fragment_count = s->fragment_width[1] * s->fragment_height[1]; + memcpy(s->motion_val[0], s1->motion_val[0], y_fragment_count * sizeof(*s->motion_val[0])); + memcpy(s->motion_val[1], s1->motion_val[1], c_fragment_count * sizeof(*s->motion_val[1])); + } + + // copy previous frame data + if ((err = ref_frames(s, s1)) < 0) + return err; + + s->keyframe = s1->keyframe; + + // copy qscale data if necessary + for (i = 0; i < 3; i++) { + if (s->qps[i] != s1->qps[1]) { + qps_changed = 1; + memcpy(&s->qmat[i], &s1->qmat[i], sizeof(s->qmat[i])); + } + } + + if (s->qps[0] != s1->qps[0]) + memcpy(&s->bounding_values_array, &s1->bounding_values_array, sizeof(s->bounding_values_array)); + + if (qps_changed) + copy_fields(s, s1, qps, superblock_count); +#undef copy_fields + } + + return update_frames(dst); +} + +static int vp3_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + Vp3DecodeContext *s = avctx->priv_data; + GetBitContext gb; + int i, ret; + + init_get_bits(&gb, buf, buf_size * 8); + +#if CONFIG_THEORA_DECODER + if (s->theora && get_bits1(&gb)) + { + int type = get_bits(&gb, 7); + skip_bits_long(&gb, 6*8); /* "theora" */ + + if (s->avctx->active_thread_type&FF_THREAD_FRAME) { + av_log(avctx, AV_LOG_ERROR, "midstream reconfiguration with multithreading is unsupported, try -threads 1\n"); + return AVERROR_PATCHWELCOME; + } + if (type == 0) { + vp3_decode_end(avctx); + ret = theora_decode_header(avctx, &gb); + + if (ret < 0) { + vp3_decode_end(avctx); + } else + ret = vp3_decode_init(avctx); + return ret; + } else if (type == 2) { + ret = theora_decode_tables(avctx, &gb); + if (ret < 0) { + vp3_decode_end(avctx); + } else + ret = vp3_decode_init(avctx); + return ret; + } + + av_log(avctx, AV_LOG_ERROR, "Header packet passed to frame decoder, skipping\n"); + return -1; + } +#endif + + s->keyframe = !get_bits1(&gb); + if (!s->all_fragments) { + av_log(avctx, AV_LOG_ERROR, "Data packet without prior valid headers\n"); + return -1; + } + if (!s->theora) + skip_bits(&gb, 1); + for (i = 0; i < 3; i++) + s->last_qps[i] = s->qps[i]; + + s->nqps=0; + do{ + s->qps[s->nqps++]= get_bits(&gb, 6); + } while(s->theora >= 0x030200 && s->nqps<3 && get_bits1(&gb)); + for (i = s->nqps; i < 3; i++) + s->qps[i] = -1; + + if (s->avctx->debug & FF_DEBUG_PICT_INFO) + av_log(s->avctx, AV_LOG_INFO, " VP3 %sframe #%d: Q index = %d\n", + s->keyframe?"key":"", avctx->frame_number+1, s->qps[0]); + + s->skip_loop_filter = !s->filter_limit_values[s->qps[0]] || + avctx->skip_loop_filter >= (s->keyframe ? AVDISCARD_ALL : AVDISCARD_NONKEY); + + if (s->qps[0] != s->last_qps[0]) + init_loop_filter(s); + + for (i = 0; i < s->nqps; i++) + // reinit all dequantizers if the first one changed, because + // the DC of the first quantizer must be used for all matrices + if (s->qps[i] != s->last_qps[i] || s->qps[0] != s->last_qps[0]) + init_dequantizer(s, i); + + if (avctx->skip_frame >= AVDISCARD_NONKEY && !s->keyframe) + return buf_size; + + s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + s->current_frame.f->key_frame = s->keyframe; + if (ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF) < 0) + goto error; + + if (!s->edge_emu_buffer) + s->edge_emu_buffer = av_malloc(9*FFABS(s->current_frame.f->linesize[0])); + + if (s->keyframe) { + if (!s->theora) + { + skip_bits(&gb, 4); /* width code */ + skip_bits(&gb, 4); /* height code */ + if (s->version) + { + s->version = get_bits(&gb, 5); + if (avctx->frame_number == 0) + av_log(s->avctx, AV_LOG_DEBUG, "VP version: %d\n", s->version); + } + } + if (s->version || s->theora) + { + if (get_bits1(&gb)) + av_log(s->avctx, AV_LOG_ERROR, "Warning, unsupported keyframe coding type?!\n"); + skip_bits(&gb, 2); /* reserved? */ + } + } else { + if (!s->golden_frame.f->data[0]) { + av_log(s->avctx, AV_LOG_WARNING, "vp3: first frame not a keyframe\n"); + + s->golden_frame.f->pict_type = AV_PICTURE_TYPE_I; + if (ff_thread_get_buffer(avctx, &s->golden_frame, AV_GET_BUFFER_FLAG_REF) < 0) + goto error; + ff_thread_release_buffer(avctx, &s->last_frame); + if ((ret = ff_thread_ref_frame(&s->last_frame, &s->golden_frame)) < 0) + goto error; + ff_thread_report_progress(&s->last_frame, INT_MAX, 0); + } + } + + memset(s->all_fragments, 0, s->fragment_count * sizeof(Vp3Fragment)); + ff_thread_finish_setup(avctx); + + if (unpack_superblocks(s, &gb)){ + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_superblocks\n"); + goto error; + } + if (unpack_modes(s, &gb)){ + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_modes\n"); + goto error; + } + if (unpack_vectors(s, &gb)){ + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_vectors\n"); + goto error; + } + if (unpack_block_qpis(s, &gb)){ + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_block_qpis\n"); + goto error; + } + if (unpack_dct_coeffs(s, &gb)){ + av_log(s->avctx, AV_LOG_ERROR, "error in unpack_dct_coeffs\n"); + goto error; + } + + for (i = 0; i < 3; i++) { + int height = s->height >> (i && s->chroma_y_shift); + if (s->flipped_image) + s->data_offset[i] = 0; + else + s->data_offset[i] = (height-1) * s->current_frame.f->linesize[i]; + } + + s->last_slice_end = 0; + for (i = 0; i < s->c_superblock_height; i++) + render_slice(s, i); + + // filter the last row + for (i = 0; i < 3; i++) { + int row = (s->height >> (3+(i && s->chroma_y_shift))) - 1; + apply_loop_filter(s, i, row, row+1); + } + vp3_draw_horiz_band(s, s->avctx->height); + + if ((ret = av_frame_ref(data, s->current_frame.f)) < 0) + return ret; + *got_frame = 1; + + if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME)) { + ret = update_frames(avctx); + if (ret < 0) + return ret; + } + + return buf_size; + +error: + ff_thread_report_progress(&s->current_frame, INT_MAX, 0); + + if (!HAVE_THREADS || !(s->avctx->active_thread_type&FF_THREAD_FRAME)) + av_frame_unref(s->current_frame.f); + + return -1; +} + +static int read_huffman_tree(AVCodecContext *avctx, GetBitContext *gb) +{ + Vp3DecodeContext *s = avctx->priv_data; + + if (get_bits1(gb)) { + int token; + if (s->entries >= 32) { /* overflow */ + av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n"); + return -1; + } + token = get_bits(gb, 5); + av_dlog(avctx, "hti %d hbits %x token %d entry : %d size %d\n", + s->hti, s->hbits, token, s->entries, s->huff_code_size); + s->huffman_table[s->hti][token][0] = s->hbits; + s->huffman_table[s->hti][token][1] = s->huff_code_size; + s->entries++; + } + else { + if (s->huff_code_size >= 32) {/* overflow */ + av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n"); + return -1; + } + s->huff_code_size++; + s->hbits <<= 1; + if (read_huffman_tree(avctx, gb)) + return -1; + s->hbits |= 1; + if (read_huffman_tree(avctx, gb)) + return -1; + s->hbits >>= 1; + s->huff_code_size--; + } + return 0; +} + +static int vp3_init_thread_copy(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + + s->superblock_coding = NULL; + s->all_fragments = NULL; + s->coded_fragment_list[0] = NULL; + s->dct_tokens_base = NULL; + s->superblock_fragments = NULL; + s->macroblock_coding = NULL; + s->motion_val[0] = NULL; + s->motion_val[1] = NULL; + s->edge_emu_buffer = NULL; + + return init_frames(s); +} + +#if CONFIG_THEORA_DECODER +static const enum AVPixelFormat theora_pix_fmts[4] = { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P +}; + +static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb) +{ + Vp3DecodeContext *s = avctx->priv_data; + int visible_width, visible_height, colorspace; + int offset_x = 0, offset_y = 0; + AVRational fps, aspect; + + s->theora = get_bits_long(gb, 24); + av_log(avctx, AV_LOG_DEBUG, "Theora bitstream version %X\n", s->theora); + + /* 3.2.0 aka alpha3 has the same frame orientation as original vp3 */ + /* but previous versions have the image flipped relative to vp3 */ + if (s->theora < 0x030200) + { + s->flipped_image = 1; + av_log(avctx, AV_LOG_DEBUG, "Old (width = get_bits(gb, 16) << 4; + visible_height = s->height = get_bits(gb, 16) << 4; + + if(av_image_check_size(s->width, s->height, 0, avctx)){ + av_log(avctx, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n", s->width, s->height); + s->width= s->height= 0; + return -1; + } + + if (s->theora >= 0x030200) { + visible_width = get_bits_long(gb, 24); + visible_height = get_bits_long(gb, 24); + + offset_x = get_bits(gb, 8); /* offset x */ + offset_y = get_bits(gb, 8); /* offset y, from bottom */ + } + + fps.num = get_bits_long(gb, 32); + fps.den = get_bits_long(gb, 32); + if (fps.num && fps.den) { + av_reduce(&avctx->time_base.num, &avctx->time_base.den, + fps.den, fps.num, 1<<30); + } + + aspect.num = get_bits_long(gb, 24); + aspect.den = get_bits_long(gb, 24); + if (aspect.num && aspect.den) { + av_reduce(&avctx->sample_aspect_ratio.num, + &avctx->sample_aspect_ratio.den, + aspect.num, aspect.den, 1<<30); + } + + if (s->theora < 0x030200) + skip_bits(gb, 5); /* keyframe frequency force */ + colorspace = get_bits(gb, 8); + skip_bits(gb, 24); /* bitrate */ + + skip_bits(gb, 6); /* quality hint */ + + if (s->theora >= 0x030200) + { + skip_bits(gb, 5); /* keyframe frequency force */ + avctx->pix_fmt = theora_pix_fmts[get_bits(gb, 2)]; + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Invalid pixel format\n"); + return AVERROR_INVALIDDATA; + } + skip_bits(gb, 3); /* reserved */ + } + +// align_get_bits(gb); + + if ( visible_width <= s->width && visible_width > s->width-16 + && visible_height <= s->height && visible_height > s->height-16 + && !offset_x && (offset_y == s->height - visible_height)) + avcodec_set_dimensions(avctx, visible_width, visible_height); + else + avcodec_set_dimensions(avctx, s->width, s->height); + + if (colorspace == 1) { + avctx->color_primaries = AVCOL_PRI_BT470M; + } else if (colorspace == 2) { + avctx->color_primaries = AVCOL_PRI_BT470BG; + } + if (colorspace == 1 || colorspace == 2) { + avctx->colorspace = AVCOL_SPC_BT470BG; + avctx->color_trc = AVCOL_TRC_BT709; + } + + return 0; +} + +static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb) +{ + Vp3DecodeContext *s = avctx->priv_data; + int i, n, matrices, inter, plane; + + if (s->theora >= 0x030200) { + n = get_bits(gb, 3); + /* loop filter limit values table */ + if (n) + for (i = 0; i < 64; i++) + s->filter_limit_values[i] = get_bits(gb, n); + } + + if (s->theora >= 0x030200) + n = get_bits(gb, 4) + 1; + else + n = 16; + /* quality threshold table */ + for (i = 0; i < 64; i++) + s->coded_ac_scale_factor[i] = get_bits(gb, n); + + if (s->theora >= 0x030200) + n = get_bits(gb, 4) + 1; + else + n = 16; + /* dc scale factor table */ + for (i = 0; i < 64; i++) + s->coded_dc_scale_factor[i] = get_bits(gb, n); + + if (s->theora >= 0x030200) + matrices = get_bits(gb, 9) + 1; + else + matrices = 3; + + if(matrices > 384){ + av_log(avctx, AV_LOG_ERROR, "invalid number of base matrixes\n"); + return -1; + } + + for(n=0; nbase_matrix[n][i]= get_bits(gb, 8); + } + + for (inter = 0; inter <= 1; inter++) { + for (plane = 0; plane <= 2; plane++) { + int newqr= 1; + if (inter || plane > 0) + newqr = get_bits1(gb); + if (!newqr) { + int qtj, plj; + if(inter && get_bits1(gb)){ + qtj = 0; + plj = plane; + }else{ + qtj= (3*inter + plane - 1) / 3; + plj= (plane + 2) % 3; + } + s->qr_count[inter][plane]= s->qr_count[qtj][plj]; + memcpy(s->qr_size[inter][plane], s->qr_size[qtj][plj], sizeof(s->qr_size[0][0])); + memcpy(s->qr_base[inter][plane], s->qr_base[qtj][plj], sizeof(s->qr_base[0][0])); + } else { + int qri= 0; + int qi = 0; + + for(;;){ + i= get_bits(gb, av_log2(matrices-1)+1); + if(i>= matrices){ + av_log(avctx, AV_LOG_ERROR, "invalid base matrix index\n"); + return -1; + } + s->qr_base[inter][plane][qri]= i; + if(qi >= 63) + break; + i = get_bits(gb, av_log2(63-qi)+1) + 1; + s->qr_size[inter][plane][qri++]= i; + qi += i; + } + + if (qi > 63) { + av_log(avctx, AV_LOG_ERROR, "invalid qi %d > 63\n", qi); + return -1; + } + s->qr_count[inter][plane]= qri; + } + } + } + + /* Huffman tables */ + for (s->hti = 0; s->hti < 80; s->hti++) { + s->entries = 0; + s->huff_code_size = 1; + if (!get_bits1(gb)) { + s->hbits = 0; + if(read_huffman_tree(avctx, gb)) + return -1; + s->hbits = 1; + if(read_huffman_tree(avctx, gb)) + return -1; + } + } + + s->theora_tables = 1; + + return 0; +} + +static av_cold int theora_decode_init(AVCodecContext *avctx) +{ + Vp3DecodeContext *s = avctx->priv_data; + GetBitContext gb; + int ptype; + uint8_t *header_start[3]; + int header_len[3]; + int i; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + s->theora = 1; + + if (!avctx->extradata_size) + { + av_log(avctx, AV_LOG_ERROR, "Missing extradata!\n"); + return -1; + } + + if (avpriv_split_xiph_headers(avctx->extradata, avctx->extradata_size, + 42, header_start, header_len) < 0) { + av_log(avctx, AV_LOG_ERROR, "Corrupt extradata\n"); + return -1; + } + + for(i=0;i<3;i++) { + if (header_len[i] <= 0) + continue; + init_get_bits(&gb, header_start[i], header_len[i] * 8); + + ptype = get_bits(&gb, 8); + + if (!(ptype & 0x80)) + { + av_log(avctx, AV_LOG_ERROR, "Invalid extradata!\n"); +// return -1; + } + + // FIXME: Check for this as well. + skip_bits_long(&gb, 6*8); /* "theora" */ + + switch(ptype) + { + case 0x80: + if (theora_decode_header(avctx, &gb) < 0) + return -1; + break; + case 0x81: +// FIXME: is this needed? it breaks sometimes +// theora_decode_comments(avctx, gb); + break; + case 0x82: + if (theora_decode_tables(avctx, &gb)) + return -1; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown Theora config packet: %d\n", ptype&~0x80); + break; + } + if(ptype != 0x81 && 8*header_len[i] != get_bits_count(&gb)) + av_log(avctx, AV_LOG_WARNING, "%d bits left in packet %X\n", 8*header_len[i] - get_bits_count(&gb), ptype); + if (s->theora < 0x030200) + break; + } + + return vp3_decode_init(avctx); +} + +AVCodec ff_theora_decoder = { + .name = "theora", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_THEORA, + .priv_data_size = sizeof(Vp3DecodeContext), + .init = theora_decode_init, + .close = vp3_decode_end, + .decode = vp3_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_FRAME_THREADS, + .flush = vp3_decode_flush, + .long_name = NULL_IF_CONFIG_SMALL("Theora"), + .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context) +}; +#endif + +AVCodec ff_vp3_decoder = { + .name = "vp3", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP3, + .priv_data_size = sizeof(Vp3DecodeContext), + .init = vp3_decode_init, + .close = vp3_decode_end, + .decode = vp3_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_DRAW_HORIZ_BAND | + CODEC_CAP_FRAME_THREADS, + .flush = vp3_decode_flush, + .long_name = NULL_IF_CONFIG_SMALL("On2 VP3"), + .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), +}; diff --git a/ffmpeg/libavcodec/vp3_parser.c b/ffmpeg/libavcodec/vp3_parser.c new file mode 100644 index 0000000..ce15309 --- /dev/null +++ b/ffmpeg/libavcodec/vp3_parser.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008 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 "parser.h" + +static int parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + if(avctx->codec_id == AV_CODEC_ID_THEORA) + s->pict_type= (buf[0]&0x40) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + else + s->pict_type= (buf[0]&0x80) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +AVCodecParser ff_vp3_parser = { + .codec_ids = { AV_CODEC_ID_THEORA, AV_CODEC_ID_VP3, AV_CODEC_ID_VP6, + AV_CODEC_ID_VP6F, AV_CODEC_ID_VP6A }, + .parser_parse = parse, +}; diff --git a/ffmpeg/libavcodec/vp3data.h b/ffmpeg/libavcodec/vp3data.h new file mode 100644 index 0000000..904ec6a --- /dev/null +++ b/ffmpeg/libavcodec/vp3data.h @@ -0,0 +1,3181 @@ +/* + * copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +#ifndef AVCODEC_VP3DATA_H +#define AVCODEC_VP3DATA_H + +#include +#include + +/* these coefficients dequantize intraframe Y plane coefficients + * (note: same as JPEG) */ +static const int16_t vp31_intra_y_dequant[64] = +{ 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 58, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +/* these coefficients dequantize intraframe C plane coefficients + * (note: same as JPEG) */ +static const int16_t vp31_intra_c_dequant[64] = +{ 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +/* these coefficients dequantize interframe coefficients (all planes) */ +static const int16_t vp31_inter_dequant[64] = +{ 16, 16, 16, 20, 24, 28, 32, 40, + 16, 16, 20, 24, 28, 32, 40, 48, + 16, 20, 24, 28, 32, 40, 48, 64, + 20, 24, 28, 32, 40, 48, 64, 64, + 24, 28, 32, 40, 48, 64, 64, 64, + 28, 32, 40, 48, 64, 64, 64, 96, + 32, 40, 48, 64, 64, 64, 96, 128, + 40, 48, 64, 64, 64, 96, 128, 128 +}; + +static const int16_t vp31_dc_scale_factor[64] = +{ 220, 200, 190, 180, 170, 170, 160, 160, + 150, 150, 140, 140, 130, 130, 120, 120, + 110, 110, 100, 100, 90, 90, 90, 80, + 80, 80, 70, 70, 70, 60, 60, 60, + 60, 50, 50, 50, 50, 40, 40, 40, + 40, 40, 30, 30, 30, 30, 30, 30, + 30, 20, 20, 20, 20, 20, 20, 20, + 20, 10, 10, 10, 10, 10, 10, 10 +}; + +static const uint32_t vp31_ac_scale_factor[64] = +{ 500, 450, 400, 370, 340, 310, 285, 265, + 245, 225, 210, 195, 185, 180, 170, 160, + 150, 145, 135, 130, 125, 115, 110, 107, + 100, 96, 93, 89, 85, 82, 75, 74, + 70, 68, 64, 60, 57, 56, 52, 50, + 49, 45, 44, 43, 40, 38, 37, 35, + 33, 32, 30, 29, 28, 25, 24, 22, + 21, 19, 18, 17, 15, 13, 12, 10 +}; + +static const uint8_t vp31_filter_limit_values[64] = +{ 30, 25, 20, 20, 15, 15, 14, 14, + 13, 13, 12, 12, 11, 11, 10, 10, + 9, 9, 8, 8, 7, 7, 7, 7, + 6, 6, 6, 6, 5, 5, 5, 5, + 4, 4, 4, 4, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const uint16_t superblock_run_length_vlc_table[34][2] = { + { 0, 1 }, + + { 4, 3 }, { 5, 3 }, + + { 0xC, 4 }, { 0xD, 4 }, + + { 0x38, 6 }, { 0x39, 6 }, { 0x3A, 6 }, { 0x3B, 6 }, + + { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, + { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, + + { 0x3E0, 10 }, { 0x3E1, 10 }, { 0x3E2, 10 }, { 0x3E3, 10 }, + { 0x3E4, 10 }, { 0x3E5, 10 }, { 0x3E6, 10 }, { 0x3E7, 10 }, + { 0x3E8, 10 }, { 0x3E9, 10 }, { 0x3EA, 10 }, { 0x3EB, 10 }, + { 0x3EC, 10 }, { 0x3ED, 10 }, { 0x3EE, 10 }, { 0x3EF, 10 }, + + { 0x3F, 6 } /* this last VLC is a special case for reading 12 more + bits from stream and adding the value 34 */ +}; + +static const uint16_t fragment_run_length_vlc_table[30][2] = { + /* 1 -> 2 */ + { 0x0, 2 }, { 0x1, 2 }, + + /* 3 -> 4 */ + { 0x4, 3 }, { 0x5, 3 }, + + /* 5 -> 6 */ + { 0xC, 4 }, { 0xD, 4 }, + + /* 7 -> 10 */ + { 0x38, 6 }, { 0x39, 6 }, + { 0x3A, 6 }, { 0x3B, 6 }, + + /* 11 -> 14 */ + { 0x78, 7 }, { 0x79, 7 }, + { 0x7A, 7 }, { 0x7B, 7 }, + + /* 15 -> 30 */ + { 0x1F0, 9 }, { 0x1F1, 9 }, { 0x1F2, 9 }, { 0x1F3, 9 }, + { 0x1F4, 9 }, { 0x1F5, 9 }, { 0x1F6, 9 }, { 0x1F7, 9 }, + { 0x1F8, 9 }, { 0x1F9, 9 }, { 0x1FA, 9 }, { 0x1FB, 9 }, + { 0x1FC, 9 }, { 0x1FD, 9 }, { 0x1FE, 9 }, { 0x1FF, 9 } +}; + +static const uint8_t mode_code_vlc_table[8][2] = { + { 0, 1 }, { 2, 2 }, + { 6, 3 }, { 14, 4 }, + { 30, 5 }, { 62, 6 }, + { 126, 7 }, { 127, 7 } +}; + +static const uint8_t motion_vector_vlc_table[63][2] = { + { 0, 3 }, + { 1, 3 }, + { 2, 3 }, + + { 6, 4 }, { 7, 4 }, + + { 8, 4 }, { 9, 4 }, + + { 40, 6 }, { 41, 6 }, { 42, 6 }, { 43, 6 }, + { 44, 6 }, { 45, 6 }, { 46, 6 }, { 47, 6 }, + + { 96, 7 }, { 97, 7 }, { 98, 7 }, { 99, 7 }, + { 100, 7 }, { 101, 7 }, { 102, 7 }, { 103, 7 }, + { 104, 7 }, { 105, 7 }, { 106, 7 }, { 107, 7 }, + { 108, 7 }, { 109, 7 }, { 110, 7 }, { 111, 7 }, + + { 0xE0, 8 }, { 0xE1, 8 }, { 0xE2, 8 }, { 0xE3, 8 }, + { 0xE4, 8 }, { 0xE5, 8 }, { 0xE6, 8 }, { 0xE7, 8 }, + { 0xE8, 8 }, { 0xE9, 8 }, { 0xEA, 8 }, { 0xEB, 8 }, + { 0xEC, 8 }, { 0xED, 8 }, { 0xEE, 8 }, { 0xEF, 8 }, + + { 0xF0, 8 }, { 0xF1, 8 }, { 0xF2, 8 }, { 0xF3, 8 }, + { 0xF4, 8 }, { 0xF5, 8 }, { 0xF6, 8 }, { 0xF7, 8 }, + { 0xF8, 8 }, { 0xF9, 8 }, { 0xFA, 8 }, { 0xFB, 8 }, + { 0xFC, 8 }, { 0xFD, 8 }, { 0xFE, 8 }, { 0xFF, 8 } +}; + +static const int motion_vector_table[63] = { + 0, 1, -1, + 2, -2, + 3, -3, + 4, -4, 5, -5, 6, -6, 7, -7, + 8, -8, 9, -9, 10, -10, 11, -11, 12, -12, 13, -13, 14, -14, 15, -15, + 16, -16, 17, -17, 18, -18, 19, -19, 20, -20, 21, -21, 22, -22, 23, -23, + 24, -24, 25, -25, 26, -26, 27, -27, 28, -28, 29, -29, 30, -30, 31, -31 +}; + +static const int8_t fixed_motion_vector_table[64] = { + 0, 0, 1, -1, 2, -2, 3, -3, + 4, -4, 5, -5, 6, -6, 7, -7, + 8, -8, 9, -9, 10, -10, 11, -11, + 12, -12, 13, -13, 14, -14, 15, -15, + 16, -16, 17, -17, 18, -18, 19, -19, + 20, -20, 21, -21, 22, -22, 23, -23, + 24, -24, 25, -25, 26, -26, 27, -27, + 28, -28, 29, -29, 30, -30, 31, -31 +}; + +/* only tokens 0..6 indicate eob runs */ +static const int eob_run_base[7] = { + 1, 2, 3, 4, 8, 16, 0 +}; +static const int eob_run_get_bits[7] = { + 0, 0, 0, 2, 3, 4, 12 +}; + +static const int zero_run_base[32] = { + 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ + 0, 0, /* 7..8 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9..22 */ + 1, 2, 3, 4, 5, /* 23..27 */ + 6, 10, 1, 2 /* 28..31 */ +}; +static const int zero_run_get_bits[32] = { + 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ + 3, 6, /* 7..8 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9..22 */ + 0, 0, 0, 0, 0, /* 23..27 */ + 2, 3, 0, 1 /* 28..31 */ +}; + +static const int coeff_get_bits[32] = { + 0, 0, 0, 0, 0, 0, 0, /* 0..6 are never used */ + 0, 0, 0, 0, 0, 0, /* 7..12 use constant coeffs */ + 1, 1, 1, 1, /* 13..16 are constants but still need sign bit */ + 2, 3, 4, 5, 6, 10, /* 17..22, for reading large coeffs */ + 1, 1, 1, 1, 1, 1, 1, /* 23..29 are constants but still need sign bit */ + 2, 2 /* 30..31 */ +}; + +static const int16_t coeff_table_token_7_8[1] = { 0 }; +static const int16_t coeff_table_token_9[1] = { 1 }; +static const int16_t coeff_table_token_10[1] = { -1 }; +static const int16_t coeff_table_token_11[1] = { 2 }; +static const int16_t coeff_table_token_12[1] = { -2 }; + +static const int16_t coeff_table_token_13[2] = { 3, -3 }; +static const int16_t coeff_table_token_14[2] = { 4, -4 }; +static const int16_t coeff_table_token_15[2] = { 5, -5 }; +static const int16_t coeff_table_token_16[2] = { 6, -6 }; + +static const int16_t coeff_table_token_23_24_25_26_27_28_29[2] = { 1, -1 }; +static const int16_t coeff_table_token_30[4] = { 2, 3, -2, -3 }; +static const int16_t coeff_table_token_31[4] = { 2, 3, -2, -3 }; + +static const int16_t coeff_table_token_17[4] = { + 7, 8, -7, -8 +}; + +static const int16_t coeff_table_token_18[8] = { + 9, 10, 11, 12, -9, -10, -11, -12 +}; + +static const int16_t coeff_table_token_19[16] = { + 13, 14, 15, 16, 17, 18, 19, 20, -13, -14, -15, -16, -17, -18, -19, -20 +}; + +static const int16_t coeff_table_token_20[32] = { + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + -21, -22, -23, -24, -25, -26, -27, -28, + -29, -30, -31, -32, -33, -34, -35, -36 +}; + +static const int16_t coeff_table_token_21[64] = { + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, + -37, -38, -39, -40, -41, -42, -43, -44, + -45, -46, -47, -48, -49, -50, -51, -52, + -53, -54, -55, -56, -57, -58, -59, -60, + -61, -62, -63, -64, -65, -66, -67, -68 +}; + +static const int16_t coeff_table_token_22[1024] = { + 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, + 429, 430, 431, 432, 433, 434, 435, 436, + 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 449, 450, 451, 452, + 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 484, + 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, + 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 520, 521, 522, 523, 524, + 525, 526, 527, 528, 529, 530, 531, 532, + 533, 534, 535, 536, 537, 538, 539, 540, + 541, 542, 543, 544, 545, 546, 547, 548, + 549, 550, 551, 552, 553, 554, 555, 556, + 557, 558, 559, 560, 561, 562, 563, 564, + 565, 566, 567, 568, 569, 570, 571, 572, + 573, 574, 575, 576, 577, 578, 579, 580, + -69, -70, -71, -72, -73, -74, -75, -76, + -77, -78, -79, -80, -81, -82, -83, -84, + -85, -86, -87, -88, -89, -90, -91, -92, + -93, -94, -95, -96, -97, -98, -99, -100, + -101, -102, -103, -104, -105, -106, -107, -108, + -109, -110, -111, -112, -113, -114, -115, -116, + -117, -118, -119, -120, -121, -122, -123, -124, + -125, -126, -127, -128, -129, -130, -131, -132, + -133, -134, -135, -136, -137, -138, -139, -140, + -141, -142, -143, -144, -145, -146, -147, -148, + -149, -150, -151, -152, -153, -154, -155, -156, + -157, -158, -159, -160, -161, -162, -163, -164, + -165, -166, -167, -168, -169, -170, -171, -172, + -173, -174, -175, -176, -177, -178, -179, -180, + -181, -182, -183, -184, -185, -186, -187, -188, + -189, -190, -191, -192, -193, -194, -195, -196, + -197, -198, -199, -200, -201, -202, -203, -204, + -205, -206, -207, -208, -209, -210, -211, -212, + -213, -214, -215, -216, -217, -218, -219, -220, + -221, -222, -223, -224, -225, -226, -227, -228, + -229, -230, -231, -232, -233, -234, -235, -236, + -237, -238, -239, -240, -241, -242, -243, -244, + -245, -246, -247, -248, -249, -250, -251, -252, + -253, -254, -255, -256, -257, -258, -259, -260, + -261, -262, -263, -264, -265, -266, -267, -268, + -269, -270, -271, -272, -273, -274, -275, -276, + -277, -278, -279, -280, -281, -282, -283, -284, + -285, -286, -287, -288, -289, -290, -291, -292, + -293, -294, -295, -296, -297, -298, -299, -300, + -301, -302, -303, -304, -305, -306, -307, -308, + -309, -310, -311, -312, -313, -314, -315, -316, + -317, -318, -319, -320, -321, -322, -323, -324, + -325, -326, -327, -328, -329, -330, -331, -332, + -333, -334, -335, -336, -337, -338, -339, -340, + -341, -342, -343, -344, -345, -346, -347, -348, + -349, -350, -351, -352, -353, -354, -355, -356, + -357, -358, -359, -360, -361, -362, -363, -364, + -365, -366, -367, -368, -369, -370, -371, -372, + -373, -374, -375, -376, -377, -378, -379, -380, + -381, -382, -383, -384, -385, -386, -387, -388, + -389, -390, -391, -392, -393, -394, -395, -396, + -397, -398, -399, -400, -401, -402, -403, -404, + -405, -406, -407, -408, -409, -410, -411, -412, + -413, -414, -415, -416, -417, -418, -419, -420, + -421, -422, -423, -424, -425, -426, -427, -428, + -429, -430, -431, -432, -433, -434, -435, -436, + -437, -438, -439, -440, -441, -442, -443, -444, + -445, -446, -447, -448, -449, -450, -451, -452, + -453, -454, -455, -456, -457, -458, -459, -460, + -461, -462, -463, -464, -465, -466, -467, -468, + -469, -470, -471, -472, -473, -474, -475, -476, + -477, -478, -479, -480, -481, -482, -483, -484, + -485, -486, -487, -488, -489, -490, -491, -492, + -493, -494, -495, -496, -497, -498, -499, -500, + -501, -502, -503, -504, -505, -506, -507, -508, + -509, -510, -511, -512, -513, -514, -515, -516, + -517, -518, -519, -520, -521, -522, -523, -524, + -525, -526, -527, -528, -529, -530, -531, -532, + -533, -534, -535, -536, -537, -538, -539, -540, + -541, -542, -543, -544, -545, -546, -547, -548, + -549, -550, -551, -552, -553, -554, -555, -556, + -557, -558, -559, -560, -561, -562, -563, -564, + -565, -566, -567, -568, -569, -570, -571, -572, + -573, -574, -575, -576, -577, -578, -579, -580 +}; + +static const int16_t *const coeff_tables[32] = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + coeff_table_token_7_8, + + coeff_table_token_7_8, + coeff_table_token_9, + coeff_table_token_10, + coeff_table_token_11, + coeff_table_token_12, + coeff_table_token_13, + coeff_table_token_14, + coeff_table_token_15, + + coeff_table_token_16, + coeff_table_token_17, + coeff_table_token_18, + coeff_table_token_19, + coeff_table_token_20, + coeff_table_token_21, + coeff_table_token_22, + coeff_table_token_23_24_25_26_27_28_29, + + coeff_table_token_23_24_25_26_27_28_29, + coeff_table_token_23_24_25_26_27_28_29, + coeff_table_token_23_24_25_26_27_28_29, + coeff_table_token_23_24_25_26_27_28_29, + coeff_table_token_23_24_25_26_27_28_29, + coeff_table_token_23_24_25_26_27_28_29, + coeff_table_token_30, + coeff_table_token_31 +}; + +static const uint16_t dc_bias[16][32][2] = { + { /* DC bias table 0 */ + { 0x2D, 6 }, + { 0x26, 7 }, + { 0x166, 9 }, + { 0x4E, 8 }, + { 0x2CE, 10 }, + { 0x59E, 11 }, + { 0x27D, 11 }, + { 0x8, 5 }, + { 0x4F9, 12 }, + { 0xF, 4 }, + { 0xE, 4 }, + { 0x1B, 5 }, + { 0x6, 4 }, + { 0x8, 4 }, + { 0x5, 4 }, + { 0x1A, 5 }, + { 0x15, 5 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x17, 5 }, + { 0x29, 6 }, + { 0x28, 6 }, + { 0xB2, 8 }, + { 0x4F8, 12 }, + { 0x59F, 11 }, + { 0x9E, 9 }, + { 0x13F, 10 }, + { 0x12, 6 }, + { 0x58, 7 } + }, + { /* DC bias table 1 */ + { 0x10, 5 }, + { 0x47, 7 }, + { 0x1FF, 9 }, + { 0x8C, 8 }, + { 0x3FC, 10 }, + { 0x46A, 11 }, + { 0x469, 11 }, + { 0x22, 6 }, + { 0x11A1, 13 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0x4, 4 }, + { 0x5, 4 }, + { 0x9, 4 }, + { 0x6, 4 }, + { 0x1E, 5 }, + { 0x16, 5 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xA, 4 }, + { 0x17, 5 }, + { 0x7D, 7 }, + { 0x7E, 7 }, + { 0x11B, 9 }, + { 0x8D1, 12 }, + { 0x3FD, 10 }, + { 0x46B, 11 }, + { 0x11A0, 13 }, + { 0x7C, 7 }, + { 0xFE, 8 } + }, + { /* DC bias table 2 */ + { 0x16, 5 }, + { 0x20, 6 }, + { 0x86, 8 }, + { 0x87, 8 }, + { 0x367, 10 }, + { 0x6CC, 11 }, + { 0x6CB, 11 }, + { 0x6E, 7 }, + { 0x366D, 14 }, + { 0xF, 4 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0x5, 4 }, + { 0xA, 4 }, + { 0x6, 4 }, + { 0x1A, 5 }, + { 0x11, 5 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x17, 5 }, + { 0x6F, 7 }, + { 0x6D, 7 }, + { 0x364, 10 }, + { 0xD9A, 12 }, + { 0x6CA, 11 }, + { 0x1B37, 13 }, + { 0x366C, 14 }, + { 0x42, 7 }, + { 0xD8, 8 } + }, + { /* DC bias table 3 */ + { 0x0, 4 }, + { 0x2D, 6 }, + { 0xF7, 8 }, + { 0x58, 7 }, + { 0x167, 9 }, + { 0x2CB, 10 }, + { 0x2CA, 10 }, + { 0xE, 6 }, + { 0x1661, 13 }, + { 0x3, 3 }, + { 0x2, 3 }, + { 0x8, 4 }, + { 0x9, 4 }, + { 0xD, 4 }, + { 0x2, 4 }, + { 0x1F, 5 }, + { 0x17, 5 }, + { 0x1, 4 }, + { 0xC, 4 }, + { 0xE, 4 }, + { 0xA, 4 }, + { 0x6, 5 }, + { 0x78, 7 }, + { 0xF, 6 }, + { 0x7A, 7 }, + { 0x164, 9 }, + { 0x599, 11 }, + { 0x2CD, 10 }, + { 0xB31, 12 }, + { 0x1660, 13 }, + { 0x79, 7 }, + { 0xF6, 8 } + }, + { /* DC bias table 4 */ + { 0x3, 4 }, + { 0x3C, 6 }, + { 0xF, 7 }, + { 0x7A, 7 }, + { 0x1D, 8 }, + { 0x20, 9 }, + { 0x72, 10 }, + { 0x6, 6 }, + { 0x399, 13 }, + { 0x4, 3 }, + { 0x5, 3 }, + { 0x5, 4 }, + { 0x6, 4 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0x0, 4 }, + { 0x19, 5 }, + { 0x2, 4 }, + { 0xD, 4 }, + { 0x7, 4 }, + { 0x1F, 5 }, + { 0x30, 6 }, + { 0x11, 8 }, + { 0x31, 6 }, + { 0x5, 6 }, + { 0x21, 9 }, + { 0xE7, 11 }, + { 0x38, 9 }, + { 0x1CD, 12 }, + { 0x398, 13 }, + { 0x7B, 7 }, + { 0x9, 7 } + }, + { /* DC bias table 5 */ + { 0x9, 4 }, + { 0x2, 5 }, + { 0x74, 7 }, + { 0x7, 6 }, + { 0xEC, 8 }, + { 0xD1, 9 }, + { 0x1A6, 10 }, + { 0x6, 6 }, + { 0xD21, 13 }, + { 0x5, 3 }, + { 0x6, 3 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0xF, 4 }, + { 0x4, 4 }, + { 0x0, 4 }, + { 0x1C, 5 }, + { 0x2, 4 }, + { 0x5, 4 }, + { 0x3, 4 }, + { 0xC, 5 }, + { 0x35, 7 }, + { 0x1A7, 10 }, + { 0x1B, 6 }, + { 0x77, 7 }, + { 0x1A5, 10 }, + { 0x349, 11 }, + { 0xD0, 9 }, + { 0x691, 12 }, + { 0xD20, 13 }, + { 0x75, 7 }, + { 0xED, 8 } + }, + { /* DC bias table 6 */ + { 0xA, 4 }, + { 0xC, 5 }, + { 0x12, 6 }, + { 0x1B, 6 }, + { 0xB7, 8 }, + { 0x16C, 9 }, + { 0x99, 9 }, + { 0x5A, 7 }, + { 0x16D8, 13 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x0, 3 }, + { 0x5, 4 }, + { 0x17, 5 }, + { 0xE, 5 }, + { 0x2, 4 }, + { 0x3, 4 }, + { 0xF, 5 }, + { 0x1A, 6 }, + { 0x4D, 8 }, + { 0x2DB3, 14 }, + { 0x2C, 6 }, + { 0x11, 6 }, + { 0x2DA, 10 }, + { 0x5B7, 11 }, + { 0x98, 9 }, + { 0xB6D, 12 }, + { 0x2DB2, 14 }, + { 0x10, 6 }, + { 0x27, 7 } + }, + { /* DC bias table 7 */ + { 0xD, 4 }, + { 0xF, 5 }, + { 0x1D, 6 }, + { 0x8, 5 }, + { 0x51, 7 }, + { 0x56, 8 }, + { 0xAF, 9 }, + { 0x2A, 7 }, + { 0x148A, 13 }, + { 0x7, 3 }, + { 0x0, 2 }, + { 0x8, 4 }, + { 0x9, 4 }, + { 0xC, 4 }, + { 0x6, 4 }, + { 0x17, 5 }, + { 0xB, 5 }, + { 0x16, 5 }, + { 0x15, 5 }, + { 0x9, 5 }, + { 0x50, 7 }, + { 0xAE, 9 }, + { 0x2917, 14 }, + { 0x1C, 6 }, + { 0x14, 6 }, + { 0x290, 10 }, + { 0x523, 11 }, + { 0x149, 9 }, + { 0xA44, 12 }, + { 0x2916, 14 }, + { 0x53, 7 }, + { 0xA5, 8 } + }, + { /* DC bias table 8 */ + { 0x1, 4 }, + { 0x1D, 6 }, + { 0xF5, 8 }, + { 0xF4, 8 }, + { 0x24D, 10 }, + { 0x499, 11 }, + { 0x498, 11 }, + { 0x1, 5 }, + { 0x21, 6 }, + { 0x6, 3 }, + { 0x5, 3 }, + { 0x6, 4 }, + { 0x5, 4 }, + { 0x2, 4 }, + { 0x7, 5 }, + { 0x25, 6 }, + { 0x7B, 7 }, + { 0x1C, 6 }, + { 0x20, 6 }, + { 0xD, 6 }, + { 0x48, 7 }, + { 0x92, 8 }, + { 0x127, 9 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0x11, 5 }, + { 0xC, 6 }, + { 0x3C, 6 }, + { 0xF, 5 }, + { 0x0, 5 }, + { 0x1F, 5 }, + { 0x13, 5 } + }, + { /* DC bias table 9 */ + { 0x5, 4 }, + { 0x3C, 6 }, + { 0x40, 7 }, + { 0xD, 7 }, + { 0x31, 9 }, + { 0x61, 10 }, + { 0x60, 10 }, + { 0x2, 5 }, + { 0xF5, 8 }, + { 0x6, 3 }, + { 0x5, 3 }, + { 0x7, 4 }, + { 0x6, 4 }, + { 0x2, 4 }, + { 0x9, 5 }, + { 0x25, 6 }, + { 0x7, 6 }, + { 0x21, 6 }, + { 0x24, 6 }, + { 0x10, 6 }, + { 0x41, 7 }, + { 0xF4, 8 }, + { 0x19, 8 }, + { 0xE, 4 }, + { 0x3, 4 }, + { 0x11, 5 }, + { 0x11, 6 }, + { 0x3F, 6 }, + { 0x3E, 6 }, + { 0x7B, 7 }, + { 0x0, 4 }, + { 0x13, 5 } + }, + { /* DC bias table 10 */ + { 0xA, 4 }, + { 0x7, 5 }, + { 0x1, 6 }, + { 0x9, 6 }, + { 0x131, 9 }, + { 0x261, 10 }, + { 0x260, 10 }, + { 0x15, 6 }, + { 0x1, 7 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0x6, 4 }, + { 0x12, 5 }, + { 0x2F, 6 }, + { 0x14, 6 }, + { 0x27, 6 }, + { 0x2D, 6 }, + { 0x16, 6 }, + { 0x4D, 7 }, + { 0x99, 8 }, + { 0x0, 7 }, + { 0x4, 4 }, + { 0x1, 4 }, + { 0x5, 5 }, + { 0x17, 6 }, + { 0x2E, 6 }, + { 0x2C, 6 }, + { 0x8, 6 }, + { 0x6, 5 }, + { 0x1, 5 } + }, + { /* DC bias table 11 */ + { 0x0, 3 }, + { 0xE, 5 }, + { 0x17, 6 }, + { 0x2A, 6 }, + { 0x10, 7 }, + { 0xF9, 10 }, + { 0xF8, 10 }, + { 0x1E, 7 }, + { 0x3F, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x6, 4 }, + { 0xF, 5 }, + { 0x5, 5 }, + { 0x16, 6 }, + { 0x29, 6 }, + { 0x2B, 6 }, + { 0x15, 6 }, + { 0x50, 7 }, + { 0x11, 7 }, + { 0x7D, 9 }, + { 0x4, 4 }, + { 0x17, 5 }, + { 0x6, 5 }, + { 0x14, 6 }, + { 0x2C, 6 }, + { 0x2D, 6 }, + { 0xE, 6 }, + { 0x9, 6 }, + { 0x51, 7 } + }, + { /* DC bias table 12 */ + { 0x2, 3 }, + { 0x18, 5 }, + { 0x2F, 6 }, + { 0xD, 5 }, + { 0x53, 7 }, + { 0x295, 10 }, + { 0x294, 10 }, + { 0xA4, 8 }, + { 0x7C, 8 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x1B, 5 }, + { 0xC, 5 }, + { 0x28, 6 }, + { 0x6A, 7 }, + { 0x1E, 6 }, + { 0x1D, 6 }, + { 0x69, 7 }, + { 0xD7, 8 }, + { 0x7D, 8 }, + { 0x14B, 9 }, + { 0x19, 5 }, + { 0x16, 5 }, + { 0x2E, 6 }, + { 0x1C, 6 }, + { 0x2B, 6 }, + { 0x2A, 6 }, + { 0x68, 7 }, + { 0x3F, 7 }, + { 0xD6, 8 } + }, + { /* DC bias table 13 */ + { 0x2, 3 }, + { 0x1B, 5 }, + { 0xC, 5 }, + { 0x18, 5 }, + { 0x29, 6 }, + { 0x7F, 8 }, + { 0x2F0, 10 }, + { 0x198, 9 }, + { 0x179, 9 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x1A, 5 }, + { 0xD, 5 }, + { 0x2A, 6 }, + { 0x64, 7 }, + { 0x1E, 6 }, + { 0x67, 7 }, + { 0x5F, 7 }, + { 0xCD, 8 }, + { 0x7E, 8 }, + { 0x2F1, 10 }, + { 0x16, 5 }, + { 0xE, 5 }, + { 0x2E, 6 }, + { 0x65, 7 }, + { 0x2B, 6 }, + { 0x28, 6 }, + { 0x3E, 7 }, + { 0xBD, 8 }, + { 0x199, 9 } + }, + { /* DC bias table 14 */ + { 0x2, 3 }, + { 0x7, 4 }, + { 0x16, 5 }, + { 0x6, 4 }, + { 0x36, 6 }, + { 0x5C, 7 }, + { 0x15D, 9 }, + { 0x15C, 9 }, + { 0x2BF, 10 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x18, 5 }, + { 0x34, 6 }, + { 0x2A, 6 }, + { 0x5E, 7 }, + { 0x6A, 7 }, + { 0x64, 7 }, + { 0x5D, 7 }, + { 0xCB, 8 }, + { 0xAD, 8 }, + { 0x2BE, 10 }, + { 0x14, 5 }, + { 0x33, 6 }, + { 0x6E, 7 }, + { 0x5F, 7 }, + { 0x6F, 7 }, + { 0x6B, 7 }, + { 0xCA, 8 }, + { 0xAC, 8 }, + { 0x15E, 9 } + }, + { /* DC bias table 15 */ + { 0xF, 4 }, + { 0x1D, 5 }, + { 0x18, 5 }, + { 0xB, 4 }, + { 0x19, 5 }, + { 0x29, 6 }, + { 0xD6, 8 }, + { 0x551, 11 }, + { 0xAA1, 12 }, + { 0x1, 2 }, + { 0x0, 2 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x1B, 5 }, + { 0x38, 6 }, + { 0x28, 6 }, + { 0x57, 7 }, + { 0x6A, 7 }, + { 0x68, 7 }, + { 0x56, 7 }, + { 0xE5, 8 }, + { 0x155, 9 }, + { 0xAA0, 12 }, + { 0x73, 7 }, + { 0x69, 7 }, + { 0xD7, 8 }, + { 0xAB, 8 }, + { 0xE4, 8 }, + { 0xA9, 8 }, + { 0x151, 9 }, + { 0x150, 9 }, + { 0x2A9, 10 } + } +}; + +static const uint16_t ac_bias_0[16][32][2] = { + { /* AC bias group 1, table 0 */ + { 0x8, 5 }, + { 0x25, 7 }, + { 0x17A, 9 }, + { 0x2F7, 10 }, + { 0xBDB, 12 }, + { 0x17B4, 13 }, + { 0x2F6B, 14 }, + { 0x1D, 5 }, + { 0x2F6A, 14 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0x1, 4 }, + { 0x2, 4 }, + { 0xA, 4 }, + { 0x6, 4 }, + { 0x0, 4 }, + { 0x1C, 5 }, + { 0x9, 4 }, + { 0xD, 4 }, + { 0xF, 4 }, + { 0xC, 4 }, + { 0x3, 4 }, + { 0xA, 5 }, + { 0x16, 5 }, + { 0x13, 6 }, + { 0x5D, 7 }, + { 0x24, 7 }, + { 0xBC, 8 }, + { 0x5C, 7 }, + { 0x5EC, 11 }, + { 0xB, 5 }, + { 0x5F, 7 } + }, + { /* AC bias group 1, table 1 */ + { 0xF, 5 }, + { 0x10, 6 }, + { 0x4B, 8 }, + { 0xC6, 8 }, + { 0x31D, 10 }, + { 0xC71, 12 }, + { 0xC70, 12 }, + { 0x1, 4 }, + { 0xC73, 12 }, + { 0x8, 4 }, + { 0x9, 4 }, + { 0x2, 4 }, + { 0x3, 4 }, + { 0xB, 4 }, + { 0x6, 4 }, + { 0x0, 4 }, + { 0x1C, 5 }, + { 0x5, 4 }, + { 0xD, 4 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0x19, 5 }, + { 0x13, 6 }, + { 0x1D, 5 }, + { 0x30, 6 }, + { 0x62, 7 }, + { 0x24, 7 }, + { 0x4A, 8 }, + { 0x18F, 9 }, + { 0xC72, 12 }, + { 0xE, 5 }, + { 0x11, 6 } + }, + { /* AC bias group 1, table 2 */ + { 0x1B, 5 }, + { 0x3, 6 }, + { 0x8D, 8 }, + { 0x40, 7 }, + { 0x239, 10 }, + { 0x471, 11 }, + { 0x8E0, 12 }, + { 0x3, 4 }, + { 0x11C3, 13 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0x4, 4 }, + { 0x5, 4 }, + { 0xE, 4 }, + { 0x7, 4 }, + { 0x1, 4 }, + { 0x1E, 5 }, + { 0x6, 4 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x2, 4 }, + { 0x0, 5 }, + { 0x41, 7 }, + { 0x1F, 5 }, + { 0x22, 6 }, + { 0x2, 6 }, + { 0x8F, 8 }, + { 0x8C, 8 }, + { 0x11D, 9 }, + { 0x11C2, 13 }, + { 0x1A, 5 }, + { 0x21, 6 } + }, + { /* AC bias group 1, table 3 */ + { 0x1F, 5 }, + { 0x3, 6 }, + { 0x3, 7 }, + { 0x43, 7 }, + { 0xB, 9 }, + { 0x15, 10 }, + { 0x51, 12 }, + { 0x3, 4 }, + { 0x50, 12 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x4, 4 }, + { 0x6, 4 }, + { 0xE, 4 }, + { 0xA, 4 }, + { 0x1, 4 }, + { 0x1E, 5 }, + { 0x5, 4 }, + { 0x9, 4 }, + { 0x7, 4 }, + { 0x11, 5 }, + { 0x2, 6 }, + { 0x4, 8 }, + { 0x2, 4 }, + { 0x2D, 6 }, + { 0x20, 6 }, + { 0x42, 7 }, + { 0x1, 7 }, + { 0x0, 7 }, + { 0x29, 11 }, + { 0x17, 5 }, + { 0x2C, 6 } + }, + { /* AC bias group 1, table 4 */ + { 0x3, 4 }, + { 0x1F, 6 }, + { 0x3A, 7 }, + { 0x5D, 7 }, + { 0x173, 9 }, + { 0x2E4, 10 }, + { 0x172D, 13 }, + { 0x4, 4 }, + { 0x172C, 13 }, + { 0xF, 4 }, + { 0xE, 4 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0xC, 4 }, + { 0xA, 4 }, + { 0x1, 4 }, + { 0x16, 5 }, + { 0x2, 4 }, + { 0x5, 4 }, + { 0x1A, 5 }, + { 0x2F, 6 }, + { 0x38, 7 }, + { 0x5CA, 11 }, + { 0x6, 4 }, + { 0x37, 6 }, + { 0x1E, 6 }, + { 0x3B, 7 }, + { 0x39, 7 }, + { 0xB8, 8 }, + { 0xB97, 12 }, + { 0x0, 4 }, + { 0x36, 6 } + }, + { /* AC bias group 1, table 5 */ + { 0x6, 4 }, + { 0x37, 6 }, + { 0x5D, 7 }, + { 0xC, 6 }, + { 0xB9, 8 }, + { 0x2E3, 10 }, + { 0x5C4, 11 }, + { 0x4, 4 }, + { 0x1715, 13 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0x8, 4 }, + { 0x7, 4 }, + { 0xC, 4 }, + { 0x9, 4 }, + { 0x1D, 5 }, + { 0x16, 5 }, + { 0x1C, 5 }, + { 0x1A, 5 }, + { 0xB, 5 }, + { 0x5E, 7 }, + { 0x170, 9 }, + { 0x1714, 13 }, + { 0xA, 4 }, + { 0xA, 5 }, + { 0x36, 6 }, + { 0x5F, 7 }, + { 0x1B, 7 }, + { 0x1A, 7 }, + { 0xB8B, 12 }, + { 0x2, 4 }, + { 0x7, 5 } + }, + { /* AC bias group 1, table 6 */ + { 0xC, 4 }, + { 0xB, 5 }, + { 0x79, 7 }, + { 0x22, 6 }, + { 0xF0, 8 }, + { 0x119, 9 }, + { 0x230, 10 }, + { 0x1D, 5 }, + { 0x8C4, 12 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0xB, 4 }, + { 0x7, 4 }, + { 0x1C, 5 }, + { 0x3D, 6 }, + { 0xD, 5 }, + { 0x8, 5 }, + { 0x15, 6 }, + { 0x8D, 8 }, + { 0x118B, 13 }, + { 0x118A, 13 }, + { 0xD, 4 }, + { 0x10, 5 }, + { 0x9, 5 }, + { 0x14, 6 }, + { 0x47, 7 }, + { 0xF1, 8 }, + { 0x463, 11 }, + { 0x1F, 5 }, + { 0xC, 5 } + }, + { /* AC bias group 1, table 7 */ + { 0x0, 3 }, + { 0x1A, 5 }, + { 0x33, 6 }, + { 0xC, 5 }, + { 0x46, 7 }, + { 0x1E3, 9 }, + { 0x3C5, 10 }, + { 0x17, 5 }, + { 0x1E21, 13 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x9, 4 }, + { 0xA, 4 }, + { 0x7, 4 }, + { 0x1B, 5 }, + { 0x3D, 6 }, + { 0x1B, 6 }, + { 0x22, 6 }, + { 0x79, 7 }, + { 0xF0, 8 }, + { 0x1E20, 13 }, + { 0x1E23, 13 }, + { 0x1E22, 13 }, + { 0xE, 4 }, + { 0x16, 5 }, + { 0x18, 5 }, + { 0x32, 6 }, + { 0x1A, 6 }, + { 0x47, 7 }, + { 0x789, 11 }, + { 0x1F, 5 }, + { 0x10, 5 } + }, + { /* AC bias group 1, table 8 */ + { 0x1D, 5 }, + { 0x61, 7 }, + { 0x4E, 8 }, + { 0x9E, 9 }, + { 0x27C, 11 }, + { 0x9F5, 13 }, + { 0x9F4, 13 }, + { 0x3, 4 }, + { 0x60, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0x5, 4 }, + { 0xD, 5 }, + { 0x31, 6 }, + { 0x8, 5 }, + { 0x38, 6 }, + { 0x12, 6 }, + { 0x26, 7 }, + { 0x13F, 10 }, + { 0x4FB, 12 }, + { 0xD, 4 }, + { 0x2, 4 }, + { 0xC, 5 }, + { 0x39, 6 }, + { 0x1C, 6 }, + { 0xF, 5 }, + { 0x1D, 6 }, + { 0x8, 4 }, + { 0x19, 5 } + }, + { /* AC bias group 1, table 9 */ + { 0x7, 4 }, + { 0x19, 6 }, + { 0xAB, 8 }, + { 0xAA, 8 }, + { 0x119, 10 }, + { 0x461, 12 }, + { 0x460, 12 }, + { 0x1B, 5 }, + { 0x47, 8 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x9, 4 }, + { 0x5, 4 }, + { 0xD, 5 }, + { 0x35, 6 }, + { 0x3D, 6 }, + { 0x3C, 6 }, + { 0x18, 6 }, + { 0x22, 7 }, + { 0x8D, 9 }, + { 0x231, 11 }, + { 0xE, 4 }, + { 0x1F, 5 }, + { 0x9, 5 }, + { 0x2B, 6 }, + { 0x10, 6 }, + { 0x34, 6 }, + { 0x54, 7 }, + { 0x8, 4 }, + { 0x14, 5 } + }, + { /* AC bias group 1, table 10 */ + { 0xC, 4 }, + { 0x5, 5 }, + { 0x8, 6 }, + { 0x5B, 7 }, + { 0x4D, 9 }, + { 0x131, 11 }, + { 0x261, 12 }, + { 0x1A, 5 }, + { 0x12, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0x9, 4 }, + { 0x6, 4 }, + { 0x1B, 5 }, + { 0x6, 5 }, + { 0x1C, 6 }, + { 0x2C, 6 }, + { 0x15, 6 }, + { 0x5A, 7 }, + { 0x27, 8 }, + { 0x99, 10 }, + { 0x260, 12 }, + { 0xE, 4 }, + { 0x4, 4 }, + { 0xF, 5 }, + { 0x7, 5 }, + { 0x1D, 6 }, + { 0xB, 5 }, + { 0x14, 6 }, + { 0x8, 4 }, + { 0x17, 5 } + }, + { /* AC bias group 1, table 11 */ + { 0xF, 4 }, + { 0x13, 5 }, + { 0x75, 7 }, + { 0x24, 6 }, + { 0x95, 8 }, + { 0x251, 10 }, + { 0x4A0, 11 }, + { 0x10, 5 }, + { 0xC8, 8 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x1, 4 }, + { 0x0, 4 }, + { 0x1A, 5 }, + { 0x11, 5 }, + { 0x2C, 6 }, + { 0x65, 7 }, + { 0x74, 7 }, + { 0x4B, 7 }, + { 0xC9, 8 }, + { 0x129, 9 }, + { 0x943, 12 }, + { 0x942, 12 }, + { 0x3, 3 }, + { 0xA, 4 }, + { 0x1C, 5 }, + { 0x18, 5 }, + { 0x33, 6 }, + { 0x17, 5 }, + { 0x2D, 6 }, + { 0x1B, 5 }, + { 0x3B, 6 } + }, + { /* AC bias group 1, table 12 */ + { 0x3, 3 }, + { 0x1A, 5 }, + { 0x2D, 6 }, + { 0x38, 6 }, + { 0x28, 7 }, + { 0x395, 10 }, + { 0xE51, 12 }, + { 0x37, 6 }, + { 0xE4, 8 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x1F, 5 }, + { 0x1E, 5 }, + { 0x17, 5 }, + { 0x3A, 6 }, + { 0x73, 7 }, + { 0x2A, 7 }, + { 0x2B, 7 }, + { 0x29, 7 }, + { 0x1CB, 9 }, + { 0x729, 11 }, + { 0x1CA1, 13 }, + { 0x1CA0, 13 }, + { 0x4, 3 }, + { 0xA, 4 }, + { 0x4, 4 }, + { 0x18, 5 }, + { 0x36, 6 }, + { 0xB, 5 }, + { 0x2C, 6 }, + { 0x19, 5 }, + { 0x3B, 6 } + }, + { /* AC bias group 1, table 13 */ + { 0x4, 3 }, + { 0x4, 4 }, + { 0x3F, 6 }, + { 0x17, 5 }, + { 0x75, 7 }, + { 0x1F5, 9 }, + { 0x7D1, 11 }, + { 0x17, 6 }, + { 0x1F6, 9 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x1B, 5 }, + { 0x1A, 5 }, + { 0xA, 5 }, + { 0x32, 6 }, + { 0x74, 7 }, + { 0xF8, 8 }, + { 0xF9, 8 }, + { 0x1F7, 9 }, + { 0x3E9, 10 }, + { 0xFA0, 12 }, + { 0x1F43, 13 }, + { 0x1F42, 13 }, + { 0x3, 3 }, + { 0xA, 4 }, + { 0x1E, 5 }, + { 0x1C, 5 }, + { 0x3B, 6 }, + { 0x18, 5 }, + { 0x16, 6 }, + { 0x16, 5 }, + { 0x33, 6 } + }, + { /* AC bias group 1, table 14 */ + { 0x4, 3 }, + { 0x7, 4 }, + { 0x18, 5 }, + { 0x1E, 5 }, + { 0x36, 6 }, + { 0x31, 7 }, + { 0x177, 9 }, + { 0x77, 7 }, + { 0x176, 9 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0x1A, 5 }, + { 0x19, 5 }, + { 0x3A, 6 }, + { 0x19, 6 }, + { 0x5C, 7 }, + { 0xBA, 8 }, + { 0x61, 8 }, + { 0xC1, 9 }, + { 0x180, 10 }, + { 0x302, 11 }, + { 0x607, 12 }, + { 0x606, 12 }, + { 0x2, 3 }, + { 0xA, 4 }, + { 0x1F, 5 }, + { 0x1C, 5 }, + { 0x37, 6 }, + { 0x16, 5 }, + { 0x76, 7 }, + { 0xD, 5 }, + { 0x2F, 6 } + }, + { /* AC bias group 1, table 15 */ + { 0x0, 3 }, + { 0xA, 4 }, + { 0x1A, 5 }, + { 0xC, 4 }, + { 0x1D, 5 }, + { 0x39, 6 }, + { 0x78, 7 }, + { 0x5E, 7 }, + { 0x393, 11 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x16, 5 }, + { 0xF, 5 }, + { 0x2E, 6 }, + { 0x5F, 7 }, + { 0x73, 8 }, + { 0xE5, 9 }, + { 0x1C8, 10 }, + { 0xE4A, 13 }, + { 0x1C97, 14 }, + { 0x1C96, 14 }, + { 0xE49, 13 }, + { 0xE48, 13 }, + { 0x4, 3 }, + { 0x6, 4 }, + { 0x1F, 5 }, + { 0x1B, 5 }, + { 0x1D, 6 }, + { 0x38, 6 }, + { 0x38, 7 }, + { 0x3D, 6 }, + { 0x79, 7 } + } +}; + +static const uint16_t ac_bias_1[16][32][2] = { + { /* AC bias group 2, table 0 */ + { 0xB, 5 }, + { 0x2B, 7 }, + { 0x54, 8 }, + { 0x1B7, 9 }, + { 0x6D9, 11 }, + { 0xDB1, 12 }, + { 0xDB0, 12 }, + { 0x2, 4 }, + { 0xAB, 9 }, + { 0x9, 4 }, + { 0xA, 4 }, + { 0x7, 4 }, + { 0x8, 4 }, + { 0xF, 4 }, + { 0xC, 4 }, + { 0x3, 4 }, + { 0x1D, 5 }, + { 0x4, 4 }, + { 0xB, 4 }, + { 0x6, 4 }, + { 0x1A, 5 }, + { 0x3, 6 }, + { 0xAA, 9 }, + { 0x1, 4 }, + { 0x0, 5 }, + { 0x14, 6 }, + { 0x6C, 7 }, + { 0xDA, 8 }, + { 0x2, 6 }, + { 0x36D, 10 }, + { 0x1C, 5 }, + { 0x37, 6 } + }, + { /* AC bias group 2, table 1 */ + { 0x1D, 5 }, + { 0x4, 6 }, + { 0xB6, 8 }, + { 0x6A, 8 }, + { 0x5B9, 11 }, + { 0x16E1, 13 }, + { 0x16E0, 13 }, + { 0x7, 4 }, + { 0x16F, 9 }, + { 0xC, 4 }, + { 0xD, 4 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0x3, 4 }, + { 0x17, 5 }, + { 0x2, 4 }, + { 0x4, 4 }, + { 0x1C, 5 }, + { 0x2C, 6 }, + { 0x6B, 8 }, + { 0xB71, 12 }, + { 0x5, 4 }, + { 0x3, 5 }, + { 0x1B, 6 }, + { 0x5A, 7 }, + { 0x34, 7 }, + { 0x5, 6 }, + { 0x2DD, 10 }, + { 0x0, 4 }, + { 0xC, 5 } + }, + { /* AC bias group 2, table 2 */ + { 0x3, 4 }, + { 0x7F, 7 }, + { 0xA1, 8 }, + { 0xA0, 8 }, + { 0x20C, 10 }, + { 0x834, 12 }, + { 0x106B, 13 }, + { 0x7, 4 }, + { 0x82, 8 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x2, 4 }, + { 0x11, 5 }, + { 0x1E, 5 }, + { 0x15, 5 }, + { 0x3E, 6 }, + { 0x40, 7 }, + { 0x41B, 11 }, + { 0x106A, 13 }, + { 0x6, 4 }, + { 0xA, 5 }, + { 0x29, 6 }, + { 0x7E, 7 }, + { 0x51, 7 }, + { 0x21, 6 }, + { 0x107, 9 }, + { 0x4, 4 }, + { 0xB, 5 } + }, + { /* AC bias group 2, table 3 */ + { 0x7, 4 }, + { 0x1B, 6 }, + { 0xF6, 8 }, + { 0xE9, 8 }, + { 0x3A1, 10 }, + { 0x740, 11 }, + { 0xE82, 12 }, + { 0x1F, 5 }, + { 0x1EF, 9 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0xD, 4 }, + { 0x8, 4 }, + { 0x1C, 5 }, + { 0x3, 5 }, + { 0x12, 5 }, + { 0x2, 5 }, + { 0x75, 7 }, + { 0x1D1, 9 }, + { 0x1D07, 13 }, + { 0x1D06, 13 }, + { 0xA, 4 }, + { 0x13, 5 }, + { 0x3B, 6 }, + { 0x1A, 6 }, + { 0x7A, 7 }, + { 0x3C, 6 }, + { 0x1EE, 9 }, + { 0x0, 4 }, + { 0xC, 5 } + }, + { /* AC bias group 2, table 4 */ + { 0xD, 4 }, + { 0x3D, 6 }, + { 0x42, 7 }, + { 0x37, 7 }, + { 0xD9, 9 }, + { 0x362, 11 }, + { 0x6C6, 12 }, + { 0x1F, 5 }, + { 0x86, 8 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0x1, 4 }, + { 0xF, 5 }, + { 0x25, 6 }, + { 0x3C, 6 }, + { 0x1A, 6 }, + { 0x87, 8 }, + { 0x1B0, 10 }, + { 0xD8F, 13 }, + { 0xD8E, 13 }, + { 0xE, 4 }, + { 0x13, 5 }, + { 0xC, 5 }, + { 0x24, 6 }, + { 0x20, 6 }, + { 0x11, 5 }, + { 0x6D, 8 }, + { 0x0, 4 }, + { 0xE, 5 } + }, + { /* AC bias group 2, table 5 */ + { 0x0, 3 }, + { 0x12, 5 }, + { 0x76, 7 }, + { 0x77, 7 }, + { 0x14D, 9 }, + { 0x533, 11 }, + { 0x14C9, 13 }, + { 0x13, 5 }, + { 0xA5, 8 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x8, 4 }, + { 0x1A, 5 }, + { 0x2B, 6 }, + { 0x75, 7 }, + { 0x74, 7 }, + { 0xA7, 8 }, + { 0x298, 10 }, + { 0x14C8, 13 }, + { 0x14CB, 13 }, + { 0x14CA, 13 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0x7, 5 }, + { 0x2A, 6 }, + { 0x28, 6 }, + { 0x1B, 5 }, + { 0xA4, 8 }, + { 0x2, 4 }, + { 0x6, 5 } + }, + { /* AC bias group 2, table 6 */ + { 0x2, 3 }, + { 0x1A, 5 }, + { 0x2B, 6 }, + { 0x3A, 6 }, + { 0xED, 8 }, + { 0x283, 10 }, + { 0xA0A, 12 }, + { 0x4, 5 }, + { 0xA1, 8 }, + { 0x4, 3 }, + { 0x3, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x1F, 5 }, + { 0x6, 5 }, + { 0x77, 7 }, + { 0xA3, 8 }, + { 0xA2, 8 }, + { 0x140, 9 }, + { 0x1417, 13 }, + { 0x1416, 13 }, + { 0xA09, 12 }, + { 0xA08, 12 }, + { 0x0, 3 }, + { 0x1E, 5 }, + { 0x7, 5 }, + { 0x2A, 6 }, + { 0x29, 6 }, + { 0x1C, 5 }, + { 0xEC, 8 }, + { 0x1B, 5 }, + { 0x5, 5 } + }, + { /* AC bias group 2, table 7 */ + { 0x2, 3 }, + { 0x2, 4 }, + { 0x18, 5 }, + { 0x1D, 5 }, + { 0x35, 6 }, + { 0xE4, 8 }, + { 0x1CF, 11 }, + { 0x1D, 7 }, + { 0x72, 9 }, + { 0x4, 3 }, + { 0x5, 3 }, + { 0x6, 4 }, + { 0x7, 4 }, + { 0x6, 5 }, + { 0x73, 7 }, + { 0x38, 8 }, + { 0x1CE, 11 }, + { 0x39B, 12 }, + { 0x398, 12 }, + { 0x733, 13 }, + { 0x732, 13 }, + { 0x735, 13 }, + { 0x734, 13 }, + { 0x0, 3 }, + { 0x1F, 5 }, + { 0x1B, 5 }, + { 0x34, 6 }, + { 0xF, 6 }, + { 0x1E, 5 }, + { 0xE5, 8 }, + { 0x19, 5 }, + { 0x38, 6 } + }, + { /* AC bias group 2, table 8 */ + { 0x16, 5 }, + { 0x50, 7 }, + { 0x172, 9 }, + { 0x2E7, 10 }, + { 0x1732, 13 }, + { 0x2E67, 14 }, + { 0x2E66, 14 }, + { 0x6, 4 }, + { 0x51, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x9, 4 }, + { 0x1C, 5 }, + { 0x9, 5 }, + { 0x1C, 6 }, + { 0x1D, 6 }, + { 0x5D, 7 }, + { 0xB8, 8 }, + { 0x5CD, 11 }, + { 0x1731, 13 }, + { 0x1730, 13 }, + { 0xF, 4 }, + { 0x5, 4 }, + { 0xF, 5 }, + { 0x8, 5 }, + { 0x29, 6 }, + { 0x1D, 5 }, + { 0x2F, 6 }, + { 0x8, 4 }, + { 0x15, 5 } + }, + { /* AC bias group 2, table 9 */ + { 0x9, 4 }, + { 0x21, 6 }, + { 0x40, 7 }, + { 0xAD, 8 }, + { 0x2B0, 10 }, + { 0x1589, 13 }, + { 0x1588, 13 }, + { 0x1C, 5 }, + { 0x5F, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x6, 4 }, + { 0x11, 5 }, + { 0x2A, 6 }, + { 0x57, 7 }, + { 0x5E, 7 }, + { 0x41, 7 }, + { 0x159, 9 }, + { 0x563, 11 }, + { 0x158B, 13 }, + { 0x158A, 13 }, + { 0x1, 3 }, + { 0x5, 4 }, + { 0x14, 5 }, + { 0x3B, 6 }, + { 0x2E, 6 }, + { 0x4, 4 }, + { 0x3A, 6 }, + { 0x7, 4 }, + { 0x16, 5 } + }, + { /* AC bias group 2, table 10 */ + { 0xE, 4 }, + { 0x7, 5 }, + { 0x46, 7 }, + { 0x45, 7 }, + { 0x64, 9 }, + { 0x32A, 12 }, + { 0x657, 13 }, + { 0x18, 5 }, + { 0xD, 6 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xA, 4 }, + { 0xB, 4 }, + { 0x1A, 5 }, + { 0x36, 6 }, + { 0x47, 7 }, + { 0x44, 7 }, + { 0x18, 7 }, + { 0x33, 8 }, + { 0xCB, 10 }, + { 0x656, 13 }, + { 0x329, 12 }, + { 0x328, 12 }, + { 0x2, 3 }, + { 0x6, 4 }, + { 0x19, 5 }, + { 0xE, 5 }, + { 0x37, 6 }, + { 0x9, 4 }, + { 0xF, 5 }, + { 0x2, 4 }, + { 0x10, 5 } + }, + { /* AC bias group 2, table 11 */ + { 0x3, 3 }, + { 0x18, 5 }, + { 0x23, 6 }, + { 0x77, 7 }, + { 0x194, 9 }, + { 0x1956, 13 }, + { 0x32AF, 14 }, + { 0x3A, 6 }, + { 0x76, 7 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x1F, 5 }, + { 0x1E, 5 }, + { 0x14, 5 }, + { 0x22, 6 }, + { 0x64, 7 }, + { 0x197, 9 }, + { 0x196, 9 }, + { 0x32B, 10 }, + { 0x654, 11 }, + { 0x32AE, 14 }, + { 0x1955, 13 }, + { 0x1954, 13 }, + { 0x0, 3 }, + { 0x9, 4 }, + { 0x1C, 5 }, + { 0x15, 5 }, + { 0x10, 5 }, + { 0xD, 4 }, + { 0x17, 5 }, + { 0x16, 5 }, + { 0x33, 6 } + }, + { /* AC bias group 2, table 12 */ + { 0x5, 3 }, + { 0x6, 4 }, + { 0x3E, 6 }, + { 0x10, 5 }, + { 0x48, 7 }, + { 0x93F, 12 }, + { 0x24FA, 14 }, + { 0x32, 6 }, + { 0x67, 7 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x1B, 5 }, + { 0x1E, 5 }, + { 0x34, 6 }, + { 0x66, 7 }, + { 0x92, 8 }, + { 0x126, 9 }, + { 0x24E, 10 }, + { 0x49E, 11 }, + { 0x49F7, 15 }, + { 0x49F6, 15 }, + { 0x24F9, 14 }, + { 0x24F8, 14 }, + { 0x0, 3 }, + { 0x7, 4 }, + { 0x18, 5 }, + { 0x11, 5 }, + { 0x3F, 6 }, + { 0xE, 4 }, + { 0x13, 5 }, + { 0x35, 6 }, + { 0x25, 6 } + }, + { /* AC bias group 2, table 13 */ + { 0x5, 3 }, + { 0x8, 4 }, + { 0x12, 5 }, + { 0x1C, 5 }, + { 0x1C, 6 }, + { 0xEA, 9 }, + { 0x1D75, 14 }, + { 0x1E, 6 }, + { 0x66, 7 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0x1B, 5 }, + { 0x1A, 5 }, + { 0x1F, 6 }, + { 0x3B, 7 }, + { 0x74, 8 }, + { 0x1D6, 10 }, + { 0x3AF, 11 }, + { 0x1D74, 14 }, + { 0x1D77, 14 }, + { 0x1D76, 14 }, + { 0xEB9, 13 }, + { 0xEB8, 13 }, + { 0xF, 4 }, + { 0x6, 4 }, + { 0x13, 5 }, + { 0x3B, 6 }, + { 0x3A, 6 }, + { 0x0, 3 }, + { 0x18, 5 }, + { 0x32, 6 }, + { 0x67, 7 } + }, + { /* AC bias group 2, table 14 */ + { 0x4, 3 }, + { 0xA, 4 }, + { 0x1B, 5 }, + { 0xC, 4 }, + { 0xD, 5 }, + { 0xE6, 8 }, + { 0x684, 11 }, + { 0x72, 7 }, + { 0xE7, 8 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x17, 5 }, + { 0x16, 5 }, + { 0x18, 6 }, + { 0xD1, 8 }, + { 0x1A0, 9 }, + { 0x686, 11 }, + { 0xD0F, 12 }, + { 0xD0A, 12 }, + { 0x1A17, 13 }, + { 0x1A16, 13 }, + { 0x1A1D, 13 }, + { 0x1A1C, 13 }, + { 0xF, 4 }, + { 0x1D, 5 }, + { 0xE, 5 }, + { 0x35, 6 }, + { 0x38, 6 }, + { 0x0, 3 }, + { 0xF, 5 }, + { 0x19, 6 }, + { 0x69, 7 } + }, + { /* AC bias group 2, table 15 */ + { 0x3, 3 }, + { 0xC, 4 }, + { 0x1B, 5 }, + { 0x0, 3 }, + { 0x3, 4 }, + { 0x2E, 6 }, + { 0x51, 9 }, + { 0xBC, 8 }, + { 0x53, 9 }, + { 0x4, 3 }, + { 0x2, 3 }, + { 0x16, 5 }, + { 0x15, 5 }, + { 0x15, 7 }, + { 0x50, 9 }, + { 0xA4, 10 }, + { 0x294, 12 }, + { 0x52B, 13 }, + { 0x52A, 13 }, + { 0x52D, 13 }, + { 0x52C, 13 }, + { 0x52F, 13 }, + { 0x52E, 13 }, + { 0xE, 4 }, + { 0x1A, 5 }, + { 0x4, 5 }, + { 0x28, 6 }, + { 0x29, 6 }, + { 0xF, 4 }, + { 0xB, 6 }, + { 0x5F, 7 }, + { 0xBD, 8 } + } +}; + +static const uint16_t ac_bias_2[16][32][2] = { + { /* AC bias group 3, table 0 */ + { 0x3, 4 }, + { 0x9, 6 }, + { 0xD0, 8 }, + { 0x1A3, 9 }, + { 0x344, 10 }, + { 0xD14, 12 }, + { 0x1A2B, 13 }, + { 0x4, 4 }, + { 0x15, 7 }, + { 0x0, 3 }, + { 0xF, 4 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0xE, 4 }, + { 0x9, 4 }, + { 0x1B, 5 }, + { 0xA, 5 }, + { 0x14, 5 }, + { 0xD, 5 }, + { 0x2A, 6 }, + { 0x14, 7 }, + { 0x68B, 11 }, + { 0x1A2A, 13 }, + { 0x8, 4 }, + { 0xB, 5 }, + { 0x2B, 6 }, + { 0xB, 6 }, + { 0x69, 7 }, + { 0x35, 6 }, + { 0x8, 6 }, + { 0x7, 4 }, + { 0xC, 5 } + }, + { /* AC bias group 3, table 1 */ + { 0xA, 4 }, + { 0x3C, 6 }, + { 0x32, 7 }, + { 0x30, 7 }, + { 0xC5, 9 }, + { 0x621, 12 }, + { 0x620, 12 }, + { 0x1F, 5 }, + { 0x33, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x4, 4 }, + { 0xD, 5 }, + { 0x26, 6 }, + { 0x27, 6 }, + { 0x14, 6 }, + { 0x63, 8 }, + { 0x189, 10 }, + { 0x623, 12 }, + { 0x622, 12 }, + { 0xB, 4 }, + { 0x12, 5 }, + { 0x3D, 6 }, + { 0x22, 6 }, + { 0x15, 6 }, + { 0xB, 5 }, + { 0x23, 6 }, + { 0x7, 4 }, + { 0x10, 5 } + }, + { /* AC bias group 3, table 2 */ + { 0xF, 4 }, + { 0xC, 5 }, + { 0x43, 7 }, + { 0x10, 6 }, + { 0x44, 8 }, + { 0x114, 10 }, + { 0x455, 12 }, + { 0x18, 5 }, + { 0x23, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0x9, 4 }, + { 0x19, 5 }, + { 0x9, 5 }, + { 0x17, 6 }, + { 0x16, 6 }, + { 0x42, 7 }, + { 0x8B, 9 }, + { 0x454, 12 }, + { 0x457, 12 }, + { 0x456, 12 }, + { 0xB, 4 }, + { 0x15, 5 }, + { 0xA, 5 }, + { 0x29, 6 }, + { 0x20, 6 }, + { 0xD, 5 }, + { 0x28, 6 }, + { 0x7, 4 }, + { 0x11, 5 } + }, + { /* AC bias group 3, table 3 */ + { 0x1, 3 }, + { 0x1A, 5 }, + { 0x29, 6 }, + { 0x2A, 6 }, + { 0xA0, 8 }, + { 0x285, 10 }, + { 0x1425, 13 }, + { 0x2, 5 }, + { 0x0, 7 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x8, 4 }, + { 0x12, 5 }, + { 0x1, 6 }, + { 0x51, 7 }, + { 0x1, 7 }, + { 0x143, 9 }, + { 0x508, 11 }, + { 0x1424, 13 }, + { 0x1427, 13 }, + { 0x1426, 13 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0x3, 5 }, + { 0x37, 6 }, + { 0x2B, 6 }, + { 0x13, 5 }, + { 0x36, 6 }, + { 0x1D, 5 }, + { 0x1, 5 } + }, + { /* AC bias group 3, table 4 */ + { 0x4, 3 }, + { 0x1F, 5 }, + { 0x3D, 6 }, + { 0x6, 5 }, + { 0x16, 7 }, + { 0x53, 9 }, + { 0x14A, 11 }, + { 0x34, 6 }, + { 0x2A, 8 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xB, 4 }, + { 0xC, 4 }, + { 0x1C, 5 }, + { 0x37, 6 }, + { 0x17, 7 }, + { 0x2B, 8 }, + { 0x28, 8 }, + { 0xA4, 10 }, + { 0x52D, 13 }, + { 0x52C, 13 }, + { 0x52F, 13 }, + { 0x52E, 13 }, + { 0x0, 3 }, + { 0x1D, 5 }, + { 0x7, 5 }, + { 0x4, 5 }, + { 0x35, 6 }, + { 0x14, 5 }, + { 0x36, 6 }, + { 0x15, 5 }, + { 0x3C, 6 } + }, + { /* AC bias group 3, table 5 */ + { 0x4, 3 }, + { 0xA, 4 }, + { 0x7, 5 }, + { 0x1D, 5 }, + { 0x9, 6 }, + { 0x1F3, 9 }, + { 0x7C7, 11 }, + { 0x8, 6 }, + { 0x1F0, 9 }, + { 0x3, 3 }, + { 0x2, 3 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x17, 5 }, + { 0x7D, 7 }, + { 0x1F2, 9 }, + { 0x7C6, 11 }, + { 0x7C5, 11 }, + { 0x1F12, 13 }, + { 0x3E27, 14 }, + { 0x3E26, 14 }, + { 0x1F11, 13 }, + { 0x1F10, 13 }, + { 0x0, 3 }, + { 0x1E, 5 }, + { 0x6, 5 }, + { 0x39, 6 }, + { 0x38, 6 }, + { 0x3F, 6 }, + { 0x2C, 6 }, + { 0x5, 5 }, + { 0x2D, 6 } + }, + { /* AC bias group 3, table 6 */ + { 0x2, 3 }, + { 0x7, 4 }, + { 0x18, 5 }, + { 0x3, 4 }, + { 0x5, 5 }, + { 0x35, 7 }, + { 0x4F, 9 }, + { 0x12, 7 }, + { 0x4E5, 13 }, + { 0x5, 3 }, + { 0x4, 3 }, + { 0xD, 4 }, + { 0xE, 4 }, + { 0x33, 6 }, + { 0x26, 8 }, + { 0x9D, 10 }, + { 0x4E4, 13 }, + { 0x4E7, 13 }, + { 0x4E6, 13 }, + { 0x4E1, 13 }, + { 0x4E0, 13 }, + { 0x4E3, 13 }, + { 0x4E2, 13 }, + { 0x0, 3 }, + { 0x1F, 5 }, + { 0xC, 5 }, + { 0x3D, 6 }, + { 0x3C, 6 }, + { 0x32, 6 }, + { 0x34, 7 }, + { 0x1B, 6 }, + { 0x8, 6 } + }, + { /* AC bias group 3, table 7 */ + { 0x0, 3 }, + { 0x4, 4 }, + { 0x1C, 5 }, + { 0xF, 4 }, + { 0x2, 4 }, + { 0x7, 5 }, + { 0x75, 7 }, + { 0xE8, 8 }, + { 0x1D2A, 13 }, + { 0x5, 3 }, + { 0x4, 3 }, + { 0xD, 4 }, + { 0xC, 4 }, + { 0x77, 7 }, + { 0xE96, 12 }, + { 0x3A57, 14 }, + { 0x3A56, 14 }, + { 0x3A5D, 14 }, + { 0x3A5C, 14 }, + { 0x3A5F, 14 }, + { 0x3A5E, 14 }, + { 0x1D29, 13 }, + { 0x1D28, 13 }, + { 0x3, 3 }, + { 0x6, 5 }, + { 0xA, 5 }, + { 0x2C, 7 }, + { 0x17, 6 }, + { 0x76, 7 }, + { 0x1D3, 9 }, + { 0x3A4, 10 }, + { 0x2D, 7 } + }, + { /* AC bias group 3, table 8 */ + { 0xA, 4 }, + { 0x24, 6 }, + { 0xBF, 8 }, + { 0x85, 8 }, + { 0x211, 10 }, + { 0x842, 12 }, + { 0x1087, 13 }, + { 0x18, 5 }, + { 0x20, 6 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0x7, 4 }, + { 0x13, 5 }, + { 0x25, 6 }, + { 0x5E, 7 }, + { 0x43, 7 }, + { 0xBE, 8 }, + { 0x109, 9 }, + { 0x1086, 13 }, + { 0x841, 12 }, + { 0x840, 12 }, + { 0xF, 4 }, + { 0x1, 4 }, + { 0x11, 5 }, + { 0x0, 5 }, + { 0x2E, 6 }, + { 0x19, 5 }, + { 0x1, 5 }, + { 0x6, 4 }, + { 0x16, 5 } + }, + { /* AC bias group 3, table 9 */ + { 0x2, 3 }, + { 0xF, 5 }, + { 0x6F, 7 }, + { 0x61, 7 }, + { 0x374, 10 }, + { 0x1BA8, 13 }, + { 0x3753, 14 }, + { 0x12, 5 }, + { 0x36, 6 }, + { 0x0, 3 }, + { 0x1, 3 }, + { 0xA, 4 }, + { 0xB, 4 }, + { 0x1A, 5 }, + { 0x31, 6 }, + { 0x60, 7 }, + { 0xDC, 8 }, + { 0x1BB, 9 }, + { 0x6EB, 11 }, + { 0x1BAB, 13 }, + { 0x3752, 14 }, + { 0x3755, 14 }, + { 0x3754, 14 }, + { 0xE, 4 }, + { 0x6, 4 }, + { 0x13, 5 }, + { 0xE, 5 }, + { 0x3E, 6 }, + { 0x8, 4 }, + { 0x1E, 5 }, + { 0x19, 5 }, + { 0x3F, 6 } + }, + { /* AC bias group 3, table 10 */ + { 0x3, 3 }, + { 0x1C, 5 }, + { 0x25, 6 }, + { 0x24, 6 }, + { 0x1DA, 9 }, + { 0x1DBD, 13 }, + { 0x3B7C, 14 }, + { 0x3C, 6 }, + { 0x3D, 6 }, + { 0x0, 3 }, + { 0x1, 3 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0xB, 5 }, + { 0x77, 7 }, + { 0xEC, 8 }, + { 0x3B6, 10 }, + { 0x76E, 11 }, + { 0x1DBF, 13 }, + { 0x76FB, 15 }, + { 0x76FA, 15 }, + { 0x3B79, 14 }, + { 0x3B78, 14 }, + { 0xD, 4 }, + { 0x1F, 5 }, + { 0x13, 5 }, + { 0xA, 5 }, + { 0x8, 5 }, + { 0xC, 4 }, + { 0x8, 4 }, + { 0x9, 5 }, + { 0x3A, 6 } + }, + { /* AC bias group 3, table 11 */ + { 0x5, 3 }, + { 0x3, 4 }, + { 0x4, 5 }, + { 0x10, 5 }, + { 0x8F, 8 }, + { 0x475, 11 }, + { 0x11D1, 13 }, + { 0x79, 7 }, + { 0x27, 6 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0x1, 4 }, + { 0x0, 4 }, + { 0x26, 6 }, + { 0x46, 7 }, + { 0x11C, 9 }, + { 0x477, 11 }, + { 0x8ED, 12 }, + { 0x11D0, 13 }, + { 0x11D3, 13 }, + { 0x11D2, 13 }, + { 0x11D9, 13 }, + { 0x11D8, 13 }, + { 0xD, 4 }, + { 0x1F, 5 }, + { 0x12, 5 }, + { 0x5, 5 }, + { 0x3D, 6 }, + { 0xC, 4 }, + { 0xE, 4 }, + { 0x22, 6 }, + { 0x78, 7 } + }, + { /* AC bias group 3, table 12 */ + { 0x5, 3 }, + { 0xC, 4 }, + { 0x1B, 5 }, + { 0x0, 4 }, + { 0x6, 6 }, + { 0x3E2, 10 }, + { 0x3E3D, 14 }, + { 0xF, 7 }, + { 0x34, 6 }, + { 0x3, 3 }, + { 0x2, 3 }, + { 0x1E, 5 }, + { 0x1D, 5 }, + { 0x7D, 7 }, + { 0x1F0, 9 }, + { 0x7C6, 11 }, + { 0x3E3C, 14 }, + { 0x3E3F, 14 }, + { 0x3E3E, 14 }, + { 0x3E39, 14 }, + { 0x3E38, 14 }, + { 0x3E3B, 14 }, + { 0x3E3A, 14 }, + { 0x8, 4 }, + { 0x1C, 5 }, + { 0x2, 5 }, + { 0x3F, 6 }, + { 0x35, 6 }, + { 0x9, 4 }, + { 0x1, 3 }, + { 0xE, 7 }, + { 0xF9, 8 } + }, + { /* AC bias group 3, table 13 */ + { 0x4, 3 }, + { 0xB, 4 }, + { 0x1, 4 }, + { 0xA, 4 }, + { 0x1E, 6 }, + { 0xE0, 9 }, + { 0xE1E, 13 }, + { 0x71, 8 }, + { 0x39, 7 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0xD, 5 }, + { 0xC, 5 }, + { 0x20, 7 }, + { 0x1C2, 10 }, + { 0x1C3F, 14 }, + { 0x1C3E, 14 }, + { 0xE19, 13 }, + { 0xE18, 13 }, + { 0xE1B, 13 }, + { 0xE1A, 13 }, + { 0xE1D, 13 }, + { 0xE1C, 13 }, + { 0x0, 4 }, + { 0x9, 5 }, + { 0x1D, 6 }, + { 0x1F, 6 }, + { 0x11, 6 }, + { 0x5, 4 }, + { 0x1, 3 }, + { 0x43, 8 }, + { 0x42, 8 } + }, + { /* AC bias group 3, table 14 */ + { 0x4, 3 }, + { 0xD, 4 }, + { 0x7, 4 }, + { 0x2, 3 }, + { 0x14, 5 }, + { 0x16C, 9 }, + { 0x16D1, 13 }, + { 0x2DF, 10 }, + { 0x16E, 9 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x2C, 6 }, + { 0x2B, 6 }, + { 0x2DE, 10 }, + { 0x16D0, 13 }, + { 0x16D3, 13 }, + { 0x16D2, 13 }, + { 0x2DB5, 14 }, + { 0x2DB4, 14 }, + { 0x2DB7, 14 }, + { 0x2DB6, 14 }, + { 0x16D9, 13 }, + { 0x16D8, 13 }, + { 0xC, 5 }, + { 0x2A, 6 }, + { 0x5A, 7 }, + { 0x1B, 6 }, + { 0x1A, 6 }, + { 0x17, 5 }, + { 0xC, 4 }, + { 0x5B7, 11 }, + { 0x5B5, 11 } + }, + { /* AC bias group 3, table 15 */ + { 0x2, 2 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0xC, 4 }, + { 0x3B, 6 }, + { 0x1AC, 9 }, + { 0x1AD8, 13 }, + { 0x35B3, 14 }, + { 0x35B2, 14 }, + { 0x1, 2 }, + { 0x0, 2 }, + { 0x69, 7 }, + { 0x68, 7 }, + { 0x35BD, 14 }, + { 0x35BC, 14 }, + { 0x35BF, 14 }, + { 0x35BE, 14 }, + { 0x35B9, 14 }, + { 0x35B8, 14 }, + { 0x35BB, 14 }, + { 0x35BA, 14 }, + { 0x35B5, 14 }, + { 0x35B4, 14 }, + { 0x1A9, 9 }, + { 0x1A8, 9 }, + { 0x35A, 10 }, + { 0xD7, 8 }, + { 0xD5, 8 }, + { 0x3A, 6 }, + { 0x1B, 5 }, + { 0x35B7, 14 }, + { 0x35B6, 14 } + } +}; + +static const uint16_t ac_bias_3[16][32][2] = { + { /* AC bias group 4, table 0 */ + { 0x0, 3 }, + { 0x10, 5 }, + { 0x72, 7 }, + { 0x71, 7 }, + { 0x154, 9 }, + { 0xAAB, 12 }, + { 0xAA8, 12 }, + { 0x14, 5 }, + { 0x70, 7 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0xC, 4 }, + { 0xB, 4 }, + { 0x3, 4 }, + { 0x11, 5 }, + { 0x73, 7 }, + { 0x54, 7 }, + { 0xAB, 8 }, + { 0x2AB, 10 }, + { 0x1553, 13 }, + { 0x1552, 13 }, + { 0x1555, 13 }, + { 0x1554, 13 }, + { 0xD, 4 }, + { 0x1E, 5 }, + { 0x12, 5 }, + { 0x3E, 6 }, + { 0x2B, 6 }, + { 0x2, 4 }, + { 0x3F, 6 }, + { 0x1D, 5 }, + { 0x13, 5 } + }, + { /* AC bias group 4, table 1 */ + { 0x3, 3 }, + { 0x1F, 5 }, + { 0x29, 6 }, + { 0x3D, 6 }, + { 0xC, 7 }, + { 0x69, 10 }, + { 0x345, 13 }, + { 0x2, 5 }, + { 0x28, 6 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0xE, 4 }, + { 0xC, 4 }, + { 0x15, 5 }, + { 0x7, 6 }, + { 0x1B, 8 }, + { 0x6B, 10 }, + { 0x6A, 10 }, + { 0x344, 13 }, + { 0x347, 13 }, + { 0x346, 13 }, + { 0x1A1, 12 }, + { 0x1A0, 12 }, + { 0xB, 4 }, + { 0x1A, 5 }, + { 0x12, 5 }, + { 0x0, 5 }, + { 0x3C, 6 }, + { 0x8, 4 }, + { 0x1B, 5 }, + { 0x13, 5 }, + { 0x1, 5 } + }, + { /* AC bias group 4, table 2 */ + { 0x4, 3 }, + { 0x4, 4 }, + { 0x3F, 6 }, + { 0x14, 5 }, + { 0x56, 7 }, + { 0x15C, 9 }, + { 0x15D5, 13 }, + { 0x3C, 6 }, + { 0x2A, 6 }, + { 0x0, 3 }, + { 0x1, 3 }, + { 0xE, 4 }, + { 0xD, 4 }, + { 0xC, 5 }, + { 0xAF, 8 }, + { 0x2BB, 10 }, + { 0x15D4, 13 }, + { 0x15D7, 13 }, + { 0x15D6, 13 }, + { 0x15D1, 13 }, + { 0x15D0, 13 }, + { 0x15D3, 13 }, + { 0x15D2, 13 }, + { 0xB, 4 }, + { 0x19, 5 }, + { 0xD, 5 }, + { 0x3E, 6 }, + { 0x31, 6 }, + { 0x7, 4 }, + { 0x5, 4 }, + { 0x3D, 6 }, + { 0x30, 6 } + }, + { /* AC bias group 4, table 3 */ + { 0x5, 3 }, + { 0x8, 4 }, + { 0x1A, 5 }, + { 0x0, 4 }, + { 0x36, 6 }, + { 0x11, 8 }, + { 0x106, 12 }, + { 0xA, 7 }, + { 0x6E, 7 }, + { 0x2, 3 }, + { 0x3, 3 }, + { 0x3, 4 }, + { 0x2, 4 }, + { 0x6F, 7 }, + { 0x21, 9 }, + { 0x20F, 13 }, + { 0x20E, 13 }, + { 0x101, 12 }, + { 0x100, 12 }, + { 0x103, 12 }, + { 0x102, 12 }, + { 0x105, 12 }, + { 0x104, 12 }, + { 0xC, 4 }, + { 0x1E, 5 }, + { 0x3, 5 }, + { 0x3E, 6 }, + { 0x3F, 6 }, + { 0x9, 4 }, + { 0xE, 4 }, + { 0xB, 7 }, + { 0x9, 7 } + }, + { /* AC bias group 4, table 4 */ + { 0x2, 3 }, + { 0xE, 4 }, + { 0x1E, 5 }, + { 0xC, 4 }, + { 0x1F, 5 }, + { 0x6E, 7 }, + { 0xAD, 10 }, + { 0xAF, 10 }, + { 0x14, 7 }, + { 0x4, 3 }, + { 0x3, 3 }, + { 0x1A, 5 }, + { 0x17, 5 }, + { 0x2A, 8 }, + { 0x576, 13 }, + { 0xAEF, 14 }, + { 0xAEE, 14 }, + { 0x571, 13 }, + { 0x570, 13 }, + { 0x573, 13 }, + { 0x572, 13 }, + { 0x575, 13 }, + { 0x574, 13 }, + { 0x3, 4 }, + { 0x16, 5 }, + { 0x4, 5 }, + { 0x36, 6 }, + { 0xB, 6 }, + { 0xA, 4 }, + { 0x0, 3 }, + { 0x6F, 7 }, + { 0xAC, 10 } + }, + { /* AC bias group 4, table 5 */ + { 0x4, 3 }, + { 0x5, 4 }, + { 0x3, 3 }, + { 0x1, 3 }, + { 0x4, 4 }, + { 0x2F, 6 }, + { 0x526, 11 }, + { 0x1495, 13 }, + { 0xA6, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x2D, 6 }, + { 0x2C, 6 }, + { 0x1494, 13 }, + { 0x1497, 13 }, + { 0x1496, 13 }, + { 0x1491, 13 }, + { 0x1490, 13 }, + { 0x1493, 13 }, + { 0x1492, 13 }, + { 0x293D, 14 }, + { 0x293C, 14 }, + { 0x293F, 14 }, + { 0x0, 3 }, + { 0x28, 6 }, + { 0xA5, 8 }, + { 0x148, 9 }, + { 0xA7, 8 }, + { 0x2E, 6 }, + { 0x15, 5 }, + { 0xA4E, 12 }, + { 0x293E, 14 } + }, + { /* AC bias group 4, table 6 */ + { 0x4, 3 }, + { 0x5, 4 }, + { 0x3, 3 }, + { 0x1, 3 }, + { 0x4, 4 }, + { 0x2F, 6 }, + { 0x526, 11 }, + { 0x1495, 13 }, + { 0xA6, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x2D, 6 }, + { 0x2C, 6 }, + { 0x1494, 13 }, + { 0x1497, 13 }, + { 0x1496, 13 }, + { 0x1491, 13 }, + { 0x1490, 13 }, + { 0x1493, 13 }, + { 0x1492, 13 }, + { 0x293D, 14 }, + { 0x293C, 14 }, + { 0x293F, 14 }, + { 0x0, 3 }, + { 0x28, 6 }, + { 0xA5, 8 }, + { 0x148, 9 }, + { 0xA7, 8 }, + { 0x2E, 6 }, + { 0x15, 5 }, + { 0xA4E, 12 }, + { 0x293E, 14 } + }, + { /* AC bias group 4, table 7 */ + { 0x4, 3 }, + { 0x5, 4 }, + { 0x3, 3 }, + { 0x1, 3 }, + { 0x4, 4 }, + { 0x2F, 6 }, + { 0x526, 11 }, + { 0x1495, 13 }, + { 0xA6, 8 }, + { 0x7, 3 }, + { 0x6, 3 }, + { 0x2D, 6 }, + { 0x2C, 6 }, + { 0x1494, 13 }, + { 0x1497, 13 }, + { 0x1496, 13 }, + { 0x1491, 13 }, + { 0x1490, 13 }, + { 0x1493, 13 }, + { 0x1492, 13 }, + { 0x293D, 14 }, + { 0x293C, 14 }, + { 0x293F, 14 }, + { 0x0, 3 }, + { 0x28, 6 }, + { 0xA5, 8 }, + { 0x148, 9 }, + { 0xA7, 8 }, + { 0x2E, 6 }, + { 0x15, 5 }, + { 0xA4E, 12 }, + { 0x293E, 14 } + }, + { /* AC bias group 4, table 8 */ + { 0x3, 3 }, + { 0x11, 5 }, + { 0x20, 6 }, + { 0x74, 7 }, + { 0x10D, 9 }, + { 0x863, 12 }, + { 0x860, 12 }, + { 0xA, 5 }, + { 0x75, 7 }, + { 0x1, 3 }, + { 0x0, 3 }, + { 0xB, 4 }, + { 0xA, 4 }, + { 0x18, 5 }, + { 0x38, 6 }, + { 0x42, 7 }, + { 0x10F, 9 }, + { 0x10E, 9 }, + { 0x219, 10 }, + { 0x10C3, 13 }, + { 0x10C2, 13 }, + { 0x10C5, 13 }, + { 0x10C4, 13 }, + { 0xF, 4 }, + { 0x4, 4 }, + { 0x19, 5 }, + { 0xB, 5 }, + { 0x39, 6 }, + { 0x9, 4 }, + { 0x1B, 5 }, + { 0x1A, 5 }, + { 0x3B, 6 } + }, + { /* AC bias group 4, table 9 */ + { 0x5, 3 }, + { 0x1, 4 }, + { 0x3E, 6 }, + { 0x1, 5 }, + { 0xE2, 8 }, + { 0x1C6F, 13 }, + { 0x38D9, 14 }, + { 0x39, 6 }, + { 0x1F, 6 }, + { 0x2, 3 }, + { 0x1, 3 }, + { 0x9, 4 }, + { 0x8, 4 }, + { 0x0, 5 }, + { 0x70, 7 }, + { 0x1C7, 9 }, + { 0x38C, 10 }, + { 0x71A, 11 }, + { 0x38D8, 14 }, + { 0x38DB, 14 }, + { 0x38DA, 14 }, + { 0x38DD, 14 }, + { 0x38DC, 14 }, + { 0xD, 4 }, + { 0x1D, 5 }, + { 0xE, 5 }, + { 0x3F, 6 }, + { 0x3C, 6 }, + { 0xC, 4 }, + { 0x6, 4 }, + { 0x3D, 6 }, + { 0x1E, 6 } + }, + { /* AC bias group 4, table 10 */ + { 0x6, 3 }, + { 0xB, 4 }, + { 0x11, 5 }, + { 0x1E, 5 }, + { 0x74, 7 }, + { 0x3AA, 10 }, + { 0x1D5C, 13 }, + { 0x1, 6 }, + { 0x21, 6 }, + { 0x1, 3 }, + { 0x2, 3 }, + { 0x7, 4 }, + { 0x6, 4 }, + { 0x3E, 6 }, + { 0xEB, 8 }, + { 0x1D4, 9 }, + { 0xEAF, 12 }, + { 0x3ABB, 14 }, + { 0x3ABA, 14 }, + { 0x1D59, 13 }, + { 0x1D58, 13 }, + { 0x1D5B, 13 }, + { 0x1D5A, 13 }, + { 0xA, 4 }, + { 0x1C, 5 }, + { 0x1, 5 }, + { 0x3F, 6 }, + { 0x3B, 6 }, + { 0x1, 4 }, + { 0x9, 4 }, + { 0x20, 6 }, + { 0x0, 6 } + }, + { /* AC bias group 4, table 11 */ + { 0x4, 3 }, + { 0xA, 4 }, + { 0x17, 5 }, + { 0x4, 4 }, + { 0x16, 6 }, + { 0x16A, 9 }, + { 0x16B1, 13 }, + { 0x17, 7 }, + { 0x5B, 7 }, + { 0x6, 3 }, + { 0x7, 3 }, + { 0x1, 4 }, + { 0x0, 4 }, + { 0xA, 6 }, + { 0x2D7, 10 }, + { 0xB5A, 12 }, + { 0x16B0, 13 }, + { 0x16B3, 13 }, + { 0x16B2, 13 }, + { 0x2D6D, 14 }, + { 0x2D6C, 14 }, + { 0x2D6F, 14 }, + { 0x2D6E, 14 }, + { 0x6, 4 }, + { 0xA, 5 }, + { 0x4, 5 }, + { 0x2C, 6 }, + { 0x17, 6 }, + { 0x3, 4 }, + { 0x7, 4 }, + { 0x16, 7 }, + { 0xB4, 8 } + }, + { /* AC bias group 4, table 12 */ + { 0x5, 3 }, + { 0xD, 4 }, + { 0x5, 4 }, + { 0x9, 4 }, + { 0x33, 6 }, + { 0x193, 9 }, + { 0x192C, 13 }, + { 0x61, 8 }, + { 0x31, 7 }, + { 0x0, 2 }, + { 0x7, 3 }, + { 0x10, 5 }, + { 0x11, 5 }, + { 0xC8, 8 }, + { 0x192F, 13 }, + { 0x325B, 14 }, + { 0x325A, 14 }, + { 0x1929, 13 }, + { 0x1928, 13 }, + { 0x192B, 13 }, + { 0x192A, 13 }, + { 0x325D, 14 }, + { 0x325C, 14 }, + { 0x18, 5 }, + { 0x1A, 6 }, + { 0x1B, 6 }, + { 0x65, 7 }, + { 0x19, 6 }, + { 0x4, 4 }, + { 0x7, 4 }, + { 0x60, 8 }, + { 0x324, 10 } + }, + { /* AC bias group 4, table 13 */ + { 0x6, 3 }, + { 0x0, 3 }, + { 0x2, 4 }, + { 0xF, 4 }, + { 0x39, 6 }, + { 0x1D9, 9 }, + { 0x1D82, 13 }, + { 0x761, 11 }, + { 0x3BE, 10 }, + { 0x1, 2 }, + { 0x2, 2 }, + { 0xF, 6 }, + { 0xE, 6 }, + { 0x762, 11 }, + { 0x3B07, 14 }, + { 0x3B06, 14 }, + { 0x3B1D, 14 }, + { 0x3B1C, 14 }, + { 0x3B1F, 14 }, + { 0x3B1E, 14 }, + { 0x3B19, 14 }, + { 0x3B18, 14 }, + { 0x3B1B, 14 }, + { 0x38, 6 }, + { 0x1DE, 9 }, + { 0xED, 8 }, + { 0x3BF, 10 }, + { 0xEE, 8 }, + { 0x3A, 6 }, + { 0x6, 5 }, + { 0xEC0, 12 }, + { 0x3B1A, 14 } + }, + { /* AC bias group 4, table 14 */ + { 0x0, 2 }, + { 0x2, 3 }, + { 0xF, 5 }, + { 0x6, 4 }, + { 0x1C, 6 }, + { 0x1D0, 10 }, + { 0xE8C, 13 }, + { 0x1D1B, 14 }, + { 0x1D1A, 14 }, + { 0x3, 2 }, + { 0x2, 2 }, + { 0xEA, 9 }, + { 0xE9, 9 }, + { 0xE89, 13 }, + { 0xE88, 13 }, + { 0xE8B, 13 }, + { 0xE8A, 13 }, + { 0x1D65, 14 }, + { 0x1D64, 14 }, + { 0x1D67, 14 }, + { 0x1D66, 14 }, + { 0x1D61, 14 }, + { 0x1D60, 14 }, + { 0x3AD, 11 }, + { 0x1D63, 14 }, + { 0x1D62, 14 }, + { 0x1D1D, 14 }, + { 0x1D1C, 14 }, + { 0x3B, 7 }, + { 0x1D7, 10 }, + { 0x1D1F, 14 }, + { 0x1D1E, 14 } + }, + { /* AC bias group 4, table 15 */ + { 0x2, 2 }, + { 0xF, 4 }, + { 0x1C, 5 }, + { 0xC, 4 }, + { 0x3B, 6 }, + { 0x1AC, 9 }, + { 0x1AD8, 13 }, + { 0x35B3, 14 }, + { 0x35B2, 14 }, + { 0x1, 2 }, + { 0x0, 2 }, + { 0x69, 7 }, + { 0x68, 7 }, + { 0x35BD, 14 }, + { 0x35BC, 14 }, + { 0x35BF, 14 }, + { 0x35BE, 14 }, + { 0x35B9, 14 }, + { 0x35B8, 14 }, + { 0x35BB, 14 }, + { 0x35BA, 14 }, + { 0x35B5, 14 }, + { 0x35B4, 14 }, + { 0x1A9, 9 }, + { 0x1A8, 9 }, + { 0x35A, 10 }, + { 0xD7, 8 }, + { 0xD5, 8 }, + { 0x3A, 6 }, + { 0x1B, 5 }, + { 0x35B7, 14 }, + { 0x35B6, 14 } + } +}; + +#endif /* AVCODEC_VP3DATA_H */ diff --git a/ffmpeg/libavcodec/vp3dsp.c b/ffmpeg/libavcodec/vp3dsp.c new file mode 100644 index 0000000..9348963 --- /dev/null +++ b/ffmpeg/libavcodec/vp3dsp.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2004 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Standard C DSP-oriented functions cribbed from the original VP3 + * source code. + */ + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "dsputil.h" +#include "rnd_avg.h" +#include "vp3dsp.h" + +#define IdctAdjustBeforeShift 8 +#define xC1S7 64277 +#define xC2S6 60547 +#define xC3S5 54491 +#define xC4S4 46341 +#define xC5S3 36410 +#define xC6S2 25080 +#define xC7S1 12785 + +#define M(a,b) (((a) * (b))>>16) + +static av_always_inline void idct(uint8_t *dst, int stride, int16_t *input, int type) +{ + int16_t *ip = input; + + int A, B, C, D, Ad, Bd, Cd, Dd, E, F, G, H; + int Ed, Gd, Add, Bdd, Fd, Hd; + + int i; + + /* Inverse DCT on the rows now */ + for (i = 0; i < 8; i++) { + /* Check for non-zero values */ + if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] | + ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8] ) { + A = M(xC1S7, ip[1 * 8]) + M(xC7S1, ip[7 * 8]); + B = M(xC7S1, ip[1 * 8]) - M(xC1S7, ip[7 * 8]); + C = M(xC3S5, ip[3 * 8]) + M(xC5S3, ip[5 * 8]); + D = M(xC3S5, ip[5 * 8]) - M(xC5S3, ip[3 * 8]); + + Ad = M(xC4S4, (A - C)); + Bd = M(xC4S4, (B - D)); + + Cd = A + C; + Dd = B + D; + + E = M(xC4S4, (ip[0 * 8] + ip[4 * 8])); + F = M(xC4S4, (ip[0 * 8] - ip[4 * 8])); + + G = M(xC2S6, ip[2 * 8]) + M(xC6S2, ip[6 * 8]); + H = M(xC6S2, ip[2 * 8]) - M(xC2S6, ip[6 * 8]); + + Ed = E - G; + Gd = E + G; + + Add = F + Ad; + Bdd = Bd - H; + + Fd = F - Ad; + Hd = Bd + H; + + /* Final sequence of operations over-write original inputs. */ + ip[0 * 8] = Gd + Cd ; + ip[7 * 8] = Gd - Cd ; + + ip[1 * 8] = Add + Hd; + ip[2 * 8] = Add - Hd; + + ip[3 * 8] = Ed + Dd ; + ip[4 * 8] = Ed - Dd ; + + ip[5 * 8] = Fd + Bdd; + ip[6 * 8] = Fd - Bdd; + } + + ip += 1; /* next row */ + } + + ip = input; + + for ( i = 0; i < 8; i++) { + /* Check for non-zero values (bitwise or faster than ||) */ + if ( ip[1] | ip[2] | ip[3] | + ip[4] | ip[5] | ip[6] | ip[7] ) { + + A = M(xC1S7, ip[1]) + M(xC7S1, ip[7]); + B = M(xC7S1, ip[1]) - M(xC1S7, ip[7]); + C = M(xC3S5, ip[3]) + M(xC5S3, ip[5]); + D = M(xC3S5, ip[5]) - M(xC5S3, ip[3]); + + Ad = M(xC4S4, (A - C)); + Bd = M(xC4S4, (B - D)); + + Cd = A + C; + Dd = B + D; + + E = M(xC4S4, (ip[0] + ip[4])) + 8; + F = M(xC4S4, (ip[0] - ip[4])) + 8; + + if(type==1){ //HACK + E += 16*128; + F += 16*128; + } + + G = M(xC2S6, ip[2]) + M(xC6S2, ip[6]); + H = M(xC6S2, ip[2]) - M(xC2S6, ip[6]); + + Ed = E - G; + Gd = E + G; + + Add = F + Ad; + Bdd = Bd - H; + + Fd = F - Ad; + Hd = Bd + H; + + /* Final sequence of operations over-write original inputs. */ + if(type==1){ + dst[0*stride] = av_clip_uint8((Gd + Cd ) >> 4); + dst[7*stride] = av_clip_uint8((Gd - Cd ) >> 4); + + dst[1*stride] = av_clip_uint8((Add + Hd ) >> 4); + dst[2*stride] = av_clip_uint8((Add - Hd ) >> 4); + + dst[3*stride] = av_clip_uint8((Ed + Dd ) >> 4); + dst[4*stride] = av_clip_uint8((Ed - Dd ) >> 4); + + dst[5*stride] = av_clip_uint8((Fd + Bdd ) >> 4); + dst[6*stride] = av_clip_uint8((Fd - Bdd ) >> 4); + }else{ + dst[0*stride] = av_clip_uint8(dst[0*stride] + ((Gd + Cd ) >> 4)); + dst[7*stride] = av_clip_uint8(dst[7*stride] + ((Gd - Cd ) >> 4)); + + dst[1*stride] = av_clip_uint8(dst[1*stride] + ((Add + Hd ) >> 4)); + dst[2*stride] = av_clip_uint8(dst[2*stride] + ((Add - Hd ) >> 4)); + + dst[3*stride] = av_clip_uint8(dst[3*stride] + ((Ed + Dd ) >> 4)); + dst[4*stride] = av_clip_uint8(dst[4*stride] + ((Ed - Dd ) >> 4)); + + dst[5*stride] = av_clip_uint8(dst[5*stride] + ((Fd + Bdd ) >> 4)); + dst[6*stride] = av_clip_uint8(dst[6*stride] + ((Fd - Bdd ) >> 4)); + } + + } else { + if(type==1){ + dst[0*stride]= + dst[1*stride]= + dst[2*stride]= + dst[3*stride]= + dst[4*stride]= + dst[5*stride]= + dst[6*stride]= + dst[7*stride]= av_clip_uint8(128 + ((xC4S4 * ip[0] + (IdctAdjustBeforeShift<<16))>>20)); + }else{ + if(ip[0]){ + int v= ((xC4S4 * ip[0] + (IdctAdjustBeforeShift<<16))>>20); + dst[0*stride] = av_clip_uint8(dst[0*stride] + v); + dst[1*stride] = av_clip_uint8(dst[1*stride] + v); + dst[2*stride] = av_clip_uint8(dst[2*stride] + v); + dst[3*stride] = av_clip_uint8(dst[3*stride] + v); + dst[4*stride] = av_clip_uint8(dst[4*stride] + v); + dst[5*stride] = av_clip_uint8(dst[5*stride] + v); + dst[6*stride] = av_clip_uint8(dst[6*stride] + v); + dst[7*stride] = av_clip_uint8(dst[7*stride] + v); + } + } + } + + ip += 8; /* next column */ + dst++; + } +} + +static void vp3_idct_put_c(uint8_t *dest/*align 8*/, int line_size, + int16_t *block/*align 16*/) +{ + idct(dest, line_size, block, 1); + memset(block, 0, sizeof(*block) * 64); +} + +static void vp3_idct_add_c(uint8_t *dest/*align 8*/, int line_size, + int16_t *block/*align 16*/) +{ + idct(dest, line_size, block, 2); + memset(block, 0, sizeof(*block) * 64); +} + +static void vp3_idct_dc_add_c(uint8_t *dest/*align 8*/, int line_size, + int16_t *block/*align 16*/) +{ + int i, dc = (block[0] + 15) >> 5; + + for(i = 0; i < 8; i++){ + dest[0] = av_clip_uint8(dest[0] + dc); + dest[1] = av_clip_uint8(dest[1] + dc); + dest[2] = av_clip_uint8(dest[2] + dc); + dest[3] = av_clip_uint8(dest[3] + dc); + dest[4] = av_clip_uint8(dest[4] + dc); + dest[5] = av_clip_uint8(dest[5] + dc); + dest[6] = av_clip_uint8(dest[6] + dc); + dest[7] = av_clip_uint8(dest[7] + dc); + dest += line_size; + } + block[0] = 0; +} + +static void vp3_v_loop_filter_c(uint8_t *first_pixel, int stride, + int *bounding_values) +{ + unsigned char *end; + int filter_value; + const int nstride= -stride; + + for (end= first_pixel + 8; first_pixel < end; first_pixel++) { + filter_value = + (first_pixel[2 * nstride] - first_pixel[ stride]) + +3*(first_pixel[0 ] - first_pixel[nstride]); + filter_value = bounding_values[(filter_value + 4) >> 3]; + first_pixel[nstride] = av_clip_uint8(first_pixel[nstride] + filter_value); + first_pixel[0] = av_clip_uint8(first_pixel[0] - filter_value); + } +} + +static void vp3_h_loop_filter_c(uint8_t *first_pixel, int stride, + int *bounding_values) +{ + unsigned char *end; + int filter_value; + + for (end= first_pixel + 8*stride; first_pixel != end; first_pixel += stride) { + filter_value = + (first_pixel[-2] - first_pixel[ 1]) + +3*(first_pixel[ 0] - first_pixel[-1]); + filter_value = bounding_values[(filter_value + 4) >> 3]; + first_pixel[-1] = av_clip_uint8(first_pixel[-1] + filter_value); + first_pixel[ 0] = av_clip_uint8(first_pixel[ 0] - filter_value); + } +} + +static void put_no_rnd_pixels_l2(uint8_t *dst, const uint8_t *src1, + const uint8_t *src2, ptrdiff_t stride, int h) +{ + int i; + + for (i = 0; i < h; i++) { + uint32_t a, b; + + a = AV_RN32(&src1[i * stride]); + b = AV_RN32(&src2[i * stride]); + AV_WN32A(&dst[i * stride], no_rnd_avg32(a, b)); + a = AV_RN32(&src1[i * stride + 4]); + b = AV_RN32(&src2[i * stride + 4]); + AV_WN32A(&dst[i * stride + 4], no_rnd_avg32(a, b)); + } +} + +av_cold void ff_vp3dsp_init(VP3DSPContext *c, int flags) +{ + c->put_no_rnd_pixels_l2 = put_no_rnd_pixels_l2; + + c->idct_put = vp3_idct_put_c; + c->idct_add = vp3_idct_add_c; + c->idct_dc_add = vp3_idct_dc_add_c; + c->v_loop_filter = vp3_v_loop_filter_c; + c->h_loop_filter = vp3_h_loop_filter_c; + + if (ARCH_ARM) + ff_vp3dsp_init_arm(c, flags); + if (ARCH_BFIN) + ff_vp3dsp_init_bfin(c, flags); + if (ARCH_PPC) + ff_vp3dsp_init_ppc(c, flags); + if (ARCH_X86) + ff_vp3dsp_init_x86(c, flags); +} diff --git a/ffmpeg/libavcodec/vp3dsp.h b/ffmpeg/libavcodec/vp3dsp.h new file mode 100644 index 0000000..3aded99 --- /dev/null +++ b/ffmpeg/libavcodec/vp3dsp.h @@ -0,0 +1,54 @@ +/* + * 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 + */ + +#ifndef AVCODEC_VP3DSP_H +#define AVCODEC_VP3DSP_H + +#include +#include + +typedef struct VP3DSPContext { + /** + * Copy 8xH pixels from source to destination buffer using a bilinear + * filter with no rounding (i.e. *dst = (*a + *b) >> 1). + * + * @param dst destination buffer, aligned by 8 + * @param a first source buffer, no alignment + * @param b second source buffer, no alignment + * @param stride distance between two lines in source/dest buffers + * @param h height + */ + void (*put_no_rnd_pixels_l2)(uint8_t *dst, + const uint8_t *a, + const uint8_t *b, + ptrdiff_t stride, int h); + + void (*idct_put)(uint8_t *dest, int line_size, int16_t *block); + void (*idct_add)(uint8_t *dest, int line_size, int16_t *block); + void (*idct_dc_add)(uint8_t *dest, int line_size, int16_t *block); + void (*v_loop_filter)(uint8_t *src, int stride, int *bounding_values); + void (*h_loop_filter)(uint8_t *src, int stride, int *bounding_values); +} VP3DSPContext; + +void ff_vp3dsp_init(VP3DSPContext *c, int flags); +void ff_vp3dsp_init_arm(VP3DSPContext *c, int flags); +void ff_vp3dsp_init_bfin(VP3DSPContext *c, int flags); +void ff_vp3dsp_init_ppc(VP3DSPContext *c, int flags); +void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags); + +#endif /* AVCODEC_VP3DSP_H */ diff --git a/ffmpeg/libavcodec/vp5.c b/ffmpeg/libavcodec/vp5.c new file mode 100644 index 0000000..4eecbe3 --- /dev/null +++ b/ffmpeg/libavcodec/vp5.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP5 compatible video decoder + */ + +#include +#include + +#include "avcodec.h" +#include "get_bits.h" + +#include "vp56.h" +#include "vp56data.h" +#include "vp5data.h" + + +static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size) +{ + VP56RangeCoder *c = &s->c; + int rows, cols; + + ff_vp56_init_range_decoder(&s->c, buf, buf_size); + s->frames[VP56_FRAME_CURRENT]->key_frame = !vp56_rac_get(c); + vp56_rac_get(c); + ff_vp56_init_dequant(s, vp56_rac_gets(c, 6)); + if (s->frames[VP56_FRAME_CURRENT]->key_frame) + { + vp56_rac_gets(c, 8); + if(vp56_rac_gets(c, 5) > 5) + return AVERROR_INVALIDDATA; + vp56_rac_gets(c, 2); + if (vp56_rac_get(c)) { + av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n"); + return AVERROR_PATCHWELCOME; + } + rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */ + cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */ + if (!rows || !cols) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid size %dx%d\n", + cols << 4, rows << 4); + return AVERROR_INVALIDDATA; + } + vp56_rac_gets(c, 8); /* number of displayed macroblock rows */ + vp56_rac_gets(c, 8); /* number of displayed macroblock cols */ + vp56_rac_gets(c, 2); + if (!s->macroblocks || /* first frame */ + 16*cols != s->avctx->coded_width || + 16*rows != s->avctx->coded_height) { + avcodec_set_dimensions(s->avctx, 16*cols, 16*rows); + return VP56_SIZE_CHANGE; + } + } else if (!s->macroblocks) + return AVERROR_INVALIDDATA; + return 0; +} + +static void vp5_parse_vector_adjustment(VP56Context *s, VP56mv *vect) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + int comp, di; + + for (comp=0; comp<2; comp++) { + int delta = 0; + if (vp56_rac_get_prob(c, model->vector_dct[comp])) { + int sign = vp56_rac_get_prob(c, model->vector_sig[comp]); + di = vp56_rac_get_prob(c, model->vector_pdi[comp][0]); + di |= vp56_rac_get_prob(c, model->vector_pdi[comp][1]) << 1; + delta = vp56_rac_get_tree(c, ff_vp56_pva_tree, + model->vector_pdv[comp]); + delta = di | (delta << 2); + delta = (delta ^ -sign) + sign; + } + if (!comp) + vect->x = delta; + else + vect->y = delta; + } +} + +static void vp5_parse_vector_models(VP56Context *s) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + int comp, node; + + for (comp=0; comp<2; comp++) { + if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][0])) + model->vector_dct[comp] = vp56_rac_gets_nn(c, 7); + if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][1])) + model->vector_sig[comp] = vp56_rac_gets_nn(c, 7); + if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][2])) + model->vector_pdi[comp][0] = vp56_rac_gets_nn(c, 7); + if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][3])) + model->vector_pdi[comp][1] = vp56_rac_gets_nn(c, 7); + } + + for (comp=0; comp<2; comp++) + for (node=0; node<7; node++) + if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][4 + node])) + model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7); +} + +static int vp5_parse_coeff_models(VP56Context *s) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + uint8_t def_prob[11]; + int node, cg, ctx; + int ct; /* code type */ + int pt; /* plane type (0 for Y, 1 for U or V) */ + + memset(def_prob, 0x80, sizeof(def_prob)); + + for (pt=0; pt<2; pt++) + for (node=0; node<11; node++) + if (vp56_rac_get_prob(c, vp5_dccv_pct[pt][node])) { + def_prob[node] = vp56_rac_gets_nn(c, 7); + model->coeff_dccv[pt][node] = def_prob[node]; + } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + model->coeff_dccv[pt][node] = def_prob[node]; + } + + for (ct=0; ct<3; ct++) + for (pt=0; pt<2; pt++) + for (cg=0; cg<6; cg++) + for (node=0; node<11; node++) + if (vp56_rac_get_prob(c, vp5_ract_pct[ct][pt][cg][node])) { + def_prob[node] = vp56_rac_gets_nn(c, 7); + model->coeff_ract[pt][ct][cg][node] = def_prob[node]; + } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + model->coeff_ract[pt][ct][cg][node] = def_prob[node]; + } + + /* coeff_dcct is a linear combination of coeff_dccv */ + for (pt=0; pt<2; pt++) + for (ctx=0; ctx<36; ctx++) + for (node=0; node<5; node++) + model->coeff_dcct[pt][ctx][node] = av_clip(((model->coeff_dccv[pt][node] * vp5_dccv_lc[node][ctx][0] + 128) >> 8) + vp5_dccv_lc[node][ctx][1], 1, 254); + + /* coeff_acct is a linear combination of coeff_ract */ + for (ct=0; ct<3; ct++) + for (pt=0; pt<2; pt++) + for (cg=0; cg<3; cg++) + for (ctx=0; ctx<6; ctx++) + for (node=0; node<5; node++) + model->coeff_acct[pt][ct][cg][ctx][node] = av_clip(((model->coeff_ract[pt][ct][cg][node] * vp5_ract_lc[ct][cg][node][ctx][0] + 128) >> 8) + vp5_ract_lc[ct][cg][node][ctx][1], 1, 254); + return 0; +} + +static void vp5_parse_coeff(VP56Context *s) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + uint8_t *permute = s->idct_scantable; + uint8_t *model1, *model2; + int coeff, sign, coeff_idx; + int b, i, cg, idx, ctx, ctx_last; + int pt = 0; /* plane type (0 for Y, 1 for U or V) */ + + for (b=0; b<6; b++) { + int ct = 1; /* code type */ + + if (b > 3) pt = 1; + + ctx = 6*s->coeff_ctx[ff_vp56_b6to4[b]][0] + + s->above_blocks[s->above_block_idx[b]].not_null_dc; + model1 = model->coeff_dccv[pt]; + model2 = model->coeff_dcct[pt][ctx]; + + coeff_idx = 0; + for (;;) { + if (vp56_rac_get_prob(c, model2[0])) { + if (vp56_rac_get_prob(c, model2[2])) { + if (vp56_rac_get_prob(c, model2[3])) { + s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 4; + idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1); + sign = vp56_rac_get(c); + coeff = ff_vp56_coeff_bias[idx+5]; + for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--) + coeff += vp56_rac_get_prob(c, ff_vp56_coeff_parse_table[idx][i]) << i; + } else { + if (vp56_rac_get_prob(c, model2[4])) { + coeff = 3 + vp56_rac_get_prob(c, model1[5]); + s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 3; + } else { + coeff = 2; + s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 2; + } + sign = vp56_rac_get(c); + } + ct = 2; + } else { + ct = 1; + s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 1; + sign = vp56_rac_get(c); + coeff = 1; + } + coeff = (coeff ^ -sign) + sign; + if (coeff_idx) + coeff *= s->dequant_ac; + s->block_coeff[b][permute[coeff_idx]] = coeff; + } else { + if (ct && !vp56_rac_get_prob(c, model2[1])) + break; + ct = 0; + s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 0; + } + coeff_idx++; + if (coeff_idx >= 64) + break; + + cg = vp5_coeff_groups[coeff_idx]; + ctx = s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx]; + model1 = model->coeff_ract[pt][ct][cg]; + model2 = cg > 2 ? model1 : model->coeff_acct[pt][ct][cg][ctx]; + } + + ctx_last = FFMIN(s->coeff_ctx_last[ff_vp56_b6to4[b]], 24); + s->coeff_ctx_last[ff_vp56_b6to4[b]] = coeff_idx; + if (coeff_idx < ctx_last) + for (i=coeff_idx; i<=ctx_last; i++) + s->coeff_ctx[ff_vp56_b6to4[b]][i] = 5; + s->above_blocks[s->above_block_idx[b]].not_null_dc = s->coeff_ctx[ff_vp56_b6to4[b]][0]; + } +} + +static void vp5_default_models_init(VP56Context *s) +{ + VP56Model *model = s->modelp; + int i; + + for (i=0; i<2; i++) { + model->vector_sig[i] = 0x80; + model->vector_dct[i] = 0x80; + model->vector_pdi[i][0] = 0x55; + model->vector_pdi[i][1] = 0x80; + } + memcpy(model->mb_types_stats, ff_vp56_def_mb_types_stats, sizeof(model->mb_types_stats)); + memset(model->vector_pdv, 0x80, sizeof(model->vector_pdv)); +} + +static av_cold int vp5_decode_init(AVCodecContext *avctx) +{ + VP56Context *s = avctx->priv_data; + int ret; + + if ((ret = ff_vp56_init(avctx, 1, 0)) < 0) + return ret; + s->vp56_coord_div = vp5_coord_div; + s->parse_vector_adjustment = vp5_parse_vector_adjustment; + s->parse_coeff = vp5_parse_coeff; + s->default_models_init = vp5_default_models_init; + s->parse_vector_models = vp5_parse_vector_models; + s->parse_coeff_models = vp5_parse_coeff_models; + s->parse_header = vp5_parse_header; + + return 0; +} + +AVCodec ff_vp5_decoder = { + .name = "vp5", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP5, + .priv_data_size = sizeof(VP56Context), + .init = vp5_decode_init, + .close = ff_vp56_free, + .decode = ff_vp56_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("On2 VP5"), +}; diff --git a/ffmpeg/libavcodec/vp56.c b/ffmpeg/libavcodec/vp56.c new file mode 100644 index 0000000..6bf391c --- /dev/null +++ b/ffmpeg/libavcodec/vp56.c @@ -0,0 +1,755 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP5 and VP6 compatible video decoder (common features) + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "h264chroma.h" +#include "vp56.h" +#include "vp56data.h" + + +void ff_vp56_init_dequant(VP56Context *s, int quantizer) +{ + s->quantizer = quantizer; + s->dequant_dc = vp56_dc_dequant[quantizer] << 2; + s->dequant_ac = vp56_ac_dequant[quantizer] << 2; +} + +static int vp56_get_vectors_predictors(VP56Context *s, int row, int col, + VP56Frame ref_frame) +{ + int nb_pred = 0; + VP56mv vect[2] = {{0,0}, {0,0}}; + int pos, offset; + VP56mv mvp; + + for (pos=0; pos<12; pos++) { + mvp.x = col + vp56_candidate_predictor_pos[pos][0]; + mvp.y = row + vp56_candidate_predictor_pos[pos][1]; + if (mvp.x < 0 || mvp.x >= s->mb_width || + mvp.y < 0 || mvp.y >= s->mb_height) + continue; + offset = mvp.x + s->mb_width*mvp.y; + + if (vp56_reference_frame[s->macroblocks[offset].type] != ref_frame) + continue; + if ((s->macroblocks[offset].mv.x == vect[0].x && + s->macroblocks[offset].mv.y == vect[0].y) || + (s->macroblocks[offset].mv.x == 0 && + s->macroblocks[offset].mv.y == 0)) + continue; + + vect[nb_pred++] = s->macroblocks[offset].mv; + if (nb_pred > 1) { + nb_pred = -1; + break; + } + s->vector_candidate_pos = pos; + } + + s->vector_candidate[0] = vect[0]; + s->vector_candidate[1] = vect[1]; + + return nb_pred+1; +} + +static void vp56_parse_mb_type_models(VP56Context *s) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + int i, ctx, type; + + for (ctx=0; ctx<3; ctx++) { + if (vp56_rac_get_prob(c, 174)) { + int idx = vp56_rac_gets(c, 4); + memcpy(model->mb_types_stats[ctx], + vp56_pre_def_mb_type_stats[idx][ctx], + sizeof(model->mb_types_stats[ctx])); + } + if (vp56_rac_get_prob(c, 254)) { + for (type=0; type<10; type++) { + for(i=0; i<2; i++) { + if (vp56_rac_get_prob(c, 205)) { + int delta, sign = vp56_rac_get(c); + + delta = vp56_rac_get_tree(c, vp56_pmbtm_tree, + vp56_mb_type_model_model); + if (!delta) + delta = 4 * vp56_rac_gets(c, 7); + model->mb_types_stats[ctx][type][i] += (delta ^ -sign) + sign; + } + } + } + } + } + + /* compute MB type probability tables based on previous MB type */ + for (ctx=0; ctx<3; ctx++) { + int p[10]; + + for (type=0; type<10; type++) + p[type] = 100 * model->mb_types_stats[ctx][type][1]; + + for (type=0; type<10; type++) { + int p02, p34, p0234, p17, p56, p89, p5689, p156789; + + /* conservative MB type probability */ + model->mb_type[ctx][type][0] = 255 - (255 * model->mb_types_stats[ctx][type][0]) / (1 + model->mb_types_stats[ctx][type][0] + model->mb_types_stats[ctx][type][1]); + + p[type] = 0; /* same MB type => weight is null */ + + /* binary tree parsing probabilities */ + p02 = p[0] + p[2]; + p34 = p[3] + p[4]; + p0234 = p02 + p34; + p17 = p[1] + p[7]; + p56 = p[5] + p[6]; + p89 = p[8] + p[9]; + p5689 = p56 + p89; + p156789 = p17 + p5689; + + model->mb_type[ctx][type][1] = 1 + 255 * p0234/(1+p0234+p156789); + model->mb_type[ctx][type][2] = 1 + 255 * p02 / (1+p0234); + model->mb_type[ctx][type][3] = 1 + 255 * p17 / (1+p156789); + model->mb_type[ctx][type][4] = 1 + 255 * p[0] / (1+p02); + model->mb_type[ctx][type][5] = 1 + 255 * p[3] / (1+p34); + model->mb_type[ctx][type][6] = 1 + 255 * p[1] / (1+p17); + model->mb_type[ctx][type][7] = 1 + 255 * p56 / (1+p5689); + model->mb_type[ctx][type][8] = 1 + 255 * p[5] / (1+p56); + model->mb_type[ctx][type][9] = 1 + 255 * p[8] / (1+p89); + + /* restore initial value */ + p[type] = 100 * model->mb_types_stats[ctx][type][1]; + } + } +} + +static VP56mb vp56_parse_mb_type(VP56Context *s, + VP56mb prev_type, int ctx) +{ + uint8_t *mb_type_model = s->modelp->mb_type[ctx][prev_type]; + VP56RangeCoder *c = &s->c; + + if (vp56_rac_get_prob(c, mb_type_model[0])) + return prev_type; + else + return vp56_rac_get_tree(c, vp56_pmbt_tree, mb_type_model); +} + +static void vp56_decode_4mv(VP56Context *s, int row, int col) +{ + VP56mv mv = {0,0}; + int type[4]; + int b; + + /* parse each block type */ + for (b=0; b<4; b++) { + type[b] = vp56_rac_gets(&s->c, 2); + if (type[b]) + type[b]++; /* only returns 0, 2, 3 or 4 (all INTER_PF) */ + } + + /* get vectors */ + for (b=0; b<4; b++) { + switch (type[b]) { + case VP56_MB_INTER_NOVEC_PF: + s->mv[b] = (VP56mv) {0,0}; + break; + case VP56_MB_INTER_DELTA_PF: + s->parse_vector_adjustment(s, &s->mv[b]); + break; + case VP56_MB_INTER_V1_PF: + s->mv[b] = s->vector_candidate[0]; + break; + case VP56_MB_INTER_V2_PF: + s->mv[b] = s->vector_candidate[1]; + break; + } + mv.x += s->mv[b].x; + mv.y += s->mv[b].y; + } + + /* this is the one selected for the whole MB for prediction */ + s->macroblocks[row * s->mb_width + col].mv = s->mv[3]; + + /* chroma vectors are average luma vectors */ + if (s->avctx->codec->id == AV_CODEC_ID_VP5) { + s->mv[4].x = s->mv[5].x = RSHIFT(mv.x,2); + s->mv[4].y = s->mv[5].y = RSHIFT(mv.y,2); + } else { + s->mv[4] = s->mv[5] = (VP56mv) {mv.x/4, mv.y/4}; + } +} + +static VP56mb vp56_decode_mv(VP56Context *s, int row, int col) +{ + VP56mv *mv, vect = {0,0}; + int ctx, b; + + ctx = vp56_get_vectors_predictors(s, row, col, VP56_FRAME_PREVIOUS); + s->mb_type = vp56_parse_mb_type(s, s->mb_type, ctx); + s->macroblocks[row * s->mb_width + col].type = s->mb_type; + + switch (s->mb_type) { + case VP56_MB_INTER_V1_PF: + mv = &s->vector_candidate[0]; + break; + + case VP56_MB_INTER_V2_PF: + mv = &s->vector_candidate[1]; + break; + + case VP56_MB_INTER_V1_GF: + vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN); + mv = &s->vector_candidate[0]; + break; + + case VP56_MB_INTER_V2_GF: + vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN); + mv = &s->vector_candidate[1]; + break; + + case VP56_MB_INTER_DELTA_PF: + s->parse_vector_adjustment(s, &vect); + mv = &vect; + break; + + case VP56_MB_INTER_DELTA_GF: + vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN); + s->parse_vector_adjustment(s, &vect); + mv = &vect; + break; + + case VP56_MB_INTER_4V: + vp56_decode_4mv(s, row, col); + return s->mb_type; + + default: + mv = &vect; + break; + } + + s->macroblocks[row*s->mb_width + col].mv = *mv; + + /* same vector for all blocks */ + for (b=0; b<6; b++) + s->mv[b] = *mv; + + return s->mb_type; +} + +static void vp56_add_predictors_dc(VP56Context *s, VP56Frame ref_frame) +{ + int idx = s->idct_scantable[0]; + int b; + + for (b=0; b<6; b++) { + VP56RefDc *ab = &s->above_blocks[s->above_block_idx[b]]; + VP56RefDc *lb = &s->left_block[ff_vp56_b6to4[b]]; + int count = 0; + int dc = 0; + int i; + + if (ref_frame == lb->ref_frame) { + dc += lb->dc_coeff; + count++; + } + if (ref_frame == ab->ref_frame) { + dc += ab->dc_coeff; + count++; + } + if (s->avctx->codec->id == AV_CODEC_ID_VP5) + for (i=0; i<2; i++) + if (count < 2 && ref_frame == ab[-1+2*i].ref_frame) { + dc += ab[-1+2*i].dc_coeff; + count++; + } + if (count == 0) + dc = s->prev_dc[ff_vp56_b2p[b]][ref_frame]; + else if (count == 2) + dc /= 2; + + s->block_coeff[b][idx] += dc; + s->prev_dc[ff_vp56_b2p[b]][ref_frame] = s->block_coeff[b][idx]; + ab->dc_coeff = s->block_coeff[b][idx]; + ab->ref_frame = ref_frame; + lb->dc_coeff = s->block_coeff[b][idx]; + lb->ref_frame = ref_frame; + s->block_coeff[b][idx] *= s->dequant_dc; + } +} + +static void vp56_deblock_filter(VP56Context *s, uint8_t *yuv, + int stride, int dx, int dy) +{ + int t = vp56_filter_threshold[s->quantizer]; + if (dx) s->vp56dsp.edge_filter_hor(yuv + 10-dx , stride, t); + if (dy) s->vp56dsp.edge_filter_ver(yuv + stride*(10-dy), stride, t); +} + +static void vp56_mc(VP56Context *s, int b, int plane, uint8_t *src, + int stride, int x, int y) +{ + uint8_t *dst = s->frames[VP56_FRAME_CURRENT]->data[plane] + s->block_offset[b]; + uint8_t *src_block; + int src_offset; + int overlap_offset = 0; + int mask = s->vp56_coord_div[b] - 1; + int deblock_filtering = s->deblock_filtering; + int dx; + int dy; + + if (s->avctx->skip_loop_filter >= AVDISCARD_ALL || + (s->avctx->skip_loop_filter >= AVDISCARD_NONKEY + && !s->frames[VP56_FRAME_CURRENT]->key_frame)) + deblock_filtering = 0; + + dx = s->mv[b].x / s->vp56_coord_div[b]; + dy = s->mv[b].y / s->vp56_coord_div[b]; + + if (b >= 4) { + x /= 2; + y /= 2; + } + x += dx - 2; + y += dy - 2; + + if (x<0 || x+12>=s->plane_width[plane] || + y<0 || y+12>=s->plane_height[plane]) { + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, + src + s->block_offset[b] + (dy-2)*stride + (dx-2), + stride, 12, 12, x, y, + s->plane_width[plane], + s->plane_height[plane]); + src_block = s->edge_emu_buffer; + src_offset = 2 + 2*stride; + } else if (deblock_filtering) { + /* only need a 12x12 block, but there is no such dsp function, */ + /* so copy a 16x12 block */ + s->hdsp.put_pixels_tab[0][0](s->edge_emu_buffer, + src + s->block_offset[b] + (dy-2)*stride + (dx-2), + stride, 12); + src_block = s->edge_emu_buffer; + src_offset = 2 + 2*stride; + } else { + src_block = src; + src_offset = s->block_offset[b] + dy*stride + dx; + } + + if (deblock_filtering) + vp56_deblock_filter(s, src_block, stride, dx&7, dy&7); + + if (s->mv[b].x & mask) + overlap_offset += (s->mv[b].x > 0) ? 1 : -1; + if (s->mv[b].y & mask) + overlap_offset += (s->mv[b].y > 0) ? stride : -stride; + + if (overlap_offset) { + if (s->filter) + s->filter(s, dst, src_block, src_offset, src_offset+overlap_offset, + stride, s->mv[b], mask, s->filter_selection, b<4); + else + s->vp3dsp.put_no_rnd_pixels_l2(dst, src_block+src_offset, + src_block+src_offset+overlap_offset, + stride, 8); + } else { + s->hdsp.put_pixels_tab[1][0](dst, src_block+src_offset, stride, 8); + } +} + +static void vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha) +{ + AVFrame *frame_current, *frame_ref; + VP56mb mb_type; + VP56Frame ref_frame; + int b, ab, b_max, plane, off; + + if (s->frames[VP56_FRAME_CURRENT]->key_frame) + mb_type = VP56_MB_INTRA; + else + mb_type = vp56_decode_mv(s, row, col); + ref_frame = vp56_reference_frame[mb_type]; + + s->parse_coeff(s); + + vp56_add_predictors_dc(s, ref_frame); + + frame_current = s->frames[VP56_FRAME_CURRENT]; + frame_ref = s->frames[ref_frame]; + if (mb_type != VP56_MB_INTRA && !frame_ref->data[0]) + return; + + ab = 6*is_alpha; + b_max = 6 - 2*is_alpha; + + switch (mb_type) { + case VP56_MB_INTRA: + for (b=0; bvp3dsp.idct_put(frame_current->data[plane] + s->block_offset[b], + s->stride[plane], s->block_coeff[b]); + } + break; + + case VP56_MB_INTER_NOVEC_PF: + case VP56_MB_INTER_NOVEC_GF: + for (b=0; bblock_offset[b]; + s->hdsp.put_pixels_tab[1][0](frame_current->data[plane] + off, + frame_ref->data[plane] + off, + s->stride[plane], 8); + s->vp3dsp.idct_add(frame_current->data[plane] + off, + s->stride[plane], s->block_coeff[b]); + } + break; + + case VP56_MB_INTER_DELTA_PF: + case VP56_MB_INTER_V1_PF: + case VP56_MB_INTER_V2_PF: + case VP56_MB_INTER_DELTA_GF: + case VP56_MB_INTER_4V: + case VP56_MB_INTER_V1_GF: + case VP56_MB_INTER_V2_GF: + for (b=0; bdata[plane], s->stride[plane], + 16*col+x_off, 16*row+y_off); + s->vp3dsp.idct_add(frame_current->data[plane] + s->block_offset[b], + s->stride[plane], s->block_coeff[b]); + } + break; + } + + if (is_alpha) { + s->block_coeff[4][0] = 0; + s->block_coeff[5][0] = 0; + } +} + +static int vp56_size_changed(VP56Context *s) +{ + AVCodecContext *avctx = s->avctx; + int stride = s->frames[VP56_FRAME_CURRENT]->linesize[0]; + int i; + + s->plane_width[0] = s->plane_width[3] = avctx->coded_width; + s->plane_width[1] = s->plane_width[2] = avctx->coded_width/2; + s->plane_height[0] = s->plane_height[3] = avctx->coded_height; + s->plane_height[1] = s->plane_height[2] = avctx->coded_height/2; + + for (i=0; i<4; i++) + s->stride[i] = s->flip * s->frames[VP56_FRAME_CURRENT]->linesize[i]; + + s->mb_width = (avctx->coded_width +15) / 16; + s->mb_height = (avctx->coded_height+15) / 16; + + if (s->mb_width > 1000 || s->mb_height > 1000) { + avcodec_set_dimensions(avctx, 0, 0); + av_log(avctx, AV_LOG_ERROR, "picture too big\n"); + return -1; + } + + s->above_blocks = av_realloc(s->above_blocks, + (4*s->mb_width+6) * sizeof(*s->above_blocks)); + s->macroblocks = av_realloc(s->macroblocks, + s->mb_width*s->mb_height*sizeof(*s->macroblocks)); + av_free(s->edge_emu_buffer_alloc); + s->edge_emu_buffer_alloc = av_malloc(16*stride); + s->edge_emu_buffer = s->edge_emu_buffer_alloc; + if (s->flip < 0) + s->edge_emu_buffer += 15 * stride; + + if (s->alpha_context) + return vp56_size_changed(s->alpha_context); + + return 0; +} + +static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *, int, int); + +int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + VP56Context *s = avctx->priv_data; + AVFrame *const p = s->frames[VP56_FRAME_CURRENT]; + int remaining_buf_size = avpkt->size; + int av_uninit(alpha_offset); + int i, res; + int ret; + + if (s->has_alpha) { + if (remaining_buf_size < 3) + return -1; + alpha_offset = bytestream_get_be24(&buf); + remaining_buf_size -= 3; + if (remaining_buf_size < alpha_offset) + return -1; + } + + res = s->parse_header(s, buf, remaining_buf_size); + if (res < 0) + return res; + + if (res == VP56_SIZE_CHANGE) { + for (i = 0; i < 4; i++) { + av_frame_unref(s->frames[i]); + if (s->alpha_context) + av_frame_unref(s->alpha_context->frames[i]); + } + } + + if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) + return -1; + + if (s->has_alpha) { + av_frame_unref(s->alpha_context->frames[VP56_FRAME_CURRENT]); + if ((ret = av_frame_ref(s->alpha_context->frames[VP56_FRAME_CURRENT], p)) < 0) { + av_frame_unref(p); + return ret; + } + } + + if (res == VP56_SIZE_CHANGE) { + if (vp56_size_changed(s)) { + av_frame_unref(p); + return -1; + } + } + + if (s->has_alpha) { + int bak_w = avctx->width; + int bak_h = avctx->height; + int bak_cw = avctx->coded_width; + int bak_ch = avctx->coded_height; + buf += alpha_offset; + remaining_buf_size -= alpha_offset; + + res = s->alpha_context->parse_header(s->alpha_context, buf, remaining_buf_size); + if (res != 0) { + if(res==VP56_SIZE_CHANGE) { + av_log(avctx, AV_LOG_ERROR, "Alpha reconfiguration\n"); + avctx->width = bak_w; + avctx->height = bak_h; + avctx->coded_width = bak_cw; + avctx->coded_height = bak_ch; + } + av_frame_unref(p); + return -1; + } + } + + avctx->execute2(avctx, ff_vp56_decode_mbs, 0, 0, s->has_alpha + 1); + + if ((res = av_frame_ref(data, p)) < 0) + return res; + *got_frame = 1; + + return avpkt->size; +} + +static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data, + int jobnr, int threadnr) +{ + VP56Context *s0 = avctx->priv_data; + int is_alpha = (jobnr == 1); + VP56Context *s = is_alpha ? s0->alpha_context : s0; + AVFrame *const p = s->frames[VP56_FRAME_CURRENT]; + int mb_row, mb_col, mb_row_flip, mb_offset = 0; + int block, y, uv, stride_y, stride_uv; + int res; + + if (p->key_frame) { + p->pict_type = AV_PICTURE_TYPE_I; + s->default_models_init(s); + for (block=0; blockmb_height*s->mb_width; block++) + s->macroblocks[block].type = VP56_MB_INTRA; + } else { + p->pict_type = AV_PICTURE_TYPE_P; + vp56_parse_mb_type_models(s); + s->parse_vector_models(s); + s->mb_type = VP56_MB_INTER_NOVEC_PF; + } + + if (s->parse_coeff_models(s)) + goto next; + + memset(s->prev_dc, 0, sizeof(s->prev_dc)); + s->prev_dc[1][VP56_FRAME_CURRENT] = 128; + s->prev_dc[2][VP56_FRAME_CURRENT] = 128; + + for (block=0; block < 4*s->mb_width+6; block++) { + s->above_blocks[block].ref_frame = VP56_FRAME_NONE; + s->above_blocks[block].dc_coeff = 0; + s->above_blocks[block].not_null_dc = 0; + } + s->above_blocks[2*s->mb_width + 2].ref_frame = VP56_FRAME_CURRENT; + s->above_blocks[3*s->mb_width + 4].ref_frame = VP56_FRAME_CURRENT; + + stride_y = p->linesize[0]; + stride_uv = p->linesize[1]; + + if (s->flip < 0) + mb_offset = 7; + + /* main macroblocks loop */ + for (mb_row=0; mb_rowmb_height; mb_row++) { + if (s->flip < 0) + mb_row_flip = s->mb_height - mb_row - 1; + else + mb_row_flip = mb_row; + + for (block=0; block<4; block++) { + s->left_block[block].ref_frame = VP56_FRAME_NONE; + s->left_block[block].dc_coeff = 0; + s->left_block[block].not_null_dc = 0; + } + memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx)); + memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last)); + + s->above_block_idx[0] = 1; + s->above_block_idx[1] = 2; + s->above_block_idx[2] = 1; + s->above_block_idx[3] = 2; + s->above_block_idx[4] = 2*s->mb_width + 2 + 1; + s->above_block_idx[5] = 3*s->mb_width + 4 + 1; + + s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y; + s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y; + s->block_offset[1] = s->block_offset[0] + 8; + s->block_offset[3] = s->block_offset[2] + 8; + s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv; + s->block_offset[5] = s->block_offset[4]; + + for (mb_col=0; mb_colmb_width; mb_col++) { + vp56_decode_mb(s, mb_row, mb_col, is_alpha); + + for (y=0; y<4; y++) { + s->above_block_idx[y] += 2; + s->block_offset[y] += 16; + } + + for (uv=4; uv<6; uv++) { + s->above_block_idx[uv] += 1; + s->block_offset[uv] += 8; + } + } + } + +next: + if (p->key_frame || s->golden_frame) { + av_frame_unref(s->frames[VP56_FRAME_GOLDEN]); + if ((res = av_frame_ref(s->frames[VP56_FRAME_GOLDEN], p)) < 0) + return res; + } + + av_frame_unref(s->frames[VP56_FRAME_PREVIOUS]); + FFSWAP(AVFrame *, s->frames[VP56_FRAME_CURRENT], + s->frames[VP56_FRAME_PREVIOUS]); + return 0; +} + +av_cold int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha) +{ + VP56Context *s = avctx->priv_data; + return ff_vp56_init_context(avctx, s, flip, has_alpha); +} + +av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, + int flip, int has_alpha) +{ + int i; + + s->avctx = avctx; + avctx->pix_fmt = has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; + + ff_h264chroma_init(&s->h264chroma, 8); + ff_hpeldsp_init(&s->hdsp, avctx->flags); + ff_videodsp_init(&s->vdsp, 8); + ff_vp3dsp_init(&s->vp3dsp, avctx->flags); + ff_vp56dsp_init(&s->vp56dsp, avctx->codec->id); + for (i = 0; i < 64; i++) { +#define T(x) (x >> 3) | ((x & 7) << 3) + s->idct_scantable[i] = T(ff_zigzag_direct[i]); +#undef T + } + + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) { + s->frames[i] = av_frame_alloc(); + if (!s->frames[i]) { + ff_vp56_free(avctx); + return AVERROR(ENOMEM); + } + } + s->edge_emu_buffer_alloc = NULL; + + s->above_blocks = NULL; + s->macroblocks = NULL; + s->quantizer = -1; + s->deblock_filtering = 1; + s->golden_frame = 0; + + s->filter = NULL; + + s->has_alpha = has_alpha; + + s->modelp = &s->model; + + if (flip) { + s->flip = -1; + s->frbi = 2; + s->srbi = 0; + } else { + s->flip = 1; + s->frbi = 0; + s->srbi = 2; + } + + return 0; +} + +av_cold int ff_vp56_free(AVCodecContext *avctx) +{ + VP56Context *s = avctx->priv_data; + return ff_vp56_free_context(s); +} + +av_cold int ff_vp56_free_context(VP56Context *s) +{ + int i; + + av_freep(&s->above_blocks); + av_freep(&s->macroblocks); + av_freep(&s->edge_emu_buffer_alloc); + + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) + av_frame_free(&s->frames[i]); + + return 0; +} diff --git a/ffmpeg/libavcodec/vp56.h b/ffmpeg/libavcodec/vp56.h new file mode 100644 index 0000000..4b0f5e1 --- /dev/null +++ b/ffmpeg/libavcodec/vp56.h @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP5 and VP6 compatible video decoder (common features) + */ + +#ifndef AVCODEC_VP56_H +#define AVCODEC_VP56_H + +#include "vp56data.h" +#include "dsputil.h" +#include "get_bits.h" +#include "hpeldsp.h" +#include "bytestream.h" +#include "h264chroma.h" +#include "videodsp.h" +#include "vp3dsp.h" +#include "vp56dsp.h" + +typedef struct vp56_context VP56Context; + +typedef struct VP56mv { + DECLARE_ALIGNED(4, int16_t, x); + int16_t y; +} VP56mv; + +#define VP56_SIZE_CHANGE 1 + +typedef void (*VP56ParseVectorAdjustment)(VP56Context *s, + VP56mv *vect); +typedef void (*VP56Filter)(VP56Context *s, uint8_t *dst, uint8_t *src, + int offset1, int offset2, int stride, + VP56mv mv, int mask, int select, int luma); +typedef void (*VP56ParseCoeff)(VP56Context *s); +typedef void (*VP56DefaultModelsInit)(VP56Context *s); +typedef void (*VP56ParseVectorModels)(VP56Context *s); +typedef int (*VP56ParseCoeffModels)(VP56Context *s); +typedef int (*VP56ParseHeader)(VP56Context *s, const uint8_t *buf, + int buf_size); + +typedef struct VP56RangeCoder { + int high; + int bits; /* stored negated (i.e. negative "bits" is a positive number of + bits left) in order to eliminate a negate in cache refilling */ + const uint8_t *buffer; + const uint8_t *end; + unsigned int code_word; +} VP56RangeCoder; + +typedef struct VP56RefDc { + uint8_t not_null_dc; + VP56Frame ref_frame; + int16_t dc_coeff; +} VP56RefDc; + +typedef struct VP56Macroblock { + uint8_t type; + VP56mv mv; +} VP56Macroblock; + +typedef struct VP56Model { + uint8_t coeff_reorder[64]; /* used in vp6 only */ + uint8_t coeff_index_to_pos[64]; /* used in vp6 only */ + uint8_t vector_sig[2]; /* delta sign */ + uint8_t vector_dct[2]; /* delta coding types */ + uint8_t vector_pdi[2][2]; /* predefined delta init */ + uint8_t vector_pdv[2][7]; /* predefined delta values */ + uint8_t vector_fdv[2][8]; /* 8 bit delta value definition */ + uint8_t coeff_dccv[2][11]; /* DC coeff value */ + uint8_t coeff_ract[2][3][6][11]; /* Run/AC coding type and AC coeff value */ + uint8_t coeff_acct[2][3][3][6][5];/* vp5 only AC coding type for coding group < 3 */ + uint8_t coeff_dcct[2][36][5]; /* DC coeff coding type */ + uint8_t coeff_runv[2][14]; /* run value (vp6 only) */ + uint8_t mb_type[3][10][10]; /* model for decoding MB type */ + uint8_t mb_types_stats[3][10][2];/* contextual, next MB type stats */ +} VP56Model; + +struct vp56_context { + AVCodecContext *avctx; + H264ChromaContext h264chroma; + HpelDSPContext hdsp; + VideoDSPContext vdsp; + VP3DSPContext vp3dsp; + VP56DSPContext vp56dsp; + uint8_t idct_scantable[64]; + AVFrame *frames[4]; + uint8_t *edge_emu_buffer_alloc; + uint8_t *edge_emu_buffer; + VP56RangeCoder c; + VP56RangeCoder cc; + VP56RangeCoder *ccp; + int sub_version; + + /* frame info */ + int golden_frame; + int plane_width[4]; + int plane_height[4]; + int mb_width; /* number of horizontal MB */ + int mb_height; /* number of vertical MB */ + int block_offset[6]; + + int quantizer; + uint16_t dequant_dc; + uint16_t dequant_ac; + + /* DC predictors management */ + VP56RefDc *above_blocks; + VP56RefDc left_block[4]; + int above_block_idx[6]; + int16_t prev_dc[3][3]; /* [plan][ref_frame] */ + + /* blocks / macroblock */ + VP56mb mb_type; + VP56Macroblock *macroblocks; + DECLARE_ALIGNED(16, int16_t, block_coeff)[6][64]; + + /* motion vectors */ + VP56mv mv[6]; /* vectors for each block in MB */ + VP56mv vector_candidate[2]; + int vector_candidate_pos; + + /* filtering hints */ + int filter_header; /* used in vp6 only */ + int deblock_filtering; + int filter_selection; + int filter_mode; + int max_vector_length; + int sample_variance_threshold; + + uint8_t coeff_ctx[4][64]; /* used in vp5 only */ + uint8_t coeff_ctx_last[4]; /* used in vp5 only */ + + int has_alpha; + + /* upside-down flipping hints */ + int flip; /* are we flipping ? */ + int frbi; /* first row block index in MB */ + int srbi; /* second row block index in MB */ + int stride[4]; /* stride for each plan */ + + const uint8_t *vp56_coord_div; + VP56ParseVectorAdjustment parse_vector_adjustment; + VP56Filter filter; + VP56ParseCoeff parse_coeff; + VP56DefaultModelsInit default_models_init; + VP56ParseVectorModels parse_vector_models; + VP56ParseCoeffModels parse_coeff_models; + VP56ParseHeader parse_header; + + /* for "slice" parallelism between YUV and A */ + VP56Context *alpha_context; + + VP56Model *modelp; + VP56Model model; + + /* huffman decoding */ + int use_huffman; + GetBitContext gb; + VLC dccv_vlc[2]; + VLC runv_vlc[2]; + VLC ract_vlc[2][3][6]; + unsigned int nb_null[2][2]; /* number of consecutive NULL DC/AC */ +}; + + +int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha); +int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, + int flip, int has_alpha); +int ff_vp56_free(AVCodecContext *avctx); +int ff_vp56_free_context(VP56Context *s); +void ff_vp56_init_dequant(VP56Context *s, int quantizer); +int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt); + + +/** + * vp56 specific range coder implementation + */ + +extern const uint8_t ff_vp56_norm_shift[256]; +void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size); + +static av_always_inline unsigned int vp56_rac_renorm(VP56RangeCoder *c) +{ + int shift = ff_vp56_norm_shift[c->high]; + int bits = c->bits; + unsigned int code_word = c->code_word; + + c->high <<= shift; + code_word <<= shift; + bits += shift; + if(bits >= 0 && c->buffer < c->end) { + code_word |= bytestream_get_be16(&c->buffer) << bits; + bits -= 16; + } + c->bits = bits; + return code_word; +} + +#if ARCH_ARM +#include "arm/vp56_arith.h" +#elif ARCH_X86 +#include "x86/vp56_arith.h" +#endif + +#ifndef vp56_rac_get_prob +#define vp56_rac_get_prob vp56_rac_get_prob +static av_always_inline int vp56_rac_get_prob(VP56RangeCoder *c, uint8_t prob) +{ + unsigned int code_word = vp56_rac_renorm(c); + unsigned int low = 1 + (((c->high - 1) * prob) >> 8); + unsigned int low_shift = low << 16; + int bit = code_word >= low_shift; + + c->high = bit ? c->high - low : low; + c->code_word = bit ? code_word - low_shift : code_word; + + return bit; +} +#endif + +#ifndef vp56_rac_get_prob_branchy +// branchy variant, to be used where there's a branch based on the bit decoded +static av_always_inline int vp56_rac_get_prob_branchy(VP56RangeCoder *c, int prob) +{ + unsigned long code_word = vp56_rac_renorm(c); + unsigned low = 1 + (((c->high - 1) * prob) >> 8); + unsigned low_shift = low << 16; + + if (code_word >= low_shift) { + c->high -= low; + c->code_word = code_word - low_shift; + return 1; + } + + c->high = low; + c->code_word = code_word; + return 0; +} +#endif + +static av_always_inline int vp56_rac_get(VP56RangeCoder *c) +{ + unsigned int code_word = vp56_rac_renorm(c); + /* equiprobable */ + int low = (c->high + 1) >> 1; + unsigned int low_shift = low << 16; + int bit = code_word >= low_shift; + if (bit) { + c->high -= low; + code_word -= low_shift; + } else { + c->high = low; + } + + c->code_word = code_word; + return bit; +} + +// rounding is different than vp56_rac_get, is vp56_rac_get wrong? +static av_always_inline int vp8_rac_get(VP56RangeCoder *c) +{ + return vp56_rac_get_prob(c, 128); +} + +static av_unused int vp56_rac_gets(VP56RangeCoder *c, int bits) +{ + int value = 0; + + while (bits--) { + value = (value << 1) | vp56_rac_get(c); + } + + return value; +} + +static av_unused int vp8_rac_get_uint(VP56RangeCoder *c, int bits) +{ + int value = 0; + + while (bits--) { + value = (value << 1) | vp8_rac_get(c); + } + + return value; +} + +// fixme: add 1 bit to all the calls to this? +static av_unused int vp8_rac_get_sint(VP56RangeCoder *c, int bits) +{ + int v; + + if (!vp8_rac_get(c)) + return 0; + + v = vp8_rac_get_uint(c, bits); + + if (vp8_rac_get(c)) + v = -v; + + return v; +} + +// P(7) +static av_unused int vp56_rac_gets_nn(VP56RangeCoder *c, int bits) +{ + int v = vp56_rac_gets(c, 7) << 1; + return v + !v; +} + +static av_unused int vp8_rac_get_nn(VP56RangeCoder *c) +{ + int v = vp8_rac_get_uint(c, 7) << 1; + return v + !v; +} + +static av_always_inline +int vp56_rac_get_tree(VP56RangeCoder *c, + const VP56Tree *tree, + const uint8_t *probs) +{ + while (tree->val > 0) { + if (vp56_rac_get_prob(c, probs[tree->prob_idx])) + tree += tree->val; + else + tree++; + } + return -tree->val; +} + +// how probabilities are associated with decisions is different I think +// well, the new scheme fits in the old but this way has one fewer branches per decision +static av_always_inline int vp8_rac_get_tree(VP56RangeCoder *c, const int8_t (*tree)[2], + const uint8_t *probs) +{ + int i = 0; + + do { + i = tree[i][vp56_rac_get_prob(c, probs[i])]; + } while (i > 0); + + return -i; +} + +// DCTextra +static av_always_inline int vp8_rac_get_coeff(VP56RangeCoder *c, const uint8_t *prob) +{ + int v = 0; + + do { + v = (v<<1) + vp56_rac_get_prob(c, *prob++); + } while (*prob); + + return v; +} + +#endif /* AVCODEC_VP56_H */ diff --git a/ffmpeg/libavcodec/vp56data.c b/ffmpeg/libavcodec/vp56data.c new file mode 100644 index 0000000..5500fe0 --- /dev/null +++ b/ffmpeg/libavcodec/vp56data.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP5 and VP6 compatible video decoder (common data) + */ + +#include "vp56data.h" + +const uint8_t ff_vp56_b2p[] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3 }; +const uint8_t ff_vp56_b6to4[] = { 0, 0, 1, 1, 2, 3 }; + +const uint8_t ff_vp56_coeff_parse_table[6][11] = { + { 159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 145, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 140, 148, 173, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 135, 140, 155, 176, 0, 0, 0, 0, 0, 0, 0 }, + { 130, 134, 141, 157, 180, 0, 0, 0, 0, 0, 0 }, + { 129, 130, 133, 140, 153, 177, 196, 230, 243, 254, 254 }, +}; + +const uint8_t ff_vp56_def_mb_types_stats[3][10][2] = { + { { 69, 42 }, { 1, 2 }, { 1, 7 }, { 44, 42 }, { 6, 22 }, + { 1, 3 }, { 0, 2 }, { 1, 5 }, { 0, 1 }, { 0, 0 }, }, + { { 229, 8 }, { 1, 1 }, { 0, 8 }, { 0, 0 }, { 0, 0 }, + { 1, 2 }, { 0, 1 }, { 0, 0 }, { 1, 1 }, { 0, 0 }, }, + { { 122, 35 }, { 1, 1 }, { 1, 6 }, { 46, 34 }, { 0, 0 }, + { 1, 2 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, }, +}; + +const VP56Tree ff_vp56_pva_tree[] = { + { 8, 0}, + { 4, 1}, + { 2, 2}, {-0}, {-1}, + { 2, 3}, {-2}, {-3}, + { 4, 4}, + { 2, 5}, {-4}, {-5}, + { 2, 6}, {-6}, {-7}, +}; + +const VP56Tree ff_vp56_pc_tree[] = { + { 4, 6}, + { 2, 7}, {-0}, {-1}, + { 4, 8}, + { 2, 9}, {-2}, {-3}, + { 2,10}, {-4}, {-5}, +}; + +const uint8_t ff_vp56_coeff_bias[] = { 0, 1, 2, 3, 4, 5, 7, 11, 19, 35, 67 }; +const uint8_t ff_vp56_coeff_bit_length[] = { 0, 1, 2, 3, 4, 10 }; diff --git a/ffmpeg/libavcodec/vp56data.h b/ffmpeg/libavcodec/vp56data.h new file mode 100644 index 0000000..3cafaaf --- /dev/null +++ b/ffmpeg/libavcodec/vp56data.h @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP5 and VP6 compatible video decoder (common data) + */ + +#ifndef AVCODEC_VP56DATA_H +#define AVCODEC_VP56DATA_H + +#include "libavutil/common.h" + +typedef enum { + VP56_FRAME_NONE =-1, + VP56_FRAME_CURRENT = 0, + VP56_FRAME_PREVIOUS = 1, + VP56_FRAME_GOLDEN = 2, + VP56_FRAME_GOLDEN2 = 3, +} VP56Frame; + +typedef enum { + VP56_MB_INTER_NOVEC_PF = 0, /**< Inter MB, no vector, from previous frame */ + VP56_MB_INTRA = 1, /**< Intra MB */ + VP56_MB_INTER_DELTA_PF = 2, /**< Inter MB, above/left vector + delta, from previous frame */ + VP56_MB_INTER_V1_PF = 3, /**< Inter MB, first vector, from previous frame */ + VP56_MB_INTER_V2_PF = 4, /**< Inter MB, second vector, from previous frame */ + VP56_MB_INTER_NOVEC_GF = 5, /**< Inter MB, no vector, from golden frame */ + VP56_MB_INTER_DELTA_GF = 6, /**< Inter MB, above/left vector + delta, from golden frame */ + VP56_MB_INTER_4V = 7, /**< Inter MB, 4 vectors, from previous frame */ + VP56_MB_INTER_V1_GF = 8, /**< Inter MB, first vector, from golden frame */ + VP56_MB_INTER_V2_GF = 9, /**< Inter MB, second vector, from golden frame */ +} VP56mb; + +typedef struct VP56Tree { + int8_t val; + int8_t prob_idx; +} VP56Tree; + +extern const uint8_t ff_vp56_b2p[]; +extern const uint8_t ff_vp56_b6to4[]; +extern const uint8_t ff_vp56_coeff_parse_table[6][11]; +extern const uint8_t ff_vp56_def_mb_types_stats[3][10][2]; +extern const VP56Tree ff_vp56_pva_tree[]; +extern const VP56Tree ff_vp56_pc_tree[]; +extern const uint8_t ff_vp56_coeff_bias[]; +extern const uint8_t ff_vp56_coeff_bit_length[]; + +static const VP56Frame vp56_reference_frame[] = { + VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_NOVEC_PF */ + VP56_FRAME_CURRENT, /* VP56_MB_INTRA */ + VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_DELTA_PF */ + VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_V1_PF */ + VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_V2_PF */ + VP56_FRAME_GOLDEN, /* VP56_MB_INTER_NOVEC_GF */ + VP56_FRAME_GOLDEN, /* VP56_MB_INTER_DELTA_GF */ + VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_4V */ + VP56_FRAME_GOLDEN, /* VP56_MB_INTER_V1_GF */ + VP56_FRAME_GOLDEN, /* VP56_MB_INTER_V2_GF */ +}; + +static const uint8_t vp56_ac_dequant[64] = { + 94, 92, 90, 88, 86, 82, 78, 74, + 70, 66, 62, 58, 54, 53, 52, 51, + 50, 49, 48, 47, 46, 45, 44, 43, + 42, 40, 39, 37, 36, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1, +}; + +static const uint8_t vp56_dc_dequant[64] = { + 47, 47, 47, 47, 45, 43, 43, 43, + 43, 43, 42, 41, 41, 40, 40, 40, + 40, 35, 35, 35, 35, 33, 33, 33, + 33, 32, 32, 32, 27, 27, 26, 26, + 25, 25, 24, 24, 23, 23, 19, 19, + 19, 19, 18, 18, 17, 16, 16, 16, + 16, 16, 15, 11, 11, 11, 10, 10, + 9, 8, 7, 5, 3, 3, 2, 2, +}; + +static const uint8_t vp56_pre_def_mb_type_stats[16][3][10][2] = { + { { { 9, 15 }, { 32, 25 }, { 7, 19 }, { 9, 21 }, { 1, 12 }, + { 14, 12 }, { 3, 18 }, { 14, 23 }, { 3, 10 }, { 0, 4 }, }, + { { 41, 22 }, { 1, 0 }, { 1, 31 }, { 0, 0 }, { 0, 0 }, + { 0, 1 }, { 1, 7 }, { 0, 1 }, { 98, 25 }, { 4, 10 }, }, + { { 2, 3 }, { 2, 3 }, { 0, 2 }, { 0, 2 }, { 0, 0 }, + { 11, 4 }, { 1, 4 }, { 0, 2 }, { 3, 2 }, { 0, 4 }, }, }, + { { { 48, 39 }, { 1, 2 }, { 11, 27 }, { 29, 44 }, { 7, 27 }, + { 1, 4 }, { 0, 3 }, { 1, 6 }, { 1, 2 }, { 0, 0 }, }, + { { 123, 37 }, { 6, 4 }, { 1, 27 }, { 0, 0 }, { 0, 0 }, + { 5, 8 }, { 1, 7 }, { 0, 1 }, { 12, 10 }, { 0, 2 }, }, + { { 49, 46 }, { 3, 4 }, { 7, 31 }, { 42, 41 }, { 0, 0 }, + { 2, 6 }, { 1, 7 }, { 1, 4 }, { 2, 4 }, { 0, 1 }, }, }, + { { { 21, 32 }, { 1, 2 }, { 4, 10 }, { 32, 43 }, { 6, 23 }, + { 2, 3 }, { 1, 19 }, { 1, 6 }, { 12, 21 }, { 0, 7 }, }, + { { 26, 14 }, { 14, 12 }, { 0, 24 }, { 0, 0 }, { 0, 0 }, + { 55, 17 }, { 1, 9 }, { 0, 36 }, { 5, 7 }, { 1, 3 }, }, + { { 26, 25 }, { 1, 1 }, { 2, 10 }, { 67, 39 }, { 0, 0 }, + { 1, 1 }, { 0, 14 }, { 0, 2 }, { 31, 26 }, { 1, 6 }, }, }, + { { { 69, 83 }, { 0, 0 }, { 0, 2 }, { 10, 29 }, { 3, 12 }, + { 0, 1 }, { 0, 3 }, { 0, 3 }, { 2, 2 }, { 0, 0 }, }, + { { 209, 5 }, { 0, 0 }, { 0, 27 }, { 0, 0 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, }, + { { 103, 46 }, { 1, 2 }, { 2, 10 }, { 33, 42 }, { 0, 0 }, + { 1, 4 }, { 0, 3 }, { 0, 1 }, { 1, 3 }, { 0, 0 }, }, }, + { { { 11, 20 }, { 1, 4 }, { 18, 36 }, { 43, 48 }, { 13, 35 }, + { 0, 2 }, { 0, 5 }, { 3, 12 }, { 1, 2 }, { 0, 0 }, }, + { { 2, 5 }, { 4, 5 }, { 0, 121 }, { 0, 0 }, { 0, 0 }, + { 0, 3 }, { 2, 4 }, { 1, 4 }, { 2, 2 }, { 0, 1 }, }, + { { 14, 31 }, { 9, 13 }, { 14, 54 }, { 22, 29 }, { 0, 0 }, + { 2, 6 }, { 4, 18 }, { 6, 13 }, { 1, 5 }, { 0, 1 }, }, }, + { { { 70, 44 }, { 0, 1 }, { 2, 10 }, { 37, 46 }, { 8, 26 }, + { 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 1 }, { 0, 0 }, }, + { { 175, 5 }, { 0, 1 }, { 0, 48 }, { 0, 0 }, { 0, 0 }, + { 0, 2 }, { 0, 1 }, { 0, 2 }, { 0, 1 }, { 0, 0 }, }, + { { 85, 39 }, { 0, 0 }, { 1, 9 }, { 69, 40 }, { 0, 0 }, + { 0, 1 }, { 0, 3 }, { 0, 1 }, { 2, 3 }, { 0, 0 }, }, }, + { { { 8, 15 }, { 0, 1 }, { 8, 21 }, { 74, 53 }, { 22, 42 }, + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 0, 0 }, }, + { { 83, 5 }, { 2, 3 }, { 0, 102 }, { 0, 0 }, { 0, 0 }, + { 1, 3 }, { 0, 2 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, }, + { { 31, 28 }, { 0, 0 }, { 3, 14 }, { 130, 34 }, { 0, 0 }, + { 0, 1 }, { 0, 3 }, { 0, 1 }, { 3, 3 }, { 0, 1 }, }, }, + { { { 141, 42 }, { 0, 0 }, { 1, 4 }, { 11, 24 }, { 1, 11 }, + { 0, 1 }, { 0, 1 }, { 0, 2 }, { 0, 0 }, { 0, 0 }, }, + { { 233, 6 }, { 0, 0 }, { 0, 8 }, { 0, 0 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 1 }, { 0, 0 }, }, + { { 171, 25 }, { 0, 0 }, { 1, 5 }, { 25, 21 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, }, }, + { { { 8, 19 }, { 4, 10 }, { 24, 45 }, { 21, 37 }, { 9, 29 }, + { 0, 3 }, { 1, 7 }, { 11, 25 }, { 0, 2 }, { 0, 1 }, }, + { { 34, 16 }, { 112, 21 }, { 1, 28 }, { 0, 0 }, { 0, 0 }, + { 6, 8 }, { 1, 7 }, { 0, 3 }, { 2, 5 }, { 0, 2 }, }, + { { 17, 21 }, { 68, 29 }, { 6, 15 }, { 13, 22 }, { 0, 0 }, + { 6, 12 }, { 3, 14 }, { 4, 10 }, { 1, 7 }, { 0, 3 }, }, }, + { { { 46, 42 }, { 0, 1 }, { 2, 10 }, { 54, 51 }, { 10, 30 }, + { 0, 2 }, { 0, 2 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, }, + { { 159, 35 }, { 2, 2 }, { 0, 25 }, { 0, 0 }, { 0, 0 }, + { 3, 6 }, { 0, 5 }, { 0, 1 }, { 4, 4 }, { 0, 1 }, }, + { { 51, 39 }, { 0, 1 }, { 2, 12 }, { 91, 44 }, { 0, 0 }, + { 0, 2 }, { 0, 3 }, { 0, 1 }, { 2, 3 }, { 0, 1 }, }, }, + { { { 28, 32 }, { 0, 0 }, { 3, 10 }, { 75, 51 }, { 14, 33 }, + { 0, 1 }, { 0, 2 }, { 0, 1 }, { 1, 2 }, { 0, 0 }, }, + { { 75, 39 }, { 5, 7 }, { 2, 48 }, { 0, 0 }, { 0, 0 }, + { 3, 11 }, { 2, 16 }, { 1, 4 }, { 7, 10 }, { 0, 2 }, }, + { { 81, 25 }, { 0, 0 }, { 2, 9 }, { 106, 26 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, }, }, + { { { 100, 46 }, { 0, 1 }, { 3, 9 }, { 21, 37 }, { 5, 20 }, + { 0, 1 }, { 0, 2 }, { 1, 2 }, { 0, 1 }, { 0, 0 }, }, + { { 212, 21 }, { 0, 1 }, { 0, 9 }, { 0, 0 }, { 0, 0 }, + { 1, 2 }, { 0, 2 }, { 0, 0 }, { 2, 2 }, { 0, 0 }, }, + { { 140, 37 }, { 0, 1 }, { 1, 8 }, { 24, 33 }, { 0, 0 }, + { 1, 2 }, { 0, 2 }, { 0, 1 }, { 1, 2 }, { 0, 0 }, }, }, + { { { 27, 29 }, { 0, 1 }, { 9, 25 }, { 53, 51 }, { 12, 34 }, + { 0, 1 }, { 0, 3 }, { 1, 5 }, { 0, 2 }, { 0, 0 }, }, + { { 4, 2 }, { 0, 0 }, { 0, 172 }, { 0, 0 }, { 0, 0 }, + { 0, 1 }, { 0, 2 }, { 0, 0 }, { 2, 0 }, { 0, 0 }, }, + { { 14, 23 }, { 1, 3 }, { 11, 53 }, { 90, 31 }, { 0, 0 }, + { 0, 3 }, { 1, 5 }, { 2, 6 }, { 1, 2 }, { 0, 0 }, }, }, + { { { 80, 38 }, { 0, 0 }, { 1, 4 }, { 69, 33 }, { 5, 16 }, + { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 1 }, { 0, 0 }, }, + { { 187, 22 }, { 1, 1 }, { 0, 17 }, { 0, 0 }, { 0, 0 }, + { 3, 6 }, { 0, 4 }, { 0, 1 }, { 4, 4 }, { 0, 1 }, }, + { { 123, 29 }, { 0, 0 }, { 1, 7 }, { 57, 30 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, }, }, + { { { 16, 20 }, { 0, 0 }, { 2, 8 }, { 104, 49 }, { 15, 33 }, + { 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, }, + { { 133, 6 }, { 1, 2 }, { 1, 70 }, { 0, 0 }, { 0, 0 }, + { 0, 2 }, { 0, 4 }, { 0, 3 }, { 1, 1 }, { 0, 0 }, }, + { { 13, 14 }, { 0, 0 }, { 4, 20 }, { 175, 20 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, }, }, + { { { 194, 16 }, { 0, 0 }, { 1, 1 }, { 1, 9 }, { 1, 3 }, + { 0, 0 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, }, + { { 251, 1 }, { 0, 0 }, { 0, 2 }, { 0, 0 }, { 0, 0 }, + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, }, + { { 202, 23 }, { 0, 0 }, { 1, 3 }, { 2, 9 }, { 0, 0 }, + { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, }, }, +}; + +static const uint8_t vp56_filter_threshold[] = { + 14, 14, 13, 13, 12, 12, 10, 10, + 10, 10, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 7, 7, 7, 7, + 7, 7, 6, 6, 6, 6, 6, 6, + 5, 5, 5, 5, 4, 4, 4, 4, + 4, 4, 4, 3, 3, 3, 3, 2, +}; + +static const uint8_t vp56_mb_type_model_model[] = { + 171, 83, 199, 140, 125, 104, +}; + +static const VP56Tree vp56_pmbtm_tree[] = { + { 4, 0}, + { 2, 1}, {-8}, {-4}, + { 8, 2}, + { 6, 3}, + { 4, 4}, + { 2, 5}, {-24}, {-20}, {-16}, {-12}, {-0}, +}; + +static const VP56Tree vp56_pmbt_tree[] = { + { 8, 1}, + { 4, 2}, + { 2, 4}, {-VP56_MB_INTER_NOVEC_PF}, {-VP56_MB_INTER_DELTA_PF}, + { 2, 5}, {-VP56_MB_INTER_V1_PF}, {-VP56_MB_INTER_V2_PF}, + { 4, 3}, + { 2, 6}, {-VP56_MB_INTRA}, {-VP56_MB_INTER_4V}, + { 4, 7}, + { 2, 8}, {-VP56_MB_INTER_NOVEC_GF}, {-VP56_MB_INTER_DELTA_GF}, + { 2, 9}, {-VP56_MB_INTER_V1_GF}, {-VP56_MB_INTER_V2_GF}, +}; + +/* relative pos of surrounding blocks, from closest to farthest */ +static const int8_t vp56_candidate_predictor_pos[12][2] = { + { 0, -1 }, + { -1, 0 }, + { -1, -1 }, + { 1, -1 }, + { 0, -2 }, + { -2, 0 }, + { -2, -1 }, + { -1, -2 }, + { 1, -2 }, + { 2, -1 }, + { -2, -2 }, + { 2, -2 }, +}; + +#endif /* AVCODEC_VP56DATA_H */ diff --git a/ffmpeg/libavcodec/vp56dsp.c b/ffmpeg/libavcodec/vp56dsp.c new file mode 100644 index 0000000..a72c48e --- /dev/null +++ b/ffmpeg/libavcodec/vp56dsp.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006 Aurelien Jacobs + * Copyright (c) 2010 Mans Rullgard + * + * 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 "avcodec.h" +#include "vp56dsp.h" +#include "libavutil/common.h" + +/* Gives very similar result than the vp6 version except in a few cases */ +static int vp5_adjust(int v, int t) +{ + int s2, s1 = v >> 31; + v ^= s1; + v -= s1; + v *= v < 2*t; + v -= t; + s2 = v >> 31; + v ^= s2; + v -= s2; + v = t - v; + v += s1; + v ^= s1; + return v; +} + +static int vp6_adjust(int v, int t) +{ + int V = v, s = v >> 31; + V ^= s; + V -= s; + if (V-t-1 >= (unsigned)(t-1)) + return v; + V = 2*t - V; + V += s; + V ^= s; + return V; +} + + +#define VP56_EDGE_FILTER(pfx, suf, pix_inc, line_inc) \ +static void pfx##_edge_filter_##suf(uint8_t *yuv, int stride, int t) \ +{ \ + int pix2_inc = 2 * pix_inc; \ + int i, v; \ + \ + for (i=0; i<12; i++) { \ + v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4)>>3;\ + v = pfx##_adjust(v, t); \ + yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v); \ + yuv[0] = av_clip_uint8(yuv[0] - v); \ + yuv += line_inc; \ + } \ +} + +VP56_EDGE_FILTER(vp5, hor, 1, stride) +VP56_EDGE_FILTER(vp5, ver, stride, 1) +VP56_EDGE_FILTER(vp6, hor, 1, stride) +VP56_EDGE_FILTER(vp6, ver, stride, 1) + +void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec) +{ + if (codec == AV_CODEC_ID_VP5) { + s->edge_filter_hor = vp5_edge_filter_hor; + s->edge_filter_ver = vp5_edge_filter_ver; + } else { + s->edge_filter_hor = vp6_edge_filter_hor; + s->edge_filter_ver = vp6_edge_filter_ver; + + if (CONFIG_VP6_DECODER) { + s->vp6_filter_diag4 = ff_vp6_filter_diag4_c; + } + } + + if (ARCH_ARM) ff_vp56dsp_init_arm(s, codec); + if (ARCH_X86) ff_vp56dsp_init_x86(s, codec); +} diff --git a/ffmpeg/libavcodec/vp56dsp.h b/ffmpeg/libavcodec/vp56dsp.h new file mode 100644 index 0000000..51e8c16 --- /dev/null +++ b/ffmpeg/libavcodec/vp56dsp.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010 Mans Rullgard + * + * 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 + */ + +#ifndef AVCODEC_VP56DSP_H +#define AVCODEC_VP56DSP_H + +#include +#include "avcodec.h" + +typedef struct VP56DSPContext { + void (*edge_filter_hor)(uint8_t *yuv, int stride, int t); + void (*edge_filter_ver)(uint8_t *yuv, int stride, int t); + + void (*vp6_filter_diag4)(uint8_t *dst, uint8_t *src, int stride, + const int16_t *h_weights,const int16_t *v_weights); +} VP56DSPContext; + +void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, int stride, + const int16_t *h_weights, const int16_t *v_weights); + +void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec); +void ff_vp56dsp_init_arm(VP56DSPContext *s, enum AVCodecID codec); +void ff_vp56dsp_init_x86(VP56DSPContext* c, enum AVCodecID codec); + +#endif /* AVCODEC_VP56DSP_H */ diff --git a/ffmpeg/libavcodec/vp56rac.c b/ffmpeg/libavcodec/vp56rac.c new file mode 100644 index 0000000..f11531d --- /dev/null +++ b/ffmpeg/libavcodec/vp56rac.c @@ -0,0 +1,47 @@ +/* + * VP5/6/8 decoder + * Copyright (c) 2010 Jason Garrett-Glaser + * + * 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 "libavutil/common.h" +#include "vp56.h" + +const uint8_t ff_vp56_norm_shift[256]= { + 8,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size) +{ + c->high = 255; + c->bits = -16; + c->buffer = buf; + c->end = buf + buf_size; + c->code_word = bytestream_get_be24(&c->buffer); +} diff --git a/ffmpeg/libavcodec/vp5data.h b/ffmpeg/libavcodec/vp5data.h new file mode 100644 index 0000000..e16ff2d --- /dev/null +++ b/ffmpeg/libavcodec/vp5data.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP5 compatible video decoder + */ + +#ifndef AVCODEC_VP5DATA_H +#define AVCODEC_VP5DATA_H + +#include + +static const uint8_t vp5_coeff_groups[] = { + -1, 0, 1, 1, 2, 1, 1, 2, + 2, 1, 1, 2, 2, 2, 1, 2, + 2, 2, 2, 2, 1, 1, 2, 2, + 3, 3, 4, 3, 4, 4, 4, 3, + 3, 3, 3, 3, 4, 3, 3, 3, + 4, 4, 4, 4, 4, 3, 3, 4, + 4, 4, 3, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, +}; + +static const uint8_t vp5_vmc_pct[2][11] = { + { 243, 220, 251, 253, 237, 232, 241, 245, 247, 251, 253 }, + { 235, 211, 246, 249, 234, 231, 248, 249, 252, 252, 254 }, +}; + +static const uint8_t vp5_dccv_pct[2][11] = { + { 146, 197, 181, 207, 232, 243, 238, 251, 244, 250, 249 }, + { 179, 219, 214, 240, 250, 254, 244, 254, 254, 254, 254 }, +}; + +static const uint8_t vp5_ract_pct[3][2][6][11] = { + { { { 227, 246, 230, 247, 244, 254, 254, 254, 254, 254, 254 }, + { 202, 254, 209, 231, 231, 249, 249, 253, 254, 254, 254 }, + { 206, 254, 225, 242, 241, 251, 253, 254, 254, 254, 254 }, + { 235, 254, 241, 253, 252, 254, 254, 254, 254, 254, 254 }, + { 234, 254, 248, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } }, + { { 240, 254, 248, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 238, 254, 240, 253, 254, 254, 254, 254, 254, 254, 254 }, + { 244, 254, 251, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } } }, + { { { 206, 203, 227, 239, 247, 254, 253, 254, 254, 254, 254 }, + { 207, 199, 220, 236, 243, 252, 252, 254, 254, 254, 254 }, + { 212, 219, 230, 243, 244, 253, 252, 254, 254, 254, 254 }, + { 236, 237, 247, 252, 253, 254, 254, 254, 254, 254, 254 }, + { 240, 240, 248, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } }, + { { 230, 233, 249, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 238, 238, 250, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 248, 251, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } } }, + { { { 225, 239, 227, 231, 244, 253, 243, 254, 254, 253, 254 }, + { 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 254 }, + { 235, 249, 238, 240, 251, 254, 249, 254, 253, 253, 254 }, + { 249, 253, 251, 250, 254, 254, 254, 254, 254, 254, 254 }, + { 251, 250, 249, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } }, + { { 243, 244, 250, 250, 254, 254, 254, 254, 254, 254, 254 }, + { 249, 248, 250, 253, 254, 254, 254, 254, 254, 254, 254 }, + { 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 }, + { 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } } }, +}; + +static const int16_t vp5_dccv_lc[5][36][2] = { + { {154, 61}, {141, 54}, { 90, 45}, { 54, 34}, { 54, 13}, {128, 109}, + {136, 54}, {148, 45}, { 92, 41}, { 54, 33}, { 51, 15}, { 87, 113}, + { 87, 44}, { 97, 40}, { 67, 36}, { 46, 29}, { 41, 15}, { 64, 80}, + { 59, 33}, { 61, 31}, { 51, 28}, { 44, 22}, { 33, 12}, { 49, 63}, + { 69, 12}, { 59, 16}, { 46, 14}, { 31, 13}, { 26, 6}, { 92, 26}, + {128, 108}, { 77, 119}, { 54, 84}, { 26, 71}, { 87, 19}, { 95, 155} }, + { {154, 4}, {182, 0}, {159, -8}, {128, -5}, {143, -5}, {187, 55}, + {182, 0}, {228, -3}, {187, -7}, {174, -9}, {189, -11}, {169, 79}, + {161, -9}, {192, -8}, {187, -9}, {169, -10}, {136, -9}, {184, 40}, + {164, -11}, {179, -10}, {174, -10}, {161, -10}, {115, -7}, {197, 20}, + {195, -11}, {195, -11}, {146, -10}, {110, -6}, { 95, -4}, {195, 39}, + {182, 55}, {172, 77}, {177, 37}, {169, 29}, {172, 52}, { 92, 162} }, + { {174, 80}, {164, 80}, { 95, 80}, { 46, 66}, { 56, 24}, { 36, 193}, + {164, 80}, {166, 77}, {105, 76}, { 49, 68}, { 46, 31}, { 49, 186}, + { 97, 78}, {110, 74}, { 72, 72}, { 44, 60}, { 33, 30}, { 69, 131}, + { 61, 61}, { 69, 63}, { 51, 57}, { 31, 48}, { 26, 27}, { 64, 89}, + { 67, 23}, { 51, 32}, { 36, 33}, { 26, 28}, { 20, 12}, { 44, 68}, + { 26, 197}, { 41, 189}, { 61, 129}, { 28, 103}, { 49, 52}, {-12, 245} }, + { {102, 141}, { 79, 166}, { 72, 162}, { 97, 125}, {179, 4}, {307, 0}, + { 72, 168}, { 69, 175}, { 84, 160}, {105, 127}, {148, 34}, {310, 0}, + { 84, 151}, { 82, 161}, { 87, 153}, { 87, 135}, {115, 51}, {317, 0}, + { 97, 125}, {102, 131}, {105, 125}, { 87, 122}, { 84, 64}, { 54, 184}, + {166, 18}, {146, 43}, {125, 51}, { 90, 64}, { 95, 7}, { 38, 154}, + {294, 0}, { 13, 225}, { 10, 225}, { 67, 168}, { 0, 167}, {161, 94} }, + { {172, 76}, {172, 75}, {136, 80}, { 64, 98}, { 74, 67}, {315, 0}, + {169, 76}, {207, 56}, {164, 66}, { 97, 80}, { 67, 72}, {328, 0}, + {136, 80}, {187, 53}, {154, 62}, { 72, 85}, { -2, 105}, {305, 0}, + { 74, 91}, {128, 64}, {113, 64}, { 61, 77}, { 41, 75}, {259, 0}, + { 46, 84}, { 51, 81}, { 28, 89}, { 31, 78}, { 23, 77}, {202, 0}, + {323, 0}, {323, 0}, {300, 0}, {236, 0}, {195, 0}, {328, 0} }, +}; + +static const int16_t vp5_ract_lc[3][3][5][6][2] = { + { { { {276, 0}, {238, 0}, {195, 0}, {156, 0}, {113, 0}, {274, 0} }, + { { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} }, + { {192, 59}, {182, 50}, {141, 48}, {110, 40}, { 92, 19}, {125,128} }, + { {169, 87}, {169, 83}, {184, 62}, {220, 16}, {184, 0}, {264, 0} }, + { {212, 40}, {212, 36}, {169, 49}, {174, 27}, { 8,120}, {182, 71} } }, + { { {259, 10}, {197, 19}, {143, 22}, {123, 16}, {110, 8}, {133, 88} }, + { { 0, 1}, {256, 0}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} }, + { {207, 46}, {187, 50}, { 97, 83}, { 23,100}, { 41, 56}, { 56,188} }, + { {166, 90}, {146,108}, {161, 88}, {136, 95}, {174, 0}, {266, 0} }, + { {264, 7}, {243, 18}, {184, 43}, {-14,154}, { 20,112}, { 20,199} } }, + { { {230, 26}, {197, 22}, {159, 20}, {146, 12}, {136, 4}, { 54,162} }, + { { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} }, + { {192, 59}, {156, 72}, { 84,101}, { 49,101}, { 79, 47}, { 79,167} }, + { {138,115}, {136,116}, {166, 80}, {238, 0}, {195, 0}, {261, 0} }, + { {225, 33}, {205, 42}, {159, 61}, { 79, 96}, { 92, 66}, { 28,195} } }, + }, { + { { {200, 37}, {197, 18}, {159, 13}, {143, 7}, {102, 5}, {123,126} }, + { {197, 3}, {220, -9}, {210,-12}, {187, -6}, {151, -2}, {174, 80} }, + { {200, 53}, {187, 47}, {159, 40}, {118, 38}, {100, 18}, {141,111} }, + { {179, 78}, {166, 86}, {197, 50}, {207, 27}, {187, 0}, {115,139} }, + { {218, 34}, {220, 29}, {174, 46}, {128, 61}, { 54, 89}, {187, 65} } }, + { { {238, 14}, {197, 18}, {125, 26}, { 90, 25}, { 82, 13}, {161, 86} }, + { {189, 1}, {205, -2}, {156, -4}, {143, -4}, {146, -4}, {172, 72} }, + { {230, 31}, {192, 45}, {102, 76}, { 38, 85}, { 56, 41}, { 64,173} }, + { {166, 91}, {141,111}, {128,116}, {118,109}, {177, 0}, { 23,222} }, + { {253, 14}, {236, 21}, {174, 49}, { 33,118}, { 44, 93}, { 23,187} } }, + { { {218, 28}, {179, 28}, {118, 35}, { 95, 30}, { 72, 24}, {128,108} }, + { {187, 1}, {174, -1}, {125, -1}, {110, -1}, {108, -1}, {202, 52} }, + { {197, 53}, {146, 75}, { 46,118}, { 33,103}, { 64, 50}, {118,126} }, + { {138,114}, {128,122}, {161, 86}, {243, -6}, {195, 0}, { 38,210} }, + { {215, 39}, {179, 58}, { 97,101}, { 95, 85}, { 87, 70}, { 69,152} } }, + }, { + { { {236, 24}, {205, 18}, {172, 12}, {154, 6}, {125, 1}, {169, 75} }, + { {187, 4}, {230, -2}, {228, -4}, {236, -4}, {241, -2}, {192, 66} }, + { {200, 46}, {187, 42}, {159, 34}, {136, 25}, {105, 10}, {179, 62} }, + { {207, 55}, {192, 63}, {192, 54}, {195, 36}, {177, 1}, {143, 98} }, + { {225, 27}, {207, 34}, {200, 30}, {131, 57}, { 97, 60}, {197, 45} } }, + { { {271, 8}, {218, 13}, {133, 19}, { 90, 19}, { 72, 7}, {182, 51} }, + { {179, 1}, {225, -1}, {154, -2}, {110, -1}, { 92, 0}, {195, 41} }, + { {241, 26}, {189, 40}, { 82, 64}, { 33, 60}, { 67, 17}, {120, 94} }, + { {192, 68}, {151, 94}, {146, 90}, {143, 72}, {161, 0}, {113,128} }, + { {256, 12}, {218, 29}, {166, 48}, { 44, 99}, { 31, 87}, {148, 78} } }, + { { {238, 20}, {184, 22}, {113, 27}, { 90, 22}, { 74, 9}, {192, 37} }, + { {184, 0}, {215, -1}, {141, -1}, { 97, 0}, { 49, 0}, {264, 13} }, + { {182, 51}, {138, 61}, { 95, 63}, { 54, 59}, { 64, 25}, {200, 45} }, + { {179, 75}, {156, 87}, {174, 65}, {177, 44}, {174, 0}, {164, 85} }, + { {195, 45}, {148, 65}, {105, 79}, { 95, 72}, { 87, 60}, {169, 63} } }, + } +}; + +static const uint8_t vp5_coord_div[] = { 2, 2, 2, 2, 4, 4 }; + +#endif /* AVCODEC_VP5DATA_H */ diff --git a/ffmpeg/libavcodec/vp6.c b/ffmpeg/libavcodec/vp6.c new file mode 100644 index 0000000..6e385ce --- /dev/null +++ b/ffmpeg/libavcodec/vp6.c @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP6 compatible video decoder + * + * The VP6F decoder accepts an optional 1 byte extradata. It is composed of: + * - upper 4 bits: difference between encoded width and visible width + * - lower 4 bits: difference between encoded height and visible height + */ + +#include + +#include "avcodec.h" +#include "get_bits.h" +#include "huffman.h" + +#include "vp56.h" +#include "vp56data.h" +#include "vp6data.h" + +#define VP6_MAX_HUFF_SIZE 12 + +static void vp6_parse_coeff(VP56Context *s); +static void vp6_parse_coeff_huffman(VP56Context *s); + +static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size) +{ + VP56RangeCoder *c = &s->c; + int parse_filter_info = 0; + int coeff_offset = 0; + int vrt_shift = 0; + int sub_version; + int rows, cols; + int res = 0; + int separated_coeff = buf[0] & 1; + + s->frames[VP56_FRAME_CURRENT]->key_frame = !(buf[0] & 0x80); + ff_vp56_init_dequant(s, (buf[0] >> 1) & 0x3F); + + if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + sub_version = buf[1] >> 3; + if (sub_version > 8) + return AVERROR_INVALIDDATA; + s->filter_header = buf[1] & 0x06; + if (buf[1] & 1) { + avpriv_report_missing_feature(s->avctx, "Interlacing"); + return AVERROR_PATCHWELCOME; + } + if (separated_coeff || !s->filter_header) { + coeff_offset = AV_RB16(buf+2) - 2; + buf += 2; + buf_size -= 2; + } + + rows = buf[2]; /* number of stored macroblock rows */ + cols = buf[3]; /* number of stored macroblock cols */ + /* buf[4] is number of displayed macroblock rows */ + /* buf[5] is number of displayed macroblock cols */ + if (!rows || !cols) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid size %dx%d\n", cols << 4, rows << 4); + return AVERROR_INVALIDDATA; + } + + if (!s->macroblocks || /* first frame */ + 16*cols != s->avctx->coded_width || + 16*rows != s->avctx->coded_height) { + avcodec_set_dimensions(s->avctx, 16*cols, 16*rows); + if (s->avctx->extradata_size == 1) { + s->avctx->width -= s->avctx->extradata[0] >> 4; + s->avctx->height -= s->avctx->extradata[0] & 0x0F; + } + res = VP56_SIZE_CHANGE; + } + + ff_vp56_init_range_decoder(c, buf+6, buf_size-6); + vp56_rac_gets(c, 2); + + parse_filter_info = s->filter_header; + if (sub_version < 8) + vrt_shift = 5; + s->sub_version = sub_version; + s->golden_frame = 0; + } else { + if (!s->sub_version || !s->avctx->coded_width || !s->avctx->coded_height) + return AVERROR_INVALIDDATA; + + if (separated_coeff || !s->filter_header) { + coeff_offset = AV_RB16(buf+1) - 2; + buf += 2; + buf_size -= 2; + } + ff_vp56_init_range_decoder(c, buf+1, buf_size-1); + + s->golden_frame = vp56_rac_get(c); + if (s->filter_header) { + s->deblock_filtering = vp56_rac_get(c); + if (s->deblock_filtering) + vp56_rac_get(c); + if (s->sub_version > 7) + parse_filter_info = vp56_rac_get(c); + } + } + + if (parse_filter_info) { + if (vp56_rac_get(c)) { + s->filter_mode = 2; + s->sample_variance_threshold = vp56_rac_gets(c, 5) << vrt_shift; + s->max_vector_length = 2 << vp56_rac_gets(c, 3); + } else if (vp56_rac_get(c)) { + s->filter_mode = 1; + } else { + s->filter_mode = 0; + } + if (s->sub_version > 7) + s->filter_selection = vp56_rac_gets(c, 4); + else + s->filter_selection = 16; + } + + s->use_huffman = vp56_rac_get(c); + + s->parse_coeff = vp6_parse_coeff; + if (coeff_offset) { + buf += coeff_offset; + buf_size -= coeff_offset; + if (buf_size < 0) { + if (s->frames[VP56_FRAME_CURRENT]->key_frame) + avcodec_set_dimensions(s->avctx, 0, 0); + return AVERROR_INVALIDDATA; + } + if (s->use_huffman) { + s->parse_coeff = vp6_parse_coeff_huffman; + init_get_bits(&s->gb, buf, buf_size<<3); + } else { + ff_vp56_init_range_decoder(&s->cc, buf, buf_size); + s->ccp = &s->cc; + } + } else { + s->ccp = &s->c; + } + + return res; +} + +static void vp6_coeff_order_table_init(VP56Context *s) +{ + int i, pos, idx = 1; + + s->modelp->coeff_index_to_pos[0] = 0; + for (i=0; i<16; i++) + for (pos=1; pos<64; pos++) + if (s->modelp->coeff_reorder[pos] == i) + s->modelp->coeff_index_to_pos[idx++] = pos; +} + +static void vp6_default_models_init(VP56Context *s) +{ + VP56Model *model = s->modelp; + + model->vector_dct[0] = 0xA2; + model->vector_dct[1] = 0xA4; + model->vector_sig[0] = 0x80; + model->vector_sig[1] = 0x80; + + memcpy(model->mb_types_stats, ff_vp56_def_mb_types_stats, sizeof(model->mb_types_stats)); + memcpy(model->vector_fdv, vp6_def_fdv_vector_model, sizeof(model->vector_fdv)); + memcpy(model->vector_pdv, vp6_def_pdv_vector_model, sizeof(model->vector_pdv)); + memcpy(model->coeff_runv, vp6_def_runv_coeff_model, sizeof(model->coeff_runv)); + memcpy(model->coeff_reorder, vp6_def_coeff_reorder, sizeof(model->coeff_reorder)); + + vp6_coeff_order_table_init(s); +} + +static void vp6_parse_vector_models(VP56Context *s) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + int comp, node; + + for (comp=0; comp<2; comp++) { + if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][0])) + model->vector_dct[comp] = vp56_rac_gets_nn(c, 7); + if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][1])) + model->vector_sig[comp] = vp56_rac_gets_nn(c, 7); + } + + for (comp=0; comp<2; comp++) + for (node=0; node<7; node++) + if (vp56_rac_get_prob(c, vp6_pdv_pct[comp][node])) + model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7); + + for (comp=0; comp<2; comp++) + for (node=0; node<8; node++) + if (vp56_rac_get_prob(c, vp6_fdv_pct[comp][node])) + model->vector_fdv[comp][node] = vp56_rac_gets_nn(c, 7); +} + +/* nodes must ascend by count, but with descending symbol order */ +static int vp6_huff_cmp(const void *va, const void *vb) +{ + const Node *a = va, *b = vb; + return (a->count - b->count)*16 + (b->sym - a->sym); +} + +static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], + const uint8_t *map, unsigned size, VLC *vlc) +{ + Node nodes[2*VP6_MAX_HUFF_SIZE], *tmp = &nodes[size]; + int a, b, i; + + /* first compute probabilities from model */ + tmp[0].count = 256; + for (i=0; i> 8; + b = tmp[i].count * (255 - coeff_model[i]) >> 8; + nodes[map[2*i ]].count = a + !a; + nodes[map[2*i+1]].count = b + !b; + } + + ff_free_vlc(vlc); + /* then build the huffman tree according to probabilities */ + return ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, + FF_HUFFMAN_FLAG_HNODE_FIRST); +} + +static int vp6_parse_coeff_models(VP56Context *s) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + int def_prob[11]; + int node, cg, ctx, pos; + int ct; /* code type */ + int pt; /* plane type (0 for Y, 1 for U or V) */ + + memset(def_prob, 0x80, sizeof(def_prob)); + + for (pt=0; pt<2; pt++) + for (node=0; node<11; node++) + if (vp56_rac_get_prob(c, vp6_dccv_pct[pt][node])) { + def_prob[node] = vp56_rac_gets_nn(c, 7); + model->coeff_dccv[pt][node] = def_prob[node]; + } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + model->coeff_dccv[pt][node] = def_prob[node]; + } + + if (vp56_rac_get(c)) { + for (pos=1; pos<64; pos++) + if (vp56_rac_get_prob(c, vp6_coeff_reorder_pct[pos])) + model->coeff_reorder[pos] = vp56_rac_gets(c, 4); + vp6_coeff_order_table_init(s); + } + + for (cg=0; cg<2; cg++) + for (node=0; node<14; node++) + if (vp56_rac_get_prob(c, vp6_runv_pct[cg][node])) + model->coeff_runv[cg][node] = vp56_rac_gets_nn(c, 7); + + for (ct=0; ct<3; ct++) + for (pt=0; pt<2; pt++) + for (cg=0; cg<6; cg++) + for (node=0; node<11; node++) + if (vp56_rac_get_prob(c, vp6_ract_pct[ct][pt][cg][node])) { + def_prob[node] = vp56_rac_gets_nn(c, 7); + model->coeff_ract[pt][ct][cg][node] = def_prob[node]; + } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) { + model->coeff_ract[pt][ct][cg][node] = def_prob[node]; + } + + if (s->use_huffman) { + for (pt=0; pt<2; pt++) { + if (vp6_build_huff_tree(s, model->coeff_dccv[pt], + vp6_huff_coeff_map, 12, &s->dccv_vlc[pt])) + return -1; + if (vp6_build_huff_tree(s, model->coeff_runv[pt], + vp6_huff_run_map, 9, &s->runv_vlc[pt])) + return -1; + for (ct=0; ct<3; ct++) + for (cg = 0; cg < 6; cg++) + if (vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg], + vp6_huff_coeff_map, 12, + &s->ract_vlc[pt][ct][cg])) + return -1; + } + memset(s->nb_null, 0, sizeof(s->nb_null)); + } else { + /* coeff_dcct is a linear combination of coeff_dccv */ + for (pt=0; pt<2; pt++) + for (ctx=0; ctx<3; ctx++) + for (node=0; node<5; node++) + model->coeff_dcct[pt][ctx][node] = av_clip(((model->coeff_dccv[pt][node] * vp6_dccv_lc[ctx][node][0] + 128) >> 8) + vp6_dccv_lc[ctx][node][1], 1, 255); + } + return 0; +} + +static void vp6_parse_vector_adjustment(VP56Context *s, VP56mv *vect) +{ + VP56RangeCoder *c = &s->c; + VP56Model *model = s->modelp; + int comp; + + *vect = (VP56mv) {0,0}; + if (s->vector_candidate_pos < 2) + *vect = s->vector_candidate[0]; + + for (comp=0; comp<2; comp++) { + int i, delta = 0; + + if (vp56_rac_get_prob(c, model->vector_dct[comp])) { + static const uint8_t prob_order[] = {0, 1, 2, 7, 6, 5, 4}; + for (i=0; ivector_fdv[comp][j])<vector_fdv[comp][3])<<3; + else + delta |= 8; + } else { + delta = vp56_rac_get_tree(c, ff_vp56_pva_tree, + model->vector_pdv[comp]); + } + + if (delta && vp56_rac_get_prob(c, model->vector_sig[comp])) + delta = -delta; + + if (!comp) + vect->x += delta; + else + vect->y += delta; + } +} + +/** + * Read number of consecutive blocks with null DC or AC. + * This value is < 74. + */ +static unsigned vp6_get_nb_null(VP56Context *s) +{ + unsigned val = get_bits(&s->gb, 2); + if (val == 2) + val += get_bits(&s->gb, 2); + else if (val == 3) { + val = get_bits1(&s->gb) << 2; + val = 6+val + get_bits(&s->gb, 2+val); + } + return val; +} + +static void vp6_parse_coeff_huffman(VP56Context *s) +{ + VP56Model *model = s->modelp; + uint8_t *permute = s->idct_scantable; + VLC *vlc_coeff; + int coeff, sign, coeff_idx; + int b, cg, idx; + int pt = 0; /* plane type (0 for Y, 1 for U or V) */ + + for (b=0; b<6; b++) { + int ct = 0; /* code type */ + if (b > 3) pt = 1; + vlc_coeff = &s->dccv_vlc[pt]; + + for (coeff_idx = 0;;) { + int run = 1; + if (coeff_idx<2 && s->nb_null[coeff_idx][pt]) { + s->nb_null[coeff_idx][pt]--; + if (coeff_idx) + break; + } else { + if (get_bits_left(&s->gb) <= 0) + return; + coeff = get_vlc2(&s->gb, vlc_coeff->table, 9, 3); + if (coeff == 0) { + if (coeff_idx) { + int pt = (coeff_idx >= 6); + run += get_vlc2(&s->gb, s->runv_vlc[pt].table, 9, 3); + if (run >= 9) + run += get_bits(&s->gb, 6); + } else + s->nb_null[0][pt] = vp6_get_nb_null(s); + ct = 0; + } else if (coeff == 11) { /* end of block */ + if (coeff_idx == 1) /* first AC coeff ? */ + s->nb_null[1][pt] = vp6_get_nb_null(s); + break; + } else { + int coeff2 = ff_vp56_coeff_bias[coeff]; + if (coeff > 4) + coeff2 += get_bits(&s->gb, coeff <= 9 ? coeff - 4 : 11); + ct = 1 + (coeff2 > 1); + sign = get_bits1(&s->gb); + coeff2 = (coeff2 ^ -sign) + sign; + if (coeff_idx) + coeff2 *= s->dequant_ac; + idx = model->coeff_index_to_pos[coeff_idx]; + s->block_coeff[b][permute[idx]] = coeff2; + } + } + coeff_idx+=run; + if (coeff_idx >= 64) + break; + cg = FFMIN(vp6_coeff_groups[coeff_idx], 3); + vlc_coeff = &s->ract_vlc[pt][ct][cg]; + } + } +} + +static void vp6_parse_coeff(VP56Context *s) +{ + VP56RangeCoder *c = s->ccp; + VP56Model *model = s->modelp; + uint8_t *permute = s->idct_scantable; + uint8_t *model1, *model2, *model3; + int coeff, sign, coeff_idx; + int b, i, cg, idx, ctx; + int pt = 0; /* plane type (0 for Y, 1 for U or V) */ + + for (b=0; b<6; b++) { + int ct = 1; /* code type */ + int run = 1; + + if (b > 3) pt = 1; + + ctx = s->left_block[ff_vp56_b6to4[b]].not_null_dc + + s->above_blocks[s->above_block_idx[b]].not_null_dc; + model1 = model->coeff_dccv[pt]; + model2 = model->coeff_dcct[pt][ctx]; + + coeff_idx = 0; + for (;;) { + if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) { + /* parse a coeff */ + if (vp56_rac_get_prob(c, model2[2])) { + if (vp56_rac_get_prob(c, model2[3])) { + idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1); + coeff = ff_vp56_coeff_bias[idx+5]; + for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--) + coeff += vp56_rac_get_prob(c, ff_vp56_coeff_parse_table[idx][i]) << i; + } else { + if (vp56_rac_get_prob(c, model2[4])) + coeff = 3 + vp56_rac_get_prob(c, model1[5]); + else + coeff = 2; + } + ct = 2; + } else { + ct = 1; + coeff = 1; + } + sign = vp56_rac_get(c); + coeff = (coeff ^ -sign) + sign; + if (coeff_idx) + coeff *= s->dequant_ac; + idx = model->coeff_index_to_pos[coeff_idx]; + s->block_coeff[b][permute[idx]] = coeff; + run = 1; + } else { + /* parse a run */ + ct = 0; + if (coeff_idx > 0) { + if (!vp56_rac_get_prob(c, model2[1])) + break; + + model3 = model->coeff_runv[coeff_idx >= 6]; + run = vp56_rac_get_tree(c, vp6_pcr_tree, model3); + if (!run) + for (run=9, i=0; i<6; i++) + run += vp56_rac_get_prob(c, model3[i+8]) << i; + } + } + coeff_idx += run; + if (coeff_idx >= 64) + break; + cg = vp6_coeff_groups[coeff_idx]; + model1 = model2 = model->coeff_ract[pt][ct][cg]; + } + + s->left_block[ff_vp56_b6to4[b]].not_null_dc = + s->above_blocks[s->above_block_idx[b]].not_null_dc = !!s->block_coeff[b][0]; + } +} + +static int vp6_block_variance(uint8_t *src, int stride) +{ + int sum = 0, square_sum = 0; + int y, x; + + for (y=0; y<8; y+=2) { + for (x=0; x<8; x+=2) { + sum += src[x]; + square_sum += src[x]*src[x]; + } + src += 2*stride; + } + return (16*square_sum - sum*sum) >> 8; +} + +static void vp6_filter_hv4(uint8_t *dst, uint8_t *src, int stride, + int delta, const int16_t *weights) +{ + int x, y; + + for (y=0; y<8; y++) { + for (x=0; x<8; x++) { + dst[x] = av_clip_uint8(( src[x-delta ] * weights[0] + + src[x ] * weights[1] + + src[x+delta ] * weights[2] + + src[x+2*delta] * weights[3] + 64) >> 7); + } + src += stride; + dst += stride; + } +} + +static void vp6_filter_diag2(VP56Context *s, uint8_t *dst, uint8_t *src, + int stride, int h_weight, int v_weight) +{ + uint8_t *tmp = s->edge_emu_buffer+16; + s->h264chroma.put_h264_chroma_pixels_tab[0](tmp, src, stride, 9, h_weight, 0); + s->h264chroma.put_h264_chroma_pixels_tab[0](dst, tmp, stride, 8, 0, v_weight); +} + +static void vp6_filter(VP56Context *s, uint8_t *dst, uint8_t *src, + int offset1, int offset2, int stride, + VP56mv mv, int mask, int select, int luma) +{ + int filter4 = 0; + int x8 = mv.x & mask; + int y8 = mv.y & mask; + + if (luma) { + x8 *= 2; + y8 *= 2; + filter4 = s->filter_mode; + if (filter4 == 2) { + if (s->max_vector_length && + (FFABS(mv.x) > s->max_vector_length || + FFABS(mv.y) > s->max_vector_length)) { + filter4 = 0; + } else if (s->sample_variance_threshold + && (vp6_block_variance(src+offset1, stride) + < s->sample_variance_threshold)) { + filter4 = 0; + } + } + } + + if ((y8 && (offset2-offset1)*s->flip<0) || (!y8 && offset1 > offset2)) { + offset1 = offset2; + } + + if (filter4) { + if (!y8) { /* left or right combine */ + vp6_filter_hv4(dst, src+offset1, stride, 1, + vp6_block_copy_filter[select][x8]); + } else if (!x8) { /* above or below combine */ + vp6_filter_hv4(dst, src+offset1, stride, stride, + vp6_block_copy_filter[select][y8]); + } else { + s->vp56dsp.vp6_filter_diag4(dst, src+offset1+((mv.x^mv.y)>>31), stride, + vp6_block_copy_filter[select][x8], + vp6_block_copy_filter[select][y8]); + } + } else { + if (!x8 || !y8) { + s->h264chroma.put_h264_chroma_pixels_tab[0](dst, src + offset1, stride, 8, x8, y8); + } else { + vp6_filter_diag2(s, dst, src+offset1 + ((mv.x^mv.y)>>31), stride, x8, y8); + } + } +} + +static av_cold void vp6_decode_init_context(VP56Context *s); + +static av_cold int vp6_decode_init(AVCodecContext *avctx) +{ + VP56Context *s = avctx->priv_data; + int ret; + + if ((ret = ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6, + avctx->codec->id == AV_CODEC_ID_VP6A)) < 0) + return ret; + + vp6_decode_init_context(s); + + if (s->has_alpha) { + s->alpha_context = av_mallocz(sizeof(VP56Context)); + ff_vp56_init_context(avctx, s->alpha_context, + s->flip == -1, s->has_alpha); + vp6_decode_init_context(s->alpha_context); + } + + return 0; +} + +static av_cold void vp6_decode_init_context(VP56Context *s) +{ + s->deblock_filtering = 0; + s->vp56_coord_div = vp6_coord_div; + s->parse_vector_adjustment = vp6_parse_vector_adjustment; + s->filter = vp6_filter; + s->default_models_init = vp6_default_models_init; + s->parse_vector_models = vp6_parse_vector_models; + s->parse_coeff_models = vp6_parse_coeff_models; + s->parse_header = vp6_parse_header; +} + +static av_cold void vp6_decode_free_context(VP56Context *s); + +static av_cold int vp6_decode_free(AVCodecContext *avctx) +{ + VP56Context *s = avctx->priv_data; + + ff_vp56_free(avctx); + vp6_decode_free_context(s); + + if (s->alpha_context) { + ff_vp56_free_context(s->alpha_context); + vp6_decode_free_context(s->alpha_context); + av_free(s->alpha_context); + } + + return 0; +} + +static av_cold void vp6_decode_free_context(VP56Context *s) +{ + int pt, ct, cg; + + for (pt=0; pt<2; pt++) { + ff_free_vlc(&s->dccv_vlc[pt]); + ff_free_vlc(&s->runv_vlc[pt]); + for (ct=0; ct<3; ct++) + for (cg=0; cg<6; cg++) + ff_free_vlc(&s->ract_vlc[pt][ct][cg]); + } +} + +AVCodec ff_vp6_decoder = { + .name = "vp6", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP6, + .priv_data_size = sizeof(VP56Context), + .init = vp6_decode_init, + .close = vp6_decode_free, + .decode = ff_vp56_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("On2 VP6"), +}; + +/* flash version, not flipped upside-down */ +AVCodec ff_vp6f_decoder = { + .name = "vp6f", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP6F, + .priv_data_size = sizeof(VP56Context), + .init = vp6_decode_init, + .close = vp6_decode_free, + .decode = ff_vp56_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version)"), +}; + +/* flash version, not flipped upside-down, with alpha channel */ +AVCodec ff_vp6a_decoder = { + .name = "vp6a", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP6A, + .priv_data_size = sizeof(VP56Context), + .init = vp6_decode_init, + .close = vp6_decode_free, + .decode = ff_vp56_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS, + .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version, with alpha channel)"), +}; diff --git a/ffmpeg/libavcodec/vp6data.h b/ffmpeg/libavcodec/vp6data.h new file mode 100644 index 0000000..3ebfd0e --- /dev/null +++ b/ffmpeg/libavcodec/vp6data.h @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP6 compatible video decoder + */ + +#ifndef AVCODEC_VP6DATA_H +#define AVCODEC_VP6DATA_H + +#include "vp56data.h" + +static const uint8_t vp6_def_fdv_vector_model[2][8] = { + { 247, 210, 135, 68, 138, 220, 239, 246 }, + { 244, 184, 201, 44, 173, 221, 239, 253 }, +}; + +static const uint8_t vp6_def_pdv_vector_model[2][7] = { + { 225, 146, 172, 147, 214, 39, 156 }, + { 204, 170, 119, 235, 140, 230, 228 }, +}; + +static const uint8_t vp6_def_coeff_reorder[] = { + 0, 0, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 3, 3, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 7, 7, + 7, 7, 7, 8, 8, 9, 9, 9, + 9, 9, 9, 10, 10, 11, 11, 11, + 11, 11, 11, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 15, 15, 15, 15, 15, 15, +}; + +static const uint8_t vp6_def_runv_coeff_model[2][14] = { + { 198, 197, 196, 146, 198, 204, 169, 142, 130, 136, 149, 149, 191, 249 }, + { 135, 201, 181, 154, 98, 117, 132, 126, 146, 169, 184, 240, 246, 254 }, +}; + +static const uint8_t vp6_sig_dct_pct[2][2] = { + { 237, 246 }, + { 231, 243 }, +}; + +static const uint8_t vp6_pdv_pct[2][7] = { + { 253, 253, 254, 254, 254, 254, 254 }, + { 245, 253, 254, 254, 254, 254, 254 }, +}; + +static const uint8_t vp6_fdv_pct[2][8] = { + { 254, 254, 254, 254, 254, 250, 250, 252 }, + { 254, 254, 254, 254, 254, 251, 251, 254 }, +}; + +static const uint8_t vp6_dccv_pct[2][11] = { + { 146, 255, 181, 207, 232, 243, 238, 251, 244, 250, 249 }, + { 179, 255, 214, 240, 250, 255, 244, 255, 255, 255, 255 }, +}; + +static const uint8_t vp6_coeff_reorder_pct[] = { + 255, 132, 132, 159, 153, 151, 161, 170, + 164, 162, 136, 110, 103, 114, 129, 118, + 124, 125, 132, 136, 114, 110, 142, 135, + 134, 123, 143, 126, 153, 183, 166, 161, + 171, 180, 179, 164, 203, 218, 225, 217, + 215, 206, 203, 217, 229, 241, 248, 243, + 253, 255, 253, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, +}; + +static const uint8_t vp6_runv_pct[2][14] = { + { 219, 246, 238, 249, 232, 239, 249, 255, 248, 253, 239, 244, 241, 248 }, + { 198, 232, 251, 253, 219, 241, 253, 255, 248, 249, 244, 238, 251, 255 }, +}; + +static const uint8_t vp6_ract_pct[3][2][6][11] = { + { { { 227, 246, 230, 247, 244, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 209, 231, 231, 249, 249, 253, 255, 255, 255 }, + { 255, 255, 225, 242, 241, 251, 253, 255, 255, 255, 255 }, + { 255, 255, 241, 253, 252, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } }, + { { 240, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 240, 253, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } } }, + { { { 206, 203, 227, 239, 247, 255, 253, 255, 255, 255, 255 }, + { 207, 199, 220, 236, 243, 252, 252, 255, 255, 255, 255 }, + { 212, 219, 230, 243, 244, 253, 252, 255, 255, 255, 255 }, + { 236, 237, 247, 252, 253, 255, 255, 255, 255, 255, 255 }, + { 240, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } }, + { { 230, 233, 249, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 238, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } } }, + { { { 225, 239, 227, 231, 244, 253, 243, 255, 255, 253, 255 }, + { 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 255 }, + { 235, 249, 238, 240, 251, 255, 249, 255, 253, 253, 255 }, + { 249, 253, 251, 250, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 250, 249, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } }, + { { 243, 244, 250, 250, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 248, 250, 253, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } } } +}; + +static const int vp6_dccv_lc[3][5][2] = { + { { 122, 133 }, { 0, 1 }, { 78, 171 }, { 139, 117 }, { 168, 79 } }, + { { 133, 51 }, { 0, 1 }, { 169, 71 }, { 214, 44 }, { 210, 38 } }, + { { 142, -16 }, { 0, 1 }, { 221, -30 }, { 246, -3 }, { 203, 17 } }, +}; + +static const uint8_t vp6_coeff_groups[] = { + 0, 0, 1, 1, 1, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, +}; + +static const int16_t vp6_block_copy_filter[17][8][4] = { + { { 0, 128, 0, 0 }, /* 0 */ + { -3, 122, 9, 0 }, + { -4, 109, 24, -1 }, + { -5, 91, 45, -3 }, + { -4, 68, 68, -4 }, + { -3, 45, 91, -5 }, + { -1, 24, 109, -4 }, + { 0, 9, 122, -3 } }, + { { 0, 128, 0, 0 }, /* 1 */ + { -4, 124, 9, -1 }, + { -5, 110, 25, -2 }, + { -6, 91, 46, -3 }, + { -5, 69, 69, -5 }, + { -3, 46, 91, -6 }, + { -2, 25, 110, -5 }, + { -1, 9, 124, -4 } }, + { { 0, 128, 0, 0 }, /* 2 */ + { -4, 123, 10, -1 }, + { -6, 110, 26, -2 }, + { -7, 92, 47, -4 }, + { -6, 70, 70, -6 }, + { -4, 47, 92, -7 }, + { -2, 26, 110, -6 }, + { -1, 10, 123, -4 } }, + { { 0, 128, 0, 0 }, /* 3 */ + { -5, 124, 10, -1 }, + { -7, 110, 27, -2 }, + { -7, 91, 48, -4 }, + { -6, 70, 70, -6 }, + { -4, 48, 92, -8 }, + { -2, 27, 110, -7 }, + { -1, 10, 124, -5 } }, + { { 0, 128, 0, 0 }, /* 4 */ + { -6, 124, 11, -1 }, + { -8, 111, 28, -3 }, + { -8, 92, 49, -5 }, + { -7, 71, 71, -7 }, + { -5, 49, 92, -8 }, + { -3, 28, 111, -8 }, + { -1, 11, 124, -6 } }, + { { 0, 128, 0, 0 }, /* 5 */ + { -6, 123, 12, -1 }, + { -9, 111, 29, -3 }, + { -9, 93, 50, -6 }, + { -8, 72, 72, -8 }, + { -6, 50, 93, -9 }, + { -3, 29, 111, -9 }, + { -1, 12, 123, -6 } }, + { { 0, 128, 0, 0 }, /* 6 */ + { -7, 124, 12, -1 }, + { -10, 111, 30, -3 }, + { -10, 93, 51, -6 }, + { -9, 73, 73, -9 }, + { -6, 51, 93, -10 }, + { -3, 30, 111, -10 }, + { -1, 12, 124, -7 } }, + { { 0, 128, 0, 0 }, /* 7 */ + { -7, 123, 13, -1 }, + { -11, 112, 31, -4 }, + { -11, 94, 52, -7 }, + { -10, 74, 74, -10 }, + { -7, 52, 94, -11 }, + { -4, 31, 112, -11 }, + { -1, 13, 123, -7 } }, + { { 0, 128, 0, 0 }, /* 8 */ + { -8, 124, 13, -1 }, + { -12, 112, 32, -4 }, + { -12, 94, 53, -7 }, + { -10, 74, 74, -10 }, + { -7, 53, 94, -12 }, + { -4, 32, 112, -12 }, + { -1, 13, 124, -8 } }, + { { 0, 128, 0, 0 }, /* 9 */ + { -9, 124, 14, -1 }, + { -13, 112, 33, -4 }, + { -13, 95, 54, -8 }, + { -11, 75, 75, -11 }, + { -8, 54, 95, -13 }, + { -4, 33, 112, -13 }, + { -1, 14, 124, -9 } }, + { { 0, 128, 0, 0 }, /* 10 */ + { -9, 123, 15, -1 }, + { -14, 113, 34, -5 }, + { -14, 95, 55, -8 }, + { -12, 76, 76, -12 }, + { -8, 55, 95, -14 }, + { -5, 34, 112, -13 }, + { -1, 15, 123, -9 } }, + { { 0, 128, 0, 0 }, /* 11 */ + { -10, 124, 15, -1 }, + { -14, 113, 34, -5 }, + { -15, 96, 56, -9 }, + { -13, 77, 77, -13 }, + { -9, 56, 96, -15 }, + { -5, 34, 113, -14 }, + { -1, 15, 124, -10 } }, + { { 0, 128, 0, 0 }, /* 12 */ + { -10, 123, 16, -1 }, + { -15, 113, 35, -5 }, + { -16, 98, 56, -10 }, + { -14, 78, 78, -14 }, + { -10, 56, 98, -16 }, + { -5, 35, 113, -15 }, + { -1, 16, 123, -10 } }, + { { 0, 128, 0, 0 }, /* 13 */ + { -11, 124, 17, -2 }, + { -16, 113, 36, -5 }, + { -17, 98, 57, -10 }, + { -14, 78, 78, -14 }, + { -10, 57, 98, -17 }, + { -5, 36, 113, -16 }, + { -2, 17, 124, -11 } }, + { { 0, 128, 0, 0 }, /* 14 */ + { -12, 125, 17, -2 }, + { -17, 114, 37, -6 }, + { -18, 99, 58, -11 }, + { -15, 79, 79, -15 }, + { -11, 58, 99, -18 }, + { -6, 37, 114, -17 }, + { -2, 17, 125, -12 } }, + { { 0, 128, 0, 0 }, /* 15 */ + { -12, 124, 18, -2 }, + { -18, 114, 38, -6 }, + { -19, 99, 59, -11 }, + { -16, 80, 80, -16 }, + { -11, 59, 99, -19 }, + { -6, 38, 114, -18 }, + { -2, 18, 124, -12 } }, + { { 0, 128, 0, 0 }, /* 16 */ + { -4, 118, 16, -2 }, + { -7, 106, 34, -5 }, + { -8, 90, 53, -7 }, + { -8, 72, 72, -8 }, + { -7, 53, 90, -8 }, + { -5, 34, 106, -7 }, + { -2, 16, 118, -4 } }, +}; + +static const VP56Tree vp6_pcr_tree[] = { + { 8, 0}, + { 4, 1}, + { 2, 2}, {-1}, {-2}, + { 2, 3}, {-3}, {-4}, + { 8, 4}, + { 4, 5}, + { 2, 6}, {-5}, {-6}, + { 2, 7}, {-7}, {-8}, + {-0}, +}; + +static const uint8_t vp6_coord_div[] = { 4, 4, 4, 4, 8, 8 }; + +static const uint8_t vp6_huff_coeff_map[] = { + 13, 14, 11, 0, 1, 15, 16, 18, 2, 17, 3, 4, 19, 20, 5, 6, 21, 22, 7, 8, 9, 10 +}; + +static const uint8_t vp6_huff_run_map[] = { + 10, 13, 11, 12, 0, 1, 2, 3, 14, 8, 15, 16, 4, 5, 6, 7 +}; + +#endif /* AVCODEC_VP6DATA_H */ diff --git a/ffmpeg/libavcodec/vp6dsp.c b/ffmpeg/libavcodec/vp6dsp.c new file mode 100644 index 0000000..67c6be0 --- /dev/null +++ b/ffmpeg/libavcodec/vp6dsp.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006 Aurelien Jacobs + * + * 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 + */ + +/** + * @file + * VP6 DSP-oriented functions + */ + +#include "libavutil/common.h" +#include "vp56dsp.h" + + +void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, int stride, + const int16_t *h_weights, const int16_t *v_weights) +{ + int x, y; + int tmp[8*11]; + int *t = tmp; + + src -= stride; + + for (y=0; y<11; y++) { + for (x=0; x<8; x++) { + t[x] = av_clip_uint8(( src[x-1] * h_weights[0] + + src[x ] * h_weights[1] + + src[x+1] * h_weights[2] + + src[x+2] * h_weights[3] + 64) >> 7); + } + src += stride; + t += 8; + } + + t = tmp + 8; + for (y=0; y<8; y++) { + for (x=0; x<8; x++) { + dst[x] = av_clip_uint8(( t[x-8 ] * v_weights[0] + + t[x ] * v_weights[1] + + t[x+8 ] * v_weights[2] + + t[x+16] * v_weights[3] + 64) >> 7); + } + dst += stride; + t += 8; + } +} diff --git a/ffmpeg/libavcodec/vp8.c b/ffmpeg/libavcodec/vp8.c new file mode 100644 index 0000000..ac929d0 --- /dev/null +++ b/ffmpeg/libavcodec/vp8.c @@ -0,0 +1,2110 @@ +/* + * VP8 compatible video decoder + * + * Copyright (C) 2010 David Conrad + * Copyright (C) 2010 Ronald S. Bultje + * Copyright (C) 2010 Jason Garrett-Glaser + * Copyright (C) 2012 Daniel Kang + * + * 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 "libavutil/imgutils.h" +#include "avcodec.h" +#include "internal.h" +#include "vp8.h" +#include "vp8data.h" +#include "rectangle.h" +#include "thread.h" + +#if ARCH_ARM +# include "arm/vp8.h" +#endif + +static void free_buffers(VP8Context *s) +{ + int i; + if (s->thread_data) + for (i = 0; i < MAX_THREADS; i++) { + av_freep(&s->thread_data[i].filter_strength); + av_freep(&s->thread_data[i].edge_emu_buffer); + } + av_freep(&s->thread_data); + av_freep(&s->macroblocks_base); + av_freep(&s->intra4x4_pred_mode_top); + av_freep(&s->top_nnz); + av_freep(&s->top_border); + + s->macroblocks = NULL; +} + +static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) +{ + int ret; + if ((ret = ff_thread_get_buffer(s->avctx, &f->tf, + ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) + return ret; + if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height))) { + ff_thread_release_buffer(s->avctx, &f->tf); + return AVERROR(ENOMEM); + } + return 0; +} + +static void vp8_release_frame(VP8Context *s, VP8Frame *f) +{ + av_buffer_unref(&f->seg_map); + ff_thread_release_buffer(s->avctx, &f->tf); +} + +static int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src) +{ + int ret; + + vp8_release_frame(s, dst); + + if ((ret = ff_thread_ref_frame(&dst->tf, &src->tf)) < 0) + return ret; + if (src->seg_map && + !(dst->seg_map = av_buffer_ref(src->seg_map))) { + vp8_release_frame(s, dst); + return AVERROR(ENOMEM); + } + + return 0; +} + + +static void vp8_decode_flush_impl(AVCodecContext *avctx, int free_mem) +{ + VP8Context *s = avctx->priv_data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) + vp8_release_frame(s, &s->frames[i]); + memset(s->framep, 0, sizeof(s->framep)); + + if (free_mem) + free_buffers(s); +} + +static void vp8_decode_flush(AVCodecContext *avctx) +{ + vp8_decode_flush_impl(avctx, 0); +} + +static int update_dimensions(VP8Context *s, int width, int height) +{ + AVCodecContext *avctx = s->avctx; + int i; + + if (width != s->avctx->width || ((width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) && s->macroblocks_base || + height != s->avctx->height) { + if (av_image_check_size(width, height, 0, s->avctx)) + return AVERROR_INVALIDDATA; + + vp8_decode_flush_impl(s->avctx, 1); + + avcodec_set_dimensions(s->avctx, width, height); + } + + s->mb_width = (s->avctx->coded_width +15) / 16; + s->mb_height = (s->avctx->coded_height+15) / 16; + + s->mb_layout = (avctx->active_thread_type == FF_THREAD_SLICE) && (FFMIN(s->num_coeff_partitions, avctx->thread_count) > 1); + if (!s->mb_layout) { // Frame threading and one thread + s->macroblocks_base = av_mallocz((s->mb_width+s->mb_height*2+1)*sizeof(*s->macroblocks)); + s->intra4x4_pred_mode_top = av_mallocz(s->mb_width*4); + } + else // Sliced threading + s->macroblocks_base = av_mallocz((s->mb_width+2)*(s->mb_height+2)*sizeof(*s->macroblocks)); + s->top_nnz = av_mallocz(s->mb_width*sizeof(*s->top_nnz)); + s->top_border = av_mallocz((s->mb_width+1)*sizeof(*s->top_border)); + s->thread_data = av_mallocz(MAX_THREADS*sizeof(VP8ThreadData)); + + for (i = 0; i < MAX_THREADS; i++) { + s->thread_data[i].filter_strength = av_mallocz(s->mb_width*sizeof(*s->thread_data[0].filter_strength)); +#if HAVE_THREADS + pthread_mutex_init(&s->thread_data[i].lock, NULL); + pthread_cond_init(&s->thread_data[i].cond, NULL); +#endif + } + + if (!s->macroblocks_base || !s->top_nnz || !s->top_border || + (!s->intra4x4_pred_mode_top && !s->mb_layout)) + return AVERROR(ENOMEM); + + s->macroblocks = s->macroblocks_base + 1; + + return 0; +} + +static void parse_segment_info(VP8Context *s) +{ + VP56RangeCoder *c = &s->c; + int i; + + s->segmentation.update_map = vp8_rac_get(c); + + if (vp8_rac_get(c)) { // update segment feature data + s->segmentation.absolute_vals = vp8_rac_get(c); + + for (i = 0; i < 4; i++) + s->segmentation.base_quant[i] = vp8_rac_get_sint(c, 7); + + for (i = 0; i < 4; i++) + s->segmentation.filter_level[i] = vp8_rac_get_sint(c, 6); + } + if (s->segmentation.update_map) + for (i = 0; i < 3; i++) + s->prob->segmentid[i] = vp8_rac_get(c) ? vp8_rac_get_uint(c, 8) : 255; +} + +static void update_lf_deltas(VP8Context *s) +{ + VP56RangeCoder *c = &s->c; + int i; + + for (i = 0; i < 4; i++) { + if (vp8_rac_get(c)) { + s->lf_delta.ref[i] = vp8_rac_get_uint(c, 6); + + if (vp8_rac_get(c)) + s->lf_delta.ref[i] = -s->lf_delta.ref[i]; + } + } + + for (i = MODE_I4x4; i <= VP8_MVMODE_SPLIT; i++) { + if (vp8_rac_get(c)) { + s->lf_delta.mode[i] = vp8_rac_get_uint(c, 6); + + if (vp8_rac_get(c)) + s->lf_delta.mode[i] = -s->lf_delta.mode[i]; + } + } +} + +static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size) +{ + const uint8_t *sizes = buf; + int i; + + s->num_coeff_partitions = 1 << vp8_rac_get_uint(&s->c, 2); + + buf += 3*(s->num_coeff_partitions-1); + buf_size -= 3*(s->num_coeff_partitions-1); + if (buf_size < 0) + return -1; + + for (i = 0; i < s->num_coeff_partitions-1; i++) { + int size = AV_RL24(sizes + 3*i); + if (buf_size - size < 0) + return -1; + + ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size); + buf += size; + buf_size -= size; + } + ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size); + + return 0; +} + +static void get_quants(VP8Context *s) +{ + VP56RangeCoder *c = &s->c; + int i, base_qi; + + int yac_qi = vp8_rac_get_uint(c, 7); + int ydc_delta = vp8_rac_get_sint(c, 4); + int y2dc_delta = vp8_rac_get_sint(c, 4); + int y2ac_delta = vp8_rac_get_sint(c, 4); + int uvdc_delta = vp8_rac_get_sint(c, 4); + int uvac_delta = vp8_rac_get_sint(c, 4); + + for (i = 0; i < 4; i++) { + if (s->segmentation.enabled) { + base_qi = s->segmentation.base_quant[i]; + if (!s->segmentation.absolute_vals) + base_qi += yac_qi; + } else + base_qi = yac_qi; + + s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + ydc_delta , 7)]; + s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi , 7)]; + s->qmat[i].luma_dc_qmul[0] = 2 * vp8_dc_qlookup[av_clip_uintp2(base_qi + y2dc_delta, 7)]; + /* 101581>>16 is equivalent to 155/100 */ + s->qmat[i].luma_dc_qmul[1] = (101581 * vp8_ac_qlookup[av_clip_uintp2(base_qi + y2ac_delta, 7)]) >> 16; + s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + uvdc_delta, 7)]; + s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + uvac_delta, 7)]; + + s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8); + s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132); + } +} + +/** + * Determine which buffers golden and altref should be updated with after this frame. + * The spec isn't clear here, so I'm going by my understanding of what libvpx does + * + * Intra frames update all 3 references + * Inter frames update VP56_FRAME_PREVIOUS if the update_last flag is set + * If the update (golden|altref) flag is set, it's updated with the current frame + * if update_last is set, and VP56_FRAME_PREVIOUS otherwise. + * If the flag is not set, the number read means: + * 0: no update + * 1: VP56_FRAME_PREVIOUS + * 2: update golden with altref, or update altref with golden + */ +static VP56Frame ref_to_update(VP8Context *s, int update, VP56Frame ref) +{ + VP56RangeCoder *c = &s->c; + + if (update) + return VP56_FRAME_CURRENT; + + switch (vp8_rac_get_uint(c, 2)) { + case 1: + return VP56_FRAME_PREVIOUS; + case 2: + return (ref == VP56_FRAME_GOLDEN) ? VP56_FRAME_GOLDEN2 : VP56_FRAME_GOLDEN; + } + return VP56_FRAME_NONE; +} + +static void update_refs(VP8Context *s) +{ + VP56RangeCoder *c = &s->c; + + int update_golden = vp8_rac_get(c); + int update_altref = vp8_rac_get(c); + + s->update_golden = ref_to_update(s, update_golden, VP56_FRAME_GOLDEN); + s->update_altref = ref_to_update(s, update_altref, VP56_FRAME_GOLDEN2); +} + +static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size) +{ + VP56RangeCoder *c = &s->c; + int header_size, hscale, vscale, i, j, k, l, m, ret; + int width = s->avctx->width; + int height = s->avctx->height; + + s->keyframe = !(buf[0] & 1); + s->profile = (buf[0]>>1) & 7; + s->invisible = !(buf[0] & 0x10); + header_size = AV_RL24(buf) >> 5; + buf += 3; + buf_size -= 3; + + if (s->profile > 3) + av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile); + + if (!s->profile) + memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab)); + else // profile 1-3 use bilinear, 4+ aren't defined so whatever + memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab, sizeof(s->put_pixels_tab)); + + if (header_size > buf_size - 7*s->keyframe) { + av_log(s->avctx, AV_LOG_ERROR, "Header size larger than data provided\n"); + return AVERROR_INVALIDDATA; + } + + if (s->keyframe) { + if (AV_RL24(buf) != 0x2a019d) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid start code 0x%x\n", AV_RL24(buf)); + return AVERROR_INVALIDDATA; + } + width = AV_RL16(buf+3) & 0x3fff; + height = AV_RL16(buf+5) & 0x3fff; + hscale = buf[4] >> 6; + vscale = buf[6] >> 6; + buf += 7; + buf_size -= 7; + + if (hscale || vscale) + avpriv_request_sample(s->avctx, "Upscaling"); + + s->update_golden = s->update_altref = VP56_FRAME_CURRENT; + for (i = 0; i < 4; i++) + for (j = 0; j < 16; j++) + memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]], + sizeof(s->prob->token[i][j])); + memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter, sizeof(s->prob->pred16x16)); + memcpy(s->prob->pred8x8c , vp8_pred8x8c_prob_inter , sizeof(s->prob->pred8x8c)); + memcpy(s->prob->mvc , vp8_mv_default_prob , sizeof(s->prob->mvc)); + memset(&s->segmentation, 0, sizeof(s->segmentation)); + memset(&s->lf_delta, 0, sizeof(s->lf_delta)); + } + + ff_vp56_init_range_decoder(c, buf, header_size); + buf += header_size; + buf_size -= header_size; + + if (s->keyframe) { + if (vp8_rac_get(c)) + av_log(s->avctx, AV_LOG_WARNING, "Unspecified colorspace\n"); + vp8_rac_get(c); // whether we can skip clamping in dsp functions + } + + if ((s->segmentation.enabled = vp8_rac_get(c))) + parse_segment_info(s); + else + s->segmentation.update_map = 0; // FIXME: move this to some init function? + + s->filter.simple = vp8_rac_get(c); + s->filter.level = vp8_rac_get_uint(c, 6); + s->filter.sharpness = vp8_rac_get_uint(c, 3); + + if ((s->lf_delta.enabled = vp8_rac_get(c))) + if (vp8_rac_get(c)) + update_lf_deltas(s); + + if (setup_partitions(s, buf, buf_size)) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n"); + return AVERROR_INVALIDDATA; + } + + if (!s->macroblocks_base || /* first frame */ + width != s->avctx->width || height != s->avctx->height || (width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) { + if ((ret = update_dimensions(s, width, height)) < 0) + return ret; + } + + get_quants(s); + + if (!s->keyframe) { + update_refs(s); + s->sign_bias[VP56_FRAME_GOLDEN] = vp8_rac_get(c); + s->sign_bias[VP56_FRAME_GOLDEN2 /* altref */] = vp8_rac_get(c); + } + + // if we aren't saving this frame's probabilities for future frames, + // make a copy of the current probabilities + if (!(s->update_probabilities = vp8_rac_get(c))) + s->prob[1] = s->prob[0]; + + s->update_last = s->keyframe || vp8_rac_get(c); + + for (i = 0; i < 4; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 3; k++) + for (l = 0; l < NUM_DCT_TOKENS-1; l++) + if (vp56_rac_get_prob_branchy(c, vp8_token_update_probs[i][j][k][l])) { + int prob = vp8_rac_get_uint(c, 8); + for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++) + s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob; + } + + if ((s->mbskip_enabled = vp8_rac_get(c))) + s->prob->mbskip = vp8_rac_get_uint(c, 8); + + if (!s->keyframe) { + s->prob->intra = vp8_rac_get_uint(c, 8); + s->prob->last = vp8_rac_get_uint(c, 8); + s->prob->golden = vp8_rac_get_uint(c, 8); + + if (vp8_rac_get(c)) + for (i = 0; i < 4; i++) + s->prob->pred16x16[i] = vp8_rac_get_uint(c, 8); + if (vp8_rac_get(c)) + for (i = 0; i < 3; i++) + s->prob->pred8x8c[i] = vp8_rac_get_uint(c, 8); + + // 17.2 MV probability update + for (i = 0; i < 2; i++) + for (j = 0; j < 19; j++) + if (vp56_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j])) + s->prob->mvc[i][j] = vp8_rac_get_nn(c); + } + + return 0; +} + +static av_always_inline void clamp_mv(VP8Context *s, VP56mv *dst, const VP56mv *src) +{ + dst->x = av_clip(src->x, s->mv_min.x, s->mv_max.x); + dst->y = av_clip(src->y, s->mv_min.y, s->mv_max.y); +} + +/** + * Motion vector coding, 17.1. + */ +static int read_mv_component(VP56RangeCoder *c, const uint8_t *p) +{ + int bit, x = 0; + + if (vp56_rac_get_prob_branchy(c, p[0])) { + int i; + + for (i = 0; i < 3; i++) + x += vp56_rac_get_prob(c, p[9 + i]) << i; + for (i = 9; i > 3; i--) + x += vp56_rac_get_prob(c, p[9 + i]) << i; + if (!(x & 0xFFF0) || vp56_rac_get_prob(c, p[12])) + x += 8; + } else { + // small_mvtree + const uint8_t *ps = p+2; + bit = vp56_rac_get_prob(c, *ps); + ps += 1 + 3*bit; + x += 4*bit; + bit = vp56_rac_get_prob(c, *ps); + ps += 1 + bit; + x += 2*bit; + x += vp56_rac_get_prob(c, *ps); + } + + return (x && vp56_rac_get_prob(c, p[1])) ? -x : x; +} + +static av_always_inline +const uint8_t *get_submv_prob(uint32_t left, uint32_t top) +{ + if (left == top) + return vp8_submv_prob[4-!!left]; + if (!top) + return vp8_submv_prob[2]; + return vp8_submv_prob[1-!!left]; +} + +/** + * Split motion vector prediction, 16.4. + * @returns the number of motion vectors parsed (2, 4 or 16) + */ +static av_always_inline +int decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, int layout) +{ + int part_idx; + int n, num; + VP8Macroblock *top_mb; + VP8Macroblock *left_mb = &mb[-1]; + const uint8_t *mbsplits_left = vp8_mbsplits[left_mb->partitioning], + *mbsplits_top, + *mbsplits_cur, *firstidx; + VP56mv *top_mv; + VP56mv *left_mv = left_mb->bmv; + VP56mv *cur_mv = mb->bmv; + + if (!layout) // layout is inlined, s->mb_layout is not + top_mb = &mb[2]; + else + top_mb = &mb[-s->mb_width-1]; + mbsplits_top = vp8_mbsplits[top_mb->partitioning]; + top_mv = top_mb->bmv; + + if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[0])) { + if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[1])) { + part_idx = VP8_SPLITMVMODE_16x8 + vp56_rac_get_prob(c, vp8_mbsplit_prob[2]); + } else { + part_idx = VP8_SPLITMVMODE_8x8; + } + } else { + part_idx = VP8_SPLITMVMODE_4x4; + } + + num = vp8_mbsplit_count[part_idx]; + mbsplits_cur = vp8_mbsplits[part_idx], + firstidx = vp8_mbfirstidx[part_idx]; + mb->partitioning = part_idx; + + for (n = 0; n < num; n++) { + int k = firstidx[n]; + uint32_t left, above; + const uint8_t *submv_prob; + + if (!(k & 3)) + left = AV_RN32A(&left_mv[mbsplits_left[k + 3]]); + else + left = AV_RN32A(&cur_mv[mbsplits_cur[k - 1]]); + if (k <= 3) + above = AV_RN32A(&top_mv[mbsplits_top[k + 12]]); + else + above = AV_RN32A(&cur_mv[mbsplits_cur[k - 4]]); + + submv_prob = get_submv_prob(left, above); + + if (vp56_rac_get_prob_branchy(c, submv_prob[0])) { + if (vp56_rac_get_prob_branchy(c, submv_prob[1])) { + if (vp56_rac_get_prob_branchy(c, submv_prob[2])) { + mb->bmv[n].y = mb->mv.y + read_mv_component(c, s->prob->mvc[0]); + mb->bmv[n].x = mb->mv.x + read_mv_component(c, s->prob->mvc[1]); + } else { + AV_ZERO32(&mb->bmv[n]); + } + } else { + AV_WN32A(&mb->bmv[n], above); + } + } else { + AV_WN32A(&mb->bmv[n], left); + } + } + + return num; +} + +static av_always_inline +void decode_mvs(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int layout) +{ + VP8Macroblock *mb_edge[3] = { 0 /* top */, + mb - 1 /* left */, + 0 /* top-left */ }; + enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV }; + enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT }; + int idx = CNT_ZERO; + int cur_sign_bias = s->sign_bias[mb->ref_frame]; + int8_t *sign_bias = s->sign_bias; + VP56mv near_mv[4]; + uint8_t cnt[4] = { 0 }; + VP56RangeCoder *c = &s->c; + + if (!layout) { // layout is inlined (s->mb_layout is not) + mb_edge[0] = mb + 2; + mb_edge[2] = mb + 1; + } + else { + mb_edge[0] = mb - s->mb_width-1; + mb_edge[2] = mb - s->mb_width-2; + } + + AV_ZERO32(&near_mv[0]); + AV_ZERO32(&near_mv[1]); + AV_ZERO32(&near_mv[2]); + + /* Process MB on top, left and top-left */ + #define MV_EDGE_CHECK(n)\ + {\ + VP8Macroblock *edge = mb_edge[n];\ + int edge_ref = edge->ref_frame;\ + if (edge_ref != VP56_FRAME_CURRENT) {\ + uint32_t mv = AV_RN32A(&edge->mv);\ + if (mv) {\ + if (cur_sign_bias != sign_bias[edge_ref]) {\ + /* SWAR negate of the values in mv. */\ + mv = ~mv;\ + mv = ((mv&0x7fff7fff) + 0x00010001) ^ (mv&0x80008000);\ + }\ + if (!n || mv != AV_RN32A(&near_mv[idx]))\ + AV_WN32A(&near_mv[++idx], mv);\ + cnt[idx] += 1 + (n != 2);\ + } else\ + cnt[CNT_ZERO] += 1 + (n != 2);\ + }\ + } + + MV_EDGE_CHECK(0) + MV_EDGE_CHECK(1) + MV_EDGE_CHECK(2) + + mb->partitioning = VP8_SPLITMVMODE_NONE; + if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_ZERO]][0])) { + mb->mode = VP8_MVMODE_MV; + + /* If we have three distinct MVs, merge first and last if they're the same */ + if (cnt[CNT_SPLITMV] && AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT])) + cnt[CNT_NEAREST] += 1; + + /* Swap near and nearest if necessary */ + if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) { + FFSWAP(uint8_t, cnt[CNT_NEAREST], cnt[CNT_NEAR]); + FFSWAP( VP56mv, near_mv[CNT_NEAREST], near_mv[CNT_NEAR]); + } + + if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) { + if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) { + + /* Choose the best mv out of 0,0 and the nearest mv */ + clamp_mv(s, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]); + cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode == VP8_MVMODE_SPLIT) + + (mb_edge[VP8_EDGE_TOP]->mode == VP8_MVMODE_SPLIT)) * 2 + + (mb_edge[VP8_EDGE_TOPLEFT]->mode == VP8_MVMODE_SPLIT); + + if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_SPLITMV]][3])) { + mb->mode = VP8_MVMODE_SPLIT; + mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout) - 1]; + } else { + mb->mv.y += read_mv_component(c, s->prob->mvc[0]); + mb->mv.x += read_mv_component(c, s->prob->mvc[1]); + mb->bmv[0] = mb->mv; + } + } else { + clamp_mv(s, &mb->mv, &near_mv[CNT_NEAR]); + mb->bmv[0] = mb->mv; + } + } else { + clamp_mv(s, &mb->mv, &near_mv[CNT_NEAREST]); + mb->bmv[0] = mb->mv; + } + } else { + mb->mode = VP8_MVMODE_ZERO; + AV_ZERO32(&mb->mv); + mb->bmv[0] = mb->mv; + } +} + +static av_always_inline +void decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb, + int mb_x, int keyframe, int layout) +{ + uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb; + + if (layout == 1) { + VP8Macroblock *mb_top = mb - s->mb_width - 1; + memcpy(mb->intra4x4_pred_mode_top, mb_top->intra4x4_pred_mode_top, 4); + } + if (keyframe) { + int x, y; + uint8_t* top; + uint8_t* const left = s->intra4x4_pred_mode_left; + if (layout == 1) + top = mb->intra4x4_pred_mode_top; + else + top = s->intra4x4_pred_mode_top + 4 * mb_x; + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + const uint8_t *ctx; + ctx = vp8_pred4x4_prob_intra[top[x]][left[y]]; + *intra4x4 = vp8_rac_get_tree(c, vp8_pred4x4_tree, ctx); + left[y] = top[x] = *intra4x4; + intra4x4++; + } + } + } else { + int i; + for (i = 0; i < 16; i++) + intra4x4[i] = vp8_rac_get_tree(c, vp8_pred4x4_tree, vp8_pred4x4_prob_inter); + } +} + +static av_always_inline +void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, + uint8_t *segment, uint8_t *ref, int layout) +{ + VP56RangeCoder *c = &s->c; + + if (s->segmentation.update_map) { + int bit = vp56_rac_get_prob(c, s->prob->segmentid[0]); + *segment = vp56_rac_get_prob(c, s->prob->segmentid[1+bit]) + 2*bit; + } else if (s->segmentation.enabled) + *segment = ref ? *ref : *segment; + mb->segment = *segment; + + mb->skip = s->mbskip_enabled ? vp56_rac_get_prob(c, s->prob->mbskip) : 0; + + if (s->keyframe) { + mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_intra, vp8_pred16x16_prob_intra); + + if (mb->mode == MODE_I4x4) { + decode_intra4x4_modes(s, c, mb, mb_x, 1, layout); + } else { + const uint32_t modes = vp8_pred4x4_mode[mb->mode] * 0x01010101u; + if (s->mb_layout == 1) + AV_WN32A(mb->intra4x4_pred_mode_top, modes); + else + AV_WN32A(s->intra4x4_pred_mode_top + 4 * mb_x, modes); + AV_WN32A( s->intra4x4_pred_mode_left, modes); + } + + mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree, vp8_pred8x8c_prob_intra); + mb->ref_frame = VP56_FRAME_CURRENT; + } else if (vp56_rac_get_prob_branchy(c, s->prob->intra)) { + // inter MB, 16.2 + if (vp56_rac_get_prob_branchy(c, s->prob->last)) + mb->ref_frame = vp56_rac_get_prob(c, s->prob->golden) ? + VP56_FRAME_GOLDEN2 /* altref */ : VP56_FRAME_GOLDEN; + else + mb->ref_frame = VP56_FRAME_PREVIOUS; + s->ref_count[mb->ref_frame-1]++; + + // motion vectors, 16.3 + decode_mvs(s, mb, mb_x, mb_y, layout); + } else { + // intra MB, 16.1 + mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_inter, s->prob->pred16x16); + + if (mb->mode == MODE_I4x4) + decode_intra4x4_modes(s, c, mb, mb_x, 0, layout); + + mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree, s->prob->pred8x8c); + mb->ref_frame = VP56_FRAME_CURRENT; + mb->partitioning = VP8_SPLITMVMODE_NONE; + AV_ZERO32(&mb->bmv[0]); + } +} + +#ifndef decode_block_coeffs_internal +/** + * @param r arithmetic bitstream reader context + * @param block destination for block coefficients + * @param probs probabilities to use when reading trees from the bitstream + * @param i initial coeff index, 0 unless a separate DC block is coded + * @param qmul array holding the dc/ac dequant factor at position 0/1 + * @return 0 if no coeffs were decoded + * otherwise, the index of the last coeff decoded plus one + */ +static int decode_block_coeffs_internal(VP56RangeCoder *r, int16_t block[16], + uint8_t probs[16][3][NUM_DCT_TOKENS-1], + int i, uint8_t *token_prob, int16_t qmul[2]) +{ + VP56RangeCoder c = *r; + goto skip_eob; + do { + int coeff; + if (!vp56_rac_get_prob_branchy(&c, token_prob[0])) // DCT_EOB + break; + +skip_eob: + if (!vp56_rac_get_prob_branchy(&c, token_prob[1])) { // DCT_0 + if (++i == 16) + break; // invalid input; blocks should end with EOB + token_prob = probs[i][0]; + goto skip_eob; + } + + if (!vp56_rac_get_prob_branchy(&c, token_prob[2])) { // DCT_1 + coeff = 1; + token_prob = probs[i+1][1]; + } else { + if (!vp56_rac_get_prob_branchy(&c, token_prob[3])) { // DCT 2,3,4 + coeff = vp56_rac_get_prob_branchy(&c, token_prob[4]); + if (coeff) + coeff += vp56_rac_get_prob(&c, token_prob[5]); + coeff += 2; + } else { + // DCT_CAT* + if (!vp56_rac_get_prob_branchy(&c, token_prob[6])) { + if (!vp56_rac_get_prob_branchy(&c, token_prob[7])) { // DCT_CAT1 + coeff = 5 + vp56_rac_get_prob(&c, vp8_dct_cat1_prob[0]); + } else { // DCT_CAT2 + coeff = 7; + coeff += vp56_rac_get_prob(&c, vp8_dct_cat2_prob[0]) << 1; + coeff += vp56_rac_get_prob(&c, vp8_dct_cat2_prob[1]); + } + } else { // DCT_CAT3 and up + int a = vp56_rac_get_prob(&c, token_prob[8]); + int b = vp56_rac_get_prob(&c, token_prob[9+a]); + int cat = (a<<1) + b; + coeff = 3 + (8<segment; + int block_dc = 0; + + if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) { + nnz_pred = t_nnz[8] + l_nnz[8]; + + // decode DC values and do hadamard + nnz = decode_block_coeffs(c, td->block_dc, s->prob->token[1], 0, nnz_pred, + s->qmat[segment].luma_dc_qmul); + l_nnz[8] = t_nnz[8] = !!nnz; + if (nnz) { + nnz_total += nnz; + block_dc = 1; + if (nnz == 1) + s->vp8dsp.vp8_luma_dc_wht_dc(td->block, td->block_dc); + else + s->vp8dsp.vp8_luma_dc_wht(td->block, td->block_dc); + } + luma_start = 1; + luma_ctx = 0; + } + + // luma blocks + for (y = 0; y < 4; y++) + for (x = 0; x < 4; x++) { + nnz_pred = l_nnz[y] + t_nnz[x]; + nnz = decode_block_coeffs(c, td->block[y][x], s->prob->token[luma_ctx], luma_start, + nnz_pred, s->qmat[segment].luma_qmul); + // nnz+block_dc may be one more than the actual last index, but we don't care + td->non_zero_count_cache[y][x] = nnz + block_dc; + t_nnz[x] = l_nnz[y] = !!nnz; + nnz_total += nnz; + } + + // chroma blocks + // TODO: what to do about dimensions? 2nd dim for luma is x, + // but for chroma it's (y<<1)|x + for (i = 4; i < 6; i++) + for (y = 0; y < 2; y++) + for (x = 0; x < 2; x++) { + nnz_pred = l_nnz[i+2*y] + t_nnz[i+2*x]; + nnz = decode_block_coeffs(c, td->block[i][(y<<1)+x], s->prob->token[2], 0, + nnz_pred, s->qmat[segment].chroma_qmul); + td->non_zero_count_cache[i][(y<<1)+x] = nnz; + t_nnz[i+2*x] = l_nnz[i+2*y] = !!nnz; + nnz_total += nnz; + } + + // if there were no coded coeffs despite the macroblock not being marked skip, + // we MUST not do the inner loop filter and should not do IDCT + // Since skip isn't used for bitstream prediction, just manually set it. + if (!nnz_total) + mb->skip = 1; +} + +static av_always_inline +void backup_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, + int linesize, int uvlinesize, int simple) +{ + AV_COPY128(top_border, src_y + 15*linesize); + if (!simple) { + AV_COPY64(top_border+16, src_cb + 7*uvlinesize); + AV_COPY64(top_border+24, src_cr + 7*uvlinesize); + } +} + +static av_always_inline +void xchg_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, + int linesize, int uvlinesize, int mb_x, int mb_y, int mb_width, + int simple, int xchg) +{ + uint8_t *top_border_m1 = top_border-32; // for TL prediction + src_y -= linesize; + src_cb -= uvlinesize; + src_cr -= uvlinesize; + +#define XCHG(a,b,xchg) do { \ + if (xchg) AV_SWAP64(b,a); \ + else AV_COPY64(b,a); \ + } while (0) + + XCHG(top_border_m1+8, src_y-8, xchg); + XCHG(top_border, src_y, xchg); + XCHG(top_border+8, src_y+8, 1); + if (mb_x < mb_width-1) + XCHG(top_border+32, src_y+16, 1); + + // only copy chroma for normal loop filter + // or to initialize the top row to 127 + if (!simple || !mb_y) { + XCHG(top_border_m1+16, src_cb-8, xchg); + XCHG(top_border_m1+24, src_cr-8, xchg); + XCHG(top_border+16, src_cb, 1); + XCHG(top_border+24, src_cr, 1); + } +} + +static av_always_inline +int check_dc_pred8x8_mode(int mode, int mb_x, int mb_y) +{ + if (!mb_x) { + return mb_y ? TOP_DC_PRED8x8 : DC_128_PRED8x8; + } else { + return mb_y ? mode : LEFT_DC_PRED8x8; + } +} + +static av_always_inline +int check_tm_pred8x8_mode(int mode, int mb_x, int mb_y) +{ + if (!mb_x) { + return mb_y ? VERT_PRED8x8 : DC_129_PRED8x8; + } else { + return mb_y ? mode : HOR_PRED8x8; + } +} + +static av_always_inline +int check_intra_pred8x8_mode(int mode, int mb_x, int mb_y) +{ + if (mode == DC_PRED8x8) { + return check_dc_pred8x8_mode(mode, mb_x, mb_y); + } else { + return mode; + } +} + +static av_always_inline +int check_intra_pred8x8_mode_emuedge(int mode, int mb_x, int mb_y) +{ + switch (mode) { + case DC_PRED8x8: + return check_dc_pred8x8_mode(mode, mb_x, mb_y); + case VERT_PRED8x8: + return !mb_y ? DC_127_PRED8x8 : mode; + case HOR_PRED8x8: + return !mb_x ? DC_129_PRED8x8 : mode; + case PLANE_PRED8x8 /*TM*/: + return check_tm_pred8x8_mode(mode, mb_x, mb_y); + } + return mode; +} + +static av_always_inline +int check_tm_pred4x4_mode(int mode, int mb_x, int mb_y) +{ + if (!mb_x) { + return mb_y ? VERT_VP8_PRED : DC_129_PRED; + } else { + return mb_y ? mode : HOR_VP8_PRED; + } +} + +static av_always_inline +int check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y, int *copy_buf) +{ + switch (mode) { + case VERT_PRED: + if (!mb_x && mb_y) { + *copy_buf = 1; + return mode; + } + /* fall-through */ + case DIAG_DOWN_LEFT_PRED: + case VERT_LEFT_PRED: + return !mb_y ? DC_127_PRED : mode; + case HOR_PRED: + if (!mb_y) { + *copy_buf = 1; + return mode; + } + /* fall-through */ + case HOR_UP_PRED: + return !mb_x ? DC_129_PRED : mode; + case TM_VP8_PRED: + return check_tm_pred4x4_mode(mode, mb_x, mb_y); + case DC_PRED: // 4x4 DC doesn't use the same "H.264-style" exceptions as 16x16/8x8 DC + case DIAG_DOWN_RIGHT_PRED: + case VERT_RIGHT_PRED: + case HOR_DOWN_PRED: + if (!mb_y || !mb_x) + *copy_buf = 1; + return mode; + } + return mode; +} + +static av_always_inline +void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], + VP8Macroblock *mb, int mb_x, int mb_y) +{ + AVCodecContext *avctx = s->avctx; + int x, y, mode, nnz; + uint32_t tr; + + // for the first row, we need to run xchg_mb_border to init the top edge to 127 + // otherwise, skip it if we aren't going to deblock + if (!(avctx->flags & CODEC_FLAG_EMU_EDGE && !mb_y) && (s->deblock_filter || !mb_y) && td->thread_nr == 0) + xchg_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], + s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width, + s->filter.simple, 1); + + if (mb->mode < MODE_I4x4) { + if (avctx->flags & CODEC_FLAG_EMU_EDGE) { // tested + mode = check_intra_pred8x8_mode_emuedge(mb->mode, mb_x, mb_y); + } else { + mode = check_intra_pred8x8_mode(mb->mode, mb_x, mb_y); + } + s->hpc.pred16x16[mode](dst[0], s->linesize); + } else { + uint8_t *ptr = dst[0]; + uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb; + uint8_t tr_top[4] = { 127, 127, 127, 127 }; + + // all blocks on the right edge of the macroblock use bottom edge + // the top macroblock for their topright edge + uint8_t *tr_right = ptr - s->linesize + 16; + + // if we're on the right edge of the frame, said edge is extended + // from the top macroblock + if (!(!mb_y && avctx->flags & CODEC_FLAG_EMU_EDGE) && + mb_x == s->mb_width-1) { + tr = tr_right[-1]*0x01010101u; + tr_right = (uint8_t *)&tr; + } + + if (mb->skip) + AV_ZERO128(td->non_zero_count_cache); + + for (y = 0; y < 4; y++) { + uint8_t *topright = ptr + 4 - s->linesize; + for (x = 0; x < 4; x++) { + int copy = 0, linesize = s->linesize; + uint8_t *dst = ptr+4*x; + DECLARE_ALIGNED(4, uint8_t, copy_dst)[5*8]; + + if ((y == 0 || x == 3) && mb_y == 0 && avctx->flags & CODEC_FLAG_EMU_EDGE) { + topright = tr_top; + } else if (x == 3) + topright = tr_right; + + if (avctx->flags & CODEC_FLAG_EMU_EDGE) { // mb_x+x or mb_y+y is a hack but works + mode = check_intra_pred4x4_mode_emuedge(intra4x4[x], mb_x + x, mb_y + y, ©); + if (copy) { + dst = copy_dst + 12; + linesize = 8; + if (!(mb_y + y)) { + copy_dst[3] = 127U; + AV_WN32A(copy_dst+4, 127U * 0x01010101U); + } else { + AV_COPY32(copy_dst+4, ptr+4*x-s->linesize); + if (!(mb_x + x)) { + copy_dst[3] = 129U; + } else { + copy_dst[3] = ptr[4*x-s->linesize-1]; + } + } + if (!(mb_x + x)) { + copy_dst[11] = + copy_dst[19] = + copy_dst[27] = + copy_dst[35] = 129U; + } else { + copy_dst[11] = ptr[4*x -1]; + copy_dst[19] = ptr[4*x+s->linesize -1]; + copy_dst[27] = ptr[4*x+s->linesize*2-1]; + copy_dst[35] = ptr[4*x+s->linesize*3-1]; + } + } + } else { + mode = intra4x4[x]; + } + s->hpc.pred4x4[mode](dst, topright, linesize); + if (copy) { + AV_COPY32(ptr+4*x , copy_dst+12); + AV_COPY32(ptr+4*x+s->linesize , copy_dst+20); + AV_COPY32(ptr+4*x+s->linesize*2, copy_dst+28); + AV_COPY32(ptr+4*x+s->linesize*3, copy_dst+36); + } + + nnz = td->non_zero_count_cache[y][x]; + if (nnz) { + if (nnz == 1) + s->vp8dsp.vp8_idct_dc_add(ptr+4*x, td->block[y][x], s->linesize); + else + s->vp8dsp.vp8_idct_add(ptr+4*x, td->block[y][x], s->linesize); + } + topright += 4; + } + + ptr += 4*s->linesize; + intra4x4 += 4; + } + } + + if (avctx->flags & CODEC_FLAG_EMU_EDGE) { + mode = check_intra_pred8x8_mode_emuedge(mb->chroma_pred_mode, mb_x, mb_y); + } else { + mode = check_intra_pred8x8_mode(mb->chroma_pred_mode, mb_x, mb_y); + } + s->hpc.pred8x8[mode](dst[1], s->uvlinesize); + s->hpc.pred8x8[mode](dst[2], s->uvlinesize); + + if (!(avctx->flags & CODEC_FLAG_EMU_EDGE && !mb_y) && (s->deblock_filter || !mb_y) && td->thread_nr == 0) + xchg_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], + s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width, + s->filter.simple, 0); +} + +static const uint8_t subpel_idx[3][8] = { + { 0, 1, 2, 1, 2, 1, 2, 1 }, // nr. of left extra pixels, + // also function pointer index + { 0, 3, 5, 3, 5, 3, 5, 3 }, // nr. of extra pixels required + { 0, 2, 3, 2, 3, 2, 3, 2 }, // nr. of right extra pixels +}; + +/** + * luma MC function + * + * @param s VP8 decoding context + * @param dst target buffer for block data at block position + * @param ref reference picture buffer at origin (0, 0) + * @param mv motion vector (relative to block position) to get pixel data from + * @param x_off horizontal position of block from origin (0, 0) + * @param y_off vertical position of block from origin (0, 0) + * @param block_w width of block (16, 8 or 4) + * @param block_h height of block (always same as block_w) + * @param width width of src/dst plane data + * @param height height of src/dst plane data + * @param linesize size of a single line of plane data, including padding + * @param mc_func motion compensation function pointers (bilinear or sixtap MC) + */ +static av_always_inline +void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, + ThreadFrame *ref, const VP56mv *mv, + int x_off, int y_off, int block_w, int block_h, + int width, int height, int linesize, + vp8_mc_func mc_func[3][3]) +{ + uint8_t *src = ref->f->data[0]; + + if (AV_RN32A(mv)) { + + int mx = (mv->x << 1)&7, mx_idx = subpel_idx[0][mx]; + int my = (mv->y << 1)&7, my_idx = subpel_idx[0][my]; + + x_off += mv->x >> 2; + y_off += mv->y >> 2; + + // edge emulation + ff_thread_await_progress(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 4, 0); + src += y_off * linesize + x_off; + if (x_off < mx_idx || x_off >= width - block_w - subpel_idx[2][mx] || + y_off < my_idx || y_off >= height - block_h - subpel_idx[2][my]) { + s->vdsp.emulated_edge_mc(td->edge_emu_buffer, src - my_idx * linesize - mx_idx, linesize, + block_w + subpel_idx[1][mx], block_h + subpel_idx[1][my], + x_off - mx_idx, y_off - my_idx, width, height); + src = td->edge_emu_buffer + mx_idx + linesize * my_idx; + } + mc_func[my_idx][mx_idx](dst, linesize, src, linesize, block_h, mx, my); + } else { + ff_thread_await_progress(ref, (3 + y_off + block_h) >> 4, 0); + mc_func[0][0](dst, linesize, src + y_off * linesize + x_off, linesize, block_h, 0, 0); + } +} + +/** + * chroma MC function + * + * @param s VP8 decoding context + * @param dst1 target buffer for block data at block position (U plane) + * @param dst2 target buffer for block data at block position (V plane) + * @param ref reference picture buffer at origin (0, 0) + * @param mv motion vector (relative to block position) to get pixel data from + * @param x_off horizontal position of block from origin (0, 0) + * @param y_off vertical position of block from origin (0, 0) + * @param block_w width of block (16, 8 or 4) + * @param block_h height of block (always same as block_w) + * @param width width of src/dst plane data + * @param height height of src/dst plane data + * @param linesize size of a single line of plane data, including padding + * @param mc_func motion compensation function pointers (bilinear or sixtap MC) + */ +static av_always_inline +void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, uint8_t *dst2, + ThreadFrame *ref, const VP56mv *mv, int x_off, int y_off, + int block_w, int block_h, int width, int height, int linesize, + vp8_mc_func mc_func[3][3]) +{ + uint8_t *src1 = ref->f->data[1], *src2 = ref->f->data[2]; + + if (AV_RN32A(mv)) { + int mx = mv->x&7, mx_idx = subpel_idx[0][mx]; + int my = mv->y&7, my_idx = subpel_idx[0][my]; + + x_off += mv->x >> 3; + y_off += mv->y >> 3; + + // edge emulation + src1 += y_off * linesize + x_off; + src2 += y_off * linesize + x_off; + ff_thread_await_progress(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 3, 0); + if (x_off < mx_idx || x_off >= width - block_w - subpel_idx[2][mx] || + y_off < my_idx || y_off >= height - block_h - subpel_idx[2][my]) { + s->vdsp.emulated_edge_mc(td->edge_emu_buffer, src1 - my_idx * linesize - mx_idx, linesize, + block_w + subpel_idx[1][mx], block_h + subpel_idx[1][my], + x_off - mx_idx, y_off - my_idx, width, height); + src1 = td->edge_emu_buffer + mx_idx + linesize * my_idx; + mc_func[my_idx][mx_idx](dst1, linesize, src1, linesize, block_h, mx, my); + + s->vdsp.emulated_edge_mc(td->edge_emu_buffer, src2 - my_idx * linesize - mx_idx, linesize, + block_w + subpel_idx[1][mx], block_h + subpel_idx[1][my], + x_off - mx_idx, y_off - my_idx, width, height); + src2 = td->edge_emu_buffer + mx_idx + linesize * my_idx; + mc_func[my_idx][mx_idx](dst2, linesize, src2, linesize, block_h, mx, my); + } else { + mc_func[my_idx][mx_idx](dst1, linesize, src1, linesize, block_h, mx, my); + mc_func[my_idx][mx_idx](dst2, linesize, src2, linesize, block_h, mx, my); + } + } else { + ff_thread_await_progress(ref, (3 + y_off + block_h) >> 3, 0); + mc_func[0][0](dst1, linesize, src1 + y_off * linesize + x_off, linesize, block_h, 0, 0); + mc_func[0][0](dst2, linesize, src2 + y_off * linesize + x_off, linesize, block_h, 0, 0); + } +} + +static av_always_inline +void vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], + ThreadFrame *ref_frame, int x_off, int y_off, + int bx_off, int by_off, + int block_w, int block_h, + int width, int height, VP56mv *mv) +{ + VP56mv uvmv = *mv; + + /* Y */ + vp8_mc_luma(s, td, dst[0] + by_off * s->linesize + bx_off, + ref_frame, mv, x_off + bx_off, y_off + by_off, + block_w, block_h, width, height, s->linesize, + s->put_pixels_tab[block_w == 8]); + + /* U/V */ + if (s->profile == 3) { + uvmv.x &= ~7; + uvmv.y &= ~7; + } + x_off >>= 1; y_off >>= 1; + bx_off >>= 1; by_off >>= 1; + width >>= 1; height >>= 1; + block_w >>= 1; block_h >>= 1; + vp8_mc_chroma(s, td, dst[1] + by_off * s->uvlinesize + bx_off, + dst[2] + by_off * s->uvlinesize + bx_off, ref_frame, + &uvmv, x_off + bx_off, y_off + by_off, + block_w, block_h, width, height, s->uvlinesize, + s->put_pixels_tab[1 + (block_w == 4)]); +} + +/* Fetch pixels for estimated mv 4 macroblocks ahead. + * Optimized for 64-byte cache lines. Inspired by ffh264 prefetch_motion. */ +static av_always_inline void prefetch_motion(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y, int mb_xy, int ref) +{ + /* Don't prefetch refs that haven't been used very often this frame. */ + if (s->ref_count[ref-1] > (mb_xy >> 5)) { + int x_off = mb_x << 4, y_off = mb_y << 4; + int mx = (mb->mv.x>>2) + x_off + 8; + int my = (mb->mv.y>>2) + y_off; + uint8_t **src= s->framep[ref]->tf.f->data; + int off= mx + (my + (mb_x&3)*4)*s->linesize + 64; + /* For threading, a ff_thread_await_progress here might be useful, but + * it actually slows down the decoder. Since a bad prefetch doesn't + * generate bad decoder output, we don't run it here. */ + s->vdsp.prefetch(src[0]+off, s->linesize, 4); + off= (mx>>1) + ((my>>1) + (mb_x&7))*s->uvlinesize + 64; + s->vdsp.prefetch(src[1]+off, src[2]-src[1], 2); + } +} + +/** + * Apply motion vectors to prediction buffer, chapter 18. + */ +static av_always_inline +void inter_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], + VP8Macroblock *mb, int mb_x, int mb_y) +{ + int x_off = mb_x << 4, y_off = mb_y << 4; + int width = 16*s->mb_width, height = 16*s->mb_height; + ThreadFrame *ref = &s->framep[mb->ref_frame]->tf; + VP56mv *bmv = mb->bmv; + + switch (mb->partitioning) { + case VP8_SPLITMVMODE_NONE: + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 0, 0, 16, 16, width, height, &mb->mv); + break; + case VP8_SPLITMVMODE_4x4: { + int x, y; + VP56mv uvmv; + + /* Y */ + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + vp8_mc_luma(s, td, dst[0] + 4*y*s->linesize + x*4, + ref, &bmv[4*y + x], + 4*x + x_off, 4*y + y_off, 4, 4, + width, height, s->linesize, + s->put_pixels_tab[2]); + } + } + + /* U/V */ + x_off >>= 1; y_off >>= 1; width >>= 1; height >>= 1; + for (y = 0; y < 2; y++) { + for (x = 0; x < 2; x++) { + uvmv.x = mb->bmv[ 2*y * 4 + 2*x ].x + + mb->bmv[ 2*y * 4 + 2*x+1].x + + mb->bmv[(2*y+1) * 4 + 2*x ].x + + mb->bmv[(2*y+1) * 4 + 2*x+1].x; + uvmv.y = mb->bmv[ 2*y * 4 + 2*x ].y + + mb->bmv[ 2*y * 4 + 2*x+1].y + + mb->bmv[(2*y+1) * 4 + 2*x ].y + + mb->bmv[(2*y+1) * 4 + 2*x+1].y; + uvmv.x = (uvmv.x + 2 + (uvmv.x >> (INT_BIT-1))) >> 2; + uvmv.y = (uvmv.y + 2 + (uvmv.y >> (INT_BIT-1))) >> 2; + if (s->profile == 3) { + uvmv.x &= ~7; + uvmv.y &= ~7; + } + vp8_mc_chroma(s, td, dst[1] + 4*y*s->uvlinesize + x*4, + dst[2] + 4*y*s->uvlinesize + x*4, ref, &uvmv, + 4*x + x_off, 4*y + y_off, 4, 4, + width, height, s->uvlinesize, + s->put_pixels_tab[2]); + } + } + break; + } + case VP8_SPLITMVMODE_16x8: + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 0, 0, 16, 8, width, height, &bmv[0]); + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 0, 8, 16, 8, width, height, &bmv[1]); + break; + case VP8_SPLITMVMODE_8x16: + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 0, 0, 8, 16, width, height, &bmv[0]); + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 8, 0, 8, 16, width, height, &bmv[1]); + break; + case VP8_SPLITMVMODE_8x8: + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 0, 0, 8, 8, width, height, &bmv[0]); + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 8, 0, 8, 8, width, height, &bmv[1]); + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 0, 8, 8, 8, width, height, &bmv[2]); + vp8_mc_part(s, td, dst, ref, x_off, y_off, + 8, 8, 8, 8, width, height, &bmv[3]); + break; + } +} + +static av_always_inline void idct_mb(VP8Context *s, VP8ThreadData *td, + uint8_t *dst[3], VP8Macroblock *mb) +{ + int x, y, ch; + + if (mb->mode != MODE_I4x4) { + uint8_t *y_dst = dst[0]; + for (y = 0; y < 4; y++) { + uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[y]); + if (nnz4) { + if (nnz4&~0x01010101) { + for (x = 0; x < 4; x++) { + if ((uint8_t)nnz4 == 1) + s->vp8dsp.vp8_idct_dc_add(y_dst+4*x, td->block[y][x], s->linesize); + else if((uint8_t)nnz4 > 1) + s->vp8dsp.vp8_idct_add(y_dst+4*x, td->block[y][x], s->linesize); + nnz4 >>= 8; + if (!nnz4) + break; + } + } else { + s->vp8dsp.vp8_idct_dc_add4y(y_dst, td->block[y], s->linesize); + } + } + y_dst += 4*s->linesize; + } + } + + for (ch = 0; ch < 2; ch++) { + uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[4+ch]); + if (nnz4) { + uint8_t *ch_dst = dst[1+ch]; + if (nnz4&~0x01010101) { + for (y = 0; y < 2; y++) { + for (x = 0; x < 2; x++) { + if ((uint8_t)nnz4 == 1) + s->vp8dsp.vp8_idct_dc_add(ch_dst+4*x, td->block[4+ch][(y<<1)+x], s->uvlinesize); + else if((uint8_t)nnz4 > 1) + s->vp8dsp.vp8_idct_add(ch_dst+4*x, td->block[4+ch][(y<<1)+x], s->uvlinesize); + nnz4 >>= 8; + if (!nnz4) + goto chroma_idct_end; + } + ch_dst += 4*s->uvlinesize; + } + } else { + s->vp8dsp.vp8_idct_dc_add4uv(ch_dst, td->block[4+ch], s->uvlinesize); + } + } +chroma_idct_end: ; + } +} + +static av_always_inline void filter_level_for_mb(VP8Context *s, VP8Macroblock *mb, VP8FilterStrength *f ) +{ + int interior_limit, filter_level; + + if (s->segmentation.enabled) { + filter_level = s->segmentation.filter_level[mb->segment]; + if (!s->segmentation.absolute_vals) + filter_level += s->filter.level; + } else + filter_level = s->filter.level; + + if (s->lf_delta.enabled) { + filter_level += s->lf_delta.ref[mb->ref_frame]; + filter_level += s->lf_delta.mode[mb->mode]; + } + + filter_level = av_clip_uintp2(filter_level, 6); + + interior_limit = filter_level; + if (s->filter.sharpness) { + interior_limit >>= (s->filter.sharpness + 3) >> 2; + interior_limit = FFMIN(interior_limit, 9 - s->filter.sharpness); + } + interior_limit = FFMAX(interior_limit, 1); + + f->filter_level = filter_level; + f->inner_limit = interior_limit; + f->inner_filter = !mb->skip || mb->mode == MODE_I4x4 || mb->mode == VP8_MVMODE_SPLIT; +} + +static av_always_inline void filter_mb(VP8Context *s, uint8_t *dst[3], VP8FilterStrength *f, int mb_x, int mb_y) +{ + int mbedge_lim, bedge_lim, hev_thresh; + int filter_level = f->filter_level; + int inner_limit = f->inner_limit; + int inner_filter = f->inner_filter; + int linesize = s->linesize; + int uvlinesize = s->uvlinesize; + static const uint8_t hev_thresh_lut[2][64] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2 } + }; + + if (!filter_level) + return; + + bedge_lim = 2*filter_level + inner_limit; + mbedge_lim = bedge_lim + 4; + + hev_thresh = hev_thresh_lut[s->keyframe][filter_level]; + + if (mb_x) { + s->vp8dsp.vp8_h_loop_filter16y(dst[0], linesize, + mbedge_lim, inner_limit, hev_thresh); + s->vp8dsp.vp8_h_loop_filter8uv(dst[1], dst[2], uvlinesize, + mbedge_lim, inner_limit, hev_thresh); + } + + if (inner_filter) { + s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0]+ 4, linesize, bedge_lim, + inner_limit, hev_thresh); + s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0]+ 8, linesize, bedge_lim, + inner_limit, hev_thresh); + s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0]+12, linesize, bedge_lim, + inner_limit, hev_thresh); + s->vp8dsp.vp8_h_loop_filter8uv_inner(dst[1] + 4, dst[2] + 4, + uvlinesize, bedge_lim, + inner_limit, hev_thresh); + } + + if (mb_y) { + s->vp8dsp.vp8_v_loop_filter16y(dst[0], linesize, + mbedge_lim, inner_limit, hev_thresh); + s->vp8dsp.vp8_v_loop_filter8uv(dst[1], dst[2], uvlinesize, + mbedge_lim, inner_limit, hev_thresh); + } + + if (inner_filter) { + s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0]+ 4*linesize, + linesize, bedge_lim, + inner_limit, hev_thresh); + s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0]+ 8*linesize, + linesize, bedge_lim, + inner_limit, hev_thresh); + s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0]+12*linesize, + linesize, bedge_lim, + inner_limit, hev_thresh); + s->vp8dsp.vp8_v_loop_filter8uv_inner(dst[1] + 4 * uvlinesize, + dst[2] + 4 * uvlinesize, + uvlinesize, bedge_lim, + inner_limit, hev_thresh); + } +} + +static av_always_inline void filter_mb_simple(VP8Context *s, uint8_t *dst, VP8FilterStrength *f, int mb_x, int mb_y) +{ + int mbedge_lim, bedge_lim; + int filter_level = f->filter_level; + int inner_limit = f->inner_limit; + int inner_filter = f->inner_filter; + int linesize = s->linesize; + + if (!filter_level) + return; + + bedge_lim = 2*filter_level + inner_limit; + mbedge_lim = bedge_lim + 4; + + if (mb_x) + s->vp8dsp.vp8_h_loop_filter_simple(dst, linesize, mbedge_lim); + if (inner_filter) { + s->vp8dsp.vp8_h_loop_filter_simple(dst+ 4, linesize, bedge_lim); + s->vp8dsp.vp8_h_loop_filter_simple(dst+ 8, linesize, bedge_lim); + s->vp8dsp.vp8_h_loop_filter_simple(dst+12, linesize, bedge_lim); + } + + if (mb_y) + s->vp8dsp.vp8_v_loop_filter_simple(dst, linesize, mbedge_lim); + if (inner_filter) { + s->vp8dsp.vp8_v_loop_filter_simple(dst+ 4*linesize, linesize, bedge_lim); + s->vp8dsp.vp8_v_loop_filter_simple(dst+ 8*linesize, linesize, bedge_lim); + s->vp8dsp.vp8_v_loop_filter_simple(dst+12*linesize, linesize, bedge_lim); + } +} + +#define MARGIN (16 << 2) +static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe, + VP8Frame *prev_frame) +{ + VP8Context *s = avctx->priv_data; + int mb_x, mb_y; + + s->mv_min.y = -MARGIN; + s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN; + for (mb_y = 0; mb_y < s->mb_height; mb_y++) { + VP8Macroblock *mb = s->macroblocks_base + ((s->mb_width+1)*(mb_y + 1) + 1); + int mb_xy = mb_y*s->mb_width; + + AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101); + + s->mv_min.x = -MARGIN; + s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; + for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { + if (mb_y == 0) + AV_WN32A((mb-s->mb_width-1)->intra4x4_pred_mode_top, DC_PRED*0x01010101); + decode_mb_mode(s, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy, + prev_frame && prev_frame->seg_map ? + prev_frame->seg_map->data + mb_xy : NULL, 1); + s->mv_min.x -= 64; + s->mv_max.x -= 64; + } + s->mv_min.y -= 64; + s->mv_max.y -= 64; + } +} + +#if HAVE_THREADS +#define check_thread_pos(td, otd, mb_x_check, mb_y_check)\ + do {\ + int tmp = (mb_y_check << 16) | (mb_x_check & 0xFFFF);\ + if (otd->thread_mb_pos < tmp) {\ + pthread_mutex_lock(&otd->lock);\ + td->wait_mb_pos = tmp;\ + do {\ + if (otd->thread_mb_pos >= tmp)\ + break;\ + pthread_cond_wait(&otd->cond, &otd->lock);\ + } while (1);\ + td->wait_mb_pos = INT_MAX;\ + pthread_mutex_unlock(&otd->lock);\ + }\ + } while(0); + +#define update_pos(td, mb_y, mb_x)\ + do {\ + int pos = (mb_y << 16) | (mb_x & 0xFFFF);\ + int sliced_threading = (avctx->active_thread_type == FF_THREAD_SLICE) && (num_jobs > 1);\ + int is_null = (next_td == NULL) || (prev_td == NULL);\ + int pos_check = (is_null) ? 1 :\ + (next_td != td && pos >= next_td->wait_mb_pos) ||\ + (prev_td != td && pos >= prev_td->wait_mb_pos);\ + td->thread_mb_pos = pos;\ + if (sliced_threading && pos_check) {\ + pthread_mutex_lock(&td->lock);\ + pthread_cond_broadcast(&td->cond);\ + pthread_mutex_unlock(&td->lock);\ + }\ + } while(0); +#else +#define check_thread_pos(td, otd, mb_x_check, mb_y_check) +#define update_pos(td, mb_y, mb_x) +#endif + +static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + VP8Context *s = avctx->priv_data; + VP8ThreadData *prev_td, *next_td, *td = &s->thread_data[threadnr]; + int mb_y = td->thread_mb_pos>>16; + int i, y, mb_x, mb_xy = mb_y*s->mb_width; + int num_jobs = s->num_jobs; + VP8Frame *curframe = s->curframe, *prev_frame = s->prev_frame; + VP56RangeCoder *c = &s->coeff_partition[mb_y & (s->num_coeff_partitions-1)]; + VP8Macroblock *mb; + uint8_t *dst[3] = { + curframe->tf.f->data[0] + 16*mb_y*s->linesize, + curframe->tf.f->data[1] + 8*mb_y*s->uvlinesize, + curframe->tf.f->data[2] + 8*mb_y*s->uvlinesize + }; + if (mb_y == 0) prev_td = td; + else prev_td = &s->thread_data[(jobnr + num_jobs - 1)%num_jobs]; + if (mb_y == s->mb_height-1) next_td = td; + else next_td = &s->thread_data[(jobnr + 1)%num_jobs]; + if (s->mb_layout == 1) + mb = s->macroblocks_base + ((s->mb_width+1)*(mb_y + 1) + 1); + else { + mb = s->macroblocks + (s->mb_height - mb_y - 1)*2; + memset(mb - 1, 0, sizeof(*mb)); // zero left macroblock + AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101); + } + + memset(td->left_nnz, 0, sizeof(td->left_nnz)); + // left edge of 129 for intra prediction + if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { + for (i = 0; i < 3; i++) + for (y = 0; y < 16>>!!i; y++) + dst[i][y*curframe->tf.f->linesize[i]-1] = 129; + if (mb_y == 1) { + s->top_border[0][15] = s->top_border[0][23] = s->top_border[0][31] = 129; + } + } + + s->mv_min.x = -MARGIN; + s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; + + for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { + // Wait for previous thread to read mb_x+2, and reach mb_y-1. + if (prev_td != td) { + if (threadnr != 0) { + check_thread_pos(td, prev_td, mb_x+1, mb_y-1); + } else { + check_thread_pos(td, prev_td, (s->mb_width+3) + (mb_x+1), mb_y-1); + } + } + + s->vdsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4); + s->vdsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1], 2); + + if (!s->mb_layout) + decode_mb_mode(s, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy, + prev_frame && prev_frame->seg_map ? + prev_frame->seg_map->data + mb_xy : NULL, 0); + + prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS); + + if (!mb->skip) + decode_mb_coeffs(s, td, c, mb, s->top_nnz[mb_x], td->left_nnz); + + if (mb->mode <= MODE_I4x4) + intra_predict(s, td, dst, mb, mb_x, mb_y); + else + inter_predict(s, td, dst, mb, mb_x, mb_y); + + prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN); + + if (!mb->skip) { + idct_mb(s, td, dst, mb); + } else { + AV_ZERO64(td->left_nnz); + AV_WN64(s->top_nnz[mb_x], 0); // array of 9, so unaligned + + // Reset DC block predictors if they would exist if the mb had coefficients + if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) { + td->left_nnz[8] = 0; + s->top_nnz[mb_x][8] = 0; + } + } + + if (s->deblock_filter) + filter_level_for_mb(s, mb, &td->filter_strength[mb_x]); + + if (s->deblock_filter && num_jobs != 1 && threadnr == num_jobs-1) { + if (s->filter.simple) + backup_mb_border(s->top_border[mb_x+1], dst[0], NULL, NULL, s->linesize, 0, 1); + else + backup_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], s->linesize, s->uvlinesize, 0); + } + + prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN2); + + dst[0] += 16; + dst[1] += 8; + dst[2] += 8; + s->mv_min.x -= 64; + s->mv_max.x -= 64; + + if (mb_x == s->mb_width+1) { + update_pos(td, mb_y, s->mb_width+3); + } else { + update_pos(td, mb_y, mb_x); + } + } +} + +static void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + VP8Context *s = avctx->priv_data; + VP8ThreadData *td = &s->thread_data[threadnr]; + int mb_x, mb_y = td->thread_mb_pos>>16, num_jobs = s->num_jobs; + AVFrame *curframe = s->curframe->tf.f; + VP8Macroblock *mb; + VP8ThreadData *prev_td, *next_td; + uint8_t *dst[3] = { + curframe->data[0] + 16*mb_y*s->linesize, + curframe->data[1] + 8*mb_y*s->uvlinesize, + curframe->data[2] + 8*mb_y*s->uvlinesize + }; + + if (s->mb_layout == 1) + mb = s->macroblocks_base + ((s->mb_width+1)*(mb_y + 1) + 1); + else + mb = s->macroblocks + (s->mb_height - mb_y - 1)*2; + + if (mb_y == 0) prev_td = td; + else prev_td = &s->thread_data[(jobnr + num_jobs - 1)%num_jobs]; + if (mb_y == s->mb_height-1) next_td = td; + else next_td = &s->thread_data[(jobnr + 1)%num_jobs]; + + for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb++) { + VP8FilterStrength *f = &td->filter_strength[mb_x]; + if (prev_td != td) { + check_thread_pos(td, prev_td, (mb_x+1) + (s->mb_width+3), mb_y-1); + } + if (next_td != td) + if (next_td != &s->thread_data[0]) { + check_thread_pos(td, next_td, mb_x+1, mb_y+1); + } + + if (num_jobs == 1) { + if (s->filter.simple) + backup_mb_border(s->top_border[mb_x+1], dst[0], NULL, NULL, s->linesize, 0, 1); + else + backup_mb_border(s->top_border[mb_x+1], dst[0], dst[1], dst[2], s->linesize, s->uvlinesize, 0); + } + + if (s->filter.simple) + filter_mb_simple(s, dst[0], f, mb_x, mb_y); + else + filter_mb(s, dst, f, mb_x, mb_y); + dst[0] += 16; + dst[1] += 8; + dst[2] += 8; + + update_pos(td, mb_y, (s->mb_width+3) + mb_x); + } +} + +static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, + int jobnr, int threadnr) +{ + VP8Context *s = avctx->priv_data; + VP8ThreadData *td = &s->thread_data[jobnr]; + VP8ThreadData *next_td = NULL, *prev_td = NULL; + VP8Frame *curframe = s->curframe; + int mb_y, num_jobs = s->num_jobs; + td->thread_nr = threadnr; + for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) { + if (mb_y >= s->mb_height) break; + td->thread_mb_pos = mb_y<<16; + vp8_decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr); + if (s->deblock_filter) + vp8_filter_mb_row(avctx, tdata, jobnr, threadnr); + update_pos(td, mb_y, INT_MAX & 0xFFFF); + + s->mv_min.y -= 64; + s->mv_max.y -= 64; + + if (avctx->active_thread_type == FF_THREAD_FRAME) + ff_thread_report_progress(&curframe->tf, mb_y, 0); + } + + return 0; +} + +static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + VP8Context *s = avctx->priv_data; + int ret, i, referenced, num_jobs; + enum AVDiscard skip_thresh; + VP8Frame *av_uninit(curframe), *prev_frame; + + if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0) + goto err; + + prev_frame = s->framep[VP56_FRAME_CURRENT]; + + referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT + || s->update_altref == VP56_FRAME_CURRENT; + + skip_thresh = !referenced ? AVDISCARD_NONREF : + !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL; + + if (avctx->skip_frame >= skip_thresh) { + s->invisible = 1; + memcpy(&s->next_framep[0], &s->framep[0], sizeof(s->framep[0]) * 4); + goto skip_decode; + } + s->deblock_filter = s->filter.level && avctx->skip_loop_filter < skip_thresh; + + // release no longer referenced frames + for (i = 0; i < 5; i++) + if (s->frames[i].tf.f->data[0] && + &s->frames[i] != prev_frame && + &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) + vp8_release_frame(s, &s->frames[i]); + + // find a free buffer + for (i = 0; i < 5; i++) + if (&s->frames[i] != prev_frame && + &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && + &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) { + curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i]; + break; + } + if (i == 5) { + av_log(avctx, AV_LOG_FATAL, "Ran out of free frames!\n"); + abort(); + } + if (curframe->tf.f->data[0]) + vp8_release_frame(s, curframe); + + // Given that arithmetic probabilities are updated every frame, it's quite likely + // that the values we have on a random interframe are complete junk if we didn't + // start decode on a keyframe. So just don't display anything rather than junk. + if (!s->keyframe && (!s->framep[VP56_FRAME_PREVIOUS] || + !s->framep[VP56_FRAME_GOLDEN] || + !s->framep[VP56_FRAME_GOLDEN2])) { + av_log(avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n"); + ret = AVERROR_INVALIDDATA; + goto err; + } + + curframe->tf.f->key_frame = s->keyframe; + curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0) + goto err; + + // check if golden and altref are swapped + if (s->update_altref != VP56_FRAME_NONE) { + s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref]; + } else { + s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[VP56_FRAME_GOLDEN2]; + } + if (s->update_golden != VP56_FRAME_NONE) { + s->next_framep[VP56_FRAME_GOLDEN] = s->framep[s->update_golden]; + } else { + s->next_framep[VP56_FRAME_GOLDEN] = s->framep[VP56_FRAME_GOLDEN]; + } + if (s->update_last) { + s->next_framep[VP56_FRAME_PREVIOUS] = curframe; + } else { + s->next_framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_PREVIOUS]; + } + s->next_framep[VP56_FRAME_CURRENT] = curframe; + + ff_thread_finish_setup(avctx); + + s->linesize = curframe->tf.f->linesize[0]; + s->uvlinesize = curframe->tf.f->linesize[1]; + + if (!s->thread_data[0].edge_emu_buffer) + for (i = 0; i < MAX_THREADS; i++) + s->thread_data[i].edge_emu_buffer = av_malloc(21*s->linesize); + + memset(s->top_nnz, 0, s->mb_width*sizeof(*s->top_nnz)); + /* Zero macroblock structures for top/top-left prediction from outside the frame. */ + if (!s->mb_layout) + memset(s->macroblocks + s->mb_height*2 - 1, 0, (s->mb_width+1)*sizeof(*s->macroblocks)); + if (!s->mb_layout && s->keyframe) + memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width*4); + + // top edge of 127 for intra prediction + if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { + s->top_border[0][15] = s->top_border[0][23] = 127; + s->top_border[0][31] = 127; + memset(s->top_border[1], 127, s->mb_width*sizeof(*s->top_border)); + } + memset(s->ref_count, 0, sizeof(s->ref_count)); + + + // Make sure the previous frame has read its segmentation map, + // if we re-use the same map. + if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map) + ff_thread_await_progress(&prev_frame->tf, 1, 0); + + if (s->mb_layout == 1) + vp8_decode_mv_mb_modes(avctx, curframe, prev_frame); + + if (avctx->active_thread_type == FF_THREAD_FRAME) + num_jobs = 1; + else + num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count); + s->num_jobs = num_jobs; + s->curframe = curframe; + s->prev_frame = prev_frame; + s->mv_min.y = -MARGIN; + s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN; + for (i = 0; i < MAX_THREADS; i++) { + s->thread_data[i].thread_mb_pos = 0; + s->thread_data[i].wait_mb_pos = INT_MAX; + } + avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL, num_jobs); + + ff_thread_report_progress(&curframe->tf, INT_MAX, 0); + memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4); + +skip_decode: + // if future frames don't use the updated probabilities, + // reset them to the values we saved + if (!s->update_probabilities) + s->prob[0] = s->prob[1]; + + if (!s->invisible) { + if ((ret = av_frame_ref(data, curframe->tf.f)) < 0) + return ret; + *got_frame = 1; + } + + return avpkt->size; +err: + memcpy(&s->next_framep[0], &s->framep[0], sizeof(s->framep[0]) * 4); + return ret; +} + +static av_cold int vp8_decode_free(AVCodecContext *avctx) +{ + VP8Context *s = avctx->priv_data; + int i; + + vp8_decode_flush_impl(avctx, 1); + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) + av_frame_free(&s->frames[i].tf.f); + + return 0; +} + +static av_cold int vp8_init_frames(VP8Context *s) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) { + s->frames[i].tf.f = av_frame_alloc(); + if (!s->frames[i].tf.f) + return AVERROR(ENOMEM); + } + return 0; +} + +static av_cold int vp8_decode_init(AVCodecContext *avctx) +{ + VP8Context *s = avctx->priv_data; + int ret; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + avctx->internal->allocate_progress = 1; + + ff_videodsp_init(&s->vdsp, 8); + ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP8, 8, 1); + ff_vp8dsp_init(&s->vp8dsp); + + if ((ret = vp8_init_frames(s)) < 0) { + vp8_decode_free(avctx); + return ret; + } + + return 0; +} + +static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx) +{ + VP8Context *s = avctx->priv_data; + int ret; + + s->avctx = avctx; + + if ((ret = vp8_init_frames(s)) < 0) { + vp8_decode_free(avctx); + return ret; + } + + return 0; +} + +#define REBASE(pic) \ + pic ? pic - &s_src->frames[0] + &s->frames[0] : NULL + +static int vp8_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + VP8Context *s = dst->priv_data, *s_src = src->priv_data; + int i; + + if (s->macroblocks_base && + (s_src->mb_width != s->mb_width || s_src->mb_height != s->mb_height)) { + free_buffers(s); + s->mb_width = s_src->mb_width; + s->mb_height = s_src->mb_height; + } + + s->prob[0] = s_src->prob[!s_src->update_probabilities]; + s->segmentation = s_src->segmentation; + s->lf_delta = s_src->lf_delta; + memcpy(s->sign_bias, s_src->sign_bias, sizeof(s->sign_bias)); + + for (i = 0; i < FF_ARRAY_ELEMS(s_src->frames); i++) { + if (s_src->frames[i].tf.f->data[0]) { + int ret = vp8_ref_frame(s, &s->frames[i], &s_src->frames[i]); + if (ret < 0) + return ret; + } + } + + s->framep[0] = REBASE(s_src->next_framep[0]); + s->framep[1] = REBASE(s_src->next_framep[1]); + s->framep[2] = REBASE(s_src->next_framep[2]); + s->framep[3] = REBASE(s_src->next_framep[3]); + + return 0; +} + +AVCodec ff_vp8_decoder = { + .name = "vp8", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP8, + .priv_data_size = sizeof(VP8Context), + .init = vp8_decode_init, + .close = vp8_decode_free, + .decode = vp8_decode_frame, + .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS, + .flush = vp8_decode_flush, + .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), + .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy), + .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context), +}; diff --git a/ffmpeg/libavcodec/vp8.h b/ffmpeg/libavcodec/vp8.h new file mode 100644 index 0000000..90109ad --- /dev/null +++ b/ffmpeg/libavcodec/vp8.h @@ -0,0 +1,275 @@ +/* + * VP8 compatible video decoder + * + * Copyright (C) 2010 David Conrad + * Copyright (C) 2010 Ronald S. Bultje + * Copyright (C) 2010 Jason Garrett-Glaser + * Copyright (C) 2012 Daniel Kang + * + * 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 + */ + +#ifndef AVCODEC_VP8_H +#define AVCODEC_VP8_H + +#include "libavutil/buffer.h" + +#include "vp56.h" +#include "vp56data.h" +#include "vp8dsp.h" +#include "h264pred.h" +#include "thread.h" +#if HAVE_PTHREADS +#include +#elif HAVE_W32THREADS +#include "w32pthreads.h" +#elif HAVE_OS2THREADS +#include "os2threads.h" +#endif + +#define VP8_MAX_QUANT 127 + +enum dct_token { + DCT_0, + DCT_1, + DCT_2, + DCT_3, + DCT_4, + DCT_CAT1, + DCT_CAT2, + DCT_CAT3, + DCT_CAT4, + DCT_CAT5, + DCT_CAT6, + DCT_EOB, + + NUM_DCT_TOKENS +}; + +// used to signal 4x4 intra pred in luma MBs +#define MODE_I4x4 4 + +enum inter_mvmode { + VP8_MVMODE_ZERO = MODE_I4x4 + 1, + VP8_MVMODE_MV, + VP8_MVMODE_SPLIT +}; + +enum inter_splitmvmode { + VP8_SPLITMVMODE_16x8 = 0, ///< 2 16x8 blocks (vertical) + VP8_SPLITMVMODE_8x16, ///< 2 8x16 blocks (horizontal) + VP8_SPLITMVMODE_8x8, ///< 2x2 blocks of 8x8px each + VP8_SPLITMVMODE_4x4, ///< 4x4 blocks of 4x4px each + VP8_SPLITMVMODE_NONE, ///< (only used in prediction) no split MVs +}; + +typedef struct VP8FilterStrength { + uint8_t filter_level; + uint8_t inner_limit; + uint8_t inner_filter; +} VP8FilterStrength; + +typedef struct VP8Macroblock { + uint8_t skip; + // todo: make it possible to check for at least (i4x4 or split_mv) + // in one op. are others needed? + uint8_t mode; + uint8_t ref_frame; + uint8_t partitioning; + uint8_t chroma_pred_mode; + uint8_t segment; + uint8_t intra4x4_pred_mode_mb[16]; + uint8_t intra4x4_pred_mode_top[4]; + VP56mv mv; + VP56mv bmv[16]; +} VP8Macroblock; + +typedef struct VP8ThreadData { + DECLARE_ALIGNED(16, int16_t, block)[6][4][16]; + DECLARE_ALIGNED(16, int16_t, block_dc)[16]; + /** + * This is the index plus one of the last non-zero coeff + * for each of the blocks in the current macroblock. + * So, 0 -> no coeffs + * 1 -> dc-only (special transform) + * 2+-> full transform + */ + DECLARE_ALIGNED(16, uint8_t, non_zero_count_cache)[6][4]; + /** + * For coeff decode, we need to know whether the above block had non-zero + * coefficients. This means for each macroblock, we need data for 4 luma + * blocks, 2 u blocks, 2 v blocks, and the luma dc block, for a total of 9 + * per macroblock. We keep the last row in top_nnz. + */ + DECLARE_ALIGNED(8, uint8_t, left_nnz)[9]; + int thread_nr; +#if HAVE_THREADS + pthread_mutex_t lock; + pthread_cond_t cond; +#endif + int thread_mb_pos; // (mb_y << 16) | (mb_x & 0xFFFF) + int wait_mb_pos; // What the current thread is waiting on. + uint8_t *edge_emu_buffer; + VP8FilterStrength *filter_strength; +} VP8ThreadData; + +typedef struct VP8Frame { + ThreadFrame tf; + AVBufferRef *seg_map; +} VP8Frame; + +#define MAX_THREADS 8 +typedef struct VP8Context { + VP8ThreadData *thread_data; + AVCodecContext *avctx; + VP8Frame *framep[4]; + VP8Frame *next_framep[4]; + VP8Frame *curframe; + VP8Frame *prev_frame; + + uint16_t mb_width; /* number of horizontal MB */ + uint16_t mb_height; /* number of vertical MB */ + int linesize; + int uvlinesize; + + uint8_t keyframe; + uint8_t deblock_filter; + uint8_t mbskip_enabled; + uint8_t profile; + VP56mv mv_min; + VP56mv mv_max; + + int8_t sign_bias[4]; ///< one state [0, 1] per ref frame type + int ref_count[3]; + + /** + * Base parameters for segmentation, i.e. per-macroblock parameters. + * These must be kept unchanged even if segmentation is not used for + * a frame, since the values persist between interframes. + */ + struct { + uint8_t enabled; + uint8_t absolute_vals; + uint8_t update_map; + int8_t base_quant[4]; + int8_t filter_level[4]; ///< base loop filter level + } segmentation; + + struct { + uint8_t simple; + uint8_t level; + uint8_t sharpness; + } filter; + + VP8Macroblock *macroblocks; + + uint8_t *intra4x4_pred_mode_top; + uint8_t intra4x4_pred_mode_left[4]; + + /** + * Macroblocks can have one of 4 different quants in a frame when + * segmentation is enabled. + * If segmentation is disabled, only the first segment's values are used. + */ + struct { + // [0] - DC qmul [1] - AC qmul + int16_t luma_qmul[2]; + int16_t luma_dc_qmul[2]; ///< luma dc-only block quant + int16_t chroma_qmul[2]; + } qmat[4]; + + struct { + uint8_t enabled; ///< whether each mb can have a different strength based on mode/ref + + /** + * filter strength adjustment for the following macroblock modes: + * [0-3] - i16x16 (always zero) + * [4] - i4x4 + * [5] - zero mv + * [6] - inter modes except for zero or split mv + * [7] - split mv + * i16x16 modes never have any adjustment + */ + int8_t mode[VP8_MVMODE_SPLIT+1]; + + /** + * filter strength adjustment for macroblocks that reference: + * [0] - intra / VP56_FRAME_CURRENT + * [1] - VP56_FRAME_PREVIOUS + * [2] - VP56_FRAME_GOLDEN + * [3] - altref / VP56_FRAME_GOLDEN2 + */ + int8_t ref[4]; + } lf_delta; + + uint8_t (*top_border)[16+8+8]; + uint8_t (*top_nnz)[9]; + + VP56RangeCoder c; ///< header context, includes mb modes and motion vectors + + /** + * These are all of the updatable probabilities for binary decisions. + * They are only implictly reset on keyframes, making it quite likely + * for an interframe to desync if a prior frame's header was corrupt + * or missing outright! + */ + struct { + uint8_t segmentid[3]; + uint8_t mbskip; + uint8_t intra; + uint8_t last; + uint8_t golden; + uint8_t pred16x16[4]; + uint8_t pred8x8c[3]; + uint8_t token[4][16][3][NUM_DCT_TOKENS-1]; + uint8_t mvc[2][19]; + } prob[2]; + + VP8Macroblock *macroblocks_base; + int invisible; + int update_last; ///< update VP56_FRAME_PREVIOUS with the current one + int update_golden; ///< VP56_FRAME_NONE if not updated, or which frame to copy if so + int update_altref; + + /** + * If this flag is not set, all the probability updates + * are discarded after this frame is decoded. + */ + int update_probabilities; + + /** + * All coefficients are contained in separate arith coding contexts. + * There can be 1, 2, 4, or 8 of these after the header context. + */ + int num_coeff_partitions; + VP56RangeCoder coeff_partition[8]; + VideoDSPContext vdsp; + VP8DSPContext vp8dsp; + H264PredContext hpc; + vp8_mc_func put_pixels_tab[3][3][3]; + VP8Frame frames[5]; + + int num_jobs; + /** + * This describes the macroblock memory layout. + * 0 -> Only width+height*2+1 macroblocks allocated (frame/single thread). + * 1 -> Macroblocks for entire frame alloced (sliced thread). + */ + int mb_layout; +} VP8Context; + +#endif /* AVCODEC_VP8_H */ diff --git a/ffmpeg/libavcodec/vp8_parser.c b/ffmpeg/libavcodec/vp8_parser.c new file mode 100644 index 0000000..096961f --- /dev/null +++ b/ffmpeg/libavcodec/vp8_parser.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 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 "parser.h" + +static int parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + s->pict_type= (buf[0]&0x01) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +AVCodecParser ff_vp8_parser = { + .codec_ids = { AV_CODEC_ID_VP8 }, + .parser_parse = parse, +}; diff --git a/ffmpeg/libavcodec/vp8data.h b/ffmpeg/libavcodec/vp8data.h new file mode 100644 index 0000000..0ea24d7 --- /dev/null +++ b/ffmpeg/libavcodec/vp8data.h @@ -0,0 +1,691 @@ +/* + * Copyright (C) 2010 David Conrad + * Copyright (C) 2010 Ronald S. Bultje + * + * 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 + */ + +/** + * @file + * VP8 compatible video decoder + */ + +#ifndef AVCODEC_VP8DATA_H +#define AVCODEC_VP8DATA_H + +#include "vp8.h" +#include "h264pred.h" + +static const uint8_t vp8_pred4x4_mode[] = +{ + [DC_PRED8x8] = DC_PRED, + [VERT_PRED8x8] = VERT_PRED, + [HOR_PRED8x8] = HOR_PRED, + [PLANE_PRED8x8] = TM_VP8_PRED, +}; + +static const int8_t vp8_pred16x16_tree_intra[4][2] = +{ + { -MODE_I4x4, 1 }, // '0' + { 2, 3 }, + { -DC_PRED8x8, -VERT_PRED8x8 }, // '100', '101' + { -HOR_PRED8x8, -PLANE_PRED8x8 }, // '110', '111' +}; + +static const int8_t vp8_pred16x16_tree_inter[4][2] = +{ + { -DC_PRED8x8, 1 }, // '0' + { 2, 3 }, + { -VERT_PRED8x8, -HOR_PRED8x8 }, // '100', '101' + { -PLANE_PRED8x8, -MODE_I4x4 }, // '110', '111' +}; + +static const int vp8_mode_contexts[6][4] = { + { 7, 1, 1, 143 }, + { 14, 18, 14, 107 }, + { 135, 64, 57, 68 }, + { 60, 56, 128, 65 }, + { 159, 134, 128, 34 }, + { 234, 188, 128, 28 }, +}; + +static const uint8_t vp8_mbsplits[5][16] = { + { 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 1, 1, 0, 0, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, + 2, 2, 3, 3, 2, 2, 3, 3 }, + { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 }, + { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const uint8_t vp8_mbfirstidx[4][16] = { + { 0, 8 }, { 0, 2 }, { 0, 2, 8, 10 }, + { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 } +}; + +static const uint8_t vp8_mbsplit_count[4] = { 2, 2, 4, 16 }; +static const uint8_t vp8_mbsplit_prob[3] = { 110, 111, 150 }; + +static const uint8_t vp8_submv_prob[5][3] = { + { 147, 136, 18 }, + { 106, 145, 1 }, + { 179, 121, 1 }, + { 223, 1, 34 }, + { 208, 1, 1 } +}; + +static const uint8_t vp8_pred16x16_prob_intra[4] = { 145, 156, 163, 128 }; +static const uint8_t vp8_pred16x16_prob_inter[4] = { 112, 86, 140, 37 }; + +static const int8_t vp8_pred4x4_tree[9][2] = +{ + { -DC_PRED, 1 }, // '0' + { -TM_VP8_PRED, 2 }, // '10' + { -VERT_PRED, 3 }, // '110' + { 4, 6 }, + { -HOR_PRED, 5 }, // '11100' + { -DIAG_DOWN_RIGHT_PRED, -VERT_RIGHT_PRED }, // '111010', '111011' + { -DIAG_DOWN_LEFT_PRED, 7 }, // '11110' + { -VERT_LEFT_PRED, 8 }, // '111110' + { -HOR_DOWN_PRED, -HOR_UP_PRED }, // '1111110', '1111111' +}; + +static const int8_t vp8_pred8x8c_tree[3][2] = +{ + { -DC_PRED8x8, 1 }, // '0' + { -VERT_PRED8x8, 2 }, // '10 + { -HOR_PRED8x8, -PLANE_PRED8x8 }, // '110', '111' +}; + +static const uint8_t vp8_pred8x8c_prob_intra[3] = { 142, 114, 183 }; +static const uint8_t vp8_pred8x8c_prob_inter[3] = { 162, 101, 204 }; + +static const uint8_t vp8_pred4x4_prob_inter[9] = +{ + 120, 90, 79, 133, 87, 85, 80, 111, 151 +}; + +static const uint8_t vp8_pred4x4_prob_intra[10][10][9] = +{ + { + { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, + { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, + { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, + { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, + { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, + { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, + { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, + { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, + { 62, 18, 78, 95, 85, 57, 50, 48, 51 }, + { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, + }, + { + { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, + { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, + { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, + { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, + { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, + { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, + { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, + { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, + { 51, 50, 17, 168, 209, 192, 23, 25, 82 }, + { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, + }, + { + { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, + { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, + { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, + { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, + { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, + { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, + { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, + { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, + { 81, 40, 11, 96, 182, 84, 29, 16, 36 }, + { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, + }, + { + { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, + { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, + { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, + { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, + { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, + { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, + { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, + { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, + { 117, 20, 15, 36, 163, 128, 68, 1, 26 }, + { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, + }, + { + { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, + { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, + { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, + { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, + { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, + { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, + { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, + { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, + { 87, 37, 9, 115, 59, 77, 64, 21, 47 }, + { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, + }, + { + { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, + { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, + { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, + { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, + { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, + { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, + { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, + { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, + { 55, 38, 70, 124, 73, 102, 1, 34, 98 }, + { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, + }, + { + { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, + { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, + { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, + { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, + { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, + { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, + { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, + { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, + { 35, 27, 10, 146, 174, 171, 12, 26, 128 }, + { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, + }, + { + { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, + { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, + { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, + { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, + { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, + { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, + { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, + { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, + { 58, 15, 20, 82, 135, 57, 26, 121, 40 }, + { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, + }, + { + { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, + { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, + { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, + { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, + { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, + { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, + { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, + { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, + { 112, 19, 12, 61, 195, 128, 48, 4, 24 }, + { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, + }, + { + { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, + { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, + { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, + { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, + { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, + { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, + { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, + { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, + { 66, 45, 25, 102, 197, 189, 23, 18, 22 }, + { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, + }, +}; + +static const int8_t vp8_segmentid_tree[][2] = +{ + { 1, 2 }, + { -0, -1 }, // '00', '01' + { -2, -3 }, // '10', '11' +}; + +static const uint8_t vp8_coeff_band[16] = +{ + 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7 +}; + +/* Inverse of vp8_coeff_band: mappings of bands to coefficient indexes. + * Each list is -1-terminated. */ +static const int8_t vp8_coeff_band_indexes[8][10] = +{ + {0, -1}, + {1, -1}, + {2, -1}, + {3, -1}, + {5, -1}, + {6, -1}, + {4, 7, 8, 9, 10, 11, 12, 13, 14, -1}, + {15, -1} +}; + +static const uint8_t vp8_dct_cat1_prob[] = { 159, 0 }; +static const uint8_t vp8_dct_cat2_prob[] = { 165, 145, 0 }; +static const uint8_t vp8_dct_cat3_prob[] = { 173, 148, 140, 0 }; +static const uint8_t vp8_dct_cat4_prob[] = { 176, 155, 140, 135, 0 }; +static const uint8_t vp8_dct_cat5_prob[] = { 180, 157, 141, 134, 130, 0 }; +static const uint8_t vp8_dct_cat6_prob[] = { 254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0 }; + +// only used for cat3 and above; cat 1 and 2 are referenced directly +const uint8_t * const ff_vp8_dct_cat_prob[] = +{ + vp8_dct_cat3_prob, + vp8_dct_cat4_prob, + vp8_dct_cat5_prob, + vp8_dct_cat6_prob, +}; + +static const uint8_t vp8_token_default_probs[4][8][3][NUM_DCT_TOKENS-1] = +{ + { + { + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + { + { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 }, + }, + { + { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 }, + }, + { + { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 }, + }, + { + { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 }, + }, + { + { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 }, + }, + { + { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 }, + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + }, + { + { + { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 }, + }, + { + { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 }, + }, + { + { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 }, + }, + { + { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 }, + }, + { + { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 }, + }, + { + { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 }, + }, + { + { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 }, + }, + { + { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 }, + }, + }, + { + { + { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 }, + }, + { + { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 }, + }, + { + { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 }, + }, + { + { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + }, + { + { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + { + { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + { + { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + { + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + }, + { + { + { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 }, + }, + { + { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 }, + }, + { + { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 }, + }, + { + { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 }, + }, + { + { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 }, + }, + { + { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 }, + }, + { + { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 }, + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + }, + }, +}; + +static const uint8_t vp8_token_update_probs[4][8][3][NUM_DCT_TOKENS-1] = +{ + { + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + }, + { + { + { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 }, + }, + { + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + }, + { + { + { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 }, + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + }, + { + { + { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + }, + }, +}; + +// fixme: copied from h264data.h +static const uint8_t zigzag_scan[16]={ + 0+0*4, 1+0*4, 0+1*4, 0+2*4, + 1+1*4, 2+0*4, 3+0*4, 2+1*4, + 1+2*4, 0+3*4, 1+3*4, 2+2*4, + 3+1*4, 3+2*4, 2+3*4, 3+3*4, +}; + +static const uint8_t vp8_dc_qlookup[VP8_MAX_QUANT+1] = +{ + 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 17, + 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 91, 93, 95, 96, 98, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, + 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157, +}; + +static const uint16_t vp8_ac_qlookup[VP8_MAX_QUANT+1] = +{ + 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, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, + 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152, + 155, 158, 161, 164, 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, + 213, 217, 221, 225, 229, 234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284, +}; + +static const uint8_t vp8_mv_update_prob[2][19] = { + { 237, + 246, + 253, 253, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 250, 250, 252, 254, 254 }, + { 231, + 243, + 245, 253, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 251, 251, 254, 254, 254 } +}; + +static const uint8_t vp8_mv_default_prob[2][19] = { + { 162, + 128, + 225, 146, 172, 147, 214, 39, 156, + 128, 129, 132, 75, 145, 178, 206, 239, 254, 254 }, + { 164, + 128, + 204, 170, 119, 235, 140, 230, 228, + 128, 130, 130, 74, 148, 180, 203, 236, 254, 254 } +}; + +#endif /* AVCODEC_VP8DATA_H */ diff --git a/ffmpeg/libavcodec/vp8dsp.c b/ffmpeg/libavcodec/vp8dsp.c new file mode 100644 index 0000000..017278e --- /dev/null +++ b/ffmpeg/libavcodec/vp8dsp.c @@ -0,0 +1,530 @@ +/* + * Copyright (C) 2010 David Conrad + * Copyright (C) 2010 Ronald S. Bultje + * + * 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 + */ + +/** + * @file + * VP8 compatible video decoder + */ + +#include "dsputil.h" +#include "vp8dsp.h" +#include "libavutil/common.h" + +// TODO: Maybe add dequant +static void vp8_luma_dc_wht_c(int16_t block[4][4][16], int16_t dc[16]) +{ + int i, t0, t1, t2, t3; + + for (i = 0; i < 4; i++) { + t0 = dc[0*4+i] + dc[3*4+i]; + t1 = dc[1*4+i] + dc[2*4+i]; + t2 = dc[1*4+i] - dc[2*4+i]; + t3 = dc[0*4+i] - dc[3*4+i]; + + dc[0*4+i] = t0 + t1; + dc[1*4+i] = t3 + t2; + dc[2*4+i] = t0 - t1; + dc[3*4+i] = t3 - t2; + } + + for (i = 0; i < 4; i++) { + t0 = dc[i*4+0] + dc[i*4+3] + 3; // rounding + t1 = dc[i*4+1] + dc[i*4+2]; + t2 = dc[i*4+1] - dc[i*4+2]; + t3 = dc[i*4+0] - dc[i*4+3] + 3; // rounding + dc[i*4+0] = 0; + dc[i*4+1] = 0; + dc[i*4+2] = 0; + dc[i*4+3] = 0; + + block[i][0][0] = (t0 + t1) >> 3; + block[i][1][0] = (t3 + t2) >> 3; + block[i][2][0] = (t0 - t1) >> 3; + block[i][3][0] = (t3 - t2) >> 3; + } +} + +static void vp8_luma_dc_wht_dc_c(int16_t block[4][4][16], int16_t dc[16]) +{ + int i, val = (dc[0] + 3) >> 3; + dc[0] = 0; + + for (i = 0; i < 4; i++) { + block[i][0][0] = val; + block[i][1][0] = val; + block[i][2][0] = val; + block[i][3][0] = val; + } +} + +#define MUL_20091(a) ((((a)*20091) >> 16) + (a)) +#define MUL_35468(a) (((a)*35468) >> 16) + +static void vp8_idct_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) +{ + int i, t0, t1, t2, t3; + int16_t tmp[16]; + + for (i = 0; i < 4; i++) { + t0 = block[0*4+i] + block[2*4+i]; + t1 = block[0*4+i] - block[2*4+i]; + t2 = MUL_35468(block[1*4+i]) - MUL_20091(block[3*4+i]); + t3 = MUL_20091(block[1*4+i]) + MUL_35468(block[3*4+i]); + block[0*4+i] = 0; + block[1*4+i] = 0; + block[2*4+i] = 0; + block[3*4+i] = 0; + + tmp[i*4+0] = t0 + t3; + tmp[i*4+1] = t1 + t2; + tmp[i*4+2] = t1 - t2; + tmp[i*4+3] = t0 - t3; + } + + for (i = 0; i < 4; i++) { + t0 = tmp[0*4+i] + tmp[2*4+i]; + t1 = tmp[0*4+i] - tmp[2*4+i]; + t2 = MUL_35468(tmp[1*4+i]) - MUL_20091(tmp[3*4+i]); + t3 = MUL_20091(tmp[1*4+i]) + MUL_35468(tmp[3*4+i]); + + dst[0] = av_clip_uint8(dst[0] + ((t0 + t3 + 4) >> 3)); + dst[1] = av_clip_uint8(dst[1] + ((t1 + t2 + 4) >> 3)); + dst[2] = av_clip_uint8(dst[2] + ((t1 - t2 + 4) >> 3)); + dst[3] = av_clip_uint8(dst[3] + ((t0 - t3 + 4) >> 3)); + dst += stride; + } +} + +static void vp8_idct_dc_add_c(uint8_t *dst, int16_t block[16], ptrdiff_t stride) +{ + int i, dc = (block[0] + 4) >> 3; + block[0] = 0; + + for (i = 0; i < 4; i++) { + dst[0] = av_clip_uint8(dst[0] + dc); + dst[1] = av_clip_uint8(dst[1] + dc); + dst[2] = av_clip_uint8(dst[2] + dc); + dst[3] = av_clip_uint8(dst[3] + dc); + dst += stride; + } +} + +static void vp8_idct_dc_add4uv_c(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride) +{ + vp8_idct_dc_add_c(dst+stride*0+0, block[0], stride); + vp8_idct_dc_add_c(dst+stride*0+4, block[1], stride); + vp8_idct_dc_add_c(dst+stride*4+0, block[2], stride); + vp8_idct_dc_add_c(dst+stride*4+4, block[3], stride); +} + +static void vp8_idct_dc_add4y_c(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride) +{ + vp8_idct_dc_add_c(dst+ 0, block[0], stride); + vp8_idct_dc_add_c(dst+ 4, block[1], stride); + vp8_idct_dc_add_c(dst+ 8, block[2], stride); + vp8_idct_dc_add_c(dst+12, block[3], stride); +} + +// because I like only having two parameters to pass functions... +#define LOAD_PIXELS\ + int av_unused p3 = p[-4*stride];\ + int av_unused p2 = p[-3*stride];\ + int av_unused p1 = p[-2*stride];\ + int av_unused p0 = p[-1*stride];\ + int av_unused q0 = p[ 0*stride];\ + int av_unused q1 = p[ 1*stride];\ + int av_unused q2 = p[ 2*stride];\ + int av_unused q3 = p[ 3*stride]; + +#define clip_int8(n) (cm[n+0x80]-0x80) + +static av_always_inline void filter_common(uint8_t *p, ptrdiff_t stride, int is4tap) +{ + LOAD_PIXELS + int a, f1, f2; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + a = 3*(q0 - p0); + + if (is4tap) + a += clip_int8(p1 - q1); + + a = clip_int8(a); + + // We deviate from the spec here with c(a+3) >> 3 + // since that's what libvpx does. + f1 = FFMIN(a+4, 127) >> 3; + f2 = FFMIN(a+3, 127) >> 3; + + // Despite what the spec says, we do need to clamp here to + // be bitexact with libvpx. + p[-1*stride] = cm[p0 + f2]; + p[ 0*stride] = cm[q0 - f1]; + + // only used for _inner on blocks without high edge variance + if (!is4tap) { + a = (f1+1)>>1; + p[-2*stride] = cm[p1 + a]; + p[ 1*stride] = cm[q1 - a]; + } +} + +static av_always_inline int simple_limit(uint8_t *p, ptrdiff_t stride, int flim) +{ + LOAD_PIXELS + return 2*FFABS(p0-q0) + (FFABS(p1-q1) >> 1) <= flim; +} + +/** + * E - limit at the macroblock edge + * I - limit for interior difference + */ +static av_always_inline int normal_limit(uint8_t *p, ptrdiff_t stride, int E, int I) +{ + LOAD_PIXELS + return simple_limit(p, stride, E) + && FFABS(p3-p2) <= I && FFABS(p2-p1) <= I && FFABS(p1-p0) <= I + && FFABS(q3-q2) <= I && FFABS(q2-q1) <= I && FFABS(q1-q0) <= I; +} + +// high edge variance +static av_always_inline int hev(uint8_t *p, ptrdiff_t stride, int thresh) +{ + LOAD_PIXELS + return FFABS(p1-p0) > thresh || FFABS(q1-q0) > thresh; +} + +static av_always_inline void filter_mbedge(uint8_t *p, ptrdiff_t stride) +{ + int a0, a1, a2, w; + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; + + LOAD_PIXELS + + w = clip_int8(p1-q1); + w = clip_int8(w + 3*(q0-p0)); + + a0 = (27*w + 63) >> 7; + a1 = (18*w + 63) >> 7; + a2 = ( 9*w + 63) >> 7; + + p[-3*stride] = cm[p2 + a2]; + p[-2*stride] = cm[p1 + a1]; + p[-1*stride] = cm[p0 + a0]; + p[ 0*stride] = cm[q0 - a0]; + p[ 1*stride] = cm[q1 - a1]; + p[ 2*stride] = cm[q2 - a2]; +} + +#define LOOP_FILTER(dir, size, stridea, strideb, maybe_inline) \ +static maybe_inline void vp8_ ## dir ## _loop_filter ## size ## _c(uint8_t *dst, ptrdiff_t stride,\ + int flim_E, int flim_I, int hev_thresh)\ +{\ + int i;\ +\ + for (i = 0; i < size; i++)\ + if (normal_limit(dst+i*stridea, strideb, flim_E, flim_I)) {\ + if (hev(dst+i*stridea, strideb, hev_thresh))\ + filter_common(dst+i*stridea, strideb, 1);\ + else\ + filter_mbedge(dst+i*stridea, strideb);\ + }\ +}\ +\ +static maybe_inline void vp8_ ## dir ## _loop_filter ## size ## _inner_c(uint8_t *dst, ptrdiff_t stride,\ + int flim_E, int flim_I, int hev_thresh)\ +{\ + int i;\ +\ + for (i = 0; i < size; i++)\ + if (normal_limit(dst+i*stridea, strideb, flim_E, flim_I)) {\ + int hv = hev(dst+i*stridea, strideb, hev_thresh);\ + if (hv) \ + filter_common(dst+i*stridea, strideb, 1);\ + else \ + filter_common(dst+i*stridea, strideb, 0);\ + }\ +} + +LOOP_FILTER(v, 16, 1, stride,) +LOOP_FILTER(h, 16, stride, 1,) + +#define UV_LOOP_FILTER(dir, stridea, strideb) \ +LOOP_FILTER(dir, 8, stridea, strideb, av_always_inline) \ +static void vp8_ ## dir ## _loop_filter8uv_c(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride,\ + int fE, int fI, int hev_thresh)\ +{\ + vp8_ ## dir ## _loop_filter8_c(dstU, stride, fE, fI, hev_thresh);\ + vp8_ ## dir ## _loop_filter8_c(dstV, stride, fE, fI, hev_thresh);\ +}\ +static void vp8_ ## dir ## _loop_filter8uv_inner_c(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride,\ + int fE, int fI, int hev_thresh)\ +{\ + vp8_ ## dir ## _loop_filter8_inner_c(dstU, stride, fE, fI, hev_thresh);\ + vp8_ ## dir ## _loop_filter8_inner_c(dstV, stride, fE, fI, hev_thresh);\ +} + +UV_LOOP_FILTER(v, 1, stride) +UV_LOOP_FILTER(h, stride, 1) + +static void vp8_v_loop_filter_simple_c(uint8_t *dst, ptrdiff_t stride, int flim) +{ + int i; + + for (i = 0; i < 16; i++) + if (simple_limit(dst+i, stride, flim)) + filter_common(dst+i, stride, 1); +} + +static void vp8_h_loop_filter_simple_c(uint8_t *dst, ptrdiff_t stride, int flim) +{ + int i; + + for (i = 0; i < 16; i++) + if (simple_limit(dst+i*stride, 1, flim)) + filter_common(dst+i*stride, 1, 1); +} + +static const uint8_t subpel_filters[7][6] = { + { 0, 6, 123, 12, 1, 0 }, + { 2, 11, 108, 36, 8, 1 }, + { 0, 9, 93, 50, 6, 0 }, + { 3, 16, 77, 77, 16, 3 }, + { 0, 6, 50, 93, 9, 0 }, + { 1, 8, 36, 108, 11, 2 }, + { 0, 1, 12, 123, 6, 0 }, +}; + +#define PUT_PIXELS(WIDTH) \ +static void put_vp8_pixels ## WIDTH ##_c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int x, int y) { \ + int i; \ + for (i = 0; i < h; i++, dst+= dststride, src+= srcstride) { \ + memcpy(dst, src, WIDTH); \ + } \ +} + +PUT_PIXELS(16) +PUT_PIXELS(8) +PUT_PIXELS(4) + +#define FILTER_6TAP(src, F, stride) \ + cm[(F[2]*src[x+0*stride] - F[1]*src[x-1*stride] + F[0]*src[x-2*stride] + \ + F[3]*src[x+1*stride] - F[4]*src[x+2*stride] + F[5]*src[x+3*stride] + 64) >> 7] + +#define FILTER_4TAP(src, F, stride) \ + cm[(F[2]*src[x+0*stride] - F[1]*src[x-1*stride] + \ + F[3]*src[x+1*stride] - F[4]*src[x+2*stride] + 64) >> 7] + +#define VP8_EPEL_H(SIZE, TAPS) \ +static void put_vp8_epel ## SIZE ## _h ## TAPS ## _c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int mx, int my) \ +{ \ + const uint8_t *filter = subpel_filters[mx-1]; \ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; \ + int x, y; \ +\ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = FILTER_ ## TAPS ## TAP(src, filter, 1); \ + dst += dststride; \ + src += srcstride; \ + } \ +} +#define VP8_EPEL_V(SIZE, TAPS) \ +static void put_vp8_epel ## SIZE ## _v ## TAPS ## _c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int mx, int my) \ +{ \ + const uint8_t *filter = subpel_filters[my-1]; \ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; \ + int x, y; \ +\ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = FILTER_ ## TAPS ## TAP(src, filter, srcstride); \ + dst += dststride; \ + src += srcstride; \ + } \ +} +#define VP8_EPEL_HV(SIZE, HTAPS, VTAPS) \ +static void put_vp8_epel ## SIZE ## _h ## HTAPS ## v ## VTAPS ## _c(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int h, int mx, int my) \ +{ \ + const uint8_t *filter = subpel_filters[mx-1]; \ + uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; \ + int x, y; \ + uint8_t tmp_array[(2*SIZE+VTAPS-1)*SIZE]; \ + uint8_t *tmp = tmp_array; \ + src -= (2-(VTAPS==4))*srcstride; \ +\ + for (y = 0; y < h+VTAPS-1; y++) { \ + for (x = 0; x < SIZE; x++) \ + tmp[x] = FILTER_ ## HTAPS ## TAP(src, filter, 1); \ + tmp += SIZE; \ + src += srcstride; \ + } \ +\ + tmp = tmp_array + (2-(VTAPS==4))*SIZE; \ + filter = subpel_filters[my-1]; \ +\ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = FILTER_ ## VTAPS ## TAP(tmp, filter, SIZE); \ + dst += dststride; \ + tmp += SIZE; \ + } \ +} + +VP8_EPEL_H(16, 4) +VP8_EPEL_H(8, 4) +VP8_EPEL_H(4, 4) +VP8_EPEL_H(16, 6) +VP8_EPEL_H(8, 6) +VP8_EPEL_H(4, 6) +VP8_EPEL_V(16, 4) +VP8_EPEL_V(8, 4) +VP8_EPEL_V(4, 4) +VP8_EPEL_V(16, 6) +VP8_EPEL_V(8, 6) +VP8_EPEL_V(4, 6) +VP8_EPEL_HV(16, 4, 4) +VP8_EPEL_HV(8, 4, 4) +VP8_EPEL_HV(4, 4, 4) +VP8_EPEL_HV(16, 4, 6) +VP8_EPEL_HV(8, 4, 6) +VP8_EPEL_HV(4, 4, 6) +VP8_EPEL_HV(16, 6, 4) +VP8_EPEL_HV(8, 6, 4) +VP8_EPEL_HV(4, 6, 4) +VP8_EPEL_HV(16, 6, 6) +VP8_EPEL_HV(8, 6, 6) +VP8_EPEL_HV(4, 6, 6) + +#define VP8_BILINEAR(SIZE) \ +static void put_vp8_bilinear ## SIZE ## _h_c(uint8_t *dst, ptrdiff_t stride, uint8_t *src, ptrdiff_t s2, int h, int mx, int my) \ +{ \ + int a = 8-mx, b = mx; \ + int x, y; \ +\ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = (a*src[x] + b*src[x+1] + 4) >> 3; \ + dst += stride; \ + src += stride; \ + } \ +} \ +static void put_vp8_bilinear ## SIZE ## _v_c(uint8_t *dst, ptrdiff_t stride, uint8_t *src, ptrdiff_t s2, int h, int mx, int my) \ +{ \ + int c = 8-my, d = my; \ + int x, y; \ +\ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = (c*src[x] + d*src[x+stride] + 4) >> 3; \ + dst += stride; \ + src += stride; \ + } \ +} \ +\ +static void put_vp8_bilinear ## SIZE ## _hv_c(uint8_t *dst, ptrdiff_t stride, uint8_t *src, ptrdiff_t s2, int h, int mx, int my) \ +{ \ + int a = 8-mx, b = mx; \ + int c = 8-my, d = my; \ + int x, y; \ + uint8_t tmp_array[(2*SIZE+1)*SIZE]; \ + uint8_t *tmp = tmp_array; \ +\ + for (y = 0; y < h+1; y++) { \ + for (x = 0; x < SIZE; x++) \ + tmp[x] = (a*src[x] + b*src[x+1] + 4) >> 3; \ + tmp += SIZE; \ + src += stride; \ + } \ +\ + tmp = tmp_array; \ +\ + for (y = 0; y < h; y++) { \ + for (x = 0; x < SIZE; x++) \ + dst[x] = (c*tmp[x] + d*tmp[x+SIZE] + 4) >> 3; \ + dst += stride; \ + tmp += SIZE; \ + } \ +} + +VP8_BILINEAR(16) +VP8_BILINEAR(8) +VP8_BILINEAR(4) + +#define VP8_MC_FUNC(IDX, SIZE) \ + dsp->put_vp8_epel_pixels_tab[IDX][0][0] = put_vp8_pixels ## SIZE ## _c; \ + dsp->put_vp8_epel_pixels_tab[IDX][0][1] = put_vp8_epel ## SIZE ## _h4_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][0][2] = put_vp8_epel ## SIZE ## _h6_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][0] = put_vp8_epel ## SIZE ## _v4_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][1] = put_vp8_epel ## SIZE ## _h4v4_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][2] = put_vp8_epel ## SIZE ## _h6v4_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][0] = put_vp8_epel ## SIZE ## _v6_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][1] = put_vp8_epel ## SIZE ## _h4v6_c; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][2] = put_vp8_epel ## SIZE ## _h6v6_c + +#define VP8_BILINEAR_MC_FUNC(IDX, SIZE) \ + dsp->put_vp8_bilinear_pixels_tab[IDX][0][0] = put_vp8_pixels ## SIZE ## _c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][0][1] = put_vp8_bilinear ## SIZE ## _h_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][0][2] = put_vp8_bilinear ## SIZE ## _h_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][1][0] = put_vp8_bilinear ## SIZE ## _v_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][1][1] = put_vp8_bilinear ## SIZE ## _hv_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][1][2] = put_vp8_bilinear ## SIZE ## _hv_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][2][0] = put_vp8_bilinear ## SIZE ## _v_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][2][1] = put_vp8_bilinear ## SIZE ## _hv_c; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][2][2] = put_vp8_bilinear ## SIZE ## _hv_c + +av_cold void ff_vp8dsp_init(VP8DSPContext *dsp) +{ + dsp->vp8_luma_dc_wht = vp8_luma_dc_wht_c; + dsp->vp8_luma_dc_wht_dc = vp8_luma_dc_wht_dc_c; + dsp->vp8_idct_add = vp8_idct_add_c; + dsp->vp8_idct_dc_add = vp8_idct_dc_add_c; + dsp->vp8_idct_dc_add4y = vp8_idct_dc_add4y_c; + dsp->vp8_idct_dc_add4uv = vp8_idct_dc_add4uv_c; + + dsp->vp8_v_loop_filter16y = vp8_v_loop_filter16_c; + dsp->vp8_h_loop_filter16y = vp8_h_loop_filter16_c; + dsp->vp8_v_loop_filter8uv = vp8_v_loop_filter8uv_c; + dsp->vp8_h_loop_filter8uv = vp8_h_loop_filter8uv_c; + + dsp->vp8_v_loop_filter16y_inner = vp8_v_loop_filter16_inner_c; + dsp->vp8_h_loop_filter16y_inner = vp8_h_loop_filter16_inner_c; + dsp->vp8_v_loop_filter8uv_inner = vp8_v_loop_filter8uv_inner_c; + dsp->vp8_h_loop_filter8uv_inner = vp8_h_loop_filter8uv_inner_c; + + dsp->vp8_v_loop_filter_simple = vp8_v_loop_filter_simple_c; + dsp->vp8_h_loop_filter_simple = vp8_h_loop_filter_simple_c; + + VP8_MC_FUNC(0, 16); + VP8_MC_FUNC(1, 8); + VP8_MC_FUNC(2, 4); + + VP8_BILINEAR_MC_FUNC(0, 16); + VP8_BILINEAR_MC_FUNC(1, 8); + VP8_BILINEAR_MC_FUNC(2, 4); + + if (ARCH_X86) + ff_vp8dsp_init_x86(dsp); + if (HAVE_ALTIVEC) + ff_vp8dsp_init_altivec(dsp); + if (ARCH_ARM) + ff_vp8dsp_init_arm(dsp); +} diff --git a/ffmpeg/libavcodec/vp8dsp.h b/ffmpeg/libavcodec/vp8dsp.h new file mode 100644 index 0000000..6308ff4 --- /dev/null +++ b/ffmpeg/libavcodec/vp8dsp.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 David Conrad + * Copyright (C) 2010 Ronald S. Bultje + * + * 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 + */ + +/** + * @file + * VP8 compatible video decoder + */ + +#ifndef AVCODEC_VP8DSP_H +#define AVCODEC_VP8DSP_H + +#include +#include + +typedef void (*vp8_mc_func)(uint8_t *dst/*align 8*/, ptrdiff_t dstStride, + uint8_t *src/*align 1*/, ptrdiff_t srcStride, + int h, int x, int y); + +typedef struct VP8DSPContext { + void (*vp8_luma_dc_wht)(int16_t block[4][4][16], int16_t dc[16]); + void (*vp8_luma_dc_wht_dc)(int16_t block[4][4][16], int16_t dc[16]); + void (*vp8_idct_add)(uint8_t *dst, int16_t block[16], ptrdiff_t stride); + void (*vp8_idct_dc_add)(uint8_t *dst, int16_t block[16], ptrdiff_t stride); + void (*vp8_idct_dc_add4y)(uint8_t *dst, int16_t block[4][16], + ptrdiff_t stride); + void (*vp8_idct_dc_add4uv)(uint8_t *dst, int16_t block[4][16], + ptrdiff_t stride); + + // loop filter applied to edges between macroblocks + void (*vp8_v_loop_filter16y)(uint8_t *dst, ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + void (*vp8_h_loop_filter16y)(uint8_t *dst, ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + void (*vp8_v_loop_filter8uv)(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + void (*vp8_h_loop_filter8uv)(uint8_t *dstU, uint8_t *dstV, ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + + // loop filter applied to inner macroblock edges + void (*vp8_v_loop_filter16y_inner)(uint8_t *dst, ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + void (*vp8_h_loop_filter16y_inner)(uint8_t *dst, ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + void (*vp8_v_loop_filter8uv_inner)(uint8_t *dstU, uint8_t *dstV, + ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + void (*vp8_h_loop_filter8uv_inner)(uint8_t *dstU, uint8_t *dstV, + ptrdiff_t stride, + int flim_E, int flim_I, int hev_thresh); + + void (*vp8_v_loop_filter_simple)(uint8_t *dst, ptrdiff_t stride, int flim); + void (*vp8_h_loop_filter_simple)(uint8_t *dst, ptrdiff_t stride, int flim); + + /** + * first dimension: width>>3, height is assumed equal to width + * second dimension: 0 if no vertical interpolation is needed; + * 1 4-tap vertical interpolation filter (my & 1) + * 2 6-tap vertical interpolation filter (!(my & 1)) + * third dimension: same as second dimension, for horizontal interpolation + * so something like put_vp8_epel_pixels_tab[width>>3][2*!!my-(my&1)][2*!!mx-(mx&1)](..., mx, my) + */ + vp8_mc_func put_vp8_epel_pixels_tab[3][3][3]; + vp8_mc_func put_vp8_bilinear_pixels_tab[3][3][3]; +} VP8DSPContext; + +void ff_put_vp8_pixels16_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); +void ff_put_vp8_pixels8_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); +void ff_put_vp8_pixels4_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); + +void ff_vp8dsp_init(VP8DSPContext *c); +void ff_vp8dsp_init_x86(VP8DSPContext *c); +void ff_vp8dsp_init_altivec(VP8DSPContext *c); +void ff_vp8dsp_init_arm(VP8DSPContext *c); + +#endif /* AVCODEC_VP8DSP_H */ diff --git a/ffmpeg/libavcodec/vqavideo.c b/ffmpeg/libavcodec/vqavideo.c new file mode 100644 index 0000000..a47e2db --- /dev/null +++ b/ffmpeg/libavcodec/vqavideo.c @@ -0,0 +1,639 @@ +/* + * Westwood Studios VQA Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * VQA Video Decoder + * @author Mike Melanson (melanson@pcisys.net) + * @see http://wiki.multimedia.cx/index.php?title=VQA + * + * The VQA video decoder outputs PAL8 or RGB555 colorspace data, depending + * on the type of data in the file. + * + * This decoder needs the 42-byte VQHD header from the beginning + * of the VQA file passed through the extradata field. The VQHD header + * is laid out as: + * + * bytes 0-3 chunk fourcc: 'VQHD' + * bytes 4-7 chunk size in big-endian format, should be 0x0000002A + * bytes 8-49 VQHD chunk data + * + * Bytes 8-49 are what this decoder expects to see. + * + * Briefly, VQA is a vector quantized animation format that operates in a + * VGA palettized colorspace. It operates on pixel vectors (blocks) + * of either 4x2 or 4x4 in size. Compressed VQA chunks can contain vector + * codebooks, palette information, and code maps for rendering vectors onto + * frames. Any of these components can also be compressed with a run-length + * encoding (RLE) algorithm commonly referred to as "format80". + * + * VQA takes a novel approach to rate control. Each group of n frames + * (usually, n = 8) relies on a different vector codebook. Rather than + * transporting an entire codebook every 8th frame, the new codebook is + * broken up into 8 pieces and sent along with the compressed video chunks + * for each of the 8 frames preceding the 8 frames which require the + * codebook. A full codebook is also sent on the very first frame of a + * file. This is an interesting technique, although it makes random file + * seeking difficult despite the fact that the frames are all intracoded. + * + * V1,2 VQA uses 12-bit codebook indexes. If the 12-bit indexes were + * packed into bytes and then RLE compressed, bytewise, the results would + * be poor. That is why the coding method divides each index into 2 parts, + * the top 4 bits and the bottom 8 bits, then RL encodes the 4-bit pieces + * together and the 8-bit pieces together. If most of the vectors are + * clustered into one group of 256 vectors, most of the 4-bit index pieces + * should be the same. + */ + +#include +#include +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" + +#define PALETTE_COUNT 256 +#define VQA_HEADER_SIZE 0x2A + +/* allocate the maximum vector space, regardless of the file version: + * (0xFF00 codebook vectors + 0x100 solid pixel vectors) * (4x4 pixels/block) */ +#define MAX_CODEBOOK_VECTORS 0xFF00 +#define SOLID_PIXEL_VECTORS 0x100 +#define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS) +#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4) + +#define CBF0_TAG MKBETAG('C', 'B', 'F', '0') +#define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z') +#define CBP0_TAG MKBETAG('C', 'B', 'P', '0') +#define CBPZ_TAG MKBETAG('C', 'B', 'P', 'Z') +#define CPL0_TAG MKBETAG('C', 'P', 'L', '0') +#define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z') +#define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z') + +typedef struct VqaContext { + + AVCodecContext *avctx; + GetByteContext gb; + + uint32_t palette[PALETTE_COUNT]; + + int width; /* width of a frame */ + int height; /* height of a frame */ + int vector_width; /* width of individual vector */ + int vector_height; /* height of individual vector */ + int vqa_version; /* this should be either 1, 2 or 3 */ + + unsigned char *codebook; /* the current codebook */ + int codebook_size; + unsigned char *next_codebook_buffer; /* accumulator for next codebook */ + int next_codebook_buffer_index; + + unsigned char *decode_buffer; + int decode_buffer_size; + + /* number of frames to go before replacing codebook */ + int partial_countdown; + int partial_count; + +} VqaContext; + +static av_cold int vqa_decode_init(AVCodecContext *avctx) +{ + VqaContext *s = avctx->priv_data; + int i, j, codebook_index, ret; + + s->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + /* make sure the extradata made it */ + if (s->avctx->extradata_size != VQA_HEADER_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, "expected extradata size of %d\n", VQA_HEADER_SIZE); + return AVERROR(EINVAL); + } + + /* load up the VQA parameters from the header */ + s->vqa_version = s->avctx->extradata[0]; + if (s->vqa_version < 1 || s->vqa_version > 3) { + av_log(s->avctx, AV_LOG_ERROR, "unsupported version %d\n", s->vqa_version); + return AVERROR_PATCHWELCOME; + } + s->width = AV_RL16(&s->avctx->extradata[6]); + s->height = AV_RL16(&s->avctx->extradata[8]); + if ((ret = av_image_check_size(s->width, s->height, 0, avctx)) < 0) { + s->width= s->height= 0; + return ret; + } + s->vector_width = s->avctx->extradata[10]; + s->vector_height = s->avctx->extradata[11]; + s->partial_count = s->partial_countdown = s->avctx->extradata[13]; + + /* the vector dimensions have to meet very stringent requirements */ + if ((s->vector_width != 4) || + ((s->vector_height != 2) && (s->vector_height != 4))) { + /* return without further initialization */ + return AVERROR_INVALIDDATA; + } + + if (s->width % s->vector_width || s->height % s->vector_height) { + av_log(avctx, AV_LOG_ERROR, "Image size not multiple of block size\n"); + return AVERROR_INVALIDDATA; + } + + /* allocate codebooks */ + s->codebook_size = MAX_CODEBOOK_SIZE; + s->codebook = av_malloc(s->codebook_size); + if (!s->codebook) + goto fail; + s->next_codebook_buffer = av_malloc(s->codebook_size); + if (!s->next_codebook_buffer) + goto fail; + + /* allocate decode buffer */ + s->decode_buffer_size = (s->width / s->vector_width) * + (s->height / s->vector_height) * 2; + s->decode_buffer = av_malloc(s->decode_buffer_size); + if (!s->decode_buffer) + goto fail; + + /* initialize the solid-color vectors */ + if (s->vector_height == 4) { + codebook_index = 0xFF00 * 16; + for (i = 0; i < 256; i++) + for (j = 0; j < 16; j++) + s->codebook[codebook_index++] = i; + } else { + codebook_index = 0xF00 * 8; + for (i = 0; i < 256; i++) + for (j = 0; j < 8; j++) + s->codebook[codebook_index++] = i; + } + s->next_codebook_buffer_index = 0; + + return 0; +fail: + av_freep(&s->codebook); + av_freep(&s->next_codebook_buffer); + av_freep(&s->decode_buffer); + return AVERROR(ENOMEM); +} + +#define CHECK_COUNT() \ + if (dest_index + count > dest_size) { \ + av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \ + av_log(s->avctx, AV_LOG_ERROR, "current dest_index = %d, count = %d, dest_size = %d\n", \ + dest_index, count, dest_size); \ + return AVERROR_INVALIDDATA; \ + } + +#define CHECK_COPY(idx) \ + if (idx < 0 || idx + count > dest_size) { \ + av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: next op would overflow dest_index\n"); \ + av_log(s->avctx, AV_LOG_ERROR, "current src_pos = %d, count = %d, dest_size = %d\n", \ + src_pos, count, dest_size); \ + return AVERROR_INVALIDDATA; \ + } + + +static int decode_format80(VqaContext *s, int src_size, + unsigned char *dest, int dest_size, int check_size) { + + int dest_index = 0; + int count, opcode, start; + int src_pos; + unsigned char color; + int i; + + start = bytestream2_tell(&s->gb); + while (bytestream2_tell(&s->gb) - start < src_size) { + opcode = bytestream2_get_byte(&s->gb); + av_dlog(s->avctx, "opcode %02X: ", opcode); + + /* 0x80 means that frame is finished */ + if (opcode == 0x80) + return 0; + + if (dest_index >= dest_size) { + av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: dest_index (%d) exceeded dest_size (%d)\n", + dest_index, dest_size); + return AVERROR_INVALIDDATA; + } + + if (opcode == 0xFF) { + + count = bytestream2_get_le16(&s->gb); + src_pos = bytestream2_get_le16(&s->gb); + av_dlog(s->avctx, "(1) copy %X bytes from absolute pos %X\n", count, src_pos); + CHECK_COUNT(); + CHECK_COPY(src_pos); + for (i = 0; i < count; i++) + dest[dest_index + i] = dest[src_pos + i]; + dest_index += count; + + } else if (opcode == 0xFE) { + + count = bytestream2_get_le16(&s->gb); + color = bytestream2_get_byte(&s->gb); + av_dlog(s->avctx, "(2) set %X bytes to %02X\n", count, color); + CHECK_COUNT(); + memset(&dest[dest_index], color, count); + dest_index += count; + + } else if ((opcode & 0xC0) == 0xC0) { + + count = (opcode & 0x3F) + 3; + src_pos = bytestream2_get_le16(&s->gb); + av_dlog(s->avctx, "(3) copy %X bytes from absolute pos %X\n", count, src_pos); + CHECK_COUNT(); + CHECK_COPY(src_pos); + for (i = 0; i < count; i++) + dest[dest_index + i] = dest[src_pos + i]; + dest_index += count; + + } else if (opcode > 0x80) { + + count = opcode & 0x3F; + av_dlog(s->avctx, "(4) copy %X bytes from source to dest\n", count); + CHECK_COUNT(); + bytestream2_get_buffer(&s->gb, &dest[dest_index], count); + dest_index += count; + + } else { + + count = ((opcode & 0x70) >> 4) + 3; + src_pos = bytestream2_get_byte(&s->gb) | ((opcode & 0x0F) << 8); + av_dlog(s->avctx, "(5) copy %X bytes from relpos %X\n", count, src_pos); + CHECK_COUNT(); + CHECK_COPY(dest_index - src_pos); + for (i = 0; i < count; i++) + dest[dest_index + i] = dest[dest_index - src_pos + i]; + dest_index += count; + } + } + + /* validate that the entire destination buffer was filled; this is + * important for decoding frame maps since each vector needs to have a + * codebook entry; it is not important for compressed codebooks because + * not every entry needs to be filled */ + if (check_size) + if (dest_index < dest_size) + av_log(s->avctx, AV_LOG_ERROR, "decode_format80 problem: decode finished with dest_index (%d) < dest_size (%d)\n", + dest_index, dest_size); + + return 0; // let's display what we decoded anyway +} + +static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) +{ + unsigned int chunk_type; + unsigned int chunk_size; + int byte_skip; + unsigned int index = 0; + int i; + unsigned char r, g, b; + int index_shift; + int res; + + int cbf0_chunk = -1; + int cbfz_chunk = -1; + int cbp0_chunk = -1; + int cbpz_chunk = -1; + int cpl0_chunk = -1; + int cplz_chunk = -1; + int vptz_chunk = -1; + + int x, y; + int lines = 0; + int pixel_ptr; + int vector_index = 0; + int lobyte = 0; + int hibyte = 0; + int lobytes = 0; + int hibytes = s->decode_buffer_size / 2; + + /* first, traverse through the frame and find the subchunks */ + while (bytestream2_get_bytes_left(&s->gb) >= 8) { + + chunk_type = bytestream2_get_be32u(&s->gb); + index = bytestream2_tell(&s->gb); + chunk_size = bytestream2_get_be32u(&s->gb); + + switch (chunk_type) { + + case CBF0_TAG: + cbf0_chunk = index; + break; + + case CBFZ_TAG: + cbfz_chunk = index; + break; + + case CBP0_TAG: + cbp0_chunk = index; + break; + + case CBPZ_TAG: + cbpz_chunk = index; + break; + + case CPL0_TAG: + cpl0_chunk = index; + break; + + case CPLZ_TAG: + cplz_chunk = index; + break; + + case VPTZ_TAG: + vptz_chunk = index; + break; + + default: + av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %c%c%c%c (%08X)\n", + (chunk_type >> 24) & 0xFF, + (chunk_type >> 16) & 0xFF, + (chunk_type >> 8) & 0xFF, + (chunk_type >> 0) & 0xFF, + chunk_type); + break; + } + + byte_skip = chunk_size & 0x01; + bytestream2_skip(&s->gb, chunk_size + byte_skip); + } + + /* next, deal with the palette */ + if ((cpl0_chunk != -1) && (cplz_chunk != -1)) { + + /* a chunk should not have both chunk types */ + av_log(s->avctx, AV_LOG_ERROR, "problem: found both CPL0 and CPLZ chunks\n"); + return AVERROR_INVALIDDATA; + } + + /* decompress the palette chunk */ + if (cplz_chunk != -1) { + +/* yet to be handled */ + + } + + /* convert the RGB palette into the machine's endian format */ + if (cpl0_chunk != -1) { + + bytestream2_seek(&s->gb, cpl0_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + /* sanity check the palette size */ + if (chunk_size / 3 > 256 || chunk_size > bytestream2_get_bytes_left(&s->gb)) { + av_log(s->avctx, AV_LOG_ERROR, "problem: found a palette chunk with %d colors\n", + chunk_size / 3); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < chunk_size / 3; i++) { + /* scale by 4 to transform 6-bit palette -> 8-bit */ + r = bytestream2_get_byteu(&s->gb) * 4; + g = bytestream2_get_byteu(&s->gb) * 4; + b = bytestream2_get_byteu(&s->gb) * 4; + s->palette[i] = 0xFFU << 24 | r << 16 | g << 8 | b; + s->palette[i] |= s->palette[i] >> 6 & 0x30303; + } + } + + /* next, look for a full codebook */ + if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) { + + /* a chunk should not have both chunk types */ + av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n"); + return AVERROR_INVALIDDATA; + } + + /* decompress the full codebook chunk */ + if (cbfz_chunk != -1) { + + bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + if ((res = decode_format80(s, chunk_size, s->codebook, + s->codebook_size, 0)) < 0) + return res; + } + + /* copy a full codebook */ + if (cbf0_chunk != -1) { + + bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + /* sanity check the full codebook size */ + if (chunk_size > MAX_CODEBOOK_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n", + chunk_size); + return AVERROR_INVALIDDATA; + } + + bytestream2_get_buffer(&s->gb, s->codebook, chunk_size); + } + + /* decode the frame */ + if (vptz_chunk == -1) { + + /* something is wrong if there is no VPTZ chunk */ + av_log(s->avctx, AV_LOG_ERROR, "problem: no VPTZ chunk found\n"); + return AVERROR_INVALIDDATA; + } + + bytestream2_seek(&s->gb, vptz_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + if ((res = decode_format80(s, chunk_size, + s->decode_buffer, s->decode_buffer_size, 1)) < 0) + return res; + + /* render the final PAL8 frame */ + if (s->vector_height == 4) + index_shift = 4; + else + index_shift = 3; + for (y = 0; y < s->height; y += s->vector_height) { + for (x = 0; x < s->width; x += 4, lobytes++, hibytes++) { + pixel_ptr = y * frame->linesize[0] + x; + + /* get the vector index, the method for which varies according to + * VQA file version */ + switch (s->vqa_version) { + + case 1: + lobyte = s->decode_buffer[lobytes * 2]; + hibyte = s->decode_buffer[(lobytes * 2) + 1]; + vector_index = ((hibyte << 8) | lobyte) >> 3; + vector_index <<= index_shift; + lines = s->vector_height; + /* uniform color fill - a quick hack */ + if (hibyte == 0xFF) { + while (lines--) { + frame->data[0][pixel_ptr + 0] = 255 - lobyte; + frame->data[0][pixel_ptr + 1] = 255 - lobyte; + frame->data[0][pixel_ptr + 2] = 255 - lobyte; + frame->data[0][pixel_ptr + 3] = 255 - lobyte; + pixel_ptr += frame->linesize[0]; + } + lines=0; + } + break; + + case 2: + lobyte = s->decode_buffer[lobytes]; + hibyte = s->decode_buffer[hibytes]; + vector_index = (hibyte << 8) | lobyte; + vector_index <<= index_shift; + lines = s->vector_height; + break; + + case 3: +/* not implemented yet */ + lines = 0; + break; + } + + while (lines--) { + frame->data[0][pixel_ptr + 0] = s->codebook[vector_index++]; + frame->data[0][pixel_ptr + 1] = s->codebook[vector_index++]; + frame->data[0][pixel_ptr + 2] = s->codebook[vector_index++]; + frame->data[0][pixel_ptr + 3] = s->codebook[vector_index++]; + pixel_ptr += frame->linesize[0]; + } + } + } + + /* handle partial codebook */ + if ((cbp0_chunk != -1) && (cbpz_chunk != -1)) { + /* a chunk should not have both chunk types */ + av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBP0 and CBPZ chunks\n"); + return AVERROR_INVALIDDATA; + } + + if (cbp0_chunk != -1) { + + bytestream2_seek(&s->gb, cbp0_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + + if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) { + av_log(s->avctx, AV_LOG_ERROR, "cbp0 chunk too large (%u bytes)\n", + chunk_size); + return AVERROR_INVALIDDATA; + } + + /* accumulate partial codebook */ + bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index], + chunk_size); + s->next_codebook_buffer_index += chunk_size; + + s->partial_countdown--; + if (s->partial_countdown <= 0) { + + /* time to replace codebook */ + memcpy(s->codebook, s->next_codebook_buffer, + s->next_codebook_buffer_index); + + /* reset accounting */ + s->next_codebook_buffer_index = 0; + s->partial_countdown = s->partial_count; + } + } + + if (cbpz_chunk != -1) { + + bytestream2_seek(&s->gb, cbpz_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + + if (chunk_size > MAX_CODEBOOK_SIZE - s->next_codebook_buffer_index) { + av_log(s->avctx, AV_LOG_ERROR, "cbpz chunk too large (%u bytes)\n", + chunk_size); + return AVERROR_INVALIDDATA; + } + + /* accumulate partial codebook */ + bytestream2_get_buffer(&s->gb, &s->next_codebook_buffer[s->next_codebook_buffer_index], + chunk_size); + s->next_codebook_buffer_index += chunk_size; + + s->partial_countdown--; + if (s->partial_countdown <= 0) { + bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index); + /* decompress codebook */ + if ((res = decode_format80(s, s->next_codebook_buffer_index, + s->codebook, s->codebook_size, 0)) < 0) + return res; + + /* reset accounting */ + s->next_codebook_buffer_index = 0; + s->partial_countdown = s->partial_count; + } + } + + return 0; +} + +static int vqa_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + VqaContext *s = avctx->priv_data; + AVFrame *frame = data; + int res; + + if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + return res; + + bytestream2_init(&s->gb, avpkt->data, avpkt->size); + if ((res = vqa_decode_chunk(s, frame)) < 0) + return res; + + /* make the palette available on the way out */ + memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4); + frame->palette_has_changed = 1; + + *got_frame = 1; + + /* report that the buffer was completely consumed */ + return avpkt->size; +} + +static av_cold int vqa_decode_end(AVCodecContext *avctx) +{ + VqaContext *s = avctx->priv_data; + + av_freep(&s->codebook); + av_freep(&s->next_codebook_buffer); + av_freep(&s->decode_buffer); + + return 0; +} + +AVCodec ff_vqa_decoder = { + .name = "vqavideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WS_VQA, + .priv_data_size = sizeof(VqaContext), + .init = vqa_decode_init, + .close = vqa_decode_end, + .decode = vqa_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"), +}; diff --git a/ffmpeg/libavcodec/w32pthreads.h b/ffmpeg/libavcodec/w32pthreads.h new file mode 100644 index 0000000..29185c7 --- /dev/null +++ b/ffmpeg/libavcodec/w32pthreads.h @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2010-2011 x264 project + * + * Authors: Steven Walters + * Pegasys Inc. + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * w32threads to pthreads wrapper + */ + +#ifndef AVCODEC_W32PTHREADS_H +#define AVCODEC_W32PTHREADS_H + +/* Build up a pthread-like API using underlying Windows API. Have only static + * methods so as to not conflict with a potentially linked in pthread-win32 + * library. + * As most functions here are used without checking return values, + * only implement return values as necessary. */ + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/mem.h" + +typedef struct pthread_t { + void *handle; + void *(*func)(void* arg); + void *arg; + void *ret; +} pthread_t; + +/* the conditional variable api for windows 6.0+ uses critical sections and + * not mutexes */ +typedef CRITICAL_SECTION pthread_mutex_t; + +/* This is the CONDITIONAL_VARIABLE typedef for using Window's native + * conditional variables on kernels 6.0+. + * MinGW does not currently have this typedef. */ +typedef struct pthread_cond_t { + void *ptr; +} pthread_cond_t; + +/* function pointers to conditional variable API on windows 6.0+ kernels */ +static void (WINAPI *cond_broadcast)(pthread_cond_t *cond); +static void (WINAPI *cond_init)(pthread_cond_t *cond); +static void (WINAPI *cond_signal)(pthread_cond_t *cond); +static BOOL (WINAPI *cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex, + DWORD milliseconds); + +static unsigned __stdcall attribute_align_arg win32thread_worker(void *arg) +{ + pthread_t *h = arg; + h->ret = h->func(h->arg); + return 0; +} + +static int pthread_create(pthread_t *thread, const void *unused_attr, + void *(*start_routine)(void*), void *arg) +{ + thread->func = start_routine; + thread->arg = arg; + thread->handle = (void*)_beginthreadex(NULL, 0, win32thread_worker, thread, + 0, NULL); + return !thread->handle; +} + +static void pthread_join(pthread_t thread, void **value_ptr) +{ + DWORD ret = WaitForSingleObject(thread.handle, INFINITE); + if (ret != WAIT_OBJECT_0) + return; + if (value_ptr) + *value_ptr = thread.ret; + CloseHandle(thread.handle); +} + +static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr) +{ + InitializeCriticalSection(m); + return 0; +} +static inline int pthread_mutex_destroy(pthread_mutex_t *m) +{ + DeleteCriticalSection(m); + return 0; +} +static inline int pthread_mutex_lock(pthread_mutex_t *m) +{ + EnterCriticalSection(m); + return 0; +} +static inline int pthread_mutex_unlock(pthread_mutex_t *m) +{ + LeaveCriticalSection(m); + return 0; +} + +/* for pre-Windows 6.0 platforms we need to define and use our own condition + * variable and api */ +typedef struct win32_cond_t { + pthread_mutex_t mtx_broadcast; + pthread_mutex_t mtx_waiter_count; + volatile int waiter_count; + HANDLE semaphore; + HANDLE waiters_done; + volatile int is_broadcast; +} win32_cond_t; + +static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) +{ + win32_cond_t *win32_cond = NULL; + if (cond_init) { + cond_init(cond); + return; + } + + /* non native condition variables */ + win32_cond = av_mallocz(sizeof(win32_cond_t)); + if (!win32_cond) + return; + cond->ptr = win32_cond; + win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); + if (!win32_cond->semaphore) + return; + win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!win32_cond->waiters_done) + return; + + pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL); + pthread_mutex_init(&win32_cond->mtx_broadcast, NULL); +} + +static void pthread_cond_destroy(pthread_cond_t *cond) +{ + win32_cond_t *win32_cond = cond->ptr; + /* native condition variables do not destroy */ + if (cond_init) + return; + + /* non native condition variables */ + CloseHandle(win32_cond->semaphore); + CloseHandle(win32_cond->waiters_done); + pthread_mutex_destroy(&win32_cond->mtx_waiter_count); + pthread_mutex_destroy(&win32_cond->mtx_broadcast); + av_freep(&win32_cond); + cond->ptr = NULL; +} + +static void pthread_cond_broadcast(pthread_cond_t *cond) +{ + win32_cond_t *win32_cond = cond->ptr; + int have_waiter; + + if (cond_broadcast) { + cond_broadcast(cond); + return; + } + + /* non native condition variables */ + pthread_mutex_lock(&win32_cond->mtx_broadcast); + pthread_mutex_lock(&win32_cond->mtx_waiter_count); + have_waiter = 0; + + if (win32_cond->waiter_count) { + win32_cond->is_broadcast = 1; + have_waiter = 1; + } + + if (have_waiter) { + ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL); + pthread_mutex_unlock(&win32_cond->mtx_waiter_count); + WaitForSingleObject(win32_cond->waiters_done, INFINITE); + ResetEvent(win32_cond->waiters_done); + win32_cond->is_broadcast = 0; + } else + pthread_mutex_unlock(&win32_cond->mtx_waiter_count); + pthread_mutex_unlock(&win32_cond->mtx_broadcast); +} + +static int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + win32_cond_t *win32_cond = cond->ptr; + int last_waiter; + if (cond_wait) { + cond_wait(cond, mutex, INFINITE); + return 0; + } + + /* non native condition variables */ + pthread_mutex_lock(&win32_cond->mtx_broadcast); + pthread_mutex_lock(&win32_cond->mtx_waiter_count); + win32_cond->waiter_count++; + pthread_mutex_unlock(&win32_cond->mtx_waiter_count); + pthread_mutex_unlock(&win32_cond->mtx_broadcast); + + // unlock the external mutex + pthread_mutex_unlock(mutex); + WaitForSingleObject(win32_cond->semaphore, INFINITE); + + pthread_mutex_lock(&win32_cond->mtx_waiter_count); + win32_cond->waiter_count--; + last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast; + pthread_mutex_unlock(&win32_cond->mtx_waiter_count); + + if (last_waiter) + SetEvent(win32_cond->waiters_done); + + // lock the external mutex + return pthread_mutex_lock(mutex); +} + +static void pthread_cond_signal(pthread_cond_t *cond) +{ + win32_cond_t *win32_cond = cond->ptr; + int have_waiter; + if (cond_signal) { + cond_signal(cond); + return; + } + + pthread_mutex_lock(&win32_cond->mtx_broadcast); + + /* non-native condition variables */ + pthread_mutex_lock(&win32_cond->mtx_waiter_count); + have_waiter = win32_cond->waiter_count; + pthread_mutex_unlock(&win32_cond->mtx_waiter_count); + + if (have_waiter) { + ReleaseSemaphore(win32_cond->semaphore, 1, NULL); + WaitForSingleObject(win32_cond->waiters_done, INFINITE); + ResetEvent(win32_cond->waiters_done); + } + + pthread_mutex_unlock(&win32_cond->mtx_broadcast); +} + +static void w32thread_init(void) +{ + HANDLE kernel_dll = GetModuleHandle(TEXT("kernel32.dll")); + /* if one is available, then they should all be available */ + cond_init = + (void*)GetProcAddress(kernel_dll, "InitializeConditionVariable"); + cond_broadcast = + (void*)GetProcAddress(kernel_dll, "WakeAllConditionVariable"); + cond_signal = + (void*)GetProcAddress(kernel_dll, "WakeConditionVariable"); + cond_wait = + (void*)GetProcAddress(kernel_dll, "SleepConditionVariableCS"); +} + +#endif /* AVCODEC_W32PTHREADS_H */ diff --git a/ffmpeg/libavcodec/wavpack.c b/ffmpeg/libavcodec/wavpack.c new file mode 100644 index 0000000..b30b414 --- /dev/null +++ b/ffmpeg/libavcodec/wavpack.c @@ -0,0 +1,1265 @@ +/* + * WavPack lossless audio decoder + * Copyright (c) 2006,2011 Konstantin Shishkov + * + * 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 + */ + +#define BITSTREAM_READER_LE + +#include "libavutil/channel_layout.h" +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "unary.h" + +/** + * @file + * WavPack lossless audio decoder + */ + +#define WV_MONO 0x00000004 +#define WV_JOINT_STEREO 0x00000010 +#define WV_FALSE_STEREO 0x40000000 + +#define WV_HYBRID_MODE 0x00000008 +#define WV_HYBRID_SHAPE 0x00000008 +#define WV_HYBRID_BITRATE 0x00000200 +#define WV_HYBRID_BALANCE 0x00000400 + +#define WV_FLT_SHIFT_ONES 0x01 +#define WV_FLT_SHIFT_SAME 0x02 +#define WV_FLT_SHIFT_SENT 0x04 +#define WV_FLT_ZERO_SENT 0x08 +#define WV_FLT_ZERO_SIGN 0x10 + +#define WV_MAX_SAMPLES 131072 + +enum WP_ID_Flags { + WP_IDF_MASK = 0x1F, + WP_IDF_IGNORE = 0x20, + WP_IDF_ODD = 0x40, + WP_IDF_LONG = 0x80 +}; + +enum WP_ID { + WP_ID_DUMMY = 0, + WP_ID_ENCINFO, + WP_ID_DECTERMS, + WP_ID_DECWEIGHTS, + WP_ID_DECSAMPLES, + WP_ID_ENTROPY, + WP_ID_HYBRID, + WP_ID_SHAPING, + WP_ID_FLOATINFO, + WP_ID_INT32INFO, + WP_ID_DATA, + WP_ID_CORR, + WP_ID_EXTRABITS, + WP_ID_CHANINFO +}; + +typedef struct SavedContext { + int offset; + int size; + int bits_used; + uint32_t crc; +} SavedContext; + +#define MAX_TERMS 16 + +typedef struct Decorr { + int delta; + int value; + int weightA; + int weightB; + int samplesA[8]; + int samplesB[8]; +} Decorr; + +typedef struct WvChannel { + int median[3]; + int slow_level, error_limit; + int bitrate_acc, bitrate_delta; +} WvChannel; + +typedef struct WavpackFrameContext { + AVCodecContext *avctx; + int frame_flags; + int stereo, stereo_in; + int joint; + uint32_t CRC; + GetBitContext gb; + int got_extra_bits; + uint32_t crc_extra_bits; + GetBitContext gb_extra_bits; + int data_size; // in bits + int samples; + int terms; + Decorr decorr[MAX_TERMS]; + int zero, one, zeroes; + int extra_bits; + int and, or, shift; + int post_shift; + int hybrid, hybrid_bitrate; + int hybrid_maxclip, hybrid_minclip; + int float_flag; + int float_shift; + int float_max_exp; + WvChannel ch[2]; + int pos; + SavedContext sc, extra_sc; +} WavpackFrameContext; + +#define WV_MAX_FRAME_DECODERS 14 + +typedef struct WavpackContext { + AVCodecContext *avctx; + + WavpackFrameContext *fdec[WV_MAX_FRAME_DECODERS]; + int fdec_num; + + int multichannel; + int mkv_mode; + int block; + int samples; + int ch_offset; +} WavpackContext; + +// exponent table copied from WavPack source +static const uint8_t wp_exp2_table [256] = { + 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, + 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, + 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, + 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, + 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff +}; + +static const uint8_t wp_log2_table [] = { + 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, + 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, + 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, + 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, + 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce, + 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7, + 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff +}; + +static av_always_inline int wp_exp2(int16_t val) +{ + int res, neg = 0; + + if (val < 0) { + val = -val; + neg = 1; + } + + res = wp_exp2_table[val & 0xFF] | 0x100; + val >>= 8; + res = (val > 9) ? (res << (val - 9)) : (res >> (9 - val)); + return neg ? -res : res; +} + +static av_always_inline int wp_log2(int32_t val) +{ + int bits; + + if (!val) + return 0; + if (val == 1) + return 256; + val += val >> 9; + bits = av_log2(val) + 1; + if (bits < 9) + return (bits << 8) + wp_log2_table[(val << (9 - bits)) & 0xFF]; + else + return (bits << 8) + wp_log2_table[(val >> (bits - 9)) & 0xFF]; +} + +#define LEVEL_DECAY(a) ((a + 0x80) >> 8) + +// macros for manipulating median values +#define GET_MED(n) ((c->median[n] >> 4) + 1) +#define DEC_MED(n) c->median[n] -= ((c->median[n] + (128 >> n) - 2) / (128 >> n)) * 2 +#define INC_MED(n) c->median[n] += ((c->median[n] + (128 >> n) ) / (128 >> n)) * 5 + +// macros for applying weight +#define UPDATE_WEIGHT_CLIP(weight, delta, samples, in) \ + if (samples && in) { \ + if ((samples ^ in) < 0) { \ + weight -= delta; \ + if (weight < -1024) \ + weight = -1024; \ + } else { \ + weight += delta; \ + if (weight > 1024) \ + weight = 1024; \ + } \ + } + + +static av_always_inline int get_tail(GetBitContext *gb, int k) +{ + int p, e, res; + + if (k < 1) + return 0; + p = av_log2(k); + e = (1 << (p + 1)) - k - 1; + res = p ? get_bits(gb, p) : 0; + if (res >= e) + res = (res << 1) - e + get_bits1(gb); + return res; +} + +static void update_error_limit(WavpackFrameContext *ctx) +{ + int i, br[2], sl[2]; + + for (i = 0; i <= ctx->stereo_in; i++) { + ctx->ch[i].bitrate_acc += ctx->ch[i].bitrate_delta; + br[i] = ctx->ch[i].bitrate_acc >> 16; + sl[i] = LEVEL_DECAY(ctx->ch[i].slow_level); + } + if (ctx->stereo_in && ctx->hybrid_bitrate) { + int balance = (sl[1] - sl[0] + br[1] + 1) >> 1; + if (balance > br[0]) { + br[1] = br[0] << 1; + br[0] = 0; + } else if (-balance > br[0]) { + br[0] <<= 1; + br[1] = 0; + } else { + br[1] = br[0] + balance; + br[0] = br[0] - balance; + } + } + for (i = 0; i <= ctx->stereo_in; i++) { + if (ctx->hybrid_bitrate) { + if (sl[i] - br[i] > -0x100) + ctx->ch[i].error_limit = wp_exp2(sl[i] - br[i] + 0x100); + else + ctx->ch[i].error_limit = 0; + } else { + ctx->ch[i].error_limit = wp_exp2(br[i]); + } + } +} + +static int wv_get_value(WavpackFrameContext *ctx, GetBitContext *gb, + int channel, int *last) +{ + int t, t2; + int sign, base, add, ret; + WvChannel *c = &ctx->ch[channel]; + + *last = 0; + + if ((ctx->ch[0].median[0] < 2U) && (ctx->ch[1].median[0] < 2U) && + !ctx->zero && !ctx->one) { + if (ctx->zeroes) { + ctx->zeroes--; + if (ctx->zeroes) { + c->slow_level -= LEVEL_DECAY(c->slow_level); + return 0; + } + } else { + t = get_unary_0_33(gb); + if (t >= 2) { + if (get_bits_left(gb) < t - 1) + goto error; + t = get_bits(gb, t - 1) | (1 << (t-1)); + } else { + if (get_bits_left(gb) < 0) + goto error; + } + ctx->zeroes = t; + if (ctx->zeroes) { + memset(ctx->ch[0].median, 0, sizeof(ctx->ch[0].median)); + memset(ctx->ch[1].median, 0, sizeof(ctx->ch[1].median)); + c->slow_level -= LEVEL_DECAY(c->slow_level); + return 0; + } + } + } + + if (ctx->zero) { + t = 0; + ctx->zero = 0; + } else { + t = get_unary_0_33(gb); + if (get_bits_left(gb) < 0) + goto error; + if (t == 16) { + t2 = get_unary_0_33(gb); + if (t2 < 2) { + if (get_bits_left(gb) < 0) + goto error; + t += t2; + } else { + if (get_bits_left(gb) < t2 - 1) + goto error; + t += get_bits(gb, t2 - 1) | (1 << (t2 - 1)); + } + } + + if (ctx->one) { + ctx->one = t & 1; + t = (t >> 1) + 1; + } else { + ctx->one = t & 1; + t >>= 1; + } + ctx->zero = !ctx->one; + } + + if (ctx->hybrid && !channel) + update_error_limit(ctx); + + if (!t) { + base = 0; + add = GET_MED(0) - 1; + DEC_MED(0); + } else if (t == 1) { + base = GET_MED(0); + add = GET_MED(1) - 1; + INC_MED(0); + DEC_MED(1); + } else if (t == 2) { + base = GET_MED(0) + GET_MED(1); + add = GET_MED(2) - 1; + INC_MED(0); + INC_MED(1); + DEC_MED(2); + } else { + base = GET_MED(0) + GET_MED(1) + GET_MED(2) * (t - 2); + add = GET_MED(2) - 1; + INC_MED(0); + INC_MED(1); + INC_MED(2); + } + if (!c->error_limit) { + ret = base + get_tail(gb, add); + if (get_bits_left(gb) <= 0) + goto error; + } else { + int mid = (base * 2 + add + 1) >> 1; + while (add > c->error_limit) { + if (get_bits_left(gb) <= 0) + goto error; + if (get_bits1(gb)) { + add -= (mid - base); + base = mid; + } else + add = mid - base - 1; + mid = (base * 2 + add + 1) >> 1; + } + ret = mid; + } + sign = get_bits1(gb); + if (ctx->hybrid_bitrate) + c->slow_level += wp_log2(ret) - LEVEL_DECAY(c->slow_level); + return sign ? ~ret : ret; + +error: + *last = 1; + return 0; +} + +static inline int wv_get_value_integer(WavpackFrameContext *s, uint32_t *crc, + int S) +{ + int bit; + + if (s->extra_bits){ + S <<= s->extra_bits; + + if (s->got_extra_bits && get_bits_left(&s->gb_extra_bits) >= s->extra_bits) { + S |= get_bits(&s->gb_extra_bits, s->extra_bits); + *crc = *crc * 9 + (S & 0xffff) * 3 + ((unsigned)S >> 16); + } + } + + bit = (S & s->and) | s->or; + bit = ((S + bit) << s->shift) - bit; + + if (s->hybrid) + bit = av_clip(bit, s->hybrid_minclip, s->hybrid_maxclip); + + return bit << s->post_shift; +} + +static float wv_get_value_float(WavpackFrameContext *s, uint32_t *crc, int S) +{ + union { + float f; + uint32_t u; + } value; + + unsigned int sign; + int exp = s->float_max_exp; + + if (s->got_extra_bits) { + const int max_bits = 1 + 23 + 8 + 1; + const int left_bits = get_bits_left(&s->gb_extra_bits); + + if (left_bits + 8 * FF_INPUT_BUFFER_PADDING_SIZE < max_bits) + return 0.0; + } + + if (S) { + S <<= s->float_shift; + sign = S < 0; + if (sign) + S = -S; + if (S >= 0x1000000) { + if (s->got_extra_bits && get_bits1(&s->gb_extra_bits)) + S = get_bits(&s->gb_extra_bits, 23); + else + S = 0; + exp = 255; + } else if (exp) { + int shift = 23 - av_log2(S); + exp = s->float_max_exp; + if (exp <= shift) + shift = --exp; + exp -= shift; + + if (shift) { + S <<= shift; + if ((s->float_flag & WV_FLT_SHIFT_ONES) || + (s->got_extra_bits && (s->float_flag & WV_FLT_SHIFT_SAME) && + get_bits1(&s->gb_extra_bits))) { + S |= (1 << shift) - 1; + } else if (s->got_extra_bits && + (s->float_flag & WV_FLT_SHIFT_SENT)) { + S |= get_bits(&s->gb_extra_bits, shift); + } + } + } else { + exp = s->float_max_exp; + } + S &= 0x7fffff; + } else { + sign = 0; + exp = 0; + if (s->got_extra_bits && (s->float_flag & WV_FLT_ZERO_SENT)) { + if (get_bits1(&s->gb_extra_bits)) { + S = get_bits(&s->gb_extra_bits, 23); + if (s->float_max_exp >= 25) + exp = get_bits(&s->gb_extra_bits, 8); + sign = get_bits1(&s->gb_extra_bits); + } else { + if (s->float_flag & WV_FLT_ZERO_SIGN) + sign = get_bits1(&s->gb_extra_bits); + } + } + } + + *crc = *crc * 27 + S * 9 + exp * 3 + sign; + + value.u = (sign << 31) | (exp << 23) | S; + return value.f; +} + +static void wv_reset_saved_context(WavpackFrameContext *s) +{ + s->pos = 0; + s->sc.crc = s->extra_sc.crc = 0xFFFFFFFF; +} + +static inline int wv_check_crc(WavpackFrameContext *s, uint32_t crc, + uint32_t crc_extra_bits) +{ + if (crc != s->CRC) { + av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); + return AVERROR_INVALIDDATA; + } + if (s->got_extra_bits && crc_extra_bits != s->crc_extra_bits) { + av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n"); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, + void *dst, const int type) +{ + int i, j, count = 0; + int last, t; + int A, B, L, L2, R, R2; + int pos = s->pos; + uint32_t crc = s->sc.crc; + uint32_t crc_extra_bits = s->extra_sc.crc; + int16_t *dst16 = dst; + int32_t *dst32 = dst; + float *dstfl = dst; + const int channel_pad = s->avctx->channels - 2; + + s->one = s->zero = s->zeroes = 0; + do { + L = wv_get_value(s, gb, 0, &last); + if (last) + break; + R = wv_get_value(s, gb, 1, &last); + if (last) + break; + for (i = 0; i < s->terms; i++) { + t = s->decorr[i].value; + if (t > 0) { + if (t > 8) { + if (t & 1) { + A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]; + B = 2 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1]; + } else { + A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1; + B = (3 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1]) >> 1; + } + s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0]; + s->decorr[i].samplesB[1] = s->decorr[i].samplesB[0]; + j = 0; + } else { + A = s->decorr[i].samplesA[pos]; + B = s->decorr[i].samplesB[pos]; + j = (pos + t) & 7; + } + if (type != AV_SAMPLE_FMT_S16) { + L2 = L + ((s->decorr[i].weightA * (int64_t)A + 512) >> 10); + R2 = R + ((s->decorr[i].weightB * (int64_t)B + 512) >> 10); + } else { + L2 = L + ((s->decorr[i].weightA * A + 512) >> 10); + R2 = R + ((s->decorr[i].weightB * B + 512) >> 10); + } + if (A && L) s->decorr[i].weightA -= ((((L ^ A) >> 30) & 2) - 1) * s->decorr[i].delta; + if (B && R) s->decorr[i].weightB -= ((((R ^ B) >> 30) & 2) - 1) * s->decorr[i].delta; + s->decorr[i].samplesA[j] = L = L2; + s->decorr[i].samplesB[j] = R = R2; + } else if (t == -1) { + if (type != AV_SAMPLE_FMT_S16) + L2 = L + ((s->decorr[i].weightA * (int64_t)s->decorr[i].samplesA[0] + 512) >> 10); + else + L2 = L + ((s->decorr[i].weightA * s->decorr[i].samplesA[0] + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, s->decorr[i].samplesA[0], L); + L = L2; + if (type != AV_SAMPLE_FMT_S16) + R2 = R + ((s->decorr[i].weightB * (int64_t)L2 + 512) >> 10); + else + R2 = R + ((s->decorr[i].weightB * L2 + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, L2, R); + R = R2; + s->decorr[i].samplesA[0] = R; + } else { + if (type != AV_SAMPLE_FMT_S16) + R2 = R + ((s->decorr[i].weightB * (int64_t)s->decorr[i].samplesB[0] + 512) >> 10); + else + R2 = R + ((s->decorr[i].weightB * s->decorr[i].samplesB[0] + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, s->decorr[i].samplesB[0], R); + R = R2; + + if (t == -3) { + R2 = s->decorr[i].samplesA[0]; + s->decorr[i].samplesA[0] = R; + } + + if (type != AV_SAMPLE_FMT_S16) + L2 = L + ((s->decorr[i].weightA * (int64_t)R2 + 512) >> 10); + else + L2 = L + ((s->decorr[i].weightA * R2 + 512) >> 10); + UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, R2, L); + L = L2; + s->decorr[i].samplesB[0] = L; + } + } + pos = (pos + 1) & 7; + if (s->joint) + L += (R -= (L >> 1)); + crc = (crc * 3 + L) * 3 + R; + + if (type == AV_SAMPLE_FMT_FLT) { + *dstfl++ = wv_get_value_float(s, &crc_extra_bits, L); + *dstfl++ = wv_get_value_float(s, &crc_extra_bits, R); + dstfl += channel_pad; + } else if (type == AV_SAMPLE_FMT_S32) { + *dst32++ = wv_get_value_integer(s, &crc_extra_bits, L); + *dst32++ = wv_get_value_integer(s, &crc_extra_bits, R); + dst32 += channel_pad; + } else { + *dst16++ = wv_get_value_integer(s, &crc_extra_bits, L); + *dst16++ = wv_get_value_integer(s, &crc_extra_bits, R); + dst16 += channel_pad; + } + count++; + } while (!last && count < s->samples); + + wv_reset_saved_context(s); + if ((s->avctx->err_recognition & AV_EF_CRCCHECK) && + wv_check_crc(s, crc, crc_extra_bits)) + return AVERROR_INVALIDDATA; + + return count * 2; +} + +static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb, + void *dst, const int type) +{ + int i, j, count = 0; + int last, t; + int A, S, T; + int pos = s->pos; + uint32_t crc = s->sc.crc; + uint32_t crc_extra_bits = s->extra_sc.crc; + int16_t *dst16 = dst; + int32_t *dst32 = dst; + float *dstfl = dst; + const int channel_stride = s->avctx->channels; + + s->one = s->zero = s->zeroes = 0; + do { + T = wv_get_value(s, gb, 0, &last); + S = 0; + if (last) + break; + for (i = 0; i < s->terms; i++) { + t = s->decorr[i].value; + if (t > 8) { + if (t & 1) + A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]; + else + A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1; + s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0]; + j = 0; + } else { + A = s->decorr[i].samplesA[pos]; + j = (pos + t) & 7; + } + if (type != AV_SAMPLE_FMT_S16) + S = T + ((s->decorr[i].weightA * (int64_t)A + 512) >> 10); + else + S = T + ((s->decorr[i].weightA * A + 512) >> 10); + if (A && T) + s->decorr[i].weightA -= ((((T ^ A) >> 30) & 2) - 1) * s->decorr[i].delta; + s->decorr[i].samplesA[j] = T = S; + } + pos = (pos + 1) & 7; + crc = crc * 3 + S; + + if (type == AV_SAMPLE_FMT_FLT) { + *dstfl = wv_get_value_float(s, &crc_extra_bits, S); + dstfl += channel_stride; + } else if (type == AV_SAMPLE_FMT_S32) { + *dst32 = wv_get_value_integer(s, &crc_extra_bits, S); + dst32 += channel_stride; + } else { + *dst16 = wv_get_value_integer(s, &crc_extra_bits, S); + dst16 += channel_stride; + } + count++; + } while (!last && count < s->samples); + + wv_reset_saved_context(s); + if ((s->avctx->err_recognition & AV_EF_CRCCHECK) && + wv_check_crc(s, crc, crc_extra_bits)) + return AVERROR_INVALIDDATA; + + return count; +} + +static av_cold int wv_alloc_frame_context(WavpackContext *c) +{ + + if (c->fdec_num == WV_MAX_FRAME_DECODERS) + return -1; + + c->fdec[c->fdec_num] = av_mallocz(sizeof(**c->fdec)); + if (!c->fdec[c->fdec_num]) + return -1; + c->fdec_num++; + c->fdec[c->fdec_num - 1]->avctx = c->avctx; + wv_reset_saved_context(c->fdec[c->fdec_num - 1]); + + return 0; +} + +static av_cold int wavpack_decode_init(AVCodecContext *avctx) +{ + WavpackContext *s = avctx->priv_data; + + s->avctx = avctx; + if (avctx->bits_per_coded_sample <= 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + else + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + if (avctx->channels <= 2 && !avctx->channel_layout) + avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + + s->multichannel = avctx->channels > 2; + /* lavf demuxer does not provide extradata, Matroska stores 0x403 + there, use this to detect decoding mode for multichannel */ + s->mkv_mode = 0; + if (s->multichannel && avctx->extradata && avctx->extradata_size == 2) { + int ver = AV_RL16(avctx->extradata); + if (ver >= 0x402 && ver <= 0x410) + s->mkv_mode = 1; + } + + s->fdec_num = 0; + + return 0; +} + +static av_cold int wavpack_decode_end(AVCodecContext *avctx) +{ + WavpackContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->fdec_num; i++) + av_freep(&s->fdec[i]); + s->fdec_num = 0; + + return 0; +} + +static int wavpack_decode_block(AVCodecContext *avctx, int block_no, + void *data, int *got_frame_ptr, + const uint8_t *buf, int buf_size) +{ + WavpackContext *wc = avctx->priv_data; + WavpackFrameContext *s; + void *samples = data; + int samplecount; + int got_terms = 0, got_weights = 0, got_samples = 0, + got_entropy = 0, got_bs = 0, got_float = 0, got_hybrid = 0; + const uint8_t *orig_buf = buf; + const uint8_t *buf_end = buf + buf_size; + int i, j, id, size, ssize, weights, t; + int bpp, chan, chmask, orig_bpp; + + if (buf_size == 0) { + *got_frame_ptr = 0; + return 0; + } + + if (block_no >= wc->fdec_num && wv_alloc_frame_context(wc) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error creating frame decode context\n"); + return -1; + } + + s = wc->fdec[block_no]; + if (!s) { + av_log(avctx, AV_LOG_ERROR, "Context for block %d is not present\n", block_no); + return -1; + } + + if (wc->ch_offset >= avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "too many channels\n"); + return -1; + } + + memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr)); + memset(s->ch, 0, sizeof(s->ch)); + s->extra_bits = 0; + s->and = s->or = s->shift = 0; + s->got_extra_bits = 0; + + if (!wc->mkv_mode) { + s->samples = AV_RL32(buf); buf += 4; + if (!s->samples) { + *got_frame_ptr = 0; + return 0; + } + if (s->samples > wc->samples) { + av_log(avctx, AV_LOG_ERROR, "too many samples in block"); + return -1; + } + } else { + s->samples = wc->samples; + } + s->frame_flags = AV_RL32(buf); buf += 4; + bpp = av_get_bytes_per_sample(avctx->sample_fmt); + samples = (uint8_t*)samples + bpp * wc->ch_offset; + orig_bpp = ((s->frame_flags & 0x03) + 1) << 3; + + s->stereo = !(s->frame_flags & WV_MONO); + s->stereo_in = (s->frame_flags & WV_FALSE_STEREO) ? 0 : s->stereo; + s->joint = s->frame_flags & WV_JOINT_STEREO; + s->hybrid = s->frame_flags & WV_HYBRID_MODE; + s->hybrid_bitrate = s->frame_flags & WV_HYBRID_BITRATE; + s->post_shift = bpp * 8 - orig_bpp + ((s->frame_flags >> 13) & 0x1f); + s->hybrid_maxclip = (( 1LL << (orig_bpp - 1)) - 1); + s->hybrid_minclip = ((-1LL << (orig_bpp - 1))); + s->CRC = AV_RL32(buf); buf += 4; + if (wc->mkv_mode) + buf += 4; //skip block size; + + wc->ch_offset += 1 + s->stereo; + + // parse metadata blocks + while (buf < buf_end) { + id = *buf++; + size = *buf++; + if (id & WP_IDF_LONG) { + size |= (*buf++) << 8; + size |= (*buf++) << 16; + } + size <<= 1; // size is specified in words + ssize = size; + if (id & WP_IDF_ODD) + size--; + if (size < 0) { + av_log(avctx, AV_LOG_ERROR, "Got incorrect block %02X with size %i\n", id, size); + break; + } + if (buf + ssize > buf_end) { + av_log(avctx, AV_LOG_ERROR, "Block size %i is out of bounds\n", size); + break; + } + if (id & WP_IDF_IGNORE) { + buf += ssize; + continue; + } + switch (id & WP_IDF_MASK) { + case WP_ID_DECTERMS: + if (size > MAX_TERMS) { + av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n"); + s->terms = 0; + buf += ssize; + continue; + } + s->terms = size; + for (i = 0; i < s->terms; i++) { + s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5; + s->decorr[s->terms - i - 1].delta = *buf >> 5; + buf++; + } + got_terms = 1; + break; + case WP_ID_DECWEIGHTS: + if (!got_terms) { + av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n"); + continue; + } + weights = size >> s->stereo_in; + if (weights > MAX_TERMS || weights > s->terms) { + av_log(avctx, AV_LOG_ERROR, "Too many decorrelation weights\n"); + buf += ssize; + continue; + } + for (i = 0; i < weights; i++) { + t = (int8_t)(*buf++); + s->decorr[s->terms - i - 1].weightA = t << 3; + if (s->decorr[s->terms - i - 1].weightA > 0) + s->decorr[s->terms - i - 1].weightA += + (s->decorr[s->terms - i - 1].weightA + 64) >> 7; + if (s->stereo_in) { + t = (int8_t)(*buf++); + s->decorr[s->terms - i - 1].weightB = t << 3; + if (s->decorr[s->terms - i - 1].weightB > 0) + s->decorr[s->terms - i - 1].weightB += + (s->decorr[s->terms - i - 1].weightB + 64) >> 7; + } + } + got_weights = 1; + break; + case WP_ID_DECSAMPLES: + if (!got_terms) { + av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n"); + continue; + } + t = 0; + for (i = s->terms - 1; (i >= 0) && (t < size) && buf <= buf_end; i--) { + if (s->decorr[i].value > 8) { + s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2; + s->decorr[i].samplesA[1] = wp_exp2(AV_RL16(buf)); buf += 2; + if (s->stereo_in) { + s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2; + s->decorr[i].samplesB[1] = wp_exp2(AV_RL16(buf)); buf += 2; + t += 4; + } + t += 4; + } else if (s->decorr[i].value < 0) { + s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2; + s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2; + t += 4; + } else { + for (j = 0; j < s->decorr[i].value && buf+1decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf)); buf += 2; + if (s->stereo_in) { + s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); buf += 2; + } + } + t += s->decorr[i].value * 2 * (s->stereo_in + 1); + } + } + got_samples = 1; + break; + case WP_ID_ENTROPY: + if (size != 6 * (s->stereo_in + 1)) { + av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, " + "got %i", 6 * (s->stereo_in + 1), size); + buf += ssize; + continue; + } + for (j = 0; j <= s->stereo_in; j++) { + for (i = 0; i < 3; i++) { + s->ch[j].median[i] = wp_exp2(AV_RL16(buf)); + buf += 2; + } + } + got_entropy = 1; + break; + case WP_ID_HYBRID: + if (s->hybrid_bitrate) { + for (i = 0; i <= s->stereo_in; i++) { + s->ch[i].slow_level = wp_exp2(AV_RL16(buf)); + buf += 2; + size -= 2; + } + } + for (i = 0; i < (s->stereo_in + 1); i++) { + s->ch[i].bitrate_acc = AV_RL16(buf) << 16; + buf += 2; + size -= 2; + } + if (size > 0) { + for (i = 0; i < (s->stereo_in + 1); i++) { + s->ch[i].bitrate_delta = wp_exp2((int16_t)AV_RL16(buf)); + buf += 2; + } + } else { + for (i = 0; i < (s->stereo_in + 1); i++) + s->ch[i].bitrate_delta = 0; + } + got_hybrid = 1; + break; + case WP_ID_INT32INFO: + if (size != 4) { + av_log(avctx, AV_LOG_ERROR, "Invalid INT32INFO, size = %i, sent_bits = %i\n", size, *buf); + buf += ssize; + continue; + } + if (buf[0]) + s->extra_bits = buf[0]; + else if (buf[1]) + s->shift = buf[1]; + else if (buf[2]){ + s->and = s->or = 1; + s->shift = buf[2]; + } else if(buf[3]) { + s->and = 1; + s->shift = buf[3]; + } + /* original WavPack decoder forces 32-bit lossy sound to be treated + * as 24-bit one in order to have proper clipping + */ + if (s->hybrid && bpp == 4 && s->post_shift < 8 && s->shift > 8) { + s->post_shift += 8; + s->shift -= 8; + s->hybrid_maxclip >>= 8; + s->hybrid_minclip >>= 8; + } + buf += 4; + break; + case WP_ID_FLOATINFO: + if (size != 4) { + av_log(avctx, AV_LOG_ERROR, "Invalid FLOATINFO, size = %i\n", size); + buf += ssize; + continue; + } + s->float_flag = buf[0]; + s->float_shift = buf[1]; + s->float_max_exp = buf[2]; + buf += 4; + got_float = 1; + break; + case WP_ID_DATA: + s->sc.offset = buf - orig_buf; + s->sc.size = size * 8; + init_get_bits(&s->gb, buf, size * 8); + s->data_size = size * 8; + buf += size; + got_bs = 1; + break; + case WP_ID_EXTRABITS: + if (size <= 4) { + av_log(avctx, AV_LOG_ERROR, "Invalid EXTRABITS, size = %i\n", + size); + buf += size; + continue; + } + s->extra_sc.offset = buf - orig_buf; + s->extra_sc.size = size * 8; + init_get_bits(&s->gb_extra_bits, buf, size * 8); + s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32); + buf += size; + s->got_extra_bits = 1; + break; + case WP_ID_CHANINFO: + if (size <= 1) { + av_log(avctx, AV_LOG_ERROR, "Insufficient channel information\n"); + return -1; + } + chan = *buf++; + switch (size - 2) { + case 0: chmask = *buf; break; + case 1: chmask = AV_RL16(buf); break; + case 2: chmask = AV_RL24(buf); break; + case 3: chmask = AV_RL32(buf); break; + case 5: + chan |= (buf[1] & 0xF) << 8; + chmask = AV_RL24(buf + 2); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid channel info size %d\n", + size); + chan = avctx->channels; + chmask = avctx->channel_layout; + } + if (chan != avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Block reports total %d channels, " + "decoder believes it's %d channels\n", chan, + avctx->channels); + return -1; + } + if (!avctx->channel_layout) + avctx->channel_layout = chmask; + buf += size - 1; + break; + default: + buf += size; + } + if (id & WP_IDF_ODD) + buf++; + } + + if (!got_terms) { + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n"); + return -1; + } + if (!got_weights) { + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n"); + return -1; + } + if (!got_samples) { + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n"); + return -1; + } + if (!got_entropy) { + av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n"); + return -1; + } + if (s->hybrid && !got_hybrid) { + av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n"); + return -1; + } + if (!got_bs) { + av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n"); + return -1; + } + if (!got_float && avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { + av_log(avctx, AV_LOG_ERROR, "Float information not found\n"); + return -1; + } + if (s->got_extra_bits && avctx->sample_fmt != AV_SAMPLE_FMT_FLT) { + const int size = get_bits_left(&s->gb_extra_bits); + const int wanted = s->samples * s->extra_bits << s->stereo_in; + if (size < wanted) { + av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n"); + s->got_extra_bits = 0; + } + } + + if (s->stereo_in) { + if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) + samplecount = wv_unpack_stereo(s, &s->gb, samples, AV_SAMPLE_FMT_S16); + else if (avctx->sample_fmt == AV_SAMPLE_FMT_S32) + samplecount = wv_unpack_stereo(s, &s->gb, samples, AV_SAMPLE_FMT_S32); + else + samplecount = wv_unpack_stereo(s, &s->gb, samples, AV_SAMPLE_FMT_FLT); + + if (samplecount < 0) + return -1; + + samplecount >>= 1; + } else { + const int channel_stride = avctx->channels; + + if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) + samplecount = wv_unpack_mono(s, &s->gb, samples, AV_SAMPLE_FMT_S16); + else if (avctx->sample_fmt == AV_SAMPLE_FMT_S32) + samplecount = wv_unpack_mono(s, &s->gb, samples, AV_SAMPLE_FMT_S32); + else + samplecount = wv_unpack_mono(s, &s->gb, samples, AV_SAMPLE_FMT_FLT); + + if (samplecount < 0) + return -1; + + if (s->stereo && avctx->sample_fmt == AV_SAMPLE_FMT_S16) { + int16_t *dst = (int16_t*)samples + 1; + int16_t *src = (int16_t*)samples; + int cnt = samplecount; + while (cnt--) { + *dst = *src; + src += channel_stride; + dst += channel_stride; + } + } else if (s->stereo && avctx->sample_fmt == AV_SAMPLE_FMT_S32) { + int32_t *dst = (int32_t*)samples + 1; + int32_t *src = (int32_t*)samples; + int cnt = samplecount; + while (cnt--) { + *dst = *src; + src += channel_stride; + dst += channel_stride; + } + } else if (s->stereo) { + float *dst = (float*)samples + 1; + float *src = (float*)samples; + int cnt = samplecount; + while (cnt--) { + *dst = *src; + src += channel_stride; + dst += channel_stride; + } + } + } + + *got_frame_ptr = 1; + + return samplecount * bpp; +} + +static void wavpack_decode_flush(AVCodecContext *avctx) +{ + WavpackContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->fdec_num; i++) + wv_reset_saved_context(s->fdec[i]); +} + +static int wavpack_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + WavpackContext *s = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame *frame = data; + int frame_size, ret, frame_flags; + int samplecount = 0; + + s->block = 0; + s->ch_offset = 0; + + /* determine number of samples */ + if (s->mkv_mode) { + s->samples = AV_RL32(buf); buf += 4; + frame_flags = AV_RL32(buf); + } else { + if (s->multichannel) { + s->samples = AV_RL32(buf + 4); + frame_flags = AV_RL32(buf + 8); + } else { + s->samples = AV_RL32(buf); + frame_flags = AV_RL32(buf + 4); + } + } + if (s->samples <= 0 || s->samples > WV_MAX_SAMPLES) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of samples: %d\n", + s->samples); + return AVERROR(EINVAL); + } + + if (frame_flags & 0x80) { + avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + } else if ((frame_flags & 0x03) <= 1) { + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + } else { + avctx->sample_fmt = AV_SAMPLE_FMT_S32; + avctx->bits_per_raw_sample = ((frame_flags & 0x03) + 1) << 3; + } + + /* get output buffer */ + frame->nb_samples = s->samples + 1; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + frame->nb_samples = s->samples; + + while (buf_size > 0) { + if (!s->multichannel) { + frame_size = buf_size; + } else { + if (!s->mkv_mode) { + frame_size = AV_RL32(buf) - 12; buf += 4; buf_size -= 4; + } else { + if (buf_size < 12) //MKV files can have zero flags after last block + break; + frame_size = AV_RL32(buf + 8) + 12; + } + } + if (frame_size < 0 || frame_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "Block %d has invalid size (size %d " + "vs. %d bytes left)\n", s->block, frame_size, buf_size); + wavpack_decode_flush(avctx); + return AVERROR_INVALIDDATA; + } + if ((samplecount = wavpack_decode_block(avctx, s->block, + frame->data[0], got_frame_ptr, + buf, frame_size)) < 0) { + wavpack_decode_flush(avctx); + return AVERROR_INVALIDDATA; + } + s->block++; + buf += frame_size; buf_size -= frame_size; + } + + return avpkt->size; +} + +AVCodec ff_wavpack_decoder = { + .name = "wavpack", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WAVPACK, + .priv_data_size = sizeof(WavpackContext), + .init = wavpack_decode_init, + .close = wavpack_decode_end, + .decode = wavpack_decode_frame, + .flush = wavpack_decode_flush, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("WavPack"), +}; diff --git a/ffmpeg/libavcodec/webvttdec.c b/ffmpeg/libavcodec/webvttdec.c new file mode 100644 index 0000000..6b86bed --- /dev/null +++ b/ffmpeg/libavcodec/webvttdec.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2012 Clément BÅ“sch + * + * 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 + */ + +/** + * @file + * WebVTT subtitle decoder + * @see http://dev.w3.org/html5/webvtt/ + * @todo need to support extended markups and cue settings + */ + +#include "avcodec.h" +#include "ass.h" +#include "libavutil/bprint.h" + +static const struct { + const char *from; + const char *to; +} webvtt_tag_replace[] = { + {"", "{\\i1}"}, {"", "{\\i0}"}, + {"", "{\\b1}"}, {"", "{\\b0}"}, + {"", "{\\u1}"}, {"", "{\\u0}"}, + {"{", "\\{"}, {"}", "\\}"}, // escape to avoid ASS markup conflicts +}; + +static int webvtt_event_to_ass(AVBPrint *buf, const char *p) +{ + int i, skip = 0; + + while (*p) { + + for (i = 0; i < FF_ARRAY_ELEMS(webvtt_tag_replace); i++) { + const char *from = webvtt_tag_replace[i].from; + const size_t len = strlen(from); + if (!strncmp(p, from, len)) { + av_bprintf(buf, "%s", webvtt_tag_replace[i].to); + p += len; + break; + } + } + if (!*p) + break; + + if (*p == '<') + skip = 1; + else if (*p == '>') + skip = 0; + else if (p[0] == '\n' && p[1]) + av_bprintf(buf, "\\N"); + else if (!skip && *p != '\r') + av_bprint_chars(buf, *p, 1); + p++; + } + av_bprintf(buf, "\r\n"); + return 0; +} + +static int webvtt_decode_frame(AVCodecContext *avctx, + void *data, int *got_sub_ptr, AVPacket *avpkt) +{ + AVSubtitle *sub = data; + const char *ptr = avpkt->data; + AVBPrint buf; + + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + if (ptr && avpkt->size > 0 && !webvtt_event_to_ass(&buf, ptr)) { + int ts_start = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100}); + int ts_duration = avpkt->duration != -1 ? + av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1; + ff_ass_add_rect(sub, buf.str, ts_start, ts_duration, 0); + } + *got_sub_ptr = sub->num_rects > 0; + av_bprint_finalize(&buf, NULL); + return avpkt->size; +} + +AVCodec ff_webvtt_decoder = { + .name = "webvtt", + .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_WEBVTT, + .decode = webvtt_decode_frame, + .init = ff_ass_subtitle_header_default, +}; diff --git a/ffmpeg/libavcodec/wma.c b/ffmpeg/libavcodec/wma.c new file mode 100644 index 0000000..1e6ca61 --- /dev/null +++ b/ffmpeg/libavcodec/wma.c @@ -0,0 +1,488 @@ +/* + * WMA compatible codec + * Copyright (c) 2002-2007 The FFmpeg Project + * + * 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 "avcodec.h" +#include "sinewin.h" +#include "wma.h" +#include "wma_common.h" +#include "wmadata.h" + +#undef NDEBUG +#include + +/* XXX: use same run/length optimization as mpeg decoders */ +//FIXME maybe split decode / encode or pass flag +static void init_coef_vlc(VLC *vlc, uint16_t **prun_table, + float **plevel_table, uint16_t **pint_table, + const CoefVLCTable *vlc_table) +{ + int n = vlc_table->n; + const uint8_t *table_bits = vlc_table->huffbits; + const uint32_t *table_codes = vlc_table->huffcodes; + const uint16_t *levels_table = vlc_table->levels; + uint16_t *run_table, *level_table, *int_table; + float *flevel_table; + int i, l, j, k, level; + + init_vlc(vlc, VLCBITS, n, table_bits, 1, 1, table_codes, 4, 4, 0); + + run_table = av_malloc(n * sizeof(uint16_t)); + level_table = av_malloc(n * sizeof(uint16_t)); + flevel_table= av_malloc(n * sizeof(*flevel_table)); + int_table = av_malloc(n * sizeof(uint16_t)); + i = 2; + level = 1; + k = 0; + while (i < n) { + int_table[k] = i; + l = levels_table[k++]; + for (j = 0; j < l; j++) { + run_table[i] = j; + level_table[i] = level; + flevel_table[i]= level; + i++; + } + level++; + } + *prun_table = run_table; + *plevel_table = flevel_table; + *pint_table = int_table; + av_free(level_table); +} + +int ff_wma_init(AVCodecContext *avctx, int flags2) +{ + WMACodecContext *s = avctx->priv_data; + int i; + float bps1, high_freq; + volatile float bps; + int sample_rate1; + int coef_vlc_table; + + if ( avctx->sample_rate <= 0 || avctx->sample_rate > 50000 + || avctx->channels <= 0 || avctx->channels > 2 + || avctx->bit_rate <= 0) + return -1; + + ff_fmt_convert_init(&s->fmt_conv, avctx); + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + if (avctx->codec->id == AV_CODEC_ID_WMAV1) { + s->version = 1; + } else { + s->version = 2; + } + + /* compute MDCT block size */ + s->frame_len_bits = ff_wma_get_frame_len_bits(avctx->sample_rate, + s->version, 0); + s->next_block_len_bits = s->frame_len_bits; + s->prev_block_len_bits = s->frame_len_bits; + s->block_len_bits = s->frame_len_bits; + + s->frame_len = 1 << s->frame_len_bits; + if (s->use_variable_block_len) { + int nb_max, nb; + nb = ((flags2 >> 3) & 3) + 1; + if ((avctx->bit_rate / avctx->channels) >= 32000) + nb += 2; + nb_max = s->frame_len_bits - BLOCK_MIN_BITS; + if (nb > nb_max) + nb = nb_max; + s->nb_block_sizes = nb + 1; + } else { + s->nb_block_sizes = 1; + } + + /* init rate dependent parameters */ + s->use_noise_coding = 1; + high_freq = avctx->sample_rate * 0.5; + + /* if version 2, then the rates are normalized */ + sample_rate1 = avctx->sample_rate; + if (s->version == 2) { + if (sample_rate1 >= 44100) { + sample_rate1 = 44100; + } else if (sample_rate1 >= 22050) { + sample_rate1 = 22050; + } else if (sample_rate1 >= 16000) { + sample_rate1 = 16000; + } else if (sample_rate1 >= 11025) { + sample_rate1 = 11025; + } else if (sample_rate1 >= 8000) { + sample_rate1 = 8000; + } + } + + bps = (float)avctx->bit_rate / (float)(avctx->channels * avctx->sample_rate); + s->byte_offset_bits = av_log2((int)(bps * s->frame_len / 8.0 + 0.5)) + 2; + if (s->byte_offset_bits + 3 > MIN_CACHE_BITS) { + av_log(avctx, AV_LOG_ERROR, "byte_offset_bits %d is too large\n", s->byte_offset_bits); + return AVERROR_PATCHWELCOME; + } + + /* compute high frequency value and choose if noise coding should + be activated */ + bps1 = bps; + if (avctx->channels == 2) + bps1 = bps * 1.6; + if (sample_rate1 == 44100) { + if (bps1 >= 0.61) { + s->use_noise_coding = 0; + } else { + high_freq = high_freq * 0.4; + } + } else if (sample_rate1 == 22050) { + if (bps1 >= 1.16) { + s->use_noise_coding = 0; + } else if (bps1 >= 0.72) { + high_freq = high_freq * 0.7; + } else { + high_freq = high_freq * 0.6; + } + } else if (sample_rate1 == 16000) { + if (bps > 0.5) { + high_freq = high_freq * 0.5; + } else { + high_freq = high_freq * 0.3; + } + } else if (sample_rate1 == 11025) { + high_freq = high_freq * 0.7; + } else if (sample_rate1 == 8000) { + if (bps <= 0.625) { + high_freq = high_freq * 0.5; + } else if (bps > 0.75) { + s->use_noise_coding = 0; + } else { + high_freq = high_freq * 0.65; + } + } else { + if (bps >= 0.8) { + high_freq = high_freq * 0.75; + } else if (bps >= 0.6) { + high_freq = high_freq * 0.6; + } else { + high_freq = high_freq * 0.5; + } + } + av_dlog(s->avctx, "flags2=0x%x\n", flags2); + av_dlog(s->avctx, "version=%d channels=%d sample_rate=%d bitrate=%d block_align=%d\n", + s->version, avctx->channels, avctx->sample_rate, avctx->bit_rate, + avctx->block_align); + av_dlog(s->avctx, "bps=%f bps1=%f high_freq=%f bitoffset=%d\n", + bps, bps1, high_freq, s->byte_offset_bits); + av_dlog(s->avctx, "use_noise_coding=%d use_exp_vlc=%d nb_block_sizes=%d\n", + s->use_noise_coding, s->use_exp_vlc, s->nb_block_sizes); + + /* compute the scale factor band sizes for each MDCT block size */ + { + int a, b, pos, lpos, k, block_len, i, j, n; + const uint8_t *table; + + if (s->version == 1) { + s->coefs_start = 3; + } else { + s->coefs_start = 0; + } + for (k = 0; k < s->nb_block_sizes; k++) { + block_len = s->frame_len >> k; + + if (s->version == 1) { + lpos = 0; + for (i = 0; i < 25; i++) { + a = ff_wma_critical_freqs[i]; + b = avctx->sample_rate; + pos = ((block_len * 2 * a) + (b >> 1)) / b; + if (pos > block_len) + pos = block_len; + s->exponent_bands[0][i] = pos - lpos; + if (pos >= block_len) { + i++; + break; + } + lpos = pos; + } + s->exponent_sizes[0] = i; + } else { + /* hardcoded tables */ + table = NULL; + a = s->frame_len_bits - BLOCK_MIN_BITS - k; + if (a < 3) { + if (avctx->sample_rate >= 44100) { + table = exponent_band_44100[a]; + } else if (avctx->sample_rate >= 32000) { + table = exponent_band_32000[a]; + } else if (avctx->sample_rate >= 22050) { + table = exponent_band_22050[a]; + } + } + if (table) { + n = *table++; + for (i = 0; i < n; i++) + s->exponent_bands[k][i] = table[i]; + s->exponent_sizes[k] = n; + } else { + j = 0; + lpos = 0; + for (i = 0; i < 25; i++) { + a = ff_wma_critical_freqs[i]; + b = avctx->sample_rate; + pos = ((block_len * 2 * a) + (b << 1)) / (4 * b); + pos <<= 2; + if (pos > block_len) + pos = block_len; + if (pos > lpos) + s->exponent_bands[k][j++] = pos - lpos; + if (pos >= block_len) + break; + lpos = pos; + } + s->exponent_sizes[k] = j; + } + } + + /* max number of coefs */ + s->coefs_end[k] = (s->frame_len - ((s->frame_len * 9) / 100)) >> k; + /* high freq computation */ + s->high_band_start[k] = (int)((block_len * 2 * high_freq) / + avctx->sample_rate + 0.5); + n = s->exponent_sizes[k]; + j = 0; + pos = 0; + for (i = 0; i < n; i++) { + int start, end; + start = pos; + pos += s->exponent_bands[k][i]; + end = pos; + if (start < s->high_band_start[k]) + start = s->high_band_start[k]; + if (end > s->coefs_end[k]) + end = s->coefs_end[k]; + if (end > start) + s->exponent_high_bands[k][j++] = end - start; + } + s->exponent_high_sizes[k] = j; +#if 0 + tprintf(s->avctx, "%5d: coefs_end=%d high_band_start=%d nb_high_bands=%d: ", + s->frame_len >> k, + s->coefs_end[k], + s->high_band_start[k], + s->exponent_high_sizes[k]); + for (j = 0; j < s->exponent_high_sizes[k]; j++) + tprintf(s->avctx, " %d", s->exponent_high_bands[k][j]); + tprintf(s->avctx, "\n"); +#endif + } + } + +#ifdef TRACE + { + int i, j; + for (i = 0; i < s->nb_block_sizes; i++) { + tprintf(s->avctx, "%5d: n=%2d:", + s->frame_len >> i, + s->exponent_sizes[i]); + for (j = 0; j < s->exponent_sizes[i]; j++) + tprintf(s->avctx, " %d", s->exponent_bands[i][j]); + tprintf(s->avctx, "\n"); + } + } +#endif + + /* init MDCT windows : simple sinus window */ + for (i = 0; i < s->nb_block_sizes; i++) { + ff_init_ff_sine_windows(s->frame_len_bits - i); + s->windows[i] = ff_sine_windows[s->frame_len_bits - i]; + } + + s->reset_block_lengths = 1; + + if (s->use_noise_coding) { + + /* init the noise generator */ + if (s->use_exp_vlc) { + s->noise_mult = 0.02; + } else { + s->noise_mult = 0.04; + } + +#ifdef TRACE + for (i = 0; i < NOISE_TAB_SIZE; i++) + s->noise_table[i] = 1.0 * s->noise_mult; +#else + { + unsigned int seed; + float norm; + seed = 1; + norm = (1.0 / (float)(1LL << 31)) * sqrt(3) * s->noise_mult; + for (i = 0; i < NOISE_TAB_SIZE; i++) { + seed = seed * 314159 + 1; + s->noise_table[i] = (float)((int)seed) * norm; + } + } +#endif + } + + /* choose the VLC tables for the coefficients */ + coef_vlc_table = 2; + if (avctx->sample_rate >= 32000) { + if (bps1 < 0.72) { + coef_vlc_table = 0; + } else if (bps1 < 1.16) { + coef_vlc_table = 1; + } + } + s->coef_vlcs[0]= &coef_vlcs[coef_vlc_table * 2 ]; + s->coef_vlcs[1]= &coef_vlcs[coef_vlc_table * 2 + 1]; + init_coef_vlc(&s->coef_vlc[0], &s->run_table[0], &s->level_table[0], &s->int_table[0], + s->coef_vlcs[0]); + init_coef_vlc(&s->coef_vlc[1], &s->run_table[1], &s->level_table[1], &s->int_table[1], + s->coef_vlcs[1]); + + return 0; +} + +int ff_wma_total_gain_to_bits(int total_gain) +{ + if (total_gain < 15) return 13; + else if (total_gain < 32) return 12; + else if (total_gain < 40) return 11; + else if (total_gain < 45) return 10; + else return 9; +} + +int ff_wma_end(AVCodecContext *avctx) +{ + WMACodecContext *s = avctx->priv_data; + int i; + + for (i = 0; i < s->nb_block_sizes; i++) + ff_mdct_end(&s->mdct_ctx[i]); + + if (s->use_exp_vlc) { + ff_free_vlc(&s->exp_vlc); + } + if (s->use_noise_coding) { + ff_free_vlc(&s->hgain_vlc); + } + for (i = 0; i < 2; i++) { + ff_free_vlc(&s->coef_vlc[i]); + av_free(s->run_table[i]); + av_free(s->level_table[i]); + av_free(s->int_table[i]); + } + + return 0; +} + +/** + * Decode an uncompressed coefficient. + * @param gb GetBitContext + * @return the decoded coefficient + */ +unsigned int ff_wma_get_large_val(GetBitContext* gb) +{ + /** consumes up to 34 bits */ + int n_bits = 8; + /** decode length */ + if (get_bits1(gb)) { + n_bits += 8; + if (get_bits1(gb)) { + n_bits += 8; + if (get_bits1(gb)) { + n_bits += 7; + } + } + } + return get_bits_long(gb, n_bits); +} + +/** + * Decode run level compressed coefficients. + * @param avctx codec context + * @param gb bitstream reader context + * @param vlc vlc table for get_vlc2 + * @param level_table level codes + * @param run_table run codes + * @param version 0 for wma1,2 1 for wmapro + * @param ptr output buffer + * @param offset offset in the output buffer + * @param num_coefs number of input coefficents + * @param block_len input buffer length (2^n) + * @param frame_len_bits number of bits for escaped run codes + * @param coef_nb_bits number of bits for escaped level codes + * @return 0 on success, -1 otherwise + */ +int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, + VLC *vlc, + const float *level_table, const uint16_t *run_table, + int version, WMACoef *ptr, int offset, + int num_coefs, int block_len, int frame_len_bits, + int coef_nb_bits) +{ + int code, level, sign; + const uint32_t *ilvl = (const uint32_t*)level_table; + uint32_t *iptr = (uint32_t*)ptr; + const unsigned int coef_mask = block_len - 1; + for (; offset < num_coefs; offset++) { + code = get_vlc2(gb, vlc->table, VLCBITS, VLCMAX); + if (code > 1) { + /** normal code */ + offset += run_table[code]; + sign = get_bits1(gb) - 1; + iptr[offset & coef_mask] = ilvl[code] ^ sign<<31; + } else if (code == 1) { + /** EOB */ + break; + } else { + /** escape */ + if (!version) { + level = get_bits(gb, coef_nb_bits); + /** NOTE: this is rather suboptimal. reading + block_len_bits would be better */ + offset += get_bits(gb, frame_len_bits); + } else { + level = ff_wma_get_large_val(gb); + /** escape decode */ + if (get_bits1(gb)) { + if (get_bits1(gb)) { + if (get_bits1(gb)) { + av_log(avctx,AV_LOG_ERROR, + "broken escape sequence\n"); + return -1; + } else + offset += get_bits(gb, frame_len_bits) + 4; + } else + offset += get_bits(gb, 2) + 1; + } + } + sign = get_bits1(gb) - 1; + ptr[offset & coef_mask] = (level^sign) - sign; + } + } + /** NOTE: EOB can be omitted */ + if (offset > num_coefs) { + av_log(avctx, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n"); + return -1; + } + + return 0; +} diff --git a/ffmpeg/libavcodec/wma.h b/ffmpeg/libavcodec/wma.h new file mode 100644 index 0000000..c4056ec --- /dev/null +++ b/ffmpeg/libavcodec/wma.h @@ -0,0 +1,159 @@ +/* + * WMA compatible codec + * Copyright (c) 2002-2007 The FFmpeg Project + * + * 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 + */ + +#ifndef AVCODEC_WMA_H +#define AVCODEC_WMA_H + +#include "libavutil/float_dsp.h" +#include "get_bits.h" +#include "put_bits.h" +#include "fft.h" +#include "fmtconvert.h" + +/* size of blocks */ +#define BLOCK_MIN_BITS 7 +#define BLOCK_MAX_BITS 11 +#define BLOCK_MAX_SIZE (1 << BLOCK_MAX_BITS) + +#define BLOCK_NB_SIZES (BLOCK_MAX_BITS - BLOCK_MIN_BITS + 1) + +/* XXX: find exact max size */ +#define HIGH_BAND_MAX_SIZE 16 + +#define NB_LSP_COEFS 10 + +/* XXX: is it a suitable value ? */ +#define MAX_CODED_SUPERFRAME_SIZE 16384 + +#define MAX_CHANNELS 2 + +#define NOISE_TAB_SIZE 8192 + +#define LSP_POW_BITS 7 + +//FIXME should be in wmadec +#define VLCBITS 9 +#define VLCMAX ((22+VLCBITS-1)/VLCBITS) + +typedef float WMACoef; ///< type for decoded coefficients, int16_t would be enough for wma 1/2 + +typedef struct CoefVLCTable { + int n; ///< total number of codes + int max_level; + const uint32_t *huffcodes; ///< VLC bit values + const uint8_t *huffbits; ///< VLC bit size + const uint16_t *levels; ///< table to build run/level tables +} CoefVLCTable; + +typedef struct WMACodecContext { + AVCodecContext* avctx; + GetBitContext gb; + PutBitContext pb; + int version; ///< 1 = 0x160 (WMAV1), 2 = 0x161 (WMAV2) + int use_bit_reservoir; + int use_variable_block_len; + int use_exp_vlc; ///< exponent coding: 0 = lsp, 1 = vlc + delta + int use_noise_coding; ///< true if perceptual noise is added + int byte_offset_bits; + VLC exp_vlc; + int exponent_sizes[BLOCK_NB_SIZES]; + uint16_t exponent_bands[BLOCK_NB_SIZES][25]; + int high_band_start[BLOCK_NB_SIZES]; ///< index of first coef in high band + int coefs_start; ///< first coded coef + int coefs_end[BLOCK_NB_SIZES]; ///< max number of coded coefficients + int exponent_high_sizes[BLOCK_NB_SIZES]; + int exponent_high_bands[BLOCK_NB_SIZES][HIGH_BAND_MAX_SIZE]; + VLC hgain_vlc; + + /* coded values in high bands */ + int high_band_coded[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; + int high_band_values[MAX_CHANNELS][HIGH_BAND_MAX_SIZE]; + + /* there are two possible tables for spectral coefficients */ +//FIXME the following 3 tables should be shared between decoders + VLC coef_vlc[2]; + uint16_t *run_table[2]; + float *level_table[2]; + uint16_t *int_table[2]; + const CoefVLCTable *coef_vlcs[2]; + /* frame info */ + int frame_len; ///< frame length in samples + int frame_len_bits; ///< frame_len = 1 << frame_len_bits + int nb_block_sizes; ///< number of block sizes + /* block info */ + int reset_block_lengths; + int block_len_bits; ///< log2 of current block length + int next_block_len_bits; ///< log2 of next block length + int prev_block_len_bits; ///< log2 of prev block length + int block_len; ///< block length in samples + int block_num; ///< block number in current frame + int block_pos; ///< current position in frame + uint8_t ms_stereo; ///< true if mid/side stereo mode + uint8_t channel_coded[MAX_CHANNELS]; ///< true if channel is coded + int exponents_bsize[MAX_CHANNELS]; ///< log2 ratio frame/exp. length + DECLARE_ALIGNED(32, float, exponents)[MAX_CHANNELS][BLOCK_MAX_SIZE]; + float max_exponent[MAX_CHANNELS]; + WMACoef coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE]; + DECLARE_ALIGNED(32, float, coefs)[MAX_CHANNELS][BLOCK_MAX_SIZE]; + DECLARE_ALIGNED(32, FFTSample, output)[BLOCK_MAX_SIZE * 2]; + FFTContext mdct_ctx[BLOCK_NB_SIZES]; + float *windows[BLOCK_NB_SIZES]; + /* output buffer for one frame and the last for IMDCT windowing */ + DECLARE_ALIGNED(32, float, frame_out)[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]; + /* last frame info */ + uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; /* padding added */ + int last_bitoffset; + int last_superframe_len; + float noise_table[NOISE_TAB_SIZE]; + int noise_index; + float noise_mult; /* XXX: suppress that and integrate it in the noise array */ + /* lsp_to_curve tables */ + float lsp_cos_table[BLOCK_MAX_SIZE]; + float lsp_pow_e_table[256]; + float lsp_pow_m_table1[(1 << LSP_POW_BITS)]; + float lsp_pow_m_table2[(1 << LSP_POW_BITS)]; + FmtConvertContext fmt_conv; + AVFloatDSPContext fdsp; + +#ifdef TRACE + int frame_count; +#endif +} WMACodecContext; + +extern const uint16_t ff_wma_critical_freqs[25]; +extern const uint16_t ff_wma_hgain_huffcodes[37]; +extern const uint8_t ff_wma_hgain_huffbits[37]; +extern const float ff_wma_lsp_codebook[NB_LSP_COEFS][16]; +extern const uint32_t ff_aac_scalefactor_code[121]; +extern const uint8_t ff_aac_scalefactor_bits[121]; + +int ff_wma_init(AVCodecContext * avctx, int flags2); +int ff_wma_total_gain_to_bits(int total_gain); +int ff_wma_end(AVCodecContext *avctx); +unsigned int ff_wma_get_large_val(GetBitContext* gb); +int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, + VLC *vlc, + const float *level_table, const uint16_t *run_table, + int version, WMACoef *ptr, int offset, + int num_coefs, int block_len, int frame_len_bits, + int coef_nb_bits); + +#endif /* AVCODEC_WMA_H */ diff --git a/ffmpeg/libavcodec/wma_common.c b/ffmpeg/libavcodec/wma_common.c new file mode 100644 index 0000000..d1d8045 --- /dev/null +++ b/ffmpeg/libavcodec/wma_common.c @@ -0,0 +1,62 @@ +/* + * common code shared by all WMA variants + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "wma_common.h" + +/** + *@brief Get the samples per frame for this stream. + *@param sample_rate output sample_rate + *@param version wma version + *@param decode_flags codec compression features + *@return log2 of the number of output samples per frame + */ +av_cold int ff_wma_get_frame_len_bits(int sample_rate, int version, + unsigned int decode_flags) +{ + + int frame_len_bits; + + if (sample_rate <= 16000) { + frame_len_bits = 9; + } else if (sample_rate <= 22050 || + (sample_rate <= 32000 && version == 1)) { + frame_len_bits = 10; + } else if (sample_rate <= 48000 || version < 3) { + frame_len_bits = 11; + } else if (sample_rate <= 96000) { + frame_len_bits = 12; + } else { + frame_len_bits = 13; + } + + if (version == 3) { + int tmp = decode_flags & 0x6; + if (tmp == 0x2) { + ++frame_len_bits; + } else if (tmp == 0x4) { + --frame_len_bits; + } else if (tmp == 0x6) { + frame_len_bits -= 2; + } + } + + return frame_len_bits; +} diff --git a/ffmpeg/libavcodec/wma_common.h b/ffmpeg/libavcodec/wma_common.h new file mode 100644 index 0000000..55404af --- /dev/null +++ b/ffmpeg/libavcodec/wma_common.h @@ -0,0 +1,27 @@ +/* + * common code shared by all WMA variants + * + * 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 + */ + +#ifndef AVCODEC_WMA_COMMON_H +#define AVCODEC_WMA_COMMON_H + +int ff_wma_get_frame_len_bits(int sample_rate, int version, + unsigned int decode_flags); + +#endif /* AVCODEC_WMA_COMMON_H */ diff --git a/ffmpeg/libavcodec/wmadata.h b/ffmpeg/libavcodec/wmadata.h new file mode 100644 index 0000000..381f182 --- /dev/null +++ b/ffmpeg/libavcodec/wmadata.h @@ -0,0 +1,1403 @@ +/* + * WMA compatible decoder + * copyright (c) 2002 The FFmpeg Project + * + * 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 + */ + +/** + * @file + * Various WMA tables. + */ + +#ifndef AVCODEC_WMADATA_H +#define AVCODEC_WMADATA_H + +#include +#include "wma.h" + +const uint16_t ff_wma_critical_freqs[25] = { + 100, 200, 300, 400, 510, 630, 770, 920, + 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, + 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, + 24500, +}; + +/* first value is number of bands */ +static const uint8_t exponent_band_22050[3][25] = { + { 10, 4, 8, 4, 8, 8, 12, 20, 24, 24, 16, }, + { 14, 4, 8, 8, 4, 12, 12, 16, 24, 16, 20, 24, 32, 40, 36, }, + { 23, 4, 4, 4, 8, 4, 4, 8, 8, 8, 8, 8, 12, 12, 16, 16, 24, 24, 32, 44, 48, 60, 84, 72, }, +}; + +static const uint8_t exponent_band_32000[3][25] = { + { 11, 4, 4, 8, 4, 4, 12, 16, 24, 20, 28, 4, }, + { 15, 4, 8, 4, 4, 8, 8, 16, 20, 12, 20, 20, 28, 40, 56, 8, }, + { 16, 8, 4, 8, 8, 12, 16, 20, 24, 40, 32, 32, 44, 56, 80, 112, 16, }, +}; + +static const uint8_t exponent_band_44100[3][25] = { + { 12, 4, 4, 4, 4, 4, 8, 8, 8, 12, 16, 20, 36, }, + { 15, 4, 8, 4, 8, 8, 4, 8, 8, 12, 12, 12, 24, 28, 40, 76, }, + { 17, 4, 8, 8, 4, 12, 12, 8, 8, 24, 16, 20, 24, 32, 40, 60, 80, 152, }, +}; + +const uint16_t ff_wma_hgain_huffcodes[37] = { + 0x00003, 0x002e7, 0x00001, 0x005cd, 0x0005d, 0x005c9, 0x0005e, 0x00003, + 0x00016, 0x0000b, 0x00001, 0x00006, 0x00001, 0x00006, 0x00004, 0x00005, + 0x00004, 0x00007, 0x00003, 0x00007, 0x00004, 0x0000a, 0x0000a, 0x00002, + 0x00003, 0x00000, 0x00005, 0x00002, 0x0005f, 0x00004, 0x00003, 0x00002, + 0x005c8, 0x000b8, 0x005ca, 0x005cb, 0x005cc, +}; + +const uint8_t ff_wma_hgain_huffbits[37] = { + 10, 12, 10, 13, 9, 13, 9, 8, + 7, 5, 5, 4, 4, 3, 3, 3, + 4, 3, 4, 4, 5, 5, 6, 8, + 7, 10, 8, 10, 9, 8, 9, 9, + 13, 10, 13, 13, 13, +}; + +const float ff_wma_lsp_codebook[NB_LSP_COEFS][16] = { + { 1.98732877, 1.97944528, 1.97179088, 1.96260549, 1.95038374, 1.93336114, 1.90719232, 1.86191415, }, + { 1.97260000, 1.96083160, 1.94982586, 1.93806164, 1.92516608, 1.91010199, 1.89232331, 1.87149812, + 1.84564818, 1.81358067, 1.77620070, 1.73265264, 1.67907855, 1.60959081, 1.50829650, 1.33120330, }, + { 1.90109110, 1.86482426, 1.83419671, 1.80168452, 1.76650116, 1.72816320, 1.68502700, 1.63738256, + 1.58501580, 1.51795181, 1.43679906, 1.33950585, 1.24176208, 1.12260729, 0.96749668, 0.74048265, }, + { 1.76943864, 1.67822463, 1.59946365, 1.53560582, 1.47470796, 1.41210167, 1.34509536, 1.27339507, + 1.19303814, 1.09765169, 0.98818722, 0.87239446, 0.74369172, 0.59768184, 0.43168630, 0.17977021, }, + { 1.43428349, 1.32038354, 1.21074086, 1.10577988, 1.00561746, 0.90335924, 0.80437489, 0.70709671, + 0.60427395, 0.49814048, 0.38509539, 0.27106800, 0.14407416, 0.00219910, -0.16725141, -0.36936085, }, + { 0.99895687, 0.84188166, 0.70753739, 0.57906595, 0.47055563, 0.36966965, 0.26826648, 0.17163380, + 0.07208392, -0.03062936, -1.40037388, -0.25128968, -0.37213937, -0.51075646, -0.64887512, -0.80308031, }, + { 0.26515280, 0.06313551, -0.08872080, -0.21103548, -0.31069678, -0.39680323, -0.47223474, -0.54167135, + -0.61444740, -0.68943343, -0.76580211, -0.85170082, -0.95289061, -1.06514703, -1.20510707, -1.37617746, }, + { -0.53940301, -0.73770929, -0.88424876, -1.01117930, -1.13389091, -1.26830073, -1.42041987, -1.62033919, + -1.10158808, -1.16512566, -1.23337128, -1.30414401, -1.37663312, -1.46853845, -1.57625798, -1.66893638, }, + { -0.38601997, -0.56009350, -0.66978483, -0.76028471, -0.83846064, -0.90868087, -0.97408881, -1.03694962, }, + { -1.56144989, -1.65944032, -1.72689685, -1.77857740, -1.82203011, -1.86220079, -1.90283983, -1.94820479, }, +}; + +static const uint32_t coef0_huffcodes[666] = { + 0x00258, 0x0003d, 0x00000, 0x00005, 0x00008, 0x00008, 0x0000c, 0x0001b, + 0x0001f, 0x00015, 0x00024, 0x00032, 0x0003a, 0x00026, 0x0002c, 0x0002f, + 0x0004a, 0x0004d, 0x00061, 0x00070, 0x00073, 0x00048, 0x00052, 0x0005a, + 0x0005d, 0x0006e, 0x00099, 0x0009e, 0x000c1, 0x000ce, 0x000e4, 0x000f0, + 0x00093, 0x0009e, 0x000a2, 0x000a1, 0x000b8, 0x000d2, 0x000d3, 0x0012e, + 0x00130, 0x000de, 0x0012d, 0x0019b, 0x001e4, 0x00139, 0x0013a, 0x0013f, + 0x0014f, 0x0016d, 0x001a2, 0x0027c, 0x0027e, 0x00332, 0x0033c, 0x0033f, + 0x0038b, 0x00396, 0x003c5, 0x00270, 0x0027c, 0x0025a, 0x00395, 0x00248, + 0x004bd, 0x004fb, 0x00662, 0x00661, 0x0071b, 0x004e6, 0x004ff, 0x00666, + 0x0071c, 0x0071a, 0x0071f, 0x00794, 0x00536, 0x004e2, 0x0078e, 0x004ee, + 0x00518, 0x00535, 0x004fb, 0x0078d, 0x00530, 0x00680, 0x0068f, 0x005cb, + 0x00965, 0x006a6, 0x00967, 0x0097f, 0x00682, 0x006ae, 0x00cd0, 0x00e28, + 0x00f13, 0x00f1f, 0x009f5, 0x00cd3, 0x00f11, 0x00926, 0x00964, 0x00f32, + 0x00f12, 0x00f30, 0x00966, 0x00d0b, 0x00a68, 0x00b91, 0x009c7, 0x00b73, + 0x012fa, 0x0131d, 0x013f9, 0x01ca0, 0x0199c, 0x01c7a, 0x0198c, 0x01248, + 0x01c74, 0x01c64, 0x0139e, 0x012fd, 0x00a77, 0x012fc, 0x01c7b, 0x012ca, + 0x014cc, 0x014d2, 0x014e3, 0x014dc, 0x012dc, 0x03344, 0x02598, 0x0263c, + 0x0333b, 0x025e6, 0x01a1c, 0x01e3c, 0x014e2, 0x033d4, 0x01a11, 0x03349, + 0x03cce, 0x014e1, 0x01a34, 0x0273e, 0x02627, 0x0273f, 0x038ee, 0x03971, + 0x03c67, 0x03c61, 0x0333d, 0x038c2, 0x0263f, 0x038cd, 0x02638, 0x02e41, + 0x0351f, 0x03348, 0x03c66, 0x03562, 0x02989, 0x027d5, 0x0333c, 0x02e4f, + 0x0343b, 0x02ddf, 0x04bc8, 0x029c0, 0x02e57, 0x04c72, 0x025b7, 0x03547, + 0x03540, 0x029d3, 0x04c45, 0x025bb, 0x06600, 0x04c73, 0x04bce, 0x0357b, + 0x029a6, 0x029d2, 0x0263e, 0x0298a, 0x07183, 0x06602, 0x07958, 0x04b66, + 0x0537d, 0x05375, 0x04fe9, 0x04b67, 0x0799f, 0x04bc9, 0x051fe, 0x06a3b, + 0x05bb6, 0x04fa8, 0x0728f, 0x05376, 0x0492c, 0x0537e, 0x0795a, 0x06a3c, + 0x0e515, 0x07887, 0x0683a, 0x051f9, 0x051fd, 0x0cc6a, 0x06a8a, 0x0cc6d, + 0x05bb3, 0x0683b, 0x051fc, 0x05378, 0x0728e, 0x07886, 0x05bb7, 0x0f2a4, + 0x0795b, 0x0683c, 0x09fc1, 0x0683d, 0x0b752, 0x09678, 0x0a3e8, 0x06ac7, + 0x051f0, 0x0b759, 0x06af3, 0x04b6b, 0x0f2a0, 0x0f2ad, 0x096c3, 0x0e518, + 0x0b75c, 0x0d458, 0x0cc6b, 0x0537c, 0x067aa, 0x04fea, 0x0343a, 0x0cc71, + 0x0967f, 0x09fc4, 0x096c2, 0x0e516, 0x0f2a1, 0x0d45c, 0x0d45d, 0x0d45e, + 0x12fb9, 0x0967e, 0x1982f, 0x09883, 0x096c4, 0x0b753, 0x12fb8, 0x0f2a8, + 0x1ca21, 0x096c5, 0x0e51a, 0x1ca27, 0x12f3c, 0x0d471, 0x0f2aa, 0x0b75b, + 0x12fbb, 0x0f2a9, 0x0f2ac, 0x0d45a, 0x0b74f, 0x096c8, 0x16e91, 0x096ca, + 0x12fbf, 0x0d0a7, 0x13103, 0x0d516, 0x16e99, 0x12cbd, 0x0a3ea, 0x19829, + 0x0b755, 0x29ba7, 0x1ca28, 0x29ba5, 0x16e93, 0x1982c, 0x19828, 0x25994, + 0x0a3eb, 0x1ca29, 0x16e90, 0x1ca25, 0x1982d, 0x1ca26, 0x16e9b, 0x0b756, + 0x0967c, 0x25997, 0x0b75f, 0x198d3, 0x0b757, 0x19a2a, 0x0d45b, 0x0e517, + 0x1ca24, 0x1ca23, 0x1ca22, 0x0b758, 0x16e97, 0x0cd14, 0x13100, 0x00007, + 0x0003b, 0x0006b, 0x00097, 0x00138, 0x00125, 0x00173, 0x00258, 0x00335, + 0x0028e, 0x004c6, 0x00715, 0x00729, 0x004ef, 0x00519, 0x004ed, 0x00532, + 0x0068c, 0x00686, 0x00978, 0x00e5d, 0x00e31, 0x009f4, 0x00b92, 0x012f8, + 0x00d06, 0x00a67, 0x00d44, 0x00a76, 0x00d59, 0x012cd, 0x01c78, 0x01c75, + 0x0199f, 0x0198f, 0x01c67, 0x014c6, 0x01c79, 0x01c76, 0x00b94, 0x00d1b, + 0x01e32, 0x01e31, 0x01ab0, 0x01a05, 0x01aa1, 0x0333a, 0x025e5, 0x02626, + 0x03541, 0x03544, 0x03421, 0x03546, 0x02e55, 0x02e56, 0x0492d, 0x02dde, + 0x0299b, 0x02ddc, 0x0357a, 0x0249c, 0x0668b, 0x1c77f, 0x1ca20, 0x0d45f, + 0x09886, 0x16e9a, 0x0f2a7, 0x0b751, 0x0a3ee, 0x0cf59, 0x0cf57, 0x0b754, + 0x0d0a6, 0x16e98, 0x0b760, 0x06ac6, 0x0a3f0, 0x12fbe, 0x13104, 0x0f2a5, + 0x0a3ef, 0x0d472, 0x12cba, 0x1982e, 0x16e9c, 0x1c77e, 0x198d0, 0x13105, + 0x16e92, 0x0b75d, 0x0d459, 0x0001a, 0x000c0, 0x0016c, 0x003cd, 0x00350, + 0x0067b, 0x0051e, 0x006a9, 0x009f4, 0x00b72, 0x00d09, 0x01249, 0x01e3d, + 0x01ca1, 0x01a1f, 0x01721, 0x01a8a, 0x016e8, 0x03347, 0x01a35, 0x0249d, + 0x0299a, 0x02596, 0x02e4e, 0x0298b, 0x07182, 0x04c46, 0x025ba, 0x02e40, + 0x027d6, 0x04fe8, 0x06607, 0x05310, 0x09884, 0x072e1, 0x06a3d, 0x04b6a, + 0x04c7a, 0x06603, 0x04c7b, 0x03428, 0x06605, 0x09664, 0x09fc0, 0x071de, + 0x06601, 0x05bb2, 0x09885, 0x0a3e2, 0x1c61f, 0x12cbb, 0x0b750, 0x0cf58, + 0x0967d, 0x25995, 0x668ad, 0x0b75a, 0x09fc2, 0x0537f, 0x0b75e, 0x13fae, + 0x12fbc, 0x00031, 0x001c4, 0x004c5, 0x005b8, 0x00cf4, 0x0096f, 0x00d46, + 0x01e57, 0x01a04, 0x02625, 0x03346, 0x028f9, 0x04c47, 0x072e0, 0x04b69, + 0x03420, 0x07957, 0x06639, 0x0799e, 0x07959, 0x07881, 0x04b68, 0x09fc3, + 0x09fd6, 0x0cc70, 0x0a3f1, 0x12cbe, 0x0e30e, 0x0e51b, 0x06af2, 0x12cbc, + 0x1c77d, 0x0f2ab, 0x12fbd, 0x1aa2f, 0x0a3ec, 0x0d473, 0x05377, 0x0a3e9, + 0x1982b, 0x0e300, 0x12f3f, 0x0cf5f, 0x096c0, 0x38c3c, 0x16e94, 0x16e95, + 0x12f3d, 0x29ba4, 0x29ba6, 0x1c77c, 0x6a8ba, 0x3545c, 0x33457, 0x668ac, + 0x6a8bb, 0x16e9d, 0x0e519, 0x25996, 0x12f3e, 0x00036, 0x0033e, 0x006ad, + 0x00d03, 0x012c8, 0x0124a, 0x03c42, 0x03ccd, 0x06606, 0x07880, 0x06852, + 0x06a3a, 0x05bb4, 0x0f2a2, 0x09fc7, 0x12cb9, 0x0cc6c, 0x0a6e8, 0x096c1, + 0x0004a, 0x00355, 0x012f9, 0x014e8, 0x01abe, 0x025b6, 0x0492e, 0x09fc6, + 0x051ff, 0x0cc6f, 0x096cb, 0x0d071, 0x198d1, 0x12cb8, 0x38c3d, 0x13faf, + 0x096c9, 0x0009d, 0x00539, 0x012ce, 0x0341f, 0x029c1, 0x04b33, 0x0a3e3, + 0x0d070, 0x16e96, 0x0b763, 0x000a0, 0x009ce, 0x038cc, 0x0343d, 0x051fa, + 0x09888, 0x12fba, 0x000df, 0x00a75, 0x029a7, 0x09fc5, 0x0e301, 0x0967b, + 0x001e7, 0x012c9, 0x051fb, 0x09889, 0x0f2a6, 0x0016f, 0x01cb9, 0x0cf5a, + 0x12cbf, 0x09679, 0x00272, 0x01a15, 0x0967a, 0x003cb, 0x025f6, 0x0b762, + 0x0028d, 0x03c60, 0x0cf5e, 0x00352, 0x03ccc, 0x0072f, 0x07186, 0x004ec, + 0x05379, 0x0068e, 0x09887, 0x006a7, 0x06af1, 0x00e29, 0x0cf5b, 0x00f31, + 0x0d470, 0x009c6, 0x013fb, 0x13102, 0x019a5, 0x13101, 0x01983, 0x01c65, + 0x0124f, 0x014c7, 0x01726, 0x01abf, 0x03304, 0x02624, 0x03c41, 0x027d7, + 0x02ddd, 0x02e54, 0x0343c, 0x06604, 0x07181, 0x0663a, 0x04fa9, 0x0663b, + 0x05311, 0x0537a, 0x06839, 0x05bb5, 0x0492f, 0x06af0, 0x096c7, 0x0cc6e, + 0x0537b, 0x0cf5c, 0x0cf56, 0x198d2, 0x0cf5d, 0x0a3ed, 0x0f2a3, 0x1982a, + 0x0b761, 0x096c6, +}; + +static const uint8_t coef0_huffbits[666] = { + 11, 6, 2, 3, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 10, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 11, 12, + 12, 12, 12, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 12, + 12, 12, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, + 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, + 15, 14, 14, 15, 15, 15, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 15, 15, 15, 15, 16, + 16, 16, 15, 16, 15, 15, 16, 16, + 16, 16, 15, 16, 16, 16, 15, 16, + 16, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 15, 15, 16, 16, + 15, 16, 16, 16, 17, 17, 17, 16, + 16, 17, 16, 16, 16, 16, 17, 16, + 17, 17, 16, 16, 15, 15, 15, 16, + 17, 16, 17, 16, 16, 17, 17, 17, + 17, 17, 17, 16, 17, 17, 17, 16, + 17, 17, 16, 17, 17, 17, 16, 17, + 17, 16, 16, 17, 17, 17, 18, 17, + 17, 17, 17, 17, 18, 18, 17, 17, + 17, 19, 17, 19, 18, 17, 17, 18, + 17, 17, 18, 17, 17, 17, 18, 17, + 17, 18, 17, 17, 17, 17, 17, 16, + 17, 17, 17, 17, 18, 16, 17, 4, + 6, 8, 9, 9, 10, 10, 10, 10, + 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 16, 15, + 15, 15, 15, 15, 15, 17, 17, 17, + 16, 18, 16, 17, 17, 16, 16, 17, + 17, 18, 17, 16, 17, 17, 17, 16, + 17, 17, 18, 17, 18, 17, 17, 17, + 18, 17, 17, 5, 8, 10, 10, 11, + 11, 12, 12, 12, 13, 13, 14, 13, + 13, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 16, 16, 15, 16, 16, + 15, 15, 15, 15, 15, 16, 16, 15, + 15, 16, 16, 17, 17, 18, 17, 16, + 17, 18, 19, 17, 16, 16, 17, 17, + 17, 6, 9, 11, 12, 12, 13, 13, + 13, 14, 14, 14, 15, 15, 15, 16, + 15, 15, 15, 15, 15, 15, 16, 16, + 16, 16, 17, 18, 16, 16, 16, 18, + 17, 16, 17, 18, 17, 17, 16, 17, + 17, 16, 17, 16, 17, 18, 18, 18, + 17, 19, 19, 17, 20, 19, 18, 19, + 20, 18, 16, 18, 17, 7, 10, 12, + 13, 13, 14, 14, 14, 15, 15, 16, + 16, 16, 16, 16, 18, 16, 17, 17, + 8, 11, 13, 14, 14, 15, 16, 16, + 16, 16, 17, 17, 17, 18, 18, 17, + 17, 8, 12, 14, 15, 15, 15, 17, + 17, 18, 17, 9, 12, 14, 15, 16, + 16, 17, 9, 13, 15, 16, 16, 17, + 9, 13, 16, 16, 16, 10, 13, 16, + 18, 17, 10, 14, 17, 10, 14, 17, + 11, 14, 16, 11, 14, 11, 15, 12, + 16, 12, 16, 12, 16, 12, 16, 12, + 17, 13, 13, 17, 13, 17, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 15, 15, 15, 15, 16, 15, + 16, 16, 16, 16, 16, 16, 17, 16, + 16, 16, 16, 17, 16, 17, 16, 17, + 17, 17, +}; + +static const uint32_t coef1_huffcodes[555] = { + 0x00115, 0x00002, 0x00001, 0x00000, 0x0000d, 0x00007, 0x00013, 0x0001d, + 0x00008, 0x0000c, 0x00023, 0x0002b, 0x0003f, 0x00017, 0x0001b, 0x00043, + 0x00049, 0x00050, 0x00055, 0x00054, 0x00067, 0x00064, 0x0007b, 0x0002d, + 0x00028, 0x0002a, 0x00085, 0x00089, 0x0002b, 0x00035, 0x00090, 0x00091, + 0x00094, 0x00088, 0x000c1, 0x000c6, 0x000f2, 0x000e3, 0x000c5, 0x000e2, + 0x00036, 0x000f0, 0x000a7, 0x000cd, 0x000fb, 0x00059, 0x00116, 0x00103, + 0x00108, 0x0012b, 0x0012d, 0x00188, 0x0012e, 0x0014c, 0x001c3, 0x00187, + 0x001e7, 0x0006f, 0x00094, 0x00069, 0x001e6, 0x001ca, 0x00147, 0x00195, + 0x000a7, 0x00213, 0x00209, 0x00303, 0x00295, 0x00289, 0x0028c, 0x0028d, + 0x00312, 0x00330, 0x0029b, 0x00308, 0x00328, 0x0029a, 0x0025e, 0x003c5, + 0x00384, 0x0039f, 0x00397, 0x00296, 0x0032e, 0x00332, 0x003c6, 0x003e6, + 0x0012d, 0x000d1, 0x00402, 0x000dd, 0x00161, 0x0012b, 0x00127, 0x0045d, + 0x00601, 0x004ab, 0x0045f, 0x00410, 0x004bf, 0x00528, 0x0045c, 0x00424, + 0x00400, 0x00511, 0x00618, 0x0073d, 0x0063a, 0x00614, 0x0073c, 0x007c0, + 0x007cf, 0x00802, 0x00966, 0x00964, 0x00951, 0x008a0, 0x00346, 0x00803, + 0x00a52, 0x0024a, 0x007c1, 0x0063f, 0x00126, 0x00406, 0x00789, 0x008a2, + 0x00960, 0x00967, 0x00c05, 0x00c70, 0x00c79, 0x00a5d, 0x00c26, 0x00c4d, + 0x00372, 0x008a5, 0x00c08, 0x002c5, 0x00f11, 0x00cc4, 0x00f8e, 0x00e16, + 0x00496, 0x00e77, 0x00f9c, 0x00c25, 0x00f1e, 0x00c27, 0x00f1f, 0x00e17, + 0x00ccd, 0x00355, 0x00c09, 0x00c78, 0x00f90, 0x00521, 0x00357, 0x00356, + 0x0068e, 0x00f9d, 0x00c04, 0x00e58, 0x00a20, 0x00a2c, 0x00c4c, 0x0052f, + 0x00f8d, 0x01178, 0x01053, 0x01097, 0x0180f, 0x0180d, 0x012fb, 0x012aa, + 0x0202a, 0x00a40, 0x018ed, 0x01ceb, 0x01455, 0x018e3, 0x012a1, 0x00354, + 0x00353, 0x00f1c, 0x00c7b, 0x00c37, 0x0101d, 0x012cb, 0x01142, 0x0197d, + 0x01095, 0x01e3b, 0x0186b, 0x00588, 0x01c2a, 0x014b8, 0x01e3a, 0x018ec, + 0x01f46, 0x012fa, 0x00a53, 0x01ce8, 0x00a55, 0x01c29, 0x0117b, 0x01052, + 0x012a0, 0x00589, 0x00950, 0x01c2b, 0x00a50, 0x0208b, 0x0180e, 0x02027, + 0x02556, 0x01e20, 0x006e7, 0x01c28, 0x0197a, 0x00684, 0x020a2, 0x01f22, + 0x03018, 0x039cf, 0x03e25, 0x02557, 0x0294c, 0x028a6, 0x00d11, 0x028a9, + 0x02979, 0x00d46, 0x00a56, 0x039ce, 0x030cc, 0x0329a, 0x0149d, 0x0510f, + 0x0451c, 0x02028, 0x03299, 0x01ced, 0x014b9, 0x00f85, 0x00c7a, 0x01800, + 0x00341, 0x012ca, 0x039c8, 0x0329d, 0x00d0d, 0x03e20, 0x05144, 0x00d45, + 0x030d0, 0x0186d, 0x030d5, 0x00d0f, 0x00d40, 0x04114, 0x020a1, 0x0297f, + 0x03e24, 0x032f1, 0x04047, 0x030d4, 0x028a8, 0x00d0e, 0x0451d, 0x04044, + 0x0297e, 0x04042, 0x030d2, 0x030cf, 0x03e21, 0x03e26, 0x028a5, 0x0451a, + 0x00d48, 0x01a16, 0x00d44, 0x04518, 0x0149b, 0x039ca, 0x01498, 0x0403d, + 0x0451b, 0x0149c, 0x032f3, 0x030cb, 0x08073, 0x03e22, 0x0529a, 0x020aa, + 0x039cc, 0x0738a, 0x06530, 0x07389, 0x06193, 0x08071, 0x04043, 0x030ce, + 0x05147, 0x07388, 0x05145, 0x08072, 0x04521, 0x00d47, 0x0297c, 0x030cd, + 0x030ca, 0x0000b, 0x0000c, 0x00083, 0x000e4, 0x00048, 0x00102, 0x001cc, + 0x001f5, 0x00097, 0x0020b, 0x00124, 0x00453, 0x00627, 0x00639, 0x00605, + 0x00517, 0x001b8, 0x00663, 0x00667, 0x007c3, 0x00823, 0x00961, 0x00963, + 0x00e5a, 0x00e59, 0x00a2b, 0x00cbf, 0x00292, 0x00a2d, 0x007d0, 0x00953, + 0x00cc5, 0x00f84, 0x004ab, 0x014a7, 0x0068a, 0x0117a, 0x0052e, 0x01442, + 0x0052c, 0x00c77, 0x00f8f, 0x004aa, 0x01094, 0x01801, 0x012c4, 0x0297b, + 0x00952, 0x01f19, 0x006a5, 0x01149, 0x012c5, 0x01803, 0x022f2, 0x0329b, + 0x04520, 0x0149e, 0x00d13, 0x01f16, 0x01ce9, 0x0101c, 0x006e6, 0x039c9, + 0x06191, 0x07c8e, 0x06192, 0x0ca63, 0x039cd, 0x06190, 0x06884, 0x06885, + 0x07382, 0x00d49, 0x00d41, 0x0450c, 0x0149a, 0x030d1, 0x08077, 0x03e23, + 0x01a15, 0x0e701, 0x0e702, 0x08079, 0x0822a, 0x0a218, 0x07887, 0x0403f, + 0x0520b, 0x0529b, 0x0e700, 0x04519, 0x00007, 0x000e0, 0x000d0, 0x0039b, + 0x003e5, 0x00163, 0x0063e, 0x007c9, 0x00806, 0x00954, 0x01044, 0x01f44, + 0x0197c, 0x01f45, 0x00a51, 0x01f47, 0x00951, 0x0052d, 0x02291, 0x0092f, + 0x00a54, 0x00d12, 0x0297d, 0x00d0c, 0x01499, 0x0329e, 0x032f0, 0x02025, + 0x039c6, 0x00a57, 0x03e46, 0x00d42, 0x0738b, 0x05146, 0x04046, 0x08078, + 0x0510e, 0x07886, 0x02904, 0x04156, 0x04157, 0x06032, 0x030d3, 0x08bce, + 0x04040, 0x0403e, 0x0a414, 0x10457, 0x08075, 0x06887, 0x07c8f, 0x039c7, + 0x07387, 0x08070, 0x08bcf, 0x1482a, 0x10456, 0x1482b, 0x01a17, 0x06886, + 0x0450d, 0x00013, 0x0006b, 0x00615, 0x0080b, 0x0082b, 0x00952, 0x00e5b, + 0x018e2, 0x0186c, 0x01f18, 0x0329f, 0x00d43, 0x03e29, 0x05140, 0x05141, + 0x0ca62, 0x06033, 0x03c42, 0x03e28, 0x0450f, 0x0a21a, 0x07384, 0x0a219, + 0x0e703, 0x0a21b, 0x01a14, 0x07383, 0x045e6, 0x0007a, 0x0012c, 0x00ccc, + 0x0068f, 0x01802, 0x00a52, 0x00953, 0x04045, 0x01a20, 0x0451f, 0x000a4, + 0x00735, 0x01cec, 0x02029, 0x020a3, 0x0451e, 0x00069, 0x00c24, 0x02024, + 0x032f2, 0x05142, 0x00196, 0x00523, 0x000a6, 0x0197b, 0x0030b, 0x0092e, + 0x003e9, 0x03e27, 0x00160, 0x05143, 0x00652, 0x04041, 0x00734, 0x028a7, + 0x0080f, 0x01483, 0x0097c, 0x00340, 0x0068b, 0x00522, 0x01054, 0x01096, + 0x01f17, 0x0202b, 0x01cea, 0x020a0, 0x02978, 0x02026, 0x0297a, 0x039cb, + 0x03e2b, 0x0149f, 0x0329c, 0x07385, 0x08074, 0x0450e, 0x03e2a, 0x05149, + 0x08076, 0x07386, 0x05148, +}; + +static const uint8_t coef1_huffbits[555] = { + 9, 5, 2, 4, 4, 5, 5, 5, + 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 9, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 13, 12, 12, 12, 12, 12, 12, 12, + 13, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 12, 12, 12, 13, 13, 13, + 13, 12, 12, 12, 12, 12, 12, 13, + 12, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 13, 13, 13, 13, 13, 13, + 13, 12, 12, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 13, 14, 13, 13, 13, + 13, 13, 14, 13, 14, 14, 13, 14, + 14, 13, 14, 13, 13, 14, 14, 13, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 15, 14, 14, 14, 14, 15, 15, + 15, 14, 14, 13, 13, 12, 12, 13, + 13, 13, 14, 14, 15, 14, 15, 15, + 14, 13, 14, 15, 15, 15, 14, 14, + 14, 14, 15, 14, 14, 15, 15, 15, + 14, 15, 14, 14, 14, 14, 14, 15, + 15, 16, 15, 15, 15, 14, 15, 15, + 15, 15, 14, 14, 16, 14, 15, 14, + 14, 15, 15, 15, 15, 16, 15, 14, + 15, 15, 15, 16, 15, 15, 14, 14, + 14, 4, 7, 8, 8, 9, 9, 9, + 9, 10, 10, 11, 11, 11, 11, 11, + 11, 12, 11, 11, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 11, 12, + 12, 12, 13, 13, 13, 13, 13, 13, + 13, 12, 12, 13, 13, 13, 13, 14, + 14, 13, 14, 13, 13, 13, 14, 14, + 15, 15, 14, 13, 13, 13, 14, 14, + 15, 15, 15, 16, 14, 15, 17, 17, + 15, 15, 15, 15, 15, 14, 16, 14, + 16, 16, 16, 16, 16, 16, 15, 15, + 17, 15, 16, 15, 6, 8, 10, 10, + 10, 11, 11, 11, 12, 12, 13, 13, + 13, 13, 14, 13, 14, 13, 14, 14, + 14, 14, 14, 15, 15, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 16, + 15, 15, 16, 15, 15, 15, 14, 16, + 15, 15, 18, 17, 16, 17, 15, 14, + 15, 16, 16, 19, 17, 19, 16, 17, + 15, 7, 10, 11, 12, 12, 12, 12, + 13, 13, 13, 14, 15, 14, 15, 15, + 16, 15, 14, 14, 15, 16, 15, 16, + 16, 16, 16, 15, 15, 7, 11, 12, + 13, 13, 14, 14, 15, 15, 15, 8, + 11, 13, 14, 14, 15, 9, 12, 14, + 14, 15, 9, 13, 10, 13, 10, 14, + 10, 14, 11, 15, 11, 15, 11, 14, + 12, 15, 12, 13, 13, 13, 13, 13, + 13, 14, 13, 14, 14, 14, 14, 14, + 14, 15, 14, 15, 16, 15, 14, 15, + 16, 15, 15, +}; + +static const uint32_t coef2_huffcodes[1336] = { + 0x003e6, 0x000f6, 0x00000, 0x00002, 0x00006, 0x0000f, 0x0001b, 0x00028, + 0x00039, 0x0003f, 0x0006b, 0x00076, 0x000b7, 0x000e8, 0x000ef, 0x00169, + 0x001a7, 0x001d4, 0x001dc, 0x002c4, 0x00349, 0x00355, 0x00391, 0x003dc, + 0x00581, 0x005b2, 0x00698, 0x0070c, 0x00755, 0x0073a, 0x00774, 0x007cf, + 0x00b0a, 0x00b66, 0x00d2e, 0x00d5e, 0x00e1b, 0x00eac, 0x00e5a, 0x00f7e, + 0x00fa1, 0x0163e, 0x01a37, 0x01a52, 0x01c39, 0x01ab3, 0x01d5f, 0x01cb6, + 0x01f52, 0x01dd9, 0x02c04, 0x02c2e, 0x02c2d, 0x02c23, 0x03467, 0x034a3, + 0x0351b, 0x03501, 0x03a5d, 0x0351c, 0x03875, 0x03dea, 0x0397b, 0x039db, + 0x03df1, 0x039d8, 0x03bb4, 0x0580a, 0x0584d, 0x05842, 0x05b13, 0x058ea, + 0x0697d, 0x06a06, 0x068cc, 0x06ac7, 0x06a96, 0x072f4, 0x07543, 0x072b4, + 0x07d20, 0x0b003, 0x073b5, 0x07be6, 0x0d180, 0x07bd1, 0x07cb8, 0x07d06, + 0x07d25, 0x0d2f2, 0x0d19a, 0x0d334, 0x0e1dc, 0x0d529, 0x0d584, 0x0e1d2, + 0x0e5e3, 0x0eec4, 0x0e564, 0x0fa49, 0x16001, 0x0eedc, 0x0f7fa, 0x1a32c, + 0x16131, 0x16003, 0x0f9c8, 0x1ef80, 0x1d2a0, 0x1aa4b, 0x0f7ce, 0x1abfe, + 0x1aa50, 0x1a458, 0x1a816, 0x1cae4, 0x1d2fe, 0x1d52e, 0x1aa4c, 0x2c245, + 0x1d2a1, 0x1a35d, 0x1ca1b, 0x1d5d8, 0x1f531, 0x1ca1c, 0x1f389, 0x1f4af, + 0x3a5e7, 0x351fb, 0x2c24b, 0x34bce, 0x2c24d, 0x2c249, 0x2c24a, 0x72dfc, + 0x357ef, 0x35002, 0x3a5e6, 0x39431, 0x5843b, 0x34a77, 0x58431, 0x3a5f3, + 0x3a5dd, 0x3e5e5, 0x356bd, 0x3976e, 0x6a3d2, 0x3500d, 0x694c4, 0x580bd, + 0x3e5e8, 0x74b95, 0x34a6e, 0x3977c, 0x39432, 0x5b0d2, 0x6a3d8, 0x580b8, + 0x5b0cb, 0x5b0d7, 0x72dee, 0x72ded, 0x72dec, 0x74b9c, 0x3977f, 0x72dea, + 0x74b9e, 0x7be7d, 0x580bf, 0x5b0d5, 0x7cba8, 0x74b91, 0x3e5dd, 0xb6171, + 0xd46b3, 0xd46b9, 0x7cba1, 0x74b9f, 0x72de1, 0xe59f5, 0x3e5eb, 0x00004, + 0x00015, 0x00038, 0x00075, 0x000e8, 0x001d3, 0x00347, 0x0039c, 0x00690, + 0x0074a, 0x00b60, 0x00e93, 0x00f74, 0x0163d, 0x01a5a, 0x01d24, 0x01cbe, + 0x01f4b, 0x03468, 0x03562, 0x03947, 0x03e82, 0x05804, 0x05b12, 0x05803, + 0x0696d, 0x06a9e, 0x0697c, 0x06978, 0x06afb, 0x074b2, 0x072f5, 0x073c0, + 0x07541, 0x06944, 0x074b7, 0x070d3, 0x07ba9, 0x0b0b1, 0x0d1af, 0x0e1dd, + 0x0e5e2, 0x0e1a3, 0x0eec3, 0x1612f, 0x0e961, 0x0eeda, 0x0e78e, 0x0fa48, + 0x1612c, 0x0e511, 0x0e565, 0x0e953, 0x1aa4a, 0x0e59d, 0x1d52c, 0x1a811, + 0x1cae7, 0x1abfc, 0x1d52d, 0x1cacf, 0x1cf05, 0x2c254, 0x34a72, 0x1f4ac, + 0x3976b, 0x34a71, 0x2c6d9, 0x2d873, 0x34a6a, 0x357e7, 0x3464c, 0x3e5f5, + 0x58433, 0x1f53a, 0x3500a, 0x357ea, 0x34a73, 0x3942f, 0x357e5, 0x39775, + 0x694cd, 0x39772, 0x7cba5, 0x6a3ef, 0x35483, 0x74b98, 0x5b0c1, 0x39770, + 0x3a5d7, 0x39433, 0x39434, 0x694ce, 0x580be, 0x3e5ff, 0x6a3ec, 0xb616f, + 0xd46b1, 0x6a3d1, 0x72de5, 0x74b6e, 0x72de9, 0x3e700, 0xd46b6, 0x6a3e9, + 0x74b69, 0xe5675, 0xd46b8, 0x7cbaa, 0x3a5d1, 0x0000c, 0x0003c, 0x000eb, + 0x001f1, 0x003a4, 0x006a8, 0x007d5, 0x00d43, 0x00e77, 0x016c5, 0x01cb1, + 0x02c5d, 0x03a55, 0x03a56, 0x03e51, 0x03bb5, 0x05b0a, 0x06a9f, 0x074b8, + 0x07d28, 0x0d187, 0x0d40e, 0x0d52e, 0x0d425, 0x0eae3, 0x0e1d3, 0x1612e, + 0x0e59e, 0x0eec2, 0x0e578, 0x0e51a, 0x0e579, 0x0e515, 0x0e960, 0x0d183, + 0x0d220, 0x0d2cb, 0x0e512, 0x16c3e, 0x16002, 0x16c42, 0x1cae9, 0x3461a, + 0x1d2fa, 0x1a308, 0x1a849, 0x1cf07, 0x1f38f, 0x34b65, 0x2c253, 0x1ef9e, + 0x1cbc3, 0x1cbc1, 0x2c255, 0x1f384, 0x58435, 0x2c5cd, 0x3a5f7, 0x2c252, + 0x3959c, 0x2c6d8, 0x3a5d3, 0x6ad78, 0x6a3f2, 0x7cba9, 0xb6176, 0x72deb, + 0x39764, 0x3e5f6, 0x3a5d8, 0x74a8c, 0x6a3e6, 0x694d1, 0x6ad79, 0x1a4592, + 0xe59fb, 0x7cbb3, 0x5b0cd, 0x00017, 0x000b5, 0x002c3, 0x005b7, 0x00b1c, + 0x00e5c, 0x0163f, 0x01ab2, 0x01efa, 0x0348a, 0x0396e, 0x058da, 0x06963, + 0x06a30, 0x072cd, 0x073cf, 0x07ce7, 0x0d2ca, 0x0d2d8, 0x0e764, 0x0e794, + 0x16008, 0x16167, 0x1617e, 0x1aa49, 0x1a30b, 0x1a813, 0x2c6da, 0x1a580, + 0x1cbc2, 0x0f9ca, 0x1617f, 0x1d2fe, 0x0f7fc, 0x16c40, 0x0e513, 0x0eec5, + 0x0f7c3, 0x1d508, 0x1a81e, 0x1d2fd, 0x39430, 0x35486, 0x3e5fd, 0x2c24c, + 0x2c75a, 0x34a74, 0x3a5f4, 0x3464d, 0x694ca, 0x3a5f1, 0x1d509, 0x1d5c0, + 0x34648, 0x3464e, 0x6a3d5, 0x6a3e8, 0x6a3e7, 0x5b0c3, 0x2c248, 0x1f38a, + 0x3a5f2, 0x6a3e5, 0x00029, 0x00168, 0x0058c, 0x00b67, 0x00f9d, 0x01c3d, + 0x01cbf, 0x02c20, 0x0351d, 0x03df6, 0x06af9, 0x072b5, 0x0b1d7, 0x0b0b2, + 0x0d40a, 0x0d52b, 0x0e952, 0x0e797, 0x163c3, 0x1c3a0, 0x1f386, 0x1ca21, + 0x34655, 0x2c247, 0x1f53b, 0x2c250, 0x2c24f, 0x1f385, 0x1ef5d, 0x1cf15, + 0x1caea, 0x1ab0a, 0x1cf19, 0x1f53d, 0x1d5c2, 0x1d2fb, 0x1ef58, 0x34a78, + 0x357ec, 0x1f533, 0x3a5e1, 0x694d2, 0x58482, 0x3a5ee, 0x2c6dc, 0x357eb, + 0x5b0c4, 0x39778, 0x6a3e1, 0x7cbb4, 0x3a5e1, 0x74b68, 0x3a5ef, 0x3a5d2, + 0x39424, 0x72de2, 0xe59f6, 0xe59f7, 0x3e702, 0x3e5ec, 0x1f38b, 0x0003b, + 0x001f0, 0x00777, 0x00fa8, 0x01cb2, 0x02d84, 0x03a57, 0x03dd6, 0x06917, + 0x06a11, 0x07d07, 0x0eae2, 0x0e796, 0x0f9c9, 0x0f7fb, 0x16166, 0x16160, + 0x1ab1b, 0x1abfa, 0x2d87b, 0x1d2f7, 0x39768, 0x1f38c, 0x34653, 0x34651, + 0x6a3d9, 0x35001, 0x3abbd, 0x38742, 0x39426, 0x34a76, 0x3a5ec, 0x34a75, + 0x35000, 0x35488, 0x1cf10, 0x2c6db, 0x357ed, 0x357e8, 0x357e9, 0x3a5f0, + 0x694c2, 0xb6178, 0x72df5, 0x39425, 0x3942b, 0x74b6d, 0x74b6f, 0xb6177, + 0xb6179, 0x74b6a, 0xb6172, 0x58487, 0x3e5ee, 0x3e5ed, 0x72df2, 0x72df4, + 0x7cbae, 0x6a3ca, 0x70e86, 0x34bcf, 0x6a3c8, 0x00059, 0x00384, 0x00d5b, + 0x01c38, 0x03560, 0x0395b, 0x0584e, 0x06964, 0x073cd, 0x0b1e7, 0x0e798, + 0x0e78d, 0x0fa43, 0x1a848, 0x1a32f, 0x1aa4e, 0x3464a, 0x1f4ab, 0x1f38d, + 0x3a5eb, 0x3a5d4, 0x3548a, 0x6a3c7, 0x5b0d0, 0x6a3c5, 0x7cbb0, 0x694cb, + 0x3a5e5, 0x3e5e2, 0x3942c, 0x2d872, 0x1f4ae, 0x3a5d5, 0x694d3, 0x58481, + 0x35009, 0x39774, 0x58432, 0xb616c, 0x5b0db, 0x3548b, 0xb6174, 0x1d5d95, + 0xb004c, 0x7cbb2, 0x3a5e5, 0x74a8f, 0xe59f9, 0x72df6, 0xe59fd, 0x7cbad, + 0xd427d, 0x72cff, 0x3977a, 0x5b0d9, 0xb616d, 0xb616b, 0x1a4593, 0x7cbaf, + 0x5b0da, 0x00071, 0x003eb, 0x01603, 0x02c6c, 0x03961, 0x068c8, 0x06a31, + 0x072bd, 0x0d2c2, 0x0e51b, 0x0e5e6, 0x1abfb, 0x1d2ff, 0x1cae5, 0x1ef5c, + 0x1ef5e, 0x1cf13, 0x34a6d, 0x3976d, 0xb616a, 0x3e5f2, 0x6a3c4, 0xb6169, + 0x3e5dc, 0x580b9, 0x74b99, 0x75764, 0x58434, 0x3a5d9, 0x6945a, 0x69459, + 0x3548c, 0x3a5e9, 0x69457, 0x72df1, 0x6945e, 0x6a35e, 0x3e701, 0xb6168, + 0x5b0dd, 0x3a5de, 0x6a3c2, 0xd4278, 0x6a3cc, 0x72dfd, 0xb6165, 0x16009a, + 0x7cbb1, 0xd427c, 0xb6162, 0xe765e, 0x1cecbe, 0x7cbb6, 0x69454, 0xb6160, + 0xd427a, 0x1d5d96, 0xb1d6d, 0xe59f4, 0x72de8, 0x3a5db, 0x0007a, 0x006ae, + 0x01c3c, 0x03aba, 0x058e9, 0x072cc, 0x0d2dd, 0x0d22d, 0x0eec1, 0x0eedb, + 0x1d2a2, 0x1ef5b, 0x357e2, 0x3abbf, 0x1d2f9, 0x35004, 0x3a5dc, 0x351fc, + 0x3976c, 0x6a3c6, 0x6a3cb, 0x3e5ea, 0xe59f3, 0x6a3ce, 0x69452, 0xe59f0, + 0x74b90, 0xd4279, 0xd427b, 0x7cbb5, 0x5b0c5, 0x3a5e3, 0x3a5e2, 0x000d0, + 0x00775, 0x01efe, 0x03dd5, 0x0728c, 0x07cb9, 0x0e1a2, 0x0ea85, 0x0eed8, + 0x1a30a, 0x1aa4f, 0x3a5df, 0x35008, 0x3a5e0, 0x3e5f4, 0x3e5f7, 0xb1d6c, + 0x5843e, 0x34a70, 0x72df8, 0x74b6b, 0xd427f, 0x72df0, 0x5b0bf, 0x5b0c0, + 0xd46b0, 0x72def, 0xe59f8, 0x162e64, 0xb1d6f, 0x3a5e0, 0x39427, 0x69166, + 0x6a3e2, 0x6a3e3, 0x74a8d, 0xd427e, 0x1d5d97, 0xd46b4, 0x5b0d8, 0x6a3d3, + 0x000e0, 0x00b63, 0x034cc, 0x06a33, 0x073c9, 0x0e1a0, 0x0f7fd, 0x0f9cc, + 0x1617d, 0x1caeb, 0x1f4a9, 0x3abb3, 0x69450, 0x39420, 0x39777, 0x3e5e0, + 0x6a3d4, 0x6a3ed, 0xb6166, 0xe59f1, 0xb1d6e, 0xe5676, 0x6a3ea, 0xe5674, + 0xb6163, 0xd46b7, 0x7cba6, 0xd46ba, 0x1d5d94, 0xb6164, 0x6a3f1, 0x7cba2, + 0x69451, 0x72dfa, 0xd46bb, 0x72df7, 0x74b94, 0x1cecbf, 0xe59fa, 0x16009b, + 0x6a3e4, 0x000e6, 0x00e94, 0x03876, 0x070ef, 0x0d52a, 0x16015, 0x16014, + 0x1abf9, 0x1cf17, 0x34a79, 0x34650, 0x3e705, 0x6a3d0, 0x58430, 0x74b9d, + 0x7be7e, 0x5b0be, 0x39773, 0x6a3de, 0x000fb, 0x00f7b, 0x03dd7, 0x07bd0, + 0x0e59c, 0x0f9cd, 0x1cf18, 0x1d2ff, 0x34a7a, 0x39429, 0x3500c, 0x72de0, + 0x69456, 0x7be7c, 0xd46b5, 0xd46b2, 0x6a3dd, 0x001a2, 0x0163b, 0x06913, + 0x0b016, 0x0fa42, 0x1a32d, 0x1cf06, 0x34a7c, 0x34a7d, 0xb6161, 0x35481, + 0x3e5fa, 0x7cba0, 0x7be7f, 0x7cba3, 0x7cba7, 0x5b0d3, 0x72de6, 0x6a3dc, + 0x001a9, 0x01ab4, 0x06a34, 0x0d46a, 0x16130, 0x1ef5f, 0x1f532, 0x1f536, + 0x3942e, 0x58436, 0x6a3db, 0x6945b, 0x001c9, 0x01ca0, 0x0728b, 0x0eed9, + 0x1f539, 0x1ca1d, 0x39765, 0x39766, 0x58439, 0x6945d, 0x39767, 0x001d3, + 0x01f2c, 0x07bfc, 0x16161, 0x34652, 0x3a5ed, 0x3548d, 0x58438, 0x6a3da, + 0x002c1, 0x02c5e, 0x0d335, 0x1ab1a, 0x2d874, 0x35006, 0x35484, 0x5b0cc, + 0x74b9a, 0x72df3, 0x6a3d6, 0x002da, 0x034b3, 0x0d5ae, 0x1caee, 0x2d871, + 0x357e3, 0x74b97, 0x72df9, 0x580ba, 0x5b0d4, 0x0034d, 0x0354e, 0x0f750, + 0x1cbc0, 0x3a5e7, 0x3a5e4, 0x00385, 0x03a58, 0x16c41, 0x2c5cf, 0x3e5e1, + 0x74b6c, 0xe5677, 0x6a3df, 0x00390, 0x03e50, 0x163c2, 0x2d876, 0x35482, + 0x5b0d6, 0x5843a, 0x0039f, 0x0585e, 0x1a583, 0x3500f, 0x74b93, 0x39771, + 0x003e4, 0x06912, 0x16c43, 0x357e1, 0x0058a, 0x0696f, 0x1f538, 0x5b0c9, + 0x6a3cf, 0x005b6, 0x06af8, 0x1f534, 0x58483, 0x6a3e0, 0x00695, 0x07d02, + 0x1cae8, 0x58485, 0x006a2, 0x0754a, 0x357ee, 0x3977b, 0x00748, 0x074b2, + 0x34a7b, 0x00729, 0x0b1e0, 0x34649, 0x3e5e3, 0x0073d, 0x0d2c4, 0x3e5e6, + 0x007bb, 0x0b099, 0x39762, 0x5b0ce, 0x6945f, 0x007d1, 0x0d5ab, 0x39779, + 0x007d3, 0x0d52f, 0x39763, 0x6945c, 0x00b1a, 0x0d2c5, 0x35489, 0x00d23, + 0x0eaed, 0x3e5f8, 0x00d32, 0x16016, 0x3e5fb, 0x00d41, 0x0e768, 0x3a5ed, + 0x00e1f, 0x16017, 0x58027, 0x00ead, 0x0fa07, 0x69455, 0x00e54, 0x1612b, + 0x00e55, 0x1a581, 0x00f78, 0x1a32b, 0x580bc, 0x6a3ee, 0x00f79, 0x1abfd, + 0x00f95, 0x1ab18, 0x6a3f0, 0x01637, 0x1aa4d, 0x0162d, 0x1f53c, 0x6a3f3, + 0x01a31, 0x1a810, 0x39769, 0x01a50, 0x1caef, 0x01a36, 0x1a32e, 0x01a67, + 0x1f38e, 0x01a85, 0x1ef59, 0x01aa6, 0x1ef83, 0x01d51, 0x2c012, 0x01d53, + 0x2d879, 0x01d5e, 0x35005, 0x01cba, 0x1cf04, 0x69453, 0x01d2d, 0x351ff, + 0x01f2d, 0x2d86f, 0x01f29, 0x35007, 0x02c22, 0x351fa, 0x02c03, 0x3a5ec, + 0x02c5f, 0x3a5eb, 0x02c58, 0x34a6b, 0x03469, 0x356be, 0x02c59, 0x34a6c, + 0x0346a, 0x3a5ea, 0x034bd, 0x034bf, 0x356bf, 0x0386a, 0x03ab9, 0x5843f, + 0x0386b, 0x3a5f5, 0x03a4b, 0x39421, 0x03aa4, 0x3a5e9, 0x03a5a, 0x03960, + 0x3977e, 0x03de9, 0x03958, 0x03df7, 0x039e1, 0x3e5e4, 0x0395f, 0x69458, + 0x03e91, 0x03df2, 0x39428, 0x058f2, 0x03e80, 0x6a3c3, 0x03e93, 0x694c0, + 0x058b8, 0x5b0ca, 0x0584f, 0x694c1, 0x058f1, 0x068d6, 0x06a10, 0x06ac3, + 0x06a32, 0x070d2, 0x06911, 0x074b1, 0x07494, 0x06ad4, 0x06ad6, 0x072b8, + 0x06afa, 0x074b3, 0x07540, 0x073ce, 0x0b005, 0x074b3, 0x07495, 0x074b9, + 0x0d336, 0x07bff, 0x07763, 0x073c8, 0x07d29, 0x0b622, 0x0d221, 0x0d181, + 0x0b1d1, 0x074b8, 0x0b1d0, 0x0d19b, 0x0d2c3, 0x0b172, 0x0d2dc, 0x0b623, + 0x0d5aa, 0x0d426, 0x0d182, 0x0e795, 0x0e1d1, 0x0d337, 0x0e96c, 0x0e5e4, + 0x0e514, 0x0eaee, 0x16000, 0x0e767, 0x0e1a1, 0x0e78f, 0x16004, 0x0f7c2, + 0x0e799, 0x0e5e7, 0x0e566, 0x0e769, 0x0f751, 0x0eede, 0x0fa06, 0x16005, + 0x0fa9f, 0x1a5e6, 0x0e766, 0x1636f, 0x0eedd, 0x0eec0, 0x1a309, 0x1ceca, + 0x163cd, 0x0f9cb, 0x0eedf, 0x1a582, 0x1612d, 0x0e5e5, 0x1abf8, 0x1a30c, + 0x1ca1f, 0x163cc, 0x1a35c, 0x1ca1e, 0x1aa51, 0x163ac, 0x1a84e, 0x1a53f, + 0x1cf16, 0x1d2fc, 0x1a5b3, 0x1ab19, 0x1a81f, 0x1d5c3, 0x16c3f, 0x1d5c1, + 0x1d2fc, 0x1f4aa, 0x1a812, 0x1f535, 0x1cf12, 0x1a817, 0x1617c, 0x1ab0b, + 0x1d2f8, 0x1ef82, 0x2d87a, 0x1d52f, 0x1f530, 0x1aa48, 0x35487, 0x1d2fd, + 0x1f4ad, 0x1cf11, 0x3461b, 0x35485, 0x1ca20, 0x1caed, 0x1cae6, 0x1abff, + 0x3464f, 0x34a6f, 0x1ef81, 0x3464b, 0x39d96, 0x1f383, 0x1f537, 0x1cf14, + 0x2c5ce, 0x3500e, 0x2c251, 0x1caec, 0x1f387, 0x34654, 0x357e4, 0x2d878, + 0x3500b, 0x35480, 0x3a5e8, 0x3548e, 0x34b64, 0x1f4a8, 0x35003, 0x3e5df, + 0x2d870, 0x357e6, 0x3e5f0, 0x1ef5a, 0x3a5ea, 0x1f388, 0x3e703, 0x2c24e, + 0x3a5e2, 0x351fd, 0x2c6dd, 0x3e704, 0x351fe, 0x2d875, 0x5b0c7, 0x3976a, + 0x3a5e6, 0x39423, 0x58480, 0x2c246, 0x3a5e3, 0x2d877, 0x3e5f1, 0x3abbe, + 0x58489, 0x3e5f9, 0x357e0, 0x3abbc, 0x5b0c6, 0x69167, 0x69165, 0x3e5e9, + 0x39422, 0x3976f, 0x3977d, 0x3e5de, 0x6a3c9, 0x58b98, 0x3a5f6, 0x3a5d0, + 0x58486, 0x6a3c1, 0x3e5fc, 0x5b0dc, 0x3548f, 0x3942d, 0x694c9, 0x58484, + 0x3a5e8, 0x74b9b, 0x74b96, 0x694d0, 0x58488, 0x3a5e4, 0x3942a, 0x72ec2, + 0x39776, 0x5b0d1, 0x5b0cf, 0x3a5d6, 0xe59fc, 0x5b0c8, 0x3e5e7, 0x7cbb7, + 0x70e87, 0x7cbab, 0x5b0c2, 0x694c3, 0x74a8e, 0x3e5f3, 0x6a3cd, 0x72dfe, + 0x73b2e, 0x72ec0, 0x694c5, 0x58437, 0x694c8, 0x72dff, 0x39435, 0x5843d, + 0x6a3d7, 0x72ec1, 0xd22c8, 0x694cf, 0xb6173, 0x3e5fe, 0x580bb, 0xe59f2, + 0xb616e, 0xb6175, 0x3a5da, 0x5b0bd, 0x694cc, 0x5843c, 0x694c7, 0x74b92, + 0x72ec3, 0x694c6, 0xb6170, 0x7cbac, 0xb1733, 0x7cba4, 0xb6167, 0x72de7, + 0x72de4, 0x6a3c0, 0x3e5ef, 0x162e65, 0x72de3, 0x72dfb, 0x6a35f, 0x6a3eb, +}; + +static const uint8_t coef2_huffbits[1336] = { + 11, 9, 2, 3, 4, 4, 5, 6, + 6, 7, 7, 8, 8, 8, 9, 9, + 9, 9, 10, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 16, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 18, 17, 17, 17, 17, + 17, 17, 17, 18, 18, 17, 17, 18, + 17, 17, 18, 17, 18, 18, 18, 18, + 19, 18, 18, 18, 18, 18, 18, 20, + 18, 18, 18, 19, 19, 18, 19, 18, + 19, 19, 18, 19, 19, 18, 19, 19, + 19, 19, 18, 19, 19, 19, 19, 19, + 19, 19, 20, 20, 20, 19, 19, 20, + 19, 20, 19, 19, 20, 19, 19, 20, + 20, 20, 20, 19, 20, 21, 19, 3, + 5, 7, 8, 9, 9, 10, 11, 11, + 12, 12, 12, 13, 13, 13, 13, 14, + 14, 14, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 16, 16, + 15, 15, 15, 15, 16, 16, 16, 16, + 17, 16, 17, 17, 16, 17, 17, 17, + 17, 17, 17, 16, 17, 17, 17, 17, + 18, 17, 17, 18, 18, 18, 18, 18, + 19, 18, 18, 18, 18, 18, 18, 19, + 19, 18, 18, 18, 18, 19, 18, 19, + 19, 19, 20, 19, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 20, + 20, 19, 20, 19, 20, 19, 20, 19, + 19, 21, 20, 20, 19, 4, 7, 8, + 10, 11, 11, 12, 12, 13, 13, 14, + 14, 14, 14, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 16, 16, + 16, 16, 17, 17, 17, 17, 18, 18, + 18, 17, 17, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 19, 18, 18, 18, + 19, 18, 19, 19, 19, 20, 20, 20, + 19, 19, 19, 19, 19, 19, 19, 21, + 21, 20, 19, 5, 8, 10, 11, 12, + 13, 13, 13, 14, 14, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 17, 17, + 17, 17, 17, 17, 17, 17, 18, 17, + 18, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 19, 18, 19, 18, + 18, 18, 18, 18, 19, 18, 17, 17, + 18, 18, 19, 19, 19, 19, 18, 18, + 18, 19, 6, 9, 11, 12, 13, 13, + 14, 14, 14, 15, 15, 16, 16, 16, + 16, 16, 16, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 17, 18, 18, 17, 18, 18, 18, + 18, 18, 18, 19, 19, 18, 18, 18, + 19, 19, 19, 20, 19, 19, 18, 19, + 19, 20, 21, 21, 19, 19, 18, 6, + 10, 12, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 17, 17, 17, 17, 17, + 17, 17, 18, 18, 19, 18, 18, 18, + 19, 18, 18, 18, 19, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 19, 20, 20, 19, 19, 19, 19, 20, + 20, 19, 20, 19, 19, 19, 20, 20, + 20, 19, 19, 18, 19, 7, 10, 12, + 13, 14, 15, 15, 15, 16, 16, 17, + 17, 17, 17, 17, 17, 18, 18, 18, + 18, 19, 18, 19, 19, 19, 20, 19, + 18, 19, 19, 18, 18, 19, 19, 19, + 18, 19, 19, 20, 19, 18, 20, 21, + 20, 20, 19, 19, 21, 20, 21, 20, + 20, 20, 19, 19, 20, 20, 21, 20, + 19, 7, 11, 13, 14, 15, 15, 15, + 16, 16, 17, 17, 17, 17, 18, 18, + 18, 18, 18, 19, 20, 19, 19, 20, + 19, 19, 19, 19, 19, 19, 19, 19, + 18, 18, 19, 20, 19, 19, 19, 20, + 19, 19, 19, 20, 19, 20, 20, 21, + 20, 20, 20, 21, 22, 20, 19, 20, + 20, 21, 20, 21, 20, 19, 8, 11, + 13, 14, 15, 16, 16, 16, 17, 17, + 17, 18, 18, 18, 18, 18, 19, 18, + 19, 19, 19, 19, 21, 19, 19, 21, + 19, 20, 20, 20, 19, 18, 18, 8, + 12, 14, 15, 16, 16, 16, 16, 17, + 17, 17, 19, 18, 18, 19, 19, 20, + 19, 18, 20, 19, 20, 20, 19, 19, + 20, 20, 21, 21, 20, 19, 19, 19, + 19, 19, 19, 20, 21, 20, 19, 19, + 8, 12, 14, 15, 16, 16, 17, 17, + 17, 18, 18, 18, 19, 19, 19, 19, + 19, 19, 20, 21, 20, 21, 19, 21, + 20, 20, 20, 20, 21, 20, 19, 20, + 19, 20, 20, 20, 19, 22, 21, 21, + 19, 9, 12, 14, 15, 16, 17, 17, + 17, 18, 18, 18, 19, 19, 19, 19, + 20, 19, 19, 19, 9, 13, 15, 16, + 17, 17, 18, 18, 18, 19, 18, 20, + 19, 20, 20, 20, 19, 9, 13, 15, + 16, 17, 17, 18, 18, 18, 20, 18, + 19, 20, 20, 20, 20, 19, 20, 19, + 9, 13, 15, 16, 17, 18, 18, 18, + 19, 19, 19, 19, 10, 14, 16, 17, + 18, 18, 19, 19, 19, 19, 19, 10, + 14, 16, 17, 18, 18, 18, 19, 19, + 10, 14, 16, 17, 18, 18, 18, 19, + 19, 20, 19, 10, 14, 16, 18, 18, + 18, 19, 20, 19, 19, 10, 14, 17, + 18, 18, 18, 10, 15, 17, 18, 19, + 19, 21, 19, 11, 15, 17, 18, 18, + 19, 19, 11, 15, 17, 18, 19, 19, + 11, 15, 17, 18, 11, 15, 18, 19, + 19, 11, 15, 18, 19, 19, 11, 16, + 18, 19, 11, 15, 18, 19, 11, 16, + 18, 12, 16, 18, 19, 12, 16, 19, + 12, 16, 19, 19, 19, 12, 16, 19, + 12, 16, 19, 19, 12, 16, 18, 12, + 16, 19, 12, 17, 19, 12, 17, 19, + 12, 17, 19, 12, 17, 19, 13, 17, + 13, 17, 13, 17, 19, 19, 13, 17, + 13, 17, 19, 13, 17, 13, 18, 19, + 13, 17, 19, 13, 18, 13, 17, 13, + 18, 13, 18, 13, 18, 13, 18, 13, + 18, 13, 18, 14, 18, 19, 14, 18, + 14, 18, 14, 18, 14, 18, 14, 19, + 14, 19, 14, 18, 14, 18, 14, 18, + 14, 19, 14, 14, 18, 14, 14, 19, + 14, 18, 14, 19, 14, 19, 14, 15, + 19, 15, 15, 15, 15, 19, 15, 19, + 15, 15, 19, 15, 15, 19, 15, 19, + 15, 19, 15, 19, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 16, + 15, 15, 15, 16, 16, 16, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 17, 16, 16, 16, 17, + 17, 16, 17, 17, 16, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 18, + 17, 17, 17, 17, 17, 17, 17, 17, + 18, 17, 17, 18, 17, 17, 17, 17, + 18, 18, 17, 17, 17, 17, 17, 17, + 17, 18, 17, 18, 18, 17, 17, 17, + 18, 18, 18, 17, 18, 17, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 17, + 18, 18, 18, 18, 19, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 19, + 18, 18, 19, 18, 18, 18, 19, 18, + 19, 18, 18, 19, 18, 18, 19, 19, + 19, 19, 19, 18, 19, 18, 19, 18, + 19, 19, 18, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 18, 19, + 19, 19, 19, 19, 18, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 20, + 19, 19, 19, 19, 21, 19, 19, 20, + 19, 20, 19, 19, 19, 19, 19, 20, + 20, 20, 19, 19, 19, 20, 19, 19, + 19, 20, 20, 19, 20, 19, 19, 21, + 20, 20, 19, 19, 19, 19, 19, 19, + 20, 19, 20, 20, 20, 20, 20, 20, + 20, 19, 19, 21, 20, 20, 19, 19, +}; + +static const uint32_t coef3_huffcodes[1072] = { + 0x001b2, 0x00069, 0x00000, 0x00004, 0x00006, 0x0000e, 0x00014, 0x00019, + 0x00016, 0x0002b, 0x00030, 0x0003d, 0x0003c, 0x0005a, 0x0005f, 0x0006d, + 0x0007e, 0x0005f, 0x0007f, 0x000b6, 0x000bc, 0x000d8, 0x000f2, 0x000fe, + 0x000bc, 0x000fc, 0x00161, 0x0016e, 0x00174, 0x00176, 0x001a2, 0x001e3, + 0x001f3, 0x00174, 0x0017a, 0x001ea, 0x002a8, 0x002c4, 0x002e6, 0x00314, + 0x00346, 0x00367, 0x003e9, 0x002e5, 0x002ee, 0x003d6, 0x00555, 0x00554, + 0x00557, 0x005c3, 0x005d6, 0x006e0, 0x0062f, 0x006e2, 0x00799, 0x00789, + 0x007fa, 0x005ce, 0x007fe, 0x005ec, 0x007cc, 0x007af, 0x00aa7, 0x00b19, + 0x00b94, 0x00b85, 0x00b9f, 0x00c48, 0x00c45, 0x00dd8, 0x00c4c, 0x00c4b, + 0x00d99, 0x00d1f, 0x00dc2, 0x00f95, 0x00fa2, 0x00bb5, 0x00b9f, 0x00f5d, + 0x00bbf, 0x00f47, 0x0154a, 0x00fd5, 0x00f45, 0x00f7f, 0x0160d, 0x01889, + 0x01757, 0x01722, 0x018b3, 0x0172d, 0x01a39, 0x01a18, 0x01bb3, 0x01b30, + 0x01e63, 0x0173c, 0x01b35, 0x01723, 0x01e80, 0x01fee, 0x01761, 0x01ffc, + 0x01f7f, 0x02c7c, 0x01fa1, 0x0177b, 0x01755, 0x0175a, 0x01fa6, 0x02eab, + 0x0310a, 0x02c69, 0x03669, 0x03127, 0x03103, 0x02e43, 0x03662, 0x03165, + 0x03124, 0x0313b, 0x03111, 0x03668, 0x0343b, 0x03c52, 0x03efc, 0x02e6c, + 0x03fda, 0x03ef8, 0x02e7b, 0x03ee2, 0x03cc5, 0x03d72, 0x058c0, 0x03df8, + 0x02ea9, 0x03e7e, 0x0556d, 0x05c82, 0x03d71, 0x03e7b, 0x03c42, 0x058d7, + 0x03f4e, 0x06200, 0x03d70, 0x05cb2, 0x05c96, 0x05cb0, 0x03f45, 0x05cb1, + 0x02e6d, 0x03110, 0x02f68, 0x05c90, 0x07ca6, 0x07c88, 0x06204, 0x062c8, + 0x078a6, 0x07986, 0x079d5, 0x0b1ad, 0x07989, 0x0b079, 0x05cdd, 0x0aad4, + 0x05de8, 0x07dcd, 0x07987, 0x05d67, 0x05d99, 0x0b91d, 0x07cf1, 0x05d9b, + 0x079d7, 0x0b07b, 0x05c85, 0x05d9a, 0x07dcc, 0x07ebf, 0x07dce, 0x07dfb, + 0x07ec0, 0x07d1a, 0x07a07, 0x05c84, 0x0c471, 0x07cf2, 0x0baef, 0x0b9d2, + 0x05deb, 0x07bd6, 0x0b845, 0x05d98, 0x0b91a, 0x0bae8, 0x0c4e0, 0x0dc31, + 0x0f93d, 0x0bbce, 0x0d1d2, 0x0f7a9, 0x0d9b9, 0x0bbcb, 0x0b900, 0x0aad7, + 0x0babd, 0x0c4e1, 0x0f46f, 0x0c588, 0x0c58b, 0x160e6, 0x0bbcf, 0x0bac3, + 0x0f945, 0x0f7a3, 0x0d1c1, 0x0fb8e, 0x0f7a4, 0x0fb8c, 0x0f40c, 0x0c473, + 0x0fd72, 0x0bbcd, 0x0fffa, 0x0f940, 0x0bbc9, 0x0f7a8, 0x1a1ed, 0x0bbc5, + 0x1f26f, 0x163fd, 0x160c7, 0x1a1f5, 0x0f947, 0x163fc, 0x154b3, 0x0fff6, + 0x163f6, 0x160e9, 0x1a1f0, 0x0bab9, 0x0baba, 0x17086, 0x0b903, 0x0fd75, + 0x0f308, 0x176f3, 0x163ff, 0x0fd7d, 0x1bb78, 0x163fb, 0x188db, 0x1a1f7, + 0x154b2, 0x172fd, 0x163f4, 0x1bb73, 0x172ff, 0x0babc, 0x0f97d, 0x1a1f3, + 0x1bb6d, 0x1ffd5, 0x1a1f4, 0x1f272, 0x17380, 0x17382, 0x1ffe7, 0x0bac8, + 0x0bbc4, 0x188d3, 0x160e0, 0x0fd7b, 0x1725f, 0x172f5, 0x1bb79, 0x1fad9, + 0x1f269, 0x188d0, 0x0bac4, 0x0bac5, 0x31185, 0x188d2, 0x188cc, 0x31187, + 0x3e7fe, 0x188d1, 0x1bb6c, 0x1f268, 0x1fad2, 0x1ffd9, 0x1a1ea, 0x1bb68, + 0x1facb, 0x3fdb2, 0x1e81a, 0x188ce, 0x172fb, 0x1a1ef, 0x1face, 0x1bb70, + 0x0bac1, 0x1bb6b, 0x172f8, 0x1bb66, 0x1ffdf, 0x1bb6a, 0x1ffd7, 0x1f266, + 0x176f8, 0x37653, 0x1fa7e, 0x31182, 0x1fac8, 0x2c7e3, 0x370ee, 0x176ec, + 0x176e9, 0x2e4bc, 0x160c5, 0x3765a, 0x3ce9c, 0x17373, 0x176e8, 0x188d4, + 0x176f1, 0x176ef, 0x37659, 0x1bb7c, 0x1ffde, 0x176f2, 0x3118b, 0x2c7d4, + 0x37651, 0x5ce9f, 0x37650, 0x31191, 0x3f4f6, 0x3f4f5, 0x7a06c, 0x1fac1, + 0x5c97b, 0x2c7e0, 0x79d3a, 0x3e7fd, 0x2c7df, 0x3f4f0, 0x7a06d, 0x376c1, + 0x79d3b, 0x00004, 0x00014, 0x00059, 0x000ab, 0x000b8, 0x00177, 0x001f5, + 0x001f2, 0x00315, 0x003fc, 0x005bd, 0x0062d, 0x006e8, 0x007dd, 0x00b04, + 0x007cd, 0x00b1e, 0x00d1e, 0x00f15, 0x00f3b, 0x00f41, 0x01548, 0x018b0, + 0x0173b, 0x01884, 0x01a1c, 0x01bb4, 0x01f25, 0x017b5, 0x0176d, 0x01ef8, + 0x02e73, 0x03107, 0x03125, 0x03105, 0x02e49, 0x03ce8, 0x03ef9, 0x03e5e, + 0x02e72, 0x03471, 0x03fd9, 0x0623f, 0x078a0, 0x06867, 0x05cb3, 0x06272, + 0x068ec, 0x06e9a, 0x079d4, 0x06e98, 0x0b1aa, 0x06e1a, 0x07985, 0x068ee, + 0x06e9b, 0x05c88, 0x0b1ac, 0x07dfa, 0x05d65, 0x07cf0, 0x07cbf, 0x0c475, + 0x160eb, 0x1bb7e, 0x0f7a6, 0x1fedd, 0x160e3, 0x0fffb, 0x0fb8d, 0x0fff9, + 0x0d1c0, 0x0c58c, 0x1a1e9, 0x0bab8, 0x0f5cf, 0x0fff5, 0x376c5, 0x1a1ec, + 0x160ed, 0x1fede, 0x1fac9, 0x1a1eb, 0x1f224, 0x176ee, 0x0fd79, 0x17080, + 0x17387, 0x1bb7a, 0x1ffe9, 0x176f7, 0x17385, 0x17781, 0x2c7d5, 0x17785, + 0x1ffe3, 0x163f5, 0x1fac2, 0x3e7f9, 0x3118d, 0x3fdb1, 0x1ffe2, 0x1f226, + 0x3118a, 0x2c7d9, 0x31190, 0x3118c, 0x3f4f3, 0x1bb7f, 0x1bb72, 0x31184, + 0xb92f4, 0x3e7fb, 0x6e1d9, 0x1faca, 0x62300, 0x3fdb8, 0x3d037, 0x3e7fc, + 0x62301, 0x3f4f2, 0x1f26a, 0x0000e, 0x00063, 0x000f8, 0x001ee, 0x00377, + 0x003f7, 0x006e3, 0x005cc, 0x00b05, 0x00dd2, 0x00fd4, 0x0172e, 0x0172a, + 0x01e23, 0x01f2d, 0x01763, 0x01769, 0x0176c, 0x02e75, 0x03104, 0x02ec1, + 0x03e58, 0x0583f, 0x03f62, 0x03f44, 0x058c5, 0x0623c, 0x05cf4, 0x07bd7, + 0x05d9d, 0x0aad2, 0x05d66, 0x0b1a9, 0x0b078, 0x07cfe, 0x0b918, 0x0c46f, + 0x0b919, 0x0b847, 0x06e1b, 0x0b84b, 0x0aad8, 0x0fd74, 0x172f4, 0x17081, + 0x0f97c, 0x1f273, 0x0f7a0, 0x0fd7c, 0x172f7, 0x0fd7a, 0x1bb77, 0x172fe, + 0x1f270, 0x0fd73, 0x1bb7b, 0x1a1bc, 0x1bb7d, 0x0bbc3, 0x172f6, 0x0baeb, + 0x0fb8f, 0x3f4f4, 0x3fdb4, 0x376c8, 0x3e7fa, 0x1ffd0, 0x62303, 0xb92f5, + 0x1f261, 0x31189, 0x3fdb5, 0x2c7db, 0x376c9, 0x1fad6, 0x1fad1, 0x00015, + 0x000f0, 0x002e0, 0x0058e, 0x005d7, 0x00c4d, 0x00fa1, 0x00bdb, 0x01756, + 0x01f70, 0x02c19, 0x0313c, 0x0370f, 0x03cc0, 0x02ea8, 0x058c6, 0x058c7, + 0x02eb7, 0x058d0, 0x07d18, 0x0aa58, 0x0b848, 0x05d9e, 0x05d6c, 0x0b84c, + 0x0c589, 0x0b901, 0x163f8, 0x0bac9, 0x0b9c5, 0x0f93c, 0x188d8, 0x0bbc7, + 0x160ec, 0x0fd6f, 0x188d9, 0x160ea, 0x0f7a7, 0x0f944, 0x0baab, 0x0dc3a, + 0x188cf, 0x176fb, 0x2c7d8, 0x2c7d7, 0x1bb75, 0x5ce9e, 0x62302, 0x370ed, + 0x176f4, 0x1ffd1, 0x370ef, 0x3f4f8, 0x376c7, 0x1ffe1, 0x376c6, 0x176ff, + 0x6e1d8, 0x176f6, 0x17087, 0x0f5cd, 0x00035, 0x001a0, 0x0058b, 0x00aac, + 0x00b9a, 0x0175f, 0x01e22, 0x01e8c, 0x01fb2, 0x0310b, 0x058d1, 0x0552e, + 0x05c27, 0x0686e, 0x07ca7, 0x0c474, 0x0dc33, 0x07bf2, 0x05de9, 0x07a35, + 0x0baaa, 0x0b9eb, 0x0fb95, 0x0b9b8, 0x17381, 0x1f262, 0x188cd, 0x17088, + 0x172fa, 0x0f7a2, 0x1fad3, 0x0bac0, 0x3765c, 0x1fedf, 0x1f225, 0x1fad4, + 0x2c7da, 0x5ce9d, 0x3e7f8, 0x1e203, 0x188d7, 0x00054, 0x002c0, 0x007a1, + 0x00f78, 0x01b36, 0x01fa3, 0x0313a, 0x03436, 0x0343a, 0x07d1d, 0x07bd8, + 0x05cdf, 0x0b846, 0x0b189, 0x0d9b8, 0x0fff8, 0x0d9be, 0x0c58a, 0x05dea, + 0x0d1d3, 0x160e4, 0x1f26b, 0x188da, 0x1e202, 0x2c7d2, 0x163fe, 0x31193, + 0x17782, 0x376c2, 0x2c7d1, 0x3fdb0, 0x3765d, 0x2c7d0, 0x1fad0, 0x1e201, + 0x188dd, 0x2c7e2, 0x37657, 0x37655, 0x376c4, 0x376c0, 0x176ea, 0x0006f, + 0x003cf, 0x00dd5, 0x01f23, 0x02c61, 0x02ed0, 0x05d54, 0x0552d, 0x07883, + 0x0b1a8, 0x0b91c, 0x0babf, 0x0b902, 0x0f7aa, 0x0f7a5, 0x1a1e8, 0x1ffd6, + 0x0babe, 0x1a1bf, 0x163f3, 0x1ffd8, 0x1fad7, 0x1f275, 0x1ffdc, 0x0007d, + 0x005bc, 0x01549, 0x02a99, 0x03def, 0x06273, 0x079d6, 0x07d1b, 0x0aad3, + 0x0d0fc, 0x2c7dd, 0x188d6, 0x0bac2, 0x2c7e1, 0x1bb76, 0x1a1bd, 0x31186, + 0x0fd78, 0x1a1be, 0x31183, 0x3fdb6, 0x3f4f1, 0x37652, 0x1fad5, 0x3f4f9, + 0x3e7ff, 0x5ce9c, 0x3765b, 0x31188, 0x17372, 0x000bd, 0x0078b, 0x01f21, + 0x03c43, 0x03ded, 0x0aad6, 0x07ec1, 0x0f942, 0x05c86, 0x17089, 0x0babb, + 0x1ffe8, 0x2c7de, 0x1f26e, 0x1fac4, 0x3f4f7, 0x37656, 0x1fa7d, 0x376c3, + 0x3fdb3, 0x3118f, 0x1fac6, 0x000f8, 0x007ed, 0x01efd, 0x03e7a, 0x05c91, + 0x0aad9, 0x0baec, 0x0dc32, 0x0f46e, 0x1e200, 0x176fa, 0x3765e, 0x3fdb7, + 0x2c7d6, 0x3fdb9, 0x37654, 0x37658, 0x3118e, 0x1ffdb, 0x000f6, 0x00c43, + 0x03106, 0x068ef, 0x0b84d, 0x0b188, 0x0bbcc, 0x1f264, 0x1bb69, 0x17386, + 0x1fac0, 0x00171, 0x00f39, 0x03e41, 0x068ed, 0x0d9bc, 0x0f7a1, 0x1bb67, + 0x1ffdd, 0x176f9, 0x001b9, 0x00f7d, 0x03f63, 0x0d0fd, 0x0b9ea, 0x188dc, + 0x1fac3, 0x1a1f2, 0x31192, 0x1ffe4, 0x001f6, 0x01754, 0x06865, 0x0f309, + 0x160e5, 0x176f5, 0x3765f, 0x1facc, 0x001e9, 0x01a1a, 0x06201, 0x0f105, + 0x176f0, 0x002df, 0x01756, 0x05d6d, 0x163fa, 0x176ed, 0x00342, 0x02e40, + 0x0d0ff, 0x17082, 0x003cd, 0x02a98, 0x0fffc, 0x2c7dc, 0x1fa7f, 0x003fe, + 0x03764, 0x0fffd, 0x176fc, 0x1fac5, 0x002f7, 0x02ed1, 0x0fb97, 0x0058a, + 0x02edc, 0x0bbc8, 0x005d4, 0x0623d, 0x160e8, 0x0062e, 0x05830, 0x163f9, + 0x006eb, 0x06205, 0x1f274, 0x007de, 0x062c9, 0x1f265, 0x005c9, 0x05cde, + 0x1ffd3, 0x005d4, 0x07988, 0x007ce, 0x0b849, 0x00b1b, 0x05c89, 0x1fac7, + 0x00b93, 0x05c83, 0x00b9e, 0x0f14f, 0x00c4a, 0x0b9c7, 0x00dd4, 0x0c470, + 0x1f271, 0x00f38, 0x0fb96, 0x176eb, 0x00fa0, 0x163f7, 0x00bb2, 0x0b91b, + 0x00bbe, 0x0f102, 0x00f44, 0x0f946, 0x1facd, 0x00f79, 0x0d9bd, 0x0154d, + 0x0bbc6, 0x00fd2, 0x160e7, 0x0172b, 0x188cb, 0x0175e, 0x0fd76, 0x0175c, + 0x1bb71, 0x0189f, 0x1a1ee, 0x01f24, 0x1a1f6, 0x01ba7, 0x0bbca, 0x01f7d, + 0x0ffff, 0x01f2e, 0x1bb65, 0x01bb5, 0x172f9, 0x01fef, 0x1f26c, 0x01f3e, + 0x0fd77, 0x01762, 0x1bb6e, 0x01ef9, 0x172fc, 0x01fa0, 0x02ab7, 0x02e4a, + 0x1f267, 0x01fb3, 0x1ffda, 0x02e42, 0x03101, 0x17780, 0x0313d, 0x03475, + 0x17784, 0x03126, 0x1facf, 0x03c51, 0x17783, 0x03e40, 0x1ffe5, 0x03663, + 0x1ffe0, 0x03e8f, 0x1f26d, 0x0343c, 0x03cc1, 0x176fd, 0x03e45, 0x02ec0, + 0x03f61, 0x03dee, 0x03fd8, 0x0583e, 0x02e45, 0x03e59, 0x03d02, 0x05ce8, + 0x05568, 0x176fe, 0x02f69, 0x1fad8, 0x058c1, 0x05c83, 0x1ffe6, 0x06271, + 0x06e1c, 0x062c7, 0x068e1, 0x0552f, 0x06864, 0x06866, 0x06e99, 0x05cbc, + 0x07ca5, 0x078a1, 0x05c82, 0x07dcf, 0x0623b, 0x0623e, 0x068e8, 0x07a36, + 0x05d9c, 0x0b077, 0x07cf3, 0x07a34, 0x07ca4, 0x07d19, 0x079d2, 0x07d1c, + 0x07bd9, 0x0b84a, 0x0fb94, 0x0aad5, 0x0dc30, 0x07bf3, 0x0baee, 0x0b07a, + 0x0c472, 0x0b91e, 0x0d9ba, 0x05d9f, 0x0d0fe, 0x0b9c6, 0x05c87, 0x0f14e, + 0x0baed, 0x0b92e, 0x0f103, 0x0b9c4, 0x0fb91, 0x0d9bb, 0x0b1ab, 0x0c58d, + 0x0fffe, 0x0f93b, 0x0f941, 0x0baea, 0x0b91f, 0x0f5cc, 0x0d9bf, 0x0f943, + 0x0f104, 0x1f260, 0x0fb92, 0x0f93f, 0x0f3a6, 0x0bac7, 0x0f7ab, 0x0bac6, + 0x17383, 0x0fd6d, 0x0bae9, 0x0fd6e, 0x1e74f, 0x188ca, 0x1f227, 0x0fb93, + 0x0fb90, 0x0fff7, 0x17085, 0x17083, 0x160e1, 0x17084, 0x0f93e, 0x160e2, + 0x160c6, 0x1a1f1, 0x1bb6f, 0x17384, 0x0fd70, 0x1f263, 0x188d5, 0x173a6, + 0x0f5ce, 0x163f2, 0x0fd71, 0x1ffd2, 0x160c4, 0x1ffd4, 0x2c7d3, 0x1bb74, +}; + +static const uint8_t coef3_huffbits[1072] = { + 9, 7, 2, 3, 4, 4, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 12, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, + 13, 14, 13, 14, 14, 13, 14, 13, + 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, + 14, 14, 15, 14, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 14, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 16, 15, 16, 16, 16, + 16, 15, 15, 16, 16, 16, 16, 16, + 15, 16, 16, 16, 15, 16, 15, 15, + 16, 15, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 17, 16, 17, 16, 17, 17, 16, + 17, 16, 17, 16, 16, 17, 17, 17, + 16, 17, 16, 16, 17, 16, 17, 16, + 17, 17, 16, 16, 17, 17, 17, 17, + 17, 17, 17, 17, 16, 17, 17, 16, + 17, 17, 17, 17, 17, 17, 17, 17, + 16, 18, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 16, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 18, + 17, 17, 17, 17, 18, 17, 17, 18, + 19, 17, 17, 17, 18, 17, 17, 17, + 18, 18, 18, 17, 17, 17, 18, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 17, 18, 18, 18, 18, 17, + 18, 18, 18, 17, 17, 18, 18, 18, + 18, 19, 18, 18, 19, 19, 20, 18, + 19, 18, 19, 19, 18, 19, 20, 18, + 19, 4, 6, 7, 8, 9, 9, 9, + 10, 10, 10, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 16, 15, 15, 15, + 15, 16, 16, 15, 16, 16, 15, 16, + 17, 17, 17, 17, 17, 16, 16, 16, + 16, 16, 17, 17, 17, 16, 18, 17, + 17, 17, 18, 17, 17, 18, 17, 17, + 17, 17, 17, 18, 17, 18, 18, 18, + 17, 17, 18, 19, 18, 18, 17, 17, + 18, 18, 18, 18, 19, 17, 17, 18, + 20, 19, 19, 18, 19, 18, 19, 19, + 19, 19, 17, 5, 7, 9, 10, 10, + 11, 11, 12, 12, 12, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 15, + 14, 15, 15, 15, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 15, 16, 16, 17, 17, 17, + 16, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 16, + 16, 19, 18, 18, 19, 17, 19, 20, + 17, 18, 18, 18, 18, 18, 18, 6, + 8, 10, 11, 12, 12, 12, 13, 13, + 13, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, + 16, 17, 17, 17, 16, 16, 17, 17, + 17, 17, 17, 17, 17, 16, 16, 16, + 17, 18, 18, 18, 17, 19, 19, 18, + 18, 17, 18, 19, 18, 17, 18, 18, + 19, 18, 17, 17, 6, 9, 11, 12, + 13, 13, 13, 14, 14, 14, 15, 15, + 15, 15, 15, 16, 16, 16, 16, 16, + 16, 17, 16, 17, 17, 17, 17, 17, + 17, 17, 18, 17, 18, 17, 17, 18, + 18, 19, 19, 17, 17, 7, 10, 12, + 13, 13, 14, 14, 14, 14, 15, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 17, 17, 17, 17, 18, 17, 18, + 18, 18, 18, 18, 18, 18, 18, 17, + 17, 18, 18, 18, 18, 18, 18, 7, + 10, 12, 13, 14, 15, 15, 15, 15, + 16, 16, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 18, 17, 17, 8, + 11, 13, 14, 15, 15, 15, 15, 16, + 16, 18, 17, 17, 18, 17, 17, 18, + 17, 17, 18, 18, 19, 18, 18, 19, + 19, 19, 18, 18, 18, 8, 11, 13, + 14, 15, 16, 16, 16, 16, 17, 17, + 17, 18, 17, 18, 19, 18, 18, 18, + 18, 18, 18, 8, 12, 14, 15, 15, + 16, 16, 16, 17, 17, 18, 18, 18, + 18, 18, 18, 18, 18, 17, 9, 12, + 14, 15, 16, 16, 17, 17, 17, 17, + 18, 9, 12, 14, 15, 16, 17, 17, + 17, 18, 9, 13, 15, 16, 17, 17, + 18, 17, 18, 17, 9, 13, 15, 16, + 17, 18, 18, 18, 10, 13, 15, 16, + 18, 10, 14, 16, 17, 18, 10, 14, + 16, 17, 10, 14, 16, 18, 18, 10, + 14, 16, 18, 18, 11, 15, 16, 11, + 15, 17, 11, 15, 17, 11, 15, 17, + 11, 15, 17, 11, 15, 17, 12, 16, + 17, 12, 15, 12, 16, 12, 16, 18, + 12, 16, 12, 16, 12, 16, 12, 16, + 17, 12, 16, 18, 12, 17, 13, 16, + 13, 16, 13, 16, 18, 13, 16, 13, + 17, 13, 17, 13, 17, 13, 17, 13, + 17, 13, 17, 13, 17, 13, 17, 13, + 16, 13, 17, 13, 17, 13, 17, 14, + 17, 14, 17, 14, 17, 14, 14, 14, + 17, 14, 17, 14, 14, 18, 14, 14, + 18, 14, 18, 14, 18, 14, 17, 14, + 17, 14, 17, 14, 14, 18, 14, 15, + 15, 15, 14, 15, 15, 14, 15, 15, + 15, 18, 15, 18, 15, 15, 17, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 15, 15, 15, 15, 16, + 16, 16, 16, 16, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 16, 16, + 16, 17, 16, 16, 16, 17, 17, 17, + 17, 17, 16, 17, 17, 17, 17, 16, + 16, 16, 17, 17, 17, 17, 16, 17, + 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 18, 17, +}; + +static const uint32_t coef4_huffcodes[476] = { + 0x00f01, 0x0001e, 0x00000, 0x00004, 0x00006, 0x0000d, 0x0000a, 0x00017, + 0x0001d, 0x00017, 0x0002c, 0x00031, 0x00039, 0x0003e, 0x00039, 0x0005a, + 0x00066, 0x00070, 0x0007b, 0x00070, 0x00077, 0x000af, 0x000c9, 0x000f2, + 0x000f4, 0x000b2, 0x000e3, 0x0015b, 0x0015d, 0x00181, 0x0019d, 0x001e3, + 0x001c5, 0x002b5, 0x002db, 0x00338, 0x003c3, 0x003cc, 0x003f0, 0x002cd, + 0x003fa, 0x003a1, 0x005b4, 0x00657, 0x007ab, 0x0074d, 0x0074c, 0x00ac1, + 0x00ac5, 0x0076b, 0x00ca8, 0x00f04, 0x00f00, 0x00fe3, 0x00f3c, 0x00f10, + 0x00f39, 0x00fe6, 0x00e26, 0x00e90, 0x016c5, 0x01827, 0x01954, 0x015c5, + 0x01958, 0x01f8a, 0x01c4a, 0x02b0f, 0x02b41, 0x02b0e, 0x033c6, 0x03050, + 0x01c4f, 0x02d88, 0x0305c, 0x03c18, 0x02b4f, 0x02cc2, 0x03a47, 0x05680, + 0x0569d, 0x06442, 0x06443, 0x06446, 0x0656e, 0x06444, 0x07120, 0x0748a, + 0x0c1ba, 0x07e22, 0x07aa6, 0x07f25, 0x07aa7, 0x07e20, 0x0c11b, 0x0c118, + 0x07aa5, 0x0ad0a, 0x0f389, 0x19ebb, 0x0caad, 0x0fe42, 0x0fe40, 0x16c34, + 0x2b4e5, 0x33d65, 0x16c30, 0x1e7ae, 0x1e25c, 0x18370, 0x1e703, 0x19eba, + 0x16c37, 0x0e234, 0x16c6e, 0x00004, 0x0002a, 0x00061, 0x00075, 0x000cb, + 0x000ff, 0x00190, 0x001eb, 0x001d1, 0x002b9, 0x00307, 0x00339, 0x0033f, + 0x003fb, 0x003b4, 0x0060c, 0x00679, 0x00645, 0x0067d, 0x0078a, 0x007e3, + 0x00749, 0x00ac4, 0x00ad2, 0x00ae3, 0x00c10, 0x00c16, 0x00ad1, 0x00cf4, + 0x00fe2, 0x01586, 0x00e9d, 0x019f1, 0x01664, 0x01e26, 0x01d38, 0x02b4d, + 0x033c5, 0x01fc2, 0x01fc3, 0x01d28, 0x03c1d, 0x0598e, 0x0f094, 0x07aa4, + 0x0ad38, 0x0ac0c, 0x0c11a, 0x079ea, 0x0c881, 0x0fe44, 0x0b635, 0x0ac0d, + 0x0b61e, 0x05987, 0x07121, 0x0f382, 0x0f387, 0x0e237, 0x0fe47, 0x0f383, + 0x0f091, 0x0f385, 0x0e233, 0x182ee, 0x19eb8, 0x1663e, 0x0f093, 0x00014, + 0x00058, 0x00159, 0x00167, 0x00300, 0x003d4, 0x005b5, 0x0079d, 0x0076a, + 0x00b67, 0x00b60, 0x00f05, 0x00cf0, 0x00f17, 0x00e95, 0x01822, 0x01913, + 0x016c2, 0x0182f, 0x01959, 0x01fcb, 0x01e27, 0x01c40, 0x033c7, 0x01e7b, + 0x01c49, 0x02d89, 0x01e23, 0x01660, 0x03f12, 0x02cc6, 0x033e1, 0x05b34, + 0x0609a, 0x06569, 0x07488, 0x07e21, 0x0cf5f, 0x0712c, 0x0389d, 0x067cf, + 0x07f28, 0x1663f, 0x33d67, 0x1663d, 0x1e25d, 0x3c1ab, 0x15c44, 0x16c36, + 0x0001f, 0x000ec, 0x00323, 0x005b2, 0x0079f, 0x00ac2, 0x00f16, 0x00e9e, + 0x01956, 0x01e0f, 0x019ea, 0x01666, 0x02b89, 0x02b02, 0x02d8c, 0x03c1b, + 0x03c19, 0x032b5, 0x03f9c, 0x02ccf, 0x03897, 0x05b35, 0x0ad02, 0x07f29, + 0x06441, 0x03884, 0x07888, 0x0784e, 0x06568, 0x0c1bb, 0x05986, 0x067cc, + 0x0fe49, 0x0fe48, 0x0c1bc, 0x0fe41, 0x18371, 0x1663c, 0x0e231, 0x0711e, + 0x0ad09, 0x0f092, 0x0002d, 0x001db, 0x00781, 0x00c1a, 0x00f55, 0x01580, + 0x01ea8, 0x02d9b, 0x032af, 0x03f16, 0x03c1c, 0x07834, 0x03c45, 0x0389c, + 0x067ce, 0x06445, 0x0c1b9, 0x07889, 0x07f3a, 0x0784f, 0x07f2b, 0x0ad0b, + 0x0f090, 0x0c11d, 0x0e94e, 0x0711f, 0x0e9f1, 0x0f38e, 0x079e9, 0x0ad03, + 0x0f09b, 0x0caae, 0x0fe46, 0x2b4e6, 0x0e9f0, 0x19eb6, 0x67ac1, 0x67ac0, + 0x33d66, 0x0f388, 0x00071, 0x003a0, 0x00ca9, 0x01829, 0x01d39, 0x02b43, + 0x02cc4, 0x06554, 0x0f09a, 0x0b61f, 0x067cd, 0x0711c, 0x0b636, 0x07f2a, + 0x0b634, 0x0c11f, 0x0cf5e, 0x0b61d, 0x0f06b, 0x0caab, 0x0c1be, 0x0e94c, + 0x0f099, 0x182ed, 0x0e94f, 0x0c119, 0x0e232, 0x2b4e4, 0x0f38a, 0x19eb4, + 0x1e25f, 0x0e94d, 0x000b7, 0x00785, 0x016cc, 0x03051, 0x033c4, 0x0656f, + 0x03891, 0x0711d, 0x0caaf, 0x0f097, 0x07489, 0x0f098, 0x0c880, 0x0caaa, + 0x0f386, 0x19eb7, 0x16c6f, 0x0f384, 0x182e8, 0x182e9, 0x0e230, 0x1e700, + 0x33d62, 0x33d63, 0x33d64, 0x16c33, 0x0e216, 0x000fd, 0x00c15, 0x01665, + 0x03c4a, 0x07f3b, 0x07896, 0x0c11c, 0x0e215, 0x16c32, 0x0f38b, 0x0f38d, + 0x182ea, 0x1e701, 0x712df, 0x15c46, 0x00194, 0x00fe0, 0x03f13, 0x0748b, + 0x0f096, 0x0cf80, 0x1e25e, 0xe25bd, 0x33d61, 0x16c31, 0x001f9, 0x01912, + 0x05710, 0x0f3d0, 0x0c1bf, 0x00301, 0x01e24, 0x0ad08, 0x003cd, 0x01c41, + 0x0c1bd, 0x00563, 0x03a52, 0x0f3d1, 0x00570, 0x02cce, 0x0e217, 0x0067b, + 0x0655d, 0x0074b, 0x06447, 0x00c12, 0x074fb, 0x00f08, 0x0b61c, 0x00e22, + 0x0fe43, 0x016c7, 0x01836, 0x019f2, 0x01c43, 0x01d3f, 0x01fcf, 0x02b4c, + 0x0304c, 0x032b6, 0x03a46, 0x05607, 0x03f17, 0x02cc5, 0x0609b, 0x0655c, + 0x07e23, 0x067c1, 0x07f26, 0x07f27, 0x0f095, 0x0e9f3, 0x0cf81, 0x0c11e, + 0x0caac, 0x0f38f, 0x0e9f2, 0x074fa, 0x0e236, 0x0fe45, 0x1c428, 0x0e235, + 0x182ef, 0x19eb5, 0x0f3d6, 0x182ec, 0x16c35, 0x0f38c, 0x2b4e7, 0x15c47, + 0xe25bc, 0x1e702, 0x1c4b6, 0x0e25a, 0x3c1aa, 0x15c45, 0x1c429, 0x19eb9, + 0x1e7af, 0x182eb, 0x1e0d4, 0x3896e, +}; + +static const uint8_t coef4_huffbits[476] = { + 12, 6, 2, 3, 4, 4, 5, 5, + 5, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 11, + 10, 11, 11, 11, 11, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 16, 16, + 16, 15, 15, 15, 15, 15, 16, 16, + 15, 16, 16, 17, 16, 16, 16, 17, + 18, 18, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 4, 6, 7, 8, 8, + 8, 9, 9, 10, 10, 10, 10, 10, + 10, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 13, 13, 13, 14, 13, 14, 14, + 14, 13, 13, 14, 14, 16, 16, 15, + 16, 16, 16, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 16, 16, + 16, 16, 17, 17, 17, 18, 16, 5, + 8, 9, 10, 10, 10, 11, 11, 12, + 12, 12, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 14, 14, 13, + 14, 14, 13, 14, 14, 15, 14, 15, + 15, 15, 16, 15, 16, 16, 15, 15, + 15, 18, 18, 18, 17, 18, 17, 17, + 6, 9, 10, 11, 11, 12, 12, 13, + 13, 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 16, 15, + 15, 15, 15, 15, 15, 16, 16, 15, + 16, 16, 16, 16, 17, 18, 17, 16, + 16, 16, 7, 10, 11, 12, 12, 13, + 13, 14, 14, 14, 14, 15, 14, 15, + 15, 15, 16, 15, 15, 15, 15, 16, + 16, 16, 17, 16, 17, 16, 15, 16, + 16, 16, 16, 18, 17, 17, 19, 19, + 18, 16, 7, 11, 12, 13, 14, 14, + 15, 15, 16, 16, 15, 16, 16, 15, + 16, 16, 16, 16, 16, 16, 16, 17, + 16, 17, 17, 16, 17, 18, 16, 17, + 17, 17, 8, 11, 13, 14, 14, 15, + 15, 16, 16, 16, 16, 16, 16, 16, + 16, 17, 17, 16, 17, 17, 17, 17, + 18, 18, 18, 17, 17, 8, 12, 14, + 14, 15, 15, 16, 17, 17, 16, 16, + 17, 17, 20, 17, 9, 12, 14, 16, + 16, 16, 17, 21, 18, 17, 9, 13, + 15, 16, 16, 10, 13, 16, 10, 14, + 16, 11, 15, 16, 11, 15, 17, 11, + 15, 12, 15, 12, 16, 12, 16, 13, + 16, 13, 13, 13, 14, 14, 13, 14, + 14, 14, 15, 15, 14, 15, 15, 15, + 15, 15, 15, 15, 16, 17, 16, 16, + 16, 16, 17, 16, 17, 16, 18, 17, + 17, 17, 16, 17, 17, 16, 18, 17, + 21, 17, 18, 17, 18, 17, 18, 17, + 17, 17, 17, 19, +}; + +static const uint32_t coef5_huffcodes[435] = { + 0x00347, 0x0000b, 0x00001, 0x00001, 0x0000c, 0x00004, 0x00010, 0x00015, + 0x0001f, 0x0000b, 0x00023, 0x00026, 0x00029, 0x00035, 0x00037, 0x00001, + 0x00015, 0x0001a, 0x0001d, 0x0001c, 0x0001e, 0x0004e, 0x00049, 0x00051, + 0x00078, 0x00004, 0x00000, 0x00008, 0x0000d, 0x0007b, 0x00005, 0x00032, + 0x00095, 0x00091, 0x00096, 0x000a1, 0x000d9, 0x00003, 0x00019, 0x00061, + 0x00066, 0x00060, 0x00017, 0x0000e, 0x00063, 0x001a0, 0x001b7, 0x001e6, + 0x001e7, 0x001b6, 0x00018, 0x001e8, 0x00038, 0x00031, 0x00005, 0x0003d, + 0x00027, 0x001ea, 0x0001a, 0x000c5, 0x000f9, 0x000ff, 0x000db, 0x00250, + 0x000fc, 0x0025c, 0x00008, 0x00075, 0x003d7, 0x003d3, 0x001b0, 0x0007c, + 0x003ca, 0x00036, 0x00189, 0x004a6, 0x004a2, 0x004fb, 0x000c0, 0x0007f, + 0x0009a, 0x00311, 0x0006e, 0x0009b, 0x0068c, 0x006c0, 0x00484, 0x00012, + 0x000c3, 0x0094f, 0x00979, 0x009f9, 0x00d09, 0x00da6, 0x00da8, 0x00901, + 0x000c1, 0x00373, 0x00d08, 0x009fa, 0x00d8b, 0x00d85, 0x00d86, 0x000df, + 0x006e2, 0x000ce, 0x00f24, 0x009fe, 0x001f7, 0x007c1, 0x000cf, 0x009fc, + 0x009ff, 0x00d89, 0x00da9, 0x009fd, 0x001f8, 0x01a36, 0x0128c, 0x0129d, + 0x01a37, 0x00196, 0x003ea, 0x00f8b, 0x00d93, 0x01e45, 0x01e58, 0x01e4b, + 0x01e59, 0x013f1, 0x00309, 0x00265, 0x00308, 0x0243a, 0x027e1, 0x00f89, + 0x00324, 0x03cbc, 0x03c86, 0x03695, 0x0243c, 0x0243b, 0x0243e, 0x01e4a, + 0x003a5, 0x03468, 0x03428, 0x03c84, 0x027e0, 0x025e2, 0x01880, 0x00197, + 0x00325, 0x03cb7, 0x0791e, 0x007ec, 0x06c75, 0x004c8, 0x04bc7, 0x004c6, + 0x00983, 0x0481e, 0x01b53, 0x0251b, 0x01b58, 0x00984, 0x04fa8, 0x03cbb, + 0x00f8a, 0x00322, 0x0346a, 0x0243d, 0x00326, 0x03469, 0x0481f, 0x0481d, + 0x00746, 0x09032, 0x01b50, 0x01d13, 0x0d8e4, 0x0481b, 0x06c74, 0x0796b, + 0x07969, 0x00985, 0x0d8e3, 0x00986, 0x00fa2, 0x01301, 0x06c7c, 0x00987, + 0x03cb8, 0x0f4af, 0x00e88, 0x1b1c0, 0x00fce, 0x033eb, 0x03f6a, 0x03f69, + 0x00fcf, 0x0791f, 0x004c9, 0x04871, 0x00fcd, 0x00982, 0x00fcc, 0x00fa3, + 0x01d12, 0x0796c, 0x01b47, 0x00321, 0x0796a, 0x0d8e2, 0x04872, 0x04873, + 0x0000e, 0x00014, 0x0000a, 0x000a0, 0x00012, 0x0007d, 0x001a2, 0x0003b, + 0x0025f, 0x000dd, 0x0027c, 0x00343, 0x00368, 0x0036b, 0x0003e, 0x001fa, + 0x00485, 0x001b3, 0x0007f, 0x001b1, 0x0019e, 0x004ba, 0x007ad, 0x00339, + 0x00066, 0x007a4, 0x00793, 0x006c6, 0x0007e, 0x000f1, 0x00372, 0x009fb, + 0x00d83, 0x00d8a, 0x00947, 0x009f4, 0x001d0, 0x01b09, 0x01b4b, 0x007ec, + 0x003e1, 0x000ca, 0x003ec, 0x02539, 0x04fa9, 0x01b57, 0x03429, 0x03d2a, + 0x00d97, 0x003a7, 0x00dc0, 0x00d96, 0x00dc1, 0x007eb, 0x03cba, 0x00c43, + 0x00c41, 0x01b52, 0x007ef, 0x00323, 0x03cb9, 0x03c83, 0x007d0, 0x007ed, + 0x06c7f, 0x09033, 0x03f6c, 0x36383, 0x1e95d, 0x06c78, 0x00747, 0x01b51, + 0x00022, 0x00016, 0x00039, 0x00252, 0x00079, 0x00486, 0x00338, 0x00369, + 0x00d88, 0x00026, 0x00d87, 0x00f4b, 0x00d82, 0x00027, 0x001e1, 0x01a15, + 0x007c7, 0x012f0, 0x001e0, 0x006d0, 0x01a16, 0x01e44, 0x01e5f, 0x03690, + 0x00d90, 0x00c42, 0x00daf, 0x00d92, 0x00f80, 0x00cfb, 0x0342f, 0x0487f, + 0x01b46, 0x07968, 0x00d95, 0x00d91, 0x01b55, 0x03f68, 0x04bc6, 0x03cbd, + 0x00f81, 0x00320, 0x00069, 0x000fe, 0x006d5, 0x0033f, 0x000de, 0x007c6, + 0x01e40, 0x00d94, 0x00f88, 0x03c8e, 0x03694, 0x00dae, 0x00dad, 0x00267, + 0x003a6, 0x00327, 0x0487e, 0x007ee, 0x00749, 0x004c7, 0x03692, 0x01b56, + 0x00fd1, 0x07a56, 0x06c77, 0x09031, 0x00748, 0x06c7a, 0x0796d, 0x033ea, + 0x06c76, 0x00fd0, 0x36382, 0x1e417, 0x00745, 0x04faf, 0x0d8e1, 0x03f6b, + 0x1e95c, 0x04fad, 0x0009e, 0x004bd, 0x0067c, 0x01b08, 0x003eb, 0x01b45, + 0x03691, 0x0d8e5, 0x07904, 0x00981, 0x007ea, 0x019f4, 0x06c7d, 0x04fab, + 0x04fac, 0x06c7e, 0x01300, 0x06c7b, 0x0006f, 0x003f7, 0x03c85, 0x004c4, + 0x0001e, 0x006e1, 0x03693, 0x01b44, 0x00241, 0x01e46, 0x0019d, 0x00266, + 0x004bb, 0x02538, 0x007ac, 0x01b54, 0x00902, 0x04870, 0x00da7, 0x00900, + 0x00185, 0x06c79, 0x006e3, 0x003e9, 0x01e94, 0x003ed, 0x003f2, 0x0342e, + 0x0346b, 0x0251a, 0x004c5, 0x01881, 0x0481c, 0x01b59, 0x03c87, 0x04fae, + 0x007e9, 0x03f6d, 0x0f20a, 0x09030, 0x04faa, 0x0d8e6, 0x03f6f, 0x0481a, + 0x03f6e, 0x1e416, 0x0d8e7, +}; + +static const uint8_t coef5_huffbits[435] = { + 10, 4, 2, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 7, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 10, 9, 10, 10, 10, 10, + 10, 9, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 10, 10, 11, 11, + 10, 11, 11, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 13, + 13, 13, 12, 12, 13, 13, 13, 12, + 12, 12, 12, 12, 13, 13, 13, 13, + 13, 14, 14, 14, 14, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, + 15, 14, 14, 14, 14, 14, 14, 13, + 14, 14, 14, 14, 14, 14, 15, 14, + 15, 14, 15, 15, 15, 15, 15, 15, + 16, 15, 15, 14, 15, 16, 15, 14, + 14, 15, 14, 14, 15, 14, 15, 15, + 15, 16, 15, 17, 16, 15, 15, 15, + 15, 16, 16, 16, 16, 17, 15, 16, + 14, 16, 16, 17, 16, 16, 16, 16, + 16, 15, 15, 15, 16, 16, 16, 16, + 17, 15, 15, 15, 15, 16, 15, 15, + 4, 7, 8, 8, 9, 9, 9, 10, + 10, 10, 10, 10, 10, 10, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 12, + 12, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 13, 13, 13, 13, + 12, 13, 14, 14, 15, 15, 14, 14, + 14, 14, 14, 14, 14, 15, 14, 14, + 14, 15, 15, 15, 14, 14, 15, 15, + 15, 16, 16, 18, 17, 15, 15, 15, + 6, 9, 10, 10, 11, 11, 12, 12, + 12, 13, 12, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 15, + 15, 15, 14, 14, 15, 16, 15, 14, + 14, 15, 7, 10, 11, 12, 13, 13, + 13, 14, 14, 14, 14, 14, 14, 14, + 14, 15, 15, 15, 15, 15, 14, 15, + 16, 15, 15, 16, 15, 15, 15, 16, + 15, 16, 18, 17, 15, 15, 16, 16, + 17, 15, 8, 11, 13, 13, 14, 15, + 14, 16, 15, 16, 15, 15, 15, 15, + 15, 15, 17, 15, 9, 12, 14, 15, + 10, 13, 14, 15, 10, 13, 11, 14, + 11, 14, 11, 15, 12, 15, 12, 12, + 13, 15, 13, 14, 13, 14, 14, 14, + 14, 14, 15, 15, 15, 15, 14, 15, + 15, 16, 16, 16, 15, 16, 16, 15, + 16, 17, 16, +}; + +static const uint16_t levels0[60] = { +317, 92, 62, 60, 19, 17, 10, 7, + 6, 5, 5, 3, 3, 3, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, +}; + +static const uint16_t levels1[40] = { +311, 91, 61, 28, 10, 6, 5, 2, + 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +}; + +static const uint16_t levels2[340] = { +181,110, 78, 63, 61, 62, 60, 61, + 33, 41, 41, 19, 17, 19, 12, 11, + 9, 11, 10, 6, 8, 7, 6, 4, + 5, 5, 4, 4, 3, 4, 3, 5, + 3, 4, 3, 3, 3, 3, 3, 3, + 2, 2, 4, 2, 3, 2, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 2, 1, 2, 2, + 2, 2, 1, 2, 1, 1, 1, 2, + 2, 1, 2, 1, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, +}; + +static const uint16_t levels3[180] = { +351,122, 76, 61, 41, 42, 24, 30, + 22, 19, 11, 9, 10, 8, 5, 5, + 4, 5, 5, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 3, 2, 2, 2, + 3, 3, 2, 2, 2, 3, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, + 2, 2, 1, 2, 1, 2, 2, 2, + 2, 2, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, +}; + +static const uint16_t levels4[70] = { +113, 68, 49, 42, 40, 32, 27, 15, + 10, 5, 3, 3, 3, 3, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +}; + +static const uint16_t levels5[40] = { +214, 72, 42, 40, 18, 4, 4, 2, + 2, 2, 2, 2, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, +}; + +static const CoefVLCTable coef_vlcs[6] = { + { + sizeof(coef0_huffbits), sizeof(levels0)/2, coef0_huffcodes, coef0_huffbits, levels0, + }, + { + sizeof(coef1_huffbits), sizeof(levels1)/2, coef1_huffcodes, coef1_huffbits, levels1, + }, + { + sizeof(coef2_huffbits), sizeof(levels2)/2, coef2_huffcodes, coef2_huffbits, levels2, + }, + { + sizeof(coef3_huffbits), sizeof(levels3)/2, coef3_huffcodes, coef3_huffbits, levels3, + }, + { + sizeof(coef4_huffbits), sizeof(levels4)/2, coef4_huffcodes, coef4_huffbits, levels4, + }, + { + sizeof(coef5_huffbits), sizeof(levels5)/2, coef5_huffcodes, coef5_huffbits, levels5, + }, +}; + +#endif /* AVCODEC_WMADATA_H */ diff --git a/ffmpeg/libavcodec/wmadec.c b/ffmpeg/libavcodec/wmadec.c new file mode 100644 index 0000000..0648c1e --- /dev/null +++ b/ffmpeg/libavcodec/wmadec.c @@ -0,0 +1,974 @@ +/* + * WMA compatible decoder + * Copyright (c) 2002 The FFmpeg Project + * + * 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 + */ + +/** + * @file + * WMA compatible decoder. + * This decoder handles Microsoft Windows Media Audio data, versions 1 & 2. + * WMA v1 is identified by audio format 0x160 in Microsoft media files + * (ASF/AVI/WAV). WMA v2 is identified by audio format 0x161. + * + * To use this decoder, a calling application must supply the extra data + * bytes provided with the WMA data. These are the extra, codec-specific + * bytes at the end of a WAVEFORMATEX data structure. Transmit these bytes + * to the decoder using the extradata[_size] fields in AVCodecContext. There + * should be 4 extra bytes for v1 data and 6 extra bytes for v2 data. + */ + +#include "avcodec.h" +#include "internal.h" +#include "wma.h" + +#undef NDEBUG +#include + +#define EXPVLCBITS 8 +#define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS) + +#define HGAINVLCBITS 9 +#define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS) + +static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len); + +#ifdef TRACE +static void dump_floats(WMACodecContext *s, const char *name, int prec, const float *tab, int n) +{ + int i; + + tprintf(s->avctx, "%s[%d]:\n", name, n); + for(i=0;iavctx, "%4d: ", i); + tprintf(s->avctx, " %8.*f", prec, tab[i]); + if ((i & 7) == 7) + tprintf(s->avctx, "\n"); + } + if ((i & 7) != 0) + tprintf(s->avctx, "\n"); +} +#endif + +static int wma_decode_init(AVCodecContext * avctx) +{ + WMACodecContext *s = avctx->priv_data; + int i, flags2; + uint8_t *extradata; + + if (!avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, "block_align is not set\n"); + return AVERROR(EINVAL); + } + + s->avctx = avctx; + + /* extract flag infos */ + flags2 = 0; + extradata = avctx->extradata; + if (avctx->codec->id == AV_CODEC_ID_WMAV1 && avctx->extradata_size >= 4) { + flags2 = AV_RL16(extradata+2); + } else if (avctx->codec->id == AV_CODEC_ID_WMAV2 && avctx->extradata_size >= 6) { + flags2 = AV_RL16(extradata+4); + } + + s->use_exp_vlc = flags2 & 0x0001; + s->use_bit_reservoir = flags2 & 0x0002; + s->use_variable_block_len = flags2 & 0x0004; + + if(avctx->codec->id == AV_CODEC_ID_WMAV2 && avctx->extradata_size >= 8){ + if(AV_RL16(extradata+4)==0xd && s->use_variable_block_len){ + av_log(avctx, AV_LOG_WARNING, "Disabling use_variable_block_len, if this fails contact the ffmpeg developers and send us the file\n"); + s->use_variable_block_len= 0; // this fixes issue1503 + } + } + + if(ff_wma_init(avctx, flags2)<0) + return -1; + + /* init MDCT */ + for(i = 0; i < s->nb_block_sizes; i++) + ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 1, 1.0 / 32768.0); + + if (s->use_noise_coding) { + init_vlc(&s->hgain_vlc, HGAINVLCBITS, sizeof(ff_wma_hgain_huffbits), + ff_wma_hgain_huffbits, 1, 1, + ff_wma_hgain_huffcodes, 2, 2, 0); + } + + if (s->use_exp_vlc) { + init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(ff_aac_scalefactor_bits), //FIXME move out of context + ff_aac_scalefactor_bits, 1, 1, + ff_aac_scalefactor_code, 4, 4, 0); + } else { + wma_lsp_to_curve_init(s, s->frame_len); + } + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + return 0; +} + +/** + * compute x^-0.25 with an exponent and mantissa table. We use linear + * interpolation to reduce the mantissa table size at a small speed + * expense (linear interpolation approximately doubles the number of + * bits of precision). + */ +static inline float pow_m1_4(WMACodecContext *s, float x) +{ + union { + float f; + unsigned int v; + } u, t; + unsigned int e, m; + float a, b; + + u.f = x; + e = u.v >> 23; + m = (u.v >> (23 - LSP_POW_BITS)) & ((1 << LSP_POW_BITS) - 1); + /* build interpolation scale: 1 <= t < 2. */ + t.v = ((u.v << LSP_POW_BITS) & ((1 << 23) - 1)) | (127 << 23); + a = s->lsp_pow_m_table1[m]; + b = s->lsp_pow_m_table2[m]; + return s->lsp_pow_e_table[e] * (a + b * t.f); +} + +static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len) +{ + float wdel, a, b; + int i, e, m; + + wdel = M_PI / frame_len; + for(i=0;ilsp_cos_table[i] = 2.0f * cos(wdel * i); + + /* tables for x^-0.25 computation */ + for(i=0;i<256;i++) { + e = i - 126; + s->lsp_pow_e_table[i] = pow(2.0, e * -0.25); + } + + /* NOTE: these two tables are needed to avoid two operations in + pow_m1_4 */ + b = 1.0; + for(i=(1 << LSP_POW_BITS) - 1;i>=0;i--) { + m = (1 << LSP_POW_BITS) + i; + a = (float)m * (0.5 / (1 << LSP_POW_BITS)); + a = pow(a, -0.25); + s->lsp_pow_m_table1[i] = 2 * a - b; + s->lsp_pow_m_table2[i] = b - a; + b = a; + } +} + +/** + * NOTE: We use the same code as Vorbis here + * @todo optimize it further with SSE/3Dnow + */ +static void wma_lsp_to_curve(WMACodecContext *s, + float *out, float *val_max_ptr, + int n, float *lsp) +{ + int i, j; + float p, q, w, v, val_max; + + val_max = 0; + for(i=0;ilsp_cos_table[i]; + for(j=1;j val_max) + val_max = v; + out[i] = v; + } + *val_max_ptr = val_max; +} + +/** + * decode exponents coded with LSP coefficients (same idea as Vorbis) + */ +static void decode_exp_lsp(WMACodecContext *s, int ch) +{ + float lsp_coefs[NB_LSP_COEFS]; + int val, i; + + for(i = 0; i < NB_LSP_COEFS; i++) { + if (i == 0 || i >= 8) + val = get_bits(&s->gb, 3); + else + val = get_bits(&s->gb, 4); + lsp_coefs[i] = ff_wma_lsp_codebook[i][val]; + } + + wma_lsp_to_curve(s, s->exponents[ch], &s->max_exponent[ch], + s->block_len, lsp_coefs); +} + +/** pow(10, i / 16.0) for i in -60..95 */ +static const float pow_tab[] = { + 1.7782794100389e-04, 2.0535250264571e-04, + 2.3713737056617e-04, 2.7384196342644e-04, + 3.1622776601684e-04, 3.6517412725484e-04, + 4.2169650342858e-04, 4.8696752516586e-04, + 5.6234132519035e-04, 6.4938163157621e-04, + 7.4989420933246e-04, 8.6596432336006e-04, + 1.0000000000000e-03, 1.1547819846895e-03, + 1.3335214321633e-03, 1.5399265260595e-03, + 1.7782794100389e-03, 2.0535250264571e-03, + 2.3713737056617e-03, 2.7384196342644e-03, + 3.1622776601684e-03, 3.6517412725484e-03, + 4.2169650342858e-03, 4.8696752516586e-03, + 5.6234132519035e-03, 6.4938163157621e-03, + 7.4989420933246e-03, 8.6596432336006e-03, + 1.0000000000000e-02, 1.1547819846895e-02, + 1.3335214321633e-02, 1.5399265260595e-02, + 1.7782794100389e-02, 2.0535250264571e-02, + 2.3713737056617e-02, 2.7384196342644e-02, + 3.1622776601684e-02, 3.6517412725484e-02, + 4.2169650342858e-02, 4.8696752516586e-02, + 5.6234132519035e-02, 6.4938163157621e-02, + 7.4989420933246e-02, 8.6596432336007e-02, + 1.0000000000000e-01, 1.1547819846895e-01, + 1.3335214321633e-01, 1.5399265260595e-01, + 1.7782794100389e-01, 2.0535250264571e-01, + 2.3713737056617e-01, 2.7384196342644e-01, + 3.1622776601684e-01, 3.6517412725484e-01, + 4.2169650342858e-01, 4.8696752516586e-01, + 5.6234132519035e-01, 6.4938163157621e-01, + 7.4989420933246e-01, 8.6596432336007e-01, + 1.0000000000000e+00, 1.1547819846895e+00, + 1.3335214321633e+00, 1.5399265260595e+00, + 1.7782794100389e+00, 2.0535250264571e+00, + 2.3713737056617e+00, 2.7384196342644e+00, + 3.1622776601684e+00, 3.6517412725484e+00, + 4.2169650342858e+00, 4.8696752516586e+00, + 5.6234132519035e+00, 6.4938163157621e+00, + 7.4989420933246e+00, 8.6596432336007e+00, + 1.0000000000000e+01, 1.1547819846895e+01, + 1.3335214321633e+01, 1.5399265260595e+01, + 1.7782794100389e+01, 2.0535250264571e+01, + 2.3713737056617e+01, 2.7384196342644e+01, + 3.1622776601684e+01, 3.6517412725484e+01, + 4.2169650342858e+01, 4.8696752516586e+01, + 5.6234132519035e+01, 6.4938163157621e+01, + 7.4989420933246e+01, 8.6596432336007e+01, + 1.0000000000000e+02, 1.1547819846895e+02, + 1.3335214321633e+02, 1.5399265260595e+02, + 1.7782794100389e+02, 2.0535250264571e+02, + 2.3713737056617e+02, 2.7384196342644e+02, + 3.1622776601684e+02, 3.6517412725484e+02, + 4.2169650342858e+02, 4.8696752516586e+02, + 5.6234132519035e+02, 6.4938163157621e+02, + 7.4989420933246e+02, 8.6596432336007e+02, + 1.0000000000000e+03, 1.1547819846895e+03, + 1.3335214321633e+03, 1.5399265260595e+03, + 1.7782794100389e+03, 2.0535250264571e+03, + 2.3713737056617e+03, 2.7384196342644e+03, + 3.1622776601684e+03, 3.6517412725484e+03, + 4.2169650342858e+03, 4.8696752516586e+03, + 5.6234132519035e+03, 6.4938163157621e+03, + 7.4989420933246e+03, 8.6596432336007e+03, + 1.0000000000000e+04, 1.1547819846895e+04, + 1.3335214321633e+04, 1.5399265260595e+04, + 1.7782794100389e+04, 2.0535250264571e+04, + 2.3713737056617e+04, 2.7384196342644e+04, + 3.1622776601684e+04, 3.6517412725484e+04, + 4.2169650342858e+04, 4.8696752516586e+04, + 5.6234132519035e+04, 6.4938163157621e+04, + 7.4989420933246e+04, 8.6596432336007e+04, + 1.0000000000000e+05, 1.1547819846895e+05, + 1.3335214321633e+05, 1.5399265260595e+05, + 1.7782794100389e+05, 2.0535250264571e+05, + 2.3713737056617e+05, 2.7384196342644e+05, + 3.1622776601684e+05, 3.6517412725484e+05, + 4.2169650342858e+05, 4.8696752516586e+05, + 5.6234132519035e+05, 6.4938163157621e+05, + 7.4989420933246e+05, 8.6596432336007e+05, +}; + +/** + * decode exponents coded with VLC codes + */ +static int decode_exp_vlc(WMACodecContext *s, int ch) +{ + int last_exp, n, code; + const uint16_t *ptr; + float v, max_scale; + uint32_t *q, *q_end, iv; + const float *ptab = pow_tab + 60; + const uint32_t *iptab = (const uint32_t*)ptab; + + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = (uint32_t *)s->exponents[ch]; + q_end = q + s->block_len; + max_scale = 0; + if (s->version == 1) { + last_exp = get_bits(&s->gb, 5) + 10; + v = ptab[last_exp]; + iv = iptab[last_exp]; + max_scale = v; + n = *ptr++; + switch (n & 3) do { + case 0: *q++ = iv; + case 3: *q++ = iv; + case 2: *q++ = iv; + case 1: *q++ = iv; + } while ((n -= 4) > 0); + }else + last_exp = 36; + + while (q < q_end) { + code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "Exponent vlc invalid\n"); + return -1; + } + /* NOTE: this offset is the same as MPEG4 AAC ! */ + last_exp += code - 60; + if ((unsigned)last_exp + 60 >= FF_ARRAY_ELEMS(pow_tab)) { + av_log(s->avctx, AV_LOG_ERROR, "Exponent out of range: %d\n", + last_exp); + return -1; + } + v = ptab[last_exp]; + iv = iptab[last_exp]; + if (v > max_scale) + max_scale = v; + n = *ptr++; + switch (n & 3) do { + case 0: *q++ = iv; + case 3: *q++ = iv; + case 2: *q++ = iv; + case 1: *q++ = iv; + } while ((n -= 4) > 0); + } + s->max_exponent[ch] = max_scale; + return 0; +} + + +/** + * Apply MDCT window and add into output. + * + * We ensure that when the windows overlap their squared sum + * is always 1 (MDCT reconstruction rule). + */ +static void wma_window(WMACodecContext *s, float *out) +{ + float *in = s->output; + int block_len, bsize, n; + + /* left part */ + if (s->block_len_bits <= s->prev_block_len_bits) { + block_len = s->block_len; + bsize = s->frame_len_bits - s->block_len_bits; + + s->fdsp.vector_fmul_add(out, in, s->windows[bsize], + out, block_len); + + } else { + block_len = 1 << s->prev_block_len_bits; + n = (s->block_len - block_len) / 2; + bsize = s->frame_len_bits - s->prev_block_len_bits; + + s->fdsp.vector_fmul_add(out+n, in+n, s->windows[bsize], + out+n, block_len); + + memcpy(out+n+block_len, in+n+block_len, n*sizeof(float)); + } + + out += s->block_len; + in += s->block_len; + + /* right part */ + if (s->block_len_bits <= s->next_block_len_bits) { + block_len = s->block_len; + bsize = s->frame_len_bits - s->block_len_bits; + + s->fdsp.vector_fmul_reverse(out, in, s->windows[bsize], block_len); + + } else { + block_len = 1 << s->next_block_len_bits; + n = (s->block_len - block_len) / 2; + bsize = s->frame_len_bits - s->next_block_len_bits; + + memcpy(out, in, n*sizeof(float)); + + s->fdsp.vector_fmul_reverse(out+n, in+n, s->windows[bsize], block_len); + + memset(out+n+block_len, 0, n*sizeof(float)); + } +} + + +/** + * @return 0 if OK. 1 if last block of frame. return -1 if + * unrecorrable error. + */ +static int wma_decode_block(WMACodecContext *s) +{ + int n, v, a, ch, bsize; + int coef_nb_bits, total_gain; + int nb_coefs[MAX_CHANNELS]; + float mdct_norm; + FFTContext *mdct; + +#ifdef TRACE + tprintf(s->avctx, "***decode_block: %d:%d\n", s->frame_count - 1, s->block_num); +#endif + + /* compute current block length */ + if (s->use_variable_block_len) { + n = av_log2(s->nb_block_sizes - 1) + 1; + + if (s->reset_block_lengths) { + s->reset_block_lengths = 0; + v = get_bits(&s->gb, n); + if (v >= s->nb_block_sizes){ + av_log(s->avctx, AV_LOG_ERROR, "prev_block_len_bits %d out of range\n", s->frame_len_bits - v); + return -1; + } + s->prev_block_len_bits = s->frame_len_bits - v; + v = get_bits(&s->gb, n); + if (v >= s->nb_block_sizes){ + av_log(s->avctx, AV_LOG_ERROR, "block_len_bits %d out of range\n", s->frame_len_bits - v); + return -1; + } + s->block_len_bits = s->frame_len_bits - v; + } else { + /* update block lengths */ + s->prev_block_len_bits = s->block_len_bits; + s->block_len_bits = s->next_block_len_bits; + } + v = get_bits(&s->gb, n); + if (v >= s->nb_block_sizes){ + av_log(s->avctx, AV_LOG_ERROR, "next_block_len_bits %d out of range\n", s->frame_len_bits - v); + return -1; + } + s->next_block_len_bits = s->frame_len_bits - v; + } else { + /* fixed block len */ + s->next_block_len_bits = s->frame_len_bits; + s->prev_block_len_bits = s->frame_len_bits; + s->block_len_bits = s->frame_len_bits; + } + + if (s->frame_len_bits - s->block_len_bits >= s->nb_block_sizes){ + av_log(s->avctx, AV_LOG_ERROR, "block_len_bits not initialized to a valid value\n"); + return -1; + } + + /* now check if the block length is coherent with the frame length */ + s->block_len = 1 << s->block_len_bits; + if ((s->block_pos + s->block_len) > s->frame_len){ + av_log(s->avctx, AV_LOG_ERROR, "frame_len overflow\n"); + return -1; + } + + if (s->avctx->channels == 2) { + s->ms_stereo = get_bits1(&s->gb); + } + v = 0; + for(ch = 0; ch < s->avctx->channels; ch++) { + a = get_bits1(&s->gb); + s->channel_coded[ch] = a; + v |= a; + } + + bsize = s->frame_len_bits - s->block_len_bits; + + /* if no channel coded, no need to go further */ + /* XXX: fix potential framing problems */ + if (!v) + goto next; + + /* read total gain and extract corresponding number of bits for + coef escape coding */ + total_gain = 1; + for(;;) { + a = get_bits(&s->gb, 7); + total_gain += a; + if (a != 127) + break; + } + + coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); + + /* compute number of coefficients */ + n = s->coefs_end[bsize] - s->coefs_start; + for(ch = 0; ch < s->avctx->channels; ch++) + nb_coefs[ch] = n; + + /* complex coding */ + if (s->use_noise_coding) { + + for(ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + int i, n, a; + n = s->exponent_high_sizes[bsize]; + for(i=0;igb); + s->high_band_coded[ch][i] = a; + /* if noise coding, the coefficients are not transmitted */ + if (a) + nb_coefs[ch] -= s->exponent_high_bands[bsize][i]; + } + } + } + for(ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + int i, n, val, code; + + n = s->exponent_high_sizes[bsize]; + val = (int)0x80000000; + for(i=0;ihigh_band_coded[ch][i]) { + if (val == (int)0x80000000) { + val = get_bits(&s->gb, 7) - 19; + } else { + code = get_vlc2(&s->gb, s->hgain_vlc.table, HGAINVLCBITS, HGAINMAX); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "hgain vlc invalid\n"); + return -1; + } + val += code - 18; + } + s->high_band_values[ch][i] = val; + } + } + } + } + } + + /* exponents can be reused in short blocks. */ + if ((s->block_len_bits == s->frame_len_bits) || + get_bits1(&s->gb)) { + for(ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + if (s->use_exp_vlc) { + if (decode_exp_vlc(s, ch) < 0) + return -1; + } else { + decode_exp_lsp(s, ch); + } + s->exponents_bsize[ch] = bsize; + } + } + } + + /* parse spectral coefficients : just RLE encoding */ + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + int tindex; + WMACoef* ptr = &s->coefs1[ch][0]; + + /* special VLC tables are used for ms stereo because + there is potentially less energy there */ + tindex = (ch == 1 && s->ms_stereo); + memset(ptr, 0, s->block_len * sizeof(WMACoef)); + ff_wma_run_level_decode(s->avctx, &s->gb, &s->coef_vlc[tindex], + s->level_table[tindex], s->run_table[tindex], + 0, ptr, 0, nb_coefs[ch], + s->block_len, s->frame_len_bits, coef_nb_bits); + } + if (s->version == 1 && s->avctx->channels >= 2) { + align_get_bits(&s->gb); + } + } + + /* normalize */ + { + int n4 = s->block_len / 2; + mdct_norm = 1.0 / (float)n4; + if (s->version == 1) { + mdct_norm *= sqrt(n4); + } + } + + /* finally compute the MDCT coefficients */ + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + WMACoef *coefs1; + float *coefs, *exponents, mult, mult1, noise; + int i, j, n, n1, last_high_band, esize; + float exp_power[HIGH_BAND_MAX_SIZE]; + + coefs1 = s->coefs1[ch]; + exponents = s->exponents[ch]; + esize = s->exponents_bsize[ch]; + mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; + mult *= mdct_norm; + coefs = s->coefs[ch]; + if (s->use_noise_coding) { + mult1 = mult; + /* very low freqs : noise */ + for(i = 0;i < s->coefs_start; i++) { + *coefs++ = s->noise_table[s->noise_index] * + exponents[i<>esize] * mult1; + s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); + } + + n1 = s->exponent_high_sizes[bsize]; + + /* compute power of high bands */ + exponents = s->exponents[ch] + + (s->high_band_start[bsize]<>esize); + last_high_band = 0; /* avoid warning */ + for(j=0;jexponent_high_bands[s->frame_len_bits - + s->block_len_bits][j]; + if (s->high_band_coded[ch][j]) { + float e2, v; + e2 = 0; + for(i = 0;i < n; i++) { + v = exponents[i<>esize]; + e2 += v * v; + } + exp_power[j] = e2 / n; + last_high_band = j; + tprintf(s->avctx, "%d: power=%f (%d)\n", j, exp_power[j], n); + } + exponents += n<>esize; + } + + /* main freqs and high freqs */ + exponents = s->exponents[ch] + (s->coefs_start<>esize); + for(j=-1;jhigh_band_start[bsize] - + s->coefs_start; + } else { + n = s->exponent_high_bands[s->frame_len_bits - + s->block_len_bits][j]; + } + if (j >= 0 && s->high_band_coded[ch][j]) { + /* use noise with specified power */ + mult1 = sqrt(exp_power[j] / exp_power[last_high_band]); + /* XXX: use a table */ + mult1 = mult1 * pow(10, s->high_band_values[ch][j] * 0.05); + mult1 = mult1 / (s->max_exponent[ch] * s->noise_mult); + mult1 *= mdct_norm; + for(i = 0;i < n; i++) { + noise = s->noise_table[s->noise_index]; + s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); + *coefs++ = noise * + exponents[i<>esize] * mult1; + } + exponents += n<>esize; + } else { + /* coded values + small noise */ + for(i = 0;i < n; i++) { + noise = s->noise_table[s->noise_index]; + s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); + *coefs++ = ((*coefs1++) + noise) * + exponents[i<>esize] * mult; + } + exponents += n<>esize; + } + } + + /* very high freqs : noise */ + n = s->block_len - s->coefs_end[bsize]; + mult1 = mult * exponents[((-1<>esize]; + for(i = 0; i < n; i++) { + *coefs++ = s->noise_table[s->noise_index] * mult1; + s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); + } + } else { + /* XXX: optimize more */ + for(i = 0;i < s->coefs_start; i++) + *coefs++ = 0.0; + n = nb_coefs[ch]; + for(i = 0;i < n; i++) { + *coefs++ = coefs1[i] * exponents[i<>esize] * mult; + } + n = s->block_len - s->coefs_end[bsize]; + for(i = 0;i < n; i++) + *coefs++ = 0.0; + } + } + } + +#ifdef TRACE + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + dump_floats(s, "exponents", 3, s->exponents[ch], s->block_len); + dump_floats(s, "coefs", 1, s->coefs[ch], s->block_len); + } + } +#endif + + if (s->ms_stereo && s->channel_coded[1]) { + /* nominal case for ms stereo: we do it before mdct */ + /* no need to optimize this case because it should almost + never happen */ + if (!s->channel_coded[0]) { + tprintf(s->avctx, "rare ms-stereo case happened\n"); + memset(s->coefs[0], 0, sizeof(float) * s->block_len); + s->channel_coded[0] = 1; + } + + s->fdsp.butterflies_float(s->coefs[0], s->coefs[1], s->block_len); + } + +next: + mdct = &s->mdct_ctx[bsize]; + + for (ch = 0; ch < s->avctx->channels; ch++) { + int n4, index; + + n4 = s->block_len / 2; + if(s->channel_coded[ch]){ + mdct->imdct_calc(mdct, s->output, s->coefs[ch]); + }else if(!(s->ms_stereo && ch==1)) + memset(s->output, 0, sizeof(s->output)); + + /* multiply by the window and add in the frame */ + index = (s->frame_len / 2) + s->block_pos - n4; + wma_window(s, &s->frame_out[ch][index]); + } + + /* update block number */ + s->block_num++; + s->block_pos += s->block_len; + if (s->block_pos >= s->frame_len) + return 1; + else + return 0; +} + +/* decode a frame of frame_len samples */ +static int wma_decode_frame(WMACodecContext *s, float **samples, + int samples_offset) +{ + int ret, ch; + +#ifdef TRACE + tprintf(s->avctx, "***decode_frame: %d size=%d\n", s->frame_count++, s->frame_len); +#endif + + /* read each block */ + s->block_num = 0; + s->block_pos = 0; + for(;;) { + ret = wma_decode_block(s); + if (ret < 0) + return -1; + if (ret) + break; + } + + for (ch = 0; ch < s->avctx->channels; ch++) { + /* copy current block to output */ + memcpy(samples[ch] + samples_offset, s->frame_out[ch], + s->frame_len * sizeof(*s->frame_out[ch])); + /* prepare for next block */ + memmove(&s->frame_out[ch][0], &s->frame_out[ch][s->frame_len], + s->frame_len * sizeof(*s->frame_out[ch])); + +#ifdef TRACE + dump_floats(s, "samples", 6, samples[ch] + samples_offset, s->frame_len); +#endif + } + + return 0; +} + +static int wma_decode_superframe(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + WMACodecContext *s = avctx->priv_data; + int nb_frames, bit_offset, i, pos, len, ret; + uint8_t *q; + float **samples; + int samples_offset; + + tprintf(avctx, "***decode_superframe:\n"); + + if(buf_size==0){ + s->last_superframe_len = 0; + return 0; + } + if (buf_size < avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, + "Input packet size too small (%d < %d)\n", + buf_size, avctx->block_align); + return AVERROR_INVALIDDATA; + } + if(avctx->block_align) + buf_size = avctx->block_align; + + init_get_bits(&s->gb, buf, buf_size*8); + + if (s->use_bit_reservoir) { + /* read super frame header */ + skip_bits(&s->gb, 4); /* super frame index */ + nb_frames = get_bits(&s->gb, 4) - (s->last_superframe_len <= 0); + if (nb_frames <= 0) { + av_log(avctx, AV_LOG_ERROR, "nb_frames is %d\n", nb_frames); + return AVERROR_INVALIDDATA; + } + } else { + nb_frames = 1; + } + + /* get output buffer */ + frame->nb_samples = nb_frames * s->frame_len; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = (float **)frame->extended_data; + samples_offset = 0; + + if (s->use_bit_reservoir) { + bit_offset = get_bits(&s->gb, s->byte_offset_bits + 3); + if (bit_offset > get_bits_left(&s->gb)) { + av_log(avctx, AV_LOG_ERROR, + "Invalid last frame bit offset %d > buf size %d (%d)\n", + bit_offset, get_bits_left(&s->gb), buf_size); + goto fail; + } + + if (s->last_superframe_len > 0) { + /* add bit_offset bits to last frame */ + if ((s->last_superframe_len + ((bit_offset + 7) >> 3)) > + MAX_CODED_SUPERFRAME_SIZE) + goto fail; + q = s->last_superframe + s->last_superframe_len; + len = bit_offset; + while (len > 7) { + *q++ = (get_bits)(&s->gb, 8); + len -= 8; + } + if (len > 0) { + *q++ = (get_bits)(&s->gb, len) << (8 - len); + } + memset(q, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + /* XXX: bit_offset bits into last frame */ + init_get_bits(&s->gb, s->last_superframe, s->last_superframe_len * 8 + bit_offset); + /* skip unused bits */ + if (s->last_bitoffset > 0) + skip_bits(&s->gb, s->last_bitoffset); + /* this frame is stored in the last superframe and in the + current one */ + if (wma_decode_frame(s, samples, samples_offset) < 0) + goto fail; + samples_offset += s->frame_len; + nb_frames--; + } + + /* read each frame starting from bit_offset */ + pos = bit_offset + 4 + 4 + s->byte_offset_bits + 3; + if (pos >= MAX_CODED_SUPERFRAME_SIZE * 8 || pos > buf_size * 8) + return AVERROR_INVALIDDATA; + init_get_bits(&s->gb, buf + (pos >> 3), (buf_size - (pos >> 3))*8); + len = pos & 7; + if (len > 0) + skip_bits(&s->gb, len); + + s->reset_block_lengths = 1; + for(i=0;iframe_len; + } + + /* we copy the end of the frame in the last frame buffer */ + pos = get_bits_count(&s->gb) + ((bit_offset + 4 + 4 + s->byte_offset_bits + 3) & ~7); + s->last_bitoffset = pos & 7; + pos >>= 3; + len = buf_size - pos; + if (len > MAX_CODED_SUPERFRAME_SIZE || len < 0) { + av_log(s->avctx, AV_LOG_ERROR, "len %d invalid\n", len); + goto fail; + } + s->last_superframe_len = len; + memcpy(s->last_superframe, buf + pos, len); + } else { + /* single frame decode */ + if (wma_decode_frame(s, samples, samples_offset) < 0) + goto fail; + samples_offset += s->frame_len; + } + + av_dlog(s->avctx, "%d %d %d %d outbytes:%td eaten:%d\n", + s->frame_len_bits, s->block_len_bits, s->frame_len, s->block_len, + (int8_t *)samples - (int8_t *)data, avctx->block_align); + + *got_frame_ptr = 1; + + return buf_size; + fail: + /* when error, we reset the bit reservoir */ + s->last_superframe_len = 0; + return -1; +} + +static av_cold void flush(AVCodecContext *avctx) +{ + WMACodecContext *s = avctx->priv_data; + + s->last_bitoffset= + s->last_superframe_len= 0; +} + +#if CONFIG_WMAV1_DECODER +AVCodec ff_wmav1_decoder = { + .name = "wmav1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMAV1, + .priv_data_size = sizeof(WMACodecContext), + .init = wma_decode_init, + .close = ff_wma_end, + .decode = wma_decode_superframe, + .flush = flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; +#endif +#if CONFIG_WMAV2_DECODER +AVCodec ff_wmav2_decoder = { + .name = "wmav2", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMAV2, + .priv_data_size = sizeof(WMACodecContext), + .init = wma_decode_init, + .close = ff_wma_end, + .decode = wma_decode_superframe, + .flush = flush, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; +#endif diff --git a/ffmpeg/libavcodec/wmaenc.c b/ffmpeg/libavcodec/wmaenc.c new file mode 100644 index 0000000..799535e --- /dev/null +++ b/ffmpeg/libavcodec/wmaenc.c @@ -0,0 +1,421 @@ +/* + * WMA compatible encoder + * Copyright (c) 2007 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 "avcodec.h" +#include "internal.h" +#include "wma.h" +#include "libavutil/avassert.h" + + +static int encode_init(AVCodecContext * avctx){ + WMACodecContext *s = avctx->priv_data; + int i, flags1, flags2, block_align; + uint8_t *extradata; + + s->avctx = avctx; + + if(avctx->channels > MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "too many channels: got %i, need %i or fewer\n", + avctx->channels, MAX_CHANNELS); + return AVERROR(EINVAL); + } + + if (avctx->sample_rate > 48000) { + av_log(avctx, AV_LOG_ERROR, "sample rate is too high: %d > 48kHz\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } + + if(avctx->bit_rate < 24*1000) { + av_log(avctx, AV_LOG_ERROR, "bitrate too low: got %i, need 24000 or higher\n", + avctx->bit_rate); + return AVERROR(EINVAL); + } + + /* extract flag infos */ + flags1 = 0; + flags2 = 1; + if (avctx->codec->id == AV_CODEC_ID_WMAV1) { + extradata= av_malloc(4); + avctx->extradata_size= 4; + AV_WL16(extradata, flags1); + AV_WL16(extradata+2, flags2); + } else if (avctx->codec->id == AV_CODEC_ID_WMAV2) { + extradata= av_mallocz(10); + avctx->extradata_size= 10; + AV_WL32(extradata, flags1); + AV_WL16(extradata+4, flags2); + }else + av_assert0(0); + avctx->extradata= extradata; + s->use_exp_vlc = flags2 & 0x0001; + s->use_bit_reservoir = flags2 & 0x0002; + s->use_variable_block_len = flags2 & 0x0004; + if (avctx->channels == 2) + s->ms_stereo = 1; + + ff_wma_init(avctx, flags2); + + /* init MDCT */ + for(i = 0; i < s->nb_block_sizes; i++) + ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 0, 1.0); + + block_align = avctx->bit_rate * (int64_t)s->frame_len / + (avctx->sample_rate * 8); + block_align = FFMIN(block_align, MAX_CODED_SUPERFRAME_SIZE); + avctx->block_align = block_align; + + avctx->frame_size = avctx->delay = s->frame_len; + + return 0; +} + + +static void apply_window_and_mdct(AVCodecContext * avctx, const AVFrame *frame) +{ + WMACodecContext *s = avctx->priv_data; + float **audio = (float **)frame->extended_data; + int len = frame->nb_samples; + int window_index= s->frame_len_bits - s->block_len_bits; + FFTContext *mdct = &s->mdct_ctx[window_index]; + int ch; + const float * win = s->windows[window_index]; + int window_len = 1 << s->block_len_bits; + float n = 2.0 * 32768.0 / window_len; + + for (ch = 0; ch < avctx->channels; ch++) { + memcpy(s->output, s->frame_out[ch], window_len * sizeof(*s->output)); + s->fdsp.vector_fmul_scalar(s->frame_out[ch], audio[ch], n, len); + s->fdsp.vector_fmul_reverse(&s->output[window_len], s->frame_out[ch], win, len); + s->fdsp.vector_fmul(s->frame_out[ch], s->frame_out[ch], win, len); + mdct->mdct_calc(mdct, s->coefs[ch], s->output); + } +} + +//FIXME use for decoding too +static void init_exp(WMACodecContext *s, int ch, const int *exp_param){ + int n; + const uint16_t *ptr; + float v, *q, max_scale, *q_end; + + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = s->exponents[ch]; + q_end = q + s->block_len; + max_scale = 0; + while (q < q_end) { + /* XXX: use a table */ + v = pow(10, *exp_param++ * (1.0 / 16.0)); + max_scale= FFMAX(max_scale, v); + n = *ptr++; + do { + *q++ = v; + } while (--n); + } + s->max_exponent[ch] = max_scale; +} + +static void encode_exp_vlc(WMACodecContext *s, int ch, const int *exp_param){ + int last_exp; + const uint16_t *ptr; + float *q, *q_end; + + ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; + q = s->exponents[ch]; + q_end = q + s->block_len; + if (s->version == 1) { + last_exp= *exp_param++; + av_assert0(last_exp-10 >= 0 && last_exp-10 < 32); + put_bits(&s->pb, 5, last_exp - 10); + q+= *ptr++; + }else + last_exp = 36; + while (q < q_end) { + int exp = *exp_param++; + int code = exp - last_exp + 60; + av_assert1(code >= 0 && code < 120); + put_bits(&s->pb, ff_aac_scalefactor_bits[code], ff_aac_scalefactor_code[code]); + /* XXX: use a table */ + q+= *ptr++; + last_exp= exp; + } +} + +static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], int total_gain){ + int v, bsize, ch, coef_nb_bits, parse_exponents; + float mdct_norm; + int nb_coefs[MAX_CHANNELS]; + static const int fixed_exp[25]={20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20}; + + //FIXME remove duplication relative to decoder + if (s->use_variable_block_len) { + av_assert0(0); //FIXME not implemented + }else{ + /* fixed block len */ + s->next_block_len_bits = s->frame_len_bits; + s->prev_block_len_bits = s->frame_len_bits; + s->block_len_bits = s->frame_len_bits; + } + + s->block_len = 1 << s->block_len_bits; +// assert((s->block_pos + s->block_len) <= s->frame_len); + bsize = s->frame_len_bits - s->block_len_bits; + + //FIXME factor + v = s->coefs_end[bsize] - s->coefs_start; + for (ch = 0; ch < s->avctx->channels; ch++) + nb_coefs[ch] = v; + { + int n4 = s->block_len / 2; + mdct_norm = 1.0 / (float)n4; + if (s->version == 1) { + mdct_norm *= sqrt(n4); + } + } + + if (s->avctx->channels == 2) { + put_bits(&s->pb, 1, !!s->ms_stereo); + } + + for (ch = 0; ch < s->avctx->channels; ch++) { + s->channel_coded[ch] = 1; //FIXME only set channel_coded when needed, instead of always + if (s->channel_coded[ch]) { + init_exp(s, ch, fixed_exp); + } + } + + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + WMACoef *coefs1; + float *coefs, *exponents, mult; + int i, n; + + coefs1 = s->coefs1[ch]; + exponents = s->exponents[ch]; + mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; + mult *= mdct_norm; + coefs = src_coefs[ch]; + if (s->use_noise_coding && 0) { + av_assert0(0); //FIXME not implemented + } else { + coefs += s->coefs_start; + n = nb_coefs[ch]; + for(i = 0;i < n; i++){ + double t= *coefs++ / (exponents[i] * mult); + if(t<-32768 || t>32767) + return -1; + + coefs1[i] = lrint(t); + } + } + } + } + + v = 0; + for (ch = 0; ch < s->avctx->channels; ch++) { + int a = s->channel_coded[ch]; + put_bits(&s->pb, 1, a); + v |= a; + } + + if (!v) + return 1; + + for(v= total_gain-1; v>=127; v-= 127) + put_bits(&s->pb, 7, 127); + put_bits(&s->pb, 7, v); + + coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); + + if (s->use_noise_coding) { + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + int i, n; + n = s->exponent_high_sizes[bsize]; + for(i=0;ipb, 1, s->high_band_coded[ch][i]= 0); + if (0) + nb_coefs[ch] -= s->exponent_high_bands[bsize][i]; + } + } + } + } + + parse_exponents = 1; + if (s->block_len_bits != s->frame_len_bits) { + put_bits(&s->pb, 1, parse_exponents); + } + + if (parse_exponents) { + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + if (s->use_exp_vlc) { + encode_exp_vlc(s, ch, fixed_exp); + } else { + av_assert0(0); //FIXME not implemented +// encode_exp_lsp(s, ch); + } + } + } + } else { + av_assert0(0); //FIXME not implemented + } + + for (ch = 0; ch < s->avctx->channels; ch++) { + if (s->channel_coded[ch]) { + int run, tindex; + WMACoef *ptr, *eptr; + tindex = (ch == 1 && s->ms_stereo); + ptr = &s->coefs1[ch][0]; + eptr = ptr + nb_coefs[ch]; + + run=0; + for(;ptr < eptr; ptr++){ + if(*ptr){ + int level= *ptr; + int abs_level= FFABS(level); + int code= 0; + if(abs_level <= s->coef_vlcs[tindex]->max_level){ + if(run < s->coef_vlcs[tindex]->levels[abs_level-1]) + code= run + s->int_table[tindex][abs_level-1]; + } + + av_assert2(code < s->coef_vlcs[tindex]->n); + put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[code], s->coef_vlcs[tindex]->huffcodes[code]); + + if(code == 0){ + if(1<pb, coef_nb_bits, abs_level); + put_bits(&s->pb, s->frame_len_bits, run); + } + put_bits(&s->pb, 1, level < 0); //FIXME the sign is fliped somewhere + run=0; + }else{ + run++; + } + } + if(run) + put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[1], s->coef_vlcs[tindex]->huffcodes[1]); + } + if (s->version == 1 && s->avctx->channels >= 2) { + avpriv_align_put_bits(&s->pb); + } + } + return 0; +} + +static int encode_frame(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], uint8_t *buf, int buf_size, int total_gain){ + init_put_bits(&s->pb, buf, buf_size); + + if (s->use_bit_reservoir) { + av_assert0(0);//FIXME not implemented + }else{ + if(encode_block(s, src_coefs, total_gain) < 0) + return INT_MAX; + } + + avpriv_align_put_bits(&s->pb); + + return put_bits_count(&s->pb) / 8 - s->avctx->block_align; +} + +static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + WMACodecContext *s = avctx->priv_data; + int i, total_gain, ret, error; + + s->block_len_bits= s->frame_len_bits; //required by non variable block len + s->block_len = 1 << s->block_len_bits; + + apply_window_and_mdct(avctx, frame); + + if (s->ms_stereo) { + float a, b; + int i; + + for(i = 0; i < s->block_len; i++) { + a = s->coefs[0][i]*0.5; + b = s->coefs[1][i]*0.5; + s->coefs[0][i] = a + b; + s->coefs[1][i] = a - b; + } + } + + if ((ret = ff_alloc_packet2(avctx, avpkt, 2 * MAX_CODED_SUPERFRAME_SIZE)) < 0) + return ret; + + total_gain= 128; + for(i=64; i; i>>=1){ + error = encode_frame(s, s->coefs, avpkt->data, avpkt->size, + total_gain - i); + if(error<=0) + total_gain-= i; + } + + while(total_gain <= 128 && error > 0) + error = encode_frame(s, s->coefs, avpkt->data, avpkt->size, total_gain++); + av_assert0((put_bits_count(&s->pb) & 7) == 0); + i= avctx->block_align - (put_bits_count(&s->pb)+7)/8; + av_assert0(i>=0); + while(i--) + put_bits(&s->pb, 8, 'N'); + + flush_put_bits(&s->pb); + av_assert0(put_bits_ptr(&s->pb) - s->pb.buf == avctx->block_align); + + if (frame->pts != AV_NOPTS_VALUE) + avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->delay); + + avpkt->size = avctx->block_align; + *got_packet_ptr = 1; + return 0; +} + +#if CONFIG_WMAV1_ENCODER +AVCodec ff_wmav1_encoder = { + .name = "wmav1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMAV1, + .priv_data_size = sizeof(WMACodecContext), + .init = encode_init, + .encode2 = encode_superframe, + .close = ff_wma_end, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), +}; +#endif +#if CONFIG_WMAV2_ENCODER +AVCodec ff_wmav2_encoder = { + .name = "wmav2", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMAV2, + .priv_data_size = sizeof(WMACodecContext), + .init = encode_init, + .encode2 = encode_superframe, + .close = ff_wma_end, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), +}; +#endif diff --git a/ffmpeg/libavcodec/wmalosslessdec.c b/ffmpeg/libavcodec/wmalosslessdec.c new file mode 100644 index 0000000..90a0109 --- /dev/null +++ b/ffmpeg/libavcodec/wmalosslessdec.c @@ -0,0 +1,1300 @@ +/* + * Windows Media Audio Lossless decoder + * Copyright (c) 2007 Baptiste Coudurier, Benjamin Larsson, Ulion + * Copyright (c) 2008 - 2011 Sascha Sommer, Benjamin Larsson + * Copyright (c) 2011 Andreas Öman + * Copyright (c) 2011 - 2012 Mashiat Sarker Shakkhar + * + * 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 "libavutil/attributes.h" +#include "libavutil/avassert.h" + +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "put_bits.h" +#include "wma.h" +#include "wma_common.h" + +/** current decoder limitations */ +#define WMALL_MAX_CHANNELS 8 ///< max number of handled channels +#define MAX_SUBFRAMES 32 ///< max number of subframes per channel +#define MAX_BANDS 29 ///< max number of scale factor bands +#define MAX_FRAMESIZE 32768 ///< maximum compressed frame size +#define MAX_ORDER 256 + +#define WMALL_BLOCK_MIN_BITS 6 ///< log2 of min block size +#define WMALL_BLOCK_MAX_BITS 14 ///< log2 of max block size +#define WMALL_BLOCK_MAX_SIZE (1 << WMALL_BLOCK_MAX_BITS) ///< maximum block size +#define WMALL_BLOCK_SIZES (WMALL_BLOCK_MAX_BITS - WMALL_BLOCK_MIN_BITS + 1) ///< possible block sizes + + +/** + * @brief frame-specific decoder context for a single channel + */ +typedef struct { + int16_t prev_block_len; ///< length of the previous block + uint8_t transmit_coefs; + uint8_t num_subframes; + uint16_t subframe_len[MAX_SUBFRAMES]; ///< subframe length in samples + uint16_t subframe_offsets[MAX_SUBFRAMES]; ///< subframe positions in the current frame + uint8_t cur_subframe; ///< current subframe number + uint16_t decoded_samples; ///< number of already processed samples + int quant_step; ///< quantization step for the current subframe + int transient_counter; ///< number of transient samples from the beginning of the transient zone +} WmallChannelCtx; + +/** + * @brief main decoder context + */ +typedef struct WmallDecodeCtx { + /* generic decoder variables */ + AVCodecContext *avctx; + AVFrame frame; + uint8_t frame_data[MAX_FRAMESIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< compressed frame data + PutBitContext pb; ///< context for filling the frame_data buffer + + /* frame size dependent frame information (set during initialization) */ + uint32_t decode_flags; ///< used compression features + int len_prefix; ///< frame is prefixed with its length + int dynamic_range_compression; ///< frame contains DRC data + uint8_t bits_per_sample; ///< integer audio sample size for the unscaled IMDCT output (used to scale to [-1.0, 1.0]) + uint16_t samples_per_frame; ///< number of samples to output + uint16_t log2_frame_size; + int8_t num_channels; ///< number of channels in the stream (same as AVCodecContext.num_channels) + int8_t lfe_channel; ///< lfe channel index + uint8_t max_num_subframes; + uint8_t subframe_len_bits; ///< number of bits used for the subframe length + uint8_t max_subframe_len_bit; ///< flag indicating that the subframe is of maximum size when the first subframe length bit is 1 + uint16_t min_samples_per_subframe; + + /* packet decode state */ + GetBitContext pgb; ///< bitstream reader context for the packet + int next_packet_start; ///< start offset of the next WMA packet in the demuxer packet + uint8_t packet_offset; ///< offset to the frame in the packet + uint8_t packet_sequence_number; ///< current packet number + int num_saved_bits; ///< saved number of bits + int frame_offset; ///< frame offset in the bit reservoir + int subframe_offset; ///< subframe offset in the bit reservoir + uint8_t packet_loss; ///< set in case of bitstream error + uint8_t packet_done; ///< set when a packet is fully decoded + + /* frame decode state */ + uint32_t frame_num; ///< current frame number (not used for decoding) + GetBitContext gb; ///< bitstream reader context + int buf_bit_size; ///< buffer size in bits + int16_t *samples_16[WMALL_MAX_CHANNELS]; ///< current samplebuffer pointer (16-bit) + int32_t *samples_32[WMALL_MAX_CHANNELS]; ///< current samplebuffer pointer (24-bit) + uint8_t drc_gain; ///< gain for the DRC tool + int8_t skip_frame; ///< skip output step + int8_t parsed_all_subframes; ///< all subframes decoded? + + /* subframe/block decode state */ + int16_t subframe_len; ///< current subframe length + int8_t channels_for_cur_subframe; ///< number of channels that contain the subframe + int8_t channel_indexes_for_cur_subframe[WMALL_MAX_CHANNELS]; + + WmallChannelCtx channel[WMALL_MAX_CHANNELS]; ///< per channel data + + // WMA Lossless-specific + + uint8_t do_arith_coding; + uint8_t do_ac_filter; + uint8_t do_inter_ch_decorr; + uint8_t do_mclms; + uint8_t do_lpc; + + int8_t acfilter_order; + int8_t acfilter_scaling; + int64_t acfilter_coeffs[16]; + int acfilter_prevvalues[WMALL_MAX_CHANNELS][16]; + + int8_t mclms_order; + int8_t mclms_scaling; + int16_t mclms_coeffs[128]; + int16_t mclms_coeffs_cur[4]; + int16_t mclms_prevvalues[WMALL_MAX_CHANNELS * 2 * 32]; + int16_t mclms_updates[WMALL_MAX_CHANNELS * 2 * 32]; + int mclms_recent; + + int movave_scaling; + int quant_stepsize; + + struct { + int order; + int scaling; + int coefsend; + int bitsend; + int16_t coefs[MAX_ORDER]; + int16_t lms_prevvalues[MAX_ORDER * 2]; + int16_t lms_updates[MAX_ORDER * 2]; + int recent; + } cdlms[WMALL_MAX_CHANNELS][9]; + + int cdlms_ttl[WMALL_MAX_CHANNELS]; + + int bV3RTM; + + int is_channel_coded[WMALL_MAX_CHANNELS]; + int update_speed[WMALL_MAX_CHANNELS]; + + int transient[WMALL_MAX_CHANNELS]; + int transient_pos[WMALL_MAX_CHANNELS]; + int seekable_tile; + + int ave_sum[WMALL_MAX_CHANNELS]; + + int channel_residues[WMALL_MAX_CHANNELS][WMALL_BLOCK_MAX_SIZE]; + + int lpc_coefs[WMALL_MAX_CHANNELS][40]; + int lpc_order; + int lpc_scaling; + int lpc_intbits; + + int channel_coeffs[WMALL_MAX_CHANNELS][WMALL_BLOCK_MAX_SIZE]; +} WmallDecodeCtx; + + +static av_cold int decode_init(AVCodecContext *avctx) +{ + WmallDecodeCtx *s = avctx->priv_data; + uint8_t *edata_ptr = avctx->extradata; + unsigned int channel_mask; + int i, log2_max_num_subframes; + + s->avctx = avctx; + init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); + + if (avctx->extradata_size >= 18) { + s->decode_flags = AV_RL16(edata_ptr + 14); + channel_mask = AV_RL32(edata_ptr + 2); + s->bits_per_sample = AV_RL16(edata_ptr); + if (s->bits_per_sample == 16) + avctx->sample_fmt = AV_SAMPLE_FMT_S16P; + else if (s->bits_per_sample == 24) { + avctx->sample_fmt = AV_SAMPLE_FMT_S32P; + avpriv_report_missing_feature(avctx, "Bit-depth higher than 16"); + return AVERROR_PATCHWELCOME; + } else { + av_log(avctx, AV_LOG_ERROR, "Unknown bit-depth: %d\n", + s->bits_per_sample); + return AVERROR_INVALIDDATA; + } + /* dump the extradata */ + for (i = 0; i < avctx->extradata_size; i++) + av_dlog(avctx, "[%x] ", avctx->extradata[i]); + av_dlog(avctx, "\n"); + + } else { + avpriv_request_sample(avctx, "Unsupported extradata size"); + return AVERROR_PATCHWELCOME; + } + + /* generic init */ + s->log2_frame_size = av_log2(avctx->block_align) + 4; + + /* frame info */ + s->skip_frame = 1; /* skip first frame */ + s->packet_loss = 1; + s->len_prefix = s->decode_flags & 0x40; + + /* get frame len */ + s->samples_per_frame = 1 << ff_wma_get_frame_len_bits(avctx->sample_rate, + 3, s->decode_flags); + av_assert0(s->samples_per_frame <= WMALL_BLOCK_MAX_SIZE); + + /* init previous block len */ + for (i = 0; i < avctx->channels; i++) + s->channel[i].prev_block_len = s->samples_per_frame; + + /* subframe info */ + log2_max_num_subframes = (s->decode_flags & 0x38) >> 3; + s->max_num_subframes = 1 << log2_max_num_subframes; + s->max_subframe_len_bit = 0; + s->subframe_len_bits = av_log2(log2_max_num_subframes) + 1; + + s->min_samples_per_subframe = s->samples_per_frame / s->max_num_subframes; + s->dynamic_range_compression = s->decode_flags & 0x80; + s->bV3RTM = s->decode_flags & 0x100; + + if (s->max_num_subframes > MAX_SUBFRAMES) { + av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n", + s->max_num_subframes); + return AVERROR_INVALIDDATA; + } + + s->num_channels = avctx->channels; + + /* extract lfe channel position */ + s->lfe_channel = -1; + + if (channel_mask & 8) { + unsigned int mask; + for (mask = 1; mask < 16; mask <<= 1) + if (channel_mask & mask) + ++s->lfe_channel; + } + + if (s->num_channels < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", + s->num_channels); + return AVERROR_INVALIDDATA; + } else if (s->num_channels > WMALL_MAX_CHANNELS) { + avpriv_request_sample(avctx, + "More than %d channels", WMALL_MAX_CHANNELS); + return AVERROR_PATCHWELCOME; + } + + avcodec_get_frame_defaults(&s->frame); + avctx->coded_frame = &s->frame; + avctx->channel_layout = channel_mask; + return 0; +} + +/** + * @brief Decode the subframe length. + * @param s context + * @param offset sample offset in the frame + * @return decoded subframe length on success, < 0 in case of an error + */ +static int decode_subframe_length(WmallDecodeCtx *s, int offset) +{ + int frame_len_ratio, subframe_len, len; + + /* no need to read from the bitstream when only one length is possible */ + if (offset == s->samples_per_frame - s->min_samples_per_subframe) + return s->min_samples_per_subframe; + + len = av_log2(s->max_num_subframes - 1) + 1; + frame_len_ratio = get_bits(&s->gb, len); + subframe_len = s->min_samples_per_subframe * (frame_len_ratio + 1); + + /* sanity check the length */ + if (subframe_len < s->min_samples_per_subframe || + subframe_len > s->samples_per_frame) { + av_log(s->avctx, AV_LOG_ERROR, "broken frame: subframe_len %i\n", + subframe_len); + return AVERROR_INVALIDDATA; + } + return subframe_len; +} + +/** + * @brief Decode how the data in the frame is split into subframes. + * Every WMA frame contains the encoded data for a fixed number of + * samples per channel. The data for every channel might be split + * into several subframes. This function will reconstruct the list of + * subframes for every channel. + * + * If the subframes are not evenly split, the algorithm estimates the + * channels with the lowest number of total samples. + * Afterwards, for each of these channels a bit is read from the + * bitstream that indicates if the channel contains a subframe with the + * next subframe size that is going to be read from the bitstream or not. + * If a channel contains such a subframe, the subframe size gets added to + * the channel's subframe list. + * The algorithm repeats these steps until the frame is properly divided + * between the individual channels. + * + * @param s context + * @return 0 on success, < 0 in case of an error + */ +static int decode_tilehdr(WmallDecodeCtx *s) +{ + uint16_t num_samples[WMALL_MAX_CHANNELS] = { 0 }; /* sum of samples for all currently known subframes of a channel */ + uint8_t contains_subframe[WMALL_MAX_CHANNELS]; /* flag indicating if a channel contains the current subframe */ + int channels_for_cur_subframe = s->num_channels; /* number of channels that contain the current subframe */ + int fixed_channel_layout = 0; /* flag indicating that all channels use the same subfra2me offsets and sizes */ + int min_channel_len = 0; /* smallest sum of samples (channels with this length will be processed first) */ + int c, tile_aligned; + + /* reset tiling information */ + for (c = 0; c < s->num_channels; c++) + s->channel[c].num_subframes = 0; + + tile_aligned = get_bits1(&s->gb); + if (s->max_num_subframes == 1 || tile_aligned) + fixed_channel_layout = 1; + + /* loop until the frame data is split between the subframes */ + do { + int subframe_len, in_use = 0; + + /* check which channels contain the subframe */ + for (c = 0; c < s->num_channels; c++) { + if (num_samples[c] == min_channel_len) { + if (fixed_channel_layout || channels_for_cur_subframe == 1 || + (min_channel_len == s->samples_per_frame - s->min_samples_per_subframe)) { + contains_subframe[c] = in_use = 1; + } else { + if (get_bits1(&s->gb)) + contains_subframe[c] = in_use = 1; + } + } else + contains_subframe[c] = 0; + } + + if (!in_use) { + av_log(s->avctx, AV_LOG_ERROR, + "Found empty subframe\n"); + return AVERROR_INVALIDDATA; + } + + /* get subframe length, subframe_len == 0 is not allowed */ + if ((subframe_len = decode_subframe_length(s, min_channel_len)) <= 0) + return AVERROR_INVALIDDATA; + /* add subframes to the individual channels and find new min_channel_len */ + min_channel_len += subframe_len; + for (c = 0; c < s->num_channels; c++) { + WmallChannelCtx *chan = &s->channel[c]; + + if (contains_subframe[c]) { + if (chan->num_subframes >= MAX_SUBFRAMES) { + av_log(s->avctx, AV_LOG_ERROR, + "broken frame: num subframes > 31\n"); + return AVERROR_INVALIDDATA; + } + chan->subframe_len[chan->num_subframes] = subframe_len; + num_samples[c] += subframe_len; + ++chan->num_subframes; + if (num_samples[c] > s->samples_per_frame) { + av_log(s->avctx, AV_LOG_ERROR, "broken frame: " + "channel len(%d) > samples_per_frame(%d)\n", + num_samples[c], s->samples_per_frame); + return AVERROR_INVALIDDATA; + } + } else if (num_samples[c] <= min_channel_len) { + if (num_samples[c] < min_channel_len) { + channels_for_cur_subframe = 0; + min_channel_len = num_samples[c]; + } + ++channels_for_cur_subframe; + } + } + } while (min_channel_len < s->samples_per_frame); + + for (c = 0; c < s->num_channels; c++) { + int i, offset = 0; + for (i = 0; i < s->channel[c].num_subframes; i++) { + s->channel[c].subframe_offsets[i] = offset; + offset += s->channel[c].subframe_len[i]; + } + } + + return 0; +} + +static void decode_ac_filter(WmallDecodeCtx *s) +{ + int i; + s->acfilter_order = get_bits(&s->gb, 4) + 1; + s->acfilter_scaling = get_bits(&s->gb, 4); + + for (i = 0; i < s->acfilter_order; i++) + s->acfilter_coeffs[i] = (s->acfilter_scaling ? + get_bits(&s->gb, s->acfilter_scaling) : 0) + 1; +} + +static void decode_mclms(WmallDecodeCtx *s) +{ + s->mclms_order = (get_bits(&s->gb, 4) + 1) * 2; + s->mclms_scaling = get_bits(&s->gb, 4); + if (get_bits1(&s->gb)) { + int i, send_coef_bits; + int cbits = av_log2(s->mclms_scaling + 1); + if (1 << cbits < s->mclms_scaling + 1) + cbits++; + + send_coef_bits = (cbits ? get_bits(&s->gb, cbits) : 0) + 2; + + for (i = 0; i < s->mclms_order * s->num_channels * s->num_channels; i++) + s->mclms_coeffs[i] = get_bits(&s->gb, send_coef_bits); + + for (i = 0; i < s->num_channels; i++) { + int c; + for (c = 0; c < i; c++) + s->mclms_coeffs_cur[i * s->num_channels + c] = get_bits(&s->gb, send_coef_bits); + } + } +} + +static int decode_cdlms(WmallDecodeCtx *s) +{ + int c, i; + int cdlms_send_coef = get_bits1(&s->gb); + + for (c = 0; c < s->num_channels; c++) { + s->cdlms_ttl[c] = get_bits(&s->gb, 3) + 1; + for (i = 0; i < s->cdlms_ttl[c]; i++) { + s->cdlms[c][i].order = (get_bits(&s->gb, 7) + 1) * 8; + if (s->cdlms[c][i].order > MAX_ORDER) { + av_log(s->avctx, AV_LOG_ERROR, + "Order[%d][%d] %d > max (%d), not supported\n", + c, i, s->cdlms[c][i].order, MAX_ORDER); + s->cdlms[0][0].order = 0; + return AVERROR_INVALIDDATA; + } + } + + for (i = 0; i < s->cdlms_ttl[c]; i++) + s->cdlms[c][i].scaling = get_bits(&s->gb, 4); + + if (cdlms_send_coef) { + for (i = 0; i < s->cdlms_ttl[c]; i++) { + int cbits, shift_l, shift_r, j; + cbits = av_log2(s->cdlms[c][i].order); + if ((1 << cbits) < s->cdlms[c][i].order) + cbits++; + s->cdlms[c][i].coefsend = get_bits(&s->gb, cbits) + 1; + + cbits = av_log2(s->cdlms[c][i].scaling + 1); + if ((1 << cbits) < s->cdlms[c][i].scaling + 1) + cbits++; + + s->cdlms[c][i].bitsend = get_bits(&s->gb, cbits) + 2; + shift_l = 32 - s->cdlms[c][i].bitsend; + shift_r = 32 - s->cdlms[c][i].scaling - 2; + for (j = 0; j < s->cdlms[c][i].coefsend; j++) + s->cdlms[c][i].coefs[j] = + (get_bits(&s->gb, s->cdlms[c][i].bitsend) << shift_l) >> shift_r; + } + } + } + + return 0; +} + +static int decode_channel_residues(WmallDecodeCtx *s, int ch, int tile_size) +{ + int i = 0; + unsigned int ave_mean; + s->transient[ch] = get_bits1(&s->gb); + if (s->transient[ch]) { + s->transient_pos[ch] = get_bits(&s->gb, av_log2(tile_size)); + if (s->transient_pos[ch]) + s->transient[ch] = 0; + s->channel[ch].transient_counter = + FFMAX(s->channel[ch].transient_counter, s->samples_per_frame / 2); + } else if (s->channel[ch].transient_counter) + s->transient[ch] = 1; + + if (s->seekable_tile) { + ave_mean = get_bits(&s->gb, s->bits_per_sample); + s->ave_sum[ch] = ave_mean << (s->movave_scaling + 1); + } + + if (s->seekable_tile) { + if (s->do_inter_ch_decorr) + s->channel_residues[ch][0] = get_sbits_long(&s->gb, s->bits_per_sample + 1); + else + s->channel_residues[ch][0] = get_sbits_long(&s->gb, s->bits_per_sample); + i++; + } + for (; i < tile_size; i++) { + int quo = 0, rem, rem_bits, residue; + while(get_bits1(&s->gb)) { + quo++; + if (get_bits_left(&s->gb) <= 0) + return -1; + } + if (quo >= 32) + quo += get_bits_long(&s->gb, get_bits(&s->gb, 5) + 1); + + ave_mean = (s->ave_sum[ch] + (1 << s->movave_scaling)) >> (s->movave_scaling + 1); + if (ave_mean <= 1) + residue = quo; + else { + rem_bits = av_ceil_log2(ave_mean); + rem = get_bits_long(&s->gb, rem_bits); + residue = (quo << rem_bits) + rem; + } + + s->ave_sum[ch] = residue + s->ave_sum[ch] - + (s->ave_sum[ch] >> s->movave_scaling); + + if (residue & 1) + residue = -(residue >> 1) - 1; + else + residue = residue >> 1; + s->channel_residues[ch][i] = residue; + } + + return 0; + +} + +static void decode_lpc(WmallDecodeCtx *s) +{ + int ch, i, cbits; + s->lpc_order = get_bits(&s->gb, 5) + 1; + s->lpc_scaling = get_bits(&s->gb, 4); + s->lpc_intbits = get_bits(&s->gb, 3) + 1; + cbits = s->lpc_scaling + s->lpc_intbits; + for (ch = 0; ch < s->num_channels; ch++) + for (i = 0; i < s->lpc_order; i++) + s->lpc_coefs[ch][i] = get_sbits(&s->gb, cbits); +} + +static void clear_codec_buffers(WmallDecodeCtx *s) +{ + int ich, ilms; + + memset(s->acfilter_coeffs, 0, sizeof(s->acfilter_coeffs)); + memset(s->acfilter_prevvalues, 0, sizeof(s->acfilter_prevvalues)); + memset(s->lpc_coefs, 0, sizeof(s->lpc_coefs)); + + memset(s->mclms_coeffs, 0, sizeof(s->mclms_coeffs)); + memset(s->mclms_coeffs_cur, 0, sizeof(s->mclms_coeffs_cur)); + memset(s->mclms_prevvalues, 0, sizeof(s->mclms_prevvalues)); + memset(s->mclms_updates, 0, sizeof(s->mclms_updates)); + + for (ich = 0; ich < s->num_channels; ich++) { + for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++) { + memset(s->cdlms[ich][ilms].coefs, 0, + sizeof(s->cdlms[ich][ilms].coefs)); + memset(s->cdlms[ich][ilms].lms_prevvalues, 0, + sizeof(s->cdlms[ich][ilms].lms_prevvalues)); + memset(s->cdlms[ich][ilms].lms_updates, 0, + sizeof(s->cdlms[ich][ilms].lms_updates)); + } + s->ave_sum[ich] = 0; + } +} + +/** + * @brief Reset filter parameters and transient area at new seekable tile. + */ +static void reset_codec(WmallDecodeCtx *s) +{ + int ich, ilms; + s->mclms_recent = s->mclms_order * s->num_channels; + for (ich = 0; ich < s->num_channels; ich++) { + for (ilms = 0; ilms < s->cdlms_ttl[ich]; ilms++) + s->cdlms[ich][ilms].recent = s->cdlms[ich][ilms].order; + /* first sample of a seekable subframe is considered as the starting of + a transient area which is samples_per_frame samples long */ + s->channel[ich].transient_counter = s->samples_per_frame; + s->transient[ich] = 1; + s->transient_pos[ich] = 0; + } +} + +static void mclms_update(WmallDecodeCtx *s, int icoef, int *pred) +{ + int i, j, ich, pred_error; + int order = s->mclms_order; + int num_channels = s->num_channels; + int range = 1 << (s->bits_per_sample - 1); + + for (ich = 0; ich < num_channels; ich++) { + pred_error = s->channel_residues[ich][icoef] - pred[ich]; + if (pred_error > 0) { + for (i = 0; i < order * num_channels; i++) + s->mclms_coeffs[i + ich * order * num_channels] += + s->mclms_updates[s->mclms_recent + i]; + for (j = 0; j < ich; j++) { + if (s->channel_residues[j][icoef] > 0) + s->mclms_coeffs_cur[ich * num_channels + j] += 1; + else if (s->channel_residues[j][icoef] < 0) + s->mclms_coeffs_cur[ich * num_channels + j] -= 1; + } + } else if (pred_error < 0) { + for (i = 0; i < order * num_channels; i++) + s->mclms_coeffs[i + ich * order * num_channels] -= + s->mclms_updates[s->mclms_recent + i]; + for (j = 0; j < ich; j++) { + if (s->channel_residues[j][icoef] > 0) + s->mclms_coeffs_cur[ich * num_channels + j] -= 1; + else if (s->channel_residues[j][icoef] < 0) + s->mclms_coeffs_cur[ich * num_channels + j] += 1; + } + } + } + + for (ich = num_channels - 1; ich >= 0; ich--) { + s->mclms_recent--; + s->mclms_prevvalues[s->mclms_recent] = s->channel_residues[ich][icoef]; + if (s->channel_residues[ich][icoef] > range - 1) + s->mclms_prevvalues[s->mclms_recent] = range - 1; + else if (s->channel_residues[ich][icoef] < -range) + s->mclms_prevvalues[s->mclms_recent] = -range; + + s->mclms_updates[s->mclms_recent] = 0; + if (s->channel_residues[ich][icoef] > 0) + s->mclms_updates[s->mclms_recent] = 1; + else if (s->channel_residues[ich][icoef] < 0) + s->mclms_updates[s->mclms_recent] = -1; + } + + if (s->mclms_recent == 0) { + memcpy(&s->mclms_prevvalues[order * num_channels], + s->mclms_prevvalues, + 2 * order * num_channels); + memcpy(&s->mclms_updates[order * num_channels], + s->mclms_updates, + 2 * order * num_channels); + s->mclms_recent = num_channels * order; + } +} + +static void mclms_predict(WmallDecodeCtx *s, int icoef, int *pred) +{ + int ich, i; + int order = s->mclms_order; + int num_channels = s->num_channels; + + for (ich = 0; ich < num_channels; ich++) { + pred[ich] = 0; + if (!s->is_channel_coded[ich]) + continue; + for (i = 0; i < order * num_channels; i++) + pred[ich] += s->mclms_prevvalues[i + s->mclms_recent] * + s->mclms_coeffs[i + order * num_channels * ich]; + for (i = 0; i < ich; i++) + pred[ich] += s->channel_residues[i][icoef] * + s->mclms_coeffs_cur[i + num_channels * ich]; + pred[ich] += 1 << s->mclms_scaling - 1; + pred[ich] >>= s->mclms_scaling; + s->channel_residues[ich][icoef] += pred[ich]; + } +} + +static void revert_mclms(WmallDecodeCtx *s, int tile_size) +{ + int icoef, pred[WMALL_MAX_CHANNELS] = { 0 }; + for (icoef = 0; icoef < tile_size; icoef++) { + mclms_predict(s, icoef, pred); + mclms_update(s, icoef, pred); + } +} + +static int lms_predict(WmallDecodeCtx *s, int ich, int ilms) +{ + int pred = 0, icoef; + int recent = s->cdlms[ich][ilms].recent; + + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + pred += s->cdlms[ich][ilms].coefs[icoef] * + s->cdlms[ich][ilms].lms_prevvalues[icoef + recent]; + + return pred; +} + +static void lms_update(WmallDecodeCtx *s, int ich, int ilms, + int input, int residue) +{ + int icoef; + int recent = s->cdlms[ich][ilms].recent; + int range = 1 << s->bits_per_sample - 1; + + if (residue < 0) { + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + s->cdlms[ich][ilms].coefs[icoef] -= + s->cdlms[ich][ilms].lms_updates[icoef + recent]; + } else if (residue > 0) { + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + s->cdlms[ich][ilms].coefs[icoef] += + s->cdlms[ich][ilms].lms_updates[icoef + recent]; + } + + if (recent) + recent--; + else { + memcpy(&s->cdlms[ich][ilms].lms_prevvalues[s->cdlms[ich][ilms].order], + s->cdlms[ich][ilms].lms_prevvalues, + 2 * s->cdlms[ich][ilms].order); + memcpy(&s->cdlms[ich][ilms].lms_updates[s->cdlms[ich][ilms].order], + s->cdlms[ich][ilms].lms_updates, + 2 * s->cdlms[ich][ilms].order); + recent = s->cdlms[ich][ilms].order - 1; + } + + s->cdlms[ich][ilms].lms_prevvalues[recent] = av_clip(input, -range, range - 1); + if (!input) + s->cdlms[ich][ilms].lms_updates[recent] = 0; + else if (input < 0) + s->cdlms[ich][ilms].lms_updates[recent] = -s->update_speed[ich]; + else + s->cdlms[ich][ilms].lms_updates[recent] = s->update_speed[ich]; + + s->cdlms[ich][ilms].lms_updates[recent + (s->cdlms[ich][ilms].order >> 4)] >>= 2; + s->cdlms[ich][ilms].lms_updates[recent + (s->cdlms[ich][ilms].order >> 3)] >>= 1; + s->cdlms[ich][ilms].recent = recent; +} + +static void use_high_update_speed(WmallDecodeCtx *s, int ich) +{ + int ilms, recent, icoef; + for (ilms = s->cdlms_ttl[ich] - 1; ilms >= 0; ilms--) { + recent = s->cdlms[ich][ilms].recent; + if (s->update_speed[ich] == 16) + continue; + if (s->bV3RTM) { + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + s->cdlms[ich][ilms].lms_updates[icoef + recent] *= 2; + } else { + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + s->cdlms[ich][ilms].lms_updates[icoef] *= 2; + } + } + s->update_speed[ich] = 16; +} + +static void use_normal_update_speed(WmallDecodeCtx *s, int ich) +{ + int ilms, recent, icoef; + for (ilms = s->cdlms_ttl[ich] - 1; ilms >= 0; ilms--) { + recent = s->cdlms[ich][ilms].recent; + if (s->update_speed[ich] == 8) + continue; + if (s->bV3RTM) + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + s->cdlms[ich][ilms].lms_updates[icoef + recent] /= 2; + else + for (icoef = 0; icoef < s->cdlms[ich][ilms].order; icoef++) + s->cdlms[ich][ilms].lms_updates[icoef] /= 2; + } + s->update_speed[ich] = 8; +} + +static void revert_cdlms(WmallDecodeCtx *s, int ch, + int coef_begin, int coef_end) +{ + int icoef, pred, ilms, num_lms, residue, input; + + num_lms = s->cdlms_ttl[ch]; + for (ilms = num_lms - 1; ilms >= 0; ilms--) { + for (icoef = coef_begin; icoef < coef_end; icoef++) { + pred = 1 << (s->cdlms[ch][ilms].scaling - 1); + residue = s->channel_residues[ch][icoef]; + pred += lms_predict(s, ch, ilms); + input = residue + (pred >> s->cdlms[ch][ilms].scaling); + lms_update(s, ch, ilms, input, residue); + s->channel_residues[ch][icoef] = input; + } + } +} + +static void revert_inter_ch_decorr(WmallDecodeCtx *s, int tile_size) +{ + if (s->num_channels != 2) + return; + else if (s->is_channel_coded[0] || s->is_channel_coded[1]) { + int icoef; + for (icoef = 0; icoef < tile_size; icoef++) { + s->channel_residues[0][icoef] -= s->channel_residues[1][icoef] >> 1; + s->channel_residues[1][icoef] += s->channel_residues[0][icoef]; + } + } +} + +static void revert_acfilter(WmallDecodeCtx *s, int tile_size) +{ + int ich, pred, i, j; + int64_t *filter_coeffs = s->acfilter_coeffs; + int scaling = s->acfilter_scaling; + int order = s->acfilter_order; + + for (ich = 0; ich < s->num_channels; ich++) { + int *prevvalues = s->acfilter_prevvalues[ich]; + for (i = 0; i < order; i++) { + pred = 0; + for (j = 0; j < order; j++) { + if (i <= j) + pred += filter_coeffs[j] * prevvalues[j - i]; + else + pred += s->channel_residues[ich][i - j - 1] * filter_coeffs[j]; + } + pred >>= scaling; + s->channel_residues[ich][i] += pred; + } + for (i = order; i < tile_size; i++) { + pred = 0; + for (j = 0; j < order; j++) + pred += s->channel_residues[ich][i - j - 1] * filter_coeffs[j]; + pred >>= scaling; + s->channel_residues[ich][i] += pred; + } + for (j = 0; j < order; j++) + prevvalues[j] = s->channel_residues[ich][tile_size - j - 1]; + } +} + +static int decode_subframe(WmallDecodeCtx *s) +{ + int offset = s->samples_per_frame; + int subframe_len = s->samples_per_frame; + int total_samples = s->samples_per_frame * s->num_channels; + int i, j, rawpcm_tile, padding_zeroes, res; + + s->subframe_offset = get_bits_count(&s->gb); + + /* reset channel context and find the next block offset and size + == the next block of the channel with the smallest number of + decoded samples */ + for (i = 0; i < s->num_channels; i++) { + if (offset > s->channel[i].decoded_samples) { + offset = s->channel[i].decoded_samples; + subframe_len = + s->channel[i].subframe_len[s->channel[i].cur_subframe]; + } + } + + /* get a list of all channels that contain the estimated block */ + s->channels_for_cur_subframe = 0; + for (i = 0; i < s->num_channels; i++) { + const int cur_subframe = s->channel[i].cur_subframe; + /* subtract already processed samples */ + total_samples -= s->channel[i].decoded_samples; + + /* and count if there are multiple subframes that match our profile */ + if (offset == s->channel[i].decoded_samples && + subframe_len == s->channel[i].subframe_len[cur_subframe]) { + total_samples -= s->channel[i].subframe_len[cur_subframe]; + s->channel[i].decoded_samples += + s->channel[i].subframe_len[cur_subframe]; + s->channel_indexes_for_cur_subframe[s->channels_for_cur_subframe] = i; + ++s->channels_for_cur_subframe; + } + } + + /* check if the frame will be complete after processing the + estimated block */ + if (!total_samples) + s->parsed_all_subframes = 1; + + + s->seekable_tile = get_bits1(&s->gb); + if (s->seekable_tile) { + clear_codec_buffers(s); + + s->do_arith_coding = get_bits1(&s->gb); + if (s->do_arith_coding) { + avpriv_request_sample(s->avctx, "Arithmetic coding"); + return AVERROR_PATCHWELCOME; + } + s->do_ac_filter = get_bits1(&s->gb); + s->do_inter_ch_decorr = get_bits1(&s->gb); + s->do_mclms = get_bits1(&s->gb); + + if (s->do_ac_filter) + decode_ac_filter(s); + + if (s->do_mclms) + decode_mclms(s); + + if ((res = decode_cdlms(s)) < 0) + return res; + s->movave_scaling = get_bits(&s->gb, 3); + s->quant_stepsize = get_bits(&s->gb, 8) + 1; + + reset_codec(s); + } else if (!s->cdlms[0][0].order) { + av_log(s->avctx, AV_LOG_DEBUG, + "Waiting for seekable tile\n"); + s->frame.nb_samples = 0; + return -1; + } + + rawpcm_tile = get_bits1(&s->gb); + + for (i = 0; i < s->num_channels; i++) + s->is_channel_coded[i] = 1; + + if (!rawpcm_tile) { + for (i = 0; i < s->num_channels; i++) + s->is_channel_coded[i] = get_bits1(&s->gb); + + if (s->bV3RTM) { + // LPC + s->do_lpc = get_bits1(&s->gb); + if (s->do_lpc) { + decode_lpc(s); + avpriv_request_sample(s->avctx, "Expect wrong output since " + "inverse LPC filter"); + } + } else + s->do_lpc = 0; + } + + + if (get_bits1(&s->gb)) + padding_zeroes = get_bits(&s->gb, 5); + else + padding_zeroes = 0; + + if (rawpcm_tile) { + int bits = s->bits_per_sample - padding_zeroes; + if (bits <= 0) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid number of padding bits in raw PCM tile\n"); + return AVERROR_INVALIDDATA; + } + av_dlog(s->avctx, "RAWPCM %d bits per sample. " + "total %d bits, remain=%d\n", bits, + bits * s->num_channels * subframe_len, get_bits_count(&s->gb)); + for (i = 0; i < s->num_channels; i++) + for (j = 0; j < subframe_len; j++) + s->channel_coeffs[i][j] = get_sbits_long(&s->gb, bits); + } else { + for (i = 0; i < s->num_channels; i++) + if (s->is_channel_coded[i]) { + decode_channel_residues(s, i, subframe_len); + if (s->seekable_tile) + use_high_update_speed(s, i); + else + use_normal_update_speed(s, i); + revert_cdlms(s, i, 0, subframe_len); + } else { + memset(s->channel_residues[i], 0, sizeof(**s->channel_residues) * subframe_len); + } + } + if (s->do_mclms) + revert_mclms(s, subframe_len); + if (s->do_inter_ch_decorr) + revert_inter_ch_decorr(s, subframe_len); + if (s->do_ac_filter) + revert_acfilter(s, subframe_len); + + /* Dequantize */ + if (s->quant_stepsize != 1) + for (i = 0; i < s->num_channels; i++) + for (j = 0; j < subframe_len; j++) + s->channel_residues[i][j] *= s->quant_stepsize; + + /* Write to proper output buffer depending on bit-depth */ + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + int subframe_len = s->channel[c].subframe_len[s->channel[c].cur_subframe]; + + for (j = 0; j < subframe_len; j++) { + if (s->bits_per_sample == 16) { + *s->samples_16[c]++ = (int16_t) s->channel_residues[c][j] << padding_zeroes; + } else { + *s->samples_32[c]++ = s->channel_residues[c][j] << padding_zeroes; + } + } + } + + /* handled one subframe */ + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + if (s->channel[c].cur_subframe >= s->channel[c].num_subframes) { + av_log(s->avctx, AV_LOG_ERROR, "broken subframe\n"); + return AVERROR_INVALIDDATA; + } + ++s->channel[c].cur_subframe; + } + return 0; +} + +/** + * @brief Decode one WMA frame. + * @param s codec context + * @return 0 if the trailer bit indicates that this is the last frame, + * 1 if there are additional frames + */ +static int decode_frame(WmallDecodeCtx *s) +{ + GetBitContext* gb = &s->gb; + int more_frames = 0, len = 0, i, ret; + + s->frame.nb_samples = s->samples_per_frame; + if ((ret = ff_get_buffer(s->avctx, &s->frame, 0)) < 0) { + /* return an error if no frame could be decoded at all */ + s->packet_loss = 1; + return ret; + } + for (i = 0; i < s->num_channels; i++) { + s->samples_16[i] = (int16_t *)s->frame.extended_data[i]; + s->samples_32[i] = (int32_t *)s->frame.extended_data[i]; + } + + /* get frame length */ + if (s->len_prefix) + len = get_bits(gb, s->log2_frame_size); + + /* decode tile information */ + if (decode_tilehdr(s)) { + s->packet_loss = 1; + return 0; + } + + /* read drc info */ + if (s->dynamic_range_compression) + s->drc_gain = get_bits(gb, 8); + + /* no idea what these are for, might be the number of samples + that need to be skipped at the beginning or end of a stream */ + if (get_bits1(gb)) { + int av_unused skip; + + /* usually true for the first frame */ + if (get_bits1(gb)) { + skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); + av_dlog(s->avctx, "start skip: %i\n", skip); + } + + /* sometimes true for the last frame */ + if (get_bits1(gb)) { + skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); + av_dlog(s->avctx, "end skip: %i\n", skip); + } + + } + + /* reset subframe states */ + s->parsed_all_subframes = 0; + for (i = 0; i < s->num_channels; i++) { + s->channel[i].decoded_samples = 0; + s->channel[i].cur_subframe = 0; + } + + /* decode all subframes */ + while (!s->parsed_all_subframes) { + if (decode_subframe(s) < 0) { + s->packet_loss = 1; + return 0; + } + } + + av_dlog(s->avctx, "Frame done\n"); + + if (s->skip_frame) + s->skip_frame = 0; + + if (s->len_prefix) { + if (len != (get_bits_count(gb) - s->frame_offset) + 2) { + /* FIXME: not sure if this is always an error */ + av_log(s->avctx, AV_LOG_ERROR, + "frame[%i] would have to skip %i bits\n", s->frame_num, + len - (get_bits_count(gb) - s->frame_offset) - 1); + s->packet_loss = 1; + return 0; + } + + /* skip the rest of the frame data */ + skip_bits_long(gb, len - (get_bits_count(gb) - s->frame_offset) - 1); + } + + /* decode trailer bit */ + more_frames = get_bits1(gb); + ++s->frame_num; + return more_frames; +} + +/** + * @brief Calculate remaining input buffer length. + * @param s codec context + * @param gb bitstream reader context + * @return remaining size in bits + */ +static int remaining_bits(WmallDecodeCtx *s, GetBitContext *gb) +{ + return s->buf_bit_size - get_bits_count(gb); +} + +/** + * @brief Fill the bit reservoir with a (partial) frame. + * @param s codec context + * @param gb bitstream reader context + * @param len length of the partial frame + * @param append decides whether to reset the buffer or not + */ +static void save_bits(WmallDecodeCtx *s, GetBitContext* gb, int len, + int append) +{ + int buflen; + PutBitContext tmp; + + /* when the frame data does not need to be concatenated, the input buffer + is reset and additional bits from the previous frame are copied + and skipped later so that a fast byte copy is possible */ + + if (!append) { + s->frame_offset = get_bits_count(gb) & 7; + s->num_saved_bits = s->frame_offset; + init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); + } + + buflen = (s->num_saved_bits + len + 8) >> 3; + + if (len <= 0 || buflen > MAX_FRAMESIZE) { + avpriv_request_sample(s->avctx, "Too small input buffer"); + s->packet_loss = 1; + return; + } + + s->num_saved_bits += len; + if (!append) { + avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), + s->num_saved_bits); + } else { + int align = 8 - (get_bits_count(gb) & 7); + align = FFMIN(align, len); + put_bits(&s->pb, align, get_bits(gb, align)); + len -= align; + avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); + } + skip_bits_long(gb, len); + + tmp = s->pb; + flush_put_bits(&tmp); + + init_get_bits(&s->gb, s->frame_data, s->num_saved_bits); + skip_bits(&s->gb, s->frame_offset); +} + +static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, + AVPacket* avpkt) +{ + WmallDecodeCtx *s = avctx->priv_data; + GetBitContext* gb = &s->pgb; + const uint8_t* buf = avpkt->data; + int buf_size = avpkt->size; + int num_bits_prev_frame, packet_sequence_number, spliced_packet; + + s->frame.nb_samples = 0; + + if (s->packet_done || s->packet_loss) { + s->packet_done = 0; + + /* sanity check for the buffer length */ + if (buf_size < avctx->block_align) + return 0; + + s->next_packet_start = buf_size - avctx->block_align; + buf_size = avctx->block_align; + s->buf_bit_size = buf_size << 3; + + /* parse packet header */ + init_get_bits(gb, buf, s->buf_bit_size); + packet_sequence_number = get_bits(gb, 4); + skip_bits(gb, 1); // Skip seekable_frame_in_packet, currently ununused + spliced_packet = get_bits1(gb); + if (spliced_packet) + avpriv_request_sample(avctx, "Bitstream splicing"); + + /* get number of bits that need to be added to the previous frame */ + num_bits_prev_frame = get_bits(gb, s->log2_frame_size); + + /* check for packet loss */ + if (!s->packet_loss && + ((s->packet_sequence_number + 1) & 0xF) != packet_sequence_number) { + s->packet_loss = 1; + av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n", + s->packet_sequence_number, packet_sequence_number); + } + s->packet_sequence_number = packet_sequence_number; + + if (num_bits_prev_frame > 0) { + int remaining_packet_bits = s->buf_bit_size - get_bits_count(gb); + if (num_bits_prev_frame >= remaining_packet_bits) { + num_bits_prev_frame = remaining_packet_bits; + s->packet_done = 1; + } + + /* Append the previous frame data to the remaining data from the + * previous packet to create a full frame. */ + save_bits(s, gb, num_bits_prev_frame, 1); + + /* decode the cross packet frame if it is valid */ + if (num_bits_prev_frame < remaining_packet_bits && !s->packet_loss) + decode_frame(s); + } else if (s->num_saved_bits - s->frame_offset) { + av_dlog(avctx, "ignoring %x previously saved bits\n", + s->num_saved_bits - s->frame_offset); + } + + if (s->packet_loss) { + /* Reset number of saved bits so that the decoder does not start + * to decode incomplete frames in the s->len_prefix == 0 case. */ + s->num_saved_bits = 0; + s->packet_loss = 0; + init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); + } + + } else { + int frame_size; + + s->buf_bit_size = (avpkt->size - s->next_packet_start) << 3; + init_get_bits(gb, avpkt->data, s->buf_bit_size); + skip_bits(gb, s->packet_offset); + + if (s->len_prefix && remaining_bits(s, gb) > s->log2_frame_size && + (frame_size = show_bits(gb, s->log2_frame_size)) && + frame_size <= remaining_bits(s, gb)) { + save_bits(s, gb, frame_size, 0); + s->packet_done = !decode_frame(s); + } else if (!s->len_prefix + && s->num_saved_bits > get_bits_count(&s->gb)) { + /* when the frames do not have a length prefix, we don't know the + * compressed length of the individual frames however, we know what + * part of a new packet belongs to the previous frame therefore we + * save the incoming packet first, then we append the "previous + * frame" data from the next packet so that we get a buffer that + * only contains full frames */ + s->packet_done = !decode_frame(s); + } else { + s->packet_done = 1; + } + } + + if (s->packet_done && !s->packet_loss && + remaining_bits(s, gb) > 0) { + /* save the rest of the data so that it can be decoded + * with the next packet */ + save_bits(s, gb, remaining_bits(s, gb), 0); + } + + *got_frame_ptr = s->frame.nb_samples > 0; + av_frame_move_ref(data, &s->frame); + + s->packet_offset = get_bits_count(gb) & 7; + + return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3; +} + +static void flush(AVCodecContext *avctx) +{ + WmallDecodeCtx *s = avctx->priv_data; + s->packet_loss = 1; + s->packet_done = 0; + s->num_saved_bits = 0; + s->frame_offset = 0; + s->next_packet_start = 0; + s->cdlms[0][0].order = 0; + s->frame.nb_samples = 0; + init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); +} + +AVCodec ff_wmalossless_decoder = { + .name = "wmalossless", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMALOSSLESS, + .priv_data_size = sizeof(WmallDecodeCtx), + .init = decode_init, + .decode = decode_packet, + .flush = flush, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1 | CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Lossless"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/wmaprodata.h b/ffmpeg/libavcodec/wmaprodata.h new file mode 100644 index 0000000..5382479 --- /dev/null +++ b/ffmpeg/libavcodec/wmaprodata.h @@ -0,0 +1,604 @@ +/* + * WMA 9/3/PRO compatible decoder + * Copyright (c) 2007 Baptiste Coudurier, Benjamin Larsson, Ulion + * Copyright (c) 2008 - 2009 Sascha Sommer + * + * 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 + */ + +/** + * @file + * @brief tables for wmapro decoding + */ + +#ifndef AVCODEC_WMAPRODATA_H +#define AVCODEC_WMAPRODATA_H + +#include +#include + +/** + * @brief frequencies to divide the frequency spectrum into scale factor bands + */ +static const uint16_t critical_freq[] = { + 100, 200, 300, 400, 510, 630, 770, + 920, 1080, 1270, 1480, 1720, 2000, 2320, + 2700, 3150, 3700, 4400, 5300, 6400, 7700, + 9500, 12000, 15500, 20675, 28575, 41375, 63875, +}; + + +/** + * @name Huffman tables for DPCM-coded scale factors + * @{ + */ +#define HUFF_SCALE_SIZE 121 +#define HUFF_SCALE_MAXBITS 19 +static const uint16_t scale_huffcodes[HUFF_SCALE_SIZE] = { + 0xE639, 0xE6C2, 0xE6C1, 0xE6C0, 0xE63F, 0xE63E, 0xE63D, 0xE63C, + 0xE63B, 0xE63A, 0xE638, 0xE637, 0xE636, 0xE635, 0xE634, 0xE632, + 0xE633, 0xE620, 0x737B, 0xE610, 0xE611, 0xE612, 0xE613, 0xE614, + 0xE615, 0xE616, 0xE617, 0xE618, 0xE619, 0xE61A, 0xE61B, 0xE61C, + 0xE61D, 0xE61E, 0xE61F, 0xE6C3, 0xE621, 0xE622, 0xE623, 0xE624, + 0xE625, 0xE626, 0xE627, 0xE628, 0xE629, 0xE62A, 0xE62B, 0xE62C, + 0xE62D, 0xE62E, 0xE62F, 0xE630, 0xE631, 0x1CDF, 0x0E60, 0x0399, + 0x00E7, 0x001D, 0x0000, 0x0001, 0x0001, 0x0001, 0x0002, 0x0006, + 0x0002, 0x0007, 0x0006, 0x000F, 0x0038, 0x0072, 0x039A, 0xE6C4, + 0xE6C5, 0xE6C6, 0xE6C7, 0xE6C8, 0xE6C9, 0xE6CA, 0xE6CB, 0xE6CC, + 0xE6CD, 0xE6CE, 0xE6CF, 0xE6D0, 0xE6D1, 0xE6D2, 0xE6D3, 0xE6D4, + 0xE6D5, 0xE6D6, 0xE6D7, 0xE6D8, 0xE6D9, 0xE6DA, 0xE6DB, 0xE6DC, + 0xE6DD, 0xE6DE, 0xE6DF, 0xE6E0, 0xE6E1, 0xE6E2, 0xE6E3, 0xE6E4, + 0xE6E5, 0xE6E6, 0xE6E7, 0xE6E8, 0xE6E9, 0xE6EA, 0xE6EB, 0xE6EC, + 0xE6ED, 0xE6EE, 0xE6EF, 0xE6F0, 0xE6F1, 0xE6F2, 0xE6F3, 0xE6F4, + 0xE6F5, +}; + +static const uint8_t scale_huffbits[HUFF_SCALE_SIZE] = { + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 18, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 16, 15, 13, + 11, 8, 5, 2, 1, 3, 5, 6, + 6, 7, 7, 7, 9, 10, 13, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, + 19, +}; +/** @} */ + + +/** + * @name Huffman, run and level tables for runlevel-coded scale factors + * @{ + */ +#define HUFF_SCALE_RL_SIZE 120 +#define HUFF_SCALE_RL_MAXBITS 21 +static const uint32_t scale_rl_huffcodes[HUFF_SCALE_RL_SIZE] = { + 0x00010C, 0x000001, 0x10FE2A, 0x000003, 0x000003, 0x000001, 0x000013, + 0x000020, 0x000029, 0x000014, 0x000016, 0x000045, 0x000049, 0x00002F, + 0x000042, 0x00008E, 0x00008F, 0x000129, 0x000009, 0x00000D, 0x0004AC, + 0x00002C, 0x000561, 0x0002E6, 0x00087C, 0x0002E2, 0x00095C, 0x000018, + 0x000001, 0x000016, 0x000044, 0x00002A, 0x000007, 0x000159, 0x000143, + 0x000128, 0x00015A, 0x00012D, 0x00002B, 0x0000A0, 0x000142, 0x00012A, + 0x0002EF, 0x0004AF, 0x00087D, 0x004AE9, 0x0043F9, 0x000067, 0x000199, + 0x002B05, 0x001583, 0x0021FE, 0x10FE2C, 0x000004, 0x00002E, 0x00010D, + 0x00000A, 0x000244, 0x000017, 0x000245, 0x000011, 0x00010E, 0x00012C, + 0x00002A, 0x00002F, 0x000121, 0x000046, 0x00087E, 0x0000BA, 0x000032, + 0x0087F0, 0x0056DC, 0x0002EC, 0x0043FA, 0x002B6F, 0x004AE8, 0x0002B7, + 0x10FE2B, 0x000001, 0x000051, 0x000010, 0x0002EE, 0x000B9C, 0x002576, + 0x000198, 0x0056DD, 0x0000CD, 0x000AC0, 0x000170, 0x004AEF, 0x00002D, + 0x0004AD, 0x0021FF, 0x0005CF, 0x002B04, 0x10FE29, 0x10FE28, 0x0002ED, + 0x002E74, 0x021FC4, 0x004AEE, 0x010FE3, 0x087F17, 0x000000, 0x000097, + 0x0002E3, 0x000ADA, 0x002575, 0x00173B, 0x0043FB, 0x002E75, 0x10FE2D, + 0x0015B6, 0x00056C, 0x000057, 0x000123, 0x000120, 0x00021E, 0x000172, + 0x0002B1, +}; + +static const uint8_t scale_rl_huffbits[HUFF_SCALE_RL_SIZE] = { + 9, 2, 21, 2, 4, 5, 5, + 6, 6, 7, 7, 7, 7, 6, + 7, 8, 8, 9, 10, 10, 11, + 12, 11, 12, 12, 12, 12, 11, + 4, 5, 7, 8, 9, 9, 9, + 9, 9, 9, 8, 8, 9, 9, + 12, 11, 12, 15, 15, 13, 15, + 14, 13, 14, 21, 5, 6, 9, + 10, 10, 11, 10, 11, 9, 9, + 6, 8, 9, 7, 12, 10, 12, + 16, 15, 12, 15, 14, 15, 10, + 21, 6, 7, 11, 12, 14, 14, + 15, 15, 14, 12, 11, 15, 12, + 11, 14, 13, 14, 21, 21, 12, + 16, 18, 15, 17, 20, 7, 8, + 12, 12, 14, 15, 15, 16, 21, + 13, 11, 7, 9, 9, 10, 11, + 10, +}; + + +static const uint8_t scale_rl_run[HUFF_SCALE_RL_SIZE] = { + 0, 0, 0, 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, 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, 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, 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, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 0, 1, 0, 1, 0, 1, +}; + +static const uint8_t scale_rl_level[HUFF_SCALE_RL_SIZE] = { + 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 8, 8, 9, 9, +}; +/** @} */ + + +/** + * @name Huffman, run and level codes for runlevel-coded coefficients + * @{ + */ +#define HUFF_COEF0_SIZE 272 +#define HUFF_COEF0_MAXBITS 21 +static const uint32_t coef0_huffcodes[HUFF_COEF0_SIZE] = { + 0x00004A, 0x00002B, 0x000000, 0x000003, 0x000006, 0x000009, 0x00000F, + 0x000010, 0x000016, 0x000011, 0x000016, 0x000028, 0x00002F, 0x000026, + 0x000029, 0x000045, 0x000055, 0x00005D, 0x000042, 0x00004E, 0x000051, + 0x00005E, 0x00008D, 0x0000A8, 0x0000AD, 0x000080, 0x000096, 0x00009F, + 0x0000AA, 0x0000BE, 0x00011C, 0x000153, 0x000158, 0x000170, 0x000104, + 0x00010D, 0x000105, 0x000103, 0x00012F, 0x000177, 0x000175, 0x000157, + 0x000174, 0x000225, 0x00023B, 0x00020D, 0x00021F, 0x000281, 0x00027B, + 0x000282, 0x0002AC, 0x0002FD, 0x00044F, 0x000478, 0x00044D, 0x0002EC, + 0x00044E, 0x000564, 0x000409, 0x00040B, 0x000501, 0x000545, 0x0004F3, + 0x000541, 0x00043B, 0x0004F1, 0x0004F4, 0x0008FD, 0x000A94, 0x000811, + 0x000B88, 0x000B91, 0x000B93, 0x0008EA, 0x000899, 0x000B8A, 0x000972, + 0x0009E5, 0x000A8F, 0x000A84, 0x000A8E, 0x000A00, 0x000830, 0x0008E8, + 0x000B95, 0x000871, 0x00083A, 0x000814, 0x000873, 0x000BFE, 0x001728, + 0x001595, 0x001712, 0x00102A, 0x001021, 0x001729, 0x00152E, 0x0013C3, + 0x001721, 0x001597, 0x00151B, 0x0010F2, 0x001403, 0x001703, 0x001503, + 0x001708, 0x0013C1, 0x00170E, 0x00170C, 0x0010E1, 0x0011EA, 0x001020, + 0x001500, 0x0017FA, 0x001704, 0x001705, 0x0017F0, 0x0017FB, 0x0021E6, + 0x002B2D, 0x0020C6, 0x002B29, 0x002E4A, 0x0023AC, 0x001519, 0x0023F3, + 0x002B2C, 0x0021C0, 0x0017FE, 0x0023D7, 0x0017F9, 0x0012E7, 0x0013C0, + 0x002261, 0x0023D3, 0x002057, 0x002056, 0x0021D2, 0x0020C7, 0x0023D2, + 0x0020EC, 0x0044C0, 0x002FE2, 0x00475B, 0x002A03, 0x002FE3, 0x0021E2, + 0x0021D0, 0x002A31, 0x002E13, 0x002E05, 0x0047E5, 0x00000E, 0x000024, + 0x000088, 0x0000B9, 0x00010C, 0x000224, 0x0002B3, 0x000283, 0x0002ED, + 0x00047B, 0x00041E, 0x00043D, 0x0004F5, 0x0005FD, 0x000A92, 0x000B96, + 0x000838, 0x000971, 0x000B83, 0x000B80, 0x000BF9, 0x0011D3, 0x0011E8, + 0x0011D7, 0x001527, 0x0011F8, 0x001073, 0x0010F0, 0x0010E4, 0x0017F8, + 0x001062, 0x001402, 0x0017E3, 0x00151A, 0x001077, 0x00152B, 0x00170D, + 0x0021D3, 0x002E41, 0x0013C2, 0x000029, 0x0000A9, 0x00025D, 0x000419, + 0x000544, 0x000B8B, 0x0009E4, 0x0011D2, 0x001526, 0x001724, 0x0012E6, + 0x00150B, 0x0017FF, 0x002E26, 0x002E4B, 0x002B28, 0x0021E3, 0x002A14, + 0x00475A, 0x002E12, 0x000057, 0x00023E, 0x000A90, 0x000BF0, 0x001072, + 0x001502, 0x0023D6, 0x0020ED, 0x002A30, 0x0044C7, 0x00008C, 0x00047F, + 0x00152A, 0x002262, 0x002E04, 0x0000A1, 0x0005F9, 0x000173, 0x000875, + 0x000171, 0x00152D, 0x0002E3, 0x0017E2, 0x0002AD, 0x0021C1, 0x000479, + 0x0021E7, 0x00041F, 0x005C4E, 0x000543, 0x005C4F, 0x000A91, 0x00898D, + 0x000B97, 0x008746, 0x000970, 0x008745, 0x000B85, 0x00A856, 0x00152F, + 0x010E8E, 0x0010E5, 0x00A857, 0x00170F, 0x021D11, 0x002A58, 0x010E8F, + 0x002E40, 0x021D13, 0x002A59, 0x043A25, 0x002A02, 0x043A21, 0x0044C1, + 0x087448, 0x0047E4, 0x043A20, 0x00542A, 0x087449, 0x00898C, +}; + +static const uint8_t coef0_huffbits[HUFF_COEF0_SIZE] = { + 8, 7, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 13, + 12, 12, 12, 12, 12, 12, 13, + 13, 13, 13, 13, 13, 13, 12, + 12, 13, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 13, 13, 14, + 13, 13, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 14, + 14, 14, 14, 14, 14, 14, 15, + 14, 15, 14, 14, 14, 14, 14, + 14, 15, 14, 14, 14, 14, 14, + 14, 14, 15, 15, 15, 15, 14, + 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 4, 7, + 8, 9, 10, 10, 10, 11, 11, + 11, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 13, 14, + 15, 14, 14, 6, 9, 11, 12, + 12, 12, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 15, 15, + 15, 15, 7, 10, 12, 13, 14, + 14, 14, 15, 15, 15, 8, 11, + 13, 14, 15, 9, 12, 9, 13, + 10, 13, 10, 14, 11, 15, 11, + 15, 12, 15, 12, 15, 12, 16, + 12, 17, 13, 17, 13, 17, 13, + 18, 14, 17, 14, 19, 14, 18, + 14, 19, 14, 20, 15, 20, 15, + 21, 15, 20, 16, 21, 16, +}; + + +#define HUFF_COEF1_SIZE 244 +#define HUFF_COEF1_MAXBITS 22 +static const uint32_t coef1_huffcodes[HUFF_COEF1_SIZE] = { + 0x0001E2, 0x00007F, 0x000000, 0x000002, 0x000008, 0x00000E, 0x000019, + 0x00002F, 0x000037, 0x000060, 0x00006C, 0x000095, 0x0000C6, 0x0000F0, + 0x00012E, 0x000189, 0x0001A5, 0x0001F8, 0x000253, 0x00030A, 0x000344, + 0x00034D, 0x0003F2, 0x0004BD, 0x0005D7, 0x00062A, 0x00068B, 0x000693, + 0x000797, 0x00097D, 0x000BAB, 0x000C52, 0x000C5E, 0x000D21, 0x000D20, + 0x000F1A, 0x000FCE, 0x000FD1, 0x0012F1, 0x001759, 0x0018AC, 0x0018A7, + 0x0018BF, 0x001A2B, 0x001E52, 0x001E50, 0x001E31, 0x001FB8, 0x0025E6, + 0x0025E7, 0x002EB4, 0x002EB7, 0x003169, 0x00315B, 0x00317C, 0x00316C, + 0x0034CA, 0x00348D, 0x003F40, 0x003CA2, 0x003F76, 0x004BC3, 0x004BE5, + 0x003F73, 0x004BF8, 0x004BF9, 0x006131, 0x00628B, 0x006289, 0x0062DA, + 0x00628A, 0x0062D4, 0x006997, 0x0062B4, 0x006918, 0x00794D, 0x007E7B, + 0x007E87, 0x007EEA, 0x00794E, 0x00699D, 0x007967, 0x00699F, 0x0062DB, + 0x007E7A, 0x007EEB, 0x00BAC0, 0x0097C9, 0x00C537, 0x00C5AB, 0x00D233, + 0x00D338, 0x00BAC1, 0x00D23D, 0x012F91, 0x00D339, 0x00FDC8, 0x00D23C, + 0x00FDDC, 0x00FDC9, 0x00FDDD, 0x00D33C, 0x000003, 0x000016, 0x00003E, + 0x0000C3, 0x0001A1, 0x000347, 0x00062E, 0x000BAA, 0x000F2D, 0x001A2A, + 0x001E58, 0x00309B, 0x003CA3, 0x005D6A, 0x00629A, 0x006996, 0x00794F, + 0x007EE5, 0x00BAD7, 0x00C5AA, 0x00C5F4, 0x00FDDF, 0x00FDDE, 0x018A20, + 0x018A6D, 0x01A67B, 0x01A464, 0x025F21, 0x01F9E2, 0x01F9E3, 0x00000A, + 0x00003D, 0x000128, 0x0003C7, 0x000C24, 0x0018A3, 0x002EB1, 0x003CB2, + 0x00691F, 0x007E79, 0x000013, 0x0000BB, 0x00034E, 0x000D14, 0x0025FD, + 0x004BE7, 0x000024, 0x000188, 0x0007EF, 0x000035, 0x000308, 0x0012F2, + 0x00005C, 0x0003F6, 0x0025E0, 0x00006D, 0x000698, 0x000096, 0x000C25, + 0x0000C7, 0x000F1B, 0x0000F3, 0x0012FF, 0x000174, 0x001A66, 0x0001A0, + 0x003099, 0x0001E4, 0x00316B, 0x000252, 0x003F31, 0x00030B, 0x004BE6, + 0x000346, 0x0062FB, 0x00034F, 0x007966, 0x0003F5, 0x007E86, 0x0005D4, + 0x00C511, 0x00062C, 0x00C5F5, 0x000692, 0x00F299, 0x000795, 0x00F298, + 0x0007E9, 0x018A21, 0x00097E, 0x0175AD, 0x000C27, 0x01A67A, 0x000C57, + 0x02EB59, 0x000D22, 0x0314D9, 0x000F19, 0x03F3C2, 0x000FCD, 0x0348CB, + 0x0012F8, 0x04BE41, 0x0018A0, 0x03F3C1, 0x0018A1, 0x04BE40, 0x0018B7, + 0x0629B0, 0x001A64, 0x0D2329, 0x001E30, 0x03F3C3, 0x001F9F, 0x0BAD62, + 0x001F99, 0x0FCF00, 0x00309A, 0x0629B1, 0x002EB6, 0x175AC3, 0x00314C, + 0x069195, 0x003168, 0x0BAD63, 0x00348E, 0x175AC1, 0x003F30, 0x07E781, + 0x003F41, 0x0D2328, 0x003F42, 0x1F9E03, 0x004BC2, 0x175AC2, 0x003F74, + 0x175AC0, 0x005D61, 0x3F3C05, 0x006130, 0x3F3C04, 0x0062B5, +}; + +static const uint8_t coef1_huffbits[HUFF_COEF1_SIZE] = { + 9, 7, 2, 3, 4, 4, 5, + 6, 6, 7, 7, 8, 8, 8, + 9, 9, 9, 9, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, + 11, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 15, 15, + 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, + 15, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 17, 16, 16, 16, + 16, 16, 16, 16, 3, 5, 6, + 8, 9, 10, 11, 12, 12, 13, + 13, 14, 14, 15, 15, 15, 15, + 15, 16, 16, 16, 16, 16, 17, + 17, 17, 17, 18, 17, 17, 4, + 6, 9, 10, 12, 13, 14, 14, + 15, 15, 5, 8, 10, 12, 14, + 15, 6, 9, 11, 6, 10, 13, + 7, 10, 14, 7, 11, 8, 12, + 8, 12, 8, 13, 9, 13, 9, + 14, 9, 14, 10, 14, 10, 15, + 10, 15, 10, 15, 10, 15, 11, + 16, 11, 16, 11, 16, 11, 16, + 11, 17, 12, 17, 12, 17, 12, + 18, 12, 18, 12, 18, 12, 18, + 13, 19, 13, 18, 13, 19, 13, + 19, 13, 20, 13, 18, 13, 20, + 13, 20, 14, 19, 14, 21, 14, + 19, 14, 20, 14, 21, 14, 19, + 14, 20, 14, 21, 15, 21, 14, + 21, 15, 22, 15, 22, 15, +}; + + +static const uint16_t coef0_run[HUFF_COEF0_SIZE] = { + 0, 0, 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, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 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, 32, 33, 34, 35, 36, 37, 38, 39, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, +}; + +static const float coef0_level[HUFF_COEF0_SIZE] = { + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, + 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, + 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, + 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, + 25, 26, 26, 27, 27, 28, +}; + + +static const uint16_t coef1_run[HUFF_COEF1_SIZE] = { + 0, 0, 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, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 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, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, +}; + +static const float coef1_level[HUFF_COEF1_SIZE] = { + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, + 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, + 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, + 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, + 46, 47, 47, 48, 48, 49, 49, 50, 51, 52, +}; +/** @} */ + + +/** + * @name Huffman and vector lookup tables for vector-coded coefficients + * @{ + */ +#define HUFF_VEC4_SIZE 127 +#define HUFF_VEC4_MAXBITS 14 +static const uint16_t vec4_huffcodes[HUFF_VEC4_SIZE] = { + 0x0019, 0x0027, 0x00F2, 0x03BA, 0x0930, 0x1267, 0x0031, 0x0030, + 0x0097, 0x0221, 0x058B, 0x0124, 0x00EB, 0x01D4, 0x03D8, 0x0584, + 0x0364, 0x045F, 0x0F66, 0x0931, 0x24CD, 0x002F, 0x0039, 0x00E8, + 0x02C3, 0x078A, 0x0037, 0x0029, 0x0084, 0x01B1, 0x00ED, 0x0086, + 0x00F9, 0x03AB, 0x01EB, 0x08BC, 0x011E, 0x00F3, 0x0220, 0x058A, + 0x00EC, 0x008E, 0x012B, 0x01EA, 0x0119, 0x04B0, 0x04B1, 0x03B8, + 0x0691, 0x0365, 0x01ED, 0x049A, 0x0EA9, 0x0EA8, 0x08BD, 0x24CC, + 0x0026, 0x0035, 0x00DB, 0x02C4, 0x07B2, 0x0038, 0x002B, 0x007F, + 0x01B3, 0x00F4, 0x0091, 0x0116, 0x03BB, 0x0215, 0x0932, 0x002D, + 0x002A, 0x008A, 0x01DE, 0x0028, 0x0020, 0x005C, 0x0090, 0x0068, + 0x01EE, 0x00E9, 0x008D, 0x012A, 0x0087, 0x005D, 0x0118, 0x0349, + 0x01EF, 0x01E3, 0x08B9, 0x00F0, 0x00D3, 0x0214, 0x049B, 0x00DA, + 0x0089, 0x0125, 0x0217, 0x012D, 0x0690, 0x0094, 0x007D, 0x011F, + 0x007E, 0x0059, 0x0127, 0x01A5, 0x0111, 0x00F8, 0x045D, 0x03B9, + 0x0259, 0x0580, 0x02C1, 0x01DF, 0x0585, 0x0216, 0x0163, 0x01B0, + 0x03C4, 0x08B8, 0x078B, 0x0755, 0x0581, 0x0F67, 0x0000, +}; + +static const uint8_t vec4_huffbits[HUFF_VEC4_SIZE] = { + 5, 6, 8, 10, 12, 13, 6, 6, + 8, 10, 11, 9, 8, 9, 10, 11, + 10, 11, 12, 12, 14, 6, 6, 8, + 10, 11, 6, 6, 8, 9, 8, 8, + 8, 10, 9, 12, 9, 8, 10, 11, + 8, 8, 9, 9, 9, 11, 11, 10, + 11, 10, 9, 11, 12, 12, 12, 14, + 6, 6, 8, 10, 11, 6, 6, 7, + 9, 8, 8, 9, 10, 10, 12, 6, + 6, 8, 9, 6, 6, 7, 8, 7, + 9, 8, 8, 9, 8, 7, 9, 10, + 9, 9, 12, 8, 8, 10, 11, 8, + 8, 9, 10, 9, 11, 8, 7, 9, + 7, 7, 9, 9, 9, 8, 11, 10, + 10, 11, 10, 9, 11, 10, 9, 9, + 10, 12, 11, 11, 11, 12, 1, +}; + + +#define HUFF_VEC2_SIZE 137 +#define HUFF_VEC2_MAXBITS 12 +static const uint16_t vec2_huffcodes[HUFF_VEC2_SIZE] = { + 0x055, 0x01C, 0x01A, 0x02B, 0x028, 0x067, 0x08B, 0x039, + 0x170, 0x10D, 0x2A5, 0x047, 0x464, 0x697, 0x523, 0x8CB, + 0x01B, 0x00E, 0x000, 0x010, 0x012, 0x036, 0x048, 0x04C, + 0x0C2, 0x09B, 0x171, 0x03B, 0x224, 0x34A, 0x2D6, 0x019, + 0x00F, 0x002, 0x014, 0x017, 0x006, 0x05D, 0x054, 0x0C7, + 0x0B4, 0x192, 0x10E, 0x233, 0x043, 0x02C, 0x00F, 0x013, + 0x006, 0x02F, 0x02C, 0x068, 0x077, 0x0DF, 0x111, 0x1A4, + 0x16A, 0x2A4, 0x027, 0x011, 0x018, 0x02D, 0x00F, 0x04A, + 0x040, 0x097, 0x01F, 0x11B, 0x022, 0x16D, 0x066, 0x035, + 0x005, 0x02B, 0x049, 0x009, 0x075, 0x0CB, 0x0AA, 0x187, + 0x106, 0x08A, 0x047, 0x060, 0x06E, 0x01D, 0x074, 0x0C4, + 0x01E, 0x118, 0x1A7, 0x038, 0x042, 0x053, 0x076, 0x0A8, + 0x0CA, 0x082, 0x110, 0x18D, 0x12D, 0x0B9, 0x0C8, 0x0DE, + 0x01C, 0x0AB, 0x113, 0x18C, 0x10F, 0x09A, 0x0A5, 0x0B7, + 0x11A, 0x186, 0x1A6, 0x259, 0x153, 0x18A, 0x193, 0x020, + 0x10C, 0x046, 0x03A, 0x107, 0x149, 0x16C, 0x2D7, 0x225, + 0x258, 0x316, 0x696, 0x317, 0x042, 0x522, 0x290, 0x8CA, + 0x001, +}; + +static const uint8_t vec2_huffbits[HUFF_VEC2_SIZE] = { + 7, 6, 6, 6, 7, 7, 8, 9, + 9, 10, 10, 11, 11, 11, 12, 12, + 6, 4, 5, 5, 6, 6, 7, 8, + 8, 9, 9, 10, 10, 10, 11, 6, + 4, 5, 5, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 6, 5, 5, + 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 7, 6, 6, 6, 7, 7, + 8, 8, 9, 9, 10, 10, 7, 6, + 7, 7, 7, 8, 8, 8, 9, 9, + 10, 8, 7, 7, 7, 8, 8, 8, + 9, 9, 9, 9, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 8, 8, 8, + 9, 9, 9, 9, 10, 9, 9, 9, + 9, 9, 9, 10, 9, 9, 9, 10, + 10, 11, 10, 10, 10, 10, 11, 10, + 10, 10, 11, 10, 11, 12, 11, 12, + 3, +}; + + +#define HUFF_VEC1_SIZE 101 +#define HUFF_VEC1_MAXBITS 11 +static const uint16_t vec1_huffcodes[HUFF_VEC1_SIZE] = { + 0x01A, 0x003, 0x017, 0x010, 0x00C, 0x009, 0x005, 0x000, + 0x00D, 0x00A, 0x009, 0x00C, 0x00F, 0x002, 0x004, 0x007, + 0x00B, 0x00F, 0x01C, 0x006, 0x010, 0x015, 0x01C, 0x022, + 0x03B, 0x00E, 0x019, 0x023, 0x034, 0x036, 0x03A, 0x047, + 0x008, 0x00A, 0x01E, 0x031, 0x037, 0x050, 0x053, 0x06B, + 0x06F, 0x08C, 0x0E8, 0x0EA, 0x0EB, 0x016, 0x03E, 0x03F, + 0x06C, 0x089, 0x08A, 0x0A3, 0x0A4, 0x0D4, 0x0DD, 0x0EC, + 0x0EE, 0x11A, 0x1D2, 0x024, 0x025, 0x02E, 0x027, 0x0C2, + 0x0C0, 0x0DA, 0x0DB, 0x111, 0x144, 0x116, 0x14A, 0x145, + 0x1B8, 0x1AB, 0x1DA, 0x1DE, 0x1DB, 0x1DF, 0x236, 0x237, + 0x3A6, 0x3A7, 0x04D, 0x04C, 0x05E, 0x05F, 0x183, 0x182, + 0x186, 0x221, 0x187, 0x220, 0x22E, 0x22F, 0x296, 0x354, + 0x297, 0x355, 0x372, 0x373, 0x016, +}; + +static const uint8_t vec1_huffbits[HUFF_VEC1_SIZE] = { + 7, 6, 5, 5, 5, 5, 5, 5, + 4, 4, 4, 4, 4, 5, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 5, +}; + + +static const uint16_t symbol_to_vec4[HUFF_VEC4_SIZE] = { + 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, + 20, 32, 33, 34, 35, 48, 49, 50, 64, 65, + 80, 256, 257, 258, 259, 260, 272, 273, 274, 275, + 288, 289, 290, 304, 305, 320, 512, 513, 514, 515, + 528, 529, 530, 544, 545, 560, 768, 769, 770, 784, + 785, 800, 1024, 1025, 1040, 1280, 4096, 4097, 4098, 4099, + 4100, 4112, 4113, 4114, 4115, 4128, 4129, 4130, 4144, 4145, + 4160, 4352, 4353, 4354, 4355, 4368, 4369, 4370, 4384, 4385, + 4400, 4608, 4609, 4610, 4624, 4625, 4640, 4864, 4865, 4880, + 5120, 8192, 8193, 8194, 8195, 8208, 8209, 8210, 8224, 8225, + 8240, 8448, 8449, 8450, 8464, 8465, 8480, 8704, 8705, 8720, + 8960, 12288, 12289, 12290, 12304, 12305, 12320, 12544, 12545, 12560, + 12800, 16384, 16385, 16400, 16640, 20480, 0, +}; + + +static const uint8_t symbol_to_vec2[HUFF_VEC2_SIZE] = { + 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, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 112, 113, 114, 115, 116, 117, 118, 119, 120, 128, 129, 130, 131, 132, + 133, 134, 135, 144, 145, 146, 147, 148, 149, 150, 160, 161, 162, 163, 164, + 165, 176, 177, 178, 179, 180, 192, 193, 194, 195, 208, 209, 210, 224, 225, + 240, 0, +}; +/** @} */ + + +/** + * @brief decorrelation matrix for multichannel streams + **/ +static const float default_decorrelation_matrices[] = { + 1.000000, 0.707031, -0.707031, 0.707031, 0.707031, 0.578125, 0.707031, + 0.410156, 0.578125, -0.707031, 0.410156, 0.578125, 0.000000, -0.816406, + 0.500000, 0.652344, 0.500000, 0.269531, 0.500000, 0.269531, -0.500000, + -0.652344, 0.500000, -0.269531, -0.500000, 0.652344, 0.500000, -0.652344, + 0.500000, -0.269531, 0.445312, 0.601562, 0.511719, 0.371094, 0.195312, + 0.445312, 0.371094, -0.195312, -0.601562, -0.511719, 0.445312, 0.000000, + -0.632812, 0.000000, 0.632812, 0.445312, -0.371094, -0.195312, 0.601562, + -0.511719, 0.445312, -0.601562, 0.511719, -0.371094, 0.195312, 0.410156, + 0.558594, 0.500000, 0.410156, 0.289062, 0.148438, 0.410156, 0.410156, + 0.000000, -0.410156, -0.578125, -0.410156, 0.410156, 0.148438, -0.500000, + -0.410156, 0.289062, 0.558594, 0.410156, -0.148438, -0.500000, 0.410156, + 0.289062, -0.558594, 0.410156, -0.410156, 0.000000, 0.410156, -0.578125, + 0.410156, 0.410156, -0.558594, 0.500000, -0.410156, 0.289062, -0.148438, +}; + +/** + * @brief default decorrelation matrix offsets + */ +static const float * const default_decorrelation[] = { + NULL, + &default_decorrelation_matrices[0], + &default_decorrelation_matrices[1], + &default_decorrelation_matrices[5], + &default_decorrelation_matrices[14], + &default_decorrelation_matrices[30], + &default_decorrelation_matrices[55] +}; + +#endif /* AVCODEC_WMAPRODATA_H */ diff --git a/ffmpeg/libavcodec/wmaprodec.c b/ffmpeg/libavcodec/wmaprodec.c new file mode 100644 index 0000000..07cc223 --- /dev/null +++ b/ffmpeg/libavcodec/wmaprodec.c @@ -0,0 +1,1646 @@ +/* + * Wmapro compatible decoder + * Copyright (c) 2007 Baptiste Coudurier, Benjamin Larsson, Ulion + * Copyright (c) 2008 - 2011 Sascha Sommer, Benjamin Larsson + * + * 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 + */ + +/** + * @file + * @brief wmapro decoder implementation + * Wmapro is an MDCT based codec comparable to wma standard or AAC. + * The decoding therefore consists of the following steps: + * - bitstream decoding + * - reconstruction of per-channel data + * - rescaling and inverse quantization + * - IMDCT + * - windowing and overlapp-add + * + * The compressed wmapro bitstream is split into individual packets. + * Every such packet contains one or more wma frames. + * The compressed frames may have a variable length and frames may + * cross packet boundaries. + * Common to all wmapro frames is the number of samples that are stored in + * a frame. + * The number of samples and a few other decode flags are stored + * as extradata that has to be passed to the decoder. + * + * The wmapro frames themselves are again split into a variable number of + * subframes. Every subframe contains the data for 2^N time domain samples + * where N varies between 7 and 12. + * + * Example wmapro bitstream (in samples): + * + * || packet 0 || packet 1 || packet 2 packets + * --------------------------------------------------- + * || frame 0 || frame 1 || frame 2 || frames + * --------------------------------------------------- + * || | | || | | | || || subframes of channel 0 + * --------------------------------------------------- + * || | | || | | | || || subframes of channel 1 + * --------------------------------------------------- + * + * The frame layouts for the individual channels of a wma frame does not need + * to be the same. + * + * However, if the offsets and lengths of several subframes of a frame are the + * same, the subframes of the channels can be grouped. + * Every group may then use special coding techniques like M/S stereo coding + * to improve the compression ratio. These channel transformations do not + * need to be applied to a whole subframe. Instead, they can also work on + * individual scale factor bands (see below). + * The coefficients that carry the audio signal in the frequency domain + * are transmitted as huffman-coded vectors with 4, 2 and 1 elements. + * In addition to that, the encoder can switch to a runlevel coding scheme + * by transmitting subframe_length / 128 zero coefficients. + * + * Before the audio signal can be converted to the time domain, the + * coefficients have to be rescaled and inverse quantized. + * A subframe is therefore split into several scale factor bands that get + * scaled individually. + * Scale factors are submitted for every frame but they might be shared + * between the subframes of a channel. Scale factors are initially DPCM-coded. + * Once scale factors are shared, the differences are transmitted as runlevel + * codes. + * Every subframe length and offset combination in the frame layout shares a + * common quantization factor that can be adjusted for every channel by a + * modifier. + * After the inverse quantization, the coefficients get processed by an IMDCT. + * The resulting values are then windowed with a sine window and the first half + * of the values are added to the second half of the output from the previous + * subframe in order to reconstruct the output samples. + */ + +#include "libavutil/float_dsp.h" +#include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "put_bits.h" +#include "wmaprodata.h" +#include "sinewin.h" +#include "wma.h" +#include "wma_common.h" + +/** current decoder limitations */ +#define WMAPRO_MAX_CHANNELS 8 ///< max number of handled channels +#define MAX_SUBFRAMES 32 ///< max number of subframes per channel +#define MAX_BANDS 29 ///< max number of scale factor bands +#define MAX_FRAMESIZE 32768 ///< maximum compressed frame size + +#define WMAPRO_BLOCK_MIN_BITS 6 ///< log2 of min block size +#define WMAPRO_BLOCK_MAX_BITS 13 ///< log2 of max block size +#define WMAPRO_BLOCK_MAX_SIZE (1 << WMAPRO_BLOCK_MAX_BITS) ///< maximum block size +#define WMAPRO_BLOCK_SIZES (WMAPRO_BLOCK_MAX_BITS - WMAPRO_BLOCK_MIN_BITS + 1) ///< possible block sizes + + +#define VLCBITS 9 +#define SCALEVLCBITS 8 +#define VEC4MAXDEPTH ((HUFF_VEC4_MAXBITS+VLCBITS-1)/VLCBITS) +#define VEC2MAXDEPTH ((HUFF_VEC2_MAXBITS+VLCBITS-1)/VLCBITS) +#define VEC1MAXDEPTH ((HUFF_VEC1_MAXBITS+VLCBITS-1)/VLCBITS) +#define SCALEMAXDEPTH ((HUFF_SCALE_MAXBITS+SCALEVLCBITS-1)/SCALEVLCBITS) +#define SCALERLMAXDEPTH ((HUFF_SCALE_RL_MAXBITS+VLCBITS-1)/VLCBITS) + +static VLC sf_vlc; ///< scale factor DPCM vlc +static VLC sf_rl_vlc; ///< scale factor run length vlc +static VLC vec4_vlc; ///< 4 coefficients per symbol +static VLC vec2_vlc; ///< 2 coefficients per symbol +static VLC vec1_vlc; ///< 1 coefficient per symbol +static VLC coef_vlc[2]; ///< coefficient run length vlc codes +static float sin64[33]; ///< sinus table for decorrelation + +/** + * @brief frame specific decoder context for a single channel + */ +typedef struct { + int16_t prev_block_len; ///< length of the previous block + uint8_t transmit_coefs; + uint8_t num_subframes; + uint16_t subframe_len[MAX_SUBFRAMES]; ///< subframe length in samples + uint16_t subframe_offset[MAX_SUBFRAMES]; ///< subframe positions in the current frame + uint8_t cur_subframe; ///< current subframe number + uint16_t decoded_samples; ///< number of already processed samples + uint8_t grouped; ///< channel is part of a group + int quant_step; ///< quantization step for the current subframe + int8_t reuse_sf; ///< share scale factors between subframes + int8_t scale_factor_step; ///< scaling step for the current subframe + int max_scale_factor; ///< maximum scale factor for the current subframe + int saved_scale_factors[2][MAX_BANDS]; ///< resampled and (previously) transmitted scale factor values + int8_t scale_factor_idx; ///< index for the transmitted scale factor values (used for resampling) + int* scale_factors; ///< pointer to the scale factor values used for decoding + uint8_t table_idx; ///< index in sf_offsets for the scale factor reference block + float* coeffs; ///< pointer to the subframe decode buffer + uint16_t num_vec_coeffs; ///< number of vector coded coefficients + DECLARE_ALIGNED(32, float, out)[WMAPRO_BLOCK_MAX_SIZE + WMAPRO_BLOCK_MAX_SIZE / 2]; ///< output buffer +} WMAProChannelCtx; + +/** + * @brief channel group for channel transformations + */ +typedef struct { + uint8_t num_channels; ///< number of channels in the group + int8_t transform; ///< transform on / off + int8_t transform_band[MAX_BANDS]; ///< controls if the transform is enabled for a certain band + float decorrelation_matrix[WMAPRO_MAX_CHANNELS*WMAPRO_MAX_CHANNELS]; + float* channel_data[WMAPRO_MAX_CHANNELS]; ///< transformation coefficients +} WMAProChannelGrp; + +/** + * @brief main decoder context + */ +typedef struct WMAProDecodeCtx { + /* generic decoder variables */ + AVCodecContext* avctx; ///< codec context for av_log + AVFloatDSPContext fdsp; + uint8_t frame_data[MAX_FRAMESIZE + + FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data + PutBitContext pb; ///< context for filling the frame_data buffer + FFTContext mdct_ctx[WMAPRO_BLOCK_SIZES]; ///< MDCT context per block size + DECLARE_ALIGNED(32, float, tmp)[WMAPRO_BLOCK_MAX_SIZE]; ///< IMDCT output buffer + float* windows[WMAPRO_BLOCK_SIZES]; ///< windows for the different block sizes + + /* frame size dependent frame information (set during initialization) */ + uint32_t decode_flags; ///< used compression features + uint8_t len_prefix; ///< frame is prefixed with its length + uint8_t dynamic_range_compression; ///< frame contains DRC data + uint8_t bits_per_sample; ///< integer audio sample size for the unscaled IMDCT output (used to scale to [-1.0, 1.0]) + uint16_t samples_per_frame; ///< number of samples to output + uint16_t log2_frame_size; + int8_t lfe_channel; ///< lfe channel index + uint8_t max_num_subframes; + uint8_t subframe_len_bits; ///< number of bits used for the subframe length + uint8_t max_subframe_len_bit; ///< flag indicating that the subframe is of maximum size when the first subframe length bit is 1 + uint16_t min_samples_per_subframe; + int8_t num_sfb[WMAPRO_BLOCK_SIZES]; ///< scale factor bands per block size + int16_t sfb_offsets[WMAPRO_BLOCK_SIZES][MAX_BANDS]; ///< scale factor band offsets (multiples of 4) + int8_t sf_offsets[WMAPRO_BLOCK_SIZES][WMAPRO_BLOCK_SIZES][MAX_BANDS]; ///< scale factor resample matrix + int16_t subwoofer_cutoffs[WMAPRO_BLOCK_SIZES]; ///< subwoofer cutoff values + + /* packet decode state */ + GetBitContext pgb; ///< bitstream reader context for the packet + int next_packet_start; ///< start offset of the next wma packet in the demuxer packet + uint8_t packet_offset; ///< frame offset in the packet + uint8_t packet_sequence_number; ///< current packet number + int num_saved_bits; ///< saved number of bits + int frame_offset; ///< frame offset in the bit reservoir + int subframe_offset; ///< subframe offset in the bit reservoir + uint8_t packet_loss; ///< set in case of bitstream error + uint8_t packet_done; ///< set when a packet is fully decoded + + /* frame decode state */ + uint32_t frame_num; ///< current frame number (not used for decoding) + GetBitContext gb; ///< bitstream reader context + int buf_bit_size; ///< buffer size in bits + uint8_t drc_gain; ///< gain for the DRC tool + int8_t skip_frame; ///< skip output step + int8_t parsed_all_subframes; ///< all subframes decoded? + + /* subframe/block decode state */ + int16_t subframe_len; ///< current subframe length + int8_t channels_for_cur_subframe; ///< number of channels that contain the subframe + int8_t channel_indexes_for_cur_subframe[WMAPRO_MAX_CHANNELS]; + int8_t num_bands; ///< number of scale factor bands + int8_t transmit_num_vec_coeffs; ///< number of vector coded coefficients is part of the bitstream + int16_t* cur_sfb_offsets; ///< sfb offsets for the current block + uint8_t table_idx; ///< index for the num_sfb, sfb_offsets, sf_offsets and subwoofer_cutoffs tables + int8_t esc_len; ///< length of escaped coefficients + + uint8_t num_chgroups; ///< number of channel groups + WMAProChannelGrp chgroup[WMAPRO_MAX_CHANNELS]; ///< channel group information + + WMAProChannelCtx channel[WMAPRO_MAX_CHANNELS]; ///< per channel data +} WMAProDecodeCtx; + + +/** + *@brief helper function to print the most important members of the context + *@param s context + */ +static av_cold void dump_context(WMAProDecodeCtx *s) +{ +#define PRINT(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %d\n", a, b); +#define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %x\n", a, b); + + PRINT("ed sample bit depth", s->bits_per_sample); + PRINT_HEX("ed decode flags", s->decode_flags); + PRINT("samples per frame", s->samples_per_frame); + PRINT("log2 frame size", s->log2_frame_size); + PRINT("max num subframes", s->max_num_subframes); + PRINT("len prefix", s->len_prefix); + PRINT("num channels", s->avctx->channels); +} + +/** + *@brief Uninitialize the decoder and free all resources. + *@param avctx codec context + *@return 0 on success, < 0 otherwise + */ +static av_cold int decode_end(AVCodecContext *avctx) +{ + WMAProDecodeCtx *s = avctx->priv_data; + int i; + + for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) + ff_mdct_end(&s->mdct_ctx[i]); + + return 0; +} + +/** + *@brief Initialize the decoder. + *@param avctx codec context + *@return 0 on success, -1 otherwise + */ +static av_cold int decode_init(AVCodecContext *avctx) +{ + WMAProDecodeCtx *s = avctx->priv_data; + uint8_t *edata_ptr = avctx->extradata; + unsigned int channel_mask; + int i, bits; + int log2_max_num_subframes; + int num_possible_block_sizes; + + if (!avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, "block_align is not set\n"); + return AVERROR(EINVAL); + } + + s->avctx = avctx; + avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); + + init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); + + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + if (avctx->extradata_size >= 18) { + s->decode_flags = AV_RL16(edata_ptr+14); + channel_mask = AV_RL32(edata_ptr+2); + s->bits_per_sample = AV_RL16(edata_ptr); + /** dump the extradata */ + for (i = 0; i < avctx->extradata_size; i++) + av_dlog(avctx, "[%x] ", avctx->extradata[i]); + av_dlog(avctx, "\n"); + + } else { + avpriv_request_sample(avctx, "Unknown extradata size"); + return AVERROR_PATCHWELCOME; + } + + /** generic init */ + s->log2_frame_size = av_log2(avctx->block_align) + 4; + + /** frame info */ + s->skip_frame = 1; /* skip first frame */ + s->packet_loss = 1; + s->len_prefix = (s->decode_flags & 0x40); + + /** get frame len */ + bits = ff_wma_get_frame_len_bits(avctx->sample_rate, 3, s->decode_flags); + if (bits > WMAPRO_BLOCK_MAX_BITS) { + avpriv_request_sample(avctx, "14-bit block sizes"); + return AVERROR_PATCHWELCOME; + } + s->samples_per_frame = 1 << bits; + + /** subframe info */ + log2_max_num_subframes = ((s->decode_flags & 0x38) >> 3); + s->max_num_subframes = 1 << log2_max_num_subframes; + if (s->max_num_subframes == 16 || s->max_num_subframes == 4) + s->max_subframe_len_bit = 1; + s->subframe_len_bits = av_log2(log2_max_num_subframes) + 1; + + num_possible_block_sizes = log2_max_num_subframes + 1; + s->min_samples_per_subframe = s->samples_per_frame / s->max_num_subframes; + s->dynamic_range_compression = (s->decode_flags & 0x80); + + if (s->max_num_subframes > MAX_SUBFRAMES) { + av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n", + s->max_num_subframes); + return AVERROR_INVALIDDATA; + } + + if (s->min_samples_per_subframe < (1<min_samples_per_subframe); + return AVERROR_INVALIDDATA; + } + + if (s->avctx->sample_rate <= 0) { + av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n"); + return AVERROR_INVALIDDATA; + } + + if (avctx->channels < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", + avctx->channels); + return AVERROR_INVALIDDATA; + } else if (avctx->channels > WMAPRO_MAX_CHANNELS) { + avpriv_request_sample(avctx, + "More than %d channels", WMAPRO_MAX_CHANNELS); + return AVERROR_PATCHWELCOME; + } + + /** init previous block len */ + for (i = 0; i < avctx->channels; i++) + s->channel[i].prev_block_len = s->samples_per_frame; + + /** extract lfe channel position */ + s->lfe_channel = -1; + + if (channel_mask & 8) { + unsigned int mask; + for (mask = 1; mask < 16; mask <<= 1) { + if (channel_mask & mask) + ++s->lfe_channel; + } + } + + INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE, + scale_huffbits, 1, 1, + scale_huffcodes, 2, 2, 616); + + INIT_VLC_STATIC(&sf_rl_vlc, VLCBITS, HUFF_SCALE_RL_SIZE, + scale_rl_huffbits, 1, 1, + scale_rl_huffcodes, 4, 4, 1406); + + INIT_VLC_STATIC(&coef_vlc[0], VLCBITS, HUFF_COEF0_SIZE, + coef0_huffbits, 1, 1, + coef0_huffcodes, 4, 4, 2108); + + INIT_VLC_STATIC(&coef_vlc[1], VLCBITS, HUFF_COEF1_SIZE, + coef1_huffbits, 1, 1, + coef1_huffcodes, 4, 4, 3912); + + INIT_VLC_STATIC(&vec4_vlc, VLCBITS, HUFF_VEC4_SIZE, + vec4_huffbits, 1, 1, + vec4_huffcodes, 2, 2, 604); + + INIT_VLC_STATIC(&vec2_vlc, VLCBITS, HUFF_VEC2_SIZE, + vec2_huffbits, 1, 1, + vec2_huffcodes, 2, 2, 562); + + INIT_VLC_STATIC(&vec1_vlc, VLCBITS, HUFF_VEC1_SIZE, + vec1_huffbits, 1, 1, + vec1_huffcodes, 2, 2, 562); + + /** calculate number of scale factor bands and their offsets + for every possible block size */ + for (i = 0; i < num_possible_block_sizes; i++) { + int subframe_len = s->samples_per_frame >> i; + int x; + int band = 1; + + s->sfb_offsets[i][0] = 0; + + for (x = 0; x < MAX_BANDS-1 && s->sfb_offsets[i][band - 1] < subframe_len; x++) { + int offset = (subframe_len * 2 * critical_freq[x]) + / s->avctx->sample_rate + 2; + offset &= ~3; + if (offset > s->sfb_offsets[i][band - 1]) + s->sfb_offsets[i][band++] = offset; + } + s->sfb_offsets[i][band - 1] = subframe_len; + s->num_sfb[i] = band - 1; + if (s->num_sfb[i] <= 0) { + av_log(avctx, AV_LOG_ERROR, "num_sfb invalid\n"); + return AVERROR_INVALIDDATA; + } + } + + + /** Scale factors can be shared between blocks of different size + as every block has a different scale factor band layout. + The matrix sf_offsets is needed to find the correct scale factor. + */ + + for (i = 0; i < num_possible_block_sizes; i++) { + int b; + for (b = 0; b < s->num_sfb[i]; b++) { + int x; + int offset = ((s->sfb_offsets[i][b] + + s->sfb_offsets[i][b + 1] - 1) << i) >> 1; + for (x = 0; x < num_possible_block_sizes; x++) { + int v = 0; + while (s->sfb_offsets[x][v + 1] << x < offset) + ++v; + s->sf_offsets[i][x][b] = v; + } + } + } + + /** init MDCT, FIXME: only init needed sizes */ + for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) + ff_mdct_init(&s->mdct_ctx[i], WMAPRO_BLOCK_MIN_BITS+1+i, 1, + 1.0 / (1 << (WMAPRO_BLOCK_MIN_BITS + i - 1)) + / (1 << (s->bits_per_sample - 1))); + + /** init MDCT windows: simple sinus window */ + for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) { + const int win_idx = WMAPRO_BLOCK_MAX_BITS - i; + ff_init_ff_sine_windows(win_idx); + s->windows[WMAPRO_BLOCK_SIZES - i - 1] = ff_sine_windows[win_idx]; + } + + /** calculate subwoofer cutoff values */ + for (i = 0; i < num_possible_block_sizes; i++) { + int block_size = s->samples_per_frame >> i; + int cutoff = (440*block_size + 3 * (s->avctx->sample_rate >> 1) - 1) + / s->avctx->sample_rate; + s->subwoofer_cutoffs[i] = av_clip(cutoff, 4, block_size); + } + + /** calculate sine values for the decorrelation matrix */ + for (i = 0; i < 33; i++) + sin64[i] = sin(i*M_PI / 64.0); + + if (avctx->debug & FF_DEBUG_BITSTREAM) + dump_context(s); + + avctx->channel_layout = channel_mask; + + return 0; +} + +/** + *@brief Decode the subframe length. + *@param s context + *@param offset sample offset in the frame + *@return decoded subframe length on success, < 0 in case of an error + */ +static int decode_subframe_length(WMAProDecodeCtx *s, int offset) +{ + int frame_len_shift = 0; + int subframe_len; + + /** no need to read from the bitstream when only one length is possible */ + if (offset == s->samples_per_frame - s->min_samples_per_subframe) + return s->min_samples_per_subframe; + + /** 1 bit indicates if the subframe is of maximum length */ + if (s->max_subframe_len_bit) { + if (get_bits1(&s->gb)) + frame_len_shift = 1 + get_bits(&s->gb, s->subframe_len_bits-1); + } else + frame_len_shift = get_bits(&s->gb, s->subframe_len_bits); + + subframe_len = s->samples_per_frame >> frame_len_shift; + + /** sanity check the length */ + if (subframe_len < s->min_samples_per_subframe || + subframe_len > s->samples_per_frame) { + av_log(s->avctx, AV_LOG_ERROR, "broken frame: subframe_len %i\n", + subframe_len); + return AVERROR_INVALIDDATA; + } + return subframe_len; +} + +/** + *@brief Decode how the data in the frame is split into subframes. + * Every WMA frame contains the encoded data for a fixed number of + * samples per channel. The data for every channel might be split + * into several subframes. This function will reconstruct the list of + * subframes for every channel. + * + * If the subframes are not evenly split, the algorithm estimates the + * channels with the lowest number of total samples. + * Afterwards, for each of these channels a bit is read from the + * bitstream that indicates if the channel contains a subframe with the + * next subframe size that is going to be read from the bitstream or not. + * If a channel contains such a subframe, the subframe size gets added to + * the channel's subframe list. + * The algorithm repeats these steps until the frame is properly divided + * between the individual channels. + * + *@param s context + *@return 0 on success, < 0 in case of an error + */ +static int decode_tilehdr(WMAProDecodeCtx *s) +{ + uint16_t num_samples[WMAPRO_MAX_CHANNELS] = { 0 };/**< sum of samples for all currently known subframes of a channel */ + uint8_t contains_subframe[WMAPRO_MAX_CHANNELS]; /**< flag indicating if a channel contains the current subframe */ + int channels_for_cur_subframe = s->avctx->channels; /**< number of channels that contain the current subframe */ + int fixed_channel_layout = 0; /**< flag indicating that all channels use the same subframe offsets and sizes */ + int min_channel_len = 0; /**< smallest sum of samples (channels with this length will be processed first) */ + int c; + + /* Should never consume more than 3073 bits (256 iterations for the + * while loop when always the minimum amount of 128 samples is subtracted + * from missing samples in the 8 channel case). + * 1 + BLOCK_MAX_SIZE * MAX_CHANNELS / BLOCK_MIN_SIZE * (MAX_CHANNELS + 4) + */ + + /** reset tiling information */ + for (c = 0; c < s->avctx->channels; c++) + s->channel[c].num_subframes = 0; + + if (s->max_num_subframes == 1 || get_bits1(&s->gb)) + fixed_channel_layout = 1; + + /** loop until the frame data is split between the subframes */ + do { + int subframe_len; + + /** check which channels contain the subframe */ + for (c = 0; c < s->avctx->channels; c++) { + if (num_samples[c] == min_channel_len) { + if (fixed_channel_layout || channels_for_cur_subframe == 1 || + (min_channel_len == s->samples_per_frame - s->min_samples_per_subframe)) + contains_subframe[c] = 1; + else + contains_subframe[c] = get_bits1(&s->gb); + } else + contains_subframe[c] = 0; + } + + /** get subframe length, subframe_len == 0 is not allowed */ + if ((subframe_len = decode_subframe_length(s, min_channel_len)) <= 0) + return AVERROR_INVALIDDATA; + + /** add subframes to the individual channels and find new min_channel_len */ + min_channel_len += subframe_len; + for (c = 0; c < s->avctx->channels; c++) { + WMAProChannelCtx* chan = &s->channel[c]; + + if (contains_subframe[c]) { + if (chan->num_subframes >= MAX_SUBFRAMES) { + av_log(s->avctx, AV_LOG_ERROR, + "broken frame: num subframes > 31\n"); + return AVERROR_INVALIDDATA; + } + chan->subframe_len[chan->num_subframes] = subframe_len; + num_samples[c] += subframe_len; + ++chan->num_subframes; + if (num_samples[c] > s->samples_per_frame) { + av_log(s->avctx, AV_LOG_ERROR, "broken frame: " + "channel len > samples_per_frame\n"); + return AVERROR_INVALIDDATA; + } + } else if (num_samples[c] <= min_channel_len) { + if (num_samples[c] < min_channel_len) { + channels_for_cur_subframe = 0; + min_channel_len = num_samples[c]; + } + ++channels_for_cur_subframe; + } + } + } while (min_channel_len < s->samples_per_frame); + + for (c = 0; c < s->avctx->channels; c++) { + int i; + int offset = 0; + for (i = 0; i < s->channel[c].num_subframes; i++) { + av_dlog(s->avctx, "frame[%i] channel[%i] subframe[%i]" + " len %i\n", s->frame_num, c, i, + s->channel[c].subframe_len[i]); + s->channel[c].subframe_offset[i] = offset; + offset += s->channel[c].subframe_len[i]; + } + } + + return 0; +} + +/** + *@brief Calculate a decorrelation matrix from the bitstream parameters. + *@param s codec context + *@param chgroup channel group for which the matrix needs to be calculated + */ +static void decode_decorrelation_matrix(WMAProDecodeCtx *s, + WMAProChannelGrp *chgroup) +{ + int i; + int offset = 0; + int8_t rotation_offset[WMAPRO_MAX_CHANNELS * WMAPRO_MAX_CHANNELS]; + memset(chgroup->decorrelation_matrix, 0, s->avctx->channels * + s->avctx->channels * sizeof(*chgroup->decorrelation_matrix)); + + for (i = 0; i < chgroup->num_channels * (chgroup->num_channels - 1) >> 1; i++) + rotation_offset[i] = get_bits(&s->gb, 6); + + for (i = 0; i < chgroup->num_channels; i++) + chgroup->decorrelation_matrix[chgroup->num_channels * i + i] = + get_bits1(&s->gb) ? 1.0 : -1.0; + + for (i = 1; i < chgroup->num_channels; i++) { + int x; + for (x = 0; x < i; x++) { + int y; + for (y = 0; y < i + 1; y++) { + float v1 = chgroup->decorrelation_matrix[x * chgroup->num_channels + y]; + float v2 = chgroup->decorrelation_matrix[i * chgroup->num_channels + y]; + int n = rotation_offset[offset + x]; + float sinv; + float cosv; + + if (n < 32) { + sinv = sin64[n]; + cosv = sin64[32 - n]; + } else { + sinv = sin64[64 - n]; + cosv = -sin64[n - 32]; + } + + chgroup->decorrelation_matrix[y + x * chgroup->num_channels] = + (v1 * sinv) - (v2 * cosv); + chgroup->decorrelation_matrix[y + i * chgroup->num_channels] = + (v1 * cosv) + (v2 * sinv); + } + } + offset += i; + } +} + +/** + *@brief Decode channel transformation parameters + *@param s codec context + *@return 0 in case of success, < 0 in case of bitstream errors + */ +static int decode_channel_transform(WMAProDecodeCtx* s) +{ + int i; + /* should never consume more than 1921 bits for the 8 channel case + * 1 + MAX_CHANNELS * (MAX_CHANNELS + 2 + 3 * MAX_CHANNELS * MAX_CHANNELS + * + MAX_CHANNELS + MAX_BANDS + 1) + */ + + /** in the one channel case channel transforms are pointless */ + s->num_chgroups = 0; + if (s->avctx->channels > 1) { + int remaining_channels = s->channels_for_cur_subframe; + + if (get_bits1(&s->gb)) { + avpriv_request_sample(s->avctx, + "Channel transform bit"); + return AVERROR_PATCHWELCOME; + } + + for (s->num_chgroups = 0; remaining_channels && + s->num_chgroups < s->channels_for_cur_subframe; s->num_chgroups++) { + WMAProChannelGrp* chgroup = &s->chgroup[s->num_chgroups]; + float** channel_data = chgroup->channel_data; + chgroup->num_channels = 0; + chgroup->transform = 0; + + /** decode channel mask */ + if (remaining_channels > 2) { + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int channel_idx = s->channel_indexes_for_cur_subframe[i]; + if (!s->channel[channel_idx].grouped + && get_bits1(&s->gb)) { + ++chgroup->num_channels; + s->channel[channel_idx].grouped = 1; + *channel_data++ = s->channel[channel_idx].coeffs; + } + } + } else { + chgroup->num_channels = remaining_channels; + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int channel_idx = s->channel_indexes_for_cur_subframe[i]; + if (!s->channel[channel_idx].grouped) + *channel_data++ = s->channel[channel_idx].coeffs; + s->channel[channel_idx].grouped = 1; + } + } + + /** decode transform type */ + if (chgroup->num_channels == 2) { + if (get_bits1(&s->gb)) { + if (get_bits1(&s->gb)) { + avpriv_request_sample(s->avctx, + "Unknown channel transform type"); + } + } else { + chgroup->transform = 1; + if (s->avctx->channels == 2) { + chgroup->decorrelation_matrix[0] = 1.0; + chgroup->decorrelation_matrix[1] = -1.0; + chgroup->decorrelation_matrix[2] = 1.0; + chgroup->decorrelation_matrix[3] = 1.0; + } else { + /** cos(pi/4) */ + chgroup->decorrelation_matrix[0] = 0.70703125; + chgroup->decorrelation_matrix[1] = -0.70703125; + chgroup->decorrelation_matrix[2] = 0.70703125; + chgroup->decorrelation_matrix[3] = 0.70703125; + } + } + } else if (chgroup->num_channels > 2) { + if (get_bits1(&s->gb)) { + chgroup->transform = 1; + if (get_bits1(&s->gb)) { + decode_decorrelation_matrix(s, chgroup); + } else { + /** FIXME: more than 6 coupled channels not supported */ + if (chgroup->num_channels > 6) { + avpriv_request_sample(s->avctx, + "Coupled channels > 6"); + } else { + memcpy(chgroup->decorrelation_matrix, + default_decorrelation[chgroup->num_channels], + chgroup->num_channels * chgroup->num_channels * + sizeof(*chgroup->decorrelation_matrix)); + } + } + } + } + + /** decode transform on / off */ + if (chgroup->transform) { + if (!get_bits1(&s->gb)) { + int i; + /** transform can be enabled for individual bands */ + for (i = 0; i < s->num_bands; i++) { + chgroup->transform_band[i] = get_bits1(&s->gb); + } + } else { + memset(chgroup->transform_band, 1, s->num_bands); + } + } + remaining_channels -= chgroup->num_channels; + } + } + return 0; +} + +/** + *@brief Extract the coefficients from the bitstream. + *@param s codec context + *@param c current channel number + *@return 0 on success, < 0 in case of bitstream errors + */ +static int decode_coeffs(WMAProDecodeCtx *s, int c) +{ + /* Integers 0..15 as single-precision floats. The table saves a + costly int to float conversion, and storing the values as + integers allows fast sign-flipping. */ + static const uint32_t fval_tab[16] = { + 0x00000000, 0x3f800000, 0x40000000, 0x40400000, + 0x40800000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x41100000, 0x41200000, 0x41300000, + 0x41400000, 0x41500000, 0x41600000, 0x41700000, + }; + int vlctable; + VLC* vlc; + WMAProChannelCtx* ci = &s->channel[c]; + int rl_mode = 0; + int cur_coeff = 0; + int num_zeros = 0; + const uint16_t* run; + const float* level; + + av_dlog(s->avctx, "decode coefficients for channel %i\n", c); + + vlctable = get_bits1(&s->gb); + vlc = &coef_vlc[vlctable]; + + if (vlctable) { + run = coef1_run; + level = coef1_level; + } else { + run = coef0_run; + level = coef0_level; + } + + /** decode vector coefficients (consumes up to 167 bits per iteration for + 4 vector coded large values) */ + while ((s->transmit_num_vec_coeffs || !rl_mode) && + (cur_coeff + 3 < ci->num_vec_coeffs)) { + uint32_t vals[4]; + int i; + unsigned int idx; + + idx = get_vlc2(&s->gb, vec4_vlc.table, VLCBITS, VEC4MAXDEPTH); + + if (idx == HUFF_VEC4_SIZE - 1) { + for (i = 0; i < 4; i += 2) { + idx = get_vlc2(&s->gb, vec2_vlc.table, VLCBITS, VEC2MAXDEPTH); + if (idx == HUFF_VEC2_SIZE - 1) { + uint32_t v0, v1; + v0 = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH); + if (v0 == HUFF_VEC1_SIZE - 1) + v0 += ff_wma_get_large_val(&s->gb); + v1 = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH); + if (v1 == HUFF_VEC1_SIZE - 1) + v1 += ff_wma_get_large_val(&s->gb); + vals[i ] = av_float2int(v0); + vals[i+1] = av_float2int(v1); + } else { + vals[i] = fval_tab[symbol_to_vec2[idx] >> 4 ]; + vals[i+1] = fval_tab[symbol_to_vec2[idx] & 0xF]; + } + } + } else { + vals[0] = fval_tab[ symbol_to_vec4[idx] >> 12 ]; + vals[1] = fval_tab[(symbol_to_vec4[idx] >> 8) & 0xF]; + vals[2] = fval_tab[(symbol_to_vec4[idx] >> 4) & 0xF]; + vals[3] = fval_tab[ symbol_to_vec4[idx] & 0xF]; + } + + /** decode sign */ + for (i = 0; i < 4; i++) { + if (vals[i]) { + uint32_t sign = get_bits1(&s->gb) - 1; + AV_WN32A(&ci->coeffs[cur_coeff], vals[i] ^ sign << 31); + num_zeros = 0; + } else { + ci->coeffs[cur_coeff] = 0; + /** switch to run level mode when subframe_len / 128 zeros + were found in a row */ + rl_mode |= (++num_zeros > s->subframe_len >> 8); + } + ++cur_coeff; + } + } + + /** decode run level coded coefficients */ + if (cur_coeff < s->subframe_len) { + memset(&ci->coeffs[cur_coeff], 0, + sizeof(*ci->coeffs) * (s->subframe_len - cur_coeff)); + if (ff_wma_run_level_decode(s->avctx, &s->gb, vlc, + level, run, 1, ci->coeffs, + cur_coeff, s->subframe_len, + s->subframe_len, s->esc_len, 0)) + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/** + *@brief Extract scale factors from the bitstream. + *@param s codec context + *@return 0 on success, < 0 in case of bitstream errors + */ +static int decode_scale_factors(WMAProDecodeCtx* s) +{ + int i; + + /** should never consume more than 5344 bits + * MAX_CHANNELS * (1 + MAX_BANDS * 23) + */ + + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + int* sf; + int* sf_end; + s->channel[c].scale_factors = s->channel[c].saved_scale_factors[!s->channel[c].scale_factor_idx]; + sf_end = s->channel[c].scale_factors + s->num_bands; + + /** resample scale factors for the new block size + * as the scale factors might need to be resampled several times + * before some new values are transmitted, a backup of the last + * transmitted scale factors is kept in saved_scale_factors + */ + if (s->channel[c].reuse_sf) { + const int8_t* sf_offsets = s->sf_offsets[s->table_idx][s->channel[c].table_idx]; + int b; + for (b = 0; b < s->num_bands; b++) + s->channel[c].scale_factors[b] = + s->channel[c].saved_scale_factors[s->channel[c].scale_factor_idx][*sf_offsets++]; + } + + if (!s->channel[c].cur_subframe || get_bits1(&s->gb)) { + + if (!s->channel[c].reuse_sf) { + int val; + /** decode DPCM coded scale factors */ + s->channel[c].scale_factor_step = get_bits(&s->gb, 2) + 1; + val = 45 / s->channel[c].scale_factor_step; + for (sf = s->channel[c].scale_factors; sf < sf_end; sf++) { + val += get_vlc2(&s->gb, sf_vlc.table, SCALEVLCBITS, SCALEMAXDEPTH) - 60; + *sf = val; + } + } else { + int i; + /** run level decode differences to the resampled factors */ + for (i = 0; i < s->num_bands; i++) { + int idx; + int skip; + int val; + int sign; + + idx = get_vlc2(&s->gb, sf_rl_vlc.table, VLCBITS, SCALERLMAXDEPTH); + + if (!idx) { + uint32_t code = get_bits(&s->gb, 14); + val = code >> 6; + sign = (code & 1) - 1; + skip = (code & 0x3f) >> 1; + } else if (idx == 1) { + break; + } else { + skip = scale_rl_run[idx]; + val = scale_rl_level[idx]; + sign = get_bits1(&s->gb)-1; + } + + i += skip; + if (i >= s->num_bands) { + av_log(s->avctx, AV_LOG_ERROR, + "invalid scale factor coding\n"); + return AVERROR_INVALIDDATA; + } + s->channel[c].scale_factors[i] += (val ^ sign) - sign; + } + } + /** swap buffers */ + s->channel[c].scale_factor_idx = !s->channel[c].scale_factor_idx; + s->channel[c].table_idx = s->table_idx; + s->channel[c].reuse_sf = 1; + } + + /** calculate new scale factor maximum */ + s->channel[c].max_scale_factor = s->channel[c].scale_factors[0]; + for (sf = s->channel[c].scale_factors + 1; sf < sf_end; sf++) { + s->channel[c].max_scale_factor = + FFMAX(s->channel[c].max_scale_factor, *sf); + } + + } + return 0; +} + +/** + *@brief Reconstruct the individual channel data. + *@param s codec context + */ +static void inverse_channel_transform(WMAProDecodeCtx *s) +{ + int i; + + for (i = 0; i < s->num_chgroups; i++) { + if (s->chgroup[i].transform) { + float data[WMAPRO_MAX_CHANNELS]; + const int num_channels = s->chgroup[i].num_channels; + float** ch_data = s->chgroup[i].channel_data; + float** ch_end = ch_data + num_channels; + const int8_t* tb = s->chgroup[i].transform_band; + int16_t* sfb; + + /** multichannel decorrelation */ + for (sfb = s->cur_sfb_offsets; + sfb < s->cur_sfb_offsets + s->num_bands; sfb++) { + int y; + if (*tb++ == 1) { + /** multiply values with the decorrelation_matrix */ + for (y = sfb[0]; y < FFMIN(sfb[1], s->subframe_len); y++) { + const float* mat = s->chgroup[i].decorrelation_matrix; + const float* data_end = data + num_channels; + float* data_ptr = data; + float** ch; + + for (ch = ch_data; ch < ch_end; ch++) + *data_ptr++ = (*ch)[y]; + + for (ch = ch_data; ch < ch_end; ch++) { + float sum = 0; + data_ptr = data; + while (data_ptr < data_end) + sum += *data_ptr++ * *mat++; + + (*ch)[y] = sum; + } + } + } else if (s->avctx->channels == 2) { + int len = FFMIN(sfb[1], s->subframe_len) - sfb[0]; + s->fdsp.vector_fmul_scalar(ch_data[0] + sfb[0], + ch_data[0] + sfb[0], + 181.0 / 128, len); + s->fdsp.vector_fmul_scalar(ch_data[1] + sfb[0], + ch_data[1] + sfb[0], + 181.0 / 128, len); + } + } + } + } +} + +/** + *@brief Apply sine window and reconstruct the output buffer. + *@param s codec context + */ +static void wmapro_window(WMAProDecodeCtx *s) +{ + int i; + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + float* window; + int winlen = s->channel[c].prev_block_len; + float* start = s->channel[c].coeffs - (winlen >> 1); + + if (s->subframe_len < winlen) { + start += (winlen - s->subframe_len) >> 1; + winlen = s->subframe_len; + } + + window = s->windows[av_log2(winlen) - WMAPRO_BLOCK_MIN_BITS]; + + winlen >>= 1; + + s->fdsp.vector_fmul_window(start, start, start + winlen, + window, winlen); + + s->channel[c].prev_block_len = s->subframe_len; + } +} + +/** + *@brief Decode a single subframe (block). + *@param s codec context + *@return 0 on success, < 0 when decoding failed + */ +static int decode_subframe(WMAProDecodeCtx *s) +{ + int offset = s->samples_per_frame; + int subframe_len = s->samples_per_frame; + int i; + int total_samples = s->samples_per_frame * s->avctx->channels; + int transmit_coeffs = 0; + int cur_subwoofer_cutoff; + + s->subframe_offset = get_bits_count(&s->gb); + + /** reset channel context and find the next block offset and size + == the next block of the channel with the smallest number of + decoded samples + */ + for (i = 0; i < s->avctx->channels; i++) { + s->channel[i].grouped = 0; + if (offset > s->channel[i].decoded_samples) { + offset = s->channel[i].decoded_samples; + subframe_len = + s->channel[i].subframe_len[s->channel[i].cur_subframe]; + } + } + + av_dlog(s->avctx, + "processing subframe with offset %i len %i\n", offset, subframe_len); + + /** get a list of all channels that contain the estimated block */ + s->channels_for_cur_subframe = 0; + for (i = 0; i < s->avctx->channels; i++) { + const int cur_subframe = s->channel[i].cur_subframe; + /** subtract already processed samples */ + total_samples -= s->channel[i].decoded_samples; + + /** and count if there are multiple subframes that match our profile */ + if (offset == s->channel[i].decoded_samples && + subframe_len == s->channel[i].subframe_len[cur_subframe]) { + total_samples -= s->channel[i].subframe_len[cur_subframe]; + s->channel[i].decoded_samples += + s->channel[i].subframe_len[cur_subframe]; + s->channel_indexes_for_cur_subframe[s->channels_for_cur_subframe] = i; + ++s->channels_for_cur_subframe; + } + } + + /** check if the frame will be complete after processing the + estimated block */ + if (!total_samples) + s->parsed_all_subframes = 1; + + + av_dlog(s->avctx, "subframe is part of %i channels\n", + s->channels_for_cur_subframe); + + /** calculate number of scale factor bands and their offsets */ + s->table_idx = av_log2(s->samples_per_frame/subframe_len); + s->num_bands = s->num_sfb[s->table_idx]; + s->cur_sfb_offsets = s->sfb_offsets[s->table_idx]; + cur_subwoofer_cutoff = s->subwoofer_cutoffs[s->table_idx]; + + /** configure the decoder for the current subframe */ + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + + s->channel[c].coeffs = &s->channel[c].out[(s->samples_per_frame >> 1) + + offset]; + } + + s->subframe_len = subframe_len; + s->esc_len = av_log2(s->subframe_len - 1) + 1; + + /** skip extended header if any */ + if (get_bits1(&s->gb)) { + int num_fill_bits; + if (!(num_fill_bits = get_bits(&s->gb, 2))) { + int len = get_bits(&s->gb, 4); + num_fill_bits = (len ? get_bits(&s->gb, len) : 0) + 1; + } + + if (num_fill_bits >= 0) { + if (get_bits_count(&s->gb) + num_fill_bits > s->num_saved_bits) { + av_log(s->avctx, AV_LOG_ERROR, "invalid number of fill bits\n"); + return AVERROR_INVALIDDATA; + } + + skip_bits_long(&s->gb, num_fill_bits); + } + } + + /** no idea for what the following bit is used */ + if (get_bits1(&s->gb)) { + avpriv_request_sample(s->avctx, "Reserved bit"); + return AVERROR_PATCHWELCOME; + } + + + if (decode_channel_transform(s) < 0) + return AVERROR_INVALIDDATA; + + + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + if ((s->channel[c].transmit_coefs = get_bits1(&s->gb))) + transmit_coeffs = 1; + } + + av_assert0(s->subframe_len <= WMAPRO_BLOCK_MAX_SIZE); + if (transmit_coeffs) { + int step; + int quant_step = 90 * s->bits_per_sample >> 4; + + /** decode number of vector coded coefficients */ + if ((s->transmit_num_vec_coeffs = get_bits1(&s->gb))) { + int num_bits = av_log2((s->subframe_len + 3)/4) + 1; + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + int num_vec_coeffs = get_bits(&s->gb, num_bits) << 2; + if (num_vec_coeffs > s->subframe_len) { + av_log(s->avctx, AV_LOG_ERROR, "num_vec_coeffs %d is too large\n", num_vec_coeffs); + return AVERROR_INVALIDDATA; + } + s->channel[c].num_vec_coeffs = num_vec_coeffs; + } + } else { + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + s->channel[c].num_vec_coeffs = s->subframe_len; + } + } + /** decode quantization step */ + step = get_sbits(&s->gb, 6); + quant_step += step; + if (step == -32 || step == 31) { + const int sign = (step == 31) - 1; + int quant = 0; + while (get_bits_count(&s->gb) + 5 < s->num_saved_bits && + (step = get_bits(&s->gb, 5)) == 31) { + quant += 31; + } + quant_step += ((quant + step) ^ sign) - sign; + } + if (quant_step < 0) { + av_log(s->avctx, AV_LOG_DEBUG, "negative quant step\n"); + } + + /** decode quantization step modifiers for every channel */ + + if (s->channels_for_cur_subframe == 1) { + s->channel[s->channel_indexes_for_cur_subframe[0]].quant_step = quant_step; + } else { + int modifier_len = get_bits(&s->gb, 3); + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + s->channel[c].quant_step = quant_step; + if (get_bits1(&s->gb)) { + if (modifier_len) { + s->channel[c].quant_step += get_bits(&s->gb, modifier_len) + 1; + } else + ++s->channel[c].quant_step; + } + } + } + + /** decode scale factors */ + if (decode_scale_factors(s) < 0) + return AVERROR_INVALIDDATA; + } + + av_dlog(s->avctx, "BITSTREAM: subframe header length was %i\n", + get_bits_count(&s->gb) - s->subframe_offset); + + /** parse coefficients */ + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + if (s->channel[c].transmit_coefs && + get_bits_count(&s->gb) < s->num_saved_bits) { + decode_coeffs(s, c); + } else + memset(s->channel[c].coeffs, 0, + sizeof(*s->channel[c].coeffs) * subframe_len); + } + + av_dlog(s->avctx, "BITSTREAM: subframe length was %i\n", + get_bits_count(&s->gb) - s->subframe_offset); + + if (transmit_coeffs) { + FFTContext *mdct = &s->mdct_ctx[av_log2(subframe_len) - WMAPRO_BLOCK_MIN_BITS]; + /** reconstruct the per channel data */ + inverse_channel_transform(s); + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + const int* sf = s->channel[c].scale_factors; + int b; + + if (c == s->lfe_channel) + memset(&s->tmp[cur_subwoofer_cutoff], 0, sizeof(*s->tmp) * + (subframe_len - cur_subwoofer_cutoff)); + + /** inverse quantization and rescaling */ + for (b = 0; b < s->num_bands; b++) { + const int end = FFMIN(s->cur_sfb_offsets[b+1], s->subframe_len); + const int exp = s->channel[c].quant_step - + (s->channel[c].max_scale_factor - *sf++) * + s->channel[c].scale_factor_step; + const float quant = pow(10.0, exp / 20.0); + int start = s->cur_sfb_offsets[b]; + s->fdsp.vector_fmul_scalar(s->tmp + start, + s->channel[c].coeffs + start, + quant, end - start); + } + + /** apply imdct (imdct_half == DCTIV with reverse) */ + mdct->imdct_half(mdct, s->channel[c].coeffs, s->tmp); + } + } + + /** window and overlapp-add */ + wmapro_window(s); + + /** handled one subframe */ + for (i = 0; i < s->channels_for_cur_subframe; i++) { + int c = s->channel_indexes_for_cur_subframe[i]; + if (s->channel[c].cur_subframe >= s->channel[c].num_subframes) { + av_log(s->avctx, AV_LOG_ERROR, "broken subframe\n"); + return AVERROR_INVALIDDATA; + } + ++s->channel[c].cur_subframe; + } + + return 0; +} + +/** + *@brief Decode one WMA frame. + *@param s codec context + *@return 0 if the trailer bit indicates that this is the last frame, + * 1 if there are additional frames + */ +static int decode_frame(WMAProDecodeCtx *s, AVFrame *frame, int *got_frame_ptr) +{ + AVCodecContext *avctx = s->avctx; + GetBitContext* gb = &s->gb; + int more_frames = 0; + int len = 0; + int i, ret; + + /** get frame length */ + if (s->len_prefix) + len = get_bits(gb, s->log2_frame_size); + + av_dlog(s->avctx, "decoding frame with length %x\n", len); + + /** decode tile information */ + if (decode_tilehdr(s)) { + s->packet_loss = 1; + return 0; + } + + /** read postproc transform */ + if (s->avctx->channels > 1 && get_bits1(gb)) { + if (get_bits1(gb)) { + for (i = 0; i < avctx->channels * avctx->channels; i++) + skip_bits(gb, 4); + } + } + + /** read drc info */ + if (s->dynamic_range_compression) { + s->drc_gain = get_bits(gb, 8); + av_dlog(s->avctx, "drc_gain %i\n", s->drc_gain); + } + + /** no idea what these are for, might be the number of samples + that need to be skipped at the beginning or end of a stream */ + if (get_bits1(gb)) { + int av_unused skip; + + /** usually true for the first frame */ + if (get_bits1(gb)) { + skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); + av_dlog(s->avctx, "start skip: %i\n", skip); + } + + /** sometimes true for the last frame */ + if (get_bits1(gb)) { + skip = get_bits(gb, av_log2(s->samples_per_frame * 2)); + av_dlog(s->avctx, "end skip: %i\n", skip); + } + + } + + av_dlog(s->avctx, "BITSTREAM: frame header length was %i\n", + get_bits_count(gb) - s->frame_offset); + + /** reset subframe states */ + s->parsed_all_subframes = 0; + for (i = 0; i < avctx->channels; i++) { + s->channel[i].decoded_samples = 0; + s->channel[i].cur_subframe = 0; + s->channel[i].reuse_sf = 0; + } + + /** decode all subframes */ + while (!s->parsed_all_subframes) { + if (decode_subframe(s) < 0) { + s->packet_loss = 1; + return 0; + } + } + + /* get output buffer */ + frame->nb_samples = s->samples_per_frame; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { + s->packet_loss = 1; + return 0; + } + + /** copy samples to the output buffer */ + for (i = 0; i < avctx->channels; i++) + memcpy(frame->extended_data[i], s->channel[i].out, + s->samples_per_frame * sizeof(*s->channel[i].out)); + + for (i = 0; i < avctx->channels; i++) { + /** reuse second half of the IMDCT output for the next frame */ + memcpy(&s->channel[i].out[0], + &s->channel[i].out[s->samples_per_frame], + s->samples_per_frame * sizeof(*s->channel[i].out) >> 1); + } + + if (s->skip_frame) { + s->skip_frame = 0; + *got_frame_ptr = 0; + av_frame_unref(frame); + } else { + *got_frame_ptr = 1; + } + + if (s->len_prefix) { + if (len != (get_bits_count(gb) - s->frame_offset) + 2) { + /** FIXME: not sure if this is always an error */ + av_log(s->avctx, AV_LOG_ERROR, + "frame[%i] would have to skip %i bits\n", s->frame_num, + len - (get_bits_count(gb) - s->frame_offset) - 1); + s->packet_loss = 1; + return 0; + } + + /** skip the rest of the frame data */ + skip_bits_long(gb, len - (get_bits_count(gb) - s->frame_offset) - 1); + } else { + while (get_bits_count(gb) < s->num_saved_bits && get_bits1(gb) == 0) { + } + } + + /** decode trailer bit */ + more_frames = get_bits1(gb); + + ++s->frame_num; + return more_frames; +} + +/** + *@brief Calculate remaining input buffer length. + *@param s codec context + *@param gb bitstream reader context + *@return remaining size in bits + */ +static int remaining_bits(WMAProDecodeCtx *s, GetBitContext *gb) +{ + return s->buf_bit_size - get_bits_count(gb); +} + +/** + *@brief Fill the bit reservoir with a (partial) frame. + *@param s codec context + *@param gb bitstream reader context + *@param len length of the partial frame + *@param append decides whether to reset the buffer or not + */ +static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len, + int append) +{ + int buflen; + + /** when the frame data does not need to be concatenated, the input buffer + is reset and additional bits from the previous frame are copied + and skipped later so that a fast byte copy is possible */ + + if (!append) { + s->frame_offset = get_bits_count(gb) & 7; + s->num_saved_bits = s->frame_offset; + init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); + } + + buflen = (put_bits_count(&s->pb) + len + 8) >> 3; + + if (len <= 0 || buflen > MAX_FRAMESIZE) { + avpriv_request_sample(s->avctx, "Too small input buffer"); + s->packet_loss = 1; + return; + } + + s->num_saved_bits += len; + if (!append) { + avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), + s->num_saved_bits); + } else { + int align = 8 - (get_bits_count(gb) & 7); + align = FFMIN(align, len); + put_bits(&s->pb, align, get_bits(gb, align)); + len -= align; + avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len); + } + skip_bits_long(gb, len); + + { + PutBitContext tmp = s->pb; + flush_put_bits(&tmp); + } + + init_get_bits(&s->gb, s->frame_data, s->num_saved_bits); + skip_bits(&s->gb, s->frame_offset); +} + +/** + *@brief Decode a single WMA packet. + *@param avctx codec context + *@param data the output buffer + *@param avpkt input packet + *@return number of bytes that were read from the input buffer + */ +static int decode_packet(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket* avpkt) +{ + WMAProDecodeCtx *s = avctx->priv_data; + GetBitContext* gb = &s->pgb; + const uint8_t* buf = avpkt->data; + int buf_size = avpkt->size; + int num_bits_prev_frame; + int packet_sequence_number; + + *got_frame_ptr = 0; + + if (s->packet_done || s->packet_loss) { + s->packet_done = 0; + + /** sanity check for the buffer length */ + if (buf_size < avctx->block_align) { + av_log(avctx, AV_LOG_ERROR, "Input packet too small (%d < %d)\n", + buf_size, avctx->block_align); + return AVERROR_INVALIDDATA; + } + + s->next_packet_start = buf_size - avctx->block_align; + buf_size = avctx->block_align; + s->buf_bit_size = buf_size << 3; + + /** parse packet header */ + init_get_bits(gb, buf, s->buf_bit_size); + packet_sequence_number = get_bits(gb, 4); + skip_bits(gb, 2); + + /** get number of bits that need to be added to the previous frame */ + num_bits_prev_frame = get_bits(gb, s->log2_frame_size); + av_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number, + num_bits_prev_frame); + + /** check for packet loss */ + if (!s->packet_loss && + ((s->packet_sequence_number + 1) & 0xF) != packet_sequence_number) { + s->packet_loss = 1; + av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n", + s->packet_sequence_number, packet_sequence_number); + } + s->packet_sequence_number = packet_sequence_number; + + if (num_bits_prev_frame > 0) { + int remaining_packet_bits = s->buf_bit_size - get_bits_count(gb); + if (num_bits_prev_frame >= remaining_packet_bits) { + num_bits_prev_frame = remaining_packet_bits; + s->packet_done = 1; + } + + /** append the previous frame data to the remaining data from the + previous packet to create a full frame */ + save_bits(s, gb, num_bits_prev_frame, 1); + av_dlog(avctx, "accumulated %x bits of frame data\n", + s->num_saved_bits - s->frame_offset); + + /** decode the cross packet frame if it is valid */ + if (!s->packet_loss) + decode_frame(s, data, got_frame_ptr); + } else if (s->num_saved_bits - s->frame_offset) { + av_dlog(avctx, "ignoring %x previously saved bits\n", + s->num_saved_bits - s->frame_offset); + } + + if (s->packet_loss) { + /** reset number of saved bits so that the decoder + does not start to decode incomplete frames in the + s->len_prefix == 0 case */ + s->num_saved_bits = 0; + s->packet_loss = 0; + } + + } else { + int frame_size; + s->buf_bit_size = (avpkt->size - s->next_packet_start) << 3; + init_get_bits(gb, avpkt->data, s->buf_bit_size); + skip_bits(gb, s->packet_offset); + if (s->len_prefix && remaining_bits(s, gb) > s->log2_frame_size && + (frame_size = show_bits(gb, s->log2_frame_size)) && + frame_size <= remaining_bits(s, gb)) { + save_bits(s, gb, frame_size, 0); + s->packet_done = !decode_frame(s, data, got_frame_ptr); + } else if (!s->len_prefix + && s->num_saved_bits > get_bits_count(&s->gb)) { + /** when the frames do not have a length prefix, we don't know + the compressed length of the individual frames + however, we know what part of a new packet belongs to the + previous frame + therefore we save the incoming packet first, then we append + the "previous frame" data from the next packet so that + we get a buffer that only contains full frames */ + s->packet_done = !decode_frame(s, data, got_frame_ptr); + } else + s->packet_done = 1; + } + + if (s->packet_done && !s->packet_loss && + remaining_bits(s, gb) > 0) { + /** save the rest of the data so that it can be decoded + with the next packet */ + save_bits(s, gb, remaining_bits(s, gb), 0); + } + + s->packet_offset = get_bits_count(gb) & 7; + if (s->packet_loss) + return AVERROR_INVALIDDATA; + + return get_bits_count(gb) >> 3; +} + +/** + *@brief Clear decoder buffers (for seeking). + *@param avctx codec context + */ +static void flush(AVCodecContext *avctx) +{ + WMAProDecodeCtx *s = avctx->priv_data; + int i; + /** reset output buffer as a part of it is used during the windowing of a + new frame */ + for (i = 0; i < avctx->channels; i++) + memset(s->channel[i].out, 0, s->samples_per_frame * + sizeof(*s->channel[i].out)); + s->packet_loss = 1; +} + + +/** + *@brief wmapro decoder + */ +AVCodec ff_wmapro_decoder = { + .name = "wmapro", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMAPRO, + .priv_data_size = sizeof(WMAProDecodeCtx), + .init = decode_init, + .close = decode_end, + .decode = decode_packet, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .flush = flush, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE }, +}; diff --git a/ffmpeg/libavcodec/wmavoice.c b/ffmpeg/libavcodec/wmavoice.c new file mode 100644 index 0000000..19f8965 --- /dev/null +++ b/ffmpeg/libavcodec/wmavoice.c @@ -0,0 +1,2055 @@ +/* + * Windows Media Audio Voice decoder. + * Copyright (c) 2009 Ronald S. Bultje + * + * 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 + */ + +/** + * @file + * @brief Windows Media Audio Voice compatible decoder + * @author Ronald S. Bultje + */ + +#include + +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" +#include "libavutil/mem.h" +#include "avcodec.h" +#include "internal.h" +#include "get_bits.h" +#include "put_bits.h" +#include "wmavoice_data.h" +#include "celp_filters.h" +#include "acelp_vectors.h" +#include "acelp_filters.h" +#include "lsp.h" +#include "dct.h" +#include "rdft.h" +#include "sinewin.h" + +#define MAX_BLOCKS 8 ///< maximum number of blocks per frame +#define MAX_LSPS 16 ///< maximum filter order +#define MAX_LSPS_ALIGN16 16 ///< same as #MAX_LSPS; needs to be multiple + ///< of 16 for ASM input buffer alignment +#define MAX_FRAMES 3 ///< maximum number of frames per superframe +#define MAX_FRAMESIZE 160 ///< maximum number of samples per frame +#define MAX_SIGNAL_HISTORY 416 ///< maximum excitation signal history +#define MAX_SFRAMESIZE (MAX_FRAMESIZE * MAX_FRAMES) + ///< maximum number of samples per superframe +#define SFRAME_CACHE_MAXSIZE 256 ///< maximum cache size for frame data that + ///< was split over two packets +#define VLC_NBITS 6 ///< number of bits to read per VLC iteration + +/** + * Frame type VLC coding. + */ +static VLC frame_type_vlc; + +/** + * Adaptive codebook types. + */ +enum { + ACB_TYPE_NONE = 0, ///< no adaptive codebook (only hardcoded fixed) + ACB_TYPE_ASYMMETRIC = 1, ///< adaptive codebook with per-frame pitch, which + ///< we interpolate to get a per-sample pitch. + ///< Signal is generated using an asymmetric sinc + ///< window function + ///< @note see #wmavoice_ipol1_coeffs + ACB_TYPE_HAMMING = 2 ///< Per-block pitch with signal generation using + ///< a Hamming sinc window function + ///< @note see #wmavoice_ipol2_coeffs +}; + +/** + * Fixed codebook types. + */ +enum { + FCB_TYPE_SILENCE = 0, ///< comfort noise during silence + ///< generated from a hardcoded (fixed) codebook + ///< with per-frame (low) gain values + FCB_TYPE_HARDCODED = 1, ///< hardcoded (fixed) codebook with per-block + ///< gain values + FCB_TYPE_AW_PULSES = 2, ///< Pitch-adaptive window (AW) pulse signals, + ///< used in particular for low-bitrate streams + FCB_TYPE_EXC_PULSES = 3, ///< Innovation (fixed) codebook pulse sets in + ///< combinations of either single pulses or + ///< pulse pairs +}; + +/** + * Description of frame types. + */ +static const struct frame_type_desc { + uint8_t n_blocks; ///< amount of blocks per frame (each block + ///< (contains 160/#n_blocks samples) + uint8_t log_n_blocks; ///< log2(#n_blocks) + uint8_t acb_type; ///< Adaptive codebook type (ACB_TYPE_*) + uint8_t fcb_type; ///< Fixed codebook type (FCB_TYPE_*) + uint8_t dbl_pulses; ///< how many pulse vectors have pulse pairs + ///< (rather than just one single pulse) + ///< only if #fcb_type == #FCB_TYPE_EXC_PULSES + uint16_t frame_size; ///< the amount of bits that make up the block + ///< data (per frame) +} frame_descs[17] = { + { 1, 0, ACB_TYPE_NONE, FCB_TYPE_SILENCE, 0, 0 }, + { 2, 1, ACB_TYPE_NONE, FCB_TYPE_HARDCODED, 0, 28 }, + { 2, 1, ACB_TYPE_ASYMMETRIC, FCB_TYPE_AW_PULSES, 0, 46 }, + { 2, 1, ACB_TYPE_ASYMMETRIC, FCB_TYPE_EXC_PULSES, 2, 80 }, + { 2, 1, ACB_TYPE_ASYMMETRIC, FCB_TYPE_EXC_PULSES, 5, 104 }, + { 4, 2, ACB_TYPE_ASYMMETRIC, FCB_TYPE_EXC_PULSES, 0, 108 }, + { 4, 2, ACB_TYPE_ASYMMETRIC, FCB_TYPE_EXC_PULSES, 2, 132 }, + { 4, 2, ACB_TYPE_ASYMMETRIC, FCB_TYPE_EXC_PULSES, 5, 168 }, + { 2, 1, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 0, 64 }, + { 2, 1, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 2, 80 }, + { 2, 1, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 5, 104 }, + { 4, 2, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 0, 108 }, + { 4, 2, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 2, 132 }, + { 4, 2, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 5, 168 }, + { 8, 3, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 0, 176 }, + { 8, 3, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 2, 208 }, + { 8, 3, ACB_TYPE_HAMMING, FCB_TYPE_EXC_PULSES, 5, 256 } +}; + +/** + * WMA Voice decoding context. + */ +typedef struct { + /** + * @name Global values specified in the stream header / extradata or used all over. + * @{ + */ + GetBitContext gb; ///< packet bitreader. During decoder init, + ///< it contains the extradata from the + ///< demuxer. During decoding, it contains + ///< packet data. + int8_t vbm_tree[25]; ///< converts VLC codes to frame type + + int spillover_bitsize; ///< number of bits used to specify + ///< #spillover_nbits in the packet header + ///< = ceil(log2(ctx->block_align << 3)) + int history_nsamples; ///< number of samples in history for signal + ///< prediction (through ACB) + + /* postfilter specific values */ + int do_apf; ///< whether to apply the averaged + ///< projection filter (APF) + int denoise_strength; ///< strength of denoising in Wiener filter + ///< [0-11] + int denoise_tilt_corr; ///< Whether to apply tilt correction to the + ///< Wiener filter coefficients (postfilter) + int dc_level; ///< Predicted amount of DC noise, based + ///< on which a DC removal filter is used + + int lsps; ///< number of LSPs per frame [10 or 16] + int lsp_q_mode; ///< defines quantizer defaults [0, 1] + int lsp_def_mode; ///< defines different sets of LSP defaults + ///< [0, 1] + int frame_lsp_bitsize; ///< size (in bits) of LSPs, when encoded + ///< per-frame (independent coding) + int sframe_lsp_bitsize; ///< size (in bits) of LSPs, when encoded + ///< per superframe (residual coding) + + int min_pitch_val; ///< base value for pitch parsing code + int max_pitch_val; ///< max value + 1 for pitch parsing + int pitch_nbits; ///< number of bits used to specify the + ///< pitch value in the frame header + int block_pitch_nbits; ///< number of bits used to specify the + ///< first block's pitch value + int block_pitch_range; ///< range of the block pitch + int block_delta_pitch_nbits; ///< number of bits used to specify the + ///< delta pitch between this and the last + ///< block's pitch value, used in all but + ///< first block + int block_delta_pitch_hrange; ///< 1/2 range of the delta (full range is + ///< from -this to +this-1) + uint16_t block_conv_table[4]; ///< boundaries for block pitch unit/scale + ///< conversion + + /** + * @} + * + * @name Packet values specified in the packet header or related to a packet. + * + * A packet is considered to be a single unit of data provided to this + * decoder by the demuxer. + * @{ + */ + int spillover_nbits; ///< number of bits of the previous packet's + ///< last superframe preceding this + ///< packet's first full superframe (useful + ///< for re-synchronization also) + int has_residual_lsps; ///< if set, superframes contain one set of + ///< LSPs that cover all frames, encoded as + ///< independent and residual LSPs; if not + ///< set, each frame contains its own, fully + ///< independent, LSPs + int skip_bits_next; ///< number of bits to skip at the next call + ///< to #wmavoice_decode_packet() (since + ///< they're part of the previous superframe) + + uint8_t sframe_cache[SFRAME_CACHE_MAXSIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + ///< cache for superframe data split over + ///< multiple packets + int sframe_cache_size; ///< set to >0 if we have data from an + ///< (incomplete) superframe from a previous + ///< packet that spilled over in the current + ///< packet; specifies the amount of bits in + ///< #sframe_cache + PutBitContext pb; ///< bitstream writer for #sframe_cache + + /** + * @} + * + * @name Frame and superframe values + * Superframe and frame data - these can change from frame to frame, + * although some of them do in that case serve as a cache / history for + * the next frame or superframe. + * @{ + */ + double prev_lsps[MAX_LSPS]; ///< LSPs of the last frame of the previous + ///< superframe + int last_pitch_val; ///< pitch value of the previous frame + int last_acb_type; ///< frame type [0-2] of the previous frame + int pitch_diff_sh16; ///< ((cur_pitch_val - #last_pitch_val) + ///< << 16) / #MAX_FRAMESIZE + float silence_gain; ///< set for use in blocks if #ACB_TYPE_NONE + + int aw_idx_is_ext; ///< whether the AW index was encoded in + ///< 8 bits (instead of 6) + int aw_pulse_range; ///< the range over which #aw_pulse_set1() + ///< can apply the pulse, relative to the + ///< value in aw_first_pulse_off. The exact + ///< position of the first AW-pulse is within + ///< [pulse_off, pulse_off + this], and + ///< depends on bitstream values; [16 or 24] + int aw_n_pulses[2]; ///< number of AW-pulses in each block; note + ///< that this number can be negative (in + ///< which case it basically means "zero") + int aw_first_pulse_off[2]; ///< index of first sample to which to + ///< apply AW-pulses, or -0xff if unset + int aw_next_pulse_off_cache; ///< the position (relative to start of the + ///< second block) at which pulses should + ///< start to be positioned, serves as a + ///< cache for pitch-adaptive window pulses + ///< between blocks + + int frame_cntr; ///< current frame index [0 - 0xFFFE]; is + ///< only used for comfort noise in #pRNG() + float gain_pred_err[6]; ///< cache for gain prediction + float excitation_history[MAX_SIGNAL_HISTORY]; + ///< cache of the signal of previous + ///< superframes, used as a history for + ///< signal generation + float synth_history[MAX_LSPS]; ///< see #excitation_history + /** + * @} + * + * @name Postfilter values + * + * Variables used for postfilter implementation, mostly history for + * smoothing and so on, and context variables for FFT/iFFT. + * @{ + */ + RDFTContext rdft, irdft; ///< contexts for FFT-calculation in the + ///< postfilter (for denoise filter) + DCTContext dct, dst; ///< contexts for phase shift (in Hilbert + ///< transform, part of postfilter) + float sin[511], cos[511]; ///< 8-bit cosine/sine windows over [-pi,pi] + ///< range + float postfilter_agc; ///< gain control memory, used in + ///< #adaptive_gain_control() + float dcf_mem[2]; ///< DC filter history + float zero_exc_pf[MAX_SIGNAL_HISTORY + MAX_SFRAMESIZE]; + ///< zero filter output (i.e. excitation) + ///< by postfilter + float denoise_filter_cache[MAX_FRAMESIZE]; + int denoise_filter_cache_size; ///< samples in #denoise_filter_cache + DECLARE_ALIGNED(32, float, tilted_lpcs_pf)[0x80]; + ///< aligned buffer for LPC tilting + DECLARE_ALIGNED(32, float, denoise_coeffs_pf)[0x80]; + ///< aligned buffer for denoise coefficients + DECLARE_ALIGNED(32, float, synth_filter_out_buf)[0x80 + MAX_LSPS_ALIGN16]; + ///< aligned buffer for postfilter speech + ///< synthesis + /** + * @} + */ +} WMAVoiceContext; + +/** + * Set up the variable bit mode (VBM) tree from container extradata. + * @param gb bit I/O context. + * The bit context (s->gb) should be loaded with byte 23-46 of the + * container extradata (i.e. the ones containing the VBM tree). + * @param vbm_tree pointer to array to which the decoded VBM tree will be + * written. + * @return 0 on success, <0 on error. + */ +static av_cold int decode_vbmtree(GetBitContext *gb, int8_t vbm_tree[25]) +{ + static const uint8_t bits[] = { + 2, 2, 2, 4, 4, 4, + 6, 6, 6, 8, 8, 8, + 10, 10, 10, 12, 12, 12, + 14, 14, 14, 14 + }; + static const uint16_t codes[] = { + 0x0000, 0x0001, 0x0002, // 00/01/10 + 0x000c, 0x000d, 0x000e, // 11+00/01/10 + 0x003c, 0x003d, 0x003e, // 1111+00/01/10 + 0x00fc, 0x00fd, 0x00fe, // 111111+00/01/10 + 0x03fc, 0x03fd, 0x03fe, // 11111111+00/01/10 + 0x0ffc, 0x0ffd, 0x0ffe, // 1111111111+00/01/10 + 0x3ffc, 0x3ffd, 0x3ffe, 0x3fff // 111111111111+xx + }; + int cntr[8] = { 0 }, n, res; + + memset(vbm_tree, 0xff, sizeof(vbm_tree[0]) * 25); + for (n = 0; n < 17; n++) { + res = get_bits(gb, 3); + if (cntr[res] > 3) // should be >= 3 + (res == 7)) + return -1; + vbm_tree[res * 3 + cntr[res]++] = n; + } + INIT_VLC_STATIC(&frame_type_vlc, VLC_NBITS, sizeof(bits), + bits, 1, 1, codes, 2, 2, 132); + return 0; +} + +/** + * Set up decoder with parameters from demuxer (extradata etc.). + */ +static av_cold int wmavoice_decode_init(AVCodecContext *ctx) +{ + int n, flags, pitch_range, lsp16_flag; + WMAVoiceContext *s = ctx->priv_data; + + /** + * Extradata layout: + * - byte 0-18: WMAPro-in-WMAVoice extradata (see wmaprodec.c), + * - byte 19-22: flags field (annoyingly in LE; see below for known + * values), + * - byte 23-46: variable bitmode tree (really just 17 * 3 bits, + * rest is 0). + */ + if (ctx->extradata_size != 46) { + av_log(ctx, AV_LOG_ERROR, + "Invalid extradata size %d (should be 46)\n", + ctx->extradata_size); + return -1; + } + flags = AV_RL32(ctx->extradata + 18); + s->spillover_bitsize = 3 + av_ceil_log2(ctx->block_align); + s->do_apf = flags & 0x1; + if (s->do_apf) { + ff_rdft_init(&s->rdft, 7, DFT_R2C); + ff_rdft_init(&s->irdft, 7, IDFT_C2R); + ff_dct_init(&s->dct, 6, DCT_I); + ff_dct_init(&s->dst, 6, DST_I); + + ff_sine_window_init(s->cos, 256); + memcpy(&s->sin[255], s->cos, 256 * sizeof(s->cos[0])); + for (n = 0; n < 255; n++) { + s->sin[n] = -s->sin[510 - n]; + s->cos[510 - n] = s->cos[n]; + } + } + s->denoise_strength = (flags >> 2) & 0xF; + if (s->denoise_strength >= 12) { + av_log(ctx, AV_LOG_ERROR, + "Invalid denoise filter strength %d (max=11)\n", + s->denoise_strength); + return -1; + } + s->denoise_tilt_corr = !!(flags & 0x40); + s->dc_level = (flags >> 7) & 0xF; + s->lsp_q_mode = !!(flags & 0x2000); + s->lsp_def_mode = !!(flags & 0x4000); + lsp16_flag = flags & 0x1000; + if (lsp16_flag) { + s->lsps = 16; + s->frame_lsp_bitsize = 34; + s->sframe_lsp_bitsize = 60; + } else { + s->lsps = 10; + s->frame_lsp_bitsize = 24; + s->sframe_lsp_bitsize = 48; + } + for (n = 0; n < s->lsps; n++) + s->prev_lsps[n] = M_PI * (n + 1.0) / (s->lsps + 1.0); + + init_get_bits(&s->gb, ctx->extradata + 22, (ctx->extradata_size - 22) << 3); + if (decode_vbmtree(&s->gb, s->vbm_tree) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid VBM tree; broken extradata?\n"); + return -1; + } + + s->min_pitch_val = ((ctx->sample_rate << 8) / 400 + 50) >> 8; + s->max_pitch_val = ((ctx->sample_rate << 8) * 37 / 2000 + 50) >> 8; + pitch_range = s->max_pitch_val - s->min_pitch_val; + if (pitch_range <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid pitch range; broken extradata?\n"); + return -1; + } + s->pitch_nbits = av_ceil_log2(pitch_range); + s->last_pitch_val = 40; + s->last_acb_type = ACB_TYPE_NONE; + s->history_nsamples = s->max_pitch_val + 8; + + if (s->min_pitch_val < 1 || s->history_nsamples > MAX_SIGNAL_HISTORY) { + int min_sr = ((((1 << 8) - 50) * 400) + 0xFF) >> 8, + max_sr = ((((MAX_SIGNAL_HISTORY - 8) << 8) + 205) * 2000 / 37) >> 8; + + av_log(ctx, AV_LOG_ERROR, + "Unsupported samplerate %d (min=%d, max=%d)\n", + ctx->sample_rate, min_sr, max_sr); // 322-22097 Hz + + return -1; + } + + s->block_conv_table[0] = s->min_pitch_val; + s->block_conv_table[1] = (pitch_range * 25) >> 6; + s->block_conv_table[2] = (pitch_range * 44) >> 6; + s->block_conv_table[3] = s->max_pitch_val - 1; + s->block_delta_pitch_hrange = (pitch_range >> 3) & ~0xF; + if (s->block_delta_pitch_hrange <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid delta pitch hrange; broken extradata?\n"); + return -1; + } + s->block_delta_pitch_nbits = 1 + av_ceil_log2(s->block_delta_pitch_hrange); + s->block_pitch_range = s->block_conv_table[2] + + s->block_conv_table[3] + 1 + + 2 * (s->block_conv_table[1] - 2 * s->min_pitch_val); + s->block_pitch_nbits = av_ceil_log2(s->block_pitch_range); + + ctx->channels = 1; + ctx->channel_layout = AV_CH_LAYOUT_MONO; + ctx->sample_fmt = AV_SAMPLE_FMT_FLT; + + return 0; +} + +/** + * @name Postfilter functions + * Postfilter functions (gain control, wiener denoise filter, DC filter, + * kalman smoothening, plus surrounding code to wrap it) + * @{ + */ +/** + * Adaptive gain control (as used in postfilter). + * + * Identical to #ff_adaptive_gain_control() in acelp_vectors.c, except + * that the energy here is calculated using sum(abs(...)), whereas the + * other codecs (e.g. AMR-NB, SIPRO) use sqrt(dotproduct(...)). + * + * @param out output buffer for filtered samples + * @param in input buffer containing the samples as they are after the + * postfilter steps so far + * @param speech_synth input buffer containing speech synth before postfilter + * @param size input buffer size + * @param alpha exponential filter factor + * @param gain_mem pointer to filter memory (single float) + */ +static void adaptive_gain_control(float *out, const float *in, + const float *speech_synth, + int size, float alpha, float *gain_mem) +{ + int i; + float speech_energy = 0.0, postfilter_energy = 0.0, gain_scale_factor; + float mem = *gain_mem; + + for (i = 0; i < size; i++) { + speech_energy += fabsf(speech_synth[i]); + postfilter_energy += fabsf(in[i]); + } + gain_scale_factor = (1.0 - alpha) * speech_energy / postfilter_energy; + + for (i = 0; i < size; i++) { + mem = alpha * mem + gain_scale_factor; + out[i] = in[i] * mem; + } + + *gain_mem = mem; +} + +/** + * Kalman smoothing function. + * + * This function looks back pitch +/- 3 samples back into history to find + * the best fitting curve (that one giving the optimal gain of the two + * signals, i.e. the highest dot product between the two), and then + * uses that signal history to smoothen the output of the speech synthesis + * filter. + * + * @param s WMA Voice decoding context + * @param pitch pitch of the speech signal + * @param in input speech signal + * @param out output pointer for smoothened signal + * @param size input/output buffer size + * + * @returns -1 if no smoothening took place, e.g. because no optimal + * fit could be found, or 0 on success. + */ +static int kalman_smoothen(WMAVoiceContext *s, int pitch, + const float *in, float *out, int size) +{ + int n; + float optimal_gain = 0, dot; + const float *ptr = &in[-FFMAX(s->min_pitch_val, pitch - 3)], + *end = &in[-FFMIN(s->max_pitch_val, pitch + 3)], + *best_hist_ptr = NULL; + + /* find best fitting point in history */ + do { + dot = avpriv_scalarproduct_float_c(in, ptr, size); + if (dot > optimal_gain) { + optimal_gain = dot; + best_hist_ptr = ptr; + } + } while (--ptr >= end); + + if (optimal_gain <= 0) + return -1; + dot = avpriv_scalarproduct_float_c(best_hist_ptr, best_hist_ptr, size); + if (dot <= 0) // would be 1.0 + return -1; + + if (optimal_gain <= dot) { + dot = dot / (dot + 0.6 * optimal_gain); // 0.625-1.000 + } else + dot = 0.625; + + /* actual smoothing */ + for (n = 0; n < size; n++) + out[n] = best_hist_ptr[n] + dot * (in[n] - best_hist_ptr[n]); + + return 0; +} + +/** + * Get the tilt factor of a formant filter from its transfer function + * @see #tilt_factor() in amrnbdec.c, which does essentially the same, + * but somehow (??) it does a speech synthesis filter in the + * middle, which is missing here + * + * @param lpcs LPC coefficients + * @param n_lpcs Size of LPC buffer + * @returns the tilt factor + */ +static float tilt_factor(const float *lpcs, int n_lpcs) +{ + float rh0, rh1; + + rh0 = 1.0 + avpriv_scalarproduct_float_c(lpcs, lpcs, n_lpcs); + rh1 = lpcs[0] + avpriv_scalarproduct_float_c(lpcs, &lpcs[1], n_lpcs - 1); + + return rh1 / rh0; +} + +/** + * Derive denoise filter coefficients (in real domain) from the LPCs. + */ +static void calc_input_response(WMAVoiceContext *s, float *lpcs, + int fcb_type, float *coeffs, int remainder) +{ + float last_coeff, min = 15.0, max = -15.0; + float irange, angle_mul, gain_mul, range, sq; + int n, idx; + + /* Create frequency power spectrum of speech input (i.e. RDFT of LPCs) */ + s->rdft.rdft_calc(&s->rdft, lpcs); +#define log_range(var, assign) do { \ + float tmp = log10f(assign); var = tmp; \ + max = FFMAX(max, tmp); min = FFMIN(min, tmp); \ + } while (0) + log_range(last_coeff, lpcs[1] * lpcs[1]); + for (n = 1; n < 64; n++) + log_range(lpcs[n], lpcs[n * 2] * lpcs[n * 2] + + lpcs[n * 2 + 1] * lpcs[n * 2 + 1]); + log_range(lpcs[0], lpcs[0] * lpcs[0]); +#undef log_range + range = max - min; + lpcs[64] = last_coeff; + + /* Now, use this spectrum to pick out these frequencies with higher + * (relative) power/energy (which we then take to be "not noise"), + * and set up a table (still in lpc[]) of (relative) gains per frequency. + * These frequencies will be maintained, while others ("noise") will be + * decreased in the filter output. */ + irange = 64.0 / range; // so irange*(max-value) is in the range [0, 63] + gain_mul = range * (fcb_type == FCB_TYPE_HARDCODED ? (5.0 / 13.0) : + (5.0 / 14.7)); + angle_mul = gain_mul * (8.0 * M_LN10 / M_PI); + for (n = 0; n <= 64; n++) { + float pwr; + + idx = FFMAX(0, lrint((max - lpcs[n]) * irange) - 1); + pwr = wmavoice_denoise_power_table[s->denoise_strength][idx]; + lpcs[n] = angle_mul * pwr; + + /* 70.57 =~ 1/log10(1.0331663) */ + idx = (pwr * gain_mul - 0.0295) * 70.570526123; + if (idx > 127) { // fallback if index falls outside table range + coeffs[n] = wmavoice_energy_table[127] * + powf(1.0331663, idx - 127); + } else + coeffs[n] = wmavoice_energy_table[FFMAX(0, idx)]; + } + + /* calculate the Hilbert transform of the gains, which we do (since this + * is a sinus input) by doing a phase shift (in theory, H(sin())=cos()). + * Hilbert_Transform(RDFT(x)) = Laplace_Transform(x), which calculates the + * "moment" of the LPCs in this filter. */ + s->dct.dct_calc(&s->dct, lpcs); + s->dst.dct_calc(&s->dst, lpcs); + + /* Split out the coefficient indexes into phase/magnitude pairs */ + idx = 255 + av_clip(lpcs[64], -255, 255); + coeffs[0] = coeffs[0] * s->cos[idx]; + idx = 255 + av_clip(lpcs[64] - 2 * lpcs[63], -255, 255); + last_coeff = coeffs[64] * s->cos[idx]; + for (n = 63;; n--) { + idx = 255 + av_clip(-lpcs[64] - 2 * lpcs[n - 1], -255, 255); + coeffs[n * 2 + 1] = coeffs[n] * s->sin[idx]; + coeffs[n * 2] = coeffs[n] * s->cos[idx]; + + if (!--n) break; + + idx = 255 + av_clip( lpcs[64] - 2 * lpcs[n - 1], -255, 255); + coeffs[n * 2 + 1] = coeffs[n] * s->sin[idx]; + coeffs[n * 2] = coeffs[n] * s->cos[idx]; + } + coeffs[1] = last_coeff; + + /* move into real domain */ + s->irdft.rdft_calc(&s->irdft, coeffs); + + /* tilt correction and normalize scale */ + memset(&coeffs[remainder], 0, sizeof(coeffs[0]) * (128 - remainder)); + if (s->denoise_tilt_corr) { + float tilt_mem = 0; + + coeffs[remainder - 1] = 0; + ff_tilt_compensation(&tilt_mem, + -1.8 * tilt_factor(coeffs, remainder - 1), + coeffs, remainder); + } + sq = (1.0 / 64.0) * sqrtf(1 / avpriv_scalarproduct_float_c(coeffs, coeffs, + remainder)); + for (n = 0; n < remainder; n++) + coeffs[n] *= sq; +} + +/** + * This function applies a Wiener filter on the (noisy) speech signal as + * a means to denoise it. + * + * - take RDFT of LPCs to get the power spectrum of the noise + speech; + * - using this power spectrum, calculate (for each frequency) the Wiener + * filter gain, which depends on the frequency power and desired level + * of noise subtraction (when set too high, this leads to artifacts) + * We can do this symmetrically over the X-axis (so 0-4kHz is the inverse + * of 4-8kHz); + * - by doing a phase shift, calculate the Hilbert transform of this array + * of per-frequency filter-gains to get the filtering coefficients; + * - smoothen/normalize/de-tilt these filter coefficients as desired; + * - take RDFT of noisy sound, apply the coefficients and take its IRDFT + * to get the denoised speech signal; + * - the leftover (i.e. output of the IRDFT on denoised speech data beyond + * the frame boundary) are saved and applied to subsequent frames by an + * overlap-add method (otherwise you get clicking-artifacts). + * + * @param s WMA Voice decoding context + * @param fcb_type Frame (codebook) type + * @param synth_pf input: the noisy speech signal, output: denoised speech + * data; should be 16-byte aligned (for ASM purposes) + * @param size size of the speech data + * @param lpcs LPCs used to synthesize this frame's speech data + */ +static void wiener_denoise(WMAVoiceContext *s, int fcb_type, + float *synth_pf, int size, + const float *lpcs) +{ + int remainder, lim, n; + + if (fcb_type != FCB_TYPE_SILENCE) { + float *tilted_lpcs = s->tilted_lpcs_pf, + *coeffs = s->denoise_coeffs_pf, tilt_mem = 0; + + tilted_lpcs[0] = 1.0; + memcpy(&tilted_lpcs[1], lpcs, sizeof(lpcs[0]) * s->lsps); + memset(&tilted_lpcs[s->lsps + 1], 0, + sizeof(tilted_lpcs[0]) * (128 - s->lsps - 1)); + ff_tilt_compensation(&tilt_mem, 0.7 * tilt_factor(lpcs, s->lsps), + tilted_lpcs, s->lsps + 2); + + /* The IRDFT output (127 samples for 7-bit filter) beyond the frame + * size is applied to the next frame. All input beyond this is zero, + * and thus all output beyond this will go towards zero, hence we can + * limit to min(size-1, 127-size) as a performance consideration. */ + remainder = FFMIN(127 - size, size - 1); + calc_input_response(s, tilted_lpcs, fcb_type, coeffs, remainder); + + /* apply coefficients (in frequency spectrum domain), i.e. complex + * number multiplication */ + memset(&synth_pf[size], 0, sizeof(synth_pf[0]) * (128 - size)); + s->rdft.rdft_calc(&s->rdft, synth_pf); + s->rdft.rdft_calc(&s->rdft, coeffs); + synth_pf[0] *= coeffs[0]; + synth_pf[1] *= coeffs[1]; + for (n = 1; n < 64; n++) { + float v1 = synth_pf[n * 2], v2 = synth_pf[n * 2 + 1]; + synth_pf[n * 2] = v1 * coeffs[n * 2] - v2 * coeffs[n * 2 + 1]; + synth_pf[n * 2 + 1] = v2 * coeffs[n * 2] + v1 * coeffs[n * 2 + 1]; + } + s->irdft.rdft_calc(&s->irdft, synth_pf); + } + + /* merge filter output with the history of previous runs */ + if (s->denoise_filter_cache_size) { + lim = FFMIN(s->denoise_filter_cache_size, size); + for (n = 0; n < lim; n++) + synth_pf[n] += s->denoise_filter_cache[n]; + s->denoise_filter_cache_size -= lim; + memmove(s->denoise_filter_cache, &s->denoise_filter_cache[size], + sizeof(s->denoise_filter_cache[0]) * s->denoise_filter_cache_size); + } + + /* move remainder of filter output into a cache for future runs */ + if (fcb_type != FCB_TYPE_SILENCE) { + lim = FFMIN(remainder, s->denoise_filter_cache_size); + for (n = 0; n < lim; n++) + s->denoise_filter_cache[n] += synth_pf[size + n]; + if (lim < remainder) { + memcpy(&s->denoise_filter_cache[lim], &synth_pf[size + lim], + sizeof(s->denoise_filter_cache[0]) * (remainder - lim)); + s->denoise_filter_cache_size = remainder; + } + } +} + +/** + * Averaging projection filter, the postfilter used in WMAVoice. + * + * This uses the following steps: + * - A zero-synthesis filter (generate excitation from synth signal) + * - Kalman smoothing on excitation, based on pitch + * - Re-synthesized smoothened output + * - Iterative Wiener denoise filter + * - Adaptive gain filter + * - DC filter + * + * @param s WMAVoice decoding context + * @param synth Speech synthesis output (before postfilter) + * @param samples Output buffer for filtered samples + * @param size Buffer size of synth & samples + * @param lpcs Generated LPCs used for speech synthesis + * @param zero_exc_pf destination for zero synthesis filter (16-byte aligned) + * @param fcb_type Frame type (silence, hardcoded, AW-pulses or FCB-pulses) + * @param pitch Pitch of the input signal + */ +static void postfilter(WMAVoiceContext *s, const float *synth, + float *samples, int size, + const float *lpcs, float *zero_exc_pf, + int fcb_type, int pitch) +{ + float synth_filter_in_buf[MAX_FRAMESIZE / 2], + *synth_pf = &s->synth_filter_out_buf[MAX_LSPS_ALIGN16], + *synth_filter_in = zero_exc_pf; + + av_assert0(size <= MAX_FRAMESIZE / 2); + + /* generate excitation from input signal */ + ff_celp_lp_zero_synthesis_filterf(zero_exc_pf, lpcs, synth, size, s->lsps); + + if (fcb_type >= FCB_TYPE_AW_PULSES && + !kalman_smoothen(s, pitch, zero_exc_pf, synth_filter_in_buf, size)) + synth_filter_in = synth_filter_in_buf; + + /* re-synthesize speech after smoothening, and keep history */ + ff_celp_lp_synthesis_filterf(synth_pf, lpcs, + synth_filter_in, size, s->lsps); + memcpy(&synth_pf[-s->lsps], &synth_pf[size - s->lsps], + sizeof(synth_pf[0]) * s->lsps); + + wiener_denoise(s, fcb_type, synth_pf, size, lpcs); + + adaptive_gain_control(samples, synth_pf, synth, size, 0.99, + &s->postfilter_agc); + + if (s->dc_level > 8) { + /* remove ultra-low frequency DC noise / highpass filter; + * coefficients are identical to those used in SIPR decoding, + * and very closely resemble those used in AMR-NB decoding. */ + ff_acelp_apply_order_2_transfer_function(samples, samples, + (const float[2]) { -1.99997, 1.0 }, + (const float[2]) { -1.9330735188, 0.93589198496 }, + 0.93980580475, s->dcf_mem, size); + } +} +/** + * @} + */ + +/** + * Dequantize LSPs + * @param lsps output pointer to the array that will hold the LSPs + * @param num number of LSPs to be dequantized + * @param values quantized values, contains n_stages values + * @param sizes range (i.e. max value) of each quantized value + * @param n_stages number of dequantization runs + * @param table dequantization table to be used + * @param mul_q LSF multiplier + * @param base_q base (lowest) LSF values + */ +static void dequant_lsps(double *lsps, int num, + const uint16_t *values, + const uint16_t *sizes, + int n_stages, const uint8_t *table, + const double *mul_q, + const double *base_q) +{ + int n, m; + + memset(lsps, 0, num * sizeof(*lsps)); + for (n = 0; n < n_stages; n++) { + const uint8_t *t_off = &table[values[n] * num]; + double base = base_q[n], mul = mul_q[n]; + + for (m = 0; m < num; m++) + lsps[m] += base + mul * t_off[m]; + + table += sizes[n] * num; + } +} + +/** + * @name LSP dequantization routines + * LSP dequantization routines, for 10/16LSPs and independent/residual coding. + * @note we assume enough bits are available, caller should check. + * lsp10i() consumes 24 bits; lsp10r() consumes an additional 24 bits; + * lsp16i() consumes 34 bits; lsp16r() consumes an additional 26 bits. + * @{ + */ +/** + * Parse 10 independently-coded LSPs. + */ +static void dequant_lsp10i(GetBitContext *gb, double *lsps) +{ + static const uint16_t vec_sizes[4] = { 256, 64, 32, 32 }; + static const double mul_lsf[4] = { + 5.2187144800e-3, 1.4626986422e-3, + 9.6179549166e-4, 1.1325736225e-3 + }; + static const double base_lsf[4] = { + M_PI * -2.15522e-1, M_PI * -6.1646e-2, + M_PI * -3.3486e-2, M_PI * -5.7408e-2 + }; + uint16_t v[4]; + + v[0] = get_bits(gb, 8); + v[1] = get_bits(gb, 6); + v[2] = get_bits(gb, 5); + v[3] = get_bits(gb, 5); + + dequant_lsps(lsps, 10, v, vec_sizes, 4, wmavoice_dq_lsp10i, + mul_lsf, base_lsf); +} + +/** + * Parse 10 independently-coded LSPs, and then derive the tables to + * generate LSPs for the other frames from them (residual coding). + */ +static void dequant_lsp10r(GetBitContext *gb, + double *i_lsps, const double *old, + double *a1, double *a2, int q_mode) +{ + static const uint16_t vec_sizes[3] = { 128, 64, 64 }; + static const double mul_lsf[3] = { + 2.5807601174e-3, 1.2354460219e-3, 1.1763821673e-3 + }; + static const double base_lsf[3] = { + M_PI * -1.07448e-1, M_PI * -5.2706e-2, M_PI * -5.1634e-2 + }; + const float (*ipol_tab)[2][10] = q_mode ? + wmavoice_lsp10_intercoeff_b : wmavoice_lsp10_intercoeff_a; + uint16_t interpol, v[3]; + int n; + + dequant_lsp10i(gb, i_lsps); + + interpol = get_bits(gb, 5); + v[0] = get_bits(gb, 7); + v[1] = get_bits(gb, 6); + v[2] = get_bits(gb, 6); + + for (n = 0; n < 10; n++) { + double delta = old[n] - i_lsps[n]; + a1[n] = ipol_tab[interpol][0][n] * delta + i_lsps[n]; + a1[10 + n] = ipol_tab[interpol][1][n] * delta + i_lsps[n]; + } + + dequant_lsps(a2, 20, v, vec_sizes, 3, wmavoice_dq_lsp10r, + mul_lsf, base_lsf); +} + +/** + * Parse 16 independently-coded LSPs. + */ +static void dequant_lsp16i(GetBitContext *gb, double *lsps) +{ + static const uint16_t vec_sizes[5] = { 256, 64, 128, 64, 128 }; + static const double mul_lsf[5] = { + 3.3439586280e-3, 6.9908173703e-4, + 3.3216608306e-3, 1.0334960326e-3, + 3.1899104283e-3 + }; + static const double base_lsf[5] = { + M_PI * -1.27576e-1, M_PI * -2.4292e-2, + M_PI * -1.28094e-1, M_PI * -3.2128e-2, + M_PI * -1.29816e-1 + }; + uint16_t v[5]; + + v[0] = get_bits(gb, 8); + v[1] = get_bits(gb, 6); + v[2] = get_bits(gb, 7); + v[3] = get_bits(gb, 6); + v[4] = get_bits(gb, 7); + + dequant_lsps( lsps, 5, v, vec_sizes, 2, + wmavoice_dq_lsp16i1, mul_lsf, base_lsf); + dequant_lsps(&lsps[5], 5, &v[2], &vec_sizes[2], 2, + wmavoice_dq_lsp16i2, &mul_lsf[2], &base_lsf[2]); + dequant_lsps(&lsps[10], 6, &v[4], &vec_sizes[4], 1, + wmavoice_dq_lsp16i3, &mul_lsf[4], &base_lsf[4]); +} + +/** + * Parse 16 independently-coded LSPs, and then derive the tables to + * generate LSPs for the other frames from them (residual coding). + */ +static void dequant_lsp16r(GetBitContext *gb, + double *i_lsps, const double *old, + double *a1, double *a2, int q_mode) +{ + static const uint16_t vec_sizes[3] = { 128, 128, 128 }; + static const double mul_lsf[3] = { + 1.2232979501e-3, 1.4062241527e-3, 1.6114744851e-3 + }; + static const double base_lsf[3] = { + M_PI * -5.5830e-2, M_PI * -5.2908e-2, M_PI * -5.4776e-2 + }; + const float (*ipol_tab)[2][16] = q_mode ? + wmavoice_lsp16_intercoeff_b : wmavoice_lsp16_intercoeff_a; + uint16_t interpol, v[3]; + int n; + + dequant_lsp16i(gb, i_lsps); + + interpol = get_bits(gb, 5); + v[0] = get_bits(gb, 7); + v[1] = get_bits(gb, 7); + v[2] = get_bits(gb, 7); + + for (n = 0; n < 16; n++) { + double delta = old[n] - i_lsps[n]; + a1[n] = ipol_tab[interpol][0][n] * delta + i_lsps[n]; + a1[16 + n] = ipol_tab[interpol][1][n] * delta + i_lsps[n]; + } + + dequant_lsps( a2, 10, v, vec_sizes, 1, + wmavoice_dq_lsp16r1, mul_lsf, base_lsf); + dequant_lsps(&a2[10], 10, &v[1], &vec_sizes[1], 1, + wmavoice_dq_lsp16r2, &mul_lsf[1], &base_lsf[1]); + dequant_lsps(&a2[20], 12, &v[2], &vec_sizes[2], 1, + wmavoice_dq_lsp16r3, &mul_lsf[2], &base_lsf[2]); +} + +/** + * @} + * @name Pitch-adaptive window coding functions + * The next few functions are for pitch-adaptive window coding. + * @{ + */ +/** + * Parse the offset of the first pitch-adaptive window pulses, and + * the distribution of pulses between the two blocks in this frame. + * @param s WMA Voice decoding context private data + * @param gb bit I/O context + * @param pitch pitch for each block in this frame + */ +static void aw_parse_coords(WMAVoiceContext *s, GetBitContext *gb, + const int *pitch) +{ + static const int16_t start_offset[94] = { + -11, -9, -7, -5, -3, -1, 1, 3, 5, 7, 9, 11, + 13, 15, 18, 17, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 35, 37, 39, 41, 43, + 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, + 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, + 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, + 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, + 141, 143, 145, 147, 149, 151, 153, 155, 157, 159 + }; + int bits, offset; + + /* position of pulse */ + s->aw_idx_is_ext = 0; + if ((bits = get_bits(gb, 6)) >= 54) { + s->aw_idx_is_ext = 1; + bits += (bits - 54) * 3 + get_bits(gb, 2); + } + + /* for a repeated pulse at pulse_off with a pitch_lag of pitch[], count + * the distribution of the pulses in each block contained in this frame. */ + s->aw_pulse_range = FFMIN(pitch[0], pitch[1]) > 32 ? 24 : 16; + for (offset = start_offset[bits]; offset < 0; offset += pitch[0]) ; + s->aw_n_pulses[0] = (pitch[0] - 1 + MAX_FRAMESIZE / 2 - offset) / pitch[0]; + s->aw_first_pulse_off[0] = offset - s->aw_pulse_range / 2; + offset += s->aw_n_pulses[0] * pitch[0]; + s->aw_n_pulses[1] = (pitch[1] - 1 + MAX_FRAMESIZE - offset) / pitch[1]; + s->aw_first_pulse_off[1] = offset - (MAX_FRAMESIZE + s->aw_pulse_range) / 2; + + /* if continuing from a position before the block, reset position to + * start of block (when corrected for the range over which it can be + * spread in aw_pulse_set1()). */ + if (start_offset[bits] < MAX_FRAMESIZE / 2) { + while (s->aw_first_pulse_off[1] - pitch[1] + s->aw_pulse_range > 0) + s->aw_first_pulse_off[1] -= pitch[1]; + if (start_offset[bits] < 0) + while (s->aw_first_pulse_off[0] - pitch[0] + s->aw_pulse_range > 0) + s->aw_first_pulse_off[0] -= pitch[0]; + } +} + +/** + * Apply second set of pitch-adaptive window pulses. + * @param s WMA Voice decoding context private data + * @param gb bit I/O context + * @param block_idx block index in frame [0, 1] + * @param fcb structure containing fixed codebook vector info + */ +static void aw_pulse_set2(WMAVoiceContext *s, GetBitContext *gb, + int block_idx, AMRFixed *fcb) +{ + uint16_t use_mask_mem[9]; // only 5 are used, rest is padding + uint16_t *use_mask = use_mask_mem + 2; + /* in this function, idx is the index in the 80-bit (+ padding) use_mask + * bit-array. Since use_mask consists of 16-bit values, the lower 4 bits + * of idx are the position of the bit within a particular item in the + * array (0 being the most significant bit, and 15 being the least + * significant bit), and the remainder (>> 4) is the index in the + * use_mask[]-array. This is faster and uses less memory than using a + * 80-byte/80-int array. */ + int pulse_off = s->aw_first_pulse_off[block_idx], + pulse_start, n, idx, range, aidx, start_off = 0; + + /* set offset of first pulse to within this block */ + if (s->aw_n_pulses[block_idx] > 0) + while (pulse_off + s->aw_pulse_range < 1) + pulse_off += fcb->pitch_lag; + + /* find range per pulse */ + if (s->aw_n_pulses[0] > 0) { + if (block_idx == 0) { + range = 32; + } else /* block_idx = 1 */ { + range = 8; + if (s->aw_n_pulses[block_idx] > 0) + pulse_off = s->aw_next_pulse_off_cache; + } + } else + range = 16; + pulse_start = s->aw_n_pulses[block_idx] > 0 ? pulse_off - range / 2 : 0; + + /* aw_pulse_set1() already applies pulses around pulse_off (to be exactly, + * in the range of [pulse_off, pulse_off + s->aw_pulse_range], and thus + * we exclude that range from being pulsed again in this function. */ + memset(&use_mask[-2], 0, 2 * sizeof(use_mask[0])); + memset( use_mask, -1, 5 * sizeof(use_mask[0])); + memset(&use_mask[5], 0, 2 * sizeof(use_mask[0])); + if (s->aw_n_pulses[block_idx] > 0) + for (idx = pulse_off; idx < MAX_FRAMESIZE / 2; idx += fcb->pitch_lag) { + int excl_range = s->aw_pulse_range; // always 16 or 24 + uint16_t *use_mask_ptr = &use_mask[idx >> 4]; + int first_sh = 16 - (idx & 15); + *use_mask_ptr++ &= 0xFFFFu << first_sh; + excl_range -= first_sh; + if (excl_range >= 16) { + *use_mask_ptr++ = 0; + *use_mask_ptr &= 0xFFFF >> (excl_range - 16); + } else + *use_mask_ptr &= 0xFFFF >> excl_range; + } + + /* find the 'aidx'th offset that is not excluded */ + aidx = get_bits(gb, s->aw_n_pulses[0] > 0 ? 5 - 2 * block_idx : 4); + for (n = 0; n <= aidx; pulse_start++) { + for (idx = pulse_start; idx < 0; idx += fcb->pitch_lag) ; + if (idx >= MAX_FRAMESIZE / 2) { // find from zero + if (use_mask[0]) idx = 0x0F; + else if (use_mask[1]) idx = 0x1F; + else if (use_mask[2]) idx = 0x2F; + else if (use_mask[3]) idx = 0x3F; + else if (use_mask[4]) idx = 0x4F; + else return; + idx -= av_log2_16bit(use_mask[idx >> 4]); + } + if (use_mask[idx >> 4] & (0x8000 >> (idx & 15))) { + use_mask[idx >> 4] &= ~(0x8000 >> (idx & 15)); + n++; + start_off = idx; + } + } + + fcb->x[fcb->n] = start_off; + fcb->y[fcb->n] = get_bits1(gb) ? -1.0 : 1.0; + fcb->n++; + + /* set offset for next block, relative to start of that block */ + n = (MAX_FRAMESIZE / 2 - start_off) % fcb->pitch_lag; + s->aw_next_pulse_off_cache = n ? fcb->pitch_lag - n : 0; +} + +/** + * Apply first set of pitch-adaptive window pulses. + * @param s WMA Voice decoding context private data + * @param gb bit I/O context + * @param block_idx block index in frame [0, 1] + * @param fcb storage location for fixed codebook pulse info + */ +static void aw_pulse_set1(WMAVoiceContext *s, GetBitContext *gb, + int block_idx, AMRFixed *fcb) +{ + int val = get_bits(gb, 12 - 2 * (s->aw_idx_is_ext && !block_idx)); + float v; + + if (s->aw_n_pulses[block_idx] > 0) { + int n, v_mask, i_mask, sh, n_pulses; + + if (s->aw_pulse_range == 24) { // 3 pulses, 1:sign + 3:index each + n_pulses = 3; + v_mask = 8; + i_mask = 7; + sh = 4; + } else { // 4 pulses, 1:sign + 2:index each + n_pulses = 4; + v_mask = 4; + i_mask = 3; + sh = 3; + } + + for (n = n_pulses - 1; n >= 0; n--, val >>= sh) { + fcb->y[fcb->n] = (val & v_mask) ? -1.0 : 1.0; + fcb->x[fcb->n] = (val & i_mask) * n_pulses + n + + s->aw_first_pulse_off[block_idx]; + while (fcb->x[fcb->n] < 0) + fcb->x[fcb->n] += fcb->pitch_lag; + if (fcb->x[fcb->n] < MAX_FRAMESIZE / 2) + fcb->n++; + } + } else { + int num2 = (val & 0x1FF) >> 1, delta, idx; + + if (num2 < 1 * 79) { delta = 1; idx = num2 + 1; } + else if (num2 < 2 * 78) { delta = 3; idx = num2 + 1 - 1 * 77; } + else if (num2 < 3 * 77) { delta = 5; idx = num2 + 1 - 2 * 76; } + else { delta = 7; idx = num2 + 1 - 3 * 75; } + v = (val & 0x200) ? -1.0 : 1.0; + + fcb->no_repeat_mask |= 3 << fcb->n; + fcb->x[fcb->n] = idx - delta; + fcb->y[fcb->n] = v; + fcb->x[fcb->n + 1] = idx; + fcb->y[fcb->n + 1] = (val & 1) ? -v : v; + fcb->n += 2; + } +} + +/** + * @} + * + * Generate a random number from frame_cntr and block_idx, which will lief + * in the range [0, 1000 - block_size] (so it can be used as an index in a + * table of size 1000 of which you want to read block_size entries). + * + * @param frame_cntr current frame number + * @param block_num current block index + * @param block_size amount of entries we want to read from a table + * that has 1000 entries + * @return a (non-)random number in the [0, 1000 - block_size] range. + */ +static int pRNG(int frame_cntr, int block_num, int block_size) +{ + /* array to simplify the calculation of z: + * y = (x % 9) * 5 + 6; + * z = (49995 * x) / y; + * Since y only has 9 values, we can remove the division by using a + * LUT and using FASTDIV-style divisions. For each of the 9 values + * of y, we can rewrite z as: + * z = x * (49995 / y) + x * ((49995 % y) / y) + * In this table, each col represents one possible value of y, the + * first number is 49995 / y, and the second is the FASTDIV variant + * of 49995 % y / y. */ + static const unsigned int div_tbl[9][2] = { + { 8332, 3 * 715827883U }, // y = 6 + { 4545, 0 * 390451573U }, // y = 11 + { 3124, 11 * 268435456U }, // y = 16 + { 2380, 15 * 204522253U }, // y = 21 + { 1922, 23 * 165191050U }, // y = 26 + { 1612, 23 * 138547333U }, // y = 31 + { 1388, 27 * 119304648U }, // y = 36 + { 1219, 16 * 104755300U }, // y = 41 + { 1086, 39 * 93368855U } // y = 46 + }; + unsigned int z, y, x = MUL16(block_num, 1877) + frame_cntr; + if (x >= 0xFFFF) x -= 0xFFFF; // max value of x is 8*1877+0xFFFE=0x13AA6, + // so this is effectively a modulo (%) + y = x - 9 * MULH(477218589, x); // x % 9 + z = (uint16_t) (x * div_tbl[y][0] + UMULH(x, div_tbl[y][1])); + // z = x * 49995 / (y * 5 + 6) + return z % (1000 - block_size); +} + +/** + * Parse hardcoded signal for a single block. + * @note see #synth_block(). + */ +static void synth_block_hardcoded(WMAVoiceContext *s, GetBitContext *gb, + int block_idx, int size, + const struct frame_type_desc *frame_desc, + float *excitation) +{ + float gain; + int n, r_idx; + + av_assert0(size <= MAX_FRAMESIZE); + + /* Set the offset from which we start reading wmavoice_std_codebook */ + if (frame_desc->fcb_type == FCB_TYPE_SILENCE) { + r_idx = pRNG(s->frame_cntr, block_idx, size); + gain = s->silence_gain; + } else /* FCB_TYPE_HARDCODED */ { + r_idx = get_bits(gb, 8); + gain = wmavoice_gain_universal[get_bits(gb, 6)]; + } + + /* Clear gain prediction parameters */ + memset(s->gain_pred_err, 0, sizeof(s->gain_pred_err)); + + /* Apply gain to hardcoded codebook and use that as excitation signal */ + for (n = 0; n < size; n++) + excitation[n] = wmavoice_std_codebook[r_idx + n] * gain; +} + +/** + * Parse FCB/ACB signal for a single block. + * @note see #synth_block(). + */ +static void synth_block_fcb_acb(WMAVoiceContext *s, GetBitContext *gb, + int block_idx, int size, + int block_pitch_sh2, + const struct frame_type_desc *frame_desc, + float *excitation) +{ + static const float gain_coeff[6] = { + 0.8169, -0.06545, 0.1726, 0.0185, -0.0359, 0.0458 + }; + float pulses[MAX_FRAMESIZE / 2], pred_err, acb_gain, fcb_gain; + int n, idx, gain_weight; + AMRFixed fcb; + + av_assert0(size <= MAX_FRAMESIZE / 2); + memset(pulses, 0, sizeof(*pulses) * size); + + fcb.pitch_lag = block_pitch_sh2 >> 2; + fcb.pitch_fac = 1.0; + fcb.no_repeat_mask = 0; + fcb.n = 0; + + /* For the other frame types, this is where we apply the innovation + * (fixed) codebook pulses of the speech signal. */ + if (frame_desc->fcb_type == FCB_TYPE_AW_PULSES) { + aw_pulse_set1(s, gb, block_idx, &fcb); + aw_pulse_set2(s, gb, block_idx, &fcb); + } else /* FCB_TYPE_EXC_PULSES */ { + int offset_nbits = 5 - frame_desc->log_n_blocks; + + fcb.no_repeat_mask = -1; + /* similar to ff_decode_10_pulses_35bits(), but with single pulses + * (instead of double) for a subset of pulses */ + for (n = 0; n < 5; n++) { + float sign; + int pos1, pos2; + + sign = get_bits1(gb) ? 1.0 : -1.0; + pos1 = get_bits(gb, offset_nbits); + fcb.x[fcb.n] = n + 5 * pos1; + fcb.y[fcb.n++] = sign; + if (n < frame_desc->dbl_pulses) { + pos2 = get_bits(gb, offset_nbits); + fcb.x[fcb.n] = n + 5 * pos2; + fcb.y[fcb.n++] = (pos1 < pos2) ? -sign : sign; + } + } + } + ff_set_fixed_vector(pulses, &fcb, 1.0, size); + + /* Calculate gain for adaptive & fixed codebook signal. + * see ff_amr_set_fixed_gain(). */ + idx = get_bits(gb, 7); + fcb_gain = expf(avpriv_scalarproduct_float_c(s->gain_pred_err, + gain_coeff, 6) - + 5.2409161640 + wmavoice_gain_codebook_fcb[idx]); + acb_gain = wmavoice_gain_codebook_acb[idx]; + pred_err = av_clipf(wmavoice_gain_codebook_fcb[idx], + -2.9957322736 /* log(0.05) */, + 1.6094379124 /* log(5.0) */); + + gain_weight = 8 >> frame_desc->log_n_blocks; + memmove(&s->gain_pred_err[gain_weight], s->gain_pred_err, + sizeof(*s->gain_pred_err) * (6 - gain_weight)); + for (n = 0; n < gain_weight; n++) + s->gain_pred_err[n] = pred_err; + + /* Calculation of adaptive codebook */ + if (frame_desc->acb_type == ACB_TYPE_ASYMMETRIC) { + int len; + for (n = 0; n < size; n += len) { + int next_idx_sh16; + int abs_idx = block_idx * size + n; + int pitch_sh16 = (s->last_pitch_val << 16) + + s->pitch_diff_sh16 * abs_idx; + int pitch = (pitch_sh16 + 0x6FFF) >> 16; + int idx_sh16 = ((pitch << 16) - pitch_sh16) * 8 + 0x58000; + idx = idx_sh16 >> 16; + if (s->pitch_diff_sh16) { + if (s->pitch_diff_sh16 > 0) { + next_idx_sh16 = (idx_sh16) &~ 0xFFFF; + } else + next_idx_sh16 = (idx_sh16 + 0x10000) &~ 0xFFFF; + len = av_clip((idx_sh16 - next_idx_sh16) / s->pitch_diff_sh16 / 8, + 1, size - n); + } else + len = size; + + ff_acelp_interpolatef(&excitation[n], &excitation[n - pitch], + wmavoice_ipol1_coeffs, 17, + idx, 9, len); + } + } else /* ACB_TYPE_HAMMING */ { + int block_pitch = block_pitch_sh2 >> 2; + idx = block_pitch_sh2 & 3; + if (idx) { + ff_acelp_interpolatef(excitation, &excitation[-block_pitch], + wmavoice_ipol2_coeffs, 4, + idx, 8, size); + } else + av_memcpy_backptr((uint8_t *) excitation, sizeof(float) * block_pitch, + sizeof(float) * size); + } + + /* Interpolate ACB/FCB and use as excitation signal */ + ff_weighted_vector_sumf(excitation, excitation, pulses, + acb_gain, fcb_gain, size); +} + +/** + * Parse data in a single block. + * @note we assume enough bits are available, caller should check. + * + * @param s WMA Voice decoding context private data + * @param gb bit I/O context + * @param block_idx index of the to-be-read block + * @param size amount of samples to be read in this block + * @param block_pitch_sh2 pitch for this block << 2 + * @param lsps LSPs for (the end of) this frame + * @param prev_lsps LSPs for the last frame + * @param frame_desc frame type descriptor + * @param excitation target memory for the ACB+FCB interpolated signal + * @param synth target memory for the speech synthesis filter output + * @return 0 on success, <0 on error. + */ +static void synth_block(WMAVoiceContext *s, GetBitContext *gb, + int block_idx, int size, + int block_pitch_sh2, + const double *lsps, const double *prev_lsps, + const struct frame_type_desc *frame_desc, + float *excitation, float *synth) +{ + double i_lsps[MAX_LSPS]; + float lpcs[MAX_LSPS]; + float fac; + int n; + + if (frame_desc->acb_type == ACB_TYPE_NONE) + synth_block_hardcoded(s, gb, block_idx, size, frame_desc, excitation); + else + synth_block_fcb_acb(s, gb, block_idx, size, block_pitch_sh2, + frame_desc, excitation); + + /* convert interpolated LSPs to LPCs */ + fac = (block_idx + 0.5) / frame_desc->n_blocks; + for (n = 0; n < s->lsps; n++) // LSF -> LSP + i_lsps[n] = cos(prev_lsps[n] + fac * (lsps[n] - prev_lsps[n])); + ff_acelp_lspd2lpc(i_lsps, lpcs, s->lsps >> 1); + + /* Speech synthesis */ + ff_celp_lp_synthesis_filterf(synth, lpcs, excitation, size, s->lsps); +} + +/** + * Synthesize output samples for a single frame. + * @note we assume enough bits are available, caller should check. + * + * @param ctx WMA Voice decoder context + * @param gb bit I/O context (s->gb or one for cross-packet superframes) + * @param frame_idx Frame number within superframe [0-2] + * @param samples pointer to output sample buffer, has space for at least 160 + * samples + * @param lsps LSP array + * @param prev_lsps array of previous frame's LSPs + * @param excitation target buffer for excitation signal + * @param synth target buffer for synthesized speech data + * @return 0 on success, <0 on error. + */ +static int synth_frame(AVCodecContext *ctx, GetBitContext *gb, int frame_idx, + float *samples, + const double *lsps, const double *prev_lsps, + float *excitation, float *synth) +{ + WMAVoiceContext *s = ctx->priv_data; + int n, n_blocks_x2, log_n_blocks_x2, av_uninit(cur_pitch_val); + int pitch[MAX_BLOCKS], av_uninit(last_block_pitch); + + /* Parse frame type ("frame header"), see frame_descs */ + int bd_idx = s->vbm_tree[get_vlc2(gb, frame_type_vlc.table, 6, 3)], block_nsamples; + + if (bd_idx < 0) { + av_log(ctx, AV_LOG_ERROR, + "Invalid frame type VLC code, skipping\n"); + return -1; + } + + block_nsamples = MAX_FRAMESIZE / frame_descs[bd_idx].n_blocks; + + /* Pitch calculation for ACB_TYPE_ASYMMETRIC ("pitch-per-frame") */ + if (frame_descs[bd_idx].acb_type == ACB_TYPE_ASYMMETRIC) { + /* Pitch is provided per frame, which is interpreted as the pitch of + * the last sample of the last block of this frame. We can interpolate + * the pitch of other blocks (and even pitch-per-sample) by gradually + * incrementing/decrementing prev_frame_pitch to cur_pitch_val. */ + n_blocks_x2 = frame_descs[bd_idx].n_blocks << 1; + log_n_blocks_x2 = frame_descs[bd_idx].log_n_blocks + 1; + cur_pitch_val = s->min_pitch_val + get_bits(gb, s->pitch_nbits); + cur_pitch_val = FFMIN(cur_pitch_val, s->max_pitch_val - 1); + if (s->last_acb_type == ACB_TYPE_NONE || + 20 * abs(cur_pitch_val - s->last_pitch_val) > + (cur_pitch_val + s->last_pitch_val)) + s->last_pitch_val = cur_pitch_val; + + /* pitch per block */ + for (n = 0; n < frame_descs[bd_idx].n_blocks; n++) { + int fac = n * 2 + 1; + + pitch[n] = (MUL16(fac, cur_pitch_val) + + MUL16((n_blocks_x2 - fac), s->last_pitch_val) + + frame_descs[bd_idx].n_blocks) >> log_n_blocks_x2; + } + + /* "pitch-diff-per-sample" for calculation of pitch per sample */ + s->pitch_diff_sh16 = + ((cur_pitch_val - s->last_pitch_val) << 16) / MAX_FRAMESIZE; + } + + /* Global gain (if silence) and pitch-adaptive window coordinates */ + switch (frame_descs[bd_idx].fcb_type) { + case FCB_TYPE_SILENCE: + s->silence_gain = wmavoice_gain_silence[get_bits(gb, 8)]; + break; + case FCB_TYPE_AW_PULSES: + aw_parse_coords(s, gb, pitch); + break; + } + + for (n = 0; n < frame_descs[bd_idx].n_blocks; n++) { + int bl_pitch_sh2; + + /* Pitch calculation for ACB_TYPE_HAMMING ("pitch-per-block") */ + switch (frame_descs[bd_idx].acb_type) { + case ACB_TYPE_HAMMING: { + /* Pitch is given per block. Per-block pitches are encoded as an + * absolute value for the first block, and then delta values + * relative to this value) for all subsequent blocks. The scale of + * this pitch value is semi-logaritmic compared to its use in the + * decoder, so we convert it to normal scale also. */ + int block_pitch, + t1 = (s->block_conv_table[1] - s->block_conv_table[0]) << 2, + t2 = (s->block_conv_table[2] - s->block_conv_table[1]) << 1, + t3 = s->block_conv_table[3] - s->block_conv_table[2] + 1; + + if (n == 0) { + block_pitch = get_bits(gb, s->block_pitch_nbits); + } else + block_pitch = last_block_pitch - s->block_delta_pitch_hrange + + get_bits(gb, s->block_delta_pitch_nbits); + /* Convert last_ so that any next delta is within _range */ + last_block_pitch = av_clip(block_pitch, + s->block_delta_pitch_hrange, + s->block_pitch_range - + s->block_delta_pitch_hrange); + + /* Convert semi-log-style scale back to normal scale */ + if (block_pitch < t1) { + bl_pitch_sh2 = (s->block_conv_table[0] << 2) + block_pitch; + } else { + block_pitch -= t1; + if (block_pitch < t2) { + bl_pitch_sh2 = + (s->block_conv_table[1] << 2) + (block_pitch << 1); + } else { + block_pitch -= t2; + if (block_pitch < t3) { + bl_pitch_sh2 = + (s->block_conv_table[2] + block_pitch) << 2; + } else + bl_pitch_sh2 = s->block_conv_table[3] << 2; + } + } + pitch[n] = bl_pitch_sh2 >> 2; + break; + } + + case ACB_TYPE_ASYMMETRIC: { + bl_pitch_sh2 = pitch[n] << 2; + break; + } + + default: // ACB_TYPE_NONE has no pitch + bl_pitch_sh2 = 0; + break; + } + + synth_block(s, gb, n, block_nsamples, bl_pitch_sh2, + lsps, prev_lsps, &frame_descs[bd_idx], + &excitation[n * block_nsamples], + &synth[n * block_nsamples]); + } + + /* Averaging projection filter, if applicable. Else, just copy samples + * from synthesis buffer */ + if (s->do_apf) { + double i_lsps[MAX_LSPS]; + float lpcs[MAX_LSPS]; + + for (n = 0; n < s->lsps; n++) // LSF -> LSP + i_lsps[n] = cos(0.5 * (prev_lsps[n] + lsps[n])); + ff_acelp_lspd2lpc(i_lsps, lpcs, s->lsps >> 1); + postfilter(s, synth, samples, 80, lpcs, + &s->zero_exc_pf[s->history_nsamples + MAX_FRAMESIZE * frame_idx], + frame_descs[bd_idx].fcb_type, pitch[0]); + + for (n = 0; n < s->lsps; n++) // LSF -> LSP + i_lsps[n] = cos(lsps[n]); + ff_acelp_lspd2lpc(i_lsps, lpcs, s->lsps >> 1); + postfilter(s, &synth[80], &samples[80], 80, lpcs, + &s->zero_exc_pf[s->history_nsamples + MAX_FRAMESIZE * frame_idx + 80], + frame_descs[bd_idx].fcb_type, pitch[0]); + } else + memcpy(samples, synth, 160 * sizeof(synth[0])); + + /* Cache values for next frame */ + s->frame_cntr++; + if (s->frame_cntr >= 0xFFFF) s->frame_cntr -= 0xFFFF; // i.e. modulo (%) + s->last_acb_type = frame_descs[bd_idx].acb_type; + switch (frame_descs[bd_idx].acb_type) { + case ACB_TYPE_NONE: + s->last_pitch_val = 0; + break; + case ACB_TYPE_ASYMMETRIC: + s->last_pitch_val = cur_pitch_val; + break; + case ACB_TYPE_HAMMING: + s->last_pitch_val = pitch[frame_descs[bd_idx].n_blocks - 1]; + break; + } + + return 0; +} + +/** + * Ensure minimum value for first item, maximum value for last value, + * proper spacing between each value and proper ordering. + * + * @param lsps array of LSPs + * @param num size of LSP array + * + * @note basically a double version of #ff_acelp_reorder_lsf(), might be + * useful to put in a generic location later on. Parts are also + * present in #ff_set_min_dist_lsf() + #ff_sort_nearly_sorted_floats(), + * which is in float. + */ +static void stabilize_lsps(double *lsps, int num) +{ + int n, m, l; + + /* set minimum value for first, maximum value for last and minimum + * spacing between LSF values. + * Very similar to ff_set_min_dist_lsf(), but in double. */ + lsps[0] = FFMAX(lsps[0], 0.0015 * M_PI); + for (n = 1; n < num; n++) + lsps[n] = FFMAX(lsps[n], lsps[n - 1] + 0.0125 * M_PI); + lsps[num - 1] = FFMIN(lsps[num - 1], 0.9985 * M_PI); + + /* reorder (looks like one-time / non-recursed bubblesort). + * Very similar to ff_sort_nearly_sorted_floats(), but in double. */ + for (n = 1; n < num; n++) { + if (lsps[n] < lsps[n - 1]) { + for (m = 1; m < num; m++) { + double tmp = lsps[m]; + for (l = m - 1; l >= 0; l--) { + if (lsps[l] <= tmp) break; + lsps[l + 1] = lsps[l]; + } + lsps[l + 1] = tmp; + } + break; + } + } +} + +/** + * Test if there's enough bits to read 1 superframe. + * + * @param orig_gb bit I/O context used for reading. This function + * does not modify the state of the bitreader; it + * only uses it to copy the current stream position + * @param s WMA Voice decoding context private data + * @return -1 if unsupported, 1 on not enough bits or 0 if OK. + */ +static int check_bits_for_superframe(GetBitContext *orig_gb, + WMAVoiceContext *s) +{ + GetBitContext s_gb, *gb = &s_gb; + int n, need_bits, bd_idx; + const struct frame_type_desc *frame_desc; + + /* initialize a copy */ + init_get_bits(gb, orig_gb->buffer, orig_gb->size_in_bits); + skip_bits_long(gb, get_bits_count(orig_gb)); + av_assert1(get_bits_left(gb) == get_bits_left(orig_gb)); + + /* superframe header */ + if (get_bits_left(gb) < 14) + return 1; + if (!get_bits1(gb)) + return -1; // WMAPro-in-WMAVoice superframe + if (get_bits1(gb)) skip_bits(gb, 12); // number of samples in superframe + if (s->has_residual_lsps) { // residual LSPs (for all frames) + if (get_bits_left(gb) < s->sframe_lsp_bitsize) + return 1; + skip_bits_long(gb, s->sframe_lsp_bitsize); + } + + /* frames */ + for (n = 0; n < MAX_FRAMES; n++) { + int aw_idx_is_ext = 0; + + if (!s->has_residual_lsps) { // independent LSPs (per-frame) + if (get_bits_left(gb) < s->frame_lsp_bitsize) return 1; + skip_bits_long(gb, s->frame_lsp_bitsize); + } + bd_idx = s->vbm_tree[get_vlc2(gb, frame_type_vlc.table, 6, 3)]; + if (bd_idx < 0) + return -1; // invalid frame type VLC code + frame_desc = &frame_descs[bd_idx]; + if (frame_desc->acb_type == ACB_TYPE_ASYMMETRIC) { + if (get_bits_left(gb) < s->pitch_nbits) + return 1; + skip_bits_long(gb, s->pitch_nbits); + } + if (frame_desc->fcb_type == FCB_TYPE_SILENCE) { + skip_bits(gb, 8); + } else if (frame_desc->fcb_type == FCB_TYPE_AW_PULSES) { + int tmp = get_bits(gb, 6); + if (tmp >= 0x36) { + skip_bits(gb, 2); + aw_idx_is_ext = 1; + } + } + + /* blocks */ + if (frame_desc->acb_type == ACB_TYPE_HAMMING) { + need_bits = s->block_pitch_nbits + + (frame_desc->n_blocks - 1) * s->block_delta_pitch_nbits; + } else if (frame_desc->fcb_type == FCB_TYPE_AW_PULSES) { + need_bits = 2 * !aw_idx_is_ext; + } else + need_bits = 0; + need_bits += frame_desc->frame_size; + if (get_bits_left(gb) < need_bits) + return 1; + skip_bits_long(gb, need_bits); + } + + return 0; +} + +/** + * Synthesize output samples for a single superframe. If we have any data + * cached in s->sframe_cache, that will be used instead of whatever is loaded + * in s->gb. + * + * WMA Voice superframes contain 3 frames, each containing 160 audio samples, + * to give a total of 480 samples per frame. See #synth_frame() for frame + * parsing. In addition to 3 frames, superframes can also contain the LSPs + * (if these are globally specified for all frames (residually); they can + * also be specified individually per-frame. See the s->has_residual_lsps + * option), and can specify the number of samples encoded in this superframe + * (if less than 480), usually used to prevent blanks at track boundaries. + * + * @param ctx WMA Voice decoder context + * @return 0 on success, <0 on error or 1 if there was not enough data to + * fully parse the superframe + */ +static int synth_superframe(AVCodecContext *ctx, AVFrame *frame, + int *got_frame_ptr) +{ + WMAVoiceContext *s = ctx->priv_data; + GetBitContext *gb = &s->gb, s_gb; + int n, res, n_samples = 480; + double lsps[MAX_FRAMES][MAX_LSPS]; + const double *mean_lsf = s->lsps == 16 ? + wmavoice_mean_lsf16[s->lsp_def_mode] : wmavoice_mean_lsf10[s->lsp_def_mode]; + float excitation[MAX_SIGNAL_HISTORY + MAX_SFRAMESIZE + 12]; + float synth[MAX_LSPS + MAX_SFRAMESIZE]; + float *samples; + + memcpy(synth, s->synth_history, + s->lsps * sizeof(*synth)); + memcpy(excitation, s->excitation_history, + s->history_nsamples * sizeof(*excitation)); + + if (s->sframe_cache_size > 0) { + gb = &s_gb; + init_get_bits(gb, s->sframe_cache, s->sframe_cache_size); + s->sframe_cache_size = 0; + } + + if ((res = check_bits_for_superframe(gb, s)) == 1) { + *got_frame_ptr = 0; + return 1; + } + + /* First bit is speech/music bit, it differentiates between WMAVoice + * speech samples (the actual codec) and WMAVoice music samples, which + * are really WMAPro-in-WMAVoice-superframes. I've never seen those in + * the wild yet. */ + if (!get_bits1(gb)) { + avpriv_request_sample(ctx, "WMAPro-in-WMAVoice"); + return AVERROR_PATCHWELCOME; + } + + /* (optional) nr. of samples in superframe; always <= 480 and >= 0 */ + if (get_bits1(gb)) { + if ((n_samples = get_bits(gb, 12)) > 480) { + av_log(ctx, AV_LOG_ERROR, + "Superframe encodes >480 samples (%d), not allowed\n", + n_samples); + return -1; + } + } + /* Parse LSPs, if global for the superframe (can also be per-frame). */ + if (s->has_residual_lsps) { + double prev_lsps[MAX_LSPS], a1[MAX_LSPS * 2], a2[MAX_LSPS * 2]; + + for (n = 0; n < s->lsps; n++) + prev_lsps[n] = s->prev_lsps[n] - mean_lsf[n]; + + if (s->lsps == 10) { + dequant_lsp10r(gb, lsps[2], prev_lsps, a1, a2, s->lsp_q_mode); + } else /* s->lsps == 16 */ + dequant_lsp16r(gb, lsps[2], prev_lsps, a1, a2, s->lsp_q_mode); + + for (n = 0; n < s->lsps; n++) { + lsps[0][n] = mean_lsf[n] + (a1[n] - a2[n * 2]); + lsps[1][n] = mean_lsf[n] + (a1[s->lsps + n] - a2[n * 2 + 1]); + lsps[2][n] += mean_lsf[n]; + } + for (n = 0; n < 3; n++) + stabilize_lsps(lsps[n], s->lsps); + } + + /* get output buffer */ + frame->nb_samples = 480; + if ((res = ff_get_buffer(ctx, frame, 0)) < 0) + return res; + frame->nb_samples = n_samples; + samples = (float *)frame->data[0]; + + /* Parse frames, optionally preceded by per-frame (independent) LSPs. */ + for (n = 0; n < 3; n++) { + if (!s->has_residual_lsps) { + int m; + + if (s->lsps == 10) { + dequant_lsp10i(gb, lsps[n]); + } else /* s->lsps == 16 */ + dequant_lsp16i(gb, lsps[n]); + + for (m = 0; m < s->lsps; m++) + lsps[n][m] += mean_lsf[m]; + stabilize_lsps(lsps[n], s->lsps); + } + + if ((res = synth_frame(ctx, gb, n, + &samples[n * MAX_FRAMESIZE], + lsps[n], n == 0 ? s->prev_lsps : lsps[n - 1], + &excitation[s->history_nsamples + n * MAX_FRAMESIZE], + &synth[s->lsps + n * MAX_FRAMESIZE]))) { + *got_frame_ptr = 0; + return res; + } + } + + /* Statistics? FIXME - we don't check for length, a slight overrun + * will be caught by internal buffer padding, and anything else + * will be skipped, not read. */ + if (get_bits1(gb)) { + res = get_bits(gb, 4); + skip_bits(gb, 10 * (res + 1)); + } + + *got_frame_ptr = 1; + + /* Update history */ + memcpy(s->prev_lsps, lsps[2], + s->lsps * sizeof(*s->prev_lsps)); + memcpy(s->synth_history, &synth[MAX_SFRAMESIZE], + s->lsps * sizeof(*synth)); + memcpy(s->excitation_history, &excitation[MAX_SFRAMESIZE], + s->history_nsamples * sizeof(*excitation)); + if (s->do_apf) + memmove(s->zero_exc_pf, &s->zero_exc_pf[MAX_SFRAMESIZE], + s->history_nsamples * sizeof(*s->zero_exc_pf)); + + return 0; +} + +/** + * Parse the packet header at the start of each packet (input data to this + * decoder). + * + * @param s WMA Voice decoding context private data + * @return 1 if not enough bits were available, or 0 on success. + */ +static int parse_packet_header(WMAVoiceContext *s) +{ + GetBitContext *gb = &s->gb; + unsigned int res; + + if (get_bits_left(gb) < 11) + return 1; + skip_bits(gb, 4); // packet sequence number + s->has_residual_lsps = get_bits1(gb); + do { + res = get_bits(gb, 6); // number of superframes per packet + // (minus first one if there is spillover) + if (get_bits_left(gb) < 6 * (res == 0x3F) + s->spillover_bitsize) + return 1; + } while (res == 0x3F); + s->spillover_nbits = get_bits(gb, s->spillover_bitsize); + + return 0; +} + +/** + * Copy (unaligned) bits from gb/data/size to pb. + * + * @param pb target buffer to copy bits into + * @param data source buffer to copy bits from + * @param size size of the source data, in bytes + * @param gb bit I/O context specifying the current position in the source. + * data. This function might use this to align the bit position to + * a whole-byte boundary before calling #avpriv_copy_bits() on aligned + * source data + * @param nbits the amount of bits to copy from source to target + * + * @note after calling this function, the current position in the input bit + * I/O context is undefined. + */ +static void copy_bits(PutBitContext *pb, + const uint8_t *data, int size, + GetBitContext *gb, int nbits) +{ + int rmn_bytes, rmn_bits; + + rmn_bits = rmn_bytes = get_bits_left(gb); + if (rmn_bits < nbits) + return; + if (nbits > pb->size_in_bits - put_bits_count(pb)) + return; + rmn_bits &= 7; rmn_bytes >>= 3; + if ((rmn_bits = FFMIN(rmn_bits, nbits)) > 0) + put_bits(pb, rmn_bits, get_bits(gb, rmn_bits)); + avpriv_copy_bits(pb, data + size - rmn_bytes, + FFMIN(nbits - rmn_bits, rmn_bytes << 3)); +} + +/** + * Packet decoding: a packet is anything that the (ASF) demuxer contains, + * and we expect that the demuxer / application provides it to us as such + * (else you'll probably get garbage as output). Every packet has a size of + * ctx->block_align bytes, starts with a packet header (see + * #parse_packet_header()), and then a series of superframes. Superframe + * boundaries may exceed packets, i.e. superframes can split data over + * multiple (two) packets. + * + * For more information about frames, see #synth_superframe(). + */ +static int wmavoice_decode_packet(AVCodecContext *ctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + WMAVoiceContext *s = ctx->priv_data; + GetBitContext *gb = &s->gb; + int size, res, pos; + + /* Packets are sometimes a multiple of ctx->block_align, with a packet + * header at each ctx->block_align bytes. However, FFmpeg's ASF demuxer + * feeds us ASF packets, which may concatenate multiple "codec" packets + * in a single "muxer" packet, so we artificially emulate that by + * capping the packet size at ctx->block_align. */ + for (size = avpkt->size; size > ctx->block_align; size -= ctx->block_align); + if (!size) { + *got_frame_ptr = 0; + return 0; + } + init_get_bits(&s->gb, avpkt->data, size << 3); + + /* size == ctx->block_align is used to indicate whether we are dealing with + * a new packet or a packet of which we already read the packet header + * previously. */ + if (size == ctx->block_align) { // new packet header + if ((res = parse_packet_header(s)) < 0) + return res; + + /* If the packet header specifies a s->spillover_nbits, then we want + * to push out all data of the previous packet (+ spillover) before + * continuing to parse new superframes in the current packet. */ + if (s->spillover_nbits > 0) { + if (s->sframe_cache_size > 0) { + int cnt = get_bits_count(gb); + copy_bits(&s->pb, avpkt->data, size, gb, s->spillover_nbits); + flush_put_bits(&s->pb); + s->sframe_cache_size += s->spillover_nbits; + if ((res = synth_superframe(ctx, data, got_frame_ptr)) == 0 && + *got_frame_ptr) { + cnt += s->spillover_nbits; + s->skip_bits_next = cnt & 7; + return cnt >> 3; + } else + skip_bits_long (gb, s->spillover_nbits - cnt + + get_bits_count(gb)); // resync + } else + skip_bits_long(gb, s->spillover_nbits); // resync + } + } else if (s->skip_bits_next) + skip_bits(gb, s->skip_bits_next); + + /* Try parsing superframes in current packet */ + s->sframe_cache_size = 0; + s->skip_bits_next = 0; + pos = get_bits_left(gb); + if ((res = synth_superframe(ctx, data, got_frame_ptr)) < 0) { + return res; + } else if (*got_frame_ptr) { + int cnt = get_bits_count(gb); + s->skip_bits_next = cnt & 7; + return cnt >> 3; + } else if ((s->sframe_cache_size = pos) > 0) { + /* rewind bit reader to start of last (incomplete) superframe... */ + init_get_bits(gb, avpkt->data, size << 3); + skip_bits_long(gb, (size << 3) - pos); + av_assert1(get_bits_left(gb) == pos); + + /* ...and cache it for spillover in next packet */ + init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE); + copy_bits(&s->pb, avpkt->data, size, gb, s->sframe_cache_size); + // FIXME bad - just copy bytes as whole and add use the + // skip_bits_next field + } + + return size; +} + +static av_cold int wmavoice_decode_end(AVCodecContext *ctx) +{ + WMAVoiceContext *s = ctx->priv_data; + + if (s->do_apf) { + ff_rdft_end(&s->rdft); + ff_rdft_end(&s->irdft); + ff_dct_end(&s->dct); + ff_dct_end(&s->dst); + } + + return 0; +} + +static av_cold void wmavoice_flush(AVCodecContext *ctx) +{ + WMAVoiceContext *s = ctx->priv_data; + int n; + + s->postfilter_agc = 0; + s->sframe_cache_size = 0; + s->skip_bits_next = 0; + for (n = 0; n < s->lsps; n++) + s->prev_lsps[n] = M_PI * (n + 1.0) / (s->lsps + 1.0); + memset(s->excitation_history, 0, + sizeof(*s->excitation_history) * MAX_SIGNAL_HISTORY); + memset(s->synth_history, 0, + sizeof(*s->synth_history) * MAX_LSPS); + memset(s->gain_pred_err, 0, + sizeof(s->gain_pred_err)); + + if (s->do_apf) { + memset(&s->synth_filter_out_buf[MAX_LSPS_ALIGN16 - s->lsps], 0, + sizeof(*s->synth_filter_out_buf) * s->lsps); + memset(s->dcf_mem, 0, + sizeof(*s->dcf_mem) * 2); + memset(s->zero_exc_pf, 0, + sizeof(*s->zero_exc_pf) * s->history_nsamples); + memset(s->denoise_filter_cache, 0, sizeof(s->denoise_filter_cache)); + } +} + +AVCodec ff_wmavoice_decoder = { + .name = "wmavoice", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WMAVOICE, + .priv_data_size = sizeof(WMAVoiceContext), + .init = wmavoice_decode_init, + .close = wmavoice_decode_end, + .decode = wmavoice_decode_packet, + .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1, + .flush = wmavoice_flush, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Voice"), +}; diff --git a/ffmpeg/libavcodec/wmavoice_data.h b/ffmpeg/libavcodec/wmavoice_data.h new file mode 100644 index 0000000..cbf65b0 --- /dev/null +++ b/ffmpeg/libavcodec/wmavoice_data.h @@ -0,0 +1,3259 @@ +/* + * Windows Media Voice (WMAVoice) tables. + * Copyright (c) 2009 Ronald S. Bultje + * + * 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 + */ + +/** + * @file + * @brief Windows Media Voice (WMAVoice) tables + * @author Ronald S. Bultje + */ + +#ifndef AVCODEC_WMAVOICE_DATA_H +#define AVCODEC_WMAVOICE_DATA_H + +#include + +static const uint8_t wmavoice_dq_lsp10i[0xf00] = { + 125, 109, 84, 55, 34, 51, 109, 112, 118, 132, + 122, 102, 78, 80, 132, 119, 132, 132, 125, 131, + 109, 91, 131, 131, 136, 136, 137, 137, 140, 145, + 140, 143, 117, 136, 122, 106, 109, 91, 115, 119, + 133, 117, 103, 80, 55, 117, 123, 102, 93, 80, + 139, 116, 70, 39, 95, 89, 103, 113, 112, 122, + 135, 244, 229, 215, 199, 181, 163, 150, 146, 144, + 143, 173, 171, 154, 155, 154, 151, 148, 145, 143, + 132, 138, 116, 85, 117, 94, 108, 117, 107, 116, + 132, 118, 123, 119, 88, 67, 49, 95, 84, 95, + 121, 103, 74, 70, 179, 164, 141, 126, 107, 112, + 119, 95, 103, 149, 139, 148, 144, 147, 148, 141, + 151, 133, 142, 129, 111, 131, 108, 128, 122, 108, + 121, 96, 115, 138, 116, 93, 105, 115, 115, 123, + 129, 106, 136, 180, 147, 130, 108, 141, 131, 118, + 136, 155, 176, 156, 135, 129, 140, 146, 142, 134, + 141, 130, 109, 80, 52, 38, 18, 47, 118, 134, + 155, 141, 100, 78, 72, 89, 79, 96, 92, 98, + 133, 111, 83, 91, 72, 58, 105, 115, 112, 120, + 145, 127, 135, 113, 113, 105, 105, 85, 69, 61, + 115, 96, 116, 145, 159, 170, 175, 175, 168, 155, + 140, 120, 84, 52, 80, 145, 125, 127, 116, 126, + 128, 108, 101, 198, 227, 200, 178, 159, 147, 148, + 121, 88, 46, 109, 124, 126, 126, 137, 147, 147, + 129, 107, 164, 148, 127, 117, 134, 120, 111, 116, + 120, 103, 98, 73, 66, 61, 70, 115, 116, 125, + 126, 100, 77, 188, 162, 140, 114, 128, 139, 123, + 145, 165, 164, 134, 109, 100, 108, 118, 127, 130, + 156, 182, 190, 173, 167, 165, 162, 157, 152, 147, + 150, 164, 179, 183, 173, 155, 140, 136, 134, 135, + 122, 92, 69, 140, 132, 118, 108, 128, 138, 132, + 123, 127, 148, 137, 150, 149, 139, 127, 124, 130, + 136, 138, 112, 70, 41, 37, 132, 140, 129, 125, + 130, 111, 78, 33, 51, 161, 141, 136, 120, 122, + 126, 110, 87, 106, 85, 68, 48, 81, 112, 113, + 135, 125, 98, 85, 102, 80, 100, 87, 86, 116, + 142, 133, 110, 66, 48, 152, 139, 135, 136, 123, + 128, 116, 89, 102, 128, 99, 83, 61, 105, 124, + 120, 94, 73, 83, 78, 100, 122, 124, 128, 132, + 144, 137, 116, 102, 75, 144, 136, 127, 140, 127, + 154, 144, 118, 99, 90, 90, 89, 75, 68, 83, + 123, 103, 89, 198, 180, 154, 138, 122, 136, 120, + 138, 118, 121, 136, 110, 105, 85, 111, 101, 104, + 121, 126, 139, 115, 99, 101, 107, 110, 123, 126, + 127, 115, 88, 109, 164, 134, 138, 138, 120, 121, + 130, 202, 195, 202, 199, 201, 181, 164, 159, 148, + 120, 116, 194, 199, 186, 171, 154, 142, 137, 133, + 137, 129, 112, 149, 134, 112, 149, 138, 120, 134, + 119, 102, 107, 83, 79, 114, 119, 127, 128, 128, + 144, 148, 165, 155, 161, 150, 135, 122, 116, 115, + 120, 99, 80, 120, 123, 124, 111, 89, 70, 108, + 118, 95, 66, 53, 105, 126, 125, 105, 83, 111, + 129, 197, 191, 197, 206, 213, 216, 208, 196, 169, + 133, 109, 127, 164, 134, 121, 99, 92, 82, 71, + 131, 121, 93, 91, 136, 105, 115, 140, 120, 110, + 150, 164, 139, 108, 87, 81, 93, 92, 104, 116, + 133, 114, 125, 126, 111, 136, 110, 156, 147, 133, + 113, 94, 118, 120, 115, 125, 124, 126, 127, 134, + 116, 131, 161, 158, 166, 157, 150, 150, 144, 141, + 125, 185, 169, 142, 140, 143, 139, 131, 134, 138, + 179, 188, 170, 150, 134, 140, 144, 133, 127, 127, + 150, 177, 204, 184, 192, 194, 190, 193, 177, 158, + 114, 113, 138, 116, 137, 135, 132, 131, 127, 134, + 120, 147, 163, 135, 133, 137, 136, 136, 133, 135, + 137, 120, 95, 73, 46, 48, 111, 97, 97, 123, + 139, 130, 109, 76, 52, 72, 61, 61, 125, 127, + 132, 119, 119, 90, 66, 41, 64, 156, 143, 129, + 131, 106, 58, 25, 99, 115, 122, 136, 129, 132, + 134, 123, 97, 53, 27, 114, 125, 114, 120, 123, + 122, 107, 93, 57, 47, 133, 128, 138, 141, 131, + 145, 132, 122, 110, 79, 57, 30, 73, 153, 144, + 150, 132, 85, 59, 133, 125, 130, 115, 100, 96, + 148, 127, 111, 86, 61, 38, 110, 121, 108, 99, + 157, 143, 105, 77, 116, 118, 115, 131, 122, 122, + 133, 119, 134, 108, 86, 61, 129, 165, 143, 127, + 125, 105, 89, 111, 97, 85, 113, 99, 98, 117, + 149, 131, 101, 106, 88, 95, 79, 119, 123, 120, + 125, 109, 81, 100, 201, 183, 156, 138, 115, 116, + 141, 119, 129, 105, 76, 60, 110, 99, 92, 82, + 150, 156, 129, 95, 69, 115, 115, 113, 134, 125, + 118, 97, 67, 96, 203, 197, 171, 151, 133, 125, + 143, 131, 120, 134, 105, 80, 51, 60, 139, 134, + 129, 160, 223, 219, 219, 212, 197, 173, 157, 146, + 132, 112, 164, 144, 119, 102, 92, 76, 73, 94, + 132, 112, 124, 114, 93, 92, 83, 73, 69, 99, + 129, 103, 188, 163, 142, 132, 127, 101, 82, 59, + 140, 141, 111, 74, 46, 105, 113, 99, 127, 122, + 125, 94, 63, 112, 116, 101, 81, 120, 136, 134, + 133, 190, 224, 193, 179, 158, 146, 143, 140, 136, + 152, 161, 132, 120, 112, 94, 114, 102, 92, 116, + 129, 194, 196, 202, 211, 212, 210, 190, 169, 152, + 166, 166, 145, 111, 91, 132, 133, 128, 136, 130, + 118, 94, 72, 74, 92, 86, 89, 92, 106, 123, + 126, 100, 86, 137, 117, 92, 76, 104, 106, 114, + 133, 109, 204, 192, 166, 148, 138, 128, 111, 81, + 118, 99, 79, 146, 169, 141, 123, 102, 131, 120, + 127, 105, 136, 204, 170, 154, 131, 145, 135, 119, + 117, 95, 64, 83, 141, 136, 118, 96, 99, 126, + 115, 93, 98, 102, 95, 105, 106, 114, 119, 128, + 131, 121, 98, 139, 149, 119, 109, 86, 105, 129, + 134, 119, 104, 169, 185, 155, 141, 122, 107, 127, + 136, 115, 85, 108, 87, 126, 102, 128, 136, 129, + 125, 99, 126, 158, 133, 139, 132, 113, 91, 107, + 141, 122, 128, 161, 130, 127, 105, 120, 118, 106, + 122, 140, 161, 168, 187, 184, 176, 158, 144, 140, + 127, 111, 89, 130, 132, 105, 134, 121, 100, 122, + 129, 110, 128, 115, 129, 116, 132, 118, 114, 119, + 138, 133, 132, 188, 183, 159, 161, 147, 134, 140, + 132, 113, 84, 167, 147, 132, 124, 109, 133, 121, + 132, 128, 116, 121, 98, 101, 145, 129, 128, 129, + 124, 112, 152, 158, 136, 161, 139, 165, 158, 142, + 139, 138, 110, 127, 148, 117, 126, 118, 101, 116, + 155, 168, 154, 128, 120, 152, 150, 141, 140, 135, + 127, 111, 109, 134, 104, 133, 110, 112, 132, 114, + 111, 87, 68, 89, 107, 121, 121, 126, 126, 129, + 120, 148, 169, 163, 173, 178, 185, 188, 178, 163, + 122, 97, 86, 117, 101, 138, 118, 142, 155, 139, + 125, 114, 131, 138, 153, 149, 163, 150, 143, 141, + 157, 161, 138, 152, 134, 121, 122, 109, 110, 124, + 151, 171, 196, 168, 145, 139, 147, 151, 146, 139, + 134, 169, 179, 170, 175, 178, 177, 173, 165, 154, + 120, 151, 118, 107, 125, 129, 133, 133, 136, 139, + 119, 141, 159, 151, 160, 165, 168, 169, 162, 152, + 115, 111, 119, 94, 117, 121, 127, 127, 132, 136, + 134, 153, 147, 142, 142, 147, 159, 159, 154, 147, + 110, 106, 139, 135, 143, 142, 147, 146, 147, 147, + 115, 133, 151, 133, 141, 142, 151, 152, 147, 144, + 115, 132, 144, 131, 125, 126, 128, 130, 131, 136, + 138, 118, 96, 71, 48, 26, 43, 130, 125, 125, + 134, 122, 98, 54, 28, 84, 77, 73, 109, 125, + 133, 112, 67, 48, 141, 129, 126, 113, 112, 118, + 143, 123, 89, 54, 71, 73, 75, 131, 123, 123, + 126, 109, 81, 31, 15, 94, 110, 109, 119, 128, + 132, 122, 97, 92, 73, 50, 27, 22, 104, 133, + 133, 119, 94, 48, 34, 168, 160, 154, 151, 130, + 147, 133, 90, 54, 71, 123, 106, 105, 93, 117, + 143, 132, 107, 69, 45, 78, 178, 169, 150, 139, + 138, 123, 116, 96, 69, 49, 32, 113, 103, 112, + 154, 151, 125, 79, 60, 152, 160, 154, 155, 137, + 142, 151, 124, 88, 66, 59, 94, 87, 95, 119, + 166, 154, 122, 92, 138, 132, 124, 114, 97, 97, + 122, 99, 98, 219, 191, 176, 165, 159, 153, 131, + 130, 119, 91, 51, 24, 41, 144, 156, 147, 139, + 139, 122, 81, 65, 124, 111, 104, 90, 94, 98, + 138, 120, 112, 91, 63, 65, 89, 75, 78, 106, + 126, 107, 91, 85, 69, 95, 90, 84, 108, 120, + 155, 139, 100, 78, 120, 110, 109, 91, 77, 73, + 144, 130, 135, 112, 88, 65, 62, 142, 129, 126, + 170, 154, 150, 131, 121, 116, 100, 92, 83, 86, + 131, 122, 98, 107, 102, 75, 54, 38, 117, 130, + 146, 139, 117, 107, 86, 66, 44, 30, 97, 128, + 129, 116, 100, 59, 108, 127, 119, 139, 129, 129, + 124, 106, 79, 49, 154, 190, 166, 152, 133, 123, + 141, 149, 123, 89, 61, 70, 143, 132, 125, 126, + 136, 113, 177, 166, 141, 123, 109, 108, 105, 93, + 137, 117, 147, 123, 99, 85, 109, 98, 91, 75, + 129, 121, 102, 78, 53, 90, 149, 136, 134, 135, + 144, 136, 126, 90, 114, 152, 137, 152, 138, 128, + 133, 115, 107, 129, 99, 78, 60, 129, 125, 118, + 147, 141, 119, 124, 110, 91, 79, 64, 106, 117, + 134, 111, 164, 143, 123, 113, 116, 95, 76, 56, + 147, 159, 140, 109, 83, 84, 140, 135, 127, 129, + 123, 104, 116, 99, 91, 87, 80, 110, 113, 121, + 124, 106, 174, 174, 152, 141, 132, 134, 126, 124, + 140, 190, 240, 215, 212, 189, 173, 158, 144, 137, + 123, 97, 79, 102, 110, 111, 90, 75, 126, 124, + 134, 121, 104, 145, 127, 100, 77, 65, 120, 118, + 123, 106, 87, 41, 68, 119, 106, 115, 109, 119, + 137, 232, 241, 225, 217, 202, 183, 169, 156, 145, + 161, 146, 127, 110, 97, 107, 88, 114, 108, 106, + 141, 244, 216, 192, 172, 163, 148, 143, 144, 144, + 128, 127, 109, 89, 77, 68, 124, 120, 121, 125, + 125, 94, 48, 71, 116, 113, 104, 120, 142, 137, + 133, 129, 115, 82, 68, 120, 99, 133, 134, 124, + 130, 106, 108, 160, 130, 111, 89, 129, 124, 119, + 134, 120, 149, 143, 116, 95, 87, 142, 132, 122, + 126, 114, 108, 107, 80, 141, 133, 123, 137, 124, + 117, 95, 69, 43, 62, 98, 114, 116, 112, 120, + 122, 99, 87, 164, 145, 123, 99, 95, 118, 105, + 126, 101, 102, 120, 113, 110, 92, 139, 134, 126, + 148, 194, 241, 219, 221, 215, 200, 193, 174, 151, + 127, 104, 122, 136, 113, 106, 110, 95, 78, 106, + 131, 163, 217, 199, 194, 175, 164, 155, 142, 138, + 139, 124, 88, 57, 161, 161, 145, 139, 124, 116, + 127, 110, 91, 98, 126, 104, 113, 98, 94, 94, + 145, 138, 114, 90, 75, 130, 117, 107, 99, 90, + 119, 98, 86, 101, 148, 133, 103, 83, 124, 131, + 143, 168, 169, 133, 110, 117, 139, 149, 147, 137, + 124, 106, 80, 138, 194, 163, 142, 119, 106, 130, + 136, 125, 105, 114, 87, 113, 101, 89, 108, 102, + 114, 90, 53, 46, 105, 116, 126, 122, 118, 122, + 124, 102, 92, 195, 167, 160, 144, 154, 154, 132, + 118, 97, 88, 72, 98, 120, 112, 98, 79, 117, + 114, 107, 185, 191, 191, 188, 175, 165, 153, 143, + 119, 97, 90, 89, 120, 151, 136, 113, 99, 112, + 141, 121, 144, 122, 125, 113, 133, 111, 92, 69, + 120, 98, 78, 109, 151, 145, 157, 157, 151, 143, + 130, 110, 120, 188, 159, 141, 119, 112, 109, 98, + 126, 112, 83, 110, 169, 139, 127, 105, 93, 123, + 141, 145, 117, 106, 91, 78, 123, 107, 101, 125, + 117, 95, 71, 147, 176, 153, 148, 133, 135, 127, + 124, 106, 79, 64, 115, 96, 108, 115, 106, 105, + 127, 115, 90, 98, 105, 81, 144, 135, 117, 125, + 126, 104, 98, 165, 138, 136, 112, 149, 148, 131, + 119, 144, 186, 185, 204, 202, 209, 200, 182, 161, + 123, 153, 190, 189, 199, 194, 191, 176, 157, 147, + 121, 103, 119, 98, 100, 120, 106, 97, 95, 126, + 137, 130, 102, 117, 117, 92, 126, 114, 101, 118, + 131, 219, 190, 167, 153, 151, 144, 140, 142, 143, + 114, 102, 151, 152, 132, 120, 112, 120, 127, 131, + 138, 122, 91, 143, 118, 120, 114, 104, 124, 117, + 148, 142, 117, 126, 97, 125, 108, 116, 142, 125, + 126, 106, 91, 169, 208, 178, 158, 138, 127, 135, + 133, 126, 101, 83, 147, 130, 125, 117, 114, 117, + 120, 103, 94, 149, 136, 129, 139, 118, 133, 133, + 147, 152, 126, 132, 119, 97, 132, 129, 114, 126, + 112, 107, 148, 125, 112, 114, 124, 125, 129, 135, + 139, 121, 157, 151, 131, 140, 118, 147, 136, 121, + 115, 105, 159, 167, 185, 191, 196, 190, 176, 160, + 124, 106, 104, 122, 130, 114, 152, 144, 134, 136, + 136, 152, 159, 153, 131, 114, 116, 126, 129, 129, + 124, 109, 87, 131, 107, 115, 130, 107, 144, 131, + 126, 162, 176, 175, 180, 176, 160, 141, 134, 134, + 136, 127, 108, 161, 162, 133, 141, 124, 112, 128, + 130, 115, 110, 140, 107, 155, 134, 131, 156, 137, + 122, 106, 116, 127, 118, 161, 150, 170, 167, 152, + 139, 177, 203, 176, 155, 139, 130, 128, 129, 132, + 137, 119, 125, 103, 110, 123, 107, 120, 108, 101, + 113, 107, 160, 154, 160, 166, 169, 176, 168, 156, + 115, 90, 65, 115, 115, 104, 120, 112, 109, 124, + 131, 123, 100, 109, 185, 158, 141, 132, 116, 119, + 139, 130, 119, 156, 124, 138, 127, 116, 141, 128, + 133, 118, 115, 180, 149, 151, 135, 130, 147, 129, + 117, 90, 80, 119, 124, 128, 132, 130, 128, 135, + 112, 97, 142, 161, 167, 165, 154, 142, 136, 135, + 118, 141, 193, 172, 157, 152, 148, 145, 146, 141, + 125, 147, 165, 166, 149, 133, 123, 122, 128, 131, + 128, 193, 177, 174, 182, 186, 197, 193, 191, 173, + 124, 144, 162, 133, 113, 113, 123, 128, 129, 130, + 117, 98, 121, 122, 137, 132, 110, 97, 111, 130, + 128, 176, 151, 125, 126, 134, 130, 121, 127, 130, + 122, 151, 142, 111, 106, 121, 126, 126, 130, 134, + 148, 167, 186, 153, 129, 122, 124, 128, 130, 128, + 148, 172, 206, 178, 171, 182, 169, 180, 172, 156, + 133, 164, 174, 160, 155, 163, 163, 172, 169, 158, + 132, 150, 147, 142, 152, 140, 140, 140, 134, 135, + 137, 158, 167, 172, 163, 153, 169, 158, 146, 147, + 150, 161, 162, 172, 153, 133, 140, 144, 136, 135, + 109, 84, 101, 120, 129, 134, 133, 136, 137, 143, + 112, 114, 157, 147, 141, 136, 135, 133, 135, 138, + 121, 154, 161, 150, 149, 154, 151, 144, 146, 144, + 111, 117, 125, 125, 130, 131, 135, 137, 143, 148, + 121, 141, 146, 131, 138, 126, 118, 111, 119, 130, + 120, 135, 145, 121, 140, 134, 138, 137, 131, 134, + 115, 137, 132, 137, 139, 138, 138, 139, 145, 149, + 131, 149, 147, 133, 132, 126, 131, 134, 130, 133, + 110, 98, 84, 141, 107, 169, 169, 123, 125, 126, + 118, 210, 98, 126, 132, 138, 128, 139, 156, 157, + 140, 142, 129, 95, 192, 178, 182, 186, 183, 159, + 135, 134, 144, 124, 100, 228, 203, 161, 122, 104, + 139, 159, 134, 161, 121, 126, 192, 152, 218, 180, + 132, 132, 119, 99, 96, 97, 80, 53, 134, 143, + 102, 114, 133, 114, 127, 83, 77, 126, 85, 107, + 110, 114, 194, 186, 139, 116, 147, 104, 129, 138, + 126, 133, 109, 144, 115, 45, 130, 97, 159, 155, + 157, 162, 189, 185, 168, 163, 151, 151, 142, 135, + 144, 147, 120, 74, 192, 186, 149, 118, 71, 84, + 143, 156, 133, 178, 168, 107, 119, 149, 105, 112, + 182, 184, 158, 118, 118, 148, 128, 177, 171, 152, + 139, 135, 126, 209, 171, 150, 123, 100, 190, 158, + 166, 97, 136, 123, 136, 139, 128, 138, 126, 121, + 132, 131, 128, 95, 60, 168, 127, 140, 208, 161, + 109, 102, 119, 162, 150, 137, 107, 200, 156, 136, + 136, 128, 103, 95, 74, 91, 220, 173, 152, 138, + 139, 129, 140, 136, 122, 82, 180, 115, 53, 90, + 121, 107, 99, 148, 116, 139, 100, 63, 191, 155, + 130, 129, 163, 155, 98, 175, 95, 151, 127, 107, + 124, 124, 116, 88, 71, 164, 148, 96, 57, 89, + 125, 117, 77, 63, 162, 144, 113, 109, 137, 134, + 134, 130, 149, 174, 158, 158, 130, 81, 28, 67, + 142, 139, 129, 100, 194, 134, 68, 175, 131, 103, + 136, 132, 122, 96, 119, 82, 115, 249, 215, 168, + 125, 139, 199, 96, 146, 123, 136, 179, 142, 137, + 181, 166, 106, 86, 122, 106, 123, 131, 106, 119, + 129, 189, 188, 147, 126, 110, 101, 114, 147, 136, + 132, 106, 72, 175, 148, 99, 130, 153, 125, 136, + 123, 119, 147, 170, 157, 126, 209, 188, 158, 152, + 101, 89, 142, 131, 161, 150, 148, 124, 89, 119, + 141, 137, 131, 103, 81, 85, 64, 175, 129, 121, + 137, 144, 142, 145, 119, 205, 148, 80, 165, 138, + 143, 137, 167, 165, 148, 149, 110, 234, 217, 170, + 167, 152, 75, 140, 155, 155, 175, 129, 136, 134, + 136, 152, 161, 131, 140, 121, 91, 79, 255, 209, + 132, 147, 120, 114, 177, 128, 110, 61, 89, 131, + 125, 127, 93, 87, 167, 115, 186, 162, 107, 106, + 134, 162, 151, 100, 79, 67, 151, 116, 130, 142, + 162, 153, 155, 143, 122, 85, 202, 187, 135, 125, + 158, 155, 103, 129, 74, 149, 130, 98, 129, 126, + 148, 152, 153, 133, 118, 94, 80, 70, 47, 90, + 124, 118, 143, 184, 158, 126, 70, 82, 111, 113, + 126, 135, 175, 141, 203, 166, 123, 123, 134, 133, + 113, 111, 128, 76, 128, 177, 151, 178, 134, 125, + 120, 120, 193, 106, 98, 134, 101, 86, 101, 114, + 136, 127, 134, 196, 86, 105, 145, 128, 119, 137, + 138, 126, 230, 161, 141, 128, 129, 136, 88, 83, + 103, 118, 178, 123, 89, 101, 161, 173, 165, 147, + 130, 123, 171, 158, 131, 81, 50, 177, 162, 136, + 125, 115, 82, 173, 195, 168, 130, 112, 112, 121, + 152, 148, 167, 87, 82, 161, 142, 147, 98, 89, + 168, 138, 97, 157, 132, 114, 74, 126, 161, 141, + 135, 123, 68, 137, 124, 118, 112, 92, 65, 96, + 191, 181, 161, 151, 141, 145, 129, 102, 97, 111, + 144, 128, 55, 128, 115, 155, 129, 184, 167, 147, + 131, 141, 125, 33, 127, 111, 127, 131, 125, 130, + 137, 130, 121, 195, 172, 177, 176, 149, 98, 97, + 126, 106, 168, 159, 144, 185, 156, 151, 182, 158, + 123, 93, 110, 116, 98, 99, 125, 136, 139, 148, + 79, 112, 149, 128, 147, 136, 118, 105, 166, 152, + 117, 115, 92, 128, 148, 132, 170, 143, 226, 190, + 122, 192, 165, 121, 143, 144, 174, 124, 113, 124, + 122, 135, 34, 93, 118, 111, 111, 136, 123, 116, + 99, 195, 139, 99, 114, 102, 96, 108, 111, 112, + 113, 129, 172, 137, 105, 139, 154, 86, 113, 108, + 132, 79, 63, 120, 93, 162, 90, 103, 94, 95, + 117, 127, 104, 100, 142, 129, 93, 27, 196, 153, + 113, 91, 101, 90, 84, 68, 138, 38, 118, 148, + 87, 103, 125, 109, 96, 152, 100, 56, 31, 62, + 176, 129, 124, 115, 103, 92, 100, 121, 130, 125, + 128, 71, 82, 71, 152, 85, 107, 116, 138, 133, + 103, 116, 139, 144, 72, 37, 118, 141, 109, 95, + 86, 92, 121, 167, 156, 104, 92, 91, 122, 114, + 89, 61, 172, 128, 95, 103, 84, 101, 88, 84, + 116, 125, 108, 62, 74, 108, 160, 143, 189, 164, + 91, 115, 144, 43, 116, 79, 106, 108, 74, 83, + 87, 90, 61, 71, 76, 76, 95, 130, 89, 94, + 114, 107, 101, 145, 161, 147, 143, 163, 147, 129, + 101, 73, 111, 108, 93, 104, 186, 141, 99, 89, + 112, 126, 111, 113, 152, 41, 159, 115, 131, 124, + 117, 101, 115, 130, 124, 87, 59, 177, 63, 85, + 109, 116, 103, 68, 145, 132, 29, 119, 96, 89, + 117, 90, 181, 103, 101, 111, 97, 96, 199, 171, + 113, 120, 93, 119, 101, 64, 56, 55, 63, 90, + 105, 101, 86, 45, 136, 179, 142, 102, 115, 114, + 113, 108, 121, 84, 23, 125, 76, 102, 119, 107, + 120, 104, 73, 177, 83, 114, 128, 85, 152, 126, + 137, 115, 149, 109, 163, 133, 110, 98, 54, 61, + 95, 111, 135, 103, 88, 164, 115, 187, 122, 98, + 129, 132, 95, 86, 71, 119, 146, 111, 38, 67, + 102, 100, 66, 148, 137, 103, 145, 95, 35, 85, + 44, 136, 102, 111, 108, 115, 136, 105, 120, 110, + 108, 147, 112, 169, 116, 146, 81, 120, 94, 84, + 93, 97, 90, 119, 102, 91, 48, 147, 204, 151, + 148, 160, 144, 131, 144, 175, 158, 133, 212, 163, + 172, 152, 151, 112, 148, 151, 145, 179, 160, 124, + 164, 164, 167, 161, 141, 120, 131, 141, 198, 177, + 169, 156, 146, 156, 124, 185, 164, 195, 181, 193, + 201, 147, 148, 168, 165, 159, 162, 148, 150, 148, + 146, 157, 158, 149, 164, 129, 160, 214, 174, 166, + 154, 176, 146, 141, 155, 140, 140, 169, 106, 155, + 166, 162, 134, 193, 157, 155, 146, 196, 171, 107, + 177, 174, 163, 155, 147, 203, 162, 146, 150, 83, + 157, 170, 180, 178, 159, 157, 151, 117, 115, 183, + 170, 180, 174, 150, 177, 173, 136, 181, 196, 184, + 164, 168, 165, 148, 175, 168, 209, 189, 159, 114, + 157, 158, 141, 168, 170, 139, 175, 128, 151, 39, + 128, 154, 159, 161, 148, 180, 131, 165, 159, 131, + 163, 150, 174, 178, 178, 198, 172, 138, 184, 191, + 143, 164, 161, 163, 210, 171, 155, 168, 150, 116, + 182, 170, 145, 152, 141, 139, 191, 149, 160, 202, + 145, 169, 145, 181, 148, 183, 197, 165, 146, 171, + 161, 153, 157, 170, 164, 149, 183, 167, 246, 235, + 162, 144, 170, 152, 173, 150, 113, 135, 156, 154, + 158, 148, 178, 159, 161, 114, 180, 156, 116, 163, + 164, 161, 122, 164, 164, 183, 135, 135, 144, 182, + 160, 147, 163, 152, 169, 185, 159, 177, 99, 211, + 168, 167, 215, 170, 150, 157, 154, 176, 154, 143, + 163, 117, 178, 160, 163, 165, 164, 166, 174, 136, + 159, 169, 152, 123, 199, 149, 169, 140, 159, 208, + 155, 161, 186, 122, 134, 167, 171, 145, 148, 176, + 148, 137, 114, 160, 166, 153, 162, 156, 164, 172, + 155, 148, 155, 182, 114, 150, 157, 154, 140, 159, + 166, 160, 169, 206, 182, 145, 157, 165, 147, 202, + 131, 154, 193, 162, 162, 149, 167, 157, 191, 188, + 149, 205, 147, 166, 150, 150, 159, 153, 171, 160 +}; + +static const uint8_t wmavoice_dq_lsp16i1[0x640] = { + 142, 121, 141, 112, 99, 119, 92, 122, 183, 155, + 122, 98, 75, 78, 85, 101, 108, 134, 128, 123, + 115, 90, 79, 58, 73, 127, 106, 60, 97, 107, + 141, 163, 130, 123, 136, 156, 201, 189, 204, 206, + 140, 116, 69, 60, 117, 123, 106, 124, 91, 63, + 150, 144, 110, 80, 63, 112, 80, 70, 76, 63, + 114, 86, 147, 165, 137, 125, 120, 140, 115, 101, + 101, 99, 166, 158, 158, 104, 126, 131, 134, 143, + 121, 102, 73, 36, 83, 132, 113, 76, 38, 20, + 132, 111, 78, 73, 51, 131, 108, 131, 105, 80, + 148, 138, 101, 65, 47, 115, 86, 50, 124, 129, + 116, 89, 85, 87, 64, 111, 74, 39, 115, 113, + 112, 83, 75, 122, 127, 114, 91, 106, 125, 130, + 131, 108, 79, 136, 112, 110, 147, 164, 144, 124, + 121, 236, 218, 190, 168, 106, 101, 160, 172, 191, + 113, 138, 102, 91, 109, 100, 71, 85, 112, 119, + 121, 96, 51, 64, 126, 135, 114, 76, 34, 104, + 145, 127, 90, 56, 131, 142, 131, 92, 123, 102, + 128, 105, 63, 24, 95, 115, 87, 49, 156, 174, + 123, 105, 88, 58, 55, 141, 119, 99, 75, 81, + 137, 117, 114, 80, 56, 119, 91, 106, 166, 135, + 114, 84, 38, 93, 116, 129, 103, 97, 87, 97, + 115, 184, 193, 173, 157, 117, 88, 114, 151, 121, + 126, 111, 75, 129, 133, 130, 107, 71, 115, 92, + 128, 108, 120, 100, 97, 111, 80, 119, 122, 91, + 114, 94, 149, 129, 136, 114, 88, 132, 110, 85, + 116, 99, 101, 71, 71, 110, 140, 142, 131, 110, + 122, 98, 83, 127, 100, 106, 130, 123, 114, 103, + 113, 87, 140, 116, 113, 140, 161, 171, 145, 129, + 115, 178, 158, 161, 160, 118, 195, 209, 221, 228, + 99, 83, 140, 134, 140, 127, 186, 168, 187, 187, + 107, 114, 100, 111, 111, 104, 130, 131, 116, 128, + 128, 104, 64, 18, 49, 126, 107, 69, 56, 153, + 154, 142, 110, 113, 89, 120, 93, 73, 190, 172, + 119, 96, 57, 21, 60, 126, 122, 81, 99, 117, + 159, 141, 108, 88, 120, 144, 125, 89, 44, 94, + 147, 131, 93, 81, 61, 133, 113, 85, 47, 62, + 123, 121, 87, 53, 90, 120, 94, 76, 70, 48, + 125, 103, 93, 64, 35, 140, 129, 88, 47, 30, + 127, 104, 58, 51, 103, 124, 100, 102, 76, 47, + 115, 87, 54, 46, 77, 182, 218, 174, 163, 145, + 140, 126, 89, 105, 82, 125, 119, 101, 69, 58, + 125, 107, 172, 145, 128, 138, 113, 109, 92, 90, + 117, 93, 83, 93, 132, 125, 102, 67, 148, 161, + 131, 110, 96, 99, 74, 119, 92, 54, 84, 81, + 110, 152, 120, 106, 131, 108, 74, 68, 99, 107, + 121, 97, 120, 101, 78, 132, 110, 127, 164, 134, + 111, 159, 204, 189, 178, 158, 183, 146, 144, 137, + 123, 106, 136, 108, 135, 117, 91, 163, 135, 113, + 119, 177, 134, 122, 121, 132, 109, 157, 131, 113, + 115, 87, 87, 100, 92, 120, 95, 59, 146, 139, + 129, 101, 135, 122, 101, 119, 100, 112, 88, 99, + 118, 90, 123, 125, 107, 121, 98, 73, 104, 80, + 112, 79, 86, 122, 96, 104, 81, 107, 90, 93, + 112, 150, 140, 109, 115, 113, 86, 73, 76, 112, + 130, 111, 101, 112, 84, 123, 97, 63, 134, 115, + 109, 77, 128, 141, 119, 125, 101, 108, 147, 119, + 134, 149, 150, 127, 115, 136, 244, 220, 210, 189, + 105, 138, 171, 156, 174, 117, 162, 133, 146, 141, + 115, 93, 119, 98, 122, 114, 106, 154, 145, 162, + 107, 131, 189, 165, 152, 101, 107, 129, 114, 139, + 116, 186, 186, 161, 180, 100, 89, 137, 116, 116, + 106, 130, 194, 196, 207, 110, 156, 157, 138, 149, + 102, 93, 159, 138, 120, 109, 132, 105, 122, 135, + 148, 128, 85, 76, 102, 168, 154, 141, 117, 100, + 125, 106, 62, 101, 146, 124, 102, 65, 25, 15, + 120, 94, 46, 21, 94, 149, 128, 115, 85, 92, + 119, 93, 70, 52, 30, 162, 151, 123, 91, 80, + 126, 112, 84, 47, 33, 138, 114, 73, 60, 87, + 126, 211, 174, 158, 143, 129, 106, 65, 31, 133, + 119, 95, 52, 99, 173, 123, 96, 119, 206, 178, + 127, 104, 60, 61, 67, 152, 136, 104, 63, 83, + 133, 130, 92, 64, 45, 120, 96, 53, 30, 130, + 128, 103, 74, 59, 35, 135, 114, 77, 30, 57, + 108, 130, 123, 90, 87, 143, 125, 93, 54, 60, + 133, 118, 79, 87, 95, 115, 89, 111, 88, 65, + 124, 102, 70, 40, 47, 148, 131, 123, 130, 104, + 127, 109, 87, 56, 121, 147, 123, 121, 107, 85, + 178, 237, 200, 193, 170, 139, 118, 100, 75, 110, + 133, 121, 81, 73, 68, 120, 195, 157, 141, 131, + 127, 102, 107, 88, 60, 136, 113, 100, 69, 45, + 128, 105, 93, 77, 67, 131, 116, 149, 184, 156, + 115, 85, 35, 45, 112, 128, 108, 68, 73, 111, + 118, 93, 187, 162, 139, 136, 115, 84, 57, 37, + 131, 133, 125, 98, 85, 138, 115, 92, 86, 61, + 116, 96, 70, 52, 110, 115, 109, 135, 104, 88, + 136, 159, 122, 109, 115, 122, 110, 98, 70, 95, + 112, 81, 68, 85, 90, 124, 101, 87, 56, 89, + 109, 82, 98, 100, 115, 124, 102, 76, 88, 63, + 111, 78, 42, 78, 102, 110, 71, 64, 131, 111, + 125, 104, 107, 87, 123, 129, 131, 99, 85, 68, + 147, 137, 102, 99, 75, 120, 155, 142, 109, 91, + 132, 109, 131, 141, 113, 136, 119, 94, 152, 128, + 127, 102, 79, 159, 134, 111, 78, 98, 109, 80, + 115, 86, 51, 63, 103, 116, 86, 170, 149, 123, + 135, 178, 159, 125, 114, 113, 189, 226, 203, 202, + 140, 117, 116, 94, 70, 128, 103, 94, 174, 149, + 118, 98, 83, 84, 106, 115, 157, 120, 94, 95, + 131, 112, 75, 96, 74, 121, 97, 144, 117, 95, + 120, 90, 140, 138, 110, 119, 93, 55, 92, 114, + 114, 87, 151, 125, 100, 111, 82, 83, 160, 139, + 114, 86, 56, 90, 138, 104, 109, 101, 77, 118, + 140, 142, 143, 148, 126, 121, 102, 129, 107, 111, + 113, 79, 58, 111, 91, 120, 94, 63, 115, 98, + 121, 94, 99, 97, 78, 120, 92, 68, 173, 148, + 122, 114, 109, 87, 82, 132, 229, 192, 176, 155, + 137, 116, 123, 97, 115, 132, 115, 86, 120, 95, + 135, 116, 101, 136, 108, 109, 74, 100, 125, 115, + 112, 158, 144, 124, 134, 114, 83, 73, 147, 120, + 120, 104, 150, 122, 116, 110, 104, 192, 183, 174, + 134, 112, 116, 120, 93, 121, 101, 93, 110, 90, + 121, 93, 147, 152, 122, 115, 153, 171, 161, 142, + 123, 95, 116, 114, 93, 113, 89, 96, 77, 93, + 113, 174, 180, 143, 138, 116, 86, 100, 135, 106, + 103, 121, 149, 115, 103, 121, 95, 82, 149, 121, + 117, 92, 93, 111, 114, 123, 209, 196, 193, 183, + 125, 102, 107, 130, 104, 115, 91, 113, 103, 99, + 114, 86, 68, 108, 110, 111, 159, 162, 125, 113, + 125, 235, 234, 225, 214, 99, 74, 118, 121, 127, + 104, 123, 158, 128, 127, 113, 96, 116, 136, 158, + 100, 80, 138, 155, 166, 118, 143, 115, 125, 114, + 119, 137, 133, 136, 139, 151, 188, 172, 174, 173, + 138, 161, 158, 158, 155, 121, 198, 194, 211, 202, + 100, 90, 112, 110, 122, 100, 91, 122, 128, 135, + 101, 109, 127, 101, 114, 105, 126, 160, 147, 143, + 109, 138, 142, 158, 163, 113, 174, 185, 188, 206, + 112, 154, 166, 176, 183, 101, 108, 140, 140, 143, + 106, 135, 130, 137, 126, 103, 114, 115, 128, 126, + 107, 86, 21, 115, 75, 117, 139, 97, 65, 105, + 64, 191, 101, 106, 139, 107, 98, 218, 132, 104, + 73, 136, 165, 84, 118, 150, 111, 58, 130, 107, + 99, 136, 132, 56, 52, 102, 136, 69, 78, 163, + 85, 173, 148, 138, 85, 69, 106, 128, 133, 155, + 104, 91, 149, 56, 104, 103, 101, 172, 96, 57, + 104, 97, 125, 197, 166, 107, 169, 47, 120, 103, + 150, 89, 99, 139, 162, 101, 69, 137, 158, 126, + 191, 173, 127, 79, 155, 51, 131, 112, 86, 74, + 135, 61, 114, 81, 125, 117, 112, 72, 175, 72, + 127, 123, 142, 132, 78, 116, 158, 111, 121, 143, + 108, 102, 89, 20, 194, 81, 99, 107, 65, 150, + 103, 78, 91, 69, 96, 104, 116, 116, 103, 105, + 107, 117, 110, 130, 28, 88, 103, 62, 72, 85, + 125, 126, 141, 126, 178, 121, 102, 57, 46, 124, + 97, 91, 89, 138, 95, 98, 143, 99, 169, 123, + 140, 119, 113, 82, 140, 118, 112, 91, 92, 241, + 134, 89, 95, 112, 78, 167, 140, 145, 121, 100, + 109, 205, 144, 91, 100, 113, 103, 142, 175, 95, + 117, 121, 35, 121, 127, 159, 129, 85, 64, 75, + 116, 98, 103, 127, 129, 66, 68, 110, 96, 86, + 79, 100, 156, 133, 92, 135, 96, 164, 132, 121, + 93, 163, 134, 91, 208, 104, 77, 126, 116, 58, + 136, 118, 132, 81, 61, 73, 115, 66, 129, 123, + 111, 85, 42, 178, 134, 108, 132, 159, 45, 157, + 105, 164, 100, 94, 60, 96, 57, 154, 105, 102, + 103, 114, 96, 12, 91, 119, 115, 67, 92, 64, + 94, 61, 106, 106, 165, 105, 94, 98, 68, 30, + 146, 130, 107, 173, 140, 102, 90, 163, 106, 184, + 100, 53, 68, 131, 92, 105, 111, 68, 153, 186, + 101, 82, 48, 99, 147, 122, 136, 176, 96, 96, + 104, 132, 167, 149, 136, 138, 144, 97, 120, 92 +}; + +static const uint8_t wmavoice_dq_lsp16i2[0x3c0] = { + 23, 12, 107, 119, 110, 205, 214, 212, 208, 201, + 102, 95, 69, 117, 107, 118, 123, 118, 123, 121, + 82, 58, 83, 95, 84, 139, 145, 153, 161, 169, + 102, 100, 138, 121, 101, 129, 130, 138, 150, 139, + 76, 104, 86, 112, 133, 113, 91, 63, 73, 129, + 199, 193, 182, 181, 172, 119, 101, 83, 94, 76, + 161, 157, 152, 157, 158, 110, 90, 121, 96, 79, + 124, 107, 114, 88, 73, 152, 137, 121, 107, 99, + 57, 50, 100, 81, 74, 115, 96, 72, 49, 69, + 83, 68, 40, 53, 103, 36, 131, 107, 84, 64, + 236, 245, 242, 231, 213, 95, 109, 88, 69, 110, + 228, 221, 204, 182, 170, 129, 110, 97, 118, 104, + 98, 76, 98, 75, 61, 93, 77, 113, 91, 72, + 116, 94, 106, 134, 118, 177, 188, 169, 162, 153, + 163, 149, 131, 131, 132, 177, 163, 173, 168, 158, + 113, 131, 107, 113, 100, 132, 143, 131, 134, 142, + 45, 36, 121, 113, 102, 43, 95, 84, 67, 56, + 76, 82, 68, 48, 33, 55, 58, 59, 43, 65, + 66, 85, 66, 81, 94, 102, 82, 54, 33, 94, + 113, 111, 89, 60, 34, 138, 120, 101, 101, 86, + 88, 73, 55, 114, 115, 92, 74, 93, 77, 123, + 90, 117, 99, 79, 59, 97, 75, 97, 122, 104, + 233, 237, 227, 208, 190, 209, 230, 233, 240, 241, + 195, 197, 188, 167, 147, 204, 185, 168, 162, 157, + 142, 124, 119, 123, 106, 117, 110, 81, 121, 123, + 74, 116, 124, 119, 120, 178, 168, 146, 132, 125, + 102, 104, 105, 110, 114, 104, 82, 78, 100, 86, + 120, 102, 105, 93, 143, 127, 108, 128, 106, 88, + 177, 189, 203, 207, 215, 101, 131, 119, 95, 73, + 149, 139, 135, 147, 153, 160, 167, 165, 174, 177, + 120, 109, 134, 140, 145, 131, 130, 142, 139, 161, + 143, 158, 148, 145, 145, 123, 142, 132, 116, 102, + 40, 23, 79, 82, 84, 26, 83, 141, 130, 122, + 65, 46, 43, 89, 86, 28, 75, 80, 79, 98, + 84, 65, 47, 26, 44, 49, 112, 101, 100, 94, + 88, 76, 75, 48, 82, 104, 100, 75, 45, 15, + 99, 83, 63, 34, 30, 66, 55, 94, 118, 113, + 122, 106, 91, 68, 60, 135, 122, 104, 77, 59, + 82, 102, 84, 62, 46, 92, 74, 55, 82, 71, + 145, 134, 118, 93, 75, 79, 62, 83, 65, 55, + 91, 94, 64, 70, 98, 89, 117, 110, 87, 97, + 210, 223, 225, 223, 213, 83, 103, 86, 101, 85, + 126, 106, 81, 79, 105, 216, 219, 217, 199, 179, + 86, 78, 115, 138, 135, 102, 84, 87, 59, 46, + 219, 206, 184, 167, 158, 201, 188, 165, 145, 135, + 87, 113, 142, 152, 155, 190, 170, 153, 149, 146, + 205, 208, 201, 185, 167, 84, 73, 124, 104, 96, + 76, 88, 99, 74, 80, 110, 125, 122, 99, 112, + 108, 84, 70, 130, 137, 161, 152, 136, 119, 105, + 110, 91, 101, 74, 96, 111, 101, 93, 153, 149, + 133, 124, 102, 97, 120, 101, 93, 75, 81, 64, + 111, 94, 107, 79, 58, 188, 206, 215, 221, 232, + 163, 175, 165, 150, 136, 103, 106, 123, 133, 132, + 168, 184, 191, 183, 170, 110, 117, 90, 98, 93, + 104, 87, 122, 98, 127, 129, 110, 127, 113, 125, + 134, 118, 102, 140, 132, 186, 199, 202, 198, 188, + 149, 147, 175, 185, 186, 117, 93, 99, 112, 93, + 107, 138, 138, 129, 128, 96, 129, 104, 118, 134, + 145, 136, 115, 121, 129, 138, 155, 148, 134, 120, + 170, 151, 150, 145, 138, 168, 173, 185, 194, 200, + 144, 159, 172, 168, 156, 121, 121, 138, 173, 168, + 126, 111, 140, 139, 117, 149, 133, 142, 137, 130, + 143, 139, 158, 158, 146, 119, 128, 121, 132, 145, + 122, 136, 159, 153, 141, 133, 133, 130, 129, 126, + 120, 76, 50, 149, 109, 92, 155, 118, 90, 66, + 132, 117, 87, 156, 117, 119, 102, 44, 83, 91, + 109, 73, 106, 84, 29, 55, 130, 112, 81, 241, + 75, 40, 91, 89, 67, 112, 90, 149, 81, 72, + 128, 90, 71, 28, 160, 73, 157, 123, 143, 108, + 63, 88, 70, 81, 97, 75, 111, 149, 113, 96, + 78, 104, 83, 179, 95, 105, 106, 65, 130, 66, + 51, 118, 92, 53, 68, 105, 75, 176, 151, 115, + 94, 75, 68, 95, 220, 103, 125, 105, 43, 95, + 39, 114, 65, 145, 135, 33, 142, 138, 103, 52, + 82, 85, 117, 110, 67, 102, 74, 42, 62, 118, + 144, 121, 82, 57, 102, 67, 75, 44, 129, 96, + 75, 63, 88, 48, 116, 135, 94, 85, 102, 66, + 122, 77, 105, 122, 152, 120, 56, 90, 83, 100, + 90, 128, 63, 80, 103, 126, 117, 103, 80, 193, + 42, 73, 117, 93, 91, 95, 128, 100, 128, 162, + 70, 120, 126, 73, 123, 99, 99, 91, 75, 135, + 81, 125, 111, 77, 13, 94, 78, 85, 187, 157, + 11, 143, 109, 99, 119, 53, 141, 82, 122, 68, + 132, 89, 136, 119, 88, 75, 49, 174, 119, 70, + 138, 121, 108, 78, 52, 104, 90, 96, 93, 93, + 114, 90, 78, 46, 58, 62, 114, 69, 44, 162, + 103, 58, 98, 141, 83, 137, 95, 119, 73, 111, + 81, 46, 126, 111, 123, 107, 117, 122, 121, 54, + 106, 104, 59, 110, 148, 97, 155, 97, 83, 133, + 97, 71, 57, 91, 58, 52, 79, 127, 152, 109, + 96, 92, 145, 107, 149, 102, 61, 125, 61, 170, + 56, 89, 77, 106, 38, 147, 96, 77, 105, 123, + 85, 83, 117, 63, 69, 126, 133, 93, 107, 92, + 77, 115, 95, 111, 103, 61, 87, 103, 98, 155, + 94, 111, 80, 78, 54, 117, 128, 130, 99, 109, + 106, 99, 113, 133, 115, 89, 65, 74, 112, 127 +}; + +static const uint8_t wmavoice_dq_lsp16i3[0x300] = { + 70, 100, 121, 129, 132, 132, 201, 188, 165, 145, 144, 136, + 112, 127, 116, 125, 130, 129, 124, 135, 135, 146, 129, 128, + 162, 158, 144, 151, 135, 129, 103, 86, 111, 113, 112, 122, + 90, 139, 129, 117, 126, 129, 142, 145, 167, 147, 124, 124, + 230, 209, 189, 175, 156, 141, 64, 80, 86, 108, 121, 129, + 44, 79, 115, 113, 115, 128, 133, 106, 79, 109, 125, 127, + 171, 156, 132, 109, 103, 115, 106, 70, 93, 145, 141, 128, + 148, 125, 122, 107, 110, 117, 146, 145, 128, 110, 98, 111, + 237, 212, 185, 156, 139, 133, 84, 55, 26, 77, 114, 127, + 172, 170, 171, 168, 162, 143, 82, 82, 76, 70, 104, 126, + 17, 95, 109, 111, 120, 132, 81, 74, 57, 126, 141, 131, + 110, 127, 162, 148, 129, 123, 177, 172, 155, 151, 145, 134, + 144, 123, 90, 66, 109, 130, 82, 127, 103, 123, 132, 131, + 127, 97, 97, 142, 140, 128, 159, 134, 136, 123, 113, 117, + 131, 140, 154, 169, 158, 134, 96, 109, 150, 122, 105, 120, + 120, 150, 152, 122, 119, 125, 123, 126, 124, 107, 100, 113, + 248, 233, 216, 189, 160, 142, 58, 24, 13, 77, 111, 127, + 183, 189, 182, 157, 140, 131, 96, 83, 59, 43, 73, 119, + 222, 196, 171, 146, 129, 128, 32, 13, 53, 101, 114, 127, + 119, 101, 70, 70, 110, 127, 77, 86, 161, 148, 130, 118, + 199, 183, 170, 167, 156, 141, 30, 115, 142, 133, 131, 130, + 101, 103, 181, 176, 152, 126, 66, 44, 73, 94, 111, 128, + 150, 122, 100, 101, 104, 118, 61, 110, 87, 76, 93, 125, + 190, 170, 150, 134, 135, 129, 112, 89, 63, 123, 141, 132, + 175, 154, 136, 142, 140, 132, 117, 143, 129, 128, 136, 132, + 168, 142, 112, 113, 128, 128, 155, 169, 159, 144, 139, 131, + 61, 136, 144, 124, 112, 123, 86, 81, 104, 121, 129, 130, + 160, 127, 118, 150, 151, 134, 126, 115, 121, 132, 134, 131, + 137, 148, 144, 139, 140, 134, 106, 102, 105, 90, 87, 113, + 134, 129, 128, 121, 121, 123, 153, 151, 129, 139, 142, 134, + 150, 142, 141, 148, 149, 141, 100, 121, 133, 147, 150, 134, + 163, 158, 147, 132, 141, 132, 142, 127, 141, 136, 136, 132, + 232, 218, 205, 189, 169, 146, 243, 224, 201, 171, 147, 138, + 224, 196, 169, 162, 154, 140, 51, 20, 59, 111, 121, 128, + 203, 197, 193, 177, 162, 145, 75, 40, 47, 122, 130, 129, + 102, 77, 47, 83, 121, 129, 111, 108, 84, 56, 63, 114, + 211, 181, 154, 137, 126, 125, 213, 198, 186, 162, 144, 138, + 41, 45, 90, 110, 118, 130, 83, 63, 130, 164, 153, 128, + 195, 167, 142, 123, 113, 119, 19, 42, 105, 113, 120, 132, + 50, 63, 49, 64, 112, 128, 114, 90, 132, 171, 162, 134, + 129, 128, 107, 83, 74, 110, 50, 116, 109, 120, 128, 132, + 94, 59, 73, 111, 117, 126, 197, 170, 166, 153, 138, 132, + 65, 48, 109, 133, 131, 128, 170, 163, 172, 158, 138, 130, + 66, 126, 147, 160, 151, 132, 42, 129, 117, 95, 91, 120, + 97, 165, 164, 142, 133, 125, 163, 142, 114, 88, 97, 122, + 104, 77, 142, 143, 128, 120, 136, 160, 188, 169, 149, 130, + 113, 83, 85, 102, 114, 125, 164, 169, 142, 120, 122, 124, + 98, 152, 132, 105, 92, 117, 42, 71, 125, 155, 151, 137, + 94, 105, 81, 107, 118, 126, 84, 56, 123, 117, 108, 122, + 174, 179, 166, 137, 118, 121, 130, 103, 147, 152, 134, 124, + 148, 127, 94, 117, 144, 134, 129, 106, 102, 95, 106, 118, + 147, 157, 153, 125, 103, 117, 155, 128, 113, 132, 120, 122, + 181, 151, 136, 126, 122, 122, 110, 111, 109, 108, 120, 124, + 97, 130, 103, 89, 107, 124, 179, 158, 158, 142, 131, 128, + 142, 111, 115, 122, 126, 125, 145, 145, 134, 115, 129, 128, + 130, 139, 112, 99, 121, 125, 79, 104, 119, 102, 105, 123, + 116, 121, 136, 125, 126, 127, 124, 100, 122, 119, 111, 119, + 159, 140, 139, 128, 138, 131, 105, 100, 116, 128, 135, 132, + 159, 142, 156, 147, 140, 134, 130, 150, 129, 126, 114, 120, + 138, 124, 146, 131, 109, 119, 93, 115, 125, 131, 125, 129, + 125, 121, 101, 119, 114, 120, 163, 154, 151, 153, 153, 139, + 166, 153, 150, 133, 119, 121, 159, 151, 128, 130, 122, 123, + 147, 154, 144, 133, 128, 127, 129, 131, 134, 140, 148, 138, + 138, 136, 120, 131, 135, 131, 150, 140, 137, 144, 129, 129 +}; + +static const uint8_t wmavoice_dq_lsp10r[0x1400] = { + 128, 128, 129, 129, 130, 130, 131, 130, 129, 129, + 134, 133, 127, 125, 136, 135, 135, 134, 173, 172, + 133, 139, 136, 165, 133, 176, 137, 159, 135, 152, + 147, 161, 147, 152, 149, 156, 146, 146, 140, 136, + 134, 135, 136, 140, 139, 155, 123, 133, 132, 142, + 132, 148, 143, 177, 124, 143, 123, 136, 126, 134, + 126, 125, 125, 124, 129, 128, 123, 123, 133, 133, + 116, 116, 121, 121, 121, 120, 129, 128, 131, 131, + 132, 133, 132, 129, 138, 124, 138, 124, 132, 100, + 135, 94, 149, 111, 152, 115, 150, 128, 141, 133, + 129, 129, 130, 129, 147, 145, 136, 137, 120, 122, + 120, 122, 127, 129, 104, 108, 113, 115, 124, 124, + 140, 139, 147, 145, 132, 130, 184, 177, 201, 196, + 170, 171, 160, 161, 145, 147, 137, 145, 131, 131, + 130, 130, 130, 130, 130, 130, 132, 134, 131, 132, + 131, 133, 141, 144, 142, 149, 84, 93, 103, 104, + 139, 139, 142, 140, 147, 147, 172, 165, 122, 121, + 98, 100, 101, 106, 112, 117, 122, 124, 124, 124, + 134, 133, 133, 133, 146, 142, 147, 145, 156, 156, + 143, 146, 119, 124, 129, 132, 151, 149, 136, 135, + 147, 148, 181, 180, 199, 188, 190, 173, 166, 161, + 147, 142, 153, 149, 154, 146, 150, 146, 138, 134, + 131, 135, 96, 136, 48, 138, 56, 131, 63, 124, + 85, 128, 103, 132, 117, 134, 120, 132, 125, 129, + 131, 130, 129, 128, 129, 128, 163, 168, 117, 120, + 121, 121, 136, 138, 131, 132, 135, 136, 131, 133, + 133, 133, 133, 134, 117, 118, 105, 109, 142, 151, + 144, 159, 131, 138, 121, 126, 123, 123, 121, 124, + 131, 131, 129, 129, 141, 140, 142, 134, 87, 90, + 109, 109, 130, 127, 139, 143, 133, 131, 127, 126, + 134, 135, 134, 136, 97, 98, 130, 132, 134, 137, + 115, 119, 125, 130, 107, 109, 119, 118, 126, 127, + 134, 135, 127, 132, 172, 203, 160, 196, 152, 179, + 152, 172, 148, 168, 153, 172, 145, 156, 137, 140, + 102, 116, 42, 56, 74, 61, 82, 70, 86, 78, + 101, 97, 104, 100, 115, 108, 116, 108, 123, 118, + 149, 143, 166, 129, 168, 96, 142, 95, 135, 98, + 117, 86, 116, 93, 121, 108, 119, 107, 121, 117, + 135, 135, 127, 138, 72, 132, 99, 136, 112, 147, + 120, 152, 136, 155, 138, 146, 140, 142, 134, 139, + 163, 145, 192, 130, 147, 124, 147, 125, 133, 125, + 127, 124, 128, 123, 129, 122, 130, 122, 130, 125, + 130, 137, 135, 180, 124, 133, 130, 129, 132, 133, + 124, 124, 131, 130, 132, 136, 126, 124, 127, 125, + 132, 132, 133, 133, 144, 140, 143, 142, 137, 135, + 143, 138, 152, 149, 221, 219, 158, 161, 143, 141, + 130, 129, 140, 135, 170, 145, 193, 156, 186, 152, + 167, 139, 151, 131, 142, 127, 134, 120, 131, 125, + 135, 133, 141, 125, 199, 109, 137, 126, 134, 123, + 130, 129, 132, 123, 128, 125, 122, 126, 125, 125, + 130, 128, 91, 89, 138, 135, 139, 134, 133, 129, + 132, 130, 125, 128, 136, 135, 129, 127, 126, 126, + 132, 131, 133, 131, 128, 120, 132, 126, 126, 119, + 134, 130, 131, 123, 104, 95, 140, 141, 136, 137, + 133, 133, 133, 134, 117, 98, 74, 49, 112, 111, + 123, 122, 126, 127, 131, 131, 127, 126, 128, 129, + 130, 131, 124, 127, 101, 107, 108, 109, 115, 115, + 100, 99, 130, 128, 134, 136, 125, 127, 128, 130, + 136, 137, 145, 150, 149, 164, 136, 151, 114, 111, + 124, 125, 143, 150, 162, 174, 158, 169, 136, 137, + 131, 131, 131, 131, 132, 133, 111, 110, 122, 121, + 136, 136, 134, 133, 131, 132, 127, 127, 125, 125, + 128, 129, 129, 130, 125, 127, 140, 140, 148, 149, + 133, 136, 146, 153, 110, 118, 127, 129, 128, 129, + 131, 133, 127, 131, 140, 161, 167, 224, 131, 139, + 136, 143, 135, 139, 138, 143, 149, 155, 141, 143, + 134, 132, 120, 111, 83, 83, 121, 126, 102, 107, + 112, 115, 97, 104, 120, 115, 129, 123, 122, 122, + 134, 135, 122, 131, 102, 124, 114, 119, 93, 103, + 78, 79, 67, 72, 66, 73, 78, 82, 103, 102, + 144, 135, 165, 139, 165, 129, 160, 126, 153, 127, + 161, 134, 160, 142, 160, 143, 148, 140, 138, 135, + 138, 95, 147, 54, 143, 78, 140, 112, 142, 113, + 140, 121, 135, 117, 135, 122, 136, 131, 131, 132, + 147, 159, 140, 156, 127, 81, 142, 128, 146, 127, + 144, 125, 146, 128, 149, 130, 144, 135, 133, 128, + 130, 131, 131, 131, 134, 139, 126, 134, 141, 154, + 168, 205, 153, 176, 148, 163, 147, 158, 141, 143, + 131, 135, 126, 146, 108, 157, 107, 156, 119, 146, + 100, 138, 104, 125, 119, 134, 101, 122, 113, 122, + 95, 133, 52, 140, 83, 136, 110, 133, 114, 131, + 123, 131, 133, 131, 138, 135, 132, 132, 127, 127, + 129, 128, 124, 122, 128, 126, 145, 170, 143, 172, + 141, 163, 143, 176, 138, 164, 139, 155, 135, 145, + 135, 136, 136, 127, 132, 76, 128, 76, 127, 63, + 125, 66, 123, 67, 120, 71, 124, 92, 122, 111, + 133, 133, 135, 136, 139, 140, 147, 147, 150, 144, + 156, 147, 150, 145, 154, 146, 120, 123, 123, 124, + 137, 133, 170, 141, 124, 124, 135, 134, 134, 135, + 132, 132, 129, 129, 130, 130, 136, 136, 130, 132, + 147, 159, 135, 158, 115, 146, 120, 148, 117, 136, + 115, 137, 113, 132, 133, 142, 140, 144, 132, 134, + 134, 135, 134, 137, 137, 147, 162, 178, 136, 147, + 134, 144, 123, 132, 111, 113, 113, 113, 124, 124, + 132, 131, 126, 126, 117, 114, 100, 95, 130, 125, + 157, 145, 164, 156, 163, 158, 145, 145, 133, 134, + 134, 134, 127, 126, 113, 102, 136, 130, 124, 122, + 143, 145, 127, 131, 135, 143, 133, 137, 132, 132, + 92, 94, 122, 125, 128, 129, 131, 130, 134, 135, + 132, 128, 129, 127, 132, 132, 131, 129, 127, 127, + 129, 129, 132, 131, 139, 131, 137, 132, 216, 178, + 146, 134, 147, 137, 151, 142, 148, 139, 144, 138, + 128, 127, 129, 129, 123, 131, 71, 91, 126, 128, + 130, 134, 117, 123, 125, 125, 135, 140, 129, 132, + 132, 132, 133, 134, 124, 130, 127, 133, 133, 138, + 142, 149, 135, 141, 145, 149, 154, 164, 135, 138, + 135, 135, 141, 142, 138, 137, 116, 96, 105, 86, + 127, 118, 128, 120, 124, 117, 125, 117, 125, 121, + 131, 131, 132, 134, 144, 145, 112, 112, 121, 123, + 113, 116, 121, 123, 139, 138, 128, 128, 131, 131, + 134, 132, 132, 132, 125, 128, 127, 130, 125, 131, + 120, 128, 90, 119, 68, 98, 99, 112, 115, 124, + 135, 135, 134, 134, 128, 129, 137, 137, 137, 138, + 110, 114, 129, 130, 144, 145, 123, 125, 129, 129, + 132, 133, 129, 130, 168, 187, 140, 149, 137, 144, + 129, 130, 129, 134, 133, 138, 118, 118, 122, 120, + 131, 130, 129, 128, 133, 133, 125, 125, 124, 123, + 181, 179, 129, 129, 131, 127, 139, 136, 130, 128, + 133, 133, 132, 132, 121, 120, 122, 119, 132, 129, + 129, 125, 107, 96, 136, 137, 150, 146, 135, 134, + 131, 131, 130, 130, 126, 123, 126, 123, 128, 125, + 130, 123, 134, 127, 183, 159, 143, 135, 137, 134, + 129, 129, 128, 128, 134, 133, 139, 138, 133, 132, + 129, 127, 154, 151, 150, 144, 146, 146, 141, 142, + 132, 132, 131, 131, 130, 130, 132, 133, 114, 115, + 132, 132, 122, 122, 132, 131, 115, 117, 120, 120, + 129, 129, 130, 130, 130, 129, 130, 131, 129, 131, + 130, 130, 129, 129, 133, 132, 143, 144, 91, 91, + 137, 136, 118, 107, 60, 45, 56, 49, 57, 52, + 60, 56, 71, 75, 77, 80, 92, 97, 106, 106, + 112, 131, 58, 121, 19, 65, 84, 101, 108, 122, + 121, 127, 112, 117, 106, 112, 117, 124, 126, 127, + 130, 129, 138, 133, 166, 155, 192, 179, 192, 177, + 208, 191, 204, 192, 186, 179, 163, 163, 138, 142, + 134, 134, 144, 142, 243, 236, 148, 146, 141, 137, + 145, 141, 151, 144, 147, 143, 135, 139, 134, 133, + 134, 128, 138, 88, 142, 10, 127, 76, 130, 96, + 129, 102, 128, 108, 123, 111, 127, 119, 127, 124, + 136, 136, 139, 139, 142, 140, 246, 241, 158, 167, + 143, 145, 146, 149, 143, 145, 148, 152, 133, 134, + 139, 135, 135, 136, 99, 137, 95, 133, 75, 138, + 67, 135, 73, 128, 83, 132, 96, 126, 115, 127, + 130, 132, 137, 136, 140, 135, 134, 130, 137, 131, + 159, 151, 215, 197, 181, 170, 160, 149, 150, 143, + 145, 148, 186, 207, 141, 147, 135, 137, 122, 122, + 126, 125, 128, 126, 127, 127, 134, 126, 131, 123, + 133, 133, 126, 122, 128, 122, 99, 93, 59, 60, + 82, 82, 106, 107, 119, 123, 124, 128, 128, 129, + 134, 137, 133, 139, 133, 136, 141, 132, 139, 122, + 142, 97, 130, 81, 128, 89, 129, 101, 125, 112, + 137, 140, 129, 148, 101, 159, 118, 180, 122, 178, + 120, 178, 116, 168, 118, 153, 127, 151, 126, 136, + 132, 134, 125, 126, 118, 105, 156, 124, 180, 132, + 163, 124, 148, 121, 131, 112, 127, 115, 125, 122, + 129, 131, 128, 129, 136, 134, 142, 141, 165, 158, + 203, 182, 141, 136, 132, 130, 135, 135, 130, 130, + 133, 133, 132, 132, 127, 126, 106, 105, 112, 110, + 106, 105, 80, 84, 100, 101, 122, 125, 126, 128, + 101, 109, 46, 59, 114, 112, 119, 119, 126, 121, + 129, 124, 128, 125, 125, 122, 123, 120, 125, 122, + 135, 134, 121, 134, 56, 139, 131, 145, 135, 138, + 136, 139, 126, 130, 122, 132, 126, 129, 124, 129, + 153, 169, 146, 179, 138, 139, 151, 143, 148, 138, + 153, 137, 142, 129, 144, 126, 140, 128, 133, 126, + 136, 134, 154, 149, 173, 157, 152, 144, 149, 141, + 137, 136, 127, 121, 123, 121, 121, 126, 120, 123, + 157, 143, 166, 135, 120, 122, 112, 118, 102, 118, + 111, 124, 134, 131, 141, 138, 135, 134, 126, 129, + 140, 123, 152, 76, 131, 116, 138, 136, 126, 134, + 130, 142, 126, 136, 120, 132, 126, 128, 124, 127, + 131, 138, 80, 147, 126, 138, 130, 140, 129, 134, + 133, 135, 131, 132, 126, 127, 127, 125, 125, 123, + 132, 132, 130, 132, 123, 130, 102, 102, 107, 110, + 116, 127, 132, 152, 142, 160, 143, 151, 142, 146, + 132, 132, 132, 132, 125, 126, 132, 140, 158, 199, + 135, 149, 134, 140, 135, 131, 129, 120, 127, 121, + 129, 130, 122, 123, 125, 124, 138, 138, 138, 135, + 140, 141, 101, 94, 105, 98, 121, 122, 127, 128, + 126, 127, 119, 121, 133, 156, 132, 159, 130, 148, + 137, 164, 127, 138, 130, 137, 135, 140, 126, 126, + 128, 129, 129, 129, 126, 124, 130, 128, 143, 138, + 149, 143, 185, 170, 129, 127, 138, 133, 138, 135, + 132, 134, 137, 144, 139, 183, 131, 145, 127, 128, + 128, 127, 128, 122, 129, 125, 145, 139, 135, 131, + 132, 133, 132, 130, 152, 96, 159, 85, 150, 105, + 154, 115, 143, 120, 138, 126, 134, 124, 130, 126, + 128, 127, 121, 123, 122, 123, 116, 125, 84, 87, + 133, 135, 129, 131, 123, 126, 133, 135, 131, 130, + 136, 134, 129, 119, 79, 63, 116, 116, 136, 133, + 133, 130, 140, 143, 127, 127, 124, 125, 127, 128, + 128, 126, 124, 120, 139, 128, 153, 134, 151, 134, + 174, 145, 159, 136, 165, 144, 171, 149, 143, 135, + 134, 134, 133, 133, 121, 119, 177, 162, 166, 154, + 127, 130, 132, 132, 136, 137, 142, 143, 138, 137, + 167, 151, 162, 142, 128, 136, 142, 148, 128, 143, + 145, 153, 140, 149, 132, 141, 128, 139, 127, 133, + 156, 169, 131, 129, 126, 120, 127, 125, 129, 120, + 131, 126, 126, 123, 124, 121, 122, 121, 123, 123, + 138, 140, 149, 156, 145, 152, 105, 102, 131, 126, + 151, 146, 147, 139, 144, 137, 143, 133, 135, 130, + 132, 130, 131, 129, 126, 130, 126, 129, 110, 135, + 115, 139, 108, 146, 105, 147, 121, 134, 124, 133, + 137, 137, 135, 134, 143, 142, 146, 146, 120, 121, + 139, 137, 133, 129, 149, 145, 139, 133, 130, 127, + 134, 134, 134, 134, 125, 124, 117, 119, 120, 113, + 84, 80, 122, 125, 108, 112, 97, 102, 118, 120, + 124, 123, 115, 116, 110, 111, 98, 97, 127, 124, + 129, 127, 120, 117, 114, 109, 106, 104, 116, 116, + 138, 138, 139, 141, 142, 146, 127, 125, 133, 130, + 134, 128, 134, 127, 116, 91, 105, 84, 114, 106, + 128, 128, 126, 126, 131, 137, 126, 129, 133, 139, + 134, 145, 132, 143, 150, 192, 131, 142, 138, 141, + 132, 130, 132, 130, 149, 138, 196, 152, 137, 125, + 134, 125, 139, 128, 133, 125, 141, 134, 134, 135, + 134, 135, 134, 135, 131, 130, 136, 133, 110, 106, + 142, 144, 153, 162, 131, 129, 134, 132, 131, 130, + 126, 125, 132, 130, 168, 153, 126, 124, 130, 126, + 140, 135, 140, 134, 138, 133, 145, 137, 135, 134, + 130, 130, 132, 131, 133, 132, 129, 129, 125, 128, + 128, 130, 133, 139, 143, 152, 193, 215, 152, 160, + 130, 131, 129, 131, 130, 131, 135, 136, 136, 141, + 83, 81, 121, 120, 136, 130, 150, 145, 147, 145, + 134, 133, 135, 133, 146, 142, 135, 131, 127, 128, + 134, 135, 93, 102, 126, 132, 131, 133, 127, 129, + 124, 125, 120, 122, 103, 106, 128, 129, 139, 138, + 127, 128, 134, 134, 143, 138, 139, 134, 135, 133, + 131, 130, 133, 131, 139, 134, 138, 136, 166, 156, + 119, 116, 121, 122, 126, 124, 116, 117, 123, 124, + 131, 131, 129, 129, 130, 128, 141, 138, 135, 132, + 154, 145, 137, 129, 131, 125, 146, 137, 138, 135, + 131, 131, 131, 132, 129, 130, 134, 138, 111, 116, + 113, 118, 123, 125, 122, 124, 143, 147, 138, 140, + 116, 113, 114, 112, 130, 126, 117, 115, 127, 126, + 139, 137, 141, 139, 131, 132, 143, 144, 139, 140, + 130, 130, 129, 128, 136, 134, 119, 117, 152, 143, + 155, 143, 120, 119, 142, 139, 124, 130, 126, 128, + 112, 110, 112, 109, 136, 132, 125, 118, 121, 115, + 103, 101, 109, 100, 125, 120, 121, 117, 122, 121, + 128, 128, 127, 127, 124, 124, 128, 127, 131, 129, + 142, 138, 147, 141, 115, 108, 113, 109, 122, 119, + 136, 133, 150, 139, 142, 131, 119, 111, 151, 137, + 121, 116, 146, 134, 137, 129, 121, 123, 127, 129, + 130, 130, 130, 130, 136, 137, 126, 126, 136, 136, + 133, 133, 139, 139, 142, 143, 119, 120, 134, 134, + 132, 132, 133, 133, 135, 138, 129, 131, 133, 134, + 135, 138, 126, 130, 117, 118, 131, 132, 135, 135, + 129, 129, 128, 128, 126, 129, 127, 129, 123, 125, + 115, 117, 156, 157, 127, 131, 129, 129, 128, 129, + 129, 130, 131, 131, 126, 127, 135, 134, 136, 135, + 140, 136, 117, 113, 132, 128, 104, 97, 109, 106, + 131, 131, 131, 131, 121, 123, 124, 125, 126, 127, + 127, 127, 135, 135, 128, 128, 130, 130, 141, 140, + 129, 129, 129, 129, 129, 127, 127, 125, 149, 146, + 125, 123, 134, 133, 134, 132, 152, 150, 138, 138, + 128, 128, 126, 125, 132, 133, 141, 143, 136, 136, + 126, 127, 126, 127, 129, 131, 128, 129, 135, 134, + 176, 139, 192, 135, 145, 122, 149, 117, 155, 134, + 169, 133, 157, 139, 142, 136, 151, 152, 142, 147, + 166, 174, 103, 107, 141, 134, 140, 136, 144, 135, + 147, 135, 156, 131, 153, 127, 133, 126, 130, 124, + 127, 130, 123, 124, 114, 105, 195, 193, 156, 157, + 165, 158, 126, 122, 149, 141, 174, 173, 152, 147, + 136, 139, 131, 138, 163, 169, 103, 124, 80, 102, + 153, 186, 121, 151, 134, 161, 156, 190, 141, 151, + 121, 123, 124, 127, 119, 127, 133, 134, 157, 156, + 81, 69, 136, 134, 160, 169, 118, 114, 135, 128, + 114, 116, 97, 97, 117, 122, 152, 161, 115, 121, + 106, 122, 135, 137, 111, 113, 125, 135, 141, 145, + 143, 146, 143, 150, 132, 136, 142, 150, 151, 167, + 101, 107, 155, 173, 112, 124, 105, 100, 128, 126, + 127, 130, 133, 134, 142, 121, 131, 116, 176, 145, + 161, 120, 209, 150, 196, 133, 147, 115, 149, 130, + 144, 145, 144, 145, 120, 119, 163, 160, 117, 118, + 123, 117, 154, 119, 193, 98, 149, 101, 137, 116, + 133, 135, 140, 143, 144, 156, 131, 146, 186, 201, + 140, 139, 123, 125, 158, 169, 157, 166, 142, 143, + 130, 131, 132, 132, 128, 128, 141, 142, 147, 149, + 145, 148, 137, 139, 129, 129, 107, 108, 157, 157, + 120, 121, 119, 119, 140, 132, 137, 131, 118, 113, + 143, 136, 134, 135, 164, 158, 133, 125, 127, 124, + 148, 122, 197, 130, 173, 145, 110, 139, 123, 165, + 83, 158, 90, 167, 93, 142, 136, 169, 134, 152, + 130, 126, 154, 138, 227, 150, 156, 114, 147, 114, + 142, 109, 135, 110, 166, 135, 176, 150, 152, 142, + 132, 132, 136, 136, 130, 135, 143, 152, 136, 144, + 152, 160, 177, 185, 112, 112, 165, 166, 160, 161, + 145, 145, 138, 139, 116, 118, 127, 131, 66, 80, + 132, 142, 119, 127, 101, 108, 120, 130, 126, 130, + 135, 135, 142, 139, 153, 137, 55, 30, 142, 139, + 139, 143, 135, 133, 129, 133, 109, 108, 129, 129, + 136, 135, 134, 131, 129, 132, 132, 134, 135, 149, + 79, 206, 123, 137, 135, 143, 130, 140, 131, 134, + 100, 99, 165, 164, 142, 123, 148, 133, 133, 122, + 142, 133, 138, 125, 119, 111, 129, 123, 137, 130, + 131, 132, 123, 129, 174, 185, 196, 181, 127, 111, + 156, 141, 132, 114, 129, 106, 132, 107, 126, 117, + 134, 140, 131, 136, 119, 146, 92, 246, 128, 132, + 125, 129, 132, 140, 128, 141, 126, 145, 137, 142, + 130, 130, 110, 115, 124, 139, 127, 151, 118, 152, + 98, 146, 36, 108, 126, 158, 112, 146, 112, 130, + 138, 136, 145, 138, 153, 145, 116, 125, 90, 103, + 137, 138, 189, 185, 141, 151, 86, 93, 111, 111, + 133, 171, 125, 209, 140, 132, 130, 134, 129, 101, + 142, 120, 142, 132, 135, 126, 141, 140, 140, 134, + 128, 123, 131, 123, 138, 118, 163, 133, 240, 197, + 176, 151, 126, 123, 81, 94, 109, 118, 124, 133, + 135, 133, 137, 134, 154, 135, 140, 155, 69, 190, + 119, 149, 141, 151, 142, 123, 135, 125, 129, 130, + 127, 125, 132, 127, 107, 80, 123, 103, 145, 131, + 133, 107, 140, 103, 135, 106, 170, 145, 159, 143, + 136, 137, 127, 130, 105, 119, 129, 134, 141, 151, + 116, 127, 119, 140, 75, 119, 152, 162, 149, 152, + 72, 138, 9, 143, 118, 160, 126, 134, 141, 147, + 135, 131, 129, 129, 135, 129, 136, 126, 133, 125, + 137, 135, 146, 141, 145, 139, 141, 140, 133, 130, + 213, 208, 139, 130, 139, 136, 117, 117, 126, 125, + 133, 130, 138, 131, 141, 100, 145, 93, 159, 121, + 144, 132, 117, 160, 102, 187, 99, 162, 117, 144, + 132, 132, 134, 134, 140, 141, 127, 126, 128, 131, + 116, 116, 121, 127, 119, 126, 114, 114, 99, 100, + 141, 144, 148, 159, 179, 224, 95, 131, 100, 125, + 87, 110, 112, 132, 134, 147, 111, 125, 122, 122, + 137, 140, 141, 129, 169, 12, 144, 132, 133, 144, + 141, 146, 137, 147, 136, 122, 133, 130, 131, 128, + 141, 142, 128, 139, 15, 69, 160, 159, 142, 130, + 137, 126, 159, 141, 145, 143, 128, 125, 134, 128, + 131, 130, 127, 127, 114, 104, 119, 98, 83, 68, + 139, 120, 173, 142, 199, 154, 191, 153, 158, 145, + 128, 130, 127, 127, 148, 150, 110, 99, 119, 109, + 120, 113, 163, 154, 110, 90, 138, 129, 149, 144, + 131, 134, 124, 142, 76, 217, 130, 129, 140, 138, + 133, 135, 145, 150, 136, 138, 127, 130, 130, 134, + 144, 119, 178, 70, 143, 130, 115, 136, 139, 138, + 129, 109, 136, 116, 147, 122, 126, 112, 126, 123, + 132, 139, 128, 144, 107, 156, 75, 163, 120, 164, + 151, 136, 151, 99, 160, 112, 159, 126, 143, 126, + 140, 138, 137, 135, 152, 108, 251, 85, 138, 116, + 137, 118, 141, 119, 136, 121, 150, 134, 138, 131, + 137, 137, 143, 144, 150, 153, 148, 154, 152, 151, + 117, 104, 124, 96, 93, 67, 146, 138, 149, 148, + 149, 153, 172, 193, 108, 114, 125, 128, 145, 165, + 149, 160, 121, 130, 115, 120, 110, 112, 121, 118, + 145, 146, 141, 142, 127, 127, 103, 95, 138, 143, + 114, 126, 109, 115, 143, 136, 153, 149, 144, 142, + 140, 138, 150, 144, 128, 116, 142, 136, 135, 122, + 93, 88, 164, 163, 141, 142, 171, 182, 154, 160, + 124, 125, 122, 123, 158, 155, 111, 97, 138, 130, + 157, 134, 101, 65, 129, 118, 121, 114, 124, 119, + 131, 133, 125, 129, 136, 147, 135, 152, 131, 133, + 110, 115, 118, 114, 161, 159, 233, 218, 172, 166, + 140, 107, 125, 0, 140, 103, 140, 115, 125, 113, + 132, 135, 128, 133, 138, 146, 131, 145, 127, 133, + 131, 131, 122, 122, 135, 132, 126, 124, 132, 133, + 164, 167, 121, 127, 117, 120, 167, 162, 145, 143, + 135, 134, 136, 134, 156, 146, 195, 177, 127, 139, + 108, 140, 141, 173, 141, 178, 131, 155, 129, 141, + 134, 134, 119, 114, 184, 184, 127, 126, 147, 151, + 130, 140, 146, 159, 134, 145, 131, 136, 137, 142, + 135, 137, 128, 136, 83, 108, 97, 98, 152, 119, + 207, 144, 142, 121, 144, 129, 131, 127, 130, 132, + 124, 125, 108, 107, 94, 116, 81, 114, 139, 173, + 131, 158, 145, 177, 141, 163, 136, 140, 143, 144, + 135, 141, 132, 136, 134, 142, 142, 136, 173, 50, + 143, 106, 142, 127, 134, 139, 127, 133, 125, 125, + 129, 130, 131, 133, 132, 148, 110, 138, 113, 135, + 138, 175, 108, 151, 55, 119, 51, 100, 93, 116, + 121, 121, 146, 151, 99, 120, 127, 137, 107, 122, + 125, 139, 110, 132, 135, 156, 141, 156, 148, 157, + 137, 137, 141, 140, 139, 137, 130, 128, 138, 136, + 132, 134, 115, 110, 177, 179, 81, 86, 100, 98, + 84, 83, 121, 121, 148, 157, 127, 133, 146, 156, + 127, 136, 143, 151, 135, 139, 138, 142, 136, 136, + 201, 164, 151, 129, 123, 136, 147, 148, 127, 142, + 128, 143, 101, 126, 119, 133, 114, 131, 116, 126, + 132, 133, 140, 140, 126, 125, 156, 153, 142, 129, + 140, 130, 77, 69, 134, 132, 146, 148, 135, 136, + 133, 132, 123, 116, 116, 103, 150, 135, 144, 127, + 130, 117, 136, 122, 122, 106, 48, 38, 81, 78, + 145, 146, 135, 136, 123, 122, 126, 133, 133, 138, + 145, 145, 144, 150, 160, 181, 142, 139, 150, 150, + 136, 136, 139, 139, 133, 133, 139, 135, 134, 129, + 140, 137, 153, 145, 132, 131, 151, 144, 68, 66, + 137, 137, 139, 139, 146, 146, 142, 139, 129, 128, + 131, 129, 133, 132, 135, 134, 135, 134, 201, 200, + 137, 136, 146, 143, 155, 153, 157, 158, 131, 138, + 140, 139, 143, 144, 128, 123, 216, 192, 159, 150, + 137, 138, 136, 142, 145, 148, 126, 162, 140, 170, + 186, 95, 131, 140, 143, 148, 133, 128, 130, 133, + 141, 139, 153, 150, 122, 122, 134, 144, 124, 130, + 159, 166, 133, 139, 151, 150, 138, 139, 131, 134, + 121, 121, 131, 129, 148, 180, 121, 135, 118, 131, + 124, 148, 119, 119, 129, 126, 150, 156, 155, 160, + 40, 154, 115, 157, 133, 129, 140, 133, 143, 133, + 143, 132, 144, 130, 141, 131, 134, 130, 137, 133, + 134, 136, 141, 140, 145, 137, 152, 124, 183, 91, + 118, 154, 123, 158, 136, 134, 140, 142, 138, 142, + 138, 135, 131, 131, 138, 129, 121, 128, 146, 219, + 124, 123, 125, 135, 120, 126, 127, 141, 133, 136, + 127, 124, 120, 107, 152, 125, 149, 108, 158, 144, + 196, 185, 174, 164, 151, 149, 138, 131, 140, 137, + 149, 148, 144, 145, 143, 145, 140, 143, 141, 147, + 112, 125, 113, 113, 149, 155, 143, 149, 146, 151, + 138, 138, 141, 138, 144, 129, 134, 125, 143, 140, + 153, 154, 142, 123, 162, 42, 154, 106, 153, 130, + 153, 153, 137, 137, 144, 144, 142, 140, 165, 151, + 161, 140, 144, 134, 156, 124, 167, 143, 166, 155, + 132, 132, 137, 138, 137, 132, 124, 127, 140, 144, + 134, 140, 162, 180, 127, 131, 152, 169, 145, 156, + 133, 134, 131, 133, 130, 132, 147, 149, 125, 117, + 127, 118, 159, 155, 147, 142, 122, 117, 145, 144, + 138, 137, 130, 133, 113, 149, 168, 224, 166, 201, + 129, 151, 147, 154, 136, 135, 140, 136, 152, 141, + 120, 112, 140, 127, 161, 100, 132, 115, 118, 125, + 115, 133, 115, 157, 144, 146, 114, 135, 127, 139, + 138, 141, 135, 135, 137, 136, 147, 142, 143, 144, + 139, 152, 142, 136, 147, 143, 177, 39, 125, 71, + 147, 143, 66, 88, 132, 158, 123, 126, 116, 135, + 119, 124, 128, 135, 133, 140, 137, 126, 137, 130, + 155, 38, 149, 103, 130, 135, 139, 143, 127, 137, + 135, 141, 138, 148, 131, 148, 136, 147, 132, 139, + 136, 140, 115, 129, 115, 151, 136, 160, 87, 131, + 157, 176, 150, 164, 140, 141, 135, 119, 137, 133, + 141, 140, 140, 139, 134, 134, 142, 144, 131, 132, + 131, 134, 131, 132, 116, 114, 129, 133, 205, 207, + 130, 133, 160, 170, 137, 127, 124, 112, 158, 146, + 155, 137, 134, 136, 137, 142, 177, 184, 149, 152, + 135, 134, 133, 132, 135, 129, 144, 136, 139, 134, + 161, 155, 126, 109, 215, 186, 177, 153, 160, 149, + 139, 139, 136, 140, 140, 142, 186, 71, 129, 144, + 131, 165, 142, 152, 140, 151, 141, 143, 137, 139, + 144, 138, 150, 135, 133, 126, 136, 143, 99, 152, + 139, 131, 190, 118, 122, 147, 134, 155, 136, 143, + 138, 135, 137, 132, 147, 144, 150, 144, 138, 134, + 129, 133, 130, 138, 56, 175, 129, 166, 147, 165, + 140, 138, 144, 137, 141, 133, 150, 139, 129, 135, + 40, 83, 126, 130, 110, 120, 100, 110, 126, 128, + 141, 142, 217, 175, 172, 151, 146, 153, 125, 132, + 128, 137, 141, 141, 145, 145, 140, 133, 132, 131, + 129, 144, 128, 177, 133, 195, 147, 120, 138, 131, + 161, 114, 166, 134, 162, 118, 161, 115, 155, 129, + 137, 136, 141, 129, 141, 132, 55, 168, 121, 126, + 136, 139, 120, 133, 149, 147, 132, 141, 131, 136, + 147, 150, 151, 132, 101, 31, 117, 101, 129, 132, + 122, 138, 128, 137, 140, 170, 131, 143, 131, 134, + 149, 192, 122, 158, 136, 146, 133, 166, 143, 141, + 141, 136, 141, 129, 125, 155, 140, 138, 137, 131, + 111, 112, 131, 132, 120, 127, 149, 148, 151, 141, + 156, 148, 133, 129, 127, 124, 144, 137, 142, 139, + 134, 133, 141, 138, 133, 135, 124, 96, 226, 152, + 116, 108, 128, 105, 155, 130, 153, 138, 144, 139, + 142, 141, 137, 135, 142, 143, 156, 162, 136, 89, + 188, 145, 181, 152, 138, 146, 146, 154, 145, 149, + 152, 133, 158, 133, 42, 153, 117, 144, 149, 139, + 125, 139, 134, 128, 150, 128, 143, 125, 135, 132, + 143, 141, 143, 141, 164, 173, 141, 142, 156, 155, + 154, 154, 169, 170, 77, 80, 112, 105, 135, 134, + 126, 143, 120, 172, 111, 144, 120, 154, 107, 153, + 95, 134, 104, 134, 128, 116, 163, 131, 151, 136, + 135, 133, 142, 143, 152, 204, 149, 112, 156, 128, + 150, 126, 127, 129, 139, 175, 143, 141, 138, 135, + 168, 148, 152, 105, 164, 121, 134, 122, 119, 109, + 122, 148, 136, 143, 153, 132, 158, 148, 149, 150, + 133, 131, 142, 141, 150, 149, 156, 173, 138, 155, + 129, 144, 111, 107, 130, 129, 96, 89, 106, 104, + 135, 135, 144, 146, 131, 153, 134, 154, 146, 166, + 117, 138, 163, 187, 190, 216, 149, 156, 149, 152, + 142, 142, 153, 154, 109, 145, 40, 102, 116, 126, + 137, 139, 149, 157, 108, 124, 139, 146, 142, 147, + 130, 126, 120, 111, 172, 146, 169, 136, 150, 135, + 126, 96, 159, 143, 150, 122, 162, 129, 156, 142, + 135, 142, 144, 138, 222, 109, 137, 145, 144, 142, + 141, 143, 138, 136, 124, 150, 133, 144, 137, 145, + 141, 144, 139, 144, 134, 154, 114, 136, 145, 173, + 151, 215, 110, 115, 127, 134, 145, 150, 145, 144, + 144, 142, 139, 131, 147, 132, 141, 119, 143, 106, + 165, 41, 147, 129, 129, 144, 138, 135, 138, 140, + 128, 150, 89, 163, 154, 115, 141, 127, 132, 145, + 135, 157, 143, 145, 140, 141, 127, 135, 127, 129, + 142, 147, 116, 147, 104, 162, 153, 143, 146, 130, + 144, 110, 133, 123, 130, 137, 118, 198, 126, 152, + 154, 146, 139, 127, 147, 112, 207, 151, 156, 136, + 162, 137, 108, 121, 130, 135, 125, 131, 131, 134, + 134, 134, 141, 144, 107, 143, 137, 144, 124, 136, + 115, 147, 130, 157, 119, 167, 71, 144, 97, 128, + 134, 138, 132, 133, 138, 138, 146, 146, 147, 131, + 141, 138, 185, 65, 145, 123, 139, 130, 142, 128, + 139, 136, 157, 147, 124, 119, 164, 148, 170, 154, + 133, 130, 157, 148, 140, 141, 130, 135, 134, 137, + 136, 137, 143, 144, 144, 144, 178, 186, 71, 73, + 120, 118, 127, 124, 152, 151, 155, 146, 141, 138, + 142, 143, 139, 143, 133, 134, 139, 140, 138, 135, + 146, 141, 78, 198, 129, 139, 141, 141, 134, 141, + 137, 136, 120, 120, 124, 118, 143, 148, 148, 152, + 131, 143, 129, 137, 152, 158, 157, 160, 175, 178, + 137, 139, 131, 133, 146, 152, 121, 147, 142, 143, + 129, 136, 149, 145, 197, 114, 103, 141, 124, 140, + 141, 140, 129, 129, 127, 130, 131, 124, 123, 117, + 150, 139, 120, 109, 119, 120, 163, 163, 117, 121, + 139, 139, 136, 136, 94, 74, 150, 145, 126, 127, + 147, 150, 158, 162, 84, 74, 136, 129, 140, 132, + 136, 135, 146, 145, 124, 116, 129, 120, 130, 129, + 130, 109, 122, 111, 160, 141, 135, 113, 131, 121, + 136, 135, 135, 135, 147, 147, 140, 140, 144, 145, + 139, 142, 131, 137, 145, 145, 143, 153, 48, 49, + 145, 143, 151, 147, 158, 146, 135, 124, 124, 116, + 159, 140, 131, 126, 123, 120, 103, 117, 113, 119, + 148, 146, 128, 124, 123, 126, 123, 120, 158, 141, + 148, 137, 146, 143, 125, 143, 89, 107, 116, 123, + 149, 147, 141, 139, 149, 153, 118, 121, 139, 138, + 105, 119, 168, 147, 139, 141, 143, 138, 133, 130, + 126, 126, 143, 142, 146, 144, 124, 123, 143, 145, + 149, 148, 147, 141, 151, 143, 118, 113, 175, 171 +}; + +static const uint8_t wmavoice_dq_lsp16r1[0x500] = { + 147, 145, 193, 168, 188, 156, 141, 145, 141, 139, + 148, 149, 148, 149, 153, 157, 144, 144, 152, 152, + 141, 145, 153, 143, 243, 134, 151, 133, 166, 135, + 150, 149, 135, 132, 32, 39, 110, 111, 109, 114, + 126, 127, 147, 146, 177, 169, 162, 156, 210, 187, + 141, 147, 95, 150, 127, 155, 108, 133, 139, 148, + 138, 138, 140, 140, 147, 146, 134, 130, 136, 134, + 147, 146, 142, 150, 62, 174, 126, 151, 122, 156, + 154, 156, 179, 184, 115, 107, 105, 99, 127, 124, + 146, 131, 140, 44, 132, 125, 156, 146, 153, 153, + 136, 137, 145, 144, 141, 139, 158, 152, 138, 132, + 145, 145, 147, 145, 146, 141, 144, 140, 110, 97, + 140, 141, 143, 142, 130, 123, 127, 117, 126, 120, + 147, 146, 161, 155, 169, 135, 122, 117, 166, 155, + 144, 144, 142, 142, 125, 122, 137, 128, 194, 172, + 127, 85, 148, 143, 153, 141, 147, 147, 140, 143, + 118, 140, 0, 69, 51, 60, 111, 123, 137, 135, + 146, 146, 164, 165, 207, 214, 145, 143, 149, 147, + 178, 168, 197, 170, 134, 154, 148, 159, 115, 140, + 103, 118, 13, 38, 139, 138, 135, 138, 140, 141, + 144, 144, 140, 140, 150, 150, 156, 157, 164, 171, + 143, 143, 140, 142, 118, 120, 172, 172, 160, 163, + 146, 147, 150, 151, 176, 176, 230, 237, 153, 153, + 168, 156, 173, 149, 164, 148, 162, 146, 178, 158, + 147, 145, 143, 145, 111, 126, 111, 130, 89, 118, + 153, 158, 122, 120, 142, 125, 124, 105, 148, 138, + 145, 144, 156, 151, 193, 154, 146, 147, 119, 135, + 142, 141, 145, 145, 152, 147, 142, 141, 146, 146, + 139, 138, 154, 154, 148, 150, 147, 149, 144, 145, + 134, 134, 141, 140, 135, 134, 145, 147, 160, 163, + 144, 145, 149, 146, 115, 67, 127, 119, 141, 135, + 145, 141, 130, 124, 143, 144, 151, 165, 141, 144, + 154, 152, 160, 136, 115, 82, 64, 71, 64, 65, + 143, 143, 151, 149, 240, 251, 165, 173, 173, 179, + 148, 134, 156, 55, 160, 105, 133, 91, 129, 96, + 149, 149, 145, 144, 160, 154, 171, 159, 140, 142, + 154, 163, 178, 244, 147, 140, 153, 150, 137, 121, + 145, 144, 145, 146, 138, 139, 149, 152, 189, 198, + 148, 148, 156, 158, 168, 182, 165, 182, 172, 201, + 143, 142, 99, 92, 152, 152, 143, 143, 127, 127, + 165, 148, 173, 124, 113, 122, 134, 142, 127, 142, + 124, 126, 137, 137, 131, 132, 144, 142, 141, 138, + 172, 176, 138, 111, 152, 136, 167, 154, 156, 137, + 140, 150, 78, 145, 158, 157, 161, 154, 155, 147, + 153, 164, 156, 191, 129, 109, 153, 146, 153, 141, + 138, 137, 141, 138, 115, 94, 144, 141, 155, 147, + 144, 142, 144, 137, 168, 113, 141, 134, 145, 137, + 146, 144, 150, 148, 140, 155, 103, 178, 137, 149, + 145, 147, 148, 153, 175, 201, 138, 146, 110, 108, + 143, 146, 124, 134, 124, 127, 164, 158, 127, 135, + 145, 146, 150, 150, 145, 147, 95, 80, 150, 151, + 149, 149, 162, 162, 144, 152, 170, 169, 145, 154, + 145, 149, 143, 146, 142, 145, 152, 146, 160, 98, + 141, 141, 153, 153, 140, 137, 131, 131, 145, 146, + 133, 132, 127, 124, 158, 150, 173, 164, 178, 167, + 146, 146, 154, 155, 117, 127, 143, 147, 147, 156, + 142, 143, 144, 145, 146, 152, 170, 199, 151, 165, + 146, 147, 139, 140, 147, 149, 132, 134, 147, 149, + 138, 139, 142, 143, 162, 188, 145, 149, 160, 164, + 150, 150, 139, 139, 143, 142, 146, 146, 137, 138, + 142, 142, 141, 140, 152, 153, 164, 171, 110, 112, + 139, 139, 143, 143, 138, 138, 142, 142, 143, 143, + 137, 140, 142, 142, 145, 141, 149, 141, 182, 135, + 146, 146, 150, 150, 144, 145, 150, 151, 135, 137, + 137, 145, 51, 62, 68, 54, 69, 57, 62, 41, + 137, 139, 139, 144, 135, 150, 225, 232, 208, 197, + 136, 135, 141, 143, 145, 150, 160, 169, 213, 247, + 142, 137, 72, 54, 110, 107, 105, 107, 127, 130, + 145, 143, 169, 155, 219, 174, 195, 164, 183, 157, + 155, 157, 239, 232, 169, 164, 170, 172, 156, 159, + 142, 143, 136, 144, 59, 100, 139, 142, 130, 138, + 147, 146, 150, 161, 128, 235, 143, 155, 146, 167, + 154, 149, 128, 151, 42, 149, 55, 136, 59, 127, + 128, 126, 74, 92, 143, 153, 140, 150, 166, 176, + 146, 152, 150, 145, 140, 100, 140, 105, 124, 59, + 195, 191, 146, 148, 144, 136, 136, 133, 129, 122, + 133, 148, 40, 147, 102, 140, 123, 148, 118, 136, + 143, 143, 150, 148, 184, 153, 160, 147, 166, 149, + 58, 68, 127, 135, 141, 145, 143, 147, 150, 151, + 140, 143, 137, 137, 120, 114, 71, 65, 125, 123, + 153, 148, 215, 159, 136, 135, 150, 146, 150, 150, + 148, 138, 166, 94, 150, 145, 145, 139, 147, 145, + 146, 147, 150, 139, 171, 63, 158, 142, 153, 133, + 147, 148, 143, 143, 76, 72, 155, 159, 164, 176, + 149, 149, 173, 195, 145, 165, 138, 144, 150, 167, + 180, 169, 146, 151, 146, 166, 147, 166, 149, 171, + 157, 156, 168, 166, 147, 149, 121, 122, 116, 124, + 145, 145, 147, 148, 172, 189, 168, 180, 144, 146, + 139, 145, 141, 150, 115, 172, 141, 146, 143, 148, + 145, 145, 142, 143, 145, 147, 138, 143, 58, 73, + 141, 142, 146, 145, 163, 149, 218, 161, 147, 132, + 152, 147, 146, 147, 140, 150, 141, 152, 89, 150, + 78, 134, 135, 137, 139, 142, 140, 137, 137, 130, + 144, 144, 152, 151, 145, 140, 181, 170, 191, 168, + 164, 166, 136, 148, 112, 124, 139, 144, 146, 149, + 142, 151, 113, 182, 137, 150, 143, 156, 138, 147, + 154, 156, 108, 102, 118, 119, 133, 139, 113, 111, + 145, 144, 150, 147, 175, 151, 104, 106, 116, 114, + 143, 144, 151, 157, 151, 191, 135, 113, 138, 123, + 146, 146, 155, 157, 106, 145, 132, 127, 140, 125, + 161, 165, 146, 150, 151, 154, 139, 140, 142, 143, + 144, 148, 145, 149, 147, 138, 168, 104, 146, 136, + 138, 140, 91, 108, 111, 110, 145, 140, 158, 154, + 130, 112, 122, 118, 136, 135, 119, 118, 141, 140, + 147, 146, 146, 145, 138, 138, 182, 188, 132, 132, + 144, 144, 156, 155, 168, 172, 123, 128, 144, 151, + 142, 140, 145, 145, 137, 144, 141, 152, 128, 188, + 149, 149, 160, 161, 160, 160, 166, 163, 130, 107, + 143, 143, 142, 142, 149, 149, 132, 132, 170, 174, + 148, 148, 154, 153, 118, 111, 157, 155, 114, 109, + 140, 139, 138, 137, 205, 187, 137, 133, 147, 144, + 144, 145, 147, 149, 105, 125, 108, 117, 155, 162, + 146, 146, 162, 157, 144, 122, 154, 143, 161, 139, + 141, 142, 130, 131, 144, 144, 142, 141, 144, 142, + 132, 132, 141, 141, 150, 151, 139, 141, 151, 153, + 142, 142, 154, 154, 150, 150, 148, 148, 166, 165, + 143, 142, 144, 144, 132, 132, 142, 144, 130, 128, + 142, 142, 143, 143, 153, 153, 147, 142, 129, 125, + 142, 141, 143, 142, 143, 147, 105, 122, 135, 140, + 141, 140, 140, 140, 151, 151, 156, 155, 146, 146, + 133, 134, 140, 142, 142, 145, 141, 146, 112, 133, + 142, 142, 145, 145, 137, 138, 155, 157, 149, 150, + 144, 144, 139, 138, 130, 128, 132, 131, 147, 147, + 139, 140, 142, 143, 115, 121, 141, 143, 137, 141, + 146, 146, 150, 150, 145, 144, 133, 133, 133, 135, + 143, 144, 144, 144, 166, 167, 139, 142, 139, 140, + 150, 149, 138, 138, 142, 140, 148, 147, 160, 155, + 146, 146, 147, 147, 138, 137, 143, 142, 151, 150 +}; + +static const uint8_t wmavoice_dq_lsp16r2[0x500] = { + 98, 98, 119, 121, 109, 112, 128, 135, 115, 121, + 159, 113, 113, 106, 127, 114, 101, 102, 105, 111, + 161, 162, 137, 138, 161, 159, 152, 150, 150, 148, + 128, 79, 131, 102, 142, 120, 133, 119, 130, 117, + 121, 115, 142, 133, 186, 155, 179, 144, 169, 135, + 107, 103, 106, 106, 122, 122, 111, 112, 112, 115, + 127, 123, 118, 115, 128, 125, 123, 119, 115, 109, + 124, 130, 117, 126, 121, 133, 84, 144, 99, 114, + 122, 125, 123, 131, 124, 135, 176, 200, 158, 176, + 68, 74, 86, 87, 117, 115, 119, 116, 135, 128, + 115, 116, 102, 104, 119, 123, 133, 148, 102, 109, + 71, 121, 106, 117, 107, 127, 106, 122, 100, 110, + 117, 115, 129, 128, 87, 84, 116, 116, 151, 157, + 116, 128, 110, 117, 119, 134, 100, 114, 120, 129, + 142, 141, 146, 151, 94, 91, 114, 114, 118, 118, + 114, 112, 112, 109, 115, 112, 123, 123, 147, 148, + 110, 164, 106, 152, 110, 158, 106, 151, 105, 135, + 85, 51, 71, 27, 71, 34, 74, 45, 85, 53, + 145, 134, 140, 130, 136, 134, 118, 122, 118, 126, + 117, 84, 121, 81, 106, 80, 109, 106, 121, 127, + 95, 94, 112, 110, 90, 94, 109, 107, 114, 109, + 117, 118, 118, 123, 107, 107, 86, 93, 29, 31, + 125, 112, 104, 60, 121, 111, 127, 116, 133, 130, + 118, 117, 148, 145, 122, 126, 124, 127, 90, 91, + 113, 110, 119, 118, 152, 147, 115, 112, 132, 131, + 129, 140, 98, 112, 73, 85, 109, 115, 122, 126, + 123, 122, 122, 122, 126, 125, 137, 140, 203, 210, + 164, 176, 114, 114, 125, 122, 119, 112, 125, 120, + 124, 122, 118, 115, 95, 96, 141, 144, 132, 131, + 127, 130, 132, 134, 116, 114, 122, 123, 137, 134, + 111, 111, 112, 116, 106, 118, 77, 101, 104, 115, + 111, 111, 125, 126, 118, 121, 113, 115, 113, 113, + 171, 170, 202, 199, 221, 206, 199, 184, 177, 167, + 73, 90, 61, 93, 43, 74, 51, 71, 51, 72, + 130, 130, 140, 137, 134, 132, 164, 160, 118, 111, + 123, 136, 133, 154, 130, 158, 106, 110, 110, 114, + 97, 97, 91, 94, 70, 69, 125, 123, 141, 140, + 119, 100, 116, 77, 111, 67, 105, 52, 95, 34, + 100, 122, 90, 124, 68, 120, 43, 117, 50, 112, + 130, 129, 192, 188, 123, 118, 124, 117, 121, 115, + 122, 111, 129, 111, 157, 85, 125, 109, 125, 119, + 143, 152, 119, 128, 114, 116, 129, 136, 148, 157, + 119, 117, 115, 115, 150, 148, 163, 154, 109, 102, + 120, 126, 73, 119, 106, 121, 102, 122, 96, 113, + 84, 83, 117, 115, 122, 117, 154, 143, 159, 142, + 118, 122, 114, 117, 115, 122, 114, 130, 99, 156, + 123, 120, 122, 116, 100, 81, 99, 91, 121, 112, + 139, 131, 164, 142, 132, 119, 145, 133, 157, 141, + 112, 109, 118, 116, 142, 134, 108, 110, 96, 99, + 111, 110, 113, 112, 111, 104, 98, 94, 131, 131, + 115, 114, 121, 118, 120, 115, 173, 148, 123, 117, + 121, 124, 122, 124, 140, 146, 78, 82, 96, 93, + 86, 90, 124, 125, 121, 123, 105, 106, 134, 135, + 107, 109, 132, 141, 100, 95, 113, 114, 102, 105, + 113, 130, 98, 145, 116, 115, 124, 117, 115, 105, + 120, 123, 89, 87, 109, 108, 102, 101, 117, 117, + 113, 122, 132, 138, 77, 116, 86, 99, 118, 126, + 123, 120, 117, 111, 124, 119, 129, 118, 63, 58, + 141, 135, 108, 106, 109, 111, 108, 110, 135, 138, + 117, 114, 134, 127, 139, 129, 138, 130, 126, 122, + 121, 118, 124, 121, 133, 130, 98, 85, 130, 123, + 147, 129, 118, 112, 148, 130, 136, 123, 148, 131, + 113, 112, 123, 118, 123, 115, 147, 95, 117, 110, + 118, 119, 112, 113, 112, 113, 119, 119, 120, 120, + 158, 133, 198, 145, 188, 129, 197, 137, 195, 133, + 132, 140, 140, 139, 158, 156, 223, 217, 233, 233, + 48, 56, 34, 37, 82, 84, 102, 102, 108, 110, + 120, 142, 136, 169, 146, 195, 136, 186, 140, 182, + 196, 186, 158, 155, 142, 134, 132, 125, 120, 119, + 97, 105, 72, 75, 82, 85, 81, 84, 107, 109, + 67, 121, 43, 119, 69, 124, 87, 129, 88, 128, + 53, 57, 93, 98, 91, 94, 93, 98, 104, 104, + 124, 123, 133, 133, 182, 181, 119, 121, 114, 116, + 128, 105, 134, 112, 131, 72, 119, 59, 111, 84, + 132, 142, 145, 180, 124, 132, 131, 143, 122, 134, + 88, 85, 103, 103, 136, 140, 131, 143, 114, 132, + 116, 57, 113, 57, 121, 76, 126, 80, 118, 86, + 127, 112, 127, 97, 131, 100, 149, 91, 163, 86, + 122, 119, 128, 121, 128, 116, 142, 127, 173, 139, + 162, 116, 166, 107, 149, 103, 152, 107, 141, 108, + 114, 113, 118, 116, 56, 43, 90, 90, 105, 105, + 132, 134, 110, 107, 106, 105, 82, 84, 84, 84, + 102, 106, 79, 89, 99, 99, 127, 129, 114, 118, + 139, 157, 116, 123, 116, 123, 87, 89, 110, 113, + 119, 126, 97, 97, 155, 163, 142, 153, 143, 146, + 117, 114, 66, 67, 125, 126, 127, 128, 114, 113, + 111, 114, 127, 133, 123, 132, 143, 162, 133, 148, + 105, 108, 114, 114, 110, 109, 57, 48, 109, 106, + 113, 130, 104, 131, 88, 139, 102, 169, 100, 172, + 129, 114, 150, 97, 114, 112, 117, 119, 109, 116, + 92, 107, 96, 116, 90, 125, 101, 122, 125, 140, + 125, 133, 122, 129, 136, 153, 125, 135, 131, 139, + 84, 71, 129, 123, 135, 120, 114, 103, 112, 101, + 108, 121, 115, 156, 106, 123, 116, 131, 127, 139, + 137, 147, 109, 117, 119, 126, 135, 144, 117, 119, + 120, 127, 76, 105, 111, 116, 120, 125, 141, 138, + 107, 104, 162, 155, 135, 130, 127, 123, 127, 121, + 102, 104, 84, 87, 112, 115, 97, 102, 78, 82, + 119, 118, 120, 123, 91, 105, 114, 119, 119, 126, + 130, 126, 134, 126, 158, 134, 133, 99, 116, 100, + 125, 122, 145, 143, 126, 117, 98, 96, 121, 120, + 152, 148, 131, 126, 130, 129, 126, 119, 87, 87, + 131, 131, 139, 137, 101, 102, 104, 105, 86, 83, + 92, 89, 111, 105, 121, 115, 137, 124, 96, 84, + 100, 96, 122, 119, 107, 108, 93, 96, 79, 82, + 128, 123, 108, 106, 123, 120, 150, 150, 143, 140, + 121, 120, 97, 99, 79, 80, 116, 116, 88, 90, + 128, 131, 101, 97, 140, 140, 117, 116, 116, 118, + 137, 135, 100, 91, 115, 112, 134, 121, 107, 99, + 120, 122, 122, 125, 124, 126, 136, 141, 89, 95, + 103, 119, 103, 116, 122, 139, 125, 137, 152, 170, + 121, 122, 124, 124, 98, 97, 137, 140, 96, 92, + 115, 113, 136, 136, 128, 132, 122, 124, 151, 158, + 100, 107, 121, 131, 131, 158, 119, 130, 113, 114, + 114, 109, 148, 130, 103, 95, 127, 116, 137, 120, + 103, 108, 97, 97, 133, 128, 113, 109, 136, 128, + 125, 124, 118, 118, 122, 121, 101, 99, 157, 152, + 138, 134, 124, 115, 113, 101, 123, 112, 124, 110, + 116, 113, 128, 121, 119, 110, 124, 113, 128, 67, + 114, 118, 114, 123, 109, 121, 102, 123, 56, 116, + 117, 111, 112, 99, 124, 114, 112, 79, 114, 88, + 112, 113, 115, 117, 126, 127, 130, 132, 123, 122, + 111, 104, 111, 102, 112, 102, 129, 118, 129, 115, + 123, 124, 130, 133, 114, 117, 125, 127, 112, 117, + 124, 125, 119, 120, 117, 116, 105, 104, 110, 110, + 125, 124, 118, 116, 124, 123, 124, 121, 133, 132, + 111, 111, 124, 124, 120, 119, 116, 116, 134, 130, + 114, 116, 112, 113, 109, 111, 116, 118, 95, 98 +}; + +static const uint8_t wmavoice_dq_lsp16r3[0x600] = { + 84, 82, 95, 94, 125, 131, 98, 102, 94, 93, 104, 104, + 127, 113, 87, 77, 125, 114, 109, 94, 94, 91, 106, 105, + 168, 125, 163, 120, 128, 100, 119, 99, 108, 97, 108, 106, + 86, 85, 128, 125, 79, 73, 103, 102, 123, 123, 116, 117, + 84, 76, 135, 131, 133, 133, 129, 130, 125, 123, 115, 114, + 94, 97, 79, 81, 115, 115, 94, 93, 128, 127, 126, 125, + 124, 111, 105, 114, 104, 117, 109, 110, 124, 125, 118, 117, + 107, 110, 106, 110, 93, 93, 149, 148, 118, 119, 111, 110, + 147, 157, 143, 156, 134, 136, 118, 121, 106, 107, 105, 105, + 114, 83, 114, 46, 106, 53, 110, 83, 107, 94, 105, 103, + 92, 90, 109, 106, 172, 160, 114, 110, 109, 110, 110, 109, + 90, 98, 98, 109, 102, 98, 97, 92, 100, 100, 101, 102, + 123, 117, 124, 98, 82, 80, 117, 115, 112, 110, 109, 108, + 107, 111, 100, 115, 105, 120, 104, 105, 83, 82, 95, 96, + 109, 120, 72, 71, 97, 104, 69, 74, 99, 102, 118, 117, + 137, 133, 142, 135, 105, 110, 121, 121, 125, 122, 114, 112, + 151, 186, 115, 132, 103, 111, 100, 104, 99, 101, 104, 105, + 18, 38, 56, 65, 76, 83, 85, 91, 101, 103, 108, 110, + 144, 135, 126, 121, 115, 113, 79, 80, 118, 117, 117, 117, + 117, 124, 115, 115, 126, 113, 130, 116, 112, 106, 108, 105, + 77, 76, 76, 80, 109, 109, 125, 129, 130, 133, 116, 118, + 96, 86, 109, 99, 102, 69, 84, 69, 107, 103, 114, 113, + 78, 118, 82, 114, 84, 129, 69, 112, 78, 98, 96, 103, + 89, 137, 96, 111, 105, 97, 93, 93, 101, 105, 105, 105, + 141, 123, 102, 93, 91, 79, 87, 81, 102, 99, 109, 108, + 94, 92, 124, 123, 130, 134, 100, 107, 71, 75, 92, 91, + 94, 104, 107, 83, 106, 101, 113, 114, 122, 122, 114, 114, + 118, 124, 103, 106, 95, 116, 90, 93, 107, 104, 109, 107, + 116, 118, 76, 72, 88, 88, 132, 132, 140, 141, 116, 116, + 90, 81, 111, 95, 139, 97, 123, 96, 112, 100, 110, 108, + 112, 116, 133, 140, 112, 120, 80, 85, 55, 55, 85, 84, + 125, 94, 111, 104, 116, 103, 112, 86, 93, 84, 99, 98, + 180, 179, 197, 197, 169, 163, 149, 146, 130, 124, 116, 115, + 76, 47, 36, 11, 43, 28, 66, 53, 82, 80, 102, 99, + 119, 123, 176, 201, 113, 120, 112, 111, 103, 105, 106, 110, + 145, 114, 112, 89, 120, 93, 123, 104, 131, 123, 113, 111, + 97, 109, 82, 106, 75, 104, 103, 115, 120, 124, 111, 114, + 114, 111, 113, 105, 34, 33, 63, 63, 105, 106, 122, 122, + 51, 41, 96, 92, 125, 125, 118, 118, 118, 119, 113, 113, + 111, 180, 108, 178, 107, 171, 110, 160, 105, 136, 102, 117, + 76, 79, 90, 92, 80, 88, 88, 93, 123, 124, 122, 122, + 131, 128, 123, 122, 151, 158, 108, 107, 129, 128, 119, 119, + 97, 99, 114, 120, 121, 125, 151, 157, 82, 89, 95, 96, + 128, 94, 130, 95, 149, 113, 149, 120, 127, 115, 113, 109, + 167, 171, 83, 80, 84, 79, 106, 106, 112, 110, 107, 108, + 130, 139, 81, 88, 107, 106, 112, 112, 119, 118, 114, 112, + 108, 105, 100, 98, 120, 116, 122, 117, 38, 37, 72, 73, + 118, 125, 110, 120, 114, 126, 135, 142, 139, 142, 118, 119, + 119, 119, 156, 145, 78, 75, 94, 94, 112, 110, 113, 113, + 101, 108, 98, 104, 103, 109, 117, 118, 167, 167, 132, 132, + 116, 108, 118, 111, 149, 136, 85, 74, 95, 92, 113, 112, + 74, 69, 104, 107, 96, 100, 117, 121, 103, 105, 103, 103, + 110, 106, 111, 101, 82, 72, 96, 92, 132, 130, 120, 121, + 116, 113, 138, 139, 104, 103, 131, 131, 68, 69, 92, 92, + 97, 97, 146, 151, 122, 132, 97, 95, 117, 116, 115, 116, + 139, 134, 110, 110, 124, 129, 100, 110, 86, 91, 100, 102, + 116, 136, 88, 90, 137, 139, 103, 114, 114, 117, 111, 110, + 82, 83, 104, 102, 97, 99, 97, 97, 58, 56, 84, 84, + 83, 122, 76, 105, 112, 126, 120, 134, 112, 120, 108, 110, + 114, 128, 73, 90, 72, 76, 98, 100, 95, 96, 101, 102, + 101, 108, 118, 126, 94, 102, 81, 83, 138, 140, 131, 130, + 88, 100, 112, 124, 105, 106, 122, 123, 121, 121, 114, 114, + 76, 108, 73, 83, 93, 95, 110, 111, 98, 99, 103, 103, + 105, 112, 98, 108, 114, 95, 117, 98, 120, 116, 116, 115, + 231, 238, 150, 146, 124, 126, 115, 122, 117, 121, 112, 112, + 74, 73, 72, 74, 60, 61, 62, 61, 85, 85, 101, 101, + 67, 69, 50, 51, 83, 83, 110, 110, 118, 113, 112, 111, + 199, 124, 184, 115, 176, 117, 165, 120, 138, 115, 116, 114, + 52, 116, 36, 107, 49, 99, 72, 106, 91, 107, 104, 105, + 140, 138, 141, 135, 154, 147, 166, 159, 139, 136, 116, 115, + 130, 119, 180, 157, 183, 149, 136, 121, 119, 114, 111, 110, + 104, 129, 113, 154, 111, 148, 108, 132, 105, 117, 106, 111, + 114, 35, 99, 65, 113, 94, 110, 98, 111, 107, 107, 106, + 106, 110, 128, 135, 162, 175, 143, 155, 115, 116, 109, 109, + 168, 155, 112, 109, 125, 125, 126, 122, 126, 124, 111, 112, + 128, 96, 160, 77, 151, 77, 121, 80, 114, 94, 107, 103, + 97, 104, 101, 116, 56, 79, 74, 83, 92, 95, 104, 106, + 63, 68, 76, 77, 110, 107, 96, 90, 85, 83, 97, 96, + 116, 110, 46, 42, 103, 100, 122, 120, 102, 101, 104, 104, + 106, 101, 109, 98, 96, 61, 67, 35, 72, 61, 96, 93, + 88, 80, 81, 76, 113, 110, 144, 143, 88, 89, 93, 94, + 95, 96, 100, 101, 136, 132, 166, 160, 148, 147, 115, 116, + 80, 78, 130, 129, 120, 108, 91, 85, 95, 91, 104, 102, + 151, 147, 106, 109, 110, 110, 64, 69, 68, 67, 96, 96, + 90, 166, 97, 128, 99, 120, 104, 121, 109, 118, 105, 109, + 122, 138, 110, 143, 75, 97, 83, 94, 89, 94, 102, 103, + 136, 142, 103, 110, 83, 89, 99, 101, 138, 138, 120, 122, + 168, 88, 105, 90, 109, 107, 110, 111, 106, 105, 103, 102, + 68, 72, 102, 104, 92, 102, 65, 75, 89, 94, 106, 106, + 83, 74, 93, 85, 73, 66, 106, 102, 100, 92, 99, 97, + 93, 99, 101, 96, 116, 112, 125, 120, 88, 88, 96, 96, + 44, 98, 93, 115, 104, 116, 103, 107, 112, 113, 107, 107, + 93, 83, 105, 99, 93, 84, 127, 125, 141, 143, 117, 118, + 106, 103, 126, 121, 137, 123, 123, 114, 147, 142, 127, 123, + 103, 110, 89, 91, 121, 124, 66, 71, 68, 69, 96, 97, + 114, 105, 68, 65, 69, 67, 96, 94, 131, 130, 123, 121, + 111, 104, 130, 121, 95, 95, 72, 74, 88, 88, 105, 104, + 135, 124, 110, 98, 114, 111, 159, 158, 111, 113, 104, 106, + 103, 108, 94, 107, 55, 57, 115, 118, 121, 122, 111, 111, + 97, 99, 106, 111, 119, 126, 59, 62, 111, 112, 124, 125, + 86, 93, 100, 110, 118, 145, 113, 132, 120, 125, 112, 112, + 101, 115, 78, 149, 81, 114, 111, 121, 108, 112, 107, 108, + 104, 104, 94, 96, 84, 83, 135, 132, 71, 69, 88, 86, + 100, 98, 62, 60, 81, 80, 90, 89, 63, 66, 89, 90, + 123, 116, 108, 99, 90, 86, 91, 92, 65, 65, 88, 88, + 84, 79, 115, 109, 123, 111, 99, 99, 134, 136, 121, 123, + 127, 137, 84, 88, 104, 107, 128, 130, 74, 69, 89, 89, + 118, 112, 143, 132, 141, 131, 113, 113, 99, 102, 104, 105, + 117, 115, 100, 99, 131, 126, 90, 88, 145, 144, 128, 127, + 112, 114, 131, 133, 85, 84, 118, 119, 151, 152, 117, 117, + 110, 105, 162, 140, 116, 107, 140, 134, 124, 122, 113, 113, + 107, 110, 124, 133, 98, 103, 99, 107, 109, 113, 112, 112, + 115, 105, 82, 77, 125, 122, 133, 132, 118, 120, 113, 113, + 101, 88, 84, 80, 97, 99, 91, 91, 94, 94, 101, 100, + 121, 86, 139, 108, 106, 93, 103, 99, 112, 108, 108, 107, + 113, 83, 105, 102, 125, 125, 114, 115, 110, 112, 108, 109, + 93, 112, 113, 121, 125, 131, 101, 101, 107, 109, 111, 111, + 98, 102, 117, 126, 80, 84, 107, 109, 83, 84, 96, 97, + 132, 136, 112, 118, 94, 93, 121, 118, 99, 98, 102, 103, + 122, 127, 128, 133, 118, 104, 102, 88, 100, 94, 104, 102, + 115, 116, 102, 105, 140, 142, 135, 130, 90, 88, 100, 101, + 94, 86, 112, 112, 89, 121, 92, 101, 109, 108, 110, 112, + 99, 93, 129, 114, 109, 99, 131, 119, 102, 97, 103, 103, + 103, 116, 124, 101, 115, 95, 105, 101, 94, 91, 100, 100, + 113, 90, 94, 86, 92, 92, 117, 111, 106, 103, 106, 105, + 115, 99, 110, 91, 107, 104, 81, 90, 108, 113, 112, 113, + 113, 114, 93, 101, 101, 102, 101, 126, 93, 103, 104, 105, + 117, 106, 124, 107, 104, 119, 108, 133, 104, 111, 104, 106 +}; + +static const float wmavoice_lsp10_intercoeff_a[32][2][10] = { + { { 0.5108627081, 0.0480548441, -1.5099149644, 0.6736935377, + 0.7536551058, 0.7651474178, 0.8510628343, 0.6667704582, + 0.7576012611, 0.7091397047 }, + { 0.1351471841, -0.1965375543, -1.6313457787, 0.3218626380, + 0.4132472873, 0.4663473070, 0.5805781186, 0.3962165117, + 0.4818550050, 0.4907165468 } }, + { { 0.8556320667, 0.7774704993, -0.0175759494, -0.1882298589, + 0.1892164350, 0.4850396216, 0.6270319819, 0.6327089071, + 0.6513319910, 0.6075088978 }, + { 0.4374088347, 0.3505934179, -0.0762144327, -0.2830760479, + -0.0626451969, 0.1500318050, 0.2602472305, 0.2781780064, + 0.3167395592, 0.3596626520 } }, + { { 0.1899779737, 0.0650856197, 0.1699010432, 0.9122628570, + 0.9097705483, 0.7433397174, 0.6304935217, 0.5164704025, + 0.4174703658, 0.5215242505 }, + { 0.0704856217, 0.0169009864, 0.0188394487, 0.5587704182, + 0.5194473267, 0.3539164960, 0.2426626086, 0.1721164286, + 0.1371548772, 0.2594856918 } }, + { { 0.8858859241, 0.9100474715, 0.8921859264, 0.9332397878, + 1.0225475132, 1.0555013716, 1.0983552337, 1.1290244758, + 1.0363244414, 0.9277705550 }, + { 0.4810934663, 0.5782935023, 0.6835935414, 0.7650781870, + 0.9018090069, 0.9996321201, 1.0219936669, 1.0474705994, + 0.9109474719, 0.7774704993 } }, + { { 0.4359549880, 0.2275702953, 0.0993548632, 0.1763395071, + 0.1055856347, 0.1018471718, 0.1170087159, 0.1221317947, + 0.1834010482, 0.2988780141 }, + { 0.1573702693, 0.1041317880, 0.0506856143, 0.0781702399, + 0.0058932900, -0.0026913285, -0.0031067133, 0.0070702136, + 0.0116394460, 0.0566394627 } }, + { { 0.8528628349, 0.8028782010, 0.4680088460, 0.9055474699, + 1.3742399514, 1.1093629301, 0.4122780561, 0.4003703594, + 0.6360319853, 0.6415704489 }, + { 0.4252934456, 0.3823703527, 0.1676856577, 0.5241550207, + 1.1995706558, 0.9088013172, 0.1224087179, 0.0730471611, + 0.3071857095, 0.3772472739 } }, + { { 0.5508781075, 0.2829549313, -0.0022067130, 0.1042702496, + 1.0318244398, 1.3258476257, 1.3550630212, 0.9931936562, + 0.7195243239, 0.6807550788 }, + { 0.2679318488, 0.0960317850, -0.1357529163, -0.1291759908, + 0.6451012194, 0.9968628883, 0.9510321021, 0.6608166099, + 0.3799472749, 0.3735780418 } }, + { { 0.9967244267, 1.0255244374, 0.9800398052, 0.7939474285, + 0.8288397491, 0.8390166759, 0.8660166860, 0.9247936308, + 0.9127474725, 0.8684397638 }, + { 0.7921474278, 0.9416859448, 0.8547320664, 0.5348165631, + 0.6231550574, 0.6703012288, 0.6987550855, 0.8147858977, + 0.7406397164, 0.6496012211 } }, + { { 0.1439394951, -0.3193529844, -0.2024914026, -0.1854606271, + 0.0877240896, 0.1617318094, 0.3087087870, 0.3777318895, + 0.3910242021, 0.4797780812 }, + { -0.0157067180, -0.1778452396, -0.1554836929, -0.1759760082, + -0.0607759655, -0.0161221027, 0.0393317640, 0.0758856237, + 0.1163856387, 0.1947548985 } }, + { { 1.1021629274, 0.9958244264, 0.4658626914, 0.3089164793, + 0.3740626574, 0.2962472439, 0.3170857131, 0.2420395315, + 0.2649549246, 0.2936857045 }, + { 0.4700857699, 0.1809087396, 0.0311625302, 0.0106009841, + 0.0311625302, 0.0266625285, 0.0221625268, 0.0156548321, + 0.0551163852, 0.1010164022 } }, + { { 0.2925087810, 0.3418011069, 0.7339243293, 0.7322627902, + 0.7288704813, 0.7924935818, 0.7724166512, 0.7819012702, + 0.8325782120, 0.7954705060 }, + { 0.0559471548, -0.0456144214, -0.0462374985, -0.1005144417, + -0.0511528850, -0.0455451906, -0.0044220984, 0.0451471508, + 0.1232394874, 0.2085318267 } }, + { { 0.2230702937, -0.9052532017, 1.2441552877, 1.0825706124, + 0.9088705480, 0.8797243834, 0.8648397624, 0.8091089725, + 0.7633474171, 0.7468704879 }, + { -0.2030452490, -1.4167303145, 1.3542322516, 0.8369397521, + 0.6148473620, 0.5560704172, 0.5450627208, 0.4978473186, + 0.4200319052, 0.4904396236 } }, + { { 0.6088242829, 0.5965704322, 0.6547242999, 0.8554936051, + -0.2989298999, 0.2404472232, 0.3573780358, 0.7499166429, + 0.7691628039, 0.6824858487 }, + { 0.2582395375, 0.2721549273, 0.3462318778, 0.4820626974, + -0.4780299664, -0.0712990463, 0.0200163722, 0.4246703684, + 0.4660011530, 0.4172626734 } }, + { { 1.1749937236, 1.0773090720, 1.0566782951, 1.0249013603, + 0.9947167337, 0.9626628757, 0.9562244117, 0.9072782397, + 0.7654243410, 0.6448935270 }, + { 1.1595552564, 0.9340013266, 0.3959395885, 0.3693549633, + 0.3915780485, 0.3104395568, 0.3499011099, 0.2236933708, + 0.1638087332, 0.1811856627 } }, + { { 0.9572628736, 0.9389859438, 0.6619243026, 0.6849089265, + 0.7276935577, 0.7839781940, 0.7987243533, 0.7748397291, + 0.7101089358, 0.7277627885 }, + { 0.5809935033, 0.5575934947, 0.3544703424, 0.3636780381, + 0.3736472726, 0.4486242235, 0.4684934616, 0.4481396079, + 0.3456780314, 0.4478626847 } }, + { { 0.1259394884, 1.3096476197, 1.0794552267, 1.0009475052, + 0.9061013162, 0.9216782451, 0.8954397738, 0.9160013199, + 0.8575012982, 0.7479089499 }, + { -0.3689222336, 1.5293861628, 0.7323320210, 0.4102703631, + 0.3825780451, 0.2828164697, 0.2644010782, 0.2455010712, + 0.2482010722, 0.2335241437 } }, + { { 0.5380704105, 0.1600702703, -0.0657605827, -0.2390452623, + -0.3885837793, -0.4150299430, -0.3001760542, -0.1451683044, + 0.1312010288, 0.2798395455 }, + { 0.2074933648, 0.0560163856, -0.0956682861, -0.2893068194, + -0.3889991641, -0.3918376267, -0.3550068438, -0.2649375796, + -0.0554451942, 0.1167317927 } }, + { { 0.6092396677, 0.5101011693, 0.4012011290, 0.5416011810, + 0.5715781152, 0.6476627588, 0.6988243163, 0.7306012511, + 0.7531704903, 0.6534781456 }, + { 0.2060395181, 0.1409625709, 0.1024702489, 0.1834010482, + 0.1946856678, 0.2547779977, 0.3134857118, 0.3283011019, + 0.3837549686, 0.3501780331 } }, + { { 0.4516011477, 0.5351627171, 0.8068243563, 0.7049858570, + 0.7165473998, 0.6005858183, 0.4870473146, 0.2500010729, + 0.3132087886, 0.4462703764 }, + { 0.1053087115, 0.1348702610, 0.4457857609, 0.3499703407, + 0.3537780344, 0.2628780007, 0.1665087342, 0.0200856030, + 0.0329625309, 0.1525241137 } }, + { { 0.7058166265, 0.7305320203, 1.1684860289, 1.4524707496, + 1.3212091625, 1.2613245249, 1.1712552607, 1.1154552400, + 1.0487167537, 0.9153782427 }, + { 0.2286087573, 0.2851703167, 1.2016475797, 1.5154707730, + 1.2726091444, 1.1459167898, 0.9801090360, 0.9296397865, + 0.8490551412, 0.6772243083 } }, + { { 0.6686396897, 0.5728935003, 0.4734780788, 0.6970243156, + 0.5852165818, -0.0762836635, -0.2054683268, -0.1380375326, + 0.1282933354, 0.3467164934 }, + { 0.2925087810, 0.2344933748, 0.1677548885, 0.2747856975, + 0.2097087502, -0.2795452774, -0.3761222363, -0.3183837533, + -0.0834836662, 0.1482318044 } }, + { { 0.6559704542, 0.7737320364, 0.9867551923, 0.9912551939, + 0.9508936405, 0.9114320874, 0.8336859047, 0.7905551195, + 0.7672935724, 0.7532397211 }, + { 0.1843702793, 0.2565087676, 0.7571858764, 0.7545551062, + 0.6793704629, 0.5981627405, 0.5078165531, 0.4282011390, + 0.3948318958, 0.4502165318 } }, + { { 0.4430857599, 0.6102781296, 0.8485012949, 0.8573628366, + 0.9078320861, 0.9979705811, 1.0411013663, 1.0524552166, + 1.0194321275, 0.9023628533 }, + { 0.0070009828, 0.0084548295, 0.1613856554, 0.3484472632, + 0.4385857582, 0.5895088911, 0.6367935240, 0.6736935377, + 0.7026320100, 0.5924165845 } }, + { { 1.0532859862, 1.1059706211, 1.1311013997, 1.1250783205, + 1.0425552130, 0.9993551970, 0.9673013389, 0.9386397898, + 0.8836013079, 0.8336859047 }, + { 0.9791398048, 1.1481321752, 1.1275706291, 1.0082167387, + 0.8809705377, 0.8031551242, 0.7287320197, 0.6496704519, + 0.5211088657, 0.4734088480 } }, + { { -0.0251221061, -0.0443682671, 0.1282241046, 0.3850703537, + 0.4252934456, 0.4547857642, 0.4690473080, 0.4873242378, + 0.6001012027, 0.5882627368 }, + { -0.0562759638, -0.0246374905, 0.0070009828, 0.0971394777, + 0.1232394874, 0.1278779507, 0.1302317977, 0.1462241113, + 0.2073549032, 0.2446010709 } }, + { { 1.1749244928, 1.1155937016, 0.9236167073, 0.6288319826, + 0.6515396833, 0.5391781032, 0.5398011804, 0.4997165501, + 0.4066703618, 0.3998857439 }, + { 0.9403013289, 0.7346166372, 0.1841625869, 0.1319625676, + 0.1395087242, 0.0857856274, 0.0952702463, 0.0860625505, + 0.0829471648, 0.1132010221 } }, + { { 0.9047167003, 0.9840551913, 0.9933321178, 0.9360090196, + 0.9164859354, 0.9213320911, 0.8701705337, 0.8815936148, + 0.8414397538, 0.8188012838 }, + { 0.0961010158, -0.0147374868, 0.0202240646, 0.1002548635, + 0.1407548785, 0.1837472022, 0.1858241260, 0.2064549029, + 0.2228626013, 0.2859318554 } }, + { { 0.4034165144, 0.1918472052, 2.1959402561, 0.4763165414, + 0.6577012241, 0.7036704719, 0.6626858413, 0.7650089562, + 0.7702704966, 0.6543781459 }, + { 0.0940933228, -0.1222529113, 2.3491480052, 0.1385394931, + 0.3052472472, 0.3665857315, 0.3350857198, 0.4722319245, + 0.4313857555, 0.3846549690 } }, + { { 0.8215012848, 0.8613782227, 1.0399936736, 1.4082322717, + 0.4075011313, 0.4091626704, 0.5230473280, 0.6101396680, + 0.7510243356, 0.7237474024 }, + { 0.4810934663, 0.5670088828, 0.9207782447, 1.3007860780, + 0.0453548431, 0.0858548582, 0.1803548932, 0.2790087759, + 0.3974626660, 0.4581780732 } }, + { { 1.5921784937, 1.4987169206, 1.1321398616, 0.8235089779, + 0.6888550818, 0.6621319950, 0.6192089021, 0.6533396840, + 0.7196627855, 0.6549319923 }, + { 1.5911400318, 1.4768399894, 0.9358705580, 0.4674549997, + 0.3522549570, 0.3144549429, 0.2985318601, 0.3559241891, + 0.4061857462, 0.3958703578 } }, + { { 0.7975474298, 0.8712782264, 0.8974474669, 0.3008164763, + 0.5562088788, 0.6655935347, 0.8921166956, 1.0918475389, + 0.9544936419, 0.8554936051 }, + { 0.3769703507, 0.4930703938, 0.6619243026, -0.0382759571, + 0.1766856611, 0.3015780151, 0.5952550471, 0.8903859258, + 0.7395320237, 0.6205935180 } }, + { { 0.2206472158, 2.4467634261, 1.2920629978, 1.0239321291, + 0.9014628530, 0.8552166820, 0.8219859004, 0.9005628526, + 0.7614781857, 0.7763628066 }, + { -0.2722068131, 2.8967635930, 1.3039706945, 0.7695089579, + 0.6132550538, 0.5701242685, 0.5737935007, 0.6533396840, + 0.5422934890, 0.5150857866 } }, +}; + +static const float wmavoice_lsp10_intercoeff_b[32][2][10] = { + { { 0.4881048799, -0.1998192370, -0.3872502148, 0.0109423101, + 0.0406953394, 0.1788437665, 0.1673750877, 0.3409781158, + 0.4061202109, 0.5221177042 }, + { 0.1492218077, -0.1372330189, -0.2683691680, -0.0621950924, + -0.0624572337, -0.0068177581, -0.0076041818, 0.0680235624, + 0.1055752933, 0.1199930608 } }, + { { 0.7934338748, 0.0012430847, 0.4239458144, 0.5521328747, + 0.6497149467, 0.6423749924, 0.7170197070, 0.7169541717, + 0.7778364718, 0.8397018015 }, + { 0.2768190503, -0.0491535664, -0.0325731337, 0.0261465013, + 0.0469867289, 0.0649434030, 0.0781815350, 0.1031504869, + 0.1194687784, 0.2451654971 } }, + { { 0.7212139666, 0.1658677757, 0.0101558864, 0.5636015534, + 1.3175852597, 1.1911676526, 1.1266809106, 0.8230558336, + 0.8604109585, 0.8094900250 }, + { 0.3658815324, 0.0816549063, -0.2092563212, 0.1946377754, + 1.0856558084, 0.9491457641, 0.8461242616, 0.5193652213, + 0.5975488424, 0.5293265879 } }, + { { 0.9507186115, 0.9078585207, 0.8773190677, 0.8677509129, + 0.8024122119, 0.8127667904, 0.8246286809, 0.8779088855, + 0.9454102516, 0.9863698184 }, + { 0.6883807778, 0.6900191605, 0.7059442401, 0.6552854478, + 0.5843107104, 0.5553441048, 0.5887671113, 0.6494528055, + 0.7725936472, 0.7792782485 } }, + { { 0.2399882078, 0.1938513517, 0.4441962242, 0.4475385249, + 0.3055235147, 0.1745184362, 0.1174371839, 0.0679580271, + 0.0782470703, 0.1695377529 }, + { 0.0170370936, 0.0253600776, 0.2072205544, 0.1907711923, + 0.1096384823, 0.0327000320, -0.0134368241, -0.0461389422, + -0.0372916758, -0.0243156850 } }, + { { 0.5457104146, 0.3774812818, 0.5235594809, 0.2994287312, + 0.2394639254, 0.5731041729, 0.9971176088, 1.1646913886, + 0.9028123021, 0.7777709365 }, + { 0.2288472056, 0.1181580722, 0.2074171603, 0.0355180502, + -0.0024924278, 0.2596487999, 0.7474936247, 0.9103488624, + 0.5927647650, 0.4772915542 } }, + { { 0.6541713476, 0.6412608922, 0.7625012100, 0.7826205492, + 0.4839106202, 0.3311478198, 0.4577620327, 0.8572652638, + 0.9442306161, 0.8282986581 }, + { 0.2852075696, 0.2614837885, 0.4221763611, 0.4314823747, + 0.1434547007, 0.0435788929, 0.1397191882, 0.5525916219, + 0.6752081811, 0.5487250388 } }, + { { 0.6742251515, 1.0610800683, 1.0500701368, 0.9570100009, + 0.9325653315, 0.9243078828, 0.9148707986, 0.8317720294, + 0.7696445584, 0.6784849465 }, + { 0.2283884585, 0.9739181101, 0.5336519182, 0.4974764287, + 0.3998288214, 0.3674543798, 0.2719694376, 0.2608939707, + 0.2087934017, 0.1675716937 } }, + { { 0.3736146986, -1.5457833707, 0.9216864705, 0.7959242165, + 0.7358283401, 0.7233110964, 0.7271121442, 0.6852350831, + 0.6891672015, 0.6589554250 }, + { 0.1246460676, -1.7167649865, 0.7037160397, 0.4803061783, + 0.4694928527, 0.4654951990, 0.5208069980, 0.5305717587, + 0.5288023055, 0.5278192759 } }, + { { 1.0116009116, 0.9882703424, 0.8393741250, 0.8889843524, + 0.8934407532, 0.8906227350, 0.9222107530, 0.8973073363, + 0.9257496595, 0.9306648076 }, + { 0.5097970665, -0.0106843412, 0.1419473886, 0.2804890275, + 0.3719763160, 0.3694859743, 0.4640534222, 0.5034401417, + 0.5592106879, 0.6652468145 } }, + { { 0.9718209803, 0.7615181804, 0.2172474563, 0.4920369983, + 0.4310891628, 0.5038333535, 0.4668059051, 0.5339140594, + 0.4453758597, 0.4050061107 }, + { 0.6543679535, 0.1205173433, -0.0050483048, 0.1580035388, + 0.1308719218, 0.1700620353, 0.1740596890, 0.2179683447, + 0.1967349052, 0.1703897119 } }, + { { 0.7663022578, 0.4025157690, 1.3811545074, 1.1642981768, + 1.0709758997, 0.9812580645, 1.0092416406, 0.9089070857, + 0.7776398659, 0.8189926445 }, + { 0.3471384346, 0.0602248609, 1.3968829811, 1.0841484964, + 0.8940305710, 0.7313719392, 0.7345176339, 0.5304406881, + 0.4076275229, 0.4535677731 } }, + { { 0.1300854981, 0.1323136985, 0.7564064264, 0.7335346043, + 0.7924508452, 0.6039057672, 0.6896914840, 0.3694859743, + 0.2825861573, 0.3179096878 }, + { -0.0208423138, -0.0530856848, 0.3449102342, 0.3819376826, + 0.4466865659, 0.2807511687, 0.3842969537, 0.1144880950, + 0.0617321730, 0.0767397583 } }, + { { 0.7559476793, 0.8462553322, 0.6452585459, 1.1308751702, + 1.0606868565, 0.9498666525, 0.7425129414, 0.6221901178, + 0.6574481130, 0.6976212561 }, + { 0.3420922160, 0.4310236275, 0.2800958157, 0.9317133725, + 0.8210897744, 0.6144569516, 0.3227593005, 0.2464762032, + 0.2769501209, 0.3521846533 } }, + { { 0.7609938979, 0.6943444908, 1.1490939856, 0.4350868165, + 0.6101971567, 0.6246149242, 0.7370079756, 0.6522052884, + 0.6966382265, 0.7565374970 }, + { 0.3939306438, 0.3449102342, 0.9874839187, 0.0910919905, + 0.2804234922, 0.2888775468, 0.4060546756, 0.3284608722, + 0.3483836055, 0.4819445610 } }, + { { 0.7828826904, 1.1833034158, 1.9916158915, 0.8667678833, + 0.9218830764, 0.8856420517, 0.9373494089, 0.7415299118, + 0.7450032830, 0.7074515522 }, + { 0.4685098231, 1.1713104546, 1.9853245020, 0.6206828058, + 0.6664264500, 0.6033814847, 0.6089519858, 0.3784643114, + 0.4212588668, 0.3441893458 } }, + { { 0.4671335816, 0.4177199602, 0.0804097354, -0.1836975515, + -0.1802241802, -0.0775958896, -0.0250365734, 0.0884050429, + 0.2136430144, 0.3472039700 }, + { 0.1187478900, 0.1122598946, -0.0381436348, -0.2284581661, + -0.2302276194, -0.1738672554, -0.1350048184, -0.0547896028, + 0.0000634491, 0.0545888245 } }, + { { 0.5545576811, 0.4791920781, 0.8204999566, 0.8462553322, + 0.9212277234, 0.8946203887, 0.9659883380, 0.9137566984, + 0.9225384295, 0.9207034409 }, + { 0.1176993251, -0.0429277122, -0.0330318809, 0.0566859543, + 0.0983008742, 0.1593797803, 0.1732077301, 0.2320584357, + 0.2739354968, 0.3753186166 } }, + { { 0.7157745361, 0.6367389560, -1.2036890686, 0.7107283175, + 0.6885118484, 0.7332724631, 0.7436270416, 0.7113181353, + 0.5935511887, 0.6023984551 }, + { 0.3664058149, 0.3280676603, -1.3082178831, 0.3909815550, + 0.3641776145, 0.3926854730, 0.3898674548, 0.4086760879, + 0.3127979338, 0.3949792087 } }, + { { 1.0267395675, 1.0621941686, 1.0415505469, 0.9971176088, + 0.9764739871, 0.9904330075, 0.9591071308, 0.9338760376, + 0.9026156962, 0.9073997736 }, + { 0.9855833948, 1.0548542142, 0.9787021875, 0.8573307991, + 0.8360973597, 0.8193203211, 0.7386463583, 0.7038471103, + 0.6333966553, 0.6434235573 } }, + { { 0.6235008240, 0.7635497749, 0.8094900250, 0.7227212787, + -0.0610809922, -0.1357912421, -0.2359291911, 0.0800165236, + 0.3972729445, 0.5078965425 }, + { 0.2983146310, 0.4983939230, 0.4145742655, 0.3284608722, + -0.3203386664, -0.3495018780, -0.4734291434, -0.1808139980, + 0.1211071610, 0.2001427412 } }, + { { 0.8925887942, 0.8804647624, 0.6153089106, 0.6760601401, + 0.7887153327, 1.0065546930, 1.0829033256, 1.0347348750, + 0.9800128937, 0.9125770628 }, + { 0.5955827832, 0.6195687056, 0.2924164534, 0.3553958833, + 0.5417127609, 0.8713553548, 0.9977729619, 0.8817754686, + 0.7645328045, 0.6604627371 } }, + { { 1.1581378579, 1.0359145105, 0.7731179297, 0.6839243770, + 0.6839899123, 0.6664264500, 0.6910677254, 0.6579068601, + 0.6779606640, 0.6243527830 }, + { 1.1508634388, 0.8400294781, 0.2358594835, 0.2542749047, + 0.2484422624, 0.2620736063, 0.2676441073, 0.2713796198, + 0.3068997562, 0.3223005533 } }, + { { 0.1376220584, 1.2572927773, 0.8593623936, 0.6218624413, + 0.5128116906, 0.5393534899, 0.4436064065, 0.4334484339, + 0.4494390488, 0.4002220333 }, + { -0.1159995794, 1.2433337569, 0.4805027843, 0.2632532418, + 0.1769432425, 0.1868390739, 0.1555131972, 0.1530228555, + 0.1490252018, 0.1559064090 } }, + { { 0.1817273200, -0.0085216761, 0.0739872754, 0.1808098257, + 0.2770811915, 0.3344901204, 0.4292541742, 0.5404020548, + 0.5780193210, 0.5707449019 }, + { -0.0035409927, -0.0188107193, -0.0057691932, 0.0132360458, + 0.0560961366, 0.0534747243, 0.1002013981, 0.1737320125, + 0.1706518531, 0.1637706459 } }, + { { 0.9648087025, 1.0030813217, 0.9501943290, 0.8381944895, + 0.7545059025, 0.7621735334, 0.7121700943, 0.7328792512, + 0.7534573376, 0.7414643764 }, + { 0.1872322857, -0.0081939995, 0.0663851798, 0.0963348150, + 0.0509188473, 0.0565548837, 0.0471833348, 0.0809340179, + 0.1049199402, 0.1751082540 } }, + { { 0.6792713702, 0.9521603882, 0.5296542645, 0.3657504618, + 0.3905883431, 0.3121425807, 0.2726903260, 0.3156159520, + 0.2859284580, 0.3179096878 }, + { 0.2307477295, 0.3771536052, 0.0743804872, 0.0260154307, + 0.0477731526, 0.0391880274, 0.0228042006, 0.0572757721, + 0.0337485969, 0.0492149293 } }, + { { 0.8649328947, 0.9505875409, 1.0443030298, 1.1704584956, + 1.2709241211, 1.3232212961, 1.2477901578, 1.1513877213, + 1.0346038043, 0.9695272446 }, + { 0.4620873630, 0.5685822368, 0.8975039423, 1.0476453304, + 1.2278674245, 1.2290470600, 1.1962138712, 1.0051129162, + 0.8706344664, 0.7477557659 } }, + { { 0.4188340604, 0.6011532843, 0.4726385474, 0.6389671564, + 0.6753392518, 0.7842589319, 0.6147846282, 0.6708828509, + 0.6406055391, 0.5398777723 }, + { 0.1012499630, 0.2312064767, 0.1773364544, 0.2800302804, + 0.3348177969, 0.4343003929, 0.2822584808, 0.3293128312, + 0.3024433553, 0.2401848137 } }, + { { 0.5049474537, 0.7943513691, 0.9536021650, 0.9407572448, + 0.9823721647, 0.9747045338, 1.0145500004, 0.9629737139, + 0.9526191354, 0.9283710718 }, + { 0.0566204190, 0.0973178446, 0.5812305510, 0.5687133074, + 0.6834000945, 0.6616423726, 0.7611905038, 0.6683925092, + 0.6463071108, 0.6118355393 } }, + { { 0.8969141245, 0.9359731674, 0.8756151497, 0.8419300020, + 0.8353109360, 0.6807131469, 0.3358008265, 0.3386188447, + 0.3524467945, 0.4495045841 }, + { 0.5298508704, 0.4606455863, 0.4934132397, 0.4415748119, + 0.4015327394, 0.2052544951, -0.0329663455, -0.0154684186, + 0.0418094397, 0.1631152928 } }, + { { 0.6345762908, 2.5209445655, 1.0373562872, 0.9166402519, + 0.8865595460, 0.8907538056, 0.8522190452, 0.7290782034, + 0.7385808229, 0.6345107555 }, + { 0.2641707361, 2.5696372986, 0.8539884984, 0.6532538533, + 0.6087553799, 0.5851626694, 0.5276226699, 0.4330552220, + 0.3971418738, 0.3599833548 } }, +}; + +static const float wmavoice_lsp16_intercoeff_a[32][2][16] = { + { { 0.5337238312, 0.4810695648, -0.3766536713, -0.1204767227, + -0.0898437500, -0.0070896149, 0.1134738922, 0.1337728500, + 0.3739156723, 0.3849058151, 0.4220180511, 0.5404901505, + 0.5224876404, 0.5502910614, 0.5313453674, 0.4405946732 }, + { 0.1775283813, 0.1679325104, -0.2702789307, -0.1359367371, + -0.1452455521, -0.0888595581, -0.0256662369, -0.0023736954, + 0.1074047089, 0.1431636810, 0.1357412338, 0.2045526505, + 0.2686481476, 0.3404531479, 0.3209333420, 0.1493968964 } }, + { { 0.7402400970, 0.0838251114, 0.6486282349, 0.6145095825, + 0.7331047058, 0.7183008194, 0.7436847687, 0.7627944946, + 0.7653779984, 0.7795667648, 0.8399305344, 0.8393154144, + 0.8219690323, 0.7474164963, 0.6681070328, 0.6490793228 }, + { 0.2850513458, -0.0544128418, -0.0300130844, 0.0204677582, + 0.0328931808, 0.0589332581, 0.0796422958, 0.1187639236, + 0.1320505142, 0.1539077759, 0.2189874649, 0.2865276337, + 0.2973947525, 0.2614307404, 0.2416648865, 0.2428951263 } }, + { { 0.6129922867, 0.7300701141, 0.2073822021, 0.5005893707, + 0.5713691711, 0.5374965668, 0.6293134689, 0.5639057159, + 0.7402811050, 0.6982889175, 0.4668397903, 0.6698703766, + 0.8758535385, 0.8678569794, 0.8678569794, 0.7810840607 }, + { 0.2986249924, 0.3269615173, 0.0096416473, 0.1800708771, + 0.2474060059, 0.2203407288, 0.3007984161, 0.2674179077, + 0.4424810410, 0.4046306610, 0.2063980103, 0.4230022430, + 0.6222190857, 0.6574449539, 0.6776618958, 0.6604385376 } }, + { { 0.7258052826, 0.5073966980, -0.3947381973, 0.5254812241, + 1.0561246872, 0.9706230164, 0.9727144241, 0.9185838699, + 0.8184833527, 0.9093980789, 0.8645353317, 0.7870302200, + 0.6347675323, 0.5123996735, 0.2846002579, 0.3252801895 }, + { 0.4306297302, 0.2182903290, -0.4902458191, 0.1783485413, + 0.7783365250, 0.7152252197, 0.7404451370, 0.6012639999, + 0.5421304703, 0.6619558334, 0.6316919327, 0.5596818924, + 0.3952398300, 0.3567333221, 0.1505041122, 0.1290159225 } }, + { { 0.3077287674, 0.2543363571, 0.2834520340, 0.5282287598, + 0.5350360870, 0.4943971634, 0.4521999359, 0.3086309433, + 0.2372770309, 0.0819387436, -0.1385612488, -0.0848407745, + -0.0380916595, 0.1192150116, 0.3228197098, 0.3012905121 }, + { 0.0567188263, 0.0196886063, 0.0682420731, 0.2102527618, + 0.2452325821, 0.2060699463, 0.1620273590, 0.0784120560, + 0.0418329239, -0.0508041382, -0.2193880081, -0.1644783020, + -0.1361827850, -0.0307512283, 0.1486587524, 0.2356367111 } }, + { { 0.4387903214, 0.5723943710, 0.6147556305, 0.9973602295, + 1.1645498276, 1.1898927689, 1.0326681137, 0.6939010620, + 0.6064310074, 0.4686441422, 0.4646663666, 0.4895582199, + 0.5654230118, 0.6004848480, 0.6179132462, 0.6439123154 }, + { 0.1324195862, 0.2426080704, 0.3132238388, 0.7359752655, + 0.9749288559, 0.9535636902, 0.8105278015, 0.4118890762, + 0.3013315201, 0.2006158829, 0.2331352234, 0.2535161972, + 0.3375005722, 0.4103307724, 0.4102897644, 0.4529380798 } }, + { { 0.7335557938, 0.9203472137, 0.4852113724, 0.8646993637, + 0.7304391861, 0.7503690720, 0.6289854050, 0.6900463104, + 0.6421079636, 0.5184278488, 0.4444904327, 0.2660236359, + 0.2143125534, 0.2406396866, 0.4836940765, 0.5597229004 }, + { 0.3689947128, 0.4967346191, 0.1176567078, 0.5127687454, + 0.3235168457, 0.3426265717, 0.2417469025, 0.3310623169, + 0.2629890442, 0.2130823135, 0.1329116821, 0.0468769073, + -0.0081968307, 0.0146446228, 0.2440433502, 0.3408632278 } }, + { { 0.9425325394, 0.9597969055, 0.6160678864, 0.7050962448, + 0.8063859940, 0.9063224792, 0.9890356064, 1.0038805008, + 1.0338163376, 0.9453620911, 0.9634056091, 0.8068370819, + 0.6859455109, 0.8909034729, 0.9990415573, 1.0122871399 }, + { 0.6895952225, 0.6451835632, 0.3169965744, 0.4268569946, + 0.5666122437, 0.7722673416, 0.8845882416, 0.9061584473, + 0.9550399780, 0.8118810654, 0.8601064682, 0.6129922867, + 0.5069866180, 0.7065315247, 0.7862920761, 0.7766551971 } }, + { { 0.5641517639, -0.0941905975, 0.0412998199, 0.1810550690, + 0.3459482193, 0.4213209152, 0.4401025772, 0.5397109985, + 0.5607891083, 0.6348905563, 0.6861915588, 0.7280607224, + 0.7267074585, 0.6447324753, 0.5948257446, 0.5475025177 }, + { 0.1906919479, -0.0519113541, -0.0608100891, -0.0018815994, + 0.0383062363, 0.0362558365, 0.0529870987, 0.0692672729, + 0.0953073502, 0.1327886581, 0.1390628815, 0.1904459000, + 0.2362518311, 0.2063980103, 0.2311668396, 0.2291574478 } }, + { { 0.9901428223, 0.9589767456, 0.9012374878, 0.8017930984, + 0.8929538727, 0.8512077332, 0.8790111542, 0.8832759857, + 0.8949632645, 0.9159183502, 0.9293279648, 0.9152622223, + 0.9247350693, 0.8753614426, 0.8730239868, 0.8066730499 }, + { 0.4230432510, -0.0464572906, 0.0182533264, 0.1159753799, + 0.2349395752, 0.2740612030, 0.2987070084, 0.3620643616, + 0.3923282623, 0.4694643021, 0.5202322006, 0.5356512070, + 0.5564012527, 0.5362663269, 0.4791831970, 0.5046901703 } }, + { { 0.9785375595, 0.8820457458, 0.3965110779, 0.4790191650, + 0.3907699585, 0.4195575714, 0.2938270569, 0.4091415405, + 0.3659191132, 0.4030723572, 0.4168510437, 0.5030908585, + 0.5023117065, 0.5511522293, 0.5354051590, 0.5563192368 }, + { 0.6592903137, 0.2933759689, 0.0562677383, 0.1286878586, + 0.0758285522, 0.1192560196, 0.0508956909, 0.1175336838, + 0.0684061050, 0.0988750458, 0.0923957825, 0.1819572449, + 0.1965150833, 0.2257537842, 0.3049812317, 0.2993221283 } }, + { { 0.7120265961, 0.7847747803, 0.6065950394, 0.7235908508, + 0.6740531921, 0.6535081863, 0.3734235764, 0.4788551331, + 0.4410867691, 0.6927528381, 1.0758495331, 1.1148891449, + 1.0708875656, 0.8896322250, 0.6401805878, 0.5057153702 }, + { 0.4210338593, 0.4763126373, 0.3229017258, 0.4079113007, + 0.3922462463, 0.3529195786, 0.1258993149, 0.2168960571, + 0.2207508087, 0.4605655670, 0.8759355545, 0.9526205063, + 0.8843832016, 0.7001342773, 0.4503545761, 0.3484086990 } }, + { { 0.5254402161, 0.5349540710, 0.7036199570, 0.6240234375, + 0.6464548111, 0.7537727356, 0.8311548233, 0.7334327698, + 0.3484907150, 0.1846637726, 0.0894021988, 0.3977823257, + 0.7672233582, 0.9224796295, 0.8818407059, 0.7453250885 }, + { 0.2587652206, 0.2524499893, 0.4135704041, 0.3129367828, + 0.3403711319, 0.4473199844, 0.5330266953, 0.4227561951, + 0.1080198288, -0.0044651031, -0.0727024078, 0.1583776474, + 0.5302381516, 0.7313823700, 0.6735610962, 0.5630855560 } }, + { { 0.7936325073, 0.8551034927, 0.9755849838, 0.8953323364, + 0.9345769882, 0.7202281952, 0.8388233185, 0.7941656113, + 0.7550849915, 0.7894906998, 0.8590402603, 0.7813711166, + 0.8483371735, 0.8652324677, 0.8586711884, 0.9584846497 }, + { 0.4781579971, 0.4731960297, 0.8289403915, 0.6175031662, + 0.7262973785, 0.3638277054, 0.5544328690, 0.4761896133, + 0.4388723373, 0.5021476746, 0.5630445480, 0.4562187195, + 0.5190429688, 0.5937595367, 0.6121721268, 0.6973457336 } }, + { { 1.0724458694, 1.0449705124, 0.8594503403, 0.7604160309, + 0.7837905884, 0.8136444092, 0.7623023987, 0.6098756790, + 0.6432561874, 0.6395244598, 0.6853713989, 0.7401580811, + 0.7399530411, 0.7652549744, 0.7675104141, 0.7393789291 }, + { 0.9382266998, 0.8419809341, 0.3087539673, 0.3620233536, + 0.3547649384, 0.4241094589, 0.2857894897, 0.2123851776, + 0.2355957031, 0.2794332504, 0.3219995499, 0.3898267746, + 0.3937635422, 0.4058198929, 0.4228382111, 0.4181222916 } }, + { { 1.0275421143, 1.0940570831, 1.0164289474, 0.9097671509, + 0.9400720596, 0.8976287842, 0.9175586700, 0.8900833130, + 0.9154262543, 0.9492578506, 1.0011329651, 1.0361537933, + 1.0359487534, 0.9320344925, 0.8974237442, 0.8811845779 }, + { 1.0046186447, 1.0860195160, 0.9442958832, 0.7473344803, + 0.7876043320, 0.7410602570, 0.7422084808, 0.6844692230, + 0.7256412506, 0.8455486298, 0.8969316483, 0.9362173080, + 0.9092340469, 0.8227071762, 0.7481546402, 0.7088689804 } }, + { { 0.2205047607, -0.0129537582, 0.0972347260, 0.1154832840, + 0.0951843262, 0.1532516479, 0.1288108826, 0.1749858856, + 0.1591157913, 0.2134923935, 0.2477340698, 0.2634811401, + 0.3032999039, 0.3272485733, 0.3170785904, 0.3172016144 }, + { 0.0032854080, -0.0446119308, 0.0284643173, 0.0155467987, + -0.0063104630, 0.0226001740, 0.0086984634, 0.0262088776, + 0.0173921585, 0.0360507965, 0.0366659164, 0.0215339661, + 0.0412178040, 0.1047391891, 0.1258172989, 0.0609836578 } }, + { { 0.1495609283, 0.3275766373, 0.8598194122, 0.6847562790, + 0.7550849915, 0.5662431717, 0.6930398941, 0.7526245117, + 0.7300291061, 0.7284708023, 0.6608896255, 0.5224056244, + 0.4273900986, 0.5757160187, 0.4625749588, 0.5123586655 }, + { -0.0352210999, -0.0428895950, 0.3110914230, 0.2699604034, + 0.3307752609, 0.2059469223, 0.2332172394, 0.3204412460, + 0.2846412659, 0.3354911804, 0.2448635101, 0.1514062881, + 0.1062564850, 0.2613077164, 0.2123441696, 0.3000602722 } }, + { { 0.6218910217, 0.6033554077, 0.4551525116, 0.3161764145, + 0.2864866257, 0.6195125580, 0.7577505112, 1.0062179565, + 0.8485012054, 0.6777849197, 0.7455301285, 0.3630485535, + 0.2327661514, 0.5563192368, 0.4448595047, 0.3806819916 }, + { 0.2624969482, 0.2679510117, 0.1839666367, 0.0335903168, + 0.0294075012, 0.2902593613, 0.4959144592, 0.7905979156, + 0.5748548508, 0.3753919601, 0.4855394363, 0.1089630127, + 0.0362968445, 0.3632535934, 0.2681150436, 0.2735691071 } }, + { { 0.7064495087, 0.4431781769, 0.7628355026, 0.7271585464, + 0.7812070847, 0.7806739807, 0.8909854889, 0.8958654404, + 0.9126787186, 0.9038209915, 0.9246120453, 0.9624624252, + 0.9732475281, 0.7420034409, 0.5060844421, 0.5189199448 }, + { 0.3457021713, -0.0149221420, 0.3174476624, 0.3580865860, + 0.4243965149, 0.4275541306, 0.5887155533, 0.6478490829, + 0.6320610046, 0.6627349854, 0.6868886948, 0.7396659851, + 0.7551259995, 0.5275316238, 0.3075237274, 0.3806819916 } }, + { { 0.4376831055, 0.4904603958, 0.6262788773, 0.5901098251, + 0.4176712036, 0.0221490860, -0.1612796783, -0.2236118317, + -0.1087894440, -0.0022506714, 0.1051902771, 0.3307752609, + 0.4167690277, 0.4997692108, 0.4645843506, 0.5228567123 }, + { 0.1228237152, 0.1671123505, 0.2931299210, 0.2549924850, + 0.1435737610, -0.1124801636, -0.2181987762, -0.2723293304, + -0.1573429108, -0.0837745667, -0.0325555801, 0.1024427414, + 0.1938495636, 0.2825498581, 0.2247285843, 0.2879629135 } }, + { { 0.6100807190, 0.7900238037, 0.9581155777, 0.8999662399, + 0.9277286530, 0.9720993042, 0.9966220856, 0.9630365372, + 0.9571723938, 0.8992280960, 0.8370189667, 0.7417984009, + 0.7174396515, 0.6122951508, 0.6746683121, 0.7030458450 }, + { 0.0859165192, 0.0914115906, 0.6077432632, 0.5471334457, + 0.5943746567, 0.6805324554, 0.6680250168, 0.6033554077, + 0.6302976608, 0.4874258041, 0.3647298813, 0.2770137787, + 0.2544183731, 0.2608156204, 0.3331537247, 0.4950942993 } }, + { { 0.4051227570, 1.1022176743, 0.8262338638, 0.6573219299, + 0.5948667526, 0.5426225662, 0.4987850189, 0.4370269775, + 0.4421119690, 0.3837165833, 0.3728494644, 0.3706760406, + 0.4169740677, 0.3559951782, 0.2994041443, 0.3896217346 }, + { 0.0716867447, 0.9253911972, 0.2780799866, 0.2460117340, + 0.1675224304, 0.1527595520, 0.1278266907, 0.1226596832, + 0.1165084839, 0.0982189178, 0.0952253342, 0.1113414764, + 0.1498889923, 0.0940361023, 0.0802984238, 0.1560811996 } }, + { { 0.7024717331, 0.7363853455, 0.9629545212, 0.9635286331, + 1.0819597244, 1.1529855728, 1.2984409332, 1.2693252563, + 1.2848672867, 1.2877378464, 1.2133083344, 1.0696573257, + 1.0864706039, 0.9851808548, 0.8312368393, 0.8047866821 }, + { 0.3001422882, 0.2273120880, 0.6279602051, 0.6936140060, + 0.8097076416, 0.9440498352, 1.1028738022, 1.1766471863, + 1.1199741364, 1.1608181000, 1.0665817261, 0.8872537613, + 0.9082908630, 0.7602519989, 0.6542053223, 0.7317514420 } }, + { { 0.0643463135, -0.6808919907, 0.2889881134, 0.6142225266, + 0.6356697083, 0.6825828552, 0.6259508133, 0.4945611954, + 0.5866651535, 0.6357517242, 0.5208883286, 0.4207878113, + 0.5125637054, 0.3758020401, 0.5424175262, 0.6172571182 }, + { -0.0636806488, -0.7585611343, 0.0850553513, 0.2996912003, + 0.3620643616, 0.4444084167, 0.4597454071, 0.3120756149, + 0.4016780853, 0.5026807785, 0.4111919403, 0.3183498383, + 0.3666572571, 0.1829824448, 0.3269205093, 0.4095926285 } }, + { { 0.9277286530, 0.9651279449, 0.9602069855, 0.9327726364, + 0.9208393097, 0.8868436813, 0.9011554718, 0.8569488525, + 0.9015245438, 0.8969726562, 0.9367094040, 0.9445009232, + 0.8617057800, 0.8215589523, 0.8333692551, 0.7939195633 }, + { 0.1719102859, 0.1142530441, 0.1245460510, 0.1646108627, + 0.1408672333, 0.0949792862, 0.0271930695, 0.0265779495, + -0.0064334869, -0.0109033585, 0.0152187347, 0.0252656937, + 0.0166950226, 0.0736141205, 0.1205682755, 0.1895437241 } }, + { { 0.5964250565, 0.6065130234, 0.7228116989, 0.7348270416, + 0.0718097687, 0.2369899750, 0.2456426620, 0.4961194992, + 0.6410417557, 0.6765956879, 0.6771287918, 0.7285938263, + 0.6706905365, 0.5105543137, 0.5068635941, 0.5430326462 }, + { 0.2782440186, 0.2620048523, 0.4424400330, 0.4124631882, + -0.1158838272, 0.0186223984, 0.0059919357, 0.1853609085, + 0.3568563461, 0.3791646957, 0.4100847244, 0.4654865265, + 0.4614677429, 0.3209743500, 0.3199081421, 0.3836755753 } }, + { { 0.8051557541, 0.8506336212, 0.9544658661, 0.5584516525, + 0.5874032974, 0.5727224350, 0.6177902222, 0.7659521103, + 0.9526205063, 1.0424280167, 1.0705595016, 1.0042905807, + 0.6005258560, 0.3886785507, 0.4739751816, 0.6542463303 }, + { 0.4775428772, 0.5541868210, 0.7128057480, 0.2146816254, + 0.2502765656, 0.2488822937, 0.3009214401, 0.4667987823, + 0.6929988861, 0.8599834442, 0.8784780502, 0.7463912964, + 0.3217535019, 0.1274986267, 0.2767267227, 0.5119485855 } }, + { { 0.5978193283, 0.5092830658, 1.0738401413, 0.7688636780, + 0.8214769363, 0.7682075500, 0.4970626831, 0.2783260345, + 0.2652854919, 0.3625154495, 0.5700569153, 0.5044031143, + 0.4003248215, 0.5162544250, 0.5727634430, 0.5538587570 }, + { 0.2752094269, 0.1747808456, 0.8557186127, 0.4280872345, + 0.5143680573, 0.4139804840, 0.1810960770, 0.0109539032, + 0.0317039490, 0.0842351913, 0.3129367828, 0.2614717484, + 0.1564092636, 0.2352676392, 0.3249931335, 0.3505821228 } }, + { { 0.7093610764, 0.7587757111, 1.8517618179, 1.0092525482, + 0.8078622818, 0.8792982101, 0.8210668564, 0.8600654602, + 0.6913585663, 0.6436662674, 0.6216859818, 0.6123771667, + 0.5940465927, 0.5910940170, 0.6505966187, 0.5801038742 }, + { 0.3370904922, 0.4681930542, 1.9236078262, 0.8053607941, + 0.5321245193, 0.6342344284, 0.5054693222, 0.5788326263, + 0.4400615692, 0.4086904526, 0.3924102783, 0.4220180511, + 0.3835115433, 0.4230432510, 0.5190839767, 0.3990535736 } }, + { { 0.6277141571, 1.1122236252, 1.0259838104, 0.9486427307, + 0.9184608459, 0.9059944153, 0.9080038071, 0.8282022476, + 0.8440313339, 0.7887935638, 0.7468013763, 0.6746683121, + 0.6319379807, 0.6246795654, 0.7263793945, 0.7349090576 }, + { 0.2427721024, 1.0851583481, 0.6180362701, 0.5837125778, + 0.4324750900, 0.4684801102, 0.3745307922, 0.3027257919, + 0.3646888733, 0.2409267426, 0.2158298492, 0.2052907944, + 0.2100887299, 0.2276401520, 0.3409452438, 0.4045896530 } }, + { { 0.8391513824, 0.8713426590, 1.1366233826, 1.1440868378, + 1.1443738937, 1.0877418518, 1.0516138077, 1.0099496841, + 0.9216184616, 0.8990640640, 0.9001302719, 0.8993101120, + 0.8055248260, 0.8150796890, 0.7272815704, 0.7196130753 }, + { 0.4634771347, 0.5807189941, 1.1287908554, 1.1066875458, + 1.0765056610, 0.9287538528, 0.8956193924, 0.8026132584, + 0.6725769043, 0.5856809616, 0.5527515411, 0.5183868408, + 0.4529380798, 0.5074377060, 0.4632720947, 0.5554990768 } }, +}; + +static const float wmavoice_lsp16_intercoeff_b[32][2][16] = { + { { 0.5431776047, -0.1212130189, -0.2471650839, 0.0683670044, + 0.1418520808, 0.2518971562, 0.3708084226, 0.4141484499, + 0.5712364912, 0.5852659345, 0.5670641661, 0.6401320100, + 0.6447737217, 0.6726239920, 0.4994724989, 0.5574678183 }, + { 0.2040718794, -0.1271064281, -0.2266163826, -0.0406349897, + -0.0145058036, 0.0283126831, 0.0851084590, 0.0913147926, + 0.1307432652, 0.1926501393, 0.2310355306, 0.2828245163, + 0.3171940446, 0.4424681067, 0.2960716486, 0.3510941863 } }, + { { 0.8073900938, 0.0403081179, 0.5392660499, 0.6928597689, + 0.6499369740, 0.7328097820, 0.7755761147, 0.7766191959, + 0.8820225596, 0.8423333168, 0.8898978233, 0.8488525748, + 0.8654375672, 0.6728326082, 0.6169234514, 0.6755967736 }, + { 0.3653843999, -0.0846008658, -0.0224332213, 0.1120721102, + 0.1020585299, 0.1741876006, 0.2129902244, 0.2160151601, + 0.3619422317, 0.4185815454, 0.5455245376, 0.5363975763, + 0.5429168344, 0.3505726457, 0.3296067119, 0.3620986938 } }, + { { 0.1843576431, 0.0179861784, 0.3122915626, 0.3600125313, + 0.2466817498, 0.2172668576, 0.1975526214, 0.1177569032, + 0.1196866035, 0.0849519968, 0.0962694287, 0.1591672301, + 0.2300446033, 0.3082756996, 0.4047607183, 0.3925045133 }, + { -0.0275964737, -0.0794897676, 0.1168181300, 0.1591150761, + 0.0915755630, 0.0460972190, 0.0562151074, 0.0084419847, + -0.0095511675, -0.0408957601, -0.0376100540, -0.0166962743, + 0.0656028390, 0.1226072311, 0.2293144464, 0.2142419219 } }, + { { 0.4781936407, -1.2478972673, 0.4884679914, 0.7755239606, + 0.6785174012, 0.6590117812, 0.6177057624, 0.6427918673, + 0.5402048230, 0.5512614846, 0.6424267888, 0.4229103327, + 0.5106334686, 0.5136062503, 0.4490395188, 0.4753251672 }, + { 0.2852236032, -1.3815159798, 0.1904075146, 0.4874770641, + 0.4593138695, 0.4182686210, 0.4174863100, 0.4604612589, + 0.4089330435, 0.3891666532, 0.4700576067, 0.2383370996, + 0.2801646590, 0.3398289084, 0.2766703367, 0.3374298215 } }, + { { 0.5925153494, 0.3858809471, 1.0754098296, 0.5752002001, + 0.5516265631, 0.4853909016, 0.4719351530, 0.5018194318, + 0.3037382960, 0.5154316425, 0.8809794784, 0.7755761147, + 0.5941321254, 0.3974069953, 0.5925675035, 0.6097261906 }, + { 0.3008176684, 0.0706617832, 0.8484353423, 0.2574254870, + 0.2815728188, 0.1930673718, 0.2523665428, 0.2691601515, + 0.1271967888, 0.2653007507, 0.6473292708, 0.5275835395, + 0.3928174376, 0.2405275702, 0.4008491635, 0.4556109309 } }, + { { 0.7339050174, 0.4290645123, 0.6859754324, 0.6349166036, + 0.8034263849, 0.8509387374, 0.8591269255, 1.1049811840, + 1.3928194642, 1.3423343301, 1.0849018693, 0.8943830729, + 0.8579795361, 0.6920774579, 0.5613272190, 0.4303162098 }, + { 0.4534726143, 0.0901674032, 0.3465046287, 0.3470261693, + 0.5217422843, 0.5874564052, 0.6014336944, 0.9161834717, + 1.2823571563, 1.2193550467, 0.8868207335, 0.6514494419, + 0.6249030232, 0.4453887343, 0.3665317893, 0.2242033482 } }, + { { 0.4293252826, 0.3303368688, 0.6181751490, 0.9884168506, + 0.9915460944, 0.7939864993, 0.3019129038, 0.2443348169, + 0.4543070793, 0.5617444515, 0.4895110726, 0.6600027084, + 0.6290231943, 0.5580936670, 0.5459417701, 0.4647378922 }, + { 0.1409133077, -0.0050137639, 0.2551307082, 0.6764833927, + 0.7112701535, 0.4648943543, 0.0301380754, -0.0235806108, + 0.1018499136, 0.2422486544, 0.2406318784, 0.4000146985, + 0.3713299632, 0.3259559274, 0.3820737004, 0.2888743877 } }, + { { 0.7733334899, 0.8321111202, 1.3098945022, 1.0331128836, + 1.0380675197, 0.9479974508, 0.9740223289, 0.9442945123, + 0.8926619887, 0.8719046712, 0.8640815616, 0.8404036164, + 0.8359183669, 0.7675965428, 0.6895219088, 0.7266034484 }, + { 0.3655408621, 0.4643206596, 1.2171645761, 0.8341451287, + 0.8387868404, 0.6713201404, 0.6814901829, 0.6294404268, + 0.5172048807, 0.5205948949, 0.5408828259, 0.5298783183, + 0.5781729817, 0.5000983477, 0.4727174640, 0.4326109886 } }, + { { 0.8902629018, 0.4598354101, 0.6392975450, 0.4483093619, + 0.6220867038, 0.6323089004, 0.7063676715, 0.3717993498, + 0.6718416810, 0.7876758575, 0.2807383537, 0.3118221760, + 0.6703813672, 0.7662405372, 0.7122610807, 0.7851724625 }, + { 0.6301705837, 0.1221378446, 0.3532846570, 0.1412783861, + 0.3471826315, 0.3435318470, 0.4466925859, 0.1390357614, + 0.4092981219, 0.5406742096, 0.0690450072, 0.0829179883, + 0.4625995755, 0.5700891018, 0.5542864203, 0.6545265317 } }, + { { -0.1100520492, 0.3803526163, 0.8075987101, 0.6903563738, + 0.8012359142, 0.7835035324, 0.8195941448, 0.8381088376, + 0.8033220768, 0.7511680126, 0.6393496990, 0.6096218824, + 0.6934856176, 0.6690253615, 0.6401841640, 0.5600233674 }, + { -0.1776958704, -0.0293175578, 0.1520742774, 0.1746048331, + 0.2222214937, 0.3052507639, 0.2977927327, 0.3797789216, + 0.3395681381, 0.2976884246, 0.2516885400, 0.2403711081, + 0.3567789793, 0.3302847147, 0.3368039727, 0.3310148716 } }, + { { 0.5587195158, 0.4676063657, 0.1392965317, -0.0990996957, + -0.0816280842, -0.1146416068, -0.0116894841, 0.0521992445, + 0.1626615524, 0.2923687100, 0.4029874802, 0.4528989196, + 0.4694839120, 0.5058352947, 0.5369191170, 0.5105291605 }, + { 0.2193530202, 0.1211469173, 0.0179861784, -0.2022604346, + -0.1409794092, -0.2121175528, -0.1152674556, -0.0594626069, + -0.0122110248, 0.0274260640, 0.1414870024, 0.2044369578, + 0.2167974710, 0.2615978122, 0.3348221183, 0.3707562685 } }, + { { 0.5948622823, 0.7065241337, 0.9414781928, 0.9340723157, + 0.8835350275, 0.9730835557, 0.8503650427, 0.8902629018, + 0.8746688366, 0.6910865307, 0.6404449344, 0.6976057887, + 0.5916287303, 0.6022160053, 0.7729684114, 0.6096740365 }, + { 0.1262058616, 0.1300652623, 0.6594290137, 0.6535877585, + 0.5639349222, 0.6982316375, 0.4828875065, 0.5577285886, + 0.4591052532, 0.2964367270, 0.2695252299, 0.3324751854, + 0.2860580683, 0.2902825475, 0.4623388052, 0.3369604349 } }, + { { 0.8821268678, 0.8539636731, 0.2898653150, 0.7478301525, + 0.5109463930, 0.8577187657, 0.4884679914, 0.7846509218, + 0.7684310079, 0.7032384276, 0.6691296697, 0.8593355417, + 0.9383489490, 0.9808023572, 0.6804992557, 0.6403927803 }, + { 0.5590324402, 0.4209806323, 0.0259135962, 0.4318808317, + 0.2104346752, 0.5453680754, 0.1783599257, 0.4467447400, + 0.4352708459, 0.4089330435, 0.3994410038, 0.5984609127, + 0.6872792840, 0.7321317792, 0.4408513308, 0.4542027712 } }, + { { 0.6371070743, 0.6311093569, 0.7152860165, 0.6929640770, + 0.2292101383, 0.3234525323, 0.9644259810, 0.9881039262, + 0.8722697496, 0.4370440841, 0.4051779509, 0.4944135547, + 0.5392660499, 0.5969484448, 0.4268740416, 0.4990552664 }, + { 0.4233797193, 0.3647063971, 0.4345406890, 0.4180078506, + -0.0006328225, 0.0586141944, 0.7620160580, 0.8152132034, + 0.6707985997, 0.2095480561, 0.2178405523, 0.2776612639, + 0.3142212629, 0.3808741570, 0.2676998377, 0.2804775834 } }, + { { 0.4509170651, 0.9490405321, 0.8557890654, 0.8271043301, + 0.6915559173, 0.7321839333, 0.6257896423, 0.6274064183, + 0.5238284469, 0.5194996595, 0.4116972089, 0.3382642865, + 0.3755022883, 0.4867990613, 0.5686287880, 0.5106856227 }, + { 0.0989292860, 0.6244857907, 0.4700576067, 0.3905226588, + 0.2630059719, 0.3009741306, 0.2150763869, 0.2067838907, + 0.1533781290, 0.1815934777, 0.1023714542, 0.0373874903, + 0.0897501707, 0.1849313378, 0.2852757573, 0.2625887394 } }, + { { 0.9954054952, 0.9554033279, 0.8237664700, 0.9780903459, + 0.7261862159, 0.7884581685, 0.7933084965, 0.7393290401, + 0.8783196211, 1.0409359932, 1.0217954516, 0.9159227014, + 0.8698185086, 0.7057939768, 0.7662926912, 0.7339571714 }, + { 0.7913266420, 0.6739278436, 0.5061482191, 0.7058982849, + 0.3480692506, 0.4338105321, 0.4428853393, 0.3758152127, + 0.5962182879, 0.7925261855, 0.7968549728, 0.6629754901, + 0.6325175166, 0.4598354101, 0.5310778618, 0.5518873334 } }, + { { 0.4638512731, 0.0604917407, 0.1897295117, 0.3403504491, + 0.4708399177, 0.5241413713, 0.6061275601, 0.6446694136, + 0.7313494682, 0.7208143473, 0.6268848777, 0.6081094146, + 0.4913364649, 0.3529717326, 0.4954566360, 0.5767126679 }, + { 0.1353849769, -0.0274400115, 0.0002537966, 0.0272174478, + 0.0555371046, 0.0652899146, 0.1010676026, 0.1073260903, + 0.1568724513, 0.2207611799, 0.1434167027, 0.2262373567, + 0.1177047491, 0.0162650943, 0.2529402375, 0.4087765813 } }, + { { 0.9700064659, 0.9917025566, 0.9159227014, 0.9309430718, + 0.8991290927, 0.9314124584, 0.9059612751, 0.9473194480, + 0.9604622722, 0.9377752542, 0.9197821021, 0.8869771957, + 0.8506779671, 0.8594920039, 0.8320589662, 0.8739908338 }, + { 0.2892394662, 0.0551198721, 0.0892807841, 0.1158793569, + 0.0905846357, 0.0738953352, 0.0395258069, 0.0240360498, + 0.0477139950, 0.0751470327, 0.1171310544, 0.1555164456, + 0.1384620667, 0.1818542480, 0.2104868293, 0.1288135648 } }, + { { 0.4101847410, 0.3326316476, 0.4666675925, 0.5077128410, + 0.5892296433, 0.4272912741, 0.0603352785, -0.8668596745, + -1.1103670001, -0.0900248885, 0.1626615524, 0.1487885714, + 0.4130010605, 0.5119373202, 0.5820323825, 0.5486016273 }, + { 0.0383262634, 0.1300652623, 0.2295230627, 0.2706204653, + 0.3722165823, 0.1698066592, -0.0934670568, -0.8677462935, + -1.0724509954, -0.2164463401, -0.0056917667, -0.0301520228, + 0.1299088001, 0.2579991817, 0.3482257128, 0.2469425201 } }, + { { 0.6031547785, 0.5515222549, 0.4292209744, 0.5027582049, + 0.8167778254, 1.0925685167, 0.9878953099, 0.7019345760, + 0.2509583831, 0.2475162148, 0.5660732388, 0.5145971775, + 0.4824181199, 0.5970005989, 0.5996604562, 0.5384315848 }, + { 0.3677313328, 0.2650399804, 0.1585935354, 0.2213348746, + 0.5566333532, 0.8425940871, 0.7604514360, 0.4523773789, + 0.0681062341, 0.0737388730, 0.3169854283, 0.2868403792, + 0.2661873698, 0.3635068536, 0.4300554395, 0.3743027449 } }, + { { 0.5017672777, 0.6634970307, 0.6869142056, 0.7066284418, + 0.5669598579, 0.0621085167, 0.0634645224, 0.2321307659, + 0.8322675824, 0.9855483770, 0.8296598792, 0.6140028238, + 0.5462546945, 0.6730412245, 0.6856103539, 0.5975221395 }, + { 0.2680649161, 0.3324230313, 0.3688787222, 0.3886451125, + 0.2774004936, -0.1695076823, -0.1353467703, 0.0159000158, + 0.5895425677, 0.7586781979, 0.5639870763, 0.3687744141, + 0.3401418328, 0.4477356672, 0.4782979488, 0.4034568667 } }, + { { 0.8838479519, 0.9025712609, 0.7326533198, 0.8124490380, + 0.8956347704, 1.1007045507, 1.2731780410, 1.2029786706, + 1.0839109421, 0.9664078355, 0.7356782556, 0.6942157745, + 0.6917645335, 0.6383587718, 0.6503020525, 0.5989302993 }, + { 0.5576764345, 0.4596789479, 0.3790487647, 0.5514179468, + 0.7333834767, 0.9612445831, 1.1976589561, 1.1094664335, + 0.8868207335, 0.6789346337, 0.4643206596, 0.4029353261, + 0.4384522438, 0.3871847987, 0.4326109886, 0.3691916466 } }, + { { 0.8520861268, 0.8413423896, 0.7238392830, 0.9103943706, + 0.7072542906, 0.6479029655, 0.4557673931, 0.1908247471, + -0.0569070578, -0.1013423204, 0.2517406940, 0.4854952097, + 0.5820845366, 0.5886037946, 0.6177579165, 0.6226603985 }, + { 0.6160889864, 0.4592095613, 0.4752208591, 0.6685559750, + 0.4326109886, 0.4077335000, 0.2314006090, 0.0173603296, + -0.2208272815, -0.3014574647, 0.0321199298, 0.2559130192, + 0.3603254557, 0.3466089368, 0.4072119594, 0.4776199460 } }, + { { 0.7083495259, 0.9001721740, 0.6795083284, 1.2743254304, + 1.3672639728, 1.2563322783, 0.8557369113, 0.8287732601, + 0.7942472696, 0.8006622195, 0.7034991980, 0.5479236245, + 0.6391932368, 0.6248508692, 0.5495925546, 0.4719351530 }, + { 0.4000146985, 0.6493632793, 0.4583229423, 1.1484255195, + 1.2521599531, 1.1232351065, 0.6150459051, 0.5347808003, + 0.4726653099, 0.5269576907, 0.4278128147, 0.2745841742, + 0.3868718743, 0.4183729291, 0.3474434018, 0.3150035739 } }, + { { 0.9070043564, 0.7648323774, 0.4281778932, 0.5475063920, + 0.4134704471, 0.4706834555, 0.4549329281, 0.4648422003, + 0.4572798610, 0.4823138118, 0.4666154385, 0.4841913581, + 0.4018922448, 0.4297946692, 0.4646857381, 0.6091003418 }, + { 0.4925360084, 0.2065231204, 0.0948612690, 0.1716842055, + 0.0992422104, 0.1332988143, 0.1255800128, 0.1257364750, + 0.0955392718, 0.1118634939, 0.1372103691, 0.1525958180, + 0.0902717113, 0.1591672301, 0.2335910797, 0.3767018318 } }, + { { 0.3185500503, 0.8677845001, 0.7776622772, 0.8160476685, + 0.8624126315, 0.8057211637, 0.8852561116, 0.8471314907, + 0.9145145416, 0.8945916891, 0.8638729453, 0.8531292081, + 0.7425104380, 0.6215651631, 0.6501455903, 0.6341864467 }, + { -0.0499705672, 0.0687842369, 0.3051464558, 0.3368039727, + 0.4942049384, 0.3823344707, 0.5683158636, 0.5044271350, + 0.6278236508, 0.5777035952, 0.5745221972, 0.5502184033, + 0.4244228005, 0.3163595796, 0.3525545001, 0.3582914472 } }, + { { 0.3200625181, 0.9415303469, 0.6067534089, 0.3568832874, + 0.1600538492, 0.2938811779, 0.2037589550, 0.3017564416, + 0.2572168708, 0.4796018004, 0.6938506961, 0.6847758889, + 0.7232134342, 0.6111343503, 0.5159531832, 0.4856516719 }, + { 0.0680540800, 0.6285016537, 0.2514277697, 0.0790064335, + -0.0687981844, 0.0521992445, -0.0055874586, 0.0537117124, + 0.0188206434, 0.1883213520, 0.4493002892, 0.4300554395, + 0.4750122428, 0.3658016324, 0.3119786382, 0.2818335891 } }, + { { 0.6864969730, 1.0815640092, 0.9838794470, 0.8845259547, + 0.9438772798, 0.8888025880, 0.8178730607, 0.8581881523, + 0.7128347754, 0.7120524645, 0.7345308661, 0.7945601940, + 0.7854853868, 0.8261655569, 0.6941114664, 0.6646444201 }, + { 0.2847542167, 0.9535257816, 0.6691818237, 0.5026538968, + 0.5945493579, 0.4125838280, 0.3886451125, 0.3740941286, + 0.2453778982, 0.2928902507, 0.3219922185, 0.4065861106, + 0.3838469386, 0.4289602041, 0.3910441995, 0.3821780086 } }, + { { 1.1335094571, 1.0390062928, 0.7019867301, 0.6203134656, + 0.6951545477, 0.4863818288, 0.6171320677, 0.6247465611, + 0.5907421112, 0.6711115241, 0.7322882414, 0.7042293549, + 0.5635698438, 0.6174449921, 0.6727283001, 0.6431047916 }, + { 1.0146503448, 0.7762541175, 0.2200310230, 0.2459515929, + 0.2703596950, 0.1376276016, 0.2522100806, 0.2622758150, + 0.2389107943, 0.2956544161, 0.3799875379, 0.3653843999, + 0.2561216354, 0.2842326760, 0.4034568667, 0.3700782657 } }, + { { 0.6342907548, 0.9627570510, 0.5214815140, -0.0226939917, + 0.5616401434, 0.7231091261, 0.7417802811, 0.9092991352, + 0.9739701748, 0.7804785967, 0.6771092415, 0.6352295280, + 0.4660417438, 0.5869870186, 0.6692339778, 0.5986173749 }, + { 0.3988673091, 0.6997441053, 0.2316613793, -0.2566571236, + 0.2685343027, 0.4484136701, 0.4490395188, 0.6886874437, + 0.7703085542, 0.5847443938, 0.4539941549, 0.4098196626, + 0.2579991817, 0.3376384377, 0.4754816294, 0.5095382333 } }, + { { 0.4443456531, 2.0296727419, 0.6569256186, 0.6439914107, + 0.6436263323, 0.5507399440, 0.6095175743, 0.6066491008, + 0.5347808003, 0.2529402375, 0.4443978071, 0.7000570297, + 0.8259569407, 0.5927761197, 0.5078171492, 0.4418422580 }, + { 0.2430831194, 1.9133691788, 0.3723730445, 0.3764410615, + 0.3874977231, 0.3212099075, 0.3832210898, 0.4474227428, + 0.3644977808, 0.0814055204, 0.2752621770, 0.4647378922, + 0.6619845629, 0.4304205179, 0.3143777251, 0.2705683112 } }, + { { 0.9740744829, 1.0730628967, 0.9743352532, 0.9098728299, + 0.9453375936, 0.9661470652, 0.9270836711, 0.9643738270, + 0.9989519715, 0.9627048969, 0.9348546267, 0.9865393043, + 0.9399657249, 0.9752218723, 0.8440544009, 0.8819182515 }, + { 0.9258319736, 1.0357205868, 0.8463491797, 0.8108844161, + 0.8391519189, 0.8566235304, 0.8305986524, 0.8880724311, + 0.9181653261, 0.8670021892, 0.8305986524, 0.8995984793, + 0.8300249577, 0.8711223602, 0.7195626497, 0.8138571978 } }, +}; + +static const double wmavoice_mean_lsf10[2][10] = { + { 0.2235394066, 0.4097484909, 0.7025292732, 1.1077160169, + 1.3939179044, 1.6741291716, 1.9552949226, 2.2199793918, + 2.5103400247, 2.7829212906 }, + { 0.1493683393, 0.3714357373, 0.7702730245, 1.0609411394, + 1.3270362536, 1.5806033119, 1.8398507524, 2.1116740248, + 2.3823505771, 2.6865718527 } +}; + +static const double wmavoice_mean_lsf16[2][16] = { + { 0.0999206754, 0.2345933590, 0.4621011210, 0.6772546160, + 0.8346396060, 1.0067495130, 1.1571691668, 1.3292508688, + 1.4941465650, 1.6600755584, 1.8461284908, 2.0529487333, + 2.2690810112, 2.4949894820, 2.7172752965, 2.9164840903 }, + { 0.0918298402, 0.2475621892, 0.4782937721, 0.6284774045, + 0.7861951264, 0.9303736000, 1.0940441024, 1.2521029300, + 1.4434732098, 1.6551410742, 1.8917962963, 2.0967280403, + 2.2981430375, 2.4826173497, 2.6827972461, 2.8811350800 } +}; + +static const float wmavoice_std_codebook[1000] = { + -0.185013, -0.150405, -0.707267, -0.284100, 0.882898, + -0.788627, 0.061005, 0.374431, 0.053843, -0.909826, + 0.543602, 0.219326, 0.285698, 0.154709, -0.455005, + 0.426276, -0.868852, -0.952324, -0.550001, 0.813814, + -0.352815, 0.242122, 0.820495, -0.189574, -0.449538, + 0.499132, -0.247783, 0.598159, 0.732040, -0.564406, + -0.631788, -0.452973, 0.285189, -0.339055, 0.262927, + 0.168087, -0.127682, -0.676067, -0.457481, 0.926161, + -0.585893, -0.913880, 0.145487, 0.699804, 0.240829, + 0.690482, 0.126081, 0.371977, 0.738158, 0.576080, + 0.185791, -0.614657, -0.181799, 0.006285, 0.195768, + 0.368663, -0.494583, 0.947985, -0.033178, -0.762543, + -0.616421, 0.335034, -0.215516, 0.668769, 0.995979, + -0.952588, -0.163144, -0.131704, -0.628655, 0.379374, + -0.205543, -0.214549, 0.465494, 0.939944, -0.514744, + -0.293676, 0.630426, 0.611336, -0.921699, 0.368584, + 0.187416, 0.264092, 0.753927, -0.994382, -0.729623, + -0.050304, 0.374280, -0.224205, -0.102319, -0.658897, + 0.013252, 0.281260, 0.676137, 0.797736, -0.049971, + 0.672115, 0.845148, 0.786885, -0.459588, -0.783507, + 0.166259, 0.334869, 0.001944, -0.368247, 0.274813, + 0.487200, 0.338077, -0.094761, 0.098536, 0.416378, + -0.726176, -0.714048, -0.319530, -0.972249, -0.708430, + -0.049153, -0.022553, 0.665850, 0.726642, 0.875127, + -0.993047, -0.260106, 0.156387, 0.683090, -0.462370, + -0.893584, 0.355205, -0.617222, 0.893301, 0.895617, + -0.400729, 0.059559, 0.230486, 0.601215, 0.691313, + -0.494701, 0.088415, 0.029390, 0.410539, -0.813049, + -0.554232, 0.684362, -0.527097, 0.126238, 0.712113, + -0.235528, -0.922915, -0.310440, -0.569678, 0.803727, + -0.435313, -0.562725, -0.456380, 0.721075, -0.879635, + 0.081250, 0.827491, 0.475570, 0.464029, 0.720792, + 0.371187, -0.936700, -0.219649, -0.398327, 0.664515, + -0.528336, 0.106972, -0.247070, 0.501053, -0.482490, + -0.060119, 0.946821, -0.798127, 0.412784, 0.073058, + 0.913986, -0.822744, 0.150143, -0.396453, -0.392421, + -0.046130, 0.168234, 0.044854, 0.497490, -0.110691, + 0.165219, -0.421259, -0.283200, -0.359212, -0.957231, + -0.562409, -0.988025, -0.893931, 0.217942, -0.386352, + 0.770585, 0.689606, 0.720620, -0.476485, 0.190659, + -0.761870, 0.463395, 0.137480, -0.559997, -0.123821, + -0.789461, -0.646011, 0.053435, 0.360682, -0.042464, + 0.661014, -0.685448, -0.874230, -0.294133, 0.812042, + 0.015078, 0.871086, -0.609218, 0.731878, -0.488126, + -0.566448, -0.830530, -0.476150, -0.460379, 0.387412, + 0.137497, -0.689794, 0.077018, -0.141883, -0.166280, + -0.732322, 0.096247, -0.702884, 0.405158, 0.536250, + 0.173295, 0.615696, 0.890239, -0.773270, -0.023622, + -0.152226, 0.887744, 0.290930, -0.026456, -0.406389, + 0.102972, 0.988622, -0.535303, 0.493754, 0.720500, + -0.023428, 0.927306, 0.889970, 0.500421, -0.533073, + 0.277382, -0.362081, -0.222867, -0.645599, 0.496035, + 0.610853, -0.377922, -0.407718, 0.907969, -0.972764, + -0.871468, 0.081264, 0.642933, -0.981230, 0.307994, + -0.380689, -0.133456, 0.195738, 0.910241, 0.840088, + 0.789349, 0.013213, 0.828710, -0.745954, -0.493033, + 0.549210, 0.230618, -0.565727, 0.439180, -0.268961, + -0.098800, -0.283438, 0.368958, 0.678333, 0.070963, + -0.135007, 0.289186, 0.693041, 0.457275, 0.197155, + 0.720277, 0.585807, -0.721581, 0.363210, 0.604577, + 0.586413, 0.982521, -0.528878, -0.217849, 0.892762, + -0.688791, -0.428500, -0.094025, -0.860081, -0.174454, + 0.412942, 0.689129, -0.943836, 0.847215, 0.128309, + -0.212797, -0.251585, 0.844871, -0.843839, -0.573252, + -0.084167, 0.021154, 0.715935, -0.391126, -0.521570, + -0.086910, -0.670848, -0.935763, 0.191509, 0.692361, + 0.668814, -0.222078, 0.674882, -0.860064, 0.560073, + 0.567644, -0.548855, -0.868427, -0.526382, -0.408936, + -0.042881, 0.886560, -0.719807, 0.013283, 0.733775, + 0.408502, 0.800487, -0.517810, 0.253372, 0.956648, + -0.091062, -0.830794, -0.022198, -0.375127, -0.221920, + 0.456232, 0.537963, 0.107232, 0.520469, -0.270529, + -0.200406, 0.189284, 0.507393, -0.525524, 0.329220, + 0.067466, -0.957881, 0.780365, 0.199039, -0.484262, + -0.628570, -0.843843, -0.597703, -0.348377, 0.169441, + -0.863928, -0.939875, -0.030073, -0.381738, 0.313497, + -0.073425, 0.527200, 0.482703, 0.904377, -0.847927, + -0.739217, 0.360609, 0.690035, 0.368015, -0.118921, + -0.580493, -0.832391, -0.929638, 0.926900, -0.357915, + 0.399582, -0.005634, -0.315796, 0.179947, -0.806596, + 0.393360, 0.732931, -0.415833, -0.724526, 0.957347, + -0.892887, 0.475366, 0.173583, -0.418554, -0.302536, + 0.627315, 0.782000, 0.497542, 0.139082, 0.570111, + 0.732375, -0.454643, 0.302218, -0.019505, 0.881778, + -0.057606, 0.273041, 0.414170, -0.503501, -0.079602, + -0.083941, 0.007178, -0.171925, 0.506856, 0.520953, + 0.631684, -0.099784, 0.253885, -0.784149, 0.175691, + 0.211231, -0.677036, -0.348943, -0.615186, -0.095591, + 0.348521, -0.987871, -0.313590, -0.153938, 0.151210, + -0.743479, -0.421562, 0.696567, 0.558739, 0.558933, + 0.578346, -0.498867, -0.168026, -0.007485, -0.002368, + 0.752372, 0.908575, -0.995190, -0.419553, 0.415430, + 0.525763, -0.787869, -0.684353, -0.220353, -0.572018, + 0.491337, 0.990879, -0.249054, -0.857606, -0.624307, + 0.655355, 0.490915, -0.612178, -0.658235, -0.663023, + 0.539032, -0.401714, -0.084585, 0.235599, -0.842975, + -0.525653, -0.186055, -0.341841, 0.306321, 0.806460, + 0.655791, 0.058693, 0.715035, 0.660601, 0.639140, + 0.130465, 0.186363, 0.851271, 0.446112, 0.966011, + -0.720746, -0.062551, 0.956890, 0.030200, 0.079843, + -0.667418, -0.314445, -0.429243, -0.279596, 0.027320, + -0.092266, -0.740564, 0.625606, 0.823149, 0.495035, + 0.782632, -0.702504, -0.691020, -0.559209, 0.603818, + -0.884560, -0.903419, -0.337489, 0.830475, 0.757182, + -0.698349, -0.039060, -0.056455, -0.847078, -0.592948, + -0.090444, -0.567824, 0.344501, -0.133554, 0.462375, + -0.575656, 0.199028, -0.852070, -0.004899, 0.919432, + 0.175251, 0.902835, -0.821132, -0.199143, 0.725984, + 0.673903, -0.416511, -0.976519, 0.982883, 0.024279, + 0.627298, -0.901677, 0.120861, -0.710191, 0.928798, + -0.121958, -0.408540, -0.110261, 0.821588, -0.255618, + 0.296790, -0.268856, 0.176557, -0.358709, 0.597589, + -0.361067, 0.065635, -0.203382, -0.213137, -0.939264, + -0.283951, 0.962113, 0.963571, -0.105083, -0.237030, + 0.689556, -0.431180, 0.346459, 0.713037, -0.448297, + -0.629262, 0.340335, -0.349973, 0.491599, 0.630144, + -0.421175, -0.630359, -0.778396, 0.468564, -0.808771, + -0.034014, -0.234646, -0.077627, -0.857457, 0.406645, + -0.480038, -0.218524, -0.527720, 0.316580, 0.568338, + -0.466984, -0.967371, 0.530452, -0.503413, -0.072454, + -0.706578, -0.813857, 0.496366, 0.639881, 0.899179, + -0.951931, -0.989381, 0.239514, -0.301904, 0.502218, + -0.130341, 0.276921, 0.871860, 0.091262, -0.254515, + -0.936911, -0.942752, 0.510839, -0.014539, -0.800209, + -0.082516, 0.505423, -0.018733, 0.389763, -0.177997, + -0.450395, 0.922779, -0.145368, -0.919943, -0.580634, + 0.782178, -0.626521, -0.394491, 0.278545, -0.986640, + -0.495312, 0.326614, -0.976021, 0.744203, -0.975290, + 0.526197, -0.386139, 0.301631, 0.398057, 0.705124, + -0.952884, 0.461146, 0.762372, 0.557954, -0.553393, + 0.962163, -0.524562, 0.952030, -0.056570, 0.865202, + -0.225967, 0.493035, 0.787981, 0.628665, 0.573093, + -0.792653, 0.410844, 0.946571, -0.187144, -0.310612, + 0.959931, 0.317544, -0.983998, 0.983911, 0.061747, + -0.959287, 0.510108, 0.675608, 0.342344, -0.091835, + 0.380731, 0.389460, -0.630689, 0.143103, -0.052586, + -0.184083, 0.105266, 0.422852, -0.232052, -0.951303, + 0.288054, 0.541981, 0.541732, 0.076035, 0.170646, + 0.114825, 0.283382, -0.418510, 0.061396, -0.903763, + 0.270879, 0.021327, 0.413782, 0.286881, 0.005238, + -0.524472, 0.327594, -0.484654, -0.848864, -0.330063, + 0.423511, 0.531868, -0.940603, 0.792822, -0.325029, + 0.006811, -0.391261, 0.780237, -0.570337, 0.376687, + 0.828934, 0.717717, -0.081333, 0.370666, -0.206248, + -0.910686, -0.514510, -0.922867, -0.329196, 0.546886, + -0.826629, 0.941683, -0.431786, 0.587152, 0.228564, + 0.573452, -0.937320, -0.443843, -0.911202, -0.786184, + 0.226094, 0.512309, 0.745684, 0.285491, 0.305131, + -0.579345, -0.707698, 0.913870, -0.799108, -0.278035, + 0.290556, -0.970174, -0.560318, -0.790776, 0.400492, + 0.233434, -0.701462, 0.885982, 0.310567, -0.030658, + 0.432868, 0.483938, -0.088976, -0.998918, 0.071090, + -0.860412, 0.574534, 0.133770, -0.304255, 0.663332, + 0.347586, 0.921839, 0.175641, 0.093270, 0.207330, + -0.519228, 0.513925, 0.499633, -0.605358, 0.714817, + -0.778402, 0.685198, 0.744643, -0.338720, 0.894422, + 0.145135, 0.894714, -0.807041, 0.031117, 0.205281, + 0.162301, -0.536015, -0.310781, -0.926675, -0.534932, + 0.760308, -0.787088, -0.960398, -0.105922, -0.091343, + 0.702934, -0.758336, -0.169504, -0.121425, 0.334935, + -0.962173, 0.359347, -0.151140, 0.537460, 0.753989, + -0.436323, 0.759058, 0.439187, -0.691680, -0.579662, + 0.333608, 0.453454, -0.684948, 0.526567, -0.515429, + 0.520333, -0.311132, -0.051443, -0.790448, -0.237807, + 0.413625, 0.969861, -0.024895, 0.453226, -0.136061, + 0.883762, 0.156160, 0.105603, -0.285741, -0.965264, + -0.559462, -0.247914, 0.394083, 0.289398, -0.710455, + 0.148072, 0.853074, -0.951397, -0.412742, -0.838606, + -0.531059, 0.920866, 0.614848, -0.216007, 0.447434, + -0.900580, -0.695673, -0.863698, 0.047977, -0.486121, + -0.101505, -0.538399, -0.516261, 0.873600, 0.914828, + 0.347678, 0.757362, 0.070988, -0.546718, -0.528380, + 0.105724, -0.106180, 0.223706, -0.500194, -0.816782, + 0.513251, 0.647878, -0.963708, 0.561854, -0.764864, + -0.802314, -0.969205, -0.843997, 0.812534, -0.185212, + 0.603436, 0.911954, 0.119114, 0.739738, -0.040069, + 0.632993, -0.361767, 0.421532, -0.883268, -0.488168, + 0.336360, 0.464411, -0.730806, -0.592652, 0.917693, + -0.259186, 0.513071, -0.188487, 0.964520, -0.987122, + -0.005270, 0.477771, 0.660756, 0.031023, 0.039625, + 0.895892, 0.228709, 0.070419, -0.948105, 0.041243, + 0.885207, 0.655331, -0.046803, 0.004321, 0.395069, + 0.913128, -0.362686, -0.966698, 0.334661, -0.245954, + -0.454865, -0.328980, -0.781543, -0.185671, 0.078368, + -0.863850, 0.555143, -0.408560, -0.052338, 0.519663, + -0.395683, 0.942393, -0.002565, -0.734927, -0.026585, + -0.962941, -0.839035, -0.797876, 0.107479, -0.787140, + 0.243367, -0.007314, 0.868191, -0.803435, 0.997007, + 0.263261, -0.890307, -0.365679, 0.296563, 0.444354, + 0.388367, 0.841698, -0.884626, 0.606824, -0.343973, + 0.193743, 0.742974, -0.788830, 0.785182, -0.309364, + 0.730833, -0.610500, -0.366971, -0.271732, -0.345427, + 0.606444, -0.234673, -0.184462, 0.808568, 0.872806, + 0.028398, 0.051936, -0.134508, -0.103410, 0.248500, + -0.137501, -0.840150, 0.358194, 0.496819, 0.456413, + -0.197453, -0.114814, 0.298111, -0.082078, -0.507990, + 0.954138, -0.888336, -0.765016, -0.834692, 0.896847, + -0.074380, 0.896141, -0.713654, 0.558649, -0.375591, + -0.059081, 0.165093, 0.389736, 0.756458, -0.026339, + 0.262542, -0.215144, -0.974403, -0.871966, 0.681446 +}; + +static const float wmavoice_gain_silence[256] = { + 0.0000188351, 0.0000249147, 0.0000294447, 0.0000365973, + 0.0000423193, 0.0000464916, 0.0000498295, 0.0000525713, + 0.0000550747, 0.0000574589, 0.0000596046, 0.0000615120, + 0.0000634193, 0.0000649691, 0.0000665188, 0.0000679493, + 0.0000692606, 0.0000704527, 0.0000716448, 0.0000728369, + 0.0000737906, 0.0000747442, 0.0000755787, 0.0000762939, + 0.0000770092, 0.0000778437, 0.0000785589, 0.0000792742, + 0.0000799894, 0.0000807047, 0.0000814199, 0.0000822544, + 0.0000829697, 0.0000838041, 0.0000845194, 0.0000854731, + 0.0000865459, 0.0000876188, 0.0000889301, 0.0000904799, + 0.0000923872, 0.0000950098, 0.0000988245, 0.0001032352, + 0.0001088381, 0.0001147985, 0.0001225471, 0.0001319647, + 0.0001431704, 0.0001568794, 0.0001744032, 0.0001952648, + 0.0002206564, 0.0002535582, 0.0002965927, 0.0003464222, + 0.0004109144, 0.0004891157, 0.0005909204, 0.0007261038, + 0.0008867979, 0.0010721684, 0.0012696981, 0.0015079975, + 0.0017461777, 0.0019979477, 0.0022052526, 0.0023679733, + 0.0025173426, 0.0026556253, 0.0027927160, 0.0029264688, + 0.0030447245, 0.0031807423, 0.0033060312, 0.0034313202, + 0.0035454035, 0.0036598444, 0.0037686825, 0.0038731098, + 0.0039769411, 0.0040702820, 0.0041661263, 0.0042562485, + 0.0043400526, 0.0044249296, 0.0045082569, 0.0045900345, + 0.0046693087, 0.0047430992, 0.0048171282, 0.0048881769, + 0.0049589872, 0.0050252676, 0.0050880909, 0.0051497221, + 0.0052082539, 0.0052671432, 0.0053246021, 0.0053800344, + 0.0054348707, 0.0054861307, 0.0055367947, 0.0055862665, + 0.0056355000, 0.0056805611, 0.0057252645, 0.0057705641, + 0.0058110952, 0.0058538914, 0.0058966875, 0.0059366226, + 0.0059723854, 0.0060091019, 0.0060437918, 0.0060794353, + 0.0061159134, 0.0061485767, 0.0061824322, 0.0062153339, + 0.0062497854, 0.0062820911, 0.0063197613, 0.0063550472, + 0.0063927174, 0.0064336061, 0.0064769983, 0.0065194368, + 0.0065603256, 0.0066006184, 0.0066410303, 0.0066826344, + 0.0067234039, 0.0067654848, 0.0068060160, 0.0068466663, + 0.0068866014, 0.0069231987, 0.0069609880, 0.0069983006, + 0.0070366859, 0.0070750713, 0.0071122646, 0.0071535110, + 0.0071973801, 0.0072410107, 0.0072846413, 0.0073343515, + 0.0073832273, 0.0074360371, 0.0074878931, 0.0075426102, + 0.0076007843, 0.0076560974, 0.0077134371, 0.0077683926, + 0.0078265667, 0.0078855753, 0.0079488754, 0.0080170631, + 0.0080827475, 0.0081528425, 0.0082212687, 0.0082877874, + 0.0083510876, 0.0084129572, 0.0084775686, 0.0085455179, + 0.0086110830, 0.0086781979, 0.0087503195, 0.0088242292, + 0.0089002848, 0.0089734793, 0.0090423822, 0.0091133118, + 0.0091816187, 0.0092473030, 0.0093164444, 0.0093911886, + 0.0094678402, 0.0095427036, 0.0096175671, 0.0096931458, + 0.0097666979, 0.0098397732, 0.0099166632, 0.0099946260, + 0.0100749731, 0.0101612806, 0.0102528334, 0.0103493929, + 0.0104434490, 0.0105448961, 0.0106583834, 0.0107737780, + 0.0108981133, 0.0110142231, 0.0111318827, 0.0112472773, + 0.0113576651, 0.0114786625, 0.0116028786, 0.0117331743, + 0.0118676424, 0.0120122433, 0.0121580362, 0.0123010874, + 0.0124633312, 0.0126402378, 0.0128232241, 0.0130140781, + 0.0132108927, 0.0134289265, 0.0136625767, 0.0138912201, + 0.0141364336, 0.0144006014, 0.0146615505, 0.0149335861, + 0.0152134895, 0.0155050755, 0.0158376694, 0.0162067413, + 0.0165973902, 0.0169926882, 0.0174319744, 0.0179271698, + 0.0184448957, 0.0190744400, 0.0197248459, 0.0204203129, + 0.0212460756, 0.0221523046, 0.0231562853, 0.0243031979, + 0.0256397724, 0.0271918774, 0.0289602280, 0.0310072899, + 0.0333702564, 0.0363805294, 0.0401413441, 0.0443998575, + 0.0498176813, 0.0562580824, 0.0640066862, 0.0732775927, + 0.0836604834, 0.0962959528, 0.1122496128, 0.1335854530, + 0.1608980894, 0.1990102530, 0.2616490126, 0.3926030397 +}; + +static const float wmavoice_gain_universal[64] = { + 0.0000000000, 0.0000000000, 0.0000015497, 0.0000015497, + 0.0000095367, 0.0000164509, 0.0000379086, 0.0000494719, + 0.0000799894, 0.0001058578, 0.0001349449, 0.0001627207, + 0.0001972914, 0.0002325773, 0.0002671480, 0.0003106594, + 0.0003589392, 0.0004127026, 0.0004582405, 0.0005071163, + 0.0005759001, 0.0006588697, 0.0007554293, 0.0008602142, + 0.0009772778, 0.0011068583, 0.0012603998, 0.0013889074, + 0.0015437603, 0.0016924143, 0.0018980503, 0.0021264553, + 0.0023632050, 0.0025693178, 0.0028522015, 0.0031896830, + 0.0034654140, 0.0037885904, 0.0041683912, 0.0046081543, + 0.0050576925, 0.0055632591, 0.0061818361, 0.0068151951, + 0.0073953867, 0.0081818104, 0.0091186762, 0.0102789402, + 0.0119919777, 0.0134155750, 0.0154829025, 0.0173798800, + 0.0199711323, 0.0229473114, 0.0268185139, 0.0319474936, + 0.0393068790, 0.0460114479, 0.0523469448, 0.0637906790, + 0.0845471621, 0.1105458736, 0.1499300003, 0.2219169140 +}; + +static const float wmavoice_gain_codebook_acb[128] = { + 0.05, 0.14, 0.16, 0.05, 0.17, 0.25, 0.07, 0.21, + 0.12, 0.22, 0.23, 0.13, 0.24, 0.32, 0.14, 0.29, + 0.31, 0.41, 0.43, 0.32, 0.43, 0.51, 0.34, 0.48, + 0.38, 0.47, 0.49, 0.38, 0.49, 0.57, 0.40, 0.54, + 0.49, 0.59, 0.61, 0.50, 0.61, 0.69, 0.52, 0.66, + 0.56, 0.65, 0.67, 0.56, 0.67, 0.75, 0.58, 0.72, + 0.65, 0.74, 0.76, 0.65, 0.76, 0.84, 0.67, 0.81, + 0.71, 0.80, 0.82, 0.71, 0.82, 0.90, 0.73, 0.87, + 0.81, 0.90, 0.92, 0.81, 0.93, 1.01, 0.83, 0.97, + 0.87, 0.96, 0.98, 0.87, 0.98, 1.06, 0.89, 1.03, + 0.92, 1.02, 1.04, 0.93, 1.04, 1.12, 0.95, 1.09, + 0.93, 1.02, 1.04, 0.93, 1.04, 1.12, 0.95, 1.09, + 0.94, 1.04, 1.05, 0.10, 1.06, 1.14, 0.96, 1.11, + 0.98, 1.08, 1.10, 0.99, 1.10, 1.18, 1.01, 1.15, + 1.06, 1.15, 1.17, 1.06, 1.17, 1.25, 1.08, 1.22, + 1.16, 1.25, 1.27, 1.16, 1.28, 1.36, 1.18, 1.32 +}; + +static const float wmavoice_gain_codebook_fcb[128] = { + -0.8439700703 /* log(0.430) */, -0.6143360001 /* log(0.541) */, + -0.1531511795 /* log(0.858) */, -0.0998203353 /* log(0.905) */, + 0.3213585988 /* log(1.379) */, 0.3777512695 /* log(1.459) */, + 0.7158866675 /* log(2.046) */, 1.2700414043 /* log(3.561) */, + -1.6873994539 /* log(0.185) */, -1.2173958247 /* log(0.296) */, + -0.4893903430 /* log(0.613) */, -0.4155154440 /* log(0.660) */, + 0.1257512053 /* log(1.134) */, 0.1947440768 /* log(1.215) */, + 0.5883420662 /* log(1.801) */, 1.1987592373 /* log(3.316) */, + -1.3586791941 /* log(0.257) */, -0.9996723408 /* log(0.368) */, + -0.3768776513 /* log(0.686) */, -0.3119747650 /* log(0.732) */, + 0.1881379421 /* log(1.207) */, 0.2523139286 /* log(1.287) */, + 0.6280751838 /* log(1.874) */, 1.2202397768 /* log(3.388) */, + -0.7381445465 /* log(0.478) */, -0.5310283311 /* log(0.588) */, + -0.0987159729 /* log(0.906) */, -0.0491902442 /* log(0.952) */, + 0.3555743385 /* log(1.427) */, 0.4101209196 /* log(1.507) */, + 0.7390761124 /* log(2.094) */, 1.2831536022 /* log(3.608) */, + -0.2497442331 /* log(0.779) */, -0.1165338163 /* log(0.890) */, + 0.1881379421 /* log(1.207) */, 0.2255406759 /* log(1.253) */, + 0.5469646704 /* log(1.728) */, 0.5922212620 /* log(1.808) */, + 0.8733832309 /* log(2.395) */, 1.3632815868 /* log(3.909) */, + -1.3903023825 /* log(0.249) */, -1.0216512475 /* log(0.360) */, + -0.3900840061 /* log(0.677) */, -0.3229638866 /* log(0.724) */, + 0.1806534997 /* log(1.198) */, 0.2460785226 /* log(1.279) */, + 0.6232610531 /* log(1.865) */, 1.2178757095 /* log(3.380) */, + -0.6033064766 /* log(0.547) */, -0.4185503477 /* log(0.658) */, + -0.0253178080 /* log(0.975) */, 0.0217614918 /* log(1.022) */, + 0.4027948796 /* log(1.496) */, 0.4555243080 /* log(1.577) */, + 0.7714961470 /* log(2.163) */, 1.3023691262 /* log(3.678) */, + -1.1056369036 /* log(0.331) */, -0.8164453969 /* log(0.442) */, + -0.2757535016 /* log(0.759) */, -0.2156715365 /* log(0.806) */, + 0.2468600779 /* log(1.280) */, 0.3082197237 /* log(1.361) */, + 0.6662897264 /* log(1.947) */, 1.2418464568 /* log(3.462) */, + -0.5395680926 /* log(0.583) */, -0.3652833185 /* log(0.694) */, + 0.0109399400 /* log(1.011) */, 0.0554347069 /* log(1.057) */, + 0.4265740713 /* log(1.532) */, 0.4774756441 /* log(1.612) */, + 0.7880027116 /* log(2.199) */, 1.3118401752 /* log(3.713) */, + -0.9571127264 /* log(0.384) */, -0.7031975164 /* log(0.495) */, + -0.2082549388 /* log(0.812) */, -0.1519863570 /* log(0.859) */, + 0.2874320412 /* log(1.333) */, 0.3464225675 /* log(1.414) */, + 0.6931471806 /* log(2.000) */, 1.2570395253 /* log(3.515) */, + -0.2420715612 /* log(0.785) */, -0.1098148660 /* log(0.896) */, + 0.1930966300 /* log(1.213) */, 0.2311117210 /* log(1.260) */, + 0.5504308784 /* log(1.734) */, 0.5960854677 /* log(1.815) */, + 0.8758853172 /* log(2.401) */, 1.3650707247 /* log(3.916) */, + 0.6564831962 /* log(1.928) */, 0.7124594916 /* log(2.039) */, + 0.8569652658 /* log(2.356) */, 0.8767179568 /* log(2.403) */, + 1.0567480846 /* log(2.877) */, 1.0841752409 /* log(2.957) */, + 1.2652560327 /* log(3.544) */, 1.6211688353 /* log(5.059) */, + -1.5417792640 /* log(0.214) */, -1.1239300967 /* log(0.325) */, + -0.4431669753 /* log(0.642) */, -5.2983173665 /* log(0.005) */, + 0.1510028735 /* log(1.163) */, 0.2183319943 /* log(1.244) */, + 0.6043159669 /* log(1.830) */, 1.2074666936 /* log(3.345) */, + -0.5124936809 /* log(0.599) */, -0.3424903089 /* log(0.710) */, + 0.0266419309 /* log(1.027) */, 0.0713899961 /* log(1.074) */, + 0.4369637752 /* log(1.548) */, 0.4879663296 /* log(1.629) */, + 0.7952524035 /* log(2.215) */, 1.3164082337 /* log(3.730) */, + -0.8867319296 /* log(0.412) */, -0.6481738149 /* log(0.523) */, + -0.1743533871 /* log(0.840) */, -0.1199102967 /* log(0.887) */, + 0.3089542077 /* log(1.362) */, 0.3660310389 /* log(1.442) */, + 0.7075430608 /* log(2.029) */, 1.2649738259 /* log(3.543) */, + -0.0943106795 /* log(0.910) */, 0.0207825392 /* log(1.021) */, + 0.2911759617 /* log(1.338) */, 0.3249778572 /* log(1.384) */, + 0.6200387087 /* log(1.859) */, 0.6621723763 /* log(1.939) */, + 0.9266370239 /* log(2.526) */, 1.3962446920 /* log(4.040) */ +}; + +static const float wmavoice_ipol1_coeffs[17*9] = { + 0, + 0.6308171151, 0.7613050340, 0.8632577061, 0.9280143976, + 0.9499985575, 0.9273047447, 0.8618999123, 0.7594153284, + -0.1791058179, -0.1351341452, -0.0589959878, 0.0472882274, + 0.1784339990, 0.3262237605, 0.4801855979, 0.6285545824, + 0, + -0.1921342459, -0.1786532696, -0.1341681625, -0.0575229186, + 0.0492091286, 0.1806929555, 0.3286687729, 0.4826357064, + 0.0807464118, 0.0506337392, 0.0080115446, -0.0428523305, + -0.0958572026, -0.1436148431, -0.1782128509, -0.1921164688, + 0, + 0.0960653644, 0.0803771760, 0.0500416081, 0.0072485465, + -0.0437018941, -0.0966834794, -0.1442930843, -0.1786170151, + -0.0391932014, -0.0189622506, 0.0070230183, 0.0356589290, + 0.0630142610, 0.0847979258, 0.0969368290, 0.0961942221, + 0, + -0.0515680681, -0.0389267015, -0.0185848991, 0.0074699190, + 0.0361179407, 0.0634181346, 0.0850781347, 0.0970333587, + 0.0178811825, 0.0048708571, -0.0108041526, -0.0271167825, + -0.0416534986, -0.0519338618, -0.0557823736, -0.0517020743, + 0, + 0.0267091128, 0.0177022810, 0.0046363524, -0.0110662053, + -0.0273700613, -0.0418578978, -0.0520511451, -0.0557823028, + -0.0069270437, 0.0008217385, 0.0097293532, 0.0185749526, + 0.0259542684, 0.0304777338, 0.0309953480, 0.0268154419, + 0, + -0.0125539196, -0.0068173436, 0.0009580161, 0.0098749646, + 0.0187084037, 0.0260526291, 0.0305201071, 0.0309665180, + 0.0019149571, -0.0022503408, -0.0068592466, -0.0112465904, + -0.0146595868, -0.0163685936, -0.0157934162, -0.0126258885, + 0, + 0.0050976076, 0.0018546581, -0.0023221741, -0.0069331308, + -0.0113109085, -0.0147021576, -0.0163786146, -0.0157635096, + -0.0001162733, 0.0019313511, 0.0040823850, 0.0060192454, + 0.0073876535, 0.0078486321, 0.0071403184, 0.0051400312, + 0, + -0.0017920607, -0.0000857157, 0.0019657183, 0.0041159806, + 0.0060465694, 0.0074030068, 0.0078470460, 0.0071185785, + -0.0004100171, -0.0015364708, -0.0025490071, -0.0033188616, + -0.0037196307, -0.0036417283, -0.0030119629, -0.0018155784, + 0, + 0.0006907531, -0.0004282868, -0.0015539061, -0.0025635813, + -0.0033285026, -0.0037224069, -0.0036361245, -0.0029972247, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/** + * Hamming-window sinc function (num = 32, x = [ 0, 31 ]): + * (0.54 + 0.46 * cos(2 * M_PI * x / (num - 1))) * + * sin(x * M_PI / 4) / (x * M_PI / 4) + */ +static const float wmavoice_ipol2_coeffs[32] = { + 1, 0.8563459515, 0.5888634918, 0.2648358640, + 0, -0.1360490318, -0.1434589471, -0.0758505310, + 0, 0.0410402636, 0.0412485781, 0.0200064587, + 0, -0.0081391358, -0.0068223253, -0.0029313546, + 0, 0.0025864919, 0.0053062555, 0.0055688801, + 0, -0.0104795941, -0.0187493577, -0.0160592399, + 0, 0.0212381664, 0.0331059131, 0.0251942366, + 0, -0.0273968070, -0.0392575669, -0.0276240534 +}; + +/** + * LUT for 1.071575641632 * pow(1.0331663, n - 127) + */ +static const float wmavoice_energy_table[128] = { + 0.0169982178, 0.0175619858, 0.0181444519, 0.0187462362, + 0.0193679795, 0.0200103437, 0.0206740128, 0.0213596933, + 0.0220681153, 0.0228000330, 0.0235562258, 0.0243374986, + 0.0251446834, 0.0259786395, 0.0268402549, 0.0277304468, + 0.0286501631, 0.0296003830, 0.0305821182, 0.0315964139, + 0.0326443501, 0.0337270424, 0.0348456436, 0.0360013446, + 0.0371953760, 0.0384290090, 0.0397035571, 0.0410203772, + 0.0423808713, 0.0437864880, 0.0452387238, 0.0467391249, + 0.0482892887, 0.0498908657, 0.0515455612, 0.0532551367, + 0.0550214125, 0.0568462692, 0.0587316496, 0.0606795611, + 0.0626920777, 0.0647713419, 0.0669195677, 0.0691390421, + 0.0714321284, 0.0738012678, 0.0762489827, 0.0787778794, + 0.0813906502, 0.0840900769, 0.0868790336, 0.0897604897, + 0.0927375130, 0.0958132732, 0.0989910450, 0.1022742117, + 0.1056662688, 0.1091708280, 0.1127916204, 0.1165325012, + 0.1203974531, 0.1243905911, 0.1285161668, 0.1327785725, + 0.1371823465, 0.1417321773, 0.1464329093, 0.1512895470, + 0.1563072616, 0.1614913951, 0.1668474671, 0.1723811803, + 0.1780984262, 0.1840052921, 0.1901080668, 0.1964132480, + 0.2029275487, 0.2096579046, 0.2166114816, 0.2237956830, + 0.2312181577, 0.2388868085, 0.2468098001, 0.2549955679, + 0.2634528274, 0.2721905830, 0.2812181375, 0.2905451026, + 0.3001814086, 0.3101373153, 0.3204234225, 0.3310506819, + 0.3420304081, 0.3533742912, 0.3650944090, 0.3772032397, + 0.3897136755, 0.4026390362, 0.4159930832, 0.4297900346, + 0.4440445799, 0.4587718956, 0.4739876619, 0.4897080789, + 0.5059498840, 0.5227303696, 0.5400674019, 0.5579794393, + 0.5764855528, 0.5956054456, 0.6153594745, 0.6357686714, + 0.6568547659, 0.6786402082, 0.7011481929, 0.7244026842, + 0.7484284410, 0.7732510432, 0.7988969192, 0.8253933741, + 0.8527686184, 0.8810517982, 0.9102730265, 0.9404634147, + 0.9716551065, 1.0038813113, 1.0371763400, 1.0715756416 +}; + +/** + * LUT for f(x,y) = pow((y + 6.9) / 64, 0.025 * (x + 1)). + */ +static const float wmavoice_denoise_power_table[12][64] = { + { 0.9458379339, 0.9490436287, 0.9518757236, 0.9544130754, + 0.9567118717, 0.9588135761, 0.9607496688, 0.9625446194, + 0.9642178285, 0.9657849396, 0.9672587526, 0.9686498743, + 0.9699671937, 0.9712182343, 0.9724094211, 0.9735462842, + 0.9746336187, 0.9756756090, 0.9766759291, 0.9776378218, + 0.9785641645, 0.9794575217, 0.9803201890, 0.9811542296, + 0.9819615045, 0.9827436985, 0.9835023412, 0.9842388263, + 0.9849544265, 0.9856503078, 0.9863275406, 0.9869871101, + 0.9876299254, 0.9882568267, 0.9888685922, 0.9894659445, + 0.9900495551, 0.9906200497, 0.9911780119, 0.9917239872, + 0.9922584859, 0.9927819864, 0.9932949377, 0.9937977618, + 0.9942908555, 0.9947745929, 0.9952493267, 0.9957153901, + 0.9961730980, 0.9966227482, 0.9970646231, 0.9974989903, + 0.9979261037, 0.9983462046, 0.9987595223, 0.9991662752, + 0.9995666709, 0.9999609077, 1.0003491745, 1.0007316515, + 1.0011085110, 1.0014799178, 1.0018460292, 1.0022069960 }, + { 0.8946093973, 0.9006838092, 0.9060673931, 0.9109043185, + 0.9152976055, 0.9193234737, 0.9230399260, 0.9264921443, + 0.9297160207, 0.9327405496, 0.9355894944, 0.9382825789, + 0.9408363568, 0.9432648587, 0.9455800822, 0.9477923675, + 0.9499106907, 0.9519428941, 0.9538958704, 0.9557757107, + 0.9575878241, 0.9593370368, 0.9610276730, 0.9626636222, + 0.9642483964, 0.9657851769, 0.9672768552, 0.9687260672, + 0.9701352224, 0.9715065293, 0.9728420173, 0.9741435556, + 0.9754128696, 0.9766515555, 0.9778610927, 0.9790428553, + 0.9801981216, 0.9813280829, 0.9824338513, 0.9835164667, + 0.9845769028, 0.9856160726, 0.9866348334, 0.9876339913, + 0.9886143053, 0.9895764906, 0.9905212223, 0.9914491381, + 0.9923608411, 0.9932569022, 0.9941378627, 0.9950042356, + 0.9958565084, 0.9966951442, 0.9975205834, 0.9983332454, + 0.9991335296, 0.9999218170, 1.0006984708, 1.0014638383, + 1.0022182509, 1.0029620257, 1.0036954662, 1.0044188628 }, + { 0.8461555040, 0.8547882305, 0.8624635555, 0.8693789920, + 0.8756760853, 0.8814598273, 0.8868103032, 0.8917900284, + 0.8964487626, 0.9008267754, 0.9049571273, 0.9088673021, + 0.9125804007, 0.9161160306, 0.9194909803, 0.9227197376, + 0.9258148939, 0.9287874629, 0.9316471355, 0.9344024839, + 0.9370611291, 0.9396298766, 0.9421148300, 0.9445214846, + 0.9468548060, 0.9491192967, 0.9513190517, 0.9534578074, + 0.9555389816, 0.9575657096, 0.9595408742, 0.9614671327, + 0.9633469396, 0.9651825670, 0.9669761222, 0.9687295635, + 0.9704447142, 0.9721232742, 0.9737668316, 0.9753768718, + 0.9769547868, 0.9785018824, 0.9800193854, 0.9815084500, + 0.9829701633, 0.9844055505, 0.9858155796, 0.9872011653, + 0.9885631734, 0.9899024236, 0.9912196934, 0.9925157203, + 0.9937912053, 0.9950468143, 0.9962831814, 0.9975009102, + 0.9987005760, 0.9998827277, 1.0010478892, 1.0021965608, + 1.0033292209, 1.0044463270, 1.0055483173, 1.0066356112 }, + { 0.8003259737, 0.8112313241, 0.8209581209, 0.8297466775, + 0.8377697066, 0.8451556492, 0.8520027051, 0.8583876935, + 0.8643718792, 0.8700049328, 0.8753277020, 0.8803741979, + 0.8851730502, 0.8897485937, 0.8941216918, 0.8983103719, + 0.9023303202, 0.9061952736, 0.9099173316, 0.9135072091, + 0.9169744409, 0.9203275502, 0.9235741882, 0.9267212496, + 0.9297749699, 0.9327410079, 0.9356245146, 0.9384301933, + 0.9411623497, 0.9438249364, 0.9464215906, 0.9489556668, + 0.9514302661, 0.9538482608, 0.9562123167, 0.9585249126, + 0.9607883576, 0.9630048062, 0.9651762722, 0.9673046403, + 0.9693916775, 0.9714390425, 0.9734482944, 0.9754209007, + 0.9773582446, 0.9792616307, 0.9811322918, 0.9829713934, + 0.9847800389, 0.9865592739, 0.9883100900, 0.9900334289, + 0.9917301853, 0.9934012104, 0.9950473143, 0.9966692689, + 0.9982678100, 0.9998436400, 1.0013974295, 1.0029298194, + 1.0044414224, 1.0059328250, 1.0074045889, 1.0088572520 }, + { 0.7569786654, 0.7698939195, 0.7814501054, 0.7919210783, + 0.8015042240, 0.8103467104, 0.8185613167, 0.8262364557, + 0.8334427763, 0.8402376615, 0.8466683811, 0.8527743561, + 0.8585888194, 0.8641400582, 0.8694523567, 0.8745467247, + 0.8794414652, 0.8841526254, 0.8886943552, 0.8930791981, + 0.8973183276, 0.9014217415, 0.9053984227, 0.9092564737, + 0.9130032283, 0.9166453478, 0.9201889007, 0.9236394320, + 0.9270020224, 0.9302813390, 0.9334816797, 0.9366070112, + 0.9396610028, 0.9426470554, 0.9455683275, 0.9484277579, + 0.9512280860, 0.9539718690, 0.9566614986, 0.9592992147, + 0.9618871182, 0.9644271823, 0.9669212630, 0.9693711079, + 0.9717783651, 0.9741445900, 0.9764712529, 0.9787597445, + 0.9810113822, 0.9832274148, 0.9854090274, 0.9875573457, + 0.9896734398, 0.9917583281, 0.9938129803, 0.9958383209, + 0.9978352315, 0.9998045539, 1.0017470919, 1.0036636145, + 1.0055548568, 1.0074215229, 1.0092642871, 1.0110837959 }, + { 0.7159791370, 0.7306629191, 0.7438433845, 0.7558198318, + 0.7668086064, 0.7769714272, 0.7864325139, 0.7952894548, + 0.8036203840, 0.8114888792, 0.8189474022, 0.8260397728, + 0.8328029877, 0.8392685815, 0.8454636629, 0.8514117142, + 0.8571332177, 0.8626461513, 0.8679663850, 0.8731080020, + 0.8780835596, 0.8829043049, 0.8875803529, 0.8921208349, + 0.8965340237, 0.9008274393, 0.9050079382, 0.9090817905, + 0.9130547454, 0.9169320882, 0.9207186893, 0.9244190474, + 0.9280373261, 0.9315773876, 0.9350428208, 0.9384369673, + 0.9417629433, 0.9450236603, 0.9482218422, 0.9513600421, + 0.9544406555, 0.9574659338, 0.9604379957, 0.9633588374, + 0.9662303420, 0.9690542879, 0.9718323569, 0.9745661408, + 0.9772571477, 0.9799068082, 0.9825164805, 0.9850874551, + 0.9876209597, 0.9901181627, 0.9925801775, 0.9950080658, + 0.9974028405, 0.9997654692, 1.0020968764, 1.0043979464, + 1.0066695255, 1.0089124239, 1.0111274185, 1.0133152537 }, + { 0.6772002277, 0.6934309881, 0.7080464599, 0.7213643301, + 0.7336148970, 0.7449707526, 0.7555647772, 0.7655015856, + 0.7748651015, 0.7837237382, 0.7921340426, 0.8001433220, + 0.8077915768, 0.8151129499, 0.8221368310, 0.8288887107, + 0.8353908496, 0.8416628090, 0.8477218755, 0.8535834053, + 0.8592611049, 0.8647672624, 0.8701129393, 0.8753081305, + 0.8803618988, 0.8852824894, 0.8900774261, 0.8947535945, + 0.8993173131, 0.9037743949, 0.9081302004, 0.9123896841, + 0.9165574352, 0.9206377129, 0.9246344779, 0.9285514202, + 0.9323919830, 0.9361593853, 0.9398566405, 0.9434865742, + 0.9470518396, 0.9505549317, 0.9539981992, 0.9573838564, + 0.9607139933, 0.9639905847, 0.9672154989, 0.9703905051, + 0.9735172803, 0.9765974162, 0.9796324243, 0.9826237418, + 0.9855727362, 0.9884807098, 0.9913489039, 0.9941785028, + 0.9969706369, 0.9997263861, 1.0024467831, 1.0051328157, + 1.0077854297, 1.0104055314, 1.0129939892, 1.0155516364 }, + { 0.6405216642, 0.6580962612, 0.6739722363, 0.6884795488, + 0.7018580813, 0.7142880714, 0.7259086094, 0.7368294324, + 0.7471387455, 0.7569085832, 0.7661985859, 0.7750587283, + 0.7835313288, 0.7916525600, 0.7994535998, 0.8069615243, + 0.8142000068, 0.8211898738, 0.8279495504, 0.8344954211, + 0.8408421252, 0.8470027997, 0.8529892811, 0.8588122744, + 0.8644814947, 0.8700057878, 0.8753932324, 0.8806512276, + 0.8857865684, 0.8908055105, 0.8957138271, 0.9005168576, + 0.9052195513, 0.9098265046, 0.9143419945, 0.9187700080, + 0.9231142680, 0.9273782568, 0.9315652364, 0.9356782672, + 0.9397202245, 0.9436938133, 0.9476015819, 0.9514459336, + 0.9552291382, 0.9589533414, 0.9626205741, 0.9662327603, + 0.9697917251, 0.9732992008, 0.9767568340, 0.9801661903, + 0.9835287605, 0.9868459649, 0.9901191578, 0.9933496315, + 0.9965386205, 0.9996873045, 1.0027968119, 1.0058682226, + 1.0089025710, 1.0119008485, 1.0148640056, 1.0177929548 }, + { 0.6058296875, 0.6245620637, 0.6415378101, 0.6570938835, + 0.6714759586, 0.6848691001, 0.6974164561, 0.7092312055, + 0.7204044988, 0.7310109103, 0.7411122884, 0.7507605397, + 0.7599996842, 0.7688674015, 0.7773962122, 0.7856143935, + 0.7935466990, 0.8012149303, 0.8086383963, 0.8158342858, + 0.8228179717, 0.8296032631, 0.8362026133, 0.8426272954, + 0.8488875492, 0.8549927056, 0.8609512936, 0.8667711307, + 0.8724594015, 0.8780227256, 0.8834672161, 0.8887985309, + 0.8940219180, 0.8991422543, 0.9041640810, 0.9090916337, + 0.9139288704, 0.9186794948, 0.9233469789, 0.9279345818, + 0.9324453671, 0.9368822185, 0.9412478543, 0.9455448393, + 0.9497755970, 0.9539424198, 0.9580474782, 0.9620928299, + 0.9660804271, 0.9700121244, 0.9738896845, 0.9777147851, + 0.9814890239, 0.9852139236, 0.9888909370, 0.9925214512, + 0.9961067913, 0.9996482244, 1.0031469629, 1.0066041676, + 1.0100209506, 1.0133983785, 1.0167374742, 1.0200392198 }, + { 0.5730166999, 0.5927366473, 0.6106642672, 0.6271389942, + 0.6424090212, 0.6566617910, 0.6700426292, 0.6826666808, + 0.6946268614, 0.7059993279, 0.7168473476, 0.7272241023, + 0.7371747608, 0.7467380401, 0.7559474006, 0.7648319736, + 0.7734172908, 0.7817258650, 0.7897776570, 0.7975904541, + 0.8051801811, 0.8125611560, 0.8197463039, 0.8267473349, + 0.8335748949, 0.8402386937, 0.8467476129, 0.8531098003, + 0.8593327495, 0.8654233698, 0.8713880464, 0.8772326935, + 0.8829628002, 0.8885834710, 0.8940994619, 0.8995152120, + 0.9048348715, 0.9100623268, 0.9152012229, 0.9202549833, + 0.9252268281, 0.9301197899, 0.9349367288, 0.9396803449, + 0.9443531909, 0.9489576823, 0.9534961076, 0.9579706374, + 0.9623833320, 0.9667361492, 0.9710309512, 0.9752695109, + 0.9794535174, 0.9835845813, 0.9876642399, 0.9916939614, + 0.9956751493, 0.9996091459, 1.0034972362, 1.0073406510, + 1.0111405700, 1.0148981248, 1.0186144013, 1.0222904422 }, + { 0.5419809316, 0.5625329386, 0.5812764912, 0.5985496562, + 0.6146003370, 0.6296162401, 0.6437432340, 0.6570971404, + 0.6697716039, 0.6818435182, 0.6933768712, 0.7044255353, + 0.7150353340, 0.7252456009, 0.7350903742, 0.7445993259, + 0.7537984929, 0.7627108595, 0.7713568269, 0.7797545943, + 0.7879204712, 0.7958691361, 0.8036138516, 0.8111666444, + 0.8185384580, 0.8257392814, 0.8327782597, 0.8396637886, + 0.8464035955, 0.8530048108, 0.8594740287, 0.8658173611, + 0.8720404845, 0.8781486812, 0.8841468762, 0.8900396688, + 0.8958313620, 0.9015259874, 0.9071273286, 0.9126389413, + 0.9180641715, 0.9234061727, 0.9286679198, 0.9338522236, + 0.9389617420, 0.9439989920, 0.9489663591, 0.9538661069, + 0.9587003852, 0.9634712378, 0.9681806094, 0.9728303524, + 0.9774222323, 0.9819579336, 0.9864390644, 0.9908671615, + 0.9952436943, 0.9995700689, 1.0038476318, 1.0080776733, + 1.0122614305, 1.0164000906, 1.0204947932, 1.0245466331 }, + { 0.5126261246, 0.5338683013, 0.5533029807, 0.5712636181, + 0.5879954388, 0.6036845987, 0.6184760989, 0.6324853169, + 0.6458057215, 0.6585142011, 0.6706748475, 0.6823417062, + 0.6935608163, 0.7043717519, 0.7148088052, 0.7249019070, + 0.7346773529, 0.7441583823, 0.7533656456, 0.7623175831, + 0.7710307376, 0.7795200117, 0.7877988829, 0.7958795841, + 0.8037732557, 0.8114900754, 0.8190393682, 0.8264297018, + 0.8336689680, 0.8407644543, 0.8477229049, 0.8545505751, + 0.8612532786, 0.8678364291, 0.8743050768, 0.8806639416, + 0.8869174414, 0.8930697184, 0.8991246621, 0.9050859297, + 0.9109569648, 0.9167410144, 0.9224411436, 0.9280602496, + 0.9336010737, 0.9390662129, 0.9444581300, 0.9497791628, + 0.9550315328, 0.9602173528, 0.9653386345, 0.9703972943, + 0.9753951600, 0.9803339761, 0.9852154088, 0.9900410510, + 0.9948124263, 0.9995309934, 1.0041981497, 1.0088152348, + 1.0133835335, 1.0179042791, 1.0223786564, 1.0268078035 }, +}; + +#endif /* AVCODEC_WMAVOICE_DATA_H */ diff --git a/ffmpeg/libavcodec/wmv2.c b/ffmpeg/libavcodec/wmv2.c new file mode 100644 index 0000000..6676652 --- /dev/null +++ b/ffmpeg/libavcodec/wmv2.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2002 The FFmpeg Project + * + * 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 "avcodec.h" +#include "mpegvideo.h" +#include "msmpeg4data.h" +#include "simple_idct.h" +#include "wmv2.h" + + +av_cold void ff_wmv2_common_init(Wmv2Context * w){ + MpegEncContext * const s= &w->s; + + ff_wmv2dsp_init(&w->wdsp); + s->dsp.idct_permutation_type = w->wdsp.idct_perm; + ff_init_scantable_permutation(s->dsp.idct_permutation, + w->wdsp.idct_perm); + ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[0], + ff_wmv2_scantableA); + ff_init_scantable(s->dsp.idct_permutation, &w->abt_scantable[1], + ff_wmv2_scantableB); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, + ff_wmv1_scantable[1]); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, + ff_wmv1_scantable[2]); + ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, + ff_wmv1_scantable[3]); + ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable, + ff_wmv1_scantable[0]); + s->dsp.idct_put = w->wdsp.idct_put; + s->dsp.idct_add = w->wdsp.idct_add; + s->dsp.idct = NULL; +} + +static void wmv2_add_block(Wmv2Context *w, int16_t *block1, uint8_t *dst, int stride, int n){ + MpegEncContext * const s= &w->s; + + if (s->block_last_index[n] >= 0) { + switch(w->abt_type_table[n]){ + case 0: + w->wdsp.idct_add(dst, stride, block1); + break; + case 1: + ff_simple_idct84_add(dst , stride, block1); + ff_simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]); + s->dsp.clear_block(w->abt_block2[n]); + break; + case 2: + ff_simple_idct48_add(dst , stride, block1); + ff_simple_idct48_add(dst + 4 , stride, w->abt_block2[n]); + s->dsp.clear_block(w->abt_block2[n]); + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); + } + } +} + +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr){ + Wmv2Context * const w= (Wmv2Context*)s; + + wmv2_add_block(w, block1[0], dest_y , s->linesize, 0); + wmv2_add_block(w, block1[1], dest_y + 8 , s->linesize, 1); + wmv2_add_block(w, block1[2], dest_y + 8*s->linesize, s->linesize, 2); + wmv2_add_block(w, block1[3], dest_y + 8 + 8*s->linesize, s->linesize, 3); + + if(s->flags&CODEC_FLAG_GRAY) return; + + wmv2_add_block(w, block1[4], dest_cb , s->uvlinesize, 4); + wmv2_add_block(w, block1[5], dest_cr , s->uvlinesize, 5); +} + +void ff_mspel_motion(MpegEncContext *s, + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, + uint8_t **ref_picture, op_pixels_func (*pix_op)[4], + int motion_x, int motion_y, int h) +{ + Wmv2Context * const w= (Wmv2Context*)s; + uint8_t *ptr; + int dxy, offset, mx, my, src_x, src_y, v_edge_pos, linesize, uvlinesize; + int emu=0; + + dxy = ((motion_y & 1) << 1) | (motion_x & 1); + dxy = 2*dxy + w->hshift; + src_x = s->mb_x * 16 + (motion_x >> 1); + src_y = s->mb_y * 16 + (motion_y >> 1); + + /* WARNING: do no forget half pels */ + v_edge_pos = s->v_edge_pos; + src_x = av_clip(src_x, -16, s->width); + src_y = av_clip(src_y, -16, s->height); + + if(src_x<=-16 || src_x >= s->width) + dxy &= ~3; + if(src_y<=-16 || src_y >= s->height) + dxy &= ~4; + + linesize = s->linesize; + uvlinesize = s->uvlinesize; + ptr = ref_picture[0] + (src_y * linesize) + src_x; + + if(s->flags&CODEC_FLAG_EMU_EDGE){ + if(src_x<1 || src_y<1 || src_x + 17 >= s->h_edge_pos + || src_y + h+1 >= v_edge_pos){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr - 1 - s->linesize, s->linesize, 19, 19, + src_x-1, src_y-1, s->h_edge_pos, s->v_edge_pos); + ptr= s->edge_emu_buffer + 1 + s->linesize; + emu=1; + } + } + + s->dsp.put_mspel_pixels_tab[dxy](dest_y , ptr , linesize); + s->dsp.put_mspel_pixels_tab[dxy](dest_y+8 , ptr+8 , linesize); + s->dsp.put_mspel_pixels_tab[dxy](dest_y +8*linesize, ptr +8*linesize, linesize); + s->dsp.put_mspel_pixels_tab[dxy](dest_y+8+8*linesize, ptr+8+8*linesize, linesize); + + if(s->flags&CODEC_FLAG_GRAY) return; + + if (s->out_format == FMT_H263) { + dxy = 0; + if ((motion_x & 3) != 0) + dxy |= 1; + if ((motion_y & 3) != 0) + dxy |= 2; + mx = motion_x >> 2; + my = motion_y >> 2; + } else { + mx = motion_x / 2; + my = motion_y / 2; + dxy = ((my & 1) << 1) | (mx & 1); + mx >>= 1; + my >>= 1; + } + + src_x = s->mb_x * 8 + mx; + src_y = s->mb_y * 8 + my; + src_x = av_clip(src_x, -8, s->width >> 1); + if (src_x == (s->width >> 1)) + dxy &= ~1; + src_y = av_clip(src_y, -8, s->height >> 1); + if (src_y == (s->height >> 1)) + dxy &= ~2; + offset = (src_y * uvlinesize) + src_x; + ptr = ref_picture[1] + offset; + if(emu){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, + src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr= s->edge_emu_buffer; + } + pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1); + + ptr = ref_picture[2] + offset; + if(emu){ + s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9, + src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr= s->edge_emu_buffer; + } + pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1); +} diff --git a/ffmpeg/libavcodec/wmv2.h b/ffmpeg/libavcodec/wmv2.h new file mode 100644 index 0000000..52739c1 --- /dev/null +++ b/ffmpeg/libavcodec/wmv2.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002 The FFmpeg Project + * + * 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 + */ + +#ifndef AVCODEC_WMV2_H +#define AVCODEC_WMV2_H + +#include "avcodec.h" +#include "mpegvideo.h" +#include "intrax8.h" +#include "wmv2dsp.h" + +#define SKIP_TYPE_NONE 0 +#define SKIP_TYPE_MPEG 1 +#define SKIP_TYPE_ROW 2 +#define SKIP_TYPE_COL 3 + + +typedef struct Wmv2Context{ + MpegEncContext s; + IntraX8Context x8; + WMV2DSPContext wdsp; + int j_type_bit; + int j_type; + int abt_flag; + int abt_type; + int abt_type_table[6]; + int per_mb_abt; + int per_block_abt; + int mspel_bit; + int cbp_table_index; + int top_left_mv_flag; + int per_mb_rl_bit; + int skip_type; + int hshift; + + ScanTable abt_scantable[2]; + DECLARE_ALIGNED(16, int16_t, abt_block2)[6][64]; +}Wmv2Context; + +void ff_wmv2_common_init(Wmv2Context * w); + +#endif /* AVCODEC_WMV2_H */ diff --git a/ffmpeg/libavcodec/wmv2dec.c b/ffmpeg/libavcodec/wmv2dec.c new file mode 100644 index 0000000..fccb1bb --- /dev/null +++ b/ffmpeg/libavcodec/wmv2dec.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2002 The FFmpeg Project + * + * 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 "avcodec.h" +#include "mpegvideo.h" +#include "h263.h" +#include "mathops.h" +#include "msmpeg4.h" +#include "msmpeg4data.h" +#include "intrax8.h" +#include "wmv2.h" + + +static void parse_mb_skip(Wmv2Context * w){ + int mb_x, mb_y; + MpegEncContext * const s= &w->s; + uint32_t * const mb_type = s->current_picture_ptr->mb_type; + + w->skip_type= get_bits(&s->gb, 2); + switch(w->skip_type){ + case SKIP_TYPE_NONE: + for(mb_y=0; mb_ymb_height; mb_y++){ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_16x16 | MB_TYPE_L0; + } + } + break; + case SKIP_TYPE_MPEG: + for(mb_y=0; mb_ymb_height; mb_y++){ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; + } + } + break; + case SKIP_TYPE_ROW: + for(mb_y=0; mb_ymb_height; mb_y++){ + if(get_bits1(&s->gb)){ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + } + }else{ + for(mb_x=0; mb_xmb_width; mb_x++){ + mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; + } + } + } + break; + case SKIP_TYPE_COL: + for(mb_x=0; mb_xmb_width; mb_x++){ + if(get_bits1(&s->gb)){ + for(mb_y=0; mb_ymb_height; mb_y++){ + mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; + } + }else{ + for(mb_y=0; mb_ymb_height; mb_y++){ + mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; + } + } + } + break; + } +} + +static int decode_ext_header(Wmv2Context *w){ + MpegEncContext * const s= &w->s; + GetBitContext gb; + int fps; + int code; + + if(s->avctx->extradata_size<4) return -1; + + init_get_bits(&gb, s->avctx->extradata, 32); + + fps = get_bits(&gb, 5); + s->bit_rate = get_bits(&gb, 11)*1024; + w->mspel_bit = get_bits1(&gb); + s->loop_filter = get_bits1(&gb); + w->abt_flag = get_bits1(&gb); + w->j_type_bit = get_bits1(&gb); + w->top_left_mv_flag= get_bits1(&gb); + w->per_mb_rl_bit = get_bits1(&gb); + code = get_bits(&gb, 3); + + if(code==0) return -1; + + s->slice_height = s->mb_height / code; + + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, slices:%d\n", + fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, s->loop_filter, + code); + } + return 0; +} + +int ff_wmv2_decode_picture_header(MpegEncContext * s) +{ + Wmv2Context * const w= (Wmv2Context*)s; + int code; + + if(s->picture_number==0) + decode_ext_header(w); + + s->pict_type = get_bits1(&s->gb) + 1; + if(s->pict_type == AV_PICTURE_TYPE_I){ + code = get_bits(&s->gb, 7); + av_log(s->avctx, AV_LOG_DEBUG, "I7:%X/\n", code); + } + s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); + if(s->qscale <= 0) + return -1; + + return 0; +} + +int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s) +{ + Wmv2Context * const w= (Wmv2Context*)s; + + if (s->pict_type == AV_PICTURE_TYPE_I) { + if(w->j_type_bit) w->j_type= get_bits1(&s->gb); + else w->j_type= 0; //FIXME check + + if(!w->j_type){ + if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + + if(!s->per_mb_rl_table){ + s->rl_chroma_table_index = decode012(&s->gb); + s->rl_table_index = decode012(&s->gb); + } + + s->dc_table_index = get_bits1(&s->gb); + } + s->inter_intra_pred= 0; + s->no_rounding = 1; + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d j_type:%d \n", + s->qscale, + s->rl_chroma_table_index, + s->rl_table_index, + s->dc_table_index, + s->per_mb_rl_table, + w->j_type); + } + }else{ + int cbp_index; + w->j_type=0; + + parse_mb_skip(w); + cbp_index= decode012(&s->gb); + if(s->qscale <= 10){ + int map[3]= {0,2,1}; + w->cbp_table_index= map[cbp_index]; + }else if(s->qscale <= 20){ + int map[3]= {1,0,2}; + w->cbp_table_index= map[cbp_index]; + }else{ + int map[3]= {2,1,0}; + w->cbp_table_index= map[cbp_index]; + } + + if(w->mspel_bit) s->mspel= get_bits1(&s->gb); + else s->mspel= 0; //FIXME check + + if(w->abt_flag){ + w->per_mb_abt= get_bits1(&s->gb)^1; + if(!w->per_mb_abt){ + w->abt_type= decode012(&s->gb); + } + } + + if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); + else s->per_mb_rl_table= 0; + + if(!s->per_mb_rl_table){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + s->dc_table_index = get_bits1(&s->gb); + s->mv_table_index = get_bits1(&s->gb); + + s->inter_intra_pred= 0;//(s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + s->no_rounding ^= 1; + + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n", + s->rl_table_index, + s->rl_chroma_table_index, + s->dc_table_index, + s->mv_table_index, + s->per_mb_rl_table, + s->qscale, + s->mspel, + w->per_mb_abt, + w->abt_type, + w->cbp_table_index, + s->inter_intra_pred); + } + } + s->esc3_level_length= 0; + s->esc3_run_length= 0; + +s->picture_number++; //FIXME ? + + + if(w->j_type){ + ff_intrax8_decode_picture(&w->x8, 2*s->qscale, (s->qscale-1)|1 ); + return 1; + } + + return 0; +} + +static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr){ + MpegEncContext * const s= &w->s; + int ret; + + ret= ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); + + if(ret<0) return -1; + + if((((*mx_ptr)|(*my_ptr)) & 1) && s->mspel) + w->hshift= get_bits1(&s->gb); + else + w->hshift= 0; + + return 0; +} + +static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ + MpegEncContext * const s= &w->s; + int xy, wrap, diff, type; + int16_t *A, *B, *C, *mot_val; + + wrap = s->b8_stride; + xy = s->block_index[0]; + + mot_val = s->current_picture.motion_val[0][xy]; + + A = s->current_picture.motion_val[0][xy - 1]; + B = s->current_picture.motion_val[0][xy - wrap]; + C = s->current_picture.motion_val[0][xy + 2 - wrap]; + + if(s->mb_x && !s->first_slice_line && !s->mspel && w->top_left_mv_flag) + diff= FFMAX(FFABS(A[0] - B[0]), FFABS(A[1] - B[1])); + else + diff=0; + + if(diff >= 8) + type= get_bits1(&s->gb); + else + type= 2; + + if(type == 0){ + *px= A[0]; + *py= A[1]; + }else if(type == 1){ + *px= B[0]; + *py= B[1]; + }else{ + /* special case for first (slice) line */ + if (s->first_slice_line) { + *px = A[0]; + *py = A[1]; + } else { + *px = mid_pred(A[0], B[0], C[0]); + *py = mid_pred(A[1], B[1], C[1]); + } + } + + return mot_val; +} + +static inline int wmv2_decode_inter_block(Wmv2Context *w, int16_t *block, int n, int cbp){ + MpegEncContext * const s= &w->s; + static const int sub_cbp_table[3]= {2,3,1}; + int sub_cbp; + + if(!cbp){ + s->block_last_index[n] = -1; + + return 0; + } + + if(w->per_block_abt) + w->abt_type= decode012(&s->gb); + w->abt_type_table[n]= w->abt_type; + + if(w->abt_type){ +// const uint8_t *scantable= w->abt_scantable[w->abt_type-1].permutated; + const uint8_t *scantable= w->abt_scantable[w->abt_type-1].scantable; +// const uint8_t *scantable= w->abt_type-1 ? w->abt_scantable[1].permutated : w->abt_scantable[0].scantable; + + sub_cbp= sub_cbp_table[ decode012(&s->gb) ]; + + if(sub_cbp&1){ + if (ff_msmpeg4_decode_block(s, block, n, 1, scantable) < 0) + return -1; + } + + if(sub_cbp&2){ + if (ff_msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0) + return -1; + } + s->block_last_index[n] = 63; + + return 0; + }else{ + return ff_msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated); + } +} + + +int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) +{ + Wmv2Context * const w= (Wmv2Context*)s; + int cbp, code, i; + uint8_t *coded_val; + + if(w->j_type) return 0; + + if (s->pict_type == AV_PICTURE_TYPE_P) { + if (IS_SKIP(s->current_picture.mb_type[s->mb_y * s->mb_stride + s->mb_x])) { + /* skip mb */ + s->mb_intra = 0; + for(i=0;i<6;i++) + s->block_last_index[i] = -1; + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = 0; + s->mv[0][0][1] = 0; + s->mb_skipped = 1; + w->hshift=0; + return 0; + } + + code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); + if (code < 0) + return -1; + s->mb_intra = (~code & 0x40) >> 6; + + cbp = code & 0x3f; + } else { + s->mb_intra = 1; + code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); + return -1; + } + /* predict coded block pattern */ + cbp = 0; + for(i=0;i<6;i++) { + int val = ((code >> (5 - i)) & 1); + if (i < 4) { + int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_val); + val = val ^ pred; + *coded_val = val; + } + cbp |= val << (5 - i); + } + } + + if (!s->mb_intra) { + int mx, my; + wmv2_pred_motion(w, &mx, &my); + + if(cbp){ + s->dsp.clear_blocks(s->block[0]); + if(s->per_mb_rl_table){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + if(w->abt_flag && w->per_mb_abt){ + w->per_block_abt= get_bits1(&s->gb); + if(!w->per_block_abt) + w->abt_type= decode012(&s->gb); + }else + w->per_block_abt=0; + } + + if (wmv2_decode_motion(w, &mx, &my) < 0) + return -1; + + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mv[0][0][0] = mx; + s->mv[0][0][1] = my; + + for (i = 0; i < 6; i++) { + if (wmv2_decode_inter_block(w, block[i], i, (cbp >> (5 - i)) & 1) < 0) + { + av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding inter block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + } else { + if (s->pict_type==AV_PICTURE_TYPE_P) + av_dlog(s->avctx, "%d%d ", s->inter_intra_pred, cbp); + av_dlog(s->avctx, "I at %d %d %d %06X\n", s->mb_x, s->mb_y, + ((cbp & 3) ? 1 : 0) +((cbp & 0x3C)? 2 : 0), + show_bits(&s->gb, 24)); + s->ac_pred = get_bits1(&s->gb); + if(s->inter_intra_pred){ + s->h263_aic_dir= get_vlc2(&s->gb, ff_inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); + av_dlog(s->avctx, "%d%d %d %d/", + s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); + } + if(s->per_mb_rl_table && cbp){ + s->rl_table_index = decode012(&s->gb); + s->rl_chroma_table_index = s->rl_table_index; + } + + s->dsp.clear_blocks(s->block[0]); + for (i = 0; i < 6; i++) { + if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) + { + av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); + return -1; + } + } + } + + return 0; +} + +static av_cold int wmv2_decode_init(AVCodecContext *avctx){ + Wmv2Context * const w= avctx->priv_data; + + if(ff_msmpeg4_decode_init(avctx) < 0) + return -1; + + ff_wmv2_common_init(w); + + ff_intrax8_common_init(&w->x8,&w->s); + + return 0; +} + +static av_cold int wmv2_decode_end(AVCodecContext *avctx) +{ + Wmv2Context *w = avctx->priv_data; + + ff_intrax8_common_end(&w->x8); + return ff_h263_decode_end(avctx); +} + +AVCodec ff_wmv2_decoder = { + .name = "wmv2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV2, + .priv_data_size = sizeof(Wmv2Context), + .init = wmv2_decode_init, + .close = wmv2_decode_end, + .decode = ff_h263_decode_frame, + .capabilities = CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), + .pix_fmts = ff_pixfmt_list_420, +}; diff --git a/ffmpeg/libavcodec/wmv2dsp.c b/ffmpeg/libavcodec/wmv2dsp.c new file mode 100644 index 0000000..9627442 --- /dev/null +++ b/ffmpeg/libavcodec/wmv2dsp.c @@ -0,0 +1,146 @@ +/* + * 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 "libavutil/attributes.h" +#include "libavutil/common.h" +#include "avcodec.h" +#include "dsputil.h" +#include "wmv2dsp.h" + +#define W0 2048 +#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */ +#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */ +#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */ +#define W4 2048 /* 2048*sqrt (2)*cos (4*pi/16) */ +#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */ +#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */ +#define W7 565 /* 2048*sqrt (2)*cos (7*pi/16) */ + +static void wmv2_idct_row(short * b) +{ + int s1, s2; + int a0, a1, a2, a3, a4, a5, a6, a7; + + /* step 1 */ + a1 = W1 * b[1] + W7 * b[7]; + a7 = W7 * b[1] - W1 * b[7]; + a5 = W5 * b[5] + W3 * b[3]; + a3 = W3 * b[5] - W5 * b[3]; + a2 = W2 * b[2] + W6 * b[6]; + a6 = W6 * b[2] - W2 * b[6]; + a0 = W0 * b[0] + W0 * b[4]; + a4 = W0 * b[0] - W0 * b[4]; + + /* step 2 */ + s1 = (181 * (a1 - a5 + a7 - a3) + 128) >> 8; // 1, 3, 5, 7 + s2 = (181 * (a1 - a5 - a7 + a3) + 128) >> 8; + + /* step 3 */ + b[0] = (a0 + a2 + a1 + a5 + (1 << 7)) >> 8; + b[1] = (a4 + a6 + s1 + (1 << 7)) >> 8; + b[2] = (a4 - a6 + s2 + (1 << 7)) >> 8; + b[3] = (a0 - a2 + a7 + a3 + (1 << 7)) >> 8; + b[4] = (a0 - a2 - a7 - a3 + (1 << 7)) >> 8; + b[5] = (a4 - a6 - s2 + (1 << 7)) >> 8; + b[6] = (a4 + a6 - s1 + (1 << 7)) >> 8; + b[7] = (a0 + a2 - a1 - a5 + (1 << 7)) >> 8; +} + +static void wmv2_idct_col(short * b) +{ + int s1, s2; + int a0, a1, a2, a3, a4, a5, a6, a7; + + /* step 1, with extended precision */ + a1 = (W1 * b[8 * 1] + W7 * b[8 * 7] + 4) >> 3; + a7 = (W7 * b[8 * 1] - W1 * b[8 * 7] + 4) >> 3; + a5 = (W5 * b[8 * 5] + W3 * b[8 * 3] + 4) >> 3; + a3 = (W3 * b[8 * 5] - W5 * b[8 * 3] + 4) >> 3; + a2 = (W2 * b[8 * 2] + W6 * b[8 * 6] + 4) >> 3; + a6 = (W6 * b[8 * 2] - W2 * b[8 * 6] + 4) >> 3; + a0 = (W0 * b[8 * 0] + W0 * b[8 * 4] ) >> 3; + a4 = (W0 * b[8 * 0] - W0 * b[8 * 4] ) >> 3; + + /* step 2 */ + s1 = (181 * (a1 - a5 + a7 - a3) + 128) >> 8; + s2 = (181 * (a1 - a5 - a7 + a3) + 128) >> 8; + + /* step 3 */ + b[8 * 0] = (a0 + a2 + a1 + a5 + (1 << 13)) >> 14; + b[8 * 1] = (a4 + a6 + s1 + (1 << 13)) >> 14; + b[8 * 2] = (a4 - a6 + s2 + (1 << 13)) >> 14; + b[8 * 3] = (a0 - a2 + a7 + a3 + (1 << 13)) >> 14; + + b[8 * 4] = (a0 - a2 - a7 - a3 + (1 << 13)) >> 14; + b[8 * 5] = (a4 - a6 - s2 + (1 << 13)) >> 14; + b[8 * 6] = (a4 + a6 - s1 + (1 << 13)) >> 14; + b[8 * 7] = (a0 + a2 - a1 - a5 + (1 << 13)) >> 14; +} + +static void wmv2_idct_add_c(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + + for (i = 0; i < 64; i += 8) + wmv2_idct_row(block + i); + for (i = 0; i < 8; i++) + wmv2_idct_col(block + i); + + for (i = 0; i < 8; i++) { + dest[0] = av_clip_uint8(dest[0] + block[0]); + dest[1] = av_clip_uint8(dest[1] + block[1]); + dest[2] = av_clip_uint8(dest[2] + block[2]); + dest[3] = av_clip_uint8(dest[3] + block[3]); + dest[4] = av_clip_uint8(dest[4] + block[4]); + dest[5] = av_clip_uint8(dest[5] + block[5]); + dest[6] = av_clip_uint8(dest[6] + block[6]); + dest[7] = av_clip_uint8(dest[7] + block[7]); + dest += line_size; + block += 8; + } +} + +static void wmv2_idct_put_c(uint8_t *dest, int line_size, int16_t *block) +{ + int i; + + for (i = 0; i < 64; i += 8) + wmv2_idct_row(block + i); + for (i = 0; i < 8; i++) + wmv2_idct_col(block + i); + + for (i = 0; i < 8; i++) { + dest[0] = av_clip_uint8(block[0]); + dest[1] = av_clip_uint8(block[1]); + dest[2] = av_clip_uint8(block[2]); + dest[3] = av_clip_uint8(block[3]); + dest[4] = av_clip_uint8(block[4]); + dest[5] = av_clip_uint8(block[5]); + dest[6] = av_clip_uint8(block[6]); + dest[7] = av_clip_uint8(block[7]); + dest += line_size; + block += 8; + } +} + +av_cold void ff_wmv2dsp_init(WMV2DSPContext *c) +{ + c->idct_add = wmv2_idct_add_c; + c->idct_put = wmv2_idct_put_c; + c->idct_perm = FF_NO_IDCT_PERM; +} diff --git a/ffmpeg/libavcodec/wmv2dsp.h b/ffmpeg/libavcodec/wmv2dsp.h new file mode 100644 index 0000000..37bee20 --- /dev/null +++ b/ffmpeg/libavcodec/wmv2dsp.h @@ -0,0 +1,33 @@ +/* + * 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 + */ + +#ifndef AVCODEC_WMV2DSP_H +#define AVCODEC_WMV2DSP_H + +#include + +typedef struct WMV2DSPContext { + void (*idct_add)(uint8_t *dest, int line_size, int16_t *block); + void (*idct_put)(uint8_t *dest, int line_size, int16_t *block); + + int idct_perm; +} WMV2DSPContext; + +void ff_wmv2dsp_init(WMV2DSPContext *c); + +#endif /* AVCODEC_WMV2DSP_H */ diff --git a/ffmpeg/libavcodec/wmv2enc.c b/ffmpeg/libavcodec/wmv2enc.c new file mode 100644 index 0000000..23b64a7 --- /dev/null +++ b/ffmpeg/libavcodec/wmv2enc.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2002 The FFmpeg Project + * + * 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 "avcodec.h" +#include "mpegvideo.h" +#include "msmpeg4.h" +#include "msmpeg4data.h" +#include "h263.h" +#include "wmv2.h" + + +static int encode_ext_header(Wmv2Context *w){ + MpegEncContext * const s= &w->s; + PutBitContext pb; + int code; + + init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size); + + put_bits(&pb, 5, s->avctx->time_base.den / s->avctx->time_base.num); //yes 29.97 -> 29 + put_bits(&pb, 11, FFMIN(s->bit_rate/1024, 2047)); + + put_bits(&pb, 1, w->mspel_bit=1); + put_bits(&pb, 1, s->loop_filter); + put_bits(&pb, 1, w->abt_flag=1); + put_bits(&pb, 1, w->j_type_bit=1); + put_bits(&pb, 1, w->top_left_mv_flag=0); + put_bits(&pb, 1, w->per_mb_rl_bit=1); + put_bits(&pb, 3, code=1); + + flush_put_bits(&pb); + + s->slice_height = s->mb_height / code; + + return 0; +} + +static av_cold int wmv2_encode_init(AVCodecContext *avctx){ + Wmv2Context * const w= avctx->priv_data; + + if(ff_MPV_encode_init(avctx) < 0) + return -1; + + ff_wmv2_common_init(w); + + avctx->extradata_size= 4; + avctx->extradata= av_mallocz(avctx->extradata_size + 10); + encode_ext_header(w); + + return 0; +} + +int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number) +{ + Wmv2Context * const w= (Wmv2Context*)s; + + put_bits(&s->pb, 1, s->pict_type - 1); + if(s->pict_type == AV_PICTURE_TYPE_I){ + put_bits(&s->pb, 7, 0); + } + put_bits(&s->pb, 5, s->qscale); + + s->dc_table_index = 1; + s->mv_table_index = 1; /* only if P frame */ + s->per_mb_rl_table = 0; + s->mspel= 0; + w->per_mb_abt=0; + w->abt_type=0; + w->j_type=0; + + av_assert0(s->flipflop_rounding); + + if (s->pict_type == AV_PICTURE_TYPE_I) { + av_assert0(s->no_rounding==1); + if(w->j_type_bit) put_bits(&s->pb, 1, w->j_type); + + if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); + + if(!s->per_mb_rl_table){ + ff_msmpeg4_code012(&s->pb, s->rl_chroma_table_index); + ff_msmpeg4_code012(&s->pb, s->rl_table_index); + } + + put_bits(&s->pb, 1, s->dc_table_index); + + s->inter_intra_pred= 0; + }else{ + int cbp_index; + + put_bits(&s->pb, 2, SKIP_TYPE_NONE); + + ff_msmpeg4_code012(&s->pb, cbp_index=0); + if(s->qscale <= 10){ + int map[3]= {0,2,1}; + w->cbp_table_index= map[cbp_index]; + }else if(s->qscale <= 20){ + int map[3]= {1,0,2}; + w->cbp_table_index= map[cbp_index]; + }else{ + int map[3]= {2,1,0}; + w->cbp_table_index= map[cbp_index]; + } + + if(w->mspel_bit) put_bits(&s->pb, 1, s->mspel); + + if(w->abt_flag){ + put_bits(&s->pb, 1, w->per_mb_abt^1); + if(!w->per_mb_abt){ + ff_msmpeg4_code012(&s->pb, w->abt_type); + } + } + + if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); + + if(!s->per_mb_rl_table){ + ff_msmpeg4_code012(&s->pb, s->rl_table_index); + s->rl_chroma_table_index = s->rl_table_index; + } + put_bits(&s->pb, 1, s->dc_table_index); + put_bits(&s->pb, 1, s->mv_table_index); + + s->inter_intra_pred= 0;//(s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); + } + s->esc3_level_length= 0; + s->esc3_run_length= 0; + + return 0; +} + +/* Nearly identical to wmv1 but that is just because we do not use the + * useless M$ crap features. It is duplicated here in case someone wants + * to add support for these crap features. */ +void ff_wmv2_encode_mb(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y) +{ + Wmv2Context * const w= (Wmv2Context*)s; + int cbp, coded_cbp, i; + int pred_x, pred_y; + uint8_t *coded_block; + + ff_msmpeg4_handle_slices(s); + + if (!s->mb_intra) { + /* compute cbp */ + cbp = 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + + put_bits(&s->pb, + ff_wmv2_inter_table[w->cbp_table_index][cbp + 64][1], + ff_wmv2_inter_table[w->cbp_table_index][cbp + 64][0]); + + /* motion vector */ + ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y); + ff_msmpeg4_encode_motion(s, motion_x - pred_x, + motion_y - pred_y); + } else { + /* compute cbp */ + cbp = 0; + coded_cbp = 0; + for (i = 0; i < 6; i++) { + int val, pred; + val = (s->block_last_index[i] >= 1); + cbp |= val << (5 - i); + if (i < 4) { + /* predict value for close blocks only for luma */ + pred = ff_msmpeg4_coded_block_pred(s, i, &coded_block); + *coded_block = val; + val = val ^ pred; + } + coded_cbp |= val << (5 - i); + } + + if (s->pict_type == AV_PICTURE_TYPE_I) { + put_bits(&s->pb, + ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[coded_cbp][0]); + } else { + put_bits(&s->pb, + ff_wmv2_inter_table[w->cbp_table_index][cbp][1], + ff_wmv2_inter_table[w->cbp_table_index][cbp][0]); + } + put_bits(&s->pb, 1, 0); /* no AC prediction yet */ + if(s->inter_intra_pred){ + s->h263_aic_dir=0; + put_bits(&s->pb, ff_table_inter_intra[s->h263_aic_dir][1], ff_table_inter_intra[s->h263_aic_dir][0]); + } + } + + for (i = 0; i < 6; i++) { + ff_msmpeg4_encode_block(s, block[i], i); + } +} + +AVCodec ff_wmv2_encoder = { + .name = "wmv2", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WMV2, + .priv_data_size = sizeof(Wmv2Context), + .init = wmv2_encode_init, + .encode2 = ff_MPV_encode_picture, + .close = ff_MPV_encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), +}; diff --git a/ffmpeg/libavcodec/wnv1.c b/ffmpeg/libavcodec/wnv1.c new file mode 100644 index 0000000..162dd1f --- /dev/null +++ b/ffmpeg/libavcodec/wnv1.c @@ -0,0 +1,160 @@ +/* + * Winnov WNV1 codec + * Copyright (c) 2005 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Winnov WNV1 codec. + */ + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" + + +typedef struct WNV1Context { + AVCodecContext *avctx; + + int shift; + GetBitContext gb; +} WNV1Context; + +static const uint16_t code_tab[16][2] = { + { 0x1FD, 9 }, { 0xFD, 8 }, { 0x7D, 7 }, { 0x3D, 6 }, { 0x1D, 5 }, { 0x0D, 4 }, { 0x005, 3 }, + { 0x000, 1 }, + { 0x004, 3 }, { 0x0C, 4 }, { 0x1C, 5 }, { 0x3C, 6 }, { 0x7C, 7 }, { 0xFC, 8 }, { 0x1FC, 9 }, { 0xFF, 8 } +}; + +#define CODE_VLC_BITS 9 +static VLC code_vlc; + +/* returns modified base_value */ +static inline int wnv1_get_code(WNV1Context *w, int base_value) +{ + int v = get_vlc2(&w->gb, code_vlc.table, CODE_VLC_BITS, 1); + + if (v == 15) + return ff_reverse[get_bits(&w->gb, 8 - w->shift)]; + else + return base_value + ((v - 7) << w->shift); +} + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + WNV1Context * const l = avctx->priv_data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame * const p = data; + unsigned char *Y,*U,*V; + int i, j, ret; + int prev_y = 0, prev_u = 0, prev_v = 0; + uint8_t *rbuf; + + if(buf_size<=8) { + av_log(avctx, AV_LOG_ERROR, "buf_size %d is too small\n", buf_size); + return AVERROR_INVALIDDATA; + } + + rbuf = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!rbuf) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); + return AVERROR(ENOMEM); + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) { + av_free(rbuf); + return ret; + } + p->key_frame = 1; + + for (i = 8; i < buf_size; i++) + rbuf[i] = ff_reverse[buf[i]]; + init_get_bits(&l->gb, rbuf + 8, (buf_size - 8) * 8); + + if (buf[2] >> 4 == 6) + l->shift = 2; + else { + l->shift = 8 - (buf[2] >> 4); + if (l->shift > 4) { + avpriv_request_sample(avctx, + "Unknown WNV1 frame header value %i", + buf[2] >> 4); + l->shift = 4; + } + if (l->shift < 1) { + avpriv_request_sample(avctx, + "Unknown WNV1 frame header value %i", + buf[2] >> 4); + l->shift = 1; + } + } + + Y = p->data[0]; + U = p->data[1]; + V = p->data[2]; + for (j = 0; j < avctx->height; j++) { + for (i = 0; i < avctx->width / 2; i++) { + Y[i * 2] = wnv1_get_code(l, prev_y); + prev_u = U[i] = wnv1_get_code(l, prev_u); + prev_y = Y[(i * 2) + 1] = wnv1_get_code(l, Y[i * 2]); + prev_v = V[i] = wnv1_get_code(l, prev_v); + } + Y += p->linesize[0]; + U += p->linesize[1]; + V += p->linesize[2]; + } + + + *got_frame = 1; + av_free(rbuf); + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + WNV1Context * const l = avctx->priv_data; + static VLC_TYPE code_table[1 << CODE_VLC_BITS][2]; + + l->avctx = avctx; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + + code_vlc.table = code_table; + code_vlc.table_allocated = 1 << CODE_VLC_BITS; + init_vlc(&code_vlc, CODE_VLC_BITS, 16, + &code_tab[0][1], 4, 2, + &code_tab[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); + + return 0; +} + +AVCodec ff_wnv1_decoder = { + .name = "wnv1", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_WNV1, + .priv_data_size = sizeof(WNV1Context), + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Winnov WNV1"), +}; diff --git a/ffmpeg/libavcodec/ws-snd1.c b/ffmpeg/libavcodec/ws-snd1.c new file mode 100644 index 0000000..d27df75 --- /dev/null +++ b/ffmpeg/libavcodec/ws-snd1.c @@ -0,0 +1,181 @@ +/* + * Westwood SNDx codecs + * Copyright (c) 2005 Konstantin Shishkov + * + * 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 "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +/** + * @file + * Westwood SNDx codecs + * + * Reference documents about VQA format and its audio codecs + * can be found here: + * http://www.multimedia.cx + */ + +static const int8_t ws_adpcm_4bit[] = { + -9, -8, -6, -5, -4, -3, -2, -1, + 0, 1, 2, 3, 4, 5, 6, 8 +}; + +static av_cold int ws_snd_decode_init(AVCodecContext *avctx) +{ + avctx->channels = 1; + avctx->channel_layout = AV_CH_LAYOUT_MONO; + avctx->sample_fmt = AV_SAMPLE_FMT_U8; + + return 0; +} + +static int ws_snd_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + + int in_size, out_size, ret; + int sample = 128; + uint8_t *samples; + uint8_t *samples_end; + + if (!buf_size) + return 0; + + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + + out_size = AV_RL16(&buf[0]); + in_size = AV_RL16(&buf[2]); + buf += 4; + + if (in_size > buf_size) { + av_log(avctx, AV_LOG_ERROR, "Frame data is larger than input buffer\n"); + return AVERROR_INVALIDDATA; + } + + /* get output buffer */ + frame->nb_samples = out_size; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + samples = frame->data[0]; + samples_end = samples + out_size; + + if (in_size == out_size) { + memcpy(samples, buf, out_size); + *got_frame_ptr = 1; + return buf_size; + } + + while (samples < samples_end && buf - avpkt->data < buf_size) { + int code, smp, size; + uint8_t count; + code = *buf >> 6; + count = *buf & 0x3F; + buf++; + + /* make sure we don't write past the output buffer */ + switch (code) { + case 0: smp = 4 * (count + 1); break; + case 1: smp = 2 * (count + 1); break; + case 2: smp = (count & 0x20) ? 1 : count + 1; break; + default: smp = count + 1; break; + } + if (samples_end - samples < smp) + break; + + /* make sure we don't read past the input buffer */ + size = ((code == 2 && (count & 0x20)) || code == 3) ? 0 : count + 1; + if ((buf - avpkt->data) + size > buf_size) + break; + + switch (code) { + case 0: /* ADPCM 2-bit */ + for (count++; count > 0; count--) { + code = *buf++; + sample += ( code & 0x3) - 2; + sample = av_clip_uint8(sample); + *samples++ = sample; + sample += ((code >> 2) & 0x3) - 2; + sample = av_clip_uint8(sample); + *samples++ = sample; + sample += ((code >> 4) & 0x3) - 2; + sample = av_clip_uint8(sample); + *samples++ = sample; + sample += (code >> 6) - 2; + sample = av_clip_uint8(sample); + *samples++ = sample; + } + break; + case 1: /* ADPCM 4-bit */ + for (count++; count > 0; count--) { + code = *buf++; + sample += ws_adpcm_4bit[code & 0xF]; + sample = av_clip_uint8(sample); + *samples++ = sample; + sample += ws_adpcm_4bit[code >> 4]; + sample = av_clip_uint8(sample); + *samples++ = sample; + } + break; + case 2: /* no compression */ + if (count & 0x20) { /* big delta */ + int8_t t; + t = count; + t <<= 3; + sample += t >> 3; + sample = av_clip_uint8(sample); + *samples++ = sample; + } else { /* copy */ + memcpy(samples, buf, smp); + samples += smp; + buf += smp; + sample = buf[-1]; + } + break; + default: /* run */ + memset(samples, sample, smp); + samples += smp; + } + } + + frame->nb_samples = samples - frame->data[0]; + *got_frame_ptr = 1; + + return buf_size; +} + +AVCodec ff_ws_snd1_decoder = { + .name = "ws_snd1", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_WESTWOOD_SND1, + .init = ws_snd_decode_init, + .decode = ws_snd_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"), +}; diff --git a/ffmpeg/libavcodec/x86/Makefile b/ffmpeg/libavcodec/x86/Makefile new file mode 100644 index 0000000..38ef867 --- /dev/null +++ b/ffmpeg/libavcodec/x86/Makefile @@ -0,0 +1,95 @@ +OBJS += x86/fmtconvert_init.o \ + x86/constants.o + +OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp_init.o +OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp_init.o +OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp.o +OBJS-$(CONFIG_DNXHD_ENCODER) += x86/dnxhdenc.o +OBJS-$(CONFIG_FFT) += x86/fft_init.o +OBJS-$(CONFIG_H264CHROMA) += x86/h264chroma_init.o +OBJS-$(CONFIG_H264DSP) += x86/h264dsp_init.o +OBJS-$(CONFIG_H264PRED) += x86/h264_intrapred_init.o +OBJS-$(CONFIG_H264QPEL) += x86/h264_qpel.o +OBJS-$(CONFIG_HPELDSP) += x86/hpeldsp_init.o +OBJS-$(CONFIG_LPC) += x86/lpc.o +OBJS-$(CONFIG_MLP_DECODER) += x86/mlpdsp.o +OBJS-$(CONFIG_MPEGAUDIODSP) += x86/mpegaudiodec.o +OBJS-$(CONFIG_MPEGVIDEO) += x86/mpegvideo.o +OBJS-$(CONFIG_MPEGVIDEOENC) += x86/mpegvideoenc.o +OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp_init.o +OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp_init.o +OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp_init.o +OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp_init.o +OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp_init.o \ + x86/rv40dsp_init.o +OBJS-$(CONFIG_V210_DECODER) += x86/v210-init.o +OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o +OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_init.o +OBJS-$(CONFIG_VIDEODSP) += x86/videodsp_init.o +OBJS-$(CONFIG_VORBIS_DECODER) += x86/vorbisdsp_init.o +OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp_init.o +OBJS-$(CONFIG_VP5_DECODER) += x86/vp56dsp_init.o +OBJS-$(CONFIG_VP6_DECODER) += x86/vp56dsp_init.o +OBJS-$(CONFIG_VP8_DECODER) += x86/vp8dsp_init.o +OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o + +MMX-OBJS-$(CONFIG_DSPUTIL) += x86/dsputil_mmx.o \ + x86/fdct.o \ + x86/idct_mmx_xvid.o \ + x86/idct_sse2_xvid.o \ + x86/simple_idct.o \ + +MMX-OBJS-$(CONFIG_ENCODERS) += x86/dsputilenc_mmx.o \ + x86/motion_est.o +MMX-OBJS-$(CONFIG_DIRAC_DECODER) += x86/dirac_dwt.o +MMX-OBJS-$(CONFIG_SNOW_DECODER) += x86/snowdsp.o +MMX-OBJS-$(CONFIG_SNOW_ENCODER) += x86/snowdsp.o +MMX-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_mmx.o + +YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp.o +YASM-OBJS-$(CONFIG_AC3DSP) += x86/ac3dsp.o +YASM-OBJS-$(CONFIG_DCT) += x86/dct32.o +YASM-OBJS-$(CONFIG_DIRAC_DECODER) += x86/diracdsp_mmx.o x86/diracdsp_yasm.o\ + x86/dwt_yasm.o +YASM-OBJS-$(CONFIG_ENCODERS) += x86/dsputilenc.o +YASM-OBJS-$(CONFIG_FFT) += x86/fft.o +YASM-OBJS-$(CONFIG_H263_DECODER) += x86/h263_loopfilter.o +YASM-OBJS-$(CONFIG_H263_ENCODER) += x86/h263_loopfilter.o +YASM-OBJS-$(CONFIG_H264CHROMA) += x86/h264_chromamc.o \ + x86/h264_chromamc_10bit.o +YASM-OBJS-$(CONFIG_H264DSP) += x86/h264_deblock.o \ + x86/h264_deblock_10bit.o \ + x86/h264_idct.o \ + x86/h264_idct_10bit.o \ + x86/h264_weight.o \ + x86/h264_weight_10bit.o +YASM-OBJS-$(CONFIG_H264PRED) += x86/h264_intrapred.o \ + x86/h264_intrapred_10bit.o +YASM-OBJS-$(CONFIG_H264QPEL) += x86/h264_qpel_8bit.o \ + x86/h264_qpel_10bit.o \ + x86/qpelbase.o \ + x86/fpelbase.o +YASM-OBJS-$(CONFIG_HPELDSP) += x86/hpeldsp.o \ + x86/fpelbase.o +YASM-OBJS-$(CONFIG_MPEGAUDIODSP) += x86/imdct36.o +YASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o +YASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o +YASM-OBJS-$(CONFIG_PRORES_LGPL_DECODER) += x86/proresdsp.o +YASM-OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp.o +YASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp.o \ + x86/rv40dsp.o +YASM-OBJS-$(CONFIG_V210_DECODER) += x86/v210.o +YASM-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp.o +YASM-OBJS-$(CONFIG_VIDEODSP) += x86/videodsp.o +YASM-OBJS-$(CONFIG_VORBIS_DECODER) += x86/vorbisdsp.o +YASM-OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp.o +YASM-OBJS-$(CONFIG_VP6_DECODER) += x86/vp56dsp.o +YASM-OBJS-$(CONFIG_VP8_DECODER) += x86/vp8dsp.o + +YASM-OBJS-$(CONFIG_DSPUTIL) += x86/dsputil.o \ + x86/mpeg4qpel.o \ + x86/qpelbase.o \ + x86/fpelbase.o + +YASM-OBJS += x86/deinterlace.o \ + x86/fmtconvert.o diff --git a/ffmpeg/libavcodec/x86/ac3dsp.asm b/ffmpeg/libavcodec/x86/ac3dsp.asm new file mode 100644 index 0000000..98fb446 --- /dev/null +++ b/ffmpeg/libavcodec/x86/ac3dsp.asm @@ -0,0 +1,457 @@ +;***************************************************************************** +;* x86-optimized AC-3 DSP utils +;* Copyright (c) 2011 Justin Ruggles +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +; 16777216.0f - used in ff_float_to_fixed24() +pf_1_24: times 4 dd 0x4B800000 + +; used in ff_ac3_compute_mantissa_size() +cextern ac3_bap_bits +pw_bap_mul1: dw 21846, 21846, 0, 32768, 21846, 21846, 0, 32768 +pw_bap_mul2: dw 5, 7, 0, 7, 5, 7, 0, 7 + +; used in ff_ac3_extract_exponents() +pd_1: times 4 dd 1 +pd_151: times 4 dd 151 + +SECTION .text + +;----------------------------------------------------------------------------- +; void ff_ac3_exponent_min(uint8_t *exp, int num_reuse_blocks, int nb_coefs) +;----------------------------------------------------------------------------- + +%macro AC3_EXPONENT_MIN 0 +cglobal ac3_exponent_min, 3, 4, 2, exp, reuse_blks, expn, offset + shl reuse_blksq, 8 + jz .end + LOOP_ALIGN +.nextexp: + mov offsetq, reuse_blksq + mova m0, [expq+offsetq] + sub offsetq, 256 + LOOP_ALIGN +.nextblk: + PMINUB m0, [expq+offsetq], m1 + sub offsetq, 256 + jae .nextblk + mova [expq], m0 + add expq, mmsize + sub expnq, mmsize + jg .nextexp +.end: + REP_RET +%endmacro + +%define LOOP_ALIGN +INIT_MMX mmx +AC3_EXPONENT_MIN +%if HAVE_MMXEXT_EXTERNAL +%define LOOP_ALIGN ALIGN 16 +INIT_MMX mmxext +AC3_EXPONENT_MIN +%endif +%if HAVE_SSE2_EXTERNAL +INIT_XMM sse2 +AC3_EXPONENT_MIN +%endif +%undef LOOP_ALIGN + +;----------------------------------------------------------------------------- +; int ff_ac3_max_msb_abs_int16(const int16_t *src, int len) +; +; This function uses 2 different methods to calculate a valid result. +; 1) logical 'or' of abs of each element +; This is used for ssse3 because of the pabsw instruction. +; It is also used for mmx because of the lack of min/max instructions. +; 2) calculate min/max for the array, then or(abs(min),abs(max)) +; This is used for mmxext and sse2 because they have pminsw/pmaxsw. +;----------------------------------------------------------------------------- + +; logical 'or' of 4 or 8 words in an mmx or xmm register into the low word +%macro OR_WORDS_HORIZ 2 ; src, tmp +%if cpuflag(sse2) + movhlps %2, %1 + por %1, %2 + pshuflw %2, %1, q0032 + por %1, %2 + pshuflw %2, %1, q0001 + por %1, %2 +%elif cpuflag(mmxext) + pshufw %2, %1, q0032 + por %1, %2 + pshufw %2, %1, q0001 + por %1, %2 +%else ; mmx + movq %2, %1 + psrlq %2, 32 + por %1, %2 + movq %2, %1 + psrlq %2, 16 + por %1, %2 +%endif +%endmacro + +%macro AC3_MAX_MSB_ABS_INT16 1 +cglobal ac3_max_msb_abs_int16, 2,2,5, src, len + pxor m2, m2 + pxor m3, m3 +.loop: +%ifidn %1, min_max + mova m0, [srcq] + mova m1, [srcq+mmsize] + pminsw m2, m0 + pminsw m2, m1 + pmaxsw m3, m0 + pmaxsw m3, m1 +%else ; or_abs +%if notcpuflag(ssse3) + mova m0, [srcq] + mova m1, [srcq+mmsize] + ABS2 m0, m1, m3, m4 +%else ; ssse3 + ; using memory args is faster for ssse3 + pabsw m0, [srcq] + pabsw m1, [srcq+mmsize] +%endif + por m2, m0 + por m2, m1 +%endif + add srcq, mmsize*2 + sub lend, mmsize + ja .loop +%ifidn %1, min_max + ABS2 m2, m3, m0, m1 + por m2, m3 +%endif + OR_WORDS_HORIZ m2, m0 + movd eax, m2 + and eax, 0xFFFF + RET +%endmacro + +INIT_MMX mmx +AC3_MAX_MSB_ABS_INT16 or_abs +INIT_MMX mmxext +AC3_MAX_MSB_ABS_INT16 min_max +INIT_XMM sse2 +AC3_MAX_MSB_ABS_INT16 min_max +INIT_XMM ssse3 +AC3_MAX_MSB_ABS_INT16 or_abs + +;----------------------------------------------------------------------------- +; macro used for ff_ac3_lshift_int16() and ff_ac3_rshift_int32() +;----------------------------------------------------------------------------- + +%macro AC3_SHIFT 3 ; l/r, 16/32, shift instruction, instruction set +cglobal ac3_%1shift_int%2, 3, 3, 5, src, len, shift + movd m0, shiftd +.loop: + mova m1, [srcq ] + mova m2, [srcq+mmsize ] + mova m3, [srcq+mmsize*2] + mova m4, [srcq+mmsize*3] + %3 m1, m0 + %3 m2, m0 + %3 m3, m0 + %3 m4, m0 + mova [srcq ], m1 + mova [srcq+mmsize ], m2 + mova [srcq+mmsize*2], m3 + mova [srcq+mmsize*3], m4 + add srcq, mmsize*4 + sub lend, mmsize*32/%2 + ja .loop +.end: + REP_RET +%endmacro + +;----------------------------------------------------------------------------- +; void ff_ac3_lshift_int16(int16_t *src, unsigned int len, unsigned int shift) +;----------------------------------------------------------------------------- + +INIT_MMX mmx +AC3_SHIFT l, 16, psllw +INIT_XMM sse2 +AC3_SHIFT l, 16, psllw + +;----------------------------------------------------------------------------- +; void ff_ac3_rshift_int32(int32_t *src, unsigned int len, unsigned int shift) +;----------------------------------------------------------------------------- + +INIT_MMX mmx +AC3_SHIFT r, 32, psrad +INIT_XMM sse2 +AC3_SHIFT r, 32, psrad + +;----------------------------------------------------------------------------- +; void ff_float_to_fixed24(int32_t *dst, const float *src, unsigned int len) +;----------------------------------------------------------------------------- + +; The 3DNow! version is not bit-identical because pf2id uses truncation rather +; than round-to-nearest. +INIT_MMX 3dnow +cglobal float_to_fixed24, 3, 3, 0, dst, src, len + movq m0, [pf_1_24] +.loop: + movq m1, [srcq ] + movq m2, [srcq+8 ] + movq m3, [srcq+16] + movq m4, [srcq+24] + pfmul m1, m0 + pfmul m2, m0 + pfmul m3, m0 + pfmul m4, m0 + pf2id m1, m1 + pf2id m2, m2 + pf2id m3, m3 + pf2id m4, m4 + movq [dstq ], m1 + movq [dstq+8 ], m2 + movq [dstq+16], m3 + movq [dstq+24], m4 + add srcq, 32 + add dstq, 32 + sub lend, 8 + ja .loop + femms + RET + +INIT_XMM sse +cglobal float_to_fixed24, 3, 3, 3, dst, src, len + movaps m0, [pf_1_24] +.loop: + movaps m1, [srcq ] + movaps m2, [srcq+16] + mulps m1, m0 + mulps m2, m0 + cvtps2pi mm0, m1 + movhlps m1, m1 + cvtps2pi mm1, m1 + cvtps2pi mm2, m2 + movhlps m2, m2 + cvtps2pi mm3, m2 + movq [dstq ], mm0 + movq [dstq+ 8], mm1 + movq [dstq+16], mm2 + movq [dstq+24], mm3 + add srcq, 32 + add dstq, 32 + sub lend, 8 + ja .loop + emms + RET + +INIT_XMM sse2 +cglobal float_to_fixed24, 3, 3, 9, dst, src, len + movaps m0, [pf_1_24] +.loop: + movaps m1, [srcq ] + movaps m2, [srcq+16 ] + movaps m3, [srcq+32 ] + movaps m4, [srcq+48 ] +%ifdef m8 + movaps m5, [srcq+64 ] + movaps m6, [srcq+80 ] + movaps m7, [srcq+96 ] + movaps m8, [srcq+112] +%endif + mulps m1, m0 + mulps m2, m0 + mulps m3, m0 + mulps m4, m0 +%ifdef m8 + mulps m5, m0 + mulps m6, m0 + mulps m7, m0 + mulps m8, m0 +%endif + cvtps2dq m1, m1 + cvtps2dq m2, m2 + cvtps2dq m3, m3 + cvtps2dq m4, m4 +%ifdef m8 + cvtps2dq m5, m5 + cvtps2dq m6, m6 + cvtps2dq m7, m7 + cvtps2dq m8, m8 +%endif + movdqa [dstq ], m1 + movdqa [dstq+16 ], m2 + movdqa [dstq+32 ], m3 + movdqa [dstq+48 ], m4 +%ifdef m8 + movdqa [dstq+64 ], m5 + movdqa [dstq+80 ], m6 + movdqa [dstq+96 ], m7 + movdqa [dstq+112], m8 + add srcq, 128 + add dstq, 128 + sub lenq, 32 +%else + add srcq, 64 + add dstq, 64 + sub lenq, 16 +%endif + ja .loop + REP_RET + +;------------------------------------------------------------------------------ +; int ff_ac3_compute_mantissa_size(uint16_t mant_cnt[6][16]) +;------------------------------------------------------------------------------ + +%macro PHADDD4 2 ; xmm src, xmm tmp + movhlps %2, %1 + paddd %1, %2 + pshufd %2, %1, 0x1 + paddd %1, %2 +%endmacro + +INIT_XMM sse2 +cglobal ac3_compute_mantissa_size, 1, 2, 4, mant_cnt, sum + movdqa m0, [mant_cntq ] + movdqa m1, [mant_cntq+ 1*16] + paddw m0, [mant_cntq+ 2*16] + paddw m1, [mant_cntq+ 3*16] + paddw m0, [mant_cntq+ 4*16] + paddw m1, [mant_cntq+ 5*16] + paddw m0, [mant_cntq+ 6*16] + paddw m1, [mant_cntq+ 7*16] + paddw m0, [mant_cntq+ 8*16] + paddw m1, [mant_cntq+ 9*16] + paddw m0, [mant_cntq+10*16] + paddw m1, [mant_cntq+11*16] + pmaddwd m0, [ac3_bap_bits ] + pmaddwd m1, [ac3_bap_bits+16] + paddd m0, m1 + PHADDD4 m0, m1 + movd sumd, m0 + movdqa m3, [pw_bap_mul1] + movhpd m0, [mant_cntq +2] + movlpd m0, [mant_cntq+1*32+2] + movhpd m1, [mant_cntq+2*32+2] + movlpd m1, [mant_cntq+3*32+2] + movhpd m2, [mant_cntq+4*32+2] + movlpd m2, [mant_cntq+5*32+2] + pmulhuw m0, m3 + pmulhuw m1, m3 + pmulhuw m2, m3 + paddusw m0, m1 + paddusw m0, m2 + pmaddwd m0, [pw_bap_mul2] + PHADDD4 m0, m1 + movd eax, m0 + add eax, sumd + RET + +;------------------------------------------------------------------------------ +; void ff_ac3_extract_exponents(uint8_t *exp, int32_t *coef, int nb_coefs) +;------------------------------------------------------------------------------ + +%macro PABSD 1-2 ; src/dst, unused +%if cpuflag(ssse3) + pabsd %1, %1 +%else ; src/dst, tmp + pxor %2, %2 + pcmpgtd %2, %1 + pxor %1, %2 + psubd %1, %2 +%endif +%endmacro + +%if HAVE_AMD3DNOW_EXTERNAL +INIT_MMX 3dnow +cglobal ac3_extract_exponents, 3, 3, 0, exp, coef, len + add expq, lenq + lea coefq, [coefq+4*lenq] + neg lenq + movq m3, [pd_1] + movq m4, [pd_151] +.loop: + movq m0, [coefq+4*lenq ] + movq m1, [coefq+4*lenq+8] + PABSD m0, m2 + PABSD m1, m2 + pslld m0, 1 + por m0, m3 + pi2fd m2, m0 + psrld m2, 23 + movq m0, m4 + psubd m0, m2 + pslld m1, 1 + por m1, m3 + pi2fd m2, m1 + psrld m2, 23 + movq m1, m4 + psubd m1, m2 + packssdw m0, m0 + packuswb m0, m0 + packssdw m1, m1 + packuswb m1, m1 + punpcklwd m0, m1 + movd [expq+lenq], m0 + add lenq, 4 + jl .loop + REP_RET +%endif + +%macro AC3_EXTRACT_EXPONENTS 0 +cglobal ac3_extract_exponents, 3, 3, 4, exp, coef, len + add expq, lenq + lea coefq, [coefq+4*lenq] + neg lenq + mova m2, [pd_1] + mova m3, [pd_151] +.loop: + ; move 4 32-bit coefs to xmm0 + mova m0, [coefq+4*lenq] + ; absolute value + PABSD m0, m1 + ; convert to float and extract exponents + pslld m0, 1 + por m0, m2 + cvtdq2ps m1, m0 + psrld m1, 23 + mova m0, m3 + psubd m0, m1 + ; move the lowest byte in each of 4 dwords to the low dword + ; NOTE: We cannot just extract the low bytes with pshufb because the dword + ; result for 16777215 is -1 due to float inaccuracy. Using packuswb + ; clips this to 0, which is the correct exponent. + packssdw m0, m0 + packuswb m0, m0 + movd [expq+lenq], m0 + + add lenq, 4 + jl .loop + REP_RET +%endmacro + +%if HAVE_SSE2_EXTERNAL +INIT_XMM sse2 +AC3_EXTRACT_EXPONENTS +%endif +%if HAVE_SSSE3_EXTERNAL +INIT_XMM ssse3 +AC3_EXTRACT_EXPONENTS +%endif diff --git a/ffmpeg/libavcodec/x86/ac3dsp_init.c b/ffmpeg/libavcodec/x86/ac3dsp_init.c new file mode 100644 index 0000000..e2a190e --- /dev/null +++ b/ffmpeg/libavcodec/x86/ac3dsp_init.c @@ -0,0 +1,232 @@ +/* + * x86-optimized AC-3 DSP utils + * Copyright (c) 2011 Justin Ruggles + * + * 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 "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "dsputil_mmx.h" +#include "libavcodec/ac3.h" +#include "libavcodec/ac3dsp.h" + +extern void ff_ac3_exponent_min_mmx (uint8_t *exp, int num_reuse_blocks, int nb_coefs); +extern void ff_ac3_exponent_min_mmxext(uint8_t *exp, int num_reuse_blocks, int nb_coefs); +extern void ff_ac3_exponent_min_sse2 (uint8_t *exp, int num_reuse_blocks, int nb_coefs); + +extern int ff_ac3_max_msb_abs_int16_mmx (const int16_t *src, int len); +extern int ff_ac3_max_msb_abs_int16_mmxext(const int16_t *src, int len); +extern int ff_ac3_max_msb_abs_int16_sse2 (const int16_t *src, int len); +extern int ff_ac3_max_msb_abs_int16_ssse3(const int16_t *src, int len); + +extern void ff_ac3_lshift_int16_mmx (int16_t *src, unsigned int len, unsigned int shift); +extern void ff_ac3_lshift_int16_sse2(int16_t *src, unsigned int len, unsigned int shift); + +extern void ff_ac3_rshift_int32_mmx (int32_t *src, unsigned int len, unsigned int shift); +extern void ff_ac3_rshift_int32_sse2(int32_t *src, unsigned int len, unsigned int shift); + +extern void ff_float_to_fixed24_3dnow(int32_t *dst, const float *src, unsigned int len); +extern void ff_float_to_fixed24_sse (int32_t *dst, const float *src, unsigned int len); +extern void ff_float_to_fixed24_sse2 (int32_t *dst, const float *src, unsigned int len); + +extern int ff_ac3_compute_mantissa_size_sse2(uint16_t mant_cnt[6][16]); + +extern void ff_ac3_extract_exponents_3dnow(uint8_t *exp, int32_t *coef, int nb_coefs); +extern void ff_ac3_extract_exponents_sse2 (uint8_t *exp, int32_t *coef, int nb_coefs); +extern void ff_ac3_extract_exponents_ssse3(uint8_t *exp, int32_t *coef, int nb_coefs); + +#if ARCH_X86_32 && defined(__INTEL_COMPILER) +# undef HAVE_7REGS +# define HAVE_7REGS 0 +#endif + +#if HAVE_SSE_INLINE && HAVE_7REGS + +#define IF1(x) x +#define IF0(x) + +#define MIX5(mono, stereo) \ + __asm__ volatile ( \ + "movss 0(%1), %%xmm5 \n" \ + "movss 8(%1), %%xmm6 \n" \ + "movss 24(%1), %%xmm7 \n" \ + "shufps $0, %%xmm5, %%xmm5 \n" \ + "shufps $0, %%xmm6, %%xmm6 \n" \ + "shufps $0, %%xmm7, %%xmm7 \n" \ + "1: \n" \ + "movaps (%0, %2), %%xmm0 \n" \ + "movaps (%0, %3), %%xmm1 \n" \ + "movaps (%0, %4), %%xmm2 \n" \ + "movaps (%0, %5), %%xmm3 \n" \ + "movaps (%0, %6), %%xmm4 \n" \ + "mulps %%xmm5, %%xmm0 \n" \ + "mulps %%xmm6, %%xmm1 \n" \ + "mulps %%xmm5, %%xmm2 \n" \ + "mulps %%xmm7, %%xmm3 \n" \ + "mulps %%xmm7, %%xmm4 \n" \ + stereo("addps %%xmm1, %%xmm0 \n") \ + "addps %%xmm1, %%xmm2 \n" \ + "addps %%xmm3, %%xmm0 \n" \ + "addps %%xmm4, %%xmm2 \n" \ + mono("addps %%xmm2, %%xmm0 \n") \ + "movaps %%xmm0, (%0, %2) \n" \ + stereo("movaps %%xmm2, (%0, %3) \n") \ + "add $16, %0 \n" \ + "jl 1b \n" \ + : "+&r"(i) \ + : "r"(matrix), \ + "r"(samples[0] + len), \ + "r"(samples[1] + len), \ + "r"(samples[2] + len), \ + "r"(samples[3] + len), \ + "r"(samples[4] + len) \ + : XMM_CLOBBERS("%xmm0", "%xmm1", "%xmm2", "%xmm3", \ + "%xmm4", "%xmm5", "%xmm6", "%xmm7",) \ + "memory" \ + ); + +#define MIX_MISC(stereo) \ + __asm__ volatile ( \ + "mov %5, %2 \n" \ + "1: \n" \ + "mov -%c7(%6, %2, %c8), %3 \n" \ + "movaps (%3, %0), %%xmm0 \n" \ + stereo("movaps %%xmm0, %%xmm1 \n") \ + "mulps %%xmm4, %%xmm0 \n" \ + stereo("mulps %%xmm5, %%xmm1 \n") \ + "2: \n" \ + "mov (%6, %2, %c8), %1 \n" \ + "movaps (%1, %0), %%xmm2 \n" \ + stereo("movaps %%xmm2, %%xmm3 \n") \ + "mulps (%4, %2, 8), %%xmm2 \n" \ + stereo("mulps 16(%4, %2, 8), %%xmm3 \n") \ + "addps %%xmm2, %%xmm0 \n" \ + stereo("addps %%xmm3, %%xmm1 \n") \ + "add $4, %2 \n" \ + "jl 2b \n" \ + "mov %5, %2 \n" \ + stereo("mov (%6, %2, %c8), %1 \n") \ + "movaps %%xmm0, (%3, %0) \n" \ + stereo("movaps %%xmm1, (%1, %0) \n") \ + "add $16, %0 \n" \ + "jl 1b \n" \ + : "+&r"(i), "=&r"(j), "=&r"(k), "=&r"(m) \ + : "r"(matrix_simd + in_ch), \ + "g"((intptr_t) - 4 * (in_ch - 1)), \ + "r"(samp + in_ch), \ + "i"(sizeof(float *)), "i"(sizeof(float *)/4) \ + : "memory" \ + ); + +static void ac3_downmix_sse(float **samples, float (*matrix)[2], + int out_ch, int in_ch, int len) +{ + int (*matrix_cmp)[2] = (int(*)[2])matrix; + intptr_t i, j, k, m; + + i = -len * sizeof(float); + if (in_ch == 5 && out_ch == 2 && + !(matrix_cmp[0][1] | matrix_cmp[2][0] | + matrix_cmp[3][1] | matrix_cmp[4][0] | + (matrix_cmp[1][0] ^ matrix_cmp[1][1]) | + (matrix_cmp[0][0] ^ matrix_cmp[2][1]))) { + MIX5(IF0, IF1); + } else if (in_ch == 5 && out_ch == 1 && + matrix_cmp[0][0] == matrix_cmp[2][0] && + matrix_cmp[3][0] == matrix_cmp[4][0]) { + MIX5(IF1, IF0); + } else { + DECLARE_ALIGNED(16, float, matrix_simd)[AC3_MAX_CHANNELS][2][4]; + float *samp[AC3_MAX_CHANNELS]; + + for (j = 0; j < in_ch; j++) + samp[j] = samples[j] + len; + + j = 2 * in_ch * sizeof(float); + __asm__ volatile ( + "1: \n" + "sub $8, %0 \n" + "movss (%2, %0), %%xmm4 \n" + "movss 4(%2, %0), %%xmm5 \n" + "shufps $0, %%xmm4, %%xmm4 \n" + "shufps $0, %%xmm5, %%xmm5 \n" + "movaps %%xmm4, (%1, %0, 4) \n" + "movaps %%xmm5, 16(%1, %0, 4) \n" + "jg 1b \n" + : "+&r"(j) + : "r"(matrix_simd), "r"(matrix) + : "memory" + ); + if (out_ch == 2) { + MIX_MISC(IF1); + } else { + MIX_MISC(IF0); + } + } +} + +#endif /* HAVE_SSE_INLINE && HAVE_7REGS */ + +av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c, int bit_exact) +{ + int mm_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(mm_flags)) { + c->ac3_exponent_min = ff_ac3_exponent_min_mmx; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_mmx; + c->ac3_lshift_int16 = ff_ac3_lshift_int16_mmx; + c->ac3_rshift_int32 = ff_ac3_rshift_int32_mmx; + } + if (EXTERNAL_AMD3DNOW(mm_flags)) { + c->extract_exponents = ff_ac3_extract_exponents_3dnow; + if (!bit_exact) { + c->float_to_fixed24 = ff_float_to_fixed24_3dnow; + } + } + if (EXTERNAL_MMXEXT(mm_flags)) { + c->ac3_exponent_min = ff_ac3_exponent_min_mmxext; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_mmxext; + } + if (EXTERNAL_SSE(mm_flags)) { + c->float_to_fixed24 = ff_float_to_fixed24_sse; + } + if (EXTERNAL_SSE2(mm_flags)) { + c->ac3_exponent_min = ff_ac3_exponent_min_sse2; + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_sse2; + c->float_to_fixed24 = ff_float_to_fixed24_sse2; + c->compute_mantissa_size = ff_ac3_compute_mantissa_size_sse2; + c->extract_exponents = ff_ac3_extract_exponents_sse2; + if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW)) { + c->ac3_lshift_int16 = ff_ac3_lshift_int16_sse2; + c->ac3_rshift_int32 = ff_ac3_rshift_int32_sse2; + } + } + if (EXTERNAL_SSSE3(mm_flags)) { + c->ac3_max_msb_abs_int16 = ff_ac3_max_msb_abs_int16_ssse3; + if (!(mm_flags & AV_CPU_FLAG_ATOM)) { + c->extract_exponents = ff_ac3_extract_exponents_ssse3; + } + } + +#if HAVE_SSE_INLINE && HAVE_7REGS + if (INLINE_SSE(mm_flags)) { + c->downmix = ac3_downmix_sse; + } +#endif +} diff --git a/ffmpeg/libavcodec/x86/cabac.h b/ffmpeg/libavcodec/x86/cabac.h new file mode 100644 index 0000000..2c9f77e --- /dev/null +++ b/ffmpeg/libavcodec/x86/cabac.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2003 Michael Niedermayer + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_X86_CABAC_H +#define AVCODEC_X86_CABAC_H + +#include "libavcodec/cabac.h" +#include "libavutil/attributes.h" +#include "libavutil/x86/asm.h" +#include "libavutil/internal.h" +#include "config.h" + +#if HAVE_INLINE_ASM + +#ifdef BROKEN_RELOCATIONS +#define TABLES_ARG , "r"(tables) + +#if HAVE_FAST_CMOV +#define BRANCHLESS_GET_CABAC_UPDATE(ret, retq, low, range, tmp) \ + "cmp "low" , "tmp" \n\t"\ + "cmova %%ecx , "range" \n\t"\ + "sbb %%rcx , %%rcx \n\t"\ + "and %%ecx , "tmp" \n\t"\ + "xor %%rcx , "retq" \n\t"\ + "sub "tmp" , "low" \n\t" +#else /* HAVE_FAST_CMOV */ +#define BRANCHLESS_GET_CABAC_UPDATE(ret, retq, low, range, tmp) \ +/* P4 Prescott has crappy cmov,sbb,64bit shift so avoid them */ \ + "sub "low" , "tmp" \n\t"\ + "sar $31 , "tmp" \n\t"\ + "sub %%ecx , "range" \n\t"\ + "and "tmp" , "range" \n\t"\ + "add %%ecx , "range" \n\t"\ + "shl $17 , %%ecx \n\t"\ + "and "tmp" , %%ecx \n\t"\ + "sub %%ecx , "low" \n\t"\ + "xor "tmp" , "ret" \n\t"\ + "movslq "ret" , "retq" \n\t" +#endif /* HAVE_FAST_CMOV */ + +#define BRANCHLESS_GET_CABAC(ret, retq, statep, low, lowword, range, rangeq, tmp, tmpbyte, byte, end, norm_off, lps_off, mlps_off, tables) \ + "movzbl "statep" , "ret" \n\t"\ + "mov "range" , "tmp" \n\t"\ + "and $0xC0 , "range" \n\t"\ + "lea ("ret", "range", 2), %%ecx \n\t"\ + "movzbl "lps_off"("tables", %%rcx), "range" \n\t"\ + "sub "range" , "tmp" \n\t"\ + "mov "tmp" , %%ecx \n\t"\ + "shl $17 , "tmp" \n\t"\ + BRANCHLESS_GET_CABAC_UPDATE(ret, retq, low, range, tmp) \ + "movzbl "norm_off"("tables", "rangeq"), %%ecx \n\t"\ + "shl %%cl , "range" \n\t"\ + "movzbl "mlps_off"+128("tables", "retq"), "tmp" \n\t"\ + "shl %%cl , "low" \n\t"\ + "mov "tmpbyte" , "statep" \n\t"\ + "test "lowword" , "lowword" \n\t"\ + "jnz 2f \n\t"\ + "mov "byte" , %%"REG_c" \n\t"\ + "add"OPSIZE" $2 , "byte" \n\t"\ + "movzwl (%%"REG_c") , "tmp" \n\t"\ + "lea -1("low") , %%ecx \n\t"\ + "xor "low" , %%ecx \n\t"\ + "shr $15 , %%ecx \n\t"\ + "bswap "tmp" \n\t"\ + "shr $15 , "tmp" \n\t"\ + "movzbl "norm_off"("tables", %%rcx), %%ecx \n\t"\ + "sub $0xFFFF , "tmp" \n\t"\ + "neg %%ecx \n\t"\ + "add $7 , %%ecx \n\t"\ + "shl %%cl , "tmp" \n\t"\ + "add "tmp" , "low" \n\t"\ + "2: \n\t" + +#else /* BROKEN_RELOCATIONS */ +#define TABLES_ARG +#define RIP_ARG + +#if HAVE_FAST_CMOV +#define BRANCHLESS_GET_CABAC_UPDATE(ret, low, range, tmp)\ + "mov "tmp" , %%ecx \n\t"\ + "shl $17 , "tmp" \n\t"\ + "cmp "low" , "tmp" \n\t"\ + "cmova %%ecx , "range" \n\t"\ + "sbb %%ecx , %%ecx \n\t"\ + "and %%ecx , "tmp" \n\t"\ + "xor %%ecx , "ret" \n\t"\ + "sub "tmp" , "low" \n\t" +#else /* HAVE_FAST_CMOV */ +#define BRANCHLESS_GET_CABAC_UPDATE(ret, low, range, tmp)\ + "mov "tmp" , %%ecx \n\t"\ + "shl $17 , "tmp" \n\t"\ + "sub "low" , "tmp" \n\t"\ + "sar $31 , "tmp" \n\t" /*lps_mask*/\ + "sub %%ecx , "range" \n\t" /*RangeLPS - range*/\ + "and "tmp" , "range" \n\t" /*(RangeLPS - range)&lps_mask*/\ + "add %%ecx , "range" \n\t" /*new range*/\ + "shl $17 , %%ecx \n\t"\ + "and "tmp" , %%ecx \n\t"\ + "sub %%ecx , "low" \n\t"\ + "xor "tmp" , "ret" \n\t" +#endif /* HAVE_FAST_CMOV */ + +#define BRANCHLESS_GET_CABAC(ret, retq, statep, low, lowword, range, rangeq, tmp, tmpbyte, byte, end, norm_off, lps_off, mlps_off, tables) \ + "movzbl "statep" , "ret" \n\t"\ + "mov "range" , "tmp" \n\t"\ + "and $0xC0 , "range" \n\t"\ + "movzbl "MANGLE(ff_h264_cabac_tables)"+"lps_off"("ret", "range", 2), "range" \n\t"\ + "sub "range" , "tmp" \n\t"\ + BRANCHLESS_GET_CABAC_UPDATE(ret, low, range, tmp) \ + "movzbl "MANGLE(ff_h264_cabac_tables)"+"norm_off"("range"), %%ecx \n\t"\ + "shl %%cl , "range" \n\t"\ + "movzbl "MANGLE(ff_h264_cabac_tables)"+"mlps_off"+128("ret"), "tmp" \n\t"\ + "shl %%cl , "low" \n\t"\ + "mov "tmpbyte" , "statep" \n\t"\ + "test "lowword" , "lowword" \n\t"\ + " jnz 2f \n\t"\ + "mov "byte" , %%"REG_c" \n\t"\ + "add"OPSIZE" $2 , "byte" \n\t"\ + "movzwl (%%"REG_c") , "tmp" \n\t"\ + "lea -1("low") , %%ecx \n\t"\ + "xor "low" , %%ecx \n\t"\ + "shr $15 , %%ecx \n\t"\ + "bswap "tmp" \n\t"\ + "shr $15 , "tmp" \n\t"\ + "movzbl "MANGLE(ff_h264_cabac_tables)"+"norm_off"(%%ecx), %%ecx \n\t"\ + "sub $0xFFFF , "tmp" \n\t"\ + "neg %%ecx \n\t"\ + "add $7 , %%ecx \n\t"\ + "shl %%cl , "tmp" \n\t"\ + "add "tmp" , "low" \n\t"\ + "2: \n\t" + +#endif /* BROKEN_RELOCATIONS */ + + +#if HAVE_7REGS && !(defined(__i386) && defined(__clang__) && (__clang_major__<2 || (__clang_major__==2 && __clang_minor__<10)))\ + && !( !defined(__clang__) && defined(__llvm__) && __GNUC__==4 && __GNUC_MINOR__==2 && __GNUC_PATCHLEVEL__<=1) +#define get_cabac_inline get_cabac_inline_x86 +static av_always_inline int get_cabac_inline_x86(CABACContext *c, + uint8_t *const state) +{ + int bit, tmp; +#ifdef BROKEN_RELOCATIONS + void *tables; + + __asm__ volatile( + "lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t" + : "=&r"(tables) + ); +#endif + + __asm__ volatile( + BRANCHLESS_GET_CABAC("%0", "%q0", "(%4)", "%1", "%w1", + "%2", "%q2", "%3", "%b3", + "%c6(%5)", "%c7(%5)", + AV_STRINGIFY(H264_NORM_SHIFT_OFFSET), + AV_STRINGIFY(H264_LPS_RANGE_OFFSET), + AV_STRINGIFY(H264_MLPS_STATE_OFFSET), + "%8") + : "=&r"(bit), "=&r"(c->low), "=&r"(c->range), "=&q"(tmp) + : "r"(state), "r"(c), + "i"(offsetof(CABACContext, bytestream)), + "i"(offsetof(CABACContext, bytestream_end)) + TABLES_ARG + ,"1"(c->low), "2"(c->range) + : "%"REG_c, "memory" + ); + return bit & 1; +} +#endif /* HAVE_7REGS */ + +#define get_cabac_bypass_sign get_cabac_bypass_sign_x86 +static av_always_inline int get_cabac_bypass_sign_x86(CABACContext *c, int val) +{ + x86_reg tmp; + __asm__ volatile( + "movl %c6(%2), %k1 \n\t" + "movl %c3(%2), %%eax \n\t" + "shl $17, %k1 \n\t" + "add %%eax, %%eax \n\t" + "sub %k1, %%eax \n\t" + "cltd \n\t" + "and %%edx, %k1 \n\t" + "add %k1, %%eax \n\t" + "xor %%edx, %%ecx \n\t" + "sub %%edx, %%ecx \n\t" + "test %%ax, %%ax \n\t" + "jnz 1f \n\t" + "mov %c4(%2), %1 \n\t" + "subl $0xFFFF, %%eax \n\t" + "movzwl (%1), %%edx \n\t" + "bswap %%edx \n\t" + "shrl $15, %%edx \n\t" + "add $2, %1 \n\t" + "addl %%edx, %%eax \n\t" + "mov %1, %c4(%2) \n\t" + "1: \n\t" + "movl %%eax, %c3(%2) \n\t" + + : "+c"(val), "=&r"(tmp) + : "r"(c), + "i"(offsetof(CABACContext, low)), + "i"(offsetof(CABACContext, bytestream)), + "i"(offsetof(CABACContext, bytestream_end)), + "i"(offsetof(CABACContext, range)) + : "%eax", "%edx", "memory" + ); + return val; +} + +#endif /* HAVE_INLINE_ASM */ +#endif /* AVCODEC_X86_CABAC_H */ diff --git a/ffmpeg/libavcodec/x86/cavsdsp.c b/ffmpeg/libavcodec/x86/cavsdsp.c new file mode 100644 index 0000000..deeb5cf --- /dev/null +++ b/ffmpeg/libavcodec/x86/cavsdsp.c @@ -0,0 +1,512 @@ +/* + * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. + * Copyright (c) 2006 Stefan Gehrer + * + * MMX-optimized DSP functions, based on H.264 optimizations by + * Michael Niedermayer and Loren Merritt + * + * 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 "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/cavsdsp.h" +#include "dsputil_mmx.h" +#include "config.h" + +#if (HAVE_MMXEXT_INLINE || HAVE_AMD3DNOW_INLINE) + +/* in/out: mma=mma+mmb, mmb=mmb-mma */ +#define SUMSUB_BA( a, b ) \ + "paddw "#b", "#a" \n\t"\ + "paddw "#b", "#b" \n\t"\ + "psubw "#a", "#b" \n\t" + +/***************************************************************************** + * + * inverse transform + * + ****************************************************************************/ + +static inline void cavs_idct8_1d(int16_t *block, uint64_t bias) +{ + __asm__ volatile( + "movq 112(%0), %%mm4 \n\t" /* mm4 = src7 */ + "movq 16(%0), %%mm5 \n\t" /* mm5 = src1 */ + "movq 80(%0), %%mm2 \n\t" /* mm2 = src5 */ + "movq 48(%0), %%mm7 \n\t" /* mm7 = src3 */ + "movq %%mm4, %%mm0 \n\t" + "movq %%mm5, %%mm3 \n\t" + "movq %%mm2, %%mm6 \n\t" + "movq %%mm7, %%mm1 \n\t" + + "paddw %%mm4, %%mm4 \n\t" /* mm4 = 2*src7 */ + "paddw %%mm3, %%mm3 \n\t" /* mm3 = 2*src1 */ + "paddw %%mm6, %%mm6 \n\t" /* mm6 = 2*src5 */ + "paddw %%mm1, %%mm1 \n\t" /* mm1 = 2*src3 */ + "paddw %%mm4, %%mm0 \n\t" /* mm0 = 3*src7 */ + "paddw %%mm3, %%mm5 \n\t" /* mm5 = 3*src1 */ + "paddw %%mm6, %%mm2 \n\t" /* mm2 = 3*src5 */ + "paddw %%mm1, %%mm7 \n\t" /* mm7 = 3*src3 */ + "psubw %%mm4, %%mm5 \n\t" /* mm5 = 3*src1 - 2*src7 = a0 */ + "paddw %%mm6, %%mm7 \n\t" /* mm7 = 3*src3 + 2*src5 = a1 */ + "psubw %%mm2, %%mm1 \n\t" /* mm1 = 2*src3 - 3*src5 = a2 */ + "paddw %%mm0, %%mm3 \n\t" /* mm3 = 2*src1 + 3*src7 = a3 */ + + "movq %%mm5, %%mm4 \n\t" + "movq %%mm7, %%mm6 \n\t" + "movq %%mm3, %%mm0 \n\t" + "movq %%mm1, %%mm2 \n\t" + SUMSUB_BA( %%mm7, %%mm5 ) /* mm7 = a0 + a1 mm5 = a0 - a1 */ + "paddw %%mm3, %%mm7 \n\t" /* mm7 = a0 + a1 + a3 */ + "paddw %%mm1, %%mm5 \n\t" /* mm5 = a0 - a1 + a2 */ + "paddw %%mm7, %%mm7 \n\t" + "paddw %%mm5, %%mm5 \n\t" + "paddw %%mm6, %%mm7 \n\t" /* mm7 = b4 */ + "paddw %%mm4, %%mm5 \n\t" /* mm5 = b5 */ + + SUMSUB_BA( %%mm1, %%mm3 ) /* mm1 = a3 + a2 mm3 = a3 - a2 */ + "psubw %%mm1, %%mm4 \n\t" /* mm4 = a0 - a2 - a3 */ + "movq %%mm4, %%mm1 \n\t" /* mm1 = a0 - a2 - a3 */ + "psubw %%mm6, %%mm3 \n\t" /* mm3 = a3 - a2 - a1 */ + "paddw %%mm1, %%mm1 \n\t" + "paddw %%mm3, %%mm3 \n\t" + "psubw %%mm2, %%mm1 \n\t" /* mm1 = b7 */ + "paddw %%mm0, %%mm3 \n\t" /* mm3 = b6 */ + + "movq 32(%0), %%mm2 \n\t" /* mm2 = src2 */ + "movq 96(%0), %%mm6 \n\t" /* mm6 = src6 */ + "movq %%mm2, %%mm4 \n\t" + "movq %%mm6, %%mm0 \n\t" + "psllw $2, %%mm4 \n\t" /* mm4 = 4*src2 */ + "psllw $2, %%mm6 \n\t" /* mm6 = 4*src6 */ + "paddw %%mm4, %%mm2 \n\t" /* mm2 = 5*src2 */ + "paddw %%mm6, %%mm0 \n\t" /* mm0 = 5*src6 */ + "paddw %%mm2, %%mm2 \n\t" + "paddw %%mm0, %%mm0 \n\t" + "psubw %%mm0, %%mm4 \n\t" /* mm4 = 4*src2 - 10*src6 = a7 */ + "paddw %%mm2, %%mm6 \n\t" /* mm6 = 4*src6 + 10*src2 = a6 */ + + "movq (%0), %%mm2 \n\t" /* mm2 = src0 */ + "movq 64(%0), %%mm0 \n\t" /* mm0 = src4 */ + SUMSUB_BA( %%mm0, %%mm2 ) /* mm0 = src0+src4 mm2 = src0-src4 */ + "psllw $3, %%mm0 \n\t" + "psllw $3, %%mm2 \n\t" + "paddw %1, %%mm0 \n\t" /* add rounding bias */ + "paddw %1, %%mm2 \n\t" /* add rounding bias */ + + SUMSUB_BA( %%mm6, %%mm0 ) /* mm6 = a4 + a6 mm0 = a4 - a6 */ + SUMSUB_BA( %%mm4, %%mm2 ) /* mm4 = a5 + a7 mm2 = a5 - a7 */ + SUMSUB_BA( %%mm7, %%mm6 ) /* mm7 = dst0 mm6 = dst7 */ + SUMSUB_BA( %%mm5, %%mm4 ) /* mm5 = dst1 mm4 = dst6 */ + SUMSUB_BA( %%mm3, %%mm2 ) /* mm3 = dst2 mm2 = dst5 */ + SUMSUB_BA( %%mm1, %%mm0 ) /* mm1 = dst3 mm0 = dst4 */ + :: "r"(block), "m"(bias) + ); +} + +static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) +{ + int i; + DECLARE_ALIGNED(8, int16_t, b2)[64]; + + for(i=0; i<2; i++){ + DECLARE_ALIGNED(8, uint64_t, tmp); + + cavs_idct8_1d(block+4*i, ff_pw_4.a); + + __asm__ volatile( + "psraw $3, %%mm7 \n\t" + "psraw $3, %%mm6 \n\t" + "psraw $3, %%mm5 \n\t" + "psraw $3, %%mm4 \n\t" + "psraw $3, %%mm3 \n\t" + "psraw $3, %%mm2 \n\t" + "psraw $3, %%mm1 \n\t" + "psraw $3, %%mm0 \n\t" + "movq %%mm7, %0 \n\t" + TRANSPOSE4( %%mm0, %%mm2, %%mm4, %%mm6, %%mm7 ) + "movq %%mm0, 8(%1) \n\t" + "movq %%mm6, 24(%1) \n\t" + "movq %%mm7, 40(%1) \n\t" + "movq %%mm4, 56(%1) \n\t" + "movq %0, %%mm7 \n\t" + TRANSPOSE4( %%mm7, %%mm5, %%mm3, %%mm1, %%mm0 ) + "movq %%mm7, (%1) \n\t" + "movq %%mm1, 16(%1) \n\t" + "movq %%mm0, 32(%1) \n\t" + "movq %%mm3, 48(%1) \n\t" + : "=m"(tmp) + : "r"(b2+32*i) + : "memory" + ); + } + + for(i=0; i<2; i++){ + cavs_idct8_1d(b2+4*i, ff_pw_64.a); + + __asm__ volatile( + "psraw $7, %%mm7 \n\t" + "psraw $7, %%mm6 \n\t" + "psraw $7, %%mm5 \n\t" + "psraw $7, %%mm4 \n\t" + "psraw $7, %%mm3 \n\t" + "psraw $7, %%mm2 \n\t" + "psraw $7, %%mm1 \n\t" + "psraw $7, %%mm0 \n\t" + "movq %%mm7, (%0) \n\t" + "movq %%mm5, 16(%0) \n\t" + "movq %%mm3, 32(%0) \n\t" + "movq %%mm1, 48(%0) \n\t" + "movq %%mm0, 64(%0) \n\t" + "movq %%mm2, 80(%0) \n\t" + "movq %%mm4, 96(%0) \n\t" + "movq %%mm6, 112(%0) \n\t" + :: "r"(b2+4*i) + : "memory" + ); + } + + ff_add_pixels_clamped_mmx(b2, dst, stride); +} + +/***************************************************************************** + * + * motion compensation + * + ****************************************************************************/ + +/* vertical filter [-1 -2 96 42 -7 0] */ +#define QPEL_CAVSV1(A,B,C,D,E,F,OP,MUL2) \ + "movd (%0), "#F" \n\t"\ + "movq "#C", %%mm6 \n\t"\ + "pmullw %5, %%mm6 \n\t"\ + "movq "#D", %%mm7 \n\t"\ + "pmullw "MANGLE(MUL2)", %%mm7\n\t"\ + "psllw $3, "#E" \n\t"\ + "psubw "#E", %%mm6 \n\t"\ + "psraw $3, "#E" \n\t"\ + "paddw %%mm7, %%mm6 \n\t"\ + "paddw "#E", %%mm6 \n\t"\ + "paddw "#B", "#B" \n\t"\ + "pxor %%mm7, %%mm7 \n\t"\ + "add %2, %0 \n\t"\ + "punpcklbw %%mm7, "#F" \n\t"\ + "psubw "#B", %%mm6 \n\t"\ + "psraw $1, "#B" \n\t"\ + "psubw "#A", %%mm6 \n\t"\ + "paddw %4, %%mm6 \n\t"\ + "psraw $7, %%mm6 \n\t"\ + "packuswb %%mm6, %%mm6 \n\t"\ + OP(%%mm6, (%1), A, d) \ + "add %3, %1 \n\t" + +/* vertical filter [ 0 -1 5 5 -1 0] */ +#define QPEL_CAVSV2(A,B,C,D,E,F,OP,MUL2) \ + "movd (%0), "#F" \n\t"\ + "movq "#C", %%mm6 \n\t"\ + "paddw "#D", %%mm6 \n\t"\ + "pmullw %5, %%mm6 \n\t"\ + "add %2, %0 \n\t"\ + "punpcklbw %%mm7, "#F" \n\t"\ + "psubw "#B", %%mm6 \n\t"\ + "psubw "#E", %%mm6 \n\t"\ + "paddw %4, %%mm6 \n\t"\ + "psraw $3, %%mm6 \n\t"\ + "packuswb %%mm6, %%mm6 \n\t"\ + OP(%%mm6, (%1), A, d) \ + "add %3, %1 \n\t" + +/* vertical filter [ 0 -7 42 96 -2 -1] */ +#define QPEL_CAVSV3(A,B,C,D,E,F,OP,MUL2) \ + "movd (%0), "#F" \n\t"\ + "movq "#C", %%mm6 \n\t"\ + "pmullw "MANGLE(MUL2)", %%mm6\n\t"\ + "movq "#D", %%mm7 \n\t"\ + "pmullw %5, %%mm7 \n\t"\ + "psllw $3, "#B" \n\t"\ + "psubw "#B", %%mm6 \n\t"\ + "psraw $3, "#B" \n\t"\ + "paddw %%mm7, %%mm6 \n\t"\ + "paddw "#B", %%mm6 \n\t"\ + "paddw "#E", "#E" \n\t"\ + "pxor %%mm7, %%mm7 \n\t"\ + "add %2, %0 \n\t"\ + "punpcklbw %%mm7, "#F" \n\t"\ + "psubw "#E", %%mm6 \n\t"\ + "psraw $1, "#E" \n\t"\ + "psubw "#F", %%mm6 \n\t"\ + "paddw %4, %%mm6 \n\t"\ + "psraw $7, %%mm6 \n\t"\ + "packuswb %%mm6, %%mm6 \n\t"\ + OP(%%mm6, (%1), A, d) \ + "add %3, %1 \n\t" + + +#define QPEL_CAVSVNUM(VOP,OP,ADD,MUL1,MUL2)\ + int w= 2;\ + src -= 2*srcStride;\ + \ + while(w--){\ + __asm__ volatile(\ + "pxor %%mm7, %%mm7 \n\t"\ + "movd (%0), %%mm0 \n\t"\ + "add %2, %0 \n\t"\ + "movd (%0), %%mm1 \n\t"\ + "add %2, %0 \n\t"\ + "movd (%0), %%mm2 \n\t"\ + "add %2, %0 \n\t"\ + "movd (%0), %%mm3 \n\t"\ + "add %2, %0 \n\t"\ + "movd (%0), %%mm4 \n\t"\ + "add %2, %0 \n\t"\ + "punpcklbw %%mm7, %%mm0 \n\t"\ + "punpcklbw %%mm7, %%mm1 \n\t"\ + "punpcklbw %%mm7, %%mm2 \n\t"\ + "punpcklbw %%mm7, %%mm3 \n\t"\ + "punpcklbw %%mm7, %%mm4 \n\t"\ + VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, MUL2)\ + VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, MUL2)\ + VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, MUL2)\ + VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, MUL2)\ + VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP, MUL2)\ + VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP, MUL2)\ + VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, MUL2)\ + VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, MUL2)\ + \ + : "+a"(src), "+c"(dst)\ + : "S"((x86_reg)srcStride), "r"((x86_reg)dstStride), "m"(ADD), "m"(MUL1)\ + : "memory"\ + );\ + if(h==16){\ + __asm__ volatile(\ + VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, MUL2)\ + VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, MUL2)\ + VOP(%%mm4, %%mm5, %%mm0, %%mm1, %%mm2, %%mm3, OP, MUL2)\ + VOP(%%mm5, %%mm0, %%mm1, %%mm2, %%mm3, %%mm4, OP, MUL2)\ + VOP(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, OP, MUL2)\ + VOP(%%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm0, OP, MUL2)\ + VOP(%%mm2, %%mm3, %%mm4, %%mm5, %%mm0, %%mm1, OP, MUL2)\ + VOP(%%mm3, %%mm4, %%mm5, %%mm0, %%mm1, %%mm2, OP, MUL2)\ + \ + : "+a"(src), "+c"(dst)\ + : "S"((x86_reg)srcStride), "r"((x86_reg)dstStride), "m"(ADD), "m"(MUL1)\ + : "memory"\ + );\ + }\ + src += 4-(h+5)*srcStride;\ + dst += 4-h*dstStride;\ + } + +#define QPEL_CAVS(OPNAME, OP, MMX)\ +static void OPNAME ## cavs_qpel8_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + int h=8;\ + __asm__ volatile(\ + "pxor %%mm7, %%mm7 \n\t"\ + "movq %5, %%mm6 \n\t"\ + "1: \n\t"\ + "movq (%0), %%mm0 \n\t"\ + "movq 1(%0), %%mm2 \n\t"\ + "movq %%mm0, %%mm1 \n\t"\ + "movq %%mm2, %%mm3 \n\t"\ + "punpcklbw %%mm7, %%mm0 \n\t"\ + "punpckhbw %%mm7, %%mm1 \n\t"\ + "punpcklbw %%mm7, %%mm2 \n\t"\ + "punpckhbw %%mm7, %%mm3 \n\t"\ + "paddw %%mm2, %%mm0 \n\t"\ + "paddw %%mm3, %%mm1 \n\t"\ + "pmullw %%mm6, %%mm0 \n\t"\ + "pmullw %%mm6, %%mm1 \n\t"\ + "movq -1(%0), %%mm2 \n\t"\ + "movq 2(%0), %%mm4 \n\t"\ + "movq %%mm2, %%mm3 \n\t"\ + "movq %%mm4, %%mm5 \n\t"\ + "punpcklbw %%mm7, %%mm2 \n\t"\ + "punpckhbw %%mm7, %%mm3 \n\t"\ + "punpcklbw %%mm7, %%mm4 \n\t"\ + "punpckhbw %%mm7, %%mm5 \n\t"\ + "paddw %%mm4, %%mm2 \n\t"\ + "paddw %%mm3, %%mm5 \n\t"\ + "psubw %%mm2, %%mm0 \n\t"\ + "psubw %%mm5, %%mm1 \n\t"\ + "movq %6, %%mm5 \n\t"\ + "paddw %%mm5, %%mm0 \n\t"\ + "paddw %%mm5, %%mm1 \n\t"\ + "psraw $3, %%mm0 \n\t"\ + "psraw $3, %%mm1 \n\t"\ + "packuswb %%mm1, %%mm0 \n\t"\ + OP(%%mm0, (%1),%%mm5, q) \ + "add %3, %0 \n\t"\ + "add %4, %1 \n\t"\ + "decl %2 \n\t"\ + " jnz 1b \n\t"\ + : "+a"(src), "+c"(dst), "+m"(h)\ + : "d"((x86_reg)srcStride), "S"((x86_reg)dstStride), "m"(ff_pw_5), "m"(ff_pw_4)\ + : "memory"\ + );\ +}\ +\ +static inline void OPNAME ## cavs_qpel8or16_v1_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + QPEL_CAVSVNUM(QPEL_CAVSV1,OP,ff_pw_64,ff_pw_96,ff_pw_42) \ +}\ +\ +static inline void OPNAME ## cavs_qpel8or16_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + QPEL_CAVSVNUM(QPEL_CAVSV2,OP,ff_pw_4,ff_pw_5,ff_pw_5) \ +}\ +\ +static inline void OPNAME ## cavs_qpel8or16_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + QPEL_CAVSVNUM(QPEL_CAVSV3,OP,ff_pw_64,ff_pw_96,ff_pw_42) \ +}\ +\ +static void OPNAME ## cavs_qpel8_v1_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst , src , dstStride, srcStride, 8);\ +}\ +static void OPNAME ## cavs_qpel16_v1_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst , src , dstStride, srcStride, 16);\ + OPNAME ## cavs_qpel8or16_v1_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\ +}\ +\ +static void OPNAME ## cavs_qpel8_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst , src , dstStride, srcStride, 8);\ +}\ +static void OPNAME ## cavs_qpel16_v2_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst , src , dstStride, srcStride, 16);\ + OPNAME ## cavs_qpel8or16_v2_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\ +}\ +\ +static void OPNAME ## cavs_qpel8_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst , src , dstStride, srcStride, 8);\ +}\ +static void OPNAME ## cavs_qpel16_v3_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst , src , dstStride, srcStride, 16);\ + OPNAME ## cavs_qpel8or16_v3_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\ +}\ +\ +static void OPNAME ## cavs_qpel16_h_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + OPNAME ## cavs_qpel8_h_ ## MMX(dst , src , dstStride, srcStride);\ + OPNAME ## cavs_qpel8_h_ ## MMX(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + OPNAME ## cavs_qpel8_h_ ## MMX(dst , src , dstStride, srcStride);\ + OPNAME ## cavs_qpel8_h_ ## MMX(dst+8, src+8, dstStride, srcStride);\ +}\ + +#define CAVS_MC(OPNAME, SIZE, MMX) \ +static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc20_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## cavs_qpel ## SIZE ## _h_ ## MMX(dst, src, stride, stride);\ +}\ +\ +static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc01_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## cavs_qpel ## SIZE ## _v1_ ## MMX(dst, src, stride, stride);\ +}\ +\ +static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc02_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## cavs_qpel ## SIZE ## _v2_ ## MMX(dst, src, stride, stride);\ +}\ +\ +static void ff_ ## OPNAME ## cavs_qpel ## SIZE ## _mc03_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + OPNAME ## cavs_qpel ## SIZE ## _v3_ ## MMX(dst, src, stride, stride);\ +}\ + +#define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b " \n\t" +#define AVG_3DNOW_OP(a,b,temp, size) \ +"mov" #size " " #b ", " #temp " \n\t"\ +"pavgusb " #temp ", " #a " \n\t"\ +"mov" #size " " #a ", " #b " \n\t" +#define AVG_MMXEXT_OP(a, b, temp, size) \ +"mov" #size " " #b ", " #temp " \n\t"\ +"pavgb " #temp ", " #a " \n\t"\ +"mov" #size " " #a ", " #b " \n\t" + +#endif /* (HAVE_MMXEXT_INLINE || HAVE_AMD3DNOW_INLINE) */ + +#if HAVE_MMXEXT_INLINE +QPEL_CAVS(put_, PUT_OP, mmxext) +QPEL_CAVS(avg_, AVG_MMXEXT_OP, mmxext) + +CAVS_MC(put_, 8, mmxext) +CAVS_MC(put_, 16, mmxext) +CAVS_MC(avg_, 8, mmxext) +CAVS_MC(avg_, 16, mmxext) + +static av_cold void ff_cavsdsp_init_mmxext(CAVSDSPContext *c, + AVCodecContext *avctx) +{ +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_mmxext; \ + c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_mmxext; \ + c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_mmxext; \ + c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_mmxext; \ + c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_mmxext; \ + + dspfunc(put_cavs_qpel, 0, 16); + dspfunc(put_cavs_qpel, 1, 8); + dspfunc(avg_cavs_qpel, 0, 16); + dspfunc(avg_cavs_qpel, 1, 8); +#undef dspfunc + c->cavs_idct8_add = cavs_idct8_add_mmx; + c->idct_perm = FF_TRANSPOSE_IDCT_PERM; +} +#endif /* HAVE_MMXEXT_INLINE */ + +#if HAVE_AMD3DNOW_INLINE +QPEL_CAVS(put_, PUT_OP, 3dnow) +QPEL_CAVS(avg_, AVG_3DNOW_OP, 3dnow) + +CAVS_MC(put_, 8, 3dnow) +CAVS_MC(put_, 16,3dnow) +CAVS_MC(avg_, 8, 3dnow) +CAVS_MC(avg_, 16,3dnow) + +static av_cold void ff_cavsdsp_init_3dnow(CAVSDSPContext *c, + AVCodecContext *avctx) +{ +#define dspfunc(PFX, IDX, NUM) \ + c->PFX ## _pixels_tab[IDX][ 0] = ff_ ## PFX ## NUM ## _mc00_mmxext; \ + c->PFX ## _pixels_tab[IDX][ 2] = ff_ ## PFX ## NUM ## _mc20_3dnow; \ + c->PFX ## _pixels_tab[IDX][ 4] = ff_ ## PFX ## NUM ## _mc01_3dnow; \ + c->PFX ## _pixels_tab[IDX][ 8] = ff_ ## PFX ## NUM ## _mc02_3dnow; \ + c->PFX ## _pixels_tab[IDX][12] = ff_ ## PFX ## NUM ## _mc03_3dnow; \ + + dspfunc(put_cavs_qpel, 0, 16); + dspfunc(put_cavs_qpel, 1, 8); + dspfunc(avg_cavs_qpel, 0, 16); + dspfunc(avg_cavs_qpel, 1, 8); +#undef dspfunc + c->cavs_idct8_add = cavs_idct8_add_mmx; + c->idct_perm = FF_TRANSPOSE_IDCT_PERM; +} +#endif /* HAVE_AMD3DNOW_INLINE */ + +av_cold void ff_cavsdsp_init_x86(CAVSDSPContext *c, AVCodecContext *avctx) +{ + int mm_flags = av_get_cpu_flags(); + +#if HAVE_MMXEXT_INLINE + if (mm_flags & AV_CPU_FLAG_MMXEXT) ff_cavsdsp_init_mmxext(c, avctx); +#endif /* HAVE_MMXEXT_INLINE */ +#if HAVE_AMD3DNOW_INLINE + if (mm_flags & AV_CPU_FLAG_3DNOW) ff_cavsdsp_init_3dnow(c, avctx); +#endif /* HAVE_AMD3DNOW_INLINE */ +} diff --git a/ffmpeg/libavcodec/x86/constants.c b/ffmpeg/libavcodec/x86/constants.c new file mode 100644 index 0000000..821d73f --- /dev/null +++ b/ffmpeg/libavcodec/x86/constants.c @@ -0,0 +1,39 @@ +/* + * MMX/SSE constants used across x86 dsp optimizations. + * + * 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 "libavutil/mem.h" +#include "libavutil/x86/asm.h" // for xmm_reg + +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_1) = { 0x0001000100010001ULL, 0x0001000100010001ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_2) = { 0x0002000200020002ULL, 0x0002000200020002ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_3) = { 0x0003000300030003ULL, 0x0003000300030003ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_4) = { 0x0004000400040004ULL, 0x0004000400040004ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_5) = { 0x0005000500050005ULL, 0x0005000500050005ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_8) = { 0x0008000800080008ULL, 0x0008000800080008ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_9) = { 0x0009000900090009ULL, 0x0009000900090009ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_16) = { 0x0010001000100010ULL, 0x0010001000100010ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_18) = { 0x0012001200120012ULL, 0x0012001200120012ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_32) = { 0x0020002000200020ULL, 0x0020002000200020ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_64) = { 0x0040004000400040ULL, 0x0040004000400040ULL }; + +DECLARE_ALIGNED(16, const xmm_reg, ff_pb_0) = { 0x0000000000000000ULL, 0x0000000000000000ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pb_1) = { 0x0101010101010101ULL, 0x0101010101010101ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pb_3) = { 0x0303030303030303ULL, 0x0303030303030303ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pb_80) = { 0x8080808080808080ULL, 0x8080808080808080ULL }; diff --git a/ffmpeg/libavcodec/x86/dct32.asm b/ffmpeg/libavcodec/x86/dct32.asm new file mode 100644 index 0000000..6fd5ba3 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dct32.asm @@ -0,0 +1,490 @@ +;****************************************************************************** +;* 32 point SSE-optimized DCT transform +;* Copyright (c) 2010 Vitor Sessak +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +align 32 +ps_cos_vec: dd 0.500603, 0.505471, 0.515447, 0.531043 + dd 0.553104, 0.582935, 0.622504, 0.674808 + dd -10.190008, -3.407609, -2.057781, -1.484165 + dd -1.169440, -0.972568, -0.839350, -0.744536 + dd 0.502419, 0.522499, 0.566944, 0.646822 + dd 0.788155, 1.060678, 1.722447, 5.101149 + dd 0.509796, 0.601345, 0.899976, 2.562916 + dd 0.509796, 0.601345, 0.899976, 2.562916 + dd 1.000000, 1.000000, 1.306563, 0.541196 + dd 1.000000, 1.000000, 1.306563, 0.541196 + dd 1.000000, 0.707107, 1.000000, -0.707107 + dd 1.000000, 0.707107, 1.000000, -0.707107 + dd 0.707107, 0.707107, 0.707107, 0.707107 + +align 32 +ps_p1p1m1m1: dd 0, 0, 0x80000000, 0x80000000, 0, 0, 0x80000000, 0x80000000 + +%macro BUTTERFLY 4 + subps %4, %1, %2 + addps %2, %2, %1 + mulps %1, %4, %3 +%endmacro + +%macro BUTTERFLY0 5 +%if cpuflag(sse2) && notcpuflag(avx) + pshufd %4, %1, %5 + xorps %1, %2 + addps %1, %4 + mulps %1, %3 +%else + shufps %4, %1, %1, %5 + xorps %1, %1, %2 + addps %4, %4, %1 + mulps %1, %4, %3 +%endif +%endmacro + +%macro BUTTERFLY2 4 + BUTTERFLY0 %1, %2, %3, %4, 0x1b +%endmacro + +%macro BUTTERFLY3 4 + BUTTERFLY0 %1, %2, %3, %4, 0xb1 +%endmacro + +%macro BUTTERFLY3V 5 + movaps m%5, m%1 + addps m%1, m%2 + subps m%5, m%2 + SWAP %2, %5 + mulps m%2, [ps_cos_vec+192] + movaps m%5, m%3 + addps m%3, m%4 + subps m%4, m%5 + mulps m%4, [ps_cos_vec+192] +%endmacro + +%macro PASS6_AND_PERMUTE 0 + mov tmpd, [outq+4] + movss m7, [outq+72] + addss m7, [outq+76] + movss m3, [outq+56] + addss m3, [outq+60] + addss m4, m3 + movss m2, [outq+52] + addss m2, m3 + movss m3, [outq+104] + addss m3, [outq+108] + addss m1, m3 + addss m5, m4 + movss [outq+ 16], m1 + movss m1, [outq+100] + addss m1, m3 + movss m3, [outq+40] + movss [outq+ 48], m1 + addss m3, [outq+44] + movss m1, [outq+100] + addss m4, m3 + addss m3, m2 + addss m1, [outq+108] + movss [outq+ 40], m3 + addss m2, [outq+36] + movss m3, [outq+8] + movss [outq+ 56], m2 + addss m3, [outq+12] + movss [outq+ 32], m3 + movss m3, [outq+80] + movss [outq+ 8], m5 + movss [outq+ 80], m1 + movss m2, [outq+52] + movss m5, [outq+120] + addss m5, [outq+124] + movss m1, [outq+64] + addss m2, [outq+60] + addss m0, m5 + addss m5, [outq+116] + mov [outq+64], tmpd + addss m6, m0 + addss m1, m6 + mov tmpd, [outq+12] + mov [outq+ 96], tmpd + movss [outq+ 4], m1 + movss m1, [outq+24] + movss [outq+ 24], m4 + movss m4, [outq+88] + addss m4, [outq+92] + addss m3, m4 + addss m4, [outq+84] + mov tmpd, [outq+108] + addss m1, [outq+28] + addss m0, m1 + addss m1, m5 + addss m6, m3 + addss m3, m0 + addss m0, m7 + addss m5, [outq+20] + addss m7, m1 + movss [outq+ 12], m6 + mov [outq+112], tmpd + movss m6, [outq+28] + movss [outq+ 28], m0 + movss m0, [outq+36] + movss [outq+ 36], m7 + addss m1, m4 + movss m7, [outq+116] + addss m0, m2 + addss m7, [outq+124] + movss [outq+ 72], m0 + movss m0, [outq+44] + addss m2, m0 + movss [outq+ 44], m1 + movss [outq+ 88], m2 + addss m0, [outq+60] + mov tmpd, [outq+60] + mov [outq+120], tmpd + movss [outq+104], m0 + addss m4, m5 + addss m5, [outq+68] + movss [outq+52], m4 + movss [outq+60], m5 + movss m4, [outq+68] + movss m5, [outq+20] + movss [outq+ 20], m3 + addss m5, m7 + addss m7, m6 + addss m4, m5 + movss m2, [outq+84] + addss m2, [outq+92] + addss m5, m2 + movss [outq+ 68], m4 + addss m2, m7 + movss m4, [outq+76] + movss [outq+ 84], m2 + movss [outq+ 76], m5 + addss m7, m4 + addss m6, [outq+124] + addss m4, m6 + addss m6, [outq+92] + movss [outq+100], m4 + movss [outq+108], m6 + movss m6, [outq+92] + movss [outq+92], m7 + addss m6, [outq+124] + movss [outq+116], m6 +%endmacro + +INIT_YMM avx +SECTION_TEXT +%if HAVE_AVX_EXTERNAL +; void ff_dct32_float_avx(FFTSample *out, const FFTSample *in) +cglobal dct32_float, 2,3,8, out, in, tmp + ; pass 1 + vmovaps m4, [inq+0] + vinsertf128 m5, m5, [inq+96], 1 + vinsertf128 m5, m5, [inq+112], 0 + vshufps m5, m5, m5, 0x1b + BUTTERFLY m4, m5, [ps_cos_vec], m6 + + vmovaps m2, [inq+64] + vinsertf128 m6, m6, [inq+32], 1 + vinsertf128 m6, m6, [inq+48], 0 + vshufps m6, m6, m6, 0x1b + BUTTERFLY m2, m6, [ps_cos_vec+32], m0 + + ; pass 2 + + BUTTERFLY m5, m6, [ps_cos_vec+64], m0 + BUTTERFLY m4, m2, [ps_cos_vec+64], m7 + + + ; pass 3 + vperm2f128 m3, m6, m4, 0x31 + vperm2f128 m1, m6, m4, 0x20 + vshufps m3, m3, m3, 0x1b + + BUTTERFLY m1, m3, [ps_cos_vec+96], m6 + + + vperm2f128 m4, m5, m2, 0x20 + vperm2f128 m5, m5, m2, 0x31 + vshufps m5, m5, m5, 0x1b + + BUTTERFLY m4, m5, [ps_cos_vec+96], m6 + + ; pass 4 + vmovaps m6, [ps_p1p1m1m1+0] + vmovaps m2, [ps_cos_vec+128] + + BUTTERFLY2 m5, m6, m2, m7 + BUTTERFLY2 m4, m6, m2, m7 + BUTTERFLY2 m1, m6, m2, m7 + BUTTERFLY2 m3, m6, m2, m7 + + + ; pass 5 + vshufps m6, m6, m6, 0xcc + vmovaps m2, [ps_cos_vec+160] + + BUTTERFLY3 m5, m6, m2, m7 + BUTTERFLY3 m4, m6, m2, m7 + BUTTERFLY3 m1, m6, m2, m7 + BUTTERFLY3 m3, m6, m2, m7 + + vperm2f128 m6, m3, m3, 0x31 + vmovaps [outq], m3 + + vextractf128 [outq+64], m5, 1 + vextractf128 [outq+32], m5, 0 + + vextractf128 [outq+80], m4, 1 + vextractf128 [outq+48], m4, 0 + + vperm2f128 m0, m1, m1, 0x31 + vmovaps [outq+96], m1 + + vzeroupper + + ; pass 6, no SIMD... +INIT_XMM + PASS6_AND_PERMUTE + RET +%endif + +%if ARCH_X86_64 +%define SPILL SWAP +%define UNSPILL SWAP + +%macro PASS5 0 + nop ; FIXME code alignment + SWAP 5, 8 + SWAP 4, 12 + SWAP 6, 14 + SWAP 7, 13 + SWAP 0, 15 + PERMUTE 9,10, 10,12, 11,14, 12,9, 13,11, 14,13 + TRANSPOSE4x4PS 8, 9, 10, 11, 0 + BUTTERFLY3V 8, 9, 10, 11, 0 + addps m10, m11 + TRANSPOSE4x4PS 12, 13, 14, 15, 0 + BUTTERFLY3V 12, 13, 14, 15, 0 + addps m14, m15 + addps m12, m14 + addps m14, m13 + addps m13, m15 +%endmacro + +%macro PASS6 0 + SWAP 9, 12 + SWAP 11, 14 + movss [outq+0x00], m8 + pshuflw m0, m8, 0xe + movss [outq+0x10], m9 + pshuflw m1, m9, 0xe + movss [outq+0x20], m10 + pshuflw m2, m10, 0xe + movss [outq+0x30], m11 + pshuflw m3, m11, 0xe + movss [outq+0x40], m12 + pshuflw m4, m12, 0xe + movss [outq+0x50], m13 + pshuflw m5, m13, 0xe + movss [outq+0x60], m14 + pshuflw m6, m14, 0xe + movaps [outq+0x70], m15 + pshuflw m7, m15, 0xe + addss m0, m1 + addss m1, m2 + movss [outq+0x08], m0 + addss m2, m3 + movss [outq+0x18], m1 + addss m3, m4 + movss [outq+0x28], m2 + addss m4, m5 + movss [outq+0x38], m3 + addss m5, m6 + movss [outq+0x48], m4 + addss m6, m7 + movss [outq+0x58], m5 + movss [outq+0x68], m6 + movss [outq+0x78], m7 + + PERMUTE 1,8, 3,9, 5,10, 7,11, 9,12, 11,13, 13,14, 8,1, 10,3, 12,5, 14,7 + movhlps m0, m1 + pshufd m1, m1, 3 + SWAP 0, 2, 4, 6, 8, 10, 12, 14 + SWAP 1, 3, 5, 7, 9, 11, 13, 15 +%rep 7 + movhlps m0, m1 + pshufd m1, m1, 3 + addss m15, m1 + SWAP 0, 2, 4, 6, 8, 10, 12, 14 + SWAP 1, 3, 5, 7, 9, 11, 13, 15 +%endrep +%assign i 4 +%rep 15 + addss m0, m1 + movss [outq+i], m0 + SWAP 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + %assign i i+8 +%endrep +%endmacro + +%else ; ARCH_X86_32 +%macro SPILL 2 ; xmm#, mempos + movaps [outq+(%2-8)*16], m%1 +%endmacro +%macro UNSPILL 2 + movaps m%1, [outq+(%2-8)*16] +%endmacro + +%define PASS6 PASS6_AND_PERMUTE +%macro PASS5 0 + movaps m2, [ps_cos_vec+160] + shufps m3, m3, 0xcc + + BUTTERFLY3 m5, m3, m2, m1 + SPILL 5, 8 + + UNSPILL 1, 9 + BUTTERFLY3 m1, m3, m2, m5 + SPILL 1, 14 + + BUTTERFLY3 m4, m3, m2, m5 + SPILL 4, 12 + + BUTTERFLY3 m7, m3, m2, m5 + SPILL 7, 13 + + UNSPILL 5, 10 + BUTTERFLY3 m5, m3, m2, m7 + SPILL 5, 10 + + UNSPILL 4, 11 + BUTTERFLY3 m4, m3, m2, m7 + SPILL 4, 11 + + BUTTERFLY3 m6, m3, m2, m7 + SPILL 6, 9 + + BUTTERFLY3 m0, m3, m2, m7 + SPILL 0, 15 +%endmacro +%endif + + +; void ff_dct32_float_sse(FFTSample *out, const FFTSample *in) +%macro DCT32_FUNC 0 +cglobal dct32_float, 2, 3, 16, out, in, tmp + ; pass 1 + + movaps m0, [inq+0] + LOAD_INV m1, [inq+112] + BUTTERFLY m0, m1, [ps_cos_vec], m3 + + movaps m7, [inq+64] + LOAD_INV m4, [inq+48] + BUTTERFLY m7, m4, [ps_cos_vec+32], m3 + + ; pass 2 + movaps m2, [ps_cos_vec+64] + BUTTERFLY m1, m4, m2, m3 + SPILL 1, 11 + SPILL 4, 8 + + ; pass 1 + movaps m1, [inq+16] + LOAD_INV m6, [inq+96] + BUTTERFLY m1, m6, [ps_cos_vec+16], m3 + + movaps m4, [inq+80] + LOAD_INV m5, [inq+32] + BUTTERFLY m4, m5, [ps_cos_vec+48], m3 + + ; pass 2 + BUTTERFLY m0, m7, m2, m3 + + movaps m2, [ps_cos_vec+80] + BUTTERFLY m6, m5, m2, m3 + + BUTTERFLY m1, m4, m2, m3 + + ; pass 3 + movaps m2, [ps_cos_vec+96] + shufps m1, m1, 0x1b + BUTTERFLY m0, m1, m2, m3 + SPILL 0, 15 + SPILL 1, 14 + + UNSPILL 0, 8 + shufps m5, m5, 0x1b + BUTTERFLY m0, m5, m2, m3 + + UNSPILL 1, 11 + shufps m6, m6, 0x1b + BUTTERFLY m1, m6, m2, m3 + SPILL 1, 11 + + shufps m4, m4, 0x1b + BUTTERFLY m7, m4, m2, m3 + + ; pass 4 + movaps m3, [ps_p1p1m1m1+0] + movaps m2, [ps_cos_vec+128] + + BUTTERFLY2 m5, m3, m2, m1 + + BUTTERFLY2 m0, m3, m2, m1 + SPILL 0, 9 + + BUTTERFLY2 m6, m3, m2, m1 + SPILL 6, 10 + + UNSPILL 0, 11 + BUTTERFLY2 m0, m3, m2, m1 + SPILL 0, 11 + + BUTTERFLY2 m4, m3, m2, m1 + + BUTTERFLY2 m7, m3, m2, m1 + + UNSPILL 6, 14 + BUTTERFLY2 m6, m3, m2, m1 + + UNSPILL 0, 15 + BUTTERFLY2 m0, m3, m2, m1 + + PASS5 + PASS6 + RET +%endmacro + +%macro LOAD_INV 2 +%if cpuflag(sse2) + pshufd %1, %2, 0x1b +%elif cpuflag(sse) + movaps %1, %2 + shufps %1, %1, 0x1b +%endif +%endmacro + +INIT_XMM sse +DCT32_FUNC +INIT_XMM sse2 +DCT32_FUNC diff --git a/ffmpeg/libavcodec/x86/deinterlace.asm b/ffmpeg/libavcodec/x86/deinterlace.asm new file mode 100644 index 0000000..3812dbe --- /dev/null +++ b/ffmpeg/libavcodec/x86/deinterlace.asm @@ -0,0 +1,82 @@ +;****************************************************************************** +;* MMX optimized deinterlacing functions +;* Copyright (c) 2010 Vitor Sessak +;* Copyright (c) 2002 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_4 + +SECTION .text + +%macro DEINTERLACE 1 +%ifidn %1, inplace +;void ff_deinterlace_line_inplace_mmx(const uint8_t *lum_m4, const uint8_t *lum_m3, const uint8_t *lum_m2, const uint8_t *lum_m1, const uint8_t *lum, int size) +cglobal deinterlace_line_inplace_mmx, 6,6,7, lum_m4, lum_m3, lum_m2, lum_m1, lum, size +%else +;void ff_deinterlace_line_mmx(uint8_t *dst, const uint8_t *lum_m4, const uint8_t *lum_m3, const uint8_t *lum_m2, const uint8_t *lum_m1, const uint8_t *lum, int size) +cglobal deinterlace_line_mmx, 7,7,7, dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size +%endif + pxor mm7, mm7 + movq mm6, [pw_4] +.nextrow: + movd mm0, [lum_m4q] + movd mm1, [lum_m3q] + movd mm2, [lum_m2q] +%ifidn %1, inplace + movd [lum_m4q], mm2 +%endif + movd mm3, [lum_m1q] + movd mm4, [lumq] + punpcklbw mm0, mm7 + punpcklbw mm1, mm7 + punpcklbw mm2, mm7 + punpcklbw mm3, mm7 + punpcklbw mm4, mm7 + paddw mm1, mm3 + psllw mm2, 1 + paddw mm0, mm4 + psllw mm1, 2 + paddw mm2, mm6 + paddw mm1, mm2 + psubusw mm1, mm0 + psrlw mm1, 3 + packuswb mm1, mm7 +%ifidn %1, inplace + movd [lum_m2q], mm1 +%else + movd [dstq], mm1 + add dstq, 4 +%endif + add lum_m4q, 4 + add lum_m3q, 4 + add lum_m2q, 4 + add lum_m1q, 4 + add lumq, 4 + sub sized, 4 + jg .nextrow + REP_RET +%endmacro + +DEINTERLACE "" + +DEINTERLACE inplace diff --git a/ffmpeg/libavcodec/x86/dirac_dwt.c b/ffmpeg/libavcodec/x86/dirac_dwt.c new file mode 100644 index 0000000..fbb25a4 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dirac_dwt.c @@ -0,0 +1,202 @@ +/* + * MMX optimized discrete wavelet transform + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2010 David Conrad + * + * 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 "libavutil/x86/asm.h" +#include "dsputil_mmx.h" +#include "dirac_dwt.h" + +#define COMPOSE_VERTICAL(ext, align) \ +void ff_vertical_compose53iL0##ext(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width); \ +void ff_vertical_compose_dirac53iH0##ext(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width); \ +void ff_vertical_compose_dd137iL0##ext(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, int width); \ +void ff_vertical_compose_dd97iH0##ext(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, int width); \ +void ff_vertical_compose_haar##ext(IDWTELEM *b0, IDWTELEM *b1, int width); \ +void ff_horizontal_compose_haar0i##ext(IDWTELEM *b, IDWTELEM *tmp, int w);\ +void ff_horizontal_compose_haar1i##ext(IDWTELEM *b, IDWTELEM *tmp, int w);\ +\ +static void vertical_compose53iL0##ext(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width) \ +{ \ + int i, width_align = width&~(align-1); \ +\ + for(i=width_align; i>1;\ + int x= w2 - (w2&(align-1));\ + ff_horizontal_compose_haar0i##ext(b, tmp, w);\ +\ + for (; x < w2; x++) {\ + b[2*x ] = tmp[x];\ + b[2*x+1] = COMPOSE_HAARiH0(b[x+w2], tmp[x]);\ + }\ +}\ +static void horizontal_compose_haar1i##ext(IDWTELEM *b, IDWTELEM *tmp, int w)\ +{\ + int w2= w>>1;\ + int x= w2 - (w2&(align-1));\ + ff_horizontal_compose_haar1i##ext(b, tmp, w);\ +\ + for (; x < w2; x++) {\ + b[2*x ] = (tmp[x] + 1)>>1;\ + b[2*x+1] = (COMPOSE_HAARiH0(b[x+w2], tmp[x]) + 1)>>1;\ + }\ +}\ +\ + +#if HAVE_YASM +#if !ARCH_X86_64 +COMPOSE_VERTICAL(_mmx, 4) +#endif +COMPOSE_VERTICAL(_sse2, 8) + + +void ff_horizontal_compose_dd97i_ssse3(IDWTELEM *b, IDWTELEM *tmp, int w); + +static void horizontal_compose_dd97i_ssse3(IDWTELEM *b, IDWTELEM *tmp, int w) +{ + int w2= w>>1; + int x= w2 - (w2&7); + ff_horizontal_compose_dd97i_ssse3(b, tmp, w); + + for (; x < w2; x++) { + b[2*x ] = (tmp[x] + 1)>>1; + b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1; + } +} +#endif + +void ff_spatial_idwt_init_mmx(DWTContext *d, enum dwt_type type) +{ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + +#if !ARCH_X86_64 + if (!(mm_flags & AV_CPU_FLAG_MMX)) + return; + + switch (type) { + case DWT_DIRAC_DD9_7: + d->vertical_compose_l0 = (void*)vertical_compose53iL0_mmx; + d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0_mmx; + break; + case DWT_DIRAC_LEGALL5_3: + d->vertical_compose_l0 = (void*)vertical_compose53iL0_mmx; + d->vertical_compose_h0 = (void*)vertical_compose_dirac53iH0_mmx; + break; + case DWT_DIRAC_DD13_7: + d->vertical_compose_l0 = (void*)vertical_compose_dd137iL0_mmx; + d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0_mmx; + break; + case DWT_DIRAC_HAAR0: + d->vertical_compose = (void*)vertical_compose_haar_mmx; + d->horizontal_compose = horizontal_compose_haar0i_mmx; + break; + case DWT_DIRAC_HAAR1: + d->vertical_compose = (void*)vertical_compose_haar_mmx; + d->horizontal_compose = horizontal_compose_haar1i_mmx; + break; + } +#endif + + if (!(mm_flags & AV_CPU_FLAG_SSE2)) + return; + + switch (type) { + case DWT_DIRAC_DD9_7: + d->vertical_compose_l0 = (void*)vertical_compose53iL0_sse2; + d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0_sse2; + break; + case DWT_DIRAC_LEGALL5_3: + d->vertical_compose_l0 = (void*)vertical_compose53iL0_sse2; + d->vertical_compose_h0 = (void*)vertical_compose_dirac53iH0_sse2; + break; + case DWT_DIRAC_DD13_7: + d->vertical_compose_l0 = (void*)vertical_compose_dd137iL0_sse2; + d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0_sse2; + break; + case DWT_DIRAC_HAAR0: + d->vertical_compose = (void*)vertical_compose_haar_sse2; + d->horizontal_compose = horizontal_compose_haar0i_sse2; + break; + case DWT_DIRAC_HAAR1: + d->vertical_compose = (void*)vertical_compose_haar_sse2; + d->horizontal_compose = horizontal_compose_haar1i_sse2; + break; + } + + if (!(mm_flags & AV_CPU_FLAG_SSSE3)) + return; + + switch (type) { + case DWT_DIRAC_DD9_7: + d->horizontal_compose = horizontal_compose_dd97i_ssse3; + break; + } +#endif // HAVE_YASM +} diff --git a/ffmpeg/libavcodec/x86/dirac_dwt.h b/ffmpeg/libavcodec/x86/dirac_dwt.h new file mode 100644 index 0000000..126b290 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dirac_dwt.h @@ -0,0 +1,30 @@ +/* + * 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 + */ + +#ifndef AVCODEC_X86_DIRAC_DWT_H +#define AVCODEC_X86_DIRAC_DWT_H + +#include "libavcodec/dirac_dwt.h" + +void ff_horizontal_compose_dd97i_end_c(IDWTELEM *b, IDWTELEM *tmp, int w2, int x); +void ff_horizontal_compose_haar1i_end_c(IDWTELEM *b, IDWTELEM *tmp, int w2, int x); +void ff_horizontal_compose_haar0i_end_c(IDWTELEM *b, IDWTELEM *tmp, int w2, int x); + +void ff_spatial_idwt_init_mmx(DWTContext *d, enum dwt_type type); + +#endif diff --git a/ffmpeg/libavcodec/x86/diracdsp_mmx.c b/ffmpeg/libavcodec/x86/diracdsp_mmx.c new file mode 100644 index 0000000..cb6465f --- /dev/null +++ b/ffmpeg/libavcodec/x86/diracdsp_mmx.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010 David Conrad + * + * 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 "dsputil_mmx.h" +#include "diracdsp_mmx.h" + +void ff_put_rect_clamped_mmx(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); +void ff_put_rect_clamped_sse2(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); +void ff_put_signed_rect_clamped_mmx(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); +void ff_put_signed_rect_clamped_sse2(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); + +#define HPEL_FILTER(MMSIZE, EXT) \ + void ff_dirac_hpel_filter_v_ ## EXT(uint8_t *, const uint8_t *, int, int); \ + void ff_dirac_hpel_filter_h_ ## EXT(uint8_t *, const uint8_t *, int); \ + \ + static void dirac_hpel_filter_ ## EXT(uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, \ + const uint8_t *src, int stride, int width, int height) \ + { \ + while( height-- ) \ + { \ + ff_dirac_hpel_filter_v_ ## EXT(dstv-MMSIZE, src-MMSIZE, stride, width+MMSIZE+5); \ + ff_dirac_hpel_filter_h_ ## EXT(dsth, src, width); \ + ff_dirac_hpel_filter_h_ ## EXT(dstc, dstv, width); \ + \ + dsth += stride; \ + dstv += stride; \ + dstc += stride; \ + src += stride; \ + } \ + } + +#if !ARCH_X86_64 +HPEL_FILTER(8, mmx) +#endif +HPEL_FILTER(16, sse2) + +#define PIXFUNC(PFX, IDX, EXT) \ + /*MMXDISABLEDc->PFX ## _dirac_pixels_tab[0][IDX] = ff_ ## PFX ## _dirac_pixels8_ ## EXT;*/ \ + c->PFX ## _dirac_pixels_tab[1][IDX] = ff_ ## PFX ## _dirac_pixels16_ ## EXT; \ + c->PFX ## _dirac_pixels_tab[2][IDX] = ff_ ## PFX ## _dirac_pixels32_ ## EXT + +void ff_diracdsp_init_mmx(DiracDSPContext* c) +{ + int mm_flags = av_get_cpu_flags(); + + if (!(mm_flags & AV_CPU_FLAG_MMX)) + return; + +#if HAVE_YASM + c->add_dirac_obmc[0] = ff_add_dirac_obmc8_mmx; +#if !ARCH_X86_64 + c->add_dirac_obmc[1] = ff_add_dirac_obmc16_mmx; + c->add_dirac_obmc[2] = ff_add_dirac_obmc32_mmx; + c->dirac_hpel_filter = dirac_hpel_filter_mmx; + c->add_rect_clamped = ff_add_rect_clamped_mmx; + c->put_signed_rect_clamped = ff_put_signed_rect_clamped_mmx; +#endif +#endif + +#if HAVE_MMX_INLINE + PIXFUNC(put, 0, mmx); + PIXFUNC(avg, 0, mmx); +#endif + +#if HAVE_MMXEXT_INLINE + if (mm_flags & AV_CPU_FLAG_MMX2) { + PIXFUNC(avg, 0, mmxext); + } +#endif + + if (mm_flags & AV_CPU_FLAG_SSE2) { +#if HAVE_YASM + c->dirac_hpel_filter = dirac_hpel_filter_sse2; + c->add_rect_clamped = ff_add_rect_clamped_sse2; + c->put_signed_rect_clamped = ff_put_signed_rect_clamped_sse2; + + c->add_dirac_obmc[1] = ff_add_dirac_obmc16_sse2; + c->add_dirac_obmc[2] = ff_add_dirac_obmc32_sse2; +#endif +#if HAVE_SSE2_INLINE + c->put_dirac_pixels_tab[1][0] = ff_put_dirac_pixels16_sse2; + c->avg_dirac_pixels_tab[1][0] = ff_avg_dirac_pixels16_sse2; + c->put_dirac_pixels_tab[2][0] = ff_put_dirac_pixels32_sse2; + c->avg_dirac_pixels_tab[2][0] = ff_avg_dirac_pixels32_sse2; +#endif + } +} diff --git a/ffmpeg/libavcodec/x86/diracdsp_mmx.h b/ffmpeg/libavcodec/x86/diracdsp_mmx.h new file mode 100644 index 0000000..8985854 --- /dev/null +++ b/ffmpeg/libavcodec/x86/diracdsp_mmx.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010 David Conrad + * + * 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 + */ + +#ifndef AVCODEC_X86_DIRACDSP_H +#define AVCODEC_X86_DIRACDSP_H + +#include "libavcodec/diracdsp.h" + +void ff_diracdsp_init_mmx(DiracDSPContext* c); + +DECL_DIRAC_PIXOP(put, mmx); +DECL_DIRAC_PIXOP(avg, mmx); +DECL_DIRAC_PIXOP(avg, mmxext); + +void ff_put_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); +void ff_avg_dirac_pixels16_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); +void ff_put_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); +void ff_avg_dirac_pixels32_sse2(uint8_t *dst, const uint8_t *src[5], int stride, int h); + +void ff_add_rect_clamped_mmx(uint8_t *, const uint16_t *, int, const int16_t *, int, int, int); +void ff_add_rect_clamped_sse2(uint8_t *, const uint16_t *, int, const int16_t *, int, int, int); + +void ff_add_dirac_obmc8_mmx(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); +void ff_add_dirac_obmc16_mmx(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); +void ff_add_dirac_obmc32_mmx(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); + +void ff_add_dirac_obmc16_sse2(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); +void ff_add_dirac_obmc32_sse2(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); + +#endif diff --git a/ffmpeg/libavcodec/x86/diracdsp_yasm.asm b/ffmpeg/libavcodec/x86/diracdsp_yasm.asm new file mode 100644 index 0000000..3e9765b --- /dev/null +++ b/ffmpeg/libavcodec/x86/diracdsp_yasm.asm @@ -0,0 +1,264 @@ +;****************************************************************************** +;* Copyright (c) 2010 David Conrad +;* +;* 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 +;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pw_3: times 8 dw 3 +pw_7: times 8 dw 7 +pw_16: times 8 dw 16 +pw_32: times 8 dw 32 +pb_128: times 16 db 128 + +section .text + +%macro UNPACK_ADD 6 + mov%5 %1, %3 + mov%6 m5, %4 + mova m4, %1 + mova %2, m5 + punpcklbw %1, m7 + punpcklbw m5, m7 + punpckhbw m4, m7 + punpckhbw %2, m7 + paddw %1, m5 + paddw %2, m4 +%endmacro + +%macro HPEL_FILTER 1 +; dirac_hpel_filter_v_sse2(uint8_t *dst, uint8_t *src, int stride, int width); +cglobal dirac_hpel_filter_v_%1, 4,6,8, dst, src, stride, width, src0, stridex3 + mov src0q, srcq + lea stridex3q, [3*strideq] + sub src0q, stridex3q + pxor m7, m7 +.loop: + ; 7*(src[0] + src[1]) + UNPACK_ADD m0, m1, [srcq], [srcq + strideq], a,a + pmullw m0, [pw_7] + pmullw m1, [pw_7] + + ; 3*( ... + src[-2] + src[3]) + UNPACK_ADD m2, m3, [src0q + strideq], [srcq + stridex3q], a,a + paddw m0, m2 + paddw m1, m3 + pmullw m0, [pw_3] + pmullw m1, [pw_3] + + ; ... - 7*(src[-1] + src[2]) + UNPACK_ADD m2, m3, [src0q + strideq*2], [srcq + strideq*2], a,a + pmullw m2, [pw_7] + pmullw m3, [pw_7] + psubw m0, m2 + psubw m1, m3 + + ; ... - (src[-3] + src[4]) + UNPACK_ADD m2, m3, [src0q], [srcq + strideq*4], a,a + psubw m0, m2 + psubw m1, m3 + + paddw m0, [pw_16] + paddw m1, [pw_16] + psraw m0, 5 + psraw m1, 5 + packuswb m0, m1 + mova [dstq], m0 + add dstq, mmsize + add srcq, mmsize + add src0q, mmsize + sub widthd, mmsize + jg .loop + RET + +; dirac_hpel_filter_h_sse2(uint8_t *dst, uint8_t *src, int width); +cglobal dirac_hpel_filter_h_%1, 3,3,8, dst, src, width + dec widthd + pxor m7, m7 + and widthd, ~(mmsize-1) +.loop: + ; 7*(src[0] + src[1]) + UNPACK_ADD m0, m1, [srcq + widthq], [srcq + widthq + 1], u,u + pmullw m0, [pw_7] + pmullw m1, [pw_7] + + ; 3*( ... + src[-2] + src[3]) + UNPACK_ADD m2, m3, [srcq + widthq - 2], [srcq + widthq + 3], u,u + paddw m0, m2 + paddw m1, m3 + pmullw m0, [pw_3] + pmullw m1, [pw_3] + + ; ... - 7*(src[-1] + src[2]) + UNPACK_ADD m2, m3, [srcq + widthq - 1], [srcq + widthq + 2], u,u + pmullw m2, [pw_7] + pmullw m3, [pw_7] + psubw m0, m2 + psubw m1, m3 + + ; ... - (src[-3] + src[4]) + UNPACK_ADD m2, m3, [srcq + widthq - 3], [srcq + widthq + 4], u,u + psubw m0, m2 + psubw m1, m3 + + paddw m0, [pw_16] + paddw m1, [pw_16] + psraw m0, 5 + psraw m1, 5 + packuswb m0, m1 + mova [dstq + widthq], m0 + sub widthd, mmsize + jge .loop + RET +%endmacro + +%macro PUT_RECT 1 +; void put_rect_clamped(uint8_t *dst, int dst_stride, int16_t *src, int src_stride, int width, int height) +cglobal put_signed_rect_clamped_%1, 5,9,3, dst, dst_stride, src, src_stride, w, dst2, src2 + mova m0, [pb_128] + add wd, (mmsize-1) + and wd, ~(mmsize-1) + +%if ARCH_X86_64 + movsxd dst_strideq, dst_strided + movsxd src_strideq, src_strided + mov r7d, r5m + mov r8d, wd + %define wspill r8d + %define hd r7d +%else + mov r4m, wd + %define wspill r4m + %define hd r5mp +%endif + +.loopy + lea src2q, [srcq+src_strideq*2] + lea dst2q, [dstq+dst_strideq] +.loopx: + sub wd, mmsize + mova m1, [srcq +2*wq] + mova m2, [src2q+2*wq] + packsswb m1, [srcq +2*wq+mmsize] + packsswb m2, [src2q+2*wq+mmsize] + paddb m1, m0 + paddb m2, m0 + mova [dstq +wq], m1 + mova [dst2q+wq], m2 + jg .loopx + + lea srcq, [srcq+src_strideq*4] + lea dstq, [dstq+dst_strideq*2] + sub hd, 2 + mov wd, wspill + jg .loopy + RET +%endm + +%macro ADD_RECT 1 +; void add_rect_clamped(uint8_t *dst, uint16_t *src, int stride, int16_t *idwt, int idwt_stride, int width, int height) +cglobal add_rect_clamped_%1, 7,9,3, dst, src, stride, idwt, idwt_stride, w, h + mova m0, [pw_32] + add wd, (mmsize-1) + and wd, ~(mmsize-1) + +%if ARCH_X86_64 + movsxd strideq, strided + movsxd idwt_strideq, idwt_strided + mov r8d, wd + %define wspill r8d +%else + mov r5m, wd + %define wspill r5m +%endif + +.loop: + sub wd, mmsize + movu m1, [srcq +2*wq] ; FIXME: ensure alignment + paddw m1, m0 + psraw m1, 6 + movu m2, [srcq +2*wq+mmsize] ; FIXME: ensure alignment + paddw m2, m0 + psraw m2, 6 + paddw m1, [idwtq+2*wq] + paddw m2, [idwtq+2*wq+mmsize] + packuswb m1, m2 + mova [dstq +wq], m1 + jg .loop + + lea srcq, [srcq + 2*strideq] + add dstq, strideq + lea idwtq, [idwtq+ 2*idwt_strideq] + sub hd, 1 + mov wd, wspill + jg .loop + RET +%endm + +%macro ADD_OBMC 2 +; void add_obmc(uint16_t *dst, uint8_t *src, int stride, uint8_t *obmc_weight, int yblen) +cglobal add_dirac_obmc%1_%2, 6,6,5, dst, src, stride, obmc, yblen + pxor m4, m4 +.loop: +%assign i 0 +%rep %1 / mmsize + mova m0, [srcq+i] + mova m1, m0 + punpcklbw m0, m4 + punpckhbw m1, m4 + mova m2, [obmcq+i] + mova m3, m2 + punpcklbw m2, m4 + punpckhbw m3, m4 + pmullw m0, m2 + pmullw m1, m3 + movu m2, [dstq+2*i] + movu m3, [dstq+2*i+mmsize] + paddw m0, m2 + paddw m1, m3 + movu [dstq+2*i], m0 + movu [dstq+2*i+mmsize], m1 +%assign i i+mmsize +%endrep + lea srcq, [srcq+strideq] + lea dstq, [dstq+2*strideq] + add obmcq, 32 + sub yblend, 1 + jg .loop + RET +%endm + +INIT_MMX +%if ARCH_X86_64 == 0 +PUT_RECT mmx +ADD_RECT mmx + +HPEL_FILTER mmx +ADD_OBMC 32, mmx +ADD_OBMC 16, mmx +%endif +ADD_OBMC 8, mmx + +INIT_XMM +PUT_RECT sse2 +ADD_RECT sse2 + +HPEL_FILTER sse2 +ADD_OBMC 32, sse2 +ADD_OBMC 16, sse2 diff --git a/ffmpeg/libavcodec/x86/dnxhdenc.c b/ffmpeg/libavcodec/x86/dnxhdenc.c new file mode 100644 index 0000000..349fbb0 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dnxhdenc.c @@ -0,0 +1,66 @@ +/* + * VC3/DNxHD SIMD functions + * Copyright (c) 2007 Baptiste Coudurier + * + * VC-3 encoder funded by the British Broadcasting Corporation + * + * 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 "libavutil/attributes.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/dnxhdenc.h" + +#if HAVE_SSE2_INLINE + +static void get_pixels_8x4_sym_sse2(int16_t *block, const uint8_t *pixels, int line_size) +{ + __asm__ volatile( + "pxor %%xmm5, %%xmm5 \n\t" + "movq (%0), %%xmm0 \n\t" + "add %2, %0 \n\t" + "movq (%0), %%xmm1 \n\t" + "movq (%0, %2), %%xmm2 \n\t" + "movq (%0, %2,2), %%xmm3 \n\t" + "punpcklbw %%xmm5, %%xmm0 \n\t" + "punpcklbw %%xmm5, %%xmm1 \n\t" + "punpcklbw %%xmm5, %%xmm2 \n\t" + "punpcklbw %%xmm5, %%xmm3 \n\t" + "movdqa %%xmm0, (%1) \n\t" + "movdqa %%xmm1, 16(%1) \n\t" + "movdqa %%xmm2, 32(%1) \n\t" + "movdqa %%xmm3, 48(%1) \n\t" + "movdqa %%xmm3 , 64(%1) \n\t" + "movdqa %%xmm2 , 80(%1) \n\t" + "movdqa %%xmm1 , 96(%1) \n\t" + "movdqa %%xmm0, 112(%1) \n\t" + : "+r" (pixels) + : "r" (block), "r" ((x86_reg)line_size) + ); +} + +#endif /* HAVE_SSE2_INLINE */ + +av_cold void ff_dnxhdenc_init_x86(DNXHDEncContext *ctx) +{ +#if HAVE_SSE2_INLINE + if (av_get_cpu_flags() & AV_CPU_FLAG_SSE2) { + if (ctx->cid_table->bit_depth == 8) + ctx->get_pixels_8x4_sym = get_pixels_8x4_sym_sse2; + } +#endif /* HAVE_SSE2_INLINE */ +} diff --git a/ffmpeg/libavcodec/x86/dsputil.asm b/ffmpeg/libavcodec/x86/dsputil.asm new file mode 100644 index 0000000..9970c02 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputil.asm @@ -0,0 +1,652 @@ +;****************************************************************************** +;* MMX optimized DSP utils +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2003-2013 Michael Niedermayer +;* Copyright (c) 2013 Daniel Kang +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA +pb_f: times 16 db 15 +pb_zzzzzzzz77777777: times 8 db -1 +pb_7: times 8 db 7 +pb_zzzz3333zzzzbbbb: db -1,-1,-1,-1,3,3,3,3,-1,-1,-1,-1,11,11,11,11 +pb_zz11zz55zz99zzdd: db -1,-1,1,1,-1,-1,5,5,-1,-1,9,9,-1,-1,13,13 +pb_revwords: SHUFFLE_MASK_W 7, 6, 5, 4, 3, 2, 1, 0 +pd_16384: times 4 dd 16384 +pb_bswap32: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 + +SECTION_TEXT + +%macro SCALARPRODUCT 0 +; int scalarproduct_int16(int16_t *v1, int16_t *v2, int order) +cglobal scalarproduct_int16, 3,3,3, v1, v2, order + shl orderq, 1 + add v1q, orderq + add v2q, orderq + neg orderq + pxor m2, m2 +.loop: + movu m0, [v1q + orderq] + movu m1, [v1q + orderq + mmsize] + pmaddwd m0, [v2q + orderq] + pmaddwd m1, [v2q + orderq + mmsize] + paddd m2, m0 + paddd m2, m1 + add orderq, mmsize*2 + jl .loop +%if mmsize == 16 + movhlps m0, m2 + paddd m2, m0 + pshuflw m0, m2, 0x4e +%else + pshufw m0, m2, 0x4e +%endif + paddd m2, m0 + movd eax, m2 + RET + +; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul) +cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul + shl orderq, 1 + movd m7, mulm +%if mmsize == 16 + pshuflw m7, m7, 0 + punpcklqdq m7, m7 +%else + pshufw m7, m7, 0 +%endif + pxor m6, m6 + add v1q, orderq + add v2q, orderq + add v3q, orderq + neg orderq +.loop: + movu m0, [v2q + orderq] + movu m1, [v2q + orderq + mmsize] + mova m4, [v1q + orderq] + mova m5, [v1q + orderq + mmsize] + movu m2, [v3q + orderq] + movu m3, [v3q + orderq + mmsize] + pmaddwd m0, m4 + pmaddwd m1, m5 + pmullw m2, m7 + pmullw m3, m7 + paddd m6, m0 + paddd m6, m1 + paddw m2, m4 + paddw m3, m5 + mova [v1q + orderq], m2 + mova [v1q + orderq + mmsize], m3 + add orderq, mmsize*2 + jl .loop +%if mmsize == 16 + movhlps m0, m6 + paddd m6, m0 + pshuflw m0, m6, 0x4e +%else + pshufw m0, m6, 0x4e +%endif + paddd m6, m0 + movd eax, m6 + RET +%endmacro + +INIT_MMX mmxext +SCALARPRODUCT +INIT_XMM sse2 +SCALARPRODUCT + +%macro SCALARPRODUCT_LOOP 1 +align 16 +.loop%1: + sub orderq, mmsize*2 +%if %1 + mova m1, m4 + mova m4, [v2q + orderq] + mova m0, [v2q + orderq + mmsize] + palignr m1, m0, %1 + palignr m0, m4, %1 + mova m3, m5 + mova m5, [v3q + orderq] + mova m2, [v3q + orderq + mmsize] + palignr m3, m2, %1 + palignr m2, m5, %1 +%else + mova m0, [v2q + orderq] + mova m1, [v2q + orderq + mmsize] + mova m2, [v3q + orderq] + mova m3, [v3q + orderq + mmsize] +%endif + %define t0 [v1q + orderq] + %define t1 [v1q + orderq + mmsize] +%if ARCH_X86_64 + mova m8, t0 + mova m9, t1 + %define t0 m8 + %define t1 m9 +%endif + pmaddwd m0, t0 + pmaddwd m1, t1 + pmullw m2, m7 + pmullw m3, m7 + paddw m2, t0 + paddw m3, t1 + paddd m6, m0 + paddd m6, m1 + mova [v1q + orderq], m2 + mova [v1q + orderq + mmsize], m3 + jg .loop%1 +%if %1 + jmp .end +%endif +%endmacro + +; int scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, int order, int mul) +INIT_XMM ssse3 +cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul + shl orderq, 1 + movd m7, mulm + pshuflw m7, m7, 0 + punpcklqdq m7, m7 + pxor m6, m6 + mov r4d, v2d + and r4d, 15 + and v2q, ~15 + and v3q, ~15 + mova m4, [v2q + orderq] + mova m5, [v3q + orderq] + ; linear is faster than branch tree or jump table, because the branches taken are cyclic (i.e. predictable) + cmp r4d, 0 + je .loop0 + cmp r4d, 2 + je .loop2 + cmp r4d, 4 + je .loop4 + cmp r4d, 6 + je .loop6 + cmp r4d, 8 + je .loop8 + cmp r4d, 10 + je .loop10 + cmp r4d, 12 + je .loop12 +SCALARPRODUCT_LOOP 14 +SCALARPRODUCT_LOOP 12 +SCALARPRODUCT_LOOP 10 +SCALARPRODUCT_LOOP 8 +SCALARPRODUCT_LOOP 6 +SCALARPRODUCT_LOOP 4 +SCALARPRODUCT_LOOP 2 +SCALARPRODUCT_LOOP 0 +.end: + movhlps m0, m6 + paddd m6, m0 + pshuflw m0, m6, 0x4e + paddd m6, m0 + movd eax, m6 + RET + + +;----------------------------------------------------------------------------- +; void ff_apply_window_int16(int16_t *output, const int16_t *input, +; const int16_t *window, unsigned int len) +;----------------------------------------------------------------------------- + +%macro REVERSE_WORDS 1-2 +%if cpuflag(ssse3) && notcpuflag(atom) + pshufb %1, %2 +%elif cpuflag(sse2) + pshuflw %1, %1, 0x1B + pshufhw %1, %1, 0x1B + pshufd %1, %1, 0x4E +%elif cpuflag(mmxext) + pshufw %1, %1, 0x1B +%endif +%endmacro + +%macro MUL16FIXED 3 +%if cpuflag(ssse3) ; dst, src, unused +; dst = ((dst * src) + (1<<14)) >> 15 + pmulhrsw %1, %2 +%elif cpuflag(mmxext) ; dst, src, temp +; dst = (dst * src) >> 15 +; pmulhw cuts off the bottom bit, so we have to lshift by 1 and add it back +; in from the pmullw result. + mova %3, %1 + pmulhw %1, %2 + pmullw %3, %2 + psrlw %3, 15 + psllw %1, 1 + por %1, %3 +%endif +%endmacro + +%macro APPLY_WINDOW_INT16 1 ; %1 bitexact version +%if %1 +cglobal apply_window_int16, 4,5,6, output, input, window, offset, offset2 +%else +cglobal apply_window_int16_round, 4,5,6, output, input, window, offset, offset2 +%endif + lea offset2q, [offsetq-mmsize] +%if cpuflag(ssse3) && notcpuflag(atom) + mova m5, [pb_revwords] + ALIGN 16 +%elif %1 + mova m5, [pd_16384] +%endif +.loop: +%if cpuflag(ssse3) + ; This version does the 16x16->16 multiplication in-place without expanding + ; to 32-bit. The ssse3 version is bit-identical. + mova m0, [windowq+offset2q] + mova m1, [ inputq+offset2q] + pmulhrsw m1, m0 + REVERSE_WORDS m0, m5 + pmulhrsw m0, [ inputq+offsetq ] + mova [outputq+offset2q], m1 + mova [outputq+offsetq ], m0 +%elif %1 + ; This version expands 16-bit to 32-bit, multiplies by the window, + ; adds 16384 for rounding, right shifts 15, then repacks back to words to + ; save to the output. The window is reversed for the second half. + mova m3, [windowq+offset2q] + mova m4, [ inputq+offset2q] + pxor m0, m0 + punpcklwd m0, m3 + punpcklwd m1, m4 + pmaddwd m0, m1 + paddd m0, m5 + psrad m0, 15 + pxor m2, m2 + punpckhwd m2, m3 + punpckhwd m1, m4 + pmaddwd m2, m1 + paddd m2, m5 + psrad m2, 15 + packssdw m0, m2 + mova [outputq+offset2q], m0 + REVERSE_WORDS m3 + mova m4, [ inputq+offsetq] + pxor m0, m0 + punpcklwd m0, m3 + punpcklwd m1, m4 + pmaddwd m0, m1 + paddd m0, m5 + psrad m0, 15 + pxor m2, m2 + punpckhwd m2, m3 + punpckhwd m1, m4 + pmaddwd m2, m1 + paddd m2, m5 + psrad m2, 15 + packssdw m0, m2 + mova [outputq+offsetq], m0 +%else + ; This version does the 16x16->16 multiplication in-place without expanding + ; to 32-bit. The mmxext and sse2 versions do not use rounding, and + ; therefore are not bit-identical to the C version. + mova m0, [windowq+offset2q] + mova m1, [ inputq+offset2q] + mova m2, [ inputq+offsetq ] + MUL16FIXED m1, m0, m3 + REVERSE_WORDS m0 + MUL16FIXED m2, m0, m3 + mova [outputq+offset2q], m1 + mova [outputq+offsetq ], m2 +%endif + add offsetd, mmsize + sub offset2d, mmsize + jae .loop + REP_RET +%endmacro + +INIT_MMX mmxext +APPLY_WINDOW_INT16 0 +INIT_XMM sse2 +APPLY_WINDOW_INT16 0 + +INIT_MMX mmxext +APPLY_WINDOW_INT16 1 +INIT_XMM sse2 +APPLY_WINDOW_INT16 1 +INIT_XMM ssse3 +APPLY_WINDOW_INT16 1 +INIT_XMM ssse3, atom +APPLY_WINDOW_INT16 1 + + +; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int w, int *left, int *left_top) +INIT_MMX mmxext +cglobal add_hfyu_median_prediction, 6,6,0, dst, top, diff, w, left, left_top + movq mm0, [topq] + movq mm2, mm0 + movd mm4, [left_topq] + psllq mm2, 8 + movq mm1, mm0 + por mm4, mm2 + movd mm3, [leftq] + psubb mm0, mm4 ; t-tl + add dstq, wq + add topq, wq + add diffq, wq + neg wq + jmp .skip +.loop: + movq mm4, [topq+wq] + movq mm0, mm4 + psllq mm4, 8 + por mm4, mm1 + movq mm1, mm0 ; t + psubb mm0, mm4 ; t-tl +.skip: + movq mm2, [diffq+wq] +%assign i 0 +%rep 8 + movq mm4, mm0 + paddb mm4, mm3 ; t-tl+l + movq mm5, mm3 + pmaxub mm3, mm1 + pminub mm5, mm1 + pminub mm3, mm4 + pmaxub mm3, mm5 ; median + paddb mm3, mm2 ; +residual +%if i==0 + movq mm7, mm3 + psllq mm7, 56 +%else + movq mm6, mm3 + psrlq mm7, 8 + psllq mm6, 56 + por mm7, mm6 +%endif +%if i<7 + psrlq mm0, 8 + psrlq mm1, 8 + psrlq mm2, 8 +%endif +%assign i i+1 +%endrep + movq [dstq+wq], mm7 + add wq, 8 + jl .loop + movzx r2d, byte [dstq-1] + mov [leftq], r2d + movzx r2d, byte [topq-1] + mov [left_topq], r2d + RET + + +%macro ADD_HFYU_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned + add srcq, wq + add dstq, wq + neg wq +%%.loop: +%if %2 + mova m1, [srcq+wq] +%else + movu m1, [srcq+wq] +%endif + mova m2, m1 + psllw m1, 8 + paddb m1, m2 + mova m2, m1 + pshufb m1, m3 + paddb m1, m2 + pshufb m0, m5 + mova m2, m1 + pshufb m1, m4 + paddb m1, m2 +%if mmsize == 16 + mova m2, m1 + pshufb m1, m6 + paddb m1, m2 +%endif + paddb m0, m1 +%if %1 + mova [dstq+wq], m0 +%else + movq [dstq+wq], m0 + movhps [dstq+wq+8], m0 +%endif + add wq, mmsize + jl %%.loop + mov eax, mmsize-1 + sub eax, wd + movd m1, eax + pshufb m0, m1 + movd eax, m0 + RET +%endmacro + +; int add_hfyu_left_prediction(uint8_t *dst, const uint8_t *src, int w, int left) +INIT_MMX ssse3 +cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left +.skip_prologue: + mova m5, [pb_7] + mova m4, [pb_zzzz3333zzzzbbbb] + mova m3, [pb_zz11zz55zz99zzdd] + movd m0, leftm + psllq m0, 56 + ADD_HFYU_LEFT_LOOP 1, 1 + +INIT_XMM sse4 +cglobal add_hfyu_left_prediction, 3,3,7, dst, src, w, left + mova m5, [pb_f] + mova m6, [pb_zzzzzzzz77777777] + mova m4, [pb_zzzz3333zzzzbbbb] + mova m3, [pb_zz11zz55zz99zzdd] + movd m0, leftm + pslldq m0, 15 + test srcq, 15 + jnz .src_unaligned + test dstq, 15 + jnz .dst_unaligned + ADD_HFYU_LEFT_LOOP 1, 1 +.dst_unaligned: + ADD_HFYU_LEFT_LOOP 0, 1 +.src_unaligned: + ADD_HFYU_LEFT_LOOP 0, 0 + +;----------------------------------------------------------------------------- +; void ff_vector_clip_int32(int32_t *dst, const int32_t *src, int32_t min, +; int32_t max, unsigned int len) +;----------------------------------------------------------------------------- + +; %1 = number of xmm registers used +; %2 = number of inline load/process/store loops per asm loop +; %3 = process 4*mmsize (%3=0) or 8*mmsize (%3=1) bytes per loop +; %4 = CLIPD function takes min/max as float instead of int (CLIPD_SSE2) +; %5 = suffix +%macro VECTOR_CLIP_INT32 4-5 +cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len +%if %4 + cvtsi2ss m4, minm + cvtsi2ss m5, maxm +%else + movd m4, minm + movd m5, maxm +%endif + SPLATD m4 + SPLATD m5 +.loop: +%assign %%i 1 +%rep %2 + mova m0, [srcq+mmsize*0*%%i] + mova m1, [srcq+mmsize*1*%%i] + mova m2, [srcq+mmsize*2*%%i] + mova m3, [srcq+mmsize*3*%%i] +%if %3 + mova m7, [srcq+mmsize*4*%%i] + mova m8, [srcq+mmsize*5*%%i] + mova m9, [srcq+mmsize*6*%%i] + mova m10, [srcq+mmsize*7*%%i] +%endif + CLIPD m0, m4, m5, m6 + CLIPD m1, m4, m5, m6 + CLIPD m2, m4, m5, m6 + CLIPD m3, m4, m5, m6 +%if %3 + CLIPD m7, m4, m5, m6 + CLIPD m8, m4, m5, m6 + CLIPD m9, m4, m5, m6 + CLIPD m10, m4, m5, m6 +%endif + mova [dstq+mmsize*0*%%i], m0 + mova [dstq+mmsize*1*%%i], m1 + mova [dstq+mmsize*2*%%i], m2 + mova [dstq+mmsize*3*%%i], m3 +%if %3 + mova [dstq+mmsize*4*%%i], m7 + mova [dstq+mmsize*5*%%i], m8 + mova [dstq+mmsize*6*%%i], m9 + mova [dstq+mmsize*7*%%i], m10 +%endif +%assign %%i %%i+1 +%endrep + add srcq, mmsize*4*(%2+%3) + add dstq, mmsize*4*(%2+%3) + sub lend, mmsize*(%2+%3) + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +%define CLIPD CLIPD_MMX +VECTOR_CLIP_INT32 0, 1, 0, 0 +INIT_XMM sse2 +VECTOR_CLIP_INT32 6, 1, 0, 0, _int +%define CLIPD CLIPD_SSE2 +VECTOR_CLIP_INT32 6, 2, 0, 1 +INIT_XMM sse4 +%define CLIPD CLIPD_SSE41 +%ifdef m8 +VECTOR_CLIP_INT32 11, 1, 1, 0 +%else +VECTOR_CLIP_INT32 6, 1, 0, 0 +%endif + +; %1 = aligned/unaligned +%macro BSWAP_LOOPS 1 + mov r3, r2 + sar r2, 3 + jz .left4_%1 +.loop8_%1: + mov%1 m0, [r1 + 0] + mov%1 m1, [r1 + 16] +%if cpuflag(ssse3) + pshufb m0, m2 + pshufb m1, m2 + mova [r0 + 0], m0 + mova [r0 + 16], m1 +%else + pshuflw m0, m0, 10110001b + pshuflw m1, m1, 10110001b + pshufhw m0, m0, 10110001b + pshufhw m1, m1, 10110001b + mova m2, m0 + mova m3, m1 + psllw m0, 8 + psllw m1, 8 + psrlw m2, 8 + psrlw m3, 8 + por m2, m0 + por m3, m1 + mova [r0 + 0], m2 + mova [r0 + 16], m3 +%endif + add r0, 32 + add r1, 32 + dec r2 + jnz .loop8_%1 +.left4_%1: + mov r2, r3 + and r3, 4 + jz .left + mov%1 m0, [r1] +%if cpuflag(ssse3) + pshufb m0, m2 + mova [r0], m0 +%else + pshuflw m0, m0, 10110001b + pshufhw m0, m0, 10110001b + mova m2, m0 + psllw m0, 8 + psrlw m2, 8 + por m2, m0 + mova [r0], m2 +%endif + add r1, 16 + add r0, 16 +%endmacro + +; void bswap_buf(uint32_t *dst, const uint32_t *src, int w); +%macro BSWAP32_BUF 0 +%if cpuflag(ssse3) +cglobal bswap32_buf, 3,4,3 + mov r3, r1 + mova m2, [pb_bswap32] +%else +cglobal bswap32_buf, 3,4,5 + mov r3, r1 +%endif + and r3, 15 + jz .start_align + BSWAP_LOOPS u + jmp .left +.start_align: + BSWAP_LOOPS a +.left: +%if cpuflag(ssse3) + mov r3, r2 + and r2, 2 + jz .left1 + movq m0, [r1] + pshufb m0, m2 + movq [r0], m0 + add r1, 8 + add r0, 8 +.left1: + and r3, 1 + jz .end + mov r2d, [r1] + bswap r2d + mov [r0], r2d +%else + and r2, 3 + jz .end +.loop2: + mov r3d, [r1] + bswap r3d + mov [r0], r3d + add r1, 4 + add r0, 4 + dec r2 + jnz .loop2 +%endif +.end: + RET +%endmacro + +INIT_XMM sse2 +BSWAP32_BUF + +INIT_XMM ssse3 +BSWAP32_BUF diff --git a/ffmpeg/libavcodec/x86/dsputil_mmx.c b/ffmpeg/libavcodec/x86/dsputil_mmx.c new file mode 100644 index 0000000..fe59d22 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputil_mmx.c @@ -0,0 +1,1636 @@ +/* + * MMX optimized DSP utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + * + * MMX optimization by Nick Kurshev + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/h264dsp.h" +#include "libavcodec/mpegvideo.h" +#include "libavcodec/simple_idct.h" +#include "libavcodec/videodsp.h" +#include "dsputil_mmx.h" +#include "idct_xvid.h" +#include "diracdsp_mmx.h" + +//#undef NDEBUG +//#include + +/* pixel operations */ +DECLARE_ALIGNED(8, const uint64_t, ff_bone) = 0x0101010101010101ULL; +DECLARE_ALIGNED(8, const uint64_t, ff_wtwo) = 0x0002000200020002ULL; + +DECLARE_ALIGNED(8, const uint64_t, ff_pw_15) = 0x000F000F000F000FULL; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_17) = { 0x0011001100110011ULL, 0x0011001100110011ULL }; +DECLARE_ALIGNED(8, const uint64_t, ff_pw_20) = 0x0014001400140014ULL; +DECLARE_ALIGNED(8, const uint64_t, ff_pw_42) = 0x002A002A002A002AULL; +DECLARE_ALIGNED(8, const uint64_t, ff_pw_53) = 0x0035003500350035ULL; +DECLARE_ALIGNED(8, const uint64_t, ff_pw_96) = 0x0060006000600060ULL; +DECLARE_ALIGNED(8, const uint64_t, ff_pw_128) = 0x0080008000800080ULL; +DECLARE_ALIGNED(8, const uint64_t, ff_pw_255) = 0x00ff00ff00ff00ffULL; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_512) = { 0x0200020002000200ULL, 0x0200020002000200ULL }; +DECLARE_ALIGNED(16, const xmm_reg, ff_pw_1019) = { 0x03FB03FB03FB03FBULL, 0x03FB03FB03FB03FBULL }; + +DECLARE_ALIGNED(8, const uint64_t, ff_pb_3F) = 0x3F3F3F3F3F3F3F3FULL; +DECLARE_ALIGNED(8, const uint64_t, ff_pb_FC) = 0xFCFCFCFCFCFCFCFCULL; + +DECLARE_ALIGNED(16, const double, ff_pd_1)[2] = { 1.0, 1.0 }; +DECLARE_ALIGNED(16, const double, ff_pd_2)[2] = { 2.0, 2.0 }; + + +#if HAVE_YASM +void ff_put_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_no_rnd_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, + uint8_t *src2, int dstStride, + int src1Stride, int h); +void ff_avg_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_avg_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_no_rnd_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_avg_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +void ff_put_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); +static void ff_put_pixels16_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + ff_put_pixels8_mmxext(block, pixels, line_size, h); + ff_put_pixels8_mmxext(block + 8, pixels + 8, line_size, h); +} + +void ff_put_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_avg_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_put_no_rnd_mpeg4_qpel16_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, + int h); +void ff_put_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_avg_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, int h); +void ff_put_no_rnd_mpeg4_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride, + int h); +void ff_put_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_avg_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_put_no_rnd_mpeg4_qpel16_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_put_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_avg_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +void ff_put_no_rnd_mpeg4_qpel8_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, + int dstStride, int srcStride); +#define ff_put_no_rnd_pixels16_mmxext ff_put_pixels16_mmxext +#define ff_put_no_rnd_pixels8_mmxext ff_put_pixels8_mmxext +#endif /* HAVE_YASM */ + + +#if HAVE_INLINE_ASM + +#define JUMPALIGN() __asm__ volatile (".p2align 3"::) +#define MOVQ_ZERO(regd) __asm__ volatile ("pxor %%"#regd", %%"#regd ::) + +#define MOVQ_BFE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "paddb %%"#regd", %%"#regd" \n\t" ::) + +#ifndef PIC +#define MOVQ_BONE(regd) __asm__ volatile ("movq %0, %%"#regd" \n\t" :: "m"(ff_bone)) +#define MOVQ_WTWO(regd) __asm__ volatile ("movq %0, %%"#regd" \n\t" :: "m"(ff_wtwo)) +#else +// for shared library it's better to use this way for accessing constants +// pcmpeqd -> -1 +#define MOVQ_BONE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "psrlw $15, %%"#regd" \n\t" \ + "packuswb %%"#regd", %%"#regd" \n\t" ::) + +#define MOVQ_WTWO(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "psrlw $15, %%"#regd" \n\t" \ + "psllw $1, %%"#regd" \n\t"::) + +#endif + +// using regr as temporary and for the output result +// first argument is unmodifed and second is trashed +// regfe is supposed to contain 0xfefefefefefefefe +#define PAVGB_MMX(rega, regb, regr, regfe) \ + "movq "#rega", "#regr" \n\t" \ + "por "#regb", "#regr" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pand "#regfe", "#regb" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psubb "#regb", "#regr" \n\t" + +// mm6 is supposed to contain 0xfefefefefefefefe +#define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \ + "movq "#rega", "#regr" \n\t" \ + "movq "#regc", "#regp" \n\t" \ + "por "#regb", "#regr" \n\t" \ + "por "#regd", "#regp" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pxor "#regc", "#regd" \n\t" \ + "pand %%mm6, "#regb" \n\t" \ + "pand %%mm6, "#regd" \n\t" \ + "psrlq $1, "#regd" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psubb "#regb", "#regr" \n\t" \ + "psubb "#regd", "#regp" \n\t" + +/***********************************/ +/* MMX rounding */ + +#define DEF(x, y) x ## _ ## y ## _mmx +#define SET_RND MOVQ_WTWO +#define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX(a, b, c, d, e, f) +#define PAVGB(a, b, c, e) PAVGB_MMX(a, b, c, e) +#define OP_AVG(a, b, c, e) PAVGB_MMX(a, b, c, e) + +#include "dsputil_rnd_template.c" + +#undef DEF +#undef SET_RND +#undef PAVGBP +#undef PAVGB +#undef OP_AVG + +#endif /* HAVE_INLINE_ASM */ + + +#if HAVE_YASM + +/***********************************/ +/* MMXEXT specific */ + +//FIXME the following could be optimized too ... +static void ff_avg_pixels16_mmxext(uint8_t *block, const uint8_t *pixels, + int line_size, int h) +{ + ff_avg_pixels8_mmxext(block, pixels, line_size, h); + ff_avg_pixels8_mmxext(block + 8, pixels + 8, line_size, h); +} + +#endif /* HAVE_YASM */ + + +#if HAVE_INLINE_ASM +/***********************************/ +/* standard MMX */ + +void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size) +{ + const int16_t *p; + uint8_t *pix; + + /* read the pixels */ + p = block; + pix = pixels; + /* unrolled loop */ + __asm__ volatile ( + "movq (%3), %%mm0 \n\t" + "movq 8(%3), %%mm1 \n\t" + "movq 16(%3), %%mm2 \n\t" + "movq 24(%3), %%mm3 \n\t" + "movq 32(%3), %%mm4 \n\t" + "movq 40(%3), %%mm5 \n\t" + "movq 48(%3), %%mm6 \n\t" + "movq 56(%3), %%mm7 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "packuswb %%mm7, %%mm6 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm2, (%0, %1) \n\t" + "movq %%mm4, (%0, %1, 2) \n\t" + "movq %%mm6, (%0, %2) \n\t" + :: "r"(pix), "r"((x86_reg)line_size), "r"((x86_reg)line_size * 3), + "r"(p) + : "memory"); + pix += line_size * 4; + p += 32; + + // if here would be an exact copy of the code above + // compiler would generate some very strange code + // thus using "r" + __asm__ volatile ( + "movq (%3), %%mm0 \n\t" + "movq 8(%3), %%mm1 \n\t" + "movq 16(%3), %%mm2 \n\t" + "movq 24(%3), %%mm3 \n\t" + "movq 32(%3), %%mm4 \n\t" + "movq 40(%3), %%mm5 \n\t" + "movq 48(%3), %%mm6 \n\t" + "movq 56(%3), %%mm7 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "packuswb %%mm7, %%mm6 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm2, (%0, %1) \n\t" + "movq %%mm4, (%0, %1, 2) \n\t" + "movq %%mm6, (%0, %2) \n\t" + :: "r"(pix), "r"((x86_reg)line_size), "r"((x86_reg)line_size * 3), "r"(p) + : "memory"); +} + +#define put_signed_pixels_clamped_mmx_half(off) \ + "movq "#off"(%2), %%mm1 \n\t" \ + "movq 16 + "#off"(%2), %%mm2 \n\t" \ + "movq 32 + "#off"(%2), %%mm3 \n\t" \ + "movq 48 + "#off"(%2), %%mm4 \n\t" \ + "packsswb 8 + "#off"(%2), %%mm1 \n\t" \ + "packsswb 24 + "#off"(%2), %%mm2 \n\t" \ + "packsswb 40 + "#off"(%2), %%mm3 \n\t" \ + "packsswb 56 + "#off"(%2), %%mm4 \n\t" \ + "paddb %%mm0, %%mm1 \n\t" \ + "paddb %%mm0, %%mm2 \n\t" \ + "paddb %%mm0, %%mm3 \n\t" \ + "paddb %%mm0, %%mm4 \n\t" \ + "movq %%mm1, (%0) \n\t" \ + "movq %%mm2, (%0, %3) \n\t" \ + "movq %%mm3, (%0, %3, 2) \n\t" \ + "movq %%mm4, (%0, %1) \n\t" + +void ff_put_signed_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size) +{ + x86_reg line_skip = line_size; + x86_reg line_skip3; + + __asm__ volatile ( + "movq "MANGLE(ff_pb_80)", %%mm0 \n\t" + "lea (%3, %3, 2), %1 \n\t" + put_signed_pixels_clamped_mmx_half(0) + "lea (%0, %3, 4), %0 \n\t" + put_signed_pixels_clamped_mmx_half(64) + : "+&r"(pixels), "=&r"(line_skip3) + : "r"(block), "r"(line_skip) + : "memory"); +} + +void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, + int line_size) +{ + const int16_t *p; + uint8_t *pix; + int i; + + /* read the pixels */ + p = block; + pix = pixels; + MOVQ_ZERO(mm7); + i = 4; + do { + __asm__ volatile ( + "movq (%2), %%mm0 \n\t" + "movq 8(%2), %%mm1 \n\t" + "movq 16(%2), %%mm2 \n\t" + "movq 24(%2), %%mm3 \n\t" + "movq %0, %%mm4 \n\t" + "movq %1, %%mm6 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddsw %%mm4, %%mm0 \n\t" + "paddsw %%mm5, %%mm1 \n\t" + "movq %%mm6, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm6 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddsw %%mm6, %%mm2 \n\t" + "paddsw %%mm5, %%mm3 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "packuswb %%mm3, %%mm2 \n\t" + "movq %%mm0, %0 \n\t" + "movq %%mm2, %1 \n\t" + : "+m"(*pix), "+m"(*(pix + line_size)) + : "r"(p) + : "memory"); + pix += line_size * 2; + p += 16; + } while (--i); +} + +static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + __asm__ volatile ( + "lea (%3, %3), %%"REG_a" \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + : "+g"(h), "+r"(pixels), "+r"(block) + : "r"((x86_reg)line_size) + : "%"REG_a, "memory" + ); +} + +static void put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + __asm__ volatile ( + "lea (%3, %3), %%"REG_a" \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq 8(%1 ), %%mm4 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq 8(%1, %3), %%mm5 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm4, 8(%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "movq %%mm5, 8(%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq 8(%1 ), %%mm4 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq 8(%1, %3), %%mm5 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm4, 8(%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "movq %%mm5, 8(%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + : "+g"(h), "+r"(pixels), "+r"(block) + : "r"((x86_reg)line_size) + : "%"REG_a, "memory" + ); +} + +#define CLEAR_BLOCKS(name, n) \ +static void name(int16_t *blocks) \ +{ \ + __asm__ volatile ( \ + "pxor %%mm7, %%mm7 \n\t" \ + "mov %1, %%"REG_a" \n\t" \ + "1: \n\t" \ + "movq %%mm7, (%0, %%"REG_a") \n\t" \ + "movq %%mm7, 8(%0, %%"REG_a") \n\t" \ + "movq %%mm7, 16(%0, %%"REG_a") \n\t" \ + "movq %%mm7, 24(%0, %%"REG_a") \n\t" \ + "add $32, %%"REG_a" \n\t" \ + "js 1b \n\t" \ + :: "r"(((uint8_t *)blocks) + 128 * n), \ + "i"(-128 * n) \ + : "%"REG_a \ + ); \ +} +CLEAR_BLOCKS(clear_blocks_mmx, 6) +CLEAR_BLOCKS(clear_block_mmx, 1) + +static void clear_block_sse(int16_t *block) +{ + __asm__ volatile ( + "xorps %%xmm0, %%xmm0 \n" + "movaps %%xmm0, (%0) \n" + "movaps %%xmm0, 16(%0) \n" + "movaps %%xmm0, 32(%0) \n" + "movaps %%xmm0, 48(%0) \n" + "movaps %%xmm0, 64(%0) \n" + "movaps %%xmm0, 80(%0) \n" + "movaps %%xmm0, 96(%0) \n" + "movaps %%xmm0, 112(%0) \n" + :: "r"(block) + : "memory" + ); +} + +static void clear_blocks_sse(int16_t *blocks) +{ + __asm__ volatile ( + "xorps %%xmm0, %%xmm0 \n" + "mov %1, %%"REG_a" \n" + "1: \n" + "movaps %%xmm0, (%0, %%"REG_a") \n" + "movaps %%xmm0, 16(%0, %%"REG_a") \n" + "movaps %%xmm0, 32(%0, %%"REG_a") \n" + "movaps %%xmm0, 48(%0, %%"REG_a") \n" + "movaps %%xmm0, 64(%0, %%"REG_a") \n" + "movaps %%xmm0, 80(%0, %%"REG_a") \n" + "movaps %%xmm0, 96(%0, %%"REG_a") \n" + "movaps %%xmm0, 112(%0, %%"REG_a") \n" + "add $128, %%"REG_a" \n" + "js 1b \n" + :: "r"(((uint8_t *)blocks) + 128 * 6), + "i"(-128 * 6) + : "%"REG_a + ); +} + +static void add_bytes_mmx(uint8_t *dst, uint8_t *src, int w) +{ + x86_reg i = 0; + __asm__ volatile ( + "jmp 2f \n\t" + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq (%2, %0), %%mm1 \n\t" + "paddb %%mm0, %%mm1 \n\t" + "movq %%mm1, (%2, %0) \n\t" + "movq 8(%1, %0), %%mm0 \n\t" + "movq 8(%2, %0), %%mm1 \n\t" + "paddb %%mm0, %%mm1 \n\t" + "movq %%mm1, 8(%2, %0) \n\t" + "add $16, %0 \n\t" + "2: \n\t" + "cmp %3, %0 \n\t" + "js 1b \n\t" + : "+r"(i) + : "r"(src), "r"(dst), "r"((x86_reg)w - 15) + ); + for ( ; i < w; i++) + dst[i + 0] += src[i + 0]; +} + +#if HAVE_7REGS +static void add_hfyu_median_prediction_cmov(uint8_t *dst, const uint8_t *top, + const uint8_t *diff, int w, + int *left, int *left_top) +{ + x86_reg w2 = -w; + x86_reg x; + int l = *left & 0xff; + int tl = *left_top & 0xff; + int t; + __asm__ volatile ( + "mov %7, %3 \n" + "1: \n" + "movzbl (%3, %4), %2 \n" + "mov %2, %k3 \n" + "sub %b1, %b3 \n" + "add %b0, %b3 \n" + "mov %2, %1 \n" + "cmp %0, %2 \n" + "cmovg %0, %2 \n" + "cmovg %1, %0 \n" + "cmp %k3, %0 \n" + "cmovg %k3, %0 \n" + "mov %7, %3 \n" + "cmp %2, %0 \n" + "cmovl %2, %0 \n" + "add (%6, %4), %b0 \n" + "mov %b0, (%5, %4) \n" + "inc %4 \n" + "jl 1b \n" + : "+&q"(l), "+&q"(tl), "=&r"(t), "=&q"(x), "+&r"(w2) + : "r"(dst + w), "r"(diff + w), "rm"(top + w) + ); + *left = l; + *left_top = tl; +} +#endif +#endif /* HAVE_INLINE_ASM */ + +void ff_h263_v_loop_filter_mmx(uint8_t *src, int stride, int qscale); +void ff_h263_h_loop_filter_mmx(uint8_t *src, int stride, int qscale); + +#if HAVE_INLINE_ASM +/* Draw the edges of width 'w' of an image of size width, height + * this MMX version can only handle w == 8 || w == 16. */ +static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, + int w, int h, int sides) +{ + uint8_t *ptr, *last_line; + int i; + + last_line = buf + (height - 1) * wrap; + /* left and right */ + ptr = buf; + if (w == 8) { + __asm__ volatile ( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "punpckldq %%mm0, %%mm0 \n\t" + "movq %%mm0, -8(%0) \n\t" + "movq -8(%0, %2), %%mm1 \n\t" + "punpckhbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movq %%mm1, (%0, %2) \n\t" + "add %1, %0 \n\t" + "cmp %3, %0 \n\t" + "jb 1b \n\t" + : "+r"(ptr) + : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) + ); + } else if(w==16){ + __asm__ volatile ( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "punpckldq %%mm0, %%mm0 \n\t" + "movq %%mm0, -8(%0) \n\t" + "movq %%mm0, -16(%0) \n\t" + "movq -8(%0, %2), %%mm1 \n\t" + "punpckhbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movq %%mm1, (%0, %2) \n\t" + "movq %%mm1, 8(%0, %2) \n\t" + "add %1, %0 \n\t" + "cmp %3, %0 \n\t" + "jb 1b \n\t" + : "+r"(ptr) + : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) + ); + } else { + av_assert1(w == 4); + __asm__ volatile ( + "1: \n\t" + "movd (%0), %%mm0 \n\t" + "punpcklbw %%mm0, %%mm0 \n\t" + "punpcklwd %%mm0, %%mm0 \n\t" + "movd %%mm0, -4(%0) \n\t" + "movd -4(%0, %2), %%mm1 \n\t" + "punpcklbw %%mm1, %%mm1 \n\t" + "punpckhwd %%mm1, %%mm1 \n\t" + "punpckhdq %%mm1, %%mm1 \n\t" + "movd %%mm1, (%0, %2) \n\t" + "add %1, %0 \n\t" + "cmp %3, %0 \n\t" + "jb 1b \n\t" + : "+r"(ptr) + : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height) + ); + } + + /* top and bottom (and hopefully also the corners) */ + if (sides & EDGE_TOP) { + for (i = 0; i < h; i += 4) { + ptr = buf - (i + 1) * wrap - w; + __asm__ volatile ( + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm0, (%0, %2) \n\t" + "movq %%mm0, (%0, %2, 2) \n\t" + "movq %%mm0, (%0, %3) \n\t" + "add $8, %0 \n\t" + "cmp %4, %0 \n\t" + "jb 1b \n\t" + : "+r"(ptr) + : "r"((x86_reg)buf - (x86_reg)ptr - w), "r"((x86_reg) -wrap), + "r"((x86_reg) -wrap * 3), "r"(ptr + width + 2 * w) + ); + } + } + + if (sides & EDGE_BOTTOM) { + for (i = 0; i < h; i += 4) { + ptr = last_line + (i + 1) * wrap - w; + __asm__ volatile ( + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm0, (%0, %2) \n\t" + "movq %%mm0, (%0, %2, 2) \n\t" + "movq %%mm0, (%0, %3) \n\t" + "add $8, %0 \n\t" + "cmp %4, %0 \n\t" + "jb 1b \n\t" + : "+r"(ptr) + : "r"((x86_reg)last_line - (x86_reg)ptr - w), + "r"((x86_reg)wrap), "r"((x86_reg)wrap * 3), + "r"(ptr + width + 2 * w) + ); + } + } +} +#endif /* HAVE_INLINE_ASM */ + + +#if HAVE_YASM +#define QPEL_OP(OPNAME, ROUNDER, RND, MMX) \ +static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## pixels8_ ## MMX(dst, src, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, \ + stride, 8); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src, half, \ + stride, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, \ + stride, 8); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src + 1, half, stride, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, \ + 8, stride); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src, half, \ + stride, stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, \ + stride, stride); \ +} \ + \ +static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[8]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, \ + 8, stride); \ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, src + stride, half, stride,\ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half) + 64; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half) + 64; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half) + 64; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half) + 64; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half) + 64; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half) + 64; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\ + ff_ ## OPNAME ## pixels8_l2_ ## MMX(dst, halfH + 8, halfHV, \ + stride, 8, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, \ + 8, stride, 9); \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[8 + 9]; \ + uint8_t * const halfH = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_put ## RND ## pixels8_l2_ ## MMX(halfH, src + 1, halfH, 8, \ + stride, 9); \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[9]; \ + uint8_t * const halfH = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, \ + stride, 9); \ + ff_ ## OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, \ + stride, 8); \ +} \ + \ +static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## pixels16_ ## MMX(dst, src, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, \ + stride, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, \ + stride, stride, 16);\ +} \ + \ +static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, \ + stride, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src + 1, half, \ + stride, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, \ + stride); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, \ + stride, stride); \ +} \ + \ +static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t temp[32]; \ + uint8_t * const half = (uint8_t*)temp; \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, \ + stride); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, \ + stride, stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half) + 256; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half) + 256; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half) + 256; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half) + 256; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half) + 256; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[16 * 2 + 17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half) + 256; \ + uint8_t * const halfHV = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, \ + 16, 16); \ + ff_ ## OPNAME ## pixels16_l2_ ## MMX(dst, halfH + 16, halfHV, \ + stride, 16, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, \ + stride, 17); \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_put ## RND ## pixels16_l2_ ## MMX(halfH, src + 1, halfH, 16, \ + stride, 17); \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ + stride, 16); \ +} \ + \ +static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + uint64_t half[17 * 2]; \ + uint8_t * const halfH = ((uint8_t*)half); \ + ff_put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, \ + stride, 17); \ + ff_ ## OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, \ + stride, 16); \ +} + +QPEL_OP(put_, ff_pw_16, _, mmxext) +QPEL_OP(avg_, ff_pw_16, _, mmxext) +QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, mmxext) +#endif /* HAVE_YASM */ + + +#if HAVE_INLINE_ASM +void ff_put_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels8_xy2_mmx(dst, src, stride, 8); +} +void ff_put_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + put_pixels16_xy2_mmx(dst, src, stride, 16); +} +void ff_avg_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels8_xy2_mmx(dst, src, stride, 8); +} +void ff_avg_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride) +{ + avg_pixels16_xy2_mmx(dst, src, stride, 16); +} + +typedef void emulated_edge_mc_func(uint8_t *dst, const uint8_t *src, + ptrdiff_t linesize, int block_w, int block_h, + int src_x, int src_y, int w, int h); + +static av_always_inline void gmc(uint8_t *dst, uint8_t *src, + int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, + int shift, int r, int width, int height, + emulated_edge_mc_func *emu_edge_fn) +{ + const int w = 8; + const int ix = ox >> (16 + shift); + const int iy = oy >> (16 + shift); + const int oxs = ox >> 4; + const int oys = oy >> 4; + const int dxxs = dxx >> 4; + const int dxys = dxy >> 4; + const int dyxs = dyx >> 4; + const int dyys = dyy >> 4; + const uint16_t r4[4] = { r, r, r, r }; + const uint16_t dxy4[4] = { dxys, dxys, dxys, dxys }; + const uint16_t dyy4[4] = { dyys, dyys, dyys, dyys }; + const uint64_t shift2 = 2 * shift; +#define MAX_STRIDE 4096U +#define MAX_H 8U + uint8_t edge_buf[(MAX_H + 1) * MAX_STRIDE]; + int x, y; + + const int dxw = (dxx - (1 << (16 + shift))) * (w - 1); + const int dyh = (dyy - (1 << (16 + shift))) * (h - 1); + const int dxh = dxy * (h - 1); + const int dyw = dyx * (w - 1); + int need_emu = (unsigned)ix >= width - w || + (unsigned)iy >= height - h; + + if ( // non-constant fullpel offset (3% of blocks) + ((ox ^ (ox + dxw)) | (ox ^ (ox + dxh)) | (ox ^ (ox + dxw + dxh)) | + (oy ^ (oy + dyw)) | (oy ^ (oy + dyh)) | (oy ^ (oy + dyw + dyh))) >> (16 + shift) + // uses more than 16 bits of subpel mv (only at huge resolution) + || (dxx | dxy | dyx | dyy) & 15 + || (need_emu && (h > MAX_H || stride > MAX_STRIDE))) { + // FIXME could still use mmx for some of the rows + ff_gmc_c(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, + shift, r, width, height); + return; + } + + src += ix + iy * stride; + if (need_emu) { + emu_edge_fn(edge_buf, src, stride, w + 1, h + 1, ix, iy, width, height); + src = edge_buf; + } + + __asm__ volatile ( + "movd %0, %%mm6 \n\t" + "pxor %%mm7, %%mm7 \n\t" + "punpcklwd %%mm6, %%mm6 \n\t" + "punpcklwd %%mm6, %%mm6 \n\t" + :: "r"(1<PFX ## _pixels_tab[IDX][ 0] = PREFIX ## PFX ## SIZE ## _mc00_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 1] = PREFIX ## PFX ## SIZE ## _mc10_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 2] = PREFIX ## PFX ## SIZE ## _mc20_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 3] = PREFIX ## PFX ## SIZE ## _mc30_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 4] = PREFIX ## PFX ## SIZE ## _mc01_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 5] = PREFIX ## PFX ## SIZE ## _mc11_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 6] = PREFIX ## PFX ## SIZE ## _mc21_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 7] = PREFIX ## PFX ## SIZE ## _mc31_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 8] = PREFIX ## PFX ## SIZE ## _mc02_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 9] = PREFIX ## PFX ## SIZE ## _mc12_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][10] = PREFIX ## PFX ## SIZE ## _mc22_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][11] = PREFIX ## PFX ## SIZE ## _mc32_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][12] = PREFIX ## PFX ## SIZE ## _mc03_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][13] = PREFIX ## PFX ## SIZE ## _mc13_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][14] = PREFIX ## PFX ## SIZE ## _mc23_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][15] = PREFIX ## PFX ## SIZE ## _mc33_ ## CPU; \ + } while (0) + +static av_cold void dsputil_init_mmx(DSPContext *c, AVCodecContext *avctx, + int mm_flags) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + +#if HAVE_INLINE_ASM + c->put_pixels_clamped = ff_put_pixels_clamped_mmx; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx; + c->add_pixels_clamped = ff_add_pixels_clamped_mmx; + + if (!high_bit_depth) { + c->clear_block = clear_block_mmx; + c->clear_blocks = clear_blocks_mmx; + c->draw_edges = draw_edges_mmx; + } + +#if CONFIG_VIDEODSP && (ARCH_X86_32 || !HAVE_YASM) + c->gmc = gmc_mmx; +#endif + + c->add_bytes = add_bytes_mmx; +#endif /* HAVE_INLINE_ASM */ + +#if HAVE_YASM + if (CONFIG_H263_DECODER || CONFIG_H263_ENCODER) { + c->h263_v_loop_filter = ff_h263_v_loop_filter_mmx; + c->h263_h_loop_filter = ff_h263_h_loop_filter_mmx; + } + + c->vector_clip_int32 = ff_vector_clip_int32_mmx; +#endif + +} + +static av_cold void dsputil_init_mmxext(DSPContext *c, AVCodecContext *avctx, + int mm_flags) +{ + +#if HAVE_YASM + SET_QPEL_FUNCS(avg_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(avg_qpel, 1, 8, mmxext, ); + + SET_QPEL_FUNCS(put_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(put_qpel, 1, 8, mmxext, ); + SET_QPEL_FUNCS(put_no_rnd_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(put_no_rnd_qpel, 1, 8, mmxext, ); +#endif /* HAVE_YASM */ + +#if HAVE_MMXEXT_EXTERNAL + /* slower than cmov version on AMD */ + if (!(mm_flags & AV_CPU_FLAG_3DNOW)) + c->add_hfyu_median_prediction = ff_add_hfyu_median_prediction_mmxext; + + c->scalarproduct_int16 = ff_scalarproduct_int16_mmxext; + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_mmxext; + + if (avctx->flags & CODEC_FLAG_BITEXACT) { + c->apply_window_int16 = ff_apply_window_int16_mmxext; + } else { + c->apply_window_int16 = ff_apply_window_int16_round_mmxext; + } +#endif /* HAVE_MMXEXT_EXTERNAL */ +} + +static av_cold void dsputil_init_sse(DSPContext *c, AVCodecContext *avctx, + int mm_flags) +{ + const int high_bit_depth = avctx->bits_per_raw_sample > 8; + +#if HAVE_INLINE_ASM + if (!high_bit_depth) { + if (!(CONFIG_MPEG_XVMC_DECODER && avctx->xvmc_acceleration > 1)) { + /* XvMCCreateBlocks() may not allocate 16-byte aligned blocks */ + c->clear_block = clear_block_sse; + c->clear_blocks = clear_blocks_sse; + } + } + + c->vector_clipf = vector_clipf_sse; +#endif /* HAVE_INLINE_ASM */ + +#if HAVE_YASM +#if HAVE_INLINE_ASM && CONFIG_VIDEODSP + c->gmc = gmc_sse; +#endif +#endif /* HAVE_YASM */ +} + +static av_cold void dsputil_init_sse2(DSPContext *c, AVCodecContext *avctx, + int mm_flags) +{ + const int bit_depth = avctx->bits_per_raw_sample; + const int high_bit_depth = bit_depth > 8; + +#if HAVE_SSE2_INLINE + if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX) { + c->idct_put = ff_idct_xvid_sse2_put; + c->idct_add = ff_idct_xvid_sse2_add; + c->idct = ff_idct_xvid_sse2; + c->idct_permutation_type = FF_SSE2_IDCT_PERM; + } +#endif /* HAVE_SSE2_INLINE */ + +#if HAVE_SSE2_EXTERNAL + c->scalarproduct_int16 = ff_scalarproduct_int16_sse2; + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_sse2; + if (mm_flags & AV_CPU_FLAG_ATOM) { + c->vector_clip_int32 = ff_vector_clip_int32_int_sse2; + } else { + c->vector_clip_int32 = ff_vector_clip_int32_sse2; + } + if (avctx->flags & CODEC_FLAG_BITEXACT) { + c->apply_window_int16 = ff_apply_window_int16_sse2; + } else if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW)) { + c->apply_window_int16 = ff_apply_window_int16_round_sse2; + } + c->bswap_buf = ff_bswap32_buf_sse2; +#endif /* HAVE_SSE2_EXTERNAL */ +} + +static av_cold void dsputil_init_ssse3(DSPContext *c, AVCodecContext *avctx, + int mm_flags) +{ +#if HAVE_SSSE3_EXTERNAL + c->add_hfyu_left_prediction = ff_add_hfyu_left_prediction_ssse3; + if (mm_flags & AV_CPU_FLAG_SSE4) // not really sse4, just slow on Conroe + c->add_hfyu_left_prediction = ff_add_hfyu_left_prediction_sse4; + + if (mm_flags & AV_CPU_FLAG_ATOM) + c->apply_window_int16 = ff_apply_window_int16_ssse3_atom; + else + c->apply_window_int16 = ff_apply_window_int16_ssse3; + if (!(mm_flags & (AV_CPU_FLAG_SSE42|AV_CPU_FLAG_3DNOW))) // cachesplit + c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_ssse3; + c->bswap_buf = ff_bswap32_buf_ssse3; +#endif /* HAVE_SSSE3_EXTERNAL */ +} + +static av_cold void dsputil_init_sse4(DSPContext *c, AVCodecContext *avctx, + int mm_flags) +{ +#if HAVE_SSE4_EXTERNAL + c->vector_clip_int32 = ff_vector_clip_int32_sse4; +#endif /* HAVE_SSE4_EXTERNAL */ +} + +av_cold void ff_dsputil_init_mmx(DSPContext *c, AVCodecContext *avctx) +{ + int mm_flags = av_get_cpu_flags(); + +#if HAVE_7REGS && HAVE_INLINE_ASM + if (mm_flags & AV_CPU_FLAG_CMOV) + c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov; +#endif + + if (mm_flags & AV_CPU_FLAG_MMX) { +#if HAVE_INLINE_ASM + const int idct_algo = avctx->idct_algo; + + if (avctx->lowres == 0 && avctx->bits_per_raw_sample <= 8) { + if (idct_algo == FF_IDCT_AUTO || idct_algo == FF_IDCT_SIMPLEMMX) { + c->idct_put = ff_simple_idct_put_mmx; + c->idct_add = ff_simple_idct_add_mmx; + c->idct = ff_simple_idct_mmx; + c->idct_permutation_type = FF_SIMPLE_IDCT_PERM; + } else if (idct_algo == FF_IDCT_XVIDMMX) { + if (mm_flags & AV_CPU_FLAG_SSE2) { + c->idct_put = ff_idct_xvid_sse2_put; + c->idct_add = ff_idct_xvid_sse2_add; + c->idct = ff_idct_xvid_sse2; + c->idct_permutation_type = FF_SSE2_IDCT_PERM; + } else if (mm_flags & AV_CPU_FLAG_MMXEXT) { + c->idct_put = ff_idct_xvid_mmxext_put; + c->idct_add = ff_idct_xvid_mmxext_add; + c->idct = ff_idct_xvid_mmxext; + } else { + c->idct_put = ff_idct_xvid_mmx_put; + c->idct_add = ff_idct_xvid_mmx_add; + c->idct = ff_idct_xvid_mmx; + } + } + } +#endif /* HAVE_INLINE_ASM */ + + dsputil_init_mmx(c, avctx, mm_flags); + } + + if (mm_flags & AV_CPU_FLAG_MMXEXT) + dsputil_init_mmxext(c, avctx, mm_flags); + + if (mm_flags & AV_CPU_FLAG_SSE) + dsputil_init_sse(c, avctx, mm_flags); + + if (mm_flags & AV_CPU_FLAG_SSE2) + dsputil_init_sse2(c, avctx, mm_flags); + + if (mm_flags & AV_CPU_FLAG_SSSE3) + dsputil_init_ssse3(c, avctx, mm_flags); + + if (mm_flags & AV_CPU_FLAG_SSE4) + dsputil_init_sse4(c, avctx, mm_flags); + + if (CONFIG_ENCODERS) + ff_dsputilenc_init_mmx(c, avctx); +} diff --git a/ffmpeg/libavcodec/x86/dsputil_mmx.h b/ffmpeg/libavcodec/x86/dsputil_mmx.h new file mode 100644 index 0000000..28b0078 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputil_mmx.h @@ -0,0 +1,113 @@ +/* + * MMX optimized DSP utils + * Copyright (c) 2007 Aurelien Jacobs + * + * 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 + */ + +#ifndef AVCODEC_X86_DSPUTIL_MMX_H +#define AVCODEC_X86_DSPUTIL_MMX_H + +#include +#include + +#include "libavcodec/dsputil.h" +#include "libavutil/x86/asm.h" + +extern const uint64_t ff_bone; +extern const uint64_t ff_wtwo; + +extern const xmm_reg ff_pw_3; +extern const xmm_reg ff_pw_4; +extern const xmm_reg ff_pw_5; +extern const xmm_reg ff_pw_8; +extern const uint64_t ff_pw_15; +extern const xmm_reg ff_pw_16; +extern const xmm_reg ff_pw_18; +extern const uint64_t ff_pw_20; +extern const xmm_reg ff_pw_32; +extern const uint64_t ff_pw_42; +extern const uint64_t ff_pw_53; +extern const xmm_reg ff_pw_64; +extern const uint64_t ff_pw_96; +extern const uint64_t ff_pw_128; +extern const uint64_t ff_pw_255; + +extern const xmm_reg ff_pb_1; +extern const xmm_reg ff_pb_3; +extern const uint64_t ff_pb_3F; +extern const xmm_reg ff_pb_F8; +extern const uint64_t ff_pb_FC; + +extern const double ff_pd_1[2]; +extern const double ff_pd_2[2]; + +#define SBUTTERFLY(a,b,t,n,m)\ + "mov" #m " " #a ", " #t " \n\t" /* abcd */\ + "punpckl" #n " " #b ", " #a " \n\t" /* aebf */\ + "punpckh" #n " " #b ", " #t " \n\t" /* cgdh */\ + +#define TRANSPOSE4(a,b,c,d,t)\ + SBUTTERFLY(a,b,t,wd,q) /* a=aebf t=cgdh */\ + SBUTTERFLY(c,d,b,wd,q) /* c=imjn b=kolp */\ + SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\ + SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */ + +#define MOVQ_WONE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%" #regd ", %%" #regd " \n\t" \ + "psrlw $15, %%" #regd ::) + +void ff_dsputilenc_init_mmx(DSPContext* c, AVCodecContext *avctx); +void ff_dsputil_init_pix_mmx(DSPContext* c, AVCodecContext *avctx); + +void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, int line_size); +void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, int line_size); +void ff_put_signed_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, int line_size); + +void ff_avg_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +void ff_put_cavs_qpel8_mc00_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_cavs_qpel8_mc00_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_put_cavs_qpel16_mc00_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride); +void ff_avg_cavs_qpel16_mc00_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride); + +void ff_put_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int rnd); + +void ff_put_rv40_qpel8_mc33_mmx(uint8_t *block, uint8_t *pixels, ptrdiff_t stride); +void ff_put_rv40_qpel16_mc33_mmx(uint8_t *block, uint8_t *pixels, ptrdiff_t stride); +void ff_avg_rv40_qpel8_mc33_mmx(uint8_t *block, uint8_t *pixels, ptrdiff_t stride); +void ff_avg_rv40_qpel16_mc33_mmx(uint8_t *block, uint8_t *pixels, ptrdiff_t stride); + +void ff_mmx_idct(int16_t *block); +void ff_mmxext_idct(int16_t *block); + + +void ff_deinterlace_line_mmx(uint8_t *dst, + const uint8_t *lum_m4, const uint8_t *lum_m3, + const uint8_t *lum_m2, const uint8_t *lum_m1, + const uint8_t *lum, + int size); + +void ff_deinterlace_line_inplace_mmx(const uint8_t *lum_m4, + const uint8_t *lum_m3, + const uint8_t *lum_m2, + const uint8_t *lum_m1, + const uint8_t *lum, int size); + +#endif /* AVCODEC_X86_DSPUTIL_MMX_H */ diff --git a/ffmpeg/libavcodec/x86/dsputil_qns_template.c b/ffmpeg/libavcodec/x86/dsputil_qns_template.c new file mode 100644 index 0000000..77a41b9 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputil_qns_template.c @@ -0,0 +1,101 @@ +/* + * DSP utils : QNS functions are compiled 3 times for mmx/3dnow/ssse3 + * Copyright (c) 2004 Michael Niedermayer + * + * MMX optimization by Michael Niedermayer + * 3DNow! and SSSE3 optimization by Zuxy Meng + * + * 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 + */ + +#define MAX_ABS (512 >> (SCALE_OFFSET>0 ? SCALE_OFFSET : 0)) + +static int DEF(try_8x8basis)(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale) +{ + x86_reg i=0; + + assert(FFABS(scale) < MAX_ABS); + scale<<= 16 + SCALE_OFFSET - BASIS_SHIFT + RECON_SHIFT; + + SET_RND(mm6); + __asm__ volatile( + "pxor %%mm7, %%mm7 \n\t" + "movd %4, %%mm5 \n\t" + "punpcklwd %%mm5, %%mm5 \n\t" + "punpcklwd %%mm5, %%mm5 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq 8(%1, %0), %%mm1 \n\t" + PMULHRW(%%mm0, %%mm1, %%mm5, %%mm6) + "paddw (%2, %0), %%mm0 \n\t" + "paddw 8(%2, %0), %%mm1 \n\t" + "psraw $6, %%mm0 \n\t" + "psraw $6, %%mm1 \n\t" + "pmullw (%3, %0), %%mm0 \n\t" + "pmullw 8(%3, %0), %%mm1 \n\t" + "pmaddwd %%mm0, %%mm0 \n\t" + "pmaddwd %%mm1, %%mm1 \n\t" + "paddd %%mm1, %%mm0 \n\t" + "psrld $4, %%mm0 \n\t" + "paddd %%mm0, %%mm7 \n\t" + "add $16, %0 \n\t" + "cmp $128, %0 \n\t" //FIXME optimize & bench + " jb 1b \n\t" + PHADDD(%%mm7, %%mm6) + "psrld $2, %%mm7 \n\t" + "movd %%mm7, %0 \n\t" + + : "+r" (i) + : "r"(basis), "r"(rem), "r"(weight), "g"(scale) + ); + return i; +} + +static void DEF(add_8x8basis)(int16_t rem[64], int16_t basis[64], int scale) +{ + x86_reg i=0; + + if(FFABS(scale) < MAX_ABS){ + scale<<= 16 + SCALE_OFFSET - BASIS_SHIFT + RECON_SHIFT; + SET_RND(mm6); + __asm__ volatile( + "movd %3, %%mm5 \n\t" + "punpcklwd %%mm5, %%mm5 \n\t" + "punpcklwd %%mm5, %%mm5 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1, %0), %%mm0 \n\t" + "movq 8(%1, %0), %%mm1 \n\t" + PMULHRW(%%mm0, %%mm1, %%mm5, %%mm6) + "paddw (%2, %0), %%mm0 \n\t" + "paddw 8(%2, %0), %%mm1 \n\t" + "movq %%mm0, (%2, %0) \n\t" + "movq %%mm1, 8(%2, %0) \n\t" + "add $16, %0 \n\t" + "cmp $128, %0 \n\t" // FIXME optimize & bench + " jb 1b \n\t" + + : "+r" (i) + : "r"(basis), "r"(rem), "g"(scale) + ); + }else{ + for(i=0; i<8*8; i++){ + rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT); + } + } +} diff --git a/ffmpeg/libavcodec/x86/dsputil_rnd_template.c b/ffmpeg/libavcodec/x86/dsputil_rnd_template.c new file mode 100644 index 0000000..1a89b77 --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputil_rnd_template.c @@ -0,0 +1,221 @@ +/* + * DSP utils mmx functions are compiled twice for rnd/no_rnd + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003-2004 Michael Niedermayer + * + * MMX optimization by Nick Kurshev + * mostly rewritten by Michael Niedermayer + * and improved by Zdenek Kabelac + * + * 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 + */ + +// put_pixels +static void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_ZERO(mm7); + SET_RND(mm6); // =2 for rnd and =1 for no_rnd version + __asm__ volatile( + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm4 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "xor %%"REG_a", %%"REG_a" \n\t" + "add %3, %1 \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm2, %%mm3 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "paddusw %%mm2, %%mm0 \n\t" + "paddusw %%mm3, %%mm1 \n\t" + "paddusw %%mm6, %%mm4 \n\t" + "paddusw %%mm6, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "psrlw $2, %%mm4 \n\t" + "psrlw $2, %%mm5 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "movq %%mm4, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3 + "movq 1(%1, %%"REG_a"), %%mm4 \n\t" + "movq %%mm2, %%mm3 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm2, %%mm4 \n\t" + "paddusw %%mm3, %%mm5 \n\t" + "paddusw %%mm6, %%mm0 \n\t" + "paddusw %%mm6, %%mm1 \n\t" + "paddusw %%mm4, %%mm0 \n\t" + "paddusw %%mm5, %%mm1 \n\t" + "psrlw $2, %%mm0 \n\t" + "psrlw $2, %%mm1 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "movq %%mm0, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "subl $2, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels) + :"D"(block), "r"((x86_reg)line_size) + :REG_a, "memory"); +} + +// in case more speed is needed - unroling would certainly help +static void DEF(avg, pixels8)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + JUMPALIGN(); + do { + __asm__ volatile( + "movq %0, %%mm0 \n\t" + "movq %1, %%mm1 \n\t" + OP_AVG(%%mm0, %%mm1, %%mm2, %%mm6) + "movq %%mm2, %0 \n\t" + :"+m"(*block) + :"m"(*pixels) + :"memory"); + pixels += line_size; + block += line_size; + } + while (--h); +} + +static void DEF(avg, pixels16)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + JUMPALIGN(); + do { + __asm__ volatile( + "movq %0, %%mm0 \n\t" + "movq %1, %%mm1 \n\t" + OP_AVG(%%mm0, %%mm1, %%mm2, %%mm6) + "movq %%mm2, %0 \n\t" + "movq 8%0, %%mm0 \n\t" + "movq 8%1, %%mm1 \n\t" + OP_AVG(%%mm0, %%mm1, %%mm2, %%mm6) + "movq %%mm2, 8%0 \n\t" + :"+m"(*block) + :"m"(*pixels) + :"memory"); + pixels += line_size; + block += line_size; + } + while (--h); +} + +// this routine is 'slightly' suboptimal but mostly unused +static void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_ZERO(mm7); + SET_RND(mm6); // =2 for rnd and =1 for no_rnd version + __asm__ volatile( + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm4 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "xor %%"REG_a", %%"REG_a" \n\t" + "add %3, %1 \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm2, %%mm3 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "paddusw %%mm2, %%mm0 \n\t" + "paddusw %%mm3, %%mm1 \n\t" + "paddusw %%mm6, %%mm4 \n\t" + "paddusw %%mm6, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "psrlw $2, %%mm4 \n\t" + "psrlw $2, %%mm5 \n\t" + "movq (%2, %%"REG_a"), %%mm3 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "pcmpeqd %%mm2, %%mm2 \n\t" + "paddb %%mm2, %%mm2 \n\t" + OP_AVG(%%mm3, %%mm4, %%mm5, %%mm2) + "movq %%mm5, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3 + "movq 1(%1, %%"REG_a"), %%mm4 \n\t" + "movq %%mm2, %%mm3 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm2, %%mm4 \n\t" + "paddusw %%mm3, %%mm5 \n\t" + "paddusw %%mm6, %%mm0 \n\t" + "paddusw %%mm6, %%mm1 \n\t" + "paddusw %%mm4, %%mm0 \n\t" + "paddusw %%mm5, %%mm1 \n\t" + "psrlw $2, %%mm0 \n\t" + "psrlw $2, %%mm1 \n\t" + "movq (%2, %%"REG_a"), %%mm3 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "pcmpeqd %%mm2, %%mm2 \n\t" + "paddb %%mm2, %%mm2 \n\t" + OP_AVG(%%mm3, %%mm0, %%mm1, %%mm2) + "movq %%mm1, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "subl $2, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels) + :"D"(block), "r"((x86_reg)line_size) + :REG_a, "memory"); +} + +//FIXME optimize +static void DEF(put, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){ + DEF(put, pixels8_xy2)(block , pixels , line_size, h); + DEF(put, pixels8_xy2)(block+8, pixels+8, line_size, h); +} + +static void DEF(avg, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){ + DEF(avg, pixels8_xy2)(block , pixels , line_size, h); + DEF(avg, pixels8_xy2)(block+8, pixels+8, line_size, h); +} diff --git a/ffmpeg/libavcodec/x86/dsputilenc.asm b/ffmpeg/libavcodec/x86/dsputilenc.asm new file mode 100644 index 0000000..1839bee --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputilenc.asm @@ -0,0 +1,487 @@ +;***************************************************************************** +;* MMX optimized DSP utils +;***************************************************************************** +;* Copyright (c) 2000, 2001 Fabrice Bellard +;* Copyright (c) 2002-2004 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 "libavutil/x86/x86util.asm" + +SECTION .text + +%macro DIFF_PIXELS_1 4 + movh %1, %3 + movh %2, %4 + punpcklbw %2, %1 + punpcklbw %1, %1 + psubw %1, %2 +%endmacro + +; %1=uint8_t *pix1, %2=uint8_t *pix2, %3=static offset, %4=stride, %5=stride*3 +; %6=temporary storage location +; this macro requires $mmsize stack space (aligned) on %6 (except on SSE+x86-64) +%macro DIFF_PIXELS_8 6 + DIFF_PIXELS_1 m0, m7, [%1 +%3], [%2 +%3] + DIFF_PIXELS_1 m1, m7, [%1+%4 +%3], [%2+%4 +%3] + DIFF_PIXELS_1 m2, m7, [%1+%4*2+%3], [%2+%4*2+%3] + add %1, %5 + add %2, %5 + DIFF_PIXELS_1 m3, m7, [%1 +%3], [%2 +%3] + DIFF_PIXELS_1 m4, m7, [%1+%4 +%3], [%2+%4 +%3] + DIFF_PIXELS_1 m5, m7, [%1+%4*2+%3], [%2+%4*2+%3] + DIFF_PIXELS_1 m6, m7, [%1+%5 +%3], [%2+%5 +%3] +%ifdef m8 + DIFF_PIXELS_1 m7, m8, [%1+%4*4+%3], [%2+%4*4+%3] +%else + mova [%6], m0 + DIFF_PIXELS_1 m7, m0, [%1+%4*4+%3], [%2+%4*4+%3] + mova m0, [%6] +%endif + sub %1, %5 + sub %2, %5 +%endmacro + +%macro HADAMARD8 0 + SUMSUB_BADC w, 0, 1, 2, 3 + SUMSUB_BADC w, 4, 5, 6, 7 + SUMSUB_BADC w, 0, 2, 1, 3 + SUMSUB_BADC w, 4, 6, 5, 7 + SUMSUB_BADC w, 0, 4, 1, 5 + SUMSUB_BADC w, 2, 6, 3, 7 +%endmacro + +%macro ABS1_SUM 3 + ABS1 %1, %2 + paddusw %3, %1 +%endmacro + +%macro ABS2_SUM 6 + ABS2 %1, %2, %3, %4 + paddusw %5, %1 + paddusw %6, %2 +%endmacro + +%macro ABS_SUM_8x8_64 1 + ABS2 m0, m1, m8, m9 + ABS2_SUM m2, m3, m8, m9, m0, m1 + ABS2_SUM m4, m5, m8, m9, m0, m1 + ABS2_SUM m6, m7, m8, m9, m0, m1 + paddusw m0, m1 +%endmacro + +%macro ABS_SUM_8x8_32 1 + mova [%1], m7 + ABS1 m0, m7 + ABS1 m1, m7 + ABS1_SUM m2, m7, m0 + ABS1_SUM m3, m7, m1 + ABS1_SUM m4, m7, m0 + ABS1_SUM m5, m7, m1 + ABS1_SUM m6, m7, m0 + mova m2, [%1] + ABS1_SUM m2, m7, m1 + paddusw m0, m1 +%endmacro + +; FIXME: HSUM saturates at 64k, while an 8x8 hadamard or dct block can get up to +; about 100k on extreme inputs. But that's very unlikely to occur in natural video, +; and it's even more unlikely to not have any alternative mvs/modes with lower cost. +%macro HSUM 3 +%if cpuflag(sse2) + movhlps %2, %1 + paddusw %1, %2 + pshuflw %2, %1, 0xE + paddusw %1, %2 + pshuflw %2, %1, 0x1 + paddusw %1, %2 + movd %3, %1 +%elif cpuflag(mmxext) + pshufw %2, %1, 0xE + paddusw %1, %2 + pshufw %2, %1, 0x1 + paddusw %1, %2 + movd %3, %1 +%elif cpuflag(mmx) + mova %2, %1 + psrlq %1, 32 + paddusw %1, %2 + mova %2, %1 + psrlq %1, 16 + paddusw %1, %2 + movd %3, %1 +%endif +%endmacro + +%macro STORE4 5 + mova [%1+mmsize*0], %2 + mova [%1+mmsize*1], %3 + mova [%1+mmsize*2], %4 + mova [%1+mmsize*3], %5 +%endmacro + +%macro LOAD4 5 + mova %2, [%1+mmsize*0] + mova %3, [%1+mmsize*1] + mova %4, [%1+mmsize*2] + mova %5, [%1+mmsize*3] +%endmacro + +%macro hadamard8_16_wrapper 2 +cglobal hadamard8_diff, 4, 4, %1 +%ifndef m8 + %assign pad %2*mmsize-(4+stack_offset&(mmsize-1)) + SUB rsp, pad +%endif + call hadamard8x8_diff %+ SUFFIX +%ifndef m8 + ADD rsp, pad +%endif + RET + +cglobal hadamard8_diff16, 5, 6, %1 +%ifndef m8 + %assign pad %2*mmsize-(4+stack_offset&(mmsize-1)) + SUB rsp, pad +%endif + + call hadamard8x8_diff %+ SUFFIX + mov r5d, eax + + add r1, 8 + add r2, 8 + call hadamard8x8_diff %+ SUFFIX + add r5d, eax + + cmp r4d, 16 + jne .done + + lea r1, [r1+r3*8-8] + lea r2, [r2+r3*8-8] + call hadamard8x8_diff %+ SUFFIX + add r5d, eax + + add r1, 8 + add r2, 8 + call hadamard8x8_diff %+ SUFFIX + add r5d, eax + +.done: + mov eax, r5d +%ifndef m8 + ADD rsp, pad +%endif + RET +%endmacro + +%macro HADAMARD8_DIFF 0-1 +%if cpuflag(sse2) +hadamard8x8_diff %+ SUFFIX: + lea r0, [r3*3] + DIFF_PIXELS_8 r1, r2, 0, r3, r0, rsp+gprsize + HADAMARD8 +%if ARCH_X86_64 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%else + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, [rsp+gprsize], [rsp+mmsize+gprsize] +%endif + HADAMARD8 + ABS_SUM_8x8 rsp+gprsize + HSUM m0, m1, eax + and eax, 0xFFFF + ret + +hadamard8_16_wrapper %1, 3 +%elif cpuflag(mmx) +ALIGN 16 +; int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2, +; int stride, int h) +; r0 = void *s = unused, int h = unused (always 8) +; note how r1, r2 and r3 are not clobbered in this function, so 16x16 +; can simply call this 2x2x (and that's why we access rsp+gprsize +; everywhere, which is rsp of calling func +hadamard8x8_diff %+ SUFFIX: + lea r0, [r3*3] + + ; first 4x8 pixels + DIFF_PIXELS_8 r1, r2, 0, r3, r0, rsp+gprsize+0x60 + HADAMARD8 + mova [rsp+gprsize+0x60], m7 + TRANSPOSE4x4W 0, 1, 2, 3, 7 + STORE4 rsp+gprsize, m0, m1, m2, m3 + mova m7, [rsp+gprsize+0x60] + TRANSPOSE4x4W 4, 5, 6, 7, 0 + STORE4 rsp+gprsize+0x40, m4, m5, m6, m7 + + ; second 4x8 pixels + DIFF_PIXELS_8 r1, r2, 4, r3, r0, rsp+gprsize+0x60 + HADAMARD8 + mova [rsp+gprsize+0x60], m7 + TRANSPOSE4x4W 0, 1, 2, 3, 7 + STORE4 rsp+gprsize+0x20, m0, m1, m2, m3 + mova m7, [rsp+gprsize+0x60] + TRANSPOSE4x4W 4, 5, 6, 7, 0 + + LOAD4 rsp+gprsize+0x40, m0, m1, m2, m3 + HADAMARD8 + ABS_SUM_8x8_32 rsp+gprsize+0x60 + mova [rsp+gprsize+0x60], m0 + + LOAD4 rsp+gprsize , m0, m1, m2, m3 + LOAD4 rsp+gprsize+0x20, m4, m5, m6, m7 + HADAMARD8 + ABS_SUM_8x8_32 rsp+gprsize + paddusw m0, [rsp+gprsize+0x60] + + HSUM m0, m1, eax + and rax, 0xFFFF + ret + +hadamard8_16_wrapper 0, 14 +%endif +%endmacro + +INIT_MMX mmx +HADAMARD8_DIFF + +INIT_MMX mmxext +HADAMARD8_DIFF + +INIT_XMM sse2 +%if ARCH_X86_64 +%define ABS_SUM_8x8 ABS_SUM_8x8_64 +%else +%define ABS_SUM_8x8 ABS_SUM_8x8_32 +%endif +HADAMARD8_DIFF 10 + +INIT_XMM ssse3 +%define ABS_SUM_8x8 ABS_SUM_8x8_64 +HADAMARD8_DIFF 9 + +INIT_XMM sse2 +; sse16_sse2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) +cglobal sse16, 5, 5, 8 + shr r4d, 1 + pxor m0, m0 ; mm0 = 0 + pxor m7, m7 ; mm7 holds the sum + +.next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned + movu m1, [r1 ] ; mm1 = pix1[0][0-15] + movu m2, [r2 ] ; mm2 = pix2[0][0-15] + movu m3, [r1+r3] ; mm3 = pix1[1][0-15] + movu m4, [r2+r3] ; mm4 = pix2[1][0-15] + + ; todo: mm1-mm2, mm3-mm4 + ; algo: subtract mm1 from mm2 with saturation and vice versa + ; OR the result to get the absolute difference + mova m5, m1 + mova m6, m3 + psubusb m1, m2 + psubusb m3, m4 + psubusb m2, m5 + psubusb m4, m6 + + por m2, m1 + por m4, m3 + + ; now convert to 16-bit vectors so we can square them + mova m1, m2 + mova m3, m4 + + punpckhbw m2, m0 + punpckhbw m4, m0 + punpcklbw m1, m0 ; mm1 not spread over (mm1,mm2) + punpcklbw m3, m0 ; mm4 not spread over (mm3,mm4) + + pmaddwd m2, m2 + pmaddwd m4, m4 + pmaddwd m1, m1 + pmaddwd m3, m3 + + lea r1, [r1+r3*2] ; pix1 += 2*line_size + lea r2, [r2+r3*2] ; pix2 += 2*line_size + + paddd m1, m2 + paddd m3, m4 + paddd m7, m1 + paddd m7, m3 + + dec r4 + jnz .next2lines + + mova m1, m7 + psrldq m7, 8 ; shift hi qword to lo + paddd m7, m1 + mova m1, m7 + psrldq m7, 4 ; shift hi dword to lo + paddd m7, m1 + movd eax, m7 ; return value + RET + +INIT_MMX mmx +; get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size) +cglobal get_pixels, 3,4 + movsxdifnidn r2, r2d + add r0, 128 + mov r3, -128 + pxor m7, m7 +.loop: + mova m0, [r1] + mova m2, [r1+r2] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + mova [r0+r3+ 0], m0 + mova [r0+r3+ 8], m1 + mova [r0+r3+16], m2 + mova [r0+r3+24], m3 + lea r1, [r1+r2*2] + add r3, 32 + js .loop + REP_RET + +INIT_XMM sse2 +cglobal get_pixels, 3, 4 + movsxdifnidn r2, r2d + lea r3, [r2*3] + pxor m4, m4 + movh m0, [r1] + movh m1, [r1+r2] + movh m2, [r1+r2*2] + movh m3, [r1+r3] + lea r1, [r1+r2*4] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + mova [r0], m0 + mova [r0+0x10], m1 + mova [r0+0x20], m2 + mova [r0+0x30], m3 + movh m0, [r1] + movh m1, [r1+r2*1] + movh m2, [r1+r2*2] + movh m3, [r1+r3] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + mova [r0+0x40], m0 + mova [r0+0x50], m1 + mova [r0+0x60], m2 + mova [r0+0x70], m3 + RET + +INIT_MMX mmx +; diff_pixels_mmx(int16_t *block, const uint8_t *s1, const unint8_t *s2, stride) +cglobal diff_pixels, 4,5 + movsxdifnidn r3, r3d + pxor m7, m7 + add r0, 128 + mov r4, -128 +.loop: + mova m0, [r1] + mova m2, [r2] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + psubw m0, m2 + psubw m1, m3 + mova [r0+r4+0], m0 + mova [r0+r4+8], m1 + add r1, r3 + add r2, r3 + add r4, 16 + jne .loop + REP_RET + +INIT_MMX mmx +; pix_sum16_mmx(uint8_t * pix, int line_size) +cglobal pix_sum16, 2, 3 + movsxdifnidn r1, r1d + mov r2, r1 + neg r2 + shl r2, 4 + sub r0, r2 + pxor m7, m7 + pxor m6, m6 +.loop: + mova m0, [r0+r2+0] + mova m1, [r0+r2+0] + mova m2, [r0+r2+8] + mova m3, [r0+r2+8] + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + paddw m1, m0 + paddw m3, m2 + paddw m3, m1 + paddw m6, m3 + add r2, r1 + js .loop + mova m5, m6 + psrlq m6, 32 + paddw m6, m5 + mova m5, m6 + psrlq m6, 16 + paddw m6, m5 + movd eax, m6 + and eax, 0xffff + RET + +INIT_MMX mmx +; pix_norm1_mmx(uint8_t *pix, int line_size) +cglobal pix_norm1, 2, 4 + movsxdifnidn r1, r1d + mov r2, 16 + pxor m0, m0 + pxor m7, m7 +.loop: + mova m2, [r0+0] + mova m3, [r0+8] + mova m1, m2 + punpckhbw m1, m0 + punpcklbw m2, m0 + mova m4, m3 + punpckhbw m3, m0 + punpcklbw m4, m0 + pmaddwd m1, m1 + pmaddwd m2, m2 + pmaddwd m3, m3 + pmaddwd m4, m4 + paddd m2, m1 + paddd m4, m3 + paddd m7, m2 + add r0, r1 + paddd m7, m4 + dec r2 + jne .loop + mova m1, m7 + psrlq m7, 32 + paddd m1, m7 + movd eax, m1 + RET + diff --git a/ffmpeg/libavcodec/x86/dsputilenc_mmx.c b/ffmpeg/libavcodec/x86/dsputilenc_mmx.c new file mode 100644 index 0000000..a3f268e --- /dev/null +++ b/ffmpeg/libavcodec/x86/dsputilenc_mmx.c @@ -0,0 +1,1060 @@ +/* + * MMX optimized DSP utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + * + * MMX optimization by Nick Kurshev + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/dct.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/mpegvideo.h" +#include "libavcodec/mathops.h" +#include "dsputil_mmx.h" + +void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size); +void ff_get_pixels_sse2(int16_t *block, const uint8_t *pixels, int line_size); +void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2, int stride); +int ff_pix_sum16_mmx(uint8_t * pix, int line_size); +int ff_pix_norm1_mmx(uint8_t *pix, int line_size); + +#if HAVE_INLINE_ASM + +static int sse8_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { + int tmp; + __asm__ volatile ( + "movl %4,%%ecx\n" + "shr $1,%%ecx\n" + "pxor %%mm0,%%mm0\n" /* mm0 = 0 */ + "pxor %%mm7,%%mm7\n" /* mm7 holds the sum */ + "1:\n" + "movq (%0),%%mm1\n" /* mm1 = pix1[0][0-7] */ + "movq (%1),%%mm2\n" /* mm2 = pix2[0][0-7] */ + "movq (%0,%3),%%mm3\n" /* mm3 = pix1[1][0-7] */ + "movq (%1,%3),%%mm4\n" /* mm4 = pix2[1][0-7] */ + + /* todo: mm1-mm2, mm3-mm4 */ + /* algo: subtract mm1 from mm2 with saturation and vice versa */ + /* OR the results to get absolute difference */ + "movq %%mm1,%%mm5\n" + "movq %%mm3,%%mm6\n" + "psubusb %%mm2,%%mm1\n" + "psubusb %%mm4,%%mm3\n" + "psubusb %%mm5,%%mm2\n" + "psubusb %%mm6,%%mm4\n" + + "por %%mm1,%%mm2\n" + "por %%mm3,%%mm4\n" + + /* now convert to 16-bit vectors so we can square them */ + "movq %%mm2,%%mm1\n" + "movq %%mm4,%%mm3\n" + + "punpckhbw %%mm0,%%mm2\n" + "punpckhbw %%mm0,%%mm4\n" + "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */ + "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */ + + "pmaddwd %%mm2,%%mm2\n" + "pmaddwd %%mm4,%%mm4\n" + "pmaddwd %%mm1,%%mm1\n" + "pmaddwd %%mm3,%%mm3\n" + + "lea (%0,%3,2), %0\n" /* pix1 += 2*line_size */ + "lea (%1,%3,2), %1\n" /* pix2 += 2*line_size */ + + "paddd %%mm2,%%mm1\n" + "paddd %%mm4,%%mm3\n" + "paddd %%mm1,%%mm7\n" + "paddd %%mm3,%%mm7\n" + + "decl %%ecx\n" + "jnz 1b\n" + + "movq %%mm7,%%mm1\n" + "psrlq $32, %%mm7\n" /* shift hi dword to lo */ + "paddd %%mm7,%%mm1\n" + "movd %%mm1,%2\n" + : "+r" (pix1), "+r" (pix2), "=r"(tmp) + : "r" ((x86_reg)line_size) , "m" (h) + : "%ecx"); + return tmp; +} + +static int sse16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { + int tmp; + __asm__ volatile ( + "movl %4,%%ecx\n" + "pxor %%mm0,%%mm0\n" /* mm0 = 0 */ + "pxor %%mm7,%%mm7\n" /* mm7 holds the sum */ + "1:\n" + "movq (%0),%%mm1\n" /* mm1 = pix1[0-7] */ + "movq (%1),%%mm2\n" /* mm2 = pix2[0-7] */ + "movq 8(%0),%%mm3\n" /* mm3 = pix1[8-15] */ + "movq 8(%1),%%mm4\n" /* mm4 = pix2[8-15] */ + + /* todo: mm1-mm2, mm3-mm4 */ + /* algo: subtract mm1 from mm2 with saturation and vice versa */ + /* OR the results to get absolute difference */ + "movq %%mm1,%%mm5\n" + "movq %%mm3,%%mm6\n" + "psubusb %%mm2,%%mm1\n" + "psubusb %%mm4,%%mm3\n" + "psubusb %%mm5,%%mm2\n" + "psubusb %%mm6,%%mm4\n" + + "por %%mm1,%%mm2\n" + "por %%mm3,%%mm4\n" + + /* now convert to 16-bit vectors so we can square them */ + "movq %%mm2,%%mm1\n" + "movq %%mm4,%%mm3\n" + + "punpckhbw %%mm0,%%mm2\n" + "punpckhbw %%mm0,%%mm4\n" + "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */ + "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */ + + "pmaddwd %%mm2,%%mm2\n" + "pmaddwd %%mm4,%%mm4\n" + "pmaddwd %%mm1,%%mm1\n" + "pmaddwd %%mm3,%%mm3\n" + + "add %3,%0\n" + "add %3,%1\n" + + "paddd %%mm2,%%mm1\n" + "paddd %%mm4,%%mm3\n" + "paddd %%mm1,%%mm7\n" + "paddd %%mm3,%%mm7\n" + + "decl %%ecx\n" + "jnz 1b\n" + + "movq %%mm7,%%mm1\n" + "psrlq $32, %%mm7\n" /* shift hi dword to lo */ + "paddd %%mm7,%%mm1\n" + "movd %%mm1,%2\n" + : "+r" (pix1), "+r" (pix2), "=r"(tmp) + : "r" ((x86_reg)line_size) , "m" (h) + : "%ecx"); + return tmp; +} + +static int hf_noise8_mmx(uint8_t * pix1, int line_size, int h) { + int tmp; + __asm__ volatile ( + "movl %3,%%ecx\n" + "pxor %%mm7,%%mm7\n" + "pxor %%mm6,%%mm6\n" + + "movq (%0),%%mm0\n" + "movq %%mm0, %%mm1\n" + "psllq $8, %%mm0\n" + "psrlq $8, %%mm1\n" + "psrlq $8, %%mm0\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm0\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm2\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm0\n" + "psubw %%mm3, %%mm2\n" + + "add %2,%0\n" + + "movq (%0),%%mm4\n" + "movq %%mm4, %%mm1\n" + "psllq $8, %%mm4\n" + "psrlq $8, %%mm1\n" + "psrlq $8, %%mm4\n" + "movq %%mm4, %%mm5\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm4\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm5\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm4\n" + "psubw %%mm3, %%mm5\n" + "psubw %%mm4, %%mm0\n" + "psubw %%mm5, %%mm2\n" + "pxor %%mm3, %%mm3\n" + "pxor %%mm1, %%mm1\n" + "pcmpgtw %%mm0, %%mm3\n\t" + "pcmpgtw %%mm2, %%mm1\n\t" + "pxor %%mm3, %%mm0\n" + "pxor %%mm1, %%mm2\n" + "psubw %%mm3, %%mm0\n" + "psubw %%mm1, %%mm2\n" + "paddw %%mm0, %%mm2\n" + "paddw %%mm2, %%mm6\n" + + "add %2,%0\n" + "1:\n" + + "movq (%0),%%mm0\n" + "movq %%mm0, %%mm1\n" + "psllq $8, %%mm0\n" + "psrlq $8, %%mm1\n" + "psrlq $8, %%mm0\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm0\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm2\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm0\n" + "psubw %%mm3, %%mm2\n" + "psubw %%mm0, %%mm4\n" + "psubw %%mm2, %%mm5\n" + "pxor %%mm3, %%mm3\n" + "pxor %%mm1, %%mm1\n" + "pcmpgtw %%mm4, %%mm3\n\t" + "pcmpgtw %%mm5, %%mm1\n\t" + "pxor %%mm3, %%mm4\n" + "pxor %%mm1, %%mm5\n" + "psubw %%mm3, %%mm4\n" + "psubw %%mm1, %%mm5\n" + "paddw %%mm4, %%mm5\n" + "paddw %%mm5, %%mm6\n" + + "add %2,%0\n" + + "movq (%0),%%mm4\n" + "movq %%mm4, %%mm1\n" + "psllq $8, %%mm4\n" + "psrlq $8, %%mm1\n" + "psrlq $8, %%mm4\n" + "movq %%mm4, %%mm5\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm4\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm5\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm4\n" + "psubw %%mm3, %%mm5\n" + "psubw %%mm4, %%mm0\n" + "psubw %%mm5, %%mm2\n" + "pxor %%mm3, %%mm3\n" + "pxor %%mm1, %%mm1\n" + "pcmpgtw %%mm0, %%mm3\n\t" + "pcmpgtw %%mm2, %%mm1\n\t" + "pxor %%mm3, %%mm0\n" + "pxor %%mm1, %%mm2\n" + "psubw %%mm3, %%mm0\n" + "psubw %%mm1, %%mm2\n" + "paddw %%mm0, %%mm2\n" + "paddw %%mm2, %%mm6\n" + + "add %2,%0\n" + "subl $2, %%ecx\n" + " jnz 1b\n" + + "movq %%mm6, %%mm0\n" + "punpcklwd %%mm7,%%mm0\n" + "punpckhwd %%mm7,%%mm6\n" + "paddd %%mm0, %%mm6\n" + + "movq %%mm6,%%mm0\n" + "psrlq $32, %%mm6\n" + "paddd %%mm6,%%mm0\n" + "movd %%mm0,%1\n" + : "+r" (pix1), "=r"(tmp) + : "r" ((x86_reg)line_size) , "g" (h-2) + : "%ecx"); + return tmp; +} + +static int hf_noise16_mmx(uint8_t * pix1, int line_size, int h) { + int tmp; + uint8_t * pix= pix1; + __asm__ volatile ( + "movl %3,%%ecx\n" + "pxor %%mm7,%%mm7\n" + "pxor %%mm6,%%mm6\n" + + "movq (%0),%%mm0\n" + "movq 1(%0),%%mm1\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm0\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm2\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm0\n" + "psubw %%mm3, %%mm2\n" + + "add %2,%0\n" + + "movq (%0),%%mm4\n" + "movq 1(%0),%%mm1\n" + "movq %%mm4, %%mm5\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm4\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm5\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm4\n" + "psubw %%mm3, %%mm5\n" + "psubw %%mm4, %%mm0\n" + "psubw %%mm5, %%mm2\n" + "pxor %%mm3, %%mm3\n" + "pxor %%mm1, %%mm1\n" + "pcmpgtw %%mm0, %%mm3\n\t" + "pcmpgtw %%mm2, %%mm1\n\t" + "pxor %%mm3, %%mm0\n" + "pxor %%mm1, %%mm2\n" + "psubw %%mm3, %%mm0\n" + "psubw %%mm1, %%mm2\n" + "paddw %%mm0, %%mm2\n" + "paddw %%mm2, %%mm6\n" + + "add %2,%0\n" + "1:\n" + + "movq (%0),%%mm0\n" + "movq 1(%0),%%mm1\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm0\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm2\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm0\n" + "psubw %%mm3, %%mm2\n" + "psubw %%mm0, %%mm4\n" + "psubw %%mm2, %%mm5\n" + "pxor %%mm3, %%mm3\n" + "pxor %%mm1, %%mm1\n" + "pcmpgtw %%mm4, %%mm3\n\t" + "pcmpgtw %%mm5, %%mm1\n\t" + "pxor %%mm3, %%mm4\n" + "pxor %%mm1, %%mm5\n" + "psubw %%mm3, %%mm4\n" + "psubw %%mm1, %%mm5\n" + "paddw %%mm4, %%mm5\n" + "paddw %%mm5, %%mm6\n" + + "add %2,%0\n" + + "movq (%0),%%mm4\n" + "movq 1(%0),%%mm1\n" + "movq %%mm4, %%mm5\n" + "movq %%mm1, %%mm3\n" + "punpcklbw %%mm7,%%mm4\n" + "punpcklbw %%mm7,%%mm1\n" + "punpckhbw %%mm7,%%mm5\n" + "punpckhbw %%mm7,%%mm3\n" + "psubw %%mm1, %%mm4\n" + "psubw %%mm3, %%mm5\n" + "psubw %%mm4, %%mm0\n" + "psubw %%mm5, %%mm2\n" + "pxor %%mm3, %%mm3\n" + "pxor %%mm1, %%mm1\n" + "pcmpgtw %%mm0, %%mm3\n\t" + "pcmpgtw %%mm2, %%mm1\n\t" + "pxor %%mm3, %%mm0\n" + "pxor %%mm1, %%mm2\n" + "psubw %%mm3, %%mm0\n" + "psubw %%mm1, %%mm2\n" + "paddw %%mm0, %%mm2\n" + "paddw %%mm2, %%mm6\n" + + "add %2,%0\n" + "subl $2, %%ecx\n" + " jnz 1b\n" + + "movq %%mm6, %%mm0\n" + "punpcklwd %%mm7,%%mm0\n" + "punpckhwd %%mm7,%%mm6\n" + "paddd %%mm0, %%mm6\n" + + "movq %%mm6,%%mm0\n" + "psrlq $32, %%mm6\n" + "paddd %%mm6,%%mm0\n" + "movd %%mm0,%1\n" + : "+r" (pix1), "=r"(tmp) + : "r" ((x86_reg)line_size) , "g" (h-2) + : "%ecx"); + return tmp + hf_noise8_mmx(pix+8, line_size, h); +} + +static int nsse16_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { + MpegEncContext *c = p; + int score1, score2; + + if(c) score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h); + else score1 = sse16_mmx(c, pix1, pix2, line_size, h); + score2= hf_noise16_mmx(pix1, line_size, h) - hf_noise16_mmx(pix2, line_size, h); + + if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight; + else return score1 + FFABS(score2)*8; +} + +static int nsse8_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { + MpegEncContext *c = p; + int score1= sse8_mmx(c, pix1, pix2, line_size, h); + int score2= hf_noise8_mmx(pix1, line_size, h) - hf_noise8_mmx(pix2, line_size, h); + + if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight; + else return score1 + FFABS(score2)*8; +} + +static int vsad_intra16_mmx(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) { + int tmp; + + av_assert2( (((int)pix) & 7) == 0); + av_assert2((line_size &7) ==0); + +#define SUM(in0, in1, out0, out1) \ + "movq (%0), %%mm2\n"\ + "movq 8(%0), %%mm3\n"\ + "add %2,%0\n"\ + "movq %%mm2, " #out0 "\n"\ + "movq %%mm3, " #out1 "\n"\ + "psubusb " #in0 ", %%mm2\n"\ + "psubusb " #in1 ", %%mm3\n"\ + "psubusb " #out0 ", " #in0 "\n"\ + "psubusb " #out1 ", " #in1 "\n"\ + "por %%mm2, " #in0 "\n"\ + "por %%mm3, " #in1 "\n"\ + "movq " #in0 ", %%mm2\n"\ + "movq " #in1 ", %%mm3\n"\ + "punpcklbw %%mm7, " #in0 "\n"\ + "punpcklbw %%mm7, " #in1 "\n"\ + "punpckhbw %%mm7, %%mm2\n"\ + "punpckhbw %%mm7, %%mm3\n"\ + "paddw " #in1 ", " #in0 "\n"\ + "paddw %%mm3, %%mm2\n"\ + "paddw %%mm2, " #in0 "\n"\ + "paddw " #in0 ", %%mm6\n" + + + __asm__ volatile ( + "movl %3,%%ecx\n" + "pxor %%mm6,%%mm6\n" + "pxor %%mm7,%%mm7\n" + "movq (%0),%%mm0\n" + "movq 8(%0),%%mm1\n" + "add %2,%0\n" + "jmp 2f\n" + "1:\n" + + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movq %%mm6,%%mm0\n" + "psrlq $32, %%mm6\n" + "paddw %%mm6,%%mm0\n" + "movq %%mm0,%%mm6\n" + "psrlq $16, %%mm0\n" + "paddw %%mm6,%%mm0\n" + "movd %%mm0,%1\n" + : "+r" (pix), "=r"(tmp) + : "r" ((x86_reg)line_size) , "m" (h) + : "%ecx"); + return tmp & 0xFFFF; +} +#undef SUM + +static int vsad_intra16_mmxext(void *v, uint8_t *pix, uint8_t *dummy, + int line_size, int h) +{ + int tmp; + + av_assert2( (((int)pix) & 7) == 0); + av_assert2((line_size &7) ==0); + +#define SUM(in0, in1, out0, out1) \ + "movq (%0), " #out0 "\n"\ + "movq 8(%0), " #out1 "\n"\ + "add %2,%0\n"\ + "psadbw " #out0 ", " #in0 "\n"\ + "psadbw " #out1 ", " #in1 "\n"\ + "paddw " #in1 ", " #in0 "\n"\ + "paddw " #in0 ", %%mm6\n" + + __asm__ volatile ( + "movl %3,%%ecx\n" + "pxor %%mm6,%%mm6\n" + "pxor %%mm7,%%mm7\n" + "movq (%0),%%mm0\n" + "movq 8(%0),%%mm1\n" + "add %2,%0\n" + "jmp 2f\n" + "1:\n" + + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movd %%mm6,%1\n" + : "+r" (pix), "=r"(tmp) + : "r" ((x86_reg)line_size) , "m" (h) + : "%ecx"); + return tmp; +} +#undef SUM + +static int vsad16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) { + int tmp; + + av_assert2( (((int)pix1) & 7) == 0); + av_assert2( (((int)pix2) & 7) == 0); + av_assert2((line_size &7) ==0); + +#define SUM(in0, in1, out0, out1) \ + "movq (%0),%%mm2\n"\ + "movq (%1)," #out0 "\n"\ + "movq 8(%0),%%mm3\n"\ + "movq 8(%1)," #out1 "\n"\ + "add %3,%0\n"\ + "add %3,%1\n"\ + "psubb " #out0 ", %%mm2\n"\ + "psubb " #out1 ", %%mm3\n"\ + "pxor %%mm7, %%mm2\n"\ + "pxor %%mm7, %%mm3\n"\ + "movq %%mm2, " #out0 "\n"\ + "movq %%mm3, " #out1 "\n"\ + "psubusb " #in0 ", %%mm2\n"\ + "psubusb " #in1 ", %%mm3\n"\ + "psubusb " #out0 ", " #in0 "\n"\ + "psubusb " #out1 ", " #in1 "\n"\ + "por %%mm2, " #in0 "\n"\ + "por %%mm3, " #in1 "\n"\ + "movq " #in0 ", %%mm2\n"\ + "movq " #in1 ", %%mm3\n"\ + "punpcklbw %%mm7, " #in0 "\n"\ + "punpcklbw %%mm7, " #in1 "\n"\ + "punpckhbw %%mm7, %%mm2\n"\ + "punpckhbw %%mm7, %%mm3\n"\ + "paddw " #in1 ", " #in0 "\n"\ + "paddw %%mm3, %%mm2\n"\ + "paddw %%mm2, " #in0 "\n"\ + "paddw " #in0 ", %%mm6\n" + + + __asm__ volatile ( + "movl %4,%%ecx\n" + "pxor %%mm6,%%mm6\n" + "pcmpeqw %%mm7,%%mm7\n" + "psllw $15, %%mm7\n" + "packsswb %%mm7, %%mm7\n" + "movq (%0),%%mm0\n" + "movq (%1),%%mm2\n" + "movq 8(%0),%%mm1\n" + "movq 8(%1),%%mm3\n" + "add %3,%0\n" + "add %3,%1\n" + "psubb %%mm2, %%mm0\n" + "psubb %%mm3, %%mm1\n" + "pxor %%mm7, %%mm0\n" + "pxor %%mm7, %%mm1\n" + "jmp 2f\n" + "1:\n" + + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movq %%mm6,%%mm0\n" + "psrlq $32, %%mm6\n" + "paddw %%mm6,%%mm0\n" + "movq %%mm0,%%mm6\n" + "psrlq $16, %%mm0\n" + "paddw %%mm6,%%mm0\n" + "movd %%mm0,%2\n" + : "+r" (pix1), "+r" (pix2), "=r"(tmp) + : "r" ((x86_reg)line_size) , "m" (h) + : "%ecx"); + return tmp & 0x7FFF; +} +#undef SUM + +static int vsad16_mmxext(void *v, uint8_t *pix1, uint8_t *pix2, + int line_size, int h) +{ + int tmp; + + av_assert2( (((int)pix1) & 7) == 0); + av_assert2( (((int)pix2) & 7) == 0); + av_assert2((line_size &7) ==0); + +#define SUM(in0, in1, out0, out1) \ + "movq (%0)," #out0 "\n"\ + "movq (%1),%%mm2\n"\ + "movq 8(%0)," #out1 "\n"\ + "movq 8(%1),%%mm3\n"\ + "add %3,%0\n"\ + "add %3,%1\n"\ + "psubb %%mm2, " #out0 "\n"\ + "psubb %%mm3, " #out1 "\n"\ + "pxor %%mm7, " #out0 "\n"\ + "pxor %%mm7, " #out1 "\n"\ + "psadbw " #out0 ", " #in0 "\n"\ + "psadbw " #out1 ", " #in1 "\n"\ + "paddw " #in1 ", " #in0 "\n"\ + "paddw " #in0 ", %%mm6\n" + + __asm__ volatile ( + "movl %4,%%ecx\n" + "pxor %%mm6,%%mm6\n" + "pcmpeqw %%mm7,%%mm7\n" + "psllw $15, %%mm7\n" + "packsswb %%mm7, %%mm7\n" + "movq (%0),%%mm0\n" + "movq (%1),%%mm2\n" + "movq 8(%0),%%mm1\n" + "movq 8(%1),%%mm3\n" + "add %3,%0\n" + "add %3,%1\n" + "psubb %%mm2, %%mm0\n" + "psubb %%mm3, %%mm1\n" + "pxor %%mm7, %%mm0\n" + "pxor %%mm7, %%mm1\n" + "jmp 2f\n" + "1:\n" + + SUM(%%mm4, %%mm5, %%mm0, %%mm1) + "2:\n" + SUM(%%mm0, %%mm1, %%mm4, %%mm5) + + "subl $2, %%ecx\n" + "jnz 1b\n" + + "movd %%mm6,%2\n" + : "+r" (pix1), "+r" (pix2), "=r"(tmp) + : "r" ((x86_reg)line_size) , "m" (h) + : "%ecx"); + return tmp; +} +#undef SUM + +static void diff_bytes_mmx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w){ + x86_reg i=0; + if(w>=16) + __asm__ volatile( + "1: \n\t" + "movq (%2, %0), %%mm0 \n\t" + "movq (%1, %0), %%mm1 \n\t" + "psubb %%mm0, %%mm1 \n\t" + "movq %%mm1, (%3, %0) \n\t" + "movq 8(%2, %0), %%mm0 \n\t" + "movq 8(%1, %0), %%mm1 \n\t" + "psubb %%mm0, %%mm1 \n\t" + "movq %%mm1, 8(%3, %0) \n\t" + "add $16, %0 \n\t" + "cmp %4, %0 \n\t" + " jb 1b \n\t" + : "+r" (i) + : "r"(src1), "r"(src2), "r"(dst), "r"((x86_reg)w-15) + ); + for(; ibits_per_raw_sample; + +#if HAVE_YASM + if (EXTERNAL_MMX(mm_flags)) { + if (bit_depth <= 8) + c->get_pixels = ff_get_pixels_mmx; + c->diff_pixels = ff_diff_pixels_mmx; + c->pix_sum = ff_pix_sum16_mmx; + + c->pix_norm1 = ff_pix_norm1_mmx; + } + if (EXTERNAL_SSE2(mm_flags)) + if (bit_depth <= 8) + c->get_pixels = ff_get_pixels_sse2; +#endif /* HAVE_YASM */ + +#if HAVE_INLINE_ASM + if (mm_flags & AV_CPU_FLAG_MMX) { + const int dct_algo = avctx->dct_algo; + if (avctx->bits_per_raw_sample <= 8 && + (dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX)) { + if(mm_flags & AV_CPU_FLAG_SSE2){ + c->fdct = ff_fdct_sse2; + } else if (mm_flags & AV_CPU_FLAG_MMXEXT) { + c->fdct = ff_fdct_mmxext; + }else{ + c->fdct = ff_fdct_mmx; + } + } + + + c->diff_bytes= diff_bytes_mmx; + c->sum_abs_dctelem= sum_abs_dctelem_mmx; + + c->sse[0] = sse16_mmx; + c->sse[1] = sse8_mmx; + c->vsad[4]= vsad_intra16_mmx; + + c->nsse[0] = nsse16_mmx; + c->nsse[1] = nsse8_mmx; + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->vsad[0] = vsad16_mmx; + } + + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->try_8x8basis= try_8x8basis_mmx; + } + c->add_8x8basis= add_8x8basis_mmx; + + c->ssd_int8_vs_int16 = ssd_int8_vs_int16_mmx; + + if (mm_flags & AV_CPU_FLAG_MMXEXT) { + c->sum_abs_dctelem = sum_abs_dctelem_mmxext; + c->vsad[4] = vsad_intra16_mmxext; + + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->vsad[0] = vsad16_mmxext; + } + + c->sub_hfyu_median_prediction = sub_hfyu_median_prediction_mmxext; + } + + if(mm_flags & AV_CPU_FLAG_SSE2){ + c->sum_abs_dctelem= sum_abs_dctelem_sse2; + } + +#if HAVE_SSSE3_INLINE + if(mm_flags & AV_CPU_FLAG_SSSE3){ + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->try_8x8basis= try_8x8basis_ssse3; + } + c->add_8x8basis= add_8x8basis_ssse3; + c->sum_abs_dctelem= sum_abs_dctelem_ssse3; + } +#endif + + if(mm_flags & AV_CPU_FLAG_3DNOW){ + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->try_8x8basis= try_8x8basis_3dnow; + } + c->add_8x8basis= add_8x8basis_3dnow; + } + } +#endif /* HAVE_INLINE_ASM */ + + if (EXTERNAL_MMX(mm_flags)) { + c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx; + c->hadamard8_diff[1] = ff_hadamard8_diff_mmx; + + if (EXTERNAL_MMXEXT(mm_flags)) { + c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext; + c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext; + } + + if (EXTERNAL_SSE2(mm_flags)) { + c->sse[0] = ff_sse16_sse2; + +#if HAVE_ALIGNED_STACK + c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2; + c->hadamard8_diff[1] = ff_hadamard8_diff_sse2; +#endif + } + + if (EXTERNAL_SSSE3(mm_flags) && HAVE_ALIGNED_STACK) { + c->hadamard8_diff[0] = ff_hadamard8_diff16_ssse3; + c->hadamard8_diff[1] = ff_hadamard8_diff_ssse3; + } + } + + ff_dsputil_init_pix_mmx(c, avctx); +} diff --git a/ffmpeg/libavcodec/x86/dwt_yasm.asm b/ffmpeg/libavcodec/x86/dwt_yasm.asm new file mode 100644 index 0000000..5253abc --- /dev/null +++ b/ffmpeg/libavcodec/x86/dwt_yasm.asm @@ -0,0 +1,306 @@ +;****************************************************************************** +;* MMX optimized discrete wavelet trasnform +;* Copyright (c) 2010 David Conrad +;* +;* 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 +;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pw_1: times 8 dw 1 +pw_2: times 8 dw 2 +pw_8: times 8 dw 8 +pw_16: times 8 dw 16 +pw_1991: times 4 dw 9,-1 + +section .text + +; %1 -= (%2 + %3 + 2)>>2 %4 is pw_2 +%macro COMPOSE_53iL0 4 + paddw %2, %3 + paddw %2, %4 + psraw %2, 2 + psubw %1, %2 +%endm + +; m1 = %1 + (-m0 + 9*m1 + 9*%2 -%3 + 8)>>4 +; if %4 is supplied, %1 is loaded unaligned from there +; m2: clobbered m3: pw_8 m4: pw_1991 +%macro COMPOSE_DD97iH0 3-4 + paddw m0, %3 + paddw m1, %2 + psubw m0, m3 + mova m2, m1 + punpcklwd m1, m0 + punpckhwd m2, m0 + pmaddwd m1, m4 + pmaddwd m2, m4 +%if %0 > 3 + movu %1, %4 +%endif + psrad m1, 4 + psrad m2, 4 + packssdw m1, m2 + paddw m1, %1 +%endm + +%macro COMPOSE_VERTICAL 1 +; void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, +; int width) +cglobal vertical_compose53iL0_%1, 4,4,1, b0, b1, b2, width + mova m2, [pw_2] +%if ARCH_X86_64 + mov widthd, widthd +%endif +.loop: + sub widthq, mmsize/2 + mova m1, [b0q+2*widthq] + mova m0, [b1q+2*widthq] + COMPOSE_53iL0 m0, m1, [b2q+2*widthq], m2 + mova [b1q+2*widthq], m0 + jg .loop + REP_RET + +; void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, +; int width) +cglobal vertical_compose_dirac53iH0_%1, 4,4,1, b0, b1, b2, width + mova m1, [pw_1] +%if ARCH_X86_64 + mov widthd, widthd +%endif +.loop: + sub widthq, mmsize/2 + mova m0, [b0q+2*widthq] + paddw m0, [b2q+2*widthq] + paddw m0, m1 + psraw m0, 1 + paddw m0, [b1q+2*widthq] + mova [b1q+2*widthq], m0 + jg .loop + REP_RET + +; void vertical_compose_dd97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, +; IDWTELEM *b3, IDWTELEM *b4, int width) +cglobal vertical_compose_dd97iH0_%1, 6,6,5, b0, b1, b2, b3, b4, width + mova m3, [pw_8] + mova m4, [pw_1991] +%if ARCH_X86_64 + mov widthd, widthd +%endif +.loop: + sub widthq, mmsize/2 + mova m0, [b0q+2*widthq] + mova m1, [b1q+2*widthq] + COMPOSE_DD97iH0 [b2q+2*widthq], [b3q+2*widthq], [b4q+2*widthq] + mova [b2q+2*widthq], m1 + jg .loop + REP_RET + +; void vertical_compose_dd137iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, +; IDWTELEM *b3, IDWTELEM *b4, int width) +cglobal vertical_compose_dd137iL0_%1, 6,6,6, b0, b1, b2, b3, b4, width + mova m3, [pw_16] + mova m4, [pw_1991] +%if ARCH_X86_64 + mov widthd, widthd +%endif +.loop: + sub widthq, mmsize/2 + mova m0, [b0q+2*widthq] + mova m1, [b1q+2*widthq] + mova m5, [b2q+2*widthq] + paddw m0, [b4q+2*widthq] + paddw m1, [b3q+2*widthq] + psubw m0, m3 + mova m2, m1 + punpcklwd m1, m0 + punpckhwd m2, m0 + pmaddwd m1, m4 + pmaddwd m2, m4 + psrad m1, 5 + psrad m2, 5 + packssdw m1, m2 + psubw m5, m1 + mova [b2q+2*widthq], m5 + jg .loop + REP_RET + +; void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width) +cglobal vertical_compose_haar_%1, 3,4,3, b0, b1, width + mova m3, [pw_1] +%if ARCH_X86_64 + mov widthd, widthd +%endif +.loop: + sub widthq, mmsize/2 + mova m1, [b1q+2*widthq] + mova m0, [b0q+2*widthq] + mova m2, m1 + paddw m1, m3 + psraw m1, 1 + psubw m0, m1 + mova [b0q+2*widthq], m0 + paddw m2, m0 + mova [b1q+2*widthq], m2 + jg .loop + REP_RET +%endmacro + +; extend the left and right edges of the tmp array by %1 and %2 respectively +%macro EDGE_EXTENSION 3 + mov %3, [tmpq] +%assign %%i 1 +%rep %1 + mov [tmpq-2*%%i], %3 + %assign %%i %%i+1 +%endrep + mov %3, [tmpq+2*w2q-2] +%assign %%i 0 +%rep %2 + mov [tmpq+2*w2q+2*%%i], %3 + %assign %%i %%i+1 +%endrep +%endmacro + + +%macro HAAR_HORIZONTAL 2 +; void horizontal_compose_haari(IDWTELEM *b, IDWTELEM *tmp, int width) +cglobal horizontal_compose_haar%2i_%1, 3,6,4, b, tmp, w, x, w2, b_w2 + mov w2d, wd + xor xq, xq + shr w2d, 1 + lea b_w2q, [bq+wq] + mova m3, [pw_1] +.lowpass_loop: + movu m1, [b_w2q + 2*xq] + mova m0, [bq + 2*xq] + paddw m1, m3 + psraw m1, 1 + psubw m0, m1 + mova [tmpq + 2*xq], m0 + add xq, mmsize/2 + cmp xq, w2q + jl .lowpass_loop + + xor xq, xq + and w2q, ~(mmsize/2 - 1) + cmp w2q, mmsize/2 + jl .end + +.highpass_loop: + movu m1, [b_w2q + 2*xq] + mova m0, [tmpq + 2*xq] + paddw m1, m0 + + ; shift and interleave +%if %2 == 1 + paddw m0, m3 + paddw m1, m3 + psraw m0, 1 + psraw m1, 1 +%endif + mova m2, m0 + punpcklwd m0, m1 + punpckhwd m2, m1 + mova [bq+4*xq], m0 + mova [bq+4*xq+mmsize], m2 + + add xq, mmsize/2 + cmp xq, w2q + jl .highpass_loop +.end: + REP_RET +%endmacro + + +INIT_XMM +; void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int width) +cglobal horizontal_compose_dd97i_ssse3, 3,6,8, b, tmp, w, x, w2, b_w2 + mov w2d, wd + xor xd, xd + shr w2d, 1 + lea b_w2q, [bq+wq] + movu m4, [bq+wq] + mova m7, [pw_2] + pslldq m4, 14 +.lowpass_loop: + movu m1, [b_w2q + 2*xq] + mova m0, [bq + 2*xq] + mova m2, m1 + palignr m1, m4, 14 + mova m4, m2 + COMPOSE_53iL0 m0, m1, m2, m7 + mova [tmpq + 2*xq], m0 + add xd, mmsize/2 + cmp xd, w2d + jl .lowpass_loop + + EDGE_EXTENSION 1, 2, xw + ; leave the last up to 7 (sse) or 3 (mmx) values for C + xor xd, xd + and w2d, ~(mmsize/2 - 1) + cmp w2d, mmsize/2 + jl .end + + mova m7, [tmpq-mmsize] + mova m0, [tmpq] + mova m5, [pw_1] + mova m3, [pw_8] + mova m4, [pw_1991] +.highpass_loop: + mova m6, m0 + palignr m0, m7, 14 + mova m7, [tmpq + 2*xq + 16] + mova m1, m7 + mova m2, m7 + palignr m1, m6, 2 + palignr m2, m6, 4 + COMPOSE_DD97iH0 m0, m6, m2, [b_w2q + 2*xq] + mova m0, m7 + mova m7, m6 + + ; shift and interleave + paddw m6, m5 + paddw m1, m5 + psraw m6, 1 + psraw m1, 1 + mova m2, m6 + punpcklwd m6, m1 + punpckhwd m2, m1 + mova [bq+4*xq], m6 + mova [bq+4*xq+mmsize], m2 + + add xd, mmsize/2 + cmp xd, w2d + jl .highpass_loop +.end: + REP_RET + + +%if ARCH_X86_64 == 0 +INIT_MMX +COMPOSE_VERTICAL mmx +HAAR_HORIZONTAL mmx, 0 +HAAR_HORIZONTAL mmx, 1 +%endif + +;;INIT_XMM +INIT_XMM +COMPOSE_VERTICAL sse2 +HAAR_HORIZONTAL sse2, 0 +HAAR_HORIZONTAL sse2, 1 diff --git a/ffmpeg/libavcodec/x86/fdct.c b/ffmpeg/libavcodec/x86/fdct.c new file mode 100644 index 0000000..d35245d --- /dev/null +++ b/ffmpeg/libavcodec/x86/fdct.c @@ -0,0 +1,586 @@ +/* + * MMX optimized forward DCT + * The gcc porting is Copyright (c) 2001 Fabrice Bellard. + * cleanup/optimizations are Copyright (c) 2002-2004 Michael Niedermayer + * SSE2 optimization is Copyright (c) 2004 Denes Balatoni. + * + * from fdctam32.c - AP922 MMX(3D-Now) forward-DCT + * + * Intel Application Note AP-922 - fast, precise implementation of DCT + * http://developer.intel.com/vtune/cbts/appnotes.htm + * + * Also of inspiration: + * a page about fdct at http://www.geocities.com/ssavekar/dct.htm + * Skal's fdct at http://skal.planet-d.net/coding/dct.html + * + * 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 "libavutil/common.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/dct.h" + +#if HAVE_INLINE_ASM + +////////////////////////////////////////////////////////////////////// +// +// constants for the forward DCT +// ----------------------------- +// +// Be sure to check that your compiler is aligning all constants to QWORD +// (8-byte) memory boundaries! Otherwise the unaligned memory access will +// severely stall MMX execution. +// +////////////////////////////////////////////////////////////////////// + +#define BITS_FRW_ACC 3 //; 2 or 3 for accuracy +#define SHIFT_FRW_COL BITS_FRW_ACC +#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17 - 3) +#define RND_FRW_ROW (1 << (SHIFT_FRW_ROW-1)) +//#define RND_FRW_COL (1 << (SHIFT_FRW_COL-1)) + +#define X8(x) x,x,x,x,x,x,x,x + +//concatenated table, for forward DCT transformation +DECLARE_ALIGNED(16, static const int16_t, fdct_tg_all_16)[24] = { + X8(13036), // tg * (2<<16) + 0.5 + X8(27146), // tg * (2<<16) + 0.5 + X8(-21746) // tg * (2<<16) + 0.5 +}; + +DECLARE_ALIGNED(16, static const int16_t, ocos_4_16)[8] = { + X8(23170) //cos * (2<<15) + 0.5 +}; + +DECLARE_ALIGNED(16, static const int16_t, fdct_one_corr)[8] = { X8(1) }; + +DECLARE_ALIGNED(8, static const int32_t, fdct_r_row)[2] = {RND_FRW_ROW, RND_FRW_ROW }; + +static const struct +{ + DECLARE_ALIGNED(16, const int32_t, fdct_r_row_sse2)[4]; +} fdct_r_row_sse2 = +{{ + RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW +}}; +//DECLARE_ALIGNED(16, static const long, fdct_r_row_sse2)[4] = {RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW}; + +DECLARE_ALIGNED(8, static const int16_t, tab_frw_01234567)[] = { // forward_dct coeff table + 16384, 16384, 22725, 19266, + 16384, 16384, 12873, 4520, + 21407, 8867, 19266, -4520, + -8867, -21407, -22725, -12873, + 16384, -16384, 12873, -22725, + -16384, 16384, 4520, 19266, + 8867, -21407, 4520, -12873, + 21407, -8867, 19266, -22725, + + 22725, 22725, 31521, 26722, + 22725, 22725, 17855, 6270, + 29692, 12299, 26722, -6270, + -12299, -29692, -31521, -17855, + 22725, -22725, 17855, -31521, + -22725, 22725, 6270, 26722, + 12299, -29692, 6270, -17855, + 29692, -12299, 26722, -31521, + + 21407, 21407, 29692, 25172, + 21407, 21407, 16819, 5906, + 27969, 11585, 25172, -5906, + -11585, -27969, -29692, -16819, + 21407, -21407, 16819, -29692, + -21407, 21407, 5906, 25172, + 11585, -27969, 5906, -16819, + 27969, -11585, 25172, -29692, + + 19266, 19266, 26722, 22654, + 19266, 19266, 15137, 5315, + 25172, 10426, 22654, -5315, + -10426, -25172, -26722, -15137, + 19266, -19266, 15137, -26722, + -19266, 19266, 5315, 22654, + 10426, -25172, 5315, -15137, + 25172, -10426, 22654, -26722, + + 16384, 16384, 22725, 19266, + 16384, 16384, 12873, 4520, + 21407, 8867, 19266, -4520, + -8867, -21407, -22725, -12873, + 16384, -16384, 12873, -22725, + -16384, 16384, 4520, 19266, + 8867, -21407, 4520, -12873, + 21407, -8867, 19266, -22725, + + 19266, 19266, 26722, 22654, + 19266, 19266, 15137, 5315, + 25172, 10426, 22654, -5315, + -10426, -25172, -26722, -15137, + 19266, -19266, 15137, -26722, + -19266, 19266, 5315, 22654, + 10426, -25172, 5315, -15137, + 25172, -10426, 22654, -26722, + + 21407, 21407, 29692, 25172, + 21407, 21407, 16819, 5906, + 27969, 11585, 25172, -5906, + -11585, -27969, -29692, -16819, + 21407, -21407, 16819, -29692, + -21407, 21407, 5906, 25172, + 11585, -27969, 5906, -16819, + 27969, -11585, 25172, -29692, + + 22725, 22725, 31521, 26722, + 22725, 22725, 17855, 6270, + 29692, 12299, 26722, -6270, + -12299, -29692, -31521, -17855, + 22725, -22725, 17855, -31521, + -22725, 22725, 6270, 26722, + 12299, -29692, 6270, -17855, + 29692, -12299, 26722, -31521, +}; + +static const struct +{ + DECLARE_ALIGNED(16, const int16_t, tab_frw_01234567_sse2)[256]; +} tab_frw_01234567_sse2 = +{{ +//DECLARE_ALIGNED(16, static const int16_t, tab_frw_01234567_sse2)[] = { // forward_dct coeff table +#define TABLE_SSE2 C4, C4, C1, C3, -C6, -C2, -C1, -C5, \ + C4, C4, C5, C7, C2, C6, C3, -C7, \ + -C4, C4, C7, C3, C6, -C2, C7, -C5, \ + C4, -C4, C5, -C1, C2, -C6, C3, -C1, +// c1..c7 * cos(pi/4) * 2^15 +#define C1 22725 +#define C2 21407 +#define C3 19266 +#define C4 16384 +#define C5 12873 +#define C6 8867 +#define C7 4520 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 31521 +#define C2 29692 +#define C3 26722 +#define C4 22725 +#define C5 17855 +#define C6 12299 +#define C7 6270 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 29692 +#define C2 27969 +#define C3 25172 +#define C4 21407 +#define C5 16819 +#define C6 11585 +#define C7 5906 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 26722 +#define C2 25172 +#define C3 22654 +#define C4 19266 +#define C5 15137 +#define C6 10426 +#define C7 5315 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 22725 +#define C2 21407 +#define C3 19266 +#define C4 16384 +#define C5 12873 +#define C6 8867 +#define C7 4520 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 26722 +#define C2 25172 +#define C3 22654 +#define C4 19266 +#define C5 15137 +#define C6 10426 +#define C7 5315 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 29692 +#define C2 27969 +#define C3 25172 +#define C4 21407 +#define C5 16819 +#define C6 11585 +#define C7 5906 +TABLE_SSE2 + +#undef C1 +#undef C2 +#undef C3 +#undef C4 +#undef C5 +#undef C6 +#undef C7 +#define C1 31521 +#define C2 29692 +#define C3 26722 +#define C4 22725 +#define C5 17855 +#define C6 12299 +#define C7 6270 +TABLE_SSE2 +}}; + +#define S(s) AV_TOSTRING(s) //AV_STRINGIFY is too long + +#define FDCT_COL(cpu, mm, mov)\ +static av_always_inline void fdct_col_##cpu(const int16_t *in, int16_t *out, int offset)\ +{\ + __asm__ volatile (\ + #mov" 16(%0), %%"#mm"0 \n\t" \ + #mov" 96(%0), %%"#mm"1 \n\t" \ + #mov" %%"#mm"0, %%"#mm"2 \n\t" \ + #mov" 32(%0), %%"#mm"3 \n\t" \ + "paddsw %%"#mm"1, %%"#mm"0 \n\t" \ + #mov" 80(%0), %%"#mm"4 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)", %%"#mm"0 \n\t" \ + #mov" (%0), %%"#mm"5 \n\t" \ + "paddsw %%"#mm"3, %%"#mm"4 \n\t" \ + "paddsw 112(%0), %%"#mm"5 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)", %%"#mm"4 \n\t" \ + #mov" %%"#mm"0, %%"#mm"6 \n\t" \ + "psubsw %%"#mm"1, %%"#mm"2 \n\t" \ + #mov" 16(%1), %%"#mm"1 \n\t" \ + "psubsw %%"#mm"4, %%"#mm"0 \n\t" \ + #mov" 48(%0), %%"#mm"7 \n\t" \ + "pmulhw %%"#mm"0, %%"#mm"1 \n\t" \ + "paddsw 64(%0), %%"#mm"7 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)", %%"#mm"5 \n\t" \ + "paddsw %%"#mm"4, %%"#mm"6 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)", %%"#mm"7 \n\t" \ + #mov" %%"#mm"5, %%"#mm"4 \n\t" \ + "psubsw %%"#mm"7, %%"#mm"5 \n\t" \ + "paddsw %%"#mm"5, %%"#mm"1 \n\t" \ + "paddsw %%"#mm"7, %%"#mm"4 \n\t" \ + "por (%2), %%"#mm"1 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)"+1, %%"#mm"2 \n\t" \ + "pmulhw 16(%1), %%"#mm"5 \n\t" \ + #mov" %%"#mm"4, %%"#mm"7 \n\t" \ + "psubsw 80(%0), %%"#mm"3 \n\t" \ + "psubsw %%"#mm"6, %%"#mm"4 \n\t" \ + #mov" %%"#mm"1, 32(%3) \n\t" \ + "paddsw %%"#mm"6, %%"#mm"7 \n\t" \ + #mov" 48(%0), %%"#mm"1 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)"+1, %%"#mm"3 \n\t" \ + "psubsw 64(%0), %%"#mm"1 \n\t" \ + #mov" %%"#mm"2, %%"#mm"6 \n\t" \ + #mov" %%"#mm"4, 64(%3) \n\t" \ + "paddsw %%"#mm"3, %%"#mm"2 \n\t" \ + "pmulhw (%4), %%"#mm"2 \n\t" \ + "psubsw %%"#mm"3, %%"#mm"6 \n\t" \ + "pmulhw (%4), %%"#mm"6 \n\t" \ + "psubsw %%"#mm"0, %%"#mm"5 \n\t" \ + "por (%2), %%"#mm"5 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)", %%"#mm"1 \n\t" \ + "por (%2), %%"#mm"2 \n\t" \ + #mov" %%"#mm"1, %%"#mm"4 \n\t" \ + #mov" (%0), %%"#mm"3 \n\t" \ + "paddsw %%"#mm"6, %%"#mm"1 \n\t" \ + "psubsw 112(%0), %%"#mm"3 \n\t" \ + "psubsw %%"#mm"6, %%"#mm"4 \n\t" \ + #mov" (%1), %%"#mm"0 \n\t" \ + "psllw $"S(SHIFT_FRW_COL)", %%"#mm"3 \n\t" \ + #mov" 32(%1), %%"#mm"6 \n\t" \ + "pmulhw %%"#mm"1, %%"#mm"0 \n\t" \ + #mov" %%"#mm"7, (%3) \n\t" \ + "pmulhw %%"#mm"4, %%"#mm"6 \n\t" \ + #mov" %%"#mm"5, 96(%3) \n\t" \ + #mov" %%"#mm"3, %%"#mm"7 \n\t" \ + #mov" 32(%1), %%"#mm"5 \n\t" \ + "psubsw %%"#mm"2, %%"#mm"7 \n\t" \ + "paddsw %%"#mm"2, %%"#mm"3 \n\t" \ + "pmulhw %%"#mm"7, %%"#mm"5 \n\t" \ + "paddsw %%"#mm"3, %%"#mm"0 \n\t" \ + "paddsw %%"#mm"4, %%"#mm"6 \n\t" \ + "pmulhw (%1), %%"#mm"3 \n\t" \ + "por (%2), %%"#mm"0 \n\t" \ + "paddsw %%"#mm"7, %%"#mm"5 \n\t" \ + "psubsw %%"#mm"6, %%"#mm"7 \n\t" \ + #mov" %%"#mm"0, 16(%3) \n\t" \ + "paddsw %%"#mm"4, %%"#mm"5 \n\t" \ + #mov" %%"#mm"7, 48(%3) \n\t" \ + "psubsw %%"#mm"1, %%"#mm"3 \n\t" \ + #mov" %%"#mm"5, 80(%3) \n\t" \ + #mov" %%"#mm"3, 112(%3) \n\t" \ + : \ + : "r" (in + offset), "r" (fdct_tg_all_16), "r" (fdct_one_corr), \ + "r" (out + offset), "r" (ocos_4_16)); \ +} + +FDCT_COL(mmx, mm, movq) +FDCT_COL(sse2, xmm, movdqa) + +static av_always_inline void fdct_row_sse2(const int16_t *in, int16_t *out) +{ + __asm__ volatile( +#define FDCT_ROW_SSE2_H1(i,t) \ + "movq " #i "(%0), %%xmm2 \n\t" \ + "movq " #i "+8(%0), %%xmm0 \n\t" \ + "movdqa " #t "+32(%1), %%xmm3 \n\t" \ + "movdqa " #t "+48(%1), %%xmm7 \n\t" \ + "movdqa " #t "(%1), %%xmm4 \n\t" \ + "movdqa " #t "+16(%1), %%xmm5 \n\t" + +#define FDCT_ROW_SSE2_H2(i,t) \ + "movq " #i "(%0), %%xmm2 \n\t" \ + "movq " #i "+8(%0), %%xmm0 \n\t" \ + "movdqa " #t "+32(%1), %%xmm3 \n\t" \ + "movdqa " #t "+48(%1), %%xmm7 \n\t" + +#define FDCT_ROW_SSE2(i) \ + "movq %%xmm2, %%xmm1 \n\t" \ + "pshuflw $27, %%xmm0, %%xmm0 \n\t" \ + "paddsw %%xmm0, %%xmm1 \n\t" \ + "psubsw %%xmm0, %%xmm2 \n\t" \ + "punpckldq %%xmm2, %%xmm1 \n\t" \ + "pshufd $78, %%xmm1, %%xmm2 \n\t" \ + "pmaddwd %%xmm2, %%xmm3 \n\t" \ + "pmaddwd %%xmm1, %%xmm7 \n\t" \ + "pmaddwd %%xmm5, %%xmm2 \n\t" \ + "pmaddwd %%xmm4, %%xmm1 \n\t" \ + "paddd %%xmm7, %%xmm3 \n\t" \ + "paddd %%xmm2, %%xmm1 \n\t" \ + "paddd %%xmm6, %%xmm3 \n\t" \ + "paddd %%xmm6, %%xmm1 \n\t" \ + "psrad %3, %%xmm3 \n\t" \ + "psrad %3, %%xmm1 \n\t" \ + "packssdw %%xmm3, %%xmm1 \n\t" \ + "movdqa %%xmm1, " #i "(%4) \n\t" + + "movdqa (%2), %%xmm6 \n\t" + FDCT_ROW_SSE2_H1(0,0) + FDCT_ROW_SSE2(0) + FDCT_ROW_SSE2_H2(64,0) + FDCT_ROW_SSE2(64) + + FDCT_ROW_SSE2_H1(16,64) + FDCT_ROW_SSE2(16) + FDCT_ROW_SSE2_H2(112,64) + FDCT_ROW_SSE2(112) + + FDCT_ROW_SSE2_H1(32,128) + FDCT_ROW_SSE2(32) + FDCT_ROW_SSE2_H2(96,128) + FDCT_ROW_SSE2(96) + + FDCT_ROW_SSE2_H1(48,192) + FDCT_ROW_SSE2(48) + FDCT_ROW_SSE2_H2(80,192) + FDCT_ROW_SSE2(80) + : + : "r" (in), "r" (tab_frw_01234567_sse2.tab_frw_01234567_sse2), + "r" (fdct_r_row_sse2.fdct_r_row_sse2), "i" (SHIFT_FRW_ROW), "r" (out) + XMM_CLOBBERS_ONLY("%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm4", "%xmm5", "%xmm6", "%xmm7") + ); +} + +static av_always_inline void fdct_row_mmxext(const int16_t *in, int16_t *out, + const int16_t *table) +{ + __asm__ volatile ( + "pshufw $0x1B, 8(%0), %%mm5 \n\t" + "movq (%0), %%mm0 \n\t" + "movq %%mm0, %%mm1 \n\t" + "paddsw %%mm5, %%mm0 \n\t" + "psubsw %%mm5, %%mm1 \n\t" + "movq %%mm0, %%mm2 \n\t" + "punpckldq %%mm1, %%mm0 \n\t" + "punpckhdq %%mm1, %%mm2 \n\t" + "movq (%1), %%mm1 \n\t" + "movq 8(%1), %%mm3 \n\t" + "movq 16(%1), %%mm4 \n\t" + "movq 24(%1), %%mm5 \n\t" + "movq 32(%1), %%mm6 \n\t" + "movq 40(%1), %%mm7 \n\t" + "pmaddwd %%mm0, %%mm1 \n\t" + "pmaddwd %%mm2, %%mm3 \n\t" + "pmaddwd %%mm0, %%mm4 \n\t" + "pmaddwd %%mm2, %%mm5 \n\t" + "pmaddwd %%mm0, %%mm6 \n\t" + "pmaddwd %%mm2, %%mm7 \n\t" + "pmaddwd 48(%1), %%mm0 \n\t" + "pmaddwd 56(%1), %%mm2 \n\t" + "paddd %%mm1, %%mm3 \n\t" + "paddd %%mm4, %%mm5 \n\t" + "paddd %%mm6, %%mm7 \n\t" + "paddd %%mm0, %%mm2 \n\t" + "movq (%2), %%mm0 \n\t" + "paddd %%mm0, %%mm3 \n\t" + "paddd %%mm0, %%mm5 \n\t" + "paddd %%mm0, %%mm7 \n\t" + "paddd %%mm0, %%mm2 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm3 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm5 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm7 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm2 \n\t" + "packssdw %%mm5, %%mm3 \n\t" + "packssdw %%mm2, %%mm7 \n\t" + "movq %%mm3, (%3) \n\t" + "movq %%mm7, 8(%3) \n\t" + : + : "r" (in), "r" (table), "r" (fdct_r_row), "r" (out)); +} + +static av_always_inline void fdct_row_mmx(const int16_t *in, int16_t *out, const int16_t *table) +{ + //FIXME reorder (I do not have an old MMX-only CPU here to benchmark ...) + __asm__ volatile( + "movd 12(%0), %%mm1 \n\t" + "punpcklwd 8(%0), %%mm1 \n\t" + "movq %%mm1, %%mm2 \n\t" + "psrlq $0x20, %%mm1 \n\t" + "movq 0(%0), %%mm0 \n\t" + "punpcklwd %%mm2, %%mm1 \n\t" + "movq %%mm0, %%mm5 \n\t" + "paddsw %%mm1, %%mm0 \n\t" + "psubsw %%mm1, %%mm5 \n\t" + "movq %%mm0, %%mm2 \n\t" + "punpckldq %%mm5, %%mm0 \n\t" + "punpckhdq %%mm5, %%mm2 \n\t" + "movq 0(%1), %%mm1 \n\t" + "movq 8(%1), %%mm3 \n\t" + "movq 16(%1), %%mm4 \n\t" + "movq 24(%1), %%mm5 \n\t" + "movq 32(%1), %%mm6 \n\t" + "movq 40(%1), %%mm7 \n\t" + "pmaddwd %%mm0, %%mm1 \n\t" + "pmaddwd %%mm2, %%mm3 \n\t" + "pmaddwd %%mm0, %%mm4 \n\t" + "pmaddwd %%mm2, %%mm5 \n\t" + "pmaddwd %%mm0, %%mm6 \n\t" + "pmaddwd %%mm2, %%mm7 \n\t" + "pmaddwd 48(%1), %%mm0 \n\t" + "pmaddwd 56(%1), %%mm2 \n\t" + "paddd %%mm1, %%mm3 \n\t" + "paddd %%mm4, %%mm5 \n\t" + "paddd %%mm6, %%mm7 \n\t" + "paddd %%mm0, %%mm2 \n\t" + "movq (%2), %%mm0 \n\t" + "paddd %%mm0, %%mm3 \n\t" + "paddd %%mm0, %%mm5 \n\t" + "paddd %%mm0, %%mm7 \n\t" + "paddd %%mm0, %%mm2 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm3 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm5 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm7 \n\t" + "psrad $"S(SHIFT_FRW_ROW)", %%mm2 \n\t" + "packssdw %%mm5, %%mm3 \n\t" + "packssdw %%mm2, %%mm7 \n\t" + "movq %%mm3, 0(%3) \n\t" + "movq %%mm7, 8(%3) \n\t" + : + : "r" (in), "r" (table), "r" (fdct_r_row), "r" (out)); +} + +void ff_fdct_mmx(int16_t *block) +{ + DECLARE_ALIGNED(8, int64_t, align_tmp)[16]; + int16_t * block1= (int16_t*)align_tmp; + const int16_t *table= tab_frw_01234567; + int i; + + fdct_col_mmx(block, block1, 0); + fdct_col_mmx(block, block1, 4); + + for(i=8;i>0;i--) { + fdct_row_mmx(block1, block, table); + block1 += 8; + table += 32; + block += 8; + } +} + +void ff_fdct_mmxext(int16_t *block) +{ + DECLARE_ALIGNED(8, int64_t, align_tmp)[16]; + int16_t *block1= (int16_t*)align_tmp; + const int16_t *table= tab_frw_01234567; + int i; + + fdct_col_mmx(block, block1, 0); + fdct_col_mmx(block, block1, 4); + + for(i=8;i>0;i--) { + fdct_row_mmxext(block1, block, table); + block1 += 8; + table += 32; + block += 8; + } +} + +void ff_fdct_sse2(int16_t *block) +{ + DECLARE_ALIGNED(16, int64_t, align_tmp)[16]; + int16_t * const block1= (int16_t*)align_tmp; + + fdct_col_sse2(block, block1, 0); + fdct_row_sse2(block1, block); +} + +#endif /* HAVE_INLINE_ASM */ diff --git a/ffmpeg/libavcodec/x86/fft.asm b/ffmpeg/libavcodec/x86/fft.asm new file mode 100644 index 0000000..5071741 --- /dev/null +++ b/ffmpeg/libavcodec/x86/fft.asm @@ -0,0 +1,1093 @@ +;****************************************************************************** +;* FFT transform with SSE/3DNow optimizations +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2011 Vitor Sessak +;* +;* This algorithm (though not any of the implementation details) is +;* based on libdjbfft by D. J. Bernstein. +;* +;* 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 +;****************************************************************************** + +; These functions are not individually interchangeable with the C versions. +; While C takes arrays of FFTComplex, SSE/3DNow leave intermediate results +; in blocks as conventient to the vector size. +; i.e. {4x real, 4x imaginary, 4x real, ...} (or 2x respectively) + +%include "libavutil/x86/x86util.asm" + +%if ARCH_X86_64 +%define pointer resq +%else +%define pointer resd +%endif + +SECTION_RODATA + +struc FFTContext + .nbits: resd 1 + .reverse: resd 1 + .revtab: pointer 1 + .tmpbuf: pointer 1 + .mdctsize: resd 1 + .mdctbits: resd 1 + .tcos: pointer 1 + .tsin: pointer 1 + .fftperm: pointer 1 + .fftcalc: pointer 1 + .imdctcalc:pointer 1 + .imdcthalf:pointer 1 +endstruc + +%define M_SQRT1_2 0.70710678118654752440 +%define M_COS_PI_1_8 0.923879532511287 +%define M_COS_PI_3_8 0.38268343236509 + +align 32 +ps_cos16_1: dd 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8, 1.0, M_COS_PI_1_8, M_SQRT1_2, M_COS_PI_3_8 +ps_cos16_2: dd 0, M_COS_PI_3_8, M_SQRT1_2, M_COS_PI_1_8, 0, -M_COS_PI_3_8, -M_SQRT1_2, -M_COS_PI_1_8 + +ps_root2: times 8 dd M_SQRT1_2 +ps_root2mppm: dd -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2 +ps_p1p1m1p1: dd 0, 0, 1<<31, 0, 0, 0, 1<<31, 0 + +perm1: dd 0x00, 0x02, 0x03, 0x01, 0x03, 0x00, 0x02, 0x01 +perm2: dd 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x02, 0x03 +ps_p1p1m1p1root2: dd 1.0, 1.0, -1.0, 1.0, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2 +ps_m1m1p1m1p1m1m1m1: dd 1<<31, 1<<31, 0, 1<<31, 0, 1<<31, 1<<31, 1<<31 +ps_m1m1m1m1: times 4 dd 1<<31 +ps_m1p1: dd 1<<31, 0 + +%assign i 16 +%rep 13 +cextern cos_ %+ i +%assign i i<<1 +%endrep + +%if ARCH_X86_64 + %define pointer dq +%else + %define pointer dd +%endif + +%macro IF0 1+ +%endmacro +%macro IF1 1+ + %1 +%endmacro + +SECTION_TEXT + +%macro T2_3DNOW 4 ; z0, z1, mem0, mem1 + mova %1, %3 + mova %2, %1 + pfadd %1, %4 + pfsub %2, %4 +%endmacro + +%macro T4_3DNOW 6 ; z0, z1, z2, z3, tmp0, tmp1 + mova %5, %3 + pfsub %3, %4 + pfadd %5, %4 ; {t6,t5} + pxor %3, [ps_m1p1] ; {t8,t7} + mova %6, %1 + movd [r0+12], %3 + punpckhdq %3, [r0+8] + pfadd %1, %5 ; {r0,i0} + pfsub %6, %5 ; {r2,i2} + mova %4, %2 + pfadd %2, %3 ; {r1,i1} + pfsub %4, %3 ; {r3,i3} + SWAP %3, %6 +%endmacro + +; in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6} +; %2 = {r1,i1,r3,i3,r5,i5,r7,i7} +; %3, %4, %5 tmp +; out: %1 = {r0,r1,r2,r3,i0,i1,i2,i3} +; %2 = {r4,r5,r6,r7,i4,i5,i6,i7} +%macro T8_AVX 5 + vsubps %5, %1, %2 ; v = %1 - %2 + vaddps %3, %1, %2 ; w = %1 + %2 + vmulps %2, %5, [ps_p1p1m1p1root2] ; v *= vals1 + vpermilps %2, %2, [perm1] + vblendps %1, %2, %3, 0x33 ; q = {w1,w2,v4,v2,w5,w6,v7,v6} + vshufps %5, %3, %2, 0x4e ; r = {w3,w4,v1,v3,w7,w8,v8,v5} + vsubps %4, %5, %1 ; s = r - q + vaddps %1, %5, %1 ; u = r + q + vpermilps %1, %1, [perm2] ; k = {u1,u2,u3,u4,u6,u5,u7,u8} + vshufps %5, %4, %1, 0xbb + vshufps %3, %4, %1, 0xee + vperm2f128 %3, %3, %5, 0x13 + vxorps %4, %4, [ps_m1m1p1m1p1m1m1m1] ; s *= {1,1,-1,-1,1,-1,-1,-1} + vshufps %2, %1, %4, 0xdd + vshufps %1, %1, %4, 0x88 + vperm2f128 %4, %2, %1, 0x02 ; v = {k1,k3,s1,s3,k2,k4,s2,s4} + vperm2f128 %1, %1, %2, 0x13 ; w = {k6,k8,s6,s8,k5,k7,s5,s7} + vsubps %5, %1, %3 + vblendps %1, %5, %1, 0x55 ; w -= {0,s7,0,k7,0,s8,0,k8} + vsubps %2, %4, %1 ; %2 = v - w + vaddps %1, %4, %1 ; %1 = v + w +%endmacro + +; In SSE mode do one fft4 transforms +; in: %1={r0,i0,r2,i2} %2={r1,i1,r3,i3} +; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} +; +; In AVX mode do two fft4 transforms +; in: %1={r0,i0,r2,i2,r4,i4,r6,i6} %2={r1,i1,r3,i3,r5,i5,r7,i7} +; out: %1={r0,r1,r2,r3,r4,r5,r6,r7} %2={i0,i1,i2,i3,i4,i5,i6,i7} +%macro T4_SSE 3 + subps %3, %1, %2 ; {t3,t4,-t8,t7} + addps %1, %1, %2 ; {t1,t2,t6,t5} + xorps %3, %3, [ps_p1p1m1p1] + shufps %2, %1, %3, 0xbe ; {t6,t5,t7,t8} + shufps %1, %1, %3, 0x44 ; {t1,t2,t3,t4} + subps %3, %1, %2 ; {r2,i2,r3,i3} + addps %1, %1, %2 ; {r0,i0,r1,i1} + shufps %2, %1, %3, 0xdd ; {i0,i1,i2,i3} + shufps %1, %1, %3, 0x88 ; {r0,r1,r2,r3} +%endmacro + +; In SSE mode do one FFT8 +; in: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %3={r4,i4,r6,i6} %4={r5,i5,r7,i7} +; out: %1={r0,r1,r2,r3} %2={i0,i1,i2,i3} %1={r4,r5,r6,r7} %2={i4,i5,i6,i7} +; +; In AVX mode do two FFT8 +; in: %1={r0,i0,r2,i2,r8, i8, r10,i10} %2={r1,i1,r3,i3,r9, i9, r11,i11} +; %3={r4,i4,r6,i6,r12,i12,r14,i14} %4={r5,i5,r7,i7,r13,i13,r15,i15} +; out: %1={r0,r1,r2,r3,r8, r9, r10,r11} %2={i0,i1,i2,i3,i8, i9, i10,i11} +; %3={r4,r5,r6,r7,r12,r13,r14,r15} %4={i4,i5,i6,i7,i12,i13,i14,i15} +%macro T8_SSE 6 + addps %6, %3, %4 ; {t1,t2,t3,t4} + subps %3, %3, %4 ; {r5,i5,r7,i7} + shufps %4, %3, %3, 0xb1 ; {i5,r5,i7,r7} + mulps %3, %3, [ps_root2mppm] ; {-r5,i5,r7,-i7} + mulps %4, %4, [ps_root2] + addps %3, %3, %4 ; {t8,t7,ta,t9} + shufps %4, %6, %3, 0x9c ; {t1,t4,t7,ta} + shufps %6, %6, %3, 0x36 ; {t3,t2,t9,t8} + subps %3, %6, %4 ; {t6,t5,tc,tb} + addps %6, %6, %4 ; {t1,t2,t9,ta} + shufps %5, %6, %3, 0x8d ; {t2,ta,t6,tc} + shufps %6, %6, %3, 0xd8 ; {t1,t9,t5,tb} + subps %3, %1, %6 ; {r4,r5,r6,r7} + addps %1, %1, %6 ; {r0,r1,r2,r3} + subps %4, %2, %5 ; {i4,i5,i6,i7} + addps %2, %2, %5 ; {i0,i1,i2,i3} +%endmacro + +; scheduled for cpu-bound sizes +%macro PASS_SMALL 3 ; (to load m4-m7), wre, wim +IF%1 mova m4, Z(4) +IF%1 mova m5, Z(5) + mova m0, %2 ; wre + mova m1, %3 ; wim + mulps m2, m4, m0 ; r2*wre +IF%1 mova m6, Z2(6) + mulps m3, m5, m1 ; i2*wim +IF%1 mova m7, Z2(7) + mulps m4, m4, m1 ; r2*wim + mulps m5, m5, m0 ; i2*wre + addps m2, m2, m3 ; r2*wre + i2*wim + mulps m3, m1, m7 ; i3*wim + subps m5, m5, m4 ; i2*wre - r2*wim + mulps m1, m1, m6 ; r3*wim + mulps m4, m0, m6 ; r3*wre + mulps m0, m0, m7 ; i3*wre + subps m4, m4, m3 ; r3*wre - i3*wim + mova m3, Z(0) + addps m0, m0, m1 ; i3*wre + r3*wim + subps m1, m4, m2 ; t3 + addps m4, m4, m2 ; t5 + subps m3, m3, m4 ; r2 + addps m4, m4, Z(0) ; r0 + mova m6, Z(2) + mova Z(4), m3 + mova Z(0), m4 + subps m3, m5, m0 ; t4 + subps m4, m6, m3 ; r3 + addps m3, m3, m6 ; r1 + mova Z2(6), m4 + mova Z(2), m3 + mova m2, Z(3) + addps m3, m5, m0 ; t6 + subps m2, m2, m1 ; i3 + mova m7, Z(1) + addps m1, m1, Z(3) ; i1 + mova Z2(7), m2 + mova Z(3), m1 + subps m4, m7, m3 ; i2 + addps m3, m3, m7 ; i0 + mova Z(5), m4 + mova Z(1), m3 +%endmacro + +; scheduled to avoid store->load aliasing +%macro PASS_BIG 1 ; (!interleave) + mova m4, Z(4) ; r2 + mova m5, Z(5) ; i2 + mova m0, [wq] ; wre + mova m1, [wq+o1q] ; wim + mulps m2, m4, m0 ; r2*wre + mova m6, Z2(6) ; r3 + mulps m3, m5, m1 ; i2*wim + mova m7, Z2(7) ; i3 + mulps m4, m4, m1 ; r2*wim + mulps m5, m5, m0 ; i2*wre + addps m2, m2, m3 ; r2*wre + i2*wim + mulps m3, m1, m7 ; i3*wim + mulps m1, m1, m6 ; r3*wim + subps m5, m5, m4 ; i2*wre - r2*wim + mulps m4, m0, m6 ; r3*wre + mulps m0, m0, m7 ; i3*wre + subps m4, m4, m3 ; r3*wre - i3*wim + mova m3, Z(0) + addps m0, m0, m1 ; i3*wre + r3*wim + subps m1, m4, m2 ; t3 + addps m4, m4, m2 ; t5 + subps m3, m3, m4 ; r2 + addps m4, m4, Z(0) ; r0 + mova m6, Z(2) + mova Z(4), m3 + mova Z(0), m4 + subps m3, m5, m0 ; t4 + subps m4, m6, m3 ; r3 + addps m3, m3, m6 ; r1 +IF%1 mova Z2(6), m4 +IF%1 mova Z(2), m3 + mova m2, Z(3) + addps m5, m5, m0 ; t6 + subps m2, m2, m1 ; i3 + mova m7, Z(1) + addps m1, m1, Z(3) ; i1 +IF%1 mova Z2(7), m2 +IF%1 mova Z(3), m1 + subps m6, m7, m5 ; i2 + addps m5, m5, m7 ; i0 +IF%1 mova Z(5), m6 +IF%1 mova Z(1), m5 +%if %1==0 + INTERL m1, m3, m7, Z, 2 + INTERL m2, m4, m0, Z2, 6 + + mova m1, Z(0) + mova m2, Z(4) + + INTERL m5, m1, m3, Z, 0 + INTERL m6, m2, m7, Z, 4 +%endif +%endmacro + +%macro PUNPCK 3 + mova %3, %1 + punpckldq %1, %2 + punpckhdq %3, %2 +%endmacro + +%define Z(x) [r0+mmsize*x] +%define Z2(x) [r0+mmsize*x] +%define ZH(x) [r0+mmsize*x+mmsize/2] + +INIT_YMM avx + +%if HAVE_AVX_EXTERNAL +align 16 +fft8_avx: + mova m0, Z(0) + mova m1, Z(1) + T8_AVX m0, m1, m2, m3, m4 + mova Z(0), m0 + mova Z(1), m1 + ret + + +align 16 +fft16_avx: + mova m2, Z(2) + mova m3, Z(3) + T4_SSE m2, m3, m7 + + mova m0, Z(0) + mova m1, Z(1) + T8_AVX m0, m1, m4, m5, m7 + + mova m4, [ps_cos16_1] + mova m5, [ps_cos16_2] + vmulps m6, m2, m4 + vmulps m7, m3, m5 + vaddps m7, m7, m6 + vmulps m2, m2, m5 + vmulps m3, m3, m4 + vsubps m3, m3, m2 + vblendps m2, m7, m3, 0xf0 + vperm2f128 m3, m7, m3, 0x21 + vaddps m4, m2, m3 + vsubps m2, m3, m2 + vperm2f128 m2, m2, m2, 0x01 + vsubps m3, m1, m2 + vaddps m1, m1, m2 + vsubps m5, m0, m4 + vaddps m0, m0, m4 + vextractf128 Z(0), m0, 0 + vextractf128 ZH(0), m1, 0 + vextractf128 Z(1), m0, 1 + vextractf128 ZH(1), m1, 1 + vextractf128 Z(2), m5, 0 + vextractf128 ZH(2), m3, 0 + vextractf128 Z(3), m5, 1 + vextractf128 ZH(3), m3, 1 + ret + +align 16 +fft32_avx: + call fft16_avx + + mova m0, Z(4) + mova m1, Z(5) + + T4_SSE m0, m1, m4 + + mova m2, Z(6) + mova m3, Z(7) + + T8_SSE m0, m1, m2, m3, m4, m6 + ; m0={r0,r1,r2,r3,r8, r9, r10,r11} m1={i0,i1,i2,i3,i8, i9, i10,i11} + ; m2={r4,r5,r6,r7,r12,r13,r14,r15} m3={i4,i5,i6,i7,i12,i13,i14,i15} + + vperm2f128 m4, m0, m2, 0x20 + vperm2f128 m5, m1, m3, 0x20 + vperm2f128 m6, m0, m2, 0x31 + vperm2f128 m7, m1, m3, 0x31 + + PASS_SMALL 0, [cos_32], [cos_32+32] + + ret + +fft32_interleave_avx: + call fft32_avx + mov r2d, 32 +.deint_loop: + mova m2, Z(0) + mova m3, Z(1) + vunpcklps m0, m2, m3 + vunpckhps m1, m2, m3 + vextractf128 Z(0), m0, 0 + vextractf128 ZH(0), m1, 0 + vextractf128 Z(1), m0, 1 + vextractf128 ZH(1), m1, 1 + add r0, mmsize*2 + sub r2d, mmsize/4 + jg .deint_loop + ret + +%endif + +INIT_XMM sse + +align 16 +fft4_avx: +fft4_sse: + mova m0, Z(0) + mova m1, Z(1) + T4_SSE m0, m1, m2 + mova Z(0), m0 + mova Z(1), m1 + ret + +align 16 +fft8_sse: + mova m0, Z(0) + mova m1, Z(1) + T4_SSE m0, m1, m2 + mova m2, Z(2) + mova m3, Z(3) + T8_SSE m0, m1, m2, m3, m4, m5 + mova Z(0), m0 + mova Z(1), m1 + mova Z(2), m2 + mova Z(3), m3 + ret + +align 16 +fft16_sse: + mova m0, Z(0) + mova m1, Z(1) + T4_SSE m0, m1, m2 + mova m2, Z(2) + mova m3, Z(3) + T8_SSE m0, m1, m2, m3, m4, m5 + mova m4, Z(4) + mova m5, Z(5) + mova Z(0), m0 + mova Z(1), m1 + mova Z(2), m2 + mova Z(3), m3 + T4_SSE m4, m5, m6 + mova m6, Z2(6) + mova m7, Z2(7) + T4_SSE m6, m7, m0 + PASS_SMALL 0, [cos_16], [cos_16+16] + ret + + +%macro FFT48_3DNOW 0 +align 16 +fft4 %+ SUFFIX: + T2_3DNOW m0, m1, Z(0), Z(1) + mova m2, Z(2) + mova m3, Z(3) + T4_3DNOW m0, m1, m2, m3, m4, m5 + PUNPCK m0, m1, m4 + PUNPCK m2, m3, m5 + mova Z(0), m0 + mova Z(1), m4 + mova Z(2), m2 + mova Z(3), m5 + ret + +align 16 +fft8 %+ SUFFIX: + T2_3DNOW m0, m1, Z(0), Z(1) + mova m2, Z(2) + mova m3, Z(3) + T4_3DNOW m0, m1, m2, m3, m4, m5 + mova Z(0), m0 + mova Z(2), m2 + T2_3DNOW m4, m5, Z(4), Z(5) + T2_3DNOW m6, m7, Z2(6), Z2(7) + PSWAPD m0, m5 + PSWAPD m2, m7 + pxor m0, [ps_m1p1] + pxor m2, [ps_m1p1] + pfsub m5, m0 + pfadd m7, m2 + pfmul m5, [ps_root2] + pfmul m7, [ps_root2] + T4_3DNOW m1, m3, m5, m7, m0, m2 + mova Z(5), m5 + mova Z2(7), m7 + mova m0, Z(0) + mova m2, Z(2) + T4_3DNOW m0, m2, m4, m6, m5, m7 + PUNPCK m0, m1, m5 + PUNPCK m2, m3, m7 + mova Z(0), m0 + mova Z(1), m5 + mova Z(2), m2 + mova Z(3), m7 + PUNPCK m4, Z(5), m5 + PUNPCK m6, Z2(7), m7 + mova Z(4), m4 + mova Z(5), m5 + mova Z2(6), m6 + mova Z2(7), m7 + ret +%endmacro + +%if ARCH_X86_32 +INIT_MMX 3dnowext +FFT48_3DNOW + +INIT_MMX 3dnow +FFT48_3DNOW +%endif + +%define Z(x) [zcq + o1q*(x&6) + mmsize*(x&1)] +%define Z2(x) [zcq + o3q + mmsize*(x&1)] +%define ZH(x) [zcq + o1q*(x&6) + mmsize*(x&1) + mmsize/2] +%define Z2H(x) [zcq + o3q + mmsize*(x&1) + mmsize/2] + +%macro DECL_PASS 2+ ; name, payload +align 16 +%1: +DEFINE_ARGS zc, w, n, o1, o3 + lea o3q, [nq*3] + lea o1q, [nq*8] + shl o3q, 4 +.loop: + %2 + add zcq, mmsize*2 + add wq, mmsize + sub nd, mmsize/8 + jg .loop + rep ret +%endmacro + +%macro FFT_DISPATCH 2; clobbers 5 GPRs, 8 XMMs + lea r2, [dispatch_tab%1] + mov r2, [r2 + (%2q-2)*gprsize] +%ifdef PIC + lea r3, [$$] + add r2, r3 +%endif + call r2 +%endmacro ; FFT_DISPATCH + +INIT_YMM avx + +%if HAVE_AVX_EXTERNAL +%macro INTERL_AVX 5 + vunpckhps %3, %2, %1 + vunpcklps %2, %2, %1 + vextractf128 %4(%5), %2, 0 + vextractf128 %4 %+ H(%5), %3, 0 + vextractf128 %4(%5 + 1), %2, 1 + vextractf128 %4 %+ H(%5 + 1), %3, 1 +%endmacro + +%define INTERL INTERL_AVX + +DECL_PASS pass_avx, PASS_BIG 1 +DECL_PASS pass_interleave_avx, PASS_BIG 0 + +cglobal fft_calc, 2,5,8 + mov r3d, [r0 + FFTContext.nbits] + mov r0, r1 + mov r1, r3 + FFT_DISPATCH _interleave %+ SUFFIX, r1 + REP_RET + +%endif + +INIT_XMM sse + +%macro INTERL_SSE 5 + mova %3, %2 + unpcklps %2, %1 + unpckhps %3, %1 + mova %4(%5), %2 + mova %4(%5+1), %3 +%endmacro + +%define INTERL INTERL_SSE + +DECL_PASS pass_sse, PASS_BIG 1 +DECL_PASS pass_interleave_sse, PASS_BIG 0 + +%macro FFT_CALC_FUNC 0 +cglobal fft_calc, 2,5,8 + mov r3d, [r0 + FFTContext.nbits] + PUSH r1 + PUSH r3 + mov r0, r1 + mov r1, r3 + FFT_DISPATCH _interleave %+ SUFFIX, r1 + POP rcx + POP r4 + cmp rcx, 3+(mmsize/16) + jg .end + mov r2, -1 + add rcx, 3 + shl r2, cl + sub r4, r2 +.loop: +%if mmsize == 8 + PSWAPD m0, [r4 + r2 + 4] + mova [r4 + r2 + 4], m0 +%else + movaps xmm0, [r4 + r2] + movaps xmm1, xmm0 + unpcklps xmm0, [r4 + r2 + 16] + unpckhps xmm1, [r4 + r2 + 16] + movaps [r4 + r2], xmm0 + movaps [r4 + r2 + 16], xmm1 +%endif + add r2, mmsize*2 + jl .loop +.end: +%if cpuflag(3dnow) + femms + RET +%else + REP_RET +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX 3dnow +FFT_CALC_FUNC +INIT_MMX 3dnowext +FFT_CALC_FUNC +%endif +INIT_XMM sse +FFT_CALC_FUNC + +cglobal fft_permute, 2,7,1 + mov r4, [r0 + FFTContext.revtab] + mov r5, [r0 + FFTContext.tmpbuf] + mov ecx, [r0 + FFTContext.nbits] + mov r2, 1 + shl r2, cl + xor r0, r0 +%if ARCH_X86_32 + mov r1, r1m +%endif +.loop: + movaps xmm0, [r1 + 8*r0] + movzx r6, word [r4 + 2*r0] + movzx r3, word [r4 + 2*r0 + 2] + movlps [r5 + 8*r6], xmm0 + movhps [r5 + 8*r3], xmm0 + add r0, 2 + cmp r0, r2 + jl .loop + shl r2, 3 + add r1, r2 + add r5, r2 + neg r2 +; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B +.loopcopy: + movaps xmm0, [r5 + r2] + movaps xmm1, [r5 + r2 + 16] + movaps [r1 + r2], xmm0 + movaps [r1 + r2 + 16], xmm1 + add r2, 32 + jl .loopcopy + REP_RET + +%macro IMDCT_CALC_FUNC 0 +cglobal imdct_calc, 3,5,3 + mov r3d, [r0 + FFTContext.mdctsize] + mov r4, [r0 + FFTContext.imdcthalf] + add r1, r3 + PUSH r3 + PUSH r1 +%if ARCH_X86_32 + push r2 + push r1 + push r0 +%else + sub rsp, 8 +%endif + call r4 +%if ARCH_X86_32 + add esp, 12 +%else + add rsp, 8 +%endif + POP r1 + POP r3 + lea r0, [r1 + 2*r3] + mov r2, r3 + sub r3, mmsize + neg r2 + mova m2, [ps_m1m1m1m1] +.loop: +%if mmsize == 8 + PSWAPD m0, [r1 + r3] + PSWAPD m1, [r0 + r2] + pxor m0, m2 +%else + mova m0, [r1 + r3] + mova m1, [r0 + r2] + shufps m0, m0, 0x1b + shufps m1, m1, 0x1b + xorps m0, m2 +%endif + mova [r0 + r3], m1 + mova [r1 + r2], m0 + sub r3, mmsize + add r2, mmsize + jl .loop +%if cpuflag(3dnow) + femms + RET +%else + REP_RET +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX 3dnow +IMDCT_CALC_FUNC +INIT_MMX 3dnowext +IMDCT_CALC_FUNC +%endif + +INIT_XMM sse +IMDCT_CALC_FUNC + +%if ARCH_X86_32 +INIT_MMX 3dnow +%define mulps pfmul +%define addps pfadd +%define subps pfsub +%define unpcklps punpckldq +%define unpckhps punpckhdq +DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q] +DECL_PASS pass_interleave_3dnow, PASS_BIG 0 +%define pass_3dnowext pass_3dnow +%define pass_interleave_3dnowext pass_interleave_3dnow +%endif + +%ifdef PIC +%define SECTION_REL - $$ +%else +%define SECTION_REL +%endif + +%macro DECL_FFT 1-2 ; nbits, suffix +%ifidn %0, 1 +%xdefine fullsuffix SUFFIX +%else +%xdefine fullsuffix %2 %+ SUFFIX +%endif +%xdefine list_of_fft fft4 %+ SUFFIX SECTION_REL, fft8 %+ SUFFIX SECTION_REL +%if %1>=5 +%xdefine list_of_fft list_of_fft, fft16 %+ SUFFIX SECTION_REL +%endif +%if %1>=6 +%xdefine list_of_fft list_of_fft, fft32 %+ fullsuffix SECTION_REL +%endif + +%assign n 1<<%1 +%rep 17-%1 +%assign n2 n/2 +%assign n4 n/4 +%xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL + +align 16 +fft %+ n %+ fullsuffix: + call fft %+ n2 %+ SUFFIX + add r0, n*4 - (n&(-2<<%1)) + call fft %+ n4 %+ SUFFIX + add r0, n*2 - (n2&(-2<<%1)) + call fft %+ n4 %+ SUFFIX + sub r0, n*6 + (n2&(-2<<%1)) + lea r1, [cos_ %+ n] + mov r2d, n4/2 + jmp pass %+ fullsuffix + +%assign n n*2 +%endrep +%undef n + +align 8 +dispatch_tab %+ fullsuffix: pointer list_of_fft +%endmacro ; DECL_FFT + +%if HAVE_AVX_EXTERNAL +INIT_YMM avx +DECL_FFT 6 +DECL_FFT 6, _interleave +%endif +INIT_XMM sse +DECL_FFT 5 +DECL_FFT 5, _interleave +%if ARCH_X86_32 +INIT_MMX 3dnow +DECL_FFT 4 +DECL_FFT 4, _interleave +INIT_MMX 3dnowext +DECL_FFT 4 +DECL_FFT 4, _interleave +%endif + +INIT_XMM sse +%undef mulps +%undef addps +%undef subps +%undef unpcklps +%undef unpckhps + +%macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8 +%if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8 + PSWAPD m0, [%3+%2*4] + movq m2, [%3+%1*4-8] + movq m3, m0 + punpckldq m0, m2 + punpckhdq m2, m3 + movd m1, [%4+%1*2-4] ; tcos[j] + movd m3, [%4+%2*2] ; tcos[n4-j-1] + punpckldq m1, [%5+%1*2-4] ; tsin[j] + punpckldq m3, [%5+%2*2] ; tsin[n4-j-1] + + mova m4, m0 + PSWAPD m5, m1 + pfmul m0, m1 + pfmul m4, m5 + mova m6, m2 + PSWAPD m5, m3 + pfmul m2, m3 + pfmul m6, m5 +%if cpuflag(3dnowext) + pfpnacc m0, m4 + pfpnacc m2, m6 +%else + SBUTTERFLY dq, 0, 4, 1 + SBUTTERFLY dq, 2, 6, 3 + pxor m4, m7 + pxor m6, m7 + pfadd m0, m4 + pfadd m2, m6 +%endif +%else + movaps xmm0, [%3+%2*4] + movaps xmm1, [%3+%1*4-0x10] + movaps xmm2, xmm0 + shufps xmm0, xmm1, 0x88 + shufps xmm1, xmm2, 0x77 + movlps xmm4, [%4+%2*2] + movlps xmm5, [%5+%2*2+0x0] + movhps xmm4, [%4+%1*2-0x8] + movhps xmm5, [%5+%1*2-0x8] + movaps xmm2, xmm0 + movaps xmm3, xmm1 + mulps xmm0, xmm5 + mulps xmm1, xmm4 + mulps xmm2, xmm4 + mulps xmm3, xmm5 + subps xmm1, xmm0 + addps xmm2, xmm3 + movaps xmm0, xmm1 + unpcklps xmm1, xmm2 + unpckhps xmm0, xmm2 +%endif +%endmacro + +%macro CMUL 6 ;j, xmm0, xmm1, 3, 4, 5 + mulps m6, %3, [%5+%1] + mulps m7, %2, [%5+%1] + mulps %2, %2, [%6+%1] + mulps %3, %3, [%6+%1] + subps %2, %2, m6 + addps %3, %3, m7 +%endmacro + +%macro POSROTATESHUF_AVX 5 ;j, k, z+n8, tcos+n8, tsin+n8 +.post: + vmovaps ymm1, [%3+%1*2] + vmovaps ymm0, [%3+%1*2+0x20] + vmovaps ymm3, [%3+%2*2] + vmovaps ymm2, [%3+%2*2+0x20] + + CMUL %1, ymm0, ymm1, %3, %4, %5 + CMUL %2, ymm2, ymm3, %3, %4, %5 + vshufps ymm1, ymm1, ymm1, 0x1b + vshufps ymm3, ymm3, ymm3, 0x1b + vperm2f128 ymm1, ymm1, ymm1, 0x01 + vperm2f128 ymm3, ymm3, ymm3, 0x01 + vunpcklps ymm6, ymm2, ymm1 + vunpckhps ymm4, ymm2, ymm1 + vunpcklps ymm7, ymm0, ymm3 + vunpckhps ymm5, ymm0, ymm3 + + vextractf128 [%3+%1*2], ymm7, 0 + vextractf128 [%3+%1*2+0x10], ymm5, 0 + vextractf128 [%3+%1*2+0x20], ymm7, 1 + vextractf128 [%3+%1*2+0x30], ymm5, 1 + + vextractf128 [%3+%2*2], ymm6, 0 + vextractf128 [%3+%2*2+0x10], ymm4, 0 + vextractf128 [%3+%2*2+0x20], ymm6, 1 + vextractf128 [%3+%2*2+0x30], ymm4, 1 + sub %2, 0x20 + add %1, 0x20 + jl .post +%endmacro + +%macro POSROTATESHUF 5 ;j, k, z+n8, tcos+n8, tsin+n8 +.post: + movaps xmm1, [%3+%1*2] + movaps xmm0, [%3+%1*2+0x10] + CMUL %1, xmm0, xmm1, %3, %4, %5 + movaps xmm5, [%3+%2*2] + movaps xmm4, [%3+%2*2+0x10] + CMUL %2, xmm4, xmm5, %3, %4, %5 + shufps xmm1, xmm1, 0x1b + shufps xmm5, xmm5, 0x1b + movaps xmm6, xmm4 + unpckhps xmm4, xmm1 + unpcklps xmm6, xmm1 + movaps xmm2, xmm0 + unpcklps xmm0, xmm5 + unpckhps xmm2, xmm5 + movaps [%3+%2*2], xmm6 + movaps [%3+%2*2+0x10], xmm4 + movaps [%3+%1*2], xmm0 + movaps [%3+%1*2+0x10], xmm2 + sub %2, 0x10 + add %1, 0x10 + jl .post +%endmacro + +%macro CMUL_3DNOW 6 + mova m6, [%1+%2*2] + mova %3, [%1+%2*2+8] + mova %4, m6 + mova m7, %3 + pfmul m6, [%5+%2] + pfmul %3, [%6+%2] + pfmul %4, [%6+%2] + pfmul m7, [%5+%2] + pfsub %3, m6 + pfadd %4, m7 +%endmacro + +%macro POSROTATESHUF_3DNOW 5 ;j, k, z+n8, tcos+n8, tsin+n8 +.post: + CMUL_3DNOW %3, %1, m0, m1, %4, %5 + CMUL_3DNOW %3, %2, m2, m3, %4, %5 + movd [%3+%1*2+ 0], m0 + movd [%3+%2*2+12], m1 + movd [%3+%2*2+ 0], m2 + movd [%3+%1*2+12], m3 + psrlq m0, 32 + psrlq m1, 32 + psrlq m2, 32 + psrlq m3, 32 + movd [%3+%1*2+ 8], m0 + movd [%3+%2*2+ 4], m1 + movd [%3+%2*2+ 8], m2 + movd [%3+%1*2+ 4], m3 + sub %2, 8 + add %1, 8 + jl .post +%endmacro + +%macro DECL_IMDCT 1 +cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *input +%if ARCH_X86_64 +%define rrevtab r7 +%define rtcos r8 +%define rtsin r9 +%else +%define rrevtab r6 +%define rtsin r6 +%define rtcos r5 +%endif + mov r3d, [r0+FFTContext.mdctsize] + add r2, r3 + shr r3, 1 + mov rtcos, [r0+FFTContext.tcos] + mov rtsin, [r0+FFTContext.tsin] + add rtcos, r3 + add rtsin, r3 +%if ARCH_X86_64 == 0 + push rtcos + push rtsin +%endif + shr r3, 1 + mov rrevtab, [r0+FFTContext.revtab] + add rrevtab, r3 +%if ARCH_X86_64 == 0 + push rrevtab +%endif + +%if mmsize == 8 + sub r3, 2 +%else + sub r3, 4 +%endif +%if ARCH_X86_64 || mmsize == 8 + xor r4, r4 + sub r4, r3 +%endif +%if notcpuflag(3dnowext) && mmsize == 8 + movd m7, [ps_m1m1m1m1] +%endif +.pre: +%if ARCH_X86_64 == 0 +;unspill +%if mmsize != 8 + xor r4, r4 + sub r4, r3 +%endif + mov rtcos, [esp+8] + mov rtsin, [esp+4] +%endif + + PREROTATER r4, r3, r2, rtcos, rtsin +%if mmsize == 8 + mov r6, [esp] ; rrevtab = ptr+n8 + movzx r5, word [rrevtab+r4-2] ; rrevtab[j] + movzx r6, word [rrevtab+r3] ; rrevtab[n4-j-1] + mova [r1+r5*8], m0 + mova [r1+r6*8], m2 + add r4, 2 + sub r3, 2 +%else +%if ARCH_X86_64 + movzx r5, word [rrevtab+r4-4] + movzx r6, word [rrevtab+r4-2] + movzx r10, word [rrevtab+r3] + movzx r11, word [rrevtab+r3+2] + movlps [r1+r5 *8], xmm0 + movhps [r1+r6 *8], xmm0 + movlps [r1+r10*8], xmm1 + movhps [r1+r11*8], xmm1 + add r4, 4 +%else + mov r6, [esp] + movzx r5, word [r6+r4-4] + movzx r4, word [r6+r4-2] + movlps [r1+r5*8], xmm0 + movhps [r1+r4*8], xmm0 + movzx r5, word [r6+r3] + movzx r4, word [r6+r3+2] + movlps [r1+r5*8], xmm1 + movhps [r1+r4*8], xmm1 +%endif + sub r3, 4 +%endif + jns .pre + + mov r5, r0 + mov r6, r1 + mov r0, r1 + mov r1d, [r5+FFTContext.nbits] + + FFT_DISPATCH SUFFIX, r1 + + mov r0d, [r5+FFTContext.mdctsize] + add r6, r0 + shr r0, 1 +%if ARCH_X86_64 == 0 +%define rtcos r2 +%define rtsin r3 + mov rtcos, [esp+8] + mov rtsin, [esp+4] +%endif + neg r0 + mov r1, -mmsize + sub r1, r0 + %1 r0, r1, r6, rtcos, rtsin +%if ARCH_X86_64 == 0 + add esp, 12 +%endif +%if mmsize == 8 + femms +%endif + RET +%endmacro + +DECL_IMDCT POSROTATESHUF + +%if ARCH_X86_32 +INIT_MMX 3dnow +DECL_IMDCT POSROTATESHUF_3DNOW + +INIT_MMX 3dnowext +DECL_IMDCT POSROTATESHUF_3DNOW +%endif + +INIT_YMM avx + +%if HAVE_AVX_EXTERNAL +DECL_IMDCT POSROTATESHUF_AVX +%endif diff --git a/ffmpeg/libavcodec/x86/fft.h b/ffmpeg/libavcodec/x86/fft.h new file mode 100644 index 0000000..3f8b21d --- /dev/null +++ b/ffmpeg/libavcodec/x86/fft.h @@ -0,0 +1,41 @@ +/* + * 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 + */ + +#ifndef AVCODEC_X86_FFT_H +#define AVCODEC_X86_FFT_H + +#include "libavcodec/fft.h" + +void ff_fft_permute_sse(FFTContext *s, FFTComplex *z); +void ff_fft_calc_avx(FFTContext *s, FFTComplex *z); +void ff_fft_calc_sse(FFTContext *s, FFTComplex *z); +void ff_fft_calc_3dnow(FFTContext *s, FFTComplex *z); +void ff_fft_calc_3dnowext(FFTContext *s, FFTComplex *z); + +void ff_imdct_calc_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_calc_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_calc_sse(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_sse(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_imdct_half_avx(FFTContext *s, FFTSample *output, const FFTSample *input); +void ff_dct32_float_sse(FFTSample *out, const FFTSample *in); +void ff_dct32_float_sse2(FFTSample *out, const FFTSample *in); +void ff_dct32_float_avx(FFTSample *out, const FFTSample *in); + +#endif /* AVCODEC_X86_FFT_H */ diff --git a/ffmpeg/libavcodec/x86/fft_init.c b/ffmpeg/libavcodec/x86/fft_init.c new file mode 100644 index 0000000..bfa7947 --- /dev/null +++ b/ffmpeg/libavcodec/x86/fft_init.c @@ -0,0 +1,68 @@ +/* + * 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 "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/dct.h" +#include "fft.h" + +av_cold void ff_fft_init_x86(FFTContext *s) +{ + int has_vectors = av_get_cpu_flags(); +#if ARCH_X86_32 + if (EXTERNAL_AMD3DNOW(has_vectors)) { + /* 3DNow! for K6-2/3 */ + s->imdct_calc = ff_imdct_calc_3dnow; + s->imdct_half = ff_imdct_half_3dnow; + s->fft_calc = ff_fft_calc_3dnow; + } + if (EXTERNAL_AMD3DNOWEXT(has_vectors)) { + /* 3DNowEx for K7 */ + s->imdct_calc = ff_imdct_calc_3dnowext; + s->imdct_half = ff_imdct_half_3dnowext; + s->fft_calc = ff_fft_calc_3dnowext; + } +#endif + if (EXTERNAL_SSE(has_vectors)) { + /* SSE for P3/P4/K8 */ + s->imdct_calc = ff_imdct_calc_sse; + s->imdct_half = ff_imdct_half_sse; + s->fft_permute = ff_fft_permute_sse; + s->fft_calc = ff_fft_calc_sse; + s->fft_permutation = FF_FFT_PERM_SWAP_LSBS; + } + if (EXTERNAL_AVX(has_vectors) && s->nbits >= 5) { + /* AVX for SB */ + s->imdct_half = ff_imdct_half_avx; + s->fft_calc = ff_fft_calc_avx; + s->fft_permutation = FF_FFT_PERM_AVX; + } +} + +#if CONFIG_DCT +av_cold void ff_dct_init_x86(DCTContext *s) +{ + int has_vectors = av_get_cpu_flags(); + if (EXTERNAL_SSE(has_vectors)) + s->dct32 = ff_dct32_float_sse; + if (EXTERNAL_SSE2(has_vectors)) + s->dct32 = ff_dct32_float_sse2; + if (EXTERNAL_AVX(has_vectors)) + s->dct32 = ff_dct32_float_avx; +} +#endif diff --git a/ffmpeg/libavcodec/x86/fmtconvert.asm b/ffmpeg/libavcodec/x86/fmtconvert.asm new file mode 100644 index 0000000..1bd13fc --- /dev/null +++ b/ffmpeg/libavcodec/x86/fmtconvert.asm @@ -0,0 +1,429 @@ +;****************************************************************************** +;* x86 optimized Format Conversion Utils +;* Copyright (c) 2008 Loren Merritt +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_TEXT + +%macro CVTPS2PI 2 +%if cpuflag(sse) + cvtps2pi %1, %2 +%elif cpuflag(3dnow) + pf2id %1, %2 +%endif +%endmacro + +;--------------------------------------------------------------------------------- +; void int32_to_float_fmul_scalar(float *dst, const int *src, float mul, int len); +;--------------------------------------------------------------------------------- +%macro INT32_TO_FLOAT_FMUL_SCALAR 1 +%if UNIX64 +cglobal int32_to_float_fmul_scalar, 3, 3, %1, dst, src, len +%else +cglobal int32_to_float_fmul_scalar, 4, 4, %1, dst, src, mul, len +%endif +%if WIN64 + SWAP 0, 2 +%elif ARCH_X86_32 + movss m0, mulm +%endif + SPLATD m0 + shl lenq, 2 + add srcq, lenq + add dstq, lenq + neg lenq +.loop: +%if cpuflag(sse2) + cvtdq2ps m1, [srcq+lenq ] + cvtdq2ps m2, [srcq+lenq+16] +%else + cvtpi2ps m1, [srcq+lenq ] + cvtpi2ps m3, [srcq+lenq+ 8] + cvtpi2ps m2, [srcq+lenq+16] + cvtpi2ps m4, [srcq+lenq+24] + movlhps m1, m3 + movlhps m2, m4 +%endif + mulps m1, m0 + mulps m2, m0 + mova [dstq+lenq ], m1 + mova [dstq+lenq+16], m2 + add lenq, 32 + jl .loop + REP_RET +%endmacro + +INIT_XMM sse +INT32_TO_FLOAT_FMUL_SCALAR 5 +INIT_XMM sse2 +INT32_TO_FLOAT_FMUL_SCALAR 3 + + +;------------------------------------------------------------------------------ +; void ff_float_to_int16(int16_t *dst, const float *src, long len); +;------------------------------------------------------------------------------ +%macro FLOAT_TO_INT16 1 +cglobal float_to_int16, 3, 3, %1, dst, src, len + add lenq, lenq + lea srcq, [srcq+2*lenq] + add dstq, lenq + neg lenq +.loop: +%if cpuflag(sse2) + cvtps2dq m0, [srcq+2*lenq ] + cvtps2dq m1, [srcq+2*lenq+16] + packssdw m0, m1 + mova [dstq+lenq], m0 +%else + CVTPS2PI m0, [srcq+2*lenq ] + CVTPS2PI m1, [srcq+2*lenq+ 8] + CVTPS2PI m2, [srcq+2*lenq+16] + CVTPS2PI m3, [srcq+2*lenq+24] + packssdw m0, m1 + packssdw m2, m3 + mova [dstq+lenq ], m0 + mova [dstq+lenq+8], m2 +%endif + add lenq, 16 + js .loop +%if mmsize == 8 + emms +%endif + REP_RET +%endmacro + +INIT_XMM sse2 +FLOAT_TO_INT16 2 +INIT_MMX sse +FLOAT_TO_INT16 0 +INIT_MMX 3dnow +FLOAT_TO_INT16 0 + +;------------------------------------------------------------------------------ +; void ff_float_to_int16_step(int16_t *dst, const float *src, long len, long step); +;------------------------------------------------------------------------------ +%macro FLOAT_TO_INT16_STEP 1 +cglobal float_to_int16_step, 4, 7, %1, dst, src, len, step, step3, v1, v2 + add lenq, lenq + lea srcq, [srcq+2*lenq] + lea step3q, [stepq*3] + neg lenq +.loop: +%if cpuflag(sse2) + cvtps2dq m0, [srcq+2*lenq ] + cvtps2dq m1, [srcq+2*lenq+16] + packssdw m0, m1 + movd v1d, m0 + psrldq m0, 4 + movd v2d, m0 + psrldq m0, 4 + mov [dstq], v1w + mov [dstq+stepq*4], v2w + shr v1d, 16 + shr v2d, 16 + mov [dstq+stepq*2], v1w + mov [dstq+step3q*2], v2w + lea dstq, [dstq+stepq*8] + movd v1d, m0 + psrldq m0, 4 + movd v2d, m0 + mov [dstq], v1w + mov [dstq+stepq*4], v2w + shr v1d, 16 + shr v2d, 16 + mov [dstq+stepq*2], v1w + mov [dstq+step3q*2], v2w + lea dstq, [dstq+stepq*8] +%else + CVTPS2PI m0, [srcq+2*lenq ] + CVTPS2PI m1, [srcq+2*lenq+ 8] + CVTPS2PI m2, [srcq+2*lenq+16] + CVTPS2PI m3, [srcq+2*lenq+24] + packssdw m0, m1 + packssdw m2, m3 + movd v1d, m0 + psrlq m0, 32 + movd v2d, m0 + mov [dstq], v1w + mov [dstq+stepq*4], v2w + shr v1d, 16 + shr v2d, 16 + mov [dstq+stepq*2], v1w + mov [dstq+step3q*2], v2w + lea dstq, [dstq+stepq*8] + movd v1d, m2 + psrlq m2, 32 + movd v2d, m2 + mov [dstq], v1w + mov [dstq+stepq*4], v2w + shr v1d, 16 + shr v2d, 16 + mov [dstq+stepq*2], v1w + mov [dstq+step3q*2], v2w + lea dstq, [dstq+stepq*8] +%endif + add lenq, 16 + js .loop +%if mmsize == 8 + emms +%endif + REP_RET +%endmacro + +INIT_XMM sse2 +FLOAT_TO_INT16_STEP 2 +INIT_MMX sse +FLOAT_TO_INT16_STEP 0 +INIT_MMX 3dnow +FLOAT_TO_INT16_STEP 0 + +;------------------------------------------------------------------------------- +; void ff_float_to_int16_interleave2(int16_t *dst, const float **src, long len); +;------------------------------------------------------------------------------- +%macro FLOAT_TO_INT16_INTERLEAVE2 0 +cglobal float_to_int16_interleave2, 3, 4, 2, dst, src0, src1, len + lea lenq, [4*r2q] + mov src1q, [src0q+gprsize] + mov src0q, [src0q] + add dstq, lenq + add src0q, lenq + add src1q, lenq + neg lenq +.loop: +%if cpuflag(sse2) + cvtps2dq m0, [src0q+lenq] + cvtps2dq m1, [src1q+lenq] + packssdw m0, m1 + movhlps m1, m0 + punpcklwd m0, m1 + mova [dstq+lenq], m0 +%else + CVTPS2PI m0, [src0q+lenq ] + CVTPS2PI m1, [src0q+lenq+8] + CVTPS2PI m2, [src1q+lenq ] + CVTPS2PI m3, [src1q+lenq+8] + packssdw m0, m1 + packssdw m2, m3 + mova m1, m0 + punpcklwd m0, m2 + punpckhwd m1, m2 + mova [dstq+lenq ], m0 + mova [dstq+lenq+8], m1 +%endif + add lenq, 16 + js .loop +%if mmsize == 8 + emms +%endif + REP_RET +%endmacro + +INIT_MMX 3dnow +FLOAT_TO_INT16_INTERLEAVE2 +INIT_MMX sse +FLOAT_TO_INT16_INTERLEAVE2 +INIT_XMM sse2 +FLOAT_TO_INT16_INTERLEAVE2 + +%macro FLOAT_TO_INT16_INTERLEAVE6 0 +; void float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len) +cglobal float_to_int16_interleave6, 2, 8, 0, dst, src, src1, src2, src3, src4, src5, len +%if ARCH_X86_64 + mov lend, r2d +%else + %define lend dword r2m +%endif + mov src1q, [srcq+1*gprsize] + mov src2q, [srcq+2*gprsize] + mov src3q, [srcq+3*gprsize] + mov src4q, [srcq+4*gprsize] + mov src5q, [srcq+5*gprsize] + mov srcq, [srcq] + sub src1q, srcq + sub src2q, srcq + sub src3q, srcq + sub src4q, srcq + sub src5q, srcq +.loop: + CVTPS2PI mm0, [srcq] + CVTPS2PI mm1, [srcq+src1q] + CVTPS2PI mm2, [srcq+src2q] + CVTPS2PI mm3, [srcq+src3q] + CVTPS2PI mm4, [srcq+src4q] + CVTPS2PI mm5, [srcq+src5q] + packssdw mm0, mm3 + packssdw mm1, mm4 + packssdw mm2, mm5 + PSWAPD mm3, mm0 + punpcklwd mm0, mm1 + punpckhwd mm1, mm2 + punpcklwd mm2, mm3 + PSWAPD mm3, mm0 + punpckldq mm0, mm2 + punpckhdq mm2, mm1 + punpckldq mm1, mm3 + movq [dstq ], mm0 + movq [dstq+16], mm2 + movq [dstq+ 8], mm1 + add srcq, 8 + add dstq, 24 + sub lend, 2 + jg .loop + emms + RET +%endmacro ; FLOAT_TO_INT16_INTERLEAVE6 + +INIT_MMX sse +FLOAT_TO_INT16_INTERLEAVE6 +INIT_MMX 3dnow +FLOAT_TO_INT16_INTERLEAVE6 +INIT_MMX 3dnowext +FLOAT_TO_INT16_INTERLEAVE6 + +;----------------------------------------------------------------------------- +; void ff_float_interleave6(float *dst, const float **src, unsigned int len); +;----------------------------------------------------------------------------- + +%macro FLOAT_INTERLEAVE6 1 +cglobal float_interleave6, 2, 8, %1, dst, src, src1, src2, src3, src4, src5, len +%if ARCH_X86_64 + mov lend, r2d +%else + %define lend dword r2m +%endif + mov src1q, [srcq+1*gprsize] + mov src2q, [srcq+2*gprsize] + mov src3q, [srcq+3*gprsize] + mov src4q, [srcq+4*gprsize] + mov src5q, [srcq+5*gprsize] + mov srcq, [srcq] + sub src1q, srcq + sub src2q, srcq + sub src3q, srcq + sub src4q, srcq + sub src5q, srcq +.loop: +%if cpuflag(sse) + movaps m0, [srcq] + movaps m1, [srcq+src1q] + movaps m2, [srcq+src2q] + movaps m3, [srcq+src3q] + movaps m4, [srcq+src4q] + movaps m5, [srcq+src5q] + + SBUTTERFLYPS 0, 1, 6 + SBUTTERFLYPS 2, 3, 6 + SBUTTERFLYPS 4, 5, 6 + + movaps m6, m4 + shufps m4, m0, 0xe4 + movlhps m0, m2 + movhlps m6, m2 + movaps [dstq ], m0 + movaps [dstq+16], m4 + movaps [dstq+32], m6 + + movaps m6, m5 + shufps m5, m1, 0xe4 + movlhps m1, m3 + movhlps m6, m3 + movaps [dstq+48], m1 + movaps [dstq+64], m5 + movaps [dstq+80], m6 +%else ; mmx + movq m0, [srcq] + movq m1, [srcq+src1q] + movq m2, [srcq+src2q] + movq m3, [srcq+src3q] + movq m4, [srcq+src4q] + movq m5, [srcq+src5q] + + SBUTTERFLY dq, 0, 1, 6 + SBUTTERFLY dq, 2, 3, 6 + SBUTTERFLY dq, 4, 5, 6 + movq [dstq ], m0 + movq [dstq+ 8], m2 + movq [dstq+16], m4 + movq [dstq+24], m1 + movq [dstq+32], m3 + movq [dstq+40], m5 +%endif + add srcq, mmsize + add dstq, mmsize*6 + sub lend, mmsize/4 + jg .loop +%if mmsize == 8 + emms +%endif + REP_RET +%endmacro + +INIT_MMX mmx +FLOAT_INTERLEAVE6 0 +INIT_XMM sse +FLOAT_INTERLEAVE6 7 + +;----------------------------------------------------------------------------- +; void ff_float_interleave2(float *dst, const float **src, unsigned int len); +;----------------------------------------------------------------------------- + +%macro FLOAT_INTERLEAVE2 1 +cglobal float_interleave2, 3, 4, %1, dst, src, len, src1 + mov src1q, [srcq+gprsize] + mov srcq, [srcq ] + sub src1q, srcq +.loop: + mova m0, [srcq ] + mova m1, [srcq+src1q ] + mova m3, [srcq +mmsize] + mova m4, [srcq+src1q+mmsize] + + mova m2, m0 + PUNPCKLDQ m0, m1 + PUNPCKHDQ m2, m1 + + mova m1, m3 + PUNPCKLDQ m3, m4 + PUNPCKHDQ m1, m4 + + mova [dstq ], m0 + mova [dstq+1*mmsize], m2 + mova [dstq+2*mmsize], m3 + mova [dstq+3*mmsize], m1 + + add srcq, mmsize*2 + add dstq, mmsize*4 + sub lend, mmsize/2 + jg .loop +%if mmsize == 8 + emms +%endif + REP_RET +%endmacro + +INIT_MMX mmx +%define PUNPCKLDQ punpckldq +%define PUNPCKHDQ punpckhdq +FLOAT_INTERLEAVE2 0 +INIT_XMM sse +%define PUNPCKLDQ unpcklps +%define PUNPCKHDQ unpckhps +FLOAT_INTERLEAVE2 5 diff --git a/ffmpeg/libavcodec/x86/fmtconvert_init.c b/ffmpeg/libavcodec/x86/fmtconvert_init.c new file mode 100644 index 0000000..4a4c017 --- /dev/null +++ b/ffmpeg/libavcodec/x86/fmtconvert_init.c @@ -0,0 +1,148 @@ +/* + * Format Conversion Utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + * + * MMX optimization by Nick Kurshev + */ + +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/fmtconvert.h" + +#if HAVE_YASM + +void ff_int32_to_float_fmul_scalar_sse (float *dst, const int *src, float mul, int len); +void ff_int32_to_float_fmul_scalar_sse2(float *dst, const int *src, float mul, int len); + +void ff_float_to_int16_3dnow(int16_t *dst, const float *src, long len); +void ff_float_to_int16_sse (int16_t *dst, const float *src, long len); +void ff_float_to_int16_sse2 (int16_t *dst, const float *src, long len); + +void ff_float_to_int16_step_3dnow(int16_t *dst, const float *src, long len, long step); +void ff_float_to_int16_step_sse (int16_t *dst, const float *src, long len, long step); +void ff_float_to_int16_step_sse2 (int16_t *dst, const float *src, long len, long step); + +void ff_float_to_int16_interleave2_3dnow(int16_t *dst, const float **src, long len); +void ff_float_to_int16_interleave2_sse (int16_t *dst, const float **src, long len); +void ff_float_to_int16_interleave2_sse2 (int16_t *dst, const float **src, long len); + +void ff_float_to_int16_interleave6_sse(int16_t *dst, const float **src, int len); +void ff_float_to_int16_interleave6_3dnow(int16_t *dst, const float **src, int len); +void ff_float_to_int16_interleave6_3dnowext(int16_t *dst, const float **src, int len); + +#define ff_float_to_int16_interleave6_sse2 ff_float_to_int16_interleave6_sse + +#define FLOAT_TO_INT16_INTERLEAVE(cpu) \ +/* gcc pessimizes register allocation if this is in the same function as float_to_int16_interleave_sse2*/\ +static av_noinline void float_to_int16_interleave_misc_##cpu(int16_t *dst, const float **src, long len, int channels){\ + int c;\ + for(c=0; cfloat_interleave = float_interleave_mmx; + + if (EXTERNAL_AMD3DNOW(mm_flags)) { + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->float_to_int16 = ff_float_to_int16_3dnow; + c->float_to_int16_interleave = float_to_int16_interleave_3dnow; + } + } + if (EXTERNAL_AMD3DNOWEXT(mm_flags)) { + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->float_to_int16_interleave = float_to_int16_interleave_3dnowext; + } + } + if (EXTERNAL_SSE(mm_flags)) { + c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse; + c->float_to_int16 = ff_float_to_int16_sse; + c->float_to_int16_interleave = float_to_int16_interleave_sse; + c->float_interleave = float_interleave_sse; + } + if (EXTERNAL_SSE2(mm_flags)) { + c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse2; + c->float_to_int16 = ff_float_to_int16_sse2; + c->float_to_int16_interleave = float_to_int16_interleave_sse2; + } + } +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/fpelbase.asm b/ffmpeg/libavcodec/x86/fpelbase.asm new file mode 100644 index 0000000..a327206 --- /dev/null +++ b/ffmpeg/libavcodec/x86/fpelbase.asm @@ -0,0 +1,106 @@ +;****************************************************************************** +;* MMX optimized DSP utils +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2003-2013 Michael Niedermayer +;* Copyright (c) 2013 Daniel Kang +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION .text + +INIT_MMX mmxext +; void pixels(uint8_t *block, const uint8_t *pixels, int line_size, int h) +%macro PIXELS48 2 +%if %2 == 4 +%define OP movh +%else +%define OP mova +%endif +cglobal %1_pixels%2, 4,5 + movsxdifnidn r2, r2d + lea r4, [r2*3] +.loop: + OP m0, [r1] + OP m1, [r1+r2] + OP m2, [r1+r2*2] + OP m3, [r1+r4] + lea r1, [r1+r2*4] +%ifidn %1, avg + pavgb m0, [r0] + pavgb m1, [r0+r2] + pavgb m2, [r0+r2*2] + pavgb m3, [r0+r4] +%endif + OP [r0], m0 + OP [r0+r2], m1 + OP [r0+r2*2], m2 + OP [r0+r4], m3 + sub r3d, 4 + lea r0, [r0+r2*4] + jne .loop + RET +%endmacro + +PIXELS48 put, 4 +PIXELS48 avg, 4 +PIXELS48 put, 8 +PIXELS48 avg, 8 + + +INIT_XMM sse2 +; void put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +cglobal put_pixels16, 4,5,4 + lea r4, [r2*3] +.loop: + movu m0, [r1] + movu m1, [r1+r2] + movu m2, [r1+r2*2] + movu m3, [r1+r4] + lea r1, [r1+r2*4] + mova [r0], m0 + mova [r0+r2], m1 + mova [r0+r2*2], m2 + mova [r0+r4], m3 + sub r3d, 4 + lea r0, [r0+r2*4] + jnz .loop + REP_RET + +; void avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +cglobal avg_pixels16, 4,5,4 + lea r4, [r2*3] +.loop: + movu m0, [r1] + movu m1, [r1+r2] + movu m2, [r1+r2*2] + movu m3, [r1+r4] + lea r1, [r1+r2*4] + pavgb m0, [r0] + pavgb m1, [r0+r2] + pavgb m2, [r0+r2*2] + pavgb m3, [r0+r4] + mova [r0], m0 + mova [r0+r2], m1 + mova [r0+r2*2], m2 + mova [r0+r4], m3 + sub r3d, 4 + lea r0, [r0+r2*4] + jnz .loop + REP_RET diff --git a/ffmpeg/libavcodec/x86/h263_loopfilter.asm b/ffmpeg/libavcodec/x86/h263_loopfilter.asm new file mode 100644 index 0000000..a21baf1 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h263_loopfilter.asm @@ -0,0 +1,189 @@ +;****************************************************************************** +;* MMX-optimized H.263 loop filter +;* Copyright (c) 2003-2013 Michael Niedermayer +;* Copyright (c) 2013 Daniel Kang +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA +cextern pb_FC +cextern h263_loop_filter_strength + +SECTION_TEXT + +%macro H263_LOOP_FILTER 5 + pxor m7, m7 + mova m0, [%1] + mova m1, [%1] + mova m2, [%4] + mova m3, [%4] + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + psubw m0, m2 + psubw m1, m3 + mova m2, [%2] + mova m3, [%2] + mova m4, [%3] + mova m5, [%3] + punpcklbw m2, m7 + punpckhbw m3, m7 + punpcklbw m4, m7 + punpckhbw m5, m7 + psubw m4, m2 + psubw m5, m3 + psllw m4, 2 + psllw m5, 2 + paddw m4, m0 + paddw m5, m1 + pxor m6, m6 + pcmpgtw m6, m4 + pcmpgtw m7, m5 + pxor m4, m6 + pxor m5, m7 + psubw m4, m6 + psubw m5, m7 + psrlw m4, 3 + psrlw m5, 3 + packuswb m4, m5 + packsswb m6, m7 + pxor m7, m7 + movd m2, %5 + punpcklbw m2, m2 + punpcklbw m2, m2 + punpcklbw m2, m2 + psubusb m2, m4 + mova m3, m2 + psubusb m3, m4 + psubb m2, m3 + mova m3, [%2] + mova m4, [%3] + pxor m3, m6 + pxor m4, m6 + paddusb m3, m2 + psubusb m4, m2 + pxor m3, m6 + pxor m4, m6 + paddusb m2, m2 + packsswb m0, m1 + pcmpgtb m7, m0 + pxor m0, m7 + psubb m0, m7 + mova m1, m0 + psubusb m0, m2 + psubb m1, m0 + pand m1, [pb_FC] + psrlw m1, 2 + pxor m1, m7 + psubb m1, m7 + mova m5, [%1] + mova m6, [%4] + psubb m5, m1 + paddb m6, m1 +%endmacro + +INIT_MMX mmx +; void h263_v_loop_filter(uint8_t *src, int stride, int qscale) +cglobal h263_v_loop_filter, 3,5 + movsxdifnidn r1, r1d + movsxdifnidn r2, r2d + + lea r4, [h263_loop_filter_strength] + movzx r3d, BYTE [r4+r2] + movsx r2, r3b + shl r2, 1 + + mov r3, r0 + sub r3, r1 + mov r4, r3 + sub r4, r1 + H263_LOOP_FILTER r4, r3, r0, r0+r1, r2d + + mova [r3], m3 + mova [r0], m4 + mova [r4], m5 + mova [r0+r1], m6 + RET + +%macro TRANSPOSE4X4 2 + movd m0, [%1] + movd m1, [%1+r1] + movd m2, [%1+r1*2] + movd m3, [%1+r3] + punpcklbw m0, m1 + punpcklbw m2, m3 + mova m1, m0 + punpcklwd m0, m2 + punpckhwd m1, m2 + movd [%2+ 0], m0 + punpckhdq m0, m0 + movd [%2+ 8], m0 + movd [%2+16], m1 + punpckhdq m1, m1 + movd [%2+24], m1 +%endmacro + + +; void h263_h_loop_filter(uint8_t *src, int stride, int qscale) +INIT_MMX mmx +cglobal h263_h_loop_filter, 3,5,0,32 + movsxdifnidn r1, r1d + movsxdifnidn r2, r2d + + lea r4, [h263_loop_filter_strength] + movzx r3d, BYTE [r4+r2] + movsx r2, r3b + shl r2, 1 + + sub r0, 2 + lea r3, [r1*3] + + TRANSPOSE4X4 r0, rsp + lea r4, [r0+r1*4] + TRANSPOSE4X4 r4, rsp+4 + + H263_LOOP_FILTER rsp, rsp+8, rsp+16, rsp+24, r2d + + mova m1, m5 + mova m0, m4 + punpcklbw m5, m3 + punpcklbw m4, m6 + punpckhbw m1, m3 + punpckhbw m0, m6 + mova m3, m5 + mova m6, m1 + punpcklwd m5, m4 + punpcklwd m1, m0 + punpckhwd m3, m4 + punpckhwd m6, m0 + movd [r0], m5 + punpckhdq m5, m5 + movd [r0+r1*1], m5 + movd [r0+r1*2], m3 + punpckhdq m3, m3 + movd [r0+r3], m3 + movd [r4], m1 + punpckhdq m1, m1 + movd [r4+r1*1], m1 + movd [r4+r1*2], m6 + punpckhdq m6, m6 + movd [r4+r3], m6 + RET diff --git a/ffmpeg/libavcodec/x86/h264_chromamc.asm b/ffmpeg/libavcodec/x86/h264_chromamc.asm new file mode 100644 index 0000000..32681aa --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_chromamc.asm @@ -0,0 +1,678 @@ +;****************************************************************************** +;* MMX/SSSE3-optimized functions for H264 chroma MC +;* Copyright (c) 2005 Zoltan Hidvegi , +;* 2005-2008 Loren Merritt +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +rnd_rv40_2d_tbl: times 4 dw 0 + times 4 dw 16 + times 4 dw 32 + times 4 dw 16 + times 4 dw 32 + times 4 dw 28 + times 4 dw 32 + times 4 dw 28 + times 4 dw 0 + times 4 dw 32 + times 4 dw 16 + times 4 dw 32 + times 4 dw 32 + times 4 dw 28 + times 4 dw 32 + times 4 dw 28 +rnd_rv40_1d_tbl: times 4 dw 0 + times 4 dw 2 + times 4 dw 4 + times 4 dw 2 + times 4 dw 4 + times 4 dw 3 + times 4 dw 4 + times 4 dw 3 + times 4 dw 0 + times 4 dw 4 + times 4 dw 2 + times 4 dw 4 + times 4 dw 4 + times 4 dw 3 + times 4 dw 4 + times 4 dw 3 + +cextern pw_3 +cextern pw_4 +cextern pw_8 +pw_28: times 8 dw 28 +cextern pw_32 +cextern pw_64 + +SECTION .text + +%macro mv0_pixels_mc8 0 + lea r4, [r2*2 ] +.next4rows: + movq mm0, [r1 ] + movq mm1, [r1+r2] + add r1, r4 + CHROMAMC_AVG mm0, [r0 ] + CHROMAMC_AVG mm1, [r0+r2] + movq [r0 ], mm0 + movq [r0+r2], mm1 + add r0, r4 + movq mm0, [r1 ] + movq mm1, [r1+r2] + add r1, r4 + CHROMAMC_AVG mm0, [r0 ] + CHROMAMC_AVG mm1, [r0+r2] + movq [r0 ], mm0 + movq [r0+r2], mm1 + add r0, r4 + sub r3d, 4 + jne .next4rows +%endmacro + +%macro chroma_mc8_mmx_func 2-3 +%ifidn %2, rv40 +%ifdef PIC +%define rnd_1d_rv40 r8 +%define rnd_2d_rv40 r8 +%define extra_regs 2 +%else ; no-PIC +%define rnd_1d_rv40 rnd_rv40_1d_tbl +%define rnd_2d_rv40 rnd_rv40_2d_tbl +%define extra_regs 1 +%endif ; PIC +%else +%define extra_regs 0 +%endif ; rv40 +; put/avg_h264_chroma_mc8_*(uint8_t *dst /*align 8*/, uint8_t *src /*align 1*/, +; int stride, int h, int mx, int my) +cglobal %1_%2_chroma_mc8%3, 6, 7 + extra_regs, 0 +%if ARCH_X86_64 + movsxd r2, r2d +%endif + mov r6d, r5d + or r6d, r4d + jne .at_least_one_non_zero + ; mx == 0 AND my == 0 - no filter needed + mv0_pixels_mc8 + REP_RET + +.at_least_one_non_zero: +%ifidn %2, rv40 +%if ARCH_X86_64 + mov r7, r5 + and r7, 6 ; &~1 for mx/my=[0,7] + lea r7, [r7*4+r4] + sar r7d, 1 +%define rnd_bias r7 +%define dest_reg r0 +%else ; x86-32 + mov r0, r5 + and r0, 6 ; &~1 for mx/my=[0,7] + lea r0, [r0*4+r4] + sar r0d, 1 +%define rnd_bias r0 +%define dest_reg r5 +%endif +%else ; vc1, h264 +%define rnd_bias 0 +%define dest_reg r0 +%endif + + test r5d, r5d + mov r6, 1 + je .my_is_zero + test r4d, r4d + mov r6, r2 ; dxy = x ? 1 : stride + jne .both_non_zero +.my_is_zero: + ; mx == 0 XOR my == 0 - 1 dimensional filter only + or r4d, r5d ; x + y + +%ifidn %2, rv40 +%ifdef PIC + lea r8, [rnd_rv40_1d_tbl] +%endif +%if ARCH_X86_64 == 0 + mov r5, r0m +%endif +%endif + + movd m5, r4d + movq m4, [pw_8] + movq m6, [rnd_1d_%2+rnd_bias*8] ; mm6 = rnd >> 3 + punpcklwd m5, m5 + punpckldq m5, m5 ; mm5 = B = x + pxor m7, m7 + psubw m4, m5 ; mm4 = A = 8-x + +.next1drow: + movq m0, [r1 ] ; mm0 = src[0..7] + movq m2, [r1+r6] ; mm1 = src[1..8] + + movq m1, m0 + movq m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + pmullw m0, m4 ; [mm0,mm1] = A * src[0..7] + pmullw m1, m4 + pmullw m2, m5 ; [mm2,mm3] = B * src[1..8] + pmullw m3, m5 + + paddw m0, m6 + paddw m1, m6 + paddw m0, m2 + paddw m1, m3 + psrlw m0, 3 + psrlw m1, 3 + packuswb m0, m1 + CHROMAMC_AVG m0, [dest_reg] + movq [dest_reg], m0 ; dst[0..7] = (A * src[0..7] + B * src[1..8] + (rnd >> 3)) >> 3 + + add dest_reg, r2 + add r1, r2 + dec r3d + jne .next1drow + REP_RET + +.both_non_zero: ; general case, bilinear + movd m4, r4d ; x + movd m6, r5d ; y +%ifidn %2, rv40 +%ifdef PIC + lea r8, [rnd_rv40_2d_tbl] +%endif +%if ARCH_X86_64 == 0 + mov r5, r0m +%endif +%endif + mov r6, rsp ; backup stack pointer + and rsp, ~(mmsize-1) ; align stack + sub rsp, 16 ; AA and DD + + punpcklwd m4, m4 + punpcklwd m6, m6 + punpckldq m4, m4 ; mm4 = x words + punpckldq m6, m6 ; mm6 = y words + movq m5, m4 + pmullw m4, m6 ; mm4 = x * y + psllw m5, 3 + psllw m6, 3 + movq m7, m5 + paddw m7, m6 + movq [rsp+8], m4 ; DD = x * y + psubw m5, m4 ; mm5 = B = 8x - xy + psubw m6, m4 ; mm6 = C = 8y - xy + paddw m4, [pw_64] + psubw m4, m7 ; mm4 = A = xy - (8x+8y) + 64 + pxor m7, m7 + movq [rsp ], m4 + + movq m0, [r1 ] ; mm0 = src[0..7] + movq m1, [r1+1] ; mm1 = src[1..8] +.next2drow: + add r1, r2 + + movq m2, m0 + movq m3, m1 + punpckhbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + pmullw m0, [rsp] + pmullw m2, [rsp] + pmullw m1, m5 + pmullw m3, m5 + paddw m2, m1 ; mm2 = A * src[0..3] + B * src[1..4] + paddw m3, m0 ; mm3 = A * src[4..7] + B * src[5..8] + + movq m0, [r1] + movq m1, m0 + punpcklbw m0, m7 + punpckhbw m1, m7 + pmullw m0, m6 + pmullw m1, m6 + paddw m2, m0 + paddw m3, m1 ; [mm2,mm3] += C * src[0..7] + + movq m1, [r1+1] + movq m0, m1 + movq m4, m1 + punpcklbw m0, m7 + punpckhbw m4, m7 + pmullw m0, [rsp+8] + pmullw m4, [rsp+8] + paddw m2, m0 + paddw m3, m4 ; [mm2,mm3] += D * src[1..8] + movq m0, [r1] + + paddw m2, [rnd_2d_%2+rnd_bias*8] + paddw m3, [rnd_2d_%2+rnd_bias*8] + psrlw m2, 6 + psrlw m3, 6 + packuswb m2, m3 + CHROMAMC_AVG m2, [dest_reg] + movq [dest_reg], m2 ; dst[0..7] = ([mm2,mm3] + rnd) >> 6 + + add dest_reg, r2 + dec r3d + jne .next2drow + mov rsp, r6 ; restore stack pointer + RET +%endmacro + +%macro chroma_mc4_mmx_func 2 +%define extra_regs 0 +%ifidn %2, rv40 +%ifdef PIC +%define extra_regs 1 +%endif ; PIC +%endif ; rv40 +cglobal %1_%2_chroma_mc4, 6, 6 + extra_regs, 0 +%if ARCH_X86_64 + movsxd r2, r2d +%endif + pxor m7, m7 + movd m2, r4d ; x + movd m3, r5d ; y + movq m4, [pw_8] + movq m5, [pw_8] + punpcklwd m2, m2 + punpcklwd m3, m3 + punpcklwd m2, m2 + punpcklwd m3, m3 + psubw m4, m2 + psubw m5, m3 + +%ifidn %2, rv40 +%ifdef PIC + lea r6, [rnd_rv40_2d_tbl] +%define rnd_2d_rv40 r6 +%else +%define rnd_2d_rv40 rnd_rv40_2d_tbl +%endif + and r5, 6 ; &~1 for mx/my=[0,7] + lea r5, [r5*4+r4] + sar r5d, 1 +%define rnd_bias r5 +%else ; vc1, h264 +%define rnd_bias 0 +%endif + + movd m0, [r1 ] + movd m6, [r1+1] + add r1, r2 + punpcklbw m0, m7 + punpcklbw m6, m7 + pmullw m0, m4 + pmullw m6, m2 + paddw m6, m0 + +.next2rows: + movd m0, [r1 ] + movd m1, [r1+1] + add r1, r2 + punpcklbw m0, m7 + punpcklbw m1, m7 + pmullw m0, m4 + pmullw m1, m2 + paddw m1, m0 + movq m0, m1 + + pmullw m6, m5 + pmullw m1, m3 + paddw m6, [rnd_2d_%2+rnd_bias*8] + paddw m1, m6 + psrlw m1, 6 + packuswb m1, m1 + CHROMAMC_AVG4 m1, m6, [r0] + movd [r0], m1 + add r0, r2 + + movd m6, [r1 ] + movd m1, [r1+1] + add r1, r2 + punpcklbw m6, m7 + punpcklbw m1, m7 + pmullw m6, m4 + pmullw m1, m2 + paddw m1, m6 + movq m6, m1 + pmullw m0, m5 + pmullw m1, m3 + paddw m0, [rnd_2d_%2+rnd_bias*8] + paddw m1, m0 + psrlw m1, 6 + packuswb m1, m1 + CHROMAMC_AVG4 m1, m0, [r0] + movd [r0], m1 + add r0, r2 + sub r3d, 2 + jnz .next2rows + REP_RET +%endmacro + +%macro chroma_mc2_mmx_func 2 +cglobal %1_%2_chroma_mc2, 6, 7, 0 +%if ARCH_X86_64 + movsxd r2, r2d +%endif + + mov r6d, r4d + shl r4d, 16 + sub r4d, r6d + add r4d, 8 + imul r5d, r4d ; x*y<<16 | y*(8-x) + shl r4d, 3 + sub r4d, r5d ; x*(8-y)<<16 | (8-x)*(8-y) + + movd m5, r4d + movd m6, r5d + punpckldq m5, m5 ; mm5 = {A,B,A,B} + punpckldq m6, m6 ; mm6 = {C,D,C,D} + pxor m7, m7 + movd m2, [r1] + punpcklbw m2, m7 + pshufw m2, m2, 0x94 ; mm0 = src[0,1,1,2] + +.nextrow: + add r1, r2 + movq m1, m2 + pmaddwd m1, m5 ; mm1 = A * src[0,1] + B * src[1,2] + movd m0, [r1] + punpcklbw m0, m7 + pshufw m0, m0, 0x94 ; mm0 = src[0,1,1,2] + movq m2, m0 + pmaddwd m0, m6 + paddw m1, [rnd_2d_%2] + paddw m1, m0 ; mm1 += C * src[0,1] + D * src[1,2] + psrlw m1, 6 + packssdw m1, m7 + packuswb m1, m7 + CHROMAMC_AVG4 m1, m3, [r0] + movd r5d, m1 + mov [r0], r5w + add r0, r2 + sub r3d, 1 + jnz .nextrow + REP_RET +%endmacro + +%define rnd_1d_h264 pw_4 +%define rnd_2d_h264 pw_32 +%define rnd_1d_vc1 pw_3 +%define rnd_2d_vc1 pw_28 + +%macro NOTHING 2-3 +%endmacro +%macro DIRECT_AVG 2 + PAVGB %1, %2 +%endmacro +%macro COPY_AVG 3 + movd %2, %3 + PAVGB %1, %2 +%endmacro + +INIT_MMX mmx +%define CHROMAMC_AVG NOTHING +%define CHROMAMC_AVG4 NOTHING +chroma_mc8_mmx_func put, h264, _rnd +chroma_mc8_mmx_func put, vc1, _nornd +chroma_mc8_mmx_func put, rv40 +chroma_mc4_mmx_func put, h264 +chroma_mc4_mmx_func put, rv40 + +INIT_MMX mmxext +chroma_mc2_mmx_func put, h264 + +%define CHROMAMC_AVG DIRECT_AVG +%define CHROMAMC_AVG4 COPY_AVG +chroma_mc8_mmx_func avg, h264, _rnd +chroma_mc8_mmx_func avg, vc1, _nornd +chroma_mc8_mmx_func avg, rv40 +chroma_mc4_mmx_func avg, h264 +chroma_mc4_mmx_func avg, rv40 +chroma_mc2_mmx_func avg, h264 + +INIT_MMX 3dnow +chroma_mc8_mmx_func avg, h264, _rnd +chroma_mc8_mmx_func avg, vc1, _nornd +chroma_mc8_mmx_func avg, rv40 +chroma_mc4_mmx_func avg, h264 +chroma_mc4_mmx_func avg, rv40 + +%macro chroma_mc8_ssse3_func 2-3 +cglobal %1_%2_chroma_mc8%3, 6, 7, 8 +%if ARCH_X86_64 + movsxd r2, r2d +%endif + mov r6d, r5d + or r6d, r4d + jne .at_least_one_non_zero + ; mx == 0 AND my == 0 - no filter needed + mv0_pixels_mc8 + REP_RET + +.at_least_one_non_zero: + test r5d, r5d + je .my_is_zero + test r4d, r4d + je .mx_is_zero + + ; general case, bilinear + mov r6d, r4d + shl r4d, 8 + sub r4, r6 + mov r6, 8 + add r4, 8 ; x*288+8 = x<<8 | (8-x) + sub r6d, r5d + imul r6, r4 ; (8-y)*(x*255+8) = (8-y)*x<<8 | (8-y)*(8-x) + imul r4d, r5d ; y *(x*255+8) = y *x<<8 | y *(8-x) + + movd m7, r6d + movd m6, r4d + movdqa m5, [rnd_2d_%2] + movq m0, [r1 ] + movq m1, [r1+1] + pshuflw m7, m7, 0 + pshuflw m6, m6, 0 + punpcklbw m0, m1 + movlhps m7, m7 + movlhps m6, m6 + +.next2rows: + movq m1, [r1+r2*1 ] + movq m2, [r1+r2*1+1] + movq m3, [r1+r2*2 ] + movq m4, [r1+r2*2+1] + lea r1, [r1+r2*2] + punpcklbw m1, m2 + movdqa m2, m1 + punpcklbw m3, m4 + movdqa m4, m3 + pmaddubsw m0, m7 + pmaddubsw m1, m6 + pmaddubsw m2, m7 + pmaddubsw m3, m6 + paddw m0, m5 + paddw m2, m5 + paddw m1, m0 + paddw m3, m2 + psrlw m1, 6 + movdqa m0, m4 + psrlw m3, 6 +%ifidn %1, avg + movq m2, [r0 ] + movhps m2, [r0+r2] +%endif + packuswb m1, m3 + CHROMAMC_AVG m1, m2 + movq [r0 ], m1 + movhps [r0+r2], m1 + sub r3d, 2 + lea r0, [r0+r2*2] + jg .next2rows + REP_RET + +.my_is_zero: + mov r5d, r4d + shl r4d, 8 + add r4, 8 + sub r4, r5 ; 255*x+8 = x<<8 | (8-x) + movd m7, r4d + movdqa m6, [rnd_1d_%2] + pshuflw m7, m7, 0 + movlhps m7, m7 + +.next2xrows: + movq m0, [r1 ] + movq m1, [r1 +1] + movq m2, [r1+r2 ] + movq m3, [r1+r2+1] + punpcklbw m0, m1 + punpcklbw m2, m3 + pmaddubsw m0, m7 + pmaddubsw m2, m7 +%ifidn %1, avg + movq m4, [r0 ] + movhps m4, [r0+r2] +%endif + paddw m0, m6 + paddw m2, m6 + psrlw m0, 3 + psrlw m2, 3 + packuswb m0, m2 + CHROMAMC_AVG m0, m4 + movq [r0 ], m0 + movhps [r0+r2], m0 + sub r3d, 2 + lea r0, [r0+r2*2] + lea r1, [r1+r2*2] + jg .next2xrows + REP_RET + +.mx_is_zero: + mov r4d, r5d + shl r5d, 8 + add r5, 8 + sub r5, r4 ; 255*y+8 = y<<8 | (8-y) + movd m7, r5d + movdqa m6, [rnd_1d_%2] + pshuflw m7, m7, 0 + movlhps m7, m7 + +.next2yrows: + movq m0, [r1 ] + movq m1, [r1+r2 ] + movdqa m2, m1 + movq m3, [r1+r2*2] + lea r1, [r1+r2*2] + punpcklbw m0, m1 + punpcklbw m2, m3 + pmaddubsw m0, m7 + pmaddubsw m2, m7 +%ifidn %1, avg + movq m4, [r0 ] + movhps m4, [r0+r2] +%endif + paddw m0, m6 + paddw m2, m6 + psrlw m0, 3 + psrlw m2, 3 + packuswb m0, m2 + CHROMAMC_AVG m0, m4 + movq [r0 ], m0 + movhps [r0+r2], m0 + sub r3d, 2 + lea r0, [r0+r2*2] + jg .next2yrows + REP_RET +%endmacro + +%macro chroma_mc4_ssse3_func 2 +cglobal %1_%2_chroma_mc4, 6, 7, 0 +%if ARCH_X86_64 + movsxd r2, r2d +%endif + mov r6, r4 + shl r4d, 8 + sub r4d, r6d + mov r6, 8 + add r4d, 8 ; x*288+8 + sub r6d, r5d + imul r6d, r4d ; (8-y)*(x*255+8) = (8-y)*x<<8 | (8-y)*(8-x) + imul r4d, r5d ; y *(x*255+8) = y *x<<8 | y *(8-x) + + movd m7, r6d + movd m6, r4d + movq m5, [pw_32] + movd m0, [r1 ] + pshufw m7, m7, 0 + punpcklbw m0, [r1+1] + pshufw m6, m6, 0 + +.next2rows: + movd m1, [r1+r2*1 ] + movd m3, [r1+r2*2 ] + punpcklbw m1, [r1+r2*1+1] + punpcklbw m3, [r1+r2*2+1] + lea r1, [r1+r2*2] + movq m2, m1 + movq m4, m3 + pmaddubsw m0, m7 + pmaddubsw m1, m6 + pmaddubsw m2, m7 + pmaddubsw m3, m6 + paddw m0, m5 + paddw m2, m5 + paddw m1, m0 + paddw m3, m2 + psrlw m1, 6 + movq m0, m4 + psrlw m3, 6 + packuswb m1, m1 + packuswb m3, m3 + CHROMAMC_AVG m1, [r0 ] + CHROMAMC_AVG m3, [r0+r2] + movd [r0 ], m1 + movd [r0+r2], m3 + sub r3d, 2 + lea r0, [r0+r2*2] + jg .next2rows + REP_RET +%endmacro + +%define CHROMAMC_AVG NOTHING +INIT_XMM ssse3 +chroma_mc8_ssse3_func put, h264, _rnd +chroma_mc8_ssse3_func put, vc1, _nornd +INIT_MMX ssse3 +chroma_mc4_ssse3_func put, h264 + +%define CHROMAMC_AVG DIRECT_AVG +INIT_XMM ssse3 +chroma_mc8_ssse3_func avg, h264, _rnd +chroma_mc8_ssse3_func avg, vc1, _nornd +INIT_MMX ssse3 +chroma_mc4_ssse3_func avg, h264 diff --git a/ffmpeg/libavcodec/x86/h264_chromamc_10bit.asm b/ffmpeg/libavcodec/x86/h264_chromamc_10bit.asm new file mode 100644 index 0000000..b850551 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_chromamc_10bit.asm @@ -0,0 +1,271 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 chroma MC code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Daniel Kang +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_4 +cextern pw_8 +cextern pw_32 +cextern pw_64 + +SECTION .text + + +%macro MV0_PIXELS_MC8 0 + lea r4, [r2*3 ] + lea r5, [r2*4 ] +.next4rows: + movu m0, [r1 ] + movu m1, [r1+r2 ] + CHROMAMC_AVG m0, [r0 ] + CHROMAMC_AVG m1, [r0+r2 ] + mova [r0 ], m0 + mova [r0+r2 ], m1 + movu m0, [r1+r2*2] + movu m1, [r1+r4 ] + CHROMAMC_AVG m0, [r0+r2*2] + CHROMAMC_AVG m1, [r0+r4 ] + mova [r0+r2*2], m0 + mova [r0+r4 ], m1 + add r1, r5 + add r0, r5 + sub r3d, 4 + jne .next4rows +%endmacro + +;----------------------------------------------------------------------------- +; void put/avg_h264_chroma_mc8(pixel *dst, pixel *src, int stride, int h, int mx, int my) +;----------------------------------------------------------------------------- +%macro CHROMA_MC8 1 +; put/avg_h264_chroma_mc8_*(uint8_t *dst /*align 8*/, uint8_t *src /*align 1*/, +; int stride, int h, int mx, int my) +cglobal %1_h264_chroma_mc8_10, 6,7,8 + movsxdifnidn r2, r2d + mov r6d, r5d + or r6d, r4d + jne .at_least_one_non_zero + ; mx == 0 AND my == 0 - no filter needed + MV0_PIXELS_MC8 + REP_RET + +.at_least_one_non_zero: + mov r6d, 2 + test r5d, r5d + je .x_interpolation + mov r6, r2 ; dxy = x ? 1 : stride + test r4d, r4d + jne .xy_interpolation +.x_interpolation: + ; mx == 0 XOR my == 0 - 1 dimensional filter only + or r4d, r5d ; x + y + movd m5, r4d + mova m4, [pw_8] + mova m6, [pw_4] ; mm6 = rnd >> 3 + SPLATW m5, m5 ; mm5 = B = x + psubw m4, m5 ; mm4 = A = 8-x + +.next1drow: + movu m0, [r1 ] ; mm0 = src[0..7] + movu m2, [r1+r6] ; mm2 = src[1..8] + + pmullw m0, m4 ; mm0 = A * src[0..7] + pmullw m2, m5 ; mm2 = B * src[1..8] + + paddw m0, m6 + paddw m0, m2 + psrlw m0, 3 + CHROMAMC_AVG m0, [r0] + mova [r0], m0 ; dst[0..7] = (A * src[0..7] + B * src[1..8] + (rnd >> 3)) >> 3 + + add r0, r2 + add r1, r2 + dec r3d + jne .next1drow + REP_RET + +.xy_interpolation: ; general case, bilinear + movd m4, r4m ; x + movd m6, r5m ; y + + SPLATW m4, m4 ; mm4 = x words + SPLATW m6, m6 ; mm6 = y words + psllw m5, m4, 3 ; mm5 = 8x + pmullw m4, m6 ; mm4 = x * y + psllw m6, 3 ; mm6 = 8y + paddw m1, m5, m6 ; mm7 = 8x+8y + mova m7, m4 ; DD = x * y + psubw m5, m4 ; mm5 = B = 8x - xy + psubw m6, m4 ; mm6 = C = 8y - xy + paddw m4, [pw_64] + psubw m4, m1 ; mm4 = A = xy - (8x+8y) + 64 + + movu m0, [r1 ] ; mm0 = src[0..7] + movu m1, [r1+2] ; mm1 = src[1..8] +.next2drow: + add r1, r2 + + pmullw m2, m0, m4 + pmullw m1, m5 + paddw m2, m1 ; mm2 = A * src[0..7] + B * src[1..8] + + movu m0, [r1] + movu m1, [r1+2] + pmullw m3, m0, m6 + paddw m2, m3 ; mm2 += C * src[0..7+strde] + pmullw m3, m1, m7 + paddw m2, m3 ; mm2 += D * src[1..8+strde] + + paddw m2, [pw_32] + psrlw m2, 6 + CHROMAMC_AVG m2, [r0] + mova [r0], m2 ; dst[0..7] = (mm2 + 32) >> 6 + + add r0, r2 + dec r3d + jne .next2drow + REP_RET +%endmacro + +;----------------------------------------------------------------------------- +; void put/avg_h264_chroma_mc4(pixel *dst, pixel *src, int stride, int h, int mx, int my) +;----------------------------------------------------------------------------- +;TODO: xmm mc4 +%macro MC4_OP 2 + movq %1, [r1 ] + movq m1, [r1+2] + add r1, r2 + pmullw %1, m4 + pmullw m1, m2 + paddw m1, %1 + mova %1, m1 + + pmullw %2, m5 + pmullw m1, m3 + paddw %2, [pw_32] + paddw m1, %2 + psrlw m1, 6 + CHROMAMC_AVG m1, %2, [r0] + movq [r0], m1 + add r0, r2 +%endmacro + +%macro CHROMA_MC4 1 +cglobal %1_h264_chroma_mc4_10, 6,6,7 + movsxdifnidn r2, r2d + movd m2, r4m ; x + movd m3, r5m ; y + mova m4, [pw_8] + mova m5, m4 + SPLATW m2, m2 + SPLATW m3, m3 + psubw m4, m2 + psubw m5, m3 + + movq m0, [r1 ] + movq m6, [r1+2] + add r1, r2 + pmullw m0, m4 + pmullw m6, m2 + paddw m6, m0 + +.next2rows: + MC4_OP m0, m6 + MC4_OP m6, m0 + sub r3d, 2 + jnz .next2rows + REP_RET +%endmacro + +;----------------------------------------------------------------------------- +; void put/avg_h264_chroma_mc2(pixel *dst, pixel *src, int stride, int h, int mx, int my) +;----------------------------------------------------------------------------- +%macro CHROMA_MC2 1 +cglobal %1_h264_chroma_mc2_10, 6,7 + movsxdifnidn r2, r2d + mov r6d, r4d + shl r4d, 16 + sub r4d, r6d + add r4d, 8 + imul r5d, r4d ; x*y<<16 | y*(8-x) + shl r4d, 3 + sub r4d, r5d ; x*(8-y)<<16 | (8-x)*(8-y) + + movd m5, r4d + movd m6, r5d + punpckldq m5, m5 ; mm5 = {A,B,A,B} + punpckldq m6, m6 ; mm6 = {C,D,C,D} + pxor m7, m7 + pshufw m2, [r1], 0x94 ; mm0 = src[0,1,1,2] + +.nextrow: + add r1, r2 + movq m1, m2 + pmaddwd m1, m5 ; mm1 = A * src[0,1] + B * src[1,2] + pshufw m0, [r1], 0x94 ; mm0 = src[0,1,1,2] + movq m2, m0 + pmaddwd m0, m6 + paddw m1, [pw_32] + paddw m1, m0 ; mm1 += C * src[0,1] + D * src[1,2] + psrlw m1, 6 + packssdw m1, m7 + CHROMAMC_AVG m1, m3, [r0] + movd [r0], m1 + add r0, r2 + dec r3d + jnz .nextrow + REP_RET +%endmacro + +%macro NOTHING 2-3 +%endmacro +%macro AVG 2-3 +%if %0==3 + movq %2, %3 +%endif + pavgw %1, %2 +%endmacro + +%define CHROMAMC_AVG NOTHING +INIT_XMM sse2 +CHROMA_MC8 put +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +CHROMA_MC8 put +%endif +INIT_MMX mmxext +CHROMA_MC4 put +CHROMA_MC2 put + +%define CHROMAMC_AVG AVG +INIT_XMM sse2 +CHROMA_MC8 avg +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +CHROMA_MC8 avg +%endif +INIT_MMX mmxext +CHROMA_MC4 avg +CHROMA_MC2 avg diff --git a/ffmpeg/libavcodec/x86/h264_deblock.asm b/ffmpeg/libavcodec/x86/h264_deblock.asm new file mode 100644 index 0000000..d58e16c --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_deblock.asm @@ -0,0 +1,1083 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized H.264 deblocking code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Loren Merritt +;* Jason Garrett-Glaser +;* Oskar Arvidsson +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pb_A1: times 16 db 0xA1 +pb_3_1: times 4 db 3, 1 + +SECTION .text + +cextern pb_0 +cextern pb_1 +cextern pb_3 + +; expands to [base],...,[base+7*stride] +%define PASS8ROWS(base, base3, stride, stride3) \ + [base], [base+stride], [base+stride*2], [base3], \ + [base3+stride], [base3+stride*2], [base3+stride3], [base3+stride*4] + +%define PASS8ROWS(base, base3, stride, stride3, offset) \ + PASS8ROWS(base+offset, base3+offset, stride, stride3) + +; in: 8 rows of 4 bytes in %4..%11 +; out: 4 rows of 8 bytes in m0..m3 +%macro TRANSPOSE4x8_LOAD 11 + movh m0, %4 + movh m2, %5 + movh m1, %6 + movh m3, %7 + punpckl%1 m0, m2 + punpckl%1 m1, m3 + mova m2, m0 + punpckl%2 m0, m1 + punpckh%2 m2, m1 + + movh m4, %8 + movh m6, %9 + movh m5, %10 + movh m7, %11 + punpckl%1 m4, m6 + punpckl%1 m5, m7 + mova m6, m4 + punpckl%2 m4, m5 + punpckh%2 m6, m5 + + punpckh%3 m1, m0, m4 + punpckh%3 m3, m2, m6 + punpckl%3 m0, m4 + punpckl%3 m2, m6 +%endmacro + +; in: 4 rows of 8 bytes in m0..m3 +; out: 8 rows of 4 bytes in %1..%8 +%macro TRANSPOSE8x4B_STORE 8 + punpckhdq m4, m0, m0 + punpckhdq m5, m1, m1 + punpckhdq m6, m2, m2 + + punpcklbw m0, m1 + punpcklbw m2, m3 + punpcklwd m1, m0, m2 + punpckhwd m0, m2 + movh %1, m1 + punpckhdq m1, m1 + movh %2, m1 + movh %3, m0 + punpckhdq m0, m0 + movh %4, m0 + + punpckhdq m3, m3 + punpcklbw m4, m5 + punpcklbw m6, m3 + punpcklwd m5, m4, m6 + punpckhwd m4, m6 + movh %5, m5 + punpckhdq m5, m5 + movh %6, m5 + movh %7, m4 + punpckhdq m4, m4 + movh %8, m4 +%endmacro + +%macro TRANSPOSE4x8B_LOAD 8 + TRANSPOSE4x8_LOAD bw, wd, dq, %1, %2, %3, %4, %5, %6, %7, %8 +%endmacro + +%macro SBUTTERFLY3 4 + punpckh%1 %4, %2, %3 + punpckl%1 %2, %3 +%endmacro + +; in: 8 rows of 8 (only the middle 6 pels are used) in %1..%8 +; out: 6 rows of 8 in [%9+0*16] .. [%9+5*16] +%macro TRANSPOSE6x8_MEM 9 + RESET_MM_PERMUTATION + movq m0, %1 + movq m1, %2 + movq m2, %3 + movq m3, %4 + movq m4, %5 + movq m5, %6 + movq m6, %7 + SBUTTERFLY bw, 0, 1, 7 + SBUTTERFLY bw, 2, 3, 7 + SBUTTERFLY bw, 4, 5, 7 + movq [%9+0x10], m3 + SBUTTERFLY3 bw, m6, %8, m7 + SBUTTERFLY wd, 0, 2, 3 + SBUTTERFLY wd, 4, 6, 3 + punpckhdq m0, m4 + movq [%9+0x00], m0 + SBUTTERFLY3 wd, m1, [%9+0x10], m3 + SBUTTERFLY wd, 5, 7, 0 + SBUTTERFLY dq, 1, 5, 0 + SBUTTERFLY dq, 2, 6, 0 + punpckldq m3, m7 + movq [%9+0x10], m2 + movq [%9+0x20], m6 + movq [%9+0x30], m1 + movq [%9+0x40], m5 + movq [%9+0x50], m3 + RESET_MM_PERMUTATION +%endmacro + +; in: 8 rows of 8 in %1..%8 +; out: 8 rows of 8 in %9..%16 +%macro TRANSPOSE8x8_MEM 16 + RESET_MM_PERMUTATION + movq m0, %1 + movq m1, %2 + movq m2, %3 + movq m3, %4 + movq m4, %5 + movq m5, %6 + movq m6, %7 + SBUTTERFLY bw, 0, 1, 7 + SBUTTERFLY bw, 2, 3, 7 + SBUTTERFLY bw, 4, 5, 7 + SBUTTERFLY3 bw, m6, %8, m7 + movq %9, m5 + SBUTTERFLY wd, 0, 2, 5 + SBUTTERFLY wd, 4, 6, 5 + SBUTTERFLY wd, 1, 3, 5 + movq %11, m6 + movq m6, %9 + SBUTTERFLY wd, 6, 7, 5 + SBUTTERFLY dq, 0, 4, 5 + SBUTTERFLY dq, 1, 6, 5 + movq %9, m0 + movq %10, m4 + movq %13, m1 + movq %14, m6 + SBUTTERFLY3 dq, m2, %11, m0 + SBUTTERFLY dq, 3, 7, 4 + movq %11, m2 + movq %12, m0 + movq %15, m3 + movq %16, m7 + RESET_MM_PERMUTATION +%endmacro + +; out: %4 = |%1-%2|>%3 +; clobbers: %5 +%macro DIFF_GT 5 +%if avx_enabled == 0 + mova %5, %2 + mova %4, %1 + psubusb %5, %1 + psubusb %4, %2 +%else + psubusb %5, %2, %1 + psubusb %4, %1, %2 +%endif + por %4, %5 + psubusb %4, %3 +%endmacro + +; out: %4 = |%1-%2|>%3 +; clobbers: %5 +%macro DIFF_GT2 5 +%if ARCH_X86_64 + psubusb %5, %2, %1 + psubusb %4, %1, %2 +%else + mova %5, %2 + mova %4, %1 + psubusb %5, %1 + psubusb %4, %2 +%endif + psubusb %5, %3 + psubusb %4, %3 + pcmpeqb %4, %5 +%endmacro + +; in: m0=p1 m1=p0 m2=q0 m3=q1 %1=alpha-1 %2=beta-1 +; out: m5=beta-1, m7=mask, %3=alpha-1 +; clobbers: m4,m6 +%macro LOAD_MASK 2-3 + movd m4, %1 + movd m5, %2 + SPLATW m4, m4 + SPLATW m5, m5 + packuswb m4, m4 ; 16x alpha-1 + packuswb m5, m5 ; 16x beta-1 +%if %0>2 + mova %3, m4 +%endif + DIFF_GT m1, m2, m4, m7, m6 ; |p0-q0| > alpha-1 + DIFF_GT m0, m1, m5, m4, m6 ; |p1-p0| > beta-1 + por m7, m4 + DIFF_GT m3, m2, m5, m4, m6 ; |q1-q0| > beta-1 + por m7, m4 + pxor m6, m6 + pcmpeqb m7, m6 +%endmacro + +; in: m0=p1 m1=p0 m2=q0 m3=q1 m7=(tc&mask) +; out: m1=p0' m2=q0' +; clobbers: m0,3-6 +%macro DEBLOCK_P0_Q0 0 + pcmpeqb m4, m4 + pxor m5, m1, m2 ; p0^q0 + pxor m3, m4 + pand m5, [pb_1] ; (p0^q0)&1 + pavgb m3, m0 ; (p1 - q1 + 256)>>1 + pxor m4, m1 + pavgb m3, [pb_3] ; (((p1 - q1 + 256)>>1)+4)>>1 = 64+2+(p1-q1)>>2 + pavgb m4, m2 ; (q0 - p0 + 256)>>1 + pavgb m3, m5 + mova m6, [pb_A1] + paddusb m3, m4 ; d+128+33 + psubusb m6, m3 + psubusb m3, [pb_A1] + pminub m6, m7 + pminub m3, m7 + psubusb m1, m6 + psubusb m2, m3 + paddusb m1, m3 + paddusb m2, m6 +%endmacro + +; in: m1=p0 m2=q0 +; %1=p1 %2=q2 %3=[q2] %4=[q1] %5=tc0 %6=tmp +; out: [q1] = clip( (q2+((p0+q0+1)>>1))>>1, q1-tc0, q1+tc0 ) +; clobbers: q2, tmp, tc0 +%macro LUMA_Q1 6 + pavgb %6, m1, m2 + pavgb %2, %6 ; avg(p2,avg(p0,q0)) + pxor %6, %3 + pand %6, [pb_1] ; (p2^avg(p0,q0))&1 + psubusb %2, %6 ; (p2+((p0+q0+1)>>1))>>1 + psubusb %6, %1, %5 + paddusb %5, %1 + pmaxub %2, %6 + pminub %2, %5 + mova %4, %2 +%endmacro + +%if ARCH_X86_64 +;----------------------------------------------------------------------------- +; void deblock_v_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +%macro DEBLOCK_LUMA 0 +cglobal deblock_v_luma_8, 5,5,10 + movd m8, [r4] ; tc0 + lea r4, [r1*3] + dec r2d ; alpha-1 + neg r4 + dec r3d ; beta-1 + add r4, r0 ; pix-3*stride + + mova m0, [r4+r1] ; p1 + mova m1, [r4+2*r1] ; p0 + mova m2, [r0] ; q0 + mova m3, [r0+r1] ; q1 + LOAD_MASK r2d, r3d + + punpcklbw m8, m8 + punpcklbw m8, m8 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0] + pcmpeqb m9, m9 + pcmpeqb m9, m8 + pandn m9, m7 + pand m8, m9 + + movdqa m3, [r4] ; p2 + DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1 + pand m6, m9 + psubb m7, m8, m6 + pand m6, m8 + LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4 + + movdqa m4, [r0+2*r1] ; q2 + DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1 + pand m6, m9 + pand m8, m6 + psubb m7, m6 + mova m3, [r0+r1] + LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m8, m6 + + DEBLOCK_P0_Q0 + mova [r4+2*r1], m1 + mova [r0], m2 + RET + +;----------------------------------------------------------------------------- +; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +INIT_MMX cpuname +cglobal deblock_h_luma_8, 5,9 + movsxd r7, r1d + lea r8, [r7+r7*2] + lea r6, [r0-4] + lea r5, [r0-4+r8] +%if WIN64 + sub rsp, 0x98 + %define pix_tmp rsp+0x30 +%else + sub rsp, 0x68 + %define pix_tmp rsp +%endif + + ; transpose 6x16 -> tmp space + TRANSPOSE6x8_MEM PASS8ROWS(r6, r5, r7, r8), pix_tmp + lea r6, [r6+r7*8] + lea r5, [r5+r7*8] + TRANSPOSE6x8_MEM PASS8ROWS(r6, r5, r7, r8), pix_tmp+8 + + ; vertical filter + ; alpha, beta, tc0 are still in r2d, r3d, r4 + ; don't backup r6, r5, r7, r8 because deblock_v_luma_sse2 doesn't use them + lea r0, [pix_tmp+0x30] + mov r1d, 0x10 +%if WIN64 + mov [rsp+0x20], r4 +%endif + call deblock_v_luma_8 + + ; transpose 16x4 -> original space (only the middle 4 rows were changed by the filter) + add r6, 2 + add r5, 2 + movq m0, [pix_tmp+0x18] + movq m1, [pix_tmp+0x28] + movq m2, [pix_tmp+0x38] + movq m3, [pix_tmp+0x48] + TRANSPOSE8x4B_STORE PASS8ROWS(r6, r5, r7, r8) + + shl r7, 3 + sub r6, r7 + sub r5, r7 + shr r7, 3 + movq m0, [pix_tmp+0x10] + movq m1, [pix_tmp+0x20] + movq m2, [pix_tmp+0x30] + movq m3, [pix_tmp+0x40] + TRANSPOSE8x4B_STORE PASS8ROWS(r6, r5, r7, r8) + +%if WIN64 + add rsp, 0x98 +%else + add rsp, 0x68 +%endif + RET +%endmacro + +INIT_XMM sse2 +DEBLOCK_LUMA +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_LUMA +%endif + +%else + +%macro DEBLOCK_LUMA 2 +;----------------------------------------------------------------------------- +; void deblock_v8_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +cglobal deblock_%1_luma_8, 5,5,8,2*%2 + lea r4, [r1*3] + dec r2 ; alpha-1 + neg r4 + dec r3 ; beta-1 + add r4, r0 ; pix-3*stride + + mova m0, [r4+r1] ; p1 + mova m1, [r4+2*r1] ; p0 + mova m2, [r0] ; q0 + mova m3, [r0+r1] ; q1 + LOAD_MASK r2, r3 + + mov r3, r4mp + pcmpeqb m3, m3 + movd m4, [r3] ; tc0 + punpcklbw m4, m4 + punpcklbw m4, m4 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0] + mova [esp+%2], m4 ; tc + pcmpgtb m4, m3 + mova m3, [r4] ; p2 + pand m4, m7 + mova [esp], m4 ; mask + + DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1 + pand m6, m4 + pand m4, [esp+%2] ; tc + psubb m7, m4, m6 + pand m6, m4 + LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4 + + mova m4, [r0+2*r1] ; q2 + DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1 + pand m6, [esp] ; mask + mova m5, [esp+%2] ; tc + psubb m7, m6 + pand m5, m6 + mova m3, [r0+r1] + LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m5, m6 + + DEBLOCK_P0_Q0 + mova [r4+2*r1], m1 + mova [r0], m2 + RET + +;----------------------------------------------------------------------------- +; void deblock_h_luma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +INIT_MMX cpuname +cglobal deblock_h_luma_8, 0,5,8,0x60+HAVE_ALIGNED_STACK*12 + mov r0, r0mp + mov r3, r1m + lea r4, [r3*3] + sub r0, 4 + lea r1, [r0+r4] +%define pix_tmp esp+12*HAVE_ALIGNED_STACK + + ; transpose 6x16 -> tmp space + TRANSPOSE6x8_MEM PASS8ROWS(r0, r1, r3, r4), pix_tmp + lea r0, [r0+r3*8] + lea r1, [r1+r3*8] + TRANSPOSE6x8_MEM PASS8ROWS(r0, r1, r3, r4), pix_tmp+8 + + ; vertical filter + lea r0, [pix_tmp+0x30] + PUSH dword r4m + PUSH dword r3m + PUSH dword r2m + PUSH dword 16 + PUSH dword r0 + call deblock_%1_luma_8 +%ifidn %1, v8 + add dword [esp ], 8 ; pix_tmp+0x38 + add dword [esp+16], 2 ; tc0+2 + call deblock_%1_luma_8 +%endif + ADD esp, 20 + + ; transpose 16x4 -> original space (only the middle 4 rows were changed by the filter) + mov r0, r0mp + sub r0, 2 + + movq m0, [pix_tmp+0x10] + movq m1, [pix_tmp+0x20] + lea r1, [r0+r4] + movq m2, [pix_tmp+0x30] + movq m3, [pix_tmp+0x40] + TRANSPOSE8x4B_STORE PASS8ROWS(r0, r1, r3, r4) + + lea r0, [r0+r3*8] + lea r1, [r1+r3*8] + movq m0, [pix_tmp+0x18] + movq m1, [pix_tmp+0x28] + movq m2, [pix_tmp+0x38] + movq m3, [pix_tmp+0x48] + TRANSPOSE8x4B_STORE PASS8ROWS(r0, r1, r3, r4) + + RET +%endmacro ; DEBLOCK_LUMA + +INIT_MMX mmxext +DEBLOCK_LUMA v8, 8 +INIT_XMM sse2 +DEBLOCK_LUMA v, 16 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_LUMA v, 16 +%endif + +%endif ; ARCH + + + +%macro LUMA_INTRA_P012 4 ; p0..p3 in memory +%if ARCH_X86_64 + pavgb t0, p2, p1 + pavgb t1, p0, q0 +%else + mova t0, p2 + mova t1, p0 + pavgb t0, p1 + pavgb t1, q0 +%endif + pavgb t0, t1 ; ((p2+p1+1)/2 + (p0+q0+1)/2 + 1)/2 + mova t5, t1 +%if ARCH_X86_64 + paddb t2, p2, p1 + paddb t3, p0, q0 +%else + mova t2, p2 + mova t3, p0 + paddb t2, p1 + paddb t3, q0 +%endif + paddb t2, t3 + mova t3, t2 + mova t4, t2 + psrlw t2, 1 + pavgb t2, mpb_0 + pxor t2, t0 + pand t2, mpb_1 + psubb t0, t2 ; p1' = (p2+p1+p0+q0+2)/4; + +%if ARCH_X86_64 + pavgb t1, p2, q1 + psubb t2, p2, q1 +%else + mova t1, p2 + mova t2, p2 + pavgb t1, q1 + psubb t2, q1 +%endif + paddb t3, t3 + psubb t3, t2 ; p2+2*p1+2*p0+2*q0+q1 + pand t2, mpb_1 + psubb t1, t2 + pavgb t1, p1 + pavgb t1, t5 ; (((p2+q1)/2 + p1+1)/2 + (p0+q0+1)/2 + 1)/2 + psrlw t3, 2 + pavgb t3, mpb_0 + pxor t3, t1 + pand t3, mpb_1 + psubb t1, t3 ; p0'a = (p2+2*p1+2*p0+2*q0+q1+4)/8 + + pxor t3, p0, q1 + pavgb t2, p0, q1 + pand t3, mpb_1 + psubb t2, t3 + pavgb t2, p1 ; p0'b = (2*p1+p0+q0+2)/4 + + pxor t1, t2 + pxor t2, p0 + pand t1, mask1p + pand t2, mask0 + pxor t1, t2 + pxor t1, p0 + mova %1, t1 ; store p0 + + mova t1, %4 ; p3 + paddb t2, t1, p2 + pavgb t1, p2 + pavgb t1, t0 ; (p3+p2+1)/2 + (p2+p1+p0+q0+2)/4 + paddb t2, t2 + paddb t2, t4 ; 2*p3+3*p2+p1+p0+q0 + psrlw t2, 2 + pavgb t2, mpb_0 + pxor t2, t1 + pand t2, mpb_1 + psubb t1, t2 ; p2' = (2*p3+3*p2+p1+p0+q0+4)/8 + + pxor t0, p1 + pxor t1, p2 + pand t0, mask1p + pand t1, mask1p + pxor t0, p1 + pxor t1, p2 + mova %2, t0 ; store p1 + mova %3, t1 ; store p2 +%endmacro + +%macro LUMA_INTRA_SWAP_PQ 0 + %define q1 m0 + %define q0 m1 + %define p0 m2 + %define p1 m3 + %define p2 q2 + %define mask1p mask1q +%endmacro + +%macro DEBLOCK_LUMA_INTRA 1 + %define p1 m0 + %define p0 m1 + %define q0 m2 + %define q1 m3 + %define t0 m4 + %define t1 m5 + %define t2 m6 + %define t3 m7 +%if ARCH_X86_64 + %define p2 m8 + %define q2 m9 + %define t4 m10 + %define t5 m11 + %define mask0 m12 + %define mask1p m13 +%if WIN64 + %define mask1q [rsp] +%else + %define mask1q [rsp-24] +%endif + %define mpb_0 m14 + %define mpb_1 m15 +%else + %define spill(x) [esp+16*x] + %define p2 [r4+r1] + %define q2 [r0+2*r1] + %define t4 spill(0) + %define t5 spill(1) + %define mask0 spill(2) + %define mask1p spill(3) + %define mask1q spill(4) + %define mpb_0 [pb_0] + %define mpb_1 [pb_1] +%endif + +;----------------------------------------------------------------------------- +; void deblock_v_luma_intra( uint8_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +%if WIN64 +cglobal deblock_%1_luma_intra_8, 4,6,16,0x10 +%else +cglobal deblock_%1_luma_intra_8, 4,6,16,ARCH_X86_64*0x50-0x50 +%endif + lea r4, [r1*4] + lea r5, [r1*3] ; 3*stride + dec r2d ; alpha-1 + jl .end + neg r4 + dec r3d ; beta-1 + jl .end + add r4, r0 ; pix-4*stride + mova p1, [r4+2*r1] + mova p0, [r4+r5] + mova q0, [r0] + mova q1, [r0+r1] +%if ARCH_X86_64 + pxor mpb_0, mpb_0 + mova mpb_1, [pb_1] + LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0 + SWAP 7, 12 ; m12=mask0 + pavgb t5, mpb_0 + pavgb t5, mpb_1 ; alpha/4+1 + movdqa p2, [r4+r1] + movdqa q2, [r0+2*r1] + DIFF_GT2 p0, q0, t5, t0, t3 ; t0 = |p0-q0| > alpha/4+1 + DIFF_GT2 p0, p2, m5, t2, t5 ; mask1 = |p2-p0| > beta-1 + DIFF_GT2 q0, q2, m5, t4, t5 ; t4 = |q2-q0| > beta-1 + pand t0, mask0 + pand t4, t0 + pand t2, t0 + mova mask1q, t4 + mova mask1p, t2 +%else + LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0 + mova m4, t5 + mova mask0, m7 + pavgb m4, [pb_0] + pavgb m4, [pb_1] ; alpha/4+1 + DIFF_GT2 p0, q0, m4, m6, m7 ; m6 = |p0-q0| > alpha/4+1 + pand m6, mask0 + DIFF_GT2 p0, p2, m5, m4, m7 ; m4 = |p2-p0| > beta-1 + pand m4, m6 + mova mask1p, m4 + DIFF_GT2 q0, q2, m5, m4, m7 ; m4 = |q2-q0| > beta-1 + pand m4, m6 + mova mask1q, m4 +%endif + LUMA_INTRA_P012 [r4+r5], [r4+2*r1], [r4+r1], [r4] + LUMA_INTRA_SWAP_PQ + LUMA_INTRA_P012 [r0], [r0+r1], [r0+2*r1], [r0+r5] +.end: + RET + +INIT_MMX cpuname +%if ARCH_X86_64 +;----------------------------------------------------------------------------- +; void deblock_h_luma_intra( uint8_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_h_luma_intra_8, 4,9 + movsxd r7, r1d + lea r8, [r7*3] + lea r6, [r0-4] + lea r5, [r0-4+r8] + sub rsp, 0x88 + %define pix_tmp rsp + + ; transpose 8x16 -> tmp space + TRANSPOSE8x8_MEM PASS8ROWS(r6, r5, r7, r8), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30) + lea r6, [r6+r7*8] + lea r5, [r5+r7*8] + TRANSPOSE8x8_MEM PASS8ROWS(r6, r5, r7, r8), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30) + + lea r0, [pix_tmp+0x40] + mov r1, 0x10 + call deblock_v_luma_intra_8 + + ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8) + lea r5, [r6+r8] + TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r6, r5, r7, r8) + shl r7, 3 + sub r6, r7 + sub r5, r7 + shr r7, 3 + TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r6, r5, r7, r8) + add rsp, 0x88 + RET +%else +cglobal deblock_h_luma_intra_8, 2,4,8,0x80 + lea r3, [r1*3] + sub r0, 4 + lea r2, [r0+r3] + %define pix_tmp rsp + + ; transpose 8x16 -> tmp space + TRANSPOSE8x8_MEM PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30) + lea r0, [r0+r1*8] + lea r2, [r2+r1*8] + TRANSPOSE8x8_MEM PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30) + + lea r0, [pix_tmp+0x40] + PUSH dword r3m + PUSH dword r2m + PUSH dword 16 + PUSH r0 + call deblock_%1_luma_intra_8 +%ifidn %1, v8 + add dword [rsp], 8 ; pix_tmp+8 + call deblock_%1_luma_intra_8 +%endif + ADD esp, 16 + + mov r1, r1m + mov r0, r0mp + lea r3, [r1*3] + sub r0, 4 + lea r2, [r0+r3] + ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8) + TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3) + lea r0, [r0+r1*8] + lea r2, [r2+r1*8] + TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3) + RET +%endif ; ARCH_X86_64 +%endmacro ; DEBLOCK_LUMA_INTRA + +INIT_XMM sse2 +DEBLOCK_LUMA_INTRA v +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_LUMA_INTRA v +%endif +%if ARCH_X86_64 == 0 +INIT_MMX mmxext +DEBLOCK_LUMA_INTRA v8 +%endif + +INIT_MMX mmxext + +%macro CHROMA_V_START 0 + dec r2d ; alpha-1 + dec r3d ; beta-1 + mov t5, r0 + sub t5, r1 + sub t5, r1 +%endmacro + +%macro CHROMA_H_START 0 + dec r2d + dec r3d + sub r0, 2 + lea t6, [r1*3] + mov t5, r0 + add r0, t6 +%endmacro + +%define t5 r5 +%define t6 r6 + +;----------------------------------------------------------------------------- +; void ff_deblock_v_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +cglobal deblock_v_chroma_8, 5,6 + CHROMA_V_START + movq m0, [t5] + movq m1, [t5+r1] + movq m2, [r0] + movq m3, [r0+r1] + call ff_chroma_inter_body_mmxext + movq [t5+r1], m1 + movq [r0], m2 + RET + +;----------------------------------------------------------------------------- +; void ff_deblock_h_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +cglobal deblock_h_chroma_8, 5,7 +%if UNIX64 + %define buf0 [rsp-24] + %define buf1 [rsp-16] +%elif WIN64 + sub rsp, 16 + %define buf0 [rsp] + %define buf1 [rsp+8] +%else + %define buf0 r0m + %define buf1 r2m +%endif + CHROMA_H_START + TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) + movq buf0, m0 + movq buf1, m3 + LOAD_MASK r2d, r3d + movd m6, [r4] ; tc0 + punpcklbw m6, m6 + pand m7, m6 + DEBLOCK_P0_Q0 + movq m0, buf0 + movq m3, buf1 + TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) +%if WIN64 + add rsp, 16 +%endif + RET + +ALIGN 16 +ff_chroma_inter_body_mmxext: + LOAD_MASK r2d, r3d + movd m6, [r4] ; tc0 + punpcklbw m6, m6 + pand m7, m6 + DEBLOCK_P0_Q0 + ret + + + +; in: %1=p0 %2=p1 %3=q1 +; out: p0 = (p0 + q1 + 2*p1 + 2) >> 2 +%macro CHROMA_INTRA_P0 3 + movq m4, %1 + pxor m4, %3 + pand m4, [pb_1] ; m4 = (p0^q1)&1 + pavgb %1, %3 + psubusb %1, m4 + pavgb %1, %2 ; dst = avg(p1, avg(p0,q1) - ((p0^q1)&1)) +%endmacro + +%define t5 r4 +%define t6 r5 + +;----------------------------------------------------------------------------- +; void ff_deblock_v_chroma_intra( uint8_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_v_chroma_intra_8, 4,5 + CHROMA_V_START + movq m0, [t5] + movq m1, [t5+r1] + movq m2, [r0] + movq m3, [r0+r1] + call ff_chroma_intra_body_mmxext + movq [t5+r1], m1 + movq [r0], m2 + RET + +;----------------------------------------------------------------------------- +; void ff_deblock_h_chroma_intra( uint8_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_h_chroma_intra_8, 4,6 + CHROMA_H_START + TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) + call ff_chroma_intra_body_mmxext + TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) + RET + +ALIGN 16 +ff_chroma_intra_body_mmxext: + LOAD_MASK r2d, r3d + movq m5, m1 + movq m6, m2 + CHROMA_INTRA_P0 m1, m0, m3 + CHROMA_INTRA_P0 m2, m3, m0 + psubb m1, m5 + psubb m2, m6 + pand m1, m7 + pand m2, m7 + paddb m1, m5 + paddb m2, m6 + ret + +;----------------------------------------------------------------------------- +; void h264_loop_filter_strength(int16_t bs[2][4][4], uint8_t nnz[40], +; int8_t ref[2][40], int16_t mv[2][40][2], +; int bidir, int edges, int step, +; int mask_mv0, int mask_mv1, int field); +; +; bidir is 0 or 1 +; edges is 1 or 4 +; step is 1 or 2 +; mask_mv0 is 0 or 3 +; mask_mv1 is 0 or 1 +; field is 0 or 1 +;----------------------------------------------------------------------------- +%macro loop_filter_strength_iteration 7 ; edges, step, mask_mv, + ; dir, d_idx, mask_dir, bidir +%define edgesd %1 +%define stepd %2 +%define mask_mvd %3 +%define dir %4 +%define d_idx %5 +%define mask_dir %6 +%define bidir %7 + xor b_idxd, b_idxd ; for (b_idx = 0; b_idx < edges; b_idx += step) +%%.b_idx_loop: +%if mask_dir == 0 + pxor m0, m0 +%endif + test b_idxd, dword mask_mvd + jnz %%.skip_loop_iter ; if (!(b_idx & mask_mv)) +%if bidir == 1 + movd m2, [refq+b_idxq+d_idx+12] ; { ref0[bn] } + punpckldq m2, [refq+b_idxq+d_idx+52] ; { ref0[bn], ref1[bn] } + pshufw m0, [refq+b_idxq+12], 0x44 ; { ref0[b], ref0[b] } + pshufw m1, [refq+b_idxq+52], 0x44 ; { ref1[b], ref1[b] } + pshufw m3, m2, 0x4E ; { ref1[bn], ref0[bn] } + psubb m0, m2 ; { ref0[b] != ref0[bn], + ; ref0[b] != ref1[bn] } + psubb m1, m3 ; { ref1[b] != ref1[bn], + ; ref1[b] != ref0[bn] } + + por m0, m1 + mova m1, [mvq+b_idxq*4+(d_idx+12)*4] + mova m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize] + mova m3, m1 + mova m4, m2 + psubw m1, [mvq+b_idxq*4+12*4] + psubw m2, [mvq+b_idxq*4+12*4+mmsize] + psubw m3, [mvq+b_idxq*4+52*4] + psubw m4, [mvq+b_idxq*4+52*4+mmsize] + packsswb m1, m2 + packsswb m3, m4 + paddb m1, m6 + paddb m3, m6 + psubusb m1, m5 ; abs(mv[b] - mv[bn]) >= limit + psubusb m3, m5 + packsswb m1, m3 + + por m0, m1 + mova m1, [mvq+b_idxq*4+(d_idx+52)*4] + mova m2, [mvq+b_idxq*4+(d_idx+52)*4+mmsize] + mova m3, m1 + mova m4, m2 + psubw m1, [mvq+b_idxq*4+12*4] + psubw m2, [mvq+b_idxq*4+12*4+mmsize] + psubw m3, [mvq+b_idxq*4+52*4] + psubw m4, [mvq+b_idxq*4+52*4+mmsize] + packsswb m1, m2 + packsswb m3, m4 + paddb m1, m6 + paddb m3, m6 + psubusb m1, m5 ; abs(mv[b] - mv[bn]) >= limit + psubusb m3, m5 + packsswb m1, m3 + + pshufw m1, m1, 0x4E + por m0, m1 + pshufw m1, m0, 0x4E + pminub m0, m1 +%else ; bidir == 0 + movd m0, [refq+b_idxq+12] + psubb m0, [refq+b_idxq+d_idx+12] ; ref[b] != ref[bn] + + mova m1, [mvq+b_idxq*4+12*4] + mova m2, [mvq+b_idxq*4+12*4+mmsize] + psubw m1, [mvq+b_idxq*4+(d_idx+12)*4] + psubw m2, [mvq+b_idxq*4+(d_idx+12)*4+mmsize] + packsswb m1, m2 + paddb m1, m6 + psubusb m1, m5 ; abs(mv[b] - mv[bn]) >= limit + packsswb m1, m1 + por m0, m1 +%endif ; bidir == 1/0 + +%%.skip_loop_iter: + movd m1, [nnzq+b_idxq+12] + por m1, [nnzq+b_idxq+d_idx+12] ; nnz[b] || nnz[bn] + + pminub m1, m7 + pminub m0, m7 + psllw m1, 1 + pxor m2, m2 + pmaxub m1, m0 + punpcklbw m1, m2 + movq [bsq+b_idxq+32*dir], m1 + + add b_idxd, dword stepd + cmp b_idxd, dword edgesd + jl %%.b_idx_loop +%endmacro + +INIT_MMX mmxext +cglobal h264_loop_filter_strength, 9, 9, 0, bs, nnz, ref, mv, bidir, edges, \ + step, mask_mv0, mask_mv1, field +%define b_idxq bidirq +%define b_idxd bidird + cmp dword fieldm, 0 + mova m7, [pb_1] + mova m5, [pb_3] + je .nofield + mova m5, [pb_3_1] +.nofield: + mova m6, m5 + paddb m5, m5 + + shl dword stepd, 3 + shl dword edgesd, 3 +%if ARCH_X86_32 +%define mask_mv0d mask_mv0m +%define mask_mv1d mask_mv1m +%endif + shl dword mask_mv1d, 3 + shl dword mask_mv0d, 3 + + cmp dword bidird, 0 + jne .bidir + loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8, 0, 0 + loop_filter_strength_iteration 32, 8, mask_mv0d, 0, -1, -1, 0 + + mova m0, [bsq+mmsize*0] + mova m1, [bsq+mmsize*1] + mova m2, [bsq+mmsize*2] + mova m3, [bsq+mmsize*3] + TRANSPOSE4x4W 0, 1, 2, 3, 4 + mova [bsq+mmsize*0], m0 + mova [bsq+mmsize*1], m1 + mova [bsq+mmsize*2], m2 + mova [bsq+mmsize*3], m3 + RET + +.bidir: + loop_filter_strength_iteration edgesd, stepd, mask_mv1d, 1, -8, 0, 1 + loop_filter_strength_iteration 32, 8, mask_mv0d, 0, -1, -1, 1 + + mova m0, [bsq+mmsize*0] + mova m1, [bsq+mmsize*1] + mova m2, [bsq+mmsize*2] + mova m3, [bsq+mmsize*3] + TRANSPOSE4x4W 0, 1, 2, 3, 4 + mova [bsq+mmsize*0], m0 + mova [bsq+mmsize*1], m1 + mova [bsq+mmsize*2], m2 + mova [bsq+mmsize*3], m3 + RET diff --git a/ffmpeg/libavcodec/x86/h264_deblock_10bit.asm b/ffmpeg/libavcodec/x86/h264_deblock_10bit.asm new file mode 100644 index 0000000..d63ca02 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_deblock_10bit.asm @@ -0,0 +1,923 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 deblocking code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Oskar Arvidsson +;* Loren Merritt +;* Jason Garrett-Glaser +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pw_pixel_max: times 8 dw ((1 << 10)-1) + +SECTION .text + +cextern pw_2 +cextern pw_3 +cextern pw_4 + +; out: %4 = |%1-%2|-%3 +; clobbers: %5 +%macro ABS_SUB 5 + psubusw %5, %2, %1 + psubusw %4, %1, %2 + por %4, %5 + psubw %4, %3 +%endmacro + +; out: %4 = |%1-%2|<%3 +%macro DIFF_LT 5 + psubusw %4, %2, %1 + psubusw %5, %1, %2 + por %5, %4 ; |%1-%2| + pxor %4, %4 + psubw %5, %3 ; |%1-%2|-%3 + pcmpgtw %4, %5 ; 0 > |%1-%2|-%3 +%endmacro + +%macro LOAD_AB 4 + movd %1, %3 + movd %2, %4 + SPLATW %1, %1 + SPLATW %2, %2 +%endmacro + +; in: %2=tc reg +; out: %1=splatted tc +%macro LOAD_TC 2 + movd %1, [%2] + punpcklbw %1, %1 +%if mmsize == 8 + pshufw %1, %1, 0 +%else + pshuflw %1, %1, 01010000b + pshufd %1, %1, 01010000b +%endif + psraw %1, 6 +%endmacro + +; in: %1=p1, %2=p0, %3=q0, %4=q1 +; %5=alpha, %6=beta, %7-%9=tmp +; out: %7=mask +%macro LOAD_MASK 9 + ABS_SUB %2, %3, %5, %8, %7 ; |p0-q0| - alpha + ABS_SUB %1, %2, %6, %9, %7 ; |p1-p0| - beta + pand %8, %9 + ABS_SUB %3, %4, %6, %9, %7 ; |q1-q0| - beta + pxor %7, %7 + pand %8, %9 + pcmpgtw %7, %8 +%endmacro + +; in: %1=p0, %2=q0, %3=p1, %4=q1, %5=mask, %6=tmp, %7=tmp +; out: %1=p0', m2=q0' +%macro DEBLOCK_P0_Q0 7 + psubw %3, %4 + pxor %7, %7 + paddw %3, [pw_4] + psubw %7, %5 + psubw %6, %2, %1 + psllw %6, 2 + paddw %3, %6 + psraw %3, 3 + mova %6, [pw_pixel_max] + CLIPW %3, %7, %5 + pxor %7, %7 + paddw %1, %3 + psubw %2, %3 + CLIPW %1, %7, %6 + CLIPW %2, %7, %6 +%endmacro + +; in: %1=x2, %2=x1, %3=p0, %4=q0 %5=mask&tc, %6=tmp +%macro LUMA_Q1 6 + pavgw %6, %3, %4 ; (p0+q0+1)>>1 + paddw %1, %6 + pxor %6, %6 + psraw %1, 1 + psubw %6, %5 + psubw %1, %2 + CLIPW %1, %6, %5 + paddw %1, %2 +%endmacro + +%macro LUMA_DEBLOCK_ONE 3 + DIFF_LT m5, %1, bm, m4, m6 + pxor m6, m6 + mova %3, m4 + pcmpgtw m6, tcm + pand m4, tcm + pandn m6, m7 + pand m4, m6 + LUMA_Q1 m5, %2, m1, m2, m4, m6 +%endmacro + +%macro LUMA_H_STORE 2 +%if mmsize == 8 + movq [r0-4], m0 + movq [r0+r1-4], m1 + movq [r0+r1*2-4], m2 + movq [r0+%2-4], m3 +%else + movq [r0-4], m0 + movhps [r0+r1-4], m0 + movq [r0+r1*2-4], m1 + movhps [%1-4], m1 + movq [%1+r1-4], m2 + movhps [%1+r1*2-4], m2 + movq [%1+%2-4], m3 + movhps [%1+r1*4-4], m3 +%endif +%endmacro + +%macro DEBLOCK_LUMA 0 +;----------------------------------------------------------------------------- +; void deblock_v_luma( uint16_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +cglobal deblock_v_luma_10, 5,5,8*(mmsize/16) + %assign pad 5*mmsize+12-(stack_offset&15) + %define tcm [rsp] + %define ms1 [rsp+mmsize] + %define ms2 [rsp+mmsize*2] + %define am [rsp+mmsize*3] + %define bm [rsp+mmsize*4] + SUB rsp, pad + shl r2d, 2 + shl r3d, 2 + LOAD_AB m4, m5, r2d, r3d + mov r3, 32/mmsize + mov r2, r0 + sub r0, r1 + mova am, m4 + sub r0, r1 + mova bm, m5 + sub r0, r1 +.loop: + mova m0, [r0+r1] + mova m1, [r0+r1*2] + mova m2, [r2] + mova m3, [r2+r1] + + LOAD_MASK m0, m1, m2, m3, am, bm, m7, m4, m6 + LOAD_TC m6, r4 + mova tcm, m6 + + mova m5, [r0] + LUMA_DEBLOCK_ONE m1, m0, ms1 + mova [r0+r1], m5 + + mova m5, [r2+r1*2] + LUMA_DEBLOCK_ONE m2, m3, ms2 + mova [r2+r1], m5 + + pxor m5, m5 + mova m6, tcm + pcmpgtw m5, tcm + psubw m6, ms1 + pandn m5, m7 + psubw m6, ms2 + pand m5, m6 + DEBLOCK_P0_Q0 m1, m2, m0, m3, m5, m7, m6 + mova [r0+r1*2], m1 + mova [r2], m2 + + add r0, mmsize + add r2, mmsize + add r4, mmsize/8 + dec r3 + jg .loop + ADD rsp, pad + RET + +cglobal deblock_h_luma_10, 5,6,8*(mmsize/16) + %assign pad 7*mmsize+12-(stack_offset&15) + %define tcm [rsp] + %define ms1 [rsp+mmsize] + %define ms2 [rsp+mmsize*2] + %define p1m [rsp+mmsize*3] + %define p2m [rsp+mmsize*4] + %define am [rsp+mmsize*5] + %define bm [rsp+mmsize*6] + SUB rsp, pad + shl r2d, 2 + shl r3d, 2 + LOAD_AB m4, m5, r2d, r3d + mov r3, r1 + mova am, m4 + add r3, r1 + mov r5, 32/mmsize + mova bm, m5 + add r3, r1 +%if mmsize == 16 + mov r2, r0 + add r2, r3 +%endif +.loop: +%if mmsize == 8 + movq m2, [r0-8] ; y q2 q1 q0 + movq m7, [r0+0] + movq m5, [r0+r1-8] + movq m3, [r0+r1+0] + movq m0, [r0+r1*2-8] + movq m6, [r0+r1*2+0] + movq m1, [r0+r3-8] + TRANSPOSE4x4W 2, 5, 0, 1, 4 + SWAP 2, 7 + movq m7, [r0+r3] + TRANSPOSE4x4W 2, 3, 6, 7, 4 +%else + movu m5, [r0-8] ; y q2 q1 q0 p0 p1 p2 x + movu m0, [r0+r1-8] + movu m2, [r0+r1*2-8] + movu m3, [r2-8] + TRANSPOSE4x4W 5, 0, 2, 3, 6 + mova tcm, m3 + + movu m4, [r2+r1-8] + movu m1, [r2+r1*2-8] + movu m3, [r2+r3-8] + movu m7, [r2+r1*4-8] + TRANSPOSE4x4W 4, 1, 3, 7, 6 + + mova m6, tcm + punpcklqdq m6, m7 + punpckhqdq m5, m4 + SBUTTERFLY qdq, 0, 1, 7 + SBUTTERFLY qdq, 2, 3, 7 +%endif + + mova p2m, m6 + LOAD_MASK m0, m1, m2, m3, am, bm, m7, m4, m6 + LOAD_TC m6, r4 + mova tcm, m6 + + LUMA_DEBLOCK_ONE m1, m0, ms1 + mova p1m, m5 + + mova m5, p2m + LUMA_DEBLOCK_ONE m2, m3, ms2 + mova p2m, m5 + + pxor m5, m5 + mova m6, tcm + pcmpgtw m5, tcm + psubw m6, ms1 + pandn m5, m7 + psubw m6, ms2 + pand m5, m6 + DEBLOCK_P0_Q0 m1, m2, m0, m3, m5, m7, m6 + mova m0, p1m + mova m3, p2m + TRANSPOSE4x4W 0, 1, 2, 3, 4 + LUMA_H_STORE r2, r3 + + add r4, mmsize/8 + lea r0, [r0+r1*(mmsize/2)] + lea r2, [r2+r1*(mmsize/2)] + dec r5 + jg .loop + ADD rsp, pad + RET +%endmacro + +%if ARCH_X86_64 +; in: m0=p1, m1=p0, m2=q0, m3=q1, m8=p2, m9=q2 +; m12=alpha, m13=beta +; out: m0=p1', m3=q1', m1=p0', m2=q0' +; clobbers: m4, m5, m6, m7, m10, m11, m14 +%macro DEBLOCK_LUMA_INTER_SSE2 0 + LOAD_MASK m0, m1, m2, m3, m12, m13, m7, m4, m6 + LOAD_TC m6, r4 + DIFF_LT m8, m1, m13, m10, m4 + DIFF_LT m9, m2, m13, m11, m4 + pand m6, m7 + + mova m14, m6 + pxor m4, m4 + pcmpgtw m6, m4 + pand m6, m14 + + mova m5, m10 + pand m5, m6 + LUMA_Q1 m8, m0, m1, m2, m5, m4 + + mova m5, m11 + pand m5, m6 + LUMA_Q1 m9, m3, m1, m2, m5, m4 + + pxor m4, m4 + psubw m6, m10 + pcmpgtw m4, m14 + pandn m4, m7 + psubw m6, m11 + pand m4, m6 + DEBLOCK_P0_Q0 m1, m2, m0, m3, m4, m5, m6 + + SWAP 0, 8 + SWAP 3, 9 +%endmacro + +%macro DEBLOCK_LUMA_64 0 +cglobal deblock_v_luma_10, 5,5,15 + %define p2 m8 + %define p1 m0 + %define p0 m1 + %define q0 m2 + %define q1 m3 + %define q2 m9 + %define mask0 m7 + %define mask1 m10 + %define mask2 m11 + shl r2d, 2 + shl r3d, 2 + LOAD_AB m12, m13, r2d, r3d + mov r2, r0 + sub r0, r1 + sub r0, r1 + sub r0, r1 + mov r3, 2 +.loop: + mova p2, [r0] + mova p1, [r0+r1] + mova p0, [r0+r1*2] + mova q0, [r2] + mova q1, [r2+r1] + mova q2, [r2+r1*2] + DEBLOCK_LUMA_INTER_SSE2 + mova [r0+r1], p1 + mova [r0+r1*2], p0 + mova [r2], q0 + mova [r2+r1], q1 + add r0, mmsize + add r2, mmsize + add r4, 2 + dec r3 + jg .loop + REP_RET + +cglobal deblock_h_luma_10, 5,7,15 + shl r2d, 2 + shl r3d, 2 + LOAD_AB m12, m13, r2d, r3d + mov r2, r1 + add r2, r1 + add r2, r1 + mov r5, r0 + add r5, r2 + mov r6, 2 +.loop: + movu m8, [r0-8] ; y q2 q1 q0 p0 p1 p2 x + movu m0, [r0+r1-8] + movu m2, [r0+r1*2-8] + movu m9, [r5-8] + movu m5, [r5+r1-8] + movu m1, [r5+r1*2-8] + movu m3, [r5+r2-8] + movu m7, [r5+r1*4-8] + + TRANSPOSE4x4W 8, 0, 2, 9, 10 + TRANSPOSE4x4W 5, 1, 3, 7, 10 + + punpckhqdq m8, m5 + SBUTTERFLY qdq, 0, 1, 10 + SBUTTERFLY qdq, 2, 3, 10 + punpcklqdq m9, m7 + + DEBLOCK_LUMA_INTER_SSE2 + + TRANSPOSE4x4W 0, 1, 2, 3, 4 + LUMA_H_STORE r5, r2 + add r4, 2 + lea r0, [r0+r1*8] + lea r5, [r5+r1*8] + dec r6 + jg .loop + REP_RET +%endmacro + +INIT_XMM sse2 +DEBLOCK_LUMA_64 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_LUMA_64 +%endif +%endif + +%macro SWAPMOVA 2 +%ifid %1 + SWAP %1, %2 +%else + mova %1, %2 +%endif +%endmacro + +; in: t0-t2: tmp registers +; %1=p0 %2=p1 %3=p2 %4=p3 %5=q0 %6=q1 %7=mask0 +; %8=mask1p %9=2 %10=p0' %11=p1' %12=p2' +%macro LUMA_INTRA_P012 12 ; p0..p3 in memory +%if ARCH_X86_64 + paddw t0, %3, %2 + mova t2, %4 + paddw t2, %3 +%else + mova t0, %3 + mova t2, %4 + paddw t0, %2 + paddw t2, %3 +%endif + paddw t0, %1 + paddw t2, t2 + paddw t0, %5 + paddw t2, %9 + paddw t0, %9 ; (p2 + p1 + p0 + q0 + 2) + paddw t2, t0 ; (2*p3 + 3*p2 + p1 + p0 + q0 + 4) + + psrlw t2, 3 + psrlw t1, t0, 2 + psubw t2, %3 + psubw t1, %2 + pand t2, %8 + pand t1, %8 + paddw t2, %3 + paddw t1, %2 + SWAPMOVA %11, t1 + + psubw t1, t0, %3 + paddw t0, t0 + psubw t1, %5 + psubw t0, %3 + paddw t1, %6 + paddw t1, %2 + paddw t0, %6 + psrlw t1, 2 ; (2*p1 + p0 + q1 + 2)/4 + psrlw t0, 3 ; (p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4)>>3 + + pxor t0, t1 + pxor t1, %1 + pand t0, %8 + pand t1, %7 + pxor t0, t1 + pxor t0, %1 + SWAPMOVA %10, t0 + SWAPMOVA %12, t2 +%endmacro + +%macro LUMA_INTRA_INIT 1 + %xdefine pad %1*mmsize+((gprsize*3) % mmsize)-(stack_offset&15) + %define t0 m4 + %define t1 m5 + %define t2 m6 + %define t3 m7 + %assign i 4 +%rep %1 + CAT_XDEFINE t, i, [rsp+mmsize*(i-4)] + %assign i i+1 +%endrep + SUB rsp, pad +%endmacro + +; in: %1-%3=tmp, %4=p2, %5=q2 +%macro LUMA_INTRA_INTER 5 + LOAD_AB t0, t1, r2d, r3d + mova %1, t0 + LOAD_MASK m0, m1, m2, m3, %1, t1, t0, t2, t3 +%if ARCH_X86_64 + mova %2, t0 ; mask0 + psrlw t3, %1, 2 +%else + mova t3, %1 + mova %2, t0 ; mask0 + psrlw t3, 2 +%endif + paddw t3, [pw_2] ; alpha/4+2 + DIFF_LT m1, m2, t3, t2, t0 ; t2 = |p0-q0| < alpha/4+2 + pand t2, %2 + mova t3, %5 ; q2 + mova %1, t2 ; mask1 + DIFF_LT t3, m2, t1, t2, t0 ; t2 = |q2-q0| < beta + pand t2, %1 + mova t3, %4 ; p2 + mova %3, t2 ; mask1q + DIFF_LT t3, m1, t1, t2, t0 ; t2 = |p2-p0| < beta + pand t2, %1 + mova %1, t2 ; mask1p +%endmacro + +%macro LUMA_H_INTRA_LOAD 0 +%if mmsize == 8 + movu t0, [r0-8] + movu t1, [r0+r1-8] + movu m0, [r0+r1*2-8] + movu m1, [r0+r4-8] + TRANSPOSE4x4W 4, 5, 0, 1, 2 + mova t4, t0 ; p3 + mova t5, t1 ; p2 + + movu m2, [r0] + movu m3, [r0+r1] + movu t0, [r0+r1*2] + movu t1, [r0+r4] + TRANSPOSE4x4W 2, 3, 4, 5, 6 + mova t6, t0 ; q2 + mova t7, t1 ; q3 +%else + movu t0, [r0-8] + movu t1, [r0+r1-8] + movu m0, [r0+r1*2-8] + movu m1, [r0+r5-8] + movu m2, [r4-8] + movu m3, [r4+r1-8] + movu t2, [r4+r1*2-8] + movu t3, [r4+r5-8] + TRANSPOSE8x8W 4, 5, 0, 1, 2, 3, 6, 7, t4, t5 + mova t4, t0 ; p3 + mova t5, t1 ; p2 + mova t6, t2 ; q2 + mova t7, t3 ; q3 +%endif +%endmacro + +; in: %1=q3 %2=q2' %3=q1' %4=q0' %5=p0' %6=p1' %7=p2' %8=p3 %9=tmp +%macro LUMA_H_INTRA_STORE 9 +%if mmsize == 8 + TRANSPOSE4x4W %1, %2, %3, %4, %9 + movq [r0-8], m%1 + movq [r0+r1-8], m%2 + movq [r0+r1*2-8], m%3 + movq [r0+r4-8], m%4 + movq m%1, %8 + TRANSPOSE4x4W %5, %6, %7, %1, %9 + movq [r0], m%5 + movq [r0+r1], m%6 + movq [r0+r1*2], m%7 + movq [r0+r4], m%1 +%else + TRANSPOSE2x4x4W %1, %2, %3, %4, %9 + movq [r0-8], m%1 + movq [r0+r1-8], m%2 + movq [r0+r1*2-8], m%3 + movq [r0+r5-8], m%4 + movhps [r4-8], m%1 + movhps [r4+r1-8], m%2 + movhps [r4+r1*2-8], m%3 + movhps [r4+r5-8], m%4 +%ifnum %8 + SWAP %1, %8 +%else + mova m%1, %8 +%endif + TRANSPOSE2x4x4W %5, %6, %7, %1, %9 + movq [r0], m%5 + movq [r0+r1], m%6 + movq [r0+r1*2], m%7 + movq [r0+r5], m%1 + movhps [r4], m%5 + movhps [r4+r1], m%6 + movhps [r4+r1*2], m%7 + movhps [r4+r5], m%1 +%endif +%endmacro + +%if ARCH_X86_64 +;----------------------------------------------------------------------------- +; void deblock_v_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +%macro DEBLOCK_LUMA_INTRA_64 0 +cglobal deblock_v_luma_intra_10, 4,7,16 + %define t0 m1 + %define t1 m2 + %define t2 m4 + %define p2 m8 + %define p1 m9 + %define p0 m10 + %define q0 m11 + %define q1 m12 + %define q2 m13 + %define aa m5 + %define bb m14 + lea r4, [r1*4] + lea r5, [r1*3] ; 3*stride + neg r4 + add r4, r0 ; pix-4*stride + mov r6, 2 + mova m0, [pw_2] + shl r2d, 2 + shl r3d, 2 + LOAD_AB aa, bb, r2d, r3d +.loop: + mova p2, [r4+r1] + mova p1, [r4+2*r1] + mova p0, [r4+r5] + mova q0, [r0] + mova q1, [r0+r1] + mova q2, [r0+2*r1] + + LOAD_MASK p1, p0, q0, q1, aa, bb, m3, t0, t1 + mova t2, aa + psrlw t2, 2 + paddw t2, m0 ; alpha/4+2 + DIFF_LT p0, q0, t2, m6, t0 ; m6 = |p0-q0| < alpha/4+2 + DIFF_LT p2, p0, bb, t1, t0 ; m7 = |p2-p0| < beta + DIFF_LT q2, q0, bb, m7, t0 ; t1 = |q2-q0| < beta + pand m6, m3 + pand m7, m6 + pand m6, t1 + LUMA_INTRA_P012 p0, p1, p2, [r4], q0, q1, m3, m6, m0, [r4+r5], [r4+2*r1], [r4+r1] + LUMA_INTRA_P012 q0, q1, q2, [r0+r5], p0, p1, m3, m7, m0, [r0], [r0+r1], [r0+2*r1] + add r0, mmsize + add r4, mmsize + dec r6 + jg .loop + REP_RET + +;----------------------------------------------------------------------------- +; void deblock_h_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_h_luma_intra_10, 4,7,16 + %define t0 m15 + %define t1 m14 + %define t2 m2 + %define q3 m5 + %define q2 m8 + %define q1 m9 + %define q0 m10 + %define p0 m11 + %define p1 m12 + %define p2 m13 + %define p3 m4 + %define spill [rsp] + %assign pad 24-(stack_offset&15) + SUB rsp, pad + lea r4, [r1*4] + lea r5, [r1*3] ; 3*stride + add r4, r0 ; pix+4*stride + mov r6, 2 + mova m0, [pw_2] + shl r2d, 2 + shl r3d, 2 +.loop: + movu q3, [r0-8] + movu q2, [r0+r1-8] + movu q1, [r0+r1*2-8] + movu q0, [r0+r5-8] + movu p0, [r4-8] + movu p1, [r4+r1-8] + movu p2, [r4+r1*2-8] + movu p3, [r4+r5-8] + TRANSPOSE8x8W 5, 8, 9, 10, 11, 12, 13, 4, 1 + + LOAD_AB m1, m2, r2d, r3d + LOAD_MASK q1, q0, p0, p1, m1, m2, m3, t0, t1 + psrlw m1, 2 + paddw m1, m0 ; alpha/4+2 + DIFF_LT p0, q0, m1, m6, t0 ; m6 = |p0-q0| < alpha/4+2 + DIFF_LT q2, q0, m2, t1, t0 ; t1 = |q2-q0| < beta + DIFF_LT p0, p2, m2, m7, t0 ; m7 = |p2-p0| < beta + pand m6, m3 + pand m7, m6 + pand m6, t1 + + mova spill, q3 + LUMA_INTRA_P012 q0, q1, q2, q3, p0, p1, m3, m6, m0, m5, m1, q2 + LUMA_INTRA_P012 p0, p1, p2, p3, q0, q1, m3, m7, m0, p0, m6, p2 + mova m7, spill + + LUMA_H_INTRA_STORE 7, 8, 1, 5, 11, 6, 13, 4, 14 + + lea r0, [r0+r1*8] + lea r4, [r4+r1*8] + dec r6 + jg .loop + ADD rsp, pad + RET +%endmacro + +INIT_XMM sse2 +DEBLOCK_LUMA_INTRA_64 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_LUMA_INTRA_64 +%endif + +%endif + +%macro DEBLOCK_LUMA_INTRA 0 +;----------------------------------------------------------------------------- +; void deblock_v_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_v_luma_intra_10, 4,7,8*(mmsize/16) + LUMA_INTRA_INIT 3 + lea r4, [r1*4] + lea r5, [r1*3] + neg r4 + add r4, r0 + mov r6, 32/mmsize + shl r2d, 2 + shl r3d, 2 +.loop: + mova m0, [r4+r1*2] ; p1 + mova m1, [r4+r5] ; p0 + mova m2, [r0] ; q0 + mova m3, [r0+r1] ; q1 + LUMA_INTRA_INTER t4, t5, t6, [r4+r1], [r0+r1*2] + LUMA_INTRA_P012 m1, m0, t3, [r4], m2, m3, t5, t4, [pw_2], [r4+r5], [r4+2*r1], [r4+r1] + mova t3, [r0+r1*2] ; q2 + LUMA_INTRA_P012 m2, m3, t3, [r0+r5], m1, m0, t5, t6, [pw_2], [r0], [r0+r1], [r0+2*r1] + add r0, mmsize + add r4, mmsize + dec r6 + jg .loop + ADD rsp, pad + RET + +;----------------------------------------------------------------------------- +; void deblock_h_luma_intra( uint16_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_h_luma_intra_10, 4,7,8*(mmsize/16) + LUMA_INTRA_INIT 8 +%if mmsize == 8 + lea r4, [r1*3] + mov r5, 32/mmsize +%else + lea r4, [r1*4] + lea r5, [r1*3] ; 3*stride + add r4, r0 ; pix+4*stride + mov r6, 32/mmsize +%endif + shl r2d, 2 + shl r3d, 2 +.loop: + LUMA_H_INTRA_LOAD + LUMA_INTRA_INTER t8, t9, t10, t5, t6 + + LUMA_INTRA_P012 m1, m0, t3, t4, m2, m3, t9, t8, [pw_2], t8, t5, t11 + mova t3, t6 ; q2 + LUMA_INTRA_P012 m2, m3, t3, t7, m1, m0, t9, t10, [pw_2], m4, t6, m5 + + mova m2, t4 + mova m0, t11 + mova m1, t5 + mova m3, t8 + mova m6, t6 + + LUMA_H_INTRA_STORE 2, 0, 1, 3, 4, 6, 5, t7, 7 + + lea r0, [r0+r1*(mmsize/2)] +%if mmsize == 8 + dec r5 +%else + lea r4, [r4+r1*(mmsize/2)] + dec r6 +%endif + jg .loop + ADD rsp, pad + RET +%endmacro + +%if ARCH_X86_64 == 0 +INIT_MMX mmxext +DEBLOCK_LUMA +DEBLOCK_LUMA_INTRA +INIT_XMM sse2 +DEBLOCK_LUMA +DEBLOCK_LUMA_INTRA +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_LUMA +DEBLOCK_LUMA_INTRA +%endif +%endif + +; in: %1=p0, %2=q0, %3=p1, %4=q1, %5=mask, %6=tmp, %7=tmp +; out: %1=p0', %2=q0' +%macro CHROMA_DEBLOCK_P0_Q0_INTRA 7 + mova %6, [pw_2] + paddw %6, %3 + paddw %6, %4 + paddw %7, %6, %2 + paddw %6, %1 + paddw %6, %3 + paddw %7, %4 + psraw %6, 2 + psraw %7, 2 + psubw %6, %1 + psubw %7, %2 + pand %6, %5 + pand %7, %5 + paddw %1, %6 + paddw %2, %7 +%endmacro + +%macro CHROMA_V_LOAD 1 + mova m0, [r0] ; p1 + mova m1, [r0+r1] ; p0 + mova m2, [%1] ; q0 + mova m3, [%1+r1] ; q1 +%endmacro + +%macro CHROMA_V_STORE 0 + mova [r0+1*r1], m1 + mova [r0+2*r1], m2 +%endmacro + +%macro CHROMA_V_LOAD_TC 2 + movd %1, [%2] + punpcklbw %1, %1 + punpcklwd %1, %1 + psraw %1, 6 +%endmacro + +%macro DEBLOCK_CHROMA 0 +;----------------------------------------------------------------------------- +; void deblock_v_chroma( uint16_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) +;----------------------------------------------------------------------------- +cglobal deblock_v_chroma_10, 5,7-(mmsize/16),8*(mmsize/16) + mov r5, r0 + sub r0, r1 + sub r0, r1 + shl r2d, 2 + shl r3d, 2 +%if mmsize < 16 + mov r6, 16/mmsize +.loop: +%endif + CHROMA_V_LOAD r5 + LOAD_AB m4, m5, r2d, r3d + LOAD_MASK m0, m1, m2, m3, m4, m5, m7, m6, m4 + pxor m4, m4 + CHROMA_V_LOAD_TC m6, r4 + psubw m6, [pw_3] + pmaxsw m6, m4 + pand m7, m6 + DEBLOCK_P0_Q0 m1, m2, m0, m3, m7, m5, m6 + CHROMA_V_STORE +%if mmsize < 16 + add r0, mmsize + add r5, mmsize + add r4, mmsize/4 + dec r6 + jg .loop + REP_RET +%else + RET +%endif + +;----------------------------------------------------------------------------- +; void deblock_v_chroma_intra( uint16_t *pix, int stride, int alpha, int beta ) +;----------------------------------------------------------------------------- +cglobal deblock_v_chroma_intra_10, 4,6-(mmsize/16),8*(mmsize/16) + mov r4, r0 + sub r0, r1 + sub r0, r1 + shl r2d, 2 + shl r3d, 2 +%if mmsize < 16 + mov r5, 16/mmsize +.loop: +%endif + CHROMA_V_LOAD r4 + LOAD_AB m4, m5, r2d, r3d + LOAD_MASK m0, m1, m2, m3, m4, m5, m7, m6, m4 + CHROMA_DEBLOCK_P0_Q0_INTRA m1, m2, m0, m3, m7, m5, m6 + CHROMA_V_STORE +%if mmsize < 16 + add r0, mmsize + add r4, mmsize + dec r5 + jg .loop + REP_RET +%else + RET +%endif +%endmacro + +%if ARCH_X86_64 == 0 +INIT_MMX mmxext +DEBLOCK_CHROMA +%endif +INIT_XMM sse2 +DEBLOCK_CHROMA +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEBLOCK_CHROMA +%endif diff --git a/ffmpeg/libavcodec/x86/h264_i386.h b/ffmpeg/libavcodec/x86/h264_i386.h new file mode 100644 index 0000000..0dc0a7c --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_i386.h @@ -0,0 +1,204 @@ +/* + * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder + * Copyright (c) 2003 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 + */ + +/** + * @file + * H.264 / AVC / MPEG4 part10 codec. + * non-MMX i386-specific optimizations for H.264 + * @author Michael Niedermayer + */ + +#ifndef AVCODEC_X86_H264_I386_H +#define AVCODEC_X86_H264_I386_H + +#include + +#include "libavcodec/cabac.h" +#include "cabac.h" + +#if HAVE_INLINE_ASM + +//FIXME use some macros to avoid duplicating get_cabac (cannot be done yet +//as that would make optimization work hard) +#if HAVE_7REGS +#define decode_significance decode_significance_x86 +static int decode_significance_x86(CABACContext *c, int max_coeff, + uint8_t *significant_coeff_ctx_base, + int *index, x86_reg last_off){ + void *end= significant_coeff_ctx_base + max_coeff - 1; + int minusstart= -(intptr_t)significant_coeff_ctx_base; + int minusindex= 4-(intptr_t)index; + int bit; + x86_reg coeff_count; + +#ifdef BROKEN_RELOCATIONS + void *tables; + + __asm__ volatile( + "lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t" + : "=&r"(tables) + ); +#endif + + __asm__ volatile( + "3: \n\t" + + BRANCHLESS_GET_CABAC("%4", "%q4", "(%1)", "%3", "%w3", + "%5", "%q5", "%k0", "%b0", + "%c11(%6)", "%c12(%6)", + AV_STRINGIFY(H264_NORM_SHIFT_OFFSET), + AV_STRINGIFY(H264_LPS_RANGE_OFFSET), + AV_STRINGIFY(H264_MLPS_STATE_OFFSET), + "%13") + + "test $1, %4 \n\t" + " jz 4f \n\t" + "add %10, %1 \n\t" + + BRANCHLESS_GET_CABAC("%4", "%q4", "(%1)", "%3", "%w3", + "%5", "%q5", "%k0", "%b0", + "%c11(%6)", "%c12(%6)", + AV_STRINGIFY(H264_NORM_SHIFT_OFFSET), + AV_STRINGIFY(H264_LPS_RANGE_OFFSET), + AV_STRINGIFY(H264_MLPS_STATE_OFFSET), + "%13") + + "sub %10, %1 \n\t" + "mov %2, %0 \n\t" + "movl %7, %%ecx \n\t" + "add %1, %%"REG_c" \n\t" + "movl %%ecx, (%0) \n\t" + + "test $1, %4 \n\t" + " jnz 5f \n\t" + + "add"OPSIZE" $4, %2 \n\t" + + "4: \n\t" + "add $1, %1 \n\t" + "cmp %8, %1 \n\t" + " jb 3b \n\t" + "mov %2, %0 \n\t" + "movl %7, %%ecx \n\t" + "add %1, %%"REG_c" \n\t" + "movl %%ecx, (%0) \n\t" + "5: \n\t" + "add %9, %k0 \n\t" + "shr $2, %k0 \n\t" + : "=&q"(coeff_count), "+r"(significant_coeff_ctx_base), "+m"(index), + "+&r"(c->low), "=&r"(bit), "+&r"(c->range) + : "r"(c), "m"(minusstart), "m"(end), "m"(minusindex), "m"(last_off), + "i"(offsetof(CABACContext, bytestream)), + "i"(offsetof(CABACContext, bytestream_end)) + TABLES_ARG + : "%"REG_c, "memory" + ); + return coeff_count; +} + +#define decode_significance_8x8 decode_significance_8x8_x86 +static int decode_significance_8x8_x86(CABACContext *c, + uint8_t *significant_coeff_ctx_base, + int *index, uint8_t *last_coeff_ctx_base, const uint8_t *sig_off){ + int minusindex= 4-(intptr_t)index; + int bit; + x86_reg coeff_count; + x86_reg last=0; + x86_reg state; + +#ifdef BROKEN_RELOCATIONS + void *tables; + + __asm__ volatile( + "lea "MANGLE(ff_h264_cabac_tables)", %0 \n\t" + : "=&r"(tables) + ); +#endif + + __asm__ volatile( + "mov %1, %6 \n\t" + "3: \n\t" + + "mov %10, %0 \n\t" + "movzbl (%0, %6), %k6 \n\t" + "add %9, %6 \n\t" + + BRANCHLESS_GET_CABAC("%4", "%q4", "(%6)", "%3", "%w3", + "%5", "%q5", "%k0", "%b0", + "%c12(%7)", "%c13(%7)", + AV_STRINGIFY(H264_NORM_SHIFT_OFFSET), + AV_STRINGIFY(H264_LPS_RANGE_OFFSET), + AV_STRINGIFY(H264_MLPS_STATE_OFFSET), + "%15") + + "mov %1, %k6 \n\t" + "test $1, %4 \n\t" + " jz 4f \n\t" + +#ifdef BROKEN_RELOCATIONS + "movzbl %c14(%15, %q6), %k6\n\t" +#else + "movzbl "MANGLE(ff_h264_cabac_tables)"+%c14(%k6), %k6\n\t" +#endif + "add %11, %6 \n\t" + + BRANCHLESS_GET_CABAC("%4", "%q4", "(%6)", "%3", "%w3", + "%5", "%q5", "%k0", "%b0", + "%c12(%7)", "%c13(%7)", + AV_STRINGIFY(H264_NORM_SHIFT_OFFSET), + AV_STRINGIFY(H264_LPS_RANGE_OFFSET), + AV_STRINGIFY(H264_MLPS_STATE_OFFSET), + "%15") + + "mov %2, %0 \n\t" + "mov %1, %k6 \n\t" + "movl %k6, (%0) \n\t" + + "test $1, %4 \n\t" + " jnz 5f \n\t" + + "add"OPSIZE" $4, %2 \n\t" + + "4: \n\t" + "addl $1, %k6 \n\t" + "mov %k6, %1 \n\t" + "cmpl $63, %k6 \n\t" + " jb 3b \n\t" + "mov %2, %0 \n\t" + "movl %k6, (%0) \n\t" + "5: \n\t" + "addl %8, %k0 \n\t" + "shr $2, %k0 \n\t" + : "=&q"(coeff_count), "+m"(last), "+m"(index), "+&r"(c->low), + "=&r"(bit), "+&r"(c->range), "=&r"(state) + : "r"(c), "m"(minusindex), "m"(significant_coeff_ctx_base), + "m"(sig_off), "m"(last_coeff_ctx_base), + "i"(offsetof(CABACContext, bytestream)), + "i"(offsetof(CABACContext, bytestream_end)), + "i"(H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET) TABLES_ARG + : "%"REG_c, "memory" + ); + return coeff_count; +} +#endif /* HAVE_7REGS && !defined(BROKEN_RELOCATIONS) */ + +#endif /* HAVE_INLINE_ASM */ +#endif /* AVCODEC_X86_H264_I386_H */ diff --git a/ffmpeg/libavcodec/x86/h264_idct.asm b/ffmpeg/libavcodec/x86/h264_idct.asm new file mode 100644 index 0000000..7bb1653 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_idct.asm @@ -0,0 +1,1073 @@ +;***************************************************************************** +;* MMX/SSE2-optimized H.264 iDCT +;***************************************************************************** +;* Copyright (C) 2004-2005 Michael Niedermayer, Loren Merritt +;* Copyright (C) 2003-2008 x264 project +;* +;* Authors: Laurent Aimar +;* Loren Merritt +;* Holger Lubitz +;* Min Chen +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +; FIXME this table is a duplicate from h264data.h, and will be removed once the tables from, h264 have been split +scan8_mem: db 4+ 1*8, 5+ 1*8, 4+ 2*8, 5+ 2*8 + db 6+ 1*8, 7+ 1*8, 6+ 2*8, 7+ 2*8 + db 4+ 3*8, 5+ 3*8, 4+ 4*8, 5+ 4*8 + db 6+ 3*8, 7+ 3*8, 6+ 4*8, 7+ 4*8 + db 4+ 6*8, 5+ 6*8, 4+ 7*8, 5+ 7*8 + db 6+ 6*8, 7+ 6*8, 6+ 7*8, 7+ 7*8 + db 4+ 8*8, 5+ 8*8, 4+ 9*8, 5+ 9*8 + db 6+ 8*8, 7+ 8*8, 6+ 9*8, 7+ 9*8 + db 4+11*8, 5+11*8, 4+12*8, 5+12*8 + db 6+11*8, 7+11*8, 6+12*8, 7+12*8 + db 4+13*8, 5+13*8, 4+14*8, 5+14*8 + db 6+13*8, 7+13*8, 6+14*8, 7+14*8 +%ifdef PIC +%define npicregs 1 +%define scan8 picregq +%else +%define npicregs 0 +%define scan8 scan8_mem +%endif + +cextern pw_32 +cextern pw_1 + +SECTION .text + +; %1=uint8_t *dst, %2=int16_t *block, %3=int stride +%macro IDCT4_ADD 3 + ; Load dct coeffs + movq m0, [%2] + movq m1, [%2+8] + movq m2, [%2+16] + movq m3, [%2+24] + + IDCT4_1D w, 0, 1, 2, 3, 4, 5 + mova m6, [pw_32] + TRANSPOSE4x4W 0, 1, 2, 3, 4 + paddw m0, m6 + IDCT4_1D w, 0, 1, 2, 3, 4, 5 + pxor m7, m7 + movq [%2+ 0], m7 + movq [%2+ 8], m7 + movq [%2+16], m7 + movq [%2+24], m7 + + STORE_DIFFx2 m0, m1, m4, m5, m7, 6, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m2, m3, m4, m5, m7, 6, %1, %3 +%endmacro + +INIT_MMX mmx +; ff_h264_idct_add_mmx(uint8_t *dst, int16_t *block, int stride) +cglobal h264_idct_add_8, 3, 3, 0 + IDCT4_ADD r0, r1, r2 + RET + +%macro IDCT8_1D 2 + mova m0, m1 + psraw m1, 1 + mova m4, m5 + psraw m4, 1 + paddw m4, m5 + paddw m1, m0 + paddw m4, m7 + paddw m1, m5 + psubw m4, m0 + paddw m1, m3 + + psubw m0, m3 + psubw m5, m3 + psraw m3, 1 + paddw m0, m7 + psubw m5, m7 + psraw m7, 1 + psubw m0, m3 + psubw m5, m7 + + mova m7, m1 + psraw m1, 2 + mova m3, m4 + psraw m3, 2 + paddw m3, m0 + psraw m0, 2 + paddw m1, m5 + psraw m5, 2 + psubw m0, m4 + psubw m7, m5 + + mova m5, m6 + psraw m6, 1 + mova m4, m2 + psraw m4, 1 + paddw m6, m2 + psubw m4, m5 + + mova m2, %1 + mova m5, %2 + SUMSUB_BA w, 5, 2 + SUMSUB_BA w, 6, 5 + SUMSUB_BA w, 4, 2 + SUMSUB_BA w, 7, 6 + SUMSUB_BA w, 0, 4 + SUMSUB_BA w, 3, 2 + SUMSUB_BA w, 1, 5 + SWAP 7, 6, 4, 5, 2, 3, 1, 0 ; 70315246 -> 01234567 +%endmacro + +%macro IDCT8_1D_FULL 1 + mova m7, [%1+112] + mova m6, [%1+ 96] + mova m5, [%1+ 80] + mova m3, [%1+ 48] + mova m2, [%1+ 32] + mova m1, [%1+ 16] + IDCT8_1D [%1], [%1+ 64] +%endmacro + +; %1=int16_t *block, %2=int16_t *dstblock +%macro IDCT8_ADD_MMX_START 2 + IDCT8_1D_FULL %1 + mova [%1], m7 + TRANSPOSE4x4W 0, 1, 2, 3, 7 + mova m7, [%1] + mova [%2 ], m0 + mova [%2+16], m1 + mova [%2+32], m2 + mova [%2+48], m3 + TRANSPOSE4x4W 4, 5, 6, 7, 3 + mova [%2+ 8], m4 + mova [%2+24], m5 + mova [%2+40], m6 + mova [%2+56], m7 +%endmacro + +; %1=uint8_t *dst, %2=int16_t *block, %3=int stride +%macro IDCT8_ADD_MMX_END 3-4 + IDCT8_1D_FULL %2 + mova [%2 ], m5 + mova [%2+16], m6 + mova [%2+32], m7 + + pxor m7, m7 +%if %0 == 4 + movq [%4+ 0], m7 + movq [%4+ 8], m7 + movq [%4+ 16], m7 + movq [%4+ 24], m7 + movq [%4+ 32], m7 + movq [%4+ 40], m7 + movq [%4+ 48], m7 + movq [%4+ 56], m7 + movq [%4+ 64], m7 + movq [%4+ 72], m7 + movq [%4+ 80], m7 + movq [%4+ 88], m7 + movq [%4+ 96], m7 + movq [%4+104], m7 + movq [%4+112], m7 + movq [%4+120], m7 +%endif + STORE_DIFFx2 m0, m1, m5, m6, m7, 6, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m2, m3, m5, m6, m7, 6, %1, %3 + mova m0, [%2 ] + mova m1, [%2+16] + mova m2, [%2+32] + lea %1, [%1+%3*2] + STORE_DIFFx2 m4, m0, m5, m6, m7, 6, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m1, m2, m5, m6, m7, 6, %1, %3 +%endmacro + +INIT_MMX mmx +; ff_h264_idct8_add_mmx(uint8_t *dst, int16_t *block, int stride) +cglobal h264_idct8_add_8, 3, 4, 0 + %assign pad 128+4-(stack_offset&7) + SUB rsp, pad + + add word [r1], 32 + IDCT8_ADD_MMX_START r1 , rsp + IDCT8_ADD_MMX_START r1+8, rsp+64 + lea r3, [r0+4] + IDCT8_ADD_MMX_END r0 , rsp, r2, r1 + IDCT8_ADD_MMX_END r3 , rsp+8, r2 + + ADD rsp, pad + RET + +; %1=uint8_t *dst, %2=int16_t *block, %3=int stride +%macro IDCT8_ADD_SSE 4 + IDCT8_1D_FULL %2 +%if ARCH_X86_64 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%else + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, [%2], [%2+16] +%endif + paddw m0, [pw_32] + +%if ARCH_X86_64 == 0 + mova [%2 ], m0 + mova [%2+16], m4 + IDCT8_1D [%2], [%2+ 16] + mova [%2 ], m6 + mova [%2+16], m7 +%else + SWAP 0, 8 + SWAP 4, 9 + IDCT8_1D m8, m9 + SWAP 6, 8 + SWAP 7, 9 +%endif + + pxor m7, m7 + lea %4, [%3*3] + STORE_DIFF m0, m6, m7, [%1 ] + STORE_DIFF m1, m6, m7, [%1+%3 ] + STORE_DIFF m2, m6, m7, [%1+%3*2] + STORE_DIFF m3, m6, m7, [%1+%4 ] +%if ARCH_X86_64 == 0 + mova m0, [%2 ] + mova m1, [%2+16] +%else + SWAP 0, 8 + SWAP 1, 9 +%endif + mova [%2+ 0], m7 + mova [%2+ 16], m7 + mova [%2+ 32], m7 + mova [%2+ 48], m7 + mova [%2+ 64], m7 + mova [%2+ 80], m7 + mova [%2+ 96], m7 + mova [%2+112], m7 + lea %1, [%1+%3*4] + STORE_DIFF m4, m6, m7, [%1 ] + STORE_DIFF m5, m6, m7, [%1+%3 ] + STORE_DIFF m0, m6, m7, [%1+%3*2] + STORE_DIFF m1, m6, m7, [%1+%4 ] +%endmacro + +INIT_XMM sse2 +; ff_h264_idct8_add_sse2(uint8_t *dst, int16_t *block, int stride) +cglobal h264_idct8_add_8, 3, 4, 10 + IDCT8_ADD_SSE r0, r1, r2, r3 + RET + +%macro DC_ADD_MMXEXT_INIT 2 + add %1, 32 + sar %1, 6 + movd m0, %1d + lea %1, [%2*3] + pshufw m0, m0, 0 + pxor m1, m1 + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 +%endmacro + +%macro DC_ADD_MMXEXT_OP 4 + %1 m2, [%2 ] + %1 m3, [%2+%3 ] + %1 m4, [%2+%3*2] + %1 m5, [%2+%4 ] + paddusb m2, m0 + paddusb m3, m0 + paddusb m4, m0 + paddusb m5, m0 + psubusb m2, m1 + psubusb m3, m1 + psubusb m4, m1 + psubusb m5, m1 + %1 [%2 ], m2 + %1 [%2+%3 ], m3 + %1 [%2+%3*2], m4 + %1 [%2+%4 ], m5 +%endmacro + +INIT_MMX mmxext +; ff_h264_idct_dc_add_mmxext(uint8_t *dst, int16_t *block, int stride) +%if ARCH_X86_64 +cglobal h264_idct_dc_add_8, 3, 4, 0 + movsx r3, word [r1] + mov word [r1], 0 + DC_ADD_MMXEXT_INIT r3, r2 + DC_ADD_MMXEXT_OP movh, r0, r2, r3 + RET + +; ff_h264_idct8_dc_add_mmxext(uint8_t *dst, int16_t *block, int stride) +cglobal h264_idct8_dc_add_8, 3, 4, 0 + movsx r3, word [r1] + mov word [r1], 0 + DC_ADD_MMXEXT_INIT r3, r2 + DC_ADD_MMXEXT_OP mova, r0, r2, r3 + lea r0, [r0+r2*4] + DC_ADD_MMXEXT_OP mova, r0, r2, r3 + RET +%else +cglobal h264_idct_dc_add_8, 2, 3, 0 + movsx r2, word [r1] + mov word [r1], 0 + mov r1, r2m + DC_ADD_MMXEXT_INIT r2, r1 + DC_ADD_MMXEXT_OP movh, r0, r1, r2 + RET + +; ff_h264_idct8_dc_add_mmxext(uint8_t *dst, int16_t *block, int stride) +cglobal h264_idct8_dc_add_8, 2, 3, 0 + movsx r2, word [r1] + mov word [r1], 0 + mov r1, r2m + DC_ADD_MMXEXT_INIT r2, r1 + DC_ADD_MMXEXT_OP mova, r0, r1, r2 + lea r0, [r0+r1*4] + DC_ADD_MMXEXT_OP mova, r0, r1, r2 + RET +%endif + +INIT_MMX mmx +; ff_h264_idct_add16_mmx(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add16_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .skipblock + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6] + IDCT4_ADD r6, r2, r3 +.skipblock: + inc r5 + add r2, 32 + cmp r5, 16 + jl .nextblock + REP_RET + +; ff_h264_idct8_add4_mmx(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct8_add4_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg + %assign pad 128+4-(stack_offset&7) + SUB rsp, pad + + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .skipblock + mov r6d, dword [r1+r5*4] + add r6, r0 + add word [r2], 32 + IDCT8_ADD_MMX_START r2 , rsp + IDCT8_ADD_MMX_START r2+8, rsp+64 + IDCT8_ADD_MMX_END r6 , rsp, r3, r2 + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6+4] + IDCT8_ADD_MMX_END r6 , rsp+8, r3 +.skipblock: + add r5, 4 + add r2, 128 + cmp r5, 16 + jl .nextblock + ADD rsp, pad + RET + +INIT_MMX mmxext +; ff_h264_idct_add16_mmxext(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add16_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .skipblock + cmp r6, 1 + jnz .no_dc + movsx r6, word [r2] + test r6, r6 + jz .no_dc + mov word [r2], 0 + DC_ADD_MMXEXT_INIT r6, r3 +%if ARCH_X86_64 == 0 +%define dst2q r1 +%define dst2d r1d +%endif + mov dst2d, dword [r1+r5*4] + lea dst2q, [r0+dst2q] + DC_ADD_MMXEXT_OP movh, dst2q, r3, r6 +%if ARCH_X86_64 == 0 + mov r1, r1m +%endif + inc r5 + add r2, 32 + cmp r5, 16 + jl .nextblock + REP_RET +.no_dc: + mov r6d, dword [r1+r5*4] + add r6, r0 + IDCT4_ADD r6, r2, r3 +.skipblock: + inc r5 + add r2, 32 + cmp r5, 16 + jl .nextblock + REP_RET + +INIT_MMX mmx +; ff_h264_idct_add16intra_mmx(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add16intra_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + or r6w, word [r2] + test r6, r6 + jz .skipblock + mov r6d, dword [r1+r5*4] + add r6, r0 + IDCT4_ADD r6, r2, r3 +.skipblock: + inc r5 + add r2, 32 + cmp r5, 16 + jl .nextblock + REP_RET + +INIT_MMX mmxext +; ff_h264_idct_add16intra_mmxext(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6*8]) +cglobal h264_idct_add16intra_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .try_dc + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6] + IDCT4_ADD r6, r2, r3 + inc r5 + add r2, 32 + cmp r5, 16 + jl .nextblock + REP_RET +.try_dc: + movsx r6, word [r2] + test r6, r6 + jz .skipblock + mov word [r2], 0 + DC_ADD_MMXEXT_INIT r6, r3 +%if ARCH_X86_64 == 0 +%define dst2q r1 +%define dst2d r1d +%endif + mov dst2d, dword [r1+r5*4] + add dst2q, r0 + DC_ADD_MMXEXT_OP movh, dst2q, r3, r6 +%if ARCH_X86_64 == 0 + mov r1, r1m +%endif +.skipblock: + inc r5 + add r2, 32 + cmp r5, 16 + jl .nextblock + REP_RET + +; ff_h264_idct8_add4_mmxext(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, +; const uint8_t nnzc[6*8]) +cglobal h264_idct8_add4_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + %assign pad 128+4-(stack_offset&7) + SUB rsp, pad + + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .skipblock + cmp r6, 1 + jnz .no_dc + movsx r6, word [r2] + test r6, r6 + jz .no_dc + mov word [r2], 0 + DC_ADD_MMXEXT_INIT r6, r3 +%if ARCH_X86_64 == 0 +%define dst2q r1 +%define dst2d r1d +%endif + mov dst2d, dword [r1+r5*4] + lea dst2q, [r0+dst2q] + DC_ADD_MMXEXT_OP mova, dst2q, r3, r6 + lea dst2q, [dst2q+r3*4] + DC_ADD_MMXEXT_OP mova, dst2q, r3, r6 +%if ARCH_X86_64 == 0 + mov r1, r1m +%endif + add r5, 4 + add r2, 128 + cmp r5, 16 + jl .nextblock + + ADD rsp, pad + RET +.no_dc: + mov r6d, dword [r1+r5*4] + add r6, r0 + add word [r2], 32 + IDCT8_ADD_MMX_START r2 , rsp + IDCT8_ADD_MMX_START r2+8, rsp+64 + IDCT8_ADD_MMX_END r6 , rsp, r3, r2 + mov r6d, dword [r1+r5*4] + lea r6, [r0+r6+4] + IDCT8_ADD_MMX_END r6 , rsp+8, r3 +.skipblock: + add r5, 4 + add r2, 128 + cmp r5, 16 + jl .nextblock + + ADD rsp, pad + RET + +INIT_XMM sse2 +; ff_h264_idct8_add4_sse2(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct8_add4_8, 5, 8 + npicregs, 10, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + xor r5, r5 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .skipblock + cmp r6, 1 + jnz .no_dc + movsx r6, word [r2] + test r6, r6 + jz .no_dc +INIT_MMX cpuname + mov word [r2], 0 + DC_ADD_MMXEXT_INIT r6, r3 +%if ARCH_X86_64 == 0 +%define dst2q r1 +%define dst2d r1d +%endif + mov dst2d, dword [r1+r5*4] + add dst2q, r0 + DC_ADD_MMXEXT_OP mova, dst2q, r3, r6 + lea dst2q, [dst2q+r3*4] + DC_ADD_MMXEXT_OP mova, dst2q, r3, r6 +%if ARCH_X86_64 == 0 + mov r1, r1m +%endif + add r5, 4 + add r2, 128 + cmp r5, 16 + jl .nextblock + REP_RET +.no_dc: +INIT_XMM cpuname + mov dst2d, dword [r1+r5*4] + add dst2q, r0 + IDCT8_ADD_SSE dst2q, r2, r3, r6 +%if ARCH_X86_64 == 0 + mov r1, r1m +%endif +.skipblock: + add r5, 4 + add r2, 128 + cmp r5, 16 + jl .nextblock + REP_RET + +INIT_MMX mmx +h264_idct_add8_mmx_plane: +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + or r6w, word [r2] + test r6, r6 + jz .skipblock +%if ARCH_X86_64 + mov r0d, dword [r1+r5*4] + add r0, [dst2q] +%else + mov r0, r1m ; XXX r1m here is actually r0m of the calling func + mov r0, [r0] + add r0, dword [r1+r5*4] +%endif + IDCT4_ADD r0, r2, r3 +.skipblock: + inc r5 + add r2, 32 + test r5, 3 + jnz .nextblock + rep ret + +; ff_h264_idct_add8_mmx(uint8_t **dest, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + mov r5, 16 + add r2, 512 +%ifdef PIC + lea picregq, [scan8_mem] +%endif +%if ARCH_X86_64 + mov dst2q, r0 +%endif + call h264_idct_add8_mmx_plane + mov r5, 32 + add r2, 384 +%if ARCH_X86_64 + add dst2q, gprsize +%else + add r0mp, gprsize +%endif + call h264_idct_add8_mmx_plane + RET + +h264_idct_add8_mmxext_plane: +.nextblock: + movzx r6, byte [scan8+r5] + movzx r6, byte [r4+r6] + test r6, r6 + jz .try_dc +%if ARCH_X86_64 + mov r0d, dword [r1+r5*4] + add r0, [dst2q] +%else + mov r0, r1m ; XXX r1m here is actually r0m of the calling func + mov r0, [r0] + add r0, dword [r1+r5*4] +%endif + IDCT4_ADD r0, r2, r3 + inc r5 + add r2, 32 + test r5, 3 + jnz .nextblock + rep ret +.try_dc: + movsx r6, word [r2] + test r6, r6 + jz .skipblock + mov word [r2], 0 + DC_ADD_MMXEXT_INIT r6, r3 +%if ARCH_X86_64 + mov r0d, dword [r1+r5*4] + add r0, [dst2q] +%else + mov r0, r1m ; XXX r1m here is actually r0m of the calling func + mov r0, [r0] + add r0, dword [r1+r5*4] +%endif + DC_ADD_MMXEXT_OP movh, r0, r3, r6 +.skipblock: + inc r5 + add r2, 32 + test r5, 3 + jnz .nextblock + rep ret + +INIT_MMX mmxext +; ff_h264_idct_add8_mmxext(uint8_t **dest, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg + mov r5, 16 + add r2, 512 +%if ARCH_X86_64 + mov dst2q, r0 +%endif +%ifdef PIC + lea picregq, [scan8_mem] +%endif + call h264_idct_add8_mmxext_plane + mov r5, 32 + add r2, 384 +%if ARCH_X86_64 + add dst2q, gprsize +%else + add r0mp, gprsize +%endif + call h264_idct_add8_mmxext_plane + RET + +; r0 = uint8_t *dst, r2 = int16_t *block, r3 = int stride, r6=clobbered +h264_idct_dc_add8_mmxext: + movd m0, [r2 ] ; 0 0 X D + mov word [r2+ 0], 0 + punpcklwd m0, [r2+32] ; x X d D + mov word [r2+32], 0 + paddsw m0, [pw_32] + psraw m0, 6 + punpcklwd m0, m0 ; d d D D + pxor m1, m1 ; 0 0 0 0 + psubw m1, m0 ; -d-d-D-D + packuswb m0, m1 ; -d-d-D-D d d D D + pshufw m1, m0, 0xFA ; -d-d-d-d-D-D-D-D + punpcklwd m0, m0 ; d d d d D D D D + lea r6, [r3*3] + DC_ADD_MMXEXT_OP movq, r0, r3, r6 + ret + +ALIGN 16 +INIT_XMM sse2 +; r0 = uint8_t *dst (clobbered), r2 = int16_t *block, r3 = int stride +h264_add8x4_idct_sse2: + movq m0, [r2+ 0] + movq m1, [r2+ 8] + movq m2, [r2+16] + movq m3, [r2+24] + movhps m0, [r2+32] + movhps m1, [r2+40] + movhps m2, [r2+48] + movhps m3, [r2+56] + IDCT4_1D w,0,1,2,3,4,5 + TRANSPOSE2x4x4W 0,1,2,3,4 + paddw m0, [pw_32] + IDCT4_1D w,0,1,2,3,4,5 + pxor m7, m7 + mova [r2+ 0], m7 + mova [r2+16], m7 + mova [r2+32], m7 + mova [r2+48], m7 + STORE_DIFFx2 m0, m1, m4, m5, m7, 6, r0, r3 + lea r0, [r0+r3*2] + STORE_DIFFx2 m2, m3, m4, m5, m7, 6, r0, r3 + ret + +%macro add16_sse2_cycle 2 + movzx r0, word [r4+%2] + test r0, r0 + jz .cycle%1end + mov r0d, dword [r1+%1*8] +%if ARCH_X86_64 + add r0, r5 +%else + add r0, r0m +%endif + call h264_add8x4_idct_sse2 +.cycle%1end: +%if %1 < 7 + add r2, 64 +%endif +%endmacro + +; ff_h264_idct_add16_sse2(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add16_8, 5, 5 + ARCH_X86_64, 8 +%if ARCH_X86_64 + mov r5, r0 +%endif + ; unrolling of the loop leads to an average performance gain of + ; 20-25% + add16_sse2_cycle 0, 0xc + add16_sse2_cycle 1, 0x14 + add16_sse2_cycle 2, 0xe + add16_sse2_cycle 3, 0x16 + add16_sse2_cycle 4, 0x1c + add16_sse2_cycle 5, 0x24 + add16_sse2_cycle 6, 0x1e + add16_sse2_cycle 7, 0x26 + RET + +%macro add16intra_sse2_cycle 2 + movzx r0, word [r4+%2] + test r0, r0 + jz .try%1dc + mov r0d, dword [r1+%1*8] +%if ARCH_X86_64 + add r0, r7 +%else + add r0, r0m +%endif + call h264_add8x4_idct_sse2 + jmp .cycle%1end +.try%1dc: + movsx r0, word [r2 ] + or r0w, word [r2+32] + jz .cycle%1end + mov r0d, dword [r1+%1*8] +%if ARCH_X86_64 + add r0, r7 +%else + add r0, r0m +%endif + call h264_idct_dc_add8_mmxext +.cycle%1end: +%if %1 < 7 + add r2, 64 +%endif +%endmacro + +; ff_h264_idct_add16intra_sse2(uint8_t *dst, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add16intra_8, 5, 7 + ARCH_X86_64, 8 +%if ARCH_X86_64 + mov r7, r0 +%endif + add16intra_sse2_cycle 0, 0xc + add16intra_sse2_cycle 1, 0x14 + add16intra_sse2_cycle 2, 0xe + add16intra_sse2_cycle 3, 0x16 + add16intra_sse2_cycle 4, 0x1c + add16intra_sse2_cycle 5, 0x24 + add16intra_sse2_cycle 6, 0x1e + add16intra_sse2_cycle 7, 0x26 + RET + +%macro add8_sse2_cycle 2 + movzx r0, word [r4+%2] + test r0, r0 + jz .try%1dc +%if ARCH_X86_64 + mov r0d, dword [r1+(%1&1)*8+64*(1+(%1>>1))] + add r0, [r7] +%else + mov r0, r0m + mov r0, [r0] + add r0, dword [r1+(%1&1)*8+64*(1+(%1>>1))] +%endif + call h264_add8x4_idct_sse2 + jmp .cycle%1end +.try%1dc: + movsx r0, word [r2 ] + or r0w, word [r2+32] + jz .cycle%1end +%if ARCH_X86_64 + mov r0d, dword [r1+(%1&1)*8+64*(1+(%1>>1))] + add r0, [r7] +%else + mov r0, r0m + mov r0, [r0] + add r0, dword [r1+(%1&1)*8+64*(1+(%1>>1))] +%endif + call h264_idct_dc_add8_mmxext +.cycle%1end: +%if %1 == 1 + add r2, 384+64 +%elif %1 < 3 + add r2, 64 +%endif +%endmacro + +; ff_h264_idct_add8_sse2(uint8_t **dest, const int *block_offset, +; int16_t *block, int stride, const uint8_t nnzc[6*8]) +cglobal h264_idct_add8_8, 5, 7 + ARCH_X86_64, 8 + add r2, 512 +%if ARCH_X86_64 + mov r7, r0 +%endif + add8_sse2_cycle 0, 0x34 + add8_sse2_cycle 1, 0x3c +%if ARCH_X86_64 + add r7, gprsize +%else + add r0mp, gprsize +%endif + add8_sse2_cycle 2, 0x5c + add8_sse2_cycle 3, 0x64 + RET + +;void ff_h264_luma_dc_dequant_idct_mmx(int16_t *output, int16_t *input, int qmul) + +%macro WALSH4_1D 5 + SUMSUB_BADC w, %4, %3, %2, %1, %5 + SUMSUB_BADC w, %4, %2, %3, %1, %5 + SWAP %1, %4, %3 +%endmacro + +%macro DEQUANT_MMX 3 + mova m7, [pw_1] + mova m4, %1 + punpcklwd %1, m7 + punpckhwd m4, m7 + mova m5, %2 + punpcklwd %2, m7 + punpckhwd m5, m7 + movd m7, t3d + punpckldq m7, m7 + pmaddwd %1, m7 + pmaddwd %2, m7 + pmaddwd m4, m7 + pmaddwd m5, m7 + psrad %1, %3 + psrad %2, %3 + psrad m4, %3 + psrad m5, %3 + packssdw %1, m4 + packssdw %2, m5 +%endmacro + +%macro STORE_WORDS 5-9 +%if cpuflag(sse) + movd t0d, %1 + psrldq %1, 4 + movd t1d, %1 + psrldq %1, 4 + mov [t2+%2*32], t0w + mov [t2+%4*32], t1w + shr t0d, 16 + shr t1d, 16 + mov [t2+%3*32], t0w + mov [t2+%5*32], t1w + movd t0d, %1 + psrldq %1, 4 + movd t1d, %1 + mov [t2+%6*32], t0w + mov [t2+%8*32], t1w + shr t0d, 16 + shr t1d, 16 + mov [t2+%7*32], t0w + mov [t2+%9*32], t1w +%else + movd t0d, %1 + psrlq %1, 32 + movd t1d, %1 + mov [t2+%2*32], t0w + mov [t2+%4*32], t1w + shr t0d, 16 + shr t1d, 16 + mov [t2+%3*32], t0w + mov [t2+%5*32], t1w +%endif +%endmacro + +%macro DEQUANT_STORE 1 +%if cpuflag(sse2) + movd xmm4, t3d + movq xmm5, [pw_1] + pshufd xmm4, xmm4, 0 + movq2dq xmm0, m0 + movq2dq xmm1, m1 + movq2dq xmm2, m2 + movq2dq xmm3, m3 + punpcklwd xmm0, xmm5 + punpcklwd xmm1, xmm5 + punpcklwd xmm2, xmm5 + punpcklwd xmm3, xmm5 + pmaddwd xmm0, xmm4 + pmaddwd xmm1, xmm4 + pmaddwd xmm2, xmm4 + pmaddwd xmm3, xmm4 + psrad xmm0, %1 + psrad xmm1, %1 + psrad xmm2, %1 + psrad xmm3, %1 + packssdw xmm0, xmm1 + packssdw xmm2, xmm3 + STORE_WORDS xmm0, 0, 1, 4, 5, 2, 3, 6, 7 + STORE_WORDS xmm2, 8, 9, 12, 13, 10, 11, 14, 15 +%else + DEQUANT_MMX m0, m1, %1 + STORE_WORDS m0, 0, 1, 4, 5 + STORE_WORDS m1, 2, 3, 6, 7 + + DEQUANT_MMX m2, m3, %1 + STORE_WORDS m2, 8, 9, 12, 13 + STORE_WORDS m3, 10, 11, 14, 15 +%endif +%endmacro + +%macro IDCT_DC_DEQUANT 1 +cglobal h264_luma_dc_dequant_idct, 3, 4, %1 + ; manually spill XMM registers for Win64 because + ; the code here is initialized with INIT_MMX + WIN64_SPILL_XMM %1 + movq m3, [r1+24] + movq m2, [r1+16] + movq m1, [r1+ 8] + movq m0, [r1+ 0] + WALSH4_1D 0,1,2,3,4 + TRANSPOSE4x4W 0,1,2,3,4 + WALSH4_1D 0,1,2,3,4 + +; shift, tmp, output, qmul +%if WIN64 + DECLARE_REG_TMP 0,3,1,2 + ; we can't avoid this, because r0 is the shift register (ecx) on win64 + xchg r0, t2 +%elif ARCH_X86_64 + DECLARE_REG_TMP 3,1,0,2 +%else + DECLARE_REG_TMP 1,3,0,2 +%endif + + cmp t3d, 32767 + jg .big_qmul + add t3d, 128 << 16 + DEQUANT_STORE 8 + RET +.big_qmul: + bsr t0d, t3d + add t3d, 128 << 16 + mov t1d, 7 + cmp t0d, t1d + cmovg t0d, t1d + inc t1d + shr t3d, t0b + sub t1d, t0d +%if cpuflag(sse2) + movd xmm6, t1d + DEQUANT_STORE xmm6 +%else + movd m6, t1d + DEQUANT_STORE m6 +%endif + RET +%endmacro + +INIT_MMX mmx +IDCT_DC_DEQUANT 0 +INIT_MMX sse2 +IDCT_DC_DEQUANT 7 diff --git a/ffmpeg/libavcodec/x86/h264_idct_10bit.asm b/ffmpeg/libavcodec/x86/h264_idct_10bit.asm new file mode 100644 index 0000000..88fdb84 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_idct_10bit.asm @@ -0,0 +1,589 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 iDCT code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Daniel Kang +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pw_pixel_max: times 8 dw ((1 << 10)-1) +pd_32: times 4 dd 32 + +SECTION .text + +;----------------------------------------------------------------------------- +; void h264_idct_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro STORE_DIFFx2 6 + psrad %1, 6 + psrad %2, 6 + packssdw %1, %2 + movq %3, [%5] + movhps %3, [%5+%6] + paddsw %1, %3 + CLIPW %1, %4, [pw_pixel_max] + movq [%5], %1 + movhps [%5+%6], %1 +%endmacro + +%macro STORE_DIFF16 5 + psrad %1, 6 + psrad %2, 6 + packssdw %1, %2 + paddsw %1, [%5] + CLIPW %1, %3, %4 + mova [%5], %1 +%endmacro + +;dst, in, stride +%macro IDCT4_ADD_10 3 + mova m0, [%2+ 0] + mova m1, [%2+16] + mova m2, [%2+32] + mova m3, [%2+48] + IDCT4_1D d,0,1,2,3,4,5 + TRANSPOSE4x4D 0,1,2,3,4 + paddd m0, [pd_32] + IDCT4_1D d,0,1,2,3,4,5 + pxor m5, m5 + mova [%2+ 0], m5 + mova [%2+16], m5 + mova [%2+32], m5 + mova [%2+48], m5 + STORE_DIFFx2 m0, m1, m4, m5, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m2, m3, m4, m5, %1, %3 +%endmacro + +%macro IDCT_ADD_10 0 +cglobal h264_idct_add_10, 3,3 + IDCT4_ADD_10 r0, r1, r2 + RET +%endmacro + +INIT_XMM sse2 +IDCT_ADD_10 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +IDCT_ADD_10 +%endif + +;----------------------------------------------------------------------------- +; h264_idct_add16(pixel *dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +;;;;;;; NO FATE SAMPLES TRIGGER THIS +%macro ADD4x4IDCT 0 +add4x4_idct %+ SUFFIX: + add r5, r0 + mova m0, [r2+ 0] + mova m1, [r2+16] + mova m2, [r2+32] + mova m3, [r2+48] + IDCT4_1D d,0,1,2,3,4,5 + TRANSPOSE4x4D 0,1,2,3,4 + paddd m0, [pd_32] + IDCT4_1D d,0,1,2,3,4,5 + pxor m5, m5 + mova [r2+ 0], m5 + mova [r2+16], m5 + mova [r2+32], m5 + mova [r2+48], m5 + STORE_DIFFx2 m0, m1, m4, m5, r5, r3 + lea r5, [r5+r3*2] + STORE_DIFFx2 m2, m3, m4, m5, r5, r3 + ret +%endmacro + +INIT_XMM sse2 +ALIGN 16 +ADD4x4IDCT +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +ALIGN 16 +ADD4x4IDCT +%endif + +%macro ADD16_OP 2 + cmp byte [r4+%2], 0 + jz .skipblock%1 + mov r5d, [r1+%1*4] + call add4x4_idct %+ SUFFIX +.skipblock%1: +%if %1<15 + add r2, 64 +%endif +%endmacro + +%macro IDCT_ADD16_10 0 +cglobal h264_idct_add16_10, 5,6 + ADD16_OP 0, 4+1*8 + ADD16_OP 1, 5+1*8 + ADD16_OP 2, 4+2*8 + ADD16_OP 3, 5+2*8 + ADD16_OP 4, 6+1*8 + ADD16_OP 5, 7+1*8 + ADD16_OP 6, 6+2*8 + ADD16_OP 7, 7+2*8 + ADD16_OP 8, 4+3*8 + ADD16_OP 9, 5+3*8 + ADD16_OP 10, 4+4*8 + ADD16_OP 11, 5+4*8 + ADD16_OP 12, 6+3*8 + ADD16_OP 13, 7+3*8 + ADD16_OP 14, 6+4*8 + ADD16_OP 15, 7+4*8 + REP_RET +%endmacro + +INIT_XMM sse2 +IDCT_ADD16_10 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +IDCT_ADD16_10 +%endif + +;----------------------------------------------------------------------------- +; void h264_idct_dc_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT_DC_ADD_OP_10 3 + pxor m5, m5 +%if avx_enabled + paddw m1, m0, [%1+0 ] + paddw m2, m0, [%1+%2 ] + paddw m3, m0, [%1+%2*2] + paddw m4, m0, [%1+%3 ] +%else + mova m1, [%1+0 ] + mova m2, [%1+%2 ] + mova m3, [%1+%2*2] + mova m4, [%1+%3 ] + paddw m1, m0 + paddw m2, m0 + paddw m3, m0 + paddw m4, m0 +%endif + CLIPW m1, m5, m6 + CLIPW m2, m5, m6 + CLIPW m3, m5, m6 + CLIPW m4, m5, m6 + mova [%1+0 ], m1 + mova [%1+%2 ], m2 + mova [%1+%2*2], m3 + mova [%1+%3 ], m4 +%endmacro + +INIT_MMX mmxext +cglobal h264_idct_dc_add_10,3,3 + movd m0, [r1] + mov dword [r1], 0 + paddd m0, [pd_32] + psrad m0, 6 + lea r1, [r2*3] + pshufw m0, m0, 0 + mova m6, [pw_pixel_max] + IDCT_DC_ADD_OP_10 r0, r2, r1 + RET + +;----------------------------------------------------------------------------- +; void h264_idct8_dc_add(pixel *dst, dctcoef *block, int stride) +;----------------------------------------------------------------------------- +%macro IDCT8_DC_ADD 0 +cglobal h264_idct8_dc_add_10,3,4,7 + movd m0, [r1] + mov dword[r1], 0 + paddd m0, [pd_32] + psrad m0, 6 + lea r1, [r2*3] + SPLATW m0, m0, 0 + mova m6, [pw_pixel_max] + IDCT_DC_ADD_OP_10 r0, r2, r1 + lea r0, [r0+r2*4] + IDCT_DC_ADD_OP_10 r0, r2, r1 + RET +%endmacro + +INIT_XMM sse2 +IDCT8_DC_ADD +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +IDCT8_DC_ADD +%endif + +;----------------------------------------------------------------------------- +; h264_idct_add16intra(pixel *dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +%macro AC 1 +.ac%1: + mov r5d, [r1+(%1+0)*4] + call add4x4_idct %+ SUFFIX + mov r5d, [r1+(%1+1)*4] + add r2, 64 + call add4x4_idct %+ SUFFIX + add r2, 64 + jmp .skipadd%1 +%endmacro + +%assign last_block 16 +%macro ADD16_OP_INTRA 2 + cmp word [r4+%2], 0 + jnz .ac%1 + mov r5d, [r2+ 0] + or r5d, [r2+64] + jz .skipblock%1 + mov r5d, [r1+(%1+0)*4] + call idct_dc_add %+ SUFFIX +.skipblock%1: +%if %1 01234567 +%endmacro + +%macro IDCT8_1D_FULL 1 + mova m7, [%1+112*2] + mova m6, [%1+ 96*2] + mova m5, [%1+ 80*2] + mova m3, [%1+ 48*2] + mova m2, [%1+ 32*2] + mova m1, [%1+ 16*2] + IDCT8_1D [%1], [%1+ 64*2] +%endmacro + +; %1=int16_t *block, %2=int16_t *dstblock +%macro IDCT8_ADD_SSE_START 2 + IDCT8_1D_FULL %1 +%if ARCH_X86_64 + TRANSPOSE4x4D 0,1,2,3,8 + mova [%2 ], m0 + TRANSPOSE4x4D 4,5,6,7,8 + mova [%2+8*2], m4 +%else + mova [%1], m7 + TRANSPOSE4x4D 0,1,2,3,7 + mova m7, [%1] + mova [%2 ], m0 + mova [%2+16*2], m1 + mova [%2+32*2], m2 + mova [%2+48*2], m3 + TRANSPOSE4x4D 4,5,6,7,3 + mova [%2+ 8*2], m4 + mova [%2+24*2], m5 + mova [%2+40*2], m6 + mova [%2+56*2], m7 +%endif +%endmacro + +; %1=uint8_t *dst, %2=int16_t *block, %3=int stride +%macro IDCT8_ADD_SSE_END 3 + IDCT8_1D_FULL %2 + mova [%2 ], m6 + mova [%2+16*2], m7 + + pxor m7, m7 + STORE_DIFFx2 m0, m1, m6, m7, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m2, m3, m6, m7, %1, %3 + mova m0, [%2 ] + mova m1, [%2+16*2] + lea %1, [%1+%3*2] + STORE_DIFFx2 m4, m5, m6, m7, %1, %3 + lea %1, [%1+%3*2] + STORE_DIFFx2 m0, m1, m6, m7, %1, %3 +%endmacro + +%macro IDCT8_ADD 0 +cglobal h264_idct8_add_10, 3,4,16 +%if UNIX64 == 0 + %assign pad 16-gprsize-(stack_offset&15) + sub rsp, pad + call h264_idct8_add1_10 %+ SUFFIX + add rsp, pad + RET +%endif + +ALIGN 16 +; TODO: does not need to use stack +h264_idct8_add1_10 %+ SUFFIX: +%assign pad 256+16-gprsize + sub rsp, pad + add dword [r1], 32 + +%if ARCH_X86_64 + IDCT8_ADD_SSE_START r1, rsp + SWAP 1, 9 + SWAP 2, 10 + SWAP 3, 11 + SWAP 5, 13 + SWAP 6, 14 + SWAP 7, 15 + IDCT8_ADD_SSE_START r1+16, rsp+128 + PERMUTE 1,9, 2,10, 3,11, 5,1, 6,2, 7,3, 9,13, 10,14, 11,15, 13,5, 14,6, 15,7 + IDCT8_1D [rsp], [rsp+128] + SWAP 0, 8 + SWAP 1, 9 + SWAP 2, 10 + SWAP 3, 11 + SWAP 4, 12 + SWAP 5, 13 + SWAP 6, 14 + SWAP 7, 15 + IDCT8_1D [rsp+16], [rsp+144] + psrad m8, 6 + psrad m0, 6 + packssdw m8, m0 + paddsw m8, [r0] + pxor m0, m0 + mova [r1+ 0], m0 + mova [r1+ 16], m0 + mova [r1+ 32], m0 + mova [r1+ 48], m0 + mova [r1+ 64], m0 + mova [r1+ 80], m0 + mova [r1+ 96], m0 + mova [r1+112], m0 + mova [r1+128], m0 + mova [r1+144], m0 + mova [r1+160], m0 + mova [r1+176], m0 + mova [r1+192], m0 + mova [r1+208], m0 + mova [r1+224], m0 + mova [r1+240], m0 + CLIPW m8, m0, [pw_pixel_max] + mova [r0], m8 + mova m8, [pw_pixel_max] + STORE_DIFF16 m9, m1, m0, m8, r0+r2 + lea r0, [r0+r2*2] + STORE_DIFF16 m10, m2, m0, m8, r0 + STORE_DIFF16 m11, m3, m0, m8, r0+r2 + lea r0, [r0+r2*2] + STORE_DIFF16 m12, m4, m0, m8, r0 + STORE_DIFF16 m13, m5, m0, m8, r0+r2 + lea r0, [r0+r2*2] + STORE_DIFF16 m14, m6, m0, m8, r0 + STORE_DIFF16 m15, m7, m0, m8, r0+r2 +%else + IDCT8_ADD_SSE_START r1, rsp + IDCT8_ADD_SSE_START r1+16, rsp+128 + lea r3, [r0+8] + IDCT8_ADD_SSE_END r0, rsp, r2 + IDCT8_ADD_SSE_END r3, rsp+16, r2 + mova [r1+ 0], m7 + mova [r1+ 16], m7 + mova [r1+ 32], m7 + mova [r1+ 48], m7 + mova [r1+ 64], m7 + mova [r1+ 80], m7 + mova [r1+ 96], m7 + mova [r1+112], m7 + mova [r1+128], m7 + mova [r1+144], m7 + mova [r1+160], m7 + mova [r1+176], m7 + mova [r1+192], m7 + mova [r1+208], m7 + mova [r1+224], m7 + mova [r1+240], m7 +%endif ; ARCH_X86_64 + + add rsp, pad + ret +%endmacro + +INIT_XMM sse2 +IDCT8_ADD +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +IDCT8_ADD +%endif + +;----------------------------------------------------------------------------- +; h264_idct8_add4(pixel **dst, const int *block_offset, dctcoef *block, int stride, const uint8_t nnzc[6*8]) +;----------------------------------------------------------------------------- +;;;;;;; NO FATE SAMPLES TRIGGER THIS +%macro IDCT8_ADD4_OP 2 + cmp byte [r4+%2], 0 + jz .skipblock%1 + mov r0d, [r6+%1*4] + add r0, r5 + call h264_idct8_add1_10 %+ SUFFIX +.skipblock%1: +%if %1<12 + add r1, 256 +%endif +%endmacro + +%macro IDCT8_ADD4 0 +cglobal h264_idct8_add4_10, 0,7,16 + %assign pad 16-gprsize-(stack_offset&15) + SUB rsp, pad + mov r5, r0mp + mov r6, r1mp + mov r1, r2mp + mov r2d, r3m + movifnidn r4, r4mp + IDCT8_ADD4_OP 0, 4+1*8 + IDCT8_ADD4_OP 4, 6+1*8 + IDCT8_ADD4_OP 8, 4+3*8 + IDCT8_ADD4_OP 12, 6+3*8 + ADD rsp, pad + RET +%endmacro ; IDCT8_ADD4 + +INIT_XMM sse2 +IDCT8_ADD4 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +IDCT8_ADD4 +%endif diff --git a/ffmpeg/libavcodec/x86/h264_intrapred.asm b/ffmpeg/libavcodec/x86/h264_intrapred.asm new file mode 100644 index 0000000..5c0dff4 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_intrapred.asm @@ -0,0 +1,2702 @@ +;****************************************************************************** +;* H.264 intra prediction asm optimizations +;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (c) 2010 Holger Lubitz +;* Copyright (c) 2010 Loren Merritt +;* Copyright (c) 2010 Ronald S. Bultje +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +tm_shuf: times 8 db 0x03, 0x80 +pw_ff00: times 8 dw 0xff00 +plane_shuf: db -8, -7, -6, -5, -4, -3, -2, -1 + db 1, 2, 3, 4, 5, 6, 7, 8 +plane8_shuf: db -4, -3, -2, -1, 0, 0, 0, 0 + db 1, 2, 3, 4, 0, 0, 0, 0 +pw_0to7: dw 0, 1, 2, 3, 4, 5, 6, 7 +pw_1to8: dw 1, 2, 3, 4, 5, 6, 7, 8 +pw_m8tom1: dw -8, -7, -6, -5, -4, -3, -2, -1 +pw_m4to4: dw -4, -3, -2, -1, 1, 2, 3, 4 + +SECTION .text + +cextern pb_1 +cextern pb_3 +cextern pw_4 +cextern pw_5 +cextern pw_8 +cextern pw_16 +cextern pw_17 +cextern pw_32 + +;----------------------------------------------------------------------------- +; void pred16x16_vertical_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmx +cglobal pred16x16_vertical_8, 2,3 + sub r0, r1 + mov r2, 8 + movq mm0, [r0+0] + movq mm1, [r0+8] +.loop: + movq [r0+r1*1+0], mm0 + movq [r0+r1*1+8], mm1 + movq [r0+r1*2+0], mm0 + movq [r0+r1*2+8], mm1 + lea r0, [r0+r1*2] + dec r2 + jg .loop + REP_RET + +INIT_XMM sse +cglobal pred16x16_vertical_8, 2,3 + sub r0, r1 + mov r2, 4 + movaps xmm0, [r0] +.loop: + movaps [r0+r1*1], xmm0 + movaps [r0+r1*2], xmm0 + lea r0, [r0+r1*2] + movaps [r0+r1*1], xmm0 + movaps [r0+r1*2], xmm0 + lea r0, [r0+r1*2] + dec r2 + jg .loop + REP_RET + +;----------------------------------------------------------------------------- +; void pred16x16_horizontal_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro PRED16x16_H 0 +cglobal pred16x16_horizontal_8, 2,3 + mov r2, 8 +%if cpuflag(ssse3) + mova m2, [pb_3] +%endif +.loop: + movd m0, [r0+r1*0-4] + movd m1, [r0+r1*1-4] + +%if cpuflag(ssse3) + pshufb m0, m2 + pshufb m1, m2 +%else + punpcklbw m0, m0 + punpcklbw m1, m1 + SPLATW m0, m0, 3 + SPLATW m1, m1, 3 + mova [r0+r1*0+8], m0 + mova [r0+r1*1+8], m1 +%endif + + mova [r0+r1*0], m0 + mova [r0+r1*1], m1 + lea r0, [r0+r1*2] + dec r2 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +PRED16x16_H +INIT_MMX mmxext +PRED16x16_H +INIT_XMM ssse3 +PRED16x16_H + +;----------------------------------------------------------------------------- +; void pred16x16_dc_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro PRED16x16_DC 0 +cglobal pred16x16_dc_8, 2,7 + mov r4, r0 + sub r0, r1 + pxor mm0, mm0 + pxor mm1, mm1 + psadbw mm0, [r0+0] + psadbw mm1, [r0+8] + dec r0 + movzx r5d, byte [r0+r1*1] + paddw mm0, mm1 + movd r6d, mm0 + lea r0, [r0+r1*2] +%rep 7 + movzx r2d, byte [r0+r1*0] + movzx r3d, byte [r0+r1*1] + add r5d, r2d + add r6d, r3d + lea r0, [r0+r1*2] +%endrep + movzx r2d, byte [r0+r1*0] + add r5d, r6d + lea r2d, [r2+r5+16] + shr r2d, 5 +%if cpuflag(ssse3) + pxor m1, m1 +%endif + SPLATB_REG m0, r2, m1 + +%if mmsize==8 + mov r3d, 8 +.loop: + mova [r4+r1*0+0], m0 + mova [r4+r1*0+8], m0 + mova [r4+r1*1+0], m0 + mova [r4+r1*1+8], m0 +%else + mov r3d, 4 +.loop: + mova [r4+r1*0], m0 + mova [r4+r1*1], m0 + lea r4, [r4+r1*2] + mova [r4+r1*0], m0 + mova [r4+r1*1], m0 +%endif + lea r4, [r4+r1*2] + dec r3d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_DC +INIT_XMM sse2 +PRED16x16_DC +INIT_XMM ssse3 +PRED16x16_DC + +;----------------------------------------------------------------------------- +; void pred16x16_tm_vp8_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro PRED16x16_TM 0 +cglobal pred16x16_tm_vp8_8, 2,5 + sub r0, r1 + pxor mm7, mm7 + movq mm0, [r0+0] + movq mm2, [r0+8] + movq mm1, mm0 + movq mm3, mm2 + punpcklbw mm0, mm7 + punpckhbw mm1, mm7 + punpcklbw mm2, mm7 + punpckhbw mm3, mm7 + movzx r3d, byte [r0-1] + mov r4d, 16 +.loop: + movzx r2d, byte [r0+r1-1] + sub r2d, r3d + movd mm4, r2d + SPLATW mm4, mm4, 0 + movq mm5, mm4 + movq mm6, mm4 + movq mm7, mm4 + paddw mm4, mm0 + paddw mm5, mm1 + paddw mm6, mm2 + paddw mm7, mm3 + packuswb mm4, mm5 + packuswb mm6, mm7 + movq [r0+r1+0], mm4 + movq [r0+r1+8], mm6 + add r0, r1 + dec r4d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +PRED16x16_TM +INIT_MMX mmxext +PRED16x16_TM + +INIT_XMM sse2 +cglobal pred16x16_tm_vp8_8, 2,6,6 + sub r0, r1 + pxor xmm2, xmm2 + movdqa xmm0, [r0] + movdqa xmm1, xmm0 + punpcklbw xmm0, xmm2 + punpckhbw xmm1, xmm2 + movzx r4d, byte [r0-1] + mov r5d, 8 +.loop: + movzx r2d, byte [r0+r1*1-1] + movzx r3d, byte [r0+r1*2-1] + sub r2d, r4d + sub r3d, r4d + movd xmm2, r2d + movd xmm4, r3d + pshuflw xmm2, xmm2, 0 + pshuflw xmm4, xmm4, 0 + punpcklqdq xmm2, xmm2 + punpcklqdq xmm4, xmm4 + movdqa xmm3, xmm2 + movdqa xmm5, xmm4 + paddw xmm2, xmm0 + paddw xmm3, xmm1 + paddw xmm4, xmm0 + paddw xmm5, xmm1 + packuswb xmm2, xmm3 + packuswb xmm4, xmm5 + movdqa [r0+r1*1], xmm2 + movdqa [r0+r1*2], xmm4 + lea r0, [r0+r1*2] + dec r5d + jg .loop + REP_RET + +;----------------------------------------------------------------------------- +; void pred16x16_plane_*_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro H264_PRED16x16_PLANE 1 +cglobal pred16x16_plane_%1_8, 2,9,7 + mov r2, r1 ; +stride + neg r1 ; -stride + + movh m0, [r0+r1 -1] +%if mmsize == 8 + pxor m4, m4 + movh m1, [r0+r1 +3 ] + movh m2, [r0+r1 +8 ] + movh m3, [r0+r1 +12] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + pmullw m0, [pw_m8tom1 ] + pmullw m1, [pw_m8tom1+8] + pmullw m2, [pw_1to8 ] + pmullw m3, [pw_1to8 +8] + paddw m0, m2 + paddw m1, m3 +%else ; mmsize == 16 +%if cpuflag(ssse3) + movhps m0, [r0+r1 +8] + pmaddubsw m0, [plane_shuf] ; H coefficients +%else ; sse2 + pxor m2, m2 + movh m1, [r0+r1 +8] + punpcklbw m0, m2 + punpcklbw m1, m2 + pmullw m0, [pw_m8tom1] + pmullw m1, [pw_1to8] + paddw m0, m1 +%endif + movhlps m1, m0 +%endif + paddw m0, m1 +%if cpuflag(mmxext) + PSHUFLW m1, m0, 0xE +%elif cpuflag(mmx) + mova m1, m0 + psrlq m1, 32 +%endif + paddw m0, m1 +%if cpuflag(mmxext) + PSHUFLW m1, m0, 0x1 +%elif cpuflag(mmx) + mova m1, m0 + psrlq m1, 16 +%endif + paddw m0, m1 ; sum of H coefficients + + lea r4, [r0+r2*8-1] + lea r3, [r0+r2*4-1] + add r4, r2 + +%if ARCH_X86_64 +%define e_reg r8 +%else +%define e_reg r0 +%endif + + movzx e_reg, byte [r3+r2*2 ] + movzx r5, byte [r4+r1 ] + sub r5, e_reg + + movzx e_reg, byte [r3+r2 ] + movzx r6, byte [r4 ] + sub r6, e_reg + lea r5, [r5+r6*2] + + movzx e_reg, byte [r3+r1 ] + movzx r6, byte [r4+r2*2 ] + sub r6, e_reg + lea r5, [r5+r6*4] + + movzx e_reg, byte [r3 ] +%if ARCH_X86_64 + movzx r7, byte [r4+r2 ] + sub r7, e_reg +%else + movzx r6, byte [r4+r2 ] + sub r6, e_reg + lea r5, [r5+r6*4] + sub r5, r6 +%endif + + lea e_reg, [r3+r1*4] + lea r3, [r4+r2*4] + + movzx r4, byte [e_reg+r2 ] + movzx r6, byte [r3 ] + sub r6, r4 +%if ARCH_X86_64 + lea r6, [r7+r6*2] + lea r5, [r5+r6*2] + add r5, r6 +%else + lea r5, [r5+r6*4] + lea r5, [r5+r6*2] +%endif + + movzx r4, byte [e_reg ] +%if ARCH_X86_64 + movzx r7, byte [r3 +r2 ] + sub r7, r4 + sub r5, r7 +%else + movzx r6, byte [r3 +r2 ] + sub r6, r4 + lea r5, [r5+r6*8] + sub r5, r6 +%endif + + movzx r4, byte [e_reg+r1 ] + movzx r6, byte [r3 +r2*2] + sub r6, r4 +%if ARCH_X86_64 + add r6, r7 +%endif + lea r5, [r5+r6*8] + + movzx r4, byte [e_reg+r2*2] + movzx r6, byte [r3 +r1 ] + sub r6, r4 + lea r5, [r5+r6*4] + add r5, r6 ; sum of V coefficients + +%if ARCH_X86_64 == 0 + mov r0, r0m +%endif + +%ifidn %1, h264 + lea r5, [r5*5+32] + sar r5, 6 +%elifidn %1, rv40 + lea r5, [r5*5] + sar r5, 6 +%elifidn %1, svq3 + test r5, r5 + lea r6, [r5+3] + cmovs r5, r6 + sar r5, 2 ; V/4 + lea r5, [r5*5] ; 5*(V/4) + test r5, r5 + lea r6, [r5+15] + cmovs r5, r6 + sar r5, 4 ; (5*(V/4))/16 +%endif + + movzx r4, byte [r0+r1 +15] + movzx r3, byte [r3+r2*2 ] + lea r3, [r3+r4+1] + shl r3, 4 + + movd r1d, m0 + movsx r1d, r1w +%ifnidn %1, svq3 +%ifidn %1, h264 + lea r1d, [r1d*5+32] +%else ; rv40 + lea r1d, [r1d*5] +%endif + sar r1d, 6 +%else ; svq3 + test r1d, r1d + lea r4d, [r1d+3] + cmovs r1d, r4d + sar r1d, 2 ; H/4 + lea r1d, [r1d*5] ; 5*(H/4) + test r1d, r1d + lea r4d, [r1d+15] + cmovs r1d, r4d + sar r1d, 4 ; (5*(H/4))/16 +%endif + movd m0, r1d + + add r1d, r5d + add r3d, r1d + shl r1d, 3 + sub r3d, r1d ; a + + movd m1, r5d + movd m3, r3d + SPLATW m0, m0, 0 ; H + SPLATW m1, m1, 0 ; V + SPLATW m3, m3, 0 ; a +%ifidn %1, svq3 + SWAP 0, 1 +%endif + mova m2, m0 +%if mmsize == 8 + mova m5, m0 +%endif + pmullw m0, [pw_0to7] ; 0*H, 1*H, ..., 7*H (words) +%if mmsize == 16 + psllw m2, 3 +%else + psllw m5, 3 + psllw m2, 2 + mova m6, m5 + paddw m6, m2 +%endif + paddw m0, m3 ; a + {0,1,2,3,4,5,6,7}*H + paddw m2, m0 ; a + {8,9,10,11,12,13,14,15}*H +%if mmsize == 8 + paddw m5, m0 ; a + {8,9,10,11}*H + paddw m6, m0 ; a + {12,13,14,15}*H +%endif + + mov r4, 8 +.loop: + mova m3, m0 ; b[0..7] + mova m4, m2 ; b[8..15] + psraw m3, 5 + psraw m4, 5 + packuswb m3, m4 + mova [r0], m3 +%if mmsize == 8 + mova m3, m5 ; b[8..11] + mova m4, m6 ; b[12..15] + psraw m3, 5 + psraw m4, 5 + packuswb m3, m4 + mova [r0+8], m3 +%endif + paddw m0, m1 + paddw m2, m1 +%if mmsize == 8 + paddw m5, m1 + paddw m6, m1 +%endif + + mova m3, m0 ; b[0..7] + mova m4, m2 ; b[8..15] + psraw m3, 5 + psraw m4, 5 + packuswb m3, m4 + mova [r0+r2], m3 +%if mmsize == 8 + mova m3, m5 ; b[8..11] + mova m4, m6 ; b[12..15] + psraw m3, 5 + psraw m4, 5 + packuswb m3, m4 + mova [r0+r2+8], m3 +%endif + paddw m0, m1 + paddw m2, m1 +%if mmsize == 8 + paddw m5, m1 + paddw m6, m1 +%endif + + lea r0, [r0+r2*2] + dec r4 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +H264_PRED16x16_PLANE h264 +H264_PRED16x16_PLANE rv40 +H264_PRED16x16_PLANE svq3 +INIT_MMX mmxext +H264_PRED16x16_PLANE h264 +H264_PRED16x16_PLANE rv40 +H264_PRED16x16_PLANE svq3 +INIT_XMM sse2 +H264_PRED16x16_PLANE h264 +H264_PRED16x16_PLANE rv40 +H264_PRED16x16_PLANE svq3 +INIT_XMM ssse3 +H264_PRED16x16_PLANE h264 +H264_PRED16x16_PLANE rv40 +H264_PRED16x16_PLANE svq3 + +;----------------------------------------------------------------------------- +; void pred8x8_plane_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro H264_PRED8x8_PLANE 0 +cglobal pred8x8_plane_8, 2,9,7 + mov r2, r1 ; +stride + neg r1 ; -stride + + movd m0, [r0+r1 -1] +%if mmsize == 8 + pxor m2, m2 + movh m1, [r0+r1 +4 ] + punpcklbw m0, m2 + punpcklbw m1, m2 + pmullw m0, [pw_m4to4] + pmullw m1, [pw_m4to4+8] +%else ; mmsize == 16 +%if cpuflag(ssse3) + movhps m0, [r0+r1 +4] ; this reads 4 bytes more than necessary + pmaddubsw m0, [plane8_shuf] ; H coefficients +%else ; sse2 + pxor m2, m2 + movd m1, [r0+r1 +4] + punpckldq m0, m1 + punpcklbw m0, m2 + pmullw m0, [pw_m4to4] +%endif + movhlps m1, m0 +%endif + paddw m0, m1 + +%if notcpuflag(ssse3) +%if cpuflag(mmxext) + PSHUFLW m1, m0, 0xE +%elif cpuflag(mmx) + mova m1, m0 + psrlq m1, 32 +%endif + paddw m0, m1 +%endif ; !ssse3 + +%if cpuflag(mmxext) + PSHUFLW m1, m0, 0x1 +%elif cpuflag(mmx) + mova m1, m0 + psrlq m1, 16 +%endif + paddw m0, m1 ; sum of H coefficients + + lea r4, [r0+r2*4-1] + lea r3, [r0 -1] + add r4, r2 + +%if ARCH_X86_64 +%define e_reg r8 +%else +%define e_reg r0 +%endif + + movzx e_reg, byte [r3+r2*2 ] + movzx r5, byte [r4+r1 ] + sub r5, e_reg + + movzx e_reg, byte [r3 ] +%if ARCH_X86_64 + movzx r7, byte [r4+r2 ] + sub r7, e_reg + sub r5, r7 +%else + movzx r6, byte [r4+r2 ] + sub r6, e_reg + lea r5, [r5+r6*4] + sub r5, r6 +%endif + + movzx e_reg, byte [r3+r1 ] + movzx r6, byte [r4+r2*2 ] + sub r6, e_reg +%if ARCH_X86_64 + add r6, r7 +%endif + lea r5, [r5+r6*4] + + movzx e_reg, byte [r3+r2 ] + movzx r6, byte [r4 ] + sub r6, e_reg + lea r6, [r5+r6*2] + + lea r5, [r6*9+16] + lea r5, [r5+r6*8] + sar r5, 5 + +%if ARCH_X86_64 == 0 + mov r0, r0m +%endif + + movzx r3, byte [r4+r2*2 ] + movzx r4, byte [r0+r1 +7] + lea r3, [r3+r4+1] + shl r3, 4 + movd r1d, m0 + movsx r1d, r1w + imul r1d, 17 + add r1d, 16 + sar r1d, 5 + movd m0, r1d + add r1d, r5d + sub r3d, r1d + add r1d, r1d + sub r3d, r1d ; a + + movd m1, r5d + movd m3, r3d + SPLATW m0, m0, 0 ; H + SPLATW m1, m1, 0 ; V + SPLATW m3, m3, 0 ; a +%if mmsize == 8 + mova m2, m0 +%endif + pmullw m0, [pw_0to7] ; 0*H, 1*H, ..., 7*H (words) + paddw m0, m3 ; a + {0,1,2,3,4,5,6,7}*H +%if mmsize == 8 + psllw m2, 2 + paddw m2, m0 ; a + {4,5,6,7}*H +%endif + + mov r4, 4 +ALIGN 16 +.loop: +%if mmsize == 16 + mova m3, m0 ; b[0..7] + paddw m0, m1 + psraw m3, 5 + mova m4, m0 ; V+b[0..7] + paddw m0, m1 + psraw m4, 5 + packuswb m3, m4 + movh [r0], m3 + movhps [r0+r2], m3 +%else ; mmsize == 8 + mova m3, m0 ; b[0..3] + mova m4, m2 ; b[4..7] + paddw m0, m1 + paddw m2, m1 + psraw m3, 5 + psraw m4, 5 + mova m5, m0 ; V+b[0..3] + mova m6, m2 ; V+b[4..7] + paddw m0, m1 + paddw m2, m1 + psraw m5, 5 + psraw m6, 5 + packuswb m3, m4 + packuswb m5, m6 + mova [r0], m3 + mova [r0+r2], m5 +%endif + + lea r0, [r0+r2*2] + dec r4 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +H264_PRED8x8_PLANE +INIT_MMX mmxext +H264_PRED8x8_PLANE +INIT_XMM sse2 +H264_PRED8x8_PLANE +INIT_XMM ssse3 +H264_PRED8x8_PLANE + +;----------------------------------------------------------------------------- +; void pred8x8_vertical_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmx +cglobal pred8x8_vertical_8, 2,2 + sub r0, r1 + movq mm0, [r0] +%rep 3 + movq [r0+r1*1], mm0 + movq [r0+r1*2], mm0 + lea r0, [r0+r1*2] +%endrep + movq [r0+r1*1], mm0 + movq [r0+r1*2], mm0 + RET + +;----------------------------------------------------------------------------- +; void pred8x8_horizontal_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8_H 0 +cglobal pred8x8_horizontal_8, 2,3 + mov r2, 4 +%if cpuflag(ssse3) + mova m2, [pb_3] +%endif +.loop: + SPLATB_LOAD m0, r0+r1*0-1, m2 + SPLATB_LOAD m1, r0+r1*1-1, m2 + mova [r0+r1*0], m0 + mova [r0+r1*1], m1 + lea r0, [r0+r1*2] + dec r2 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +PRED8x8_H +INIT_MMX mmxext +PRED8x8_H +INIT_MMX ssse3 +PRED8x8_H + +;----------------------------------------------------------------------------- +; void pred8x8_top_dc_8_mmxext(uint8_t *src, int stride) +;----------------------------------------------------------------------------- +INIT_MMX mmxext +cglobal pred8x8_top_dc_8, 2,5 + sub r0, r1 + movq mm0, [r0] + pxor mm1, mm1 + pxor mm2, mm2 + lea r2, [r0+r1*2] + punpckhbw mm1, mm0 + punpcklbw mm0, mm2 + psadbw mm1, mm2 ; s1 + lea r3, [r2+r1*2] + psadbw mm0, mm2 ; s0 + psrlw mm1, 1 + psrlw mm0, 1 + pavgw mm1, mm2 + lea r4, [r3+r1*2] + pavgw mm0, mm2 + pshufw mm1, mm1, 0 + pshufw mm0, mm0, 0 ; dc0 (w) + packuswb mm0, mm1 ; dc0,dc1 (b) + movq [r0+r1*1], mm0 + movq [r0+r1*2], mm0 + lea r0, [r3+r1*2] + movq [r2+r1*1], mm0 + movq [r2+r1*2], mm0 + movq [r3+r1*1], mm0 + movq [r3+r1*2], mm0 + movq [r0+r1*1], mm0 + movq [r0+r1*2], mm0 + RET + +;----------------------------------------------------------------------------- +; void pred8x8_dc_8_mmxext(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred8x8_dc_8, 2,5 + sub r0, r1 + pxor m7, m7 + movd m0, [r0+0] + movd m1, [r0+4] + psadbw m0, m7 ; s0 + mov r4, r0 + psadbw m1, m7 ; s1 + + movzx r2d, byte [r0+r1*1-1] + movzx r3d, byte [r0+r1*2-1] + lea r0, [r0+r1*2] + add r2d, r3d + movzx r3d, byte [r0+r1*1-1] + add r2d, r3d + movzx r3d, byte [r0+r1*2-1] + add r2d, r3d + lea r0, [r0+r1*2] + movd m2, r2d ; s2 + movzx r2d, byte [r0+r1*1-1] + movzx r3d, byte [r0+r1*2-1] + lea r0, [r0+r1*2] + add r2d, r3d + movzx r3d, byte [r0+r1*1-1] + add r2d, r3d + movzx r3d, byte [r0+r1*2-1] + add r2d, r3d + movd m3, r2d ; s3 + + punpcklwd m0, m1 + mov r0, r4 + punpcklwd m2, m3 + punpckldq m0, m2 ; s0, s1, s2, s3 + pshufw m3, m0, 11110110b ; s2, s1, s3, s3 + lea r2, [r0+r1*2] + pshufw m0, m0, 01110100b ; s0, s1, s3, s1 + paddw m0, m3 + lea r3, [r2+r1*2] + psrlw m0, 2 + pavgw m0, m7 ; s0+s2, s1, s3, s1+s3 + lea r4, [r3+r1*2] + packuswb m0, m0 + punpcklbw m0, m0 + movq m1, m0 + punpcklbw m0, m0 + punpckhbw m1, m1 + movq [r0+r1*1], m0 + movq [r0+r1*2], m0 + movq [r2+r1*1], m0 + movq [r2+r1*2], m0 + movq [r3+r1*1], m1 + movq [r3+r1*2], m1 + movq [r4+r1*1], m1 + movq [r4+r1*2], m1 + RET + +;----------------------------------------------------------------------------- +; void pred8x8_dc_rv40_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred8x8_dc_rv40_8, 2,7 + mov r4, r0 + sub r0, r1 + pxor mm0, mm0 + psadbw mm0, [r0] + dec r0 + movzx r5d, byte [r0+r1*1] + movd r6d, mm0 + lea r0, [r0+r1*2] +%rep 3 + movzx r2d, byte [r0+r1*0] + movzx r3d, byte [r0+r1*1] + add r5d, r2d + add r6d, r3d + lea r0, [r0+r1*2] +%endrep + movzx r2d, byte [r0+r1*0] + add r5d, r6d + lea r2d, [r2+r5+8] + shr r2d, 4 + movd mm0, r2d + punpcklbw mm0, mm0 + pshufw mm0, mm0, 0 + mov r3d, 4 +.loop: + movq [r4+r1*0], mm0 + movq [r4+r1*1], mm0 + lea r4, [r4+r1*2] + dec r3d + jg .loop + REP_RET + +;----------------------------------------------------------------------------- +; void pred8x8_tm_vp8_8(uint8_t *src, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8_TM 0 +cglobal pred8x8_tm_vp8_8, 2,6 + sub r0, r1 + pxor mm7, mm7 + movq mm0, [r0] + movq mm1, mm0 + punpcklbw mm0, mm7 + punpckhbw mm1, mm7 + movzx r4d, byte [r0-1] + mov r5d, 4 +.loop: + movzx r2d, byte [r0+r1*1-1] + movzx r3d, byte [r0+r1*2-1] + sub r2d, r4d + sub r3d, r4d + movd mm2, r2d + movd mm4, r3d + SPLATW mm2, mm2, 0 + SPLATW mm4, mm4, 0 + movq mm3, mm2 + movq mm5, mm4 + paddw mm2, mm0 + paddw mm3, mm1 + paddw mm4, mm0 + paddw mm5, mm1 + packuswb mm2, mm3 + packuswb mm4, mm5 + movq [r0+r1*1], mm2 + movq [r0+r1*2], mm4 + lea r0, [r0+r1*2] + dec r5d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +PRED8x8_TM +INIT_MMX mmxext +PRED8x8_TM + +INIT_XMM sse2 +cglobal pred8x8_tm_vp8_8, 2,6,4 + sub r0, r1 + pxor xmm1, xmm1 + movq xmm0, [r0] + punpcklbw xmm0, xmm1 + movzx r4d, byte [r0-1] + mov r5d, 4 +.loop: + movzx r2d, byte [r0+r1*1-1] + movzx r3d, byte [r0+r1*2-1] + sub r2d, r4d + sub r3d, r4d + movd xmm2, r2d + movd xmm3, r3d + pshuflw xmm2, xmm2, 0 + pshuflw xmm3, xmm3, 0 + punpcklqdq xmm2, xmm2 + punpcklqdq xmm3, xmm3 + paddw xmm2, xmm0 + paddw xmm3, xmm0 + packuswb xmm2, xmm3 + movq [r0+r1*1], xmm2 + movhps [r0+r1*2], xmm2 + lea r0, [r0+r1*2] + dec r5d + jg .loop + REP_RET + +INIT_XMM ssse3 +cglobal pred8x8_tm_vp8_8, 2,3,6 + sub r0, r1 + movdqa xmm4, [tm_shuf] + pxor xmm1, xmm1 + movq xmm0, [r0] + punpcklbw xmm0, xmm1 + movd xmm5, [r0-4] + pshufb xmm5, xmm4 + mov r2d, 4 +.loop: + movd xmm2, [r0+r1*1-4] + movd xmm3, [r0+r1*2-4] + pshufb xmm2, xmm4 + pshufb xmm3, xmm4 + psubw xmm2, xmm5 + psubw xmm3, xmm5 + paddw xmm2, xmm0 + paddw xmm3, xmm0 + packuswb xmm2, xmm3 + movq [r0+r1*1], xmm2 + movhps [r0+r1*2], xmm2 + lea r0, [r0+r1*2] + dec r2d + jg .loop + REP_RET + +; dest, left, right, src, tmp +; output: %1 = (t[n-1] + t[n]*2 + t[n+1] + 2) >> 2 +%macro PRED4x4_LOWPASS 5 + mova %5, %2 + pavgb %2, %3 + pxor %3, %5 + mova %1, %4 + pand %3, [pb_1] + psubusb %2, %3 + pavgb %1, %2 +%endmacro + +;----------------------------------------------------------------------------- +; void pred8x8l_top_dc_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_TOP_DC 0 +cglobal pred8x8l_top_dc_8, 4,4 + sub r0, r3 + pxor mm7, mm7 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 ; top_left + jz .fix_lt_2 + test r2, r2 ; top_right + jz .fix_tr_1 + jmp .body +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 ; top_right + jnz .body +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 +.body: + PRED4x4_LOWPASS mm0, mm2, mm1, mm3, mm5 + psadbw mm7, mm0 + paddw mm7, [pw_4] + psrlw mm7, 3 + pshufw mm7, mm7, 0 + packuswb mm7, mm7 +%rep 3 + movq [r0+r3*1], mm7 + movq [r0+r3*2], mm7 + lea r0, [r0+r3*2] +%endrep + movq [r0+r3*1], mm7 + movq [r0+r3*2], mm7 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8L_TOP_DC +INIT_MMX ssse3 +PRED8x8L_TOP_DC + +;----------------------------------------------------------------------------- +;void pred8x8l_dc_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8L_DC 0 +cglobal pred8x8l_dc_8, 4,5 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 + jnz .do_left +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .body +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .body +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm4, mm0 + movq mm7, mm2 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + psllq mm1, 56 + PALIGNR mm7, mm1, 7, mm3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 +.body: + lea r1, [r0+r3*2] + PRED4x4_LOWPASS mm6, mm2, mm1, mm3, mm5 + pxor mm0, mm0 + pxor mm1, mm1 + lea r2, [r1+r3*2] + psadbw mm0, mm7 + psadbw mm1, mm6 + paddw mm0, [pw_8] + paddw mm0, mm1 + lea r4, [r2+r3*2] + psrlw mm0, 4 + pshufw mm0, mm0, 0 + packuswb mm0, mm0 + movq [r0+r3*1], mm0 + movq [r0+r3*2], mm0 + movq [r1+r3*1], mm0 + movq [r1+r3*2], mm0 + movq [r2+r3*1], mm0 + movq [r2+r3*2], mm0 + movq [r4+r3*1], mm0 + movq [r4+r3*2], mm0 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8L_DC +INIT_MMX ssse3 +PRED8x8L_DC + +;----------------------------------------------------------------------------- +; void pred8x8l_horizontal_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8L_HORIZONTAL 0 +cglobal pred8x8l_horizontal_8, 4,4 + sub r0, r3 + lea r2, [r0+r3*2] + movq mm0, [r0+r3*1-8] + test r1, r1 + lea r1, [r0+r3] + cmovnz r1, r0 + punpckhbw mm0, [r1+r3*0-8] + movq mm1, [r2+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r2, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r1+r3*0-8] + mov r0, r2 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm4, mm0 + movq mm7, mm2 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + psllq mm1, 56 + PALIGNR mm7, mm1, 7, mm3 + movq mm3, mm7 + lea r1, [r0+r3*2] + movq mm7, mm3 + punpckhbw mm3, mm3 + punpcklbw mm7, mm7 + pshufw mm0, mm3, 0xff + pshufw mm1, mm3, 0xaa + lea r2, [r1+r3*2] + pshufw mm2, mm3, 0x55 + pshufw mm3, mm3, 0x00 + pshufw mm4, mm7, 0xff + pshufw mm5, mm7, 0xaa + pshufw mm6, mm7, 0x55 + pshufw mm7, mm7, 0x00 + movq [r0+r3*1], mm0 + movq [r0+r3*2], mm1 + movq [r1+r3*1], mm2 + movq [r1+r3*2], mm3 + movq [r2+r3*1], mm4 + movq [r2+r3*2], mm5 + lea r0, [r2+r3*2] + movq [r0+r3*1], mm6 + movq [r0+r3*2], mm7 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8L_HORIZONTAL +INIT_MMX ssse3 +PRED8x8L_HORIZONTAL + +;----------------------------------------------------------------------------- +; void pred8x8l_vertical_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8L_VERTICAL 0 +cglobal pred8x8l_vertical_8, 4,4 + sub r0, r3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 ; top_left + jz .fix_lt_2 + test r2, r2 ; top_right + jz .fix_tr_1 + jmp .body +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 ; top_right + jnz .body +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 +.body: + PRED4x4_LOWPASS mm0, mm2, mm1, mm3, mm5 +%rep 3 + movq [r0+r3*1], mm0 + movq [r0+r3*2], mm0 + lea r0, [r0+r3*2] +%endrep + movq [r0+r3*1], mm0 + movq [r0+r3*2], mm0 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8L_VERTICAL +INIT_MMX ssse3 +PRED8x8L_VERTICAL + +;----------------------------------------------------------------------------- +;void pred8x8l_down_left_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred8x8l_down_left_8, 4,5 + sub r0, r3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 + jmp .do_top +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.fix_tr_2: + punpckhbw mm3, mm3 + pshufw mm1, mm3, 0xFF + jmp .do_topright +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq mm7, mm4 + test r2, r2 + jz .fix_tr_2 + movq mm0, [r0+8] + movq mm5, mm0 + movq mm2, mm0 + movq mm4, mm0 + psrlq mm5, 56 + PALIGNR mm2, mm3, 7, mm3 + PALIGNR mm5, mm4, 1, mm4 + PRED4x4_LOWPASS mm1, mm2, mm5, mm0, mm4 +.do_topright: + lea r1, [r0+r3*2] + movq mm6, mm1 + psrlq mm1, 56 + movq mm4, mm1 + lea r2, [r1+r3*2] + movq mm2, mm6 + PALIGNR mm2, mm7, 1, mm0 + movq mm3, mm6 + PALIGNR mm3, mm7, 7, mm0 + PALIGNR mm4, mm6, 1, mm0 + movq mm5, mm7 + movq mm1, mm7 + movq mm7, mm6 + lea r4, [r2+r3*2] + psllq mm1, 8 + PRED4x4_LOWPASS mm0, mm1, mm2, mm5, mm6 + PRED4x4_LOWPASS mm1, mm3, mm4, mm7, mm6 + movq [r4+r3*2], mm1 + movq mm2, mm0 + psllq mm1, 8 + psrlq mm2, 56 + psllq mm0, 8 + por mm1, mm2 + movq [r4+r3*1], mm1 + movq mm2, mm0 + psllq mm1, 8 + psrlq mm2, 56 + psllq mm0, 8 + por mm1, mm2 + movq [r2+r3*2], mm1 + movq mm2, mm0 + psllq mm1, 8 + psrlq mm2, 56 + psllq mm0, 8 + por mm1, mm2 + movq [r2+r3*1], mm1 + movq mm2, mm0 + psllq mm1, 8 + psrlq mm2, 56 + psllq mm0, 8 + por mm1, mm2 + movq [r1+r3*2], mm1 + movq mm2, mm0 + psllq mm1, 8 + psrlq mm2, 56 + psllq mm0, 8 + por mm1, mm2 + movq [r1+r3*1], mm1 + movq mm2, mm0 + psllq mm1, 8 + psrlq mm2, 56 + psllq mm0, 8 + por mm1, mm2 + movq [r0+r3*2], mm1 + psllq mm1, 8 + psrlq mm0, 56 + por mm1, mm0 + movq [r0+r3*1], mm1 + RET + +%macro PRED8x8L_DOWN_LEFT 0 +cglobal pred8x8l_down_left_8, 4,4 + sub r0, r3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 ; top_left + jz .fix_lt_2 + test r2, r2 ; top_right + jz .fix_tr_1 + jmp .do_top +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 ; top_right + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.fix_tr_2: + punpckhbw mm3, mm3 + pshufw mm1, mm3, 0xFF + jmp .do_topright +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq2dq xmm3, mm4 + test r2, r2 ; top_right + jz .fix_tr_2 + movq mm0, [r0+8] + movq mm5, mm0 + movq mm2, mm0 + movq mm4, mm0 + psrlq mm5, 56 + PALIGNR mm2, mm3, 7, mm3 + PALIGNR mm5, mm4, 1, mm4 + PRED4x4_LOWPASS mm1, mm2, mm5, mm0, mm4 +.do_topright: + movq2dq xmm4, mm1 + psrlq mm1, 56 + movq2dq xmm5, mm1 + lea r1, [r0+r3*2] + pslldq xmm4, 8 + por xmm3, xmm4 + movdqa xmm2, xmm3 + psrldq xmm2, 1 + pslldq xmm5, 15 + por xmm2, xmm5 + lea r2, [r1+r3*2] + movdqa xmm1, xmm3 + pslldq xmm1, 1 +INIT_XMM cpuname + PRED4x4_LOWPASS xmm0, xmm1, xmm2, xmm3, xmm4 + psrldq xmm0, 1 + movq [r0+r3*1], xmm0 + psrldq xmm0, 1 + movq [r0+r3*2], xmm0 + psrldq xmm0, 1 + lea r0, [r2+r3*2] + movq [r1+r3*1], xmm0 + psrldq xmm0, 1 + movq [r1+r3*2], xmm0 + psrldq xmm0, 1 + movq [r2+r3*1], xmm0 + psrldq xmm0, 1 + movq [r2+r3*2], xmm0 + psrldq xmm0, 1 + movq [r0+r3*1], xmm0 + psrldq xmm0, 1 + movq [r0+r3*2], xmm0 + RET +%endmacro + +INIT_MMX sse2 +PRED8x8L_DOWN_LEFT +INIT_MMX ssse3 +PRED8x8L_DOWN_LEFT + +;----------------------------------------------------------------------------- +;void pred8x8l_down_right_8_mmxext(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred8x8l_down_right_8, 4,5 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 ; top_left + jz .fix_lt_1 +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm4, mm0 + movq mm7, mm2 + movq mm6, mm2 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + psllq mm1, 56 + PALIGNR mm7, mm1, 7, mm3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 ; top_left + jz .fix_lt_2 + test r2, r2 ; top_right + jz .fix_tr_1 +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq mm5, mm4 + jmp .body +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 ; top_right + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.body: + lea r1, [r0+r3*2] + movq mm1, mm7 + movq mm7, mm5 + movq mm5, mm6 + movq mm2, mm7 + lea r2, [r1+r3*2] + PALIGNR mm2, mm6, 1, mm0 + movq mm3, mm7 + PALIGNR mm3, mm6, 7, mm0 + movq mm4, mm7 + lea r4, [r2+r3*2] + psrlq mm4, 8 + PRED4x4_LOWPASS mm0, mm1, mm2, mm5, mm6 + PRED4x4_LOWPASS mm1, mm3, mm4, mm7, mm6 + movq [r4+r3*2], mm0 + movq mm2, mm1 + psrlq mm0, 8 + psllq mm2, 56 + psrlq mm1, 8 + por mm0, mm2 + movq [r4+r3*1], mm0 + movq mm2, mm1 + psrlq mm0, 8 + psllq mm2, 56 + psrlq mm1, 8 + por mm0, mm2 + movq [r2+r3*2], mm0 + movq mm2, mm1 + psrlq mm0, 8 + psllq mm2, 56 + psrlq mm1, 8 + por mm0, mm2 + movq [r2+r3*1], mm0 + movq mm2, mm1 + psrlq mm0, 8 + psllq mm2, 56 + psrlq mm1, 8 + por mm0, mm2 + movq [r1+r3*2], mm0 + movq mm2, mm1 + psrlq mm0, 8 + psllq mm2, 56 + psrlq mm1, 8 + por mm0, mm2 + movq [r1+r3*1], mm0 + movq mm2, mm1 + psrlq mm0, 8 + psllq mm2, 56 + psrlq mm1, 8 + por mm0, mm2 + movq [r0+r3*2], mm0 + psrlq mm0, 8 + psllq mm1, 56 + por mm0, mm1 + movq [r0+r3*1], mm0 + RET + +%macro PRED8x8L_DOWN_RIGHT 0 +cglobal pred8x8l_down_right_8, 4,5 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 + jz .fix_lt_1 + jmp .do_left +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm4, mm0 + movq mm7, mm2 + movq2dq xmm3, mm2 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + psllq mm1, 56 + PALIGNR mm7, mm1, 7, mm3 + movq2dq xmm1, mm7 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq2dq xmm4, mm4 + lea r1, [r0+r3*2] + movdqa xmm0, xmm3 + pslldq xmm4, 8 + por xmm3, xmm4 + lea r2, [r1+r3*2] + pslldq xmm4, 1 + por xmm1, xmm4 + psrldq xmm0, 7 + pslldq xmm0, 15 + psrldq xmm0, 7 + por xmm1, xmm0 + lea r0, [r2+r3*2] + movdqa xmm2, xmm3 + psrldq xmm2, 1 +INIT_XMM cpuname + PRED4x4_LOWPASS xmm0, xmm1, xmm2, xmm3, xmm4 + movdqa xmm1, xmm0 + psrldq xmm1, 1 + movq [r0+r3*2], xmm0 + movq [r0+r3*1], xmm1 + psrldq xmm0, 2 + psrldq xmm1, 2 + movq [r2+r3*2], xmm0 + movq [r2+r3*1], xmm1 + psrldq xmm0, 2 + psrldq xmm1, 2 + movq [r1+r3*2], xmm0 + movq [r1+r3*1], xmm1 + psrldq xmm0, 2 + psrldq xmm1, 2 + movq [r4+r3*2], xmm0 + movq [r4+r3*1], xmm1 + RET +%endmacro + +INIT_MMX sse2 +PRED8x8L_DOWN_RIGHT +INIT_MMX ssse3 +PRED8x8L_DOWN_RIGHT + +;----------------------------------------------------------------------------- +; void pred8x8l_vertical_right_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred8x8l_vertical_right_8, 4,5 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 + jz .fix_lt_1 + jmp .do_left +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm7, mm2 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 +.do_top: + PRED4x4_LOWPASS mm6, mm2, mm1, mm3, mm5 + lea r1, [r0+r3*2] + movq mm2, mm6 + movq mm3, mm6 + PALIGNR mm3, mm7, 7, mm0 + PALIGNR mm6, mm7, 6, mm1 + movq mm4, mm3 + pavgb mm3, mm2 + lea r2, [r1+r3*2] + PRED4x4_LOWPASS mm0, mm6, mm2, mm4, mm5 + movq [r0+r3*1], mm3 + movq [r0+r3*2], mm0 + movq mm5, mm0 + movq mm6, mm3 + movq mm1, mm7 + movq mm2, mm1 + psllq mm2, 8 + movq mm3, mm1 + psllq mm3, 16 + lea r4, [r2+r3*2] + PRED4x4_LOWPASS mm0, mm1, mm3, mm2, mm4 + PALIGNR mm6, mm0, 7, mm2 + movq [r1+r3*1], mm6 + psllq mm0, 8 + PALIGNR mm5, mm0, 7, mm1 + movq [r1+r3*2], mm5 + psllq mm0, 8 + PALIGNR mm6, mm0, 7, mm2 + movq [r2+r3*1], mm6 + psllq mm0, 8 + PALIGNR mm5, mm0, 7, mm1 + movq [r2+r3*2], mm5 + psllq mm0, 8 + PALIGNR mm6, mm0, 7, mm2 + movq [r4+r3*1], mm6 + psllq mm0, 8 + PALIGNR mm5, mm0, 7, mm1 + movq [r4+r3*2], mm5 + RET + +%macro PRED8x8L_VERTICAL_RIGHT 0 +cglobal pred8x8l_vertical_right_8, 4,5,7 + ; manually spill XMM registers for Win64 because + ; the code here is initialized with INIT_MMX + WIN64_SPILL_XMM 7 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 + jnz .do_left +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq2dq xmm0, mm2 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 +.do_top: + PRED4x4_LOWPASS mm6, mm2, mm1, mm3, mm5 + lea r1, [r0+r3*2] + movq2dq xmm4, mm6 + pslldq xmm4, 8 + por xmm0, xmm4 + movdqa xmm6, [pw_ff00] + movdqa xmm1, xmm0 + lea r2, [r1+r3*2] + movdqa xmm2, xmm0 + movdqa xmm3, xmm0 + pslldq xmm0, 1 + pslldq xmm1, 2 + pavgb xmm2, xmm0 +INIT_XMM cpuname + PRED4x4_LOWPASS xmm4, xmm3, xmm1, xmm0, xmm5 + pandn xmm6, xmm4 + movdqa xmm5, xmm4 + psrlw xmm4, 8 + packuswb xmm6, xmm4 + movhlps xmm4, xmm6 + movhps [r0+r3*2], xmm5 + movhps [r0+r3*1], xmm2 + psrldq xmm5, 4 + movss xmm5, xmm6 + psrldq xmm2, 4 + movss xmm2, xmm4 + lea r0, [r2+r3*2] + psrldq xmm5, 1 + psrldq xmm2, 1 + movq [r0+r3*2], xmm5 + movq [r0+r3*1], xmm2 + psrldq xmm5, 1 + psrldq xmm2, 1 + movq [r2+r3*2], xmm5 + movq [r2+r3*1], xmm2 + psrldq xmm5, 1 + psrldq xmm2, 1 + movq [r1+r3*2], xmm5 + movq [r1+r3*1], xmm2 + RET +%endmacro + +INIT_MMX sse2 +PRED8x8L_VERTICAL_RIGHT +INIT_MMX ssse3 +PRED8x8L_VERTICAL_RIGHT + +;----------------------------------------------------------------------------- +;void pred8x8l_vertical_left_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8L_VERTICAL_LEFT 0 +cglobal pred8x8l_vertical_left_8, 4,4 + sub r0, r3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 + jmp .do_top +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.fix_tr_2: + punpckhbw mm3, mm3 + pshufw mm1, mm3, 0xFF + jmp .do_topright +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq2dq xmm4, mm4 + test r2, r2 + jz .fix_tr_2 + movq mm0, [r0+8] + movq mm5, mm0 + movq mm2, mm0 + movq mm4, mm0 + psrlq mm5, 56 + PALIGNR mm2, mm3, 7, mm3 + PALIGNR mm5, mm4, 1, mm4 + PRED4x4_LOWPASS mm1, mm2, mm5, mm0, mm4 +.do_topright: + movq2dq xmm3, mm1 + lea r1, [r0+r3*2] + pslldq xmm3, 8 + por xmm4, xmm3 + movdqa xmm2, xmm4 + movdqa xmm1, xmm4 + movdqa xmm3, xmm4 + psrldq xmm2, 1 + pslldq xmm1, 1 + pavgb xmm3, xmm2 + lea r2, [r1+r3*2] +INIT_XMM cpuname + PRED4x4_LOWPASS xmm0, xmm1, xmm2, xmm4, xmm5 + psrldq xmm0, 1 + movq [r0+r3*1], xmm3 + movq [r0+r3*2], xmm0 + lea r0, [r2+r3*2] + psrldq xmm3, 1 + psrldq xmm0, 1 + movq [r1+r3*1], xmm3 + movq [r1+r3*2], xmm0 + psrldq xmm3, 1 + psrldq xmm0, 1 + movq [r2+r3*1], xmm3 + movq [r2+r3*2], xmm0 + psrldq xmm3, 1 + psrldq xmm0, 1 + movq [r0+r3*1], xmm3 + movq [r0+r3*2], xmm0 + RET +%endmacro + +INIT_MMX sse2 +PRED8x8L_VERTICAL_LEFT +INIT_MMX ssse3 +PRED8x8L_VERTICAL_LEFT + +;----------------------------------------------------------------------------- +; void pred8x8l_horizontal_up_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +%macro PRED8x8L_HORIZONTAL_UP 0 +cglobal pred8x8l_horizontal_up_8, 4,4 + sub r0, r3 + lea r2, [r0+r3*2] + movq mm0, [r0+r3*1-8] + test r1, r1 + lea r1, [r0+r3] + cmovnz r1, r0 + punpckhbw mm0, [r1+r3*0-8] + movq mm1, [r2+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r2, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r1+r3*0-8] + mov r0, r2 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm4, mm0 + movq mm7, mm2 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + psllq mm1, 56 + PALIGNR mm7, mm1, 7, mm3 + lea r1, [r0+r3*2] + pshufw mm0, mm7, 00011011b ; l6 l7 l4 l5 l2 l3 l0 l1 + psllq mm7, 56 ; l7 .. .. .. .. .. .. .. + movq mm2, mm0 + psllw mm0, 8 + psrlw mm2, 8 + por mm2, mm0 ; l7 l6 l5 l4 l3 l2 l1 l0 + movq mm3, mm2 + movq mm4, mm2 + movq mm5, mm2 + psrlq mm2, 8 + psrlq mm3, 16 + lea r2, [r1+r3*2] + por mm2, mm7 ; l7 l7 l6 l5 l4 l3 l2 l1 + punpckhbw mm7, mm7 + por mm3, mm7 ; l7 l7 l7 l6 l5 l4 l3 l2 + pavgb mm4, mm2 + PRED4x4_LOWPASS mm1, mm3, mm5, mm2, mm6 + movq mm5, mm4 + punpcklbw mm4, mm1 ; p4 p3 p2 p1 + punpckhbw mm5, mm1 ; p8 p7 p6 p5 + movq mm6, mm5 + movq mm7, mm5 + movq mm0, mm5 + PALIGNR mm5, mm4, 2, mm1 + pshufw mm1, mm6, 11111001b + PALIGNR mm6, mm4, 4, mm2 + pshufw mm2, mm7, 11111110b + PALIGNR mm7, mm4, 6, mm3 + pshufw mm3, mm0, 11111111b + movq [r0+r3*1], mm4 + movq [r0+r3*2], mm5 + lea r0, [r2+r3*2] + movq [r1+r3*1], mm6 + movq [r1+r3*2], mm7 + movq [r2+r3*1], mm0 + movq [r2+r3*2], mm1 + movq [r0+r3*1], mm2 + movq [r0+r3*2], mm3 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8L_HORIZONTAL_UP +INIT_MMX ssse3 +PRED8x8L_HORIZONTAL_UP + +;----------------------------------------------------------------------------- +;void pred8x8l_horizontal_down_8(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred8x8l_horizontal_down_8, 4,5 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 + jnz .do_left +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq mm4, mm0 + movq mm7, mm2 + movq mm6, mm2 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + psllq mm1, 56 + PALIGNR mm7, mm1, 7, mm3 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq mm5, mm4 + lea r1, [r0+r3*2] + psllq mm7, 56 + movq mm2, mm5 + movq mm3, mm6 + movq mm4, mm2 + PALIGNR mm2, mm6, 7, mm5 + PALIGNR mm6, mm7, 7, mm0 + lea r2, [r1+r3*2] + PALIGNR mm4, mm3, 1, mm7 + movq mm5, mm3 + pavgb mm3, mm6 + PRED4x4_LOWPASS mm0, mm4, mm6, mm5, mm7 + movq mm4, mm2 + movq mm1, mm2 + lea r4, [r2+r3*2] + psrlq mm4, 16 + psrlq mm1, 8 + PRED4x4_LOWPASS mm6, mm4, mm2, mm1, mm5 + movq mm7, mm3 + punpcklbw mm3, mm0 + punpckhbw mm7, mm0 + movq mm1, mm7 + movq mm0, mm7 + movq mm4, mm7 + movq [r4+r3*2], mm3 + PALIGNR mm7, mm3, 2, mm5 + movq [r4+r3*1], mm7 + PALIGNR mm1, mm3, 4, mm5 + movq [r2+r3*2], mm1 + PALIGNR mm0, mm3, 6, mm3 + movq [r2+r3*1], mm0 + movq mm2, mm6 + movq mm3, mm6 + movq [r1+r3*2], mm4 + PALIGNR mm6, mm4, 2, mm5 + movq [r1+r3*1], mm6 + PALIGNR mm2, mm4, 4, mm5 + movq [r0+r3*2], mm2 + PALIGNR mm3, mm4, 6, mm4 + movq [r0+r3*1], mm3 + RET + +%macro PRED8x8L_HORIZONTAL_DOWN 0 +cglobal pred8x8l_horizontal_down_8, 4,5 + sub r0, r3 + lea r4, [r0+r3*2] + movq mm0, [r0+r3*1-8] + punpckhbw mm0, [r0+r3*0-8] + movq mm1, [r4+r3*1-8] + punpckhbw mm1, [r0+r3*2-8] + mov r4, r0 + punpckhwd mm1, mm0 + lea r0, [r0+r3*4] + movq mm2, [r0+r3*1-8] + punpckhbw mm2, [r0+r3*0-8] + lea r0, [r0+r3*2] + movq mm3, [r0+r3*1-8] + punpckhbw mm3, [r0+r3*0-8] + punpckhwd mm3, mm2 + punpckhdq mm3, mm1 + lea r0, [r0+r3*2] + movq mm0, [r0+r3*0-8] + movq mm1, [r4] + mov r0, r4 + movq mm4, mm3 + movq mm2, mm3 + PALIGNR mm4, mm0, 7, mm0 + PALIGNR mm1, mm2, 1, mm2 + test r1, r1 + jnz .do_left +.fix_lt_1: + movq mm5, mm3 + pxor mm5, mm4 + psrlq mm5, 56 + psllq mm5, 48 + pxor mm1, mm5 + jmp .do_left +.fix_lt_2: + movq mm5, mm3 + pxor mm5, mm2 + psllq mm5, 56 + psrlq mm5, 56 + pxor mm2, mm5 + test r2, r2 + jnz .do_top +.fix_tr_1: + movq mm5, mm3 + pxor mm5, mm1 + psrlq mm5, 56 + psllq mm5, 56 + pxor mm1, mm5 + jmp .do_top +.fix_tr_2: + punpckhbw mm3, mm3 + pshufw mm1, mm3, 0xFF + jmp .do_topright +.do_left: + movq mm0, mm4 + PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 + movq2dq xmm0, mm2 + pslldq xmm0, 8 + movq mm4, mm0 + PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 + movq2dq xmm2, mm1 + pslldq xmm2, 15 + psrldq xmm2, 8 + por xmm0, xmm2 + movq mm0, [r0-8] + movq mm3, [r0] + movq mm1, [r0+8] + movq mm2, mm3 + movq mm4, mm3 + PALIGNR mm2, mm0, 7, mm0 + PALIGNR mm1, mm4, 1, mm4 + test r1, r1 + jz .fix_lt_2 + test r2, r2 + jz .fix_tr_1 +.do_top: + PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 + movq2dq xmm1, mm4 + test r2, r2 + jz .fix_tr_2 + movq mm0, [r0+8] + movq mm5, mm0 + movq mm2, mm0 + movq mm4, mm0 + psrlq mm5, 56 + PALIGNR mm2, mm3, 7, mm3 + PALIGNR mm5, mm4, 1, mm4 + PRED4x4_LOWPASS mm1, mm2, mm5, mm0, mm4 +.do_topright: + movq2dq xmm5, mm1 + pslldq xmm5, 8 + por xmm1, xmm5 +INIT_XMM cpuname + lea r2, [r4+r3*2] + movdqa xmm2, xmm1 + movdqa xmm3, xmm1 + PALIGNR xmm1, xmm0, 7, xmm4 + PALIGNR xmm2, xmm0, 9, xmm5 + lea r1, [r2+r3*2] + PALIGNR xmm3, xmm0, 8, xmm0 + movdqa xmm4, xmm1 + pavgb xmm4, xmm3 + lea r0, [r1+r3*2] + PRED4x4_LOWPASS xmm0, xmm1, xmm2, xmm3, xmm5 + punpcklbw xmm4, xmm0 + movhlps xmm0, xmm4 + movq [r0+r3*2], xmm4 + movq [r2+r3*2], xmm0 + psrldq xmm4, 2 + psrldq xmm0, 2 + movq [r0+r3*1], xmm4 + movq [r2+r3*1], xmm0 + psrldq xmm4, 2 + psrldq xmm0, 2 + movq [r1+r3*2], xmm4 + movq [r4+r3*2], xmm0 + psrldq xmm4, 2 + psrldq xmm0, 2 + movq [r1+r3*1], xmm4 + movq [r4+r3*1], xmm0 + RET +%endmacro + +INIT_MMX sse2 +PRED8x8L_HORIZONTAL_DOWN +INIT_MMX ssse3 +PRED8x8L_HORIZONTAL_DOWN + +;----------------------------------------------------------------------------- +; void pred4x4_dc_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_dc_8, 3,5 + pxor mm7, mm7 + mov r4, r0 + sub r0, r2 + movd mm0, [r0] + psadbw mm0, mm7 + movzx r1d, byte [r0+r2*1-1] + movd r3d, mm0 + add r3d, r1d + movzx r1d, byte [r0+r2*2-1] + lea r0, [r0+r2*2] + add r3d, r1d + movzx r1d, byte [r0+r2*1-1] + add r3d, r1d + movzx r1d, byte [r0+r2*2-1] + add r3d, r1d + add r3d, 4 + shr r3d, 3 + imul r3d, 0x01010101 + mov [r4+r2*0], r3d + mov [r0+r2*0], r3d + mov [r0+r2*1], r3d + mov [r0+r2*2], r3d + RET + +;----------------------------------------------------------------------------- +; void pred4x4_tm_vp8_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +%macro PRED4x4_TM 0 +cglobal pred4x4_tm_vp8_8, 3,6 + sub r0, r2 + pxor mm7, mm7 + movd mm0, [r0] + punpcklbw mm0, mm7 + movzx r4d, byte [r0-1] + mov r5d, 2 +.loop: + movzx r1d, byte [r0+r2*1-1] + movzx r3d, byte [r0+r2*2-1] + sub r1d, r4d + sub r3d, r4d + movd mm2, r1d + movd mm4, r3d +%if cpuflag(mmxext) + pshufw mm2, mm2, 0 + pshufw mm4, mm4, 0 +%else + punpcklwd mm2, mm2 + punpcklwd mm4, mm4 + punpckldq mm2, mm2 + punpckldq mm4, mm4 +%endif + paddw mm2, mm0 + paddw mm4, mm0 + packuswb mm2, mm2 + packuswb mm4, mm4 + movd [r0+r2*1], mm2 + movd [r0+r2*2], mm4 + lea r0, [r0+r2*2] + dec r5d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmx +PRED4x4_TM +INIT_MMX mmxext +PRED4x4_TM + +INIT_XMM ssse3 +cglobal pred4x4_tm_vp8_8, 3,3 + sub r0, r2 + movq mm6, [tm_shuf] + pxor mm1, mm1 + movd mm0, [r0] + punpcklbw mm0, mm1 + movd mm7, [r0-4] + pshufb mm7, mm6 + lea r1, [r0+r2*2] + movd mm2, [r0+r2*1-4] + movd mm3, [r0+r2*2-4] + movd mm4, [r1+r2*1-4] + movd mm5, [r1+r2*2-4] + pshufb mm2, mm6 + pshufb mm3, mm6 + pshufb mm4, mm6 + pshufb mm5, mm6 + psubw mm2, mm7 + psubw mm3, mm7 + psubw mm4, mm7 + psubw mm5, mm7 + paddw mm2, mm0 + paddw mm3, mm0 + paddw mm4, mm0 + paddw mm5, mm0 + packuswb mm2, mm2 + packuswb mm3, mm3 + packuswb mm4, mm4 + packuswb mm5, mm5 + movd [r0+r2*1], mm2 + movd [r0+r2*2], mm3 + movd [r1+r2*1], mm4 + movd [r1+r2*2], mm5 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_vertical_vp8_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_vertical_vp8_8, 3,3 + sub r0, r2 + movd m1, [r0-1] + movd m0, [r0] + mova m2, m0 ;t0 t1 t2 t3 + punpckldq m0, [r1] ;t0 t1 t2 t3 t4 t5 t6 t7 + lea r1, [r0+r2*2] + psrlq m0, 8 ;t1 t2 t3 t4 + PRED4x4_LOWPASS m3, m1, m0, m2, m4 + movd [r0+r2*1], m3 + movd [r0+r2*2], m3 + movd [r1+r2*1], m3 + movd [r1+r2*2], m3 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_down_left_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- +INIT_MMX mmxext +cglobal pred4x4_down_left_8, 3,3 + sub r0, r2 + movq m1, [r0] + punpckldq m1, [r1] + movq m2, m1 + movq m3, m1 + psllq m1, 8 + pxor m2, m1 + psrlq m2, 8 + pxor m2, m3 + PRED4x4_LOWPASS m0, m1, m2, m3, m4 + lea r1, [r0+r2*2] + psrlq m0, 8 + movd [r0+r2*1], m0 + psrlq m0, 8 + movd [r0+r2*2], m0 + psrlq m0, 8 + movd [r1+r2*1], m0 + psrlq m0, 8 + movd [r1+r2*2], m0 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_vertical_left_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_vertical_left_8, 3,3 + sub r0, r2 + movq m1, [r0] + punpckldq m1, [r1] + movq m3, m1 + movq m2, m1 + psrlq m3, 8 + psrlq m2, 16 + movq m4, m3 + pavgb m4, m1 + PRED4x4_LOWPASS m0, m1, m2, m3, m5 + lea r1, [r0+r2*2] + movh [r0+r2*1], m4 + movh [r0+r2*2], m0 + psrlq m4, 8 + psrlq m0, 8 + movh [r1+r2*1], m4 + movh [r1+r2*2], m0 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_horizontal_up_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_horizontal_up_8, 3,3 + sub r0, r2 + lea r1, [r0+r2*2] + movd m0, [r0+r2*1-4] + punpcklbw m0, [r0+r2*2-4] + movd m1, [r1+r2*1-4] + punpcklbw m1, [r1+r2*2-4] + punpckhwd m0, m1 + movq m1, m0 + punpckhbw m1, m1 + pshufw m1, m1, 0xFF + punpckhdq m0, m1 + movq m2, m0 + movq m3, m0 + movq m7, m0 + psrlq m2, 16 + psrlq m3, 8 + pavgb m7, m3 + PRED4x4_LOWPASS m4, m0, m2, m3, m5 + punpcklbw m7, m4 + movd [r0+r2*1], m7 + psrlq m7, 16 + movd [r0+r2*2], m7 + psrlq m7, 16 + movd [r1+r2*1], m7 + movd [r1+r2*2], m1 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_horizontal_down_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_horizontal_down_8, 3,3 + sub r0, r2 + lea r1, [r0+r2*2] + movh m0, [r0-4] ; lt .. + punpckldq m0, [r0] ; t3 t2 t1 t0 lt .. .. .. + psllq m0, 8 ; t2 t1 t0 lt .. .. .. .. + movd m1, [r1+r2*2-4] ; l3 + punpcklbw m1, [r1+r2*1-4] ; l2 l3 + movd m2, [r0+r2*2-4] ; l1 + punpcklbw m2, [r0+r2*1-4] ; l0 l1 + punpckhwd m1, m2 ; l0 l1 l2 l3 + punpckhdq m1, m0 ; t2 t1 t0 lt l0 l1 l2 l3 + movq m0, m1 + movq m2, m1 + movq m5, m1 + psrlq m0, 16 ; .. .. t2 t1 t0 lt l0 l1 + psrlq m2, 8 ; .. t2 t1 t0 lt l0 l1 l2 + pavgb m5, m2 + PRED4x4_LOWPASS m3, m1, m0, m2, m4 + punpcklbw m5, m3 + psrlq m3, 32 + PALIGNR m3, m5, 6, m4 + movh [r1+r2*2], m5 + psrlq m5, 16 + movh [r1+r2*1], m5 + psrlq m5, 16 + movh [r0+r2*2], m5 + movh [r0+r2*1], m3 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_vertical_right_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_vertical_right_8, 3,3 + sub r0, r2 + lea r1, [r0+r2*2] + movh m0, [r0] ; ........t3t2t1t0 + movq m5, m0 + PALIGNR m0, [r0-8], 7, m1 ; ......t3t2t1t0lt + pavgb m5, m0 + PALIGNR m0, [r0+r2*1-8], 7, m1 ; ....t3t2t1t0ltl0 + movq m1, m0 + PALIGNR m0, [r0+r2*2-8], 7, m2 ; ..t3t2t1t0ltl0l1 + movq m2, m0 + PALIGNR m0, [r1+r2*1-8], 7, m3 ; t3t2t1t0ltl0l1l2 + PRED4x4_LOWPASS m3, m1, m0, m2, m4 + movq m1, m3 + psrlq m3, 16 + psllq m1, 48 + movh [r0+r2*1], m5 + movh [r0+r2*2], m3 + PALIGNR m5, m1, 7, m2 + psllq m1, 8 + movh [r1+r2*1], m5 + PALIGNR m3, m1, 7, m1 + movh [r1+r2*2], m3 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_down_right_8_mmxext(uint8_t *src, const uint8_t *topright, int stride) +;----------------------------------------------------------------------------- + +INIT_MMX mmxext +cglobal pred4x4_down_right_8, 3,3 + sub r0, r2 + lea r1, [r0+r2*2] + movq m1, [r1-8] + movq m2, [r0+r2*1-8] + punpckhbw m2, [r0-8] + movh m3, [r0] + punpckhwd m1, m2 + PALIGNR m3, m1, 5, m1 + movq m1, m3 + PALIGNR m3, [r1+r2*1-8], 7, m4 + movq m2, m3 + PALIGNR m3, [r1+r2*2-8], 7, m4 + PRED4x4_LOWPASS m0, m3, m1, m2, m4 + movh [r1+r2*2], m0 + psrlq m0, 8 + movh [r1+r2*1], m0 + psrlq m0, 8 + movh [r0+r2*2], m0 + psrlq m0, 8 + movh [r0+r2*1], m0 + RET diff --git a/ffmpeg/libavcodec/x86/h264_intrapred_10bit.asm b/ffmpeg/libavcodec/x86/h264_intrapred_10bit.asm new file mode 100644 index 0000000..db2b25c --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_intrapred_10bit.asm @@ -0,0 +1,1199 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 intra prediction code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Daniel Kang +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_16 +cextern pw_8 +cextern pw_4 +cextern pw_2 +cextern pw_1 + +pw_m32101234: dw -3, -2, -1, 0, 1, 2, 3, 4 +pw_m3: times 8 dw -3 +pw_pixel_max: times 8 dw ((1 << 10)-1) +pw_512: times 8 dw 512 +pd_17: times 4 dd 17 +pd_16: times 4 dd 16 + +SECTION .text + +; dest, left, right, src +; output: %1 = (t[n-1] + t[n]*2 + t[n+1] + 2) >> 2 +%macro PRED4x4_LOWPASS 4 + paddw %2, %3 + psrlw %2, 1 + pavgw %1, %4, %2 +%endmacro + +;----------------------------------------------------------------------------- +; void pred4x4_down_right(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED4x4_DR 0 +cglobal pred4x4_down_right_10, 3, 3 + sub r0, r2 + lea r1, [r0+r2*2] + movhps m1, [r1-8] + movhps m2, [r0+r2*1-8] + movhps m4, [r0-8] + punpckhwd m2, m4 + movq m3, [r0] + punpckhdq m1, m2 + PALIGNR m3, m1, 10, m1 + movhps m4, [r1+r2*1-8] + PALIGNR m0, m3, m4, 14, m4 + movhps m4, [r1+r2*2-8] + PALIGNR m2, m0, m4, 14, m4 + PRED4x4_LOWPASS m0, m2, m3, m0 + movq [r1+r2*2], m0 + psrldq m0, 2 + movq [r1+r2*1], m0 + psrldq m0, 2 + movq [r0+r2*2], m0 + psrldq m0, 2 + movq [r0+r2*1], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED4x4_DR +INIT_XMM ssse3 +PRED4x4_DR +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED4x4_DR +%endif + +;----------------------------------------------------------------------------- +; void pred4x4_vertical_right(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED4x4_VR 0 +cglobal pred4x4_vertical_right_10, 3, 3, 6 + sub r0, r2 + lea r1, [r0+r2*2] + movq m5, [r0] ; ........t3t2t1t0 + movhps m1, [r0-8] + PALIGNR m0, m5, m1, 14, m1 ; ......t3t2t1t0lt + pavgw m5, m0 + movhps m1, [r0+r2*1-8] + PALIGNR m0, m1, 14, m1 ; ....t3t2t1t0ltl0 + movhps m2, [r0+r2*2-8] + PALIGNR m1, m0, m2, 14, m2 ; ..t3t2t1t0ltl0l1 + movhps m3, [r1+r2*1-8] + PALIGNR m2, m1, m3, 14, m3 ; t3t2t1t0ltl0l1l2 + PRED4x4_LOWPASS m1, m0, m2, m1 + pslldq m0, m1, 12 + psrldq m1, 4 + movq [r0+r2*1], m5 + movq [r0+r2*2], m1 + PALIGNR m5, m0, 14, m2 + pslldq m0, 2 + movq [r1+r2*1], m5 + PALIGNR m1, m0, 14, m0 + movq [r1+r2*2], m1 + RET +%endmacro + +INIT_XMM sse2 +PRED4x4_VR +INIT_XMM ssse3 +PRED4x4_VR +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED4x4_VR +%endif + +;----------------------------------------------------------------------------- +; void pred4x4_horizontal_down(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED4x4_HD 0 +cglobal pred4x4_horizontal_down_10, 3, 3 + sub r0, r2 + lea r1, [r0+r2*2] + movq m0, [r0-8] ; lt .. + movhps m0, [r0] + pslldq m0, 2 ; t2 t1 t0 lt .. .. .. .. + movq m1, [r1+r2*2-8] ; l3 + movq m3, [r1+r2*1-8] + punpcklwd m1, m3 ; l2 l3 + movq m2, [r0+r2*2-8] ; l1 + movq m3, [r0+r2*1-8] + punpcklwd m2, m3 ; l0 l1 + punpckhdq m1, m2 ; l0 l1 l2 l3 + punpckhqdq m1, m0 ; t2 t1 t0 lt l0 l1 l2 l3 + psrldq m0, m1, 4 ; .. .. t2 t1 t0 lt l0 l1 + psrldq m3, m1, 2 ; .. t2 t1 t0 lt l0 l1 l2 + pavgw m5, m1, m3 + PRED4x4_LOWPASS m3, m1, m0, m3 + punpcklwd m5, m3 + psrldq m3, 8 + PALIGNR m3, m5, 12, m4 + movq [r1+r2*2], m5 + movhps [r0+r2*2], m5 + psrldq m5, 4 + movq [r1+r2*1], m5 + movq [r0+r2*1], m3 + RET +%endmacro + +INIT_XMM sse2 +PRED4x4_HD +INIT_XMM ssse3 +PRED4x4_HD +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED4x4_HD +%endif + +;----------------------------------------------------------------------------- +; void pred4x4_dc(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +%macro HADDD 2 ; sum junk +%if mmsize == 16 + movhlps %2, %1 + paddd %1, %2 + pshuflw %2, %1, 0xE + paddd %1, %2 +%else + pshufw %2, %1, 0xE + paddd %1, %2 +%endif +%endmacro + +%macro HADDW 2 + pmaddwd %1, [pw_1] + HADDD %1, %2 +%endmacro + +INIT_MMX mmxext +cglobal pred4x4_dc_10, 3, 3 + sub r0, r2 + lea r1, [r0+r2*2] + movq m2, [r0+r2*1-8] + paddw m2, [r0+r2*2-8] + paddw m2, [r1+r2*1-8] + paddw m2, [r1+r2*2-8] + psrlq m2, 48 + movq m0, [r0] + HADDW m0, m1 + paddw m0, [pw_4] + paddw m0, m2 + psrlw m0, 3 + SPLATW m0, m0, 0 + movq [r0+r2*1], m0 + movq [r0+r2*2], m0 + movq [r1+r2*1], m0 + movq [r1+r2*2], m0 + RET + +;----------------------------------------------------------------------------- +; void pred4x4_down_left(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED4x4_DL 0 +cglobal pred4x4_down_left_10, 3, 3 + sub r0, r2 + movq m0, [r0] + movhps m0, [r1] + psrldq m2, m0, 2 + pslldq m3, m0, 2 + pshufhw m2, m2, 10100100b + PRED4x4_LOWPASS m0, m3, m2, m0 + lea r1, [r0+r2*2] + movhps [r1+r2*2], m0 + psrldq m0, 2 + movq [r0+r2*1], m0 + psrldq m0, 2 + movq [r0+r2*2], m0 + psrldq m0, 2 + movq [r1+r2*1], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED4x4_DL +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED4x4_DL +%endif + +;----------------------------------------------------------------------------- +; void pred4x4_vertical_left(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED4x4_VL 0 +cglobal pred4x4_vertical_left_10, 3, 3 + sub r0, r2 + movu m1, [r0] + movhps m1, [r1] + psrldq m0, m1, 2 + psrldq m2, m1, 4 + pavgw m4, m0, m1 + PRED4x4_LOWPASS m0, m1, m2, m0 + lea r1, [r0+r2*2] + movq [r0+r2*1], m4 + movq [r0+r2*2], m0 + psrldq m4, 2 + psrldq m0, 2 + movq [r1+r2*1], m4 + movq [r1+r2*2], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED4x4_VL +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED4x4_VL +%endif + +;----------------------------------------------------------------------------- +; void pred4x4_horizontal_up(pixel *src, const pixel *topright, int stride) +;----------------------------------------------------------------------------- +INIT_MMX mmxext +cglobal pred4x4_horizontal_up_10, 3, 3 + sub r0, r2 + lea r1, [r0+r2*2] + movq m0, [r0+r2*1-8] + punpckhwd m0, [r0+r2*2-8] + movq m1, [r1+r2*1-8] + punpckhwd m1, [r1+r2*2-8] + punpckhdq m0, m1 + pshufw m1, m1, 0xFF + movq [r1+r2*2], m1 + movd [r1+r2*1+4], m1 + pshufw m2, m0, 11111001b + movq m1, m2 + pavgw m2, m0 + + pshufw m5, m0, 11111110b + PRED4x4_LOWPASS m1, m0, m5, m1 + movq m6, m2 + punpcklwd m6, m1 + movq [r0+r2*1], m6 + psrlq m2, 16 + psrlq m1, 16 + punpcklwd m2, m1 + movq [r0+r2*2], m2 + psrlq m2, 32 + movd [r1+r2*1], m2 + RET + + + +;----------------------------------------------------------------------------- +; void pred8x8_vertical(pixel *src, int stride) +;----------------------------------------------------------------------------- +INIT_XMM sse2 +cglobal pred8x8_vertical_10, 2, 2 + sub r0, r1 + mova m0, [r0] +%rep 3 + mova [r0+r1*1], m0 + mova [r0+r1*2], m0 + lea r0, [r0+r1*2] +%endrep + mova [r0+r1*1], m0 + mova [r0+r1*2], m0 + RET + +;----------------------------------------------------------------------------- +; void pred8x8_horizontal(pixel *src, int stride) +;----------------------------------------------------------------------------- +INIT_XMM sse2 +cglobal pred8x8_horizontal_10, 2, 3 + mov r2d, 4 +.loop: + movq m0, [r0+r1*0-8] + movq m1, [r0+r1*1-8] + pshuflw m0, m0, 0xff + pshuflw m1, m1, 0xff + punpcklqdq m0, m0 + punpcklqdq m1, m1 + mova [r0+r1*0], m0 + mova [r0+r1*1], m1 + lea r0, [r0+r1*2] + dec r2d + jg .loop + REP_RET + +;----------------------------------------------------------------------------- +; void predict_8x8_dc(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro MOV8 2-3 +; sort of a hack, but it works +%if mmsize==8 + movq [%1+0], %2 + movq [%1+8], %3 +%else + movdqa [%1], %2 +%endif +%endmacro + +%macro PRED8x8_DC 1 +cglobal pred8x8_dc_10, 2, 6 + sub r0, r1 + pxor m4, m4 + movq m0, [r0+0] + movq m1, [r0+8] +%if mmsize==16 + punpcklwd m0, m1 + movhlps m1, m0 + paddw m0, m1 +%else + pshufw m2, m0, 00001110b + pshufw m3, m1, 00001110b + paddw m0, m2 + paddw m1, m3 + punpcklwd m0, m1 +%endif + %1 m2, m0, 00001110b + paddw m0, m2 + + lea r5, [r1*3] + lea r4, [r0+r1*4] + movzx r2d, word [r0+r1*1-2] + movzx r3d, word [r0+r1*2-2] + add r2d, r3d + movzx r3d, word [r0+r5*1-2] + add r2d, r3d + movzx r3d, word [r4-2] + add r2d, r3d + movd m2, r2d ; s2 + + movzx r2d, word [r4+r1*1-2] + movzx r3d, word [r4+r1*2-2] + add r2d, r3d + movzx r3d, word [r4+r5*1-2] + add r2d, r3d + movzx r3d, word [r4+r1*4-2] + add r2d, r3d + movd m3, r2d ; s3 + + punpcklwd m2, m3 + punpckldq m0, m2 ; s0, s1, s2, s3 + %1 m3, m0, 11110110b ; s2, s1, s3, s3 + %1 m0, m0, 01110100b ; s0, s1, s3, s1 + paddw m0, m3 + psrlw m0, 2 + pavgw m0, m4 ; s0+s2, s1, s3, s1+s3 +%if mmsize==16 + punpcklwd m0, m0 + pshufd m3, m0, 11111010b + punpckldq m0, m0 + SWAP 0,1 +%else + pshufw m1, m0, 0x00 + pshufw m2, m0, 0x55 + pshufw m3, m0, 0xaa + pshufw m4, m0, 0xff +%endif + MOV8 r0+r1*1, m1, m2 + MOV8 r0+r1*2, m1, m2 + MOV8 r0+r5*1, m1, m2 + MOV8 r0+r1*4, m1, m2 + MOV8 r4+r1*1, m3, m4 + MOV8 r4+r1*2, m3, m4 + MOV8 r4+r5*1, m3, m4 + MOV8 r4+r1*4, m3, m4 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8_DC pshufw +INIT_XMM sse2 +PRED8x8_DC pshuflw + +;----------------------------------------------------------------------------- +; void pred8x8_top_dc(pixel *src, int stride) +;----------------------------------------------------------------------------- +INIT_XMM sse2 +cglobal pred8x8_top_dc_10, 2, 4 + sub r0, r1 + mova m0, [r0] + pshuflw m1, m0, 0x4e + pshufhw m1, m1, 0x4e + paddw m0, m1 + pshuflw m1, m0, 0xb1 + pshufhw m1, m1, 0xb1 + paddw m0, m1 + lea r2, [r1*3] + lea r3, [r0+r1*4] + paddw m0, [pw_2] + psrlw m0, 2 + mova [r0+r1*1], m0 + mova [r0+r1*2], m0 + mova [r0+r2*1], m0 + mova [r0+r1*4], m0 + mova [r3+r1*1], m0 + mova [r3+r1*2], m0 + mova [r3+r2*1], m0 + mova [r3+r1*4], m0 + RET + +;----------------------------------------------------------------------------- +; void pred8x8_plane(pixel *src, int stride) +;----------------------------------------------------------------------------- +INIT_XMM sse2 +cglobal pred8x8_plane_10, 2, 7, 7 + sub r0, r1 + lea r2, [r1*3] + lea r3, [r0+r1*4] + mova m2, [r0] + pmaddwd m2, [pw_m32101234] + HADDD m2, m1 + movd m0, [r0-4] + psrld m0, 14 + psubw m2, m0 ; H + movd m0, [r3+r1*4-4] + movd m1, [r0+12] + paddw m0, m1 + psllw m0, 4 ; 16*(src[7*stride-1] + src[-stride+7]) + movzx r4d, word [r3+r1*1-2] ; src[4*stride-1] + movzx r5d, word [r0+r2*1-2] ; src[2*stride-1] + sub r4d, r5d + movzx r6d, word [r3+r1*2-2] ; src[5*stride-1] + movzx r5d, word [r0+r1*2-2] ; src[1*stride-1] + sub r6d, r5d + lea r4d, [r4+r6*2] + movzx r5d, word [r3+r2*1-2] ; src[6*stride-1] + movzx r6d, word [r0+r1*1-2] ; src[0*stride-1] + sub r5d, r6d + lea r5d, [r5*3] + add r4d, r5d + movzx r6d, word [r3+r1*4-2] ; src[7*stride-1] + movzx r5d, word [r0+r1*0-2] ; src[ -stride-1] + sub r6d, r5d + lea r4d, [r4+r6*4] + movd m3, r4d ; V + punpckldq m2, m3 + pmaddwd m2, [pd_17] + paddd m2, [pd_16] + psrad m2, 5 ; b, c + + mova m3, [pw_pixel_max] + pxor m1, m1 + SPLATW m0, m0, 1 + SPLATW m4, m2, 2 + SPLATW m2, m2, 0 + pmullw m2, [pw_m32101234] ; b + pmullw m5, m4, [pw_m3] ; c + paddw m5, [pw_16] + mov r2d, 8 + add r0, r1 +.loop: + paddsw m6, m2, m5 + paddsw m6, m0 + psraw m6, 5 + CLIPW m6, m1, m3 + mova [r0], m6 + paddw m5, m4 + add r0, r1 + dec r2d + jg .loop + REP_RET + + +;----------------------------------------------------------------------------- +; void pred8x8l_128_dc(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_128_DC 0 +cglobal pred8x8l_128_dc_10, 4, 4 + mova m0, [pw_512] ; (1<<(BIT_DEPTH-1)) + lea r1, [r3*3] + lea r2, [r0+r3*4] + MOV8 r0+r3*0, m0, m0 + MOV8 r0+r3*1, m0, m0 + MOV8 r0+r3*2, m0, m0 + MOV8 r0+r1*1, m0, m0 + MOV8 r2+r3*0, m0, m0 + MOV8 r2+r3*1, m0, m0 + MOV8 r2+r3*2, m0, m0 + MOV8 r2+r1*1, m0, m0 + RET +%endmacro + +INIT_MMX mmxext +PRED8x8L_128_DC +INIT_XMM sse2 +PRED8x8L_128_DC + +;----------------------------------------------------------------------------- +; void pred8x8l_top_dc(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_TOP_DC 0 +cglobal pred8x8l_top_dc_10, 4, 4, 6 + sub r0, r3 + mova m0, [r0] + shr r1d, 14 + shr r2d, 13 + neg r1 + pslldq m1, m0, 2 + psrldq m2, m0, 2 + pinsrw m1, [r0+r1], 0 + pinsrw m2, [r0+r2+14], 7 + lea r1, [r3*3] + lea r2, [r0+r3*4] + PRED4x4_LOWPASS m0, m2, m1, m0 + HADDW m0, m1 + paddw m0, [pw_4] + psrlw m0, 3 + SPLATW m0, m0, 0 + mova [r0+r3*1], m0 + mova [r0+r3*2], m0 + mova [r0+r1*1], m0 + mova [r0+r3*4], m0 + mova [r2+r3*1], m0 + mova [r2+r3*2], m0 + mova [r2+r1*1], m0 + mova [r2+r3*4], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_TOP_DC +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_TOP_DC +%endif + +;----------------------------------------------------------------------------- +;void pred8x8l_dc(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +;TODO: see if scalar is faster +%macro PRED8x8L_DC 0 +cglobal pred8x8l_dc_10, 4, 6, 6 + sub r0, r3 + lea r4, [r0+r3*4] + lea r5, [r3*3] + mova m0, [r0+r3*2-16] + punpckhwd m0, [r0+r3*1-16] + mova m1, [r4+r3*0-16] + punpckhwd m1, [r0+r5*1-16] + punpckhdq m1, m0 + mova m2, [r4+r3*2-16] + punpckhwd m2, [r4+r3*1-16] + mova m3, [r4+r3*4-16] + punpckhwd m3, [r4+r5*1-16] + punpckhdq m3, m2 + punpckhqdq m3, m1 + mova m0, [r0] + shr r1d, 14 + shr r2d, 13 + neg r1 + pslldq m1, m0, 2 + psrldq m2, m0, 2 + pinsrw m1, [r0+r1], 0 + pinsrw m2, [r0+r2+14], 7 + not r1 + and r1, r3 + pslldq m4, m3, 2 + psrldq m5, m3, 2 + pshuflw m4, m4, 11100101b + pinsrw m5, [r0+r1-2], 7 + PRED4x4_LOWPASS m3, m4, m5, m3 + PRED4x4_LOWPASS m0, m2, m1, m0 + paddw m0, m3 + HADDW m0, m1 + paddw m0, [pw_8] + psrlw m0, 4 + SPLATW m0, m0 + mova [r0+r3*1], m0 + mova [r0+r3*2], m0 + mova [r0+r5*1], m0 + mova [r0+r3*4], m0 + mova [r4+r3*1], m0 + mova [r4+r3*2], m0 + mova [r4+r5*1], m0 + mova [r4+r3*4], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_DC +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_DC +%endif + +;----------------------------------------------------------------------------- +; void pred8x8l_vertical(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_VERTICAL 0 +cglobal pred8x8l_vertical_10, 4, 4, 6 + sub r0, r3 + mova m0, [r0] + shr r1d, 14 + shr r2d, 13 + neg r1 + pslldq m1, m0, 2 + psrldq m2, m0, 2 + pinsrw m1, [r0+r1], 0 + pinsrw m2, [r0+r2+14], 7 + lea r1, [r3*3] + lea r2, [r0+r3*4] + PRED4x4_LOWPASS m0, m2, m1, m0 + mova [r0+r3*1], m0 + mova [r0+r3*2], m0 + mova [r0+r1*1], m0 + mova [r0+r3*4], m0 + mova [r2+r3*1], m0 + mova [r2+r3*2], m0 + mova [r2+r1*1], m0 + mova [r2+r3*4], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_VERTICAL +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_VERTICAL +%endif + +;----------------------------------------------------------------------------- +; void pred8x8l_horizontal(uint8_t *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_HORIZONTAL 0 +cglobal pred8x8l_horizontal_10, 4, 4, 5 + mova m0, [r0-16] + shr r1d, 14 + dec r1 + and r1, r3 + sub r1, r3 + punpckhwd m0, [r0+r1-16] + mova m1, [r0+r3*2-16] + punpckhwd m1, [r0+r3*1-16] + lea r2, [r0+r3*4] + lea r1, [r3*3] + punpckhdq m1, m0 + mova m2, [r2+r3*0-16] + punpckhwd m2, [r0+r1-16] + mova m3, [r2+r3*2-16] + punpckhwd m3, [r2+r3*1-16] + punpckhdq m3, m2 + punpckhqdq m3, m1 + PALIGNR m4, m3, [r2+r1-16], 14, m0 + pslldq m0, m4, 2 + pshuflw m0, m0, 11100101b + PRED4x4_LOWPASS m4, m3, m0, m4 + punpckhwd m3, m4, m4 + punpcklwd m4, m4 + pshufd m0, m3, 0xff + pshufd m1, m3, 0xaa + pshufd m2, m3, 0x55 + pshufd m3, m3, 0x00 + mova [r0+r3*0], m0 + mova [r0+r3*1], m1 + mova [r0+r3*2], m2 + mova [r0+r1*1], m3 + pshufd m0, m4, 0xff + pshufd m1, m4, 0xaa + pshufd m2, m4, 0x55 + pshufd m3, m4, 0x00 + mova [r2+r3*0], m0 + mova [r2+r3*1], m1 + mova [r2+r3*2], m2 + mova [r2+r1*1], m3 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_HORIZONTAL +INIT_XMM ssse3 +PRED8x8L_HORIZONTAL +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_HORIZONTAL +%endif + +;----------------------------------------------------------------------------- +;void pred8x8l_down_left(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_DOWN_LEFT 0 +cglobal pred8x8l_down_left_10, 4, 4, 7 + sub r0, r3 + mova m3, [r0] + shr r1d, 14 + neg r1 + shr r2d, 13 + pslldq m1, m3, 2 + psrldq m2, m3, 2 + pinsrw m1, [r0+r1], 0 + pinsrw m2, [r0+r2+14], 7 + PRED4x4_LOWPASS m6, m2, m1, m3 + jz .fix_tr ; flags from shr r2d + mova m1, [r0+16] + psrldq m5, m1, 2 + PALIGNR m2, m1, m3, 14, m3 + pshufhw m5, m5, 10100100b + PRED4x4_LOWPASS m1, m2, m5, m1 +.do_topright: + lea r1, [r3*3] + psrldq m5, m1, 14 + lea r2, [r0+r3*4] + PALIGNR m2, m1, m6, 2, m0 + PALIGNR m3, m1, m6, 14, m0 + PALIGNR m5, m1, 2, m0 + pslldq m4, m6, 2 + PRED4x4_LOWPASS m6, m4, m2, m6 + PRED4x4_LOWPASS m1, m3, m5, m1 + mova [r2+r3*4], m1 + PALIGNR m1, m6, 14, m2 + pslldq m6, 2 + mova [r2+r1*1], m1 + PALIGNR m1, m6, 14, m2 + pslldq m6, 2 + mova [r2+r3*2], m1 + PALIGNR m1, m6, 14, m2 + pslldq m6, 2 + mova [r2+r3*1], m1 + PALIGNR m1, m6, 14, m2 + pslldq m6, 2 + mova [r0+r3*4], m1 + PALIGNR m1, m6, 14, m2 + pslldq m6, 2 + mova [r0+r1*1], m1 + PALIGNR m1, m6, 14, m2 + pslldq m6, 2 + mova [r0+r3*2], m1 + PALIGNR m1, m6, 14, m6 + mova [r0+r3*1], m1 + RET +.fix_tr: + punpckhwd m3, m3 + pshufd m1, m3, 0xFF + jmp .do_topright +%endmacro + +INIT_XMM sse2 +PRED8x8L_DOWN_LEFT +INIT_XMM ssse3 +PRED8x8L_DOWN_LEFT +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_DOWN_LEFT +%endif + +;----------------------------------------------------------------------------- +;void pred8x8l_down_right(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_DOWN_RIGHT 0 +; standard forbids this when has_topleft is false +; no need to check +cglobal pred8x8l_down_right_10, 4, 5, 8 + sub r0, r3 + lea r4, [r0+r3*4] + lea r1, [r3*3] + mova m0, [r0+r3*1-16] + punpckhwd m0, [r0+r3*0-16] + mova m1, [r0+r1*1-16] + punpckhwd m1, [r0+r3*2-16] + punpckhdq m1, m0 + mova m2, [r4+r3*1-16] + punpckhwd m2, [r4+r3*0-16] + mova m3, [r4+r1*1-16] + punpckhwd m3, [r4+r3*2-16] + punpckhdq m3, m2 + punpckhqdq m3, m1 + mova m0, [r4+r3*4-16] + mova m1, [r0] + PALIGNR m4, m3, m0, 14, m0 + PALIGNR m1, m3, 2, m2 + pslldq m0, m4, 2 + pshuflw m0, m0, 11100101b + PRED4x4_LOWPASS m6, m1, m4, m3 + PRED4x4_LOWPASS m4, m3, m0, m4 + mova m3, [r0] + shr r2d, 13 + pslldq m1, m3, 2 + psrldq m2, m3, 2 + pinsrw m1, [r0-2], 0 + pinsrw m2, [r0+r2+14], 7 + PRED4x4_LOWPASS m3, m2, m1, m3 + PALIGNR m2, m3, m6, 2, m0 + PALIGNR m5, m3, m6, 14, m0 + psrldq m7, m3, 2 + PRED4x4_LOWPASS m6, m4, m2, m6 + PRED4x4_LOWPASS m3, m5, m7, m3 + mova [r4+r3*4], m6 + PALIGNR m3, m6, 14, m2 + pslldq m6, 2 + mova [r0+r3*1], m3 + PALIGNR m3, m6, 14, m2 + pslldq m6, 2 + mova [r0+r3*2], m3 + PALIGNR m3, m6, 14, m2 + pslldq m6, 2 + mova [r0+r1*1], m3 + PALIGNR m3, m6, 14, m2 + pslldq m6, 2 + mova [r0+r3*4], m3 + PALIGNR m3, m6, 14, m2 + pslldq m6, 2 + mova [r4+r3*1], m3 + PALIGNR m3, m6, 14, m2 + pslldq m6, 2 + mova [r4+r3*2], m3 + PALIGNR m3, m6, 14, m6 + mova [r4+r1*1], m3 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_DOWN_RIGHT +INIT_XMM ssse3 +PRED8x8L_DOWN_RIGHT +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_DOWN_RIGHT +%endif + +;----------------------------------------------------------------------------- +; void pred8x8l_vertical_right(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_VERTICAL_RIGHT 0 +; likewise with 8x8l_down_right +cglobal pred8x8l_vertical_right_10, 4, 5, 7 + sub r0, r3 + lea r4, [r0+r3*4] + lea r1, [r3*3] + mova m0, [r0+r3*1-16] + punpckhwd m0, [r0+r3*0-16] + mova m1, [r0+r1*1-16] + punpckhwd m1, [r0+r3*2-16] + punpckhdq m1, m0 + mova m2, [r4+r3*1-16] + punpckhwd m2, [r4+r3*0-16] + mova m3, [r4+r1*1-16] + punpckhwd m3, [r4+r3*2-16] + punpckhdq m3, m2 + punpckhqdq m3, m1 + mova m0, [r4+r3*4-16] + mova m1, [r0] + PALIGNR m4, m3, m0, 14, m0 + PALIGNR m1, m3, 2, m2 + PRED4x4_LOWPASS m3, m1, m4, m3 + mova m2, [r0] + shr r2d, 13 + pslldq m1, m2, 2 + psrldq m5, m2, 2 + pinsrw m1, [r0-2], 0 + pinsrw m5, [r0+r2+14], 7 + PRED4x4_LOWPASS m2, m5, m1, m2 + PALIGNR m6, m2, m3, 12, m1 + PALIGNR m5, m2, m3, 14, m0 + PRED4x4_LOWPASS m0, m6, m2, m5 + pavgw m2, m5 + mova [r0+r3*2], m0 + mova [r0+r3*1], m2 + pslldq m6, m3, 4 + pslldq m1, m3, 2 + PRED4x4_LOWPASS m1, m3, m6, m1 + PALIGNR m2, m1, 14, m4 + mova [r0+r1*1], m2 + pslldq m1, 2 + PALIGNR m0, m1, 14, m3 + mova [r0+r3*4], m0 + pslldq m1, 2 + PALIGNR m2, m1, 14, m4 + mova [r4+r3*1], m2 + pslldq m1, 2 + PALIGNR m0, m1, 14, m3 + mova [r4+r3*2], m0 + pslldq m1, 2 + PALIGNR m2, m1, 14, m4 + mova [r4+r1*1], m2 + pslldq m1, 2 + PALIGNR m0, m1, 14, m1 + mova [r4+r3*4], m0 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_VERTICAL_RIGHT +INIT_XMM ssse3 +PRED8x8L_VERTICAL_RIGHT +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_VERTICAL_RIGHT +%endif + +;----------------------------------------------------------------------------- +; void pred8x8l_horizontal_up(pixel *src, int has_topleft, int has_topright, int stride) +;----------------------------------------------------------------------------- +%macro PRED8x8L_HORIZONTAL_UP 0 +cglobal pred8x8l_horizontal_up_10, 4, 4, 6 + mova m0, [r0+r3*0-16] + punpckhwd m0, [r0+r3*1-16] + shr r1d, 14 + dec r1 + and r1, r3 + sub r1, r3 + mova m4, [r0+r1*1-16] + lea r1, [r3*3] + lea r2, [r0+r3*4] + mova m1, [r0+r3*2-16] + punpckhwd m1, [r0+r1*1-16] + punpckhdq m0, m1 + mova m2, [r2+r3*0-16] + punpckhwd m2, [r2+r3*1-16] + mova m3, [r2+r3*2-16] + punpckhwd m3, [r2+r1*1-16] + punpckhdq m2, m3 + punpckhqdq m0, m2 + PALIGNR m1, m0, m4, 14, m4 + psrldq m2, m0, 2 + pshufhw m2, m2, 10100100b + PRED4x4_LOWPASS m0, m1, m2, m0 + psrldq m1, m0, 2 + psrldq m2, m0, 4 + pshufhw m1, m1, 10100100b + pshufhw m2, m2, 01010100b + pavgw m4, m0, m1 + PRED4x4_LOWPASS m1, m2, m0, m1 + punpckhwd m5, m4, m1 + punpcklwd m4, m1 + mova [r2+r3*0], m5 + mova [r0+r3*0], m4 + pshufd m0, m5, 11111001b + pshufd m1, m5, 11111110b + pshufd m2, m5, 11111111b + mova [r2+r3*1], m0 + mova [r2+r3*2], m1 + mova [r2+r1*1], m2 + PALIGNR m2, m5, m4, 4, m0 + PALIGNR m3, m5, m4, 8, m1 + PALIGNR m5, m5, m4, 12, m4 + mova [r0+r3*1], m2 + mova [r0+r3*2], m3 + mova [r0+r1*1], m5 + RET +%endmacro + +INIT_XMM sse2 +PRED8x8L_HORIZONTAL_UP +INIT_XMM ssse3 +PRED8x8L_HORIZONTAL_UP +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +PRED8x8L_HORIZONTAL_UP +%endif + + +;----------------------------------------------------------------------------- +; void pred16x16_vertical(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro MOV16 3-5 + mova [%1+ 0], %2 + mova [%1+mmsize], %3 +%if mmsize==8 + mova [%1+ 16], %4 + mova [%1+ 24], %5 +%endif +%endmacro + +%macro PRED16x16_VERTICAL 0 +cglobal pred16x16_vertical_10, 2, 3 + sub r0, r1 + mov r2d, 8 + mova m0, [r0+ 0] + mova m1, [r0+mmsize] +%if mmsize==8 + mova m2, [r0+16] + mova m3, [r0+24] +%endif +.loop: + MOV16 r0+r1*1, m0, m1, m2, m3 + MOV16 r0+r1*2, m0, m1, m2, m3 + lea r0, [r0+r1*2] + dec r2d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_VERTICAL +INIT_XMM sse2 +PRED16x16_VERTICAL + +;----------------------------------------------------------------------------- +; void pred16x16_horizontal(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro PRED16x16_HORIZONTAL 0 +cglobal pred16x16_horizontal_10, 2, 3 + mov r2d, 8 +.vloop: + movd m0, [r0+r1*0-4] + movd m1, [r0+r1*1-4] + SPLATW m0, m0, 1 + SPLATW m1, m1, 1 + MOV16 r0+r1*0, m0, m0, m0, m0 + MOV16 r0+r1*1, m1, m1, m1, m1 + lea r0, [r0+r1*2] + dec r2d + jg .vloop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_HORIZONTAL +INIT_XMM sse2 +PRED16x16_HORIZONTAL + +;----------------------------------------------------------------------------- +; void pred16x16_dc(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro PRED16x16_DC 0 +cglobal pred16x16_dc_10, 2, 6 + mov r5, r0 + sub r0, r1 + mova m0, [r0+0] + paddw m0, [r0+mmsize] +%if mmsize==8 + paddw m0, [r0+16] + paddw m0, [r0+24] +%endif + HADDW m0, m2 + + lea r0, [r0+r1-2] + movzx r3d, word [r0] + movzx r4d, word [r0+r1] +%rep 7 + lea r0, [r0+r1*2] + movzx r2d, word [r0] + add r3d, r2d + movzx r2d, word [r0+r1] + add r4d, r2d +%endrep + lea r3d, [r3+r4+16] + + movd m1, r3d + paddw m0, m1 + psrlw m0, 5 + SPLATW m0, m0 + mov r3d, 8 +.loop: + MOV16 r5+r1*0, m0, m0, m0, m0 + MOV16 r5+r1*1, m0, m0, m0, m0 + lea r5, [r5+r1*2] + dec r3d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_DC +INIT_XMM sse2 +PRED16x16_DC + +;----------------------------------------------------------------------------- +; void pred16x16_top_dc(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro PRED16x16_TOP_DC 0 +cglobal pred16x16_top_dc_10, 2, 3 + sub r0, r1 + mova m0, [r0+0] + paddw m0, [r0+mmsize] +%if mmsize==8 + paddw m0, [r0+16] + paddw m0, [r0+24] +%endif + HADDW m0, m2 + + SPLATW m0, m0 + paddw m0, [pw_8] + psrlw m0, 4 + mov r2d, 8 +.loop: + MOV16 r0+r1*1, m0, m0, m0, m0 + MOV16 r0+r1*2, m0, m0, m0, m0 + lea r0, [r0+r1*2] + dec r2d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_TOP_DC +INIT_XMM sse2 +PRED16x16_TOP_DC + +;----------------------------------------------------------------------------- +; void pred16x16_left_dc(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro PRED16x16_LEFT_DC 0 +cglobal pred16x16_left_dc_10, 2, 6 + mov r5, r0 + + sub r0, 2 + movzx r3d, word [r0] + movzx r4d, word [r0+r1] +%rep 7 + lea r0, [r0+r1*2] + movzx r2d, word [r0] + add r3d, r2d + movzx r2d, word [r0+r1] + add r4d, r2d +%endrep + lea r3d, [r3+r4+8] + shr r3d, 4 + + movd m0, r3d + SPLATW m0, m0 + mov r3d, 8 +.loop: + MOV16 r5+r1*0, m0, m0, m0, m0 + MOV16 r5+r1*1, m0, m0, m0, m0 + lea r5, [r5+r1*2] + dec r3d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_LEFT_DC +INIT_XMM sse2 +PRED16x16_LEFT_DC + +;----------------------------------------------------------------------------- +; void pred16x16_128_dc(pixel *src, int stride) +;----------------------------------------------------------------------------- +%macro PRED16x16_128_DC 0 +cglobal pred16x16_128_dc_10, 2,3 + mova m0, [pw_512] + mov r2d, 8 +.loop: + MOV16 r0+r1*0, m0, m0, m0, m0 + MOV16 r0+r1*1, m0, m0, m0, m0 + lea r0, [r0+r1*2] + dec r2d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PRED16x16_128_DC +INIT_XMM sse2 +PRED16x16_128_DC diff --git a/ffmpeg/libavcodec/x86/h264_intrapred_init.c b/ffmpeg/libavcodec/x86/h264_intrapred_init.c new file mode 100644 index 0000000..f5b5e3e --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_intrapred_init.c @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2010 Jason Garrett-Glaser + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/h264pred.h" + +#define PRED4x4(TYPE, DEPTH, OPT) \ +void ff_pred4x4_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ + const uint8_t *topright, \ + ptrdiff_t stride); + +PRED4x4(dc, 10, mmxext) +PRED4x4(down_left, 10, sse2) +PRED4x4(down_left, 10, avx) +PRED4x4(down_right, 10, sse2) +PRED4x4(down_right, 10, ssse3) +PRED4x4(down_right, 10, avx) +PRED4x4(vertical_left, 10, sse2) +PRED4x4(vertical_left, 10, avx) +PRED4x4(vertical_right, 10, sse2) +PRED4x4(vertical_right, 10, ssse3) +PRED4x4(vertical_right, 10, avx) +PRED4x4(horizontal_up, 10, mmxext) +PRED4x4(horizontal_down, 10, sse2) +PRED4x4(horizontal_down, 10, ssse3) +PRED4x4(horizontal_down, 10, avx) + +#define PRED8x8(TYPE, DEPTH, OPT) \ +void ff_pred8x8_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ + ptrdiff_t stride); + +PRED8x8(dc, 10, mmxext) +PRED8x8(dc, 10, sse2) +PRED8x8(top_dc, 10, sse2) +PRED8x8(plane, 10, sse2) +PRED8x8(vertical, 10, sse2) +PRED8x8(horizontal, 10, sse2) + +#define PRED8x8L(TYPE, DEPTH, OPT)\ +void ff_pred8x8l_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ + int has_topleft, \ + int has_topright, \ + ptrdiff_t stride); + +PRED8x8L(dc, 10, sse2) +PRED8x8L(dc, 10, avx) +PRED8x8L(128_dc, 10, mmxext) +PRED8x8L(128_dc, 10, sse2) +PRED8x8L(top_dc, 10, sse2) +PRED8x8L(top_dc, 10, avx) +PRED8x8L(vertical, 10, sse2) +PRED8x8L(vertical, 10, avx) +PRED8x8L(horizontal, 10, sse2) +PRED8x8L(horizontal, 10, ssse3) +PRED8x8L(horizontal, 10, avx) +PRED8x8L(down_left, 10, sse2) +PRED8x8L(down_left, 10, ssse3) +PRED8x8L(down_left, 10, avx) +PRED8x8L(down_right, 10, sse2) +PRED8x8L(down_right, 10, ssse3) +PRED8x8L(down_right, 10, avx) +PRED8x8L(vertical_right, 10, sse2) +PRED8x8L(vertical_right, 10, ssse3) +PRED8x8L(vertical_right, 10, avx) +PRED8x8L(horizontal_up, 10, sse2) +PRED8x8L(horizontal_up, 10, ssse3) +PRED8x8L(horizontal_up, 10, avx) + +#define PRED16x16(TYPE, DEPTH, OPT)\ +void ff_pred16x16_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ + ptrdiff_t stride); + +PRED16x16(dc, 10, mmxext) +PRED16x16(dc, 10, sse2) +PRED16x16(top_dc, 10, mmxext) +PRED16x16(top_dc, 10, sse2) +PRED16x16(128_dc, 10, mmxext) +PRED16x16(128_dc, 10, sse2) +PRED16x16(left_dc, 10, mmxext) +PRED16x16(left_dc, 10, sse2) +PRED16x16(vertical, 10, mmxext) +PRED16x16(vertical, 10, sse2) +PRED16x16(horizontal, 10, mmxext) +PRED16x16(horizontal, 10, sse2) + +/* 8-bit versions */ +PRED16x16(vertical, 8, mmx) +PRED16x16(vertical, 8, sse) +PRED16x16(horizontal, 8, mmx) +PRED16x16(horizontal, 8, mmxext) +PRED16x16(horizontal, 8, ssse3) +PRED16x16(dc, 8, mmxext) +PRED16x16(dc, 8, sse2) +PRED16x16(dc, 8, ssse3) +PRED16x16(plane_h264, 8, mmx) +PRED16x16(plane_h264, 8, mmxext) +PRED16x16(plane_h264, 8, sse2) +PRED16x16(plane_h264, 8, ssse3) +PRED16x16(plane_rv40, 8, mmx) +PRED16x16(plane_rv40, 8, mmxext) +PRED16x16(plane_rv40, 8, sse2) +PRED16x16(plane_rv40, 8, ssse3) +PRED16x16(plane_svq3, 8, mmx) +PRED16x16(plane_svq3, 8, mmxext) +PRED16x16(plane_svq3, 8, sse2) +PRED16x16(plane_svq3, 8, ssse3) +PRED16x16(tm_vp8, 8, mmx) +PRED16x16(tm_vp8, 8, mmxext) +PRED16x16(tm_vp8, 8, sse2) + +PRED8x8(top_dc, 8, mmxext) +PRED8x8(dc_rv40, 8, mmxext) +PRED8x8(dc, 8, mmxext) +PRED8x8(vertical, 8, mmx) +PRED8x8(horizontal, 8, mmx) +PRED8x8(horizontal, 8, mmxext) +PRED8x8(horizontal, 8, ssse3) +PRED8x8(plane, 8, mmx) +PRED8x8(plane, 8, mmxext) +PRED8x8(plane, 8, sse2) +PRED8x8(plane, 8, ssse3) +PRED8x8(tm_vp8, 8, mmx) +PRED8x8(tm_vp8, 8, mmxext) +PRED8x8(tm_vp8, 8, sse2) +PRED8x8(tm_vp8, 8, ssse3) + +PRED8x8L(top_dc, 8, mmxext) +PRED8x8L(top_dc, 8, ssse3) +PRED8x8L(dc, 8, mmxext) +PRED8x8L(dc, 8, ssse3) +PRED8x8L(horizontal, 8, mmxext) +PRED8x8L(horizontal, 8, ssse3) +PRED8x8L(vertical, 8, mmxext) +PRED8x8L(vertical, 8, ssse3) +PRED8x8L(down_left, 8, mmxext) +PRED8x8L(down_left, 8, sse2) +PRED8x8L(down_left, 8, ssse3) +PRED8x8L(down_right, 8, mmxext) +PRED8x8L(down_right, 8, sse2) +PRED8x8L(down_right, 8, ssse3) +PRED8x8L(vertical_right, 8, mmxext) +PRED8x8L(vertical_right, 8, sse2) +PRED8x8L(vertical_right, 8, ssse3) +PRED8x8L(vertical_left, 8, sse2) +PRED8x8L(vertical_left, 8, ssse3) +PRED8x8L(horizontal_up, 8, mmxext) +PRED8x8L(horizontal_up, 8, ssse3) +PRED8x8L(horizontal_down, 8, mmxext) +PRED8x8L(horizontal_down, 8, sse2) +PRED8x8L(horizontal_down, 8, ssse3) + +PRED4x4(dc, 8, mmxext) +PRED4x4(down_left, 8, mmxext) +PRED4x4(down_right, 8, mmxext) +PRED4x4(vertical_left, 8, mmxext) +PRED4x4(vertical_right, 8, mmxext) +PRED4x4(horizontal_up, 8, mmxext) +PRED4x4(horizontal_down, 8, mmxext) +PRED4x4(tm_vp8, 8, mmx) +PRED4x4(tm_vp8, 8, mmxext) +PRED4x4(tm_vp8, 8, ssse3) +PRED4x4(vertical_vp8, 8, mmxext) + +av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, + const int bit_depth, + const int chroma_format_idc) +{ + int mm_flags = av_get_cpu_flags(); + + if (bit_depth == 8) { + if (EXTERNAL_MMX(mm_flags)) { + h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_8_mmx; + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_mmx; + if (chroma_format_idc == 1) { + h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x8_vertical_8_mmx; + h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmx; + } + if (codec_id == AV_CODEC_ID_VP8) { + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_mmx; + h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_mmx; + h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_mmx; + } else { + if (chroma_format_idc == 1) + h->pred8x8 [PLANE_PRED8x8] = ff_pred8x8_plane_8_mmx; + if (codec_id == AV_CODEC_ID_SVQ3) { + if (mm_flags & AV_CPU_FLAG_CMOV) + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_svq3_8_mmx; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_rv40_8_mmx; + } else { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_h264_8_mmx; + } + } + } + + if (EXTERNAL_MMXEXT(mm_flags)) { + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_mmxext; + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_8_mmxext; + if (chroma_format_idc == 1) + h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmxext; + h->pred8x8l [TOP_DC_PRED ] = ff_pred8x8l_top_dc_8_mmxext; + h->pred8x8l [DC_PRED ] = ff_pred8x8l_dc_8_mmxext; + h->pred8x8l [HOR_PRED ] = ff_pred8x8l_horizontal_8_mmxext; + h->pred8x8l [VERT_PRED ] = ff_pred8x8l_vertical_8_mmxext; + h->pred8x8l [DIAG_DOWN_RIGHT_PRED ] = ff_pred8x8l_down_right_8_mmxext; + h->pred8x8l [VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_8_mmxext; + h->pred8x8l [HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_8_mmxext; + h->pred8x8l [DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_8_mmxext; + h->pred8x8l [HOR_DOWN_PRED ] = ff_pred8x8l_horizontal_down_8_mmxext; + h->pred4x4 [DIAG_DOWN_RIGHT_PRED ] = ff_pred4x4_down_right_8_mmxext; + h->pred4x4 [VERT_RIGHT_PRED ] = ff_pred4x4_vertical_right_8_mmxext; + h->pred4x4 [HOR_DOWN_PRED ] = ff_pred4x4_horizontal_down_8_mmxext; + h->pred4x4 [DC_PRED ] = ff_pred4x4_dc_8_mmxext; + if (codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_H264) { + h->pred4x4 [DIAG_DOWN_LEFT_PRED] = ff_pred4x4_down_left_8_mmxext; + } + if (codec_id == AV_CODEC_ID_SVQ3 || codec_id == AV_CODEC_ID_H264) { + h->pred4x4 [VERT_LEFT_PRED ] = ff_pred4x4_vertical_left_8_mmxext; + } + if (codec_id != AV_CODEC_ID_RV40) { + h->pred4x4 [HOR_UP_PRED ] = ff_pred4x4_horizontal_up_8_mmxext; + } + if (codec_id == AV_CODEC_ID_SVQ3 || codec_id == AV_CODEC_ID_H264) { + if (chroma_format_idc == 1) { + h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_8_mmxext; + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_8_mmxext; + } + } + if (codec_id == AV_CODEC_ID_VP8) { + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_mmxext; + h->pred8x8 [DC_PRED8x8 ] = ff_pred8x8_dc_rv40_8_mmxext; + h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_mmxext; + h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_mmxext; + h->pred4x4 [VERT_PRED ] = ff_pred4x4_vertical_vp8_8_mmxext; + } else { + if (chroma_format_idc == 1) + h->pred8x8 [PLANE_PRED8x8] = ff_pred8x8_plane_8_mmxext; + if (codec_id == AV_CODEC_ID_SVQ3) { + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_svq3_8_mmxext; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_rv40_8_mmxext; + } else { + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_h264_8_mmxext; + } + } + } + + if (EXTERNAL_SSE(mm_flags)) { + h->pred16x16[VERT_PRED8x8] = ff_pred16x16_vertical_8_sse; + } + + if (EXTERNAL_SSE2(mm_flags)) { + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_8_sse2; + h->pred8x8l [DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_8_sse2; + h->pred8x8l [DIAG_DOWN_RIGHT_PRED ] = ff_pred8x8l_down_right_8_sse2; + h->pred8x8l [VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_8_sse2; + h->pred8x8l [VERT_LEFT_PRED ] = ff_pred8x8l_vertical_left_8_sse2; + h->pred8x8l [HOR_DOWN_PRED ] = ff_pred8x8l_horizontal_down_8_sse2; + if (codec_id == AV_CODEC_ID_VP8) { + h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_sse2; + h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_sse2; + } else { + if (chroma_format_idc == 1) + h->pred8x8 [PLANE_PRED8x8] = ff_pred8x8_plane_8_sse2; + if (codec_id == AV_CODEC_ID_SVQ3) { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_svq3_8_sse2; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_rv40_8_sse2; + } else { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_h264_8_sse2; + } + } + } + + if (EXTERNAL_SSSE3(mm_flags)) { + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_ssse3; + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_8_ssse3; + if (chroma_format_idc == 1) + h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_ssse3; + h->pred8x8l [TOP_DC_PRED ] = ff_pred8x8l_top_dc_8_ssse3; + h->pred8x8l [DC_PRED ] = ff_pred8x8l_dc_8_ssse3; + h->pred8x8l [HOR_PRED ] = ff_pred8x8l_horizontal_8_ssse3; + h->pred8x8l [VERT_PRED ] = ff_pred8x8l_vertical_8_ssse3; + h->pred8x8l [DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_8_ssse3; + h->pred8x8l [DIAG_DOWN_RIGHT_PRED ] = ff_pred8x8l_down_right_8_ssse3; + h->pred8x8l [VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_8_ssse3; + h->pred8x8l [VERT_LEFT_PRED ] = ff_pred8x8l_vertical_left_8_ssse3; + h->pred8x8l [HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_8_ssse3; + h->pred8x8l [HOR_DOWN_PRED ] = ff_pred8x8l_horizontal_down_8_ssse3; + if (codec_id == AV_CODEC_ID_VP8) { + h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_ssse3; + h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_ssse3; + } else { + if (chroma_format_idc == 1) + h->pred8x8 [PLANE_PRED8x8] = ff_pred8x8_plane_8_ssse3; + if (codec_id == AV_CODEC_ID_SVQ3) { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_svq3_8_ssse3; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_rv40_8_ssse3; + } else { + h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_h264_8_ssse3; + } + } + } + } else if (bit_depth == 10) { + if (EXTERNAL_MMXEXT(mm_flags)) { + h->pred4x4[DC_PRED ] = ff_pred4x4_dc_10_mmxext; + h->pred4x4[HOR_UP_PRED ] = ff_pred4x4_horizontal_up_10_mmxext; + + if (chroma_format_idc == 1) + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_10_mmxext; + + h->pred8x8l[DC_128_PRED ] = ff_pred8x8l_128_dc_10_mmxext; + + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_10_mmxext; + h->pred16x16[TOP_DC_PRED8x8 ] = ff_pred16x16_top_dc_10_mmxext; + h->pred16x16[DC_128_PRED8x8 ] = ff_pred16x16_128_dc_10_mmxext; + h->pred16x16[LEFT_DC_PRED8x8 ] = ff_pred16x16_left_dc_10_mmxext; + h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_10_mmxext; + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_10_mmxext; + } + if (EXTERNAL_SSE2(mm_flags)) { + h->pred4x4[DIAG_DOWN_LEFT_PRED ] = ff_pred4x4_down_left_10_sse2; + h->pred4x4[DIAG_DOWN_RIGHT_PRED] = ff_pred4x4_down_right_10_sse2; + h->pred4x4[VERT_LEFT_PRED ] = ff_pred4x4_vertical_left_10_sse2; + h->pred4x4[VERT_RIGHT_PRED ] = ff_pred4x4_vertical_right_10_sse2; + h->pred4x4[HOR_DOWN_PRED ] = ff_pred4x4_horizontal_down_10_sse2; + + if (chroma_format_idc == 1) { + h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_10_sse2; + h->pred8x8[TOP_DC_PRED8x8 ] = ff_pred8x8_top_dc_10_sse2; + h->pred8x8[PLANE_PRED8x8 ] = ff_pred8x8_plane_10_sse2; + h->pred8x8[VERT_PRED8x8 ] = ff_pred8x8_vertical_10_sse2; + h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_horizontal_10_sse2; + } + + h->pred8x8l[VERT_PRED ] = ff_pred8x8l_vertical_10_sse2; + h->pred8x8l[HOR_PRED ] = ff_pred8x8l_horizontal_10_sse2; + h->pred8x8l[DC_PRED ] = ff_pred8x8l_dc_10_sse2; + h->pred8x8l[DC_128_PRED ] = ff_pred8x8l_128_dc_10_sse2; + h->pred8x8l[TOP_DC_PRED ] = ff_pred8x8l_top_dc_10_sse2; + h->pred8x8l[DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_10_sse2; + h->pred8x8l[DIAG_DOWN_RIGHT_PRED] = ff_pred8x8l_down_right_10_sse2; + h->pred8x8l[VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_10_sse2; + h->pred8x8l[HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_10_sse2; + + h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_10_sse2; + h->pred16x16[TOP_DC_PRED8x8 ] = ff_pred16x16_top_dc_10_sse2; + h->pred16x16[DC_128_PRED8x8 ] = ff_pred16x16_128_dc_10_sse2; + h->pred16x16[LEFT_DC_PRED8x8 ] = ff_pred16x16_left_dc_10_sse2; + h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_10_sse2; + h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_10_sse2; + } + if (EXTERNAL_SSSE3(mm_flags)) { + h->pred4x4[DIAG_DOWN_RIGHT_PRED] = ff_pred4x4_down_right_10_ssse3; + h->pred4x4[VERT_RIGHT_PRED ] = ff_pred4x4_vertical_right_10_ssse3; + h->pred4x4[HOR_DOWN_PRED ] = ff_pred4x4_horizontal_down_10_ssse3; + + h->pred8x8l[HOR_PRED ] = ff_pred8x8l_horizontal_10_ssse3; + h->pred8x8l[DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_10_ssse3; + h->pred8x8l[DIAG_DOWN_RIGHT_PRED] = ff_pred8x8l_down_right_10_ssse3; + h->pred8x8l[VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_10_ssse3; + h->pred8x8l[HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_10_ssse3; + } + if (EXTERNAL_AVX(mm_flags)) { + h->pred4x4[DIAG_DOWN_LEFT_PRED ] = ff_pred4x4_down_left_10_avx; + h->pred4x4[DIAG_DOWN_RIGHT_PRED] = ff_pred4x4_down_right_10_avx; + h->pred4x4[VERT_LEFT_PRED ] = ff_pred4x4_vertical_left_10_avx; + h->pred4x4[VERT_RIGHT_PRED ] = ff_pred4x4_vertical_right_10_avx; + h->pred4x4[HOR_DOWN_PRED ] = ff_pred4x4_horizontal_down_10_avx; + + h->pred8x8l[VERT_PRED ] = ff_pred8x8l_vertical_10_avx; + h->pred8x8l[HOR_PRED ] = ff_pred8x8l_horizontal_10_avx; + h->pred8x8l[DC_PRED ] = ff_pred8x8l_dc_10_avx; + h->pred8x8l[TOP_DC_PRED ] = ff_pred8x8l_top_dc_10_avx; + h->pred8x8l[DIAG_DOWN_RIGHT_PRED] = ff_pred8x8l_down_right_10_avx; + h->pred8x8l[DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_10_avx; + h->pred8x8l[VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_10_avx; + h->pred8x8l[HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_10_avx; + } + } +} diff --git a/ffmpeg/libavcodec/x86/h264_qpel.c b/ffmpeg/libavcodec/x86/h264_qpel.c new file mode 100644 index 0000000..96dec82 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_qpel.c @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2004-2005 Michael Niedermayer, Loren Merritt + * Copyright (c) 2011 Daniel Kang + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/h264qpel.h" +#include "libavcodec/mpegvideo.h" +#include "dsputil_mmx.h" + +#if HAVE_YASM +void ff_put_pixels4_mmxext(uint8_t *block, const uint8_t *pixels, int line_size, int h); +void ff_avg_pixels4_mmxext(uint8_t *block, const uint8_t *pixels, int line_size, int h); +void ff_put_pixels8_mmxext(uint8_t *block, const uint8_t *pixels, int line_size, int h); +static void ff_put_pixels16_mmxext(uint8_t *block, const uint8_t *pixels, + int line_size, int h) +{ + ff_put_pixels8_mmxext(block, pixels, line_size, h); + ff_put_pixels8_mmxext(block + 8, pixels + 8, line_size, h); +} +static void ff_avg_pixels16_mmxext(uint8_t *block, const uint8_t *pixels, + int line_size, int h) +{ + ff_avg_pixels8_mmxext(block, pixels, line_size, h); + ff_avg_pixels8_mmxext(block + 8, pixels + 8, line_size, h); +} +void ff_put_pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_avg_pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_avg_pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_avg_pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, + int dstStride, int src1Stride, int h); +void ff_put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, + int line_size, int h); +void ff_avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, + int line_size, int h); +#define ff_put_pixels8_l2_sse2 ff_put_pixels8_l2_mmxext +#define ff_avg_pixels8_l2_sse2 ff_avg_pixels8_l2_mmxext +#define ff_put_pixels16_l2_sse2 ff_put_pixels16_l2_mmxext +#define ff_avg_pixels16_l2_sse2 ff_avg_pixels16_l2_mmxext + +#define DEF_QPEL(OPNAME)\ +void ff_ ## OPNAME ## _h264_qpel4_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, int dstStride, int srcStride);\ +void ff_ ## OPNAME ## _h264_qpel8_h_lowpass_mmxext(uint8_t *dst, uint8_t *src, int dstStride, int srcStride);\ +void ff_ ## OPNAME ## _h264_qpel8_h_lowpass_ssse3(uint8_t *dst, uint8_t *src, int dstStride, int srcStride);\ +void ff_ ## OPNAME ## _h264_qpel4_h_lowpass_l2_mmxext(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride);\ +void ff_ ## OPNAME ## _h264_qpel8_h_lowpass_l2_mmxext(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride);\ +void ff_ ## OPNAME ## _h264_qpel8_h_lowpass_l2_ssse3(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride);\ +void ff_ ## OPNAME ## _h264_qpel4_v_lowpass_mmxext(uint8_t *dst, uint8_t *src, int dstStride, int srcStride);\ +void ff_ ## OPNAME ## _h264_qpel8or16_v_lowpass_op_mmxext(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h);\ +void ff_ ## OPNAME ## _h264_qpel8or16_v_lowpass_sse2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h);\ +void ff_ ## OPNAME ## _h264_qpel4_hv_lowpass_v_mmxext(uint8_t *src, int16_t *tmp, int srcStride);\ +void ff_ ## OPNAME ## _h264_qpel4_hv_lowpass_h_mmxext(int16_t *tmp, uint8_t *dst, int dstStride);\ +void ff_ ## OPNAME ## _h264_qpel8or16_hv1_lowpass_op_mmxext(uint8_t *src, int16_t *tmp, int srcStride, int size);\ +void ff_ ## OPNAME ## _h264_qpel8or16_hv1_lowpass_op_sse2(uint8_t *src, int16_t *tmp, int srcStride, int size);\ +void ff_ ## OPNAME ## _h264_qpel8or16_hv2_lowpass_op_mmxext(uint8_t *dst, int16_t *tmp, int dstStride, int unused, int h);\ +void ff_ ## OPNAME ## _h264_qpel8or16_hv2_lowpass_ssse3(uint8_t *dst, int16_t *tmp, int dstStride, int tmpStride, int size);\ +void ff_ ## OPNAME ## _pixels4_l2_shift5_mmxext(uint8_t *dst, int16_t *src16, uint8_t *src8, int dstStride, int src8Stride, int h);\ +void ff_ ## OPNAME ## _pixels8_l2_shift5_mmxext(uint8_t *dst, int16_t *src16, uint8_t *src8, int dstStride, int src8Stride, int h); + +DEF_QPEL(avg) +DEF_QPEL(put) + +#define QPEL_H264(OPNAME, OP, MMX)\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel4_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\ + int w=3;\ + src -= 2*srcStride+2;\ + while(w--){\ + ff_ ## OPNAME ## h264_qpel4_hv_lowpass_v_mmxext(src, tmp, srcStride);\ + tmp += 4;\ + src += 4;\ + }\ + tmp -= 3*4;\ + ff_ ## OPNAME ## h264_qpel4_hv_lowpass_h_mmxext(tmp, dst, dstStride);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\ + src -= 2*srcStride;\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_op_mmxext(dst, src, dstStride, srcStride, h);\ + src += 4;\ + dst += 4;\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_op_mmxext(dst, src, dstStride, srcStride, h);\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv1_lowpass_ ## MMX(int16_t *tmp, uint8_t *src, int tmpStride, int srcStride, int size){\ + int w = (size+8)>>2;\ + src -= 2*srcStride+2;\ + while(w--){\ + ff_ ## OPNAME ## h264_qpel8or16_hv1_lowpass_op_mmxext(src, tmp, srcStride, size);\ + tmp += 4;\ + src += 4;\ + }\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, int dstStride, int tmpStride, int size){\ + int w = size>>4;\ + do{\ + ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_op_mmxext(dst, tmp, dstStride, 0, size);\ + tmp += 8;\ + dst += 8;\ + }while(w--);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 8);\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 16);\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_h_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_h_lowpass_l2_ ## MMX(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride){\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst , src , src2 , dstStride, src2Stride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\ + src += 8*dstStride;\ + dst += 8*dstStride;\ + src2 += 8*src2Stride;\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst , src , src2 , dstStride, src2Stride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride, int size){\ + ff_put_h264_qpel8or16_hv1_lowpass_ ## MMX(tmp, src, tmpStride, srcStride, size);\ + ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_ ## MMX(dst, tmp, dstStride, tmpStride, size);\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst , tmp , src , dstStride, tmpStride, srcStride, 8);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst , tmp , src , dstStride, tmpStride, srcStride, 16);\ +}\ +\ +static av_always_inline void ff_ ## OPNAME ## pixels16_l2_shift5_ ## MMX(uint8_t *dst, int16_t *src16, uint8_t *src8, int dstStride, int src8Stride, int h)\ +{\ + ff_ ## OPNAME ## pixels8_l2_shift5_ ## MMX(dst , src16 , src8 , dstStride, src8Stride, h);\ + ff_ ## OPNAME ## pixels8_l2_shift5_ ## MMX(dst+8, src16+8, src8+8, dstStride, src8Stride, h);\ +}\ + + +#if ARCH_X86_64 +#define QPEL_H264_H16_XMM(OPNAME, OP, MMX)\ + +void ff_avg_h264_qpel16_h_lowpass_l2_ssse3(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride); +void ff_put_h264_qpel16_h_lowpass_l2_ssse3(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride); + +#else // ARCH_X86_64 +#define QPEL_H264_H16_XMM(OPNAME, OP, MMX)\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_h_lowpass_l2_ ## MMX(uint8_t *dst, uint8_t *src, uint8_t *src2, int dstStride, int src2Stride){\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst , src , src2 , dstStride, src2Stride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\ + src += 8*dstStride;\ + dst += 8*dstStride;\ + src2 += 8*src2Stride;\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst , src , src2 , dstStride, src2Stride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\ +} +#endif // ARCH_X86_64 + +#define QPEL_H264_H_XMM(OPNAME, OP, MMX)\ +QPEL_H264_H16_XMM(OPNAME, OP, MMX)\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_h_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\ + src += 8*srcStride;\ + dst += 8*dstStride;\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\ + ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\ +}\ + +#define QPEL_H264_V_XMM(OPNAME, OP, MMX)\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 8);\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 16);\ + ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\ +} + +static av_always_inline void ff_put_h264_qpel8or16_hv1_lowpass_sse2(int16_t *tmp, uint8_t *src, int tmpStride, int srcStride, int size){ + int w = (size+8)>>3; + src -= 2*srcStride+2; + while(w--){ + ff_put_h264_qpel8or16_hv1_lowpass_op_sse2(src, tmp, srcStride, size); + tmp += 8; + src += 8; + } +} + +#define QPEL_H264_HV_XMM(OPNAME, OP, MMX)\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride, int size){\ + ff_put_h264_qpel8or16_hv1_lowpass_sse2(tmp, src, tmpStride, srcStride, size);\ + ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_ ## MMX(dst, tmp, dstStride, tmpStride, size);\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel8_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst, tmp, src, dstStride, tmpStride, srcStride, 8);\ +}\ +static av_always_inline void ff_ ## OPNAME ## h264_qpel16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, uint8_t *src, int dstStride, int tmpStride, int srcStride){\ + ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst, tmp, src, dstStride, tmpStride, srcStride, 16);\ +}\ + +#define ff_put_h264_qpel8_h_lowpass_l2_sse2 ff_put_h264_qpel8_h_lowpass_l2_mmxext +#define ff_avg_h264_qpel8_h_lowpass_l2_sse2 ff_avg_h264_qpel8_h_lowpass_l2_mmxext +#define ff_put_h264_qpel16_h_lowpass_l2_sse2 ff_put_h264_qpel16_h_lowpass_l2_mmxext +#define ff_avg_h264_qpel16_h_lowpass_l2_sse2 ff_avg_h264_qpel16_h_lowpass_l2_mmxext + +#define ff_put_h264_qpel8_v_lowpass_ssse3 ff_put_h264_qpel8_v_lowpass_sse2 +#define ff_avg_h264_qpel8_v_lowpass_ssse3 ff_avg_h264_qpel8_v_lowpass_sse2 +#define ff_put_h264_qpel16_v_lowpass_ssse3 ff_put_h264_qpel16_v_lowpass_sse2 +#define ff_avg_h264_qpel16_v_lowpass_ssse3 ff_avg_h264_qpel16_v_lowpass_sse2 + +#define ff_put_h264_qpel8or16_hv2_lowpass_sse2 ff_put_h264_qpel8or16_hv2_lowpass_mmxext +#define ff_avg_h264_qpel8or16_hv2_lowpass_sse2 ff_avg_h264_qpel8or16_hv2_lowpass_mmxext + +#define H264_MC(OPNAME, SIZE, MMX, ALIGN) \ +H264_MC_C(OPNAME, SIZE, MMX, ALIGN)\ +H264_MC_V(OPNAME, SIZE, MMX, ALIGN)\ +H264_MC_H(OPNAME, SIZE, MMX, ALIGN)\ +H264_MC_HV(OPNAME, SIZE, MMX, ALIGN)\ + +static void put_h264_qpel16_mc00_sse2 (uint8_t *dst, uint8_t *src, + ptrdiff_t stride) +{ + ff_put_pixels16_sse2(dst, src, stride, 16); +} +static void avg_h264_qpel16_mc00_sse2 (uint8_t *dst, uint8_t *src, + ptrdiff_t stride) +{ + ff_avg_pixels16_sse2(dst, src, stride, 16); +} +#define put_h264_qpel8_mc00_sse2 put_h264_qpel8_mc00_mmxext +#define avg_h264_qpel8_mc00_sse2 avg_h264_qpel8_mc00_mmxext + +#define H264_MC_C(OPNAME, SIZE, MMX, ALIGN) \ +static void OPNAME ## h264_qpel ## SIZE ## _mc00_ ## MMX (uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + ff_ ## OPNAME ## pixels ## SIZE ## _ ## MMX(dst, src, stride, SIZE);\ +}\ + +#define H264_MC_H(OPNAME, SIZE, MMX, ALIGN) \ +static void OPNAME ## h264_qpel ## SIZE ## _mc10_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, src, stride, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc20_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_ ## MMX(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc30_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, src+1, stride, stride);\ +}\ + +#define H264_MC_V(OPNAME, SIZE, MMX, ALIGN) \ +static void OPNAME ## h264_qpel ## SIZE ## _mc01_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*SIZE];\ + ff_put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(temp, src, SIZE, stride);\ + ff_ ## OPNAME ## pixels ## SIZE ## _l2_ ## MMX(dst, src, temp, stride, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc02_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _v_lowpass_ ## MMX(dst, src, stride, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc03_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*SIZE];\ + ff_put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(temp, src, SIZE, stride);\ + ff_ ## OPNAME ## pixels ## SIZE ## _l2_ ## MMX(dst, src+stride, temp, stride, stride, SIZE);\ +}\ + +#define H264_MC_HV(OPNAME, SIZE, MMX, ALIGN) \ +static void OPNAME ## h264_qpel ## SIZE ## _mc11_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*SIZE];\ + ff_put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(temp, src, SIZE, stride);\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, temp, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc31_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*SIZE];\ + ff_put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(temp, src+1, SIZE, stride);\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, temp, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc13_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*SIZE];\ + ff_put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(temp, src, SIZE, stride);\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, temp, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc33_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*SIZE];\ + ff_put_h264_qpel ## SIZE ## _v_lowpass_ ## MMX(temp, src+1, SIZE, stride);\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, temp, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc22_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint16_t, temp)[SIZE*(SIZE<8?12:24)];\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(dst, temp, src, stride, SIZE, stride);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc21_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE];\ + uint8_t * const halfHV= temp;\ + int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ + assert(((int)temp & 7) == 0);\ + ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, halfHV, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc23_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE];\ + uint8_t * const halfHV= temp;\ + int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ + assert(((int)temp & 7) == 0);\ + ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ + ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, halfHV, stride, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc12_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE];\ + uint8_t * const halfHV= temp;\ + int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ + assert(((int)temp & 7) == 0);\ + ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ + ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+2, halfHV, stride, SIZE, SIZE);\ +}\ +\ +static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\ +{\ + DECLARE_ALIGNED(ALIGN, uint8_t, temp)[SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE];\ + uint8_t * const halfHV= temp;\ + int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ + assert(((int)temp & 7) == 0);\ + ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ + ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+3, halfHV, stride, SIZE, SIZE);\ +}\ + +#define H264_MC_4816(MMX)\ +H264_MC(put_, 4, MMX, 8)\ +H264_MC(put_, 8, MMX, 8)\ +H264_MC(put_, 16,MMX, 8)\ +H264_MC(avg_, 4, MMX, 8)\ +H264_MC(avg_, 8, MMX, 8)\ +H264_MC(avg_, 16,MMX, 8)\ + +#define H264_MC_816(QPEL, XMM)\ +QPEL(put_, 8, XMM, 16)\ +QPEL(put_, 16,XMM, 16)\ +QPEL(avg_, 8, XMM, 16)\ +QPEL(avg_, 16,XMM, 16)\ + +#undef PAVGB +#define PAVGB "pavgb" +QPEL_H264(put_, PUT_OP, mmxext) +QPEL_H264(avg_, AVG_MMXEXT_OP, mmxext) +QPEL_H264_V_XMM(put_, PUT_OP, sse2) +QPEL_H264_V_XMM(avg_,AVG_MMXEXT_OP, sse2) +QPEL_H264_HV_XMM(put_, PUT_OP, sse2) +QPEL_H264_HV_XMM(avg_,AVG_MMXEXT_OP, sse2) +QPEL_H264_H_XMM(put_, PUT_OP, ssse3) +QPEL_H264_H_XMM(avg_,AVG_MMXEXT_OP, ssse3) +QPEL_H264_HV_XMM(put_, PUT_OP, ssse3) +QPEL_H264_HV_XMM(avg_,AVG_MMXEXT_OP, ssse3) +#undef PAVGB + +H264_MC_4816(mmxext) +H264_MC_816(H264_MC_V, sse2) +H264_MC_816(H264_MC_HV, sse2) +H264_MC_816(H264_MC_H, ssse3) +H264_MC_816(H264_MC_HV, ssse3) + + +//10bit +#define LUMA_MC_OP(OP, NUM, DEPTH, TYPE, OPT) \ +void ff_ ## OP ## _h264_qpel ## NUM ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT \ + (uint8_t *dst, uint8_t *src, ptrdiff_t stride); + +#define LUMA_MC_ALL(DEPTH, TYPE, OPT) \ + LUMA_MC_OP(put, 4, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(avg, 4, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(put, 8, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(avg, 8, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(put, 16, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(avg, 16, DEPTH, TYPE, OPT) + +#define LUMA_MC_816(DEPTH, TYPE, OPT) \ + LUMA_MC_OP(put, 8, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(avg, 8, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(put, 16, DEPTH, TYPE, OPT) \ + LUMA_MC_OP(avg, 16, DEPTH, TYPE, OPT) + +LUMA_MC_ALL(10, mc00, mmxext) +LUMA_MC_ALL(10, mc10, mmxext) +LUMA_MC_ALL(10, mc20, mmxext) +LUMA_MC_ALL(10, mc30, mmxext) +LUMA_MC_ALL(10, mc01, mmxext) +LUMA_MC_ALL(10, mc11, mmxext) +LUMA_MC_ALL(10, mc21, mmxext) +LUMA_MC_ALL(10, mc31, mmxext) +LUMA_MC_ALL(10, mc02, mmxext) +LUMA_MC_ALL(10, mc12, mmxext) +LUMA_MC_ALL(10, mc22, mmxext) +LUMA_MC_ALL(10, mc32, mmxext) +LUMA_MC_ALL(10, mc03, mmxext) +LUMA_MC_ALL(10, mc13, mmxext) +LUMA_MC_ALL(10, mc23, mmxext) +LUMA_MC_ALL(10, mc33, mmxext) + +LUMA_MC_816(10, mc00, sse2) +LUMA_MC_816(10, mc10, sse2) +LUMA_MC_816(10, mc10, sse2_cache64) +LUMA_MC_816(10, mc10, ssse3_cache64) +LUMA_MC_816(10, mc20, sse2) +LUMA_MC_816(10, mc20, sse2_cache64) +LUMA_MC_816(10, mc20, ssse3_cache64) +LUMA_MC_816(10, mc30, sse2) +LUMA_MC_816(10, mc30, sse2_cache64) +LUMA_MC_816(10, mc30, ssse3_cache64) +LUMA_MC_816(10, mc01, sse2) +LUMA_MC_816(10, mc11, sse2) +LUMA_MC_816(10, mc21, sse2) +LUMA_MC_816(10, mc31, sse2) +LUMA_MC_816(10, mc02, sse2) +LUMA_MC_816(10, mc12, sse2) +LUMA_MC_816(10, mc22, sse2) +LUMA_MC_816(10, mc32, sse2) +LUMA_MC_816(10, mc03, sse2) +LUMA_MC_816(10, mc13, sse2) +LUMA_MC_816(10, mc23, sse2) +LUMA_MC_816(10, mc33, sse2) + +#define QPEL16_OPMC(OP, MC, MMX)\ +void ff_ ## OP ## _h264_qpel16_ ## MC ## _10_ ## MMX(uint8_t *dst, uint8_t *src, ptrdiff_t stride){\ + ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst , src , stride);\ + ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst+16, src+16, stride);\ + src += 8*stride;\ + dst += 8*stride;\ + ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst , src , stride);\ + ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst+16, src+16, stride);\ +} + +#define QPEL16_OP(MC, MMX)\ +QPEL16_OPMC(put, MC, MMX)\ +QPEL16_OPMC(avg, MC, MMX) + +#define QPEL16(MMX)\ +QPEL16_OP(mc00, MMX)\ +QPEL16_OP(mc01, MMX)\ +QPEL16_OP(mc02, MMX)\ +QPEL16_OP(mc03, MMX)\ +QPEL16_OP(mc10, MMX)\ +QPEL16_OP(mc11, MMX)\ +QPEL16_OP(mc12, MMX)\ +QPEL16_OP(mc13, MMX)\ +QPEL16_OP(mc20, MMX)\ +QPEL16_OP(mc21, MMX)\ +QPEL16_OP(mc22, MMX)\ +QPEL16_OP(mc23, MMX)\ +QPEL16_OP(mc30, MMX)\ +QPEL16_OP(mc31, MMX)\ +QPEL16_OP(mc32, MMX)\ +QPEL16_OP(mc33, MMX) + +#if ARCH_X86_32 && HAVE_YASM && CONFIG_H264QPEL // ARCH_X86_64 implies SSE2+ +QPEL16(mmxext) +#endif + +#endif /* HAVE_YASM */ + +#define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ + do { \ + c->PFX ## _pixels_tab[IDX][ 0] = PREFIX ## PFX ## SIZE ## _mc00_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 1] = PREFIX ## PFX ## SIZE ## _mc10_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 2] = PREFIX ## PFX ## SIZE ## _mc20_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 3] = PREFIX ## PFX ## SIZE ## _mc30_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 4] = PREFIX ## PFX ## SIZE ## _mc01_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 5] = PREFIX ## PFX ## SIZE ## _mc11_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 6] = PREFIX ## PFX ## SIZE ## _mc21_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 7] = PREFIX ## PFX ## SIZE ## _mc31_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 8] = PREFIX ## PFX ## SIZE ## _mc02_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][ 9] = PREFIX ## PFX ## SIZE ## _mc12_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][10] = PREFIX ## PFX ## SIZE ## _mc22_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][11] = PREFIX ## PFX ## SIZE ## _mc32_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][12] = PREFIX ## PFX ## SIZE ## _mc03_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][13] = PREFIX ## PFX ## SIZE ## _mc13_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][14] = PREFIX ## PFX ## SIZE ## _mc23_ ## CPU; \ + c->PFX ## _pixels_tab[IDX][15] = PREFIX ## PFX ## SIZE ## _mc33_ ## CPU; \ + } while (0) + +#define H264_QPEL_FUNCS(x, y, CPU) \ + do { \ + c->put_h264_qpel_pixels_tab[0][x + y * 4] = put_h264_qpel16_mc ## x ## y ## _ ## CPU; \ + c->put_h264_qpel_pixels_tab[1][x + y * 4] = put_h264_qpel8_mc ## x ## y ## _ ## CPU; \ + c->avg_h264_qpel_pixels_tab[0][x + y * 4] = avg_h264_qpel16_mc ## x ## y ## _ ## CPU; \ + c->avg_h264_qpel_pixels_tab[1][x + y * 4] = avg_h264_qpel8_mc ## x ## y ## _ ## CPU; \ + } while (0) + +#define H264_QPEL_FUNCS_10(x, y, CPU) \ + do { \ + c->put_h264_qpel_pixels_tab[0][x + y * 4] = ff_put_h264_qpel16_mc ## x ## y ## _10_ ## CPU; \ + c->put_h264_qpel_pixels_tab[1][x + y * 4] = ff_put_h264_qpel8_mc ## x ## y ## _10_ ## CPU; \ + c->avg_h264_qpel_pixels_tab[0][x + y * 4] = ff_avg_h264_qpel16_mc ## x ## y ## _10_ ## CPU; \ + c->avg_h264_qpel_pixels_tab[1][x + y * 4] = ff_avg_h264_qpel8_mc ## x ## y ## _10_ ## CPU; \ + } while (0) + +av_cold void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth) +{ +#if HAVE_YASM + int high_bit_depth = bit_depth > 8; + int mm_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMXEXT(mm_flags)) { + if (!high_bit_depth) { + SET_QPEL_FUNCS(put_h264_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(put_h264_qpel, 1, 8, mmxext, ); + SET_QPEL_FUNCS(put_h264_qpel, 2, 4, mmxext, ); + SET_QPEL_FUNCS(avg_h264_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS(avg_h264_qpel, 1, 8, mmxext, ); + SET_QPEL_FUNCS(avg_h264_qpel, 2, 4, mmxext, ); + } else if (bit_depth == 10) { +#if ARCH_X86_32 + SET_QPEL_FUNCS(avg_h264_qpel, 0, 16, 10_mmxext, ff_); + SET_QPEL_FUNCS(put_h264_qpel, 0, 16, 10_mmxext, ff_); + SET_QPEL_FUNCS(put_h264_qpel, 1, 8, 10_mmxext, ff_); + SET_QPEL_FUNCS(avg_h264_qpel, 1, 8, 10_mmxext, ff_); +#endif + SET_QPEL_FUNCS(put_h264_qpel, 2, 4, 10_mmxext, ff_); + SET_QPEL_FUNCS(avg_h264_qpel, 2, 4, 10_mmxext, ff_); + } + } + + if (EXTERNAL_SSE2(mm_flags)) { + if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW) && !high_bit_depth) { + // these functions are slower than mmx on AMD, but faster on Intel + H264_QPEL_FUNCS(0, 0, sse2); + } + + if (!high_bit_depth) { + H264_QPEL_FUNCS(0, 1, sse2); + H264_QPEL_FUNCS(0, 2, sse2); + H264_QPEL_FUNCS(0, 3, sse2); + H264_QPEL_FUNCS(1, 1, sse2); + H264_QPEL_FUNCS(1, 2, sse2); + H264_QPEL_FUNCS(1, 3, sse2); + H264_QPEL_FUNCS(2, 1, sse2); + H264_QPEL_FUNCS(2, 2, sse2); + H264_QPEL_FUNCS(2, 3, sse2); + H264_QPEL_FUNCS(3, 1, sse2); + H264_QPEL_FUNCS(3, 2, sse2); + H264_QPEL_FUNCS(3, 3, sse2); + } + + if (bit_depth == 10) { + SET_QPEL_FUNCS(put_h264_qpel, 0, 16, 10_sse2, ff_); + SET_QPEL_FUNCS(put_h264_qpel, 1, 8, 10_sse2, ff_); + SET_QPEL_FUNCS(avg_h264_qpel, 0, 16, 10_sse2, ff_); + SET_QPEL_FUNCS(avg_h264_qpel, 1, 8, 10_sse2, ff_); + H264_QPEL_FUNCS_10(1, 0, sse2_cache64); + H264_QPEL_FUNCS_10(2, 0, sse2_cache64); + H264_QPEL_FUNCS_10(3, 0, sse2_cache64); + } + } + + if (EXTERNAL_SSSE3(mm_flags)) { + if (!high_bit_depth) { + H264_QPEL_FUNCS(1, 0, ssse3); + H264_QPEL_FUNCS(1, 1, ssse3); + H264_QPEL_FUNCS(1, 2, ssse3); + H264_QPEL_FUNCS(1, 3, ssse3); + H264_QPEL_FUNCS(2, 0, ssse3); + H264_QPEL_FUNCS(2, 1, ssse3); + H264_QPEL_FUNCS(2, 2, ssse3); + H264_QPEL_FUNCS(2, 3, ssse3); + H264_QPEL_FUNCS(3, 0, ssse3); + H264_QPEL_FUNCS(3, 1, ssse3); + H264_QPEL_FUNCS(3, 2, ssse3); + H264_QPEL_FUNCS(3, 3, ssse3); + } + + if (bit_depth == 10) { + H264_QPEL_FUNCS_10(1, 0, ssse3_cache64); + H264_QPEL_FUNCS_10(2, 0, ssse3_cache64); + H264_QPEL_FUNCS_10(3, 0, ssse3_cache64); + } + } + + if (EXTERNAL_AVX(mm_flags)) { + /* AVX implies 64 byte cache lines without the need to avoid unaligned + * memory accesses that cross the boundary between two cache lines. + * TODO: Port X264_CPU_CACHELINE_32/64 detection from x264 to avoid + * having to treat SSE2 functions with such properties as AVX. */ + if (bit_depth == 10) { + H264_QPEL_FUNCS_10(1, 0, sse2); + H264_QPEL_FUNCS_10(2, 0, sse2); + H264_QPEL_FUNCS_10(3, 0, sse2); + } + } +#endif +} diff --git a/ffmpeg/libavcodec/x86/h264_qpel_10bit.asm b/ffmpeg/libavcodec/x86/h264_qpel_10bit.asm new file mode 100644 index 0000000..e14df84 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_qpel_10bit.asm @@ -0,0 +1,884 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 qpel code +;***************************************************************************** +;* Copyright (C) 2011 x264 project +;* +;* Authors: Daniel Kang +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +cextern pw_16 +cextern pw_1 +cextern pb_0 + +pw_pixel_max: times 8 dw ((1 << 10)-1) + +pad10: times 8 dw 10*1023 +pad20: times 8 dw 20*1023 +pad30: times 8 dw 30*1023 +depad: times 4 dd 32*20*1023 + 512 +depad2: times 8 dw 20*1023 + 16*1022 + 16 +unpad: times 8 dw 16*1022/32 ; needs to be mod 16 + +tap1: times 4 dw 1, -5 +tap2: times 4 dw 20, 20 +tap3: times 4 dw -5, 1 +pd_0f: times 4 dd 0xffff + +SECTION .text + + +%macro AVG_MOV 2 + pavgw %2, %1 + mova %1, %2 +%endmacro + +%macro ADDW 3 +%if mmsize == 8 + paddw %1, %2 +%else + movu %3, %2 + paddw %1, %3 +%endif +%endmacro + +%macro FILT_H 4 + paddw %1, %4 + psubw %1, %2 ; a-b + psraw %1, 2 ; (a-b)/4 + psubw %1, %2 ; (a-b)/4-b + paddw %1, %3 ; (a-b)/4-b+c + psraw %1, 2 ; ((a-b)/4-b+c)/4 + paddw %1, %3 ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16 +%endmacro + +%macro PRELOAD_V 0 + lea r3, [r2*3] + sub r1, r3 + movu m0, [r1+r2] + movu m1, [r1+r2*2] + add r1, r3 + movu m2, [r1] + movu m3, [r1+r2] + movu m4, [r1+r2*2] + add r1, r3 +%endmacro + +%macro FILT_V 8 + movu %6, [r1] + paddw %1, %6 + mova %7, %2 + paddw %7, %5 + mova %8, %3 + paddw %8, %4 + FILT_H %1, %7, %8, [pw_16] + psraw %1, 1 + CLIPW %1, [pb_0], [pw_pixel_max] +%endmacro + +%macro MC 1 +%define OP_MOV mova +INIT_MMX mmxext +%1 put, 4 +INIT_XMM sse2 +%1 put, 8 + +%define OP_MOV AVG_MOV +INIT_MMX mmxext +%1 avg, 4 +INIT_XMM sse2 +%1 avg, 8 +%endmacro + +%macro MCAxA_OP 7 +%if ARCH_X86_32 +cglobal %1_h264_qpel%4_%2_10, %5,%6,%7 + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + mov r0, r0m + mov r1, r1m + add r0, %3*2 + add r1, %3*2 + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + mov r0, r0m + mov r1, r1m + lea r0, [r0+r2*%3] + lea r1, [r1+r2*%3] + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + mov r0, r0m + mov r1, r1m + lea r0, [r0+r2*%3+%3*2] + lea r1, [r1+r2*%3+%3*2] + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + RET +%else ; ARCH_X86_64 +cglobal %1_h264_qpel%4_%2_10, %5,%6 + 2,%7 + mov r%6, r0 +%assign p1 %6+1 + mov r %+ p1, r1 + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + lea r0, [r%6+%3*2] + lea r1, [r %+ p1+%3*2] + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + lea r0, [r%6+r2*%3] + lea r1, [r %+ p1+r2*%3] + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + lea r0, [r%6+r2*%3+%3*2] + lea r1, [r %+ p1+r2*%3+%3*2] +%if UNIX64 == 0 ; fall through to function + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + RET +%endif +%endif +%endmacro + +;cpu, put/avg, mc, 4/8, ... +%macro cglobal_mc 6 +%assign i %3*2 +%if ARCH_X86_32 || cpuflag(sse2) +MCAxA_OP %1, %2, %3, i, %4,%5,%6 +%endif + +cglobal %1_h264_qpel%3_%2_10, %4,%5,%6 +%if UNIX64 == 0 ; no prologue or epilogue for UNIX64 + call stub_%1_h264_qpel%3_%2_10 %+ SUFFIX + RET +%endif + +stub_%1_h264_qpel%3_%2_10 %+ SUFFIX: +%endmacro + +;----------------------------------------------------------------------------- +; void h264_qpel_mc00(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro COPY4 0 + movu m0, [r1 ] + OP_MOV [r0 ], m0 + movu m0, [r1+r2 ] + OP_MOV [r0+r2 ], m0 + movu m0, [r1+r2*2] + OP_MOV [r0+r2*2], m0 + movu m0, [r1+r3 ] + OP_MOV [r0+r3 ], m0 +%endmacro + +%macro MC00 1 +INIT_MMX mmxext +cglobal_mc %1, mc00, 4, 3,4,0 + lea r3, [r2*3] + COPY4 + ret + +INIT_XMM sse2 +cglobal %1_h264_qpel8_mc00_10, 3,4 + lea r3, [r2*3] + COPY4 + lea r0, [r0+r2*4] + lea r1, [r1+r2*4] + COPY4 + RET + +cglobal %1_h264_qpel16_mc00_10, 3,4 + mov r3d, 8 +.loop: + movu m0, [r1 ] + movu m1, [r1 +16] + OP_MOV [r0 ], m0 + OP_MOV [r0 +16], m1 + movu m0, [r1+r2 ] + movu m1, [r1+r2+16] + OP_MOV [r0+r2 ], m0 + OP_MOV [r0+r2+16], m1 + lea r0, [r0+r2*2] + lea r1, [r1+r2*2] + dec r3d + jg .loop + REP_RET +%endmacro + +%define OP_MOV mova +MC00 put + +%define OP_MOV AVG_MOV +MC00 avg + +;----------------------------------------------------------------------------- +; void h264_qpel_mc20(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC_CACHE 1 +%define OP_MOV mova +INIT_MMX mmxext +%1 put, 4 +INIT_XMM sse2, cache64 +%1 put, 8 +INIT_XMM ssse3, cache64 +%1 put, 8 +INIT_XMM sse2 +%1 put, 8 + +%define OP_MOV AVG_MOV +INIT_MMX mmxext +%1 avg, 4 +INIT_XMM sse2, cache64 +%1 avg, 8 +INIT_XMM ssse3, cache64 +%1 avg, 8 +INIT_XMM sse2 +%1 avg, 8 +%endmacro + +%macro MC20 2 +cglobal_mc %1, mc20, %2, 3,4,9 + mov r3d, %2 + mova m1, [pw_pixel_max] +%if num_mmregs > 8 + mova m8, [pw_16] + %define p16 m8 +%else + %define p16 [pw_16] +%endif +.nextrow: +%if %0 == 4 + movu m2, [r1-4] + movu m3, [r1-2] + movu m4, [r1+0] + ADDW m2, [r1+6], m5 + ADDW m3, [r1+4], m5 + ADDW m4, [r1+2], m5 +%else ; movu is slow on these processors +%if mmsize==16 + movu m2, [r1-4] + movu m0, [r1+6] + mova m6, m0 + psrldq m0, 6 + + paddw m6, m2 + PALIGNR m3, m0, m2, 2, m5 + PALIGNR m7, m0, m2, 8, m5 + paddw m3, m7 + PALIGNR m4, m0, m2, 4, m5 + PALIGNR m7, m0, m2, 6, m5 + paddw m4, m7 + SWAP 2, 6 +%else + movu m2, [r1-4] + movu m6, [r1+4] + PALIGNR m3, m6, m2, 2, m5 + paddw m3, m6 + PALIGNR m4, m6, m2, 4, m5 + PALIGNR m7, m6, m2, 6, m5 + paddw m4, m7 + paddw m2, [r1+6] +%endif +%endif + + FILT_H m2, m3, m4, p16 + psraw m2, 1 + pxor m0, m0 + CLIPW m2, m0, m1 + OP_MOV [r0], m2 + add r0, r2 + add r1, r2 + dec r3d + jg .nextrow + rep ret +%endmacro + +MC_CACHE MC20 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc30(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC30 2 +cglobal_mc %1, mc30, %2, 3,5,9 + lea r4, [r1+2] + jmp stub_%1_h264_qpel%2_mc10_10 %+ SUFFIX %+ .body +%endmacro + +MC_CACHE MC30 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc10(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC10 2 +cglobal_mc %1, mc10, %2, 3,5,9 + mov r4, r1 +.body: + mov r3d, %2 + mova m1, [pw_pixel_max] +%if num_mmregs > 8 + mova m8, [pw_16] + %define p16 m8 +%else + %define p16 [pw_16] +%endif +.nextrow: +%if %0 == 4 + movu m2, [r1-4] + movu m3, [r1-2] + movu m4, [r1+0] + ADDW m2, [r1+6], m5 + ADDW m3, [r1+4], m5 + ADDW m4, [r1+2], m5 +%else ; movu is slow on these processors +%if mmsize==16 + movu m2, [r1-4] + movu m0, [r1+6] + mova m6, m0 + psrldq m0, 6 + + paddw m6, m2 + PALIGNR m3, m0, m2, 2, m5 + PALIGNR m7, m0, m2, 8, m5 + paddw m3, m7 + PALIGNR m4, m0, m2, 4, m5 + PALIGNR m7, m0, m2, 6, m5 + paddw m4, m7 + SWAP 2, 6 +%else + movu m2, [r1-4] + movu m6, [r1+4] + PALIGNR m3, m6, m2, 2, m5 + paddw m3, m6 + PALIGNR m4, m6, m2, 4, m5 + PALIGNR m7, m6, m2, 6, m5 + paddw m4, m7 + paddw m2, [r1+6] +%endif +%endif + + FILT_H m2, m3, m4, p16 + psraw m2, 1 + pxor m0, m0 + CLIPW m2, m0, m1 + movu m3, [r4] + pavgw m2, m3 + OP_MOV [r0], m2 + add r0, r2 + add r1, r2 + add r4, r2 + dec r3d + jg .nextrow + rep ret +%endmacro + +MC_CACHE MC10 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc02(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro V_FILT 10 +v_filt%9_%10_10 + add r4, r2 +.no_addr4: + FILT_V m0, m1, m2, m3, m4, m5, m6, m7 + add r1, r2 + add r0, r2 + ret +%endmacro + +INIT_MMX mmxext +RESET_MM_PERMUTATION +%assign i 0 +%rep 4 +V_FILT m0, m1, m2, m3, m4, m5, m6, m7, 4, i +SWAP 0,1,2,3,4,5 +%assign i i+1 +%endrep + +INIT_XMM sse2 +RESET_MM_PERMUTATION +%assign i 0 +%rep 6 +V_FILT m0, m1, m2, m3, m4, m5, m6, m7, 8, i +SWAP 0,1,2,3,4,5 +%assign i i+1 +%endrep + +%macro MC02 2 +cglobal_mc %1, mc02, %2, 3,4,8 + PRELOAD_V + + sub r0, r2 +%assign j 0 +%rep %2 + %assign i (j % 6) + call v_filt%2_ %+ i %+ _10.no_addr4 + OP_MOV [r0], m0 + SWAP 0,1,2,3,4,5 + %assign j j+1 +%endrep + ret +%endmacro + +MC MC02 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc01(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC01 2 +cglobal_mc %1, mc01, %2, 3,5,8 + mov r4, r1 +.body: + PRELOAD_V + + sub r4, r2 + sub r0, r2 +%assign j 0 +%rep %2 + %assign i (j % 6) + call v_filt%2_ %+ i %+ _10 + movu m7, [r4] + pavgw m0, m7 + OP_MOV [r0], m0 + SWAP 0,1,2,3,4,5 + %assign j j+1 +%endrep + ret +%endmacro + +MC MC01 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc03(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC03 2 +cglobal_mc %1, mc03, %2, 3,5,8 + lea r4, [r1+r2] + jmp stub_%1_h264_qpel%2_mc01_10 %+ SUFFIX %+ .body +%endmacro + +MC MC03 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc11(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro H_FILT_AVG 2-3 +h_filt%1_%2_10: +;FILT_H with fewer registers and averaged with the FILT_V result +;m6,m7 are tmp registers, m0 is the FILT_V result, the rest are to be used next in the next iteration +;unfortunately I need three registers, so m5 will have to be re-read from memory + movu m5, [r4-4] + ADDW m5, [r4+6], m7 + movu m6, [r4-2] + ADDW m6, [r4+4], m7 + paddw m5, [pw_16] + psubw m5, m6 ; a-b + psraw m5, 2 ; (a-b)/4 + psubw m5, m6 ; (a-b)/4-b + movu m6, [r4+0] + ADDW m6, [r4+2], m7 + paddw m5, m6 ; (a-b)/4-b+c + psraw m5, 2 ; ((a-b)/4-b+c)/4 + paddw m5, m6 ; ((a-b)/4-b+c)/4+c = (a-5*b+20*c)/16 + psraw m5, 1 + CLIPW m5, [pb_0], [pw_pixel_max] +;avg FILT_V, FILT_H + pavgw m0, m5 +%if %0!=4 + movu m5, [r1+r5] +%endif + ret +%endmacro + +INIT_MMX mmxext +RESET_MM_PERMUTATION +%assign i 0 +%rep 3 +H_FILT_AVG 4, i +SWAP 0,1,2,3,4,5 +%assign i i+1 +%endrep +H_FILT_AVG 4, i, 0 + +INIT_XMM sse2 +RESET_MM_PERMUTATION +%assign i 0 +%rep 6 +%if i==1 +H_FILT_AVG 8, i, 0 +%else +H_FILT_AVG 8, i +%endif +SWAP 0,1,2,3,4,5 +%assign i i+1 +%endrep + +%macro MC11 2 +; this REALLY needs x86_64 +cglobal_mc %1, mc11, %2, 3,6,8 + mov r4, r1 +.body: + PRELOAD_V + + sub r0, r2 + sub r4, r2 + mov r5, r2 + neg r5 +%assign j 0 +%rep %2 + %assign i (j % 6) + call v_filt%2_ %+ i %+ _10 + call h_filt%2_ %+ i %+ _10 +%if %2==8 && i==1 + movu m5, [r1+r5] +%endif + OP_MOV [r0], m0 + SWAP 0,1,2,3,4,5 + %assign j j+1 +%endrep + ret +%endmacro + +MC MC11 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc31(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC31 2 +cglobal_mc %1, mc31, %2, 3,6,8 + mov r4, r1 + add r1, 2 + jmp stub_%1_h264_qpel%2_mc11_10 %+ SUFFIX %+ .body +%endmacro + +MC MC31 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc13(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC13 2 +cglobal_mc %1, mc13, %2, 3,7,12 + lea r4, [r1+r2] + jmp stub_%1_h264_qpel%2_mc11_10 %+ SUFFIX %+ .body +%endmacro + +MC MC13 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc33(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC33 2 +cglobal_mc %1, mc33, %2, 3,6,8 + lea r4, [r1+r2] + add r1, 2 + jmp stub_%1_h264_qpel%2_mc11_10 %+ SUFFIX %+ .body +%endmacro + +MC MC33 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc22(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro FILT_H2 3 + psubw %1, %2 ; a-b + psubw %2, %3 ; b-c + psllw %2, 2 + psubw %1, %2 ; a-5*b+4*c + psllw %3, 4 + paddw %1, %3 ; a-5*b+20*c +%endmacro + +%macro FILT_VNRD 8 + movu %6, [r1] + paddw %1, %6 + mova %7, %2 + paddw %7, %5 + mova %8, %3 + paddw %8, %4 + FILT_H2 %1, %7, %8 +%endmacro + +%macro HV 1 +%if mmsize==16 +%define PAD 12 +%define COUNT 2 +%else +%define PAD 4 +%define COUNT 3 +%endif +put_hv%1_10: + neg r2 ; This actually saves instructions + lea r1, [r1+r2*2-mmsize+PAD] + lea r4, [rsp+PAD+gprsize] + mov r3d, COUNT +.v_loop: + movu m0, [r1] + sub r1, r2 + movu m1, [r1] + sub r1, r2 + movu m2, [r1] + sub r1, r2 + movu m3, [r1] + sub r1, r2 + movu m4, [r1] + sub r1, r2 +%assign i 0 +%rep %1-1 + FILT_VNRD m0, m1, m2, m3, m4, m5, m6, m7 + psubw m0, [pad20] + movu [r4+i*mmsize*3], m0 + sub r1, r2 + SWAP 0,1,2,3,4,5 +%assign i i+1 +%endrep + FILT_VNRD m0, m1, m2, m3, m4, m5, m6, m7 + psubw m0, [pad20] + movu [r4+i*mmsize*3], m0 + add r4, mmsize + lea r1, [r1+r2*8+mmsize] +%if %1==8 + lea r1, [r1+r2*4] +%endif + dec r3d + jg .v_loop + neg r2 + ret +%endmacro + +INIT_MMX mmxext +HV 4 +INIT_XMM sse2 +HV 8 + +%macro H_LOOP 1 +%if num_mmregs > 8 + %define s1 m8 + %define s2 m9 + %define s3 m10 + %define d1 m11 +%else + %define s1 [tap1] + %define s2 [tap2] + %define s3 [tap3] + %define d1 [depad] +%endif +h%1_loop_op: + movu m1, [r1+mmsize-4] + movu m2, [r1+mmsize-2] + mova m3, [r1+mmsize+0] + movu m4, [r1+mmsize+2] + movu m5, [r1+mmsize+4] + movu m6, [r1+mmsize+6] +%if num_mmregs > 8 + pmaddwd m1, s1 + pmaddwd m2, s1 + pmaddwd m3, s2 + pmaddwd m4, s2 + pmaddwd m5, s3 + pmaddwd m6, s3 + paddd m1, d1 + paddd m2, d1 +%else + mova m0, s1 + pmaddwd m1, m0 + pmaddwd m2, m0 + mova m0, s2 + pmaddwd m3, m0 + pmaddwd m4, m0 + mova m0, s3 + pmaddwd m5, m0 + pmaddwd m6, m0 + mova m0, d1 + paddd m1, m0 + paddd m2, m0 +%endif + paddd m3, m5 + paddd m4, m6 + paddd m1, m3 + paddd m2, m4 + psrad m1, 10 + psrad m2, 10 + pslld m2, 16 + pand m1, [pd_0f] + por m1, m2 +%if num_mmregs <= 8 + pxor m0, m0 +%endif + CLIPW m1, m0, m7 + add r1, mmsize*3 + ret +%endmacro + +INIT_MMX mmxext +H_LOOP 4 +INIT_XMM sse2 +H_LOOP 8 + +%macro MC22 2 +cglobal_mc %1, mc22, %2, 3,7,12 +%define PAD mmsize*8*4*2 ; SIZE*16*4*sizeof(pixel) + mov r6, rsp ; backup stack pointer + and rsp, ~(mmsize-1) ; align stack + sub rsp, PAD + + call put_hv%2_10 + + mov r3d, %2 + mova m7, [pw_pixel_max] +%if num_mmregs > 8 + pxor m0, m0 + mova m8, [tap1] + mova m9, [tap2] + mova m10, [tap3] + mova m11, [depad] +%endif + mov r1, rsp +.h_loop: + call h%2_loop_op + + OP_MOV [r0], m1 + add r0, r2 + dec r3d + jg .h_loop + + mov rsp, r6 ; restore stack pointer + ret +%endmacro + +MC MC22 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc12(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC12 2 +cglobal_mc %1, mc12, %2, 3,7,12 +%define PAD mmsize*8*4*2 ; SIZE*16*4*sizeof(pixel) + mov r6, rsp ; backup stack pointer + and rsp, ~(mmsize-1) ; align stack + sub rsp, PAD + + call put_hv%2_10 + + xor r4d, r4d +.body: + mov r3d, %2 + pxor m0, m0 + mova m7, [pw_pixel_max] +%if num_mmregs > 8 + mova m8, [tap1] + mova m9, [tap2] + mova m10, [tap3] + mova m11, [depad] +%endif + mov r1, rsp +.h_loop: + call h%2_loop_op + + movu m3, [r1+r4-2*mmsize] ; movu needed for mc32, etc + paddw m3, [depad2] + psrlw m3, 5 + psubw m3, [unpad] + CLIPW m3, m0, m7 + pavgw m1, m3 + + OP_MOV [r0], m1 + add r0, r2 + dec r3d + jg .h_loop + + mov rsp, r6 ; restore stack pointer + ret +%endmacro + +MC MC12 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc32(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC32 2 +cglobal_mc %1, mc32, %2, 3,7,12 +%define PAD mmsize*8*3*2 ; SIZE*16*4*sizeof(pixel) + mov r6, rsp ; backup stack pointer + and rsp, ~(mmsize-1) ; align stack + sub rsp, PAD + + call put_hv%2_10 + + mov r4d, 2 ; sizeof(pixel) + jmp stub_%1_h264_qpel%2_mc12_10 %+ SUFFIX %+ .body +%endmacro + +MC MC32 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc21(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro H_NRD 1 +put_h%1_10: + add rsp, gprsize + mov r3d, %1 + xor r4d, r4d + mova m6, [pad20] +.nextrow: + movu m2, [r5-4] + movu m3, [r5-2] + movu m4, [r5+0] + ADDW m2, [r5+6], m5 + ADDW m3, [r5+4], m5 + ADDW m4, [r5+2], m5 + + FILT_H2 m2, m3, m4 + psubw m2, m6 + mova [rsp+r4], m2 + add r4d, mmsize*3 + add r5, r2 + dec r3d + jg .nextrow + sub rsp, gprsize + ret +%endmacro + +INIT_MMX mmxext +H_NRD 4 +INIT_XMM sse2 +H_NRD 8 + +%macro MC21 2 +cglobal_mc %1, mc21, %2, 3,7,12 + mov r5, r1 +.body: +%define PAD mmsize*8*3*2 ; SIZE*16*4*sizeof(pixel) + mov r6, rsp ; backup stack pointer + and rsp, ~(mmsize-1) ; align stack + + sub rsp, PAD + call put_h%2_10 + + sub rsp, PAD + call put_hv%2_10 + + mov r4d, PAD-mmsize ; H buffer + jmp stub_%1_h264_qpel%2_mc12_10 %+ SUFFIX %+ .body +%endmacro + +MC MC21 + +;----------------------------------------------------------------------------- +; void h264_qpel_mc23(uint8_t *dst, uint8_t *src, int stride) +;----------------------------------------------------------------------------- +%macro MC23 2 +cglobal_mc %1, mc23, %2, 3,7,12 + lea r5, [r1+r2] + jmp stub_%1_h264_qpel%2_mc21_10 %+ SUFFIX %+ .body +%endmacro + +MC MC23 diff --git a/ffmpeg/libavcodec/x86/h264_qpel_8bit.asm b/ffmpeg/libavcodec/x86/h264_qpel_8bit.asm new file mode 100644 index 0000000..2d287ba --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_qpel_8bit.asm @@ -0,0 +1,862 @@ +;***************************************************************************** +;* MMX/SSE2/SSSE3-optimized H.264 QPEL code +;***************************************************************************** +;* Copyright (c) 2004-2005 Michael Niedermayer, Loren Merritt +;* Copyright (C) 2012 Daniel Kang +;* +;* Authors: Daniel Kang +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +cextern pw_16 +cextern pw_5 +cextern pb_0 + +SECTION .text + + +%macro op_avgh 3 + movh %3, %2 + pavgb %1, %3 + movh %2, %1 +%endmacro + +%macro op_avg 2-3 + pavgb %1, %2 + mova %2, %1 +%endmacro + +%macro op_puth 2-3 + movh %2, %1 +%endmacro + +%macro op_put 2-3 + mova %2, %1 +%endmacro + +%macro QPEL4_H_LOWPASS_OP 1 +cglobal %1_h264_qpel4_h_lowpass, 4,5 ; dst, src, dstStride, srcStride + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + pxor m7, m7 + mova m4, [pw_5] + mova m5, [pw_16] + mov r4d, 4 +.loop: + movh m1, [r1-1] + movh m2, [r1+0] + movh m3, [r1+1] + movh m0, [r1+2] + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m0, m7 + paddw m1, m0 + paddw m2, m3 + movh m0, [r1-2] + movh m3, [r1+3] + punpcklbw m0, m7 + punpcklbw m3, m7 + paddw m0, m3 + psllw m2, 2 + psubw m2, m1 + pmullw m2, m4 + paddw m0, m5 + paddw m0, m2 + psraw m0, 5 + packuswb m0, m0 + op_%1h m0, [r0], m6 + add r0, r2 + add r1, r3 + dec r4d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL4_H_LOWPASS_OP put +QPEL4_H_LOWPASS_OP avg + +%macro QPEL8_H_LOWPASS_OP 1 +cglobal %1_h264_qpel8_h_lowpass, 4,5 ; dst, src, dstStride, srcStride + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + mov r4d, 8 + pxor m7, m7 + mova m6, [pw_5] +.loop: + mova m0, [r1] + mova m2, [r1+1] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + paddw m0, m2 + paddw m1, m3 + psllw m0, 2 + psllw m1, 2 + mova m2, [r1-1] + mova m4, [r1+2] + mova m3, m2 + mova m5, m4 + punpcklbw m2, m7 + punpckhbw m3, m7 + punpcklbw m4, m7 + punpckhbw m5, m7 + paddw m2, m4 + paddw m5, m3 + psubw m0, m2 + psubw m1, m5 + pmullw m0, m6 + pmullw m1, m6 + movd m2, [r1-2] + movd m5, [r1+7] + punpcklbw m2, m7 + punpcklbw m5, m7 + paddw m2, m3 + paddw m4, m5 + mova m5, [pw_16] + paddw m2, m5 + paddw m4, m5 + paddw m0, m2 + paddw m1, m4 + psraw m0, 5 + psraw m1, 5 + packuswb m0, m1 + op_%1 m0, [r0], m4 + add r0, r2 + add r1, r3 + dec r4d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL8_H_LOWPASS_OP put +QPEL8_H_LOWPASS_OP avg + +%macro QPEL8_H_LOWPASS_OP_XMM 1 +cglobal %1_h264_qpel8_h_lowpass, 4,5,8 ; dst, src, dstStride, srcStride + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + mov r4d, 8 + pxor m7, m7 + mova m6, [pw_5] +.loop: + movu m1, [r1-2] + mova m0, m1 + punpckhbw m1, m7 + punpcklbw m0, m7 + mova m2, m1 + mova m3, m1 + mova m4, m1 + mova m5, m1 + palignr m4, m0, 2 + palignr m3, m0, 4 + palignr m2, m0, 6 + palignr m1, m0, 8 + palignr m5, m0, 10 + paddw m0, m5 + paddw m2, m3 + paddw m1, m4 + psllw m2, 2 + psubw m2, m1 + paddw m0, [pw_16] + pmullw m2, m6 + paddw m2, m0 + psraw m2, 5 + packuswb m2, m2 + op_%1h m2, [r0], m4 + add r1, r3 + add r0, r2 + dec r4d + jne .loop + REP_RET +%endmacro + +INIT_XMM ssse3 +QPEL8_H_LOWPASS_OP_XMM put +QPEL8_H_LOWPASS_OP_XMM avg + + +%macro QPEL4_H_LOWPASS_L2_OP 1 +cglobal %1_h264_qpel4_h_lowpass_l2, 5,6 ; dst, src, src2, dstStride, srcStride + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + pxor m7, m7 + mova m4, [pw_5] + mova m5, [pw_16] + mov r5d, 4 +.loop: + movh m1, [r1-1] + movh m2, [r1+0] + movh m3, [r1+1] + movh m0, [r1+2] + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m0, m7 + paddw m1, m0 + paddw m2, m3 + movh m0, [r1-2] + movh m3, [r1+3] + punpcklbw m0, m7 + punpcklbw m3, m7 + paddw m0, m3 + psllw m2, 2 + psubw m2, m1 + pmullw m2, m4 + paddw m0, m5 + paddw m0, m2 + movh m3, [r2] + psraw m0, 5 + packuswb m0, m0 + pavgb m0, m3 + op_%1h m0, [r0], m6 + add r0, r3 + add r1, r3 + add r2, r4 + dec r5d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL4_H_LOWPASS_L2_OP put +QPEL4_H_LOWPASS_L2_OP avg + + +%macro QPEL8_H_LOWPASS_L2_OP 1 +cglobal %1_h264_qpel8_h_lowpass_l2, 5,6 ; dst, src, src2, dstStride, srcStride + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + mov r5d, 8 + pxor m7, m7 + mova m6, [pw_5] +.loop: + mova m0, [r1] + mova m2, [r1+1] + mova m1, m0 + mova m3, m2 + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + paddw m0, m2 + paddw m1, m3 + psllw m0, 2 + psllw m1, 2 + mova m2, [r1-1] + mova m4, [r1+2] + mova m3, m2 + mova m5, m4 + punpcklbw m2, m7 + punpckhbw m3, m7 + punpcklbw m4, m7 + punpckhbw m5, m7 + paddw m2, m4 + paddw m5, m3 + psubw m0, m2 + psubw m1, m5 + pmullw m0, m6 + pmullw m1, m6 + movd m2, [r1-2] + movd m5, [r1+7] + punpcklbw m2, m7 + punpcklbw m5, m7 + paddw m2, m3 + paddw m4, m5 + mova m5, [pw_16] + paddw m2, m5 + paddw m4, m5 + paddw m0, m2 + paddw m1, m4 + psraw m0, 5 + psraw m1, 5 + mova m4, [r2] + packuswb m0, m1 + pavgb m0, m4 + op_%1 m0, [r0], m4 + add r0, r3 + add r1, r3 + add r2, r4 + dec r5d + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL8_H_LOWPASS_L2_OP put +QPEL8_H_LOWPASS_L2_OP avg + + +%macro QPEL8_H_LOWPASS_L2_OP_XMM 1 +cglobal %1_h264_qpel8_h_lowpass_l2, 5,6,8 ; dst, src, src2, dstStride, src2Stride + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + mov r5d, 8 + pxor m7, m7 + mova m6, [pw_5] +.loop: + lddqu m1, [r1-2] + mova m0, m1 + punpckhbw m1, m7 + punpcklbw m0, m7 + mova m2, m1 + mova m3, m1 + mova m4, m1 + mova m5, m1 + palignr m4, m0, 2 + palignr m3, m0, 4 + palignr m2, m0, 6 + palignr m1, m0, 8 + palignr m5, m0, 10 + paddw m0, m5 + paddw m2, m3 + paddw m1, m4 + psllw m2, 2 + movh m3, [r2] + psubw m2, m1 + paddw m0, [pw_16] + pmullw m2, m6 + paddw m2, m0 + psraw m2, 5 + packuswb m2, m2 + pavgb m2, m3 + op_%1h m2, [r0], m4 + add r1, r3 + add r0, r3 + add r2, r4 + dec r5d + jg .loop + REP_RET +%endmacro + +INIT_XMM ssse3 +QPEL8_H_LOWPASS_L2_OP_XMM put +QPEL8_H_LOWPASS_L2_OP_XMM avg + + +; All functions that call this are required to have function arguments of +; dst, src, dstStride, srcStride +%macro FILT_V 1 + mova m6, m2 + movh m5, [r1] + paddw m6, m3 + psllw m6, 2 + psubw m6, m1 + psubw m6, m4 + punpcklbw m5, m7 + pmullw m6, [pw_5] + paddw m0, [pw_16] + add r1, r3 + paddw m0, m5 + paddw m6, m0 + psraw m6, 5 + packuswb m6, m6 + op_%1h m6, [r0], m0 ; 1 + add r0, r2 + SWAP 0, 1, 2, 3, 4, 5 +%endmacro + +%macro QPEL4_V_LOWPASS_OP 1 +cglobal %1_h264_qpel4_v_lowpass, 4,4 ; dst, src, dstStride, srcStride + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + sub r1, r3 + sub r1, r3 + pxor m7, m7 + movh m0, [r1] + movh m1, [r1+r3] + lea r1, [r1+2*r3] + movh m2, [r1] + movh m3, [r1+r3] + lea r1, [r1+2*r3] + movh m4, [r1] + add r1, r3 + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + RET +%endmacro + +INIT_MMX mmxext +QPEL4_V_LOWPASS_OP put +QPEL4_V_LOWPASS_OP avg + + + +%macro QPEL8OR16_V_LOWPASS_OP 1 +%if cpuflag(sse2) +cglobal %1_h264_qpel8or16_v_lowpass, 5,5,8 ; dst, src, dstStride, srcStride, h + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + sub r1, r3 + sub r1, r3 +%else +cglobal %1_h264_qpel8or16_v_lowpass_op, 5,5,8 ; dst, src, dstStride, srcStride, h + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d +%endif + pxor m7, m7 + movh m0, [r1] + movh m1, [r1+r3] + lea r1, [r1+2*r3] + movh m2, [r1] + movh m3, [r1+r3] + lea r1, [r1+2*r3] + movh m4, [r1] + add r1, r3 + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + cmp r4d, 16 + jne .end + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 + FILT_V %1 +.end: + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL8OR16_V_LOWPASS_OP put +QPEL8OR16_V_LOWPASS_OP avg + +INIT_XMM sse2 +QPEL8OR16_V_LOWPASS_OP put +QPEL8OR16_V_LOWPASS_OP avg + + +; All functions that use this are required to have args: +; src, tmp, srcSize +%macro FILT_HV 1 ; offset + mova m6, m2 + movh m5, [r0] + paddw m6, m3 + psllw m6, 2 + paddw m0, [pw_16] + psubw m6, m1 + psubw m6, m4 + punpcklbw m5, m7 + pmullw m6, [pw_5] + paddw m0, m5 + add r0, r2 + paddw m6, m0 + mova [r1+%1], m6 + SWAP 0, 1, 2, 3, 4, 5 +%endmacro + +%macro QPEL4_HV1_LOWPASS_OP 1 +cglobal %1_h264_qpel4_hv_lowpass_v, 3,3 ; src, tmp, srcStride + movsxdifnidn r2, r2d + pxor m7, m7 + movh m0, [r0] + movh m1, [r0+r2] + lea r0, [r0+2*r2] + movh m2, [r0] + movh m3, [r0+r2] + lea r0, [r0+2*r2] + movh m4, [r0] + add r0, r2 + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + FILT_HV 0*24 + FILT_HV 1*24 + FILT_HV 2*24 + FILT_HV 3*24 + RET + +cglobal %1_h264_qpel4_hv_lowpass_h, 3,4 ; tmp, dst, dstStride + movsxdifnidn r2, r2d + mov r3d, 4 +.loop: + mova m0, [r0] + paddw m0, [r0+10] + mova m1, [r0+2] + paddw m1, [r0+8] + mova m2, [r0+4] + paddw m2, [r0+6] + psubw m0, m1 + psraw m0, 2 + psubw m0, m1 + paddsw m0, m2 + psraw m0, 2 + paddw m0, m2 + psraw m0, 6 + packuswb m0, m0 + op_%1h m0, [r1], m7 + add r0, 24 + add r1, r2 + dec r3d + jnz .loop + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL4_HV1_LOWPASS_OP put +QPEL4_HV1_LOWPASS_OP avg + +%macro QPEL8OR16_HV1_LOWPASS_OP 1 +cglobal %1_h264_qpel8or16_hv1_lowpass_op, 4,4,8 ; src, tmp, srcStride, size + movsxdifnidn r2, r2d + pxor m7, m7 + movh m0, [r0] + movh m1, [r0+r2] + lea r0, [r0+2*r2] + movh m2, [r0] + movh m3, [r0+r2] + lea r0, [r0+2*r2] + movh m4, [r0] + add r0, r2 + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + FILT_HV 0*48 + FILT_HV 1*48 + FILT_HV 2*48 + FILT_HV 3*48 + FILT_HV 4*48 + FILT_HV 5*48 + FILT_HV 6*48 + FILT_HV 7*48 + cmp r3d, 16 + jne .end + FILT_HV 8*48 + FILT_HV 9*48 + FILT_HV 10*48 + FILT_HV 11*48 + FILT_HV 12*48 + FILT_HV 13*48 + FILT_HV 14*48 + FILT_HV 15*48 +.end: + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL8OR16_HV1_LOWPASS_OP put +QPEL8OR16_HV1_LOWPASS_OP avg + +INIT_XMM sse2 +QPEL8OR16_HV1_LOWPASS_OP put + + + +%macro QPEL8OR16_HV2_LOWPASS_OP 1 +; unused is to match ssse3 and mmxext args +cglobal %1_h264_qpel8or16_hv2_lowpass_op, 5,5 ; dst, tmp, dstStride, unused, h + movsxdifnidn r2, r2d +.loop: + mova m0, [r1] + mova m3, [r1+8] + mova m1, [r1+2] + mova m4, [r1+10] + paddw m0, m4 + paddw m1, m3 + paddw m3, [r1+18] + paddw m4, [r1+16] + mova m2, [r1+4] + mova m5, [r1+12] + paddw m2, [r1+6] + paddw m5, [r1+14] + psubw m0, m1 + psubw m3, m4 + psraw m0, 2 + psraw m3, 2 + psubw m0, m1 + psubw m3, m4 + paddsw m0, m2 + paddsw m3, m5 + psraw m0, 2 + psraw m3, 2 + paddw m0, m2 + paddw m3, m5 + psraw m0, 6 + psraw m3, 6 + packuswb m0, m3 + op_%1 m0, [r0], m7 + add r1, 48 + add r0, r2 + dec r4d + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +QPEL8OR16_HV2_LOWPASS_OP put +QPEL8OR16_HV2_LOWPASS_OP avg + +%macro QPEL8OR16_HV2_LOWPASS_OP_XMM 1 +cglobal %1_h264_qpel8or16_hv2_lowpass, 5,5,8 ; dst, tmp, dstStride, tmpStride, size + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + cmp r4d, 16 + je .op16 +.loop8: + mova m1, [r1+16] + mova m0, [r1] + mova m2, m1 + mova m3, m1 + mova m4, m1 + mova m5, m1 + palignr m5, m0, 10 + palignr m4, m0, 8 + palignr m3, m0, 6 + palignr m2, m0, 4 + palignr m1, m0, 2 + paddw m0, m5 + paddw m1, m4 + paddw m2, m3 + psubw m0, m1 + psraw m0, 2 + psubw m0, m1 + paddw m0, m2 + psraw m0, 2 + paddw m0, m2 + psraw m0, 6 + packuswb m0, m0 + op_%1h m0, [r0], m7 + add r1, 48 + add r0, r2 + dec r4d + jne .loop8 + jmp .done +.op16: + mova m4, [r1+32] + mova m5, [r1+16] + mova m7, [r1] + mova m3, m4 + mova m2, m4 + mova m1, m4 + mova m0, m4 + palignr m0, m5, 10 + palignr m1, m5, 8 + palignr m2, m5, 6 + palignr m3, m5, 4 + palignr m4, m5, 2 + paddw m0, m5 + paddw m1, m4 + paddw m2, m3 + mova m6, m5 + mova m4, m5 + mova m3, m5 + palignr m4, m7, 8 + palignr m6, m7, 2 + palignr m3, m7, 10 + paddw m4, m6 + mova m6, m5 + palignr m5, m7, 6 + palignr m6, m7, 4 + paddw m3, m7 + paddw m5, m6 + psubw m0, m1 + psubw m3, m4 + psraw m0, 2 + psraw m3, 2 + psubw m0, m1 + psubw m3, m4 + paddw m0, m2 + paddw m3, m5 + psraw m0, 2 + psraw m3, 2 + paddw m0, m2 + paddw m3, m5 + psraw m0, 6 + psraw m3, 6 + packuswb m3, m0 + op_%1 m3, [r0], m7 + add r1, 48 + add r0, r2 + dec r4d + jne .op16 +.done: + REP_RET +%endmacro + +INIT_XMM ssse3 +QPEL8OR16_HV2_LOWPASS_OP_XMM put +QPEL8OR16_HV2_LOWPASS_OP_XMM avg + + +%macro PIXELS4_L2_SHIFT5 1 +cglobal %1_pixels4_l2_shift5,6,6 ; dst, src16, src8, dstStride, src8Stride, h + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + mova m0, [r1] + mova m1, [r1+24] + psraw m0, 5 + psraw m1, 5 + packuswb m0, m0 + packuswb m1, m1 + pavgb m0, [r2] + pavgb m1, [r2+r4] + op_%1h m0, [r0], m4 + op_%1h m1, [r0+r3], m5 + lea r2, [r2+r4*2] + lea r0, [r0+r3*2] + mova m0, [r1+48] + mova m1, [r1+72] + psraw m0, 5 + psraw m1, 5 + packuswb m0, m0 + packuswb m1, m1 + pavgb m0, [r2] + pavgb m1, [r2+r4] + op_%1h m0, [r0], m4 + op_%1h m1, [r0+r3], m5 + RET +%endmacro + +INIT_MMX mmxext +PIXELS4_L2_SHIFT5 put +PIXELS4_L2_SHIFT5 avg + + +%macro PIXELS8_L2_SHIFT5 1 +cglobal %1_pixels8_l2_shift5, 6, 6 ; dst, src16, src8, dstStride, src8Stride, h + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d +.loop: + mova m0, [r1] + mova m1, [r1+8] + mova m2, [r1+48] + mova m3, [r1+48+8] + psraw m0, 5 + psraw m1, 5 + psraw m2, 5 + psraw m3, 5 + packuswb m0, m1 + packuswb m2, m3 + pavgb m0, [r2] + pavgb m2, [r2+r4] + op_%1 m0, [r0], m4 + op_%1 m2, [r0+r3], m5 + lea r2, [r2+2*r4] + add r1, 48*2 + lea r0, [r0+2*r3] + sub r5d, 2 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PIXELS8_L2_SHIFT5 put +PIXELS8_L2_SHIFT5 avg + + +%if ARCH_X86_64 +%macro QPEL16_H_LOWPASS_L2_OP 1 +cglobal %1_h264_qpel16_h_lowpass_l2, 5, 6, 16 ; dst, src, src2, dstStride, src2Stride + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + mov r5d, 16 + pxor m15, m15 + mova m14, [pw_5] + mova m13, [pw_16] +.loop: + lddqu m1, [r1+6] + lddqu m7, [r1-2] + mova m0, m1 + punpckhbw m1, m15 + punpcklbw m0, m15 + punpcklbw m7, m15 + mova m2, m1 + mova m6, m0 + mova m3, m1 + mova m8, m0 + mova m4, m1 + mova m9, m0 + mova m12, m0 + mova m11, m1 + palignr m11, m0, 10 + palignr m12, m7, 10 + palignr m4, m0, 2 + palignr m9, m7, 2 + palignr m3, m0, 4 + palignr m8, m7, 4 + palignr m2, m0, 6 + palignr m6, m7, 6 + paddw m11, m0 + palignr m1, m0, 8 + palignr m0, m7, 8 + paddw m7, m12 + paddw m2, m3 + paddw m6, m8 + paddw m1, m4 + paddw m0, m9 + psllw m2, 2 + psllw m6, 2 + psubw m2, m1 + psubw m6, m0 + paddw m11, m13 + paddw m7, m13 + pmullw m2, m14 + pmullw m6, m14 + lddqu m3, [r2] + paddw m2, m11 + paddw m6, m7 + psraw m2, 5 + psraw m6, 5 + packuswb m6, m2 + pavgb m6, m3 + op_%1 m6, [r0], m11 + add r1, r3 + add r0, r3 + add r2, r4 + dec r5d + jg .loop + REP_RET +%endmacro + +INIT_XMM ssse3 +QPEL16_H_LOWPASS_L2_OP put +QPEL16_H_LOWPASS_L2_OP avg +%endif diff --git a/ffmpeg/libavcodec/x86/h264_weight.asm b/ffmpeg/libavcodec/x86/h264_weight.asm new file mode 100644 index 0000000..4759a06 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_weight.asm @@ -0,0 +1,317 @@ +;***************************************************************************** +;* SSE2-optimized weighted prediction code +;***************************************************************************** +;* Copyright (c) 2004-2005 Michael Niedermayer, Loren Merritt +;* Copyright (C) 2010 Eli Friedman +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION .text + +;----------------------------------------------------------------------------- +; biweight pred: +; +; void h264_biweight_16_sse2(uint8_t *dst, uint8_t *src, int stride, +; int height, int log2_denom, int weightd, +; int weights, int offset); +; and +; void h264_weight_16_sse2(uint8_t *dst, int stride, int height, +; int log2_denom, int weight, int offset); +;----------------------------------------------------------------------------- + +%macro WEIGHT_SETUP 0 + add r5, r5 + inc r5 + movd m3, r4d + movd m5, r5d + movd m6, r3d + pslld m5, m6 + psrld m5, 1 +%if mmsize == 16 + pshuflw m3, m3, 0 + pshuflw m5, m5, 0 + punpcklqdq m3, m3 + punpcklqdq m5, m5 +%else + pshufw m3, m3, 0 + pshufw m5, m5, 0 +%endif + pxor m7, m7 +%endmacro + +%macro WEIGHT_OP 2 + movh m0, [r0+%1] + movh m1, [r0+%2] + punpcklbw m0, m7 + punpcklbw m1, m7 + pmullw m0, m3 + pmullw m1, m3 + paddsw m0, m5 + paddsw m1, m5 + psraw m0, m6 + psraw m1, m6 + packuswb m0, m1 +%endmacro + +INIT_MMX mmxext +cglobal h264_weight_16, 6, 6, 0 + WEIGHT_SETUP +.nextrow: + WEIGHT_OP 0, 4 + mova [r0 ], m0 + WEIGHT_OP 8, 12 + mova [r0+8], m0 + add r0, r1 + dec r2d + jnz .nextrow + REP_RET + +%macro WEIGHT_FUNC_MM 2 +cglobal h264_weight_%1, 6, 6, %2 + WEIGHT_SETUP +.nextrow: + WEIGHT_OP 0, mmsize/2 + mova [r0], m0 + add r0, r1 + dec r2d + jnz .nextrow + REP_RET +%endmacro + +INIT_MMX mmxext +WEIGHT_FUNC_MM 8, 0 +INIT_XMM sse2 +WEIGHT_FUNC_MM 16, 8 + +%macro WEIGHT_FUNC_HALF_MM 2 +cglobal h264_weight_%1, 6, 6, %2 + WEIGHT_SETUP + sar r2d, 1 + lea r3, [r1*2] +.nextrow: + WEIGHT_OP 0, r1 + movh [r0], m0 +%if mmsize == 16 + movhps [r0+r1], m0 +%else + psrlq m0, 32 + movh [r0+r1], m0 +%endif + add r0, r3 + dec r2d + jnz .nextrow + REP_RET +%endmacro + +INIT_MMX mmxext +WEIGHT_FUNC_HALF_MM 4, 0 +INIT_XMM sse2 +WEIGHT_FUNC_HALF_MM 8, 8 + +%macro BIWEIGHT_SETUP 0 +%if ARCH_X86_64 +%define off_regd r7d +%else +%define off_regd r3d +%endif + mov off_regd, r7m + add off_regd, 1 + or off_regd, 1 + add r4, 1 + cmp r5, 128 + jne .normal + sar r5, 1 + sar r6, 1 + sar off_regd, 1 + sub r4, 1 +.normal +%if cpuflag(ssse3) + movd m4, r5d + movd m0, r6d +%else + movd m3, r5d + movd m4, r6d +%endif + movd m5, off_regd + movd m6, r4d + pslld m5, m6 + psrld m5, 1 +%if cpuflag(ssse3) + punpcklbw m4, m0 + pshuflw m4, m4, 0 + pshuflw m5, m5, 0 + punpcklqdq m4, m4 + punpcklqdq m5, m5 + +%else +%if mmsize == 16 + pshuflw m3, m3, 0 + pshuflw m4, m4, 0 + pshuflw m5, m5, 0 + punpcklqdq m3, m3 + punpcklqdq m4, m4 + punpcklqdq m5, m5 +%else + pshufw m3, m3, 0 + pshufw m4, m4, 0 + pshufw m5, m5, 0 +%endif + pxor m7, m7 +%endif +%endmacro + +%macro BIWEIGHT_STEPA 3 + movh m%1, [r0+%3] + movh m%2, [r1+%3] + punpcklbw m%1, m7 + punpcklbw m%2, m7 + pmullw m%1, m3 + pmullw m%2, m4 + paddsw m%1, m%2 +%endmacro + +%macro BIWEIGHT_STEPB 0 + paddsw m0, m5 + paddsw m1, m5 + psraw m0, m6 + psraw m1, m6 + packuswb m0, m1 +%endmacro + +INIT_MMX mmxext +cglobal h264_biweight_16, 7, 8, 0 + BIWEIGHT_SETUP + movifnidn r3d, r3m +.nextrow: + BIWEIGHT_STEPA 0, 1, 0 + BIWEIGHT_STEPA 1, 2, 4 + BIWEIGHT_STEPB + mova [r0], m0 + BIWEIGHT_STEPA 0, 1, 8 + BIWEIGHT_STEPA 1, 2, 12 + BIWEIGHT_STEPB + mova [r0+8], m0 + add r0, r2 + add r1, r2 + dec r3d + jnz .nextrow + REP_RET + +%macro BIWEIGHT_FUNC_MM 2 +cglobal h264_biweight_%1, 7, 8, %2 + BIWEIGHT_SETUP + movifnidn r3d, r3m +.nextrow: + BIWEIGHT_STEPA 0, 1, 0 + BIWEIGHT_STEPA 1, 2, mmsize/2 + BIWEIGHT_STEPB + mova [r0], m0 + add r0, r2 + add r1, r2 + dec r3d + jnz .nextrow + REP_RET +%endmacro + +INIT_MMX mmxext +BIWEIGHT_FUNC_MM 8, 0 +INIT_XMM sse2 +BIWEIGHT_FUNC_MM 16, 8 + +%macro BIWEIGHT_FUNC_HALF_MM 2 +cglobal h264_biweight_%1, 7, 8, %2 + BIWEIGHT_SETUP + movifnidn r3d, r3m + sar r3, 1 + lea r4, [r2*2] +.nextrow: + BIWEIGHT_STEPA 0, 1, 0 + BIWEIGHT_STEPA 1, 2, r2 + BIWEIGHT_STEPB + movh [r0], m0 +%if mmsize == 16 + movhps [r0+r2], m0 +%else + psrlq m0, 32 + movh [r0+r2], m0 +%endif + add r0, r4 + add r1, r4 + dec r3d + jnz .nextrow + REP_RET +%endmacro + +INIT_MMX mmxext +BIWEIGHT_FUNC_HALF_MM 4, 0 +INIT_XMM sse2 +BIWEIGHT_FUNC_HALF_MM 8, 8 + +%macro BIWEIGHT_SSSE3_OP 0 + pmaddubsw m0, m4 + pmaddubsw m2, m4 + paddsw m0, m5 + paddsw m2, m5 + psraw m0, m6 + psraw m2, m6 + packuswb m0, m2 +%endmacro + +INIT_XMM ssse3 +cglobal h264_biweight_16, 7, 8, 8 + BIWEIGHT_SETUP + movifnidn r3d, r3m + +.nextrow: + movh m0, [r0] + movh m2, [r0+8] + movh m3, [r1+8] + punpcklbw m0, [r1] + punpcklbw m2, m3 + BIWEIGHT_SSSE3_OP + mova [r0], m0 + add r0, r2 + add r1, r2 + dec r3d + jnz .nextrow + REP_RET + +INIT_XMM ssse3 +cglobal h264_biweight_8, 7, 8, 8 + BIWEIGHT_SETUP + movifnidn r3d, r3m + sar r3, 1 + lea r4, [r2*2] + +.nextrow: + movh m0, [r0] + movh m1, [r1] + movh m2, [r0+r2] + movh m3, [r1+r2] + punpcklbw m0, m1 + punpcklbw m2, m3 + BIWEIGHT_SSSE3_OP + movh [r0], m0 + movhps [r0+r2], m0 + add r0, r4 + add r1, r4 + dec r3d + jnz .nextrow + REP_RET diff --git a/ffmpeg/libavcodec/x86/h264_weight_10bit.asm b/ffmpeg/libavcodec/x86/h264_weight_10bit.asm new file mode 100644 index 0000000..3b09e42 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264_weight_10bit.asm @@ -0,0 +1,282 @@ +;***************************************************************************** +;* MMX/SSE2/AVX-optimized 10-bit H.264 weighted prediction code +;***************************************************************************** +;* Copyright (C) 2005-2011 x264 project +;* +;* Authors: Daniel Kang +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +pw_pixel_max: times 8 dw ((1 << 10)-1) +sq_1: dq 1 + dq 0 + +cextern pw_1 + +SECTION .text + +;----------------------------------------------------------------------------- +; void h264_weight(uint8_t *dst, int stride, int height, int log2_denom, +; int weight, int offset); +;----------------------------------------------------------------------------- +%macro WEIGHT_PROLOGUE 0 +.prologue: + PROLOGUE 0,6,8 + movifnidn r0, r0mp + movifnidn r1d, r1m + movifnidn r2d, r2m + movifnidn r4d, r4m + movifnidn r5d, r5m +%endmacro + +%macro WEIGHT_SETUP 0 + mova m0, [pw_1] + movd m2, r3m + pslld m0, m2 ; 1< + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/h264chroma.h" + +void ff_put_h264_chroma_mc8_rnd_mmx (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc8_rnd_mmxext(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc8_rnd_3dnow(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +void ff_put_h264_chroma_mc4_mmx (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc4_mmxext (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc4_3dnow (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +void ff_put_h264_chroma_mc2_mmxext (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc2_mmxext (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +void ff_put_h264_chroma_mc8_rnd_ssse3(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_put_h264_chroma_mc4_ssse3 (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +void ff_avg_h264_chroma_mc8_rnd_ssse3(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_h264_chroma_mc4_ssse3 (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +#define CHROMA_MC(OP, NUM, DEPTH, OPT) \ +void ff_ ## OP ## _h264_chroma_mc ## NUM ## _ ## DEPTH ## _ ## OPT \ + (uint8_t *dst, uint8_t *src, \ + int stride, int h, int x, int y); + +CHROMA_MC(put, 2, 10, mmxext) +CHROMA_MC(avg, 2, 10, mmxext) +CHROMA_MC(put, 4, 10, mmxext) +CHROMA_MC(avg, 4, 10, mmxext) +CHROMA_MC(put, 8, 10, sse2) +CHROMA_MC(avg, 8, 10, sse2) +CHROMA_MC(put, 8, 10, avx) +CHROMA_MC(avg, 8, 10, avx) + +void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth) +{ +#if HAVE_YASM + int high_bit_depth = bit_depth > 8; + int mm_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(mm_flags) && !high_bit_depth) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_rnd_mmx; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_mmx; + } + + if (EXTERNAL_AMD3DNOW(mm_flags) && !high_bit_depth) { + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_rnd_3dnow; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_3dnow; + } + + if (EXTERNAL_MMXEXT(mm_flags) && !high_bit_depth) { + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_rnd_mmxext; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_mmxext; + c->avg_h264_chroma_pixels_tab[2] = ff_avg_h264_chroma_mc2_mmxext; + c->put_h264_chroma_pixels_tab[2] = ff_put_h264_chroma_mc2_mmxext; + } + + if (EXTERNAL_MMXEXT(mm_flags) && bit_depth > 8 && bit_depth <= 10) { + c->put_h264_chroma_pixels_tab[2] = ff_put_h264_chroma_mc2_10_mmxext; + c->avg_h264_chroma_pixels_tab[2] = ff_avg_h264_chroma_mc2_10_mmxext; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_10_mmxext; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_10_mmxext; + } + + if (EXTERNAL_SSE2(mm_flags) && bit_depth > 8 && bit_depth <= 10) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_10_sse2; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_10_sse2; + } + + if (EXTERNAL_SSSE3(mm_flags) && !high_bit_depth) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_rnd_ssse3; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_rnd_ssse3; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_ssse3; + c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_ssse3; + } + + if (EXTERNAL_AVX(mm_flags) && bit_depth > 8 && bit_depth <= 10) { + // AVX implies !cache64. + // TODO: Port cache(32|64) detection from x264. + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_10_avx; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_10_avx; + } +#endif +} diff --git a/ffmpeg/libavcodec/x86/h264dsp_init.c b/ffmpeg/libavcodec/x86/h264dsp_init.c new file mode 100644 index 0000000..11aae77 --- /dev/null +++ b/ffmpeg/libavcodec/x86/h264dsp_init.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2004-2005 Michael Niedermayer, Loren Merritt + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/h264dsp.h" +#include "dsputil_mmx.h" + +/***********************************/ +/* IDCT */ +#define IDCT_ADD_FUNC(NUM, DEPTH, OPT) \ +void ff_h264_idct ## NUM ## _add_ ## DEPTH ## _ ## OPT(uint8_t *dst, \ + int16_t *block, \ + int stride); + +IDCT_ADD_FUNC(, 8, mmx) +IDCT_ADD_FUNC(, 10, sse2) +IDCT_ADD_FUNC(_dc, 8, mmxext) +IDCT_ADD_FUNC(_dc, 10, mmxext) +IDCT_ADD_FUNC(8_dc, 8, mmxext) +IDCT_ADD_FUNC(8_dc, 10, sse2) +IDCT_ADD_FUNC(8, 8, mmx) +IDCT_ADD_FUNC(8, 8, sse2) +IDCT_ADD_FUNC(8, 10, sse2) +IDCT_ADD_FUNC(, 10, avx) +IDCT_ADD_FUNC(8_dc, 10, avx) +IDCT_ADD_FUNC(8, 10, avx) + + +#define IDCT_ADD_REP_FUNC(NUM, REP, DEPTH, OPT) \ +void ff_h264_idct ## NUM ## _add ## REP ## _ ## DEPTH ## _ ## OPT \ + (uint8_t *dst, const int *block_offset, \ + int16_t *block, int stride, const uint8_t nnzc[6 * 8]); + +IDCT_ADD_REP_FUNC(8, 4, 8, mmx) +IDCT_ADD_REP_FUNC(8, 4, 8, mmxext) +IDCT_ADD_REP_FUNC(8, 4, 8, sse2) +IDCT_ADD_REP_FUNC(8, 4, 10, sse2) +IDCT_ADD_REP_FUNC(8, 4, 10, avx) +IDCT_ADD_REP_FUNC(, 16, 8, mmx) +IDCT_ADD_REP_FUNC(, 16, 8, mmxext) +IDCT_ADD_REP_FUNC(, 16, 8, sse2) +IDCT_ADD_REP_FUNC(, 16, 10, sse2) +IDCT_ADD_REP_FUNC(, 16intra, 8, mmx) +IDCT_ADD_REP_FUNC(, 16intra, 8, mmxext) +IDCT_ADD_REP_FUNC(, 16intra, 8, sse2) +IDCT_ADD_REP_FUNC(, 16intra, 10, sse2) +IDCT_ADD_REP_FUNC(, 16, 10, avx) +IDCT_ADD_REP_FUNC(, 16intra, 10, avx) + + +#define IDCT_ADD_REP_FUNC2(NUM, REP, DEPTH, OPT) \ +void ff_h264_idct ## NUM ## _add ## REP ## _ ## DEPTH ## _ ## OPT \ + (uint8_t **dst, const int *block_offset, \ + int16_t *block, int stride, const uint8_t nnzc[6 * 8]); + +IDCT_ADD_REP_FUNC2(, 8, 8, mmx) +IDCT_ADD_REP_FUNC2(, 8, 8, mmxext) +IDCT_ADD_REP_FUNC2(, 8, 8, sse2) +IDCT_ADD_REP_FUNC2(, 8, 10, sse2) +IDCT_ADD_REP_FUNC2(, 8, 10, avx) + +void ff_h264_luma_dc_dequant_idct_mmx(int16_t *output, int16_t *input, int qmul); +void ff_h264_luma_dc_dequant_idct_sse2(int16_t *output, int16_t *input, int qmul); + +/***********************************/ +/* deblocking */ + +void ff_h264_loop_filter_strength_mmxext(int16_t bS[2][4][4], uint8_t nnz[40], + int8_t ref[2][40], + int16_t mv[2][40][2], + int bidir, int edges, int step, + int mask_mv0, int mask_mv1, int field); + +#define LF_FUNC(DIR, TYPE, DEPTH, OPT) \ +void ff_deblock_ ## DIR ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT(uint8_t *pix, \ + int stride, \ + int alpha, \ + int beta, \ + int8_t *tc0); +#define LF_IFUNC(DIR, TYPE, DEPTH, OPT) \ +void ff_deblock_ ## DIR ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT(uint8_t *pix, \ + int stride, \ + int alpha, \ + int beta); + +#define LF_FUNCS(type, depth) \ +LF_FUNC(h, chroma, depth, mmxext) \ +LF_IFUNC(h, chroma_intra, depth, mmxext) \ +LF_FUNC(v, chroma, depth, mmxext) \ +LF_IFUNC(v, chroma_intra, depth, mmxext) \ +LF_FUNC(h, luma, depth, mmxext) \ +LF_IFUNC(h, luma_intra, depth, mmxext) \ +LF_FUNC(h, luma, depth, sse2) \ +LF_IFUNC(h, luma_intra, depth, sse2) \ +LF_FUNC(v, luma, depth, sse2) \ +LF_IFUNC(v, luma_intra, depth, sse2) \ +LF_FUNC(h, chroma, depth, sse2) \ +LF_IFUNC(h, chroma_intra, depth, sse2) \ +LF_FUNC(v, chroma, depth, sse2) \ +LF_IFUNC(v, chroma_intra, depth, sse2) \ +LF_FUNC(h, luma, depth, avx) \ +LF_IFUNC(h, luma_intra, depth, avx) \ +LF_FUNC(v, luma, depth, avx) \ +LF_IFUNC(v, luma_intra, depth, avx) \ +LF_FUNC(h, chroma, depth, avx) \ +LF_IFUNC(h, chroma_intra, depth, avx) \ +LF_FUNC(v, chroma, depth, avx) \ +LF_IFUNC(v, chroma_intra, depth, avx) + +LF_FUNCS(uint8_t, 8) +LF_FUNCS(uint16_t, 10) + +#if ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL +LF_FUNC(v8, luma, 8, mmxext) +static void ff_deblock_v_luma_8_mmxext(uint8_t *pix, int stride, int alpha, + int beta, int8_t *tc0) +{ + if ((tc0[0] & tc0[1]) >= 0) + ff_deblock_v8_luma_8_mmxext(pix + 0, stride, alpha, beta, tc0); + if ((tc0[2] & tc0[3]) >= 0) + ff_deblock_v8_luma_8_mmxext(pix + 8, stride, alpha, beta, tc0 + 2); +} +LF_IFUNC(v8, luma_intra, 8, mmxext) +static void ff_deblock_v_luma_intra_8_mmxext(uint8_t *pix, int stride, + int alpha, int beta) +{ + ff_deblock_v8_luma_intra_8_mmxext(pix + 0, stride, alpha, beta); + ff_deblock_v8_luma_intra_8_mmxext(pix + 8, stride, alpha, beta); +} +#endif /* ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL */ + +LF_FUNC(v, luma, 10, mmxext) +LF_IFUNC(v, luma_intra, 10, mmxext) + +/***********************************/ +/* weighted prediction */ + +#define H264_WEIGHT(W, OPT) \ +void ff_h264_weight_ ## W ## _ ## OPT(uint8_t *dst, int stride, \ + int height, int log2_denom, \ + int weight, int offset); + +#define H264_BIWEIGHT(W, OPT) \ +void ff_h264_biweight_ ## W ## _ ## OPT(uint8_t *dst, uint8_t *src, \ + int stride, int height, \ + int log2_denom, int weightd, \ + int weights, int offset); + +#define H264_BIWEIGHT_MMX(W) \ + H264_WEIGHT(W, mmxext) \ + H264_BIWEIGHT(W, mmxext) + +#define H264_BIWEIGHT_MMX_SSE(W) \ + H264_BIWEIGHT_MMX(W) \ + H264_WEIGHT(W, sse2) \ + H264_BIWEIGHT(W, sse2) \ + H264_BIWEIGHT(W, ssse3) + +H264_BIWEIGHT_MMX_SSE(16) +H264_BIWEIGHT_MMX_SSE(8) +H264_BIWEIGHT_MMX(4) + +#define H264_WEIGHT_10(W, DEPTH, OPT) \ +void ff_h264_weight_ ## W ## _ ## DEPTH ## _ ## OPT(uint8_t *dst, \ + int stride, \ + int height, \ + int log2_denom, \ + int weight, \ + int offset); + +#define H264_BIWEIGHT_10(W, DEPTH, OPT) \ +void ff_h264_biweight_ ## W ## _ ## DEPTH ## _ ## OPT(uint8_t *dst, \ + uint8_t *src, \ + int stride, \ + int height, \ + int log2_denom, \ + int weightd, \ + int weights, \ + int offset); + +#define H264_BIWEIGHT_10_SSE(W, DEPTH) \ + H264_WEIGHT_10(W, DEPTH, sse2) \ + H264_WEIGHT_10(W, DEPTH, sse4) \ + H264_BIWEIGHT_10(W, DEPTH, sse2) \ + H264_BIWEIGHT_10(W, DEPTH, sse4) + +H264_BIWEIGHT_10_SSE(16, 10) +H264_BIWEIGHT_10_SSE(8, 10) +H264_BIWEIGHT_10_SSE(4, 10) + +av_cold void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) +{ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + + if (chroma_format_idc == 1 && EXTERNAL_MMXEXT(mm_flags)) + c->h264_loop_filter_strength = ff_h264_loop_filter_strength_mmxext; + + if (bit_depth == 8) { + if (EXTERNAL_MMX(mm_flags)) { + c->h264_idct_dc_add = + c->h264_idct_add = ff_h264_idct_add_8_mmx; + c->h264_idct8_dc_add = + c->h264_idct8_add = ff_h264_idct8_add_8_mmx; + + c->h264_idct_add16 = ff_h264_idct_add16_8_mmx; + c->h264_idct8_add4 = ff_h264_idct8_add4_8_mmx; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_8_mmx; + c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmx; + if (mm_flags & AV_CPU_FLAG_CMOV) + c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_mmx; + + if (EXTERNAL_MMXEXT(mm_flags)) { + c->h264_idct_dc_add = ff_h264_idct_dc_add_8_mmxext; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_mmxext; + c->h264_idct_add16 = ff_h264_idct_add16_8_mmxext; + c->h264_idct8_add4 = ff_h264_idct8_add4_8_mmxext; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_8_mmxext; + c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmxext; + + c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_8_mmxext; + c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_8_mmxext; + if (chroma_format_idc == 1) { + c->h264_h_loop_filter_chroma = ff_deblock_h_chroma_8_mmxext; + c->h264_h_loop_filter_chroma_intra = ff_deblock_h_chroma_intra_8_mmxext; + } +#if ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL + c->h264_v_loop_filter_luma = ff_deblock_v_luma_8_mmxext; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_8_mmxext; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_8_mmxext; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_8_mmxext; +#endif /* ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL */ + c->weight_h264_pixels_tab[0] = ff_h264_weight_16_mmxext; + c->weight_h264_pixels_tab[1] = ff_h264_weight_8_mmxext; + c->weight_h264_pixels_tab[2] = ff_h264_weight_4_mmxext; + + c->biweight_h264_pixels_tab[0] = ff_h264_biweight_16_mmxext; + c->biweight_h264_pixels_tab[1] = ff_h264_biweight_8_mmxext; + c->biweight_h264_pixels_tab[2] = ff_h264_biweight_4_mmxext; + + if (EXTERNAL_SSE2(mm_flags)) { + c->h264_idct8_add = ff_h264_idct8_add_8_sse2; + + c->h264_idct_add16 = ff_h264_idct_add16_8_sse2; + c->h264_idct8_add4 = ff_h264_idct8_add4_8_sse2; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_8_sse2; + c->h264_idct_add16intra = ff_h264_idct_add16intra_8_sse2; + c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_sse2; + + c->weight_h264_pixels_tab[0] = ff_h264_weight_16_sse2; + c->weight_h264_pixels_tab[1] = ff_h264_weight_8_sse2; + + c->biweight_h264_pixels_tab[0] = ff_h264_biweight_16_sse2; + c->biweight_h264_pixels_tab[1] = ff_h264_biweight_8_sse2; + + c->h264_v_loop_filter_luma = ff_deblock_v_luma_8_sse2; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_8_sse2; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_8_sse2; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_8_sse2; + } + if (EXTERNAL_SSSE3(mm_flags)) { + c->biweight_h264_pixels_tab[0] = ff_h264_biweight_16_ssse3; + c->biweight_h264_pixels_tab[1] = ff_h264_biweight_8_ssse3; + } + if (EXTERNAL_AVX(mm_flags)) { + c->h264_v_loop_filter_luma = ff_deblock_v_luma_8_avx; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_8_avx; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_8_avx; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_8_avx; + } + } + } + } else if (bit_depth == 10) { + if (EXTERNAL_MMX(mm_flags)) { + if (EXTERNAL_MMXEXT(mm_flags)) { +#if ARCH_X86_32 + c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_10_mmxext; + c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_10_mmxext; + c->h264_v_loop_filter_luma = ff_deblock_v_luma_10_mmxext; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_10_mmxext; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_10_mmxext; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_mmxext; +#endif /* ARCH_X86_32 */ + c->h264_idct_dc_add = ff_h264_idct_dc_add_10_mmxext; + if (EXTERNAL_SSE2(mm_flags)) { + c->h264_idct_add = ff_h264_idct_add_10_sse2; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_10_sse2; + + c->h264_idct_add16 = ff_h264_idct_add16_10_sse2; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_10_sse2; + c->h264_idct_add16intra = ff_h264_idct_add16intra_10_sse2; +#if HAVE_ALIGNED_STACK + c->h264_idct8_add = ff_h264_idct8_add_10_sse2; + c->h264_idct8_add4 = ff_h264_idct8_add4_10_sse2; +#endif /* HAVE_ALIGNED_STACK */ + + c->weight_h264_pixels_tab[0] = ff_h264_weight_16_10_sse2; + c->weight_h264_pixels_tab[1] = ff_h264_weight_8_10_sse2; + c->weight_h264_pixels_tab[2] = ff_h264_weight_4_10_sse2; + + c->biweight_h264_pixels_tab[0] = ff_h264_biweight_16_10_sse2; + c->biweight_h264_pixels_tab[1] = ff_h264_biweight_8_10_sse2; + c->biweight_h264_pixels_tab[2] = ff_h264_biweight_4_10_sse2; + + c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_10_sse2; + c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_10_sse2; +#if HAVE_ALIGNED_STACK + c->h264_v_loop_filter_luma = ff_deblock_v_luma_10_sse2; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_10_sse2; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_10_sse2; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_sse2; +#endif /* HAVE_ALIGNED_STACK */ + } + if (EXTERNAL_SSE4(mm_flags)) { + c->weight_h264_pixels_tab[0] = ff_h264_weight_16_10_sse4; + c->weight_h264_pixels_tab[1] = ff_h264_weight_8_10_sse4; + c->weight_h264_pixels_tab[2] = ff_h264_weight_4_10_sse4; + + c->biweight_h264_pixels_tab[0] = ff_h264_biweight_16_10_sse4; + c->biweight_h264_pixels_tab[1] = ff_h264_biweight_8_10_sse4; + c->biweight_h264_pixels_tab[2] = ff_h264_biweight_4_10_sse4; + } + if (EXTERNAL_AVX(mm_flags)) { + c->h264_idct_dc_add = + c->h264_idct_add = ff_h264_idct_add_10_avx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_add_10_avx; + + c->h264_idct_add16 = ff_h264_idct_add16_10_avx; + if (chroma_format_idc == 1) + c->h264_idct_add8 = ff_h264_idct_add8_10_avx; + c->h264_idct_add16intra = ff_h264_idct_add16intra_10_avx; +#if HAVE_ALIGNED_STACK + c->h264_idct8_add = ff_h264_idct8_add_10_avx; + c->h264_idct8_add4 = ff_h264_idct8_add4_10_avx; +#endif /* HAVE_ALIGNED_STACK */ + + c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_10_avx; + c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_10_avx; +#if HAVE_ALIGNED_STACK + c->h264_v_loop_filter_luma = ff_deblock_v_luma_10_avx; + c->h264_h_loop_filter_luma = ff_deblock_h_luma_10_avx; + c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_10_avx; + c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_avx; +#endif /* HAVE_ALIGNED_STACK */ + } + } + } + } +#endif +} diff --git a/ffmpeg/libavcodec/x86/hpeldsp.asm b/ffmpeg/libavcodec/x86/hpeldsp.asm new file mode 100644 index 0000000..1a572a3 --- /dev/null +++ b/ffmpeg/libavcodec/x86/hpeldsp.asm @@ -0,0 +1,461 @@ +;****************************************************************************** +;* +;* Copyright (c) 2000-2001 Fabrice Bellard +;* Copyright (c) Nick Kurshev +;* Copyright (c) 2002 Michael Niedermayer +;* Copyright (c) 2002 Zdenek Kabelac +;* Copyright (c) 2013 Daniel Kang +;* +;* MMX optimized hpel functions +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA +cextern pb_1 + +SECTION_TEXT + +; put_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_PIXELS8_X2 0 +cglobal put_pixels8_x2, 4,5 + lea r4, [r2*2] +.loop: + mova m0, [r1] + mova m1, [r1+r2] + PAVGB m0, [r1+1] + PAVGB m1, [r1+r2+1] + mova [r0], m0 + mova [r0+r2], m1 + add r1, r4 + add r0, r4 + mova m0, [r1] + mova m1, [r1+r2] + PAVGB m0, [r1+1] + PAVGB m1, [r1+r2+1] + add r1, r4 + mova [r0], m0 + mova [r0+r2], m1 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_PIXELS8_X2 +INIT_MMX 3dnow +PUT_PIXELS8_X2 + + +; put_pixels16_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_PIXELS_16 0 +cglobal put_pixels16_x2, 4,5 + lea r4, [r2*2] +.loop: + mova m0, [r1] + mova m1, [r1+r2] + mova m2, [r1+8] + mova m3, [r1+r2+8] + PAVGB m0, [r1+1] + PAVGB m1, [r1+r2+1] + PAVGB m2, [r1+9] + PAVGB m3, [r1+r2+9] + mova [r0], m0 + mova [r0+r2], m1 + mova [r0+8], m2 + mova [r0+r2+8], m3 + add r1, r4 + add r0, r4 + mova m0, [r1] + mova m1, [r1+r2] + mova m2, [r1+8] + mova m3, [r1+r2+8] + PAVGB m0, [r1+1] + PAVGB m1, [r1+r2+1] + PAVGB m2, [r1+9] + PAVGB m3, [r1+r2+9] + add r1, r4 + mova [r0], m0 + mova [r0+r2], m1 + mova [r0+8], m2 + mova [r0+r2+8], m3 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_PIXELS_16 +INIT_MMX 3dnow +PUT_PIXELS_16 + + +; put_no_rnd_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_NO_RND_PIXELS8_X2 0 +cglobal put_no_rnd_pixels8_x2, 4,5 + mova m6, [pb_1] + lea r4, [r2*2] +.loop: + mova m0, [r1] + mova m2, [r1+r2] + mova m1, [r1+1] + mova m3, [r1+r2+1] + add r1, r4 + psubusb m0, m6 + psubusb m2, m6 + PAVGB m0, m1 + PAVGB m2, m3 + mova [r0], m0 + mova [r0+r2], m2 + mova m0, [r1] + mova m1, [r1+1] + mova m2, [r1+r2] + mova m3, [r1+r2+1] + add r0, r4 + add r1, r4 + psubusb m0, m6 + psubusb m2, m6 + PAVGB m0, m1 + PAVGB m2, m3 + mova [r0], m0 + mova [r0+r2], m2 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_X2 +INIT_MMX 3dnow +PUT_NO_RND_PIXELS8_X2 + + +; put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_NO_RND_PIXELS8_X2_EXACT 0 +cglobal put_no_rnd_pixels8_x2_exact, 4,5 + lea r4, [r2*3] + pcmpeqb m6, m6 +.loop: + mova m0, [r1] + mova m2, [r1+r2] + mova m1, [r1+1] + mova m3, [r1+r2+1] + pxor m0, m6 + pxor m2, m6 + pxor m1, m6 + pxor m3, m6 + PAVGB m0, m1 + PAVGB m2, m3 + pxor m0, m6 + pxor m2, m6 + mova [r0], m0 + mova [r0+r2], m2 + mova m0, [r1+r2*2] + mova m1, [r1+r2*2+1] + mova m2, [r1+r4] + mova m3, [r1+r4+1] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m1 + PAVGB m2, m3 + pxor m0, m6 + pxor m2, m6 + mova [r0+r2*2], m0 + mova [r0+r4], m2 + lea r1, [r1+r2*4] + lea r0, [r0+r2*4] + sub r3d, 4 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_X2_EXACT +INIT_MMX 3dnow +PUT_NO_RND_PIXELS8_X2_EXACT + + +; put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_PIXELS8_Y2 0 +cglobal put_pixels8_y2, 4,5 + lea r4, [r2*2] + mova m0, [r1] + sub r0, r2 +.loop: + mova m1, [r1+r2] + mova m2, [r1+r4] + add r1, r4 + PAVGB m0, m1 + PAVGB m1, m2 + mova [r0+r2], m0 + mova [r0+r4], m1 + mova m1, [r1+r2] + mova m0, [r1+r4] + add r0, r4 + add r1, r4 + PAVGB m2, m1 + PAVGB m1, m0 + mova [r0+r2], m2 + mova [r0+r4], m1 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_PIXELS8_Y2 +INIT_MMX 3dnow +PUT_PIXELS8_Y2 + + +; put_no_rnd_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_NO_RND_PIXELS8_Y2 0 +cglobal put_no_rnd_pixels8_y2, 4,5 + mova m6, [pb_1] + lea r4, [r2+r2] + mova m0, [r1] + sub r0, r2 +.loop: + mova m1, [r1+r2] + mova m2, [r1+r4] + add r1, r4 + psubusb m1, m6 + PAVGB m0, m1 + PAVGB m1, m2 + mova [r0+r2], m0 + mova [r0+r4], m1 + mova m1, [r1+r2] + mova m0, [r1+r4] + add r0, r4 + add r1, r4 + psubusb m1, m6 + PAVGB m2, m1 + PAVGB m1, m0 + mova [r0+r2], m2 + mova [r0+r4], m1 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_Y2 +INIT_MMX 3dnow +PUT_NO_RND_PIXELS8_Y2 + + +; put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro PUT_NO_RND_PIXELS8_Y2_EXACT 0 +cglobal put_no_rnd_pixels8_y2_exact, 4,5 + lea r4, [r2*3] + mova m0, [r1] + pcmpeqb m6, m6 + add r1, r2 + pxor m0, m6 +.loop: + mova m1, [r1] + mova m2, [r1+r2] + pxor m1, m6 + pxor m2, m6 + PAVGB m0, m1 + PAVGB m1, m2 + pxor m0, m6 + pxor m1, m6 + mova [r0], m0 + mova [r0+r2], m1 + mova m1, [r1+r2*2] + mova m0, [r1+r4] + pxor m1, m6 + pxor m0, m6 + PAVGB m2, m1 + PAVGB m1, m0 + pxor m2, m6 + pxor m1, m6 + mova [r0+r2*2], m2 + mova [r0+r4], m1 + lea r1, [r1+r2*4] + lea r0, [r0+r2*4] + sub r3d, 4 + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_Y2_EXACT +INIT_MMX 3dnow +PUT_NO_RND_PIXELS8_Y2_EXACT + + +; avg_pixels8(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro AVG_PIXELS8 0 +cglobal avg_pixels8, 4,5 + lea r4, [r2*2] +.loop: + mova m0, [r0] + mova m1, [r0+r2] + PAVGB m0, [r1] + PAVGB m1, [r1+r2] + mova [r0], m0 + mova [r0+r2], m1 + add r1, r4 + add r0, r4 + mova m0, [r0] + mova m1, [r0+r2] + PAVGB m0, [r1] + PAVGB m1, [r1+r2] + add r1, r4 + mova [r0], m0 + mova [r0+r2], m1 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX 3dnow +AVG_PIXELS8 + + +; avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro AVG_PIXELS8_X2 0 +cglobal avg_pixels8_x2, 4,5 + lea r4, [r2*2] +.loop: + mova m0, [r1] + mova m2, [r1+r2] + PAVGB m0, [r1+1] + PAVGB m2, [r1+r2+1] + PAVGB m0, [r0] + PAVGB m2, [r0+r2] + add r1, r4 + mova [r0], m0 + mova [r0+r2], m2 + mova m0, [r1] + mova m2, [r1+r2] + PAVGB m0, [r1+1] + PAVGB m2, [r1+r2+1] + add r0, r4 + add r1, r4 + PAVGB m0, [r0] + PAVGB m2, [r0+r2] + mova [r0], m0 + mova [r0+r2], m2 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +AVG_PIXELS8_X2 +INIT_MMX 3dnow +AVG_PIXELS8_X2 + + +; avg_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro AVG_PIXELS8_Y2 0 +cglobal avg_pixels8_y2, 4,5 + lea r4, [r2*2] + mova m0, [r1] + sub r0, r2 +.loop: + mova m1, [r1+r2] + mova m2, [r1+r4] + add r1, r4 + PAVGB m0, m1 + PAVGB m1, m2 + mova m3, [r0+r2] + mova m4, [r0+r4] + PAVGB m0, m3 + PAVGB m1, m4 + mova [r0+r2], m0 + mova [r0+r4], m1 + mova m1, [r1+r2] + mova m0, [r1+r4] + PAVGB m2, m1 + PAVGB m1, m0 + add r0, r4 + add r1, r4 + mova m3, [r0+r2] + mova m4, [r0+r4] + PAVGB m2, m3 + PAVGB m1, m4 + mova [r0+r2], m2 + mova [r0+r4], m1 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +AVG_PIXELS8_Y2 +INIT_MMX 3dnow +AVG_PIXELS8_Y2 + + +; avg_pixels8_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +%macro AVG_PIXELS8_XY2 0 +cglobal avg_pixels8_xy2, 4,5 + mova m6, [pb_1] + lea r4, [r2*2] + mova m0, [r1] + pavgb m0, [r1+1] +.loop: + mova m2, [r1+r4] + mova m1, [r1+r2] + psubusb m2, m6 + pavgb m1, [r1+r2+1] + pavgb m2, [r1+r4+1] + add r1, r4 + pavgb m0, m1 + pavgb m1, m2 + pavgb m0, [r0] + pavgb m1, [r0+r2] + mova [r0], m0 + mova [r0+r2], m1 + mova m1, [r1+r2] + mova m0, [r1+r4] + pavgb m1, [r1+r2+1] + pavgb m0, [r1+r4+1] + add r0, r4 + add r1, r4 + pavgb m2, m1 + pavgb m1, m0 + pavgb m2, [r0] + pavgb m1, [r0+r2] + mova [r0], m2 + mova [r0+r2], m1 + add r0, r4 + sub r3d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +AVG_PIXELS8_XY2 +INIT_MMX 3dnow +AVG_PIXELS8_XY2 diff --git a/ffmpeg/libavcodec/x86/hpeldsp_avg_template.c b/ffmpeg/libavcodec/x86/hpeldsp_avg_template.c new file mode 100644 index 0000000..b9a8f83 --- /dev/null +++ b/ffmpeg/libavcodec/x86/hpeldsp_avg_template.c @@ -0,0 +1,77 @@ +/* + * DSP utils : average functions are compiled twice for 3dnow/mmxext + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * MMX optimization by Nick Kurshev + * mostly rewritten by Michael Niedermayer + * and improved by Zdenek Kabelac + * + * 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 + */ + +//FIXME the following could be optimized too ... +static void DEF(ff_put_no_rnd_pixels16_x2)(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_put_no_rnd_pixels8_x2)(block, pixels, line_size, h); + DEF(ff_put_no_rnd_pixels8_x2)(block + 8, pixels + 8, line_size, h); +} + +static void DEF(ff_put_pixels16_y2)(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_put_pixels8_y2)(block, pixels, line_size, h); + DEF(ff_put_pixels8_y2)(block + 8, pixels + 8, line_size, h); +} + +static void DEF(ff_put_no_rnd_pixels16_y2)(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_put_no_rnd_pixels8_y2)(block, pixels, line_size, h); + DEF(ff_put_no_rnd_pixels8_y2)(block + 8, pixels + 8, line_size, h); +} + +static void DEF(ff_avg_pixels16)(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_avg_pixels8)(block, pixels, line_size, h); + DEF(ff_avg_pixels8)(block + 8, pixels + 8, line_size, h); +} + +static void DEF(ff_avg_pixels16_x2)(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_avg_pixels8_x2)(block, pixels, line_size, h); + DEF(ff_avg_pixels8_x2)(block + 8, pixels + 8, line_size, h); +} + +static void DEF(ff_avg_pixels16_y2)(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_avg_pixels8_y2)(block, pixels, line_size, h); + DEF(ff_avg_pixels8_y2)(block + 8, pixels + 8, line_size, h); +} + +static void DEF(ff_avg_pixels16_xy2)(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + DEF(ff_avg_pixels8_xy2)(block, pixels, line_size, h); + DEF(ff_avg_pixels8_xy2)(block + 8, pixels + 8, line_size, h); +} diff --git a/ffmpeg/libavcodec/x86/hpeldsp_init.c b/ffmpeg/libavcodec/x86/hpeldsp_init.c new file mode 100644 index 0000000..4b877b8 --- /dev/null +++ b/ffmpeg/libavcodec/x86/hpeldsp_init.c @@ -0,0 +1,415 @@ +/* + * MMX optimized DSP utils + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 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 + * + * MMX optimization by Nick Kurshev + */ + +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/hpeldsp.h" +#include "dsputil_mmx.h" + +//#undef NDEBUG +//#include + +#if HAVE_YASM +void ff_put_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_x2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_x2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_exact_mmxext(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_exact_3dnow(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_exact_mmxext(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_exact_3dnow(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_xy2_mmxext(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels8_xy2_3dnow(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +#endif /* HAVE_YASM */ + + +#if HAVE_INLINE_ASM + +#define JUMPALIGN() __asm__ volatile (".p2align 3"::) +#define MOVQ_ZERO(regd) __asm__ volatile ("pxor %%"#regd", %%"#regd ::) + +#define MOVQ_BFE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "paddb %%"#regd", %%"#regd" \n\t" ::) + +#ifndef PIC +#define MOVQ_BONE(regd) __asm__ volatile ("movq %0, %%"#regd" \n\t" :: "m"(ff_bone)) +#define MOVQ_WTWO(regd) __asm__ volatile ("movq %0, %%"#regd" \n\t" :: "m"(ff_wtwo)) +#else +// for shared library it's better to use this way for accessing constants +// pcmpeqd -> -1 +#define MOVQ_BONE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "psrlw $15, %%"#regd" \n\t" \ + "packuswb %%"#regd", %%"#regd" \n\t" ::) + +#define MOVQ_WTWO(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "psrlw $15, %%"#regd" \n\t" \ + "psllw $1, %%"#regd" \n\t"::) + +#endif + +// using regr as temporary and for the output result +// first argument is unmodifed and second is trashed +// regfe is supposed to contain 0xfefefefefefefefe +#define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \ + "movq "#rega", "#regr" \n\t" \ + "pand "#regb", "#regr" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pand "#regfe", "#regb" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "paddb "#regb", "#regr" \n\t" + +#define PAVGB_MMX(rega, regb, regr, regfe) \ + "movq "#rega", "#regr" \n\t" \ + "por "#regb", "#regr" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pand "#regfe", "#regb" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psubb "#regb", "#regr" \n\t" + +// mm6 is supposed to contain 0xfefefefefefefefe +#define PAVGBP_MMX_NO_RND(rega, regb, regr, regc, regd, regp) \ + "movq "#rega", "#regr" \n\t" \ + "movq "#regc", "#regp" \n\t" \ + "pand "#regb", "#regr" \n\t" \ + "pand "#regd", "#regp" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pxor "#regc", "#regd" \n\t" \ + "pand %%mm6, "#regb" \n\t" \ + "pand %%mm6, "#regd" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psrlq $1, "#regd" \n\t" \ + "paddb "#regb", "#regr" \n\t" \ + "paddb "#regd", "#regp" \n\t" + +#define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \ + "movq "#rega", "#regr" \n\t" \ + "movq "#regc", "#regp" \n\t" \ + "por "#regb", "#regr" \n\t" \ + "por "#regd", "#regp" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pxor "#regc", "#regd" \n\t" \ + "pand %%mm6, "#regb" \n\t" \ + "pand %%mm6, "#regd" \n\t" \ + "psrlq $1, "#regd" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psubb "#regb", "#regr" \n\t" \ + "psubb "#regd", "#regp" \n\t" + +/***********************************/ +/* MMX no rounding */ +#define NO_RND 1 +#define DEF(x, y) x ## _no_rnd_ ## y ## _mmx +#define SET_RND MOVQ_WONE +#define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX_NO_RND(a, b, c, d, e, f) +#define PAVGB(a, b, c, e) PAVGB_MMX_NO_RND(a, b, c, e) +#define OP_AVG(a, b, c, e) PAVGB_MMX(a, b, c, e) + +#include "hpeldsp_rnd_template.c" + +#undef DEF +#undef SET_RND +#undef PAVGBP +#undef PAVGB +#undef NO_RND +/***********************************/ +/* MMX rounding */ + +#define DEF(x, y) x ## _ ## y ## _mmx +#define SET_RND MOVQ_WTWO +#define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX(a, b, c, d, e, f) +#define PAVGB(a, b, c, e) PAVGB_MMX(a, b, c, e) + +#include "hpeldsp_rnd_template.c" + +#undef DEF +#undef SET_RND +#undef PAVGBP +#undef PAVGB +#undef OP_AVG + +#endif /* HAVE_INLINE_ASM */ + + +#if HAVE_YASM +#define ff_put_pixels8_mmx ff_put_pixels8_mmxext + +/***********************************/ +/* 3Dnow specific */ + +#define DEF(x) x ## _3dnow + +#include "hpeldsp_avg_template.c" + +#undef DEF + +/***********************************/ +/* MMXEXT specific */ + +#define DEF(x) x ## _mmxext + +#include "hpeldsp_avg_template.c" + +#undef DEF + +#endif /* HAVE_YASM */ + + +#if HAVE_INLINE_ASM +#define put_no_rnd_pixels16_mmx put_pixels16_mmx +#define put_no_rnd_pixels8_mmx put_pixels8_mmx +#define put_pixels16_mmxext put_pixels16_mmx +#define put_pixels8_mmxext put_pixels8_mmx +#define put_pixels4_mmxext put_pixels4_mmx +#define put_no_rnd_pixels16_mmxext put_no_rnd_pixels16_mmx +#define put_no_rnd_pixels8_mmxext put_no_rnd_pixels8_mmx + +static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + __asm__ volatile ( + "lea (%3, %3), %%"REG_a" \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + : "+g"(h), "+r"(pixels), "+r"(block) + : "r"((x86_reg)line_size) + : "%"REG_a, "memory" + ); +} + +static void put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + __asm__ volatile ( + "lea (%3, %3), %%"REG_a" \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq 8(%1 ), %%mm4 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq 8(%1, %3), %%mm5 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm4, 8(%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "movq %%mm5, 8(%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1 ), %%mm0 \n\t" + "movq 8(%1 ), %%mm4 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq 8(%1, %3), %%mm5 \n\t" + "movq %%mm0, (%2) \n\t" + "movq %%mm4, 8(%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "movq %%mm5, 8(%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + : "+g"(h), "+r"(pixels), "+r"(block) + : "r"((x86_reg)line_size) + : "%"REG_a, "memory" + ); +} +#endif /* HAVE_INLINE_ASM */ + +void ff_put_pixels16_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_avg_pixels16_sse2(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); + +#define SET_HPEL_FUNCS(PFX, IDX, SIZE, CPU) \ + do { \ + c->PFX ## _pixels_tab IDX [0] = PFX ## _pixels ## SIZE ## _ ## CPU; \ + c->PFX ## _pixels_tab IDX [1] = PFX ## _pixels ## SIZE ## _x2_ ## CPU; \ + c->PFX ## _pixels_tab IDX [2] = PFX ## _pixels ## SIZE ## _y2_ ## CPU; \ + c->PFX ## _pixels_tab IDX [3] = PFX ## _pixels ## SIZE ## _xy2_ ## CPU; \ + } while (0) + +static void hpeldsp_init_mmx(HpelDSPContext *c, int flags, int mm_flags) +{ +#if HAVE_INLINE_ASM + SET_HPEL_FUNCS(put, [0], 16, mmx); + SET_HPEL_FUNCS(put_no_rnd, [0], 16, mmx); + SET_HPEL_FUNCS(avg, [0], 16, mmx); + SET_HPEL_FUNCS(avg_no_rnd, , 16, mmx); + SET_HPEL_FUNCS(put, [1], 8, mmx); + SET_HPEL_FUNCS(put_no_rnd, [1], 8, mmx); + SET_HPEL_FUNCS(avg, [1], 8, mmx); +#endif /* HAVE_INLINE_ASM */ +} + +static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags, int mm_flags) +{ +#if HAVE_YASM + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_mmxext; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_mmxext; + + c->avg_pixels_tab[0][0] = ff_avg_pixels16_mmxext; + c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_mmxext; + c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_mmxext; + + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_mmxext; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_mmxext; + + c->avg_pixels_tab[1][0] = ff_avg_pixels8_mmxext; + c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_mmxext; + c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_mmxext; + + if (!(flags & CODEC_FLAG_BITEXACT)) { + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_mmxext; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_mmxext; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_mmxext; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_mmxext; + + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_mmxext; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_mmxext; + } +#endif /* HAVE_YASM */ + +#if HAVE_MMXEXT_EXTERNAL + if (flags & CODEC_FLAG_BITEXACT && CONFIG_VP3_DECODER) { + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_mmxext; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_mmxext; + } +#endif /* HAVE_MMXEXT_EXTERNAL */ +} + +static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags, int mm_flags) +{ +#if HAVE_YASM + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_3dnow; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_3dnow; + + c->avg_pixels_tab[0][0] = ff_avg_pixels16_3dnow; + c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_3dnow; + c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_3dnow; + + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_3dnow; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_3dnow; + + c->avg_pixels_tab[1][0] = ff_avg_pixels8_3dnow; + c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_3dnow; + c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_3dnow; + + if (!(flags & CODEC_FLAG_BITEXACT)){ + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_3dnow; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_3dnow; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_3dnow; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_3dnow; + + c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_3dnow; + c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_3dnow; + } + + if (flags & CODEC_FLAG_BITEXACT && CONFIG_VP3_DECODER) { + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_3dnow; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_3dnow; + } +#endif /* HAVE_YASM */ +} + +static void hpeldsp_init_sse2(HpelDSPContext *c, int flags, int mm_flags) +{ +#if HAVE_SSE2_EXTERNAL + if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW)) { + // these functions are slower than mmx on AMD, but faster on Intel + c->put_pixels_tab[0][0] = ff_put_pixels16_sse2; + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_sse2; + c->avg_pixels_tab[0][0] = ff_avg_pixels16_sse2; + } +#endif /* HAVE_SSE2_EXTERNAL */ +} + +void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags) +{ + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_MMX) + hpeldsp_init_mmx(c, flags, mm_flags); + + if (mm_flags & AV_CPU_FLAG_MMXEXT) + hpeldsp_init_mmxext(c, flags, mm_flags); + + if (mm_flags & AV_CPU_FLAG_3DNOW) + hpeldsp_init_3dnow(c, flags, mm_flags); + + if (mm_flags & AV_CPU_FLAG_SSE2) + hpeldsp_init_sse2(c, flags, mm_flags); +} diff --git a/ffmpeg/libavcodec/x86/hpeldsp_rnd_template.c b/ffmpeg/libavcodec/x86/hpeldsp_rnd_template.c new file mode 100644 index 0000000..07de675 --- /dev/null +++ b/ffmpeg/libavcodec/x86/hpeldsp_rnd_template.c @@ -0,0 +1,428 @@ +/* + * DSP utils mmx functions are compiled twice for rnd/no_rnd + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003-2004 Michael Niedermayer + * + * MMX optimization by Nick Kurshev + * mostly rewritten by Michael Niedermayer + * and improved by Zdenek Kabelac + * + * 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 + */ + +// put_pixels +static void DEF(put, pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + __asm__ volatile( + "lea (%3, %3), %%"REG_a" \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm1 \n\t" + "movq (%1, %3), %%mm2 \n\t" + "movq 1(%1, %3), %%mm3 \n\t" + PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, (%2) \n\t" + "movq %%mm5, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm1 \n\t" + "movq (%1, %3), %%mm2 \n\t" + "movq 1(%1, %3), %%mm3 \n\t" + PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, (%2) \n\t" + "movq %%mm5, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels), "+D"(block) + :"r"((x86_reg)line_size) + :REG_a, "memory"); +} + +static void DEF(put, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + __asm__ volatile( + "lea (%3, %3), %%"REG_a" \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm1 \n\t" + "movq (%1, %3), %%mm2 \n\t" + "movq 1(%1, %3), %%mm3 \n\t" + PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, (%2) \n\t" + "movq %%mm5, (%2, %3) \n\t" + "movq 8(%1), %%mm0 \n\t" + "movq 9(%1), %%mm1 \n\t" + "movq 8(%1, %3), %%mm2 \n\t" + "movq 9(%1, %3), %%mm3 \n\t" + PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, 8(%2) \n\t" + "movq %%mm5, 8(%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm1 \n\t" + "movq (%1, %3), %%mm2 \n\t" + "movq 1(%1, %3), %%mm3 \n\t" + PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, (%2) \n\t" + "movq %%mm5, (%2, %3) \n\t" + "movq 8(%1), %%mm0 \n\t" + "movq 9(%1), %%mm1 \n\t" + "movq 8(%1, %3), %%mm2 \n\t" + "movq 9(%1, %3), %%mm3 \n\t" + PAVGBP(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, 8(%2) \n\t" + "movq %%mm5, 8(%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels), "+D"(block) + :"r"((x86_reg)line_size) + :REG_a, "memory"); +} + +static void DEF(put, pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + __asm__ volatile( + "lea (%3, %3), %%"REG_a" \n\t" + "movq (%1), %%mm0 \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq (%1, %%"REG_a"),%%mm2 \n\t" + PAVGBP(%%mm1, %%mm0, %%mm4, %%mm2, %%mm1, %%mm5) + "movq %%mm4, (%2) \n\t" + "movq %%mm5, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq (%1, %%"REG_a"),%%mm0 \n\t" + PAVGBP(%%mm1, %%mm2, %%mm4, %%mm0, %%mm1, %%mm5) + "movq %%mm4, (%2) \n\t" + "movq %%mm5, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels), "+D"(block) + :"r"((x86_reg)line_size) + :REG_a, "memory"); +} + +static void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_ZERO(mm7); + SET_RND(mm6); // =2 for rnd and =1 for no_rnd version + __asm__ volatile( + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm4 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "xor %%"REG_a", %%"REG_a" \n\t" + "add %3, %1 \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm2, %%mm3 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "paddusw %%mm2, %%mm0 \n\t" + "paddusw %%mm3, %%mm1 \n\t" + "paddusw %%mm6, %%mm4 \n\t" + "paddusw %%mm6, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "psrlw $2, %%mm4 \n\t" + "psrlw $2, %%mm5 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "movq %%mm4, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3 + "movq 1(%1, %%"REG_a"), %%mm4 \n\t" + "movq %%mm2, %%mm3 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm2, %%mm4 \n\t" + "paddusw %%mm3, %%mm5 \n\t" + "paddusw %%mm6, %%mm0 \n\t" + "paddusw %%mm6, %%mm1 \n\t" + "paddusw %%mm4, %%mm0 \n\t" + "paddusw %%mm5, %%mm1 \n\t" + "psrlw $2, %%mm0 \n\t" + "psrlw $2, %%mm1 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "movq %%mm0, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "subl $2, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels) + :"D"(block), "r"((x86_reg)line_size) + :REG_a, "memory"); +} + +// avg_pixels +#ifndef NO_RND +// in case more speed is needed - unroling would certainly help +static void DEF(avg, pixels8)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + JUMPALIGN(); + do { + __asm__ volatile( + "movq %0, %%mm0 \n\t" + "movq %1, %%mm1 \n\t" + OP_AVG(%%mm0, %%mm1, %%mm2, %%mm6) + "movq %%mm2, %0 \n\t" + :"+m"(*block) + :"m"(*pixels) + :"memory"); + pixels += line_size; + block += line_size; + } + while (--h); +} +#endif // NO_RND + +static void DEF(avg, pixels16)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + JUMPALIGN(); + do { + __asm__ volatile( + "movq %0, %%mm0 \n\t" + "movq %1, %%mm1 \n\t" + OP_AVG(%%mm0, %%mm1, %%mm2, %%mm6) + "movq %%mm2, %0 \n\t" + "movq 8%0, %%mm0 \n\t" + "movq 8%1, %%mm1 \n\t" + OP_AVG(%%mm0, %%mm1, %%mm2, %%mm6) + "movq %%mm2, 8%0 \n\t" + :"+m"(*block) + :"m"(*pixels) + :"memory"); + pixels += line_size; + block += line_size; + } + while (--h); +} + +#ifndef NO_RND +static void DEF(avg, pixels8_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + JUMPALIGN(); + do { + __asm__ volatile( + "movq %1, %%mm0 \n\t" + "movq 1%1, %%mm1 \n\t" + "movq %0, %%mm3 \n\t" + PAVGB(%%mm0, %%mm1, %%mm2, %%mm6) + OP_AVG(%%mm3, %%mm2, %%mm0, %%mm6) + "movq %%mm0, %0 \n\t" + :"+m"(*block) + :"m"(*pixels) + :"memory"); + pixels += line_size; + block += line_size; + } while (--h); +} +#endif // NO_RND + +static void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + JUMPALIGN(); + do { + __asm__ volatile( + "movq %1, %%mm0 \n\t" + "movq 1%1, %%mm1 \n\t" + "movq %0, %%mm3 \n\t" + PAVGB(%%mm0, %%mm1, %%mm2, %%mm6) + OP_AVG(%%mm3, %%mm2, %%mm0, %%mm6) + "movq %%mm0, %0 \n\t" + "movq 8%1, %%mm0 \n\t" + "movq 9%1, %%mm1 \n\t" + "movq 8%0, %%mm3 \n\t" + PAVGB(%%mm0, %%mm1, %%mm2, %%mm6) + OP_AVG(%%mm3, %%mm2, %%mm0, %%mm6) + "movq %%mm0, 8%0 \n\t" + :"+m"(*block) + :"m"(*pixels) + :"memory"); + pixels += line_size; + block += line_size; + } while (--h); +} + +static void DEF(avg, pixels8_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_BFE(mm6); + __asm__ volatile( + "lea (%3, %3), %%"REG_a" \n\t" + "movq (%1), %%mm0 \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1, %3), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm2 \n\t" + PAVGBP(%%mm1, %%mm0, %%mm4, %%mm2, %%mm1, %%mm5) + "movq (%2), %%mm3 \n\t" + OP_AVG(%%mm3, %%mm4, %%mm0, %%mm6) + "movq (%2, %3), %%mm3 \n\t" + OP_AVG(%%mm3, %%mm5, %%mm1, %%mm6) + "movq %%mm0, (%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + + "movq (%1, %3), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + PAVGBP(%%mm1, %%mm2, %%mm4, %%mm0, %%mm1, %%mm5) + "movq (%2), %%mm3 \n\t" + OP_AVG(%%mm3, %%mm4, %%mm2, %%mm6) + "movq (%2, %3), %%mm3 \n\t" + OP_AVG(%%mm3, %%mm5, %%mm1, %%mm6) + "movq %%mm2, (%2) \n\t" + "movq %%mm1, (%2, %3) \n\t" + "add %%"REG_a", %1 \n\t" + "add %%"REG_a", %2 \n\t" + + "subl $4, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels), "+D"(block) + :"r"((x86_reg)line_size) + :REG_a, "memory"); +} + +// this routine is 'slightly' suboptimal but mostly unused +static void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) +{ + MOVQ_ZERO(mm7); + SET_RND(mm6); // =2 for rnd and =1 for no_rnd version + __asm__ volatile( + "movq (%1), %%mm0 \n\t" + "movq 1(%1), %%mm4 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "xor %%"REG_a", %%"REG_a" \n\t" + "add %3, %1 \n\t" + ".p2align 3 \n\t" + "1: \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm2, %%mm3 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "paddusw %%mm2, %%mm0 \n\t" + "paddusw %%mm3, %%mm1 \n\t" + "paddusw %%mm6, %%mm4 \n\t" + "paddusw %%mm6, %%mm5 \n\t" + "paddusw %%mm0, %%mm4 \n\t" + "paddusw %%mm1, %%mm5 \n\t" + "psrlw $2, %%mm4 \n\t" + "psrlw $2, %%mm5 \n\t" + "movq (%2, %%"REG_a"), %%mm3 \n\t" + "packuswb %%mm5, %%mm4 \n\t" + "pcmpeqd %%mm2, %%mm2 \n\t" + "paddb %%mm2, %%mm2 \n\t" + OP_AVG(%%mm3, %%mm4, %%mm5, %%mm2) + "movq %%mm5, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "movq (%1, %%"REG_a"), %%mm2 \n\t" // 0 <-> 2 1 <-> 3 + "movq 1(%1, %%"REG_a"), %%mm4 \n\t" + "movq %%mm2, %%mm3 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddusw %%mm2, %%mm4 \n\t" + "paddusw %%mm3, %%mm5 \n\t" + "paddusw %%mm6, %%mm0 \n\t" + "paddusw %%mm6, %%mm1 \n\t" + "paddusw %%mm4, %%mm0 \n\t" + "paddusw %%mm5, %%mm1 \n\t" + "psrlw $2, %%mm0 \n\t" + "psrlw $2, %%mm1 \n\t" + "movq (%2, %%"REG_a"), %%mm3 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "pcmpeqd %%mm2, %%mm2 \n\t" + "paddb %%mm2, %%mm2 \n\t" + OP_AVG(%%mm3, %%mm0, %%mm1, %%mm2) + "movq %%mm1, (%2, %%"REG_a") \n\t" + "add %3, %%"REG_a" \n\t" + + "subl $2, %0 \n\t" + "jnz 1b \n\t" + :"+g"(h), "+S"(pixels) + :"D"(block), "r"((x86_reg)line_size) + :REG_a, "memory"); +} + +//FIXME optimize +static void DEF(put, pixels16_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){ + DEF(put, pixels8_y2)(block , pixels , line_size, h); + DEF(put, pixels8_y2)(block+8, pixels+8, line_size, h); +} + +static void DEF(put, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){ + DEF(put, pixels8_xy2)(block , pixels , line_size, h); + DEF(put, pixels8_xy2)(block+8, pixels+8, line_size, h); +} + +static void DEF(avg, pixels16_y2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){ + DEF(avg, pixels8_y2)(block , pixels , line_size, h); + DEF(avg, pixels8_y2)(block+8, pixels+8, line_size, h); +} + +static void DEF(avg, pixels16_xy2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h){ + DEF(avg, pixels8_xy2)(block , pixels , line_size, h); + DEF(avg, pixels8_xy2)(block+8, pixels+8, line_size, h); +} diff --git a/ffmpeg/libavcodec/x86/idct_mmx_xvid.c b/ffmpeg/libavcodec/x86/idct_mmx_xvid.c new file mode 100644 index 0000000..5e9f405 --- /dev/null +++ b/ffmpeg/libavcodec/x86/idct_mmx_xvid.c @@ -0,0 +1,558 @@ +/* + * XVID MPEG-4 VIDEO CODEC + * - MMX and XMM forward discrete cosine transform - + * + * Copyright(C) 2001 Peter Ross + * + * Originally provided by Intel at AP-922 + * http://developer.intel.com/vtune/cbts/strmsimd/922down.htm + * (See more app notes at http://developer.intel.com/vtune/cbts/strmsimd/appnotes.htm) + * but in a limited edition. + * New macro implements a column part for precise iDCT + * The routine precision now satisfies IEEE standard 1180-1990. + * + * Copyright(C) 2000-2001 Peter Gubanov + * Rounding trick Copyright(C) 2000 Michel Lespinasse + * + * http://www.elecard.com/peter/idct.html + * http://www.linuxvideo.org/mpeg2dec/ + * + * These examples contain code fragments for first stage iDCT 8x8 + * (for rows) and first stage DCT 8x8 (for columns) + * + * conversion to gcc syntax 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 "libavcodec/avcodec.h" +#include "libavutil/mem.h" +#include "dsputil_mmx.h" +#include "idct_xvid.h" + +#if HAVE_INLINE_ASM + +//============================================================================= +// Macros and other preprocessor constants +//============================================================================= + +#define BITS_INV_ACC 5 // 4 or 5 for IEEE +#define SHIFT_INV_ROW (16 - BITS_INV_ACC) //11 +#define SHIFT_INV_COL (1 + BITS_INV_ACC) //6 +#define RND_INV_ROW (1024 * (6 - BITS_INV_ACC)) +#define RND_INV_COL (16 * (BITS_INV_ACC - 3)) +#define RND_INV_CORR (RND_INV_COL - 1) + +#define BITS_FRW_ACC 3 // 2 or 3 for accuracy +#define SHIFT_FRW_COL BITS_FRW_ACC +#define SHIFT_FRW_ROW (BITS_FRW_ACC + 17) +#define RND_FRW_ROW (262144*(BITS_FRW_ACC - 1)) + + +//----------------------------------------------------------------------------- +// Various memory constants (trigonometric values or rounding values) +//----------------------------------------------------------------------------- + + +DECLARE_ALIGNED(8, static const int16_t, tg_1_16)[4*4] = { + 13036,13036,13036,13036, // tg * (2<<16) + 0.5 + 27146,27146,27146,27146, // tg * (2<<16) + 0.5 + -21746,-21746,-21746,-21746, // tg * (2<<16) + 0.5 + 23170,23170,23170,23170}; // cos * (2<<15) + 0.5 + +DECLARE_ALIGNED(8, static const int32_t, rounder_0)[2*8] = { + 65536,65536, + 3597,3597, + 2260,2260, + 1203,1203, + 0,0, + 120,120, + 512,512, + 512,512}; + +//----------------------------------------------------------------------------- +// +// The first stage iDCT 8x8 - inverse DCTs of rows +// +//----------------------------------------------------------------------------- +// The 8-point inverse DCT direct algorithm +//----------------------------------------------------------------------------- +// +// static const short w[32] = { +// FIX(cos_4_16), FIX(cos_2_16), FIX(cos_4_16), FIX(cos_6_16), +// FIX(cos_4_16), FIX(cos_6_16), -FIX(cos_4_16), -FIX(cos_2_16), +// FIX(cos_4_16), -FIX(cos_6_16), -FIX(cos_4_16), FIX(cos_2_16), +// FIX(cos_4_16), -FIX(cos_2_16), FIX(cos_4_16), -FIX(cos_6_16), +// FIX(cos_1_16), FIX(cos_3_16), FIX(cos_5_16), FIX(cos_7_16), +// FIX(cos_3_16), -FIX(cos_7_16), -FIX(cos_1_16), -FIX(cos_5_16), +// FIX(cos_5_16), -FIX(cos_1_16), FIX(cos_7_16), FIX(cos_3_16), +// FIX(cos_7_16), -FIX(cos_5_16), FIX(cos_3_16), -FIX(cos_1_16) }; +// +// #define DCT_8_INV_ROW(x, y) +// { +// int a0, a1, a2, a3, b0, b1, b2, b3; +// +// a0 =x[0]*w[0]+x[2]*w[1]+x[4]*w[2]+x[6]*w[3]; +// a1 =x[0]*w[4]+x[2]*w[5]+x[4]*w[6]+x[6]*w[7]; +// a2 = x[0] * w[ 8] + x[2] * w[ 9] + x[4] * w[10] + x[6] * w[11]; +// a3 = x[0] * w[12] + x[2] * w[13] + x[4] * w[14] + x[6] * w[15]; +// b0 = x[1] * w[16] + x[3] * w[17] + x[5] * w[18] + x[7] * w[19]; +// b1 = x[1] * w[20] + x[3] * w[21] + x[5] * w[22] + x[7] * w[23]; +// b2 = x[1] * w[24] + x[3] * w[25] + x[5] * w[26] + x[7] * w[27]; +// b3 = x[1] * w[28] + x[3] * w[29] + x[5] * w[30] + x[7] * w[31]; +// +// y[0] = SHIFT_ROUND ( a0 + b0 ); +// y[1] = SHIFT_ROUND ( a1 + b1 ); +// y[2] = SHIFT_ROUND ( a2 + b2 ); +// y[3] = SHIFT_ROUND ( a3 + b3 ); +// y[4] = SHIFT_ROUND ( a3 - b3 ); +// y[5] = SHIFT_ROUND ( a2 - b2 ); +// y[6] = SHIFT_ROUND ( a1 - b1 ); +// y[7] = SHIFT_ROUND ( a0 - b0 ); +// } +// +//----------------------------------------------------------------------------- +// +// In this implementation the outputs of the iDCT-1D are multiplied +// for rows 0,4 - by cos_4_16, +// for rows 1,7 - by cos_1_16, +// for rows 2,6 - by cos_2_16, +// for rows 3,5 - by cos_3_16 +// and are shifted to the left for better accuracy +// +// For the constants used, +// FIX(float_const) = (short) (float_const * (1<<15) + 0.5) +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Tables for mmx processors +//----------------------------------------------------------------------------- + +// Table for rows 0,4 - constants are multiplied by cos_4_16 +DECLARE_ALIGNED(8, static const int16_t, tab_i_04_mmx)[32*4] = { + 16384,16384,16384,-16384, // movq-> w06 w04 w02 w00 + 21407,8867,8867,-21407, // w07 w05 w03 w01 + 16384,-16384,16384,16384, // w14 w12 w10 w08 + -8867,21407,-21407,-8867, // w15 w13 w11 w09 + 22725,12873,19266,-22725, // w22 w20 w18 w16 + 19266,4520,-4520,-12873, // w23 w21 w19 w17 + 12873,4520,4520,19266, // w30 w28 w26 w24 + -22725,19266,-12873,-22725, // w31 w29 w27 w25 +// Table for rows 1,7 - constants are multiplied by cos_1_16 + 22725,22725,22725,-22725, // movq-> w06 w04 w02 w00 + 29692,12299,12299,-29692, // w07 w05 w03 w01 + 22725,-22725,22725,22725, // w14 w12 w10 w08 + -12299,29692,-29692,-12299, // w15 w13 w11 w09 + 31521,17855,26722,-31521, // w22 w20 w18 w16 + 26722,6270,-6270,-17855, // w23 w21 w19 w17 + 17855,6270,6270,26722, // w30 w28 w26 w24 + -31521,26722,-17855,-31521, // w31 w29 w27 w25 +// Table for rows 2,6 - constants are multiplied by cos_2_16 + 21407,21407,21407,-21407, // movq-> w06 w04 w02 w00 + 27969,11585,11585,-27969, // w07 w05 w03 w01 + 21407,-21407,21407,21407, // w14 w12 w10 w08 + -11585,27969,-27969,-11585, // w15 w13 w11 w09 + 29692,16819,25172,-29692, // w22 w20 w18 w16 + 25172,5906,-5906,-16819, // w23 w21 w19 w17 + 16819,5906,5906,25172, // w30 w28 w26 w24 + -29692,25172,-16819,-29692, // w31 w29 w27 w25 +// Table for rows 3,5 - constants are multiplied by cos_3_16 + 19266,19266,19266,-19266, // movq-> w06 w04 w02 w00 + 25172,10426,10426,-25172, // w07 w05 w03 w01 + 19266,-19266,19266,19266, // w14 w12 w10 w08 + -10426,25172,-25172,-10426, // w15 w13 w11 w09 + 26722,15137,22654,-26722, // w22 w20 w18 w16 + 22654,5315,-5315,-15137, // w23 w21 w19 w17 + 15137,5315,5315,22654, // w30 w28 w26 w24 + -26722,22654,-15137,-26722, // w31 w29 w27 w25 +}; +//----------------------------------------------------------------------------- +// Tables for xmm processors +//----------------------------------------------------------------------------- + +// %3 for rows 0,4 - constants are multiplied by cos_4_16 +DECLARE_ALIGNED(8, static const int16_t, tab_i_04_xmm)[32*4] = { + 16384,21407,16384,8867, // movq-> w05 w04 w01 w00 + 16384,8867,-16384,-21407, // w07 w06 w03 w02 + 16384,-8867,16384,-21407, // w13 w12 w09 w08 + -16384,21407,16384,-8867, // w15 w14 w11 w10 + 22725,19266,19266,-4520, // w21 w20 w17 w16 + 12873,4520,-22725,-12873, // w23 w22 w19 w18 + 12873,-22725,4520,-12873, // w29 w28 w25 w24 + 4520,19266,19266,-22725, // w31 w30 w27 w26 +// %3 for rows 1,7 - constants are multiplied by cos_1_16 + 22725,29692,22725,12299, // movq-> w05 w04 w01 w00 + 22725,12299,-22725,-29692, // w07 w06 w03 w02 + 22725,-12299,22725,-29692, // w13 w12 w09 w08 + -22725,29692,22725,-12299, // w15 w14 w11 w10 + 31521,26722,26722,-6270, // w21 w20 w17 w16 + 17855,6270,-31521,-17855, // w23 w22 w19 w18 + 17855,-31521,6270,-17855, // w29 w28 w25 w24 + 6270,26722,26722,-31521, // w31 w30 w27 w26 +// %3 for rows 2,6 - constants are multiplied by cos_2_16 + 21407,27969,21407,11585, // movq-> w05 w04 w01 w00 + 21407,11585,-21407,-27969, // w07 w06 w03 w02 + 21407,-11585,21407,-27969, // w13 w12 w09 w08 + -21407,27969,21407,-11585, // w15 w14 w11 w10 + 29692,25172,25172,-5906, // w21 w20 w17 w16 + 16819,5906,-29692,-16819, // w23 w22 w19 w18 + 16819,-29692,5906,-16819, // w29 w28 w25 w24 + 5906,25172,25172,-29692, // w31 w30 w27 w26 +// %3 for rows 3,5 - constants are multiplied by cos_3_16 + 19266,25172,19266,10426, // movq-> w05 w04 w01 w00 + 19266,10426,-19266,-25172, // w07 w06 w03 w02 + 19266,-10426,19266,-25172, // w13 w12 w09 w08 + -19266,25172,19266,-10426, // w15 w14 w11 w10 + 26722,22654,22654,-5315, // w21 w20 w17 w16 + 15137,5315,-26722,-15137, // w23 w22 w19 w18 + 15137,-26722,5315,-15137, // w29 w28 w25 w24 + 5315,22654,22654,-26722, // w31 w30 w27 w26 +}; +//============================================================================= +// Helper macros for the code +//============================================================================= + +//----------------------------------------------------------------------------- +// DCT_8_INV_ROW_MMX( INP, OUT, TABLE, ROUNDER +//----------------------------------------------------------------------------- + +#define DCT_8_INV_ROW_MMX(A1,A2,A3,A4)\ + "movq " #A1 ",%%mm0 \n\t"/* 0 ; x3 x2 x1 x0*/\ + "movq 8+" #A1 ",%%mm1 \n\t"/* 1 ; x7 x6 x5 x4*/\ + "movq %%mm0,%%mm2 \n\t"/* 2 ; x3 x2 x1 x0*/\ + "movq " #A3 ",%%mm3 \n\t"/* 3 ; w06 w04 w02 w00*/\ + "punpcklwd %%mm1,%%mm0 \n\t"/* x5 x1 x4 x0*/\ + "movq %%mm0,%%mm5 \n\t"/* 5 ; x5 x1 x4 x0*/\ + "punpckldq %%mm0,%%mm0 \n\t"/* x4 x0 x4 x0*/\ + "movq 8+" #A3 ",%%mm4 \n\t"/* 4 ; w07 w05 w03 w01*/\ + "punpckhwd %%mm1,%%mm2 \n\t"/* 1 ; x7 x3 x6 x2*/\ + "pmaddwd %%mm0,%%mm3 \n\t"/* x4*w06+x0*w04 x4*w02+x0*w00*/\ + "movq %%mm2,%%mm6 \n\t"/* 6 ; x7 x3 x6 x2*/\ + "movq 32+" #A3 ",%%mm1 \n\t"/* 1 ; w22 w20 w18 w16*/\ + "punpckldq %%mm2,%%mm2 \n\t"/* x6 x2 x6 x2*/\ + "pmaddwd %%mm2,%%mm4 \n\t"/* x6*w07+x2*w05 x6*w03+x2*w01*/\ + "punpckhdq %%mm5,%%mm5 \n\t"/* x5 x1 x5 x1*/\ + "pmaddwd 16+" #A3 ",%%mm0 \n\t"/* x4*w14+x0*w12 x4*w10+x0*w08*/\ + "punpckhdq %%mm6,%%mm6 \n\t"/* x7 x3 x7 x3*/\ + "movq 40+" #A3 ",%%mm7 \n\t"/* 7 ; w23 w21 w19 w17*/\ + "pmaddwd %%mm5,%%mm1 \n\t"/* x5*w22+x1*w20 x5*w18+x1*w16*/\ + "paddd " #A4 ",%%mm3 \n\t"/* +%4*/\ + "pmaddwd %%mm6,%%mm7 \n\t"/* x7*w23+x3*w21 x7*w19+x3*w17*/\ + "pmaddwd 24+" #A3 ",%%mm2 \n\t"/* x6*w15+x2*w13 x6*w11+x2*w09*/\ + "paddd %%mm4,%%mm3 \n\t"/* 4 ; a1=sum(even1) a0=sum(even0)*/\ + "pmaddwd 48+" #A3 ",%%mm5 \n\t"/* x5*w30+x1*w28 x5*w26+x1*w24*/\ + "movq %%mm3,%%mm4 \n\t"/* 4 ; a1 a0*/\ + "pmaddwd 56+" #A3 ",%%mm6 \n\t"/* x7*w31+x3*w29 x7*w27+x3*w25*/\ + "paddd %%mm7,%%mm1 \n\t"/* 7 ; b1=sum(odd1) b0=sum(odd0)*/\ + "paddd " #A4 ",%%mm0 \n\t"/* +%4*/\ + "psubd %%mm1,%%mm3 \n\t"/* a1-b1 a0-b0*/\ + "psrad $11,%%mm3 \n\t"/* y6=a1-b1 y7=a0-b0*/\ + "paddd %%mm4,%%mm1 \n\t"/* 4 ; a1+b1 a0+b0*/\ + "paddd %%mm2,%%mm0 \n\t"/* 2 ; a3=sum(even3) a2=sum(even2)*/\ + "psrad $11,%%mm1 \n\t"/* y1=a1+b1 y0=a0+b0*/\ + "paddd %%mm6,%%mm5 \n\t"/* 6 ; b3=sum(odd3) b2=sum(odd2)*/\ + "movq %%mm0,%%mm4 \n\t"/* 4 ; a3 a2*/\ + "paddd %%mm5,%%mm0 \n\t"/* a3+b3 a2+b2*/\ + "psubd %%mm5,%%mm4 \n\t"/* 5 ; a3-b3 a2-b2*/\ + "psrad $11,%%mm0 \n\t"/* y3=a3+b3 y2=a2+b2*/\ + "psrad $11,%%mm4 \n\t"/* y4=a3-b3 y5=a2-b2*/\ + "packssdw %%mm0,%%mm1 \n\t"/* 0 ; y3 y2 y1 y0*/\ + "packssdw %%mm3,%%mm4 \n\t"/* 3 ; y6 y7 y4 y5*/\ + "movq %%mm4,%%mm7 \n\t"/* 7 ; y6 y7 y4 y5*/\ + "psrld $16,%%mm4 \n\t"/* 0 y6 0 y4*/\ + "pslld $16,%%mm7 \n\t"/* y7 0 y5 0*/\ + "movq %%mm1," #A2 " \n\t"/* 1 ; save y3 y2 y1 y0*/\ + "por %%mm4,%%mm7 \n\t"/* 4 ; y7 y6 y5 y4*/\ + "movq %%mm7,8 +" #A2 "\n\t"/* 7 ; save y7 y6 y5 y4*/\ + + +//----------------------------------------------------------------------------- +// DCT_8_INV_ROW_XMM( INP, OUT, TABLE, ROUNDER +//----------------------------------------------------------------------------- + +#define DCT_8_INV_ROW_XMM(A1,A2,A3,A4)\ + "movq " #A1 ",%%mm0 \n\t"/* 0 ; x3 x2 x1 x0*/\ + "movq 8+" #A1 ",%%mm1 \n\t"/* 1 ; x7 x6 x5 x4*/\ + "movq %%mm0,%%mm2 \n\t"/* 2 ; x3 x2 x1 x0*/\ + "movq " #A3 ",%%mm3 \n\t"/* 3 ; w05 w04 w01 w00*/\ + "pshufw $0x88,%%mm0,%%mm0 \n\t"/* x2 x0 x2 x0*/\ + "movq 8+" #A3 ",%%mm4 \n\t"/* 4 ; w07 w06 w03 w02*/\ + "movq %%mm1,%%mm5 \n\t"/* 5 ; x7 x6 x5 x4*/\ + "pmaddwd %%mm0,%%mm3 \n\t"/* x2*w05+x0*w04 x2*w01+x0*w00*/\ + "movq 32+" #A3 ",%%mm6 \n\t"/* 6 ; w21 w20 w17 w16*/\ + "pshufw $0x88,%%mm1,%%mm1 \n\t"/* x6 x4 x6 x4*/\ + "pmaddwd %%mm1,%%mm4 \n\t"/* x6*w07+x4*w06 x6*w03+x4*w02*/\ + "movq 40+" #A3 ",%%mm7 \n\t"/* 7 ; w23 w22 w19 w18*/\ + "pshufw $0xdd,%%mm2,%%mm2 \n\t"/* x3 x1 x3 x1*/\ + "pmaddwd %%mm2,%%mm6 \n\t"/* x3*w21+x1*w20 x3*w17+x1*w16*/\ + "pshufw $0xdd,%%mm5,%%mm5 \n\t"/* x7 x5 x7 x5*/\ + "pmaddwd %%mm5,%%mm7 \n\t"/* x7*w23+x5*w22 x7*w19+x5*w18*/\ + "paddd " #A4 ",%%mm3 \n\t"/* +%4*/\ + "pmaddwd 16+" #A3 ",%%mm0 \n\t"/* x2*w13+x0*w12 x2*w09+x0*w08*/\ + "paddd %%mm4,%%mm3 \n\t"/* 4 ; a1=sum(even1) a0=sum(even0)*/\ + "pmaddwd 24+" #A3 ",%%mm1 \n\t"/* x6*w15+x4*w14 x6*w11+x4*w10*/\ + "movq %%mm3,%%mm4 \n\t"/* 4 ; a1 a0*/\ + "pmaddwd 48+" #A3 ",%%mm2 \n\t"/* x3*w29+x1*w28 x3*w25+x1*w24*/\ + "paddd %%mm7,%%mm6 \n\t"/* 7 ; b1=sum(odd1) b0=sum(odd0)*/\ + "pmaddwd 56+" #A3 ",%%mm5 \n\t"/* x7*w31+x5*w30 x7*w27+x5*w26*/\ + "paddd %%mm6,%%mm3 \n\t"/* a1+b1 a0+b0*/\ + "paddd " #A4 ",%%mm0 \n\t"/* +%4*/\ + "psrad $11,%%mm3 \n\t"/* y1=a1+b1 y0=a0+b0*/\ + "paddd %%mm1,%%mm0 \n\t"/* 1 ; a3=sum(even3) a2=sum(even2)*/\ + "psubd %%mm6,%%mm4 \n\t"/* 6 ; a1-b1 a0-b0*/\ + "movq %%mm0,%%mm7 \n\t"/* 7 ; a3 a2*/\ + "paddd %%mm5,%%mm2 \n\t"/* 5 ; b3=sum(odd3) b2=sum(odd2)*/\ + "paddd %%mm2,%%mm0 \n\t"/* a3+b3 a2+b2*/\ + "psrad $11,%%mm4 \n\t"/* y6=a1-b1 y7=a0-b0*/\ + "psubd %%mm2,%%mm7 \n\t"/* 2 ; a3-b3 a2-b2*/\ + "psrad $11,%%mm0 \n\t"/* y3=a3+b3 y2=a2+b2*/\ + "psrad $11,%%mm7 \n\t"/* y4=a3-b3 y5=a2-b2*/\ + "packssdw %%mm0,%%mm3 \n\t"/* 0 ; y3 y2 y1 y0*/\ + "packssdw %%mm4,%%mm7 \n\t"/* 4 ; y6 y7 y4 y5*/\ + "movq %%mm3, " #A2 " \n\t"/* 3 ; save y3 y2 y1 y0*/\ + "pshufw $0xb1,%%mm7,%%mm7 \n\t"/* y7 y6 y5 y4*/\ + "movq %%mm7,8 +" #A2 "\n\t"/* 7 ; save y7 y6 y5 y4*/\ + + +//----------------------------------------------------------------------------- +// +// The first stage DCT 8x8 - forward DCTs of columns +// +// The %2puts are multiplied +// for rows 0,4 - on cos_4_16, +// for rows 1,7 - on cos_1_16, +// for rows 2,6 - on cos_2_16, +// for rows 3,5 - on cos_3_16 +// and are shifted to the left for rise of accuracy +// +//----------------------------------------------------------------------------- +// +// The 8-point scaled forward DCT algorithm (26a8m) +// +//----------------------------------------------------------------------------- +// +// #define DCT_8_FRW_COL(x, y) +//{ +// short t0, t1, t2, t3, t4, t5, t6, t7; +// short tp03, tm03, tp12, tm12, tp65, tm65; +// short tp465, tm465, tp765, tm765; +// +// t0 = LEFT_SHIFT ( x[0] + x[7] ); +// t1 = LEFT_SHIFT ( x[1] + x[6] ); +// t2 = LEFT_SHIFT ( x[2] + x[5] ); +// t3 = LEFT_SHIFT ( x[3] + x[4] ); +// t4 = LEFT_SHIFT ( x[3] - x[4] ); +// t5 = LEFT_SHIFT ( x[2] - x[5] ); +// t6 = LEFT_SHIFT ( x[1] - x[6] ); +// t7 = LEFT_SHIFT ( x[0] - x[7] ); +// +// tp03 = t0 + t3; +// tm03 = t0 - t3; +// tp12 = t1 + t2; +// tm12 = t1 - t2; +// +// y[0] = tp03 + tp12; +// y[4] = tp03 - tp12; +// +// y[2] = tm03 + tm12 * tg_2_16; +// y[6] = tm03 * tg_2_16 - tm12; +// +// tp65 =(t6 +t5 )*cos_4_16; +// tm65 =(t6 -t5 )*cos_4_16; +// +// tp765 = t7 + tp65; +// tm765 = t7 - tp65; +// tp465 = t4 + tm65; +// tm465 = t4 - tm65; +// +// y[1] = tp765 + tp465 * tg_1_16; +// y[7] = tp765 * tg_1_16 - tp465; +// y[5] = tm765 * tg_3_16 + tm465; +// y[3] = tm765 - tm465 * tg_3_16; +//} +// +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// DCT_8_INV_COL_4 INP,OUT +//----------------------------------------------------------------------------- + +#define DCT_8_INV_COL(A1,A2)\ + "movq 2*8(%3),%%mm0\n\t"\ + "movq 16*3+" #A1 ",%%mm3\n\t"\ + "movq %%mm0,%%mm1 \n\t"/* tg_3_16*/\ + "movq 16*5+" #A1 ",%%mm5\n\t"\ + "pmulhw %%mm3,%%mm0 \n\t"/* x3*(tg_3_16-1)*/\ + "movq (%3),%%mm4\n\t"\ + "pmulhw %%mm5,%%mm1 \n\t"/* x5*(tg_3_16-1)*/\ + "movq 16*7+" #A1 ",%%mm7\n\t"\ + "movq %%mm4,%%mm2 \n\t"/* tg_1_16*/\ + "movq 16*1+" #A1 ",%%mm6\n\t"\ + "pmulhw %%mm7,%%mm4 \n\t"/* x7*tg_1_16*/\ + "paddsw %%mm3,%%mm0 \n\t"/* x3*tg_3_16*/\ + "pmulhw %%mm6,%%mm2 \n\t"/* x1*tg_1_16*/\ + "paddsw %%mm3,%%mm1 \n\t"/* x3+x5*(tg_3_16-1)*/\ + "psubsw %%mm5,%%mm0 \n\t"/* x3*tg_3_16-x5 = tm35*/\ + "movq 3*8(%3),%%mm3\n\t"\ + "paddsw %%mm5,%%mm1 \n\t"/* x3+x5*tg_3_16 = tp35*/\ + "paddsw %%mm6,%%mm4 \n\t"/* x1+tg_1_16*x7 = tp17*/\ + "psubsw %%mm7,%%mm2 \n\t"/* x1*tg_1_16-x7 = tm17*/\ + "movq %%mm4,%%mm5 \n\t"/* tp17*/\ + "movq %%mm2,%%mm6 \n\t"/* tm17*/\ + "paddsw %%mm1,%%mm5 \n\t"/* tp17+tp35 = b0*/\ + "psubsw %%mm0,%%mm6 \n\t"/* tm17-tm35 = b3*/\ + "psubsw %%mm1,%%mm4 \n\t"/* tp17-tp35 = t1*/\ + "paddsw %%mm0,%%mm2 \n\t"/* tm17+tm35 = t2*/\ + "movq 1*8(%3),%%mm7\n\t"\ + "movq %%mm4,%%mm1 \n\t"/* t1*/\ + "movq %%mm5,3*16 +" #A2 "\n\t"/* save b0*/\ + "paddsw %%mm2,%%mm1 \n\t"/* t1+t2*/\ + "movq %%mm6,5*16 +" #A2 "\n\t"/* save b3*/\ + "psubsw %%mm2,%%mm4 \n\t"/* t1-t2*/\ + "movq 2*16+" #A1 ",%%mm5\n\t"\ + "movq %%mm7,%%mm0 \n\t"/* tg_2_16*/\ + "movq 6*16+" #A1 ",%%mm6\n\t"\ + "pmulhw %%mm5,%%mm0 \n\t"/* x2*tg_2_16*/\ + "pmulhw %%mm6,%%mm7 \n\t"/* x6*tg_2_16*/\ + "pmulhw %%mm3,%%mm1 \n\t"/* ocos_4_16*(t1+t2) = b1/2*/\ + "movq 0*16+" #A1 ",%%mm2\n\t"\ + "pmulhw %%mm3,%%mm4 \n\t"/* ocos_4_16*(t1-t2) = b2/2*/\ + "psubsw %%mm6,%%mm0 \n\t"/* t2*tg_2_16-x6 = tm26*/\ + "movq %%mm2,%%mm3 \n\t"/* x0*/\ + "movq 4*16+" #A1 ",%%mm6\n\t"\ + "paddsw %%mm5,%%mm7 \n\t"/* x2+x6*tg_2_16 = tp26*/\ + "paddsw %%mm6,%%mm2 \n\t"/* x0+x4 = tp04*/\ + "psubsw %%mm6,%%mm3 \n\t"/* x0-x4 = tm04*/\ + "movq %%mm2,%%mm5 \n\t"/* tp04*/\ + "movq %%mm3,%%mm6 \n\t"/* tm04*/\ + "psubsw %%mm7,%%mm2 \n\t"/* tp04-tp26 = a3*/\ + "paddsw %%mm0,%%mm3 \n\t"/* tm04+tm26 = a1*/\ + "paddsw %%mm1,%%mm1 \n\t"/* b1*/\ + "paddsw %%mm4,%%mm4 \n\t"/* b2*/\ + "paddsw %%mm7,%%mm5 \n\t"/* tp04+tp26 = a0*/\ + "psubsw %%mm0,%%mm6 \n\t"/* tm04-tm26 = a2*/\ + "movq %%mm3,%%mm7 \n\t"/* a1*/\ + "movq %%mm6,%%mm0 \n\t"/* a2*/\ + "paddsw %%mm1,%%mm3 \n\t"/* a1+b1*/\ + "paddsw %%mm4,%%mm6 \n\t"/* a2+b2*/\ + "psraw $6,%%mm3 \n\t"/* dst1*/\ + "psubsw %%mm1,%%mm7 \n\t"/* a1-b1*/\ + "psraw $6,%%mm6 \n\t"/* dst2*/\ + "psubsw %%mm4,%%mm0 \n\t"/* a2-b2*/\ + "movq 3*16+" #A2 ",%%mm1 \n\t"/* load b0*/\ + "psraw $6,%%mm7 \n\t"/* dst6*/\ + "movq %%mm5,%%mm4 \n\t"/* a0*/\ + "psraw $6,%%mm0 \n\t"/* dst5*/\ + "movq %%mm3,1*16+" #A2 "\n\t"\ + "paddsw %%mm1,%%mm5 \n\t"/* a0+b0*/\ + "movq %%mm6,2*16+" #A2 "\n\t"\ + "psubsw %%mm1,%%mm4 \n\t"/* a0-b0*/\ + "movq 5*16+" #A2 ",%%mm3 \n\t"/* load b3*/\ + "psraw $6,%%mm5 \n\t"/* dst0*/\ + "movq %%mm2,%%mm6 \n\t"/* a3*/\ + "psraw $6,%%mm4 \n\t"/* dst7*/\ + "movq %%mm0,5*16+" #A2 "\n\t"\ + "paddsw %%mm3,%%mm2 \n\t"/* a3+b3*/\ + "movq %%mm7,6*16+" #A2 "\n\t"\ + "psubsw %%mm3,%%mm6 \n\t"/* a3-b3*/\ + "movq %%mm5,0*16+" #A2 "\n\t"\ + "psraw $6,%%mm2 \n\t"/* dst3*/\ + "movq %%mm4,7*16+" #A2 "\n\t"\ + "psraw $6,%%mm6 \n\t"/* dst4*/\ + "movq %%mm2,3*16+" #A2 "\n\t"\ + "movq %%mm6,4*16+" #A2 "\n\t" + +//============================================================================= +// Code +//============================================================================= + +//----------------------------------------------------------------------------- +// void idct_mmx(uint16_t block[64]); +//----------------------------------------------------------------------------- + + +void ff_idct_xvid_mmx(short *block){ +__asm__ volatile( + //# Process each row + DCT_8_INV_ROW_MMX(0*16(%0), 0*16(%0), 64*0(%2), 8*0(%1)) + DCT_8_INV_ROW_MMX(1*16(%0), 1*16(%0), 64*1(%2), 8*1(%1)) + DCT_8_INV_ROW_MMX(2*16(%0), 2*16(%0), 64*2(%2), 8*2(%1)) + DCT_8_INV_ROW_MMX(3*16(%0), 3*16(%0), 64*3(%2), 8*3(%1)) + DCT_8_INV_ROW_MMX(4*16(%0), 4*16(%0), 64*0(%2), 8*4(%1)) + DCT_8_INV_ROW_MMX(5*16(%0), 5*16(%0), 64*3(%2), 8*5(%1)) + DCT_8_INV_ROW_MMX(6*16(%0), 6*16(%0), 64*2(%2), 8*6(%1)) + DCT_8_INV_ROW_MMX(7*16(%0), 7*16(%0), 64*1(%2), 8*7(%1)) + + //# Process the columns (4 at a time) + DCT_8_INV_COL(0(%0), 0(%0)) + DCT_8_INV_COL(8(%0), 8(%0)) + :: "r"(block), "r"(rounder_0), "r"(tab_i_04_mmx), "r"(tg_1_16)); +} + +//----------------------------------------------------------------------------- +// void idct_xmm(uint16_t block[64]); +//----------------------------------------------------------------------------- + + +void ff_idct_xvid_mmxext(short *block) +{ +__asm__ volatile( + //# Process each row + DCT_8_INV_ROW_XMM(0*16(%0), 0*16(%0), 64*0(%2), 8*0(%1)) + DCT_8_INV_ROW_XMM(1*16(%0), 1*16(%0), 64*1(%2), 8*1(%1)) + DCT_8_INV_ROW_XMM(2*16(%0), 2*16(%0), 64*2(%2), 8*2(%1)) + DCT_8_INV_ROW_XMM(3*16(%0), 3*16(%0), 64*3(%2), 8*3(%1)) + DCT_8_INV_ROW_XMM(4*16(%0), 4*16(%0), 64*0(%2), 8*4(%1)) + DCT_8_INV_ROW_XMM(5*16(%0), 5*16(%0), 64*3(%2), 8*5(%1)) + DCT_8_INV_ROW_XMM(6*16(%0), 6*16(%0), 64*2(%2), 8*6(%1)) + DCT_8_INV_ROW_XMM(7*16(%0), 7*16(%0), 64*1(%2), 8*7(%1)) + + //# Process the columns (4 at a time) + DCT_8_INV_COL(0(%0), 0(%0)) + DCT_8_INV_COL(8(%0), 8(%0)) + :: "r"(block), "r"(rounder_0), "r"(tab_i_04_xmm), "r"(tg_1_16)); +} + +void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_idct_xvid_mmx(block); + ff_put_pixels_clamped_mmx(block, dest, line_size); +} + +void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_idct_xvid_mmx(block); + ff_add_pixels_clamped_mmx(block, dest, line_size); +} + +void ff_idct_xvid_mmxext_put(uint8_t *dest, int line_size, int16_t *block) +{ + ff_idct_xvid_mmxext(block); + ff_put_pixels_clamped_mmx(block, dest, line_size); +} + +void ff_idct_xvid_mmxext_add(uint8_t *dest, int line_size, int16_t *block) +{ + ff_idct_xvid_mmxext(block); + ff_add_pixels_clamped_mmx(block, dest, line_size); +} + +#endif /* HAVE_INLINE_ASM */ diff --git a/ffmpeg/libavcodec/x86/idct_sse2_xvid.c b/ffmpeg/libavcodec/x86/idct_sse2_xvid.c new file mode 100644 index 0000000..b51466c --- /dev/null +++ b/ffmpeg/libavcodec/x86/idct_sse2_xvid.c @@ -0,0 +1,407 @@ +/* + * XVID MPEG-4 VIDEO CODEC + * - SSE2 inverse discrete cosine transform - + * + * Copyright(C) 2003 Pascal Massimino + * + * Conversion to gcc syntax with modifications + * by Alexander Strange + * + * Originally from dct/x86_asm/fdct_sse2_skal.asm in Xvid. + * + * This file is part of FFmpeg. + * + * Vertical pass is an implementation of the scheme: + * Loeffler C., Ligtenberg A., and Moschytz C.S.: + * Practical Fast 1D DCT Algorithm with Eleven Multiplications, + * Proc. ICASSP 1989, 988-991. + * + * Horizontal pass is a double 4x4 vector/matrix multiplication, + * (see also Intel's Application Note 922: + * http://developer.intel.com/vtune/cbts/strmsimd/922down.htm + * Copyright (C) 1999 Intel Corporation) + * + * More details at http://skal.planet-d.net/coding/dct.html + * + * 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 "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "idct_xvid.h" +#include "dsputil_mmx.h" + +#if HAVE_INLINE_ASM + +/** + * @file + * @brief SSE2 idct compatible with xvidmmx + */ + +#define X8(x) x,x,x,x,x,x,x,x + +#define ROW_SHIFT 11 +#define COL_SHIFT 6 + +DECLARE_ASM_CONST(16, int16_t, tan1)[] = {X8(13036)}; // tan( pi/16) +DECLARE_ASM_CONST(16, int16_t, tan2)[] = {X8(27146)}; // tan(2pi/16) = sqrt(2)-1 +DECLARE_ASM_CONST(16, int16_t, tan3)[] = {X8(43790)}; // tan(3pi/16)-1 +DECLARE_ASM_CONST(16, int16_t, sqrt2)[]= {X8(23170)}; // 0.5/sqrt(2) +DECLARE_ASM_CONST(8, uint8_t, m127)[] = {X8(127)}; + +DECLARE_ASM_CONST(16, int16_t, iTab1)[] = { + 0x4000, 0x539f, 0xc000, 0xac61, 0x4000, 0xdd5d, 0x4000, 0xdd5d, + 0x4000, 0x22a3, 0x4000, 0x22a3, 0xc000, 0x539f, 0x4000, 0xac61, + 0x3249, 0x11a8, 0x4b42, 0xee58, 0x11a8, 0x4b42, 0x11a8, 0xcdb7, + 0x58c5, 0x4b42, 0xa73b, 0xcdb7, 0x3249, 0xa73b, 0x4b42, 0xa73b +}; + +DECLARE_ASM_CONST(16, int16_t, iTab2)[] = { + 0x58c5, 0x73fc, 0xa73b, 0x8c04, 0x58c5, 0xcff5, 0x58c5, 0xcff5, + 0x58c5, 0x300b, 0x58c5, 0x300b, 0xa73b, 0x73fc, 0x58c5, 0x8c04, + 0x45bf, 0x187e, 0x6862, 0xe782, 0x187e, 0x6862, 0x187e, 0xba41, + 0x7b21, 0x6862, 0x84df, 0xba41, 0x45bf, 0x84df, 0x6862, 0x84df +}; + +DECLARE_ASM_CONST(16, int16_t, iTab3)[] = { + 0x539f, 0x6d41, 0xac61, 0x92bf, 0x539f, 0xd2bf, 0x539f, 0xd2bf, + 0x539f, 0x2d41, 0x539f, 0x2d41, 0xac61, 0x6d41, 0x539f, 0x92bf, + 0x41b3, 0x1712, 0x6254, 0xe8ee, 0x1712, 0x6254, 0x1712, 0xbe4d, + 0x73fc, 0x6254, 0x8c04, 0xbe4d, 0x41b3, 0x8c04, 0x6254, 0x8c04 +}; + +DECLARE_ASM_CONST(16, int16_t, iTab4)[] = { + 0x4b42, 0x6254, 0xb4be, 0x9dac, 0x4b42, 0xd746, 0x4b42, 0xd746, + 0x4b42, 0x28ba, 0x4b42, 0x28ba, 0xb4be, 0x6254, 0x4b42, 0x9dac, + 0x3b21, 0x14c3, 0x587e, 0xeb3d, 0x14c3, 0x587e, 0x14c3, 0xc4df, + 0x6862, 0x587e, 0x979e, 0xc4df, 0x3b21, 0x979e, 0x587e, 0x979e +}; + +DECLARE_ASM_CONST(16, int32_t, walkenIdctRounders)[] = { + 65536, 65536, 65536, 65536, + 3597, 3597, 3597, 3597, + 2260, 2260, 2260, 2260, + 1203, 1203, 1203, 1203, + 120, 120, 120, 120, + 512, 512, 512, 512 +}; + +// Temporary storage before the column pass +#define ROW1 "%%xmm6" +#define ROW3 "%%xmm4" +#define ROW5 "%%xmm5" +#define ROW7 "%%xmm7" + +#define CLEAR_ODD(r) "pxor "r","r" \n\t" +#define PUT_ODD(dst) "pshufhw $0x1B, %%xmm2, "dst" \n\t" + +#if ARCH_X86_64 + +# define ROW0 "%%xmm8" +# define REG0 ROW0 +# define ROW2 "%%xmm9" +# define REG2 ROW2 +# define ROW4 "%%xmm10" +# define REG4 ROW4 +# define ROW6 "%%xmm11" +# define REG6 ROW6 +# define CLEAR_EVEN(r) CLEAR_ODD(r) +# define PUT_EVEN(dst) PUT_ODD(dst) +# define XMMS "%%xmm12" +# define MOV_32_ONLY "#" +# define SREG2 REG2 +# define TAN3 "%%xmm13" +# define TAN1 "%%xmm14" + +#else + +# define ROW0 "(%0)" +# define REG0 "%%xmm4" +# define ROW2 "2*16(%0)" +# define REG2 "%%xmm4" +# define ROW4 "4*16(%0)" +# define REG4 "%%xmm6" +# define ROW6 "6*16(%0)" +# define REG6 "%%xmm6" +# define CLEAR_EVEN(r) +# define PUT_EVEN(dst) \ + "pshufhw $0x1B, %%xmm2, %%xmm2 \n\t" \ + "movdqa %%xmm2, "dst" \n\t" +# define XMMS "%%xmm2" +# define MOV_32_ONLY "movdqa " +# define SREG2 "%%xmm7" +# define TAN3 "%%xmm0" +# define TAN1 "%%xmm2" + +#endif + +#define ROUND(x) "paddd "MANGLE(x) + +#define JZ(reg, to) \ + "testl "reg","reg" \n\t" \ + "jz "to" \n\t" + +#define JNZ(reg, to) \ + "testl "reg","reg" \n\t" \ + "jnz "to" \n\t" + +#define TEST_ONE_ROW(src, reg, clear) \ + clear \ + "movq "src", %%mm1 \n\t" \ + "por 8+"src", %%mm1 \n\t" \ + "paddusb %%mm0, %%mm1 \n\t" \ + "pmovmskb %%mm1, "reg" \n\t" + +#define TEST_TWO_ROWS(row1, row2, reg1, reg2, clear1, clear2) \ + clear1 \ + clear2 \ + "movq "row1", %%mm1 \n\t" \ + "por 8+"row1", %%mm1 \n\t" \ + "movq "row2", %%mm2 \n\t" \ + "por 8+"row2", %%mm2 \n\t" \ + "paddusb %%mm0, %%mm1 \n\t" \ + "paddusb %%mm0, %%mm2 \n\t" \ + "pmovmskb %%mm1, "reg1" \n\t" \ + "pmovmskb %%mm2, "reg2" \n\t" + +///IDCT pass on rows. +#define iMTX_MULT(src, table, rounder, put) \ + "movdqa "src", %%xmm3 \n\t" \ + "movdqa %%xmm3, %%xmm0 \n\t" \ + "pshufd $0x11, %%xmm3, %%xmm1 \n\t" /* 4602 */ \ + "punpcklqdq %%xmm0, %%xmm0 \n\t" /* 0246 */ \ + "pmaddwd "table", %%xmm0 \n\t" \ + "pmaddwd 16+"table", %%xmm1 \n\t" \ + "pshufd $0xBB, %%xmm3, %%xmm2 \n\t" /* 5713 */ \ + "punpckhqdq %%xmm3, %%xmm3 \n\t" /* 1357 */ \ + "pmaddwd 32+"table", %%xmm2 \n\t" \ + "pmaddwd 48+"table", %%xmm3 \n\t" \ + "paddd %%xmm1, %%xmm0 \n\t" \ + "paddd %%xmm3, %%xmm2 \n\t" \ + rounder", %%xmm0 \n\t" \ + "movdqa %%xmm2, %%xmm3 \n\t" \ + "paddd %%xmm0, %%xmm2 \n\t" \ + "psubd %%xmm3, %%xmm0 \n\t" \ + "psrad $11, %%xmm2 \n\t" \ + "psrad $11, %%xmm0 \n\t" \ + "packssdw %%xmm0, %%xmm2 \n\t" \ + put \ + "1: \n\t" + +#define iLLM_HEAD \ + "movdqa "MANGLE(tan3)", "TAN3" \n\t" \ + "movdqa "MANGLE(tan1)", "TAN1" \n\t" \ + +///IDCT pass on columns. +#define iLLM_PASS(dct) \ + "movdqa "TAN3", %%xmm1 \n\t" \ + "movdqa "TAN1", %%xmm3 \n\t" \ + "pmulhw %%xmm4, "TAN3" \n\t" \ + "pmulhw %%xmm5, %%xmm1 \n\t" \ + "paddsw %%xmm4, "TAN3" \n\t" \ + "paddsw %%xmm5, %%xmm1 \n\t" \ + "psubsw %%xmm5, "TAN3" \n\t" \ + "paddsw %%xmm4, %%xmm1 \n\t" \ + "pmulhw %%xmm7, %%xmm3 \n\t" \ + "pmulhw %%xmm6, "TAN1" \n\t" \ + "paddsw %%xmm6, %%xmm3 \n\t" \ + "psubsw %%xmm7, "TAN1" \n\t" \ + "movdqa %%xmm3, %%xmm7 \n\t" \ + "movdqa "TAN1", %%xmm6 \n\t" \ + "psubsw %%xmm1, %%xmm3 \n\t" \ + "psubsw "TAN3", "TAN1" \n\t" \ + "paddsw %%xmm7, %%xmm1 \n\t" \ + "paddsw %%xmm6, "TAN3" \n\t" \ + "movdqa %%xmm3, %%xmm6 \n\t" \ + "psubsw "TAN3", %%xmm3 \n\t" \ + "paddsw %%xmm6, "TAN3" \n\t" \ + "movdqa "MANGLE(sqrt2)", %%xmm4 \n\t" \ + "pmulhw %%xmm4, %%xmm3 \n\t" \ + "pmulhw %%xmm4, "TAN3" \n\t" \ + "paddsw "TAN3", "TAN3" \n\t" \ + "paddsw %%xmm3, %%xmm3 \n\t" \ + "movdqa "MANGLE(tan2)", %%xmm7 \n\t" \ + MOV_32_ONLY ROW2", "REG2" \n\t" \ + MOV_32_ONLY ROW6", "REG6" \n\t" \ + "movdqa %%xmm7, %%xmm5 \n\t" \ + "pmulhw "REG6", %%xmm7 \n\t" \ + "pmulhw "REG2", %%xmm5 \n\t" \ + "paddsw "REG2", %%xmm7 \n\t" \ + "psubsw "REG6", %%xmm5 \n\t" \ + MOV_32_ONLY ROW0", "REG0" \n\t" \ + MOV_32_ONLY ROW4", "REG4" \n\t" \ + MOV_32_ONLY" "TAN1", (%0) \n\t" \ + "movdqa "REG0", "XMMS" \n\t" \ + "psubsw "REG4", "REG0" \n\t" \ + "paddsw "XMMS", "REG4" \n\t" \ + "movdqa "REG4", "XMMS" \n\t" \ + "psubsw %%xmm7, "REG4" \n\t" \ + "paddsw "XMMS", %%xmm7 \n\t" \ + "movdqa "REG0", "XMMS" \n\t" \ + "psubsw %%xmm5, "REG0" \n\t" \ + "paddsw "XMMS", %%xmm5 \n\t" \ + "movdqa %%xmm5, "XMMS" \n\t" \ + "psubsw "TAN3", %%xmm5 \n\t" \ + "paddsw "XMMS", "TAN3" \n\t" \ + "movdqa "REG0", "XMMS" \n\t" \ + "psubsw %%xmm3, "REG0" \n\t" \ + "paddsw "XMMS", %%xmm3 \n\t" \ + MOV_32_ONLY" (%0), "TAN1" \n\t" \ + "psraw $6, %%xmm5 \n\t" \ + "psraw $6, "REG0" \n\t" \ + "psraw $6, "TAN3" \n\t" \ + "psraw $6, %%xmm3 \n\t" \ + "movdqa "TAN3", 1*16("dct") \n\t" \ + "movdqa %%xmm3, 2*16("dct") \n\t" \ + "movdqa "REG0", 5*16("dct") \n\t" \ + "movdqa %%xmm5, 6*16("dct") \n\t" \ + "movdqa %%xmm7, %%xmm0 \n\t" \ + "movdqa "REG4", %%xmm4 \n\t" \ + "psubsw %%xmm1, %%xmm7 \n\t" \ + "psubsw "TAN1", "REG4" \n\t" \ + "paddsw %%xmm0, %%xmm1 \n\t" \ + "paddsw %%xmm4, "TAN1" \n\t" \ + "psraw $6, %%xmm1 \n\t" \ + "psraw $6, %%xmm7 \n\t" \ + "psraw $6, "TAN1" \n\t" \ + "psraw $6, "REG4" \n\t" \ + "movdqa %%xmm1, ("dct") \n\t" \ + "movdqa "TAN1", 3*16("dct") \n\t" \ + "movdqa "REG4", 4*16("dct") \n\t" \ + "movdqa %%xmm7, 7*16("dct") \n\t" + +///IDCT pass on columns, assuming rows 4-7 are zero. +#define iLLM_PASS_SPARSE(dct) \ + "pmulhw %%xmm4, "TAN3" \n\t" \ + "paddsw %%xmm4, "TAN3" \n\t" \ + "movdqa %%xmm6, %%xmm3 \n\t" \ + "pmulhw %%xmm6, "TAN1" \n\t" \ + "movdqa %%xmm4, %%xmm1 \n\t" \ + "psubsw %%xmm1, %%xmm3 \n\t" \ + "paddsw %%xmm6, %%xmm1 \n\t" \ + "movdqa "TAN1", %%xmm6 \n\t" \ + "psubsw "TAN3", "TAN1" \n\t" \ + "paddsw %%xmm6, "TAN3" \n\t" \ + "movdqa %%xmm3, %%xmm6 \n\t" \ + "psubsw "TAN3", %%xmm3 \n\t" \ + "paddsw %%xmm6, "TAN3" \n\t" \ + "movdqa "MANGLE(sqrt2)", %%xmm4 \n\t" \ + "pmulhw %%xmm4, %%xmm3 \n\t" \ + "pmulhw %%xmm4, "TAN3" \n\t" \ + "paddsw "TAN3", "TAN3" \n\t" \ + "paddsw %%xmm3, %%xmm3 \n\t" \ + "movdqa "MANGLE(tan2)", %%xmm5 \n\t" \ + MOV_32_ONLY ROW2", "SREG2" \n\t" \ + "pmulhw "SREG2", %%xmm5 \n\t" \ + MOV_32_ONLY ROW0", "REG0" \n\t" \ + "movdqa "REG0", %%xmm6 \n\t" \ + "psubsw "SREG2", %%xmm6 \n\t" \ + "paddsw "REG0", "SREG2" \n\t" \ + MOV_32_ONLY" "TAN1", (%0) \n\t" \ + "movdqa "REG0", "XMMS" \n\t" \ + "psubsw %%xmm5, "REG0" \n\t" \ + "paddsw "XMMS", %%xmm5 \n\t" \ + "movdqa %%xmm5, "XMMS" \n\t" \ + "psubsw "TAN3", %%xmm5 \n\t" \ + "paddsw "XMMS", "TAN3" \n\t" \ + "movdqa "REG0", "XMMS" \n\t" \ + "psubsw %%xmm3, "REG0" \n\t" \ + "paddsw "XMMS", %%xmm3 \n\t" \ + MOV_32_ONLY" (%0), "TAN1" \n\t" \ + "psraw $6, %%xmm5 \n\t" \ + "psraw $6, "REG0" \n\t" \ + "psraw $6, "TAN3" \n\t" \ + "psraw $6, %%xmm3 \n\t" \ + "movdqa "TAN3", 1*16("dct") \n\t" \ + "movdqa %%xmm3, 2*16("dct") \n\t" \ + "movdqa "REG0", 5*16("dct") \n\t" \ + "movdqa %%xmm5, 6*16("dct") \n\t" \ + "movdqa "SREG2", %%xmm0 \n\t" \ + "movdqa %%xmm6, %%xmm4 \n\t" \ + "psubsw %%xmm1, "SREG2" \n\t" \ + "psubsw "TAN1", %%xmm6 \n\t" \ + "paddsw %%xmm0, %%xmm1 \n\t" \ + "paddsw %%xmm4, "TAN1" \n\t" \ + "psraw $6, %%xmm1 \n\t" \ + "psraw $6, "SREG2" \n\t" \ + "psraw $6, "TAN1" \n\t" \ + "psraw $6, %%xmm6 \n\t" \ + "movdqa %%xmm1, ("dct") \n\t" \ + "movdqa "TAN1", 3*16("dct") \n\t" \ + "movdqa %%xmm6, 4*16("dct") \n\t" \ + "movdqa "SREG2", 7*16("dct") \n\t" + +inline void ff_idct_xvid_sse2(short *block) +{ + __asm__ volatile( + "movq "MANGLE(m127)", %%mm0 \n\t" + iMTX_MULT("(%0)", MANGLE(iTab1), ROUND(walkenIdctRounders), PUT_EVEN(ROW0)) + iMTX_MULT("1*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+1*16), PUT_ODD(ROW1)) + iMTX_MULT("2*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+2*16), PUT_EVEN(ROW2)) + + TEST_TWO_ROWS("3*16(%0)", "4*16(%0)", "%%eax", "%%ecx", CLEAR_ODD(ROW3), CLEAR_EVEN(ROW4)) + JZ("%%eax", "1f") + iMTX_MULT("3*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders+3*16), PUT_ODD(ROW3)) + + TEST_TWO_ROWS("5*16(%0)", "6*16(%0)", "%%eax", "%%edx", CLEAR_ODD(ROW5), CLEAR_EVEN(ROW6)) + TEST_ONE_ROW("7*16(%0)", "%%esi", CLEAR_ODD(ROW7)) + iLLM_HEAD + ".p2align 4 \n\t" + JNZ("%%ecx", "2f") + JNZ("%%eax", "3f") + JNZ("%%edx", "4f") + JNZ("%%esi", "5f") + iLLM_PASS_SPARSE("%0") + "jmp 6f \n\t" + "2: \n\t" + iMTX_MULT("4*16(%0)", MANGLE(iTab1), "#", PUT_EVEN(ROW4)) + "3: \n\t" + iMTX_MULT("5*16(%0)", MANGLE(iTab4), ROUND(walkenIdctRounders+4*16), PUT_ODD(ROW5)) + JZ("%%edx", "1f") + "4: \n\t" + iMTX_MULT("6*16(%0)", MANGLE(iTab3), ROUND(walkenIdctRounders+5*16), PUT_EVEN(ROW6)) + JZ("%%esi", "1f") + "5: \n\t" + iMTX_MULT("7*16(%0)", MANGLE(iTab2), ROUND(walkenIdctRounders+5*16), PUT_ODD(ROW7)) +#if ARCH_X86_32 + iLLM_HEAD +#endif + iLLM_PASS("%0") + "6: \n\t" + : "+r"(block) + : + : XMM_CLOBBERS("%xmm0" , "%xmm1" , "%xmm2" , "%xmm3" , + "%xmm4" , "%xmm5" , "%xmm6" , "%xmm7" ,) +#if ARCH_X86_64 + XMM_CLOBBERS("%xmm8" , "%xmm9" , "%xmm10", "%xmm11", + "%xmm12", "%xmm13", "%xmm14",) +#endif + "%eax", "%ecx", "%edx", "%esi", "memory" + ); +} + +void ff_idct_xvid_sse2_put(uint8_t *dest, int line_size, short *block) +{ + ff_idct_xvid_sse2(block); + ff_put_pixels_clamped_mmx(block, dest, line_size); +} + +void ff_idct_xvid_sse2_add(uint8_t *dest, int line_size, short *block) +{ + ff_idct_xvid_sse2(block); + ff_add_pixels_clamped_mmx(block, dest, line_size); +} + +#endif /* HAVE_INLINE_ASM */ diff --git a/ffmpeg/libavcodec/x86/idct_xvid.h b/ffmpeg/libavcodec/x86/idct_xvid.h new file mode 100644 index 0000000..7a2847b --- /dev/null +++ b/ffmpeg/libavcodec/x86/idct_xvid.h @@ -0,0 +1,43 @@ +/* + * XVID MPEG-4 VIDEO CODEC + * + * 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 + */ + +/** + * @file + * header for Xvid IDCT functions + */ + +#ifndef AVCODEC_X86_IDCT_XVID_H +#define AVCODEC_X86_IDCT_XVID_H + +#include + +void ff_idct_xvid_mmx(short *block); +void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, int16_t *block); +void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, int16_t *block); + +void ff_idct_xvid_mmxext(short *block); +void ff_idct_xvid_mmxext_put(uint8_t *dest, int line_size, int16_t *block); +void ff_idct_xvid_mmxext_add(uint8_t *dest, int line_size, int16_t *block); + +void ff_idct_xvid_sse2(short *block); +void ff_idct_xvid_sse2_put(uint8_t *dest, int line_size, short *block); +void ff_idct_xvid_sse2_add(uint8_t *dest, int line_size, short *block); + +#endif /* AVCODEC_X86_IDCT_XVID_H */ diff --git a/ffmpeg/libavcodec/x86/imdct36.asm b/ffmpeg/libavcodec/x86/imdct36.asm new file mode 100644 index 0000000..d311fbe --- /dev/null +++ b/ffmpeg/libavcodec/x86/imdct36.asm @@ -0,0 +1,724 @@ +;****************************************************************************** +;* 36 point SSE-optimized IMDCT transform +;* Copyright (c) 2011 Vitor Sessak +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +align 16 +ps_mask: dd 0, ~0, ~0, ~0 +ps_mask2: dd 0, ~0, 0, ~0 +ps_mask3: dd 0, 0, 0, ~0 +ps_mask4: dd 0, ~0, 0, 0 + +ps_val1: dd -0.5, -0.5, -0.8660254038, -0.8660254038 +ps_val2: dd 1.0, 1.0, 0.8660254038, 0.8660254038 +ps_val3: dd 0.1736481777, 0.1736481777, 0.3420201433, 0.3420201433 +ps_val4: dd -0.7660444431, -0.7660444431, 0.8660254038, 0.8660254038 +ps_val5: dd -0.9396926208, -0.9396926208, -0.9848077530, -0.9848077530 +ps_val6: dd 0.5, 0.5, -0.6427876097, -0.6427876097 +ps_val7: dd 1.0, 1.0, -0.6427876097, -0.6427876097 + +ps_p1p1m1m1: dd 0, 0, 0x80000000, 0x80000000 +ps_p1m1p1m1: dd 0, 0x80000000, 0, 0x80000000 + +ps_cosh: dd 1.0, 0.50190991877167369479, 1.0, 5.73685662283492756461 + dd 1.0, 0.51763809020504152469, 1.0, 1.93185165257813657349 + dd 1.0, 0.55168895948124587824, -1.0, -1.18310079157624925896 + dd 1.0, 0.61038729438072803416, -1.0, -0.87172339781054900991 + dd 1.0, 0.70710678118654752439, 0.0, 0.0 + +ps_cosh_sse3: dd 1.0, -0.50190991877167369479, 1.0, -5.73685662283492756461 + dd 1.0, -0.51763809020504152469, 1.0, -1.93185165257813657349 + dd 1.0, -0.55168895948124587824, -1.0, 1.18310079157624925896 + dd 1.0, -0.61038729438072803416, -1.0, 0.87172339781054900991 + dd 1.0, 0.70710678118654752439, 0.0, 0.0 + +costabs: times 4 dd 0.98480773 + times 4 dd 0.93969262 + times 4 dd 0.86602539 + times 4 dd -0.76604444 + times 4 dd -0.64278764 + times 4 dd 0.50000000 + times 4 dd -0.50000000 + times 4 dd -0.34202015 + times 4 dd -0.17364818 + times 4 dd 0.50190992 + times 4 dd 0.51763808 + times 4 dd 0.55168896 + times 4 dd 0.61038726 + times 4 dd 0.70710677 + times 4 dd 0.87172341 + times 4 dd 1.18310082 + times 4 dd 1.93185163 + times 4 dd 5.73685646 + +%define SBLIMIT 32 +SECTION_TEXT + +%macro PSHUFD 3 +%if cpuflag(sse2) && notcpuflag(avx) + pshufd %1, %2, %3 +%else + shufps %1, %2, %2, %3 +%endif +%endmacro + +; input %2={x1,x2,x3,x4}, %3={y1,y2,y3,y4} +; output %1={x3,x4,y1,y2} +%macro BUILDINVHIGHLOW 3 +%if cpuflag(avx) + shufps %1, %2, %3, 0x4e +%else + movlhps %1, %3 + movhlps %1, %2 +%endif +%endmacro + +; input %2={x1,x2,x3,x4}, %3={y1,y2,y3,y4} +; output %1={x4,y1,y2,y3} +%macro ROTLEFT 3 +%if cpuflag(ssse3) + palignr %1, %3, %2, 12 +%else + BUILDINVHIGHLOW %1, %2, %3 + shufps %1, %1, %3, 0x99 +%endif +%endmacro + +%macro INVERTHL 2 +%if cpuflag(sse2) + PSHUFD %1, %2, 0x4e +%else + movhlps %1, %2 + movlhps %1, %2 +%endif +%endmacro + +%macro BUTTERF 3 + INVERTHL %2, %1 + xorps %1, [ps_p1p1m1m1] + addps %1, %2 +%if cpuflag(sse3) + mulps %1, %1, [ps_cosh_sse3 + %3] + PSHUFD %2, %1, 0xb1 + addsubps %1, %1, %2 +%else + mulps %1, [ps_cosh + %3] + PSHUFD %2, %1, 0xb1 + xorps %1, [ps_p1m1p1m1] + addps %1, %2 +%endif +%endmacro + +%macro STORE 4 + movhlps %2, %1 + movss [%3 ], %1 + movss [%3 + 2*%4], %2 + shufps %1, %1, 0xb1 + movss [%3 + %4], %1 + movhlps %2, %1 + movss [%3 + 3*%4], %2 +%endmacro + +%macro LOAD 4 + movlps %1, [%3 ] + movhps %1, [%3 + %4] + movlps %2, [%3 + 2*%4] + movhps %2, [%3 + 3*%4] + shufps %1, %2, 0x88 +%endmacro + +%macro LOADA64 2 +%if cpuflag(avx) + movu %1, [%2] +%else + movlps %1, [%2] + movhps %1, [%2 + 8] +%endif +%endmacro + +%macro DEFINE_IMDCT 0 +cglobal imdct36_float, 4,4,9, out, buf, in, win + + ; for(i=17;i>=1;i--) in[i] += in[i-1]; + LOADA64 m0, inq + LOADA64 m1, inq + 16 + + ROTLEFT m5, m0, m1 + + PSHUFD m6, m0, 0x93 + andps m6, m6, [ps_mask] + addps m0, m0, m6 + + LOADA64 m2, inq + 32 + + ROTLEFT m7, m1, m2 + + addps m1, m1, m5 + LOADA64 m3, inq + 48 + + ROTLEFT m5, m2, m3 + + xorps m4, m4, m4 + movlps m4, [inq+64] + BUILDINVHIGHLOW m6, m3, m4 + shufps m6, m6, m4, 0xa9 + + addps m4, m4, m6 + addps m2, m2, m7 + addps m3, m3, m5 + + ; for(i=17;i>=3;i-=2) in[i] += in[i-2]; + movlhps m5, m5, m0 + andps m5, m5, [ps_mask3] + + BUILDINVHIGHLOW m7, m0, m1 + andps m7, m7, [ps_mask2] + + addps m0, m0, m5 + + BUILDINVHIGHLOW m6, m1, m2 + andps m6, m6, [ps_mask2] + + addps m1, m1, m7 + + BUILDINVHIGHLOW m7, m2, m3 + andps m7, m7, [ps_mask2] + + addps m2, m2, m6 + + movhlps m6, m6, m3 + andps m6, m6, [ps_mask4] + + addps m3, m3, m7 + addps m4, m4, m6 + + ; Populate tmp[] + movlhps m6, m1, m5 ; zero out high values + subps m6, m6, m4 + + subps m5, m0, m3 + +%if ARCH_X86_64 + SWAP m5, m8 +%endif + + mulps m7, m2, [ps_val1] + +%if ARCH_X86_64 + mulps m5, m8, [ps_val2] +%else + mulps m5, m5, [ps_val2] +%endif + addps m7, m7, m5 + + mulps m5, m6, [ps_val1] + subps m7, m7, m5 + +%if ARCH_X86_64 + SWAP m5, m8 +%else + subps m5, m0, m3 +%endif + + subps m5, m5, m6 + addps m5, m5, m2 + + shufps m6, m4, m3, 0xe4 + subps m6, m6, m2 + mulps m6, m6, [ps_val3] + + addps m4, m4, m1 + mulps m4, m4, [ps_val4] + + shufps m1, m1, m0, 0xe4 + addps m1, m1, m2 + mulps m1, m1, [ps_val5] + + mulps m3, m3, [ps_val6] + mulps m0, m0, [ps_val7] + addps m0, m0, m3 + + xorps m2, m1, [ps_p1p1m1m1] + subps m2, m2, m4 + addps m2, m2, m0 + + addps m3, m4, m0 + subps m3, m3, m6 + xorps m3, m3, [ps_p1p1m1m1] + + shufps m0, m0, m4, 0xe4 + subps m0, m0, m1 + addps m0, m0, m6 + + BUILDINVHIGHLOW m4, m2, m3 + shufps m3, m3, m2, 0x4e + + ; we have tmp = {SwAPLH(m0), SwAPLH(m7), m3, m4, m5} + + BUTTERF m0, m1, 0 + BUTTERF m7, m2, 16 + BUTTERF m3, m6, 32 + BUTTERF m4, m1, 48 + + mulps m5, m5, [ps_cosh + 64] + PSHUFD m1, m5, 0xe1 + xorps m5, m5, [ps_p1m1p1m1] + addps m5, m5, m1 + + ; permutates: + ; m0 0 1 2 3 => 2 6 10 14 m1 + ; m7 4 5 6 7 => 3 7 11 15 m2 + ; m3 8 9 10 11 => 17 13 9 5 m3 + ; m4 12 13 14 15 => 16 12 8 4 m5 + ; m5 16 17 xx xx => 0 1 xx xx m0 + + unpckhps m1, m0, m7 + unpckhps m6, m3, m4 + movhlps m2, m6, m1 + movlhps m1, m1, m6 + + unpcklps m5, m5, m4 + unpcklps m3, m3, m7 + movhlps m4, m3, m5 + movlhps m5, m5, m3 + SWAP m4, m3 + ; permutation done + + PSHUFD m6, m2, 0xb1 + movss m4, [bufq + 4*68] + movss m7, [bufq + 4*64] + unpcklps m7, m7, m4 + mulps m6, m6, [winq + 16*4] + addps m6, m6, m7 + movss [outq + 64*SBLIMIT], m6 + shufps m6, m6, m6, 0xb1 + movss [outq + 68*SBLIMIT], m6 + + mulps m6, m3, [winq + 4*4] + LOAD m4, m7, bufq + 4*16, 16 + addps m6, m6, m4 + STORE m6, m7, outq + 16*SBLIMIT, 4*SBLIMIT + + shufps m4, m0, m3, 0xb5 + mulps m4, m4, [winq + 8*4] + LOAD m7, m6, bufq + 4*32, 16 + addps m4, m4, m7 + STORE m4, m6, outq + 32*SBLIMIT, 4*SBLIMIT + + shufps m3, m3, m2, 0xb1 + mulps m3, m3, [winq + 12*4] + LOAD m7, m6, bufq + 4*48, 16 + addps m3, m3, m7 + STORE m3, m7, outq + 48*SBLIMIT, 4*SBLIMIT + + mulps m2, m2, [winq] + LOAD m6, m7, bufq, 16 + addps m2, m2, m6 + STORE m2, m7, outq, 4*SBLIMIT + + mulps m4, m1, [winq + 20*4] + STORE m4, m7, bufq, 16 + + mulps m3, m5, [winq + 24*4] + STORE m3, m7, bufq + 4*16, 16 + + shufps m0, m0, m5, 0xb0 + mulps m0, m0, [winq + 28*4] + STORE m0, m7, bufq + 4*32, 16 + + shufps m5, m5, m1, 0xb1 + mulps m5, m5, [winq + 32*4] + STORE m5, m7, bufq + 4*48, 16 + + shufps m1, m1, m1, 0xb1 + mulps m1, m1, [winq + 36*4] + movss [bufq + 4*64], m1 + shufps m1, m1, 0xb1 + movss [bufq + 4*68], m1 + RET +%endmacro + +INIT_XMM sse +DEFINE_IMDCT + +INIT_XMM sse2 +DEFINE_IMDCT + +INIT_XMM sse3 +DEFINE_IMDCT + +INIT_XMM ssse3 +DEFINE_IMDCT + +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEFINE_IMDCT +%endif + +INIT_XMM sse + +%if ARCH_X86_64 +%define SPILL SWAP +%define UNSPILL SWAP +%define SPILLED(x) m %+ x +%else +%define SPILLED(x) [tmpq+(x-8)*16 + 32*4] +%macro SPILL 2 ; xmm#, mempos + movaps SPILLED(%2), m%1 +%endmacro +%macro UNSPILL 2 + movaps m%1, SPILLED(%2) +%endmacro +%endif + +%macro DEFINE_FOUR_IMDCT 0 +cglobal four_imdct36_float, 5,5,16, out, buf, in, win, tmp + movlps m0, [inq+64] + movhps m0, [inq+64 + 72] + movlps m3, [inq+64 + 2*72] + movhps m3, [inq+64 + 3*72] + + shufps m5, m0, m3, 0xdd + shufps m0, m0, m3, 0x88 + + mova m1, [inq+48] + movu m6, [inq+48 + 72] + mova m7, [inq+48 + 2*72] + movu m3, [inq+48 + 3*72] + + TRANSPOSE4x4PS 1, 6, 7, 3, 4 + + addps m4, m6, m7 + mova [tmpq+4*28], m4 + + addps m7, m3 + addps m6, m1 + addps m3, m0 + addps m0, m5 + addps m0, m7 + addps m7, m6 + mova [tmpq+4*12], m7 + SPILL 3, 12 + + mova m4, [inq+32] + movu m5, [inq+32 + 72] + mova m2, [inq+32 + 2*72] + movu m7, [inq+32 + 3*72] + + TRANSPOSE4x4PS 4, 5, 2, 7, 3 + + addps m1, m7 + SPILL 1, 11 + + addps m3, m5, m2 + SPILL 3, 13 + + addps m7, m2 + addps m5, m4 + addps m6, m7 + mova [tmpq], m6 + addps m7, m5 + mova [tmpq+4*16], m7 + + mova m2, [inq+16] + movu m7, [inq+16 + 72] + mova m1, [inq+16 + 2*72] + movu m6, [inq+16 + 3*72] + + TRANSPOSE4x4PS 2, 7, 1, 6, 3 + + addps m4, m6 + addps m6, m1 + addps m1, m7 + addps m7, m2 + addps m5, m6 + SPILL 5, 15 + addps m6, m7 + mulps m6, [costabs + 16*2] + mova [tmpq+4*8], m6 + SPILL 1, 10 + SPILL 0, 14 + + mova m1, [inq] + movu m6, [inq + 72] + mova m3, [inq + 2*72] + movu m5, [inq + 3*72] + + TRANSPOSE4x4PS 1, 6, 3, 5, 0 + + addps m2, m5 + addps m5, m3 + addps m7, m5 + addps m3, m6 + addps m6, m1 + SPILL 7, 8 + addps m5, m6 + SPILL 6, 9 + addps m6, m4, SPILLED(12) + subps m6, m2 + UNSPILL 7, 11 + SPILL 5, 11 + subps m5, m1, m7 + mulps m7, [costabs + 16*5] + addps m7, m1 + mulps m0, m6, [costabs + 16*6] + addps m0, m5 + mova [tmpq+4*24], m0 + addps m6, m5 + mova [tmpq+4*4], m6 + addps m6, m4, m2 + mulps m6, [costabs + 16*1] + subps m4, SPILLED(12) + mulps m4, [costabs + 16*8] + addps m2, SPILLED(12) + mulps m2, [costabs + 16*3] + subps m5, m7, m6 + subps m5, m2 + addps m6, m7 + addps m6, m4 + addps m7, m2 + subps m7, m4 + mova [tmpq+4*20], m7 + mova m2, [tmpq+4*28] + mova [tmpq+4*28], m5 + UNSPILL 7, 13 + subps m5, m7, m2 + mulps m5, [costabs + 16*7] + UNSPILL 1, 10 + mulps m1, [costabs + 16*2] + addps m4, m3, m2 + mulps m4, [costabs + 16*4] + addps m2, m7 + addps m7, m3 + mulps m7, [costabs] + subps m3, m2 + mulps m3, [costabs + 16*2] + addps m2, m7, m5 + addps m2, m1 + SPILL 2, 10 + addps m7, m4 + subps m7, m1 + SPILL 7, 12 + subps m5, m4 + subps m5, m1 + UNSPILL 0, 14 + SPILL 5, 13 + addps m1, m0, SPILLED(15) + subps m1, SPILLED(8) + mova m4, [costabs + 16*5] + mulps m4, [tmpq] + UNSPILL 2, 9 + addps m4, m2 + subps m2, [tmpq] + mulps m5, m1, [costabs + 16*6] + addps m5, m2 + SPILL 5, 9 + addps m2, m1 + SPILL 2, 14 + UNSPILL 5, 15 + subps m7, m5, m0 + addps m5, SPILLED(8) + mulps m5, [costabs + 16*1] + mulps m7, [costabs + 16*8] + addps m0, SPILLED(8) + mulps m0, [costabs + 16*3] + subps m2, m4, m5 + subps m2, m0 + SPILL 2, 15 + addps m5, m4 + addps m5, m7 + addps m4, m0 + subps m4, m7 + SPILL 4, 8 + mova m7, [tmpq+4*16] + mova m2, [tmpq+4*12] + addps m0, m7, m2 + subps m0, SPILLED(11) + mulps m0, [costabs + 16*2] + addps m4, m7, SPILLED(11) + mulps m4, [costabs] + subps m7, m2 + mulps m7, [costabs + 16*7] + addps m2, SPILLED(11) + mulps m2, [costabs + 16*4] + addps m1, m7, [tmpq+4*8] + addps m1, m4 + addps m4, m2 + subps m4, [tmpq+4*8] + SPILL 4, 11 + subps m7, m2 + subps m7, [tmpq+4*8] + addps m4, m6, SPILLED(10) + subps m6, SPILLED(10) + addps m2, m5, m1 + mulps m2, [costabs + 16*9] + subps m5, m1 + mulps m5, [costabs + 16*17] + subps m1, m4, m2 + addps m4, m2 + mulps m2, m1, [winq+4*36] + addps m2, [bufq+4*36] + mova [outq+1152], m2 + mulps m1, [winq+4*32] + addps m1, [bufq+4*32] + mova [outq+1024], m1 + mulps m1, m4, [winq+4*116] + mova [bufq+4*36], m1 + mulps m4, [winq+4*112] + mova [bufq+4*32], m4 + addps m2, m6, m5 + subps m6, m5 + mulps m1, m6, [winq+4*68] + addps m1, [bufq+4*68] + mova [outq+2176], m1 + mulps m6, [winq] + addps m6, [bufq] + mova [outq], m6 + mulps m1, m2, [winq+4*148] + mova [bufq+4*68], m1 + mulps m2, [winq+4*80] + mova [bufq], m2 + addps m5, m3, [tmpq+4*24] + mova m2, [tmpq+4*24] + subps m2, m3 + mova m1, SPILLED(9) + subps m1, m0 + mulps m1, [costabs + 16*10] + addps m0, SPILLED(9) + mulps m0, [costabs + 16*16] + addps m6, m5, m1 + subps m5, m1 + mulps m3, m5, [winq+4*40] + addps m3, [bufq+4*40] + mova [outq+1280], m3 + mulps m5, [winq+4*28] + addps m5, [bufq+4*28] + mova [outq+896], m5 + mulps m1, m6, [winq+4*120] + mova [bufq+4*40], m1 + mulps m6, [winq+4*108] + mova [bufq+4*28], m6 + addps m1, m2, m0 + subps m2, m0 + mulps m5, m2, [winq+4*64] + addps m5, [bufq+4*64] + mova [outq+2048], m5 + mulps m2, [winq+4*4] + addps m2, [bufq+4*4] + mova [outq+128], m2 + mulps m0, m1, [winq+4*144] + mova [bufq+4*64], m0 + mulps m1, [winq+4*84] + mova [bufq+4*4], m1 + mova m1, [tmpq+4*28] + mova m5, m1 + addps m1, SPILLED(13) + subps m5, SPILLED(13) + UNSPILL 3, 15 + addps m2, m7, m3 + mulps m2, [costabs + 16*11] + subps m3, m7 + mulps m3, [costabs + 16*15] + addps m0, m2, m1 + subps m1, m2 + SWAP m0, m2 + mulps m6, m1, [winq+4*44] + addps m6, [bufq+4*44] + mova [outq+1408], m6 + mulps m1, [winq+4*24] + addps m1, [bufq+4*24] + mova [outq+768], m1 + mulps m0, m2, [winq+4*124] + mova [bufq+4*44], m0 + mulps m2, [winq+4*104] + mova [bufq+4*24], m2 + addps m0, m5, m3 + subps m5, m3 + mulps m1, m5, [winq+4*60] + addps m1, [bufq+4*60] + mova [outq+1920], m1 + mulps m5, [winq+4*8] + addps m5, [bufq+4*8] + mova [outq+256], m5 + mulps m1, m0, [winq+4*140] + mova [bufq+4*60], m1 + mulps m0, [winq+4*88] + mova [bufq+4*8], m0 + mova m1, [tmpq+4*20] + addps m1, SPILLED(12) + mova m2, [tmpq+4*20] + subps m2, SPILLED(12) + UNSPILL 7, 8 + subps m0, m7, SPILLED(11) + addps m7, SPILLED(11) + mulps m4, m7, [costabs + 16*12] + mulps m0, [costabs + 16*14] + addps m5, m1, m4 + subps m1, m4 + mulps m7, m1, [winq+4*48] + addps m7, [bufq+4*48] + mova [outq+1536], m7 + mulps m1, [winq+4*20] + addps m1, [bufq+4*20] + mova [outq+640], m1 + mulps m1, m5, [winq+4*128] + mova [bufq+4*48], m1 + mulps m5, [winq+4*100] + mova [bufq+4*20], m5 + addps m6, m2, m0 + subps m2, m0 + mulps m1, m2, [winq+4*56] + addps m1, [bufq+4*56] + mova [outq+1792], m1 + mulps m2, [winq+4*12] + addps m2, [bufq+4*12] + mova [outq+384], m2 + mulps m0, m6, [winq+4*136] + mova [bufq+4*56], m0 + mulps m6, [winq+4*92] + mova [bufq+4*12], m6 + UNSPILL 0, 14 + mulps m0, [costabs + 16*13] + mova m3, [tmpq+4*4] + addps m2, m0, m3 + subps m3, m0 + mulps m0, m3, [winq+4*52] + addps m0, [bufq+4*52] + mova [outq+1664], m0 + mulps m3, [winq+4*16] + addps m3, [bufq+4*16] + mova [outq+512], m3 + mulps m0, m2, [winq+4*132] + mova [bufq+4*52], m0 + mulps m2, [winq+4*96] + mova [bufq+4*16], m2 + RET +%endmacro + +INIT_XMM sse +DEFINE_FOUR_IMDCT + +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +DEFINE_FOUR_IMDCT +%endif diff --git a/ffmpeg/libavcodec/x86/lpc.c b/ffmpeg/libavcodec/x86/lpc.c new file mode 100644 index 0000000..1962212 --- /dev/null +++ b/ffmpeg/libavcodec/x86/lpc.c @@ -0,0 +1,154 @@ +/* + * MMX optimized LPC DSP utils + * Copyright (c) 2007 Loren Merritt + * + * 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 "libavutil/x86/asm.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavcodec/lpc.h" + +#if HAVE_SSE2_INLINE + +static void lpc_apply_welch_window_sse2(const int32_t *data, int len, + double *w_data) +{ + double c = 2.0 / (len-1.0); + int n2 = len>>1; + x86_reg i = -n2*sizeof(int32_t); + x86_reg j = n2*sizeof(int32_t); + __asm__ volatile( + "movsd %4, %%xmm7 \n\t" + "movapd "MANGLE(ff_pd_1)", %%xmm6 \n\t" + "movapd "MANGLE(ff_pd_2)", %%xmm5 \n\t" + "movlhps %%xmm7, %%xmm7 \n\t" + "subpd %%xmm5, %%xmm7 \n\t" + "addsd %%xmm6, %%xmm7 \n\t" + "test $1, %5 \n\t" + "jz 2f \n\t" +#define WELCH(MOVPD, offset)\ + "1: \n\t"\ + "movapd %%xmm7, %%xmm1 \n\t"\ + "mulpd %%xmm1, %%xmm1 \n\t"\ + "movapd %%xmm6, %%xmm0 \n\t"\ + "subpd %%xmm1, %%xmm0 \n\t"\ + "pshufd $0x4e, %%xmm0, %%xmm1 \n\t"\ + "cvtpi2pd (%3,%0), %%xmm2 \n\t"\ + "cvtpi2pd "#offset"*4(%3,%1), %%xmm3 \n\t"\ + "mulpd %%xmm0, %%xmm2 \n\t"\ + "mulpd %%xmm1, %%xmm3 \n\t"\ + "movapd %%xmm2, (%2,%0,2) \n\t"\ + MOVPD" %%xmm3, "#offset"*8(%2,%1,2) \n\t"\ + "subpd %%xmm5, %%xmm7 \n\t"\ + "sub $8, %1 \n\t"\ + "add $8, %0 \n\t"\ + "jl 1b \n\t"\ + + WELCH("movupd", -1) + "jmp 3f \n\t" + "2: \n\t" + WELCH("movapd", -2) + "3: \n\t" + :"+&r"(i), "+&r"(j) + :"r"(w_data+n2), "r"(data+n2), "m"(c), "r"(len) + XMM_CLOBBERS_ONLY("%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm5", "%xmm6", "%xmm7") + ); +#undef WELCH +} + +static void lpc_compute_autocorr_sse2(const double *data, int len, int lag, + double *autoc) +{ + int j; + + if((x86_reg)data & 15) + data++; + + for(j=0; jlpc_apply_welch_window = lpc_apply_welch_window_sse2; + c->lpc_compute_autocorr = lpc_compute_autocorr_sse2; + } +#endif /* HAVE_SSE2_INLINE */ +} diff --git a/ffmpeg/libavcodec/x86/mathops.h b/ffmpeg/libavcodec/x86/mathops.h new file mode 100644 index 0000000..79e29e6 --- /dev/null +++ b/ffmpeg/libavcodec/x86/mathops.h @@ -0,0 +1,130 @@ +/* + * simple math operations + * Copyright (c) 2006 Michael Niedermayer et al + * + * 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 + */ + +#ifndef AVCODEC_X86_MATHOPS_H +#define AVCODEC_X86_MATHOPS_H + +#include "config.h" +#include "libavutil/common.h" + +#if HAVE_INLINE_ASM + +#if ARCH_X86_32 + +#define MULL MULL +static av_always_inline av_const int MULL(int a, int b, unsigned shift) +{ + int rt, dummy; + __asm__ ( + "imull %3 \n\t" + "shrdl %4, %%edx, %%eax \n\t" + :"=a"(rt), "=d"(dummy) + :"a"(a), "rm"(b), "ci"((uint8_t)shift) + ); + return rt; +} + +#define MULH MULH +static av_always_inline av_const int MULH(int a, int b) +{ + int rt, dummy; + __asm__ ( + "imull %3" + :"=d"(rt), "=a"(dummy) + :"a"(a), "rm"(b) + ); + return rt; +} + +#define MUL64 MUL64 +static av_always_inline av_const int64_t MUL64(int a, int b) +{ + int64_t rt; + __asm__ ( + "imull %2" + :"=A"(rt) + :"a"(a), "rm"(b) + ); + return rt; +} + +#endif /* ARCH_X86_32 */ + +#if HAVE_CMOV +/* median of 3 */ +#define mid_pred mid_pred +static inline av_const int mid_pred(int a, int b, int c) +{ + int i=b; + __asm__ volatile( + "cmp %2, %1 \n\t" + "cmovg %1, %0 \n\t" + "cmovg %2, %1 \n\t" + "cmp %3, %1 \n\t" + "cmovl %3, %1 \n\t" + "cmp %1, %0 \n\t" + "cmovg %1, %0 \n\t" + :"+&r"(i), "+&r"(a) + :"r"(b), "r"(c) + ); + return i; +} +#endif + +#if HAVE_CMOV +#define COPY3_IF_LT(x, y, a, b, c, d)\ +__asm__ volatile(\ + "cmpl %0, %3 \n\t"\ + "cmovl %3, %0 \n\t"\ + "cmovl %4, %1 \n\t"\ + "cmovl %5, %2 \n\t"\ + : "+&r" (x), "+&r" (a), "+r" (c)\ + : "r" (y), "r" (b), "r" (d)\ +); +#endif + +#define MASK_ABS(mask, level) \ + __asm__ ("cltd \n\t" \ + "xorl %1, %0 \n\t" \ + "subl %1, %0 \n\t" \ + : "+a"(level), "=&d"(mask)) + +// avoid +32 for shift optimization (gcc should do that ...) +#define NEG_SSR32 NEG_SSR32 +static inline int32_t NEG_SSR32( int32_t a, int8_t s){ + __asm__ ("sarl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} + +#define NEG_USR32 NEG_USR32 +static inline uint32_t NEG_USR32(uint32_t a, int8_t s){ + __asm__ ("shrl %1, %0\n\t" + : "+r" (a) + : "ic" ((uint8_t)(-s)) + ); + return a; +} + +#endif /* HAVE_INLINE_ASM */ +#endif /* AVCODEC_X86_MATHOPS_H */ diff --git a/ffmpeg/libavcodec/x86/mlpdsp.c b/ffmpeg/libavcodec/x86/mlpdsp.c new file mode 100644 index 0000000..81cab5a --- /dev/null +++ b/ffmpeg/libavcodec/x86/mlpdsp.c @@ -0,0 +1,182 @@ +/* + * MLP DSP functions x86-optimized + * Copyright (c) 2009 Ramiro Polla + * + * 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 "libavutil/attributes.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/mlpdsp.h" +#include "libavcodec/mlp.h" + +#if HAVE_7REGS && HAVE_INLINE_ASM + +extern char ff_mlp_firorder_8; +extern char ff_mlp_firorder_7; +extern char ff_mlp_firorder_6; +extern char ff_mlp_firorder_5; +extern char ff_mlp_firorder_4; +extern char ff_mlp_firorder_3; +extern char ff_mlp_firorder_2; +extern char ff_mlp_firorder_1; +extern char ff_mlp_firorder_0; + +extern char ff_mlp_iirorder_4; +extern char ff_mlp_iirorder_3; +extern char ff_mlp_iirorder_2; +extern char ff_mlp_iirorder_1; +extern char ff_mlp_iirorder_0; + +static const void *firtable[9] = { &ff_mlp_firorder_0, &ff_mlp_firorder_1, + &ff_mlp_firorder_2, &ff_mlp_firorder_3, + &ff_mlp_firorder_4, &ff_mlp_firorder_5, + &ff_mlp_firorder_6, &ff_mlp_firorder_7, + &ff_mlp_firorder_8 }; +static const void *iirtable[5] = { &ff_mlp_iirorder_0, &ff_mlp_iirorder_1, + &ff_mlp_iirorder_2, &ff_mlp_iirorder_3, + &ff_mlp_iirorder_4 }; + +#if ARCH_X86_64 + +#define MLPMUL(label, offset, offs, offc) \ + LABEL_MANGLE(label)": \n\t" \ + "movslq "offset"+"offs"(%0), %%rax\n\t" \ + "movslq "offset"+"offc"(%1), %%rdx\n\t" \ + "imul %%rdx, %%rax\n\t" \ + "add %%rax, %%rsi\n\t" + +#define FIRMULREG(label, offset, firc)\ + LABEL_MANGLE(label)": \n\t" \ + "movslq "#offset"(%0), %%rax\n\t" \ + "imul %"#firc", %%rax\n\t" \ + "add %%rax, %%rsi\n\t" + +#define CLEAR_ACCUM \ + "xor %%rsi, %%rsi\n\t" + +#define SHIFT_ACCUM \ + "shr %%cl, %%rsi\n\t" + +#define ACCUM "%%rdx" +#define RESULT "%%rsi" +#define RESULT32 "%%esi" + +#else /* if ARCH_X86_32 */ + +#define MLPMUL(label, offset, offs, offc) \ + LABEL_MANGLE(label)": \n\t" \ + "mov "offset"+"offs"(%0), %%eax\n\t" \ + "imull "offset"+"offc"(%1) \n\t" \ + "add %%eax , %%esi\n\t" \ + "adc %%edx , %%ecx\n\t" + +#define FIRMULREG(label, offset, firc) \ + MLPMUL(label, #offset, "0", "0") + +#define CLEAR_ACCUM \ + "xor %%esi, %%esi\n\t" \ + "xor %%ecx, %%ecx\n\t" + +#define SHIFT_ACCUM \ + "mov %%ecx, %%edx\n\t" \ + "mov %%esi, %%eax\n\t" \ + "movzbl %7 , %%ecx\n\t" \ + "shrd %%cl, %%edx, %%eax\n\t" \ + +#define ACCUM "%%edx" +#define RESULT "%%eax" +#define RESULT32 "%%eax" + +#endif /* !ARCH_X86_64 */ + +#define BINC AV_STRINGIFY(4* MAX_CHANNELS) +#define IOFFS AV_STRINGIFY(4*(MAX_FIR_ORDER + MAX_BLOCKSIZE)) +#define IOFFC AV_STRINGIFY(4* MAX_FIR_ORDER) + +#define FIRMUL(label, offset) MLPMUL(label, #offset, "0", "0") +#define IIRMUL(label, offset) MLPMUL(label, #offset, IOFFS, IOFFC) + +static void mlp_filter_channel_x86(int32_t *state, const int32_t *coeff, + int firorder, int iirorder, + unsigned int filter_shift, int32_t mask, + int blocksize, int32_t *sample_buffer) +{ + const void *firjump = firtable[firorder]; + const void *iirjump = iirtable[iirorder]; + + blocksize = -blocksize; + + __asm__ volatile( + "1: \n\t" + CLEAR_ACCUM + "jmp *%5 \n\t" + FIRMUL (ff_mlp_firorder_8, 0x1c ) + FIRMUL (ff_mlp_firorder_7, 0x18 ) + FIRMUL (ff_mlp_firorder_6, 0x14 ) + FIRMUL (ff_mlp_firorder_5, 0x10 ) + FIRMUL (ff_mlp_firorder_4, 0x0c ) + FIRMULREG(ff_mlp_firorder_3, 0x08,10) + FIRMULREG(ff_mlp_firorder_2, 0x04, 9) + FIRMULREG(ff_mlp_firorder_1, 0x00, 8) + LABEL_MANGLE(ff_mlp_firorder_0)":\n\t" + "jmp *%6 \n\t" + IIRMUL (ff_mlp_iirorder_4, 0x0c ) + IIRMUL (ff_mlp_iirorder_3, 0x08 ) + IIRMUL (ff_mlp_iirorder_2, 0x04 ) + IIRMUL (ff_mlp_iirorder_1, 0x00 ) + LABEL_MANGLE(ff_mlp_iirorder_0)":\n\t" + SHIFT_ACCUM + "mov "RESULT" ,"ACCUM" \n\t" + "add (%2) ,"RESULT" \n\t" + "and %4 ,"RESULT" \n\t" + "sub $4 , %0 \n\t" + "mov "RESULT32", (%0) \n\t" + "mov "RESULT32", (%2) \n\t" + "add $"BINC" , %2 \n\t" + "sub "ACCUM" ,"RESULT" \n\t" + "mov "RESULT32","IOFFS"(%0) \n\t" + "incl %3 \n\t" + "js 1b \n\t" + : /* 0*/"+r"(state), + /* 1*/"+r"(coeff), + /* 2*/"+r"(sample_buffer), +#if ARCH_X86_64 + /* 3*/"+r"(blocksize) + : /* 4*/"r"((x86_reg)mask), /* 5*/"r"(firjump), + /* 6*/"r"(iirjump) , /* 7*/"c"(filter_shift) + , /* 8*/"r"((int64_t)coeff[0]) + , /* 9*/"r"((int64_t)coeff[1]) + , /*10*/"r"((int64_t)coeff[2]) + : "rax", "rdx", "rsi" +#else /* ARCH_X86_32 */ + /* 3*/"+m"(blocksize) + : /* 4*/"m"( mask), /* 5*/"m"(firjump), + /* 6*/"m"(iirjump) , /* 7*/"m"(filter_shift) + : "eax", "edx", "esi", "ecx" +#endif /* !ARCH_X86_64 */ + ); +} + +#endif /* HAVE_7REGS && HAVE_INLINE_ASM */ + +av_cold void ff_mlpdsp_init_x86(MLPDSPContext *c) +{ +#if HAVE_7REGS && HAVE_INLINE_ASM + c->mlp_filter_channel = mlp_filter_channel_x86; +#endif +} diff --git a/ffmpeg/libavcodec/x86/motion_est.c b/ffmpeg/libavcodec/x86/motion_est.c new file mode 100644 index 0000000..3ffb002 --- /dev/null +++ b/ffmpeg/libavcodec/x86/motion_est.c @@ -0,0 +1,473 @@ +/* + * MMX optimized motion estimation + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * mostly 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 "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "dsputil_mmx.h" + +#if HAVE_INLINE_ASM + +DECLARE_ASM_CONST(8, uint64_t, round_tab)[3]={ +0x0000000000000000ULL, +0x0001000100010001ULL, +0x0002000200020002ULL, +}; + +DECLARE_ASM_CONST(8, uint64_t, bone)= 0x0101010101010101LL; + +static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +{ + x86_reg len= -(x86_reg)stride*h; + __asm__ volatile( + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq (%2, %%"REG_a"), %%mm2 \n\t" + "movq (%2, %%"REG_a"), %%mm4 \n\t" + "add %3, %%"REG_a" \n\t" + "psubusb %%mm0, %%mm2 \n\t" + "psubusb %%mm4, %%mm0 \n\t" + "movq (%1, %%"REG_a"), %%mm1 \n\t" + "movq (%2, %%"REG_a"), %%mm3 \n\t" + "movq (%2, %%"REG_a"), %%mm5 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm5, %%mm1 \n\t" + "por %%mm2, %%mm0 \n\t" + "por %%mm1, %%mm3 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm3, %%mm2 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpcklbw %%mm7, %%mm3 \n\t" + "punpckhbw %%mm7, %%mm2 \n\t" + "paddw %%mm1, %%mm0 \n\t" + "paddw %%mm3, %%mm2 \n\t" + "paddw %%mm2, %%mm0 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "add %3, %%"REG_a" \n\t" + " js 1b \n\t" + : "+a" (len) + : "r" (blk1 - len), "r" (blk2 - len), "r" ((x86_reg)stride) + ); +} + +static inline void sad8_1_mmxext(uint8_t *blk1, uint8_t *blk2, + int stride, int h) +{ + __asm__ volatile( + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1), %%mm0 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "psadbw (%2), %%mm0 \n\t" + "psadbw (%2, %3), %%mm1 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "paddw %%mm1, %%mm6 \n\t" + "lea (%1,%3,2), %1 \n\t" + "lea (%2,%3,2), %2 \n\t" + "sub $2, %0 \n\t" + " jg 1b \n\t" + : "+r" (h), "+r" (blk1), "+r" (blk2) + : "r" ((x86_reg)stride) + ); +} + +static int sad16_sse2(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h) +{ + int ret; + __asm__ volatile( + "pxor %%xmm2, %%xmm2 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movdqu (%1), %%xmm0 \n\t" + "movdqu (%1, %4), %%xmm1 \n\t" + "psadbw (%2), %%xmm0 \n\t" + "psadbw (%2, %4), %%xmm1 \n\t" + "paddw %%xmm0, %%xmm2 \n\t" + "paddw %%xmm1, %%xmm2 \n\t" + "lea (%1,%4,2), %1 \n\t" + "lea (%2,%4,2), %2 \n\t" + "sub $2, %0 \n\t" + " jg 1b \n\t" + "movhlps %%xmm2, %%xmm0 \n\t" + "paddw %%xmm0, %%xmm2 \n\t" + "movd %%xmm2, %3 \n\t" + : "+r" (h), "+r" (blk1), "+r" (blk2), "=r"(ret) + : "r" ((x86_reg)stride) + ); + return ret; +} + +static inline void sad8_x2a_mmxext(uint8_t *blk1, uint8_t *blk2, + int stride, int h) +{ + __asm__ volatile( + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1), %%mm0 \n\t" + "movq (%1, %3), %%mm1 \n\t" + "pavgb 1(%1), %%mm0 \n\t" + "pavgb 1(%1, %3), %%mm1 \n\t" + "psadbw (%2), %%mm0 \n\t" + "psadbw (%2, %3), %%mm1 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "paddw %%mm1, %%mm6 \n\t" + "lea (%1,%3,2), %1 \n\t" + "lea (%2,%3,2), %2 \n\t" + "sub $2, %0 \n\t" + " jg 1b \n\t" + : "+r" (h), "+r" (blk1), "+r" (blk2) + : "r" ((x86_reg)stride) + ); +} + +static inline void sad8_y2a_mmxext(uint8_t *blk1, uint8_t *blk2, + int stride, int h) +{ + __asm__ volatile( + "movq (%1), %%mm0 \n\t" + "add %3, %1 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1), %%mm1 \n\t" + "movq (%1, %3), %%mm2 \n\t" + "pavgb %%mm1, %%mm0 \n\t" + "pavgb %%mm2, %%mm1 \n\t" + "psadbw (%2), %%mm0 \n\t" + "psadbw (%2, %3), %%mm1 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "paddw %%mm1, %%mm6 \n\t" + "movq %%mm2, %%mm0 \n\t" + "lea (%1,%3,2), %1 \n\t" + "lea (%2,%3,2), %2 \n\t" + "sub $2, %0 \n\t" + " jg 1b \n\t" + : "+r" (h), "+r" (blk1), "+r" (blk2) + : "r" ((x86_reg)stride) + ); +} + +static inline void sad8_4_mmxext(uint8_t *blk1, uint8_t *blk2, + int stride, int h) +{ + __asm__ volatile( + "movq "MANGLE(bone)", %%mm5 \n\t" + "movq (%1), %%mm0 \n\t" + "pavgb 1(%1), %%mm0 \n\t" + "add %3, %1 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1), %%mm1 \n\t" + "movq (%1,%3), %%mm2 \n\t" + "pavgb 1(%1), %%mm1 \n\t" + "pavgb 1(%1,%3), %%mm2 \n\t" + "psubusb %%mm5, %%mm1 \n\t" + "pavgb %%mm1, %%mm0 \n\t" + "pavgb %%mm2, %%mm1 \n\t" + "psadbw (%2), %%mm0 \n\t" + "psadbw (%2,%3), %%mm1 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "paddw %%mm1, %%mm6 \n\t" + "movq %%mm2, %%mm0 \n\t" + "lea (%1,%3,2), %1 \n\t" + "lea (%2,%3,2), %2 \n\t" + "sub $2, %0 \n\t" + " jg 1b \n\t" + : "+r" (h), "+r" (blk1), "+r" (blk2) + : "r" ((x86_reg)stride) + ); +} + +static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, int stride, int h) +{ + x86_reg len= -(x86_reg)stride*h; + __asm__ volatile( + ".p2align 4 \n\t" + "1: \n\t" + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq (%2, %%"REG_a"), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm2 \n\t" + "movq (%2, %%"REG_a"), %%mm3 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm1 \n\t" + "punpckhbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "paddw %%mm0, %%mm1 \n\t" + "paddw %%mm2, %%mm3 \n\t" + "movq (%3, %%"REG_a"), %%mm4 \n\t" + "movq (%3, %%"REG_a"), %%mm2 \n\t" + "paddw %%mm5, %%mm1 \n\t" + "paddw %%mm5, %%mm3 \n\t" + "psrlw $1, %%mm1 \n\t" + "psrlw $1, %%mm3 \n\t" + "packuswb %%mm3, %%mm1 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm2, %%mm1 \n\t" + "por %%mm4, %%mm1 \n\t" + "movq %%mm1, %%mm0 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "paddw %%mm1, %%mm0 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "add %4, %%"REG_a" \n\t" + " js 1b \n\t" + : "+a" (len) + : "r" (blk1a - len), "r" (blk1b -len), "r" (blk2 - len), "r" ((x86_reg)stride) + ); +} + +static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +{ + x86_reg len= -(x86_reg)stride*h; + __asm__ volatile( + "movq (%1, %%"REG_a"), %%mm0 \n\t" + "movq 1(%1, %%"REG_a"), %%mm2 \n\t" + "movq %%mm0, %%mm1 \n\t" + "movq %%mm2, %%mm3 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpckhbw %%mm7, %%mm1 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "paddw %%mm2, %%mm0 \n\t" + "paddw %%mm3, %%mm1 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%2, %%"REG_a"), %%mm2 \n\t" + "movq 1(%2, %%"REG_a"), %%mm4 \n\t" + "movq %%mm2, %%mm3 \n\t" + "movq %%mm4, %%mm5 \n\t" + "punpcklbw %%mm7, %%mm2 \n\t" + "punpckhbw %%mm7, %%mm3 \n\t" + "punpcklbw %%mm7, %%mm4 \n\t" + "punpckhbw %%mm7, %%mm5 \n\t" + "paddw %%mm4, %%mm2 \n\t" + "paddw %%mm5, %%mm3 \n\t" + "movq 16+"MANGLE(round_tab)", %%mm5 \n\t" + "paddw %%mm2, %%mm0 \n\t" + "paddw %%mm3, %%mm1 \n\t" + "paddw %%mm5, %%mm0 \n\t" + "paddw %%mm5, %%mm1 \n\t" + "movq (%3, %%"REG_a"), %%mm4 \n\t" + "movq (%3, %%"REG_a"), %%mm5 \n\t" + "psrlw $2, %%mm0 \n\t" + "psrlw $2, %%mm1 \n\t" + "packuswb %%mm1, %%mm0 \n\t" + "psubusb %%mm0, %%mm4 \n\t" + "psubusb %%mm5, %%mm0 \n\t" + "por %%mm4, %%mm0 \n\t" + "movq %%mm0, %%mm4 \n\t" + "punpcklbw %%mm7, %%mm0 \n\t" + "punpckhbw %%mm7, %%mm4 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "paddw %%mm4, %%mm6 \n\t" + "movq %%mm2, %%mm0 \n\t" + "movq %%mm3, %%mm1 \n\t" + "add %4, %%"REG_a" \n\t" + " js 1b \n\t" + : "+a" (len) + : "r" (blk1 - len), "r" (blk1 -len + stride), "r" (blk2 - len), "r" ((x86_reg)stride) + ); +} + +static inline int sum_mmx(void) +{ + int ret; + __asm__ volatile( + "movq %%mm6, %%mm0 \n\t" + "psrlq $32, %%mm6 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "movq %%mm6, %%mm0 \n\t" + "psrlq $16, %%mm6 \n\t" + "paddw %%mm0, %%mm6 \n\t" + "movd %%mm6, %0 \n\t" + : "=r" (ret) + ); + return ret&0xFFFF; +} + +static inline int sum_mmxext(void) +{ + int ret; + __asm__ volatile( + "movd %%mm6, %0 \n\t" + : "=r" (ret) + ); + return ret; +} + +static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +{ + sad8_2_mmx(blk1, blk1+1, blk2, stride, h); +} +static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h) +{ + sad8_2_mmx(blk1, blk1+stride, blk2, stride, h); +} + + +#define PIX_SAD(suf)\ +static int sad8_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + av_assert2(h==8);\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t":);\ +\ + sad8_1_ ## suf(blk1, blk2, stride, 8);\ +\ + return sum_ ## suf();\ +}\ +static int sad8_x2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + av_assert2(h==8);\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "movq %0, %%mm5 \n\t"\ + :: "m"(round_tab[1]) \ + );\ +\ + sad8_x2a_ ## suf(blk1, blk2, stride, 8);\ +\ + return sum_ ## suf();\ +}\ +\ +static int sad8_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + av_assert2(h==8);\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "movq %0, %%mm5 \n\t"\ + :: "m"(round_tab[1]) \ + );\ +\ + sad8_y2a_ ## suf(blk1, blk2, stride, 8);\ +\ + return sum_ ## suf();\ +}\ +\ +static int sad8_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + av_assert2(h==8);\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + ::);\ +\ + sad8_4_ ## suf(blk1, blk2, stride, 8);\ +\ + return sum_ ## suf();\ +}\ +\ +static int sad16_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t":);\ +\ + sad8_1_ ## suf(blk1 , blk2 , stride, h);\ + sad8_1_ ## suf(blk1+8, blk2+8, stride, h);\ +\ + return sum_ ## suf();\ +}\ +static int sad16_x2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "movq %0, %%mm5 \n\t"\ + :: "m"(round_tab[1]) \ + );\ +\ + sad8_x2a_ ## suf(blk1 , blk2 , stride, h);\ + sad8_x2a_ ## suf(blk1+8, blk2+8, stride, h);\ +\ + return sum_ ## suf();\ +}\ +static int sad16_y2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + "movq %0, %%mm5 \n\t"\ + :: "m"(round_tab[1]) \ + );\ +\ + sad8_y2a_ ## suf(blk1 , blk2 , stride, h);\ + sad8_y2a_ ## suf(blk1+8, blk2+8, stride, h);\ +\ + return sum_ ## suf();\ +}\ +static int sad16_xy2_ ## suf(void *v, uint8_t *blk2, uint8_t *blk1, int stride, int h)\ +{\ + __asm__ volatile("pxor %%mm7, %%mm7 \n\t"\ + "pxor %%mm6, %%mm6 \n\t"\ + ::);\ +\ + sad8_4_ ## suf(blk1 , blk2 , stride, h);\ + sad8_4_ ## suf(blk1+8, blk2+8, stride, h);\ +\ + return sum_ ## suf();\ +}\ + +PIX_SAD(mmx) +PIX_SAD(mmxext) + +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_dsputil_init_pix_mmx(DSPContext *c, AVCodecContext *avctx) +{ +#if HAVE_INLINE_ASM + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_MMX) { + c->pix_abs[0][0] = sad16_mmx; + c->pix_abs[0][1] = sad16_x2_mmx; + c->pix_abs[0][2] = sad16_y2_mmx; + c->pix_abs[0][3] = sad16_xy2_mmx; + c->pix_abs[1][0] = sad8_mmx; + c->pix_abs[1][1] = sad8_x2_mmx; + c->pix_abs[1][2] = sad8_y2_mmx; + c->pix_abs[1][3] = sad8_xy2_mmx; + + c->sad[0]= sad16_mmx; + c->sad[1]= sad8_mmx; + } + if (mm_flags & AV_CPU_FLAG_MMXEXT) { + c->pix_abs[0][0] = sad16_mmxext; + c->pix_abs[1][0] = sad8_mmxext; + + c->sad[0] = sad16_mmxext; + c->sad[1] = sad8_mmxext; + + if(!(avctx->flags & CODEC_FLAG_BITEXACT)){ + c->pix_abs[0][1] = sad16_x2_mmxext; + c->pix_abs[0][2] = sad16_y2_mmxext; + c->pix_abs[0][3] = sad16_xy2_mmxext; + c->pix_abs[1][1] = sad8_x2_mmxext; + c->pix_abs[1][2] = sad8_y2_mmxext; + c->pix_abs[1][3] = sad8_xy2_mmxext; + } + } + if ((mm_flags & AV_CPU_FLAG_SSE2) && !(mm_flags & AV_CPU_FLAG_3DNOW) && avctx->codec_id != AV_CODEC_ID_SNOW) { + c->sad[0]= sad16_sse2; + } +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/x86/mpeg4qpel.asm b/ffmpeg/libavcodec/x86/mpeg4qpel.asm new file mode 100644 index 0000000..ca52375 --- /dev/null +++ b/ffmpeg/libavcodec/x86/mpeg4qpel.asm @@ -0,0 +1,560 @@ +;****************************************************************************** +;* mpeg4 qpel +;* Copyright (c) 2003 Michael Niedermayer +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2013 Daniel Kang +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA +cextern pb_1 +cextern pw_3 +cextern pw_15 +cextern pw_16 +cextern pw_20 + + +SECTION_TEXT + +; put_no_rnd_pixels8_l2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +%macro PUT_NO_RND_PIXELS8_L2 0 +cglobal put_no_rnd_pixels8_l2, 6,6 + movsxdifnidn r4, r4d + movsxdifnidn r3, r3d + pcmpeqb m6, m6 + test r5d, 1 + je .loop + mova m0, [r1] + mova m1, [r2] + add r1, r4 + add r2, 8 + pxor m0, m6 + pxor m1, m6 + PAVGB m0, m1 + pxor m0, m6 + mova [r0], m0 + add r0, r3 + dec r5d +.loop: + mova m0, [r1] + add r1, r4 + mova m1, [r1] + add r1, r4 + mova m2, [r2] + mova m3, [r2+8] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m2 + PAVGB m1, m3 + pxor m0, m6 + pxor m1, m6 + mova [r0], m0 + add r0, r3 + mova [r0], m1 + add r0, r3 + mova m0, [r1] + add r1, r4 + mova m1, [r1] + add r1, r4 + mova m2, [r2+16] + mova m3, [r2+24] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m2 + PAVGB m1, m3 + pxor m0, m6 + pxor m1, m6 + mova [r0], m0 + add r0, r3 + mova [r0], m1 + add r0, r3 + add r2, 32 + sub r5d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS8_L2 + + +; put_no_rnd_pixels16_l2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +%macro PUT_NO_RND_PIXELS16_l2 0 +cglobal put_no_rnd_pixels16_l2, 6,6 + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + pcmpeqb m6, m6 + test r5d, 1 + je .loop + mova m0, [r1] + mova m1, [r1+8] + mova m2, [r2] + mova m3, [r2+8] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m2 + PAVGB m1, m3 + pxor m0, m6 + pxor m1, m6 + add r1, r4 + add r2, 16 + mova [r0], m0 + mova [r0+8], m1 + add r0, r3 + dec r5d +.loop: + mova m0, [r1] + mova m1, [r1+8] + add r1, r4 + mova m2, [r2] + mova m3, [r2+8] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m2 + PAVGB m1, m3 + pxor m0, m6 + pxor m1, m6 + mova [r0], m0 + mova [r0+8], m1 + add r0, r3 + mova m0, [r1] + mova m1, [r1+8] + add r1, r4 + mova m2, [r2+16] + mova m3, [r2+24] + pxor m0, m6 + pxor m1, m6 + pxor m2, m6 + pxor m3, m6 + PAVGB m0, m2 + PAVGB m1, m3 + pxor m0, m6 + pxor m1, m6 + mova [r0], m0 + mova [r0+8], m1 + add r0, r3 + add r2, 32 + sub r5d, 2 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PUT_NO_RND_PIXELS16_l2 +INIT_MMX 3dnow +PUT_NO_RND_PIXELS16_l2 + +%macro MPEG4_QPEL16_H_LOWPASS 1 +cglobal %1_mpeg4_qpel16_h_lowpass, 5, 5, 0, 16 + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + pxor m7, m7 +.loop: + mova m0, [r1] + mova m1, m0 + mova m2, m0 + punpcklbw m0, m7 + punpckhbw m1, m7 + pshufw m5, m0, 0x90 + pshufw m6, m0, 0x41 + mova m3, m2 + mova m4, m2 + psllq m2, 8 + psllq m3, 16 + psllq m4, 24 + punpckhbw m2, m7 + punpckhbw m3, m7 + punpckhbw m4, m7 + paddw m5, m3 + paddw m6, m2 + paddw m5, m5 + psubw m6, m5 + pshufw m5, m0, 6 + pmullw m6, [pw_3] + paddw m0, m4 + paddw m5, m1 + pmullw m0, [pw_20] + psubw m0, m5 + paddw m6, [PW_ROUND] + paddw m0, m6 + psraw m0, 5 + mova [rsp+8], m0 + mova m0, [r1+5] + mova m5, m0 + mova m6, m0 + psrlq m0, 8 + psrlq m5, 16 + punpcklbw m0, m7 + punpcklbw m5, m7 + paddw m2, m0 + paddw m3, m5 + paddw m2, m2 + psubw m3, m2 + mova m2, m6 + psrlq m6, 24 + punpcklbw m2, m7 + punpcklbw m6, m7 + pmullw m3, [pw_3] + paddw m1, m2 + paddw m4, m6 + pmullw m1, [pw_20] + psubw m3, m4 + paddw m1, [PW_ROUND] + paddw m3, m1 + psraw m3, 5 + mova m1, [rsp+8] + packuswb m1, m3 + OP_MOV [r0], m1, m4 + mova m1, [r1+9] + mova m4, m1 + mova m3, m1 + psrlq m1, 8 + psrlq m4, 16 + punpcklbw m1, m7 + punpcklbw m4, m7 + paddw m5, m1 + paddw m0, m4 + paddw m5, m5 + psubw m0, m5 + mova m5, m3 + psrlq m3, 24 + pmullw m0, [pw_3] + punpcklbw m3, m7 + paddw m2, m3 + psubw m0, m2 + mova m2, m5 + punpcklbw m2, m7 + punpckhbw m5, m7 + paddw m6, m2 + pmullw m6, [pw_20] + paddw m0, [PW_ROUND] + paddw m0, m6 + psraw m0, 5 + paddw m3, m5 + pshufw m6, m5, 0xf9 + paddw m6, m4 + pshufw m4, m5, 0xbe + pshufw m5, m5, 0x6f + paddw m4, m1 + paddw m5, m2 + paddw m6, m6 + psubw m4, m6 + pmullw m3, [pw_20] + pmullw m4, [pw_3] + psubw m3, m5 + paddw m4, [PW_ROUND] + paddw m4, m3 + psraw m4, 5 + packuswb m0, m4 + OP_MOV [r0+8], m0, m4 + add r1, r3 + add r0, r2 + dec r4d + jne .loop + REP_RET +%endmacro + +%macro PUT_OP 2-3 + mova %1, %2 +%endmacro + +%macro AVG_OP 2-3 + mova %3, %1 + pavgb %2, %3 + mova %1, %2 +%endmacro + +INIT_MMX mmxext +%define PW_ROUND pw_16 +%define OP_MOV PUT_OP +MPEG4_QPEL16_H_LOWPASS put +%define PW_ROUND pw_16 +%define OP_MOV AVG_OP +MPEG4_QPEL16_H_LOWPASS avg +%define PW_ROUND pw_15 +%define OP_MOV PUT_OP +MPEG4_QPEL16_H_LOWPASS put_no_rnd + + + +%macro MPEG4_QPEL8_H_LOWPASS 1 +cglobal %1_mpeg4_qpel8_h_lowpass, 5, 5, 0, 8 + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + pxor m7, m7 +.loop: + mova m0, [r1] + mova m1, m0 + mova m2, m0 + punpcklbw m0, m7 + punpckhbw m1, m7 + pshufw m5, m0, 0x90 + pshufw m6, m0, 0x41 + mova m3, m2 + mova m4, m2 + psllq m2, 8 + psllq m3, 16 + psllq m4, 24 + punpckhbw m2, m7 + punpckhbw m3, m7 + punpckhbw m4, m7 + paddw m5, m3 + paddw m6, m2 + paddw m5, m5 + psubw m6, m5 + pshufw m5, m0, 0x6 + pmullw m6, [pw_3] + paddw m0, m4 + paddw m5, m1 + pmullw m0, [pw_20] + psubw m0, m5 + paddw m6, [PW_ROUND] + paddw m0, m6 + psraw m0, 5 + movh m5, [r1+5] + punpcklbw m5, m7 + pshufw m6, m5, 0xf9 + paddw m1, m5 + paddw m2, m6 + pshufw m6, m5, 0xbe + pshufw m5, m5, 0x6f + paddw m3, m6 + paddw m4, m5 + paddw m2, m2 + psubw m3, m2 + pmullw m1, [pw_20] + pmullw m3, [pw_3] + psubw m3, m4 + paddw m1, [PW_ROUND] + paddw m3, m1 + psraw m3, 5 + packuswb m0, m3 + OP_MOV [r0], m0, m4 + add r1, r3 + add r0, r2 + dec r4d + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +%define PW_ROUND pw_16 +%define OP_MOV PUT_OP +MPEG4_QPEL8_H_LOWPASS put +%define PW_ROUND pw_16 +%define OP_MOV AVG_OP +MPEG4_QPEL8_H_LOWPASS avg +%define PW_ROUND pw_15 +%define OP_MOV PUT_OP +MPEG4_QPEL8_H_LOWPASS put_no_rnd + + + +%macro QPEL_V_LOW 5 + paddw m0, m1 + mova m4, [pw_20] + pmullw m4, m0 + mova m0, %4 + mova m5, %1 + paddw m5, m0 + psubw m4, m5 + mova m5, %2 + mova m6, %3 + paddw m5, m3 + paddw m6, m2 + paddw m6, m6 + psubw m5, m6 + pmullw m5, [pw_3] + paddw m4, [PW_ROUND] + paddw m5, m4 + psraw m5, 5 + packuswb m5, m5 + OP_MOV %5, m5, m7 + SWAP 0,1,2,3 +%endmacro + +%macro MPEG4_QPEL16_V_LOWPASS 1 +cglobal %1_mpeg4_qpel16_v_lowpass, 4, 6, 0, 544 + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + + mov r4d, 17 + mov r5, rsp + pxor m7, m7 +.looph: + mova m0, [r1] + mova m1, [r1] + mova m2, [r1+8] + mova m3, [r1+8] + punpcklbw m0, m7 + punpckhbw m1, m7 + punpcklbw m2, m7 + punpckhbw m3, m7 + mova [r5], m0 + mova [r5+0x88], m1 + mova [r5+0x110], m2 + mova [r5+0x198], m3 + add r5, 8 + add r1, r3 + dec r4d + jne .looph + + + ; NOTE: r1 CHANGES VALUES: r1 -> 4 - 14*dstStride + mov r4d, 4 + mov r1, 4 + neg r2 + lea r1, [r1+r2*8] + lea r1, [r1+r2*4] + lea r1, [r1+r2*2] + neg r2 + mov r5, rsp +.loopv: + pxor m7, m7 + mova m0, [r5+ 0x0] + mova m1, [r5+ 0x8] + mova m2, [r5+0x10] + mova m3, [r5+0x18] + QPEL_V_LOW [r5+0x10], [r5+ 0x8], [r5+ 0x0], [r5+0x20], [r0] + QPEL_V_LOW [r5+ 0x8], [r5+ 0x0], [r5+ 0x0], [r5+0x28], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+ 0x0], [r5+ 0x0], [r5+ 0x8], [r5+0x30], [r0] + QPEL_V_LOW [r5+ 0x0], [r5+ 0x8], [r5+0x10], [r5+0x38], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+ 0x8], [r5+0x10], [r5+0x18], [r5+0x40], [r0] + QPEL_V_LOW [r5+0x10], [r5+0x18], [r5+0x20], [r5+0x48], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+0x18], [r5+0x20], [r5+0x28], [r5+0x50], [r0] + QPEL_V_LOW [r5+0x20], [r5+0x28], [r5+0x30], [r5+0x58], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+0x28], [r5+0x30], [r5+0x38], [r5+0x60], [r0] + QPEL_V_LOW [r5+0x30], [r5+0x38], [r5+0x40], [r5+0x68], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+0x38], [r5+0x40], [r5+0x48], [r5+0x70], [r0] + QPEL_V_LOW [r5+0x40], [r5+0x48], [r5+0x50], [r5+0x78], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+0x48], [r5+0x50], [r5+0x58], [r5+0x80], [r0] + QPEL_V_LOW [r5+0x50], [r5+0x58], [r5+0x60], [r5+0x80], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+0x58], [r5+0x60], [r5+0x68], [r5+0x78], [r0] + QPEL_V_LOW [r5+0x60], [r5+0x68], [r5+0x70], [r5+0x70], [r0+r2] + + add r5, 0x88 + add r0, r1 + dec r4d + jne .loopv + REP_RET +%endmacro + +%macro PUT_OPH 2-3 + movh %1, %2 +%endmacro + +%macro AVG_OPH 2-3 + movh %3, %1 + pavgb %2, %3 + movh %1, %2 +%endmacro + +INIT_MMX mmxext +%define PW_ROUND pw_16 +%define OP_MOV PUT_OPH +MPEG4_QPEL16_V_LOWPASS put +%define PW_ROUND pw_16 +%define OP_MOV AVG_OPH +MPEG4_QPEL16_V_LOWPASS avg +%define PW_ROUND pw_15 +%define OP_MOV PUT_OPH +MPEG4_QPEL16_V_LOWPASS put_no_rnd + + + +%macro MPEG4_QPEL8_V_LOWPASS 1 +cglobal %1_mpeg4_qpel8_v_lowpass, 4, 6, 0, 288 + movsxdifnidn r2, r2d + movsxdifnidn r3, r3d + + mov r4d, 9 + mov r5, rsp + pxor m7, m7 +.looph: + mova m0, [r1] + mova m1, [r1] + punpcklbw m0, m7 + punpckhbw m1, m7 + mova [r5], m0 + mova [r5+0x48], m1 + add r5, 8 + add r1, r3 + dec r4d + jne .looph + + + ; NOTE: r1 CHANGES VALUES: r1 -> 4 - 6*dstStride + mov r4d, 2 + mov r1, 4 + neg r2 + lea r1, [r1+r2*4] + lea r1, [r1+r2*2] + neg r2 + mov r5, rsp +.loopv: + pxor m7, m7 + mova m0, [r5+ 0x0] + mova m1, [r5+ 0x8] + mova m2, [r5+0x10] + mova m3, [r5+0x18] + QPEL_V_LOW [r5+0x10], [r5+ 0x8], [r5+ 0x0], [r5+0x20], [r0] + QPEL_V_LOW [r5+ 0x8], [r5+ 0x0], [r5+ 0x0], [r5+0x28], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+ 0x0], [r5+ 0x0], [r5+ 0x8], [r5+0x30], [r0] + QPEL_V_LOW [r5+ 0x0], [r5+ 0x8], [r5+0x10], [r5+0x38], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+ 0x8], [r5+0x10], [r5+0x18], [r5+0x40], [r0] + QPEL_V_LOW [r5+0x10], [r5+0x18], [r5+0x20], [r5+0x40], [r0+r2] + lea r0, [r0+r2*2] + QPEL_V_LOW [r5+0x18], [r5+0x20], [r5+0x28], [r5+0x38], [r0] + QPEL_V_LOW [r5+0x20], [r5+0x28], [r5+0x30], [r5+0x30], [r0+r2] + + add r5, 0x48 + add r0, r1 + dec r4d + jne .loopv + REP_RET +%endmacro + +INIT_MMX mmxext +%define PW_ROUND pw_16 +%define OP_MOV PUT_OPH +MPEG4_QPEL8_V_LOWPASS put +%define PW_ROUND pw_16 +%define OP_MOV AVG_OPH +MPEG4_QPEL8_V_LOWPASS avg +%define PW_ROUND pw_15 +%define OP_MOV PUT_OPH +MPEG4_QPEL8_V_LOWPASS put_no_rnd diff --git a/ffmpeg/libavcodec/x86/mpegaudiodec.c b/ffmpeg/libavcodec/x86/mpegaudiodec.c new file mode 100644 index 0000000..287d8ff --- /dev/null +++ b/ffmpeg/libavcodec/x86/mpegaudiodec.c @@ -0,0 +1,273 @@ +/* + * MMX optimized MP3 decoding functions + * Copyright (c) 2010 Vitor Sessak + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/internal.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/mpegaudiodsp.h" + +#define DECL(CPU)\ +static void imdct36_blocks_ ## CPU(float *out, float *buf, float *in, int count, int switch_point, int block_type);\ +void ff_imdct36_float_ ## CPU(float *out, float *buf, float *in, float *win); + +DECL(sse) +DECL(sse2) +DECL(sse3) +DECL(ssse3) +DECL(avx) + +void ff_four_imdct36_float_sse(float *out, float *buf, float *in, float *win, + float *tmpbuf); +void ff_four_imdct36_float_avx(float *out, float *buf, float *in, float *win, + float *tmpbuf); + +DECLARE_ALIGNED(16, static float, mdct_win_sse)[2][4][4*40]; + +#if HAVE_SSE2_INLINE + +#define MACS(rt, ra, rb) rt+=(ra)*(rb) +#define MLSS(rt, ra, rb) rt-=(ra)*(rb) + +#define SUM8(op, sum, w, p) \ +{ \ + op(sum, (w)[0 * 64], (p)[0 * 64]); \ + op(sum, (w)[1 * 64], (p)[1 * 64]); \ + op(sum, (w)[2 * 64], (p)[2 * 64]); \ + op(sum, (w)[3 * 64], (p)[3 * 64]); \ + op(sum, (w)[4 * 64], (p)[4 * 64]); \ + op(sum, (w)[5 * 64], (p)[5 * 64]); \ + op(sum, (w)[6 * 64], (p)[6 * 64]); \ + op(sum, (w)[7 * 64], (p)[7 * 64]); \ +} + +static void apply_window(const float *buf, const float *win1, + const float *win2, float *sum1, float *sum2, int len) +{ + x86_reg count = - 4*len; + const float *win1a = win1+len; + const float *win2a = win2+len; + const float *bufa = buf+len; + float *sum1a = sum1+len; + float *sum2a = sum2+len; + + +#define MULT(a, b) \ + "movaps " #a "(%1,%0), %%xmm1 \n\t" \ + "movaps " #a "(%3,%0), %%xmm2 \n\t" \ + "mulps %%xmm2, %%xmm1 \n\t" \ + "subps %%xmm1, %%xmm0 \n\t" \ + "mulps " #b "(%2,%0), %%xmm2 \n\t" \ + "subps %%xmm2, %%xmm4 \n\t" \ + + __asm__ volatile( + "1: \n\t" + "xorps %%xmm0, %%xmm0 \n\t" + "xorps %%xmm4, %%xmm4 \n\t" + + MULT( 0, 0) + MULT( 256, 64) + MULT( 512, 128) + MULT( 768, 192) + MULT(1024, 256) + MULT(1280, 320) + MULT(1536, 384) + MULT(1792, 448) + + "movaps %%xmm0, (%4,%0) \n\t" + "movaps %%xmm4, (%5,%0) \n\t" + "add $16, %0 \n\t" + "jl 1b \n\t" + :"+&r"(count) + :"r"(win1a), "r"(win2a), "r"(bufa), "r"(sum1a), "r"(sum2a) + ); + +#undef MULT +} + +static void apply_window_mp3(float *in, float *win, int *unused, float *out, + int incr) +{ + LOCAL_ALIGNED_16(float, suma, [17]); + LOCAL_ALIGNED_16(float, sumb, [17]); + LOCAL_ALIGNED_16(float, sumc, [17]); + LOCAL_ALIGNED_16(float, sumd, [17]); + + float sum; + + /* copy to avoid wrap */ + __asm__ volatile( + "movaps 0(%0), %%xmm0 \n\t" \ + "movaps 16(%0), %%xmm1 \n\t" \ + "movaps 32(%0), %%xmm2 \n\t" \ + "movaps 48(%0), %%xmm3 \n\t" \ + "movaps %%xmm0, 0(%1) \n\t" \ + "movaps %%xmm1, 16(%1) \n\t" \ + "movaps %%xmm2, 32(%1) \n\t" \ + "movaps %%xmm3, 48(%1) \n\t" \ + "movaps 64(%0), %%xmm0 \n\t" \ + "movaps 80(%0), %%xmm1 \n\t" \ + "movaps 96(%0), %%xmm2 \n\t" \ + "movaps 112(%0), %%xmm3 \n\t" \ + "movaps %%xmm0, 64(%1) \n\t" \ + "movaps %%xmm1, 80(%1) \n\t" \ + "movaps %%xmm2, 96(%1) \n\t" \ + "movaps %%xmm3, 112(%1) \n\t" + ::"r"(in), "r"(in+512) + :"memory" + ); + + apply_window(in + 16, win , win + 512, suma, sumc, 16); + apply_window(in + 32, win + 48, win + 640, sumb, sumd, 16); + + SUM8(MACS, suma[0], win + 32, in + 48); + + sumc[ 0] = 0; + sumb[16] = 0; + sumd[16] = 0; + +#define SUMS(suma, sumb, sumc, sumd, out1, out2) \ + "movups " #sumd "(%4), %%xmm0 \n\t" \ + "shufps $0x1b, %%xmm0, %%xmm0 \n\t" \ + "subps " #suma "(%1), %%xmm0 \n\t" \ + "movaps %%xmm0," #out1 "(%0) \n\t" \ +\ + "movups " #sumc "(%3), %%xmm0 \n\t" \ + "shufps $0x1b, %%xmm0, %%xmm0 \n\t" \ + "addps " #sumb "(%2), %%xmm0 \n\t" \ + "movaps %%xmm0," #out2 "(%0) \n\t" + + if (incr == 1) { + __asm__ volatile( + SUMS( 0, 48, 4, 52, 0, 112) + SUMS(16, 32, 20, 36, 16, 96) + SUMS(32, 16, 36, 20, 32, 80) + SUMS(48, 0, 52, 4, 48, 64) + + :"+&r"(out) + :"r"(&suma[0]), "r"(&sumb[0]), "r"(&sumc[0]), "r"(&sumd[0]) + :"memory" + ); + out += 16*incr; + } else { + int j; + float *out2 = out + 32 * incr; + out[0 ] = -suma[ 0]; + out += incr; + out2 -= incr; + for(j=1;j<16;j++) { + *out = -suma[ j] + sumd[16-j]; + *out2 = sumb[16-j] + sumc[ j]; + out += incr; + out2 -= incr; + } + } + + sum = 0; + SUM8(MLSS, sum, win + 16 + 32, in + 32); + *out = sum; +} + +#endif /* HAVE_SSE2_INLINE */ + +#if HAVE_YASM +#define DECL_IMDCT_BLOCKS(CPU1, CPU2) \ +static void imdct36_blocks_ ## CPU1(float *out, float *buf, float *in, \ + int count, int switch_point, int block_type) \ +{ \ + int align_end = count - (count & 3); \ + int j; \ + for (j = 0; j < align_end; j+= 4) { \ + LOCAL_ALIGNED_16(float, tmpbuf, [1024]); \ + float *win = mdct_win_sse[switch_point && j < 4][block_type]; \ + /* apply window & overlap with previous buffer */ \ + \ + /* select window */ \ + ff_four_imdct36_float_ ## CPU2(out, buf, in, win, tmpbuf); \ + in += 4*18; \ + buf += 4*18; \ + out += 4; \ + } \ + for (; j < count; j++) { \ + /* apply window & overlap with previous buffer */ \ + \ + /* select window */ \ + int win_idx = (switch_point && j < 2) ? 0 : block_type; \ + float *win = ff_mdct_win_float[win_idx + (4 & -(j & 1))]; \ + \ + ff_imdct36_float_ ## CPU1(out, buf, in, win); \ + \ + in += 18; \ + buf++; \ + out++; \ + } \ +} + +#if HAVE_SSE +DECL_IMDCT_BLOCKS(sse,sse) +DECL_IMDCT_BLOCKS(sse2,sse) +DECL_IMDCT_BLOCKS(sse3,sse) +DECL_IMDCT_BLOCKS(ssse3,sse) +#endif +#if HAVE_AVX_EXTERNAL +DECL_IMDCT_BLOCKS(avx,avx) +#endif +#endif /* HAVE_YASM */ + +av_cold void ff_mpadsp_init_x86(MPADSPContext *s) +{ + int mm_flags = av_get_cpu_flags(); + + int i, j; + for (j = 0; j < 4; j++) { + for (i = 0; i < 40; i ++) { + mdct_win_sse[0][j][4*i ] = ff_mdct_win_float[j ][i]; + mdct_win_sse[0][j][4*i + 1] = ff_mdct_win_float[j + 4][i]; + mdct_win_sse[0][j][4*i + 2] = ff_mdct_win_float[j ][i]; + mdct_win_sse[0][j][4*i + 3] = ff_mdct_win_float[j + 4][i]; + mdct_win_sse[1][j][4*i ] = ff_mdct_win_float[0 ][i]; + mdct_win_sse[1][j][4*i + 1] = ff_mdct_win_float[4 ][i]; + mdct_win_sse[1][j][4*i + 2] = ff_mdct_win_float[j ][i]; + mdct_win_sse[1][j][4*i + 3] = ff_mdct_win_float[j + 4][i]; + } + } + +#if HAVE_SSE2_INLINE + if (mm_flags & AV_CPU_FLAG_SSE2) { + s->apply_window_float = apply_window_mp3; + } +#endif /* HAVE_SSE2_INLINE */ + +#if HAVE_YASM + if (EXTERNAL_AVX(mm_flags)) { + s->imdct36_blocks_float = imdct36_blocks_avx; + } else if (EXTERNAL_SSSE3(mm_flags)) { + s->imdct36_blocks_float = imdct36_blocks_ssse3; + } else if (EXTERNAL_SSE3(mm_flags)) { + s->imdct36_blocks_float = imdct36_blocks_sse3; + } else if (EXTERNAL_SSE2(mm_flags)) { + s->imdct36_blocks_float = imdct36_blocks_sse2; + } else if (EXTERNAL_SSE(mm_flags)) { + s->imdct36_blocks_float = imdct36_blocks_sse; + } +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/mpegvideo.c b/ffmpeg/libavcodec/x86/mpegvideo.c new file mode 100644 index 0000000..903ad62 --- /dev/null +++ b/ffmpeg/libavcodec/x86/mpegvideo.c @@ -0,0 +1,600 @@ +/* + * Optimized for ia32 CPUs by Nick Kurshev + * h263, mpeg1, mpeg2 dequantizer & draw_edges 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpegvideo.h" +#include "dsputil_mmx.h" + +#if HAVE_INLINE_ASM + +static void dct_unquantize_h263_intra_mmx(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + x86_reg level, qmul, qadd, nCoeffs; + + qmul = qscale << 1; + + av_assert2(s->block_last_index[n]>=0 || s->h263_aic); + + if (!s->h263_aic) { + if (n < 4) + level = block[0] * s->y_dc_scale; + else + level = block[0] * s->c_dc_scale; + qadd = (qscale - 1) | 1; + }else{ + qadd = 0; + level= block[0]; + } + if(s->ac_pred) + nCoeffs=63; + else + nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ]; + +__asm__ volatile( + "movd %1, %%mm6 \n\t" //qmul + "packssdw %%mm6, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "movd %2, %%mm5 \n\t" //qadd + "pxor %%mm7, %%mm7 \n\t" + "packssdw %%mm5, %%mm5 \n\t" + "packssdw %%mm5, %%mm5 \n\t" + "psubw %%mm5, %%mm7 \n\t" + "pxor %%mm4, %%mm4 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%0, %3), %%mm0 \n\t" + "movq 8(%0, %3), %%mm1 \n\t" + + "pmullw %%mm6, %%mm0 \n\t" + "pmullw %%mm6, %%mm1 \n\t" + + "movq (%0, %3), %%mm2 \n\t" + "movq 8(%0, %3), %%mm3 \n\t" + + "pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 + "pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 + + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + + "paddw %%mm7, %%mm0 \n\t" + "paddw %%mm7, %%mm1 \n\t" + + "pxor %%mm0, %%mm2 \n\t" + "pxor %%mm1, %%mm3 \n\t" + + "pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0 + + "pandn %%mm2, %%mm0 \n\t" + "pandn %%mm3, %%mm1 \n\t" + + "movq %%mm0, (%0, %3) \n\t" + "movq %%mm1, 8(%0, %3) \n\t" + + "add $16, %3 \n\t" + "jng 1b \n\t" + ::"r" (block+nCoeffs), "rm"(qmul), "rm" (qadd), "r" (2*(-nCoeffs)) + : "memory" + ); + block[0]= level; +} + + +static void dct_unquantize_h263_inter_mmx(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + x86_reg qmul, qadd, nCoeffs; + + qmul = qscale << 1; + qadd = (qscale - 1) | 1; + + assert(s->block_last_index[n]>=0 || s->h263_aic); + + nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ]; + +__asm__ volatile( + "movd %1, %%mm6 \n\t" //qmul + "packssdw %%mm6, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "movd %2, %%mm5 \n\t" //qadd + "pxor %%mm7, %%mm7 \n\t" + "packssdw %%mm5, %%mm5 \n\t" + "packssdw %%mm5, %%mm5 \n\t" + "psubw %%mm5, %%mm7 \n\t" + "pxor %%mm4, %%mm4 \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%0, %3), %%mm0 \n\t" + "movq 8(%0, %3), %%mm1 \n\t" + + "pmullw %%mm6, %%mm0 \n\t" + "pmullw %%mm6, %%mm1 \n\t" + + "movq (%0, %3), %%mm2 \n\t" + "movq 8(%0, %3), %%mm3 \n\t" + + "pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 + "pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 + + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + + "paddw %%mm7, %%mm0 \n\t" + "paddw %%mm7, %%mm1 \n\t" + + "pxor %%mm0, %%mm2 \n\t" + "pxor %%mm1, %%mm3 \n\t" + + "pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0 + + "pandn %%mm2, %%mm0 \n\t" + "pandn %%mm3, %%mm1 \n\t" + + "movq %%mm0, (%0, %3) \n\t" + "movq %%mm1, 8(%0, %3) \n\t" + + "add $16, %3 \n\t" + "jng 1b \n\t" + ::"r" (block+nCoeffs), "rm"(qmul), "rm" (qadd), "r" (2*(-nCoeffs)) + : "memory" + ); +} + + +/* + We can suppose that result of two multiplications can't be greater than 0xFFFF + i.e. is 16-bit, so we use here only PMULLW instruction and can avoid + a complex multiplication. +===================================================== + Full formula for multiplication of 2 integer numbers + which are represent as high:low words: + input: value1 = high1:low1 + value2 = high2:low2 + output: value3 = value1*value2 + value3=high3:low3 (on overflow: modulus 2^32 wrap-around) + this mean that for 0x123456 * 0x123456 correct result is 0x766cb0ce4 + but this algorithm will compute only 0x66cb0ce4 + this limited by 16-bit size of operands + --------------------------------- + tlow1 = high1*low2 + tlow2 = high2*low1 + tlow1 = tlow1 + tlow2 + high3:low3 = low1*low2 + high3 += tlow1 +*/ +static void dct_unquantize_mpeg1_intra_mmx(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + x86_reg nCoeffs; + const uint16_t *quant_matrix; + int block0; + + av_assert2(s->block_last_index[n]>=0); + + nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1; + + if (n < 4) + block0 = block[0] * s->y_dc_scale; + else + block0 = block[0] * s->c_dc_scale; + /* XXX: only mpeg1 */ + quant_matrix = s->intra_matrix; +__asm__ volatile( + "pcmpeqw %%mm7, %%mm7 \n\t" + "psrlw $15, %%mm7 \n\t" + "movd %2, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "mov %3, %%"REG_a" \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%0, %%"REG_a"), %%mm0 \n\t" + "movq 8(%0, %%"REG_a"), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm4 \n\t" + "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i] + "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i] + "pxor %%mm2, %%mm2 \n\t" + "pxor %%mm3, %%mm3 \n\t" + "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 + "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" // abs(block[i]) + "psubw %%mm3, %%mm1 \n\t" // abs(block[i]) + "pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*q + "pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*q + "pxor %%mm4, %%mm4 \n\t" + "pxor %%mm5, %%mm5 \n\t" // FIXME slow + "pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0 + "psraw $3, %%mm0 \n\t" + "psraw $3, %%mm1 \n\t" + "psubw %%mm7, %%mm0 \n\t" + "psubw %%mm7, %%mm1 \n\t" + "por %%mm7, %%mm0 \n\t" + "por %%mm7, %%mm1 \n\t" + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" + "psubw %%mm3, %%mm1 \n\t" + "pandn %%mm0, %%mm4 \n\t" + "pandn %%mm1, %%mm5 \n\t" + "movq %%mm4, (%0, %%"REG_a") \n\t" + "movq %%mm5, 8(%0, %%"REG_a") \n\t" + + "add $16, %%"REG_a" \n\t" + "js 1b \n\t" + ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs) + : "%"REG_a, "memory" + ); + block[0]= block0; +} + +static void dct_unquantize_mpeg1_inter_mmx(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + x86_reg nCoeffs; + const uint16_t *quant_matrix; + + av_assert2(s->block_last_index[n]>=0); + + nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1; + + quant_matrix = s->inter_matrix; +__asm__ volatile( + "pcmpeqw %%mm7, %%mm7 \n\t" + "psrlw $15, %%mm7 \n\t" + "movd %2, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "mov %3, %%"REG_a" \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%0, %%"REG_a"), %%mm0 \n\t" + "movq 8(%0, %%"REG_a"), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm4 \n\t" + "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i] + "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i] + "pxor %%mm2, %%mm2 \n\t" + "pxor %%mm3, %%mm3 \n\t" + "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 + "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" // abs(block[i]) + "psubw %%mm3, %%mm1 \n\t" // abs(block[i]) + "paddw %%mm0, %%mm0 \n\t" // abs(block[i])*2 + "paddw %%mm1, %%mm1 \n\t" // abs(block[i])*2 + "paddw %%mm7, %%mm0 \n\t" // abs(block[i])*2 + 1 + "paddw %%mm7, %%mm1 \n\t" // abs(block[i])*2 + 1 + "pmullw %%mm4, %%mm0 \n\t" // (abs(block[i])*2 + 1)*q + "pmullw %%mm5, %%mm1 \n\t" // (abs(block[i])*2 + 1)*q + "pxor %%mm4, %%mm4 \n\t" + "pxor %%mm5, %%mm5 \n\t" // FIXME slow + "pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0 + "psraw $4, %%mm0 \n\t" + "psraw $4, %%mm1 \n\t" + "psubw %%mm7, %%mm0 \n\t" + "psubw %%mm7, %%mm1 \n\t" + "por %%mm7, %%mm0 \n\t" + "por %%mm7, %%mm1 \n\t" + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" + "psubw %%mm3, %%mm1 \n\t" + "pandn %%mm0, %%mm4 \n\t" + "pandn %%mm1, %%mm5 \n\t" + "movq %%mm4, (%0, %%"REG_a") \n\t" + "movq %%mm5, 8(%0, %%"REG_a") \n\t" + + "add $16, %%"REG_a" \n\t" + "js 1b \n\t" + ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs) + : "%"REG_a, "memory" + ); +} + +static void dct_unquantize_mpeg2_intra_mmx(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + x86_reg nCoeffs; + const uint16_t *quant_matrix; + int block0; + + av_assert2(s->block_last_index[n]>=0); + + if(s->alternate_scan) nCoeffs= 63; //FIXME + else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]; + + if (n < 4) + block0 = block[0] * s->y_dc_scale; + else + block0 = block[0] * s->c_dc_scale; + quant_matrix = s->intra_matrix; +__asm__ volatile( + "pcmpeqw %%mm7, %%mm7 \n\t" + "psrlw $15, %%mm7 \n\t" + "movd %2, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "mov %3, %%"REG_a" \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%0, %%"REG_a"), %%mm0 \n\t" + "movq 8(%0, %%"REG_a"), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm4 \n\t" + "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i] + "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i] + "pxor %%mm2, %%mm2 \n\t" + "pxor %%mm3, %%mm3 \n\t" + "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 + "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" // abs(block[i]) + "psubw %%mm3, %%mm1 \n\t" // abs(block[i]) + "pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*q + "pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*q + "pxor %%mm4, %%mm4 \n\t" + "pxor %%mm5, %%mm5 \n\t" // FIXME slow + "pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0 + "psraw $3, %%mm0 \n\t" + "psraw $3, %%mm1 \n\t" + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" + "psubw %%mm3, %%mm1 \n\t" + "pandn %%mm0, %%mm4 \n\t" + "pandn %%mm1, %%mm5 \n\t" + "movq %%mm4, (%0, %%"REG_a") \n\t" + "movq %%mm5, 8(%0, %%"REG_a") \n\t" + + "add $16, %%"REG_a" \n\t" + "jng 1b \n\t" + ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "g" (-2*nCoeffs) + : "%"REG_a, "memory" + ); + block[0]= block0; + //Note, we do not do mismatch control for intra as errors cannot accumulate +} + +static void dct_unquantize_mpeg2_inter_mmx(MpegEncContext *s, + int16_t *block, int n, int qscale) +{ + x86_reg nCoeffs; + const uint16_t *quant_matrix; + + av_assert2(s->block_last_index[n]>=0); + + if(s->alternate_scan) nCoeffs= 63; //FIXME + else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]; + + quant_matrix = s->inter_matrix; +__asm__ volatile( + "pcmpeqw %%mm7, %%mm7 \n\t" + "psrlq $48, %%mm7 \n\t" + "movd %2, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "packssdw %%mm6, %%mm6 \n\t" + "mov %3, %%"REG_a" \n\t" + ".p2align 4 \n\t" + "1: \n\t" + "movq (%0, %%"REG_a"), %%mm0 \n\t" + "movq 8(%0, %%"REG_a"), %%mm1 \n\t" + "movq (%1, %%"REG_a"), %%mm4 \n\t" + "movq 8(%1, %%"REG_a"), %%mm5 \n\t" + "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i] + "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i] + "pxor %%mm2, %%mm2 \n\t" + "pxor %%mm3, %%mm3 \n\t" + "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0 + "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0 + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" // abs(block[i]) + "psubw %%mm3, %%mm1 \n\t" // abs(block[i]) + "paddw %%mm0, %%mm0 \n\t" // abs(block[i])*2 + "paddw %%mm1, %%mm1 \n\t" // abs(block[i])*2 + "pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*2*q + "pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*2*q + "paddw %%mm4, %%mm0 \n\t" // (abs(block[i])*2 + 1)*q + "paddw %%mm5, %%mm1 \n\t" // (abs(block[i])*2 + 1)*q + "pxor %%mm4, %%mm4 \n\t" + "pxor %%mm5, %%mm5 \n\t" // FIXME slow + "pcmpeqw (%0, %%"REG_a"), %%mm4 \n\t" // block[i] == 0 ? -1 : 0 + "pcmpeqw 8(%0, %%"REG_a"), %%mm5\n\t" // block[i] == 0 ? -1 : 0 + "psrlw $4, %%mm0 \n\t" + "psrlw $4, %%mm1 \n\t" + "pxor %%mm2, %%mm0 \n\t" + "pxor %%mm3, %%mm1 \n\t" + "psubw %%mm2, %%mm0 \n\t" + "psubw %%mm3, %%mm1 \n\t" + "pandn %%mm0, %%mm4 \n\t" + "pandn %%mm1, %%mm5 \n\t" + "pxor %%mm4, %%mm7 \n\t" + "pxor %%mm5, %%mm7 \n\t" + "movq %%mm4, (%0, %%"REG_a") \n\t" + "movq %%mm5, 8(%0, %%"REG_a") \n\t" + + "add $16, %%"REG_a" \n\t" + "jng 1b \n\t" + "movd 124(%0, %3), %%mm0 \n\t" + "movq %%mm7, %%mm6 \n\t" + "psrlq $32, %%mm7 \n\t" + "pxor %%mm6, %%mm7 \n\t" + "movq %%mm7, %%mm6 \n\t" + "psrlq $16, %%mm7 \n\t" + "pxor %%mm6, %%mm7 \n\t" + "pslld $31, %%mm7 \n\t" + "psrlq $15, %%mm7 \n\t" + "pxor %%mm7, %%mm0 \n\t" + "movd %%mm0, 124(%0, %3) \n\t" + + ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "rm" (qscale), "r" (-2*nCoeffs) + : "%"REG_a, "memory" + ); +} + +static void denoise_dct_mmx(MpegEncContext *s, int16_t *block){ + const int intra= s->mb_intra; + int *sum= s->dct_error_sum[intra]; + uint16_t *offset= s->dct_offset[intra]; + + s->dct_count[intra]++; + + __asm__ volatile( + "pxor %%mm7, %%mm7 \n\t" + "1: \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "movq (%0), %%mm2 \n\t" + "movq 8(%0), %%mm3 \n\t" + "pcmpgtw %%mm2, %%mm0 \n\t" + "pcmpgtw %%mm3, %%mm1 \n\t" + "pxor %%mm0, %%mm2 \n\t" + "pxor %%mm1, %%mm3 \n\t" + "psubw %%mm0, %%mm2 \n\t" + "psubw %%mm1, %%mm3 \n\t" + "movq %%mm2, %%mm4 \n\t" + "movq %%mm3, %%mm5 \n\t" + "psubusw (%2), %%mm2 \n\t" + "psubusw 8(%2), %%mm3 \n\t" + "pxor %%mm0, %%mm2 \n\t" + "pxor %%mm1, %%mm3 \n\t" + "psubw %%mm0, %%mm2 \n\t" + "psubw %%mm1, %%mm3 \n\t" + "movq %%mm2, (%0) \n\t" + "movq %%mm3, 8(%0) \n\t" + "movq %%mm4, %%mm2 \n\t" + "movq %%mm5, %%mm3 \n\t" + "punpcklwd %%mm7, %%mm4 \n\t" + "punpckhwd %%mm7, %%mm2 \n\t" + "punpcklwd %%mm7, %%mm5 \n\t" + "punpckhwd %%mm7, %%mm3 \n\t" + "paddd (%1), %%mm4 \n\t" + "paddd 8(%1), %%mm2 \n\t" + "paddd 16(%1), %%mm5 \n\t" + "paddd 24(%1), %%mm3 \n\t" + "movq %%mm4, (%1) \n\t" + "movq %%mm2, 8(%1) \n\t" + "movq %%mm5, 16(%1) \n\t" + "movq %%mm3, 24(%1) \n\t" + "add $16, %0 \n\t" + "add $32, %1 \n\t" + "add $16, %2 \n\t" + "cmp %3, %0 \n\t" + " jb 1b \n\t" + : "+r" (block), "+r" (sum), "+r" (offset) + : "r"(block+64) + ); +} + +static void denoise_dct_sse2(MpegEncContext *s, int16_t *block){ + const int intra= s->mb_intra; + int *sum= s->dct_error_sum[intra]; + uint16_t *offset= s->dct_offset[intra]; + + s->dct_count[intra]++; + + __asm__ volatile( + "pxor %%xmm7, %%xmm7 \n\t" + "1: \n\t" + "pxor %%xmm0, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm1 \n\t" + "movdqa (%0), %%xmm2 \n\t" + "movdqa 16(%0), %%xmm3 \n\t" + "pcmpgtw %%xmm2, %%xmm0 \n\t" + "pcmpgtw %%xmm3, %%xmm1 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm3 \n\t" + "psubw %%xmm0, %%xmm2 \n\t" + "psubw %%xmm1, %%xmm3 \n\t" + "movdqa %%xmm2, %%xmm4 \n\t" + "movdqa %%xmm3, %%xmm5 \n\t" + "psubusw (%2), %%xmm2 \n\t" + "psubusw 16(%2), %%xmm3 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm3 \n\t" + "psubw %%xmm0, %%xmm2 \n\t" + "psubw %%xmm1, %%xmm3 \n\t" + "movdqa %%xmm2, (%0) \n\t" + "movdqa %%xmm3, 16(%0) \n\t" + "movdqa %%xmm4, %%xmm6 \n\t" + "movdqa %%xmm5, %%xmm0 \n\t" + "punpcklwd %%xmm7, %%xmm4 \n\t" + "punpckhwd %%xmm7, %%xmm6 \n\t" + "punpcklwd %%xmm7, %%xmm5 \n\t" + "punpckhwd %%xmm7, %%xmm0 \n\t" + "paddd (%1), %%xmm4 \n\t" + "paddd 16(%1), %%xmm6 \n\t" + "paddd 32(%1), %%xmm5 \n\t" + "paddd 48(%1), %%xmm0 \n\t" + "movdqa %%xmm4, (%1) \n\t" + "movdqa %%xmm6, 16(%1) \n\t" + "movdqa %%xmm5, 32(%1) \n\t" + "movdqa %%xmm0, 48(%1) \n\t" + "add $32, %0 \n\t" + "add $64, %1 \n\t" + "add $32, %2 \n\t" + "cmp %3, %0 \n\t" + " jb 1b \n\t" + : "+r" (block), "+r" (sum), "+r" (offset) + : "r"(block+64) + XMM_CLOBBERS_ONLY("%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm4", "%xmm5", "%xmm6", "%xmm7") + ); +} + +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_MPV_common_init_x86(MpegEncContext *s) +{ +#if HAVE_INLINE_ASM + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_MMX) { + s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_mmx; + s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_mmx; + s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_mmx; + s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_mmx; + if(!(s->flags & CODEC_FLAG_BITEXACT)) + s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_mmx; + s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_mmx; + + if (mm_flags & AV_CPU_FLAG_SSE2) { + s->denoise_dct= denoise_dct_sse2; + } else { + s->denoise_dct= denoise_dct_mmx; + } + } +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/x86/mpegvideoenc.c b/ffmpeg/libavcodec/x86/mpegvideoenc.c new file mode 100644 index 0000000..6219667 --- /dev/null +++ b/ffmpeg/libavcodec/x86/mpegvideoenc.c @@ -0,0 +1,107 @@ +/* + * The simplest mpeg encoder (well, it was the simplest!) + * Copyright (c) 2000,2001 Fabrice Bellard + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dct.h" +#include "libavcodec/mpegvideo.h" +#include "dsputil_mmx.h" + +extern uint16_t ff_inv_zigzag_direct16[64]; + +#if HAVE_MMX_INLINE +#define COMPILE_TEMPLATE_MMXEXT 0 +#define COMPILE_TEMPLATE_SSE2 0 +#define COMPILE_TEMPLATE_SSSE3 0 +#define RENAME(a) a ## _MMX +#define RENAMEl(a) a ## _mmx +#include "mpegvideoenc_template.c" +#endif /* HAVE_MMX_INLINE */ + +#if HAVE_MMXEXT_INLINE +#undef COMPILE_TEMPLATE_SSSE3 +#undef COMPILE_TEMPLATE_SSE2 +#undef COMPILE_TEMPLATE_MMXEXT +#define COMPILE_TEMPLATE_MMXEXT 1 +#define COMPILE_TEMPLATE_SSE2 0 +#define COMPILE_TEMPLATE_SSSE3 0 +#undef RENAME +#undef RENAMEl +#define RENAME(a) a ## _MMXEXT +#define RENAMEl(a) a ## _mmxext +#include "mpegvideoenc_template.c" +#endif /* HAVE_MMXEXT_INLINE */ + +#if HAVE_SSE2_INLINE +#undef COMPILE_TEMPLATE_MMXEXT +#undef COMPILE_TEMPLATE_SSE2 +#undef COMPILE_TEMPLATE_SSSE3 +#define COMPILE_TEMPLATE_MMXEXT 0 +#define COMPILE_TEMPLATE_SSE2 1 +#define COMPILE_TEMPLATE_SSSE3 0 +#undef RENAME +#undef RENAMEl +#define RENAME(a) a ## _SSE2 +#define RENAMEl(a) a ## _sse2 +#include "mpegvideoenc_template.c" +#endif /* HAVE_SSE2_INLINE */ + +#if HAVE_SSSE3_INLINE +#undef COMPILE_TEMPLATE_MMXEXT +#undef COMPILE_TEMPLATE_SSE2 +#undef COMPILE_TEMPLATE_SSSE3 +#define COMPILE_TEMPLATE_MMXEXT 0 +#define COMPILE_TEMPLATE_SSE2 1 +#define COMPILE_TEMPLATE_SSSE3 1 +#undef RENAME +#undef RENAMEl +#define RENAME(a) a ## _SSSE3 +#define RENAMEl(a) a ## _sse2 +#include "mpegvideoenc_template.c" +#endif /* HAVE_SSSE3_INLINE */ + +av_cold void ff_dct_encode_init_x86(MpegEncContext *s) +{ + int mm_flags = av_get_cpu_flags(); + const int dct_algo = s->avctx->dct_algo; + + if (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX) { +#if HAVE_MMX_INLINE + if (INLINE_MMX(mm_flags)) + s->dct_quantize = dct_quantize_MMX; +#endif +#if HAVE_MMXEXT_INLINE + if (INLINE_MMXEXT(mm_flags)) + s->dct_quantize = dct_quantize_MMXEXT; +#endif +#if HAVE_SSE2_INLINE + if (INLINE_SSE2(mm_flags)) + s->dct_quantize = dct_quantize_SSE2; +#endif +#if HAVE_SSSE3_INLINE + if (INLINE_SSSE3(mm_flags)) + s->dct_quantize = dct_quantize_SSSE3; +#endif + } +} diff --git a/ffmpeg/libavcodec/x86/mpegvideoenc_template.c b/ffmpeg/libavcodec/x86/mpegvideoenc_template.c new file mode 100644 index 0000000..1e0505e --- /dev/null +++ b/ffmpeg/libavcodec/x86/mpegvideoenc_template.c @@ -0,0 +1,364 @@ +/* + * MPEG video MMX templates + * + * Copyright (c) 2002 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 + */ + +#undef MMREG_WIDTH +#undef MM +#undef MOVQ +#undef SPREADW +#undef PMAXW +#undef PMAX +#undef SAVE_SIGN +#undef RESTORE_SIGN + +#if COMPILE_TEMPLATE_SSE2 +#define MMREG_WIDTH "16" +#define MM "%%xmm" +#define MOVQ "movdqa" +#define SPREADW(a) \ + "pshuflw $0, "a", "a" \n\t"\ + "punpcklwd "a", "a" \n\t" +#define PMAXW(a,b) "pmaxsw "a", "b" \n\t" +#define PMAX(a,b) \ + "movhlps "a", "b" \n\t"\ + PMAXW(b, a)\ + "pshuflw $0x0E, "a", "b" \n\t"\ + PMAXW(b, a)\ + "pshuflw $0x01, "a", "b" \n\t"\ + PMAXW(b, a) +#else +#define MMREG_WIDTH "8" +#define MM "%%mm" +#define MOVQ "movq" +#if COMPILE_TEMPLATE_MMXEXT +#define SPREADW(a) "pshufw $0, "a", "a" \n\t" +#define PMAXW(a,b) "pmaxsw "a", "b" \n\t" +#define PMAX(a,b) \ + "pshufw $0x0E, "a", "b" \n\t"\ + PMAXW(b, a)\ + "pshufw $0x01, "a", "b" \n\t"\ + PMAXW(b, a) +#else +#define SPREADW(a) \ + "punpcklwd "a", "a" \n\t"\ + "punpcklwd "a", "a" \n\t" +#define PMAXW(a,b) \ + "psubusw "a", "b" \n\t"\ + "paddw "a", "b" \n\t" +#define PMAX(a,b) \ + "movq "a", "b" \n\t"\ + "psrlq $32, "a" \n\t"\ + PMAXW(b, a)\ + "movq "a", "b" \n\t"\ + "psrlq $16, "a" \n\t"\ + PMAXW(b, a) + +#endif +#endif + +#if COMPILE_TEMPLATE_SSSE3 +#define SAVE_SIGN(a,b) \ + "movdqa "b", "a" \n\t"\ + "pabsw "b", "b" \n\t" +#define RESTORE_SIGN(a,b) \ + "psignw "a", "b" \n\t" +#else +#define SAVE_SIGN(a,b) \ + "pxor "a", "a" \n\t"\ + "pcmpgtw "b", "a" \n\t" /* block[i] <= 0 ? 0xFF : 0x00 */\ + "pxor "a", "b" \n\t"\ + "psubw "a", "b" \n\t" /* ABS(block[i]) */ +#define RESTORE_SIGN(a,b) \ + "pxor "a", "b" \n\t"\ + "psubw "a", "b" \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) +#endif + +static int RENAME(dct_quantize)(MpegEncContext *s, + int16_t *block, int n, + int qscale, int *overflow) +{ + x86_reg last_non_zero_p1; + int level=0, q; //=0 is because gcc says uninitialized ... + const uint16_t *qmat, *bias; + LOCAL_ALIGNED_16(int16_t, temp_block, [64]); + + av_assert2((7&(int)(&temp_block[0])) == 0); //did gcc align it correctly? + + //s->fdct (block); + RENAMEl(ff_fdct) (block); //cannot be anything else ... + + if(s->dct_error_sum) + s->denoise_dct(s, block); + + if (s->mb_intra) { + int dummy; + if (n < 4){ + q = s->y_dc_scale; + bias = s->q_intra_matrix16[qscale][1]; + qmat = s->q_intra_matrix16[qscale][0]; + }else{ + q = s->c_dc_scale; + bias = s->q_chroma_intra_matrix16[qscale][1]; + qmat = s->q_chroma_intra_matrix16[qscale][0]; + } + /* note: block[0] is assumed to be positive */ + if (!s->h263_aic) { + __asm__ volatile ( + "mul %%ecx \n\t" + : "=d" (level), "=a"(dummy) + : "a" ((block[0]>>2) + q), "c" (ff_inverse[q<<1]) + ); + } else + /* For AIC we skip quant/dequant of INTRADC */ + level = (block[0] + 4)>>3; + + block[0]=0; //avoid fake overflow +// temp_block[0] = (block[0] + (q >> 1)) / q; + last_non_zero_p1 = 1; + } else { + last_non_zero_p1 = 0; + bias = s->q_inter_matrix16[qscale][1]; + qmat = s->q_inter_matrix16[qscale][0]; + } + + if((s->out_format == FMT_H263 || s->out_format == FMT_H261) && s->mpeg_quant==0){ + + __asm__ volatile( + "movd %%"REG_a", "MM"3 \n\t" // last_non_zero_p1 + SPREADW(MM"3") + "pxor "MM"7, "MM"7 \n\t" // 0 + "pxor "MM"4, "MM"4 \n\t" // 0 + MOVQ" (%2), "MM"5 \n\t" // qmat[0] + "pxor "MM"6, "MM"6 \n\t" + "psubw (%3), "MM"6 \n\t" // -bias[0] + "mov $-128, %%"REG_a" \n\t" + ".p2align 4 \n\t" + "1: \n\t" + MOVQ" (%1, %%"REG_a"), "MM"0 \n\t" // block[i] + SAVE_SIGN(MM"1", MM"0") // ABS(block[i]) + "psubusw "MM"6, "MM"0 \n\t" // ABS(block[i]) + bias[0] + "pmulhw "MM"5, "MM"0 \n\t" // (ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16 + "por "MM"0, "MM"4 \n\t" + RESTORE_SIGN(MM"1", MM"0") // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) + MOVQ" "MM"0, (%5, %%"REG_a") \n\t" + "pcmpeqw "MM"7, "MM"0 \n\t" // out==0 ? 0xFF : 0x00 + MOVQ" (%4, %%"REG_a"), "MM"1 \n\t" + MOVQ" "MM"7, (%1, %%"REG_a") \n\t" // 0 + "pandn "MM"1, "MM"0 \n\t" + PMAXW(MM"0", MM"3") + "add $"MMREG_WIDTH", %%"REG_a" \n\t" + " js 1b \n\t" + PMAX(MM"3", MM"0") + "movd "MM"3, %%"REG_a" \n\t" + "movzb %%al, %%"REG_a" \n\t" // last_non_zero_p1 + : "+a" (last_non_zero_p1) + : "r" (block+64), "r" (qmat), "r" (bias), + "r" (ff_inv_zigzag_direct16+64), "r" (temp_block+64) + XMM_CLOBBERS_ONLY("%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm4", "%xmm5", "%xmm6", "%xmm7") + ); + }else{ // FMT_H263 + __asm__ volatile( + "movd %%"REG_a", "MM"3 \n\t" // last_non_zero_p1 + SPREADW(MM"3") + "pxor "MM"7, "MM"7 \n\t" // 0 + "pxor "MM"4, "MM"4 \n\t" // 0 + "mov $-128, %%"REG_a" \n\t" + ".p2align 4 \n\t" + "1: \n\t" + MOVQ" (%1, %%"REG_a"), "MM"0 \n\t" // block[i] + SAVE_SIGN(MM"1", MM"0") // ABS(block[i]) + MOVQ" (%3, %%"REG_a"), "MM"6 \n\t" // bias[0] + "paddusw "MM"6, "MM"0 \n\t" // ABS(block[i]) + bias[0] + MOVQ" (%2, %%"REG_a"), "MM"5 \n\t" // qmat[i] + "pmulhw "MM"5, "MM"0 \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16 + "por "MM"0, "MM"4 \n\t" + RESTORE_SIGN(MM"1", MM"0") // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i]) + MOVQ" "MM"0, (%5, %%"REG_a") \n\t" + "pcmpeqw "MM"7, "MM"0 \n\t" // out==0 ? 0xFF : 0x00 + MOVQ" (%4, %%"REG_a"), "MM"1 \n\t" + MOVQ" "MM"7, (%1, %%"REG_a") \n\t" // 0 + "pandn "MM"1, "MM"0 \n\t" + PMAXW(MM"0", MM"3") + "add $"MMREG_WIDTH", %%"REG_a" \n\t" + " js 1b \n\t" + PMAX(MM"3", MM"0") + "movd "MM"3, %%"REG_a" \n\t" + "movzb %%al, %%"REG_a" \n\t" // last_non_zero_p1 + : "+a" (last_non_zero_p1) + : "r" (block+64), "r" (qmat+64), "r" (bias+64), + "r" (ff_inv_zigzag_direct16+64), "r" (temp_block+64) + XMM_CLOBBERS_ONLY("%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm4", "%xmm5", "%xmm6", "%xmm7") + ); + } + __asm__ volatile( + "movd %1, "MM"1 \n\t" // max_qcoeff + SPREADW(MM"1") + "psubusw "MM"1, "MM"4 \n\t" + "packuswb "MM"4, "MM"4 \n\t" +#if COMPILE_TEMPLATE_SSE2 + "packuswb "MM"4, "MM"4 \n\t" +#endif + "movd "MM"4, %0 \n\t" // *overflow + : "=g" (*overflow) + : "g" (s->max_qcoeff) + ); + + if(s->mb_intra) block[0]= level; + else block[0]= temp_block[0]; + + if(s->dsp.idct_permutation_type == FF_SIMPLE_IDCT_PERM){ + if(last_non_zero_p1 <= 1) goto end; + block[0x08] = temp_block[0x01]; block[0x10] = temp_block[0x08]; + block[0x20] = temp_block[0x10]; + if(last_non_zero_p1 <= 4) goto end; + block[0x18] = temp_block[0x09]; block[0x04] = temp_block[0x02]; + block[0x09] = temp_block[0x03]; + if(last_non_zero_p1 <= 7) goto end; + block[0x14] = temp_block[0x0A]; block[0x28] = temp_block[0x11]; + block[0x12] = temp_block[0x18]; block[0x02] = temp_block[0x20]; + if(last_non_zero_p1 <= 11) goto end; + block[0x1A] = temp_block[0x19]; block[0x24] = temp_block[0x12]; + block[0x19] = temp_block[0x0B]; block[0x01] = temp_block[0x04]; + block[0x0C] = temp_block[0x05]; + if(last_non_zero_p1 <= 16) goto end; + block[0x11] = temp_block[0x0C]; block[0x29] = temp_block[0x13]; + block[0x16] = temp_block[0x1A]; block[0x0A] = temp_block[0x21]; + block[0x30] = temp_block[0x28]; block[0x22] = temp_block[0x30]; + block[0x38] = temp_block[0x29]; block[0x06] = temp_block[0x22]; + if(last_non_zero_p1 <= 24) goto end; + block[0x1B] = temp_block[0x1B]; block[0x21] = temp_block[0x14]; + block[0x1C] = temp_block[0x0D]; block[0x05] = temp_block[0x06]; + block[0x0D] = temp_block[0x07]; block[0x15] = temp_block[0x0E]; + block[0x2C] = temp_block[0x15]; block[0x13] = temp_block[0x1C]; + if(last_non_zero_p1 <= 32) goto end; + block[0x0B] = temp_block[0x23]; block[0x34] = temp_block[0x2A]; + block[0x2A] = temp_block[0x31]; block[0x32] = temp_block[0x38]; + block[0x3A] = temp_block[0x39]; block[0x26] = temp_block[0x32]; + block[0x39] = temp_block[0x2B]; block[0x03] = temp_block[0x24]; + if(last_non_zero_p1 <= 40) goto end; + block[0x1E] = temp_block[0x1D]; block[0x25] = temp_block[0x16]; + block[0x1D] = temp_block[0x0F]; block[0x2D] = temp_block[0x17]; + block[0x17] = temp_block[0x1E]; block[0x0E] = temp_block[0x25]; + block[0x31] = temp_block[0x2C]; block[0x2B] = temp_block[0x33]; + if(last_non_zero_p1 <= 48) goto end; + block[0x36] = temp_block[0x3A]; block[0x3B] = temp_block[0x3B]; + block[0x23] = temp_block[0x34]; block[0x3C] = temp_block[0x2D]; + block[0x07] = temp_block[0x26]; block[0x1F] = temp_block[0x1F]; + block[0x0F] = temp_block[0x27]; block[0x35] = temp_block[0x2E]; + if(last_non_zero_p1 <= 56) goto end; + block[0x2E] = temp_block[0x35]; block[0x33] = temp_block[0x3C]; + block[0x3E] = temp_block[0x3D]; block[0x27] = temp_block[0x36]; + block[0x3D] = temp_block[0x2F]; block[0x2F] = temp_block[0x37]; + block[0x37] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F]; + }else if(s->dsp.idct_permutation_type == FF_LIBMPEG2_IDCT_PERM){ + if(last_non_zero_p1 <= 1) goto end; + block[0x04] = temp_block[0x01]; + block[0x08] = temp_block[0x08]; block[0x10] = temp_block[0x10]; + if(last_non_zero_p1 <= 4) goto end; + block[0x0C] = temp_block[0x09]; block[0x01] = temp_block[0x02]; + block[0x05] = temp_block[0x03]; + if(last_non_zero_p1 <= 7) goto end; + block[0x09] = temp_block[0x0A]; block[0x14] = temp_block[0x11]; + block[0x18] = temp_block[0x18]; block[0x20] = temp_block[0x20]; + if(last_non_zero_p1 <= 11) goto end; + block[0x1C] = temp_block[0x19]; + block[0x11] = temp_block[0x12]; block[0x0D] = temp_block[0x0B]; + block[0x02] = temp_block[0x04]; block[0x06] = temp_block[0x05]; + if(last_non_zero_p1 <= 16) goto end; + block[0x0A] = temp_block[0x0C]; block[0x15] = temp_block[0x13]; + block[0x19] = temp_block[0x1A]; block[0x24] = temp_block[0x21]; + block[0x28] = temp_block[0x28]; block[0x30] = temp_block[0x30]; + block[0x2C] = temp_block[0x29]; block[0x21] = temp_block[0x22]; + if(last_non_zero_p1 <= 24) goto end; + block[0x1D] = temp_block[0x1B]; block[0x12] = temp_block[0x14]; + block[0x0E] = temp_block[0x0D]; block[0x03] = temp_block[0x06]; + block[0x07] = temp_block[0x07]; block[0x0B] = temp_block[0x0E]; + block[0x16] = temp_block[0x15]; block[0x1A] = temp_block[0x1C]; + if(last_non_zero_p1 <= 32) goto end; + block[0x25] = temp_block[0x23]; block[0x29] = temp_block[0x2A]; + block[0x34] = temp_block[0x31]; block[0x38] = temp_block[0x38]; + block[0x3C] = temp_block[0x39]; block[0x31] = temp_block[0x32]; + block[0x2D] = temp_block[0x2B]; block[0x22] = temp_block[0x24]; + if(last_non_zero_p1 <= 40) goto end; + block[0x1E] = temp_block[0x1D]; block[0x13] = temp_block[0x16]; + block[0x0F] = temp_block[0x0F]; block[0x17] = temp_block[0x17]; + block[0x1B] = temp_block[0x1E]; block[0x26] = temp_block[0x25]; + block[0x2A] = temp_block[0x2C]; block[0x35] = temp_block[0x33]; + if(last_non_zero_p1 <= 48) goto end; + block[0x39] = temp_block[0x3A]; block[0x3D] = temp_block[0x3B]; + block[0x32] = temp_block[0x34]; block[0x2E] = temp_block[0x2D]; + block[0x23] = temp_block[0x26]; block[0x1F] = temp_block[0x1F]; + block[0x27] = temp_block[0x27]; block[0x2B] = temp_block[0x2E]; + if(last_non_zero_p1 <= 56) goto end; + block[0x36] = temp_block[0x35]; block[0x3A] = temp_block[0x3C]; + block[0x3E] = temp_block[0x3D]; block[0x33] = temp_block[0x36]; + block[0x2F] = temp_block[0x2F]; block[0x37] = temp_block[0x37]; + block[0x3B] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F]; + }else{ + if(last_non_zero_p1 <= 1) goto end; + block[0x01] = temp_block[0x01]; + block[0x08] = temp_block[0x08]; block[0x10] = temp_block[0x10]; + if(last_non_zero_p1 <= 4) goto end; + block[0x09] = temp_block[0x09]; block[0x02] = temp_block[0x02]; + block[0x03] = temp_block[0x03]; + if(last_non_zero_p1 <= 7) goto end; + block[0x0A] = temp_block[0x0A]; block[0x11] = temp_block[0x11]; + block[0x18] = temp_block[0x18]; block[0x20] = temp_block[0x20]; + if(last_non_zero_p1 <= 11) goto end; + block[0x19] = temp_block[0x19]; + block[0x12] = temp_block[0x12]; block[0x0B] = temp_block[0x0B]; + block[0x04] = temp_block[0x04]; block[0x05] = temp_block[0x05]; + if(last_non_zero_p1 <= 16) goto end; + block[0x0C] = temp_block[0x0C]; block[0x13] = temp_block[0x13]; + block[0x1A] = temp_block[0x1A]; block[0x21] = temp_block[0x21]; + block[0x28] = temp_block[0x28]; block[0x30] = temp_block[0x30]; + block[0x29] = temp_block[0x29]; block[0x22] = temp_block[0x22]; + if(last_non_zero_p1 <= 24) goto end; + block[0x1B] = temp_block[0x1B]; block[0x14] = temp_block[0x14]; + block[0x0D] = temp_block[0x0D]; block[0x06] = temp_block[0x06]; + block[0x07] = temp_block[0x07]; block[0x0E] = temp_block[0x0E]; + block[0x15] = temp_block[0x15]; block[0x1C] = temp_block[0x1C]; + if(last_non_zero_p1 <= 32) goto end; + block[0x23] = temp_block[0x23]; block[0x2A] = temp_block[0x2A]; + block[0x31] = temp_block[0x31]; block[0x38] = temp_block[0x38]; + block[0x39] = temp_block[0x39]; block[0x32] = temp_block[0x32]; + block[0x2B] = temp_block[0x2B]; block[0x24] = temp_block[0x24]; + if(last_non_zero_p1 <= 40) goto end; + block[0x1D] = temp_block[0x1D]; block[0x16] = temp_block[0x16]; + block[0x0F] = temp_block[0x0F]; block[0x17] = temp_block[0x17]; + block[0x1E] = temp_block[0x1E]; block[0x25] = temp_block[0x25]; + block[0x2C] = temp_block[0x2C]; block[0x33] = temp_block[0x33]; + if(last_non_zero_p1 <= 48) goto end; + block[0x3A] = temp_block[0x3A]; block[0x3B] = temp_block[0x3B]; + block[0x34] = temp_block[0x34]; block[0x2D] = temp_block[0x2D]; + block[0x26] = temp_block[0x26]; block[0x1F] = temp_block[0x1F]; + block[0x27] = temp_block[0x27]; block[0x2E] = temp_block[0x2E]; + if(last_non_zero_p1 <= 56) goto end; + block[0x35] = temp_block[0x35]; block[0x3C] = temp_block[0x3C]; + block[0x3D] = temp_block[0x3D]; block[0x36] = temp_block[0x36]; + block[0x2F] = temp_block[0x2F]; block[0x37] = temp_block[0x37]; + block[0x3E] = temp_block[0x3E]; block[0x3F] = temp_block[0x3F]; + } + end: + return last_non_zero_p1 - 1; +} diff --git a/ffmpeg/libavcodec/x86/pngdsp.asm b/ffmpeg/libavcodec/x86/pngdsp.asm new file mode 100644 index 0000000..c05f3da --- /dev/null +++ b/ffmpeg/libavcodec/x86/pngdsp.asm @@ -0,0 +1,173 @@ +;****************************************************************************** +;* x86 optimizations for PNG decoding +;* +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2012 Ronald S. Bultje +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +cextern pw_255 + +SECTION_TEXT + +; %1 = nr. of xmm registers used +%macro ADD_BYTES_FN 1 +cglobal add_bytes_l2, 4, 6, %1, dst, src1, src2, wa, w, i +%if ARCH_X86_64 + movsxd waq, wad +%endif + xor iq, iq + + ; vector loop + mov wq, waq + and waq, ~(mmsize*2-1) + jmp .end_v +.loop_v: + mova m0, [src1q+iq] + mova m1, [src1q+iq+mmsize] + paddb m0, [src2q+iq] + paddb m1, [src2q+iq+mmsize] + mova [dstq+iq ], m0 + mova [dstq+iq+mmsize], m1 + add iq, mmsize*2 +.end_v: + cmp iq, waq + jl .loop_v + +%if mmsize == 16 + ; vector loop + mov waq, wq + and waq, ~7 + jmp .end_l +.loop_l: + movq mm0, [src1q+iq] + paddb mm0, [src2q+iq] + movq [dstq+iq ], mm0 + add iq, 8 +.end_l: + cmp iq, waq + jl .loop_l +%endif + + ; scalar loop for leftover + jmp .end_s +.loop_s: + mov wab, [src1q+iq] + add wab, [src2q+iq] + mov [dstq+iq], wab + inc iq +.end_s: + cmp iq, wq + jl .loop_s + REP_RET +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +ADD_BYTES_FN 0 +%endif + +INIT_XMM sse2 +ADD_BYTES_FN 2 + +%macro ADD_PAETH_PRED_FN 1 +cglobal add_png_paeth_prediction, 5, 7, %1, dst, src, top, w, bpp, end, cntr +%if ARCH_X86_64 + movsxd bppq, bppd + movsxd wq, wd +%endif + lea endq, [dstq+wq-(mmsize/2-1)] + sub topq, dstq + sub srcq, dstq + sub dstq, bppq + pxor m7, m7 + + PUSH dstq + lea cntrq, [bppq-1] + shr cntrq, 2 + mmsize/16 +.bpp_loop: + lea dstq, [dstq+cntrq*(mmsize/2)] + movh m0, [dstq] + movh m1, [topq+dstq] + punpcklbw m0, m7 + punpcklbw m1, m7 + add dstq, bppq +.loop: + mova m2, m1 + movh m1, [topq+dstq] + mova m3, m2 + punpcklbw m1, m7 + mova m4, m2 + psubw m3, m1 + psubw m4, m0 + mova m5, m3 + paddw m5, m4 +%if cpuflag(ssse3) + pabsw m3, m3 + pabsw m4, m4 + pabsw m5, m5 +%else ; !cpuflag(ssse3) + psubw m7, m5 + pmaxsw m5, m7 + pxor m6, m6 + pxor m7, m7 + psubw m6, m3 + psubw m7, m4 + pmaxsw m3, m6 + pmaxsw m4, m7 + pxor m7, m7 +%endif ; cpuflag(ssse3) + mova m6, m4 + pminsw m6, m5 + pcmpgtw m3, m6 + pcmpgtw m4, m5 + mova m6, m4 + pand m4, m3 + pandn m6, m3 + pandn m3, m0 + movh m0, [srcq+dstq] + pand m6, m1 + pand m2, m4 + punpcklbw m0, m7 + paddw m0, m6 + paddw m3, m2 + paddw m0, m3 + pand m0, [pw_255] + mova m3, m0 + packuswb m3, m3 + movh [dstq], m3 + add dstq, bppq + cmp dstq, endq + jle .loop + + mov dstq, [rsp] + dec cntrq + jge .bpp_loop + POP dstq + RET +%endmacro + +INIT_MMX mmxext +ADD_PAETH_PRED_FN 0 + +INIT_MMX ssse3 +ADD_PAETH_PRED_FN 0 diff --git a/ffmpeg/libavcodec/x86/pngdsp_init.c b/ffmpeg/libavcodec/x86/pngdsp_init.c new file mode 100644 index 0000000..4c54ed3 --- /dev/null +++ b/ffmpeg/libavcodec/x86/pngdsp_init.c @@ -0,0 +1,50 @@ +/* + * x86 PNG optimizations. + * Copyright (c) 2008 Loren Merrit + * + * 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 "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/pngdsp.h" + +void ff_add_png_paeth_prediction_mmxext(uint8_t *dst, uint8_t *src, + uint8_t *top, int w, int bpp); +void ff_add_png_paeth_prediction_ssse3(uint8_t *dst, uint8_t *src, + uint8_t *top, int w, int bpp); +void ff_add_bytes_l2_mmx (uint8_t *dst, uint8_t *src1, + uint8_t *src2, int w); +void ff_add_bytes_l2_sse2(uint8_t *dst, uint8_t *src1, + uint8_t *src2, int w); + +av_cold void ff_pngdsp_init_x86(PNGDSPContext *dsp) +{ + int flags = av_get_cpu_flags(); + +#if ARCH_X86_32 + if (EXTERNAL_MMX(flags)) + dsp->add_bytes_l2 = ff_add_bytes_l2_mmx; +#endif + if (EXTERNAL_MMXEXT(flags)) + dsp->add_paeth_prediction = ff_add_png_paeth_prediction_mmxext; + if (EXTERNAL_SSE2(flags)) + dsp->add_bytes_l2 = ff_add_bytes_l2_sse2; + if (EXTERNAL_SSSE3(flags)) + dsp->add_paeth_prediction = ff_add_png_paeth_prediction_ssse3; +} diff --git a/ffmpeg/libavcodec/x86/proresdsp.asm b/ffmpeg/libavcodec/x86/proresdsp.asm new file mode 100644 index 0000000..aedacc2 --- /dev/null +++ b/ffmpeg/libavcodec/x86/proresdsp.asm @@ -0,0 +1,326 @@ +;****************************************************************************** +;* x86-SIMD-optimized IDCT for prores +;* this is identical to "simple" IDCT written by Michael Niedermayer +;* except for the clip range +;* +;* Copyright (c) 2011 Ronald S. Bultje +;* +;* 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 +;* 51, Inc., Foundation Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +%define W1sh2 22725 ; W1 = 90901 = 22725<<2 + 1 +%define W2sh2 21407 ; W2 = 85627 = 21407<<2 - 1 +%define W3sh2 19265 ; W3 = 77062 = 19265<<2 + 2 +%define W4sh2 16384 ; W4 = 65535 = 16384<<2 - 1 +%define W5sh2 12873 ; W5 = 51491 = 12873<<2 - 1 +%define W6sh2 8867 ; W6 = 35468 = 8867<<2 +%define W7sh2 4520 ; W7 = 18081 = 4520<<2 + 1 + +%if ARCH_X86_64 + +SECTION_RODATA + +w4_plus_w2: times 4 dw W4sh2, +W2sh2 +w4_min_w2: times 4 dw W4sh2, -W2sh2 +w4_plus_w6: times 4 dw W4sh2, +W6sh2 +w4_min_w6: times 4 dw W4sh2, -W6sh2 +w1_plus_w3: times 4 dw W1sh2, +W3sh2 +w3_min_w1: times 4 dw W3sh2, -W1sh2 +w7_plus_w3: times 4 dw W7sh2, +W3sh2 +w3_min_w7: times 4 dw W3sh2, -W7sh2 +w1_plus_w5: times 4 dw W1sh2, +W5sh2 +w5_min_w1: times 4 dw W5sh2, -W1sh2 +w5_plus_w7: times 4 dw W5sh2, +W7sh2 +w7_min_w5: times 4 dw W7sh2, -W5sh2 +pw_88: times 8 dw 0x2008 + +cextern pw_1 +cextern pw_4 +cextern pw_512 +cextern pw_1019 + +section .text align=16 + +; interleave data while maintaining source +; %1=type, %2=dstlo, %3=dsthi, %4=src, %5=interleave +%macro SBUTTERFLY3 5 + punpckl%1 m%2, m%4, m%5 + punpckh%1 m%3, m%4, m%5 +%endmacro + +; %1/%2=src1/dst1, %3/%4=dst2, %5/%6=src2, %7=shift +; action: %3/%4 = %1/%2 - %5/%6; %1/%2 += %5/%6 +; %1/%2/%3/%4 >>= %7; dword -> word (in %1/%3) +%macro SUMSUB_SHPK 7 + psubd %3, %1, %5 ; { a0 - b0 }[0-3] + psubd %4, %2, %6 ; { a0 - b0 }[4-7] + paddd %1, %5 ; { a0 + b0 }[0-3] + paddd %2, %6 ; { a0 + b0 }[4-7] + psrad %1, %7 + psrad %2, %7 + psrad %3, %7 + psrad %4, %7 + packssdw %1, %2 ; row[0] + packssdw %3, %4 ; row[7] +%endmacro + +; %1 = row or col (for rounding variable) +; %2 = number of bits to shift at the end +%macro IDCT_1D 2 + ; a0 = (W4 * row[0]) + (1 << (15 - 1)); + ; a1 = a0; + ; a2 = a0; + ; a3 = a0; + ; a0 += W2 * row[2]; + ; a1 += W6 * row[2]; + ; a2 -= W6 * row[2]; + ; a3 -= W2 * row[2]; +%ifidn %1, col + paddw m10,[pw_88] +%endif +%ifidn %1, row + paddw m10,[pw_1] +%endif + SBUTTERFLY3 wd, 0, 1, 10, 8 ; { row[0], row[2] }[0-3]/[4-7] + pmaddwd m2, m0, [w4_plus_w6] + pmaddwd m3, m1, [w4_plus_w6] + pmaddwd m4, m0, [w4_min_w6] + pmaddwd m5, m1, [w4_min_w6] + pmaddwd m6, m0, [w4_min_w2] + pmaddwd m7, m1, [w4_min_w2] + pmaddwd m0, [w4_plus_w2] + pmaddwd m1, [w4_plus_w2] + + ; a0: -1*row[0]-1*row[2] + ; a1: -1*row[0] + ; a2: -1*row[0] + ; a3: -1*row[0]+1*row[2] + + ; a0 += W4*row[4] + W6*row[6]; i.e. -1*row[4] + ; a1 -= W4*row[4] + W2*row[6]; i.e. -1*row[4]-1*row[6] + ; a2 -= W4*row[4] - W2*row[6]; i.e. -1*row[4]+1*row[6] + ; a3 += W4*row[4] - W6*row[6]; i.e. -1*row[4] + SBUTTERFLY3 wd, 8, 9, 13, 12 ; { row[4], row[6] }[0-3]/[4-7] + pmaddwd m10, m8, [w4_plus_w6] + pmaddwd m11, m9, [w4_plus_w6] + paddd m0, m10 ; a0[0-3] + paddd m1, m11 ; a0[4-7] + pmaddwd m10, m8, [w4_min_w6] + pmaddwd m11, m9, [w4_min_w6] + paddd m6, m10 ; a3[0-3] + paddd m7, m11 ; a3[4-7] + pmaddwd m10, m8, [w4_min_w2] + pmaddwd m11, m9, [w4_min_w2] + pmaddwd m8, [w4_plus_w2] + pmaddwd m9, [w4_plus_w2] + psubd m4, m10 ; a2[0-3] intermediate + psubd m5, m11 ; a2[4-7] intermediate + psubd m2, m8 ; a1[0-3] intermediate + psubd m3, m9 ; a1[4-7] intermediate + + ; load/store + mova [r2+ 0], m0 + mova [r2+ 32], m2 + mova [r2+ 64], m4 + mova [r2+ 96], m6 + mova m10,[r2+ 16] ; { row[1] }[0-7] + mova m8, [r2+ 48] ; { row[3] }[0-7] + mova m13,[r2+ 80] ; { row[5] }[0-7] + mova m14,[r2+112] ; { row[7] }[0-7] + mova [r2+ 16], m1 + mova [r2+ 48], m3 + mova [r2+ 80], m5 + mova [r2+112], m7 +%ifidn %1, row + pmullw m10,[r3+ 16] + pmullw m8, [r3+ 48] + pmullw m13,[r3+ 80] + pmullw m14,[r3+112] +%endif + + ; b0 = MUL(W1, row[1]); + ; MAC(b0, W3, row[3]); + ; b1 = MUL(W3, row[1]); + ; MAC(b1, -W7, row[3]); + ; b2 = MUL(W5, row[1]); + ; MAC(b2, -W1, row[3]); + ; b3 = MUL(W7, row[1]); + ; MAC(b3, -W5, row[3]); + SBUTTERFLY3 wd, 0, 1, 10, 8 ; { row[1], row[3] }[0-3]/[4-7] + pmaddwd m2, m0, [w3_min_w7] + pmaddwd m3, m1, [w3_min_w7] + pmaddwd m4, m0, [w5_min_w1] + pmaddwd m5, m1, [w5_min_w1] + pmaddwd m6, m0, [w7_min_w5] + pmaddwd m7, m1, [w7_min_w5] + pmaddwd m0, [w1_plus_w3] + pmaddwd m1, [w1_plus_w3] + + ; b0: +1*row[1]+2*row[3] + ; b1: +2*row[1]-1*row[3] + ; b2: -1*row[1]-1*row[3] + ; b3: +1*row[1]+1*row[3] + + ; MAC(b0, W5, row[5]); + ; MAC(b0, W7, row[7]); + ; MAC(b1, -W1, row[5]); + ; MAC(b1, -W5, row[7]); + ; MAC(b2, W7, row[5]); + ; MAC(b2, W3, row[7]); + ; MAC(b3, W3, row[5]); + ; MAC(b3, -W1, row[7]); + SBUTTERFLY3 wd, 8, 9, 13, 14 ; { row[5], row[7] }[0-3]/[4-7] + + ; b0: -1*row[5]+1*row[7] + ; b1: -1*row[5]+1*row[7] + ; b2: +1*row[5]+2*row[7] + ; b3: +2*row[5]-1*row[7] + + pmaddwd m10, m8, [w1_plus_w5] + pmaddwd m11, m9, [w1_plus_w5] + pmaddwd m12, m8, [w5_plus_w7] + pmaddwd m13, m9, [w5_plus_w7] + psubd m2, m10 ; b1[0-3] + psubd m3, m11 ; b1[4-7] + paddd m0, m12 ; b0[0-3] + paddd m1, m13 ; b0[4-7] + pmaddwd m12, m8, [w7_plus_w3] + pmaddwd m13, m9, [w7_plus_w3] + pmaddwd m8, [w3_min_w1] + pmaddwd m9, [w3_min_w1] + paddd m4, m12 ; b2[0-3] + paddd m5, m13 ; b2[4-7] + paddd m6, m8 ; b3[0-3] + paddd m7, m9 ; b3[4-7] + + ; row[0] = (a0 + b0) >> 15; + ; row[7] = (a0 - b0) >> 15; + ; row[1] = (a1 + b1) >> 15; + ; row[6] = (a1 - b1) >> 15; + ; row[2] = (a2 + b2) >> 15; + ; row[5] = (a2 - b2) >> 15; + ; row[3] = (a3 + b3) >> 15; + ; row[4] = (a3 - b3) >> 15; + mova m8, [r2+ 0] ; a0[0-3] + mova m9, [r2+16] ; a0[4-7] + SUMSUB_SHPK m8, m9, m10, m11, m0, m1, %2 + mova m0, [r2+32] ; a1[0-3] + mova m1, [r2+48] ; a1[4-7] + SUMSUB_SHPK m0, m1, m9, m11, m2, m3, %2 + mova m1, [r2+64] ; a2[0-3] + mova m2, [r2+80] ; a2[4-7] + SUMSUB_SHPK m1, m2, m11, m3, m4, m5, %2 + mova m2, [r2+96] ; a3[0-3] + mova m3, [r2+112] ; a3[4-7] + SUMSUB_SHPK m2, m3, m4, m5, m6, m7, %2 +%endmacro + +; void prores_idct_put_10_(uint8_t *pixels, int stride, +; int16_t *block, const int16_t *qmat); +%macro idct_put_fn 1 +cglobal prores_idct_put_10, 4, 4, %1 + movsxd r1, r1d + pxor m15, m15 ; zero + + ; for (i = 0; i < 8; i++) + ; idctRowCondDC(block + i*8); + mova m10,[r2+ 0] ; { row[0] }[0-7] + mova m8, [r2+32] ; { row[2] }[0-7] + mova m13,[r2+64] ; { row[4] }[0-7] + mova m12,[r2+96] ; { row[6] }[0-7] + + pmullw m10,[r3+ 0] + pmullw m8, [r3+32] + pmullw m13,[r3+64] + pmullw m12,[r3+96] + + IDCT_1D row, 15 + + ; transpose for second part of IDCT + TRANSPOSE8x8W 8, 0, 1, 2, 4, 11, 9, 10, 3 + mova [r2+ 16], m0 + mova [r2+ 48], m2 + mova [r2+ 80], m11 + mova [r2+112], m10 + SWAP 8, 10 + SWAP 1, 8 + SWAP 4, 13 + SWAP 9, 12 + + ; for (i = 0; i < 8; i++) + ; idctSparseColAdd(dest + i, line_size, block + i); + IDCT_1D col, 18 + + ; clip/store + mova m3, [pw_4] + mova m5, [pw_1019] + pmaxsw m8, m3 + pmaxsw m0, m3 + pmaxsw m1, m3 + pmaxsw m2, m3 + pmaxsw m4, m3 + pmaxsw m11, m3 + pmaxsw m9, m3 + pmaxsw m10, m3 + pminsw m8, m5 + pminsw m0, m5 + pminsw m1, m5 + pminsw m2, m5 + pminsw m4, m5 + pminsw m11, m5 + pminsw m9, m5 + pminsw m10, m5 + + lea r2, [r1*3] + mova [r0 ], m8 + mova [r0+r1 ], m0 + mova [r0+r1*2], m1 + mova [r0+r2 ], m2 + lea r0, [r0+r1*4] + mova [r0 ], m4 + mova [r0+r1 ], m11 + mova [r0+r1*2], m9 + mova [r0+r2 ], m10 + RET +%endmacro + +%macro SIGNEXTEND 2-3 +%if cpuflag(sse4) ; dstlow, dsthigh + movhlps %2, %1 + pmovsxwd %1, %1 + pmovsxwd %2, %2 +%elif cpuflag(sse2) ; dstlow, dsthigh, tmp + pxor %3, %3 + pcmpgtw %3, %1 + mova %2, %1 + punpcklwd %1, %3 + punpckhwd %2, %3 +%endif +%endmacro + +INIT_XMM sse2 +idct_put_fn 16 +INIT_XMM sse4 +idct_put_fn 16 +%if HAVE_AVX_EXTERNAL +INIT_XMM avx +idct_put_fn 16 +%endif + +%endif diff --git a/ffmpeg/libavcodec/x86/proresdsp_init.c b/ffmpeg/libavcodec/x86/proresdsp_init.c new file mode 100644 index 0000000..91ff257 --- /dev/null +++ b/ffmpeg/libavcodec/x86/proresdsp_init.c @@ -0,0 +1,57 @@ +/* + * Apple ProRes compatible decoder + * + * Copyright (c) 2010-2011 Maxim Poliakovski + * + * 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 "libavutil/x86/cpu.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/proresdsp.h" + +void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize, + int16_t *block, const int16_t *qmat); +void ff_prores_idct_put_10_sse4(uint16_t *dst, int linesize, + int16_t *block, const int16_t *qmat); +void ff_prores_idct_put_10_avx (uint16_t *dst, int linesize, + int16_t *block, const int16_t *qmat); + +void ff_proresdsp_x86_init(ProresDSPContext *dsp, AVCodecContext *avctx) +{ +#if ARCH_X86_64 + int flags = av_get_cpu_flags(); + + if(avctx->flags & CODEC_FLAG_BITEXACT) + return; + + if (EXTERNAL_SSE2(flags)) { + dsp->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; + dsp->idct_put = ff_prores_idct_put_10_sse2; + } + + if (EXTERNAL_SSE4(flags)) { + dsp->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; + dsp->idct_put = ff_prores_idct_put_10_sse4; + } + + if (EXTERNAL_AVX(flags)) { + dsp->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM; + dsp->idct_put = ff_prores_idct_put_10_avx; + } +#endif /* ARCH_X86_64 */ +} diff --git a/ffmpeg/libavcodec/x86/qpelbase.asm b/ffmpeg/libavcodec/x86/qpelbase.asm new file mode 100644 index 0000000..c2ffb86 --- /dev/null +++ b/ffmpeg/libavcodec/x86/qpelbase.asm @@ -0,0 +1,176 @@ +;****************************************************************************** +;* MMX optimized DSP utils +;* Copyright (c) 2008 Loren Merritt +;* Copyright (c) 2003-2013 Michael Niedermayer +;* Copyright (c) 2013 Daniel Kang +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION .text + +%macro op_avgh 3 + movh %3, %2 + pavgb %1, %3 + movh %2, %1 +%endmacro + +%macro op_avg 2 + pavgb %1, %2 + mova %2, %1 +%endmacro + +%macro op_puth 2-3 + movh %2, %1 +%endmacro + +%macro op_put 2 + mova %2, %1 +%endmacro + +; void pixels4_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +%macro PIXELS4_L2 1 +%define OP op_%1h +cglobal %1_pixels4_l2, 6,6 + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + test r5d, 1 + je .loop + movd m0, [r1] + movd m1, [r2] + add r1, r4 + add r2, 4 + pavgb m0, m1 + OP m0, [r0], m3 + add r0, r3 + dec r5d +.loop: + mova m0, [r1] + mova m1, [r1+r4] + lea r1, [r1+2*r4] + pavgb m0, [r2] + pavgb m1, [r2+4] + OP m0, [r0], m3 + OP m1, [r0+r3], m3 + lea r0, [r0+2*r3] + mova m0, [r1] + mova m1, [r1+r4] + lea r1, [r1+2*r4] + pavgb m0, [r2+8] + pavgb m1, [r2+12] + OP m0, [r0], m3 + OP m1, [r0+r3], m3 + lea r0, [r0+2*r3] + add r2, 16 + sub r5d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PIXELS4_L2 put +PIXELS4_L2 avg + +; void pixels8_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +%macro PIXELS8_L2 1 +%define OP op_%1 +cglobal %1_pixels8_l2, 6,6 + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + test r5d, 1 + je .loop + mova m0, [r1] + mova m1, [r2] + add r1, r4 + add r2, 8 + pavgb m0, m1 + OP m0, [r0] + add r0, r3 + dec r5d +.loop: + mova m0, [r1] + mova m1, [r1+r4] + lea r1, [r1+2*r4] + pavgb m0, [r2] + pavgb m1, [r2+8] + OP m0, [r0] + OP m1, [r0+r3] + lea r0, [r0+2*r3] + mova m0, [r1] + mova m1, [r1+r4] + lea r1, [r1+2*r4] + pavgb m0, [r2+16] + pavgb m1, [r2+24] + OP m0, [r0] + OP m1, [r0+r3] + lea r0, [r0+2*r3] + add r2, 32 + sub r5d, 4 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PIXELS8_L2 put +PIXELS8_L2 avg + +; void pixels16_l2_mmxext(uint8_t *dst, uint8_t *src1, uint8_t *src2, int dstStride, int src1Stride, int h) +%macro PIXELS16_L2 1 +%define OP op_%1 +cglobal %1_pixels16_l2, 6,6 + movsxdifnidn r3, r3d + movsxdifnidn r4, r4d + test r5d, 1 + je .loop + mova m0, [r1] + mova m1, [r1+8] + pavgb m0, [r2] + pavgb m1, [r2+8] + add r1, r4 + add r2, 16 + OP m0, [r0] + OP m1, [r0+8] + add r0, r3 + dec r5d +.loop: + mova m0, [r1] + mova m1, [r1+8] + add r1, r4 + pavgb m0, [r2] + pavgb m1, [r2+8] + OP m0, [r0] + OP m1, [r0+8] + add r0, r3 + mova m0, [r1] + mova m1, [r1+8] + add r1, r4 + pavgb m0, [r2+16] + pavgb m1, [r2+24] + OP m0, [r0] + OP m1, [r0+8] + add r0, r3 + add r2, 32 + sub r5d, 2 + jne .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PIXELS16_L2 put +PIXELS16_L2 avg diff --git a/ffmpeg/libavcodec/x86/rv34dsp.asm b/ffmpeg/libavcodec/x86/rv34dsp.asm new file mode 100644 index 0000000..4d9c35b --- /dev/null +++ b/ffmpeg/libavcodec/x86/rv34dsp.asm @@ -0,0 +1,196 @@ +;****************************************************************************** +;* MMX/SSE2-optimized functions for the RV30 and RV40 decoders +;* Copyright (C) 2012 Christophe Gisquet +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +pw_row_coeffs: times 4 dw 13 + times 4 dw 17 + times 4 dw 7 +pd_512: times 2 dd 0x200 +pw_col_coeffs: dw 13, 13, 13, -13 + dw 17, 7, 7, -17 + dw 13, -13, 13, 13 + dw -7, 17, -17, -7 + +SECTION .text + +%macro IDCT_DC_NOROUND 1 + imul %1, 13*13*3 + sar %1, 11 +%endmacro + +%macro IDCT_DC_ROUND 1 + imul %1, 13*13 + add %1, 0x200 + sar %1, 10 +%endmacro + +%macro rv34_idct 1 +cglobal rv34_idct_%1, 1, 2, 0 + movsx r1, word [r0] + IDCT_DC r1 + movd m0, r1d + pshufw m0, m0, 0 + movq [r0+ 0], m0 + movq [r0+ 8], m0 + movq [r0+16], m0 + movq [r0+24], m0 + REP_RET +%endmacro + +INIT_MMX mmxext +%define IDCT_DC IDCT_DC_ROUND +rv34_idct dc +%define IDCT_DC IDCT_DC_NOROUND +rv34_idct dc_noround + +; ff_rv34_idct_dc_add_mmx(uint8_t *dst, int stride, int dc); +INIT_MMX mmx +cglobal rv34_idct_dc_add, 3, 3 + ; calculate DC + IDCT_DC_ROUND r2 + pxor m1, m1 + movd m0, r2d + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 + punpcklbw m0, m0 + punpcklbw m1, m1 + punpcklwd m0, m0 + punpcklwd m1, m1 + + ; add DC + lea r2, [r0+r1*2] + movh m2, [r0] + movh m3, [r0+r1] + movh m4, [r2] + movh m5, [r2+r1] + paddusb m2, m0 + paddusb m3, m0 + paddusb m4, m0 + paddusb m5, m0 + psubusb m2, m1 + psubusb m3, m1 + psubusb m4, m1 + psubusb m5, m1 + movh [r0], m2 + movh [r0+r1], m3 + movh [r2], m4 + movh [r2+r1], m5 + RET + +; Load coeffs and perform row transform +; Output: coeffs in mm[0467], rounder in mm5 +%macro ROW_TRANSFORM 1 + pxor mm7, mm7 + mova mm0, [%1+ 0*8] + mova mm1, [%1+ 1*8] + mova mm2, [%1+ 2*8] + mova mm3, [%1+ 3*8] + mova [%1+ 0*8], mm7 + mova [%1+ 1*8], mm7 + mova [%1+ 2*8], mm7 + mova [%1+ 3*8], mm7 + mova mm4, mm0 + mova mm6, [pw_row_coeffs+ 0] + paddsw mm0, mm2 ; b0 + b2 + psubsw mm4, mm2 ; b0 - b2 + pmullw mm0, mm6 ; *13 = z0 + pmullw mm4, mm6 ; *13 = z1 + mova mm5, mm1 + pmullw mm1, [pw_row_coeffs+ 8] ; b1*17 + pmullw mm5, [pw_row_coeffs+16] ; b1* 7 + mova mm7, mm3 + pmullw mm3, [pw_row_coeffs+ 8] ; b3*17 + pmullw mm7, [pw_row_coeffs+16] ; b3* 7 + paddsw mm1, mm7 ; z3 = b1*17 + b3* 7 + psubsw mm5, mm3 ; z2 = b1* 7 - b3*17 + mova mm7, mm0 + mova mm6, mm4 + paddsw mm0, mm1 ; z0 + z3 + psubsw mm7, mm1 ; z0 - z3 + paddsw mm4, mm5 ; z1 + z2 + psubsw mm6, mm5 ; z1 - z2 + mova mm5, [pd_512] ; 0x200 +%endmacro + +; ff_rv34_idct_add_mmxext(uint8_t *dst, ptrdiff_t stride, int16_t *block); +%macro COL_TRANSFORM 4 + pshufw mm3, %2, 0xDD ; col. 1,3,1,3 + pshufw %2, %2, 0x88 ; col. 0,2,0,2 + pmaddwd %2, %3 ; 13*c0+13*c2 | 13*c0-13*c2 = z0 | z1 + pmaddwd mm3, %4 ; 17*c1+ 7*c3 | 7*c1-17*c3 = z3 | z2 + paddd %2, mm5 + pshufw mm1, %2, 01001110b ; z1 | z0 + pshufw mm2, mm3, 01001110b ; z2 | z3 + paddd %2, mm3 ; z0+z3 | z1+z2 + psubd mm1, mm2 ; z1-z2 | z0-z3 + movd mm3, %1 + psrad %2, 10 + pxor mm2, mm2 + psrad mm1, 10 + punpcklbw mm3, mm2 + packssdw %2, mm1 + paddw %2, mm3 + packuswb %2, %2 + movd %1, %2 +%endmacro +INIT_MMX mmxext +cglobal rv34_idct_add, 3,3,0, d, s, b + ROW_TRANSFORM bq + COL_TRANSFORM [dq], mm0, [pw_col_coeffs+ 0], [pw_col_coeffs+ 8] + mova mm0, [pw_col_coeffs+ 0] + COL_TRANSFORM [dq+sq], mm4, mm0, [pw_col_coeffs+ 8] + mova mm4, [pw_col_coeffs+ 8] + lea dq, [dq + 2*sq] + COL_TRANSFORM [dq], mm6, mm0, mm4 + COL_TRANSFORM [dq+sq], mm7, mm0, mm4 + ret + +; ff_rv34_idct_dc_add_sse4(uint8_t *dst, int stride, int dc); +INIT_XMM sse4 +cglobal rv34_idct_dc_add, 3, 3, 6 + ; load data + IDCT_DC_ROUND r2 + pxor m1, m1 + + ; calculate DC + movd m0, r2d + lea r2, [r0+r1*2] + movd m2, [r0] + movd m3, [r0+r1] + pshuflw m0, m0, 0 + movd m4, [r2] + movd m5, [r2+r1] + punpcklqdq m0, m0 + punpckldq m2, m3 + punpckldq m4, m5 + punpcklbw m2, m1 + punpcklbw m4, m1 + paddw m2, m0 + paddw m4, m0 + packuswb m2, m4 + movd [r0], m2 + pextrd [r0+r1], m2, 1 + pextrd [r2], m2, 2 + pextrd [r2+r1], m2, 3 + RET diff --git a/ffmpeg/libavcodec/x86/rv34dsp_init.c b/ffmpeg/libavcodec/x86/rv34dsp_init.c new file mode 100644 index 0000000..a2dea74 --- /dev/null +++ b/ffmpeg/libavcodec/x86/rv34dsp_init.c @@ -0,0 +1,45 @@ +/* + * RV30/40 MMX/SSE2 optimizations + * Copyright (C) 2012 Christophe Gisquet + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/rv34dsp.h" + +void ff_rv34_idct_dc_mmxext(int16_t *block); +void ff_rv34_idct_dc_noround_mmxext(int16_t *block); +void ff_rv34_idct_dc_add_mmx(uint8_t *dst, ptrdiff_t stride, int dc); +void ff_rv34_idct_dc_add_sse4(uint8_t *dst, ptrdiff_t stride, int dc); +void ff_rv34_idct_add_mmxext(uint8_t *dst, ptrdiff_t stride, int16_t *block); + +av_cold void ff_rv34dsp_init_x86(RV34DSPContext* c) +{ + int mm_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(mm_flags)) + c->rv34_idct_dc_add = ff_rv34_idct_dc_add_mmx; + if (EXTERNAL_MMXEXT(mm_flags)) { + c->rv34_inv_transform_dc = ff_rv34_idct_dc_noround_mmxext; + c->rv34_idct_add = ff_rv34_idct_add_mmxext; + } + if (EXTERNAL_SSE4(mm_flags)) + c->rv34_idct_dc_add = ff_rv34_idct_dc_add_sse4; +} diff --git a/ffmpeg/libavcodec/x86/rv40dsp.asm b/ffmpeg/libavcodec/x86/rv40dsp.asm new file mode 100644 index 0000000..7ec72be --- /dev/null +++ b/ffmpeg/libavcodec/x86/rv40dsp.asm @@ -0,0 +1,505 @@ +;****************************************************************************** +;* MMX/SSE2-optimized functions for the RV40 decoder +;* Copyright (c) 2010 Ronald S. Bultje +;* Copyright (c) 2010 Jason Garrett-Glaser +;* Copyright (C) 2012 Christophe Gisquet +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +align 16 +pw_1024: times 8 dw 1 << (16 - 6) ; pw_1024 + +sixtap_filter_hb_m: times 8 db 1, -5 + times 8 db 52, 20 + ; multiplied by 2 to have the same shift + times 8 db 2, -10 + times 8 db 40, 40 + ; back to normal + times 8 db 1, -5 + times 8 db 20, 52 + +sixtap_filter_v_m: times 8 dw 1 + times 8 dw -5 + times 8 dw 52 + times 8 dw 20 + ; multiplied by 2 to have the same shift + times 8 dw 2 + times 8 dw -10 + times 8 dw 40 + times 8 dw 40 + ; back to normal + times 8 dw 1 + times 8 dw -5 + times 8 dw 20 + times 8 dw 52 + +%ifdef PIC +%define sixtap_filter_hw picregq +%define sixtap_filter_hb picregq +%define sixtap_filter_v picregq +%define npicregs 1 +%else +%define sixtap_filter_hw sixtap_filter_hw_m +%define sixtap_filter_hb sixtap_filter_hb_m +%define sixtap_filter_v sixtap_filter_v_m +%define npicregs 0 +%endif + +filter_h6_shuf1: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 +filter_h6_shuf2: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 +filter_h6_shuf3: db 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11, 10, 12, 11 + +cextern pw_32 +cextern pw_16 +cextern pw_512 + +SECTION .text + +;----------------------------------------------------------------------------- +; subpel MC functions: +; +; void [put|rv40]_rv40_qpel_[h|v]_(uint8_t *dst, int deststride, +; uint8_t *src, int srcstride, +; int len, int m); +;---------------------------------------------------------------------- +%macro LOAD 2 +%if WIN64 + movsxd %1q, %1d +%endif +%ifdef PIC + add %1q, picregq +%else + add %1q, %2 +%endif +%endmacro + +%macro STORE 3 +%ifidn %3, avg + movh %2, [dstq] +%endif + packuswb %1, %1 +%ifidn %3, avg +%if cpuflag(3dnow) + pavgusb %1, %2 +%else + pavgb %1, %2 +%endif +%endif + movh [dstq], %1 +%endmacro + +%macro FILTER_V 1 +cglobal %1_rv40_qpel_v, 6,6+npicregs,12, dst, dststride, src, srcstride, height, my, picreg +%ifdef PIC + lea picregq, [sixtap_filter_v_m] +%endif + pxor m7, m7 + LOAD my, sixtap_filter_v + + ; read 5 lines + sub srcq, srcstrideq + sub srcq, srcstrideq + movh m0, [srcq] + movh m1, [srcq+srcstrideq] + movh m2, [srcq+srcstrideq*2] + lea srcq, [srcq+srcstrideq*2] + add srcq, srcstrideq + movh m3, [srcq] + movh m4, [srcq+srcstrideq] + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + +%ifdef m8 + mova m8, [myq+ 0] + mova m9, [myq+16] + mova m10, [myq+32] + mova m11, [myq+48] +%define COEFF05 m8 +%define COEFF14 m9 +%define COEFF2 m10 +%define COEFF3 m11 +%else +%define COEFF05 [myq+ 0] +%define COEFF14 [myq+16] +%define COEFF2 [myq+32] +%define COEFF3 [myq+48] +%endif +.nextrow: + mova m6, m1 + movh m5, [srcq+2*srcstrideq] ; read new row + paddw m6, m4 + punpcklbw m5, m7 + pmullw m6, COEFF14 + paddw m0, m5 + pmullw m0, COEFF05 + paddw m6, m0 + mova m0, m1 + paddw m6, [pw_32] + mova m1, m2 + pmullw m2, COEFF2 + paddw m6, m2 + mova m2, m3 + pmullw m3, COEFF3 + paddw m6, m3 + + ; round/clip/store + mova m3, m4 + psraw m6, 6 + mova m4, m5 + STORE m6, m5, %1 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET +%endmacro + +%macro FILTER_H 1 +cglobal %1_rv40_qpel_h, 6, 6+npicregs, 12, dst, dststride, src, srcstride, height, mx, picreg +%ifdef PIC + lea picregq, [sixtap_filter_v_m] +%endif + pxor m7, m7 + LOAD mx, sixtap_filter_v + mova m6, [pw_32] +%ifdef m8 + mova m8, [mxq+ 0] + mova m9, [mxq+16] + mova m10, [mxq+32] + mova m11, [mxq+48] +%define COEFF05 m8 +%define COEFF14 m9 +%define COEFF2 m10 +%define COEFF3 m11 +%else +%define COEFF05 [mxq+ 0] +%define COEFF14 [mxq+16] +%define COEFF2 [mxq+32] +%define COEFF3 [mxq+48] +%endif +.nextrow: + movq m0, [srcq-2] + movq m5, [srcq+3] + movq m1, [srcq-1] + movq m4, [srcq+2] + punpcklbw m0, m7 + punpcklbw m5, m7 + punpcklbw m1, m7 + punpcklbw m4, m7 + movq m2, [srcq-0] + movq m3, [srcq+1] + paddw m0, m5 + paddw m1, m4 + punpcklbw m2, m7 + punpcklbw m3, m7 + pmullw m0, COEFF05 + pmullw m1, COEFF14 + pmullw m2, COEFF2 + pmullw m3, COEFF3 + paddw m0, m6 + paddw m1, m2 + paddw m0, m3 + paddw m0, m1 + psraw m0, 6 + STORE m0, m1, %1 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +FILTER_V put +FILTER_H put + +INIT_MMX mmxext +FILTER_V avg +FILTER_H avg + +INIT_MMX 3dnow +FILTER_V avg +FILTER_H avg +%endif + +INIT_XMM sse2 +FILTER_H put +FILTER_H avg +FILTER_V put +FILTER_V avg + +%macro FILTER_SSSE3 1 +cglobal %1_rv40_qpel_v, 6,6+npicregs,8, dst, dststride, src, srcstride, height, my, picreg +%ifdef PIC + lea picregq, [sixtap_filter_hb_m] +%endif + + ; read 5 lines + sub srcq, srcstrideq + LOAD my, sixtap_filter_hb + sub srcq, srcstrideq + movh m0, [srcq] + movh m1, [srcq+srcstrideq] + movh m2, [srcq+srcstrideq*2] + lea srcq, [srcq+srcstrideq*2] + add srcq, srcstrideq + mova m5, [myq] + movh m3, [srcq] + movh m4, [srcq+srcstrideq] + lea srcq, [srcq+2*srcstrideq] + +.nextrow: + mova m6, m2 + punpcklbw m0, m1 + punpcklbw m6, m3 + pmaddubsw m0, m5 + pmaddubsw m6, [myq+16] + movh m7, [srcq] ; read new row + paddw m6, m0 + mova m0, m1 + mova m1, m2 + mova m2, m3 + mova m3, m4 + mova m4, m7 + punpcklbw m7, m3 + pmaddubsw m7, m5 + paddw m6, m7 + pmulhrsw m6, [pw_512] + STORE m6, m7, %1 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +cglobal %1_rv40_qpel_h, 6,6+npicregs,8, dst, dststride, src, srcstride, height, mx, picreg +%ifdef PIC + lea picregq, [sixtap_filter_hb_m] +%endif + mova m3, [filter_h6_shuf2] + mova m4, [filter_h6_shuf3] + LOAD mx, sixtap_filter_hb + mova m5, [mxq] ; set up 6tap filter in bytes + mova m6, [mxq+16] + mova m7, [filter_h6_shuf1] + +.nextrow: + movu m0, [srcq-2] + mova m1, m0 + mova m2, m0 + pshufb m0, m7 + pshufb m1, m3 + pshufb m2, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m6 + pmaddubsw m2, m5 + paddw m0, m1 + paddw m0, m2 + pmulhrsw m0, [pw_512] + STORE m0, m1, %1 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET +%endmacro + +INIT_XMM ssse3 +FILTER_SSSE3 put +FILTER_SSSE3 avg + +; %1=5bits weights?, %2=dst %3=src1 %4=src3 %5=stride if sse2 +%macro RV40_WCORE 4-5 + movh m4, [%3 + r6 + 0] + movh m5, [%4 + r6 + 0] +%if %0 == 4 +%define OFFSET r6 + mmsize / 2 +%else + ; 8x8 block and sse2, stride was provided +%define OFFSET r6 + add r6, r5 +%endif + movh m6, [%3 + OFFSET] + movh m7, [%4 + OFFSET] + +%if %1 == 0 + ; 14bits weights + punpcklbw m4, m0 + punpcklbw m5, m0 + punpcklbw m6, m0 + punpcklbw m7, m0 + + psllw m4, 7 + psllw m5, 7 + psllw m6, 7 + psllw m7, 7 + pmulhw m4, m3 + pmulhw m5, m2 + pmulhw m6, m3 + pmulhw m7, m2 + + paddw m4, m5 + paddw m6, m7 +%else + ; 5bits weights +%if cpuflag(ssse3) + punpcklbw m4, m5 + punpcklbw m6, m7 + + pmaddubsw m4, m3 + pmaddubsw m6, m3 +%else + punpcklbw m4, m0 + punpcklbw m5, m0 + punpcklbw m6, m0 + punpcklbw m7, m0 + + pmullw m4, m3 + pmullw m5, m2 + pmullw m6, m3 + pmullw m7, m2 + paddw m4, m5 + paddw m6, m7 +%endif + +%endif + + ; bias and shift down +%if cpuflag(ssse3) + pmulhrsw m4, m1 + pmulhrsw m6, m1 +%else + paddw m4, m1 + paddw m6, m1 + psrlw m4, 5 + psrlw m6, 5 +%endif + + packuswb m4, m6 +%if %0 == 5 + ; Only called for 8x8 blocks and sse2 + sub r6, r5 + movh [%2 + r6], m4 + add r6, r5 + movhps [%2 + r6], m4 +%else + mova [%2 + r6], m4 +%endif +%endmacro + + +%macro MAIN_LOOP 2 +%if mmsize == 8 + RV40_WCORE %2, r0, r1, r2 +%if %1 == 16 + RV40_WCORE %2, r0 + 8, r1 + 8, r2 + 8 +%endif + + ; Prepare for next loop + add r6, r5 +%else +%ifidn %1, 8 + RV40_WCORE %2, r0, r1, r2, r5 + ; Prepare 2 next lines + add r6, r5 +%else + RV40_WCORE %2, r0, r1, r2 + ; Prepare single next line + add r6, r5 +%endif +%endif + +%endmacro + +; rv40_weight_func_%1(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w1, int w2, int stride) +; %1=size %2=num of xmm regs +; The weights are FP0.14 notation of fractions depending on pts. +; For timebases without rounding error (i.e. PAL), the fractions +; can be simplified, and several operations can be avoided. +; Therefore, we check here whether they are multiples of 2^9 for +; those simplifications to occur. +%macro RV40_WEIGHT 3 +cglobal rv40_weight_func_%1_%2, 6, 7, 8 +%if cpuflag(ssse3) + mova m1, [pw_1024] +%else + mova m1, [pw_16] +%endif + pxor m0, m0 + ; Set loop counter and increments + mov r6, r5 + shl r6, %3 + add r0, r6 + add r1, r6 + add r2, r6 + neg r6 + + movd m2, r3d + movd m3, r4d +%ifidn %1,rnd +%define RND 0 + SPLATW m2, m2 +%else +%define RND 1 +%if cpuflag(ssse3) + punpcklbw m3, m2 +%else + SPLATW m2, m2 +%endif +%endif + SPLATW m3, m3 + +.loop: + MAIN_LOOP %2, RND + jnz .loop + REP_RET +%endmacro + +INIT_MMX mmxext +RV40_WEIGHT rnd, 8, 3 +RV40_WEIGHT rnd, 16, 4 +RV40_WEIGHT nornd, 8, 3 +RV40_WEIGHT nornd, 16, 4 + +INIT_XMM sse2 +RV40_WEIGHT rnd, 8, 3 +RV40_WEIGHT rnd, 16, 4 +RV40_WEIGHT nornd, 8, 3 +RV40_WEIGHT nornd, 16, 4 + +INIT_XMM ssse3 +RV40_WEIGHT rnd, 8, 3 +RV40_WEIGHT rnd, 16, 4 +RV40_WEIGHT nornd, 8, 3 +RV40_WEIGHT nornd, 16, 4 diff --git a/ffmpeg/libavcodec/x86/rv40dsp_init.c b/ffmpeg/libavcodec/x86/rv40dsp_init.c new file mode 100644 index 0000000..2f97518 --- /dev/null +++ b/ffmpeg/libavcodec/x86/rv40dsp_init.c @@ -0,0 +1,243 @@ +/* + * RV40 decoder motion compensation functions x86-optimised + * Copyright (c) 2008 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * RV40 decoder motion compensation functions x86-optimised + * 2,0 and 0,2 have h264 equivalents. + * 3,3 is bugged in the rv40 format and maps to _xy2 version + */ + +#include "libavcodec/rv34dsp.h" +#include "libavutil/attributes.h" +#include "libavutil/mem.h" +#include "libavutil/x86/cpu.h" +#include "dsputil_mmx.h" + +#if HAVE_YASM +void ff_put_rv40_chroma_mc8_mmx (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_rv40_chroma_mc8_mmxext(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_rv40_chroma_mc8_3dnow(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +void ff_put_rv40_chroma_mc4_mmx (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_rv40_chroma_mc4_mmxext(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_rv40_chroma_mc4_3dnow(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + +#define DECLARE_WEIGHT(opt) \ +void ff_rv40_weight_func_rnd_16_##opt(uint8_t *dst, uint8_t *src1, uint8_t *src2, \ + int w1, int w2, ptrdiff_t stride); \ +void ff_rv40_weight_func_rnd_8_##opt (uint8_t *dst, uint8_t *src1, uint8_t *src2, \ + int w1, int w2, ptrdiff_t stride); \ +void ff_rv40_weight_func_nornd_16_##opt(uint8_t *dst, uint8_t *src1, uint8_t *src2, \ + int w1, int w2, ptrdiff_t stride); \ +void ff_rv40_weight_func_nornd_8_##opt (uint8_t *dst, uint8_t *src1, uint8_t *src2, \ + int w1, int w2, ptrdiff_t stride); +DECLARE_WEIGHT(mmxext) +DECLARE_WEIGHT(sse2) +DECLARE_WEIGHT(ssse3) + +/** @{ */ +/** + * Define one qpel function. + * LOOPSIZE must be already set to the number of pixels processed per + * iteration in the inner loop of the called functions. + * COFF(x) must be already defined so as to provide the offset into any + * array of coeffs used by the called function for the qpel position x. + */ +#define QPEL_FUNC_DECL(OP, SIZE, PH, PV, OPT) \ +static void OP ## rv40_qpel ##SIZE ##_mc ##PH ##PV ##OPT(uint8_t *dst, \ + uint8_t *src, \ + ptrdiff_t stride) \ +{ \ + int i; \ + if (PH && PV) { \ + DECLARE_ALIGNED(16, uint8_t, tmp)[SIZE * (SIZE + 5)]; \ + uint8_t *tmpptr = tmp + SIZE * 2; \ + src -= stride * 2; \ + \ + for (i = 0; i < SIZE; i += LOOPSIZE) \ + ff_put_rv40_qpel_h ##OPT(tmp + i, SIZE, src + i, stride, \ + SIZE + 5, HCOFF(PH)); \ + for (i = 0; i < SIZE; i += LOOPSIZE) \ + ff_ ##OP ##rv40_qpel_v ##OPT(dst + i, stride, tmpptr + i, \ + SIZE, SIZE, VCOFF(PV)); \ + } else if (PV) { \ + for (i = 0; i < SIZE; i += LOOPSIZE) \ + ff_ ##OP ##rv40_qpel_v ## OPT(dst + i, stride, src + i, \ + stride, SIZE, VCOFF(PV)); \ + } else { \ + for (i = 0; i < SIZE; i += LOOPSIZE) \ + ff_ ##OP ##rv40_qpel_h ## OPT(dst + i, stride, src + i, \ + stride, SIZE, HCOFF(PH)); \ + } \ +}; + +/** Declare functions for sizes 8 and 16 and given operations + * and qpel position. */ +#define QPEL_FUNCS_DECL(OP, PH, PV, OPT) \ + QPEL_FUNC_DECL(OP, 8, PH, PV, OPT) \ + QPEL_FUNC_DECL(OP, 16, PH, PV, OPT) + +/** Declare all functions for all sizes and qpel positions */ +#define QPEL_MC_DECL(OP, OPT) \ +void ff_ ##OP ##rv40_qpel_h ##OPT(uint8_t *dst, ptrdiff_t dstStride, \ + const uint8_t *src, \ + ptrdiff_t srcStride, \ + int len, int m); \ +void ff_ ##OP ##rv40_qpel_v ##OPT(uint8_t *dst, ptrdiff_t dstStride, \ + const uint8_t *src, \ + ptrdiff_t srcStride, \ + int len, int m); \ +QPEL_FUNCS_DECL(OP, 0, 1, OPT) \ +QPEL_FUNCS_DECL(OP, 0, 3, OPT) \ +QPEL_FUNCS_DECL(OP, 1, 0, OPT) \ +QPEL_FUNCS_DECL(OP, 1, 1, OPT) \ +QPEL_FUNCS_DECL(OP, 1, 2, OPT) \ +QPEL_FUNCS_DECL(OP, 1, 3, OPT) \ +QPEL_FUNCS_DECL(OP, 2, 1, OPT) \ +QPEL_FUNCS_DECL(OP, 2, 2, OPT) \ +QPEL_FUNCS_DECL(OP, 2, 3, OPT) \ +QPEL_FUNCS_DECL(OP, 3, 0, OPT) \ +QPEL_FUNCS_DECL(OP, 3, 1, OPT) \ +QPEL_FUNCS_DECL(OP, 3, 2, OPT) +/** @} */ + +#define LOOPSIZE 8 +#define HCOFF(x) (32 * (x - 1)) +#define VCOFF(x) (32 * (x - 1)) +QPEL_MC_DECL(put_, _ssse3) +QPEL_MC_DECL(avg_, _ssse3) + +#undef LOOPSIZE +#undef HCOFF +#undef VCOFF +#define LOOPSIZE 8 +#define HCOFF(x) (64 * (x - 1)) +#define VCOFF(x) (64 * (x - 1)) +QPEL_MC_DECL(put_, _sse2) +QPEL_MC_DECL(avg_, _sse2) + +#if ARCH_X86_32 +#undef LOOPSIZE +#undef HCOFF +#undef VCOFF +#define LOOPSIZE 4 +#define HCOFF(x) (64 * (x - 1)) +#define VCOFF(x) (64 * (x - 1)) + +QPEL_MC_DECL(put_, _mmx) + +#define ff_put_rv40_qpel_h_mmxext ff_put_rv40_qpel_h_mmx +#define ff_put_rv40_qpel_v_mmxext ff_put_rv40_qpel_v_mmx +QPEL_MC_DECL(avg_, _mmxext) + +#define ff_put_rv40_qpel_h_3dnow ff_put_rv40_qpel_h_mmx +#define ff_put_rv40_qpel_v_3dnow ff_put_rv40_qpel_v_mmx +QPEL_MC_DECL(avg_, _3dnow) +#endif + +/** @{ */ +/** Set one function */ +#define QPEL_FUNC_SET(OP, SIZE, PH, PV, OPT) \ + c-> OP ## pixels_tab[2 - SIZE / 8][4 * PV + PH] = OP ## rv40_qpel ##SIZE ## _mc ##PH ##PV ##OPT; + +/** Set functions put and avg for sizes 8 and 16 and a given qpel position */ +#define QPEL_FUNCS_SET(OP, PH, PV, OPT) \ + QPEL_FUNC_SET(OP, 8, PH, PV, OPT) \ + QPEL_FUNC_SET(OP, 16, PH, PV, OPT) + +/** Set all functions for all sizes and qpel positions */ +#define QPEL_MC_SET(OP, OPT) \ +QPEL_FUNCS_SET (OP, 0, 1, OPT) \ +QPEL_FUNCS_SET (OP, 0, 3, OPT) \ +QPEL_FUNCS_SET (OP, 1, 0, OPT) \ +QPEL_FUNCS_SET (OP, 1, 1, OPT) \ +QPEL_FUNCS_SET (OP, 1, 2, OPT) \ +QPEL_FUNCS_SET (OP, 1, 3, OPT) \ +QPEL_FUNCS_SET (OP, 2, 1, OPT) \ +QPEL_FUNCS_SET (OP, 2, 2, OPT) \ +QPEL_FUNCS_SET (OP, 2, 3, OPT) \ +QPEL_FUNCS_SET (OP, 3, 0, OPT) \ +QPEL_FUNCS_SET (OP, 3, 1, OPT) \ +QPEL_FUNCS_SET (OP, 3, 2, OPT) +/** @} */ + +#endif /* HAVE_YASM */ + +av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) +{ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + + if (EXTERNAL_MMX(mm_flags)) { + c->put_chroma_pixels_tab[0] = ff_put_rv40_chroma_mc8_mmx; + c->put_chroma_pixels_tab[1] = ff_put_rv40_chroma_mc4_mmx; +#if HAVE_MMX_INLINE + c->put_pixels_tab[0][15] = ff_put_rv40_qpel16_mc33_mmx; + c->put_pixels_tab[1][15] = ff_put_rv40_qpel8_mc33_mmx; + c->avg_pixels_tab[0][15] = ff_avg_rv40_qpel16_mc33_mmx; + c->avg_pixels_tab[1][15] = ff_avg_rv40_qpel8_mc33_mmx; +#endif /* HAVE_MMX_INLINE */ +#if ARCH_X86_32 + QPEL_MC_SET(put_, _mmx) +#endif + } + if (EXTERNAL_MMXEXT(mm_flags)) { + c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_mmxext; + c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_mmxext; + c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_mmxext; + c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_mmxext; + c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_mmxext; + c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_mmxext; +#if ARCH_X86_32 + QPEL_MC_SET(avg_, _mmxext) +#endif + } else if (EXTERNAL_AMD3DNOW(mm_flags)) { + c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_3dnow; + c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_3dnow; +#if ARCH_X86_32 + QPEL_MC_SET(avg_, _3dnow) +#endif + } + if (EXTERNAL_SSE2(mm_flags)) { + c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_sse2; + c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_sse2; + c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_sse2; + c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_sse2; + QPEL_MC_SET(put_, _sse2) + QPEL_MC_SET(avg_, _sse2) + } + if (EXTERNAL_SSSE3(mm_flags)) { + c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_ssse3; + c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_ssse3; + c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_ssse3; + c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_ssse3; + QPEL_MC_SET(put_, _ssse3) + QPEL_MC_SET(avg_, _ssse3) + } +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/sbrdsp.asm b/ffmpeg/libavcodec/x86/sbrdsp.asm new file mode 100644 index 0000000..1b7f3a8 --- /dev/null +++ b/ffmpeg/libavcodec/x86/sbrdsp.asm @@ -0,0 +1,222 @@ +;****************************************************************************** +;* AAC Spectral Band Replication decoding functions +;* Copyright (C) 2012 Christophe Gisquet +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA +; mask equivalent for multiply by -1.0 1.0 +ps_mask times 2 dd 1<<31, 0 +ps_neg times 4 dd 1<<31 + +SECTION_TEXT + +INIT_XMM sse +cglobal sbr_sum_square, 2, 3, 6 + mov r2, r1 + xorps m0, m0 + xorps m1, m1 + sar r2, 3 + jz .prepare +.loop: + movu m2, [r0 + 0] + movu m3, [r0 + 16] + movu m4, [r0 + 32] + movu m5, [r0 + 48] + mulps m2, m2 + mulps m3, m3 + mulps m4, m4 + mulps m5, m5 + addps m0, m2 + addps m1, m3 + addps m0, m4 + addps m1, m5 + add r0, 64 + dec r2 + jnz .loop +.prepare: + and r1, 7 + sar r1, 1 + jz .end +; len is a multiple of 2, thus there are at least 4 elements to process +.endloop: + movu m2, [r0] + add r0, 16 + mulps m2, m2 + dec r1 + addps m0, m2 + jnz .endloop +.end: + addps m0, m1 + movhlps m2, m0 + addps m0, m2 + movss m1, m0 + shufps m0, m0, 1 + addss m0, m1 +%if ARCH_X86_64 == 0 + movss r0m, m0 + fld dword r0m +%endif + RET + +%define STEP 40*4*2 +cglobal sbr_hf_g_filt, 5, 6, 5 + lea r1, [r1 + 8*r4] ; offset by ixh elements into X_high + mov r5, r3 + and r3, 0xFC + lea r2, [r2 + r3*4] + lea r0, [r0 + r3*8] + neg r3 + jz .loop1 +.loop4: + movlps m0, [r2 + 4*r3 + 0] + movlps m1, [r2 + 4*r3 + 8] + movlps m2, [r1 + 0*STEP] + movlps m3, [r1 + 2*STEP] + movhps m2, [r1 + 1*STEP] + movhps m3, [r1 + 3*STEP] + unpcklps m0, m0 + unpcklps m1, m1 + mulps m0, m2 + mulps m1, m3 + movu [r0 + 8*r3 + 0], m0 + movu [r0 + 8*r3 + 16], m1 + add r1, 4*STEP + add r3, 4 + jnz .loop4 + and r5, 3 ; number of single element loops + jz .end +.loop1: ; element 0 and 1 can be computed at the same time + movss m0, [r2] + movlps m2, [r1] + unpcklps m0, m0 + mulps m2, m0 + movlps [r0], m2 + add r0, 8 + add r2, 4 + add r1, STEP + dec r5 + jnz .loop1 +.end: + RET + +; static void sbr_hf_gen_c(float (*X_high)[2], const float (*X_low)[2], +; const float alpha0[2], const float alpha1[2], +; float bw, int start, int end) +; +cglobal sbr_hf_gen, 4,4,8, X_high, X_low, alpha0, alpha1, BW, S, E + ; load alpha factors +%define bw m0 +%if ARCH_X86_64 == 0 || WIN64 + movss bw, BWm +%endif + movlps m2, [alpha1q] + movlps m1, [alpha0q] + shufps bw, bw, 0 + mulps m2, bw ; (a1[0] a1[1])*bw + mulps m1, bw ; (a0[0] a0[1])*bw = (a2 a3) + mulps m2, bw ; (a1[0] a1[1])*bw*bw = (a0 a1) + mova m3, m1 + mova m4, m2 + + ; Set pointers +%if ARCH_X86_64 == 0 || WIN64 + ; start and end 6th and 7th args on stack + mov r2d, Sm + mov r3d, Em +%define start r2q +%define end r3q +%else +; BW does not actually occupy a register, so shift by 1 +%define start BWq +%define end Sq +%endif + sub start, end ; neg num of loops + lea X_highq, [X_highq + end*2*4] + lea X_lowq, [X_lowq + end*2*4 - 2*2*4] + shl start, 3 ; offset from num loops + + mova m0, [X_lowq + start] + shufps m3, m3, q1111 + shufps m4, m4, q1111 + xorps m3, [ps_mask] + shufps m1, m1, q0000 + shufps m2, m2, q0000 + xorps m4, [ps_mask] +.loop2: + movu m7, [X_lowq + start + 8] ; BbCc + mova m6, m0 + mova m5, m7 + shufps m0, m0, q2301 ; aAbB + shufps m7, m7, q2301 ; bBcC + mulps m0, m4 + mulps m7, m3 + mulps m6, m2 + mulps m5, m1 + addps m7, m0 + mova m0, [X_lowq + start +16] ; CcDd + addps m7, m0 + addps m6, m5 + addps m7, m6 + mova [X_highq + start], m7 + add start, 16 + jnz .loop2 + RET + +cglobal sbr_sum64x5, 1,2,4,z + lea r1q, [zq+ 256] +.loop: + mova m0, [zq+ 0] + mova m2, [zq+ 16] + mova m1, [zq+ 256] + mova m3, [zq+ 272] + addps m0, [zq+ 512] + addps m2, [zq+ 528] + addps m1, [zq+ 768] + addps m3, [zq+ 784] + addps m0, [zq+1024] + addps m2, [zq+1040] + addps m0, m1 + addps m2, m3 + mova [zq], m0 + mova [zq+16], m2 + add zq, 32 + cmp zq, r1q + jne .loop + REP_RET + +INIT_XMM sse +cglobal sbr_qmf_post_shuffle, 2,3,4,W,z + lea r2q, [zq + (64-4)*4] + mova m3, [ps_neg] +.loop: + mova m1, [zq] + xorps m0, m3, [r2q] + shufps m0, m0, m0, q0123 + unpcklps m2, m0, m1 + unpckhps m0, m0, m1 + mova [Wq + 0], m2 + mova [Wq + 16], m0 + add Wq, 32 + sub r2q, 16 + add zq, 16 + cmp zq, r2q + jl .loop + REP_RET diff --git a/ffmpeg/libavcodec/x86/sbrdsp_init.c b/ffmpeg/libavcodec/x86/sbrdsp_init.c new file mode 100644 index 0000000..27fade1 --- /dev/null +++ b/ffmpeg/libavcodec/x86/sbrdsp_init.c @@ -0,0 +1,48 @@ +/* + * AAC Spectral Band Replication decoding functions + * Copyright (c) 2012 Christophe Gisquet + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/sbrdsp.h" + +float ff_sbr_sum_square_sse(float (*x)[2], int n); +void ff_sbr_sum64x5_sse(float *z); +void ff_sbr_hf_g_filt_sse(float (*Y)[2], const float (*X_high)[40][2], + const float *g_filt, int m_max, intptr_t ixh); +void ff_sbr_hf_gen_sse(float (*X_high)[2], const float (*X_low)[2], + const float alpha0[2], const float alpha1[2], + float bw, int start, int end); +void ff_sbr_qmf_post_shuffle_sse(float W[32][2], const float *z); + +av_cold void ff_sbrdsp_init_x86(SBRDSPContext *s) +{ + int mm_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE(mm_flags)) { + s->sum_square = ff_sbr_sum_square_sse; + s->sum64x5 = ff_sbr_sum64x5_sse; + s->hf_g_filt = ff_sbr_hf_g_filt_sse; + s->hf_gen = ff_sbr_hf_gen_sse; + s->qmf_post_shuffle = ff_sbr_qmf_post_shuffle_sse; + } +} diff --git a/ffmpeg/libavcodec/x86/simple_idct.c b/ffmpeg/libavcodec/x86/simple_idct.c new file mode 100644 index 0000000..f27d2b9 --- /dev/null +++ b/ffmpeg/libavcodec/x86/simple_idct.c @@ -0,0 +1,1167 @@ +/* + * Simple IDCT MMX + * + * Copyright (c) 2001, 2002 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 "libavcodec/simple_idct.h" +#include "libavutil/mem.h" +#include "dsputil_mmx.h" + +#if HAVE_INLINE_ASM + +/* +23170.475006 +22725.260826 +21406.727617 +19265.545870 +16384.000000 +12872.826198 +8866.956905 +4520.335430 +*/ +#define C0 23170 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define C1 22725 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define C2 21407 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define C3 19266 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define C4 16383 //cos(i*M_PI/16)*sqrt(2)*(1<<14) - 0.5 +#define C5 12873 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define C6 8867 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 +#define C7 4520 //cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5 + +#define ROW_SHIFT 11 +#define COL_SHIFT 20 // 6 + +DECLARE_ASM_CONST(8, uint64_t, wm1010)= 0xFFFF0000FFFF0000ULL; +DECLARE_ASM_CONST(8, uint64_t, d40000)= 0x0000000000040000ULL; + +DECLARE_ALIGNED(8, static const int16_t, coeffs)[]= { + 1<<(ROW_SHIFT-1), 0, 1<<(ROW_SHIFT-1), 0, +// 1<<(COL_SHIFT-1), 0, 1<<(COL_SHIFT-1), 0, +// 0, 1<<(COL_SHIFT-1-16), 0, 1<<(COL_SHIFT-1-16), + 1<<(ROW_SHIFT-1), 1, 1<<(ROW_SHIFT-1), 0, + // the 1 = ((1<<(COL_SHIFT-1))/C4)< + * + * 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 "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/snow.h" +#include "libavcodec/snow_dwt.h" +#include "dsputil_mmx.h" + +#if HAVE_INLINE_ASM + +static void ff_snow_horizontal_compose97i_sse2(IDWTELEM *b, IDWTELEM *temp, int width){ + const int w2= (width+1)>>1; + const int w_l= (width>>1); + const int w_r= w2 - 1; + int i; + + { // Lift 0 + IDWTELEM * const ref = b + w2 - 1; + IDWTELEM b_0 = b[0]; //By allowing the first entry in b[0] to be calculated twice + // (the first time erroneously), we allow the SSE2 code to run an extra pass. + // The savings in code and time are well worth having to store this value and + // calculate b[0] correctly afterwards. + + i = 0; + __asm__ volatile( + "pcmpeqd %%xmm7, %%xmm7 \n\t" + "pcmpeqd %%xmm3, %%xmm3 \n\t" + "psllw $1, %%xmm3 \n\t" + "paddw %%xmm7, %%xmm3 \n\t" + "psllw $13, %%xmm3 \n\t" + ::); + for(; i>W_DS); + } + + { // Lift 1 + IDWTELEM * const dst = b+w2; + + i = 0; + for(; (((x86_reg)&dst[i]) & 0x1F) && i> W_BS); + } + + { // Lift 3 + IDWTELEM * const src = b+w2; + + i = 0; + for(; (((x86_reg)&temp[i]) & 0x1F) && i>W_AS); + } + for(; i>1]; + b[i] = b[i>>1]; + } + for (i-=62; i>=0; i-=64){ + __asm__ volatile( + "movdqa (%1), %%xmm0 \n\t" + "movdqa 16(%1), %%xmm2 \n\t" + "movdqa 32(%1), %%xmm4 \n\t" + "movdqa 48(%1), %%xmm6 \n\t" + "movdqa (%1), %%xmm1 \n\t" + "movdqa 16(%1), %%xmm3 \n\t" + "movdqa 32(%1), %%xmm5 \n\t" + "movdqa 48(%1), %%xmm7 \n\t" + "punpcklwd (%2), %%xmm0 \n\t" + "punpcklwd 16(%2), %%xmm2 \n\t" + "punpcklwd 32(%2), %%xmm4 \n\t" + "punpcklwd 48(%2), %%xmm6 \n\t" + "movdqa %%xmm0, (%0) \n\t" + "movdqa %%xmm2, 32(%0) \n\t" + "movdqa %%xmm4, 64(%0) \n\t" + "movdqa %%xmm6, 96(%0) \n\t" + "punpckhwd (%2), %%xmm1 \n\t" + "punpckhwd 16(%2), %%xmm3 \n\t" + "punpckhwd 32(%2), %%xmm5 \n\t" + "punpckhwd 48(%2), %%xmm7 \n\t" + "movdqa %%xmm1, 16(%0) \n\t" + "movdqa %%xmm3, 48(%0) \n\t" + "movdqa %%xmm5, 80(%0) \n\t" + "movdqa %%xmm7, 112(%0) \n\t" + :: "r"(&(b)[i]), "r"(&(b)[i>>1]), "r"(&(temp)[i>>1]) + : "memory" + ); + } + } +} + +static void ff_snow_horizontal_compose97i_mmx(IDWTELEM *b, IDWTELEM *temp, int width){ + const int w2= (width+1)>>1; + const int w_l= (width>>1); + const int w_r= w2 - 1; + int i; + + { // Lift 0 + IDWTELEM * const ref = b + w2 - 1; + + i = 1; + b[0] = b[0] - ((W_DM * 2 * ref[1]+W_DO)>>W_DS); + __asm__ volatile( + "pcmpeqw %%mm7, %%mm7 \n\t" + "pcmpeqw %%mm3, %%mm3 \n\t" + "psllw $1, %%mm3 \n\t" + "paddw %%mm7, %%mm3 \n\t" + "psllw $13, %%mm3 \n\t" + ::); + for(; i> W_BS); + __asm__ volatile( + "psllw $15, %%mm7 \n\t" + "pcmpeqw %%mm6, %%mm6 \n\t" + "psrlw $13, %%mm6 \n\t" + "paddw %%mm7, %%mm6 \n\t" + ::); + for(; i>1]; + b[i] = b[i>>1]; + } + for (i-=30; i>=0; i-=32){ + __asm__ volatile( + "movq (%1), %%mm0 \n\t" + "movq 8(%1), %%mm2 \n\t" + "movq 16(%1), %%mm4 \n\t" + "movq 24(%1), %%mm6 \n\t" + "movq (%1), %%mm1 \n\t" + "movq 8(%1), %%mm3 \n\t" + "movq 16(%1), %%mm5 \n\t" + "movq 24(%1), %%mm7 \n\t" + "punpcklwd (%2), %%mm0 \n\t" + "punpcklwd 8(%2), %%mm2 \n\t" + "punpcklwd 16(%2), %%mm4 \n\t" + "punpcklwd 24(%2), %%mm6 \n\t" + "movq %%mm0, (%0) \n\t" + "movq %%mm2, 16(%0) \n\t" + "movq %%mm4, 32(%0) \n\t" + "movq %%mm6, 48(%0) \n\t" + "punpckhwd (%2), %%mm1 \n\t" + "punpckhwd 8(%2), %%mm3 \n\t" + "punpckhwd 16(%2), %%mm5 \n\t" + "punpckhwd 24(%2), %%mm7 \n\t" + "movq %%mm1, 8(%0) \n\t" + "movq %%mm3, 24(%0) \n\t" + "movq %%mm5, 40(%0) \n\t" + "movq %%mm7, 56(%0) \n\t" + :: "r"(&b[i]), "r"(&b[i>>1]), "r"(&temp[i>>1]) + : "memory" + ); + } + } +} + +#if HAVE_7REGS +#define snow_vertical_compose_sse2_load_add(op,r,t0,t1,t2,t3)\ + ""op" ("r",%%"REG_d"), %%"t0" \n\t"\ + ""op" 16("r",%%"REG_d"), %%"t1" \n\t"\ + ""op" 32("r",%%"REG_d"), %%"t2" \n\t"\ + ""op" 48("r",%%"REG_d"), %%"t3" \n\t" + +#define snow_vertical_compose_sse2_load(r,t0,t1,t2,t3)\ + snow_vertical_compose_sse2_load_add("movdqa",r,t0,t1,t2,t3) + +#define snow_vertical_compose_sse2_add(r,t0,t1,t2,t3)\ + snow_vertical_compose_sse2_load_add("paddw",r,t0,t1,t2,t3) + +#define snow_vertical_compose_r2r_sub(s0,s1,s2,s3,t0,t1,t2,t3)\ + "psubw %%"s0", %%"t0" \n\t"\ + "psubw %%"s1", %%"t1" \n\t"\ + "psubw %%"s2", %%"t2" \n\t"\ + "psubw %%"s3", %%"t3" \n\t" + +#define snow_vertical_compose_sse2_store(w,s0,s1,s2,s3)\ + "movdqa %%"s0", ("w",%%"REG_d") \n\t"\ + "movdqa %%"s1", 16("w",%%"REG_d") \n\t"\ + "movdqa %%"s2", 32("w",%%"REG_d") \n\t"\ + "movdqa %%"s3", 48("w",%%"REG_d") \n\t" + +#define snow_vertical_compose_sra(n,t0,t1,t2,t3)\ + "psraw $"n", %%"t0" \n\t"\ + "psraw $"n", %%"t1" \n\t"\ + "psraw $"n", %%"t2" \n\t"\ + "psraw $"n", %%"t3" \n\t" + +#define snow_vertical_compose_r2r_add(s0,s1,s2,s3,t0,t1,t2,t3)\ + "paddw %%"s0", %%"t0" \n\t"\ + "paddw %%"s1", %%"t1" \n\t"\ + "paddw %%"s2", %%"t2" \n\t"\ + "paddw %%"s3", %%"t3" \n\t" + +#define snow_vertical_compose_r2r_pmulhw(s0,s1,s2,s3,t0,t1,t2,t3)\ + "pmulhw %%"s0", %%"t0" \n\t"\ + "pmulhw %%"s1", %%"t1" \n\t"\ + "pmulhw %%"s2", %%"t2" \n\t"\ + "pmulhw %%"s3", %%"t3" \n\t" + +#define snow_vertical_compose_sse2_move(s0,s1,s2,s3,t0,t1,t2,t3)\ + "movdqa %%"s0", %%"t0" \n\t"\ + "movdqa %%"s1", %%"t1" \n\t"\ + "movdqa %%"s2", %%"t2" \n\t"\ + "movdqa %%"s3", %%"t3" \n\t" + +static void ff_snow_vertical_compose97i_sse2(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){ + x86_reg i = width; + + while(i & 0x1F) + { + i--; + b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS; + b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS; + b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS; + b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS; + } + i+=i; + + __asm__ volatile ( + "jmp 2f \n\t" + "1: \n\t" + snow_vertical_compose_sse2_load("%4","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_add("%6","xmm0","xmm2","xmm4","xmm6") + + + "pcmpeqw %%xmm0, %%xmm0 \n\t" + "pcmpeqw %%xmm2, %%xmm2 \n\t" + "paddw %%xmm2, %%xmm2 \n\t" + "paddw %%xmm0, %%xmm2 \n\t" + "psllw $13, %%xmm2 \n\t" + snow_vertical_compose_r2r_add("xmm0","xmm0","xmm0","xmm0","xmm1","xmm3","xmm5","xmm7") + snow_vertical_compose_r2r_pmulhw("xmm2","xmm2","xmm2","xmm2","xmm1","xmm3","xmm5","xmm7") + snow_vertical_compose_sse2_add("%5","xmm1","xmm3","xmm5","xmm7") + snow_vertical_compose_sse2_store("%5","xmm1","xmm3","xmm5","xmm7") + snow_vertical_compose_sse2_load("%4","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_add("%3","xmm1","xmm3","xmm5","xmm7") + snow_vertical_compose_r2r_sub("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_store("%4","xmm0","xmm2","xmm4","xmm6") + + "pcmpeqw %%xmm7, %%xmm7 \n\t" + "pcmpeqw %%xmm5, %%xmm5 \n\t" + "psllw $15, %%xmm7 \n\t" + "psrlw $13, %%xmm5 \n\t" + "paddw %%xmm7, %%xmm5 \n\t" + snow_vertical_compose_r2r_add("xmm5","xmm5","xmm5","xmm5","xmm0","xmm2","xmm4","xmm6") + "movq (%2,%%"REG_d"), %%xmm1 \n\t" + "movq 8(%2,%%"REG_d"), %%xmm3 \n\t" + "paddw %%xmm7, %%xmm1 \n\t" + "paddw %%xmm7, %%xmm3 \n\t" + "pavgw %%xmm1, %%xmm0 \n\t" + "pavgw %%xmm3, %%xmm2 \n\t" + "movq 16(%2,%%"REG_d"), %%xmm1 \n\t" + "movq 24(%2,%%"REG_d"), %%xmm3 \n\t" + "paddw %%xmm7, %%xmm1 \n\t" + "paddw %%xmm7, %%xmm3 \n\t" + "pavgw %%xmm1, %%xmm4 \n\t" + "pavgw %%xmm3, %%xmm6 \n\t" + snow_vertical_compose_r2r_sub("xmm7","xmm7","xmm7","xmm7","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sra("1","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_add("%3","xmm0","xmm2","xmm4","xmm6") + + snow_vertical_compose_sra("2","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_add("%3","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_store("%3","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_add("%1","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_move("xmm0","xmm2","xmm4","xmm6","xmm1","xmm3","xmm5","xmm7") + snow_vertical_compose_sra("1","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_r2r_add("xmm1","xmm3","xmm5","xmm7","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_add("%2","xmm0","xmm2","xmm4","xmm6") + snow_vertical_compose_sse2_store("%2","xmm0","xmm2","xmm4","xmm6") + + "2: \n\t" + "sub $64, %%"REG_d" \n\t" + "jge 1b \n\t" + :"+d"(i) + :"r"(b0),"r"(b1),"r"(b2),"r"(b3),"r"(b4),"r"(b5)); +} + +#define snow_vertical_compose_mmx_load_add(op,r,t0,t1,t2,t3)\ + ""op" ("r",%%"REG_d"), %%"t0" \n\t"\ + ""op" 8("r",%%"REG_d"), %%"t1" \n\t"\ + ""op" 16("r",%%"REG_d"), %%"t2" \n\t"\ + ""op" 24("r",%%"REG_d"), %%"t3" \n\t" + +#define snow_vertical_compose_mmx_load(r,t0,t1,t2,t3)\ + snow_vertical_compose_mmx_load_add("movq",r,t0,t1,t2,t3) + +#define snow_vertical_compose_mmx_add(r,t0,t1,t2,t3)\ + snow_vertical_compose_mmx_load_add("paddw",r,t0,t1,t2,t3) + +#define snow_vertical_compose_mmx_store(w,s0,s1,s2,s3)\ + "movq %%"s0", ("w",%%"REG_d") \n\t"\ + "movq %%"s1", 8("w",%%"REG_d") \n\t"\ + "movq %%"s2", 16("w",%%"REG_d") \n\t"\ + "movq %%"s3", 24("w",%%"REG_d") \n\t" + +#define snow_vertical_compose_mmx_move(s0,s1,s2,s3,t0,t1,t2,t3)\ + "movq %%"s0", %%"t0" \n\t"\ + "movq %%"s1", %%"t1" \n\t"\ + "movq %%"s2", %%"t2" \n\t"\ + "movq %%"s3", %%"t3" \n\t" + + +static void ff_snow_vertical_compose97i_mmx(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5, int width){ + x86_reg i = width; + while(i & 15) + { + i--; + b4[i] -= (W_DM*(b3[i] + b5[i])+W_DO)>>W_DS; + b3[i] -= (W_CM*(b2[i] + b4[i])+W_CO)>>W_CS; + b2[i] += (W_BM*(b1[i] + b3[i])+4*b2[i]+W_BO)>>W_BS; + b1[i] += (W_AM*(b0[i] + b2[i])+W_AO)>>W_AS; + } + i+=i; + __asm__ volatile( + "jmp 2f \n\t" + "1: \n\t" + + snow_vertical_compose_mmx_load("%4","mm1","mm3","mm5","mm7") + snow_vertical_compose_mmx_add("%6","mm1","mm3","mm5","mm7") + "pcmpeqw %%mm0, %%mm0 \n\t" + "pcmpeqw %%mm2, %%mm2 \n\t" + "paddw %%mm2, %%mm2 \n\t" + "paddw %%mm0, %%mm2 \n\t" + "psllw $13, %%mm2 \n\t" + snow_vertical_compose_r2r_add("mm0","mm0","mm0","mm0","mm1","mm3","mm5","mm7") + snow_vertical_compose_r2r_pmulhw("mm2","mm2","mm2","mm2","mm1","mm3","mm5","mm7") + snow_vertical_compose_mmx_add("%5","mm1","mm3","mm5","mm7") + snow_vertical_compose_mmx_store("%5","mm1","mm3","mm5","mm7") + snow_vertical_compose_mmx_load("%4","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_add("%3","mm1","mm3","mm5","mm7") + snow_vertical_compose_r2r_sub("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_store("%4","mm0","mm2","mm4","mm6") + "pcmpeqw %%mm7, %%mm7 \n\t" + "pcmpeqw %%mm5, %%mm5 \n\t" + "psllw $15, %%mm7 \n\t" + "psrlw $13, %%mm5 \n\t" + "paddw %%mm7, %%mm5 \n\t" + snow_vertical_compose_r2r_add("mm5","mm5","mm5","mm5","mm0","mm2","mm4","mm6") + "movq (%2,%%"REG_d"), %%mm1 \n\t" + "movq 8(%2,%%"REG_d"), %%mm3 \n\t" + "paddw %%mm7, %%mm1 \n\t" + "paddw %%mm7, %%mm3 \n\t" + "pavgw %%mm1, %%mm0 \n\t" + "pavgw %%mm3, %%mm2 \n\t" + "movq 16(%2,%%"REG_d"), %%mm1 \n\t" + "movq 24(%2,%%"REG_d"), %%mm3 \n\t" + "paddw %%mm7, %%mm1 \n\t" + "paddw %%mm7, %%mm3 \n\t" + "pavgw %%mm1, %%mm4 \n\t" + "pavgw %%mm3, %%mm6 \n\t" + snow_vertical_compose_r2r_sub("mm7","mm7","mm7","mm7","mm0","mm2","mm4","mm6") + snow_vertical_compose_sra("1","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_add("%3","mm0","mm2","mm4","mm6") + + snow_vertical_compose_sra("2","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_add("%3","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_store("%3","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_add("%1","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_move("mm0","mm2","mm4","mm6","mm1","mm3","mm5","mm7") + snow_vertical_compose_sra("1","mm0","mm2","mm4","mm6") + snow_vertical_compose_r2r_add("mm1","mm3","mm5","mm7","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_add("%2","mm0","mm2","mm4","mm6") + snow_vertical_compose_mmx_store("%2","mm0","mm2","mm4","mm6") + + "2: \n\t" + "sub $32, %%"REG_d" \n\t" + "jge 1b \n\t" + :"+d"(i) + :"r"(b0),"r"(b1),"r"(b2),"r"(b3),"r"(b4),"r"(b5)); +} +#endif //HAVE_7REGS + +#define snow_inner_add_yblock_sse2_header \ + IDWTELEM * * dst_array = sb->line + src_y;\ + x86_reg tmp;\ + __asm__ volatile(\ + "mov %7, %%"REG_c" \n\t"\ + "mov %6, %2 \n\t"\ + "mov %4, %%"REG_S" \n\t"\ + "pxor %%xmm7, %%xmm7 \n\t" /* 0 */\ + "pcmpeqd %%xmm3, %%xmm3 \n\t"\ + "psllw $15, %%xmm3 \n\t"\ + "psrlw $12, %%xmm3 \n\t" /* FRAC_BITS >> 1 */\ + "1: \n\t"\ + "mov %1, %%"REG_D" \n\t"\ + "mov (%%"REG_D"), %%"REG_D" \n\t"\ + "add %3, %%"REG_D" \n\t" + +#define snow_inner_add_yblock_sse2_start_8(out_reg1, out_reg2, ptr_offset, s_offset)\ + "mov "PTR_SIZE"*"ptr_offset"(%%"REG_a"), %%"REG_d"; \n\t"\ + "movq (%%"REG_d"), %%"out_reg1" \n\t"\ + "movq (%%"REG_d", %%"REG_c"), %%"out_reg2" \n\t"\ + "punpcklbw %%xmm7, %%"out_reg1" \n\t"\ + "punpcklbw %%xmm7, %%"out_reg2" \n\t"\ + "movq "s_offset"(%%"REG_S"), %%xmm0 \n\t"\ + "movq "s_offset"+16(%%"REG_S"), %%xmm4 \n\t"\ + "punpcklbw %%xmm7, %%xmm0 \n\t"\ + "punpcklbw %%xmm7, %%xmm4 \n\t"\ + "pmullw %%xmm0, %%"out_reg1" \n\t"\ + "pmullw %%xmm4, %%"out_reg2" \n\t" + +#define snow_inner_add_yblock_sse2_start_16(out_reg1, out_reg2, ptr_offset, s_offset)\ + "mov "PTR_SIZE"*"ptr_offset"(%%"REG_a"), %%"REG_d"; \n\t"\ + "movq (%%"REG_d"), %%"out_reg1" \n\t"\ + "movq 8(%%"REG_d"), %%"out_reg2" \n\t"\ + "punpcklbw %%xmm7, %%"out_reg1" \n\t"\ + "punpcklbw %%xmm7, %%"out_reg2" \n\t"\ + "movq "s_offset"(%%"REG_S"), %%xmm0 \n\t"\ + "movq "s_offset"+8(%%"REG_S"), %%xmm4 \n\t"\ + "punpcklbw %%xmm7, %%xmm0 \n\t"\ + "punpcklbw %%xmm7, %%xmm4 \n\t"\ + "pmullw %%xmm0, %%"out_reg1" \n\t"\ + "pmullw %%xmm4, %%"out_reg2" \n\t" + +#define snow_inner_add_yblock_sse2_accum_8(ptr_offset, s_offset) \ + snow_inner_add_yblock_sse2_start_8("xmm2", "xmm6", ptr_offset, s_offset)\ + "paddusw %%xmm2, %%xmm1 \n\t"\ + "paddusw %%xmm6, %%xmm5 \n\t" + +#define snow_inner_add_yblock_sse2_accum_16(ptr_offset, s_offset) \ + snow_inner_add_yblock_sse2_start_16("xmm2", "xmm6", ptr_offset, s_offset)\ + "paddusw %%xmm2, %%xmm1 \n\t"\ + "paddusw %%xmm6, %%xmm5 \n\t" + +#define snow_inner_add_yblock_sse2_end_common1\ + "add $32, %%"REG_S" \n\t"\ + "add %%"REG_c", %0 \n\t"\ + "add %%"REG_c", "PTR_SIZE"*3(%%"REG_a");\n\t"\ + "add %%"REG_c", "PTR_SIZE"*2(%%"REG_a");\n\t"\ + "add %%"REG_c", "PTR_SIZE"*1(%%"REG_a");\n\t"\ + "add %%"REG_c", (%%"REG_a") \n\t" + +#define snow_inner_add_yblock_sse2_end_common2\ + "jnz 1b \n\t"\ + :"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\ + :\ + "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ + "%"REG_c"","%"REG_S"","%"REG_D"","%"REG_d""); + +#define snow_inner_add_yblock_sse2_end_8\ + "sal $1, %%"REG_c" \n\t"\ + "add"OPSIZE" $"PTR_SIZE"*2, %1 \n\t"\ + snow_inner_add_yblock_sse2_end_common1\ + "sar $1, %%"REG_c" \n\t"\ + "sub $2, %2 \n\t"\ + snow_inner_add_yblock_sse2_end_common2 + +#define snow_inner_add_yblock_sse2_end_16\ + "add"OPSIZE" $"PTR_SIZE"*1, %1 \n\t"\ + snow_inner_add_yblock_sse2_end_common1\ + "dec %2 \n\t"\ + snow_inner_add_yblock_sse2_end_common2 + +static void inner_add_yblock_bw_8_obmc_16_bh_even_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, + int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ +snow_inner_add_yblock_sse2_header +snow_inner_add_yblock_sse2_start_8("xmm1", "xmm5", "3", "0") +snow_inner_add_yblock_sse2_accum_8("2", "8") +snow_inner_add_yblock_sse2_accum_8("1", "128") +snow_inner_add_yblock_sse2_accum_8("0", "136") + + "mov %0, %%"REG_d" \n\t" + "movdqa (%%"REG_D"), %%xmm0 \n\t" + "movdqa %%xmm1, %%xmm2 \n\t" + + "punpckhwd %%xmm7, %%xmm1 \n\t" + "punpcklwd %%xmm7, %%xmm2 \n\t" + "paddd %%xmm2, %%xmm0 \n\t" + "movdqa 16(%%"REG_D"), %%xmm2 \n\t" + "paddd %%xmm1, %%xmm2 \n\t" + "paddd %%xmm3, %%xmm0 \n\t" + "paddd %%xmm3, %%xmm2 \n\t" + + "mov %1, %%"REG_D" \n\t" + "mov "PTR_SIZE"(%%"REG_D"), %%"REG_D";\n\t" + "add %3, %%"REG_D" \n\t" + + "movdqa (%%"REG_D"), %%xmm4 \n\t" + "movdqa %%xmm5, %%xmm6 \n\t" + "punpckhwd %%xmm7, %%xmm5 \n\t" + "punpcklwd %%xmm7, %%xmm6 \n\t" + "paddd %%xmm6, %%xmm4 \n\t" + "movdqa 16(%%"REG_D"), %%xmm6 \n\t" + "paddd %%xmm5, %%xmm6 \n\t" + "paddd %%xmm3, %%xmm4 \n\t" + "paddd %%xmm3, %%xmm6 \n\t" + + "psrad $8, %%xmm0 \n\t" /* FRAC_BITS. */ + "psrad $8, %%xmm2 \n\t" /* FRAC_BITS. */ + "packssdw %%xmm2, %%xmm0 \n\t" + "packuswb %%xmm7, %%xmm0 \n\t" + "movq %%xmm0, (%%"REG_d") \n\t" + + "psrad $8, %%xmm4 \n\t" /* FRAC_BITS. */ + "psrad $8, %%xmm6 \n\t" /* FRAC_BITS. */ + "packssdw %%xmm6, %%xmm4 \n\t" + "packuswb %%xmm7, %%xmm4 \n\t" + "movq %%xmm4, (%%"REG_d",%%"REG_c");\n\t" +snow_inner_add_yblock_sse2_end_8 +} + +static void inner_add_yblock_bw_16_obmc_32_sse2(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, + int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ +snow_inner_add_yblock_sse2_header +snow_inner_add_yblock_sse2_start_16("xmm1", "xmm5", "3", "0") +snow_inner_add_yblock_sse2_accum_16("2", "16") +snow_inner_add_yblock_sse2_accum_16("1", "512") +snow_inner_add_yblock_sse2_accum_16("0", "528") + + "mov %0, %%"REG_d" \n\t" + "psrlw $4, %%xmm1 \n\t" + "psrlw $4, %%xmm5 \n\t" + "paddw (%%"REG_D"), %%xmm1 \n\t" + "paddw 16(%%"REG_D"), %%xmm5 \n\t" + "paddw %%xmm3, %%xmm1 \n\t" + "paddw %%xmm3, %%xmm5 \n\t" + "psraw $4, %%xmm1 \n\t" /* FRAC_BITS. */ + "psraw $4, %%xmm5 \n\t" /* FRAC_BITS. */ + "packuswb %%xmm5, %%xmm1 \n\t" + + "movdqu %%xmm1, (%%"REG_d") \n\t" + +snow_inner_add_yblock_sse2_end_16 +} + +#define snow_inner_add_yblock_mmx_header \ + IDWTELEM * * dst_array = sb->line + src_y;\ + x86_reg tmp;\ + __asm__ volatile(\ + "mov %7, %%"REG_c" \n\t"\ + "mov %6, %2 \n\t"\ + "mov %4, %%"REG_S" \n\t"\ + "pxor %%mm7, %%mm7 \n\t" /* 0 */\ + "pcmpeqd %%mm3, %%mm3 \n\t"\ + "psllw $15, %%mm3 \n\t"\ + "psrlw $12, %%mm3 \n\t" /* FRAC_BITS >> 1 */\ + "1: \n\t"\ + "mov %1, %%"REG_D" \n\t"\ + "mov (%%"REG_D"), %%"REG_D" \n\t"\ + "add %3, %%"REG_D" \n\t" + +#define snow_inner_add_yblock_mmx_start(out_reg1, out_reg2, ptr_offset, s_offset, d_offset)\ + "mov "PTR_SIZE"*"ptr_offset"(%%"REG_a"), %%"REG_d"; \n\t"\ + "movd "d_offset"(%%"REG_d"), %%"out_reg1" \n\t"\ + "movd "d_offset"+4(%%"REG_d"), %%"out_reg2" \n\t"\ + "punpcklbw %%mm7, %%"out_reg1" \n\t"\ + "punpcklbw %%mm7, %%"out_reg2" \n\t"\ + "movd "s_offset"(%%"REG_S"), %%mm0 \n\t"\ + "movd "s_offset"+4(%%"REG_S"), %%mm4 \n\t"\ + "punpcklbw %%mm7, %%mm0 \n\t"\ + "punpcklbw %%mm7, %%mm4 \n\t"\ + "pmullw %%mm0, %%"out_reg1" \n\t"\ + "pmullw %%mm4, %%"out_reg2" \n\t" + +#define snow_inner_add_yblock_mmx_accum(ptr_offset, s_offset, d_offset) \ + snow_inner_add_yblock_mmx_start("mm2", "mm6", ptr_offset, s_offset, d_offset)\ + "paddusw %%mm2, %%mm1 \n\t"\ + "paddusw %%mm6, %%mm5 \n\t" + +#define snow_inner_add_yblock_mmx_mix(read_offset, write_offset)\ + "mov %0, %%"REG_d" \n\t"\ + "psrlw $4, %%mm1 \n\t"\ + "psrlw $4, %%mm5 \n\t"\ + "paddw "read_offset"(%%"REG_D"), %%mm1 \n\t"\ + "paddw "read_offset"+8(%%"REG_D"), %%mm5 \n\t"\ + "paddw %%mm3, %%mm1 \n\t"\ + "paddw %%mm3, %%mm5 \n\t"\ + "psraw $4, %%mm1 \n\t"\ + "psraw $4, %%mm5 \n\t"\ + "packuswb %%mm5, %%mm1 \n\t"\ + "movq %%mm1, "write_offset"(%%"REG_d") \n\t" + +#define snow_inner_add_yblock_mmx_end(s_step)\ + "add $"s_step", %%"REG_S" \n\t"\ + "add %%"REG_c", "PTR_SIZE"*3(%%"REG_a");\n\t"\ + "add %%"REG_c", "PTR_SIZE"*2(%%"REG_a");\n\t"\ + "add %%"REG_c", "PTR_SIZE"*1(%%"REG_a");\n\t"\ + "add %%"REG_c", (%%"REG_a") \n\t"\ + "add"OPSIZE " $"PTR_SIZE"*1, %1 \n\t"\ + "add %%"REG_c", %0 \n\t"\ + "dec %2 \n\t"\ + "jnz 1b \n\t"\ + :"+m"(dst8),"+m"(dst_array),"=&r"(tmp)\ + :\ + "rm"((x86_reg)(src_x<<1)),"m"(obmc),"a"(block),"m"(b_h),"m"(src_stride):\ + "%"REG_c"","%"REG_S"","%"REG_D"","%"REG_d""); + +static void inner_add_yblock_bw_8_obmc_16_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, + int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ +snow_inner_add_yblock_mmx_header +snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0") +snow_inner_add_yblock_mmx_accum("2", "8", "0") +snow_inner_add_yblock_mmx_accum("1", "128", "0") +snow_inner_add_yblock_mmx_accum("0", "136", "0") +snow_inner_add_yblock_mmx_mix("0", "0") +snow_inner_add_yblock_mmx_end("16") +} + +static void inner_add_yblock_bw_16_obmc_32_mmx(const uint8_t *obmc, const x86_reg obmc_stride, uint8_t * * block, int b_w, x86_reg b_h, + int src_x, int src_y, x86_reg src_stride, slice_buffer * sb, int add, uint8_t * dst8){ +snow_inner_add_yblock_mmx_header +snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "0", "0") +snow_inner_add_yblock_mmx_accum("2", "16", "0") +snow_inner_add_yblock_mmx_accum("1", "512", "0") +snow_inner_add_yblock_mmx_accum("0", "528", "0") +snow_inner_add_yblock_mmx_mix("0", "0") + +snow_inner_add_yblock_mmx_start("mm1", "mm5", "3", "8", "8") +snow_inner_add_yblock_mmx_accum("2", "24", "8") +snow_inner_add_yblock_mmx_accum("1", "520", "8") +snow_inner_add_yblock_mmx_accum("0", "536", "8") +snow_inner_add_yblock_mmx_mix("16", "8") +snow_inner_add_yblock_mmx_end("32") +} + +static void ff_snow_inner_add_yblock_sse2(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, + int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + + if (b_w == 16) + inner_add_yblock_bw_16_obmc_32_sse2(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + else if (b_w == 8 && obmc_stride == 16) { + if (!(b_h & 1)) + inner_add_yblock_bw_8_obmc_16_bh_even_sse2(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + else + inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + } else + ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); +} + +static void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, + int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){ + if (b_w == 16) + inner_add_yblock_bw_16_obmc_32_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + else if (b_w == 8 && obmc_stride == 16) + inner_add_yblock_bw_8_obmc_16_mmx(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); + else + ff_snow_inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8); +} + +#endif /* HAVE_INLINE_ASM */ + +void ff_dwt_init_x86(SnowDWTContext *c) +{ +#if HAVE_INLINE_ASM + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_MMX) { + if(mm_flags & AV_CPU_FLAG_SSE2 & 0){ + c->horizontal_compose97i = ff_snow_horizontal_compose97i_sse2; +#if HAVE_7REGS + c->vertical_compose97i = ff_snow_vertical_compose97i_sse2; +#endif + c->inner_add_yblock = ff_snow_inner_add_yblock_sse2; + } + else{ + if (mm_flags & AV_CPU_FLAG_MMXEXT) { + c->horizontal_compose97i = ff_snow_horizontal_compose97i_mmx; +#if HAVE_7REGS + c->vertical_compose97i = ff_snow_vertical_compose97i_mmx; +#endif + } + c->inner_add_yblock = ff_snow_inner_add_yblock_mmx; + } + } +#endif /* HAVE_INLINE_ASM */ +} diff --git a/ffmpeg/libavcodec/x86/v210-init.c b/ffmpeg/libavcodec/x86/v210-init.c new file mode 100644 index 0000000..02c5eaa --- /dev/null +++ b/ffmpeg/libavcodec/x86/v210-init.c @@ -0,0 +1,48 @@ +/* + * 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 "libavutil/cpu.h" +#include "libavcodec/v210dec.h" + +extern void ff_v210_planar_unpack_unaligned_ssse3(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); +extern void ff_v210_planar_unpack_unaligned_avx(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); + +extern void ff_v210_planar_unpack_aligned_ssse3(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); +extern void ff_v210_planar_unpack_aligned_avx(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); + +av_cold void v210_x86_init(V210DecContext *s) +{ + int cpu_flags = av_get_cpu_flags(); + +#if HAVE_YASM + if (s->aligned_input) { + if (cpu_flags & AV_CPU_FLAG_SSSE3) + s->unpack_frame = ff_v210_planar_unpack_aligned_ssse3; + + if (HAVE_AVX_EXTERNAL && cpu_flags & AV_CPU_FLAG_AVX) + s->unpack_frame = ff_v210_planar_unpack_aligned_avx; + } + else { + if (cpu_flags & AV_CPU_FLAG_SSSE3) + s->unpack_frame = ff_v210_planar_unpack_unaligned_ssse3; + + if (HAVE_AVX_EXTERNAL && cpu_flags & AV_CPU_FLAG_AVX) + s->unpack_frame = ff_v210_planar_unpack_unaligned_avx; + } +#endif +} diff --git a/ffmpeg/libavcodec/x86/v210.asm b/ffmpeg/libavcodec/x86/v210.asm new file mode 100644 index 0000000..5473126 --- /dev/null +++ b/ffmpeg/libavcodec/x86/v210.asm @@ -0,0 +1,88 @@ +;****************************************************************************** +;* V210 SIMD unpack +;* Copyright (c) 2011 Loren Merritt +;* Copyright (c) 2011 Kieran Kunhya +;* +;* This file is part of Libav. +;* +;* Libav 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, +;* 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 +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA + +v210_mask: times 4 dd 0x3ff +v210_mult: dw 64,4,64,4,64,4,64,4 +v210_luma_shuf: db 8,9,0,1,2,3,12,13,4,5,6,7,-1,-1,-1,-1 +v210_chroma_shuf: db 0,1,8,9,6,7,-1,-1,2,3,4,5,12,13,-1,-1 + +SECTION .text + +%macro v210_planar_unpack 2 + +; v210_planar_unpack(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width) +cglobal v210_planar_unpack_%1_%2, 5, 5, 7 + movsxdifnidn r4, r4d + lea r1, [r1+2*r4] + add r2, r4 + add r3, r4 + neg r4 + + mova m3, [v210_mult] + mova m4, [v210_mask] + mova m5, [v210_luma_shuf] + mova m6, [v210_chroma_shuf] +.loop +%ifidn %1, unaligned + movu m0, [r0] +%else + mova m0, [r0] +%endif + + pmullw m1, m0, m3 + psrld m0, 10 + psrlw m1, 6 ; u0 v0 y1 y2 v1 u2 y4 y5 + pand m0, m4 ; y0 __ u1 __ y3 __ v2 __ + + shufps m2, m1, m0, 0x8d ; y1 y2 y4 y5 y0 __ y3 __ + pshufb m2, m5 ; y0 y1 y2 y3 y4 y5 __ __ + movu [r1+2*r4], m2 + + shufps m1, m0, 0xd8 ; u0 v0 v1 u2 u1 __ v2 __ + pshufb m1, m6 ; u0 u1 u2 __ v0 v1 v2 __ + movq [r2+r4], m1 + movhps [r3+r4], m1 + + add r0, mmsize + add r4, 6 + jl .loop + + REP_RET +%endmacro + +INIT_XMM +v210_planar_unpack unaligned, ssse3 +%if HAVE_AVX_EXTERNAL +INIT_AVX +v210_planar_unpack unaligned, avx +%endif + +INIT_XMM +v210_planar_unpack aligned, ssse3 +%if HAVE_AVX_EXTERNAL +INIT_AVX +v210_planar_unpack aligned, avx +%endif diff --git a/ffmpeg/libavcodec/x86/vc1dsp.asm b/ffmpeg/libavcodec/x86/vc1dsp.asm new file mode 100644 index 0000000..546688c --- /dev/null +++ b/ffmpeg/libavcodec/x86/vc1dsp.asm @@ -0,0 +1,317 @@ +;****************************************************************************** +;* VC1 deblocking optimizations +;* Copyright (c) 2009 David Conrad +;* +;* 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 "libavutil/x86/x86util.asm" + +cextern pw_4 +cextern pw_5 + +section .text + +; dst_low, dst_high (src), zero +; zero-extends one vector from 8 to 16 bits +%macro UNPACK_8TO16 4 + mova m%2, m%3 + punpckh%1 m%3, m%4 + punpckl%1 m%2, m%4 +%endmacro + +%macro STORE_4_WORDS 6 +%if cpuflag(sse4) + pextrw %1, %5, %6+0 + pextrw %2, %5, %6+1 + pextrw %3, %5, %6+2 + pextrw %4, %5, %6+3 +%else + movd %6d, %5 +%if mmsize==16 + psrldq %5, 4 +%else + psrlq %5, 32 +%endif + mov %1, %6w + shr %6, 16 + mov %2, %6w + movd %6d, %5 + mov %3, %6w + shr %6, 16 + mov %4, %6w +%endif +%endmacro + +; in: p1 p0 q0 q1, clobbers p0 +; out: p1 = (2*(p1 - q1) - 5*(p0 - q0) + 4) >> 3 +%macro VC1_LOOP_FILTER_A0 4 + psubw %1, %4 + psubw %2, %3 + paddw %1, %1 + pmullw %2, [pw_5] + psubw %1, %2 + paddw %1, [pw_4] + psraw %1, 3 +%endmacro + +; in: p0 q0 a0 a1 a2 +; m0 m1 m7 m6 m5 +; %1: size +; out: m0=p0' m1=q0' +%macro VC1_FILTER 1 + PABSW m4, m7 + PABSW m3, m6 + PABSW m2, m5 + mova m6, m4 + pminsw m3, m2 + pcmpgtw m6, m3 ; if (a2 < a0 || a1 < a0) + psubw m3, m4 + pmullw m3, [pw_5] ; 5*(a3 - a0) + PABSW m2, m3 + psraw m2, 3 ; abs(d/8) + pxor m7, m3 ; d_sign ^= a0_sign + + pxor m5, m5 + movd m3, r2d +%if %1 > 4 + punpcklbw m3, m3 +%endif + punpcklbw m3, m5 + pcmpgtw m3, m4 ; if (a0 < pq) + pand m6, m3 + + mova m3, m0 + psubw m3, m1 + PABSW m4, m3 + psraw m4, 1 + pxor m3, m7 ; d_sign ^ clip_sign + psraw m3, 15 + pminsw m2, m4 ; min(d, clip) + pcmpgtw m4, m5 + pand m6, m4 ; filt3 (C return value) + +; each set of 4 pixels is not filtered if the 3rd is not +%if mmsize==16 + pshuflw m4, m6, 0xaa +%if %1 > 4 + pshufhw m4, m4, 0xaa +%endif +%else + pshufw m4, m6, 0xaa +%endif + pandn m3, m4 + pand m2, m6 + pand m3, m2 ; d final + + psraw m7, 15 + pxor m3, m7 + psubw m3, m7 + psubw m0, m3 + paddw m1, m3 + packuswb m0, m0 + packuswb m1, m1 +%endmacro + +; 1st param: size of filter +; 2nd param: mov suffix equivalent to the filter size +%macro VC1_V_LOOP_FILTER 2 + pxor m5, m5 + mov%2 m6, [r4] + mov%2 m4, [r4+r1] + mov%2 m7, [r4+2*r1] + mov%2 m0, [r4+r3] + punpcklbw m6, m5 + punpcklbw m4, m5 + punpcklbw m7, m5 + punpcklbw m0, m5 + + VC1_LOOP_FILTER_A0 m6, m4, m7, m0 + mov%2 m1, [r0] + mov%2 m2, [r0+r1] + punpcklbw m1, m5 + punpcklbw m2, m5 + mova m4, m0 + VC1_LOOP_FILTER_A0 m7, m4, m1, m2 + mov%2 m3, [r0+2*r1] + mov%2 m4, [r0+r3] + punpcklbw m3, m5 + punpcklbw m4, m5 + mova m5, m1 + VC1_LOOP_FILTER_A0 m5, m2, m3, m4 + + VC1_FILTER %1 + mov%2 [r4+r3], m0 + mov%2 [r0], m1 +%endmacro + +; 1st param: size of filter +; NOTE: UNPACK_8TO16 this number of 8 bit numbers are in half a register +; 2nd (optional) param: temp register to use for storing words +%macro VC1_H_LOOP_FILTER 1-2 +%if %1 == 4 + movq m0, [r0 -4] + movq m1, [r0+ r1-4] + movq m2, [r0+2*r1-4] + movq m3, [r0+ r3-4] + TRANSPOSE4x4B 0, 1, 2, 3, 4 +%else + movq m0, [r0 -4] + movq m4, [r0+ r1-4] + movq m1, [r0+2*r1-4] + movq m5, [r0+ r3-4] + movq m2, [r4 -4] + movq m6, [r4+ r1-4] + movq m3, [r4+2*r1-4] + movq m7, [r4+ r3-4] + punpcklbw m0, m4 + punpcklbw m1, m5 + punpcklbw m2, m6 + punpcklbw m3, m7 + TRANSPOSE4x4W 0, 1, 2, 3, 4 +%endif + pxor m5, m5 + + UNPACK_8TO16 bw, 6, 0, 5 + UNPACK_8TO16 bw, 7, 1, 5 + VC1_LOOP_FILTER_A0 m6, m0, m7, m1 + UNPACK_8TO16 bw, 4, 2, 5 + mova m0, m1 ; m0 = p0 + VC1_LOOP_FILTER_A0 m7, m1, m4, m2 + UNPACK_8TO16 bw, 1, 3, 5 + mova m5, m4 + VC1_LOOP_FILTER_A0 m5, m2, m1, m3 + SWAP 1, 4 ; m1 = q0 + + VC1_FILTER %1 + punpcklbw m0, m1 +%if %0 > 1 + STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, %2 +%if %1 > 4 + psrldq m0, 4 + STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, %2 +%endif +%else + STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, 0 + STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, 4 +%endif +%endmacro + + +%macro START_V_FILTER 0 + mov r4, r0 + lea r3, [4*r1] + sub r4, r3 + lea r3, [r1+2*r1] + imul r2, 0x01010101 +%endmacro + +%macro START_H_FILTER 1 + lea r3, [r1+2*r1] +%if %1 > 4 + lea r4, [r0+4*r1] +%endif + imul r2, 0x01010101 +%endmacro + +%macro VC1_LF 0 +cglobal vc1_v_loop_filter_internal + VC1_V_LOOP_FILTER 4, d + ret + +cglobal vc1_h_loop_filter_internal + VC1_H_LOOP_FILTER 4, r4 + ret + +; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, int stride, int pq) +cglobal vc1_v_loop_filter4, 3,5,0 + START_V_FILTER + call vc1_v_loop_filter_internal + RET + +; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, int stride, int pq) +cglobal vc1_h_loop_filter4, 3,5,0 + START_H_FILTER 4 + call vc1_h_loop_filter_internal + RET + +; void ff_vc1_v_loop_filter8_mmxext(uint8_t *src, int stride, int pq) +cglobal vc1_v_loop_filter8, 3,5,0 + START_V_FILTER + call vc1_v_loop_filter_internal + add r4, 4 + add r0, 4 + call vc1_v_loop_filter_internal + RET + +; void ff_vc1_h_loop_filter8_mmxext(uint8_t *src, int stride, int pq) +cglobal vc1_h_loop_filter8, 3,5,0 + START_H_FILTER 4 + call vc1_h_loop_filter_internal + lea r0, [r0+4*r1] + call vc1_h_loop_filter_internal + RET +%endmacro + +INIT_MMX mmxext +VC1_LF + +INIT_XMM sse2 +; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, int stride, int pq) +cglobal vc1_v_loop_filter8, 3,5,8 + START_V_FILTER + VC1_V_LOOP_FILTER 8, q + RET + +; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, int stride, int pq) +cglobal vc1_h_loop_filter8, 3,6,8 + START_H_FILTER 8 + VC1_H_LOOP_FILTER 8, r5 + RET + +INIT_MMX ssse3 +; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, int stride, int pq) +cglobal vc1_v_loop_filter4, 3,5,0 + START_V_FILTER + VC1_V_LOOP_FILTER 4, d + RET + +; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, int stride, int pq) +cglobal vc1_h_loop_filter4, 3,5,0 + START_H_FILTER 4 + VC1_H_LOOP_FILTER 4, r4 + RET + +INIT_XMM ssse3 +; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, int stride, int pq) +cglobal vc1_v_loop_filter8, 3,5,8 + START_V_FILTER + VC1_V_LOOP_FILTER 8, q + RET + +; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, int stride, int pq) +cglobal vc1_h_loop_filter8, 3,6,8 + START_H_FILTER 8 + VC1_H_LOOP_FILTER 8, r5 + RET + +INIT_XMM sse4 +; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq) +cglobal vc1_h_loop_filter8, 3,5,8 + START_H_FILTER 8 + VC1_H_LOOP_FILTER 8 + RET diff --git a/ffmpeg/libavcodec/x86/vc1dsp.h b/ffmpeg/libavcodec/x86/vc1dsp.h new file mode 100644 index 0000000..fdd4de1 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vc1dsp.h @@ -0,0 +1,29 @@ +/* + * VC-1 and WMV3 decoder - X86 DSP init functions + * + * 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 + */ + +#ifndef AVCODEC_X86_VC1DSP_H +#define AVCODEC_X86_VC1DSP_H + +#include "libavcodec/vc1dsp.h" + +void ff_vc1dsp_init_mmx(VC1DSPContext *dsp); +void ff_vc1dsp_init_mmxext(VC1DSPContext *dsp); + +#endif /* AVCODEC_X86_VC1DSP_H */ diff --git a/ffmpeg/libavcodec/x86/vc1dsp_init.c b/ffmpeg/libavcodec/x86/vc1dsp_init.c new file mode 100644 index 0000000..228f4dc --- /dev/null +++ b/ffmpeg/libavcodec/x86/vc1dsp_init.c @@ -0,0 +1,132 @@ +/* + * VC-1 and WMV3 - DSP functions MMX-optimized + * Copyright (c) 2007 Christophe GISQUET + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/vc1dsp.h" +#include "dsputil_mmx.h" +#include "vc1dsp.h" +#include "config.h" + +#define LOOP_FILTER(EXT) \ +void ff_vc1_v_loop_filter4_ ## EXT(uint8_t *src, int stride, int pq); \ +void ff_vc1_h_loop_filter4_ ## EXT(uint8_t *src, int stride, int pq); \ +void ff_vc1_v_loop_filter8_ ## EXT(uint8_t *src, int stride, int pq); \ +void ff_vc1_h_loop_filter8_ ## EXT(uint8_t *src, int stride, int pq); \ +\ +static void vc1_v_loop_filter16_ ## EXT(uint8_t *src, int stride, int pq) \ +{ \ + ff_vc1_v_loop_filter8_ ## EXT(src, stride, pq); \ + ff_vc1_v_loop_filter8_ ## EXT(src+8, stride, pq); \ +} \ +\ +static void vc1_h_loop_filter16_ ## EXT(uint8_t *src, int stride, int pq) \ +{ \ + ff_vc1_h_loop_filter8_ ## EXT(src, stride, pq); \ + ff_vc1_h_loop_filter8_ ## EXT(src+8*stride, stride, pq); \ +} + +#if HAVE_YASM +LOOP_FILTER(mmxext) +LOOP_FILTER(sse2) +LOOP_FILTER(ssse3) + +void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq); + +static void vc1_h_loop_filter16_sse4(uint8_t *src, int stride, int pq) +{ + ff_vc1_h_loop_filter8_sse4(src, stride, pq); + ff_vc1_h_loop_filter8_sse4(src+8*stride, stride, pq); +} + +static void avg_vc1_mspel_mc00_mmxext(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int rnd) +{ + ff_avg_pixels8_mmxext(dst, src, stride, 8); +} +#endif /* HAVE_YASM */ + +void ff_put_vc1_chroma_mc8_nornd_mmx (uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_vc1_chroma_mc8_nornd_mmxext(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_vc1_chroma_mc8_nornd_3dnow(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_put_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); +void ff_avg_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, uint8_t *src, + int stride, int h, int x, int y); + + +av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) +{ + int mm_flags = av_get_cpu_flags(); + + if (INLINE_MMX(mm_flags)) + ff_vc1dsp_init_mmx(dsp); + + if (INLINE_MMXEXT(mm_flags)) + ff_vc1dsp_init_mmxext(dsp); + +#define ASSIGN_LF(EXT) \ + dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_ ## EXT; \ + dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_ ## EXT; \ + dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_ ## EXT; \ + dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_ ## EXT; \ + dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_ ## EXT; \ + dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_ ## EXT + +#if HAVE_YASM + if (mm_flags & AV_CPU_FLAG_MMX) { + dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_mmx; + } + + if (mm_flags & AV_CPU_FLAG_MMXEXT) { + ASSIGN_LF(mmxext); + dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_mmxext; + + dsp->avg_vc1_mspel_pixels_tab[0] = avg_vc1_mspel_mc00_mmxext; + } else if (mm_flags & AV_CPU_FLAG_3DNOW) { + dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_3dnow; + } + + if (mm_flags & AV_CPU_FLAG_SSE2) { + dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_sse2; + dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse2; + dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_sse2; + dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse2; + } + if (mm_flags & AV_CPU_FLAG_SSSE3) { + ASSIGN_LF(ssse3); + dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_ssse3; + dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_ssse3; + } + if (mm_flags & AV_CPU_FLAG_SSE4) { + dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse4; + dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse4; + } +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/vc1dsp_mmx.c b/ffmpeg/libavcodec/x86/vc1dsp_mmx.c new file mode 100644 index 0000000..df0385f --- /dev/null +++ b/ffmpeg/libavcodec/x86/vc1dsp_mmx.c @@ -0,0 +1,750 @@ +/* + * VC-1 and WMV3 - DSP functions MMX-optimized + * Copyright (c) 2007 Christophe GISQUET + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "dsputil_mmx.h" +#include "libavcodec/vc1dsp.h" +#include "vc1dsp.h" + +#if HAVE_INLINE_ASM + +#define OP_PUT(S,D) +#define OP_AVG(S,D) "pavgb " #S ", " #D " \n\t" + +/** Add rounder from mm7 to mm3 and pack result at destination */ +#define NORMALIZE_MMX(SHIFT) \ + "paddw %%mm7, %%mm3 \n\t" /* +bias-r */ \ + "paddw %%mm7, %%mm4 \n\t" /* +bias-r */ \ + "psraw "SHIFT", %%mm3 \n\t" \ + "psraw "SHIFT", %%mm4 \n\t" + +#define TRANSFER_DO_PACK(OP) \ + "packuswb %%mm4, %%mm3 \n\t" \ + OP((%2), %%mm3) \ + "movq %%mm3, (%2) \n\t" + +#define TRANSFER_DONT_PACK(OP) \ + OP(0(%2), %%mm3) \ + OP(8(%2), %%mm4) \ + "movq %%mm3, 0(%2) \n\t" \ + "movq %%mm4, 8(%2) \n\t" + +/** @see MSPEL_FILTER13_CORE for use as UNPACK macro */ +#define DO_UNPACK(reg) "punpcklbw %%mm0, " reg "\n\t" +#define DONT_UNPACK(reg) + +/** Compute the rounder 32-r or 8-r and unpacks it to mm7 */ +#define LOAD_ROUNDER_MMX(ROUND) \ + "movd "ROUND", %%mm7 \n\t" \ + "punpcklwd %%mm7, %%mm7 \n\t" \ + "punpckldq %%mm7, %%mm7 \n\t" + +#define SHIFT2_LINE(OFF, R0,R1,R2,R3) \ + "paddw %%mm"#R2", %%mm"#R1" \n\t" \ + "movd (%0,%3), %%mm"#R0" \n\t" \ + "pmullw %%mm6, %%mm"#R1" \n\t" \ + "punpcklbw %%mm0, %%mm"#R0" \n\t" \ + "movd (%0,%2), %%mm"#R3" \n\t" \ + "psubw %%mm"#R0", %%mm"#R1" \n\t" \ + "punpcklbw %%mm0, %%mm"#R3" \n\t" \ + "paddw %%mm7, %%mm"#R1" \n\t" \ + "psubw %%mm"#R3", %%mm"#R1" \n\t" \ + "psraw %4, %%mm"#R1" \n\t" \ + "movq %%mm"#R1", "#OFF"(%1) \n\t" \ + "add %2, %0 \n\t" + +/** Sacrifying mm6 allows to pipeline loads from src */ +static void vc1_put_ver_16b_shift2_mmx(int16_t *dst, + const uint8_t *src, x86_reg stride, + int rnd, int64_t shift) +{ + __asm__ volatile( + "mov $3, %%"REG_c" \n\t" + LOAD_ROUNDER_MMX("%5") + "movq "MANGLE(ff_pw_9)", %%mm6 \n\t" + "1: \n\t" + "movd (%0), %%mm2 \n\t" + "add %2, %0 \n\t" + "movd (%0), %%mm3 \n\t" + "punpcklbw %%mm0, %%mm2 \n\t" + "punpcklbw %%mm0, %%mm3 \n\t" + SHIFT2_LINE( 0, 1, 2, 3, 4) + SHIFT2_LINE( 24, 2, 3, 4, 1) + SHIFT2_LINE( 48, 3, 4, 1, 2) + SHIFT2_LINE( 72, 4, 1, 2, 3) + SHIFT2_LINE( 96, 1, 2, 3, 4) + SHIFT2_LINE(120, 2, 3, 4, 1) + SHIFT2_LINE(144, 3, 4, 1, 2) + SHIFT2_LINE(168, 4, 1, 2, 3) + "sub %6, %0 \n\t" + "add $8, %1 \n\t" + "dec %%"REG_c" \n\t" + "jnz 1b \n\t" + : "+r"(src), "+r"(dst) + : "r"(stride), "r"(-2*stride), + "m"(shift), "m"(rnd), "r"(9*stride-4) + : "%"REG_c, "memory" + ); +} + +/** + * Data is already unpacked, so some operations can directly be made from + * memory. + */ +#define VC1_HOR_16b_SHIFT2(OP, OPNAME)\ +static void OPNAME ## vc1_hor_16b_shift2_mmx(uint8_t *dst, x86_reg stride,\ + const int16_t *src, int rnd)\ +{\ + int h = 8;\ +\ + src -= 1;\ + rnd -= (-1+9+9-1)*1024; /* Add -1024 bias */\ + __asm__ volatile(\ + LOAD_ROUNDER_MMX("%4")\ + "movq "MANGLE(ff_pw_128)", %%mm6\n\t"\ + "movq "MANGLE(ff_pw_9)", %%mm5 \n\t"\ + "1: \n\t"\ + "movq 2*0+0(%1), %%mm1 \n\t"\ + "movq 2*0+8(%1), %%mm2 \n\t"\ + "movq 2*1+0(%1), %%mm3 \n\t"\ + "movq 2*1+8(%1), %%mm4 \n\t"\ + "paddw 2*3+0(%1), %%mm1 \n\t"\ + "paddw 2*3+8(%1), %%mm2 \n\t"\ + "paddw 2*2+0(%1), %%mm3 \n\t"\ + "paddw 2*2+8(%1), %%mm4 \n\t"\ + "pmullw %%mm5, %%mm3 \n\t"\ + "pmullw %%mm5, %%mm4 \n\t"\ + "psubw %%mm1, %%mm3 \n\t"\ + "psubw %%mm2, %%mm4 \n\t"\ + NORMALIZE_MMX("$7")\ + /* Remove bias */\ + "paddw %%mm6, %%mm3 \n\t"\ + "paddw %%mm6, %%mm4 \n\t"\ + TRANSFER_DO_PACK(OP)\ + "add $24, %1 \n\t"\ + "add %3, %2 \n\t"\ + "decl %0 \n\t"\ + "jnz 1b \n\t"\ + : "+r"(h), "+r" (src), "+r" (dst)\ + : "r"(stride), "m"(rnd)\ + : "memory"\ + );\ +} + +VC1_HOR_16b_SHIFT2(OP_PUT, put_) +VC1_HOR_16b_SHIFT2(OP_AVG, avg_) + + +/** + * Purely vertical or horizontal 1/2 shift interpolation. + * Sacrify mm6 for *9 factor. + */ +#define VC1_SHIFT2(OP, OPNAME)\ +static void OPNAME ## vc1_shift2_mmx(uint8_t *dst, const uint8_t *src,\ + x86_reg stride, int rnd, x86_reg offset)\ +{\ + rnd = 8-rnd;\ + __asm__ volatile(\ + "mov $8, %%"REG_c" \n\t"\ + LOAD_ROUNDER_MMX("%5")\ + "movq "MANGLE(ff_pw_9)", %%mm6\n\t"\ + "1: \n\t"\ + "movd 0(%0 ), %%mm3 \n\t"\ + "movd 4(%0 ), %%mm4 \n\t"\ + "movd 0(%0,%2), %%mm1 \n\t"\ + "movd 4(%0,%2), %%mm2 \n\t"\ + "add %2, %0 \n\t"\ + "punpcklbw %%mm0, %%mm3 \n\t"\ + "punpcklbw %%mm0, %%mm4 \n\t"\ + "punpcklbw %%mm0, %%mm1 \n\t"\ + "punpcklbw %%mm0, %%mm2 \n\t"\ + "paddw %%mm1, %%mm3 \n\t"\ + "paddw %%mm2, %%mm4 \n\t"\ + "movd 0(%0,%3), %%mm1 \n\t"\ + "movd 4(%0,%3), %%mm2 \n\t"\ + "pmullw %%mm6, %%mm3 \n\t" /* 0,9,9,0*/\ + "pmullw %%mm6, %%mm4 \n\t" /* 0,9,9,0*/\ + "punpcklbw %%mm0, %%mm1 \n\t"\ + "punpcklbw %%mm0, %%mm2 \n\t"\ + "psubw %%mm1, %%mm3 \n\t" /*-1,9,9,0*/\ + "psubw %%mm2, %%mm4 \n\t" /*-1,9,9,0*/\ + "movd 0(%0,%2), %%mm1 \n\t"\ + "movd 4(%0,%2), %%mm2 \n\t"\ + "punpcklbw %%mm0, %%mm1 \n\t"\ + "punpcklbw %%mm0, %%mm2 \n\t"\ + "psubw %%mm1, %%mm3 \n\t" /*-1,9,9,-1*/\ + "psubw %%mm2, %%mm4 \n\t" /*-1,9,9,-1*/\ + NORMALIZE_MMX("$4")\ + "packuswb %%mm4, %%mm3 \n\t"\ + OP((%1), %%mm3)\ + "movq %%mm3, (%1) \n\t"\ + "add %6, %0 \n\t"\ + "add %4, %1 \n\t"\ + "dec %%"REG_c" \n\t"\ + "jnz 1b \n\t"\ + : "+r"(src), "+r"(dst)\ + : "r"(offset), "r"(-2*offset), "g"(stride), "m"(rnd),\ + "g"(stride-offset)\ + : "%"REG_c, "memory"\ + );\ +} + +VC1_SHIFT2(OP_PUT, put_) +VC1_SHIFT2(OP_AVG, avg_) + +/** + * Core of the 1/4 and 3/4 shift bicubic interpolation. + * + * @param UNPACK Macro unpacking arguments from 8 to 16bits (can be empty). + * @param MOVQ "movd 1" or "movq 2", if data read is already unpacked. + * @param A1 Address of 1st tap (beware of unpacked/packed). + * @param A2 Address of 2nd tap + * @param A3 Address of 3rd tap + * @param A4 Address of 4th tap + */ +#define MSPEL_FILTER13_CORE(UNPACK, MOVQ, A1, A2, A3, A4) \ + MOVQ "*0+"A1", %%mm1 \n\t" \ + MOVQ "*4+"A1", %%mm2 \n\t" \ + UNPACK("%%mm1") \ + UNPACK("%%mm2") \ + "pmullw "MANGLE(ff_pw_3)", %%mm1\n\t" \ + "pmullw "MANGLE(ff_pw_3)", %%mm2\n\t" \ + MOVQ "*0+"A2", %%mm3 \n\t" \ + MOVQ "*4+"A2", %%mm4 \n\t" \ + UNPACK("%%mm3") \ + UNPACK("%%mm4") \ + "pmullw %%mm6, %%mm3 \n\t" /* *18 */ \ + "pmullw %%mm6, %%mm4 \n\t" /* *18 */ \ + "psubw %%mm1, %%mm3 \n\t" /* 18,-3 */ \ + "psubw %%mm2, %%mm4 \n\t" /* 18,-3 */ \ + MOVQ "*0+"A4", %%mm1 \n\t" \ + MOVQ "*4+"A4", %%mm2 \n\t" \ + UNPACK("%%mm1") \ + UNPACK("%%mm2") \ + "psllw $2, %%mm1 \n\t" /* 4* */ \ + "psllw $2, %%mm2 \n\t" /* 4* */ \ + "psubw %%mm1, %%mm3 \n\t" /* -4,18,-3 */ \ + "psubw %%mm2, %%mm4 \n\t" /* -4,18,-3 */ \ + MOVQ "*0+"A3", %%mm1 \n\t" \ + MOVQ "*4+"A3", %%mm2 \n\t" \ + UNPACK("%%mm1") \ + UNPACK("%%mm2") \ + "pmullw %%mm5, %%mm1 \n\t" /* *53 */ \ + "pmullw %%mm5, %%mm2 \n\t" /* *53 */ \ + "paddw %%mm1, %%mm3 \n\t" /* 4,53,18,-3 */ \ + "paddw %%mm2, %%mm4 \n\t" /* 4,53,18,-3 */ + +/** + * Macro to build the vertical 16bits version of vc1_put_shift[13]. + * Here, offset=src_stride. Parameters passed A1 to A4 must use + * %3 (src_stride) and %4 (3*src_stride). + * + * @param NAME Either 1 or 3 + * @see MSPEL_FILTER13_CORE for information on A1->A4 + */ +#define MSPEL_FILTER13_VER_16B(NAME, A1, A2, A3, A4) \ +static void \ +vc1_put_ver_16b_ ## NAME ## _mmx(int16_t *dst, const uint8_t *src, \ + x86_reg src_stride, \ + int rnd, int64_t shift) \ +{ \ + int h = 8; \ + src -= src_stride; \ + __asm__ volatile( \ + LOAD_ROUNDER_MMX("%5") \ + "movq "MANGLE(ff_pw_53)", %%mm5\n\t" \ + "movq "MANGLE(ff_pw_18)", %%mm6\n\t" \ + ".p2align 3 \n\t" \ + "1: \n\t" \ + MSPEL_FILTER13_CORE(DO_UNPACK, "movd 1", A1, A2, A3, A4) \ + NORMALIZE_MMX("%6") \ + TRANSFER_DONT_PACK(OP_PUT) \ + /* Last 3 (in fact 4) bytes on the line */ \ + "movd 8+"A1", %%mm1 \n\t" \ + DO_UNPACK("%%mm1") \ + "movq %%mm1, %%mm3 \n\t" \ + "paddw %%mm1, %%mm1 \n\t" \ + "paddw %%mm3, %%mm1 \n\t" /* 3* */ \ + "movd 8+"A2", %%mm3 \n\t" \ + DO_UNPACK("%%mm3") \ + "pmullw %%mm6, %%mm3 \n\t" /* *18 */ \ + "psubw %%mm1, %%mm3 \n\t" /*18,-3 */ \ + "movd 8+"A3", %%mm1 \n\t" \ + DO_UNPACK("%%mm1") \ + "pmullw %%mm5, %%mm1 \n\t" /* *53 */ \ + "paddw %%mm1, %%mm3 \n\t" /*53,18,-3 */ \ + "movd 8+"A4", %%mm1 \n\t" \ + DO_UNPACK("%%mm1") \ + "psllw $2, %%mm1 \n\t" /* 4* */ \ + "psubw %%mm1, %%mm3 \n\t" \ + "paddw %%mm7, %%mm3 \n\t" \ + "psraw %6, %%mm3 \n\t" \ + "movq %%mm3, 16(%2) \n\t" \ + "add %3, %1 \n\t" \ + "add $24, %2 \n\t" \ + "decl %0 \n\t" \ + "jnz 1b \n\t" \ + : "+r"(h), "+r" (src), "+r" (dst) \ + : "r"(src_stride), "r"(3*src_stride), \ + "m"(rnd), "m"(shift) \ + : "memory" \ + ); \ +} + +/** + * Macro to build the horizontal 16bits version of vc1_put_shift[13]. + * Here, offset=16bits, so parameters passed A1 to A4 should be simple. + * + * @param NAME Either 1 or 3 + * @see MSPEL_FILTER13_CORE for information on A1->A4 + */ +#define MSPEL_FILTER13_HOR_16B(NAME, A1, A2, A3, A4, OP, OPNAME) \ +static void \ +OPNAME ## vc1_hor_16b_ ## NAME ## _mmx(uint8_t *dst, x86_reg stride, \ + const int16_t *src, int rnd) \ +{ \ + int h = 8; \ + src -= 1; \ + rnd -= (-4+58+13-3)*256; /* Add -256 bias */ \ + __asm__ volatile( \ + LOAD_ROUNDER_MMX("%4") \ + "movq "MANGLE(ff_pw_18)", %%mm6 \n\t" \ + "movq "MANGLE(ff_pw_53)", %%mm5 \n\t" \ + ".p2align 3 \n\t" \ + "1: \n\t" \ + MSPEL_FILTER13_CORE(DONT_UNPACK, "movq 2", A1, A2, A3, A4) \ + NORMALIZE_MMX("$7") \ + /* Remove bias */ \ + "paddw "MANGLE(ff_pw_128)", %%mm3 \n\t" \ + "paddw "MANGLE(ff_pw_128)", %%mm4 \n\t" \ + TRANSFER_DO_PACK(OP) \ + "add $24, %1 \n\t" \ + "add %3, %2 \n\t" \ + "decl %0 \n\t" \ + "jnz 1b \n\t" \ + : "+r"(h), "+r" (src), "+r" (dst) \ + : "r"(stride), "m"(rnd) \ + : "memory" \ + ); \ +} + +/** + * Macro to build the 8bits, any direction, version of vc1_put_shift[13]. + * Here, offset=src_stride. Parameters passed A1 to A4 must use + * %3 (offset) and %4 (3*offset). + * + * @param NAME Either 1 or 3 + * @see MSPEL_FILTER13_CORE for information on A1->A4 + */ +#define MSPEL_FILTER13_8B(NAME, A1, A2, A3, A4, OP, OPNAME) \ +static void \ +OPNAME ## vc1_## NAME ## _mmx(uint8_t *dst, const uint8_t *src, \ + x86_reg stride, int rnd, x86_reg offset) \ +{ \ + int h = 8; \ + src -= offset; \ + rnd = 32-rnd; \ + __asm__ volatile ( \ + LOAD_ROUNDER_MMX("%6") \ + "movq "MANGLE(ff_pw_53)", %%mm5 \n\t" \ + "movq "MANGLE(ff_pw_18)", %%mm6 \n\t" \ + ".p2align 3 \n\t" \ + "1: \n\t" \ + MSPEL_FILTER13_CORE(DO_UNPACK, "movd 1", A1, A2, A3, A4) \ + NORMALIZE_MMX("$6") \ + TRANSFER_DO_PACK(OP) \ + "add %5, %1 \n\t" \ + "add %5, %2 \n\t" \ + "decl %0 \n\t" \ + "jnz 1b \n\t" \ + : "+r"(h), "+r" (src), "+r" (dst) \ + : "r"(offset), "r"(3*offset), "g"(stride), "m"(rnd) \ + : "memory" \ + ); \ +} + +/** 1/4 shift bicubic interpolation */ +MSPEL_FILTER13_8B (shift1, "0(%1,%4 )", "0(%1,%3,2)", "0(%1,%3 )", "0(%1 )", OP_PUT, put_) +MSPEL_FILTER13_8B (shift1, "0(%1,%4 )", "0(%1,%3,2)", "0(%1,%3 )", "0(%1 )", OP_AVG, avg_) +MSPEL_FILTER13_VER_16B(shift1, "0(%1,%4 )", "0(%1,%3,2)", "0(%1,%3 )", "0(%1 )") +MSPEL_FILTER13_HOR_16B(shift1, "2*3(%1)", "2*2(%1)", "2*1(%1)", "2*0(%1)", OP_PUT, put_) +MSPEL_FILTER13_HOR_16B(shift1, "2*3(%1)", "2*2(%1)", "2*1(%1)", "2*0(%1)", OP_AVG, avg_) + +/** 3/4 shift bicubic interpolation */ +MSPEL_FILTER13_8B (shift3, "0(%1 )", "0(%1,%3 )", "0(%1,%3,2)", "0(%1,%4 )", OP_PUT, put_) +MSPEL_FILTER13_8B (shift3, "0(%1 )", "0(%1,%3 )", "0(%1,%3,2)", "0(%1,%4 )", OP_AVG, avg_) +MSPEL_FILTER13_VER_16B(shift3, "0(%1 )", "0(%1,%3 )", "0(%1,%3,2)", "0(%1,%4 )") +MSPEL_FILTER13_HOR_16B(shift3, "2*0(%1)", "2*1(%1)", "2*2(%1)", "2*3(%1)", OP_PUT, put_) +MSPEL_FILTER13_HOR_16B(shift3, "2*0(%1)", "2*1(%1)", "2*2(%1)", "2*3(%1)", OP_AVG, avg_) + +typedef void (*vc1_mspel_mc_filter_ver_16bits)(int16_t *dst, const uint8_t *src, x86_reg src_stride, int rnd, int64_t shift); +typedef void (*vc1_mspel_mc_filter_hor_16bits)(uint8_t *dst, x86_reg dst_stride, const int16_t *src, int rnd); +typedef void (*vc1_mspel_mc_filter_8bits)(uint8_t *dst, const uint8_t *src, x86_reg stride, int rnd, x86_reg offset); + +/** + * Interpolate fractional pel values by applying proper vertical then + * horizontal filter. + * + * @param dst Destination buffer for interpolated pels. + * @param src Source buffer. + * @param stride Stride for both src and dst buffers. + * @param hmode Horizontal filter (expressed in quarter pixels shift). + * @param hmode Vertical filter. + * @param rnd Rounding bias. + */ +#define VC1_MSPEL_MC(OP)\ +static void OP ## vc1_mspel_mc(uint8_t *dst, const uint8_t *src, int stride,\ + int hmode, int vmode, int rnd)\ +{\ + static const vc1_mspel_mc_filter_ver_16bits vc1_put_shift_ver_16bits[] =\ + { NULL, vc1_put_ver_16b_shift1_mmx, vc1_put_ver_16b_shift2_mmx, vc1_put_ver_16b_shift3_mmx };\ + static const vc1_mspel_mc_filter_hor_16bits vc1_put_shift_hor_16bits[] =\ + { NULL, OP ## vc1_hor_16b_shift1_mmx, OP ## vc1_hor_16b_shift2_mmx, OP ## vc1_hor_16b_shift3_mmx };\ + static const vc1_mspel_mc_filter_8bits vc1_put_shift_8bits[] =\ + { NULL, OP ## vc1_shift1_mmx, OP ## vc1_shift2_mmx, OP ## vc1_shift3_mmx };\ +\ + __asm__ volatile(\ + "pxor %%mm0, %%mm0 \n\t"\ + ::: "memory"\ + );\ +\ + if (vmode) { /* Vertical filter to apply */\ + if (hmode) { /* Horizontal filter to apply, output to tmp */\ + static const int shift_value[] = { 0, 5, 1, 5 };\ + int shift = (shift_value[hmode]+shift_value[vmode])>>1;\ + int r;\ + DECLARE_ALIGNED(16, int16_t, tmp)[12*8];\ +\ + r = (1<<(shift-1)) + rnd-1;\ + vc1_put_shift_ver_16bits[vmode](tmp, src-1, stride, r, shift);\ +\ + vc1_put_shift_hor_16bits[hmode](dst, stride, tmp+1, 64-rnd);\ + return;\ + }\ + else { /* No horizontal filter, output 8 lines to dst */\ + vc1_put_shift_8bits[vmode](dst, src, stride, 1-rnd, stride);\ + return;\ + }\ + }\ +\ + /* Horizontal mode with no vertical mode */\ + vc1_put_shift_8bits[hmode](dst, src, stride, rnd, 1);\ +} + +VC1_MSPEL_MC(put_) +VC1_MSPEL_MC(avg_) + +/** Macro to ease bicubic filter interpolation functions declarations */ +#define DECLARE_FUNCTION(a, b) \ +static void put_vc1_mspel_mc ## a ## b ## _mmx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, \ + int rnd) \ +{ \ + put_vc1_mspel_mc(dst, src, stride, a, b, rnd); \ +}\ +static void avg_vc1_mspel_mc ## a ## b ## _mmxext(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, \ + int rnd) \ +{ \ + avg_vc1_mspel_mc(dst, src, stride, a, b, rnd); \ +} + +DECLARE_FUNCTION(0, 1) +DECLARE_FUNCTION(0, 2) +DECLARE_FUNCTION(0, 3) + +DECLARE_FUNCTION(1, 0) +DECLARE_FUNCTION(1, 1) +DECLARE_FUNCTION(1, 2) +DECLARE_FUNCTION(1, 3) + +DECLARE_FUNCTION(2, 0) +DECLARE_FUNCTION(2, 1) +DECLARE_FUNCTION(2, 2) +DECLARE_FUNCTION(2, 3) + +DECLARE_FUNCTION(3, 0) +DECLARE_FUNCTION(3, 1) +DECLARE_FUNCTION(3, 2) +DECLARE_FUNCTION(3, 3) + +static void vc1_inv_trans_4x4_dc_mmxext(uint8_t *dest, int linesize, + int16_t *block) +{ + int dc = block[0]; + dc = (17 * dc + 4) >> 3; + dc = (17 * dc + 64) >> 7; + __asm__ volatile( + "movd %0, %%mm0 \n\t" + "pshufw $0, %%mm0, %%mm0 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "psubw %%mm0, %%mm1 \n\t" + "packuswb %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm1 \n\t" + ::"r"(dc) + ); + __asm__ volatile( + "movd %0, %%mm2 \n\t" + "movd %1, %%mm3 \n\t" + "movd %2, %%mm4 \n\t" + "movd %3, %%mm5 \n\t" + "paddusb %%mm0, %%mm2 \n\t" + "paddusb %%mm0, %%mm3 \n\t" + "paddusb %%mm0, %%mm4 \n\t" + "paddusb %%mm0, %%mm5 \n\t" + "psubusb %%mm1, %%mm2 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm1, %%mm5 \n\t" + "movd %%mm2, %0 \n\t" + "movd %%mm3, %1 \n\t" + "movd %%mm4, %2 \n\t" + "movd %%mm5, %3 \n\t" + :"+m"(*(uint32_t*)(dest+0*linesize)), + "+m"(*(uint32_t*)(dest+1*linesize)), + "+m"(*(uint32_t*)(dest+2*linesize)), + "+m"(*(uint32_t*)(dest+3*linesize)) + ); +} + +static void vc1_inv_trans_4x8_dc_mmxext(uint8_t *dest, int linesize, + int16_t *block) +{ + int dc = block[0]; + dc = (17 * dc + 4) >> 3; + dc = (12 * dc + 64) >> 7; + __asm__ volatile( + "movd %0, %%mm0 \n\t" + "pshufw $0, %%mm0, %%mm0 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "psubw %%mm0, %%mm1 \n\t" + "packuswb %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm1 \n\t" + ::"r"(dc) + ); + __asm__ volatile( + "movd %0, %%mm2 \n\t" + "movd %1, %%mm3 \n\t" + "movd %2, %%mm4 \n\t" + "movd %3, %%mm5 \n\t" + "paddusb %%mm0, %%mm2 \n\t" + "paddusb %%mm0, %%mm3 \n\t" + "paddusb %%mm0, %%mm4 \n\t" + "paddusb %%mm0, %%mm5 \n\t" + "psubusb %%mm1, %%mm2 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm1, %%mm5 \n\t" + "movd %%mm2, %0 \n\t" + "movd %%mm3, %1 \n\t" + "movd %%mm4, %2 \n\t" + "movd %%mm5, %3 \n\t" + :"+m"(*(uint32_t*)(dest+0*linesize)), + "+m"(*(uint32_t*)(dest+1*linesize)), + "+m"(*(uint32_t*)(dest+2*linesize)), + "+m"(*(uint32_t*)(dest+3*linesize)) + ); + dest += 4*linesize; + __asm__ volatile( + "movd %0, %%mm2 \n\t" + "movd %1, %%mm3 \n\t" + "movd %2, %%mm4 \n\t" + "movd %3, %%mm5 \n\t" + "paddusb %%mm0, %%mm2 \n\t" + "paddusb %%mm0, %%mm3 \n\t" + "paddusb %%mm0, %%mm4 \n\t" + "paddusb %%mm0, %%mm5 \n\t" + "psubusb %%mm1, %%mm2 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm1, %%mm5 \n\t" + "movd %%mm2, %0 \n\t" + "movd %%mm3, %1 \n\t" + "movd %%mm4, %2 \n\t" + "movd %%mm5, %3 \n\t" + :"+m"(*(uint32_t*)(dest+0*linesize)), + "+m"(*(uint32_t*)(dest+1*linesize)), + "+m"(*(uint32_t*)(dest+2*linesize)), + "+m"(*(uint32_t*)(dest+3*linesize)) + ); +} + +static void vc1_inv_trans_8x4_dc_mmxext(uint8_t *dest, int linesize, + int16_t *block) +{ + int dc = block[0]; + dc = ( 3 * dc + 1) >> 1; + dc = (17 * dc + 64) >> 7; + __asm__ volatile( + "movd %0, %%mm0 \n\t" + "pshufw $0, %%mm0, %%mm0 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "psubw %%mm0, %%mm1 \n\t" + "packuswb %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm1 \n\t" + ::"r"(dc) + ); + __asm__ volatile( + "movq %0, %%mm2 \n\t" + "movq %1, %%mm3 \n\t" + "movq %2, %%mm4 \n\t" + "movq %3, %%mm5 \n\t" + "paddusb %%mm0, %%mm2 \n\t" + "paddusb %%mm0, %%mm3 \n\t" + "paddusb %%mm0, %%mm4 \n\t" + "paddusb %%mm0, %%mm5 \n\t" + "psubusb %%mm1, %%mm2 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm1, %%mm5 \n\t" + "movq %%mm2, %0 \n\t" + "movq %%mm3, %1 \n\t" + "movq %%mm4, %2 \n\t" + "movq %%mm5, %3 \n\t" + :"+m"(*(uint32_t*)(dest+0*linesize)), + "+m"(*(uint32_t*)(dest+1*linesize)), + "+m"(*(uint32_t*)(dest+2*linesize)), + "+m"(*(uint32_t*)(dest+3*linesize)) + ); +} + +static void vc1_inv_trans_8x8_dc_mmxext(uint8_t *dest, int linesize, + int16_t *block) +{ + int dc = block[0]; + dc = (3 * dc + 1) >> 1; + dc = (3 * dc + 16) >> 5; + __asm__ volatile( + "movd %0, %%mm0 \n\t" + "pshufw $0, %%mm0, %%mm0 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "psubw %%mm0, %%mm1 \n\t" + "packuswb %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm1 \n\t" + ::"r"(dc) + ); + __asm__ volatile( + "movq %0, %%mm2 \n\t" + "movq %1, %%mm3 \n\t" + "movq %2, %%mm4 \n\t" + "movq %3, %%mm5 \n\t" + "paddusb %%mm0, %%mm2 \n\t" + "paddusb %%mm0, %%mm3 \n\t" + "paddusb %%mm0, %%mm4 \n\t" + "paddusb %%mm0, %%mm5 \n\t" + "psubusb %%mm1, %%mm2 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm1, %%mm5 \n\t" + "movq %%mm2, %0 \n\t" + "movq %%mm3, %1 \n\t" + "movq %%mm4, %2 \n\t" + "movq %%mm5, %3 \n\t" + :"+m"(*(uint32_t*)(dest+0*linesize)), + "+m"(*(uint32_t*)(dest+1*linesize)), + "+m"(*(uint32_t*)(dest+2*linesize)), + "+m"(*(uint32_t*)(dest+3*linesize)) + ); + dest += 4*linesize; + __asm__ volatile( + "movq %0, %%mm2 \n\t" + "movq %1, %%mm3 \n\t" + "movq %2, %%mm4 \n\t" + "movq %3, %%mm5 \n\t" + "paddusb %%mm0, %%mm2 \n\t" + "paddusb %%mm0, %%mm3 \n\t" + "paddusb %%mm0, %%mm4 \n\t" + "paddusb %%mm0, %%mm5 \n\t" + "psubusb %%mm1, %%mm2 \n\t" + "psubusb %%mm1, %%mm3 \n\t" + "psubusb %%mm1, %%mm4 \n\t" + "psubusb %%mm1, %%mm5 \n\t" + "movq %%mm2, %0 \n\t" + "movq %%mm3, %1 \n\t" + "movq %%mm4, %2 \n\t" + "movq %%mm5, %3 \n\t" + :"+m"(*(uint32_t*)(dest+0*linesize)), + "+m"(*(uint32_t*)(dest+1*linesize)), + "+m"(*(uint32_t*)(dest+2*linesize)), + "+m"(*(uint32_t*)(dest+3*linesize)) + ); +} + +av_cold void ff_vc1dsp_init_mmx(VC1DSPContext *dsp) +{ + dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_vc1_mspel_mc00_mmx; + dsp->put_vc1_mspel_pixels_tab[ 4] = put_vc1_mspel_mc01_mmx; + dsp->put_vc1_mspel_pixels_tab[ 8] = put_vc1_mspel_mc02_mmx; + dsp->put_vc1_mspel_pixels_tab[12] = put_vc1_mspel_mc03_mmx; + + dsp->put_vc1_mspel_pixels_tab[ 1] = put_vc1_mspel_mc10_mmx; + dsp->put_vc1_mspel_pixels_tab[ 5] = put_vc1_mspel_mc11_mmx; + dsp->put_vc1_mspel_pixels_tab[ 9] = put_vc1_mspel_mc12_mmx; + dsp->put_vc1_mspel_pixels_tab[13] = put_vc1_mspel_mc13_mmx; + + dsp->put_vc1_mspel_pixels_tab[ 2] = put_vc1_mspel_mc20_mmx; + dsp->put_vc1_mspel_pixels_tab[ 6] = put_vc1_mspel_mc21_mmx; + dsp->put_vc1_mspel_pixels_tab[10] = put_vc1_mspel_mc22_mmx; + dsp->put_vc1_mspel_pixels_tab[14] = put_vc1_mspel_mc23_mmx; + + dsp->put_vc1_mspel_pixels_tab[ 3] = put_vc1_mspel_mc30_mmx; + dsp->put_vc1_mspel_pixels_tab[ 7] = put_vc1_mspel_mc31_mmx; + dsp->put_vc1_mspel_pixels_tab[11] = put_vc1_mspel_mc32_mmx; + dsp->put_vc1_mspel_pixels_tab[15] = put_vc1_mspel_mc33_mmx; +} + +av_cold void ff_vc1dsp_init_mmxext(VC1DSPContext *dsp) +{ + dsp->avg_vc1_mspel_pixels_tab[ 4] = avg_vc1_mspel_mc01_mmxext; + dsp->avg_vc1_mspel_pixels_tab[ 8] = avg_vc1_mspel_mc02_mmxext; + dsp->avg_vc1_mspel_pixels_tab[12] = avg_vc1_mspel_mc03_mmxext; + + dsp->avg_vc1_mspel_pixels_tab[ 1] = avg_vc1_mspel_mc10_mmxext; + dsp->avg_vc1_mspel_pixels_tab[ 5] = avg_vc1_mspel_mc11_mmxext; + dsp->avg_vc1_mspel_pixels_tab[ 9] = avg_vc1_mspel_mc12_mmxext; + dsp->avg_vc1_mspel_pixels_tab[13] = avg_vc1_mspel_mc13_mmxext; + + dsp->avg_vc1_mspel_pixels_tab[ 2] = avg_vc1_mspel_mc20_mmxext; + dsp->avg_vc1_mspel_pixels_tab[ 6] = avg_vc1_mspel_mc21_mmxext; + dsp->avg_vc1_mspel_pixels_tab[10] = avg_vc1_mspel_mc22_mmxext; + dsp->avg_vc1_mspel_pixels_tab[14] = avg_vc1_mspel_mc23_mmxext; + + dsp->avg_vc1_mspel_pixels_tab[ 3] = avg_vc1_mspel_mc30_mmxext; + dsp->avg_vc1_mspel_pixels_tab[ 7] = avg_vc1_mspel_mc31_mmxext; + dsp->avg_vc1_mspel_pixels_tab[11] = avg_vc1_mspel_mc32_mmxext; + dsp->avg_vc1_mspel_pixels_tab[15] = avg_vc1_mspel_mc33_mmxext; + + dsp->vc1_inv_trans_8x8_dc = vc1_inv_trans_8x8_dc_mmxext; + dsp->vc1_inv_trans_4x8_dc = vc1_inv_trans_4x8_dc_mmxext; + dsp->vc1_inv_trans_8x4_dc = vc1_inv_trans_8x4_dc_mmxext; + dsp->vc1_inv_trans_4x4_dc = vc1_inv_trans_4x4_dc_mmxext; +} +#endif /* HAVE_INLINE_ASM */ diff --git a/ffmpeg/libavcodec/x86/videodsp.asm b/ffmpeg/libavcodec/x86/videodsp.asm new file mode 100644 index 0000000..0eb4721 --- /dev/null +++ b/ffmpeg/libavcodec/x86/videodsp.asm @@ -0,0 +1,612 @@ +;****************************************************************************** +;* Core video DSP functions +;* Copyright (c) 2012 Ronald S. Bultje +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION .text + +; extern void ff_emu_edge_core(uint8_t *buf, const uint8_t *src, x86_reg linesize, +; x86_reg start_y, x86_reg end_y, x86_reg block_h, +; x86_reg start_x, x86_reg end_x, x86_reg block_w); +; +; The actual function itself is below. It basically wraps a very simple +; w = end_x - start_x +; if (w) { +; if (w > 22) { +; jump to the slow loop functions +; } else { +; jump to the fast loop functions +; } +; } +; +; ... and then the same for left/right extend also. See below for loop +; function implementations. Fast are fixed-width, slow is variable-width + +%macro EMU_EDGE_FUNC 0 +%if ARCH_X86_64 +%define w_reg r7 +cglobal emu_edge_core, 6, 9, 1 + mov r8, r5 ; save block_h +%else +%define w_reg r6 +cglobal emu_edge_core, 2, 7, 0 + mov r4, r4m ; end_y + mov r5, r5m ; block_h +%endif + + ; start with vertical extend (top/bottom) and body pixel copy + mov w_reg, r7m + sub w_reg, r6m ; w = start_x - end_x + sub r5, r4 +%if ARCH_X86_64 + sub r4, r3 +%else + sub r4, dword r3m +%endif + cmp w_reg, 22 + jg .slow_v_extend_loop +%if ARCH_X86_32 + mov r2, r2m ; linesize +%endif + sal w_reg, 7 ; w * 128 +%ifdef PIC + lea rax, [.emuedge_v_extend_1 - (.emuedge_v_extend_2 - .emuedge_v_extend_1)] + add w_reg, rax +%else + lea w_reg, [.emuedge_v_extend_1 - (.emuedge_v_extend_2 - .emuedge_v_extend_1)+w_reg] +%endif + call w_reg ; fast top extend, body copy and bottom extend +.v_extend_end: + + ; horizontal extend (left/right) + mov w_reg, r6m ; start_x + sub r0, w_reg +%if ARCH_X86_64 + mov r3, r0 ; backup of buf+block_h*linesize + mov r5, r8 +%else + mov r0m, r0 ; backup of buf+block_h*linesize + mov r5, r5m +%endif + test w_reg, w_reg + jz .right_extend + cmp w_reg, 22 + jg .slow_left_extend_loop + mov r1, w_reg + dec w_reg + ; FIXME we can do a if size == 1 here if that makes any speed difference, test me + sar w_reg, 1 + sal w_reg, 6 + ; r0=buf+block_h*linesize,r7(64)/r6(32)=start_x offset for funcs + ; r6(rax)/r3(ebx)=val,r2=linesize,r1=start_x,r5=block_h +%ifdef PIC + lea rax, [.emuedge_extend_left_2] + add w_reg, rax +%else + lea w_reg, [.emuedge_extend_left_2+w_reg] +%endif + call w_reg + + ; now r3(64)/r0(32)=buf,r2=linesize,r8/r5=block_h,r6/r3=val, r7/r6=end_x, r1=block_w +.right_extend: +%if ARCH_X86_32 + mov r0, r0m + mov r5, r5m +%endif + mov w_reg, r7m ; end_x + mov r1, r8m ; block_w + mov r4, r1 + sub r1, w_reg + jz .h_extend_end ; if (end_x == block_w) goto h_extend_end + cmp r1, 22 + jg .slow_right_extend_loop + dec r1 + ; FIXME we can do a if size == 1 here if that makes any speed difference, test me + sar r1, 1 + sal r1, 6 +%ifdef PIC + lea rax, [.emuedge_extend_right_2] + add r1, rax +%else + lea r1, [.emuedge_extend_right_2+r1] +%endif + call r1 +.h_extend_end: + RET + +%if ARCH_X86_64 +%define vall al +%define valh ah +%define valw ax +%define valw2 r7w +%define valw3 r3w +%if WIN64 +%define valw4 r7w +%else ; unix64 +%define valw4 r3w +%endif +%define vald eax +%else +%define vall bl +%define valh bh +%define valw bx +%define valw2 r6w +%define valw3 valw2 +%define valw4 valw3 +%define vald ebx +%define stack_offset 0x14 +%endif + +%endmacro + +; macro to read/write a horizontal number of pixels (%2) to/from registers +; on x86-64, - fills xmm0-15 for consecutive sets of 16 pixels +; - if (%2 & 15 == 8) fills the last 8 bytes into rax +; - else if (%2 & 8) fills 8 bytes into mm0 +; - if (%2 & 7 == 4) fills the last 4 bytes into rax +; - else if (%2 & 4) fills 4 bytes into mm0-1 +; - if (%2 & 3 == 3) fills 2 bytes into r7/r3, and 1 into eax +; (note that we're using r3 for body/bottom because it's a shorter +; opcode, and then the loop fits in 128 bytes) +; - else fills remaining bytes into rax +; on x86-32, - fills mm0-7 for consecutive sets of 8 pixels +; - if (%2 & 7 == 4) fills 4 bytes into ebx +; - else if (%2 & 4) fills 4 bytes into mm0-7 +; - if (%2 & 3 == 3) fills 2 bytes into r6, and 1 into ebx +; - else fills remaining bytes into ebx +; writing data out is in the same way +%macro READ_NUM_BYTES 2 +%assign %%src_off 0 ; offset in source buffer +%assign %%smidx 0 ; mmx register idx +%assign %%sxidx 0 ; xmm register idx + +%if cpuflag(sse) +%rep %2/16 + movups xmm %+ %%sxidx, [r1+%%src_off] +%assign %%src_off %%src_off+16 +%assign %%sxidx %%sxidx+1 +%endrep ; %2/16 +%endif + +%if ARCH_X86_64 +%if (%2-%%src_off) == 8 + mov rax, [r1+%%src_off] +%assign %%src_off %%src_off+8 +%endif ; (%2-%%src_off) == 8 +%endif ; x86-64 + +%rep (%2-%%src_off)/8 + movq mm %+ %%smidx, [r1+%%src_off] +%assign %%src_off %%src_off+8 +%assign %%smidx %%smidx+1 +%endrep ; (%2-%%dst_off)/8 + +%if (%2-%%src_off) == 4 + mov vald, [r1+%%src_off] +%elif (%2-%%src_off) & 4 + movd mm %+ %%smidx, [r1+%%src_off] +%assign %%src_off %%src_off+4 +%endif ; (%2-%%src_off) ==/& 4 + +%if (%2-%%src_off) == 1 + mov vall, [r1+%%src_off] +%elif (%2-%%src_off) == 2 + mov valw, [r1+%%src_off] +%elif (%2-%%src_off) == 3 +%ifidn %1, top + mov valw2, [r1+%%src_off] +%elifidn %1, body + mov valw3, [r1+%%src_off] +%elifidn %1, bottom + mov valw4, [r1+%%src_off] +%endif ; %1 ==/!= top + mov vall, [r1+%%src_off+2] +%endif ; (%2-%%src_off) == 1/2/3 +%endmacro ; READ_NUM_BYTES + +%macro WRITE_NUM_BYTES 2 +%assign %%dst_off 0 ; offset in destination buffer +%assign %%dmidx 0 ; mmx register idx +%assign %%dxidx 0 ; xmm register idx + +%if cpuflag(sse) +%rep %2/16 + movups [r0+%%dst_off], xmm %+ %%dxidx +%assign %%dst_off %%dst_off+16 +%assign %%dxidx %%dxidx+1 +%endrep ; %2/16 +%endif + +%if ARCH_X86_64 +%if (%2-%%dst_off) == 8 + mov [r0+%%dst_off], rax +%assign %%dst_off %%dst_off+8 +%endif ; (%2-%%dst_off) == 8 +%endif ; x86-64 + +%rep (%2-%%dst_off)/8 + movq [r0+%%dst_off], mm %+ %%dmidx +%assign %%dst_off %%dst_off+8 +%assign %%dmidx %%dmidx+1 +%endrep ; (%2-%%dst_off)/8 + +%if (%2-%%dst_off) == 4 + mov [r0+%%dst_off], vald +%elif (%2-%%dst_off) & 4 + movd [r0+%%dst_off], mm %+ %%dmidx +%assign %%dst_off %%dst_off+4 +%endif ; (%2-%%dst_off) ==/& 4 + +%if (%2-%%dst_off) == 1 + mov [r0+%%dst_off], vall +%elif (%2-%%dst_off) == 2 + mov [r0+%%dst_off], valw +%elif (%2-%%dst_off) == 3 +%ifidn %1, top + mov [r0+%%dst_off], valw2 +%elifidn %1, body + mov [r0+%%dst_off], valw3 +%elifidn %1, bottom + mov [r0+%%dst_off], valw4 +%endif ; %1 ==/!= top + mov [r0+%%dst_off+2], vall +%endif ; (%2-%%dst_off) == 1/2/3 +%endmacro ; WRITE_NUM_BYTES + +; vertical top/bottom extend and body copy fast loops +; these are function pointers to set-width line copy functions, i.e. +; they read a fixed number of pixels into set registers, and write +; those out into the destination buffer +; r0=buf,r1=src,r2=linesize,r3(64)/r3m(32)=start_x,r4=end_y,r5=block_h +; r6(eax/64)/r3(ebx/32)=val_reg +%macro VERTICAL_EXTEND 0 +%assign %%n 1 +%rep 22 +ALIGN 128 +.emuedge_v_extend_ %+ %%n: + ; extend pixels above body +%if ARCH_X86_64 + test r3 , r3 ; if (!start_y) + jz .emuedge_copy_body_ %+ %%n %+ _loop ; goto body +%else ; ARCH_X86_32 + cmp dword r3m, 0 + je .emuedge_copy_body_ %+ %%n %+ _loop +%endif ; ARCH_X86_64/32 + READ_NUM_BYTES top, %%n ; read bytes +.emuedge_extend_top_ %+ %%n %+ _loop: ; do { + WRITE_NUM_BYTES top, %%n ; write bytes + add r0 , r2 ; dst += linesize +%if ARCH_X86_64 + dec r3d +%else ; ARCH_X86_32 + dec dword r3m +%endif ; ARCH_X86_64/32 + jnz .emuedge_extend_top_ %+ %%n %+ _loop ; } while (--start_y) + + ; copy body pixels +.emuedge_copy_body_ %+ %%n %+ _loop: ; do { + READ_NUM_BYTES body, %%n ; read bytes + WRITE_NUM_BYTES body, %%n ; write bytes + add r0 , r2 ; dst += linesize + add r1 , r2 ; src += linesize + dec r4d + jnz .emuedge_copy_body_ %+ %%n %+ _loop ; } while (--end_y) + + ; copy bottom pixels + test r5 , r5 ; if (!block_h) + jz .emuedge_v_extend_end_ %+ %%n ; goto end + sub r1 , r2 ; src -= linesize + READ_NUM_BYTES bottom, %%n ; read bytes +.emuedge_extend_bottom_ %+ %%n %+ _loop: ; do { + WRITE_NUM_BYTES bottom, %%n ; write bytes + add r0 , r2 ; dst += linesize + dec r5d + jnz .emuedge_extend_bottom_ %+ %%n %+ _loop ; } while (--block_h) + +.emuedge_v_extend_end_ %+ %%n: +%if ARCH_X86_64 + ret +%else ; ARCH_X86_32 + rep ret +%endif ; ARCH_X86_64/32 +%assign %%n %%n+1 +%endrep +%endmacro VERTICAL_EXTEND + +; left/right (horizontal) fast extend functions +; these are essentially identical to the vertical extend ones above, +; just left/right separated because number of pixels to extend is +; obviously not the same on both sides. +; for reading, pixels are placed in eax (x86-64) or ebx (x86-64) in the +; lowest two bytes of the register (so val*0x0101), and are splatted +; into each byte of mm0 as well if n_pixels >= 8 + +%macro READ_V_PIXEL 2 + mov vall, %2 + mov valh, vall +%if %1 >= 8 + movd mm0, vald +%if cpuflag(mmxext) + pshufw mm0, mm0, 0 +%else ; mmx + punpcklwd mm0, mm0 + punpckldq mm0, mm0 +%endif ; sse +%endif ; %1 >= 8 +%endmacro + +%macro WRITE_V_PIXEL 2 +%assign %%dst_off 0 +%rep %1/8 + movq [%2+%%dst_off], mm0 +%assign %%dst_off %%dst_off+8 +%endrep +%if %1 & 4 +%if %1 >= 8 + movd [%2+%%dst_off], mm0 +%else ; %1 < 8 + mov [%2+%%dst_off] , valw + mov [%2+%%dst_off+2], valw +%endif ; %1 >=/< 8 +%assign %%dst_off %%dst_off+4 +%endif ; %1 & 4 +%if %1&2 + mov [%2+%%dst_off], valw +%endif ; %1 & 2 +%endmacro + +; r0=buf+block_h*linesize, r1=start_x, r2=linesize, r5=block_h, r6/r3=val +%macro LEFT_EXTEND 0 +%assign %%n 2 +%rep 11 +ALIGN 64 +.emuedge_extend_left_ %+ %%n: ; do { + sub r0, r2 ; dst -= linesize + READ_V_PIXEL %%n, [r0+r1] ; read pixels + WRITE_V_PIXEL %%n, r0 ; write pixels + dec r5 + jnz .emuedge_extend_left_ %+ %%n ; } while (--block_h) +%if ARCH_X86_64 + ret +%else ; ARCH_X86_32 + rep ret +%endif ; ARCH_X86_64/32 +%assign %%n %%n+2 +%endrep +%endmacro ; LEFT_EXTEND + +; r3/r0=buf+block_h*linesize, r2=linesize, r8/r5=block_h, r0/r6=end_x, r6/r3=val +%macro RIGHT_EXTEND 0 +%assign %%n 2 +%rep 11 +ALIGN 64 +.emuedge_extend_right_ %+ %%n: ; do { +%if ARCH_X86_64 + sub r3, r2 ; dst -= linesize + READ_V_PIXEL %%n, [r3+w_reg-1] ; read pixels + WRITE_V_PIXEL %%n, r3+r4-%%n ; write pixels + dec r8 +%else ; ARCH_X86_32 + sub r0, r2 ; dst -= linesize + READ_V_PIXEL %%n, [r0+w_reg-1] ; read pixels + WRITE_V_PIXEL %%n, r0+r4-%%n ; write pixels + dec r5 +%endif ; ARCH_X86_64/32 + jnz .emuedge_extend_right_ %+ %%n ; } while (--block_h) +%if ARCH_X86_64 + ret +%else ; ARCH_X86_32 + rep ret +%endif ; ARCH_X86_64/32 +%assign %%n %%n+2 +%endrep + +%if ARCH_X86_32 +%define stack_offset 0x10 +%endif +%endmacro ; RIGHT_EXTEND + +; below follow the "slow" copy/extend functions, these act on a non-fixed +; width specified in a register, and run a loop to copy the full amount +; of bytes. They are optimized for copying of large amounts of pixels per +; line, so they unconditionally splat data into mm registers to copy 8 +; bytes per loop iteration. It could be considered to use xmm for x86-64 +; also, but I haven't optimized this as much (i.e. FIXME) +%macro V_COPY_NPX 4-5 +%if %0 == 4 + test w_reg, %4 + jz .%1_skip_%4_px +%else ; %0 == 5 +.%1_%4_px_loop: +%endif + %3 %2, [r1+cnt_reg] + %3 [r0+cnt_reg], %2 + add cnt_reg, %4 +%if %0 == 5 + sub w_reg, %4 + test w_reg, %5 + jnz .%1_%4_px_loop +%endif +.%1_skip_%4_px: +%endmacro + +%macro V_COPY_ROW 2 +%ifidn %1, bottom + sub r1, linesize +%endif +.%1_copy_loop: + xor cnt_reg, cnt_reg +%if notcpuflag(sse) +%define linesize r2m + V_COPY_NPX %1, mm0, movq, 8, 0xFFFFFFF8 +%else ; sse + V_COPY_NPX %1, xmm0, movups, 16, 0xFFFFFFF0 +%if ARCH_X86_64 +%define linesize r2 + V_COPY_NPX %1, rax , mov, 8 +%else ; ARCH_X86_32 +%define linesize r2m + V_COPY_NPX %1, mm0, movq, 8 +%endif ; ARCH_X86_64/32 +%endif ; sse + V_COPY_NPX %1, vald, mov, 4 + V_COPY_NPX %1, valw, mov, 2 + V_COPY_NPX %1, vall, mov, 1 + mov w_reg, cnt_reg +%ifidn %1, body + add r1, linesize +%endif + add r0, linesize + dec %2 + jnz .%1_copy_loop +%endmacro + +%macro SLOW_V_EXTEND 0 +.slow_v_extend_loop: +; r0=buf,r1=src,r2(64)/r2m(32)=linesize,r3(64)/r3m(32)=start_x,r4=end_y,r5=block_h +; r8(64)/r3(later-64)/r2(32)=cnt_reg,r6(64)/r3(32)=val_reg,r7(64)/r6(32)=w=end_x-start_x +%if ARCH_X86_64 + push r8 ; save old value of block_h + test r3, r3 +%define cnt_reg r8 + jz .do_body_copy ; if (!start_y) goto do_body_copy + V_COPY_ROW top, r3 +%else + cmp dword r3m, 0 +%define cnt_reg r2 + je .do_body_copy ; if (!start_y) goto do_body_copy + V_COPY_ROW top, dword r3m +%endif + +.do_body_copy: + V_COPY_ROW body, r4 + +%if ARCH_X86_64 + pop r8 ; restore old value of block_h +%define cnt_reg r3 +%endif + test r5, r5 +%if ARCH_X86_64 + jz .v_extend_end +%else + jz .skip_bottom_extend +%endif + V_COPY_ROW bottom, r5 +%if ARCH_X86_32 +.skip_bottom_extend: + mov r2, r2m +%endif + jmp .v_extend_end +%endmacro + +%macro SLOW_LEFT_EXTEND 0 +.slow_left_extend_loop: +; r0=buf+block_h*linesize,r2=linesize,r6(64)/r3(32)=val,r5=block_h,r4=cntr,r7/r6=start_x + mov r4, 8 + sub r0, linesize + READ_V_PIXEL 8, [r0+w_reg] +.left_extend_8px_loop: + movq [r0+r4-8], mm0 + add r4, 8 + cmp r4, w_reg + jle .left_extend_8px_loop + sub r4, 8 + cmp r4, w_reg + jge .left_extend_loop_end +.left_extend_2px_loop: + mov [r0+r4], valw + add r4, 2 + cmp r4, w_reg + jl .left_extend_2px_loop +.left_extend_loop_end: + dec r5 + jnz .slow_left_extend_loop +%if ARCH_X86_32 + mov r2, r2m +%endif + jmp .right_extend +%endmacro + +%macro SLOW_RIGHT_EXTEND 0 +.slow_right_extend_loop: +; r3(64)/r0(32)=buf+block_h*linesize,r2=linesize,r4=block_w,r8(64)/r5(32)=block_h, +; r7(64)/r6(32)=end_x,r6/r3=val,r1=cntr +%if ARCH_X86_64 +%define buf_reg r3 +%define bh_reg r8 +%else +%define buf_reg r0 +%define bh_reg r5 +%endif + lea r1, [r4-8] + sub buf_reg, linesize + READ_V_PIXEL 8, [buf_reg+w_reg-1] +.right_extend_8px_loop: + movq [buf_reg+r1], mm0 + sub r1, 8 + cmp r1, w_reg + jge .right_extend_8px_loop + add r1, 8 + cmp r1, w_reg + je .right_extend_loop_end +.right_extend_2px_loop: + sub r1, 2 + mov [buf_reg+r1], valw + cmp r1, w_reg + jg .right_extend_2px_loop +.right_extend_loop_end: + dec bh_reg + jnz .slow_right_extend_loop + jmp .h_extend_end +%endmacro + +%macro emu_edge 1 +INIT_XMM %1 +EMU_EDGE_FUNC +VERTICAL_EXTEND +LEFT_EXTEND +RIGHT_EXTEND +SLOW_V_EXTEND +SLOW_LEFT_EXTEND +SLOW_RIGHT_EXTEND +%endmacro + +emu_edge sse +%if ARCH_X86_32 +emu_edge mmx +%endif + +%macro PREFETCH_FN 1 +cglobal prefetch, 3, 3, 0, buf, stride, h +.loop: + %1 [bufq] + add bufq, strideq + dec hd + jg .loop + REP_RET +%endmacro + +INIT_MMX mmxext +PREFETCH_FN prefetcht0 +%if ARCH_X86_32 +INIT_MMX 3dnow +PREFETCH_FN prefetch +%endif diff --git a/ffmpeg/libavcodec/x86/videodsp_init.c b/ffmpeg/libavcodec/x86/videodsp_init.c new file mode 100644 index 0000000..902450e --- /dev/null +++ b/ffmpeg/libavcodec/x86/videodsp_init.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2002-2012 Michael Niedermayer + * Copyright (C) 2012 Ronald S. Bultje + * + * 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 "config.h" +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/videodsp.h" + +#if HAVE_YASM +typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src, + x86_reg linesize, x86_reg start_y, + x86_reg end_y, x86_reg block_h, + x86_reg start_x, x86_reg end_x, + x86_reg block_w); +extern emu_edge_core_func ff_emu_edge_core_mmx; +extern emu_edge_core_func ff_emu_edge_core_sse; + +static av_always_inline void emulated_edge_mc(uint8_t *buf, const uint8_t *src, + ptrdiff_t linesize_arg, + int block_w, int block_h, + int src_x, int src_y, + int w, int h, + emu_edge_core_func *core_fn) +{ + int start_y, start_x, end_y, end_x, src_y_add = 0; + int linesize = linesize_arg; + + if(!w || !h) + return; + + if (src_y >= h) { + src -= src_y*linesize; + src_y_add = h - 1; + src_y = h - 1; + } else if (src_y <= -block_h) { + src -= src_y*linesize; + src_y_add = 1 - block_h; + src_y = 1 - block_h; + } + if (src_x >= w) { + src += w - 1 - src_x; + src_x = w - 1; + } else if (src_x <= -block_w) { + src += 1 - block_w - src_x; + src_x = 1 - block_w; + } + + start_y = FFMAX(0, -src_y); + start_x = FFMAX(0, -src_x); + end_y = FFMIN(block_h, h-src_y); + end_x = FFMIN(block_w, w-src_x); + av_assert2(start_x < end_x && block_w > 0); + av_assert2(start_y < end_y && block_h > 0); + + // fill in the to-be-copied part plus all above/below + src += (src_y_add + start_y) * linesize + start_x; + buf += start_x; + core_fn(buf, src, linesize, start_y, end_y, + block_h, start_x, end_x, block_w); +} + +#if ARCH_X86_32 +static av_noinline void emulated_edge_mc_mmx(uint8_t *buf, const uint8_t *src, + ptrdiff_t linesize, + int block_w, int block_h, + int src_x, int src_y, int w, int h) +{ + emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y, + w, h, &ff_emu_edge_core_mmx); +} +#endif + +static av_noinline void emulated_edge_mc_sse(uint8_t *buf, const uint8_t *src, + ptrdiff_t linesize, + int block_w, int block_h, + int src_x, int src_y, int w, int h) +{ + emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y, + w, h, &ff_emu_edge_core_sse); +} +#endif /* HAVE_YASM */ + +void ff_prefetch_mmxext(uint8_t *buf, ptrdiff_t stride, int h); +void ff_prefetch_3dnow(uint8_t *buf, ptrdiff_t stride, int h); + +av_cold void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc) +{ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + +#if ARCH_X86_32 + if (bpc <= 8 && mm_flags & AV_CPU_FLAG_MMX) { + ctx->emulated_edge_mc = emulated_edge_mc_mmx; + } + if (mm_flags & AV_CPU_FLAG_3DNOW) { + ctx->prefetch = ff_prefetch_3dnow; + } +#endif /* ARCH_X86_32 */ + if (mm_flags & AV_CPU_FLAG_MMXEXT) { + ctx->prefetch = ff_prefetch_mmxext; + } + if (bpc <= 8 && mm_flags & AV_CPU_FLAG_SSE) { + ctx->emulated_edge_mc = emulated_edge_mc_sse; + } +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/vorbisdsp.asm b/ffmpeg/libavcodec/x86/vorbisdsp.asm new file mode 100644 index 0000000..b25d838 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vorbisdsp.asm @@ -0,0 +1,83 @@ +;****************************************************************************** +;* Vorbis x86 optimizations +;* Copyright (C) 2006 Loren Merritt +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +pdw_80000000: times 4 dd 0x80000000 + +SECTION .text + +%if ARCH_X86_32 +INIT_MMX 3dnow +cglobal vorbis_inverse_coupling, 3, 3, 6, mag, ang, block_size + pxor m7, m7 + lea magq, [magq+block_sizeq*4] + lea angq, [angq+block_sizeq*4] + neg block_sizeq +.loop: + mova m0, [magq+block_sizeq*4] + mova m1, [angq+block_sizeq*4] + mova m2, m0 + mova m3, m1 + pfcmpge m2, m7 ; m <= 0.0 + pfcmpge m3, m7 ; a <= 0.0 + pslld m2, 31 ; keep only the sign bit + pxor m1, m2 + mova m4, m3 + pand m3, m1 + pandn m4, m1 + pfadd m3, m0 ; a = m + ((a < 0) & (a ^ sign(m))) + pfsub m0, m4 ; m = m + ((a > 0) & (a ^ sign(m))) + mova [angq+block_sizeq*4], m3 + mova [magq+block_sizeq*4], m0 + add block_sizeq, 2 + jl .loop + femms + RET +%endif + +INIT_XMM sse +cglobal vorbis_inverse_coupling, 3, 4, 6, mag, ang, block_size, cntr + mova m5, [pdw_80000000] + xor cntrq, cntrq +align 16 +.loop: + mova m0, [magq+cntrq*4] + mova m1, [angq+cntrq*4] + xorps m2, m2 + xorps m3, m3 + cmpleps m2, m0 ; m <= 0.0 + cmpleps m3, m1 ; a <= 0.0 + andps m2, m5 ; keep only the sign bit + xorps m1, m2 + mova m4, m3 + andps m3, m1 + andnps m4, m1 + addps m3, m0 ; a = m + ((a < 0) & (a ^ sign(m))) + subps m0, m4 ; m = m + ((a > 0) & (a ^ sign(m))) + mova [angq+cntrq*4], m3 + mova [magq+cntrq*4], m0 + add cntrq, 4 + cmp cntrq, block_sizeq + jl .loop + RET diff --git a/ffmpeg/libavcodec/x86/vorbisdsp_init.c b/ffmpeg/libavcodec/x86/vorbisdsp_init.c new file mode 100644 index 0000000..08a2c09 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vorbisdsp_init.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2006 Loren Merritt + * + * 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 "config.h" +#include "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavcodec/vorbisdsp.h" + +void ff_vorbis_inverse_coupling_3dnow(float *mag, float *ang, + intptr_t blocksize); +void ff_vorbis_inverse_coupling_sse(float *mag, float *ang, + intptr_t blocksize); + +av_cold void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp) +{ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + +#if ARCH_X86_32 + if (mm_flags & AV_CPU_FLAG_3DNOW) + dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_3dnow; +#endif /* ARCH_X86_32 */ + if (mm_flags & AV_CPU_FLAG_SSE) + dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_sse; +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/vp3dsp.asm b/ffmpeg/libavcodec/x86/vp3dsp.asm new file mode 100644 index 0000000..a47b8f2 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp3dsp.asm @@ -0,0 +1,709 @@ +;****************************************************************************** +;* MMX/SSE2-optimized functions for the VP3 decoder +;* Copyright (c) 2007 Aurelien Jacobs +;* +;* 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 "libavutil/x86/x86util.asm" + +; MMX-optimized functions cribbed from the original VP3 source code. + +SECTION_RODATA + +vp3_idct_data: times 8 dw 64277 + times 8 dw 60547 + times 8 dw 54491 + times 8 dw 46341 + times 8 dw 36410 + times 8 dw 25080 + times 8 dw 12785 + +pb_7: times 8 db 7 +pb_1F: times 8 db 0x1f +pb_81: times 8 db 0x81 + +cextern pb_1 +cextern pb_3 +cextern pb_80 + +cextern pw_8 + +SECTION .text + +; this is off by one or two for some cases when filter_limit is greater than 63 +; in: p0 in mm6, p1 in mm4, p2 in mm2, p3 in mm1 +; out: p1 in mm4, p2 in mm3 +%macro VP3_LOOP_FILTER 0 + movq m7, m6 + pand m6, [pb_7] ; p0&7 + psrlw m7, 3 + pand m7, [pb_1F] ; p0>>3 + movq m3, m2 ; p2 + pxor m2, m4 + pand m2, [pb_1] ; (p2^p1)&1 + movq m5, m2 + paddb m2, m2 + paddb m2, m5 ; 3*(p2^p1)&1 + paddb m2, m6 ; extra bits lost in shifts + pcmpeqb m0, m0 + pxor m1, m0 ; 255 - p3 + pavgb m1, m2 ; (256 - p3 + extrabits) >> 1 + pxor m0, m4 ; 255 - p1 + pavgb m0, m3 ; (256 + p2-p1) >> 1 + paddb m1, [pb_3] + pavgb m1, m0 ; 128+2+( p2-p1 - p3) >> 2 + pavgb m1, m0 ; 128+1+(3*(p2-p1) - p3) >> 3 + paddusb m7, m1 ; d+128+1 + movq m6, [pb_81] + psubusb m6, m7 + psubusb m7, [pb_81] + + movq m5, [r2+516] ; flim + pminub m6, m5 + pminub m7, m5 + movq m0, m6 + movq m1, m7 + paddb m6, m6 + paddb m7, m7 + pminub m6, m5 + pminub m7, m5 + psubb m6, m0 + psubb m7, m1 + paddusb m4, m7 + psubusb m4, m6 + psubusb m3, m7 + paddusb m3, m6 +%endmacro + +%macro STORE_4_WORDS 1 + movd r2d, %1 + mov [r0 -1], r2w + psrlq %1, 32 + shr r2, 16 + mov [r0+r1 -1], r2w + movd r2d, %1 + mov [r0+r1*2-1], r2w + shr r2, 16 + mov [r0+r3 -1], r2w +%endmacro + +INIT_MMX mmxext +cglobal vp3_v_loop_filter, 3, 4 +%if ARCH_X86_64 + movsxd r1, r1d +%endif + mov r3, r1 + neg r1 + movq m6, [r0+r1*2] + movq m4, [r0+r1 ] + movq m2, [r0 ] + movq m1, [r0+r3 ] + + VP3_LOOP_FILTER + + movq [r0+r1], m4 + movq [r0 ], m3 + RET + +cglobal vp3_h_loop_filter, 3, 4 +%if ARCH_X86_64 + movsxd r1, r1d +%endif + lea r3, [r1*3] + + movd m6, [r0 -2] + movd m4, [r0+r1 -2] + movd m2, [r0+r1*2-2] + movd m1, [r0+r3 -2] + lea r0, [r0+r1*4 ] + punpcklbw m6, [r0 -2] + punpcklbw m4, [r0+r1 -2] + punpcklbw m2, [r0+r1*2-2] + punpcklbw m1, [r0+r3 -2] + sub r0, r3 + sub r0, r1 + + TRANSPOSE4x4B 6, 4, 2, 1, 0 + VP3_LOOP_FILTER + SBUTTERFLY bw, 4, 3, 5 + + STORE_4_WORDS m4 + lea r0, [r0+r1*4 ] + STORE_4_WORDS m3 + RET + +; from original comments: The Macro does IDct on 4 1-D Dcts +%macro BeginIDCT 0 + movq m2, I(3) + movq m6, C(3) + movq m4, m2 + movq m7, J(5) + pmulhw m4, m6 ; r4 = c3*i3 - i3 + movq m1, C(5) + pmulhw m6, m7 ; r6 = c3*i5 - i5 + movq m5, m1 + pmulhw m1, m2 ; r1 = c5*i3 - i3 + movq m3, I(1) + pmulhw m5, m7 ; r5 = c5*i5 - i5 + movq m0, C(1) + paddw m4, m2 ; r4 = c3*i3 + paddw m6, m7 ; r6 = c3*i5 + paddw m2, m1 ; r2 = c5*i3 + movq m1, J(7) + paddw m7, m5 ; r7 = c5*i5 + movq m5, m0 ; r5 = c1 + pmulhw m0, m3 ; r0 = c1*i1 - i1 + paddsw m4, m7 ; r4 = C = c3*i3 + c5*i5 + pmulhw m5, m1 ; r5 = c1*i7 - i7 + movq m7, C(7) + psubsw m6, m2 ; r6 = D = c3*i5 - c5*i3 + paddw m0, m3 ; r0 = c1*i1 + pmulhw m3, m7 ; r3 = c7*i1 + movq m2, I(2) + pmulhw m7, m1 ; r7 = c7*i7 + paddw m5, m1 ; r5 = c1*i7 + movq m1, m2 ; r1 = i2 + pmulhw m2, C(2) ; r2 = c2*i2 - i2 + psubsw m3, m5 ; r3 = B = c7*i1 - c1*i7 + movq m5, J(6) + paddsw m0, m7 ; r0 = A = c1*i1 + c7*i7 + movq m7, m5 ; r7 = i6 + psubsw m0, m4 ; r0 = A - C + pmulhw m5, C(2) ; r5 = c2*i6 - i6 + paddw m2, m1 ; r2 = c2*i2 + pmulhw m1, C(6) ; r1 = c6*i2 + paddsw m4, m4 ; r4 = C + C + paddsw m4, m0 ; r4 = C. = A + C + psubsw m3, m6 ; r3 = B - D + paddw m5, m7 ; r5 = c2*i6 + paddsw m6, m6 ; r6 = D + D + pmulhw m7, C(6) ; r7 = c6*i6 + paddsw m6, m3 ; r6 = D. = B + D + movq I(1), m4 ; save C. at I(1) + psubsw m1, m5 ; r1 = H = c6*i2 - c2*i6 + movq m4, C(4) + movq m5, m3 ; r5 = B - D + pmulhw m3, m4 ; r3 = (c4 - 1) * (B - D) + paddsw m7, m2 ; r3 = (c4 - 1) * (B - D) + movq I(2), m6 ; save D. at I(2) + movq m2, m0 ; r2 = A - C + movq m6, I(0) + pmulhw m0, m4 ; r0 = (c4 - 1) * (A - C) + paddw m5, m3 ; r5 = B. = c4 * (B - D) + movq m3, J(4) + psubsw m5, m1 ; r5 = B.. = B. - H + paddw m2, m0 ; r0 = A. = c4 * (A - C) + psubsw m6, m3 ; r6 = i0 - i4 + movq m0, m6 + pmulhw m6, m4 ; r6 = (c4 - 1) * (i0 - i4) + paddsw m3, m3 ; r3 = i4 + i4 + paddsw m1, m1 ; r1 = H + H + paddsw m3, m0 ; r3 = i0 + i4 + paddsw m1, m5 ; r1 = H. = B + H + pmulhw m4, m3 ; r4 = (c4 - 1) * (i0 + i4) + paddsw m6, m0 ; r6 = F = c4 * (i0 - i4) + psubsw m6, m2 ; r6 = F. = F - A. + paddsw m2, m2 ; r2 = A. + A. + movq m0, I(1) ; r0 = C. + paddsw m2, m6 ; r2 = A.. = F + A. + paddw m4, m3 ; r4 = E = c4 * (i0 + i4) + psubsw m2, m1 ; r2 = R2 = A.. - H. +%endmacro + +; RowIDCT gets ready to transpose +%macro RowIDCT 0 + BeginIDCT + movq m3, I(2) ; r3 = D. + psubsw m4, m7 ; r4 = E. = E - G + paddsw m1, m1 ; r1 = H. + H. + paddsw m7, m7 ; r7 = G + G + paddsw m1, m2 ; r1 = R1 = A.. + H. + paddsw m7, m4 ; r1 = R1 = A.. + H. + psubsw m4, m3 ; r4 = R4 = E. - D. + paddsw m3, m3 + psubsw m6, m5 ; r6 = R6 = F. - B.. + paddsw m5, m5 + paddsw m3, m4 ; r3 = R3 = E. + D. + paddsw m5, m6 ; r5 = R5 = F. + B.. + psubsw m7, m0 ; r7 = R7 = G. - C. + paddsw m0, m0 + movq I(1), m1 ; save R1 + paddsw m0, m7 ; r0 = R0 = G. + C. +%endmacro + +; Column IDCT normalizes and stores final results +%macro ColumnIDCT 0 + BeginIDCT + paddsw m2, OC_8 ; adjust R2 (and R1) for shift + paddsw m1, m1 ; r1 = H. + H. + paddsw m1, m2 ; r1 = R1 = A.. + H. + psraw m2, 4 ; r2 = NR2 + psubsw m4, m7 ; r4 = E. = E - G + psraw m1, 4 ; r1 = NR2 + movq m3, I(2) ; r3 = D. + paddsw m7, m7 ; r7 = G + G + movq I(2), m2 ; store NR2 at I2 + paddsw m7, m4 ; r7 = G. = E + G + movq I(1), m1 ; store NR1 at I1 + psubsw m4, m3 ; r4 = R4 = E. - D. + paddsw m4, OC_8 ; adjust R4 (and R3) for shift + paddsw m3, m3 ; r3 = D. + D. + paddsw m3, m4 ; r3 = R3 = E. + D. + psraw m4, 4 ; r4 = NR4 + psubsw m6, m5 ; r6 = R6 = F. - B.. + psraw m3, 4 ; r3 = NR3 + paddsw m6, OC_8 ; adjust R6 (and R5) for shift + paddsw m5, m5 ; r5 = B.. + B.. + paddsw m5, m6 ; r5 = R5 = F. + B.. + psraw m6, 4 ; r6 = NR6 + movq J(4), m4 ; store NR4 at J4 + psraw m5, 4 ; r5 = NR5 + movq I(3), m3 ; store NR3 at I3 + psubsw m7, m0 ; r7 = R7 = G. - C. + paddsw m7, OC_8 ; adjust R7 (and R0) for shift + paddsw m0, m0 ; r0 = C. + C. + paddsw m0, m7 ; r0 = R0 = G. + C. + psraw m7, 4 ; r7 = NR7 + movq J(6), m6 ; store NR6 at J6 + psraw m0, 4 ; r0 = NR0 + movq J(5), m5 ; store NR5 at J5 + movq J(7), m7 ; store NR7 at J7 + movq I(0), m0 ; store NR0 at I0 +%endmacro + +; Following macro does two 4x4 transposes in place. +; +; At entry (we assume): +; +; r0 = a3 a2 a1 a0 +; I(1) = b3 b2 b1 b0 +; r2 = c3 c2 c1 c0 +; r3 = d3 d2 d1 d0 +; +; r4 = e3 e2 e1 e0 +; r5 = f3 f2 f1 f0 +; r6 = g3 g2 g1 g0 +; r7 = h3 h2 h1 h0 +; +; At exit, we have: +; +; I(0) = d0 c0 b0 a0 +; I(1) = d1 c1 b1 a1 +; I(2) = d2 c2 b2 a2 +; I(3) = d3 c3 b3 a3 +; +; J(4) = h0 g0 f0 e0 +; J(5) = h1 g1 f1 e1 +; J(6) = h2 g2 f2 e2 +; J(7) = h3 g3 f3 e3 +; +; I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3. +; J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7. +; +; Since r1 is free at entry, we calculate the Js first. +%macro Transpose 0 + movq m1, m4 ; r1 = e3 e2 e1 e0 + punpcklwd m4, m5 ; r4 = f1 e1 f0 e0 + movq I(0), m0 ; save a3 a2 a1 a0 + punpckhwd m1, m5 ; r1 = f3 e3 f2 e2 + movq m0, m6 ; r0 = g3 g2 g1 g0 + punpcklwd m6, m7 ; r6 = h1 g1 h0 g0 + movq m5, m4 ; r5 = f1 e1 f0 e0 + punpckldq m4, m6 ; r4 = h0 g0 f0 e0 = R4 + punpckhdq m5, m6 ; r5 = h1 g1 f1 e1 = R5 + movq m6, m1 ; r6 = f3 e3 f2 e2 + movq J(4), m4 + punpckhwd m0, m7 ; r0 = h3 g3 h2 g2 + movq J(5), m5 + punpckhdq m6, m0 ; r6 = h3 g3 f3 e3 = R7 + movq m4, I(0) ; r4 = a3 a2 a1 a0 + punpckldq m1, m0 ; r1 = h2 g2 f2 e2 = R6 + movq m5, I(1) ; r5 = b3 b2 b1 b0 + movq m0, m4 ; r0 = a3 a2 a1 a0 + movq J(7), m6 + punpcklwd m0, m5 ; r0 = b1 a1 b0 a0 + movq J(6), m1 + punpckhwd m4, m5 ; r4 = b3 a3 b2 a2 + movq m5, m2 ; r5 = c3 c2 c1 c0 + punpcklwd m2, m3 ; r2 = d1 c1 d0 c0 + movq m1, m0 ; r1 = b1 a1 b0 a0 + punpckldq m0, m2 ; r0 = d0 c0 b0 a0 = R0 + punpckhdq m1, m2 ; r1 = d1 c1 b1 a1 = R1 + movq m2, m4 ; r2 = b3 a3 b2 a2 + movq I(0), m0 + punpckhwd m5, m3 ; r5 = d3 c3 d2 c2 + movq I(1), m1 + punpckhdq m4, m5 ; r4 = d3 c3 b3 a3 = R3 + punpckldq m2, m5 ; r2 = d2 c2 b2 a2 = R2 + movq I(3), m4 + movq I(2), m2 +%endmacro + +%macro VP3_1D_IDCT_SSE2 0 + movdqa m2, I(3) ; xmm2 = i3 + movdqa m6, C(3) ; xmm6 = c3 + movdqa m4, m2 ; xmm4 = i3 + movdqa m7, I(5) ; xmm7 = i5 + pmulhw m4, m6 ; xmm4 = c3 * i3 - i3 + movdqa m1, C(5) ; xmm1 = c5 + pmulhw m6, m7 ; xmm6 = c3 * i5 - i5 + movdqa m5, m1 ; xmm5 = c5 + pmulhw m1, m2 ; xmm1 = c5 * i3 - i3 + movdqa m3, I(1) ; xmm3 = i1 + pmulhw m5, m7 ; xmm5 = c5 * i5 - i5 + movdqa m0, C(1) ; xmm0 = c1 + paddw m4, m2 ; xmm4 = c3 * i3 + paddw m6, m7 ; xmm6 = c3 * i5 + paddw m2, m1 ; xmm2 = c5 * i3 + movdqa m1, I(7) ; xmm1 = i7 + paddw m7, m5 ; xmm7 = c5 * i5 + movdqa m5, m0 ; xmm5 = c1 + pmulhw m0, m3 ; xmm0 = c1 * i1 - i1 + paddsw m4, m7 ; xmm4 = c3 * i3 + c5 * i5 = C + pmulhw m5, m1 ; xmm5 = c1 * i7 - i7 + movdqa m7, C(7) ; xmm7 = c7 + psubsw m6, m2 ; xmm6 = c3 * i5 - c5 * i3 = D + paddw m0, m3 ; xmm0 = c1 * i1 + pmulhw m3, m7 ; xmm3 = c7 * i1 + movdqa m2, I(2) ; xmm2 = i2 + pmulhw m7, m1 ; xmm7 = c7 * i7 + paddw m5, m1 ; xmm5 = c1 * i7 + movdqa m1, m2 ; xmm1 = i2 + pmulhw m2, C(2) ; xmm2 = i2 * c2 -i2 + psubsw m3, m5 ; xmm3 = c7 * i1 - c1 * i7 = B + movdqa m5, I(6) ; xmm5 = i6 + paddsw m0, m7 ; xmm0 = c1 * i1 + c7 * i7 = A + movdqa m7, m5 ; xmm7 = i6 + psubsw m0, m4 ; xmm0 = A - C + pmulhw m5, C(2) ; xmm5 = c2 * i6 - i6 + paddw m2, m1 ; xmm2 = i2 * c2 + pmulhw m1, C(6) ; xmm1 = c6 * i2 + paddsw m4, m4 ; xmm4 = C + C + paddsw m4, m0 ; xmm4 = A + C = C. + psubsw m3, m6 ; xmm3 = B - D + paddw m5, m7 ; xmm5 = c2 * i6 + paddsw m6, m6 ; xmm6 = D + D + pmulhw m7, C(6) ; xmm7 = c6 * i6 + paddsw m6, m3 ; xmm6 = B + D = D. + movdqa I(1), m4 ; Save C. at I(1) + psubsw m1, m5 ; xmm1 = c6 * i2 - c2 * i6 = H + movdqa m4, C(4) ; xmm4 = C4 + movdqa m5, m3 ; xmm5 = B - D + pmulhw m3, m4 ; xmm3 = ( c4 -1 ) * ( B - D ) + paddsw m7, m2 ; xmm7 = c2 * i2 + c6 * i6 = G + movdqa I(2), m6 ; save D. at I(2) + movdqa m2, m0 ; xmm2 = A - C + movdqa m6, I(0) ; xmm6 = i0 + pmulhw m0, m4 ; xmm0 = ( c4 - 1 ) * ( A - C ) = A. + paddw m5, m3 ; xmm5 = c4 * ( B - D ) = B. + movdqa m3, I(4) ; xmm3 = i4 + psubsw m5, m1 ; xmm5 = B. - H = B.. + paddw m2, m0 ; xmm2 = c4 * ( A - C) = A. + psubsw m6, m3 ; xmm6 = i0 - i4 + movdqa m0, m6 ; xmm0 = i0 - i4 + pmulhw m6, m4 ; xmm6 = (c4 - 1) * (i0 - i4) = F + paddsw m3, m3 ; xmm3 = i4 + i4 + paddsw m1, m1 ; xmm1 = H + H + paddsw m3, m0 ; xmm3 = i0 + i4 + paddsw m1, m5 ; xmm1 = B. + H = H. + pmulhw m4, m3 ; xmm4 = ( c4 - 1 ) * ( i0 + i4 ) + paddw m6, m0 ; xmm6 = c4 * ( i0 - i4 ) + psubsw m6, m2 ; xmm6 = F - A. = F. + paddsw m2, m2 ; xmm2 = A. + A. + movdqa m0, I(1) ; Load C. from I(1) + paddsw m2, m6 ; xmm2 = F + A. = A.. + paddw m4, m3 ; xmm4 = c4 * ( i0 + i4 ) = 3 + psubsw m2, m1 ; xmm2 = A.. - H. = R2 + ADD(m2) ; Adjust R2 and R1 before shifting + paddsw m1, m1 ; xmm1 = H. + H. + paddsw m1, m2 ; xmm1 = A.. + H. = R1 + SHIFT(m2) ; xmm2 = op2 + psubsw m4, m7 ; xmm4 = E - G = E. + SHIFT(m1) ; xmm1 = op1 + movdqa m3, I(2) ; Load D. from I(2) + paddsw m7, m7 ; xmm7 = G + G + paddsw m7, m4 ; xmm7 = E + G = G. + psubsw m4, m3 ; xmm4 = E. - D. = R4 + ADD(m4) ; Adjust R4 and R3 before shifting + paddsw m3, m3 ; xmm3 = D. + D. + paddsw m3, m4 ; xmm3 = E. + D. = R3 + SHIFT(m4) ; xmm4 = op4 + psubsw m6, m5 ; xmm6 = F. - B..= R6 + SHIFT(m3) ; xmm3 = op3 + ADD(m6) ; Adjust R6 and R5 before shifting + paddsw m5, m5 ; xmm5 = B.. + B.. + paddsw m5, m6 ; xmm5 = F. + B.. = R5 + SHIFT(m6) ; xmm6 = op6 + SHIFT(m5) ; xmm5 = op5 + psubsw m7, m0 ; xmm7 = G. - C. = R7 + ADD(m7) ; Adjust R7 and R0 before shifting + paddsw m0, m0 ; xmm0 = C. + C. + paddsw m0, m7 ; xmm0 = G. + C. + SHIFT(m7) ; xmm7 = op7 + SHIFT(m0) ; xmm0 = op0 +%endmacro + +%macro PUT_BLOCK 8 + movdqa O(0), m%1 + movdqa O(1), m%2 + movdqa O(2), m%3 + movdqa O(3), m%4 + movdqa O(4), m%5 + movdqa O(5), m%6 + movdqa O(6), m%7 + movdqa O(7), m%8 +%endmacro + +%macro VP3_IDCT 1 +%if mmsize == 16 +%define I(x) [%1+16*x] +%define O(x) [%1+16*x] +%define C(x) [vp3_idct_data+16*(x-1)] +%define SHIFT(x) +%define ADD(x) + VP3_1D_IDCT_SSE2 +%if ARCH_X86_64 + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, 8 +%else + TRANSPOSE8x8W 0, 1, 2, 3, 4, 5, 6, 7, [%1], [%1+16] +%endif + PUT_BLOCK 0, 1, 2, 3, 4, 5, 6, 7 + +%define SHIFT(x) psraw x, 4 +%define ADD(x) paddsw x, [pw_8] + VP3_1D_IDCT_SSE2 + PUT_BLOCK 0, 1, 2, 3, 4, 5, 6, 7 +%else ; mmsize == 8 + ; eax = quantized input + ; ebx = dequantizer matrix + ; ecx = IDCT constants + ; M(I) = ecx + MaskOffset(0) + I * 8 + ; C(I) = ecx + CosineOffset(32) + (I-1) * 8 + ; edx = output + ; r0..r7 = mm0..mm7 +%define OC_8 [pw_8] +%define C(x) [vp3_idct_data+16*(x-1)] + + ; at this point, function has completed dequantization + dezigzag + + ; partial transposition; now do the idct itself +%define I(x) [%1+16*x] +%define J(x) [%1+16*x] + RowIDCT + Transpose + +%define I(x) [%1+16*x+8] +%define J(x) [%1+16*x+8] + RowIDCT + Transpose + +%define I(x) [%1+16* x] +%define J(x) [%1+16*(x-4)+8] + ColumnIDCT + +%define I(x) [%1+16* x +64] +%define J(x) [%1+16*(x-4)+72] + ColumnIDCT +%endif ; mmsize == 16/8 +%endmacro + +%macro vp3_idct_funcs 0 +cglobal vp3_idct_put, 3, 4, 9 + VP3_IDCT r2 + + movsxdifnidn r1, r1d + mova m4, [pb_80] + lea r3, [r1*3] +%assign %%i 0 +%rep 16/mmsize + mova m0, [r2+mmsize*0+%%i] + mova m1, [r2+mmsize*2+%%i] + mova m2, [r2+mmsize*4+%%i] + mova m3, [r2+mmsize*6+%%i] +%if mmsize == 8 + packsswb m0, [r2+mmsize*8+%%i] + packsswb m1, [r2+mmsize*10+%%i] + packsswb m2, [r2+mmsize*12+%%i] + packsswb m3, [r2+mmsize*14+%%i] +%else + packsswb m0, [r2+mmsize*1+%%i] + packsswb m1, [r2+mmsize*3+%%i] + packsswb m2, [r2+mmsize*5+%%i] + packsswb m3, [r2+mmsize*7+%%i] +%endif + paddb m0, m4 + paddb m1, m4 + paddb m2, m4 + paddb m3, m4 + movq [r0 ], m0 +%if mmsize == 8 + movq [r0+r1 ], m1 + movq [r0+r1*2], m2 + movq [r0+r3 ], m3 +%else + movhps [r0+r1 ], m0 + movq [r0+r1*2], m1 + movhps [r0+r3 ], m1 +%endif +%if %%i == 0 + lea r0, [r0+r1*4] +%endif +%if mmsize == 16 + movq [r0 ], m2 + movhps [r0+r1 ], m2 + movq [r0+r1*2], m3 + movhps [r0+r3 ], m3 +%endif +%assign %%i %%i+8 +%endrep + + pxor m0, m0 +%assign %%offset 0 +%rep 128/mmsize + mova [r2+%%offset], m0 +%assign %%offset %%offset+mmsize +%endrep + RET + +cglobal vp3_idct_add, 3, 4, 9 + VP3_IDCT r2 + + movsxdifnidn r1, r1d + lea r3, [r1*3] + pxor m4, m4 +%if mmsize == 16 +%assign %%i 0 +%rep 2 + movq m0, [r0] + movq m1, [r0+r1] + movq m2, [r0+r1*2] + movq m3, [r0+r3] + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpcklbw m3, m4 + paddsw m0, [r2+ 0+%%i] + paddsw m1, [r2+16+%%i] + paddsw m2, [r2+32+%%i] + paddsw m3, [r2+48+%%i] + packuswb m0, m1 + packuswb m2, m3 + movq [r0 ], m0 + movhps [r0+r1 ], m0 + movq [r0+r1*2], m2 + movhps [r0+r3 ], m2 +%if %%i == 0 + lea r0, [r0+r1*4] +%endif +%assign %%i %%i+64 +%endrep +%else +%assign %%i 0 +%rep 2 + movq m0, [r0] + movq m1, [r0+r1] + movq m2, [r0+r1*2] + movq m3, [r0+r3] + movq m5, m0 + movq m6, m1 + movq m7, m2 + punpcklbw m0, m4 + punpcklbw m1, m4 + punpcklbw m2, m4 + punpckhbw m5, m4 + punpckhbw m6, m4 + punpckhbw m7, m4 + paddsw m0, [r2+ 0+%%i] + paddsw m1, [r2+16+%%i] + paddsw m2, [r2+32+%%i] + paddsw m5, [r2+64+%%i] + paddsw m6, [r2+80+%%i] + paddsw m7, [r2+96+%%i] + packuswb m0, m5 + movq m5, m3 + punpcklbw m3, m4 + punpckhbw m5, m4 + packuswb m1, m6 + paddsw m3, [r2+48+%%i] + paddsw m5, [r2+112+%%i] + packuswb m2, m7 + packuswb m3, m5 + movq [r0 ], m0 + movq [r0+r1 ], m1 + movq [r0+r1*2], m2 + movq [r0+r3 ], m3 +%if %%i == 0 + lea r0, [r0+r1*4] +%endif +%assign %%i %%i+8 +%endrep +%endif +%assign %%i 0 +%rep 128/mmsize + mova [r2+%%i], m4 +%assign %%i %%i+mmsize +%endrep + RET +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +vp3_idct_funcs +%endif + +INIT_XMM sse2 +vp3_idct_funcs + +%macro DC_ADD 0 + movq m2, [r0 ] + movq m3, [r0+r1 ] + paddusb m2, m0 + movq m4, [r0+r1*2] + paddusb m3, m0 + movq m5, [r0+r2 ] + paddusb m4, m0 + paddusb m5, m0 + psubusb m2, m1 + psubusb m3, m1 + movq [r0 ], m2 + psubusb m4, m1 + movq [r0+r1 ], m3 + psubusb m5, m1 + movq [r0+r1*2], m4 + movq [r0+r2 ], m5 +%endmacro + +INIT_MMX mmxext +cglobal vp3_idct_dc_add, 3, 4 +%if ARCH_X86_64 + movsxd r1, r1d +%endif + movsx r3, word [r2] + mov word [r2], 0 + lea r2, [r1*3] + add r3, 15 + sar r3, 5 + movd m0, r3d + pshufw m0, m0, 0x0 + pxor m1, m1 + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 + DC_ADD + lea r0, [r0+r1*4] + DC_ADD + RET diff --git a/ffmpeg/libavcodec/x86/vp3dsp_init.c b/ffmpeg/libavcodec/x86/vp3dsp_init.c new file mode 100644 index 0000000..252b40a --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp3dsp_init.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2009 David Conrad + * + * 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 "libavutil/attributes.h" +#include "libavutil/cpu.h" +#include "libavutil/x86/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/dsputil.h" +#include "libavcodec/vp3dsp.h" +#include "config.h" + +void ff_vp3_idct_put_mmx(uint8_t *dest, int line_size, int16_t *block); +void ff_vp3_idct_add_mmx(uint8_t *dest, int line_size, int16_t *block); + +void ff_vp3_idct_put_sse2(uint8_t *dest, int line_size, int16_t *block); +void ff_vp3_idct_add_sse2(uint8_t *dest, int line_size, int16_t *block); + +void ff_vp3_idct_dc_add_mmxext(uint8_t *dest, int line_size, + int16_t *block); + +void ff_vp3_v_loop_filter_mmxext(uint8_t *src, int stride, + int *bounding_values); +void ff_vp3_h_loop_filter_mmxext(uint8_t *src, int stride, + int *bounding_values); + +#if HAVE_INLINE_ASM + +#define MOVQ_BFE(regd) \ + __asm__ volatile ( \ + "pcmpeqd %%"#regd", %%"#regd" \n\t" \ + "paddb %%"#regd", %%"#regd" \n\t" ::) + +#define PAVGBP_MMX_NO_RND(rega, regb, regr, regc, regd, regp) \ + "movq "#rega", "#regr" \n\t" \ + "movq "#regc", "#regp" \n\t" \ + "pand "#regb", "#regr" \n\t" \ + "pand "#regd", "#regp" \n\t" \ + "pxor "#rega", "#regb" \n\t" \ + "pxor "#regc", "#regd" \n\t" \ + "pand %%mm6, "#regb" \n\t" \ + "pand %%mm6, "#regd" \n\t" \ + "psrlq $1, "#regb" \n\t" \ + "psrlq $1, "#regd" \n\t" \ + "paddb "#regb", "#regr" \n\t" \ + "paddb "#regd", "#regp" \n\t" + +static void put_vp_no_rnd_pixels8_l2_mmx(uint8_t *dst, const uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h) +{ +// START_TIMER + MOVQ_BFE(mm6); + __asm__ volatile( + "1: \n\t" + "movq (%1), %%mm0 \n\t" + "movq (%2), %%mm1 \n\t" + "movq (%1,%4), %%mm2 \n\t" + "movq (%2,%4), %%mm3 \n\t" + PAVGBP_MMX_NO_RND(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, (%3) \n\t" + "movq %%mm5, (%3,%4) \n\t" + + "movq (%1,%4,2), %%mm0 \n\t" + "movq (%2,%4,2), %%mm1 \n\t" + "movq (%1,%5), %%mm2 \n\t" + "movq (%2,%5), %%mm3 \n\t" + "lea (%1,%4,4), %1 \n\t" + "lea (%2,%4,4), %2 \n\t" + PAVGBP_MMX_NO_RND(%%mm0, %%mm1, %%mm4, %%mm2, %%mm3, %%mm5) + "movq %%mm4, (%3,%4,2) \n\t" + "movq %%mm5, (%3,%5) \n\t" + "lea (%3,%4,4), %3 \n\t" + "subl $4, %0 \n\t" + "jnz 1b \n\t" + :"+r"(h), "+r"(a), "+r"(b), "+r"(dst) + :"r"((x86_reg)stride), "r"((x86_reg)3L*stride) + :"memory"); +// STOP_TIMER("put_vp_no_rnd_pixels8_l2_mmx") +} +#endif /* HAVE_INLINE_ASM */ + +av_cold void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags) +{ + int cpuflags = av_get_cpu_flags(); + +#if HAVE_INLINE_ASM + c->put_no_rnd_pixels_l2 = put_vp_no_rnd_pixels8_l2_mmx; +#endif /* HAVE_INLINE_ASM */ + +#if ARCH_X86_32 + if (EXTERNAL_MMX(cpuflags)) { + c->idct_put = ff_vp3_idct_put_mmx; + c->idct_add = ff_vp3_idct_add_mmx; + } +#endif + + if (EXTERNAL_MMXEXT(cpuflags)) { + c->idct_dc_add = ff_vp3_idct_dc_add_mmxext; + + if (!(flags & CODEC_FLAG_BITEXACT)) { + c->v_loop_filter = ff_vp3_v_loop_filter_mmxext; + c->h_loop_filter = ff_vp3_h_loop_filter_mmxext; + } + } + + if (EXTERNAL_SSE2(cpuflags)) { + c->idct_put = ff_vp3_idct_put_sse2; + c->idct_add = ff_vp3_idct_add_sse2; + } +} diff --git a/ffmpeg/libavcodec/x86/vp56_arith.h b/ffmpeg/libavcodec/x86/vp56_arith.h new file mode 100644 index 0000000..e71dbf8 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp56_arith.h @@ -0,0 +1,54 @@ +/** + * VP5 and VP6 compatible video decoder (arith decoder) + * + * Copyright (C) 2006 Aurelien Jacobs + * Copyright (C) 2010 Eli Friedman + * + * 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 + */ + +#ifndef AVCODEC_X86_VP56_ARITH_H +#define AVCODEC_X86_VP56_ARITH_H + +#if HAVE_INLINE_ASM && HAVE_FAST_CMOV +#define vp56_rac_get_prob vp56_rac_get_prob +static av_always_inline int vp56_rac_get_prob(VP56RangeCoder *c, uint8_t prob) +{ + unsigned int code_word = vp56_rac_renorm(c); + unsigned int high = c->high; + unsigned int low = 1 + (((high - 1) * prob) >> 8); + unsigned int low_shift = low << 16; + int bit = 0; + + __asm__( + "subl %4, %1 \n\t" + "subl %3, %2 \n\t" + "leal (%2, %3), %3 \n\t" + "setae %b0 \n\t" + "cmovb %4, %1 \n\t" + "cmovb %3, %2 \n\t" + : "+q"(bit), "+r"(high), "+r"(code_word), "+r"(low_shift) + : "r"(low) + ); + + c->high = high; + c->code_word = code_word; + return bit; +} +#endif + +#endif /* AVCODEC_X86_VP56_ARITH_H */ diff --git a/ffmpeg/libavcodec/x86/vp56dsp.asm b/ffmpeg/libavcodec/x86/vp56dsp.asm new file mode 100644 index 0000000..3d874ea --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp56dsp.asm @@ -0,0 +1,170 @@ +;****************************************************************************** +;* MMX/SSE2-optimized functions for the VP6 decoder +;* Copyright (C) 2009 Sebastien Lucas +;* Copyright (C) 2009 Zuxy Meng +;* +;* 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 "libavutil/x86/x86util.asm" + +cextern pw_64 + +SECTION .text + +%macro DIAG4 6 +%if mmsize == 8 + movq m0, [%1+%2] + movq m1, [%1+%3] + movq m3, m0 + movq m4, m1 + punpcklbw m0, m7 + punpcklbw m1, m7 + punpckhbw m3, m7 + punpckhbw m4, m7 + pmullw m0, [rsp+8*11] ; src[x-8 ] * biweight [0] + pmullw m1, [rsp+8*12] ; src[x ] * biweight [1] + pmullw m3, [rsp+8*11] ; src[x-8 ] * biweight [0] + pmullw m4, [rsp+8*12] ; src[x ] * biweight [1] + paddw m0, m1 + paddw m3, m4 + movq m1, [%1+%4] + movq m2, [%1+%5] + movq m4, m1 + movq m5, m2 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpckhbw m4, m7 + punpckhbw m5, m7 + pmullw m1, [rsp+8*13] ; src[x+8 ] * biweight [2] + pmullw m2, [rsp+8*14] ; src[x+16] * biweight [3] + pmullw m4, [rsp+8*13] ; src[x+8 ] * biweight [2] + pmullw m5, [rsp+8*14] ; src[x+16] * biweight [3] + paddw m1, m2 + paddw m4, m5 + paddsw m0, m1 + paddsw m3, m4 + paddsw m0, m6 ; Add 64 + paddsw m3, m6 ; Add 64 + psraw m0, 7 + psraw m3, 7 + packuswb m0, m3 + movq [%6], m0 +%else ; mmsize == 16 + movq m0, [%1+%2] + movq m1, [%1+%3] + punpcklbw m0, m7 + punpcklbw m1, m7 + pmullw m0, m4 ; src[x-8 ] * biweight [0] + pmullw m1, m5 ; src[x ] * biweight [1] + paddw m0, m1 + movq m1, [%1+%4] + movq m2, [%1+%5] + punpcklbw m1, m7 + punpcklbw m2, m7 + pmullw m1, m6 ; src[x+8 ] * biweight [2] + pmullw m2, m3 ; src[x+16] * biweight [3] + paddw m1, m2 + paddsw m0, m1 + paddsw m0, [pw_64] ; Add 64 + psraw m0, 7 + packuswb m0, m0 + movq [%6], m0 +%endif ; mmsize == 8/16 +%endmacro + +%macro SPLAT4REGS 0 +%if mmsize == 8 + movq m5, m3 + punpcklwd m3, m3 + movq m4, m3 + punpckldq m3, m3 + punpckhdq m4, m4 + punpckhwd m5, m5 + movq m2, m5 + punpckhdq m2, m2 + punpckldq m5, m5 + movq [rsp+8*11], m3 + movq [rsp+8*12], m4 + movq [rsp+8*13], m5 + movq [rsp+8*14], m2 +%else ; mmsize == 16 + pshuflw m4, m3, 0x0 + pshuflw m5, m3, 0x55 + pshuflw m6, m3, 0xAA + pshuflw m3, m3, 0xFF + punpcklqdq m4, m4 + punpcklqdq m5, m5 + punpcklqdq m6, m6 + punpcklqdq m3, m3 +%endif ; mmsize == 8/16 +%endmacro + +%macro vp6_filter_diag4 0 +; void ff_vp6_filter_diag4_(uint8_t *dst, uint8_t *src, int stride, +; const int16_t h_weight[4], const int16_t v_weights[4]) +cglobal vp6_filter_diag4, 5, 7, 8 + mov r5, rsp ; backup stack pointer + and rsp, ~(mmsize-1) ; align stack +%if mmsize == 16 + sub rsp, 8*11 +%else + sub rsp, 8*15 + movq m6, [pw_64] +%endif +%if ARCH_X86_64 + movsxd r2, r2d +%endif + + sub r1, r2 + + pxor m7, m7 + movq m3, [r3] + SPLAT4REGS + + mov r3, rsp + mov r6, 11 +.nextrow: + DIAG4 r1, -1, 0, 1, 2, r3 + add r3, 8 + add r1, r2 + dec r6 + jnz .nextrow + + movq m3, [r4] + SPLAT4REGS + + lea r3, [rsp+8] + mov r6, 8 +.nextcol: + DIAG4 r3, -8, 0, 8, 16, r0 + add r3, 8 + add r0, r2 + dec r6 + jnz .nextcol + + mov rsp, r5 ; restore stack pointer + RET +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +vp6_filter_diag4 +%endif + +INIT_XMM sse2 +vp6_filter_diag4 diff --git a/ffmpeg/libavcodec/x86/vp56dsp_init.c b/ffmpeg/libavcodec/x86/vp56dsp_init.c new file mode 100644 index 0000000..defc63b --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp56dsp_init.c @@ -0,0 +1,48 @@ +/* + * VP6 MMX/SSE2 optimizations + * Copyright (C) 2009 Sebastien Lucas + * Copyright (C) 2009 Zuxy Meng + * + * 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 "libavutil/cpu.h" +#include "libavutil/x86/asm.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/vp56dsp.h" + +void ff_vp6_filter_diag4_mmx(uint8_t *dst, uint8_t *src, int stride, + const int16_t *h_weights,const int16_t *v_weights); +void ff_vp6_filter_diag4_sse2(uint8_t *dst, uint8_t *src, int stride, + const int16_t *h_weights,const int16_t *v_weights); + +av_cold void ff_vp56dsp_init_x86(VP56DSPContext* c, enum AVCodecID codec) +{ + int mm_flags = av_get_cpu_flags(); + + if (CONFIG_VP6_DECODER && codec == AV_CODEC_ID_VP6) { +#if ARCH_X86_32 + if (EXTERNAL_MMX(mm_flags)) { + c->vp6_filter_diag4 = ff_vp6_filter_diag4_mmx; + } +#endif + + if (EXTERNAL_SSE2(mm_flags)) { + c->vp6_filter_diag4 = ff_vp6_filter_diag4_sse2; + } + } +} diff --git a/ffmpeg/libavcodec/x86/vp8dsp.asm b/ffmpeg/libavcodec/x86/vp8dsp.asm new file mode 100644 index 0000000..ca07333 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp8dsp.asm @@ -0,0 +1,2780 @@ +;****************************************************************************** +;* VP8 MMXEXT optimizations +;* Copyright (c) 2010 Ronald S. Bultje +;* Copyright (c) 2010 Jason Garrett-Glaser +;* +;* 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 "libavutil/x86/x86util.asm" + +SECTION_RODATA + +fourtap_filter_hw_m: times 4 dw -6, 123 + times 4 dw 12, -1 + times 4 dw -9, 93 + times 4 dw 50, -6 + times 4 dw -6, 50 + times 4 dw 93, -9 + times 4 dw -1, 12 + times 4 dw 123, -6 + +sixtap_filter_hw_m: times 4 dw 2, -11 + times 4 dw 108, 36 + times 4 dw -8, 1 + times 4 dw 3, -16 + times 4 dw 77, 77 + times 4 dw -16, 3 + times 4 dw 1, -8 + times 4 dw 36, 108 + times 4 dw -11, 2 + +fourtap_filter_hb_m: times 8 db -6, 123 + times 8 db 12, -1 + times 8 db -9, 93 + times 8 db 50, -6 + times 8 db -6, 50 + times 8 db 93, -9 + times 8 db -1, 12 + times 8 db 123, -6 + +sixtap_filter_hb_m: times 8 db 2, 1 + times 8 db -11, 108 + times 8 db 36, -8 + times 8 db 3, 3 + times 8 db -16, 77 + times 8 db 77, -16 + times 8 db 1, 2 + times 8 db -8, 36 + times 8 db 108, -11 + +fourtap_filter_v_m: times 8 dw -6 + times 8 dw 123 + times 8 dw 12 + times 8 dw -1 + times 8 dw -9 + times 8 dw 93 + times 8 dw 50 + times 8 dw -6 + times 8 dw -6 + times 8 dw 50 + times 8 dw 93 + times 8 dw -9 + times 8 dw -1 + times 8 dw 12 + times 8 dw 123 + times 8 dw -6 + +sixtap_filter_v_m: times 8 dw 2 + times 8 dw -11 + times 8 dw 108 + times 8 dw 36 + times 8 dw -8 + times 8 dw 1 + times 8 dw 3 + times 8 dw -16 + times 8 dw 77 + times 8 dw 77 + times 8 dw -16 + times 8 dw 3 + times 8 dw 1 + times 8 dw -8 + times 8 dw 36 + times 8 dw 108 + times 8 dw -11 + times 8 dw 2 + +bilinear_filter_vw_m: times 8 dw 1 + times 8 dw 2 + times 8 dw 3 + times 8 dw 4 + times 8 dw 5 + times 8 dw 6 + times 8 dw 7 + +bilinear_filter_vb_m: times 8 db 7, 1 + times 8 db 6, 2 + times 8 db 5, 3 + times 8 db 4, 4 + times 8 db 3, 5 + times 8 db 2, 6 + times 8 db 1, 7 + +%ifdef PIC +%define fourtap_filter_hw picregq +%define sixtap_filter_hw picregq +%define fourtap_filter_hb picregq +%define sixtap_filter_hb picregq +%define fourtap_filter_v picregq +%define sixtap_filter_v picregq +%define bilinear_filter_vw picregq +%define bilinear_filter_vb picregq +%define npicregs 1 +%else +%define fourtap_filter_hw fourtap_filter_hw_m +%define sixtap_filter_hw sixtap_filter_hw_m +%define fourtap_filter_hb fourtap_filter_hb_m +%define sixtap_filter_hb sixtap_filter_hb_m +%define fourtap_filter_v fourtap_filter_v_m +%define sixtap_filter_v sixtap_filter_v_m +%define bilinear_filter_vw bilinear_filter_vw_m +%define bilinear_filter_vb bilinear_filter_vb_m +%define npicregs 0 +%endif + +filter_h2_shuf: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8 +filter_h4_shuf: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 + +filter_h6_shuf1: db 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12 +filter_h6_shuf2: db 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9 +filter_h6_shuf3: db 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11 + +pw_27: times 8 dw 27 +pw_63: times 8 dw 63 +pw_256: times 8 dw 256 +pw_20091: times 4 dw 20091 +pw_17734: times 4 dw 17734 + +pb_4: times 16 db 4 +pb_F8: times 16 db 0xF8 +pb_FE: times 16 db 0xFE +pb_27_63: times 8 db 27, 63 +pb_18_63: times 8 db 18, 63 +pb_9_63: times 8 db 9, 63 + +cextern pb_1 +cextern pw_3 +cextern pb_3 +cextern pw_4 +cextern pw_9 +cextern pw_18 +cextern pw_64 +cextern pb_80 + +SECTION .text + +;----------------------------------------------------------------------------- +; subpel MC functions: +; +; void put_vp8_epel_hv_(uint8_t *dst, int deststride, +; uint8_t *src, int srcstride, +; int height, int mx, int my); +;----------------------------------------------------------------------------- + +%macro FILTER_SSSE3 1 +cglobal put_vp8_epel%1_h6, 6, 6 + npicregs, 8, dst, dststride, src, srcstride, height, mx, picreg + lea mxd, [mxq*3] + mova m3, [filter_h6_shuf2] + mova m4, [filter_h6_shuf3] +%ifdef PIC + lea picregq, [sixtap_filter_hb_m] +%endif + mova m5, [sixtap_filter_hb+mxq*8-48] ; set up 6tap filter in bytes + mova m6, [sixtap_filter_hb+mxq*8-32] + mova m7, [sixtap_filter_hb+mxq*8-16] + +.nextrow: + movu m0, [srcq-2] + mova m1, m0 + mova m2, m0 +%if mmsize == 8 +; For epel4, we need 9 bytes, but only 8 get loaded; to compensate, do the +; shuffle with a memory operand + punpcklbw m0, [srcq+3] +%else + pshufb m0, [filter_h6_shuf1] +%endif + pshufb m1, m3 + pshufb m2, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m6 + pmaddubsw m2, m7 + paddsw m0, m1 + paddsw m0, m2 + pmulhrsw m0, [pw_256] + packuswb m0, m0 + movh [dstq], m0 ; store + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +cglobal put_vp8_epel%1_h4, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, height, mx, picreg + shl mxd, 4 + mova m2, [pw_256] + mova m3, [filter_h2_shuf] + mova m4, [filter_h4_shuf] +%ifdef PIC + lea picregq, [fourtap_filter_hb_m] +%endif + mova m5, [fourtap_filter_hb+mxq-16] ; set up 4tap filter in bytes + mova m6, [fourtap_filter_hb+mxq] + +.nextrow: + movu m0, [srcq-1] + mova m1, m0 + pshufb m0, m3 + pshufb m1, m4 + pmaddubsw m0, m5 + pmaddubsw m1, m6 + paddsw m0, m1 + pmulhrsw m0, m2 + packuswb m0, m0 + movh [dstq], m0 ; store + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my + shl myd, 4 +%ifdef PIC + lea picregq, [fourtap_filter_hb_m] +%endif + mova m5, [fourtap_filter_hb+myq-16] + mova m6, [fourtap_filter_hb+myq] + mova m7, [pw_256] + + ; read 3 lines + sub srcq, srcstrideq + movh m0, [srcq] + movh m1, [srcq+ srcstrideq] + movh m2, [srcq+2*srcstrideq] + add srcq, srcstrideq + +.nextrow: + movh m3, [srcq+2*srcstrideq] ; read new row + mova m4, m0 + mova m0, m1 + punpcklbw m4, m1 + mova m1, m2 + punpcklbw m2, m3 + pmaddubsw m4, m5 + pmaddubsw m2, m6 + paddsw m4, m2 + mova m2, m3 + pmulhrsw m4, m7 + packuswb m4, m4 + movh [dstq], m4 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my + lea myd, [myq*3] +%ifdef PIC + lea picregq, [sixtap_filter_hb_m] +%endif + lea myq, [sixtap_filter_hb+myq*8] + + ; read 5 lines + sub srcq, srcstrideq + sub srcq, srcstrideq + movh m0, [srcq] + movh m1, [srcq+srcstrideq] + movh m2, [srcq+srcstrideq*2] + lea srcq, [srcq+srcstrideq*2] + add srcq, srcstrideq + movh m3, [srcq] + movh m4, [srcq+srcstrideq] + +.nextrow: + movh m5, [srcq+2*srcstrideq] ; read new row + mova m6, m0 + punpcklbw m6, m5 + mova m0, m1 + punpcklbw m1, m2 + mova m7, m3 + punpcklbw m7, m4 + pmaddubsw m6, [myq-48] + pmaddubsw m1, [myq-32] + pmaddubsw m7, [myq-16] + paddsw m6, m1 + paddsw m6, m7 + mova m1, m2 + mova m2, m3 + pmulhrsw m6, [pw_256] + mova m3, m4 + packuswb m6, m6 + mova m4, m5 + movh [dstq], m6 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET +%endmacro + +INIT_MMX ssse3 +FILTER_SSSE3 4 +INIT_XMM ssse3 +FILTER_SSSE3 8 + +; 4x4 block, H-only 4-tap filter +INIT_MMX mmxext +cglobal put_vp8_epel4_h4, 6, 6 + npicregs, 0, dst, dststride, src, srcstride, height, mx, picreg + shl mxd, 4 +%ifdef PIC + lea picregq, [fourtap_filter_hw_m] +%endif + movq mm4, [fourtap_filter_hw+mxq-16] ; set up 4tap filter in words + movq mm5, [fourtap_filter_hw+mxq] + movq mm7, [pw_64] + pxor mm6, mm6 + +.nextrow: + movq mm1, [srcq-1] ; (ABCDEFGH) load 8 horizontal pixels + + ; first set of 2 pixels + movq mm2, mm1 ; byte ABCD.. + punpcklbw mm1, mm6 ; byte->word ABCD + pshufw mm0, mm2, 9 ; byte CDEF.. + punpcklbw mm0, mm6 ; byte->word CDEF + pshufw mm3, mm1, 0x94 ; word ABBC + pshufw mm1, mm0, 0x94 ; word CDDE + pmaddwd mm3, mm4 ; multiply 2px with F0/F1 + movq mm0, mm1 ; backup for second set of pixels + pmaddwd mm1, mm5 ; multiply 2px with F2/F3 + paddd mm3, mm1 ; finish 1st 2px + + ; second set of 2 pixels, use backup of above + punpckhbw mm2, mm6 ; byte->word EFGH + pmaddwd mm0, mm4 ; multiply backed up 2px with F0/F1 + pshufw mm1, mm2, 0x94 ; word EFFG + pmaddwd mm1, mm5 ; multiply 2px with F2/F3 + paddd mm0, mm1 ; finish 2nd 2px + + ; merge two sets of 2 pixels into one set of 4, round/clip/store + packssdw mm3, mm0 ; merge dword->word (4px) + paddsw mm3, mm7 ; rounding + psraw mm3, 7 + packuswb mm3, mm6 ; clip and word->bytes + movd [dstq], mm3 ; store + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +; 4x4 block, H-only 6-tap filter +INIT_MMX mmxext +cglobal put_vp8_epel4_h6, 6, 6 + npicregs, 0, dst, dststride, src, srcstride, height, mx, picreg + lea mxd, [mxq*3] +%ifdef PIC + lea picregq, [sixtap_filter_hw_m] +%endif + movq mm4, [sixtap_filter_hw+mxq*8-48] ; set up 4tap filter in words + movq mm5, [sixtap_filter_hw+mxq*8-32] + movq mm6, [sixtap_filter_hw+mxq*8-16] + movq mm7, [pw_64] + pxor mm3, mm3 + +.nextrow: + movq mm1, [srcq-2] ; (ABCDEFGH) load 8 horizontal pixels + + ; first set of 2 pixels + movq mm2, mm1 ; byte ABCD.. + punpcklbw mm1, mm3 ; byte->word ABCD + pshufw mm0, mm2, 0x9 ; byte CDEF.. + punpckhbw mm2, mm3 ; byte->word EFGH + punpcklbw mm0, mm3 ; byte->word CDEF + pshufw mm1, mm1, 0x94 ; word ABBC + pshufw mm2, mm2, 0x94 ; word EFFG + pmaddwd mm1, mm4 ; multiply 2px with F0/F1 + pshufw mm3, mm0, 0x94 ; word CDDE + movq mm0, mm3 ; backup for second set of pixels + pmaddwd mm3, mm5 ; multiply 2px with F2/F3 + paddd mm1, mm3 ; add to 1st 2px cache + movq mm3, mm2 ; backup for second set of pixels + pmaddwd mm2, mm6 ; multiply 2px with F4/F5 + paddd mm1, mm2 ; finish 1st 2px + + ; second set of 2 pixels, use backup of above + movd mm2, [srcq+3] ; byte FGHI (prevent overreads) + pmaddwd mm0, mm4 ; multiply 1st backed up 2px with F0/F1 + pmaddwd mm3, mm5 ; multiply 2nd backed up 2px with F2/F3 + paddd mm0, mm3 ; add to 2nd 2px cache + pxor mm3, mm3 + punpcklbw mm2, mm3 ; byte->word FGHI + pshufw mm2, mm2, 0xE9 ; word GHHI + pmaddwd mm2, mm6 ; multiply 2px with F4/F5 + paddd mm0, mm2 ; finish 2nd 2px + + ; merge two sets of 2 pixels into one set of 4, round/clip/store + packssdw mm1, mm0 ; merge dword->word (4px) + paddsw mm1, mm7 ; rounding + psraw mm1, 7 + packuswb mm1, mm3 ; clip and word->bytes + movd [dstq], mm1 ; store + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +INIT_XMM sse2 +cglobal put_vp8_epel8_h4, 6, 6 + npicregs, 10, dst, dststride, src, srcstride, height, mx, picreg + shl mxd, 5 +%ifdef PIC + lea picregq, [fourtap_filter_v_m] +%endif + lea mxq, [fourtap_filter_v+mxq-32] + pxor m7, m7 + mova m4, [pw_64] + mova m5, [mxq+ 0] + mova m6, [mxq+16] +%ifdef m8 + mova m8, [mxq+32] + mova m9, [mxq+48] +%endif +.nextrow: + movq m0, [srcq-1] + movq m1, [srcq-0] + movq m2, [srcq+1] + movq m3, [srcq+2] + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + pmullw m0, m5 + pmullw m1, m6 +%ifdef m8 + pmullw m2, m8 + pmullw m3, m9 +%else + pmullw m2, [mxq+32] + pmullw m3, [mxq+48] +%endif + paddsw m0, m1 + paddsw m2, m3 + paddsw m0, m2 + paddsw m0, m4 + psraw m0, 7 + packuswb m0, m7 + movh [dstq], m0 ; store + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +INIT_XMM sse2 +cglobal put_vp8_epel8_h6, 6, 6 + npicregs, 14, dst, dststride, src, srcstride, height, mx, picreg + lea mxd, [mxq*3] + shl mxd, 4 +%ifdef PIC + lea picregq, [sixtap_filter_v_m] +%endif + lea mxq, [sixtap_filter_v+mxq-96] + pxor m7, m7 + mova m6, [pw_64] +%ifdef m8 + mova m8, [mxq+ 0] + mova m9, [mxq+16] + mova m10, [mxq+32] + mova m11, [mxq+48] + mova m12, [mxq+64] + mova m13, [mxq+80] +%endif +.nextrow: + movq m0, [srcq-2] + movq m1, [srcq-1] + movq m2, [srcq-0] + movq m3, [srcq+1] + movq m4, [srcq+2] + movq m5, [srcq+3] + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + punpcklbw m5, m7 +%ifdef m8 + pmullw m0, m8 + pmullw m1, m9 + pmullw m2, m10 + pmullw m3, m11 + pmullw m4, m12 + pmullw m5, m13 +%else + pmullw m0, [mxq+ 0] + pmullw m1, [mxq+16] + pmullw m2, [mxq+32] + pmullw m3, [mxq+48] + pmullw m4, [mxq+64] + pmullw m5, [mxq+80] +%endif + paddsw m1, m4 + paddsw m0, m5 + paddsw m1, m2 + paddsw m0, m3 + paddsw m0, m1 + paddsw m0, m6 + psraw m0, 7 + packuswb m0, m7 + movh [dstq], m0 ; store + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + +%macro FILTER_V 1 +; 4x4 block, V-only 4-tap filter +cglobal put_vp8_epel%1_v4, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my + shl myd, 5 +%ifdef PIC + lea picregq, [fourtap_filter_v_m] +%endif + lea myq, [fourtap_filter_v+myq-32] + mova m6, [pw_64] + pxor m7, m7 + mova m5, [myq+48] + + ; read 3 lines + sub srcq, srcstrideq + movh m0, [srcq] + movh m1, [srcq+ srcstrideq] + movh m2, [srcq+2*srcstrideq] + add srcq, srcstrideq + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + +.nextrow: + ; first calculate negative taps (to prevent losing positive overflows) + movh m4, [srcq+2*srcstrideq] ; read new row + punpcklbw m4, m7 + mova m3, m4 + pmullw m0, [myq+0] + pmullw m4, m5 + paddsw m4, m0 + + ; then calculate positive taps + mova m0, m1 + pmullw m1, [myq+16] + paddsw m4, m1 + mova m1, m2 + pmullw m2, [myq+32] + paddsw m4, m2 + mova m2, m3 + + ; round/clip/store + paddsw m4, m6 + psraw m4, 7 + packuswb m4, m7 + movh [dstq], m4 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET + + +; 4x4 block, V-only 6-tap filter +cglobal put_vp8_epel%1_v6, 7, 7, 8, dst, dststride, src, srcstride, height, picreg, my + shl myd, 4 + lea myq, [myq*3] +%ifdef PIC + lea picregq, [sixtap_filter_v_m] +%endif + lea myq, [sixtap_filter_v+myq-96] + pxor m7, m7 + + ; read 5 lines + sub srcq, srcstrideq + sub srcq, srcstrideq + movh m0, [srcq] + movh m1, [srcq+srcstrideq] + movh m2, [srcq+srcstrideq*2] + lea srcq, [srcq+srcstrideq*2] + add srcq, srcstrideq + movh m3, [srcq] + movh m4, [srcq+srcstrideq] + punpcklbw m0, m7 + punpcklbw m1, m7 + punpcklbw m2, m7 + punpcklbw m3, m7 + punpcklbw m4, m7 + +.nextrow: + ; first calculate negative taps (to prevent losing positive overflows) + mova m5, m1 + pmullw m5, [myq+16] + mova m6, m4 + pmullw m6, [myq+64] + paddsw m6, m5 + + ; then calculate positive taps + movh m5, [srcq+2*srcstrideq] ; read new row + punpcklbw m5, m7 + pmullw m0, [myq+0] + paddsw m6, m0 + mova m0, m1 + mova m1, m2 + pmullw m2, [myq+32] + paddsw m6, m2 + mova m2, m3 + pmullw m3, [myq+48] + paddsw m6, m3 + mova m3, m4 + mova m4, m5 + pmullw m5, [myq+80] + paddsw m6, m5 + + ; round/clip/store + paddsw m6, [pw_64] + psraw m6, 7 + packuswb m6, m7 + movh [dstq], m6 + + ; go to next line + add dstq, dststrideq + add srcq, srcstrideq + dec heightd ; next row + jg .nextrow + REP_RET +%endmacro + +INIT_MMX mmxext +FILTER_V 4 +INIT_XMM sse2 +FILTER_V 8 + +%macro FILTER_BILINEAR 1 +cglobal put_vp8_bilinear%1_v, 7, 7, 7, dst, dststride, src, srcstride, height, picreg, my + shl myd, 4 +%ifdef PIC + lea picregq, [bilinear_filter_vw_m] +%endif + pxor m6, m6 + mova m5, [bilinear_filter_vw+myq-1*16] + neg myq + mova m4, [bilinear_filter_vw+myq+7*16] +.nextrow: + movh m0, [srcq+srcstrideq*0] + movh m1, [srcq+srcstrideq*1] + movh m3, [srcq+srcstrideq*2] + punpcklbw m0, m6 + punpcklbw m1, m6 + punpcklbw m3, m6 + mova m2, m1 + pmullw m0, m4 + pmullw m1, m5 + pmullw m2, m4 + pmullw m3, m5 + paddsw m0, m1 + paddsw m2, m3 + psraw m0, 2 + psraw m2, 2 + pavgw m0, m6 + pavgw m2, m6 +%if mmsize == 8 + packuswb m0, m0 + packuswb m2, m2 + movh [dstq+dststrideq*0], m0 + movh [dstq+dststrideq*1], m2 +%else + packuswb m0, m2 + movh [dstq+dststrideq*0], m0 + movhps [dstq+dststrideq*1], m0 +%endif + + lea dstq, [dstq+dststrideq*2] + lea srcq, [srcq+srcstrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET + +cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 7, dst, dststride, src, srcstride, height, mx, picreg + shl mxd, 4 +%ifdef PIC + lea picregq, [bilinear_filter_vw_m] +%endif + pxor m6, m6 + mova m5, [bilinear_filter_vw+mxq-1*16] + neg mxq + mova m4, [bilinear_filter_vw+mxq+7*16] +.nextrow: + movh m0, [srcq+srcstrideq*0+0] + movh m1, [srcq+srcstrideq*0+1] + movh m2, [srcq+srcstrideq*1+0] + movh m3, [srcq+srcstrideq*1+1] + punpcklbw m0, m6 + punpcklbw m1, m6 + punpcklbw m2, m6 + punpcklbw m3, m6 + pmullw m0, m4 + pmullw m1, m5 + pmullw m2, m4 + pmullw m3, m5 + paddsw m0, m1 + paddsw m2, m3 + psraw m0, 2 + psraw m2, 2 + pavgw m0, m6 + pavgw m2, m6 +%if mmsize == 8 + packuswb m0, m0 + packuswb m2, m2 + movh [dstq+dststrideq*0], m0 + movh [dstq+dststrideq*1], m2 +%else + packuswb m0, m2 + movh [dstq+dststrideq*0], m0 + movhps [dstq+dststrideq*1], m0 +%endif + + lea dstq, [dstq+dststrideq*2] + lea srcq, [srcq+srcstrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET +%endmacro + +INIT_MMX mmxext +FILTER_BILINEAR 4 +INIT_XMM sse2 +FILTER_BILINEAR 8 + +%macro FILTER_BILINEAR_SSSE3 1 +cglobal put_vp8_bilinear%1_v, 7, 7, 5, dst, dststride, src, srcstride, height, picreg, my + shl myd, 4 +%ifdef PIC + lea picregq, [bilinear_filter_vb_m] +%endif + pxor m4, m4 + mova m3, [bilinear_filter_vb+myq-16] +.nextrow: + movh m0, [srcq+srcstrideq*0] + movh m1, [srcq+srcstrideq*1] + movh m2, [srcq+srcstrideq*2] + punpcklbw m0, m1 + punpcklbw m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + psraw m0, 2 + psraw m1, 2 + pavgw m0, m4 + pavgw m1, m4 +%if mmsize==8 + packuswb m0, m0 + packuswb m1, m1 + movh [dstq+dststrideq*0], m0 + movh [dstq+dststrideq*1], m1 +%else + packuswb m0, m1 + movh [dstq+dststrideq*0], m0 + movhps [dstq+dststrideq*1], m0 +%endif + + lea dstq, [dstq+dststrideq*2] + lea srcq, [srcq+srcstrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET + +cglobal put_vp8_bilinear%1_h, 6, 6 + npicregs, 5, dst, dststride, src, srcstride, height, mx, picreg + shl mxd, 4 +%ifdef PIC + lea picregq, [bilinear_filter_vb_m] +%endif + pxor m4, m4 + mova m2, [filter_h2_shuf] + mova m3, [bilinear_filter_vb+mxq-16] +.nextrow: + movu m0, [srcq+srcstrideq*0] + movu m1, [srcq+srcstrideq*1] + pshufb m0, m2 + pshufb m1, m2 + pmaddubsw m0, m3 + pmaddubsw m1, m3 + psraw m0, 2 + psraw m1, 2 + pavgw m0, m4 + pavgw m1, m4 +%if mmsize==8 + packuswb m0, m0 + packuswb m1, m1 + movh [dstq+dststrideq*0], m0 + movh [dstq+dststrideq*1], m1 +%else + packuswb m0, m1 + movh [dstq+dststrideq*0], m0 + movhps [dstq+dststrideq*1], m0 +%endif + + lea dstq, [dstq+dststrideq*2] + lea srcq, [srcq+srcstrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET +%endmacro + +INIT_MMX ssse3 +FILTER_BILINEAR_SSSE3 4 +INIT_XMM ssse3 +FILTER_BILINEAR_SSSE3 8 + +INIT_MMX mmx +cglobal put_vp8_pixels8, 5, 5, 0, dst, dststride, src, srcstride, height +.nextrow: + movq mm0, [srcq+srcstrideq*0] + movq mm1, [srcq+srcstrideq*1] + lea srcq, [srcq+srcstrideq*2] + movq [dstq+dststrideq*0], mm0 + movq [dstq+dststrideq*1], mm1 + lea dstq, [dstq+dststrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET + +%if ARCH_X86_32 +INIT_MMX mmx +cglobal put_vp8_pixels16, 5, 5, 0, dst, dststride, src, srcstride, height +.nextrow: + movq mm0, [srcq+srcstrideq*0+0] + movq mm1, [srcq+srcstrideq*0+8] + movq mm2, [srcq+srcstrideq*1+0] + movq mm3, [srcq+srcstrideq*1+8] + lea srcq, [srcq+srcstrideq*2] + movq [dstq+dststrideq*0+0], mm0 + movq [dstq+dststrideq*0+8], mm1 + movq [dstq+dststrideq*1+0], mm2 + movq [dstq+dststrideq*1+8], mm3 + lea dstq, [dstq+dststrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET +%endif + +INIT_XMM sse +cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height +.nextrow: + movups xmm0, [srcq+srcstrideq*0] + movups xmm1, [srcq+srcstrideq*1] + lea srcq, [srcq+srcstrideq*2] + movaps [dstq+dststrideq*0], xmm0 + movaps [dstq+dststrideq*1], xmm1 + lea dstq, [dstq+dststrideq*2] + sub heightd, 2 + jg .nextrow + REP_RET + +;----------------------------------------------------------------------------- +; void vp8_idct_dc_add_(uint8_t *dst, int16_t block[16], int stride); +;----------------------------------------------------------------------------- + +%macro ADD_DC 4 + %4 m2, [dst1q+%3] + %4 m3, [dst1q+strideq+%3] + %4 m4, [dst2q+%3] + %4 m5, [dst2q+strideq+%3] + paddusb m2, %1 + paddusb m3, %1 + paddusb m4, %1 + paddusb m5, %1 + psubusb m2, %2 + psubusb m3, %2 + psubusb m4, %2 + psubusb m5, %2 + %4 [dst1q+%3], m2 + %4 [dst1q+strideq+%3], m3 + %4 [dst2q+%3], m4 + %4 [dst2q+strideq+%3], m5 +%endmacro + +INIT_MMX mmx +cglobal vp8_idct_dc_add, 3, 3, 0, dst, block, stride + ; load data + movd m0, [blockq] + + ; calculate DC + paddw m0, [pw_4] + pxor m1, m1 + psraw m0, 3 + movd [blockq], m1 + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 + punpcklbw m0, m0 + punpcklbw m1, m1 + punpcklwd m0, m0 + punpcklwd m1, m1 + + ; add DC + DEFINE_ARGS dst1, dst2, stride + lea dst2q, [dst1q+strideq*2] + ADD_DC m0, m1, 0, movh + RET + +INIT_XMM sse4 +cglobal vp8_idct_dc_add, 3, 3, 6, dst, block, stride + ; load data + movd m0, [blockq] + pxor m1, m1 + + ; calculate DC + paddw m0, [pw_4] + movd [blockq], m1 + DEFINE_ARGS dst1, dst2, stride + lea dst2q, [dst1q+strideq*2] + movd m2, [dst1q] + movd m3, [dst1q+strideq] + movd m4, [dst2q] + movd m5, [dst2q+strideq] + psraw m0, 3 + pshuflw m0, m0, 0 + punpcklqdq m0, m0 + punpckldq m2, m3 + punpckldq m4, m5 + punpcklbw m2, m1 + punpcklbw m4, m1 + paddw m2, m0 + paddw m4, m0 + packuswb m2, m4 + movd [dst1q], m2 + pextrd [dst1q+strideq], m2, 1 + pextrd [dst2q], m2, 2 + pextrd [dst2q+strideq], m2, 3 + RET + +;----------------------------------------------------------------------------- +; void vp8_idct_dc_add4y_(uint8_t *dst, int16_t block[4][16], int stride); +;----------------------------------------------------------------------------- + +%if ARCH_X86_32 +INIT_MMX mmx +cglobal vp8_idct_dc_add4y, 3, 3, 0, dst, block, stride + ; load data + movd m0, [blockq+32*0] ; A + movd m1, [blockq+32*2] ; C + punpcklwd m0, [blockq+32*1] ; A B + punpcklwd m1, [blockq+32*3] ; C D + punpckldq m0, m1 ; A B C D + pxor m6, m6 + + ; calculate DC + paddw m0, [pw_4] + movd [blockq+32*0], m6 + movd [blockq+32*1], m6 + movd [blockq+32*2], m6 + movd [blockq+32*3], m6 + psraw m0, 3 + psubw m6, m0 + packuswb m0, m0 + packuswb m6, m6 + punpcklbw m0, m0 ; AABBCCDD + punpcklbw m6, m6 ; AABBCCDD + movq m1, m0 + movq m7, m6 + punpcklbw m0, m0 ; AAAABBBB + punpckhbw m1, m1 ; CCCCDDDD + punpcklbw m6, m6 ; AAAABBBB + punpckhbw m7, m7 ; CCCCDDDD + + ; add DC + DEFINE_ARGS dst1, dst2, stride + lea dst2q, [dst1q+strideq*2] + ADD_DC m0, m6, 0, mova + ADD_DC m1, m7, 8, mova + RET +%endif + +INIT_XMM sse2 +cglobal vp8_idct_dc_add4y, 3, 3, 6, dst, block, stride + ; load data + movd m0, [blockq+32*0] ; A + movd m1, [blockq+32*2] ; C + punpcklwd m0, [blockq+32*1] ; A B + punpcklwd m1, [blockq+32*3] ; C D + punpckldq m0, m1 ; A B C D + pxor m1, m1 + + ; calculate DC + paddw m0, [pw_4] + movd [blockq+32*0], m1 + movd [blockq+32*1], m1 + movd [blockq+32*2], m1 + movd [blockq+32*3], m1 + psraw m0, 3 + psubw m1, m0 + packuswb m0, m0 + packuswb m1, m1 + punpcklbw m0, m0 + punpcklbw m1, m1 + punpcklbw m0, m0 + punpcklbw m1, m1 + + ; add DC + DEFINE_ARGS dst1, dst2, stride + lea dst2q, [dst1q+strideq*2] + ADD_DC m0, m1, 0, mova + RET + +;----------------------------------------------------------------------------- +; void vp8_idct_dc_add4uv_(uint8_t *dst, int16_t block[4][16], int stride); +;----------------------------------------------------------------------------- + +INIT_MMX mmx +cglobal vp8_idct_dc_add4uv, 3, 3, 0, dst, block, stride + ; load data + movd m0, [blockq+32*0] ; A + movd m1, [blockq+32*2] ; C + punpcklwd m0, [blockq+32*1] ; A B + punpcklwd m1, [blockq+32*3] ; C D + punpckldq m0, m1 ; A B C D + pxor m6, m6 + + ; calculate DC + paddw m0, [pw_4] + movd [blockq+32*0], m6 + movd [blockq+32*1], m6 + movd [blockq+32*2], m6 + movd [blockq+32*3], m6 + psraw m0, 3 + psubw m6, m0 + packuswb m0, m0 + packuswb m6, m6 + punpcklbw m0, m0 ; AABBCCDD + punpcklbw m6, m6 ; AABBCCDD + movq m1, m0 + movq m7, m6 + punpcklbw m0, m0 ; AAAABBBB + punpckhbw m1, m1 ; CCCCDDDD + punpcklbw m6, m6 ; AAAABBBB + punpckhbw m7, m7 ; CCCCDDDD + + ; add DC + DEFINE_ARGS dst1, dst2, stride + lea dst2q, [dst1q+strideq*2] + ADD_DC m0, m6, 0, mova + lea dst1q, [dst1q+strideq*4] + lea dst2q, [dst2q+strideq*4] + ADD_DC m1, m7, 0, mova + RET + +;----------------------------------------------------------------------------- +; void vp8_idct_add_(uint8_t *dst, int16_t block[16], int stride); +;----------------------------------------------------------------------------- + +; calculate %1=mul_35468(%1)-mul_20091(%2); %2=mul_20091(%1)+mul_35468(%2) +; this macro assumes that m6/m7 have words for 20091/17734 loaded +%macro VP8_MULTIPLY_SUMSUB 4 + mova %3, %1 + mova %4, %2 + pmulhw %3, m6 ;20091(1) + pmulhw %4, m6 ;20091(2) + paddw %3, %1 + paddw %4, %2 + paddw %1, %1 + paddw %2, %2 + pmulhw %1, m7 ;35468(1) + pmulhw %2, m7 ;35468(2) + psubw %1, %4 + paddw %2, %3 +%endmacro + +; calculate x0=%1+%3; x1=%1-%3 +; x2=mul_35468(%2)-mul_20091(%4); x3=mul_20091(%2)+mul_35468(%4) +; %1=x0+x3 (tmp0); %2=x1+x2 (tmp1); %3=x1-x2 (tmp2); %4=x0-x3 (tmp3) +; %5/%6 are temporary registers +; we assume m6/m7 have constant words 20091/17734 loaded in them +%macro VP8_IDCT_TRANSFORM4x4_1D 6 + SUMSUB_BA w, %3, %1, %5 ;t0, t1 + VP8_MULTIPLY_SUMSUB m%2, m%4, m%5,m%6 ;t2, t3 + SUMSUB_BA w, %4, %3, %5 ;tmp0, tmp3 + SUMSUB_BA w, %2, %1, %5 ;tmp1, tmp2 + SWAP %4, %1 + SWAP %4, %3 +%endmacro + +%macro VP8_IDCT_ADD 0 +cglobal vp8_idct_add, 3, 3, 0, dst, block, stride + ; load block data + movq m0, [blockq+ 0] + movq m1, [blockq+ 8] + movq m2, [blockq+16] + movq m3, [blockq+24] + movq m6, [pw_20091] + movq m7, [pw_17734] +%if cpuflag(sse) + xorps xmm0, xmm0 + movaps [blockq+ 0], xmm0 + movaps [blockq+16], xmm0 +%else + pxor m4, m4 + movq [blockq+ 0], m4 + movq [blockq+ 8], m4 + movq [blockq+16], m4 + movq [blockq+24], m4 +%endif + + ; actual IDCT + VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5 + TRANSPOSE4x4W 0, 1, 2, 3, 4 + paddw m0, [pw_4] + VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5 + TRANSPOSE4x4W 0, 1, 2, 3, 4 + + ; store + pxor m4, m4 + DEFINE_ARGS dst1, dst2, stride + lea dst2q, [dst1q+2*strideq] + STORE_DIFFx2 m0, m1, m6, m7, m4, 3, dst1q, strideq + STORE_DIFFx2 m2, m3, m6, m7, m4, 3, dst2q, strideq + + RET +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +VP8_IDCT_ADD +%endif +INIT_MMX sse +VP8_IDCT_ADD + +;----------------------------------------------------------------------------- +; void vp8_luma_dc_wht_mmxext(int16_t block[4][4][16], int16_t dc[16]) +;----------------------------------------------------------------------------- + +%macro SCATTER_WHT 3 + movd dc1d, m%1 + movd dc2d, m%2 + mov [blockq+2*16*(0+%3)], dc1w + mov [blockq+2*16*(1+%3)], dc2w + shr dc1d, 16 + shr dc2d, 16 + psrlq m%1, 32 + psrlq m%2, 32 + mov [blockq+2*16*(4+%3)], dc1w + mov [blockq+2*16*(5+%3)], dc2w + movd dc1d, m%1 + movd dc2d, m%2 + mov [blockq+2*16*(8+%3)], dc1w + mov [blockq+2*16*(9+%3)], dc2w + shr dc1d, 16 + shr dc2d, 16 + mov [blockq+2*16*(12+%3)], dc1w + mov [blockq+2*16*(13+%3)], dc2w +%endmacro + +%macro HADAMARD4_1D 4 + SUMSUB_BADC w, %2, %1, %4, %3 + SUMSUB_BADC w, %4, %2, %3, %1 + SWAP %1, %4, %3 +%endmacro + +%macro VP8_DC_WHT 0 +cglobal vp8_luma_dc_wht, 2, 3, 0, block, dc1, dc2 + movq m0, [dc1q] + movq m1, [dc1q+8] + movq m2, [dc1q+16] + movq m3, [dc1q+24] +%if cpuflag(sse) + xorps xmm0, xmm0 + movaps [dc1q+ 0], xmm0 + movaps [dc1q+16], xmm0 +%else + pxor m4, m4 + movq [dc1q+ 0], m4 + movq [dc1q+ 8], m4 + movq [dc1q+16], m4 + movq [dc1q+24], m4 +%endif + HADAMARD4_1D 0, 1, 2, 3 + TRANSPOSE4x4W 0, 1, 2, 3, 4 + paddw m0, [pw_3] + HADAMARD4_1D 0, 1, 2, 3 + psraw m0, 3 + psraw m1, 3 + psraw m2, 3 + psraw m3, 3 + SCATTER_WHT 0, 1, 0 + SCATTER_WHT 2, 3, 2 + RET +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +VP8_DC_WHT +%endif +INIT_MMX sse +VP8_DC_WHT + +;----------------------------------------------------------------------------- +; void vp8_h/v_loop_filter_simple_(uint8_t *dst, int stride, int flim); +;----------------------------------------------------------------------------- + +; macro called with 7 mm register indexes as argument, and 4 regular registers +; +; first 4 mm registers will carry the transposed pixel data +; the other three are scratchspace (one would be sufficient, but this allows +; for more spreading/pipelining and thus faster execution on OOE CPUs) +; +; first two regular registers are buf+4*stride and buf+5*stride +; third is -stride, fourth is +stride +%macro READ_8x4_INTERLEAVED 11 + ; interleave 8 (A-H) rows of 4 pixels each + movd m%1, [%8+%10*4] ; A0-3 + movd m%5, [%9+%10*4] ; B0-3 + movd m%2, [%8+%10*2] ; C0-3 + movd m%6, [%8+%10] ; D0-3 + movd m%3, [%8] ; E0-3 + movd m%7, [%9] ; F0-3 + movd m%4, [%9+%11] ; G0-3 + punpcklbw m%1, m%5 ; A/B interleaved + movd m%5, [%9+%11*2] ; H0-3 + punpcklbw m%2, m%6 ; C/D interleaved + punpcklbw m%3, m%7 ; E/F interleaved + punpcklbw m%4, m%5 ; G/H interleaved +%endmacro + +; macro called with 7 mm register indexes as argument, and 5 regular registers +; first 11 mean the same as READ_8x4_TRANSPOSED above +; fifth regular register is scratchspace to reach the bottom 8 rows, it +; will be set to second regular register + 8*stride at the end +%macro READ_16x4_INTERLEAVED 12 + ; transpose 16 (A-P) rows of 4 pixels each + lea %12, [r0+8*r2] + + ; read (and interleave) those addressable by %8 (=r0), A/C/D/E/I/K/L/M + movd m%1, [%8+%10*4] ; A0-3 + movd m%3, [%12+%10*4] ; I0-3 + movd m%2, [%8+%10*2] ; C0-3 + movd m%4, [%12+%10*2] ; K0-3 + movd m%6, [%8+%10] ; D0-3 + movd m%5, [%12+%10] ; L0-3 + movd m%7, [%12] ; M0-3 + add %12, %11 + punpcklbw m%1, m%3 ; A/I + movd m%3, [%8] ; E0-3 + punpcklbw m%2, m%4 ; C/K + punpcklbw m%6, m%5 ; D/L + punpcklbw m%3, m%7 ; E/M + punpcklbw m%2, m%6 ; C/D/K/L interleaved + + ; read (and interleave) those addressable by %9 (=r4), B/F/G/H/J/N/O/P + movd m%5, [%9+%10*4] ; B0-3 + movd m%4, [%12+%10*4] ; J0-3 + movd m%7, [%9] ; F0-3 + movd m%6, [%12] ; N0-3 + punpcklbw m%5, m%4 ; B/J + punpcklbw m%7, m%6 ; F/N + punpcklbw m%1, m%5 ; A/B/I/J interleaved + punpcklbw m%3, m%7 ; E/F/M/N interleaved + movd m%4, [%9+%11] ; G0-3 + movd m%6, [%12+%11] ; O0-3 + movd m%5, [%9+%11*2] ; H0-3 + movd m%7, [%12+%11*2] ; P0-3 + punpcklbw m%4, m%6 ; G/O + punpcklbw m%5, m%7 ; H/P + punpcklbw m%4, m%5 ; G/H/O/P interleaved +%endmacro + +; write 4 mm registers of 2 dwords each +; first four arguments are mm register indexes containing source data +; last four are registers containing buf+4*stride, buf+5*stride, +; -stride and +stride +%macro WRITE_4x2D 8 + ; write out (2 dwords per register) + movd [%5+%7*4], m%1 + movd [%5+%7*2], m%2 + movd [%5], m%3 + movd [%6+%8], m%4 + punpckhdq m%1, m%1 + punpckhdq m%2, m%2 + punpckhdq m%3, m%3 + punpckhdq m%4, m%4 + movd [%6+%7*4], m%1 + movd [%5+%7], m%2 + movd [%6], m%3 + movd [%6+%8*2], m%4 +%endmacro + +; write 4 xmm registers of 4 dwords each +; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular +; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride +; we add 1*stride to the third regular registry in the process +; the 10th argument is 16 if it's a Y filter (i.e. all regular registers cover the +; same memory region), or 8 if they cover two separate buffers (third one points to +; a different memory region than the first two), allowing for more optimal code for +; the 16-width case +%macro WRITE_4x4D 10 + ; write out (4 dwords per register), start with dwords zero + movd [%5+%8*4], m%1 + movd [%5], m%2 + movd [%7+%8*4], m%3 + movd [%7], m%4 + + ; store dwords 1 + psrldq m%1, 4 + psrldq m%2, 4 + psrldq m%3, 4 + psrldq m%4, 4 + movd [%6+%8*4], m%1 + movd [%6], m%2 +%if %10 == 16 + movd [%6+%9*4], m%3 +%endif + movd [%7+%9], m%4 + + ; write dwords 2 + psrldq m%1, 4 + psrldq m%2, 4 +%if %10 == 8 + movd [%5+%8*2], m%1 + movd %5d, m%3 +%endif + psrldq m%3, 4 + psrldq m%4, 4 +%if %10 == 16 + movd [%5+%8*2], m%1 +%endif + movd [%6+%9], m%2 + movd [%7+%8*2], m%3 + movd [%7+%9*2], m%4 + add %7, %9 + + ; store dwords 3 + psrldq m%1, 4 + psrldq m%2, 4 + psrldq m%3, 4 + psrldq m%4, 4 +%if %10 == 8 + mov [%7+%8*4], %5d + movd [%6+%8*2], m%1 +%else + movd [%5+%8], m%1 +%endif + movd [%6+%9*2], m%2 + movd [%7+%8*2], m%3 + movd [%7+%9*2], m%4 +%endmacro + +; write 4 or 8 words in the mmx/xmm registers as 8 lines +; 1 and 2 are the registers to write, this can be the same (for SSE2) +; for pre-SSE4: +; 3 is a general-purpose register that we will clobber +; for SSE4: +; 3 is a pointer to the destination's 5th line +; 4 is a pointer to the destination's 4th line +; 5/6 is -stride and +stride +%macro WRITE_2x4W 6 + movd %3d, %1 + punpckhdq %1, %1 + mov [%4+%5*4], %3w + shr %3, 16 + add %4, %6 + mov [%4+%5*4], %3w + + movd %3d, %1 + add %4, %5 + mov [%4+%5*2], %3w + shr %3, 16 + mov [%4+%5 ], %3w + + movd %3d, %2 + punpckhdq %2, %2 + mov [%4 ], %3w + shr %3, 16 + mov [%4+%6 ], %3w + + movd %3d, %2 + add %4, %6 + mov [%4+%6 ], %3w + shr %3, 16 + mov [%4+%6*2], %3w + add %4, %5 +%endmacro + +%macro WRITE_8W 5 +%if cpuflag(sse4) + pextrw [%3+%4*4], %1, 0 + pextrw [%2+%4*4], %1, 1 + pextrw [%3+%4*2], %1, 2 + pextrw [%3+%4 ], %1, 3 + pextrw [%3 ], %1, 4 + pextrw [%2 ], %1, 5 + pextrw [%2+%5 ], %1, 6 + pextrw [%2+%5*2], %1, 7 +%else + movd %2d, %1 + psrldq %1, 4 + mov [%3+%4*4], %2w + shr %2, 16 + add %3, %5 + mov [%3+%4*4], %2w + + movd %2d, %1 + psrldq %1, 4 + add %3, %4 + mov [%3+%4*2], %2w + shr %2, 16 + mov [%3+%4 ], %2w + + movd %2d, %1 + psrldq %1, 4 + mov [%3 ], %2w + shr %2, 16 + mov [%3+%5 ], %2w + + movd %2d, %1 + add %3, %5 + mov [%3+%5 ], %2w + shr %2, 16 + mov [%3+%5*2], %2w +%endif +%endmacro + +%macro SIMPLE_LOOPFILTER 2 +cglobal vp8_%1_loop_filter_simple, 3, %2, 8, dst, stride, flim, cntr +%if mmsize == 8 ; mmx/mmxext + mov cntrq, 2 +%endif +%if cpuflag(ssse3) + pxor m0, m0 +%endif + SPLATB_REG m7, flim, m0 ; splat "flim" into register + + ; set up indexes to address 4 rows +%if mmsize == 8 + DEFINE_ARGS dst1, mstride, stride, cntr, dst2 +%else + DEFINE_ARGS dst1, mstride, stride, dst3, dst2 +%endif + mov strideq, mstrideq + neg mstrideq +%ifidn %1, h + lea dst1q, [dst1q+4*strideq-2] +%endif + +%if mmsize == 8 ; mmx / mmxext +.next8px: +%endif +%ifidn %1, v + ; read 4 half/full rows of pixels + mova m0, [dst1q+mstrideq*2] ; p1 + mova m1, [dst1q+mstrideq] ; p0 + mova m2, [dst1q] ; q0 + mova m3, [dst1q+ strideq] ; q1 +%else ; h + lea dst2q, [dst1q+ strideq] + +%if mmsize == 8 ; mmx/mmxext + READ_8x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, dst1q, dst2q, mstrideq, strideq +%else ; sse2 + READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, dst1q, dst2q, mstrideq, strideq, dst3q +%endif + TRANSPOSE4x4W 0, 1, 2, 3, 4 +%endif + + ; simple_limit + mova m5, m2 ; m5=backup of q0 + mova m6, m1 ; m6=backup of p0 + psubusb m1, m2 ; p0-q0 + psubusb m2, m6 ; q0-p0 + por m1, m2 ; FFABS(p0-q0) + paddusb m1, m1 ; m1=FFABS(p0-q0)*2 + + mova m4, m3 + mova m2, m0 + psubusb m3, m0 ; q1-p1 + psubusb m0, m4 ; p1-q1 + por m3, m0 ; FFABS(p1-q1) + mova m0, [pb_80] + pxor m2, m0 + pxor m4, m0 + psubsb m2, m4 ; m2=p1-q1 (signed) backup for below + pand m3, [pb_FE] + psrlq m3, 1 ; m3=FFABS(p1-q1)/2, this can be used signed + paddusb m3, m1 + psubusb m3, m7 + pxor m1, m1 + pcmpeqb m3, m1 ; abs(p0-q0)*2+abs(p1-q1)/2<=flim mask(0xff/0x0) + + ; filter_common (use m2/p1-q1, m4=q0, m6=p0, m5/q0-p0 and m3/mask) + mova m4, m5 + pxor m5, m0 + pxor m0, m6 + psubsb m5, m0 ; q0-p0 (signed) + paddsb m2, m5 + paddsb m2, m5 + paddsb m2, m5 ; a=(p1-q1) + 3*(q0-p0) + pand m2, m3 ; apply filter mask (m3) + + mova m3, [pb_F8] + mova m1, m2 + paddsb m2, [pb_4] ; f1<<3=a+4 + paddsb m1, [pb_3] ; f2<<3=a+3 + pand m2, m3 + pand m1, m3 ; cache f2<<3 + + pxor m0, m0 + pxor m3, m3 + pcmpgtb m0, m2 ; which values are <0? + psubb m3, m2 ; -f1<<3 + psrlq m2, 3 ; +f1 + psrlq m3, 3 ; -f1 + pand m3, m0 + pandn m0, m2 + psubusb m4, m0 + paddusb m4, m3 ; q0-f1 + + pxor m0, m0 + pxor m3, m3 + pcmpgtb m0, m1 ; which values are <0? + psubb m3, m1 ; -f2<<3 + psrlq m1, 3 ; +f2 + psrlq m3, 3 ; -f2 + pand m3, m0 + pandn m0, m1 + paddusb m6, m0 + psubusb m6, m3 ; p0+f2 + + ; store +%ifidn %1, v + mova [dst1q], m4 + mova [dst1q+mstrideq], m6 +%else ; h + inc dst1q + SBUTTERFLY bw, 6, 4, 0 + +%if mmsize == 16 ; sse2 +%if cpuflag(sse4) + inc dst2q +%endif + WRITE_8W m6, dst2q, dst1q, mstrideq, strideq + lea dst2q, [dst3q+mstrideq+1] +%if cpuflag(sse4) + inc dst3q +%endif + WRITE_8W m4, dst3q, dst2q, mstrideq, strideq +%else ; mmx/mmxext + WRITE_2x4W m6, m4, dst2q, dst1q, mstrideq, strideq +%endif +%endif + +%if mmsize == 8 ; mmx/mmxext + ; next 8 pixels +%ifidn %1, v + add dst1q, 8 ; advance 8 cols = pixels +%else ; h + lea dst1q, [dst1q+strideq*8-1] ; advance 8 rows = lines +%endif + dec cntrq + jg .next8px + REP_RET +%else ; sse2 + RET +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +SIMPLE_LOOPFILTER v, 4 +SIMPLE_LOOPFILTER h, 5 +INIT_MMX mmxext +SIMPLE_LOOPFILTER v, 4 +SIMPLE_LOOPFILTER h, 5 +%endif + +INIT_XMM sse2 +SIMPLE_LOOPFILTER v, 3 +SIMPLE_LOOPFILTER h, 5 +INIT_XMM ssse3 +SIMPLE_LOOPFILTER v, 3 +SIMPLE_LOOPFILTER h, 5 +INIT_XMM sse4 +SIMPLE_LOOPFILTER h, 5 + +;----------------------------------------------------------------------------- +; void vp8_h/v_loop_filter_inner_(uint8_t *dst, [uint8_t *v,] int stride, +; int flimE, int flimI, int hev_thr); +;----------------------------------------------------------------------------- + +%macro INNER_LOOPFILTER 2 +%define stack_size 0 +%ifndef m8 ; stack layout: [0]=E, [1]=I, [2]=hev_thr +%ifidn %1, v ; [3]=hev() result +%define stack_size mmsize * -4 +%else ; h ; extra storage space for transposes +%define stack_size mmsize * -5 +%endif +%endif + +%if %2 == 8 ; chroma +cglobal vp8_%1_loop_filter8uv_inner, 6, 6, 13, stack_size, dst, dst8, stride, flimE, flimI, hevthr +%else ; luma +cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, flimI, hevthr +%endif + +%if cpuflag(ssse3) + pxor m7, m7 +%endif + +%ifndef m8 + ; splat function arguments + SPLATB_REG m0, flimEq, m7 ; E + SPLATB_REG m1, flimIq, m7 ; I + SPLATB_REG m2, hevthrq, m7 ; hev_thresh + +%define m_flimE [rsp] +%define m_flimI [rsp+mmsize] +%define m_hevthr [rsp+mmsize*2] +%define m_maskres [rsp+mmsize*3] +%define m_p0backup [rsp+mmsize*3] +%define m_q0backup [rsp+mmsize*4] + + mova m_flimE, m0 + mova m_flimI, m1 + mova m_hevthr, m2 +%else +%define m_flimE m9 +%define m_flimI m10 +%define m_hevthr m11 +%define m_maskres m12 +%define m_p0backup m12 +%define m_q0backup m8 + + ; splat function arguments + SPLATB_REG m_flimE, flimEq, m7 ; E + SPLATB_REG m_flimI, flimIq, m7 ; I + SPLATB_REG m_hevthr, hevthrq, m7 ; hev_thresh +%endif + +%if %2 == 8 ; chroma + DEFINE_ARGS dst1, dst8, mstride, stride, dst2 +%elif mmsize == 8 + DEFINE_ARGS dst1, mstride, stride, dst2, cntr + mov cntrq, 2 +%else + DEFINE_ARGS dst1, mstride, stride, dst2, dst8 +%endif + mov strideq, mstrideq + neg mstrideq +%ifidn %1, h + lea dst1q, [dst1q+strideq*4-4] +%if %2 == 8 ; chroma + lea dst8q, [dst8q+strideq*4-4] +%endif +%endif + +%if mmsize == 8 +.next8px: +%endif + ; read + lea dst2q, [dst1q+strideq] +%ifidn %1, v +%if %2 == 8 && mmsize == 16 +%define movrow movh +%else +%define movrow mova +%endif + movrow m0, [dst1q+mstrideq*4] ; p3 + movrow m1, [dst2q+mstrideq*4] ; p2 + movrow m2, [dst1q+mstrideq*2] ; p1 + movrow m5, [dst2q] ; q1 + movrow m6, [dst2q+ strideq*1] ; q2 + movrow m7, [dst2q+ strideq*2] ; q3 +%if mmsize == 16 && %2 == 8 + movhps m0, [dst8q+mstrideq*4] + movhps m2, [dst8q+mstrideq*2] + add dst8q, strideq + movhps m1, [dst8q+mstrideq*4] + movhps m5, [dst8q] + movhps m6, [dst8q+ strideq ] + movhps m7, [dst8q+ strideq*2] + add dst8q, mstrideq +%endif +%elif mmsize == 8 ; mmx/mmxext (h) + ; read 8 rows of 8px each + movu m0, [dst1q+mstrideq*4] + movu m1, [dst2q+mstrideq*4] + movu m2, [dst1q+mstrideq*2] + movu m3, [dst1q+mstrideq ] + movu m4, [dst1q] + movu m5, [dst2q] + movu m6, [dst2q+ strideq ] + + ; 8x8 transpose + TRANSPOSE4x4B 0, 1, 2, 3, 7 + mova m_q0backup, m1 + movu m7, [dst2q+ strideq*2] + TRANSPOSE4x4B 4, 5, 6, 7, 1 + SBUTTERFLY dq, 0, 4, 1 ; p3/p2 + SBUTTERFLY dq, 2, 6, 1 ; q0/q1 + SBUTTERFLY dq, 3, 7, 1 ; q2/q3 + mova m1, m_q0backup + mova m_q0backup, m2 ; store q0 + SBUTTERFLY dq, 1, 5, 2 ; p1/p0 + mova m_p0backup, m5 ; store p0 + SWAP 1, 4 + SWAP 2, 4 + SWAP 6, 3 + SWAP 5, 3 +%else ; sse2 (h) +%if %2 == 16 + lea dst8q, [dst1q+ strideq*8] +%endif + + ; read 16 rows of 8px each, interleave + movh m0, [dst1q+mstrideq*4] + movh m1, [dst8q+mstrideq*4] + movh m2, [dst1q+mstrideq*2] + movh m5, [dst8q+mstrideq*2] + movh m3, [dst1q+mstrideq ] + movh m6, [dst8q+mstrideq ] + movh m4, [dst1q] + movh m7, [dst8q] + punpcklbw m0, m1 ; A/I + punpcklbw m2, m5 ; C/K + punpcklbw m3, m6 ; D/L + punpcklbw m4, m7 ; E/M + + add dst8q, strideq + movh m1, [dst2q+mstrideq*4] + movh m6, [dst8q+mstrideq*4] + movh m5, [dst2q] + movh m7, [dst8q] + punpcklbw m1, m6 ; B/J + punpcklbw m5, m7 ; F/N + movh m6, [dst2q+ strideq ] + movh m7, [dst8q+ strideq ] + punpcklbw m6, m7 ; G/O + + ; 8x16 transpose + TRANSPOSE4x4B 0, 1, 2, 3, 7 +%ifdef m8 + SWAP 1, 8 +%else + mova m_q0backup, m1 +%endif + movh m7, [dst2q+ strideq*2] + movh m1, [dst8q+ strideq*2] + punpcklbw m7, m1 ; H/P + TRANSPOSE4x4B 4, 5, 6, 7, 1 + SBUTTERFLY dq, 0, 4, 1 ; p3/p2 + SBUTTERFLY dq, 2, 6, 1 ; q0/q1 + SBUTTERFLY dq, 3, 7, 1 ; q2/q3 +%ifdef m8 + SWAP 1, 8 + SWAP 2, 8 +%else + mova m1, m_q0backup + mova m_q0backup, m2 ; store q0 +%endif + SBUTTERFLY dq, 1, 5, 2 ; p1/p0 +%ifdef m12 + SWAP 5, 12 +%else + mova m_p0backup, m5 ; store p0 +%endif + SWAP 1, 4 + SWAP 2, 4 + SWAP 6, 3 + SWAP 5, 3 +%endif + + ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1 + mova m4, m1 + SWAP 4, 1 + psubusb m4, m0 ; p2-p3 + psubusb m0, m1 ; p3-p2 + por m0, m4 ; abs(p3-p2) + + mova m4, m2 + SWAP 4, 2 + psubusb m4, m1 ; p1-p2 + psubusb m1, m2 ; p2-p1 + por m1, m4 ; abs(p2-p1) + + mova m4, m6 + SWAP 4, 6 + psubusb m4, m7 ; q2-q3 + psubusb m7, m6 ; q3-q2 + por m7, m4 ; abs(q3-q2) + + mova m4, m5 + SWAP 4, 5 + psubusb m4, m6 ; q1-q2 + psubusb m6, m5 ; q2-q1 + por m6, m4 ; abs(q2-q1) + +%if notcpuflag(mmxext) + mova m4, m_flimI + pxor m3, m3 + psubusb m0, m4 + psubusb m1, m4 + psubusb m7, m4 + psubusb m6, m4 + pcmpeqb m0, m3 ; abs(p3-p2) <= I + pcmpeqb m1, m3 ; abs(p2-p1) <= I + pcmpeqb m7, m3 ; abs(q3-q2) <= I + pcmpeqb m6, m3 ; abs(q2-q1) <= I + pand m0, m1 + pand m7, m6 + pand m0, m7 +%else ; mmxext/sse2 + pmaxub m0, m1 + pmaxub m6, m7 + pmaxub m0, m6 +%endif + + ; normal_limit and high_edge_variance for p1-p0, q1-q0 + SWAP 7, 3 ; now m7 is zero +%ifidn %1, v + movrow m3, [dst1q+mstrideq ] ; p0 +%if mmsize == 16 && %2 == 8 + movhps m3, [dst8q+mstrideq ] +%endif +%elifdef m12 + SWAP 3, 12 +%else + mova m3, m_p0backup +%endif + + mova m1, m2 + SWAP 1, 2 + mova m6, m3 + SWAP 3, 6 + psubusb m1, m3 ; p1-p0 + psubusb m6, m2 ; p0-p1 + por m1, m6 ; abs(p1-p0) +%if notcpuflag(mmxext) + mova m6, m1 + psubusb m1, m4 + psubusb m6, m_hevthr + pcmpeqb m1, m7 ; abs(p1-p0) <= I + pcmpeqb m6, m7 ; abs(p1-p0) <= hev_thresh + pand m0, m1 + mova m_maskres, m6 +%else ; mmxext/sse2 + pmaxub m0, m1 ; max_I + SWAP 1, 4 ; max_hev_thresh +%endif + + SWAP 6, 4 ; now m6 is I +%ifidn %1, v + movrow m4, [dst1q] ; q0 +%if mmsize == 16 && %2 == 8 + movhps m4, [dst8q] +%endif +%elifdef m8 + SWAP 4, 8 +%else + mova m4, m_q0backup +%endif + mova m1, m4 + SWAP 1, 4 + mova m7, m5 + SWAP 7, 5 + psubusb m1, m5 ; q0-q1 + psubusb m7, m4 ; q1-q0 + por m1, m7 ; abs(q1-q0) +%if notcpuflag(mmxext) + mova m7, m1 + psubusb m1, m6 + psubusb m7, m_hevthr + pxor m6, m6 + pcmpeqb m1, m6 ; abs(q1-q0) <= I + pcmpeqb m7, m6 ; abs(q1-q0) <= hev_thresh + mova m6, m_maskres + pand m0, m1 ; abs([pq][321]-[pq][210]) <= I + pand m6, m7 +%else ; mmxext/sse2 + pxor m7, m7 + pmaxub m0, m1 + pmaxub m6, m1 + psubusb m0, m_flimI + psubusb m6, m_hevthr + pcmpeqb m0, m7 ; max(abs(..)) <= I + pcmpeqb m6, m7 ; !(max(abs..) > thresh) +%endif +%ifdef m12 + SWAP 6, 12 +%else + mova m_maskres, m6 ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t) +%endif + + ; simple_limit + mova m1, m3 + SWAP 1, 3 + mova m6, m4 ; keep copies of p0/q0 around for later use + SWAP 6, 4 + psubusb m1, m4 ; p0-q0 + psubusb m6, m3 ; q0-p0 + por m1, m6 ; abs(q0-p0) + paddusb m1, m1 ; m1=2*abs(q0-p0) + + mova m7, m2 + SWAP 7, 2 + mova m6, m5 + SWAP 6, 5 + psubusb m7, m5 ; p1-q1 + psubusb m6, m2 ; q1-p1 + por m7, m6 ; abs(q1-p1) + pxor m6, m6 + pand m7, [pb_FE] + psrlq m7, 1 ; abs(q1-p1)/2 + paddusb m7, m1 ; abs(q0-p0)*2+abs(q1-p1)/2 + psubusb m7, m_flimE + pcmpeqb m7, m6 ; abs(q0-p0)*2+abs(q1-p1)/2 <= E + pand m0, m7 ; normal_limit result + + ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask +%ifdef m8 ; x86-64 && sse2 + mova m8, [pb_80] +%define m_pb_80 m8 +%else ; x86-32 or mmx/mmxext +%define m_pb_80 [pb_80] +%endif + mova m1, m4 + mova m7, m3 + pxor m1, m_pb_80 + pxor m7, m_pb_80 + psubsb m1, m7 ; (signed) q0-p0 + mova m6, m2 + mova m7, m5 + pxor m6, m_pb_80 + pxor m7, m_pb_80 + psubsb m6, m7 ; (signed) p1-q1 + mova m7, m_maskres + pandn m7, m6 + paddsb m7, m1 + paddsb m7, m1 + paddsb m7, m1 ; 3*(q0-p0)+is4tap?(p1-q1) + + pand m7, m0 + mova m1, [pb_F8] + mova m6, m7 + paddsb m7, [pb_3] + paddsb m6, [pb_4] + pand m7, m1 + pand m6, m1 + + pxor m1, m1 + pxor m0, m0 + pcmpgtb m1, m7 + psubb m0, m7 + psrlq m7, 3 ; +f2 + psrlq m0, 3 ; -f2 + pand m0, m1 + pandn m1, m7 + psubusb m3, m0 + paddusb m3, m1 ; p0+f2 + + pxor m1, m1 + pxor m0, m0 + pcmpgtb m0, m6 + psubb m1, m6 + psrlq m6, 3 ; +f1 + psrlq m1, 3 ; -f1 + pand m1, m0 + pandn m0, m6 + psubusb m4, m0 + paddusb m4, m1 ; q0-f1 + +%ifdef m12 + SWAP 6, 12 +%else + mova m6, m_maskres +%endif +%if notcpuflag(mmxext) + mova m7, [pb_1] +%else ; mmxext/sse2 + pxor m7, m7 +%endif + pand m0, m6 + pand m1, m6 +%if notcpuflag(mmxext) + paddusb m0, m7 + pand m1, [pb_FE] + pandn m7, m0 + psrlq m1, 1 + psrlq m7, 1 + SWAP 0, 7 +%else ; mmxext/sse2 + psubusb m1, [pb_1] + pavgb m0, m7 ; a + pavgb m1, m7 ; -a +%endif + psubusb m5, m0 + psubusb m2, m1 + paddusb m5, m1 ; q1-a + paddusb m2, m0 ; p1+a + + ; store +%ifidn %1, v + movrow [dst1q+mstrideq*2], m2 + movrow [dst1q+mstrideq ], m3 + movrow [dst1q], m4 + movrow [dst1q+ strideq ], m5 +%if mmsize == 16 && %2 == 8 + movhps [dst8q+mstrideq*2], m2 + movhps [dst8q+mstrideq ], m3 + movhps [dst8q], m4 + movhps [dst8q+ strideq ], m5 +%endif +%else ; h + add dst1q, 2 + add dst2q, 2 + + ; 4x8/16 transpose + TRANSPOSE4x4B 2, 3, 4, 5, 6 + +%if mmsize == 8 ; mmx/mmxext (h) + WRITE_4x2D 2, 3, 4, 5, dst1q, dst2q, mstrideq, strideq +%else ; sse2 (h) + lea dst8q, [dst8q+mstrideq +2] + WRITE_4x4D 2, 3, 4, 5, dst1q, dst2q, dst8q, mstrideq, strideq, %2 +%endif +%endif + +%if mmsize == 8 +%if %2 == 8 ; chroma +%ifidn %1, h + sub dst1q, 2 +%endif + cmp dst1q, dst8q + mov dst1q, dst8q + jnz .next8px +%else +%ifidn %1, h + lea dst1q, [dst1q+ strideq*8-2] +%else ; v + add dst1q, 8 +%endif + dec cntrq + jg .next8px +%endif + REP_RET +%else ; mmsize == 16 + RET +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +INNER_LOOPFILTER v, 16 +INNER_LOOPFILTER h, 16 +INNER_LOOPFILTER v, 8 +INNER_LOOPFILTER h, 8 + +INIT_MMX mmxext +INNER_LOOPFILTER v, 16 +INNER_LOOPFILTER h, 16 +INNER_LOOPFILTER v, 8 +INNER_LOOPFILTER h, 8 +%endif + +INIT_XMM sse2 +INNER_LOOPFILTER v, 16 +INNER_LOOPFILTER h, 16 +INNER_LOOPFILTER v, 8 +INNER_LOOPFILTER h, 8 + +INIT_XMM ssse3 +INNER_LOOPFILTER v, 16 +INNER_LOOPFILTER h, 16 +INNER_LOOPFILTER v, 8 +INNER_LOOPFILTER h, 8 + +;----------------------------------------------------------------------------- +; void vp8_h/v_loop_filter_mbedge_(uint8_t *dst, [uint8_t *v,] int stride, +; int flimE, int flimI, int hev_thr); +;----------------------------------------------------------------------------- + +%macro MBEDGE_LOOPFILTER 2 +%define stack_size 0 +%ifndef m8 ; stack layout: [0]=E, [1]=I, [2]=hev_thr +%if mmsize == 16 ; [3]=hev() result + ; [4]=filter tmp result + ; [5]/[6] = p2/q2 backup + ; [7]=lim_res sign result +%define stack_size mmsize * -7 +%else ; 8 ; extra storage space for transposes +%define stack_size mmsize * -8 +%endif +%endif + +%if %2 == 8 ; chroma +cglobal vp8_%1_loop_filter8uv_mbedge, 6, 6, 15, stack_size, dst1, dst8, stride, flimE, flimI, hevthr +%else ; luma +cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, flimI, hevthr +%endif + +%if cpuflag(ssse3) + pxor m7, m7 +%endif + +%ifndef m8 + ; splat function arguments + SPLATB_REG m0, flimEq, m7 ; E + SPLATB_REG m1, flimIq, m7 ; I + SPLATB_REG m2, hevthrq, m7 ; hev_thresh + +%define m_flimE [rsp] +%define m_flimI [rsp+mmsize] +%define m_hevthr [rsp+mmsize*2] +%define m_maskres [rsp+mmsize*3] +%define m_limres [rsp+mmsize*4] +%define m_p0backup [rsp+mmsize*3] +%define m_q0backup [rsp+mmsize*4] +%define m_p2backup [rsp+mmsize*5] +%define m_q2backup [rsp+mmsize*6] +%if mmsize == 16 +%define m_limsign [rsp] +%else +%define m_limsign [rsp+mmsize*7] +%endif + + mova m_flimE, m0 + mova m_flimI, m1 + mova m_hevthr, m2 +%else ; sse2 on x86-64 +%define m_flimE m9 +%define m_flimI m10 +%define m_hevthr m11 +%define m_maskres m12 +%define m_limres m8 +%define m_p0backup m12 +%define m_q0backup m8 +%define m_p2backup m13 +%define m_q2backup m14 +%define m_limsign m9 + + ; splat function arguments + SPLATB_REG m_flimE, flimEq, m7 ; E + SPLATB_REG m_flimI, flimIq, m7 ; I + SPLATB_REG m_hevthr, hevthrq, m7 ; hev_thresh +%endif + +%if %2 == 8 ; chroma + DEFINE_ARGS dst1, dst8, mstride, stride, dst2 +%elif mmsize == 8 + DEFINE_ARGS dst1, mstride, stride, dst2, cntr + mov cntrq, 2 +%else + DEFINE_ARGS dst1, mstride, stride, dst2, dst8 +%endif + mov strideq, mstrideq + neg mstrideq +%ifidn %1, h + lea dst1q, [dst1q+strideq*4-4] +%if %2 == 8 ; chroma + lea dst8q, [dst8q+strideq*4-4] +%endif +%endif + +%if mmsize == 8 +.next8px: +%endif + ; read + lea dst2q, [dst1q+ strideq ] +%ifidn %1, v +%if %2 == 8 && mmsize == 16 +%define movrow movh +%else +%define movrow mova +%endif + movrow m0, [dst1q+mstrideq*4] ; p3 + movrow m1, [dst2q+mstrideq*4] ; p2 + movrow m2, [dst1q+mstrideq*2] ; p1 + movrow m5, [dst2q] ; q1 + movrow m6, [dst2q+ strideq ] ; q2 + movrow m7, [dst2q+ strideq*2] ; q3 +%if mmsize == 16 && %2 == 8 + movhps m0, [dst8q+mstrideq*4] + movhps m2, [dst8q+mstrideq*2] + add dst8q, strideq + movhps m1, [dst8q+mstrideq*4] + movhps m5, [dst8q] + movhps m6, [dst8q+ strideq ] + movhps m7, [dst8q+ strideq*2] + add dst8q, mstrideq +%endif +%elif mmsize == 8 ; mmx/mmxext (h) + ; read 8 rows of 8px each + movu m0, [dst1q+mstrideq*4] + movu m1, [dst2q+mstrideq*4] + movu m2, [dst1q+mstrideq*2] + movu m3, [dst1q+mstrideq ] + movu m4, [dst1q] + movu m5, [dst2q] + movu m6, [dst2q+ strideq ] + + ; 8x8 transpose + TRANSPOSE4x4B 0, 1, 2, 3, 7 + mova m_q0backup, m1 + movu m7, [dst2q+ strideq*2] + TRANSPOSE4x4B 4, 5, 6, 7, 1 + SBUTTERFLY dq, 0, 4, 1 ; p3/p2 + SBUTTERFLY dq, 2, 6, 1 ; q0/q1 + SBUTTERFLY dq, 3, 7, 1 ; q2/q3 + mova m1, m_q0backup + mova m_q0backup, m2 ; store q0 + SBUTTERFLY dq, 1, 5, 2 ; p1/p0 + mova m_p0backup, m5 ; store p0 + SWAP 1, 4 + SWAP 2, 4 + SWAP 6, 3 + SWAP 5, 3 +%else ; sse2 (h) +%if %2 == 16 + lea dst8q, [dst1q+ strideq*8 ] +%endif + + ; read 16 rows of 8px each, interleave + movh m0, [dst1q+mstrideq*4] + movh m1, [dst8q+mstrideq*4] + movh m2, [dst1q+mstrideq*2] + movh m5, [dst8q+mstrideq*2] + movh m3, [dst1q+mstrideq ] + movh m6, [dst8q+mstrideq ] + movh m4, [dst1q] + movh m7, [dst8q] + punpcklbw m0, m1 ; A/I + punpcklbw m2, m5 ; C/K + punpcklbw m3, m6 ; D/L + punpcklbw m4, m7 ; E/M + + add dst8q, strideq + movh m1, [dst2q+mstrideq*4] + movh m6, [dst8q+mstrideq*4] + movh m5, [dst2q] + movh m7, [dst8q] + punpcklbw m1, m6 ; B/J + punpcklbw m5, m7 ; F/N + movh m6, [dst2q+ strideq ] + movh m7, [dst8q+ strideq ] + punpcklbw m6, m7 ; G/O + + ; 8x16 transpose + TRANSPOSE4x4B 0, 1, 2, 3, 7 +%ifdef m8 + SWAP 1, 8 +%else + mova m_q0backup, m1 +%endif + movh m7, [dst2q+ strideq*2] + movh m1, [dst8q+ strideq*2] + punpcklbw m7, m1 ; H/P + TRANSPOSE4x4B 4, 5, 6, 7, 1 + SBUTTERFLY dq, 0, 4, 1 ; p3/p2 + SBUTTERFLY dq, 2, 6, 1 ; q0/q1 + SBUTTERFLY dq, 3, 7, 1 ; q2/q3 +%ifdef m8 + SWAP 1, 8 + SWAP 2, 8 +%else + mova m1, m_q0backup + mova m_q0backup, m2 ; store q0 +%endif + SBUTTERFLY dq, 1, 5, 2 ; p1/p0 +%ifdef m12 + SWAP 5, 12 +%else + mova m_p0backup, m5 ; store p0 +%endif + SWAP 1, 4 + SWAP 2, 4 + SWAP 6, 3 + SWAP 5, 3 +%endif + + ; normal_limit for p3-p2, p2-p1, q3-q2 and q2-q1 + mova m4, m1 + SWAP 4, 1 + psubusb m4, m0 ; p2-p3 + psubusb m0, m1 ; p3-p2 + por m0, m4 ; abs(p3-p2) + + mova m4, m2 + SWAP 4, 2 + psubusb m4, m1 ; p1-p2 + mova m_p2backup, m1 + psubusb m1, m2 ; p2-p1 + por m1, m4 ; abs(p2-p1) + + mova m4, m6 + SWAP 4, 6 + psubusb m4, m7 ; q2-q3 + psubusb m7, m6 ; q3-q2 + por m7, m4 ; abs(q3-q2) + + mova m4, m5 + SWAP 4, 5 + psubusb m4, m6 ; q1-q2 + mova m_q2backup, m6 + psubusb m6, m5 ; q2-q1 + por m6, m4 ; abs(q2-q1) + +%if notcpuflag(mmxext) + mova m4, m_flimI + pxor m3, m3 + psubusb m0, m4 + psubusb m1, m4 + psubusb m7, m4 + psubusb m6, m4 + pcmpeqb m0, m3 ; abs(p3-p2) <= I + pcmpeqb m1, m3 ; abs(p2-p1) <= I + pcmpeqb m7, m3 ; abs(q3-q2) <= I + pcmpeqb m6, m3 ; abs(q2-q1) <= I + pand m0, m1 + pand m7, m6 + pand m0, m7 +%else ; mmxext/sse2 + pmaxub m0, m1 + pmaxub m6, m7 + pmaxub m0, m6 +%endif + + ; normal_limit and high_edge_variance for p1-p0, q1-q0 + SWAP 7, 3 ; now m7 is zero +%ifidn %1, v + movrow m3, [dst1q+mstrideq ] ; p0 +%if mmsize == 16 && %2 == 8 + movhps m3, [dst8q+mstrideq ] +%endif +%elifdef m12 + SWAP 3, 12 +%else + mova m3, m_p0backup +%endif + + mova m1, m2 + SWAP 1, 2 + mova m6, m3 + SWAP 3, 6 + psubusb m1, m3 ; p1-p0 + psubusb m6, m2 ; p0-p1 + por m1, m6 ; abs(p1-p0) +%if notcpuflag(mmxext) + mova m6, m1 + psubusb m1, m4 + psubusb m6, m_hevthr + pcmpeqb m1, m7 ; abs(p1-p0) <= I + pcmpeqb m6, m7 ; abs(p1-p0) <= hev_thresh + pand m0, m1 + mova m_maskres, m6 +%else ; mmxext/sse2 + pmaxub m0, m1 ; max_I + SWAP 1, 4 ; max_hev_thresh +%endif + + SWAP 6, 4 ; now m6 is I +%ifidn %1, v + movrow m4, [dst1q] ; q0 +%if mmsize == 16 && %2 == 8 + movhps m4, [dst8q] +%endif +%elifdef m8 + SWAP 4, 8 +%else + mova m4, m_q0backup +%endif + mova m1, m4 + SWAP 1, 4 + mova m7, m5 + SWAP 7, 5 + psubusb m1, m5 ; q0-q1 + psubusb m7, m4 ; q1-q0 + por m1, m7 ; abs(q1-q0) +%if notcpuflag(mmxext) + mova m7, m1 + psubusb m1, m6 + psubusb m7, m_hevthr + pxor m6, m6 + pcmpeqb m1, m6 ; abs(q1-q0) <= I + pcmpeqb m7, m6 ; abs(q1-q0) <= hev_thresh + mova m6, m_maskres + pand m0, m1 ; abs([pq][321]-[pq][210]) <= I + pand m6, m7 +%else ; mmxext/sse2 + pxor m7, m7 + pmaxub m0, m1 + pmaxub m6, m1 + psubusb m0, m_flimI + psubusb m6, m_hevthr + pcmpeqb m0, m7 ; max(abs(..)) <= I + pcmpeqb m6, m7 ; !(max(abs..) > thresh) +%endif +%ifdef m12 + SWAP 6, 12 +%else + mova m_maskres, m6 ; !(abs(p1-p0) > hev_t || abs(q1-q0) > hev_t) +%endif + + ; simple_limit + mova m1, m3 + SWAP 1, 3 + mova m6, m4 ; keep copies of p0/q0 around for later use + SWAP 6, 4 + psubusb m1, m4 ; p0-q0 + psubusb m6, m3 ; q0-p0 + por m1, m6 ; abs(q0-p0) + paddusb m1, m1 ; m1=2*abs(q0-p0) + + mova m7, m2 + SWAP 7, 2 + mova m6, m5 + SWAP 6, 5 + psubusb m7, m5 ; p1-q1 + psubusb m6, m2 ; q1-p1 + por m7, m6 ; abs(q1-p1) + pxor m6, m6 + pand m7, [pb_FE] + psrlq m7, 1 ; abs(q1-p1)/2 + paddusb m7, m1 ; abs(q0-p0)*2+abs(q1-p1)/2 + psubusb m7, m_flimE + pcmpeqb m7, m6 ; abs(q0-p0)*2+abs(q1-p1)/2 <= E + pand m0, m7 ; normal_limit result + + ; filter_common; at this point, m2-m5=p1-q1 and m0 is filter_mask +%ifdef m8 ; x86-64 && sse2 + mova m8, [pb_80] +%define m_pb_80 m8 +%else ; x86-32 or mmx/mmxext +%define m_pb_80 [pb_80] +%endif + mova m1, m4 + mova m7, m3 + pxor m1, m_pb_80 + pxor m7, m_pb_80 + psubsb m1, m7 ; (signed) q0-p0 + mova m6, m2 + mova m7, m5 + pxor m6, m_pb_80 + pxor m7, m_pb_80 + psubsb m6, m7 ; (signed) p1-q1 + mova m7, m_maskres + paddsb m6, m1 + paddsb m6, m1 + paddsb m6, m1 + pand m6, m0 +%ifdef m8 + mova m_limres, m6 ; 3*(qp-p0)+(p1-q1) masked for filter_mbedge + pand m_limres, m7 +%else + mova m0, m6 + pand m0, m7 + mova m_limres, m0 +%endif + pandn m7, m6 ; 3*(q0-p0)+(p1-q1) masked for filter_common + + mova m1, [pb_F8] + mova m6, m7 + paddsb m7, [pb_3] + paddsb m6, [pb_4] + pand m7, m1 + pand m6, m1 + + pxor m1, m1 + pxor m0, m0 + pcmpgtb m1, m7 + psubb m0, m7 + psrlq m7, 3 ; +f2 + psrlq m0, 3 ; -f2 + pand m0, m1 + pandn m1, m7 + psubusb m3, m0 + paddusb m3, m1 ; p0+f2 + + pxor m1, m1 + pxor m0, m0 + pcmpgtb m0, m6 + psubb m1, m6 + psrlq m6, 3 ; +f1 + psrlq m1, 3 ; -f1 + pand m1, m0 + pandn m0, m6 + psubusb m4, m0 + paddusb m4, m1 ; q0-f1 + + ; filter_mbedge (m2-m5 = p1-q1; lim_res carries w) +%if cpuflag(ssse3) + mova m7, [pb_1] +%else + mova m7, [pw_63] +%endif +%ifdef m8 + SWAP 1, 8 +%else + mova m1, m_limres +%endif + pxor m0, m0 + mova m6, m1 + pcmpgtb m0, m1 ; which are negative +%if cpuflag(ssse3) + punpcklbw m6, m7 ; interleave with "1" for rounding + punpckhbw m1, m7 +%else + punpcklbw m6, m0 ; signed byte->word + punpckhbw m1, m0 +%endif + mova m_limsign, m0 +%if cpuflag(ssse3) + mova m7, [pb_27_63] +%ifndef m8 + mova m_limres, m1 +%endif +%ifdef m10 + SWAP 0, 10 ; don't lose lim_sign copy +%endif + mova m0, m7 + pmaddubsw m7, m6 + SWAP 6, 7 + pmaddubsw m0, m1 + SWAP 1, 0 +%ifdef m10 + SWAP 0, 10 +%else + mova m0, m_limsign +%endif +%else + mova m_maskres, m6 ; backup for later in filter + mova m_limres, m1 + pmullw m6, [pw_27] + pmullw m1, [pw_27] + paddw m6, m7 + paddw m1, m7 +%endif + psraw m6, 7 + psraw m1, 7 + packsswb m6, m1 ; a0 + pxor m1, m1 + psubb m1, m6 + pand m1, m0 ; -a0 + pandn m0, m6 ; +a0 +%if cpuflag(ssse3) + mova m6, [pb_18_63] ; pipelining +%endif + psubusb m3, m1 + paddusb m4, m1 + paddusb m3, m0 ; p0+a0 + psubusb m4, m0 ; q0-a0 + +%if cpuflag(ssse3) + SWAP 6, 7 +%ifdef m10 + SWAP 1, 10 +%else + mova m1, m_limres +%endif + mova m0, m7 + pmaddubsw m7, m6 + SWAP 6, 7 + pmaddubsw m0, m1 + SWAP 1, 0 +%ifdef m10 + SWAP 0, 10 +%endif + mova m0, m_limsign +%else + mova m6, m_maskres + mova m1, m_limres + pmullw m6, [pw_18] + pmullw m1, [pw_18] + paddw m6, m7 + paddw m1, m7 +%endif + mova m0, m_limsign + psraw m6, 7 + psraw m1, 7 + packsswb m6, m1 ; a1 + pxor m1, m1 + psubb m1, m6 + pand m1, m0 ; -a1 + pandn m0, m6 ; +a1 +%if cpuflag(ssse3) + mova m6, [pb_9_63] +%endif + psubusb m2, m1 + paddusb m5, m1 + paddusb m2, m0 ; p1+a1 + psubusb m5, m0 ; q1-a1 + +%if cpuflag(ssse3) + SWAP 6, 7 +%ifdef m10 + SWAP 1, 10 +%else + mova m1, m_limres +%endif + mova m0, m7 + pmaddubsw m7, m6 + SWAP 6, 7 + pmaddubsw m0, m1 + SWAP 1, 0 +%else +%ifdef m8 + SWAP 6, 12 + SWAP 1, 8 +%else + mova m6, m_maskres + mova m1, m_limres +%endif + pmullw m6, [pw_9] + pmullw m1, [pw_9] + paddw m6, m7 + paddw m1, m7 +%endif +%ifdef m9 + SWAP 7, 9 +%else + mova m7, m_limsign +%endif + psraw m6, 7 + psraw m1, 7 + packsswb m6, m1 ; a1 + pxor m0, m0 + psubb m0, m6 + pand m0, m7 ; -a1 + pandn m7, m6 ; +a1 +%ifdef m8 + SWAP 1, 13 + SWAP 6, 14 +%else + mova m1, m_p2backup + mova m6, m_q2backup +%endif + psubusb m1, m0 + paddusb m6, m0 + paddusb m1, m7 ; p1+a1 + psubusb m6, m7 ; q1-a1 + + ; store +%ifidn %1, v + movrow [dst2q+mstrideq*4], m1 + movrow [dst1q+mstrideq*2], m2 + movrow [dst1q+mstrideq ], m3 + movrow [dst1q], m4 + movrow [dst2q], m5 + movrow [dst2q+ strideq ], m6 +%if mmsize == 16 && %2 == 8 + add dst8q, mstrideq + movhps [dst8q+mstrideq*2], m1 + movhps [dst8q+mstrideq ], m2 + movhps [dst8q], m3 + add dst8q, strideq + movhps [dst8q], m4 + movhps [dst8q+ strideq ], m5 + movhps [dst8q+ strideq*2], m6 +%endif +%else ; h + inc dst1q + inc dst2q + + ; 4x8/16 transpose + TRANSPOSE4x4B 1, 2, 3, 4, 0 + SBUTTERFLY bw, 5, 6, 0 + +%if mmsize == 8 ; mmx/mmxext (h) + WRITE_4x2D 1, 2, 3, 4, dst1q, dst2q, mstrideq, strideq + add dst1q, 4 + WRITE_2x4W m5, m6, dst2q, dst1q, mstrideq, strideq +%else ; sse2 (h) + lea dst8q, [dst8q+mstrideq+1] + WRITE_4x4D 1, 2, 3, 4, dst1q, dst2q, dst8q, mstrideq, strideq, %2 + lea dst1q, [dst2q+mstrideq+4] + lea dst8q, [dst8q+mstrideq+4] +%if cpuflag(sse4) + add dst2q, 4 +%endif + WRITE_8W m5, dst2q, dst1q, mstrideq, strideq +%if cpuflag(sse4) + lea dst2q, [dst8q+ strideq ] +%endif + WRITE_8W m6, dst2q, dst8q, mstrideq, strideq +%endif +%endif + +%if mmsize == 8 +%if %2 == 8 ; chroma +%ifidn %1, h + sub dst1q, 5 +%endif + cmp dst1q, dst8q + mov dst1q, dst8q + jnz .next8px +%else +%ifidn %1, h + lea dst1q, [dst1q+ strideq*8-5] +%else ; v + add dst1q, 8 +%endif + dec cntrq + jg .next8px +%endif + REP_RET +%else ; mmsize == 16 + RET +%endif +%endmacro + +%if ARCH_X86_32 +INIT_MMX mmx +MBEDGE_LOOPFILTER v, 16 +MBEDGE_LOOPFILTER h, 16 +MBEDGE_LOOPFILTER v, 8 +MBEDGE_LOOPFILTER h, 8 + +INIT_MMX mmxext +MBEDGE_LOOPFILTER v, 16 +MBEDGE_LOOPFILTER h, 16 +MBEDGE_LOOPFILTER v, 8 +MBEDGE_LOOPFILTER h, 8 +%endif + +INIT_XMM sse2 +MBEDGE_LOOPFILTER v, 16 +MBEDGE_LOOPFILTER h, 16 +MBEDGE_LOOPFILTER v, 8 +MBEDGE_LOOPFILTER h, 8 + +INIT_XMM ssse3 +MBEDGE_LOOPFILTER v, 16 +MBEDGE_LOOPFILTER h, 16 +MBEDGE_LOOPFILTER v, 8 +MBEDGE_LOOPFILTER h, 8 + +INIT_XMM sse4 +MBEDGE_LOOPFILTER h, 16 +MBEDGE_LOOPFILTER h, 8 diff --git a/ffmpeg/libavcodec/x86/vp8dsp_init.c b/ffmpeg/libavcodec/x86/vp8dsp_init.c new file mode 100644 index 0000000..09e2d91 --- /dev/null +++ b/ffmpeg/libavcodec/x86/vp8dsp_init.c @@ -0,0 +1,442 @@ +/* + * VP8 DSP functions x86-optimized + * Copyright (c) 2010 Ronald S. Bultje + * Copyright (c) 2010 Jason Garrett-Glaser + * + * 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 "libavutil/cpu.h" +#include "libavutil/mem.h" +#include "libavutil/x86/asm.h" +#include "libavcodec/vp8dsp.h" + +#if HAVE_YASM + +/* + * MC functions + */ +extern void ff_put_vp8_epel4_h4_mmxext(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel4_h6_mmxext(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel4_v4_mmxext(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel4_v6_mmxext(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); + +extern void ff_put_vp8_epel8_h4_sse2 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_h6_sse2 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_v4_sse2 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_v6_sse2 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); + +extern void ff_put_vp8_epel4_h4_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel4_h6_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel4_v4_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel4_v6_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_h4_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_h6_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_v4_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_epel8_v6_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); + +extern void ff_put_vp8_bilinear4_h_mmxext(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_bilinear8_h_sse2 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_bilinear4_h_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_bilinear8_h_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); + +extern void ff_put_vp8_bilinear4_v_mmxext(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_bilinear8_v_sse2 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_bilinear4_v_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_bilinear8_v_ssse3 (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); + + +extern void ff_put_vp8_pixels8_mmx (uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_pixels16_mmx(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); +extern void ff_put_vp8_pixels16_sse(uint8_t *dst, ptrdiff_t dststride, + uint8_t *src, ptrdiff_t srcstride, + int height, int mx, int my); + +#define TAP_W16(OPT, FILTERTYPE, TAPTYPE) \ +static void ff_put_vp8_ ## FILTERTYPE ## 16_ ## TAPTYPE ## _ ## OPT( \ + uint8_t *dst, ptrdiff_t dststride, uint8_t *src, \ + ptrdiff_t srcstride, int height, int mx, int my) \ +{ \ + ff_put_vp8_ ## FILTERTYPE ## 8_ ## TAPTYPE ## _ ## OPT( \ + dst, dststride, src, srcstride, height, mx, my); \ + ff_put_vp8_ ## FILTERTYPE ## 8_ ## TAPTYPE ## _ ## OPT( \ + dst + 8, dststride, src + 8, srcstride, height, mx, my); \ +} +#define TAP_W8(OPT, FILTERTYPE, TAPTYPE) \ +static void ff_put_vp8_ ## FILTERTYPE ## 8_ ## TAPTYPE ## _ ## OPT( \ + uint8_t *dst, ptrdiff_t dststride, uint8_t *src, \ + ptrdiff_t srcstride, int height, int mx, int my) \ +{ \ + ff_put_vp8_ ## FILTERTYPE ## 4_ ## TAPTYPE ## _ ## OPT( \ + dst, dststride, src, srcstride, height, mx, my); \ + ff_put_vp8_ ## FILTERTYPE ## 4_ ## TAPTYPE ## _ ## OPT( \ + dst + 4, dststride, src + 4, srcstride, height, mx, my); \ +} + +#if ARCH_X86_32 +TAP_W8 (mmxext, epel, h4) +TAP_W8 (mmxext, epel, h6) +TAP_W16(mmxext, epel, h6) +TAP_W8 (mmxext, epel, v4) +TAP_W8 (mmxext, epel, v6) +TAP_W16(mmxext, epel, v6) +TAP_W8 (mmxext, bilinear, h) +TAP_W16(mmxext, bilinear, h) +TAP_W8 (mmxext, bilinear, v) +TAP_W16(mmxext, bilinear, v) +#endif + +TAP_W16(sse2, epel, h6) +TAP_W16(sse2, epel, v6) +TAP_W16(sse2, bilinear, h) +TAP_W16(sse2, bilinear, v) + +TAP_W16(ssse3, epel, h6) +TAP_W16(ssse3, epel, v6) +TAP_W16(ssse3, bilinear, h) +TAP_W16(ssse3, bilinear, v) + +#define HVTAP(OPT, ALIGN, TAPNUMX, TAPNUMY, SIZE, MAXHEIGHT) \ +static void ff_put_vp8_epel ## SIZE ## _h ## TAPNUMX ## v ## TAPNUMY ## _ ## OPT( \ + uint8_t *dst, ptrdiff_t dststride, uint8_t *src, \ + ptrdiff_t srcstride, int height, int mx, int my) \ +{ \ + DECLARE_ALIGNED(ALIGN, uint8_t, tmp)[SIZE * (MAXHEIGHT + TAPNUMY - 1)]; \ + uint8_t *tmpptr = tmp + SIZE * (TAPNUMY / 2 - 1); \ + src -= srcstride * (TAPNUMY / 2 - 1); \ + ff_put_vp8_epel ## SIZE ## _h ## TAPNUMX ## _ ## OPT( \ + tmp, SIZE, src, srcstride, height + TAPNUMY - 1, mx, my); \ + ff_put_vp8_epel ## SIZE ## _v ## TAPNUMY ## _ ## OPT( \ + dst, dststride, tmpptr, SIZE, height, mx, my); \ +} + +#if ARCH_X86_32 +#define HVTAPMMX(x, y) \ +HVTAP(mmxext, 8, x, y, 4, 8) \ +HVTAP(mmxext, 8, x, y, 8, 16) + +HVTAP(mmxext, 8, 6, 6, 16, 16) +#else +#define HVTAPMMX(x, y) \ +HVTAP(mmxext, 8, x, y, 4, 8) +#endif + +HVTAPMMX(4, 4) +HVTAPMMX(4, 6) +HVTAPMMX(6, 4) +HVTAPMMX(6, 6) + +#define HVTAPSSE2(x, y, w) \ +HVTAP(sse2, 16, x, y, w, 16) \ +HVTAP(ssse3, 16, x, y, w, 16) + +HVTAPSSE2(4, 4, 8) +HVTAPSSE2(4, 6, 8) +HVTAPSSE2(6, 4, 8) +HVTAPSSE2(6, 6, 8) +HVTAPSSE2(6, 6, 16) + +HVTAP(ssse3, 16, 4, 4, 4, 8) +HVTAP(ssse3, 16, 4, 6, 4, 8) +HVTAP(ssse3, 16, 6, 4, 4, 8) +HVTAP(ssse3, 16, 6, 6, 4, 8) + +#define HVBILIN(OPT, ALIGN, SIZE, MAXHEIGHT) \ +static void ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT( \ + uint8_t *dst, ptrdiff_t dststride, uint8_t *src, \ + ptrdiff_t srcstride, int height, int mx, int my) \ +{ \ + DECLARE_ALIGNED(ALIGN, uint8_t, tmp)[SIZE * (MAXHEIGHT + 2)]; \ + ff_put_vp8_bilinear ## SIZE ## _h_ ## OPT( \ + tmp, SIZE, src, srcstride, height + 1, mx, my); \ + ff_put_vp8_bilinear ## SIZE ## _v_ ## OPT( \ + dst, dststride, tmp, SIZE, height, mx, my); \ +} + +HVBILIN(mmxext, 8, 4, 8) +#if ARCH_X86_32 +HVBILIN(mmxext, 8, 8, 16) +HVBILIN(mmxext, 8, 16, 16) +#endif +HVBILIN(sse2, 8, 8, 16) +HVBILIN(sse2, 8, 16, 16) +HVBILIN(ssse3, 8, 4, 8) +HVBILIN(ssse3, 8, 8, 16) +HVBILIN(ssse3, 8, 16, 16) + +extern void ff_vp8_idct_dc_add_mmx(uint8_t *dst, int16_t block[16], + ptrdiff_t stride); +extern void ff_vp8_idct_dc_add_sse4(uint8_t *dst, int16_t block[16], + ptrdiff_t stride); +extern void ff_vp8_idct_dc_add4y_mmx(uint8_t *dst, int16_t block[4][16], + ptrdiff_t stride); +extern void ff_vp8_idct_dc_add4y_sse2(uint8_t *dst, int16_t block[4][16], + ptrdiff_t stride); +extern void ff_vp8_idct_dc_add4uv_mmx(uint8_t *dst, int16_t block[2][16], + ptrdiff_t stride); +extern void ff_vp8_luma_dc_wht_mmx(int16_t block[4][4][16], int16_t dc[16]); +extern void ff_vp8_luma_dc_wht_sse(int16_t block[4][4][16], int16_t dc[16]); +extern void ff_vp8_idct_add_mmx(uint8_t *dst, int16_t block[16], + ptrdiff_t stride); +extern void ff_vp8_idct_add_sse(uint8_t *dst, int16_t block[16], + ptrdiff_t stride); + +#define DECLARE_LOOP_FILTER(NAME)\ +extern void ff_vp8_v_loop_filter_simple_ ## NAME(uint8_t *dst, \ + ptrdiff_t stride, \ + int flim);\ +extern void ff_vp8_h_loop_filter_simple_ ## NAME(uint8_t *dst, \ + ptrdiff_t stride, \ + int flim);\ +extern void ff_vp8_v_loop_filter16y_inner_ ## NAME (uint8_t *dst, \ + ptrdiff_t stride,\ + int e, int i, int hvt);\ +extern void ff_vp8_h_loop_filter16y_inner_ ## NAME (uint8_t *dst, \ + ptrdiff_t stride,\ + int e, int i, int hvt);\ +extern void ff_vp8_v_loop_filter8uv_inner_ ## NAME (uint8_t *dstU, \ + uint8_t *dstV,\ + ptrdiff_t s, \ + int e, int i, int hvt);\ +extern void ff_vp8_h_loop_filter8uv_inner_ ## NAME (uint8_t *dstU, \ + uint8_t *dstV,\ + ptrdiff_t s, \ + int e, int i, int hvt);\ +extern void ff_vp8_v_loop_filter16y_mbedge_ ## NAME(uint8_t *dst, \ + ptrdiff_t stride,\ + int e, int i, int hvt);\ +extern void ff_vp8_h_loop_filter16y_mbedge_ ## NAME(uint8_t *dst, \ + ptrdiff_t stride,\ + int e, int i, int hvt);\ +extern void ff_vp8_v_loop_filter8uv_mbedge_ ## NAME(uint8_t *dstU, \ + uint8_t *dstV,\ + ptrdiff_t s, \ + int e, int i, int hvt);\ +extern void ff_vp8_h_loop_filter8uv_mbedge_ ## NAME(uint8_t *dstU, \ + uint8_t *dstV,\ + ptrdiff_t s, \ + int e, int i, int hvt); + +DECLARE_LOOP_FILTER(mmx) +DECLARE_LOOP_FILTER(mmxext) +DECLARE_LOOP_FILTER(sse2) +DECLARE_LOOP_FILTER(ssse3) +DECLARE_LOOP_FILTER(sse4) + +#endif /* HAVE_YASM */ + +#define VP8_LUMA_MC_FUNC(IDX, SIZE, OPT) \ + c->put_vp8_epel_pixels_tab[IDX][0][2] = ff_put_vp8_epel ## SIZE ## _h6_ ## OPT; \ + c->put_vp8_epel_pixels_tab[IDX][2][0] = ff_put_vp8_epel ## SIZE ## _v6_ ## OPT; \ + c->put_vp8_epel_pixels_tab[IDX][2][2] = ff_put_vp8_epel ## SIZE ## _h6v6_ ## OPT + +#define VP8_MC_FUNC(IDX, SIZE, OPT) \ + c->put_vp8_epel_pixels_tab[IDX][0][1] = ff_put_vp8_epel ## SIZE ## _h4_ ## OPT; \ + c->put_vp8_epel_pixels_tab[IDX][1][0] = ff_put_vp8_epel ## SIZE ## _v4_ ## OPT; \ + c->put_vp8_epel_pixels_tab[IDX][1][1] = ff_put_vp8_epel ## SIZE ## _h4v4_ ## OPT; \ + c->put_vp8_epel_pixels_tab[IDX][1][2] = ff_put_vp8_epel ## SIZE ## _h6v4_ ## OPT; \ + c->put_vp8_epel_pixels_tab[IDX][2][1] = ff_put_vp8_epel ## SIZE ## _h4v6_ ## OPT; \ + VP8_LUMA_MC_FUNC(IDX, SIZE, OPT) + +#define VP8_BILINEAR_MC_FUNC(IDX, SIZE, OPT) \ + c->put_vp8_bilinear_pixels_tab[IDX][0][1] = ff_put_vp8_bilinear ## SIZE ## _h_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][0][2] = ff_put_vp8_bilinear ## SIZE ## _h_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][1][0] = ff_put_vp8_bilinear ## SIZE ## _v_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][1][1] = ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][1][2] = ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][2][0] = ff_put_vp8_bilinear ## SIZE ## _v_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][2][1] = ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT; \ + c->put_vp8_bilinear_pixels_tab[IDX][2][2] = ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT + + +av_cold void ff_vp8dsp_init_x86(VP8DSPContext* c) +{ +#if HAVE_YASM + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_MMX) { + c->vp8_idct_dc_add = ff_vp8_idct_dc_add_mmx; + c->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_mmx; +#if ARCH_X86_32 + c->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_mmx; + c->vp8_idct_add = ff_vp8_idct_add_mmx; + c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_mmx; + c->put_vp8_epel_pixels_tab[0][0][0] = + c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmx; +#endif + c->put_vp8_epel_pixels_tab[1][0][0] = + c->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmx; + +#if ARCH_X86_32 + c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmx; + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmx; + + c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_mmx; + c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_mmx; + c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmx; + c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmx; + + c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_mmx; + c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmx; + c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmx; + c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmx; +#endif + } + + /* note that 4-tap width=16 functions are missing because w=16 + * is only used for luma, and luma is always a copy or sixtap. */ + if (mm_flags & AV_CPU_FLAG_MMXEXT) { + VP8_MC_FUNC(2, 4, mmxext); + VP8_BILINEAR_MC_FUNC(2, 4, mmxext); +#if ARCH_X86_32 + VP8_LUMA_MC_FUNC(0, 16, mmxext); + VP8_MC_FUNC(1, 8, mmxext); + VP8_BILINEAR_MC_FUNC(0, 16, mmxext); + VP8_BILINEAR_MC_FUNC(1, 8, mmxext); + + c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmxext; + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmxext; + + c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_mmxext; + c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_mmxext; + c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmxext; + c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmxext; + + c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_mmxext; + c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmxext; + c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmxext; + c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmxext; +#endif + } + + if (mm_flags & AV_CPU_FLAG_SSE) { + c->vp8_idct_add = ff_vp8_idct_add_sse; + c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_sse; + c->put_vp8_epel_pixels_tab[0][0][0] = + c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_sse; + } + + if (mm_flags & (AV_CPU_FLAG_SSE2|AV_CPU_FLAG_SSE2SLOW)) { + VP8_LUMA_MC_FUNC(0, 16, sse2); + VP8_MC_FUNC(1, 8, sse2); + VP8_BILINEAR_MC_FUNC(0, 16, sse2); + VP8_BILINEAR_MC_FUNC(1, 8, sse2); + + c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_sse2; + + c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_sse2; + c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_sse2; + + c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_sse2; + c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_sse2; + } + + if (mm_flags & AV_CPU_FLAG_SSE2) { + c->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_sse2; + + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_sse2; + + c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_sse2; + c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_sse2; + + c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_sse2; + c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_sse2; + } + + if (mm_flags & AV_CPU_FLAG_SSSE3) { + VP8_LUMA_MC_FUNC(0, 16, ssse3); + VP8_MC_FUNC(1, 8, ssse3); + VP8_MC_FUNC(2, 4, ssse3); + VP8_BILINEAR_MC_FUNC(0, 16, ssse3); + VP8_BILINEAR_MC_FUNC(1, 8, ssse3); + VP8_BILINEAR_MC_FUNC(2, 4, ssse3); + + c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_ssse3; + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_ssse3; + + c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_ssse3; + c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_ssse3; + c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_ssse3; + c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_ssse3; + + c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_ssse3; + c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_ssse3; + c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_ssse3; + c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_ssse3; + } + + if (mm_flags & AV_CPU_FLAG_SSE4) { + c->vp8_idct_dc_add = ff_vp8_idct_dc_add_sse4; + + c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_sse4; + c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_sse4; + c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_sse4; + } +#endif /* HAVE_YASM */ +} diff --git a/ffmpeg/libavcodec/x86/w64xmmtest.c b/ffmpeg/libavcodec/x86/w64xmmtest.c new file mode 100644 index 0000000..f6e3de9 --- /dev/null +++ b/ffmpeg/libavcodec/x86/w64xmmtest.c @@ -0,0 +1,80 @@ +/* + * check XMM registers for clobbers on Win64 + * Copyright (c) 2012 Ronald S. Bultje + * + * This file is part of Libav. + * + * Libav 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/avcodec.h" +#include "libavutil/x86/w64xmmtest.h" + +wrap(avcodec_open2(AVCodecContext *avctx, + AVCodec *codec, + AVDictionary **options)) +{ + testxmmclobbers(avcodec_open2, avctx, codec, options); +} + +wrap(avcodec_decode_audio4(AVCodecContext *avctx, + AVFrame *frame, + int *got_frame_ptr, + AVPacket *avpkt)) +{ + testxmmclobbers(avcodec_decode_audio4, avctx, frame, + got_frame_ptr, avpkt); +} + +wrap(avcodec_decode_video2(AVCodecContext *avctx, + AVFrame *picture, + int *got_picture_ptr, + AVPacket *avpkt)) +{ + testxmmclobbers(avcodec_decode_video2, avctx, picture, + got_picture_ptr, avpkt); +} + +wrap(avcodec_decode_subtitle2(AVCodecContext *avctx, + AVSubtitle *sub, + int *got_sub_ptr, + AVPacket *avpkt)) +{ + testxmmclobbers(avcodec_decode_subtitle2, avctx, sub, + got_sub_ptr, avpkt); +} + +wrap(avcodec_encode_audio2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr)) +{ + testxmmclobbers(avcodec_encode_audio2, avctx, avpkt, frame, + got_packet_ptr); +} + +wrap(avcodec_encode_video(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const AVFrame *pict)) +{ + testxmmclobbers(avcodec_encode_video, avctx, buf, buf_size, pict); +} + +wrap(avcodec_encode_subtitle(AVCodecContext *avctx, + uint8_t *buf, int buf_size, + const AVSubtitle *sub)) +{ + testxmmclobbers(avcodec_encode_subtitle, avctx, buf, buf_size, sub); +} diff --git a/ffmpeg/libavcodec/xan.c b/ffmpeg/libavcodec/xan.c new file mode 100644 index 0000000..2ee2291 --- /dev/null +++ b/ffmpeg/libavcodec/xan.c @@ -0,0 +1,638 @@ +/* + * Wing Commander/Xan Video Decoder + * Copyright (C) 2003 the ffmpeg project + * + * 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 + */ + +/** + * @file + * Xan video decoder for Wing Commander III computer game + * by Mario Brito (mbrito@student.dei.uc.pt) + * and Mike Melanson (melanson@pcisys.net) + * + * The xan_wc3 decoder outputs PAL8 data. + */ + +#include +#include +#include + +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "avcodec.h" +#include "bytestream.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" + +#define RUNTIME_GAMMA 0 + +#define VGA__TAG MKTAG('V', 'G', 'A', ' ') +#define PALT_TAG MKTAG('P', 'A', 'L', 'T') +#define SHOT_TAG MKTAG('S', 'H', 'O', 'T') +#define PALETTE_COUNT 256 +#define PALETTE_SIZE (PALETTE_COUNT * 3) +#define PALETTES_MAX 256 + +typedef struct XanContext { + + AVCodecContext *avctx; + AVFrame last_frame; + + const unsigned char *buf; + int size; + + /* scratch space */ + unsigned char *buffer1; + int buffer1_size; + unsigned char *buffer2; + int buffer2_size; + + unsigned *palettes; + int palettes_count; + int cur_palette; + + int frame_size; + +} XanContext; + +static av_cold int xan_decode_init(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + + s->avctx = avctx; + s->frame_size = 0; + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + s->buffer1_size = avctx->width * avctx->height; + s->buffer1 = av_malloc(s->buffer1_size); + if (!s->buffer1) + return AVERROR(ENOMEM); + s->buffer2_size = avctx->width * avctx->height; + s->buffer2 = av_malloc(s->buffer2_size + 130); + if (!s->buffer2) { + av_freep(&s->buffer1); + return AVERROR(ENOMEM); + } + avcodec_get_frame_defaults(&s->last_frame); + + return 0; +} + +static int xan_huffman_decode(unsigned char *dest, int dest_len, + const unsigned char *src, int src_len) +{ + unsigned char byte = *src++; + unsigned char ival = byte + 0x16; + const unsigned char * ptr = src + byte*2; + int ptr_len = src_len - 1 - byte*2; + unsigned char val = ival; + unsigned char *dest_end = dest + dest_len; + GetBitContext gb; + + if (ptr_len < 0) + return AVERROR_INVALIDDATA; + + init_get_bits(&gb, ptr, ptr_len * 8); + + while (val != 0x16) { + unsigned idx = val - 0x17 + get_bits1(&gb) * byte; + if (idx >= 2 * byte) + return AVERROR_INVALIDDATA; + val = src[idx]; + + if (val < 0x16) { + if (dest >= dest_end) + return 0; + *dest++ = val; + val = ival; + } + } + + return 0; +} + +/** + * unpack simple compression + * + * @param dest destination buffer of dest_len, must be padded with at least 130 bytes + */ +static void xan_unpack(unsigned char *dest, int dest_len, + const unsigned char *src, int src_len) +{ + unsigned char opcode; + int size; + unsigned char *dest_org = dest; + unsigned char *dest_end = dest + dest_len; + GetByteContext ctx; + + bytestream2_init(&ctx, src, src_len); + while (dest < dest_end && bytestream2_get_bytes_left(&ctx)) { + opcode = bytestream2_get_byte(&ctx); + + if (opcode < 0xe0) { + int size2, back; + if ((opcode & 0x80) == 0) { + size = opcode & 3; + + back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&ctx) + 1; + size2 = ((opcode & 0x1c) >> 2) + 3; + } else if ((opcode & 0x40) == 0) { + size = bytestream2_peek_byte(&ctx) >> 6; + + back = (bytestream2_get_be16(&ctx) & 0x3fff) + 1; + size2 = (opcode & 0x3f) + 4; + } else { + size = opcode & 3; + + back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&ctx) + 1; + size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&ctx) + 5; + } + + if (dest_end - dest < size + size2 || + dest + size - dest_org < back || + bytestream2_get_bytes_left(&ctx) < size) + return; + bytestream2_get_buffer(&ctx, dest, size); + dest += size; + av_memcpy_backptr(dest, back, size2); + dest += size2; + } else { + int finish = opcode >= 0xfc; + size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4; + + if (dest_end - dest < size || bytestream2_get_bytes_left(&ctx) < size) + return; + bytestream2_get_buffer(&ctx, dest, size); + dest += size; + if (finish) + return; + } + } +} + +static inline void xan_wc3_output_pixel_run(XanContext *s, AVFrame *frame, + const unsigned char *pixel_buffer, int x, int y, int pixel_count) +{ + int stride; + int line_inc; + int index; + int current_x; + int width = s->avctx->width; + unsigned char *palette_plane; + + palette_plane = frame->data[0]; + stride = frame->linesize[0]; + line_inc = stride - width; + index = y * stride + x; + current_x = x; + while (pixel_count && index < s->frame_size) { + int count = FFMIN(pixel_count, width - current_x); + memcpy(palette_plane + index, pixel_buffer, count); + pixel_count -= count; + index += count; + pixel_buffer += count; + current_x += count; + + if (current_x >= width) { + index += line_inc; + current_x = 0; + } + } +} + +static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame, + int x, int y, + int pixel_count, int motion_x, + int motion_y) +{ + int stride; + int line_inc; + int curframe_index, prevframe_index; + int curframe_x, prevframe_x; + int width = s->avctx->width; + unsigned char *palette_plane, *prev_palette_plane; + + if (y + motion_y < 0 || y + motion_y >= s->avctx->height || + x + motion_x < 0 || x + motion_x >= s->avctx->width) + return; + + palette_plane = frame->data[0]; + prev_palette_plane = s->last_frame.data[0]; + if (!prev_palette_plane) + prev_palette_plane = palette_plane; + stride = frame->linesize[0]; + line_inc = stride - width; + curframe_index = y * stride + x; + curframe_x = x; + prevframe_index = (y + motion_y) * stride + x + motion_x; + prevframe_x = x + motion_x; + while (pixel_count && + curframe_index < s->frame_size && + prevframe_index < s->frame_size) { + int count = FFMIN3(pixel_count, width - curframe_x, + width - prevframe_x); + + memcpy(palette_plane + curframe_index, + prev_palette_plane + prevframe_index, count); + pixel_count -= count; + curframe_index += count; + prevframe_index += count; + curframe_x += count; + prevframe_x += count; + + if (curframe_x >= width) { + curframe_index += line_inc; + curframe_x = 0; + } + + if (prevframe_x >= width) { + prevframe_index += line_inc; + prevframe_x = 0; + } + } +} + +static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame) +{ + + int width = s->avctx->width; + int height = s->avctx->height; + int total_pixels = width * height; + unsigned char opcode; + unsigned char flag = 0; + int size = 0; + int motion_x, motion_y; + int x, y; + + unsigned char *opcode_buffer = s->buffer1; + unsigned char *opcode_buffer_end = s->buffer1 + s->buffer1_size; + int opcode_buffer_size = s->buffer1_size; + const unsigned char *imagedata_buffer = s->buffer2; + + /* pointers to segments inside the compressed chunk */ + const unsigned char *huffman_segment; + const unsigned char *size_segment; + const unsigned char *vector_segment; + const unsigned char *imagedata_segment; + const unsigned char *buf_end = s->buf + s->size; + int huffman_offset, size_offset, vector_offset, imagedata_offset, + imagedata_size; + + if (s->size < 8) + return AVERROR_INVALIDDATA; + + huffman_offset = AV_RL16(&s->buf[0]); + size_offset = AV_RL16(&s->buf[2]); + vector_offset = AV_RL16(&s->buf[4]); + imagedata_offset = AV_RL16(&s->buf[6]); + + if (huffman_offset >= s->size || + size_offset >= s->size || + vector_offset >= s->size || + imagedata_offset >= s->size) + return AVERROR_INVALIDDATA; + + huffman_segment = s->buf + huffman_offset; + size_segment = s->buf + size_offset; + vector_segment = s->buf + vector_offset; + imagedata_segment = s->buf + imagedata_offset; + + if (xan_huffman_decode(opcode_buffer, opcode_buffer_size, + huffman_segment, s->size - huffman_offset) < 0) + return AVERROR_INVALIDDATA; + + if (imagedata_segment[0] == 2) { + xan_unpack(s->buffer2, s->buffer2_size, + &imagedata_segment[1], s->size - imagedata_offset - 1); + imagedata_size = s->buffer2_size; + } else { + imagedata_size = s->size - imagedata_offset - 1; + imagedata_buffer = &imagedata_segment[1]; + } + + /* use the decoded data segments to build the frame */ + x = y = 0; + while (total_pixels && opcode_buffer < opcode_buffer_end) { + + opcode = *opcode_buffer++; + size = 0; + + switch (opcode) { + + case 0: + flag ^= 1; + continue; + + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + size = opcode; + break; + + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + size += (opcode - 10); + break; + + case 9: + case 19: + if (buf_end - size_segment < 1) { + av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n"); + return AVERROR_INVALIDDATA; + } + size = *size_segment++; + break; + + case 10: + case 20: + if (buf_end - size_segment < 2) { + av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n"); + return AVERROR_INVALIDDATA; + } + size = AV_RB16(&size_segment[0]); + size_segment += 2; + break; + + case 11: + case 21: + if (buf_end - size_segment < 3) { + av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n"); + return AVERROR_INVALIDDATA; + } + size = AV_RB24(size_segment); + size_segment += 3; + break; + } + + if (size > total_pixels) + break; + + if (opcode < 12) { + flag ^= 1; + if (flag) { + /* run of (size) pixels is unchanged from last frame */ + xan_wc3_copy_pixel_run(s, frame, x, y, size, 0, 0); + } else { + /* output a run of pixels from imagedata_buffer */ + if (imagedata_size < size) + break; + xan_wc3_output_pixel_run(s, frame, imagedata_buffer, x, y, size); + imagedata_buffer += size; + imagedata_size -= size; + } + } else { + if (vector_segment >= buf_end) { + av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n"); + return AVERROR_INVALIDDATA; + } + /* run-based motion compensation from last frame */ + motion_x = sign_extend(*vector_segment >> 4, 4); + motion_y = sign_extend(*vector_segment & 0xF, 4); + vector_segment++; + + /* copy a run of pixels from the previous frame */ + xan_wc3_copy_pixel_run(s, frame, x, y, size, motion_x, motion_y); + + flag = 0; + } + + /* coordinate accounting */ + total_pixels -= size; + y += (x + size) / width; + x = (x + size) % width; + } + return 0; +} + +#if RUNTIME_GAMMA +static inline unsigned mul(unsigned a, unsigned b) +{ + return (a * b) >> 16; +} + +static inline unsigned pow4(unsigned a) +{ + unsigned square = mul(a, a); + return mul(square, square); +} + +static inline unsigned pow5(unsigned a) +{ + return mul(pow4(a), a); +} + +static uint8_t gamma_corr(uint8_t in) { + unsigned lo, hi = 0xff40, target; + int i = 15; + in = (in << 2) | (in >> 6); + /* equivalent float code: + if (in >= 252) + return 253; + return round(pow(in / 256.0, 0.8) * 256); + */ + lo = target = in << 8; + do { + unsigned mid = (lo + hi) >> 1; + unsigned pow = pow5(mid); + if (pow > target) hi = mid; + else lo = mid; + } while (--i); + return (pow4((lo + hi) >> 1) + 0x80) >> 8; +} +#else +/** + * This is a gamma correction that xan3 applies to all palette entries. + * + * There is a peculiarity, namely that the values are clamped to 253 - + * it seems likely that this table was calculated by a buggy fixed-point + * implementation, the one above under RUNTIME_GAMMA behaves like this for + * example. + * The exponent value of 0.8 can be explained by this as well, since 0.8 = 4/5 + * and thus pow(x, 0.8) is still easy to calculate. + * Also, the input values are first rotated to the left by 2. + */ +static const uint8_t gamma_lookup[256] = { + 0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C, + 0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50, + 0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71, + 0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F, + 0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC, + 0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, + 0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3, + 0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD, + 0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D, + 0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51, + 0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72, + 0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90, + 0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD, + 0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9, + 0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4, + 0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD, + 0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E, + 0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52, + 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73, + 0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91, + 0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE, + 0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA, + 0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4, + 0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD, + 0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F, + 0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53, + 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74, + 0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92, + 0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF, + 0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB, + 0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5, + 0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD +}; +#endif + +static int xan_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int ret, buf_size = avpkt->size; + XanContext *s = avctx->priv_data; + GetByteContext ctx; + int tag = 0; + + bytestream2_init(&ctx, buf, buf_size); + while (bytestream2_get_bytes_left(&ctx) > 8 && tag != VGA__TAG) { + unsigned *tmpptr; + uint32_t new_pal; + int size; + int i; + tag = bytestream2_get_le32(&ctx); + size = bytestream2_get_be32(&ctx); + if(size < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size); + return AVERROR_INVALIDDATA; + } + size = FFMIN(size, bytestream2_get_bytes_left(&ctx)); + switch (tag) { + case PALT_TAG: + if (size < PALETTE_SIZE) + return AVERROR_INVALIDDATA; + if (s->palettes_count >= PALETTES_MAX) + return AVERROR_INVALIDDATA; + tmpptr = av_realloc(s->palettes, + (s->palettes_count + 1) * AVPALETTE_SIZE); + if (!tmpptr) + return AVERROR(ENOMEM); + s->palettes = tmpptr; + tmpptr += s->palettes_count * AVPALETTE_COUNT; + for (i = 0; i < PALETTE_COUNT; i++) { +#if RUNTIME_GAMMA + int r = gamma_corr(bytestream2_get_byteu(&ctx)); + int g = gamma_corr(bytestream2_get_byteu(&ctx)); + int b = gamma_corr(bytestream2_get_byteu(&ctx)); +#else + int r = gamma_lookup[bytestream2_get_byteu(&ctx)]; + int g = gamma_lookup[bytestream2_get_byteu(&ctx)]; + int b = gamma_lookup[bytestream2_get_byteu(&ctx)]; +#endif + *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b; + } + s->palettes_count++; + break; + case SHOT_TAG: + if (size < 4) + return AVERROR_INVALIDDATA; + new_pal = bytestream2_get_le32(&ctx); + if (new_pal < s->palettes_count) { + s->cur_palette = new_pal; + } else + av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n"); + break; + case VGA__TAG: + break; + default: + bytestream2_skip(&ctx, size); + break; + } + } + buf_size = bytestream2_get_bytes_left(&ctx); + + if (s->palettes_count <= 0) { + av_log(s->avctx, AV_LOG_ERROR, "No palette found\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + if (!s->frame_size) + s->frame_size = frame->linesize[0] * s->avctx->height; + + memcpy(frame->data[1], + s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE); + + s->buf = ctx.buffer; + s->size = buf_size; + + if (xan_wc3_decode_frame(s, frame) < 0) + return AVERROR_INVALIDDATA; + + av_frame_unref(&s->last_frame); + if ((ret = av_frame_ref(&s->last_frame, frame)) < 0) + return ret; + + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int xan_decode_end(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + + av_frame_unref(&s->last_frame); + + av_freep(&s->buffer1); + av_freep(&s->buffer2); + av_freep(&s->palettes); + + return 0; +} + +AVCodec ff_xan_wc3_decoder = { + .name = "xan_wc3", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XAN_WC3, + .priv_data_size = sizeof(XanContext), + .init = xan_decode_init, + .close = xan_decode_end, + .decode = xan_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"), +}; diff --git a/ffmpeg/libavcodec/xbmdec.c b/ffmpeg/libavcodec/xbmdec.c new file mode 100644 index 0000000..51f88a2 --- /dev/null +++ b/ffmpeg/libavcodec/xbmdec.c @@ -0,0 +1,127 @@ +/* + * XBM image format + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "avcodec.h" +#include "internal.h" +#include "mathops.h" +#include "libavutil/avstring.h" + +static av_cold int xbm_decode_init(AVCodecContext *avctx) +{ + + return 0; +} + +static int convert(uint8_t x) +{ + if (x >= 'a') + x -= 87; + else if (x >= 'A') + x -= 55; + else + x -= '0'; + return x; +} + +static int xbm_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *p = data; + const uint8_t *end, *ptr = avpkt->data; + uint8_t *dst; + int ret, linesize, i, j; + + end = avpkt->data + avpkt->size; + while (!avctx->width || !avctx->height) { + char name[256]; + int number, len; + + ptr += strcspn(ptr, "#"); + if (sscanf(ptr, "#define %256s %u", name, &number) != 2) { + av_log(avctx, AV_LOG_ERROR, "Unexpected preprocessor directive\n"); + return AVERROR_INVALIDDATA; + } + + len = strlen(name); + if ((len > 6) && !avctx->height && !memcmp(name + len - 7, "_height", 7)) { + avctx->height = number; + } else if ((len > 5) && !avctx->width && !memcmp(name + len - 6, "_width", 6)) { + avctx->width = number; + } else { + av_log(avctx, AV_LOG_ERROR, "Unknown define '%s'\n", name); + return AVERROR_INVALIDDATA; + } + ptr += strcspn(ptr, "\n\r") + 1; + } + + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + // goto start of image data + ptr += strcspn(ptr, "{") + 1; + + linesize = (avctx->width + 7) / 8; + for (i = 0; i < avctx->height; i++) { + dst = p->data[0] + i * p->linesize[0]; + for (j = 0; j < linesize; j++) { + uint8_t val; + + ptr += strcspn(ptr, "x") + 1; + if (ptr < end && av_isxdigit(*ptr)) { + val = convert(*ptr); + ptr++; + if (av_isxdigit(*ptr)) + val = (val << 4) + convert(*ptr); + *dst++ = ff_reverse[val]; + } else { + av_log(avctx, AV_LOG_ERROR, "Unexpected data at '%.8s'\n", ptr); + return AVERROR_INVALIDDATA; + } + } + } + + p->key_frame = 1; + p->pict_type = AV_PICTURE_TYPE_I; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int xbm_decode_close(AVCodecContext *avctx) +{ + + return 0; +} + +AVCodec ff_xbm_decoder = { + .name = "xbm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XBM, + .init = xbm_decode_init, + .close = xbm_decode_close, + .decode = xbm_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), +}; diff --git a/ffmpeg/libavcodec/xbmenc.c b/ffmpeg/libavcodec/xbmenc.c new file mode 100644 index 0000000..8e39969 --- /dev/null +++ b/ffmpeg/libavcodec/xbmenc.c @@ -0,0 +1,85 @@ +/* + * XBM image format + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "avcodec.h" +#include "internal.h" +#include "mathops.h" + +static av_cold int xbm_encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + return 0; +} + +static int xbm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *p, int *got_packet) +{ + int i, j, ret, size, linesize; + uint8_t *ptr, *buf; + + linesize = (avctx->width + 7) / 8; + size = avctx->height * (linesize * 7 + 2) + 110; + if ((ret = ff_alloc_packet2(avctx, pkt, size)) < 0) + return ret; + + buf = pkt->data; + ptr = p->data[0]; + + buf += snprintf(buf, 32, "#define image_width %u\n", avctx->width); + buf += snprintf(buf, 33, "#define image_height %u\n", avctx->height); + buf += snprintf(buf, 40, "static unsigned char image_bits[] = {\n"); + for (i = 0; i < avctx->height; i++) { + for (j = 0; j < linesize; j++) + buf += snprintf(buf, 7, " 0x%02X,", ff_reverse[*ptr++]); + ptr += p->linesize[0] - linesize; + buf += snprintf(buf, 2, "\n"); + } + buf += snprintf(buf, 5, " };\n"); + + pkt->size = buf - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int xbm_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_xbm_encoder = { + .name = "xbm", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XBM, + .init = xbm_encode_init, + .encode2 = xbm_encode_frame, + .close = xbm_encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), +}; diff --git a/ffmpeg/libavcodec/xface.c b/ffmpeg/libavcodec/xface.c new file mode 100644 index 0000000..0ebf2f2 --- /dev/null +++ b/ffmpeg/libavcodec/xface.c @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1990 James Ashton - Sydney University + * Copyright (c) 2012 Stefano Sabatini + * + * 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 + */ + +/** + * @file + * X-Face common data and utilities definition. + */ + +#include "xface.h" + +void ff_big_add(BigInt *b, uint8_t a) +{ + int i; + uint8_t *w; + uint16_t c; + + a &= XFACE_WORDMASK; + if (a == 0) + return; + w = b->words; + c = a; + for (i = 0; i < b->nb_words && c; i++) { + c += *w; + *w++ = c & XFACE_WORDMASK; + c >>= XFACE_BITSPERWORD; + } + if (i == b->nb_words && c) { + b->nb_words++; + *w = c & XFACE_WORDMASK; + } +} + +void ff_big_div(BigInt *b, uint8_t a, uint8_t *r) +{ + int i; + uint8_t *w; + uint16_t c, d; + + a &= XFACE_WORDMASK; + if (a == 1 || b->nb_words == 0) { + *r = 0; + return; + } + + /* treat this as a == WORDCARRY and just shift everything right a WORD */ + if (a == 0) { + i = --b->nb_words; + w = b->words; + *r = *w; + while (i--) { + *w = *(w + 1); + w++; + } + *w = 0; + return; + } + i = b->nb_words; + w = b->words + i; + c = 0; + while (i--) { + c <<= XFACE_BITSPERWORD; + c += *--w; + d = c / (uint16_t)a; + c = c % (uint16_t)a; + *w = d & XFACE_WORDMASK; + } + *r = c; + if (b->words[b->nb_words - 1] == 0) + b->nb_words--; +} + +void ff_big_mul(BigInt *b, uint8_t a) +{ + int i; + uint8_t *w; + uint16_t c; + + a &= XFACE_WORDMASK; + if (a == 1 || b->nb_words == 0) + return; + if (a == 0) { + /* treat this as a == WORDCARRY and just shift everything left a WORD */ + i = b->nb_words++; + w = b->words + i; + while (i--) { + *w = *(w - 1); + w--; + } + *w = 0; + return; + } + i = b->nb_words; + w = b->words; + c = 0; + while (i--) { + c += (uint16_t)*w * (uint16_t)a; + *(w++) = c & XFACE_WORDMASK; + c >>= XFACE_BITSPERWORD; + } + if (c) { + b->nb_words++; + *w = c & XFACE_WORDMASK; + } +} + +const ProbRange ff_xface_probranges_per_level[4][3] = { + // black grey white + { { 1, 255}, {251, 0}, { 4, 251} }, /* Top of tree almost always grey */ + { { 1, 255}, {200, 0}, { 55, 200} }, + { { 33, 223}, {159, 0}, { 64, 159} }, + { {131, 0}, { 0, 0}, {125, 131} }, /* Grey disallowed at bottom */ +}; + +const ProbRange ff_xface_probranges_2x2[16] = { + { 0, 0}, {38, 0}, {38, 38}, {13, 152}, + {38, 76}, {13, 165}, {13, 178}, { 6, 230}, + {38, 114}, {13, 191}, {13, 204}, { 6, 236}, + {13, 217}, { 6, 242}, { 5, 248}, { 3, 253}, +}; + +/* + * The "guess the next pixel" tables follow. Normally there are 12 + * neighbour pixels used to give 1<<12 cases as we get closer to the + * upper left corner lesser numbers of neighbours are available. + * + * Each byte in the tables represents 8 boolean values starting from + * the most significant bit. + */ + +static const uint8_t g_00[] = { + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xe3, 0xdf, 0x05, 0x17, + 0x05, 0x0f, 0x00, 0x1b, 0x0f, 0xdf, 0x00, 0x04, 0x00, 0x00, + 0x0d, 0x0f, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1d, + 0x45, 0x2f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0a, 0xff, 0xff, + 0x00, 0x04, 0x00, 0x05, 0x01, 0x3f, 0xcf, 0xff, 0x10, 0x01, + 0x80, 0xc9, 0x0f, 0x0f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x1f, 0xff, 0xff, 0x4f, 0x54, 0x07, 0x1f, 0x57, 0x47, + 0xd7, 0x3d, 0xff, 0xff, 0x5f, 0x1f, 0x7f, 0xff, 0x7f, 0x7f, + 0x05, 0x0f, 0x01, 0x0f, 0x0f, 0x5f, 0x9b, 0xdf, 0x7f, 0xff, + 0x5f, 0x1d, 0x5f, 0xff, 0x0f, 0x1f, 0x0f, 0x5f, 0x03, 0x1f, + 0x4f, 0x5f, 0xf7, 0x7f, 0x7f, 0xff, 0x0d, 0x0f, 0xfb, 0xff, + 0xf7, 0xbf, 0x0f, 0x4f, 0xd7, 0x3f, 0x4f, 0x7f, 0xff, 0xff, + 0x67, 0xbf, 0x56, 0x25, 0x1f, 0x7f, 0x9f, 0xff, 0x00, 0x00, + 0x00, 0x05, 0x5f, 0x7f, 0x01, 0xdf, 0x14, 0x00, 0x05, 0x0f, + 0x07, 0xa2, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x5f, + 0x18, 0xd7, 0x94, 0x71, 0x00, 0x05, 0x1f, 0xb7, 0x0c, 0x07, + 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x1f, 0x84, 0x8f, 0x05, 0x15, + 0x05, 0x0f, 0x4f, 0xff, 0x87, 0xdf, 0x05, 0x01, 0x10, 0x00, + 0x0f, 0x0f, 0x00, 0x08, 0x05, 0x04, 0x04, 0x01, 0x4f, 0xff, + 0x9f, 0x8f, 0x4a, 0x40, 0x5f, 0x5f, 0xff, 0xfe, 0xdf, 0xff, + 0x7f, 0xf7, 0xff, 0x7f, 0xff, 0xff, 0x7b, 0xff, 0x0f, 0xfd, + 0xd7, 0x5f, 0x4f, 0x7f, 0x7f, 0xdf, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x77, 0xdf, 0x7f, 0x4f, 0xef, 0xff, 0xff, 0x77, 0xff, + 0xff, 0xff, 0x6f, 0xff, 0x0f, 0x4f, 0xff, 0xff, 0x9d, 0xff, + 0x0f, 0xef, 0xff, 0xdf, 0x6f, 0xff, 0xff, 0xff, 0x4f, 0xff, + 0xcd, 0x0f, 0x4f, 0xff, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x0b, + 0x05, 0x02, 0x02, 0x0f, 0x04, 0x00, 0x00, 0x0c, 0x01, 0x06, + 0x00, 0x0f, 0x20, 0x03, 0x00, 0x00, 0x05, 0x0f, 0x40, 0x08, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x0c, 0x0f, 0x01, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x14, 0x01, 0x05, + 0x01, 0x15, 0xaf, 0x0f, 0x00, 0x01, 0x10, 0x00, 0x08, 0x00, + 0x46, 0x0c, 0x20, 0x00, 0x88, 0x00, 0x0f, 0x15, 0xff, 0xdf, + 0x02, 0x00, 0x00, 0x0f, 0x7f, 0x5f, 0xdb, 0xff, 0x4f, 0x3e, + 0x05, 0x0f, 0x7f, 0xf7, 0x95, 0x4f, 0x0d, 0x0f, 0x01, 0x0f, + 0x4f, 0x5f, 0x9f, 0xdf, 0x25, 0x0e, 0x0d, 0x0d, 0x4f, 0x7f, + 0x8f, 0x0f, 0x0f, 0xfa, 0x04, 0x4f, 0x4f, 0xff, 0xf7, 0x77, + 0x47, 0xed, 0x05, 0x0f, 0xff, 0xff, 0xdf, 0xff, 0x4f, 0x6f, + 0xd8, 0x5f, 0x0f, 0x7f, 0xdf, 0x5f, 0x07, 0x0f, 0x94, 0x0d, + 0x1f, 0xff, 0xff, 0xff, 0x00, 0x02, 0x00, 0x03, 0x46, 0x57, + 0x01, 0x0d, 0x01, 0x08, 0x01, 0x0f, 0x47, 0x6c, 0x0d, 0x0f, + 0x02, 0x00, 0x00, 0x00, 0x0b, 0x4f, 0x00, 0x08, 0x05, 0x00, + 0x95, 0x01, 0x0f, 0x7f, 0x0c, 0x0f, 0x01, 0x0e, 0x00, 0x00, + 0x0f, 0x41, 0x00, 0x00, 0x04, 0x24, 0x0d, 0x0f, 0x0f, 0x7f, + 0xcf, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, + 0x06, 0x26, 0xcf, 0x05, 0xcf, 0x7f, 0xdf, 0xdf, 0x00, 0x00, + 0x17, 0x5f, 0xff, 0xfd, 0xff, 0xff, 0x46, 0x09, 0x4f, 0x5f, + 0x7f, 0xfd, 0xdf, 0xff, 0x0a, 0x88, 0xa7, 0x7f, 0x7f, 0xff, + 0xff, 0xff, 0x0f, 0x04, 0xdf, 0x7f, 0x4f, 0xff, 0x9f, 0xff, + 0x0e, 0xe6, 0xdf, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x0f, 0xec, + 0x8f, 0x4f, 0x7f, 0xff, 0xdf, 0xff, 0x0f, 0xcf, 0xdf, 0xff, + 0x6f, 0x7f, 0xff, 0xff, 0x03, 0x0c, 0x9d, 0x0f, 0x7f, 0xff, + 0xff, 0xff, +}; + +static const uint8_t g_01[] = { + 0x37, 0x73, 0x00, 0x19, 0x57, 0x7f, 0xf5, 0xfb, 0x70, 0x33, + 0xf0, 0xf9, 0x7f, 0xff, 0xff, 0xff, +}; + +static const uint8_t g_02[] = { + 0x50, +}; + +static const uint8_t g_10[] = { + 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0xf3, 0x5f, 0x84, 0x04, + 0x17, 0x9f, 0x04, 0x23, 0x05, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x03, 0x03, 0x33, 0xd7, 0x05, 0x03, 0x5f, 0x3f, 0x17, 0x33, + 0xff, 0xff, 0x00, 0x80, 0x02, 0x04, 0x12, 0x00, 0x11, 0x57, + 0x05, 0x25, 0x05, 0x03, 0x35, 0xbf, 0x9f, 0xff, 0x07, 0x6f, + 0x20, 0x40, 0x17, 0x06, 0xfa, 0xe8, 0x01, 0x07, 0x1f, 0x9f, + 0x1f, 0xff, 0xff, 0xff, +}; + +static const uint8_t g_20[] = { + 0x04, 0x00, 0x01, 0x01, 0x43, 0x2e, 0xff, 0x3f, +}; + +static const uint8_t g_30[] = { + 0x11, 0x11, 0x11, 0x11, 0x51, 0x11, 0x13, 0x11, 0x11, 0x11, + 0x13, 0x11, 0x11, 0x11, 0x33, 0x11, 0x13, 0x11, 0x13, 0x13, + 0x13, 0x13, 0x31, 0x31, 0x11, 0x01, 0x11, 0x11, 0x71, 0x11, + 0x11, 0x75, +}; + +static const uint8_t g_40[] = { + 0x00, 0x0f, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, + 0x00, 0x4e, 0xe4, 0x0d, 0x10, 0x0f, 0x00, 0x0f, 0x44, 0x4f, + 0x00, 0x1e, 0x0f, 0x0f, 0xae, 0xaf, 0x45, 0x7f, 0xef, 0xff, + 0x0f, 0xff, 0x00, 0x09, 0x01, 0x11, 0x00, 0x01, 0x1c, 0xdd, + 0x00, 0x15, 0x00, 0xff, 0x00, 0x10, 0x00, 0xfd, 0x00, 0x0f, + 0x4f, 0x5f, 0x3d, 0xff, 0xff, 0xff, 0x4f, 0xff, 0x1c, 0xff, + 0xdf, 0xff, 0x8f, 0xff, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x15, + 0x01, 0x07, 0x00, 0x01, 0x02, 0x1f, 0x01, 0x11, 0x05, 0x7f, + 0x00, 0x1f, 0x41, 0x57, 0x1f, 0xff, 0x05, 0x77, 0x0d, 0x5f, + 0x4d, 0xff, 0x4f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x02, 0x05, + 0x00, 0x11, 0x05, 0x7d, 0x10, 0x15, 0x2f, 0xff, 0x40, 0x50, + 0x0d, 0xfd, 0x04, 0x0f, 0x07, 0x1f, 0x07, 0x7f, 0x0f, 0xbf, + 0x0d, 0x7f, 0x0f, 0xff, 0x4d, 0x7d, 0x0f, 0xff, +}; + +static const uint8_t g_11[] = { + 0x01, 0x13, 0x03, 0x7f, +}; + +static const uint8_t g_21[] = { + 0x17, +}; + +static const uint8_t g_31[] = { + 0x55, 0x57, 0x57, 0x7f, +}; + +static const uint8_t g_41[] = { + 0x01, 0x01, 0x01, 0x1f, 0x03, 0x1f, 0x3f, 0xff, +}; + +static const uint8_t g_12[] = { + 0x40, +}; + +static const uint8_t g_22[] = { + 0x00, +}; + +static const uint8_t g_32[] = { + 0x10, +}; + +static const uint8_t g_42[] = { + 0x10, +}; + +void ff_xface_generate_face(uint8_t *dst, uint8_t * const src) +{ + int h, i, j, k, l, m; + + for (j = 0; j < XFACE_HEIGHT; j++) { + for (i = 0; i < XFACE_WIDTH; i++) { + h = i + j * XFACE_WIDTH; + k = 0; + + /* + Compute k, encoding the bits *before* the current one, contained in the + image buffer. That is, given the grid: + + l i + | | + v v + +--+--+--+--+--+ + m -> | 1| 2| 3| 4| 5| + +--+--+--+--+--+ + | 6| 7| 8| 9|10| + +--+--+--+--+--+ + j -> |11|12| *| | | + +--+--+--+--+--+ + + the value k for the pixel marked as "*" will contain the bit encoding of + the values in the matrix marked from "1" to "12". In case the pixel is + near the border of the grid, the number of values contained within the + grid will be lesser than 12. + */ + + for (l = i - 2; l <= i + 2; l++) { + for (m = j - 2; m <= j; m++) { + if (l >= i && m == j) + continue; + if (l > 0 && l <= XFACE_WIDTH && m > 0) + k = 2*k + src[l + m * XFACE_WIDTH]; + } + } + + /* + Use the guess for the given position and the computed value of k. + + The following table shows the number of digits in k, depending on + the position of the pixel, and shows the corresponding guess table + to use: + + i=1 i=2 i=3 i=w-1 i=w + +----+----+----+ ... +----+----+ + j=1 | 0 | 1 | 2 | | 2 | 2 | + |g22 |g12 |g02 | |g42 |g32 | + +----+----+----+ ... +----+----+ + j=2 | 3 | 5 | 7 | | 6 | 5 | + |g21 |g11 |g01 | |g41 |g31 | + +----+----+----+ ... +----+----+ + j=3 | 5 | 9 | 12 | | 10 | 8 | + |g20 |g10 |g00 | |g40 |g30 | + +----+----+----+ ... +----+----+ + */ + +#define GEN(table) dst[h] ^= (table[k>>3]>>(7-(k&7)))&1 + + switch (i) { + case 1: + switch (j) { + case 1: GEN(g_22); break; + case 2: GEN(g_21); break; + default: GEN(g_20); break; + } + break; + case 2: + switch (j) { + case 1: GEN(g_12); break; + case 2: GEN(g_11); break; + default: GEN(g_10); break; + } + break; + case XFACE_WIDTH - 1: + switch (j) { + case 1: GEN(g_42); break; + case 2: GEN(g_41); break; + default: GEN(g_40); break; + } + break; + case XFACE_WIDTH: + switch (j) { + case 1: GEN(g_32); break; + case 2: GEN(g_31); break; + default: GEN(g_30); break; + } + break; + default: + switch (j) { + case 1: GEN(g_02); break; + case 2: GEN(g_01); break; + default: GEN(g_00); break; + } + break; + } + } + } +} diff --git a/ffmpeg/libavcodec/xface.h b/ffmpeg/libavcodec/xface.h new file mode 100644 index 0000000..cd59ba0 --- /dev/null +++ b/ffmpeg/libavcodec/xface.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1990 James Ashton - Sydney University + * Copyright (c) 2012 Stefano Sabatini + * + * 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 + */ + +/** + * @file + * X-Face common definitions. + */ + +#include + +/* define the face size - 48x48x1 */ +#define XFACE_WIDTH 48 +#define XFACE_HEIGHT 48 +#define XFACE_PIXELS (XFACE_WIDTH * XFACE_HEIGHT) + +/* compressed output uses the full range of printable characters. + * In ASCII these are in a contiguous block so we just need to know + * the first and last. The total number of printables is needed too. */ +#define XFACE_FIRST_PRINT '!' +#define XFACE_LAST_PRINT '~' +#define XFACE_PRINTS (XFACE_LAST_PRINT - XFACE_FIRST_PRINT + 1) + +/* + * Image is encoded as a big integer, using characters from '~' to + * '!', for a total of 92 symbols. In order to express 48x48=2304 + * bits, we need a total of 354 digits, as given by: + * ceil(lg_92(2^2304)) = 354 + */ +#define XFACE_MAX_DIGITS 354 + +#define XFACE_BITSPERWORD 8 +#define XFACE_WORDCARRY (1 << XFACE_BITSPERWORD) +#define XFACE_WORDMASK (XFACE_WORDCARRY - 1) + +#define XFACE_MAX_WORDS ((XFACE_PIXELS * 2 + XFACE_BITSPERWORD - 1) / XFACE_BITSPERWORD) + +/* Portable, very large unsigned integer arithmetic is needed. + * Implementation uses arrays of WORDs. */ +typedef struct { + int nb_words; + uint8_t words[XFACE_MAX_WORDS]; +} BigInt; + +/** + * Add a to b storing the result in b. + */ +void ff_big_add(BigInt *b, uint8_t a); + +/** + * Divide b by a storing the result in b and the remainder in the word + * pointed to by r. + */ +void ff_big_div(BigInt *b, uint8_t a, uint8_t *r); + +/** + * Multiply a by b storing the result in b. + */ +void ff_big_mul(BigInt *b, uint8_t a); + +/* Each face is encoded using 9 octrees of 16x16 each. Each level of the + * trees has varying probabilities of being white, grey or black. + * The table below is based on sampling many faces */ +enum XFaceColor { XFACE_COLOR_BLACK = 0, XFACE_COLOR_GREY, XFACE_COLOR_WHITE }; + +/* Data of varying probabilities are encoded by a value in the range 0 - 255. + * The probability of the data determines the range of possible encodings. + * Offset gives the first possible encoding of the range. */ +typedef struct { + int range; + int offset; +} ProbRange; + +extern const ProbRange ff_xface_probranges_per_level[4][3]; + +extern const ProbRange ff_xface_probranges_2x2[16]; + +void ff_xface_generate_face(uint8_t *dst, uint8_t * const src); diff --git a/ffmpeg/libavcodec/xfacedec.c b/ffmpeg/libavcodec/xfacedec.c new file mode 100644 index 0000000..fbaabdb --- /dev/null +++ b/ffmpeg/libavcodec/xfacedec.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1990 James Ashton - Sydney University + * Copyright (c) 2012 Stefano Sabatini + * + * 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 + */ + +/** + * @file + * X-Face decoder, based on libcompface, by James Ashton. + */ + +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "xface.h" + +static int pop_integer(BigInt *b, const ProbRange *pranges) +{ + uint8_t r; + int i; + + /* extract the last byte into r, and shift right b by 8 bits */ + ff_big_div(b, 0, &r); + + i = 0; + while (r < pranges->offset || r >= pranges->range + pranges->offset) { + pranges++; + i++; + } + ff_big_mul(b, pranges->range); + ff_big_add(b, r - pranges->offset); + return i; +} + +static void pop_greys(BigInt *b, char *bitmap, int w, int h) +{ + if (w > 3) { + w /= 2; + h /= 2; + pop_greys(b, bitmap, w, h); + pop_greys(b, bitmap + w, w, h); + pop_greys(b, bitmap + XFACE_WIDTH * h, w, h); + pop_greys(b, bitmap + XFACE_WIDTH * h + w, w, h); + } else { + w = pop_integer(b, ff_xface_probranges_2x2); + if (w & 1) bitmap[0] = 1; + if (w & 2) bitmap[1] = 1; + if (w & 4) bitmap[XFACE_WIDTH] = 1; + if (w & 8) bitmap[XFACE_WIDTH + 1] = 1; + } +} + +static void decode_block(BigInt *b, char *bitmap, int w, int h, int level) +{ + switch (pop_integer(b, &ff_xface_probranges_per_level[level][0])) { + case XFACE_COLOR_WHITE: + return; + case XFACE_COLOR_BLACK: + pop_greys(b, bitmap, w, h); + return; + default: + w /= 2; + h /= 2; + level++; + decode_block(b, bitmap, w, h, level); + decode_block(b, bitmap + w, w, h, level); + decode_block(b, bitmap + h * XFACE_WIDTH, w, h, level); + decode_block(b, bitmap + w + h * XFACE_WIDTH, w, h, level); + return; + } +} + +typedef struct XFaceContext { + uint8_t bitmap[XFACE_PIXELS]; ///< image used internally for decoding +} XFaceContext; + +static av_cold int xface_decode_init(AVCodecContext *avctx) +{ + if (avctx->width || avctx->height) { + if (avctx->width != XFACE_WIDTH || avctx->height != XFACE_HEIGHT) { + av_log(avctx, AV_LOG_ERROR, + "Size value %dx%d not supported, only accepts a size of %dx%d\n", + avctx->width, avctx->height, XFACE_WIDTH, XFACE_HEIGHT); + return AVERROR(EINVAL); + } + } + + avctx->width = XFACE_WIDTH; + avctx->height = XFACE_HEIGHT; + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + + return 0; +} + +static int xface_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + XFaceContext *xface = avctx->priv_data; + int ret, i, j, k; + uint8_t byte; + BigInt b = {0}; + char *buf; + int64_t c; + AVFrame *frame = data; + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + for (i = 0, k = 0; avpkt->data[i] && i < avpkt->size; i++) { + c = avpkt->data[i]; + + /* ignore invalid digits */ + if (c < XFACE_FIRST_PRINT || c > XFACE_LAST_PRINT) + continue; + + if (++k > XFACE_MAX_DIGITS) { + av_log(avctx, AV_LOG_WARNING, + "Buffer is longer than expected, truncating at byte %d\n", i); + break; + } + ff_big_mul(&b, XFACE_PRINTS); + ff_big_add(&b, c - XFACE_FIRST_PRINT); + } + + /* decode image and put it in bitmap */ + memset(xface->bitmap, 0, XFACE_PIXELS); + buf = xface->bitmap; + decode_block(&b, buf, 16, 16, 0); + decode_block(&b, buf + 16, 16, 16, 0); + decode_block(&b, buf + 32, 16, 16, 0); + decode_block(&b, buf + XFACE_WIDTH * 16, 16, 16, 0); + decode_block(&b, buf + XFACE_WIDTH * 16 + 16, 16, 16, 0); + decode_block(&b, buf + XFACE_WIDTH * 16 + 32, 16, 16, 0); + decode_block(&b, buf + XFACE_WIDTH * 32 , 16, 16, 0); + decode_block(&b, buf + XFACE_WIDTH * 32 + 16, 16, 16, 0); + decode_block(&b, buf + XFACE_WIDTH * 32 + 32, 16, 16, 0); + + ff_xface_generate_face(xface->bitmap, xface->bitmap); + + /* convert image from 1=black 0=white bitmap to MONOWHITE */ + buf = frame->data[0]; + for (i = 0, j = 0, k = 0, byte = 0; i < XFACE_PIXELS; i++) { + byte += xface->bitmap[i]; + if (k == 7) { + buf[j++] = byte; + byte = k = 0; + } else { + k++; + byte <<= 1; + } + if (j == XFACE_WIDTH/8) { + j = 0; + buf += frame->linesize[0]; + } + } + + *got_frame = 1; + + return avpkt->size; +} + +AVCodec ff_xface_decoder = { + .name = "xface", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XFACE, + .priv_data_size = sizeof(XFaceContext), + .init = xface_decode_init, + .decode = xface_decode_frame, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("X-face image"), +}; diff --git a/ffmpeg/libavcodec/xfaceenc.c b/ffmpeg/libavcodec/xfaceenc.c new file mode 100644 index 0000000..5206afd --- /dev/null +++ b/ffmpeg/libavcodec/xfaceenc.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 1990 James Ashton - Sydney University + * Copyright (c) 2012 Stefano Sabatini + * + * 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 + */ + +/** + * @file + * X-Face encoder, based on libcompface, by James Ashton. + */ + +#include "xface.h" +#include "avcodec.h" +#include "internal.h" + +typedef struct XFaceContext { + AVClass *class; + uint8_t bitmap[XFACE_PIXELS]; ///< image used internally for decoding + int max_line_len; ///< max line length for compressed data + int set_header; ///< set X-Face header in the output +} XFaceContext; + +static int all_same(char *bitmap, int w, int h) +{ + char val, *row; + int x; + + val = *bitmap; + while (h--) { + row = bitmap; + x = w; + while (x--) + if (*(row++) != val) + return 0; + bitmap += XFACE_WIDTH; + } + return 1; +} + +static int all_black(char *bitmap, int w, int h) +{ + if (w > 3) { + w /= 2; + h /= 2; + return (all_black(bitmap, w, h) && all_black(bitmap + w, w, h) && + all_black(bitmap + XFACE_WIDTH * h, w, h) && + all_black(bitmap + XFACE_WIDTH * h + w, w, h)); + } else { + /* at least one pixel in the 2x2 grid is non-zero */ + return *bitmap || *(bitmap + 1) || + *(bitmap + XFACE_WIDTH) || *(bitmap + XFACE_WIDTH + 1); + } +} + +static int all_white(char *bitmap, int w, int h) +{ + return *bitmap == 0 && all_same(bitmap, w, h); +} + +typedef struct { + const ProbRange *prob_ranges[XFACE_PIXELS*2]; + int prob_ranges_idx; +} ProbRangesQueue; + +static inline int pq_push(ProbRangesQueue *pq, const ProbRange *p) +{ + if (pq->prob_ranges_idx >= XFACE_PIXELS * 2 - 1) + return -1; + pq->prob_ranges[pq->prob_ranges_idx++] = p; + return 0; +} + +static void push_greys(ProbRangesQueue *pq, char *bitmap, int w, int h) +{ + if (w > 3) { + w /= 2; + h /= 2; + push_greys(pq, bitmap, w, h); + push_greys(pq, bitmap + w, w, h); + push_greys(pq, bitmap + XFACE_WIDTH * h, w, h); + push_greys(pq, bitmap + XFACE_WIDTH * h + w, w, h); + } else { + const ProbRange *p = ff_xface_probranges_2x2 + + *bitmap + + 2 * *(bitmap + 1) + + 4 * *(bitmap + XFACE_WIDTH) + + 8 * *(bitmap + XFACE_WIDTH + 1); + pq_push(pq, p); + } +} + +static void encode_block(char *bitmap, int w, int h, int level, ProbRangesQueue *pq) +{ + if (all_white(bitmap, w, h)) { + pq_push(pq, &ff_xface_probranges_per_level[level][XFACE_COLOR_WHITE]); + } else if (all_black(bitmap, w, h)) { + pq_push(pq, &ff_xface_probranges_per_level[level][XFACE_COLOR_BLACK]); + push_greys(pq, bitmap, w, h); + } else { + pq_push(pq, &ff_xface_probranges_per_level[level][XFACE_COLOR_GREY]); + w /= 2; + h /= 2; + level++; + encode_block(bitmap, w, h, level, pq); + encode_block(bitmap + w, w, h, level, pq); + encode_block(bitmap + h * XFACE_WIDTH, w, h, level, pq); + encode_block(bitmap + w + h * XFACE_WIDTH, w, h, level, pq); + } +} + +static av_cold int xface_encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + return 0; +} + +static void push_integer(BigInt *b, const ProbRange *prange) +{ + uint8_t r; + + ff_big_div(b, prange->range, &r); + ff_big_mul(b, 0); + ff_big_add(b, r + prange->offset); +} + +static int xface_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + XFaceContext *xface = avctx->priv_data; + ProbRangesQueue pq = {{ 0 }, 0}; + uint8_t bitmap_copy[XFACE_PIXELS]; + BigInt b = {0}; + int i, j, k, ret = 0; + const uint8_t *buf; + uint8_t *p; + char intbuf[XFACE_MAX_DIGITS]; + + if (avctx->width || avctx->height) { + if (avctx->width != XFACE_WIDTH || avctx->height != XFACE_HEIGHT) { + av_log(avctx, AV_LOG_ERROR, + "Size value %dx%d not supported, only accepts a size of %dx%d\n", + avctx->width, avctx->height, XFACE_WIDTH, XFACE_HEIGHT); + return AVERROR(EINVAL); + } + } + avctx->width = XFACE_WIDTH; + avctx->height = XFACE_HEIGHT; + + /* convert image from MONOWHITE to 1=black 0=white bitmap */ + buf = frame->data[0]; + i = j = 0; + do { + for (k = 0; k < 8; k++) + xface->bitmap[i++] = (buf[j]>>(7-k))&1; + if (++j == XFACE_WIDTH/8) { + buf += frame->linesize[0]; + j = 0; + } + } while (i < XFACE_PIXELS); + + /* create a copy of bitmap */ + memcpy(bitmap_copy, xface->bitmap, XFACE_PIXELS); + ff_xface_generate_face(xface->bitmap, bitmap_copy); + + encode_block(xface->bitmap, 16, 16, 0, &pq); + encode_block(xface->bitmap + 16, 16, 16, 0, &pq); + encode_block(xface->bitmap + 32, 16, 16, 0, &pq); + encode_block(xface->bitmap + XFACE_WIDTH * 16, 16, 16, 0, &pq); + encode_block(xface->bitmap + XFACE_WIDTH * 16 + 16, 16, 16, 0, &pq); + encode_block(xface->bitmap + XFACE_WIDTH * 16 + 32, 16, 16, 0, &pq); + encode_block(xface->bitmap + XFACE_WIDTH * 32, 16, 16, 0, &pq); + encode_block(xface->bitmap + XFACE_WIDTH * 32 + 16, 16, 16, 0, &pq); + encode_block(xface->bitmap + XFACE_WIDTH * 32 + 32, 16, 16, 0, &pq); + + while (pq.prob_ranges_idx > 0) + push_integer(&b, pq.prob_ranges[--pq.prob_ranges_idx]); + + /* write the inverted big integer in b to intbuf */ + i = 0; + while (b.nb_words) { + uint8_t r; + ff_big_div(&b, XFACE_PRINTS, &r); + intbuf[i++] = r + XFACE_FIRST_PRINT; + } + + if ((ret = ff_alloc_packet2(avctx, pkt, i+2)) < 0) + return ret; + + /* revert the number, and close the buffer */ + p = pkt->data; + while (--i >= 0) + *(p++) = intbuf[i]; + *(p++) = '\n'; + *(p++) = 0; + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; +} + +static av_cold int xface_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_xface_encoder = { + .name = "xface", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XFACE, + .priv_data_size = sizeof(XFaceContext), + .init = xface_encode_init, + .close = xface_encode_close, + .encode2 = xface_encode_frame, + .pix_fmts = (const enum PixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("X-face image"), +}; diff --git a/ffmpeg/libavcodec/xiph.c b/ffmpeg/libavcodec/xiph.c new file mode 100644 index 0000000..0636f8e --- /dev/null +++ b/ffmpeg/libavcodec/xiph.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007 FFmpeg Project + * + * 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 "libavutil/intreadwrite.h" +#include "xiph.h" + +int avpriv_split_xiph_headers(uint8_t *extradata, int extradata_size, + int first_header_size, uint8_t *header_start[3], + int header_len[3]) +{ + int i; + + if (extradata_size >= 6 && AV_RB16(extradata) == first_header_size) { + int overall_len = 6; + for (i=0; i<3; i++) { + header_len[i] = AV_RB16(extradata); + extradata += 2; + header_start[i] = extradata; + extradata += header_len[i]; + if (overall_len > extradata_size - header_len[i]) + return -1; + overall_len += header_len[i]; + } + } else if (extradata_size >= 3 && extradata_size < INT_MAX - 0x1ff && extradata[0] == 2) { + int overall_len = 3; + extradata++; + for (i=0; i<2; i++, extradata++) { + header_len[i] = 0; + for (; overall_len < extradata_size && *extradata==0xff; extradata++) { + header_len[i] += 0xff; + overall_len += 0xff + 1; + } + header_len[i] += *extradata; + overall_len += *extradata; + if (overall_len > extradata_size) + return -1; + } + header_len[2] = extradata_size - overall_len; + header_start[0] = extradata; + header_start[1] = header_start[0] + header_len[0]; + header_start[2] = header_start[1] + header_len[1]; + } else { + return -1; + } + return 0; +} diff --git a/ffmpeg/libavcodec/xiph.h b/ffmpeg/libavcodec/xiph.h new file mode 100644 index 0000000..cd8caa4 --- /dev/null +++ b/ffmpeg/libavcodec/xiph.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2007 FFmpeg Project + * + * 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 + */ + +#ifndef AVCODEC_XIPH_H +#define AVCODEC_XIPH_H + +#include "libavutil/common.h" + +/** + * Split a single extradata buffer into the three headers that most + * Xiph codecs use. (e.g. Theora and Vorbis) + * Works both with Matroska's packing and lavc's packing. + * + * @param[in] extradata The single chunk that combines all three headers + * @param[in] extradata_size The size of the extradata buffer + * @param[in] first_header_size The size of the first header, used to + * differentiate between the Matroska packing and lavc packing. + * @param[out] header_start Pointers to the start of the three separate headers. + * @param[out] header_len The sizes of each of the three headers. + * @return On error a negative value is returned, on success zero. + */ +int avpriv_split_xiph_headers(uint8_t *extradata, int extradata_size, + int first_header_size, uint8_t *header_start[3], + int header_len[3]); + +#endif /* AVCODEC_XIPH_H */ diff --git a/ffmpeg/libavcodec/xl.c b/ffmpeg/libavcodec/xl.c new file mode 100644 index 0000000..f50b650 --- /dev/null +++ b/ffmpeg/libavcodec/xl.c @@ -0,0 +1,139 @@ +/* + * Miro VideoXL codec + * Copyright (c) 2004 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Miro VideoXL codec. + */ + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +static const int xl_table[32] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 12, 15, 20, 25, 34, 46, + 64, 82, 94, 103, 108, 113, 116, 119, + 120, 121, 122, 123, 124, 125, 126, 127 +}; + +static int decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVFrame * const p = data; + uint8_t *Y, *U, *V; + int i, j, ret; + int stride; + uint32_t val; + int y0, y1, y2, y3 = 0, c0 = 0, c1 = 0; + + if (avctx->width & 3) { + av_log(avctx, AV_LOG_ERROR, "width is not a multiple of 4\n"); + return AVERROR_INVALIDDATA; + } + + if (buf_size < avctx->width * avctx->height) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + p->pict_type = AV_PICTURE_TYPE_I; + p->key_frame = 1; + + Y = p->data[0]; + U = p->data[1]; + V = p->data[2]; + + stride = avctx->width - 4; + + for (i = 0; i < avctx->height; i++) { + /* lines are stored in reversed order */ + buf += stride; + + for (j = 0; j < avctx->width; j += 4) { + /* value is stored in LE dword with word swapped */ + val = AV_RL32(buf); + buf -= 4; + val = ((val >> 16) & 0xFFFF) | ((val & 0xFFFF) << 16); + + if(!j) + y0 = (val & 0x1F) << 2; + else + y0 = y3 + xl_table[val & 0x1F]; + val >>= 5; + y1 = y0 + xl_table[val & 0x1F]; + val >>= 5; + y2 = y1 + xl_table[val & 0x1F]; + val >>= 6; /* align to word */ + y3 = y2 + xl_table[val & 0x1F]; + val >>= 5; + if(!j) + c0 = (val & 0x1F) << 2; + else + c0 += xl_table[val & 0x1F]; + val >>= 5; + if(!j) + c1 = (val & 0x1F) << 2; + else + c1 += xl_table[val & 0x1F]; + + Y[j + 0] = y0 << 1; + Y[j + 1] = y1 << 1; + Y[j + 2] = y2 << 1; + Y[j + 3] = y3 << 1; + + U[j >> 2] = c0 << 1; + V[j >> 2] = c1 << 1; + } + + buf += avctx->width + 4; + Y += p->linesize[0]; + U += p->linesize[1]; + V += p->linesize[2]; + } + + *got_frame = 1; + + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV411P; + + return 0; +} + +AVCodec ff_xl_decoder = { + .name = "xl", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VIXL, + .init = decode_init, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"), +}; diff --git a/ffmpeg/libavcodec/xsubdec.c b/ffmpeg/libavcodec/xsubdec.c new file mode 100644 index 0000000..d3367b0 --- /dev/null +++ b/ffmpeg/libavcodec/xsubdec.c @@ -0,0 +1,145 @@ +/* + * XSUB subtitle decoder + * Copyright (c) 2007 Reimar Döffinger + * + * 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 "libavutil/mathematics.h" +#include "libavutil/imgutils.h" +#include "avcodec.h" +#include "get_bits.h" +#include "bytestream.h" + +static av_cold int decode_init(AVCodecContext *avctx) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + return 0; +} + +static const uint8_t tc_offsets[9] = { 0, 1, 3, 4, 6, 7, 9, 10, 11 }; +static const uint8_t tc_muls[9] = { 10, 6, 10, 6, 10, 10, 10, 10, 1 }; + +static int64_t parse_timecode(const uint8_t *buf, int64_t packet_time) { + int i; + int64_t ms = 0; + if (buf[2] != ':' || buf[5] != ':' || buf[8] != '.') + return AV_NOPTS_VALUE; + for (i = 0; i < sizeof(tc_offsets); i++) { + uint8_t c = buf[tc_offsets[i]] - '0'; + if (c > 9) return AV_NOPTS_VALUE; + ms = (ms + c) * tc_muls[i]; + } + return ms - packet_time; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + AVSubtitle *sub = data; + const uint8_t *buf_end = buf + buf_size; + uint8_t *bitmap; + int w, h, x, y, i; + int64_t packet_time = 0; + GetBitContext gb; + int has_alpha = avctx->codec_tag == MKTAG('D','X','S','A'); + + // check that at least header fits + if (buf_size < 27 + 7 * 2 + 4 * 3) { + av_log(avctx, AV_LOG_ERROR, "coded frame size %d too small\n", buf_size); + return -1; + } + + // read start and end time + if (buf[0] != '[' || buf[13] != '-' || buf[26] != ']') { + av_log(avctx, AV_LOG_ERROR, "invalid time code\n"); + return -1; + } + if (avpkt->pts != AV_NOPTS_VALUE) + packet_time = av_rescale_q(avpkt->pts, AV_TIME_BASE_Q, (AVRational){1, 1000}); + sub->start_display_time = parse_timecode(buf + 1, packet_time); + sub->end_display_time = parse_timecode(buf + 14, packet_time); + buf += 27; + + // read header + w = bytestream_get_le16(&buf); + h = bytestream_get_le16(&buf); + if (av_image_check_size(w, h, 0, avctx) < 0) + return -1; + x = bytestream_get_le16(&buf); + y = bytestream_get_le16(&buf); + // skip bottom right position, it gives no new information + bytestream_get_le16(&buf); + bytestream_get_le16(&buf); + // The following value is supposed to indicate the start offset + // (relative to the palette) of the data for the second field, + // however there are files in which it has a bogus value and thus + // we just ignore it + bytestream_get_le16(&buf); + + // allocate sub and set values + sub->rects = av_mallocz(sizeof(*sub->rects)); + sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); + sub->num_rects = 1; + sub->rects[0]->x = x; sub->rects[0]->y = y; + sub->rects[0]->w = w; sub->rects[0]->h = h; + sub->rects[0]->type = SUBTITLE_BITMAP; + sub->rects[0]->pict.linesize[0] = w; + sub->rects[0]->pict.data[0] = av_malloc(w * h); + sub->rects[0]->nb_colors = 4; + sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE); + + // read palette + for (i = 0; i < sub->rects[0]->nb_colors; i++) + ((uint32_t*)sub->rects[0]->pict.data[1])[i] = bytestream_get_be24(&buf); + // make all except background (first entry) non-transparent + for (i = 0; i < sub->rects[0]->nb_colors; i++) + ((uint32_t*)sub->rects[0]->pict.data[1])[i] |= (has_alpha ? *buf++ : (i ? 0xff : 0)) << 24; + + // process RLE-compressed data + init_get_bits(&gb, buf, (buf_end - buf) * 8); + bitmap = sub->rects[0]->pict.data[0]; + for (y = 0; y < h; y++) { + // interlaced: do odd lines + if (y == (h + 1) / 2) bitmap = sub->rects[0]->pict.data[0] + w; + for (x = 0; x < w; ) { + int log2 = ff_log2_tab[show_bits(&gb, 8)]; + int run = get_bits(&gb, 14 - 4 * (log2 >> 1)); + int color = get_bits(&gb, 2); + run = FFMIN(run, w - x); + // run length 0 means till end of row + if (!run) run = w - x; + memset(bitmap, color, run); + bitmap += run; + x += run; + } + // interlaced, skip every second line + bitmap += w; + align_get_bits(&gb); + } + *data_size = 1; + return buf_size; +} + +AVCodec ff_xsub_decoder = { + .name = "xsub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_XSUB, + .init = decode_init, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("XSUB"), +}; diff --git a/ffmpeg/libavcodec/xsubenc.c b/ffmpeg/libavcodec/xsubenc.c new file mode 100644 index 0000000..cb2a908 --- /dev/null +++ b/ffmpeg/libavcodec/xsubenc.c @@ -0,0 +1,219 @@ +/* + * DivX (XSUB) subtitle encoder + * Copyright (c) 2005 DivX, Inc. + * Copyright (c) 2009 Bjorn Axelsson + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "put_bits.h" + +/** + * Number of pixels to pad left and right. + * + * The official encoder pads the subtitles with two pixels on either side, + * but until we find out why, we won't do it (we will pad to have width + * divisible by 2 though). + */ +#define PADDING 0 +#define PADDING_COLOR 0 + +/** + * Encode a single color run. At most 16 bits will be used. + * @param len length of the run, values > 255 mean "until end of line", may not be < 0. + * @param color color to encode, only the lowest two bits are used and all others must be 0. + */ +static void put_xsub_rle(PutBitContext *pb, int len, int color) +{ + if (len <= 255) + put_bits(pb, 2 + ((ff_log2_tab[len] >> 1) << 2), len); + else + put_bits(pb, 14, 0); + put_bits(pb, 2, color); +} + +/** + * Encode a 4-color bitmap with XSUB rle. + * + * The encoded bitmap may be wider than the source bitmap due to padding. + */ +static int xsub_encode_rle(PutBitContext *pb, const uint8_t *bitmap, + int linesize, int w, int h) +{ + int x0, x1, y, len, color = PADDING_COLOR; + + for (y = 0; y < h; y++) { + x0 = 0; + while (x0 < w) { + // Make sure we have enough room for at least one run and padding + if (pb->size_in_bits - put_bits_count(pb) < 7*8) + return -1; + + x1 = x0; + color = bitmap[x1++] & 3; + while (x1 < w && (bitmap[x1] & 3) == color) + x1++; + len = x1 - x0; + if (PADDING && x0 == 0) { + if (color == PADDING_COLOR) { + len += PADDING; + x0 -= PADDING; + } else + put_xsub_rle(pb, PADDING, PADDING_COLOR); + } + + // Run can't be longer than 255, unless it is the rest of a row + if (x1 == w && color == PADDING_COLOR) { + len += PADDING + (w&1); + } else + len = FFMIN(len, 255); + put_xsub_rle(pb, len, color); + + x0 += len; + } + if (color != PADDING_COLOR && (PADDING + (w&1))) + put_xsub_rle(pb, PADDING + (w&1), PADDING_COLOR); + + avpriv_align_put_bits(pb); + + bitmap += linesize; + } + + return 0; +} + +static int make_tc(uint64_t ms, int *tc) +{ + static const int tc_divs[3] = { 1000, 60, 60 }; + int i; + for (i=0; i<3; i++) { + tc[i] = ms % tc_divs[i]; + ms /= tc_divs[i]; + } + tc[3] = ms; + return ms > 99; +} + +static int xsub_encode(AVCodecContext *avctx, unsigned char *buf, + int bufsize, const AVSubtitle *h) +{ + uint64_t startTime = h->pts / 1000; // FIXME: need better solution... + uint64_t endTime = startTime + h->end_display_time - h->start_display_time; + int start_tc[4], end_tc[4]; + uint8_t *hdr = buf + 27; // Point behind the timestamp + uint8_t *rlelenptr; + uint16_t width, height; + int i; + PutBitContext pb; + + if (bufsize < 27 + 7*2 + 4*3) { + av_log(avctx, AV_LOG_ERROR, "Buffer too small for XSUB header.\n"); + return -1; + } + + // TODO: support multiple rects + if (h->num_rects != 1) + av_log(avctx, AV_LOG_WARNING, "Only single rects supported (%d in subtitle.)\n", h->num_rects); + + // TODO: render text-based subtitles into bitmaps + if (!h->rects[0]->pict.data[0] || !h->rects[0]->pict.data[1]) { + av_log(avctx, AV_LOG_WARNING, "No subtitle bitmap available.\n"); + return -1; + } + + // TODO: color reduction, similar to dvdsub encoder + if (h->rects[0]->nb_colors > 4) + av_log(avctx, AV_LOG_WARNING, "No more than 4 subtitle colors supported (%d found.)\n", h->rects[0]->nb_colors); + + // TODO: Palette swapping if color zero is not transparent + if (((uint32_t *)h->rects[0]->pict.data[1])[0] & 0xff) + av_log(avctx, AV_LOG_WARNING, "Color index 0 is not transparent. Transparency will be messed up.\n"); + + if (make_tc(startTime, start_tc) || make_tc(endTime, end_tc)) { + av_log(avctx, AV_LOG_WARNING, "Time code >= 100 hours.\n"); + return -1; + } + + snprintf(buf, 28, + "[%02d:%02d:%02d.%03d-%02d:%02d:%02d.%03d]", + start_tc[3], start_tc[2], start_tc[1], start_tc[0], + end_tc[3], end_tc[2], end_tc[1], end_tc[0]); + + // Width and height must probably be multiples of 2. + // 2 pixels required on either side of subtitle. + // Possibly due to limitations of hardware renderers. + // TODO: check if the bitmap is already padded + width = FFALIGN(h->rects[0]->w, 2) + PADDING * 2; + height = FFALIGN(h->rects[0]->h, 2); + + bytestream_put_le16(&hdr, width); + bytestream_put_le16(&hdr, height); + bytestream_put_le16(&hdr, h->rects[0]->x); + bytestream_put_le16(&hdr, h->rects[0]->y); + bytestream_put_le16(&hdr, h->rects[0]->x + width); + bytestream_put_le16(&hdr, h->rects[0]->y + height); + + rlelenptr = hdr; // Will store length of first field here later. + hdr+=2; + + // Palette + for (i=0; i<4; i++) + bytestream_put_be24(&hdr, ((uint32_t *)h->rects[0]->pict.data[1])[i]); + + // Bitmap + // RLE buffer. Reserve 2 bytes for possible padding after the last row. + init_put_bits(&pb, hdr, bufsize - (hdr - buf) - 2); + if (xsub_encode_rle(&pb, h->rects[0]->pict.data[0], + h->rects[0]->pict.linesize[0]*2, + h->rects[0]->w, (h->rects[0]->h + 1) >> 1)) + return -1; + bytestream_put_le16(&rlelenptr, put_bits_count(&pb) >> 3); // Length of first field + + if (xsub_encode_rle(&pb, h->rects[0]->pict.data[0] + h->rects[0]->pict.linesize[0], + h->rects[0]->pict.linesize[0]*2, + h->rects[0]->w, h->rects[0]->h >> 1)) + return -1; + + // Enforce total height to be be multiple of 2 + if (h->rects[0]->h & 1) { + put_xsub_rle(&pb, h->rects[0]->w, PADDING_COLOR); + avpriv_align_put_bits(&pb); + } + + flush_put_bits(&pb); + + return hdr - buf + put_bits_count(&pb)/8; +} + +static av_cold int xsub_encoder_init(AVCodecContext *avctx) +{ + if (!avctx->codec_tag) + avctx->codec_tag = MKTAG('D','X','S','B'); + + return 0; +} + +AVCodec ff_xsub_encoder = { + .name = "xsub", + .type = AVMEDIA_TYPE_SUBTITLE, + .id = AV_CODEC_ID_XSUB, + .init = xsub_encoder_init, + .encode_sub = xsub_encode, + .long_name = NULL_IF_CONFIG_SMALL("DivX subtitles (XSUB)"), +}; diff --git a/ffmpeg/libavcodec/xvmc.h b/ffmpeg/libavcodec/xvmc.h new file mode 100644 index 0000000..b2bf518 --- /dev/null +++ b/ffmpeg/libavcodec/xvmc.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2003 Ivan Kalvachev + * + * 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 + */ + +#ifndef AVCODEC_XVMC_H +#define AVCODEC_XVMC_H + +/** + * @file + * @ingroup lavc_codec_hwaccel_xvmc + * Public libavcodec XvMC header. + */ + +#include + +#include "avcodec.h" + +/** + * @defgroup lavc_codec_hwaccel_xvmc XvMC + * @ingroup lavc_codec_hwaccel + * + * @{ + */ + +#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct + the number is 1337 speak for the letters IDCT MCo (motion compensation) */ + +struct xvmc_pix_fmt { + /** The field contains the special constant value AV_XVMC_ID. + It is used as a test that the application correctly uses the API, + and that there is no corruption caused by pixel routines. + - application - set during initialization + - libavcodec - unchanged + */ + int xvmc_id; + + /** Pointer to the block array allocated by XvMCCreateBlocks(). + The array has to be freed by XvMCDestroyBlocks(). + Each group of 64 values represents one data block of differential + pixel information (in MoCo mode) or coefficients for IDCT. + - application - set the pointer during initialization + - libavcodec - fills coefficients/pixel data into the array + */ + short* data_blocks; + + /** Pointer to the macroblock description array allocated by + XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks(). + - application - set the pointer during initialization + - libavcodec - fills description data into the array + */ + XvMCMacroBlock* mv_blocks; + + /** Number of macroblock descriptions that can be stored in the mv_blocks + array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_mv_blocks; + + /** Number of blocks that can be stored at once in the data_blocks array. + - application - set during initialization + - libavcodec - unchanged + */ + int allocated_data_blocks; + + /** Indicate that the hardware would interpret data_blocks as IDCT + coefficients and perform IDCT on them. + - application - set during initialization + - libavcodec - unchanged + */ + int idct; + + /** In MoCo mode it indicates that intra macroblocks are assumed to be in + unsigned format; same as the XVMC_INTRA_UNSIGNED flag. + - application - set during initialization + - libavcodec - unchanged + */ + int unsigned_intra; + + /** Pointer to the surface allocated by XvMCCreateSurface(). + It has to be freed by XvMCDestroySurface() on application exit. + It identifies the frame and its state on the video hardware. + - application - set during initialization + - libavcodec - unchanged + */ + XvMCSurface* p_surface; + +/** Set by the decoder before calling ff_draw_horiz_band(), + needed by the XvMCRenderSurface function. */ +//@{ + /** Pointer to the surface used as past reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_past_surface; + + /** Pointer to the surface used as future reference + - application - unchanged + - libavcodec - set + */ + XvMCSurface* p_future_surface; + + /** top/bottom field or frame + - application - unchanged + - libavcodec - set + */ + unsigned int picture_structure; + + /** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence + - application - unchanged + - libavcodec - set + */ + unsigned int flags; +//}@ + + /** Number of macroblock descriptions in the mv_blocks array + that have already been passed to the hardware. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may increment it + with filled_mb_block_num or zero both. + - libavcodec - unchanged + */ + int start_mv_blocks_num; + + /** Number of new macroblock descriptions in the mv_blocks array (after + start_mv_blocks_num) that are filled by libavcodec and have to be + passed to the hardware. + - application - zeroes it on get_buffer() or after successful + ff_draw_horiz_band(). + - libavcodec - increment with one of each stored MB + */ + int filled_mv_blocks_num; + + /** Number of the next free data block; one data block consists of + 64 short values in the data_blocks array. + All blocks before this one have already been claimed by placing their + position into the corresponding block description structure field, + that are part of the mv_blocks array. + - application - zeroes it on get_buffer(). + A successful ff_draw_horiz_band() may zero it together + with start_mb_blocks_num. + - libavcodec - each decoded macroblock increases it by the number + of coded blocks it contains. + */ + int next_free_data_block_num; +}; + +/** + * @} + */ + +#endif /* AVCODEC_XVMC_H */ diff --git a/ffmpeg/libavcodec/xvmc_internal.h b/ffmpeg/libavcodec/xvmc_internal.h new file mode 100644 index 0000000..04197ce --- /dev/null +++ b/ffmpeg/libavcodec/xvmc_internal.h @@ -0,0 +1,33 @@ +/* + * XVideo Motion Compensation internal functions + * + * 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 + */ + +#ifndef AVCODEC_XVMC_INTERNAL_H +#define AVCODEC_XVMC_INTERNAL_H + +#include "avcodec.h" +#include "mpegvideo.h" + +void ff_xvmc_init_block(MpegEncContext *s); +void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp); +int ff_xvmc_field_start(MpegEncContext*s, AVCodecContext *avctx); +void ff_xvmc_field_end(MpegEncContext *s); +void ff_xvmc_decode_mb(MpegEncContext *s); + +#endif /* AVCODEC_XVMC_INTERNAL_H */ diff --git a/ffmpeg/libavcodec/xwd.h b/ffmpeg/libavcodec/xwd.h new file mode 100644 index 0000000..d046046 --- /dev/null +++ b/ffmpeg/libavcodec/xwd.h @@ -0,0 +1,41 @@ +/* + * XWD image format + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 + */ + +#ifndef AVCODEC_XWD_H +#define AVCODEC_XWD_H + +#define XWD_VERSION 7 +#define XWD_HEADER_SIZE 100 +#define XWD_CMAP_SIZE 12 + +#define XWD_XY_BITMAP 0 +#define XWD_XY_PIXMAP 1 +#define XWD_Z_PIXMAP 2 + +#define XWD_STATIC_GRAY 0 +#define XWD_GRAY_SCALE 1 +#define XWD_STATIC_COLOR 2 +#define XWD_PSEUDO_COLOR 3 +#define XWD_TRUE_COLOR 4 +#define XWD_DIRECT_COLOR 5 + +#endif /* AVCODEC_XWD_H */ diff --git a/ffmpeg/libavcodec/xwddec.c b/ffmpeg/libavcodec/xwddec.c new file mode 100644 index 0000000..66a2fe9 --- /dev/null +++ b/ffmpeg/libavcodec/xwddec.c @@ -0,0 +1,247 @@ +/* + * XWD image format + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "libavutil/imgutils.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "xwd.h" + +static int xwd_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *p = data; + const uint8_t *buf = avpkt->data; + int i, ret, buf_size = avpkt->size; + uint32_t version, header_size, vclass, ncolors; + uint32_t xoffset, be, bpp, lsize, rsize; + uint32_t pixformat, pixdepth, bunit, bitorder, bpad; + uint32_t rgb[3]; + uint8_t *ptr; + GetByteContext gb; + + if (buf_size < XWD_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb, buf, buf_size); + header_size = bytestream2_get_be32u(&gb); + + version = bytestream2_get_be32u(&gb); + if (version != XWD_VERSION) { + av_log(avctx, AV_LOG_ERROR, "unsupported version\n"); + return AVERROR_INVALIDDATA; + } + + if (buf_size < header_size || header_size < XWD_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "invalid header size\n"); + return AVERROR_INVALIDDATA; + } + + pixformat = bytestream2_get_be32u(&gb); + pixdepth = bytestream2_get_be32u(&gb); + avctx->width = bytestream2_get_be32u(&gb); + avctx->height = bytestream2_get_be32u(&gb); + xoffset = bytestream2_get_be32u(&gb); + be = bytestream2_get_be32u(&gb); + bunit = bytestream2_get_be32u(&gb); + bitorder = bytestream2_get_be32u(&gb); + bpad = bytestream2_get_be32u(&gb); + bpp = bytestream2_get_be32u(&gb); + lsize = bytestream2_get_be32u(&gb); + vclass = bytestream2_get_be32u(&gb); + rgb[0] = bytestream2_get_be32u(&gb); + rgb[1] = bytestream2_get_be32u(&gb); + rgb[2] = bytestream2_get_be32u(&gb); + bytestream2_skipu(&gb, 8); + ncolors = bytestream2_get_be32u(&gb); + bytestream2_skipu(&gb, header_size - (XWD_HEADER_SIZE - 20)); + + av_log(avctx, AV_LOG_DEBUG, "pixformat %d, pixdepth %d, bunit %d, bitorder %d, bpad %d\n", + pixformat, pixdepth, bunit, bitorder, bpad); + av_log(avctx, AV_LOG_DEBUG, "vclass %d, ncolors %d, bpp %d, be %d, lsize %d, xoffset %d\n", + vclass, ncolors, bpp, be, lsize, xoffset); + av_log(avctx, AV_LOG_DEBUG, "red %0x, green %0x, blue %0x\n", rgb[0], rgb[1], rgb[2]); + + if (pixformat > XWD_Z_PIXMAP) { + av_log(avctx, AV_LOG_ERROR, "invalid pixmap format\n"); + return AVERROR_INVALIDDATA; + } + + if (pixdepth == 0 || pixdepth > 32) { + av_log(avctx, AV_LOG_ERROR, "invalid pixmap depth\n"); + return AVERROR_INVALIDDATA; + } + + if (xoffset) { + avpriv_request_sample(avctx, "xoffset %d", xoffset); + return AVERROR_PATCHWELCOME; + } + + if (be > 1) { + av_log(avctx, AV_LOG_ERROR, "invalid byte order\n"); + return AVERROR_INVALIDDATA; + } + + if (bitorder > 1) { + av_log(avctx, AV_LOG_ERROR, "invalid bitmap bit order\n"); + return AVERROR_INVALIDDATA; + } + + if (bunit != 8 && bunit != 16 && bunit != 32) { + av_log(avctx, AV_LOG_ERROR, "invalid bitmap unit\n"); + return AVERROR_INVALIDDATA; + } + + if (bpad != 8 && bpad != 16 && bpad != 32) { + av_log(avctx, AV_LOG_ERROR, "invalid bitmap scan-line pad\n"); + return AVERROR_INVALIDDATA; + } + + if (bpp == 0 || bpp > 32) { + av_log(avctx, AV_LOG_ERROR, "invalid bits per pixel\n"); + return AVERROR_INVALIDDATA; + } + + if (ncolors > 256) { + av_log(avctx, AV_LOG_ERROR, "invalid number of entries in colormap\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, NULL)) < 0) + return ret; + + rsize = FFALIGN(avctx->width * bpp, bpad) / 8; + if (lsize < rsize) { + av_log(avctx, AV_LOG_ERROR, "invalid bytes per scan-line\n"); + return AVERROR_INVALIDDATA; + } + + if (bytestream2_get_bytes_left(&gb) < ncolors * XWD_CMAP_SIZE + avctx->height * lsize) { + av_log(avctx, AV_LOG_ERROR, "input buffer too small\n"); + return AVERROR_INVALIDDATA; + } + + if (pixformat != XWD_Z_PIXMAP) { + av_log(avctx, AV_LOG_ERROR, "pixmap format %d unsupported\n", pixformat); + return AVERROR_PATCHWELCOME; + } + + avctx->pix_fmt = AV_PIX_FMT_NONE; + switch (vclass) { + case XWD_STATIC_GRAY: + case XWD_GRAY_SCALE: + if (bpp != 1 && bpp != 8) + return AVERROR_INVALIDDATA; + if (pixdepth == 1) { + avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; + } else if (pixdepth == 8) { + avctx->pix_fmt = AV_PIX_FMT_GRAY8; + } + break; + case XWD_STATIC_COLOR: + case XWD_PSEUDO_COLOR: + if (bpp == 8) + avctx->pix_fmt = AV_PIX_FMT_PAL8; + break; + case XWD_TRUE_COLOR: + case XWD_DIRECT_COLOR: + if (bpp != 16 && bpp != 24 && bpp != 32) + return AVERROR_INVALIDDATA; + if (bpp == 16 && pixdepth == 15) { + if (rgb[0] == 0x7C00 && rgb[1] == 0x3E0 && rgb[2] == 0x1F) + avctx->pix_fmt = be ? AV_PIX_FMT_RGB555BE : AV_PIX_FMT_RGB555LE; + else if (rgb[0] == 0x1F && rgb[1] == 0x3E0 && rgb[2] == 0x7C00) + avctx->pix_fmt = be ? AV_PIX_FMT_BGR555BE : AV_PIX_FMT_BGR555LE; + } else if (bpp == 16 && pixdepth == 16) { + if (rgb[0] == 0xF800 && rgb[1] == 0x7E0 && rgb[2] == 0x1F) + avctx->pix_fmt = be ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_RGB565LE; + else if (rgb[0] == 0x1F && rgb[1] == 0x7E0 && rgb[2] == 0xF800) + avctx->pix_fmt = be ? AV_PIX_FMT_BGR565BE : AV_PIX_FMT_BGR565LE; + } else if (bpp == 24) { + if (rgb[0] == 0xFF0000 && rgb[1] == 0xFF00 && rgb[2] == 0xFF) + avctx->pix_fmt = be ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_BGR24; + else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) + avctx->pix_fmt = be ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_RGB24; + } else if (bpp == 32) { + if (rgb[0] == 0xFF0000 && rgb[1] == 0xFF00 && rgb[2] == 0xFF) + avctx->pix_fmt = be ? AV_PIX_FMT_ARGB : AV_PIX_FMT_BGRA; + else if (rgb[0] == 0xFF && rgb[1] == 0xFF00 && rgb[2] == 0xFF0000) + avctx->pix_fmt = be ? AV_PIX_FMT_ABGR : AV_PIX_FMT_RGBA; + } + bytestream2_skipu(&gb, ncolors * XWD_CMAP_SIZE); + break; + default: + av_log(avctx, AV_LOG_ERROR, "invalid visual class\n"); + return AVERROR_INVALIDDATA; + } + + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { + avpriv_request_sample(avctx, + "Unknown file: bpp %d, pixdepth %d, vclass %d", + bpp, pixdepth, vclass); + return AVERROR_PATCHWELCOME; + } + + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) + return ret; + + p->key_frame = 1; + p->pict_type = AV_PICTURE_TYPE_I; + + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + uint32_t *dst = (uint32_t *)p->data[1]; + uint8_t red, green, blue; + + for (i = 0; i < ncolors; i++) { + + bytestream2_skipu(&gb, 4); // skip colormap entry number + red = bytestream2_get_byteu(&gb); + bytestream2_skipu(&gb, 1); + green = bytestream2_get_byteu(&gb); + bytestream2_skipu(&gb, 1); + blue = bytestream2_get_byteu(&gb); + bytestream2_skipu(&gb, 3); // skip bitmask flag and padding + + dst[i] = red << 16 | green << 8 | blue; + } + } + + ptr = p->data[0]; + for (i = 0; i < avctx->height; i++) { + bytestream2_get_bufferu(&gb, ptr, rsize); + bytestream2_skipu(&gb, lsize - rsize); + ptr += p->linesize[0]; + } + + *got_frame = 1; + + return buf_size; +} + +AVCodec ff_xwd_decoder = { + .name = "xwd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XWD, + .decode = xwd_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), +}; diff --git a/ffmpeg/libavcodec/xwdenc.c b/ffmpeg/libavcodec/xwdenc.c new file mode 100644 index 0000000..fac3d0b --- /dev/null +++ b/ffmpeg/libavcodec/xwdenc.c @@ -0,0 +1,256 @@ +/* + * XWD image format + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" +#include "avcodec.h" +#include "bytestream.h" +#include "internal.h" +#include "xwd.h" + +#define WINDOW_NAME "lavcxwdenc" +#define WINDOW_NAME_SIZE 11 + +static av_cold int xwd_encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) + return AVERROR(ENOMEM); + + return 0; +} + +static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *p, int *got_packet) +{ + enum AVPixelFormat pix_fmt = avctx->pix_fmt; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + uint32_t pixdepth, bpp, bpad, ncolors = 0, lsize, vclass, be = 0; + uint32_t rgb[3] = { 0 }, bitorder = 0; + uint32_t header_size; + int i, out_size, ret; + uint8_t *ptr, *buf; + + pixdepth = av_get_bits_per_pixel(desc); + if (desc->flags & PIX_FMT_BE) + be = 1; + switch (pix_fmt) { + case AV_PIX_FMT_ARGB: + case AV_PIX_FMT_BGRA: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_ABGR: + if (pix_fmt == AV_PIX_FMT_ARGB || + pix_fmt == AV_PIX_FMT_ABGR) + be = 1; + if (pix_fmt == AV_PIX_FMT_ABGR || + pix_fmt == AV_PIX_FMT_RGBA) { + rgb[0] = 0xFF; + rgb[1] = 0xFF00; + rgb[2] = 0xFF0000; + } else { + rgb[0] = 0xFF0000; + rgb[1] = 0xFF00; + rgb[2] = 0xFF; + } + bpp = 32; + pixdepth = 24; + vclass = XWD_TRUE_COLOR; + bpad = 32; + break; + case AV_PIX_FMT_BGR24: + case AV_PIX_FMT_RGB24: + if (pix_fmt == AV_PIX_FMT_RGB24) + be = 1; + bpp = 24; + vclass = XWD_TRUE_COLOR; + bpad = 32; + rgb[0] = 0xFF0000; + rgb[1] = 0xFF00; + rgb[2] = 0xFF; + break; + case AV_PIX_FMT_RGB565LE: + case AV_PIX_FMT_RGB565BE: + case AV_PIX_FMT_BGR565LE: + case AV_PIX_FMT_BGR565BE: + if (pix_fmt == AV_PIX_FMT_BGR565LE || + pix_fmt == AV_PIX_FMT_BGR565BE) { + rgb[0] = 0x1F; + rgb[1] = 0x7E0; + rgb[2] = 0xF800; + } else { + rgb[0] = 0xF800; + rgb[1] = 0x7E0; + rgb[2] = 0x1F; + } + bpp = 16; + vclass = XWD_TRUE_COLOR; + bpad = 16; + break; + case AV_PIX_FMT_RGB555LE: + case AV_PIX_FMT_RGB555BE: + case AV_PIX_FMT_BGR555LE: + case AV_PIX_FMT_BGR555BE: + if (pix_fmt == AV_PIX_FMT_BGR555LE || + pix_fmt == AV_PIX_FMT_BGR555BE) { + rgb[0] = 0x1F; + rgb[1] = 0x3E0; + rgb[2] = 0x7C00; + } else { + rgb[0] = 0x7C00; + rgb[1] = 0x3E0; + rgb[2] = 0x1F; + } + bpp = 16; + vclass = XWD_TRUE_COLOR; + bpad = 16; + break; + case AV_PIX_FMT_RGB8: + case AV_PIX_FMT_BGR8: + case AV_PIX_FMT_RGB4_BYTE: + case AV_PIX_FMT_BGR4_BYTE: + case AV_PIX_FMT_PAL8: + bpp = 8; + vclass = XWD_PSEUDO_COLOR; + bpad = 8; + ncolors = 256; + break; + case AV_PIX_FMT_GRAY8: + bpp = 8; + bpad = 8; + vclass = XWD_STATIC_GRAY; + break; + case AV_PIX_FMT_MONOWHITE: + be = 1; + bitorder = 1; + bpp = 1; + bpad = 8; + vclass = XWD_STATIC_GRAY; + break; + default: + av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); + return AVERROR(EINVAL); + } + + lsize = FFALIGN(bpp * avctx->width, bpad) / 8; + header_size = XWD_HEADER_SIZE + WINDOW_NAME_SIZE; + out_size = header_size + ncolors * XWD_CMAP_SIZE + avctx->height * lsize; + + if ((ret = ff_alloc_packet2(avctx, pkt, out_size)) < 0) + return ret; + buf = pkt->data; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + bytestream_put_be32(&buf, header_size); + bytestream_put_be32(&buf, XWD_VERSION); // file version + bytestream_put_be32(&buf, XWD_Z_PIXMAP); // pixmap format + bytestream_put_be32(&buf, pixdepth); // pixmap depth in pixels + bytestream_put_be32(&buf, avctx->width); // pixmap width in pixels + bytestream_put_be32(&buf, avctx->height); // pixmap height in pixels + bytestream_put_be32(&buf, 0); // bitmap x offset + bytestream_put_be32(&buf, be); // byte order + bytestream_put_be32(&buf, 32); // bitmap unit + bytestream_put_be32(&buf, bitorder); // bit-order of image data + bytestream_put_be32(&buf, bpad); // bitmap scan-line pad in bits + bytestream_put_be32(&buf, bpp); // bits per pixel + bytestream_put_be32(&buf, lsize); // bytes per scan-line + bytestream_put_be32(&buf, vclass); // visual class + bytestream_put_be32(&buf, rgb[0]); // red mask + bytestream_put_be32(&buf, rgb[1]); // green mask + bytestream_put_be32(&buf, rgb[2]); // blue mask + bytestream_put_be32(&buf, 8); // size of each bitmask in bits + bytestream_put_be32(&buf, ncolors); // number of colors + bytestream_put_be32(&buf, ncolors); // number of entries in color map + bytestream_put_be32(&buf, avctx->width); // window width + bytestream_put_be32(&buf, avctx->height); // window height + bytestream_put_be32(&buf, 0); // window upper left X coordinate + bytestream_put_be32(&buf, 0); // window upper left Y coordinate + bytestream_put_be32(&buf, 0); // window border width + bytestream_put_buffer(&buf, WINDOW_NAME, WINDOW_NAME_SIZE); + + for (i = 0; i < ncolors; i++) { + uint32_t val; + uint8_t red, green, blue; + + val = AV_RN32A(p->data[1] + i * 4); + red = (val >> 16) & 0xFF; + green = (val >> 8) & 0xFF; + blue = val & 0xFF; + + bytestream_put_be32(&buf, i); // colormap entry number + bytestream_put_be16(&buf, red << 8); + bytestream_put_be16(&buf, green << 8); + bytestream_put_be16(&buf, blue << 8); + bytestream_put_byte(&buf, 0x7); // bitmask flag + bytestream_put_byte(&buf, 0); // padding + } + + ptr = p->data[0]; + for (i = 0; i < avctx->height; i++) { + bytestream_put_buffer(&buf, ptr, lsize); + ptr += p->linesize[0]; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int xwd_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_xwd_encoder = { + .name = "xwd", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XWD, + .init = xwd_encode_init, + .encode2 = xwd_encode_frame, + .close = xwd_encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA, + AV_PIX_FMT_RGBA, + AV_PIX_FMT_ARGB, + AV_PIX_FMT_ABGR, + AV_PIX_FMT_RGB24, + AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB565BE, + AV_PIX_FMT_RGB565LE, + AV_PIX_FMT_BGR565BE, + AV_PIX_FMT_BGR565LE, + AV_PIX_FMT_RGB555BE, + AV_PIX_FMT_RGB555LE, + AV_PIX_FMT_BGR555BE, + AV_PIX_FMT_BGR555LE, + AV_PIX_FMT_RGB8, + AV_PIX_FMT_BGR8, + AV_PIX_FMT_RGB4_BYTE, + AV_PIX_FMT_BGR4_BYTE, + AV_PIX_FMT_PAL8, + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_MONOWHITE, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), +}; diff --git a/ffmpeg/libavcodec/xxan.c b/ffmpeg/libavcodec/xxan.c new file mode 100644 index 0000000..e2b1b8c --- /dev/null +++ b/ffmpeg/libavcodec/xxan.c @@ -0,0 +1,444 @@ +/* + * Wing Commander/Xan Video Decoder + * Copyright (C) 2011 Konstantin Shishkov + * based on work by Mike Melanson + * + * 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 "avcodec.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "bytestream.h" +#define BITSTREAM_READER_LE +#include "get_bits.h" +#include "internal.h" + +typedef struct XanContext { + AVCodecContext *avctx; + AVFrame pic; + + uint8_t *y_buffer; + uint8_t *scratch_buffer; + int buffer_size; + GetByteContext gb; +} XanContext; + +static av_cold int xan_decode_init(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + + s->avctx = avctx; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + if (avctx->height < 8) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height); + return AVERROR(EINVAL); + } + + s->buffer_size = avctx->width * avctx->height; + s->y_buffer = av_malloc(s->buffer_size); + if (!s->y_buffer) + return AVERROR(ENOMEM); + s->scratch_buffer = av_malloc(s->buffer_size + 130); + if (!s->scratch_buffer) { + av_freep(&s->y_buffer); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int xan_unpack_luma(XanContext *s, + uint8_t *dst, const int dst_size) +{ + int tree_size, eof; + int bits, mask; + int tree_root, node; + const uint8_t *dst_end = dst + dst_size; + GetByteContext tree = s->gb; + int start_off = bytestream2_tell(&tree); + + tree_size = bytestream2_get_byte(&s->gb); + eof = bytestream2_get_byte(&s->gb); + tree_root = eof + tree_size; + bytestream2_skip(&s->gb, tree_size * 2); + + node = tree_root; + bits = bytestream2_get_byte(&s->gb); + mask = 0x80; + for (;;) { + int bit = !!(bits & mask); + mask >>= 1; + bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET); + node = bytestream2_get_byte(&tree); + if (node == eof) + break; + if (node < eof) { + *dst++ = node; + if (dst > dst_end) + break; + node = tree_root; + } + if (!mask) { + if (bytestream2_get_bytes_left(&s->gb) <= 0) + break; + bits = bytestream2_get_byteu(&s->gb); + mask = 0x80; + } + } + return dst != dst_end ? AVERROR_INVALIDDATA : 0; +} + +/* almost the same as in xan_wc3 decoder */ +static int xan_unpack(XanContext *s, + uint8_t *dest, const int dest_len) +{ + uint8_t opcode; + int size; + uint8_t *orig_dest = dest; + const uint8_t *dest_end = dest + dest_len; + + while (dest < dest_end) { + if (bytestream2_get_bytes_left(&s->gb) <= 0) + return AVERROR_INVALIDDATA; + + opcode = bytestream2_get_byteu(&s->gb); + + if (opcode < 0xe0) { + int size2, back; + if ((opcode & 0x80) == 0) { + size = opcode & 3; + back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1; + size2 = ((opcode & 0x1c) >> 2) + 3; + } else if ((opcode & 0x40) == 0) { + size = bytestream2_peek_byte(&s->gb) >> 6; + back = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1; + size2 = (opcode & 0x3f) + 4; + } else { + size = opcode & 3; + back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1; + size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&s->gb) + 5; + if (size + size2 > dest_end - dest) + break; + } + if (dest + size + size2 > dest_end || + dest - orig_dest + size < back) + return AVERROR_INVALIDDATA; + bytestream2_get_buffer(&s->gb, dest, size); + dest += size; + av_memcpy_backptr(dest, back, size2); + dest += size2; + } else { + int finish = opcode >= 0xfc; + + size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4; + if (dest_end - dest < size) + return AVERROR_INVALIDDATA; + bytestream2_get_buffer(&s->gb, dest, size); + dest += size; + if (finish) + break; + } + } + return dest - orig_dest; +} + +static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off) +{ + XanContext *s = avctx->priv_data; + uint8_t *U, *V; + int val, uval, vval; + int i, j; + const uint8_t *src, *src_end; + const uint8_t *table; + int mode, offset, dec_size, table_size; + + if (!chroma_off) + return 0; + if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) { + av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n"); + return AVERROR_INVALIDDATA; + } + bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET); + mode = bytestream2_get_le16(&s->gb); + table = s->gb.buffer; + table_size = bytestream2_get_le16(&s->gb); + offset = table_size * 2; + table_size += 1; + + if (offset >= bytestream2_get_bytes_left(&s->gb)) { + av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n"); + return AVERROR_INVALIDDATA; + } + + bytestream2_skip(&s->gb, offset); + memset(s->scratch_buffer, 0, s->buffer_size); + dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size); + if (dec_size < 0) { + av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n"); + return dec_size; + } + + U = s->pic.data[1]; + V = s->pic.data[2]; + src = s->scratch_buffer; + src_end = src + dec_size; + if (mode) { + for (j = 0; j < avctx->height >> 1; j++) { + for (i = 0; i < avctx->width >> 1; i++) { + if (src_end - src < 1) + return 0; + val = *src++; + if (val) { + if (val >= table_size) + return AVERROR_INVALIDDATA; + val = AV_RL16(table + (val << 1)); + uval = (val >> 3) & 0xF8; + vval = (val >> 8) & 0xF8; + U[i] = uval | (uval >> 5); + V[i] = vval | (vval >> 5); + } + } + U += s->pic.linesize[1]; + V += s->pic.linesize[2]; + } + if (avctx->height & 1) { + memcpy(U, U - s->pic.linesize[1], avctx->width >> 1); + memcpy(V, V - s->pic.linesize[2], avctx->width >> 1); + } + } else { + uint8_t *U2 = U + s->pic.linesize[1]; + uint8_t *V2 = V + s->pic.linesize[2]; + + for (j = 0; j < avctx->height >> 2; j++) { + for (i = 0; i < avctx->width >> 1; i += 2) { + if (src_end - src < 1) + return 0; + val = *src++; + if (val) { + if (val >= table_size) + return AVERROR_INVALIDDATA; + val = AV_RL16(table + (val << 1)); + uval = (val >> 3) & 0xF8; + vval = (val >> 8) & 0xF8; + U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5); + V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5); + } + } + U += s->pic.linesize[1] * 2; + V += s->pic.linesize[2] * 2; + U2 += s->pic.linesize[1] * 2; + V2 += s->pic.linesize[2] * 2; + } + if (avctx->height & 3) { + int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2; + + memcpy(U, U - lines * s->pic.linesize[1], lines * s->pic.linesize[1]); + memcpy(V, V - lines * s->pic.linesize[2], lines * s->pic.linesize[2]); + } + } + + return 0; +} + +static int xan_decode_frame_type0(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer; + unsigned chroma_off, corr_off; + int cur, last; + int i, j; + int ret; + + chroma_off = bytestream2_get_le32(&s->gb); + corr_off = bytestream2_get_le32(&s->gb); + + if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0) + return ret; + + if (corr_off >= bytestream2_size(&s->gb)) { + av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n"); + corr_off = 0; + } + bytestream2_seek(&s->gb, 12, SEEK_SET); + ret = xan_unpack_luma(s, src, s->buffer_size >> 1); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n"); + return ret; + } + + ybuf = s->y_buffer; + last = *src++; + ybuf[0] = last << 1; + for (j = 1; j < avctx->width - 1; j += 2) { + cur = (last + *src++) & 0x1F; + ybuf[j] = last + cur; + ybuf[j+1] = cur << 1; + last = cur; + } + if(j < avctx->width) + ybuf[j] = last << 1; + prev_buf = ybuf; + ybuf += avctx->width; + + for (i = 1; i < avctx->height; i++) { + last = ((prev_buf[0] >> 1) + *src++) & 0x1F; + ybuf[0] = last << 1; + for (j = 1; j < avctx->width - 1; j += 2) { + cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F; + ybuf[j] = last + cur; + ybuf[j+1] = cur << 1; + last = cur; + } + if(j < avctx->width) + ybuf[j] = last << 1; + prev_buf = ybuf; + ybuf += avctx->width; + } + + if (corr_off) { + int dec_size; + + bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET); + dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2); + if (dec_size < 0) + dec_size = 0; + else + dec_size = FFMIN(dec_size, s->buffer_size/2 - 1); + + for (i = 0; i < dec_size; i++) + s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F; + } + + src = s->y_buffer; + ybuf = s->pic.data[0]; + for (j = 0; j < avctx->height; j++) { + for (i = 0; i < avctx->width; i++) + ybuf[i] = (src[i] << 2) | (src[i] >> 3); + src += avctx->width; + ybuf += s->pic.linesize[0]; + } + + return 0; +} + +static int xan_decode_frame_type1(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + uint8_t *ybuf, *src = s->scratch_buffer; + int cur, last; + int i, j; + int ret; + + if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0) + return ret; + + bytestream2_seek(&s->gb, 16, SEEK_SET); + ret = xan_unpack_luma(s, src, + s->buffer_size >> 1); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n"); + return ret; + } + + ybuf = s->y_buffer; + for (i = 0; i < avctx->height; i++) { + last = (ybuf[0] + (*src++ << 1)) & 0x3F; + ybuf[0] = last; + for (j = 1; j < avctx->width - 1; j += 2) { + cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F; + ybuf[j] = (last + cur) >> 1; + ybuf[j+1] = cur; + last = cur; + } + if(j < avctx->width) + ybuf[j] = last; + ybuf += avctx->width; + } + + src = s->y_buffer; + ybuf = s->pic.data[0]; + for (j = 0; j < avctx->height; j++) { + for (i = 0; i < avctx->width; i++) + ybuf[i] = (src[i] << 2) | (src[i] >> 3); + src += avctx->width; + ybuf += s->pic.linesize[0]; + } + + return 0; +} + +static int xan_decode_frame(AVCodecContext *avctx, + void *data, int *got_frame, + AVPacket *avpkt) +{ + XanContext *s = avctx->priv_data; + int ftype; + int ret; + + if ((ret = ff_reget_buffer(avctx, &s->pic)) < 0) + return ret; + + bytestream2_init(&s->gb, avpkt->data, avpkt->size); + ftype = bytestream2_get_le32(&s->gb); + switch (ftype) { + case 0: + ret = xan_decode_frame_type0(avctx); + break; + case 1: + ret = xan_decode_frame_type1(avctx); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype); + return AVERROR_INVALIDDATA; + } + if (ret) + return ret; + + if ((ret = av_frame_ref(data, &s->pic)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int xan_decode_end(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + + av_frame_unref(&s->pic); + + av_freep(&s->y_buffer); + av_freep(&s->scratch_buffer); + + return 0; +} + +AVCodec ff_xan_wc4_decoder = { + .name = "xan_wc4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_XAN_WC4, + .priv_data_size = sizeof(XanContext), + .init = xan_decode_init, + .close = xan_decode_end, + .decode = xan_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), +}; diff --git a/ffmpeg/libavcodec/y41pdec.c b/ffmpeg/libavcodec/y41pdec.c new file mode 100644 index 0000000..42449c6 --- /dev/null +++ b/ffmpeg/libavcodec/y41pdec.c @@ -0,0 +1,99 @@ +/* + * y41p decoder + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int y41p_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV411P; + avctx->bits_per_raw_sample = 12; + + if (avctx->width & 7) { + av_log(avctx, AV_LOG_WARNING, "y41p requires width to be divisible by 8.\n"); + } + + return 0; +} + +static int y41p_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *pic = data; + uint8_t *src = avpkt->data; + uint8_t *y, *u, *v; + int i, j, ret; + + if (avpkt->size < 1.5 * avctx->height * avctx->width) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + for (i = avctx->height - 1; i >= 0 ; i--) { + y = &pic->data[0][i * pic->linesize[0]]; + u = &pic->data[1][i * pic->linesize[1]]; + v = &pic->data[2][i * pic->linesize[2]]; + for (j = 0; j < avctx->width; j += 8) { + *(u++) = *src++; + *(y++) = *src++; + *(v++) = *src++; + *(y++) = *src++; + + *(u++) = *src++; + *(y++) = *src++; + *(v++) = *src++; + *(y++) = *src++; + + *(y++) = *src++; + *(y++) = *src++; + *(y++) = *src++; + *(y++) = *src++; + } + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int y41p_decode_close(AVCodecContext *avctx) +{ + + return 0; +} + +AVCodec ff_y41p_decoder = { + .name = "y41p", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_Y41P, + .init = y41p_decode_init, + .decode = y41p_decode_frame, + .close = y41p_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), +}; diff --git a/ffmpeg/libavcodec/y41penc.c b/ffmpeg/libavcodec/y41penc.c new file mode 100644 index 0000000..1a8f0fb --- /dev/null +++ b/ffmpeg/libavcodec/y41penc.c @@ -0,0 +1,102 @@ +/* + * y41p encoder + * + * Copyright (c) 2012 Paul B Mahol + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int y41p_encode_init(AVCodecContext *avctx) +{ + if (avctx->width & 7) { + av_log(avctx, AV_LOG_ERROR, "y41p requires width to be divisible by 8.\n"); + return AVERROR_INVALIDDATA; + } + + avctx->coded_frame = avcodec_alloc_frame(); + avctx->bits_per_coded_sample = 12; + + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int y41p_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + uint8_t *dst; + uint8_t *y, *u, *v; + int i, j, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, avctx->width * avctx->height * 1.5)) < 0) + return ret; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + dst = pkt->data; + + for (i = avctx->height - 1; i >= 0; i--) { + y = &pic->data[0][i * pic->linesize[0]]; + u = &pic->data[1][i * pic->linesize[1]]; + v = &pic->data[2][i * pic->linesize[2]]; + for (j = 0; j < avctx->width; j += 8) { + *(dst++) = *(u++); + *(dst++) = *(y++); + *(dst++) = *(v++); + *(dst++) = *(y++); + + *(dst++) = *(u++); + *(dst++) = *(y++); + *(dst++) = *(v++); + *(dst++) = *(y++); + + *(dst++) = *(y++); + *(dst++) = *(y++); + *(dst++) = *(y++); + *(dst++) = *(y++); + } + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int y41p_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_y41p_encoder = { + .name = "y41p", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_Y41P, + .init = y41p_encode_init, + .encode2 = y41p_encode_frame, + .close = y41p_encode_close, + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, + AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), +}; diff --git a/ffmpeg/libavcodec/yop.c b/ffmpeg/libavcodec/yop.c new file mode 100644 index 0000000..e1f5321 --- /dev/null +++ b/ffmpeg/libavcodec/yop.c @@ -0,0 +1,257 @@ +/* + * Psygnosis YOP decoder + * + * Copyright (C) 2010 Mohamed Naufal Basheer + * derived from the code by + * Copyright (C) 2009 Thomas P. Higdon + * + * 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 "libavutil/intreadwrite.h" +#include "libavutil/imgutils.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "internal.h" + +typedef struct YopDecContext { + AVCodecContext *avctx; + + int num_pal_colors; + int first_color[2]; + int frame_data_length; + + uint8_t *low_nibble; + uint8_t *srcptr; + uint8_t *src_end; + uint8_t *dstptr; + uint8_t *dstbuf; +} YopDecContext; + +// These tables are taken directly from: +// http://wiki.multimedia.cx/index.php?title=Psygnosis_YOP + +/** + * Lookup table for painting macroblocks. Bytes 0-2 of each entry contain + * the macroblock positions to be painted (taken as (0, B0, B1, B2)). + * Byte 3 contains the number of bytes consumed on the input, + * equal to max(bytes 0-2) + 1. + */ +static const uint8_t paint_lut[15][4] = + {{1, 2, 3, 4}, {1, 2, 0, 3}, + {1, 2, 1, 3}, {1, 2, 2, 3}, + {1, 0, 2, 3}, {1, 0, 0, 2}, + {1, 0, 1, 2}, {1, 1, 2, 3}, + {0, 1, 2, 3}, {0, 1, 0, 2}, + {1, 1, 0, 2}, {0, 1, 1, 2}, + {0, 0, 1, 2}, {0, 0, 0, 1}, + {1, 1, 1, 2}, + }; + +/** + * Lookup table for copying macroblocks. Each entry contains the respective + * x and y pixel offset for the copy source. + */ +static const int8_t motion_vector[16][2] = + {{-4, -4}, {-2, -4}, + { 0, -4}, { 2, -4}, + {-4, -2}, {-4, 0}, + {-3, -3}, {-1, -3}, + { 1, -3}, { 3, -3}, + {-3, -1}, {-2, -2}, + { 0, -2}, { 2, -2}, + { 4, -2}, {-2, 0}, + }; + +static av_cold int yop_decode_init(AVCodecContext *avctx) +{ + YopDecContext *s = avctx->priv_data; + s->avctx = avctx; + + if (avctx->width & 1 || avctx->height & 1 || + av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0) { + av_log(avctx, AV_LOG_ERROR, "YOP has invalid dimensions\n"); + return AVERROR_INVALIDDATA; + } + + if (avctx->extradata_size < 3) { + av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata.\n"); + return AVERROR_INVALIDDATA; + } + + avctx->pix_fmt = AV_PIX_FMT_PAL8; + + s->num_pal_colors = avctx->extradata[0]; + s->first_color[0] = avctx->extradata[1]; + s->first_color[1] = avctx->extradata[2]; + + if (s->num_pal_colors + s->first_color[0] > 256 || + s->num_pal_colors + s->first_color[1] > 256) { + av_log(avctx, AV_LOG_ERROR, + "Palette parameters invalid, header probably corrupt\n"); + return AVERROR_INVALIDDATA; + } + + return 0; +} + +/** + * Paint a macroblock using the pattern in paint_lut. + * @param s codec context + * @param tag the tag that was in the nibble + */ +static int yop_paint_block(YopDecContext *s, int linesize, int tag) +{ + if (s->src_end - s->srcptr < paint_lut[tag][3]) { + av_log(s->avctx, AV_LOG_ERROR, "Packet too small.\n"); + return AVERROR_INVALIDDATA; + } + + s->dstptr[0] = s->srcptr[0]; + s->dstptr[1] = s->srcptr[paint_lut[tag][0]]; + s->dstptr[linesize] = s->srcptr[paint_lut[tag][1]]; + s->dstptr[linesize + 1] = s->srcptr[paint_lut[tag][2]]; + + // The number of src bytes consumed is in the last part of the lut entry. + s->srcptr += paint_lut[tag][3]; + return 0; +} + +/** + * Copy a previously painted macroblock to the current_block. + * @param copy_tag the tag that was in the nibble + */ +static int yop_copy_previous_block(YopDecContext *s, int linesize, int copy_tag) +{ + uint8_t *bufptr; + + // Calculate position for the copy source + bufptr = s->dstptr + motion_vector[copy_tag][0] + + linesize * motion_vector[copy_tag][1]; + if (bufptr < s->dstbuf) { + av_log(s->avctx, AV_LOG_ERROR, "File probably corrupt\n"); + return AVERROR_INVALIDDATA; + } + + s->dstptr[0] = bufptr[0]; + s->dstptr[1] = bufptr[1]; + s->dstptr[linesize] = bufptr[linesize]; + s->dstptr[linesize + 1] = bufptr[linesize + 1]; + + return 0; +} + +/** + * Return the next nibble in sequence, consuming a new byte on the input + * only if necessary. + */ +static uint8_t yop_get_next_nibble(YopDecContext *s) +{ + int ret; + + if (s->low_nibble) { + ret = *s->low_nibble & 0xf; + s->low_nibble = NULL; + }else { + s->low_nibble = s->srcptr++; + ret = *s->low_nibble >> 4; + } + return ret; +} + +static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + YopDecContext *s = avctx->priv_data; + AVFrame *frame = data; + int tag, firstcolor, is_odd_frame; + int ret, i, x, y; + uint32_t *palette; + + if (avpkt->size < 4 + 3 * s->num_pal_colors) { + av_log(avctx, AV_LOG_ERROR, "Packet too small.\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (!avctx->frame_number) + memset(frame->data[1], 0, AVPALETTE_SIZE); + + s->dstbuf = frame->data[0]; + s->dstptr = frame->data[0]; + s->srcptr = avpkt->data + 4; + s->src_end = avpkt->data + avpkt->size; + s->low_nibble = NULL; + + is_odd_frame = avpkt->data[0]; + if(is_odd_frame>1){ + av_log(avctx, AV_LOG_ERROR, "frame is too odd %d\n", is_odd_frame); + return AVERROR_INVALIDDATA; + } + firstcolor = s->first_color[is_odd_frame]; + palette = (uint32_t *)frame->data[1]; + + for (i = 0; i < s->num_pal_colors; i++, s->srcptr += 3) { + palette[i + firstcolor] = (s->srcptr[0] << 18) | + (s->srcptr[1] << 10) | + (s->srcptr[2] << 2); + palette[i + firstcolor] |= 0xFFU << 24 | + (palette[i + firstcolor] >> 6) & 0x30303; + } + + frame->palette_has_changed = 1; + + for (y = 0; y < avctx->height; y += 2) { + for (x = 0; x < avctx->width; x += 2) { + if (s->srcptr - avpkt->data >= avpkt->size) { + av_log(avctx, AV_LOG_ERROR, "Packet too small.\n"); + return AVERROR_INVALIDDATA; + } + + tag = yop_get_next_nibble(s); + + if (tag != 0xf) { + ret = yop_paint_block(s, frame->linesize[0], tag); + if (ret < 0) + return ret; + } else { + tag = yop_get_next_nibble(s); + ret = yop_copy_previous_block(s, frame->linesize[0], tag); + if (ret < 0) + return ret; + } + s->dstptr += 2; + } + s->dstptr += 2*frame->linesize[0] - x; + } + + *got_frame = 1; + return avpkt->size; +} + +AVCodec ff_yop_decoder = { + .name = "yop", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_YOP, + .priv_data_size = sizeof(YopDecContext), + .init = yop_decode_init, + .decode = yop_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Psygnosis YOP Video"), +}; diff --git a/ffmpeg/libavcodec/yuv4dec.c b/ffmpeg/libavcodec/yuv4dec.c new file mode 100644 index 0000000..6965f39 --- /dev/null +++ b/ffmpeg/libavcodec/yuv4dec.c @@ -0,0 +1,91 @@ +/* + * libquicktime yuv4 decoder + * + * Copyright (c) 2011 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int yuv4_decode_init(AVCodecContext *avctx) +{ + avctx->pix_fmt = AV_PIX_FMT_YUV420P; + + return 0; +} + +static int yuv4_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + AVFrame *pic = data; + const uint8_t *src = avpkt->data; + uint8_t *y, *u, *v; + int i, j, ret; + + if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n"); + return AVERROR(EINVAL); + } + + if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) + return ret; + + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + + y = pic->data[0]; + u = pic->data[1]; + v = pic->data[2]; + + for (i = 0; i < (avctx->height + 1) >> 1; i++) { + for (j = 0; j < (avctx->width + 1) >> 1; j++) { + u[j] = *src++ ^ 0x80; + v[j] = *src++ ^ 0x80; + y[ 2 * j ] = *src++; + y[ 2 * j + 1] = *src++; + y[pic->linesize[0] + 2 * j ] = *src++; + y[pic->linesize[0] + 2 * j + 1] = *src++; + } + + y += 2 * pic->linesize[0]; + u += pic->linesize[1]; + v += pic->linesize[2]; + } + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int yuv4_decode_close(AVCodecContext *avctx) +{ + + return 0; +} + +AVCodec ff_yuv4_decoder = { + .name = "yuv4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_YUV4, + .init = yuv4_decode_init, + .decode = yuv4_decode_frame, + .close = yuv4_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), +}; diff --git a/ffmpeg/libavcodec/yuv4enc.c b/ffmpeg/libavcodec/yuv4enc.c new file mode 100644 index 0000000..6e2f9bc --- /dev/null +++ b/ffmpeg/libavcodec/yuv4enc.c @@ -0,0 +1,91 @@ +/* + * libquicktime yuv4 encoder + * + * Copyright (c) 2011 Carl Eugen Hoyos + * + * 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 "avcodec.h" +#include "internal.h" + +static av_cold int yuv4_encode_init(AVCodecContext *avctx) +{ + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int yuv4_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) +{ + uint8_t *dst; + uint8_t *y, *u, *v; + int i, j, ret; + + if ((ret = ff_alloc_packet2(avctx, pkt, 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1))) < 0) + return ret; + dst = pkt->data; + + avctx->coded_frame->key_frame = 1; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; + + y = pic->data[0]; + u = pic->data[1]; + v = pic->data[2]; + + for (i = 0; i < avctx->height + 1 >> 1; i++) { + for (j = 0; j < avctx->width + 1 >> 1; j++) { + *dst++ = u[j] ^ 0x80; + *dst++ = v[j] ^ 0x80; + *dst++ = y[ 2 * j ]; + *dst++ = y[ 2 * j + 1]; + *dst++ = y[pic->linesize[0] + 2 * j ]; + *dst++ = y[pic->linesize[0] + 2 * j + 1]; + } + y += 2 * pic->linesize[0]; + u += pic->linesize[1]; + v += pic->linesize[2]; + } + + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; +} + +static av_cold int yuv4_encode_close(AVCodecContext *avctx) +{ + av_freep(&avctx->coded_frame); + + return 0; +} + +AVCodec ff_yuv4_encoder = { + .name = "yuv4", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_YUV4, + .init = yuv4_encode_init, + .encode2 = yuv4_encode_frame, + .close = yuv4_encode_close, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), +}; diff --git a/ffmpeg/libavcodec/zerocodec.c b/ffmpeg/libavcodec/zerocodec.c new file mode 100644 index 0000000..4a23b67 --- /dev/null +++ b/ffmpeg/libavcodec/zerocodec.c @@ -0,0 +1,146 @@ +/* + * ZeroCodec Decoder + * + * Copyright (c) 2012, Derek Buitenhuis + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "avcodec.h" +#include "internal.h" +#include "libavutil/common.h" + +typedef struct { + AVFrame previous_frame; + z_stream zstream; +} ZeroCodecContext; + +static int zerocodec_decode_frame(AVCodecContext *avctx, void *data, + int *got_frame, AVPacket *avpkt) +{ + ZeroCodecContext *zc = avctx->priv_data; + AVFrame *pic = data; + AVFrame *prev_pic = &zc->previous_frame; + z_stream *zstream = &zc->zstream; + uint8_t *prev = prev_pic->data[0]; + uint8_t *dst; + int i, j, zret, ret; + + if (avpkt->flags & AV_PKT_FLAG_KEY) { + pic->key_frame = 1; + pic->pict_type = AV_PICTURE_TYPE_I; + } else { + if (!prev) { + av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n"); + return AVERROR_INVALIDDATA; + } + + prev += (avctx->height - 1) * prev_pic->linesize[0]; + + pic->key_frame = 0; + pic->pict_type = AV_PICTURE_TYPE_P; + } + + zret = inflateReset(zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not reset inflate: %d.\n", zret); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, pic, AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + + zstream->next_in = avpkt->data; + zstream->avail_in = avpkt->size; + + dst = pic->data[0] + (avctx->height - 1) * pic->linesize[0]; + + /** + * ZeroCodec has very simple interframe compression. If a value + * is the same as the previous frame, set it to 0. + */ + + for (i = 0; i < avctx->height; i++) { + zstream->next_out = dst; + zstream->avail_out = avctx->width << 1; + + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK && zret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, + "Inflate failed with return code: %d.\n", zret); + return AVERROR_INVALIDDATA; + } + + if (!(avpkt->flags & AV_PKT_FLAG_KEY)) + for (j = 0; j < avctx->width << 1; j++) + dst[j] += prev[j] & -!dst[j]; + + prev -= prev_pic->linesize[0]; + dst -= pic->linesize[0]; + } + + av_frame_unref(&zc->previous_frame); + if ((ret = av_frame_ref(&zc->previous_frame, pic)) < 0) + return ret; + + *got_frame = 1; + + return avpkt->size; +} + +static av_cold int zerocodec_decode_close(AVCodecContext *avctx) +{ + ZeroCodecContext *zc = avctx->priv_data; + + av_frame_unref(&zc->previous_frame); + + inflateEnd(&zc->zstream); + + return 0; +} + +static av_cold int zerocodec_decode_init(AVCodecContext *avctx) +{ + ZeroCodecContext *zc = avctx->priv_data; + z_stream *zstream = &zc->zstream; + int zret; + + avctx->pix_fmt = AV_PIX_FMT_UYVY422; + avctx->bits_per_raw_sample = 8; + + zstream->zalloc = Z_NULL; + zstream->zfree = Z_NULL; + zstream->opaque = Z_NULL; + + zret = inflateInit(zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret); + return AVERROR(ENOMEM); + } + + return 0; +} + +AVCodec ff_zerocodec_decoder = { + .type = AVMEDIA_TYPE_VIDEO, + .name = "zerocodec", + .id = AV_CODEC_ID_ZEROCODEC, + .priv_data_size = sizeof(ZeroCodecContext), + .init = zerocodec_decode_init, + .decode = zerocodec_decode_frame, + .close = zerocodec_decode_close, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"), +}; diff --git a/ffmpeg/libavcodec/zmbv.c b/ffmpeg/libavcodec/zmbv.c new file mode 100644 index 0000000..7f3b326 --- /dev/null +++ b/ffmpeg/libavcodec/zmbv.c @@ -0,0 +1,635 @@ +/* + * Zip Motion Blocks Video (ZMBV) decoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Zip Motion Blocks Video decoder + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +#include + +#define ZMBV_KEYFRAME 1 +#define ZMBV_DELTAPAL 2 + +enum ZmbvFormat { + ZMBV_FMT_NONE = 0, + ZMBV_FMT_1BPP = 1, + ZMBV_FMT_2BPP = 2, + ZMBV_FMT_4BPP = 3, + ZMBV_FMT_8BPP = 4, + ZMBV_FMT_15BPP = 5, + ZMBV_FMT_16BPP = 6, + ZMBV_FMT_24BPP = 7, + ZMBV_FMT_32BPP = 8 +}; + +/* + * Decoder context + */ +typedef struct ZmbvContext { + AVCodecContext *avctx; + + int bpp; + unsigned int decomp_size; + uint8_t* decomp_buf; + uint8_t pal[768]; + uint8_t *prev, *cur; + int width, height; + int fmt; + int comp; + int flags; + int stride; + int bw, bh, bx, by; + int decomp_len; + z_stream zstream; + int (*decode_intra)(struct ZmbvContext *c); + int (*decode_xor)(struct ZmbvContext *c); +} ZmbvContext; + +/** + * Decode XOR'ed frame - 8bpp version + */ + +static int zmbv_decode_xor_8(ZmbvContext *c) +{ + uint8_t *src = c->decomp_buf; + uint8_t *output, *prev; + int8_t *mvec; + int x, y; + int d, dx, dy, bw2, bh2; + int block; + int i, j; + int mx, my; + + output = c->cur; + prev = c->prev; + + if (c->flags & ZMBV_DELTAPAL) { + for (i = 0; i < 768; i++) + c->pal[i] ^= *src++; + } + + mvec = (int8_t*)src; + src += ((c->bx * c->by * 2 + 3) & ~3); + + block = 0; + for (y = 0; y < c->height; y += c->bh) { + bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); + for (x = 0; x < c->width; x += c->bw) { + uint8_t *out, *tprev; + + d = mvec[block] & 1; + dx = mvec[block] >> 1; + dy = mvec[block + 1] >> 1; + block += 2; + + bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); + + /* copy block - motion vectors out of bounds are used to zero blocks */ + out = output + x; + tprev = prev + x + dx + dy * c->width; + mx = x + dx; + my = y + dy; + for (j = 0; j < bh2; j++) { + if (my + j < 0 || my + j >= c->height) { + memset(out, 0, bw2); + } else { + for (i = 0; i < bw2; i++) { + if (mx + i < 0 || mx + i >= c->width) + out[i] = 0; + else + out[i] = tprev[i]; + } + } + out += c->width; + tprev += c->width; + } + + if (d) { /* apply XOR'ed difference */ + out = output + x; + for (j = 0; j < bh2; j++) { + for (i = 0; i < bw2; i++) + out[i] ^= *src++; + out += c->width; + } + } + } + output += c->width * c->bh; + prev += c->width * c->bh; + } + if (src - c->decomp_buf != c->decomp_len) + av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", + src-c->decomp_buf, c->decomp_len); + return 0; +} + +/** + * Decode XOR'ed frame - 15bpp and 16bpp version + */ + +static int zmbv_decode_xor_16(ZmbvContext *c) +{ + uint8_t *src = c->decomp_buf; + uint16_t *output, *prev; + int8_t *mvec; + int x, y; + int d, dx, dy, bw2, bh2; + int block; + int i, j; + int mx, my; + + output = (uint16_t*)c->cur; + prev = (uint16_t*)c->prev; + + mvec = (int8_t*)src; + src += ((c->bx * c->by * 2 + 3) & ~3); + + block = 0; + for (y = 0; y < c->height; y += c->bh) { + bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); + for (x = 0; x < c->width; x += c->bw) { + uint16_t *out, *tprev; + + d = mvec[block] & 1; + dx = mvec[block] >> 1; + dy = mvec[block + 1] >> 1; + block += 2; + + bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); + + /* copy block - motion vectors out of bounds are used to zero blocks */ + out = output + x; + tprev = prev + x + dx + dy * c->width; + mx = x + dx; + my = y + dy; + for (j = 0; j < bh2; j++) { + if (my + j < 0 || my + j >= c->height) { + memset(out, 0, bw2 * 2); + } else { + for (i = 0; i < bw2; i++) { + if (mx + i < 0 || mx + i >= c->width) + out[i] = 0; + else + out[i] = tprev[i]; + } + } + out += c->width; + tprev += c->width; + } + + if (d) { /* apply XOR'ed difference */ + out = output + x; + for (j = 0; j < bh2; j++){ + for (i = 0; i < bw2; i++) { + out[i] ^= *((uint16_t*)src); + src += 2; + } + out += c->width; + } + } + } + output += c->width * c->bh; + prev += c->width * c->bh; + } + if (src - c->decomp_buf != c->decomp_len) + av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", + src-c->decomp_buf, c->decomp_len); + return 0; +} + +#ifdef ZMBV_ENABLE_24BPP +/** + * Decode XOR'ed frame - 24bpp version + */ + +static int zmbv_decode_xor_24(ZmbvContext *c) +{ + uint8_t *src = c->decomp_buf; + uint8_t *output, *prev; + int8_t *mvec; + int x, y; + int d, dx, dy, bw2, bh2; + int block; + int i, j; + int mx, my; + int stride; + + output = c->cur; + prev = c->prev; + + stride = c->width * 3; + mvec = (int8_t*)src; + src += ((c->bx * c->by * 2 + 3) & ~3); + + block = 0; + for (y = 0; y < c->height; y += c->bh) { + bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); + for (x = 0; x < c->width; x += c->bw) { + uint8_t *out, *tprev; + + d = mvec[block] & 1; + dx = mvec[block] >> 1; + dy = mvec[block + 1] >> 1; + block += 2; + + bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); + + /* copy block - motion vectors out of bounds are used to zero blocks */ + out = output + x * 3; + tprev = prev + (x + dx) * 3 + dy * stride; + mx = x + dx; + my = y + dy; + for (j = 0; j < bh2; j++) { + if (my + j < 0 || my + j >= c->height) { + memset(out, 0, bw2 * 3); + } else { + for (i = 0; i < bw2; i++){ + if (mx + i < 0 || mx + i >= c->width) { + out[i * 3 + 0] = 0; + out[i * 3 + 1] = 0; + out[i * 3 + 2] = 0; + } else { + out[i * 3 + 0] = tprev[i * 3 + 0]; + out[i * 3 + 1] = tprev[i * 3 + 1]; + out[i * 3 + 2] = tprev[i * 3 + 2]; + } + } + } + out += stride; + tprev += stride; + } + + if (d) { /* apply XOR'ed difference */ + out = output + x * 3; + for (j = 0; j < bh2; j++) { + for (i = 0; i < bw2; i++) { + out[i * 3 + 0] ^= *src++; + out[i * 3 + 1] ^= *src++; + out[i * 3 + 2] ^= *src++; + } + out += stride; + } + } + } + output += stride * c->bh; + prev += stride * c->bh; + } + if (src - c->decomp_buf != c->decomp_len) + av_log(c->avctx, AV_LOG_ERROR, "Used %i of %i bytes\n", + src-c->decomp_buf, c->decomp_len); + return 0; +} +#endif //ZMBV_ENABLE_24BPP + +/** + * Decode XOR'ed frame - 32bpp version + */ + +static int zmbv_decode_xor_32(ZmbvContext *c) +{ + uint8_t *src = c->decomp_buf; + uint32_t *output, *prev; + int8_t *mvec; + int x, y; + int d, dx, dy, bw2, bh2; + int block; + int i, j; + int mx, my; + + output = (uint32_t*)c->cur; + prev = (uint32_t*)c->prev; + + mvec = (int8_t*)src; + src += ((c->bx * c->by * 2 + 3) & ~3); + + block = 0; + for (y = 0; y < c->height; y += c->bh) { + bh2 = ((c->height - y) > c->bh) ? c->bh : (c->height - y); + for (x = 0; x < c->width; x += c->bw) { + uint32_t *out, *tprev; + + d = mvec[block] & 1; + dx = mvec[block] >> 1; + dy = mvec[block + 1] >> 1; + block += 2; + + bw2 = ((c->width - x) > c->bw) ? c->bw : (c->width - x); + + /* copy block - motion vectors out of bounds are used to zero blocks */ + out = output + x; + tprev = prev + x + dx + dy * c->width; + mx = x + dx; + my = y + dy; + for (j = 0; j < bh2; j++) { + if (my + j < 0 || my + j >= c->height) { + memset(out, 0, bw2 * 4); + } else { + for (i = 0; i < bw2; i++){ + if (mx + i < 0 || mx + i >= c->width) + out[i] = 0; + else + out[i] = tprev[i]; + } + } + out += c->width; + tprev += c->width; + } + + if (d) { /* apply XOR'ed difference */ + out = output + x; + for (j = 0; j < bh2; j++){ + for (i = 0; i < bw2; i++) { + out[i] ^= *((uint32_t *) src); + src += 4; + } + out += c->width; + } + } + } + output += c->width * c->bh; + prev += c->width * c->bh; + } + if (src - c->decomp_buf != c->decomp_len) + av_log(c->avctx, AV_LOG_ERROR, "Used %ti of %i bytes\n", + src-c->decomp_buf, c->decomp_len); + return 0; +} + +/** + * Decode intraframe + */ +static int zmbv_decode_intra(ZmbvContext *c) +{ + uint8_t *src = c->decomp_buf; + + /* make the palette available on the way out */ + if (c->fmt == ZMBV_FMT_8BPP) { + memcpy(c->pal, src, 768); + src += 768; + } + + memcpy(c->cur, src, c->width * c->height * (c->bpp / 8)); + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +{ + AVFrame *frame = data; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + ZmbvContext * const c = avctx->priv_data; + int zret = Z_OK; // Zlib return code + int len = buf_size; + int hi_ver, lo_ver, ret; + + /* parse header */ + c->flags = buf[0]; + buf++; len--; + if (c->flags & ZMBV_KEYFRAME) { + void *decode_intra = NULL; + c->decode_intra= NULL; + hi_ver = buf[0]; + lo_ver = buf[1]; + c->comp = buf[2]; + c->fmt = buf[3]; + c->bw = buf[4]; + c->bh = buf[5]; + c->decode_intra = NULL; + c->decode_xor = NULL; + + buf += 6; + len -= 6; + av_log(avctx, AV_LOG_DEBUG, + "Flags=%X ver=%i.%i comp=%i fmt=%i blk=%ix%i\n", + c->flags,hi_ver,lo_ver,c->comp,c->fmt,c->bw,c->bh); + if (hi_ver != 0 || lo_ver != 1) { + avpriv_request_sample(avctx, "Version %i.%i", hi_ver, lo_ver); + return AVERROR_PATCHWELCOME; + } + if (c->bw == 0 || c->bh == 0) { + avpriv_request_sample(avctx, "Block size %ix%i", c->bw, c->bh); + return AVERROR_PATCHWELCOME; + } + if (c->comp != 0 && c->comp != 1) { + avpriv_request_sample(avctx, "Compression type %i", c->comp); + return AVERROR_PATCHWELCOME; + } + + switch (c->fmt) { + case ZMBV_FMT_8BPP: + c->bpp = 8; + decode_intra = zmbv_decode_intra; + c->decode_xor = zmbv_decode_xor_8; + avctx->pix_fmt = AV_PIX_FMT_PAL8; + c->stride = c->width; + break; + case ZMBV_FMT_15BPP: + case ZMBV_FMT_16BPP: + c->bpp = 16; + decode_intra = zmbv_decode_intra; + c->decode_xor = zmbv_decode_xor_16; + if (c->fmt == ZMBV_FMT_15BPP) + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + else + avctx->pix_fmt = AV_PIX_FMT_RGB565LE; + c->stride = c->width * 2; + break; +#ifdef ZMBV_ENABLE_24BPP + case ZMBV_FMT_24BPP: + c->bpp = 24; + decode_intra = zmbv_decode_intra; + c->decode_xor = zmbv_decode_xor_24; + avctx->pix_fmt = AV_PIX_FMT_RGB24; + c->stride = c->width * 3; + break; +#endif //ZMBV_ENABLE_24BPP + case ZMBV_FMT_32BPP: + c->bpp = 32; + decode_intra = zmbv_decode_intra; + c->decode_xor = zmbv_decode_xor_32; + avctx->pix_fmt = AV_PIX_FMT_BGR0; + c->stride = c->width * 4; + break; + default: + c->decode_xor = NULL; + avpriv_request_sample(avctx, "Format %i", c->fmt); + return AVERROR_PATCHWELCOME; + } + + zret = inflateReset(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); + return AVERROR_UNKNOWN; + } + + c->cur = av_realloc_f(c->cur, avctx->width * avctx->height, (c->bpp / 8)); + c->prev = av_realloc_f(c->prev, avctx->width * avctx->height, (c->bpp / 8)); + c->bx = (c->width + c->bw - 1) / c->bw; + c->by = (c->height+ c->bh - 1) / c->bh; + if (!c->cur || !c->prev) + return -1; + memset(c->cur, 0, avctx->width * avctx->height * (c->bpp / 8)); + memset(c->prev, 0, avctx->width * avctx->height * (c->bpp / 8)); + c->decode_intra= decode_intra; + } + + if (c->decode_intra == NULL) { + av_log(avctx, AV_LOG_ERROR, "Error! Got no format or no keyframe!\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + + if (c->comp == 0) { //Uncompressed data + if (c->decomp_size < len) { + av_log(avctx, AV_LOG_ERROR, "decomp buffer too small\n"); + return AVERROR_INVALIDDATA; + } + memcpy(c->decomp_buf, buf, len); + } else { // ZLIB-compressed data + c->zstream.total_in = c->zstream.total_out = 0; + c->zstream.next_in = (uint8_t*)buf; + c->zstream.avail_in = len; + c->zstream.next_out = c->decomp_buf; + c->zstream.avail_out = c->decomp_size; + zret = inflate(&c->zstream, Z_SYNC_FLUSH); + if (zret != Z_OK && zret != Z_STREAM_END) { + av_log(avctx, AV_LOG_ERROR, "inflate error %d\n", zret); + return AVERROR_INVALIDDATA; + } + c->decomp_len = c->zstream.total_out; + } + if (c->flags & ZMBV_KEYFRAME) { + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + c->decode_intra(c); + } else { + frame->key_frame = 0; + frame->pict_type = AV_PICTURE_TYPE_P; + if (c->decomp_len) + c->decode_xor(c); + } + + /* update frames */ + { + uint8_t *out, *src; + int j; + + out = frame->data[0]; + src = c->cur; + switch (c->fmt) { + case ZMBV_FMT_8BPP: + for (j = 0; j < 256; j++) + AV_WN32(&frame->data[1][j * 4], 0xFFU << 24 | AV_RB24(&c->pal[j * 3])); + case ZMBV_FMT_15BPP: + case ZMBV_FMT_16BPP: +#ifdef ZMBV_ENABLE_24BPP + case ZMBV_FMT_24BPP: +#endif + case ZMBV_FMT_32BPP: + for (j = 0; j < c->height; j++) { + memcpy(out, src, c->stride); + src += c->stride; + out += frame->linesize[0]; + } + break; + default: + av_log(avctx, AV_LOG_ERROR, "Cannot handle format %i\n", c->fmt); + } + FFSWAP(uint8_t *, c->cur, c->prev); + } + *got_frame = 1; + + /* always report that the buffer was completely consumed */ + return buf_size; +} + +static av_cold int decode_init(AVCodecContext *avctx) +{ + ZmbvContext * const c = avctx->priv_data; + int zret; // Zlib return code + + c->avctx = avctx; + + c->width = avctx->width; + c->height = avctx->height; + + c->bpp = avctx->bits_per_coded_sample; + + // Needed if zlib unused or init aborted before inflateInit + memset(&c->zstream, 0, sizeof(z_stream)); + + c->decomp_size = (avctx->width + 255) * 4 * (avctx->height + 64); + + /* Allocate decompression buffer */ + if (c->decomp_size) { + if ((c->decomp_buf = av_mallocz(c->decomp_size)) == NULL) { + av_log(avctx, AV_LOG_ERROR, + "Can't allocate decompression buffer.\n"); + return AVERROR(ENOMEM); + } + } + + c->zstream.zalloc = Z_NULL; + c->zstream.zfree = Z_NULL; + c->zstream.opaque = Z_NULL; + zret = inflateInit(&c->zstream); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return AVERROR_UNKNOWN; + } + + return 0; +} + +static av_cold int decode_end(AVCodecContext *avctx) +{ + ZmbvContext * const c = avctx->priv_data; + + av_freep(&c->decomp_buf); + + inflateEnd(&c->zstream); + av_freep(&c->cur); + av_freep(&c->prev); + + return 0; +} + +AVCodec ff_zmbv_decoder = { + .name = "zmbv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ZMBV, + .priv_data_size = sizeof(ZmbvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), +}; diff --git a/ffmpeg/libavcodec/zmbvenc.c b/ffmpeg/libavcodec/zmbvenc.c new file mode 100644 index 0000000..fb782a4 --- /dev/null +++ b/ffmpeg/libavcodec/zmbvenc.c @@ -0,0 +1,348 @@ +/* + * Zip Motion Blocks Video (ZMBV) encoder + * Copyright (c) 2006 Konstantin Shishkov + * + * 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 + */ + +/** + * @file + * Zip Motion Blocks Video encoder + */ + +#include +#include + +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "avcodec.h" +#include "internal.h" + +#include + +#define ZMBV_KEYFRAME 1 +#define ZMBV_DELTAPAL 2 + +#define ZMBV_BLOCK 16 + +/** + * Encoder context + */ +typedef struct ZmbvEncContext { + AVCodecContext *avctx; + AVFrame pic; + + int range; + uint8_t *comp_buf, *work_buf; + uint8_t pal[768]; + uint32_t pal2[256]; //for quick comparisons + uint8_t *prev; + int pstride; + int comp_size; + int keyint, curfrm; + z_stream zstream; +} ZmbvEncContext; + +static int score_tab[256]; + +/** Block comparing function + * XXX should be optimized and moved to DSPContext + * TODO handle out of edge ME + */ +static inline int block_cmp(uint8_t *src, int stride, uint8_t *src2, int stride2, + int bw, int bh, int *xored) +{ + int sum = 0; + int i, j; + uint8_t histogram[256] = {0}; + + *xored = 0; + for(j = 0; j < bh; j++){ + for(i = 0; i < bw; i++){ + int t = src[i] ^ src2[i]; + histogram[t]++; + *xored |= t; + } + src += stride; + src2 += stride2; + } + + for(i = 1; i < 256; i++) + sum += score_tab[histogram[i]]; + + return sum; +} + +/** Motion estimation function + * TODO make better ME decisions + */ +static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev, + int pstride, int x, int y, int *mx, int *my, int *xored) +{ + int dx, dy, tx, ty, tv, bv, bw, bh; + + *mx = *my = 0; + bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x); + bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y); + bv = block_cmp(src, sstride, prev, pstride, bw, bh, xored); + if(!bv) return 0; + for(ty = FFMAX(y - c->range, 0); ty < FFMIN(y + c->range, c->avctx->height - bh); ty++){ + for(tx = FFMAX(x - c->range, 0); tx < FFMIN(x + c->range, c->avctx->width - bw); tx++){ + if(tx == x && ty == y) continue; // we already tested this block + dx = tx - x; + dy = ty - y; + tv = block_cmp(src, sstride, prev + dx + dy*pstride, pstride, bw, bh, xored); + if(tv < bv){ + bv = tv; + *mx = dx; + *my = dy; + if(!bv) return 0; + } + } + } + return bv; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + ZmbvEncContext * const c = avctx->priv_data; + AVFrame * const p = &c->pic; + uint8_t *src, *prev, *buf; + uint32_t *palptr; + int keyframe, chpal; + int fl; + int work_size = 0, pkt_size; + int bw, bh; + int i, j, ret; + + keyframe = !c->curfrm; + c->curfrm++; + if(c->curfrm == c->keyint) + c->curfrm = 0; + *p = *pict; + p->pict_type= keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + p->key_frame= keyframe; + chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024); + + palptr = (uint32_t*)p->data[1]; + src = p->data[0]; + prev = c->prev; + if(chpal){ + uint8_t tpal[3]; + for(i = 0; i < 256; i++){ + AV_WB24(tpal, palptr[i]); + c->work_buf[work_size++] = tpal[0] ^ c->pal[i * 3 + 0]; + c->work_buf[work_size++] = tpal[1] ^ c->pal[i * 3 + 1]; + c->work_buf[work_size++] = tpal[2] ^ c->pal[i * 3 + 2]; + c->pal[i * 3 + 0] = tpal[0]; + c->pal[i * 3 + 1] = tpal[1]; + c->pal[i * 3 + 2] = tpal[2]; + } + memcpy(c->pal2, p->data[1], 1024); + } + if(keyframe){ + for(i = 0; i < 256; i++){ + AV_WB24(c->pal+(i*3), palptr[i]); + } + memcpy(c->work_buf, c->pal, 768); + memcpy(c->pal2, p->data[1], 1024); + work_size = 768; + for(i = 0; i < avctx->height; i++){ + memcpy(c->work_buf + work_size, src, avctx->width); + src += p->linesize[0]; + work_size += avctx->width; + } + }else{ + int x, y, bh2, bw2, xored; + uint8_t *tsrc, *tprev; + uint8_t *mv; + int mx, my; + + bw = (avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK; + bh = (avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK; + mv = c->work_buf + work_size; + memset(c->work_buf + work_size, 0, (bw * bh * 2 + 3) & ~3); + work_size += (bw * bh * 2 + 3) & ~3; + /* for now just XOR'ing */ + for(y = 0; y < avctx->height; y += ZMBV_BLOCK) { + bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK); + for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) { + bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK); + + tsrc = src + x; + tprev = prev + x; + + zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored); + mv[0] = (mx << 1) | !!xored; + mv[1] = my << 1; + tprev += mx + my * c->pstride; + if(xored){ + for(j = 0; j < bh2; j++){ + for(i = 0; i < bw2; i++) + c->work_buf[work_size++] = tsrc[i] ^ tprev[i]; + tsrc += p->linesize[0]; + tprev += c->pstride; + } + } + } + src += p->linesize[0] * ZMBV_BLOCK; + prev += c->pstride * ZMBV_BLOCK; + } + } + /* save the previous frame */ + src = p->data[0]; + prev = c->prev; + for(i = 0; i < avctx->height; i++){ + memcpy(prev, src, avctx->width); + prev += c->pstride; + src += p->linesize[0]; + } + + if (keyframe) + deflateReset(&c->zstream); + + c->zstream.next_in = c->work_buf; + c->zstream.avail_in = work_size; + c->zstream.total_in = 0; + + c->zstream.next_out = c->comp_buf; + c->zstream.avail_out = c->comp_size; + c->zstream.total_out = 0; + if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){ + av_log(avctx, AV_LOG_ERROR, "Error compressing data\n"); + return -1; + } + + pkt_size = c->zstream.total_out + 1 + 6*keyframe; + if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size)) < 0) + return ret; + buf = pkt->data; + + fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); + *buf++ = fl; + if (keyframe) { + *buf++ = 0; // hi ver + *buf++ = 1; // lo ver + *buf++ = 1; // comp + *buf++ = 4; // format - 8bpp + *buf++ = ZMBV_BLOCK; // block width + *buf++ = ZMBV_BLOCK; // block height + } + memcpy(buf, c->comp_buf, c->zstream.total_out); + + pkt->flags |= AV_PKT_FLAG_KEY*keyframe; + *got_packet = 1; + + return 0; +} + + +/** + * Init zmbv encoder + */ +static av_cold int encode_init(AVCodecContext *avctx) +{ + ZmbvEncContext * const c = avctx->priv_data; + int zret; // Zlib return code + int i; + int lvl = 9; + + for(i=1; i<256; i++) + score_tab[i]= -i * log(i/(double)(ZMBV_BLOCK*ZMBV_BLOCK)) * (256/M_LN2); + + c->avctx = avctx; + + c->curfrm = 0; + c->keyint = avctx->keyint_min; + c->range = 8; + if(avctx->me_range > 0) + c->range = FFMIN(avctx->me_range, 127); + + if(avctx->compression_level >= 0) + lvl = avctx->compression_level; + if(lvl < 0 || lvl > 9){ + av_log(avctx, AV_LOG_ERROR, "Compression level should be 0-9, not %i\n", lvl); + return AVERROR(EINVAL); + } + + // Needed if zlib unused or init aborted before deflateInit + memset(&c->zstream, 0, sizeof(z_stream)); + c->comp_size = avctx->width * avctx->height + 1024 + + ((avctx->width + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * ((avctx->height + ZMBV_BLOCK - 1) / ZMBV_BLOCK) * 2 + 4; + if ((c->work_buf = av_malloc(c->comp_size)) == NULL) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate work buffer.\n"); + return AVERROR(ENOMEM); + } + /* Conservative upper bound taken from zlib v1.2.1 source via lcl.c */ + c->comp_size = c->comp_size + ((c->comp_size + 7) >> 3) + + ((c->comp_size + 63) >> 6) + 11; + + /* Allocate compression buffer */ + if ((c->comp_buf = av_malloc(c->comp_size)) == NULL) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate compression buffer.\n"); + return AVERROR(ENOMEM); + } + c->pstride = FFALIGN(avctx->width, 16); + if ((c->prev = av_malloc(c->pstride * avctx->height)) == NULL) { + av_log(avctx, AV_LOG_ERROR, "Can't allocate picture.\n"); + return AVERROR(ENOMEM); + } + + c->zstream.zalloc = Z_NULL; + c->zstream.zfree = Z_NULL; + c->zstream.opaque = Z_NULL; + zret = deflateInit(&c->zstream, lvl); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); + return -1; + } + + avctx->coded_frame = &c->pic; + + return 0; +} + + + +/** + * Uninit zmbv encoder + */ +static av_cold int encode_end(AVCodecContext *avctx) +{ + ZmbvEncContext * const c = avctx->priv_data; + + av_freep(&c->comp_buf); + av_freep(&c->work_buf); + + deflateEnd(&c->zstream); + av_freep(&c->prev); + + return 0; +} + +AVCodec ff_zmbv_encoder = { + .name = "zmbv", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ZMBV, + .priv_data_size = sizeof(ZmbvEncContext), + .init = encode_init, + .encode2 = encode_frame, + .close = encode_end, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), +}; -- cgit v1.2.3